summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python/syscall-counts.py
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-09-11 11:29:42 +0800
committerShawn Guo <shawn.guo@freescale.com>2014-09-16 10:09:41 +0800
commitbad3db104f8922df2c84fd7653cfbcbc93cd0cb7 (patch)
tree19bea59e889eefaed55dea1de283508b45093af4 /tools/perf/scripts/python/syscall-counts.py
parent6f11c69d35d5b1db0ec4cfccd0188b00eada3ad3 (diff)
ARM: imx: source gpt per clk from OSC for system timer
On i.MX6Q TO > 1.0, i.MX6DL and i.MX6SX, gpt per clock can be from OSC instead of ipg_per, as ipg_per's rate may be scaled when system enter low bus mode, to keep system timer NOT drift, better to make gpt per clock at fixed rate, here add support for gpt per clock to be from OSC which is at fixed rate always. There are some difference on this implementation of gpt per clock source, see below for details: i.MX6Q TO > 1.0: GPT_CR_CLKSRC, b'101 selects fix clock of OSC / 8 for gpt per clk; i.MX6DL and i.MX6SX: GPT_CR_CLKSRC, b'101 selects OSC for gpt per clk, and we must enable GPT_CR_24MEM to enable OSC clk source for gpt per, GPT_PR_PRESCALER24M is for pre-scaling of this OSC clk, here set it to 8 to make gpt per clk is 3MHz; i.MX6SL: ipg_per can be from OSC directly, so no need to implement this new clk source for gpt per. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Diffstat (limited to 'tools/perf/scripts/python/syscall-counts.py')
0 files changed, 0 insertions, 0 deletions
bus-rbd4
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb-lvstest47
-rw-r--r--Documentation/ABI/testing/sysfs-class-iommu17
-rw-r--r--Documentation/ABI/testing/sysfs-class-iommu-amd-iommu14
-rw-r--r--Documentation/ABI/testing/sysfs-class-iommu-intel-iommu32
-rw-r--r--Documentation/ABI/testing/sysfs-class-leds-gt683r16
-rw-r--r--Documentation/ABI/testing/sysfs-class-mei16
-rw-r--r--Documentation/ABI/testing/sysfs-class-mtd38
-rw-r--r--Documentation/ABI/testing/sysfs-class-net11
-rw-r--r--Documentation/ABI/testing/sysfs-driver-genwqe9
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-lenovo (renamed from Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd)12
-rw-r--r--Documentation/ABI/testing/sysfs-driver-pciback13
-rw-r--r--Documentation/ABI/testing/sysfs-driver-tegra-fuse11
-rw-r--r--Documentation/ABI/testing/sysfs-driver-wacom70
-rw-r--r--Documentation/ABI/testing/sysfs-fs-nilfs2269
-rw-r--r--Documentation/ABI/testing/sysfs-fs-xfs39
-rw-r--r--Documentation/ABI/testing/sysfs-platform-ts55007
-rw-r--r--Documentation/ABI/testing/sysfs-tty16
-rw-r--r--Documentation/DocBook/device-drivers.tmpl12
-rw-r--r--Documentation/DocBook/drm.tmpl91
-rw-r--r--Documentation/DocBook/gadget.tmpl10
-rw-r--r--Documentation/DocBook/media/Makefile2
-rw-r--r--Documentation/DocBook/media/dvb/dvbproperty.xml44
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml408
-rw-r--r--Documentation/DocBook/media/v4l/dev-raw-vbi.xml12
-rw-r--r--Documentation/DocBook/media/v4l/dev-sdr.xml18
-rw-r--r--Documentation/DocBook/media/v4l/dev-sliced-vbi.xml9
-rw-r--r--Documentation/DocBook/media/v4l/io.xml9
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml418
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml44
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml47
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml40
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb12.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt.xml61
-rw-r--r--Documentation/DocBook/media/v4l/selection-api.xml95
-rw-r--r--Documentation/DocBook/media/v4l/v4l2.xml8
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dqevent.xml50
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml51
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml12
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-selection.xml40
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-querycap.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-queryctrl.xml234
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml8
-rw-r--r--Documentation/PCI/MSI-HOWTO.txt2
-rw-r--r--Documentation/RCU/RTFP.txt4
-rw-r--r--Documentation/RCU/rcuref.txt9
-rw-r--r--Documentation/RCU/whatisRCU.txt2
-rw-r--r--Documentation/SubmittingDrivers4
-rw-r--r--Documentation/SubmittingPatches42
-rw-r--r--Documentation/arm/CCN.txt52
-rw-r--r--Documentation/arm/Marvell/README23
-rw-r--r--Documentation/arm/Samsung/Overview.txt11
-rwxr-xr-xDocumentation/arm/Samsung/clksrc-change-registers.awk1
-rw-r--r--Documentation/arm64/booting.txt51
-rw-r--r--Documentation/arm64/memory.txt69
-rw-r--r--Documentation/cgroups/cgroups.txt14
-rw-r--r--Documentation/cgroups/memcg_test.txt160
-rw-r--r--Documentation/cgroups/unified-hierarchy.txt35
-rw-r--r--Documentation/device-mapper/switch.txt12
-rw-r--r--Documentation/devicetree/bindings/arm/adapteva.txt7
-rw-r--r--Documentation/devicetree/bindings/arm/arm-boards6
-rw-r--r--Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt14
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-pmc.txt5
-rw-r--r--Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method36
-rw-r--r--Documentation/devicetree/bindings/arm/brcm-brcmstb.txt95
-rw-r--r--Documentation/devicetree/bindings/arm/ccn.txt21
-rw-r--r--Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp41
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.txt4
-rw-r--r--Documentation/devicetree/bindings/arm/gic-v3.txt79
-rw-r--r--Documentation/devicetree/bindings/arm/gic.txt1
-rw-r--r--Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt11
-rw-r--r--Documentation/devicetree/bindings/arm/marvell,berlin.txt16
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek.txt8
-rw-r--r--Documentation/devicetree/bindings/arm/omap/crossbar.txt36
-rw-r--r--Documentation/devicetree/bindings/arm/omap/omap.txt3
-rw-r--r--Documentation/devicetree/bindings/arm/omap/prcm.txt65
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt25
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/pmu.txt32
-rw-r--r--Documentation/devicetree/bindings/arm/spear-misc.txt9
-rw-r--r--Documentation/devicetree/bindings/arm/tegra.txt2
-rw-r--r--Documentation/devicetree/bindings/arm/xilinx.txt8
-rw-r--r--Documentation/devicetree/bindings/ata/ahci-platform.txt45
-rw-r--r--Documentation/devicetree/bindings/ata/ahci-st.txt31
-rw-r--r--Documentation/devicetree/bindings/ata/imx-sata.txt36
-rw-r--r--Documentation/devicetree/bindings/ata/tegra-sata.txt30
-rw-r--r--Documentation/devicetree/bindings/clock/arm-integrator.txt4
-rw-r--r--Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt35
-rw-r--r--Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt53
-rw-r--r--Documentation/devicetree/bindings/clock/clock-bindings.txt36
-rw-r--r--Documentation/devicetree/bindings/clock/clps711x-clock.txt19
-rw-r--r--Documentation/devicetree/bindings/clock/imx1-clock.txt26
-rw-r--r--Documentation/devicetree/bindings/clock/imx21-clock.txt28
-rw-r--r--Documentation/devicetree/bindings/clock/imx27-clock.txt127
-rw-r--r--Documentation/devicetree/bindings/clock/imx6q-clock.txt220
-rw-r--r--Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt5
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,mmcc.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt61
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt61
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip.txt3
-rw-r--r--Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt78
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt28
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt6
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt17
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt8
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt34
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen.txt59
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,flexgen.txt119
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,quadfs.txt15
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt7
-rw-r--r--Documentation/devicetree/bindings/crypto/amd-ccp.txt19
-rw-r--r--Documentation/devicetree/bindings/crypto/qcom-qce.txt25
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt1
-rw-r--r--Documentation/devicetree/bindings/dma/mpc512x-dma.txt29
-rw-r--r--Documentation/devicetree/bindings/dma/nbpfaxi.txt61
-rw-r--r--Documentation/devicetree/bindings/dma/rcar-audmapp.txt29
-rw-r--r--Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt98
-rw-r--r--Documentation/devicetree/bindings/dma/ste-dma40.txt74
-rw-r--r--Documentation/devicetree/bindings/dma/sun6i-dma.txt45
-rw-r--r--Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt30
-rw-r--r--Documentation/devicetree/bindings/drm/i2c/tda998x.txt2
-rw-r--r--Documentation/devicetree/bindings/drm/msm/gpu.txt52
-rw-r--r--Documentation/devicetree/bindings/drm/msm/hdmi.txt46
-rw-r--r--Documentation/devicetree/bindings/drm/msm/mdp.txt48
-rw-r--r--Documentation/devicetree/bindings/extcon/extcon-sm5502.txt23
-rw-r--r--Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt40
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-zynq.txt26
-rw-r--r--Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt43
-rw-r--r--Documentation/devicetree/bindings/gpu/st,stih4xx.txt189
-rw-r--r--Documentation/devicetree/bindings/hwmon/ibmpowernv.txt23
-rw-r--r--Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt1
-rw-r--r--Documentation/devicetree/bindings/hwmon/pwm-fan.txt12
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-efm32.txt4
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/max1027-adc.txt22
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt4
-rw-r--r--Documentation/devicetree/bindings/iio/st-sensors.txt54
-rw-r--r--Documentation/devicetree/bindings/input/atmel,maxtouch.txt25
-rw-r--r--Documentation/devicetree/bindings/input/cap1106.txt53
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt26
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt4
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt (renamed from Documentation/devicetree/bindings/arm/atmel-aic.txt)0
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt23
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.txt6
-rw-r--r--Documentation/devicetree/bindings/iommu/iommu.txt182
-rw-r--r--Documentation/devicetree/bindings/leds/pca963x.txt9
-rw-r--r--Documentation/devicetree/bindings/leds/tca6507.txt2
-rw-r--r--Documentation/devicetree/bindings/media/atmel-isi.txt51
-rw-r--r--Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt12
-rw-r--r--Documentation/devicetree/bindings/media/i2c/mt9m111.txt28
-rw-r--r--Documentation/devicetree/bindings/media/pxa-camera.txt43
-rw-r--r--Documentation/devicetree/bindings/media/rcar_vin.txt86
-rw-r--r--Documentation/devicetree/bindings/media/sunxi-ir.txt23
-rw-r--r--Documentation/devicetree/bindings/mfd/arizona.txt10
-rw-r--r--Documentation/devicetree/bindings/mfd/as3722.txt8
-rw-r--r--Documentation/devicetree/bindings/mfd/palmas.txt2
-rw-r--r--Documentation/devicetree/bindings/mfd/s2mps11.txt11
-rw-r--r--Documentation/devicetree/bindings/mfd/sun6i-prcm.txt2
-rw-r--r--Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt13
-rw-r--r--Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt17
-rw-r--r--Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt12
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc.txt4
-rw-r--r--Documentation/devicetree/bindings/mmc/renesas,mmcif.txt32
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.txt8
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-st.txt33
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt12
-rw-r--r--Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt54
-rw-r--r--Documentation/devicetree/bindings/mmc/tmio_mmc.txt1
-rw-r--r--Documentation/devicetree/bindings/mtd/gpmi-nand.txt10
-rw-r--r--Documentation/devicetree/bindings/net/amd-xgbe-phy.txt6
-rw-r--r--Documentation/devicetree/bindings/net/amd-xgbe.txt17
-rw-r--r--Documentation/devicetree/bindings/net/apm-xgene-enet.txt66
-rw-r--r--Documentation/devicetree/bindings/net/broadcom-systemport.txt3
-rw-r--r--Documentation/devicetree/bindings/net/davinci-mdio.txt8
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt29
-rw-r--r--Documentation/devicetree/bindings/net/ieee802154/cc2520.txt29
-rw-r--r--Documentation/devicetree/bindings/net/marvell-pp2.txt61
-rw-r--r--Documentation/devicetree/bindings/net/nfc/st21nfcb.txt33
-rw-r--r--Documentation/devicetree/bindings/net/sh_eth.txt1
-rw-r--r--Documentation/devicetree/bindings/net/stmmac.txt6
-rw-r--r--Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt41
-rw-r--r--Documentation/devicetree/bindings/panel/auo,b133htn01.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/innolux,n116bge.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt7
-rw-r--r--Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt30
-rw-r--r--Documentation/devicetree/bindings/pci/spear13xx-pcie.txt14
-rw-r--r--Documentation/devicetree/bindings/phy/berlin-sata-phy.txt34
-rw-r--r--Documentation/devicetree/bindings/phy/hix5hd2-phy.txt22
-rw-r--r--Documentation/devicetree/bindings/phy/phy-bindings.txt4
-rw-r--r--Documentation/devicetree/bindings/phy/phy-miphy365x.txt76
-rw-r--r--Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt24
-rw-r--r--Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt23
-rw-r--r--Documentation/devicetree/bindings/phy/samsung-phy.txt3
-rw-r--r--Documentation/devicetree/bindings/phy/st-spear-miphy.txt15
-rw-r--r--Documentation/devicetree/bindings/phy/ti-phy.txt23
-rw-r--r--Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt127
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt181
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt1
-rw-r--r--Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt24
-rw-r--r--Documentation/devicetree/bindings/power/rx51-battery.txt25
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/board.txt16
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-rockchip.txt20
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-st.txt41
-rw-r--r--Documentation/devicetree/bindings/regulator/act8865-regulator.txt7
-rw-r--r--Documentation/devicetree/bindings/regulator/palmas-pmic.txt1
-rw-r--r--Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt2
-rw-r--r--Documentation/devicetree/bindings/regulator/tps65218.txt23
-rw-r--r--Documentation/devicetree/bindings/serial/cdns,uart.txt20
-rw-r--r--Documentation/devicetree/bindings/serial/efm32-uart.txt4
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.txt6
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.txt56
-rw-r--r--Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt32
-rw-r--r--Documentation/devicetree/bindings/sound/ak5386.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/cs4265.txt29
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,asrc.txt60
-rw-r--r--Documentation/devicetree/bindings/sound/max98090.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt9
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.txt37
-rw-r--r--Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt35
-rw-r--r--Documentation/devicetree/bindings/sound/sirf-usp.txt27
-rw-r--r--Documentation/devicetree/bindings/sound/snow.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/tas2552.txt26
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas5086.txt5
-rw-r--r--Documentation/devicetree/bindings/sound/wm8904.txt33
-rw-r--r--Documentation/devicetree/bindings/spi/efm32-spi.txt13
-rw-r--r--Documentation/devicetree/bindings/spi/qcom,spi-qup.txt6
-rw-r--r--Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt28
-rw-r--r--Documentation/devicetree/bindings/spi/spi-davinci.txt9
-rw-r--r--Documentation/devicetree/bindings/spi/spi-rockchip.txt37
-rw-r--r--Documentation/devicetree/bindings/spi/spi-samsung.txt27
-rw-r--r--Documentation/devicetree/bindings/thermal/exynos-thermal.txt1
-rw-r--r--Documentation/devicetree/bindings/thermal/rcar-thermal.txt18
-rw-r--r--Documentation/devicetree/bindings/thermal/st-thermal.txt42
-rw-r--r--Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt29
-rw-r--r--Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt17
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,cmt.txt47
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,mtu2.txt39
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,tmu.txt39
-rw-r--r--Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt2
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt8
-rw-r--r--Documentation/devicetree/bindings/usb/usb-xhci.txt3
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt6
-rw-r--r--Documentation/devicetree/bindings/video/arm,pl11x.txt109
-rw-r--r--Documentation/devicetree/bindings/video/atmel,lcdc.txt1
-rw-r--r--Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt47
-rw-r--r--Documentation/devicetree/bindings/video/exynos_dsim.txt4
-rw-r--r--Documentation/devicetree/bindings/video/exynos_mixer.txt5
-rw-r--r--Documentation/devicetree/bindings/video/samsung-fimd.txt30
-rw-r--r--Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt5
-rw-r--r--Documentation/devicetree/changesets.txt40
-rw-r--r--Documentation/devicetree/todo.txt11
-rw-r--r--Documentation/dmaengine.txt17
-rw-r--r--Documentation/driver-model/devres.txt112
-rwxr-xr-xDocumentation/dvb/get_dvb_firmware33
-rw-r--r--Documentation/filesystems/Locking6
-rw-r--r--Documentation/filesystems/caching/operations.txt2
-rw-r--r--Documentation/filesystems/cifs/AUTHORS1
-rw-r--r--Documentation/filesystems/cifs/TODO97
-rw-r--r--Documentation/filesystems/f2fs.txt5
-rw-r--r--Documentation/filesystems/nfs/Exporting38
-rw-r--r--Documentation/filesystems/proc.txt19
-rw-r--r--Documentation/filesystems/vfs.txt3
-rw-r--r--Documentation/firmware_class/README6
-rw-r--r--Documentation/gpio/board.txt2
-rw-r--r--Documentation/gpio/consumer.txt26
-rw-r--r--Documentation/gpio/driver.txt25
-rw-r--r--Documentation/hwmon/ibmpowernv41
-rw-r--r--Documentation/hwmon/lm755
-rw-r--r--Documentation/hwmon/ntc_thermistor5
-rw-r--r--Documentation/hwmon/pmbus5
-rw-r--r--Documentation/hwmon/powr122045
-rw-r--r--Documentation/hwmon/pwm-fan17
-rw-r--r--Documentation/hwmon/tmp10328
-rw-r--r--Documentation/hwmon/tmp42126
-rw-r--r--Documentation/hwmon/tps4042264
-rw-r--r--Documentation/i2c/busses/i2c-i8011
-rw-r--r--Documentation/i2c/i2c-stub23
-rw-r--r--Documentation/infiniband/user_mad.txt13
-rw-r--r--Documentation/ioctl/00-INDEX2
-rw-r--r--Documentation/ioctl/botching-up-ioctls.txt219
-rw-r--r--Documentation/ioctl/ioctl-number.txt1
-rw-r--r--Documentation/kbuild/00-INDEX2
-rw-r--r--Documentation/kbuild/headers_install.txt (renamed from Documentation/make/headers_install.txt)0
-rw-r--r--Documentation/kbuild/makefiles.txt39
-rw-r--r--Documentation/kernel-parameters.txt79
-rw-r--r--Documentation/laptops/freefall.c5
-rw-r--r--Documentation/memory-barriers.txt27
-rw-r--r--Documentation/mic/mic_overview.txt67
-rwxr-xr-xDocumentation/mic/mpssd/mpss14
-rw-r--r--Documentation/networking/bonding.txt31
-rw-r--r--Documentation/networking/filter.txt12
-rw-r--r--Documentation/networking/i40e.txt7
-rw-r--r--Documentation/networking/ip-sysctl.txt38
-rw-r--r--Documentation/networking/packet_mmap.txt18
-rw-r--r--Documentation/networking/phy.txt18
-rw-r--r--Documentation/networking/pktgen.txt28
-rw-r--r--Documentation/networking/timestamping.txt16
-rw-r--r--Documentation/networking/timestamping/timestamping.c7
-rw-r--r--Documentation/oops-tracing.txt2
-rw-r--r--Documentation/phy.txt10
-rw-r--r--Documentation/power/opp.txt3
-rw-r--r--Documentation/power/power_supply_class.txt6
-rw-r--r--Documentation/power/regulator/consumer.txt35
-rw-r--r--Documentation/powerpc/00-INDEX2
-rw-r--r--Documentation/powerpc/kvm_440.txt41
-rw-r--r--Documentation/rapidio/tsi721.txt19
-rw-r--r--Documentation/scsi/ncr53c8xx.txt2
-rw-r--r--Documentation/scsi/tmscsim.txt2
-rw-r--r--Documentation/security/LSM.txt2
-rw-r--r--Documentation/security/keys.txt14
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt4
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt5
-rw-r--r--Documentation/stable_kernel_rules.txt3
-rw-r--r--Documentation/sysctl/kernel.txt1
-rw-r--r--Documentation/timers/00-INDEX2
-rw-r--r--Documentation/timers/timekeeping.txt179
-rw-r--r--Documentation/trace/ftrace-design.txt26
-rw-r--r--Documentation/trace/ftrace.txt2
-rw-r--r--Documentation/trace/postprocess/trace-vmscan-postprocess.pl53
-rw-r--r--Documentation/usb/hotplug.txt8
-rw-r--r--Documentation/usb/power-management.txt245
-rw-r--r--Documentation/vfio.txt87
-rw-r--r--Documentation/video4linux/CARDLIST.cx238852
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx2
-rw-r--r--Documentation/video4linux/v4l2-controls.txt63
-rw-r--r--Documentation/video4linux/v4l2-framework.txt8
-rw-r--r--Documentation/video4linux/v4l2-pci-skeleton.c5
-rw-r--r--Documentation/virtual/kvm/api.txt403
-rw-r--r--Documentation/w1/slaves/w1_ds240625
-rw-r--r--Documentation/watchdog/watchdog-api.txt2
-rw-r--r--Documentation/x86/tlb.txt75
-rw-r--r--Documentation/zh_CN/SubmittingDrivers4
-rw-r--r--Documentation/zh_CN/video4linux/v4l2-framework.txt7
-rw-r--r--MAINTAINERS436
-rw-r--r--Makefile49
-rw-r--r--arch/Kconfig1
-rw-r--r--arch/alpha/include/asm/Kbuild1
-rw-r--r--arch/alpha/include/asm/processor.h1
-rw-r--r--arch/alpha/include/asm/scatterlist.h6
-rw-r--r--arch/arc/boot/dts/angel4.dts2
-rw-r--r--arch/arc/include/asm/arcregs.h2
-rw-r--r--arch/arc/include/asm/irq.h4
-rw-r--r--arch/arc/include/asm/irqflags.h18
-rw-r--r--arch/arc/include/asm/processor.h2
-rw-r--r--arch/arc/kernel/irq.c53
-rw-r--r--arch/arc/kernel/perf_event.c7
-rw-r--r--arch/arc/kernel/signal.c47
-rw-r--r--arch/arc/kernel/smp.c23
-rw-r--r--arch/arc/kernel/time.c28
-rw-r--r--arch/arc/mm/cache_arc700.c168
-rw-r--r--arch/arc/mm/fault.c1
-rw-r--r--arch/arc/mm/tlbex.S4
-rw-r--r--arch/arc/plat-arcfpga/Kconfig7
-rw-r--r--arch/arc/plat-arcfpga/Makefile2
-rw-r--r--arch/arc/plat-arcfpga/include/plat/irq.h2
-rw-r--r--arch/arc/plat-arcfpga/irq.c25
-rw-r--r--arch/arc/plat-arcfpga/platform.c100
-rw-r--r--arch/arm/Kconfig117
-rw-r--r--arch/arm/Kconfig.debug80
-rw-r--r--arch/arm/Makefile13
-rw-r--r--arch/arm/boot/compressed/Makefile5
-rw-r--r--arch/arm/boot/compressed/head.S8
-rw-r--r--arch/arm/boot/compressed/vmlinux.lds.S (renamed from arch/arm/boot/compressed/vmlinux.lds.in)17
-rw-r--r--arch/arm/boot/dts/Makefile66
-rw-r--r--arch/arm/boot/dts/aks-cdu.dts6
-rw-r--r--arch/arm/boot/dts/am335x-evmsk.dts105
-rw-r--r--arch/arm/boot/dts/am335x-pepper.dts653
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi9
-rw-r--r--arch/arm/boot/dts/am4372.dtsi11
-rw-r--r--arch/arm/boot/dts/am437x-gp-evm.dts75
-rw-r--r--arch/arm/boot/dts/am437x-sk-evm.dts613
-rw-r--r--arch/arm/boot/dts/am43x-epos-evm.dts63
-rw-r--r--arch/arm/boot/dts/animeo_ip.dts8
-rw-r--r--arch/arm/boot/dts/armada-375-db.dts26
-rw-r--r--arch/arm/boot/dts/armada-375.dtsi34
-rw-r--r--arch/arm/boot/dts/armada-38x.dtsi5
-rw-r--r--arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts284
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78230.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78260.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78460.dtsi4
-rw-r--r--arch/arm/boot/dts/armada-xp.dtsi2
-rw-r--r--arch/arm/boot/dts/at91-ariag25.dts8
-rw-r--r--arch/arm/boot/dts/at91-cosino.dtsi8
-rw-r--r--arch/arm/boot/dts/at91-foxg20.dts8
-rw-r--r--arch/arm/boot/dts/at91-qil_a9260.dts8
-rw-r--r--arch/arm/boot/dts/at91-sama5d3_xplained.dts12
-rw-r--r--arch/arm/boot/dts/at91rm9200.dtsi304
-rw-r--r--arch/arm/boot/dts/at91rm9200ek.dts8
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi314
-rw-r--r--arch/arm/boot/dts/at91sam9261.dtsi20
-rw-r--r--arch/arm/boot/dts/at91sam9261ek.dts16
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi311
-rw-r--r--arch/arm/boot/dts/at91sam9263ek.dts8
-rw-r--r--arch/arm/boot/dts/at91sam9g20.dtsi24
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_common.dtsi8
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi342
-rw-r--r--arch/arm/boot/dts/at91sam9m10g45ek.dts8
-rw-r--r--arch/arm/boot/dts/at91sam9n12.dtsi20
-rw-r--r--arch/arm/boot/dts/at91sam9n12ek.dts18
-rw-r--r--arch/arm/boot/dts/at91sam9rl.dtsi32
-rw-r--r--arch/arm/boot/dts/at91sam9rlek.dts17
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi30
-rw-r--r--arch/arm/boot/dts/at91sam9x5cm.dtsi12
-rw-r--r--arch/arm/boot/dts/bcm11351.dtsi19
-rw-r--r--arch/arm/boot/dts/bcm21664.dtsi19
-rw-r--r--arch/arm/boot/dts/bcm7445-bcm97445svmb.dts14
-rw-r--r--arch/arm/boot/dts/bcm7445.dtsi111
-rw-r--r--arch/arm/boot/dts/berlin2.dtsi6
-rw-r--r--arch/arm/boot/dts/berlin2q-marvell-dmp.dts8
-rw-r--r--arch/arm/boot/dts/berlin2q.dtsi80
-rw-r--r--arch/arm/boot/dts/cros-ec-keyboard.dtsi105
-rw-r--r--arch/arm/boot/dts/dove-cubox-es.dts12
-rw-r--r--arch/arm/boot/dts/dove-cubox.dts3
-rw-r--r--arch/arm/boot/dts/dove.dtsi14
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts8
-rw-r--r--arch/arm/boot/dts/dra7.dtsi382
-rw-r--r--arch/arm/boot/dts/dra7xx-clocks.dtsi39
-rw-r--r--arch/arm/boot/dts/emev2.dtsi2
-rw-r--r--arch/arm/boot/dts/ethernut5.dts10
-rw-r--r--arch/arm/boot/dts/evk-pro3.dts6
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi35
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi43
-rw-r--r--arch/arm/boot/dts/exynos4210-smdkv310.dts2
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi16
-rw-r--r--arch/arm/boot/dts/exynos4412-odroid-common.dtsi371
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidu3.dts61
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx.dts279
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx2.dts32
-rw-r--r--arch/arm/boot/dts/exynos4412-trats2.dts2
-rw-r--r--arch/arm/boot/dts/exynos4412.dtsi4
-rw-r--r--arch/arm/boot/dts/exynos4x12.dtsi13
-rw-r--r--arch/arm/boot/dts/exynos5.dtsi16
-rw-r--r--arch/arm/boot/dts/exynos5250-cros-common.dtsi159
-rw-r--r--arch/arm/boot/dts/exynos5250-smdk5250.dts4
-rw-r--r--arch/arm/boot/dts/exynos5250-snow.dts259
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi3
-rw-r--r--arch/arm/boot/dts/exynos5260.dtsi9
-rw-r--r--arch/arm/boot/dts/exynos5410.dtsi15
-rw-r--r--arch/arm/boot/dts/exynos5420-peach-pit.dts392
-rw-r--r--arch/arm/boot/dts/exynos5420.dtsi28
-rw-r--r--arch/arm/boot/dts/exynos5440.dtsi6
-rw-r--r--arch/arm/boot/dts/exynos5800-peach-pi.dts374
-rw-r--r--arch/arm/boot/dts/ge863-pro3.dtsi4
-rw-r--r--arch/arm/boot/dts/hi3620.dtsi1
-rw-r--r--arch/arm/boot/dts/hisi-x5hd2-dkb.dts53
-rw-r--r--arch/arm/boot/dts/hisi-x5hd2.dtsi170
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts73
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts45
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts45
-rw-r--r--arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts1
-rw-r--r--arch/arm/boot/dts/imx25-pdk.dts8
-rw-r--r--arch/arm/boot/dts/imx25.dtsi8
-rw-r--r--arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi296
-rw-r--r--arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts273
-rw-r--r--arch/arm/boot/dts/imx27-pdk.dts2
-rw-r--r--arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts2
-rw-r--r--arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi3
-rw-r--r--arch/arm/boot/dts/imx27-pinfunc.h46
-rw-r--r--arch/arm/boot/dts/imx27.dtsi115
-rw-r--r--arch/arm/boot/dts/imx28-cfa10036.dts22
-rw-r--r--arch/arm/boot/dts/imx28-m28.dtsi87
-rw-r--r--arch/arm/boot/dts/imx28-m28evk.dts62
-rw-r--r--arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts1
-rw-r--r--arch/arm/boot/dts/imx35.dtsi8
-rw-r--r--arch/arm/boot/dts/imx50.dtsi8
-rw-r--r--arch/arm/boot/dts/imx51-babbage.dts2
-rw-r--r--arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts1
-rw-r--r--arch/arm/boot/dts/imx51.dtsi3
-rw-r--r--arch/arm/boot/dts/imx53-m53.dtsi140
-rw-r--r--arch/arm/boot/dts/imx53-m53evk.dts113
-rw-r--r--arch/arm/boot/dts/imx53-mba53.dts1
-rw-r--r--arch/arm/boot/dts/imx53-qsb-common.dtsi1
-rw-r--r--arch/arm/boot/dts/imx53-tx53.dtsi1
-rw-r--r--arch/arm/boot/dts/imx53-voipac-bsb.dts1
-rw-r--r--arch/arm/boot/dts/imx53.dtsi15
-rw-r--r--arch/arm/boot/dts/imx6dl-aristainetos_4.dts85
-rw-r--r--arch/arm/boot/dts/imx6dl-aristainetos_7.dts74
-rw-r--r--arch/arm/boot/dts/imx6dl-gw51xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl-gw52xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl-gw53xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl-gw54xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl-rex-basic.dts30
-rw-r--r--arch/arm/boot/dts/imx6dl-riotboard.dts33
-rw-r--r--arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts103
-rw-r--r--arch/arm/boot/dts/imx6dl-tx6u-801x.dts177
-rw-r--r--arch/arm/boot/dts/imx6dl-tx6u-811x.dts150
-rw-r--r--arch/arm/boot/dts/imx6dl-wandboard-revb1.dts22
-rw-r--r--arch/arm/boot/dts/imx6dl-wandboard.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl.dtsi17
-rw-r--r--arch/arm/boot/dts/imx6q-cubox-i.dts4
-rw-r--r--arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts54
-rw-r--r--arch/arm/boot/dts/imx6q-gw51xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-gw52xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-gw53xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-gw5400-a.dts5
-rw-r--r--arch/arm/boot/dts/imx6q-gw54xx.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-rex-pro.dts34
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts103
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1010.dts177
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts136
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1020.dts210
-rw-r--r--arch/arm/boot/dts/imx6q-tx6q-1110.dts154
-rw-r--r--arch/arm/boot/dts/imx6q-udoo.dts32
-rw-r--r--arch/arm/boot/dts/imx6q-wandboard-revb1.dts26
-rw-r--r--arch/arm/boot/dts/imx6q-wandboard.dts2
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi35
-rw-r--r--arch/arm/boot/dts/imx6qdl-aristainetos.dtsi418
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw52xx.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw53xx.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw54xx.dtsi6
-rw-r--r--arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-rex.dtsi357
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabrelite.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-tx6.dtsi696
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi42
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi41
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi22
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi161
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts17
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi12
-rw-r--r--arch/arm/boot/dts/imx6sx-pinfunc.h1544
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dts479
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi1208
-rw-r--r--arch/arm/boot/dts/integratorap.dts1
-rw-r--r--arch/arm/boot/dts/k2e-clocks.dtsi2
-rw-r--r--arch/arm/boot/dts/k2hk-clocks.dtsi2
-rw-r--r--arch/arm/boot/dts/k2hk-evm.dts12
-rw-r--r--arch/arm/boot/dts/k2l-clocks.dtsi2
-rw-r--r--arch/arm/boot/dts/keystone-clocks.dtsi2
-rw-r--r--arch/arm/boot/dts/keystone.dtsi11
-rw-r--r--arch/arm/boot/dts/kirkwood-d2net.dts42
-rw-r--r--arch/arm/boot/dts/kirkwood-net2big.dts60
-rw-r--r--arch/arm/boot/dts/kirkwood-net5big.dts111
-rw-r--r--arch/arm/boot/dts/kirkwood-netxbig.dtsi154
-rw-r--r--arch/arm/boot/dts/kizbox.dts4
-rw-r--r--arch/arm/boot/dts/mpa1600.dts8
-rw-r--r--arch/arm/boot/dts/mt6589-aquaris5.dts (renamed from arch/arm/mach-s5pv210/include/mach/dma.h)21
-rw-r--r--arch/arm/boot/dts/mt6589.dtsi94
-rw-r--r--arch/arm/boot/dts/omap2420.dtsi5
-rw-r--r--arch/arm/boot/dts/omap2430.dtsi5
-rw-r--r--arch/arm/boot/dts/omap3.dtsi2
-rw-r--r--arch/arm/boot/dts/omap4.dtsi9
-rw-r--r--arch/arm/boot/dts/omap5-uevm.dts68
-rw-r--r--arch/arm/boot/dts/omap5.dtsi62
-rw-r--r--arch/arm/boot/dts/pm9g45.dts8
-rw-r--r--arch/arm/boot/dts/r7s72100-genmai.dts10
-rw-r--r--arch/arm/boot/dts/r7s72100.dtsi1
-rw-r--r--arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts14
-rw-r--r--arch/arm/boot/dts/r8a73a4.dtsi42
-rw-r--r--arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts28
-rw-r--r--arch/arm/boot/dts/r8a7740.dtsi63
-rw-r--r--arch/arm/boot/dts/r8a7778-bockw-reference.dts14
-rw-r--r--arch/arm/boot/dts/r8a7778.dtsi42
-rw-r--r--arch/arm/boot/dts/r8a7779-marzen-reference.dts121
-rw-r--r--arch/arm/boot/dts/r8a7779-marzen.dts116
-rw-r--r--arch/arm/boot/dts/r8a7779.dtsi234
-rw-r--r--arch/arm/boot/dts/r8a7790-lager.dts88
-rw-r--r--arch/arm/boot/dts/r8a7790.dtsi207
-rw-r--r--arch/arm/boot/dts/r8a7791-henninger.dts45
-rw-r--r--arch/arm/boot/dts/r8a7791-koelsch.dts89
-rw-r--r--arch/arm/boot/dts/r8a7791.dtsi218
-rw-r--r--arch/arm/boot/dts/rk3066a-bqcurie2.dts214
-rw-r--r--arch/arm/boot/dts/rk3066a-clocks.dtsi299
-rw-r--r--arch/arm/boot/dts/rk3066a.dtsi519
-rw-r--r--arch/arm/boot/dts/rk3188-clocks.dtsi289
-rw-r--r--arch/arm/boot/dts/rk3188-radxarock.dts218
-rw-r--r--arch/arm/boot/dts/rk3188.dtsi446
-rw-r--r--arch/arm/boot/dts/rk3288-evb-act8846.dts134
-rw-r--r--arch/arm/boot/dts/rk3288-evb-rk808.dts18
-rw-r--r--arch/arm/boot/dts/rk3288-evb.dtsi96
-rw-r--r--arch/arm/boot/dts/rk3288.dtsi595
-rw-r--r--arch/arm/boot/dts/rk3xxx.dtsi356
-rw-r--r--arch/arm/boot/dts/s3c2416.dtsi6
-rw-r--r--arch/arm/boot/dts/s3c24xx.dtsi9
-rw-r--r--arch/arm/boot/dts/s3c64xx.dtsi4
-rw-r--r--arch/arm/boot/dts/s5pv210-aquila.dts392
-rw-r--r--arch/arm/boot/dts/s5pv210-goni.dts449
-rw-r--r--arch/arm/boot/dts/s5pv210-pinctrl.dtsi839
-rw-r--r--arch/arm/boot/dts/s5pv210-smdkc110.dts78
-rw-r--r--arch/arm/boot/dts/s5pv210-smdkv210.dts238
-rw-r--r--arch/arm/boot/dts/s5pv210-torbreck.dts92
-rw-r--r--arch/arm/boot/dts/s5pv210.dtsi633
-rw-r--r--arch/arm/boot/dts/sama5d3.dtsi22
-rw-r--r--arch/arm/boot/dts/sama5d3_gmac.dtsi2
-rw-r--r--arch/arm/boot/dts/sama5d3xcm.dtsi12
-rw-r--r--arch/arm/boot/dts/sama5d3xmb.dtsi2
-rw-r--r--arch/arm/boot/dts/sh73a0-kzm9g-reference.dts16
-rw-r--r--arch/arm/boot/dts/sh73a0.dtsi72
-rw-r--r--arch/arm/boot/dts/socfpga.dtsi5
-rw-r--r--arch/arm/boot/dts/spear1310-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear1310.dtsi93
-rw-r--r--arch/arm/boot/dts/spear1340-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear1340.dtsi30
-rw-r--r--arch/arm/boot/dts/spear13xx.dtsi9
-rw-r--r--arch/arm/boot/dts/ste-dbx5x0.dtsi10
-rw-r--r--arch/arm/boot/dts/ste-href-stuib.dtsi2
-rw-r--r--arch/arm/boot/dts/ste-href-tvk1281618.dtsi59
-rw-r--r--arch/arm/boot/dts/ste-hrefv60plus.dtsi24
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts38
-rw-r--r--arch/arm/boot/dts/sun4i-a10-a1000.dts15
-rw-r--r--arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts110
-rw-r--r--arch/arm/boot/dts/sun4i-a10-cubieboard.dts15
-rw-r--r--arch/arm/boot/dts/sun4i-a10-hackberry.dts21
-rw-r--r--arch/arm/boot/dts/sun4i-a10-inet97fv2.dts21
-rw-r--r--arch/arm/boot/dts/sun4i-a10-mini-xplus.dts28
-rw-r--r--arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts15
-rw-r--r--arch/arm/boot/dts/sun4i-a10-pcduino.dts9
-rw-r--r--arch/arm/boot/dts/sun4i-a10.dtsi34
-rw-r--r--arch/arm/boot/dts/sun5i-a10s.dtsi2
-rw-r--r--arch/arm/boot/dts/sun5i-a13.dtsi2
-rw-r--r--arch/arm/boot/dts/sun6i-a31-hummingbird.dts119
-rw-r--r--arch/arm/boot/dts/sun6i-a31.dtsi92
-rw-r--r--arch/arm/boot/dts/sun7i-a20-cubieboard2.dts16
-rw-r--r--arch/arm/boot/dts/sun7i-a20-cubietruck.dts16
-rw-r--r--arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts22
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts10
-rw-r--r--arch/arm/boot/dts/sun7i-a20-pcduino3.dts173
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi34
-rw-r--r--arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts30
-rw-r--r--arch/arm/boot/dts/sun8i-a23.dtsi343
-rw-r--r--arch/arm/boot/dts/tegra114-roth.dts32
-rw-r--r--arch/arm/boot/dts/tegra114.dtsi20
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts33
-rw-r--r--arch/arm/boot/dts/tegra124-venice2.dts128
-rw-r--r--arch/arm/boot/dts/tegra124.dtsi62
-rw-r--r--arch/arm/boot/dts/tegra20-harmony.dts8
-rw-r--r--arch/arm/boot/dts/tegra20-medcom-wide.dts61
-rw-r--r--arch/arm/boot/dts/tegra20-paz00.dts6
-rw-r--r--arch/arm/boot/dts/tegra20-plutux.dts41
-rw-r--r--arch/arm/boot/dts/tegra20-tamonten.dtsi17
-rw-r--r--arch/arm/boot/dts/tegra20-tec.dts41
-rw-r--r--arch/arm/boot/dts/tegra20-trimslice.dts8
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi22
-rw-r--r--arch/arm/boot/dts/tegra30-apalis-eval.dts260
-rw-r--r--arch/arm/boot/dts/tegra30-apalis.dtsi678
-rw-r--r--arch/arm/boot/dts/tegra30-beaver.dts12
-rw-r--r--arch/arm/boot/dts/tegra30-cardhu.dtsi11
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi22
-rw-r--r--arch/arm/boot/dts/tny_a9260_common.dtsi8
-rw-r--r--arch/arm/boot/dts/tny_a9263.dts8
-rw-r--r--arch/arm/boot/dts/usb_a9260_common.dtsi8
-rw-r--r--arch/arm/boot/dts/usb_a9263.dts8
-rw-r--r--arch/arm/boot/dts/versatile-ab.dts85
-rw-r--r--arch/arm/boot/dts/versatile-pb.dts14
-rw-r--r--arch/arm/boot/dts/vf610.dtsi25
-rw-r--r--arch/arm/boot/dts/zynq-7000.dtsi90
-rw-r--r--arch/arm/boot/dts/zynq-parallella.dts64
-rw-r--r--arch/arm/boot/dts/zynq-zc702.dts4
-rw-r--r--arch/arm/common/bL_switcher.c16
-rw-r--r--arch/arm/common/edma.c31
-rw-r--r--arch/arm/common/mcpm_entry.c52
-rw-r--r--arch/arm/common/timer-sp.c4
-rw-r--r--arch/arm/configs/armadillo800eva_defconfig4
-rw-r--r--arch/arm/configs/bcm_defconfig1
-rw-r--r--arch/arm/configs/exynos_defconfig56
-rw-r--r--arch/arm/configs/genmai_defconfig122
-rw-r--r--arch/arm/configs/hi3xxx_defconfig2
-rw-r--r--arch/arm/configs/imx_v4_v5_defconfig5
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig9
-rw-r--r--arch/arm/configs/kirkwood_defconfig181
-rw-r--r--arch/arm/configs/msm_defconfig1
-rw-r--r--arch/arm/configs/multi_v5_defconfig2
-rw-r--r--arch/arm/configs/multi_v7_defconfig23
-rw-r--r--arch/arm/configs/mvebu_v5_defconfig6
-rw-r--r--arch/arm/configs/mvebu_v7_defconfig5
-rw-r--r--arch/arm/configs/mxs_defconfig1
-rw-r--r--arch/arm/configs/omap1_defconfig2
-rw-r--r--arch/arm/configs/omap2plus_defconfig2
-rw-r--r--arch/arm/configs/s3c2410_defconfig1
-rw-r--r--arch/arm/configs/s5p64x0_defconfig68
-rw-r--r--arch/arm/configs/s5pc100_defconfig49
-rw-r--r--arch/arm/configs/shmobile_defconfig23
-rw-r--r--arch/arm/configs/socfpga_defconfig35
-rw-r--r--arch/arm/configs/spear13xx_defconfig16
-rw-r--r--arch/arm/configs/tegra_defconfig16
-rw-r--r--arch/arm/crypto/Makefile4
-rw-r--r--arch/arm/crypto/aes-armv4.S3
-rw-r--r--arch/arm/crypto/sha1-armv7-neon.S634
-rw-r--r--arch/arm/crypto/sha1_glue.c58
-rw-r--r--arch/arm/crypto/sha1_neon_glue.c197
-rw-r--r--arch/arm/crypto/sha512-armv7-neon.S455
-rw-r--r--arch/arm/crypto/sha512_neon_glue.c305
-rw-r--r--arch/arm/include/asm/Kbuild1
-rw-r--r--arch/arm/include/asm/assembler.h29
-rw-r--r--arch/arm/include/asm/cputype.h37
-rw-r--r--arch/arm/include/asm/crypto/sha1.h10
-rw-r--r--arch/arm/include/asm/entry-macro-multi.S2
-rw-r--r--arch/arm/include/asm/glue-proc.h18
-rw-r--r--arch/arm/include/asm/gpio.h7
-rw-r--r--arch/arm/include/asm/kvm_asm.h18
-rw-r--r--arch/arm/include/asm/kvm_emulate.h22
-rw-r--r--arch/arm/include/asm/kvm_host.h8
-rw-r--r--arch/arm/include/asm/kvm_mmu.h12
-rw-r--r--arch/arm/include/asm/mcpm.h16
-rw-r--r--arch/arm/include/asm/mcs_spinlock.h23
-rw-r--r--arch/arm/include/asm/memory.h10
-rw-r--r--arch/arm/include/asm/perf_event.h9
-rw-r--r--arch/arm/include/asm/pgtable-3level-hwdef.h3
-rw-r--r--arch/arm/include/asm/pgtable-3level.h49
-rw-r--r--arch/arm/include/asm/pgtable.h18
-rw-r--r--arch/arm/include/asm/pmu.h19
-rw-r--r--arch/arm/include/asm/processor.h2
-rw-r--r--arch/arm/include/asm/ptrace.h6
-rw-r--r--arch/arm/include/asm/scatterlist.h12
-rw-r--r--arch/arm/include/asm/smp_scu.h2
-rw-r--r--arch/arm/include/asm/stacktrace.h15
-rw-r--r--arch/arm/include/asm/thread_info.h3
-rw-r--r--arch/arm/include/asm/uaccess.h22
-rw-r--r--arch/arm/include/asm/unistd.h12
-rw-r--r--arch/arm/include/debug/clps711x.S38
-rw-r--r--arch/arm/include/debug/s5pv210.S (renamed from arch/arm/mach-s5pv210/include/mach/debug-macro.S)23
-rw-r--r--arch/arm/include/uapi/asm/unistd.h14
-rw-r--r--arch/arm/kernel/asm-offsets.c14
-rw-r--r--arch/arm/kernel/calls.S3
-rw-r--r--arch/arm/kernel/debug.S10
-rw-r--r--arch/arm/kernel/entry-armv.S42
-rw-r--r--arch/arm/kernel/entry-common.S13
-rw-r--r--arch/arm/kernel/entry-header.S14
-rw-r--r--arch/arm/kernel/fiqasm.S4
-rw-r--r--arch/arm/kernel/head-common.S7
-rw-r--r--arch/arm/kernel/head-nommu.S8
-rw-r--r--arch/arm/kernel/head.S18
-rw-r--r--arch/arm/kernel/hyp-stub.S10
-rw-r--r--arch/arm/kernel/iwmmxt.S16
-rw-r--r--arch/arm/kernel/perf_event.c18
-rw-r--r--arch/arm/kernel/perf_event_cpu.c66
-rw-r--r--arch/arm/kernel/perf_event_v6.c307
-rw-r--r--arch/arm/kernel/perf_event_v7.c967
-rw-r--r--arch/arm/kernel/perf_event_xscale.c121
-rw-r--r--arch/arm/kernel/relocate_kernel.S3
-rw-r--r--arch/arm/kernel/setup.c29
-rw-r--r--arch/arm/kernel/sleep.S2
-rw-r--r--arch/arm/kernel/smp.c70
-rw-r--r--arch/arm/kernel/smp_scu.c12
-rw-r--r--arch/arm/kernel/smp_tlb.c20
-rw-r--r--arch/arm/kernel/swp_emulate.c4
-rw-r--r--arch/arm/kernel/time.c5
-rw-r--r--arch/arm/kernel/traps.c6
-rw-r--r--arch/arm/kernel/unwind.c8
-rw-r--r--arch/arm/kernel/vmlinux.lds.S1
-rw-r--r--arch/arm/kvm/Kconfig2
-rw-r--r--arch/arm/kvm/Makefile1
-rw-r--r--arch/arm/kvm/arm.c39
-rw-r--r--arch/arm/kvm/coproc.c88
-rw-r--r--arch/arm/kvm/guest.c18
-rw-r--r--arch/arm/kvm/init.S7
-rw-r--r--arch/arm/kvm/interrupts.S9
-rw-r--r--arch/arm/kvm/interrupts_head.S48
-rw-r--r--arch/arm/kvm/mmu.c214
-rw-r--r--arch/arm/lib/ashldi3.S3
-rw-r--r--arch/arm/lib/ashrdi3.S3
-rw-r--r--arch/arm/lib/backtrace.S2
-rw-r--r--arch/arm/lib/bitops.h5
-rw-r--r--arch/arm/lib/bswapsdi2.S5
-rw-r--r--arch/arm/lib/call_with_stack.S4
-rw-r--r--arch/arm/lib/csumpartial.S2
-rw-r--r--arch/arm/lib/csumpartialcopygeneric.S5
-rw-r--r--arch/arm/lib/delay-loop.S18
-rw-r--r--arch/arm/lib/delay.c26
-rw-r--r--arch/arm/lib/div64.S13
-rw-r--r--arch/arm/lib/findbit.S10
-rw-r--r--arch/arm/lib/getuser.S45
-rw-r--r--arch/arm/lib/io-readsb.S2
-rw-r--r--arch/arm/lib/io-readsl.S6
-rw-r--r--arch/arm/lib/io-readsw-armv3.S4
-rw-r--r--arch/arm/lib/io-readsw-armv4.S2
-rw-r--r--arch/arm/lib/io-writesb.S2
-rw-r--r--arch/arm/lib/io-writesl.S10
-rw-r--r--arch/arm/lib/io-writesw-armv3.S4
-rw-r--r--arch/arm/lib/io-writesw-armv4.S4
-rw-r--r--arch/arm/lib/lib1funcs.S26
-rw-r--r--arch/arm/lib/lshrdi3.S3
-rw-r--r--arch/arm/lib/memchr.S2
-rw-r--r--arch/arm/lib/memset.S2
-rw-r--r--arch/arm/lib/memzero.S2
-rw-r--r--arch/arm/lib/muldi3.S3
-rw-r--r--arch/arm/lib/putuser.S10
-rw-r--r--arch/arm/lib/strchr.S2
-rw-r--r--arch/arm/lib/strrchr.S2
-rw-r--r--arch/arm/lib/ucmpdi2.S5
-rw-r--r--arch/arm/mach-at91/Kconfig4
-rw-r--r--arch/arm/mach-at91/at91rm9200.c6
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9260.c6
-rw-r--r--arch/arm/mach-at91/at91sam9263.c7
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c11
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c7
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c11
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c1
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c11
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c55
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c42
-rw-r--r--arch/arm/mach-at91/board.h1
-rw-r--r--arch/arm/mach-at91/leds.c37
-rw-r--r--arch/arm/mach-bcm/Kconfig34
-rw-r--r--arch/arm/mach-bcm/Makefile8
-rw-r--r--arch/arm/mach-bcm/board_bcm21664.c3
-rw-r--r--arch/arm/mach-bcm/board_bcm281xx.c3
-rw-r--r--arch/arm/mach-bcm/brcmstb.c28
-rw-r--r--arch/arm/mach-bcm/brcmstb.h19
-rw-r--r--arch/arm/mach-bcm/headsmp-brcmstb.S33
-rw-r--r--arch/arm/mach-bcm/kona_smp.c202
-rw-r--r--arch/arm/mach-bcm/platsmp-brcmstb.c363
-rw-r--r--arch/arm/mach-berlin/Kconfig3
-rw-r--r--arch/arm/mach-berlin/Makefile3
-rw-r--r--arch/arm/mach-berlin/headsmp.S30
-rw-r--r--arch/arm/mach-berlin/platsmp.c99
-rw-r--r--arch/arm/mach-clps711x/board-autcpu12.c1
-rw-r--r--arch/arm/mach-clps711x/board-cdb89712.c1
-rw-r--r--arch/arm/mach-clps711x/board-clep7312.c3
-rw-r--r--arch/arm/mach-clps711x/board-edb7211.c14
-rw-r--r--arch/arm/mach-clps711x/board-p720t.c7
-rw-r--r--arch/arm/mach-clps711x/common.c12
-rw-r--r--arch/arm/mach-clps711x/common.h1
-rw-r--r--arch/arm/mach-clps711x/devices.c10
-rw-r--r--arch/arm/mach-clps711x/include/mach/debug-macro.S38
-rw-r--r--arch/arm/mach-clps711x/include/mach/hardware.h5
-rw-r--r--arch/arm/mach-davinci/sleep.S2
-rw-r--r--arch/arm/mach-ebsa110/include/mach/memory.h5
-rw-r--r--arch/arm/mach-ep93xx/crunch-bits.S6
-rw-r--r--arch/arm/mach-ep93xx/include/mach/memory.h22
-rw-r--r--arch/arm/mach-exynos/Kconfig2
-rw-r--r--arch/arm/mach-exynos/common.h27
-rw-r--r--arch/arm/mach-exynos/exynos.c76
-rw-r--r--arch/arm/mach-exynos/headsmp.S1
-rw-r--r--arch/arm/mach-exynos/hotplug.c3
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h6
-rw-r--r--arch/arm/mach-exynos/include/mach/memory.h3
-rw-r--r--arch/arm/mach-exynos/mcpm-exynos.c123
-rw-r--r--arch/arm/mach-exynos/platsmp.c77
-rw-r--r--arch/arm/mach-exynos/pm.c286
-rw-r--r--arch/arm/mach-exynos/pm_domains.c9
-rw-r--r--arch/arm/mach-exynos/pmu.c41
-rw-r--r--arch/arm/mach-exynos/regs-pmu.h525
-rw-r--r--arch/arm/mach-exynos/regs-sys.h22
-rw-r--r--arch/arm/mach-footbridge/include/mach/memory.h5
-rw-r--r--arch/arm/mach-highbank/Kconfig1
-rw-r--r--arch/arm/mach-hisi/Kconfig30
-rw-r--r--arch/arm/mach-hisi/Makefile2
-rw-r--r--arch/arm/mach-hisi/core.h5
-rw-r--r--arch/arm/mach-hisi/headsmp.S16
-rw-r--r--arch/arm/mach-hisi/hisilicon.c43
-rw-r--r--arch/arm/mach-hisi/hotplug.c58
-rw-r--r--arch/arm/mach-hisi/platsmp.c53
-rw-r--r--arch/arm/mach-imx/Kconfig60
-rw-r--r--arch/arm/mach-imx/Makefile11
-rw-r--r--arch/arm/mach-imx/clk-imx1.c151
-rw-r--r--arch/arm/mach-imx/clk-imx21.c299
-rw-r--r--arch/arm/mach-imx/clk-imx25.c47
-rw-r--r--arch/arm/mach-imx/clk-imx27.c452
-rw-r--r--arch/arm/mach-imx/clk-imx31.c6
-rw-r--r--arch/arm/mach-imx/clk-imx35.c6
-rw-r--r--arch/arm/mach-imx/clk-imx51-imx53.c256
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c540
-rw-r--r--arch/arm/mach-imx/clk-imx6sl.c11
-rw-r--r--arch/arm/mach-imx/clk-imx6sx.c25
-rw-r--r--arch/arm/mach-imx/clk-vf610.c8
-rw-r--r--arch/arm/mach-imx/clk.c10
-rw-r--r--arch/arm/mach-imx/clk.h9
-rw-r--r--arch/arm/mach-imx/common.h32
-rw-r--r--arch/arm/mach-imx/cpu-imx5.c25
-rw-r--r--arch/arm/mach-imx/cpu.c13
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c6
-rw-r--r--arch/arm/mach-imx/crm-regs-imx5.h600
-rw-r--r--arch/arm/mach-imx/devices-imx51.h66
-rw-r--r--arch/arm/mach-imx/devices/Kconfig9
-rw-r--r--arch/arm/mach-imx/devices/Makefile2
-rw-r--r--arch/arm/mach-imx/devices/devices-common.h26
-rw-r--r--arch/arm/mach-imx/devices/devices.c2
-rw-r--r--arch/arm/mach-imx/devices/platform-fec.c12
-rw-r--r--arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c5
-rw-r--r--arch/arm/mach-imx/devices/platform-imx-i2c.c26
-rw-r--r--arch/arm/mach-imx/devices/platform-imx-keypad.c10
-rw-r--r--arch/arm/mach-imx/devices/platform-imx-ssi.c20
-rw-r--r--arch/arm/mach-imx/devices/platform-imx-uart.c22
-rw-r--r--arch/arm/mach-imx/devices/platform-imx2-wdt.c18
-rw-r--r--arch/arm/mach-imx/devices/platform-imx_udc.c75
-rw-r--r--arch/arm/mach-imx/devices/platform-mx1-camera.c42
-rw-r--r--arch/arm/mach-imx/devices/platform-mxc-ehci.c9
-rw-r--r--arch/arm/mach-imx/devices/platform-mxc_nand.c5
-rw-r--r--arch/arm/mach-imx/devices/platform-mxc_rnga.c5
-rw-r--r--arch/arm/mach-imx/devices/platform-pata_imx.c10
-rw-r--r--arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c24
-rw-r--r--arch/arm/mach-imx/devices/platform-spi_imx.c27
-rw-r--r--arch/arm/mach-imx/ehci-imx25.c1
-rw-r--r--arch/arm/mach-imx/ehci-imx27.c1
-rw-r--r--arch/arm/mach-imx/ehci-imx31.c1
-rw-r--r--arch/arm/mach-imx/ehci-imx35.c1
-rw-r--r--arch/arm/mach-imx/ehci-imx5.c171
-rw-r--r--arch/arm/mach-imx/ehci.h43
-rw-r--r--arch/arm/mach-imx/gpc.c5
-rw-r--r--arch/arm/mach-imx/hardware.h2
-rw-r--r--arch/arm/mach-imx/imx25-dt.c6
-rw-r--r--arch/arm/mach-imx/imx27-dt.c6
-rw-r--r--arch/arm/mach-imx/imx31-dt.c2
-rw-r--r--arch/arm/mach-imx/imx35-dt.c2
-rw-r--r--arch/arm/mach-imx/iomux-mx51.h827
-rw-r--r--arch/arm/mach-imx/mach-armadillo5x0.c1
-rw-r--r--arch/arm/mach-imx/mach-cpuimx27.c1
-rw-r--r--arch/arm/mach-imx/mach-cpuimx35.c1
-rw-r--r--arch/arm/mach-imx/mach-eukrea_cpuimx25.c1
-rw-r--r--arch/arm/mach-imx/mach-imx27_visstrim_m10.c1
-rw-r--r--arch/arm/mach-imx/mach-imx27ipcam.c77
-rw-r--r--arch/arm/mach-imx/mach-imx27lite.c83
-rw-r--r--arch/arm/mach-imx/mach-imx50.c5
-rw-r--r--arch/arm/mach-imx/mach-imx51.c (renamed from arch/arm/mach-imx/imx51-dt.c)45
-rw-r--r--arch/arm/mach-imx/mach-imx53.c19
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c4
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c2
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c10
-rw-r--r--arch/arm/mach-imx/mach-mx25_3ds.c1
-rw-r--r--arch/arm/mach-imx/mach-mx27_3ds.c1
-rw-r--r--arch/arm/mach-imx/mach-mx27ads.c2
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c1
-rw-r--r--arch/arm/mach-imx/mach-mx31lilly.c1
-rw-r--r--arch/arm/mach-imx/mach-mx31lite.c1
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c5
-rw-r--r--arch/arm/mach-imx/mach-mx35_3ds.c1
-rw-r--r--arch/arm/mach-imx/mach-pca100.c1
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c1
-rw-r--r--arch/arm/mach-imx/mach-pcm038.c1
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c1
-rw-r--r--arch/arm/mach-imx/mach-vf610.c2
-rw-r--r--arch/arm/mach-imx/mach-vpr200.c1
-rw-r--r--arch/arm/mach-imx/mm-imx5.c155
-rw-r--r--arch/arm/mach-imx/mx1-camera-fiq-ksym.c18
-rw-r--r--arch/arm/mach-imx/mx1-camera-fiq.S35
-rw-r--r--arch/arm/mach-imx/mx31moboard-devboard.c5
-rw-r--r--arch/arm/mach-imx/mx31moboard-marxbot.c5
-rw-r--r--arch/arm/mach-imx/mx31moboard-smartbot.c5
-rw-r--r--arch/arm/mach-imx/mx51.h346
-rw-r--r--arch/arm/mach-imx/mx53.h342
-rw-r--r--arch/arm/mach-imx/mxc.h7
-rw-r--r--arch/arm/mach-imx/pm-imx5.c98
-rw-r--r--arch/arm/mach-imx/pm-imx6.c67
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S5
-rw-r--r--arch/arm/mach-imx/system.c24
-rw-r--r--arch/arm/mach-imx/time.c55
-rw-r--r--arch/arm/mach-imx/tzic.c9
-rw-r--r--arch/arm/mach-integrator/Kconfig1
-rw-r--r--arch/arm/mach-integrator/include/mach/memory.h34
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c10
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c13
-rw-r--r--arch/arm/mach-iop13xx/include/mach/iop13xx.h2
-rw-r--r--arch/arm/mach-iop13xx/include/mach/memory.h5
-rw-r--r--arch/arm/mach-iop13xx/setup.c1
-rw-r--r--arch/arm/mach-kirkwood/Kconfig111
-rw-r--r--arch/arm/mach-kirkwood/Makefile14
-rw-r--r--arch/arm/mach-kirkwood/Makefile.boot3
-rw-r--r--arch/arm/mach-kirkwood/board-dt.c223
-rw-r--r--arch/arm/mach-kirkwood/common.c746
-rw-r--r--arch/arm/mach-kirkwood/common.h74
-rw-r--r--arch/arm/mach-kirkwood/d2net_v2-setup.c231
-rw-r--r--arch/arm/mach-kirkwood/include/mach/bridge-regs.h86
-rw-r--r--arch/arm/mach-kirkwood/include/mach/entry-macro.S34
-rw-r--r--arch/arm/mach-kirkwood/include/mach/irqs.h65
-rw-r--r--arch/arm/mach-kirkwood/include/mach/kirkwood.h142
-rw-r--r--arch/arm/mach-kirkwood/include/mach/uncompress.h46
-rw-r--r--arch/arm/mach-kirkwood/irq.c82
-rw-r--r--arch/arm/mach-kirkwood/lacie_v2-common.c114
-rw-r--r--arch/arm/mach-kirkwood/lacie_v2-common.h16
-rw-r--r--arch/arm/mach-kirkwood/mpp.c43
-rw-r--r--arch/arm/mach-kirkwood/mpp.h348
-rw-r--r--arch/arm/mach-kirkwood/netxbig_v2-setup.c422
-rw-r--r--arch/arm/mach-kirkwood/openrd-setup.c255
-rw-r--r--arch/arm/mach-kirkwood/pcie.c296
-rw-r--r--arch/arm/mach-kirkwood/pm.c76
-rw-r--r--arch/arm/mach-kirkwood/pm.h26
-rw-r--r--arch/arm/mach-kirkwood/rd88f6192-nas-setup.c89
-rw-r--r--arch/arm/mach-kirkwood/rd88f6281-setup.c128
-rw-r--r--arch/arm/mach-kirkwood/t5325-setup.c216
-rw-r--r--arch/arm/mach-kirkwood/ts219-setup.c142
-rw-r--r--arch/arm/mach-kirkwood/ts41x-setup.c186
-rw-r--r--arch/arm/mach-kirkwood/tsx1x-common.c113
-rw-r--r--arch/arm/mach-kirkwood/tsx1x-common.h7
-rw-r--r--arch/arm/mach-ks8695/include/mach/memory.h5
-rw-r--r--arch/arm/mach-mediatek/Kconfig6
-rw-r--r--arch/arm/mach-mediatek/Makefile1
-rw-r--r--arch/arm/mach-mediatek/mediatek.c (renamed from arch/arm/mach-s5pc100/include/mach/dma.h)25
-rw-r--r--arch/arm/mach-mmp/include/mach/mfp-pxa910.h1
-rw-r--r--arch/arm/mach-msm/Kconfig3
-rw-r--r--arch/arm/mach-mvebu/Kconfig13
-rw-r--r--arch/arm/mach-mvebu/Makefile4
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.h2
-rw-r--r--arch/arm/mach-mvebu/board-v7.c22
-rw-r--r--arch/arm/mach-mvebu/board.h5
-rw-r--r--arch/arm/mach-mvebu/coherency_ll.S10
-rw-r--r--arch/arm/mach-mvebu/common.h3
-rw-r--r--arch/arm/mach-mvebu/cpu-reset.c2
-rw-r--r--arch/arm/mach-mvebu/headsmp-a9.S15
-rw-r--r--arch/arm/mach-mvebu/hotplug.c31
-rw-r--r--arch/arm/mach-mvebu/kirkwood.c3
-rw-r--r--arch/arm/mach-mvebu/mvebu-soc-id.c21
-rw-r--r--arch/arm/mach-mvebu/netxbig.c191
-rw-r--r--arch/arm/mach-mvebu/platsmp-a9.c45
-rw-r--r--arch/arm/mach-mvebu/platsmp.c49
-rw-r--r--arch/arm/mach-mvebu/pmsu.c438
-rw-r--r--arch/arm/mach-mvebu/pmsu.h5
-rw-r--r--arch/arm/mach-mvebu/pmsu_ll.S36
-rw-r--r--arch/arm/mach-mvebu/system-controller.c50
-rw-r--r--arch/arm/mach-omap1/include/mach/memory.h5
-rw-r--r--arch/arm/mach-omap1/ocpi.c1
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-omap2/Makefile11
-rw-r--r--arch/arm/mach-omap2/board-omap3touchbook.c2
-rw-r--r--arch/arm/mach-omap2/cclock2420_data.c1931
-rw-r--r--arch/arm/mach-omap2/cclock2430_data.c2048
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_osc.c69
-rw-r--r--arch/arm/mach-omap2/clkt2xxx_sys.c47
-rw-r--r--arch/arm/mach-omap2/clkt_dpll.c126
-rw-r--r--arch/arm/mach-omap2/clkt_iclk.c8
-rw-r--r--arch/arm/mach-omap2/clock.c97
-rw-r--r--arch/arm/mach-omap2/clock.h47
-rw-r--r--arch/arm/mach-omap2/clock2xxx.h2
-rw-r--r--arch/arm/mach-omap2/cm-regbits-24xx.h1
-rw-r--r--arch/arm/mach-omap2/cm2_7xx.h4
-rw-r--r--arch/arm/mach-omap2/common.c2
-rw-r--r--arch/arm/mach-omap2/control.c66
-rw-r--r--arch/arm/mach-omap2/control.h40
-rw-r--r--arch/arm/mach-omap2/ctrl_module_core_44xx.h392
-rw-r--r--arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h1409
-rw-r--r--arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h236
-rw-r--r--arch/arm/mach-omap2/devices.c2
-rw-r--r--arch/arm/mach-omap2/dma.c3
-rw-r--r--arch/arm/mach-omap2/dpll3xxx.c20
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c19
-rw-r--r--arch/arm/mach-omap2/dsp.c134
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c79
-rw-r--r--arch/arm/mach-omap2/io.c9
-rw-r--r--arch/arm/mach-omap2/mux.c22
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c14
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c13
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c9
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c40
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c10
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_43xx_data.c100
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c14
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_7xx_data.c574
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.h1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c55
-rw-r--r--arch/arm/mach-omap2/pm24xx.c35
-rw-r--r--arch/arm/mach-omap2/pm34xx.c218
-rw-r--r--arch/arm/mach-omap2/prcm43xx.h1
-rw-r--r--arch/arm/mach-omap2/prm2xxx.c18
-rw-r--r--arch/arm/mach-omap2/prm2xxx.h1
-rw-r--r--arch/arm/mach-omap2/prm3xxx.c233
-rw-r--r--arch/arm/mach-omap2/prm3xxx.h6
-rw-r--r--arch/arm/mach-omap2/prm7xx.h4
-rw-r--r--arch/arm/mach-omap2/prm_common.c2
-rw-r--r--arch/arm/mach-omap2/sleep44xx.S3
-rw-r--r--arch/arm/mach-omap2/sram242x.S6
-rw-r--r--arch/arm/mach-omap2/sram243x.S6
-rw-r--r--arch/arm/mach-omap2/usb-tusb6010.c1
-rw-r--r--arch/arm/mach-pxa/Makefile2
-rw-r--r--arch/arm/mach-pxa/balloon3.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c2
-rw-r--r--arch/arm/mach-pxa/generic.c23
-rw-r--r--arch/arm/mach-pxa/include/mach/hardware.h4
-rw-r--r--arch/arm/mach-pxa/mioa701_bootresume.S2
-rw-r--r--arch/arm/mach-pxa/pxa25x.c7
-rw-r--r--arch/arm/mach-pxa/pxa27x.c10
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c2
-rw-r--r--arch/arm/mach-pxa/sleep.S2
-rw-r--r--arch/arm/mach-pxa/standby.S4
-rw-r--r--arch/arm/mach-pxa/time.c162
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-realview/core.c2
-rw-r--r--arch/arm/mach-realview/include/mach/memory.h9
-rw-r--r--arch/arm/mach-rockchip/Kconfig2
-rw-r--r--arch/arm/mach-rockchip/Makefile2
-rw-r--r--arch/arm/mach-rockchip/platsmp.c20
-rw-r--r--arch/arm/mach-rockchip/rockchip.c1
-rw-r--r--arch/arm/mach-rpc/include/mach/memory.h5
-rw-r--r--arch/arm/mach-s3c24xx/common.c2
-rw-r--r--arch/arm/mach-s3c24xx/iotiming-s3c2412.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-h1940.c5
-rw-r--r--arch/arm/mach-s3c24xx/mach-jive.c3
-rw-r--r--arch/arm/mach-s3c24xx/mach-smdk2413.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-smdk2416.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-smdk2443.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-vstms.c1
-rw-r--r--arch/arm/mach-s3c24xx/s3c2410.c6
-rw-r--r--arch/arm/mach-s3c24xx/s3c2412.c6
-rw-r--r--arch/arm/mach-s3c24xx/s3c2442.c1
-rw-r--r--arch/arm/mach-s3c24xx/s3c244x.c6
-rw-r--r--arch/arm/mach-s3c24xx/sleep-s3c2410.S2
-rw-r--r--arch/arm/mach-s3c24xx/sleep-s3c2412.S2
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-ncp.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6400.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c1
-rw-r--r--arch/arm/mach-s3c64xx/s3c6400.c1
-rw-r--r--arch/arm/mach-s3c64xx/s3c6410.c1
-rw-r--r--arch/arm/mach-s5p64x0/Kconfig102
-rw-r--r--arch/arm/mach-s5p64x0/Makefile36
-rw-r--r--arch/arm/mach-s5p64x0/Makefile.boot2
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c632
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c701
-rw-r--r--arch/arm/mach-s5p64x0/clock.c236
-rw-r--r--arch/arm/mach-s5p64x0/clock.h38
-rw-r--r--arch/arm/mach-s5p64x0/common.c490
-rw-r--r--arch/arm/mach-s5p64x0/common.h56
-rw-r--r--arch/arm/mach-s5p64x0/dev-audio.c176
-rw-r--r--arch/arm/mach-s5p64x0/dma.c128
-rw-r--r--arch/arm/mach-s5p64x0/i2c.h16
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/debug-macro.S32
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/gpio.h132
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/irqs.h148
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/map.h96
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/pm-core.h119
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-clock.h98
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-gpio.h68
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/regs-irq.h18
-rw-r--r--arch/arm/mach-s5p64x0/irq-pm.c98
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c280
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c299
-rw-r--r--arch/arm/mach-s5p64x0/pm.c202
-rw-r--r--arch/arm/mach-s5p64x0/setup-fb-24bpp.c29
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c0.c38
-rw-r--r--arch/arm/mach-s5p64x0/setup-i2c1.c38
-rw-r--r--arch/arm/mach-s5p64x0/setup-sdhci-gpio.c104
-rw-r--r--arch/arm/mach-s5p64x0/setup-spi.c38
-rw-r--r--arch/arm/mach-s5pc100/Kconfig81
-rw-r--r--arch/arm/mach-s5pc100/Makefile32
-rw-r--r--arch/arm/mach-s5pc100/Makefile.boot2
-rw-r--r--arch/arm/mach-s5pc100/clock.c1361
-rw-r--r--arch/arm/mach-s5pc100/common.c255
-rw-r--r--arch/arm/mach-s5pc100/common.h30
-rw-r--r--arch/arm/mach-s5pc100/dev-audio.c239
-rw-r--r--arch/arm/mach-s5pc100/dma.c130
-rw-r--r--arch/arm/mach-s5pc100/include/mach/debug-macro.S39
-rw-r--r--arch/arm/mach-s5pc100/include/mach/entry-macro.S19
-rw-r--r--arch/arm/mach-s5pc100/include/mach/gpio.h144
-rw-r--r--arch/arm/mach-s5pc100/include/mach/hardware.h14
-rw-r--r--arch/arm/mach-s5pc100/include/mach/irqs.h115
-rw-r--r--arch/arm/mach-s5pc100/include/mach/map.h137
-rw-r--r--arch/arm/mach-s5pc100/include/mach/regs-clock.h80
-rw-r--r--arch/arm/mach-s5pc100/include/mach/regs-gpio.h38
-rw-r--r--arch/arm/mach-s5pc100/include/mach/regs-irq.h18
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c264
-rw-r--r--arch/arm/mach-s5pc100/setup-fb-24bpp.c35
-rw-r--r--arch/arm/mach-s5pc100/setup-i2c0.c28
-rw-r--r--arch/arm/mach-s5pc100/setup-i2c1.c28
-rw-r--r--arch/arm/mach-s5pc100/setup-ide.c57
-rw-r--r--arch/arm/mach-s5pc100/setup-keypad.c23
-rw-r--r--arch/arm/mach-s5pc100/setup-sdhci-gpio.c70
-rw-r--r--arch/arm/mach-s5pc100/setup-spi.c41
-rw-r--r--arch/arm/mach-s5pv210/Kconfig197
-rw-r--r--arch/arm/mach-s5pv210/Makefile29
-rw-r--r--arch/arm/mach-s5pv210/Makefile.boot2
-rw-r--r--arch/arm/mach-s5pv210/clock.c1365
-rw-r--r--arch/arm/mach-s5pv210/common.c279
-rw-r--r--arch/arm/mach-s5pv210/common.h21
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c246
-rw-r--r--arch/arm/mach-s5pv210/dma.c130
-rw-r--r--arch/arm/mach-s5pv210/include/mach/gpio.h140
-rw-r--r--arch/arm/mach-s5pv210/include/mach/hardware.h18
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h137
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h158
-rw-r--r--arch/arm/mach-s5pv210/include/mach/memory.h27
-rw-r--r--arch/arm/mach-s5pv210/include/mach/pm-core.h46
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-clock.h2
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-gpio.h41
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-irq.h18
-rw-r--r--arch/arm/mach-s5pv210/mach-aquila.c687
-rw-r--r--arch/arm/mach-s5pv210/mach-goni.c916
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkc110.c159
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c337
-rw-r--r--arch/arm/mach-s5pv210/mach-torbreck.c135
-rw-r--r--arch/arm/mach-s5pv210/pm.c147
-rw-r--r--arch/arm/mach-s5pv210/s5pv210.c77
-rw-r--r--arch/arm/mach-s5pv210/setup-fb-24bpp.c49
-rw-r--r--arch/arm/mach-s5pv210/setup-fimc.c43
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c0.c28
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c1.c28
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c2.c28
-rw-r--r--arch/arm/mach-s5pv210/setup-ide.c39
-rw-r--r--arch/arm/mach-s5pv210/setup-keypad.c24
-rw-r--r--arch/arm/mach-s5pv210/setup-sdhci-gpio.c103
-rw-r--r--arch/arm/mach-s5pv210/setup-spi.c34
-rw-r--r--arch/arm/mach-s5pv210/setup-usb-phy.c95
-rw-r--r--arch/arm/mach-s5pv210/sleep.S (renamed from arch/arm/plat-samsung/s5p-sleep.S)19
-rw-r--r--arch/arm/mach-sa1100/include/mach/memory.h5
-rw-r--r--arch/arm/mach-shmobile/Kconfig26
-rw-r--r--arch/arm/mach-shmobile/Makefile23
-rw-r--r--arch/arm/mach-shmobile/Makefile.boot1
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm-reference.c6
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm.c22
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva-reference.c14
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c47
-rw-r--r--arch/arm/mach-shmobile/board-bockw-reference.c6
-rw-r--r--arch/arm/mach-shmobile/board-bockw.c27
-rw-r--r--arch/arm/mach-shmobile/board-genmai-reference.c10
-rw-r--r--arch/arm/mach-shmobile/board-genmai.c15
-rw-r--r--arch/arm/mach-shmobile/board-koelsch-reference.c28
-rw-r--r--arch/arm/mach-shmobile/board-koelsch.c37
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g-reference.c6
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c10
-rw-r--r--arch/arm/mach-shmobile/board-lager-reference.c29
-rw-r--r--arch/arm/mach-shmobile/board-lager.c56
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c16
-rw-r--r--arch/arm/mach-shmobile/board-marzen-reference.c32
-rw-r--r--arch/arm/mach-shmobile/board-marzen.c9
-rw-r--r--arch/arm/mach-shmobile/clock-r7s72100.c5
-rw-r--r--arch/arm/mach-shmobile/clock-r8a73a4.c11
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c28
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c12
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7779.c27
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7790.c8
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7791.c6
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c4
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c14
-rw-r--r--arch/arm/mach-shmobile/clock.c6
-rw-r--r--arch/arm/mach-shmobile/clock.h (renamed from arch/arm/mach-shmobile/include/mach/clock.h)0
-rw-r--r--arch/arm/mach-shmobile/common.h (renamed from arch/arm/mach-shmobile/include/mach/common.h)9
-rw-r--r--arch/arm/mach-shmobile/console.c2
-rw-r--r--arch/arm/mach-shmobile/cpufreq.c17
-rw-r--r--arch/arm/mach-shmobile/dma-register.h (renamed from arch/arm/mach-shmobile/include/mach/dma-register.h)0
-rw-r--r--arch/arm/mach-shmobile/headsmp.S16
-rw-r--r--arch/arm/mach-shmobile/include/mach/irqs.h16
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c5
-rw-r--r--arch/arm/mach-shmobile/intc-sh73a0.c9
-rw-r--r--arch/arm/mach-shmobile/intc.h (renamed from arch/arm/mach-shmobile/include/mach/intc.h)0
-rw-r--r--arch/arm/mach-shmobile/irqs.h21
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c71
-rw-r--r--arch/arm/mach-shmobile/platsmp-scu.c2
-rw-r--r--arch/arm/mach-shmobile/platsmp.c2
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7740.c4
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7779.c19
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7790.c45
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7791.c73
-rw-r--r--arch/arm/mach-shmobile/pm-rcar.c2
-rw-r--r--arch/arm/mach-shmobile/pm-rcar.h (renamed from arch/arm/mach-shmobile/include/mach/pm-rcar.h)0
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.c2
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.h (renamed from arch/arm/mach-shmobile/include/mach/pm-rmobile.h)0
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c8
-rw-r--r--arch/arm/mach-shmobile/pm-sh73a0.c2
-rw-r--r--arch/arm/mach-shmobile/r7s72100.h (renamed from arch/arm/mach-shmobile/include/mach/r7s72100.h)1
-rw-r--r--arch/arm/mach-shmobile/r8a73a4.h (renamed from arch/arm/mach-shmobile/include/mach/r8a73a4.h)0
-rw-r--r--arch/arm/mach-shmobile/r8a7740.h (renamed from arch/arm/mach-shmobile/include/mach/r8a7740.h)2
-rw-r--r--arch/arm/mach-shmobile/r8a7778.h (renamed from arch/arm/mach-shmobile/include/mach/r8a7778.h)0
-rw-r--r--arch/arm/mach-shmobile/r8a7779.h (renamed from arch/arm/mach-shmobile/include/mach/r8a7779.h)14
-rw-r--r--arch/arm/mach-shmobile/r8a7790.h (renamed from arch/arm/mach-shmobile/include/mach/r8a7790.h)3
-rw-r--r--arch/arm/mach-shmobile/r8a7791.h (renamed from arch/arm/mach-shmobile/include/mach/r8a7791.h)1
-rw-r--r--arch/arm/mach-shmobile/rcar-gen2.h (renamed from arch/arm/mach-shmobile/include/mach/rcar-gen2.h)1
-rw-r--r--arch/arm/mach-shmobile/setup-emev2.c19
-rw-r--r--arch/arm/mach-shmobile/setup-r7s72100.c17
-rw-r--r--arch/arm/mach-shmobile/setup-r8a73a4.c30
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c20
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7778.c33
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c59
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7790.c32
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7791.c20
-rw-r--r--arch/arm/mach-shmobile/setup-rcar-gen2.c76
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c12
-rw-r--r--arch/arm/mach-shmobile/setup-sh73a0.c19
-rw-r--r--arch/arm/mach-shmobile/sh7372.h (renamed from arch/arm/mach-shmobile/include/mach/sh7372.h)4
-rw-r--r--arch/arm/mach-shmobile/sh73a0.h (renamed from arch/arm/mach-shmobile/include/mach/sh73a0.h)0
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c2
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c8
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7790.c36
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7791.c30
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c6
-rw-r--r--arch/arm/mach-shmobile/timer.c50
-rw-r--r--arch/arm/mach-spear/Kconfig4
-rw-r--r--arch/arm/mach-spear/include/mach/spear.h4
-rw-r--r--arch/arm/mach-spear/spear1310.c2
-rw-r--r--arch/arm/mach-spear/spear1340.c125
-rw-r--r--arch/arm/mach-spear/spear13xx.c4
-rw-r--r--arch/arm/mach-sti/platsmp.c6
-rw-r--r--arch/arm/mach-sunxi/Kconfig9
-rw-r--r--arch/arm/mach-sunxi/sunxi.c9
-rw-r--r--arch/arm/mach-tegra/Makefile7
-rw-r--r--arch/arm/mach-tegra/apbio.c206
-rw-r--r--arch/arm/mach-tegra/apbio.h22
-rw-r--r--arch/arm/mach-tegra/board-paz00.c3
-rw-r--r--arch/arm/mach-tegra/board.h7
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra114.c10
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c16
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c10
-rw-r--r--arch/arm/mach-tegra/cpuidle.c7
-rw-r--r--arch/arm/mach-tegra/flowctrl.c11
-rw-r--r--arch/arm/mach-tegra/fuse.c252
-rw-r--r--arch/arm/mach-tegra/fuse.h79
-rw-r--r--arch/arm/mach-tegra/hotplug.c30
-rw-r--r--arch/arm/mach-tegra/io.c8
-rw-r--r--arch/arm/mach-tegra/irq.c8
-rw-r--r--arch/arm/mach-tegra/platsmp.c29
-rw-r--r--arch/arm/mach-tegra/pm-tegra20.c1
-rw-r--r--arch/arm/mach-tegra/pm-tegra30.c1
-rw-r--r--arch/arm/mach-tegra/pm.c63
-rw-r--r--arch/arm/mach-tegra/pm.h10
-rw-r--r--arch/arm/mach-tegra/pmc.c413
-rw-r--r--arch/arm/mach-tegra/pmc.h49
-rw-r--r--arch/arm/mach-tegra/powergate.c515
-rw-r--r--arch/arm/mach-tegra/reset-handler.S7
-rw-r--r--arch/arm/mach-tegra/reset.c19
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S24
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S21
-rw-r--r--arch/arm/mach-tegra/sleep.S8
-rw-r--r--arch/arm/mach-tegra/sleep.h3
-rw-r--r--arch/arm/mach-tegra/tegra.c37
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.c2
-rw-r--r--arch/arm/mach-ux500/cache-l2x0.c18
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c8
-rw-r--r--arch/arm/mach-ux500/cpu.c2
-rw-r--r--arch/arm/mach-ux500/timer.c2
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--arch/arm/mach-versatile/versatile_dt.c1
-rw-r--r--arch/arm/mach-vexpress/Kconfig2
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c3
-rw-r--r--arch/arm/mach-vexpress/tc2_pm.c19
-rw-r--r--arch/arm/mach-vt8500/vt8500.c6
-rw-r--r--arch/arm/mach-w90x900/cpu.c3
-rw-r--r--arch/arm/mach-zynq/Kconfig1
-rw-r--r--arch/arm/mm/Kconfig11
-rw-r--r--arch/arm/mm/alignment.c4
-rw-r--r--arch/arm/mm/cache-fa.S19
-rw-r--r--arch/arm/mm/cache-l2x0.c2
-rw-r--r--arch/arm/mm/cache-nop.S5
-rw-r--r--arch/arm/mm/cache-v4.S13
-rw-r--r--arch/arm/mm/cache-v4wb.S15
-rw-r--r--arch/arm/mm/cache-v4wt.S13
-rw-r--r--arch/arm/mm/cache-v6.S20
-rw-r--r--arch/arm/mm/cache-v7.S30
-rw-r--r--arch/arm/mm/dma-mapping.c1
-rw-r--r--arch/arm/mm/dump.c4
-rw-r--r--arch/arm/mm/l2c-l2x0-resume.S7
-rw-r--r--arch/arm/mm/mmu.c45
-rw-r--r--arch/arm/mm/proc-arm1020.S34
-rw-r--r--arch/arm/mm/proc-arm1020e.S34
-rw-r--r--arch/arm/mm/proc-arm1022.S34
-rw-r--r--arch/arm/mm/proc-arm1026.S34
-rw-r--r--arch/arm/mm/proc-arm720.S16
-rw-r--r--arch/arm/mm/proc-arm740.S8
-rw-r--r--arch/arm/mm/proc-arm7tdmi.S8
-rw-r--r--arch/arm/mm/proc-arm920.S34
-rw-r--r--arch/arm/mm/proc-arm922.S34
-rw-r--r--arch/arm/mm/proc-arm925.S34
-rw-r--r--arch/arm/mm/proc-arm926.S34
-rw-r--r--arch/arm/mm/proc-arm940.S24
-rw-r--r--arch/arm/mm/proc-arm946.S30
-rw-r--r--arch/arm/mm/proc-arm9tdmi.S8
-rw-r--r--arch/arm/mm/proc-fa526.S16
-rw-r--r--arch/arm/mm/proc-feroceon.S44
-rw-r--r--arch/arm/mm/proc-mohawk.S34
-rw-r--r--arch/arm/mm/proc-sa110.S16
-rw-r--r--arch/arm/mm/proc-sa1100.S16
-rw-r--r--arch/arm/mm/proc-v6.S16
-rw-r--r--arch/arm/mm/proc-v7-2level.S4
-rw-r--r--arch/arm/mm/proc-v7-3level.S21
-rw-r--r--arch/arm/mm/proc-v7.S74
-rw-r--r--arch/arm/mm/proc-v7m.S18
-rw-r--r--arch/arm/mm/proc-xsc3.S32
-rw-r--r--arch/arm/mm/proc-xscale.S34
-rw-r--r--arch/arm/mm/tlb-fa.S7
-rw-r--r--arch/arm/mm/tlb-v4.S5
-rw-r--r--arch/arm/mm/tlb-v4wb.S7
-rw-r--r--arch/arm/mm/tlb-v4wbi.S7
-rw-r--r--arch/arm/mm/tlb-v6.S5
-rw-r--r--arch/arm/mm/tlb-v7.S4
-rw-r--r--arch/arm/net/bpf_jit_32.c8
-rw-r--r--arch/arm/nwfpe/entry.S8
-rw-r--r--arch/arm/oprofile/common.c19
-rw-r--r--arch/arm/plat-omap/dma.c7
-rw-r--r--arch/arm/plat-samsung/Kconfig163
-rw-r--r--arch/arm/plat-samsung/Makefile15
-rw-r--r--arch/arm/plat-samsung/adc.c2
-rw-r--r--arch/arm/plat-samsung/clock-clksrc.c212
-rw-r--r--arch/arm/plat-samsung/clock.c539
-rw-r--r--arch/arm/plat-samsung/cpu.c3
-rw-r--r--arch/arm/plat-samsung/devs.c330
-rw-r--r--arch/arm/plat-samsung/include/plat/camport.h28
-rw-r--r--arch/arm/plat-samsung/include/plat/clock-clksrc.h83
-rw-r--r--arch/arm/plat-samsung/include/plat/clock.h152
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu-freq-core.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h42
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h59
-rw-r--r--arch/arm/plat-samsung/include/plat/fb-core.h15
-rw-r--r--arch/arm/plat-samsung/include/plat/fb.h36
-rw-r--r--arch/arm/plat-samsung/include/plat/fimc-core.h51
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg.h64
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-core.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/hdmi.h16
-rw-r--r--arch/arm/plat-samsung/include/plat/irqs.h72
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/mfc.h35
-rw-r--r--arch/arm/plat-samsung/include/plat/pll.h323
-rw-r--r--arch/arm/plat-samsung/include/plat/s5p-clock.h65
-rw-r--r--arch/arm/plat-samsung/include/plat/sdhci.h124
-rw-r--r--arch/arm/plat-samsung/include/plat/tv-core.h44
-rw-r--r--arch/arm/plat-samsung/init.c1
-rw-r--r--arch/arm/plat-samsung/pm-gpio.c6
-rw-r--r--arch/arm/plat-samsung/s5p-clock.c294
-rw-r--r--arch/arm/plat-samsung/s5p-dev-mfc.c81
-rw-r--r--arch/arm/plat-samsung/s5p-dev-uart.c88
-rw-r--r--arch/arm/plat-samsung/s5p-irq-eint.c221
-rw-r--r--arch/arm/plat-samsung/s5p-irq-gpioint.c218
-rw-r--r--arch/arm/plat-samsung/s5p-irq-pm.c92
-rw-r--r--arch/arm/plat-samsung/s5p-irq.c31
-rw-r--r--arch/arm/plat-samsung/s5p-pm.c40
-rw-r--r--arch/arm/plat-versatile/Kconfig3
-rw-r--r--arch/arm/plat-versatile/Makefile1
-rw-r--r--arch/arm/plat-versatile/include/plat/clcd.h9
-rw-r--r--arch/arm/vfp/entry.S4
-rw-r--r--arch/arm/vfp/vfphw.S26
-rw-r--r--arch/arm/xen/enlighten.c6
-rw-r--r--arch/arm/xen/grant-table.c9
-rw-r--r--arch/arm/xen/hypercall.S6
-rw-r--r--arch/arm64/Kconfig64
-rw-r--r--arch/arm64/Kconfig.debug15
-rw-r--r--arch/arm64/Makefile5
-rw-r--r--arch/arm64/boot/dts/apm-mustang.dts4
-rw-r--r--arch/arm64/boot/dts/apm-storm.dtsi30
-rw-r--r--arch/arm64/configs/defconfig7
-rw-r--r--arch/arm64/crypto/Makefile2
-rw-r--r--arch/arm64/include/asm/cacheflush.h11
-rw-r--r--arch/arm64/include/asm/cachetype.h16
-rw-r--r--arch/arm64/include/asm/cpu.h59
-rw-r--r--arch/arm64/include/asm/cputype.h35
-rw-r--r--arch/arm64/include/asm/debug-monitors.h19
-rw-r--r--arch/arm64/include/asm/efi.h33
-rw-r--r--arch/arm64/include/asm/fpsimdmacros.h17
-rw-r--r--arch/arm64/include/asm/kvm_arm.h5
-rw-r--r--arch/arm64/include/asm/kvm_asm.h53
-rw-r--r--arch/arm64/include/asm/kvm_coproc.h3
-rw-r--r--arch/arm64/include/asm/kvm_emulate.h22
-rw-r--r--arch/arm64/include/asm/kvm_host.h48
-rw-r--r--arch/arm64/include/asm/kvm_mmu.h15
-rw-r--r--arch/arm64/include/asm/memory.h6
-rw-r--r--arch/arm64/include/asm/page.h23
-rw-r--r--arch/arm64/include/asm/pgalloc.h24
-rw-r--r--arch/arm64/include/asm/pgtable-2level-hwdef.h43
-rw-r--r--arch/arm64/include/asm/pgtable-2level-types.h62
-rw-r--r--arch/arm64/include/asm/pgtable-3level-hwdef.h50
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h42
-rw-r--r--arch/arm64/include/asm/pgtable-types.h (renamed from arch/arm64/include/asm/pgtable-3level-types.h)73
-rw-r--r--arch/arm64/include/asm/pgtable.h100
-rw-r--r--arch/arm64/include/asm/processor.h5
-rw-r--r--arch/arm64/include/asm/signal32.h11
-rw-r--r--arch/arm64/include/asm/stackprotector.h38
-rw-r--r--arch/arm64/include/asm/syscall.h14
-rw-r--r--arch/arm64/include/asm/sysreg.h60
-rw-r--r--arch/arm64/include/asm/thread_info.h5
-rw-r--r--arch/arm64/include/asm/tlb.h11
-rw-r--r--arch/arm64/include/asm/tlbflush.h34
-rw-r--r--arch/arm64/include/asm/unistd.h17
-rw-r--r--arch/arm64/include/asm/unistd32.h1166
-rw-r--r--arch/arm64/include/asm/virt.h4
-rw-r--r--arch/arm64/kernel/Makefile6
-rw-r--r--arch/arm64/kernel/asm-offsets.c26
-rw-r--r--arch/arm64/kernel/cpu_ops.c2
-rw-r--r--arch/arm64/kernel/cpuinfo.c192
-rw-r--r--arch/arm64/kernel/debug-monitors.c31
-rw-r--r--arch/arm64/kernel/efi-stub.c48
-rw-r--r--arch/arm64/kernel/efi.c42
-rw-r--r--arch/arm64/kernel/entry-fpsimd.S2
-rw-r--r--arch/arm64/kernel/entry-ftrace.S5
-rw-r--r--arch/arm64/kernel/entry.S56
-rw-r--r--arch/arm64/kernel/head.S121
-rw-r--r--arch/arm64/kernel/hyp-stub.S1
-rw-r--r--arch/arm64/kernel/image.h62
-rw-r--r--arch/arm64/kernel/kuser32.S2
-rw-r--r--arch/arm64/kernel/process.c6
-rw-r--r--arch/arm64/kernel/psci.c8
-rw-r--r--arch/arm64/kernel/ptrace.c11
-rw-r--r--arch/arm64/kernel/setup.c47
-rw-r--r--arch/arm64/kernel/signal.c58
-rw-r--r--arch/arm64/kernel/signal32.c26
-rw-r--r--arch/arm64/kernel/smp.c71
-rw-r--r--arch/arm64/kernel/suspend.c2
-rw-r--r--arch/arm64/kernel/sys_compat.c2
-rw-r--r--arch/arm64/kernel/topology.c47
-rw-r--r--arch/arm64/kernel/traps.c13
-rw-r--r--arch/arm64/kernel/vdso.c121
-rw-r--r--arch/arm64/kernel/vdso/Makefile6
-rw-r--r--arch/arm64/kernel/vdso/vdso.lds.S4
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S16
-rw-r--r--arch/arm64/kvm/Makefile4
-rw-r--r--arch/arm64/kvm/guest.c68
-rw-r--r--arch/arm64/kvm/handle_exit.c4
-rw-r--r--arch/arm64/kvm/hyp.S600
-rw-r--r--arch/arm64/kvm/sys_regs.c546
-rw-r--r--arch/arm64/kvm/vgic-v2-switch.S133
-rw-r--r--arch/arm64/kvm/vgic-v3-switch.S267
-rw-r--r--arch/arm64/mm/fault.c1
-rw-r--r--arch/arm64/mm/init.c34
-rw-r--r--arch/arm64/mm/ioremap.c30
-rw-r--r--arch/arm64/mm/mmu.c14
-rw-r--r--arch/avr32/boards/atngw100/mrmt.c34
-rw-r--r--arch/avr32/boards/favr-32/setup.c48
-rw-r--r--arch/avr32/boards/hammerhead/flash.c11
-rw-r--r--arch/avr32/boards/merisc/setup.c34
-rw-r--r--arch/avr32/configs/atngw100_mrmt_defconfig5
-rw-r--r--arch/avr32/configs/atstk1002_defconfig5
-rw-r--r--arch/avr32/configs/atstk1003_defconfig5
-rw-r--r--arch/avr32/configs/atstk1004_defconfig5
-rw-r--r--arch/avr32/configs/atstk1006_defconfig5
-rw-r--r--arch/avr32/configs/favr-32_defconfig6
-rw-r--r--arch/avr32/configs/merisc_defconfig5
-rw-r--r--arch/avr32/include/asm/processor.h1
-rw-r--r--arch/avr32/kernel/signal.c50
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c7
-rw-r--r--arch/blackfin/Kconfig1
-rw-r--r--arch/blackfin/include/asm/processor.h2
-rw-r--r--arch/blackfin/kernel/ftrace-entry.S18
-rw-r--r--arch/blackfin/kernel/perf_event.c15
-rw-r--r--arch/blackfin/kernel/signal.c51
-rw-r--r--arch/c6x/include/asm/processor.h1
-rw-r--r--arch/c6x/kernel/signal.c53
-rw-r--r--arch/cris/arch-v10/kernel/signal.c89
-rw-r--r--arch/cris/arch-v32/kernel/signal.c89
-rw-r--r--arch/cris/include/asm/Kbuild1
-rw-r--r--arch/cris/include/asm/processor.h1
-rw-r--r--arch/cris/include/asm/scatterlist.h6
-rw-r--r--arch/frv/include/asm/Kbuild1
-rw-r--r--arch/frv/include/asm/scatterlist.h6
-rw-r--r--arch/frv/kernel/signal.c112
-rw-r--r--arch/hexagon/Kconfig1
-rw-r--r--arch/hexagon/include/asm/cache.h2
-rw-r--r--arch/hexagon/include/asm/processor.h1
-rw-r--r--arch/hexagon/kernel/signal.c57
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/Makefile2
-rw-r--r--arch/ia64/include/asm/Kbuild1
-rw-r--r--arch/ia64/include/asm/acenv.h4
-rw-r--r--arch/ia64/include/asm/acpi.h5
-rw-r--r--arch/ia64/include/asm/io.h1
-rw-r--r--arch/ia64/include/asm/page.h2
-rw-r--r--arch/ia64/include/asm/processor.h1
-rw-r--r--arch/ia64/include/asm/scatterlist.h7
-rw-r--r--arch/ia64/include/asm/unistd.h2
-rw-r--r--arch/ia64/include/uapi/asm/unistd.h1
-rw-r--r--arch/ia64/kernel/entry.S1
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ia64/kernel/signal.c46
-rw-r--r--arch/ia64/kernel/time.c19
-rw-r--r--arch/ia64/kvm/Kconfig1
-rw-r--r--arch/ia64/kvm/kvm-ia64.c2
-rw-r--r--arch/ia64/mm/init.c34
-rw-r--r--arch/ia64/pci/fixup.c22
-rw-r--r--arch/ia64/sn/kernel/bte.c4
-rw-r--r--arch/ia64/sn/kernel/setup.c2
-rw-r--r--arch/m32r/include/asm/Kbuild1
-rw-r--r--arch/m32r/include/asm/processor.h1
-rw-r--r--arch/m32r/include/asm/scatterlist.h6
-rw-r--r--arch/m32r/kernel/signal.c57
-rw-r--r--arch/m68k/Kconfig2
-rw-r--r--arch/m68k/configs/amiga_defconfig1
-rw-r--r--arch/m68k/configs/apollo_defconfig1
-rw-r--r--arch/m68k/configs/atari_defconfig1
-rw-r--r--arch/m68k/configs/bvme6000_defconfig1
-rw-r--r--arch/m68k/configs/hp300_defconfig1
-rw-r--r--arch/m68k/configs/mac_defconfig1
-rw-r--r--arch/m68k/configs/multi_defconfig1
-rw-r--r--arch/m68k/configs/mvme147_defconfig1
-rw-r--r--arch/m68k/configs/mvme16x_defconfig1
-rw-r--r--arch/m68k/configs/q40_defconfig1
-rw-r--r--arch/m68k/configs/sun3_defconfig1
-rw-r--r--arch/m68k/configs/sun3x_defconfig1
-rw-r--r--arch/m68k/include/asm/pgtable_no.h5
-rw-r--r--arch/m68k/include/asm/processor.h1
-rw-r--r--arch/m68k/include/asm/sun3_pgalloc.h4
-rw-r--r--arch/m68k/include/asm/virtconvert.h6
-rw-r--r--arch/m68k/kernel/signal.c75
-rw-r--r--arch/metag/Kconfig1
-rw-r--r--arch/metag/include/asm/processor.h1
-rw-r--r--arch/metag/kernel/cachepart.c4
-rw-r--r--arch/metag/kernel/ftrace_stub.S14
-rw-r--r--arch/metag/kernel/perf/perf_event.c19
-rw-r--r--arch/metag/kernel/signal.c10
-rw-r--r--arch/metag/mm/hugetlbpage.c2
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/include/asm/Kbuild1
-rw-r--r--arch/microblaze/include/asm/delay.h28
-rw-r--r--arch/microblaze/include/asm/processor.h1
-rw-r--r--arch/microblaze/include/asm/scatterlist.h1
-rw-r--r--arch/microblaze/include/uapi/asm/unistd.h1
-rw-r--r--arch/microblaze/kernel/ftrace.c3
-rw-r--r--arch/microblaze/kernel/mcount.S5
-rw-r--r--arch/microblaze/kernel/signal.c55
-rw-r--r--arch/microblaze/kernel/syscall_table.S3
-rw-r--r--arch/microblaze/lib/Makefile14
-rw-r--r--arch/mips/Kconfig12
-rw-r--r--arch/mips/Makefile4
-rw-r--r--arch/mips/alchemy/board-mtx1.c4
-rw-r--r--arch/mips/alchemy/board-xxs1500.c4
-rw-r--r--arch/mips/alchemy/common/Makefile4
-rw-r--r--arch/mips/alchemy/common/clock.c1094
-rw-r--r--arch/mips/alchemy/common/clocks.c105
-rw-r--r--arch/mips/alchemy/common/dbdma.c22
-rw-r--r--arch/mips/alchemy/common/dma.c15
-rw-r--r--arch/mips/alchemy/common/irq.c5
-rw-r--r--arch/mips/alchemy/common/platform.c15
-rw-r--r--arch/mips/alchemy/common/power.c74
-rw-r--r--arch/mips/alchemy/common/setup.c15
-rw-r--r--arch/mips/alchemy/common/time.c23
-rw-r--r--arch/mips/alchemy/common/usb.c47
-rw-r--r--arch/mips/alchemy/devboards/db1000.c19
-rw-r--r--arch/mips/alchemy/devboards/db1200.c61
-rw-r--r--arch/mips/alchemy/devboards/db1300.c9
-rw-r--r--arch/mips/alchemy/devboards/db1550.c27
-rw-r--r--arch/mips/alchemy/devboards/pm.c39
-rw-r--r--arch/mips/bcm47xx/Kconfig5
-rw-r--r--arch/mips/bcm47xx/bcm47xx_private.h3
-rw-r--r--arch/mips/bcm47xx/board.c26
-rw-r--r--arch/mips/bcm47xx/buttons.c38
-rw-r--r--arch/mips/bcm47xx/leds.c92
-rw-r--r--arch/mips/bcm47xx/prom.c68
-rw-r--r--arch/mips/bcm47xx/setup.c7
-rw-r--r--arch/mips/bcm47xx/sprom.c48
-rw-r--r--arch/mips/bcm63xx/cpu.c11
-rw-r--r--arch/mips/bcm63xx/dev-enet.c4
-rw-r--r--arch/mips/bcm63xx/dev-spi.c4
-rw-r--r--arch/mips/bcm63xx/gpio.c14
-rw-r--r--arch/mips/bcm63xx/irq.c558
-rw-r--r--arch/mips/bcm63xx/reset.c60
-rw-r--r--arch/mips/boot/compressed/decompress.c14
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c22
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c12
-rw-r--r--arch/mips/cavium-octeon/oct_ilm.c3
-rw-r--r--arch/mips/cavium-octeon/smp.c23
-rw-r--r--arch/mips/configs/cavium_octeon_defconfig1
-rw-r--r--arch/mips/configs/db1xxx_defconfig1
-rw-r--r--arch/mips/configs/decstation_defconfig1
-rw-r--r--arch/mips/configs/ip22_defconfig1
-rw-r--r--arch/mips/configs/ip27_defconfig1
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/jazz_defconfig1
-rw-r--r--arch/mips/configs/loongson3_defconfig3
-rw-r--r--arch/mips/configs/malta_defconfig1
-rw-r--r--arch/mips/configs/malta_kvm_defconfig1
-rw-r--r--arch/mips/configs/malta_kvm_guest_defconfig1
-rw-r--r--arch/mips/configs/markeins_defconfig1
-rw-r--r--arch/mips/configs/nlm_xlp_defconfig3
-rw-r--r--arch/mips/configs/nlm_xlr_defconfig3
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/tb0226_defconfig1
-rw-r--r--arch/mips/configs/tb0287_defconfig1
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/mips/include/asm/abi.h10
-rw-r--r--arch/mips/include/asm/addrspace.h2
-rw-r--r--arch/mips/include/asm/asmmacro.h31
-rw-r--r--arch/mips/include/asm/bitops.h8
-rw-r--r--arch/mips/include/asm/cop2.h8
-rw-r--r--arch/mips/include/asm/cpu-features.h9
-rw-r--r--arch/mips/include/asm/cpu-info.h5
-rw-r--r--arch/mips/include/asm/cpu.h61
-rw-r--r--arch/mips/include/asm/elf.h17
-rw-r--r--arch/mips/include/asm/fpu.h19
-rw-r--r--arch/mips/include/asm/gic.h41
-rw-r--r--arch/mips/include/asm/kvm_host.h12
-rw-r--r--arch/mips/include/asm/maar.h109
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h1529
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000_dma.h50
-rw-r--r--arch/mips/include/asm/mach-au1x00/gpio-au1000.h56
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h7
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h198
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h46
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h31
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h16
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-loongson/boot_param.h4
-rw-r--r--arch/mips/include/asm/mach-loongson/kernel-entry-init.h52
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h11
-rw-r--r--arch/mips/include/asm/mach-loongson/machine.h4
-rw-r--r--arch/mips/include/asm/mach-loongson/mmzone.h53
-rw-r--r--arch/mips/include/asm/mach-loongson/topology.h23
-rw-r--r--arch/mips/include/asm/mach-malta/irq.h1
-rw-r--r--arch/mips/include/asm/mach-sead3/irq.h1
-rw-r--r--arch/mips/include/asm/mips-boards/bonito64.h1
-rw-r--r--arch/mips/include/asm/mipsregs.h58
-rw-r--r--arch/mips/include/asm/mmu_context.h10
-rw-r--r--arch/mips/include/asm/msa.h31
-rw-r--r--arch/mips/include/asm/octeon/cvmx-bootinfo.h2
-rw-r--r--arch/mips/include/asm/pgtable-32.h12
-rw-r--r--arch/mips/include/asm/pgtable.h27
-rw-r--r--arch/mips/include/asm/processor.h11
-rw-r--r--arch/mips/include/asm/ptrace.h8
-rw-r--r--arch/mips/include/asm/r4kcache.h3
-rw-r--r--arch/mips/include/asm/reg.h129
-rw-r--r--arch/mips/include/asm/smp-cps.h12
-rw-r--r--arch/mips/include/asm/smp.h6
-rw-r--r--arch/mips/include/asm/sparsemem.h2
-rw-r--r--arch/mips/include/asm/user.h58
-rw-r--r--arch/mips/include/uapi/asm/ptrace.h25
-rw-r--r--arch/mips/include/uapi/asm/reg.h206
-rw-r--r--arch/mips/include/uapi/asm/unistd.h15
-rw-r--r--arch/mips/jz4740/board-qi_lb60.c1
-rw-r--r--arch/mips/jz4740/clock-debugfs.c3
-rw-r--r--arch/mips/jz4740/platform.c2
-rw-r--r--arch/mips/kernel/asm-offsets.c1
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c38
-rw-r--r--arch/mips/kernel/cpu-probe.c45
-rw-r--r--arch/mips/kernel/ftrace.c59
-rw-r--r--arch/mips/kernel/irq-gic.c38
-rw-r--r--arch/mips/kernel/mcount.S20
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c42
-rw-r--r--arch/mips/kernel/pm-cps.c10
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/process.c60
-rw-r--r--arch/mips/kernel/ptrace.c223
-rw-r--r--arch/mips/kernel/ptrace32.c10
-rw-r--r--arch/mips/kernel/r4k_switch.S9
-rw-r--r--arch/mips/kernel/rtlx-cmp.c3
-rw-r--r--arch/mips/kernel/rtlx-mt.c3
-rw-r--r--arch/mips/kernel/scall32-o32.S7
-rw-r--r--arch/mips/kernel/scall64-64.S5
-rw-r--r--arch/mips/kernel/scall64-n32.S13
-rw-r--r--arch/mips/kernel/scall64-o32.S9
-rw-r--r--arch/mips/kernel/setup.c22
-rw-r--r--arch/mips/kernel/signal-common.h2
-rw-r--r--arch/mips/kernel/signal.c72
-rw-r--r--arch/mips/kernel/signal32.c39
-rw-r--r--arch/mips/kernel/signal_n32.c20
-rw-r--r--arch/mips/kernel/smp-cps.c12
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smp.c26
-rw-r--r--arch/mips/kernel/traps.c61
-rw-r--r--arch/mips/kernel/unaligned.c1
-rw-r--r--arch/mips/kvm/Makefile8
-rw-r--r--arch/mips/kvm/callback.c (renamed from arch/mips/kvm/kvm_cb.c)0
-rw-r--r--arch/mips/kvm/commpage.c33
-rw-r--r--arch/mips/kvm/commpage.h24
-rw-r--r--arch/mips/kvm/dyntrans.c (renamed from arch/mips/kvm/kvm_mips_dyntrans.c)40
-rw-r--r--arch/mips/kvm/emulate.c (renamed from arch/mips/kvm/kvm_mips_emul.c)539
-rw-r--r--arch/mips/kvm/interrupt.c (renamed from arch/mips/kvm/kvm_mips_int.c)47
-rw-r--r--arch/mips/kvm/interrupt.h (renamed from arch/mips/kvm/kvm_mips_int.h)22
-rw-r--r--arch/mips/kvm/kvm_mips_comm.h23
-rw-r--r--arch/mips/kvm/kvm_mips_commpage.c37
-rw-r--r--arch/mips/kvm/kvm_mips_opcode.h24
-rw-r--r--arch/mips/kvm/locore.S (renamed from arch/mips/kvm/kvm_locore.S)55
-rw-r--r--arch/mips/kvm/mips.c (renamed from arch/mips/kvm/kvm_mips.c)226
-rw-r--r--arch/mips/kvm/opcode.h22
-rw-r--r--arch/mips/kvm/stats.c (renamed from arch/mips/kvm/kvm_mips_stats.c)28
-rw-r--r--arch/mips/kvm/tlb.c (renamed from arch/mips/kvm/kvm_tlb.c)258
-rw-r--r--arch/mips/kvm/trace.h18
-rw-r--r--arch/mips/kvm/trap_emul.c (renamed from arch/mips/kvm/kvm_trap_emul.c)112
-rw-r--r--arch/mips/loongson/Kconfig9
-rw-r--r--arch/mips/loongson/Platform2
-rw-r--r--arch/mips/loongson/common/env.c49
-rw-r--r--arch/mips/loongson/common/init.c4
-rw-r--r--arch/mips/loongson/common/pm.c8
-rw-r--r--arch/mips/loongson/lemote-2f/clock.c4
-rw-r--r--arch/mips/loongson/lemote-2f/reset.c2
-rw-r--r--arch/mips/loongson/loongson-3/Makefile4
-rw-r--r--arch/mips/loongson/loongson-3/cop2-ex.c63
-rw-r--r--arch/mips/loongson/loongson-3/irq.c26
-rw-r--r--arch/mips/loongson/loongson-3/numa.c291
-rw-r--r--arch/mips/loongson/loongson-3/smp.c387
-rw-r--r--arch/mips/loongson/loongson-3/smp.h37
-rw-r--r--arch/mips/math-emu/cp1emu.c2
-rw-r--r--arch/mips/mm/c-r4k.c8
-rw-r--r--arch/mips/mm/init.c33
-rw-r--r--arch/mips/mm/tlb-r3k.c2
-rw-r--r--arch/mips/mm/tlb-r4k.c59
-rw-r--r--arch/mips/mm/tlbex.c98
-rw-r--r--arch/mips/mti-malta/malta-int.c27
-rw-r--r--arch/mips/mti-malta/malta-memory.c26
-rw-r--r--arch/mips/net/bpf_jit.c8
-rw-r--r--arch/mips/pci/Makefile2
-rw-r--r--arch/mips/pci/ops-tx4927.c2
-rw-r--r--arch/mips/pci/pci-alchemy.c24
-rw-r--r--arch/mips/ralink/of.c2
-rw-r--r--arch/mips/rb532/devices.c28
-rw-r--r--arch/mips/sgi-ip22/ip22-gio.c10
-rw-r--r--arch/mips/txx9/generic/7segled.c14
-rw-r--r--arch/mips/txx9/generic/pci.c4
-rw-r--r--arch/mips/txx9/generic/setup.c29
-rw-r--r--arch/mn10300/include/asm/Kbuild1
-rw-r--r--arch/mn10300/include/asm/processor.h2
-rw-r--r--arch/mn10300/include/asm/scatterlist.h16
-rw-r--r--arch/mn10300/kernel/signal.c102
-rw-r--r--arch/openrisc/Kconfig1
-rw-r--r--arch/openrisc/include/asm/irq.h3
-rw-r--r--arch/openrisc/include/asm/processor.h1
-rw-r--r--arch/openrisc/kernel/irq.c146
-rw-r--r--arch/openrisc/kernel/signal.c20
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/configs/generic-64bit_defconfig1
-rw-r--r--arch/parisc/include/asm/processor.h1
-rw-r--r--arch/parisc/kernel/ftrace.c6
-rw-r--r--arch/parisc/kernel/signal.c58
-rw-r--r--arch/powerpc/Kconfig3
-rw-r--r--arch/powerpc/Kconfig.debug4
-rw-r--r--arch/powerpc/boot/dts/fsl/p2041si-post.dtsi1
-rw-r--r--arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/t2080si-post.dtsi69
-rw-r--r--arch/powerpc/boot/dts/fsl/t2081si-post.dtsi435
-rw-r--r--arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi99
-rw-r--r--arch/powerpc/boot/dts/fsl/t4240si-post.dtsi1
-rw-r--r--arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi1
-rw-r--r--arch/powerpc/boot/dts/mpc5121.dtsi1
-rw-r--r--arch/powerpc/boot/dts/t2080qds.dts57
-rw-r--r--arch/powerpc/boot/dts/t2080rdb.dts57
-rw-r--r--arch/powerpc/boot/dts/t2081qds.dts46
-rw-r--r--arch/powerpc/boot/dts/t208xqds.dtsi239
-rw-r--r--arch/powerpc/boot/dts/t208xrdb.dtsi184
-rw-r--r--arch/powerpc/boot/dts/t4240rdb.dts186
-rw-r--r--arch/powerpc/boot/gunzip_util.c4
-rw-r--r--arch/powerpc/boot/io.h2
-rw-r--r--arch/powerpc/configs/52xx/motionpro_defconfig1
-rw-r--r--arch/powerpc/configs/85xx/kmp204x_defconfig1
-rw-r--r--arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig1
-rw-r--r--arch/powerpc/configs/corenet32_smp_defconfig4
-rw-r--r--arch/powerpc/configs/corenet64_smp_defconfig5
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig1
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig3
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig3
-rw-r--r--arch/powerpc/configs/ppc44x_defconfig1
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig2
-rw-r--r--arch/powerpc/include/asm/Kbuild1
-rw-r--r--arch/powerpc/include/asm/asm-compat.h4
-rw-r--r--arch/powerpc/include/asm/cache.h7
-rw-r--r--arch/powerpc/include/asm/cputable.h33
-rw-r--r--arch/powerpc/include/asm/eeh.h62
-rw-r--r--arch/powerpc/include/asm/exception-64s.h14
-rw-r--r--arch/powerpc/include/asm/fs_pd.h1
-rw-r--r--arch/powerpc/include/asm/hardirq.h1
-rw-r--r--arch/powerpc/include/asm/hvcall.h6
-rw-r--r--arch/powerpc/include/asm/hw_irq.h1
-rw-r--r--arch/powerpc/include/asm/irqflags.h8
-rw-r--r--arch/powerpc/include/asm/jump_label.h9
-rw-r--r--arch/powerpc/include/asm/kvm_44x.h67
-rw-r--r--arch/powerpc/include/asm/kvm_asm.h3
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h51
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h29
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h15
-rw-r--r--arch/powerpc/include/asm/kvm_host.h28
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h116
-rw-r--r--arch/powerpc/include/asm/machdep.h11
-rw-r--r--arch/powerpc/include/asm/mmu-book3e.h8
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h22
-rw-r--r--arch/powerpc/include/asm/mmu.h8
-rw-r--r--arch/powerpc/include/asm/mmu_context.h6
-rw-r--r--arch/powerpc/include/asm/mpc85xx.h2
-rw-r--r--arch/powerpc/include/asm/mpc8xx.h12
-rw-r--r--arch/powerpc/include/asm/opal.h205
-rw-r--r--arch/powerpc/include/asm/oprofile_impl.h1
-rw-r--r--arch/powerpc/include/asm/paca.h5
-rw-r--r--arch/powerpc/include/asm/page.h3
-rw-r--r--arch/powerpc/include/asm/perf_event_server.h5
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc64.h2
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h26
-rw-r--r--arch/powerpc/include/asm/processor.h2
-rw-r--r--arch/powerpc/include/asm/pte-fsl-booke.h2
-rw-r--r--arch/powerpc/include/asm/pte-hash64-64k.h35
-rw-r--r--arch/powerpc/include/asm/reg.h18
-rw-r--r--arch/powerpc/include/asm/reg_booke.h57
-rw-r--r--arch/powerpc/include/asm/scatterlist.h17
-rw-r--r--arch/powerpc/include/asm/spinlock.h1
-rw-r--r--arch/powerpc/include/asm/systbl.h4
-rw-r--r--arch/powerpc/include/asm/time.h9
-rw-r--r--arch/powerpc/include/asm/trace.h45
-rw-r--r--arch/powerpc/include/uapi/asm/kvm.h2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c4
-rw-r--r--arch/powerpc/kernel/cputable.c94
-rw-r--r--arch/powerpc/kernel/eeh.c366
-rw-r--r--arch/powerpc/kernel/eeh_cache.c9
-rw-r--r--arch/powerpc/kernel/eeh_dev.c3
-rw-r--r--arch/powerpc/kernel/eeh_driver.c16
-rw-r--r--arch/powerpc/kernel/eeh_pe.c86
-rw-r--r--arch/powerpc/kernel/entry_64.S13
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S359
-rw-r--r--arch/powerpc/kernel/ftrace.c3
-rw-r--r--arch/powerpc/kernel/head_44x.S4
-rw-r--r--arch/powerpc/kernel/head_64.S30
-rw-r--r--arch/powerpc/kernel/idle_power7.S69
-rw-r--r--arch/powerpc/kernel/iommu.c42
-rw-r--r--arch/powerpc/kernel/irq.c14
-rw-r--r--arch/powerpc/kernel/pci-common.c11
-rw-r--r--arch/powerpc/kernel/process.c34
-rw-r--r--arch/powerpc/kernel/prom.c81
-rw-r--r--arch/powerpc/kernel/setup-common.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c21
-rw-r--r--arch/powerpc/kernel/signal.c41
-rw-r--r--arch/powerpc/kernel/signal.h14
-rw-r--r--arch/powerpc/kernel/signal_32.c36
-rw-r--r--arch/powerpc/kernel/signal_64.c28
-rw-r--r--arch/powerpc/kernel/smp.c11
-rw-r--r--arch/powerpc/kernel/systbl.S3
-rw-r--r--arch/powerpc/kernel/time.c4
-rw-r--r--arch/powerpc/kernel/traps.c26
-rw-r--r--arch/powerpc/kernel/vdso.c16
-rw-r--r--arch/powerpc/kernel/vio.c2
-rw-r--r--arch/powerpc/kvm/44x.c237
-rw-r--r--arch/powerpc/kvm/44x_emulate.c194
-rw-r--r--arch/powerpc/kvm/44x_tlb.c528
-rw-r--r--arch/powerpc/kvm/44x_tlb.h86
-rw-r--r--arch/powerpc/kvm/Kconfig20
-rw-r--r--arch/powerpc/kvm/Makefile19
-rw-r--r--arch/powerpc/kvm/book3s.c156
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu.c2
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu_host.c7
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_host.c5
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c149
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c28
-rw-r--r--arch/powerpc/kvm/book3s_hv.c271
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c32
-rw-r--r--arch/powerpc/kvm/book3s_hv_cma.c240
-rw-r--r--arch/powerpc/kvm/book3s_hv_cma.h27
-rw-r--r--arch/powerpc/kvm/book3s_hv_ras.c6
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c146
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_xics.c5
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S76
-rw-r--r--arch/powerpc/kvm/book3s_paired_singles.c38
-rw-r--r--arch/powerpc/kvm/book3s_pr.c223
-rw-r--r--arch/powerpc/kvm/book3s_pr_papr.c92
-rw-r--r--arch/powerpc/kvm/book3s_xics.c55
-rw-r--r--arch/powerpc/kvm/book3s_xics.h2
-rw-r--r--arch/powerpc/kvm/booke.c225
-rw-r--r--arch/powerpc/kvm/booke.h7
-rw-r--r--arch/powerpc/kvm/booke_emulate.c8
-rw-r--r--arch/powerpc/kvm/booke_interrupts.S5
-rw-r--r--arch/powerpc/kvm/bookehv_interrupts.S60
-rw-r--r--arch/powerpc/kvm/e500_emulate.c12
-rw-r--r--arch/powerpc/kvm/e500_mmu_host.c102
-rw-r--r--arch/powerpc/kvm/e500mc.c28
-rw-r--r--arch/powerpc/kvm/emulate.c206
-rw-r--r--arch/powerpc/kvm/emulate_loadstore.c272
-rw-r--r--arch/powerpc/kvm/mpic.c4
-rw-r--r--arch/powerpc/kvm/powerpc.c181
-rw-r--r--arch/powerpc/kvm/timing.c1
-rw-r--r--arch/powerpc/kvm/timing.h3
-rw-r--r--arch/powerpc/lib/copyuser_64.S3
-rw-r--r--arch/powerpc/lib/locks.c4
-rw-r--r--arch/powerpc/mm/Makefile4
-rw-r--r--arch/powerpc/mm/dma-noncoherent.c1
-rw-r--r--arch/powerpc/mm/hash_native_64.c40
-rw-r--r--arch/powerpc/mm/hash_utils_64.c26
-rw-r--r--arch/powerpc/mm/hugepage-hash64.c88
-rw-r--r--arch/powerpc/mm/init_64.c132
-rw-r--r--arch/powerpc/mm/mem.c3
-rw-r--r--arch/powerpc/mm/mmu_context_hash32.c2
-rw-r--r--arch/powerpc/mm/numa.c15
-rw-r--r--arch/powerpc/mm/pgtable_32.c2
-rw-r--r--arch/powerpc/mm/pgtable_64.c46
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c2
-rw-r--r--arch/powerpc/mm/stab.c286
-rw-r--r--arch/powerpc/mm/tlb_hash64.c6
-rw-r--r--arch/powerpc/mm/tlb_low_64e.S69
-rw-r--r--arch/powerpc/mm/tlb_nohash.c111
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c8
-rw-r--r--arch/powerpc/oprofile/Makefile2
-rw-r--r--arch/powerpc/oprofile/common.c3
-rw-r--r--arch/powerpc/oprofile/op_model_rs64.c222
-rw-r--r--arch/powerpc/perf/core-book3s.c73
-rw-r--r--arch/powerpc/perf/hv-24x7.c8
-rw-r--r--arch/powerpc/perf/hv-gpci.c6
-rw-r--r--arch/powerpc/perf/mpc7450-pmu.c5
-rw-r--r--arch/powerpc/perf/power4-pmu.c2
-rw-r--r--arch/powerpc/perf/power5+-pmu.c2
-rw-r--r--arch/powerpc/perf/power5-pmu.c2
-rw-r--r--arch/powerpc/perf/power6-pmu.c2
-rw-r--r--arch/powerpc/perf/power7-pmu.c2
-rw-r--r--arch/powerpc/perf/power8-pmu.c27
-rw-r--r--arch/powerpc/perf/ppc970-pmu.c2
-rw-r--r--arch/powerpc/platforms/44x/warp.c1
-rw-r--r--arch/powerpc/platforms/52xx/efika.c1
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig2
-rw-r--r--arch/powerpc/platforms/85xx/corenet_generic.c53
-rw-r--r--arch/powerpc/platforms/85xx/smp.c44
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c3
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c62
-rw-r--r--arch/powerpc/platforms/8xx/tqm8xx_setup.c1
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype18
-rw-r--r--arch/powerpc/platforms/amigaone/setup.c1
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c11
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c4
-rw-r--r--arch/powerpc/platforms/powermac/Kconfig2
-rw-r--r--arch/powerpc/platforms/powermac/feature.c62
-rw-r--r--arch/powerpc/platforms/powermac/pci.c2
-rw-r--r--arch/powerpc/platforms/powermac/smp.c2
-rw-r--r--arch/powerpc/platforms/powermac/udbg_adb.c2
-rw-r--r--arch/powerpc/platforms/powernv/Makefile3
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c393
-rw-r--r--arch/powerpc/platforms/powernv/eeh-powernv.c55
-rw-r--r--arch/powerpc/platforms/powernv/opal-async.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal-dump.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-elog.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-hmi.c188
-rw-r--r--arch/powerpc/platforms/powernv/opal-lpc.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal-memory-errors.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal-tracepoints.c84
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S119
-rw-r--r--arch/powerpc/platforms/powernv/opal-xscom.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c75
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c501
-rw-r--r--arch/powerpc/platforms/powernv/pci-p5ioc2.c3
-rw-r--r--arch/powerpc/platforms/powernv/pci.c169
-rw-r--r--arch/powerpc/platforms/powernv/pci.h25
-rw-r--r--arch/powerpc/platforms/powernv/rng.c2
-rw-r--r--arch/powerpc/platforms/powernv/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/dtl.c3
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c40
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c4
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S172
-rw-r--r--arch/powerpc/platforms/pseries/hvCall_inst.c3
-rw-r--r--arch/powerpc/platforms/pseries/hvcserver.c4
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c20
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c50
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c5
-rw-r--r--arch/powerpc/platforms/pseries/msi.c4
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c4
-rw-r--r--arch/powerpc/platforms/pseries/power.c5
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c5
-rw-r--r--arch/powerpc/platforms/pseries/rng.c2
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/platforms/pseries/suspend.c5
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c4
-rw-r--r--arch/powerpc/sysdev/micropatch.c1
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c2
-rw-r--r--arch/powerpc/xmon/xmon.c37
-rw-r--r--arch/s390/Kconfig6
-rw-r--r--arch/s390/configs/default_defconfig2
-rw-r--r--arch/s390/configs/gcov_defconfig2
-rw-r--r--arch/s390/configs/performance_defconfig2
-rw-r--r--arch/s390/include/asm/Kbuild1
-rw-r--r--arch/s390/include/asm/kvm_host.h3
-rw-r--r--arch/s390/include/asm/page.h2
-rw-r--r--arch/s390/include/asm/pgtable.h197
-rw-r--r--arch/s390/include/asm/processor.h2
-rw-r--r--arch/s390/include/asm/qdio.h4
-rw-r--r--arch/s390/include/asm/scatterlist.h3
-rw-r--r--arch/s390/include/asm/syscall.h2
-rw-r--r--arch/s390/include/uapi/asm/Kbuild1
-rw-r--r--arch/s390/include/uapi/asm/kvm_perf.h25
-rw-r--r--arch/s390/include/uapi/asm/sie.h1
-rw-r--r--arch/s390/kernel/compat_signal.c79
-rw-r--r--arch/s390/kernel/entry.h4
-rw-r--r--arch/s390/kernel/irq.c95
-rw-r--r--arch/s390/kernel/mcount.S10
-rw-r--r--arch/s390/kernel/mcount64.S3
-rw-r--r--arch/s390/kernel/perf_cpum_cf.c12
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/s390/kernel/signal.c78
-rw-r--r--arch/s390/kernel/time.c16
-rw-r--r--arch/s390/kernel/vdso.c15
-rw-r--r--arch/s390/kvm/Kconfig1
-rw-r--r--arch/s390/kvm/diag.c3
-rw-r--r--arch/s390/kvm/intercept.c32
-rw-r--r--arch/s390/kvm/interrupt.c106
-rw-r--r--arch/s390/kvm/kvm-s390.c68
-rw-r--r--arch/s390/kvm/kvm-s390.h12
-rw-r--r--arch/s390/kvm/sigp.c44
-rw-r--r--arch/s390/mm/hugetlbpage.c103
-rw-r--r--arch/s390/mm/pgtable.c8
-rw-r--r--arch/s390/net/bpf_jit_comp.c4
-rw-r--r--arch/s390/pci/pci.c4
-rw-r--r--arch/s390/pci/pci_clp.c4
-rw-r--r--arch/s390/pci/pci_debug.c4
-rw-r--r--arch/s390/pci/pci_dma.c50
-rw-r--r--arch/s390/pci/pci_event.c4
-rw-r--r--arch/s390/pci/pci_sysfs.c4
-rw-r--r--arch/score/include/asm/Kbuild1
-rw-r--r--arch/score/include/asm/processor.h1
-rw-r--r--arch/score/include/asm/scatterlist.h6
-rw-r--r--arch/score/include/uapi/asm/ptrace.h11
-rw-r--r--arch/score/kernel/signal.c43
-rw-r--r--arch/sh/Kconfig3
-rw-r--r--arch/sh/boards/Kconfig2
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c2
-rw-r--r--arch/sh/configs/sh2007_defconfig1
-rw-r--r--arch/sh/drivers/dma/Kconfig5
-rw-r--r--arch/sh/drivers/dma/dma-sh.c2
-rw-r--r--arch/sh/include/asm/dma-register.h36
-rw-r--r--arch/sh/include/asm/io_noioport.h11
-rw-r--r--arch/sh/include/asm/page.h5
-rw-r--r--arch/sh/include/asm/processor.h1
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma-register.h1
-rw-r--r--arch/sh/include/cpu-sh4a/cpu/dma.h3
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7724.c4
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c24
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c48
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7757.c64
-rw-r--r--arch/sh/kernel/ftrace.c3
-rw-r--r--arch/sh/kernel/perf_event.c15
-rw-r--r--arch/sh/kernel/signal_32.c79
-rw-r--r--arch/sh/kernel/signal_64.c82
-rw-r--r--arch/sh/kernel/time.c4
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c15
-rw-r--r--arch/sh/lib/mcount.S24
-rw-r--r--arch/sh/mm/asids-debugfs.c4
-rw-r--r--arch/sh/mm/init.c5
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/Makefile3
-rw-r--r--arch/sparc/boot/Makefile4
-rw-r--r--arch/sparc/boot/install.sh50
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/io_64.h381
-rw-r--r--arch/sparc/include/asm/processor_32.h2
-rw-r--r--arch/sparc/include/asm/processor_64.h1
-rw-r--r--arch/sparc/include/asm/scatterlist.h8
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h12
-rw-r--r--arch/sparc/include/uapi/asm/unistd.h5
-rw-r--r--arch/sparc/kernel/ldc.c2
-rw-r--r--arch/sparc/kernel/mdesc.c82
-rw-r--r--arch/sparc/kernel/nmi.c1
-rw-r--r--arch/sparc/kernel/pci.c67
-rw-r--r--arch/sparc/kernel/perf_event.c7
-rw-r--r--arch/sparc/kernel/process_64.c3
-rw-r--r--arch/sparc/kernel/smp_32.c2
-rw-r--r--arch/sparc/kernel/smp_64.c1
-rw-r--r--arch/sparc/kernel/systbls_32.S2
-rw-r--r--arch/sparc/kernel/systbls_64.S4
-rw-r--r--arch/sparc/kernel/unaligned_32.c2
-rw-r--r--arch/sparc/lib/PeeCeeI.c36
-rw-r--r--arch/sparc/lib/mcount.S10
-rw-r--r--arch/sparc/math-emu/math_32.c2
-rw-r--r--arch/sparc/mm/init_64.c96
-rw-r--r--arch/sparc/net/bpf_jit_comp.c4
-rw-r--r--arch/tile/Kconfig3
-rw-r--r--arch/tile/configs/tilegx_defconfig1
-rw-r--r--arch/tile/configs/tilepro_defconfig1
-rw-r--r--arch/tile/include/asm/compat.h3
-rw-r--r--arch/tile/include/asm/hardwall.h2
-rw-r--r--arch/tile/include/asm/page.h6
-rw-r--r--arch/tile/include/asm/processor.h2
-rw-r--r--arch/tile/kernel/compat_signal.c29
-rw-r--r--arch/tile/kernel/hardwall.c6
-rw-r--r--arch/tile/kernel/mcount_64.S18
-rw-r--r--arch/tile/kernel/module.c2
-rw-r--r--arch/tile/kernel/signal.c54
-rw-r--r--arch/tile/kernel/time.c13
-rw-r--r--arch/tile/kernel/vdso.c15
-rw-r--r--arch/tile/kernel/vdso/vgettimeofday.c7
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/page.h5
-rw-r--r--arch/um/include/shared/frame_kern.h12
-rw-r--r--arch/um/kernel/signal.c27
-rw-r--r--arch/unicore32/include/asm/processor.h1
-rw-r--r--arch/unicore32/kernel/puv3-core.c2
-rw-r--r--arch/unicore32/kernel/puv3-nb0916.c6
-rw-r--r--arch/unicore32/kernel/signal.c48
-rw-r--r--arch/x86/Kbuild4
-rw-r--r--arch/x86/Kconfig43
-rw-r--r--arch/x86/Makefile17
-rw-r--r--arch/x86/boot/code16gcc.h24
-rw-r--r--arch/x86/boot/compressed/Makefile3
-rw-r--r--arch/x86/boot/compressed/eboot.c48
-rw-r--r--arch/x86/boot/compressed/eboot.h16
-rw-r--r--arch/x86/boot/header.S2
-rw-r--r--arch/x86/crypto/Makefile4
-rw-r--r--arch/x86/crypto/aes_ctrby8_avx-x86_64.S546
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c40
-rw-r--r--arch/x86/crypto/crc32c-pcl-intel-asm_64.S281
-rw-r--r--arch/x86/crypto/des3_ede-asm_64.S805
-rw-r--r--arch/x86/crypto/des3_ede_glue.c509
-rw-r--r--arch/x86/include/asm/Kbuild3
-rw-r--r--arch/x86/include/asm/acenv.h4
-rw-r--r--arch/x86/include/asm/acpi.h5
-rw-r--r--arch/x86/include/asm/alternative.h14
-rw-r--r--arch/x86/include/asm/apic.h48
-rw-r--r--arch/x86/include/asm/barrier.h2
-rw-r--r--arch/x86/include/asm/cmpxchg.h4
-rw-r--r--arch/x86/include/asm/cmpxchg_32.h2
-rw-r--r--arch/x86/include/asm/cmpxchg_64.h2
-rw-r--r--arch/x86/include/asm/cpufeature.h409
-rw-r--r--arch/x86/include/asm/crash.h9
-rw-r--r--arch/x86/include/asm/efi.h33
-rw-r--r--arch/x86/include/asm/fpu-internal.h11
-rw-r--r--arch/x86/include/asm/ftrace.h2
-rw-r--r--arch/x86/include/asm/hardirq.h3
-rw-r--r--arch/x86/include/asm/i8259.h5
-rw-r--r--arch/x86/include/asm/io_apic.h56
-rw-r--r--arch/x86/include/asm/kexec-bzimage64.h6
-rw-r--r--arch/x86/include/asm/kexec.h45
-rw-r--r--arch/x86/include/asm/kvm_emulate.h33
-rw-r--r--arch/x86/include/asm/kvm_host.h15
-rw-r--r--arch/x86/include/asm/mc146818rtc.h2
-rw-r--r--arch/x86/include/asm/mmu_context.h6
-rw-r--r--arch/x86/include/asm/mpspec.h15
-rw-r--r--arch/x86/include/asm/mutex_32.h16
-rw-r--r--arch/x86/include/asm/mwait.h2
-rw-r--r--arch/x86/include/asm/page.h1
-rw-r--r--arch/x86/include/asm/page_64.h2
-rw-r--r--arch/x86/include/asm/percpu.h3
-rw-r--r--arch/x86/include/asm/platform_sst_audio.h78
-rw-r--r--arch/x86/include/asm/pmc_atom.h107
-rw-r--r--arch/x86/include/asm/processor.h7
-rw-r--r--arch/x86/include/asm/prom.h2
-rw-r--r--arch/x86/include/asm/qrwlock.h2
-rw-r--r--arch/x86/include/asm/scatterlist.h8
-rw-r--r--arch/x86/include/asm/smpboot_hooks.h10
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h19
-rw-r--r--arch/x86/include/asm/vdso.h18
-rw-r--r--arch/x86/include/asm/vga.h6
-rw-r--r--arch/x86/include/asm/vmx.h7
-rw-r--r--arch/x86/include/asm/xsave.h223
-rw-r--r--arch/x86/include/uapi/asm/Kbuild1
-rw-r--r--arch/x86/include/uapi/asm/kvm.h3
-rw-r--r--arch/x86/include/uapi/asm/kvm_perf.h16
-rw-r--r--arch/x86/include/uapi/asm/msr-index.h3
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/Makefile1
-rw-r--r--arch/x86/kernel/acpi/apei.c62
-rw-r--r--arch/x86/kernel/acpi/boot.c404
-rw-r--r--arch/x86/kernel/apic/apic.c75
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c16
-rw-r--r--arch/x86/kernel/apic/apic_noop.c23
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c8
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c14
-rw-r--r--arch/x86/kernel/apic/io_apic.c759
-rw-r--r--arch/x86/kernel/apic/probe_32.c33
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c8
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c8
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c8
-rw-r--r--arch/x86/kernel/cpu/amd.c348
-rw-r--r--arch/x86/kernel/cpu/common.c30
-rw-r--r--arch/x86/kernel/cpu/intel.c30
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c4
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c15
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c4
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c18
-rw-r--r--arch/x86/kernel/cpu/mkcapflags.sh51
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_uncore.c111
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c15
-rw-r--r--arch/x86/kernel/cpu/proc.c8
-rw-r--r--arch/x86/kernel/cpu/scattered.c1
-rw-r--r--arch/x86/kernel/crash.c563
-rw-r--r--arch/x86/kernel/devicetree.c207
-rw-r--r--arch/x86/kernel/entry_32.S9
-rw-r--r--arch/x86/kernel/entry_64.S52
-rw-r--r--arch/x86/kernel/ftrace.c3
-rw-r--r--arch/x86/kernel/i387.c2
-rw-r--r--arch/x86/kernel/iosf_mbi.c2
-rw-r--r--arch/x86/kernel/irqinit.c12
-rw-r--r--arch/x86/kernel/kexec-bzimage64.c553
-rw-r--r--arch/x86/kernel/machine_kexec_64.c239
-rw-r--r--arch/x86/kernel/mcount_64.S13
-rw-r--r--arch/x86/kernel/mpparse.c111
-rw-r--r--arch/x86/kernel/pmc_atom.c321
-rw-r--r--arch/x86/kernel/process.c1
-rw-r--r--arch/x86/kernel/reboot.c24
-rw-r--r--arch/x86/kernel/resource.c8
-rw-r--r--arch/x86/kernel/setup.c4
-rw-r--r--arch/x86/kernel/smpboot.c8
-rw-r--r--arch/x86/kernel/tsc.c28
-rw-r--r--arch/x86/kernel/vsmp_64.c4
-rw-r--r--arch/x86/kernel/vsyscall_64.c8
-rw-r--r--arch/x86/kernel/vsyscall_gtod.c23
-rw-r--r--arch/x86/kernel/xsave.c118
-rw-r--r--arch/x86/kvm/Kconfig1
-rw-r--r--arch/x86/kvm/cpuid.h8
-rw-r--r--arch/x86/kvm/emulate.c494
-rw-r--r--arch/x86/kvm/irq.c2
-rw-r--r--arch/x86/kvm/lapic.c56
-rw-r--r--arch/x86/kvm/mmu_audit.c2
-rw-r--r--arch/x86/kvm/mmutrace.h4
-rw-r--r--arch/x86/kvm/pmu.c9
-rw-r--r--arch/x86/kvm/svm.c57
-rw-r--r--arch/x86/kvm/trace.h6
-rw-r--r--arch/x86/kvm/vmx.c241
-rw-r--r--arch/x86/kvm/x86.c235
-rw-r--r--arch/x86/kvm/x86.h27
-rw-r--r--arch/x86/mm/fault.c9
-rw-r--r--arch/x86/mm/init.c7
-rw-r--r--arch/x86/mm/init_32.c3
-rw-r--r--arch/x86/mm/init_64.c3
-rw-r--r--arch/x86/mm/tlb.c103
-rw-r--r--arch/x86/net/bpf_jit_comp.c16
-rw-r--r--arch/x86/pci/acpi.c6
-rw-r--r--arch/x86/pci/fixup.c21
-rw-r--r--arch/x86/pci/i386.c4
-rw-r--r--arch/x86/pci/intel_mid_pci.c27
-rw-r--r--arch/x86/pci/irq.c16
-rw-r--r--arch/x86/pci/xen.c7
-rw-r--r--arch/x86/platform/ce4100/ce4100.c11
-rw-r--r--arch/x86/platform/efi/Makefile2
-rw-r--r--arch/x86/platform/efi/efi.c483
-rw-r--r--arch/x86/platform/efi/quirks.c290
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_wdt.c22
-rw-r--r--arch/x86/platform/intel-mid/sfi.c56
-rw-r--r--arch/x86/platform/sfi/sfi.c10
-rw-r--r--arch/x86/platform/ts5500/ts5500.c94
-rw-r--r--arch/x86/platform/uv/tlb_uv.c71
-rw-r--r--arch/x86/power/cpu.c4
-rw-r--r--arch/x86/purgatory/Makefile30
-rw-r--r--arch/x86/purgatory/entry64.S101
-rw-r--r--arch/x86/purgatory/purgatory.c72
-rw-r--r--arch/x86/purgatory/setup-x86_64.S58
-rw-r--r--arch/x86/purgatory/sha256.c283
-rw-r--r--arch/x86/purgatory/sha256.h22
-rw-r--r--arch/x86/purgatory/stack.S19
-rw-r--r--arch/x86/purgatory/string.c13
-rw-r--r--arch/x86/syscalls/syscall_32.tbl3
-rw-r--r--arch/x86/syscalls/syscall_64.tbl4
-rw-r--r--arch/x86/um/asm/elf.h1
-rw-r--r--arch/x86/um/asm/processor.h3
-rw-r--r--arch/x86/um/mem_64.c15
-rw-r--r--arch/x86/um/signal.c45
-rw-r--r--arch/x86/vdso/Makefile16
-rw-r--r--arch/x86/vdso/vdso-fakesections.c21
-rw-r--r--arch/x86/vdso/vdso-layout.lds.S44
-rw-r--r--arch/x86/vdso/vdso2c.c128
-rw-r--r--arch/x86/vdso/vdso2c.h227
-rw-r--r--arch/x86/vdso/vdso32-setup.c19
-rw-r--r--arch/x86/vdso/vma.c22
-rw-r--r--arch/x86/xen/Makefile1
-rw-r--r--arch/x86/xen/efi.c43
-rw-r--r--arch/x86/xen/enlighten.c15
-rw-r--r--arch/x86/xen/grant-table.c70
-rw-r--r--arch/x86/xen/p2m.c5
-rw-r--r--arch/x86/xen/time.c2
-rw-r--r--arch/x86/xen/xen-ops.h8
-rw-r--r--arch/xtensa/include/asm/processor.h1
-rw-r--r--arch/xtensa/kernel/signal.c43
-rw-r--r--block/bio-integrity.c12
-rw-r--r--block/bio.c3
-rw-r--r--block/blk-cgroup.c13
-rw-r--r--block/blk-core.c13
-rw-r--r--block/blk-mq.c81
-rw-r--r--block/blk-mq.h2
-rw-r--r--block/blk-sysfs.c2
-rw-r--r--block/blk-throttle.c6
-rw-r--r--block/compat_ioctl.c6
-rw-r--r--block/ioctl.c5
-rw-r--r--block/partitions/aix.c4
-rw-r--r--block/partitions/amiga.c12
-rw-r--r--block/partitions/efi.c46
-rw-r--r--block/partitions/msdos.c13
-rw-r--r--block/scsi_ioctl.c20
-rw-r--r--crypto/Kconfig76
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/algapi.c14
-rw-r--r--crypto/asymmetric_keys/Kconfig34
-rw-r--r--crypto/asymmetric_keys/Makefile37
-rw-r--r--crypto/asymmetric_keys/asymmetric_keys.h2
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c78
-rw-r--r--crypto/asymmetric_keys/mscode.asn128
-rw-r--r--crypto/asymmetric_keys/mscode_parser.c126
-rw-r--r--crypto/asymmetric_keys/pkcs7.asn1127
-rw-r--r--crypto/asymmetric_keys/pkcs7_key_type.c100
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c396
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.h61
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c166
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c321
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c457
-rw-r--r--crypto/asymmetric_keys/verify_pefile.h42
-rw-r--r--crypto/asymmetric_keys/x509.asn12
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c20
-rw-r--r--crypto/asymmetric_keys/x509_parser.h13
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c115
-rw-r--r--crypto/cryptd.c12
-rw-r--r--crypto/des_generic.c22
-rw-r--r--crypto/drbg.c2044
-rw-r--r--crypto/eseqiv.c8
-rw-r--r--crypto/gcm.c30
-rw-r--r--crypto/lzo.c8
-rw-r--r--crypto/seqiv.c16
-rw-r--r--crypto/tcrypt.c114
-rw-r--r--crypto/testmgr.c304
-rw-r--r--crypto/testmgr.h1158
-rw-r--r--crypto/zlib.c8
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/acpi/Kconfig10
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_extlog.c56
-rw-r--r--drivers/acpi/acpi_lpss.c10
-rw-r--r--drivers/acpi/acpi_pnp.c8
-rw-r--r--drivers/acpi/acpi_processor.c2
-rw-r--r--drivers/acpi/acpica/Makefile10
-rw-r--r--drivers/acpi/acpica/acapps.h9
-rw-r--r--drivers/acpi/acpica/acdebug.h3
-rw-r--r--drivers/acpi/acpica/acglobal.h8
-rw-r--r--drivers/acpi/acpica/aclocal.h18
-rw-r--r--drivers/acpi/acpica/acpredef.h16
-rw-r--r--drivers/acpi/acpica/acutils.h48
-rw-r--r--drivers/acpi/acpica/evgpe.c32
-rw-r--r--drivers/acpi/acpica/evxfgpe.c61
-rw-r--r--drivers/acpi/acpica/exdebug.c11
-rw-r--r--drivers/acpi/acpica/exdump.c6
-rw-r--r--drivers/acpi/acpica/exfield.c26
-rw-r--r--drivers/acpi/acpica/hwregs.c3
-rw-r--r--drivers/acpi/acpica/nsobject.c10
-rw-r--r--drivers/acpi/acpica/utbuffer.c128
-rw-r--r--drivers/acpi/acpica/utcopy.c6
-rw-r--r--drivers/acpi/acpica/utdebug.c26
-rw-r--r--drivers/acpi/acpica/utdecode.c32
-rw-r--r--drivers/acpi/acpica/utfileio.c331
-rw-r--r--drivers/acpi/acpica/utglobal.c146
-rw-r--r--drivers/acpi/acpica/uthex.c100
-rw-r--r--drivers/acpi/acpica/utinit.c145
-rw-r--r--drivers/acpi/acpica/utprint.c664
-rw-r--r--drivers/acpi/acpica/utuuid.c96
-rw-r--r--drivers/acpi/apei/Kconfig8
-rw-r--r--drivers/acpi/apei/apei-base.c13
-rw-r--r--drivers/acpi/apei/apei-internal.h10
-rw-r--r--drivers/acpi/apei/ghes.c205
-rw-r--r--drivers/acpi/apei/hest.c29
-rw-r--r--drivers/acpi/battery.c3
-rw-r--r--drivers/acpi/blacklist.c68
-rw-r--r--drivers/acpi/bus.c3
-rw-r--r--drivers/acpi/button.c25
-rw-r--r--drivers/acpi/device_pm.c148
-rw-r--r--drivers/acpi/internal.h7
-rw-r--r--drivers/acpi/osl.c4
-rw-r--r--drivers/acpi/pci_irq.c7
-rw-r--r--drivers/acpi/pci_root.c2
-rw-r--r--drivers/acpi/processor_core.c200
-rw-r--r--drivers/acpi/processor_driver.c1
-rw-r--r--drivers/acpi/processor_pdc.c206
-rw-r--r--drivers/acpi/scan.c36
-rw-r--r--drivers/acpi/sleep.c5
-rw-r--r--drivers/acpi/video.c121
-rw-r--r--drivers/amba/tegra-ahb.c3
-rw-r--r--drivers/ata/Kconfig10
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/acard-ahci.c2
-rw-r--r--drivers/ata/ahci.c3
-rw-r--r--drivers/ata/ahci.h19
-rw-r--r--drivers/ata/ahci_da850.c3
-rw-r--r--drivers/ata/ahci_imx.c187
-rw-r--r--drivers/ata/ahci_mvebu.c3
-rw-r--r--drivers/ata/ahci_platform.c8
-rw-r--r--drivers/ata/ahci_st.c4
-rw-r--r--drivers/ata/ahci_sunxi.c8
-rw-r--r--drivers/ata/ahci_tegra.c376
-rw-r--r--drivers/ata/ahci_xgene.c29
-rw-r--r--drivers/ata/libahci.c19
-rw-r--r--drivers/ata/libahci_platform.c215
-rw-r--r--drivers/ata/libata-core.c72
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_samsung_cf.c13
-rw-r--r--drivers/ata/sata_fsl.c5
-rw-r--r--drivers/ata/sata_highbank.c2
-rw-r--r--drivers/ata/sata_sil24.c4
-rw-r--r--drivers/atm/atmtcp.c1
-rw-r--r--drivers/atm/eni.c4
-rw-r--r--drivers/atm/he.c31
-rw-r--r--drivers/atm/idt77252.c15
-rw-r--r--drivers/atm/solos-pci.c1
-rw-r--r--drivers/base/Kconfig29
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/component.c192
-rw-r--r--drivers/base/devres.c55
-rw-r--r--drivers/base/dma-contiguous.c220
-rw-r--r--drivers/base/firmware_class.c77
-rw-r--r--drivers/base/memory.c30
-rw-r--r--drivers/base/node.c2
-rw-r--r--drivers/base/platform.c56
-rw-r--r--drivers/base/power/main.c5
-rw-r--r--drivers/base/regmap/regmap.c13
-rw-r--r--drivers/base/reservation.c39
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/driver_chipcommon_pmu.c2
-rw-r--r--drivers/bcma/driver_gpio.c1
-rw-r--r--drivers/bcma/driver_pcie2.c175
-rw-r--r--drivers/bcma/host_pci.c2
-rw-r--r--drivers/bcma/main.c8
-rw-r--r--drivers/bcma/scan.c22
-rw-r--r--drivers/bcma/sprom.c43
-rw-r--r--drivers/block/DAC960.c18
-rw-r--r--drivers/block/cciss.c11
-rw-r--r--drivers/block/drbd/Makefile1
-rw-r--r--drivers/block/drbd/drbd_actlog.c518
-rw-r--r--drivers/block/drbd/drbd_bitmap.c150
-rw-r--r--drivers/block/drbd/drbd_debugfs.c958
-rw-r--r--drivers/block/drbd/drbd_debugfs.h39
-rw-r--r--drivers/block/drbd/drbd_int.h383
-rw-r--r--drivers/block/drbd/drbd_interval.h4
-rw-r--r--drivers/block/drbd/drbd_main.c302
-rw-r--r--drivers/block/drbd/drbd_nl.c110
-rw-r--r--drivers/block/drbd/drbd_proc.c125
-rw-r--r--drivers/block/drbd/drbd_receiver.c316
-rw-r--r--drivers/block/drbd/drbd_req.c527
-rw-r--r--drivers/block/drbd/drbd_req.h1
-rw-r--r--drivers/block/drbd/drbd_state.c90
-rw-r--r--drivers/block/drbd/drbd_worker.c348
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c2
-rw-r--r--drivers/block/rbd.c689
-rw-r--r--drivers/block/rsxx/core.c2
-rw-r--r--drivers/block/skd_main.c27
-rw-r--r--drivers/block/virtio_blk.c104
-rw-r--r--drivers/block/zram/zram_drv.c71
-rw-r--r--drivers/block/zram/zram_drv.h29
-rw-r--r--drivers/bluetooth/Kconfig12
-rw-r--r--drivers/bluetooth/ath3k.c35
-rw-r--r--drivers/bluetooth/btmrvl_drv.h4
-rw-r--r--drivers/bluetooth/btmrvl_main.c73
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c21
-rw-r--r--drivers/bluetooth/btmrvl_sdio.h2
-rw-r--r--drivers/bluetooth/btusb.c221
-rw-r--r--drivers/bluetooth/hci_h5.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c25
-rw-r--r--drivers/bluetooth/hci_uart.h1
-rw-r--r--drivers/bluetooth/hci_vhci.c34
-rw-r--r--drivers/bus/Kconfig8
-rw-r--r--drivers/bus/Makefile4
-rw-r--r--drivers/bus/arm-cci.c3
-rw-r--r--drivers/bus/arm-ccn.c1391
-rw-r--r--drivers/bus/brcmstb_gisb.c6
-rw-r--r--drivers/bus/imx-weim.c4
-rw-r--r--drivers/char/agp/frontend.c15
-rw-r--r--drivers/char/bsr.c2
-rw-r--r--drivers/char/dsp56k.c2
-rw-r--r--drivers/char/hangcheck-timer.c33
-rw-r--r--drivers/char/hw_random/core.c73
-rw-r--r--drivers/char/hw_random/virtio-rng.c40
-rw-r--r--drivers/char/i8k.c123
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/random.c315
-rw-r--r--drivers/char/tpm/tpm-interface.c73
-rw-r--r--drivers/char/tpm/tpm_eventlog.c4
-rw-r--r--drivers/char/tpm/tpm_i2c_stm_st33.c1
-rw-r--r--drivers/char/tpm/tpm_tis.c31
-rw-r--r--drivers/char/virtio_console.c6
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c1
-rw-r--r--drivers/clk/Kconfig7
-rw-r--r--drivers/clk/Makefile5
-rw-r--r--drivers/clk/at91/clk-main.c1
-rw-r--r--drivers/clk/clk-clps711x.c192
-rw-r--r--drivers/clk/clk-composite.c79
-rw-r--r--drivers/clk/clk-conf.c144
-rw-r--r--drivers/clk/clk-palmas.c307
-rw-r--r--drivers/clk/clk-ppc-corenet.c2
-rw-r--r--drivers/clk/clk-s2mps11.c33
-rw-r--r--drivers/clk/clk.c134
-rw-r--r--drivers/clk/clkdev.c5
-rw-r--r--drivers/clk/mvebu/clk-cpu.c80
-rw-r--r--drivers/clk/qcom/Kconfig25
-rw-r--r--drivers/clk/qcom/Makefile3
-rw-r--r--drivers/clk/qcom/clk-pll.c15
-rw-r--r--drivers/clk/qcom/clk-pll.h2
-rw-r--r--drivers/clk/qcom/clk-rcg.c51
-rw-r--r--drivers/clk/qcom/clk-rcg.h1
-rw-r--r--drivers/clk/qcom/common.c39
-rw-r--r--drivers/clk/qcom/common.h6
-rw-r--r--drivers/clk/qcom/gcc-apq8084.c3611
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c2424
-rw-r--r--drivers/clk/qcom/gcc-msm8960.c583
-rw-r--r--drivers/clk/qcom/mmcc-apq8084.c3352
-rw-r--r--drivers/clk/qcom/mmcc-msm8960.c526
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c10
-rw-r--r--drivers/clk/rockchip/Makefile6
-rw-r--r--drivers/clk/rockchip/clk-pll.c431
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c672
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c717
-rw-r--r--drivers/clk/rockchip/clk.c244
-rw-r--r--drivers/clk/rockchip/clk.h347
-rw-r--r--drivers/clk/rockchip/softrst.c118
-rw-r--r--drivers/clk/samsung/Makefile2
-rw-r--r--drivers/clk/samsung/clk-exynos-clkout.c153
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c43
-rw-r--r--drivers/clk/samsung/clk-exynos4.c231
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c4
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c2
-rw-r--r--drivers/clk/samsung/clk-exynos5410.c2
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c61
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c4
-rw-r--r--drivers/clk/samsung/clk-s3c2410.c2
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c2
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c2
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c2
-rw-r--r--drivers/clk/samsung/clk-s5pv210-audss.c241
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c856
-rw-r--r--drivers/clk/samsung/clk.c21
-rw-r--r--drivers/clk/samsung/clk.h4
-rw-r--r--drivers/clk/spear/spear1310_clock.c6
-rw-r--r--drivers/clk/spear/spear1340_clock.c2
-rw-r--r--drivers/clk/st/Makefile2
-rw-r--r--drivers/clk/st/clk-flexgen.c331
-rw-r--r--drivers/clk/st/clkgen-fsyn.c223
-rw-r--r--drivers/clk/st/clkgen-mux.c12
-rw-r--r--drivers/clk/st/clkgen-pll.c94
-rw-r--r--drivers/clk/sunxi/Makefile4
-rw-r--r--drivers/clk/sunxi/clk-a20-gmac.c2
-rw-r--r--drivers/clk/sunxi/clk-factors.c2
-rw-r--r--drivers/clk/sunxi/clk-factors.h1
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0-gates.c76
-rw-r--r--drivers/clk/sunxi/clk-sun6i-apb0.c2
-rw-r--r--drivers/clk/sunxi/clk-sun6i-ar100.c4
-rw-r--r--drivers/clk/sunxi/clk-sun8i-apb0.c68
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c129
-rw-r--r--drivers/clk/tegra/clk-periph-gate.c3
-rw-r--r--drivers/clk/tegra/clk-pll.c19
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c4
-rw-r--r--drivers/clk/tegra/clk-tegra114.c31
-rw-r--r--drivers/clk/tegra/clk-tegra124.c10
-rw-r--r--drivers/clk/tegra/clk-tegra30.c5
-rw-r--r--drivers/clk/tegra/clk.c9
-rw-r--r--drivers/clk/ti/clk-7xx.c11
-rw-r--r--drivers/clk/versatile/Makefile3
-rw-r--r--drivers/clk/versatile/clk-versatile.c (renamed from drivers/clk/versatile/clk-integrator.c)38
-rw-r--r--drivers/clocksource/Kconfig14
-rw-r--r--drivers/clocksource/Makefile3
-rw-r--r--drivers/clocksource/arm_global_timer.c2
-rw-r--r--drivers/clocksource/clps711x-timer.c131
-rw-r--r--drivers/clocksource/exynos_mct.c63
-rw-r--r--drivers/clocksource/mtk_timer.c261
-rw-r--r--drivers/clocksource/pxa_timer.c227
-rw-r--r--drivers/clocksource/sh_cmt.c233
-rw-r--r--drivers/clocksource/sh_mtu2.c146
-rw-r--r--drivers/clocksource/sh_tmu.c127
-rw-r--r--drivers/clocksource/tegra20_timer.c13
-rw-r--r--drivers/clocksource/timer-marco.c3
-rw-r--r--drivers/clocksource/timer-prima2.c3
-rw-r--r--drivers/connector/cn_proc.c36
-rw-r--r--drivers/cpufreq/arm_big_little.c5
-rw-r--r--drivers/cpufreq/arm_big_little_dt.c2
-rw-r--r--drivers/cpufreq/cpufreq-cpu0.c2
-rw-r--r--drivers/cpufreq/cpufreq.c74
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c11
-rw-r--r--drivers/cpufreq/cpufreq_opp.c2
-rw-r--r--drivers/cpufreq/freq_table.c12
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c35
-rw-r--r--drivers/cpufreq/integrator-cpufreq.c10
-rw-r--r--drivers/cpufreq/intel_pstate.c131
-rw-r--r--drivers/cpufreq/loongson2_cpufreq.c6
-rw-r--r--drivers/cpufreq/pmac64-cpufreq.c3
-rw-r--r--drivers/cpufreq/powernow-k6.c1
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c18
-rw-r--r--drivers/cpufreq/s3c2410-cpufreq.c2
-rw-r--r--drivers/cpufreq/s3c2412-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c2440-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c1
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c131
-rw-r--r--drivers/cpufreq/speedstep-smi.c4
-rw-r--r--drivers/cpuidle/Kconfig7
-rw-r--r--drivers/cpuidle/Kconfig.arm15
-rw-r--r--drivers/cpuidle/Makefile2
-rw-r--r--drivers/cpuidle/cpuidle-armada-370-xp.c93
-rw-r--r--drivers/cpuidle/cpuidle-big_little.c12
-rw-r--r--drivers/cpuidle/cpuidle-exynos.c25
-rw-r--r--drivers/cpuidle/cpuidle-mvebu-v7.c150
-rw-r--r--drivers/cpuidle/cpuidle-powernv.c16
-rw-r--r--drivers/cpuidle/cpuidle.c2
-rw-r--r--drivers/cpuidle/driver.c11
-rw-r--r--drivers/cpuidle/governors/ladder.c4
-rw-r--r--drivers/cpuidle/governors/menu.c46
-rw-r--r--drivers/cpuidle/sysfs.c2
-rw-r--r--drivers/crypto/Kconfig20
-rw-r--r--drivers/crypto/Makefile2
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c2
-rw-r--r--drivers/crypto/atmel-sha.c9
-rw-r--r--drivers/crypto/atmel-tdes.c8
-rw-r--r--drivers/crypto/caam/caamalg.c80
-rw-r--r--drivers/crypto/caam/caamhash.c186
-rw-r--r--drivers/crypto/caam/caamrng.c79
-rw-r--r--drivers/crypto/caam/ctrl.c76
-rw-r--r--drivers/crypto/caam/desc.h1
-rw-r--r--drivers/crypto/caam/intern.h1
-rw-r--r--drivers/crypto/caam/jr.c6
-rw-r--r--drivers/crypto/caam/regs.h105
-rw-r--r--drivers/crypto/ccp/Makefile5
-rw-r--r--drivers/crypto/ccp/ccp-dev.c34
-rw-r--r--drivers/crypto/ccp/ccp-dev.h14
-rw-r--r--drivers/crypto/ccp/ccp-ops.c26
-rw-r--r--drivers/crypto/ccp/ccp-pci.c41
-rw-r--r--drivers/crypto/ccp/ccp-platform.c230
-rw-r--r--drivers/crypto/hifn_795x.c5
-rw-r--r--drivers/crypto/nx/nx-842.c32
-rw-r--r--drivers/crypto/qat/Kconfig23
-rw-r--r--drivers/crypto/qat/Makefile2
-rw-r--r--drivers/crypto/qat/qat_common/Makefile14
-rw-r--r--drivers/crypto/qat/qat_common/adf_accel_devices.h205
-rw-r--r--drivers/crypto/qat/qat_common/adf_accel_engine.c168
-rw-r--r--drivers/crypto/qat/qat_common/adf_aer.c259
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg.c361
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg.h87
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg_common.h100
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg_strings.h83
-rw-r--r--drivers/crypto/qat/qat_common/adf_cfg_user.h94
-rw-r--r--drivers/crypto/qat/qat_common/adf_common_drv.h192
-rw-r--r--drivers/crypto/qat/qat_common/adf_ctl_drv.c490
-rw-r--r--drivers/crypto/qat/qat_common/adf_dev_mgr.c215
-rw-r--r--drivers/crypto/qat/qat_common/adf_init.c388
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport.c567
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport.h63
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport_access_macros.h160
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport_debug.c304
-rw-r--r--drivers/crypto/qat/qat_common/adf_transport_internal.h118
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_fw.h316
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h131
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_fw_la.h404
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h78
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_hal.h125
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_hw.h305
-rw-r--r--drivers/crypto/qat/qat_common/icp_qat_uclo.h377
-rw-r--r--drivers/crypto/qat/qat_common/qat_algs.c1038
-rw-r--r--drivers/crypto/qat/qat_common/qat_crypto.c284
-rw-r--r--drivers/crypto/qat/qat_common/qat_crypto.h83
-rw-r--r--drivers/crypto/qat/qat_common/qat_hal.c1393
-rw-r--r--drivers/crypto/qat/qat_common/qat_uclo.c1181
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/Makefile8
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_admin.c144
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c214
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h86
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_drv.c449
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_drv.h67
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c159
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/adf_isr.c266
-rw-r--r--drivers/crypto/qat/qat_dh895xcc/qat_admin.c107
-rw-r--r--drivers/crypto/qce/Makefile6
-rw-r--r--drivers/crypto/qce/ablkcipher.c431
-rw-r--r--drivers/crypto/qce/cipher.h68
-rw-r--r--drivers/crypto/qce/common.c438
-rw-r--r--drivers/crypto/qce/common.h102
-rw-r--r--drivers/crypto/qce/core.c286
-rw-r--r--drivers/crypto/qce/core.h68
-rw-r--r--drivers/crypto/qce/dma.c186
-rw-r--r--drivers/crypto/qce/dma.h58
-rw-r--r--drivers/crypto/qce/regs-v5.h334
-rw-r--r--drivers/crypto/qce/sha.c588
-rw-r--r--drivers/crypto/qce/sha.h81
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c25
-rw-r--r--drivers/devfreq/Kconfig1
-rw-r--r--drivers/dma-buf/Makefile1
-rw-r--r--drivers/dma-buf/dma-buf.c (renamed from drivers/base/dma-buf.c)168
-rw-r--r--drivers/dma-buf/fence.c431
-rw-r--r--drivers/dma-buf/reservation.c477
-rw-r--r--drivers/dma-buf/seqno-fence.c73
-rw-r--r--drivers/dma/Kconfig35
-rw-r--r--drivers/dma/Makefile7
-rw-r--r--drivers/dma/TODO1
-rw-r--r--drivers/dma/amba-pl08x.c6
-rw-r--r--drivers/dma/at_hdmac.c15
-rw-r--r--drivers/dma/bcm2835-dma.c2
-rw-r--r--drivers/dma/dma-jz4740.c4
-rw-r--r--drivers/dma/dw/core.c42
-rw-r--r--drivers/dma/edma.c24
-rw-r--r--drivers/dma/ep93xx_dma.c4
-rw-r--r--drivers/dma/fsl-edma.c8
-rw-r--r--drivers/dma/fsldma.c297
-rw-r--r--drivers/dma/fsldma.h32
-rw-r--r--drivers/dma/imx-dma.c2
-rw-r--r--drivers/dma/imx-sdma.c17
-rw-r--r--drivers/dma/ipu/ipu_idmac.c14
-rw-r--r--drivers/dma/mic_x100_dma.c774
-rw-r--r--drivers/dma/mic_x100_dma.h286
-rw-r--r--drivers/dma/mmp_pdma.c2
-rw-r--r--drivers/dma/mmp_tdma.c2
-rw-r--r--drivers/dma/mpc512x_dma.c13
-rw-r--r--drivers/dma/mxs-dma.c10
-rw-r--r--drivers/dma/nbpfaxi.c1517
-rw-r--r--drivers/dma/of-dma.c35
-rw-r--r--drivers/dma/omap-dma.c3
-rw-r--r--drivers/dma/pl330.c964
-rw-r--r--drivers/dma/qcom_bam_dma.c20
-rw-r--r--drivers/dma/s3c24xx-dma.c3
-rw-r--r--drivers/dma/sa11x0-dma.c2
-rw-r--r--drivers/dma/sh/Kconfig24
-rw-r--r--drivers/dma/sh/Makefile16
-rw-r--r--drivers/dma/sh/rcar-audmapp.c114
-rw-r--r--drivers/dma/sh/shdma-arm.h4
-rw-r--r--drivers/dma/sh/shdma-base.c103
-rw-r--r--drivers/dma/sh/shdma.h2
-rw-r--r--drivers/dma/sh/shdmac.c15
-rw-r--r--drivers/dma/sirf-dma.c2
-rw-r--r--drivers/dma/ste_dma40.c3
-rw-r--r--drivers/dma/sun6i-dma.c1053
-rw-r--r--drivers/dma/tegra20-apb-dma.c2
-rw-r--r--drivers/edac/Kconfig12
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/cell_edac.c3
-rw-r--r--drivers/edac/edac_mc.c3
-rw-r--r--drivers/edac/edac_mc_sysfs.c4
-rw-r--r--drivers/edac/edac_module.c2
-rw-r--r--drivers/edac/ie31200_edac.c536
-rw-r--r--drivers/edac/mce_amd.c44
-rw-r--r--drivers/edac/sb_edac.c810
-rw-r--r--drivers/edac/x38_edac.c15
-rw-r--r--drivers/extcon/Kconfig38
-rw-r--r--drivers/extcon/Makefile7
-rw-r--r--drivers/extcon/extcon-adc-jack.c1
-rw-r--r--drivers/extcon/extcon-arizona.c74
-rw-r--r--drivers/extcon/extcon-class.c2
-rw-r--r--drivers/extcon/extcon-gpio.c1
-rw-r--r--drivers/extcon/extcon-max14577.c5
-rw-r--r--drivers/extcon/extcon-max77693.c41
-rw-r--r--drivers/extcon/extcon-max8997.c5
-rw-r--r--drivers/extcon/extcon-palmas.c3
-rw-r--r--drivers/extcon/extcon-sm5502.c724
-rw-r--r--drivers/firewire/core-cdev.c6
-rw-r--r--drivers/firewire/net.c3
-rw-r--r--drivers/firmware/efi/Kconfig6
-rw-r--r--drivers/firmware/efi/Makefile4
-rw-r--r--drivers/firmware/efi/cper.c212
-rw-r--r--drivers/firmware/efi/efi.c40
-rw-r--r--drivers/firmware/efi/efivars.c1
-rw-r--r--drivers/firmware/efi/libstub/Makefile26
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c (renamed from drivers/firmware/efi/arm-stub.c)32
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c (renamed from drivers/firmware/efi/efi-stub-helper.c)74
-rw-r--r--drivers/firmware/efi/libstub/efistub.h42
-rw-r--r--drivers/firmware/efi/libstub/fdt.c (renamed from drivers/firmware/efi/fdt.c)20
-rw-r--r--drivers/firmware/efi/reboot.c56
-rw-r--r--drivers/firmware/efi/runtime-map.c21
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c161
-rw-r--r--drivers/firmware/memmap.c6
-rw-r--r--drivers/gpio/Kconfig23
-rw-r--r--drivers/gpio/Makefile4
-rw-r--r--drivers/gpio/devres.c40
-rw-r--r--drivers/gpio/gpio-74x164.c8
-rw-r--r--drivers/gpio/gpio-adnp.c9
-rw-r--r--drivers/gpio/gpio-adp5520.c8
-rw-r--r--drivers/gpio/gpio-adp5588.c6
-rw-r--r--drivers/gpio/gpio-amd8111.c3
-rw-r--r--drivers/gpio/gpio-arizona.c3
-rw-r--r--drivers/gpio/gpio-crystalcove.c380
-rw-r--r--drivers/gpio/gpio-cs5535.c8
-rw-r--r--drivers/gpio/gpio-da9052.c3
-rw-r--r--drivers/gpio/gpio-da9055.c3
-rw-r--r--drivers/gpio/gpio-dwapb.c2
-rw-r--r--drivers/gpio/gpio-em.c5
-rw-r--r--drivers/gpio/gpio-f7188x.c18
-rw-r--r--drivers/gpio/gpio-generic.c3
-rw-r--r--drivers/gpio/gpio-grgpio.c4
-rw-r--r--drivers/gpio/gpio-ich.c9
-rw-r--r--drivers/gpio/gpio-intel-mid.c86
-rw-r--r--drivers/gpio/gpio-it8761e.c6
-rw-r--r--drivers/gpio/gpio-janz-ttl.c8
-rw-r--r--drivers/gpio/gpio-kempld.c3
-rw-r--r--drivers/gpio/gpio-lp3943.c3
-rw-r--r--drivers/gpio/gpio-lpc32xx.c2
-rw-r--r--drivers/gpio/gpio-lynxpoint.c98
-rw-r--r--drivers/gpio/gpio-max730x.c13
-rw-r--r--drivers/gpio/gpio-max732x.c7
-rw-r--r--drivers/gpio/gpio-mc33880.c11
-rw-r--r--drivers/gpio/gpio-mc9s08dz60.c3
-rw-r--r--drivers/gpio/gpio-mcp23s08.c26
-rw-r--r--drivers/gpio/gpio-ml-ioh.c8
-rw-r--r--drivers/gpio/gpio-msm-v2.c5
-rw-r--r--drivers/gpio/gpio-mxc.c2
-rw-r--r--drivers/gpio/gpio-octeon.c3
-rw-r--r--drivers/gpio/gpio-omap.c275
-rw-r--r--drivers/gpio/gpio-palmas.c3
-rw-r--r--drivers/gpio/gpio-pca953x.c7
-rw-r--r--drivers/gpio/gpio-pcf857x.c4
-rw-r--r--drivers/gpio/gpio-pch.c10
-rw-r--r--drivers/gpio/gpio-pxa.c7
-rw-r--r--drivers/gpio/gpio-rc5t583.c3
-rw-r--r--drivers/gpio/gpio-rcar.c9
-rw-r--r--drivers/gpio/gpio-rdc321x.c7
-rw-r--r--drivers/gpio/gpio-samsung.c965
-rw-r--r--drivers/gpio/gpio-sch.c16
-rw-r--r--drivers/gpio/gpio-sch311x.c6
-rw-r--r--drivers/gpio/gpio-sodaville.c4
-rw-r--r--drivers/gpio/gpio-stmpe.c119
-rw-r--r--drivers/gpio/gpio-sx150x.c7
-rw-r--r--drivers/gpio/gpio-syscon.c3
-rw-r--r--drivers/gpio/gpio-tb10x.c5
-rw-r--r--drivers/gpio/gpio-tc3589x.c8
-rw-r--r--drivers/gpio/gpio-timberdale.c5
-rw-r--r--drivers/gpio/gpio-tps6586x.c3
-rw-r--r--drivers/gpio/gpio-tps65910.c3
-rw-r--r--drivers/gpio/gpio-tps65912.c3
-rw-r--r--drivers/gpio/gpio-ts5500.c6
-rw-r--r--drivers/gpio/gpio-twl4030.c6
-rw-r--r--drivers/gpio/gpio-twl6040.c3
-rw-r--r--drivers/gpio/gpio-ucb1400.c4
-rw-r--r--drivers/gpio/gpio-viperboard.c10
-rw-r--r--drivers/gpio/gpio-vr41xx.c8
-rw-r--r--drivers/gpio/gpio-vx855.c3
-rw-r--r--drivers/gpio/gpio-wm831x.c3
-rw-r--r--drivers/gpio/gpio-wm8350.c3
-rw-r--r--drivers/gpio/gpio-wm8994.c3
-rw-r--r--drivers/gpio/gpio-zynq.c692
-rw-r--r--drivers/gpio/gpiolib-acpi.c44
-rw-r--r--drivers/gpio/gpiolib-legacy.c102
-rw-r--r--drivers/gpio/gpiolib-of.c10
-rw-r--r--drivers/gpio/gpiolib-sysfs.c827
-rw-r--r--drivers/gpio/gpiolib.c1273
-rw-r--r--drivers/gpio/gpiolib.h105
-rw-r--r--drivers/gpu/drm/Kconfig3
-rw-r--r--drivers/gpu/drm/Makefile8
-rw-r--r--drivers/gpu/drm/armada/armada_510.c23
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c193
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h11
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h13
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c245
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c4
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c2
-rw-r--r--drivers/gpu/drm/armada/armada_output.c4
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c2
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h2
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c6
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c16
-rw-r--r--drivers/gpu/drm/bochs/bochs_drv.c4
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c7
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c17
-rw-r--r--drivers/gpu/drm/bochs/bochs_mm.c2
-rw-r--r--drivers/gpu/drm/bridge/ptn3460.c2
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.c4
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.h2
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c6
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c14
-rw-r--r--drivers/gpu/drm/drm_buffer.c6
-rw-r--r--drivers/gpu/drm/drm_bufs.c17
-rw-r--r--drivers/gpu/drm/drm_context.c102
-rw-r--r--drivers/gpu/drm/drm_crtc.c604
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c1
-rw-r--r--drivers/gpu/drm/drm_debugfs.c182
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c2715
-rw-r--r--drivers/gpu/drm/drm_drv.c1190
-rw-r--r--drivers/gpu/drm/drm_edid.c11
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c5
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c115
-rw-r--r--drivers/gpu/drm/drm_fops.c85
-rw-r--r--drivers/gpu/drm/drm_gem.c29
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c2
-rw-r--r--drivers/gpu/drm/drm_hashtab.c2
-rw-r--r--drivers/gpu/drm/drm_info.c2
-rw-r--r--drivers/gpu/drm/drm_ioctl.c372
-rw-r--r--drivers/gpu/drm/drm_irq.c16
-rw-r--r--drivers/gpu/drm/drm_legacy.h51
-rw-r--r--drivers/gpu/drm/drm_lock.c1
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c14
-rw-r--r--drivers/gpu/drm/drm_of.c67
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c7
-rw-r--r--drivers/gpu/drm/drm_prime.c8
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c9
-rw-r--r--drivers/gpu/drm/drm_rect.c140
-rw-r--r--drivers/gpu/drm/drm_stub.c805
-rw-r--r--drivers/gpu/drm/drm_sysfs.c92
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c117
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_connector.c21
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dmabuf.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c285
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c277
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c29
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c259
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c38
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c57
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_crt.c4
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c4
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_hdmi.c4
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c4
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c5
-rw-r--r--drivers/gpu/drm/gma500/gtt.c2
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.c4
-rw-r--r--drivers/gpu/drm/gma500/mid_bios.c1
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi.c4
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds.c2
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c2
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c4
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_sdvo.c4
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c390
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c5
-rw-r--r--drivers/gpu/drm/i915/Kconfig12
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/i915_cmd_parser.c3
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c425
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c73
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c70
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h192
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c128
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c149
-rw-r--r--drivers/gpu/drm/i915/i915_gem_dmabuf.c3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c308
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c64
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem_render_state.c161
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c104
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c149
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c122
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c639
-rw-r--r--drivers/gpu/drm/i915/i915_params.c11
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h550
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c57
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c5
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c38
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c474
-rw-r--r--drivers/gpu/drm/i915/intel_display.c1463
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c743
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c548
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h155
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c57
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.h1
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_cmd.c16
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_cmd.h1
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_panel_vbt.c8
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_pll.c81
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c10
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c37
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c102
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c54
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c20
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c3
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c22
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c160
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c950
-rw-r--r--drivers/gpu/drm/i915/intel_renderstate.h2
-rw-r--r--drivers/gpu/drm/i915/intel_renderstate_gen6.c1
-rw-r--r--drivers/gpu/drm/i915/intel_renderstate_gen7.c1
-rw-r--r--drivers/gpu/drm/i915/intel_renderstate_gen8.c1
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c491
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h92
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c10
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c36
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c2
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c212
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c5
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c16
-rw-r--r--drivers/gpu/drm/msm/Kconfig1
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h58
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h296
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c7
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.h5
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h56
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c14
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h239
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h4
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h4
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h4
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c69
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h1
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h109
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c27
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c377
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c25
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h431
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c159
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h25
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h4
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c91
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c49
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c17
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c12
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c31
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h8
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig12
-rw-r--r--drivers/gpu/drm/nouveau/Makefile25
-rw-r--r--drivers/gpu/drm/nouveau/core/core/client.c162
-rw-r--r--drivers/gpu/drm/nouveau/core/core/event.c176
-rw-r--r--drivers/gpu/drm/nouveau/core/core/handle.c115
-rw-r--r--drivers/gpu/drm/nouveau/core/core/ioctl.c531
-rw-r--r--drivers/gpu/drm/nouveau/core/core/notify.c167
-rw-r--r--drivers/gpu/drm/nouveau/core/core/object.c154
-rw-r--r--drivers/gpu/drm/nouveau/core/core/parent.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nva3.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nve0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/acpi.c59
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/acpi.h9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/base.c396
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/ctrl.c153
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/gm100.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv10.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv20.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv30.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv40.c32
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv50.c36
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c54
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/base.c96
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/conn.c63
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/conn.h5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c85
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/gm107.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c28
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c28
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c137
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c477
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h131
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c32
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c380
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c100
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c88
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c157
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c160
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c210
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c170
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c157
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c113
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c32
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c58
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c83
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c58
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c64
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c104
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c121
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c56
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c123
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h65
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c64
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c81
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c85
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c74
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c117
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gm107.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv04.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv10.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv108.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv20.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv25.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv30.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv34.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv35.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c271
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h40
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve4.c39
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/base.c128
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv04.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv10.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.c39
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.h5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h470
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/client.h11
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/device.h18
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/event.h51
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/handle.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/ioctl.h6
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/notify.h36
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/object.h29
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/parent.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/printk.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/disp.h11
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h27
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/fifo.h11
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/graph.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/engine/perfmon.h1
l---------drivers/gpu/drm/nouveau/core/include/nvif/class.h1
l---------drivers/gpu/drm/nouveau/core/include/nvif/event.h1
l---------drivers/gpu/drm/nouveau/core/include/nvif/ioctl.h1
l---------drivers/gpu/drm/nouveau/core/include/nvif/unpack.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/bar.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/clock.h30
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/gpio.h16
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/i2c.h23
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/ltc.h35
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h41
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/mc.h31
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/pwr.h43
-rw-r--r--drivers/gpu/drm/nouveau/core/os.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/base.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c54
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/base.c197
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c665
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c11
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/base.c50
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c45
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/base.c126
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c (renamed from drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c)167
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c58
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c (renamed from drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c)121
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h69
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h21
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/base.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c38
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/priv.h38
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/base.c33
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h658
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h222
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h222
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h222
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c69
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c43
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c51
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c43
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c43
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h44
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/arb.c12
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c42
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/cursor.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dac.c54
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/dfp.c14
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c12
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.h8
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.c114
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/hw.h84
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/overlay.c120
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv04.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.c27
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/tvnv17.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c246
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_agp.c33
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c57
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c41
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c152
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c246
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c80
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c293
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c308
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.h70
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c142
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c37
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c88
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hwmon.c58
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_nvif.c136
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.c183
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.h49
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_prime.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sysfs.c88
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sysfs.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c41
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.c384
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.h9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c14
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c59
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fence.c4
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.c9
-rw-r--r--drivers/gpu/drm/nouveau/nv10_fence.h3
-rw-r--r--drivers/gpu/drm/nouveau/nv17_fence.c28
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c920
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c13
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fence.c31
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fence.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvif/class.h558
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.c129
-rw-r--r--drivers/gpu/drm/nouveau/nvif/client.h39
-rw-r--r--drivers/gpu/drm/nouveau/nvif/device.c78
-rw-r--r--drivers/gpu/drm/nouveau/nvif/device.h62
-rw-r--r--drivers/gpu/drm/nouveau/nvif/driver.h21
-rw-r--r--drivers/gpu/drm/nouveau/nvif/event.h62
-rw-r--r--drivers/gpu/drm/nouveau/nvif/ioctl.h128
-rw-r--r--drivers/gpu/drm/nouveau/nvif/list.h353
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.c248
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.h39
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c304
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.h75
l---------drivers/gpu/drm/nouveau/nvif/os.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvif/unpack.h24
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c16
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h8
-rw-r--r--drivers/gpu/drm/omapdrm/omap_encoder.c27
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c33
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_plane.c21
-rw-r--r--drivers/gpu/drm/panel/Kconfig7
-rw-r--r--drivers/gpu/drm/panel/panel-ld9040.c21
-rw-r--r--drivers/gpu/drm/panel/panel-s6e8aa0.c29
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c203
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.h4
-rw-r--r--drivers/gpu/drm/radeon/Makefile2
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c16
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c13
-rw-r--r--drivers/gpu/drm/radeon/ci_smc.c39
-rw-r--r--drivers/gpu/drm/radeon/cik.c722
-rw-r--r--drivers/gpu/drm/radeon/cik_sdma.c247
-rw-r--r--drivers/gpu/drm/radeon/dce6_afmt.c16
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c18
-rw-r--r--drivers/gpu/drm/radeon/evergreen_hdmi.c4
-rw-r--r--drivers/gpu/drm/radeon/ni.c1
-rw-r--r--drivers/gpu/drm/radeon/ni_dma.c178
-rw-r--r--drivers/gpu/drm/radeon/r100.c62
-rw-r--r--drivers/gpu/drm/radeon/r300.c13
-rw-r--r--drivers/gpu/drm/radeon/r600.c24
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon.h127
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c79
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h77
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c83
-rw-r--r--drivers/gpu/drm/radeon/radeon_benchmark.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c388
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c87
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c72
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_gart.c38
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c58
-rw-r--r--drivers/gpu/drm/radeon/radeon_ib.c319
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c63
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h6
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_prime.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c287
-rw-r--r--drivers/gpu/drm/radeon/radeon_sa.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_test.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_trace.h22
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_ucode.c167
-rw-r--r--drivers/gpu/drm/radeon/radeon_ucode.h71
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_vce.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_vm.c278
-rw-r--r--drivers/gpu/drm/radeon/rs400.c14
-rw-r--r--drivers/gpu/drm/radeon/rs600.c17
-rw-r--r--drivers/gpu/drm/radeon/rv770.c1
-rw-r--r--drivers/gpu/drm/radeon/si.c460
-rw-r--r--drivers/gpu/drm/radeon/si_dma.c172
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c152
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.h5
-rw-r--r--drivers/gpu/drm/radeon/si_smc.c62
-rw-r--r--drivers/gpu/drm/radeon/sislands_smc.h3
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c13
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vgacon.c4
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c6
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.c2
-rw-r--r--drivers/gpu/drm/sti/Kconfig14
-rw-r--r--drivers/gpu/drm/sti/Makefile21
-rw-r--r--drivers/gpu/drm/sti/NOTES58
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c281
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.h90
-rw-r--r--drivers/gpu/drm/sti/sti_drm_crtc.c421
-rw-r--r--drivers/gpu/drm/sti/sti_drm_crtc.h22
-rw-r--r--drivers/gpu/drm/sti/sti_drm_drv.c241
-rw-r--r--drivers/gpu/drm/sti/sti_drm_drv.h29
-rw-r--r--drivers/gpu/drm/sti/sti_drm_plane.c195
-rw-r--r--drivers/gpu/drm/sti/sti_drm_plane.h18
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c549
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.h16
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c794
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c810
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.h88
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c336
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h14
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c211
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h14
-rw-r--r--drivers/gpu/drm/sti/sti_layer.c197
-rw-r--r--drivers/gpu/drm/sti/sti_layer.h123
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c249
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.h54
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c648
-rw-r--r--drivers/gpu/drm/sti/sti_vid.c138
-rw-r--r--drivers/gpu/drm/sti/sti_vid.h12
-rw-r--r--drivers/gpu/drm/sti/sti_vtac.c215
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.c366
-rw-r--r--drivers/gpu/drm/sti/sti_vtg.h28
-rw-r--r--drivers/gpu/drm/tegra/dc.c123
-rw-r--r--drivers/gpu/drm/tegra/dc.h5
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c1
-rw-r--r--drivers/gpu/drm/tegra/drm.c216
-rw-r--r--drivers/gpu/drm/tegra/drm.h11
-rw-r--r--drivers/gpu/drm/tegra/dsi.c4
-rw-r--r--drivers/gpu/drm/tegra/fb.c66
-rw-r--r--drivers/gpu/drm/tegra/gem.c7
-rw-r--r--drivers/gpu/drm/tegra/gem.h16
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c1
-rw-r--r--drivers/gpu/drm/tegra/gr3d.c4
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c1
-rw-r--r--drivers/gpu/drm/tegra/output.c6
-rw-r--r--drivers/gpu/drm/tegra/sor.c24
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c15
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h1
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c41
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.c29
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.c37
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c20
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_manager.c3
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_module.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_object.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c31
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c36
-rw-r--r--drivers/gpu/drm/ttm/ttm_tt.c13
-rw-r--r--drivers/gpu/drm/udl/udl_connector.c13
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c5
-rw-r--r--drivers/gpu/drm/udl/udl_gem.c8
-rw-r--r--drivers/gpu/drm/udl/udl_main.c15
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c21
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c341
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c38
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c9
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h78
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c227
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_marker.c44
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c396
-rw-r--r--drivers/gpu/host1x/job.c22
-rw-r--r--drivers/gpu/vga/vgaarb.c40
-rw-r--r--drivers/hid/Kconfig45
-rw-r--r--drivers/hid/Makefile7
-rw-r--r--drivers/hid/hid-core.c24
-rw-r--r--drivers/hid/hid-cp2112.c111
-rw-r--r--drivers/hid/hid-gt683r.c321
-rw-r--r--drivers/hid/hid-huion.c265
-rw-r--r--drivers/hid/hid-hyperv.c6
-rw-r--r--drivers/hid/hid-ids.h8
-rw-r--r--drivers/hid/hid-lenovo-tpkbd.c462
-rw-r--r--drivers/hid/hid-lenovo.c708
-rw-r--r--drivers/hid/hid-picolcd_cir.c2
-rw-r--r--drivers/hid/hid-picolcd_debugfs.c9
-rw-r--r--drivers/hid/hid-rmi.c67
-rw-r--r--drivers/hid/hid-roccat-lua.c2
-rw-r--r--drivers/hid/hid-sony.c132
-rw-r--r--drivers/hid/hid-wacom.c973
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c15
-rw-r--r--drivers/hid/usbhid/hid-core.c8
-rw-r--r--drivers/hid/usbhid/hid-quirks.c3
-rw-r--r--drivers/hid/wacom.h (renamed from drivers/input/tablet/wacom.h)27
-rw-r--r--drivers/hid/wacom_sys.c (renamed from drivers/input/tablet/wacom_sys.c)1231
-rw-r--r--drivers/hid/wacom_wac.c (renamed from drivers/input/tablet/wacom_wac.c)1176
-rw-r--r--drivers/hid/wacom_wac.h (renamed from drivers/input/tablet/wacom_wac.h)22
-rw-r--r--drivers/hsi/clients/ssi_protocol.c4
-rw-r--r--drivers/hsi/controllers/omap_ssi.c14
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c15
-rw-r--r--drivers/hv/channel.c6
-rw-r--r--drivers/hwmon/Kconfig57
-rw-r--r--drivers/hwmon/Makefile4
-rw-r--r--drivers/hwmon/ad7414.c57
-rw-r--r--drivers/hwmon/ad7418.c133
-rw-r--r--drivers/hwmon/adm1021.c175
-rw-r--r--drivers/hwmon/adm1025.c234
-rw-r--r--drivers/hwmon/adm1026.c591
-rw-r--r--drivers/hwmon/adm1029.c208
-rw-r--r--drivers/hwmon/adm1031.c349
-rw-r--r--drivers/hwmon/adm9240.c339
-rw-r--r--drivers/hwmon/ads1015.c4
-rw-r--r--drivers/hwmon/ads7828.c52
-rw-r--r--drivers/hwmon/adt7411.c59
-rw-r--r--drivers/hwmon/adt7462.c142
-rw-r--r--drivers/hwmon/adt7470.c163
-rw-r--r--drivers/hwmon/amc6821.c397
-rw-r--r--drivers/hwmon/asb100.c4
-rw-r--r--drivers/hwmon/asc7621.c14
-rw-r--r--drivers/hwmon/asus_atk0110.c2
-rw-r--r--drivers/hwmon/atxp1.c76
-rw-r--r--drivers/hwmon/dme1737.c33
-rw-r--r--drivers/hwmon/ds620.c60
-rw-r--r--drivers/hwmon/emc1403.c2
-rw-r--r--drivers/hwmon/emc2103.c89
-rw-r--r--drivers/hwmon/emc6w201.c68
-rw-r--r--drivers/hwmon/fam15h_power.c54
-rw-r--r--drivers/hwmon/g760a.c84
-rw-r--r--drivers/hwmon/g762.c78
-rw-r--r--drivers/hwmon/gl518sm.c319
-rw-r--r--drivers/hwmon/gl520sm.c353
-rw-r--r--drivers/hwmon/gpio-fan.c19
-rw-r--r--drivers/hwmon/hih6130.c85
-rw-r--r--drivers/hwmon/htu21.c69
-rw-r--r--drivers/hwmon/ibmaem.c6
-rw-r--r--drivers/hwmon/ibmpowernv.c363
-rw-r--r--drivers/hwmon/lineage-pem.c66
-rw-r--r--drivers/hwmon/lm63.c27
-rw-r--r--drivers/hwmon/lm75.c8
-rw-r--r--drivers/hwmon/lm77.c11
-rw-r--r--drivers/hwmon/lm78.c100
-rw-r--r--drivers/hwmon/lm85.c660
-rw-r--r--drivers/hwmon/lm87.c4
-rw-r--r--drivers/hwmon/lm92.c13
-rw-r--r--drivers/hwmon/lm93.c154
-rw-r--r--drivers/hwmon/ltc2945.c2
-rw-r--r--drivers/hwmon/ltc4222.c2
-rw-r--r--drivers/hwmon/ltc4260.c2
-rw-r--r--drivers/hwmon/max16065.c5
-rw-r--r--drivers/hwmon/max1668.c2
-rw-r--r--drivers/hwmon/max6639.c2
-rw-r--r--drivers/hwmon/max6697.c16
-rw-r--r--drivers/hwmon/nct6775.c14
-rw-r--r--drivers/hwmon/ntc_thermistor.c50
-rw-r--r--drivers/hwmon/pc87360.c3
-rw-r--r--drivers/hwmon/pmbus/Kconfig13
-rw-r--r--drivers/hwmon/pmbus/Makefile1
-rw-r--r--drivers/hwmon/pmbus/pmbus.c1
-rw-r--r--drivers/hwmon/pmbus/tps40422.c64
-rw-r--r--drivers/hwmon/powr1220.c391
-rw-r--r--drivers/hwmon/pwm-fan.c193
-rw-r--r--drivers/hwmon/sht21.c82
-rw-r--r--drivers/hwmon/sis5595.c2
-rw-r--r--drivers/hwmon/smm665.c44
-rw-r--r--drivers/hwmon/smsc47m1.c115
-rw-r--r--drivers/hwmon/smsc47m192.c232
-rw-r--r--drivers/hwmon/thmc50.c212
-rw-r--r--drivers/hwmon/tmp103.c199
-rw-r--r--drivers/hwmon/tmp421.c39
-rw-r--r--drivers/hwmon/twl4030-madc-hwmon.c38
-rw-r--r--drivers/hwmon/vt1211.c3
-rw-r--r--drivers/hwmon/w83627hf.c3
-rw-r--r--drivers/hwmon/w83791d.c18
-rw-r--r--drivers/hwmon/w83793.c3
-rw-r--r--drivers/hwmon/w83l786ng.c289
-rw-r--r--drivers/hwmon/wm831x-hwmon.c72
-rw-r--r--drivers/hwmon/wm8350-hwmon.c50
-rw-r--r--drivers/hwspinlock/Kconfig2
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c27
-rw-r--r--drivers/i2c/Kconfig18
-rw-r--r--drivers/i2c/Makefile5
-rw-r--r--drivers/i2c/busses/Kconfig46
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-at91.c6
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c2
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c2
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c17
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c9
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c3
-rw-r--r--drivers/i2c/busses/i2c-efm32.c8
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c16
-rw-r--r--drivers/i2c/busses/i2c-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c139
-rw-r--r--drivers/i2c/busses/i2c-imx.c5
-rw-r--r--drivers/i2c/busses/i2c-mpc.c3
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c8
-rw-r--r--drivers/i2c/busses/i2c-ocores.c12
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-qup.c12
-rw-r--r--drivers/i2c/busses/i2c-rcar.c14
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c16
-rw-r--r--drivers/i2c/busses/i2c-s6000.c404
-rw-r--r--drivers/i2c/busses/i2c-s6000.h79
-rw-r--r--drivers/i2c/busses/i2c-sirf.c2
-rw-r--r--drivers/i2c/busses/i2c-st.c34
-rw-r--r--drivers/i2c/busses/i2c-stu300.c2
-rw-r--r--drivers/i2c/busses/i2c-taos-evm.c13
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/i2c/busses/i2c-xiic.c12
-rw-r--r--drivers/i2c/busses/scx200_i2c.c129
-rw-r--r--drivers/i2c/i2c-acpi.c362
-rw-r--r--drivers/i2c/i2c-core.c112
-rw-r--r--drivers/i2c/i2c-stub.c237
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c15
-rw-r--r--drivers/ide/au1xxx-ide.c13
-rw-r--r--drivers/ide/ide_platform.c13
-rw-r--r--drivers/iio/accel/Kconfig12
-rw-r--r--drivers/iio/accel/Makefile1
-rw-r--r--drivers/iio/accel/kxcjk-1013.c764
-rw-r--r--drivers/iio/accel/mma8452.c6
-rw-r--r--drivers/iio/accel/st_accel_core.c12
-rw-r--r--drivers/iio/accel/st_accel_i2c.c51
-rw-r--r--drivers/iio/adc/Kconfig19
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ad7291.c (renamed from drivers/staging/iio/adc/ad7291.c)107
-rw-r--r--drivers/iio/adc/ad7298.c21
-rw-r--r--drivers/iio/adc/ad7476.c5
-rw-r--r--drivers/iio/adc/ad7887.c21
-rw-r--r--drivers/iio/adc/ad799x.c507
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c2
-rw-r--r--drivers/iio/adc/at91_adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c335
-rw-r--r--drivers/iio/adc/max1027.c521
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c6
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c5
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c64
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_i2c.c30
-rw-r--r--drivers/iio/dac/Kconfig10
-rw-r--r--drivers/iio/dac/Makefile1
-rw-r--r--drivers/iio/dac/ad5504.c16
-rw-r--r--drivers/iio/dac/ad5624r_spi.c5
-rw-r--r--drivers/iio/dac/ad5686.c3
-rw-r--r--drivers/iio/dac/ad5791.c29
-rw-r--r--drivers/iio/dac/mcp4922.c216
-rw-r--r--drivers/iio/gyro/adis16260.c124
-rw-r--r--drivers/iio/gyro/itg3200_core.c101
-rw-r--r--drivers/iio/gyro/st_gyro_core.c12
-rw-r--r--drivers/iio/gyro/st_gyro_i2c.c39
-rw-r--r--drivers/iio/imu/adis16400_buffer.c3
-rw-r--r--drivers/iio/imu/adis16400_core.c78
-rw-r--r--drivers/iio/imu/adis16480.c82
-rw-r--r--drivers/iio/industrialio-buffer.c5
-rw-r--r--drivers/iio/industrialio-core.c4
-rw-r--r--drivers/iio/industrialio-event.c1
-rw-r--r--drivers/iio/industrialio-trigger.c8
-rw-r--r--drivers/iio/light/Kconfig24
-rw-r--r--drivers/iio/light/Makefile2
-rw-r--r--drivers/iio/light/cm32181.c11
-rw-r--r--drivers/iio/light/gp2ap020a00f.c2
-rw-r--r--drivers/iio/light/isl29125.c347
-rw-r--r--drivers/iio/light/tcs3414.c405
-rw-r--r--drivers/iio/magnetometer/Kconfig10
-rw-r--r--drivers/iio/magnetometer/Makefile1
-rw-r--r--drivers/iio/magnetometer/ak09911.c326
-rw-r--r--drivers/iio/magnetometer/ak8975.c58
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c202
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c12
-rw-r--r--drivers/iio/magnetometer/st_magn_i2c.c23
-rw-r--r--drivers/iio/pressure/Kconfig10
-rw-r--r--drivers/iio/pressure/Makefile1
-rw-r--r--drivers/iio/pressure/st_pressure_core.c27
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c23
-rw-r--r--drivers/iio/pressure/t5403.c275
-rw-r--r--drivers/iio/proximity/as3935.c2
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c3
-rw-r--r--drivers/iio/trigger/iio-trig-sysfs.c2
-rw-r--r--drivers/infiniband/core/agent.c16
-rw-r--r--drivers/infiniband/core/cm.c5
-rw-r--r--drivers/infiniband/core/iwcm.c27
-rw-r--r--drivers/infiniband/core/mad.c283
-rw-r--r--drivers/infiniband/core/mad_priv.h3
-rw-r--r--drivers/infiniband/core/sa_query.c2
-rw-r--r--drivers/infiniband/core/user_mad.c188
-rw-r--r--drivers/infiniband/core/uverbs.h1
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c93
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c6
-rw-r--r--drivers/infiniband/hw/amso1100/c2_cq.c7
-rw-r--r--drivers/infiniband/hw/amso1100/c2_provider.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c112
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c14
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c192
-rw-r--r--drivers/infiniband/hw/cxgb4/ev.c56
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h40
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c14
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c150
-rw-r--r--drivers/infiniband/hw/cxgb4/t4.h30
-rw-r--r--drivers/infiniband/hw/cxgb4/t4fw_ri_api.h1
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c14
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c2
-rw-r--r--drivers/infiniband/hw/mlx4/main.c8
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h4
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c88
-rw-r--r--drivers/infiniband/hw/mlx5/cq.c48
-rw-r--r--drivers/infiniband/hw/mlx5/mad.c6
-rw-r--r--drivers/infiniband/hw/mlx5/main.c295
-rw-r--r--drivers/infiniband/hw/mlx5/mem.c2
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h14
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c48
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c90
-rw-r--r--drivers/infiniband/hw/mlx5/srq.c26
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c12
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c5
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma.h26
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_ah.c6
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c227
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.h2
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c83
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_sli.h295
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c36
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c133
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c13
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c47
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h8
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c128
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c48
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c3
-rw-r--r--drivers/input/evdev.c7
-rw-r--r--drivers/input/input-mt.c38
-rw-r--r--drivers/input/joystick/analog.c2
-rw-r--r--drivers/input/joystick/xpad.c174
-rw-r--r--drivers/input/keyboard/Kconfig10
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/cap1106.c341
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c70
-rw-r--r--drivers/input/keyboard/imx_keypad.c6
-rw-r--r--drivers/input/keyboard/lm8323.c22
-rw-r--r--drivers/input/keyboard/max7359_keypad.c45
-rw-r--r--drivers/input/misc/keyspan_remote.c1
-rw-r--r--drivers/input/misc/soc_button_array.c3
-rw-r--r--drivers/input/misc/sparcspkr.c22
-rw-r--r--drivers/input/misc/uinput.c47
-rw-r--r--drivers/input/mouse/alps.c691
-rw-r--r--drivers/input/mouse/alps.h60
-rw-r--r--drivers/input/mouse/synaptics.c72
-rw-r--r--drivers/input/serio/hyperv-keyboard.c13
-rw-r--r--drivers/input/tablet/Kconfig18
-rw-r--r--drivers/input/tablet/Makefile4
-rw-r--r--drivers/input/tablet/wacom_serial4.c620
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c6
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c1343
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c4
-rw-r--r--drivers/input/touchscreen/ipaq-micro-ts.c166
-rw-r--r--drivers/input/touchscreen/jornada720_ts.c70
-rw-r--r--drivers/input/touchscreen/mcs5000_ts.c6
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c250
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c4
-rw-r--r--drivers/input/touchscreen/zforce_ts.c31
-rw-r--r--drivers/iommu/Kconfig13
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/amd_iommu.c224
-rw-r--r--drivers/iommu/amd_iommu_init.c38
-rw-r--r--drivers/iommu/amd_iommu_types.h10
-rw-r--r--drivers/iommu/amd_iommu_v2.c107
-rw-r--r--drivers/iommu/arm-smmu.c495
-rw-r--r--drivers/iommu/dmar.c40
-rw-r--r--drivers/iommu/exynos-iommu.c2
-rw-r--r--drivers/iommu/fsl_pamu.c2
-rw-r--r--drivers/iommu/fsl_pamu_domain.c73
-rw-r--r--drivers/iommu/intel-iommu.c874
-rw-r--r--drivers/iommu/intel_irq_remapping.c60
-rw-r--r--drivers/iommu/iommu-sysfs.c134
-rw-r--r--drivers/iommu/iommu.c201
-rw-r--r--drivers/iommu/ipmmu-vmsa.c2
-rw-r--r--drivers/iommu/msm_iommu.c2
-rw-r--r--drivers/iommu/omap-iommu-debug.c114
-rw-r--r--drivers/iommu/omap-iommu.c15
-rw-r--r--drivers/iommu/omap-iommu.h8
-rw-r--r--drivers/iommu/omap-iovmm.c791
-rw-r--r--drivers/iommu/pci.h29
-rw-r--r--drivers/iommu/shmobile-iommu.c2
-rw-r--r--drivers/iommu/tegra-gart.c2
-rw-r--r--drivers/iommu/tegra-smmu.c5
-rw-r--r--drivers/ipack/carriers/tpci200.c2
-rw-r--r--drivers/ipack/devices/ipoctal.c20
-rw-r--r--drivers/irqchip/Kconfig24
-rw-r--r--drivers/irqchip/Makefile6
-rw-r--r--drivers/irqchip/irq-atmel-aic-common.c254
-rw-r--r--drivers/irqchip/irq-atmel-aic-common.h39
-rw-r--r--drivers/irqchip/irq-atmel-aic.c262
-rw-r--r--drivers/irqchip/irq-atmel-aic5.c353
-rw-r--r--drivers/irqchip/irq-crossbar.c168
-rw-r--r--drivers/irqchip/irq-gic-common.c115
-rw-r--r--drivers/irqchip/irq-gic-common.h29
-rw-r--r--drivers/irqchip/irq-gic-v3.c692
-rw-r--r--drivers/irqchip/irq-gic.c61
-rw-r--r--drivers/irqchip/irq-nvic.c13
-rw-r--r--drivers/irqchip/irq-or1k-pic.c182
-rw-r--r--drivers/irqchip/irq-versatile-fpga.c18
-rw-r--r--drivers/irqchip/spear-shirq.c304
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/isdn/i4l/isdn_net.c7
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c26
-rw-r--r--drivers/isdn/pcbit/drv.c4
-rw-r--r--drivers/leds/Kconfig15
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c19
-rw-r--r--drivers/leds/led-core.c11
-rw-r--r--drivers/leds/leds-atmel-pwm.c149
-rw-r--r--drivers/leds/leds-ipaq-micro.c141
-rw-r--r--drivers/leds/leds-lm3530.c20
-rw-r--r--drivers/leds/leds-lm3533.c20
-rw-r--r--drivers/leds/leds-lm355x.c21
-rw-r--r--drivers/leds/leds-lm3642.c30
-rw-r--r--drivers/leds/leds-lp55xx-common.c20
-rw-r--r--drivers/leds/leds-max8997.c16
-rw-r--r--drivers/leds/leds-netxbig.c31
-rw-r--r--drivers/leds/leds-ns2.c16
-rw-r--r--drivers/leds/leds-pca963x.c28
-rw-r--r--drivers/leds/leds-ss4200.c14
-rw-r--r--drivers/leds/leds-wm831x-status.c23
-rw-r--r--drivers/lguest/core.c7
-rw-r--r--drivers/macintosh/via-pmu-backlight.c6
-rw-r--r--drivers/mailbox/Kconfig19
-rw-r--r--drivers/mailbox/Makefile6
-rw-r--r--drivers/mailbox/mailbox-omap1.c203
-rw-r--r--drivers/mailbox/mailbox-omap2.c357
-rw-r--r--drivers/mailbox/omap-mailbox.c444
-rw-r--r--drivers/mailbox/omap-mbox.h67
-rw-r--r--drivers/md/bcache/alloc.c2
-rw-r--r--drivers/md/bcache/bcache.h4
-rw-r--r--drivers/md/bcache/bset.c2
-rw-r--r--drivers/md/bcache/bset.h2
-rw-r--r--drivers/md/bcache/btree.c50
-rw-r--r--drivers/md/bcache/btree.h5
-rw-r--r--drivers/md/bcache/extents.c13
-rw-r--r--drivers/md/bcache/extents.h1
-rw-r--r--drivers/md/bcache/journal.c24
-rw-r--r--drivers/md/bcache/request.c3
-rw-r--r--drivers/md/bcache/super.c57
-rw-r--r--drivers/md/bcache/util.h4
-rw-r--r--drivers/md/bcache/writeback.c14
-rw-r--r--drivers/md/bcache/writeback.h3
-rw-r--r--drivers/md/dm-bufio.c41
-rw-r--r--drivers/md/dm-cache-metadata.c4
-rw-r--r--drivers/md/dm-cache-metadata.h8
-rw-r--r--drivers/md/dm-cache-target.c128
-rw-r--r--drivers/md/dm-crypt.c41
-rw-r--r--drivers/md/dm-io.c77
-rw-r--r--drivers/md/dm-mpath.c6
-rw-r--r--drivers/md/dm-snap.c10
-rw-r--r--drivers/md/dm-switch.c67
-rw-r--r--drivers/md/dm-table.c86
-rw-r--r--drivers/md/dm-thin.c181
-rw-r--r--drivers/md/dm.h1
-rw-r--r--drivers/md/md.c13
-rw-r--r--drivers/md/raid0.c6
-rw-r--r--drivers/md/raid1.c8
-rw-r--r--drivers/md/raid10.c11
-rw-r--r--drivers/media/Kconfig12
-rw-r--r--drivers/media/common/saa7146/saa7146_core.c15
-rw-r--r--drivers/media/common/saa7146/saa7146_fops.c19
-rw-r--r--drivers/media/common/siano/Kconfig3
-rw-r--r--drivers/media/common/siano/smsir.c2
-rw-r--r--drivers/media/dvb-core/dvb-usb-ids.h2
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c36
-rw-r--r--drivers/media/dvb-core/dvb_frontend.h6
-rw-r--r--drivers/media/dvb-core/dvb_net.c3
-rw-r--r--drivers/media/dvb-core/dvbdev.h4
-rw-r--r--drivers/media/dvb-frontends/Kconfig18
-rw-r--r--drivers/media/dvb-frontends/Makefile7
-rw-r--r--drivers/media/dvb-frontends/af9013.c1
-rw-r--r--drivers/media/dvb-frontends/au8522_decoder.c180
-rw-r--r--drivers/media/dvb-frontends/au8522_priv.h2
-rw-r--r--drivers/media/dvb-frontends/cxd2820r.h6
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_c.c1
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_t.c1
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_t2.c1
-rw-r--r--drivers/media/dvb-frontends/dib0090.c15
-rw-r--r--drivers/media/dvb-frontends/dib7000m.c5
-rw-r--r--drivers/media/dvb-frontends/dib7000p.c433
-rw-r--r--drivers/media/dvb-frontends/dib7000p.h131
-rw-r--r--drivers/media/dvb-frontends/dib8000.c732
-rw-r--r--drivers/media/dvb-frontends/dib8000.h150
-rw-r--r--drivers/media/dvb-frontends/dib9000.c13
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c228
-rw-r--r--drivers/media/dvb-frontends/drxd.h1
-rw-r--r--drivers/media/dvb-frontends/drxd_hard.c3
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c85
-rw-r--r--drivers/media/dvb-frontends/m88ds3103_priv.h2
-rw-r--r--drivers/media/dvb-frontends/mb86a20s.c35
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c (renamed from drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c)100
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.h (renamed from drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h)0
-rw-r--r--drivers/media/dvb-frontends/si2165.c1040
-rw-r--r--drivers/media/dvb-frontends/si2165.h62
-rw-r--r--drivers/media/dvb-frontends/si2165_priv.h23
-rw-r--r--drivers/media/dvb-frontends/si2168.c266
-rw-r--r--drivers/media/dvb-frontends/si2168_priv.h9
-rw-r--r--drivers/media/dvb-frontends/stb6100_cfg.h42
-rw-r--r--drivers/media/dvb-frontends/stb6100_proc.h34
-rw-r--r--drivers/media/dvb-frontends/stv0367.c9
-rw-r--r--drivers/media/dvb-frontends/tda18271c2dd.c2
-rw-r--r--drivers/media/dvb-frontends/tda18271c2dd_maps.h8
-rw-r--r--drivers/media/dvb-frontends/tda8261_cfg.h30
-rw-r--r--drivers/media/i2c/Kconfig1
-rw-r--r--drivers/media/i2c/adv7180.c1
-rw-r--r--drivers/media/i2c/adv7604.c5
-rw-r--r--drivers/media/i2c/ir-kbd-i2c.c95
-rw-r--r--drivers/media/i2c/mt9v032.c170
-rw-r--r--drivers/media/i2c/noon010pc30.c1
-rw-r--r--drivers/media/i2c/s5k4ecgx.c1
-rw-r--r--drivers/media/i2c/s5k5baf.c2
-rw-r--r--drivers/media/i2c/s5k6a3.c1
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c17
-rw-r--r--drivers/media/i2c/soc_camera/mt9m001.c6
-rw-r--r--drivers/media/i2c/soc_camera/mt9m111.c12
-rw-r--r--drivers/media/i2c/soc_camera/mt9t031.c6
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c4
-rw-r--r--drivers/media/i2c/tvp5150.c35
-rw-r--r--drivers/media/media-device.c2
-rw-r--r--drivers/media/parport/bw-qcam.c3
-rw-r--r--drivers/media/parport/c-qcam.c1
-rw-r--r--drivers/media/parport/pms.c1
-rw-r--r--drivers/media/parport/w9966.c1
-rw-r--r--drivers/media/pci/Kconfig1
-rw-r--r--drivers/media/pci/Makefile1
-rw-r--r--drivers/media/pci/bt8xx/bt878.c16
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c1
-rw-r--r--drivers/media/pci/bt8xx/bttv-input.c78
-rw-r--r--drivers/media/pci/bt8xx/bttvp.h2
-rw-r--r--drivers/media/pci/cx18/cx18-alsa.h1
-rw-r--r--drivers/media/pci/cx18/cx18-ioctl.c1
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c1
-rw-r--r--drivers/media/pci/cx23885/Kconfig2
-rw-r--r--drivers/media/pci/cx23885/cx23885-417.c8
-rw-r--r--drivers/media/pci/cx23885/cx23885-cards.c61
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c175
-rw-r--r--drivers/media/pci/cx23885/cx23885-input.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c11
-rw-r--r--drivers/media/pci/cx23885/cx23885.h2
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c4
-rw-r--r--drivers/media/pci/cx88/cx88-core.c1
-rw-r--r--drivers/media/pci/cx88/cx88-input.c38
-rw-r--r--drivers/media/pci/ddbridge/ddbridge-core.c35
-rw-r--r--drivers/media/pci/dm1105/dm1105.c3
-rw-r--r--drivers/media/pci/ivtv/ivtv-controls.c4
-rw-r--r--drivers/media/pci/ivtv/ivtv-i2c.c9
-rw-r--r--drivers/media/pci/ivtv/ivtv-ioctl.c3
-rw-r--r--drivers/media/pci/ivtv/ivtv-streams.c1
-rw-r--r--drivers/media/pci/meye/meye.c3
-rw-r--r--drivers/media/pci/ngene/ngene-core.c14
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c4
-rw-r--r--drivers/media/pci/saa7134/saa7134-input.c86
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-dvb.c32
-rw-r--r--drivers/media/pci/solo6x10/Kconfig (renamed from drivers/staging/media/solo6x10/Kconfig)3
-rw-r--r--drivers/media/pci/solo6x10/Makefile (renamed from drivers/staging/media/solo6x10/Makefile)2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-core.c (renamed from drivers/staging/media/solo6x10/solo6x10-core.c)6
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-disp.c (renamed from drivers/staging/media/solo6x10/solo6x10-disp.c)20
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-eeprom.c (renamed from drivers/staging/media/solo6x10/solo6x10-eeprom.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-enc.c (renamed from drivers/staging/media/solo6x10/solo6x10-enc.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-g723.c (renamed from drivers/staging/media/solo6x10/solo6x10-g723.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-gpio.c (renamed from drivers/staging/media/solo6x10/solo6x10-gpio.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-i2c.c (renamed from drivers/staging/media/solo6x10/solo6x10-i2c.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-jpeg.h (renamed from drivers/staging/media/solo6x10/solo6x10-jpeg.h)6
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-offsets.h (renamed from drivers/staging/media/solo6x10/solo6x10-offsets.h)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-p2m.c (renamed from drivers/staging/media/solo6x10/solo6x10-p2m.c)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-regs.h (renamed from drivers/staging/media/solo6x10/solo6x10-regs.h)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-tw28.c (renamed from drivers/staging/media/solo6x10/solo6x10-tw28.c)5
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-tw28.h (renamed from drivers/staging/media/solo6x10/solo6x10-tw28.h)4
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c (renamed from drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c)207
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-v4l2.c (renamed from drivers/staging/media/solo6x10/solo6x10-v4l2.c)9
-rw-r--r--drivers/media/pci/solo6x10/solo6x10.h (renamed from drivers/staging/media/solo6x10/solo6x10.h)30
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c2
-rw-r--r--drivers/media/pci/ttpci/budget-ci.c10
-rw-r--r--drivers/media/pci/zoran/zr36050.h1
-rw-r--r--drivers/media/platform/Kconfig7
-rw-r--r--drivers/media/platform/arv.c1
-rw-r--r--drivers/media/platform/blackfin/bfin_capture.c9
-rw-r--r--drivers/media/platform/blackfin/ppi.c25
-rw-r--r--drivers/media/platform/coda.c1518
-rw-r--r--drivers/media/platform/coda.h115
-rw-r--r--drivers/media/platform/davinci/dm644x_ccdc.c5
-rw-r--r--drivers/media/platform/davinci/vpbe_display.c1
-rw-r--r--drivers/media/platform/davinci/vpfe_capture.c1
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c248
-rw-r--r--drivers/media/platform/davinci/vpif_capture.h11
-rw-r--r--drivers/media/platform/davinci/vpif_display.c4
-rw-r--r--drivers/media/platform/m2m-deinterlace.c7
-rw-r--r--drivers/media/platform/mem2mem_testdev.c1
-rw-r--r--drivers/media/platform/omap/omap_vout.c2
-rw-r--r--drivers/media/platform/s3c-camif/camif-capture.c3
-rw-r--r--drivers/media/platform/s5p-jpeg/Makefile2
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c660
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.h32
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c487
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h60
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-regs.h247
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c17
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_common.h11
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c49
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c9
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c6
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_pm.c24
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c2
-rw-r--r--drivers/media/platform/sh_veu.c2
-rw-r--r--drivers/media/platform/soc_camera/Kconfig18
-rw-r--r--drivers/media/platform/soc_camera/Makefile1
-rw-r--r--drivers/media/platform/soc_camera/atmel-isi.c90
-rw-r--r--drivers/media/platform/soc_camera/mx1_camera.c866
-rw-r--r--drivers/media/platform/soc_camera/pxa_camera.c81
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c82
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c141
-rw-r--r--drivers/media/platform/vino.c5
-rw-r--r--drivers/media/platform/vivi.c11
-rw-r--r--drivers/media/platform/vsp1/vsp1.h14
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c85
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.h9
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c22
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c42
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.h10
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c72
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c107
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.h1
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c63
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.h6
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c219
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.h11
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c72
-rw-r--r--drivers/media/radio/dsbr100.c1
-rw-r--r--drivers/media/radio/radio-cadet.c1
-rw-r--r--drivers/media/radio/radio-isa.c1
-rw-r--r--drivers/media/radio/radio-keene.c3
-rw-r--r--drivers/media/radio/radio-ma901.c1
-rw-r--r--drivers/media/radio/radio-miropcm20.c304
-rw-r--r--drivers/media/radio/radio-mr800.c3
-rw-r--r--drivers/media/radio/radio-raremono.c1
-rw-r--r--drivers/media/radio/radio-sf16fmi.c1
-rw-r--r--drivers/media/radio/radio-si476x.c1
-rw-r--r--drivers/media/radio/radio-tea5764.c1
-rw-r--r--drivers/media/radio/radio-tea5777.c1
-rw-r--r--drivers/media/radio/radio-timb.c1
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c1
-rw-r--r--drivers/media/radio/si4713/radio-platform-si4713.c1
-rw-r--r--drivers/media/radio/si4713/radio-usb-si4713.c1
-rw-r--r--drivers/media/radio/si4713/si4713.c80
-rw-r--r--drivers/media/radio/si4713/si4713.h9
-rw-r--r--drivers/media/radio/tea575x.c1
-rw-r--r--drivers/media/rc/Kconfig32
-rw-r--r--drivers/media/rc/Makefile5
-rw-r--r--drivers/media/rc/ati_remote.c159
-rw-r--r--drivers/media/rc/ene_ir.c2
-rw-r--r--drivers/media/rc/fintek-cir.c6
-rw-r--r--drivers/media/rc/gpio-ir-recv.c4
-rw-r--r--drivers/media/rc/iguanair.c2
-rw-r--r--drivers/media/rc/img-ir/img-ir-core.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.c31
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.h8
-rw-r--r--drivers/media/rc/img-ir/img-ir-jvc.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-nec.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.h5
-rw-r--r--drivers/media/rc/img-ir/img-ir-sanyo.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-sharp.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-sony.c17
-rw-r--r--drivers/media/rc/img-ir/img-ir.h5
-rw-r--r--drivers/media/rc/imon.c20
-rw-r--r--drivers/media/rc/ir-jvc-decoder.c4
-rw-r--r--drivers/media/rc/ir-lirc-codec.c2
-rw-r--r--drivers/media/rc/ir-mce_kbd-decoder.c2
-rw-r--r--drivers/media/rc/ir-nec-decoder.c4
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c85
-rw-r--r--drivers/media/rc/ir-rc5-sz-decoder.c154
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c43
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c4
-rw-r--r--drivers/media/rc/ir-sharp-decoder.c4
-rw-r--r--drivers/media/rc/ir-sony-decoder.c16
-rw-r--r--drivers/media/rc/ir-xmp-decoder.c225
-rw-r--r--drivers/media/rc/ite-cir.c6
-rw-r--r--drivers/media/rc/keymaps/rc-ati-x10.c92
-rw-r--r--drivers/media/rc/keymaps/rc-behold.c68
-rw-r--r--drivers/media/rc/keymaps/rc-nebula.c112
-rw-r--r--drivers/media/rc/keymaps/rc-streamzap.c4
-rw-r--r--drivers/media/rc/mceusb.c33
-rw-r--r--drivers/media/rc/nuvoton-cir.c6
-rw-r--r--drivers/media/rc/rc-core-priv.h20
-rw-r--r--drivers/media/rc/rc-ir-raw.c (renamed from drivers/media/rc/ir-raw.c)12
-rw-r--r--drivers/media/rc/rc-loopback.c2
-rw-r--r--drivers/media/rc/rc-main.c301
-rw-r--r--drivers/media/rc/redrat3.c2
-rw-r--r--drivers/media/rc/st_rc.c2
-rw-r--r--drivers/media/rc/streamzap.c12
-rw-r--r--drivers/media/rc/sunxi-cir.c318
-rw-r--r--drivers/media/rc/ttusbir.c2
-rw-r--r--drivers/media/rc/winbond-cir.c2
-rw-r--r--drivers/media/tuners/Kconfig11
-rw-r--r--drivers/media/tuners/Makefile1
-rw-r--r--drivers/media/tuners/msi001.c (renamed from drivers/staging/media/msi3101/msi001.c)2
-rw-r--r--drivers/media/tuners/r820t.c3
-rw-r--r--drivers/media/tuners/si2157.c257
-rw-r--r--drivers/media/tuners/si2157.h7
-rw-r--r--drivers/media/tuners/si2157_priv.h9
-rw-r--r--drivers/media/tuners/tuner-xc2028.c1
-rw-r--r--drivers/media/tuners/xc4000.c48
-rw-r--r--drivers/media/tuners/xc5000.c164
-rw-r--r--drivers/media/usb/Kconfig7
-rw-r--r--drivers/media/usb/Makefile3
-rw-r--r--drivers/media/usb/airspy/Kconfig10
-rw-r--r--drivers/media/usb/airspy/Makefile1
-rw-r--r--drivers/media/usb/airspy/airspy.c1132
-rw-r--r--drivers/media/usb/au0828/Kconfig8
-rw-r--r--drivers/media/usb/au0828/Makefile4
-rw-r--r--drivers/media/usb/au0828/au0828-cards.c7
-rw-r--r--drivers/media/usb/au0828/au0828-core.c25
-rw-r--r--drivers/media/usb/au0828/au0828-i2c.c37
-rw-r--r--drivers/media/usb/au0828/au0828-input.c386
-rw-r--r--drivers/media/usb/au0828/au0828-video.c62
-rw-r--r--drivers/media/usb/au0828/au0828.h11
-rw-r--r--drivers/media/usb/cpia2/cpia2_v4l.c1
-rw-r--r--drivers/media/usb/cx231xx/Kconfig2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c3
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-avcore.c1
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-cards.c403
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-core.c3
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-dvb.c105
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-input.c22
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c10
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c14
-rw-r--r--drivers/media/usb/cx231xx/cx231xx.h2
-rw-r--r--drivers/media/usb/dvb-usb-v2/Kconfig1
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9015.c18
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c28
-rw-r--r--drivers/media/usb/dvb-usb-v2/anysee.c3
-rw-r--r--drivers/media/usb/dvb-usb-v2/az6007.c25
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c14
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c34
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c14
-rw-r--r--drivers/media/usb/dvb-usb/Kconfig3
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.c233
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_core.c45
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c636
-rw-r--r--drivers/media/usb/dvb-usb/dibusb.h2
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-remote.c2
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c21
-rw-r--r--drivers/media/usb/dvb-usb/m920x.c2
-rw-r--r--drivers/media/usb/dvb-usb/pctv452e.c8
-rw-r--r--drivers/media/usb/dvb-usb/technisat-usb2.c2
-rw-r--r--drivers/media/usb/dvb-usb/ttusb2.c6
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c4
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c3
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c40
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c6
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c106
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c116
-rw-r--r--drivers/media/usb/em28xx/em28xx.h8
-rw-r--r--drivers/media/usb/go7007/Kconfig (renamed from drivers/staging/media/go7007/Kconfig)0
-rw-r--r--drivers/media/usb/go7007/Makefile (renamed from drivers/staging/media/go7007/Makefile)4
-rw-r--r--drivers/media/usb/go7007/go7007-driver.c (renamed from drivers/staging/media/go7007/go7007-driver.c)133
-rw-r--r--drivers/media/usb/go7007/go7007-fw.c (renamed from drivers/staging/media/go7007/go7007-fw.c)32
-rw-r--r--drivers/media/usb/go7007/go7007-i2c.c (renamed from drivers/staging/media/go7007/go7007-i2c.c)4
-rw-r--r--drivers/media/usb/go7007/go7007-loader.c (renamed from drivers/staging/media/go7007/go7007-loader.c)4
-rw-r--r--drivers/media/usb/go7007/go7007-priv.h (renamed from drivers/staging/media/go7007/go7007-priv.h)20
-rw-r--r--drivers/media/usb/go7007/go7007-usb.c (renamed from drivers/staging/media/go7007/go7007-usb.c)4
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c (renamed from drivers/staging/media/go7007/go7007-v4l2.c)322
-rw-r--r--drivers/media/usb/go7007/s2250-board.c (renamed from drivers/staging/media/go7007/s2250-board.c)9
-rw-r--r--drivers/media/usb/go7007/snd-go7007.c (renamed from drivers/staging/media/go7007/snd-go7007.c)4
-rw-r--r--drivers/media/usb/gspca/autogain_functions.c4
-rw-r--r--drivers/media/usb/gspca/gspca.c29
-rw-r--r--drivers/media/usb/gspca/gspca.h1
-rw-r--r--drivers/media/usb/gspca/kinect.c98
-rw-r--r--drivers/media/usb/gspca/pac7302.c8
-rw-r--r--drivers/media/usb/gspca/sonixb.c2
-rw-r--r--drivers/media/usb/hdpvr/hdpvr-video.c4
-rw-r--r--drivers/media/usb/msi2500/Kconfig5
-rw-r--r--drivers/media/usb/msi2500/Makefile1
-rw-r--r--drivers/media/usb/msi2500/msi2500.c (renamed from drivers/staging/media/msi3101/sdr-msi3101.c)818
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-v4l2.c12
-rw-r--r--drivers/media/usb/pwc/pwc-if.c1
-rw-r--r--drivers/media/usb/s2255/s2255drv.c1
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c1
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c3
-rw-r--r--drivers/media/usb/tlg2300/pd-main.c2
-rw-r--r--drivers/media/usb/tlg2300/pd-radio.c1
-rw-r--r--drivers/media/usb/tlg2300/pd-video.c1
-rw-r--r--drivers/media/usb/tm6000/tm6000-input.c55
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c3
-rw-r--r--drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c14
-rw-r--r--drivers/media/usb/ttusb-dec/ttusb_dec.c11
-rw-r--r--drivers/media/usb/usbtv/usbtv-core.c2
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c1
-rw-r--r--drivers/media/usb/usbvision/usbvision-core.c16
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c1
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c6
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c19
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c971
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c14
-rw-r--r--drivers/media/v4l2-core/v4l2-fh.c13
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c239
-rw-r--r--drivers/media/v4l2-core/v4l2-mem2mem.c11
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c125
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-sg.c62
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c129
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-contig.c10
-rw-r--r--drivers/memory/Kconfig10
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/fsl-corenet-cf.c251
-rw-r--r--drivers/message/fusion/mptbase.c23
-rw-r--r--drivers/message/fusion/mptbase.h4
-rw-r--r--drivers/message/fusion/mptctl.c18
-rw-r--r--drivers/message/fusion/mptfc.c9
-rw-r--r--drivers/message/fusion/mptsas.c76
-rw-r--r--drivers/message/fusion/mptsas.h2
-rw-r--r--drivers/message/fusion/mptscsih.c31
-rw-r--r--drivers/message/fusion/mptscsih.h4
-rw-r--r--drivers/message/fusion/mptspi.c5
-rw-r--r--drivers/message/i2o/i2o_scsi.c11
-rw-r--r--drivers/mfd/88pm805.c2
-rw-r--r--drivers/mfd/88pm860x-core.c37
-rw-r--r--drivers/mfd/88pm860x-i2c.c3
-rw-r--r--drivers/mfd/Kconfig26
-rw-r--r--drivers/mfd/Makefile7
-rw-r--r--drivers/mfd/aat2870-core.c5
-rw-r--r--drivers/mfd/ab3100-core.c54
-rw-r--r--drivers/mfd/ab8500-core.c49
-rw-r--r--drivers/mfd/ab8500-debugfs.c308
-rw-r--r--drivers/mfd/arizona-core.c53
-rw-r--r--drivers/mfd/arizona-i2c.c5
-rw-r--r--drivers/mfd/arizona-irq.c29
-rw-r--r--drivers/mfd/arizona-spi.c3
-rw-r--r--drivers/mfd/arizona.h5
-rw-r--r--drivers/mfd/asic3.c12
-rw-r--r--drivers/mfd/cros_ec.c97
-rw-r--r--drivers/mfd/cros_ec_i2c.c44
-rw-r--r--drivers/mfd/cros_ec_spi.c64
-rw-r--r--drivers/mfd/da9063-core.c6
-rw-r--r--drivers/mfd/da9063-i2c.c134
-rw-r--r--drivers/mfd/dm355evm_msp.c2
-rw-r--r--drivers/mfd/ezx-pcap.c3
-rw-r--r--drivers/mfd/htc-i2cpld.c5
-rw-r--r--drivers/mfd/intel_msic.c2
-rw-r--r--drivers/mfd/intel_soc_pmic_core.c170
-rw-r--r--drivers/mfd/intel_soc_pmic_core.h32
-rw-r--r--drivers/mfd/intel_soc_pmic_crc.c158
-rw-r--r--drivers/mfd/ipaq-micro.c8
-rw-r--r--drivers/mfd/kempld-core.c10
-rw-r--r--drivers/mfd/lp8788-irq.c2
-rw-r--r--drivers/mfd/max77686-irq.c319
-rw-r--r--drivers/mfd/max77686.c329
-rw-r--r--drivers/mfd/max77693-irq.c336
-rw-r--r--drivers/mfd/max77693.c210
-rw-r--r--drivers/mfd/max8925-core.c2
-rw-r--r--drivers/mfd/max8925-i2c.c2
-rw-r--r--drivers/mfd/mc13xxx-core.c310
-rw-r--r--drivers/mfd/mc13xxx.h11
-rw-r--r--drivers/mfd/mcp-core.c1
-rw-r--r--drivers/mfd/omap-usb-host.c2
-rw-r--r--drivers/mfd/palmas.c233
-rw-r--r--drivers/mfd/pcf50633-core.c18
-rw-r--r--drivers/mfd/pm8921-core.c4
-rw-r--r--drivers/mfd/rtsx_pcr.c76
-rw-r--r--drivers/mfd/rtsx_usb.c1
-rw-r--r--drivers/mfd/sec-core.c82
-rw-r--r--drivers/mfd/sec-irq.c110
-rw-r--r--drivers/mfd/si476x-cmd.c12
-rw-r--r--drivers/mfd/stmpe-i2c.c4
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/stmpe.h2
-rw-r--r--drivers/mfd/sun6i-prcm.c30
-rw-r--r--drivers/mfd/tc3589x.c2
-rw-r--r--drivers/mfd/tc6387xb.c7
-rw-r--r--drivers/mfd/tps6105x.c17
-rw-r--r--drivers/mfd/tps65910.c10
-rw-r--r--drivers/mfd/tps65912-spi.c3
-rw-r--r--drivers/mfd/twl4030-irq.c6
-rw-r--r--drivers/mfd/twl6030-irq.c4
-rw-r--r--drivers/mfd/twl6040.c2
-rw-r--r--drivers/mfd/wm5102-tables.c8
-rw-r--r--drivers/mfd/wm5110-tables.c245
-rw-r--r--drivers/mfd/wm8350-i2c.c8
-rw-r--r--drivers/mfd/wm8350-irq.c3
-rw-r--r--drivers/mfd/wm8994-regmap.c64
-rw-r--r--drivers/mfd/wm8997-tables.c16
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/atmel-ssc.c13
-rw-r--r--drivers/misc/atmel_pwm.c402
-rw-r--r--drivers/misc/bh1770glc.c35
-rw-r--r--drivers/misc/bh1780gli.c33
-rw-r--r--drivers/misc/carma/carma-fpga.c5
-rw-r--r--drivers/misc/dummy-irq.c1
-rw-r--r--drivers/misc/fuse/Makefile1
-rw-r--r--drivers/misc/genwqe/Kconfig6
-rw-r--r--drivers/misc/genwqe/card_base.c217
-rw-r--r--drivers/misc/genwqe/card_base.h2
-rw-r--r--drivers/misc/genwqe/card_ddcb.c28
-rw-r--r--drivers/misc/genwqe/card_debugfs.c7
-rw-r--r--drivers/misc/genwqe/card_dev.c5
-rw-r--r--drivers/misc/genwqe/card_sysfs.c25
-rw-r--r--drivers/misc/genwqe/card_utils.c20
-rw-r--r--drivers/misc/genwqe/genwqe_driver.h2
-rw-r--r--drivers/misc/ioc4.c7
-rw-r--r--drivers/misc/lattice-ecp3-config.c16
-rw-r--r--drivers/misc/lkdtm.c1
-rw-r--r--drivers/misc/mei/client.c17
-rw-r--r--drivers/misc/mei/hw-me-regs.h1
-rw-r--r--drivers/misc/mei/hw-me.c54
-rw-r--r--drivers/misc/mei/hw-txe.c32
-rw-r--r--drivers/misc/mei/main.c148
-rw-r--r--drivers/misc/mei/mei_dev.h12
-rw-r--r--drivers/misc/mei/pci-me.c6
-rw-r--r--drivers/misc/mei/pci-txe.c4
-rw-r--r--drivers/misc/mic/Kconfig21
-rw-r--r--drivers/misc/mic/Makefile1
-rw-r--r--drivers/misc/mic/bus/Makefile5
-rw-r--r--drivers/misc/mic/bus/mic_bus.c218
-rw-r--r--drivers/misc/mic/card/mic_device.c23
-rw-r--r--drivers/misc/mic/card/mic_device.h9
-rw-r--r--drivers/misc/mic/card/mic_virtio.c7
-rw-r--r--drivers/misc/mic/card/mic_x100.c62
-rw-r--r--drivers/misc/mic/host/mic_boot.c83
-rw-r--r--drivers/misc/mic/host/mic_device.h24
-rw-r--r--drivers/misc/mic/host/mic_intr.c121
-rw-r--r--drivers/misc/mic/host/mic_intr.h27
-rw-r--r--drivers/misc/mic/host/mic_main.c7
-rw-r--r--drivers/misc/mic/host/mic_virtio.c187
-rw-r--r--drivers/misc/mic/host/mic_virtio.h21
-rw-r--r--drivers/misc/mic/host/mic_x100.c8
-rw-r--r--drivers/misc/sgi-xp/xpnet.c3
-rw-r--r--drivers/misc/ti-st/st_kim.c8
-rw-r--r--drivers/misc/vexpress-syscfg.c4
-rw-r--r--drivers/misc/vmw_vmci/vmci_guest.c2
-rw-r--r--drivers/mmc/card/block.c6
-rw-r--r--drivers/mmc/core/bus.c10
-rw-r--r--drivers/mmc/core/core.c3
-rw-r--r--drivers/mmc/core/mmc.c11
-rw-r--r--drivers/mmc/core/quirks.c2
-rw-r--r--drivers/mmc/core/sd_ops.c3
-rw-r--r--drivers/mmc/host/Kconfig28
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/au1xmmc.c198
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c2
-rw-r--r--drivers/mmc/host/dw_mmc.c98
-rw-r--r--drivers/mmc/host/dw_mmc.h5
-rw-r--r--drivers/mmc/host/mmci.c168
-rw-r--r--drivers/mmc/host/mmci.h20
-rw-r--r--drivers/mmc/host/moxart-mmc.c1
-rw-r--r--drivers/mmc/host/mxs-mmc.c3
-rw-r--r--drivers/mmc/host/omap_hsmmc.c283
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c133
-rw-r--r--drivers/mmc/host/s3cmci.c186
-rw-r--r--drivers/mmc/host/s3cmci.h4
-rw-r--r--drivers/mmc/host/sdhci-acpi.c4
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/mmc/host/sdhci-pci.c38
-rw-r--r--drivers/mmc/host/sdhci-pci.h1
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c13
-rw-r--r--drivers/mmc/host/sdhci-st.c176
-rw-r--r--drivers/mmc/host/sdhci-tegra.c2
-rw-r--r--drivers/mmc/host/sdhci.c144
-rw-r--r--drivers/mmc/host/sh_mmcif.c96
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c2
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c33
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c375
-rw-r--r--drivers/mtd/cmdlinepart.c2
-rw-r--r--drivers/mtd/devices/phram.c7
-rw-r--r--drivers/mtd/ftl.c4
-rw-r--r--drivers/mtd/maps/rbtx4939-flash.c2
-rw-r--r--drivers/mtd/mtdcore.c59
-rw-r--r--drivers/mtd/mtdpart.c13
-rw-r--r--drivers/mtd/nand/Makefile2
-rw-r--r--drivers/mtd/nand/atmel_nand.c142
-rw-r--r--drivers/mtd/nand/atmel_nand_nfc.h4
-rw-r--r--drivers/mtd/nand/au1550nd.c29
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c24
-rw-r--r--drivers/mtd/nand/denali.c6
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c71
-rw-r--r--drivers/mtd/nand/lpc32xx_mlc.c6
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c6
-rw-r--r--drivers/mtd/nand/nand_base.c18
-rw-r--r--drivers/mtd/nand/nand_bbt.c14
-rw-r--r--drivers/mtd/nand/nand_timings.c253
-rw-r--r--drivers/mtd/nand/s3c2410.c4
-rw-r--r--drivers/mtd/onenand/Kconfig4
-rw-r--r--drivers/mtd/onenand/samsung.c25
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c53
-rw-r--r--drivers/mtd/ubi/block.c18
-rw-r--r--drivers/mtd/ubi/vtbl.c2
-rw-r--r--drivers/mtd/ubi/wl.c4
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/Makefile10
-rw-r--r--drivers/net/arcnet/arcnet.c3
-rw-r--r--drivers/net/arcnet/com20020-pci.c2
-rw-r--r--drivers/net/arcnet/com20020_cs.c16
-rw-r--r--drivers/net/bonding/bond_3ad.c185
-rw-r--r--drivers/net/bonding/bond_alb.c146
-rw-r--r--drivers/net/bonding/bond_alb.h8
-rw-r--r--drivers/net/bonding/bond_debugfs.c6
-rw-r--r--drivers/net/bonding/bond_main.c535
-rw-r--r--drivers/net/bonding/bond_netlink.c32
-rw-r--r--drivers/net/bonding/bond_options.c228
-rw-r--r--drivers/net/bonding/bond_procfs.c4
-rw-r--r--drivers/net/bonding/bond_sysfs.c3
-rw-r--r--drivers/net/bonding/bond_sysfs_slave.c4
-rw-r--r--drivers/net/bonding/bonding.h22
-rw-r--r--drivers/net/caif/caif_serial.c3
-rw-r--r--drivers/net/caif/caif_spi.c4
-rw-r--r--drivers/net/caif/caif_virtio.c2
-rw-r--r--drivers/net/can/c_can/c_can_pci.c3
-rw-r--r--drivers/net/can/c_can/c_can_platform.c43
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/can/pch_can.c2
-rw-r--r--drivers/net/can/sja1000/ems_pci.c2
-rw-r--r--drivers/net/can/sja1000/kvaser_pci.c2
-rw-r--r--drivers/net/can/sja1000/peak_pci.c2
-rw-r--r--drivers/net/can/sja1000/plx_pci.c2
-rw-r--r--drivers/net/can/sja1000/sja1000.c27
-rw-r--r--drivers/net/can/slcan.c2
-rw-r--r--drivers/net/cris/eth_v10.c1
-rw-r--r--drivers/net/dummy.c2
-rw-r--r--drivers/net/eql.c3
-rw-r--r--drivers/net/ethernet/3com/3c59x.c2
-rw-r--r--drivers/net/ethernet/3com/typhoon.c2
-rw-r--r--drivers/net/ethernet/8390/Kconfig3
-rw-r--r--drivers/net/ethernet/8390/axnet_cs.c26
-rw-r--r--drivers/net/ethernet/8390/lib8390.c2
-rw-r--r--drivers/net/ethernet/8390/mac8390.c8
-rw-r--r--drivers/net/ethernet/8390/ne.c2
-rw-r--r--drivers/net/ethernet/8390/ne2k-pci.c2
-rw-r--r--drivers/net/ethernet/8390/pcnet_cs.c68
-rw-r--r--drivers/net/ethernet/Kconfig1
-rw-r--r--drivers/net/ethernet/Makefile1
-rw-r--r--drivers/net/ethernet/adaptec/starfire.c2
-rw-r--r--drivers/net/ethernet/adi/Kconfig3
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c79
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.h3
-rw-r--r--drivers/net/ethernet/allwinner/sun4i-emac.c6
-rw-r--r--drivers/net/ethernet/alteon/acenic.c2
-rw-r--r--drivers/net/ethernet/amd/Kconfig13
-rw-r--r--drivers/net/ethernet/amd/amd8111e.c363
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c149
-rw-r--r--drivers/net/ethernet/amd/declance.c12
-rw-r--r--drivers/net/ethernet/amd/pcnet32.c47
-rw-r--r--drivers/net/ethernet/amd/xgbe/Makefile4
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-common.h121
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dcb.c270
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c7
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-desc.c32
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c780
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c729
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c74
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-main.c66
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-mdio.c107
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-ptp.c285
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe.h151
-rw-r--r--drivers/net/ethernet/apm/Kconfig1
-rw-r--r--drivers/net/ethernet/apm/Makefile5
-rw-r--r--drivers/net/ethernet/apm/xgene/Kconfig9
-rw-r--r--drivers/net/ethernet/apm/xgene/Makefile6
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c125
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c728
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.h337
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.c954
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_main.h135
-rw-r--r--drivers/net/ethernet/arc/emac.h4
-rw-r--r--drivers/net/ethernet/arc/emac_main.c11
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c2
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c2
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c2
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_hw.c1
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_main.c9
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c3
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c5
-rw-r--r--drivers/net/ethernet/broadcom/Kconfig8
-rw-r--r--drivers/net/ethernet/broadcom/b44.c2
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c489
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.h14
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c11
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.h5
-rw-r--r--drivers/net/ethernet/broadcom/bnx2_fw.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h9
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c55
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c44
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c11
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c264
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h35
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c78
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h23
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c10
-rw-r--r--drivers/net/ethernet/broadcom/cnic.h3
-rw-r--r--drivers/net/ethernet/broadcom/cnic_defs.h3
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h3
-rw-r--r--drivers/net/ethernet/broadcom/genet/Makefile2
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c602
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h30
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c206
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c54
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c31
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c4
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c6
-rw-r--r--drivers/net/ethernet/brocade/bna/cna_fwimg.c4
-rw-r--r--drivers/net/ethernet/cadence/macb.c419
-rw-r--r--drivers/net/ethernet/cadence/macb.h53
-rw-r--r--drivers/net/ethernet/chelsio/Kconfig11
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/subr.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/Makefile1
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h48
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c1091
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h151
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c488
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c37
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c364
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h17
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h109
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c40
-rw-r--r--drivers/net/ethernet/cirrus/cs89x0.c32
-rw-r--r--drivers/net/ethernet/cisco/enic/Makefile2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h40
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_api.c4
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.c284
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.h37
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_dev.c80
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_dev.h4
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_ethtool.c125
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c247
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_res.c1
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.c73
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_dev.h2
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_devcmd.h5
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_enet.h2
-rw-r--r--drivers/net/ethernet/cisco/enic/vnic_rq.h122
-rw-r--r--drivers/net/ethernet/davicom/dm9000.c98
-rw-r--r--drivers/net/ethernet/dec/tulip/de2104x.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/de4x5.c3
-rw-r--r--drivers/net/ethernet/dec/tulip/dmfe.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/tulip_core.c4
-rw-r--r--drivers/net/ethernet/dec/tulip/uli526x.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/winbond-840.c2
-rw-r--r--drivers/net/ethernet/dec/tulip/xircom_cb.c2
-rw-r--r--drivers/net/ethernet/dlink/dl2k.h2
-rw-r--r--drivers/net/ethernet/dlink/sundance.c2
-rw-r--r--drivers/net/ethernet/dnet.c46
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h18
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c297
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h54
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c29
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c273
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.c18
-rw-r--r--drivers/net/ethernet/emulex/benet/be_roce.h3
-rw-r--r--drivers/net/ethernet/fealnx.c2
-rw-r--r--drivers/net/ethernet/freescale/fec.h11
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c457
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c3
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fec.c1
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-scc.c1
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c16
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c26
-rw-r--r--drivers/net/ethernet/freescale/xgmac_mdio.c4
-rw-r--r--drivers/net/ethernet/fujitsu/fmvj18x_cs.c34
-rw-r--r--drivers/net/ethernet/hp/hp100.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/Makefile2
-rw-r--r--drivers/net/ethernet/icplus/ipg.c2
-rw-r--r--drivers/net/ethernet/intel/e100.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c3
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_hw.c2
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_main.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/82571.c4
-rw-r--r--drivers/net/ethernet/intel/e1000e/defines.h1
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c21
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.h4
-rw-r--r--drivers/net/ethernet/intel/e1000e/mac.c1
-rw-r--r--drivers/net/ethernet/intel/e1000e/manage.c9
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c55
-rw-r--r--drivers/net/ethernet/intel/e1000e/nvm.c4
-rw-r--r--drivers/net/ethernet/intel/i40e/Makefile1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h72
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c132
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.h39
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c482
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c29
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c551
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_fcoe.c1562
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_fcoe.h128
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_hmc.h4
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c249
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h28
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c773
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_nvm.c520
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_osdep.h3
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h31
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c135
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_register.h5011
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c190
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.h16
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_type.h213
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c40
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.c119
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_adminq.h39
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_common.c2
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_hmc.h4
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h28
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_register.h5011
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.c9
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_txrx.h7
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40e_type.h74
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c6
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c88
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c44
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_regs.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c31
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c2
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c213
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c315
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c580
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c39
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c46
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c24
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c76
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c117
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c582
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c16
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c31
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h20
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c216
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h1
-rw-r--r--drivers/net/ethernet/jme.c2
-rw-r--r--drivers/net/ethernet/marvell/Kconfig8
-rw-r--r--drivers/net/ethernet/marvell/Makefile1
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c9
-rw-r--r--drivers/net/ethernet/marvell/mvpp2.c6426
-rw-r--r--drivers/net/ethernet/marvell/skge.c2
-rw-r--r--drivers/net/ethernet/marvell/sky2.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c57
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_selftest.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_tx.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c91
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c279
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c160
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c32
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/alloc.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eq.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/mad.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c292
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/port.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8851_mll.c59
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c9
-rw-r--r--drivers/net/ethernet/myricom/myri10ge/myri10ge.c91
-rw-r--r--drivers/net/ethernet/natsemi/natsemi.c2
-rw-r--r--drivers/net/ethernet/natsemi/ns83820.c2
-rw-r--r--drivers/net/ethernet/neterion/s2io.c2
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c3
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c2
-rw-r--r--drivers/net/ethernet/octeon/octeon_mgmt.c25
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c2
-rw-r--r--drivers/net/ethernet/packetengines/hamachi.c2
-rw-r--r--drivers/net/ethernet/packetengines/yellowfin.c2
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c2
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c4
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c2
-rw-r--r--drivers/net/ethernet/qlogic/qla3xxx.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/Makefile2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c18
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c60
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c13
-rw-r--r--drivers/net/ethernet/rdc/r6040.c2
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c36
-rw-r--r--drivers/net/ethernet/realtek/8139too.c2
-rw-r--r--drivers/net/ethernet/realtek/r8169.c222
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c20
-rw-r--r--drivers/net/ethernet/sfc/ef10.c14
-rw-r--r--drivers/net/ethernet/sfc/efx.c69
-rw-r--r--drivers/net/ethernet/sfc/efx.h5
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c59
-rw-r--r--drivers/net/ethernet/sfc/falcon.c9
-rw-r--r--drivers/net/ethernet/sfc/mcdi_port.c11
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h154
-rw-r--r--drivers/net/ethernet/sfc/nic.h13
-rw-r--r--drivers/net/ethernet/sfc/rx.c12
-rw-r--r--drivers/net/ethernet/sfc/selftest.c5
-rw-r--r--drivers/net/ethernet/sfc/siena.c9
-rw-r--r--drivers/net/ethernet/sfc/tx.c28
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c2
-rw-r--r--drivers/net/ethernet/silan/sc92031.c2
-rw-r--r--drivers/net/ethernet/sis/sis190.c2
-rw-r--r--drivers/net/ethernet/sis/sis900.c4
-rw-r--r--drivers/net/ethernet/smsc/epic100.c2
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c2
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.h2
-rw-r--r--drivers/net/ethernet/smsc/smsc9420.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h47
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c69
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c131
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c27
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c42
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c67
-rw-r--r--drivers/net/ethernet/sun/cassini.c2
-rw-r--r--drivers/net/ethernet/sun/niu.c3
-rw-r--r--drivers/net/ethernet/sun/sungem.c2
-rw-r--r--drivers/net/ethernet/sun/sunhme.c2
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c38
-rw-r--r--drivers/net/ethernet/sun/sunvnet.h4
-rw-r--r--drivers/net/ethernet/tehuti/tehuti.c2
-rw-r--r--drivers/net/ethernet/ti/Kconfig4
-rw-r--r--drivers/net/ethernet/ti/cpmac.c280
-rw-r--r--drivers/net/ethernet/ti/cpsw.c45
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c12
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.h4
-rw-r--r--drivers/net/ethernet/ti/cpts.c24
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c21
-rw-r--r--drivers/net/ethernet/ti/tlan.c226
-rw-r--r--drivers/net/ethernet/ti/tlan.h5
-rw-r--r--drivers/net/ethernet/tile/tilegx.c4
-rw-r--r--drivers/net/ethernet/tile/tilepro.c3
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c10
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.c2
-rw-r--r--drivers/net/ethernet/toshiba/tc35815.c2
-rw-r--r--drivers/net/ethernet/via/via-rhine.c2
-rw-r--r--drivers/net/ethernet/via/via-velocity.c2
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c6
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c4
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c2
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c3
-rw-r--r--drivers/net/ethernet/xircom/xirc2ps_cs.c40
-rw-r--r--drivers/net/fddi/defxx.c144
-rw-r--r--drivers/net/fddi/defxx.h2
-rw-r--r--drivers/net/fddi/skfp/skfddi.c2
-rw-r--r--drivers/net/hamradio/6pack.c3
-rw-r--r--drivers/net/hamradio/baycom_epp.c2
-rw-r--r--drivers/net/hamradio/bpqether.c4
-rw-r--r--drivers/net/hamradio/dmascc.c4
-rw-r--r--drivers/net/hamradio/hdlcdrv.c2
-rw-r--r--drivers/net/hamradio/mkiss.c3
-rw-r--r--drivers/net/hamradio/scc.c2
-rw-r--r--drivers/net/hamradio/yam.c2
-rw-r--r--drivers/net/hippi/rrunner.c2
-rw-r--r--drivers/net/hyperv/hyperv_net.h5
-rw-r--r--drivers/net/hyperv/netvsc.c11
-rw-r--r--drivers/net/hyperv/netvsc_drv.c41
-rw-r--r--drivers/net/hyperv/rndis_filter.c21
-rw-r--r--drivers/net/ieee802154/Kconfig12
-rw-r--r--drivers/net/ieee802154/Makefile1
-rw-r--r--drivers/net/ieee802154/at86rf230.c1464
-rw-r--r--drivers/net/ieee802154/cc2520.c1039
-rw-r--r--drivers/net/ieee802154/fakehard.c3
-rw-r--r--drivers/net/ieee802154/mrf24j40.c115
-rw-r--r--drivers/net/ifb.c4
-rw-r--r--drivers/net/irda/au1k_ir.c48
-rw-r--r--drivers/net/irda/donauboe.c17
-rw-r--r--drivers/net/irda/kingsun-sir.c4
-rw-r--r--drivers/net/irda/via-ircc.c2
-rw-r--r--drivers/net/irda/vlsi_ir.c6
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/macvlan.c13
-rw-r--r--drivers/net/phy/amd-xgbe-phy.c136
-rw-r--r--drivers/net/phy/dp83640.c239
-rw-r--r--drivers/net/phy/mdio_bus.c1
-rw-r--r--drivers/net/phy/micrel.c22
-rw-r--r--drivers/net/phy/phy.c83
-rw-r--r--drivers/net/phy/phy_device.c2
-rw-r--r--drivers/net/phy/spi_ks8995.c26
-rw-r--r--drivers/net/ppp/ppp_generic.c35
-rw-r--r--drivers/net/slip/slhc.c1
-rw-r--r--drivers/net/slip/slip.c2
-rw-r--r--drivers/net/team/team.c8
-rw-r--r--drivers/net/team/team_mode_loadbalance.c18
-rw-r--r--drivers/net/tun.c3
-rw-r--r--drivers/net/usb/Kconfig13
-rw-r--r--drivers/net/usb/ax88179_178a.c264
-rw-r--r--drivers/net/usb/cdc-phonet.c2
-rw-r--r--drivers/net/usb/cdc_subset.c27
-rw-r--r--drivers/net/usb/hso.c4
-rw-r--r--drivers/net/usb/r8152.c38
-rw-r--r--drivers/net/usb/usbnet.c8
-rw-r--r--drivers/net/veth.c29
-rw-r--r--drivers/net/virtio_net.c67
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c4
-rw-r--r--drivers/net/vxlan.c144
-rw-r--r--drivers/net/wan/dlci.c5
-rw-r--r--drivers/net/wan/dscc4.c2
-rw-r--r--drivers/net/wan/farsync.c2
-rw-r--r--drivers/net/wan/hdlc.c3
-rw-r--r--drivers/net/wan/hdlc_fr.c68
-rw-r--r--drivers/net/wan/lapbether.c4
-rw-r--r--drivers/net/wan/lmc/lmc_main.c2
-rw-r--r--drivers/net/wan/pc300too.c2
-rw-r--r--drivers/net/wan/pci200syn.c2
-rw-r--r--drivers/net/wan/sbni.c7
-rw-r--r--drivers/net/wan/sdla.c3
-rw-r--r--drivers/net/wan/wanxl.c65
-rw-r--r--drivers/net/wan/x25_asy.c4
-rw-r--r--drivers/net/wimax/i2400m/usb.c2
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/adm8211.c2
-rw-r--r--drivers/net/wireless/airo.c8
-rw-r--r--drivers/net/wireless/airo_cs.c25
-rw-r--r--drivers/net/wireless/at76c50x-usb.c3
-rw-r--r--drivers/net/wireless/ath/ath.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c73
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c20
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c122
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c52
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c99
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c30
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c8
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c31
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c8
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c16
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h36
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c32
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c91
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c17
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c72
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar953x_initvals.h201
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h162
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c97
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c685
-rw-r--r--drivers/net/wireless/ath/ath9k/common-beacon.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c57
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c892
-rw-r--r--drivers/net/wireless/ath/ath9k/mci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/spectral.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/wow.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c135
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h1
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c1
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c31
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c68
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c361
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c64
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c53
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c39
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h36
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c59
-rw-r--r--drivers/net/wireless/atmel.c8
-rw-r--r--drivers/net/wireless/atmel_pci.c2
-rw-r--r--drivers/net/wireless/b43/Kconfig31
-rw-r--r--drivers/net/wireless/b43/Makefile6
-rw-r--r--drivers/net/wireless/b43/main.c459
-rw-r--r--drivers/net/wireless/b43/main.h1
-rw-r--r--drivers/net/wireless/b43/phy_a.c2
-rw-r--r--drivers/net/wireless/b43/phy_a.h4
-rw-r--r--drivers/net/wireless/b43/phy_common.c26
-rw-r--r--drivers/net/wireless/b43/phy_common.h12
-rw-r--r--drivers/net/wireless/b43/phy_ht.c2
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c35
-rw-r--r--drivers/net/wireless/b43/phy_n.c1461
-rw-r--r--drivers/net/wireless/b43/phy_n.h15
-rw-r--r--drivers/net/wireless/b43/radio_2057.c540
-rw-r--r--drivers/net/wireless/b43/radio_2057.h76
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c626
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h4
-rw-r--r--drivers/net/wireless/b43/xmit.c7
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig10
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcdc.c20
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c43
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.c38
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.c36
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/commonring.c273
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/commonring.h69
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h22
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h33
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c7
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c196
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h110
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c25
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c283
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.c136
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.h86
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/flowring.c501
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/flowring.h84
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fweh.h5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c100
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c1401
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h40
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/of.c56
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/of.h22
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/pcie.c1847
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/pcie.h29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/proto.c29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/proto.h31
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h16
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c251
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/vendor.c115
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/vendor.h64
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c1078
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c37
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c1
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h71
-rw-r--r--drivers/net/wireless/cw1200/fwio.c1
-rw-r--r--drivers/net/wireless/cw1200/scan.c3
-rw-r--r--drivers/net/wireless/cw1200/scan.h2
-rw-r--r--drivers/net/wireless/cw1200/sta.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c18
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c3
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c3
-rw-r--r--drivers/net/wireless/iwlegacy/3945.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/iwlegacy/common.c6
-rw-r--r--drivers/net/wireless/iwlegacy/common.h2
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig25
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c3
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/power.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h67
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-file.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c99
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c513
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex_legacy.c1257
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c324
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h222
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h256
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h7
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h30
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h78
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c111
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c795
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h150
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c35
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c128
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c26
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c39
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c38
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c96
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h19
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c17
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c540
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c98
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c162
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.h29
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c35
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c65
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h7
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c339
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c1
-rw-r--r--drivers/net/wireless/libertas/Kconfig2
-rw-r--r--drivers/net/wireless/libertas/cmd.c1
-rw-r--r--drivers/net/wireless/libertas/main.c2
-rw-r--r--drivers/net/wireless/libertas/mesh.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c83
-rw-r--r--drivers/net/wireless/mwifiex/11ac.c2
-rw-r--r--drivers/net/wireless/mwifiex/11ac.h2
-rw-r--r--drivers/net/wireless/mwifiex/11h.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n.h2
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.h2
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c29
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h2
-rw-r--r--drivers/net/wireless/mwifiex/Makefile2
-rw-r--r--drivers/net/wireless/mwifiex/README32
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c66
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.h2
-rw-r--r--drivers/net/wireless/mwifiex/cfp.c2
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c46
-rw-r--r--drivers/net/wireless/mwifiex/debugfs.c95
-rw-r--r--drivers/net/wireless/mwifiex/decl.h2
-rw-r--r--drivers/net/wireless/mwifiex/ethtool.c85
-rw-r--r--drivers/net/wireless/mwifiex/fw.h4
-rw-r--r--drivers/net/wireless/mwifiex/ie.c2
-rw-r--r--drivers/net/wireless/mwifiex/init.c15
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h2
-rw-r--r--drivers/net/wireless/mwifiex/join.c10
-rw-r--r--drivers/net/wireless/mwifiex/main.c24
-rw-r--r--drivers/net/wireless/mwifiex/main.h34
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c191
-rw-r--r--drivers/net/wireless/mwifiex/pcie.h12
-rw-r--r--drivers/net/wireless/mwifiex/scan.c2
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c235
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h14
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c4
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c4
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c18
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c2
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c30
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c2
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c2
-rw-r--r--drivers/net/wireless/mwifiex/uap_event.c2
-rw-r--r--drivers/net/wireless/mwifiex/uap_txrx.c6
-rw-r--r--drivers/net/wireless/mwifiex/usb.c2
-rw-r--r--drivers/net/wireless/mwifiex/usb.h2
-rw-r--r--drivers/net/wireless/mwifiex/util.c2
-rw-r--r--drivers/net/wireless/mwifiex/util.h2
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c11
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h2
-rw-r--r--drivers/net/wireless/mwl8k.c13
-rw-r--r--drivers/net/wireless/orinoco/Kconfig4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c1
-rw-r--r--drivers/net/wireless/p54/p54pci.c2
-rw-r--r--drivers/net/wireless/p54/p54spi.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c2
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_core.c85
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_debugfs.c10
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c143
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c239
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_pkt.c17
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c6
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio_ops.c8
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_usb.c88
-rw-r--r--drivers/net/wireless/rsi/rsi_main.h12
-rw-r--r--drivers/net/wireless/rsi/rsi_mgmt.h25
-rw-r--r--drivers/net/wireless/rsi/rsi_sdio.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c69
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c20
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mmio.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c21
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c91
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/rtl8180.h1
-rw-r--r--drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h2
-rw-r--r--drivers/net/wireless/rtlwifi/core.c1
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c17
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/sw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/phy.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hw.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/reg.h1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/sw.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c3
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wl12xx/scan.c20
-rw-r--r--drivers/net/wireless/ti/wl12xx/scan.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.c89
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.h19
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.c65
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c34
-rw-r--r--drivers/net/wireless/ti/wl18xx/scan.c16
-rw-r--r--drivers/net/wireless/ti/wl18xx/scan.h2
-rw-r--r--drivers/net/wireless/ti/wl18xx/tx.c7
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/Makefile2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c23
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h6
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h27
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c108
-rw-r--r--drivers/net/wireless/ti/wlcore/scan.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.c197
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.h45
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h10
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h20
-rw-r--r--drivers/net/wireless/zd1211rw/Kconfig4
-rw-r--r--drivers/net/xen-netback/common.h35
-rw-r--r--drivers/net/xen-netback/interface.c114
-rw-r--r--drivers/net/xen-netback/netback.c142
-rw-r--r--drivers/net/xen-netback/xenbus.c181
-rw-r--r--drivers/net/xen-netfront.c81
-rw-r--r--drivers/nfc/Kconfig2
-rw-r--r--drivers/nfc/Makefile3
-rw-r--r--drivers/nfc/st21nfca/Makefile2
-rw-r--r--drivers/nfc/st21nfca/i2c.c9
-rw-r--r--drivers/nfc/st21nfca/st21nfca.c272
-rw-r--r--drivers/nfc/st21nfca/st21nfca.h26
-rw-r--r--drivers/nfc/st21nfca/st21nfca_dep.c661
-rw-r--r--drivers/nfc/st21nfca/st21nfca_dep.h43
-rw-r--r--drivers/nfc/st21nfcb/Kconfig22
-rw-r--r--drivers/nfc/st21nfcb/Makefile8
-rw-r--r--drivers/nfc/st21nfcb/i2c.c462
-rw-r--r--drivers/nfc/st21nfcb/ndlc.c298
-rw-r--r--drivers/nfc/st21nfcb/ndlc.h55
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb.c129
-rw-r--r--drivers/nfc/st21nfcb/st21nfcb.h38
-rw-r--r--drivers/of/Kconfig3
-rw-r--r--drivers/of/Makefile4
-rw-r--r--drivers/of/address.c36
-rw-r--r--drivers/of/base.c451
-rw-r--r--drivers/of/device.c4
-rw-r--r--drivers/of/dynamic.c660
-rw-r--r--drivers/of/fdt.c22
-rw-r--r--drivers/of/of_private.h59
-rw-r--r--drivers/of/of_reserved_mem.c70
-rw-r--r--drivers/of/platform.c32
-rw-r--r--drivers/of/selftest.c235
-rw-r--r--drivers/of/testcase-data/testcases.dts15
-rw-r--r--drivers/of/testcase-data/testcases.dtsi4
-rw-r--r--drivers/parport/parport_ip32.c2
-rw-r--r--drivers/pci/host/Kconfig8
-rw-r--r--drivers/pci/host/Makefile1
-rw-r--r--drivers/pci/host/pci-host-generic.c2
-rw-r--r--drivers/pci/host/pci-mvebu.c2
-rw-r--r--drivers/pci/host/pci-tegra.c229
-rw-r--r--drivers/pci/host/pcie-rcar.c158
-rw-r--r--drivers/pci/host/pcie-spear13xx.c393
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c33
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c3
-rw-r--r--drivers/pci/hotplug/pciehp.h3
-rw-r--r--drivers/pci/hotplug/pciehp_core.c7
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c101
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c4
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c4
-rw-r--r--drivers/pci/ioapic.c2
-rw-r--r--drivers/pci/msi.c141
-rw-r--r--drivers/pci/pci-acpi.c76
-rw-r--r--drivers/pci/pci-driver.c18
-rw-r--r--drivers/pci/pci-label.c18
-rw-r--r--drivers/pci/pci.c19
-rw-r--r--drivers/pci/pcie/aer/Kconfig1
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c4
-rw-r--r--drivers/pci/pcie/portdrv_pci.c4
-rw-r--r--drivers/pci/quirks.c106
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--drivers/pci/setup-res.c75
-rw-r--r--drivers/pcmcia/Kconfig12
-rw-r--r--drivers/pcmcia/Makefile2
-rw-r--r--drivers/pcmcia/bcm63xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/i82092.c2
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c1168
-rw-r--r--drivers/pcmcia/pd6729.c2
-rw-r--r--drivers/pcmcia/sa1111_jornada720.c10
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c2
-rw-r--r--drivers/pcmcia/yenta_socket.c2
-rw-r--r--drivers/phy/Kconfig100
-rw-r--r--drivers/phy/Makefile8
-rw-r--r--drivers/phy/phy-bcm-kona-usb2.c2
-rw-r--r--drivers/phy/phy-berlin-sata.c284
-rw-r--r--drivers/phy/phy-core.c56
-rw-r--r--drivers/phy/phy-exynos-dp-video.c7
-rw-r--r--drivers/phy/phy-exynos-mipi-video.c7
-rw-r--r--drivers/phy/phy-exynos4x12-usb2.c125
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c9
-rw-r--r--drivers/phy/phy-exynos5250-sata.c2
-rw-r--r--drivers/phy/phy-exynos5250-usb2.c2
-rw-r--r--drivers/phy/phy-hix5hd2-sata.c192
-rw-r--r--drivers/phy/phy-miphy365x.c636
-rw-r--r--drivers/phy/phy-mvebu-sata.c2
-rw-r--r--drivers/phy/phy-omap-control.c52
-rw-r--r--drivers/phy/phy-omap-usb2.c2
-rw-r--r--drivers/phy/phy-qcom-apq8064-sata.c289
-rw-r--r--drivers/phy/phy-qcom-ipq806x-sata.c211
-rw-r--r--drivers/phy/phy-s5pv210-usb2.c187
-rw-r--r--drivers/phy/phy-samsung-usb2.c15
-rw-r--r--drivers/phy/phy-samsung-usb2.h6
-rw-r--r--drivers/phy/phy-spear1310-miphy.c274
-rw-r--r--drivers/phy/phy-spear1340-miphy.c307
-rw-r--r--drivers/phy/phy-sun4i-usb.c7
-rw-r--r--drivers/phy/phy-ti-pipe3.c107
-rw-r--r--drivers/phy/phy-twl4030-usb.c2
-rw-r--r--drivers/phy/phy-xgene.c2
-rw-r--r--drivers/pinctrl/Kconfig123
-rw-r--r--drivers/pinctrl/Makefile25
-rw-r--r--drivers/pinctrl/core.c24
-rw-r--r--drivers/pinctrl/nomadik/Kconfig51
-rw-r--r--drivers/pinctrl/nomadik/Makefile10
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-ab8500.c (renamed from drivers/pinctrl/pinctrl-ab8500.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-ab8505.c (renamed from drivers/pinctrl/pinctrl-ab8505.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-ab8540.c (renamed from drivers/pinctrl/pinctrl-ab8540.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-ab9540.c (renamed from drivers/pinctrl/pinctrl-ab9540.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c (renamed from drivers/pinctrl/pinctrl-abx500.c)19
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.h (renamed from drivers/pinctrl/pinctrl-abx500.h)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c (renamed from drivers/pinctrl/pinctrl-nomadik-db8500.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c (renamed from drivers/pinctrl/pinctrl-nomadik-db8540.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c (renamed from drivers/pinctrl/pinctrl-nomadik-stn8815.c)0
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.c (renamed from drivers/pinctrl/pinctrl-nomadik.c)18
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.h (renamed from drivers/pinctrl/pinctrl-nomadik.h)0
-rw-r--r--drivers/pinctrl/pinctrl-adi2.c41
-rw-r--r--drivers/pinctrl/pinctrl-as3722.c11
-rw-r--r--drivers/pinctrl/pinctrl-at91.c27
-rw-r--r--drivers/pinctrl/pinctrl-baytrail.c103
-rw-r--r--drivers/pinctrl/pinctrl-bcm281xx.c2
-rw-r--r--drivers/pinctrl/pinctrl-bcm2835.c11
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c10
-rw-r--r--drivers/pinctrl/pinctrl-imx.c2
-rw-r--r--drivers/pinctrl/pinctrl-imx1-core.c2
-rw-r--r--drivers/pinctrl/pinctrl-imx1.c279
-rw-r--r--drivers/pinctrl/pinctrl-imx27.c52
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c401
-rw-r--r--drivers/pinctrl/pinctrl-single.c61
-rw-r--r--drivers/pinctrl/pinctrl-st.c15
-rw-r--r--drivers/pinctrl/pinctrl-tb10x.c17
-rw-r--r--drivers/pinctrl/pinctrl-tegra-xusb.c973
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c13
-rw-r--r--drivers/pinctrl/pinctrl-tz1090-pdc.c28
-rw-r--r--drivers/pinctrl/pinctrl-tz1090.c58
-rw-r--r--drivers/pinctrl/pinctrl-u300.c14
-rw-r--r--drivers/pinctrl/pinmux.c4
-rw-r--r--drivers/pinctrl/qcom/Kconfig42
-rw-r--r--drivers/pinctrl/qcom/Makefile6
-rw-r--r--drivers/pinctrl/qcom/pinctrl-apq8064.c (renamed from drivers/pinctrl/pinctrl-apq8064.c)19
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ipq8064.c (renamed from drivers/pinctrl/pinctrl-ipq8064.c)17
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c (renamed from drivers/pinctrl/pinctrl-msm.c)42
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h (renamed from drivers/pinctrl/pinctrl-msm.h)0
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8960.c1282
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8x74.c (renamed from drivers/pinctrl/pinctrl-msm8x74.c)29
-rw-r--r--drivers/pinctrl/samsung/Kconfig28
-rw-r--r--drivers/pinctrl/samsung/Makefile7
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c (renamed from drivers/pinctrl/pinctrl-exynos.c)307
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.h (renamed from drivers/pinctrl/pinctrl-exynos.h)0
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos5440.c (renamed from drivers/pinctrl/pinctrl-exynos5440.c)10
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c24xx.c (renamed from drivers/pinctrl/pinctrl-s3c24xx.c)0
-rw-r--r--drivers/pinctrl/samsung/pinctrl-s3c64xx.c (renamed from drivers/pinctrl/pinctrl-s3c64xx.c)0
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c (renamed from drivers/pinctrl/pinctrl-samsung.c)728
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h (renamed from drivers/pinctrl/pinctrl-samsung.h)18
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c9
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c417
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c11
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c22
-rw-r--r--drivers/pinctrl/sirf/pinctrl-sirf.c10
-rw-r--r--drivers/pinctrl/spear/Kconfig1
-rw-r--r--drivers/pinctrl/spear/pinctrl-plgpio.c84
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c7
-rw-r--r--drivers/pinctrl/sunxi/Kconfig24
-rw-r--r--drivers/pinctrl/sunxi/Makefile2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c4
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c217
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c1
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c142
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c593
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c187
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.h44
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c21
-rw-r--r--drivers/platform/chrome/chromeos_laptop.c144
-rw-r--r--drivers/platform/chrome/chromeos_pstore.c14
-rw-r--r--drivers/platform/x86/intel_ips.c2
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c2
-rw-r--r--drivers/platform/x86/samsung-q10.c6
-rw-r--r--drivers/pnp/pnpacpi/core.c91
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/bq2415x_charger.c8
-rw-r--r--drivers/power/bq27x00_battery.c28
-rw-r--r--drivers/power/ipaq_micro_battery.c290
-rw-r--r--drivers/power/power_supply_core.c3
-rw-r--r--drivers/power/power_supply_sysfs.c4
-rw-r--r--drivers/power/reset/Kconfig17
-rw-r--r--drivers/power/reset/Makefile2
-rw-r--r--drivers/power/reset/brcmstb-reboot.c120
-rw-r--r--drivers/power/reset/gpio-poweroff.c52
-rw-r--r--drivers/power/reset/hisi-reboot.c67
-rw-r--r--drivers/power/reset/restart-poweroff.c2
-rw-r--r--drivers/power/rx51_battery.c90
-rw-r--r--drivers/power/tps65090-charger.c76
-rw-r--r--drivers/power/twl4030_charger.c44
-rw-r--r--drivers/ptp/ptp_chardev.c9
-rw-r--r--drivers/ptp/ptp_pch.c2
-rw-r--r--drivers/pwm/Kconfig19
-rw-r--r--drivers/pwm/Makefile2
-rw-r--r--drivers/pwm/pwm-imx.c1
-rw-r--r--drivers/pwm/pwm-lpss.c32
-rw-r--r--drivers/pwm/pwm-rockchip.c264
-rw-r--r--drivers/pwm/pwm-sti.c418
-rw-r--r--drivers/pwm/pwm-tipwmss.c4
-rw-r--r--drivers/rapidio/devices/tsi721.c2
-rw-r--r--drivers/rapidio/devices/tsi721.h12
-rw-r--r--drivers/rapidio/devices/tsi721_dma.c718
-rw-r--r--drivers/rapidio/rio.c66
-rw-r--r--drivers/ras/Kconfig2
-rw-r--r--drivers/ras/Makefile1
-rw-r--r--drivers/ras/debugfs.c56
-rw-r--r--drivers/ras/ras.c29
-rw-r--r--drivers/regulator/88pm800.c1
-rw-r--r--drivers/regulator/Kconfig14
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/ab8500.c38
-rw-r--r--drivers/regulator/act8865-regulator.c329
-rw-r--r--drivers/regulator/arizona-ldo1.c2
-rw-r--r--drivers/regulator/as3722-regulator.c4
-rw-r--r--drivers/regulator/bcm590xx-regulator.c16
-rw-r--r--drivers/regulator/core.c126
-rw-r--r--drivers/regulator/da9211-regulator.c368
-rw-r--r--drivers/regulator/da9211-regulator.h271
-rw-r--r--drivers/regulator/lp872x.c9
-rw-r--r--drivers/regulator/lp8755.c23
-rw-r--r--drivers/regulator/ltc3589.c2
-rw-r--r--drivers/regulator/max77693.c12
-rw-r--r--drivers/regulator/max8952.c34
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c37
-rw-r--r--drivers/regulator/mc13xxx.h1
-rw-r--r--drivers/regulator/palmas-regulator.c1104
-rw-r--r--drivers/regulator/s2mps11.c323
-rw-r--r--drivers/regulator/s5m8767.c4
-rw-r--r--drivers/regulator/tps65090-regulator.c76
-rw-r--r--drivers/regulator/tps65217-regulator.c4
-rw-r--r--drivers/regulator/tps65218-regulator.c52
-rw-r--r--drivers/regulator/tps6586x-regulator.c129
-rw-r--r--drivers/regulator/twl-regulator.c13
-rw-r--r--drivers/rtc/Kconfig29
-rw-r--r--drivers/rtc/Makefile5
-rw-r--r--drivers/rtc/class.c16
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-au1xxx.c18
-rw-r--r--drivers/rtc/rtc-da9063.c54
-rw-r--r--drivers/rtc/rtc-ds1343.c75
-rw-r--r--drivers/rtc/rtc-ds1742.c2
-rw-r--r--drivers/rtc/rtc-efi-platform.c31
-rw-r--r--drivers/rtc/rtc-efi.c32
-rw-r--r--drivers/rtc/rtc-isl12022.c12
-rw-r--r--drivers/rtc/rtc-max77686.c27
-rw-r--r--drivers/rtc/rtc-pcf85063.c204
-rw-r--r--drivers/rtc/rtc-pcf8563.c231
-rw-r--r--drivers/rtc/rtc-tps65910.c4
-rw-r--r--drivers/s390/block/dasd.c196
-rw-r--r--drivers/s390/block/dasd_eckd.c30
-rw-r--r--drivers/s390/block/dasd_int.h5
-rw-r--r--drivers/s390/block/dasd_ioctl.c33
-rw-r--r--drivers/s390/char/con3215.c32
-rw-r--r--drivers/s390/cio/qdio_setup.c53
-rw-r--r--drivers/s390/net/claw.c2
-rw-r--r--drivers/s390/net/ctcm_main.c6
-rw-r--r--drivers/s390/net/netiucv.c2
-rw-r--r--drivers/s390/net/qeth_core.h15
-rw-r--r--drivers/s390/net/qeth_core_main.c200
-rw-r--r--drivers/s390/net/qeth_core_mpc.h17
-rw-r--r--drivers/s390/net/qeth_core_sys.c38
-rw-r--r--drivers/s390/net/qeth_l2_main.c6
-rw-r--r--drivers/s390/net/qeth_l3_main.c3
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c3
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c49
-rw-r--r--drivers/s390/scsi/zfcp_unit.c4
-rw-r--r--drivers/sbus/char/bbc_envctrl.c6
-rw-r--r--drivers/sbus/char/bbc_i2c.c11
-rw-r--r--drivers/sbus/char/display7seg.c10
-rw-r--r--drivers/scsi/3w-sas.c5
-rw-r--r--drivers/scsi/3w-xxxx.h4
-rw-r--r--drivers/scsi/53c700.c7
-rw-r--r--drivers/scsi/BusLogic.c2
-rw-r--r--drivers/scsi/Kconfig61
-rw-r--r--drivers/scsi/Makefile5
-rw-r--r--drivers/scsi/NCR5380.c31
-rw-r--r--drivers/scsi/NCR53c406a.c4
-rw-r--r--drivers/scsi/a100u2w.c10
-rw-r--r--drivers/scsi/aacraid/linit.c2
-rw-r--r--drivers/scsi/advansys.c6
-rw-r--r--drivers/scsi/aha152x.c6
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c3
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c2
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c8
-rw-r--r--drivers/scsi/arm/acornscsi.c14
-rw-r--r--drivers/scsi/arm/fas216.c11
-rw-r--r--drivers/scsi/arm/queue.c3
-rw-r--r--drivers/scsi/atari_NCR5380.c62
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c12
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c23
-rw-r--r--drivers/scsi/bfa/bfa_fcs.c6
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h2
-rw-r--r--drivers/scsi/bfa/bfad.c62
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c16
-rw-r--r--drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h13
-rw-r--r--drivers/scsi/bnx2fc/Kconfig4
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h7
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_constants.h13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.c13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_debug.h13
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_els.c3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c11
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c7
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c3
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h6
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h6
-rw-r--r--drivers/scsi/bnx2i/Kconfig4
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c14
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c15
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c6
-rw-r--r--drivers/scsi/ch.c30
-rw-r--r--drivers/scsi/csiostor/csio_init.c2
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c24
-rw-r--r--drivers/scsi/csiostor/csio_wr.c8
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/Kconfig2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kconfig2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c363
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c243
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.h23
-rw-r--r--drivers/scsi/dc395x.c51
-rw-r--r--drivers/scsi/dpt_i2o.c38
-rw-r--r--drivers/scsi/dpti.h6
-rw-r--r--drivers/scsi/eata.c9
-rw-r--r--drivers/scsi/fnic/fnic_isr.c4
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c20
-rw-r--r--drivers/scsi/g_NCR5380.c2
-rw-r--r--drivers/scsi/hosts.c50
-rw-r--r--drivers/scsi/hpsa.c45
-rw-r--r--drivers/scsi/hptiop.c2
-rw-r--r--drivers/scsi/ibmvscsi/Makefile1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c477
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h268
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c1001
-rw-r--r--drivers/scsi/in2000.c6
-rw-r--r--drivers/scsi/isci/init.c4
-rw-r--r--drivers/scsi/libiscsi.c14
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c16
-rw-r--r--drivers/scsi/libsrp.c447
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c36
-rw-r--r--drivers/scsi/megaraid.c6
-rw-r--r--drivers/scsi/megaraid/mega_common.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c16
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c8
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c4
-rw-r--r--drivers/scsi/mesh.c8
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c75
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h2
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c83
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c75
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c94
-rw-r--r--drivers/scsi/mvsas/mv_sas.c24
-rw-r--r--drivers/scsi/mvumi.c11
-rw-r--r--drivers/scsi/ncr53c8xx.c2
-rw-r--r--drivers/scsi/ncr53c8xx.h4
-rw-r--r--drivers/scsi/nsp32.c2
-rw-r--r--drivers/scsi/pas16.c2
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c2
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c151
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c69
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c79
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c43
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h2
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c48
-rw-r--r--drivers/scsi/pmcraid.c6
-rw-r--r--drivers/scsi/ps3rom.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h18
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c48
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h4
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c6
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c22
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c20
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c36
-rw-r--r--drivers/scsi/qlogicfas.c2
-rw-r--r--drivers/scsi/qlogicpti.c2
-rw-r--r--drivers/scsi/scsi.c132
-rw-r--r--drivers/scsi/scsi_debug.c1483
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c186
-rw-r--r--drivers/scsi/scsi_ioctl.c17
-rw-r--r--drivers/scsi/scsi_lib.c935
-rw-r--r--drivers/scsi/scsi_priv.h5
-rw-r--r--drivers/scsi/scsi_proc.c2
-rw-r--r--drivers/scsi/scsi_scan.c187
-rw-r--r--drivers/scsi/scsi_sysfs.c49
-rw-r--r--drivers/scsi/scsi_tgt_if.c399
-rw-r--r--drivers/scsi/scsi_tgt_lib.c661
-rw-r--r--drivers/scsi/scsi_tgt_priv.h32
-rw-r--r--drivers/scsi/scsi_trace.c16
-rw-r--r--drivers/scsi/scsi_transport_fc.c20
-rw-r--r--drivers/scsi/scsi_transport_fc_internal.h26
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c14
-rw-r--r--drivers/scsi/scsi_transport_sas.c2
-rw-r--r--drivers/scsi/scsi_transport_srp.c21
-rw-r--r--drivers/scsi/scsi_transport_srp_internal.h25
-rw-r--r--drivers/scsi/sd.c220
-rw-r--r--drivers/scsi/sd.h3
-rw-r--r--drivers/scsi/sg.c657
-rw-r--r--drivers/scsi/sr.c70
-rw-r--r--drivers/scsi/sr.h5
-rw-r--r--drivers/scsi/sr_ioctl.c26
-rw-r--r--drivers/scsi/sr_vendor.c36
-rw-r--r--drivers/scsi/st.c605
-rw-r--r--drivers/scsi/storvsc_drv.c123
-rw-r--r--drivers/scsi/sun3_NCR5380.c57
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h2
-rw-r--r--drivers/scsi/tmscsim.c6
-rw-r--r--drivers/scsi/u14-34f.c12
-rw-r--r--drivers/scsi/ufs/ufs.h38
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c28
-rw-r--r--drivers/scsi/ufs/ufshcd.c427
-rw-r--r--drivers/scsi/ufs/ufshci.h5
-rw-r--r--drivers/scsi/virtio_scsi.c75
-rw-r--r--drivers/scsi/vmw_pvscsi.c2
-rw-r--r--drivers/scsi/wd33c93.c33
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/tegra/Makefile4
-rw-r--r--drivers/soc/tegra/common.c30
-rw-r--r--drivers/soc/tegra/fuse/Makefile8
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c163
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra20.c215
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c224
-rw-r--r--drivers/soc/tegra/fuse/fuse.h71
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra114.c (renamed from arch/arm/mach-tegra/tegra114_speedo.c)56
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra124.c168
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra20.c (renamed from arch/arm/mach-tegra/tegra20_speedo.c)45
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra30.c (renamed from arch/arm/mach-tegra/tegra30_speedo.c)176
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c115
-rw-r--r--drivers/soc/tegra/pmc.c957
-rw-r--r--drivers/spi/Kconfig16
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-adi-v3.c5
-rw-r--r--drivers/spi/spi-atmel.c22
-rw-r--r--drivers/spi/spi-au1550.c72
-rw-r--r--drivers/spi/spi-cadence.c37
-rw-r--r--drivers/spi/spi-clps711x.c2
-rw-r--r--drivers/spi/spi-davinci.c72
-rw-r--r--drivers/spi/spi-dw-mmio.c19
-rw-r--r--drivers/spi/spi-efm32.c8
-rw-r--r--drivers/spi/spi-falcon.c2
-rw-r--r--drivers/spi/spi-fsl-lib.c2
-rw-r--r--drivers/spi/spi-fsl-spi.c2
-rw-r--r--drivers/spi/spi-omap-100k.c2
-rw-r--r--drivers/spi/spi-omap-uwire.c11
-rw-r--r--drivers/spi/spi-omap2-mcspi.c14
-rw-r--r--drivers/spi/spi-orion.c78
-rw-r--r--drivers/spi/spi-pl022.c2
-rw-r--r--drivers/spi/spi-qup.c36
-rw-r--r--drivers/spi/spi-rockchip.c837
-rw-r--r--drivers/spi/spi-rspi.c45
-rw-r--r--drivers/spi/spi-s3c64xx.c76
-rw-r--r--drivers/spi/spi-sh-hspi.c2
-rw-r--r--drivers/spi/spi-sh-msiof.c527
-rw-r--r--drivers/spi/spi-sh.c15
-rw-r--r--drivers/spi/spi-topcliff-pch.c12
-rw-r--r--drivers/spi/spi-xilinx.c2
-rw-r--r--drivers/spi/spi.c17
-rw-r--r--drivers/spmi/spmi.c1
-rw-r--r--drivers/ssb/pci.c113
-rw-r--r--drivers/staging/Kconfig32
-rw-r--r--drivers/staging/Makefile17
-rw-r--r--drivers/staging/android/Kconfig3
-rw-r--r--drivers/staging/android/Makefile2
-rw-r--r--drivers/staging/android/alarm-dev.c2
-rw-r--r--drivers/staging/android/binder.c229
-rw-r--r--drivers/staging/android/ion/Kconfig2
-rw-r--r--drivers/staging/android/ion/ion.c3
-rw-r--r--drivers/staging/android/ion/ion.h1
-rw-r--r--drivers/staging/android/ion/ion_chunk_heap.c2
-rw-r--r--drivers/staging/android/ion/ion_cma_heap.c9
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c71
-rw-r--r--drivers/staging/android/logger.c7
-rw-r--r--drivers/staging/android/sw_sync.c6
-rw-r--r--drivers/staging/android/sync.c916
-rw-r--r--drivers/staging/android/sync.h79
-rw-r--r--drivers/staging/android/sync_debug.c252
-rw-r--r--drivers/staging/android/timed_gpio.c15
-rw-r--r--drivers/staging/android/timed_output.c4
-rw-r--r--drivers/staging/android/trace/sync.h12
-rw-r--r--drivers/staging/bcm/Bcmchar.c2
-rw-r--r--drivers/staging/bcm/CmHost.c3
-rw-r--r--drivers/staging/bcm/DDRInit.c338
-rw-r--r--drivers/staging/bcm/HandleControlPacket.c24
-rw-r--r--drivers/staging/bcm/IPv6Protocol.c217
-rw-r--r--drivers/staging/bcm/InterfaceDld.c1
-rw-r--r--drivers/staging/bcm/InterfaceInit.c304
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c126
-rw-r--r--drivers/staging/bcm/InterfaceRx.c206
-rw-r--r--drivers/staging/bcm/InterfaceTx.c185
-rw-r--r--drivers/staging/bcm/LeakyBucket.c312
-rw-r--r--drivers/staging/bcm/Misc.c27
-rw-r--r--drivers/staging/bcm/PHSModule.c1099
-rw-r--r--drivers/staging/bcm/PHSModule.h25
-rw-r--r--drivers/staging/bcm/Prototypes.h89
-rw-r--r--drivers/staging/bcm/Qos.c1053
-rw-r--r--drivers/staging/bcm/Queue.h46
-rw-r--r--drivers/staging/bcm/TODO4
-rw-r--r--drivers/staging/bcm/Transmit.c88
-rw-r--r--drivers/staging/bcm/hostmibs.c62
-rw-r--r--drivers/staging/bcm/led_control.c668
-rw-r--r--drivers/staging/bcm/led_control.h16
-rw-r--r--drivers/staging/bcm/nvm.c146
-rw-r--r--drivers/staging/board/Kconfig9
-rw-r--r--drivers/staging/board/Makefile2
-rw-r--r--drivers/staging/board/TODO2
-rw-r--r--drivers/staging/board/board.c41
-rw-r--r--drivers/staging/board/board.h20
-rw-r--r--drivers/staging/board/kzm9d.c19
-rw-r--r--drivers/staging/ced1401/Kconfig6
-rw-r--r--drivers/staging/ced1401/Makefile3
-rw-r--r--drivers/staging/ced1401/TODO10
-rw-r--r--drivers/staging/ced1401/ced_ioc.c1494
-rw-r--r--drivers/staging/ced1401/ced_ioctl.h336
-rw-r--r--drivers/staging/ced1401/machine.h119
-rw-r--r--drivers/staging/ced1401/usb1401.c1582
-rw-r--r--drivers/staging/ced1401/usb1401.h246
-rw-r--r--drivers/staging/ced1401/use1401.h288
-rw-r--r--drivers/staging/ced1401/use14_ioc.h299
-rw-r--r--drivers/staging/ced1401/userspace/use1401.c3035
-rw-r--r--drivers/staging/comedi/Kconfig24
-rw-r--r--drivers/staging/comedi/comedi.h127
-rw-r--r--drivers/staging/comedi/comedi_compat32.c28
-rw-r--r--drivers/staging/comedi/comedi_compat32.h3
-rw-r--r--drivers/staging/comedi/comedi_fops.c93
-rw-r--r--drivers/staging/comedi/comedi_internal.h1
-rw-r--r--drivers/staging/comedi/comedidev.h152
-rw-r--r--drivers/staging/comedi/drivers.c9
-rw-r--r--drivers/staging/comedi/drivers/8253.h6
-rw-r--r--drivers/staging/comedi/drivers/8255.c3
-rw-r--r--drivers/staging/comedi/drivers/8255_pci.c27
-rw-r--r--drivers/staging/comedi/drivers/Makefile4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c10
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h20
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c9
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c7
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c321
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c61
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c228
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_035.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1500.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1564.c391
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c11
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3200.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c84
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c101
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c161
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c148
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c22
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c5
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1724.c15
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c11
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c3
-rw-r--r--drivers/staging/comedi/drivers/amcc_s5933.h8
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c3
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.h13
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_common.c45
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_pci.c45
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c591
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.h42
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236_common.c206
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c7
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c26
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c1310
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci236.c161
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci263.c11
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c2
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c24
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c154
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c3
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c6
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c4
-rw-r--r--drivers/staging/comedi/drivers/daqboard2000.c87
-rw-r--r--drivers/staging/comedi/drivers/das08.c3
-rw-r--r--drivers/staging/comedi/drivers/das08_pci.c4
-rw-r--r--drivers/staging/comedi/drivers/das16.c16
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c13
-rw-r--r--drivers/staging/comedi/drivers/das1800.c120
-rw-r--r--drivers/staging/comedi/drivers/das800.c3
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c13
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c4
-rw-r--r--drivers/staging/comedi/drivers/dt2814.c12
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c4
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c1351
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c117
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c1
-rw-r--r--drivers/staging/comedi/drivers/gsc_hpdi.c44
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c94
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c68
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c5
-rw-r--r--drivers/staging/comedi/drivers/ke_counter.c66
-rw-r--r--drivers/staging/comedi/drivers/me4000.c1
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c67
-rw-r--r--drivers/staging/comedi/drivers/mf6x4.c47
-rw-r--r--drivers/staging/comedi/drivers/mite.c46
-rw-r--r--drivers/staging/comedi/drivers/mite.h136
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c5
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c154
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c797
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c67
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c68
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c254
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c392
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c14
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c89
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c231
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.h7
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_isadma.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc_pci.c51
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c4866
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_cs.c107
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c374
-rw-r--r--drivers/staging/comedi/drivers/ni_pcimio.c775
-rw-r--r--drivers/staging/comedi/drivers/ni_stc.h187
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.c1687
-rw-r--r--drivers/staging/comedi/drivers/ni_tio.h4
-rw-r--r--drivers/staging/comedi/drivers/ni_tio_internal.h387
-rw-r--r--drivers/staging/comedi/drivers/ni_tiocmd.c140
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c2
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c11
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c21
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c2
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c118
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c9
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c18
-rw-r--r--drivers/staging/comedi/drivers/pcmuio.c1
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c12
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c207
-rw-r--r--drivers/staging/comedi/drivers/rti800.c4
-rw-r--r--drivers/staging/comedi/drivers/s526.c6
-rw-r--r--drivers/staging/comedi/drivers/s626.c890
-rw-r--r--drivers/staging/comedi/drivers/s626.h28
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c112
-rw-r--r--drivers/staging/comedi/drivers/skel.c9
-rw-r--r--drivers/staging/comedi/drivers/unioxx5.c3
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c12
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c8
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c14
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c1
-rw-r--r--drivers/staging/cptm1217/clearpad_tm1217.c15
-rw-r--r--drivers/staging/crystalhd/Kconfig6
-rw-r--r--drivers/staging/crystalhd/Makefile6
-rw-r--r--drivers/staging/crystalhd/TODO15
-rw-r--r--drivers/staging/crystalhd/bc_dts_defs.h572
-rw-r--r--drivers/staging/crystalhd/bc_dts_glob_lnx.h300
-rw-r--r--drivers/staging/crystalhd/bcm_70012_regs.h758
-rw-r--r--drivers/staging/crystalhd/crystalhd.h13
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.c1066
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.h92
-rw-r--r--drivers/staging/crystalhd/crystalhd_fw_if.h370
-rw-r--r--drivers/staging/crystalhd/crystalhd_hw.c2458
-rw-r--r--drivers/staging/crystalhd/crystalhd_hw.h407
-rw-r--r--drivers/staging/crystalhd/crystalhd_lnx.c782
-rw-r--r--drivers/staging/crystalhd/crystalhd_lnx.h93
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.c1044
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.h232
-rw-r--r--drivers/staging/cxt1e1/Kconfig21
-rw-r--r--drivers/staging/cxt1e1/Makefile18
-rw-r--r--drivers/staging/cxt1e1/comet.c596
-rw-r--r--drivers/staging/cxt1e1/comet.h353
-rw-r--r--drivers/staging/cxt1e1/comet_tables.c538
-rw-r--r--drivers/staging/cxt1e1/comet_tables.h61
-rw-r--r--drivers/staging/cxt1e1/functions.c318
-rw-r--r--drivers/staging/cxt1e1/hwprobe.c382
-rw-r--r--drivers/staging/cxt1e1/libsbew.h549
-rw-r--r--drivers/staging/cxt1e1/linux.c1142
-rw-r--r--drivers/staging/cxt1e1/musycc.c1720
-rw-r--r--drivers/staging/cxt1e1/musycc.h427
-rw-r--r--drivers/staging/cxt1e1/pmc93x6_eeprom.c532
-rw-r--r--drivers/staging/cxt1e1/pmc93x6_eeprom.h39
-rw-r--r--drivers/staging/cxt1e1/pmcc4.h108
-rw-r--r--drivers/staging/cxt1e1/pmcc4_cpld.h91
-rw-r--r--drivers/staging/cxt1e1/pmcc4_defs.h68
-rw-r--r--drivers/staging/cxt1e1/pmcc4_drv.c1613
-rw-r--r--drivers/staging/cxt1e1/pmcc4_ioctls.h65
-rw-r--r--drivers/staging/cxt1e1/pmcc4_private.h295
-rw-r--r--drivers/staging/cxt1e1/pmcc4_sysdep.h63
-rw-r--r--drivers/staging/cxt1e1/sbe_bid.h47
-rw-r--r--drivers/staging/cxt1e1/sbe_promformat.h130
-rw-r--r--drivers/staging/cxt1e1/sbecom_inline_linux.h193
-rw-r--r--drivers/staging/cxt1e1/sbecrc.c133
-rw-r--r--drivers/staging/cxt1e1/sbeid.c205
-rw-r--r--drivers/staging/cxt1e1/sbeproc.c219
-rw-r--r--drivers/staging/cxt1e1/sbeproc.h42
-rw-r--r--drivers/staging/cxt1e1/sbew_ioc.h81
-rw-r--r--drivers/staging/dgap/dgap.c662
-rw-r--r--drivers/staging/dgap/dgap.h2
-rw-r--r--drivers/staging/dgnc/Makefile2
-rw-r--r--drivers/staging/dgnc/dgnc_cls.c14
-rw-r--r--drivers/staging/dgnc/dgnc_driver.c19
-rw-r--r--drivers/staging/dgnc/dgnc_driver.h57
-rw-r--r--drivers/staging/dgnc/dgnc_neo.c1
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.c20
-rw-r--r--drivers/staging/dgnc/dgnc_trace.c185
-rw-r--r--drivers/staging/dgnc/dgnc_trace.h44
-rw-r--r--drivers/staging/dgnc/dgnc_tty.c53
-rw-r--r--drivers/staging/dgnc/digi.h35
-rw-r--r--drivers/staging/dgrp/Kconfig9
-rw-r--r--drivers/staging/dgrp/Makefile12
-rw-r--r--drivers/staging/dgrp/README2
-rw-r--r--drivers/staging/dgrp/TODO13
-rw-r--r--drivers/staging/dgrp/dgrp_common.c169
-rw-r--r--drivers/staging/dgrp/dgrp_common.h150
-rw-r--r--drivers/staging/dgrp/dgrp_dpa_ops.c534
-rw-r--r--drivers/staging/dgrp/dgrp_driver.c105
-rw-r--r--drivers/staging/dgrp/dgrp_mon_ops.c327
-rw-r--r--drivers/staging/dgrp/dgrp_net_ops.c3666
-rw-r--r--drivers/staging/dgrp/dgrp_ports_ops.c156
-rw-r--r--drivers/staging/dgrp/dgrp_specproc.c541
-rw-r--r--drivers/staging/dgrp/dgrp_sysfs.c558
-rw-r--r--drivers/staging/dgrp/dgrp_tty.c3337
-rw-r--r--drivers/staging/dgrp/digirp.h129
-rw-r--r--drivers/staging/dgrp/drp.h693
-rw-r--r--drivers/staging/emxx_udc/Kconfig10
-rw-r--r--drivers/staging/emxx_udc/Makefile1
-rw-r--r--drivers/staging/emxx_udc/TODO4
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c3520
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.h653
-rw-r--r--drivers/staging/et131x/et131x.c26
-rw-r--r--drivers/staging/et131x/et131x.h46
-rw-r--r--drivers/staging/frontier/Kconfig5
-rw-r--r--drivers/staging/frontier/Makefile2
-rw-r--r--drivers/staging/frontier/README47
-rw-r--r--drivers/staging/frontier/TODO9
-rw-r--r--drivers/staging/frontier/alphatrack.c849
-rw-r--r--drivers/staging/frontier/alphatrack.h78
-rw-r--r--drivers/staging/frontier/tranzport.c973
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/Makefile3
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000.h2
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c4
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c4
-rw-r--r--drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c211
-rw-r--r--drivers/staging/ft1000/ft1000-usb/Makefile2
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_debug.c6
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_hw.c25
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_proc.c241
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.c8
-rw-r--r--drivers/staging/ft1000/ft1000-usb/ft1000_usb.h5
-rw-r--r--drivers/staging/ft1000/ft1000.h2
-rw-r--r--drivers/staging/fwserial/fwserial.c6
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c4
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c5
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c40
-rw-r--r--drivers/staging/gdm724x/netlink_k.c2
-rw-r--r--drivers/staging/gdm72xx/Kconfig19
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.c61
-rw-r--r--drivers/staging/gdm72xx/gdm_qos.h18
-rw-r--r--drivers/staging/gdm72xx/gdm_sdio.c107
-rw-r--r--drivers/staging/gdm72xx/gdm_sdio.h6
-rw-r--r--drivers/staging/gdm72xx/gdm_usb.c121
-rw-r--r--drivers/staging/gdm72xx/gdm_usb.h6
-rw-r--r--drivers/staging/gdm72xx/gdm_wimax.c382
-rw-r--r--drivers/staging/gdm72xx/gdm_wimax.h17
-rw-r--r--drivers/staging/gdm72xx/hci.h22
-rw-r--r--drivers/staging/gdm72xx/netlink_k.h7
-rw-r--r--drivers/staging/gdm72xx/sdio_boot.h6
-rw-r--r--drivers/staging/gdm72xx/usb_boot.c10
-rw-r--r--drivers/staging/gdm72xx/usb_boot.h6
-rw-r--r--drivers/staging/gdm72xx/usb_ids.h6
-rw-r--r--drivers/staging/gdm72xx/wm_ioctl.h7
-rw-r--r--drivers/staging/goldfish/goldfish_audio.c65
-rw-r--r--drivers/staging/iio/Documentation/generic_buffer.c9
-rw-r--r--drivers/staging/iio/Documentation/iio_event_monitor.c8
-rw-r--r--drivers/staging/iio/Documentation/iio_utils.h6
-rw-r--r--drivers/staging/iio/Documentation/trigger.txt2
-rw-r--r--drivers/staging/iio/accel/adis16201_core.c14
-rw-r--r--drivers/staging/iio/accel/adis16203_core.c11
-rw-r--r--drivers/staging/iio/accel/adis16204_core.c12
-rw-r--r--drivers/staging/iio/accel/adis16209_core.c18
-rw-r--r--drivers/staging/iio/accel/adis16240_core.c12
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c2
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c6
-rw-r--r--drivers/staging/iio/adc/Kconfig9
-rw-r--r--drivers/staging/iio/adc/Makefile1
-rw-r--r--drivers/staging/iio/adc/ad7606_par.c37
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c2
-rw-r--r--drivers/staging/iio/frequency/ad9832.c16
-rw-r--r--drivers/staging/iio/frequency/ad9850.c6
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c2
-rw-r--r--drivers/staging/iio/magnetometer/Kconfig30
-rw-r--r--drivers/staging/iio/magnetometer/Makefile4
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.h59
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843_core.c (renamed from drivers/staging/iio/magnetometer/hmc5843.c)266
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843_i2c.c104
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843_spi.c100
-rw-r--r--drivers/staging/iio/meter/ade7758_trigger.c2
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c33
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c29
-rw-r--r--drivers/staging/imx-drm/imx-drm-core.c63
-rw-r--r--drivers/staging/keucr/Kconfig14
-rw-r--r--drivers/staging/keucr/Makefile13
-rw-r--r--drivers/staging/keucr/TODO12
-rw-r--r--drivers/staging/keucr/common.h7
-rw-r--r--drivers/staging/keucr/init.c333
-rw-r--r--drivers/staging/keucr/init.h518
-rw-r--r--drivers/staging/keucr/scsiglue.c467
-rw-r--r--drivers/staging/keucr/scsiglue.h10
-rw-r--r--drivers/staging/keucr/smcommon.h29
-rw-r--r--drivers/staging/keucr/smil.h288
-rw-r--r--drivers/staging/keucr/smilecc.c211
-rw-r--r--drivers/staging/keucr/smilmain.c760
-rw-r--r--drivers/staging/keucr/smilsub.c679
-rw-r--r--drivers/staging/keucr/smscsi.c194
-rw-r--r--drivers/staging/keucr/transport.c865
-rw-r--r--drivers/staging/keucr/transport.h73
-rw-r--r--drivers/staging/keucr/usb.c642
-rw-r--r--drivers/staging/keucr/usb.h240
-rw-r--r--drivers/staging/line6/driver.c2
-rw-r--r--drivers/staging/lustre/Makefile2
-rw-r--r--drivers/staging/lustre/TODO3
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/bitmap.h1
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/curproc.h2
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs.h55
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h10
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h2
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h18
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h33
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h17
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h4
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_private.h43
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/libcfs_time.h29
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/kp30.h93
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h67
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-bitops.h38
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h84
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-lock.h204
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h11
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h82
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h72
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h149
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/linux-types.h36
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h22
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/lucache.h16
-rw-r--r--drivers/staging/lustre/include/linux/libcfs/params_tree.h164
-rw-r--r--drivers/staging/lustre/include/linux/lnet/api-support.h8
-rw-r--r--drivers/staging/lustre/include/linux/lnet/api.h5
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lib-lnet.h50
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lib-types.h23
-rw-r--r--drivers/staging/lustre/include/linux/lnet/linux/api-support.h1
-rw-r--r--drivers/staging/lustre/include/linux/lnet/linux/lib-lnet.h5
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lnet-sysctl.h2
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lnet.h6
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lnetctl.h22
-rw-r--r--drivers/staging/lustre/include/linux/lnet/lnetst.h6
-rw-r--r--drivers/staging/lustre/include/linux/lnet/ptllnd.h3
-rw-r--r--drivers/staging/lustre/include/linux/lnet/ptllnd_wire.h3
-rw-r--r--drivers/staging/lustre/include/linux/lnet/socklnd.h4
-rw-r--r--drivers/staging/lustre/include/linux/lnet/types.h4
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/Makefile3
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c39
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h22
-rw-r--r--drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c11
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/Makefile4
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c98
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h46
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c43
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c2
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h4
-rw-r--r--drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c12
-rw-r--r--drivers/staging/lustre/lnet/lnet/Makefile3
-rw-r--r--drivers/staging/lustre/lnet/lnet/acceptor.c28
-rw-r--r--drivers/staging/lustre/lnet/lnet/api-ni.c34
-rw-r--r--drivers/staging/lustre/lnet/lnet/config.c4
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-eq.c4
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-md.c12
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-me.c15
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-move.c108
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-msg.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/lib-ptl.c18
-rw-r--r--drivers/staging/lustre/lnet/lnet/lo.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/module.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/peer.c2
-rw-r--r--drivers/staging/lustre/lnet/lnet/router.c23
-rw-r--r--drivers/staging/lustre/lnet/lnet/router_proc.c84
-rw-r--r--drivers/staging/lustre/lnet/selftest/Makefile2
-rw-r--r--drivers/staging/lustre/lnet/selftest/brw_test.c2
-rw-r--r--drivers/staging/lustre/lnet/selftest/conctl.c8
-rw-r--r--drivers/staging/lustre/lnet/selftest/conrpc.c16
-rw-r--r--drivers/staging/lustre/lnet/selftest/conrpc.h10
-rw-r--r--drivers/staging/lustre/lnet/selftest/console.c16
-rw-r--r--drivers/staging/lustre/lnet/selftest/console.h10
-rw-r--r--drivers/staging/lustre/lnet/selftest/framework.c12
-rw-r--r--drivers/staging/lustre/lnet/selftest/rpc.c14
-rw-r--r--drivers/staging/lustre/lnet/selftest/rpc.h2
-rw-r--r--drivers/staging/lustre/lnet/selftest/selftest.h12
-rw-r--r--drivers/staging/lustre/lnet/selftest/timer.c16
-rw-r--r--drivers/staging/lustre/lnet/selftest/timer.h2
-rw-r--r--drivers/staging/lustre/lustre/Kconfig1
-rw-r--r--drivers/staging/lustre/lustre/fid/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_internal.h8
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_lib.c6
-rw-r--r--drivers/staging/lustre/lustre/fid/fid_request.c38
-rw-r--r--drivers/staging/lustre/lustre/fid/lproc_fid.c32
-rw-r--r--drivers/staging/lustre/lustre/fld/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_cache.c34
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_internal.h12
-rw-r--r--drivers/staging/lustre/lustre/fld/fld_request.c54
-rw-r--r--drivers/staging/lustre/lustre/fld/lproc_fld.c25
-rw-r--r--drivers/staging/lustre/lustre/include/cl_object.h8
-rw-r--r--drivers/staging/lustre/lustre/include/dt_object.h8
-rw-r--r--drivers/staging/lustre/lustre/include/interval_tree.h2
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lprocfs_status.h2
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_acl.h2
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_compat25.h4
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h10
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_lib.h4
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lustre_lite.h10
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lvfs.h6
-rw-r--r--drivers/staging/lustre/lustre/include/linux/lvfs_linux.h9
-rw-r--r--drivers/staging/lustre/lustre/include/linux/obd.h4
-rw-r--r--drivers/staging/lustre/lustre/include/linux/obd_support.h10
-rw-r--r--drivers/staging/lustre/lustre/include/lprocfs_status.h21
-rw-r--r--drivers/staging/lustre/lustre/include/lu_object.h6
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_idl.h17
-rw-r--r--drivers/staging/lustre/lustre/include/lustre/lustre_user.h14
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_acl.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_capa.h14
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_cfg.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_debug.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_disk.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_dlm.h28
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_export.h16
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_fid.h6
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_fld.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_fsfilt.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_handles.h4
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_idmap.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_import.h10
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_lib.h30
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_lite.h14
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_log.h10
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_mdc.h16
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_mds.h12
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_net.h58
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_quota.h8
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_req_layout.h2
-rw-r--r--drivers/staging/lustre/lustre/include/lustre_sec.h10
-rw-r--r--drivers/staging/lustre/lustre/include/lvfs.h6
-rw-r--r--drivers/staging/lustre/lustre/include/md_object.h2
-rw-r--r--drivers/staging/lustre/lustre/include/obd.h21
-rw-r--r--drivers/staging/lustre/lustre/include/obd_cksum.h4
-rw-r--r--drivers/staging/lustre/lustre/include/obd_class.h32
-rw-r--r--drivers/staging/lustre/lustre/include/obd_ost.h6
-rw-r--r--drivers/staging/lustre/lustre/include/obd_support.h23
-rw-r--r--drivers/staging/lustre/lustre/lclient/glimpse.c28
-rw-r--r--drivers/staging/lustre/lustre/lclient/lcommon_cl.c37
-rw-r--r--drivers/staging/lustre/lustre/lclient/lcommon_misc.c16
-rw-r--r--drivers/staging/lustre/lustre/ldlm/interval_tree.c6
-rw-r--r--drivers/staging/lustre/lustre/ldlm/l_lock.c6
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_extent.c16
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_flock.c14
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_inodebits.c7
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_lib.c46
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_lock.c53
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c15
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_plain.c6
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_pool.c38
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_request.c38
-rw-r--r--drivers/staging/lustre/lustre/ldlm/ldlm_resource.c39
-rw-r--r--drivers/staging/lustre/lustre/libcfs/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/libcfs/debug.c10
-rw-r--r--drivers/staging/lustre/lustre/libcfs/fail.c12
-rw-r--r--drivers/staging/lustre/lustre/libcfs/hash.c6
-rw-r--r--drivers/staging/lustre/lustre/libcfs/heap.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_lock.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_mem.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/libcfs_string.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-crypto-adler.c5
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c4
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.h (renamed from drivers/staging/lustre/include/linux/libcfs/linux/linux-crypto.h)20
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c6
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-module.c16
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c6
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c94
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c31
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c6
-rw-r--r--drivers/staging/lustre/lustre/libcfs/module.c11
-rw-r--r--drivers/staging/lustre/lustre/libcfs/nidstrings.c9
-rw-r--r--drivers/staging/lustre/lustre/libcfs/prng.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/tracefile.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/tracefile.h2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/upcall_cache.c26
-rw-r--r--drivers/staging/lustre/lustre/libcfs/workitem.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/llite/dcache.c16
-rw-r--r--drivers/staging/lustre/lustre/llite/dir.c62
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c24
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_capa.c24
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_close.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_internal.h26
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_lib.c52
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_mmap.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_nfs.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_rmtacl.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/lloop.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/lproc_llite.c79
-rw-r--r--drivers/staging/lustre/lustre/llite/namei.c14
-rw-r--r--drivers/staging/lustre/lustre/llite/remote_perm.c14
-rw-r--r--drivers/staging/lustre/lustre/llite/rw.c15
-rw-r--r--drivers/staging/lustre/lustre/llite/rw26.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/statahead.c30
-rw-r--r--drivers/staging/lustre/lustre/llite/super25.c8
-rw-r--r--drivers/staging/lustre/lustre/llite/symlink.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_dev.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_internal.h2
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_io.c10
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_lock.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_object.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_page.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr.c11
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr_cache.c8
-rw-r--r--drivers/staging/lustre/lustre/lmv/Makefile2
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_fld.c20
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_intent.c17
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/lmv/lmv_obd.c30
-rw-r--r--drivers/staging/lustre/lustre/lmv/lproc_lmv.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/Makefile4
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_cl_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_dev.c4
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_ea.c8
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_internal.h8
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_io.c6
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_merge.c31
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_obd.c52
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_offset.c6
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_pack.c12
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_pool.c10
-rw-r--r--drivers/staging/lustre/lustre/lov/lov_request.c43
-rw-r--r--drivers/staging/lustre/lustre/lov/lproc_lov.c8
-rw-r--r--drivers/staging/lustre/lustre/lvfs/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/lvfs/fsfilt.c4
-rw-r--r--drivers/staging/lustre/lustre/lvfs/lvfs_lib.c4
-rw-r--r--drivers/staging/lustre/lustre/lvfs/lvfs_linux.c18
-rw-r--r--drivers/staging/lustre/lustre/mdc/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/mdc/lproc_mdc.c48
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_lib.c4
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_locks.c18
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_reint.c6
-rw-r--r--drivers/staging/lustre/lustre/mdc/mdc_request.c34
-rw-r--r--drivers/staging/lustre/lustre/mgc/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/mgc/libmgc.c12
-rw-r--r--drivers/staging/lustre/lustre/mgc/lproc_mgc.c4
-rw-r--r--drivers/staging/lustre/lustre/mgc/mgc_internal.h16
-rw-r--r--drivers/staging/lustre/lustre/mgc/mgc_request.c29
-rw-r--r--drivers/staging/lustre/lustre/obdclass/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/obdclass/acl.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/capa.c23
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_io.c10
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_lock.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_object.c15
-rw-r--r--drivers/staging/lustre/lustre/obdclass/cl_page.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/class_obd.c56
-rw-r--r--drivers/staging/lustre/lustre/obdclass/debug.c24
-rw-r--r--drivers/staging/lustre/lustre/obdclass/dt_object.c22
-rw-r--r--drivers/staging/lustre/lustre/obdclass/genops.c16
-rw-r--r--drivers/staging/lustre/lustre/obdclass/idmap.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linkea.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linux/linux-module.c20
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c98
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_cat.c2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_internal.h2
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_ioctl.c4
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_lvfs.c50
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_obd.c4
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_osd.c22
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_swab.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/llog_test.c12
-rw-r--r--drivers/staging/lustre/lustre/obdclass/local_storage.c10
-rw-r--r--drivers/staging/lustre/lustre/obdclass/local_storage.h8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lprocfs_status.c48
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_object.c18
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_ref.c10
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lu_ucred.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lustre_handles.c14
-rw-r--r--drivers/staging/lustre/lustre/obdclass/lustre_peer.c14
-rw-r--r--drivers/staging/lustre/lustre/obdclass/md_attrs.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/mea.c6
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_config.c22
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obd_mount.c32
-rw-r--r--drivers/staging/lustre/lustre/obdclass/obdo.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/statfs_pack.c8
-rw-r--r--drivers/staging/lustre/lustre/obdclass/uuid.c6
-rw-r--r--drivers/staging/lustre/lustre/obdecho/Makefile3
-rw-r--r--drivers/staging/lustre/lustre/obdecho/echo.c34
-rw-r--r--drivers/staging/lustre/lustre/obdecho/echo_client.c40
-rw-r--r--drivers/staging/lustre/lustre/obdecho/lproc_echo.c16
-rw-r--r--drivers/staging/lustre/lustre/osc/Makefile4
-rw-r--r--drivers/staging/lustre/lustre/osc/lproc_osc.c12
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_cache.c13
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_cl_internal.h14
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_dev.c16
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_io.c4
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_lock.c17
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_object.c12
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_page.c6
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_quota.c2
-rw-r--r--drivers/staging/lustre/lustre/osc/osc_request.c93
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/Makefile5
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/client.c92
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/connection.c6
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/errno.c4
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/events.c27
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/Makefile8
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h179
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h84
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c505
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c446
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h193
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c296
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h526
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c1409
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h163
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c1786
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c358
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c1233
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c242
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c1093
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c220
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c2889
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/import.c89
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/layout.c16
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/llog_client.c8
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/llog_net.c10
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c29
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/niobuf.c49
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/nrs.c10
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c14
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/pack_generic.c38
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/pers.c10
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/pinger.c26
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h6
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c8
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c19
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/recover.c26
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec.c42
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c40
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_config.c24
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_gc.c16
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c20
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_null.c21
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_plain.c22
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/service.c84
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/wiretest.c8
-rw-r--r--drivers/staging/media/Kconfig10
-rw-r--r--drivers/staging/media/Makefile5
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c22
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h1
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipeif.c5
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.c4
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c1
-rw-r--r--drivers/staging/media/go7007/README137
-rw-r--r--drivers/staging/media/go7007/go7007.h40
-rw-r--r--drivers/staging/media/go7007/go7007.txt478
-rw-r--r--drivers/staging/media/go7007/saa7134-go7007.c567
-rw-r--r--drivers/staging/media/lirc/lirc_igorplugusb.c6
-rw-r--r--drivers/staging/media/lirc/lirc_imon.c9
-rw-r--r--drivers/staging/media/lirc/lirc_parallel.c32
-rw-r--r--drivers/staging/media/lirc/lirc_serial.c37
-rw-r--r--drivers/staging/media/lirc/lirc_sir.c301
-rw-r--r--drivers/staging/media/msi3101/Kconfig10
-rw-r--r--drivers/staging/media/msi3101/Makefile2
-rw-r--r--drivers/staging/media/omap4iss/iss.c86
-rw-r--r--drivers/staging/media/omap4iss/iss.h2
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c2
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c22
-rw-r--r--drivers/staging/media/rtl2832u_sdr/Kconfig7
-rw-r--r--drivers/staging/media/rtl2832u_sdr/Makefile6
-rw-r--r--drivers/staging/media/sn9c102/Kconfig17
-rw-r--r--drivers/staging/media/sn9c102/Makefile15
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.h214
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.txt592
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_config.h86
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_core.c3465
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_devtable.h145
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131d.c269
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131r.c369
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0343.c352
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0360.c453
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mt9v111.c260
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7630.c634
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7660.c546
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas106b.c308
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas202bcb.c340
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_sensor.h307
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c154
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110d.c119
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c165
-rw-r--r--drivers/staging/media/solo6x10/TODO15
-rw-r--r--drivers/staging/netlogic/xlr_net.c1
-rw-r--r--drivers/staging/nokia_h4p/nokia_core.c1
-rw-r--r--drivers/staging/nvec/nvec.c17
-rw-r--r--drivers/staging/nvec/nvec_paz00.c1
-rw-r--r--drivers/staging/nvec/nvec_power.c1
-rw-r--r--drivers/staging/nvec/nvec_ps2.c2
-rw-r--r--drivers/staging/octeon-usb/octeon-hcd.c69
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c79
-rw-r--r--drivers/staging/octeon/ethernet-mem.c11
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c23
-rw-r--r--drivers/staging/octeon/ethernet-sgmii.c87
-rw-r--r--drivers/staging/octeon/ethernet-xaui.c84
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/octeon/octeon-ethernet.h4
-rw-r--r--drivers/staging/panel/panel.c9
-rw-r--r--drivers/staging/phison/Kconfig5
-rw-r--r--drivers/staging/phison/Makefile1
-rw-r--r--drivers/staging/phison/phison.c94
-rw-r--r--drivers/staging/quickstart/Kconfig10
-rw-r--r--drivers/staging/quickstart/Makefile1
-rw-r--r--drivers/staging/quickstart/quickstart.c458
-rw-r--r--drivers/staging/rtl8188eu/Kconfig8
-rw-r--r--drivers/staging/rtl8188eu/Makefile9
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c60
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_br_ext.c1191
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c909
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_debug.c28
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c1509
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c262
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_io.c301
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ioctl_set.c480
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_iol.c14
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_led.c52
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c216
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c3224
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mp.c995
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mp_ioctl.c1430
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_p2p.c2041
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_pwrctrl.c171
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c80
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_security.c59
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sreset.c19
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sta_mgt.c54
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c19
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c252
-rw-r--r--drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c10
-rw-r--r--drivers/staging/rtl8188eu/hal/HalPhyRf.c49
-rw-r--r--drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c99
-rw-r--r--drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c7
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_com.c60
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_intf.c67
-rw-r--r--drivers/staging/rtl8188eu/hal/odm.c28
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_RegConfig8188E.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c107
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_dm.c8
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c1395
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_mp.c854
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c26
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_sreset.c80
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_led.c15
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c6
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c33
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_halinit.c560
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_ops_linux.c684
-rw-r--r--drivers/staging/rtl8188eu/include/Hal8188EReg.h46
-rw-r--r--drivers/staging/rtl8188eu/include/HalPhyRf.h30
-rw-r--r--drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h2
-rw-r--r--drivers/staging/rtl8188eu/include/cmd_osdep.h32
-rw-r--r--drivers/staging/rtl8188eu/include/drv_types.h78
-rw-r--r--drivers/staging/rtl8188eu/include/hal_com.h4
-rw-r--r--drivers/staging/rtl8188eu/include/hal_intf.h46
-rw-r--r--drivers/staging/rtl8188eu/include/ieee80211.h13
-rw-r--r--drivers/staging/rtl8188eu/include/odm_precomp.h4
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_intf.h38
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_service.h178
-rw-r--r--drivers/staging/rtl8188eu/include/recv_osdep.h3
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_cmd.h5
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_hal.h14
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_sreset.h31
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_xmit.h1
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_br_ext.h66
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_cmd.h612
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_debug.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_efuse.h51
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_io.h343
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ioctl_set.h8
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_iol.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme.h28
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme_ext.h93
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mp.h495
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mp_ioctl.h340
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_p2p.h135
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_security.h1
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_sreset.h5
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_version.h1
-rw-r--r--drivers/staging/rtl8188eu/include/sta_info.h15
-rw-r--r--drivers/staging/rtl8188eu/include/usb_ops.h114
-rw-r--r--drivers/staging/rtl8188eu/include/usb_ops_linux.h42
-rw-r--r--drivers/staging/rtl8188eu/include/usb_osintf.h45
-rw-r--r--drivers/staging/rtl8188eu/include/usb_vendor_req.h52
-rw-r--r--drivers/staging/rtl8188eu/include/wlan_bssdef.h4
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c5151
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mlme_linux.c64
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c111
-rw-r--r--drivers/staging/rtl8188eu/os_dep/osdep_service.c287
-rw-r--r--drivers/staging/rtl8188eu/os_dep/recv_linux.c28
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c255
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c646
-rw-r--r--drivers/staging/rtl8188eu/os_dep/xmit_linux.c5
-rw-r--r--drivers/staging/rtl8192e/dot11d.c8
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c15
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c5
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c3
-rw-r--r--drivers/staging/rtl8192ee/Kconfig1
-rw-r--r--drivers/staging/rtl8192ee/base.c5
-rw-r--r--drivers/staging/rtl8192ee/base.h4
-rw-r--r--drivers/staging/rtl8192ee/btcoexist/halbtc8821a2ant.c2
-rw-r--r--drivers/staging/rtl8192ee/btcoexist/halbtcoutsrc.h2
-rw-r--r--drivers/staging/rtl8192ee/pci.c39
-rw-r--r--drivers/staging/rtl8192ee/rtl8192ee/trx.c4
-rw-r--r--drivers/staging/rtl8192ee/rtl8192ee/trx.h2
-rw-r--r--drivers/staging/rtl8192ee/wifi.h2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h10
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c8
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.c15
-rw-r--r--drivers/staging/rtl8192u/r8180_93cx6.h11
-rw-r--r--drivers/staging/rtl8192u/r8190_rtl8256.c169
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c548
-rw-r--r--drivers/staging/rtl8192u/r8192U_wx.c159
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c25
-rw-r--r--drivers/staging/rtl8712/drv_types.h3
-rw-r--r--drivers/staging/rtl8712/hal_init.c2
-rw-r--r--drivers/staging/rtl8712/ieee80211.h4
-rw-r--r--drivers/staging/rtl8712/mlme_linux.c3
-rw-r--r--drivers/staging/rtl8712/os_intfs.c3
-rw-r--r--drivers/staging/rtl8712/osdep_service.h82
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c6
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c4
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c57
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c20
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c114
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h2
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.c12
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c31
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c6
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h2
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c64
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c8
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c10
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h4
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c18
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c51
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c56
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h6
-rw-r--r--drivers/staging/rtl8712/usb_intf.c40
-rw-r--r--drivers/staging/rtl8723au/Makefile4
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ap.c205
-rw-r--r--drivers/staging/rtl8723au/core/rtw_cmd.c42
-rw-r--r--drivers/staging/rtl8723au/core/rtw_efuse.c31
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ieee80211.c348
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ioctl_set.c425
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme.c541
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme_ext.c1747
-rw-r--r--drivers/staging/rtl8723au/core/rtw_pwrctrl.c56
-rw-r--r--drivers/staging/rtl8723au/core/rtw_recv.c8
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sreset.c49
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sta_mgt.c63
-rw-r--r--drivers/staging/rtl8723au/core/rtw_wlan_util.c418
-rw-r--r--drivers/staging/rtl8723au/core/rtw_xmit.c12
-rw-r--r--drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c160
-rw-r--r--drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c5
-rw-r--r--drivers/staging/rtl8723au/hal/hal_com.c36
-rw-r--r--drivers/staging/rtl8723au/hal/odm.c429
-rw-r--r--drivers/staging/rtl8723au/hal/odm_HWConfig.c68
-rw-r--r--drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c58
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c5
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_cmd.c89
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_dm.c81
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c125
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c28
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c13
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_sreset.c19
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_xmit.c21
-rw-r--r--drivers/staging/rtl8723au/hal/usb_halinit.c162
-rw-r--r--drivers/staging/rtl8723au/hal/usb_ops_linux.c317
-rw-r--r--drivers/staging/rtl8723au/include/Hal8723APhyCfg.h1
-rw-r--r--drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h6
-rw-r--r--drivers/staging/rtl8723au/include/drv_types.h15
-rw-r--r--drivers/staging/rtl8723au/include/hal_com.h3
-rw-r--r--drivers/staging/rtl8723au/include/hal_intf.h5
-rw-r--r--drivers/staging/rtl8723au/include/ieee80211.h109
-rw-r--r--drivers/staging/rtl8723au/include/ioctl_cfg80211.h3
-rw-r--r--drivers/staging/rtl8723au/include/odm.h102
-rw-r--r--drivers/staging/rtl8723au/include/odm_HWConfig.h17
-rw-r--r--drivers/staging/rtl8723au/include/odm_RegConfig8723A.h6
-rw-r--r--drivers/staging/rtl8723au/include/odm_RegDefine11AC.h49
-rw-r--r--drivers/staging/rtl8723au/include/odm_interface.h11
-rw-r--r--drivers/staging/rtl8723au/include/odm_precomp.h1
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_cmd.h2
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_dm.h4
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_hal.h5
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_spec.h10
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_sreset.h1
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_xmit.h1
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ap.h3
-rw-r--r--drivers/staging/rtl8723au/include/rtw_debug.h2
-rw-r--r--drivers/staging/rtl8723au/include/rtw_event.h2
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ht.h4
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ioctl_set.h32
-rw-r--r--drivers/staging/rtl8723au/include/rtw_mlme.h50
-rw-r--r--drivers/staging/rtl8723au/include/rtw_mlme_ext.h37
-rw-r--r--drivers/staging/rtl8723au/include/rtw_pwrctrl.h20
-rw-r--r--drivers/staging/rtl8723au/include/rtw_rf.h11
-rw-r--r--drivers/staging/rtl8723au/include/rtw_security.h3
-rw-r--r--drivers/staging/rtl8723au/include/rtw_sreset.h20
-rw-r--r--drivers/staging/rtl8723au/include/sta_info.h2
-rw-r--r--drivers/staging/rtl8723au/include/usb_ops_linux.h14
-rw-r--r--drivers/staging/rtl8723au/include/wifi.h71
-rw-r--r--drivers/staging/rtl8723au/include/wlan_bssdef.h6
-rw-r--r--drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c1105
-rw-r--r--drivers/staging/rtl8723au/os_dep/mlme_linux.c1
-rw-r--r--drivers/staging/rtl8723au/os_dep/os_intfs.c19
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_intf.c93
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_ops_linux.c10
-rw-r--r--drivers/staging/rtl8821ae/Kconfig1
-rw-r--r--drivers/staging/rtl8821ae/btcoexist/HalBtc8812a1Ant.c14
-rw-r--r--drivers/staging/rtl8821ae/btcoexist/halbtc8192e2ant.h2
-rw-r--r--drivers/staging/rtl8821ae/btcoexist/halbtcoutsrc.h2
-rw-r--r--drivers/staging/rtl8821ae/cam.c7
-rw-r--r--drivers/staging/rtl8821ae/pci.c38
-rw-r--r--drivers/staging/rtl8821ae/ps.c6
-rw-r--r--drivers/staging/rtl8821ae/rtl8821ae/hal_btc.c17
-rw-r--r--drivers/staging/rtl8821ae/rtl8821ae/hw.c2
-rw-r--r--drivers/staging/rtl8821ae/rtl8821ae/reg.h1
-rw-r--r--drivers/staging/rtl8821ae/rtl8821ae/sw.c4
-rw-r--r--drivers/staging/rtl8821ae/wifi.h2
-rw-r--r--drivers/staging/rts5208/debug.h43
-rw-r--r--drivers/staging/rts5208/ms.c126
-rw-r--r--drivers/staging/rts5208/rtsx.c10
-rw-r--r--drivers/staging/rts5208/rtsx.h1
-rw-r--r--drivers/staging/rts5208/rtsx_card.c73
-rw-r--r--drivers/staging/rts5208/rtsx_card.h1
-rw-r--r--drivers/staging/rts5208/rtsx_chip.c133
-rw-r--r--drivers/staging/rts5208/rtsx_chip.h5
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c44
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.h2
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c55
-rw-r--r--drivers/staging/rts5208/sd.c185
-rw-r--r--drivers/staging/rts5208/spi.c7
-rw-r--r--drivers/staging/rts5208/trace.h10
-rw-r--r--drivers/staging/rts5208/xd.c104
-rw-r--r--drivers/staging/sep/Kconfig11
-rw-r--r--drivers/staging/sep/Makefile3
-rw-r--r--drivers/staging/sep/TODO3
-rw-r--r--drivers/staging/sep/sep_crypto.c3962
-rw-r--r--drivers/staging/sep/sep_crypto.h359
-rw-r--r--drivers/staging/sep/sep_dev.h162
-rw-r--r--drivers/staging/sep/sep_driver_api.h402
-rw-r--r--drivers/staging/sep/sep_driver_config.h298
-rw-r--r--drivers/staging/sep/sep_driver_hw_defs.h56
-rw-r--r--drivers/staging/sep/sep_main.c4452
-rw-r--r--drivers/staging/sep/sep_trace_events.h193
-rw-r--r--drivers/staging/serqt_usb2/Kconfig9
-rw-r--r--drivers/staging/serqt_usb2/Makefile1
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c1528
-rw-r--r--drivers/staging/silicom/Kconfig45
-rw-r--r--drivers/staging/silicom/Makefile6
-rw-r--r--drivers/staging/silicom/README14
-rw-r--r--drivers/staging/silicom/TODO8
-rw-r--r--drivers/staging/silicom/bits.h56
-rw-r--r--drivers/staging/silicom/bp_ioctl.h140
-rw-r--r--drivers/staging/silicom/bp_mod.h711
-rw-r--r--drivers/staging/silicom/bpctl_mod.c7530
-rw-r--r--drivers/staging/silicom/bypass.h202
-rw-r--r--drivers/staging/silicom/bypasslib/Makefile6
-rw-r--r--drivers/staging/silicom/bypasslib/bp_ioctl.h198
-rw-r--r--drivers/staging/silicom/bypasslib/bplibk.h36
-rw-r--r--drivers/staging/silicom/bypasslib/bypass.c536
-rw-r--r--drivers/staging/silicom/bypasslib/libbp_sd.h532
-rw-r--r--drivers/staging/silicom/libbp_sd.h550
-rw-r--r--drivers/staging/skein/skein_iv.h26
-rw-r--r--drivers/staging/slicoss/slicoss.c31
-rw-r--r--drivers/staging/speakup/TODO2
-rw-r--r--drivers/staging/speakup/main.c2
-rw-r--r--drivers/staging/speakup/speakup_dectlk.c2
-rw-r--r--drivers/staging/tidspbridge/Documentation/CONTRIBUTORS45
-rw-r--r--drivers/staging/tidspbridge/Documentation/README70
-rw-r--r--drivers/staging/tidspbridge/Documentation/error-codes157
-rw-r--r--drivers/staging/tidspbridge/Kconfig69
-rw-r--r--drivers/staging/tidspbridge/Makefile32
-rw-r--r--drivers/staging/tidspbridge/TODO18
-rw-r--r--drivers/staging/tidspbridge/core/_cmm.h45
-rw-r--r--drivers/staging/tidspbridge/core/_deh.h35
-rw-r--r--drivers/staging/tidspbridge/core/_msg_sm.h142
-rw-r--r--drivers/staging/tidspbridge/core/_tiomap.h382
-rw-r--r--drivers/staging/tidspbridge/core/_tiomap_pwr.h85
-rw-r--r--drivers/staging/tidspbridge/core/chnl_sm.c907
-rw-r--r--drivers/staging/tidspbridge/core/dsp-clock.c391
-rw-r--r--drivers/staging/tidspbridge/core/io_sm.c2245
-rw-r--r--drivers/staging/tidspbridge/core/msg_sm.c564
-rw-r--r--drivers/staging/tidspbridge/core/sync.c121
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430.c1813
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430_pwr.c556
-rw-r--r--drivers/staging/tidspbridge/core/tiomap_io.c438
-rw-r--r--drivers/staging/tidspbridge/core/tiomap_io.h104
-rw-r--r--drivers/staging/tidspbridge/core/ue_deh.c272
-rw-r--r--drivers/staging/tidspbridge/core/wdt.c143
-rw-r--r--drivers/staging/tidspbridge/dynload/cload.c1952
-rw-r--r--drivers/staging/tidspbridge/dynload/dload_internal.h344
-rw-r--r--drivers/staging/tidspbridge/dynload/doff.h354
-rw-r--r--drivers/staging/tidspbridge/dynload/getsection.c407
-rw-r--r--drivers/staging/tidspbridge/dynload/header.h49
-rw-r--r--drivers/staging/tidspbridge/dynload/module_list.h159
-rw-r--r--drivers/staging/tidspbridge/dynload/params.h226
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc.c484
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc_table.h102
-rw-r--r--drivers/staging/tidspbridge/dynload/reloc_table_c6000.c257
-rw-r--r--drivers/staging/tidspbridge/dynload/tramp.c1143
-rw-r--r--drivers/staging/tidspbridge/dynload/tramp_table_c6000.c164
-rw-r--r--drivers/staging/tidspbridge/gen/gh.c141
-rw-r--r--drivers/staging/tidspbridge/hw/EasiGlobal.h41
-rw-r--r--drivers/staging/tidspbridge/hw/MMUAccInt.h76
-rw-r--r--drivers/staging/tidspbridge/hw/MMURegAcM.h225
-rw-r--r--drivers/staging/tidspbridge/hw/hw_defs.h58
-rw-r--r--drivers/staging/tidspbridge/hw/hw_mmu.c487
-rw-r--r--drivers/staging/tidspbridge/hw/hw_mmu.h160
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h177
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/brddefs.h37
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h61
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/chnl.h80
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/chnldefs.h63
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/chnlpriv.h85
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/clk.h101
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/cmm.h337
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/cmmdefs.h104
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/cod.h329
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dbdcd.h358
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dbdcddef.h78
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dbdefs.h488
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dbll.h56
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dblldefs.h431
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dev.h620
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/devdefs.h26
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/disp.h186
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dmm.h71
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/drv.h468
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspapi-ioctl.h467
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspapi.h167
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspchnl.h72
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspdefs.h1048
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspdeh.h43
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspdrv.h60
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspio.h41
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspioctl.h68
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dspmsg.h56
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dynamic_loader.h490
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/getsection.h108
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/gh.h32
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/host_os.h57
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/io.h80
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/io_sm.h160
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h144
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/memdefs.h30
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/mgr.h205
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/mgrpriv.h45
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/msg.h59
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/msgdefs.h29
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/nldr.h55
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/nldrdefs.h259
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/node.h524
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/nodedefs.h28
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/nodepriv.h181
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/ntfy.h217
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/proc.h591
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/procpriv.h25
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/pwr.h113
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h41
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/rmm.h156
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/rms_sh.h86
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/rmstypes.h24
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/strm.h306
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/strmdefs.h44
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/sync.h119
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/uuidutil.h24
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/wdt.h79
-rw-r--r--drivers/staging/tidspbridge/pmgr/chnl.c115
-rw-r--r--drivers/staging/tidspbridge/pmgr/chnlobj.h46
-rw-r--r--drivers/staging/tidspbridge/pmgr/cmm.c915
-rw-r--r--drivers/staging/tidspbridge/pmgr/cod.c537
-rw-r--r--drivers/staging/tidspbridge/pmgr/dbll.c1421
-rw-r--r--drivers/staging/tidspbridge/pmgr/dev.c969
-rw-r--r--drivers/staging/tidspbridge/pmgr/dmm.c487
-rw-r--r--drivers/staging/tidspbridge/pmgr/dspapi.c1843
-rw-r--r--drivers/staging/tidspbridge/pmgr/io.c93
-rw-r--r--drivers/staging/tidspbridge/pmgr/ioobj.h38
-rw-r--r--drivers/staging/tidspbridge/pmgr/msg.c91
-rw-r--r--drivers/staging/tidspbridge/pmgr/msgobj.h38
-rw-r--r--drivers/staging/tidspbridge/rmgr/dbdcd.c1483
-rw-r--r--drivers/staging/tidspbridge/rmgr/disp.c655
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv.c816
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c648
-rw-r--r--drivers/staging/tidspbridge/rmgr/dspdrv.c139
-rw-r--r--drivers/staging/tidspbridge/rmgr/mgr.c352
-rw-r--r--drivers/staging/tidspbridge/rmgr/nldr.c1860
-rw-r--r--drivers/staging/tidspbridge/rmgr/node.c3029
-rw-r--r--drivers/staging/tidspbridge/rmgr/proc.c1833
-rw-r--r--drivers/staging/tidspbridge/rmgr/pwr.c176
-rw-r--r--drivers/staging/tidspbridge/rmgr/rmm.c456
-rw-r--r--drivers/staging/tidspbridge/rmgr/strm.c733
-rw-r--r--drivers/staging/unisys/Documentation/ABI/sysfs-platform-visorchipset101
-rw-r--r--drivers/staging/unisys/Kconfig2
-rw-r--r--drivers/staging/unisys/channels/Kconfig2
-rw-r--r--drivers/staging/unisys/channels/Makefile2
-rw-r--r--drivers/staging/unisys/channels/channel.c8
-rw-r--r--drivers/staging/unisys/channels/chanstub.c4
-rw-r--r--drivers/staging/unisys/channels/chanstub.h4
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/channel.h158
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/controlframework.h26
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/controlvmchannel.h250
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/diagchannel.h62
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/iochannel.h160
-rw-r--r--drivers/staging/unisys/common-spar/include/channels/vbuschannel.h50
-rw-r--r--drivers/staging/unisys/common-spar/include/vbusdeviceinfo.h42
-rw-r--r--drivers/staging/unisys/common-spar/include/vmcallinterface.h26
-rw-r--r--drivers/staging/unisys/include/commontypes.h85
-rw-r--r--drivers/staging/unisys/include/guestlinuxdebug.h20
-rw-r--r--drivers/staging/unisys/include/uisqueue.h98
-rw-r--r--drivers/staging/unisys/include/uisutils.h94
-rw-r--r--drivers/staging/unisys/include/vbushelper.h8
-rw-r--r--drivers/staging/unisys/uislib/Makefile3
-rw-r--r--drivers/staging/unisys/uislib/uislib.c86
-rw-r--r--drivers/staging/unisys/uislib/uisqueue.c10
-rw-r--r--drivers/staging/unisys/uislib/uisutils.c15
-rw-r--r--drivers/staging/unisys/virthba/Makefile3
-rw-r--r--drivers/staging/unisys/virthba/virthba.c222
-rw-r--r--drivers/staging/unisys/virtpci/Makefile3
-rw-r--r--drivers/staging/unisys/virtpci/virtpci.c353
-rw-r--r--drivers/staging/unisys/virtpci/virtpci.h6
-rw-r--r--drivers/staging/unisys/visorchannel/Makefile2
-rw-r--r--drivers/staging/unisys/visorchannel/visorchannel.h16
-rw-r--r--drivers/staging/unisys/visorchannel/visorchannel_funcs.c34
-rw-r--r--drivers/staging/unisys/visorchipset/Makefile5
-rw-r--r--drivers/staging/unisys/visorchipset/controlvm.h27
-rw-r--r--drivers/staging/unisys/visorchipset/controlvm_direct.c62
-rw-r--r--drivers/staging/unisys/visorchipset/file.c4
-rw-r--r--drivers/staging/unisys/visorchipset/parser.c6
-rw-r--r--drivers/staging/unisys/visorchipset/parser.h4
-rw-r--r--drivers/staging/unisys/visorchipset/visorchipset.h90
-rw-r--r--drivers/staging/unisys/visorchipset/visorchipset_main.c1146
-rw-r--r--drivers/staging/unisys/visorutil/Makefile1
-rw-r--r--drivers/staging/unisys/visorutil/memregion_direct.c2
-rw-r--r--drivers/staging/usbip/stub_main.c10
-rw-r--r--drivers/staging/usbip/stub_rx.c1
-rw-r--r--drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c7
-rw-r--r--drivers/staging/usbip/vhci_hcd.c3
-rw-r--r--drivers/staging/usbip/vhci_rx.c2
-rw-r--r--drivers/staging/vme/devices/vme_pio2_core.c12
-rw-r--r--drivers/staging/vme/devices/vme_pio2_gpio.c6
-rw-r--r--drivers/staging/vme/devices/vme_user.c4
-rw-r--r--drivers/staging/vt6655/80211hdr.h7
-rw-r--r--drivers/staging/vt6655/80211mgr.c37
-rw-r--r--drivers/staging/vt6655/80211mgr.h38
-rw-r--r--drivers/staging/vt6655/IEEE11h.c175
-rw-r--r--drivers/staging/vt6655/IEEE11h.h10
-rw-r--r--drivers/staging/vt6655/aes_ccmp.c1
-rw-r--r--drivers/staging/vt6655/aes_ccmp.h9
-rw-r--r--drivers/staging/vt6655/baseband.c350
-rw-r--r--drivers/staging/vt6655/baseband.h36
-rw-r--r--drivers/staging/vt6655/bssdb.c72
-rw-r--r--drivers/staging/vt6655/bssdb.h28
-rw-r--r--drivers/staging/vt6655/card.c40
-rw-r--r--drivers/staging/vt6655/card.h18
-rw-r--r--drivers/staging/vt6655/channel.h4
-rw-r--r--drivers/staging/vt6655/country.h1
-rw-r--r--drivers/staging/vt6655/datarate.c37
-rw-r--r--drivers/staging/vt6655/datarate.h28
-rw-r--r--drivers/staging/vt6655/desc.h185
-rw-r--r--drivers/staging/vt6655/device.h78
-rw-r--r--drivers/staging/vt6655/device_cfg.h5
-rw-r--r--drivers/staging/vt6655/device_main.c812
-rw-r--r--drivers/staging/vt6655/dpc.c48
-rw-r--r--drivers/staging/vt6655/dpc.h10
-rw-r--r--drivers/staging/vt6655/hostap.c48
-rw-r--r--drivers/staging/vt6655/hostap.h8
-rw-r--r--drivers/staging/vt6655/iocmd.h25
-rw-r--r--drivers/staging/vt6655/ioctl.c8
-rw-r--r--drivers/staging/vt6655/ioctl.h8
-rw-r--r--drivers/staging/vt6655/iowpa.h10
-rw-r--r--drivers/staging/vt6655/iwctl.c134
-rw-r--r--drivers/staging/vt6655/iwctl.h18
-rw-r--r--drivers/staging/vt6655/key.c33
-rw-r--r--drivers/staging/vt6655/key.h25
-rw-r--r--drivers/staging/vt6655/mac.c104
-rw-r--r--drivers/staging/vt6655/mac.h107
-rw-r--r--drivers/staging/vt6655/mib.h45
-rw-r--r--drivers/staging/vt6655/michael.h6
-rw-r--r--drivers/staging/vt6655/power.c9
-rw-r--r--drivers/staging/vt6655/power.h9
-rw-r--r--drivers/staging/vt6655/rc4.c1
-rw-r--r--drivers/staging/vt6655/rf.c20
-rw-r--r--drivers/staging/vt6655/rf.h8
-rw-r--r--drivers/staging/vt6655/rxtx.c26
-rw-r--r--drivers/staging/vt6655/srom.c24
-rw-r--r--drivers/staging/vt6655/srom.h24
-rw-r--r--drivers/staging/vt6655/tcrc.c2
-rw-r--r--drivers/staging/vt6655/upc.h52
-rw-r--r--drivers/staging/vt6655/vntwifi.c19
-rw-r--r--drivers/staging/vt6655/wcmd.c39
-rw-r--r--drivers/staging/vt6655/wcmd.h15
-rw-r--r--drivers/staging/vt6655/wmgr.c89
-rw-r--r--drivers/staging/vt6655/wmgr.h12
-rw-r--r--drivers/staging/vt6655/wpa.c10
-rw-r--r--drivers/staging/vt6655/wpactl.c8
-rw-r--r--drivers/staging/vt6656/80211hdr.h324
-rw-r--r--drivers/staging/vt6656/80211mgr.c861
-rw-r--r--drivers/staging/vt6656/80211mgr.h808
-rw-r--r--drivers/staging/vt6656/Kconfig4
-rw-r--r--drivers/staging/vt6656/Makefile13
-rw-r--r--drivers/staging/vt6656/baseband.c1034
-rw-r--r--drivers/staging/vt6656/baseband.h19
-rw-r--r--drivers/staging/vt6656/bssdb.c1466
-rw-r--r--drivers/staging/vt6656/bssdb.h276
-rw-r--r--drivers/staging/vt6656/card.c384
-rw-r--r--drivers/staging/vt6656/card.h48
-rw-r--r--drivers/staging/vt6656/channel.c549
-rw-r--r--drivers/staging/vt6656/channel.h9
-rw-r--r--drivers/staging/vt6656/country.h162
-rw-r--r--drivers/staging/vt6656/datarate.c364
-rw-r--r--drivers/staging/vt6656/datarate.h76
-rw-r--r--drivers/staging/vt6656/desc.h2
-rw-r--r--drivers/staging/vt6656/device.h544
-rw-r--r--drivers/staging/vt6656/dpc.c999
-rw-r--r--drivers/staging/vt6656/dpc.h11
-rw-r--r--drivers/staging/vt6656/firmware.c78
-rw-r--r--drivers/staging/vt6656/firmware.h6
-rw-r--r--drivers/staging/vt6656/int.c213
-rw-r--r--drivers/staging/vt6656/int.h4
-rw-r--r--drivers/staging/vt6656/iocmd.h38
-rw-r--r--drivers/staging/vt6656/iowpa.h75
-rw-r--r--drivers/staging/vt6656/iwctl.c1802
-rw-r--r--drivers/staging/vt6656/iwctl.h138
-rw-r--r--drivers/staging/vt6656/key.c789
-rw-r--r--drivers/staging/vt6656/key.h79
-rw-r--r--drivers/staging/vt6656/mac.c37
-rw-r--r--drivers/staging/vt6656/mac.h708
-rw-r--r--drivers/staging/vt6656/main_usb.c1608
-rw-r--r--drivers/staging/vt6656/michael.c167
-rw-r--r--drivers/staging/vt6656/michael.h52
-rw-r--r--drivers/staging/vt6656/power.c254
-rw-r--r--drivers/staging/vt6656/power.h17
-rw-r--r--drivers/staging/vt6656/rc4.c87
-rw-r--r--drivers/staging/vt6656/rc4.h46
-rw-r--r--drivers/staging/vt6656/rf.c1303
-rw-r--r--drivers/staging/vt6656/rf.h11
-rw-r--r--drivers/staging/vt6656/rxtx.c2408
-rw-r--r--drivers/staging/vt6656/rxtx.h36
-rw-r--r--drivers/staging/vt6656/tether.c60
-rw-r--r--drivers/staging/vt6656/tether.h101
-rw-r--r--drivers/staging/vt6656/tkip.c246
-rw-r--r--drivers/staging/vt6656/tkip.h45
-rw-r--r--drivers/staging/vt6656/tmacro.h52
-rw-r--r--drivers/staging/vt6656/usbpipe.c321
-rw-r--r--drivers/staging/vt6656/usbpipe.h7
-rw-r--r--drivers/staging/vt6656/vntconfiguration.dat6
-rw-r--r--drivers/staging/vt6656/wcmd.c1066
-rw-r--r--drivers/staging/vt6656/wcmd.h91
-rw-r--r--drivers/staging/vt6656/wctl.c244
-rw-r--r--drivers/staging/vt6656/wctl.h94
-rw-r--r--drivers/staging/vt6656/wmgr.c4362
-rw-r--r--drivers/staging/vt6656/wmgr.h397
-rw-r--r--drivers/staging/vt6656/wpa.c314
-rw-r--r--drivers/staging/vt6656/wpa.h72
-rw-r--r--drivers/staging/vt6656/wpa2.c235
-rw-r--r--drivers/staging/vt6656/wpa2.h53
-rw-r--r--drivers/staging/vt6656/wpactl.c247
-rw-r--r--drivers/staging/vt6656/wpactl.h47
-rw-r--r--drivers/staging/winbond/Kconfig11
-rw-r--r--drivers/staging/winbond/Makefile15
-rw-r--r--drivers/staging/winbond/TODO12
-rw-r--r--drivers/staging/winbond/core.h61
-rw-r--r--drivers/staging/winbond/localpara.h311
-rw-r--r--drivers/staging/winbond/mac_structures.h71
-rw-r--r--drivers/staging/winbond/mds.c650
-rw-r--r--drivers/staging/winbond/mds_f.h22
-rw-r--r--drivers/staging/winbond/mds_s.h130
-rw-r--r--drivers/staging/winbond/mto.c167
-rw-r--r--drivers/staging/winbond/mto.h134
-rw-r--r--drivers/staging/winbond/phy_calibration.c1317
-rw-r--r--drivers/staging/winbond/phy_calibration.h85
-rw-r--r--drivers/staging/winbond/reg.c2328
-rw-r--r--drivers/staging/winbond/sme_api.h191
-rw-r--r--drivers/staging/winbond/wb35reg.c806
-rw-r--r--drivers/staging/winbond/wb35reg_f.h65
-rw-r--r--drivers/staging/winbond/wb35reg_s.h240
-rw-r--r--drivers/staging/winbond/wb35rx.c358
-rw-r--r--drivers/staging/winbond/wb35rx_f.h15
-rw-r--r--drivers/staging/winbond/wb35rx_s.h44
-rw-r--r--drivers/staging/winbond/wb35tx.c290
-rw-r--r--drivers/staging/winbond/wb35tx_f.h22
-rw-r--r--drivers/staging/winbond/wb35tx_s.h39
-rw-r--r--drivers/staging/winbond/wbhal.h513
-rw-r--r--drivers/staging/winbond/wbusb.c853
-rw-r--r--drivers/staging/wlags49_h2/Kconfig11
-rw-r--r--drivers/staging/wlags49_h2/Makefile53
-rw-r--r--drivers/staging/wlags49_h2/README.ubuntu180
-rw-r--r--drivers/staging/wlags49_h2/README.wlags49641
-rw-r--r--drivers/staging/wlags49_h2/TODO33
-rw-r--r--drivers/staging/wlags49_h2/WARNING.txt3
-rw-r--r--drivers/staging/wlags49_h2/ap_h2.c3337
-rw-r--r--drivers/staging/wlags49_h2/ap_h25.c4094
-rw-r--r--drivers/staging/wlags49_h2/debug.h199
-rw-r--r--drivers/staging/wlags49_h2/dhf.c380
-rw-r--r--drivers/staging/wlags49_h2/dhf.h225
-rw-r--r--drivers/staging/wlags49_h2/dhfcfg.h158
-rw-r--r--drivers/staging/wlags49_h2/hcf.c4748
-rw-r--r--drivers/staging/wlags49_h2/hcf.h394
-rw-r--r--drivers/staging/wlags49_h2/hcfcfg.h785
-rw-r--r--drivers/staging/wlags49_h2/hcfdef.h752
-rw-r--r--drivers/staging/wlags49_h2/man/wlags49.4734
-rw-r--r--drivers/staging/wlags49_h2/mdd.h1155
-rw-r--r--drivers/staging/wlags49_h2/mmd.c250
-rw-r--r--drivers/staging/wlags49_h2/mmd.h77
-rw-r--r--drivers/staging/wlags49_h2/sta_h2.c4480
-rw-r--r--drivers/staging/wlags49_h2/sta_h25.c5255
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.c440
-rw-r--r--drivers/staging/wlags49_h2/wl_cs.h89
-rw-r--r--drivers/staging/wlags49_h2/wl_enc.c217
-rw-r--r--drivers/staging/wlags49_h2/wl_enc.h118
-rw-r--r--drivers/staging/wlags49_h2/wl_if.h221
-rw-r--r--drivers/staging/wlags49_h2/wl_internal.h1040
-rw-r--r--drivers/staging/wlags49_h2/wl_main.c3702
-rw-r--r--drivers/staging/wlags49_h2/wl_main.h138
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.c1951
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.h154
-rw-r--r--drivers/staging/wlags49_h2/wl_priv.c1928
-rw-r--r--drivers/staging/wlags49_h2/wl_priv.h127
-rw-r--r--drivers/staging/wlags49_h2/wl_profile.c995
-rw-r--r--drivers/staging/wlags49_h2/wl_profile.h87
-rw-r--r--drivers/staging/wlags49_h2/wl_util.c1367
-rw-r--r--drivers/staging/wlags49_h2/wl_util.h96
-rw-r--r--drivers/staging/wlags49_h2/wl_version.h146
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.c3794
-rw-r--r--drivers/staging/wlags49_h2/wl_wext.h88
-rw-r--r--drivers/staging/wlags49_h25/Kconfig11
-rw-r--r--drivers/staging/wlags49_h25/Makefile52
-rw-r--r--drivers/staging/wlags49_h25/README.txt30
-rw-r--r--drivers/staging/wlags49_h25/TODO33
-rw-r--r--drivers/staging/wlags49_h25/ap_h25.c2
-rw-r--r--drivers/staging/wlags49_h25/debug.h2
-rw-r--r--drivers/staging/wlags49_h25/dhf.c2
-rw-r--r--drivers/staging/wlags49_h25/dhf.h2
-rw-r--r--drivers/staging/wlags49_h25/dhfcfg.h2
-rw-r--r--drivers/staging/wlags49_h25/hcf.c2
-rw-r--r--drivers/staging/wlags49_h25/hcf.h2
-rw-r--r--drivers/staging/wlags49_h25/hcfcfg.h2
-rw-r--r--drivers/staging/wlags49_h25/hcfdef.h2
-rw-r--r--drivers/staging/wlags49_h25/mdd.h2
-rw-r--r--drivers/staging/wlags49_h25/mmd.c2
-rw-r--r--drivers/staging/wlags49_h25/mmd.h2
-rw-r--r--drivers/staging/wlags49_h25/sta_h25.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_cs.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_cs.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_enc.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_enc.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_if.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_internal.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_main.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_main.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_netdev.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_netdev.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_priv.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_priv.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_profile.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_profile.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_util.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_util.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_version.h2
-rw-r--r--drivers/staging/wlags49_h25/wl_wext.c2
-rw-r--r--drivers/staging/wlags49_h25/wl_wext.h2
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c2
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c19
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c1
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c42
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h1
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c2
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c42
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c7
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c7
-rw-r--r--drivers/staging/xillybus/README23
-rw-r--r--drivers/staging/xillybus/xillybus.h48
-rw-r--r--drivers/staging/xillybus/xillybus_core.c541
-rw-r--r--drivers/staging/xillybus/xillybus_of.c72
-rw-r--r--drivers/staging/xillybus/xillybus_pcie.c66
-rw-r--r--drivers/target/loopback/tcm_loop.c2
-rw-r--r--drivers/target/target_core_pscsi.c12
-rw-r--r--drivers/target/target_core_tpg.c4
-rw-r--r--drivers/thermal/Kconfig7
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/cpu_cooling.c2
-rw-r--r--drivers/thermal/int3403_thermal.c67
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c11
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h3
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.c89
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.h7
-rw-r--r--drivers/thermal/st/Kconfig12
-rw-r--r--drivers/thermal/st/Makefile3
-rw-r--r--drivers/thermal/st/st_thermal.c313
-rw-r--r--drivers/thermal/st/st_thermal.h104
-rw-r--r--drivers/thermal/st/st_thermal_memmap.c209
-rw-r--r--drivers/thermal/st/st_thermal_syscfg.c179
-rw-r--r--drivers/thunderbolt/Kconfig13
-rw-r--r--drivers/thunderbolt/Makefile3
-rw-r--r--drivers/thunderbolt/cap.c116
-rw-r--r--drivers/thunderbolt/ctl.c731
-rw-r--r--drivers/thunderbolt/ctl.h75
-rw-r--r--drivers/thunderbolt/eeprom.c449
-rw-r--r--drivers/thunderbolt/nhi.c675
-rw-r--r--drivers/thunderbolt/nhi.h114
-rw-r--r--drivers/thunderbolt/nhi_regs.h101
-rw-r--r--drivers/thunderbolt/path.c215
-rw-r--r--drivers/thunderbolt/switch.c507
-rw-r--r--drivers/thunderbolt/tb.c436
-rw-r--r--drivers/thunderbolt/tb.h271
-rw-r--r--drivers/thunderbolt/tb_regs.h213
-rw-r--r--drivers/thunderbolt/tunnel_pci.c232
-rw-r--r--drivers/thunderbolt/tunnel_pci.h30
-rw-r--r--drivers/tty/cyclades.c2
-rw-r--r--drivers/tty/ehv_bytechan.c43
-rw-r--r--drivers/tty/hvc/hvc_opal.c15
-rw-r--r--drivers/tty/hvc/hvc_vio.c29
-rw-r--r--drivers/tty/ipwireless/tty.c5
-rw-r--r--drivers/tty/n_gsm.c22
-rw-r--r--drivers/tty/pty.c21
-rw-r--r--drivers/tty/serial/21285.c5
-rw-r--r--drivers/tty/serial/8250/8250.h2
-rw-r--r--drivers/tty/serial/8250/8250_core.c230
-rw-r--r--drivers/tty/serial/8250/8250_dw.c190
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c3
-rw-r--r--drivers/tty/serial/8250/8250_pci.c6
-rw-r--r--drivers/tty/serial/Kconfig4
-rw-r--r--drivers/tty/serial/altera_jtaguart.c19
-rw-r--r--drivers/tty/serial/altera_uart.c13
-rw-r--r--drivers/tty/serial/amba-pl010.c48
-rw-r--r--drivers/tty/serial/amba-pl011.c30
-rw-r--r--drivers/tty/serial/apbuart.c6
-rw-r--r--drivers/tty/serial/ar933x_uart.c5
-rw-r--r--drivers/tty/serial/arc_uart.c337
-rw-r--r--drivers/tty/serial/atmel_serial.c8
-rw-r--r--drivers/tty/serial/bfin_sport_uart.c17
-rw-r--r--drivers/tty/serial/bfin_uart.c22
-rw-r--r--drivers/tty/serial/clps711x.c1
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c9
-rw-r--r--drivers/tty/serial/crisv10.c15
-rw-r--r--drivers/tty/serial/dz.c6
-rw-r--r--drivers/tty/serial/efm32-uart.c14
-rw-r--r--drivers/tty/serial/fsl_lpuart.c689
-rw-r--r--drivers/tty/serial/icom.c6
-rw-r--r--drivers/tty/serial/ioc3_serial.c1
-rw-r--r--drivers/tty/serial/ioc4_serial.c1
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c6
-rw-r--r--drivers/tty/serial/kgdb_nmi.c36
-rw-r--r--drivers/tty/serial/lantiq.c8
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c7
-rw-r--r--drivers/tty/serial/max310x.c1
-rw-r--r--drivers/tty/serial/mcf.c11
-rw-r--r--drivers/tty/serial/men_z135_uart.c6
-rw-r--r--drivers/tty/serial/mpsc.c5
-rw-r--r--drivers/tty/serial/mrst_max3110.c5
-rw-r--r--drivers/tty/serial/msm_serial.c32
-rw-r--r--drivers/tty/serial/msm_serial.h4
-rw-r--r--drivers/tty/serial/mux.c11
-rw-r--r--drivers/tty/serial/mxs-auart.c6
-rw-r--r--drivers/tty/serial/nwpserial.c6
-rw-r--r--drivers/tty/serial/pch_uart.c9
-rw-r--r--drivers/tty/serial/pmac_zilog.c9
-rw-r--r--drivers/tty/serial/pxa.c2
-rw-r--r--drivers/tty/serial/samsung.c48
-rw-r--r--drivers/tty/serial/sc16is7xx.c10
-rw-r--r--drivers/tty/serial/sccnxp.c6
-rw-r--r--drivers/tty/serial/serial-tegra.c4
-rw-r--r--drivers/tty/serial/serial_core.c62
-rw-r--r--drivers/tty/serial/serial_txx9.c7
-rw-r--r--drivers/tty/serial/sh-sci.c94
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c3
-rw-r--r--drivers/tty/serial/sirfsoc_uart.h2
-rw-r--r--drivers/tty/serial/sn_console.c10
-rw-r--r--drivers/tty/serial/st-asc.c20
-rw-r--r--drivers/tty/serial/sunhv.c6
-rw-r--r--drivers/tty/serial/sunsab.c16
-rw-r--r--drivers/tty/serial/tilegx.c10
-rw-r--r--drivers/tty/serial/timbuart.c6
-rw-r--r--drivers/tty/serial/uartlite.c6
-rw-r--r--drivers/tty/serial/ucc_uart.c11
-rw-r--r--drivers/tty/serial/xilinx_uartps.c6
-rw-r--r--drivers/tty/synclink.c10
-rw-r--r--drivers/tty/synclink_gt.c15
-rw-r--r--drivers/tty/synclinkmp.c11
-rw-r--r--drivers/tty/sysrq.c2
-rw-r--r--drivers/tty/tty_io.c39
-rw-r--r--drivers/tty/tty_port.c43
-rw-r--r--drivers/uio/uio_pruss.c37
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c3
-rw-r--r--drivers/usb/chipidea/debug.c4
-rw-r--r--drivers/usb/class/usbtmc.c2
-rw-r--r--drivers/usb/core/config.c11
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/driver.c7
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c94
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/port.c21
-rw-r--r--drivers/usb/core/quirks.c7
-rw-r--r--drivers/usb/core/urb.c1
-rw-r--r--drivers/usb/core/usb.c1
-rw-r--r--drivers/usb/dwc2/gadget.c12
-rw-r--r--drivers/usb/dwc3/Kconfig7
-rw-r--r--drivers/usb/dwc3/core.c51
-rw-r--r--drivers/usb/dwc3/core.h13
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c172
-rw-r--r--drivers/usb/dwc3/gadget.c7
-rw-r--r--drivers/usb/dwc3/host.c14
-rw-r--r--drivers/usb/gadget/Kconfig824
-rw-r--r--drivers/usb/gadget/Makefile101
-rw-r--r--drivers/usb/gadget/composite.c1
-rw-r--r--drivers/usb/gadget/configfs.c4
-rw-r--r--drivers/usb/gadget/function/Makefile34
-rw-r--r--drivers/usb/gadget/function/f_acm.c (renamed from drivers/usb/gadget/f_acm.c)0
-rw-r--r--drivers/usb/gadget/function/f_ecm.c (renamed from drivers/usb/gadget/f_ecm.c)0
-rw-r--r--drivers/usb/gadget/function/f_eem.c (renamed from drivers/usb/gadget/f_eem.c)22
-rw-r--r--drivers/usb/gadget/function/f_fs.c (renamed from drivers/usb/gadget/f_fs.c)352
-rw-r--r--drivers/usb/gadget/function/f_hid.c (renamed from drivers/usb/gadget/f_hid.c)0
-rw-r--r--drivers/usb/gadget/function/f_loopback.c (renamed from drivers/usb/gadget/f_loopback.c)0
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c (renamed from drivers/usb/gadget/f_mass_storage.c)0
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.h (renamed from drivers/usb/gadget/f_mass_storage.h)0
-rw-r--r--drivers/usb/gadget/function/f_midi.c (renamed from drivers/usb/gadget/f_midi.c)0
-rw-r--r--drivers/usb/gadget/function/f_ncm.c (renamed from drivers/usb/gadget/f_ncm.c)480
-rw-r--r--drivers/usb/gadget/function/f_obex.c (renamed from drivers/usb/gadget/f_obex.c)0
-rw-r--r--drivers/usb/gadget/function/f_phonet.c (renamed from drivers/usb/gadget/f_phonet.c)3
-rw-r--r--drivers/usb/gadget/function/f_rndis.c (renamed from drivers/usb/gadget/f_rndis.c)4
-rw-r--r--drivers/usb/gadget/function/f_serial.c (renamed from drivers/usb/gadget/f_serial.c)0
-rw-r--r--drivers/usb/gadget/function/f_sourcesink.c (renamed from drivers/usb/gadget/f_sourcesink.c)0
-rw-r--r--drivers/usb/gadget/function/f_subset.c (renamed from drivers/usb/gadget/f_subset.c)0
-rw-r--r--drivers/usb/gadget/function/f_uac1.c (renamed from drivers/usb/gadget/f_uac1.c)0
-rw-r--r--drivers/usb/gadget/function/f_uac2.c (renamed from drivers/usb/gadget/f_uac2.c)24
-rw-r--r--drivers/usb/gadget/function/f_uvc.c (renamed from drivers/usb/gadget/f_uvc.c)0
-rw-r--r--drivers/usb/gadget/function/f_uvc.h (renamed from drivers/usb/gadget/f_uvc.h)0
-rw-r--r--drivers/usb/gadget/function/g_zero.h (renamed from drivers/usb/gadget/g_zero.h)0
-rw-r--r--drivers/usb/gadget/function/ndis.h (renamed from drivers/usb/gadget/ndis.h)0
-rw-r--r--drivers/usb/gadget/function/rndis.c (renamed from drivers/usb/gadget/rndis.c)0
-rw-r--r--drivers/usb/gadget/function/rndis.h (renamed from drivers/usb/gadget/rndis.h)0
-rw-r--r--drivers/usb/gadget/function/storage_common.c (renamed from drivers/usb/gadget/storage_common.c)0
-rw-r--r--drivers/usb/gadget/function/storage_common.h (renamed from drivers/usb/gadget/storage_common.h)0
-rw-r--r--drivers/usb/gadget/function/u_ecm.h (renamed from drivers/usb/gadget/u_ecm.h)0
-rw-r--r--drivers/usb/gadget/function/u_eem.h (renamed from drivers/usb/gadget/u_eem.h)0
-rw-r--r--drivers/usb/gadget/function/u_ether.c (renamed from drivers/usb/gadget/u_ether.c)19
-rw-r--r--drivers/usb/gadget/function/u_ether.h (renamed from drivers/usb/gadget/u_ether.h)2
-rw-r--r--drivers/usb/gadget/function/u_ether_configfs.h (renamed from drivers/usb/gadget/u_ether_configfs.h)0
-rw-r--r--drivers/usb/gadget/function/u_fs.h (renamed from drivers/usb/gadget/u_fs.h)7
-rw-r--r--drivers/usb/gadget/function/u_gether.h (renamed from drivers/usb/gadget/u_gether.h)0
-rw-r--r--drivers/usb/gadget/function/u_ncm.h (renamed from drivers/usb/gadget/u_ncm.h)0
-rw-r--r--drivers/usb/gadget/function/u_phonet.h (renamed from drivers/usb/gadget/u_phonet.h)0
-rw-r--r--drivers/usb/gadget/function/u_rndis.h (renamed from drivers/usb/gadget/u_rndis.h)0
-rw-r--r--drivers/usb/gadget/function/u_serial.c (renamed from drivers/usb/gadget/u_serial.c)0
-rw-r--r--drivers/usb/gadget/function/u_serial.h (renamed from drivers/usb/gadget/u_serial.h)0
-rw-r--r--drivers/usb/gadget/function/u_uac1.c (renamed from drivers/usb/gadget/u_uac1.c)0
-rw-r--r--drivers/usb/gadget/function/u_uac1.h (renamed from drivers/usb/gadget/u_uac1.h)0
-rw-r--r--drivers/usb/gadget/function/uvc.h (renamed from drivers/usb/gadget/uvc.h)0
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c (renamed from drivers/usb/gadget/uvc_queue.c)0
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h (renamed from drivers/usb/gadget/uvc_queue.h)0
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c (renamed from drivers/usb/gadget/uvc_v4l2.c)0
-rw-r--r--drivers/usb/gadget/function/uvc_video.c (renamed from drivers/usb/gadget/uvc_video.c)0
-rw-r--r--drivers/usb/gadget/legacy/Kconfig475
-rw-r--r--drivers/usb/gadget/legacy/Makefile44
-rw-r--r--drivers/usb/gadget/legacy/acm_ms.c (renamed from drivers/usb/gadget/acm_ms.c)14
-rw-r--r--drivers/usb/gadget/legacy/audio.c (renamed from drivers/usb/gadget/audio.c)12
-rw-r--r--drivers/usb/gadget/legacy/cdc2.c (renamed from drivers/usb/gadget/cdc2.c)14
-rw-r--r--drivers/usb/gadget/legacy/dbgp.c (renamed from drivers/usb/gadget/dbgp.c)0
-rw-r--r--drivers/usb/gadget/legacy/ether.c (renamed from drivers/usb/gadget/ether.c)14
-rw-r--r--drivers/usb/gadget/legacy/g_ffs.c (renamed from drivers/usb/gadget/g_ffs.c)2
-rw-r--r--drivers/usb/gadget/legacy/gmidi.c (renamed from drivers/usb/gadget/gmidi.c)13
-rw-r--r--drivers/usb/gadget/legacy/hid.c (renamed from drivers/usb/gadget/hid.c)0
-rw-r--r--drivers/usb/gadget/legacy/inode.c (renamed from drivers/usb/gadget/inode.c)0
-rw-r--r--drivers/usb/gadget/legacy/mass_storage.c (renamed from drivers/usb/gadget/mass_storage.c)0
-rw-r--r--drivers/usb/gadget/legacy/multi.c (renamed from drivers/usb/gadget/multi.c)13
-rw-r--r--drivers/usb/gadget/legacy/ncm.c (renamed from drivers/usb/gadget/ncm.c)14
-rw-r--r--drivers/usb/gadget/legacy/nokia.c (renamed from drivers/usb/gadget/nokia.c)12
-rw-r--r--drivers/usb/gadget/legacy/printer.c (renamed from drivers/usb/gadget/printer.c)0
-rw-r--r--drivers/usb/gadget/legacy/serial.c (renamed from drivers/usb/gadget/serial.c)0
-rw-r--r--drivers/usb/gadget/legacy/tcm_usb_gadget.c (renamed from drivers/usb/gadget/tcm_usb_gadget.c)0
-rw-r--r--drivers/usb/gadget/legacy/tcm_usb_gadget.h (renamed from drivers/usb/gadget/tcm_usb_gadget.h)0
-rw-r--r--drivers/usb/gadget/legacy/webcam.c (renamed from drivers/usb/gadget/webcam.c)15
-rw-r--r--drivers/usb/gadget/legacy/zero.c (renamed from drivers/usb/gadget/zero.c)14
-rw-r--r--drivers/usb/gadget/net2280.c2905
-rw-r--r--drivers/usb/gadget/net2280.h308
-rw-r--r--drivers/usb/gadget/u_os_desc.h59
-rw-r--r--drivers/usb/gadget/udc/Kconfig385
-rw-r--r--drivers/usb/gadget/udc/Makefile31
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.c (renamed from drivers/usb/gadget/amd5536udc.c)0
-rw-r--r--drivers/usb/gadget/udc/amd5536udc.h (renamed from drivers/usb/gadget/amd5536udc.h)0
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c (renamed from drivers/usb/gadget/at91_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/at91_udc.h (renamed from drivers/usb/gadget/at91_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c (renamed from drivers/usb/gadget/atmel_usba_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.h (renamed from drivers/usb/gadget/atmel_usba_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c (renamed from drivers/usb/gadget/bcm63xx_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c (renamed from drivers/usb/gadget/dummy_hcd.c)0
-rw-r--r--drivers/usb/gadget/udc/fotg210-udc.c (renamed from drivers/usb/gadget/fotg210-udc.c)0
-rw-r--r--drivers/usb/gadget/udc/fotg210.h (renamed from drivers/usb/gadget/fotg210.h)0
-rw-r--r--drivers/usb/gadget/udc/fsl_mxc_udc.c (renamed from drivers/usb/gadget/fsl_mxc_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c (renamed from drivers/usb/gadget/fsl_qe_udc.c)19
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.h (renamed from drivers/usb/gadget/fsl_qe_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c (renamed from drivers/usb/gadget/fsl_udc_core.c)19
-rw-r--r--drivers/usb/gadget/udc/fsl_usb2_udc.h (renamed from drivers/usb/gadget/fsl_usb2_udc.h)3
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c (renamed from drivers/usb/gadget/fusb300_udc.c)4
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.h (renamed from drivers/usb/gadget/fusb300_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/gadget_chips.h (renamed from drivers/usb/gadget/gadget_chips.h)0
-rw-r--r--drivers/usb/gadget/udc/goku_udc.c (renamed from drivers/usb/gadget/goku_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/goku_udc.h (renamed from drivers/usb/gadget/goku_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c (renamed from drivers/usb/gadget/gr_udc.c)2
-rw-r--r--drivers/usb/gadget/udc/gr_udc.h (renamed from drivers/usb/gadget/gr_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c (renamed from drivers/usb/gadget/lpc32xx_udc.c)7
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c (renamed from drivers/usb/gadget/m66592-udc.c)4
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.h (renamed from drivers/usb/gadget/m66592-udc.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_u3d.h (renamed from drivers/usb/gadget/mv_u3d.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c (renamed from drivers/usb/gadget/mv_u3d_core.c)0
-rw-r--r--drivers/usb/gadget/udc/mv_udc.h (renamed from drivers/usb/gadget/mv_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c (renamed from drivers/usb/gadget/mv_udc_core.c)4
-rw-r--r--drivers/usb/gadget/udc/net2272.c (renamed from drivers/usb/gadget/net2272.c)2
-rw-r--r--drivers/usb/gadget/udc/net2272.h (renamed from drivers/usb/gadget/net2272.h)0
-rw-r--r--drivers/usb/gadget/udc/net2280.c3827
-rw-r--r--drivers/usb/gadget/udc/net2280.h403
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c (renamed from drivers/usb/gadget/omap_udc.c)5
-rw-r--r--drivers/usb/gadget/udc/omap_udc.h (renamed from drivers/usb/gadget/omap_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/pch_udc.c (renamed from drivers/usb/gadget/pch_udc.c)0
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c (renamed from drivers/usb/gadget/pxa25x_udc.c)75
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.h (renamed from drivers/usb/gadget/pxa25x_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c (renamed from drivers/usb/gadget/pxa27x_udc.c)6
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.h (renamed from drivers/usb/gadget/pxa27x_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c (renamed from drivers/usb/gadget/r8a66597-udc.c)92
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.h (renamed from drivers/usb/gadget/r8a66597-udc.h)0
-rw-r--r--drivers/usb/gadget/udc/s3c-hsudc.c (renamed from drivers/usb/gadget/s3c-hsudc.c)0
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c (renamed from drivers/usb/gadget/s3c2410_udc.c)8
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.h (renamed from drivers/usb/gadget/s3c2410_udc.h)0
-rw-r--r--drivers/usb/gadget/udc/udc-core.c (renamed from drivers/usb/gadget/udc-core.c)0
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile3
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-mem.c2
-rw-r--r--drivers/usb/host/ehci-msm.c2
-rw-r--r--drivers/usb/host/ehci-pci.c25
-rw-r--r--drivers/usb/host/ehci-spear.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c67
-rw-r--r--drivers/usb/host/fhci-dbg.c8
-rw-r--r--drivers/usb/host/fotg210-hcd.c48
-rw-r--r--drivers/usb/host/max3421-hcd.c48
-rw-r--r--drivers/usb/host/ohci-dbg.c9
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c381
-rw-r--r--drivers/usb/host/ohci-hub.c11
-rw-r--r--drivers/usb/host/ohci-mem.c1
-rw-r--r--drivers/usb/host/ohci-q.c262
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci.h23
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c48
-rw-r--r--drivers/usb/host/uhci-grlib.c31
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/uhci-platform.c22
-rw-r--r--drivers/usb/host/xhci-pci.c8
-rw-r--r--drivers/usb/host/xhci-plat.c52
-rw-r--r--drivers/usb/host/xhci-rcar.c148
-rw-r--r--drivers/usb/host/xhci-rcar.h27
-rw-r--r--drivers/usb/host/xhci-ring.c4
-rw-r--r--drivers/usb/host/xhci.c160
-rw-r--r--drivers/usb/host/xhci.h2
-rw-r--r--drivers/usb/misc/Kconfig7
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/lvstest.c460
-rw-r--r--drivers/usb/misc/usb3503.c37
-rw-r--r--drivers/usb/musb/blackfin.c20
-rw-r--r--drivers/usb/musb/davinci.c20
-rw-r--r--drivers/usb/musb/jz4740.c3
-rw-r--r--drivers/usb/musb/musb_core.c41
-rw-r--r--drivers/usb/musb/musb_core.h12
-rw-r--r--drivers/usb/musb/musb_cppi41.c70
-rw-r--r--drivers/usb/musb/musb_dma.h1
-rw-r--r--drivers/usb/musb/musb_dsps.c104
-rw-r--r--drivers/usb/musb/musb_host.c19
-rw-r--r--drivers/usb/musb/musb_regs.h7
-rw-r--r--drivers/usb/musb/tusb6010.c16
-rw-r--r--drivers/usb/musb/ux500.c28
-rw-r--r--drivers/usb/phy/phy-am335x.c12
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c45
-rw-r--r--drivers/usb/phy/phy-msm-usb.c12
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c11
-rw-r--r--drivers/usb/phy/phy.c2
-rw-r--r--drivers/usb/renesas_usbhs/Makefile2
-rw-r--r--drivers/usb/renesas_usbhs/common.c66
-rw-r--r--drivers/usb/renesas_usbhs/common.h2
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c2
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c11
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h1
-rw-r--r--drivers/usb/renesas_usbhs/rcar2.c77
-rw-r--r--drivers/usb/renesas_usbhs/rcar2.h4
-rw-r--r--drivers/usb/serial/cp210x.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c84
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h13
-rw-r--r--drivers/usb/serial/kl5kusb105.c30
-rw-r--r--drivers/usb/serial/mos7840.c5
-rw-r--r--drivers/usb/storage/Kconfig6
-rw-r--r--drivers/usb/storage/ene_ub6250.c4
-rw-r--r--drivers/usb/storage/sddr09.c4
-rw-r--r--drivers/usb/storage/uas-detect.h40
-rw-r--r--drivers/usb/storage/uas.c2
-rw-r--r--drivers/usb/storage/usb.c10
-rw-r--r--drivers/uwb/whci.c2
-rw-r--r--drivers/vfio/Kconfig6
-rw-r--r--drivers/vfio/Makefile1
-rw-r--r--drivers/vfio/pci/vfio_pci.c167
-rw-r--r--drivers/vfio/pci/vfio_pci_private.h3
-rw-r--r--drivers/vfio/vfio_iommu_spapr_tce.c17
-rw-r--r--drivers/vfio/vfio_spapr_eeh.c100
-rw-r--r--drivers/video/backlight/Kconfig20
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/aat2870_bl.c6
-rw-r--r--drivers/video/backlight/ams369fg06.c6
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c223
-rw-r--r--drivers/video/backlight/backlight.c2
-rw-r--r--drivers/video/backlight/bd6107.c6
-rw-r--r--drivers/video/backlight/gpio_backlight.c6
-rw-r--r--drivers/video/backlight/ipaq_micro_bl.c83
-rw-r--r--drivers/video/backlight/jornada720_lcd.c37
-rw-r--r--drivers/video/backlight/ld9040.c6
-rw-r--r--drivers/video/backlight/lp855x_bl.c6
-rw-r--r--drivers/video/backlight/lp8788_bl.c6
-rw-r--r--drivers/video/backlight/lv5207lp.c6
-rw-r--r--drivers/video/backlight/pandora_bl.c6
-rw-r--r--drivers/video/backlight/pwm_bl.c13
-rw-r--r--drivers/video/backlight/s6e63m0.c6
-rw-r--r--drivers/video/backlight/tps65217_bl.c6
-rw-r--r--drivers/video/fbdev/68328fb.c8
-rw-r--r--drivers/video/fbdev/Kconfig33
-rw-r--r--drivers/video/fbdev/Makefile4
-rw-r--r--drivers/video/fbdev/amba-clcd-versatile.c (renamed from arch/arm/plat-versatile/clcd.c)2
-rw-r--r--drivers/video/fbdev/amba-clcd.c263
-rw-r--r--drivers/video/fbdev/atmel_lcdfb.c3
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c6
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c6
-rw-r--r--drivers/video/fbdev/aty/radeon_backlight.c6
-rw-r--r--drivers/video/fbdev/au1100fb.c39
-rw-r--r--drivers/video/fbdev/au1100fb.h1
-rw-r--r--drivers/video/fbdev/au1200fb.c81
-rw-r--r--drivers/video/fbdev/clps711x-fb.c397
-rw-r--r--drivers/video/fbdev/da8xx-fb.c9
-rw-r--r--drivers/video/fbdev/efifb.c39
-rw-r--r--drivers/video/fbdev/exynos/s6e8ax0.c6
-rw-r--r--drivers/video/fbdev/hyperv_fb.c64
-rw-r--r--drivers/video/fbdev/i740fb.c2
-rw-r--r--drivers/video/fbdev/mbx/mbxfb.c4
-rw-r--r--drivers/video/fbdev/msm/mddi_client_dummy.c19
-rw-r--r--drivers/video/fbdev/nvidia/nv_backlight.c6
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-hdmi.c19
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c20
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c5
-rw-r--r--drivers/video/fbdev/omap2/dss/Kconfig1
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c22
-rw-r--r--drivers/video/fbdev/omap2/dss/dsi.c9
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h107
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c53
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.c164
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.h1
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5.c53
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5_core.c124
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_common.c316
-rw-r--r--drivers/video/fbdev/riva/fbdev.c6
-rw-r--r--drivers/video/fbdev/s3c-fb.c65
-rw-r--r--drivers/video/fbdev/s3c2410fb.c12
-rw-r--r--drivers/video/fbdev/sis/init.c2
-rw-r--r--drivers/video/fbdev/sis/sis_main.c4
-rw-r--r--drivers/virtio/virtio_pci.c2
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.c6
-rw-r--r--drivers/vme/bridges/vme_ca91cx42.h1
-rw-r--r--drivers/vme/bridges/vme_tsi148.c6
-rw-r--r--drivers/w1/masters/ds1wm.c2
-rw-r--r--drivers/w1/masters/ds2482.c2
-rw-r--r--drivers/w1/masters/ds2490.c50
-rw-r--r--drivers/w1/masters/mxc_w1.c64
-rw-r--r--drivers/w1/slaves/Kconfig8
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2406.c168
-rw-r--r--drivers/w1/slaves/w1_ds2760.c3
-rw-r--r--drivers/w1/w1.c10
-rw-r--r--drivers/w1/w1_family.c2
-rw-r--r--drivers/w1/w1_family.h1
-rw-r--r--drivers/w1/w1_int.c19
-rw-r--r--drivers/w1/w1_log.h4
-rw-r--r--drivers/w1/w1_netlink.c3
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/dw_wdt.c3
-rw-r--r--drivers/watchdog/imx2_wdt.c7
-rw-r--r--drivers/watchdog/lantiq_wdt.c5
-rw-r--r--drivers/watchdog/octeon-wdt-main.c62
-rw-r--r--drivers/watchdog/shwdt.c5
-rw-r--r--drivers/watchdog/sunxi_wdt.c29
-rw-r--r--drivers/xen/Kconfig4
-rw-r--r--drivers/xen/Makefile3
-rw-r--r--drivers/xen/efi.c368
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/events/events_fifo.c55
-rw-r--r--drivers/xen/grant-table.c309
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c2
-rw-r--r--drivers/xen/xen-pciback/xenbus.c1
-rw-r--r--drivers/zorro/names.c4
-rw-r--r--fs/Makefile2
-rw-r--r--fs/adfs/adfs.h1
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/dir_fplus.c9
-rw-r--r--fs/aio.c92
-rw-r--r--fs/autofs4/autofs_i.h63
-rw-r--r--fs/autofs4/expire.c1
-rw-r--r--fs/autofs4/root.c10
-rw-r--r--fs/bad_inode.c7
-rw-r--r--fs/befs/linuxvfs.c8
-rw-r--r--fs/bfs/bfs.h1
-rw-r--r--fs/bfs/dir.c4
-rw-r--r--fs/bfs/inode.c8
-rw-r--r--fs/btrfs/backref.c14
-rw-r--r--fs/btrfs/btrfs_inode.h6
-rw-r--r--fs/btrfs/ctree.c20
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c32
-rw-r--r--fs/btrfs/extent-tree.c285
-rw-r--r--fs/btrfs/extent_io.c10
-rw-r--r--fs/btrfs/file-item.c2
-rw-r--r--fs/btrfs/file.c26
-rw-r--r--fs/btrfs/inode.c71
-rw-r--r--fs/btrfs/ordered-data.c123
-rw-r--r--fs/btrfs/ordered-data.h5
-rw-r--r--fs/btrfs/qgroup.c169
-rw-r--r--fs/btrfs/qgroup.h1
-rw-r--r--fs/btrfs/super.c60
-rw-r--r--fs/btrfs/transaction.c33
-rw-r--r--fs/btrfs/transaction.h1
-rw-r--r--fs/btrfs/ulist.h15
-rw-r--r--fs/buffer.c11
-rw-r--r--fs/ceph/acl.c14
-rw-r--r--fs/ceph/caps.c2
-rw-r--r--fs/ceph/file.c24
-rw-r--r--fs/ceph/mds_client.c16
-rw-r--r--fs/ceph/super.c2
-rw-r--r--fs/ceph/xattr.c4
-rw-r--r--fs/cifs/cifs_debug.c2
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsfs.h6
-rw-r--r--fs/cifs/cifsglob.h19
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c119
-rw-r--r--fs/cifs/connect.c18
-rw-r--r--fs/cifs/file.c881
-rw-r--r--fs/cifs/inode.c20
-rw-r--r--fs/cifs/misc.c15
-rw-r--r--fs/cifs/sess.c1192
-rw-r--r--fs/cifs/smb1ops.c8
-rw-r--r--fs/cifs/smb2inode.c2
-rw-r--r--fs/cifs/smb2maperror.c2
-rw-r--r--fs/cifs/smb2misc.c6
-rw-r--r--fs/cifs/smb2ops.c73
-rw-r--r--fs/cifs/smb2pdu.c94
-rw-r--r--fs/cifs/smb2proto.h2
-rw-r--r--fs/cifs/smb2transport.c5
-rw-r--r--fs/cifs/transport.c25
-rw-r--r--fs/coda/cache.c2
-rw-r--r--fs/coda/coda_linux.c2
-rw-r--r--fs/coda/dir.c3
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/inode.c4
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/coda/psdev.c2
-rw-r--r--fs/coda/upcall.c2
-rw-r--r--fs/compat_ioctl.c2
-rw-r--r--fs/cramfs/inode.c45
-rw-r--r--fs/cramfs/uncompress.c10
-rw-r--r--fs/dcache.c196
-rw-r--r--fs/debugfs/file.c2
-rw-r--r--fs/debugfs/inode.c39
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dlm/debug_fs.c15
-rw-r--r--fs/efs/namei.c11
-rw-r--r--fs/exec.c10
-rw-r--r--fs/exofs/ore_raid.c2
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext4/balloc.c1
-rw-r--r--fs/ext4/dir.c25
-rw-r--r--fs/ext4/ext4.h14
-rw-r--r--fs/ext4/extents.c14
-rw-r--r--fs/ext4/file.c4
-rw-r--r--fs/ext4/indirect.c281
-rw-r--r--fs/ext4/inline.c18
-rw-r--r--fs/ext4/inode.c130
-rw-r--r--fs/ext4/mballoc.c41
-rw-r--r--fs/ext4/migrate.c7
-rw-r--r--fs/ext4/move_extent.c3
-rw-r--r--fs/ext4/namei.c1
-rw-r--r--fs/ext4/super.c88
-rw-r--r--fs/f2fs/acl.c6
-rw-r--r--fs/f2fs/checkpoint.c178
-rw-r--r--fs/f2fs/data.c59
-rw-r--r--fs/f2fs/debug.c19
-rw-r--r--fs/f2fs/dir.c87
-rw-r--r--fs/f2fs/f2fs.h50
-rw-r--r--fs/f2fs/file.c45
-rw-r--r--fs/f2fs/gc.c7
-rw-r--r--fs/f2fs/hash.c4
-rw-r--r--fs/f2fs/inline.c1
-rw-r--r--fs/f2fs/inode.c12
-rw-r--r--fs/f2fs/namei.c246
-rw-r--r--fs/f2fs/node.c273
-rw-r--r--fs/f2fs/node.h7
-rw-r--r--fs/f2fs/recovery.c22
-rw-r--r--fs/f2fs/segment.c38
-rw-r--r--fs/f2fs/segment.h8
-rw-r--r--fs/f2fs/super.c21
-rw-r--r--fs/fcntl.c5
-rw-r--r--fs/fs-writeback.c3
-rw-r--r--fs/fs_pin.c78
-rw-r--r--fs/fscache/cookie.c7
-rw-r--r--fs/fscache/internal.h2
-rw-r--r--fs/fscache/main.c22
-rw-r--r--fs/fscache/page.c4
-rw-r--r--fs/fuse/dir.c7
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/gfs2/glock.c25
-rw-r--r--fs/gfs2/lock_dlm.c8
-rw-r--r--fs/gfs2/ops_fstype.c11
-rw-r--r--fs/gfs2/recovery.c8
-rw-r--r--fs/gfs2/super.c8
-rw-r--r--fs/hostfs/hostfs.h1
-rw-r--r--fs/hostfs/hostfs_kern.c30
-rw-r--r--fs/hostfs/hostfs_user.c28
-rw-r--r--fs/hpfs/dnode.c17
-rw-r--r--fs/inode.c8
-rw-r--r--fs/internal.h7
-rw-r--r--fs/isofs/compress.c4
-rw-r--r--fs/jbd2/transaction.c10
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/compr_zlib.c7
-rw-r--r--fs/jffs2/xattr.c3
-rw-r--r--fs/kernfs/file.c2
-rw-r--r--fs/lockd/mon.c4
-rw-r--r--fs/locks.c112
-rw-r--r--fs/logfs/readwrite.c15
-rw-r--r--fs/minix/bitmap.c2
-rw-r--r--fs/minix/inode.c4
-rw-r--r--fs/mount.h2
-rw-r--r--fs/namei.c34
-rw-r--r--fs/namespace.c132
-rw-r--r--fs/nfs/blocklayout/blocklayout.c101
-rw-r--r--fs/nfs/callback.c12
-rw-r--r--fs/nfs/client.c113
-rw-r--r--fs/nfs/delegation.c34
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/dir.c208
-rw-r--r--fs/nfs/direct.c33
-rw-r--r--fs/nfs/file.c4
-rw-r--r--fs/nfs/filelayout/filelayout.c298
-rw-r--r--fs/nfs/filelayout/filelayoutdev.c6
-rw-r--r--fs/nfs/getroot.c2
-rw-r--r--fs/nfs/idmap.c10
-rw-r--r--fs/nfs/inode.c18
-rw-r--r--fs/nfs/internal.h22
-rw-r--r--fs/nfs/netns.h3
-rw-r--r--fs/nfs/nfs3acl.c2
-rw-r--r--fs/nfs/nfs3proc.c21
-rw-r--r--fs/nfs/nfs4_fs.h32
-rw-r--r--fs/nfs/nfs4client.c5
-rw-r--r--fs/nfs/nfs4proc.c248
-rw-r--r--fs/nfs/nfs4state.c73
-rw-r--r--fs/nfs/nfs4trace.h28
-rw-r--r--fs/nfs/nfs4xdr.c2
-rw-r--r--fs/nfs/objlayout/objio_osd.c24
-rw-r--r--fs/nfs/objlayout/objlayout.c81
-rw-r--r--fs/nfs/objlayout/objlayout.h8
-rw-r--r--fs/nfs/pagelist.c290
-rw-r--r--fs/nfs/pnfs.c180
-rw-r--r--fs/nfs/pnfs.h45
-rw-r--r--fs/nfs/proc.c27
-rw-r--r--fs/nfs/read.c54
-rw-r--r--fs/nfs/super.c12
-rw-r--r--fs/nfs/write.c154
-rw-r--r--fs/nfs_common/nfsacl.c5
-rw-r--r--fs/nfsd/acl.h2
-rw-r--r--fs/nfsd/auth.c2
-rw-r--r--fs/nfsd/export.c6
-rw-r--r--fs/nfsd/export.h3
-rw-r--r--fs/nfsd/fault_inject.c138
-rw-r--r--fs/nfsd/netns.h23
-rw-r--r--fs/nfsd/nfs2acl.c8
-rw-r--r--fs/nfsd/nfs3acl.c8
-rw-r--r--fs/nfsd/nfs3proc.c9
-rw-r--r--fs/nfsd/nfs3xdr.c30
-rw-r--r--fs/nfsd/nfs4acl.c39
-rw-r--r--fs/nfsd/nfs4callback.c32
-rw-r--r--fs/nfsd/nfs4proc.c53
-rw-r--r--fs/nfsd/nfs4state.c3096
-rw-r--r--fs/nfsd/nfs4xdr.c128
-rw-r--r--fs/nfsd/nfscache.c13
-rw-r--r--fs/nfsd/nfsctl.c51
-rw-r--r--fs/nfsd/nfsfh.c12
-rw-r--r--fs/nfsd/nfsfh.h15
-rw-r--r--fs/nfsd/nfsproc.c13
-rw-r--r--fs/nfsd/nfssvc.c21
-rw-r--r--fs/nfsd/nfsxdr.c14
-rw-r--r--fs/nfsd/state.h220
-rw-r--r--fs/nfsd/vfs.c48
-rw-r--r--fs/nfsd/vfs.h8
-rw-r--r--fs/nfsd/xdr4.h30
-rw-r--r--fs/nilfs2/Makefile2
-rw-r--r--fs/nilfs2/nilfs.h8
-rw-r--r--fs/nilfs2/super.c11
-rw-r--r--fs/nilfs2/sysfs.c1137
-rw-r--r--fs/nilfs2/sysfs.h176
-rw-r--r--fs/nilfs2/the_nilfs.c17
-rw-r--r--fs/nilfs2/the_nilfs.h20
-rw-r--r--fs/notify/fanotify/fanotify.c11
-rw-r--r--fs/notify/fanotify/fanotify_user.c14
-rw-r--r--fs/notify/inode_mark.c2
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c2
-rw-r--r--fs/notify/inotify/inotify_user.c4
-rw-r--r--fs/notify/notification.c37
-rw-r--r--fs/notify/vfsmount_mark.c2
-rw-r--r--fs/ntfs/file.c3
-rw-r--r--fs/ocfs2/alloc.c15
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c5
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c4
-rw-r--r--fs/ocfs2/move_extents.c2
-rw-r--r--fs/ocfs2/refcounttree.c2
-rw-r--r--fs/ocfs2/slot_map.c2
-rw-r--r--fs/omfs/inode.c2
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/array.c18
-rw-r--r--fs/proc/base.c199
-rw-r--r--fs/proc/fd.c2
-rw-r--r--fs/proc/generic.c32
-rw-r--r--fs/proc/inode.c7
-rw-r--r--fs/proc/internal.h15
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/meminfo.c2
-rw-r--r--fs/proc/proc_net.c4
-rw-r--r--fs/proc/proc_sysctl.c2
-rw-r--r--fs/proc/proc_tty.c4
-rw-r--r--fs/proc/root.c7
-rw-r--r--fs/proc/task_mmu.c27
-rw-r--r--fs/proc/thread_self.c85
-rw-r--r--fs/proc/vmcore.c82
-rw-r--r--fs/proc_namespace.c8
-rw-r--r--fs/pstore/ram_core.c2
-rw-r--r--fs/qnx6/Makefile1
-rw-r--r--fs/qnx6/dir.c26
-rw-r--r--fs/qnx6/inode.c99
-rw-r--r--fs/qnx6/namei.c6
-rw-r--r--fs/qnx6/qnx6.h12
-rw-r--r--fs/qnx6/super_mmi.c22
-rw-r--r--fs/quota/dquot.c180
-rw-r--r--fs/quota/kqid.c2
-rw-r--r--fs/quota/netlink.c3
-rw-r--r--fs/quota/quota.c6
-rw-r--r--fs/ramfs/file-nommu.c2
-rw-r--r--fs/reiserfs/dir.c2
-rw-r--r--fs/reiserfs/do_balan.c113
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/ibalance.c2
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/reiserfs/ioctl.c2
-rw-r--r--fs/reiserfs/item_ops.c4
-rw-r--r--fs/reiserfs/journal.c22
-rw-r--r--fs/reiserfs/lbalance.c7
-rw-r--r--fs/reiserfs/prints.c4
-rw-r--r--fs/reiserfs/procfs.c2
-rw-r--r--fs/reiserfs/reiserfs.h9
-rw-r--r--fs/reiserfs/stree.c2
-rw-r--r--fs/reiserfs/super.c15
-rw-r--r--fs/reiserfs/xattr.c22
-rw-r--r--fs/reiserfs/xattr_acl.c2
-rw-r--r--fs/reiserfs/xattr_security.c2
-rw-r--r--fs/reiserfs/xattr_trusted.c2
-rw-r--r--fs/reiserfs/xattr_user.c2
-rw-r--r--fs/romfs/super.c23
-rw-r--r--fs/squashfs/file_direct.c2
-rw-r--r--fs/squashfs/super.c5
-rw-r--r--fs/super.c20
-rw-r--r--fs/timerfd.c77
-rw-r--r--fs/ubifs/commit.c2
-rw-r--r--fs/ubifs/io.c2
-rw-r--r--fs/ubifs/log.c12
-rw-r--r--fs/ubifs/lpt.c5
-rw-r--r--fs/ubifs/lpt_commit.c7
-rw-r--r--fs/ubifs/master.c7
-rw-r--r--fs/ubifs/orphan.c1
-rw-r--r--fs/ubifs/recovery.c5
-rw-r--r--fs/ubifs/sb.c4
-rw-r--r--fs/ubifs/scan.c14
-rw-r--r--fs/ubifs/super.c19
-rw-r--r--fs/ubifs/tnc.c1
-rw-r--r--fs/ubifs/tnc_commit.c1
-rw-r--r--fs/ubifs/ubifs.h4
-rw-r--r--fs/udf/file.c22
-rw-r--r--fs/udf/lowlevel.c2
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/udf/symlink.c2
-rw-r--r--fs/udf/unicode.c9
-rw-r--r--fs/ufs/Makefile1
-rw-r--r--fs/ufs/inode.c32
-rw-r--r--fs/ufs/super.c304
-rw-r--r--fs/ufs/ufs.h10
-rw-r--r--fs/xfs/Kconfig1
-rw-r--r--fs/xfs/Makefile71
-rw-r--r--fs/xfs/libxfs/xfs_ag.h (renamed from fs/xfs/xfs_ag.h)0
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c (renamed from fs/xfs/xfs_alloc.c)20
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h (renamed from fs/xfs/xfs_alloc.h)0
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c (renamed from fs/xfs/xfs_alloc_btree.c)6
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.h (renamed from fs/xfs/xfs_alloc_btree.h)0
-rw-r--r--fs/xfs/libxfs/xfs_attr.c (renamed from fs/xfs/xfs_attr.c)92
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c (renamed from fs/xfs/xfs_attr_leaf.c)78
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h (renamed from fs/xfs/xfs_attr_leaf.h)0
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c (renamed from fs/xfs/xfs_attr_remote.c)22
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.h (renamed from fs/xfs/xfs_attr_remote.h)0
-rw-r--r--fs/xfs/libxfs/xfs_attr_sf.h (renamed from fs/xfs/xfs_attr_sf.h)0
-rw-r--r--fs/xfs/libxfs/xfs_bit.h (renamed from fs/xfs/xfs_bit.h)0
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c (renamed from fs/xfs/xfs_bmap.c)60
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h (renamed from fs/xfs/xfs_bmap.h)0
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c (renamed from fs/xfs/xfs_bmap_btree.c)99
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.h (renamed from fs/xfs/xfs_bmap_btree.h)0
-rw-r--r--fs/xfs/libxfs/xfs_btree.c (renamed from fs/xfs/xfs_btree.c)46
-rw-r--r--fs/xfs/libxfs/xfs_btree.h (renamed from fs/xfs/xfs_btree.h)2
-rw-r--r--fs/xfs/libxfs/xfs_cksum.h (renamed from fs/xfs/xfs_cksum.h)0
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c (renamed from fs/xfs/xfs_da_btree.c)112
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.h (renamed from fs/xfs/xfs_da_btree.h)0
-rw-r--r--fs/xfs/libxfs/xfs_da_format.c (renamed from fs/xfs/xfs_da_format.c)0
-rw-r--r--fs/xfs/libxfs/xfs_da_format.h (renamed from fs/xfs/xfs_da_format.h)0
-rw-r--r--fs/xfs/libxfs/xfs_dinode.h (renamed from fs/xfs/xfs_dinode.h)0
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c (renamed from fs/xfs/xfs_dir2.c)24
-rw-r--r--fs/xfs/libxfs/xfs_dir2.h (renamed from fs/xfs/xfs_dir2.h)0
-rw-r--r--fs/xfs/libxfs/xfs_dir2_block.c (renamed from fs/xfs/xfs_dir2_block.c)18
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c (renamed from fs/xfs/xfs_dir2_data.c)10
-rw-r--r--fs/xfs/libxfs/xfs_dir2_leaf.c (renamed from fs/xfs/xfs_dir2_leaf.c)24
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c (renamed from fs/xfs/xfs_dir2_node.c)40
-rw-r--r--fs/xfs/libxfs/xfs_dir2_priv.h (renamed from fs/xfs/xfs_dir2_priv.h)0
-rw-r--r--fs/xfs/libxfs/xfs_dir2_sf.c (renamed from fs/xfs/xfs_dir2_sf.c)75
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c (renamed from fs/xfs/xfs_dquot_buf.c)6
-rw-r--r--fs/xfs/libxfs/xfs_format.h (renamed from fs/xfs/xfs_format.h)14
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c (renamed from fs/xfs/xfs_ialloc.c)34
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h (renamed from fs/xfs/xfs_ialloc.h)0
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c (renamed from fs/xfs/xfs_ialloc_btree.c)6
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.h (renamed from fs/xfs/xfs_ialloc_btree.h)0
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c (renamed from fs/xfs/xfs_inode_buf.c)10
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h (renamed from fs/xfs/xfs_inode_buf.h)0
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c (renamed from fs/xfs/xfs_inode_fork.c)36
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.h (renamed from fs/xfs/xfs_inode_fork.h)0
-rw-r--r--fs/xfs/libxfs/xfs_inum.h (renamed from fs/xfs/xfs_inum.h)4
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h (renamed from fs/xfs/xfs_log_format.h)4
-rw-r--r--fs/xfs/libxfs/xfs_log_recover.h (renamed from fs/xfs/xfs_log_recover.h)0
-rw-r--r--fs/xfs/libxfs/xfs_log_rlimit.c (renamed from fs/xfs/xfs_log_rlimit.c)0
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h (renamed from fs/xfs/xfs_quota_defs.h)2
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c (renamed from fs/xfs/xfs_rtbitmap.c)0
-rw-r--r--fs/xfs/libxfs/xfs_sb.c (renamed from fs/xfs/xfs_sb.c)56
-rw-r--r--fs/xfs/libxfs/xfs_sb.h (renamed from fs/xfs/xfs_sb.h)8
-rw-r--r--fs/xfs/libxfs/xfs_shared.h (renamed from fs/xfs/xfs_shared.h)0
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c (renamed from fs/xfs/xfs_symlink_remote.c)6
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c (renamed from fs/xfs/xfs_trans_resv.c)0
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h (renamed from fs/xfs/xfs_trans_resv.h)0
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h (renamed from fs/xfs/xfs_trans_space.h)0
-rw-r--r--fs/xfs/xfs_acl.c8
-rw-r--r--fs/xfs/xfs_aops.c18
-rw-r--r--fs/xfs/xfs_attr_inactive.c22
-rw-r--r--fs/xfs/xfs_attr_list.c38
-rw-r--r--fs/xfs/xfs_bmap_util.c174
-rw-r--r--fs/xfs/xfs_buf.c40
-rw-r--r--fs/xfs/xfs_buf.h2
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_dir2_readdir.c4
-rw-r--r--fs/xfs/xfs_discard.c18
-rw-r--r--fs/xfs/xfs_dquot.c41
-rw-r--r--fs/xfs/xfs_dquot.h15
-rw-r--r--fs/xfs/xfs_error.c25
-rw-r--r--fs/xfs/xfs_error.h13
-rw-r--r--fs/xfs/xfs_export.c10
-rw-r--r--fs/xfs/xfs_extfree_item.c2
-rw-r--r--fs/xfs/xfs_file.c75
-rw-r--r--fs/xfs/xfs_filestream.c4
-rw-r--r--fs/xfs/xfs_fs.h7
-rw-r--r--fs/xfs/xfs_fsops.c42
-rw-r--r--fs/xfs/xfs_icache.c148
-rw-r--r--fs/xfs/xfs_icache.h13
-rw-r--r--fs/xfs/xfs_inode.c68
-rw-r--r--fs/xfs/xfs_inode.h10
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_ioctl.c266
-rw-r--r--fs/xfs/xfs_ioctl32.c111
-rw-r--r--fs/xfs/xfs_iomap.c54
-rw-r--r--fs/xfs/xfs_iops.c72
-rw-r--r--fs/xfs/xfs_itable.c579
-rw-r--r--fs/xfs/xfs_itable.h23
-rw-r--r--fs/xfs/xfs_linux.h27
-rw-r--r--fs/xfs/xfs_log.c69
-rw-r--r--fs/xfs/xfs_log_cil.c8
-rw-r--r--fs/xfs/xfs_log_priv.h2
-rw-r--r--fs/xfs/xfs_log_recover.c284
-rw-r--r--fs/xfs/xfs_mount.c97
-rw-r--r--fs/xfs/xfs_mount.h1
-rw-r--r--fs/xfs/xfs_mru_cache.c14
-rw-r--r--fs/xfs/xfs_qm.c229
-rw-r--r--fs/xfs/xfs_qm.h1
-rw-r--r--fs/xfs/xfs_qm_bhv.c2
-rw-r--r--fs/xfs/xfs_qm_syscalls.c46
-rw-r--r--fs/xfs/xfs_quotaops.c20
-rw-r--r--fs/xfs/xfs_rtalloc.c24
-rw-r--r--fs/xfs/xfs_rtalloc.h2
-rw-r--r--fs/xfs/xfs_super.c132
-rw-r--r--fs/xfs/xfs_super.h15
-rw-r--r--fs/xfs/xfs_symlink.c30
-rw-r--r--fs/xfs/xfs_sysfs.c165
-rw-r--r--fs/xfs/xfs_sysfs.h59
-rw-r--r--fs/xfs/xfs_trans.c10
-rw-r--r--fs/xfs/xfs_trans_ail.c4
-rw-r--r--fs/xfs/xfs_trans_buf.c37
-rw-r--r--fs/xfs/xfs_trans_dquot.c4
-rw-r--r--fs/xfs/xfs_types.h29
-rw-r--r--fs/xfs/xfs_vnode.h46
-rw-r--r--fs/xfs/xfs_xattr.c6
-rw-r--r--include/acpi/acconfig.h18
-rw-r--r--include/acpi/acnames.h1
-rw-r--r--include/acpi/acpi_bus.h42
-rw-r--r--include/acpi/acpiosxf.h31
-rw-r--r--include/acpi/acpixf.h54
-rw-r--r--include/acpi/actbl.h12
-rw-r--r--include/acpi/actbl1.h58
-rw-r--r--include/acpi/actbl2.h14
-rw-r--r--include/acpi/actbl3.h118
-rw-r--r--include/acpi/actypes.h19
-rw-r--r--include/acpi/apei.h4
-rw-r--r--include/acpi/ghes.h2
-rw-r--r--include/acpi/platform/acenv.h53
-rw-r--r--include/acpi/platform/aclinux.h12
-rw-r--r--include/acpi/platform/aclinuxex.h22
-rw-r--r--include/asm-generic/gpio.h3
-rw-r--r--include/asm-generic/io-64-nonatomic-hi-lo.h14
-rw-r--r--include/asm-generic/io-64-nonatomic-lo-hi.h14
-rw-r--r--include/asm-generic/pci-dma-compat.h8
-rw-r--r--include/asm-generic/percpu.h410
-rw-r--r--include/asm-generic/vmlinux.lds.h3
-rw-r--r--include/clocksource/pxa.h18
-rw-r--r--include/crypto/aead.h4
-rw-r--r--include/crypto/algapi.h6
-rw-r--r--include/crypto/des.h3
-rw-r--r--include/crypto/drbg.h290
-rw-r--r--include/crypto/hash.h4
-rw-r--r--include/crypto/internal/skcipher.h3
-rw-r--r--include/crypto/pkcs7.h36
-rw-r--r--include/crypto/public_key.h4
-rw-r--r--include/crypto/scatterwalk.h6
-rw-r--r--include/crypto/skcipher.h4
-rw-r--r--include/drm/drmP.h92
-rw-r--r--include/drm/drm_crtc.h36
-rw-r--r--include/drm/drm_dp_mst_helper.h509
-rw-r--r--include/drm/drm_fb_helper.h8
-rw-r--r--include/drm/drm_mipi_dsi.h21
-rw-r--r--include/drm/drm_of.h18
-rw-r--r--include/drm/drm_panel.h58
-rw-r--r--include/drm/drm_rect.h6
-rw-r--r--include/drm/ttm/ttm_bo_driver.h16
-rw-r--r--include/dt-bindings/clock/clps711x-clock.h27
-rw-r--r--include/dt-bindings/clock/exynos4.h25
-rw-r--r--include/dt-bindings/clock/exynos5250.h2
-rw-r--r--include/dt-bindings/clock/exynos5420.h2
-rw-r--r--include/dt-bindings/clock/exynos5440.h2
-rw-r--r--include/dt-bindings/clock/imx1-clock.h40
-rw-r--r--include/dt-bindings/clock/imx21-clock.h80
-rw-r--r--include/dt-bindings/clock/imx27-clock.h108
-rw-r--r--include/dt-bindings/clock/imx6qdl-clock.h224
-rw-r--r--include/dt-bindings/clock/qcom,gcc-apq8084.h351
-rw-r--r--include/dt-bindings/clock/qcom,gcc-ipq806x.h293
-rw-r--r--include/dt-bindings/clock/qcom,gcc-msm8960.h11
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-apq8084.h183
-rw-r--r--include/dt-bindings/clock/qcom,mmcc-msm8960.h8
-rw-r--r--include/dt-bindings/clock/r8a7790-clock.h27
-rw-r--r--include/dt-bindings/clock/r8a7791-clock.h27
-rw-r--r--include/dt-bindings/clock/rk3066a-cru.h (renamed from arch/arm/mach-s5p64x0/include/mach/dma.h)31
-rw-r--r--include/dt-bindings/clock/rk3188-cru-common.h249
-rw-r--r--include/dt-bindings/clock/rk3188-cru.h51
-rw-r--r--include/dt-bindings/clock/rk3288-cru.h278
-rw-r--r--include/dt-bindings/clock/s5pv210-audss.h34
-rw-r--r--include/dt-bindings/clock/s5pv210.h239
-rw-r--r--include/dt-bindings/clock/vf610-clock.h4
-rw-r--r--include/dt-bindings/dma/nbpfaxi.h20
-rw-r--r--include/dt-bindings/mfd/as3722.h2
-rw-r--r--include/dt-bindings/mfd/palmas.h18
-rw-r--r--include/dt-bindings/phy/phy-miphy365x.h14
-rw-r--r--include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h7
-rw-r--r--include/dt-bindings/reset/qcom,gcc-apq8084.h109
-rw-r--r--include/dt-bindings/reset/qcom,gcc-ipq806x.h132
-rw-r--r--include/dt-bindings/reset/qcom,gcc-msm8960.h16
-rw-r--r--include/dt-bindings/reset/qcom,mmcc-apq8084.h64
-rw-r--r--include/dt-bindings/reset/qcom,mmcc-msm8960.h8
-rw-r--r--include/keys/big_key-type.h3
-rw-r--r--include/keys/system_keyring.h10
-rw-r--r--include/keys/user-type.h3
-rw-r--r--include/kvm/arm_arch_timer.h14
-rw-r--r--include/kvm/arm_vgic.h115
-rw-r--r--include/linux/acct.h4
-rw-r--r--include/linux/acpi.h17
-rw-r--r--include/linux/aer.h2
-rw-r--r--include/linux/ahci_platform.h5
-rw-r--r--include/linux/amd-iommu.h7
-rw-r--r--include/linux/arcdevice.h10
-rw-r--r--include/linux/atmel-pwm-bl.h43
-rw-r--r--include/linux/atmel-ssc.h13
-rw-r--r--include/linux/atmel_pwm.h70
-rw-r--r--include/linux/bcma/bcma.h27
-rw-r--r--include/linux/bcma/bcma_driver_pcie2.h158
-rw-r--r--include/linux/bio.h1
-rw-r--r--include/linux/bitmap.h62
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/linux/byteorder/generic.h2
-rw-r--r--include/linux/capability.h5
-rw-r--r--include/linux/ceph/messenger.h14
-rw-r--r--include/linux/ceph/osd_client.h18
-rw-r--r--include/linux/cgroup.h165
-rw-r--r--include/linux/clk-provider.h5
-rw-r--r--include/linux/clk/clk-conf.h20
-rw-r--r--include/linux/clocksource.h2
-rw-r--r--include/linux/cma.h27
-rw-r--r--include/linux/component.h7
-rw-r--r--include/linux/cper.h32
-rw-r--r--include/linux/cpufreq.h1
-rw-r--r--include/linux/crc32.h20
-rw-r--r--include/linux/cred.h9
-rw-r--r--include/linux/crypto.h8
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/decompress/bunzip2.h8
-rw-r--r--include/linux/decompress/generic.h10
-rw-r--r--include/linux/decompress/inflate.h8
-rw-r--r--include/linux/decompress/unlz4.h8
-rw-r--r--include/linux/decompress/unlzma.h8
-rw-r--r--include/linux/decompress/unlzo.h8
-rw-r--r--include/linux/decompress/unxz.h8
-rw-r--r--include/linux/device.h8
-rw-r--r--include/linux/dma-buf.h21
-rw-r--r--include/linux/dma-contiguous.h11
-rw-r--r--include/linux/dmaengine.h6
-rw-r--r--include/linux/dmar.h50
-rw-r--r--include/linux/drbd.h4
-rw-r--r--include/linux/drbd_genl.h4
-rw-r--r--include/linux/drbd_limits.h6
-rw-r--r--include/linux/edac.h5
-rw-r--r--include/linux/efi.h82
-rw-r--r--include/linux/extcon/sm5502.h287
-rw-r--r--include/linux/fb.h2
-rw-r--r--include/linux/fence.h360
-rw-r--r--include/linux/filter.h112
-rw-r--r--include/linux/firmware.h15
-rw-r--r--include/linux/fs.h35
-rw-r--r--include/linux/fs_pin.h17
-rw-r--r--include/linux/fsnotify_backend.h14
-rw-r--r--include/linux/ftrace.h68
-rw-r--r--include/linux/ftrace_event.h37
-rw-r--r--include/linux/gfp.h2
-rw-r--r--include/linux/glob.h9
-rw-r--r--include/linux/gpio/consumer.h81
-rw-r--r--include/linux/gpio/driver.h66
-rw-r--r--include/linux/gpio/machine.h61
-rw-r--r--include/linux/hid.h6
-rw-r--r--include/linux/highmem.h2
-rw-r--r--include/linux/host1x.h15
-rw-r--r--include/linux/hrtimer.h16
-rw-r--r--include/linux/huge_mm.h4
-rw-r--r--include/linux/hugetlb.h1
-rw-r--r--include/linux/hw_random.h5
-rw-r--r--include/linux/i2c.h12
-rw-r--r--include/linux/i2c/atmel_mxt_ts.h3
-rw-r--r--include/linux/i2c/s6000.h10
-rw-r--r--include/linux/ieee80211.h23
-rw-r--r--include/linux/if_bridge.h20
-rw-r--r--include/linux/if_vlan.h6
-rw-r--r--include/linux/iio/accel/kxcjk_1013.h (renamed from include/linux/tegra-soc.h)16
-rw-r--r--include/linux/iio/common/st_sensors.h12
-rw-r--r--include/linux/iio/common/st_sensors_i2c.h11
-rw-r--r--include/linux/iio/iio.h9
-rw-r--r--include/linux/iio/imu/adis.h33
-rw-r--r--include/linux/iio/trigger.h5
-rw-r--r--include/linux/iio/types.h5
-rw-r--r--include/linux/ima.h6
-rw-r--r--include/linux/init_task.h9
-rw-r--r--include/linux/input/mt.h1
-rw-r--r--include/linux/input/pixcir_ts.h12
-rw-r--r--include/linux/intel-iommu.h3
-rw-r--r--include/linux/io.h2
-rw-r--r--include/linux/iommu.h32
-rw-r--r--include/linux/ioport.h6
-rw-r--r--include/linux/iova.h5
-rw-r--r--include/linux/ipv6.h24
-rw-r--r--include/linux/irq.h2
-rw-r--r--include/linux/irq_work.h5
-rw-r--r--include/linux/irqchip/arm-gic-v3.h200
-rw-r--r--include/linux/irqchip/spear-shirq.h64
-rw-r--r--include/linux/irqdomain.h2
-rw-r--r--include/linux/isdn_ppp.h4
-rw-r--r--include/linux/kernel.h10
-rw-r--r--include/linux/kexec.h104
-rw-r--r--include/linux/key-type.h5
-rw-r--r--include/linux/key.h2
-rw-r--r--include/linux/klist.h2
-rw-r--r--include/linux/kthread.h13
-rw-r--r--include/linux/ktime.h228
-rw-r--r--include/linux/kvm_host.h47
-rw-r--r--include/linux/leds.h5
-rw-r--r--include/linux/list.h14
-rw-r--r--include/linux/memblock.h4
-rw-r--r--include/linux/memcontrol.h98
-rw-r--r--include/linux/memory_hotplug.h10
-rw-r--r--include/linux/mfd/abx500/ab8500.h1
-rw-r--r--include/linux/mfd/arizona/core.h41
-rw-r--r--include/linux/mfd/arizona/pdata.h3
-rw-r--r--include/linux/mfd/arizona/registers.h785
-rw-r--r--include/linux/mfd/cros_ec.h110
-rw-r--r--include/linux/mfd/da9063/core.h3
-rw-r--r--include/linux/mfd/da9063/registers.h129
-rw-r--r--include/linux/mfd/intel_soc_pmic.h30
-rw-r--r--include/linux/mfd/max77686-private.h239
-rw-r--r--include/linux/mfd/max77686.h59
-rw-r--r--include/linux/mfd/max77693-private.h54
-rw-r--r--include/linux/mfd/mc13783.h1
-rw-r--r--include/linux/mfd/mc13xxx.h23
-rw-r--r--include/linux/mfd/palmas.h837
-rw-r--r--include/linux/mfd/rtsx_pci.h6
-rw-r--r--include/linux/mfd/samsung/core.h1
-rw-r--r--include/linux/mfd/samsung/irq.h24
-rw-r--r--include/linux/mfd/samsung/s2mpu02.h201
-rw-r--r--include/linux/mfd/tps65910.h2
-rw-r--r--include/linux/mic_bus.h110
-rw-r--r--include/linux/mlx4/cmd.h7
-rw-r--r--include/linux/mlx4/device.h35
-rw-r--r--include/linux/mlx5/device.h4
-rw-r--r--include/linux/mlx5/driver.h31
-rw-r--r--include/linux/mm.h17
-rw-r--r--include/linux/mm_types.h9
-rw-r--r--include/linux/mmc/dw_mmc.h2
-rw-r--r--include/linux/mmc/sdhci.h3
-rw-r--r--include/linux/mmdebug.h2
-rw-r--r--include/linux/mmu_notifier.h6
-rw-r--r--include/linux/mmzone.h219
-rw-r--r--include/linux/module.h11
-rw-r--r--include/linux/moduleloader.h6
-rw-r--r--include/linux/moduleparam.h5
-rw-r--r--include/linux/mount.h13
-rw-r--r--include/linux/msi.h3
-rw-r--r--include/linux/mtd/mtd.h2
-rw-r--r--include/linux/mtd/nand.h53
-rw-r--r--include/linux/mtd/spi-nor.h4
-rw-r--r--include/linux/mutex.h4
-rw-r--r--include/linux/mvebu-pmsu.h20
-rw-r--r--include/linux/netdev_features.h8
-rw-r--r--include/linux/netdevice.h421
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nfs_page.h19
-rw-r--r--include/linux/nfs_xdr.h34
-rw-r--r--include/linux/nmi.h4
-rw-r--r--include/linux/nodemask.h11
-rw-r--r--include/linux/nsproxy.h16
-rw-r--r--include/linux/of.h87
-rw-r--r--include/linux/of_address.h11
-rw-r--r--include/linux/of_dma.h4
-rw-r--r--include/linux/of_platform.h7
-rw-r--r--include/linux/of_reserved_mem.h7
-rw-r--r--include/linux/oid_registry.h8
-rw-r--r--include/linux/omap-dma.h1
-rw-r--r--include/linux/omap-iommu.h37
-rw-r--r--include/linux/oom.h4
-rw-r--r--include/linux/page-flags.h21
-rw-r--r--include/linux/page_cgroup.h70
-rw-r--r--include/linux/pagemap.h3
-rw-r--r--include/linux/pci-acpi.h13
-rw-r--r--include/linux/pci.h16
-rw-r--r--include/linux/pci_ids.h4
-rw-r--r--include/linux/pe.h448
-rw-r--r--include/linux/percpu-defs.h380
-rw-r--r--include/linux/percpu-refcount.h64
-rw-r--r--include/linux/percpu.h673
-rw-r--r--include/linux/phy.h18
-rw-r--r--include/linux/phy/omap_control_phy.h10
-rw-r--r--include/linux/phy/phy.h17
-rw-r--r--include/linux/pid_namespace.h1
-rw-r--r--include/linux/pinctrl/pinmux.h2
-rw-r--r--include/linux/platform_data/ad7291.h (renamed from drivers/staging/iio/adc/ad7291.h)0
-rw-r--r--include/linux/platform_data/asoc-s3c.h9
-rw-r--r--include/linux/platform_data/ata-samsung_cf.h1
-rw-r--r--include/linux/platform_data/camera-mx1.h35
-rw-r--r--include/linux/platform_data/dma-imx.h2
-rw-r--r--include/linux/platform_data/dsp-omap.h34
-rw-r--r--include/linux/platform_data/edma.h2
-rw-r--r--include/linux/platform_data/iommu-omap.h6
-rw-r--r--include/linux/platform_data/mmc-omap.h1
-rw-r--r--include/linux/platform_data/ntc_thermistor.h1
-rw-r--r--include/linux/platform_data/st21nfcb.h32
-rw-r--r--include/linux/platform_data/usb-ehci-mxc.h46
-rw-r--r--include/linux/platform_data/usb-imx_udc.h23
-rw-r--r--include/linux/platform_data/video-clcd-versatile.h27
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/pm_runtime.h11
-rw-r--r--include/linux/power_supply.h4
-rw-r--r--include/linux/printk.h5
-rw-r--r--include/linux/ptp_classify.h5
-rw-r--r--include/linux/quota.h1
-rw-r--r--include/linux/ras.h14
-rw-r--r--include/linux/rculist.h8
-rw-r--r--include/linux/rcupdate.h45
-rw-r--r--include/linux/regmap.h7
-rw-r--r--include/linux/regulator/ab8500.h14
-rw-r--r--include/linux/regulator/act8865.h23
-rw-r--r--include/linux/regulator/consumer.h26
-rw-r--r--include/linux/regulator/da9211.h32
-rw-r--r--include/linux/reservation.h82
-rw-r--r--include/linux/rhashtable.h208
-rw-r--r--include/linux/rio_drv.h5
-rw-r--r--include/linux/rndis.h1
-rw-r--r--include/linux/rtmutex.h6
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--include/linux/scatterlist.h8
-rw-r--r--include/linux/sched.h62
-rw-r--r--include/linux/seccomp.h8
-rw-r--r--include/linux/security.h17
-rw-r--r--include/linux/seqlock.h29
-rw-r--r--include/linux/seqno-fence.h116
-rw-r--r--include/linux/serial_8250.h7
-rw-r--r--include/linux/serial_core.h2
-rw-r--r--include/linux/sfi_acpi.h3
-rw-r--r--include/linux/sh_dma.h24
-rw-r--r--include/linux/sh_timer.h5
-rw-r--r--include/linux/shm.h18
-rw-r--r--include/linux/shmem_fs.h17
-rw-r--r--include/linux/signal.h15
-rw-r--r--include/linux/skbuff.h45
-rw-r--r--include/linux/spi/cc2520.h26
-rw-r--r--include/linux/spi/sh_msiof.h2
-rw-r--r--include/linux/ssb/ssb_regs.h37
-rw-r--r--include/linux/stmmac.h2
-rw-r--r--include/linux/sunrpc/auth.h4
-rw-r--r--include/linux/sunrpc/auth_gss.h3
-rw-r--r--include/linux/sunrpc/gss_krb5.h4
-rw-r--r--include/linux/sunrpc/sched.h2
-rw-r--r--include/linux/sunrpc/svc.h4
-rw-r--r--include/linux/sunrpc/svc_rdma.h3
-rw-r--r--include/linux/sunrpc/svc_xprt.h2
-rw-r--r--include/linux/sunrpc/xprtrdma.h2
-rw-r--r--include/linux/swap.h16
-rw-r--r--include/linux/syscalls.h10
-rw-r--r--include/linux/sysctl.h2
-rw-r--r--include/linux/tcp.h3
-rw-r--r--include/linux/thermal.h46
-rw-r--r--include/linux/tick.h29
-rw-r--r--include/linux/time.h65
-rw-r--r--include/linux/time64.h190
-rw-r--r--include/linux/timekeeper_internal.h150
-rw-r--r--include/linux/timekeeping.h209
-rw-r--r--include/linux/timerfd.h5
-rw-r--r--include/linux/tpm.h3
-rw-r--r--include/linux/trace_seq.h36
-rw-r--r--include/linux/tracehook.h8
-rw-r--r--include/linux/tracepoint.h44
-rw-r--r--include/linux/tty.h4
-rw-r--r--include/linux/tty_driver.h8
-rw-r--r--include/linux/uio.h2
-rw-r--r--include/linux/usb/composite.h15
-rw-r--r--include/linux/usb/quirks.h11
-rw-r--r--include/linux/usb/renesas_usbhs.h6
-rw-r--r--include/linux/usb/usb338x.h199
-rw-r--r--include/linux/usb/usbnet.h3
-rw-r--r--include/linux/usb/xhci_pdriver.h27
-rw-r--r--include/linux/user_namespace.h6
-rw-r--r--include/linux/verify_pefile.h18
-rw-r--r--include/linux/vfio.h23
-rw-r--r--include/linux/vmalloc.h2
-rw-r--r--include/linux/wait.h125
-rw-r--r--include/linux/writeback.h3
-rw-r--r--include/linux/zbud.h2
-rw-r--r--include/linux/zlib.h122
-rw-r--r--include/linux/zpool.h106
-rw-r--r--include/media/atmel-isi.h4
-rw-r--r--include/media/blackfin/ppi.h4
-rw-r--r--include/media/ir-kbd-i2c.h6
-rw-r--r--include/media/rc-core.h71
-rw-r--r--include/media/rc-map.h16
-rw-r--r--include/media/v4l2-ctrls.h222
-rw-r--r--include/media/v4l2-dev.h2
-rw-r--r--include/media/v4l2-ioctl.h2
-rw-r--r--include/media/v4l2-mem2mem.h2
-rw-r--r--include/media/videobuf-dma-sg.h3
-rw-r--r--include/media/videobuf2-core.h19
-rw-r--r--include/net/6lowpan.h50
-rw-r--r--include/net/bluetooth/bluetooth.h18
-rw-r--r--include/net/bluetooth/hci.h297
-rw-r--r--include/net/bluetooth/hci_core.h187
-rw-r--r--include/net/bluetooth/hci_sock.h175
-rw-r--r--include/net/bluetooth/l2cap.h46
-rw-r--r--include/net/bluetooth/mgmt.h103
-rw-r--r--include/net/bluetooth/sco.h30
-rw-r--r--include/net/cfg80211.h38
-rw-r--r--include/net/dcbnl.h4
-rw-r--r--include/net/flow_keys.h15
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--include/net/inet_connection_sock.h1
-rw-r--r--include/net/inet_frag.h118
-rw-r--r--include/net/inet_sock.h6
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--include/net/ip.h21
-rw-r--r--include/net/ip_tunnels.h1
-rw-r--r--include/net/ipv6.h71
-rw-r--r--include/net/mac80211.h105
-rw-r--r--include/net/mac802154.h19
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h26
-rw-r--r--include/net/netfilter/nf_log.h42
-rw-r--r--include/net/netfilter/xt_log.h54
-rw-r--r--include/net/netlabel.h94
-rw-r--r--include/net/netlink.h6
-rw-r--r--include/net/netns/conntrack.h6
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--include/net/netns/x_tables.h6
-rw-r--r--include/net/nfc/digital.h13
-rw-r--r--include/net/nfc/hci.h1
-rw-r--r--include/net/rtnetlink.h1
-rw-r--r--include/net/sch_generic.h2
-rw-r--r--include/net/sctp/command.h39
-rw-r--r--include/net/sctp/constants.h2
-rw-r--r--include/net/sctp/sctp.h24
-rw-r--r--include/net/sctp/structs.h15
-rw-r--r--include/net/sctp/ulpevent.h14
-rw-r--r--include/net/sock.h77
-rw-r--r--include/net/tcp.h70
-rw-r--r--include/net/udp.h29
-rw-r--r--include/net/udp_tunnel.h32
-rw-r--r--include/net/vxlan.h2
-rw-r--r--include/ras/ras_event.h128
-rw-r--r--include/rdma/ib_mad.h18
-rw-r--r--include/rdma/ib_verbs.h10
-rw-r--r--include/scsi/iscsi_if.h1
-rw-r--r--include/scsi/libsrp.h78
-rw-r--r--include/scsi/scsi.h5
-rw-r--r--include/scsi/scsi_cmnd.h3
-rw-r--r--include/scsi/scsi_device.h39
-rw-r--r--include/scsi/scsi_devinfo.h5
-rw-r--r--include/scsi/scsi_driver.h3
-rw-r--r--include/scsi/scsi_host.h68
-rw-r--r--include/scsi/scsi_tcq.h28
-rw-r--r--include/scsi/scsi_tgt.h21
-rw-r--r--include/scsi/scsi_tgt_if.h108
-rw-r--r--include/scsi/scsi_transport.h2
-rw-r--r--include/scsi/scsi_transport_fc.h4
-rw-r--r--include/scsi/sg.h94
-rw-r--r--include/soc/tegra/ahb.h (renamed from include/linux/tegra-ahb.h)6
-rw-r--r--include/soc/tegra/common.h (renamed from arch/arm/mach-kirkwood/include/mach/hardware.h)10
-rw-r--r--include/soc/tegra/cpuidle.h (renamed from include/linux/tegra-cpuidle.h)6
-rw-r--r--include/soc/tegra/fuse.h65
-rw-r--r--include/soc/tegra/pm.h38
-rw-r--r--include/soc/tegra/pmc.h (renamed from include/linux/tegra-powergate.h)31
-rw-r--r--include/sound/control.h7
-rw-r--r--include/sound/pcm.h11
-rw-r--r--include/sound/rcar_snd.h1
-rw-r--r--include/sound/rt286.h19
-rw-r--r--include/sound/rt5670.h27
-rw-r--r--include/sound/soc-dai.h5
-rw-r--r--include/sound/soc-dapm.h8
-rw-r--r--include/sound/soc.h94
-rw-r--r--include/sound/tas2552-plat.h25
-rw-r--r--include/sound/wm8962.h1
-rw-r--r--include/trace/events/asoc.h6
-rw-r--r--include/trace/events/bcache.h21
-rw-r--r--include/trace/events/f2fs.h87
-rw-r--r--include/trace/events/fence.h128
-rw-r--r--include/trace/events/ipi.h89
-rw-r--r--include/trace/events/kvm.h8
-rw-r--r--include/trace/events/migrate.h1
-rw-r--r--include/trace/events/pagemap.h16
-rw-r--r--include/trace/events/ras.h77
-rw-r--r--include/trace/events/thp.h88
-rw-r--r--include/trace/events/tlb.h40
-rw-r--r--include/uapi/asm-generic/unistd.h6
-rw-r--r--include/uapi/drm/drm.h2
-rw-r--r--include/uapi/drm/drm_mode.h5
-rw-r--r--include/uapi/drm/nouveau_drm.h11
-rw-r--r--include/uapi/drm/radeon_drm.h4
-rw-r--r--include/uapi/drm/tegra_drm.h46
-rw-r--r--include/uapi/linux/audit.h1
-rw-r--r--include/uapi/linux/bsg.h11
-rw-r--r--include/uapi/linux/can/netlink.h3
-rw-r--r--include/uapi/linux/dcbnl.h3
-rw-r--r--include/uapi/linux/errqueue.h20
-rw-r--r--include/uapi/linux/fcntl.h15
-rw-r--r--include/uapi/linux/genwqe/genwqe_card.h1
-rw-r--r--include/uapi/linux/i8k.h3
-rw-r--r--include/uapi/linux/if_link.h6
-rw-r--r--include/uapi/linux/if_packet.h2
-rw-r--r--include/uapi/linux/in6.h1
-rw-r--r--include/uapi/linux/ipv6.h1
-rw-r--r--include/uapi/linux/kexec.h11
-rw-r--r--include/uapi/linux/kvm.h13
-rw-r--r--include/uapi/linux/memfd.h8
-rw-r--r--include/uapi/linux/net_tstamp.h10
-rw-r--r--include/uapi/linux/netdevice.h6
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h4
-rw-r--r--include/uapi/linux/netfilter/xt_bpf.h4
-rw-r--r--include/uapi/linux/netfilter_bridge/Kbuild1
-rw-r--r--include/uapi/linux/netfilter_bridge/ebt_ulog.h38
-rw-r--r--include/uapi/linux/netfilter_ipv4/Kbuild1
-rw-r--r--include/uapi/linux/netfilter_ipv4/ipt_ULOG.h49
-rw-r--r--include/uapi/linux/nl80211.h5
-rw-r--r--include/uapi/linux/openvswitch.h13
-rw-r--r--include/uapi/linux/random.h9
-rw-r--r--include/uapi/linux/sctp.h102
-rw-r--r--include/uapi/linux/seccomp.h7
-rw-r--r--include/uapi/linux/serial_reg.h5
-rw-r--r--include/uapi/linux/serio.h1
-rw-r--r--include/uapi/linux/sysctl.h1
-rw-r--r--include/uapi/linux/tipc_config.h2
-rw-r--r--include/uapi/linux/uinput.h9
-rw-r--r--include/uapi/linux/usb/functionfs.h82
-rw-r--r--include/uapi/linux/v4l2-controls.h32
-rw-r--r--include/uapi/linux/vfio.h34
-rw-r--r--include/uapi/linux/videodev2.h101
-rw-r--r--include/uapi/linux/virtio_blk.h5
-rw-r--r--include/uapi/rdma/ib_user_mad.h42
-rw-r--r--include/uapi/rdma/ib_user_verbs.h16
-rw-r--r--include/uapi/rdma/rdma_user_cm.h1
-rw-r--r--include/uapi/sound/asound.h9
-rw-r--r--include/video/omapdss.h9
-rw-r--r--include/video/samsung_fimd.h5
-rw-r--r--include/xen/grant_table.h30
-rw-r--r--include/xen/interface/platform.h123
-rw-r--r--include/xen/xen-ops.h11
-rw-r--r--init/Kconfig59
-rw-r--r--init/calibrate.c11
-rw-r--r--init/do_mounts.c12
-rw-r--r--init/do_mounts_rd.c10
-rw-r--r--init/initramfs.c60
-rw-r--r--init/main.c23
-rw-r--r--ipc/namespace.c6
-rw-r--r--ipc/shm.c75
-rw-r--r--kernel/Makefile28
-rw-r--r--kernel/acct.c494
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditfilter.c4
-rw-r--r--kernel/bounds.c2
-rw-r--r--kernel/bpf/Makefile1
-rw-r--r--kernel/bpf/core.c534
-rw-r--r--kernel/capability.c4
-rw-r--r--kernel/cgroup.c461
-rw-r--r--kernel/cgroup_freezer.c2
-rw-r--r--kernel/cpu.c33
-rw-r--r--kernel/cpuset.c500
-rw-r--r--kernel/debug/kdb/kdb_main.c2
-rw-r--r--kernel/delayacct.c62
-rw-r--r--kernel/events/core.c8
-rw-r--r--kernel/events/uprobes.c15
-rw-r--r--kernel/exit.c50
-rw-r--r--kernel/fork.c134
-rw-r--r--kernel/futex.c402
-rw-r--r--kernel/gcov/fs.c3
-rw-r--r--kernel/irq/generic-chip.c5
-rw-r--r--kernel/irq/irqdomain.c2
-rw-r--r--kernel/irq_work.c110
-rw-r--r--kernel/kallsyms.c2
-rw-r--r--kernel/kexec.c1291
-rw-r--r--kernel/kthread.c2
-rw-r--r--kernel/locking/lockdep.c2
-rw-r--r--kernel/locking/mcs_spinlock.c8
-rw-r--r--kernel/locking/mcs_spinlock.h4
-rw-r--r--kernel/locking/mutex.c39
-rw-r--r--kernel/locking/qrwlock.c9
-rw-r--r--kernel/locking/rtmutex-debug.c5
-rw-r--r--kernel/locking/rtmutex-debug.h7
-rw-r--r--kernel/locking/rtmutex.c562
-rw-r--r--kernel/locking/rtmutex.h7
-rw-r--r--kernel/locking/rtmutex_common.h22
-rw-r--r--kernel/locking/rwsem-xadd.c4
-rw-r--r--kernel/module.c23
-rw-r--r--kernel/nsproxy.c15
-rw-r--r--kernel/panic.c1
-rw-r--r--kernel/params.c1
-rw-r--r--kernel/power/Kconfig3
-rw-r--r--kernel/power/hibernate.c6
-rw-r--r--kernel/power/main.c25
-rw-r--r--kernel/power/power.h7
-rw-r--r--kernel/power/snapshot.c515
-rw-r--r--kernel/power/suspend.c154
-rw-r--r--kernel/power/suspend_test.c12
-rw-r--r--kernel/printk/printk.c169
-rw-r--r--kernel/ptrace.c8
-rw-r--r--kernel/rcu/rcu.h8
-rw-r--r--kernel/rcu/srcu.c4
-rw-r--r--kernel/rcu/tree.c59
-rw-r--r--kernel/rcu/tree.h36
-rw-r--r--kernel/rcu/tree_plugin.h302
-rw-r--r--kernel/rcu/update.c3
-rw-r--r--kernel/resource.c101
-rw-r--r--kernel/sched/core.c128
-rw-r--r--kernel/sched/cpuacct.c2
-rw-r--r--kernel/sched/deadline.c18
-rw-r--r--kernel/sched/fair.c244
-rw-r--r--kernel/sched/idle.c8
-rw-r--r--kernel/sched/idle_task.c2
-rw-r--r--kernel/sched/proc.c7
-rw-r--r--kernel/sched/rt.c30
-rw-r--r--kernel/sched/sched.h38
-rw-r--r--kernel/sched/wait.c30
-rw-r--r--kernel/seccomp.c430
-rw-r--r--kernel/signal.c50
-rw-r--r--kernel/smp.c11
-rw-r--r--kernel/sys.c4
-rw-r--r--kernel/sys_ni.c5
-rw-r--r--kernel/sysctl.c9
-rw-r--r--kernel/sysctl_binary.c1
-rw-r--r--kernel/system_keyring.c1
-rw-r--r--kernel/test_kprobes.c87
-rw-r--r--kernel/time/Kconfig9
-rw-r--r--kernel/time/Makefile19
-rw-r--r--kernel/time/alarmtimer.c2
-rw-r--r--kernel/time/clocksource.c12
-rw-r--r--kernel/time/hrtimer.c (renamed from kernel/hrtimer.c)125
-rw-r--r--kernel/time/itimer.c (renamed from kernel/itimer.c)0
-rw-r--r--kernel/time/ntp.c15
-rw-r--r--kernel/time/ntp_internal.h2
-rw-r--r--kernel/time/posix-cpu-timers.c (renamed from kernel/posix-cpu-timers.c)0
-rw-r--r--kernel/time/posix-timers.c (renamed from kernel/posix-timers.c)2
-rw-r--r--kernel/time/tick-internal.h2
-rw-r--r--kernel/time/tick-sched.c20
-rw-r--r--kernel/time/time.c (renamed from kernel/time.c)64
-rw-r--r--kernel/time/timeconst.bc (renamed from kernel/timeconst.bc)0
-rw-r--r--kernel/time/timekeeping.c1148
-rw-r--r--kernel/time/timekeeping.h20
-rw-r--r--kernel/time/timekeeping_debug.c2
-rw-r--r--kernel/time/timekeeping_internal.h17
-rw-r--r--kernel/time/timer.c (renamed from kernel/timer.c)34
-rw-r--r--kernel/time/udelay_test.c168
-rw-r--r--kernel/torture.c2
-rw-r--r--kernel/trace/Kconfig5
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/ftrace.c445
-rw-r--r--kernel/trace/ring_buffer.c57
-rw-r--r--kernel/trace/trace.c107
-rw-r--r--kernel/trace/trace.h2
-rw-r--r--kernel/trace/trace_event_perf.c12
-rw-r--r--kernel/trace/trace_events.c60
-rw-r--r--kernel/trace/trace_events_filter.c73
-rw-r--r--kernel/trace/trace_functions_graph.c43
-rw-r--r--kernel/trace/trace_output.c282
-rw-r--r--kernel/trace/trace_output.h4
-rw-r--r--kernel/trace/trace_seq.c428
-rw-r--r--kernel/trace/trace_uprobe.c3
-rw-r--r--kernel/tsacct.c19
-rw-r--r--kernel/user_namespace.c6
-rw-r--r--kernel/utsname.c6
-rw-r--r--kernel/watchdog.c11
-rw-r--r--kernel/workqueue.c206
-rw-r--r--lib/Kconfig43
-rw-r--r--lib/Kconfig.debug72
-rw-r--r--lib/Makefile5
-rw-r--r--lib/bitmap.c111
-rw-r--r--lib/cmdline.c15
-rw-r--r--lib/crc32.c153
-rw-r--r--lib/decompress.c2
-rw-r--r--lib/decompress_bunzip2.c26
-rw-r--r--lib/decompress_inflate.c12
-rw-r--r--lib/decompress_unlz4.c83
-rw-r--r--lib/decompress_unlzma.c28
-rw-r--r--lib/decompress_unlzo.c12
-rw-r--r--lib/decompress_unxz.c10
-rw-r--r--lib/devres.c30
-rw-r--r--lib/dynamic_debug.c8
-rw-r--r--lib/glob.c287
-rw-r--r--lib/idr.c25
-rw-r--r--lib/iovec.c4
-rw-r--r--lib/kfifo.c6
-rw-r--r--lib/klist.c6
-rw-r--r--lib/list_sort.c71
-rw-r--r--lib/lockref.c3
-rw-r--r--lib/lru_cache.c23
-rw-r--r--lib/net_utils.c10
-rw-r--r--lib/percpu-refcount.c86
-rw-r--r--lib/random32.c49
-rw-r--r--lib/rbtree.c2
-rw-r--r--lib/rhashtable.c791
-rw-r--r--lib/scatterlist.c29
-rw-r--r--lib/string_helpers.c15
-rw-r--r--lib/test-kstrtox.c2
-rw-r--r--lib/test_bpf.c28
-rw-r--r--lib/test_firmware.c117
-rw-r--r--lib/zlib_deflate/deflate.c143
-rw-r--r--lib/zlib_inflate/inflate.c132
-rw-r--r--mm/Kconfig54
-rw-r--r--mm/Makefile2
-rw-r--r--mm/cma.c335
-rw-r--r--mm/filemap.c74
-rw-r--r--mm/gup.c18
-rw-r--r--mm/highmem.c86
-rw-r--r--mm/huge_memory.c89
-rw-r--r--mm/hugetlb.c129
-rw-r--r--mm/hugetlb_cgroup.c6
-rw-r--r--mm/hwpoison-inject.c3
-rw-r--r--mm/internal.h2
-rw-r--r--mm/iov_iter.c17
-rw-r--r--mm/ksm.c8
-rw-r--r--mm/madvise.c3
-rw-r--r--mm/memcontrol.c1709
-rw-r--r--mm/memory-failure.c10
-rw-r--r--mm/memory.c151
-rw-r--r--mm/memory_hotplug.c45
-rw-r--r--mm/migrate.c38
-rw-r--r--mm/mlock.c9
-rw-r--r--mm/mmap.c35
-rw-r--r--mm/mmu_notifier.c40
-rw-r--r--mm/nommu.c5
-rw-r--r--mm/oom_kill.c34
-rw-r--r--mm/page-writeback.c5
-rw-r--r--mm/page_alloc.c159
-rw-r--r--mm/percpu.c3
-rw-r--r--mm/readahead.c3
-rw-r--r--mm/rmap.c20
-rw-r--r--mm/shmem.c440
-rw-r--r--mm/slab.c512
-rw-r--r--mm/slab.h24
-rw-r--r--mm/slab_common.c101
-rw-r--r--mm/slub.c221
-rw-r--r--mm/swap.c54
-rw-r--r--mm/swap_state.c9
-rw-r--r--mm/swapfile.c21
-rw-r--r--mm/truncate.c9
-rw-r--r--mm/util.c111
-rw-r--r--mm/vmalloc.c30
-rw-r--r--mm/vmscan.c286
-rw-r--r--mm/vmstat.c9
-rw-r--r--mm/zbud.c98
-rw-r--r--mm/zpool.c364
-rw-r--r--mm/zsmalloc.c86
-rw-r--r--mm/zswap.c81
-rw-r--r--net/6lowpan/Kconfig6
-rw-r--r--net/6lowpan/Makefile3
-rw-r--r--net/6lowpan/iphc.c (renamed from net/ieee802154/6lowpan_iphc.c)296
-rw-r--r--net/802/fc.c2
-rw-r--r--net/802/fddi.c3
-rw-r--r--net/802/hippi.c3
-rw-r--r--net/8021q/vlan.c24
-rw-r--r--net/8021q/vlan_core.c53
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/8021q/vlanproc.c2
-rw-r--r--net/9p/client.c1
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile3
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/appletalk/dev.c3
-rw-r--r--net/atm/br2684.c4
-rw-r--r--net/atm/clip.c3
-rw-r--r--net/atm/lec.c5
-rw-r--r--net/atm/svc.c60
-rw-r--r--net/batman-adv/bat_iv_ogm.c13
-rw-r--r--net/batman-adv/distributed-arp-table.c3
-rw-r--r--net/batman-adv/fragmentation.c10
-rw-r--r--net/batman-adv/hash.c6
-rw-r--r--net/batman-adv/main.h22
-rw-r--r--net/batman-adv/multicast.c1
-rw-r--r--net/batman-adv/routing.c18
-rw-r--r--net/batman-adv/soft-interface.c4
-rw-r--r--net/batman-adv/sysfs.c24
-rw-r--r--net/bluetooth/6lowpan.c857
-rw-r--r--net/bluetooth/6lowpan.h47
-rw-r--r--net/bluetooth/Kconfig7
-rw-r--r--net/bluetooth/Makefile4
-rw-r--r--net/bluetooth/a2mp.c8
-rw-r--r--net/bluetooth/af_bluetooth.c2
-rw-r--r--net/bluetooth/amp.c6
-rw-r--r--net/bluetooth/bnep/core.c5
-rw-r--r--net/bluetooth/cmtp/capi.c6
-rw-r--r--net/bluetooth/hci_conn.c191
-rw-r--r--net/bluetooth/hci_core.c1198
-rw-r--r--net/bluetooth/hci_event.c815
-rw-r--r--net/bluetooth/hci_sock.c33
-rw-r--r--net/bluetooth/hidp/core.c2
-rw-r--r--net/bluetooth/l2cap_core.c174
-rw-r--r--net/bluetooth/l2cap_sock.c53
-rw-r--r--net/bluetooth/mgmt.c1399
-rw-r--r--net/bluetooth/rfcomm/core.c10
-rw-r--r--net/bluetooth/rfcomm/sock.c3
-rw-r--r--net/bluetooth/sco.c125
-rw-r--r--net/bluetooth/smp.c246
-rw-r--r--net/bluetooth/smp.h7
-rw-r--r--net/bridge/br_fdb.c26
-rw-r--r--net/bridge/br_if.c2
-rw-r--r--net/bridge/br_multicast.c39
-rw-r--r--net/bridge/br_netlink.c1
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_vlan.c8
-rw-r--r--net/bridge/netfilter/Kconfig25
-rw-r--r--net/bridge/netfilter/Makefile5
-rw-r--r--net/bridge/netfilter/ebt_log.c47
-rw-r--r--net/bridge/netfilter/ebt_ulog.c393
-rw-r--r--net/bridge/netfilter/ebtables.c10
-rw-r--r--net/bridge/netfilter/nf_log_bridge.c96
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c67
-rw-r--r--net/caif/caif_socket.c3
-rw-r--r--net/caif/cfctrl.c1
-rw-r--r--net/ceph/crypto.c26
-rw-r--r--net/ceph/messenger.c47
-rw-r--r--net/ceph/osd_client.c129
-rw-r--r--net/core/dev.c55
-rw-r--r--net/core/drop_monitor.c2
-rw-r--r--net/core/filter.c728
-rw-r--r--net/core/flow_dissector.c85
-rw-r--r--net/core/net-sysfs.c154
-rw-r--r--net/core/net_namespace.c10
-rw-r--r--net/core/netclassid_cgroup.c2
-rw-r--r--net/core/netpoll.c3
-rw-r--r--net/core/netprio_cgroup.c2
-rw-r--r--net/core/pktgen.c111
-rw-r--r--net/core/ptp_classifier.c70
-rw-r--r--net/core/request_sock.c43
-rw-r--r--net/core/rtnetlink.c110
-rw-r--r--net/core/skbuff.c75
-rw-r--r--net/core/sock.c52
-rw-r--r--net/core/sock_diag.c4
-rw-r--r--net/core/timestamping.c57
-rw-r--r--net/dcb/dcbnl.c13
-rw-r--r--net/dccp/ipv6.c2
-rw-r--r--net/dccp/minisocks.c4
-rw-r--r--net/dns_resolver/dns_key.c43
-rw-r--r--net/dns_resolver/dns_query.c1
-rw-r--r--net/dsa/dsa.c3
-rw-r--r--net/dsa/slave.c4
-rw-r--r--net/ethernet/eth.c3
-rw-r--r--net/hsr/Makefile3
-rw-r--r--net/hsr/hsr_device.c580
-rw-r--r--net/hsr/hsr_device.h12
-rw-r--r--net/hsr/hsr_forward.c368
-rw-r--r--net/hsr/hsr_forward.h20
-rw-r--r--net/hsr/hsr_framereg.c477
-rw-r--r--net/hsr/hsr_framereg.h45
-rw-r--r--net/hsr/hsr_main.c425
-rw-r--r--net/hsr/hsr_main.h61
-rw-r--r--net/hsr/hsr_netlink.c102
-rw-r--r--net/hsr/hsr_netlink.h11
-rw-r--r--net/hsr/hsr_slave.c196
-rw-r--r--net/hsr/hsr_slave.h38
-rw-r--r--net/ieee802154/6lowpan_rtnl.c16
-rw-r--r--net/ieee802154/Kconfig9
-rw-r--r--net/ieee802154/Makefile5
-rw-r--r--net/ieee802154/af_ieee802154.c26
-rw-r--r--net/ieee802154/dgram.c28
-rw-r--r--net/ieee802154/ieee802154.h2
-rw-r--r--net/ieee802154/netlink.c4
-rw-r--r--net/ieee802154/nl-mac.c48
-rw-r--r--net/ieee802154/nl-phy.c23
-rw-r--r--net/ieee802154/raw.c14
-rw-r--r--net/ieee802154/reassembly.c69
-rw-r--r--net/ieee802154/wpan-class.c10
-rw-r--r--net/ipv4/Kconfig4
-rw-r--r--net/ipv4/Makefile1
-rw-r--r--net/ipv4/cipso_ipv4.c47
-rw-r--r--net/ipv4/datagram.c1
-rw-r--r--net/ipv4/devinet.c36
-rw-r--r--net/ipv4/fib_trie.c2
-rw-r--r--net/ipv4/gre_offload.c2
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/inet_fragment.c318
-rw-r--r--net/ipv4/ip_fragment.c87
-rw-r--r--net/ipv4/ip_output.c13
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ip_tunnel.c31
-rw-r--r--net/ipv4/ip_vti.c54
-rw-r--r--net/ipv4/ipconfig.c5
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/netfilter/Kconfig29
-rw-r--r--net/ipv4/netfilter/Makefile5
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c498
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c6
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c4
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c8
-rw-r--r--net/ipv4/netfilter/nf_log_arp.c149
-rw-r--r--net/ipv4/netfilter/nf_log_ipv4.c385
-rw-r--r--net/ipv4/netfilter/nf_nat_l3proto_ipv4.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c2
-rw-r--r--net/ipv4/ping.c2
-rw-r--r--net/ipv4/proc.c5
-rw-r--r--net/ipv4/raw.c9
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/syncookies.c3
-rw-r--r--net/ipv4/tcp.c38
-rw-r--r--net/ipv4/tcp_input.c211
-rw-r--r--net/ipv4/tcp_ipv4.c242
-rw-r--r--net/ipv4/tcp_memcontrol.c2
-rw-r--r--net/ipv4/tcp_metrics.c7
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv4/tcp_offload.c18
-rw-r--r--net/ipv4/tcp_output.c42
-rw-r--r--net/ipv4/tcp_timer.c4
-rw-r--r--net/ipv4/tcp_vegas.c3
-rw-r--r--net/ipv4/tcp_veno.c2
-rw-r--r--net/ipv4/udp.c156
-rw-r--r--net/ipv4/udp_offload.c76
-rw-r--r--net/ipv4/udp_tunnel.c100
-rw-r--r--net/ipv4/xfrm4_protocol.c2
-rw-r--r--net/ipv6/addrconf.c148
-rw-r--r--net/ipv6/addrlabel.c2
-rw-r--r--net/ipv6/af_inet6.c7
-rw-r--r--net/ipv6/datagram.c1
-rw-r--r--net/ipv6/icmp.c13
-rw-r--r--net/ipv6/ip6_gre.c13
-rw-r--r--net/ipv6/ip6_output.c32
-rw-r--r--net/ipv6/ip6_tunnel.c8
-rw-r--r--net/ipv6/ip6_vti.c55
-rw-r--r--net/ipv6/ip6mr.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c13
-rw-r--r--net/ipv6/ndisc.c58
-rw-r--r--net/ipv6/netfilter/Kconfig5
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c1
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c49
-rw-r--r--net/ipv6/netfilter/nf_log_ipv6.c417
-rw-r--r--net/ipv6/netfilter/nf_nat_l3proto_ipv6.c4
-rw-r--r--net/ipv6/proc.c4
-rw-r--r--net/ipv6/raw.c14
-rw-r--r--net/ipv6/reassembly.c90
-rw-r--r--net/ipv6/sit.c10
-rw-r--r--net/ipv6/syncookies.c2
-rw-r--r--net/ipv6/sysctl_net_ipv6.c9
-rw-r--r--net/ipv6/tcp_ipv6.c237
-rw-r--r--net/ipv6/udp.c131
-rw-r--r--net/irda/af_irda.c1
-rw-r--r--net/irda/ircomm/ircomm_tty.c6
-rw-r--r--net/irda/irda_device.c3
-rw-r--r--net/irda/irlan/irlan_common.c1
-rw-r--r--net/irda/irlan/irlan_eth.c2
-rw-r--r--net/irda/irlap_frame.c2
-rw-r--r--net/irda/irlmp.c3
-rw-r--r--net/iucv/af_iucv.c4
-rw-r--r--net/key/af_key.c3
-rw-r--r--net/l2tp/Kconfig1
-rw-r--r--net/l2tp/l2tp_core.c86
-rw-r--r--net/l2tp/l2tp_eth.c3
-rw-r--r--net/l2tp/l2tp_ip6.c2
-rw-r--r--net/mac80211/Kconfig17
-rw-r--r--net/mac80211/Makefile6
-rw-r--r--net/mac80211/agg-rx.c110
-rw-r--r--net/mac80211/agg-tx.c8
-rw-r--r--net/mac80211/cfg.c558
-rw-r--r--net/mac80211/chan.c861
-rw-r--r--net/mac80211/debugfs_sta.c3
-rw-r--r--net/mac80211/driver-ops.h20
-rw-r--r--net/mac80211/ethtool.c244
-rw-r--r--net/mac80211/ht.c10
-rw-r--r--net/mac80211/ibss.c15
-rw-r--r--net/mac80211/ieee80211_i.h116
-rw-r--r--net/mac80211/iface.c46
-rw-r--r--net/mac80211/key.c3
-rw-r--r--net/mac80211/main.c10
-rw-r--r--net/mac80211/mesh.c4
-rw-r--r--net/mac80211/mesh_hwmp.c1
-rw-r--r--net/mac80211/mesh_plink.c30
-rw-r--r--net/mac80211/mlme.c156
-rw-r--r--net/mac80211/offchannel.c6
-rw-r--r--net/mac80211/pm.c6
-rw-r--r--net/mac80211/rate.h13
-rw-r--r--net/mac80211/rc80211_pid.h278
-rw-r--r--net/mac80211/rc80211_pid_algo.c478
-rw-r--r--net/mac80211/rc80211_pid_debugfs.c228
-rw-r--r--net/mac80211/rx.c67
-rw-r--r--net/mac80211/scan.c118
-rw-r--r--net/mac80211/sta_info.c204
-rw-r--r--net/mac80211/sta_info.h21
-rw-r--r--net/mac80211/status.c7
-rw-r--r--net/mac80211/tdls.c674
-rw-r--r--net/mac80211/trace.h7
-rw-r--r--net/mac80211/tx.c170
-rw-r--r--net/mac80211/util.c285
-rw-r--r--net/mac80211/vht.c4
-rw-r--r--net/mac80211/wep.c20
-rw-r--r--net/mac80211/wpa.c2
-rw-r--r--net/mac802154/ieee802154_dev.c70
-rw-r--r--net/mac802154/llsec.c1
-rw-r--r--net/mac802154/mib.c7
-rw-r--r--net/mac802154/tx.c1
-rw-r--r--net/netfilter/Kconfig4
-rw-r--r--net/netfilter/Makefile3
-rw-r--r--net/netfilter/core.c11
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c105
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c2
-rw-r--r--net/netfilter/nf_conntrack_core.c68
-rw-r--r--net/netfilter/nf_conntrack_ecache.c96
-rw-r--r--net/netfilter/nf_conntrack_netlink.c3
-rw-r--r--net/netfilter/nf_log.c155
-rw-r--r--net/netfilter/nf_log_common.c187
-rw-r--r--net/netfilter/nf_nat_core.c2
-rw-r--r--net/netfilter/nf_nat_proto_common.c2
-rw-r--r--net/netfilter/nf_nat_proto_dccp.c2
-rw-r--r--net/netfilter/nf_nat_proto_sctp.c2
-rw-r--r--net/netfilter/nf_nat_proto_tcp.c2
-rw-r--r--net/netfilter/nf_nat_proto_udp.c2
-rw-r--r--net/netfilter/nf_nat_proto_udplite.c2
-rw-r--r--net/netfilter/nf_sockopt.c8
-rw-r--r--net/netfilter/nf_tables_api.c168
-rw-r--r--net/netfilter/nfnetlink_acct.c12
-rw-r--r--net/netfilter/nfnetlink_log.c4
-rw-r--r--net/netfilter/nft_hash.c291
-rw-r--r--net/netfilter/nft_log.c98
-rw-r--r--net/netfilter/x_tables.c70
-rw-r--r--net/netfilter/xt_LED.c14
-rw-r--r--net/netfilter/xt_LOG.c884
-rw-r--r--net/netfilter/xt_bpf.c6
-rw-r--r--net/netfilter/xt_hashlimit.c31
-rw-r--r--net/netlabel/netlabel_kapi.c328
-rw-r--r--net/netlink/af_netlink.c313
-rw-r--r--net/netlink/af_netlink.h19
-rw-r--r--net/netlink/diag.c14
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/nfc/digital.h3
-rw-r--r--net/nfc/digital_core.c27
-rw-r--r--net/nfc/digital_dep.c13
-rw-r--r--net/nfc/digital_technology.c96
-rw-r--r--net/nfc/hci/core.c7
-rw-r--r--net/nfc/nci/ntf.c4
-rw-r--r--net/openvswitch/actions.c50
-rw-r--r--net/openvswitch/datapath.c57
-rw-r--r--net/openvswitch/datapath.h2
-rw-r--r--net/openvswitch/vport-internal_dev.c24
-rw-r--r--net/openvswitch/vport-internal_dev.h2
-rw-r--r--net/openvswitch/vport-vxlan.c5
-rw-r--r--net/openvswitch/vport.c103
-rw-r--r--net/openvswitch/vport.h27
-rw-r--r--net/packet/af_packet.c14
-rw-r--r--net/phonet/pep-gprs.c2
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/rxrpc/ar-key.c167
-rw-r--r--net/sched/act_mirred.c2
-rw-r--r--net/sched/cls_api.c11
-rw-r--r--net/sched/cls_bpf.c12
-rw-r--r--net/sched/cls_tcindex.c2
-rw-r--r--net/sched/em_canid.c7
-rw-r--r--net/sched/sch_generic.c4
-rw-r--r--net/sched/sch_teql.c4
-rw-r--r--net/sctp/Makefile2
-rw-r--r--net/sctp/command.c68
-rw-r--r--net/sctp/input.c5
-rw-r--r--net/sctp/ipv6.c156
-rw-r--r--net/sctp/output.c73
-rw-r--r--net/sctp/outqueue.c5
-rw-r--r--net/sctp/protocol.c12
-rw-r--r--net/sctp/sm_statefuns.c4
-rw-r--r--net/sctp/socket.c327
-rw-r--r--net/sctp/sysctl.c5
-rw-r--r--net/sctp/transport.c21
-rw-r--r--net/sctp/ulpevent.c65
-rw-r--r--net/socket.c55
-rw-r--r--net/sunrpc/addr.c16
-rw-r--r--net/sunrpc/auth.c68
-rw-r--r--net/sunrpc/auth_generic.c6
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c126
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_crypto.c9
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_seal.c28
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_wrap.c20
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c2
-rw-r--r--net/sunrpc/auth_null.c2
-rw-r--r--net/sunrpc/clnt.c5
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/sched.c4
-rw-r--r--net/sunrpc/svc.c4
-rw-r--r--net/sunrpc/svc_xprt.c27
-rw-r--r--net/sunrpc/svcsock.c50
-rw-r--r--net/sunrpc/xdr.c3
-rw-r--r--net/sunrpc/xprt.c3
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c83
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c28
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c39
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c20
-rw-r--r--net/sunrpc/xprtrdma/transport.c17
-rw-r--r--net/sunrpc/xprtrdma/verbs.c739
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h61
-rw-r--r--net/sunrpc/xprtsock.c9
-rw-r--r--net/tipc/bcast.c87
-rw-r--r--net/tipc/bcast.h5
-rw-r--r--net/tipc/link.c794
-rw-r--r--net/tipc/link.h7
-rw-r--r--net/tipc/msg.c381
-rw-r--r--net/tipc/msg.h35
-rw-r--r--net/tipc/name_distr.c76
-rw-r--r--net/tipc/name_distr.h2
-rw-r--r--net/tipc/net.c63
-rw-r--r--net/tipc/net.h2
-rw-r--r--net/tipc/node.c38
-rw-r--r--net/tipc/node.h17
-rw-r--r--net/tipc/node_subscr.c6
-rw-r--r--net/tipc/port.c440
-rw-r--r--net/tipc/port.h50
-rw-r--r--net/tipc/socket.c551
-rw-r--r--net/tipc/socket.h16
-rw-r--r--net/wireless/Kconfig6
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/ethtool.c86
-rw-r--r--net/wireless/ethtool.h6
-rw-r--r--net/wireless/genregdb.awk35
-rw-r--r--net/wireless/nl80211.c18
-rw-r--r--net/wireless/rdev-ops.h54
-rw-r--r--net/wireless/trace.h59
-rw-r--r--net/xfrm/xfrm_policy.c4
-rw-r--r--samples/trace_events/trace-events-sample.h2
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Kbuild.include14
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.clean4
-rw-r--r--scripts/Makefile.extrawarn21
-rw-r--r--scripts/Makefile.host61
-rw-r--r--scripts/Makefile.modinst2
-rwxr-xr-xscripts/analyze_suspend.py3817
-rw-r--r--scripts/basic/.gitignore1
-rw-r--r--scripts/basic/Makefile1
-rw-r--r--scripts/basic/bin2c.c (renamed from scripts/bin2c.c)7
-rwxr-xr-xscripts/checkpatch.pl581
-rwxr-xr-xscripts/checkstack.pl12
-rw-r--r--scripts/coccinelle/api/alloc/alloc_cast.cocci72
-rw-r--r--scripts/coccinelle/api/devm_ioremap_resource.cocci90
-rw-r--r--scripts/coccinelle/free/ifnullfree.cocci53
-rw-r--r--scripts/coccinelle/misc/array_size.cocci87
-rw-r--r--scripts/coccinelle/misc/badty.cocci76
-rw-r--r--scripts/coccinelle/misc/bugon.cocci (renamed from scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci)47
-rw-r--r--scripts/coccinelle/null/badzero.cocci3
-rwxr-xr-xscripts/get_maintainer.pl22
-rw-r--r--scripts/mod/modpost.c58
-rw-r--r--scripts/selinux/genheaders/Makefile1
-rw-r--r--scripts/selinux/mdp/Makefile2
-rwxr-xr-xscripts/tags.sh2
-rw-r--r--security/apparmor/domain.c4
-rw-r--r--security/capability.c6
-rw-r--r--security/commoncap.c75
-rw-r--r--security/device_cgroup.c2
-rw-r--r--security/integrity/digsig.c28
-rw-r--r--security/integrity/ima/Kconfig10
-rw-r--r--security/integrity/ima/ima.h15
-rw-r--r--security/integrity/ima/ima_appraise.c10
-rw-r--r--security/integrity/ima/ima_crypto.c312
-rw-r--r--security/integrity/ima/ima_main.c28
-rw-r--r--security/integrity/ima/ima_policy.c13
-rw-r--r--security/integrity/integrity.h14
-rw-r--r--security/keys/big_key.c41
-rw-r--r--security/keys/gc.c11
-rw-r--r--security/keys/key.c49
-rw-r--r--security/keys/keyctl.c21
-rw-r--r--security/keys/keyring.c34
-rw-r--r--security/keys/request_key.c23
-rw-r--r--security/keys/request_key_auth.c13
-rw-r--r--security/keys/user_defined.c41
-rw-r--r--security/security.c11
-rw-r--r--security/selinux/hooks.c14
-rw-r--r--security/selinux/include/netif.h2
-rw-r--r--security/selinux/include/netnode.h2
-rw-r--r--security/selinux/include/netport.h2
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/netif.c19
-rw-r--r--security/selinux/netnode.c18
-rw-r--r--security/selinux/netport.c18
-rw-r--r--security/selinux/ss/conditional.c11
-rw-r--r--security/selinux/ss/ebitmap.c133
-rw-r--r--security/selinux/ss/ebitmap.h8
-rw-r--r--security/selinux/ss/policydb.c141
-rw-r--r--security/selinux/ss/services.c41
-rw-r--r--security/smack/smack_access.c11
-rw-r--r--security/smack/smack_lsm.c6
-rw-r--r--security/smack/smackfs.c14
-rw-r--r--security/tomoyo/audit.c8
-rw-r--r--security/tomoyo/common.c4
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c12
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c12
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/control.c6
-rw-r--r--sound/core/pcm_compat.c8
-rw-r--r--sound/core/pcm_dmaengine.c4
-rw-r--r--sound/core/pcm_native.c9
-rw-r--r--sound/core/seq/seq_memory.c4
-rw-r--r--sound/firewire/Kconfig14
-rw-r--r--sound/firewire/fireworks/fireworks_proc.c4
-rw-r--r--sound/oss/kahlua.c2
-rw-r--r--sound/oss/mpu401.c2
-rw-r--r--sound/oss/opl3.c4
-rw-r--r--sound/oss/pss.c46
-rw-r--r--sound/oss/uart401.c40
-rw-r--r--sound/oss/waveartist.c157
-rw-r--r--sound/pci/Kconfig4
-rw-r--r--sound/pci/ad1889.c2
-rw-r--r--sound/pci/ali5451/ali5451.c2
-rw-r--r--sound/pci/als300.c2
-rw-r--r--sound/pci/als4000.c2
-rw-r--r--sound/pci/asihpi/asihpi.c2
-rw-r--r--sound/pci/atiixp.c2
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/au88x0/au8810.c2
-rw-r--r--sound/pci/au88x0/au8820.c2
-rw-r--r--sound/pci/au88x0/au8830.c2
-rw-r--r--sound/pci/aw2/aw2-alsa.c2
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106_main.c2
-rw-r--r--sound/pci/cmipci.c4
-rw-r--r--sound/pci/cs4281.c2
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs5530.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c2
-rw-r--r--sound/pci/ctxfi/xfi.c2
-rw-r--r--sound/pci/echoaudio/darla20.c2
-rw-r--r--sound/pci/echoaudio/darla24.c2
-rw-r--r--sound/pci/echoaudio/echo3g.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c6
-rw-r--r--sound/pci/echoaudio/gina20.c2
-rw-r--r--sound/pci/echoaudio/gina24.c2
-rw-r--r--sound/pci/echoaudio/indigo.c2
-rw-r--r--sound/pci/echoaudio/indigodj.c2
-rw-r--r--sound/pci/echoaudio/indigodjx.c2
-rw-r--r--sound/pci/echoaudio/indigoio.c2
-rw-r--r--sound/pci/echoaudio/indigoiox.c2
-rw-r--r--sound/pci/echoaudio/layla20.c2
-rw-r--r--sound/pci/echoaudio/layla24.c2
-rw-r--r--sound/pci/echoaudio/mia.c2
-rw-r--r--sound/pci/echoaudio/mona.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c2
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/es1968.c2
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/dell_wmi_helper.c76
-rw-r--r--sound/pci/hda/hda_auto_parser.c17
-rw-r--r--sound/pci/hda/hda_codec.c45
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_controller.c203
-rw-r--r--sound/pci/hda/hda_controller.h9
-rw-r--r--sound/pci/hda/hda_eld.c46
-rw-r--r--sound/pci/hda/hda_generic.c22
-rw-r--r--sound/pci/hda/hda_i915.c4
-rw-r--r--sound/pci/hda/hda_intel.c379
-rw-r--r--sound/pci/hda/hda_local.h9
-rw-r--r--sound/pci/hda/hda_priv.h253
-rw-r--r--sound/pci/hda/hda_tegra.c36
-rw-r--r--sound/pci/hda/patch_ca0132.c13
-rw-r--r--sound/pci/hda/patch_cirrus.c4
-rw-r--r--sound/pci/hda/patch_cmedia.c639
-rw-r--r--sound/pci/hda/patch_conexant.c2637
-rw-r--r--sound/pci/hda/patch_hdmi.c13
-rw-r--r--sound/pci/hda/patch_realtek.c205
-rw-r--r--sound/pci/hda/patch_sigmatel.c29
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/ice1712/ice1712.h15
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c2
-rw-r--r--sound/pci/intel8x0m.c2
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/lola/lola.c2
-rw-r--r--sound/pci/lx6464es/lx6464es.c2
-rw-r--r--sound/pci/maestro3.c2
-rw-r--r--sound/pci/mixart/mixart.c2
-rw-r--r--sound/pci/mixart/mixart_core.c4
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/oxygen/oxygen.c2
-rw-r--r--sound/pci/oxygen/virtuoso.c3
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c12
-rw-r--r--sound/pci/pcxhr/pcxhr.c2
-rw-r--r--sound/pci/riptide/riptide.c8
-rw-r--r--sound/pci/rme32.c2
-rw-r--r--sound/pci/rme96.c2
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pci/rme9652/rme9652.c2
-rw-r--r--sound/pci/sis7019.c2
-rw-r--r--sound/pci/sonicvibes.c2
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/trident/trident_main.c2
-rw-r--r--sound/pci/trident/trident_memory.c3
-rw-r--r--sound/pci/via82xx.c2
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c2
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/ppc/pmac.c6
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c34
-rw-r--r--sound/soc/atmel/atmel_wm8904.c50
-rw-r--r--sound/soc/au1x/psc-ac97.c140
-rw-r--r--sound/soc/au1x/psc-i2s.c100
-rw-r--r--sound/soc/au1x/psc.h22
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c8
-rw-r--r--sound/soc/codecs/88pm860x-codec.c12
-rw-r--r--sound/soc/codecs/Kconfig27
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ac97.c4
-rw-r--r--sound/soc/codecs/adau1701.c6
-rw-r--r--sound/soc/codecs/adau17x1.c8
-rw-r--r--sound/soc/codecs/adau1977.c2
-rw-r--r--sound/soc/codecs/ak4642.c4
-rw-r--r--sound/soc/codecs/ak5386.c50
-rw-r--r--sound/soc/codecs/arizona.c298
-rw-r--r--sound/soc/codecs/arizona.h1
-rw-r--r--sound/soc/codecs/cs4265.c682
-rw-r--r--sound/soc/codecs/cs4265.h64
-rw-r--r--sound/soc/codecs/cs4270.c4
-rw-r--r--sound/soc/codecs/cs42l52.c14
-rw-r--r--sound/soc/codecs/cs42l56.c76
-rw-r--r--sound/soc/codecs/cs42l73.c6
-rw-r--r--sound/soc/codecs/cs42xx8.c5
-rw-r--r--sound/soc/codecs/cs42xx8.h8
-rw-r--r--sound/soc/codecs/cx20442.c10
-rw-r--r--sound/soc/codecs/max98088.c6
-rw-r--r--sound/soc/codecs/max98090.c44
-rw-r--r--sound/soc/codecs/max98095.c12
-rw-r--r--sound/soc/codecs/mc13783.c6
-rw-r--r--sound/soc/codecs/pcm1792a.c3
-rw-r--r--sound/soc/codecs/pcm1792a.h3
-rw-r--r--sound/soc/codecs/rl6231.c19
-rw-r--r--sound/soc/codecs/rt286.c1222
-rw-r--r--sound/soc/codecs/rt286.h198
-rw-r--r--sound/soc/codecs/rt5631.c10
-rw-r--r--sound/soc/codecs/rt5640.c10
-rw-r--r--sound/soc/codecs/rt5645.c10
-rw-r--r--sound/soc/codecs/rt5651.c10
-rw-r--r--sound/soc/codecs/rt5670-dsp.h54
-rw-r--r--sound/soc/codecs/rt5670.c2657
-rw-r--r--sound/soc/codecs/rt5670.h2000
-rw-r--r--sound/soc/codecs/rt5677.c272
-rw-r--r--sound/soc/codecs/rt5677.h15
-rw-r--r--sound/soc/codecs/sgtl5000.c25
-rw-r--r--sound/soc/codecs/si476x.c10
-rw-r--r--sound/soc/codecs/sirf-audio-codec.c4
-rw-r--r--sound/soc/codecs/sn95031.c6
-rw-r--r--sound/soc/codecs/spdif_transmitter.c2
-rw-r--r--sound/soc/codecs/ssm2518.c6
-rw-r--r--sound/soc/codecs/ssm2602.c10
-rw-r--r--sound/soc/codecs/sta32x.c19
-rw-r--r--sound/soc/codecs/sta529.c12
-rw-r--r--sound/soc/codecs/tas2552.c544
-rw-r--r--sound/soc/codecs/tas2552.h129
-rw-r--r--sound/soc/codecs/tas5086.c75
-rw-r--r--sound/soc/codecs/tlv320aic23.c10
-rw-r--r--sound/soc/codecs/tlv320aic26.c14
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c40
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c31
-rw-r--r--sound/soc/codecs/tlv320aic3x.c21
-rw-r--r--sound/soc/codecs/tlv320dac33.c12
-rw-r--r--sound/soc/codecs/tpa6130a2.c4
-rw-r--r--sound/soc/codecs/twl4030.c19
-rw-r--r--sound/soc/codecs/uda134x.c10
-rw-r--r--sound/soc/codecs/wl1273.c9
-rw-r--r--sound/soc/codecs/wm0010.c14
-rw-r--r--sound/soc/codecs/wm1250-ev1.c1
-rw-r--r--sound/soc/codecs/wm2000.c4
-rw-r--r--sound/soc/codecs/wm5100.c3
-rw-r--r--sound/soc/codecs/wm5102.c65
-rw-r--r--sound/soc/codecs/wm5110.c4
-rw-r--r--sound/soc/codecs/wm8350.c13
-rw-r--r--sound/soc/codecs/wm8400.c10
-rw-r--r--sound/soc/codecs/wm8510.c10
-rw-r--r--sound/soc/codecs/wm8523.c10
-rw-r--r--sound/soc/codecs/wm8580.c10
-rw-r--r--sound/soc/codecs/wm8711.c8
-rw-r--r--sound/soc/codecs/wm8728.c8
-rw-r--r--sound/soc/codecs/wm8731.c8
-rw-r--r--sound/soc/codecs/wm8737.c10
-rw-r--r--sound/soc/codecs/wm8741.c14
-rw-r--r--sound/soc/codecs/wm8750.c10
-rw-r--r--sound/soc/codecs/wm8753.c20
-rw-r--r--sound/soc/codecs/wm8770.c10
-rw-r--r--sound/soc/codecs/wm8804.c10
-rw-r--r--sound/soc/codecs/wm8900.c10
-rw-r--r--sound/soc/codecs/wm8903.c13
-rw-r--r--sound/soc/codecs/wm8904.c27
-rw-r--r--sound/soc/codecs/wm8940.c12
-rw-r--r--sound/soc/codecs/wm8955.c10
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c24
-rw-r--r--sound/soc/codecs/wm8960.c17
-rw-r--r--sound/soc/codecs/wm8961.c10
-rw-r--r--sound/soc/codecs/wm8962.c29
-rw-r--r--sound/soc/codecs/wm8971.c10
-rw-r--r--sound/soc/codecs/wm8974.c10
-rw-r--r--sound/soc/codecs/wm8978.c14
-rw-r--r--sound/soc/codecs/wm8983.c12
-rw-r--r--sound/soc/codecs/wm8985.c15
-rw-r--r--sound/soc/codecs/wm8988.c10
-rw-r--r--sound/soc/codecs/wm8990.c10
-rw-r--r--sound/soc/codecs/wm8991.c10
-rw-r--r--sound/soc/codecs/wm8993.c10
-rw-r--r--sound/soc/codecs/wm8994.c35
-rw-r--r--sound/soc/codecs/wm8995.c12
-rw-r--r--sound/soc/codecs/wm8996.c6
-rw-r--r--sound/soc/codecs/wm8997.c2
-rw-r--r--sound/soc/codecs/wm9081.c10
-rw-r--r--sound/soc/codecs/wm9090.c4
-rw-r--r--sound/soc/codecs/wm9713.c10
-rw-r--r--sound/soc/codecs/wm_adsp.c6
-rw-r--r--sound/soc/codecs/wm_hubs.c4
-rw-r--r--sound/soc/davinci/Kconfig25
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c93
-rw-r--r--sound/soc/davinci/edma-pcm.c2
-rw-r--r--sound/soc/davinci/edma-pcm.h7
-rw-r--r--sound/soc/fsl/Kconfig16
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/fsl_asrc.c995
-rw-r--r--sound/soc/fsl/fsl_asrc.h461
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c391
-rw-r--r--sound/soc/fsl/fsl_esai.c2
-rw-r--r--sound/soc/fsl/fsl_sai.c39
-rw-r--r--sound/soc/fsl/fsl_spdif.c88
-rw-r--r--sound/soc/fsl/fsl_spdif.h10
-rw-r--r--sound/soc/fsl/fsl_ssi.c6
-rw-r--r--sound/soc/fsl/imx-audmux.c8
-rw-r--r--sound/soc/generic/simple-card.c13
-rw-r--r--sound/soc/intel/Kconfig12
-rw-r--r--sound/soc/intel/Makefile2
-rw-r--r--sound/soc/intel/broadwell.c251
-rw-r--r--sound/soc/intel/byt-max98090.c27
-rw-r--r--sound/soc/intel/byt-rt5640.c1
-rw-r--r--sound/soc/intel/sst-atom-controls.h30
-rw-r--r--sound/soc/intel/sst-baytrail-ipc.c30
-rw-r--r--sound/soc/intel/sst-baytrail-pcm.c2
-rw-r--r--sound/soc/intel/sst-dsp.c10
-rw-r--r--sound/soc/intel/sst-dsp.h39
-rw-r--r--sound/soc/intel/sst-haswell-dsp.c70
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c40
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c27
-rw-r--r--sound/soc/intel/sst-mfld-dsp.h429
-rw-r--r--sound/soc/intel/sst-mfld-platform-compress.c11
-rw-r--r--sound/soc/intel/sst-mfld-platform-pcm.c319
-rw-r--r--sound/soc/intel/sst-mfld-platform.h29
-rw-r--r--sound/soc/kirkwood/Kconfig19
-rw-r--r--sound/soc/kirkwood/Makefile4
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c11
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c33
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c109
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c116
-rw-r--r--sound/soc/kirkwood/kirkwood.h7
-rw-r--r--sound/soc/omap/ams-delta.c2
-rw-r--r--sound/soc/omap/omap-dmic.c35
-rw-r--r--sound/soc/omap/omap-mcbsp.c7
-rw-r--r--sound/soc/omap/omap-pcm.c1
-rw-r--r--sound/soc/pxa/pxa-ssp.c3
-rw-r--r--sound/soc/rockchip/Kconfig12
-rw-r--r--sound/soc/rockchip/Makefile4
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c529
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h223
-rw-r--r--sound/soc/s6000/Kconfig13
-rw-r--r--sound/soc/s6000/Makefile2
-rw-r--r--sound/soc/s6000/s6000-i2s.c4
-rw-r--r--sound/soc/s6000/s6105-ipcam.c17
-rw-r--r--sound/soc/samsung/Kconfig40
-rw-r--r--sound/soc/samsung/Makefile6
-rw-r--r--sound/soc/samsung/ac97.c32
-rw-r--r--sound/soc/samsung/dma.c454
-rw-r--r--sound/soc/samsung/dma.h7
-rw-r--r--sound/soc/samsung/dmaengine.c3
-rw-r--r--sound/soc/samsung/goni_wm8994.c2
-rw-r--r--sound/soc/samsung/i2s.c35
-rw-r--r--sound/soc/samsung/idma.c3
-rw-r--r--sound/soc/samsung/odroidx2_max98090.c177
-rw-r--r--sound/soc/samsung/pcm.c12
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c19
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c43
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c58
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c2
-rw-r--r--sound/soc/samsung/snow.c4
-rw-r--r--sound/soc/samsung/spdif.c5
-rw-r--r--sound/soc/sh/Kconfig2
-rw-r--r--sound/soc/sh/fsi.c201
-rw-r--r--sound/soc/sh/rcar/core.c247
-rw-r--r--sound/soc/sh/rcar/dvc.c135
-rw-r--r--sound/soc/sh/rcar/gen.c554
-rw-r--r--sound/soc/sh/rcar/rsnd.h26
-rw-r--r--sound/soc/sh/rcar/src.c86
-rw-r--r--sound/soc/sh/rcar/ssi.c33
-rw-r--r--sound/soc/sirf/Kconfig6
-rw-r--r--sound/soc/sirf/Makefile2
-rw-r--r--sound/soc/sirf/sirf-usp.c415
-rw-r--r--sound/soc/sirf/sirf-usp.h293
-rw-r--r--sound/soc/soc-cache.c7
-rw-r--r--sound/soc/soc-compress.c13
-rw-r--r--sound/soc/soc-core.c900
-rw-r--r--sound/soc/soc-dapm.c279
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c37
-rw-r--r--sound/soc/soc-jack.c4
-rw-r--r--sound/soc/soc-pcm.c581
-rw-r--r--sound/soc/tegra/tegra_alc5632.c5
-rw-r--r--sound/soc/tegra/tegra_max98090.c5
-rw-r--r--sound/soc/tegra/tegra_rt5640.c5
-rw-r--r--sound/soc/tegra/tegra_wm8753.c3
-rw-r--r--sound/soc/tegra/tegra_wm8903.c5
-rw-r--r--sound/soc/tegra/trimslice.c3
-rw-r--r--sound/sparc/dbri.c6
-rw-r--r--sound/usb/card.c9
-rw-r--r--sound/usb/midi.c401
-rw-r--r--sound/usb/midi.h6
-rw-r--r--sound/usb/mixer.c9
-rw-r--r--sound/usb/quirks-table.h29
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--tools/hv/hv_fcopy_daemon.c3
-rw-r--r--tools/lib/traceevent/event-parse.c6
-rw-r--r--tools/lib/traceevent/plugin_cfg80211.c3
-rw-r--r--tools/lib/traceevent/plugin_jbd2.c6
-rw-r--r--tools/lib/traceevent/plugin_kvm.c64
-rw-r--r--tools/perf/Documentation/perf-bench.txt4
-rw-r--r--tools/perf/Documentation/perf-inject.txt3
-rw-r--r--tools/perf/Documentation/perf-kvm.txt16
-rw-r--r--tools/perf/Documentation/perf-timechart.txt38
-rw-r--r--tools/perf/Documentation/perf-trace.txt46
-rw-r--r--tools/perf/Documentation/perf.txt10
-rw-r--r--tools/perf/MANIFEST3
-rw-r--r--tools/perf/Makefile.perf4
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/util/header.c4
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c266
-rw-r--r--tools/perf/arch/s390/Makefile3
-rw-r--r--tools/perf/arch/s390/util/header.c28
-rw-r--r--tools/perf/arch/s390/util/kvm-stat.c105
-rw-r--r--tools/perf/arch/x86/Makefile2
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/x86/util/kvm-stat.c156
-rw-r--r--tools/perf/arch/x86/util/tsc.c31
-rw-r--r--tools/perf/arch/x86/util/tsc.h3
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c1
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/futex-requeue.c10
-rw-r--r--tools/perf/bench/futex-wake.c12
-rw-r--r--tools/perf/bench/mem-memcpy.c9
-rw-r--r--tools/perf/bench/mem-memset.c9
-rw-r--r--tools/perf/bench/sched-messaging.c47
-rw-r--r--tools/perf/builtin-bench.c7
-rw-r--r--tools/perf/builtin-buildid-cache.c8
-rw-r--r--tools/perf/builtin-evlist.c1
-rw-r--r--tools/perf/builtin-help.c1
-rw-r--r--tools/perf/builtin-inject.c5
-rw-r--r--tools/perf/builtin-kvm.c414
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-sched.c16
-rw-r--r--tools/perf/builtin-script.c60
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-timechart.c694
-rw-r--r--tools/perf/builtin-trace.c266
-rw-r--r--tools/perf/config/Makefile14
-rw-r--r--tools/perf/config/feature-checks/Makefile4
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-sync-compare-and-swap.c14
-rw-r--r--tools/perf/perf-sys.h1
-rw-r--r--tools/perf/perf.c13
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record3
-rw-r--r--tools/perf/scripts/perl/failed-syscalls.pl5
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py3
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record3
-rw-r--r--tools/perf/scripts/python/bin/sctop-record3
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record3
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record3
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py4
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py7
-rw-r--r--tools/perf/scripts/python/futex-contention.py4
-rwxr-xr-xtools/perf/scripts/python/net_dropmonitor.py2
-rw-r--r--tools/perf/scripts/python/netdev-times.py26
-rw-r--r--tools/perf/scripts/python/sched-migration.py41
-rw-r--r--tools/perf/scripts/python/sctop.py7
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py7
-rw-r--r--tools/perf/scripts/python/syscall-counts.py7
-rw-r--r--tools/perf/tests/attr/base-record3
-rw-r--r--tools/perf/tests/attr/base-stat3
-rw-r--r--tools/perf/tests/bp_signal.c4
-rw-r--r--tools/perf/tests/bp_signal_overflow.c4
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c1
-rw-r--r--tools/perf/tests/evsel-tp-sched.c1
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c1
-rw-r--r--tools/perf/tests/parse-events.c1
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c1
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c12
-rw-r--r--tools/perf/tests/rdpmc.c4
-rw-r--r--tools/perf/tests/sample-parsing.c1
-rw-r--r--tools/perf/tests/thread-mg-share.c1
-rw-r--r--tools/perf/ui/browser.c39
-rw-r--r--tools/perf/ui/browser.h3
-rw-r--r--tools/perf/ui/browsers/hists.c153
-rw-r--r--tools/perf/ui/stdio/hist.c2
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/callchain.h13
-rw-r--r--tools/perf/util/cloexec.c57
-rw-r--r--tools/perf/util/cloexec.h6
-rw-r--r--tools/perf/util/config.c13
-rw-r--r--tools/perf/util/data.c3
-rw-r--r--tools/perf/util/debug.c56
-rw-r--r--tools/perf/util/debug.h22
-rw-r--r--tools/perf/util/dso.c71
-rw-r--r--tools/perf/util/dso.h26
-rw-r--r--tools/perf/util/event.c52
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/evlist.c51
-rw-r--r--tools/perf/util/evsel.c26
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c51
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/include/linux/kernel.h21
-rw-r--r--tools/perf/util/kvm-stat.h140
-rw-r--r--tools/perf/util/machine.c139
-rw-r--r--tools/perf/util/machine.h8
-rw-r--r--tools/perf/util/map.c47
-rw-r--r--tools/perf/util/map.h15
-rw-r--r--tools/perf/util/parse-options.h5
-rw-r--r--tools/perf/util/probe-finder.c1
-rw-r--r--tools/perf/util/pstack.c1
-rw-r--r--tools/perf/util/python.c4
-rw-r--r--tools/perf/util/record.c27
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c197
-rw-r--r--tools/perf/util/session.c39
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/svghelper.c168
-rw-r--r--tools/perf/util/svghelper.h6
-rw-r--r--tools/perf/util/symbol-elf.c41
-rw-r--r--tools/perf/util/symbol-minimal.c43
-rw-r--r--tools/perf/util/symbol.c21
-rw-r--r--tools/perf/util/symbol.h9
-rw-r--r--tools/perf/util/thread.c13
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/trace-event-info.c13
-rw-r--r--tools/perf/util/trace-event-read.c2
-rw-r--r--tools/perf/util/tsc.c30
-rw-r--r--tools/perf/util/tsc.h12
-rw-r--r--tools/perf/util/unwind-libdw.c1
-rw-r--r--tools/perf/util/unwind-libunwind.c1
-rw-r--r--tools/perf/util/util.c10
-rw-r--r--tools/perf/util/vdso.c97
-rw-r--r--tools/perf/util/vdso.h13
-rw-r--r--tools/power/acpi/Makefile5
-rw-r--r--tools/power/acpi/common/cmfsize.c20
-rw-r--r--tools/power/acpi/common/getopt.c14
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslibcfs.c214
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c48
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c1311
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h3
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c108
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c92
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c96
-rw-r--r--tools/power/cpupower/bench/parse.c39
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c11
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c2
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c2
-rwxr-xr-xtools/testing/ktest/ktest.pl581
-rw-r--r--tools/testing/ktest/sample.conf65
-rw-r--r--tools/testing/selftests/Makefile21
-rw-r--r--tools/testing/selftests/README.txt27
-rw-r--r--tools/testing/selftests/cpu-hotplug/Makefile3
-rw-r--r--tools/testing/selftests/cpu-hotplug/on-off-test.sh52
-rw-r--r--tools/testing/selftests/firmware/Makefile27
-rw-r--r--tools/testing/selftests/firmware/fw_filesystem.sh62
-rw-r--r--tools/testing/selftests/firmware/fw_userhelper.sh89
-rw-r--r--tools/testing/selftests/kcmp/kcmp_test.c2
-rw-r--r--tools/testing/selftests/memfd/.gitignore4
-rw-r--r--tools/testing/selftests/memfd/Makefile41
-rw-r--r--tools/testing/selftests/memfd/fuse_mnt.c110
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c311
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c913
-rw-r--r--tools/testing/selftests/memfd/run_fuse_test.sh14
-rw-r--r--tools/testing/selftests/memory-hotplug/Makefile3
-rw-r--r--tools/testing/selftests/memory-hotplug/on-off-test.sh8
-rw-r--r--tools/testing/selftests/mount/Makefile17
-rw-r--r--tools/testing/selftests/mount/unprivileged-remount-test.c242
-rw-r--r--tools/testing/selftests/mqueue/Makefile4
-rw-r--r--tools/testing/selftests/mqueue/mq_open_tests.c20
-rw-r--r--tools/testing/selftests/mqueue/mq_perf_tests.c40
-rw-r--r--tools/testing/selftests/powerpc/Makefile10
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile19
-rw-r--r--tools/testing/selftests/powerpc/pmu/count_instructions.c30
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S271
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c91
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c261
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.h1
-rw-r--r--tools/testing/selftests/powerpc/pmu/l3_bank_test.c48
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c50
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.h1
-rw-r--r--tools/testing/selftests/powerpc/pmu/per_event_excludes.c114
-rw-r--r--tools/testing/selftests/ptrace/peeksiginfo.c4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh8
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh9
-rw-r--r--tools/testing/selftests/rcutorture/bin/kvm.sh21
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE011
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE021
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE02-T1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE031
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE041
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE051
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE061
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE071
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE081
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08-T1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE091
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp1
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt1
-rwxr-xr-xtools/time/udelay_test.sh66
-rw-r--r--tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c39
-rw-r--r--tools/usb/ffs-aio-example/multibuff/host_app/test.c27
-rw-r--r--tools/usb/ffs-aio-example/simple/device_app/aio_simple.c39
-rw-r--r--tools/usb/ffs-aio-example/simple/host_app/test.c27
-rw-r--r--virt/kvm/Kconfig3
-rw-r--r--virt/kvm/arm/vgic-v2.c265
-rw-r--r--virt/kvm/arm/vgic-v3.c247
-rw-r--r--virt/kvm/arm/vgic.c389
-rw-r--r--virt/kvm/eventfd.c134
-rw-r--r--virt/kvm/ioapic.c7
-rw-r--r--virt/kvm/irq_comm.c28
-rw-r--r--virt/kvm/irqchip.c98
-rw-r--r--virt/kvm/kvm_main.c62
9631 files changed, 426210 insertions, 448865 deletions
diff --git a/.gitignore b/.gitignore
index f4c0b091dcf4..e213b27f3921 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@
*.gcno
modules.builtin
Module.symvers
+*.dwo
#
# Top-level generic files
diff --git a/CREDITS b/CREDITS
index a80b66718f66..bb6278884f89 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1381,6 +1381,9 @@ S: 17 rue Danton
S: F - 94270 Le Kremlin-Bicêtre
S: France
+N: Jack Hammer
+D: IBM ServeRAID RAID (ips) driver maintenance
+
N: Greg Hankins
E: gregh@cc.gatech.edu
D: fixed keyboard driver to separate LED and locking status
@@ -1691,6 +1694,10 @@ S: Reading
S: RG6 2NU
S: United Kingdom
+N: Dave Jeffery
+E: dhjeffery@gmail.com
+D: SCSI hacks and IBM ServeRAID RAID driver maintenance
+
N: Jakub Jelinek
E: jakub@redhat.com
W: http://sunsite.mff.cuni.cz/~jj
diff --git a/Documentation/ABI/stable/sysfs-bus-usb b/Documentation/ABI/stable/sysfs-bus-usb
index a6b685724740..e2bc700a6f9c 100644
--- a/Documentation/ABI/stable/sysfs-bus-usb
+++ b/Documentation/ABI/stable/sysfs-bus-usb
@@ -3,13 +3,13 @@ Date: May 2007
KernelVersion: 2.6.23
Contact: Alan Stern <stern@rowland.harvard.edu>
Description:
- If CONFIG_USB_PERSIST is set, then each USB device directory
- will contain a file named power/persist. The file holds a
- boolean value (0 or 1) indicating whether or not the
- "USB-Persist" facility is enabled for the device. Since the
- facility is inherently dangerous, it is disabled by default
- for all devices except hubs. For more information, see
- Documentation/usb/persist.txt.
+ USB device directories can contain a file named power/persist.
+ The file holds a boolean value (0 or 1) indicating whether or
+ not the "USB-Persist" facility is enabled for the device. For
+ hubs this facility is always enabled and their device
+ directories will not contain this file.
+
+ For more information, see Documentation/usb/persist.txt.
What: /sys/bus/usb/devices/.../power/autosuspend
Date: March 2007
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 4c3efe434806..d0d0c578324c 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -26,6 +26,7 @@ Description:
option: [[appraise_type=]] [permit_directio]
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
+ [FIRMWARE_CHECK]
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
fsmagic:= hex value
fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
@@ -57,7 +58,8 @@ Description:
measure func=BPRM_CHECK
measure func=FILE_MMAP mask=MAY_EXEC
measure func=FILE_CHECK mask=MAY_READ uid=0
- measure func=MODULE_CHECK uid=0
+ measure func=MODULE_CHECK
+ measure func=FIRMWARE_CHECK
appraise fowner=0
The default policy measures all executables in bprm_check,
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index a9757dcf2e81..d760b0224ef7 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -260,6 +260,10 @@ What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_tilt_comp_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_scale
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale
KernelVersion: 2.6.35
@@ -447,6 +451,14 @@ What: /sys/.../iio:deviceX/events/in_magn_y_thresh_rising_en
What: /sys/.../iio:deviceX/events/in_magn_y_thresh_falling_en
What: /sys/.../iio:deviceX/events/in_magn_z_thresh_rising_en
What: /sys/.../iio:deviceX/events/in_magn_z_thresh_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_thresh_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_thresh_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_thresh_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_thresh_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_thresh_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_thresh_falling_en
What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_rising_en
What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_falling_en
What: /sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en
@@ -492,6 +504,14 @@ What: /sys/.../iio:deviceX/events/in_magn_y_roc_rising_en
What: /sys/.../iio:deviceX/events/in_magn_y_roc_falling_en
What: /sys/.../iio:deviceX/events/in_magn_z_roc_rising_en
What: /sys/.../iio:deviceX/events/in_magn_z_roc_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_roc_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_roc_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_roc_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_roc_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_roc_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_magnetic_tilt_comp_roc_falling_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_roc_rising_en
+What: /sys/.../iio:deviceX/events/in_rot_from_north_true_tilt_comp_roc_falling_en
What: /sys/.../iio:deviceX/events/in_voltageY_supply_roc_rising_en
What: /sys/.../iio:deviceX/events/in_voltageY_supply_roc_falling_en
What: /sys/.../iio:deviceX/events/in_voltageY_roc_rising_en
@@ -538,6 +558,14 @@ What: /sys/.../events/in_magn_y_raw_thresh_rising_value
What: /sys/.../events/in_magn_y_raw_thresh_falling_value
What: /sys/.../events/in_magn_z_raw_thresh_rising_value
What: /sys/.../events/in_magn_z_raw_thresh_falling_value
+What: /sys/.../events/in_rot_from_north_magnetic_raw_thresh_rising_value
+What: /sys/.../events/in_rot_from_north_magnetic_raw_thresh_falling_value
+What: /sys/.../events/in_rot_from_north_true_raw_thresh_rising_value
+What: /sys/.../events/in_rot_from_north_true_raw_thresh_falling_value
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_thresh_rising_value
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_thresh_falling_value
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_raw_thresh_rising_value
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_raw_thresh_rising_value
@@ -588,6 +616,18 @@ What: /sys/.../events/in_magn_y_thresh_either_hysteresis
What: /sys/.../events/in_magn_z_thresh_rising_hysteresis
What: /sys/.../events/in_magn_z_thresh_falling_hysteresis
What: /sys/.../events/in_magn_z_thresh_either_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_thresh_rising_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_thresh_falling_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_thresh_either_hysteresis
+What: /sys/.../events/in_rot_from_north_true_thresh_rising_hysteresis
+What: /sys/.../events/in_rot_from_north_true_thresh_falling_hysteresis
+What: /sys/.../events/in_rot_from_north_true_thresh_either_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_hysteresis
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_either_hysteresis
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_thresh_rising_hysteresis
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_thresh_falling_hysteresis
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_thresh_either_hysteresis
What: /sys/.../events/in_voltageY_thresh_rising_hysteresis
What: /sys/.../events/in_voltageY_thresh_falling_hysteresis
What: /sys/.../events/in_voltageY_thresh_either_hysteresis
@@ -635,6 +675,14 @@ What: /sys/.../events/in_magn_y_raw_roc_rising_value
What: /sys/.../events/in_magn_y_raw_roc_falling_value
What: /sys/.../events/in_magn_z_raw_roc_rising_value
What: /sys/.../events/in_magn_z_raw_roc_falling_value
+What: /sys/.../events/in_rot_from_north_magnetic_raw_roc_rising_value
+What: /sys/.../events/in_rot_from_north_magnetic_raw_roc_falling_value
+What: /sys/.../events/in_rot_from_north_true_raw_roc_rising_value
+What: /sys/.../events/in_rot_from_north_true_raw_roc_falling_value
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_roc_rising_value
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_raw_roc_falling_value
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_raw_roc_rising_value
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_raw_roc_falling_value
What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value
What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value
What: /sys/.../events/in_voltageY_raw_roc_rising_value
@@ -690,6 +738,22 @@ What: /sys/.../events/in_magn_z_thresh_rising_period
What: /sys/.../events/in_magn_z_thresh_falling_period
What: /sys/.../events/in_magn_z_roc_rising_period
What: /sys/.../events/in_magn_z_roc_falling_period
+What: /sys/.../events/in_rot_from_north_magnetic_thresh_rising_period
+What: /sys/.../events/in_rot_from_north_magnetic_thresh_falling_period
+What: /sys/.../events/in_rot_from_north_magnetic_roc_rising_period
+What: /sys/.../events/in_rot_from_north_magnetic_roc_falling_period
+What: /sys/.../events/in_rot_from_north_true_thresh_rising_period
+What: /sys/.../events/in_rot_from_north_true_thresh_falling_period
+What: /sys/.../events/in_rot_from_north_true_roc_rising_period
+What: /sys/.../events/in_rot_from_north_true_roc_falling_period
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_rising_period
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_thresh_falling_period
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_roc_rising_period
+What: /sys/.../events/in_rot_from_north_magnetic_tilt_comp_roc_falling_period
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_thresh_rising_period
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_thresh_falling_period
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_roc_rising_period
+What: /sys/.../events/in_rot_from_north_true_tilt_comp_roc_falling_period
What: /sys/.../events/in_voltageY_supply_thresh_rising_period
What: /sys/.../events/in_voltageY_supply_thresh_falling_period
What: /sys/.../events/in_voltageY_supply_roc_rising_period
@@ -787,6 +851,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_en
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_en
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_en
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_en
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_en
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en
@@ -853,6 +921,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_index
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_index
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_index
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_magnetic_tilt_comp_index
+What: /sys/.../iio:deviceX/scan_elements/in_rot_from_north_true_tilt_comp_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index
@@ -895,6 +967,19 @@ Description:
on-chip EEPROM. After power-up or chip reset the device will
automatically load the saved configuration.
+What: /sys/.../iio:deviceX/in_proximity_raw
+What: /sys/.../iio:deviceX/in_proximity_input
+What: /sys/.../iio:deviceX/in_proximityY_raw
+KernelVersion: 3.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Proximity measurement indicating that some
+ object is near the sensor, usually be observing
+ reflectivity of infrared or ultrasound emitted.
+ Often these sensors are unit less and as such conversion
+ to SI units is not possible. Where it is, the units should
+ be meters.
+
What: /sys/.../iio:deviceX/in_illuminanceY_input
What: /sys/.../iio:deviceX/in_illuminanceY_raw
What: /sys/.../iio:deviceX/in_illuminanceY_mean_raw
@@ -933,3 +1018,13 @@ Description:
x y z w. Here x, y, and z component represents the axis about
which a rotation will occur and w component represents the
amount of rotation.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_tilt_comp_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_magnetic_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_raw
+KernelVersion: 3.15
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw value of rotation from true/magnetic north measured with
+ or without compensation from tilt sensors.
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
index 5235e6c749ab..5235e6c749ab 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs
+++ b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
diff --git a/Documentation/ABI/testing/sysfs-bus-platform b/Documentation/ABI/testing/sysfs-bus-platform
new file mode 100644
index 000000000000..5172a6124b27
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-platform
@@ -0,0 +1,20 @@
+What: /sys/bus/platform/devices/.../driver_override
+Date: April 2014
+Contact: Kim Phillips <kim.phillips@freescale.com>
+Description:
+ This file allows the driver for a device to be specified which
+ will override standard OF, ACPI, ID table, and name matching.
+ When specified, only a driver with a name matching the value
+ written to driver_override will have an opportunity to bind
+ to the device. The override is specified by writing a string
+ to the driver_override file (echo vfio-platform > \
+ driver_override) and may be cleared with an empty string
+ (echo > driver_override). This returns the device to standard
+ matching rules binding. Writing to driver_override does not
+ automatically unbind the device from its current driver or make
+ any attempt to automatically load the specified driver. If no
+ driver with a matching name is currently loaded in the kernel,
+ the device will not bind to any driver. This also allows
+ devices to opt-out of driver binding using a driver_override
+ name such as "none". Only a single driver may be specified in
+ the override, there is no support for parsing delimiters.
diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd
index 501adc2a9ec7..2ddd680929d8 100644
--- a/Documentation/ABI/testing/sysfs-bus-rbd
+++ b/Documentation/ABI/testing/sysfs-bus-rbd
@@ -94,5 +94,5 @@ current_snap
parent
- Information identifying the pool, image, and snapshot id for
- the parent image in a layered rbd image (format 2 only).
+ Information identifying the chain of parent images in a layered rbd
+ image. Entries are separated by empty lines.
diff --git a/Documentation/ABI/testing/sysfs-bus-usb-lvstest b/Documentation/ABI/testing/sysfs-bus-usb-lvstest
new file mode 100644
index 000000000000..aae68fc2d842
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-usb-lvstest
@@ -0,0 +1,47 @@
+Link Layer Validation Device is a standard device for testing of Super
+Speed Link Layer tests. These nodes are available in sysfs only when lvs
+driver is bound with root hub device.
+
+What: /sys/bus/usb/devices/.../get_dev_desc
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Write to this node to issue "Get Device Descriptor"
+ for Link Layer Validation device. It is needed for TD.7.06.
+
+What: /sys/bus/usb/devices/.../u1_timeout
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Set "U1 timeout" for the downstream port where Link Layer
+ Validation device is connected. Timeout value must be between 0
+ and 127. It is needed for TD.7.18, TD.7.19, TD.7.20 and TD.7.21.
+
+What: /sys/bus/usb/devices/.../u2_timeout
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Set "U2 timeout" for the downstream port where Link Layer
+ Validation device is connected. Timeout value must be between 0
+ and 127. It is needed for TD.7.18, TD.7.19, TD.7.20 and TD.7.21.
+
+What: /sys/bus/usb/devices/.../hot_reset
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Write to this node to issue "Reset" for Link Layer Validation
+ device. It is needed for TD.7.29, TD.7.31, TD.7.34 and TD.7.35.
+
+What: /sys/bus/usb/devices/.../u3_entry
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Write to this node to issue "U3 entry" for Link Layer
+ Validation device. It is needed for TD.7.35 and TD.7.36.
+
+What: /sys/bus/usb/devices/.../u3_exit
+Date: March 2014
+Contact: Pratyush Anand <pratyush.anand@st.com>
+Description:
+ Write to this node to issue "U3 exit" for Link Layer
+ Validation device. It is needed for TD.7.36.
diff --git a/Documentation/ABI/testing/sysfs-class-iommu b/Documentation/ABI/testing/sysfs-class-iommu
new file mode 100644
index 000000000000..6d0a1b4be82d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-iommu
@@ -0,0 +1,17 @@
+What: /sys/class/iommu/<iommu>/devices/
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ IOMMU drivers are able to link devices managed by a
+ given IOMMU here to allow association of IOMMU to
+ device.
+
+What: /sys/devices/.../iommu
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ IOMMU drivers are able to link the IOMMU for a
+ given device here to allow association of device to
+ IOMMU.
diff --git a/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu b/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu
new file mode 100644
index 000000000000..d6ba8e8a4a97
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-iommu-amd-iommu
@@ -0,0 +1,14 @@
+What: /sys/class/iommu/<iommu>/amd-iommu/cap
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ IOMMU capability header as documented in the AMD IOMMU
+ specification. Format: %x
+
+What: /sys/class/iommu/<iommu>/amd-iommu/features
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ Extended features of the IOMMU. Format: %llx
diff --git a/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu b/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu
new file mode 100644
index 000000000000..258cc246d98e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-iommu-intel-iommu
@@ -0,0 +1,32 @@
+What: /sys/class/iommu/<iommu>/intel-iommu/address
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ Physical address of the VT-d DRHD for this IOMMU.
+ Format: %llx. This allows association of a sysfs
+ intel-iommu with a DMAR DRHD table entry.
+
+What: /sys/class/iommu/<iommu>/intel-iommu/cap
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ The cached hardware capability register value
+ of this DRHD unit. Format: %llx.
+
+What: /sys/class/iommu/<iommu>/intel-iommu/ecap
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ The cached hardware extended capability register
+ value of this DRHD unit. Format: %llx.
+
+What: /sys/class/iommu/<iommu>/intel-iommu/version
+Date: June 2014
+KernelVersion: 3.17
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ The architecture version as reported from the
+ VT-d VER_REG. Format: %d:%d, major:minor
diff --git a/Documentation/ABI/testing/sysfs-class-leds-gt683r b/Documentation/ABI/testing/sysfs-class-leds-gt683r
new file mode 100644
index 000000000000..e4fae6026e79
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-leds-gt683r
@@ -0,0 +1,16 @@
+What: /sys/class/leds/<led>/gt683r/mode
+Date: Jun 2014
+KernelVersion: 3.17
+Contact: Janne Kanniainen <janne.kanniainen@gmail.com>
+Description:
+ Set the mode of LEDs. You should notice that changing the mode
+ of one LED will update the mode of its two sibling devices as
+ well.
+
+ 0 - normal
+ 1 - audio
+ 2 - breathing
+
+ Normal: LEDs are fully on when enabled
+ Audio: LEDs brightness depends on sound level
+ Breathing: LEDs brightness varies at human breathing rate \ No newline at end of file
diff --git a/Documentation/ABI/testing/sysfs-class-mei b/Documentation/ABI/testing/sysfs-class-mei
new file mode 100644
index 000000000000..0ec8b8178c41
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-mei
@@ -0,0 +1,16 @@
+What: /sys/class/mei/
+Date: May 2014
+KernelVersion: 3.17
+Contact: Tomas Winkler <tomas.winkler@intel.com>
+Description:
+ The mei/ class sub-directory belongs to mei device class
+
+
+What: /sys/class/mei/meiN/
+Date: May 2014
+KernelVersion: 3.17
+Contact: Tomas Winkler <tomas.winkler@intel.com>
+Description:
+ The /sys/class/mei/meiN directory is created for
+ each probed mei device
+
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd
index 1399bb2da3eb..76ee192f80a0 100644
--- a/Documentation/ABI/testing/sysfs-class-mtd
+++ b/Documentation/ABI/testing/sysfs-class-mtd
@@ -184,3 +184,41 @@ Description:
It will always be a non-negative integer. In the case of
devices lacking any ECC capability, it is 0.
+
+What: /sys/class/mtd/mtdX/ecc_failures
+Date: June 2014
+KernelVersion: 3.17
+Contact: linux-mtd@lists.infradead.org
+Description:
+ The number of failures reported by this device's ECC. Typically,
+ these failures are associated with failed read operations.
+
+ It will always be a non-negative integer. In the case of
+ devices lacking any ECC capability, it is 0.
+
+What: /sys/class/mtd/mtdX/corrected_bits
+Date: June 2014
+KernelVersion: 3.17
+Contact: linux-mtd@lists.infradead.org
+Description:
+ The number of bits that have been corrected by means of the
+ device's ECC.
+
+ It will always be a non-negative integer. In the case of
+ devices lacking any ECC capability, it is 0.
+
+What: /sys/class/mtd/mtdX/bad_blocks
+Date: June 2014
+KernelVersion: 3.17
+Contact: linux-mtd@lists.infradead.org
+Description:
+ The number of blocks marked as bad, if any, in this partition.
+
+What: /sys/class/mtd/mtdX/bbt_blocks
+Date: June 2014
+KernelVersion: 3.17
+Contact: linux-mtd@lists.infradead.org
+Description:
+ The number of blocks that are marked as reserved, if any, in
+ this partition. These are typically used to store the in-flash
+ bad block table (BBT).
diff --git a/Documentation/ABI/testing/sysfs-class-net b/Documentation/ABI/testing/sysfs-class-net
index 416c5d59f52e..d322b0581194 100644
--- a/Documentation/ABI/testing/sysfs-class-net
+++ b/Documentation/ABI/testing/sysfs-class-net
@@ -1,3 +1,14 @@
+What: /sys/class/net/<iface>/name_assign_type
+Date: July 2014
+KernelVersion: 3.17
+Contact: netdev@vger.kernel.org
+Description:
+ Indicates the name assignment type. Possible values are:
+ 1: enumerated by the kernel, possibly in an unpredictable way
+ 2: predictably named by the kernel
+ 3: named by userspace
+ 4: renamed
+
What: /sys/class/net/<iface>/addr_assign_type
Date: July 2010
KernelVersion: 3.2
diff --git a/Documentation/ABI/testing/sysfs-driver-genwqe b/Documentation/ABI/testing/sysfs-driver-genwqe
index 1870737a1f5e..64ac6d567c4b 100644
--- a/Documentation/ABI/testing/sysfs-driver-genwqe
+++ b/Documentation/ABI/testing/sysfs-driver-genwqe
@@ -25,6 +25,15 @@ Date: Oct 2013
Contact: haver@linux.vnet.ibm.com
Description: Interface to set the next bitstream to be used.
+What: /sys/class/genwqe/genwqe<n>_card/reload_bitstream
+Date: May 2014
+Contact: klebers@linux.vnet.ibm.com
+Description: Interface to trigger a PCIe card reset to reload the bitstream.
+ sudo sh -c 'echo 1 > \
+ /sys/class/genwqe/genwqe0_card/reload_bitstream'
+ If successfully, the card will come back with the bitstream set
+ on 'next_bitstream'.
+
What: /sys/class/genwqe/genwqe<n>_card/tempsens
Date: Oct 2013
Contact: haver@linux.vnet.ibm.com
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd b/Documentation/ABI/testing/sysfs-driver-hid-lenovo
index 57b92cbdceae..53a0725962e1 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd
+++ b/Documentation/ABI/testing/sysfs-driver-hid-lenovo
@@ -4,18 +4,21 @@ Contact: linux-input@vger.kernel.org
Description: This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
is being controlled by press_speed.
Values are 0 or 1.
+ Applies to Thinkpad USB Keyboard with TrackPoint.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
Date: July 2011
Contact: linux-input@vger.kernel.org
Description: If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
Values are 0 or 1.
+ Applies to Thinkpad USB Keyboard with TrackPoint.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
Date: July 2011
Contact: linux-input@vger.kernel.org
Description: For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html
Values are 0 or 1.
+ Applies to Thinkpad USB Keyboard with TrackPoint.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right
Date: July 2011
@@ -23,16 +26,25 @@ Contact: linux-input@vger.kernel.org
Description: This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
a left or right mouse button click.
Values are 0 or 1.
+ Applies to Thinkpad USB Keyboard with TrackPoint.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
Date: July 2011
Contact: linux-input@vger.kernel.org
Description: This file contains the trackpoint sensitivity.
Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity).
+ Applies to Thinkpad USB Keyboard with TrackPoint.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed
Date: July 2011
Contact: linux-input@vger.kernel.org
Description: This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
Values are decimal integers from 1 (slowest) to 255 (fastest).
+ Applies to Thinkpad USB Keyboard with TrackPoint.
+What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fn_lock
+Date: July 2014
+Contact: linux-input@vger.kernel.org
+Description: This setting controls whether Fn Lock is enabled on the keyboard (i.e. if F1 is Mute or F1)
+ Values are 0 or 1
+ Applies to ThinkPad Compact (USB|Bluetooth) Keyboard with TrackPoint.
diff --git a/Documentation/ABI/testing/sysfs-driver-pciback b/Documentation/ABI/testing/sysfs-driver-pciback
new file mode 100644
index 000000000000..6a733bfa37e6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-pciback
@@ -0,0 +1,13 @@
+What: /sys/bus/pci/drivers/pciback/quirks
+Date: Oct 2011
+KernelVersion: 3.1
+Contact: xen-devel@lists.xenproject.org
+Description:
+ If the permissive attribute is set, then writing a string in
+ the format of DDDD:BB:DD.F-REG:SIZE:MASK will allow the guest
+ to write and read from the PCI device. That is Domain:Bus:
+ Device.Function-Register:Size:Mask (Domain is optional).
+ For example:
+ #echo 00:19.0-E0:2:FF > /sys/bus/pci/drivers/pciback/quirks
+ will allow the guest to read and write to the configuration
+ register 0x0E.
diff --git a/Documentation/ABI/testing/sysfs-driver-tegra-fuse b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
new file mode 100644
index 000000000000..69f5af632657
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-tegra-fuse
@@ -0,0 +1,11 @@
+What: /sys/devices/*/<our-device>/fuse
+Date: February 2014
+Contact: Peter De Schrijver <pdeschrijver@nvidia.com>
+Description: read-only access to the efuses on Tegra20, Tegra30, Tegra114
+ and Tegra124 SoC's from NVIDIA. The efuses contain write once
+ data programmed at the factory. The data is layed out in 32bit
+ words in LSB first format. Each bit represents a single value
+ as decoded from the fuse registers. Bits order/assignment
+ exactly matches the HW registers, including any unused bits.
+Users: any user space application which wants to read the efuses on
+ Tegra SoC's
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
index 7fc781048b79..c4f0fed64a6e 100644
--- a/Documentation/ABI/testing/sysfs-driver-wacom
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
@@ -1,48 +1,27 @@
-WWhat: /sys/class/hidraw/hidraw*/device/oled*_img
-Date: June 2012
-Contact: linux-bluetooth@vger.kernel.org
-Description:
- The /sys/class/hidraw/hidraw*/device/oled*_img files control
- OLED mocro displays on Intuos4 Wireless tablet. Accepted image
- has to contain 256 bytes (64x32 px 1 bit colour). The format
- is the same as PBM image 62x32px without header (64 bits per
- horizontal line, 32 lines). An example of setting OLED No. 0:
- dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img
- The attribute is read only and no local copy of the image is
- stored.
-
-What: /sys/class/hidraw/hidraw*/device/speed
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed
Date: April 2010
Kernel Version: 2.6.35
Contact: linux-bluetooth@vger.kernel.org
Description:
- The /sys/class/hidraw/hidraw*/device/speed file controls
- reporting speed of Wacom bluetooth tablet. Reading from
- this file returns 1 if tablet reports in high speed mode
+ The /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/speed file
+ controls reporting speed of Wacom bluetooth tablet. Reading
+ from this file returns 1 if tablet reports in high speed mode
or 0 otherwise. Writing to this file one of these values
switches reporting speed.
-What: /sys/class/leds/0005\:056A\:00BD.0001\:selector\:*/
-Date: May 2012
-Kernel Version: 3.5
-Contact: linux-bluetooth@vger.kernel.org
-Description:
- LED selector for Intuos4 WL. There are 4 leds, but only one LED
- can be lit at a time. Max brightness is 127.
-
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/led
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/led
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Attribute group for control of the status LEDs and the OLEDs.
This attribute group is only available for Intuos 4 M, L,
- and XL (with LEDs and OLEDs), Intuos 5 (LEDs only), and Cintiq
- 21UX2 and Cintiq 24HD (LEDs only). Therefore its presence
- implicitly signifies the presence of said LEDs and OLEDs on the
- tablet device.
+ and XL (with LEDs and OLEDs), Intuos 4 WL, Intuos 5 (LEDs only),
+ Intuos Pro (LEDs only) and Cintiq 21UX2 and Cintiq 24HD
+ (LEDs only). Therefore its presence implicitly signifies the
+ presence of said LEDs and OLEDs on the tablet device.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status0_luminance
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the status LED luminance (1..127)
@@ -50,16 +29,16 @@ Description:
button is pressed on the stylus. This luminance level is
normally lower than the level when a button is pressed.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status1_luminance
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status1_luminance
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the status LED luminance (1..127)
when the stylus touches the tablet surface, or any button is
pressed on the stylus.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led0_select
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led0_select
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets which one of the four (for Intuos 4
@@ -67,23 +46,23 @@ Description:
24HD) status LEDs is active (0..3). The other three LEDs on the
same side are always inactive.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
-Date: September 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/status_led1_select
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets which one of the left four (for Cintiq 21UX2
and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on
the left are always inactive.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/buttons_luminance
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
Writing to this file sets the overall luminance level (0..15)
of all eight button OLED displays.
-What: /sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/button<n>_rawimg
-Date: August 2011
+What: /sys/bus/hid/devices/<bus>:<vid>:<pid>.<n>/wacom_led/button<n>_rawimg
+Date: August 2014
Contact: linux-input@vger.kernel.org
Description:
When writing a 1024 byte raw image in Wacom Intuos 4
@@ -93,3 +72,8 @@ Description:
byte chunk encodes the image data for two consecutive lines on
the display. The low nibble of each byte contains the first
line, and the high nibble contains the second line.
+ When the Wacom Intuos 4 is connected over Bluetooth, the
+ image has to contain 256 bytes (64x32 px 1 bit colour).
+ The format is also scrambled, like in the USB mode, and it can
+ be summarized by converting 76543210 into GECA6420.
+ HGFEDCBA HFDB7531
diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2
new file mode 100644
index 000000000000..304ba84a973a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-nilfs2
@@ -0,0 +1,269 @@
+
+What: /sys/fs/nilfs2/features/revision
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show current revision of NILFS file system driver.
+ This value informs about file system revision that
+ driver is ready to support.
+
+What: /sys/fs/nilfs2/features/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/features group.
+
+What: /sys/fs/nilfs2/<device>/revision
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show NILFS file system revision on volume.
+ This value informs about metadata structures'
+ revision on mounted volume.
+
+What: /sys/fs/nilfs2/<device>/blocksize
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show volume's block size in bytes.
+
+What: /sys/fs/nilfs2/<device>/device_size
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show volume size in bytes.
+
+What: /sys/fs/nilfs2/<device>/free_blocks
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show count of free blocks on volume.
+
+What: /sys/fs/nilfs2/<device>/uuid
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show volume's UUID (Universally Unique Identifier).
+
+What: /sys/fs/nilfs2/<device>/volume_name
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show volume's label.
+
+What: /sys/fs/nilfs2/<device>/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device> group.
+
+What: /sys/fs/nilfs2/<device>/superblock/sb_write_time
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show last write time of super block in human-readable
+ format.
+
+What: /sys/fs/nilfs2/<device>/superblock/sb_write_time_secs
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show last write time of super block in seconds.
+
+What: /sys/fs/nilfs2/<device>/superblock/sb_write_count
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show current write count of super block.
+
+What: /sys/fs/nilfs2/<device>/superblock/sb_update_frequency
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show/Set interval of periodical update of superblock
+ (in seconds).
+
+What: /sys/fs/nilfs2/<device>/superblock/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device>/superblock
+ group.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_pseg_block
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show start block number of the latest segment.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_seg_sequence
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show sequence value of the latest segment.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_seg_checkpoint
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show checkpoint number of the latest segment.
+
+What: /sys/fs/nilfs2/<device>/segctor/current_seg_sequence
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show segment sequence counter.
+
+What: /sys/fs/nilfs2/<device>/segctor/current_last_full_seg
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show index number of the latest full segment.
+
+What: /sys/fs/nilfs2/<device>/segctor/next_full_seg
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show index number of the full segment index
+ to be used next.
+
+What: /sys/fs/nilfs2/<device>/segctor/next_pseg_offset
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show offset of next partial segment in the current
+ full segment.
+
+What: /sys/fs/nilfs2/<device>/segctor/next_checkpoint
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show next checkpoint number.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_seg_write_time
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show write time of the last segment in
+ human-readable format.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_seg_write_time_secs
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show write time of the last segment in seconds.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_nongc_write_time
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show write time of the last segment not for cleaner
+ operation in human-readable format.
+
+What: /sys/fs/nilfs2/<device>/segctor/last_nongc_write_time_secs
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show write time of the last segment not for cleaner
+ operation in seconds.
+
+What: /sys/fs/nilfs2/<device>/segctor/dirty_data_blocks_count
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of dirty data blocks.
+
+What: /sys/fs/nilfs2/<device>/segctor/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device>/segctor
+ group.
+
+What: /sys/fs/nilfs2/<device>/segments/segments_number
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of segments on a volume.
+
+What: /sys/fs/nilfs2/<device>/segments/blocks_per_segment
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of blocks in segment.
+
+What: /sys/fs/nilfs2/<device>/segments/clean_segments
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show count of clean segments.
+
+What: /sys/fs/nilfs2/<device>/segments/dirty_segments
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show count of dirty segments.
+
+What: /sys/fs/nilfs2/<device>/segments/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device>/segments
+ group.
+
+What: /sys/fs/nilfs2/<device>/checkpoints/checkpoints_number
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of checkpoints on volume.
+
+What: /sys/fs/nilfs2/<device>/checkpoints/snapshots_number
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of snapshots on volume.
+
+What: /sys/fs/nilfs2/<device>/checkpoints/last_seg_checkpoint
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show checkpoint number of the latest segment.
+
+What: /sys/fs/nilfs2/<device>/checkpoints/next_checkpoint
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show next checkpoint number.
+
+What: /sys/fs/nilfs2/<device>/checkpoints/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device>/checkpoints
+ group.
+
+What: /sys/fs/nilfs2/<device>/mounted_snapshots/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe content of /sys/fs/nilfs2/<device>/mounted_snapshots
+ group.
+
+What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/inodes_count
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of inodes for snapshot.
+
+What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/blocks_count
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Show number of blocks for snapshot.
+
+What: /sys/fs/nilfs2/<device>/mounted_snapshots/<id>/README
+Date: April 2014
+Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
+Description:
+ Describe attributes of /sys/fs/nilfs2/<device>/mounted_snapshots/<id>
+ group.
diff --git a/Documentation/ABI/testing/sysfs-fs-xfs b/Documentation/ABI/testing/sysfs-fs-xfs
new file mode 100644
index 000000000000..ea0cc8c42093
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-xfs
@@ -0,0 +1,39 @@
+What: /sys/fs/xfs/<disk>/log/log_head_lsn
+Date: July 2014
+KernelVersion: 3.17
+Contact: xfs@oss.sgi.com
+Description:
+ The log sequence number (LSN) of the current head of the
+ log. The LSN is exported in "cycle:basic block" format.
+Users: xfstests
+
+What: /sys/fs/xfs/<disk>/log/log_tail_lsn
+Date: July 2014
+KernelVersion: 3.17
+Contact: xfs@oss.sgi.com
+Description:
+ The log sequence number (LSN) of the current tail of the
+ log. The LSN is exported in "cycle:basic block" format.
+
+What: /sys/fs/xfs/<disk>/log/reserve_grant_head
+Date: July 2014
+KernelVersion: 3.17
+Contact: xfs@oss.sgi.com
+Description:
+ The current state of the log reserve grant head. It
+ represents the total log reservation of all currently
+ outstanding transactions. The grant head is exported in
+ "cycle:bytes" format.
+Users: xfstests
+
+What: /sys/fs/xfs/<disk>/log/write_grant_head
+Date: July 2014
+KernelVersion: 3.17
+Contact: xfs@oss.sgi.com
+Description:
+ The current state of the log write grant head. It
+ represents the total log reservation of all currently
+ oustanding transactions, including regrants due to
+ rolling transactions. The grant head is exported in
+ "cycle:bytes" format.
+Users: xfstests
diff --git a/Documentation/ABI/testing/sysfs-platform-ts5500 b/Documentation/ABI/testing/sysfs-platform-ts5500
index c88375a537a1..e685957caa12 100644
--- a/Documentation/ABI/testing/sysfs-platform-ts5500
+++ b/Documentation/ABI/testing/sysfs-platform-ts5500
@@ -30,6 +30,13 @@ Description:
the corresponding bit is set. For instance, 0x0e means jumpers
2, 3 and 4 are set.
+What: /sys/devices/platform/ts5500/name
+Date: July 2014
+KernelVersion: 3.16
+Contact: "Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
+Description:
+ Model name of the TS board, e.g. "TS-5500".
+
What: /sys/devices/platform/ts5500/rs485
Date: January 2013
KernelVersion: 3.7
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index ad22fb0ee765..9eb3c2b6b040 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -138,3 +138,19 @@ Description:
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
+
+What: /sys/class/tty/ttyS0/rx_trig_bytes
+Date: May 2014
+Contact: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
+Description:
+ Shows current RX interrupt trigger bytes or sets the
+ user specified value to change it for the FIFO buffer.
+ Users can show or set this value regardless of opening the
+ serial device file or not.
+
+ The RX trigger can be set one of four kinds of values for UART
+ serials. When users input a meaning less value to this I/F,
+ the RX trigger is changed to the nearest lower value for the
+ device specification. For example, when user sets 7bytes on
+ 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
+ automatically changed to 4 bytes.
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index cc63f30de166..f2130586ef5d 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -54,7 +54,7 @@
!Ikernel/sched/cpupri.c
!Ikernel/sched/fair.c
!Iinclude/linux/completion.h
-!Ekernel/timer.c
+!Ekernel/time/timer.c
</sect1>
<sect1><title>Wait queues and Wake events</title>
!Iinclude/linux/wait.h
@@ -63,7 +63,7 @@
<sect1><title>High-resolution timers</title>
!Iinclude/linux/ktime.h
!Iinclude/linux/hrtimer.h
-!Ekernel/hrtimer.c
+!Ekernel/time/hrtimer.c
</sect1>
<sect1><title>Workqueues and Kevents</title>
!Ekernel/workqueue.c
@@ -128,8 +128,12 @@ X!Edrivers/base/interface.c
!Edrivers/base/bus.c
</sect1>
<sect1><title>Device Drivers DMA Management</title>
-!Edrivers/base/dma-buf.c
-!Edrivers/base/reservation.c
+!Edrivers/dma-buf/dma-buf.c
+!Edrivers/dma-buf/fence.c
+!Edrivers/dma-buf/seqno-fence.c
+!Iinclude/linux/fence.h
+!Iinclude/linux/seqno-fence.h
+!Edrivers/dma-buf/reservation.c
!Iinclude/linux/reservation.h
!Edrivers/base/dma-coherent.c
!Edrivers/base/dma-mapping.c
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 7df3134ebc0e..bacefc5b222e 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -315,7 +315,7 @@ char *date;</synopsis>
<function>drm_dev_unregister()</function> followed by a call to
<function>drm_dev_unref()</function>.
</para>
-!Edrivers/gpu/drm/drm_stub.c
+!Edrivers/gpu/drm/drm_drv.c
</sect2>
<sect2>
<title>Driver Load</title>
@@ -1610,7 +1610,7 @@ int max_width, max_height;</synopsis>
The connector is then registered with a call to
<function>drm_connector_init</function> with a pointer to the connector
functions and a connector type, and exposed through sysfs with a call to
- <function>drm_sysfs_connector_add</function>.
+ <function>drm_connector_register</function>.
</para>
<para>
Supported connector types are
@@ -1768,7 +1768,7 @@ int max_width, max_height;</synopsis>
(<function>drm_encoder_cleanup</function>) and connectors
(<function>drm_connector_cleanup</function>). Furthermore, connectors
that have been added to sysfs must be removed by a call to
- <function>drm_sysfs_connector_remove</function> before calling
+ <function>drm_connector_unregister</function> before calling
<function>drm_connector_cleanup</function>.
</para>
<para>
@@ -1813,7 +1813,7 @@ void intel_crt_init(struct drm_device *dev)
drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
}]]></programlisting>
<para>
In the example above (taken from the i915 driver), a CRTC, connector and
@@ -2338,6 +2338,12 @@ void intel_crt_init(struct drm_device *dev)
!Edrivers/gpu/drm/drm_dp_helper.c
</sect2>
<sect2>
+ <title>Display Port MST Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
+!Iinclude/drm/drm_dp_mst_helper.h
+!Edrivers/gpu/drm/drm_dp_mst_topology.c
+ </sect2>
+ <sect2>
<title>EDID Helper Functions Reference</title>
!Edrivers/gpu/drm/drm_edid.c
</sect2>
@@ -2502,7 +2508,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >Description/Restrictions</td>
</tr>
<tr>
- <td rowspan="20" valign="top" >DRM</td>
+ <td rowspan="21" valign="top" >DRM</td>
<td rowspan="2" valign="top" >Generic</td>
<td valign="top" >“EDID”</td>
<td valign="top" >BLOB | IMMUTABLE</td>
@@ -2633,7 +2639,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="2" valign="top" >Optional</td>
+ <td rowspan="3" valign="top" >Optional</td>
<td valign="top" >“scaling mode”</td>
<td valign="top" >ENUM</td>
<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
@@ -2641,6 +2647,15 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
+ <td valign="top" >"aspect ratio"</td>
+ <td valign="top" >ENUM</td>
+ <td valign="top" >{ "None", "4:3", "16:9" }</td>
+ <td valign="top" >Connector</td>
+ <td valign="top" >DRM property to set aspect ratio from user space app.
+ This enum is made generic to allow addition of custom aspect
+ ratios.</td>
+ </tr>
+ <tr>
<td valign="top" >“dirty”</td>
<td valign="top" >ENUM | IMMUTABLE</td>
<td valign="top" >{ "Off", "On", "Annotate" }</td>
@@ -2649,7 +2664,7 @@ void intel_crt_init(struct drm_device *dev)
</tr>
<tr>
<td rowspan="21" valign="top" >i915</td>
- <td rowspan="3" valign="top" >Generic</td>
+ <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >"Broadcast RGB"</td>
<td valign="top" >ENUM</td>
<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
@@ -2664,10 +2679,11 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td valign="top" >Standard name as in DRM</td>
- <td valign="top" >Standard type as in DRM</td>
- <td valign="top" >Standard value as in DRM</td>
- <td valign="top" >Standard Object as in DRM</td>
+ <td rowspan="1" valign="top" >Plane</td>
+ <td valign="top" >“rotation”</td>
+ <td valign="top" >BITMASK</td>
+ <td valign="top" >{ 0, "rotate-0" }, { 2, "rotate-180" }</td>
+ <td valign="top" >Plane</td>
<td valign="top" >TBD</td>
</tr>
<tr>
@@ -2799,8 +2815,8 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="3" valign="top" >CDV gma-500</td>
- <td rowspan="3" valign="top" >Generic</td>
+ <td rowspan="2" valign="top" >CDV gma-500</td>
+ <td rowspan="2" valign="top" >Generic</td>
<td valign="top" >"Broadcast RGB"</td>
<td valign="top" >ENUM</td>
<td valign="top" >{ “Full”, “Limited 16:235” }</td>
@@ -2815,15 +2831,8 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td valign="top" >Standard name as in DRM</td>
- <td valign="top" >Standard type as in DRM</td>
- <td valign="top" >Standard value as in DRM</td>
- <td valign="top" >Standard Object as in DRM</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="20" valign="top" >Poulsbo</td>
- <td rowspan="2" valign="top" >Generic</td>
+ <td rowspan="19" valign="top" >Poulsbo</td>
+ <td rowspan="1" valign="top" >Generic</td>
<td valign="top" >“backlight”</td>
<td valign="top" >RANGE</td>
<td valign="top" >Min=0, Max=100</td>
@@ -2831,13 +2840,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td valign="top" >Standard name as in DRM</td>
- <td valign="top" >Standard type as in DRM</td>
- <td valign="top" >Standard value as in DRM</td>
- <td valign="top" >Standard Object as in DRM</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
<td rowspan="17" valign="top" >SDVO-TV</td>
<td valign="top" >“mode”</td>
<td valign="top" >ENUM</td>
@@ -3064,7 +3066,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="3" valign="top" >i2c/ch7006_drv</td>
+ <td rowspan="2" valign="top" >i2c/ch7006_drv</td>
<td valign="top" >Generic</td>
<td valign="top" >“scale”</td>
<td valign="top" >RANGE</td>
@@ -3073,14 +3075,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="2" valign="top" >TV</td>
- <td valign="top" >Standard names as in DRM</td>
- <td valign="top" >Standard types as in DRM</td>
- <td valign="top" >Standard Values as in DRM</td>
- <td valign="top" >Standard object as in DRM</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
+ <td rowspan="1" valign="top" >TV</td>
<td valign="top" >“mode”</td>
<td valign="top" >ENUM</td>
<td valign="top" >{ "PAL", "PAL-M","PAL-N"}, ”PAL-Nc"
@@ -3089,7 +3084,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="16" valign="top" >nouveau</td>
+ <td rowspan="15" valign="top" >nouveau</td>
<td rowspan="6" valign="top" >NV10 Overlay</td>
<td valign="top" >"colorkey"</td>
<td valign="top" >RANGE</td>
@@ -3198,14 +3193,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td valign="top" >Generic</td>
- <td valign="top" >Standard name as in DRM</td>
- <td valign="top" >Standard type as in DRM</td>
- <td valign="top" >Standard value as in DRM</td>
- <td valign="top" >Standard Object as in DRM</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
<td rowspan="2" valign="top" >omap</td>
<td rowspan="2" valign="top" >Generic</td>
<td valign="top" >“rotation”</td>
@@ -3236,7 +3223,7 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td rowspan="10" valign="top" >radeon</td>
+ <td rowspan="9" valign="top" >radeon</td>
<td valign="top" >DVI-I</td>
<td valign="top" >“coherent”</td>
<td valign="top" >RANGE</td>
@@ -3308,14 +3295,6 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >TBD</td>
</tr>
<tr>
- <td valign="top" >Generic</td>
- <td valign="top" >Standard name as in DRM</td>
- <td valign="top" >Standard type as in DRM</td>
- <td valign="top" >Standard value as in DRM</td>
- <td valign="top" >Standard Object as in DRM</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
<td rowspan="3" valign="top" >rcar-du</td>
<td rowspan="3" valign="top" >Generic</td>
<td valign="top" >"alpha"</td>
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 2c425d70f7e2..641629221176 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -556,11 +556,11 @@ been converted to this framework.
Near-term plans include converting all of them, except for "gadgetfs".
</para>
-!Edrivers/usb/gadget/f_acm.c
-!Edrivers/usb/gadget/f_ecm.c
-!Edrivers/usb/gadget/f_subset.c
-!Edrivers/usb/gadget/f_obex.c
-!Edrivers/usb/gadget/f_serial.c
+!Edrivers/usb/gadget/function/f_acm.c
+!Edrivers/usb/gadget/function/f_ecm.c
+!Edrivers/usb/gadget/function/f_subset.c
+!Edrivers/usb/gadget/function/f_obex.c
+!Edrivers/usb/gadget/function/f_serial.c
</sect1>
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
index 639e74857968..df2962d9e11e 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -174,7 +174,7 @@ FILENAME = \
DOCUMENTED = \
-e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
-e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
- -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+ -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
-e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
-e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
index 24c22cabc668..948ddaab592e 100644
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ b/Documentation/DocBook/media/dvb/dvbproperty.xml
@@ -555,10 +555,46 @@ typedef enum fe_delivery_system {
</section>
<section id="DTV-ISDBT-LAYER-TIME-INTERLEAVING">
<title><constant>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</constant></title>
- <para>Possible values: 0, 1, 2, 3, -1 (AUTO)</para>
- <para>Note: The real inter-leaver depth-names depend on the mode (fft-size); the values
- here are referring to what can be found in the TMCC-structure -
- independent of the mode.</para>
+ <para>Valid values: 0, 1, 2, 4, -1 (AUTO)</para>
+ <para>when DTV_ISDBT_SOUND_BROADCASTING is active, value 8 is also valid.</para>
+ <para>Note: The real time interleaving length depends on the mode (fft-size). The values
+ here are referring to what can be found in the TMCC-structure, as shown in the table below.</para>
+ <informaltable id="isdbt-layer-interleaving-table">
+ <tgroup cols="4" align="center">
+ <tbody>
+ <row>
+ <entry>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</entry>
+ <entry>Mode 1 (2K FFT)</entry>
+ <entry>Mode 2 (4K FFT)</entry>
+ <entry>Mode 3 (8K FFT)</entry>
+ </row>
+ <row>
+ <entry>0</entry>
+ <entry>0</entry>
+ <entry>0</entry>
+ <entry>0</entry>
+ </row>
+ <row>
+ <entry>1</entry>
+ <entry>4</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ </row>
+ <row>
+ <entry>2</entry>
+ <entry>8</entry>
+ <entry>4</entry>
+ <entry>2</entry>
+ </row>
+ <row>
+ <entry>4</entry>
+ <entry>16</entry>
+ <entry>8</entry>
+ <entry>4</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
</section>
<section id="DTV-ATSCMH-FIC-VER">
<title><constant>DTV_ATSCMH_FIC_VER</constant></title>
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 47198eef75a4..9f5ffd85560b 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -13,6 +13,19 @@ correctly with any device.</para>
<para>All controls are accessed using an ID value. V4L2 defines
several IDs for specific purposes. Drivers can also implement their
own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
+<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
+is problematic because different drivers may use the same
+<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
+This makes it hard to programatically set such controls since the meaning
+of the control with that ID is driver dependent. In order to resolve this
+drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs are mapped to those unique IDs by the kernel. Consider these
+<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
+IDs.</para>
+<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
+flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
+is still around.</para></footnote>
and higher values. The pre-defined control IDs have the prefix
<constant>V4L2_CID_</constant>, and are listed in <xref
linkend="control-id" />. The ID is used when querying the attributes of
@@ -31,25 +44,22 @@ the current video input or output, tuner or modulator, or audio input
or output. Different in the sense of other bounds, another default and
current value, step size or other menu items. A control with a certain
<emphasis>custom</emphasis> ID can also change name and
-type.<footnote>
- <para>It will be more convenient for applications if drivers
-make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
-that was never required.</para>
- </footnote> Control values are stored globally, they do not
+type.</para>
+
+ <para>If a control is not applicable to the current configuration
+of the device (for example, it doesn't apply to the current video input)
+drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
+
+ <para>Control values are stored globally, they do not
change when switching except to stay within the reported bounds. They
also do not change &eg; when the device is opened or closed, when the
tuner radio frequency is changed or generally never without
-application request. Since V4L2 specifies no event mechanism, panel
-applications intended to cooperate with other panel applications (be
-they built into a larger application, as a TV viewer) may need to
-regularly poll control values to update their user
-interface.<footnote>
- <para>Applications could call an ioctl to request events.
-After another process called &VIDIOC-S-CTRL; or another ioctl changing
-shared properties the &func-select; function would indicate
-readability until any ioctl (querying the properties) is
-called.</para>
- </footnote></para>
+application request.</para>
+
+ <para>V4L2 specifies an event mechanism to notify applications
+when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
+<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
+use of that in order to always reflect the correct control value.</para>
<para>
All controls use machine endianness.
@@ -398,14 +408,17 @@ to work.</entry>
<row id="v4l2-alpha-component">
<entry><constant>V4L2_CID_ALPHA_COMPONENT</constant></entry>
<entry>integer</entry>
- <entry> Sets the alpha color component on the capture device or on
- the capture buffer queue of a mem-to-mem device. When a mem-to-mem
- device produces frame format that includes an alpha component
+ <entry>Sets the alpha color component. When a capture device (or
+ capture queue of a mem-to-mem device) produces a frame format that
+ includes an alpha component
(e.g. <link linkend="rgb-formats">packed RGB image formats</link>)
- and the alpha value is not defined by the mem-to-mem input data
- this control lets you select the alpha component value of all
- pixels. It is applicable to any pixel format that contains an alpha
- component.
+ and the alpha value is not defined by the device or the mem-to-mem
+ input data this control lets you select the alpha component value of
+ all pixels. When an output device (or output queue of a mem-to-mem
+ device) consumes a frame format that doesn't include an alpha
+ component and the device supports alpha channel processing this
+ control lets you set the alpha component value of all pixels for
+ further processing in the device.
</entry>
</row>
<row>
@@ -434,127 +447,152 @@ Drivers must implement <constant>VIDIOC_QUERYCTRL</constant>,
controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
more menu type controls.</para>
- <example>
- <title>Enumerating all controls</title>
+ <example id="enum_all_controls">
+ <title>Enumerating all user controls</title>
<programlisting>
&v4l2-queryctrl; queryctrl;
&v4l2-querymenu; querymenu;
-static void
-enumerate_menu (void)
+static void enumerate_menu(void)
{
- printf (" Menu items:\n");
+ printf(" Menu items:\n");
- memset (&amp;querymenu, 0, sizeof (querymenu));
+ memset(&amp;querymenu, 0, sizeof(querymenu));
querymenu.id = queryctrl.id;
for (querymenu.index = queryctrl.minimum;
querymenu.index &lt;= queryctrl.maximum;
- querymenu.index++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
- printf (" %s\n", querymenu.name);
+ querymenu.index++) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
+ printf(" %s\n", querymenu.name);
}
}
}
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
for (queryctrl.id = V4L2_CID_BASE;
queryctrl.id &lt; V4L2_CID_LASTP1;
queryctrl.id++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
continue;
- printf ("Control %s\n", queryctrl.name);
+ printf("Control %s\n", queryctrl.name);
if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu ();
+ enumerate_menu();
} else {
if (errno == EINVAL)
continue;
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
}
}
for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
queryctrl.id++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
continue;
- printf ("Control %s\n", queryctrl.name);
+ printf("Control %s\n", queryctrl.name);
if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu ();
+ enumerate_menu();
} else {
if (errno == EINVAL)
break;
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
}
}
</programlisting>
</example>
<example>
+ <title>Enumerating all user controls (alternative)</title>
+ <programlisting>
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
+
+queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
+ break;
+ if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+ printf("Control %s\n", queryctrl.name);
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerate_menu();
+
+ queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
+if (errno != EINVAL) {
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
+}
+</programlisting>
+ </example>
+
+ <example>
<title>Changing controls</title>
<programlisting>
&v4l2-queryctrl; queryctrl;
&v4l2-control; control;
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
queryctrl.id = V4L2_CID_BRIGHTNESS;
-if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (errno != EINVAL) {
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
} else {
- printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ printf("V4L2_CID_BRIGHTNESS is not supported\n");
}
} else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
- printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ printf("V4L2_CID_BRIGHTNESS is not supported\n");
} else {
- memset (&amp;control, 0, sizeof (control));
+ memset(&amp;control, 0, sizeof (control));
control.id = V4L2_CID_BRIGHTNESS;
control.value = queryctrl.default_value;
- if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
- perror ("VIDIOC_S_CTRL");
- exit (EXIT_FAILURE);
+ if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
+ perror("VIDIOC_S_CTRL");
+ exit(EXIT_FAILURE);
}
}
-memset (&amp;control, 0, sizeof (control));
+memset(&amp;control, 0, sizeof(control));
control.id = V4L2_CID_CONTRAST;
-if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
+if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
control.value += 1;
/* The driver may clamp the value or return ERANGE, ignored here */
- if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
+ if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
&amp;&amp; errno != ERANGE) {
- perror ("VIDIOC_S_CTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_S_CTRL");
+ exit(EXIT_FAILURE);
}
/* Ignore if V4L2_CID_CONTRAST is unsupported */
} else if (errno != EINVAL) {
- perror ("VIDIOC_G_CTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_G_CTRL");
+ exit(EXIT_FAILURE);
}
control.id = V4L2_CID_AUDIO_MUTE;
-control.value = TRUE; /* silence */
+control.value = 1; /* silence */
/* Errors ignored */
-ioctl (fd, VIDIOC_S_CTRL, &amp;control);
+ioctl(fd, VIDIOC_S_CTRL, &amp;control);
</programlisting>
</example>
</section>
@@ -625,16 +663,29 @@ supported.</para>
&v4l2-control;, except for the fact that it also allows for 64-bit
values and pointers to be passed.</para>
+ <para>Since the &v4l2-ext-control; supports pointers it is now
+also possible to have controls with compound types such as N-dimensional arrays
+and/or structures. You need to specify the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+when enumerating controls to actually be able to see such compound controls.
+In other words, these controls with compound types should only be used
+programmatically.</para>
+
+ <para>Since such compound controls need to expose more information
+about themselves than is possible with &VIDIOC-QUERYCTRL; the
+&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
+the dimensions of the N-dimensional array if this control consists of more than
+one element.</para>
+
<para>It is important to realize that due to the flexibility of
controls it is necessary to check whether the control you want to set
actually is supported in the driver and what the valid range of values
-is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
-check this. Also note that it is possible that some of the menu
-indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
-may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
-return an error). A good example is the list of supported MPEG audio
-bitrates. Some drivers only support one or two bitrates, others
-support a wider range.</para>
+is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
+&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
+that some of the menu indices in a control of type
+<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
+(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
+example is the list of supported MPEG audio bitrates. Some drivers only
+support one or two bitrates, others support a wider range.</para>
<para>
All controls use machine endianness.
@@ -675,12 +726,12 @@ control class is found:</para>
<informalexample>
<programlisting>
qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
- if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
+ if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
break;
/* ... */
- qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
- }
+ qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
</programlisting>
</informalexample>
@@ -700,7 +751,7 @@ ID based on a control ID.</para>
<constant>VIDIOC_QUERYCTRL</constant> will fail when used in
combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
that case the old method of enumerating control should be used (see
-1.8). But if it is supported, then it is guaranteed to enumerate over
+<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
all controls, including driver-private controls.</para>
</section>
@@ -4000,6 +4051,68 @@ to find receivers which can scroll strings sized as 32 x N or 64 x N characters.
with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
</row>
<row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_MONO_STEREO</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Sets the Mono/Stereo bit of the Decoder Identification code. If set,
+then the audio was recorded as stereo.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_ARTIFICIAL_HEAD</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Sets the
+<ulink url="http://en.wikipedia.org/wiki/Artificial_head">Artificial Head</ulink> bit of the Decoder
+Identification code. If set, then the audio was recorded using an artificial head.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_COMPRESSED</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Sets the Compressed bit of the Decoder Identification code. If set,
+then the audio is compressed.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_DYNAMIC_PTY</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">Sets the Dynamic PTY bit of the Decoder Identification code. If set,
+then the PTY code is dynamically switched.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_MUSIC_SPEECH</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
+broadcasts speech. If the transmitter doesn't make this distinction, then it should be set.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS_ENABLE</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then transmit alternate frequencies.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS</constant>&nbsp;</entry>
+ <entry>__u32 array</entry>
+ </row>
+ <row><entry spanname="descr">The alternate frequencies in kHz units. The RDS standard allows
+for up to 25 frequencies to be defined. Drivers may support fewer frequencies so check
+the array size.</entry>
+ </row>
+ <row>
<entry spanname="id"><constant>V4L2_CID_AUDIO_LIMITER_ENABLED</constant>&nbsp;</entry>
<entry>boolean</entry>
</row>
@@ -4976,6 +5089,57 @@ description of this control class.</entry>
</row><row><entry spanname="descr">Enables/disables RDS
reception by the radio tuner</entry>
</row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_PTY</constant>&nbsp;</entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Gets RDS Programme Type field.
+This encodes up to 31 pre-defined programme types.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_PS_NAME</constant>&nbsp;</entry>
+ <entry>string</entry>
+ </row>
+ <row><entry spanname="descr">Gets the Programme Service name (PS_NAME).
+It is intended for static display on a receiver. It is the primary aid to listeners in programme service
+identification and selection. In Annex E of <xref linkend="iec62106" />, the RDS specification,
+there is a full description of the correct character encoding for Programme Service name strings.
+Also from RDS specification, PS is usually a single eight character text. However, it is also possible
+to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
+with steps of 8 characters. The result is it must always contain a string with size multiple of 8.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_RADIO_TEXT</constant>&nbsp;</entry>
+ <entry>string</entry>
+ </row>
+ <row><entry spanname="descr">Gets the Radio Text info. It is a textual description of
+what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
+programme-related information or any other text. In these cases, RadioText can be used in addition to
+<constant>V4L2_CID_RDS_RX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
+in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
+used to transmit it, either 32 (2A block) or 64 (2B block). However, it is also possible
+to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
+with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_RDS_RX_MUSIC_SPEECH</constant>&nbsp;</entry>
+ <entry>boolean</entry>
+ </row>
+ <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
+broadcasts speech. If the transmitter doesn't make this distinction, then it will be set.</entry>
+ </row>
<row>
<entry spanname="id"><constant>V4L2_CID_TUNE_DEEMPHASIS</constant>&nbsp;</entry>
<entry>enum v4l2_deemphasis</entry>
@@ -5007,6 +5171,102 @@ defines possible values for de-emphasis. Here they are:</entry>
</tbody>
</tgroup>
</table>
+ </section>
+
+ <section id="detect-controls">
+ <title>Detect Control Reference</title>
+
+ <para>The Detect class includes controls for common features of
+ various motion or object detection capable devices.</para>
+
+ <table pgwide="1" frame="none" id="detect-control-id">
+ <title>Detect Control IDs</title>
+
+ <tgroup cols="4">
+ <colspec colname="c1" colwidth="1*" />
+ <colspec colname="c2" colwidth="6*" />
+ <colspec colname="c3" colwidth="2*" />
+ <colspec colname="c4" colwidth="6*" />
+ <spanspec namest="c1" nameend="c2" spanname="id" />
+ <spanspec namest="c2" nameend="c4" spanname="descr" />
+ <thead>
+ <row>
+ <entry spanname="id" align="left">ID</entry>
+ <entry align="left">Type</entry>
+ </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+ </row>
+ </thead>
+ <tbody valign="top">
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_CLASS</constant>&nbsp;</entry>
+ <entry>class</entry>
+ </row><row><entry spanname="descr">The Detect class
+descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
+description of this control class.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_MODE</constant>&nbsp;</entry>
+ <entry>menu</entry>
+ </row><row><entry spanname="descr">Sets the motion detection mode.</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_DISABLED</constant>
+ </entry><entry>Disable motion detection.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_GLOBAL</constant>
+ </entry><entry>Use a single motion detection threshold.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+ </entry><entry>The image is divided into a grid, each cell with its own
+ motion detection threshold. These thresholds are set through the
+ <constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant> matrix control.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+ </entry><entry>The image is divided into a grid, each cell with its own
+ region value that specifies which per-region motion detection thresholds
+ should be used. Each region has its own thresholds. How these per-region
+ thresholds are set up is driver-specific. The region values for the grid are set
+ through the <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> matrix
+ control.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD</constant>&nbsp;</entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Sets the global motion detection threshold to be
+ used with the <constant>V4L2_DETECT_MD_MODE_GLOBAL</constant> motion detection mode.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant>&nbsp;</entry>
+ <entry>__u16 matrix</entry>
+ </row>
+ <row><entry spanname="descr">Sets the motion detection thresholds for each cell in the grid.
+ To be used with the <constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+ motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+ grid.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_REGION_GRID</constant>&nbsp;</entry>
+ <entry>__u8 matrix</entry>
+ </row>
+ <row><entry spanname="descr">Sets the motion detection region value for each cell in the grid.
+ To be used with the <constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+ motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+ grid.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</section>
diff --git a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml b/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
index b788c72c885e..f4b61b6ce3c2 100644
--- a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
+++ b/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
@@ -150,9 +150,15 @@ signal. Drivers shall not convert the sample format by software.</para></entry>
<entry>This is the scanning system line number
associated with the first line of the VBI image, of the first and the
second field respectively. See <xref linkend="vbi-525" /> and
-<xref linkend="vbi-625" /> for valid values. VBI input drivers can
-return start values 0 if the hardware cannot reliable identify
-scanning lines, VBI acquisition may not require this
+<xref linkend="vbi-625" /> for valid values.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start line
+numbers for each field for each 525 or 625 line format as a convenience.
+Don't forget that ITU line numbering starts at 1, not 0.
+VBI input drivers can return start values 0 if the hardware cannot
+reliable identify scanning lines, VBI acquisition may not require this
information.</entry>
</row>
<row>
diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml
index dc14804f5436..f8903568a243 100644
--- a/Documentation/DocBook/media/v4l/dev-sdr.xml
+++ b/Documentation/DocBook/media/v4l/dev-sdr.xml
@@ -72,9 +72,12 @@ To use the <link linkend="format">format</link> ioctls applications set the
<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> and use the &v4l2-sdr-format;
<structfield>sdr</structfield> member of the <structfield>fmt</structfield>
union as needed per the desired operation.
-Currently only the <structfield>pixelformat</structfield> field of
-&v4l2-sdr-format; is used. The content of that field is the V4L2 fourcc code
-of the data format.
+Currently there is two fields, <structfield>pixelformat</structfield> and
+<structfield>buffersize</structfield>, of struct &v4l2-sdr-format; which are
+used. Content of the <structfield>pixelformat</structfield> is V4L2 FourCC
+code of the data format. The <structfield>buffersize</structfield> field is
+maximum buffer size in bytes required for data transfer, set by the driver in
+order to inform application.
</para>
<table pgwide="1" frame="none" id="v4l2-sdr-format">
@@ -92,8 +95,15 @@ V4L2 defines SDR formats in <xref linkend="sdr-formats" />.
</entry>
</row>
<row>
+ <entry>__u32</entry>
+ <entry><structfield>buffersize</structfield></entry>
+ <entry>
+Maximum size in bytes required for data. Value is set by the driver.
+ </entry>
+ </row>
+ <row>
<entry>__u8</entry>
- <entry><structfield>reserved[28]</structfield></entry>
+ <entry><structfield>reserved[24]</structfield></entry>
<entry>This array is reserved for future extensions.
Drivers and applications must set it to zero.</entry>
</row>
diff --git a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml b/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
index 548f8ea28dee..7a8bf3011ee9 100644
--- a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
+++ b/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
@@ -185,7 +185,14 @@ tables, sigh. --></para></entry>
<entry></entry>
<entry spanname="hspan">Drivers must set
<structfield>service_lines</structfield>[0][0] and
-<structfield>service_lines</structfield>[1][0] to zero.</entry>
+<structfield>service_lines</structfield>[1][0] to zero.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start
+line numbers for each field for each 525 or 625 line format as a
+convenience. Don't forget that ITU line numbering starts at 1, not 0.
+</entry>
</row>
<row>
<entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index a086a5db7a18..e5e8325aa3d7 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -870,7 +870,8 @@ should set this to 0.</entry>
If the application sets this to 0 for an output stream, then
<structfield>bytesused</structfield> will be set to the size of the
plane (see the <structfield>length</structfield> field of this struct)
- by the driver.</entry>
+ by the driver. Note that the actual image data starts at
+ <structfield>data_offset</structfield> which may not be 0.</entry>
</row>
<row>
<entry>__u32</entry>
@@ -919,6 +920,10 @@ should set this to 0.</entry>
<entry>Offset in bytes to video data in the plane.
Drivers must set this field when <structfield>type</structfield>
refers to an input stream, applications when it refers to an output stream.
+ Note that data_offset is included in <structfield>bytesused</structfield>.
+ So the size of the image in the plane is
+ <structfield>bytesused</structfield>-<structfield>data_offset</structfield> at
+ offset <structfield>data_offset</structfield> from the start of the plane.
</entry>
</row>
<row>
@@ -1066,7 +1071,7 @@ state, in the application domain so to say.</entry>
<entry>Drivers set or clear this flag when calling the
<constant>VIDIOC_DQBUF</constant> ioctl. It may be set by video
capture devices when the buffer contains a compressed image which is a
-key frame (or field), &ie; can be decompressed on its own. Also know as
+key frame (or field), &ie; can be decompressed on its own. Also known as
an I-frame. Applications can set this bit when <structfield>type</structfield>
refers to an output stream.</entry>
</row>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
index e1c4f8b4c0b3..2aae8e9452a4 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
@@ -15,9 +15,6 @@ typical PC graphics frame buffers. They occupy 8, 16, 24 or 32 bits
per pixel. These are all packed-pixel formats, meaning all the data
for a pixel lie next to each other in memory.</para>
- <para>When one of these formats is used, drivers shall report the
-colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
-
<table pgwide="1" frame="none" id="rgb-formats">
<title>Packed RGB Image Formats</title>
<tgroup cols="37" align="center">
@@ -130,9 +127,9 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB444">
- <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
- <entry>'R444'</entry>
+ <row id="V4L2-PIX-FMT-ARGB444">
+ <entry><constant>V4L2_PIX_FMT_ARGB444</constant></entry>
+ <entry>'AR12'</entry>
<entry></entry>
<entry>g<subscript>3</subscript></entry>
<entry>g<subscript>2</subscript></entry>
@@ -152,9 +149,31 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>r<subscript>1</subscript></entry>
<entry>r<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB555">
- <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
- <entry>'RGBO'</entry>
+ <row id="V4L2-PIX-FMT-XRGB444">
+ <entry><constant>V4L2_PIX_FMT_XRGB444</constant></entry>
+ <entry>'XR12'</entry>
+ <entry></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-ARGB555">
+ <entry><constant>V4L2_PIX_FMT_ARGB555</constant></entry>
+ <entry>'AR15'</entry>
<entry></entry>
<entry>g<subscript>2</subscript></entry>
<entry>g<subscript>1</subscript></entry>
@@ -174,6 +193,28 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>g<subscript>4</subscript></entry>
<entry>g<subscript>3</subscript></entry>
</row>
+ <row id="V4L2-PIX-FMT-XRGB555">
+ <entry><constant>V4L2_PIX_FMT_XRGB555</constant></entry>
+ <entry>'XR15'</entry>
+ <entry></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ </row>
<row id="V4L2-PIX-FMT-RGB565">
<entry><constant>V4L2_PIX_FMT_RGB565</constant></entry>
<entry>'RGBP'</entry>
@@ -341,9 +382,9 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-BGR32">
- <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
- <entry>'BGR4'</entry>
+ <row id="V4L2-PIX-FMT-ABGR32">
+ <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
+ <entry>'AR24'</entry>
<entry></entry>
<entry>b<subscript>7</subscript></entry>
<entry>b<subscript>6</subscript></entry>
@@ -381,9 +422,49 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>a<subscript>1</subscript></entry>
<entry>a<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB32">
- <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
- <entry>'RGB4'</entry>
+ <row id="V4L2-PIX-FMT-XBGR32">
+ <entry><constant>V4L2_PIX_FMT_XBGR32</constant></entry>
+ <entry>'XR24'</entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ </row>
+ <row id="V4L2-PIX-FMT-ARGB32">
+ <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry>
+ <entry>'AX24'</entry>
<entry></entry>
<entry>a<subscript>7</subscript></entry>
<entry>a<subscript>6</subscript></entry>
@@ -421,18 +502,76 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
+ <row id="V4L2-PIX-FMT-XRGB32">
+ <entry><constant>V4L2_PIX_FMT_XRGB32</constant></entry>
+ <entry>'BX24'</entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
</tbody>
</tgroup>
</table>
- <para>Bit 7 is the most significant bit. The value of the a = alpha
-bits is undefined when reading from the driver, ignored when writing
-to the driver, except when alpha blending has been negotiated for a
-<link linkend="overlay">Video Overlay</link> or <link linkend="osd">
-Video Output Overlay</link> or when the alpha component has been configured
-for a <link linkend="capture">Video Capture</link> by means of <link
-linkend="v4l2-alpha-component"> <constant>V4L2_CID_ALPHA_COMPONENT
-</constant> </link> control.</para>
+ <para>Bit 7 is the most significant bit.</para>
+
+ <para>The usage and value of the alpha bits (a) in the ARGB and ABGR formats
+ (collectively referred to as alpha formats) depend on the device type and
+ hardware operation. <link linkend="capture">Capture</link> devices
+ (including capture queues of mem-to-mem devices) fill the alpha component in
+ memory. When the device outputs an alpha channel the alpha component will
+ have a meaningful value. Otherwise, when the device doesn't output an alpha
+ channel but can set the alpha bit to a user-configurable value, the <link
+ linkend="v4l2-alpha-component"><constant>V4L2_CID_ALPHA_COMPONENT</constant>
+ </link> control is used to specify that alpha value, and the alpha component
+ of all pixels will be set to the value specified by that control. Otherwise
+ a corresponding format without an alpha component (XRGB or XBGR) must be
+ used instead of an alpha format.</para>
+
+ <para><link linkend="output">Output</link> devices (including output queues
+ of mem-to-mem devices and <link linkend="osd">video output overlay</link>
+ devices) read the alpha component from memory. When the device processes the
+ alpha channel the alpha component must be filled with meaningful values by
+ applications. Otherwise a corresponding format without an alpha component
+ (XRGB or XBGR) must be used instead of an alpha format.</para>
+
+ <para>The XRGB and XBGR formats contain undefined bits (-). Applications,
+ devices and drivers must ignore those bits, for both <link
+ linkend="capture">capture</link> and <link linkend="output">output</link>
+ devices.</para>
<example>
<title><constant>V4L2_PIX_FMT_BGR24</constant> 4 &times; 4 pixel
@@ -512,6 +651,239 @@ image</title>
</formalpara>
</example>
+ <para>Formats defined in <xref linkend="rgb-formats-deprecated"/> are
+ deprecated and must not be used by new drivers. They are documented here for
+ reference. The meaning of their alpha bits (a) is ill-defined and
+ interpreted as in either the corresponding ARGB or XRGB format, depending on
+ the driver.</para>
+
+ <table pgwide="1" frame="none" id="rgb-formats-deprecated">
+ <title>Deprecated Packed RGB Image Formats</title>
+ <tgroup cols="37" align="center">
+ <colspec colname="id" align="left" />
+ <colspec colname="fourcc" />
+ <colspec colname="bit" />
+
+ <colspec colnum="4" colname="b07" align="center" />
+ <colspec colnum="5" colname="b06" align="center" />
+ <colspec colnum="6" colname="b05" align="center" />
+ <colspec colnum="7" colname="b04" align="center" />
+ <colspec colnum="8" colname="b03" align="center" />
+ <colspec colnum="9" colname="b02" align="center" />
+ <colspec colnum="10" colname="b01" align="center" />
+ <colspec colnum="11" colname="b00" align="center" />
+
+ <colspec colnum="13" colname="b17" align="center" />
+ <colspec colnum="14" colname="b16" align="center" />
+ <colspec colnum="15" colname="b15" align="center" />
+ <colspec colnum="16" colname="b14" align="center" />
+ <colspec colnum="17" colname="b13" align="center" />
+ <colspec colnum="18" colname="b12" align="center" />
+ <colspec colnum="19" colname="b11" align="center" />
+ <colspec colnum="20" colname="b10" align="center" />
+
+ <colspec colnum="22" colname="b27" align="center" />
+ <colspec colnum="23" colname="b26" align="center" />
+ <colspec colnum="24" colname="b25" align="center" />
+ <colspec colnum="25" colname="b24" align="center" />
+ <colspec colnum="26" colname="b23" align="center" />
+ <colspec colnum="27" colname="b22" align="center" />
+ <colspec colnum="28" colname="b21" align="center" />
+ <colspec colnum="29" colname="b20" align="center" />
+
+ <colspec colnum="31" colname="b37" align="center" />
+ <colspec colnum="32" colname="b36" align="center" />
+ <colspec colnum="33" colname="b35" align="center" />
+ <colspec colnum="34" colname="b34" align="center" />
+ <colspec colnum="35" colname="b33" align="center" />
+ <colspec colnum="36" colname="b32" align="center" />
+ <colspec colnum="37" colname="b31" align="center" />
+ <colspec colnum="38" colname="b30" align="center" />
+
+ <spanspec namest="b07" nameend="b00" spanname="b0" />
+ <spanspec namest="b17" nameend="b10" spanname="b1" />
+ <spanspec namest="b27" nameend="b20" spanname="b2" />
+ <spanspec namest="b37" nameend="b30" spanname="b3" />
+ <thead>
+ <row>
+ <entry>Identifier</entry>
+ <entry>Code</entry>
+ <entry>&nbsp;</entry>
+ <entry spanname="b0">Byte&nbsp;0 in memory</entry>
+ <entry spanname="b1">Byte&nbsp;1</entry>
+ <entry spanname="b2">Byte&nbsp;2</entry>
+ <entry spanname="b3">Byte&nbsp;3</entry>
+ </row>
+ <row>
+ <entry>&nbsp;</entry>
+ <entry>&nbsp;</entry>
+ <entry>Bit</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row id="V4L2-PIX-FMT-RGB444">
+ <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
+ <entry>'R444'</entry>
+ <entry></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-RGB555">
+ <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
+ <entry>'RGBO'</entry>
+ <entry></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a</entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-BGR32">
+ <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
+ <entry>'BGR4'</entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a<subscript>7</subscript></entry>
+ <entry>a<subscript>6</subscript></entry>
+ <entry>a<subscript>5</subscript></entry>
+ <entry>a<subscript>4</subscript></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-RGB32">
+ <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
+ <entry>'RGB4'</entry>
+ <entry></entry>
+ <entry>a<subscript>7</subscript></entry>
+ <entry>a<subscript>6</subscript></entry>
+ <entry>a<subscript>5</subscript></entry>
+ <entry>a<subscript>4</subscript></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<para>A test utility to determine which RGB formats a driver
actually supports is available from the LinuxTV v4l-dvb repository.
See &v4l-dvb; for access instructions.</para>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
new file mode 100644
index 000000000000..6118d8f7a20c
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
@@ -0,0 +1,44 @@
+<refentry id="V4L2-SDR-FMT-CS08">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CS8 ('CS08')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CS8</constant>
+ </refname>
+ <refpurpose>Complex signed 8-bit IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 8 bit signed number. I value comes first and Q value after
+that.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CS8</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="2" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0</subscript></entry>
+ </row>
+ <row>
+ <entry>start&nbsp;+&nbsp;1:</entry>
+ <entry>Q'<subscript>0</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
new file mode 100644
index 000000000000..e4b494ce1369
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
@@ -0,0 +1,47 @@
+<refentry id="V4L2-SDR-FMT-CS14LE">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CS14LE ('CS14')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CS14LE</constant>
+ </refname>
+ <refpurpose>Complex signed 14-bit little endian IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 14 bit signed little endian number. I value comes first
+and Q value after that. 14 bit value is stored in 16 bit space with unused
+high bits padded with 0.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CS14LE</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="3" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0[7:0]</subscript></entry>
+ <entry>I'<subscript>0[13:8]</subscript></entry>
+ </row>
+ <row>
+ <entry>start&nbsp;+&nbsp;2:</entry>
+ <entry>Q'<subscript>0[7:0]</subscript></entry>
+ <entry>Q'<subscript>0[13:8]</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
new file mode 100644
index 000000000000..3df076b99f94
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
@@ -0,0 +1,40 @@
+<refentry id="V4L2-SDR-FMT-RU12LE">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_RU12LE ('RU12')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_RU12LE</constant>
+ </refname>
+ <refpurpose>Real unsigned 12-bit little endian sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of real number samples. Each sample is
+represented as a 12 bit unsigned little endian number. Sample is stored
+in 16 bit space with unused high bits padded with 0.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_RU12LE</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="3" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0[7:0]</subscript></entry>
+ <entry>I'<subscript>0[11:8]</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
index 9ba4fb690bc0..96947f17fca1 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
@@ -18,7 +18,7 @@
<title>Description</title>
<para>The following four pixel formats are raw sRGB / Bayer formats with
-12 bits per colour. Each colour component is stored in a 16-bit word, with 6
+12 bits per colour. Each colour component is stored in a 16-bit word, with 4
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
stored in memory in little endian order. They are conventionally described
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 91dcbc84f3f8..df5b23d46552 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -112,9 +112,34 @@ see <xref linkend="colorspaces" />.</entry>
<row>
<entry>__u32</entry>
<entry><structfield>priv</structfield></entry>
- <entry>Reserved for custom (driver defined) additional
-information about formats. When not used drivers and applications must
-set this field to zero.</entry>
+ <entry><para>This field indicates whether the remaining fields of the
+<structname>v4l2_pix_format</structname> structure, also called the extended
+fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
+indicates that the extended fields have been correctly initialized. When set to
+any other value it indicates that the extended fields contain undefined values.
+</para>
+<para>Applications that wish to use the pixel format extended fields must first
+ensure that the feature is supported by querying the device for the
+<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
+capability. If the capability isn't set the pixel format extended fields are not
+supported and using the extended fields will lead to undefined results.</para>
+<para>To use the extended fields, applications must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
+and zero the unused bytes of the <structname>v4l2_format</structname>
+<structfield>raw_data</structfield> field.</para>
+<para>When the <structfield>priv</structfield> field isn't set to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
+extended fields were set to zero. On return drivers must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended fields to
+applicable values.</para></entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
</row>
</tbody>
</tgroup>
@@ -201,9 +226,15 @@ codes can be used.</entry>
and the number of valid entries in the
<structfield>plane_fmt</structfield> array.</entry>
</row>
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
+ </row>
<row>
<entry>__u8</entry>
- <entry><structfield>reserved[11]</structfield></entry>
+ <entry><structfield>reserved[10]</structfield></entry>
<entry>Reserved for future extensions. Should be zeroed by the
application.</entry>
</row>
@@ -248,7 +279,7 @@ has just as many pad bytes after it as the other rows.</para>
<para>In V4L2 each format has an identifier which looks like
<constant>PIX_FMT_XXX</constant>, defined in the <link
-linkend="videodev">videodev.h</link> header file. These identifiers
+linkend="videodev">videodev2.h</link> header file. These identifiers
represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
which are also listed below, however they are not the same as those
used in the Windows world.</para>
@@ -828,6 +859,9 @@ interface only.</para>
&sub-sdr-cu08;
&sub-sdr-cu16le;
+ &sub-sdr-cs08;
+ &sub-sdr-cs14le;
+ &sub-sdr-ru12le;
</section>
@@ -1060,4 +1094,21 @@ concatenated to form the JPEG stream. </para>
</tbody>
</tgroup>
</table>
+
+ <table frame="none" pgwide="1" id="format-flags">
+ <title>Format Flags</title>
+ <tgroup cols="3">
+ &cs-def;
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_PIX_FMT_FLAG_PREMUL_ALPHA</constant></entry>
+ <entry>0x00000001</entry>
+ <entry>The color values are premultiplied by the alpha channel
+value. For example, if a light blue pixel with 50% transparency was described by
+RGBA values (128, 192, 255, 128), the same pixel described with premultiplied
+colors would be described by RGBA values (64, 96, 128, 128) </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</section>
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
index 4c238ce068b0..28cbded766c9 100644
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/Documentation/DocBook/media/v4l/selection-api.xml
@@ -86,47 +86,47 @@ selection targets available for a video capture device. It is recommended to
configure the cropping targets before to the composing targets.</para>
<para>The range of coordinates of the top left corner, width and height of
-areas that can be sampled is given by the <constant> V4L2_SEL_TGT_CROP_BOUNDS
-</constant> target. It is recommended for the driver developers to put the
-top/left corner at position <constant> (0,0) </constant>. The rectangle's
+areas that can be sampled is given by the <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>
+target. It is recommended for the driver developers to put the
+top/left corner at position <constant>(0,0)</constant>. The rectangle's
coordinates are expressed in pixels.</para>
<para>The top left corner, width and height of the source rectangle, that is
-the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP
-</constant> target. It uses the same coordinate system as <constant>
-V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
-completely inside the capture boundaries. The driver may further adjust the
-requested size and/or position according to hardware limitations.</para>
+the area actually sampled, is given by the <constant>V4L2_SEL_TGT_CROP</constant>
+target. It uses the same coordinate system as <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
+The active cropping area must lie completely inside the capture boundaries. The
+driver may further adjust the requested size and/or position according to hardware
+limitations.</para>
<para>Each capture device has a default source rectangle, given by the
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant> target. This rectangle shall
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant> target. This rectangle shall
over what the driver writer considers the complete picture. Drivers shall set
the active crop rectangle to the default when the driver is first loaded, but
not later.</para>
<para>The composing targets refer to a memory buffer. The limits of composing
-coordinates are obtained using <constant> V4L2_SEL_TGT_COMPOSE_BOUNDS
-</constant>. All coordinates are expressed in pixels. The rectangle's top/left
-corner must be located at position <constant> (0,0) </constant>. The width and
-height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant>.
+All coordinates are expressed in pixels. The rectangle's top/left
+corner must be located at position <constant>(0,0)</constant>. The width and
+height are equal to the image size set by <constant>VIDIOC_S_FMT</constant>.
</para>
<para>The part of a buffer into which the image is inserted by the hardware is
-controlled by the <constant> V4L2_SEL_TGT_COMPOSE </constant> target.
+controlled by the <constant>V4L2_SEL_TGT_COMPOSE</constant> target.
The rectangle's coordinates are also expressed in the same coordinate system as
the bounds rectangle. The composing rectangle must lie completely inside bounds
rectangle. The driver must adjust the composing rectangle to fit to the
bounding limits. Moreover, the driver can perform other adjustments according
to hardware limitations. The application can control rounding behaviour using
-<link linkend="v4l2-selection-flags"> constraint flags </link>.</para>
+<link linkend="v4l2-selection-flags"> constraint flags</link>.</para>
<para>For capture devices the default composing rectangle is queried using
-<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant>. It is usually equal to the
bounding rectangle.</para>
<para>The part of a buffer that is modified by the hardware is given by
-<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
-defined using <constant> V4L2_SEL_TGT_COMPOSE </constant> plus all
+<constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>. It contains all pixels
+defined using <constant>V4L2_SEL_TGT_COMPOSE</constant> plus all
padding data modified by hardware during insertion process. All pixels outside
this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
content of pixels that lie inside the padded area but outside active area is
@@ -140,52 +140,51 @@ where the rubbish pixels are located and remove them if needed.</para>
<title>Configuration of video output</title>
<para>For output devices targets and ioctls are used similarly to the video
-capture case. The <emphasis> composing </emphasis> rectangle refers to the
+capture case. The <emphasis>composing</emphasis> rectangle refers to the
insertion of an image into a video signal. The cropping rectangles refer to a
memory buffer. It is recommended to configure the composing targets before to
the cropping targets.</para>
<para>The cropping targets refer to the memory buffer that contains an image to
be inserted into a video signal or graphical screen. The limits of cropping
-coordinates are obtained using <constant> V4L2_SEL_TGT_CROP_BOUNDS </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
All coordinates are expressed in pixels. The top/left corner is always point
-<constant> (0,0) </constant>. The width and height is equal to the image size
-specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
+<constant>(0,0)</constant>. The width and height is equal to the image size
+specified using <constant>VIDIOC_S_FMT</constant> ioctl.</para>
<para>The top left corner, width and height of the source rectangle, that is
the area from which image date are processed by the hardware, is given by the
-<constant> V4L2_SEL_TGT_CROP </constant>. Its coordinates are expressed
+<constant>V4L2_SEL_TGT_CROP</constant>. Its coordinates are expressed
in in the same coordinate system as the bounds rectangle. The active cropping
area must lie completely inside the crop boundaries and the driver may further
adjust the requested size and/or position according to hardware
limitations.</para>
<para>For output devices the default cropping rectangle is queried using
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant>. It is usually equal to the
bounding rectangle.</para>
<para>The part of a video signal or graphics display where the image is
-inserted by the hardware is controlled by <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target. The rectangle's coordinates
-are expressed in pixels. The composing rectangle must lie completely inside the
-bounds rectangle. The driver must adjust the area to fit to the bounding
-limits. Moreover, the driver can perform other adjustments according to
-hardware limitations. </para>
-
-<para>The device has a default composing rectangle, given by the <constant>
-V4L2_SEL_TGT_COMPOSE_DEFAULT </constant> target. This rectangle shall cover what
+inserted by the hardware is controlled by <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target. The rectangle's coordinates are expressed in pixels. The composing
+rectangle must lie completely inside the bounds rectangle. The driver must
+adjust the area to fit to the bounding limits. Moreover, the driver can
+perform other adjustments according to hardware limitations.</para>
+
+<para>The device has a default composing rectangle, given by the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant> target. This rectangle shall cover what
the driver writer considers the complete picture. It is recommended for the
-driver developers to put the top/left corner at position <constant> (0,0)
-</constant>. Drivers shall set the active composing rectangle to the default
+driver developers to put the top/left corner at position <constant>(0,0)</constant>.
+Drivers shall set the active composing rectangle to the default
one when the driver is first loaded.</para>
<para>The devices may introduce additional content to video signal other than
an image from memory buffers. It includes borders around an image. However,
such a padded area is driver-dependent feature not covered by this document.
Driver developers are encouraged to keep padded rectangle equal to active one.
-The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
-</constant> identifier. It must contain all pixels from the <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target.</para>
+The padded target is accessed by the <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>
+identifier. It must contain all pixels from the <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target.</para>
</section>
@@ -194,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE </constant> target.</para>
<title>Scaling control</title>
<para>An application can detect if scaling is performed by comparing the width
-and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
-</constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
+and the height of rectangles obtained using <constant>V4L2_SEL_TGT_CROP</constant>
+and <constant>V4L2_SEL_TGT_COMPOSE</constant> targets. If
these are not equal then the scaling is applied. The application can compute
the scaling ratios using these values.</para>
@@ -208,7 +207,7 @@ the scaling ratios using these values.</para>
<title>Comparison with old cropping API</title>
<para>The selection API was introduced to cope with deficiencies of previous
-<link linkend="crop"> API </link>, that was designed to control simple capture
+<link linkend="crop"> API</link>, that was designed to control simple capture
devices. Later the cropping API was adopted by video output drivers. The ioctls
are used to select a part of the display were the video signal is inserted. It
should be considered as an API abuse because the described operation is
@@ -220,7 +219,7 @@ part of an image by abusing V4L2 API. Cropping a smaller image from a larger
one is achieved by setting the field
&v4l2-pix-format;<structfield>::bytesperline</structfield>. Introducing an image offsets
could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield>
-before calling <constant> VIDIOC_QBUF </constant>. Those
+before calling <constant>VIDIOC_QBUF</constant>. Those
operations should be avoided because they are not portable (endianness), and do
not work for macroblock and Bayer formats and mmap buffers. The selection API
deals with configuration of buffer cropping/composing in a clear, intuitive and
@@ -229,7 +228,7 @@ and constraints flags are introduced. Finally, &v4l2-crop; and &v4l2-cropcap;
have no reserved fields. Therefore there is no way to extend their functionality.
The new &v4l2-selection; provides a lot of place for future
extensions. Driver developers are encouraged to implement only selection API.
-The former cropping API would be simulated using the new one. </para>
+The former cropping API would be simulated using the new one.</para>
</section>
@@ -238,9 +237,9 @@ The former cropping API would be simulated using the new one. </para>
<example>
<title>Resetting the cropping parameters</title>
- <para>(A video capture device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_CAPTURE </constant> for other devices; change target to
-<constant> V4L2_SEL_TGT_COMPOSE_* </constant> family to configure composing
+ <para>(A video capture device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other devices; change target to
+<constant>V4L2_SEL_TGT_COMPOSE_*</constant> family to configure composing
area)</para>
<programlisting>
@@ -292,8 +291,8 @@ area)</para>
<example>
<title>Querying for scaling factors</title>
- <para>A video output device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
+ <para>A video output device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> for other devices</para>
<programlisting>
&v4l2-selection; compose = {
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index b445161b912c..f2f81f06a17b 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -152,6 +152,14 @@ structs, ioctls) must be noted in more detail in the history chapter
applications. -->
<revision>
+ <revnumber>3.16</revnumber>
+ <date>2014-05-27</date>
+ <authorinitials>lp</authorinitials>
+ <revremark>Extended &v4l2-pix-format;. Added format flags.
+ </revremark>
+ </revision>
+
+ <revision>
<revnumber>3.15</revnumber>
<date>2014-02-03</date>
<authorinitials>hv, ap</authorinitials>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
index 820f86e8744b..cb7732582f03 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
@@ -94,6 +94,18 @@
</row>
<row>
<entry></entry>
+ <entry>&v4l2-event-motion-det;</entry>
+ <entry><structfield>motion_det</structfield></entry>
+ <entry>Event data for event V4L2_EVENT_MOTION_DET.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>&v4l2-event-src-change;</entry>
+ <entry><structfield>src_change</structfield></entry>
+ <entry>Event data for event V4L2_EVENT_SOURCE_CHANGE.</entry>
+ </row>
+ <row>
+ <entry></entry>
<entry>__u8</entry>
<entry><structfield>data</structfield>[64]</entry>
<entry>Event data. Defined by the event type. The union
@@ -258,6 +270,44 @@
</tgroup>
</table>
+ <table frame="none" pgwide="1" id="v4l2-event-motion-det">
+ <title>struct <structname>v4l2_event_motion_det</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>
+ Currently only one flag is available: if <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant>
+ is set, then the <structfield>frame_sequence</structfield> field is valid,
+ otherwise that field should be ignored.
+ </entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>frame_sequence</structfield></entry>
+ <entry>
+ The sequence number of the frame being received. Only valid if the
+ <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant> flag was set.
+ </entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>region_mask</structfield></entry>
+ <entry>
+ The bitmask of the regions that reported motion. There is at least one
+ region. If this field is 0, then no motion was detected at all.
+ If there is no <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> control
+ (see <xref linkend="detect-controls" />) to assign a different region
+ to each cell in the motion detection grid, then that all cells
+ are automatically assigned to the default region 0.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<table pgwide="1" frame="none" id="changes-flags">
<title>Changes</title>
<tgroup cols="3">
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index e9f6735c0823..c5bdbfcc42b3 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -72,23 +72,30 @@ initialize the <structfield>id</structfield>,
<structfield>size</structfield> and <structfield>reserved2</structfield> fields
of each &v4l2-ext-control; and call the
<constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
-must also set the <structfield>string</structfield> field.</para>
+must also set the <structfield>string</structfield> field. Controls
+of compound types (<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set)
+must set the <structfield>ptr</structfield> field.</para>
<para>If the <structfield>size</structfield> is too small to
receive the control result (only relevant for pointer-type controls
like strings), then the driver will set <structfield>size</structfield>
to a valid value and return an &ENOSPC;. You should re-allocate the
-string memory to this new size and try again. It is possible that the
-same issue occurs again if the string has grown in the meantime. It is
+memory to this new size and try again. For the string type it is possible that
+the same issue occurs again if the string has grown in the meantime. It is
recommended to call &VIDIOC-QUERYCTRL; first and use
<structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
value. It is guaranteed that that is sufficient memory.
</para>
+ <para>N-dimensional arrays are set and retrieved row-by-row. You cannot set a partial
+array, all elements have to be set or retrieved. The total size is calculated
+as <structfield>elems</structfield> * <structfield>elem_size</structfield>.
+These values can be obtained by calling &VIDIOC-QUERY-EXT-CTRL;.</para>
+
<para>To change the value of a set of controls applications
initialize the <structfield>id</structfield>, <structfield>size</structfield>,
<structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
will only be set if <emphasis>all</emphasis> control values are
valid.</para>
@@ -96,7 +103,7 @@ valid.</para>
<para>To check if a set of controls have correct values applications
initialize the <structfield>id</structfield>, <structfield>size</structfield>,
<structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
the driver whether wrong values are automatically adjusted to a valid
value or if an error is returned.</para>
@@ -158,19 +165,47 @@ applications must set the array to zero.</entry>
<entry></entry>
<entry>__s32</entry>
<entry><structfield>value</structfield></entry>
- <entry>New value or current value.</entry>
+ <entry>New value or current value. Valid if this control is not of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
</row>
<row>
<entry></entry>
<entry>__s64</entry>
<entry><structfield>value64</structfield></entry>
- <entry>New value or current value.</entry>
+ <entry>New value or current value. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
</row>
<row>
<entry></entry>
<entry>char *</entry>
<entry><structfield>string</structfield></entry>
- <entry>A pointer to a string.</entry>
+ <entry>A pointer to a string. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__u8 *</entry>
+ <entry><structfield>p_u8</structfield></entry>
+ <entry>A pointer to a matrix control of unsigned 8-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U8</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__u16 *</entry>
+ <entry><structfield>p_u16</structfield></entry>
+ <entry>A pointer to a matrix control of unsigned 16-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U16</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>void *</entry>
+ <entry><structfield>ptr</structfield></entry>
+ <entry>A pointer to a compound type which can be an N-dimensional array and/or a
+compound type (the control's type is >= <constant>V4L2_CTRL_COMPOUND_TYPES</constant>).
+Valid if <constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set for this control.
+</entry>
</row>
</tbody>
</tgroup>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
index 7c63815e7afd..20460730b02c 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
@@ -152,13 +152,10 @@ a valid base address, so applications can find the corresponding Linux
framebuffer device (see <xref linkend="osd" />).</entry>
</row>
<row>
- <entry>&v4l2-pix-format;</entry>
+ <entry>struct</entry>
<entry><structfield>fmt</structfield></entry>
<entry></entry>
- <entry>Layout of the frame buffer. The
-<structname>v4l2_pix_format</structname> structure is defined in <xref
-linkend="pixfmt" />, for clarification the fields and acceptable values
- are listed below:</entry>
+ <entry>Layout of the frame buffer.</entry>
</row>
<row>
<entry></entry>
@@ -276,9 +273,8 @@ see <xref linkend="colorspaces" />.</entry>
<entry></entry>
<entry>__u32</entry>
<entry><structfield>priv</structfield></entry>
- <entry>Reserved for additional information about custom
-(driver defined) formats. When not used drivers and applications must
-set this field to zero.</entry>
+ <entry>Reserved. Drivers and applications must set this field to
+zero.</entry>
</row>
</tbody>
</tgroup>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index b11ec75e21a1..9c04ac8661b1 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -58,17 +58,16 @@
<para>The ioctls are used to query and configure selection rectangles.</para>
-<para> To query the cropping (composing) rectangle set &v4l2-selection;
+<para>To query the cropping (composing) rectangle set &v4l2-selection;
<structfield> type </structfield> field to the respective buffer type.
-Do not use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
+Do not use multiplanar buffers. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> field
-to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets. The <structfield>flags</structfield> and <structfield>reserved
+to <constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets. The <structfield>flags</structfield> and <structfield>reserved
</structfield> fields of &v4l2-selection; are ignored and they must be filled
with zeros. The driver fills the rest of the structure or
returns &EINVAL; if incorrect buffer type or target was used. If cropping
@@ -77,19 +76,18 @@ always equal to the bounds rectangle. Finally, the &v4l2-rect;
<structfield>r</structfield> rectangle is filled with the current cropping
(composing) coordinates. The coordinates are expressed in driver-dependent
units. The only exception are rectangles for images in raw formats, whose
-coordinates are always expressed in pixels. </para>
+coordinates are always expressed in pixels.</para>
-<para> To change the cropping (composing) rectangle set the &v4l2-selection;
+<para>To change the cropping (composing) rectangle set the &v4l2-selection;
<structfield>type</structfield> field to the respective buffer type. Do not
-use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
+use multiplanar buffers. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> to
-<constant>V4L2_SEL_TGT_CROP</constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
+<constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
set to the desired active area. Field &v4l2-selection; <structfield> reserved
</structfield> is ignored and must be filled with zeros. The driver may adjust
coordinates of the requested rectangle. An application may
@@ -149,8 +147,8 @@ On success the &v4l2-rect; <structfield>r</structfield> field contains
the adjusted rectangle. When the parameters are unsuitable the application may
modify the cropping (composing) or image parameters and repeat the cycle until
satisfactory parameters have been negotiated. If constraints flags have to be
-violated at then ERANGE is returned. The error indicates that <emphasis> there
-exist no rectangle </emphasis> that satisfies the constraints.</para>
+violated at then ERANGE is returned. The error indicates that <emphasis>there
+exist no rectangle</emphasis> that satisfies the constraints.</para>
<para>Selection targets and flags are documented in <xref
linkend="v4l2-selections-common"/>.</para>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
index 370d49d6fb64..d0c5e604f014 100644
--- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
@@ -302,6 +302,12 @@ modulator programming see
<link linkend="sdr">SDR Capture</link> interface.</entry>
</row>
<row>
+ <entry><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></entry>
+ <entry>0x00200000</entry>
+ <entry>The device supports the &v4l2-pix-format; extended
+fields.</entry>
+ </row>
+ <row>
<entry><constant>V4L2_CAP_READWRITE</constant></entry>
<entry>0x01000000</entry>
<entry>The device supports the <link
diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
index e6645b996558..2bd98fd7a4e5 100644
--- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
@@ -1,11 +1,12 @@
<refentry id="vidioc-queryctrl">
<refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</refentrytitle>
+ <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_QUERYCTRL</refname>
+ <refname>VIDIOC_QUERY_EXT_CTRL</refname>
<refname>VIDIOC_QUERYMENU</refname>
<refpurpose>Enumerate controls and menu control items</refpurpose>
</refnamediv>
@@ -24,6 +25,14 @@
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
+ <paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ <funcsynopsis>
+ <funcprototype>
+ <funcdef>int <function>ioctl</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>int <parameter>request</parameter></paramdef>
<paramdef>struct v4l2_querymenu *<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
@@ -42,7 +51,7 @@
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
- <para>VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</para>
+ <para>VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -67,7 +76,7 @@ structure. The driver fills the rest of the structure or returns an
<constant>VIDIOC_QUERYCTRL</constant> with successive
<structfield>id</structfield> values starting from
<constant>V4L2_CID_BASE</constant> up to and exclusive
-<constant>V4L2_CID_BASE_LASTP1</constant>. Drivers may return
+<constant>V4L2_CID_LASTP1</constant>. Drivers may return
<errorcode>EINVAL</errorcode> if a control in this range is not
supported. Further applications can enumerate private controls, which
are not defined in this specification, by starting at
@@ -89,9 +98,23 @@ prematurely end the enumeration).</para></footnote></para>
<para>When the application ORs <structfield>id</structfield> with
<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
-next supported control, or <errorcode>EINVAL</errorcode> if there is
-none. Drivers which do not support this flag yet always return
-<errorcode>EINVAL</errorcode>.</para>
+next supported non-compound control, or <errorcode>EINVAL</errorcode>
+if there is none. In addition, the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+flag can be specified to enumerate all compound controls (i.e. controls
+with type &ge; <constant>V4L2_CTRL_COMPOUND_TYPES</constant>). Specify both
+<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
+<constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> in order to enumerate
+all controls, compound or not. Drivers which do not support these flags yet
+always return <errorcode>EINVAL</errorcode>.</para>
+
+ <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
+introduced in order to better support controls that can use compound
+types, and to expose additional control information that cannot be
+returned in &v4l2-queryctrl; since that structure is full.</para>
+
+ <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
+same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
+<structfield>reserved</structfield> array must be zeroed as well.</para>
<para>Additional information is required for menu controls: the
names of the menu items. To query them applications set the
@@ -142,38 +165,23 @@ string. This information is intended for the user.</entry>
<entry>__s32</entry>
<entry><structfield>minimum</structfield></entry>
<entry>Minimum value, inclusive. This field gives a lower
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
-gives the minimum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
</row>
<row>
<entry>__s32</entry>
<entry><structfield>maximum</structfield></entry>
<entry>Maximum value, inclusive. This field gives an upper
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
-controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
-set of usable bits.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
-gives the maximum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
</row>
<row>
<entry>__s32</entry>
<entry><structfield>step</structfield></entry>
- <entry><para>This field gives a step size for
-<constant>V4L2_CTRL_TYPE_INTEGER</constant> controls. For
-<constant>V4L2_CTRL_TYPE_STRING</constant> controls this field refers to
-the string length that has to be a multiple of this step size.
-It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant>
-controls.</para><para>Generally drivers should not scale hardware
+ <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 32-bit value.
+</para><para>Generally drivers should not scale hardware
control values. It may be necessary for example when the
<structfield>name</structfield> or <structfield>id</structfield> imply
a particular unit and the hardware actually accepts only multiples of
@@ -192,10 +200,11 @@ be always positive.</para></entry>
<entry><structfield>default_value</structfield></entry>
<entry>The default value of a
<constant>V4L2_CTRL_TYPE_INTEGER</constant>,
-<constant>_BOOLEAN</constant> or <constant>_MENU</constant> control.
-Not valid for other types of controls. Drivers reset controls only
-when the driver is loaded, not later, in particular not when the
-func-open; is called.</entry>
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.</entry>
</row>
<row>
<entry>__u32</entry>
@@ -213,6 +222,126 @@ the array to zero.</entry>
</tgroup>
</table>
+ <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
+ <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>id</structfield></entry>
+ <entry>Identifies the control, set by the application. See
+<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
+with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
+flag and returns the first non-compound control with a higher ID. When the
+ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> the driver
+clears the flag and returns the first compound control with a higher ID.
+Set both to get the first control (compound or not) with a higher ID.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>type</structfield></entry>
+ <entry>Type of control, see <xref
+ linkend="v4l2-ctrl-type" />.</entry>
+ </row>
+ <row>
+ <entry>char</entry>
+ <entry><structfield>name</structfield>[32]</entry>
+ <entry>Name of the control, a NUL-terminated ASCII
+string. This information is intended for the user.</entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>minimum</structfield></entry>
+ <entry>Minimum value, inclusive. This field gives a lower
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>maximum</structfield></entry>
+ <entry>Maximum value, inclusive. This field gives an upper
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+ </row>
+ <row>
+ <entry>__u64</entry>
+ <entry><structfield>step</structfield></entry>
+ <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 64-bit value.
+</para><para>Generally drivers should not scale hardware
+control values. It may be necessary for example when the
+<structfield>name</structfield> or <structfield>id</structfield> imply
+a particular unit and the hardware actually accepts only multiples of
+said unit. If so, drivers must take care values are properly rounded
+when scaling, such that errors will not accumulate on repeated
+read-write cycles.</para><para>This field gives the smallest change of
+an integer control actually affecting hardware. Often the information
+is needed when the user can change controls by keyboard or GUI
+buttons, rather than a slider. When for example a hardware register
+accepts values 0-511 and the driver reports 0-65535, step should be
+128.</para></entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>default_value</structfield></entry>
+ <entry>The default value of a
+<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant>, <constant>_INTEGER_MENU</constant>,
+<constant>_U8</constant> or <constant>_U16</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.
+</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Control flags, see <xref
+ linkend="control-flags" />.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>elem_size</structfield></entry>
+ <entry>The size in bytes of a single element of the array.
+Given a char pointer <constant>p</constant> to a 3-dimensional array you can find the
+position of cell <constant>(z, y, x)</constant> as follows:
+<constant>p + ((z * dims[1] + y) * dims[0] + x) * elem_size</constant>. <structfield>elem_size</structfield>
+is always valid, also when the control isn't an array. For string controls
+<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
+</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>elems</structfield></entry>
+ <entry>The number of elements in the N-dimensional array. If this control
+is not an array, then <structfield>elems</structfield> is 1. The <structfield>elems</structfield>
+field can never be 0.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>nr_of_dims</structfield></entry>
+ <entry>The number of dimension in the N-dimensional array. If this control
+is not an array, then this field is 0.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>dims[V4L2_CTRL_MAX_DIMS]</structfield></entry>
+ <entry>The size of each dimension. The first <structfield>nr_of_dims</structfield>
+elements of this array must be non-zero, all remaining elements must be zero.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>reserved</structfield>[32]</entry>
+ <entry>Reserved for future extensions. Applications and drivers
+must set the array to zero.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<table pgwide="1" frame="none" id="v4l2-querymenu">
<title>struct <structname>v4l2_querymenu</structname></title>
<tgroup cols="4">
@@ -347,11 +476,14 @@ Drivers must ignore the value passed with
</row>
<row>
<entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
<entry>A 64-bit integer valued control. Minimum, maximum
-and step size cannot be queried.</entry>
+and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
+Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
+min/max/step values, they should be interpreted as n/a when using
+<constant>VIDIOC_QUERYCTRL</constant>.</entry>
</row>
<row>
<entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
@@ -379,6 +511,26 @@ ioctl returns the name of the control class and this control type.
Older drivers which do not support this feature return an
&EINVAL;.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_CTRL_TYPE_U8</constant></entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>An unsigned 8-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_CTRL_TYPE_U16</constant></entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>An unsigned 16-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -450,6 +602,14 @@ is in auto-gain mode. In such a case the hardware calculates the gain value base
the lighting conditions which can change over time. Note that setting a new value for
a volatile control will have no effect. The new value will just be ignored.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
+ <entry>0x0100</entry>
+ <entry>This control has a pointer type, so its value has to be accessed
+using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
+that are an array, string, or have a compound type. In all cases you have to set a
+pointer to memory containing the payload of the control.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
index 17efa870d4d2..9f6095608837 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
@@ -175,6 +175,14 @@
</entry>
</row>
<row>
+ <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
+ <entry>5</entry>
+ <entry>
+ <para>Triggered whenever the motion detection state for one or more of the regions
+ changes. This event has a &v4l2-event-motion-det; associated with it.</para>
+ </entry>
+ </row>
+ <row>
<entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
<entry>0x08000000</entry>
<entry>Base event number for driver-private events.</entry>
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt
index 10a93696e55a..0d920d54536d 100644
--- a/Documentation/PCI/MSI-HOWTO.txt
+++ b/Documentation/PCI/MSI-HOWTO.txt
@@ -576,7 +576,7 @@ Some devices are known to have faulty MSI implementations. Usually this
is handled in the individual device driver, but occasionally it's necessary
to handle this with a quirk. Some drivers have an option to disable use
of MSI. While this is a convenient workaround for the driver author,
-it is not good practise, and should not be emulated.
+it is not good practice, and should not be emulated.
5.4. Finding why MSIs are disabled on a device
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index 2f0fcb2112d2..f29bcbc463e7 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -2451,8 +2451,8 @@ lot of {Linux} into your technology!!!"
,month="February"
,year="2010"
,note="Available:
-\url{http://kerneltrap.com/mailarchive/linux-netdev/2010/2/26/6270589}
-[Viewed March 20, 2011]"
+\url{http://thread.gmane.org/gmane.linux.network/153338}
+[Viewed June 9, 2014]"
,annotation={
Use a pair of list_head structures to support RCU-protected
resizable hash tables.
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
index 141d531aa14b..613033ff2b9b 100644
--- a/Documentation/RCU/rcuref.txt
+++ b/Documentation/RCU/rcuref.txt
@@ -1,5 +1,14 @@
Reference-count design for elements of lists/arrays protected by RCU.
+
+Please note that the percpu-ref feature is likely your first
+stop if you need to combine reference counts and RCU. Please see
+include/linux/percpu-refcount.h for more information. However, in
+those unusual cases where percpu-ref would consume too much memory,
+please read on.
+
+------------------------------------------------------------------------
+
Reference counting on elements of lists which are protected by traditional
reader/writer spinlocks or semaphores are straightforward:
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 49b8551a3b68..e48c57f1943b 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -818,7 +818,7 @@ RCU pointer/list update:
list_add_tail_rcu
list_del_rcu
list_replace_rcu
- hlist_add_after_rcu
+ hlist_add_behind_rcu
hlist_add_before_rcu
hlist_add_head_rcu
hlist_del_rcu
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 36d16bbf72c6..31d372609ac0 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -146,10 +146,6 @@ LWN.net:
Porting drivers from prior kernels to 2.6:
http://lwn.net/Articles/driver-porting/
-KernelTrap:
- Occasional Linux kernel articles and developer interviews
- http://kerneltrap.org/
-
KernelNewbies:
Documentation and assistance for new kernel programmers
http://kernelnewbies.org/
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 7e9abb8a276b..0a523c9a5ff4 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -84,18 +84,42 @@ is another popular alternative.
2) Describe your changes.
-Describe the technical detail of the change(s) your patch includes.
-
-Be as specific as possible. The WORST descriptions possible include
-things like "update driver X", "bug fix for driver X", or "this patch
-includes updates for subsystem X. Please apply."
+Describe your problem. Whether your patch is a one-line bug fix or
+5000 lines of a new feature, there must be an underlying problem that
+motivated you to do this work. Convince the reviewer that there is a
+problem worth fixing and that it makes sense for them to read past the
+first paragraph.
+
+Describe user-visible impact. Straight up crashes and lockups are
+pretty convincing, but not all bugs are that blatant. Even if the
+problem was spotted during code review, describe the impact you think
+it can have on users. Keep in mind that the majority of Linux
+installations run kernels from secondary stable trees or
+vendor/product-specific trees that cherry-pick only specific patches
+from upstream, so include anything that could help route your change
+downstream: provoking circumstances, excerpts from dmesg, crash
+descriptions, performance regressions, latency spikes, lockups, etc.
+
+Quantify optimizations and trade-offs. If you claim improvements in
+performance, memory consumption, stack footprint, or binary size,
+include numbers that back them up. But also describe non-obvious
+costs. Optimizations usually aren't free but trade-offs between CPU,
+memory, and readability; or, when it comes to heuristics, between
+different workloads. Describe the expected downsides of your
+optimization so that the reviewer can weigh costs against benefits.
+
+Once the problem is established, describe what you are actually doing
+about it in technical detail. It's important to describe the change
+in plain English for the reviewer to verify that the code is behaving
+as you intend it to.
The maintainer will thank you if you write your patch description in a
form which can be easily pulled into Linux's source code management
system, git, as a "commit log". See #15, below.
-If your description starts to get long, that's a sign that you probably
-need to split up your patch. See #3, next.
+Solve only one problem per patch. If your description starts to get
+long, that's a sign that you probably need to split up your patch.
+See #3, next.
When you submit or resubmit a patch or patch series, include the
complete patch description and justification for it. Don't just
@@ -396,13 +420,13 @@ you are responsible for last-minute changes. Example :
[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
-This practise is particularly helpful if you maintain a stable branch and
+This practice is particularly helpful if you maintain a stable branch and
want at the same time to credit the author, track changes, merge the fix,
and protect the submitter from complaints. Note that under no circumstances
can you change the author's identity (the From header), as it is the one
which appears in the changelog.
-Special note to back-porters: It seems to be a common and useful practise
+Special note to back-porters: It seems to be a common and useful practice
to insert an indication of the origin of a patch at the top of the commit
message (just after the subject line) to facilitate tracking. For instance,
here's what we see in 2.6-stable :
diff --git a/Documentation/arm/CCN.txt b/Documentation/arm/CCN.txt
new file mode 100644
index 000000000000..0632b3aad83e
--- /dev/null
+++ b/Documentation/arm/CCN.txt
@@ -0,0 +1,52 @@
+ARM Cache Coherent Network
+==========================
+
+CCN-504 is a ring-bus interconnect consisting of 11 crosspoints
+(XPs), with each crosspoint supporting up to two device ports,
+so nodes (devices) 0 and 1 are connected to crosspoint 0,
+nodes 2 and 3 to crosspoint 1 etc.
+
+PMU (perf) driver
+-----------------
+
+The CCN driver registers a perf PMU driver, which provides
+description of available events and configuration options
+in sysfs, see /sys/bus/event_source/devices/ccn*.
+
+The "format" directory describes format of the config, config1
+and config2 fields of the perf_event_attr structure. The "events"
+directory provides configuration templates for all documented
+events, that can be used with perf tool. For example "xp_valid_flit"
+is an equivalent of "type=0x8,event=0x4". Other parameters must be
+explicitly specified. For events originating from device, "node"
+defines its index. All crosspoint events require "xp" (index),
+"port" (device port number) and "vc" (virtual channel ID) and
+"dir" (direction). Watchpoints (special "event" value 0xfe) also
+require comparator values ("cmp_l" and "cmp_h") and "mask", being
+index of the comparator mask.
+
+Masks are defined separately from the event description
+(due to limited number of the config values) in the "cmp_mask"
+directory, with first 8 configurable by user and additional
+4 hardcoded for the most frequent use cases.
+
+Cycle counter is described by a "type" value 0xff and does
+not require any other settings.
+
+Example of perf tool use:
+
+/ # perf list | grep ccn
+ ccn/cycles/ [Kernel PMU event]
+<...>
+ ccn/xp_valid_flit/ [Kernel PMU event]
+<...>
+
+/ # perf stat -C 0 -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \
+ sleep 1
+
+The driver does not support sampling, therefore "perf record" will
+not work. Also notice that only single cpu is being selected
+("-C 0") - this is because perf framework does not support
+"non-CPU related" counters (yet?) so system-wide session ("-a")
+would try (and in most cases fail) to set up the same event
+per each CPU.
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README
index 2cce5401e323..4dc66c173e10 100644
--- a/Documentation/arm/Marvell/README
+++ b/Documentation/arm/Marvell/README
@@ -53,8 +53,8 @@ Kirkwood family
Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
Homepage: http://www.marvell.com/embedded-processors/kirkwood/
Core: Feroceon ARMv5 compatible
- Linux kernel mach directory: arch/arm/mach-kirkwood
- Linux kernel plat directory: arch/arm/plat-orion
+ Linux kernel mach directory: arch/arm/mach-mvebu
+ Linux kernel plat directory: none
Discovery family
----------------
@@ -83,7 +83,9 @@ EBU Armada family
88F6710
88F6707
88F6W11
- Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
+ Product Brief: http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
+ Hardware Spec: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-datasheet.pdf
+ Functional Spec: http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
Armada 375 Flavors:
88F6720
@@ -100,8 +102,7 @@ EBU Armada family
MV78460
NOTE: not to be confused with the non-SMP 78xx0 SoCs
Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
-
- No public datasheet available.
+ Functional Spec: http://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
Core: Sheeva ARMv7 compatible
@@ -135,7 +136,9 @@ Dove family (application processor)
Functional Spec : http://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf
Homepage: http://www.marvell.com/application-processors/armada-500/
Core: ARMv7 compatible
- Directory: arch/arm/mach-dove
+
+ Directory: arch/arm/mach-mvebu (DT enabled platforms)
+ arch/arm/mach-dove (non-DT enabled platforms)
PXA 2xx/3xx/93x/95x family
--------------------------
@@ -253,10 +256,10 @@ Berlin family (Digital Entertainment)
Long-term plans
---------------
- * Unify the mach-dove/, mach-mv78xx0/, mach-orion5x/ and
- mach-kirkwood/ into the mach-mvebu/ to support all SoCs from the
- Marvell EBU (Engineering Business Unit) in a single mach-<foo>
- directory. The plat-orion/ would therefore disappear.
+ * Unify the mach-dove/, mach-mv78xx0/, mach-orion5x/ into the
+ mach-mvebu/ to support all SoCs from the Marvell EBU (Engineering
+ Business Unit) in a single mach-<foo> directory. The plat-orion/
+ would therefore disappear.
* Unify the mach-mmp/ and mach-pxa/ into the same mach-pxa
directory. The plat-pxa/ would therefore disappear.
diff --git a/Documentation/arm/Samsung/Overview.txt b/Documentation/arm/Samsung/Overview.txt
index 658abb258cef..8f7309bad460 100644
--- a/Documentation/arm/Samsung/Overview.txt
+++ b/Documentation/arm/Samsung/Overview.txt
@@ -13,8 +13,6 @@ Introduction
- S3C24XX: See Documentation/arm/Samsung-S3C24XX/Overview.txt for full list
- S3C64XX: S3C6400 and S3C6410
- - S5P6440
- - S5PC100
- S5PC110 / S5PV210
@@ -34,8 +32,6 @@ Configuration
A number of configurations are supplied, as there is no current way of
unifying all the SoCs into one kernel.
- s5p6440_defconfig - S5P6440 specific default configuration
- s5pc100_defconfig - S5PC100 specific default configuration
s5pc110_defconfig - S5PC110 specific default configuration
s5pv210_defconfig - S5PV210 specific default configuration
@@ -67,13 +63,6 @@ Layout changes
where to simplify the include and dependency issues involved with having
so many different platform directories.
- It was decided to remove plat-s5pc1xx as some of the support was already
- in plat-s5p or plat-samsung, with the S5PC110 support added with S5PV210
- the only user was the S5PC100. The S5PC100 specific items where moved to
- arch/arm/mach-s5pc100.
-
-
-
Port Contributors
-----------------
diff --git a/Documentation/arm/Samsung/clksrc-change-registers.awk b/Documentation/arm/Samsung/clksrc-change-registers.awk
index 0c50220851fb..d9174fabe37e 100755
--- a/Documentation/arm/Samsung/clksrc-change-registers.awk
+++ b/Documentation/arm/Samsung/clksrc-change-registers.awk
@@ -68,7 +68,6 @@ BEGIN {
while (getline line < ARGV[1] > 0) {
if (line ~ /\#define.*_MASK/ &&
- !(line ~ /S5PC100_EPLL_MASK/) &&
!(line ~ /USB_SIG_MASK/)) {
splitdefine(line, fields)
name = fields[0]
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 37fc4f632176..f3c05b5f9f08 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -72,27 +72,54 @@ The decompressed kernel image contains a 64-byte header as follows:
u32 code0; /* Executable code */
u32 code1; /* Executable code */
- u64 text_offset; /* Image load offset */
- u64 res0 = 0; /* reserved */
- u64 res1 = 0; /* reserved */
+ u64 text_offset; /* Image load offset, little endian */
+ u64 image_size; /* Effective Image size, little endian */
+ u64 flags; /* kernel flags, little endian */
u64 res2 = 0; /* reserved */
u64 res3 = 0; /* reserved */
u64 res4 = 0; /* reserved */
u32 magic = 0x644d5241; /* Magic number, little endian, "ARM\x64" */
- u32 res5 = 0; /* reserved */
+ u32 res5; /* reserved (used for PE COFF offset) */
Header notes:
+- As of v3.17, all fields are little endian unless stated otherwise.
+
- code0/code1 are responsible for branching to stext.
+
- when booting through EFI, code0/code1 are initially skipped.
res5 is an offset to the PE header and the PE header has the EFI
- entry point (efi_stub_entry). When the stub has done its work, it
+ entry point (efi_stub_entry). When the stub has done its work, it
jumps to code0 to resume the normal boot process.
-The image must be placed at the specified offset (currently 0x80000)
-from the start of the system RAM and called there. The start of the
-system RAM must be aligned to 2MB.
+- Prior to v3.17, the endianness of text_offset was not specified. In
+ these cases image_size is zero and text_offset is 0x80000 in the
+ endianness of the kernel. Where image_size is non-zero image_size is
+ little-endian and must be respected. Where image_size is zero,
+ text_offset can be assumed to be 0x80000.
+
+- The flags field (introduced in v3.17) is a little-endian 64-bit field
+ composed as follows:
+ Bit 0: Kernel endianness. 1 if BE, 0 if LE.
+ Bits 1-63: Reserved.
+
+- When image_size is zero, a bootloader should attempt to keep as much
+ memory as possible free for use by the kernel immediately after the
+ end of the kernel image. The amount of space required will vary
+ depending on selected features, and is effectively unbound.
+
+The Image must be placed text_offset bytes from a 2MB aligned base
+address near the start of usable system RAM and called there. Memory
+below that base address is currently unusable by Linux, and therefore it
+is strongly recommended that this location is the start of system RAM.
+At least image_size bytes from the start of the image must be free for
+use by the kernel.
+
+Any memory described to the kernel (even that below the 2MB aligned base
+address) which is not marked as reserved from the kernel e.g. with a
+memreserve region in the device tree) will be considered as available to
+the kernel.
Before jumping into the kernel, the following conditions must be met:
@@ -141,6 +168,14 @@ Before jumping into the kernel, the following conditions must be met:
the kernel image will be entered must be initialised by software at a
higher exception level to prevent execution in an UNKNOWN state.
+ For systems with a GICv3 interrupt controller:
+ - If EL3 is present:
+ ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1.
+ ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
+ - If the kernel is entered at EL1:
+ ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1
+ ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1.
+
The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level.
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index d50fa618371b..344e85cc7323 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -2,18 +2,18 @@
==============================
Author: Catalin Marinas <catalin.marinas@arm.com>
-Date : 20 February 2012
This document describes the virtual memory layout used by the AArch64
Linux kernel. The architecture allows up to 4 levels of translation
tables with a 4KB page size and up to 3 levels with a 64KB page size.
-AArch64 Linux uses 3 levels of translation tables with the 4KB page
-configuration, allowing 39-bit (512GB) virtual addresses for both user
-and kernel. With 64KB pages, only 2 levels of translation tables are
-used but the memory layout is the same.
+AArch64 Linux uses either 3 levels or 4 levels of translation tables
+with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit
+(256TB) virtual addresses, respectively, for both user and kernel. With
+64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB)
+virtual address, are used but the memory layout is the same.
-User addresses have bits 63:39 set to 0 while the kernel addresses have
+User addresses have bits 63:48 set to 0 while the kernel addresses have
the same bits set to 1. TTBRx selection is given by bit 63 of the
virtual address. The swapper_pg_dir contains only kernel (global)
mappings while the user pgd contains only user (non-global) mappings.
@@ -21,58 +21,40 @@ The swapper_pgd_dir address is written to TTBR1 and never written to
TTBR0.
-AArch64 Linux memory layout with 4KB pages:
+AArch64 Linux memory layout with 4KB pages + 3 levels:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB user
+ffffff8000000000 ffffffffffffffff 512GB kernel
-ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
-ffffffbbffff0000 ffffffbbffffffff 64KB [guard page]
+AArch64 Linux memory layout with 4KB pages + 4 levels:
-ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
-
-ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
-
-ffffffbffa000000 ffffffbffaffffff 16MB PCI I/O space
-
-ffffffbffb000000 ffffffbffbbfffff 12MB [guard]
-
-ffffffbffbc00000 ffffffbffbdfffff 2MB fixed mappings
-
-ffffffbffbe00000 ffffffbffbffffff 2MB [guard]
-
-ffffffbffc000000 ffffffbfffffffff 64MB modules
-
-ffffffc000000000 ffffffffffffffff 256GB kernel logical memory map
+Start End Size Use
+-----------------------------------------------------------------------
+0000000000000000 0000ffffffffffff 256TB user
+ffff000000000000 ffffffffffffffff 256TB kernel
-AArch64 Linux memory layout with 64KB pages:
+AArch64 Linux memory layout with 64KB pages + 2 levels:
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 000003ffffffffff 4TB user
+fffffc0000000000 ffffffffffffffff 4TB kernel
-fffffc0000000000 fffffdfbfffeffff ~2TB vmalloc
-fffffdfbffff0000 fffffdfbffffffff 64KB [guard page]
+AArch64 Linux memory layout with 64KB pages + 3 levels:
-fffffdfc00000000 fffffdfdffffffff 8GB vmemmap
-
-fffffdfe00000000 fffffdfffbbfffff ~8GB [guard, future vmmemap]
-
-fffffdfffa000000 fffffdfffaffffff 16MB PCI I/O space
-
-fffffdfffb000000 fffffdfffbbfffff 12MB [guard]
-
-fffffdfffbc00000 fffffdfffbdfffff 2MB fixed mappings
-
-fffffdfffbe00000 fffffdfffbffffff 2MB [guard]
+Start End Size Use
+-----------------------------------------------------------------------
+0000000000000000 0000ffffffffffff 256TB user
+ffff000000000000 ffffffffffffffff 256TB kernel
-fffffdfffc000000 fffffdffffffffff 64MB modules
-fffffe0000000000 ffffffffffffffff 2TB kernel logical memory map
+For details of the virtual kernel memory layout please see the kernel
+booting log.
Translation table lookup with 4KB pages:
@@ -86,7 +68,7 @@ Translation table lookup with 4KB pages:
| | | | +-> [20:12] L3 index
| | | +-----------> [29:21] L2 index
| | +---------------------> [38:30] L1 index
- | +-------------------------------> [47:39] L0 index (not used)
+ | +-------------------------------> [47:39] L0 index
+-------------------------------------------------> [63] TTBR0/1
@@ -99,10 +81,11 @@ Translation table lookup with 64KB pages:
| | | | v
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
- | | +--------------------------> [41:29] L2 index (only 38:29 used)
- | +-------------------------------> [47:42] L1 index (not used)
+ | | +--------------------------> [41:29] L2 index
+ | +-------------------------------> [47:42] L1 index
+-------------------------------------------------> [63] TTBR0/1
+
When using KVM, the hypervisor maps kernel pages in EL2, at a fixed
offset from the kernel VA (top 24bits of the kernel VA set to zero):
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 821de56d1580..10c949b293e4 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -599,6 +599,20 @@ fork. If this method returns 0 (success) then this should remain valid
while the caller holds cgroup_mutex and it is ensured that either
attach() or cancel_attach() will be called in future.
+void css_reset(struct cgroup_subsys_state *css)
+(cgroup_mutex held by caller)
+
+An optional operation which should restore @css's configuration to the
+initial state. This is currently only used on the unified hierarchy
+when a subsystem is disabled on a cgroup through
+"cgroup.subtree_control" but should remain enabled because other
+subsystems depend on it. cgroup core makes such a css invisible by
+removing the associated interface files and invokes this callback so
+that the hidden subsystem can return to the initial neutral state.
+This prevents unexpected resource control from a hidden css and
+ensures that the configuration is in the initial state when it is made
+visible again later.
+
void cancel_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
(cgroup_mutex held by caller)
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt
index 80ac454704b8..8870b0212150 100644
--- a/Documentation/cgroups/memcg_test.txt
+++ b/Documentation/cgroups/memcg_test.txt
@@ -24,64 +24,27 @@ Please note that implementation details can be changed.
a page/swp_entry may be charged (usage += PAGE_SIZE) at
- mem_cgroup_charge_anon()
- Called at new page fault and Copy-On-Write.
-
- mem_cgroup_try_charge_swapin()
- Called at do_swap_page() (page fault on swap entry) and swapoff.
- Followed by charge-commit-cancel protocol. (With swap accounting)
- At commit, a charge recorded in swap_cgroup is removed.
-
- mem_cgroup_charge_file()
- Called at add_to_page_cache()
-
- mem_cgroup_cache_charge_swapin()
- Called at shmem's swapin.
-
- mem_cgroup_prepare_migration()
- Called before migration. "extra" charge is done and followed by
- charge-commit-cancel protocol.
- At commit, charge against oldpage or newpage will be committed.
+ mem_cgroup_try_charge()
2. Uncharge
a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by
- mem_cgroup_uncharge_page()
- Called when an anonymous page is fully unmapped. I.e., mapcount goes
- to 0. If the page is SwapCache, uncharge is delayed until
- mem_cgroup_uncharge_swapcache().
-
- mem_cgroup_uncharge_cache_page()
- Called when a page-cache is deleted from radix-tree. If the page is
- SwapCache, uncharge is delayed until mem_cgroup_uncharge_swapcache().
-
- mem_cgroup_uncharge_swapcache()
- Called when SwapCache is removed from radix-tree. The charge itself
- is moved to swap_cgroup. (If mem+swap controller is disabled, no
- charge to swap occurs.)
+ mem_cgroup_uncharge()
+ Called when a page's refcount goes down to 0.
mem_cgroup_uncharge_swap()
Called when swp_entry's refcnt goes down to 0. A charge against swap
disappears.
- mem_cgroup_end_migration(old, new)
- At success of migration old is uncharged (if necessary), a charge
- to new page is committed. At failure, charge to old page is committed.
-
3. charge-commit-cancel
- In some case, we can't know this "charge" is valid or not at charging
- (because of races).
- To handle such case, there are charge-commit-cancel functions.
- mem_cgroup_try_charge_XXX
- mem_cgroup_commit_charge_XXX
- mem_cgroup_cancel_charge_XXX
- these are used in swap-in and migration.
+ Memcg pages are charged in two steps:
+ mem_cgroup_try_charge()
+ mem_cgroup_commit_charge() or mem_cgroup_cancel_charge()
At try_charge(), there are no flags to say "this page is charged".
at this point, usage += PAGE_SIZE.
- At commit(), the function checks the page should be charged or not
- and set flags or avoid charging.(usage -= PAGE_SIZE)
+ At commit(), the page is associated with the memcg.
At cancel(), simply usage -= PAGE_SIZE.
@@ -91,18 +54,6 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
Anonymous page is newly allocated at
- page fault into MAP_ANONYMOUS mapping.
- Copy-On-Write.
- It is charged right after it's allocated before doing any page table
- related operations. Of course, it's uncharged when another page is used
- for the fault address.
-
- At freeing anonymous page (by exit() or munmap()), zap_pte() is called
- and pages for ptes are freed one by one.(see mm/memory.c). Uncharges
- are done at page_remove_rmap() when page_mapcount() goes down to 0.
-
- Another page freeing is by page-reclaim (vmscan.c) and anonymous
- pages are swapped out. In this case, the page is marked as
- PageSwapCache(). uncharge() routine doesn't uncharge the page marked
- as SwapCache(). It's delayed until __delete_from_swap_cache().
4.1 Swap-in.
At swap-in, the page is taken from swap-cache. There are 2 cases.
@@ -111,41 +62,6 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
(b) If the SwapCache has been mapped by processes, it has been
charged already.
- This swap-in is one of the most complicated work. In do_swap_page(),
- following events occur when pte is unchanged.
-
- (1) the page (SwapCache) is looked up.
- (2) lock_page()
- (3) try_charge_swapin()
- (4) reuse_swap_page() (may call delete_swap_cache())
- (5) commit_charge_swapin()
- (6) swap_free().
-
- Considering following situation for example.
-
- (A) The page has not been charged before (2) and reuse_swap_page()
- doesn't call delete_from_swap_cache().
- (B) The page has not been charged before (2) and reuse_swap_page()
- calls delete_from_swap_cache().
- (C) The page has been charged before (2) and reuse_swap_page() doesn't
- call delete_from_swap_cache().
- (D) The page has been charged before (2) and reuse_swap_page() calls
- delete_from_swap_cache().
-
- memory.usage/memsw.usage changes to this page/swp_entry will be
- Case (A) (B) (C) (D)
- Event
- Before (2) 0/ 1 0/ 1 1/ 1 1/ 1
- ===========================================
- (3) +1/+1 +1/+1 +1/+1 +1/+1
- (4) - 0/ 0 - -1/ 0
- (5) 0/-1 0/ 0 -1/-1 0/ 0
- (6) - 0/-1 - 0/-1
- ===========================================
- Result 1/ 1 1/ 1 1/ 1 1/ 1
-
- In any cases, charges to this page should be 1/ 1.
-
4.2 Swap-out.
At swap-out, typical state transition is below.
@@ -158,28 +74,20 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
swp_entry's refcnt -= 1.
- At (b), the page is marked as SwapCache and not uncharged.
- At (d), the page is removed from SwapCache and a charge in page_cgroup
- is moved to swap_cgroup.
-
Finally, at task exit,
(e) zap_pte() is called and swp_entry's refcnt -=1 -> 0.
- Here, a charge in swap_cgroup disappears.
5. Page Cache
Page Cache is charged at
- add_to_page_cache_locked().
- uncharged at
- - __remove_from_page_cache().
-
The logic is very clear. (About migration, see below)
Note: __remove_from_page_cache() is called by remove_from_page_cache()
and __remove_mapping().
6. Shmem(tmpfs) Page Cache
- Memcg's charge/uncharge have special handlers of shmem. The best way
- to understand shmem's page state transition is to read mm/shmem.c.
+ The best way to understand shmem's page state transition is to read
+ mm/shmem.c.
But brief explanation of the behavior of memcg around shmem will be
helpful to understand the logic.
@@ -192,56 +100,10 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
It's charged when...
- A new page is added to shmem's radix-tree.
- A swp page is read. (move a charge from swap_cgroup to page_cgroup)
- It's uncharged when
- - A page is removed from radix-tree and not SwapCache.
- - When SwapCache is removed, a charge is moved to swap_cgroup.
- - When swp_entry's refcnt goes down to 0, a charge in swap_cgroup
- disappears.
7. Page Migration
- One of the most complicated functions is page-migration-handler.
- Memcg has 2 routines. Assume that we are migrating a page's contents
- from OLDPAGE to NEWPAGE.
-
- Usual migration logic is..
- (a) remove the page from LRU.
- (b) allocate NEWPAGE (migration target)
- (c) lock by lock_page().
- (d) unmap all mappings.
- (e-1) If necessary, replace entry in radix-tree.
- (e-2) move contents of a page.
- (f) map all mappings again.
- (g) pushback the page to LRU.
- (-) OLDPAGE will be freed.
-
- Before (g), memcg should complete all necessary charge/uncharge to
- NEWPAGE/OLDPAGE.
-
- The point is....
- - If OLDPAGE is anonymous, all charges will be dropped at (d) because
- try_to_unmap() drops all mapcount and the page will not be
- SwapCache.
-
- - If OLDPAGE is SwapCache, charges will be kept at (g) because
- __delete_from_swap_cache() isn't called at (e-1)
-
- - If OLDPAGE is page-cache, charges will be kept at (g) because
- remove_from_swap_cache() isn't called at (e-1)
-
- memcg provides following hooks.
-
- - mem_cgroup_prepare_migration(OLDPAGE)
- Called after (b) to account a charge (usage += PAGE_SIZE) against
- memcg which OLDPAGE belongs to.
-
- - mem_cgroup_end_migration(OLDPAGE, NEWPAGE)
- Called after (f) before (g).
- If OLDPAGE is used, commit OLDPAGE again. If OLDPAGE is already
- charged, a charge by prepare_migration() is automatically canceled.
- If NEWPAGE is used, commit NEWPAGE and uncharge OLDPAGE.
-
- But zap_pte() (by exit or munmap) can be called while migration,
- we have to check if OLDPAGE/NEWPAGE is a valid page after commit().
+
+ mem_cgroup_migrate()
8. LRU
Each memcg has its own private LRU. Now, its handling is under global
diff --git a/Documentation/cgroups/unified-hierarchy.txt b/Documentation/cgroups/unified-hierarchy.txt
index 324b182e6000..4f4563277864 100644
--- a/Documentation/cgroups/unified-hierarchy.txt
+++ b/Documentation/cgroups/unified-hierarchy.txt
@@ -94,12 +94,35 @@ change soon.
mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT
-All controllers which are not bound to other hierarchies are
-automatically bound to unified hierarchy and show up at the root of
-it. Controllers which are enabled only in the root of unified
-hierarchy can be bound to other hierarchies at any time. This allows
-mixing unified hierarchy with the traditional multiple hierarchies in
-a fully backward compatible way.
+All controllers which support the unified hierarchy and are not bound
+to other hierarchies are automatically bound to unified hierarchy and
+show up at the root of it. Controllers which are enabled only in the
+root of unified hierarchy can be bound to other hierarchies. This
+allows mixing unified hierarchy with the traditional multiple
+hierarchies in a fully backward compatible way.
+
+For development purposes, the following boot parameter makes all
+controllers to appear on the unified hierarchy whether supported or
+not.
+
+ cgroup__DEVEL__legacy_files_on_dfl
+
+A controller can be moved across hierarchies only after the controller
+is no longer referenced in its current hierarchy. Because per-cgroup
+controller states are destroyed asynchronously and controllers may
+have lingering references, a controller may not show up immediately on
+the unified hierarchy after the final umount of the previous
+hierarchy. Similarly, a controller should be fully disabled to be
+moved out of the unified hierarchy and it may take some time for the
+disabled controller to become available for other hierarchies;
+furthermore, due to dependencies among controllers, other controllers
+may need to be disabled too.
+
+While useful for development and manual configurations, dynamically
+moving controllers between the unified and other hierarchies is
+strongly discouraged for production use. It is recommended to decide
+the hierarchies and controller associations before starting using the
+controllers.
2-2. cgroup.subtree_control
diff --git a/Documentation/device-mapper/switch.txt b/Documentation/device-mapper/switch.txt
index 2fa749387be8..8897d0494838 100644
--- a/Documentation/device-mapper/switch.txt
+++ b/Documentation/device-mapper/switch.txt
@@ -106,6 +106,11 @@ which paths.
The path number in the range 0 ... (<num_paths> - 1).
Expressed in hexadecimal (WITHOUT any prefix like 0x).
+R<n>,<m>
+ This parameter allows repetitive patterns to be loaded quickly. <n> and <m>
+ are hexadecimal numbers. The last <n> mappings are repeated in the next <m>
+ slots.
+
Status
======
@@ -124,3 +129,10 @@ Create a switch device with 64kB region size:
Set mappings for the first 7 entries to point to devices switch0, switch1,
switch2, switch0, switch1, switch2, switch1:
dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1
+
+Set repetitive mapping. This command:
+ dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10
+is equivalent to:
+ dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \
+ :1 :2 :1 :2 :1 :2 :1 :2 :1 :2
+
diff --git a/Documentation/devicetree/bindings/arm/adapteva.txt b/Documentation/devicetree/bindings/arm/adapteva.txt
new file mode 100644
index 000000000000..1d8af9e36065
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/adapteva.txt
@@ -0,0 +1,7 @@
+Adapteva Platforms Device Tree Bindings
+---------------------------------------
+
+Parallella board
+
+Required root node properties:
+ - compatible = "adapteva,parallella";
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index 3509707f9320..c554ed3d44fb 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -86,3 +86,9 @@ Interrupt controllers:
compatible = "arm,versatile-sic";
interrupt-controller;
#interrupt-cells = <1>;
+
+Required nodes:
+
+- core-module: the root node to the Versatile platforms must have
+ a core-module with regs and the compatible strings
+ "arm,core-module-versatile", "syscon"
diff --git a/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt b/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
new file mode 100644
index 000000000000..8781073029e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armada-380-mpcore-soc-ctrl.txt
@@ -0,0 +1,14 @@
+Marvell Armada 38x CA9 MPcore SoC Controller
+============================================
+
+Required properties:
+
+- compatible: Should be "marvell,armada-380-mpcore-soc-ctrl".
+
+- reg: should be the register base and length as documented in the
+ datasheet for the CA9 MPcore SoC Control registers
+
+mpcore-soc-ctrl@20d20 {
+ compatible = "marvell,armada-380-mpcore-soc-ctrl";
+ reg = <0x20d20 0x6c>;
+};
diff --git a/Documentation/devicetree/bindings/arm/atmel-pmc.txt b/Documentation/devicetree/bindings/arm/atmel-pmc.txt
index 389bed5056e8..795cc78543fe 100644
--- a/Documentation/devicetree/bindings/arm/atmel-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-pmc.txt
@@ -1,7 +1,10 @@
* Power Management Controller (PMC)
Required properties:
-- compatible: Should be "atmel,at91rm9200-pmc"
+- compatible: Should be "atmel,<chip>-pmc".
+ <chip> can be: at91rm9200, at91sam9260, at91sam9g45, at91sam9n12,
+ at91sam9x5, sama5d3
+
- reg: Should contain PMC registers location and length
Examples:
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method
new file mode 100644
index 000000000000..8240c023e202
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method
@@ -0,0 +1,36 @@
+Broadcom Kona Family CPU Enable Method
+--------------------------------------
+This binding defines the enable method used for starting secondary
+CPUs in the following Broadcom SoCs:
+ BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664
+
+The enable method is specified by defining the following required
+properties in the "cpus" device tree node:
+ - enable-method = "brcm,bcm11351-cpu-method";
+ - secondary-boot-reg = <...>;
+
+The secondary-boot-reg property is a u32 value that specifies the
+physical address of the register used to request the ROM holding pen
+code release a secondary CPU. The value written to the register is
+formed by encoding the target CPU id into the low bits of the
+physical start address it should jump to.
+
+Example:
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "brcm,bcm11351-cpu-method";
+ secondary-boot-reg = <0x3500417c>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt b/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt
new file mode 100644
index 000000000000..3c436cc4f35d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/brcm-brcmstb.txt
@@ -0,0 +1,95 @@
+ARM Broadcom STB platforms Device Tree Bindings
+-----------------------------------------------
+Boards with Broadcom Brahma15 ARM-based BCMxxxx (generally BCM7xxx variants)
+SoC shall have the following DT organization:
+
+Required root node properties:
+ - compatible: "brcm,bcm<chip_id>", "brcm,brcmstb"
+
+example:
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "Broadcom STB (bcm7445)";
+ compatible = "brcm,bcm7445", "brcm,brcmstb";
+
+Further, syscon nodes that map platform-specific registers used for general
+system control is required:
+
+ - compatible: "brcm,bcm<chip_id>-sun-top-ctrl", "syscon"
+ - compatible: "brcm,bcm<chip_id>-hif-cpubiuctrl", "syscon"
+ - compatible: "brcm,bcm<chip_id>-hif-continuation", "syscon"
+
+example:
+ rdb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0 0x00 0xf0000000 0x1000000>;
+
+ sun_top_ctrl: syscon@404000 {
+ compatible = "brcm,bcm7445-sun-top-ctrl", "syscon";
+ reg = <0x404000 0x51c>;
+ };
+
+ hif_cpubiuctrl: syscon@3e2400 {
+ compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon";
+ reg = <0x3e2400 0x5b4>;
+ };
+
+ hif_continuation: syscon@452000 {
+ compatible = "brcm,bcm7445-hif-continuation", "syscon";
+ reg = <0x452000 0x100>;
+ };
+ };
+
+Lastly, nodes that allow for support of SMP initialization and reboot are
+required:
+
+smpboot
+-------
+Required properties:
+
+ - compatible
+ The string "brcm,brcmstb-smpboot".
+
+ - syscon-cpu
+ A phandle / integer array property which lets the BSP know the location
+ of certain CPU power-on registers.
+
+ The layout of the property is as follows:
+ o a phandle to the "hif_cpubiuctrl" syscon node
+ o offset to the base CPU power zone register
+ o offset to the base CPU reset register
+
+ - syscon-cont
+ A phandle pointing to the syscon node which describes the CPU boot
+ continuation registers.
+ o a phandle to the "hif_continuation" syscon node
+
+example:
+ smpboot {
+ compatible = "brcm,brcmstb-smpboot";
+ syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+ syscon-cont = <&hif_continuation>;
+ };
+
+reboot
+-------
+Required properties
+
+ - compatible
+ The string property "brcm,brcmstb-reboot".
+
+ - syscon
+ A phandle / integer array that points to the syscon node which describes
+ the general system reset registers.
+ o a phandle to "sun_top_ctrl"
+ o offset to the "reset source enable" register
+ o offset to the "software master reset" register
+
+example:
+ reboot {
+ compatible = "brcm,brcmstb-reboot";
+ syscon = <&sun_top_ctrl 0x304 0x308>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/ccn.txt b/Documentation/devicetree/bindings/arm/ccn.txt
new file mode 100644
index 000000000000..b100d3847d88
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/ccn.txt
@@ -0,0 +1,21 @@
+* ARM CCN (Cache Coherent Network)
+
+Required properties:
+
+- compatible: (standard compatible string) should be one of:
+ "arm,ccn-504"
+ "arm,ccn-508"
+
+- reg: (standard registers property) physical address and size
+ (16MB) of the configuration registers block
+
+- interrupts: (standard interrupt property) single interrupt
+ generated by the control block
+
+Example:
+
+ ccn@0x2000000000 {
+ compatible = "arm,ccn-504";
+ reg = <0x20 0x00000000 0 0x1000000>;
+ interrupts = <0 181 4>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp b/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp
new file mode 100644
index 000000000000..cd236b727e2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cpu-enable-method/marvell,berlin-smp
@@ -0,0 +1,41 @@
+========================================================
+Secondary CPU enable-method "marvell,berlin-smp" binding
+========================================================
+
+This document describes the "marvell,berlin-smp" method for enabling secondary
+CPUs. To apply to all CPUs, a single "marvell,berlin-smp" enable method should
+be defined in the "cpus" node.
+
+Enable method name: "marvell,berlin-smp"
+Compatible machines: "marvell,berlin2" and "marvell,berlin2q"
+Compatible CPUs: "marvell,pj4b" and "arm,cortex-a9"
+Related properties: (none)
+
+Note:
+This enable method needs valid nodes compatible with "arm,cortex-a9-scu" and
+"marvell,berlin-cpu-ctrl"[1].
+
+Example:
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "marvell,berlin-smp";
+
+ cpu@0 {
+ compatible = "marvell,pj4b";
+ device_type = "cpu";
+ next-level-cache = <&l2>;
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "marvell,pj4b";
+ device_type = "cpu";
+ next-level-cache = <&l2>;
+ reg = <1>;
+ };
+ };
+
+--
+[1] arm/marvell,berlin.txt
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 1fe72a0778cd..298e2f6b33c6 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -152,7 +152,9 @@ nodes to be present and contain the properties described below.
"arm,cortex-a7"
"arm,cortex-a8"
"arm,cortex-a9"
+ "arm,cortex-a12"
"arm,cortex-a15"
+ "arm,cortex-a17"
"arm,cortex-a53"
"arm,cortex-a57"
"arm,cortex-m0"
@@ -163,6 +165,7 @@ nodes to be present and contain the properties described below.
"arm,cortex-r4"
"arm,cortex-r5"
"arm,cortex-r7"
+ "brcm,brahma-b15"
"faraday,fa526"
"intel,sa110"
"intel,sa1100"
@@ -184,6 +187,7 @@ nodes to be present and contain the properties described below.
can be one of:
"allwinner,sun6i-a31"
"arm,psci"
+ "brcm,brahma-b15"
"marvell,armada-375-smp"
"marvell,armada-380-smp"
"marvell,armada-xp-smp"
diff --git a/Documentation/devicetree/bindings/arm/gic-v3.txt b/Documentation/devicetree/bindings/arm/gic-v3.txt
new file mode 100644
index 000000000000..33cd05e6c125
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic-v3.txt
@@ -0,0 +1,79 @@
+* ARM Generic Interrupt Controller, version 3
+
+AArch64 SMP cores are often associated with a GICv3, providing Private
+Peripheral Interrupts (PPI), Shared Peripheral Interrupts (SPI),
+Software Generated Interrupts (SGI), and Locality-specific Peripheral
+Interrupts (LPI).
+
+Main node required properties:
+
+- compatible : should at least contain "arm,gic-v3".
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. Must be a single cell with a value of at least 3.
+
+ The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+ interrupts. Other values are reserved for future use.
+
+ The 2nd cell contains the interrupt number for the interrupt type.
+ SPI interrupts are in the range [0-987]. PPI interrupts are in the
+ range [0-15].
+
+ The 3rd cell is the flags, encoded as follows:
+ bits[3:0] trigger type and level flags.
+ 1 = edge triggered
+ 4 = level triggered
+
+ Cells 4 and beyond are reserved for future use. When the 1st cell
+ has a value of 0 or 1, cells 4 and beyond act as padding, and may be
+ ignored. It is recommended that padding cells have a value of 0.
+
+- reg : Specifies base physical address(s) and size of the GIC
+ registers, in the following order:
+ - GIC Distributor interface (GICD)
+ - GIC Redistributors (GICR), one range per redistributor region
+ - GIC CPU interface (GICC)
+ - GIC Hypervisor interface (GICH)
+ - GIC Virtual CPU interface (GICV)
+
+ GICC, GICH and GICV are optional.
+
+- interrupts : Interrupt source of the VGIC maintenance interrupt.
+
+Optional
+
+- redistributor-stride : If using padding pages, specifies the stride
+ of consecutive redistributors. Must be a multiple of 64kB.
+
+- #redistributor-regions: The number of independent contiguous regions
+ occupied by the redistributors. Required if more than one such
+ region is present.
+
+Examples:
+
+ gic: interrupt-controller@2cf00000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x0 0x2f000000 0 0x10000>, // GICD
+ <0x0 0x2f100000 0 0x200000>, // GICR
+ <0x0 0x2c000000 0 0x2000>, // GICC
+ <0x0 0x2c010000 0 0x2000>, // GICH
+ <0x0 0x2c020000 0 0x2000>; // GICV
+ interrupts = <1 9 4>;
+ };
+
+ gic: interrupt-controller@2c010000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ redistributor-stride = <0x0 0x40000>; // 256kB stride
+ #redistributor-regions = <2>;
+ reg = <0x0 0x2c010000 0 0x10000>, // GICD
+ <0x0 0x2d000000 0 0x800000>, // GICR 1: CPUs 0-31
+ <0x0 0x2e000000 0 0x800000>; // GICR 2: CPUs 32-63
+ <0x0 0x2c040000 0 0x2000>, // GICC
+ <0x0 0x2c060000 0 0x2000>, // GICH
+ <0x0 0x2c080000 0 0x2000>; // GICV
+ interrupts = <1 9 4>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 5573c08d3180..c7d2fa156678 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -16,6 +16,7 @@ Main node required properties:
"arm,cortex-a9-gic"
"arm,cortex-a7-gic"
"arm,arm11mp-gic"
+ "brcm,brahma-b15-gic"
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The type shall be a <u32> and the value shall be 3.
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index df0a452b8526..934f00025cc4 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -31,6 +31,17 @@ Example:
reboot-offset = <0x4>;
};
+-----------------------------------------------------------------------
+Hisilicon CPU controller
+
+Required properties:
+- compatible : "hisilicon,cpuctrl"
+- reg : Register address and size
+
+The clock registers and power registers of secondary cores are defined
+in CPU controller, especially in HIX5HD2 SoC.
+
+-----------------------------------------------------------------------
PCTRL: Peripheral misc control register
Required Properties:
diff --git a/Documentation/devicetree/bindings/arm/marvell,berlin.txt b/Documentation/devicetree/bindings/arm/marvell,berlin.txt
index 94013a9a8769..904de5781f44 100644
--- a/Documentation/devicetree/bindings/arm/marvell,berlin.txt
+++ b/Documentation/devicetree/bindings/arm/marvell,berlin.txt
@@ -24,6 +24,22 @@ SoC and board used. Currently known SoC compatibles are:
...
}
+* Marvell Berlin CPU control bindings
+
+CPU control register allows various operations on CPUs, like resetting them
+independently.
+
+Required properties:
+- compatible: should be "marvell,berlin-cpu-ctrl"
+- reg: address and length of the register set
+
+Example:
+
+cpu-ctrl@f7dd0000 {
+ compatible = "marvell,berlin-cpu-ctrl";
+ reg = <0xf7dd0000 0x10000>;
+};
+
* Marvell Berlin2 chip control binding
Marvell Berlin SoCs have a chip control register set providing several
diff --git a/Documentation/devicetree/bindings/arm/mediatek.txt b/Documentation/devicetree/bindings/arm/mediatek.txt
new file mode 100644
index 000000000000..d6ac71f37314
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek.txt
@@ -0,0 +1,8 @@
+Mediatek MT6589 Platforms Device Tree Bindings
+
+Boards with a SoC of the Mediatek MT6589 shall have the following property:
+
+Required root node property:
+
+compatible: must contain "mediatek,mt6589"
+
diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
index fb88585cfb93..4139db353d0a 100644
--- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -10,6 +10,7 @@ Required properties:
- compatible : Should be "ti,irq-crossbar"
- reg: Base address and the size of the crossbar registers.
- ti,max-irqs: Total number of irqs available at the interrupt controller.
+- ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed.
- ti,reg-size: Size of a individual register in bytes. Every individual
register is assumed to be of same size. Valid sizes are 1, 2, 4.
- ti,irqs-reserved: List of the reserved irq lines that are not muxed using
@@ -17,11 +18,46 @@ Required properties:
so crossbar bar driver should not consider them as free
lines.
+Optional properties:
+- ti,irqs-skip: This is similar to "ti,irqs-reserved", but these are for
+ SOC-specific hard-wiring of those irqs which unexpectedly bypasses the
+ crossbar. These irqs have a crossbar register, but still cannot be used.
+
+- ti,irqs-safe-map: integer which maps to a safe configuration to use
+ when the interrupt controller irq is unused (when not provided, default is 0)
+
Examples:
crossbar_mpu: @4a020000 {
compatible = "ti,irq-crossbar";
reg = <0x4a002a48 0x130>;
ti,max-irqs = <160>;
+ ti,max-crossbar-sources = <400>;
ti,reg-size = <2>;
ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+ ti,irqs-skip = <10 133 139 140>;
};
+
+Consumer:
+========
+See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
+Documentation/devicetree/bindings/arm/gic.txt for further details.
+
+An interrupt consumer on an SoC using crossbar will use:
+ interrupts = <GIC_SPI request_number interrupt_level>
+When the request number is between 0 to that described by
+"ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the
+request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
+quirky hardware mapping direct to GIC.
+
+Example:
+ device_x@0x4a023000 {
+ /* Crossbar 8 used */
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ ...
+ };
+
+ device_y@0x4a033000 {
+ /* Direct mapped GIC SPI 1 used */
+ interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
+ ...
+ };
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index d22b216f5d23..0edc90305dfe 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -129,6 +129,9 @@ Boards:
- AM437x GP EVM
compatible = "ti,am437x-gp-evm", "ti,am4372", "ti,am43"
+- AM437x SK EVM: AM437x StarterKit Evaluation Module
+ compatible = "ti,am437x-sk-evm", "ti,am4372", "ti,am43"
+
- DRA742 EVM: Software Development Board for DRA742
compatible = "ti,dra7-evm", "ti,dra742", "ti,dra74", "ti,dra7"
diff --git a/Documentation/devicetree/bindings/arm/omap/prcm.txt b/Documentation/devicetree/bindings/arm/omap/prcm.txt
new file mode 100644
index 000000000000..79074dac684a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/prcm.txt
@@ -0,0 +1,65 @@
+OMAP PRCM bindings
+
+Power Reset and Clock Manager lists the device clocks and clockdomains under
+a DT hierarchy. Each TI SoC can have multiple PRCM entities listed for it,
+each describing one module and the clock hierarchy under it. see [1] for
+documentation about the individual clock/clockdomain nodes.
+
+[1] Documentation/devicetree/bindings/clock/ti/*
+
+Required properties:
+- compatible: Must be one of:
+ "ti,am3-prcm"
+ "ti,am3-scrm"
+ "ti,am4-prcm"
+ "ti,am4-scrm"
+ "ti,omap2-prcm"
+ "ti,omap2-scrm"
+ "ti,omap3-prm"
+ "ti,omap3-cm"
+ "ti,omap3-scrm"
+ "ti,omap4-cm1"
+ "ti,omap4-prm"
+ "ti,omap4-cm2"
+ "ti,omap4-scrm"
+ "ti,omap5-prm"
+ "ti,omap5-cm-core-aon"
+ "ti,omap5-scrm"
+ "ti,omap5-cm-core"
+ "ti,dra7-prm"
+ "ti,dra7-cm-core-aon"
+ "ti,dra7-cm-core"
+- reg: Contains PRCM module register address range
+ (base address and length)
+- clocks: clocks for this module
+- clockdomains: clockdomains for this module
+
+Example:
+
+cm: cm@48004000 {
+ compatible = "ti,omap3-cm";
+ reg = <0x48004000 0x4000>;
+
+ cm_clocks: clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cm_clockdomains: clockdomains {
+ };
+}
+
+&cm_clocks {
+ omap2_32k_fck: omap_32k_fck {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ };
+};
+
+&cm_clockdomains {
+ core_l3_clkdm: core_l3_clkdm {
+ compatible = "ti,clockdomain";
+ clocks = <&sdrc_ick>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
index 832fe8cc24d7..adc61b095bd1 100644
--- a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
@@ -14,14 +14,21 @@ Required properties:
for exynos4412/5250 controllers.
Must be "samsung,exynos-adc-v2" for
future controllers.
+ Must be "samsung,exynos3250-adc" for
+ controllers compatible with ADC of Exynos3250.
- reg: Contains ADC register address range (base address and
length) and the address of the phy enable register.
- interrupts: Contains the interrupt information for the timer. The
format is being dependent on which interrupt controller
the Samsung device uses.
- #io-channel-cells = <1>; As ADC has multiple outputs
-- clocks From common clock binding: handle to adc clock.
-- clock-names From common clock binding: Shall be "adc".
+- clocks From common clock bindings: handles to clocks specified
+ in "clock-names" property, in the same order.
+- clock-names From common clock bindings: list of clock input names
+ used by ADC block:
+ - "adc" : ADC bus clock
+ - "sclk" : ADC special clock (only for Exynos3250 and
+ compatible ADC block)
- vdd-supply VDD input supply.
Note: child nodes can be added for auto probing from device tree.
@@ -41,6 +48,20 @@ adc: adc@12D10000 {
vdd-supply = <&buck5_reg>;
};
+Example: adding device info in dtsi file for Exynos3250 with additional sclk
+
+adc: adc@126C0000 {
+ compatible = "samsung,exynos3250-adc", "samsung,exynos-adc-v2;
+ reg = <0x126C0000 0x100>, <0x10020718 0x4>;
+ interrupts = <0 137 0>;
+ #io-channel-cells = <1>;
+ io-channel-ranges;
+
+ clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
+ clock-names = "adc", "sclk";
+
+ vdd-supply = <&buck5_reg>;
+};
Example: Adding child nodes in dts file
diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
index 2a4ab046a8a1..1e1979b229ff 100644
--- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
@@ -7,13 +7,45 @@ Properties:
- "samsung,exynos4212-pmu" - for Exynos4212 SoC,
- "samsung,exynos4412-pmu" - for Exynos4412 SoC,
- "samsung,exynos5250-pmu" - for Exynos5250 SoC,
+ - "samsung,exynos5260-pmu" - for Exynos5260 SoC.
+ - "samsung,exynos5410-pmu" - for Exynos5410 SoC,
- "samsung,exynos5420-pmu" - for Exynos5420 SoC.
second value must be always "syscon".
- reg : offset and length of the register set.
+ - #clock-cells : must be <1>, since PMU requires once cell as clock specifier.
+ The single specifier cell is used as index to list of clocks
+ provided by PMU, which is currently:
+ 0 : SoC clock output (CLKOUT pin)
+
+ - clock-names : list of clock names for particular CLKOUT mux inputs in
+ following format:
+ "clkoutN", where N is a decimal number corresponding to
+ CLKOUT mux control bits value for given input, e.g.
+ "clkout0", "clkout7", "clkout15".
+
+ - clocks : list of phandles and specifiers to all input clocks listed in
+ clock-names property.
+
Example :
pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5250-pmu", "syscon";
reg = <0x10040000 0x5000>;
+ #clock-cells = <1>;
+ clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+ "clkout4", "clkout8", "clkout9";
+ clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+ <&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+ <&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+ <&clock CLK_XUSBXTI>;
+};
+
+Example of clock consumer :
+
+usb3503: usb3503@08 {
+ /* ... */
+ clock-names = "refclk";
+ clocks = <&pmu_system_controller 0>;
+ /* ... */
};
diff --git a/Documentation/devicetree/bindings/arm/spear-misc.txt b/Documentation/devicetree/bindings/arm/spear-misc.txt
new file mode 100644
index 000000000000..cf649827ffcd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/spear-misc.txt
@@ -0,0 +1,9 @@
+SPEAr Misc configuration
+===========================
+SPEAr SOCs have some miscellaneous registers which are used to configure
+few properties of different peripheral controllers.
+
+misc node required properties:
+
+- compatible Should be "st,spear1340-misc", "syscon".
+- reg: Address range of misc space upto 8K
diff --git a/Documentation/devicetree/bindings/arm/tegra.txt b/Documentation/devicetree/bindings/arm/tegra.txt
index 558ed4b4ef39..73278c6d2dc3 100644
--- a/Documentation/devicetree/bindings/arm/tegra.txt
+++ b/Documentation/devicetree/bindings/arm/tegra.txt
@@ -30,6 +30,8 @@ board-specific compatible values:
nvidia,seaboard
nvidia,ventana
nvidia,whistler
+ toradex,apalis_t30
+ toradex,apalis_t30-eval
toradex,colibri_t20-512
toradex,iris
diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
index 6f1ed830b4f7..1f7995357888 100644
--- a/Documentation/devicetree/bindings/arm/xilinx.txt
+++ b/Documentation/devicetree/bindings/arm/xilinx.txt
@@ -1,7 +1,7 @@
-Xilinx Zynq EP107 Emulation Platform board
+Xilinx Zynq Platforms Device Tree Bindings
-This board is an emulation platform for the Zynq product which is
-based on an ARM Cortex A9 processor.
+Boards with Zynq-7000 SOC based on an ARM Cortex A9 processor
+shall have the following properties.
Required root node properties:
- - compatible = "xlnx,zynq-ep107";
+ - compatible = "xlnx,zynq-7000";
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index c96d8dcf98fd..4ab09f2202d4 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -3,28 +3,43 @@
SATA nodes are defined to describe on-chip Serial ATA controllers.
Each SATA controller should have its own node.
+It is possible, but not required, to represent each port as a sub-node.
+It allows to enable each port independently when dealing with multiple
+PHYs.
+
Required properties:
- compatible : compatible string, one of:
- "allwinner,sun4i-a10-ahci"
- - "fsl,imx53-ahci"
- - "fsl,imx6q-ahci"
- "hisilicon,hisi-ahci"
- "ibm,476gtr-ahci"
- "marvell,armada-380-ahci"
- "snps,dwc-ahci"
- "snps,exynos5440-ahci"
- "snps,spear-ahci"
+ - "generic-ahci"
- interrupts : <interrupt mapping for SATA IRQ>
- reg : <registers mapping>
+Please note that when using "generic-ahci" you must also specify a SoC specific
+compatible:
+ compatible = "manufacturer,soc-model-ahci", "generic-ahci";
+
Optional properties:
- dma-coherent : Present if dma operations are coherent
- clocks : a list of phandle + clock specifier pairs
- target-supply : regulator for SATA target power
+- phys : reference to the SATA PHY node
+- phy-names : must be "sata-phy"
+
+Required properties when using sub-nodes:
+- #address-cells : number of cells to encode an address
+- #size-cells : number of cells representing the size of an address
+
+
+Sub-nodes required properties:
+- reg : the port number
+- phys : reference to the SATA PHY node
-"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
-- clocks : must contain the sata, sata_ref and ahb clocks
-- clock-names : must contain "ahb" for the ahb clock
Examples:
sata@ffe08000 {
@@ -40,3 +55,23 @@ Examples:
clocks = <&pll6 0>, <&ahb_gates 25>;
target-supply = <&reg_ahci_5v>;
};
+
+With sub-nodes:
+ sata@f7e90000 {
+ compatible = "marvell,berlin2q-achi", "generic-ahci";
+ reg = <0xe90000 0x1000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&chip CLKID_SATA>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sata0: sata-port@0 {
+ reg = <0>;
+ phys = <&sata_phy 0>;
+ };
+
+ sata1: sata-port@1 {
+ reg = <1>;
+ phys = <&sata_phy 1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/ata/ahci-st.txt b/Documentation/devicetree/bindings/ata/ahci-st.txt
new file mode 100644
index 000000000000..0574a77a0b9f
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/ahci-st.txt
@@ -0,0 +1,31 @@
+STMicroelectronics STi SATA controller
+
+This binding describes a SATA device.
+
+Required properties:
+ - compatible : Must be "st,sti-ahci"
+ - reg : Physical base addresses and length of register sets
+ - interrupts : Interrupt associated with the SATA device
+ - interrupt-names : Associated name must be; "hostc"
+ - resets : The power-down and soft-reset lines of SATA IP
+ - reset-names : Associated names must be; "pwr-dwn" and "sw-rst"
+ - clocks : The phandle for the clock
+ - clock-names : Associated name must be; "ahci_clk"
+ - phys : The phandle for the PHY device
+ - phy-names : Associated name must be; "ahci_phy"
+
+Example:
+
+ sata0: sata@fe380000 {
+ compatible = "st,sti-ahci";
+ reg = <0xfe380000 0x1000>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_NONE>;
+ interrupt-names = "hostc";
+ phys = <&miphy365x_phy MIPHY_PORT_0 MIPHY_TYPE_SATA>;
+ phy-names = "ahci_phy";
+ resets = <&powerdown STIH416_SATA0_POWERDOWN>,
+ <&softreset STIH416_SATA0_SOFTRESET>;
+ reset-names = "pwr-dwn", "sw-rst";
+ clocks = <&clk_s_a0_ls CLK_ICN_REG>;
+ clock-names = "ahci_clk";
+ };
diff --git a/Documentation/devicetree/bindings/ata/imx-sata.txt b/Documentation/devicetree/bindings/ata/imx-sata.txt
new file mode 100644
index 000000000000..fa511db18408
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/imx-sata.txt
@@ -0,0 +1,36 @@
+* Freescale i.MX AHCI SATA Controller
+
+The Freescale i.MX SATA controller mostly conforms to the AHCI interface
+with some special extensions at integration level.
+
+Required properties:
+- compatible : should be one of the following:
+ - "fsl,imx53-ahci" for i.MX53 SATA controller
+ - "fsl,imx6q-ahci" for i.MX6Q SATA controller
+- interrupts : interrupt mapping for SATA IRQ
+- reg : registers mapping
+- clocks : list of clock specifiers, must contain an entry for each
+ required entry in clock-names
+- clock-names : should include "sata", "sata_ref" and "ahb" entries
+
+Optional properties:
+- fsl,transmit-level-mV : transmit voltage level, in millivolts.
+- fsl,transmit-boost-mdB : transmit boost level, in milli-decibels
+- fsl,transmit-atten-16ths : transmit attenuation, in 16ths
+- fsl,receive-eq-mdB : receive equalisation, in milli-decibels
+ Please refer to the technical documentation or the driver source code
+ for the list of legal values for these options.
+- fsl,no-spread-spectrum : disable spread-spectrum clocking on the SATA
+ link.
+
+Examples:
+
+sata@02200000 {
+ compatible = "fsl,imx6q-ahci";
+ reg = <0x02200000 0x4000>;
+ interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_SATA>,
+ <&clks IMX6QDL_CLK_SATA_REF_100M>,
+ <&clks IMX6QDL_CLK_AHB>;
+ clock-names = "sata", "sata_ref", "ahb";
+};
diff --git a/Documentation/devicetree/bindings/ata/tegra-sata.txt b/Documentation/devicetree/bindings/ata/tegra-sata.txt
new file mode 100644
index 000000000000..946f2072570b
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/tegra-sata.txt
@@ -0,0 +1,30 @@
+Tegra124 SoC SATA AHCI controller
+
+Required properties :
+- compatible : "nvidia,tegra124-ahci".
+- reg : Should contain 2 entries:
+ - AHCI register set (SATA BAR5)
+ - SATA register set
+- interrupts : Defines the interrupt used by SATA
+- clocks : Must contain an entry for each entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+ - sata
+ - sata-oob
+ - cml1
+ - pll_e
+- resets : Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+ - sata
+ - sata-oob
+ - sata-cold
+- phys : Must contain an entry for each entry in phy-names.
+ See ../phy/phy-bindings.txt for details.
+- phy-names : Must include the following entries:
+ - sata-phy : XUSB PADCTL SATA PHY
+- hvdd-supply : Defines the SATA HVDD regulator
+- vddio-supply : Defines the SATA VDDIO regulator
+- avdd-supply : Defines the SATA AVDD regulator
+- target-5v-supply : Defines the SATA 5V power regulator
+- target-12v-supply : Defines the SATA 12V power regulator
diff --git a/Documentation/devicetree/bindings/clock/arm-integrator.txt b/Documentation/devicetree/bindings/clock/arm-integrator.txt
index 652914b17b95..ecc69520bcea 100644
--- a/Documentation/devicetree/bindings/clock/arm-integrator.txt
+++ b/Documentation/devicetree/bindings/clock/arm-integrator.txt
@@ -1,4 +1,4 @@
-Clock bindings for ARM Integrator Core Module clocks
+Clock bindings for ARM Integrator and Versatile Core Module clocks
Auxilary Oscillator Clock
@@ -12,7 +12,7 @@ parent node.
Required properties:
-- compatible: must be "arm,integrator-cm-auxosc"
+- compatible: must be "arm,integrator-cm-auxosc" or "arm,versatile-cm-auxosc"
- #clock-cells: must be <0>
Optional properties:
diff --git a/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt b/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
new file mode 100644
index 000000000000..4208886d834a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clk-palmas-clk32kg-clocks.txt
@@ -0,0 +1,35 @@
+* Palmas 32KHz clocks *
+
+Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO.
+
+This binding uses the common clock binding ./clock-bindings.txt.
+
+Required properties:
+- compatible : "ti,palmas-clk32kg" for clk32kg clock
+ "ti,palmas-clk32kgaudio" for clk32kgaudio clock
+- #clock-cells : shall be set to 0.
+
+Optional property:
+- ti,external-sleep-control: The external enable input pins controlled the
+ enable/disable of clocks. The external enable input pins ENABLE1,
+ ENABLE2 and NSLEEP. The valid values for the external pins are:
+ PALMAS_EXT_CONTROL_PIN_ENABLE1 for ENABLE1 pin
+ PALMAS_EXT_CONTROL_PIN_ENABLE2 for ENABLE2 pin
+ PALMAS_EXT_CONTROL_PIN_NSLEEP for NSLEEP pin
+ Option 0 or missing this property means the clock is enabled/disabled
+ via register access and these pins do not have any control.
+ The macros of external control pins for DTS is defined at
+ dt-bindings/mfd/palmas.h
+
+Example:
+ #include <dt-bindings/mfd/palmas.h>
+ ...
+ palmas: tps65913@58 {
+ ...
+ clk32kg: palmas_clk32k@0 {
+ compatible = "ti,palmas-clk32kg";
+ #clock-cells = <0>;
+ ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>;
+ };
+ ...
+ };
diff --git a/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt b/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt
new file mode 100644
index 000000000000..4fc869b69d4a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clk-s5pv210-audss.txt
@@ -0,0 +1,53 @@
+* Samsung Audio Subsystem Clock Controller
+
+The Samsung Audio Subsystem clock controller generates and supplies clocks
+to Audio Subsystem block available in the S5PV210 and compatible SoCs.
+
+Required Properties:
+
+- compatible: should be "samsung,s5pv210-audss-clock".
+- reg: physical base address and length of the controller's register set.
+
+- #clock-cells: should be 1.
+
+- clocks:
+ - hclk: AHB bus clock of the Audio Subsystem.
+ - xxti: Optional fixed rate PLL reference clock, parent of mout_audss. If
+ not specified (i.e. xusbxti is used for PLL reference), it is fixed to
+ a clock named "xxti".
+ - fout_epll: Input PLL to the AudioSS block, parent of mout_audss.
+ - iiscdclk0: Optional external i2s clock, parent of mout_i2s. If not
+ specified, it is fixed to a clock named "iiscdclk0".
+ - sclk_audio0: Audio bus clock, parent of mout_i2s.
+
+- clock-names: Aliases for the above clocks. They should be "hclk",
+ "xxti", "fout_epll", "iiscdclk0", and "sclk_audio0" respectively.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s5pv210-audss-clk.h header and can be used in device
+tree sources.
+
+Example: Clock controller node.
+
+ clk_audss: clock-controller@c0900000 {
+ compatible = "samsung,s5pv210-audss-clock";
+ reg = <0xc0900000 0x1000>;
+ #clock-cells = <1>;
+ clock-names = "hclk", "xxti",
+ "fout_epll", "sclk_audio0";
+ clocks = <&clocks DOUT_HCLKP>, <&xxti>,
+ <&clocks FOUT_EPLL>, <&clocks SCLK_AUDIO0>;
+ };
+
+Example: I2S controller node that consumes the clock generated by the clock
+ controller. Refer to the standard clock bindings for information
+ about 'clocks' and 'clock-names' property.
+
+ i2s0: i2s@03830000 {
+ /* ... */
+ clock-names = "iis", "i2s_opclk0",
+ "i2s_opclk1";
+ clocks = <&clk_audss CLK_I2S>, <&clk_audss CLK_I2S>,
+ <&clk_audss CLK_DOUT_AUD_BUS>;
+ /* ... */
+ };
diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index f15787817d6b..06fc6d541c89 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -131,3 +131,39 @@ clock signal, and a UART.
("pll" and "pll-switched").
* The UART has its baud clock connected the external oscillator and its
register clock connected to the PLL clock (the "pll-switched" signal)
+
+==Assigned clock parents and rates==
+
+Some platforms may require initial configuration of default parent clocks
+and clock frequencies. Such a configuration can be specified in a device tree
+node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
+properties. The assigned-clock-parents property should contain a list of parent
+clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
+property the list of assigned clock frequency values - corresponding to clocks
+listed in the assigned-clocks property.
+
+To skip setting parent or rate of a clock its corresponding entry should be
+set to 0, or can be omitted if it is not followed by any non-zero entry.
+
+ uart@a000 {
+ compatible = "fsl,imx-uart";
+ reg = <0xa000 0x1000>;
+ ...
+ clocks = <&osc 0>, <&pll 1>;
+ clock-names = "baud", "register";
+
+ assigned-clocks = <&clkcon 0>, <&pll 2>;
+ assigned-clock-parents = <&pll 2>;
+ assigned-clock-rates = <0>, <460800>;
+ };
+
+In this example the <&pll 2> clock is set as parent of clock <&clkcon 0> and
+the <&pll 2> clock is assigned a frequency value of 460800 Hz.
+
+Configuring a clock's parent and rate through the device node that consumes
+the clock can be done only for clocks that have a single user. Specifying
+conflicting parent or rate configuration in multiple consumer nodes for
+a shared clock is forbidden.
+
+Configuration of common clocks, which affect multiple consumer devices can
+be similarly specified in the clock provider node.
diff --git a/Documentation/devicetree/bindings/clock/clps711x-clock.txt b/Documentation/devicetree/bindings/clock/clps711x-clock.txt
new file mode 100644
index 000000000000..ce5a7476f05d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/clps711x-clock.txt
@@ -0,0 +1,19 @@
+* Clock bindings for the Cirrus Logic CLPS711X CPUs
+
+Required properties:
+- compatible : Shall contain "cirrus,clps711x-clk".
+- reg : Address of the internal register set.
+- startup-frequency: Factory set CPU startup frequency in HZ.
+- #clock-cells : Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/clps711x-clock.h
+for the full list of CLPS711X clock IDs.
+
+Example:
+ clks: clks@80000000 {
+ #clock-cells = <1>;
+ compatible = "cirrus,ep7312-clk", "cirrus,clps711x-clk";
+ reg = <0x80000000 0xc000>;
+ startup-frequency = <73728000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx1-clock.txt b/Documentation/devicetree/bindings/clock/imx1-clock.txt
new file mode 100644
index 000000000000..b7adf4e3ea98
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx1-clock.txt
@@ -0,0 +1,26 @@
+* Clock bindings for Freescale i.MX1 CPUs
+
+Required properties:
+- compatible: Should be "fsl,imx1-ccm".
+- reg: Address and length of the register set.
+- #clock-cells: Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx1-clock.h
+for the full list of i.MX1 clock IDs.
+
+Examples:
+ clks: ccm@0021b000 {
+ #clock-cells = <1>;
+ compatible = "fsl,imx1-ccm";
+ reg = <0x0021b000 0x1000>;
+ };
+
+ pwm: pwm@00208000 {
+ #pwm-cells = <2>;
+ compatible = "fsl,imx1-pwm";
+ reg = <0x00208000 0x1000>;
+ interrupts = <34>;
+ clocks = <&clks IMX1_CLK_DUMMY>, <&clks IMX1_CLK_PER1>;
+ clock-names = "ipg", "per";
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx21-clock.txt b/Documentation/devicetree/bindings/clock/imx21-clock.txt
new file mode 100644
index 000000000000..c3b0db437c48
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx21-clock.txt
@@ -0,0 +1,28 @@
+* Clock bindings for Freescale i.MX21
+
+Required properties:
+- compatible : Should be "fsl,imx21-ccm".
+- reg : Address and length of the register set.
+- interrupts : Should contain CCM interrupt.
+- #clock-cells: Should be <1>.
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx21-clock.h
+for the full list of i.MX21 clock IDs.
+
+Examples:
+ clks: ccm@10027000{
+ compatible = "fsl,imx21-ccm";
+ reg = <0x10027000 0x800>;
+ #clock-cells = <1>;
+ };
+
+ uart1: serial@1000a000 {
+ compatible = "fsl,imx21-uart";
+ reg = <0x1000a000 0x1000>;
+ interrupts = <20>;
+ clocks = <&clks IMX21_CLK_UART1_IPG_GATE>,
+ <&clks IMX21_CLK_PER1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx27-clock.txt b/Documentation/devicetree/bindings/clock/imx27-clock.txt
index 6bc9fd2c6631..cc05de9ec393 100644
--- a/Documentation/devicetree/bindings/clock/imx27-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx27-clock.txt
@@ -7,117 +7,22 @@ Required properties:
- #clock-cells: Should be <1>
The clock consumer should specify the desired clock by having the clock
-ID in its "clocks" phandle cell. The following is a full list of i.MX27
-clocks and IDs.
-
- Clock ID
- -----------------------
- dummy 0
- ckih 1
- ckil 2
- mpll 3
- spll 4
- mpll_main2 5
- ahb 6
- ipg 7
- nfc_div 8
- per1_div 9
- per2_div 10
- per3_div 11
- per4_div 12
- vpu_sel 13
- vpu_div 14
- usb_div 15
- cpu_sel 16
- clko_sel 17
- cpu_div 18
- clko_div 19
- ssi1_sel 20
- ssi2_sel 21
- ssi1_div 22
- ssi2_div 23
- clko_en 24
- ssi2_ipg_gate 25
- ssi1_ipg_gate 26
- slcdc_ipg_gate 27
- sdhc3_ipg_gate 28
- sdhc2_ipg_gate 29
- sdhc1_ipg_gate 30
- scc_ipg_gate 31
- sahara_ipg_gate 32
- rtc_ipg_gate 33
- pwm_ipg_gate 34
- owire_ipg_gate 35
- lcdc_ipg_gate 36
- kpp_ipg_gate 37
- iim_ipg_gate 38
- i2c2_ipg_gate 39
- i2c1_ipg_gate 40
- gpt6_ipg_gate 41
- gpt5_ipg_gate 42
- gpt4_ipg_gate 43
- gpt3_ipg_gate 44
- gpt2_ipg_gate 45
- gpt1_ipg_gate 46
- gpio_ipg_gate 47
- fec_ipg_gate 48
- emma_ipg_gate 49
- dma_ipg_gate 50
- cspi3_ipg_gate 51
- cspi2_ipg_gate 52
- cspi1_ipg_gate 53
- nfc_baud_gate 54
- ssi2_baud_gate 55
- ssi1_baud_gate 56
- vpu_baud_gate 57
- per4_gate 58
- per3_gate 59
- per2_gate 60
- per1_gate 61
- usb_ahb_gate 62
- slcdc_ahb_gate 63
- sahara_ahb_gate 64
- lcdc_ahb_gate 65
- vpu_ahb_gate 66
- fec_ahb_gate 67
- emma_ahb_gate 68
- emi_ahb_gate 69
- dma_ahb_gate 70
- csi_ahb_gate 71
- brom_ahb_gate 72
- ata_ahb_gate 73
- wdog_ipg_gate 74
- usb_ipg_gate 75
- uart6_ipg_gate 76
- uart5_ipg_gate 77
- uart4_ipg_gate 78
- uart3_ipg_gate 79
- uart2_ipg_gate 80
- uart1_ipg_gate 81
- ckih_div1p5 82
- fpm 83
- mpll_osc_sel 84
- mpll_sel 85
- spll_gate 86
- mshc_div 87
- rtic_ipg_gate 88
- mshc_ipg_gate 89
- rtic_ahb_gate 90
- mshc_baud_gate 91
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx27-clock.h
+for the full list of i.MX27 clock IDs.
Examples:
+ clks: ccm@10027000{
+ compatible = "fsl,imx27-ccm";
+ reg = <0x10027000 0x1000>;
+ #clock-cells = <1>;
+ };
-clks: ccm@10027000{
- compatible = "fsl,imx27-ccm";
- reg = <0x10027000 0x1000>;
- #clock-cells = <1>;
-};
-
-uart1: serial@1000a000 {
- compatible = "fsl,imx27-uart", "fsl,imx21-uart";
- reg = <0x1000a000 0x1000>;
- interrupts = <20>;
- clocks = <&clks 81>, <&clks 61>;
- clock-names = "ipg", "per";
- status = "disabled";
-};
+ uart1: serial@1000a000 {
+ compatible = "fsl,imx27-uart", "fsl,imx21-uart";
+ reg = <0x1000a000 0x1000>;
+ interrupts = <20>;
+ clocks = <&clks IMX27_CLK_UART1_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 90ec91fe5ce0..9252912a5b0e 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -7,223 +7,13 @@ Required properties:
- #clock-cells: Should be <1>
The clock consumer should specify the desired clock by having the clock
-ID in its "clocks" phandle cell. The following is a full list of i.MX6Q
-clocks and IDs.
-
- Clock ID
- ---------------------------
- dummy 0
- ckil 1
- ckih 2
- osc 3
- pll2_pfd0_352m 4
- pll2_pfd1_594m 5
- pll2_pfd2_396m 6
- pll3_pfd0_720m 7
- pll3_pfd1_540m 8
- pll3_pfd2_508m 9
- pll3_pfd3_454m 10
- pll2_198m 11
- pll3_120m 12
- pll3_80m 13
- pll3_60m 14
- twd 15
- step 16
- pll1_sw 17
- periph_pre 18
- periph2_pre 19
- periph_clk2_sel 20
- periph2_clk2_sel 21
- axi_sel 22
- esai_sel 23
- asrc_sel 24
- spdif_sel 25
- gpu2d_axi 26
- gpu3d_axi 27
- gpu2d_core_sel 28
- gpu3d_core_sel 29
- gpu3d_shader_sel 30
- ipu1_sel 31
- ipu2_sel 32
- ldb_di0_sel 33
- ldb_di1_sel 34
- ipu1_di0_pre_sel 35
- ipu1_di1_pre_sel 36
- ipu2_di0_pre_sel 37
- ipu2_di1_pre_sel 38
- ipu1_di0_sel 39
- ipu1_di1_sel 40
- ipu2_di0_sel 41
- ipu2_di1_sel 42
- hsi_tx_sel 43
- pcie_axi_sel 44
- ssi1_sel 45
- ssi2_sel 46
- ssi3_sel 47
- usdhc1_sel 48
- usdhc2_sel 49
- usdhc3_sel 50
- usdhc4_sel 51
- enfc_sel 52
- emi_sel 53
- emi_slow_sel 54
- vdo_axi_sel 55
- vpu_axi_sel 56
- cko1_sel 57
- periph 58
- periph2 59
- periph_clk2 60
- periph2_clk2 61
- ipg 62
- ipg_per 63
- esai_pred 64
- esai_podf 65
- asrc_pred 66
- asrc_podf 67
- spdif_pred 68
- spdif_podf 69
- can_root 70
- ecspi_root 71
- gpu2d_core_podf 72
- gpu3d_core_podf 73
- gpu3d_shader 74
- ipu1_podf 75
- ipu2_podf 76
- ldb_di0_podf 77
- ldb_di1_podf 78
- ipu1_di0_pre 79
- ipu1_di1_pre 80
- ipu2_di0_pre 81
- ipu2_di1_pre 82
- hsi_tx_podf 83
- ssi1_pred 84
- ssi1_podf 85
- ssi2_pred 86
- ssi2_podf 87
- ssi3_pred 88
- ssi3_podf 89
- uart_serial_podf 90
- usdhc1_podf 91
- usdhc2_podf 92
- usdhc3_podf 93
- usdhc4_podf 94
- enfc_pred 95
- enfc_podf 96
- emi_podf 97
- emi_slow_podf 98
- vpu_axi_podf 99
- cko1_podf 100
- axi 101
- mmdc_ch0_axi_podf 102
- mmdc_ch1_axi_podf 103
- arm 104
- ahb 105
- apbh_dma 106
- asrc 107
- can1_ipg 108
- can1_serial 109
- can2_ipg 110
- can2_serial 111
- ecspi1 112
- ecspi2 113
- ecspi3 114
- ecspi4 115
- ecspi5 116
- enet 117
- esai 118
- gpt_ipg 119
- gpt_ipg_per 120
- gpu2d_core 121
- gpu3d_core 122
- hdmi_iahb 123
- hdmi_isfr 124
- i2c1 125
- i2c2 126
- i2c3 127
- iim 128
- enfc 129
- ipu1 130
- ipu1_di0 131
- ipu1_di1 132
- ipu2 133
- ipu2_di0 134
- ldb_di0 135
- ldb_di1 136
- ipu2_di1 137
- hsi_tx 138
- mlb 139
- mmdc_ch0_axi 140
- mmdc_ch1_axi 141
- ocram 142
- openvg_axi 143
- pcie_axi 144
- pwm1 145
- pwm2 146
- pwm3 147
- pwm4 148
- per1_bch 149
- gpmi_bch_apb 150
- gpmi_bch 151
- gpmi_io 152
- gpmi_apb 153
- sata 154
- sdma 155
- spba 156
- ssi1 157
- ssi2 158
- ssi3 159
- uart_ipg 160
- uart_serial 161
- usboh3 162
- usdhc1 163
- usdhc2 164
- usdhc3 165
- usdhc4 166
- vdo_axi 167
- vpu_axi 168
- cko1 169
- pll1_sys 170
- pll2_bus 171
- pll3_usb_otg 172
- pll4_audio 173
- pll5_video 174
- pll8_mlb 175
- pll7_usb_host 176
- pll6_enet 177
- ssi1_ipg 178
- ssi2_ipg 179
- ssi3_ipg 180
- rom 181
- usbphy1 182
- usbphy2 183
- ldb_di0_div_3_5 184
- ldb_di1_div_3_5 185
- sata_ref 186
- sata_ref_100m 187
- pcie_ref 188
- pcie_ref_125m 189
- enet_ref 190
- usbphy1_gate 191
- usbphy2_gate 192
- pll4_post_div 193
- pll5_post_div 194
- pll5_video_div 195
- eim_slow 196
- spdif 197
- cko2_sel 198
- cko2_podf 199
- cko2 200
- cko 201
- vdoa 202
- pll4_audio_div 203
- lvds1_sel 204
- lvds2_sel 205
- lvds1_gate 206
- lvds2_gate 207
- esai_ahb 208
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx6qdl-clock.h
+for the full list of i.MX6 Quad and DualLite clock IDs.
Examples:
+#include <dt-bindings/clock/imx6qdl-clock.h>
+
clks: ccm@020c4000 {
compatible = "fsl,imx6q-ccm";
reg = <0x020c4000 0x4000>;
@@ -235,7 +25,7 @@ uart1: serial@02020000 {
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <0 26 0x04>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>, <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
status = "disabled";
};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
index feb830130714..99c214660bdc 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt
@@ -3,14 +3,15 @@ Device Tree Clock bindings for cpu clock of Marvell EBU platforms
Required properties:
- compatible : shall be one of the following:
"marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP
-- reg : Address and length of the clock complex register set
+- reg : Address and length of the clock complex register set, followed
+ by address and length of the PMU DFS registers
- #clock-cells : should be set to 1.
- clocks : shall be the input parent clock phandle for the clock.
cpuclk: clock-complex@d0018700 {
#clock-cells = <1>;
compatible = "marvell,armada-xp-cpu-clock";
- reg = <0xd0018700 0xA0>;
+ reg = <0xd0018700 0xA0>, <0x1c054 0x10>;
clocks = <&coreclk 1>;
}
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 9cfcb4f2bc97..aba3d254e037 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -5,6 +5,8 @@ Required properties :
- compatible : shall contain only one of the following:
"qcom,gcc-apq8064"
+ "qcom,gcc-apq8084"
+ "qcom,gcc-ipq8064"
"qcom,gcc-msm8660"
"qcom,gcc-msm8960"
"qcom,gcc-msm8974"
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
index d572e9964c54..29ebf84d25af 100644
--- a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
@@ -4,6 +4,8 @@ Qualcomm Multimedia Clock & Reset Controller Binding
Required properties :
- compatible : shall contain only one of the following:
+ "qcom,mmcc-apq8064"
+ "qcom,mmcc-apq8084"
"qcom,mmcc-msm8660"
"qcom,mmcc-msm8960"
"qcom,mmcc-msm8974"
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt
new file mode 100644
index 000000000000..0c2bf5eba43e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt
@@ -0,0 +1,61 @@
+* Rockchip RK3188/RK3066 Clock and Reset Unit
+
+The RK3188/RK3066 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3188-cru", "rockchip,rk3188a-cru" or
+ "rockchip,rk3066a-cru"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+ If missing pll rates are not changable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3188-cru.h and
+dt-bindings/clock/rk3066-cru.h headers and can be used in device tree sources.
+Similar macros exist for the reset sources in these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "xin27m" - 27mhz crystal input on rk3066 - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_cif0" - external camera clock - optional,
+ - "ext_rmii" - external RMII clock - optional,
+ - "ext_jtag" - externalJTAG clock - optional
+
+Example: Clock controller node:
+
+ cru: cru@20000000 {
+ compatible = "rockchip,rk3188-cru";
+ reg = <0x20000000 0x1000>;
+ rockchip,grf = <&grf>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart0: serial@10124000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x10124000 0x400>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clocks = <&cru SCLK_UART0>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt
new file mode 100644
index 000000000000..c9fbb76573e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt
@@ -0,0 +1,61 @@
+* Rockchip RK3288 Clock and Reset Unit
+
+The RK3288 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3288-cru"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+ If missing pll rates are not changable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3288-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_edp_24m" - external display port clock - optional,
+ - "ext_vip" - external VIP clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+
+Example: Clock controller node:
+
+ cru: cru@20000000 {
+ compatible = "rockchip,rk3188-cru";
+ reg = <0x20000000 0x1000>;
+ rockchip,grf = <&grf>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller:
+
+ uart0: serial@10124000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x10124000 0x400>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clocks = <&cru SCLK_UART0>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/rockchip.txt b/Documentation/devicetree/bindings/clock/rockchip.txt
index a891c823ed44..22f6769e5d4a 100644
--- a/Documentation/devicetree/bindings/clock/rockchip.txt
+++ b/Documentation/devicetree/bindings/clock/rockchip.txt
@@ -6,6 +6,9 @@ This binding uses the common clock binding[1].
== Gate clocks ==
+These bindings are deprecated!
+Please use the soc specific CRU bindings instead.
+
The gate registers form a continuos block which makes the dt node
structure a matter of taste, as either all gates can be put into
one gate clock spanning all registers or they can be divided into
diff --git a/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt
new file mode 100644
index 000000000000..effd9401c133
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/samsung,s5pv210-clock.txt
@@ -0,0 +1,78 @@
+* Samsung S5P6442/S5PC110/S5PV210 Clock Controller
+
+Samsung S5P6442, S5PC110 and S5PV210 SoCs contain integrated clock
+controller, which generates and supplies clock to various controllers
+within the SoC.
+
+Required Properties:
+
+- compatible: should be one of following:
+ - "samsung,s5pv210-clock" : for clock controller of Samsung
+ S5PC110/S5PV210 SoCs,
+ - "samsung,s5p6442-clock" : for clock controller of Samsung
+ S5P6442 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- #clock-cells: should be 1.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/s5pv210.h header and can be used in device tree sources.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xxti": external crystal oscillator connected to XXTI and XXTO pins of
+the SoC,
+ - "xusbxti": external crystal oscillator connected to XUSBXTI and XUSBXTO
+pins of the SoC,
+
+A subset of above clocks available on given board shall be specified in
+board device tree, including the system base clock, as selected by XOM[0]
+pin of the SoC. Refer to generic fixed rate clock bindings
+documentation[1] for more information how to specify these clocks.
+
+[1] Documentation/devicetree/bindings/clock/fixed-clock.txt
+
+Example: Clock controller node:
+
+ clock: clock-controller@7e00f000 {
+ compatible = "samsung,s5pv210-clock";
+ reg = <0x7e00f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+Example: Required external clocks:
+
+ xxti: clock-xxti {
+ compatible = "fixed-clock";
+ clock-output-names = "xxti";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ };
+
+ xusbxti: clock-xusbxti {
+ compatible = "fixed-clock";
+ clock-output-names = "xusbxti";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ };
+
+Example: UART controller node that consumes the clock generated by the clock
+ controller (refer to the standard clock bindings for information about
+ "clocks" and "clock-names" properties):
+
+ uart0: serial@e2900000 {
+ compatible = "samsung,s5pv210-uart";
+ reg = <0xe2900000 0x400>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-names = "uart", "clk_uart_baud0",
+ "clk_uart_baud1";
+ clocks = <&clocks UART0>, <&clocks UART0>,
+ <&clocks SCLK_UART0>;
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
index ae56315fcec5..6247652044a0 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-divmux.txt
@@ -24,26 +24,26 @@ Required properties:
Example:
- clockgenA@fd345000 {
+ clockgen-a@fd345000 {
reg = <0xfd345000 0xb50>;
- CLK_M_A1_DIV1: CLK_M_A1_DIV1 {
+ clk_m_a1_div1: clk-m-a1-div1 {
#clock-cells = <1>;
compatible = "st,clkgena-divmux-c32-odf1",
"st,clkgena-divmux";
- clocks = <&CLK_M_A1_OSC_PREDIV>,
- <&CLK_M_A1_PLL0 1>, /* PLL0 PHI1 */
- <&CLK_M_A1_PLL1 1>; /* PLL1 PHI1 */
-
- clock-output-names = "CLK_M_RX_ICN_TS",
- "CLK_M_RX_ICN_VDP_0",
- "", /* Unused */
- "CLK_M_PRV_T1_BUS",
- "CLK_M_ICN_REG_12",
- "CLK_M_ICN_REG_10",
- "", /* Unused */
- "CLK_M_ICN_ST231";
+ clocks = <&clk_m_a1_osc_prediv>,
+ <&clk_m_a1_pll0 1>, /* PLL0 PHI1 */
+ <&clk_m_a1_pll1 1>; /* PLL1 PHI1 */
+
+ clock-output-names = "clk-m-rx-icn-ts",
+ "clk-m-rx-icn-vdp-0",
+ "", /* unused */
+ "clk-m-prv-t1-bus",
+ "clk-m-icn-reg-12",
+ "clk-m-icn-reg-10",
+ "", /* unused */
+ "clk-m-icn-st231";
};
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
index 943e0808e212..f1fa91c68768 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
@@ -17,7 +17,7 @@ Required properties:
"st,stih416-clkgenf-vcc-sd", "st,clkgen-mux"
"st,stih415-clkgen-a9-mux", "st,clkgen-mux"
"st,stih416-clkgen-a9-mux", "st,clkgen-mux"
-
+ "st,stih407-clkgen-a9-mux", "st,clkgen-mux"
- #clock-cells : from common clock binding; shall be set to 0.
@@ -27,10 +27,10 @@ Required properties:
Example:
- CLK_M_HVA: CLK_M_HVA {
+ clk_m_hva: clk-m-hva@fd690868 {
#clock-cells = <0>;
compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
reg = <0xfd690868 4>;
- clocks = <&CLOCKGEN_F 1>, <&CLK_M_A1_DIV0 3>;
+ clocks = <&clockgen_f 1>, <&clk_m_a1_div0 3>;
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
index 81eb3855ab92..efb51cf0c845 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
@@ -19,11 +19,14 @@ Required properties:
"st,stih415-plls-c32-ddr", "st,clkgen-plls-c32"
"st,stih416-plls-c32-a9", "st,clkgen-plls-c32"
"st,stih416-plls-c32-ddr", "st,clkgen-plls-c32"
+ "st,stih407-plls-c32-a0", "st,clkgen-plls-c32"
+ "st,stih407-plls-c32-a9", "st,clkgen-plls-c32"
+ "st,stih407-plls-c32-c0_0", "st,clkgen-plls-c32"
+ "st,stih407-plls-c32-c0_1", "st,clkgen-plls-c32"
"st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32"
"st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32"
-
- #clock-cells : From common clock binding; shall be set to 1.
- clocks : From common clock binding
@@ -32,17 +35,17 @@ Required properties:
Example:
- clockgenA@fee62000 {
+ clockgen-a@fee62000 {
reg = <0xfee62000 0xb48>;
- CLK_S_A0_PLL: CLK_S_A0_PLL {
+ clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>;
compatible = "st,clkgena-plls-c65";
- clocks = <&CLK_SYSIN>;
+ clocks = <&clk_sysin>;
- clock-output-names = "CLK_S_A0_PLL0_HS",
- "CLK_S_A0_PLL0_LS",
- "CLK_S_A0_PLL1";
+ clock-output-names = "clk-s-a0-pll0-hs",
+ "clk-s-a0-pll0-ls",
+ "clk-s-a0-pll1";
};
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
index 566c9d79ed32..604766c2619e 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-prediv.txt
@@ -20,17 +20,17 @@ Required properties:
Example:
- clockgenA@fd345000 {
+ clockgen-a@fd345000 {
reg = <0xfd345000 0xb50>;
- CLK_M_A2_OSC_PREDIV: CLK_M_A2_OSC_PREDIV {
+ clk_m_a2_osc_prediv: clk-m-a2-osc-prediv {
#clock-cells = <0>;
compatible = "st,clkgena-prediv-c32",
"st,clkgena-prediv";
- clocks = <&CLK_SYSIN>;
+ clocks = <&clk_sysin>;
- clock-output-names = "CLK_M_A2_OSC_PREDIV";
+ clock-output-names = "clk-m-a2-osc-prediv";
};
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
index 4e3ff28b04c3..109b3eddcb17 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-vcc.txt
@@ -32,22 +32,30 @@ Required properties:
Example:
- CLOCKGEN_C_VCC: CLOCKGEN_C_VCC {
+ clockgen_c_vcc: clockgen-c-vcc@0xfe8308ac {
#clock-cells = <1>;
compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
reg = <0xfe8308ac 12>;
- clocks = <&CLK_S_VCC_HD>, <&CLOCKGEN_C 1>,
- <&CLK_S_TMDS_FROMPHY>, <&CLOCKGEN_C 2>;
-
- clock-output-names =
- "CLK_S_PIX_HDMI", "CLK_S_PIX_DVO",
- "CLK_S_OUT_DVO", "CLK_S_PIX_HD",
- "CLK_S_HDDAC", "CLK_S_DENC",
- "CLK_S_SDDAC", "CLK_S_PIX_MAIN",
- "CLK_S_PIX_AUX", "CLK_S_STFE_FRC_0",
- "CLK_S_REF_MCRU", "CLK_S_SLAVE_MCRU",
- "CLK_S_TMDS_HDMI", "CLK_S_HDMI_REJECT_PLL",
- "CLK_S_THSENS";
+ clocks = <&clk_s_vcc_hd>,
+ <&clockgen_c 1>,
+ <&clk_s_tmds_fromphy>,
+ <&clockgen_c 2>;
+
+ clock-output-names = "clk-s-pix-hdmi",
+ "clk-s-pix-dvo",
+ "clk-s-out-dvo",
+ "clk-s-pix-hd",
+ "clk-s-hddac",
+ "clk-s-denc",
+ "clk-s-sddac",
+ "clk-s-pix-main",
+ "clk-s-pix-aux",
+ "clk-s-stfe-frc-0",
+ "clk-s-ref-mcru",
+ "clk-s-slave-mcru",
+ "clk-s-tmds-hdmi",
+ "clk-s-hdmi-reject-pll",
+ "clk-s-thsens";
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
index 49ec5ae18b5b..78978f1f5158 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
@@ -24,60 +24,77 @@ address is common of all subnode.
quadfs_node {
...
};
+
+ mux_node {
+ ...
+ };
+
+ vcc_node {
+ ...
+ };
+
+ flexgen_node {
+ ...
+ };
...
};
This binding uses the common clock binding[1].
-Each subnode should use the binding discribe in [2]..[4]
+Each subnode should use the binding discribe in [2]..[7]
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/st,quadfs.txt
-[3] Documentation/devicetree/bindings/clock/st,quadfs.txt
-[4] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
+[3] Documentation/devicetree/bindings/clock/st,clkgen-mux.txt
+[4] Documentation/devicetree/bindings/clock/st,clkgen-pll.txt
+[5] Documentation/devicetree/bindings/clock/st,clkgen-prediv.txt
+[6] Documentation/devicetree/bindings/clock/st,vcc.txt
+[7] Documentation/devicetree/bindings/clock/st,quadfs.txt
+[8] Documentation/devicetree/bindings/clock/st,flexgen.txt
+
Required properties:
- reg : A Base address and length of the register set.
Example:
- clockgenA@fee62000 {
+ clockgen-a@fee62000 {
reg = <0xfee62000 0xb48>;
- CLK_S_A0_PLL: CLK_S_A0_PLL {
+ clk_s_a0_pll: clk-s-a0-pll {
#clock-cells = <1>;
compatible = "st,clkgena-plls-c65";
- clocks = <&CLK_SYSIN>;
+ clocks = <&clk-sysin>;
- clock-output-names = "CLK_S_A0_PLL0_HS",
- "CLK_S_A0_PLL0_LS",
- "CLK_S_A0_PLL1";
+ clock-output-names = "clk-s-a0-pll0-hs",
+ "clk-s-a0-pll0-ls",
+ "clk-s-a0-pll1";
};
- CLK_S_A0_OSC_PREDIV: CLK_S_A0_OSC_PREDIV {
+ clk_s_a0_osc_prediv: clk-s-a0-osc-prediv {
#clock-cells = <0>;
compatible = "st,clkgena-prediv-c65",
"st,clkgena-prediv";
- clocks = <&CLK_SYSIN>;
+ clocks = <&clk_sysin>;
- clock-output-names = "CLK_S_A0_OSC_PREDIV";
+ clock-output-names = "clk-s-a0-osc-prediv";
};
- CLK_S_A0_HS: CLK_S_A0_HS {
+ clk_s_a0_hs: clk-s-a0-hs {
#clock-cells = <1>;
compatible = "st,clkgena-divmux-c65-hs",
"st,clkgena-divmux";
- clocks = <&CLK_S_A0_OSC_PREDIV>,
- <&CLK_S_A0_PLL 0>, /* PLL0 HS */
- <&CLK_S_A0_PLL 2>; /* PLL1 */
+ clocks = <&clk-s_a0_osc_prediv>,
+ <&clk-s_a0_pll 0>, /* pll0 hs */
+ <&clk-s_a0_pll 2>; /* pll1 */
- clock-output-names = "CLK_S_FDMA_0",
- "CLK_S_FDMA_1",
- ""; /* CLK_S_JIT_SENSE */
- /* Fourth output unused */
+ clock-output-names = "clk-s-fdma-0",
+ "clk-s-fdma-1",
+ ""; /* clk-s-jit-sense */
+ /* fourth output unused */
};
};
diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
new file mode 100644
index 000000000000..1d3ace088172
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
@@ -0,0 +1,119 @@
+Binding for a type of flexgen structure found on certain
+STMicroelectronics consumer electronics SoC devices
+
+This structure includes:
+- a clock cross bar (represented by a mux element)
+- a pre and final dividers (represented by a divider and gate elements)
+
+Flexgen structure is a part of Clockgen[1].
+
+Please find an example below:
+
+ Clockgen block diagram
+ -------------------------------------------------------------------
+ | Flexgen stucture |
+ | --------------------------------------------- |
+ | | ------- -------- -------- | |
+clk_sysin | | | | | | | | |
+---|-----------------|-->| | | | | | | |
+ | | | | | | | | | | |
+ | | ------- | | | |Pre | |Final | | |
+ | | |PLL0 | | | | |Dividers| |Dividers| | |
+ | |->| | | | | | x32 | | x32 | | |
+ | | | odf_0|----|-->| | | | | | | |
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ | | ------- | | | | | | | | |
+ | | | | | | | | | | |
+ | | ------- | | Clock | | | | | | |
+ | | |PLL1 | | | | | | | | | |
+ | |->| | | | Cross | | | | | | |
+ | | | odf_0|----|-->| | | | | | CLK_DIV[31:0]
+ | | | | | | Bar |====>| |====>| |===|=========>
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ | | ------- | | | | | | | | |
+ | | | | | | | | | | |
+ | | ------- | | | | | | | | |
+ | | |QUADFS | | | | | | | | | |
+ | |->| ch0|----|-->| | | | | | | |
+ | | | | | | | | | | | |
+ | | ch1|----|-->| | | | | | | |
+ | | | | | | | | | | | |
+ | | ch2|----|-->| | | DIV | | DIV | | |
+ | | | | | | | 1 to | | 1 to | | |
+ | | ch3|----|-->| | | 1024 | | 64 | | |
+ | ------- | | | | | | | | |
+ | | ------- -------- -------- | |
+ | -------------------------------------------- |
+ | |
+ -------------------------------------------------------------------
+
+This binding uses the common clock binding[2].
+
+[1] Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be:
+ "st,flexgen"
+
+- #clock-cells : from common clock binding; shall be set to 1 (multiple clock
+ outputs).
+
+- clocks : must be set to the parent's phandle. it's could be output clocks of
+ a quadsfs or/and a pll or/and clk_sysin (up to 7 clocks)
+
+- clock-output-names : List of strings used to name the clock outputs.
+
+Example:
+
+ clk_s_c0_flexgen: clk-s-c0-flexgen {
+
+ #clock-cells = <1>;
+ compatible = "st,flexgen";
+
+ clocks = <&clk_s_c0_pll0 0>,
+ <&clk_s_c0_pll1 0>,
+ <&clk_s_c0_quadfs 0>,
+ <&clk_s_c0_quadfs 1>,
+ <&clk_s_c0_quadfs 2>,
+ <&clk_s_c0_quadfs 3>,
+ <&clk_sysin>;
+
+ clock-output-names = "clk-icn-gpu",
+ "clk-fdma",
+ "clk-nand",
+ "clk-hva",
+ "clk-proc-stfe",
+ "clk-proc-tp",
+ "clk-rx-icn-dmu",
+ "clk-rx-icn-hva",
+ "clk-icn-cpu",
+ "clk-tx-icn-dmu",
+ "clk-mmc-0",
+ "clk-mmc-1",
+ "clk-jpegdec",
+ "clk-ext2fa9",
+ "clk-ic-bdisp-0",
+ "clk-ic-bdisp-1",
+ "clk-pp-dmu",
+ "clk-vid-dmu",
+ "clk-dss-lpc",
+ "clk-st231-aud-0",
+ "clk-st231-gp-1",
+ "clk-st231-dmu",
+ "clk-icn-lmi",
+ "clk-tx-icn-disp-1",
+ "clk-icn-sbc",
+ "clk-stfe-frc2",
+ "clk-eth-phy",
+ "clk-eth-ref-phyclk",
+ "clk-flash-promip",
+ "clk-main-disp",
+ "clk-aux-disp",
+ "clk-compo-dvp";
+ };
diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
index ec86d62ca283..cedeb9cc8208 100644
--- a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt
@@ -15,6 +15,9 @@ Required properties:
"st,stih416-quadfs432", "st,quadfs"
"st,stih416-quadfs660-E", "st,quadfs"
"st,stih416-quadfs660-F", "st,quadfs"
+ "st,stih407-quadfs660-C", "st,quadfs"
+ "st,stih407-quadfs660-D", "st,quadfs"
+
- #clock-cells : from common clock binding; shall be set to 1.
@@ -32,14 +35,14 @@ Required properties:
Example:
- CLOCKGEN_E: CLOCKGEN_E {
+ clockgen_e: clockgen-e@fd3208bc {
#clock-cells = <1>;
compatible = "st,stih416-quadfs660-E", "st,quadfs";
reg = <0xfd3208bc 0xB0>;
- clocks = <&CLK_SYSIN>;
- clock-output-names = "CLK_M_PIX_MDTP_0",
- "CLK_M_PIX_MDTP_1",
- "CLK_M_PIX_MDTP_2",
- "CLK_M_MPELPC";
+ clocks = <&clk_sysin>;
+ clock-output-names = "clk-m-pix-mdtp-0",
+ "clk-m-pix-mdtp-1",
+ "clk-m-pix-mdtp-2",
+ "clk-m-mpelpc";
};
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index b9ec668bfe62..d3a5c3c6d677 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -9,11 +9,13 @@ Required properties:
"allwinner,sun4i-a10-osc-clk" - for a gatable oscillator
"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
+ "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-a10-axi-clk" - for the AXI clock
+ "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
"allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
@@ -23,13 +25,16 @@ Required properties:
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
+ "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
"allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
"allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
+ "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23
"allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
"allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
+ "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
"allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
"allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10
@@ -37,8 +42,10 @@ Required properties:
"allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s
"allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31
"allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
+ "allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23
"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
+ "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
"allwinner,sun7i-a20-out-clk" - for the external output clocks
"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff --git a/Documentation/devicetree/bindings/crypto/amd-ccp.txt b/Documentation/devicetree/bindings/crypto/amd-ccp.txt
new file mode 100644
index 000000000000..8c61183b41e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/amd-ccp.txt
@@ -0,0 +1,19 @@
+* AMD Cryptographic Coprocessor driver (ccp)
+
+Required properties:
+- compatible: Should be "amd,ccp-seattle-v1a"
+- reg: Address and length of the register set for the device
+- interrupt-parent: Should be the phandle for the interrupt controller
+ that services interrupts for this device
+- interrupts: Should contain the CCP interrupt
+
+Optional properties:
+- dma-coherent: Present if dma operations are coherent
+
+Example:
+ ccp@e0100000 {
+ compatible = "amd,ccp-seattle-v1a";
+ reg = <0 0xe0100000 0 0x10000>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 3 4>;
+ };
diff --git a/Documentation/devicetree/bindings/crypto/qcom-qce.txt b/Documentation/devicetree/bindings/crypto/qcom-qce.txt
new file mode 100644
index 000000000000..fdd53b184ba8
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/qcom-qce.txt
@@ -0,0 +1,25 @@
+Qualcomm crypto engine driver
+
+Required properties:
+
+- compatible : should be "qcom,crypto-v5.1"
+- reg : specifies base physical address and size of the registers map
+- clocks : phandle to clock-controller plus clock-specifier pair
+- clock-names : "iface" clocks register interface
+ "bus" clocks data transfer interface
+ "core" clocks rest of the crypto block
+- dmas : DMA specifiers for tx and rx dma channels. For more see
+ Documentation/devicetree/bindings/dma/dma.txt
+- dma-names : DMA request names should be "rx" and "tx"
+
+Example:
+ crypto@fd45a000 {
+ compatible = "qcom,crypto-v5.1";
+ reg = <0xfd45a000 0x6000>;
+ clocks = <&gcc GCC_CE2_AHB_CLK>,
+ <&gcc GCC_CE2_AXI_CLK>,
+ <&gcc GCC_CE2_CLK>;
+ clock-names = "iface", "bus", "core";
+ dmas = <&cryptobam 2>, <&cryptobam 3>;
+ dma-names = "rx", "tx";
+ };
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
index e577196a12c0..4659fd952301 100644
--- a/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
@@ -47,6 +47,7 @@ The full ID of peripheral types can be found below.
20 ASRC
21 ESAI
22 SSI Dual FIFO (needs firmware ver >= 2)
+ 23 Shared ASRC
The third cell specifies the transfer priority as below.
diff --git a/Documentation/devicetree/bindings/dma/mpc512x-dma.txt b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
new file mode 100644
index 000000000000..a6511df165c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
@@ -0,0 +1,29 @@
+* Freescale MPC512x and MPC8308 DMA Controller
+
+The DMA controller in Freescale MPC512x and MPC8308 SoCs can move
+blocks of memory contents between memory and peripherals or
+from memory to memory.
+
+Refer to "Generic DMA Controller and DMA request bindings" in
+the dma/dma.txt file for a more detailed description of binding.
+
+Required properties:
+- compatible: should be "fsl,mpc5121-dma" or "fsl,mpc8308-dma";
+- reg: should contain the DMA controller registers location and length;
+- interrupt for the DMA controller: syntax of interrupt client node
+ is described in interrupt-controller/interrupts.txt file.
+- #dma-cells: the length of the DMA specifier, must be <1>.
+ Each channel of this DMA controller has a peripheral request line,
+ the assignment is fixed in hardware. This one cell
+ in dmas property of a client device represents the channel number.
+
+Example:
+
+ dma0: dma@14000 {
+ compatible = "fsl,mpc5121-dma";
+ reg = <0x14000 0x1800>;
+ interrupts = <65 0x8>;
+ #dma-cells = <1>;
+ };
+
+DMA clients must use the format described in dma/dma.txt file.
diff --git a/Documentation/devicetree/bindings/dma/nbpfaxi.txt b/Documentation/devicetree/bindings/dma/nbpfaxi.txt
new file mode 100644
index 000000000000..d5e2522b9ec1
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/nbpfaxi.txt
@@ -0,0 +1,61 @@
+* Renesas "Type-AXI" NBPFAXI* DMA controllers
+
+* DMA controller
+
+Required properties
+
+- compatible: must be one of
+ "renesas,nbpfaxi64dmac1b4"
+ "renesas,nbpfaxi64dmac1b8"
+ "renesas,nbpfaxi64dmac1b16"
+ "renesas,nbpfaxi64dmac4b4"
+ "renesas,nbpfaxi64dmac4b8"
+ "renesas,nbpfaxi64dmac4b16"
+ "renesas,nbpfaxi64dmac8b4"
+ "renesas,nbpfaxi64dmac8b8"
+ "renesas,nbpfaxi64dmac8b16"
+- #dma-cells: must be 2: the first integer is a terminal number, to which this
+ slave is connected, the second one is flags. Flags is a bitmask
+ with the following bits defined:
+
+#define NBPF_SLAVE_RQ_HIGH 1
+#define NBPF_SLAVE_RQ_LOW 2
+#define NBPF_SLAVE_RQ_LEVEL 4
+
+Optional properties:
+
+You can use dma-channels and dma-requests as described in dma.txt, although they
+won't be used, this information is derived from the compatibility string.
+
+Example:
+
+ dma: dma-controller@48000000 {
+ compatible = "renesas,nbpfaxi64dmac8b4";
+ reg = <0x48000000 0x400>;
+ interrupts = <0 12 0x4
+ 0 13 0x4
+ 0 14 0x4
+ 0 15 0x4
+ 0 16 0x4
+ 0 17 0x4
+ 0 18 0x4
+ 0 19 0x4>;
+ #dma-cells = <2>;
+ dma-channels = <8>;
+ dma-requests = <8>;
+ };
+
+* DMA client
+
+Required properties:
+
+dmas and dma-names are required, as described in dma.txt.
+
+Example:
+
+#include <dt-bindings/dma/nbpfaxi.h>
+
+...
+ dmas = <&dma 0 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)
+ &dma 1 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)>;
+ dma-names = "rx", "tx";
diff --git a/Documentation/devicetree/bindings/dma/rcar-audmapp.txt b/Documentation/devicetree/bindings/dma/rcar-audmapp.txt
new file mode 100644
index 000000000000..9f1d750d76de
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/rcar-audmapp.txt
@@ -0,0 +1,29 @@
+* R-Car Audio DMAC peri peri Device Tree bindings
+
+Required properties:
+- compatible: should be "renesas,rcar-audmapp"
+- #dma-cells: should be <1>, see "dmas" property below
+
+Example:
+ audmapp: audio-dma-pp@0xec740000 {
+ compatible = "renesas,rcar-audmapp";
+ #dma-cells = <1>;
+
+ reg = <0 0xec740000 0 0x200>;
+ };
+
+
+* DMA client
+
+Required properties:
+- dmas: a list of <[DMA multiplexer phandle] [SRS/DRS value]> pairs,
+ where SRS/DRS values are fixed handles, specified in the SoC
+ manual as the value that would be written into the PDMACHCR.
+- dma-names: a list of DMA channel names, one per "dmas" entry
+
+Example:
+
+ dmas = <&audmapp 0x2d00
+ &audmapp 0x3700>;
+ dma-names = "src0_ssiu0",
+ "dvc0_ssiu0";
diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
new file mode 100644
index 000000000000..df0f48bcf75a
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
@@ -0,0 +1,98 @@
+* Renesas R-Car DMA Controller Device Tree bindings
+
+Renesas R-Car Generation 2 SoCs have have multiple multi-channel DMA
+controller instances named DMAC capable of serving multiple clients. Channels
+can be dedicated to specific clients or shared between a large number of
+clients.
+
+DMA clients are connected to the DMAC ports referenced by an 8-bit identifier
+called MID/RID.
+
+Each DMA client is connected to one dedicated port of the DMAC, identified by
+an 8-bit port number called the MID/RID. A DMA controller can thus serve up to
+256 clients in total. When the number of hardware channels is lower than the
+number of clients to be served, channels must be shared between multiple DMA
+clients. The association of DMA clients to DMAC channels is fully dynamic and
+not described in these device tree bindings.
+
+Required Properties:
+
+- compatible: must contain "renesas,rcar-dmac"
+
+- reg: base address and length of the registers block for the DMAC
+
+- interrupts: interrupt specifiers for the DMAC, one for each entry in
+ interrupt-names.
+- interrupt-names: one entry per channel, named "ch%u", where %u is the
+ channel number ranging from zero to the number of channels minus one.
+
+- clock-names: "fck" for the functional clock
+- clocks: a list of phandle + clock-specifier pairs, one for each entry
+ in clock-names.
+- clock-names: must contain "fck" for the functional clock.
+
+- #dma-cells: must be <1>, the cell specifies the MID/RID of the DMAC port
+ connected to the DMA client
+- dma-channels: number of DMA channels
+
+Example: R8A7790 (R-Car H2) SYS-DMACs
+
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,rcar-dmac";
+ reg = <0 0xe6700000 0 0x20000>;
+ interrupts = <0 197 IRQ_TYPE_LEVEL_HIGH
+ 0 200 IRQ_TYPE_LEVEL_HIGH
+ 0 201 IRQ_TYPE_LEVEL_HIGH
+ 0 202 IRQ_TYPE_LEVEL_HIGH
+ 0 203 IRQ_TYPE_LEVEL_HIGH
+ 0 204 IRQ_TYPE_LEVEL_HIGH
+ 0 205 IRQ_TYPE_LEVEL_HIGH
+ 0 206 IRQ_TYPE_LEVEL_HIGH
+ 0 207 IRQ_TYPE_LEVEL_HIGH
+ 0 208 IRQ_TYPE_LEVEL_HIGH
+ 0 209 IRQ_TYPE_LEVEL_HIGH
+ 0 210 IRQ_TYPE_LEVEL_HIGH
+ 0 211 IRQ_TYPE_LEVEL_HIGH
+ 0 212 IRQ_TYPE_LEVEL_HIGH
+ 0 213 IRQ_TYPE_LEVEL_HIGH
+ 0 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC0>;
+ clock-names = "fck";
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
+
+ dmac1: dma-controller@e6720000 {
+ compatible = "renesas,rcar-dmac";
+ reg = <0 0xe6720000 0 0x20000>;
+ interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
+ 0 216 IRQ_TYPE_LEVEL_HIGH
+ 0 217 IRQ_TYPE_LEVEL_HIGH
+ 0 218 IRQ_TYPE_LEVEL_HIGH
+ 0 219 IRQ_TYPE_LEVEL_HIGH
+ 0 308 IRQ_TYPE_LEVEL_HIGH
+ 0 309 IRQ_TYPE_LEVEL_HIGH
+ 0 310 IRQ_TYPE_LEVEL_HIGH
+ 0 311 IRQ_TYPE_LEVEL_HIGH
+ 0 312 IRQ_TYPE_LEVEL_HIGH
+ 0 313 IRQ_TYPE_LEVEL_HIGH
+ 0 314 IRQ_TYPE_LEVEL_HIGH
+ 0 315 IRQ_TYPE_LEVEL_HIGH
+ 0 316 IRQ_TYPE_LEVEL_HIGH
+ 0 317 IRQ_TYPE_LEVEL_HIGH
+ 0 318 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC1>;
+ clock-names = "fck";
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
diff --git a/Documentation/devicetree/bindings/dma/ste-dma40.txt b/Documentation/devicetree/bindings/dma/ste-dma40.txt
index 1f5729f10621..95800ab37bb0 100644
--- a/Documentation/devicetree/bindings/dma/ste-dma40.txt
+++ b/Documentation/devicetree/bindings/dma/ste-dma40.txt
@@ -35,9 +35,11 @@ Required properties:
Each dmas request consists of 4 cells:
1. A phandle pointing to the DMA controller
- 2. Device Type
+ 2. Device signal number, the signal line for single and burst requests
+ connected from the device to the DMA40 engine
3. The DMA request line number (only when 'use fixed channel' is set)
- 4. A 32bit mask specifying; mode, direction and endianness [NB: This list will grow]
+ 4. A 32bit mask specifying; mode, direction and endianness
+ [NB: This list will grow]
0x00000001: Mode:
Logical channel when unset
Physical channel when set
@@ -54,6 +56,74 @@ Each dmas request consists of 4 cells:
Normal priority when unset
High priority when set
+Existing signal numbers for the DB8500 ASIC. Unless specified, the signals are
+bidirectional, i.e. the same for RX and TX operations:
+
+0: SPI controller 0
+1: SD/MMC controller 0 (unused)
+2: SD/MMC controller 1 (unused)
+3: SD/MMC controller 2 (unused)
+4: I2C port 1
+5: I2C port 3
+6: I2C port 2
+7: I2C port 4
+8: Synchronous Serial Port SSP0
+9: Synchronous Serial Port SSP1
+10: Multi-Channel Display Engine MCDE RX
+11: UART port 2
+12: UART port 1
+13: UART port 0
+14: Multirate Serial Port MSP2
+15: I2C port 0
+16: USB OTG in/out endpoints 7 & 15
+17: USB OTG in/out endpoints 6 & 14
+18: USB OTG in/out endpoints 5 & 13
+19: USB OTG in/out endpoints 4 & 12
+20: SLIMbus or HSI channel 0
+21: SLIMbus or HSI channel 1
+22: SLIMbus or HSI channel 2
+23: SLIMbus or HSI channel 3
+24: Multimedia DSP SXA0
+25: Multimedia DSP SXA1
+26: Multimedia DSP SXA2
+27: Multimedia DSP SXA3
+28: SD/MM controller 2
+29: SD/MM controller 0
+30: MSP port 1 on DB8500 v1, MSP port 3 on DB8500 v2
+31: MSP port 0 or SLIMbus channel 0
+32: SD/MM controller 1
+33: SPI controller 2
+34: i2c3 RX2 TX2
+35: SPI controller 1
+36: USB OTG in/out endpoints 3 & 11
+37: USB OTG in/out endpoints 2 & 10
+38: USB OTG in/out endpoints 1 & 9
+39: USB OTG in/out endpoints 8
+40: SPI controller 3
+41: SD/MM controller 3
+42: SD/MM controller 4
+43: SD/MM controller 5
+44: Multimedia DSP SXA4
+45: Multimedia DSP SXA5
+46: SLIMbus channel 8 or Multimedia DSP SXA6
+47: SLIMbus channel 9 or Multimedia DSP SXA7
+48: Crypto Accelerator 1
+49: Crypto Accelerator 1 TX or Hash Accelerator 1 TX
+50: Hash Accelerator 1 TX
+51: memcpy TX (to be used by the DMA driver for memcpy operations)
+52: SLIMbus or HSI channel 4
+53: SLIMbus or HSI channel 5
+54: SLIMbus or HSI channel 6
+55: SLIMbus or HSI channel 7
+56: memcpy (to be used by the DMA driver for memcpy operations)
+57: memcpy (to be used by the DMA driver for memcpy operations)
+58: memcpy (to be used by the DMA driver for memcpy operations)
+59: memcpy (to be used by the DMA driver for memcpy operations)
+60: memcpy (to be used by the DMA driver for memcpy operations)
+61: Crypto Accelerator 0
+62: Crypto Accelerator 0 TX or Hash Accelerator 0 TX
+63: Hash Accelerator 0 TX
+
Example:
uart@80120000 {
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
new file mode 100644
index 000000000000..3e145c1675b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -0,0 +1,45 @@
+Allwinner A31 DMA Controller
+
+This driver follows the generic DMA bindings defined in dma.txt.
+
+Required properties:
+
+- compatible: Must be "allwinner,sun6i-a31-dma"
+- reg: Should contain the registers base address and length
+- interrupts: Should contain a reference to the interrupt used by this device
+- clocks: Should contain a reference to the parent AHB clock
+- resets: Should contain a reference to the reset controller asserting
+ this device in reset
+- #dma-cells : Should be 1, a single cell holding a line request number
+
+Example:
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun6i-a31-dma";
+ reg = <0x01c02000 0x1000>;
+ interrupts = <0 50 4>;
+ clocks = <&ahb1_gates 6>;
+ resets = <&ahb1_rst 6>;
+ #dma-cells = <1>;
+ };
+
+Clients:
+
+DMA clients connected to the A31 DMA controller must use the format
+described in the dma.txt file, using a two-cell specifier for each
+channel: a phandle plus one integer cells.
+The two cells in order are:
+
+1. A phandle pointing to the DMA controller.
+2. The port ID as specified in the datasheet
+
+Example:
+spi2: spi@01c6a000 {
+ compatible = "allwinner,sun6i-a31-spi";
+ reg = <0x01c6a000 0x1000>;
+ interrupts = <0 67 4>;
+ clocks = <&ahb1_gates 22>, <&spi2_clk>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 25>, <&dma 25>;
+ dma-names = "rx", "tx";
+ resets = <&ahb1_rst 22>;
+};
diff --git a/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt b/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt
new file mode 100644
index 000000000000..46525ea3e646
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt
@@ -0,0 +1,30 @@
+Device Tree bindings for Armada DRM CRTC driver
+
+Required properties:
+ - compatible: value should be "marvell,dove-lcd".
+ - reg: base address and size of the LCD controller
+ - interrupts: single interrupt number for the LCD controller
+ - port: video output port with endpoints, as described by graph.txt
+
+Optional properties:
+
+ - clocks: as described by clock-bindings.txt
+ - clock-names: as described by clock-bindings.txt
+ "axiclk" - axi bus clock for pixel clock
+ "plldivider" - pll divider clock for pixel clock
+ "ext_ref_clk0" - external clock 0 for pixel clock
+ "ext_ref_clk1" - external clock 1 for pixel clock
+
+Note: all clocks are optional but at least one must be specified.
+Further clocks may be added in the future according to requirements of
+different SoCs.
+
+Example:
+
+ lcd0: lcd-controller@820000 {
+ compatible = "marvell,dove-lcd";
+ reg = <0x820000 0x1000>;
+ interrupts = <47>;
+ clocks = <&si5351 0>;
+ clock-names = "ext_ref_clk_1";
+ };
diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
index d7df01c5bb3a..e9e4bce40760 100644
--- a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
+++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
@@ -3,6 +3,8 @@ Device-Tree bindings for the NXP TDA998x HDMI transmitter
Required properties;
- compatible: must be "nxp,tda998x"
+ - reg: I2C address
+
Optional properties:
- interrupts: interrupt number and trigger type
default: polling
diff --git a/Documentation/devicetree/bindings/drm/msm/gpu.txt b/Documentation/devicetree/bindings/drm/msm/gpu.txt
new file mode 100644
index 000000000000..67d0a58dbb77
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/gpu.txt
@@ -0,0 +1,52 @@
+Qualcomm adreno/snapdragon GPU
+
+Required properties:
+- compatible: "qcom,adreno-3xx"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt signal from the gpu.
+- clocks: device clocks
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+ * "core_clk"
+ * "iface_clk"
+ * "mem_iface_clk"
+- qcom,chipid: gpu chip-id. Note this may become optional for future
+ devices if we can reliably read the chipid from hw
+- qcom,gpu-pwrlevels: list of operating points
+ - compatible: "qcom,gpu-pwrlevels"
+ - for each qcom,gpu-pwrlevel:
+ - qcom,gpu-freq: requested gpu clock speed
+ - NOTE: downstream android driver defines additional parameters to
+ configure memory bandwidth scaling per OPP.
+
+Example:
+
+/ {
+ ...
+
+ gpu: qcom,kgsl-3d0@4300000 {
+ compatible = "qcom,adreno-3xx";
+ reg = <0x04300000 0x20000>;
+ reg-names = "kgsl_3d0_reg_memory";
+ interrupts = <GIC_SPI 80 0>;
+ interrupt-names = "kgsl_3d0_irq";
+ clock-names =
+ "core_clk",
+ "iface_clk",
+ "mem_iface_clk";
+ clocks =
+ <&mmcc GFX3D_CLK>,
+ <&mmcc GFX3D_AHB_CLK>,
+ <&mmcc MMSS_IMEM_AHB_CLK>;
+ qcom,chipid = <0x03020100>;
+ qcom,gpu-pwrlevels {
+ compatible = "qcom,gpu-pwrlevels";
+ qcom,gpu-pwrlevel@0 {
+ qcom,gpu-freq = <450000000>;
+ };
+ qcom,gpu-pwrlevel@1 {
+ qcom,gpu-freq = <27000000>;
+ };
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi.txt b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
new file mode 100644
index 000000000000..aca917fe2ba7
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
@@ -0,0 +1,46 @@
+Qualcomm adreno/snapdragon hdmi output
+
+Required properties:
+- compatible: one of the following
+ * "qcom,hdmi-tx-8660"
+ * "qcom,hdmi-tx-8960"
+- reg: Physical base address and length of the controller's registers
+- reg-names: "core_physical"
+- interrupts: The interrupt signal from the hdmi block.
+- clocks: device clocks
+ See ../clocks/clock-bindings.txt for details.
+- qcom,hdmi-tx-ddc-clk-gpio: ddc clk pin
+- qcom,hdmi-tx-ddc-data-gpio: ddc data pin
+- qcom,hdmi-tx-hpd-gpio: hpd pin
+- core-vdda-supply: phandle to supply regulator
+- hdmi-mux-supply: phandle to mux regulator
+
+Optional properties:
+- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin
+- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin
+
+Example:
+
+/ {
+ ...
+
+ hdmi: qcom,hdmi-tx-8960@4a00000 {
+ compatible = "qcom,hdmi-tx-8960";
+ reg-names = "core_physical";
+ reg = <0x04a00000 0x1000>;
+ interrupts = <GIC_SPI 79 0>;
+ clock-names =
+ "core_clk",
+ "master_iface_clk",
+ "slave_iface_clk";
+ clocks =
+ <&mmcc HDMI_APP_CLK>,
+ <&mmcc HDMI_M_AHB_CLK>,
+ <&mmcc HDMI_S_AHB_CLK>;
+ qcom,hdmi-tx-ddc-clk = <&msmgpio 70 GPIO_ACTIVE_HIGH>;
+ qcom,hdmi-tx-ddc-data = <&msmgpio 71 GPIO_ACTIVE_HIGH>;
+ qcom,hdmi-tx-hpd = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
+ core-vdda-supply = <&pm8921_hdmi_mvs>;
+ hdmi-mux-supply = <&ext_3p3v>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/drm/msm/mdp.txt b/Documentation/devicetree/bindings/drm/msm/mdp.txt
new file mode 100644
index 000000000000..1a0598e5279d
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/mdp.txt
@@ -0,0 +1,48 @@
+Qualcomm adreno/snapdragon display controller
+
+Required properties:
+- compatible:
+ * "qcom,mdp" - mdp4
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt signal from the display controller.
+- connectors: array of phandles for output device(s)
+- clocks: device clocks
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: the following clocks are required:
+ * "core_clk"
+ * "iface_clk"
+ * "lut_clk"
+ * "src_clk"
+ * "hdmi_clk"
+ * "mpd_clk"
+
+Optional properties:
+- gpus: phandle for gpu device
+
+Example:
+
+/ {
+ ...
+
+ mdp: qcom,mdp@5100000 {
+ compatible = "qcom,mdp";
+ reg = <0x05100000 0xf0000>;
+ interrupts = <GIC_SPI 75 0>;
+ connectors = <&hdmi>;
+ gpus = <&gpu>;
+ clock-names =
+ "core_clk",
+ "iface_clk",
+ "lut_clk",
+ "src_clk",
+ "hdmi_clk",
+ "mdp_clk";
+ clocks =
+ <&mmcc MDP_SRC>,
+ <&mmcc MDP_AHB_CLK>,
+ <&mmcc MDP_LUT_CLK>,
+ <&mmcc TV_SRC>,
+ <&mmcc HDMI_TV_CLK>,
+ <&mmcc MDP_TV_CLK>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt b/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt
new file mode 100644
index 000000000000..4ecda224955f
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-sm5502.txt
@@ -0,0 +1,23 @@
+
+* SM5502 MUIC (Micro-USB Interface Controller) device
+
+The Silicon Mitus SM5502 is a MUIC (Micro-USB Interface Controller) device
+which can detect the state of external accessory when external accessory is
+attached or detached and button is pressed or released. It is interfaced to
+the host controller using an I2C interface.
+
+Required properties:
+- compatible: Should be "siliconmitus,sm5502-muic"
+- reg: Specifies the I2C slave address of the MUIC block. It should be 0x25
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+ the interrupts from sm5502 are delivered to.
+- interrupts: Interrupt specifiers for detection interrupt sources.
+
+Example:
+
+ sm5502@25 {
+ compatible = "siliconmitus,sm5502-muic";
+ interrupt-parent = <&gpx1>;
+ interrupts = <5 0>;
+ reg = <0x25>;
+ };
diff --git a/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt
new file mode 100644
index 000000000000..d8c98c7614d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/fuse/nvidia,tegra20-fuse.txt
@@ -0,0 +1,40 @@
+NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 fuse block.
+
+Required properties:
+- compatible : should be:
+ "nvidia,tegra20-efuse"
+ "nvidia,tegra30-efuse"
+ "nvidia,tegra114-efuse"
+ "nvidia,tegra124-efuse"
+ Details:
+ nvidia,tegra20-efuse: Tegra20 requires using APB DMA to read the fuse data
+ due to a hardware bug. Tegra20 also lacks certain information which is
+ available in later generations such as fab code, lot code, wafer id,..
+ nvidia,tegra30-efuse, nvidia,tegra114-efuse and nvidia,tegra124-efuse:
+ The differences between these SoCs are the size of the efuse array,
+ the location of the spare (OEM programmable) bits and the location of
+ the speedo data.
+- reg: Should contain 1 entry: the entry gives the physical address and length
+ of the fuse registers.
+- clocks: Must contain an entry for each entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+ - fuse
+- resets: Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+ - fuse
+
+Example:
+
+ fuse@7000f800 {
+ compatible = "nvidia,tegra20-efuse";
+ reg = <0x7000F800 0x400>,
+ <0x70000000 0x400>;
+ clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+ clock-names = "fuse";
+ resets = <&tegra_car 39>;
+ reset-names = "fuse";
+ };
+
+
diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt
new file mode 100644
index 000000000000..986371a4be2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt
@@ -0,0 +1,26 @@
+Xilinx Zynq GPIO controller Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- #gpio-cells : Should be two
+ - First cell is the GPIO line number
+ - Second cell is used to specify optional
+ parameters (unused)
+- compatible : Should be "xlnx,zynq-gpio-1.0"
+- clocks : Clock specifier (see clock bindings for details)
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupts : Interrupt specifier (see interrupt bindings for
+ details)
+- interrupt-parent : Must be core interrupt controller
+- reg : Address and length of the register set for the device
+
+Example:
+ gpio@e000a000 {
+ #gpio-cells = <2>;
+ compatible = "xlnx,zynq-gpio-1.0";
+ clocks = <&clkc 42>;
+ gpio-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <0 20 4>;
+ reg = <0xe000a000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
new file mode 100644
index 000000000000..23bfe8e1f7cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
@@ -0,0 +1,43 @@
+NVIDIA GK20A Graphics Processing Unit
+
+Required properties:
+- compatible: "nvidia,<chip>-<gpu>"
+ Currently recognized values:
+ - nvidia,tegra124-gk20a
+- reg: Physical base address and length of the controller's registers.
+ Must contain two entries:
+ - first entry for bar0
+ - second entry for bar1
+- interrupts: Must contain an entry for each entry in interrupt-names.
+ See ../interrupt-controller/interrupts.txt for details.
+- interrupt-names: Must include the following entries:
+ - stall
+ - nonstall
+- vdd-supply: regulator for supply voltage.
+- clocks: Must contain an entry for each entry in clock-names.
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+ - gpu
+ - pwr
+- resets: Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+ - gpu
+
+Example:
+
+ gpu@0,57000000 {
+ compatible = "nvidia,gk20a";
+ reg = <0x0 0x57000000 0x0 0x01000000>,
+ <0x0 0x58000000 0x0 0x01000000>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "stall", "nonstall";
+ vdd-supply = <&vdd_gpu>;
+ clocks = <&tegra_car TEGRA124_CLK_GPU>,
+ <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
+ clock-names = "gpu", "pwr";
+ resets = <&tegra_car 184>;
+ reset-names = "gpu";
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/gpu/st,stih4xx.txt b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
new file mode 100644
index 000000000000..2d150c311a05
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt
@@ -0,0 +1,189 @@
+STMicroelectronics stih4xx platforms
+
+- sti-vtg: video timing generator
+ Required properties:
+ - compatible: "st,vtg"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ Optional properties:
+ - interrupts : VTG interrupt number to the CPU.
+ - st,slave: phandle on a slave vtg
+
+- sti-vtac: video timing advanced inter dye communication Rx and TX
+ Required properties:
+ - compatible: "st,vtac-main" or "st,vtac-aux"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - clocks: from common clock binding: handle hardware IP needed clocks, the
+ number of clocks may depend of the SoC type.
+ See ../clocks/clock-bindings.txt for details.
+ - clock-names: names of the clocks listed in clocks property in the same
+ order.
+
+- sti-display-subsystem: Master device for DRM sub-components
+ This device must be the parent of all the sub-components and is responsible
+ of bind them.
+ Required properties:
+ - compatible: "st,sti-display-subsystem"
+ - ranges: to allow probing of subdevices
+
+- sti-compositor: frame compositor engine
+ must be a child of sti-display-subsystem
+ Required properties:
+ - compatible: "st,stih<chip>-compositor"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - clocks: from common clock binding: handle hardware IP needed clocks, the
+ number of clocks may depend of the SoC type.
+ See ../clocks/clock-bindings.txt for details.
+ - clock-names: names of the clocks listed in clocks property in the same
+ order.
+ - resets: resets to be used by the device
+ See ../reset/reset.txt for details.
+ - reset-names: names of the resets listed in resets property in the same
+ order.
+ - st,vtg: phandle(s) on vtg device (main and aux) nodes.
+
+- sti-tvout: video out hardware block
+ must be a child of sti-display-subsystem
+ Required properties:
+ - compatible: "st,stih<chip>-tvout"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - reg-names: names of the mapped memory regions listed in regs property in
+ the same order.
+ - resets: resets to be used by the device
+ See ../reset/reset.txt for details.
+ - reset-names: names of the resets listed in resets property in the same
+ order.
+ - ranges: to allow probing of subdevices
+
+- sti-hdmi: hdmi output block
+ must be a child of sti-tvout
+ Required properties:
+ - compatible: "st,stih<chip>-hdmi";
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - reg-names: names of the mapped memory regions listed in regs property in
+ the same order.
+ - interrupts : HDMI interrupt number to the CPU.
+ - interrupt-names: name of the interrupts listed in interrupts property in
+ the same order
+ - clocks: from common clock binding: handle hardware IP needed clocks, the
+ number of clocks may depend of the SoC type.
+ - clock-names: names of the clocks listed in clocks property in the same
+ order.
+ - hdmi,hpd-gpio: gpio id to detect if an hdmi cable is plugged or not.
+
+sti-hda:
+ Required properties:
+ must be a child of sti-tvout
+ - compatible: "st,stih<chip>-hda"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - reg-names: names of the mapped memory regions listed in regs property in
+ the same order.
+ - clocks: from common clock binding: handle hardware IP needed clocks, the
+ number of clocks may depend of the SoC type.
+ See ../clocks/clock-bindings.txt for details.
+ - clock-names: names of the clocks listed in clocks property in the same
+ order.
+
+Example:
+
+/ {
+ ...
+
+ vtg_main_slave: sti-vtg-main-slave@fe85A800 {
+ compatible = "st,vtg";
+ reg = <0xfe85A800 0x300>;
+ interrupts = <GIC_SPI 175 IRQ_TYPE_NONE>;
+ };
+
+ vtg_main: sti-vtg-main-master@fd348000 {
+ compatible = "st,vtg";
+ reg = <0xfd348000 0x400>;
+ st,slave = <&vtg_main_slave>;
+ };
+
+ vtg_aux_slave: sti-vtg-aux-slave@fd348400 {
+ compatible = "st,vtg";
+ reg = <0xfe858200 0x300>;
+ interrupts = <GIC_SPI 176 IRQ_TYPE_NONE>;
+ };
+
+ vtg_aux: sti-vtg-aux-master@fd348400 {
+ compatible = "st,vtg";
+ reg = <0xfd348400 0x400>;
+ st,slave = <&vtg_aux_slave>;
+ };
+
+
+ sti-vtac-rx-main@fee82800 {
+ compatible = "st,vtac-main";
+ reg = <0xfee82800 0x200>;
+ clock-names = "vtac";
+ clocks = <&clk_m_a2_div0 CLK_M_VTAC_MAIN_PHY>;
+ };
+
+ sti-vtac-rx-aux@fee82a00 {
+ compatible = "st,vtac-aux";
+ reg = <0xfee82a00 0x200>;
+ clock-names = "vtac";
+ clocks = <&clk_m_a2_div0 CLK_M_VTAC_AUX_PHY>;
+ };
+
+ sti-vtac-tx-main@fd349000 {
+ compatible = "st,vtac-main";
+ reg = <0xfd349000 0x200>, <0xfd320000 0x10000>;
+ clock-names = "vtac";
+ clocks = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
+ };
+
+ sti-vtac-tx-aux@fd349200 {
+ compatible = "st,vtac-aux";
+ reg = <0xfd349200 0x200>, <0xfd320000 0x10000>;
+ clock-names = "vtac";
+ clocks = <&clk_s_a1_hs CLK_S_VTAC_TX_PHY>;
+ };
+
+ sti-display-subsystem {
+ compatible = "st,sti-display-subsystem";
+ ranges;
+
+ sti-compositor@fd340000 {
+ compatible = "st,stih416-compositor";
+ reg = <0xfd340000 0x1000>;
+ clock-names = "compo_main", "compo_aux",
+ "pix_main", "pix_aux";
+ clocks = <&clk_m_a2_div1 CLK_M_COMPO_MAIN>, <&clk_m_a2_div1 CLK_M_COMPO_AUX>,
+ <&clockgen_c_vcc CLK_S_PIX_MAIN>, <&clockgen_c_vcc CLK_S_PIX_AUX>;
+ reset-names = "compo-main", "compo-aux";
+ resets = <&softreset STIH416_COMPO_M_SOFTRESET>, <&softreset STIH416_COMPO_A_SOFTRESET>;
+ st,vtg = <&vtg_main>, <&vtg_aux>;
+ };
+
+ sti-tvout@fe000000 {
+ compatible = "st,stih416-tvout";
+ reg = <0xfe000000 0x1000>, <0xfe85a000 0x400>, <0xfe830000 0x10000>;
+ reg-names = "tvout-reg", "hda-reg", "syscfg";
+ reset-names = "tvout";
+ resets = <&softreset STIH416_HDTVOUT_SOFTRESET>;
+ ranges;
+
+ sti-hdmi@fe85c000 {
+ compatible = "st,stih416-hdmi";
+ reg = <0xfe85c000 0x1000>, <0xfe830000 0x10000>;
+ reg-names = "hdmi-reg", "syscfg";
+ interrupts = <GIC_SPI 173 IRQ_TYPE_NONE>;
+ interrupt-names = "irq";
+ clock-names = "pix", "tmds", "phy", "audio";
+ clocks = <&clockgen_c_vcc CLK_S_PIX_HDMI>, <&clockgen_c_vcc CLK_S_TMDS_HDMI>, <&clockgen_c_vcc CLK_S_HDMI_REJECT_PLL>, <&clockgen_b1 CLK_S_PCM_0>;
+ hdmi,hpd-gpio = <&PIO2 5>;
+ };
+
+ sti-hda@fe85a000 {
+ compatible = "st,stih416-hda";
+ reg = <0xfe85a000 0x400>, <0xfe83085c 0x4>;
+ reg-names = "hda-reg", "video-dacs-ctrl";
+ clock-names = "pix", "hddac";
+ clocks = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>;
+ };
+ };
+ };
+ ...
+};
diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
new file mode 100644
index 000000000000..f93242be60a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
@@ -0,0 +1,23 @@
+IBM POWERNV platform sensors
+----------------------------
+
+Required node properties:
+- compatible: must be one of
+ "ibm,opal-sensor-cooling-fan"
+ "ibm,opal-sensor-amb-temp"
+ "ibm,opal-sensor-power-supply"
+ "ibm,opal-sensor-power"
+- sensor-id: an opaque id provided by the firmware to the kernel, identifies a
+ given sensor and its attribute data
+
+Example sensors node:
+
+cooling-fan#8-data {
+ sensor-id = <0x7052107>;
+ compatible = "ibm,opal-sensor-cooling-fan";
+};
+
+amb-temp#1-thrs {
+ sensor-id = <0x5096000>;
+ compatible = "ibm,opal-sensor-amb-temp";
+};
diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
index b117b2e9e1a7..2391e5c41999 100644
--- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
+++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
@@ -3,6 +3,7 @@ NTC Thermistor hwmon sensors
Requires node properties:
- "compatible" value : one of
+ "epcos,b57330v2103"
"murata,ncp15wb473"
"murata,ncp18wb473"
"murata,ncp21wb473"
diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
new file mode 100644
index 000000000000..610757ce4492
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
@@ -0,0 +1,12 @@
+Bindings for a fan connected to the PWM lines
+
+Required properties:
+- compatible : "pwm-fan"
+- pwms : the PWM that is used to control the PWM fan
+
+Example:
+ pwm-fan {
+ compatible = "pwm-fan";
+ status = "okay";
+ pwms = <&pwm 0 10000 0>;
+ };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-efm32.txt b/Documentation/devicetree/bindings/i2c/i2c-efm32.txt
index fc15ac519437..50b25c3da186 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-efm32.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-efm32.txt
@@ -10,7 +10,7 @@ Required properties :
Recommended properties :
- clock-frequency : maximal I2C bus clock frequency in Hz.
- - efm32,location : Decides the location of the USART I/O pins.
+ - energymicro,location : Decides the location of the USART I/O pins.
Allowed range : [0 .. 6]
Example:
@@ -23,7 +23,7 @@ Example:
clocks = <&cmu clk_HFPERCLKI2C0>;
clock-frequency = <100000>;
status = "ok";
- efm32,location = <3>;
+ energymicro,location = <3>;
eeprom@50 {
compatible = "microchip,24c02";
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index bef86e57c388..6af570ec53b4 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -50,6 +50,7 @@ epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE
fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
+fsl,mma8452 MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer
fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller
fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
@@ -69,6 +70,7 @@ nuvoton,npct501 i2c trusted platform module (TPM)
nxp,pca9556 Octal SMBus and I2C registered interface
nxp,pca9557 8-bit I2C-bus and SMBus I/O port with reset
nxp,pcf8563 Real-time clock/calendar
+nxp,pcf85063 Tiny Real-Time Clock
ovti,ov5642 OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus
pericom,pt7c4338 Real-time Clock Module
plx,pex8648 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
@@ -83,5 +85,6 @@ stm,m41t80 M41T80 - SERIAL ACCESS RTC WITH ALARMS
taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface
ti,tsc2003 I2C Touch-Screen Controller
ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
+ti,tmp103 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
ti,tmp275 Digital Temperature Sensor
winbond,wpct301 i2c trusted platform module (TPM)
diff --git a/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt b/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt
new file mode 100644
index 000000000000..a8770cc6bcad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/max1027-adc.txt
@@ -0,0 +1,22 @@
+* Maxim 1027/1029/1031 Analog to Digital Converter (ADC)
+
+Required properties:
+ - compatible: Should be "maxim,max1027" or "maxim,max1029" or "maxim,max1031"
+ - reg: SPI chip select number for the device
+ - interrupt-parent: phandle to the parent interrupt controller
+ see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+ - interrupts: IRQ line for the ADC
+ see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+
+Recommended properties:
+- spi-max-frequency: Definition as per
+ Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Example:
+adc@0 {
+ compatible = "maxim,max1027";
+ reg = <0>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <15 IRQ_TYPE_EDGE_RISING>;
+ spi-max-frequency = <1000000>;
+};
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt b/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt
index 90d5f34db04e..8e191eef014e 100644
--- a/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt
+++ b/Documentation/devicetree/bindings/iio/magnetometer/hmc5843.txt
@@ -3,6 +3,10 @@
Required properties:
- compatible : should be "honeywell,hmc5843"
+ Other models which are supported with driver are:
+ "honeywell,hmc5883"
+ "honeywell,hmc5883l"
+ "honeywell,hmc5983"
- reg : the I2C address of the magnetometer - typically 0x1e
Optional properties:
diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
new file mode 100644
index 000000000000..a7a0a15913ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
@@ -0,0 +1,54 @@
+STMicroelectronics MEMS sensors
+
+The STMicroelectronics sensor devices are pretty straight-forward I2C or
+SPI devices, all sharing the same device tree descriptions no matter what
+type of sensor it is.
+
+Required properties:
+- compatible: see the list of valid compatible strings below
+- reg: the I2C or SPI address the device will respond to
+
+Optional properties:
+- vdd-supply: an optional regulator that needs to be on to provide VDD
+ power to the sensor.
+- vddio-supply: an optional regulator that needs to be on to provide the
+ VDD IO power to the sensor.
+- st,drdy-int-pin: the pin on the package that will be used to signal
+ "data ready" (valid values: 1 or 2). This property is not configurable
+ on all sensors.
+
+Sensors may also have applicable pin control settings, those use the
+standard bindings from pinctrl/pinctrl-bindings.txt.
+
+Valid compatible strings:
+
+Accelerometers:
+- st,lsm303dlh-accel
+- st,lsm303dlhc-accel
+- st,lis3dh-accel
+- st,lsm330d-accel
+- st,lsm330dl-accel
+- st,lsm330dlc-accel
+- st,lis331dlh-accel
+- st,lsm303dl-accel
+- st,lsm303dlm-accel
+- st,lsm330-accel
+
+Gyroscopes:
+- st,l3g4200d-gyro
+- st,lsm330d-gyro
+- st,lsm330dl-gyro
+- st,lsm330dlc-gyro
+- st,l3gd20-gyro
+- st,l3g4is-gyro
+- st,lsm330-gyro
+
+Magnetometers:
+- st,lsm303dlhc-magn
+- st,lsm303dlm-magn
+- st,lis3mdl-magn
+
+Pressure sensors:
+- st,lps001wp-press
+- st,lps25h-press
+- st,lps331ap-press
diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
new file mode 100644
index 000000000000..baef432e8369
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
@@ -0,0 +1,25 @@
+Atmel maXTouch touchscreen/touchpad
+
+Required properties:
+- compatible:
+ atmel,maxtouch
+
+- reg: The I2C address of the device
+
+- interrupts: The sink for the touchpad's IRQ output
+ See ../interrupt-controller/interrupts.txt
+
+Optional properties for main touchpad device:
+
+- linux,gpio-keymap: An array of up to 4 entries indicating the Linux
+ keycode generated by each GPIO. Linux keycodes are defined in
+ <dt-bindings/input/input.h>.
+
+Example:
+
+ touch@4b {
+ compatible = "atmel,maxtouch";
+ reg = <0x4b>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_LOW>;
+ };
diff --git a/Documentation/devicetree/bindings/input/cap1106.txt b/Documentation/devicetree/bindings/input/cap1106.txt
new file mode 100644
index 000000000000..4b463904cba0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/cap1106.txt
@@ -0,0 +1,53 @@
+Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
+
+The node for this driver must be a child of a I2C controller node, as the
+device communication via I2C only.
+
+Required properties:
+
+ compatible: Must be "microchip,cap1106"
+
+ reg: The I2C slave address of the device.
+ Only 0x28 is valid.
+
+ interrupts: Property describing the interrupt line the
+ device's ALERT#/CM_IRQ# pin is connected to.
+ The device only has one interrupt source.
+
+Optional properties:
+
+ autorepeat: Enables the Linux input system's autorepeat
+ feature on the input device.
+
+ microchip,sensor-gain: Defines the gain of the sensor circuitry. This
+ effectively controls the sensitivity, as a
+ smaller delta capacitance is required to
+ generate the same delta count values.
+ Valid values are 1, 2, 4, and 8.
+ By default, a gain of 1 is set.
+
+ linux,keycodes: Specifies an array of numeric keycode values to
+ be used for the channels. If this property is
+ omitted, KEY_A, KEY_B, etc are used as
+ defaults. The array must have exactly six
+ entries.
+
+Example:
+
+i2c_controller {
+ cap1106@28 {
+ compatible = "microchip,cap1106";
+ interrupt-parent = <&gpio1>;
+ interrupts = <0 0>;
+ reg = <0x28>;
+ autorepeat;
+ microchip,sensor-gain = <2>;
+
+ linux,keycodes = <103 /* KEY_UP */
+ 106 /* KEY_RIGHT */
+ 108 /* KEY_DOWN */
+ 105 /* KEY_LEFT */
+ 109 /* KEY_PAGEDOWN */
+ 104>; /* KEY_PAGEUP */
+ };
+}
diff --git a/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
new file mode 100644
index 000000000000..6e551090f465
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt
@@ -0,0 +1,26 @@
+* Pixcir I2C touchscreen controllers
+
+Required properties:
+- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- attb-gpio: GPIO connected to the ATTB line of the chip
+- touchscreen-size-x: horizontal resolution of touchscreen (in pixels)
+- touchscreen-size-y: vertical resolution of touchscreen (in pixels)
+
+Example:
+
+ i2c@00000000 {
+ /* ... */
+
+ pixcir_ts@5c {
+ compatible = "pixcir,pixcir_ts";
+ reg = <0x5c>;
+ interrupts = <2 0>;
+ attb-gpio = <&gpf 2 0 2>;
+ touchscreen-size-x = <800>;
+ touchscreen-size-y = <600>;
+ };
+
+ /* ... */
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
index 2faf1f1fa39e..80c37df940a7 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
@@ -9,6 +9,9 @@ Required properties:
- x-size: horizontal resolution of touchscreen
- y-size: vertical resolution of touchscreen
+Optional properties:
+- vdd-supply: Regulator controlling the controller supply
+
Example:
i2c@00000000 {
@@ -18,6 +21,7 @@ Example:
compatible = "neonode,zforce";
reg = <0x50>;
interrupts = <2 0>;
+ vdd-supply = <&reg_zforce_vdd>;
gpios = <&gpio5 6 0>, /* INT */
<&gpio5 9 0>; /* RST */
diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
index 2742e9cfd6b1..2742e9cfd6b1 100644
--- a/Documentation/devicetree/bindings/arm/atmel-aic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt b/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt
new file mode 100644
index 000000000000..55c04faa3f3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt
@@ -0,0 +1,23 @@
+OpenRISC 1000 Programmable Interrupt Controller
+
+Required properties:
+
+- compatible : should be "opencores,or1k-pic-level" for variants with
+ level triggered interrupt lines, "opencores,or1k-pic-edge" for variants with
+ edge triggered interrupt lines or "opencores,or1200-pic" for machines
+ with the non-spec compliant or1200 type implementation.
+
+ "opencores,or1k-pic" is also provided as an alias to "opencores,or1200-pic",
+ but this is only for backwards compatibility.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. The value shall be 1.
+
+Example:
+
+intc: interrupt-controller {
+ compatible = "opencores,or1k-pic-level";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index f284b99402bc..2d0f7cd867ea 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -42,12 +42,6 @@ conditions.
** System MMU optional properties:
-- smmu-parent : When multiple SMMUs are chained together, this
- property can be used to provide a phandle to the
- parent SMMU (that is the next SMMU on the path going
- from the mmu-masters towards memory) node for this
- SMMU.
-
- calxeda,smmu-secure-config-access : Enable proper handling of buggy
implementations that always use secure access to
SMMU configuration registers. In this case non-secure
diff --git a/Documentation/devicetree/bindings/iommu/iommu.txt b/Documentation/devicetree/bindings/iommu/iommu.txt
new file mode 100644
index 000000000000..5a8b4624defc
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/iommu.txt
@@ -0,0 +1,182 @@
+This document describes the generic device tree binding for IOMMUs and their
+master(s).
+
+
+IOMMU device node:
+==================
+
+An IOMMU can provide the following services:
+
+* Remap address space to allow devices to access physical memory ranges that
+ they otherwise wouldn't be capable of accessing.
+
+ Example: 32-bit DMA to 64-bit physical addresses
+
+* Implement scatter-gather at page level granularity so that the device does
+ not have to.
+
+* Provide system protection against "rogue" DMA by forcing all accesses to go
+ through the IOMMU and faulting when encountering accesses to unmapped
+ address regions.
+
+* Provide address space isolation between multiple contexts.
+
+ Example: Virtualization
+
+Device nodes compatible with this binding represent hardware with some of the
+above capabilities.
+
+IOMMUs can be single-master or multiple-master. Single-master IOMMU devices
+typically have a fixed association to the master device, whereas multiple-
+master IOMMU devices can translate accesses from more than one master.
+
+The device tree node of the IOMMU device's parent bus must contain a valid
+"dma-ranges" property that describes how the physical address space of the
+IOMMU maps to memory. An empty "dma-ranges" property means that there is a
+1:1 mapping from IOMMU to memory.
+
+Required properties:
+--------------------
+- #iommu-cells: The number of cells in an IOMMU specifier needed to encode an
+ address.
+
+The meaning of the IOMMU specifier is defined by the device tree binding of
+the specific IOMMU. Below are a few examples of typical use-cases:
+
+- #iommu-cells = <0>: Single master IOMMU devices are not configurable and
+ therefore no additional information needs to be encoded in the specifier.
+ This may also apply to multiple master IOMMU devices that do not allow the
+ association of masters to be configured. Note that an IOMMU can by design
+ be multi-master yet only expose a single master in a given configuration.
+ In such cases the number of cells will usually be 1 as in the next case.
+- #iommu-cells = <1>: Multiple master IOMMU devices may need to be configured
+ in order to enable translation for a given master. In such cases the single
+ address cell corresponds to the master device's ID. In some cases more than
+ one cell can be required to represent a single master ID.
+- #iommu-cells = <4>: Some IOMMU devices allow the DMA window for masters to
+ be configured. The first cell of the address in this may contain the master
+ device's ID for example, while the second cell could contain the start of
+ the DMA window for the given device. The length of the DMA window is given
+ by the third and fourth cells.
+
+Note that these are merely examples and real-world use-cases may use different
+definitions to represent their individual needs. Always refer to the specific
+IOMMU binding for the exact meaning of the cells that make up the specifier.
+
+
+IOMMU master node:
+==================
+
+Devices that access memory through an IOMMU are called masters. A device can
+have multiple master interfaces (to one or more IOMMU devices).
+
+Required properties:
+--------------------
+- iommus: A list of phandle and IOMMU specifier pairs that describe the IOMMU
+ master interfaces of the device. One entry in the list describes one master
+ interface of the device.
+
+When an "iommus" property is specified in a device tree node, the IOMMU will
+be used for address translation. If a "dma-ranges" property exists in the
+device's parent node it will be ignored. An exception to this rule is if the
+referenced IOMMU is disabled, in which case the "dma-ranges" property of the
+parent shall take effect. Note that merely disabling a device tree node does
+not guarantee that the IOMMU is really disabled since the hardware may not
+have a means to turn off translation. But it is invalid in such cases to
+disable the IOMMU's device tree node in the first place because it would
+prevent any driver from properly setting up the translations.
+
+
+Notes:
+======
+
+One possible extension to the above is to use an "iommus" property along with
+a "dma-ranges" property in a bus device node (such as PCI host bridges). This
+can be useful to describe how children on the bus relate to the IOMMU if they
+are not explicitly listed in the device tree (e.g. PCI devices). However, the
+requirements of that use-case haven't been fully determined yet. Implementing
+this is therefore not recommended without further discussion and extension of
+this binding.
+
+
+Examples:
+=========
+
+Single-master IOMMU:
+--------------------
+
+ iommu {
+ #iommu-cells = <0>;
+ };
+
+ master {
+ iommus = <&{/iommu}>;
+ };
+
+Multiple-master IOMMU with fixed associations:
+----------------------------------------------
+
+ /* multiple-master IOMMU */
+ iommu {
+ /*
+ * Masters are statically associated with this IOMMU and share
+ * the same address translations because the IOMMU does not
+ * have sufficient information to distinguish between masters.
+ *
+ * Consequently address translation is always on or off for
+ * all masters at any given point in time.
+ */
+ #iommu-cells = <0>;
+ };
+
+ /* static association with IOMMU */
+ master@1 {
+ reg = <1>;
+ iommus = <&{/iommu}>;
+ };
+
+ /* static association with IOMMU */
+ master@2 {
+ reg = <2>;
+ iommus = <&{/iommu}>;
+ };
+
+Multiple-master IOMMU:
+----------------------
+
+ iommu {
+ /* the specifier represents the ID of the master */
+ #iommu-cells = <1>;
+ };
+
+ master@1 {
+ /* device has master ID 42 in the IOMMU */
+ iommus = <&{/iommu} 42>;
+ };
+
+ master@2 {
+ /* device has master IDs 23 and 24 in the IOMMU */
+ iommus = <&{/iommu} 23>, <&{/iommu} 24>;
+ };
+
+Multiple-master IOMMU with configurable DMA window:
+---------------------------------------------------
+
+ / {
+ iommu {
+ /*
+ * One cell for the master ID and one cell for the
+ * address of the DMA window. The length of the DMA
+ * window is encoded in two cells.
+ *
+ * The DMA window is the range addressable by the
+ * master (i.e. the I/O virtual address space).
+ */
+ #iommu-cells = <4>;
+ };
+
+ master {
+ /* master ID 42, 4 GiB DMA window starting at 0 */
+ iommus = <&{/iommu} 42 0 0x1 0x0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/pca963x.txt b/Documentation/devicetree/bindings/leds/pca963x.txt
index aece3eac1b63..dafbe9931c2b 100644
--- a/Documentation/devicetree/bindings/leds/pca963x.txt
+++ b/Documentation/devicetree/bindings/leds/pca963x.txt
@@ -1,18 +1,19 @@
LEDs connected to pca9632, pca9633 or pca9634
Required properties:
-- compatible : should be : "nxp,pca9632", "nxp,pca9633" or "nxp,pca9634"
+- compatible : should be : "nxp,pca9632", "nxp,pca9633", "nxp,pca9634" or "nxp,pca9635"
Optional properties:
-- nxp,totem-pole : use totem pole (push-pull) instead of default open-drain
+- nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults
+ to open-drain, newer chips to totem pole)
- nxp,hw-blink : use hardware blinking instead of software blinking
Each led is represented as a sub-node of the nxp,pca963x device.
LED sub-node properties:
- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
-- reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633
- or 0 to 7 in pca9634)
+- reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633,
+ 0 to 7 in pca9634, or 0 to 15 in pca9635)
- linux,default-trigger : (optional)
see Documentation/devicetree/bindings/leds/common.txt
diff --git a/Documentation/devicetree/bindings/leds/tca6507.txt b/Documentation/devicetree/bindings/leds/tca6507.txt
index d7221b84987c..bad9102796f3 100644
--- a/Documentation/devicetree/bindings/leds/tca6507.txt
+++ b/Documentation/devicetree/bindings/leds/tca6507.txt
@@ -8,7 +8,7 @@ Required properties:
Optional properties:
- gpio-controller: allows lines to be used as output-only GPIOs.
-- #gpio-cells: if present, must be 0.
+- #gpio-cells: if present, must not be 0.
Each led is represented as a sub-node of the ti,tca6507 device.
diff --git a/Documentation/devicetree/bindings/media/atmel-isi.txt b/Documentation/devicetree/bindings/media/atmel-isi.txt
new file mode 100644
index 000000000000..17e71b7b44c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/atmel-isi.txt
@@ -0,0 +1,51 @@
+Atmel Image Sensor Interface (ISI) SoC Camera Subsystem
+----------------------------------------------
+
+Required properties:
+- compatible: must be "atmel,at91sam9g45-isi"
+- reg: physical base address and length of the registers set for the device;
+- interrupts: should contain IRQ line for the ISI;
+- clocks: list of clock specifiers, corresponding to entries in
+ the clock-names property;
+- clock-names: must contain "isi_clk", which is the isi peripherial clock.
+
+ISI supports a single port node with parallel bus. It should contain one
+'port' child node with child 'endpoint' node. Please refer to the bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+ isi: isi@f0034000 {
+ compatible = "atmel,at91sam9g45-isi";
+ reg = <0xf0034000 0x4000>;
+ interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>;
+
+ clocks = <&isi_clk>;
+ clock-names = "isi_clk";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_isi>;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ isi_0: endpoint {
+ remote-endpoint = <&ov2640_0>;
+ bus-width = <8>;
+ };
+ };
+ };
+
+ i2c1: i2c@f0018000 {
+ ov2640: camera@0x30 {
+ compatible = "omnivision,ov2640";
+ reg = <0x30>;
+
+ port {
+ ov2640_0: endpoint {
+ remote-endpoint = <&isi_0>;
+ bus-width = <8>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt b/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
index 937b755baf8f..bf52ed4a5067 100644
--- a/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
+++ b/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
@@ -3,9 +3,13 @@ Samsung S5P/EXYNOS SoC series JPEG codec
Required properties:
- compatible : should be one of:
- "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg";
+ "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
+ "samsung,exynos3250-jpeg";
- reg : address and length of the JPEG codec IP register set;
- interrupts : specifies the JPEG codec IP interrupt;
-- clocks : should contain the JPEG codec IP gate clock specifier, from the
- common clock bindings;
-- clock-names : should contain "jpeg" entry.
+- clock-names : should contain:
+ - "jpeg" for the core gate clock,
+ - "sclk" for the special clock (optional).
+- clocks : should contain the clock specifier and clock ID list
+ matching entries in the clock-names property; from
+ the common clock bindings.
diff --git a/Documentation/devicetree/bindings/media/i2c/mt9m111.txt b/Documentation/devicetree/bindings/media/i2c/mt9m111.txt
new file mode 100644
index 000000000000..ed5a334b1e57
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/mt9m111.txt
@@ -0,0 +1,28 @@
+Micron 1.3Mp CMOS Digital Image Sensor
+
+The Micron MT9M111 is a CMOS active pixel digital image sensor with an active
+array size of 1280H x 1024V. It is programmable through a simple two-wire serial
+interface.
+
+Required Properties:
+- compatible: value should be "micron,mt9m111"
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+ i2c_master {
+ mt9m111@5d {
+ compatible = "micron,mt9m111";
+ reg = <0x5d>;
+
+ remote = <&pxa_camera>;
+ port {
+ mt9m111_1: endpoint {
+ bus-width = <8>;
+ remote-endpoint = <&pxa_camera>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/pxa-camera.txt b/Documentation/devicetree/bindings/media/pxa-camera.txt
new file mode 100644
index 000000000000..11f5b5d51af8
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/pxa-camera.txt
@@ -0,0 +1,43 @@
+Marvell PXA camera host interface
+
+Required properties:
+ - compatible: Should be "marvell,pxa270-qci"
+ - reg: register base and size
+ - interrupts: the interrupt number
+ - any required generic properties defined in video-interfaces.txt
+
+Optional properties:
+ - clocks: input clock (see clock-bindings.txt)
+ - clock-output-names: should contain the name of the clock driving the
+ sensor master clock MCLK
+ - clock-frequency: host interface is driving MCLK, and MCLK rate is this rate
+
+Example:
+
+ pxa_camera: pxa_camera@50000000 {
+ compatible = "marvell,pxa270-qci";
+ reg = <0x50000000 0x1000>;
+ interrupts = <33>;
+
+ clocks = <&pxa2xx_clks 24>;
+ clock-names = "ciclk";
+ clock-frequency = <50000000>;
+ clock-output-names = "qci_mclk";
+
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Parallel bus endpoint */
+ qci: endpoint@0 {
+ reg = <0>; /* Local endpoint # */
+ remote-endpoint = <&mt9m111_1>;
+ bus-width = <8>; /* Used data lines */
+ hsync-active = <0>; /* Active low */
+ vsync-active = <0>; /* Active low */
+ pclk-sample = <1>; /* Rising */
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
new file mode 100644
index 000000000000..ba61782c2af9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -0,0 +1,86 @@
+Renesas RCar Video Input driver (rcar_vin)
+------------------------------------------
+
+The rcar_vin device provides video input capabilities for the Renesas R-Car
+family of devices. The current blocks are always slaves and suppot one input
+channel which can be either RGB, YUYV or BT656.
+
+ - compatible: Must be one of the following
+ - "renesas,vin-r8a7791" for the R8A7791 device
+ - "renesas,vin-r8a7790" for the R8A7790 device
+ - "renesas,vin-r8a7779" for the R8A7779 device
+ - "renesas,vin-r8a7778" for the R8A7778 device
+ - reg: the register base and size for the device registers
+ - interrupts: the interrupt for the device
+ - clocks: Reference to the parent clock
+
+Additionally, an alias named vinX will need to be created to specify
+which video input device this is.
+
+The per-board settings:
+ - port sub-node describing a single endpoint connected to the vin
+ as described in video-interfaces.txt[1]. Only the first one will
+ be considered as each vin interface has one input port.
+
+ These settings are used to work out video input format and widths
+ into the system.
+
+
+Device node example
+-------------------
+
+ aliases {
+ vin0 = &vin0;
+ };
+
+ vin0: vin@0xe6ef0000 {
+ compatible = "renesas,vin-r8a7790";
+ clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+Board setup example (vin1 composite video input)
+------------------------------------------------
+
+&i2c2 {
+ status = "ok";
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+
+ adv7180@20 {
+ compatible = "adi,adv7180";
+ reg = <0x20>;
+ remote = <&vin1>;
+
+ port {
+ adv7180: endpoint {
+ bus-width = <8>;
+ remote-endpoint = <&vin1ep0>;
+ };
+ };
+ };
+};
+
+/* composite video input */
+&vin1 {
+ pinctrl-0 = <&vin1_pins>;
+ pinctrl-names = "default";
+
+ status = "ok";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vin1ep0: endpoint {
+ remote-endpoint = <&adv7180>;
+ bus-width = <8>;
+ };
+ };
+};
+
+
+
+[1] video-interfaces.txt common video media interface
diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt
new file mode 100644
index 000000000000..23dd5ad07b7c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt
@@ -0,0 +1,23 @@
+Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
+
+Required properties:
+- compatible : should be "allwinner,sun4i-a10-ir";
+- clocks : list of clock specifiers, corresponding to
+ entries in clock-names property;
+- clock-names : should contain "apb" and "ir" entries;
+- interrupts : should contain IR IRQ number;
+- reg : should contain IO map address for IR.
+
+Optional properties:
+- linux,rc-map-name : Remote control map name.
+
+Example:
+
+ir0: ir@01c21800 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 6>, <&ir0_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <0 5 1>;
+ reg = <0x01C21800 0x40>;
+ linux,rc-map-name = "rc-rc6-mce";
+};
diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt
index 36a0c3d8c726..5c7e7230984a 100644
--- a/Documentation/devicetree/bindings/mfd/arizona.txt
+++ b/Documentation/devicetree/bindings/mfd/arizona.txt
@@ -42,6 +42,16 @@ Optional properties:
the chip default will be used. If present exactly five values must
be specified.
+ - DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
+ they are being externally supplied. As covered in
+ Documentation/devicetree/bindings/regulator/regulator.txt
+
+Optional subnodes:
+ - ldo1 : Initial data for the LDO1 regulator, as covered in
+ Documentation/devicetree/bindings/regulator/regulator.txt
+ - micvdd : Initial data for the MICVDD regulator, as covered in
+ Documentation/devicetree/bindings/regulator/regulator.txt
+
Example:
codec: wm5102@1a {
diff --git a/Documentation/devicetree/bindings/mfd/as3722.txt b/Documentation/devicetree/bindings/mfd/as3722.txt
index 8edcb9bd873b..4f64b2a73169 100644
--- a/Documentation/devicetree/bindings/mfd/as3722.txt
+++ b/Documentation/devicetree/bindings/mfd/as3722.txt
@@ -13,6 +13,14 @@ Required properties:
The second cell is the flags, encoded as the trigger masks from binding document
interrupts.txt, using dt-bindings/irq.
+Optional properties:
+--------------------
+- ams,enable-internal-int-pullup: Boolean property, to enable internal pullup on
+ interrupt pin. Missing this will disable internal pullup on INT pin.
+- ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
+ i2c scl/sda pins. Missing this will disable internal pullup on i2c
+ scl/sda lines.
+
Optional submodule and their properties:
=======================================
diff --git a/Documentation/devicetree/bindings/mfd/palmas.txt b/Documentation/devicetree/bindings/mfd/palmas.txt
index e5f0f8303461..eda898978d33 100644
--- a/Documentation/devicetree/bindings/mfd/palmas.txt
+++ b/Documentation/devicetree/bindings/mfd/palmas.txt
@@ -6,6 +6,7 @@ twl6037 (palmas)
tps65913 (palmas)
tps65914 (palmas)
tps659038
+tps65917
Required properties:
- compatible : Should be from the list
@@ -16,6 +17,7 @@ Required properties:
ti,tps65914
ti,tps80036
ti,tps659038
+ ti,tps65917
and also the generic series names
ti,palmas
- interrupt-controller : palmas has its own internal IRQs
diff --git a/Documentation/devicetree/bindings/mfd/s2mps11.txt b/Documentation/devicetree/bindings/mfd/s2mps11.txt
index d81ba30c0d8b..ba2d7f0f9c5f 100644
--- a/Documentation/devicetree/bindings/mfd/s2mps11.txt
+++ b/Documentation/devicetree/bindings/mfd/s2mps11.txt
@@ -1,5 +1,5 @@
-* Samsung S2MPS11 and S2MPS14 Voltage and Current Regulator
+* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
The Samsung S2MPS11 is a multi-function device which includes voltage and
current regulators, RTC, charger controller and other sub-blocks. It is
@@ -7,7 +7,8 @@ interfaced to the host controller using an I2C interface. Each sub-block is
addressed by the host system using different I2C slave addresses.
Required properties:
-- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic".
+- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic"
+ or "samsung,s2mpu02-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties:
@@ -81,11 +82,13 @@ as per the datasheet of s2mps11.
- valid values for n are:
- S2MPS11: 1 to 38
- S2MPS14: 1 to 25
- - Example: LDO1, LD02, LDO28
+ - S2MPU02: 1 to 28
+ - Example: LDO1, LDO2, LDO28
- BUCKn
- valid values for n are:
- S2MPS11: 1 to 10
- S2MPS14: 1 to 5
+ - S2MPU02: 1 to 7
- Example: BUCK1, BUCK2, BUCK9
Example:
@@ -96,7 +99,7 @@ Example:
s2m_osc: clocks {
compatible = "samsung,s2mps11-clk";
- #clock-cells = 1;
+ #clock-cells = <1>;
clock-output-names = "xx", "yy", "zz";
};
diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
index 1f5a31fef907..03c5a551da55 100644
--- a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
+++ b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
@@ -4,7 +4,7 @@ PRCM is an MFD device exposing several Power Management related devices
(like clks and reset controllers).
Required properties:
- - compatible: "allwinner,sun6i-a31-prcm"
+ - compatible: "allwinner,sun6i-a31-prcm" or "allwinner,sun8i-a23-prcm"
- reg: The PRCM registers range
The prcm node may contain several subdevices definitions:
diff --git a/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
new file mode 100644
index 000000000000..b97b8bef1fe5
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/nvidia,tegra20-apbmisc.txt
@@ -0,0 +1,13 @@
+NVIDIA Tegra20/Tegra30/Tegr114/Tegra124 apbmisc block
+
+Required properties:
+- compatible : should be:
+ "nvidia,tegra20-apbmisc"
+ "nvidia,tegra30-apbmisc"
+ "nvidia,tegra114-apbmisc"
+ "nvidia,tegra124-apbmisc"
+- reg: Should contain 2 entries: the first entry gives the physical address
+ and length of the registers which contain revision and debug features.
+ The second entry gives the physical address and length of the
+ registers indicating the strapping options.
+
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
index 532b1d440abc..6cd3525d0e09 100644
--- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -46,13 +46,14 @@ Required Properties:
- if CIU clock divider value is 0 (that is divide by 1), both tx and rx
phase shift clocks should be 0.
-Required properties for a slot:
+Required properties for a slot (Deprecated - Recommend to use one slot per host):
* gpios: specifies a list of gpios used for command, clock and data bus. The
first gpio is the command line and the second gpio is the clock line. The
rest of the gpios (depending on the bus-width property) are the data lines in
no particular order. The format of the gpio specifier depends on the gpio
controller.
+(Deprecated - Refer to Documentation/devicetree/binding/pinctrl/samsung-pinctrl.txt)
Example:
@@ -69,21 +70,13 @@ Example:
dwmmc0@12200000 {
num-slots = <1>;
- supports-highspeed;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
broken-cd;
fifo-depth = <0x80>;
card-detect-delay = <200>;
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <2 3>;
samsung,dw-mshc-ddr-timing = <1 2>;
-
- slot@0 {
- reg = <0>;
- bus-width = <8>;
- gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
- <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
- <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
- <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
- <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
- };
+ bus-width = <8>;
};
diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
index e5bc49f764d1..3b3544931437 100644
--- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -34,13 +34,11 @@ Example:
num-slots = <1>;
vmmc-supply = <&ldo12>;
fifo-depth = <0x100>;
- supports-highspeed;
pinctrl-names = "default";
pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- disable-wp;
- cd-gpios = <&gpio10 3 0>;
- };
+ bus-width = <4>;
+ disable-wp;
+ cd-gpios = <&gpio10 3 0>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
};
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 3c18001dfd5d..431716e37a39 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -34,8 +34,8 @@ Optional properties:
- cap-power-off-card: powering off the card is safe
- cap-sdio-irq: enable SDIO IRQ signalling on this interface
- full-pwr-cycle: full power cycle of the card is supported
-- mmc-highspeed-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
-- mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
+- mmc-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported
+- mmc-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
- mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
new file mode 100644
index 000000000000..299081f94abd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
@@ -0,0 +1,32 @@
+* Renesas Multi Media Card Interface (MMCIF) Controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the MMCIF device.
+
+
+Required properties:
+
+- compatible: must contain one of the following
+ - "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
+ - "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
+ - "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
+ - "renesas,sh-mmcif" for the generic MMCIF
+
+- clocks: reference to the functional clock
+
+- dmas: reference to the DMA channels, one per channel name listed in the
+ dma-names property.
+- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the
+ receive DMA channel.
+
+
+Example: R8A7790 (R-Car H2) MMCIF0
+
+ mmcif0: mmc@ee200000 {
+ compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
+ reg = <0 0xee200000 0 0x80>;
+ interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
+ dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
+ dma-names = "tx", "rx";
+ };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 81b33b5b20fc..485483a63d8c 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -27,8 +27,8 @@ Example:
bus-width = <8>;
non-removable;
- vmmc = <&pm8941_l20>;
- vqmmc = <&pm8941_s3>;
+ vmmc-supply = <&pm8941_l20>;
+ vqmmc-supply = <&pm8941_s3>;
pinctrl-names = "default";
pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>;
@@ -44,8 +44,8 @@ Example:
bus-width = <4>;
cd-gpios = <&msmgpio 62 0x1>;
- vmmc = <&pm8941_l21>;
- vqmmc = <&pm8941_l13>;
+ vmmc-supply = <&pm8941_l21>;
+ vqmmc-supply = <&pm8941_l13>;
pinctrl-names = "default";
pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>;
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
new file mode 100644
index 000000000000..7527db447a35
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
@@ -0,0 +1,33 @@
+* STMicroelectronics sdhci-st MMC/SD controller
+
+This file documents the differences between the core properties in
+Documentation/devicetree/bindings/mmc/mmc.txt and the properties
+used by the sdhci-st driver.
+
+Required properties:
+- compatible : Must be "st,sdhci"
+- clock-names : Should be "mmc"
+ See: Documentation/devicetree/bindings/resource-names.txt
+- clocks : Phandle of the clock used by the sdhci controler
+ See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional properties:
+- non-removable: non-removable slot
+ See: Documentation/devicetree/bindings/mmc/mmc.txt
+- bus-width: Number of data lines
+ See: Documentation/devicetree/bindings/mmc/mmc.txt
+
+Example:
+
+mmc0: sdhci@fe81e000 {
+ compatible = "st,sdhci";
+ status = "disabled";
+ reg = <0xfe81e000 0x1000>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_NONE>;
+ interrupt-names = "mmcirq";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mmc0>;
+ clock-names = "mmc";
+ clocks = <&clk_s_a1_ls 1>;
+ bus-width = <8>
+};
diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
index 2d4a7258a10d..346c6095a615 100644
--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
@@ -67,7 +67,8 @@ Optional properties:
* card-detect-delay: Delay in milli-seconds before detecting card after card
insert event. The default value is 0.
-* supports-highspeed: Enables support for high speed cards (up to 50MHz)
+* supports-highspeed (DEPRECATED): Enables support for high speed cards (up to 50MHz)
+ (use "cap-mmc-highspeed" or "cap-sd-highspeed" instead)
* broken-cd: as documented in mmc core bindings.
@@ -98,14 +99,11 @@ board specific portions as listed below.
clock-frequency = <400000000>;
clock-freq-min-max = <400000 200000000>;
num-slots = <1>;
- supports-highspeed;
broken-cd;
fifo-depth = <0x80>;
card-detect-delay = <200>;
vmmc-supply = <&buck8>;
-
- slot@0 {
- reg = <0>;
- bus-width = <8>;
- };
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
};
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index ce8056116fb0..76bf087bc889 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -12,6 +12,7 @@ Required properties:
Should be "ti,omap3-hsmmc", for OMAP3 controllers
Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0
Should be "ti,omap4-hsmmc", for OMAP4 controllers
+ Should be "ti,am33xx-hsmmc", for AM335x controllers
- ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
Optional properties:
@@ -56,3 +57,56 @@ Examples:
&edma 25>;
dma-names = "tx", "rx";
};
+
+[workaround for missing swakeup on am33xx]
+
+This SOC is missing the swakeup line, it will not detect SDIO irq
+while in suspend.
+
+ ------
+ | PRCM |
+ ------
+ ^ |
+ swakeup | | fclk
+ | v
+ ------ ------- -----
+ | card | -- CIRQ --> | hsmmc | -- IRQ --> | CPU |
+ ------ ------- -----
+
+In suspend the fclk is off and the module is disfunctional. Even register reads
+will fail. A small logic in the host will request fclk restore, when an
+external event is detected. Once the clock is restored, the host detects the
+event normally. Since am33xx doesn't have this line it never wakes from
+suspend.
+
+The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make
+this work, we need to set the named pinctrl states "default" and "idle".
+Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio
+dat1. The MMC driver will then toggle between idle and default state during
+runtime.
+
+In summary:
+1. select matching 'compatible' section, see example below.
+2. specify pinctrl states "default" and "idle", "sleep" is optional.
+3. specify the gpio irq used for detecting sdio irq in suspend
+
+If configuration is incomplete, a warning message is emitted "falling back to
+polling". Also check the "sdio irq mode" in /sys/kernel/debug/mmc0/regs. Mind
+not every application needs SDIO irq, e.g. MMC cards.
+
+ mmc1: mmc@48060100 {
+ compatible = "ti,am33xx-hsmmc";
+ ...
+ pinctrl-names = "default", "idle", "sleep"
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-1 = <&mmc1_idle>;
+ pinctrl-2 = <&mmc1_sleep>;
+ ...
+ interrupts-extended = <&intc 64 &gpio2 28 0>;
+ };
+
+ mmc1_idle : pinmux_cirq_pin {
+ pinctrl-single,pins = <
+ 0x0f8 0x3f /* GPIO2_28 */
+ >;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
index 6a2a1160a70d..fa0f327cde01 100644
--- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
@@ -18,6 +18,7 @@ Required properties:
"renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
"renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC
"renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC
+ "renesas,sdhi-r8a7791" - SDHI IP on R8A7791 SoC
Optional properties:
- toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
index 458d59634688..a011fdf61dbf 100644
--- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
@@ -25,6 +25,16 @@ Optional properties:
discoverable or this property is not enabled,
the software may chooses an implementation-defined
ECC scheme.
+ - fsl,no-blockmark-swap: Don't swap the bad block marker from the OOB
+ area with the byte in the data area but rely on the
+ flash based BBT for identifying bad blocks.
+ NOTE: this is only valid in conjunction with
+ 'nand-on-flash-bbt'.
+ WARNING: on i.MX28 blockmark swapping cannot be
+ disabled for the BootROM in the FCB. Thus,
+ partitions written from Linux with this feature
+ turned on may not be accessible by the BootROM
+ code.
The device tree may optionally contain sub-nodes describing partitions of the
address space. See partition.txt for more detail.
diff --git a/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt b/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt
index d01ed63d3ebb..42409bfe04c4 100644
--- a/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt
+++ b/Documentation/devicetree/bindings/net/amd-xgbe-phy.txt
@@ -8,10 +8,16 @@ Required properties:
- SerDes integration registers (1/2)
- SerDes integration registers (2/2)
+Optional properties:
+- amd,speed-set: Speed capabilities of the device
+ 0 - 1GbE and 10GbE (default)
+ 1 - 2.5GbE and 10GbE
+
Example:
xgbe_phy@e1240800 {
compatible = "amd,xgbe-phy-seattle-v1a", "ethernet-phy-ieee802.3-c45";
reg = <0 0xe1240800 0 0x00400>,
<0 0xe1250000 0 0x00060>,
<0 0xe1250080 0 0x00004>;
+ amd,speed-set = <0>;
};
diff --git a/Documentation/devicetree/bindings/net/amd-xgbe.txt b/Documentation/devicetree/bindings/net/amd-xgbe.txt
index ea0c7908a3b8..41354f730beb 100644
--- a/Documentation/devicetree/bindings/net/amd-xgbe.txt
+++ b/Documentation/devicetree/bindings/net/amd-xgbe.txt
@@ -8,16 +8,21 @@ Required properties:
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the amd-xgbe interrupt
-- clocks: Should be the DMA clock for the amd-xgbe device (used for
- calculating the correct Rx interrupt watchdog timer value on a DMA
- channel for coalescing)
-- clock-names: Should be the name of the DMA clock, "dma_clk"
+- clocks:
+ - DMA clock for the amd-xgbe device (used for calculating the
+ correct Rx interrupt watchdog timer value on a DMA channel
+ for coalescing)
+ - PTP clock for the amd-xgbe device
+- clock-names: Should be the names of the clocks
+ - "dma_clk" for the DMA clock
+ - "ptp_clk" for the PTP clock
- phy-handle: See ethernet.txt file in the same directory
- phy-mode: See ethernet.txt file in the same directory
Optional properties:
- mac-address: mac address to be assigned to the device. Can be overridden
by UEFI.
+- dma-coherent: Present if dma operations are coherent
Example:
xgbe@e0700000 {
@@ -26,8 +31,8 @@ Example:
<0 0xe0780000 0 0x80000>;
interrupt-parent = <&gic>;
interrupts = <0 325 4>;
- clocks = <&xgbe_clk>;
- clock-names = "dma_clk";
+ clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>;
+ clock-names = "dma_clk", "ptp_clk";
phy-handle = <&phy>;
phy-mode = "xgmii";
mac-address = [ 02 a1 a2 a3 a4 a5 ];
diff --git a/Documentation/devicetree/bindings/net/apm-xgene-enet.txt b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
new file mode 100644
index 000000000000..ebcad25efd0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
@@ -0,0 +1,66 @@
+APM X-Gene SoC Ethernet nodes
+
+Ethernet nodes are defined to describe on-chip ethernet interfaces in
+APM X-Gene SoC.
+
+Required properties:
+- compatible: Should be "apm,xgene-enet"
+- reg: Address and length of the register set for the device. It contains the
+ information of registers in the same order as described by reg-names
+- reg-names: Should contain the register set names
+ - "enet_csr": Ethernet control and status register address space
+ - "ring_csr": Descriptor ring control and status register address space
+ - "ring_cmd": Descriptor ring command register address space
+- interrupts: Ethernet main interrupt
+- clocks: Reference to the clock entry.
+- local-mac-address: MAC address assigned to this device
+- phy-connection-type: Interface type between ethernet device and PHY device
+- phy-handle: Reference to a PHY node connected to this device
+
+- mdio: Device tree subnode with the following required properties:
+ - compatible: Must be "apm,xgene-mdio".
+ - #address-cells: Must be <1>.
+ - #size-cells: Must be <0>.
+
+ For the phy on the mdio bus, there must be a node with the following fields:
+ - compatible: PHY identifier. Please refer ./phy.txt for the format.
+ - reg: The ID number for the phy.
+
+Optional properties:
+- status: Should be "ok" or "disabled" for enabled/disabled. Default is "ok".
+
+Example:
+ menetclk: menetclk {
+ compatible = "apm,xgene-device-clock";
+ clock-output-names = "menetclk";
+ status = "ok";
+ };
+
+ menet: ethernet@17020000 {
+ compatible = "apm,xgene-enet";
+ status = "disabled";
+ reg = <0x0 0x17020000 0x0 0xd100>,
+ <0x0 0X17030000 0x0 0X400>,
+ <0x0 0X10000000 0x0 0X200>;
+ reg-names = "enet_csr", "ring_csr", "ring_cmd";
+ interrupts = <0x0 0x3c 0x4>;
+ clocks = <&menetclk 0>;
+ local-mac-address = [00 01 73 00 00 01];
+ phy-connection-type = "rgmii";
+ phy-handle = <&menetphy>;
+ mdio {
+ compatible = "apm,xgene-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ menetphy: menetphy@3 {
+ compatible = "ethernet-phy-id001c.c915";
+ reg = <0x3>;
+ };
+
+ };
+ };
+
+/* Board-specific peripheral configurations */
+&menet {
+ status = "ok";
+};
diff --git a/Documentation/devicetree/bindings/net/broadcom-systemport.txt b/Documentation/devicetree/bindings/net/broadcom-systemport.txt
index c183ea90d9bc..aa7ad622259d 100644
--- a/Documentation/devicetree/bindings/net/broadcom-systemport.txt
+++ b/Documentation/devicetree/bindings/net/broadcom-systemport.txt
@@ -4,7 +4,8 @@ Required properties:
- compatible: should be one of "brcm,systemport-v1.00" or "brcm,systemport"
- reg: address and length of the register set for the device.
- interrupts: interrupts for the device, first cell must be for the the rx
- interrupts, and the second cell should be for the transmit queues
+ interrupts, and the second cell should be for the transmit queues. An
+ optional third interrupt cell for Wake-on-LAN can be specified
- local-mac-address: Ethernet MAC address (48 bits) of this adapter
- phy-mode: Should be a string describing the PHY interface to the
Ethernet switch/PHY, see Documentation/devicetree/bindings/net/ethernet.txt
diff --git a/Documentation/devicetree/bindings/net/davinci-mdio.txt b/Documentation/devicetree/bindings/net/davinci-mdio.txt
index 72efaaf764f7..0369e25aabd2 100644
--- a/Documentation/devicetree/bindings/net/davinci-mdio.txt
+++ b/Documentation/devicetree/bindings/net/davinci-mdio.txt
@@ -1,8 +1,8 @@
-TI SoC Davinci MDIO Controller Device Tree Bindings
+TI SoC Davinci/Keystone2 MDIO Controller Device Tree Bindings
---------------------------------------------------
Required properties:
-- compatible : Should be "ti,davinci_mdio"
+- compatible : Should be "ti,davinci_mdio" or "ti,keystone_mdio"
- reg : physical base address and size of the davinci mdio
registers map
- bus_freq : Mdio Bus frequency
@@ -19,7 +19,7 @@ file.
Examples:
mdio: davinci_mdio@4A101000 {
- compatible = "ti,cpsw";
+ compatible = "ti,davinci_mdio";
reg = <0x4A101000 0x1000>;
bus_freq = <1000000>;
};
@@ -27,7 +27,7 @@ Examples:
(or)
mdio: davinci_mdio@4A101000 {
- compatible = "ti,cpsw";
+ compatible = "ti,davinci_mdio";
ti,hwmods = "davinci_mdio";
bus_freq = <1000000>;
};
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 6bc84adb10c0..8a2c7b55ec16 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -12,7 +12,14 @@ Optional properties:
only if property "phy-reset-gpios" is available. Missing the property
will have the duration be 1 millisecond. Numbers greater than 1000 are
invalid and 1 millisecond will be used instead.
-- phy-supply: regulator that powers the Ethernet PHY.
+- phy-supply : regulator that powers the Ethernet PHY.
+- phy-handle : phandle to the PHY device connected to this device.
+- fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
+ Use instead of phy-handle.
+
+Optional subnodes:
+- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
+ according to phy.txt in the same directory
Example:
@@ -25,3 +32,23 @@ ethernet@83fec000 {
local-mac-address = [00 04 9F 01 1B B9];
phy-supply = <&reg_fec_supply>;
};
+
+Example with phy specified:
+
+ethernet@83fec000 {
+ compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+ reg = <0x83fec000 0x4000>;
+ interrupts = <87>;
+ phy-mode = "mii";
+ phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
+ local-mac-address = [00 04 9F 01 1B B9];
+ phy-supply = <&reg_fec_supply>;
+ phy-handle = <&ethphy>;
+ mdio {
+ ethphy: ethernet-phy@6 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <6>;
+ max-speed = <100>;
+ };
+ };
+};
diff --git a/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt b/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
new file mode 100644
index 000000000000..0071883c08d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
@@ -0,0 +1,29 @@
+*CC2520 IEEE 802.15.4 Compatible Radio*
+
+Required properties:
+ - compatible: should be "ti,cc2520"
+ - spi-max-frequency: maximal bus speed (8000000), should be set to 4000000 depends
+ sync or async operation mode
+ - reg: the chipselect index
+ - pinctrl-0: pin control group to be used for this controller.
+ - pinctrl-names: must contain a "default" entry.
+ - fifo-gpio: GPIO spec for the FIFO pin
+ - fifop-gpio: GPIO spec for the FIFOP pin
+ - sfd-gpio: GPIO spec for the SFD pin
+ - cca-gpio: GPIO spec for the CCA pin
+ - vreg-gpio: GPIO spec for the VREG pin
+ - reset-gpio: GPIO spec for the RESET pin
+Example:
+ cc2520@0 {
+ compatible = "ti,cc2520";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cc2520_cape_pins>;
+ fifo-gpio = <&gpio1 18 0>;
+ fifop-gpio = <&gpio1 19 0>;
+ sfd-gpio = <&gpio1 13 0>;
+ cca-gpio = <&gpio1 16 0>;
+ vreg-gpio = <&gpio0 31 0>;
+ reset-gpio = <&gpio1 12 0>;
+ };
diff --git a/Documentation/devicetree/bindings/net/marvell-pp2.txt b/Documentation/devicetree/bindings/net/marvell-pp2.txt
new file mode 100644
index 000000000000..aa4f4230bfd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/marvell-pp2.txt
@@ -0,0 +1,61 @@
+* Marvell Armada 375 Ethernet Controller (PPv2)
+
+Required properties:
+
+- compatible: should be "marvell,armada-375-pp2"
+- reg: addresses and length of the register sets for the device.
+ Must contain the following register sets:
+ - common controller registers
+ - LMS registers
+ In addition, at least one port register set is required.
+- clocks: a pointer to the reference clocks for this device, consequently:
+ - main controller clock
+ - GOP clock
+- clock-names: names of used clocks, must be "pp_clk" and "gop_clk".
+
+The ethernet ports are represented by subnodes. At least one port is
+required.
+
+Required properties (port):
+
+- interrupts: interrupt for the port
+- port-id: should be '0' or '1' for ethernet ports, and '2' for the
+ loopback port
+- phy-mode: See ethernet.txt file in the same directory
+
+Optional properties (port):
+
+- marvell,loopback: port is loopback mode
+- phy: a phandle to a phy node defining the PHY address (as the reg
+ property, a single integer). Note: if this property isn't present,
+ then fixed link is assumed, and the 'fixed-link' property is
+ mandatory.
+
+Example:
+
+ethernet@f0000 {
+ compatible = "marvell,armada-375-pp2";
+ reg = <0xf0000 0xa000>,
+ <0xc0000 0x3060>,
+ <0xc4000 0x100>,
+ <0xc5000 0x100>;
+ clocks = <&gateclk 3>, <&gateclk 19>;
+ clock-names = "pp_clk", "gop_clk";
+ status = "okay";
+
+ eth0: eth0@c4000 {
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <0>;
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "gmii";
+ };
+
+ eth1: eth1@c5000 {
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <1>;
+ status = "okay";
+ phy = <&phy3>;
+ phy-mode = "gmii";
+ };
+};
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
new file mode 100644
index 000000000000..3b58ae480344
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt
@@ -0,0 +1,33 @@
+* STMicroelectronics SAS. ST21NFCB NFC Controller
+
+Required properties:
+- compatible: Should be "st,st21nfcb_i2c".
+- clock-frequency: I²C work frequency.
+- reg: address on the bus
+- interrupt-parent: phandle for the interrupt gpio controller
+- interrupts: GPIO interrupt to which the chip is connected
+- reset-gpios: Output GPIO pin used to reset the ST21NFCB
+
+Optional SoC Specific Properties:
+- pinctrl-names: Contains only one value - "default".
+- pintctrl-0: Specifies the pin control groups used for this controller.
+
+Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
+
+&i2c2 {
+
+ status = "okay";
+
+ st21nfcb: st21nfcb@8 {
+
+ compatible = "st,st21nfcb_i2c";
+
+ reg = <0x08>;
+ clock-frequency = <400000>;
+
+ interrupt-parent = <&gpio5>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+ reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/net/sh_eth.txt b/Documentation/devicetree/bindings/net/sh_eth.txt
index e7106b50dbdc..34d4db1a4e25 100644
--- a/Documentation/devicetree/bindings/net/sh_eth.txt
+++ b/Documentation/devicetree/bindings/net/sh_eth.txt
@@ -9,6 +9,7 @@ Required properties:
"renesas,ether-r8a7779" if the device is a part of R8A7779 SoC.
"renesas,ether-r8a7790" if the device is a part of R8A7790 SoC.
"renesas,ether-r8a7791" if the device is a part of R8A7791 SoC.
+ "renesas,ether-r8a7794" if the device is a part of R8A7794 SoC.
"renesas,ether-r7s72100" if the device is a part of R7S72100 SoC.
- reg: offset and length of (1) the E-DMAC/feLic register block (required),
(2) the TSU register block (optional).
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index a2acd2b26baf..9b03c57563a4 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -25,6 +25,10 @@ Required properties:
- snps,force_sf_dma_mode Force DMA to use the Store and Forward
mode for both tx and rx. This flag is
ignored if force_thresh_dma_mode is set.
+- snps,multicast-filter-bins: Number of multicast filter hash bins
+ supported by this device instance
+- snps,perfect-filter-entries: Number of perfect filter entries supported
+ by this device instance
Optional properties:
- resets: Should contain a phandle to the STMMAC reset signal, if any
@@ -47,6 +51,8 @@ Examples:
mac-address = [000000000000]; /* Filled in by U-Boot */
max-frame-size = <3800>;
phy-mode = "gmii";
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
clocks = <&clock>;
clock-names = "stmmaceth">;
};
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt
new file mode 100644
index 000000000000..5dbf169cd81c
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt
@@ -0,0 +1,41 @@
+Broadcom BCM43xx Fullmac wireless SDIO devices
+
+This node provides properties for controlling the Broadcom wireless device. The
+node is expected to be specified as a child node to the SDIO controller that
+connects the device to the system.
+
+Required properties:
+
+ - compatible : Should be "brcm,bcm4329-fmac".
+
+Optional properties:
+ - brcm,drive-strength : drive strength used for SDIO pins on device in mA
+ (default = 6).
+ - interrupt-parent : the phandle for the interrupt controller to which the
+ device interrupts are connected.
+ - interrupts : specifies attributes for the out-of-band interrupt (host-wake).
+ When not specified the device will use in-band SDIO interrupts.
+ - interrupt-names : name of the out-of-band interrupt, which must be set
+ to "host-wake".
+
+Example:
+
+mmc3: mmc@01c12000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc3_pins_a>;
+ vmmc-supply = <&reg_vmmc3>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ interrupt-parent = <&pio>;
+ interrupts = <10 8>; /* PH10 / EINT10 */
+ interrupt-names = "host-wake";
+ };
+};
diff --git a/Documentation/devicetree/bindings/panel/auo,b133htn01.txt b/Documentation/devicetree/bindings/panel/auo,b133htn01.txt
new file mode 100644
index 000000000000..302226b5bb55
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/auo,b133htn01.txt
@@ -0,0 +1,7 @@
+AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
+
+Required properties:
+- compatible: should be "auo,b133htn01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt b/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt
new file mode 100644
index 000000000000..b47f9d87bc19
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/foxlink,fl500wvr00-a0t.txt
@@ -0,0 +1,7 @@
+Foxlink Group 5" WVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "foxlink,fl500wvr00-a0t"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/innolux,n116bge.txt b/Documentation/devicetree/bindings/panel/innolux,n116bge.txt
new file mode 100644
index 000000000000..081bb939ed31
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/innolux,n116bge.txt
@@ -0,0 +1,7 @@
+Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,n116bge"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt b/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt
new file mode 100644
index 000000000000..7825844aafdf
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/innolux,n156bge-l21.txt
@@ -0,0 +1,7 @@
+InnoLux 15.6" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,n156bge-l21"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
index c300391e8d3e..0823362548dc 100644
--- a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
@@ -14,9 +14,6 @@ Required properties:
- interrupt-names: Must include the following entries:
"intr": The Tegra interrupt that is asserted for controller interrupts
"msi": The Tegra interrupt that is asserted when an MSI is received
-- pex-clk-supply: Supply voltage for internal reference clock
-- vdd-supply: Power supply for controller (1.05V)
-- avdd-supply: Power supply for controller (1.05V) (not required for Tegra20)
- bus-range: Range of bus numbers associated with this controller
- #address-cells: Address representation for root ports (must be 3)
- cell 0 specifies the bus and device numbers of the root port:
@@ -60,6 +57,33 @@ Required properties:
- afi
- pcie_x
+Power supplies for Tegra20:
+- avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+- vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+- avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
+ supply 1.05 V.
+- avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
+ supply 1.05 V.
+- vddio-pex-clk-supply: Power supply for PCIe clock. Must supply 3.3 V.
+
+Power supplies for Tegra30:
+- Required:
+ - avdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
+ supply 1.05 V.
+ - avdd-plle-supply: Power supply for PLLE, which is shared with SATA. Must
+ supply 1.05 V.
+ - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must
+ supply 1.8 V.
+ - hvdd-pex-supply: High-voltage supply for PCIe I/O and PCIe output clocks.
+ Must supply 3.3 V.
+- Optional:
+ - If lanes 0 to 3 are used:
+ - avdd-pexa-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+ - vdd-pexa-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+ - If lanes 4 or 5 are used:
+ - avdd-pexb-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
+ - vdd-pexb-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+
Root ports are defined as subnodes of the PCIe controller node.
Required properties:
diff --git a/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt b/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt
new file mode 100644
index 000000000000..49ea76da7718
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/spear13xx-pcie.txt
@@ -0,0 +1,14 @@
+SPEAr13XX PCIe DT detail:
+================================
+
+SPEAr13XX uses synopsis designware PCIe controller and ST MiPHY as phy
+controller.
+
+Required properties:
+- compatible : should be "st,spear1340-pcie", "snps,dw-pcie".
+- phys : phandle to phy node associated with pcie controller
+- phy-names : must be "pcie-phy"
+- All other definitions as per generic PCI bindings
+
+ Optional properties:
+- st,pcie-is-gen1 indicates that forced gen1 initialization is needed.
diff --git a/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
new file mode 100644
index 000000000000..88f8c23384c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
@@ -0,0 +1,34 @@
+Berlin SATA PHY
+---------------
+
+Required properties:
+- compatible: should be "marvell,berlin2q-sata-phy"
+- address-cells: should be 1
+- size-cells: should be 0
+- phy-cells: from the generic PHY bindings, must be 1
+- reg: address and length of the register
+- clocks: reference to the clock entry
+
+Sub-nodes:
+Each PHY should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: the PHY number
+
+Example:
+ sata_phy: phy@f7e900a0 {
+ compatible = "marvell,berlin2q-sata-phy";
+ reg = <0xf7e900a0 0x200>;
+ clocks = <&chip CLKID_SATA>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #phy-cells = <1>;
+
+ sata-phy@0 {
+ reg = <0>;
+ };
+
+ sata-phy@1 {
+ reg = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt b/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
new file mode 100644
index 000000000000..296168b74d24
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
@@ -0,0 +1,22 @@
+Hisilicon hix5hd2 SATA PHY
+-----------------------
+
+Required properties:
+- compatible: should be "hisilicon,hix5hd2-sata-phy"
+- reg: offset and length of the PHY registers
+- #phy-cells: must be 0
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Optional Properties:
+- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
+- hisilicon,power-reg: offset and bit number within peripheral-syscon,
+ register of controlling sata power supply.
+
+Example:
+ sata_phy: phy@f9900000 {
+ compatible = "hisilicon,hix5hd2-sata-phy";
+ reg = <0xf9900000 0x10000>;
+ #phy-cells = <0>;
+ hisilicon,peripheral-syscon = <&peripheral_ctrl>;
+ hisilicon,power-reg = <0x8 10>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/phy-bindings.txt b/Documentation/devicetree/bindings/phy/phy-bindings.txt
index 8ae844fc0c60..2aa1840200ed 100644
--- a/Documentation/devicetree/bindings/phy/phy-bindings.txt
+++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt
@@ -10,6 +10,10 @@ Required Properties:
provider can use the values in cells to find the appropriate
PHY.
+Optional Properties:
+phy-supply: Phandle to a regulator that provides power to the PHY. This
+ regulator will be managed during the PHY power on/off sequence.
+
For example:
phys: phy {
diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
new file mode 100644
index 000000000000..42c880886cf7
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
@@ -0,0 +1,76 @@
+STMicroelectronics STi MIPHY365x PHY binding
+============================================
+
+This binding describes a miphy device that is used to control PHY hardware
+for SATA and PCIe.
+
+Required properties (controller (parent) node):
+- compatible : Should be "st,miphy365x-phy"
+- st,syscfg : Should be a phandle of the system configuration register group
+ which contain the SATA, PCIe mode setting bits
+
+Required nodes : A sub-node is required for each channel the controller
+ provides. Address range information including the usual
+ 'reg' and 'reg-names' properties are used inside these
+ nodes to describe the controller's topology. These nodes
+ are translated by the driver's .xlate() function.
+
+Required properties (port (child) node):
+- #phy-cells : Should be 1 (See second example)
+ Cell after port phandle is device type from:
+ - MIPHY_TYPE_SATA
+ - MIPHY_TYPE_PCI
+- reg : Address and length of register sets for each device in
+ "reg-names"
+- reg-names : The names of the register addresses corresponding to the
+ registers filled in "reg":
+ - sata: For SATA devices
+ - pcie: For PCIe devices
+ - syscfg: To specify the syscfg based config register
+
+Optional properties (port (child) node):
+- st,sata-gen : Generation of locally attached SATA IP. Expected values
+ are {1,2,3). If not supplied generation 1 hardware will
+ be expected
+- st,pcie-tx-pol-inv : Bool property to invert the polarity PCIe Tx (Txn/Txp)
+- st,sata-tx-pol-inv : Bool property to invert the polarity SATA Tx (Txn/Txp)
+
+Example:
+
+ miphy365x_phy: miphy365x@fe382000 {
+ compatible = "st,miphy365x-phy";
+ st,syscfg = <&syscfg_rear>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ phy_port0: port@fe382000 {
+ reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>;
+ reg-names = "sata", "pcie", "syscfg";
+ #phy-cells = <1>;
+ st,sata-gen = <3>;
+ };
+
+ phy_port1: port@fe38a000 {
+ reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;;
+ reg-names = "sata", "pcie", "syscfg";
+ #phy-cells = <1>;
+ st,pcie-tx-pol-inv;
+ };
+ };
+
+Specifying phy control of devices
+=================================
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type.
+
+Example:
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+ sata0: sata@fe380000 {
+ ...
+ phys = <&phy_port0 MIPHY_TYPE_SATA>;
+ ...
+ };
diff --git a/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt b/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
new file mode 100644
index 000000000000..952f6c96bab9
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
@@ -0,0 +1,24 @@
+Qualcomm APQ8064 SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,apq8064-sata-phy".
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+ clock-names.
+- clock-names: must be "cfg" for phy config clock.
+
+Example:
+ sata_phy: sata-phy@1b400000 {
+ compatible = "qcom,apq8064-sata-phy";
+ reg = <0x1b400000 0x200>;
+
+ clocks = <&gcc SATA_PHY_CFG_CLK>;
+ clock-names = "cfg";
+
+ #phy-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt b/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
new file mode 100644
index 000000000000..76bfbd056202
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
@@ -0,0 +1,23 @@
+Qualcomm IPQ806x SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,ipq806x-sata-phy"
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: must be exactly one entry
+- clock-names: must be "cfg"
+
+Example:
+ sata_phy: sata-phy@1b400000 {
+ compatible = "qcom,ipq806x-sata-phy";
+ reg = <0x1b400000 0x200>;
+
+ clocks = <&gcc SATA_PHY_CFG_CLK>;
+ clock-names = "cfg";
+
+ #phy-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 2049261d8c31..7a6feea2a48b 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -26,9 +26,11 @@ Samsung S5P/EXYNOS SoC series USB PHY
Required properties:
- compatible : should be one of the listed compatibles:
+ - "samsung,exynos3250-usb2-phy"
- "samsung,exynos4210-usb2-phy"
- "samsung,exynos4x12-usb2-phy"
- "samsung,exynos5250-usb2-phy"
+ - "samsung,s5pv210-usb2-phy"
- reg : a list of registers used by phy driver
- first and obligatory is the location of phy modules registers
- samsung,sysreg-phandle - handle to syscon used to control the system registers
@@ -46,6 +48,7 @@ and Exynos 4212) it is as follows:
1 - USB host ("host"),
2 - HSIC0 ("hsic0"),
3 - HSIC1 ("hsic1"),
+Exynos3250 has only USB device phy available as phy 0.
Exynos 4210 and Exynos 4212 use mode switching and require that mode switch
register is supplied.
diff --git a/Documentation/devicetree/bindings/phy/st-spear-miphy.txt b/Documentation/devicetree/bindings/phy/st-spear-miphy.txt
new file mode 100644
index 000000000000..2a6bfdcc09b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/st-spear-miphy.txt
@@ -0,0 +1,15 @@
+ST SPEAr miphy DT details
+=========================
+
+ST Microelectronics SPEAr miphy is a phy controller supporting PCIe and SATA.
+
+Required properties:
+- compatible : should be "st,spear1310-miphy" or "st,spear1340-miphy"
+- reg : offset and length of the PHY register set.
+- misc: phandle for the syscon node to access misc registers
+- #phy-cells : from the generic PHY bindings, must be 1.
+ - cell[1]: 0 if phy used for SATA, 1 for PCIe.
+
+Optional properties:
+- phy-id: Instance id of the phy. Only required when there are multiple phys
+ present on a implementation.
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 9ce458f32945..305e3df3d9b1 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -9,15 +9,17 @@ Required properties:
e.g. USB2_PHY on OMAP5.
"ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
e.g. USB3 PHY and SATA PHY on OMAP5.
+ "ti,control-phy-pcie" - for pcie to support external clock for pcie and to
+ set PCS delay value.
+ e.g. PCIE PHY in DRA7x
"ti,control-phy-usb2-dra7" - if it has power down register like USB2 PHY on
DRA7 platform.
"ti,control-phy-usb2-am437" - if it has power down register like USB2 PHY on
AM437 platform.
- - reg : Address and length of the register set for the device. It contains
- the address of "otghs_control" for control-phy-otghs or "power" register
- for other types.
- - reg-names: should be "otghs_control" control-phy-otghs and "power" for
- other types.
+ - reg : register ranges as listed in the reg-names property
+ - reg-names: "otghs_control" for control-phy-otghs
+ "power", "pcie_pcs" and "control_sma" for control-phy-pcie
+ "power" for all other types
omap_control_usb: omap-control-usb@4a002300 {
compatible = "ti,control-phy-otghs";
@@ -56,8 +58,8 @@ usb2phy@4a0ad080 {
TI PIPE3 PHY
Required properties:
- - compatible: Should be "ti,phy-usb3" or "ti,phy-pipe3-sata".
- "ti,omap-usb3" is deprecated.
+ - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
+ "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
- reg : Address and length of the register set for the device.
- reg-names: The names of the register addresses corresponding to the registers
filled in "reg".
@@ -69,10 +71,17 @@ Required properties:
* "wkupclk" - wakeup clock.
* "sysclk" - system clock.
* "refclk" - reference clock.
+ * "dpll_ref" - external dpll ref clk
+ * "dpll_ref_m2" - external dpll ref clk
+ * "phy-div" - divider for apll
+ * "div-clk" - apll clock
Optional properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
the PHY.
+ - id: If there are multiple instance of the same type, in order to
+ differentiate between each instance "id" can be used (e.g., multi-lane PCIe
+ PHY). If "id" is not provided, it is set to default value of '1'.
This is usually a subnode of ocp2scp to which it is connected.
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index d8d065608ec0..93ce12eb422a 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -13,6 +13,8 @@ Required properties:
"allwinner,sun6i-a31-pinctrl"
"allwinner,sun6i-a31-r-pinctrl"
"allwinner,sun7i-a20-pinctrl"
+ "allwinner,sun8i-a23-pinctrl"
+ "allwinner,sun8i-a23-r-pinctrl"
- reg: Should contain the register physical address and length for the
pin controller.
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
new file mode 100644
index 000000000000..2f9c0bd66457
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
@@ -0,0 +1,127 @@
+Device tree binding for NVIDIA Tegra XUSB pad controller
+========================================================
+
+The Tegra XUSB pad controller manages a set of lanes, each of which can be
+assigned to one out of a set of different pads. Some of these pads have an
+associated PHY that must be powered up before the pad can be used.
+
+This document defines the device-specific binding for the XUSB pad controller.
+
+Refer to pinctrl-bindings.txt in this directory for generic information about
+pin controller device tree bindings and ../phy/phy-bindings.txt for details on
+how to describe and reference PHYs in device trees.
+
+Required properties:
+--------------------
+- compatible: should be "nvidia,tegra124-xusb-padctl"
+- reg: Physical base address and length of the controller's registers.
+- resets: Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+ - padctl
+- #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
+ See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
+
+Lane muxing:
+------------
+
+Child nodes contain the pinmux configurations following the conventions from
+the pinctrl-bindings.txt document. Typically a single, static configuration is
+given and applied at boot time.
+
+Each subnode describes groups of lanes along with parameters and pads that
+they should be assigned to. The name of these subnodes is not important. All
+subnodes should be parsed solely based on their content.
+
+Each subnode only applies the parameters that are explicitly listed. In other
+words, if a subnode that lists a function but no pin configuration parameters
+implies no information about any pin configuration parameters. Similarly, a
+subnode that describes only an IDDQ parameter implies no information about
+what function the pins are assigned to. For this reason even seemingly boolean
+values are actually tristates in this binding: unspecified, off or on.
+Unspecified is represented as an absent property, and off/on are represented
+as integer values 0 and 1.
+
+Required properties:
+- nvidia,lanes: An array of strings. Each string is the name of a lane.
+
+Optional properties:
+- nvidia,function: A string that is the name of the function (pad) that the
+ pin or group should be assigned to. Valid values for function names are
+ listed below.
+- nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
+
+Note that not all of these properties are valid for all lanes. Lanes can be
+divided into three groups:
+
+ - otg-0, otg-1, otg-2:
+
+ Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
+
+ The nvidia,iddq property does not apply to this group.
+
+ - ulpi-0, hsic-0, hsic-1:
+
+ Valid functions for this group are: "snps", "xusb".
+
+ The nvidia,iddq property does not apply to this group.
+
+ - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
+
+ Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
+
+
+Example:
+========
+
+SoC file extract:
+-----------------
+
+ padctl@0,7009f000 {
+ compatible = "nvidia,tegra124-xusb-padctl";
+ reg = <0x0 0x7009f000 0x0 0x1000>;
+ resets = <&tegra_car 142>;
+ reset-names = "padctl";
+
+ #phy-cells = <1>;
+ };
+
+Board file extract:
+-------------------
+
+ pcie-controller@0,01003000 {
+ ...
+
+ phys = <&padctl 0>;
+ phy-names = "pcie";
+
+ ...
+ };
+
+ ...
+
+ padctl: padctl@0,7009f000 {
+ pinctrl-0 = <&padctl_default>;
+ pinctrl-names = "default";
+
+ padctl_default: pinmux {
+ usb3 {
+ nvidia,lanes = "pcie-0", "pcie-1";
+ nvidia,function = "usb3";
+ nvidia,iddq = <0>;
+ };
+
+ pcie {
+ nvidia,lanes = "pcie-2", "pcie-3",
+ "pcie-4";
+ nvidia,function = "pcie";
+ nvidia,iddq = <0>;
+ };
+
+ sata {
+ nvidia,lanes = "sata-0";
+ nvidia,function = "sata";
+ nvidia,iddq = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
index 7181f925acaa..0211c6d8a522 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
@@ -46,7 +46,7 @@ Valid values for pins are:
gpio0-gpio89
Valid values for function are:
- cam_mclk, codec_mic_i2s, codec_spkr_i2s, gsbi1, gsbi2, gsbi3, gsbi4,
+ cam_mclk, codec_mic_i2s, codec_spkr_i2s, gpio, gsbi1, gsbi2, gsbi3, gsbi4,
gsbi4_cam_i2c, gsbi5, gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6,
gsbi6_spi_cs1, gsbi6_spi_cs2, gsbi6_spi_cs3, gsbi7, gsbi7_spi_cs1,
gsbi7_spi_cs2, gsbi7_spi_cs3, gsbi_cam_i2c, hdmi, mi2s, riva_bt, riva_fm,
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt
index e0d35a40981b..e33e4dcdce79 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt
@@ -51,7 +51,7 @@ Valid values for qcom,pins are:
Valid values for function are:
- mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gsbi1, gsbi2, gsbi4, gsbi5,
+ mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gpio, gsbi1, gsbi2, gsbi4, gsbi5,
gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6, gsbi7, nss_spi, sdc1,
spdif, nand, tsif1, tsif2, usb_fs_n, usb_fs, usb2_hsic, rgmii2, sata,
pcie1_rst, pcie1_prsnt, pcie1_pwren_n, pcie1_pwren, pcie1_pwrflt,
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
new file mode 100644
index 000000000000..93b7de91b9f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
@@ -0,0 +1,181 @@
+Qualcomm MSM8960 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8960 platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be "qcom,msm8960-pinctrl"
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+ Usage: required
+ Value type: <string-array>
+ Definition: List of gpio pins affected by the properties specified in
+ this subnode. Valid pins are:
+ gpio0-gpio151,
+ sdc1_clk,
+ sdc1_cmd,
+ sdc1_data
+ sdc3_clk,
+ sdc3_cmd,
+ sdc3_data
+
+- function:
+ Usage: required
+ Value type: <string>
+ Definition: Specify the alternative function to be configured for the
+ specified pins. Functions are only valid for gpio pins.
+ Valid values are:
+ audio_pcm, bt, cam_mclk0, cam_mclk1, cam_mclk2,
+ codec_mic_i2s, codec_spkr_i2s, ext_gps, fm, gps_blanking,
+ gps_pps_in, gps_pps_out, gp_clk_0a, gp_clk_0b, gp_clk_1a,
+ gp_clk_1b, gp_clk_2a, gp_clk_2b, gp_mn, gp_pdm_0a,
+ gp_pdm_0b, gp_pdm_1a, gp_pdm_1b, gp_pdm_2a, gp_pdm_2b, gpio,
+ gsbi1, gsbi1_spi_cs1_n, gsbi1_spi_cs2a_n, gsbi1_spi_cs2b_n,
+ gsbi1_spi_cs3_n, gsbi2, gsbi2_spi_cs1_n, gsbi2_spi_cs2_n,
+ gsbi2_spi_cs3_n, gsbi3, gsbi4, gsbi4_3d_cam_i2c_l,
+ gsbi4_3d_cam_i2c_r, gsbi5, gsbi5_3d_cam_i2c_l,
+ gsbi5_3d_cam_i2c_r, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10,
+ gsbi11, gsbi11_spi_cs1a_n, gsbi11_spi_cs1b_n,
+ gsbi11_spi_cs2a_n, gsbi11_spi_cs2b_n, gsbi11_spi_cs3_n,
+ gsbi12, hdmi_cec, hdmi_ddc_clock, hdmi_ddc_data,
+ hdmi_hot_plug_detect, hsic, mdp_vsync, mi2s, mic_i2s,
+ pmb_clk, pmb_ext_ctrl, ps_hold, rpm_wdog, sdc2, sdc4, sdc5,
+ slimbus1, slimbus2, spkr_i2s, ssbi1, ssbi2, ssbi_ext_gps,
+ ssbi_pmic2, ssbi_qpa1, ssbi_ts, tsif1, tsif2, ts_eoc,
+ usb_fs1, usb_fs1_oe, usb_fs1_oe_n, usb_fs2, usb_fs2_oe,
+ usb_fs2_oe_n, vfe_camif_timer1_a, vfe_camif_timer1_b,
+ vfe_camif_timer2, vfe_camif_timer3_a, vfe_camif_timer3_b,
+ vfe_camif_timer4_a, vfe_camif_timer4_b, vfe_camif_timer4_c,
+ vfe_camif_timer5_a, vfe_camif_timer5_b, vfe_camif_timer6_a,
+ vfe_camif_timer6_b, vfe_camif_timer6_c, vfe_camif_timer7_a,
+ vfe_camif_timer7_b, vfe_camif_timer7_c, wlan
+
+- bias-disable:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull up.
+
+- output-high:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ high.
+ Not valid for sdc pins.
+
+- output-low:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ low.
+ Not valid for sdc pins.
+
+- drive-strength:
+ Usage: optional
+ Value type: <u32>
+ Definition: Selects the drive strength for the specified pins, in mA.
+ Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+ msmgpio: pinctrl@800000 {
+ compatible = "qcom,msm8960-pinctrl";
+ reg = <0x800000 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <0 16 0x4>;
+
+ gsbi8_uart: gsbi8-uart {
+ mux {
+ pins = "gpio34", "gpio35";
+ function = "gsbi8";
+ };
+
+ tx {
+ pins = "gpio34";
+ drive-strength = <4>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio35";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
index 73262b575dfc..d2ea80dc43eb 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
@@ -70,7 +70,7 @@ Valid values for function are:
cam_mckl0, cam_mclk1, cam_mclk2, cam_mclk3, mdp_vsync, hdmi_cec, hdmi_ddc,
hdmi_hpd, edp_hpd, gp_pdm0, gp_pdm1, gp_pdm2, gp_pdm3, gp0_clk, gp1_clk,
gp_mn, tsif1, tsif2, hsic, grfc, audio_ref_clk, qua_mi2s, pri_mi2s, spkr_mi2s,
- ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus
+ ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus, gpio
(Note that this is not yet the complete list of functions)
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
index 35d2e1f186f0..daef6fad6a5f 100644
--- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
@@ -15,6 +15,7 @@ Required Properties:
- "renesas,pfc-r8a7778": for R8A7778 (R-Mobile M1) compatible pin-controller.
- "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
- "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
+ - "renesas,pfc-r8a7791": for R8A7791 (R-Car M2) compatible pin-controller.
- "renesas,pfc-sh7372": for SH7372 (SH-Mobile AP4) compatible pin-controller.
- "renesas,pfc-sh73a0": for SH73A0 (SH-Mobile AG5) compatible pin-controller.
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
index cefef741a40b..4658b69d4f4d 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -21,6 +21,7 @@ defined as gpio sub-nodes of the pinmux controller.
Required properties for iomux controller:
- compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
"rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
+ "rockchip,rk3288-pinctrl"
- rockchip,grf: phandle referencing a syscon providing the
"general register files"
@@ -36,7 +37,7 @@ Deprecated properties for iomux controller:
Use rockchip,grf and rockchip,pmu described above instead.
Required properties for gpio sub nodes:
- - compatible: "rockchip,gpio-bank", "rockchip,rk3188-gpio-bank0"
+ - compatible: "rockchip,gpio-bank"
- reg: register of the gpio bank (different than the iomux registerset)
- interrupts: base interrupt of the gpio bank in the interrupt controller
- clocks: clock that drives this bank
@@ -50,6 +51,7 @@ Required properties for gpio sub nodes:
bindings/interrupt-controller/interrupts.txt
Deprecated properties for gpio sub nodes:
+ - compatible: "rockchip,rk3188-gpio-bank0"
- reg: second element: separate pull register for rk3188 bank0, use
rockchip,pmu described above instead
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 2b32783ba821..e82aaf492517 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -44,7 +44,11 @@ Required Properties:
- Pin mux/config groups as child nodes: The pin mux (selecting pin function
mode) and pin config (pull up/down, driver strength) settings are represented
as child nodes of the pin-controller node. There should be atleast one
- child node and there is no limit on the count of these child nodes.
+ child node and there is no limit on the count of these child nodes. It is
+ also possible for a child node to consist of several further child nodes
+ to allow grouping multiple pinctrl groups into one. The format of second
+ level child nodes is exactly the same as for first level ones and is
+ described below.
The child node should contain a list of pin(s) on which a particular pin
function selection or pin configuration (or both) have to applied. This
@@ -71,6 +75,7 @@ Required Properties:
"samsung,pins" property of the child node. The following pin configuration
properties are supported.
+ - samsung,pin-val: Initial value of pin output buffer.
- samsung,pin-pud: Pull up/down configuration.
- samsung,pin-drv: Drive strength configuration.
- samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
@@ -249,6 +254,23 @@ Example 1: A pin-controller node with pin groups.
samsung,pin-pud = <3>;
samsung,pin-drv = <0>;
};
+
+ sd4_bus8: sd4-bus-width8 {
+ part-1 {
+ samsung,pins = "gpk0-3", "gpk0-4",
+ "gpk0-5", "gpk0-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <3>;
+ };
+ part-2 {
+ samsung,pins = "gpk1-3", "gpk1-4",
+ "gpk1-5", "gpk1-6";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <4>;
+ samsung,pin-drv = <3>;
+ };
+ };
};
Example 2: A pin-controller node with external wakeup interrupt controller node.
diff --git a/Documentation/devicetree/bindings/power/rx51-battery.txt b/Documentation/devicetree/bindings/power/rx51-battery.txt
new file mode 100644
index 000000000000..90438453db58
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rx51-battery.txt
@@ -0,0 +1,25 @@
+Binding for Nokia N900 battery
+
+The Nokia N900 battery status can be read via the TWL4030's A/D converter.
+
+Required properties:
+- compatible: Should contain one of the following:
+ * "nokia,n900-battery"
+- io-channels: Should contain IIO channel specifiers
+ for each element in io-channel-names.
+- io-channel-names: Should contain the following values:
+ * "temp" - The ADC channel for temperature reading
+ * "bsi" - The ADC channel for battery size identification
+ * "vbat" - The ADC channel to measure the battery voltage
+
+Example from Nokia N900:
+
+battery: n900-battery {
+ compatible = "nokia,n900-battery";
+ io-channels = <&twl4030_madc 0>,
+ <&twl4030_madc 4>,
+ <&twl4030_madc 12>;
+ io-channel-names = "temp",
+ "bsi",
+ "vbat";
+};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/board.txt b/Documentation/devicetree/bindings/powerpc/fsl/board.txt
index 700dec4774fa..cff38bdbc0e4 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/board.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/board.txt
@@ -84,3 +84,19 @@ Example:
compatible = "fsl,bsc9132qds-fpga", "fsl,fpga-qixis-i2c";
reg = <0x66>;
};
+
+* Freescale on-board CPLD
+
+Some Freescale boards like T1040RDB have an on board CPLD connected.
+
+Required properties:
+- compatible: Should be a board-specific string like "fsl,<board>-cpld"
+ Example:
+ "fsl,t1040rdb-cpld", "fsl,t1042rdb-cpld", "fsl,t1042rdb_pi-cpld"
+- reg: should describe CPLD registers
+
+Example:
+ cpld@3,0 {
+ compatible = "fsl,t1040rdb-cpld";
+ reg = <3 0 0x300>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
new file mode 100644
index 000000000000..d47d15a6a298
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
@@ -0,0 +1,20 @@
+Rockchip PWM controller
+
+Required properties:
+ - compatible: should be "rockchip,<name>-pwm"
+ "rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
+ "rockchip,rk3288-pwm": found on RK3288 SoC
+ "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
+ - reg: physical base address and length of the controller's registers
+ - clocks: phandle and clock specifier of the PWM reference clock
+ - #pwm-cells: should be 2. See pwm.txt in this directory for a
+ description of the cell format.
+
+Example:
+
+ pwm0: pwm@20030000 {
+ compatible = "rockchip,rk2928-pwm";
+ reg = <0x20030000 0x10>;
+ clocks = <&cru PCLK_PWM01>;
+ #pwm-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-st.txt b/Documentation/devicetree/bindings/pwm/pwm-st.txt
new file mode 100644
index 000000000000..84d2fb807d3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-st.txt
@@ -0,0 +1,41 @@
+STMicroelectronics PWM driver bindings
+--------------------------------------
+
+Required parameters:
+- compatible : "st,pwm"
+- #pwm-cells : Number of cells used to specify a PWM. First cell
+ specifies the per-chip index of the PWM to use and the
+ second cell is the period in nanoseconds - fixed to 2
+ for STiH41x.
+- reg : Physical base address and length of the controller's
+ registers.
+- pinctrl-names: Set to "default".
+- pinctrl-0: List of phandles pointing to pin configuration nodes
+ for PWM module.
+ For Pinctrl properties, please refer to [1].
+- clock-names: Set to "pwm".
+- clocks: phandle of the clock used by the PWM module.
+ For Clk properties, please refer to [2].
+
+Optional properties:
+- st,pwm-num-chan: Number of available channels. If not passed, the driver
+ will consider single channel by default.
+
+[1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Example:
+
+pwm1: pwm@fe510000 {
+ compatible = "st,pwm";
+ reg = <0xfe510000 0x68>;
+ #pwm-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1_chan0_default
+ &pinctrl_pwm1_chan1_default
+ &pinctrl_pwm1_chan2_default
+ &pinctrl_pwm1_chan3_default>;
+ clocks = <&clk_sysin>;
+ clock-names = "pwm";
+ st,pwm-num-chan = <4>;
+};
diff --git a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
index bef1fbb647ca..865614b34d6f 100644
--- a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt
@@ -1,13 +1,16 @@
-ACT8865 regulator
+ACT88xx regulators
-------------------
Required properties:
-- compatible: "active-semi,act8865"
+- compatible: "active-semi,act8846" or "active-semi,act8865"
- reg: I2C slave address
Any standard regulator properties can be used to configure the single regulator.
The valid names for regulators are:
+ - for act8846:
+ REG1, REG2, REG3, REG4, REG5, REG6, REG7, REG8, REG9, REG10, REG11, REG12
+ - for act8865:
DCDC_REG1, DCDC_REG2, DCDC_REG3, LDO_REG1, LDO_REG2, LDO_REG3, LDO_REG4.
Example:
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
index 42e6b6bc48ff..725393c8a7f2 100644
--- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -7,6 +7,7 @@ Required properties:
ti,twl6037-pmic
ti,tps65913-pmic
ti,tps65914-pmic
+ ti,tps65917-pmic
and also the generic series names
ti,palmas-pmic
- interrupt-parent : The parent interrupt controller which is palmas.
diff --git a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
index d290988ed975..20191315e444 100644
--- a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt
@@ -86,7 +86,7 @@ as per the datasheet of s5m8767.
- LDOn
- valid values for n are 1 to 28
- - Example: LDO1, LD02, LDO28
+ - Example: LDO1, LDO2, LDO28
- BUCKn
- valid values for n are 1 to 9.
- Example: BUCK1, BUCK2, BUCK9
diff --git a/Documentation/devicetree/bindings/regulator/tps65218.txt b/Documentation/devicetree/bindings/regulator/tps65218.txt
new file mode 100644
index 000000000000..fccc1d24af58
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/tps65218.txt
@@ -0,0 +1,23 @@
+TPS65218 family of regulators
+
+Required properties:
+For tps65218 regulators/LDOs
+- compatible:
+ - "ti,tps65218-dcdc1" for DCDC1
+ - "ti,tps65218-dcdc2" for DCDC2
+ - "ti,tps65218-dcdc3" for DCDC3
+ - "ti,tps65218-dcdc4" for DCDC4
+ - "ti,tps65218-dcdc5" for DCDC5
+ - "ti,tps65218-dcdc6" for DCDC6
+ - "ti,tps65218-ldo1" for LDO1
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+ xyz: regulator@0 {
+ compatible = "ti,tps65218-dcdc1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/cdns,uart.txt b/Documentation/devicetree/bindings/serial/cdns,uart.txt
new file mode 100644
index 000000000000..a3eb154c32ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/cdns,uart.txt
@@ -0,0 +1,20 @@
+Binding for Cadence UART Controller
+
+Required properties:
+- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- reg: Should contain UART controller registers location and length.
+- interrupts: Should contain UART controller interrupts.
+- clocks: Must contain phandles to the UART clocks
+ See ../clocks/clock-bindings.txt for details.
+- clock-names: Tuple to identify input clocks, must contain "uart_clk" and "pclk"
+ See ../clocks/clock-bindings.txt for details.
+
+
+Example:
+ uart@e0000000 {
+ compatible = "cdns,uart-r1p8";
+ clocks = <&clkc 23>, <&clkc 40>;
+ clock-names = "uart_clk", "pclk";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <0 27 4>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/efm32-uart.txt b/Documentation/devicetree/bindings/serial/efm32-uart.txt
index 3ca01336b837..8adbab268ca3 100644
--- a/Documentation/devicetree/bindings/serial/efm32-uart.txt
+++ b/Documentation/devicetree/bindings/serial/efm32-uart.txt
@@ -6,7 +6,7 @@ Required properties:
- interrupts : Should contain uart interrupt
Optional properties:
-- efm32,location : Decides the location of the USART I/O pins.
+- energymicro,location : Decides the location of the USART I/O pins.
Allowed range : [0 .. 5]
Default: 0
@@ -16,5 +16,5 @@ uart@0x4000c400 {
compatible = "energymicro,efm32-uart";
reg = <0x4000c400 0x400>;
interrupts = <15>;
- efm32,location = <0>;
+ energymicro,location = <0>;
};
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
index a1d1205d8185..c95005efbcb8 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt
@@ -1,7 +1,11 @@
* Freescale low power universal asynchronous receiver/transmitter (lpuart)
Required properties:
-- compatible : Should be "fsl,<soc>-lpuart"
+- compatible :
+ - "fsl,vf610-lpuart" for lpuart compatible with the one integrated
+ on Vybrid vf610 SoC with 8-bit register organization
+ - "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
+ on LS1021A SoC with 32-bit big-endian register organization
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.txt b/Documentation/devicetree/bindings/serial/samsung_uart.txt
index 2c8a17cf5cb5..e85f37ec33f0 100644
--- a/Documentation/devicetree/bindings/serial/samsung_uart.txt
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.txt
@@ -1,14 +1,58 @@
* Samsung's UART Controller
-The Samsung's UART controller is used for interfacing SoC with serial communicaion
-devices.
+The Samsung's UART controller is used for interfacing SoC with serial
+communicaion devices.
Required properties:
-- compatible: should be
- - "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
+- compatible: should be one of following:
+ - "samsung,exynos4210-uart" - Exynos4210 SoC,
+ - "samsung,s3c2410-uart" - compatible with ports present on S3C2410 SoC,
+ - "samsung,s3c2412-uart" - compatible with ports present on S3C2412 SoC,
+ - "samsung,s3c2440-uart" - compatible with ports present on S3C2440 SoC,
+ - "samsung,s3c6400-uart" - compatible with ports present on S3C6400 SoC,
+ - "samsung,s5pv210-uart" - compatible with ports present on S5PV210 SoC.
- reg: base physical address of the controller and length of memory mapped
region.
-- interrupts: interrupt number to the cpu. The interrupt specifier format depends
- on the interrupt controller parent.
+- interrupts: a single interrupt signal to SoC interrupt controller,
+ according to interrupt bindings documentation [1].
+
+- clock-names: input names of clocks used by the controller:
+ - "uart" - controller bus clock,
+ - "clk_uart_baudN" - Nth baud base clock input (N = 0, 1, ...),
+ according to SoC User's Manual (only N = 0 is allowedfor SoCs without
+ internal baud clock mux).
+- clocks: phandles and specifiers for all clocks specified in "clock-names"
+ property, in the same order, according to clock bindings documentation [2].
+
+[1] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional properties:
+- samsung,uart-fifosize: The fifo size supported by the UART channel
+
+Note: Each Samsung UART should have an alias correctly numbered in the
+"aliases" node, according to serialN format, where N is the port number
+(non-negative decimal integer) as specified by User's Manual of respective
+SoC.
+
+Example:
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ };
+
+Example:
+ uart1: serial@7f005400 {
+ compatible = "samsung,s3c6400-uart";
+ reg = <0x7f005400 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <6>;
+ clock-names = "uart", "clk_uart_baud2",
+ "clk_uart_baud3";
+ clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+ <&clocks SCLK_UART>;
+ samsung,uart-fifosize = <16>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
index f13f1c5be91c..7f76214f728a 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
@@ -4,9 +4,18 @@ Required properties:
- compatible : "snps,dw-apb-uart"
- reg : offset and length of the register set for the device.
- interrupts : should contain uart interrupt.
+
+Clock handling:
+The clock rate of the input clock needs to be supplied by one of
- clock-frequency : the input clock frequency for the UART.
+- clocks : phandle to the input clock
+
+The supplying peripheral clock can also be handled, needing a second property
+- clock-names: tuple listing input clock names.
+ Required elements: "baudclk", "apb_pclk"
Optional properties:
+- resets : phandle to the parent reset controller.
- reg-shift : quantity to shift the register offsets by. If this property is
not present then the register offsets are not shifted.
- reg-io-width : the size (in bytes) of the IO accesses that should be
@@ -23,3 +32,26 @@ Example:
reg-shift = <2>;
reg-io-width = <4>;
};
+
+Example with one clock:
+
+ uart@80230000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x80230000 0x100>;
+ clocks = <&baudclk>;
+ interrupts = <10>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+Example with two clocks:
+
+ uart@80230000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x80230000 0x100>;
+ clocks = <&baudclk>, <&apb_pclk>;
+ clock-names = "baudclk", "apb_pclk";
+ interrupts = <10>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/ak5386.txt b/Documentation/devicetree/bindings/sound/ak5386.txt
index dc3914fe6ce8..ec3df3abba0c 100644
--- a/Documentation/devicetree/bindings/sound/ak5386.txt
+++ b/Documentation/devicetree/bindings/sound/ak5386.txt
@@ -10,10 +10,14 @@ Optional properties:
- reset-gpio : a GPIO spec for the reset/power down pin.
If specified, it will be deasserted at probe time.
+ - va-supply : a regulator spec, providing 5.0V
+ - vd-supply : a regulator spec, providing 3.3V
Example:
spdif: ak5386@0 {
compatible = "asahi-kasei,ak5386";
reset-gpio = <&gpio0 23>;
+ va-supply = <&vdd_5v0_reg>;
+ vd-supply = <&vdd_3v3_reg>;
};
diff --git a/Documentation/devicetree/bindings/sound/cs4265.txt b/Documentation/devicetree/bindings/sound/cs4265.txt
new file mode 100644
index 000000000000..380fff8e4e83
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs4265.txt
@@ -0,0 +1,29 @@
+CS4265 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+ - compatible : "cirrus,cs4265"
+
+ - reg : the I2C address of the device for I2C. The I2C address depends on
+ the state of the AD0 pin. If AD0 is high, the i2c address is 0x4f.
+ If it is low, the i2c address is 0x4e.
+
+Optional properties:
+
+ - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+ deasserted before communication to the codec starts.
+
+Examples:
+
+codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
+ compatible = "cirrus,cs4265";
+ reg = <0x4f>;
+};
+
+
+codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
+ compatible = "cirrus,cs4265";
+ reg = <0x4e>;
+};
diff --git a/Documentation/devicetree/bindings/sound/fsl,asrc.txt b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
new file mode 100644
index 000000000000..b93362a570be
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,asrc.txt
@@ -0,0 +1,60 @@
+Freescale Asynchronous Sample Rate Converter (ASRC) Controller
+
+The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
+signal associated with an input clock into a signal associated with a different
+output clock. The driver currently works as a Front End of DPCM with other Back
+Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
+three substreams within totally 10 channels.
+
+Required properties:
+
+ - compatible : Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
+
+ - reg : Offset and length of the register set for the device.
+
+ - interrupts : Contains the spdif interrupt.
+
+ - dmas : Generic dma devicetree binding as described in
+ Documentation/devicetree/bindings/dma/dma.txt.
+
+ - dma-names : Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
+
+ - clocks : Contains an entry for each entry in clock-names.
+
+ - clock-names : Contains the following entries
+ "mem" Peripheral access clock to access registers.
+ "ipg" Peripheral clock to driver module.
+ "asrck_<0-f>" Clock sources for input and output clock.
+
+ - big-endian : If this property is absent, the little endian mode
+ will be in use as default. Otherwise, the big endian
+ mode will be in use for all the device registers.
+
+ - fsl,asrc-rate : Defines a mutual sample rate used by DPCM Back Ends.
+
+ - fsl,asrc-width : Defines a mutual sample width used by DPCM Back Ends.
+
+Example:
+
+asrc: asrc@02034000 {
+ compatible = "fsl,imx53-asrc";
+ reg = <0x02034000 0x4000>;
+ interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks 107>, <&clks 107>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks 107>, <&clks 0>, <&clks 0>;
+ clock-names = "mem", "ipg", "asrck0",
+ "asrck_1", "asrck_2", "asrck_3", "asrck_4",
+ "asrck_5", "asrck_6", "asrck_7", "asrck_8",
+ "asrck_9", "asrck_a", "asrck_b", "asrck_c",
+ "asrck_d", "asrck_e", "asrck_f";
+ dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+ <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+ dma-names = "rxa", "rxb", "rxc",
+ "txa", "txb", "txc";
+ fsl,asrc-rate = <48000>;
+ fsl,asrc-width = <16>;
+ status = "okay";
+};
diff --git a/Documentation/devicetree/bindings/sound/max98090.txt b/Documentation/devicetree/bindings/sound/max98090.txt
index a5e63fa47dc5..c454e67f54bb 100644
--- a/Documentation/devicetree/bindings/sound/max98090.txt
+++ b/Documentation/devicetree/bindings/sound/max98090.txt
@@ -4,7 +4,7 @@ This device supports I2C only.
Required properties:
-- compatible : "maxim,max98090".
+- compatible : "maxim,max98090" or "maxim,max98091".
- reg : The I2C address of the device.
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index 8346cab046cd..aa697abf337e 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -13,6 +13,9 @@ Required properties:
- rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW.
see below for detail.
+- rcar_sound,dvc : Should contain DVC feature.
+ The number of DVC subnode should be same as HW.
+ see below for detail.
- rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW.
see below for detail.
@@ -21,6 +24,7 @@ SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin
- pio-transfer : use PIO transfer mode
+- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
SRC subnode properties:
no properties at this point
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec541000 0 0x1280>; /* SSI */
+ rcar_sound,dvc {
+ dvc0: dvc@0 { };
+ dvc1: dvc@1 { };
+ };
+
rcar_sound,src {
src0: src@0 { };
src1: src@1 { };
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
new file mode 100644
index 000000000000..6c55fcfe5e1d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt
@@ -0,0 +1,37 @@
+* Rockchip I2S controller
+
+The I2S bus (Inter-IC sound bus) is a serial link for digital
+audio data transfer between devices in the system.
+
+Required properties:
+
+- compatible: should be one of the followings
+ - "rockchip,rk3066-i2s": for rk3066
+ - "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+ - "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: should contain the I2S interrupt.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+ Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "tx" and "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
+- clock-names: should contain followings:
+ - "i2s_hclk": clock for I2S BUS
+ - "i2s_clk" : clock for I2S controller
+
+Example for rk3288 I2S controller:
+
+i2s@ff890000 {
+ compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
+ reg = <0xff890000 0x10000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dmas = <&pdma1 0>, <&pdma1 1>;
+ dma-names = "rx", "tx";
+ clock-names = "i2s_hclk", "i2s_clk";
+ clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+};
diff --git a/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
new file mode 100644
index 000000000000..9148f72319e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
@@ -0,0 +1,35 @@
+Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
+
+Required properties:
+ - compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
+ "samsung,odroidu3-audio" - for Odroid U3 board
+ - samsung,model : the user-visible name of this sound complex
+ - samsung,i2s-controller : the phandle of the I2S controller
+ - samsung,audio-codec : the phandle of the MAX98090 audio codec
+ - samsung,audio-routing : a list of the connections between audio
+ components; each entry is a pair of strings, the first being the
+ connection's sink, the second being the connection's source;
+ valid names for sources and sinks are the MAX98090's pins (as
+ documented in its binding), and the jacks on the board
+ For Odroid X2:
+ * Headphone Jack
+ * Mic Jack
+ * DMIC
+
+ For Odroid U3:
+ * Headphone Jack
+ * Speakers
+
+Example:
+
+sound {
+ compatible = "samsung,odroidu3-audio";
+ samsung,i2s-controller = <&i2s0>;
+ samsung,audio-codec = <&max98090>;
+ samsung,model = "Odroid-X2";
+ samsung,audio-routing =
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "IN1", "Mic Jack",
+ "Mic Jack", "MICBIAS";
+};
diff --git a/Documentation/devicetree/bindings/sound/sirf-usp.txt b/Documentation/devicetree/bindings/sound/sirf-usp.txt
new file mode 100644
index 000000000000..02f85b32d359
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sirf-usp.txt
@@ -0,0 +1,27 @@
+* SiRF SoC USP module
+
+Required properties:
+- compatible: "sirf,prima2-usp-pcm"
+- reg: Base address and size entries:
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+ These strings correspond 1:1 with the ordered pairs in dmas.
+
+ One of the DMA channels will be responsible for transmission (should be
+ named "tx") and one for reception (should be named "rx").
+
+- clocks: USP controller clock source
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+
+Example:
+usp0: usp@b0080000 {
+ compatible = "sirf,prima2-usp-pcm";
+ reg = <0xb0080000 0x10000>;
+ clocks = <&clks 28>;
+ dmas = <&dmac1 1>, <&dmac1 2>;
+ dma-names = "rx", "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usp0_only_utfs_pins_a>;
+};
+
diff --git a/Documentation/devicetree/bindings/sound/snow.txt b/Documentation/devicetree/bindings/sound/snow.txt
index 678b191c37b8..6df74f15687f 100644
--- a/Documentation/devicetree/bindings/sound/snow.txt
+++ b/Documentation/devicetree/bindings/sound/snow.txt
@@ -3,15 +3,20 @@ Audio Binding for Snow boards
Required properties:
- compatible : Can be one of the following,
"google,snow-audio-max98090" or
+ "google,snow-audio-max98091" or
"google,snow-audio-max98095"
- samsung,i2s-controller: The phandle of the Samsung I2S controller
- samsung,audio-codec: The phandle of the audio codec
+Optional:
+- samsung,model: The name of the sound-card
+
Example:
sound {
compatible = "google,snow-audio-max98095";
+ samsung,model = "Snow-I2S-MAX98095";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98095>;
};
diff --git a/Documentation/devicetree/bindings/sound/tas2552.txt b/Documentation/devicetree/bindings/sound/tas2552.txt
new file mode 100644
index 000000000000..55e2a0af5645
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas2552.txt
@@ -0,0 +1,26 @@
+Texas Instruments - tas2552 Codec module
+
+The tas2552 serial control bus communicates through I2C protocols
+
+Required properties:
+ - compatible - One of:
+ "ti,tas2552" - TAS2552
+ - reg - I2C slave address
+ - supply-*: Required supply regulators are:
+ "vbat" battery voltage
+ "iovdd" I/O Voltage
+ "avdd" Analog DAC Voltage
+
+Optional properties:
+ - enable-gpio - gpio pin to enable/disable the device
+
+Example:
+
+tas2552: tas2552@41 {
+ compatible = "ti,tas2552";
+ reg = <0x41>;
+ enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+};
+
+For more product information please see the link below:
+http://www.ti.com/product/TAS2552
diff --git a/Documentation/devicetree/bindings/sound/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
index d2866a0d6a26..234dad296da7 100644
--- a/Documentation/devicetree/bindings/sound/ti,tas5086.txt
+++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
@@ -31,6 +31,9 @@ Optional properties:
Most systems should not set any of these properties.
+ - avdd-supply: Power supply for AVDD, providing 3.3V
+ - dvdd-supply: Power supply for DVDD, providing 3.3V
+
Examples:
i2c_bus {
@@ -39,5 +42,7 @@ Examples:
reg = <0x1b>;
reset-gpio = <&gpio 23 0>;
ti,charge-period = <156000>;
+ avdd-supply = <&vdd_3v3_reg>;
+ dvdd-supply = <&vdd_3v3_reg>;
};
};
diff --git a/Documentation/devicetree/bindings/sound/wm8904.txt b/Documentation/devicetree/bindings/sound/wm8904.txt
new file mode 100644
index 000000000000..e99f4097c83c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wm8904.txt
@@ -0,0 +1,33 @@
+WM8904 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+ - compatible: "wlf,wm8904"
+ - reg: the I2C address of the device.
+ - clock-names: "mclk"
+ - clocks: reference to
+ <Documentation/devicetree/bindings/clock/clock-bindings.txt>
+
+Pins on the device (for linking into audio routes):
+
+ * IN1L
+ * IN1R
+ * IN2L
+ * IN2R
+ * IN3L
+ * IN3R
+ * HPOUTL
+ * HPOUTR
+ * LINEOUTL
+ * LINEOUTR
+ * MICBIAS
+
+Examples:
+
+codec: wm8904@1a {
+ compatible = "wlf,wm8904";
+ reg = <0x1a>;
+ clocks = <&pck0>;
+ clock-names = "mclk";
+};
diff --git a/Documentation/devicetree/bindings/spi/efm32-spi.txt b/Documentation/devicetree/bindings/spi/efm32-spi.txt
index 130cd17e3680..750e29aff9bc 100644
--- a/Documentation/devicetree/bindings/spi/efm32-spi.txt
+++ b/Documentation/devicetree/bindings/spi/efm32-spi.txt
@@ -10,11 +10,12 @@ Required properties:
- cs-gpios: see spi-bus.txt
Recommended properties :
-- efm32,location: Value to write to the ROUTE register's LOCATION bitfield to
- configure the pinmux for the device, see datasheet for values.
- If "efm32,location" property is not provided, keeping what is
- already configured in the hardware, so its either the reset
- default 0 or whatever the bootloader did.
+- energymicro,location: Value to write to the ROUTE register's LOCATION
+ bitfield to configure the pinmux for the device, see
+ datasheet for values.
+ If this property is not provided, keeping what is
+ already configured in the hardware, so its either the
+ reset default 0 or whatever the bootloader did.
Example:
@@ -26,7 +27,7 @@ spi1: spi@0x4000c400 { /* USART1 */
interrupts = <15 16>;
clocks = <&cmu 20>;
cs-gpios = <&gpio 51 1>; // D3
- efm32,location = <1>;
+ energymicro,location = <1>;
status = "ok";
ks8851@0 {
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
index bee6ff204baf..e2c88df2cc15 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz, up to four chip selects, programmable
data path from 4 bits to 32 bits and numerous protocol variants.
Required properties:
-- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1"
+- compatible: Should contain:
+ "qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064.
+ "qcom,spi-qup-v2.1.1" for 8974 and later
+ "qcom,spi-qup-v2.2.1" for 8974 v2 and later.
+
- reg: Should contain base register location and length
- interrupts: Interrupt number used by this controller
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
new file mode 100644
index 000000000000..bd99193e87b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
@@ -0,0 +1,28 @@
+Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
+
+Required properties:
+- compatible : "snps,dw-apb-ssi"
+- reg : The register base for the controller.
+- interrupts : One interrupt, used by the controller.
+- #address-cells : <1>, as required by generic SPI binding.
+- #size-cells : <0>, also as required by generic SPI binding.
+
+Optional properties:
+- cs-gpios : Specifies the gpio pis to be used for chipselects.
+- num-cs : The number of chipselects. If omitted, this will default to 4.
+
+Child nodes as per the generic SPI binding.
+
+Example:
+
+ spi@fff00000 {
+ compatible = "snps,dw-apb-ssi";
+ reg = <0xfff00000 0x1000>;
+ interrupts = <0 154 4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <2>;
+ cs-gpios = <&gpio0 13 0>,
+ <&gpio0 14 0>;
+ };
+
diff --git a/Documentation/devicetree/bindings/spi/spi-davinci.txt b/Documentation/devicetree/bindings/spi/spi-davinci.txt
index 6d0ac8d0ad9b..f80887bca0d6 100644
--- a/Documentation/devicetree/bindings/spi/spi-davinci.txt
+++ b/Documentation/devicetree/bindings/spi/spi-davinci.txt
@@ -8,7 +8,8 @@ Required properties:
- "ti,dm6441-spi" for SPI used similar to that on DM644x SoC family
- "ti,da830-spi" for SPI used similar to that on DA8xx SoC family
- reg: Offset and length of SPI controller register space
-- num-cs: Number of chip selects
+- num-cs: Number of chip selects. This includes internal as well as
+ GPIO chip selects.
- ti,davinci-spi-intr-line: interrupt line used to connect the SPI
IP to the interrupt controller within the SoC. Possible values
are 0 and 1. Manual says one of the two possible interrupt
@@ -17,6 +18,12 @@ Required properties:
- interrupts: interrupt number mapped to CPU.
- clocks: spi clk phandle
+Optional:
+- cs-gpios: gpio chip selects
+ For example to have 3 internal CS and 2 GPIO CS, user could define
+ cs-gpios = <0>, <0>, <0>, <&gpio1 30 0>, <&gpio1 31 0>;
+ where first three are internal CS and last two are GPIO CS.
+
Example of a NOR flash slave device (n25q032) connected to DaVinci
SPI controller device over the SPI bus.
diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
new file mode 100644
index 000000000000..7bab35575817
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
@@ -0,0 +1,37 @@
+* Rockchip SPI Controller
+
+The Rockchip SPI controller is used to interface with various devices such as flash
+and display controllers using the SPI communication interface.
+
+Required Properties:
+
+- compatible: should be one of the following.
+ "rockchip,rk3066-spi" for rk3066.
+ "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
+ "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+ depends on the interrupt controller.
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Shall be "spiclk" for the transfer-clock, and "apb_pclk" for
+ the peripheral clock.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+ Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "tx" and "rx" if present.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+
+Example:
+
+ spi0: spi@ff110000 {
+ compatible = "rockchip,rk3066-spi";
+ reg = <0xff110000 0x1000>;
+ dmas = <&pdma1 11>, <&pdma1 12>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+ clock-names = "spiclk", "apb_pclk";
+ };
diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt
index 86aa061f069f..1e8a8578148f 100644
--- a/Documentation/devicetree/bindings/spi/spi-samsung.txt
+++ b/Documentation/devicetree/bindings/spi/spi-samsung.txt
@@ -8,7 +8,6 @@ Required SoC Specific Properties:
- compatible: should be one of the following.
- samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
- samsung,s3c6410-spi: for s3c6410 platforms
- - samsung,s5p6440-spi: for s5p6440 and s5p6450 platforms
- samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
- samsung,exynos4210-spi: for exynos4 and exynos5 platforms
@@ -18,14 +17,11 @@ Required SoC Specific Properties:
- interrupts: The interrupt number to the cpu. The interrupt specifier format
depends on the interrupt controller.
-[PRELIMINARY: the dma channel allocation will change once there are
-official DMA bindings]
+- dmas : Two or more DMA channel specifiers following the convention outlined
+ in bindings/dma/dma.txt
-- tx-dma-channel: The dma channel specifier for tx operations. The format of
- the dma specifier depends on the dma controller.
-
-- rx-dma-channel: The dma channel specifier for rx operations. The format of
- the dma specifier depends on the dma controller.
+- dma-names: Names for the dma channels. There must be at least one channel
+ named "tx" for transmit and named "rx" for receive.
Required Board Specific Properties:
@@ -42,15 +38,13 @@ Optional Board Specific Properties:
- num-cs: Specifies the number of chip select lines supported. If
not specified, the default number of chip select lines is set to 1.
+- cs-gpios: should specify GPIOs used for chipselects (see spi-bus.txt)
+
SPI Controller specific data in SPI slave nodes:
- The spi slave nodes should provide the following information which is required
by the spi controller.
- - cs-gpio: A gpio specifier that specifies the gpio line used as
- the slave select line by the spi controller. The format of the gpio
- specifier depends on the gpio controller.
-
- samsung,spi-feedback-delay: The sampling phase shift to be applied on the
miso line (to account for any lag in the miso line). The following are the
valid values.
@@ -74,8 +68,11 @@ Example:
compatible = "samsung,exynos4210-spi";
reg = <0x12d20000 0x100>;
interrupts = <0 66 0>;
- tx-dma-channel = <&pdma0 5>;
- rx-dma-channel = <&pdma0 4>;
+ dmas = <&pdma0 5
+ &pdma0 4>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
};
- Board Specific Portion:
@@ -85,6 +82,7 @@ Example:
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_bus>;
+ cs-gpios = <&gpa2 5 0>;
w25q80bw@0 {
#address-cells = <1>;
@@ -94,7 +92,6 @@ Example:
spi-max-frequency = <10000>;
controller-data {
- cs-gpio = <&gpa2 5 1 0 3>;
samsung,spi-feedback-delay = <0>;
};
diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index c94909215c07..ae738f562acc 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -3,6 +3,7 @@
** Required properties:
- compatible : One of the following:
+ "samsung,exynos3250-tmu"
"samsung,exynos4412-tmu"
"samsung,exynos4210-tmu"
"samsung,exynos5250-tmu"
diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
index 28ef498a66e5..0ef00be44b01 100644
--- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
@@ -1,7 +1,13 @@
* Renesas R-Car Thermal
Required properties:
-- compatible : "renesas,rcar-thermal"
+- compatible : "renesas,thermal-<soctype>", "renesas,rcar-thermal"
+ as fallback.
+ Examples with soctypes are:
+ - "renesas,thermal-r8a73a4" (R-Mobile AP6)
+ - "renesas,thermal-r8a7779" (R-Car H1)
+ - "renesas,thermal-r8a7790" (R-Car H2)
+ - "renesas,thermal-r8a7791" (R-Car M2)
- reg : Address range of the thermal registers.
The 1st reg will be recognized as common register
if it has "interrupts".
@@ -12,18 +18,18 @@ Option properties:
Example (non interrupt support):
-thermal@e61f0100 {
- compatible = "renesas,rcar-thermal";
- reg = <0xe61f0100 0x38>;
+thermal@ffc48000 {
+ compatible = "renesas,thermal-r8a7779", "renesas,rcar-thermal";
+ reg = <0xffc48000 0x38>;
};
Example (interrupt support):
thermal@e61f0000 {
- compatible = "renesas,rcar-thermal";
+ compatible = "renesas,thermal-r8a73a4", "renesas,rcar-thermal";
reg = <0xe61f0000 0x14
0xe61f0100 0x38
0xe61f0200 0x38
0xe61f0300 0x38>;
- interrupts = <0 69 4>;
+ interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
};
diff --git a/Documentation/devicetree/bindings/thermal/st-thermal.txt b/Documentation/devicetree/bindings/thermal/st-thermal.txt
new file mode 100644
index 000000000000..3b9251b4a145
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/st-thermal.txt
@@ -0,0 +1,42 @@
+Binding for Thermal Sensor driver for STMicroelectronics STi series of SoCs.
+
+Required parameters:
+-------------------
+
+compatible : st,<SoC>-<module>-thermal; should be one of:
+ "st,stih415-sas-thermal",
+ "st,stih415-mpe-thermal",
+ "st,stih416-sas-thermal"
+ "st,stih416-mpe-thermal"
+ "st,stid127-thermal" or
+ "st,stih407-thermal"
+ according to the SoC type (stih415, stih416, stid127, stih407)
+ and module type (sas or mpe). On stid127 & stih407 there is only
+ one die/module, so there is no module type in the compatible
+ string.
+clock-names : Should be "thermal".
+ See: Documentation/devicetree/bindings/resource-names.txt
+clocks : Phandle of the clock used by the thermal sensor.
+ See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Optional parameters:
+-------------------
+
+reg : For non-sysconf based sensors, this should be the physical base
+ address and length of the sensor's registers.
+interrupts : Standard way to define interrupt number.
+ Interrupt is mandatory to be defined when compatible is
+ "stih416-mpe-thermal".
+ NB: For thermal sensor's for which no interrupt has been
+ defined, a polling delay of 1000ms will be used to read the
+ temperature from device.
+
+Example:
+
+ temp1@fdfe8000 {
+ compatible = "st,stih416-mpe-thermal";
+ reg = <0xfdfe8000 0x10>;
+ clock-names = "thermal";
+ clocks = <&clk_m_mpethsens>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_NONE>;
+ };
diff --git a/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt b/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt
new file mode 100644
index 000000000000..cd55b52548e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/cirrus,clps711x-timer.txt
@@ -0,0 +1,29 @@
+* Cirrus Logic CLPS711X Timer Counter
+
+Required properties:
+- compatible: Shall contain "cirrus,clps711x-timer".
+- reg : Address and length of the register set.
+- interrupts: The interrupt number of the timer.
+- clocks : phandle of timer reference clock.
+
+Note: Each timer should have an alias correctly numbered in "aliases" node.
+
+Example:
+ aliases {
+ timer0 = &timer1;
+ timer1 = &timer2;
+ };
+
+ timer1: timer@80000300 {
+ compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
+ reg = <0x80000300 0x4>;
+ interrupts = <8>;
+ clocks = <&clks 5>;
+ };
+
+ timer2: timer@80000340 {
+ compatible = "cirrus,ep7312-timer", "cirrus,clps711x-timer";
+ reg = <0x80000340 0x4>;
+ interrupts = <9>;
+ clocks = <&clks 6>;
+ };
diff --git a/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt b/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt
new file mode 100644
index 000000000000..7c4408ff4b83
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/mediatek,mtk-timer.txt
@@ -0,0 +1,17 @@
+Mediatek MT6577, MT6572 and MT6589 Timers
+---------------------------------------
+
+Required properties:
+- compatible: Should be "mediatek,mt6577-timer"
+- reg: Should contain location and length for timers register.
+- clocks: Clocks driving the timer hardware. This list should include two
+ clocks. The order is system clock and as second clock the RTC clock.
+
+Examples:
+
+ timer@10008000 {
+ compatible = "mediatek,mt6577-timer";
+ reg = <0x10008000 0x80>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&system_clk>, <&rtc_clk>;
+ };
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
new file mode 100644
index 000000000000..a17418b0ece3
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,47 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
+inputs and programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channel indices represent the hardware
+position of the channel in the CMT and don't match the channel numbers in the
+datasheets.
+
+Required Properties:
+
+ - compatible: must contain one of the following.
+ - "renesas,cmt-32" for the 32-bit CMT
+ (CMT0 on sh7372, sh73a0 and r8a7740)
+ - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+ (CMT[234] on sh7372, sh73a0 and r8a7740)
+ - "renesas,cmt-48" for the 48-bit CMT
+ (CMT1 on sh7372, sh73a0 and r8a7740)
+ - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+ (CMT[01] on r8a73a4, r8a7790 and r8a7791)
+
+ - reg: base address and length of the registers block for the timer module.
+ - interrupts: interrupt-specifier for the timer, one per channel.
+ - clocks: a list of phandle + clock-specifier pairs, one for each entry
+ in clock-names.
+ - clock-names: must contain "fck" for the functional clock.
+
+ - renesas,channels-mask: bitmask of the available channels.
+
+
+Example: R8A7790 (R-Car H2) CMT0 node
+
+ CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
+ them channels 0 and 1 in the documentation.
+
+ cmt0: timer@ffca0000 {
+ compatible = "renesas,cmt-48-gen2";
+ reg = <0 0xffca0000 0 0x1004>;
+ interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+ <0 142 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+ clock-names = "fck";
+
+ renesas,channels-mask = <0x60>;
+ };
diff --git a/Documentation/devicetree/bindings/timer/renesas,mtu2.txt b/Documentation/devicetree/bindings/timer/renesas,mtu2.txt
new file mode 100644
index 000000000000..917453f826bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,mtu2.txt
@@ -0,0 +1,39 @@
+* Renesas R-Car Multi-Function Timer Pulse Unit 2 (MTU2)
+
+The MTU2 is a multi-purpose, multi-channel timer/counter with configurable
+clock inputs and programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. The MTU2 hardware supports five channels indexed from 0 to 4.
+
+Required Properties:
+
+ - compatible: must contain "renesas,mtu2"
+
+ - reg: base address and length of the registers block for the timer module.
+
+ - interrupts: interrupt specifiers for the timer, one for each entry in
+ interrupt-names.
+ - interrupt-names: must contain one entry named "tgi?a" for each enabled
+ channel, where "?" is the channel index expressed as one digit from "0" to
+ "4".
+
+ - clocks: a list of phandle + clock-specifier pairs, one for each entry
+ in clock-names.
+ - clock-names: must contain "fck" for the functional clock.
+
+
+Example: R7S72100 (RZ/A1H) MTU2 node
+
+ mtu2: timer@fcff0000 {
+ compatible = "renesas,mtu2";
+ reg = <0xfcff0000 0x400>;
+ interrupts = <0 139 IRQ_TYPE_LEVEL_HIGH>,
+ <0 146 IRQ_TYPE_LEVEL_HIGH>,
+ <0 150 IRQ_TYPE_LEVEL_HIGH>,
+ <0 154 IRQ_TYPE_LEVEL_HIGH>,
+ <0 159 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tgi0a", "tgi1a", "tgi2a", "tgi3a", "tgi4a";
+ clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
+ clock-names = "fck";
+ };
diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.txt b/Documentation/devicetree/bindings/timer/renesas,tmu.txt
new file mode 100644
index 000000000000..425d0c5f4aee
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,tmu.txt
@@ -0,0 +1,39 @@
+* Renesas R-Car Timer Unit (TMU)
+
+The TMU is a 32-bit timer/counter with configurable clock inputs and
+programmable compare match.
+
+Channels share hardware resources but their counter and compare match value
+are independent. The TMU hardware supports up to three channels.
+
+Required Properties:
+
+ - compatible: must contain "renesas,tmu"
+
+ - reg: base address and length of the registers block for the timer module.
+
+ - interrupts: interrupt-specifier for the timer, one per channel.
+
+ - clocks: a list of phandle + clock-specifier pairs, one for each entry
+ in clock-names.
+ - clock-names: must contain "fck" for the functional clock.
+
+Optional Properties:
+
+ - #renesas,channels: number of channels implemented by the timer, must be 2
+ or 3 (if not specified the value defaults to 3).
+
+
+Example: R8A7779 (R-Car H1) TMU0 node
+
+ tmu0: timer@ffd80000 {
+ compatible = "renesas,tmu";
+ reg = <0xffd80000 0x30>;
+ interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
+ <0 33 IRQ_TYPE_LEVEL_HIGH>,
+ <0 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
+ clock-names = "fck";
+
+ #renesas,channels = <3>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
index a6a32cb7f777..1bae71e9ad47 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-imx.txt
@@ -4,6 +4,7 @@ Required properties:
- compatible: Should be "fsl,imx27-usb"
- reg: Should contain registers location and length
- interrupts: Should contain controller interrupt
+- fsl,usbphy: phandle of usb phy that connects to the port
Recommended properies:
- phy_type: the type of the phy connected to the core. Should be one
@@ -12,7 +13,6 @@ Recommended properies:
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
Optional properties:
-- fsl,usbphy: phandler of usb phy that connects to the only one port
- fsl,usbmisc: phandler of non-core register device, with one argument
that indicate usb controller index
- vbus-supply: regulator for vbus
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
index ba797d3e6326..c9205fbf26e2 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
@@ -20,6 +20,12 @@ Required properties :
Present if phy_type == utmi.
- ulpi-link: The clock Tegra provides to the ULPI PHY (cdev2).
Present if phy_type == ulpi, and ULPI link mode is in use.
+ - resets : Must contain an entry for each entry in reset-names.
+ See ../reset/reset.txt for details.
+ - reset-names : Must include the following entries:
+ - usb: The PHY's own reset signal.
+ - utmi-pads: The reset of the PHY containing the chip-wide UTMI pad control
+ registers. Required even if phy_type == ulpi.
Required properties for phy_type == ulpi:
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
@@ -56,6 +62,8 @@ Optional properties:
host means this is a host controller
peripheral means it is device controller
otg means it can operate as either ("on the go")
+ - nvidia,has-utmi-pad-registers : boolean indicates whether this controller
+ contains the UTMI pad control registers common to all USB controllers.
VBUS control (required for dr_mode == otg, optional for dr_mode == host):
- vbus-supply: regulator for VBUS
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 5a79377c6a96..86f67f0886bc 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -9,8 +9,9 @@ Required properties:
register set for the device.
- interrupts: one XHCI interrupt should be described here.
-Optional property:
+Optional properties:
- clocks: reference to a clock
+ - usb3-lpm-capable: determines if platform is USB3 LPM capable
Example:
usb@f0931000 {
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 46a311e728a8..ac7269f90764 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -6,6 +6,7 @@ using them to avoid name-space collisions.
abilis Abilis Systems
active-semi Active-Semi International Inc
ad Avionic Design GmbH
+adapteva Adapteva, Inc.
adi Analog Devices, Inc.
aeroflexgaisler Aeroflex Gaisler AB
ak Asahi Kasei Corp.
@@ -42,6 +43,7 @@ dmo Data Modul AG
ebv EBV Elektronik
edt Emerging Display Technologies
emmicro EM Microelectronic
+epcos EPCOS AG
epfl Ecole Polytechnique Fédérale de Lausanne
epson Seiko Epson Corp.
est ESTeem Wireless Modems
@@ -71,12 +73,14 @@ karo Ka-Ro electronics GmbH
keymile Keymile GmbH
lacie LaCie
lantiq Lantiq Semiconductor
+lenovo Lenovo Group Ltd.
lg LG Corporation
linux Linux-specific binding
lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
+mediatek MediaTek Inc.
micrel Micrel Inc.
microchip Microchip Technology Inc.
mosaixtech Mosaix Technologies, Inc.
@@ -99,6 +103,7 @@ panasonic Panasonic Corporation
phytec PHYTEC Messtechnik GmbH
picochip Picochip Ltd
plathome Plat'Home Co., Ltd.
+pixcir PIXCIR MICROELECTRONICS Co., Ltd
powervr PowerVR (deprecated, use img)
qca Qualcomm Atheros, Inc.
qcom Qualcomm Technologies, Inc
@@ -122,6 +127,7 @@ sii Seiko Instruments, Inc.
sirf SiRF Technology, Inc.
smsc Standard Microsystems Corporation
snps Synopsys, Inc.
+solidrun SolidRun
spansion Spansion Inc.
st STMicroelectronics
ste ST-Ericsson
diff --git a/Documentation/devicetree/bindings/video/arm,pl11x.txt b/Documentation/devicetree/bindings/video/arm,pl11x.txt
new file mode 100644
index 000000000000..3e3039a8a253
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/arm,pl11x.txt
@@ -0,0 +1,109 @@
+* ARM PrimeCell Color LCD Controller PL110/PL111
+
+See also Documentation/devicetree/bindings/arm/primecell.txt
+
+Required properties:
+
+- compatible: must be one of:
+ "arm,pl110", "arm,primecell"
+ "arm,pl111", "arm,primecell"
+
+- reg: base address and size of the control registers block
+
+- interrupt-names: either the single entry "combined" representing a
+ combined interrupt output (CLCDINTR), or the four entries
+ "mbe", "vcomp", "lnbu", "fuf" representing the individual
+ CLCDMBEINTR, CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR interrupts
+
+- interrupts: contains an interrupt specifier for each entry in
+ interrupt-names
+
+- clock-names: should contain "clcdclk" and "apb_pclk"
+
+- clocks: contains phandle and clock specifier pairs for the entries
+ in the clock-names property. See
+ Documentation/devicetree/binding/clock/clock-bindings.txt
+
+Optional properties:
+
+- memory-region: phandle to a node describing memory (see
+ Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt)
+ to be used for the framebuffer; if not present, the framebuffer
+ may be located anywhere in the memory
+
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+ cell's memory interface can handle; if not present, the memory
+ interface is fast enough to handle all possible video modes
+
+Required sub-nodes:
+
+- port: describes LCD panel signals, following the common binding
+ for video transmitter interfaces; see
+ Documentation/devicetree/bindings/media/video-interfaces.txt;
+ when it is a TFT panel, the port's endpoint must define the
+ following property:
+
+ - arm,pl11x,tft-r0g0b0-pads: an array of three 32-bit values,
+ defining the way CLD pads are wired up; first value
+ contains index of the "CLD" external pin (pad) used
+ as R0 (first bit of the red component), second value
+ index of the pad used as G0, third value index of the
+ pad used as B0, see also "LCD panel signal multiplexing
+ details" paragraphs in the PL110/PL111 Technical
+ Reference Manuals; this implicitly defines available
+ color modes, for example:
+ - PL111 TFT 4:4:4 panel:
+ arm,pl11x,tft-r0g0b0-pads = <4 15 20>;
+ - PL110 TFT (1:)5:5:5 panel:
+ arm,pl11x,tft-r0g0b0-pads = <1 7 13>;
+ - PL111 TFT (1:)5:5:5 panel:
+ arm,pl11x,tft-r0g0b0-pads = <3 11 19>;
+ - PL111 TFT 5:6:5 panel:
+ arm,pl11x,tft-r0g0b0-pads = <3 10 19>;
+ - PL110 and PL111 TFT 8:8:8 panel:
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+ - PL110 and PL111 TFT 8:8:8 panel, R & B components swapped:
+ arm,pl11x,tft-r0g0b0-pads = <16 8 0>;
+
+
+Example:
+
+ clcd@10020000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0x10020000 0x1000>;
+ interrupt-names = "combined";
+ interrupts = <0 44 4>;
+ clocks = <&oscclk1>, <&oscclk2>;
+ clock-names = "clcdclk", "apb_pclk";
+ max-memory-bandwidth = <94371840>; /* Bps, 1024x768@60 16bpp */
+
+ port {
+ clcd_pads: endpoint {
+ remote-endpoint = <&clcd_panel>;
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+ };
+ };
+
+ };
+
+ panel {
+ compatible = "panel-dpi";
+
+ port {
+ clcd_panel: endpoint {
+ remote-endpoint = <&clcd_pads>;
+ };
+ };
+
+ panel-timing {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ hsync-len = <96>;
+ vactive = <480>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/video/atmel,lcdc.txt b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
index 1ec175eddca8..b75af94a5e52 100644
--- a/Documentation/devicetree/bindings/video/atmel,lcdc.txt
+++ b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
@@ -46,6 +46,7 @@ Required properties (as per of_videomode_helper):
Optional properties (as per of_videomode_helper):
- atmel,lcdcon-backlight: enable backlight
+ - atmel,lcdcon-backlight-inverted: invert backlight PWM polarity
- atmel,lcd-wiring-mode: lcd wiring mode "RGB" or "BRG"
- atmel,power-control-gpio: gpio to power on or off the LCD (as many as needed)
diff --git a/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt b/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt
new file mode 100644
index 000000000000..6fc3c6adeefa
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/cirrus,clps711x-fb.txt
@@ -0,0 +1,47 @@
+* Currus Logic CLPS711X Framebuffer
+
+Required properties:
+- compatible: Shall contain "cirrus,clps711x-fb".
+- reg : Physical base address and length of the controller's registers +
+ location and size of the framebuffer memory.
+- clocks : phandle + clock specifier pair of the FB reference clock.
+- display : phandle to a display node as described in
+ Documentation/devicetree/bindings/video/display-timing.txt.
+ Additionally, the display node has to define properties:
+ - bits-per-pixel: Bits per pixel.
+ - ac-prescale : LCD AC bias frequency. This frequency is the required
+ AC bias frequency for a given manufacturer's LCD plate.
+ - cmap-invert : Invert the color levels (Optional).
+
+Optional properties:
+- lcd-supply: Regulator for LCD supply voltage.
+
+Example:
+ fb: fb@800002c0 {
+ compatible = "cirrus,ep7312-fb", "cirrus,clps711x-fb";
+ reg = <0x800002c0 0xd44>, <0x60000000 0xc000>;
+ clocks = <&clks 2>;
+ lcd-supply = <&reg5v0>;
+ display = <&display>;
+ };
+
+ display: display {
+ model = "320x240x4";
+ native-mode = <&timing0>;
+ bits-per-pixel = <4>;
+ ac-prescale = <17>;
+
+ display-timings {
+ timing0: 320x240 {
+ hactive = <320>;
+ hback-porch = <0>;
+ hfront-porch = <0>;
+ hsync-len = <0>;
+ vactive = <240>;
+ vback-porch = <0>;
+ vfront-porch = <0>;
+ vsync-len = <0>;
+ clock-frequency = <6500000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 33b5730d07ba..31036c667d54 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -1,7 +1,9 @@
Exynos MIPI DSI Master
Required properties:
- - compatible: "samsung,exynos4210-mipi-dsi"
+ - compatible: value should be one of the following
+ "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
+ "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
- reg: physical base address and length of the registers set for the device
- interrupts: should contain DSI interrupt
- clocks: list of clock specifiers, must contain an entry for each required
diff --git a/Documentation/devicetree/bindings/video/exynos_mixer.txt b/Documentation/devicetree/bindings/video/exynos_mixer.txt
index 7bfde9c9d658..08b394b1edbf 100644
--- a/Documentation/devicetree/bindings/video/exynos_mixer.txt
+++ b/Documentation/devicetree/bindings/video/exynos_mixer.txt
@@ -4,8 +4,9 @@ Required properties:
- compatible: value should be one of the following:
1) "samsung,exynos5-mixer" <DEPRECATED>
2) "samsung,exynos4210-mixer"
- 3) "samsung,exynos5250-mixer"
- 4) "samsung,exynos5420-mixer"
+ 3) "samsung,exynos4212-mixer"
+ 4) "samsung,exynos5250-mixer"
+ 5) "samsung,exynos5420-mixer"
- reg: physical base address of the mixer and length of memory mapped
region.
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index 2dad41b689af..ecc899b9817b 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -8,8 +8,6 @@ Required properties:
- compatible: value should be one of the following
"samsung,s3c2443-fimd"; /* for S3C24XX SoCs */
"samsung,s3c6400-fimd"; /* for S3C64XX SoCs */
- "samsung,s5p6440-fimd"; /* for S5P64X0 SoCs */
- "samsung,s5pc100-fimd"; /* for S5PC100 SoC */
"samsung,s5pv210-fimd"; /* for S5PV210 SoC */
"samsung,exynos4210-fimd"; /* for Exynos4 SoCs */
"samsung,exynos5250-fimd"; /* for Exynos5 SoCs */
@@ -44,6 +42,34 @@ Optional Properties:
- display-timings: timing settings for FIMD, as described in document [1].
Can be used in case timings cannot be provided otherwise
or to override timings provided by the panel.
+- samsung,sysreg: handle to syscon used to control the system registers
+- i80-if-timings: timing configuration for lcd i80 interface support.
+ - cs-setup: clock cycles for the active period of address signal is enabled
+ until chip select is enabled.
+ If not specified, the default value(0) will be used.
+ - wr-setup: clock cycles for the active period of CS signal is enabled until
+ write signal is enabled.
+ If not specified, the default value(0) will be used.
+ - wr-active: clock cycles for the active period of CS is enabled.
+ If not specified, the default value(1) will be used.
+ - wr-hold: clock cycles for the active period of CS is disabled until write
+ signal is disabled.
+ If not specified, the default value(0) will be used.
+
+ The parameters are defined as:
+
+ VCLK(internal) __|??????|_____|??????|_____|??????|_____|??????|_____|??
+ : : : : :
+ Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
+ | cs-setup+1 | : : :
+ |<---------->| : : :
+ Chip Select ???????????????|____________:____________:____________|??
+ | wr-setup+1 | | wr-hold+1 |
+ |<---------->| |<---------->|
+ Write Enable ????????????????????????????|____________|???????????????
+ | wr-active+1|
+ |<---------->|
+ Video Data ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
The device node can contain 'port' child nodes according to the bindings defined
in [2]. The following are properties specific to those nodes:
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
index 2144af1a5264..e52ba2da868c 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
@@ -5,10 +5,15 @@ Required properties:
- reg : Should contain WDT registers location and length
- interrupts : Should contain WDT interrupt
+Optional property:
+- big-endian: If present the watchdog device's registers are implemented
+ in big endian mode, otherwise in little mode.
+
Examples:
wdt@73f98000 {
compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
reg = <0x73f98000 0x4000>;
interrupts = <58>;
+ big-endian;
};
diff --git a/Documentation/devicetree/changesets.txt b/Documentation/devicetree/changesets.txt
new file mode 100644
index 000000000000..935ba5acc34e
--- /dev/null
+++ b/Documentation/devicetree/changesets.txt
@@ -0,0 +1,40 @@
+A DT changeset is a method which allows one to apply changes
+in the live tree in such a way that either the full set of changes
+will be applied, or none of them will be. If an error occurs partway
+through applying the changeset, then the tree will be rolled back to the
+previous state. A changeset can also be removed after it has been
+applied.
+
+When a changeset is applied, all of the changes get applied to the tree
+at once before emitting OF_RECONFIG notifiers. This is so that the
+receiver sees a complete and consistent state of the tree when it
+receives the notifier.
+
+The sequence of a changeset is as follows.
+
+1. of_changeset_init() - initializes a changeset
+
+2. A number of DT tree change calls, of_changeset_attach_node(),
+of_changeset_detach_node(), of_changeset_add_property(),
+of_changeset_remove_property, of_changeset_update_property() to prepare
+a set of changes. No changes to the active tree are made at this point.
+All the change operations are recorded in the of_changeset 'entries'
+list.
+
+3. mutex_lock(of_mutex) - starts a changeset; The global of_mutex
+ensures there can only be one editor at a time.
+
+4. of_changeset_apply() - Apply the changes to the tree. Either the
+entire changeset will get applied, or if there is an error the tree will
+be restored to the previous state
+
+5. mutex_unlock(of_mutex) - All operations complete, release the mutex
+
+If a successfully applied changeset needs to be removed, it can be done
+with the following sequence.
+
+1. mutex_lock(of_mutex)
+
+2. of_changeset_revert()
+
+3. mutex_unlock(of_mutex)
diff --git a/Documentation/devicetree/todo.txt b/Documentation/devicetree/todo.txt
new file mode 100644
index 000000000000..c3cf0659bd19
--- /dev/null
+++ b/Documentation/devicetree/todo.txt
@@ -0,0 +1,11 @@
+Todo list for devicetree:
+
+=== General structure ===
+- Switch from custom lists to (h)list_head for nodes and properties structure
+- Remove of_allnodes list and iterate using list of child nodes alone
+
+=== CONFIG_OF_DYNAMIC ===
+- Switch to RCU for tree updates and get rid of global spinlock
+- Document node lifecycle for CONFIG_OF_DYNAMIC
+- Always set ->full_name at of_attach_node() time
+- pseries: Get rid of open-coded tree modification from arch/powerpc/platforms/pseries/dlpar.c
diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
index 879b6e31e2da..573e28ce9751 100644
--- a/Documentation/dmaengine.txt
+++ b/Documentation/dmaengine.txt
@@ -84,31 +84,32 @@ The slave DMA usage consists of following steps:
the given transaction.
Interface:
- struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)(
+ struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_data_direction direction,
unsigned long flags);
- struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)(
+ struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_data_direction direction);
- struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)(
+ struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma(
struct dma_chan *chan, struct dma_interleaved_template *xt,
unsigned long flags);
The peripheral driver is expected to have mapped the scatterlist for
the DMA operation prior to calling device_prep_slave_sg, and must
keep the scatterlist mapped until the DMA operation has completed.
- The scatterlist must be mapped using the DMA struct device. So,
- normal setup should look like this:
+ The scatterlist must be mapped using the DMA struct device.
+ If a mapping needs to be synchronized later, dma_sync_*_for_*() must be
+ called using the DMA struct device, too.
+ So, normal setup should look like this:
nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len);
if (nr_sg == 0)
/* error */
- desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg,
- direction, flags);
+ desc = dmaengine_prep_slave_sg(chan, sgl, nr_sg, direction, flags);
Once a descriptor has been obtained, the callback information can be
added and the descriptor must then be submitted. Some DMA engine
@@ -188,7 +189,7 @@ Further APIs:
description of this API.
This can be used in conjunction with dma_async_is_complete() and
- the cookie returned from 'descriptor->submit()' to check for
+ the cookie returned from dmaengine_submit() to check for
completion of a specific DMA transaction.
Note:
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 1525e30483fd..d14710b04439 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -233,66 +233,78 @@ certainly invest a bit more effort into libata core layer).
6. List of managed interfaces
-----------------------------
-MEM
- devm_kzalloc()
- devm_kfree()
- devm_kmemdup()
- devm_get_free_pages()
- devm_free_pages()
+CLOCK
+ devm_clk_get()
+ devm_clk_put()
+
+DMA
+ dmam_alloc_coherent()
+ dmam_alloc_noncoherent()
+ dmam_declare_coherent_memory()
+ dmam_free_coherent()
+ dmam_free_noncoherent()
+ dmam_pool_create()
+ dmam_pool_destroy()
+
+GPIO
+ devm_gpiod_get()
+ devm_gpiod_get_index()
+ devm_gpiod_get_index_optional()
+ devm_gpiod_get_optional()
+ devm_gpiod_put()
IIO
devm_iio_device_alloc()
devm_iio_device_free()
- devm_iio_trigger_alloc()
- devm_iio_trigger_free()
devm_iio_device_register()
devm_iio_device_unregister()
+ devm_iio_trigger_alloc()
+ devm_iio_trigger_free()
IO region
- devm_request_region()
- devm_request_mem_region()
- devm_release_region()
devm_release_mem_region()
-
-IRQ
- devm_request_irq()
- devm_free_irq()
-
-DMA
- dmam_alloc_coherent()
- dmam_free_coherent()
- dmam_alloc_noncoherent()
- dmam_free_noncoherent()
- dmam_declare_coherent_memory()
- dmam_pool_create()
- dmam_pool_destroy()
-
-PCI
- pcim_enable_device() : after success, all PCI ops become managed
- pcim_pin_device() : keep PCI device enabled after release
+ devm_release_region()
+ devm_request_mem_region()
+ devm_request_region()
IOMAP
devm_ioport_map()
devm_ioport_unmap()
devm_ioremap()
devm_ioremap_nocache()
- devm_iounmap()
devm_ioremap_resource() : checks resource, requests memory region, ioremaps
- devm_request_and_ioremap() : obsoleted by devm_ioremap_resource()
+ devm_iounmap()
pcim_iomap()
- pcim_iounmap()
- pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
+ pcim_iomap_table() : array of mapped addresses indexed by BAR
+ pcim_iounmap()
-REGULATOR
- devm_regulator_get()
- devm_regulator_put()
- devm_regulator_bulk_get()
- devm_regulator_register()
+IRQ
+ devm_free_irq()
+ devm_request_irq()
-CLOCK
- devm_clk_get()
- devm_clk_put()
+MDIO
+ devm_mdiobus_alloc()
+ devm_mdiobus_alloc_size()
+ devm_mdiobus_free()
+
+MEM
+ devm_free_pages()
+ devm_get_free_pages()
+ devm_kcalloc()
+ devm_kfree()
+ devm_kmalloc()
+ devm_kmalloc_array()
+ devm_kmemdup()
+ devm_kzalloc()
+
+PCI
+ pcim_enable_device() : after success, all PCI ops become managed
+ pcim_pin_device() : keep PCI device enabled after release
+
+PHY
+ devm_usb_get_phy()
+ devm_usb_put_phy()
PINCTRL
devm_pinctrl_get()
@@ -302,24 +314,14 @@ PWM
devm_pwm_get()
devm_pwm_put()
-PHY
- devm_usb_get_phy()
- devm_usb_put_phy()
+REGULATOR
+ devm_regulator_bulk_get()
+ devm_regulator_get()
+ devm_regulator_put()
+ devm_regulator_register()
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
SPI
devm_spi_register_master()
-
-GPIO
- devm_gpiod_get()
- devm_gpiod_get_index()
- devm_gpiod_get_optional()
- devm_gpiod_get_index_optional()
- devm_gpiod_put()
-
-MDIO
- devm_mdiobus_alloc()
- devm_mdiobus_alloc_size()
- devm_mdiobus_free()
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index d91b8be80b66..26c623dd3aa3 100755
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -29,7 +29,7 @@ use IO::Handle;
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
"drxk_hauppauge_hvr930c", "tda10071", "it9135", "drxk_pctv",
- "drxk_terratec_htc_stick", "sms1xxx_hcw");
+ "drxk_terratec_htc_stick", "sms1xxx_hcw", "si2165");
# Check args
syntax() if (scalar(@ARGV) != 1);
@@ -783,6 +783,37 @@ sub sms1xxx_hcw {
$allfiles;
}
+sub si2165 {
+ my $sourcefile = "model_111xxx_122xxx_driver_6_0_119_31191_WHQL.zip";
+ my $url = "http://www.hauppauge.de/files/drivers/";
+ my $hash = "76633e7c76b0edee47c3ba18ded99336";
+ my $fwfile = "dvb-demod-si2165.fw";
+ my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+
+ checkstandard();
+
+ wgetfile($sourcefile, $url . $sourcefile);
+ verify($sourcefile, $hash);
+ unzip($sourcefile, $tmpdir);
+ extract("$tmpdir/Driver10/Hcw10bda.sys", 0x80788, 0x81E08-0x80788, "$tmpdir/fw1");
+
+ delzero("$tmpdir/fw1","$tmpdir/fw1-1");
+ #verify("$tmpdir/fw1","5e0909858fdf0b5b09ad48b9fe622e70");
+
+ my $CRC="\x0A\xCC";
+ my $BLOCKS_MAIN="\x27";
+ open FW,">$fwfile";
+ print FW "\x01\x00"; # just a version id for the driver itself
+ print FW "\x9A"; # fw version
+ print FW "\x00"; # padding
+ print FW "$BLOCKS_MAIN"; # number of blocks of main part
+ print FW "\x00"; # padding
+ print FW "$CRC"; # 16bit crc value of main part
+ appendfile(FW,"$tmpdir/fw1");
+
+ "$fwfile";
+}
+
# ---------------------------------------------------------------
# Utilities
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index b18dd1779029..f1997e9da61f 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -349,7 +349,11 @@ prototypes:
locking rules:
inode->i_lock may block
fl_copy_lock: yes no
-fl_release_private: maybe no
+fl_release_private: maybe maybe[1]
+
+[1]: ->fl_release_private for flock or POSIX locks is currently allowed
+to block. Leases however can still be freed while the i_lock is held and
+so fl_release_private called on a lease should not block.
----------------------- lock_manager_operations ---------------------------
prototypes:
diff --git a/Documentation/filesystems/caching/operations.txt b/Documentation/filesystems/caching/operations.txt
index bee2a5f93d60..a1c052cbba35 100644
--- a/Documentation/filesystems/caching/operations.txt
+++ b/Documentation/filesystems/caching/operations.txt
@@ -90,7 +90,7 @@ operations:
to be cleared before proceeding:
wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
- fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+ TASK_UNINTERRUPTIBLE);
(2) The operation may be fast asynchronous (FSCACHE_OP_FAST), in which case it
diff --git a/Documentation/filesystems/cifs/AUTHORS b/Documentation/filesystems/cifs/AUTHORS
index ca4a67a0bb1e..c98800df677f 100644
--- a/Documentation/filesystems/cifs/AUTHORS
+++ b/Documentation/filesystems/cifs/AUTHORS
@@ -40,6 +40,7 @@ Gunter Kukkukk (testing and suggestions for support of old servers)
Igor Mammedov (DFS support)
Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
Scott Lovenberg
+Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
Test case and Bug Report contributors
-------------------------------------
diff --git a/Documentation/filesystems/cifs/TODO b/Documentation/filesystems/cifs/TODO
index 355abcdcda98..066ffddc3964 100644
--- a/Documentation/filesystems/cifs/TODO
+++ b/Documentation/filesystems/cifs/TODO
@@ -1,4 +1,4 @@
-Version 1.53 May 20, 2008
+Version 2.03 August 1, 2014
A Partial List of Missing Features
==================================
@@ -7,63 +7,49 @@ Contributions are welcome. There are plenty of opportunities
for visible, important contributions to this module. Here
is a partial list of the known problems and missing features:
-a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown
-so that these operations can be supported to Windows servers
+a) SMB3 (and SMB3.02) missing optional features:
+ - RDMA
+ - multichannel (started)
+ - directory leases (improved metadata caching)
+ - T10 copy offload (copy chunk is only mechanism supported)
+ - encrypted shares
-b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS
-SecurityDescriptors
+b) improved sparse file support
-c) Better pam/winbind integration (e.g. to handle uid mapping
-better)
-
-d) Cleanup now unneeded SessSetup code in
-fs/cifs/connect.c and add back in NTLMSSP code if any servers
-need it
-
-e) fix NTLMv2 signing when two mounts with different users to same
-server.
-
-f) Directory entry caching relies on a 1 second timer, rather than
+c) Directory entry caching relies on a 1 second timer, rather than
using FindNotify or equivalent. - (started)
-g) quota support (needs minor kernel change since quota calls
+d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
-h) investigate sync behavior (including syncpage) and check
-for proper behavior of intr/nointr
-
-i) improve support for very old servers (OS/2 and Win9x for example)
+e) improve support for very old servers (OS/2 and Win9x for example)
Including support for changing the time remotely (utimes command).
-j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+f) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
extra copy in/out of the socket buffers in some cases.
-k) Better optimize open (and pathbased setfilesize) to reduce the
+g) Better optimize open (and pathbased setfilesize) to reduce the
oplock breaks coming from windows srv. Piggyback identical file
opens on top of each other by incrementing reference count rather
than resending (helps reduce server resource utilization and avoid
spurious oplock breaks).
-l) Improve performance of readpages by sending more than one read
-at a time when 8 pages or more are requested. In conjuntion
-add support for async_cifs_readpages.
-
-m) Add support for storing symlink info to Windows servers
+h) Add support for storing symlink info to Windows servers
in the Extended Attribute format their SFU clients would recognize.
-n) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+i) Finish inotify support so kde and gnome file list windows
will autorefresh (partially complete by Asser). Needs minor kernel
vfs change to support removing D_NOTIFY on a file.
-o) Add GUI tool to configure /proc/fs/cifs settings and for display of
+j) Add GUI tool to configure /proc/fs/cifs settings and for display of
the CIFS statistics (started)
-p) implement support for security and trusted categories of xattrs
+k) implement support for security and trusted categories of xattrs
(requires minor protocol extension) to enable better support for SELINUX
-q) Implement O_DIRECT flag on open (already supported on mount)
+l) Implement O_DIRECT flag on open (already supported on mount)
-r) Create UID mapping facility so server UIDs can be mapped on a per
+m) Create UID mapping facility so server UIDs can be mapped on a per
mount or a per server basis to client UIDs or nobody if no mapping
exists. This is helpful when Unix extensions are negotiated to
allow better permission checking when UIDs differ on the server
@@ -71,28 +57,29 @@ and client. Add new protocol request to the CIFS protocol
standard for asking the server for the corresponding name of a
particular uid.
-s) Add support for CIFS Unix and also the newer POSIX extensions to the
-server side for Samba 4.
+n) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+
+o) mount check for unmatched uids
-t) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
-need to add ability to set time to server (utimes command)
+p) Add support for new vfs entry point for fallocate
-u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for this too)
+q) Add tools to take advantage of cifs/smb3 specific ioctls and features
+such as "CopyChunk" (fast server side file copy)
-v) mount check for unmatched uids
+r) encrypted file support
-w) Add support for new vfs entry point for fallocate
+s) improved stats gathering, tools (perhaps integration with nfsometer?)
-x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of
-processes can proceed better in parallel (on the server)
+t) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
+file attribute via chflags)
-y) Fix Samba 3 to handle reads/writes over 127K (and remove the cifs mount
-restriction of wsize max being 127K)
+u) mount helper GUI (to simplify the various configuration options on mount)
-KNOWN BUGS (updated April 24, 2007)
+
+KNOWN BUGS
====================================
See http://bugzilla.samba.org - search on product "CifsVFS" for
-current bug list.
+current bug list. Also check http://bugzilla.kernel.org (Product = File System, Component = CIFS)
1) existing symbolic links (Windows reparse points) are recognized but
can not be created remotely. They are implemented for Samba and those that
@@ -100,30 +87,18 @@ support the CIFS Unix extensions, although earlier versions of Samba
overly restrict the pathnames.
2) follow_link and readdir code does not follow dfs junctions
but recognizes them
-3) create of new files to FAT partitions on Windows servers can
-succeed but still return access denied (appears to be Windows
-server not cifs client problem) and has not been reproduced recently.
-NTFS partitions do not have this problem.
-4) Unix/POSIX capabilities are reset after reconnection, and affect
-a few fields in the tree connection but we do do not know which
-superblocks to apply these changes to. We should probably walk
-the list of superblocks to set these. Also need to check the
-flags on the second mount to the same share, and see if we
-can do the same trick that NFS does to remount duplicate shares.
Misc testing to do
==================
1) check out max path names and max path name components against various server
types. Try nested symlinks (8 deep). Return max path name in stat -f information
-2) Modify file portion of ltp so it can run against a mounted network
-share and run it against cifs vfs in automated fashion.
+2) Improve xfstest's cifs enablement and adapt xfstests where needed to test
+cifs better
3) Additional performance testing and optimization using iozone and similar -
there are some easy changes that can be done to parallelize sequential writes,
and when signing is disabled to request larger read sizes (larger than
negotiated size) and send larger write sizes to modern servers.
-4) More exhaustively test against less common servers. More testing
-against Windows 9x, Windows ME servers.
-
+4) More exhaustively test against less common servers
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 51afba17bbae..a2046a7d0a9d 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -126,6 +126,11 @@ flush_merge Merge concurrent cache_flush commands as much as possible
to eliminate redundant command issues. If the underlying
device handles the cache_flush command relatively slowly,
recommend to enable this option.
+nobarrier This option can be used if underlying storage guarantees
+ its cached data should be written to the novolatile area.
+ If this option is set, no cache_flush commands are issued
+ but f2fs still guarantees the write ordering of all the
+ data writes.
================================================================================
DEBUGFS ENTRIES
diff --git a/Documentation/filesystems/nfs/Exporting b/Documentation/filesystems/nfs/Exporting
index e543b1a619cc..c8f036a9b13f 100644
--- a/Documentation/filesystems/nfs/Exporting
+++ b/Documentation/filesystems/nfs/Exporting
@@ -66,23 +66,31 @@ b/ A per-superblock list "s_anon" of dentries which are the roots of
c/ Helper routines to allocate anonymous dentries, and to help attach
loose directory dentries at lookup time. They are:
- d_alloc_anon(inode) will return a dentry for the given inode.
+ d_obtain_alias(inode) will return a dentry for the given inode.
If the inode already has a dentry, one of those is returned.
If it doesn't, a new anonymous (IS_ROOT and
DCACHE_DISCONNECTED) dentry is allocated and attached.
In the case of a directory, care is taken that only one dentry
can ever be attached.
- d_splice_alias(inode, dentry) will make sure that there is a
- dentry with the same name and parent as the given dentry, and
- which refers to the given inode.
- If the inode is a directory and already has a dentry, then that
- dentry is d_moved over the given dentry.
- If the passed dentry gets attached, care is taken that this is
- mutually exclusive to a d_alloc_anon operation.
- If the passed dentry is used, NULL is returned, else the used
- dentry is returned. This corresponds to the calling pattern of
- ->lookup.
-
+ d_splice_alias(inode, dentry) or d_materialise_unique(dentry, inode)
+ will introduce a new dentry into the tree; either the passed-in
+ dentry or a preexisting alias for the given inode (such as an
+ anonymous one created by d_obtain_alias), if appropriate. The two
+ functions differ in their handling of directories with preexisting
+ aliases:
+ d_splice_alias will use any existing IS_ROOT dentry, but it will
+ return -EIO rather than try to move a dentry with a different
+ parent. This is appropriate for local filesystems, which
+ should never see such an alias unless the filesystem is
+ corrupted somehow (for example, if two on-disk directory
+ entries refer to the same directory.)
+ d_materialise_unique will attempt to move any dentry. This is
+ appropriate for distributed filesystems, where finding a
+ directory other than where we last cached it may be a normal
+ consequence of concurrent operations on other hosts.
+ Both functions return NULL when the passed-in dentry is used,
+ following the calling convention of ->lookup.
+
Filesystem Issues
-----------------
@@ -120,12 +128,12 @@ struct which has the following members:
fh_to_dentry (mandatory)
Given a filehandle fragment, this should find the implied object and
- create a dentry for it (possibly with d_alloc_anon).
+ create a dentry for it (possibly with d_obtain_alias).
fh_to_parent (optional but strongly recommended)
Given a filehandle fragment, this should find the parent of the
- implied object and create a dentry for it (possibly with d_alloc_anon).
- May fail if the filehandle fragment is too small.
+ implied object and create a dentry for it (possibly with
+ d_obtain_alias). May fail if the filehandle fragment is too small.
get_parent (optional but strongly recommended)
When given a dentry for a directory, this should return a dentry for
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index ddc531a74d04..eb8a10e22f7c 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1743,6 +1743,25 @@ pair provide additional information particular to the objects they represent.
While the first three lines are mandatory and always printed, the rest is
optional and may be omitted if no marks created yet.
+ Timerfd files
+ ~~~~~~~~~~~~~
+
+ pos: 0
+ flags: 02
+ mnt_id: 9
+ clockid: 0
+ ticks: 0
+ settime flags: 01
+ it_value: (0, 49406829)
+ it_interval: (1, 0)
+
+ where 'clockid' is the clock type and 'ticks' is the number of the timer expirations
+ that have occurred [see timerfd_create(2) for details]. 'settime flags' are
+ flags in octal form been used to setup the timer [see timerfd_settime(2) for
+ details]. 'it_value' is remaining time until the timer exiration.
+ 'it_interval' is the interval for the timer. Note the timer might be set up
+ with TIMER_ABSTIME option which will be shown in 'settime flags', but 'it_value'
+ still exhibits timer's remaining time.
------------------------------------------------------------------------------
Configuring procfs
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index a1d0d7a30165..61d65cc65c54 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -1053,7 +1053,8 @@ struct dentry_operations {
If the 'rcu_walk' parameter is true, then the caller is doing a
pathwalk in RCU-walk mode. Sleeping is not permitted in this mode,
and the caller can be asked to leave it and call again by returning
- -ECHILD.
+ -ECHILD. -EISDIR may also be returned to tell pathwalk to
+ ignore d_automount or any mounts.
This function is only used if DCACHE_MANAGE_TRANSIT is set on the
dentry being transited from.
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index 43fada989e65..71f86859d7d8 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -64,7 +64,7 @@
if(request_firmware(&fw_entry, $FIRMWARE, device) == 0)
copy_fw_to_device(fw_entry->data, fw_entry->size);
- release(fw_entry);
+ release_firmware(fw_entry);
Sample/simple hotplug script:
============================
@@ -74,7 +74,7 @@
HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
echo 1 > /sys/$DEVPATH/loading
- cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+ cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
echo 0 > /sys/$DEVPATH/loading
Random notes:
@@ -123,6 +123,6 @@
--------------------
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
+ resume callback, and callers needn't cache the firmware by
themselves any more for dealing with firmware loss during system
resume.
diff --git a/Documentation/gpio/board.txt b/Documentation/gpio/board.txt
index ba169faad5c6..4452786225b8 100644
--- a/Documentation/gpio/board.txt
+++ b/Documentation/gpio/board.txt
@@ -60,7 +60,7 @@ Platform Data
Finally, GPIOs can be bound to devices and functions using platform data. Board
files that desire to do so need to include the following header:
- #include <linux/gpio/driver.h>
+ #include <linux/gpio/machine.h>
GPIOs are mapped by the means of tables of lookups, containing instances of the
gpiod_lookup structure. Two macros are defined to help declaring such mappings:
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
index d8abfc31abbe..76546324e968 100644
--- a/Documentation/gpio/consumer.txt
+++ b/Documentation/gpio/consumer.txt
@@ -29,13 +29,24 @@ gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the
device that will use the GPIO and the function the requested GPIO is supposed to
fulfill:
- struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
+ struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
+ enum gpiod_flags flags)
If a function is implemented by using several GPIOs together (e.g. a simple LED
device that displays digits), an additional index argument can be specified:
struct gpio_desc *gpiod_get_index(struct device *dev,
- const char *con_id, unsigned int idx)
+ const char *con_id, unsigned int idx,
+ enum gpiod_flags flags)
+
+The flags parameter is used to optionally specify a direction and initial value
+for the GPIO. Values can be:
+
+* GPIOD_ASIS or 0 to not initialize the GPIO at all. The direction must be set
+ later with one of the dedicated functions.
+* GPIOD_IN to initialize the GPIO as input.
+* GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0.
+* GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1.
Both functions return either a valid GPIO descriptor, or an error code checkable
with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned
@@ -46,11 +57,13 @@ errors and an absence of GPIO for optional GPIO parameters.
Device-managed variants of these functions are also defined:
- struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
+ struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
+ enum gpiod_flags flags)
struct gpio_desc *devm_gpiod_get_index(struct device *dev,
const char *con_id,
- unsigned int idx)
+ unsigned int idx,
+ enum gpiod_flags flags)
A GPIO descriptor can be disposed of using the gpiod_put() function:
@@ -67,8 +80,9 @@ Using GPIOs
Setting Direction
-----------------
-The first thing a driver must do with a GPIO is setting its direction. This is
-done by invoking one of the gpiod_direction_*() functions:
+The first thing a driver must do with a GPIO is setting its direction. If no
+direction-setting flags have been given to gpiod_get*(), this is done by
+invoking one of the gpiod_direction_*() functions:
int gpiod_direction_input(struct gpio_desc *desc)
int gpiod_direction_output(struct gpio_desc *desc, int value)
diff --git a/Documentation/gpio/driver.txt b/Documentation/gpio/driver.txt
index fa9a0a8b3734..18790c237977 100644
--- a/Documentation/gpio/driver.txt
+++ b/Documentation/gpio/driver.txt
@@ -157,13 +157,34 @@ Locking IRQ usage
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
to mark the GPIO as being used as an IRQ:
- int gpiod_lock_as_irq(struct gpio_desc *desc)
+ int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
is released:
- void gpiod_unlock_as_irq(struct gpio_desc *desc)
+ void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
When implementing an irqchip inside a GPIO driver, these two functions should
typically be called in the .startup() and .shutdown() callbacks from the
irqchip.
+
+
+Requesting self-owned GPIO pins
+-------------------------------
+
+Sometimes it is useful to allow a GPIO chip driver to request its own GPIO
+descriptors through the gpiolib API. Using gpio_request() for this purpose
+does not help since it pins the module to the kernel forever (it calls
+try_module_get()). A GPIO driver can use the following functions instead
+to request and free descriptors without being pinned to the kernel forever.
+
+ int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
+
+ void gpiochip_free_own_desc(struct gpio_desc *desc)
+
+Descriptors requested with gpiochip_request_own_desc() must be released with
+gpiochip_free_own_desc().
+
+These functions must be used with care since they do not affect module use
+count. Do not use the functions to request gpio descriptors not owned by the
+calling driver.
diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv
new file mode 100644
index 000000000000..8826ba29db36
--- /dev/null
+++ b/Documentation/hwmon/ibmpowernv
@@ -0,0 +1,41 @@
+Kernel Driver IBMPOWERNV
+========================
+
+Supported systems:
+ * Any recent IBM P servers based on POWERNV platform
+
+Author: Neelesh Gupta
+
+Description
+-----------
+
+This driver implements reading the platform sensors data like temperature/fan/
+voltage/power for 'POWERNV' platform.
+
+The driver uses the platform device infrastructure. It probes the device tree
+for sensor devices during the __init phase and registers them with the 'hwmon'.
+'hwmon' populates the 'sysfs' tree having attribute files, each for a given
+sensor type and its attribute data.
+
+All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in
+the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'
+which the driver uses to make an OPAL call to the firmware.
+
+Usage notes
+-----------
+The driver is built statically with the kernel by enabling the config
+CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.
+
+Sysfs attributes
+----------------
+
+fanX_input Measured RPM value.
+fanX_min Threshold RPM for alert generation.
+fanX_fault 0: No fail condition
+ 1: Failing fan
+tempX_input Measured ambient temperature.
+tempX_max Threshold ambient temperature for alert generation.
+inX_input Measured power supply voltage
+inX_fault 0: No fail condition.
+ 1: Failing power supply.
+power1_input System power consumption (microWatt)
diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75
index 2560a9c6d445..c6a5ff1b4641 100644
--- a/Documentation/hwmon/lm75
+++ b/Documentation/hwmon/lm75
@@ -42,13 +42,14 @@ Supported chips:
Addresses scanned: none
Datasheet: Publicly available at the ST website
http://www.st.com/internet/analog/product/121769.jsp
- * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275
- Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275'
+ * Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75, TMP175, TMP275
+ Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp112', 'tmp175', 'tmp75', 'tmp275'
Addresses scanned: none
Datasheet: Publicly available at the Texas Instruments website
http://www.ti.com/product/tmp100
http://www.ti.com/product/tmp101
http://www.ti.com/product/tmp105
+ http://www.ti.com/product/tmp112
http://www.ti.com/product/tmp75
http://www.ti.com/product/tmp175
http://www.ti.com/product/tmp275
diff --git a/Documentation/hwmon/ntc_thermistor b/Documentation/hwmon/ntc_thermistor
index 057b77029f26..c5e05e2900a3 100644
--- a/Documentation/hwmon/ntc_thermistor
+++ b/Documentation/hwmon/ntc_thermistor
@@ -6,6 +6,11 @@ Supported thermistors from Murata:
Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333'
Datasheet: Publicly available at Murata
+Supported thermistors from EPCOS:
+* EPCOS NTC Thermistors B57330V2103
+ Prefixes: b57330v2103
+ Datasheet: Publicly available at EPCOS
+
Other NTC thermistors can be supported simply by adding compensation
tables; e.g., NCP15WL333 support is added by the table ncpXXwl333.
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
index cf756ed48ff9..a3557da8f5b4 100644
--- a/Documentation/hwmon/pmbus
+++ b/Documentation/hwmon/pmbus
@@ -23,12 +23,11 @@ Supported chips:
http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
- * Texas Instruments TPS40400, TPS40422
- Prefixes: 'tps40400', 'tps40422'
+ * Texas Instruments TPS40400
+ Prefixes: 'tps40400'
Addresses scanned: -
Datasheets:
http://www.ti.com/lit/gpn/tps40400
- http://www.ti.com/lit/gpn/tps40422
* Generic PMBus devices
Prefix: 'pmbus'
Addresses scanned: -
diff --git a/Documentation/hwmon/powr1220 b/Documentation/hwmon/powr1220
new file mode 100644
index 000000000000..21e44f71ae6e
--- /dev/null
+++ b/Documentation/hwmon/powr1220
@@ -0,0 +1,45 @@
+Kernel driver powr1220
+==================
+
+Supported chips:
+ * Lattice POWR1220AT8
+ Prefix: 'powr1220'
+ Addresses scanned: none
+ Datasheet: Publicly available at the Lattice website
+ http://www.latticesemi.com/
+
+Author: Scott Kanowitz <scott.kanowitz@gmail.com>
+
+Description
+-----------
+
+This driver supports the Lattice POWR1220AT8 chip. The POWR1220
+includes voltage monitoring for 14 inputs as well as trim settings
+for output voltages and GPIOs. This driver implements the voltage
+monitoring portion of the chip.
+
+Voltages are sampled by a 12-bit ADC with a step size of 2 mV.
+An in-line attenuator allows measurements from 0 to 6 V. The
+attenuator is enabled or disabled depending on the setting of the
+input's max value. The driver will enable the attenuator for any
+value over the low measurement range maximum of 2 V.
+
+The input naming convention is as follows:
+
+driver name pin name
+in0 VMON1
+in1 VMON2
+in2 VMON3
+in2 VMON4
+in4 VMON5
+in5 VMON6
+in6 VMON7
+in7 VMON8
+in8 VMON9
+in9 VMON10
+in10 VMON11
+in11 VMON12
+in12 VCCA
+in13 VCCINP
+
+The ADC readings are updated on request with a minimum period of 1s.
diff --git a/Documentation/hwmon/pwm-fan b/Documentation/hwmon/pwm-fan
new file mode 100644
index 000000000000..18529d2e3bcf
--- /dev/null
+++ b/Documentation/hwmon/pwm-fan
@@ -0,0 +1,17 @@
+Kernel driver pwm-fan
+=====================
+
+This driver enables the use of a PWM module to drive a fan. It uses the
+generic PWM interface thus it is hardware independent. It can be used on
+many SoCs, as long as the SoC supplies a PWM line driver that exposes
+the generic PWM API.
+
+Author: Kamil Debski <k.debski@samsung.com>
+
+Description
+-----------
+
+The driver implements a simple interface for driving a fan connected to
+a PWM output. It uses the generic PWM interface, thus it can be used with
+a range of SoCs. The driver exposes the fan to the user space through
+the hwmon's sysfs interface.
diff --git a/Documentation/hwmon/tmp103 b/Documentation/hwmon/tmp103
new file mode 100644
index 000000000000..ec00a15645ba
--- /dev/null
+++ b/Documentation/hwmon/tmp103
@@ -0,0 +1,28 @@
+Kernel driver tmp103
+====================
+
+Supported chips:
+ * Texas Instruments TMP103
+ Prefix: 'tmp103'
+ Addresses scanned: none
+ Product info and datasheet: http://www.ti.com/product/tmp103
+
+Author:
+ Heiko Schocher <hs@denx.de>
+
+Description
+-----------
+
+The TMP103 is a digital output temperature sensor in a four-ball
+wafer chip-scale package (WCSP). The TMP103 is capable of reading
+temperatures to a resolution of 1°C. The TMP103 is specified for
+operation over a temperature range of –40°C to +125°C.
+
+Resolution: 8 Bits
+Accuracy: ±1°C Typ (–10°C to +100°C)
+
+The driver provides the common sysfs-interface for temperatures (see
+Documentation/hwmon/sysfs-interface under Temperatures).
+
+Please refer how to instantiate this driver:
+Documentation/i2c/instantiating-devices
diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
index 0cf07f824741..9e6fe5549ca1 100644
--- a/Documentation/hwmon/tmp421
+++ b/Documentation/hwmon/tmp421
@@ -8,12 +8,20 @@ Supported chips:
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
* Texas Instruments TMP422
Prefix: 'tmp422'
- Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+ Addresses scanned: I2C 0x4c, 0x4d, 0x4e and 0x4f
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
* Texas Instruments TMP423
Prefix: 'tmp423'
- Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+ Addresses scanned: I2C 0x4c and 0x4d
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+ * Texas Instruments TMP441
+ Prefix: 'tmp441'
+ Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+ Datasheet: http://www.ti.com/product/tmp441
+ * Texas Instruments TMP442
+ Prefix: 'tmp442'
+ Addresses scanned: I2C 0x4c and 0x4d
+ Datasheet: http://www.ti.com/product/tmp442
Authors:
Andre Prendel <andre.prendel@gmx.de>
@@ -21,13 +29,13 @@ Authors:
Description
-----------
-This driver implements support for Texas Instruments TMP421, TMP422
-and TMP423 temperature sensor chips. These chips implement one local
-and up to one (TMP421), up to two (TMP422) or up to three (TMP423)
-remote sensors. Temperature is measured in degrees Celsius. The chips
-are wired over I2C/SMBus and specified over a temperature range of -40
-to +125 degrees Celsius. Resolution for both the local and remote
-channels is 0.0625 degree C.
+This driver implements support for Texas Instruments TMP421, TMP422,
+TMP423, TMP441, and TMP442 temperature sensor chips. These chips
+implement one local and up to one (TMP421, TMP441), up to two (TMP422,
+TMP442) or up to three (TMP423) remote sensors. Temperature is measured
+in degrees Celsius. The chips are wired over I2C/SMBus and specified
+over a temperature range of -40 to +125 degrees Celsius. Resolution
+for both the local and remote channels is 0.0625 degree C.
The chips support only temperature measurement. The driver exports
the temperature values via the following sysfs files:
diff --git a/Documentation/hwmon/tps40422 b/Documentation/hwmon/tps40422
new file mode 100644
index 000000000000..24bb0688d515
--- /dev/null
+++ b/Documentation/hwmon/tps40422
@@ -0,0 +1,64 @@
+Kernel driver tps40422
+======================
+
+Supported chips:
+ * TI TPS40422
+ Prefix: 'tps40422'
+ Addresses scanned: -
+ Datasheet: http://www.ti.com/lit/gpn/tps40422
+
+Author: Zhu Laiwen <richard.zhu@nsn.com>
+
+
+Description
+-----------
+
+This driver supports TI TPS40422 Dual-Output or Two-Phase Synchronous Buck
+Controller with PMBus
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported.
+
+in[1-2]_label "vout[1-2]"
+in[1-2]_input Measured voltage. From READ_VOUT register.
+in[1-2]_alarm voltage alarm.
+
+curr[1-2]_input Measured current. From READ_IOUT register.
+curr[1-2]_label "iout[1-2]"
+curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT status.
+curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
+curr2_alarm Current high alarm. From IOUT_OC_WARNING status.
+
+temp1_input Measured temperature. From READ_TEMPERATURE_2 register on page 0.
+temp1_max Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm Chip temperature high alarm. Set by comparing
+ READ_TEMPERATURE_2 on page 0 with OT_WARN_LIMIT if TEMP_OT_WARNING
+ status is set.
+temp1_crit_alarm Chip temperature critical high alarm. Set by comparing
+ READ_TEMPERATURE_2 on page 0 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+ status is set.
+temp2_input Measured temperature. From READ_TEMPERATURE_2 register on page 1.
+temp2_alarm Chip temperature alarm on page 1.
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index adf5e33e8312..e9c803ea306d 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -25,6 +25,7 @@ Supported adapters:
* Intel Avoton (SOC)
* Intel Wellsburg (PCH)
* Intel Coleto Creek (PCH)
+ * Intel Wildcat Point (PCH)
* Intel Wildcat Point-LP (PCH)
* Intel BayTrail (SOC)
Datasheets: Publicly available at the Intel website
diff --git a/Documentation/i2c/i2c-stub b/Documentation/i2c/i2c-stub
index fa4b669c166b..a16924fbd289 100644
--- a/Documentation/i2c/i2c-stub
+++ b/Documentation/i2c/i2c-stub
@@ -2,9 +2,9 @@ MODULE: i2c-stub
DESCRIPTION:
-This module is a very simple fake I2C/SMBus driver. It implements five
+This module is a very simple fake I2C/SMBus driver. It implements six
types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, (r/w)
-word data, and (r/w) I2C block data.
+word data, (r/w) I2C block data, and (r/w) SMBus block data.
You need to provide chip addresses as a module parameter when loading this
driver, which will then only react to SMBus commands to these addresses.
@@ -19,6 +19,14 @@ A pointer register with auto-increment is implemented for all byte
operations. This allows for continuous byte reads like those supported by
EEPROMs, among others.
+SMBus block command support is disabled by default, and must be enabled
+explicitly by setting the respective bits (0x03000000) in the functionality
+module parameter.
+
+SMBus block commands must be written to configure an SMBus command for
+SMBus block operations. Writes can be partial. Block read commands always
+return the number of bytes selected with the largest write so far.
+
The typical use-case is like this:
1. load this module
2. use i2cset (from the i2c-tools project) to pre-load some data
@@ -39,15 +47,18 @@ unsigned long functionality:
value 0x1f0000 would only enable the quick, byte and byte data
commands.
+u8 bank_reg[10]
+u8 bank_mask[10]
+u8 bank_start[10]
+u8 bank_end[10]:
+ Optional bank settings. They tell which bits in which register
+ select the active bank, as well as the range of banked registers.
+
CAVEATS:
If your target driver polls some byte or word waiting for it to change, the
stub could lock it up. Use i2cset to unlock it.
-If the hardware for your driver has banked registers (e.g. Winbond sensors
-chips) this module will not work well - although it could be extended to
-support that pretty easily.
-
If you spam it hard enough, printk can be lossy. This module really wants
something like relayfs.
diff --git a/Documentation/infiniband/user_mad.txt b/Documentation/infiniband/user_mad.txt
index 8a366959f5cc..7aca13a54a3a 100644
--- a/Documentation/infiniband/user_mad.txt
+++ b/Documentation/infiniband/user_mad.txt
@@ -26,6 +26,11 @@ Creating MAD agents
ioctl. Also, all agents registered through a file descriptor will
be unregistered when the descriptor is closed.
+ 2014 -- a new registration ioctl is now provided which allows additional
+ fields to be provided during registration.
+ Users of this registration call are implicitly setting the use of
+ pkey_index (see below).
+
Receiving MADs
MADs are received using read(). The receive side now supports
@@ -104,10 +109,10 @@ P_Key Index Handling
The old ib_umad interface did not allow setting the P_Key index for
MADs that are sent and did not provide a way for obtaining the P_Key
index of received MADs. A new layout for struct ib_user_mad_hdr
- with a pkey_index member has been defined; however, to preserve
- binary compatibility with older applications, this new layout will
- not be used unless the IB_USER_MAD_ENABLE_PKEY ioctl is called
- before a file descriptor is used for anything else.
+ with a pkey_index member has been defined; however, to preserve binary
+ compatibility with older applications, this new layout will not be used
+ unless one of IB_USER_MAD_ENABLE_PKEY or IB_USER_MAD_REGISTER_AGENT2 ioctl's
+ are called before a file descriptor is used for anything else.
In September 2008, the IB_USER_MAD_ABI_VERSION will be incremented
to 6, the new layout of struct ib_user_mad_hdr will be used by
diff --git a/Documentation/ioctl/00-INDEX b/Documentation/ioctl/00-INDEX
index d2fe4d4729ef..c1a925787950 100644
--- a/Documentation/ioctl/00-INDEX
+++ b/Documentation/ioctl/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- this file
+botching-up-ioctls.txt
+ - how to avoid botching up ioctls
cdrom.txt
- summary of CDROM ioctl calls
hdio.txt
diff --git a/Documentation/ioctl/botching-up-ioctls.txt b/Documentation/ioctl/botching-up-ioctls.txt
new file mode 100644
index 000000000000..45fe78c58019
--- /dev/null
+++ b/Documentation/ioctl/botching-up-ioctls.txt
@@ -0,0 +1,219 @@
+(How to avoid) Botching up ioctls
+=================================
+
+From: http://blog.ffwll.ch/2013/11/botching-up-ioctls.html
+
+By: Daniel Vetter, Copyright © 2013 Intel Corporation
+
+One clear insight kernel graphics hackers gained in the past few years is that
+trying to come up with a unified interface to manage the execution units and
+memory on completely different GPUs is a futile effort. So nowadays every
+driver has its own set of ioctls to allocate memory and submit work to the GPU.
+Which is nice, since there's no more insanity in the form of fake-generic, but
+actually only used once interfaces. But the clear downside is that there's much
+more potential to screw things up.
+
+To avoid repeating all the same mistakes again I've written up some of the
+lessons learned while botching the job for the drm/i915 driver. Most of these
+only cover technicalities and not the big-picture issues like what the command
+submission ioctl exactly should look like. Learning these lessons is probably
+something every GPU driver has to do on its own.
+
+
+Prerequisites
+-------------
+
+First the prerequisites. Without these you have already failed, because you
+will need to add a a 32-bit compat layer:
+
+ * Only use fixed sized integers. To avoid conflicts with typedefs in userspace
+ the kernel has special types like __u32, __s64. Use them.
+
+ * Align everything to the natural size and use explicit padding. 32-bit
+ platforms don't necessarily align 64-bit values to 64-bit boundaries, but
+ 64-bit platforms do. So we always need padding to the natural size to get
+ this right.
+
+ * Pad the entire struct to a multiple of 64-bits - the structure size will
+ otherwise differ on 32-bit versus 64-bit. Having a different structure size
+ hurts when passing arrays of structures to the kernel, or if the kernel
+ checks the structure size, which e.g. the drm core does.
+
+ * Pointers are __u64, cast from/to a uintprt_t on the userspace side and
+ from/to a void __user * in the kernel. Try really hard not to delay this
+ conversion or worse, fiddle the raw __u64 through your code since that
+ diminishes the checking tools like sparse can provide.
+
+
+Basics
+------
+
+With the joys of writing a compat layer avoided we can take a look at the basic
+fumbles. Neglecting these will make backward and forward compatibility a real
+pain. And since getting things wrong on the first attempt is guaranteed you
+will have a second iteration or at least an extension for any given interface.
+
+ * Have a clear way for userspace to figure out whether your new ioctl or ioctl
+ extension is supported on a given kernel. If you can't rely on old kernels
+ rejecting the new flags/modes or ioctls (since doing that was botched in the
+ past) then you need a driver feature flag or revision number somewhere.
+
+ * Have a plan for extending ioctls with new flags or new fields at the end of
+ the structure. The drm core checks the passed-in size for each ioctl call
+ and zero-extends any mismatches between kernel and userspace. That helps,
+ but isn't a complete solution since newer userspace on older kernels won't
+ notice that the newly added fields at the end get ignored. So this still
+ needs a new driver feature flags.
+
+ * Check all unused fields and flags and all the padding for whether it's 0,
+ and reject the ioctl if that's not the case. Otherwise your nice plan for
+ future extensions is going right down the gutters since someone will submit
+ an ioctl struct with random stack garbage in the yet unused parts. Which
+ then bakes in the ABI that those fields can never be used for anything else
+ but garbage.
+
+ * Have simple testcases for all of the above.
+
+
+Fun with Error Paths
+--------------------
+
+Nowadays we don't have any excuse left any more for drm drivers being neat
+little root exploits. This means we both need full input validation and solid
+error handling paths - GPUs will die eventually in the oddmost corner cases
+anyway:
+
+ * The ioctl must check for array overflows. Also it needs to check for
+ over/underflows and clamping issues of integer values in general. The usual
+ example is sprite positioning values fed directly into the hardware with the
+ hardware just having 12 bits or so. Works nicely until some odd display
+ server doesn't bother with clamping itself and the cursor wraps around the
+ screen.
+
+ * Have simple testcases for every input validation failure case in your ioctl.
+ Check that the error code matches your expectations. And finally make sure
+ that you only test for one single error path in each subtest by submitting
+ otherwise perfectly valid data. Without this an earlier check might reject
+ the ioctl already and shadow the codepath you actually want to test, hiding
+ bugs and regressions.
+
+ * Make all your ioctls restartable. First X really loves signals and second
+ this will allow you to test 90% of all error handling paths by just
+ interrupting your main test suite constantly with signals. Thanks to X's
+ love for signal you'll get an excellent base coverage of all your error
+ paths pretty much for free for graphics drivers. Also, be consistent with
+ how you handle ioctl restarting - e.g. drm has a tiny drmIoctl helper in its
+ userspace library. The i915 driver botched this with the set_tiling ioctl,
+ now we're stuck forever with some arcane semantics in both the kernel and
+ userspace.
+
+ * If you can't make a given codepath restartable make a stuck task at least
+ killable. GPUs just die and your users won't like you more if you hang their
+ entire box (by means of an unkillable X process). If the state recovery is
+ still too tricky have a timeout or hangcheck safety net as a last-ditch
+ effort in case the hardware has gone bananas.
+
+ * Have testcases for the really tricky corner cases in your error recovery code
+ - it's way too easy to create a deadlock between your hangcheck code and
+ waiters.
+
+
+Time, Waiting and Missing it
+----------------------------
+
+GPUs do most everything asynchronously, so we have a need to time operations and
+wait for oustanding ones. This is really tricky business; at the moment none of
+the ioctls supported by the drm/i915 get this fully right, which means there's
+still tons more lessons to learn here.
+
+ * Use CLOCK_MONOTONIC as your reference time, always. It's what alsa, drm and
+ v4l use by default nowadays. But let userspace know which timestamps are
+ derived from different clock domains like your main system clock (provided
+ by the kernel) or some independent hardware counter somewhere else. Clocks
+ will mismatch if you look close enough, but if performance measuring tools
+ have this information they can at least compensate. If your userspace can
+ get at the raw values of some clocks (e.g. through in-command-stream
+ performance counter sampling instructions) consider exposing those also.
+
+ * Use __s64 seconds plus __u64 nanoseconds to specify time. It's not the most
+ convenient time specification, but it's mostly the standard.
+
+ * Check that input time values are normalized and reject them if not. Note
+ that the kernel native struct ktime has a signed integer for both seconds
+ and nanoseconds, so beware here.
+
+ * For timeouts, use absolute times. If you're a good fellow and made your
+ ioctl restartable relative timeouts tend to be too coarse and can
+ indefinitely extend your wait time due to rounding on each restart.
+ Especially if your reference clock is something really slow like the display
+ frame counter. With a spec laywer hat on this isn't a bug since timeouts can
+ always be extended - but users will surely hate you if their neat animations
+ starts to stutter due to this.
+
+ * Consider ditching any synchronous wait ioctls with timeouts and just deliver
+ an asynchronous event on a pollable file descriptor. It fits much better
+ into event driven applications' main loop.
+
+ * Have testcases for corner-cases, especially whether the return values for
+ already-completed events, successful waits and timed-out waits are all sane
+ and suiting to your needs.
+
+
+Leaking Resources, Not
+----------------------
+
+A full-blown drm driver essentially implements a little OS, but specialized to
+the given GPU platforms. This means a driver needs to expose tons of handles
+for different objects and other resources to userspace. Doing that right
+entails its own little set of pitfalls:
+
+ * Always attach the lifetime of your dynamically created resources to the
+ lifetime of a file descriptor. Consider using a 1:1 mapping if your resource
+ needs to be shared across processes - fd-passing over unix domain sockets
+ also simplifies lifetime management for userspace.
+
+ * Always have O_CLOEXEC support.
+
+ * Ensure that you have sufficient insulation between different clients. By
+ default pick a private per-fd namespace which forces any sharing to be done
+ explictly. Only go with a more global per-device namespace if the objects
+ are truly device-unique. One counterexample in the drm modeset interfaces is
+ that the per-device modeset objects like connectors share a namespace with
+ framebuffer objects, which mostly are not shared at all. A separate
+ namespace, private by default, for framebuffers would have been more
+ suitable.
+
+ * Think about uniqueness requirements for userspace handles. E.g. for most drm
+ drivers it's a userspace bug to submit the same object twice in the same
+ command submission ioctl. But then if objects are shareable userspace needs
+ to know whether it has seen an imported object from a different process
+ already or not. I haven't tried this myself yet due to lack of a new class
+ of objects, but consider using inode numbers on your shared file descriptors
+ as unique identifiers - it's how real files are told apart, too.
+ Unfortunately this requires a full-blown virtual filesystem in the kernel.
+
+
+Last, but not Least
+-------------------
+
+Not every problem needs a new ioctl:
+
+ * Think hard whether you really want a driver-private interface. Of course
+ it's much quicker to push a driver-private interface than engaging in
+ lengthy discussions for a more generic solution. And occasionally doing a
+ private interface to spearhead a new concept is what's required. But in the
+ end, once the generic interface comes around you'll end up maintainer two
+ interfaces. Indefinitely.
+
+ * Consider other interfaces than ioctls. A sysfs attribute is much better for
+ per-device settings, or for child objects with fairly static lifetimes (like
+ output connectors in drm with all the detection override attributes). Or
+ maybe only your testsuite needs this interface, and then debugfs with its
+ disclaimer of not having a stable ABI would be better.
+
+Finally, the name of the game is to get it right on the first attempt, since if
+your driver proves popular and your hardware platforms long-lived then you'll
+be stuck with a given ioctl essentially forever. You can try to deprecate
+horrible ioctls on newer iterations of your hardware, but generally it takes
+years to accomplish this. And then again years until the last user able to
+complain about regressions disappears, too.
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index d7e43fa88575..7e240a7c9ab1 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -197,6 +197,7 @@ Code Seq#(hex) Include File Comments
<mailto:gregkh@linuxfoundation.org>
'a' all linux/atm*.h, linux/sonet.h ATM on linux
<http://lrcwww.epfl.ch/>
+'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver
'b' 00-FF conflict! bit3 vme host bridge
<mailto:natalia@nikhefk.nikhef.nl>
'c' all linux/cm4000_cs.h conflict!
diff --git a/Documentation/kbuild/00-INDEX b/Documentation/kbuild/00-INDEX
index e8d2b6d83a3d..8c5e6aa78004 100644
--- a/Documentation/kbuild/00-INDEX
+++ b/Documentation/kbuild/00-INDEX
@@ -1,5 +1,7 @@
00-INDEX
- this file: info on the kernel build process
+headers_install.txt
+ - how to export Linux headers for use by userspace
kbuild.txt
- developer information on kbuild
kconfig.txt
diff --git a/Documentation/make/headers_install.txt b/Documentation/kbuild/headers_install.txt
index 951eb9f1e040..951eb9f1e040 100644
--- a/Documentation/make/headers_install.txt
+++ b/Documentation/kbuild/headers_install.txt
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index c600e2f44a62..764f5991a3fc 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -23,11 +23,10 @@ This document describes the Linux kernel Makefiles.
=== 4 Host Program support
--- 4.1 Simple Host Program
--- 4.2 Composite Host Programs
- --- 4.3 Defining shared libraries
- --- 4.4 Using C++ for host programs
- --- 4.5 Controlling compiler options for host programs
- --- 4.6 When host programs are actually built
- --- 4.7 Using hostprogs-$(CONFIG_FOO)
+ --- 4.3 Using C++ for host programs
+ --- 4.4 Controlling compiler options for host programs
+ --- 4.5 When host programs are actually built
+ --- 4.6 Using hostprogs-$(CONFIG_FOO)
=== 5 Kbuild clean infrastructure
@@ -643,29 +642,7 @@ Both possibilities are described in the following.
Finally, the two .o files are linked to the executable, lxdialog.
Note: The syntax <executable>-y is not permitted for host-programs.
---- 4.3 Defining shared libraries
-
- Objects with extension .so are considered shared libraries, and
- will be compiled as position independent objects.
- Kbuild provides support for shared libraries, but the usage
- shall be restricted.
- In the following example the libkconfig.so shared library is used
- to link the executable conf.
-
- Example:
- #scripts/kconfig/Makefile
- hostprogs-y := conf
- conf-objs := conf.o libkconfig.so
- libkconfig-objs := expr.o type.o
-
- Shared libraries always require a corresponding -objs line, and
- in the example above the shared library libkconfig is composed by
- the two objects expr.o and type.o.
- expr.o and type.o will be built as position independent code and
- linked as a shared library libkconfig.so. C++ is not supported for
- shared libraries.
-
---- 4.4 Using C++ for host programs
+--- 4.3 Using C++ for host programs
kbuild offers support for host programs written in C++. This was
introduced solely to support kconfig, and is not recommended
@@ -688,7 +665,7 @@ Both possibilities are described in the following.
qconf-cxxobjs := qconf.o
qconf-objs := check.o
---- 4.5 Controlling compiler options for host programs
+--- 4.4 Controlling compiler options for host programs
When compiling host programs, it is possible to set specific flags.
The programs will always be compiled utilising $(HOSTCC) passed
@@ -716,7 +693,7 @@ Both possibilities are described in the following.
When linking qconf, it will be passed the extra option
"-L$(QTDIR)/lib".
---- 4.6 When host programs are actually built
+--- 4.5 When host programs are actually built
Kbuild will only build host-programs when they are referenced
as a prerequisite.
@@ -747,7 +724,7 @@ Both possibilities are described in the following.
This will tell kbuild to build lxdialog even if not referenced in
any rule.
---- 4.7 Using hostprogs-$(CONFIG_FOO)
+--- 4.6 Using hostprogs-$(CONFIG_FOO)
A typical pattern in a Kbuild file looks like this:
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b7fa2f599459..5ae8608ca9f5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -566,6 +566,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
possible to determine what the correct size should be.
This option provides an override for these situations.
+ ca_keys= [KEYS] This parameter identifies a specific key(s) on
+ the system trusted keyring to be used for certificate
+ trust validation.
+ format: { id:<keyid> | builtin }
+
+ cca= [MIPS] Override the kernel pages' cache coherency
+ algorithm. Accepted values range from 0 to 7
+ inclusive. See arch/mips/include/asm/pgtable-bits.h
+ for platform specific values (SB1, Loongson3 and
+ others).
+
ccw_timeout_log [S390]
See Documentation/s390/CommonIO for details.
@@ -1097,6 +1108,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
that can be changed at run time by the
set_graph_function file in the debugfs tracing directory.
+ ftrace_graph_notrace=[function-list]
+ [FTRACE] Do not trace from the functions specified in
+ function-list. This list is a comma separated list of
+ functions that can be changed at run time by the
+ set_graph_notrace file in the debugfs tracing directory.
+
gamecon.map[2|3]=
[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
support via parallel port (up to 5 devices per port)
@@ -1313,6 +1330,23 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Formats: { "ima" | "ima-ng" }
Default: "ima-ng"
+ ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
+ Format: <min_file_size>
+ Set the minimal file size for using asynchronous hash.
+ If left unspecified, ahash usage is disabled.
+
+ ahash performance varies for different data sizes on
+ different crypto accelerators. This option can be used
+ to achieve the best performance for a particular HW.
+
+ ima.ahash_bufsize= [IMA] Asynchronous hash buffer size
+ Format: <bufsize>
+ Set hashing buffer size. Default: 4k.
+
+ ahash performance varies for different chunk sizes on
+ different crypto accelerators. This option can be used
+ to achieve best performance for particular HW.
+
init= [KNL]
Format: <full_path>
Run specified binary instead of /sbin/init as init
@@ -1416,10 +1450,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ip= [IP_PNP]
See Documentation/filesystems/nfs/nfsroot.txt.
- ip2= [HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
- See comment before ip2_setup() in
- drivers/char/ip2/ip2base.c.
-
irqfixup [HW]
When an interrupt is not handled search all handlers
for it. Intended to get systems with badly broken
@@ -1692,8 +1722,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
7 (KERN_DEBUG) debug-level messages
log_buf_len=n[KMG] Sets the size of the printk ring buffer,
- in bytes. n must be a power of two. The default
- size is set in the kernel config file.
+ in bytes. n must be a power of two and greater
+ than the minimal size. The minimal size is defined
+ by LOG_BUF_SHIFT kernel config parameter. There is
+ also CONFIG_LOG_CPU_MAX_BUF_SHIFT config parameter
+ that allows to increase the default size depending on
+ the number of CPUs. See init/Kconfig for more details.
logo.nologo [FB] Disables display of the built-in Linux logo.
This may be used to provide more screen space for
@@ -2166,6 +2200,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
and restore using xsave. The kernel will fallback to
enabling legacy floating-point and sse state.
+ noxsaveopt [X86] Disables xsaveopt used in saving x86 extended
+ register states. The kernel will fall back to use
+ xsave to save the states. By using this parameter,
+ performance of saving the states is degraded because
+ xsave doesn't support modified optimization while
+ xsaveopt supports it on xsaveopt enabled systems.
+
+ noxsaves [X86] Disables xsaves and xrstors used in saving and
+ restoring x86 extended register state in compacted
+ form of xsave area. The kernel will fall back to use
+ xsaveopt and xrstor to save and restore the states
+ in standard form of xsave area. By using this
+ parameter, xsave area per process might occupy more
+ memory on xsaves enabled systems.
+
eagerfpu= [X86]
on enable eager fpu restore
off disable eager fpu restore
@@ -2807,6 +2856,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
quiescent states. Units are jiffies, minimum
value is one, and maximum value is HZ.
+ rcutree.rcu_nocb_leader_stride= [KNL]
+ Set the number of NOCB kthread groups, which
+ defaults to the square root of the number of
+ CPUs. Larger numbers reduces the wakeup overhead
+ on the per-CPU grace-period kthreads, but increases
+ that same overhead on each group's leader.
+
rcutree.qhimark= [KNL]
Set threshold of queued RCU callbacks beyond which
batch limiting is disabled.
@@ -3023,6 +3079,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
S [KNL] Run init in single mode
+ s390_iommu= [HW,S390]
+ Set s390 IOTLB flushing mode
+ strict
+ With strict flushing every unmap operation will result in
+ an IOTLB flush. Default is lazy flushing before reuse,
+ which is faster.
+
sa1100ir [NET]
See drivers/net/irda/sa1100_ir.c.
@@ -3697,6 +3760,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Disables the ticketlock slowpath using Xen PV
optimizations.
+ xen_nopv [X86]
+ Disables the PV optimizations forcing the HVM guest to
+ run as generic HVM guest with no PV drivers.
+
xirc2ps_cs= [NET,PCMCIA]
Format:
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
diff --git a/Documentation/laptops/freefall.c b/Documentation/laptops/freefall.c
index aab2ff09e868..5e44b20b1848 100644
--- a/Documentation/laptops/freefall.c
+++ b/Documentation/laptops/freefall.c
@@ -29,15 +29,12 @@ static const char app_name[] = "FREE FALL";
static int set_unload_heads_path(char *device)
{
- char devname[64];
-
if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
return -EINVAL;
- strncpy(devname, device + 5, sizeof(devname) - 1);
strncpy(device_path, device, sizeof(device_path) - 1);
snprintf(unload_heads_path, sizeof(unload_heads_path) - 1,
- "/sys/block/%s/device/unload_heads", devname);
+ "/sys/block/%s/device/unload_heads", device+5);
return 0;
}
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index f1dc4a215593..a4de88fb55f0 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -757,10 +757,14 @@ SMP BARRIER PAIRING
When dealing with CPU-CPU interactions, certain types of memory barrier should
always be paired. A lack of appropriate pairing is almost certainly an error.
-A write barrier should always be paired with a data dependency barrier or read
-barrier, though a general barrier would also be viable. Similarly a read
-barrier or a data dependency barrier should always be paired with at least an
-write barrier, though, again, a general barrier is viable:
+General barriers pair with each other, though they also pair with
+most other types of barriers, albeit without transitivity. An acquire
+barrier pairs with a release barrier, but both may also pair with other
+barriers, including of course general barriers. A write barrier pairs
+with a data dependency barrier, an acquire barrier, a release barrier,
+a read barrier, or a general barrier. Similarly a read barrier or a
+data dependency barrier pairs with a write barrier, an acquire barrier,
+a release barrier, or a general barrier:
CPU 1 CPU 2
=============== ===============
@@ -1893,6 +1897,21 @@ between the STORE to indicate the event and the STORE to set TASK_RUNNING:
<general barrier> STORE current->state
LOAD event_indicated
+To repeat, this write memory barrier is present if and only if something
+is actually awakened. To see this, consider the following sequence of
+events, where X and Y are both initially zero:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ X = 1; STORE event_indicated
+ smp_mb(); wake_up();
+ Y = 1; wait_event(wq, Y == 1);
+ wake_up(); load from Y sees 1, no memory barrier
+ load from X might see 0
+
+In contrast, if a wakeup does occur, CPU 2's load from X would be guaranteed
+to see 1.
+
The available waker functions include:
complete();
diff --git a/Documentation/mic/mic_overview.txt b/Documentation/mic/mic_overview.txt
index b41929224804..77c541802ad9 100644
--- a/Documentation/mic/mic_overview.txt
+++ b/Documentation/mic/mic_overview.txt
@@ -17,35 +17,50 @@ for applications. A key benefit of our solution is that it leverages
the standard virtio framework for network, disk and console devices,
though in our case the virtio framework is used across a PCIe bus.
+MIC PCIe card has a dma controller with 8 channels. These channels are
+shared between the host s/w and the card s/w. 0 to 3 are used by host
+and 4 to 7 by card. As the dma device doesn't show up as PCIe device,
+a virtual bus called mic bus is created and virtual dma devices are
+created on it by the host/card drivers. On host the channels are private
+and used only by the host driver to transfer data for the virtio devices.
+
Here is a block diagram of the various components described above. The
virtio backends are situated on the host rather than the card given better
single threaded performance for the host compared to MIC, the ability of
the host to initiate DMA's to/from the card using the MIC DMA engine and
the fact that the virtio block storage backend can only be on the host.
- |
- +----------+ | +----------+
- | Card OS | | | Host OS |
- +----------+ | +----------+
- |
-+-------+ +--------+ +------+ | +---------+ +--------+ +--------+
-| Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio |
-| Net | |Console | |Block | | |Net | |Console | |Block |
-| Driver| |Driver | |Driver| | |backend | |backend | |backend |
-+-------+ +--------+ +------+ | +---------+ +--------+ +--------+
- | | | | | | |
- | | | |User | | |
- | | | |------|------------|---------|-------
- +-------------------+ |Kernel +--------------------------+
- | | | Virtio over PCIe IOCTLs |
- | | +--------------------------+
- +--------------+ | |
- |Intel MIC | | +---------------+
- |Card Driver | | |Intel MIC |
- +--------------+ | |Host Driver |
- | | +---------------+
- | | |
- +-------------------------------------------------------------+
- | |
- | PCIe Bus |
- +-------------------------------------------------------------+
+ |
+ +----------+ | +----------+
+ | Card OS | | | Host OS |
+ +----------+ | +----------+
+ |
+ +-------+ +--------+ +------+ | +---------+ +--------+ +--------+
+ | Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio |
+ | Net | |Console | |Block | | |Net | |Console | |Block |
+ | Driver| |Driver | |Driver| | |backend | |backend | |backend |
+ +-------+ +--------+ +------+ | +---------+ +--------+ +--------+
+ | | | | | | |
+ | | | |User | | |
+ | | | |------|------------|---------|-------
+ +-------------------+ |Kernel +--------------------------+
+ | | | Virtio over PCIe IOCTLs |
+ | | +--------------------------+
++-----------+ | | | +-----------+
+| MIC DMA | | | | | MIC DMA |
+| Driver | | | | | Driver |
++-----------+ | | | +-----------+
+ | | | | |
++---------------+ | | | +----------------+
+|MIC virtual Bus| | | | |MIC virtual Bus |
++---------------+ | | | +----------------+
+ | | | | |
+ | +--------------+ | +---------------+ |
+ | |Intel MIC | | |Intel MIC | |
+ +---|Card Driver | | |Host Driver | |
+ +--------------+ | +---------------+-----+
+ | | |
+ +-------------------------------------------------------------+
+ | |
+ | PCIe Bus |
+ +-------------------------------------------------------------+
diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss
index 3136c68dad0b..cacbdb0aefb9 100755
--- a/Documentation/mic/mpssd/mpss
+++ b/Documentation/mic/mpssd/mpss
@@ -48,18 +48,18 @@ start()
fi
echo -e $"Starting MPSS Stack"
- echo -e $"Loading MIC_HOST Module"
+ echo -e $"Loading MIC_X100_DMA & MIC_HOST Modules"
- # Ensure the driver is loaded
- if [ ! -d "$sysfs" ]; then
- modprobe mic_host
+ for f in "mic_host" "mic_x100_dma"
+ do
+ modprobe $f
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
failure
echo
return $RETVAL
fi
- fi
+ done
# Start the daemon
echo -n $"Starting MPSSD "
@@ -170,8 +170,8 @@ unload()
stop
sleep 5
- echo -n $"Removing MIC_HOST Module: "
- modprobe -r mic_host
+ echo -n $"Removing MIC_HOST & MIC_X100_DMA Modules: "
+ modprobe -r mic_host mic_x100_dma
RETVAL=$?
[ $RETVAL -ne 0 ] && failure || success
echo
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 9c723ecd0025..eeb5b2e97bed 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -542,10 +542,10 @@ mode
XOR policy: Transmit based on the selected transmit
hash policy. The default policy is a simple [(source
- MAC address XOR'd with destination MAC address) modulo
- slave count]. Alternate transmit policies may be
- selected via the xmit_hash_policy option, described
- below.
+ MAC address XOR'd with destination MAC address XOR
+ packet type ID) modulo slave count]. Alternate transmit
+ policies may be selected via the xmit_hash_policy option,
+ described below.
This mode provides load balancing and fault tolerance.
@@ -801,10 +801,11 @@ xmit_hash_policy
layer2
- Uses XOR of hardware MAC addresses to generate the
- hash. The formula is
+ Uses XOR of hardware MAC addresses and packet type ID
+ field to generate the hash. The formula is
- (source MAC XOR destination MAC) modulo slave count
+ hash = source MAC XOR destination MAC XOR packet type ID
+ slave number = hash modulo slave count
This algorithm will place all traffic to a particular
network peer on the same slave.
@@ -819,7 +820,7 @@ xmit_hash_policy
Uses XOR of hardware MAC addresses and IP addresses to
generate the hash. The formula is
- hash = source MAC XOR destination MAC
+ hash = source MAC XOR destination MAC XOR packet type ID
hash = hash XOR source IP XOR destination IP
hash = hash XOR (hash RSHIFT 16)
hash = hash XOR (hash RSHIFT 8)
@@ -2301,13 +2302,13 @@ broadcast: Like active-backup, there is not much advantage to this
bandwidth.
Additionally, the linux bonding 802.3ad implementation
- distributes traffic by peer (using an XOR of MAC addresses),
- so in a "gatewayed" configuration, all outgoing traffic will
- generally use the same device. Incoming traffic may also end
- up on a single device, but that is dependent upon the
- balancing policy of the peer's 8023.ad implementation. In a
- "local" configuration, traffic will be distributed across the
- devices in the bond.
+ distributes traffic by peer (using an XOR of MAC addresses
+ and packet type ID), so in a "gatewayed" configuration, all
+ outgoing traffic will generally use the same device. Incoming
+ traffic may also end up on a single device, but that is
+ dependent upon the balancing policy of the peer's 8023.ad
+ implementation. In a "local" configuration, traffic will be
+ distributed across the devices in the bond.
Finally, the 802.3ad mode mandates the use of the MII monitor,
therefore, the ARP monitor is not available in this mode.
diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt
index ee78eba78a9d..c48a9704bda8 100644
--- a/Documentation/networking/filter.txt
+++ b/Documentation/networking/filter.txt
@@ -586,12 +586,12 @@ team driver's classifier for its load-balancing mode, netfilter's xt_bpf
extension, PTP dissector/classifier, and much more. They are all internally
converted by the kernel into the new instruction set representation and run
in the eBPF interpreter. For in-kernel handlers, this all works transparently
-by using sk_unattached_filter_create() for setting up the filter, resp.
-sk_unattached_filter_destroy() for destroying it. The macro
-SK_RUN_FILTER(filter, ctx) transparently invokes eBPF interpreter or JITed
-code to run the filter. 'filter' is a pointer to struct sk_filter that we
-got from sk_unattached_filter_create(), and 'ctx' the given context (e.g.
-skb pointer). All constraints and restrictions from sk_chk_filter() apply
+by using bpf_prog_create() for setting up the filter, resp.
+bpf_prog_destroy() for destroying it. The macro
+BPF_PROG_RUN(filter, ctx) transparently invokes eBPF interpreter or JITed
+code to run the filter. 'filter' is a pointer to struct bpf_prog that we
+got from bpf_prog_create(), and 'ctx' the given context (e.g.
+skb pointer). All constraints and restrictions from bpf_check_classic() apply
before a conversion to the new layout is being done behind the scenes!
Currently, the classic BPF format is being used for JITing on most of the
diff --git a/Documentation/networking/i40e.txt b/Documentation/networking/i40e.txt
index f737273c6dc1..a251bf4fe9c9 100644
--- a/Documentation/networking/i40e.txt
+++ b/Documentation/networking/i40e.txt
@@ -69,8 +69,11 @@ Additional Configurations
FCoE
----
- Fiber Channel over Ethernet (FCoE) hardware offload is not currently
- supported.
+ The driver supports Fiber Channel over Ethernet (FCoE) and Data Center
+ Bridging (DCB) functionality. Configuring DCB and FCoE is outside the scope
+ of this driver doc. Refer to http://www.open-fcoe.org/ for FCoE project
+ information and http://www.open-lldp.org/ or email list
+ e1000-eedc@lists.sourceforge.net for DCB information.
MAC and VLAN anti-spoofing feature
----------------------------------
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ab42c95f9985..29a93518bf18 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -101,19 +101,17 @@ ipfrag_high_thresh - INTEGER
Maximum memory used to reassemble IP fragments. When
ipfrag_high_thresh bytes of memory is allocated for this purpose,
the fragment handler will toss packets until ipfrag_low_thresh
- is reached.
+ is reached. This also serves as a maximum limit to namespaces
+ different from the initial one.
ipfrag_low_thresh - INTEGER
- See ipfrag_high_thresh
+ Maximum memory used to reassemble IP fragments before the kernel
+ begins to remove incomplete fragment queues to free up resources.
+ The kernel still accepts new fragments for defragmentation.
ipfrag_time - INTEGER
Time in seconds to keep an IP fragment in memory.
-ipfrag_secret_interval - INTEGER
- Regeneration interval (in seconds) of the hash secret (or lifetime
- for the hash secret) for IP fragments.
- Default: 600
-
ipfrag_max_dist - INTEGER
ipfrag_max_dist is a non-negative integer value which defines the
maximum "disorder" which is allowed among fragments which share a
@@ -1132,6 +1130,15 @@ flowlabel_consistency - BOOLEAN
FALSE: disabled
Default: TRUE
+auto_flowlabels - BOOLEAN
+ Automatically generate flow labels based based on a flow hash
+ of the packet. This allows intermediate devices, such as routers,
+ to idenfify packet flows for mechanisms like Equal Cost Multipath
+ Routing (see RFC 6438).
+ TRUE: enabled
+ FALSE: disabled
+ Default: false
+
anycast_src_echo_reply - BOOLEAN
Controls the use of anycast addresses as source addresses for ICMPv6
echo reply
@@ -1153,11 +1160,6 @@ ip6frag_low_thresh - INTEGER
ip6frag_time - INTEGER
Time in seconds to keep an IPv6 fragment in memory.
-ip6frag_secret_interval - INTEGER
- Regeneration interval (in seconds) of the hash secret (or lifetime
- for the hash secret) for IPv6 fragments.
- Default: 600
-
conf/default/*:
Change the interface-specific default settings.
@@ -1210,6 +1212,18 @@ accept_ra_defrtr - BOOLEAN
Functional default: enabled if accept_ra is enabled.
disabled if accept_ra is disabled.
+accept_ra_from_local - BOOLEAN
+ Accept RA with source-address that is found on local machine
+ if the RA is otherwise proper and able to be accepted.
+ Default is to NOT accept these as it may be an un-intended
+ network loop.
+
+ Functional default:
+ enabled if accept_ra_from_local is enabled
+ on a specific interface.
+ disabled if accept_ra_from_local is disabled
+ on a specific interface.
+
accept_ra_pinfo - BOOLEAN
Learn Prefix Information in Router Advertisement.
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 38112d512f47..a6d7cb91069e 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -1008,14 +1008,9 @@ hardware timestamps to be used. Note: you may need to enable the generation
of hardware timestamps with SIOCSHWTSTAMP (see related information from
Documentation/networking/timestamping.txt).
-PACKET_TIMESTAMP accepts the same integer bit field as
-SO_TIMESTAMPING. However, only the SOF_TIMESTAMPING_SYS_HARDWARE
-and SOF_TIMESTAMPING_RAW_HARDWARE values are recognized by
-PACKET_TIMESTAMP. SOF_TIMESTAMPING_SYS_HARDWARE takes precedence over
-SOF_TIMESTAMPING_RAW_HARDWARE if both bits are set.
-
- int req = 0;
- req |= SOF_TIMESTAMPING_SYS_HARDWARE;
+PACKET_TIMESTAMP accepts the same integer bit field as SO_TIMESTAMPING:
+
+ int req = SOF_TIMESTAMPING_RAW_HARDWARE;
setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req))
For the mmap(2)ed ring buffers, such timestamps are stored in the
@@ -1023,14 +1018,13 @@ tpacket{,2,3}_hdr structure's tp_sec and tp_{n,u}sec members. To determine
what kind of timestamp has been reported, the tp_status field is binary |'ed
with the following possible bits ...
- TP_STATUS_TS_SYS_HARDWARE
TP_STATUS_TS_RAW_HARDWARE
TP_STATUS_TS_SOFTWARE
... that are equivalent to its SOF_TIMESTAMPING_* counterparts. For the
-RX_RING, if none of those 3 are set (i.e. PACKET_TIMESTAMP is not set),
-then this means that a software fallback was invoked *within* PF_PACKET's
-processing code (less precise).
+RX_RING, if neither is set (i.e. PACKET_TIMESTAMP is not set), then a
+software fallback was invoked *within* PF_PACKET's processing code (less
+precise).
Getting timestamps for the TX_RING works as follows: i) fill the ring frames,
ii) call sendto() e.g. in blocking mode, iii) wait for status of relevant
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 3544c98401fd..e839e7efc835 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -272,6 +272,8 @@ Writing a PHY driver
txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
set_wol: Enable Wake-on-LAN at the PHY level
get_wol: Get the Wake-on-LAN status at the PHY level
+ read_mmd_indirect: Read PHY MMD indirect register
+ write_mmd_indirect: Write PHY MMD indirect register
Of these, only config_aneg and read_status are required to be
assigned by the driver code. The rest are optional. Also, it is
@@ -284,7 +286,21 @@ Writing a PHY driver
Feel free to look at the Marvell, Cicada, and Davicom drivers in
drivers/net/phy/ for examples (the lxt and qsemi drivers have
- not been tested as of this writing)
+ not been tested as of this writing).
+
+ The PHY's MMD register accesses are handled by the PAL framework
+ by default, but can be overridden by a specific PHY driver if
+ required. This could be the case if a PHY was released for
+ manufacturing before the MMD PHY register definitions were
+ standardized by the IEEE. Most modern PHYs will be able to use
+ the generic PAL framework for accessing the PHY's MMD registers.
+ An example of such usage is for Energy Efficient Ethernet support,
+ implemented in the PAL. This support uses the PAL to access MMD
+ registers for EEE query and configuration if the PHY supports
+ the IEEE standard access mechanisms, or can use the PHY's specific
+ access interfaces if overridden by the specific PHY driver. See
+ the Micrel driver in drivers/net/phy/ for an example of how this
+ can be implemented.
Board Fixups
diff --git a/Documentation/networking/pktgen.txt b/Documentation/networking/pktgen.txt
index 0e30c7845b2b..0dffc6e37902 100644
--- a/Documentation/networking/pktgen.txt
+++ b/Documentation/networking/pktgen.txt
@@ -24,6 +24,34 @@ For monitoring and control pktgen creates:
/proc/net/pktgen/ethX
+Tuning NIC for max performance
+==============================
+
+The default NIC setting are (likely) not tuned for pktgen's artificial
+overload type of benchmarking, as this could hurt the normal use-case.
+
+Specifically increasing the TX ring buffer in the NIC:
+ # ethtool -G ethX tx 1024
+
+A larger TX ring can improve pktgen's performance, while it can hurt
+in the general case, 1) because the TX ring buffer might get larger
+than the CPUs L1/L2 cache, 2) because it allow more queueing in the
+NIC HW layer (which is bad for bufferbloat).
+
+One should be careful to conclude, that packets/descriptors in the HW
+TX ring cause delay. Drivers usually delay cleaning up the
+ring-buffers (for various performance reasons), thus packets stalling
+the TX ring, might just be waiting for cleanup.
+
+This cleanup issues is specifically the case, for the driver ixgbe
+(Intel 82599 chip). This driver (ixgbe) combine TX+RX ring cleanups,
+and the cleanup interval is affected by the ethtool --coalesce setting
+of parameter "rx-usecs".
+
+For ixgbe use e.g "30" resulting in approx 33K interrupts/sec (1/30*10^6):
+ # ethtool -C ethX rx-usecs 30
+
+
Viewing threads
===============
/proc/net/pktgen/kpktgend_0
diff --git a/Documentation/networking/timestamping.txt b/Documentation/networking/timestamping.txt
index bc3554124903..897f942b976b 100644
--- a/Documentation/networking/timestamping.txt
+++ b/Documentation/networking/timestamping.txt
@@ -40,7 +40,7 @@ the set bits correspond to data that is available, then the control
message will not be generated:
SOF_TIMESTAMPING_SOFTWARE: report systime if available
-SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available
+SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available (deprecated)
SOF_TIMESTAMPING_RAW_HARDWARE: report hwtimeraw if available
It is worth noting that timestamps may be collected for reasons other
@@ -88,13 +88,12 @@ hwtimeraw is the original hardware time stamp. Filled in if
SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its
relation to system time should be made.
-hwtimetrans is the hardware time stamp transformed so that it
-corresponds as good as possible to system time. This correlation is
-not perfect; as a consequence, sorting packets received via different
-NICs by their hwtimetrans may differ from the order in which they were
-received. hwtimetrans may be non-monotonic even for the same NIC.
-Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
-by the network device and will be empty without that support.
+hwtimetrans is always zero. This field is deprecated. It used to hold
+hw timestamps converted to system time. Instead, expose the hardware
+clock device on the NIC directly as a HW PTP clock source, to allow
+time conversion in userspace and optionally synchronize system time
+with a userspace PTP stack such as linuxptp. For the PTP clock API,
+see Documentation/ptp/ptp.txt.
SIOCSHWTSTAMP, SIOCGHWTSTAMP:
@@ -185,7 +184,6 @@ struct skb_shared_hwtstamps {
* since arbitrary point in time
*/
ktime_t hwtstamp;
- ktime_t syststamp; /* hwtstamp transformed to system time base */
};
Time stamps for outgoing packets are to be generated as follows:
diff --git a/Documentation/networking/timestamping/timestamping.c b/Documentation/networking/timestamping/timestamping.c
index 8ba82bfe6a33..5cdfd743447b 100644
--- a/Documentation/networking/timestamping/timestamping.c
+++ b/Documentation/networking/timestamping/timestamping.c
@@ -76,7 +76,6 @@ static void usage(const char *error)
" SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
" SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
" SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
- " SOF_TIMESTAMPING_SYS_HARDWARE - request reporting of transformed HW time stamps\n"
" SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
" SIOCGSTAMP - check last socket time stamp\n"
" SIOCGSTAMPNS - more accurate socket time stamp\n");
@@ -202,9 +201,7 @@ static void printpacket(struct msghdr *msg, int res,
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
stamp++;
- printf("HW transformed %ld.%09ld ",
- (long)stamp->tv_sec,
- (long)stamp->tv_nsec);
+ /* skip deprecated HW transformed */
stamp++;
printf("HW raw %ld.%09ld",
(long)stamp->tv_sec,
@@ -361,8 +358,6 @@ int main(int argc, char **argv)
so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SYS_HARDWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_SYS_HARDWARE;
else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
else
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index e3155995ddd8..beefb9f82902 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -268,6 +268,8 @@ characters, each representing a particular tainted value.
14: 'E' if an unsigned module has been loaded in a kernel supporting
module signature.
+ 15: 'L' if a soft lockup has previously occurred on the system.
+
The primary reason for the 'Tainted: ' string is to tell kernel
debuggers if this is a clean kernel or if anything unusual has
occurred. Tainting is permanent: even if an offending module is
diff --git a/Documentation/phy.txt b/Documentation/phy.txt
index ebff6ee52441..c6594af94d25 100644
--- a/Documentation/phy.txt
+++ b/Documentation/phy.txt
@@ -53,10 +53,12 @@ unregister the PHY.
The PHY driver should create the PHY in order for other peripheral controllers
to make use of it. The PHY framework provides 2 APIs to create the PHY.
-struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
- struct phy_init_data *init_data);
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
- struct phy_init_data *init_data);
+struct phy *phy_create(struct device *dev, struct device_node *node,
+ const struct phy_ops *ops,
+ struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+ const struct phy_ops *ops,
+ struct phy_init_data *init_data);
The PHY drivers can use one of the above 2 APIs to create the PHY by passing
the device pointer, phy ops and init_data.
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt
index a9adad828cdc..c6279c2be47c 100644
--- a/Documentation/power/opp.txt
+++ b/Documentation/power/opp.txt
@@ -51,9 +51,6 @@ Typical usage of the OPP library is as follows:
SoC framework -> modifies on required cases certain OPPs -> OPP layer
-> queries to search/retrieve information ->
-Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP
-to make the OPP layer available.
-
OPP layer expects each domain to be represented by a unique device pointer. SoC
framework registers a set of initial OPPs per device with the OPP layer. This
list is expected to be an optimally small number typically around 5 per device.
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index 89a8816990ff..48cff881cb8a 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -118,6 +118,10 @@ relative, time-based measurements.
CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger.
CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the
power supply object.
+INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates
+the current drawn from a charging source.
+CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge
+condition.
CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
@@ -140,6 +144,8 @@ TEMP_ALERT_MAX - maximum battery temperature alert.
TEMP_AMBIENT - ambient temperature.
TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert.
TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert.
+TEMP_MIN - minimum operatable temperature
+TEMP_MAX - maximum operatable temperature
TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
while battery powers a load)
diff --git a/Documentation/power/regulator/consumer.txt b/Documentation/power/regulator/consumer.txt
index 55c4175d8099..81c0e2b49cd8 100644
--- a/Documentation/power/regulator/consumer.txt
+++ b/Documentation/power/regulator/consumer.txt
@@ -180,3 +180,38 @@ int regulator_unregister_notifier(struct regulator *regulator,
Regulators use the kernel notifier framework to send event to their interested
consumers.
+
+7. Regulator Direct Register Access
+===================================
+Some kinds of power management hardware or firmware are designed such that
+they need to do low-level hardware access to regulators, with no involvement
+from the kernel. Examples of such devices are:
+
+- clocksource with a voltage-controlled oscillator and control logic to change
+ the supply voltage over I2C to achieve a desired output clock rate
+- thermal management firmware that can issue an arbitrary I2C transaction to
+ perform system poweroff during overtemperature conditions
+
+To set up such a device/firmware, various parameters like I2C address of the
+regulator, addresses of various regulator registers etc. need to be configured
+to it. The regulator framework provides the following helpers for querying
+these details.
+
+Bus-specific details, like I2C addresses or transfer rates are handled by the
+regmap framework. To get the regulator's regmap (if supported), use :-
+
+struct regmap *regulator_get_regmap(struct regulator *regulator);
+
+To obtain the hardware register offset and bitmask for the regulator's voltage
+selector register, use :-
+
+int regulator_get_hardware_vsel_register(struct regulator *regulator,
+ unsigned *vsel_reg,
+ unsigned *vsel_mask);
+
+To convert a regulator framework voltage selector code (used by
+regulator_list_voltage) to a hardware-specific voltage selector that can be
+directly written to the voltage selector register, use :-
+
+int regulator_list_hardware_vsel(struct regulator *regulator,
+ unsigned selector);
diff --git a/Documentation/powerpc/00-INDEX b/Documentation/powerpc/00-INDEX
index 6db73df04278..a68784d0a1ee 100644
--- a/Documentation/powerpc/00-INDEX
+++ b/Documentation/powerpc/00-INDEX
@@ -17,8 +17,6 @@ firmware-assisted-dump.txt
- Documentation on the firmware assisted dump mechanism "fadump".
hvcs.txt
- IBM "Hypervisor Virtual Console Server" Installation Guide
-kvm_440.txt
- - Various notes on the implementation of KVM for PowerPC 440.
mpc52xx.txt
- Linux 2.6.x on MPC52xx family
pmu-ebb.txt
diff --git a/Documentation/powerpc/kvm_440.txt b/Documentation/powerpc/kvm_440.txt
deleted file mode 100644
index c02a003fa03a..000000000000
--- a/Documentation/powerpc/kvm_440.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-Hollis Blanchard <hollisb@us.ibm.com>
-15 Apr 2008
-
-Various notes on the implementation of KVM for PowerPC 440:
-
-To enforce isolation, host userspace, guest kernel, and guest userspace all
-run at user privilege level. Only the host kernel runs in supervisor mode.
-Executing privileged instructions in the guest traps into KVM (in the host
-kernel), where we decode and emulate them. Through this technique, unmodified
-440 Linux kernels can be run (slowly) as guests. Future performance work will
-focus on reducing the overhead and frequency of these traps.
-
-The usual code flow is started from userspace invoking an "run" ioctl, which
-causes KVM to switch into guest context. We use IVPR to hijack the host
-interrupt vectors while running the guest, which allows us to direct all
-interrupts to kvmppc_handle_interrupt(). At this point, we could either
-- handle the interrupt completely (e.g. emulate "mtspr SPRG0"), or
-- let the host interrupt handler run (e.g. when the decrementer fires), or
-- return to host userspace (e.g. when the guest performs device MMIO)
-
-Address spaces: We take advantage of the fact that Linux doesn't use the AS=1
-address space (in host or guest), which gives us virtual address space to use
-for guest mappings. While the guest is running, the host kernel remains mapped
-in AS=0, but the guest can only use AS=1 mappings.
-
-TLB entries: The TLB entries covering the host linear mapping remain
-present while running the guest. This reduces the overhead of lightweight
-exits, which are handled by KVM running in the host kernel. We keep three
-copies of the TLB:
- - guest TLB: contents of the TLB as the guest sees it
- - shadow TLB: the TLB that is actually in hardware while guest is running
- - host TLB: to restore TLB state when context switching guest -> host
-When a TLB miss occurs because a mapping was not present in the shadow TLB,
-but was present in the guest TLB, KVM handles the fault without invoking the
-guest. Large guest pages are backed by multiple 4KB shadow pages through this
-mechanism.
-
-IO: MMIO and DCR accesses are emulated by userspace. We use virtio for network
-and block IO, so those drivers must be enabled in the guest. It's possible
-that some qemu device emulation (e.g. e1000 or rtl8139) may also work with
-little effort.
diff --git a/Documentation/rapidio/tsi721.txt b/Documentation/rapidio/tsi721.txt
index 335f3c6087dc..626052f403bb 100644
--- a/Documentation/rapidio/tsi721.txt
+++ b/Documentation/rapidio/tsi721.txt
@@ -20,13 +20,26 @@ II. Known problems
None.
-III. To do
+III. DMA Engine Support
- Add DMA data transfers (non-messaging).
- Add inbound region (SRIO-to-PCIe) mapping.
+Tsi721 mport driver supports DMA data transfers between local system memory and
+remote RapidIO devices. This functionality is implemented according to SLAVE
+mode API defined by common Linux kernel DMA Engine framework.
+
+Depending on system requirements RapidIO DMA operations can be included/excluded
+by setting CONFIG_RAPIDIO_DMA_ENGINE option. Tsi721 miniport driver uses seven
+out of eight available BDMA channels to support DMA data transfers.
+One BDMA channel is reserved for generation of maintenance read/write requests.
+
+If Tsi721 mport driver have been built with RAPIDIO_DMA_ENGINE support included,
+this driver will accept DMA-specific module parameter:
+ "dma_desc_per_channel" - defines number of hardware buffer descriptors used by
+ each BDMA channel of Tsi721 (by default - 128).
IV. Version History
+ 1.1.0 - DMA operations re-worked to support data scatter/gather lists larger
+ than hardware buffer descriptors ring.
1.0.0 - Initial driver release.
V. License
diff --git a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
index cda5f8fa2c66..1d508dcbf859 100644
--- a/Documentation/scsi/ncr53c8xx.txt
+++ b/Documentation/scsi/ncr53c8xx.txt
@@ -1095,7 +1095,7 @@ SCSI_NCR_SETUP_FORCE_SYNC_NEGO (default: not defined)
SCSI_NCR_SETUP_MASTER_PARITY (default: defined)
If defined, master parity checking is enabled.
-SCSI_NCR_SETUP_MASTER_PARITY (default: defined)
+SCSI_NCR_SETUP_SCSI_PARITY (default: defined)
If defined, SCSI parity checking is enabled.
SCSI_NCR_PROFILE_SUPPORT (default: not defined)
diff --git a/Documentation/scsi/tmscsim.txt b/Documentation/scsi/tmscsim.txt
index 3303d218b32e..0810132772a8 100644
--- a/Documentation/scsi/tmscsim.txt
+++ b/Documentation/scsi/tmscsim.txt
@@ -317,8 +317,6 @@ Each of the parameters is a number, containing the described information:
4 0x10 16 Immediate return on BIOS seek command. (Not used)
(*)5 0x20 32 Check for LUNs >= 1.
- The default for LUN Check depends on CONFIG_SCSI_MULTI_LUN.
-
* TaggedCmnds is a number indicating the maximum number of Tagged Commands.
It is the binary logarithm - 1 of the actual number. Max is 4 (32).
Value Number of Tagged Commands
diff --git a/Documentation/security/LSM.txt b/Documentation/security/LSM.txt
index c335a763a2ed..3db7e671c440 100644
--- a/Documentation/security/LSM.txt
+++ b/Documentation/security/LSM.txt
@@ -22,7 +22,7 @@ system, building their checks on top of the defined capability hooks.
For more details on capabilities, see capabilities(7) in the Linux
man-pages project.
-Based on http://kerneltrap.org/Linux/Documenting_Security_Module_Intent,
+Based on https://lkml.org/lkml/2007/10/26/215,
a new LSM is accepted into the kernel when its intent (a description of
what it tries to protect against and in what cases one would expect to
use it) has been appropriately documented in Documentation/security/.
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index a4c33f1a7c6d..8727c194ca16 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -1150,20 +1150,24 @@ The structure has a number of fields, some of which are mandatory:
const void *data;
size_t datalen;
size_t quotalen;
+ time_t expiry;
};
Before calling the method, the caller will fill in data and datalen with
the payload blob parameters; quotalen will be filled in with the default
- quota size from the key type and the rest will be cleared.
+ quota size from the key type; expiry will be set to TIME_T_MAX and the
+ rest will be cleared.
If a description can be proposed from the payload contents, that should be
attached as a string to the description field. This will be used for the
key description if the caller of add_key() passes NULL or "".
The method can attach anything it likes to type_data[] and payload. These
- are merely passed along to the instantiate() or update() operations.
+ are merely passed along to the instantiate() or update() operations. If
+ set, the expiry time will be applied to the key if it is instantiated from
+ this data.
- The method should return 0 if success ful or a negative error code
+ The method should return 0 if successful or a negative error code
otherwise.
@@ -1172,7 +1176,9 @@ The structure has a number of fields, some of which are mandatory:
This method is only required if the preparse() method is provided,
otherwise it is unused. It cleans up anything attached to the
description, type_data and payload fields of the key_preparsed_payload
- struct as filled in by the preparse() method.
+ struct as filled in by the preparse() method. It will always be called
+ after preparse() returns successfully, even if instantiate() or update()
+ succeed.
(*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 7ccf933bfbe0..48148d6d9307 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-------------------
Module for sound cards based on the Asus AV66/AV100/AV200 chips,
- i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
- HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+ i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
+ Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
This module supports autoprobe and multiple cards.
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index d1ab5e17eb13..a5e754714344 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -284,6 +284,11 @@ STAC92HD83*
hp-zephyr HP Zephyr
hp-led HP with broken BIOS for mute LED
hp-inv-led HP with broken BIOS for inverted mute LED
+ hp-mic-led HP with mic-mute LED
+ headset-jack Dell Latitude with a 4-pin headset jack
+ hp-envy-bass Pin fixup for HP Envy bass speaker (NID 0x0f)
+ hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
+ hp-bnb13-eq Hardware equalizer setup for HP laptops
auto BIOS setup (default)
STAC92HD95
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index cbc2f03056bd..aee73e78c7d4 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -29,6 +29,9 @@ Rules on what kind of patches are accepted, and which ones are not, into the
Procedure for submitting patches to the -stable tree:
+ - If the patch covers files in net/ or drivers/net please follow netdev stable
+ submission guidelines as described in
+ Documentation/networking/netdev-FAQ.txt
- Send the patch, after verifying that it follows the above rules, to
stable@vger.kernel.org. You must note the upstream commit ID in the
changelog of your submission, as well as the kernel version you wish
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index c14374e71775..f79eb9666379 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -826,6 +826,7 @@ can be ORed together:
4096 - An out-of-tree module has been loaded.
8192 - An unsigned module has been loaded in a kernel supporting module
signature.
+16384 - A soft lockup has previously occurred on the system.
==============================================================
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX
index 6d042dc1cce0..ee212a27772f 100644
--- a/Documentation/timers/00-INDEX
+++ b/Documentation/timers/00-INDEX
@@ -12,6 +12,8 @@ Makefile
- Build and link hpet_example
NO_HZ.txt
- Summary of the different methods for the scheduler clock-interrupts management.
+timekeeping.txt
+ - Clock sources, clock events, sched_clock() and delay timer notes
timers-howto.txt
- how to insert delays in the kernel the right (tm) way.
timer_stats.txt
diff --git a/Documentation/timers/timekeeping.txt b/Documentation/timers/timekeeping.txt
new file mode 100644
index 000000000000..f3a8cf28f802
--- /dev/null
+++ b/Documentation/timers/timekeeping.txt
@@ -0,0 +1,179 @@
+Clock sources, Clock events, sched_clock() and delay timers
+-----------------------------------------------------------
+
+This document tries to briefly explain some basic kernel timekeeping
+abstractions. It partly pertains to the drivers usually found in
+drivers/clocksource in the kernel tree, but the code may be spread out
+across the kernel.
+
+If you grep through the kernel source you will find a number of architecture-
+specific implementations of clock sources, clockevents and several likewise
+architecture-specific overrides of the sched_clock() function and some
+delay timers.
+
+To provide timekeeping for your platform, the clock source provides
+the basic timeline, whereas clock events shoot interrupts on certain points
+on this timeline, providing facilities such as high-resolution timers.
+sched_clock() is used for scheduling and timestamping, and delay timers
+provide an accurate delay source using hardware counters.
+
+
+Clock sources
+-------------
+
+The purpose of the clock source is to provide a timeline for the system that
+tells you where you are in time. For example issuing the command 'date' on
+a Linux system will eventually read the clock source to determine exactly
+what time it is.
+
+Typically the clock source is a monotonic, atomic counter which will provide
+n bits which count from 0 to 2^(n-1) and then wraps around to 0 and start over.
+It will ideally NEVER stop ticking as long as the system is running. It
+may stop during system suspend.
+
+The clock source shall have as high resolution as possible, and the frequency
+shall be as stable and correct as possible as compared to a real-world wall
+clock. It should not move unpredictably back and forth in time or miss a few
+cycles here and there.
+
+It must be immune to the kind of effects that occur in hardware where e.g.
+the counter register is read in two phases on the bus lowest 16 bits first
+and the higher 16 bits in a second bus cycle with the counter bits
+potentially being updated in between leading to the risk of very strange
+values from the counter.
+
+When the wall-clock accuracy of the clock source isn't satisfactory, there
+are various quirks and layers in the timekeeping code for e.g. synchronizing
+the user-visible time to RTC clocks in the system or against networked time
+servers using NTP, but all they do basically is update an offset against
+the clock source, which provides the fundamental timeline for the system.
+These measures does not affect the clock source per se, they only adapt the
+system to the shortcomings of it.
+
+The clock source struct shall provide means to translate the provided counter
+into a nanosecond value as an unsigned long long (unsigned 64 bit) number.
+Since this operation may be invoked very often, doing this in a strict
+mathematical sense is not desirable: instead the number is taken as close as
+possible to a nanosecond value using only the arithmetic operations
+multiply and shift, so in clocksource_cyc2ns() you find:
+
+ ns ~= (clocksource * mult) >> shift
+
+You will find a number of helper functions in the clock source code intended
+to aid in providing these mult and shift values, such as
+clocksource_khz2mult(), clocksource_hz2mult() that help determine the
+mult factor from a fixed shift, and clocksource_register_hz() and
+clocksource_register_khz() which will help out assigning both shift and mult
+factors using the frequency of the clock source as the only input.
+
+For real simple clock sources accessed from a single I/O memory location
+there is nowadays even clocksource_mmio_init() which will take a memory
+location, bit width, a parameter telling whether the counter in the
+register counts up or down, and the timer clock rate, and then conjure all
+necessary parameters.
+
+Since a 32-bit counter at say 100 MHz will wrap around to zero after some 43
+seconds, the code handling the clock source will have to compensate for this.
+That is the reason why the clock source struct also contains a 'mask'
+member telling how many bits of the source are valid. This way the timekeeping
+code knows when the counter will wrap around and can insert the necessary
+compensation code on both sides of the wrap point so that the system timeline
+remains monotonic.
+
+
+Clock events
+------------
+
+Clock events are the conceptual reverse of clock sources: they take a
+desired time specification value and calculate the values to poke into
+hardware timer registers.
+
+Clock events are orthogonal to clock sources. The same hardware
+and register range may be used for the clock event, but it is essentially
+a different thing. The hardware driving clock events has to be able to
+fire interrupts, so as to trigger events on the system timeline. On an SMP
+system, it is ideal (and customary) to have one such event driving timer per
+CPU core, so that each core can trigger events independently of any other
+core.
+
+You will notice that the clock event device code is based on the same basic
+idea about translating counters to nanoseconds using mult and shift
+arithmetic, and you find the same family of helper functions again for
+assigning these values. The clock event driver does not need a 'mask'
+attribute however: the system will not try to plan events beyond the time
+horizon of the clock event.
+
+
+sched_clock()
+-------------
+
+In addition to the clock sources and clock events there is a special weak
+function in the kernel called sched_clock(). This function shall return the
+number of nanoseconds since the system was started. An architecture may or
+may not provide an implementation of sched_clock() on its own. If a local
+implementation is not provided, the system jiffy counter will be used as
+sched_clock().
+
+As the name suggests, sched_clock() is used for scheduling the system,
+determining the absolute timeslice for a certain process in the CFS scheduler
+for example. It is also used for printk timestamps when you have selected to
+include time information in printk for things like bootcharts.
+
+Compared to clock sources, sched_clock() has to be very fast: it is called
+much more often, especially by the scheduler. If you have to do trade-offs
+between accuracy compared to the clock source, you may sacrifice accuracy
+for speed in sched_clock(). It however requires some of the same basic
+characteristics as the clock source, i.e. it should be monotonic.
+
+The sched_clock() function may wrap only on unsigned long long boundaries,
+i.e. after 64 bits. Since this is a nanosecond value this will mean it wraps
+after circa 585 years. (For most practical systems this means "never".)
+
+If an architecture does not provide its own implementation of this function,
+it will fall back to using jiffies, making its maximum resolution 1/HZ of the
+jiffy frequency for the architecture. This will affect scheduling accuracy
+and will likely show up in system benchmarks.
+
+The clock driving sched_clock() may stop or reset to zero during system
+suspend/sleep. This does not matter to the function it serves of scheduling
+events on the system. However it may result in interesting timestamps in
+printk().
+
+The sched_clock() function should be callable in any context, IRQ- and
+NMI-safe and return a sane value in any context.
+
+Some architectures may have a limited set of time sources and lack a nice
+counter to derive a 64-bit nanosecond value, so for example on the ARM
+architecture, special helper functions have been created to provide a
+sched_clock() nanosecond base from a 16- or 32-bit counter. Sometimes the
+same counter that is also used as clock source is used for this purpose.
+
+On SMP systems, it is crucial for performance that sched_clock() can be called
+independently on each CPU without any synchronization performance hits.
+Some hardware (such as the x86 TSC) will cause the sched_clock() function to
+drift between the CPUs on the system. The kernel can work around this by
+enabling the CONFIG_HAVE_UNSTABLE_SCHED_CLOCK option. This is another aspect
+that makes sched_clock() different from the ordinary clock source.
+
+
+Delay timers (some architectures only)
+--------------------------------------
+
+On systems with variable CPU frequency, the various kernel delay() functions
+will sometimes behave strangely. Basically these delays usually use a hard
+loop to delay a certain number of jiffy fractions using a "lpj" (loops per
+jiffy) value, calibrated on boot.
+
+Let's hope that your system is running on maximum frequency when this value
+is calibrated: as an effect when the frequency is geared down to half the
+full frequency, any delay() will be twice as long. Usually this does not
+hurt, as you're commonly requesting that amount of delay *or more*. But
+basically the semantics are quite unpredictable on such systems.
+
+Enter timer-based delays. Using these, a timer read may be used instead of
+a hard-coded loop for providing the desired delay.
+
+This is done by declaring a struct delay_timer and assigning the appropriate
+function pointers and rate settings for this delay timer.
+
+This is available on some architectures like OpenRISC or ARM.
diff --git a/Documentation/trace/ftrace-design.txt b/Documentation/trace/ftrace-design.txt
index 3f669b9e8852..dd5f916b351d 100644
--- a/Documentation/trace/ftrace-design.txt
+++ b/Documentation/trace/ftrace-design.txt
@@ -102,30 +102,6 @@ extern void mcount(void);
EXPORT_SYMBOL(mcount);
-HAVE_FUNCTION_TRACE_MCOUNT_TEST
--------------------------------
-
-This is an optional optimization for the normal case when tracing is turned off
-in the system. If you do not enable this Kconfig option, the common ftrace
-code will take care of doing the checking for you.
-
-To support this feature, you only need to check the function_trace_stop
-variable in the mcount function. If it is non-zero, there is no tracing to be
-done at all, so you can return.
-
-This additional pseudo code would simply be:
-void mcount(void)
-{
- /* save any bare state needed in order to do initial checking */
-
-+ if (function_trace_stop)
-+ return;
-
- extern void (*ftrace_trace_function)(unsigned long, unsigned long);
- if (ftrace_trace_function != ftrace_stub)
-...
-
-
HAVE_FUNCTION_GRAPH_TRACER
--------------------------
@@ -328,8 +304,6 @@ void mcount(void)
void ftrace_caller(void)
{
- /* implement HAVE_FUNCTION_TRACE_MCOUNT_TEST if you desire */
-
/* save all state needed by the ABI (see paragraph above) */
unsigned long frompc = ...;
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index 2479b2a0c77c..4da42616939f 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -1515,7 +1515,7 @@ Doing the same with chrt -r 5 and function-trace set.
<idle>-0 3d.h4 1us+: 0:120:R + [003] 2448: 94:R sleep
<idle>-0 3d.h4 2us : ttwu_do_activate.constprop.87 <-try_to_wake_up
<idle>-0 3d.h3 3us : check_preempt_curr <-ttwu_do_wakeup
- <idle>-0 3d.h3 3us : resched_task <-check_preempt_curr
+ <idle>-0 3d.h3 3us : resched_curr <-check_preempt_curr
<idle>-0 3dNh3 4us : task_woken_rt <-ttwu_do_wakeup
<idle>-0 3dNh3 4us : _raw_spin_unlock <-try_to_wake_up
<idle>-0 3dNh3 4us : sub_preempt_count <-_raw_spin_unlock
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index 78c9a7b2b58f..8f961ef2b457 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -47,6 +47,10 @@ use constant HIGH_KSWAPD_REWAKEUP => 21;
use constant HIGH_NR_SCANNED => 22;
use constant HIGH_NR_TAKEN => 23;
use constant HIGH_NR_RECLAIMED => 24;
+use constant HIGH_NR_FILE_SCANNED => 25;
+use constant HIGH_NR_ANON_SCANNED => 26;
+use constant HIGH_NR_FILE_RECLAIMED => 27;
+use constant HIGH_NR_ANON_RECLAIMED => 28;
my %perprocesspid;
my %perprocess;
@@ -56,14 +60,18 @@ my $opt_read_procstat;
my $total_wakeup_kswapd;
my ($total_direct_reclaim, $total_direct_nr_scanned);
+my ($total_direct_nr_file_scanned, $total_direct_nr_anon_scanned);
my ($total_direct_latency, $total_kswapd_latency);
my ($total_direct_nr_reclaimed);
+my ($total_direct_nr_file_reclaimed, $total_direct_nr_anon_reclaimed);
my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async);
my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async);
my ($total_kswapd_nr_scanned, $total_kswapd_wake);
+my ($total_kswapd_nr_file_scanned, $total_kswapd_nr_anon_scanned);
my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async);
my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async);
my ($total_kswapd_nr_reclaimed);
+my ($total_kswapd_nr_file_reclaimed, $total_kswapd_nr_anon_reclaimed);
# Catch sigint and exit on request
my $sigint_report = 0;
@@ -374,6 +382,7 @@ EVENT_PROCESS:
}
my $isolate_mode = $1;
my $nr_scanned = $4;
+ my $file = $6;
# To closer match vmstat scanning statistics, only count isolate_both
# and isolate_inactive as scanning. isolate_active is rotation
@@ -382,6 +391,11 @@ EVENT_PROCESS:
# isolate_both == 3
if ($isolate_mode != 2) {
$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+ if ($file == 1) {
+ $perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED} += $nr_scanned;
+ } else {
+ $perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED} += $nr_scanned;
+ }
}
} elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
$details = $6;
@@ -391,8 +405,19 @@ EVENT_PROCESS:
print " $regex_lru_shrink_inactive/o\n";
next;
}
+
my $nr_reclaimed = $4;
+ my $flags = $6;
+ my $file = 0;
+ if ($flags =~ /RECLAIM_WB_FILE/) {
+ $file = 1;
+ }
$perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed;
+ if ($file) {
+ $perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED} += $nr_reclaimed;
+ } else {
+ $perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED} += $nr_reclaimed;
+ }
} elsif ($tracepoint eq "mm_vmscan_writepage") {
$details = $6;
if ($details !~ /$regex_writepage/o) {
@@ -493,7 +518,11 @@ sub dump_stats {
$total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
$total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
$total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+ $total_direct_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
+ $total_direct_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
$total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
+ $total_direct_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+ $total_direct_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
$total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
$total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
$total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -513,7 +542,11 @@ sub dump_stats {
$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN},
$stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD},
$stats{$process_pid}->{HIGH_NR_SCANNED},
+ $stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
+ $stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
$stats{$process_pid}->{HIGH_NR_RECLAIMED},
+ $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
+ $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC},
$this_reclaim_delay / 1000);
@@ -552,7 +585,11 @@ sub dump_stats {
$total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
$total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+ $total_kswapd_nr_file_scanned += $stats{$process_pid}->{HIGH_NR_FILE_SCANNED};
+ $total_kswapd_nr_anon_scanned += $stats{$process_pid}->{HIGH_NR_ANON_SCANNED};
$total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
+ $total_kswapd_nr_file_reclaimed += $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+ $total_kswapd_nr_anon_reclaimed += $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
$total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
$total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
$total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -563,7 +600,11 @@ sub dump_stats {
$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE},
$stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP},
$stats{$process_pid}->{HIGH_NR_SCANNED},
+ $stats{$process_pid}->{HIGH_NR_FILE_SCANNED},
+ $stats{$process_pid}->{HIGH_NR_ANON_SCANNED},
$stats{$process_pid}->{HIGH_NR_RECLAIMED},
+ $stats{$process_pid}->{HIGH_NR_FILE_RECLAIMED},
+ $stats{$process_pid}->{HIGH_NR_ANON_RECLAIMED},
$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
$stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC});
@@ -594,7 +635,11 @@ sub dump_stats {
print "\nSummary\n";
print "Direct reclaims: $total_direct_reclaim\n";
print "Direct reclaim pages scanned: $total_direct_nr_scanned\n";
+ print "Direct reclaim file pages scanned: $total_direct_nr_file_scanned\n";
+ print "Direct reclaim anon pages scanned: $total_direct_nr_anon_scanned\n";
print "Direct reclaim pages reclaimed: $total_direct_nr_reclaimed\n";
+ print "Direct reclaim file pages reclaimed: $total_direct_nr_file_reclaimed\n";
+ print "Direct reclaim anon pages reclaimed: $total_direct_nr_anon_reclaimed\n";
print "Direct reclaim write file sync I/O: $total_direct_writepage_file_sync\n";
print "Direct reclaim write anon sync I/O: $total_direct_writepage_anon_sync\n";
print "Direct reclaim write file async I/O: $total_direct_writepage_file_async\n";
@@ -604,7 +649,11 @@ sub dump_stats {
print "\n";
print "Kswapd wakeups: $total_kswapd_wake\n";
print "Kswapd pages scanned: $total_kswapd_nr_scanned\n";
+ print "Kswapd file pages scanned: $total_kswapd_nr_file_scanned\n";
+ print "Kswapd anon pages scanned: $total_kswapd_nr_anon_scanned\n";
print "Kswapd pages reclaimed: $total_kswapd_nr_reclaimed\n";
+ print "Kswapd file pages reclaimed: $total_kswapd_nr_file_reclaimed\n";
+ print "Kswapd anon pages reclaimed: $total_kswapd_nr_anon_reclaimed\n";
print "Kswapd reclaim write file sync I/O: $total_kswapd_writepage_file_sync\n";
print "Kswapd reclaim write anon sync I/O: $total_kswapd_writepage_anon_sync\n";
print "Kswapd reclaim write file async I/O: $total_kswapd_writepage_file_async\n";
@@ -629,7 +678,11 @@ sub aggregate_perprocesspid() {
$perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
$perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP};
$perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED};
+ $perprocess{$process}->{HIGH_NR_FILE_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_SCANNED};
+ $perprocess{$process}->{HIGH_NR_ANON_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_SCANNED};
$perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED};
+ $perprocess{$process}->{HIGH_NR_FILE_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_FILE_RECLAIMED};
+ $perprocess{$process}->{HIGH_NR_ANON_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_ANON_RECLAIMED};
$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
$perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
diff --git a/Documentation/usb/hotplug.txt b/Documentation/usb/hotplug.txt
index 6424b130485c..a80b0e9a7a0b 100644
--- a/Documentation/usb/hotplug.txt
+++ b/Documentation/usb/hotplug.txt
@@ -105,13 +105,13 @@ macros such as these, and use driver_info to store more information.
A short example, for a driver that supports several specific USB devices
and their quirks, might have a MODULE_DEVICE_TABLE like this:
- static const struct usb_device_id mydriver_id_table = {
+ static const struct usb_device_id mydriver_id_table[] = {
{ USB_DEVICE (0x9999, 0xaaaa), driver_info: QUIRK_X },
{ USB_DEVICE (0xbbbb, 0x8888), driver_info: QUIRK_Y|QUIRK_Z },
...
{ } /* end with an all-zeroes entry */
- }
- MODULE_DEVICE_TABLE (usb, mydriver_id_table);
+ };
+ MODULE_DEVICE_TABLE(usb, mydriver_id_table);
Most USB device drivers should pass these tables to the USB subsystem as
well as to the module management subsystem. Not all, though: some driver
@@ -134,7 +134,7 @@ something like this:
if exposing any operations through usbdevfs:
.ioctl = my_ioctl,
*/
- }
+ };
When the USB subsystem knows about a driver's device ID table, it's used when
choosing drivers to probe(). The thread doing new device processing checks
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index 1392b61d6ebe..7b90fe034c4b 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -2,8 +2,27 @@
Alan Stern <stern@rowland.harvard.edu>
- October 28, 2010
-
+ Last-updated: February 2014
+
+
+ Contents:
+ ---------
+ * What is Power Management?
+ * What is Remote Wakeup?
+ * When is a USB device idle?
+ * Forms of dynamic PM
+ * The user interface for dynamic PM
+ * Changing the default idle-delay time
+ * Warnings
+ * The driver interface for Power Management
+ * The driver interface for autosuspend and autoresume
+ * Other parts of the driver interface
+ * Mutual exclusion
+ * Interaction between dynamic PM and system PM
+ * xHCI hardware link PM
+ * USB Port Power Control
+ * User Interface for Port Power Control
+ * Suggested Userspace Port Power Policy
What is Power Management?
@@ -516,3 +535,225 @@ relevant attribute files is usb2_hardware_lpm.
driver will enable hardware LPM for the device. You
can write y/Y/1 or n/N/0 to the file to enable/disable
USB2 hardware LPM manually. This is for test purpose mainly.
+
+
+ USB Port Power Control
+ ----------------------
+
+In addition to suspending endpoint devices and enabling hardware
+controlled link power management, the USB subsystem also has the
+capability to disable power to ports under some conditions. Power is
+controlled through Set/ClearPortFeature(PORT_POWER) requests to a hub.
+In the case of a root or platform-internal hub the host controller
+driver translates PORT_POWER requests into platform firmware (ACPI)
+method calls to set the port power state. For more background see the
+Linux Plumbers Conference 2012 slides [1] and video [2]:
+
+Upon receiving a ClearPortFeature(PORT_POWER) request a USB port is
+logically off, and may trigger the actual loss of VBUS to the port [3].
+VBUS may be maintained in the case where a hub gangs multiple ports into
+a shared power well causing power to remain until all ports in the gang
+are turned off. VBUS may also be maintained by hub ports configured for
+a charging application. In any event a logically off port will lose
+connection with its device, not respond to hotplug events, and not
+respond to remote wakeup events*.
+
+WARNING: turning off a port may result in the inability to hot add a device.
+Please see "User Interface for Port Power Control" for details.
+
+As far as the effect on the device itself it is similar to what a device
+goes through during system suspend, i.e. the power session is lost. Any
+USB device or driver that misbehaves with system suspend will be
+similarly affected by a port power cycle event. For this reason the
+implementation shares the same device recovery path (and honors the same
+quirks) as the system resume path for the hub.
+
+[1]: http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
+[2]: http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
+[3]: USB 3.1 Section 10.12
+* wakeup note: if a device is configured to send wakeup events the port
+ power control implementation will block poweroff attempts on that
+ port.
+
+
+ User Interface for Port Power Control
+ -------------------------------------
+
+The port power control mechanism uses the PM runtime system. Poweroff is
+requested by clearing the power/pm_qos_no_power_off flag of the port device
+(defaults to 1). If the port is disconnected it will immediately receive a
+ClearPortFeature(PORT_POWER) request. Otherwise, it will honor the pm runtime
+rules and require the attached child device and all descendants to be suspended.
+This mechanism is dependent on the hub advertising port power switching in its
+hub descriptor (wHubCharacteristics logical power switching mode field).
+
+Note, some interface devices/drivers do not support autosuspend. Userspace may
+need to unbind the interface drivers before the usb_device will suspend. An
+unbound interface device is suspended by default. When unbinding, be careful
+to unbind interface drivers, not the driver of the parent usb device. Also,
+leave hub interface drivers bound. If the driver for the usb device (not
+interface) is unbound the kernel is no longer able to resume the device. If a
+hub interface driver is unbound, control of its child ports is lost and all
+attached child-devices will disconnect. A good rule of thumb is that if the
+'driver/module' link for a device points to /sys/module/usbcore then unbinding
+it will interfere with port power control.
+
+Example of the relevant files for port power control. Note, in this example
+these files are relative to a usb hub device (prefix).
+
+ prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
+
+ attached child device +
+ hub port device + |
+ hub interface device + | |
+ v v v
+ $prefix/3-1:1.0/3-1-port1/device
+
+ $prefix/3-1:1.0/3-1-port1/power/pm_qos_no_power_off
+ $prefix/3-1:1.0/3-1-port1/device/power/control
+ $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf0>/driver/unbind
+ $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intf1>/driver/unbind
+ ...
+ $prefix/3-1:1.0/3-1-port1/device/3-1.1:<intfN>/driver/unbind
+
+In addition to these files some ports may have a 'peer' link to a port on
+another hub. The expectation is that all superspeed ports have a
+hi-speed peer.
+
+$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
+../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
+
+Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
+peer ports are simply the hi-speed and superspeed interface pins that
+are combined into a single usb3 connector. Peer ports share the same
+ancestor XHCI device.
+
+While a superspeed port is powered off a device may downgrade its
+connection and attempt to connect to the hi-speed pins. The
+implementation takes steps to prevent this:
+
+1/ Port suspend is sequenced to guarantee that hi-speed ports are powered-off
+ before their superspeed peer is permitted to power-off. The implication is
+ that the setting pm_qos_no_power_off to zero on a superspeed port may not cause
+ the port to power-off until its highspeed peer has gone to its runtime suspend
+ state. Userspace must take care to order the suspensions if it wants to
+ guarantee that a superspeed port will power-off.
+
+2/ Port resume is sequenced to force a superspeed port to power-on prior to its
+ highspeed peer.
+
+3/ Port resume always triggers an attached child device to resume. After a
+ power session is lost the device may have been removed, or need reset.
+ Resuming the child device when the parent port regains power resolves those
+ states and clamps the maximum port power cycle frequency at the rate the child
+ device can suspend (autosuspend-delay) and resume (reset-resume latency).
+
+Sysfs files relevant for port power control:
+ <hubdev-portX>/power/pm_qos_no_power_off:
+ This writable flag controls the state of an idle port.
+ Once all children and descendants have suspended the
+ port may suspend/poweroff provided that
+ pm_qos_no_power_off is '0'. If pm_qos_no_power_off is
+ '1' the port will remain active/powered regardless of
+ the stats of descendants. Defaults to 1.
+
+ <hubdev-portX>/power/runtime_status:
+ This file reflects whether the port is 'active' (power is on)
+ or 'suspended' (logically off). There is no indication to
+ userspace whether VBUS is still supplied.
+
+ <hubdev-portX>/connect_type:
+ An advisory read-only flag to userspace indicating the
+ location and connection type of the port. It returns
+ one of four values 'hotplug', 'hardwired', 'not used',
+ and 'unknown'. All values, besides unknown, are set by
+ platform firmware.
+
+ "hotplug" indicates an externally connectable/visible
+ port on the platform. Typically userspace would choose
+ to keep such a port powered to handle new device
+ connection events.
+
+ "hardwired" refers to a port that is not visible but
+ connectable. Examples are internal ports for USB
+ bluetooth that can be disconnected via an external
+ switch or a port with a hardwired USB camera. It is
+ expected to be safe to allow these ports to suspend
+ provided pm_qos_no_power_off is coordinated with any
+ switch that gates connections. Userspace must arrange
+ for the device to be connected prior to the port
+ powering off, or to activate the port prior to enabling
+ connection via a switch.
+
+ "not used" refers to an internal port that is expected
+ to never have a device connected to it. These may be
+ empty internal ports, or ports that are not physically
+ exposed on a platform. Considered safe to be
+ powered-off at all times.
+
+ "unknown" means platform firmware does not provide
+ information for this port. Most commonly refers to
+ external hub ports which should be considered 'hotplug'
+ for policy decisions.
+
+ NOTE1: since we are relying on the BIOS to get this ACPI
+ information correct, the USB port descriptions may be
+ missing or wrong.
+
+ NOTE2: Take care in clearing pm_qos_no_power_off. Once
+ power is off this port will
+ not respond to new connect events.
+
+ Once a child device is attached additional constraints are
+ applied before the port is allowed to poweroff.
+
+ <child>/power/control:
+ Must be 'auto', and the port will not
+ power down until <child>/power/runtime_status
+ reflects the 'suspended' state. Default
+ value is controlled by child device driver.
+
+ <child>/power/persist:
+ This defaults to '1' for most devices and indicates if
+ kernel can persist the device's configuration across a
+ power session loss (suspend / port-power event). When
+ this value is '0' (quirky devices), port poweroff is
+ disabled.
+
+ <child>/driver/unbind:
+ Wakeup capable devices will block port poweroff. At
+ this time the only mechanism to clear the usb-internal
+ wakeup-capability for an interface device is to unbind
+ its driver.
+
+Summary of poweroff pre-requisite settings relative to a port device:
+
+ echo 0 > power/pm_qos_no_power_off
+ echo 0 > peer/power/pm_qos_no_power_off # if it exists
+ echo auto > power/control # this is the default value
+ echo auto > <child>/power/control
+ echo 1 > <child>/power/persist # this is the default value
+
+ Suggested Userspace Port Power Policy
+ -------------------------------------
+
+As noted above userspace needs to be careful and deliberate about what
+ports are enabled for poweroff.
+
+The default configuration is that all ports start with
+power/pm_qos_no_power_off set to '1' causing ports to always remain
+active.
+
+Given confidence in the platform firmware's description of the ports
+(ACPI _PLD record for a port populates 'connect_type') userspace can
+clear pm_qos_no_power_off for all 'not used' ports. The same can be
+done for 'hardwired' ports provided poweroff is coordinated with any
+connection switch for the port.
+
+A more aggressive userspace policy is to enable USB port power off for
+all ports (set <hubdev-portX>/power/pm_qos_no_power_off to '0') when
+some external factor indicates the user has stopped interacting with the
+system. For example, a distro may want to enable power off all USB
+ports when the screen blanks, and re-power them when the screen becomes
+active. Smart phones and tablets may want to power off USB ports when
+the user pushes the power button.
diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt
index b9ca02370d46..96978eced341 100644
--- a/Documentation/vfio.txt
+++ b/Documentation/vfio.txt
@@ -305,7 +305,15 @@ faster, the map/unmap handling has been implemented in real mode which provides
an excellent performance which has limitations such as inability to do
locked pages accounting in real time.
-So 3 additional ioctls have been added:
+4) According to sPAPR specification, A Partitionable Endpoint (PE) is an I/O
+subtree that can be treated as a unit for the purposes of partitioning and
+error recovery. A PE may be a single or multi-function IOA (IO Adapter), a
+function of a multi-function IOA, or multiple IOAs (possibly including switch
+and bridge structures above the multiple IOAs). PPC64 guests detect PCI errors
+and recover from them via EEH RTAS services, which works on the basis of
+additional ioctl commands.
+
+So 4 additional ioctls have been added:
VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start
of the DMA window on the PCI bus.
@@ -316,9 +324,12 @@ So 3 additional ioctls have been added:
VFIO_IOMMU_DISABLE - disables the container.
+ VFIO_EEH_PE_OP - provides an API for EEH setup, error detection and recovery.
The code flow from the example above should be slightly changed:
+ struct vfio_eeh_pe_op pe_op = { .argsz = sizeof(pe_op), .flags = 0 };
+
.....
/* Add the group to the container */
ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);
@@ -342,9 +353,79 @@ The code flow from the example above should be slightly changed:
dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
/* Check here is .iova/.size are within DMA window from spapr_iommu_info */
-
ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
- .....
+
+ /* Get a file descriptor for the device */
+ device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:06:0d.0");
+
+ ....
+
+ /* Gratuitous device reset and go... */
+ ioctl(device, VFIO_DEVICE_RESET);
+
+ /* Make sure EEH is supported */
+ ioctl(container, VFIO_CHECK_EXTENSION, VFIO_EEH);
+
+ /* Enable the EEH functionality on the device */
+ pe_op.op = VFIO_EEH_PE_ENABLE;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /* You're suggested to create additional data struct to represent
+ * PE, and put child devices belonging to same IOMMU group to the
+ * PE instance for later reference.
+ */
+
+ /* Check the PE's state and make sure it's in functional state */
+ pe_op.op = VFIO_EEH_PE_GET_STATE;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /* Save device state using pci_save_state().
+ * EEH should be enabled on the specified device.
+ */
+
+ ....
+
+ /* When 0xFF's returned from reading PCI config space or IO BARs
+ * of the PCI device. Check the PE's state to see if that has been
+ * frozen.
+ */
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /* Waiting for pending PCI transactions to be completed and don't
+ * produce any more PCI traffic from/to the affected PE until
+ * recovery is finished.
+ */
+
+ /* Enable IO for the affected PE and collect logs. Usually, the
+ * standard part of PCI config space, AER registers are dumped
+ * as logs for further analysis.
+ */
+ pe_op.op = VFIO_EEH_PE_UNFREEZE_IO;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /*
+ * Issue PE reset: hot or fundamental reset. Usually, hot reset
+ * is enough. However, the firmware of some PCI adapters would
+ * require fundamental reset.
+ */
+ pe_op.op = VFIO_EEH_PE_RESET_HOT;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+ pe_op.op = VFIO_EEH_PE_RESET_DEACTIVATE;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /* Configure the PCI bridges for the affected PE */
+ pe_op.op = VFIO_EEH_PE_CONFIGURE;
+ ioctl(container, VFIO_EEH_PE_OP, &pe_op);
+
+ /* Restored state we saved at initialization time. pci_restore_state()
+ * is good enough as an example.
+ */
+
+ /* Hopefully, error is recovered successfully. Now, you can resume to
+ * start PCI traffic to/from the affected PE.
+ */
+
+ ....
-------------------------------------------------------------------------------
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index fc009d0ee7d6..a74eeccfe700 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -41,3 +41,5 @@
40 -> TurboSight TBS 6981 [6981:8888]
41 -> TurboSight TBS 6980 [6980:8888]
42 -> Leadtek Winfast PxPVR2200 [107d:6f21]
+ 43 -> Hauppauge ImpactVCB-e [0070:7133]
+ 44 -> DViCO FusionHDTV DVB-T Dual Express2 [18ac:db98]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 5a3ddcd340d3..bc3351bb48b4 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -77,7 +77,7 @@
76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
77 -> EM2874 Leadership ISDBT (em2874)
78 -> PCTV nanoStick T2 290e (em28174)
- 79 -> Terratec Cinergy H5 (em2884) [0ccd:10a2,0ccd:10ad,0ccd:10b6]
+ 79 -> Terratec Cinergy H5 (em2884) [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6]
80 -> PCTV DVB-S2 Stick (460e) (em28174)
81 -> Hauppauge WinTV HVR 930C (em2884) [2040:1605]
82 -> Terratec Cinergy HTC Stick (em2884) [0ccd:00b2]
diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 06cf3ac83631..0f84ce8c9a7b 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -77,9 +77,9 @@ Basic usage for V4L2 and sub-device drivers
Where foo->v4l2_dev is of type struct v4l2_device.
- Finally, remove all control functions from your v4l2_ioctl_ops:
- vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl,
- vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
+ Finally, remove all control functions from your v4l2_ioctl_ops (if any):
+ vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl,
+ vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
Those are now no longer needed.
1.3.2) For sub-device drivers do this:
@@ -258,8 +258,8 @@ The new control value has already been validated, so all you need to do is
to actually update the hardware registers.
You're done! And this is sufficient for most of the drivers we have. No need
-to do any validation of control values, or implement QUERYCTRL/QUERYMENU. And
-G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
+to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL
+and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
==============================================================================
@@ -288,30 +288,45 @@ of v4l2_device.
Accessing Control Values
========================
-The v4l2_ctrl struct contains these two unions:
+The following union is used inside the control framework to access control
+values:
- /* The current control value. */
- union {
+union v4l2_ctrl_ptr {
+ s32 *p_s32;
+ s64 *p_s64;
+ char *p_char;
+ void *p;
+};
+
+The v4l2_ctrl struct contains these fields that can be used to access both
+current and new values:
+
+ s32 val;
+ struct {
s32 val;
- s64 val64;
- char *string;
} cur;
- /* The new control value. */
- union {
- s32 val;
- s64 val64;
- char *string;
- };
-Within the control ops you can freely use these. The val and val64 speak for
-themselves. The string pointers point to character buffers of length
+ union v4l2_ctrl_ptr p_new;
+ union v4l2_ctrl_ptr p_cur;
+
+If the control has a simple s32 type type, then:
+
+ &ctrl->val == ctrl->p_new.p_s32
+ &ctrl->cur.val == ctrl->p_cur.p_s32
+
+For all other types use ctrl->p_cur.p<something>. Basically the val
+and cur.val fields can be considered an alias since these are used so often.
+
+Within the control ops you can freely use these. The val and cur.val speak for
+themselves. The p_char pointers point to character buffers of length
ctrl->maximum + 1, and are always 0-terminated.
-In most cases 'cur' contains the current cached control value. When you create
-a new control this value is made identical to the default value. After calling
-v4l2_ctrl_handler_setup() this value is passed to the hardware. It is generally
-a good idea to call this function.
+Unless the control is marked volatile the p_cur field points to the the
+current cached control value. When you create a new control this value is made
+identical to the default value. After calling v4l2_ctrl_handler_setup() this
+value is passed to the hardware. It is generally a good idea to call this
+function.
Whenever a new value is set that new value is automatically cached. This means
that most drivers do not need to implement the g_volatile_ctrl() op. The
@@ -362,8 +377,8 @@ will result in a deadlock since these helpers lock the handler as well.
You can also take the handler lock yourself:
mutex_lock(&state->ctrl_handler.lock);
- printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string);
- printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val);
+ pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
+ pr_info("Integer value is '%s'\n", ctrl2->cur.val);
mutex_unlock(&state->ctrl_handler.lock);
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 667a43361706..a11dff07ef71 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -675,11 +675,6 @@ You should also set these fields:
video_device is initialized you *do* know which parent PCI device to use and
so you set dev_device to the correct PCI device.
-- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
- handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
- v4l2_fh. Eventually this flag will disappear once all drivers use the core
- priority handling. But for now it has to be set explicitly.
-
If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2
in your v4l2_file_operations struct.
@@ -909,8 +904,7 @@ struct v4l2_fh
struct v4l2_fh provides a way to easily keep file handle specific data
that is used by the V4L2 framework. New drivers must use struct v4l2_fh
-since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY)
-if the video_device flag V4L2_FL_USE_FH_PRIO is also set.
+since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY).
The users of v4l2_fh (in the V4L2 framework, not the driver) know
whether a driver uses v4l2_fh as its file->private_data pointer by
diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c
index 46904fe49609..006721e43b2a 100644
--- a/Documentation/video4linux/v4l2-pci-skeleton.c
+++ b/Documentation/video4linux/v4l2-pci-skeleton.c
@@ -883,11 +883,6 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
vdev->v4l2_dev = &skel->v4l2_dev;
/* Supported SDTV standards, if any */
vdev->tvnorms = SKEL_TVNORMS;
- /* If this bit is set, then the v4l2 core will provide the support
- * for the VIDIOC_G/S_PRIORITY ioctls. This flag will eventually
- * go away once all drivers have been converted to use struct v4l2_fh.
- */
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(vdev, skel);
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 0fe36497642c..beae3fde075e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -148,9 +148,9 @@ of banks, as set via the KVM_X86_SETUP_MCE ioctl.
4.4 KVM_CHECK_EXTENSION
-Capability: basic
+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
Architectures: all
-Type: system ioctl
+Type: system ioctl, vm ioctl
Parameters: extension identifier (KVM_CAP_*)
Returns: 0 if unsupported; 1 (or some other positive integer) if supported
@@ -160,6 +160,9 @@ receives an integer that describes the extension availability.
Generally 0 means no and 1 means yes, but some extensions may report
additional information in the integer return value.
+Based on their initialization different VMs may have different capabilities.
+It is thus encouraged to use the vm ioctl to query for capabilities (available
+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
4.5 KVM_GET_VCPU_MMAP_SIZE
@@ -297,6 +300,15 @@ struct kvm_regs {
__u64 rip, rflags;
};
+/* mips */
+struct kvm_regs {
+ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+ __u64 gpr[32];
+ __u64 hi;
+ __u64 lo;
+ __u64 pc;
+};
+
4.12 KVM_SET_REGS
@@ -378,7 +390,7 @@ struct kvm_translation {
4.16 KVM_INTERRUPT
Capability: basic
-Architectures: x86, ppc
+Architectures: x86, ppc, mips
Type: vcpu ioctl
Parameters: struct kvm_interrupt (in)
Returns: 0 on success, -1 on error
@@ -423,6 +435,11 @@ c) KVM_INTERRUPT_SET_LEVEL
Note that any value for 'irq' other than the ones stated above is invalid
and incurs unexpected behavior.
+MIPS:
+
+Queues an external interrupt to be injected into the virtual CPU. A negative
+interrupt number dequeues the interrupt.
+
4.17 KVM_DEBUG_GUEST
@@ -512,7 +529,7 @@ struct kvm_cpuid {
4.21 KVM_SET_SIGNAL_MASK
Capability: basic
-Architectures: x86
+Architectures: all
Type: vcpu ioctl
Parameters: struct kvm_signal_mask (in)
Returns: 0 on success, -1 on error
@@ -974,7 +991,7 @@ for vm-wide capabilities.
4.38 KVM_GET_MP_STATE
Capability: KVM_CAP_MP_STATE
-Architectures: x86, ia64
+Architectures: x86, ia64, s390
Type: vcpu ioctl
Parameters: struct kvm_mp_state (out)
Returns: 0 on success; -1 on error
@@ -988,24 +1005,32 @@ uniprocessor guests).
Possible values are:
- - KVM_MP_STATE_RUNNABLE: the vcpu is currently running
+ - KVM_MP_STATE_RUNNABLE: the vcpu is currently running [x86, ia64]
- KVM_MP_STATE_UNINITIALIZED: the vcpu is an application processor (AP)
- which has not yet received an INIT signal
+ which has not yet received an INIT signal [x86,
+ ia64]
- KVM_MP_STATE_INIT_RECEIVED: the vcpu has received an INIT signal, and is
- now ready for a SIPI
+ now ready for a SIPI [x86, ia64]
- KVM_MP_STATE_HALTED: the vcpu has executed a HLT instruction and
- is waiting for an interrupt
+ is waiting for an interrupt [x86, ia64]
- KVM_MP_STATE_SIPI_RECEIVED: the vcpu has just received a SIPI (vector
- accessible via KVM_GET_VCPU_EVENTS)
+ accessible via KVM_GET_VCPU_EVENTS) [x86, ia64]
+ - KVM_MP_STATE_STOPPED: the vcpu is stopped [s390]
+ - KVM_MP_STATE_CHECK_STOP: the vcpu is in a special error state [s390]
+ - KVM_MP_STATE_OPERATING: the vcpu is operating (running or halted)
+ [s390]
+ - KVM_MP_STATE_LOAD: the vcpu is in a special load/startup state
+ [s390]
-This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel
-irqchip, the multiprocessing state must be maintained by userspace.
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
4.39 KVM_SET_MP_STATE
Capability: KVM_CAP_MP_STATE
-Architectures: x86, ia64
+Architectures: x86, ia64, s390
Type: vcpu ioctl
Parameters: struct kvm_mp_state (in)
Returns: 0 on success; -1 on error
@@ -1013,8 +1038,9 @@ Returns: 0 on success; -1 on error
Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
arguments.
-This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel
-irqchip, the multiprocessing state must be maintained by userspace.
+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
4.40 KVM_SET_IDENTITY_MAP_ADDR
@@ -1774,122 +1800,152 @@ and architecture specific registers. Each have their own range of operation
and their own constants and width. To keep track of the implemented
registers, find a list below:
- Arch | Register | Width (bits)
- | |
- PPC | KVM_REG_PPC_HIOR | 64
- PPC | KVM_REG_PPC_IAC1 | 64
- PPC | KVM_REG_PPC_IAC2 | 64
- PPC | KVM_REG_PPC_IAC3 | 64
- PPC | KVM_REG_PPC_IAC4 | 64
- PPC | KVM_REG_PPC_DAC1 | 64
- PPC | KVM_REG_PPC_DAC2 | 64
- PPC | KVM_REG_PPC_DABR | 64
- PPC | KVM_REG_PPC_DSCR | 64
- PPC | KVM_REG_PPC_PURR | 64
- PPC | KVM_REG_PPC_SPURR | 64
- PPC | KVM_REG_PPC_DAR | 64
- PPC | KVM_REG_PPC_DSISR | 32
- PPC | KVM_REG_PPC_AMR | 64
- PPC | KVM_REG_PPC_UAMOR | 64
- PPC | KVM_REG_PPC_MMCR0 | 64
- PPC | KVM_REG_PPC_MMCR1 | 64
- PPC | KVM_REG_PPC_MMCRA | 64
- PPC | KVM_REG_PPC_MMCR2 | 64
- PPC | KVM_REG_PPC_MMCRS | 64
- PPC | KVM_REG_PPC_SIAR | 64
- PPC | KVM_REG_PPC_SDAR | 64
- PPC | KVM_REG_PPC_SIER | 64
- PPC | KVM_REG_PPC_PMC1 | 32
- PPC | KVM_REG_PPC_PMC2 | 32
- PPC | KVM_REG_PPC_PMC3 | 32
- PPC | KVM_REG_PPC_PMC4 | 32
- PPC | KVM_REG_PPC_PMC5 | 32
- PPC | KVM_REG_PPC_PMC6 | 32
- PPC | KVM_REG_PPC_PMC7 | 32
- PPC | KVM_REG_PPC_PMC8 | 32
- PPC | KVM_REG_PPC_FPR0 | 64
+ Arch | Register | Width (bits)
+ | |
+ PPC | KVM_REG_PPC_HIOR | 64
+ PPC | KVM_REG_PPC_IAC1 | 64
+ PPC | KVM_REG_PPC_IAC2 | 64
+ PPC | KVM_REG_PPC_IAC3 | 64
+ PPC | KVM_REG_PPC_IAC4 | 64
+ PPC | KVM_REG_PPC_DAC1 | 64
+ PPC | KVM_REG_PPC_DAC2 | 64
+ PPC | KVM_REG_PPC_DABR | 64
+ PPC | KVM_REG_PPC_DSCR | 64
+ PPC | KVM_REG_PPC_PURR | 64
+ PPC | KVM_REG_PPC_SPURR | 64
+ PPC | KVM_REG_PPC_DAR | 64
+ PPC | KVM_REG_PPC_DSISR | 32
+ PPC | KVM_REG_PPC_AMR | 64
+ PPC | KVM_REG_PPC_UAMOR | 64
+ PPC | KVM_REG_PPC_MMCR0 | 64
+ PPC | KVM_REG_PPC_MMCR1 | 64
+ PPC | KVM_REG_PPC_MMCRA | 64
+ PPC | KVM_REG_PPC_MMCR2 | 64
+ PPC | KVM_REG_PPC_MMCRS | 64
+ PPC | KVM_REG_PPC_SIAR | 64
+ PPC | KVM_REG_PPC_SDAR | 64
+ PPC | KVM_REG_PPC_SIER | 64
+ PPC | KVM_REG_PPC_PMC1 | 32
+ PPC | KVM_REG_PPC_PMC2 | 32
+ PPC | KVM_REG_PPC_PMC3 | 32
+ PPC | KVM_REG_PPC_PMC4 | 32
+ PPC | KVM_REG_PPC_PMC5 | 32
+ PPC | KVM_REG_PPC_PMC6 | 32
+ PPC | KVM_REG_PPC_PMC7 | 32
+ PPC | KVM_REG_PPC_PMC8 | 32
+ PPC | KVM_REG_PPC_FPR0 | 64
+ ...
+ PPC | KVM_REG_PPC_FPR31 | 64
+ PPC | KVM_REG_PPC_VR0 | 128
...
- PPC | KVM_REG_PPC_FPR31 | 64
- PPC | KVM_REG_PPC_VR0 | 128
+ PPC | KVM_REG_PPC_VR31 | 128
+ PPC | KVM_REG_PPC_VSR0 | 128
...
- PPC | KVM_REG_PPC_VR31 | 128
- PPC | KVM_REG_PPC_VSR0 | 128
+ PPC | KVM_REG_PPC_VSR31 | 128
+ PPC | KVM_REG_PPC_FPSCR | 64
+ PPC | KVM_REG_PPC_VSCR | 32
+ PPC | KVM_REG_PPC_VPA_ADDR | 64
+ PPC | KVM_REG_PPC_VPA_SLB | 128
+ PPC | KVM_REG_PPC_VPA_DTL | 128
+ PPC | KVM_REG_PPC_EPCR | 32
+ PPC | KVM_REG_PPC_EPR | 32
+ PPC | KVM_REG_PPC_TCR | 32
+ PPC | KVM_REG_PPC_TSR | 32
+ PPC | KVM_REG_PPC_OR_TSR | 32
+ PPC | KVM_REG_PPC_CLEAR_TSR | 32
+ PPC | KVM_REG_PPC_MAS0 | 32
+ PPC | KVM_REG_PPC_MAS1 | 32
+ PPC | KVM_REG_PPC_MAS2 | 64
+ PPC | KVM_REG_PPC_MAS7_3 | 64
+ PPC | KVM_REG_PPC_MAS4 | 32
+ PPC | KVM_REG_PPC_MAS6 | 32
+ PPC | KVM_REG_PPC_MMUCFG | 32
+ PPC | KVM_REG_PPC_TLB0CFG | 32
+ PPC | KVM_REG_PPC_TLB1CFG | 32
+ PPC | KVM_REG_PPC_TLB2CFG | 32
+ PPC | KVM_REG_PPC_TLB3CFG | 32
+ PPC | KVM_REG_PPC_TLB0PS | 32
+ PPC | KVM_REG_PPC_TLB1PS | 32
+ PPC | KVM_REG_PPC_TLB2PS | 32
+ PPC | KVM_REG_PPC_TLB3PS | 32
+ PPC | KVM_REG_PPC_EPTCFG | 32
+ PPC | KVM_REG_PPC_ICP_STATE | 64
+ PPC | KVM_REG_PPC_TB_OFFSET | 64
+ PPC | KVM_REG_PPC_SPMC1 | 32
+ PPC | KVM_REG_PPC_SPMC2 | 32
+ PPC | KVM_REG_PPC_IAMR | 64
+ PPC | KVM_REG_PPC_TFHAR | 64
+ PPC | KVM_REG_PPC_TFIAR | 64
+ PPC | KVM_REG_PPC_TEXASR | 64
+ PPC | KVM_REG_PPC_FSCR | 64
+ PPC | KVM_REG_PPC_PSPB | 32
+ PPC | KVM_REG_PPC_EBBHR | 64
+ PPC | KVM_REG_PPC_EBBRR | 64
+ PPC | KVM_REG_PPC_BESCR | 64
+ PPC | KVM_REG_PPC_TAR | 64
+ PPC | KVM_REG_PPC_DPDES | 64
+ PPC | KVM_REG_PPC_DAWR | 64
+ PPC | KVM_REG_PPC_DAWRX | 64
+ PPC | KVM_REG_PPC_CIABR | 64
+ PPC | KVM_REG_PPC_IC | 64
+ PPC | KVM_REG_PPC_VTB | 64
+ PPC | KVM_REG_PPC_CSIGR | 64
+ PPC | KVM_REG_PPC_TACR | 64
+ PPC | KVM_REG_PPC_TCSCR | 64
+ PPC | KVM_REG_PPC_PID | 64
+ PPC | KVM_REG_PPC_ACOP | 64
+ PPC | KVM_REG_PPC_VRSAVE | 32
+ PPC | KVM_REG_PPC_LPCR | 32
+ PPC | KVM_REG_PPC_LPCR_64 | 64
+ PPC | KVM_REG_PPC_PPR | 64
+ PPC | KVM_REG_PPC_ARCH_COMPAT | 32
+ PPC | KVM_REG_PPC_DABRX | 32
+ PPC | KVM_REG_PPC_WORT | 64
+ PPC | KVM_REG_PPC_TM_GPR0 | 64
...
- PPC | KVM_REG_PPC_VSR31 | 128
- PPC | KVM_REG_PPC_FPSCR | 64
- PPC | KVM_REG_PPC_VSCR | 32
- PPC | KVM_REG_PPC_VPA_ADDR | 64
- PPC | KVM_REG_PPC_VPA_SLB | 128
- PPC | KVM_REG_PPC_VPA_DTL | 128
- PPC | KVM_REG_PPC_EPCR | 32
- PPC | KVM_REG_PPC_EPR | 32
- PPC | KVM_REG_PPC_TCR | 32
- PPC | KVM_REG_PPC_TSR | 32
- PPC | KVM_REG_PPC_OR_TSR | 32
- PPC | KVM_REG_PPC_CLEAR_TSR | 32
- PPC | KVM_REG_PPC_MAS0 | 32
- PPC | KVM_REG_PPC_MAS1 | 32
- PPC | KVM_REG_PPC_MAS2 | 64
- PPC | KVM_REG_PPC_MAS7_3 | 64
- PPC | KVM_REG_PPC_MAS4 | 32
- PPC | KVM_REG_PPC_MAS6 | 32
- PPC | KVM_REG_PPC_MMUCFG | 32
- PPC | KVM_REG_PPC_TLB0CFG | 32
- PPC | KVM_REG_PPC_TLB1CFG | 32
- PPC | KVM_REG_PPC_TLB2CFG | 32
- PPC | KVM_REG_PPC_TLB3CFG | 32
- PPC | KVM_REG_PPC_TLB0PS | 32
- PPC | KVM_REG_PPC_TLB1PS | 32
- PPC | KVM_REG_PPC_TLB2PS | 32
- PPC | KVM_REG_PPC_TLB3PS | 32
- PPC | KVM_REG_PPC_EPTCFG | 32
- PPC | KVM_REG_PPC_ICP_STATE | 64
- PPC | KVM_REG_PPC_TB_OFFSET | 64
- PPC | KVM_REG_PPC_SPMC1 | 32
- PPC | KVM_REG_PPC_SPMC2 | 32
- PPC | KVM_REG_PPC_IAMR | 64
- PPC | KVM_REG_PPC_TFHAR | 64
- PPC | KVM_REG_PPC_TFIAR | 64
- PPC | KVM_REG_PPC_TEXASR | 64
- PPC | KVM_REG_PPC_FSCR | 64
- PPC | KVM_REG_PPC_PSPB | 32
- PPC | KVM_REG_PPC_EBBHR | 64
- PPC | KVM_REG_PPC_EBBRR | 64
- PPC | KVM_REG_PPC_BESCR | 64
- PPC | KVM_REG_PPC_TAR | 64
- PPC | KVM_REG_PPC_DPDES | 64
- PPC | KVM_REG_PPC_DAWR | 64
- PPC | KVM_REG_PPC_DAWRX | 64
- PPC | KVM_REG_PPC_CIABR | 64
- PPC | KVM_REG_PPC_IC | 64
- PPC | KVM_REG_PPC_VTB | 64
- PPC | KVM_REG_PPC_CSIGR | 64
- PPC | KVM_REG_PPC_TACR | 64
- PPC | KVM_REG_PPC_TCSCR | 64
- PPC | KVM_REG_PPC_PID | 64
- PPC | KVM_REG_PPC_ACOP | 64
- PPC | KVM_REG_PPC_VRSAVE | 32
- PPC | KVM_REG_PPC_LPCR | 64
- PPC | KVM_REG_PPC_PPR | 64
- PPC | KVM_REG_PPC_ARCH_COMPAT 32
- PPC | KVM_REG_PPC_DABRX | 32
- PPC | KVM_REG_PPC_WORT | 64
- PPC | KVM_REG_PPC_TM_GPR0 | 64
+ PPC | KVM_REG_PPC_TM_GPR31 | 64
+ PPC | KVM_REG_PPC_TM_VSR0 | 128
...
- PPC | KVM_REG_PPC_TM_GPR31 | 64
- PPC | KVM_REG_PPC_TM_VSR0 | 128
+ PPC | KVM_REG_PPC_TM_VSR63 | 128
+ PPC | KVM_REG_PPC_TM_CR | 64
+ PPC | KVM_REG_PPC_TM_LR | 64
+ PPC | KVM_REG_PPC_TM_CTR | 64
+ PPC | KVM_REG_PPC_TM_FPSCR | 64
+ PPC | KVM_REG_PPC_TM_AMR | 64
+ PPC | KVM_REG_PPC_TM_PPR | 64
+ PPC | KVM_REG_PPC_TM_VRSAVE | 64
+ PPC | KVM_REG_PPC_TM_VSCR | 32
+ PPC | KVM_REG_PPC_TM_DSCR | 64
+ PPC | KVM_REG_PPC_TM_TAR | 64
+ | |
+ MIPS | KVM_REG_MIPS_R0 | 64
...
- PPC | KVM_REG_PPC_TM_VSR63 | 128
- PPC | KVM_REG_PPC_TM_CR | 64
- PPC | KVM_REG_PPC_TM_LR | 64
- PPC | KVM_REG_PPC_TM_CTR | 64
- PPC | KVM_REG_PPC_TM_FPSCR | 64
- PPC | KVM_REG_PPC_TM_AMR | 64
- PPC | KVM_REG_PPC_TM_PPR | 64
- PPC | KVM_REG_PPC_TM_VRSAVE | 64
- PPC | KVM_REG_PPC_TM_VSCR | 32
- PPC | KVM_REG_PPC_TM_DSCR | 64
- PPC | KVM_REG_PPC_TM_TAR | 64
+ MIPS | KVM_REG_MIPS_R31 | 64
+ MIPS | KVM_REG_MIPS_HI | 64
+ MIPS | KVM_REG_MIPS_LO | 64
+ MIPS | KVM_REG_MIPS_PC | 64
+ MIPS | KVM_REG_MIPS_CP0_INDEX | 32
+ MIPS | KVM_REG_MIPS_CP0_CONTEXT | 64
+ MIPS | KVM_REG_MIPS_CP0_USERLOCAL | 64
+ MIPS | KVM_REG_MIPS_CP0_PAGEMASK | 32
+ MIPS | KVM_REG_MIPS_CP0_WIRED | 32
+ MIPS | KVM_REG_MIPS_CP0_HWRENA | 32
+ MIPS | KVM_REG_MIPS_CP0_BADVADDR | 64
+ MIPS | KVM_REG_MIPS_CP0_COUNT | 32
+ MIPS | KVM_REG_MIPS_CP0_ENTRYHI | 64
+ MIPS | KVM_REG_MIPS_CP0_COMPARE | 32
+ MIPS | KVM_REG_MIPS_CP0_STATUS | 32
+ MIPS | KVM_REG_MIPS_CP0_CAUSE | 32
+ MIPS | KVM_REG_MIPS_CP0_EPC | 64
+ MIPS | KVM_REG_MIPS_CP0_CONFIG | 32
+ MIPS | KVM_REG_MIPS_CP0_CONFIG1 | 32
+ MIPS | KVM_REG_MIPS_CP0_CONFIG2 | 32
+ MIPS | KVM_REG_MIPS_CP0_CONFIG3 | 32
+ MIPS | KVM_REG_MIPS_CP0_CONFIG7 | 32
+ MIPS | KVM_REG_MIPS_CP0_ERROREPC | 64
+ MIPS | KVM_REG_MIPS_COUNT_CTL | 64
+ MIPS | KVM_REG_MIPS_COUNT_RESUME | 64
+ MIPS | KVM_REG_MIPS_COUNT_HZ | 64
ARM registers are mapped using the lower 32 bits. The upper 16 of that
is the register group type, or coprocessor number:
@@ -1928,6 +1984,22 @@ arm64 CCSIDR registers are demultiplexed by CSSELR value:
arm64 system registers have the following id bit patterns:
0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
+
+MIPS registers are mapped using the lower 32 bits. The upper 16 of that is
+the register group type:
+
+MIPS core registers (see above) have the following id bit patterns:
+ 0x7030 0000 0000 <reg:16>
+
+MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
+patterns depending on whether they're 32-bit or 64-bit registers:
+ 0x7020 0000 0001 00 <reg:5> <sel:3> (32-bit)
+ 0x7030 0000 0001 00 <reg:5> <sel:3> (64-bit)
+
+MIPS KVM control registers (see above) have the following id bit patterns:
+ 0x7030 0000 0002 <reg:16>
+
+
4.69 KVM_GET_ONE_REG
Capability: KVM_CAP_ONE_REG
@@ -2415,7 +2487,7 @@ in VCPU matching underlying host.
4.84 KVM_GET_REG_LIST
Capability: basic
-Architectures: arm, arm64
+Architectures: arm, arm64, mips
Type: vcpu ioctl
Parameters: struct kvm_reg_list (in/out)
Returns: 0 on success; -1 on error
@@ -2609,8 +2681,8 @@ The 'data' member contains, in its first 'len' bytes, the value as it would
appear if the VCPU performed a load or store of the appropriate width directly
to the byte array.
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_DCR,
- KVM_EXIT_PAPR and KVM_EXIT_EPR the corresponding
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
+ KVM_EXIT_EPR the corresponding
operations are complete (and guest state is consistent) only after userspace
has re-entered the kernel with KVM_RUN. The kernel side will first finish
incomplete operations and then check for pending signals. Userspace
@@ -2681,7 +2753,7 @@ Principles of Operation Book in the Chapter for Dynamic Address Translation
__u8 is_write;
} dcr;
-powerpc specific.
+Deprecated - was used for 440 KVM.
/* KVM_EXIT_OSI */
struct {
@@ -2863,18 +2935,21 @@ The fields in each entry are defined as follows:
this function/index combination
-6. Capabilities that can be enabled
------------------------------------
+6. Capabilities that can be enabled on vCPUs
+--------------------------------------------
-There are certain capabilities that change the behavior of the virtual CPU when
-enabled. To enable them, please see section 4.37. Below you can find a list of
-capabilities and what their effect on the vCPU is when enabling them.
+There are certain capabilities that change the behavior of the virtual CPU or
+the virtual machine when enabled. To enable them, please see section 4.37.
+Below you can find a list of capabilities and what their effect on the vCPU or
+the virtual machine is when enabling them.
The following information is provided along with the description:
Architectures: which instruction set architectures provide this ioctl.
x86 includes both i386 and x86_64.
+ Target: whether this is a per-vcpu or per-vm capability.
+
Parameters: what parameters are accepted by the capability.
Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL)
@@ -2884,6 +2959,7 @@ The following information is provided along with the description:
6.1 KVM_CAP_PPC_OSI
Architectures: ppc
+Target: vcpu
Parameters: none
Returns: 0 on success; -1 on error
@@ -2898,6 +2974,7 @@ When this capability is enabled, KVM_EXIT_OSI can occur.
6.2 KVM_CAP_PPC_PAPR
Architectures: ppc
+Target: vcpu
Parameters: none
Returns: 0 on success; -1 on error
@@ -2917,6 +2994,7 @@ When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
6.3 KVM_CAP_SW_TLB
Architectures: ppc
+Target: vcpu
Parameters: args[0] is the address of a struct kvm_config_tlb
Returns: 0 on success; -1 on error
@@ -2959,6 +3037,7 @@ For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
6.4 KVM_CAP_S390_CSS_SUPPORT
Architectures: s390
+Target: vcpu
Parameters: none
Returns: 0 on success; -1 on error
@@ -2970,9 +3049,13 @@ handled in-kernel, while the other I/O instructions are passed to userspace.
When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
SUBCHANNEL intercepts.
+Note that even though this capability is enabled per-vcpu, the complete
+virtual machine is affected.
+
6.5 KVM_CAP_PPC_EPR
Architectures: ppc
+Target: vcpu
Parameters: args[0] defines whether the proxy facility is active
Returns: 0 on success; -1 on error
@@ -2998,7 +3081,57 @@ This capability connects the vcpu to an in-kernel MPIC device.
6.7 KVM_CAP_IRQ_XICS
Architectures: ppc
+Target: vcpu
Parameters: args[0] is the XICS device fd
args[1] is the XICS CPU number (server ID) for this vcpu
This capability connects the vcpu to an in-kernel XICS device.
+
+6.8 KVM_CAP_S390_IRQCHIP
+
+Architectures: s390
+Target: vm
+Parameters: none
+
+This capability enables the in-kernel irqchip for s390. Please refer to
+"4.24 KVM_CREATE_IRQCHIP" for details.
+
+7. Capabilities that can be enabled on VMs
+------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual
+machine when enabled. To enable them, please see section 4.37. Below
+you can find a list of capabilities and what their effect on the VM
+is when enabling them.
+
+The following information is provided along with the description:
+
+ Architectures: which instruction set architectures provide this ioctl.
+ x86 includes both i386 and x86_64.
+
+ Parameters: what parameters are accepted by the capability.
+
+ Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL)
+ are not detailed, but errors with specific meanings are.
+
+
+7.1 KVM_CAP_PPC_ENABLE_HCALL
+
+Architectures: ppc
+Parameters: args[0] is the sPAPR hcall number
+ args[1] is 0 to disable, 1 to enable in-kernel handling
+
+This capability controls whether individual sPAPR hypercalls (hcalls)
+get handled by the kernel or not. Enabling or disabling in-kernel
+handling of an hcall is effective across the VM. On creation, an
+initial set of hcalls are enabled for in-kernel handling, which
+consists of those hcalls for which in-kernel handlers were implemented
+before this capability was implemented. If disabled, the kernel will
+not to attempt to handle the hcall, but will always exit to userspace
+to handle it. Note that it may not make sense to enable some and
+disable others of a group of related hcalls, but KVM does not prevent
+userspace from doing that.
+
+If the hcall number specified is not one that has an in-kernel
+implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
+error.
diff --git a/Documentation/w1/slaves/w1_ds2406 b/Documentation/w1/slaves/w1_ds2406
new file mode 100644
index 000000000000..8137fe6f6c3d
--- /dev/null
+++ b/Documentation/w1/slaves/w1_ds2406
@@ -0,0 +1,25 @@
+w1_ds2406 kernel driver
+=======================
+
+Supported chips:
+ * Maxim DS2406 (and other family 0x12) addressable switches
+
+Author: Scott Alfter <scott@alfter.us>
+
+Description
+-----------
+
+The w1_ds2406 driver allows connected devices to be switched on and off.
+These chips also provide 128 bytes of OTP EPROM, but reading/writing it is
+not supported. In TSOC-6 form, the DS2406 provides two switch outputs and
+can be provided with power on a dedicated input. In TO-92 form, it provides
+one output and uses parasitic power only.
+
+The driver provides two sysfs files. state is readable; it gives the
+current state of each switch, with PIO A in bit 0 and PIO B in bit 1. The
+driver ORs this state with 0x30, so shell scripts get an ASCII 0/1/2/3 to
+work with. output is writable; bits 0 and 1 control PIO A and B,
+respectively. Bits 2-7 are ignored, so it's safe to write ASCII data.
+
+CRCs are checked on read and write. Failed checks cause an I/O error to be
+returned. On a failed write, the switch status is not changed.
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index eb7132ed8bbc..b3a701f48118 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -118,7 +118,7 @@ resets.
Note that the pretimeout is the number of seconds before the time
when the timeout will go off. It is not the number of seconds until
the pretimeout. So, for instance, if you set the timeout to 60 seconds
-and the pretimeout to 10 seconds, the pretimout will go of in 50
+and the pretimeout to 10 seconds, the pretimeout will go off in 50
seconds. Setting a pretimeout to zero disables it.
There is also a get function for getting the pretimeout:
diff --git a/Documentation/x86/tlb.txt b/Documentation/x86/tlb.txt
new file mode 100644
index 000000000000..2b3a82e69151
--- /dev/null
+++ b/Documentation/x86/tlb.txt
@@ -0,0 +1,75 @@
+When the kernel unmaps or modified the attributes of a range of
+memory, it has two choices:
+ 1. Flush the entire TLB with a two-instruction sequence. This is
+ a quick operation, but it causes collateral damage: TLB entries
+ from areas other than the one we are trying to flush will be
+ destroyed and must be refilled later, at some cost.
+ 2. Use the invlpg instruction to invalidate a single page at a
+ time. This could potentialy cost many more instructions, but
+ it is a much more precise operation, causing no collateral
+ damage to other TLB entries.
+
+Which method to do depends on a few things:
+ 1. The size of the flush being performed. A flush of the entire
+ address space is obviously better performed by flushing the
+ entire TLB than doing 2^48/PAGE_SIZE individual flushes.
+ 2. The contents of the TLB. If the TLB is empty, then there will
+ be no collateral damage caused by doing the global flush, and
+ all of the individual flush will have ended up being wasted
+ work.
+ 3. The size of the TLB. The larger the TLB, the more collateral
+ damage we do with a full flush. So, the larger the TLB, the
+ more attrative an individual flush looks. Data and
+ instructions have separate TLBs, as do different page sizes.
+ 4. The microarchitecture. The TLB has become a multi-level
+ cache on modern CPUs, and the global flushes have become more
+ expensive relative to single-page flushes.
+
+There is obviously no way the kernel can know all these things,
+especially the contents of the TLB during a given flush. The
+sizes of the flush will vary greatly depending on the workload as
+well. There is essentially no "right" point to choose.
+
+You may be doing too many individual invalidations if you see the
+invlpg instruction (or instructions _near_ it) show up high in
+profiles. If you believe that individual invalidations being
+called too often, you can lower the tunable:
+
+ /sys/debug/kernel/x86/tlb_single_page_flush_ceiling
+
+This will cause us to do the global flush for more cases.
+Lowering it to 0 will disable the use of the individual flushes.
+Setting it to 1 is a very conservative setting and it should
+never need to be 0 under normal circumstances.
+
+Despite the fact that a single individual flush on x86 is
+guaranteed to flush a full 2MB [1], hugetlbfs always uses the full
+flushes. THP is treated exactly the same as normal memory.
+
+You might see invlpg inside of flush_tlb_mm_range() show up in
+profiles, or you can use the trace_tlb_flush() tracepoints. to
+determine how long the flush operations are taking.
+
+Essentially, you are balancing the cycles you spend doing invlpg
+with the cycles that you spend refilling the TLB later.
+
+You can measure how expensive TLB refills are by using
+performance counters and 'perf stat', like this:
+
+perf stat -e
+ cpu/event=0x8,umask=0x84,name=dtlb_load_misses_walk_duration/,
+ cpu/event=0x8,umask=0x82,name=dtlb_load_misses_walk_completed/,
+ cpu/event=0x49,umask=0x4,name=dtlb_store_misses_walk_duration/,
+ cpu/event=0x49,umask=0x2,name=dtlb_store_misses_walk_completed/,
+ cpu/event=0x85,umask=0x4,name=itlb_misses_walk_duration/,
+ cpu/event=0x85,umask=0x2,name=itlb_misses_walk_completed/
+
+That works on an IvyBridge-era CPU (i5-3320M). Different CPUs
+may have differently-named counters, but they should at least
+be there in some form. You can use pmu-tools 'ocperf list'
+(https://github.com/andikleen/pmu-tools) to find the right
+counters for a given CPU.
+
+1. A footnote in Intel's SDM "4.10.4.2 Recommended Invalidation"
+ says: "One execution of INVLPG is sufficient even for a page
+ with size greater than 4 KBytes."
diff --git a/Documentation/zh_CN/SubmittingDrivers b/Documentation/zh_CN/SubmittingDrivers
index 5889f8df6312..d313f5d8448d 100644
--- a/Documentation/zh_CN/SubmittingDrivers
+++ b/Documentation/zh_CN/SubmittingDrivers
@@ -150,10 +150,6 @@ LWN.net:
将旧版内核的驱动程序移植到 2.6 版:
http://lwn.net/Articles/driver-porting/
-KernelTrap:
- Linux 内核的最新动态以及开发者访谈
- http://kerneltrap.org/
-
内核新手(KernelNewbies):
为新的内核开发者提供文档和帮助
http://kernelnewbies.org/
diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt
index 0da95dbaef34..2b828e631e31 100644
--- a/Documentation/zh_CN/video4linux/v4l2-framework.txt
+++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt
@@ -580,11 +580,6 @@ release()回调必须被设置,且在最后一个 video_device 用户退出之
v4l2_device 无法与特定的 PCI 设备关联,所有没有设置父设备。但当
video_device 配置后,就知道使用哪个父 PCI 设备了。
-- flags:可选。如果你要让框架处理设置 VIDIOC_G/S_PRIORITY ioctls,
- 请设置 V4L2_FL_USE_FH_PRIO。这要求你使用 v4l2_fh 结构体。
- 一旦所有驱动使用了核心的优先级处理,最终这个标志将消失。但现在它
- 必须被显式设置。
-
如果你使用 v4l2_ioctl_ops,则应该在 v4l2_file_operations 结构体中
设置 .unlocked_ioctl 指向 video_ioctl2。
@@ -789,7 +784,7 @@ v4l2_fh 结构体
-------------
v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。
-如果 video_device 的 flag 设置了 V4L2_FL_USE_FH_PRIO 标志,新驱动
+如果 video_device 标志,新驱动
必须使用 v4l2_fh 结构体,因为它也用于实现优先级处理(VIDIOC_G/S_PRIORITY)。
v4l2_fh 的用户(位于 V4l2 框架中,并非驱动)可通过测试
diff --git a/MAINTAINERS b/MAINTAINERS
index c2066f4c3286..3bf3fc26c891 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -70,6 +70,8 @@ Descriptions of section entries:
P: Person (obsolete)
M: Mail patches to: FullName <address@domain>
+ R: Designated reviewer: FullName <address@domain>
+ These reviewers should be CCed on patches.
L: Mailing list that is relevant to this area
W: Web-page with status/info
Q: Patchwork web based patch tracking system site
@@ -148,6 +150,14 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/53c700*
+6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
+M: Alexander Aring <alex.aring@gmail.com>
+L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-bluetooth@vger.kernel.org
+S: Maintained
+F: net/6lowpan/
+F: include/net/6lowpan.h
+
6PACK NETWORK DRIVER FOR AX.25
M: Andreas Koensgen <ajk@comnets.uni-bremen.de>
L: linux-hams@vger.kernel.org
@@ -514,6 +524,16 @@ S: Supported
F: fs/aio.c
F: include/linux/*aio*.h
+AIRSPY MEDIA DRIVER
+M: Antti Palosaari <crope@iki.fi>
+L: linux-media@vger.kernel.org
+W: http://linuxtv.org/
+W: http://palosaari.fi/linux/
+Q: http://patchwork.linuxtv.org/project/linux-media/list/
+T: git git://linuxtv.org/anttip/media_tree.git
+S: Maintained
+F: drivers/media/usb/airspy/
+
ALCATEL SPEEDTOUCH USB DRIVER
M: Duncan Sands <duncan.sands@free.fr>
L: linux-usb@vger.kernel.org
@@ -577,7 +597,7 @@ AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
M: Thomas Dahlmann <dahlmann.thomas@arcor.de>
L: linux-geode@lists.infradead.org (moderated for non-subscribers)
S: Supported
-F: drivers/usb/gadget/amd5536udc.*
+F: drivers/usb/gadget/udc/amd5536udc.*
AMD GEODE PROCESSOR/CHIPSET SUPPORT
P: Andres Salomon <dilinger@queued.net>
@@ -586,7 +606,7 @@ W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_
S: Supported
F: drivers/char/hw_random/geode-rng.c
F: drivers/crypto/geode*
-F: drivers/video/geode/
+F: drivers/video/fbdev/geode/
F: arch/x86/include/asm/geode.h
AMD IOMMU (AMD-VI)
@@ -601,7 +621,7 @@ AMD MICROCODE UPDATE SUPPORT
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
L: amd64-microcode@amd64.org
S: Maintained
-F: arch/x86/kernel/microcode_amd.c
+F: arch/x86/kernel/cpu/microcode/amd*
AMD XGBE DRIVER
M: Tom Lendacky <thomas.lendacky@amd.com>
@@ -699,6 +719,14 @@ S: Maintained
F: drivers/net/appletalk/
F: net/appletalk/
+APPLIED MICRO (APM) X-GENE SOC ETHERNET DRIVER
+M: Iyappan Subramanian <isubramanian@apm.com>
+M: Keyur Chudgar <kchudgar@apm.com>
+M: Ravi Patel <rapatel@apm.com>
+S: Supported
+F: drivers/net/ethernet/apm/xgene/
+F: Documentation/devicetree/bindings/net/apm-xgene-enet.txt
+
APTINA CAMERA SENSOR PLL
M: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
@@ -715,8 +743,8 @@ F: drivers/ata/pata_arasan_cf.c
ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained
-F: drivers/video/arcfb.c
-F: drivers/video/fb_defio.c
+F: drivers/video/fbdev/arcfb.c
+F: drivers/video/fbdev/core/fb_defio.c
ARM MFM AND FLOPPY DRIVERS
M: Ian Molton <spyro@f2s.com>
@@ -755,7 +783,7 @@ F: sound/arm/aaci.*
ARM PRIMECELL CLCD PL110 DRIVER
M: Russell King <linux@arm.linux.org.uk>
S: Maintained
-F: drivers/video/amba-clcd.*
+F: drivers/video/fbdev/amba-clcd.*
ARM PRIMECELL KMI PL050 DRIVER
M: Russell King <linux@arm.linux.org.uk>
@@ -891,7 +919,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/baohua/linux.git
S: Maintained
F: arch/arm/mach-prima2/
-F: drivers/clk/clk-prima2.c
+F: drivers/clk/sirf/
F: drivers/clocksource/timer-prima2.c
F: drivers/clocksource/timer-marco.c
N: [^a-z]sirf
@@ -965,6 +993,14 @@ F: arch/arm/mach-pxa/hx4700.c
F: arch/arm/mach-pxa/include/mach/hx4700.h
F: sound/soc/pxa/hx4700.c
+ARM/HISILICON SOC SUPPORT
+M: Wei Xu <xuwei5@hisilicon.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+W: http://www.hisilicon.com
+S: Supported
+T: git git://github.com/hisilicon/linux-hisi.git
+F: arch/arm/mach-hisi/
+
ARM/HP JORNADA 7XX MACHINE SUPPORT
M: Kristoffer Ericson <kristoffer.ericson@gmail.com>
W: www.jlime.com
@@ -1096,14 +1132,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-berlin/
-ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
+ARM/Marvell Dove/MV78xx0/Orion SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-dove/
-F: arch/arm/mach-kirkwood/
F: arch/arm/mach-mv78xx0/
F: arch/arm/mach-orion5x/
F: arch/arm/plat-orion/
@@ -1137,6 +1172,7 @@ M: Linus Walleij <linus.walleij@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-nomadik/
+F: drivers/pinctrl/nomadik/
F: drivers/i2c/busses/i2c-nomadik.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
@@ -1152,14 +1188,13 @@ M: Daniel Walker <dwalker@fifo99.com>
M: Bryan Huntsman <bryanh@codeaurora.org>
L: linux-arm-msm@vger.kernel.org
F: arch/arm/mach-msm/
-F: drivers/video/msm/
+F: drivers/video/fbdev/msm/
F: drivers/mmc/host/msm_sdcc.c
F: drivers/mmc/host/msm_sdcc.h
F: drivers/tty/serial/msm_serial.h
F: drivers/tty/serial/msm_serial.c
F: drivers/*/pm8???-*
-F: drivers/mfd/ssbi/
-F: include/linux/mfd/pm8xxx/
+F: drivers/mfd/ssbi.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
S: Maintained
@@ -1356,6 +1391,7 @@ F: drivers/pinctrl/pinctrl-st.c
F: drivers/media/rc/st_rc.c
F: drivers/i2c/busses/i2c-st.c
F: drivers/tty/serial/st-asc.c
+F: drivers/mmc/host/sdhci-st.c
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
@@ -1386,7 +1422,7 @@ F: drivers/mtd/nand/nuc900_nand.c
F: drivers/rtc/rtc-nuc900.c
F: drivers/spi/spi-nuc900.c
F: drivers/usb/host/ehci-w90x900.c
-F: drivers/video/nuc900fb.c
+F: drivers/video/fbdev/nuc900fb.c
ARM/U300 MACHINE SUPPORT
M: Linus Walleij <linus.walleij@linaro.org>
@@ -1415,7 +1451,8 @@ F: drivers/mfd/abx500*
F: drivers/mfd/ab8500*
F: drivers/mfd/dbx500*
F: drivers/mfd/db8500*
-F: drivers/pinctrl/pinctrl-nomadik*
+F: drivers/pinctrl/nomadik/pinctrl-ab*
+F: drivers/pinctrl/nomadik/pinctrl-nomadik*
F: drivers/rtc/rtc-ab8500.c
F: drivers/rtc/rtc-pl031.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
@@ -1455,9 +1492,9 @@ F: drivers/rtc/rtc-vt8500.c
F: drivers/tty/serial/vt8500_serial.c
F: drivers/usb/host/ehci-platform.c
F: drivers/usb/host/uhci-platform.c
-F: drivers/video/vt8500lcdfb.*
-F: drivers/video/wm8505fb*
-F: drivers/video/wmt_ge_rops.*
+F: drivers/video/fbdev/vt8500lcdfb.*
+F: drivers/video/fbdev/wm8505fb*
+F: drivers/video/fbdev/wmt_ge_rops.*
ARM/ZIPIT Z2 SUPPORT
M: Marek Vasut <marek.vasut@gmail.com>
@@ -1647,7 +1684,7 @@ ATMEL LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/atmel_lcdfb.c
+F: drivers/video/fbdev/atmel_lcdfb.c
F: include/video/atmel_lcdc.h
ATMEL MACB ETHERNET DRIVER
@@ -1671,7 +1708,7 @@ ATMEL USBA UDC DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
-F: drivers/usb/gadget/atmel_usba_udc.*
+F: drivers/usb/gadget/udc/atmel_usba_udc.*
ATMEL WIRELESS DRIVER
M: Simon Kelley <simon@thekelleys.org.uk>
@@ -1794,6 +1831,13 @@ W: http://bcache.evilpiepirate.org
S: Maintained:
F: drivers/md/bcache/
+BECEEM BCS200/BCS220-3/BCSM250 WIMAX SUPPORT
+M: Kevin McKinney <klmckinney1@gmail.com>
+M: Matthias Beyer <mail@beyermatthias.de>
+L: devel@driverdev.osuosl.org
+S: Maintained
+F: drivers/staging/bcm*
+
BEFS FILE SYSTEM
S: Orphan
F: Documentation/filesystems/befs.txt
@@ -1912,6 +1956,13 @@ S: Supported
F: drivers/net/bonding/
F: include/uapi/linux/if_bonding.h
+BPF (Safe dynamic programs and tools)
+M: Alexei Starovoitov <ast@kernel.org>
+L: netdev@vger.kernel.org
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: kernel/bpf/
+
BROADCOM B44 10/100 ETHERNET DRIVER
M: Gary Zambrano <zambrano@broadcom.com>
L: netdev@vger.kernel.org
@@ -1925,7 +1976,8 @@ S: Supported
F: drivers/net/ethernet/broadcom/genet/
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-M: Michael Chan <mchan@broadcom.com>
+M: Sony Chacko <sony.chacko@qlogic.com>
+M: Dept-HSGLinuxNICDev@qlogic.com
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/broadcom/bnx2.*
@@ -1948,7 +2000,7 @@ F: arch/arm/boot/dts/bcm113*
F: arch/arm/boot/dts/bcm216*
F: arch/arm/boot/dts/bcm281*
F: arch/arm/configs/bcm_defconfig
-F: drivers/mmc/host/sdhci_bcm_kona.c
+F: drivers/mmc/host/sdhci-bcm-kona.c
F: drivers/clocksource/bcm_kona_timer.c
BROADCOM BCM2835 ARM ARCHICTURE
@@ -1969,8 +2021,16 @@ F: arch/arm/mach-bcm/bcm_5301x.c
F: arch/arm/boot/dts/bcm5301x.dtsi
F: arch/arm/boot/dts/bcm470*
+BROADCOM BCM7XXX ARM ARCHITECTURE
+M: Marc Carino <marc.ceeeee@gmail.com>
+M: Brian Norris <computersforpeace@gmail.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-bcm/*brcmstb*
+F: arch/arm/boot/dts/bcm7*.dts*
+
BROADCOM TG3 GIGABIT ETHERNET DRIVER
-M: Nithin Nayak Sujir <nsujir@broadcom.com>
+M: Prashant Sreedharan <prashant@broadcom.com>
M: Michael Chan <mchan@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
@@ -1987,13 +2047,13 @@ S: Supported
F: drivers/net/wireless/brcm80211/
BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
-M: Eddie Wai <eddie.wai@broadcom.com>
+M: QLogic-Storage-Upstream@qlogic.com
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/bnx2fc/
BROADCOM BNX2I 1/10 GIGABIT iSCSI DRIVER
-M: Eddie Wai <eddie.wai@broadcom.com>
+M: QLogic-Storage-Upstream@qlogic.com
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/bnx2i/
@@ -2290,12 +2350,6 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/cirrus/ep93xx_eth.c
-CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
-M: Lennert Buytenhek <kernel@wantstofly.org>
-L: linux-usb@vger.kernel.org
-S: Maintained
-F: drivers/usb/host/ohci-ep93xx.c
-
CIRRUS LOGIC AUDIO CODEC DRIVERS
M: Brian Austin <brian.austin@cirrus.com>
M: Paul Handrigan <Paul.Handrigan@cirrus.com>
@@ -2380,7 +2434,7 @@ W: http://linux-cifs.samba.org/
Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
S: Supported
-F: Documentation/filesystems/cifs.txt
+F: Documentation/filesystems/cifs/
F: fs/cifs/
COMPACTPCI HOTPLUG CORE
@@ -2521,8 +2575,8 @@ F: arch/x86/kernel/cpuid.c
F: arch/x86/kernel/msr.c
CPU POWER MONITORING SUBSYSTEM
-M: Dominik Brodowski <linux@dominikbrodowski.net>
M: Thomas Renninger <trenn@suse.de>
+L: linux-pm@vger.kernel.org
S: Maintained
F: tools/power/cpupower/
@@ -2657,7 +2711,7 @@ M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.arm.linux.org.uk/
S: Maintained
-F: drivers/video/cyber2000fb.*
+F: drivers/video/fbdev/cyber2000fb.*
CYCLADES ASYNC MUX DRIVER
W: http://www.cyclades.com/
@@ -2857,6 +2911,7 @@ F: drivers/staging/dgnc/
DIGI EPCA PCI PRODUCTS
M: Lidza Louina <lidza.louina@gmail.com>
M: Mark Hounschell <markh@compro.net>
+M: Daeseok Youn <daeseok.youn@gmail.com>
L: driverdev-devel@linuxdriverproject.org
S: Maintained
F: drivers/staging/dgap/
@@ -2894,7 +2949,7 @@ M: Bernie Thompson <bernie@plugable.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
W: http://plugable.com/category/projects/udlfb/
-F: drivers/video/udlfb.c
+F: drivers/video/fbdev/udlfb.c
F: include/video/udlfb.h
F: Documentation/fb/udlfb.txt
@@ -2913,8 +2968,10 @@ S: Maintained
L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org
L: linaro-mm-sig@lists.linaro.org
-F: drivers/base/dma-buf*
+F: drivers/dma-buf/
F: include/linux/dma-buf*
+F: include/linux/reservation.h
+F: include/linux/*fence.h
F: Documentation/dma-buf-sharing.txt
T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
@@ -3009,7 +3066,6 @@ L: dri-devel@lists.freedesktop.org
T: git git://people.freedesktop.org/~agd5f/linux
S: Supported
F: drivers/gpu/drm/radeon/
-F: include/drm/radeon*
F: include/uapi/drm/radeon*
DRM PANEL DRIVERS
@@ -3203,26 +3259,12 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/tuners/e4000*
-EATA-DMA SCSI DRIVER
-M: Michael Neuffer <mike@i-Connect.Net>
-L: linux-eata@i-connect.net
-L: linux-scsi@vger.kernel.org
-S: Maintained
-F: drivers/scsi/eata*
-
EATA ISA/EISA/PCI SCSI DRIVER
M: Dario Ballabio <ballabio_dario@emc.com>
L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/eata.c
-EATA-PIO SCSI DRIVER
-M: Michael Neuffer <mike@i-Connect.Net>
-L: linux-eata@i-connect.net
-L: linux-scsi@vger.kernel.org
-S: Maintained
-F: drivers/scsi/eata_pio.*
-
EC100 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
@@ -3350,6 +3392,13 @@ W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82975x_edac.c
+EDAC-IE31200
+M: Jason Baron <jbaron@akamai.com>
+L: linux-edac@vger.kernel.org
+W: bluesmoke.sourceforge.net
+S: Maintained
+F: drivers/edac/ie31200_edac.c
+
EDAC-MPC85XX
M: Johannes Thumshirn <johannes.thumshirn@men.de>
L: linux-edac@vger.kernel.org
@@ -3390,7 +3439,7 @@ M: Matt Fleming <matt.fleming@intel.com>
L: linux-efi@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
S: Maintained
-F: Documentation/x86/efi-stub.txt
+F: Documentation/efi-stub.txt
F: arch/ia64/kernel/efi.c
F: arch/x86/boot/compressed/eboot.[ch]
F: arch/x86/include/asm/efi.h
@@ -3411,7 +3460,7 @@ EFIFB FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
M: Peter Jones <pjones@redhat.com>
S: Maintained
-F: drivers/video/efifb.c
+F: drivers/video/fbdev/efifb.c
EFS FILESYSTEM
W: http://aeschi.ch.eu.org/efs/
@@ -3476,7 +3525,7 @@ EPSON S1D13XXX FRAMEBUFFER DRIVER
M: Kristoffer Ericson <kristoffer.ericson@gmail.com>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
-F: drivers/video/s1d13xxxfb.c
+F: drivers/video/fbdev/s1d13xxxfb.c
F: include/video/s1d13xxxfb.h
ETHERNET BRIDGE
@@ -3554,7 +3603,7 @@ M: Donghwa Lee <dh09.lee@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/exynos/exynos_mipi*
+F: drivers/video/fbdev/exynos/exynos_mipi*
F: include/video/exynos_mipi*
F71805F HARDWARE MONITORING DRIVER
@@ -3733,7 +3782,7 @@ FREESCALE DIU FRAMEBUFFER DRIVER
M: Timur Tabi <timur@tabi.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/fsl-diu-fb.*
+F: drivers/video/fbdev/fsl-diu-fb.*
FREESCALE DMA DRIVER
M: Li Yang <leoli@freescale.com>
@@ -3755,7 +3804,7 @@ L: linux-fbdev@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: include/linux/platform_data/video-imxfb.h
-F: drivers/video/imxfb.c
+F: drivers/video/fbdev/imxfb.c
FREESCALE SOC FS_ENET DRIVER
M: Pantelis Antoniou <pantelis.antoniou@gmail.com>
@@ -3777,7 +3826,7 @@ M: Li Yang <leoli@freescale.com>
L: linux-usb@vger.kernel.org
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
-F: drivers/usb/gadget/fsl*
+F: drivers/usb/gadget/udc/fsl*
FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
M: Li Yang <leoli@freescale.com>
@@ -3976,6 +4025,12 @@ F: Documentation/isdn/README.gigaset
F: drivers/isdn/gigaset/
F: include/uapi/linux/gigaset_dev.h
+GO7007 MPEG CODEC
+M: Hans Verkuil <hans.verkuil@cisco.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: drivers/media/usb/go7007/
+
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>
@@ -3984,7 +4039,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
S: Maintained
F: Documentation/gpio/
F: drivers/gpio/
-F: include/linux/gpio*
+F: include/linux/gpio/
+F: include/linux/gpio.h
F: include/asm-generic/gpio.h
GRE DEMULTIPLEXER DRIVER
@@ -4174,7 +4230,7 @@ M: Ferenc Bakonyi <fero@drama.obuda.kando.hu>
L: linux-nvidia@lists.surfsouth.com
W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
S: Maintained
-F: drivers/video/hgafb.c
+F: drivers/video/fbdev/hgafb.c
HIBERNATION (aka Software Suspend, aka swsusp)
M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
@@ -4204,7 +4260,7 @@ L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
S: Maintained
F: Documentation/timers/
-F: kernel/hrtimer.c
+F: kernel/time/hrtimer.c
F: kernel/time/clockevents.c
F: kernel/time/tick*.*
F: kernel/time/timer_*.c
@@ -4316,7 +4372,7 @@ F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
-F: drivers/video/hyperv_fb.c
+F: drivers/video/fbdev/hyperv_fb.c
F: include/linux/hyperv.h
F: tools/hv/
@@ -4460,10 +4516,7 @@ S: Supported
F: drivers/scsi/ibmvscsi/ibmvfc*
IBM ServeRAID RAID DRIVER
-P: Jack Hammer
-M: Dave Jeffery <ipslinux@adaptec.com>
-W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
-S: Supported
+S: Orphan
F: drivers/scsi/ips.*
ICH LPC AND GPIO DRIVER
@@ -4575,7 +4628,7 @@ F: security/integrity/ima/
IMS TWINTURBO FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
-F: drivers/video/imsttfb.c
+F: drivers/video/fbdev/imsttfb.c
INFINIBAND SUBSYSTEM
M: Roland Dreier <roland@kernel.org>
@@ -4642,13 +4695,13 @@ M: Maik Broemme <mbroemme@plusserver.de>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: Documentation/fb/intelfb.txt
-F: drivers/video/intelfb/
+F: drivers/video/fbdev/intelfb/
INTEL 810/815 FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/i810/
+F: drivers/video/fbdev/i810/
INTEL MENLOW THERMAL DRIVER
M: Sujith Thomas <sujith.thomas@intel.com>
@@ -4660,8 +4713,8 @@ F: drivers/platform/x86/intel_menlow.c
INTEL IA32 MICROCODE UPDATE SUPPORT
M: Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
S: Maintained
-F: arch/x86/kernel/microcode_core.c
-F: arch/x86/kernel/microcode_intel.c
+F: arch/x86/kernel/cpu/microcode/core*
+F: arch/x86/kernel/cpu/microcode/intel*
INTEL I/OAT DMA DRIVER
M: Dan Williams <dan.j.williams@intel.com>
@@ -5066,13 +5119,6 @@ S: Maintained
F: Documentation/hwmon/k8temp
F: drivers/hwmon/k8temp.c
-KTAP
-M: Jovi Zhangwei <jovi.zhangwei@gmail.com>
-W: http://www.ktap.org
-L: ktap@freelists.org
-S: Maintained
-F: drivers/staging/ktap/
-
KCONFIG
M: "Yann E. MORIN" <yann.morin.1998@free.fr>
L: linux-kbuild@vger.kernel.org
@@ -5127,7 +5173,6 @@ L: linux-nfs@vger.kernel.org
W: http://nfs.sourceforge.net/
S: Supported
F: fs/nfsd/
-F: include/linux/nfsd/
F: include/uapi/linux/nfsd/
F: fs/lockd/
F: fs/nfs_common/
@@ -5382,6 +5427,7 @@ F: arch/powerpc/boot/rs6000.h
LINUX FOR POWERPC (32-BIT AND 64-BIT)
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
M: Paul Mackerras <paulus@samba.org>
+M: Michael Ellerman <mpe@ellerman.id.au>
W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/
@@ -5423,16 +5469,17 @@ F: arch/powerpc/*/*/*virtex*
LINUX FOR POWERPC EMBEDDED PPC8XX
M: Vitaly Bordug <vitb@kernel.crashing.org>
-M: Marcelo Tosatti <marcelo@kvack.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
F: arch/powerpc/platforms/8xx/
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
+M: Scott Wood <scottwood@freescale.com>
M: Kumar Gala <galak@kernel.crashing.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@lists.ozlabs.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
S: Maintained
F: arch/powerpc/platforms/83xx/
F: arch/powerpc/platforms/85xx/
@@ -5655,16 +5702,6 @@ F: Documentation/networking/mac80211-injection.txt
F: include/net/mac80211.h
F: net/mac80211/
-MAC80211 PID RATE CONTROL
-M: Stefano Brivio <stefano.brivio@polimi.it>
-M: Mattias Nissler <mattias.nissler@gmx.de>
-L: linux-wireless@vger.kernel.org
-W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
-S: Maintained
-F: net/mac80211/rc80211_pid*
-
MACVLAN DRIVER
M: Patrick McHardy <kaber@trash.net>
L: netdev@vger.kernel.org
@@ -5709,7 +5746,8 @@ S: Maintained
F: drivers/net/ethernet/marvell/mvneta.*
MARVELL MWIFIEX WIRELESS DRIVER
-M: Bing Zhao <bzhao@marvell.com>
+M: Amitkumar Karwar <akarwar@marvell.com>
+M: Avinash Patil <patila@marvell.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/mwifiex/
@@ -5728,7 +5766,7 @@ F: drivers/mmc/host/mvsdio.*
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
-F: drivers/video/matrox/matroxfb_*
+F: drivers/video/fbdev/matrox/matroxfb_*
F: include/uapi/linux/matroxfb.h
MAX16065 HARDWARE MONITOR DRIVER
@@ -5855,7 +5893,6 @@ F: drivers/clocksource/metag_generic.c
F: drivers/irqchip/irq-metag.c
F: drivers/irqchip/irq-metag-ext.c
F: drivers/tty/metag_da.c
-F: fs/imgdafs/
MICROBLAZE ARCHITECTURE
M: Michal Simek <monstr@monstr.eu>
@@ -5955,9 +5992,9 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/msi3101/msi001*
+F: drivers/media/tuners/msi001*
-MSI3101 MEDIA DRIVER
+MSI2500 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
W: http://linuxtv.org/
@@ -5965,7 +6002,7 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/msi3101/sdr-msi3101*
+F: drivers/media/usb/msi2500/
MT9M032 APTINA SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -6002,8 +6039,7 @@ F: include/media/mt9v032.h
MULTIFUNCTION DEVICES (MFD)
M: Samuel Ortiz <sameo@linux.intel.com>
M: Lee Jones <lee.jones@linaro.org>
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
S: Supported
F: drivers/mfd/
F: include/linux/mfd/
@@ -6370,8 +6406,8 @@ NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/riva/
-F: drivers/video/nvidia/
+F: drivers/video/fbdev/riva/
+F: drivers/video/fbdev/nvidia/
NVM EXPRESS DRIVER
M: Matthew Wilcox <willy@linux.intel.com>
@@ -6441,14 +6477,14 @@ M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org
L: linux-omap@vger.kernel.org
S: Maintained
-F: drivers/video/omap/
+F: drivers/video/fbdev/omap/
OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-omap@vger.kernel.org
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/omap2/
+F: drivers/video/fbdev/omap2/
F: Documentation/arm/OMAP/DSS
OMAP HARDWARE SPINLOCK SUPPORT
@@ -6489,11 +6525,12 @@ L: linux-omap@vger.kernel.org
S: Maintained
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
-OMAP IMAGE SIGNAL PROCESSOR (ISP)
+OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/platform/omap3isp/
+F: drivers/staging/media/omap4iss/
OMAP USB SUPPORT
M: Felipe Balbi <balbi@ti.com>
@@ -6739,7 +6776,7 @@ F: drivers/char/agp/parisc-agp.c
F: drivers/input/serio/gscps2.c
F: drivers/parport/parport_gsc.*
F: drivers/tty/serial/8250/8250_gsc.c
-F: drivers/video/sti*
+F: drivers/video/fbdev/sti*
F: drivers/video/console/sti*
F: drivers/video/logo/logo_parisc*
@@ -6851,6 +6888,12 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
F: drivers/pci/host/pci-host-generic.c
+PCIE DRIVER FOR ST SPEAR13XX
+M: Mohit Kumar <mohit.kumar@st.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: drivers/pci/host/*spear*
+
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: linux-pcmcia@lists.infradead.org
@@ -6940,9 +6983,9 @@ M: Jamie Iles <jamie@jamieiles.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
T: git git://github.com/jamieiles/linux-2.6-ji.git
S: Supported
+F: arch/arm/boot/dts/picoxcell*
F: arch/arm/mach-picoxcell/
-F: drivers/*/picoxcell*
-F: drivers/*/*/picoxcell*
+F: drivers/crypto/picoxcell*
PIN CONTROL SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
@@ -6968,9 +7011,7 @@ M: Thomas Abraham <thomas.abraham@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
-F: drivers/pinctrl/pinctrl-exynos.*
-F: drivers/pinctrl/pinctrl-s3c*
-F: drivers/pinctrl/pinctrl-samsung.*
+F: drivers/pinctrl/samsung/
PIN CONTROLLER - ST SPEAR
M: Viresh Kumar <viresh.linux@gmail.com>
@@ -6994,7 +7035,7 @@ S: Maintained
T: git git://github.com/gxt/linux.git
F: drivers/input/serio/i8042-unicore32io.h
F: drivers/i2c/busses/i2c-puv3.c
-F: drivers/video/fb-puv3.c
+F: drivers/video/fbdev/fb-puv3.c
F: drivers/rtc/rtc-puv3.c
PMBUS HARDWARE MONITORING DRIVERS
@@ -7018,6 +7059,7 @@ F: drivers/scsi/pmcraid.*
PMC SIERRA PM8001 DRIVER
M: xjtuwjp@gmail.com
M: lindar_liu@usish.com
+L: pmchba@pmcs.com
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/pm8001/
@@ -7026,14 +7068,16 @@ POSIX CLOCKS and TIMERS
M: Thomas Gleixner <tglx@linutronix.de>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
-S: Supported
+S: Maintained
F: fs/timerfd.c
F: include/linux/timer*
-F: kernel/*timer*
+F: kernel/time/*timer*
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
+M: Sebastian Reichel <sre@kernel.org>
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
M: David Woodhouse <dwmw2@infradead.org>
+L: linux-pm@vger.kernel.org
T: git git://git.infradead.org/battery-2.6.git
S: Maintained
F: include/linux/power_supply.h
@@ -7165,7 +7209,7 @@ F: drivers/ptp/*
F: include/linux/ptp_cl*
PTRACE SUPPORT
-M: Roland McGrath <roland@redhat.com>
+M: Roland McGrath <roland@hack.frob.com>
M: Oleg Nesterov <oleg@redhat.com>
S: Maintained
F: include/asm-generic/syscall.h
@@ -7215,7 +7259,7 @@ S: Maintained
F: arch/arm/mach-pxa/
F: drivers/pcmcia/pxa2xx*
F: drivers/spi/spi-pxa2xx*
-F: drivers/usb/gadget/pxa2*
+F: drivers/usb/gadget/udc/pxa2*
F: include/sound/pxa2xx-lib.h
F: sound/arm/pxa*
F: sound/soc/pxa/
@@ -7224,7 +7268,7 @@ PXA3xx NAND FLASH DRIVER
M: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
L: linux-mtd@lists.infradead.org
S: Maintained
-F: drivers/mtd/nand/pxa3xx-nand.c
+F: drivers/mtd/nand/pxa3xx_nand.c
MMP SUPPORT
M: Eric Miao <eric.y.miao@gmail.com>
@@ -7243,6 +7287,12 @@ M: Robert Jarzmik <robert.jarzmik@free.fr>
L: rtc-linux@googlegroups.com
S: Maintained
+QAT DRIVER
+M: Tadeusz Struk <tadeusz.struk@intel.com>
+L: qat-linux@intel.com
+S: Supported
+F: drivers/crypto/qat/
+
QIB DRIVER
M: Mike Marciniszyn <infinipath@intel.com>
L: linux-rdma@vger.kernel.org
@@ -7366,7 +7416,7 @@ RADEON FRAMEBUFFER DISPLAY DRIVER
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/aty/radeon*
+F: drivers/video/fbdev/aty/radeon*
F: include/uapi/linux/radeonfb.h
RADIOSHARK RADIO DRIVER
@@ -7388,7 +7438,7 @@ RAGE128 FRAMEBUFFER DISPLAY DRIVER
M: Paul Mackerras <paulus@samba.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/aty/aty128fb.c
+F: drivers/video/fbdev/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
@@ -7430,10 +7480,14 @@ L: linux-kernel@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
F: Documentation/RCU/torture.txt
-F: kernel/rcu/torture.c
+F: kernel/rcu/rcutorture.c
RCUTORTURE TEST FRAMEWORK
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+M: Josh Triplett <josh@joshtriplett.org>
+R: Steven Rostedt <rostedt@goodmis.org>
+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+R: Lai Jiangshan <laijs@cn.fujitsu.com>
L: linux-kernel@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
@@ -7456,8 +7510,11 @@ S: Supported
F: net/rds/
READ-COPY UPDATE (RCU)
-M: Dipankar Sarma <dipankar@in.ibm.com>
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+M: Josh Triplett <josh@joshtriplett.org>
+R: Steven Rostedt <rostedt@goodmis.org>
+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+R: Lai Jiangshan <laijs@cn.fujitsu.com>
L: linux-kernel@vger.kernel.org
W: http://www.rdrop.com/users/paulmck/RCU/
S: Supported
@@ -7467,7 +7524,7 @@ X: Documentation/RCU/torture.txt
F: include/linux/rcu*
X: include/linux/srcu.h
F: kernel/rcu/
-X: kernel/rcu/torture.c
+X: kernel/torture.c
REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alessandro Zummo <a.zummo@towertech.it>
@@ -7479,6 +7536,13 @@ F: drivers/rtc/
F: include/linux/rtc.h
F: include/uapi/linux/rtc.h
+REALTEK AUDIO CODECS
+M: Bard Liao <bardliao@realtek.com>
+M: Oder Chiou <oder_chiou@realtek.com>
+S: Maintained
+F: sound/soc/codecs/rt*
+F: include/sound/rt*.h
+
REISERFS FILE SYSTEM
L: reiserfs-devel@vger.kernel.org
S: Supported
@@ -7588,7 +7652,7 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/rtl2832u_sdr/rtl2832_sdr*
+F: drivers/media/dvb-frontends/rtl2832_sdr*
RTL8180 WIRELESS DRIVER
M: "John W. Linville" <linville@tuxdriver.com>
@@ -7622,7 +7686,7 @@ S3 SAVAGE FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/savage/
+F: drivers/video/fbdev/savage/
S390
M: Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -7745,7 +7809,7 @@ SAMSUNG FRAMEBUFFER DRIVER
M: Jingoo Han <jg1.han@samsung.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/s3c-fb.c
+F: drivers/video/fbdev/s3c-fb.c
SAMSUNG MULTIFUNCTION DEVICE DRIVERS
M: Sangbeom Kim <sbkim73@samsung.com>
@@ -7822,6 +7886,11 @@ S: Maintained
F: include/linux/mmc/dw_mmc.h
F: drivers/mmc/host/dw_mmc*
+THUNDERBOLT DRIVER
+M: Andreas Noever <andreas.noever@gmail.com>
+S: Maintained
+F: drivers/thunderbolt/
+
TIMEKEEPING, CLOCKSOURCE CORE, NTP
M: John Stultz <john.stultz@linaro.org>
M: Thomas Gleixner <tglx@linutronix.de>
@@ -7957,6 +8026,16 @@ S: Maintained
F: drivers/mmc/host/sdhci.*
F: drivers/mmc/host/sdhci-pltfm.[ch]
+SECURE COMPUTING
+M: Kees Cook <keescook@chromium.org>
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp
+S: Supported
+F: kernel/seccomp.c
+F: include/uapi/linux/seccomp.h
+F: include/linux/seccomp.h
+K: \bsecure_computing
+K: \bTIF_SECCOMP\b
+
SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
M: Anton Vorontsov <anton@enomsg.org>
L: linuxppc-dev@lists.ozlabs.org
@@ -8227,7 +8306,7 @@ M: Thomas Winischhofer <thomas@winischhofer.net>
W: http://www.winischhofer.net/linuxsisvga.shtml
S: Maintained
F: Documentation/fb/sisfb.txt
-F: drivers/video/sis/
+F: drivers/video/fbdev/sis/
F: include/video/sisfb.h
SIS USB2VGA DRIVER
@@ -8250,6 +8329,9 @@ F: mm/sl?b*
SLEEPABLE READ-COPY UPDATE (SRCU)
M: Lai Jiangshan <laijs@cn.fujitsu.com>
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+M: Josh Triplett <josh@joshtriplett.org>
+R: Steven Rostedt <rostedt@goodmis.org>
+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
L: linux-kernel@vger.kernel.org
W: http://www.rdrop.com/users/paulmck/RCU/
S: Supported
@@ -8333,7 +8415,7 @@ SMSC UFX6000 and UFX7000 USB to VGA DRIVER
M: Steve Glendinning <steve.glendinning@shawell.net>
L: linux-fbdev@vger.kernel.org
S: Maintained
-F: drivers/video/smscufx.c
+F: drivers/video/fbdev/smscufx.c
SOC-CAMERA V4L2 SUBSYSTEM
M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@@ -8349,6 +8431,12 @@ M: Chris Boot <bootc@bootc.net>
S: Maintained
F: drivers/leds/leds-net48xx.c
+SOFTLOGIC 6x10 MPEG CODEC
+M: Ismael Luceno <ismael.luceno@corp.bluecherry.net>
+L: linux-media@vger.kernel.org
+S: Supported
+F: drivers/media/pci/solo6x10/
+
SOFTWARE RAID (Multiple Disks) SUPPORT
M: Neil Brown <neilb@suse.de>
L: linux-raid@vger.kernel.org
@@ -8539,37 +8627,12 @@ L: devel@driverdev.osuosl.org
S: Supported
F: drivers/staging/
-STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
-M: Henk de Groot <pe1dnn@amsat.org>
-S: Odd Fixes
-F: drivers/staging/wlags49_h2/
-F: drivers/staging/wlags49_h25/
-
-STAGING - ASUS OLED
-M: Jakub Schmidtke <sjakub@gmail.com>
-S: Odd Fixes
-F: drivers/staging/asus_oled/
-
STAGING - COMEDI
M: Ian Abbott <abbotti@mev.co.uk>
M: H Hartley Sweeten <hsweeten@visionengravers.com>
S: Odd Fixes
F: drivers/staging/comedi/
-STAGING - CRYSTAL HD VIDEO DECODER
-M: Naren Sankar <nsankar@broadcom.com>
-M: Jarod Wilson <jarod@wilsonet.com>
-M: Scott Davilla <davilla@4pi.com>
-M: Manu Abraham <abraham.manu@gmail.com>
-S: Odd Fixes
-F: drivers/staging/crystalhd/
-
-STAGING - ECHO CANCELLER
-M: Steve Underwood <steveu@coppice.org>
-M: David Rowe <david@rowetel.com>
-S: Odd Fixes
-F: drivers/staging/echo/
-
STAGING - ET131X NETWORK DRIVER
M: Mark Einon <mark.einon@gmail.com>
S: Odd Fixes
@@ -8580,16 +8643,6 @@ M: Marek Belisko <marek.belisko@gmail.com>
S: Odd Fixes
F: drivers/staging/ft1000/
-STAGING - FRONTIER TRANZPORT AND ALPHATRACK
-M: David Täht <d@teklibre.com>
-S: Odd Fixes
-F: drivers/staging/frontier/
-
-STAGING - GO7007 MPEG CODEC
-M: Hans Verkuil <hans.verkuil@cisco.com>
-S: Maintained
-F: drivers/staging/media/go7007/
-
STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
@@ -8641,52 +8694,27 @@ L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/staging/rtl8723au/
-STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
-M: Teddy Wang <teddy.wang@siliconmotion.com.cn>
-S: Odd Fixes
-F: drivers/staging/sm7xxfb/
-
STAGING - SLICOSS
M: Lior Dotan <liodot@gmail.com>
M: Christopher Harrer <charrer@alacritech.com>
S: Odd Fixes
F: drivers/staging/slicoss/
-STAGING - SOFTLOGIC 6x10 MPEG CODEC
-M: Ismael Luceno <ismael.luceno@corp.bluecherry.net>
-S: Supported
-F: drivers/staging/media/solo6x10/
-
STAGING - SPEAKUP CONSOLE SPEECH DRIVER
M: William Hubbs <w.d.hubbs@gmail.com>
M: Chris Brannon <chris@the-brannons.com>
M: Kirk Reiser <kirk@reisers.ca>
M: Samuel Thibault <samuel.thibault@ens-lyon.org>
-L: speakup@braille.uwo.ca
+L: speakup@linux-speakup.org
W: http://www.linux-speakup.org/
S: Odd Fixes
F: drivers/staging/speakup/
-STAGING - TI DSP BRIDGE DRIVERS
-M: Omar Ramirez Luna <omar.ramirez@copitl.com>
-S: Odd Fixes
-F: drivers/staging/tidspbridge/
-
-STAGING - USB ENE SM/MS CARD READER DRIVER
-M: Al Cho <acho@novell.com>
-S: Odd Fixes
-F: drivers/staging/keucr/
-
STAGING - VIA VT665X DRIVERS
M: Forest Bond <forest@alittletooquiet.net>
S: Odd Fixes
F: drivers/staging/vt665?/
-STAGING - WINBOND IS89C35 WLAN USB DRIVER
-M: Pavel Machek <pavel@ucw.cz>
-S: Odd Fixes
-F: drivers/staging/winbond/
-
STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER
M: Arnaud Patard <arnaud.patard@rtp-net.org>
S: Odd Fixes
@@ -9044,6 +9072,13 @@ L: linux-pm@vger.kernel.org
S: Supported
F: drivers/thermal/ti-soc-thermal/
+TI CLOCK DRIVER
+M: Tero Kristo <t-kristo@ti.com>
+L: linux-omap@vger.kernel.org
+S: Maintained
+F: drivers/clk/ti/
+F: include/linux/clk/ti.h
+
TI FLASH MEDIA INTERFACE DRIVER
M: Alex Dubov <oakad@yahoo.com>
S: Maintained
@@ -9531,15 +9566,6 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/usb/smsc95xx.*
-USB SN9C1xx DRIVER
-M: Luca Risolia <luca.risolia@studio.unibo.it>
-L: linux-usb@vger.kernel.org
-L: linux-media@vger.kernel.org
-T: git git://linuxtv.org/media_tree.git
-W: http://www.linux-projects.org
-S: Maintained
-F: drivers/staging/media/sn9c102/
-
USB SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
@@ -9587,8 +9613,8 @@ USB WEBCAM GADGET
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-usb@vger.kernel.org
S: Maintained
-F: drivers/usb/gadget/*uvc*.c
-F: drivers/usb/gadget/webcam.c
+F: drivers/usb/gadget/function/*uvc*.c
+F: drivers/usb/gadget/legacy/webcam.c
USB WIRELESS RNDIS DRIVER (rndis_wlan)
M: Jussi Kivilinna <jussi.kivilinna@iki.fi>
@@ -9653,7 +9679,7 @@ L: linux-fbdev@vger.kernel.org
W: http://dev.gentoo.org/~spock/projects/uvesafb/
S: Maintained
F: Documentation/fb/uvesafb.txt
-F: drivers/video/uvesafb.*
+F: drivers/video/fbdev/uvesafb.*
VFAT/FAT/MSDOS FILESYSTEM
M: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
@@ -9726,7 +9752,7 @@ S: Maintained
F: include/linux/via-core.h
F: include/linux/via-gpio.h
F: include/linux/via_i2c.h
-F: drivers/video/via/
+F: drivers/video/fbdev/via/
VIA VELOCITY NETWORK DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
@@ -9859,6 +9885,13 @@ M: Pierre Ossman <pierre@ossman.eu>
S: Maintained
F: drivers/mmc/host/wbsd.*
+WACOM PROTOCOL 4 SERIAL TABLETS
+M: Julian Squires <julian@cipht.net>
+M: Hans de Goede <hdegoede@redhat.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: drivers/input/tablet/wacom_serial4.c
+
WATCHDOG DEVICE DRIVERS
M: Wim Van Sebroeck <wim@iguana.be>
L: linux-watchdog@vger.kernel.org
@@ -10046,6 +10079,13 @@ S: Supported
F: arch/x86/pci/*xen*
F: drivers/pci/*xen*
+XEN BLOCK SUBSYSTEM
+M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
+S: Supported
+F: drivers/block/xen-blkback/*
+F: drivers/block/xen*
+
XEN SWIOTLB SUBSYSTEM
M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
diff --git a/Makefile b/Makefile
index d0901b46b4bf..6aace6750567 100644
--- a/Makefile
+++ b/Makefile
@@ -372,6 +372,7 @@ GENKSYMS = scripts/genksyms/genksyms
INSTALLKERNEL := installkernel
DEPMOD = /sbin/depmod
PERL = perl
+PYTHON = python
CHECK = sparse
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
@@ -422,7 +423,7 @@ KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(S
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP
-export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
+export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
@@ -621,6 +622,9 @@ else
KBUILD_CFLAGS += -O2
endif
+# Tell gcc to never replace conditional load with a non-conditional one
+KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
+
ifdef CONFIG_READABLE_ASM
# Disable optimizations that make assembler listings hard to read.
# reorder blocks reorders the control in the function
@@ -636,6 +640,22 @@ KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
endif
# Handle stack protector mode.
+#
+# Since kbuild can potentially perform two passes (first with the old
+# .config values and then with updated .config values), we cannot error out
+# if a desired compiler option is unsupported. If we were to error, kbuild
+# could never get to the second pass and actually notice that we changed
+# the option to something that was supported.
+#
+# Additionally, we don't want to fallback and/or silently change which compiler
+# flags will be used, since that leads to producing kernels with different
+# security feature characteristics depending on the compiler used. ("But I
+# selected CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
+#
+# The middle ground is to warn here so that the failed option is obvious, but
+# to let the build fail with bad compiler flags so that we can't produce a
+# kernel when there is a CONFIG and compiler mismatch.
+#
ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
stackp-flag := -fstack-protector
ifeq ($(call cc-option, $(stackp-flag)),)
@@ -668,6 +688,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare)
# source of a reference will be _MergedGlobals and not on of the whitelisted names.
# See modpost pattern 2
KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,)
+KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
else
# This warning generated too much noise in a regular build.
@@ -691,9 +712,16 @@ endif
KBUILD_CFLAGS += $(call cc-option, -fno-var-tracking-assignments)
ifdef CONFIG_DEBUG_INFO
+ifdef CONFIG_DEBUG_INFO_SPLIT
+KBUILD_CFLAGS += $(call cc-option, -gsplit-dwarf, -g)
+else
KBUILD_CFLAGS += -g
+endif
KBUILD_AFLAGS += -Wa,-gdwarf-2
endif
+ifdef CONFIG_DEBUG_INFO_DWARF4
+KBUILD_CFLAGS += $(call cc-option, -gdwarf-4,)
+endif
ifdef CONFIG_DEBUG_INFO_REDUCED
KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) \
@@ -1036,6 +1064,13 @@ headers_check: headers_install
$(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
# ---------------------------------------------------------------------------
+# Kernel selftest
+
+PHONY += kselftest
+kselftest:
+ $(Q)$(MAKE) -C tools/testing/selftests run_tests
+
+# ---------------------------------------------------------------------------
# Modules
ifdef CONFIG_MODULES
@@ -1222,9 +1257,9 @@ help:
@echo ' tags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ' gtags - Generate GNU GLOBAL index'
- @echo ' kernelrelease - Output the release version string'
- @echo ' kernelversion - Output the version stored in Makefile'
- @echo ' image_name - Output the image name'
+ @echo ' kernelrelease - Output the release version string (use with make -s)'
+ @echo ' kernelversion - Output the version stored in Makefile (use with make -s)'
+ @echo ' image_name - Output the image name (use with make -s)'
@echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
echo ' (default: $(INSTALL_HDR_PATH))'; \
echo ''
@@ -1238,6 +1273,11 @@ help:
@echo ' headerdep - Detect inclusion cycles in headers'
@$(MAKE) -f $(srctree)/scripts/Makefile.help checker-help
@echo ''
+ @echo 'Kernel selftest'
+ @echo ' kselftest - Build and run kernel selftest (run as root)'
+ @echo ' Build, install, and boot kernel before'
+ @echo ' running kselftest on it'
+ @echo ''
@echo 'Kernel packaging:'
@$(MAKE) $(build)=$(package-dir) help
@echo ''
@@ -1379,6 +1419,7 @@ clean: $(clean-dirs)
@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \
+ -o -name '*.dwo' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-o -name '*.symtypes' -o -name 'modules.order' \
-o -name modules.builtin -o -name '.tmp_*.o.*' \
diff --git a/arch/Kconfig b/arch/Kconfig
index 97ff872c7acc..0eae9df35b88 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -321,6 +321,7 @@ config HAVE_ARCH_SECCOMP_FILTER
- secure_computing is called from a ptrace_event()-safe context
- secure_computing return value is checked and a return value of -1
results in the system call being skipped immediately.
+ - seccomp syscall wired up
config SECCOMP_FILTER
def_bool y
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 96e54bed5088..e858aa0ad8af 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += exec.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h
index 6cb7fe85c4b5..b4cf03690394 100644
--- a/arch/alpha/include/asm/processor.h
+++ b/arch/alpha/include/asm/processor.h
@@ -57,6 +57,7 @@ unsigned long get_wchan(struct task_struct *p);
((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#define ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCHW
diff --git a/arch/alpha/include/asm/scatterlist.h b/arch/alpha/include/asm/scatterlist.h
deleted file mode 100644
index 017d7471c3c4..000000000000
--- a/arch/alpha/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ALPHA_SCATTERLIST_H
-#define _ALPHA_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_ALPHA_SCATTERLIST_H) */
diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
index 5bb2fdaca02f..6b57475967a6 100644
--- a/arch/arc/boot/dts/angel4.dts
+++ b/arch/arc/boot/dts/angel4.dts
@@ -17,7 +17,7 @@
interrupt-parent = <&intc>;
chosen {
- bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
+ bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
};
aliases {
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 355cb470c2a4..372466b371bf 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -296,7 +296,7 @@ struct cpuinfo_arc_mmu {
};
struct cpuinfo_arc_cache {
- unsigned int sz, line_len, assoc, ver;
+ unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
};
struct cpuinfo_arc_ccm {
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index fb4efb648971..f38652fb2ed7 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,9 +16,13 @@
#define TIMER0_IRQ 3
#define TIMER1_IRQ 4
+#include <linux/interrupt.h>
#include <asm-generic/irq.h>
extern void arc_init_IRQ(void);
void arc_local_timer_setup(void);
+void arc_request_percpu_irq(int irq, int cpu,
+ irqreturn_t (*isr)(int irq, void *dev),
+ const char *irq_nm, void *percpu_dev);
#endif
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index cb7efc29f16f..587df8236e8b 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -131,24 +131,6 @@ static inline int arch_irqs_disabled(void)
return arch_irqs_disabled_flags(arch_local_save_flags());
}
-static inline void arch_mask_irq(unsigned int irq)
-{
- unsigned int ienb;
-
- ienb = read_aux_reg(AUX_IENABLE);
- ienb &= ~(1 << irq);
- write_aux_reg(AUX_IENABLE, ienb);
-}
-
-static inline void arch_unmask_irq(unsigned int irq)
-{
- unsigned int ienb;
-
- ienb = read_aux_reg(AUX_IENABLE);
- ienb |= (1 << irq);
- write_aux_reg(AUX_IENABLE, ienb);
-}
-
#else
#ifdef CONFIG_TRACE_IRQFLAGS
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index d99f9b37cd15..82588f3ba77f 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -62,6 +62,8 @@ unsigned long thread_saved_pc(struct task_struct *t);
#define cpu_relax() do { } while (0)
#endif
+#define cpu_relax_lowlatency() cpu_relax()
+
#define copy_segments(tsk, mm) do { } while (0)
#define release_segments(mm) do { } while (0)
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 7d653c0d0773..620ec2fe32a9 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -19,21 +19,16 @@
/*
* Early Hardware specific Interrupt setup
+ * -Platform independent, needed for each CPU (not foldable into init_IRQ)
* -Called very early (start_kernel -> setup_arch -> setup_processor)
- * -Platform Independent (must for any ARC700)
- * -Needed for each CPU (hence not foldable into init_IRQ)
*
* what it does ?
- * -Disable all IRQs (on CPU side)
* -Optionally, setup the High priority Interrupts as Level 2 IRQs
*/
void arc_init_IRQ(void)
{
int level_mask = 0;
- /* Disable all IRQs: enable them as devices request */
- write_aux_reg(AUX_IENABLE, 0);
-
/* setup any high priority Interrupts (Level2 in ARCompact jargon) */
level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
@@ -60,20 +55,28 @@ void arc_init_IRQ(void)
* below, per IRQ.
*/
-static void arc_mask_irq(struct irq_data *data)
+static void arc_irq_mask(struct irq_data *data)
{
- arch_mask_irq(data->irq);
+ unsigned int ienb;
+
+ ienb = read_aux_reg(AUX_IENABLE);
+ ienb &= ~(1 << data->irq);
+ write_aux_reg(AUX_IENABLE, ienb);
}
-static void arc_unmask_irq(struct irq_data *data)
+static void arc_irq_unmask(struct irq_data *data)
{
- arch_unmask_irq(data->irq);
+ unsigned int ienb;
+
+ ienb = read_aux_reg(AUX_IENABLE);
+ ienb |= (1 << data->irq);
+ write_aux_reg(AUX_IENABLE, ienb);
}
static struct irq_chip onchip_intc = {
.name = "ARC In-core Intc",
- .irq_mask = arc_mask_irq,
- .irq_unmask = arc_unmask_irq,
+ .irq_mask = arc_irq_mask,
+ .irq_unmask = arc_irq_unmask,
};
static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
@@ -150,6 +153,32 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
set_irq_regs(old_regs);
}
+void arc_request_percpu_irq(int irq, int cpu,
+ irqreturn_t (*isr)(int irq, void *dev),
+ const char *irq_nm,
+ void *percpu_dev)
+{
+ /* Boot cpu calls request, all call enable */
+ if (!cpu) {
+ int rc;
+
+ /*
+ * These 2 calls are essential to making percpu IRQ APIs work
+ * Ideally these details could be hidden in irq chip map function
+ * but the issue is IPIs IRQs being static (non-DT) and platform
+ * specific, so we can't identify them there.
+ */
+ irq_set_percpu_devid(irq);
+ irq_modify_status(irq, IRQ_NOAUTOEN, 0); /* @irq, @clr, @set */
+
+ rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev);
+ if (rc)
+ panic("Percpu IRQ request failed for %d\n", irq);
+ }
+
+ enable_percpu_irq(irq, 0);
+}
+
/*
* arch_local_irq_enable - Enable interrupts.
*
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 63177e4cb66d..b9a5685a990e 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -99,10 +99,6 @@ static int arc_pmu_event_init(struct perf_event *event)
struct hw_perf_event *hwc = &event->hw;
int ret;
- /* ARC 700 PMU does not support sampling events */
- if (is_sampling_event(event))
- return -ENOENT;
-
switch (event->attr.type) {
case PERF_TYPE_HARDWARE:
if (event->attr.config >= PERF_COUNT_HW_MAX)
@@ -298,6 +294,9 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
.read = arc_pmu_read,
};
+ /* ARC 700 PMU does not support sampling events */
+ arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
return ret;
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
index 7e95e1a86510..cb3142a2d40b 100644
--- a/arch/arc/kernel/signal.c
+++ b/arch/arc/kernel/signal.c
@@ -141,17 +141,13 @@ badframe:
/*
* Determine which stack to use..
*/
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
unsigned long framesize)
{
- unsigned long sp = regs->sp;
+ unsigned long sp = sigsp(regs->sp, ksig);
void __user *frame;
- /* This is the X/Open sanctioned signal stack switching */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
/* No matter what happens, 'sp' must be word
* aligned otherwise nasty things could happen
*/
@@ -179,14 +175,13 @@ static inline int map_sig(int sig)
}
static int
-setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *sf;
unsigned int magic = 0;
int err = 0;
- sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+ sf = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
if (!sf)
return 1;
@@ -205,8 +200,8 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
* #2: struct siginfo
* #3: struct ucontext (completely populated)
*/
- if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) {
- err |= copy_siginfo_to_user(&sf->info, info);
+ if (unlikely(ksig->ka.sa.sa_flags & SA_SIGINFO)) {
+ err |= copy_siginfo_to_user(&sf->info, &ksig->info);
err |= __put_user(0, &sf->uc.uc_flags);
err |= __put_user(NULL, &sf->uc.uc_link);
err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
@@ -227,16 +222,16 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
return err;
/* #1 arg to the user Signal handler */
- regs->r0 = map_sig(signo);
+ regs->r0 = map_sig(ksig->sig);
/* setup PC of user space signal handler */
- regs->ret = (unsigned long)ka->sa.sa_handler;
+ regs->ret = (unsigned long)ksig->ka.sa.sa_handler;
/*
* handler returns using sigreturn stub provided already by userpsace
*/
- BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
- regs->blink = (unsigned long)ka->sa.sa_restorer;
+ BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER));
+ regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
/* User Stack for signal handler will be above the frame just carved */
regs->sp = (unsigned long)sf;
@@ -298,38 +293,30 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
* OK, we're invoking a handler
*/
static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
/* Set up the stack frame */
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(ksig, oldset, regs);
- if (ret)
- force_sigsegv(sig, current);
- else
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
void do_signal(struct pt_regs *regs)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
int restart_scall;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
restart_scall = in_syscall(regs) && syscall_restartable(regs);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
if (restart_scall) {
- arc_restart_syscall(&ka, regs);
+ arc_restart_syscall(&ksig.ka, regs);
syscall_wont_restart(regs); /* No more restarts */
}
- handle_signal(signr, &ka, &info, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index c802bb500602..dcd317c47d09 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -12,23 +12,15 @@
* -- Initial Write (Borrowed heavily from ARM)
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/profile.h>
-#include <linux/errno.h>
-#include <linux/err.h>
#include <linux/mm.h>
#include <linux/cpu.h>
-#include <linux/smp.h>
#include <linux/irq.h>
-#include <linux/delay.h>
#include <linux/atomic.h>
-#include <linux/percpu.h>
#include <linux/cpumask.h>
-#include <linux/spinlock_types.h>
#include <linux/reboot.h>
#include <asm/processor.h>
#include <asm/setup.h>
@@ -136,7 +128,7 @@ void start_kernel_secondary(void)
pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
if (machine_desc->init_smp)
- machine_desc->init_smp(smp_processor_id());
+ machine_desc->init_smp(cpu);
arc_local_timer_setup();
@@ -338,18 +330,11 @@ irqreturn_t do_IPI(int irq, void *dev_id)
*/
static DEFINE_PER_CPU(int, ipi_dev);
-static struct irqaction arc_ipi_irq = {
- .name = "IPI Interrupt",
- .flags = IRQF_PERCPU,
- .handler = do_IPI,
-};
-
int smp_ipi_irq_setup(int cpu, int irq)
{
- if (!cpu)
- return setup_irq(irq, &arc_ipi_irq);
- else
- arch_unmask_irq(irq);
+ int *dev = per_cpu_ptr(&ipi_dev, cpu);
+
+ arc_request_percpu_irq(irq, cpu, do_IPI, "IPI Interrupt", dev);
return 0;
}
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 36c2aa99436f..dbe74f418019 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -144,12 +144,12 @@ static struct clocksource arc_counter = {
/********** Clock Event Device *********/
/*
- * Arm the timer to interrupt after @limit cycles
+ * Arm the timer to interrupt after @cycles
* The distinction for oneshot/periodic is done in arc_event_timer_ack() below
*/
-static void arc_timer_event_setup(unsigned int limit)
+static void arc_timer_event_setup(unsigned int cycles)
{
- write_aux_reg(ARC_REG_TIMER0_LIMIT, limit);
+ write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
write_aux_reg(ARC_REG_TIMER0_CNT, 0); /* start from 0 */
write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
@@ -168,6 +168,10 @@ static void arc_clkevent_set_mode(enum clock_event_mode mode,
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
+ /*
+ * At X Hz, 1 sec = 1000ms -> X cycles;
+ * 10ms -> X / 100 cycles
+ */
arc_timer_event_setup(arc_get_core_freq() / HZ);
break;
case CLOCK_EVT_MODE_ONESHOT:
@@ -210,12 +214,6 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static struct irqaction arc_timer_irq = {
- .name = "Timer0 (clock-evt-dev)",
- .flags = IRQF_TIMER | IRQF_PERCPU,
- .handler = timer_irq_handler,
-};
-
/*
* Setup the local event timer for @cpu
*/
@@ -228,15 +226,9 @@ void arc_local_timer_setup()
clockevents_config_and_register(evt, arc_get_core_freq(),
0, ARC_TIMER_MAX);
- /*
- * setup the per-cpu timer IRQ handler - for all cpus
- * For non boot CPU explicitly unmask at intc
- * setup_irq() -> .. -> irq_startup() already does this on boot-cpu
- */
- if (!cpu)
- setup_irq(TIMER0_IRQ, &arc_timer_irq);
- else
- arch_unmask_irq(TIMER0_IRQ);
+ /* setup the per-cpu timer IRQ handler - for all cpus */
+ arc_request_percpu_irq(TIMER0_IRQ, cpu, timer_irq_handler,
+ "Timer0 (per-cpu-tick)", evt);
}
/*
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 353b202c37c9..4670afc3b971 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -77,21 +77,19 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
{
int n = 0;
-#define PR_CACHE(p, enb, str) \
-{ \
+#define PR_CACHE(p, cfg, str) \
if (!(p)->ver) \
n += scnprintf(buf + n, len - n, str"\t\t: N/A\n"); \
else \
n += scnprintf(buf + n, len - n, \
- str"\t\t: (%uK) VIPT, %dway set-asc, %ub Line %s\n", \
- TO_KB((p)->sz), (p)->assoc, (p)->line_len, \
- enb ? "" : "DISABLED (kernel-build)"); \
-}
+ str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n", \
+ (p)->sz_k, (p)->assoc, (p)->line_len, \
+ (p)->vipt ? "VIPT" : "PIPT", \
+ (p)->alias ? " aliasing" : "", \
+ IS_ENABLED(cfg) ? "" : " (not used)");
- PR_CACHE(&cpuinfo_arc700[c].icache, IS_ENABLED(CONFIG_ARC_HAS_ICACHE),
- "I-Cache");
- PR_CACHE(&cpuinfo_arc700[c].dcache, IS_ENABLED(CONFIG_ARC_HAS_DCACHE),
- "D-Cache");
+ PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
+ PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
return buf;
}
@@ -116,20 +114,31 @@ void read_decode_cache_bcr(void)
p_ic = &cpuinfo_arc700[cpu].icache;
READ_BCR(ARC_REG_IC_BCR, ibcr);
+ if (!ibcr.ver)
+ goto dc_chk;
+
BUG_ON(ibcr.config != 3);
p_ic->assoc = 2; /* Fixed to 2w set assoc */
p_ic->line_len = 8 << ibcr.line_len;
- p_ic->sz = 0x200 << ibcr.sz;
+ p_ic->sz_k = 1 << (ibcr.sz - 1);
p_ic->ver = ibcr.ver;
+ p_ic->vipt = 1;
+ p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1;
+dc_chk:
p_dc = &cpuinfo_arc700[cpu].dcache;
READ_BCR(ARC_REG_DC_BCR, dbcr);
+ if (!dbcr.ver)
+ return;
+
BUG_ON(dbcr.config != 2);
p_dc->assoc = 4; /* Fixed to 4w set assoc */
p_dc->line_len = 16 << dbcr.line_len;
- p_dc->sz = 0x200 << dbcr.sz;
+ p_dc->sz_k = 1 << (dbcr.sz - 1);
p_dc->ver = dbcr.ver;
+ p_dc->vipt = 1;
+ p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1;
}
/*
@@ -142,14 +151,16 @@ void read_decode_cache_bcr(void)
void arc_cache_init(void)
{
unsigned int __maybe_unused cpu = smp_processor_id();
- struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc;
char str[256];
printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
-#ifdef CONFIG_ARC_HAS_ICACHE
- ic = &cpuinfo_arc700[cpu].icache;
- if (ic->ver) {
+ if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
+ struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
+
+ if (!ic->ver)
+ panic("cache support enabled but non-existent cache\n");
+
if (ic->line_len != L1_CACHE_BYTES)
panic("ICache line [%d] != kernel Config [%d]",
ic->line_len, L1_CACHE_BYTES);
@@ -158,26 +169,26 @@ void arc_cache_init(void)
panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
ic->ver, CONFIG_ARC_MMU_VER);
}
-#endif
-#ifdef CONFIG_ARC_HAS_DCACHE
- dc = &cpuinfo_arc700[cpu].dcache;
- if (dc->ver) {
- unsigned int dcache_does_alias;
+ if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
+ struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
+ int handled;
+
+ if (!dc->ver)
+ panic("cache support enabled but non-existent cache\n");
if (dc->line_len != L1_CACHE_BYTES)
panic("DCache line [%d] != kernel Config [%d]",
dc->line_len, L1_CACHE_BYTES);
/* check for D-Cache aliasing */
- dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE;
+ handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
- if (dcache_does_alias && !cache_is_vipt_aliasing())
+ if (dc->alias && !handled)
panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
- else if (!dcache_does_alias && cache_is_vipt_aliasing())
+ else if (!dc->alias && handled)
panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n");
}
-#endif
}
#define OP_INV 0x1
@@ -255,10 +266,32 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
* Machine specific helpers for Entire D-Cache or Per Line ops
*/
-static inline void wait_for_flush(void)
+static unsigned int __before_dc_op(const int op)
+{
+ unsigned int reg = reg;
+
+ if (op == OP_FLUSH_N_INV) {
+ /* Dcache provides 2 cmd: FLUSH or INV
+ * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
+ * flush-n-inv is achieved by INV cmd but with IM=1
+ * So toggle INV sub-mode depending on op request and default
+ */
+ reg = read_aux_reg(ARC_REG_DC_CTRL);
+ write_aux_reg(ARC_REG_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH)
+ ;
+ }
+
+ return reg;
+}
+
+static void __after_dc_op(const int op, unsigned int reg)
{
- while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
- ;
+ if (op & OP_FLUSH) /* flush / flush-n-inv both wait */
+ while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
+
+ /* Switch back to default Invalidate mode */
+ if (op == OP_FLUSH_N_INV)
+ write_aux_reg(ARC_REG_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH);
}
/*
@@ -269,18 +302,10 @@ static inline void wait_for_flush(void)
*/
static inline void __dc_entire_op(const int cacheop)
{
- unsigned int tmp = tmp;
+ unsigned int ctrl_reg;
int aux;
- if (cacheop == OP_FLUSH_N_INV) {
- /* Dcache provides 2 cmd: FLUSH or INV
- * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
- * flush-n-inv is achieved by INV cmd but with IM=1
- * Default INV sub-mode is DISCARD, which needs to be toggled
- */
- tmp = read_aux_reg(ARC_REG_DC_CTRL);
- write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
- }
+ ctrl_reg = __before_dc_op(cacheop);
if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */
aux = ARC_REG_DC_IVDC;
@@ -289,12 +314,7 @@ static inline void __dc_entire_op(const int cacheop)
write_aux_reg(aux, 0x1);
- if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */
- wait_for_flush();
-
- /* Switch back the DISCARD ONLY Invalidate mode */
- if (cacheop == OP_FLUSH_N_INV)
- write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+ __after_dc_op(cacheop, ctrl_reg);
}
/* For kernel mappings cache operation: index is same as paddr */
@@ -306,29 +326,16 @@ static inline void __dc_entire_op(const int cacheop)
static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
unsigned long sz, const int cacheop)
{
- unsigned long flags, tmp = tmp;
+ unsigned long flags;
+ unsigned int ctrl_reg;
local_irq_save(flags);
- if (cacheop == OP_FLUSH_N_INV) {
- /*
- * Dcache provides 2 cmd: FLUSH or INV
- * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
- * flush-n-inv is achieved by INV cmd but with IM=1
- * Default INV sub-mode is DISCARD, which needs to be toggled
- */
- tmp = read_aux_reg(ARC_REG_DC_CTRL);
- write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
- }
+ ctrl_reg = __before_dc_op(cacheop);
__cache_line_loop(paddr, vaddr, sz, cacheop);
- if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */
- wait_for_flush();
-
- /* Switch back the DISCARD ONLY Invalidate mode */
- if (cacheop == OP_FLUSH_N_INV)
- write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+ __after_dc_op(cacheop, ctrl_reg);
local_irq_restore(flags);
}
@@ -389,8 +396,16 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
/***********************************************************
* Machine specific helper for per line I-Cache invalidate.
*/
-static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
- unsigned long sz)
+
+static inline void __ic_entire_inv(void)
+{
+ write_aux_reg(ARC_REG_IC_IVIC, 1);
+ read_aux_reg(ARC_REG_IC_CTRL); /* blocks */
+}
+
+static inline void
+__ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
+ unsigned long sz)
{
unsigned long flags;
@@ -399,30 +414,39 @@ static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
local_irq_restore(flags);
}
-static inline void __ic_entire_inv(void)
-{
- write_aux_reg(ARC_REG_IC_IVIC, 1);
- read_aux_reg(ARC_REG_IC_CTRL); /* blocks */
-}
+#ifndef CONFIG_SMP
+
+#define __ic_line_inv_vaddr(p, v, s) __ic_line_inv_vaddr_local(p, v, s)
-struct ic_line_inv_vaddr_ipi {
+#else
+
+struct ic_inv_args {
unsigned long paddr, vaddr;
int sz;
};
static void __ic_line_inv_vaddr_helper(void *info)
{
- struct ic_line_inv_vaddr_ipi *ic_inv = (struct ic_line_inv_vaddr_ipi*) info;
+ struct ic_inv *ic_inv_args = (struct ic_inv_args *) info;
+
__ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
}
static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
unsigned long sz)
{
- struct ic_line_inv_vaddr_ipi ic_inv = { paddr, vaddr , sz};
+ struct ic_inv_args ic_inv = {
+ .paddr = paddr,
+ .vaddr = vaddr,
+ .sz = sz
+ };
+
on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1);
}
-#else
+
+#endif /* CONFIG_SMP */
+
+#else /* !CONFIG_ARC_HAS_ICACHE */
#define __ic_entire_inv()
#define __ic_line_inv_vaddr(pstart, vstart, sz)
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index 9c69552350c4..6f7e3a68803a 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -159,7 +159,6 @@ good_area:
return;
}
- /* TBD: switch to pagefault_out_of_memory() */
if (fault & VM_FAULT_OOM)
goto out_of_memory;
else if (fault & VM_FAULT_SIGBUS)
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index 79bfc81358c9..d572f1c2c724 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -220,9 +220,9 @@ ex_saved_reg1:
.macro CONV_PTE_TO_TLB
and r3, r0, PTE_BITS_RWX ; r w x
- lsl r2, r3, 3 ; r w x 0 0 0
+ lsl r2, r3, 3 ; r w x 0 0 0 (GLOBAL, kernel only)
and.f 0, r0, _PAGE_GLOBAL
- or.z r2, r2, r3 ; r w x r w x
+ or.z r2, r2, r3 ; r w x r w x (!GLOBAL, user page)
and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE
or r3, r3, r2
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index e27bb5cc3c1e..b9f34cf55acf 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -41,11 +41,4 @@ config ISS_SMP_EXTN
-XTL (To enable CPU start/stop/set-PC for another CPU)
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
-config ARC_SERIAL_BAUD
- int "UART Baud rate"
- default "115200"
- depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
- help
- Baud rate for the ARC UART
-
endif
diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
index 4d1bddc34b5b..66fd0ecd68b3 100644
--- a/arch/arc/plat-arcfpga/Makefile
+++ b/arch/arc/plat-arcfpga/Makefile
@@ -8,5 +8,5 @@
KBUILD_CFLAGS += -Iarch/arc/plat-arcfpga/include
-obj-y := platform.o irq.o
+obj-y := platform.o
obj-$(CONFIG_ISS_SMP_EXTN) += smp.o
diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h
index 6adbc53c3a5b..2c9dea690ac4 100644
--- a/arch/arc/plat-arcfpga/include/plat/irq.h
+++ b/arch/arc/plat-arcfpga/include/plat/irq.h
@@ -24,6 +24,4 @@
#define IDU_INTERRUPT_0 16
#endif
-extern void __init plat_fpga_init_IRQ(void);
-
#endif
diff --git a/arch/arc/plat-arcfpga/irq.c b/arch/arc/plat-arcfpga/irq.c
deleted file mode 100644
index d2215fd889c2..000000000000
--- a/arch/arc/plat-arcfpga/irq.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * ARC FPGA Platform IRQ hookups
- *
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.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/interrupt.h>
-#include <plat/irq.h>
-
-void __init plat_fpga_init_IRQ(void)
-{
- /*
- * SMP Hack because UART IRQ hardwired to cpu0 (boot-cpu) but if the
- * request_irq() comes from any other CPU, the low level IRQ unamsking
- * essential for getting Interrupts won't be enabled on cpu0, locking
- * up the UART state machine.
- */
-#ifdef CONFIG_SMP
- arch_unmask_irq(UART0_IRQ);
-#endif
-}
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index 61c7e5997387..1038949a99a1 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -22,115 +22,22 @@
#include <plat/smp.h>
#include <plat/irq.h>
-/*----------------------- Platform Devices -----------------------------*/
-
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
-static unsigned long arc_uart_info[] = {
- 0, /* uart->is_emulated (runtime @running_on_hw) */
- 0, /* uart->port.uartclk */
- 0, /* uart->baud */
- 0
-};
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
-/*
- * static platform data - but only for early serial
- * TBD: derive this from a special DT node
- */
-static struct resource arc_uart0_res[] = {
- {
- .start = UART0_BASE,
- .end = UART0_BASE + 0xFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = UART0_IRQ,
- .end = UART0_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device arc_uart0_dev = {
- .name = "arc-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(arc_uart0_res),
- .resource = arc_uart0_res,
- .dev = {
- .platform_data = &arc_uart_info,
- },
-};
-
-static struct platform_device *fpga_early_devs[] __initdata = {
- &arc_uart0_dev,
-};
-#endif /* CONFIG_SERIAL_ARC_CONSOLE */
-
-static void arc_fpga_serial_init(void)
-{
- /* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
- arc_uart_info[0] = !running_on_hw;
-
- arc_uart_info[1] = arc_get_core_freq();
-
- arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
-
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
- early_platform_add_devices(fpga_early_devs,
- ARRAY_SIZE(fpga_early_devs));
-
- /*
- * ARC console driver registers (build time) as an early platform driver
- * of class "earlyprintk". However it needs explicit cmdline toggle
- * "earlyprintk=ttyARC0" to be successfuly runtime registered.
- * Otherwise the early probe below fails to find the driver
- */
- early_platform_driver_probe("earlyprintk", 1, 0);
-
- /*
- * This is to make sure that arc uart would be preferred console
- * despite one/more of following:
- * -command line lacked "console=ttyARC0" or
- * -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
- * Note that this needs to be done after above early console is reg,
- * otherwise the early console never gets a chance to run.
- */
- add_preferred_console("ttyARC", 0, "115200");
-#endif /* CONFIG_SERIAL_ARC_CONSOLE */
-}
-#else /* !IS_ENABLED(CONFIG_SERIAL_ARC) */
-static void arc_fpga_serial_init(void)
-{
-}
-#endif
-
static void __init plat_fpga_early_init(void)
{
pr_info("[plat-arcfpga]: registering early dev resources\n");
- arc_fpga_serial_init();
-
#ifdef CONFIG_ISS_SMP_EXTN
iss_model_init_early_smp();
#endif
}
-static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
-#if IS_ENABLED(CONFIG_SERIAL_ARC)
- OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
-#endif
- {}
-};
-
static void __init plat_fpga_populate_dev(void)
{
- pr_info("[plat-arcfpga]: registering device resources\n");
-
/*
* Traverses flattened DeviceTree - registering platform devices
- * complete with their resources
+ * (if any) complete with their resources
*/
- of_platform_populate(NULL, of_default_bus_match_table,
- plat_auxdata_lookup, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
/*----------------------- Machine Descriptions ------------------------------
@@ -150,7 +57,6 @@ MACHINE_START(ANGEL4, "angel4")
.dt_compat = aa4_compat,
.init_early = plat_fpga_early_init,
.init_machine = plat_fpga_populate_dev,
- .init_irq = plat_fpga_init_IRQ,
#ifdef CONFIG_ISS_SMP_EXTN
.init_smp = iss_model_init_smp,
#endif
@@ -165,7 +71,6 @@ MACHINE_START(ML509, "ml509")
.dt_compat = ml509_compat,
.init_early = plat_fpga_early_init,
.init_machine = plat_fpga_populate_dev,
- .init_irq = plat_fpga_init_IRQ,
#ifdef CONFIG_SMP
.init_smp = iss_model_init_smp,
#endif
@@ -180,5 +85,4 @@ MACHINE_START(NSIMOSCI, "nsimosci")
.dt_compat = nsimosci_compat,
.init_early = NULL,
.init_machine = plat_fpga_populate_dev,
- .init_irq = NULL,
MACHINE_END
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 290f02ee0157..c49a775937db 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -65,7 +65,6 @@ config ARM
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select IRQ_FORCED_THREADING
- select KTIME_SCALAR
select MODULES_USE_ELF_REL
select NO_BOOTMEM
select OLD_SIGACTION
@@ -84,6 +83,7 @@ config ARM
<http://www.arm.linux.org.uk/>.
config ARM_HAS_SG_CHAIN
+ select ARCH_HAS_SG_CHAIN
bool
config NEED_SG_DMA_LENGTH
@@ -240,13 +240,6 @@ config ARM_PATCH_PHYS_VIRT
this feature (eg, building a kernel for a single machine) and
you need to shrink the kernel to the minimal size.
-config NEED_MACH_GPIO_H
- bool
- help
- Select this when mach/gpio.h is required to provide special
- definitions for this platform. The need for mach/gpio.h should
- be avoided when possible.
-
config NEED_MACH_IO_H
bool
help
@@ -263,8 +256,22 @@ config NEED_MACH_MEMORY_H
config PHYS_OFFSET
hex "Physical address of main memory" if MMU
- depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H
+ depends on !ARM_PATCH_PHYS_VIRT
default DRAM_BASE if !MMU
+ default 0x00000000 if ARCH_EBSA110 || \
+ EP93XX_SDCE3_SYNC_PHYS_OFFSET || \
+ ARCH_FOOTBRIDGE || \
+ ARCH_INTEGRATOR || \
+ ARCH_IOP13XX || \
+ ARCH_KS8695 || \
+ (ARCH_REALVIEW && !REALVIEW_HIGH_PHYS_OFFSET)
+ default 0x10000000 if ARCH_OMAP1 || ARCH_RPC
+ default 0x20000000 if ARCH_S5PV210
+ default 0x70000000 if REALVIEW_HIGH_PHYS_OFFSET
+ default 0xc0000000 if EP93XX_SDCE0_PHYS_OFFSET || ARCH_SA1100
+ default 0xd0000000 if EP93XX_SDCE1_PHYS_OFFSET
+ default 0xe0000000 if EP93XX_SDCE2_PHYS_OFFSET
+ default 0xf0000000 if EP93XX_SDCE3_ASYNC_PHYS_OFFSET
help
Please provide the physical address corresponding to the
location of main memory in your system.
@@ -321,7 +328,6 @@ config ARCH_INTEGRATOR
select HAVE_TCM
select ICST
select MULTI_IRQ_HANDLER
- select NEED_MACH_MEMORY_H
select PLAT_VERSATILE
select SPARSE_IRQ
select USE_OF
@@ -341,7 +347,6 @@ config ARCH_REALVIEW
select ICST
select NEED_MACH_MEMORY_H
select PLAT_VERSATILE
- select PLAT_VERSATILE_CLCD
help
This enables support for ARM Ltd RealView boards.
@@ -356,7 +361,6 @@ config ARCH_VERSATILE
select HAVE_MACH_CLKDEV
select ICST
select PLAT_VERSATILE
- select PLAT_VERSATILE_CLCD
select PLAT_VERSATILE_CLOCK
select VERSATILE_FPGA_IRQ
help
@@ -436,7 +440,6 @@ config ARCH_EP93XX
select ARM_VIC
select CLKDEV_LOOKUP
select CPU_ARM920T
- select NEED_MACH_MEMORY_H
help
This enables support for the Cirrus EP93xx series of CPUs.
@@ -529,21 +532,6 @@ config ARCH_DOVE
help
Support for the Marvell Dove SoC 88AP510
-config ARCH_KIRKWOOD
- bool "Marvell Kirkwood"
- select ARCH_REQUIRE_GPIOLIB
- select CPU_FEROCEON
- select GENERIC_CLOCKEVENTS
- select MVEBU_MBUS
- select PCI
- select PCI_QUIRKS
- select PINCTRL
- select PINCTRL_KIRKWOOD
- select PLAT_ORION_LEGACY
- help
- Support for the following Marvell Kirkwood series SoCs:
- 88F6180, 88F6192 and 88F6281.
-
config ARCH_MV78XX0
bool "Marvell MV78xx0"
select ARCH_REQUIRE_GPIOLIB
@@ -635,6 +623,7 @@ config ARCH_PXA
select AUTO_ZRELADDR
select CLKDEV_LOOKUP
select CLKSRC_MMIO
+ select CLKSRC_OF
select GENERIC_CLOCKEVENTS
select GPIO_PXA
select HAVE_IDE
@@ -759,61 +748,6 @@ config ARCH_S3C64XX
help
Samsung S3C64XX series based systems
-config ARCH_S5P64X0
- bool "Samsung S5P6440 S5P6450"
- select ATAGS
- select CLKDEV_LOOKUP
- select CLKSRC_SAMSUNG_PWM
- select CPU_V6
- select GENERIC_CLOCKEVENTS
- select GPIO_SAMSUNG
- select HAVE_S3C2410_I2C if I2C
- select HAVE_S3C2410_WATCHDOG if WATCHDOG
- select HAVE_S3C_RTC if RTC_CLASS
- select NEED_MACH_GPIO_H
- select SAMSUNG_ATAGS
- select SAMSUNG_WDT_RESET
- help
- Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
- SMDK6450.
-
-config ARCH_S5PC100
- bool "Samsung S5PC100"
- select ARCH_REQUIRE_GPIOLIB
- select ATAGS
- select CLKDEV_LOOKUP
- select CLKSRC_SAMSUNG_PWM
- select CPU_V7
- select GENERIC_CLOCKEVENTS
- select GPIO_SAMSUNG
- select HAVE_S3C2410_I2C if I2C
- select HAVE_S3C2410_WATCHDOG if WATCHDOG
- select HAVE_S3C_RTC if RTC_CLASS
- select NEED_MACH_GPIO_H
- select SAMSUNG_ATAGS
- select SAMSUNG_WDT_RESET
- help
- Samsung S5PC100 series based systems
-
-config ARCH_S5PV210
- bool "Samsung S5PV210/S5PC110"
- select ARCH_HAS_HOLES_MEMORYMODEL
- select ARCH_SPARSEMEM_ENABLE
- select ATAGS
- select CLKDEV_LOOKUP
- select CLKSRC_SAMSUNG_PWM
- select CPU_V7
- select GENERIC_CLOCKEVENTS
- select GPIO_SAMSUNG
- select HAVE_S3C2410_I2C if I2C
- select HAVE_S3C2410_WATCHDOG if WATCHDOG
- select HAVE_S3C_RTC if RTC_CLASS
- select NEED_MACH_GPIO_H
- select NEED_MACH_MEMORY_H
- select SAMSUNG_ATAGS
- help
- Samsung S5PV210/S5PC110 series based systems
-
config ARCH_DAVINCI
bool "TI DaVinci"
select ARCH_HAS_HOLES_MEMORYMODEL
@@ -952,8 +886,6 @@ source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-keystone/Kconfig"
-source "arch/arm/mach-kirkwood/Kconfig"
-
source "arch/arm/mach-ks8695/Kconfig"
source "arch/arm/mach-msm/Kconfig"
@@ -964,6 +896,8 @@ source "arch/arm/mach-mv78xx0/Kconfig"
source "arch/arm/mach-imx/Kconfig"
+source "arch/arm/mach-mediatek/Kconfig"
+
source "arch/arm/mach-mxs/Kconfig"
source "arch/arm/mach-netx/Kconfig"
@@ -1005,10 +939,6 @@ source "arch/arm/mach-s3c24xx/Kconfig"
source "arch/arm/mach-s3c64xx/Kconfig"
-source "arch/arm/mach-s5p64x0/Kconfig"
-
-source "arch/arm/mach-s5pc100/Kconfig"
-
source "arch/arm/mach-s5pv210/Kconfig"
source "arch/arm/mach-exynos/Kconfig"
@@ -1555,10 +1485,12 @@ config ARM_PSCI
config ARCH_NR_GPIO
int
default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
- default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX
+ default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
+ SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
default 416 if ARCH_SUNXI
default 392 if ARCH_U8500
default 352 if ARCH_VT8500
+ default 288 if ARCH_ROCKCHIP
default 264 if MACH_H4700
default 0
help
@@ -1570,7 +1502,7 @@ source kernel/Kconfig.preempt
config HZ_FIXED
int
- default 200 if ARCH_EBSA110 || ARCH_S3C24XX || ARCH_S5P64X0 || \
+ default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
ARCH_S5PV210 || ARCH_EXYNOS4
default AT91_TIMER_HZ if ARCH_AT91
default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY
@@ -2051,6 +1983,8 @@ config XIP_PHYS_ADDR
config KEXEC
bool "Kexec system call (EXPERIMENTAL)"
depends on (!SMP || PM_SLEEP_SMP)
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -2195,7 +2129,6 @@ menu "Power management options"
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
- depends on !ARCH_S5PC100
depends on CPU_ARM920T || CPU_ARM926T || CPU_FEROCEON || CPU_SA1100 || \
CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
def_bool y
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 8f90595069a1..b11ad54f8d17 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -223,6 +223,14 @@ choice
Say Y here if you want kernel low-level debugging support
on HI3716 UART.
+ config DEBUG_HIX5HD2_UART
+ bool "Hisilicon Hix5hd2 Debug UART"
+ depends on ARCH_HIX5HD2
+ select DEBUG_UART_PL01X
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Hix5hd2 UART.
+
config DEBUG_HIGHBANK_UART
bool "Kernel low-level debugging messages via Highbank UART"
depends on ARCH_HIGHBANK
@@ -582,7 +590,7 @@ choice
on Rockchip based platforms.
config DEBUG_RK3X_UART0
- bool "Kernel low-level debugging messages via Rockchip RK3X UART0"
+ bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART0"
depends on ARCH_ROCKCHIP
select DEBUG_UART_8250
help
@@ -590,7 +598,7 @@ choice
on Rockchip based platforms.
config DEBUG_RK3X_UART1
- bool "Kernel low-level debugging messages via Rockchip RK3X UART1"
+ bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART1"
depends on ARCH_ROCKCHIP
select DEBUG_UART_8250
help
@@ -598,7 +606,7 @@ choice
on Rockchip based platforms.
config DEBUG_RK3X_UART2
- bool "Kernel low-level debugging messages via Rockchip RK3X UART2"
+ bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART2"
depends on ARCH_ROCKCHIP
select DEBUG_UART_8250
help
@@ -606,64 +614,64 @@ choice
on Rockchip based platforms.
config DEBUG_RK3X_UART3
- bool "Kernel low-level debugging messages via Rockchip RK3X UART3"
+ bool "Kernel low-level debugging messages via Rockchip RK30/RK31 UART3"
depends on ARCH_ROCKCHIP
select DEBUG_UART_8250
help
Say Y here if you want kernel low-level debugging support
on Rockchip based platforms.
+ config DEBUG_RK32_UART2
+ bool "Kernel low-level debugging messages via Rockchip RK32 UART2"
+ depends on ARCH_ROCKCHIP
+ select DEBUG_UART_8250
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Rockchip RK32xx based platforms.
+
config DEBUG_S3C_UART0
depends on PLAT_SAMSUNG
select DEBUG_EXYNOS_UART if ARCH_EXYNOS
select DEBUG_S3C24XX_UART if ARCH_S3C24XX
- bool "Use S3C UART 0 for low-level debug"
+ select DEBUG_S5PV210_UART if ARCH_S5PV210
+ bool "Use Samsung S3C UART 0 for low-level debug"
help
Say Y here if you want the debug print routines to direct
their output to UART 0. The port must have been initialised
by the boot-loader before use.
- The uncompressor code port configuration is now handled
- by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
config DEBUG_S3C_UART1
depends on PLAT_SAMSUNG
select DEBUG_EXYNOS_UART if ARCH_EXYNOS
select DEBUG_S3C24XX_UART if ARCH_S3C24XX
- bool "Use S3C UART 1 for low-level debug"
+ select DEBUG_S5PV210_UART if ARCH_S5PV210
+ bool "Use Samsung S3C UART 1 for low-level debug"
help
Say Y here if you want the debug print routines to direct
their output to UART 1. The port must have been initialised
by the boot-loader before use.
- The uncompressor code port configuration is now handled
- by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
config DEBUG_S3C_UART2
depends on PLAT_SAMSUNG
select DEBUG_EXYNOS_UART if ARCH_EXYNOS
select DEBUG_S3C24XX_UART if ARCH_S3C24XX
- bool "Use S3C UART 2 for low-level debug"
+ select DEBUG_S5PV210_UART if ARCH_S5PV210
+ bool "Use Samsung S3C UART 2 for low-level debug"
help
Say Y here if you want the debug print routines to direct
their output to UART 2. The port must have been initialised
by the boot-loader before use.
- The uncompressor code port configuration is now handled
- by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
config DEBUG_S3C_UART3
- depends on PLAT_SAMSUNG && ARCH_EXYNOS
- select DEBUG_EXYNOS_UART
- bool "Use S3C UART 3 for low-level debug"
+ depends on PLAT_SAMSUNG && (ARCH_EXYNOS || ARCH_S5PV210)
+ select DEBUG_EXYNOS_UART if ARCH_EXYNOS
+ select DEBUG_S5PV210_UART if ARCH_S5PV210
+ bool "Use Samsung S3C UART 3 for low-level debug"
help
Say Y here if you want the debug print routines to direct
their output to UART 3. The port must have been initialised
by the boot-loader before use.
- The uncompressor code port configuration is now handled
- by CONFIG_S3C_LOWLEVEL_UART_PORT.
-
config DEBUG_S3C2410_UART0
depends on ARCH_S3C24XX
select DEBUG_S3C2410_UART
@@ -715,6 +723,14 @@ choice
Say Y here if you want kernel low-level debugging support
on Allwinner A1X based platforms on the UART1.
+ config DEBUG_SUNXI_R_UART
+ bool "Kernel low-level debugging messages via sunXi R_UART"
+ depends on MACH_SUN6I || MACH_SUN8I
+ select DEBUG_UART_8250
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Allwinner A31/A23 based platforms on the R_UART.
+
config TEGRA_DEBUG_UART_AUTO_ODMDATA
bool "Kernel low-level debugging messages via Tegra UART via ODMDATA"
depends on ARCH_TEGRA
@@ -949,6 +965,9 @@ config DEBUG_S3C2410_UART
config DEBUG_S3C24XX_UART
bool
+config DEBUG_S5PV210_UART
+ bool
+
config DEBUG_OMAP2PLUS_UART
bool
depends on ARCH_OMAP2PLUS
@@ -991,6 +1010,7 @@ config DEBUG_STI_UART
config DEBUG_LL_INCLUDE
string
default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+ default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2
default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
default "debug/exynos.S" if DEBUG_EXYNOS_UART
default "debug/efm32.S" if DEBUG_LL_UART_EFM32
@@ -1009,6 +1029,7 @@ config DEBUG_LL_INCLUDE
default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
+ default "debug/s5pv210.S" if DEBUG_S5PV210_UART
default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
default "debug/sti.S" if DEBUG_STI_UART
default "debug/tegra.S" if DEBUG_TEGRA_UART
@@ -1033,7 +1054,7 @@ config DEBUG_UART_8250
def_bool ARCH_DOVE || ARCH_EBSA110 || \
(FOOTBRIDGE && !DEBUG_DC21285_PORT) || \
ARCH_GEMINI || ARCH_IOP13XX || ARCH_IOP32X || \
- ARCH_IOP33X || ARCH_IXP4XX || ARCH_KIRKWOOD || \
+ ARCH_IOP33X || ARCH_IXP4XX || \
ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC
config DEBUG_UART_PHYS
@@ -1043,6 +1064,7 @@ config DEBUG_UART_PHYS
default 0x01c28400 if DEBUG_SUNXI_UART1
default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
default 0x01d0d000 if DEBUG_DAVINCI_DA8XX_UART2
+ default 0x01f02800 if DEBUG_SUNXI_R_UART
default 0x02530c00 if DEBUG_KEYSTONE_UART0
default 0x02531000 if DEBUG_KEYSTONE_UART1
default 0x03010fe0 if ARCH_RPC
@@ -1089,13 +1111,14 @@ config DEBUG_UART_PHYS
default 0xe0000000 if ARCH_SPEAR13XX
default 0xf0000be0 if ARCH_EBSA110
default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
- default 0xf1012000 if ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
+ default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
ARCH_ORION5X
default 0xf7fc9000 if DEBUG_BERLIN_UART
- default 0xf8b00000 if DEBUG_HI3716_UART
+ default 0xf8b00000 if DEBUG_HIX5HD2_UART
default 0xf991e000 if DEBUG_QCOM_UARTDM
default 0xfcb00000 if DEBUG_HI3620_UART
default 0xfe800000 if ARCH_IOP32X
+ default 0xff690000 if DEBUG_RK32_UART2
default 0xffc02000 if DEBUG_SOCFPGA_UART
default 0xffd82340 if ARCH_IOP13XX
default 0xfff36000 if DEBUG_HIGHBANK_UART
@@ -1118,6 +1141,7 @@ config DEBUG_UART_VIRT
default 0xf1600000 if ARCH_INTEGRATOR
default 0xf1c28000 if DEBUG_SUNXI_UART0
default 0xf1c28400 if DEBUG_SUNXI_UART1
+ default 0xf1f02800 if DEBUG_SUNXI_R_UART
default 0xf2100000 if DEBUG_PXA_UART1
default 0xf4090000 if ARCH_LPC32XX
default 0xf4200000 if ARCH_GEMINI
@@ -1144,7 +1168,7 @@ config DEBUG_UART_VIRT
default 0xfe230000 if DEBUG_PICOXCELL_UART
default 0xfe300000 if DEBUG_BCM_KONA_UART
default 0xfe800000 if ARCH_IOP32X
- default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HI3716_UART
+ default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART
default 0xfeb24000 if DEBUG_RK3X_UART0
default 0xfeb26000 if DEBUG_RK3X_UART1
default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
@@ -1152,9 +1176,9 @@ config DEBUG_UART_VIRT
default 0xfec02000 if DEBUG_SOCFPGA_UART
default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE
default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0
+ default 0xfec90000 if DEBUG_RK32_UART2
default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1
default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2
- default 0xfed12000 if ARCH_KIRKWOOD
default 0xfed60000 if DEBUG_RK29_UART0
default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
@@ -1186,7 +1210,7 @@ config DEBUG_UART_8250_WORD
ARCH_KEYSTONE || \
DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
DEBUG_DAVINCI_DA8XX_UART2 || \
- DEBUG_BCM_KONA_UART
+ DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2
config DEBUG_UART_8250_FLOW_CONTROL
bool "Enable flow control for 8250 UART"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6721fab13734..0ce9d0f71f2a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -127,6 +127,9 @@ CHECKFLAGS += -D__arm__
#Default value
head-y := arch/arm/kernel/head$(MMUEXT).o
+
+# Text offset. This list is sorted numerically by address in order to
+# provide a means to avoid/resolve conflicts in multi-arch kernels.
textofs-y := 0x00008000
textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
# We don't want the htc bootloader to corrupt kernel during resume
@@ -156,14 +159,13 @@ machine-$(CONFIG_ARCH_EP93XX) += ep93xx
machine-$(CONFIG_ARCH_EXYNOS) += exynos
machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
-machine-$(CONFIG_ARCH_HI3xxx) += hisi
+machine-$(CONFIG_ARCH_HISI) += hisi
machine-$(CONFIG_ARCH_INTEGRATOR) += integrator
machine-$(CONFIG_ARCH_IOP13XX) += iop13xx
machine-$(CONFIG_ARCH_IOP32X) += iop32x
machine-$(CONFIG_ARCH_IOP33X) += iop33x
machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx
machine-$(CONFIG_ARCH_KEYSTONE) += keystone
-machine-$(CONFIG_ARCH_KIRKWOOD) += kirkwood
machine-$(CONFIG_ARCH_KS8695) += ks8695
machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx
machine-$(CONFIG_ARCH_MMP) += mmp
@@ -172,6 +174,7 @@ machine-$(CONFIG_ARCH_MSM) += msm
machine-$(CONFIG_ARCH_MV78XX0) += mv78xx0
machine-$(CONFIG_ARCH_MVEBU) += mvebu
machine-$(CONFIG_ARCH_MXC) += imx
+machine-$(CONFIG_ARCH_MEDIATEK) += mediatek
machine-$(CONFIG_ARCH_MXS) += mxs
machine-$(CONFIG_ARCH_NETX) += netx
machine-$(CONFIG_ARCH_NOMADIK) += nomadik
@@ -187,8 +190,6 @@ machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip
machine-$(CONFIG_ARCH_RPC) += rpc
machine-$(CONFIG_ARCH_S3C24XX) += s3c24xx
machine-$(CONFIG_ARCH_S3C64XX) += s3c64xx
-machine-$(CONFIG_ARCH_S5P64X0) += s5p64x0
-machine-$(CONFIG_ARCH_S5PC100) += s5pc100
machine-$(CONFIG_ARCH_S5PV210) += s5pv210
machine-$(CONFIG_ARCH_SA1100) += sa1100
machine-$(CONFIG_ARCH_SHMOBILE) += shmobile
@@ -212,11 +213,11 @@ machine-$(CONFIG_PLAT_SPEAR) += spear
plat-$(CONFIG_ARCH_EXYNOS) += samsung
plat-$(CONFIG_ARCH_OMAP) += omap
plat-$(CONFIG_ARCH_S3C64XX) += samsung
+plat-$(CONFIG_ARCH_S5PV210) += samsung
plat-$(CONFIG_PLAT_IOP) += iop
plat-$(CONFIG_PLAT_ORION) += orion
plat-$(CONFIG_PLAT_PXA) += pxa
plat-$(CONFIG_PLAT_S3C24XX) += samsung
-plat-$(CONFIG_PLAT_S5P) += samsung
plat-$(CONFIG_PLAT_VERSATILE) += versatile
ifeq ($(CONFIG_ARCH_EBSA110),y)
@@ -240,7 +241,7 @@ MACHINE :=
endif
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
-platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y))
+platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
ifneq ($(CONFIG_ARCH_MULTIPLATFORM),y)
ifeq ($(KBUILD_SRC),)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 68c918362b79..76a50ecae1c3 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -81,7 +81,7 @@ ZTEXTADDR := 0
ZBSSADDR := ALIGN(8)
endif
-SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
+CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
suffix_$(CONFIG_KERNEL_GZIP) = gzip
suffix_$(CONFIG_KERNEL_LZO) = lzo
@@ -199,8 +199,5 @@ CFLAGS_font.o := -Dstatic=
$(obj)/font.c: $(FONTC)
$(call cmd,shipped)
-$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG)
- @sed "$(SEDFLAGS)" < $< > $@
-
$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
$(call cmd,shipped)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 3a8b32df6b31..413fd94b5301 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -125,9 +125,11 @@ start:
THUMB( adr r12, BSYM(1f) )
THUMB( bx r12 )
- .word 0x016f2818 @ Magic numbers to help the loader
- .word start @ absolute load/run zImage address
- .word _edata @ zImage end address
+ .word _magic_sig @ Magic numbers to help the loader
+ .word _magic_start @ absolute load/run zImage address
+ .word _magic_end @ zImage end address
+ .word 0x04030201 @ endianness flag
+
THUMB( .thumb )
1:
ARM_BE8( setend be ) @ go BE8 if compiled for BE8
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.S
index 4919f2ac8b89..2b60b843ac5e 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -1,12 +1,20 @@
/*
- * linux/arch/arm/boot/compressed/vmlinux.lds.in
- *
* Copyright (C) 2000 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define ZIMAGE_MAGIC(x) ( (((x) >> 24) & 0x000000ff) | \
+ (((x) >> 8) & 0x0000ff00) | \
+ (((x) << 8) & 0x00ff0000) | \
+ (((x) << 24) & 0xff000000) )
+#else
+#define ZIMAGE_MAGIC(x) (x)
+#endif
+
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
@@ -57,6 +65,10 @@ SECTIONS
.pad : { BYTE(0); . = ALIGN(8); }
_edata = .;
+ _magic_sig = ZIMAGE_MAGIC(0x016f2818);
+ _magic_start = ZIMAGE_MAGIC(_start);
+ _magic_end = ZIMAGE_MAGIC(_edata);
+
. = BSS_START;
__bss_start = .;
.bss : { *(.bss) }
@@ -73,4 +85,3 @@ SECTIONS
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
-
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index adb5ed9e269e..b8c5cd3ddeb9 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -59,6 +59,8 @@ dtb-$(CONFIG_ARCH_BERLIN) += \
berlin2-sony-nsz-gs7.dtb \
berlin2cd-google-chromecast.dtb \
berlin2q-marvell-dmp.dtb
+dtb-$(CONFIG_ARCH_BRCMSTB) += \
+ bcm7445-bcm97445svmb.dtb
dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
da850-evm.dtb
dtb-$(CONFIG_ARCH_EFM32) += efm32gg-dk3750.dtb
@@ -66,7 +68,9 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos4210-smdkv310.dtb \
exynos4210-trats.dtb \
exynos4210-universal_c210.dtb \
+ exynos4412-odroidu3.dtb \
exynos4412-odroidx.dtb \
+ exynos4412-odroidx2.dtb \
exynos4412-origen.dtb \
exynos4412-smdk4412.dtb \
exynos4412-tiny4412.dtb \
@@ -83,6 +87,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos5440-ssdk5440.dtb \
exynos5800-peach-pi.dtb
dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb
+dtb-$(CONFIG_ARCH_HIX5HD2) += hisi-x5hd2-dkb.dtb
dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
ecx-2000.dtb
dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
@@ -90,9 +95,9 @@ dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \
k2l-evm.dtb \
k2e-evm.dtb
-kirkwood := \
- kirkwood-b3.dtb \
+dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
kirkwood-cloudbox.dtb \
+ kirkwood-d2net.dtb \
kirkwood-db-88f6281.dtb \
kirkwood-db-88f6282.dtb \
kirkwood-dns320.dtb \
@@ -123,6 +128,8 @@ kirkwood := \
kirkwood-lsxhl.dtb \
kirkwood-mplcec4.dtb \
kirkwood-mv88f6281gtw-ge.dtb \
+ kirkwood-net2big.dtb \
+ kirkwood-net5big.dtb \
kirkwood-netgear_readynas_duo_v2.dtb \
kirkwood-netgear_readynas_nv+_v2.dtb \
kirkwood-ns2.dtb \
@@ -150,17 +157,19 @@ kirkwood := \
kirkwood-ts219-6282.dtb \
kirkwood-ts419-6281.dtb \
kirkwood-ts419-6282.dtb
-dtb-$(CONFIG_ARCH_KIRKWOOD) += $(kirkwood)
-dtb-$(CONFIG_MACH_KIRKWOOD) += $(kirkwood)
dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
dtb-$(CONFIG_ARCH_MXC) += \
imx25-eukrea-mbimxsd25-baseboard.dtb \
+ imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dtb \
+ imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dtb \
+ imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \
imx25-karo-tx25.dtb \
imx25-pdk.dtb \
imx27-apf27.dtb \
imx27-apf27dev.dtb \
+ imx27-eukrea-mbimxsd27-baseboard.dtb \
imx27-pdk.dtb \
imx27-phytec-phycore-rdk.dtb \
imx27-phytec-phycard-s-rdk.dtb \
@@ -182,6 +191,8 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx53-tx53-x03x.dtb \
imx53-tx53-x13x.dtb \
imx53-voipac-bsb.dtb \
+ imx6dl-aristainetos_4.dtb \
+ imx6dl-aristainetos_7.dtb \
imx6dl-cubox-i.dtb \
imx6dl-dfi-fs700-m60.dtb \
imx6dl-gw51xx.dtb \
@@ -191,11 +202,16 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6dl-hummingboard.dtb \
imx6dl-nitrogen6x.dtb \
imx6dl-phytec-pbab01.dtb \
+ imx6dl-rex-basic.dtb \
imx6dl-riotboard.dtb \
imx6dl-sabreauto.dtb \
imx6dl-sabrelite.dtb \
imx6dl-sabresd.dtb \
+ imx6dl-tx6dl-comtft.dtb \
+ imx6dl-tx6u-801x.dtb \
+ imx6dl-tx6u-811x.dtb \
imx6dl-wandboard.dtb \
+ imx6dl-wandboard-revb1.dtb \
imx6q-arm2.dtb \
imx6q-cm-fx6.dtb \
imx6q-cubox-i.dtb \
@@ -209,13 +225,21 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6q-gw54xx.dtb \
imx6q-nitrogen6x.dtb \
imx6q-phytec-pbab01.dtb \
+ imx6q-rex-pro.dtb \
imx6q-sabreauto.dtb \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb \
imx6q-sbc6x.dtb \
imx6q-udoo.dtb \
imx6q-wandboard.dtb \
+ imx6q-wandboard-revb1.dtb \
+ imx6q-tx6q-1010.dtb \
+ imx6q-tx6q-1010-comtft.dtb \
+ imx6q-tx6q-1020.dtb \
+ imx6q-tx6q-1020-comtft.dtb \
+ imx6q-tx6q-1110.dtb \
imx6sl-evk.dtb \
+ imx6sx-sdb.dtb \
vf610-colibri.dtb \
vf610-cosmic.dtb \
vf610-twr.dtb
@@ -291,7 +315,8 @@ dtb-$(CONFIG_SOC_AM33XX) += am335x-base0033.dtb \
am335x-boneblack.dtb \
am335x-evm.dtb \
am335x-evmsk.dtb \
- am335x-nano.dtb
+ am335x-nano.dtb \
+ am335x-pepper.dtb
dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
omap4-panda.dtb \
omap4-panda-a4.dtb \
@@ -301,6 +326,7 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
omap4-var-dvk-om44.dtb \
omap4-var-stk-om44.dtb
dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \
+ am437x-sk-evm.dtb \
am437x-gp-evm.dtb
dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \
omap5-sbc-t54.dtb \
@@ -318,16 +344,25 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8084-mtp.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += \
+ rk3066a-bqcurie2.dtb \
+ rk3188-radxarock.dtb \
+ rk3288-evb-act8846.dtb \
+ rk3288-evb-rk808.dtb
dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
s3c6410-smdk6410.dtb
+dtb-$(CONFIG_ARCH_S5PV210) += s5pv210-aquila.dtb \
+ s5pv210-goni.dtb \
+ s5pv210-smdkc110.dtb \
+ s5pv210-smdkv210.dtb \
+ s5pv210-torbreck.dtb
dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += r7s72100-genmai.dtb \
r8a7740-armadillo800eva.dtb \
r8a7778-bockw.dtb \
r8a7778-bockw-reference.dtb \
r8a7740-armadillo800eva-reference.dtb \
r8a7779-marzen.dtb \
- r8a7779-marzen-reference.dtb \
r8a7791-koelsch.dtb \
r8a7790-lager.dtb \
sh73a0-kzm9g.dtb \
@@ -339,7 +374,8 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \
r7s72100-genmai.dtb \
r8a7791-henninger.dtb \
r8a7791-koelsch.dtb \
- r8a7790-lager.dtb
+ r8a7790-lager.dtb \
+ r8a7779-marzen.dtb
dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \
socfpga_cyclone5_socdk.dtb \
socfpga_cyclone5_sockit.dtb \
@@ -360,6 +396,7 @@ dtb-$(CONFIG_ARCH_STI)+= stih407-b2120.dtb \
stih416-b2020e.dtb
dtb-$(CONFIG_MACH_SUN4I) += \
sun4i-a10-a1000.dtb \
+ sun4i-a10-ba10-tvbox.dtb \
sun4i-a10-cubieboard.dtb \
sun4i-a10-mini-xplus.dtb \
sun4i-a10-hackberry.dtb \
@@ -374,12 +411,16 @@ dtb-$(CONFIG_MACH_SUN5I) += \
dtb-$(CONFIG_MACH_SUN6I) += \
sun6i-a31-app4-evb1.dtb \
sun6i-a31-colombus.dtb \
+ sun6i-a31-hummingbird.dtb \
sun6i-a31-m9.dtb
dtb-$(CONFIG_MACH_SUN7I) += \
sun7i-a20-cubieboard2.dtb \
sun7i-a20-cubietruck.dtb \
sun7i-a20-i12-tvbox.dtb \
- sun7i-a20-olinuxino-micro.dtb
+ sun7i-a20-olinuxino-micro.dtb \
+ sun7i-a20-pcduino3.dtb
+dtb-$(CONFIG_MACH_SUN8I) += \
+ sun8i-a23-ippo-q8h-v5.dtb
dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
tegra20-iris-512.dtb \
tegra20-medcom-wide.dtb \
@@ -390,6 +431,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
tegra20-trimslice.dtb \
tegra20-ventana.dtb \
tegra20-whistler.dtb \
+ tegra30-apalis-eval.dtb \
tegra30-beaver.dtb \
tegra30-cardhu-a02.dtb \
tegra30-cardhu-a04.dtb \
@@ -419,7 +461,9 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
wm8650-mid.dtb \
wm8750-apc8750.dtb \
wm8850-w70v2.dtb
-dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \
+dtb-$(CONFIG_ARCH_ZYNQ) += \
+ zynq-parallella.dtb \
+ zynq-zc702.dtb \
zynq-zc706.dtb \
zynq-zed.dtb
dtb-$(CONFIG_MACH_ARMADA_370) += \
@@ -437,11 +481,13 @@ dtb-$(CONFIG_MACH_ARMADA_XP) += \
armada-xp-axpwifiap.dtb \
armada-xp-db.dtb \
armada-xp-gp.dtb \
- armada-xp-netgear-rn2120.dtb \
+ armada-xp-lenovo-ix4-300d.dtb \
armada-xp-matrix.dtb \
+ armada-xp-netgear-rn2120.dtb \
armada-xp-openblocks-ax3-4.dtb
dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
dove-cubox.dtb \
+ dove-cubox-es.dtb \
dove-d2plug.dtb \
dove-d3plug.dtb \
dove-dove-db.dtb
diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
index 54cb5cf8604a..d9c50fbb49d2 100644
--- a/arch/arm/boot/dts/aks-cdu.dts
+++ b/arch/arm/boot/dts/aks-cdu.dts
@@ -16,6 +16,12 @@
bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
};
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+ };
+
ahb {
apb {
usart0: serial@fffb0000 {
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 80a3b215e7d6..df5fee6b6b4b 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -149,12 +149,113 @@
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT";
};
+
+ panel {
+ compatible = "ti,tilcdc,panel";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&lcd_pins_default>;
+ pinctrl-1 = <&lcd_pins_sleep>;
+ status = "okay";
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+ dma-burst-sz = <16>;
+ bpp = <32>;
+ fdd = <0x80>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
+ };
+ display-timings {
+ 480x272 {
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <43>;
+ hfront-porch = <8>;
+ hsync-len = <4>;
+ vback-porch = <12>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ clock-frequency = <9000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ };
+ };
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
+ lcd_pins_default: lcd_pins_default {
+ pinctrl-single,pins = <
+ 0x20 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data23 */
+ 0x24 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data22 */
+ 0x28 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data21 */
+ 0x2c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data20 */
+ 0x30 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data19 */
+ 0x34 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data18 */
+ 0x38 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data17 */
+ 0x3c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data16 */
+ 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ 0xe0 (PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ 0xe4 (PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ 0xe8 (PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ 0xec (PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+
+ lcd_pins_sleep: lcd_pins_sleep {
+ pinctrl-single,pins = <
+ 0x20 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad8.lcd_data23 */
+ 0x24 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad9.lcd_data22 */
+ 0x28 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.lcd_data21 */
+ 0x2c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.lcd_data20 */
+ 0x30 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.lcd_data19 */
+ 0x34 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.lcd_data18 */
+ 0x38 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.lcd_data17 */
+ 0x3c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.lcd_data16 */
+ 0xa0 (PULL_DISABLE | MUX_MODE7) /* lcd_data0.lcd_data0 */
+ 0xa4 (PULL_DISABLE | MUX_MODE7) /* lcd_data1.lcd_data1 */
+ 0xa8 (PULL_DISABLE | MUX_MODE7) /* lcd_data2.lcd_data2 */
+ 0xac (PULL_DISABLE | MUX_MODE7) /* lcd_data3.lcd_data3 */
+ 0xb0 (PULL_DISABLE | MUX_MODE7) /* lcd_data4.lcd_data4 */
+ 0xb4 (PULL_DISABLE | MUX_MODE7) /* lcd_data5.lcd_data5 */
+ 0xb8 (PULL_DISABLE | MUX_MODE7) /* lcd_data6.lcd_data6 */
+ 0xbc (PULL_DISABLE | MUX_MODE7) /* lcd_data7.lcd_data7 */
+ 0xc0 (PULL_DISABLE | MUX_MODE7) /* lcd_data8.lcd_data8 */
+ 0xc4 (PULL_DISABLE | MUX_MODE7) /* lcd_data9.lcd_data9 */
+ 0xc8 (PULL_DISABLE | MUX_MODE7) /* lcd_data10.lcd_data10 */
+ 0xcc (PULL_DISABLE | MUX_MODE7) /* lcd_data11.lcd_data11 */
+ 0xd0 (PULL_DISABLE | MUX_MODE7) /* lcd_data12.lcd_data12 */
+ 0xd4 (PULL_DISABLE | MUX_MODE7) /* lcd_data13.lcd_data13 */
+ 0xd8 (PULL_DISABLE | MUX_MODE7) /* lcd_data14.lcd_data14 */
+ 0xdc (PULL_DISABLE | MUX_MODE7) /* lcd_data15.lcd_data15 */
+ 0xe0 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.lcd_vsync */
+ 0xe4 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.lcd_hsync */
+ 0xe8 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.lcd_pclk */
+ 0xec (PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ >;
+ };
+
+
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */
@@ -573,3 +674,7 @@
ti,wire-config = <0x00 0x11 0x22 0x33>;
};
};
+
+&lcdc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts
new file mode 100644
index 000000000000..0d35ab64641c
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-pepper.dts
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2014 Gumstix, Inc. - https://www.gumstix.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "am33xx.dtsi"
+
+/ {
+ model = "Gumstix Pepper";
+ compatible = "gumstix,am335x-pepper", "ti,am33xx";
+
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&dcdc3_reg>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+
+ buttons: user_buttons {
+ compatible = "gpio-keys";
+ };
+
+ leds: user_leds {
+ compatible = "gpio-leds";
+ };
+
+ panel: lcd_panel {
+ compatible = "ti,tilcdc,panel";
+ };
+
+ sound: sound_iface {
+ compatible = "ti,da830-evm-audio";
+ };
+
+ vbat: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ };
+
+ v3v3c_reg: fixedregulator@1 {
+ compatible = "regulator-fixed";
+ };
+
+ vdd5_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ };
+};
+
+/* I2C Busses */
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ clock-frequency = <400000>;
+
+ tps: tps@24 {
+ reg = <0x24>;
+ };
+
+ eeprom: eeprom@50 {
+ compatible = "at,24c256";
+ reg = <0x50>;
+ };
+
+ audio_codec: tlv320aic3106@1b {
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ };
+
+ accel: lis331dlh@1d {
+ compatible = "st,lis3lv02d";
+ reg = <0x1d>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+};
+
+&am33xx_pinmux {
+ i2c0_pins: pinmux_i2c0 {
+ pinctrl-single,pins = <
+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+ >;
+ };
+ i2c1_pins: pinmux_i2c1 {
+ pinctrl-single,pins = <
+ 0x10C (PIN_INPUT_PULLUP | MUX_MODE3) /* mii1_crs,i2c1_sda */
+ 0x110 (PIN_INPUT_PULLUP | MUX_MODE3) /* mii1_rxerr,i2c1_scl */
+ >;
+ };
+};
+
+/* Accelerometer */
+&accel {
+ pinctrl-names = "default";
+ pinctrl-0 = <&accel_pins>;
+
+ Vdd-supply = <&ldo3_reg>;
+ Vdd_IO-supply = <&ldo3_reg>;
+ st,irq1-click;
+ st,wakeup-x-lo;
+ st,wakeup-x-hi;
+ st,wakeup-y-lo;
+ st,wakeup-y-hi;
+ st,wakeup-z-lo;
+ st,wakeup-z-hi;
+ st,min-limit-x = <92>;
+ st,max-limit-x = <14>;
+ st,min-limit-y = <14>;
+ st,max-limit-y = <92>;
+ st,min-limit-z = <92>;
+ st,max-limit-z = <14>;
+};
+
+&am33xx_pinmux {
+ accel_pins: pinmux_accel {
+ pinctrl-single,pins = <
+ 0x98 (PIN_INPUT | MUX_MODE7) /* gpmc_wen.gpio2_4 */
+ >;
+ };
+};
+
+/* Audio */
+&audio_codec {
+ status = "okay";
+
+ gpio-reset = <&gpio1 16 GPIO_ACTIVE_LOW>;
+ AVDD-supply = <&ldo3_reg>;
+ IOVDD-supply = <&ldo3_reg>;
+ DRVDD-supply = <&ldo3_reg>;
+ DVDD-supply = <&dcdc1_reg>;
+};
+
+&sound {
+ ti,model = "AM335x-EVM";
+ ti,audio-codec = <&audio_codec>;
+ ti,mcasp-controller = <&mcasp0>;
+ ti,codec-clock-rate = <12000000>;
+ ti,audio-routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "LINE1L", "Line In";
+};
+
+&mcasp0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_pins>;
+
+ op-mode = <0>; /* MCASP_ISS_MODE */
+ tdm-slots = <2>;
+ serial-dir = <
+ 1 2 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ >;
+ tx-num-evt = <1>;
+ rx-num-evt = <1>;
+};
+
+&am33xx_pinmux {
+ audio_pins: pinmux_audio {
+ pinctrl-single,pins = <
+ 0x1AC (PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+ 0x194 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+ 0x190 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+ 0x198 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0.mcasp0_axr0 */
+ 0x1A8 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr1.mcasp0_axr1 */
+ 0x40 (PIN_OUTPUT | MUX_MODE7) /* gpmc_a0.gpio1_16 */
+ >;
+ };
+};
+
+/* Display: 24-bit LCD Screen */
+&panel {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+ dma-burst-sz = <16>;
+ bpp = <32>;
+ fdd = <0x80>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
+ };
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 480x272 {
+ clock-frequency = <18400000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <4>;
+ hsync-len = <41>;
+ vfront-porch = <4>;
+ vback-porch = <2>;
+ vsync-len = <10>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+};
+
+&lcdc {
+ status = "okay";
+};
+
+&am33xx_pinmux {
+ lcd_pins: pinmux_lcd {
+ pinctrl-single,pins = <
+ 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
+ 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
+ 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
+ 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
+ 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
+ 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
+ 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
+ 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
+ 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
+ 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
+ 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
+ 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
+ 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
+ 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
+ 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
+ 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
+ 0x20 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data16 */
+ 0x24 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data17 */
+ 0x28 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data18 */
+ 0x2c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data19 */
+ 0x30 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data20 */
+ 0x34 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data21 */
+ 0x38 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data22 */
+ 0x3c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data23 */
+ 0xe0 (PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */
+ 0xe4 (PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */
+ 0xe8 (PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */
+ 0xec (PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
+ /* Display Enable */
+ 0x6c (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a11.gpio1_27 */
+ >;
+ };
+};
+
+/* Ethernet */
+&cpsw_emac0 {
+ status = "okay";
+ phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "rgmii";
+};
+
+&cpsw_emac1 {
+ status = "okay";
+ phy_id = <&davinci_mdio>, <1>;
+ phy-mode = "rgmii";
+};
+
+&davinci_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio_pins>;
+};
+
+&mac {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ethernet_pins>;
+};
+
+
+&am33xx_pinmux {
+ ethernet_pins: pinmux_ethernet {
+ pinctrl-single,pins = <
+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
+ 0x118 (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
+ 0x12c (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
+ 0x130 (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
+ 0x134 (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd3.rgmii1_rxd3 */
+ 0x138 (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd2.rgmii1_rxd2 */
+ 0x13c (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd1 */
+ 0x140 (PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd0 */
+ /* ethernet interrupt */
+ 0x144 (PIN_INPUT_PULLUP | MUX_MODE7) /* rmii2_refclk.gpio0_29 */
+ /* ethernet PHY nReset */
+ 0x108 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mii1_col.gpio3_0 */
+ >;
+ };
+
+ mdio_pins: pinmux_mdio {
+ pinctrl-single,pins = <
+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
+ >;
+ };
+};
+
+/* MMC */
+&mmc1 {
+ /* Bootable SD card slot */
+ status = "okay";
+ vmmc-supply = <&ldo3_reg>;
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_pins>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&mmc2 {
+ /* eMMC (not populated) on MMC #2 */
+ status = "disabled";
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins>;
+ vmmc-supply = <&ldo3_reg>;
+ bus-width = <8>;
+ ti,non-removable;
+};
+
+&edma {
+ /* Map eDMA MMC2 Events from Crossbar */
+ ti,edma-xbar-event-map = /bits/ 16 <1 12
+ 2 13>;
+};
+
+
+&mmc3 {
+ /* Wifi & Bluetooth on MMC #3 */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wireless_pins>;
+ vmmmc-supply = <&v3v3c_reg>;
+ bus-width = <4>;
+ ti,non-removable;
+ dmas = <&edma 12
+ &edma 13>;
+ dma-names = "tx", "rx";
+};
+
+
+&am33xx_pinmux {
+ sd_pins: pinmux_sd_card {
+ pinctrl-single,pins = <
+ 0xf0 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ 0xf4 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ 0xf8 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ 0xfc (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ 0x100 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ 0x104 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ >;
+ };
+ emmc_pins: pinmux_emmc {
+ pinctrl-single,pins = <
+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+ /* EMMC nReset */
+ 0x74 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
+ >;
+ };
+ wireless_pins: pinmux_wireless {
+ pinctrl-single,pins = <
+ 0x44 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0 */
+ 0x48 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1 */
+ 0x4c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2 */
+ 0x78 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ben1.mmc2_dat3 */
+ 0x88 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd */
+ 0x8c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc1_clk */
+ /* WLAN nReset */
+ 0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
+ /* WLAN nPower down */
+ 0x70 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
+ /* 32kHz Clock */
+ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
+ >;
+ };
+};
+
+/* Power */
+&vbat {
+ regulator-name = "vbat";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+};
+
+&v3v3c_reg {
+ regulator-name = "v3v3c_reg";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vbat>;
+};
+
+&vdd5_reg {
+ regulator-name = "vdd5_reg";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vbat>;
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+ backlight {
+ isel = <1>; /* ISET1 */
+ fdim = <200>; /* TPS65217_BL_FDIM_200HZ */
+ default-brightness = <80>;
+ };
+
+ regulators {
+ dcdc1_reg: regulator@0 {
+ /* VDD_1V8 system supply */
+ };
+
+ dcdc2_reg: regulator@1 {
+ /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1325000>;
+ regulator-boot-on;
+ };
+
+ dcdc3_reg: regulator@2 {
+ /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ };
+
+ ldo1_reg: regulator@3 {
+ /* VRTC 1.8V always-on supply */
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@4 {
+ /* 3.3V rail */
+ };
+
+ ldo3_reg: regulator@5 {
+ /* VDD_3V3A 3.3V rail */
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo4_reg: regulator@6 {
+ /* VDD_3V3B 3.3V rail */
+ };
+ };
+};
+
+/* SPI Busses */
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+};
+
+&am33xx_pinmux {
+ spi0_pins: pinmux_spi0 {
+ pinctrl-single,pins = <
+ 0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
+ 0x15C (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
+ 0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
+ 0x158 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
+ >;
+ };
+};
+
+/* Touch Screen */
+&tscadc {
+ status = "okay";
+ tsc {
+ ti,wires = <4>;
+ ti,x-plate-resistance = <200>;
+ ti,coordinate-readouts = <5>;
+ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+ ti,adc-channels = <4 5 6 7>;
+ };
+};
+
+/* UARTs */
+&uart0 {
+ /* Serial Console */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+};
+
+&uart1 {
+ /* Broken out to J6 header */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+};
+
+&am33xx_pinmux {
+ uart0_pins: pinmux_uart0 {
+ pinctrl-single,pins = <
+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+ >;
+ };
+ uart1_pins: pinmux_uart1 {
+ pinctrl-single,pins = <
+ 0x178 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */
+ 0x17C (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
+ 0x180 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */
+ 0x184 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */
+ >;
+ };
+};
+
+/* USB */
+&usb {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_pins>;
+};
+
+&usb_ctrl_mod {
+ status = "okay";
+};
+
+&usb0_phy {
+ status = "okay";
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&usb1 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&cppi41dma {
+ status = "okay";
+};
+
+&am33xx_pinmux {
+ usb_pins: pinmux_usb {
+ pinctrl-single,pins = <
+ /* USB0 Over-Current (active low) */
+ 0x64 (PIN_INPUT | MUX_MODE7) /* gpmc_a9.gpio1_25 */
+ /* USB1 Over-Current (active low) */
+ 0x68 (PIN_INPUT | MUX_MODE7) /* gpmc_a10.gpio1_26 */
+ >;
+ };
+};
+
+/* User IO */
+&leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_leds_pins>;
+
+ led@0 {
+ label = "pepper:user0:blue";
+ gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "off";
+ };
+
+ led@1 {
+ label = "pepper:user1:red";
+ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "off";
+ };
+};
+
+&buttons {
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_buttons_pins>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ button@0 {
+ label = "home";
+ linux,code = <KEY_HOME>;
+ gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ };
+
+ button@1 {
+ label = "menu";
+ linux,code = <KEY_MENU>;
+ gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ };
+
+ buttons@2 {
+ label = "power";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ };
+};
+
+&am33xx_pinmux {
+ user_leds_pins: pinmux_user_leds {
+ pinctrl-single,pins = <
+ 0x50 (PIN_OUTPUT | MUX_MODE7) /* gpmc_a4.gpio1_20 */
+ 0x54 (PIN_OUTPUT | MUX_MODE7) /* gpmc_a5.gpio1_21 */
+ >;
+ };
+
+ user_buttons_pins: pinmux_user_buttons {
+ pinctrl-single,pins = <
+ 0x58 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
+ 0x5C (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a7.gpio1_21 */
+ 0x164 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio0_7 */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 4a4e02d0ce9e..3a0a161342ba 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -347,6 +347,15 @@
status = "disabled";
};
+ mailbox: mailbox@480C8000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x480C8000 0x200>;
+ interrupts = <77>;
+ ti,hwmods = "mailbox";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <8>;
+ };
+
timer1: timer@44e31000 {
compatible = "ti,am335x-timer-1ms";
reg = <0x44e31000 0x400>;
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 49fa59622254..9b3d2ba82f13 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -30,7 +30,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0>;
@@ -168,9 +168,6 @@
ti,hwmods = "mailbox";
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <8>;
- ti,mbox-names = "wkup_m3";
- ti,mbox-data = <0 0 0 0>;
- status = "disabled";
};
timer1: timer@44e31000 {
@@ -270,7 +267,7 @@
ti,hwmods = "counter_32k";
};
- rtc@44e3e000 {
+ rtc: rtc@44e3e000 {
compatible = "ti,am4372-rtc","ti,da830-rtc";
reg = <0x44e3e000 0x1000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
@@ -279,7 +276,7 @@
status = "disabled";
};
- wdt@44e35000 {
+ wdt: wdt@44e35000 {
compatible = "ti,am4372-wdt","ti,omap3-wdt";
reg = <0x44e35000 0x1000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
@@ -871,7 +868,7 @@
#size-cells = <1>;
ranges;
- dispc@4832a400 {
+ dispc: dispc@4832a400 {
compatible = "ti,omap3-dispc";
reg = <0x4832a400 0x400>;
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 003766c47bbf..646a6eade788 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -257,16 +257,73 @@
};
&i2c0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins>;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <400000>;
+
+ tps65218: tps65218@24 {
+ reg = <0x24>;
+ compatible = "ti,tps65218";
+ interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+ interrupt-parent = <&gic>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ dcdc1: regulator-dcdc1 {
+ compatible = "ti,tps65218-dcdc1";
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1144000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc2: regulator-dcdc2 {
+ compatible = "ti,tps65218-dcdc2";
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1378000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3: regulator-dcdc3 {
+ compatible = "ti,tps65218-dcdc3";
+ regulator-name = "vdcdc3";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ dcdc5: regulator-dcdc5 {
+ compatible = "ti,tps65218-dcdc5";
+ regulator-name = "v1_0bat";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ dcdc6: regulator-dcdc6 {
+ compatible = "ti,tps65218-dcdc6";
+ regulator-name = "v1_8bat";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo1: regulator-ldo1 {
+ compatible = "ti,tps65218-ldo1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
};
&i2c1 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins>;
-
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
pixcir_ts@5c {
compatible = "pixcir,pixcir_tangoc";
pinctrl-names = "default";
@@ -277,8 +334,8 @@
attb-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
- x-size = <1024>;
- y-size = <600>;
+ touchscreen-size-x = <1024>;
+ touchscreen-size-y = <600>;
};
};
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
new file mode 100644
index 000000000000..859ff3d620ee
--- /dev/null
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -0,0 +1,613 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM437x SK EVM */
+
+/dts-v1/;
+
+#include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "TI AM437x SK EVM";
+ compatible = "ti,am437x-sk-evm","ti,am4372","ti,am43";
+
+ aliases {
+ display0 = &lcd0;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <0 51 53 56 62 75 101 152 255>;
+ default-brightness-level = <8>;
+ };
+
+ sound {
+ compatible = "ti,da830-evm-audio";
+ ti,model = "AM437x-SK-EVM";
+ ti,audio-codec = <&tlv320aic3106>;
+ ti,mcasp-controller = <&mcasp1>;
+ ti,codec-clock-rate = <24000000>;
+ ti,audio-routing =
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT";
+ };
+
+ matrix_keypad: matrix_keypad@0 {
+ compatible = "gpio-matrix-keypad";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&matrix_keypad_pins>;
+
+ debounce-delay-ms = <5>;
+ col-scan-delay-us = <1500>;
+
+ row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH /* Bank5, pin5 */
+ &gpio5 6 GPIO_ACTIVE_HIGH>; /* Bank5, pin6 */
+
+ col-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH /* Bank5, pin13 */
+ &gpio5 4 GPIO_ACTIVE_HIGH>; /* Bank5, pin4 */
+
+ linux,keymap = <
+ MATRIX_KEY(0, 0, KEY_DOWN)
+ MATRIX_KEY(0, 1, KEY_RIGHT)
+ MATRIX_KEY(1, 0, KEY_LEFT)
+ MATRIX_KEY(1, 1, KEY_UP)
+ >;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_pins>;
+
+ led@0 {
+ label = "am437x-sk:red:heartbeat";
+ gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 0 */
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led@1 {
+ label = "am437x-sk:green:mmc1";
+ gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 1 */
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
+ led@2 {
+ label = "am437x-sk:blue:cpu0";
+ gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 2 */
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
+ led@3 {
+ label = "am437x-sk:blue:usr3";
+ gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 3 */
+ default-state = "off";
+ };
+ };
+
+ lcd0: display {
+ compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+ label = "lcd";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+
+ enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+
+ panel-timing {
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <8>;
+ hback-porch = <43>;
+ hsync-len = <4>;
+ vback-porch = <12>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ port {
+ lcd_in: endpoint {
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+ };
+};
+
+&am43xx_pinmux {
+ matrix_keypad_pins: matrix_keypad_pins {
+ pinctrl-single,pins = <
+ 0x24c (PIN_OUTPUT | MUX_MODE7) /* gpio5_13.gpio5_13 */
+ 0x250 (PIN_OUTPUT | MUX_MODE7) /* spi4_sclk.gpio5_4 */
+ 0x254 (PIN_INPUT | MUX_MODE7) /* spi4_d0.gpio5_5 */
+ 0x258 (PIN_INPUT | MUX_MODE7) /* spi4_d1.gpio5_5 */
+ >;
+ };
+
+ leds_pins: leds_pins {
+ pinctrl-single,pins = <
+ 0x228 (PIN_OUTPUT | MUX_MODE7) /* uart3_rxd.gpio5_2 */
+ 0x22c (PIN_OUTPUT | MUX_MODE7) /* uart3_txd.gpio5_3 */
+ 0x230 (PIN_OUTPUT | MUX_MODE7) /* uart3_ctsn.gpio5_0 */
+ 0x234 (PIN_OUTPUT | MUX_MODE7) /* uart3_rtsn.gpio5_1 */
+ >;
+ };
+
+ i2c0_pins: i2c0_pins {
+ pinctrl-single,pins = <
+ 0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */
+ 0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */
+ >;
+ };
+
+ i2c1_pins: i2c1_pins {
+ pinctrl-single,pins = <
+ 0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */
+ 0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */
+ >;
+ };
+
+ mmc1_pins: pinmux_mmc1_pins {
+ pinctrl-single,pins = <
+ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ >;
+ };
+
+ ecap0_pins: backlight_pins {
+ pinctrl-single,pins = <
+ 0x164 (PIN_OUTPUT | MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
+ >;
+ };
+
+ edt_ft5306_ts_pins: edt_ft5306_ts_pins {
+ pinctrl-single,pins = <
+ 0x74 (PIN_INPUT | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
+ 0x78 (PIN_OUTPUT | MUX_MODE7) /* gpmc_be1n.gpio1_28 */
+ >;
+ };
+
+ cpsw_default: cpsw_default {
+ pinctrl-single,pins = <
+ /* Slave 1 */
+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rmii1_tclk */
+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */
+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */
+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */
+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */
+
+ /* Slave 2 */
+ 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
+ 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
+ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
+ 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
+ 0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
+ 0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
+ 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
+ 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rtcl */
+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
+ 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
+ >;
+ };
+
+ cpsw_sleep: cpsw_sleep {
+ pinctrl-single,pins = <
+ /* Slave 1 reset value */
+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+ /* Slave 2 reset value */
+ 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ davinci_mdio_default: davinci_mdio_default {
+ pinctrl-single,pins = <
+ /* MDIO */
+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
+ >;
+ };
+
+ davinci_mdio_sleep: davinci_mdio_sleep {
+ pinctrl-single,pins = <
+ /* MDIO reset value */
+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+ >;
+ };
+
+ dss_pins: dss_pins {
+ pinctrl-single,pins = <
+ 0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /* gpmc ad 8 -> DSS DATA 23 */
+ 0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x02c (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1)
+ 0x03c (PIN_OUTPUT_PULLUP | MUX_MODE1) /* gpmc ad 15 -> DSS DATA 16 */
+ 0x0a0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */
+ 0x0a4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0a8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0ac (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0b0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0b4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0b8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0bc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0c0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0c4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0c8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0cc (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0d0 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0d4 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0d8 (PIN_OUTPUT_PULLUP | MUX_MODE0)
+ 0x0dc (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */
+ 0x0e0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */
+ 0x0e4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */
+ 0x0e8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */
+ 0x0ec (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */
+
+ >;
+ };
+
+ qspi_pins: qspi_pins {
+ pinctrl-single,pins = <
+ 0x7c (PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_csn0.qspi_csn */
+ 0x88 (PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */
+ 0x90 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */
+ 0x94 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */
+ 0x98 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wen.qspi_d2 */
+ 0x9c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */
+ >;
+ };
+
+ mcasp1_pins: mcasp1_pins {
+ pinctrl-single,pins = <
+ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+ 0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+ >;
+ };
+
+ lcd_pins: lcd_pins {
+ pinctrl-single,pins = <
+ /* GPIO 5_8 to select LCD / HDMI */
+ 0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7)
+ >;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <400000>;
+
+ tps@24 {
+ compatible = "ti,tps65218";
+ reg = <0x24>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ dcdc1: regulator-dcdc1 {
+ compatible = "ti,tps65218-dcdc1";
+ /* VDD_CORE limits min of OPP50 and max of OPP100 */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1144000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc2: regulator-dcdc2 {
+ compatible = "ti,tps65218-dcdc2";
+ /* VDD_MPU limits min of OPP50 and max of OPP_NITRO */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1378000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3: regulator-dcdc3 {
+ compatible = "ti,tps65218-dcdc3";
+ regulator-name = "vdds_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc4: regulator-dcdc4 {
+ compatible = "ti,tps65218-dcdc4";
+ regulator-name = "v3_3d";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1: regulator-ldo1 {
+ compatible = "ti,tps65218-ldo1";
+ regulator-name = "v1_8d";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ };
+
+ at24@50 {
+ compatible = "at24,24c256";
+ pagesize = <64>;
+ reg = <0x50>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <400000>;
+
+ edt-ft5306@38 {
+ status = "okay";
+ compatible = "edt,edt-ft5306", "edt,edt-ft5x06";
+ pinctrl-names = "default";
+ pinctrl-0 = <&edt_ft5306_ts_pins>;
+
+ reg = <0x38>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <31 0>;
+
+ wake-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <272>;
+ };
+
+ tlv320aic3106: tlv320aic3106@1b {
+ compatible = "ti,tlv320aic3106";
+ reg = <0x1b>;
+ status = "okay";
+
+ /* Regulators */
+ AVDD-supply = <&dcdc4>;
+ IOVDD-supply = <&dcdc4>;
+ DRVDD-supply = <&dcdc4>;
+ DVDD-supply = <&ldo1>;
+ };
+
+ lis331dlh@18 {
+ compatible = "st,lis331dlh";
+ reg = <0x18>;
+ status = "okay";
+
+ Vdd-supply = <&dcdc4>;
+ Vdd_IO-supply = <&dcdc4>;
+ interrupts-extended = <&gpio1 6 0>, <&gpio2 1 0>;
+ };
+};
+
+&epwmss0 {
+ status = "okay";
+};
+
+&ecap0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ecap0_pins>;
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&gpio5 {
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+
+ vmmc-supply = <&dcdc4>;
+ bus-width = <4>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+};
+
+&usb2_phy1 {
+ status = "okay";
+};
+
+&usb1 {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb2_phy2 {
+ status = "okay";
+};
+
+&usb2 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&qspi {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&qspi_pins>;
+
+ spi-max-frequency = <48000000>;
+ m25p80@0 {
+ compatible = "mx66l51235l";
+ spi-max-frequency = <48000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* MTD partition table.
+ * The ROM checks the first 512KiB
+ * for a valid file to boot(XIP).
+ */
+ partition@0 {
+ label = "QSPI.U_BOOT";
+ reg = <0x00000000 0x000080000>;
+ };
+ partition@1 {
+ label = "QSPI.U_BOOT.backup";
+ reg = <0x00080000 0x00080000>;
+ };
+ partition@2 {
+ label = "QSPI.U-BOOT-SPL_OS";
+ reg = <0x00100000 0x00010000>;
+ };
+ partition@3 {
+ label = "QSPI.U_BOOT_ENV";
+ reg = <0x00110000 0x00010000>;
+ };
+ partition@4 {
+ label = "QSPI.U-BOOT-ENV.backup";
+ reg = <0x00120000 0x00010000>;
+ };
+ partition@5 {
+ label = "QSPI.KERNEL";
+ reg = <0x00130000 0x0800000>;
+ };
+ partition@6 {
+ label = "QSPI.FILESYSTEM";
+ reg = <0x00930000 0x36D0000>;
+ };
+ };
+};
+
+&mac {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cpsw_default>;
+ pinctrl-1 = <&cpsw_sleep>;
+ dual_emac = <1>;
+ status = "okay";
+};
+
+&davinci_mdio {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&davinci_mdio_default>;
+ pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
+};
+
+&cpsw_emac0 {
+ phy_id = <&davinci_mdio>, <4>;
+ phy-mode = "rgmii";
+ dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <5>;
+ phy-mode = "rgmii";
+ dual_emac_res_vlan = <2>;
+};
+
+&elm {
+ status = "okay";
+};
+
+&mcasp1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcasp1_pins>;
+
+ status = "okay";
+
+ op-mode = <0>;
+ tdm-slots = <2>;
+ serial-dir = <
+ 0 0 1 2
+ >;
+
+ tx-num-evt = <1>;
+ rx-num-evt = <1>;
+};
+
+&dss {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&dss_pins>;
+
+ port {
+ dpi_out: endpoint@0 {
+ remote-endpoint = <&lcd_in>;
+ data-lines = <24>;
+ };
+ };
+};
+
+&rtc {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 90098f98a5c8..ed7dd2395915 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -327,6 +327,65 @@
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <400000>;
+
+ tps65218: tps65218@24 {
+ reg = <0x24>;
+ compatible = "ti,tps65218";
+ interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+ interrupt-parent = <&gic>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ dcdc1: regulator-dcdc1 {
+ compatible = "ti,tps65218-dcdc1";
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1144000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc2: regulator-dcdc2 {
+ compatible = "ti,tps65218-dcdc2";
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <1378000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3: regulator-dcdc3 {
+ compatible = "ti,tps65218-dcdc3";
+ regulator-name = "vdcdc3";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc5: regulator-dcdc5 {
+ compatible = "ti,tps65218-dcdc5";
+ regulator-name = "v1_0bat";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ dcdc6: regulator-dcdc6 {
+ compatible = "ti,tps65218-dcdc6";
+ regulator-name = "v1_8bat";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo1: regulator-ldo1 {
+ compatible = "ti,tps65218-ldo1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
at24@50 {
compatible = "at24,24c256";
@@ -344,8 +403,8 @@
attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
- x-size = <1024>;
- y-size = <600>;
+ touchscreen-size-x = <1024>;
+ touchscreen-size-y = <600>;
};
};
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
index 3c4f6d983cbd..4e0ad3b82796 100644
--- a/arch/arm/boot/dts/animeo_ip.dts
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -40,6 +40,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts
index 1e2919d43d78..929ae00b4063 100644
--- a/arch/arm/boot/dts/armada-375-db.dts
+++ b/arch/arm/boot/dts/armada-375-db.dts
@@ -123,6 +123,32 @@
cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
};
+
+ mdio {
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ };
+ };
+
+ ethernet@f0000 {
+ status = "okay";
+
+ eth0@c4000 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "rgmii-id";
+ };
+
+ eth1@c5000 {
+ status = "okay";
+ phy = <&phy3>;
+ phy-mode = "gmii";
+ };
+ };
};
pcie-controller {
diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
index fb92551a1e71..c1e49e7bf0fa 100644
--- a/arch/arm/boot/dts/armada-375.dtsi
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -25,6 +25,8 @@
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
+ ethernet0 = &eth0;
+ ethernet1 = &eth1;
};
clocks {
@@ -151,6 +153,38 @@
<0xc100 0x100>;
};
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0xc0054 0x4>;
+ clocks = <&gateclk 19>;
+ };
+
+ /* Network controller */
+ ethernet@f0000 {
+ compatible = "marvell,armada-375-pp2";
+ reg = <0xf0000 0xa000>, /* Packet Processor regs */
+ <0xc0000 0x3060>, /* LMS regs */
+ <0xc4000 0x100>, /* eth0 regs */
+ <0xc5000 0x100>; /* eth1 regs */
+ clocks = <&gateclk 3>, <&gateclk 19>;
+ clock-names = "pp_clk", "gop_clk";
+ status = "disabled";
+
+ eth0: eth0@c4000 {
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <0>;
+ status = "disabled";
+ };
+
+ eth1: eth1@c5000 {
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ port-id = <1>;
+ status = "disabled";
+ };
+ };
+
spi0: spi@10600 {
compatible = "marvell,orion-spi";
reg = <0x10600 0x50>;
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index 689fa1a46728..242d0ecc99f3 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -286,6 +286,11 @@
reg = <0x20800 0x10>;
};
+ mpcore-soc-ctrl@20d20 {
+ compatible = "marvell,armada-380-mpcore-soc-ctrl";
+ reg = <0x20d20 0x6c>;
+ };
+
coherency-fabric@21010 {
compatible = "marvell,armada-380-coherency-fabric";
reg = <0x21010 0x1c>;
diff --git a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
new file mode 100644
index 000000000000..469cf7137595
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
@@ -0,0 +1,284 @@
+/*
+ * Device Tree file for Lenovo Iomega ix4-300d
+ *
+ * Copyright (C) 2014, Benoit Masson <yahoo@perenite.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+ model = "Lenovo Iomega ix4-300d";
+ compatible = "lenovo,ix4-300d", "marvell,armadaxp-mv78230",
+ "marvell,armadaxp", "marvell,armada-370-xp";
+
+ chosen {
+ bootargs = "console=ttyS0,115200 earlyprintk";
+ stdout-path = "/soc/internal-regs/serial@12000";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x00000000 0 0x20000000>; /* 512MB */
+ };
+
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+ pcie-controller {
+ status = "okay";
+
+ /* Quad port sata: Marvell 88SX7042 */
+ pcie@1,0 {
+ /* Port 0, Lane 0 */
+ status = "okay";
+ };
+
+ /* USB 3.0 xHCI controller: NEC D720200F1 */
+ pcie@5,0 {
+ /* Port 1, Lane 0 */
+ status = "okay";
+ };
+ };
+
+ internal-regs {
+ pinctrl {
+ poweroff_pin: poweroff-pin {
+ marvell,pins = "mpp24";
+ marvell,function = "gpio";
+ };
+
+ power_button_pin: power-button-pin {
+ marvell,pins = "mpp44";
+ marvell,function = "gpio";
+ };
+
+ reset_button_pin: reset-button-pin {
+ marvell,pins = "mpp45";
+ marvell,function = "gpio";
+ };
+ select_button_pin: select-button-pin {
+ marvell,pins = "mpp41";
+ marvell,function = "gpio";
+ };
+
+ scroll_button_pin: scroll-button-pin {
+ marvell,pins = "mpp42";
+ marvell,function = "gpio";
+ };
+
+ hdd_led_pin: hdd-led-pin {
+ marvell,pins = "mpp26";
+ marvell,function = "gpio";
+ };
+ };
+
+ serial@12000 {
+ status = "okay";
+ };
+
+ mdio {
+ phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+ reg = <0>;
+ };
+
+ phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+ reg = <1>;
+ };
+ };
+
+ ethernet@70000 {
+ status = "okay";
+ phy = <&phy0>;
+ phy-mode = "rgmii-id";
+ };
+
+ ethernet@74000 {
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "rgmii-id";
+ };
+
+ usb@50000 {
+ status = "okay";
+ };
+
+ usb@51000 {
+ status = "okay";
+ };
+
+ i2c@11000 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ adt7473@2e {
+ compatible = "adi,adt7473";
+ reg = <0x2e>;
+ };
+
+ pcf8563@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+
+ };
+
+ nand@d0000 {
+ status = "okay";
+ num-cs = <1>;
+ marvell,nand-keep-config;
+ marvell,nand-enable-arbiter;
+ nand-on-flash-bbt;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0xe0000>;
+ read-only;
+ };
+
+ partition@e0000 {
+ label = "u-boot-env";
+ reg = <0xe0000 0x20000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env2";
+ reg = <0x100000 0x20000>;
+ read-only;
+ };
+
+ partition@120000 {
+ label = "zImage";
+ reg = <0x120000 0x400000>;
+ };
+
+ partition@520000 {
+ label = "initrd";
+ reg = <0x520000 0x400000>;
+ };
+
+ partition@xE00000 {
+ label = "boot";
+ reg = <0xE00000 0x3F200000>;
+ };
+
+ partition@flash {
+ label = "flash";
+ reg = <0x0 0x40000000>;
+ };
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&power_button_pin &reset_button_pin
+ &select_button_pin &scroll_button_pin>;
+ pinctrl-names = "default";
+
+ power-button {
+ label = "Power Button";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ reset-button {
+ label = "Reset Button";
+ linux,code = <KEY_RESTART>;
+ gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+ };
+
+ select-button {
+ label = "Select Button";
+ linux,code = <BTN_SELECT>;
+ gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ };
+
+ scroll-button {
+ label = "Scroll Button";
+ linux,code = <KEY_SCROLLDOWN>;
+ gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ spi3 {
+ compatible = "spi-gpio";
+ status = "okay";
+ gpio-sck = <&gpio0 25 GPIO_ACTIVE_LOW>;
+ gpio-mosi = <&gpio1 15 GPIO_ACTIVE_LOW>; /*gpio 47*/
+ cs-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio_spi: gpio_spi@0 {
+ compatible = "fairchild,74hc595";
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0>;
+ registers-number = <2>;
+ spi-max-frequency = <100000>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&hdd_led_pin>;
+ pinctrl-names = "default";
+
+ hdd-led {
+ label = "ix4-300d:hdd:blue";
+ gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ power-led {
+ label = "ix4-300d:power:white";
+ gpios = <&gpio_spi 1 GPIO_ACTIVE_LOW>;
+ /* init blinking while booting */
+ linux,default-trigger = "timer";
+ default-state = "on";
+ };
+
+ sysfail-led {
+ label = "ix4-300d:sysfail:red";
+ gpios = <&gpio_spi 2 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ sys-led {
+ label = "ix4-300d:sys:blue";
+ gpios = <&gpio_spi 3 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ hddfail-led {
+ label = "ix4-300d:hddfail:red";
+ gpios = <&gpio_spi 4 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ };
+
+ /*
+ * Warning: you need both eth1 & 0 PHY initialized (i.e having
+ * them up does the tweak) for poweroff to shutdown otherwise it
+ * reboots
+ */
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ pinctrl-0 = <&poweroff_pin>;
+ pinctrl-names = "default";
+ gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+ };
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index 1257ff1ed278..2592e1c13560 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -34,6 +34,7 @@
compatible = "marvell,sheeva-v7";
reg = <0>;
clocks = <&cpuclk 0>;
+ clock-latency = <1000000>;
};
cpu@1 {
@@ -41,6 +42,7 @@
compatible = "marvell,sheeva-v7";
reg = <1>;
clocks = <&cpuclk 1>;
+ clock-latency = <1000000>;
};
};
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 3396b25b39e1..480e237a870f 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -36,6 +36,7 @@
compatible = "marvell,sheeva-v7";
reg = <0>;
clocks = <&cpuclk 0>;
+ clock-latency = <1000000>;
};
cpu@1 {
@@ -43,6 +44,7 @@
compatible = "marvell,sheeva-v7";
reg = <1>;
clocks = <&cpuclk 1>;
+ clock-latency = <1000000>;
};
};
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index 6da84bf40aaf..2c7b1fef4703 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -37,6 +37,7 @@
compatible = "marvell,sheeva-v7";
reg = <0>;
clocks = <&cpuclk 0>;
+ clock-latency = <1000000>;
};
cpu@1 {
@@ -44,6 +45,7 @@
compatible = "marvell,sheeva-v7";
reg = <1>;
clocks = <&cpuclk 1>;
+ clock-latency = <1000000>;
};
cpu@2 {
@@ -51,6 +53,7 @@
compatible = "marvell,sheeva-v7";
reg = <2>;
clocks = <&cpuclk 2>;
+ clock-latency = <1000000>;
};
cpu@3 {
@@ -58,6 +61,7 @@
compatible = "marvell,sheeva-v7";
reg = <3>;
clocks = <&cpuclk 3>;
+ clock-latency = <1000000>;
};
};
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 5902e8359c91..bff9f6c18db1 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -99,7 +99,7 @@
cpuclk: clock-complex@18700 {
#clock-cells = <1>;
compatible = "marvell,armada-xp-cpu-clock";
- reg = <0x18700 0xA0>;
+ reg = <0x18700 0xA0>, <0x1c054 0x10>;
clocks = <&coreclk 1>;
};
diff --git a/arch/arm/boot/dts/at91-ariag25.dts b/arch/arm/boot/dts/at91-ariag25.dts
index 55ab6180e350..e9ced30159a7 100644
--- a/arch/arm/boot/dts/at91-ariag25.dts
+++ b/arch/arm/boot/dts/at91-ariag25.dts
@@ -42,6 +42,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91-cosino.dtsi b/arch/arm/boot/dts/at91-cosino.dtsi
index df4b78695695..b6ea3f4a7206 100644
--- a/arch/arm/boot/dts/at91-cosino.dtsi
+++ b/arch/arm/boot/dts/at91-cosino.dtsi
@@ -34,6 +34,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91-foxg20.dts b/arch/arm/boot/dts/at91-foxg20.dts
index cbe967343997..f89598af4c2b 100644
--- a/arch/arm/boot/dts/at91-foxg20.dts
+++ b/arch/arm/boot/dts/at91-foxg20.dts
@@ -31,6 +31,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91-qil_a9260.dts b/arch/arm/boot/dts/at91-qil_a9260.dts
index 5576ae8786c0..a9aef53ab764 100644
--- a/arch/arm/boot/dts/at91-qil_a9260.dts
+++ b/arch/arm/boot/dts/at91-qil_a9260.dts
@@ -28,6 +28,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
index 5b8e40400bec..fec1fca2ad66 100644
--- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -21,12 +21,14 @@
reg = <0x20000000 0x10000000>;
};
- slow_xtal {
- clock-frequency = <32768>;
- };
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
- main_xtal {
- clock-frequency = <12000000>;
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
index c61b16fba79b..65ccf564b9a5 100644
--- a/arch/arm/boot/dts/at91rm9200.dtsi
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/pinctrl/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
/ {
model = "Atmel AT91RM9200 family SoC";
@@ -51,6 +52,20 @@
reg = <0x20000000 0x04000000>;
};
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -79,6 +94,260 @@
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+ clocks = <&main_xtal>;
+ };
+
+ main: mainck {
+ compatible = "atmel,at91rm9200-clk-main";
+ #clock-cells = <0>;
+ clocks = <&main_osc>;
+ };
+
+ plla: pllack {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+ clocks = <&main>;
+ reg = <0>;
+ atmel,clk-input-range = <1000000 32000000>;
+ #atmel,pll-clk-output-range-cells = <3>;
+ atmel,pll-clk-output-ranges = <80000000 160000000 0>,
+ <150000000 180000000 2>;
+ };
+
+ pllb: pllbck {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+ clocks = <&main>;
+ reg = <1>;
+ atmel,clk-input-range = <1000000 32000000>;
+ #atmel,pll-clk-output-range-cells = <3>;
+ atmel,pll-clk-output-ranges = <80000000 160000000 0>,
+ <150000000 180000000 2>;
+ };
+
+ mck: masterck {
+ compatible = "atmel,at91rm9200-clk-master";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+ atmel,clk-output-range = <0 80000000>;
+ atmel,clk-divisors = <1 2 3 4>;
+ };
+
+ usb: usbck {
+ compatible = "atmel,at91rm9200-clk-usb";
+ #clock-cells = <0>;
+ atmel,clk-divisors = <1 2>;
+ clocks = <&pllb>;
+ };
+
+ prog: progck {
+ compatible = "atmel,at91rm9200-clk-programmable";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&pmc>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+
+ prog0: prog0 {
+ #clock-cells = <0>;
+ reg = <0>;
+ interrupts = <AT91_PMC_PCKRDY(0)>;
+ };
+
+ prog1: prog1 {
+ #clock-cells = <0>;
+ reg = <1>;
+ interrupts = <AT91_PMC_PCKRDY(1)>;
+ };
+
+ prog2: prog2 {
+ #clock-cells = <0>;
+ reg = <2>;
+ interrupts = <AT91_PMC_PCKRDY(2)>;
+ };
+
+ prog3: prog3 {
+ #clock-cells = <0>;
+ reg = <3>;
+ interrupts = <AT91_PMC_PCKRDY(3)>;
+ };
+ };
+
+ systemck {
+ compatible = "atmel,at91rm9200-clk-system";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ udpck: udpck {
+ #clock-cells = <0>;
+ reg = <2>;
+ clocks = <&usb>;
+ };
+
+ uhpck: uhpck {
+ #clock-cells = <0>;
+ reg = <4>;
+ clocks = <&usb>;
+ };
+
+ pck0: pck0 {
+ #clock-cells = <0>;
+ reg = <8>;
+ clocks = <&prog0>;
+ };
+
+ pck1: pck1 {
+ #clock-cells = <0>;
+ reg = <9>;
+ clocks = <&prog1>;
+ };
+
+ pck2: pck2 {
+ #clock-cells = <0>;
+ reg = <10>;
+ clocks = <&prog2>;
+ };
+
+ pck3: pck3 {
+ #clock-cells = <0>;
+ reg = <11>;
+ clocks = <&prog3>;
+ };
+ };
+
+ periphck {
+ compatible = "atmel,at91rm9200-clk-peripheral";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&mck>;
+
+ pioA_clk: pioA_clk {
+ #clock-cells = <0>;
+ reg = <2>;
+ };
+
+ pioB_clk: pioB_clk {
+ #clock-cells = <0>;
+ reg = <3>;
+ };
+
+ pioC_clk: pioC_clk {
+ #clock-cells = <0>;
+ reg = <4>;
+ };
+
+ pioD_clk: pioD_clk {
+ #clock-cells = <0>;
+ reg = <5>;
+ };
+
+ usart0_clk: usart0_clk {
+ #clock-cells = <0>;
+ reg = <6>;
+ };
+
+ usart1_clk: usart1_clk {
+ #clock-cells = <0>;
+ reg = <7>;
+ };
+
+ usart2_clk: usart2_clk {
+ #clock-cells = <0>;
+ reg = <8>;
+ };
+
+ usart3_clk: usart3_clk {
+ #clock-cells = <0>;
+ reg = <9>;
+ };
+
+ mci0_clk: mci0_clk {
+ #clock-cells = <0>;
+ reg = <10>;
+ };
+
+ udc_clk: udc_clk {
+ #clock-cells = <0>;
+ reg = <11>;
+ };
+
+ twi0_clk: twi0_clk {
+ reg = <12>;
+ #clock-cells = <0>;
+ };
+
+ spi0_clk: spi0_clk {
+ #clock-cells = <0>;
+ reg = <13>;
+ };
+
+ ssc0_clk: ssc0_clk {
+ #clock-cells = <0>;
+ reg = <14>;
+ };
+
+ ssc1_clk: ssc1_clk {
+ #clock-cells = <0>;
+ reg = <15>;
+ };
+
+ ssc2_clk: ssc2_clk {
+ #clock-cells = <0>;
+ reg = <16>;
+ };
+
+ tc0_clk: tc0_clk {
+ #clock-cells = <0>;
+ reg = <17>;
+ };
+
+ tc1_clk: tc1_clk {
+ #clock-cells = <0>;
+ reg = <18>;
+ };
+
+ tc2_clk: tc2_clk {
+ #clock-cells = <0>;
+ reg = <19>;
+ };
+
+ tc3_clk: tc3_clk {
+ #clock-cells = <0>;
+ reg = <20>;
+ };
+
+ tc4_clk: tc4_clk {
+ #clock-cells = <0>;
+ reg = <21>;
+ };
+
+ tc5_clk: tc5_clk {
+ #clock-cells = <0>;
+ reg = <22>;
+ };
+
+ ohci_clk: ohci_clk {
+ #clock-cells = <0>;
+ reg = <23>;
+ };
+
+ macb0_clk: macb0_clk {
+ #clock-cells = <0>;
+ reg = <24>;
+ };
+ };
};
st: timer@fffffd00 {
@@ -93,6 +362,8 @@
interrupts = <17 IRQ_TYPE_LEVEL_HIGH 0
18 IRQ_TYPE_LEVEL_HIGH 0
19 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tc0_clk>, <&tc1_clk>, <&tc2_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
tcb1: timer@fffa4000 {
@@ -101,6 +372,8 @@
interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0
21 IRQ_TYPE_LEVEL_HIGH 0
22 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tc3_clk>, <&tc4_clk>, <&tc5_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
i2c0: i2c@fffb8000 {
@@ -109,6 +382,7 @@
interrupts = <12 IRQ_TYPE_LEVEL_HIGH 6>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_twi>;
+ clocks = <&twi0_clk>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -118,6 +392,8 @@
compatible = "atmel,hsmci";
reg = <0xfffb4000 0x4000>;
interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&mci0_clk>;
+ clock-names = "mci_clk";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
@@ -130,6 +406,8 @@
interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ clocks = <&ssc0_clk>;
+ clock-names = "pclk";
status = "disable";
};
@@ -139,6 +417,8 @@
interrupts = <15 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+ clocks = <&ssc1_clk>;
+ clock-names = "pclk";
status = "disable";
};
@@ -148,6 +428,8 @@
interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc2_tx &pinctrl_ssc2_rx>;
+ clocks = <&ssc2_clk>;
+ clock-names = "pclk";
status = "disable";
};
@@ -158,6 +440,8 @@
phy-mode = "rmii";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb_rmii>;
+ clocks = <&macb0_clk>;
+ clock-names = "ether_clk";
status = "disabled";
};
@@ -496,6 +780,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioA_clk>;
};
pioB: gpio@fffff600 {
@@ -506,6 +791,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioB_clk>;
};
pioC: gpio@fffff800 {
@@ -516,6 +802,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioC_clk>;
};
pioD: gpio@fffffa00 {
@@ -526,6 +813,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioD_clk>;
};
};
@@ -535,6 +823,8 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
+ clocks = <&mck>;
+ clock-names = "usart";
status = "disabled";
};
@@ -546,6 +836,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
+ clocks = <&usart0_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -557,6 +849,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
+ clocks = <&usart1_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -568,6 +862,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
+ clocks = <&usart2_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -579,6 +875,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
+ clocks = <&usart3_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -586,6 +884,8 @@
compatible = "atmel,at91rm9200-udc";
reg = <0xfffb0000 0x4000>;
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&udc_clk>, <&udpck>;
+ clock-names = "pclk", "hclk";
status = "disabled";
};
@@ -597,6 +897,8 @@
interrupts = <13 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
+ clocks = <&spi0_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
};
@@ -622,6 +924,8 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00300000 0x100000>;
interrupts = <23 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+ clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts
index df6b0aa0e4dd..43eb779dd6f6 100644
--- a/arch/arm/boot/dts/at91rm9200ek.dts
+++ b/arch/arm/boot/dts/at91rm9200ek.dts
@@ -25,6 +25,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index c0e0eae16a27..cb100b03a362 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/pinctrl/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
/ {
model = "Atmel AT91SAM9260 family SoC";
@@ -48,6 +49,26 @@
reg = <0x20000000 0x04000000>;
};
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ adc_op_clk: adc_op_clk{
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <5000000>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -74,8 +95,260 @@
};
pmc: pmc@fffffc00 {
- compatible = "atmel,at91rm9200-pmc";
+ compatible = "atmel,at91sam9260-pmc";
reg = <0xfffffc00 0x100>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+ clocks = <&main_xtal>;
+ };
+
+ main: mainck {
+ compatible = "atmel,at91rm9200-clk-main";
+ #clock-cells = <0>;
+ clocks = <&main_osc>;
+ };
+
+ slow_rc_osc: slow_rc_osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-accuracy = <50000000>;
+ };
+
+ clk32k: slck {
+ compatible = "atmel,at91sam9260-clk-slow";
+ #clock-cells = <0>;
+ clocks = <&slow_rc_osc>, <&slow_xtal>;
+ };
+
+ plla: pllack {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+ clocks = <&main>;
+ reg = <0>;
+ atmel,clk-input-range = <1000000 32000000>;
+ #atmel,pll-clk-output-range-cells = <4>;
+ atmel,pll-clk-output-ranges = <80000000 160000000 0 1>,
+ <150000000 240000000 2 1>;
+ };
+
+ pllb: pllbck {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+ clocks = <&main>;
+ reg = <1>;
+ atmel,clk-input-range = <1000000 5000000>;
+ #atmel,pll-clk-output-range-cells = <4>;
+ atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
+ };
+
+ mck: masterck {
+ compatible = "atmel,at91rm9200-clk-master";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+ clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+ atmel,clk-output-range = <0 105000000>;
+ atmel,clk-divisors = <1 2 4 0>;
+ };
+
+ usb: usbck {
+ compatible = "atmel,at91rm9200-clk-usb";
+ #clock-cells = <0>;
+ atmel,clk-divisors = <1 2 4 0>;
+ clocks = <&pllb>;
+ };
+
+ prog: progck {
+ compatible = "atmel,at91rm9200-clk-programmable";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&pmc>;
+ clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+
+ prog0: prog0 {
+ #clock-cells = <0>;
+ reg = <0>;
+ interrupts = <AT91_PMC_PCKRDY(0)>;
+ };
+
+ prog1: prog1 {
+ #clock-cells = <0>;
+ reg = <1>;
+ interrupts = <AT91_PMC_PCKRDY(1)>;
+ };
+ };
+
+ systemck {
+ compatible = "atmel,at91rm9200-clk-system";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ uhpck: uhpck {
+ #clock-cells = <0>;
+ reg = <6>;
+ clocks = <&usb>;
+ };
+
+ udpck: udpck {
+ #clock-cells = <0>;
+ reg = <7>;
+ clocks = <&usb>;
+ };
+
+ pck0: pck0 {
+ #clock-cells = <0>;
+ reg = <8>;
+ clocks = <&prog0>;
+ };
+
+ pck1: pck1 {
+ #clock-cells = <0>;
+ reg = <9>;
+ clocks = <&prog1>;
+ };
+ };
+
+ periphck {
+ compatible = "atmel,at91rm9200-clk-peripheral";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&mck>;
+
+ pioA_clk: pioA_clk {
+ #clock-cells = <0>;
+ reg = <2>;
+ };
+
+ pioB_clk: pioB_clk {
+ #clock-cells = <0>;
+ reg = <3>;
+ };
+
+ pioC_clk: pioC_clk {
+ #clock-cells = <0>;
+ reg = <4>;
+ };
+
+ adc_clk: adc_clk {
+ #clock-cells = <0>;
+ reg = <5>;
+ };
+
+ usart0_clk: usart0_clk {
+ #clock-cells = <0>;
+ reg = <6>;
+ };
+
+ usart1_clk: usart1_clk {
+ #clock-cells = <0>;
+ reg = <7>;
+ };
+
+ usart2_clk: usart2_clk {
+ #clock-cells = <0>;
+ reg = <8>;
+ };
+
+ mci0_clk: mci0_clk {
+ #clock-cells = <0>;
+ reg = <9>;
+ };
+
+ udc_clk: udc_clk {
+ #clock-cells = <0>;
+ reg = <10>;
+ };
+
+ twi0_clk: twi0_clk {
+ reg = <11>;
+ #clock-cells = <0>;
+ };
+
+ spi0_clk: spi0_clk {
+ #clock-cells = <0>;
+ reg = <12>;
+ };
+
+ spi1_clk: spi1_clk {
+ #clock-cells = <0>;
+ reg = <13>;
+ };
+
+ ssc0_clk: ssc0_clk {
+ #clock-cells = <0>;
+ reg = <14>;
+ };
+
+ tc0_clk: tc0_clk {
+ #clock-cells = <0>;
+ reg = <17>;
+ };
+
+ tc1_clk: tc1_clk {
+ #clock-cells = <0>;
+ reg = <18>;
+ };
+
+ tc2_clk: tc2_clk {
+ #clock-cells = <0>;
+ reg = <19>;
+ };
+
+ ohci_clk: ohci_clk {
+ #clock-cells = <0>;
+ reg = <20>;
+ };
+
+ macb0_clk: macb0_clk {
+ #clock-cells = <0>;
+ reg = <21>;
+ };
+
+ isi_clk: isi_clk {
+ #clock-cells = <0>;
+ reg = <22>;
+ };
+
+ usart3_clk: usart3_clk {
+ #clock-cells = <0>;
+ reg = <23>;
+ };
+
+ uart0_clk: uart0_clk {
+ #clock-cells = <0>;
+ reg = <24>;
+ };
+
+ uart1_clk: uart1_clk {
+ #clock-cells = <0>;
+ reg = <25>;
+ };
+
+ tc3_clk: tc3_clk {
+ #clock-cells = <0>;
+ reg = <26>;
+ };
+
+ tc4_clk: tc4_clk {
+ #clock-cells = <0>;
+ reg = <27>;
+ };
+
+ tc5_clk: tc5_clk {
+ #clock-cells = <0>;
+ reg = <28>;
+ };
+ };
};
rstc@fffffd00 {
@@ -92,6 +365,7 @@
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0xf>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&mck>;
};
tcb0: timer@fffa0000 {
@@ -100,6 +374,8 @@
interrupts = <17 IRQ_TYPE_LEVEL_HIGH 0
18 IRQ_TYPE_LEVEL_HIGH 0
19 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tc0_clk>, <&tc1_clk>, <&tc2_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
tcb1: timer@fffdc000 {
@@ -108,6 +384,8 @@
interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0
27 IRQ_TYPE_LEVEL_HIGH 0
28 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tc3_clk>, <&tc4_clk>, <&tc5_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
pinctrl@fffff400 {
@@ -443,6 +721,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioA_clk>;
};
pioB: gpio@fffff600 {
@@ -453,6 +732,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioB_clk>;
};
pioC: gpio@fffff800 {
@@ -463,6 +743,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioC_clk>;
};
};
@@ -472,6 +753,8 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
+ clocks = <&mck>;
+ clock-names = "usart";
status = "disabled";
};
@@ -483,6 +766,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart0>;
+ clocks = <&usart0_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -494,6 +779,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart1>;
+ clocks = <&usart1_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -505,6 +792,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart2>;
+ clocks = <&usart2_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -516,6 +805,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart3>;
+ clocks = <&usart3_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -527,6 +818,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
+ clocks = <&uart0_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -538,6 +831,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
+ clocks = <&uart1_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -547,6 +842,8 @@
interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb_rmii>;
+ clocks = <&macb0_clk>, <&macb0_clk>;
+ clock-names = "hclk", "pclk";
status = "disabled";
};
@@ -554,6 +851,8 @@
compatible = "atmel,at91rm9200-udc";
reg = <0xfffa4000 0x4000>;
interrupts = <10 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&udc_clk>, <&udpck>;
+ clock-names = "pclk", "hclk";
status = "disabled";
};
@@ -563,6 +862,7 @@
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 6>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&twi0_clk>;
status = "disabled";
};
@@ -573,6 +873,8 @@
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
+ clocks = <&mci0_clk>;
+ clock-names = "mci_clk";
status = "disabled";
};
@@ -582,6 +884,8 @@
interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ clocks = <&ssc0_clk>;
+ clock-names = "pclk";
status = "disabled";
};
@@ -593,6 +897,8 @@
interrupts = <12 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
+ clocks = <&spi0_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -604,6 +910,8 @@
interrupts = <13 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
+ clocks = <&spi1_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -613,6 +921,8 @@
compatible = "atmel,at91sam9260-adc";
reg = <0xfffe0000 0x100>;
interrupts = <5 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&adc_clk>, <&adc_op_clk>;
+ clock-names = "adc_clk", "adc_op_clk";
atmel,adc-use-external-triggers;
atmel,adc-channels-used = <0xf>;
atmel,adc-vref = <3300>;
@@ -680,6 +990,8 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00500000 0x100000>;
interrupts = <20 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+ clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/at91sam9261.dtsi b/arch/arm/boot/dts/at91sam9261.dtsi
index 04927db1d6bf..a81aab4281a7 100644
--- a/arch/arm/boot/dts/at91sam9261.dtsi
+++ b/arch/arm/boot/dts/at91sam9261.dtsi
@@ -46,16 +46,18 @@
reg = <0x20000000 0x08000000>;
};
- main_xtal: main_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ clocks {
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- slow_xtal: slow_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9261ek.dts b/arch/arm/boot/dts/at91sam9261ek.dts
index aa35a7aec9a8..f4a765729c7a 100644
--- a/arch/arm/boot/dts/at91sam9261ek.dts
+++ b/arch/arm/boot/dts/at91sam9261ek.dts
@@ -20,14 +20,6 @@
reg = <0x20000000 0x4000000>;
};
- slow_xtal {
- clock-frequency = <32768>;
- };
-
- main_xtal {
- clock-frequency = <18432000>;
- };
-
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -37,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index fece8665fb63..bb23c2d33cf8 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/pinctrl/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
/ {
model = "Atmel AT91SAM9263 family SoC";
@@ -32,6 +33,7 @@
ssc1 = &ssc1;
pwm0 = &pwm0;
};
+
cpus {
#address-cells = <0>;
#size-cells = <0>;
@@ -46,6 +48,20 @@
reg = <0x20000000 0x08000000>;
};
+ clocks {
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -69,6 +85,264 @@
pmc: pmc@fffffc00 {
compatible = "atmel,at91rm9200-pmc";
reg = <0xfffffc00 0x100>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+ clocks = <&main_xtal>;
+ };
+
+ main: mainck {
+ compatible = "atmel,at91rm9200-clk-main";
+ #clock-cells = <0>;
+ clocks = <&main_osc>;
+ };
+
+ plla: pllack {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+ clocks = <&main>;
+ reg = <0>;
+ atmel,clk-input-range = <1000000 32000000>;
+ #atmel,pll-clk-output-range-cells = <4>;
+ atmel,pll-clk-output-ranges = <80000000 200000000 0 1>,
+ <190000000 240000000 2 1>;
+ };
+
+ pllb: pllbck {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKB>;
+ clocks = <&main>;
+ reg = <1>;
+ atmel,clk-input-range = <1000000 5000000>;
+ #atmel,pll-clk-output-range-cells = <4>;
+ atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
+ };
+
+ mck: masterck {
+ compatible = "atmel,at91rm9200-clk-master";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+ atmel,clk-output-range = <0 120000000>;
+ atmel,clk-divisors = <1 2 4 0>;
+ };
+
+ usb: usbck {
+ compatible = "atmel,at91rm9200-clk-usb";
+ #clock-cells = <0>;
+ atmel,clk-divisors = <1 2 4 0>;
+ clocks = <&pllb>;
+ };
+
+ prog: progck {
+ compatible = "atmel,at91rm9200-clk-programmable";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&pmc>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
+
+ prog0: prog0 {
+ #clock-cells = <0>;
+ reg = <0>;
+ interrupts = <AT91_PMC_PCKRDY(0)>;
+ };
+
+ prog1: prog1 {
+ #clock-cells = <0>;
+ reg = <1>;
+ interrupts = <AT91_PMC_PCKRDY(1)>;
+ };
+
+ prog2: prog2 {
+ #clock-cells = <0>;
+ reg = <2>;
+ interrupts = <AT91_PMC_PCKRDY(2)>;
+ };
+
+ prog3: prog3 {
+ #clock-cells = <0>;
+ reg = <3>;
+ interrupts = <AT91_PMC_PCKRDY(3)>;
+ };
+ };
+
+ systemck {
+ compatible = "atmel,at91rm9200-clk-system";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ uhpck: uhpck {
+ #clock-cells = <0>;
+ reg = <6>;
+ clocks = <&usb>;
+ };
+
+ udpck: udpck {
+ #clock-cells = <0>;
+ reg = <7>;
+ clocks = <&usb>;
+ };
+
+ pck0: pck0 {
+ #clock-cells = <0>;
+ reg = <8>;
+ clocks = <&prog0>;
+ };
+
+ pck1: pck1 {
+ #clock-cells = <0>;
+ reg = <9>;
+ clocks = <&prog1>;
+ };
+
+ pck2: pck2 {
+ #clock-cells = <0>;
+ reg = <10>;
+ clocks = <&prog2>;
+ };
+
+ pck3: pck3 {
+ #clock-cells = <0>;
+ reg = <11>;
+ clocks = <&prog3>;
+ };
+ };
+
+ periphck {
+ compatible = "atmel,at91rm9200-clk-peripheral";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&mck>;
+
+ pioA_clk: pioA_clk {
+ #clock-cells = <0>;
+ reg = <2>;
+ };
+
+ pioB_clk: pioB_clk {
+ #clock-cells = <0>;
+ reg = <3>;
+ };
+
+ pioCDE_clk: pioCDE_clk {
+ #clock-cells = <0>;
+ reg = <4>;
+ };
+
+ usart0_clk: usart0_clk {
+ #clock-cells = <0>;
+ reg = <7>;
+ };
+
+ usart1_clk: usart1_clk {
+ #clock-cells = <0>;
+ reg = <8>;
+ };
+
+ usart2_clk: usart2_clk {
+ #clock-cells = <0>;
+ reg = <9>;
+ };
+
+ mci0_clk: mci0_clk {
+ #clock-cells = <0>;
+ reg = <10>;
+ };
+
+ mci1_clk: mci1_clk {
+ #clock-cells = <0>;
+ reg = <11>;
+ };
+
+ can_clk: can_clk {
+ #clock-cells = <0>;
+ reg = <12>;
+ };
+
+ twi0_clk: twi0_clk {
+ #clock-cells = <0>;
+ reg = <13>;
+ };
+
+ spi0_clk: spi0_clk {
+ #clock-cells = <0>;
+ reg = <14>;
+ };
+
+ spi1_clk: spi1_clk {
+ #clock-cells = <0>;
+ reg = <15>;
+ };
+
+ ssc0_clk: ssc0_clk {
+ #clock-cells = <0>;
+ reg = <16>;
+ };
+
+ ssc1_clk: ssc1_clk {
+ #clock-cells = <0>;
+ reg = <17>;
+ };
+
+ ac91_clk: ac97_clk {
+ #clock-cells = <0>;
+ reg = <18>;
+ };
+
+ tcb_clk: tcb_clk {
+ #clock-cells = <0>;
+ reg = <19>;
+ };
+
+ pwm_clk: pwm_clk {
+ #clock-cells = <0>;
+ reg = <20>;
+ };
+
+ macb0_clk: macb0_clk {
+ #clock-cells = <0>;
+ reg = <21>;
+ };
+
+ g2de_clk: g2de_clk {
+ #clock-cells = <0>;
+ reg = <23>;
+ };
+
+ udc_clk: udc_clk {
+ #clock-cells = <0>;
+ reg = <24>;
+ };
+
+ isi_clk: isi_clk {
+ #clock-cells = <0>;
+ reg = <25>;
+ };
+
+ lcd_clk: lcd_clk {
+ #clock-cells = <0>;
+ reg = <26>;
+ };
+
+ dma_clk: dma_clk {
+ #clock-cells = <0>;
+ reg = <27>;
+ };
+
+ ohci_clk: ohci_clk {
+ #clock-cells = <0>;
+ reg = <29>;
+ };
+ };
};
ramc: ramc@ffffe200 {
@@ -81,12 +355,15 @@
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0xf>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&mck>;
};
tcb0: timer@fff7c000 {
compatible = "atmel,at91rm9200-tcb";
reg = <0xfff7c000 0x100>;
interrupts = <19 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tcb_clk>;
+ clock-names = "t0_clk";
};
rstc@fffffd00 {
@@ -403,6 +680,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioA_clk>;
};
pioB: gpio@fffff400 {
@@ -413,6 +691,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioB_clk>;
};
pioC: gpio@fffff600 {
@@ -423,6 +702,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioCDE_clk>;
};
pioD: gpio@fffff800 {
@@ -433,6 +713,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioCDE_clk>;
};
pioE: gpio@fffffa00 {
@@ -443,6 +724,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioCDE_clk>;
};
};
@@ -452,6 +734,8 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
+ clocks = <&mck>;
+ clock-names = "usart";
status = "disabled";
};
@@ -463,6 +747,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart0>;
+ clocks = <&usart0_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -474,6 +760,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart1>;
+ clocks = <&usart1_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -485,6 +773,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart2>;
+ clocks = <&usart2_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -494,6 +784,8 @@
interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ clocks = <&ssc0_clk>;
+ clock-names = "pclk";
status = "disabled";
};
@@ -503,6 +795,8 @@
interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+ clocks = <&ssc1_clk>;
+ clock-names = "pclk";
status = "disabled";
};
@@ -512,6 +806,8 @@
interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb_rmii>;
+ clocks = <&macb0_clk>, <&macb0_clk>;
+ clock-names = "hclk", "pclk";
status = "disabled";
};
@@ -519,6 +815,8 @@
compatible = "atmel,at91rm9200-udc";
reg = <0xfff78000 0x4000>;
interrupts = <24 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&udc_clk>, <&udpck>;
+ clock-names = "pclk", "hclk";
status = "disabled";
};
@@ -528,6 +826,7 @@
interrupts = <13 IRQ_TYPE_LEVEL_HIGH 6>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&twi0_clk>;
status = "disabled";
};
@@ -537,6 +836,8 @@
interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mci0_clk>;
+ clock-names = "mci_clk";
status = "disabled";
};
@@ -546,6 +847,8 @@
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mci1_clk>;
+ clock-names = "mci_clk";
status = "disabled";
};
@@ -568,6 +871,8 @@
interrupts = <14 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
+ clocks = <&spi0_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -579,6 +884,8 @@
interrupts = <15 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
+ clocks = <&spi1_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -587,6 +894,8 @@
reg = <0xfffb8000 0x300>;
interrupts = <20 IRQ_TYPE_LEVEL_HIGH 4>;
#pwm-cells = <3>;
+ clocks = <&pwm_clk>;
+ clock-names = "pwm_clk";
status = "disabled";
};
};
@@ -622,6 +931,8 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00a00000 0x100000>;
interrupts = <29 IRQ_TYPE_LEVEL_HIGH 2>;
+ clocks = <&usb>, <&ohci_clk>, <&ohci_clk>, <&uhpck>;
+ clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index 15009c9f2293..5cf93eecd8f1 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -29,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <16367660>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <16367660>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index b8e79466014f..31f7652612fc 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -25,6 +25,30 @@
adc0: adc@fffe0000 {
atmel,adc-startup-time = <40>;
};
+
+ pmc: pmc@fffffc00 {
+ plla: pllack {
+ atmel,clk-input-range = <2000000 32000000>;
+ atmel,pll-clk-output-ranges = <745000000 800000000 0 0>,
+ <695000000 750000000 1 0>,
+ <645000000 700000000 2 0>,
+ <595000000 650000000 3 0>,
+ <545000000 600000000 0 1>,
+ <495000000 550000000 1 1>,
+ <445000000 500000000 2 1>,
+ <400000000 450000000 3 1>;
+ };
+
+ pllb: pllbck {
+ atmel,clk-input-range = <2000000 32000000>;
+ atmel,pll-clk-output-ranges = <30000000 100000000 0 0>;
+ };
+
+ mck: masterck {
+ atmel,clk-output-range = <0 133000000>;
+ atmel,clk-divisors = <1 2 4 6>;
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index cb2c010e08e2..d2919108e92d 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -26,6 +26,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index ace6bf197b70..932a669156af 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -14,6 +14,7 @@
#include <dt-bindings/pinctrl/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/at91.h>
/ {
model = "Atmel AT91SAM9G45 family SoC";
@@ -53,6 +54,26 @@
reg = <0x70000000 0x10000000>;
};
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ adc_op_clk: adc_op_clk{
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <300000>;
+ };
+ };
+
ahb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -77,11 +98,279 @@
compatible = "atmel,at91sam9g45-ddramc";
reg = <0xffffe400 0x200
0xffffe600 0x200>;
+ clocks = <&ddrck>;
+ clock-names = "ddrck";
};
pmc: pmc@fffffc00 {
- compatible = "atmel,at91rm9200-pmc";
+ compatible = "atmel,at91sam9g45-pmc";
reg = <0xfffffc00 0x100>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+ clocks = <&main_xtal>;
+ };
+
+ main: mainck {
+ compatible = "atmel,at91rm9200-clk-main";
+ #clock-cells = <0>;
+ clocks = <&main_osc>;
+ };
+
+ plla: pllack {
+ compatible = "atmel,at91rm9200-clk-pll";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKA>;
+ clocks = <&main>;
+ reg = <0>;
+ atmel,clk-input-range = <2000000 32000000>;
+ #atmel,pll-clk-output-range-cells = <4>;
+ atmel,pll-clk-output-ranges = <745000000 800000000 0 0
+ 695000000 750000000 1 0
+ 645000000 700000000 2 0
+ 595000000 650000000 3 0
+ 545000000 600000000 0 1
+ 495000000 555000000 1 1
+ 445000000 500000000 2 1
+ 400000000 450000000 3 1>;
+ };
+
+ plladiv: plladivck {
+ compatible = "atmel,at91sam9x5-clk-plldiv";
+ #clock-cells = <0>;
+ clocks = <&plla>;
+ };
+
+ utmi: utmick {
+ compatible = "atmel,at91sam9x5-clk-utmi";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_LOCKU>;
+ clocks = <&main>;
+ };
+
+ mck: masterck {
+ compatible = "atmel,at91rm9200-clk-master";
+ #clock-cells = <0>;
+ interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
+ clocks = <&slow_xtal>, <&main>, <&plladiv>, <&utmi>;
+ atmel,clk-output-range = <0 133333333>;
+ atmel,clk-divisors = <1 2 4 3>;
+ };
+
+ usb: usbck {
+ compatible = "atmel,at91sam9x5-clk-usb";
+ #clock-cells = <0>;
+ clocks = <&plladiv>, <&utmi>;
+ };
+
+ prog: progck {
+ compatible = "atmel,at91sam9g45-clk-programmable";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&pmc>;
+ clocks = <&slow_xtal>, <&main>, <&plladiv>, <&utmi>, <&mck>;
+
+ prog0: prog0 {
+ #clock-cells = <0>;
+ reg = <0>;
+ interrupts = <AT91_PMC_PCKRDY(0)>;
+ };
+
+ prog1: prog1 {
+ #clock-cells = <0>;
+ reg = <1>;
+ interrupts = <AT91_PMC_PCKRDY(1)>;
+ };
+ };
+
+ systemck {
+ compatible = "atmel,at91rm9200-clk-system";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ddrck: ddrck {
+ #clock-cells = <0>;
+ reg = <2>;
+ clocks = <&mck>;
+ };
+
+ uhpck: uhpck {
+ #clock-cells = <0>;
+ reg = <6>;
+ clocks = <&usb>;
+ };
+
+ pck0: pck0 {
+ #clock-cells = <0>;
+ reg = <8>;
+ clocks = <&prog0>;
+ };
+
+ pck1: pck1 {
+ #clock-cells = <0>;
+ reg = <9>;
+ clocks = <&prog1>;
+ };
+ };
+
+ periphck {
+ compatible = "atmel,at91rm9200-clk-peripheral";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&mck>;
+
+ pioA_clk: pioA_clk {
+ #clock-cells = <0>;
+ reg = <2>;
+ };
+
+ pioB_clk: pioB_clk {
+ #clock-cells = <0>;
+ reg = <3>;
+ };
+
+ pioC_clk: pioC_clk {
+ #clock-cells = <0>;
+ reg = <4>;
+ };
+
+ pioDE_clk: pioDE_clk {
+ #clock-cells = <0>;
+ reg = <5>;
+ };
+
+ trng_clk: trng_clk {
+ #clock-cells = <0>;
+ reg = <6>;
+ };
+
+ usart0_clk: usart0_clk {
+ #clock-cells = <0>;
+ reg = <7>;
+ };
+
+ usart1_clk: usart1_clk {
+ #clock-cells = <0>;
+ reg = <8>;
+ };
+
+ usart2_clk: usart2_clk {
+ #clock-cells = <0>;
+ reg = <9>;
+ };
+
+ usart3_clk: usart3_clk {
+ #clock-cells = <0>;
+ reg = <10>;
+ };
+
+ mci0_clk: mci0_clk {
+ #clock-cells = <0>;
+ reg = <11>;
+ };
+
+ twi0_clk: twi0_clk {
+ #clock-cells = <0>;
+ reg = <12>;
+ };
+
+ twi1_clk: twi1_clk {
+ #clock-cells = <0>;
+ reg = <13>;
+ };
+
+ spi0_clk: spi0_clk {
+ #clock-cells = <0>;
+ reg = <14>;
+ };
+
+ spi1_clk: spi1_clk {
+ #clock-cells = <0>;
+ reg = <15>;
+ };
+
+ ssc0_clk: ssc0_clk {
+ #clock-cells = <0>;
+ reg = <16>;
+ };
+
+ ssc1_clk: ssc1_clk {
+ #clock-cells = <0>;
+ reg = <17>;
+ };
+
+ tcb0_clk: tcb0_clk {
+ #clock-cells = <0>;
+ reg = <18>;
+ };
+
+ pwm_clk: pwm_clk {
+ #clock-cells = <0>;
+ reg = <19>;
+ };
+
+ adc_clk: adc_clk {
+ #clock-cells = <0>;
+ reg = <20>;
+ };
+
+ dma0_clk: dma0_clk {
+ #clock-cells = <0>;
+ reg = <21>;
+ };
+
+ uhphs_clk: uhphs_clk {
+ #clock-cells = <0>;
+ reg = <22>;
+ };
+
+ lcd_clk: lcd_clk {
+ #clock-cells = <0>;
+ reg = <23>;
+ };
+
+ ac97_clk: ac97_clk {
+ #clock-cells = <0>;
+ reg = <24>;
+ };
+
+ macb0_clk: macb0_clk {
+ #clock-cells = <0>;
+ reg = <25>;
+ };
+
+ isi_clk: isi_clk {
+ #clock-cells = <0>;
+ reg = <26>;
+ };
+
+ udphs_clk: udphs_clk {
+ #clock-cells = <0>;
+ reg = <27>;
+ };
+
+ aestdessha_clk: aestdessha_clk {
+ #clock-cells = <0>;
+ reg = <28>;
+ };
+
+ mci1_clk: mci1_clk {
+ #clock-cells = <0>;
+ reg = <29>;
+ };
+
+ vdec_clk: vdec_clk {
+ #clock-cells = <0>;
+ reg = <30>;
+ };
+ };
};
rstc@fffffd00 {
@@ -93,6 +382,7 @@
compatible = "atmel,at91sam9260-pit";
reg = <0xfffffd30 0xf>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&mck>;
};
@@ -105,12 +395,16 @@
compatible = "atmel,at91rm9200-tcb";
reg = <0xfff7c000 0x100>;
interrupts = <18 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tcb0_clk>, <&tcb0_clk>, <&tcb0_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
tcb1: timer@fffd4000 {
compatible = "atmel,at91rm9200-tcb";
reg = <0xfffd4000 0x100>;
interrupts = <18 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&tcb0_clk>, <&tcb0_clk>, <&tcb0_clk>;
+ clock-names = "t0_clk", "t1_clk", "t2_clk";
};
dma: dma-controller@ffffec00 {
@@ -118,6 +412,8 @@
reg = <0xffffec00 0x200>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH 0>;
#dma-cells = <2>;
+ clocks = <&dma0_clk>;
+ clock-names = "dma_clk";
};
pinctrl@fffff200 {
@@ -516,6 +812,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioA_clk>;
};
pioB: gpio@fffff400 {
@@ -526,6 +823,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioB_clk>;
};
pioC: gpio@fffff600 {
@@ -536,6 +834,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioC_clk>;
};
pioD: gpio@fffff800 {
@@ -546,6 +845,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioDE_clk>;
};
pioE: gpio@fffffa00 {
@@ -556,6 +856,7 @@
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pioDE_clk>;
};
};
@@ -565,6 +866,8 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_dbgu>;
+ clocks = <&mck>;
+ clock-names = "usart";
status = "disabled";
};
@@ -576,6 +879,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart0>;
+ clocks = <&usart0_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -587,6 +892,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart1>;
+ clocks = <&usart1_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -598,6 +905,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart2>;
+ clocks = <&usart2_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -609,6 +918,8 @@
atmel,use-dma-tx;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usart3>;
+ clocks = <&usart3_clk>;
+ clock-names = "usart";
status = "disabled";
};
@@ -618,6 +929,8 @@
interrupts = <25 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_macb_rmii>;
+ clocks = <&macb0_clk>, <&macb0_clk>;
+ clock-names = "hclk", "pclk";
status = "disabled";
};
@@ -629,6 +942,7 @@
pinctrl-0 = <&pinctrl_i2c0>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&twi0_clk>;
status = "disabled";
};
@@ -640,6 +954,7 @@
pinctrl-0 = <&pinctrl_i2c1>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&twi1_clk>;
status = "disabled";
};
@@ -649,6 +964,8 @@
interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ clocks = <&ssc0_clk>;
+ clock-names = "pclk";
status = "disabled";
};
@@ -658,6 +975,8 @@
interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+ clocks = <&ssc1_clk>;
+ clock-names = "pclk";
status = "disabled";
};
@@ -667,6 +986,8 @@
compatible = "atmel,at91sam9g45-adc";
reg = <0xfffb0000 0x100>;
interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&adc_clk>, <&adc_op_clk>;
+ clock-names = "adc_clk", "adc_op_clk";
atmel,adc-channels-used = <0xff>;
atmel,adc-vref = <3300>;
atmel,adc-startup-time = <40>;
@@ -706,6 +1027,7 @@
reg = <0xfffb8000 0x300>;
interrupts = <19 IRQ_TYPE_LEVEL_HIGH 4>;
#pwm-cells = <3>;
+ clocks = <&pwm_clk>;
status = "disabled";
};
@@ -718,6 +1040,8 @@
dma-names = "rxtx";
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mci0_clk>;
+ clock-names = "mci_clk";
status = "disabled";
};
@@ -730,6 +1054,8 @@
dma-names = "rxtx";
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mci1_clk>;
+ clock-names = "mci_clk";
status = "disabled";
};
@@ -752,6 +1078,8 @@
interrupts = <14 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
+ clocks = <&spi0_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -763,6 +1091,8 @@
interrupts = <15 4 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi1>;
+ clocks = <&spi1_clk>;
+ clock-names = "spi_clk";
status = "disabled";
};
@@ -773,6 +1103,8 @@
reg = <0x00600000 0x80000
0xfff78000 0x400>;
interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&udphs_clk>, <&utmi>;
+ clock-names = "pclk", "hclk";
status = "disabled";
ep0 {
@@ -835,6 +1167,8 @@
interrupts = <23 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fb>;
+ clocks = <&lcd_clk>, <&lcd_clk>;
+ clock-names = "hclk", "lcdc_clk";
status = "disabled";
};
@@ -861,6 +1195,9 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00700000 0x100000>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
+ //TODO
+ clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
+ clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
};
@@ -868,6 +1205,9 @@
compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
reg = <0x00800000 0x100000>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
+ //TODO
+ clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
+ clock-names = "usb_clk", "ehci_clk", "hclk", "uhpck";
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 9f5b0a674995..96ccc7de4f0a 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -31,6 +31,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index b84bac5bada4..2bfac310dbec 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -50,16 +50,18 @@
reg = <0x20000000 0x10000000>;
};
- slow_xtal: slow_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- main_xtal: main_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index 64bbe46e4f90..83d723711ae1 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -21,14 +21,6 @@
reg = <0x20000000 0x8000000>;
};
- slow_xtal {
- clock-frequency = <32768>;
- };
-
- main_xtal {
- clock-frequency = <16000000>;
- };
-
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -38,6 +30,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <16000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <16000000>;
+ };
};
ahb {
@@ -56,6 +56,8 @@
wm8904: codec@1a {
compatible = "wm8904";
reg = <0x1a>;
+ clocks = <&pck0>;
+ clock-names = "mclk";
};
qt1070: keyboard@1b {
diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi
index 1da183155eee..ab56c8b81dfa 100644
--- a/arch/arm/boot/dts/at91sam9rl.dtsi
+++ b/arch/arm/boot/dts/at91sam9rl.dtsi
@@ -50,19 +50,19 @@
reg = <0x20000000 0x04000000>;
};
- slow_xtal: slow_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- main_xtal: main_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- clocks {
adc_op_clk: adc_op_clk{
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -95,6 +95,7 @@
<0xffffe800 0x200>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ atmel,nand-has-dma;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioD 17 GPIO_ACTIVE_HIGH>,
@@ -348,6 +349,15 @@
};
};
+ dma0: dma-controller@ffffe600 {
+ compatible = "atmel,at91sam9rl-dma";
+ reg = <0xffffe600 0x200>;
+ interrupts = <21 IRQ_TYPE_LEVEL_HIGH 0>;
+ #dma-cells = <2>;
+ clocks = <&dma0_clk>;
+ clock-names = "dma_clk";
+ };
+
ramc0: ramc@ffffea00 {
compatible = "atmel,at91sam9260-sdramc";
reg = <0xffffea00 0x200>;
diff --git a/arch/arm/boot/dts/at91sam9rlek.dts b/arch/arm/boot/dts/at91sam9rlek.dts
index d4a010e40fe3..9be5b540eebf 100644
--- a/arch/arm/boot/dts/at91sam9rlek.dts
+++ b/arch/arm/boot/dts/at91sam9rlek.dts
@@ -20,15 +20,6 @@
reg = <0x20000000 0x4000000>;
};
-
- slow_xtal {
- clock-frequency = <32768>;
- };
-
- main_xtal {
- clock-frequency = <12000000>;
- };
-
clocks {
#address-cells = <1>;
#size-cells = <1>;
@@ -38,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 2c0d6ea3ab41..e1a5c70b885c 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -52,22 +52,24 @@
reg = <0x20000000 0x10000000>;
};
- slow_xtal: slow_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- main_xtal: main_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- adc_op_clk: adc_op_clk{
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <5000000>;
+ adc_op_clk: adc_op_clk{
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <5000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi
index 8413e21192eb..229d6c24a9c4 100644
--- a/arch/arm/boot/dts/at91sam9x5cm.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi
@@ -23,12 +23,14 @@
};
};
- slow_xtal {
- clock-frequency = <32768>;
- };
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
- main_xtal {
- clock-frequency = <12000000>;
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
index 6b05ae6d476f..2ddaa5136611 100644
--- a/arch/arm/boot/dts/bcm11351.dtsi
+++ b/arch/arm/boot/dts/bcm11351.dtsi
@@ -27,6 +27,25 @@
bootargs = "console=ttyS0,115200n8";
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "brcm,bcm11351-cpu-method";
+ secondary-boot-reg = <0x3500417c>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
gic: interrupt-controller@3ff00100 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
diff --git a/arch/arm/boot/dts/bcm21664.dtsi b/arch/arm/boot/dts/bcm21664.dtsi
index 8b366822bb43..2016b72a8fb7 100644
--- a/arch/arm/boot/dts/bcm21664.dtsi
+++ b/arch/arm/boot/dts/bcm21664.dtsi
@@ -27,6 +27,25 @@
bootargs = "console=ttyS0,115200n8";
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "brcm,bcm11351-cpu-method";
+ secondary-boot-reg = <0x35004178>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
gic: interrupt-controller@3ff00100 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
diff --git a/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts b/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts
new file mode 100644
index 000000000000..9eec2ac1112f
--- /dev/null
+++ b/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+#include "bcm7445.dtsi"
+
+/ {
+ model = "Broadcom STB (bcm7445), SVMB reference board";
+ compatible = "brcm,bcm7445", "brcm,brcmstb";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00 0x00000000 0x00 0x40000000>,
+ <0x00 0x40000000 0x00 0x40000000>,
+ <0x00 0x80000000 0x00 0x40000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/bcm7445.dtsi b/arch/arm/boot/dts/bcm7445.dtsi
new file mode 100644
index 000000000000..0ca0f4e523d0
--- /dev/null
+++ b/arch/arm/boot/dts/bcm7445.dtsi
@@ -0,0 +1,111 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "Broadcom STB (bcm7445)";
+ compatible = "brcm,bcm7445", "brcm,brcmstb";
+ interrupt-parent = <&gic>;
+
+ chosen {
+ bootargs = "console=ttyS0,115200 earlyprintk";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "brcm,brahma-b15";
+ device_type = "cpu";
+ enable-method = "brcm,brahma-b15";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "brcm,brahma-b15";
+ device_type = "cpu";
+ enable-method = "brcm,brahma-b15";
+ reg = <1>;
+ };
+
+ cpu@2 {
+ compatible = "brcm,brahma-b15";
+ device_type = "cpu";
+ enable-method = "brcm,brahma-b15";
+ reg = <2>;
+ };
+
+ cpu@3 {
+ compatible = "brcm,brahma-b15";
+ device_type = "cpu";
+ enable-method = "brcm,brahma-b15";
+ reg = <3>;
+ };
+ };
+
+ gic: interrupt-controller@ffd00000 {
+ compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic";
+ reg = <0x00 0xffd01000 0x00 0x1000>,
+ <0x00 0xffd02000 0x00 0x2000>,
+ <0x00 0xffd04000 0x00 0x2000>,
+ <0x00 0xffd06000 0x00 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_RAW(15) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ rdb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0 0x00 0xf0000000 0x1000000>;
+
+ serial@40ab00 {
+ compatible = "ns16550a";
+ reg = <0x40ab00 0x20>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0x4d3f640>;
+ };
+
+ sun_top_ctrl: syscon@404000 {
+ compatible = "brcm,bcm7445-sun-top-ctrl",
+ "syscon";
+ reg = <0x404000 0x51c>;
+ };
+
+ hif_cpubiuctrl: syscon@3e2400 {
+ compatible = "brcm,bcm7445-hif-cpubiuctrl",
+ "syscon";
+ reg = <0x3e2400 0x5b4>;
+ };
+
+ hif_continuation: syscon@452000 {
+ compatible = "brcm,bcm7445-hif-continuation",
+ "syscon";
+ reg = <0x452000 0x100>;
+ };
+ };
+
+ smpboot {
+ compatible = "brcm,brcmstb-smpboot";
+ syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+ syscon-cont = <&hif_continuation>;
+ };
+
+ reboot {
+ compatible = "brcm,brcmstb-reboot";
+ syscon = <&sun_top_ctrl 0x304 0x308>;
+ };
+};
diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
index 2477dac4d643..9d7c810ebd0b 100644
--- a/arch/arm/boot/dts/berlin2.dtsi
+++ b/arch/arm/boot/dts/berlin2.dtsi
@@ -22,6 +22,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "marvell,berlin-smp";
cpu@0 {
compatible = "marvell,pj4b";
@@ -78,6 +79,11 @@
clocks = <&chip CLKID_TWD>;
};
+ cpu-ctrl@dd0000 {
+ compatible = "marvell,berlin-cpu-ctrl";
+ reg = <0xdd0000 0x10000>;
+ };
+
apb@e80000 {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index 995150f93795..a357ce02a64e 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -34,6 +34,14 @@
status = "okay";
};
+&i2c0 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
&uart0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 635a16a64cb4..400c40fceccc 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -18,6 +18,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "marvell,berlin-smp";
cpu@0 {
compatible = "arm,cortex-a9";
@@ -90,6 +91,8 @@
compatible = "arm,pl310-cache";
reg = <0xac0000 0x1000>;
cache-level = <2>;
+ arm,data-latency = <2 2 2>;
+ arm,tag-latency = <2 2 2>;
};
scu: snoop-control-unit@ad0000 {
@@ -111,6 +114,11 @@
#interrupt-cells = <3>;
};
+ cpu-ctrl@dd0000 {
+ compatible = "marvell,berlin-cpu-ctrl";
+ reg = <0xdd0000 0x10000>;
+ };
+
apb@e80000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -191,6 +199,32 @@
};
};
+ i2c0: i2c@1400 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1400 0x100>;
+ interrupt-parent = <&aic>;
+ interrupts = <4>;
+ clocks = <&chip CLKID_CFG>;
+ pinctrl-0 = <&twsi0_pmux>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ i2c1: i2c@1800 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1800 0x100>;
+ interrupt-parent = <&aic>;
+ interrupts = <5>;
+ clocks = <&chip CLKID_CFG>;
+ pinctrl-0 = <&twsi1_pmux>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
timer0: timer@2c00 {
compatible = "snps,dw-apb-timer";
reg = <0x2c00 0x14>;
@@ -301,6 +335,16 @@
reg = <0xea0000 0x400>, <0xdd0170 0x10>;
clocks = <&refclk>;
clock-names = "refclk";
+
+ twsi0_pmux: twsi0-pmux {
+ groups = "G6";
+ function = "twsi0";
+ };
+
+ twsi1_pmux: twsi1-pmux {
+ groups = "G7";
+ function = "twsi1";
+ };
};
apb@fc0000 {
@@ -311,6 +355,32 @@
ranges = <0 0xfc0000 0x10000>;
interrupt-parent = <&sic>;
+ i2c2: i2c@7000 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7000 0x100>;
+ interrupt-parent = <&sic>;
+ interrupts = <6>;
+ clocks = <&refclk>;
+ pinctrl-0 = <&twsi2_pmux>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ i2c3: i2c@8000 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x8000 0x100>;
+ interrupt-parent = <&sic>;
+ interrupts = <7>;
+ clocks = <&refclk>;
+ pinctrl-0 = <&twsi3_pmux>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
uart0: uart@9000 {
compatible = "snps,dw-apb-uart";
reg = <0x9000 0x100>;
@@ -348,6 +418,16 @@
groups = "GSM14";
function = "uart1";
};
+
+ twsi2_pmux: twsi2-pmux {
+ groups = "GSM13";
+ function = "twsi2";
+ };
+
+ twsi3_pmux: twsi3-pmux {
+ groups = "GSM14";
+ function = "twsi3";
+ };
};
sic: interrupt-controller@e000 {
diff --git a/arch/arm/boot/dts/cros-ec-keyboard.dtsi b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
new file mode 100644
index 000000000000..9c7fb0acae79
--- /dev/null
+++ b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
@@ -0,0 +1,105 @@
+/*
+ * Keyboard dts fragment for devices that use cros-ec-keyboard
+ *
+ * Copyright (c) 2014 Google, 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 <dt-bindings/input/input.h>
+
+&cros_ec {
+ keyboard-controller {
+ compatible = "google,cros-ec-keyb";
+ keypad,num-rows = <8>;
+ keypad,num-columns = <13>;
+ google,needs-ghost-filter;
+
+ linux,keymap = <
+ MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
+ MATRIX_KEY(0x00, 0x02, KEY_F1)
+ MATRIX_KEY(0x00, 0x03, KEY_B)
+ MATRIX_KEY(0x00, 0x04, KEY_F10)
+ MATRIX_KEY(0x00, 0x06, KEY_N)
+ MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
+ MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
+
+ MATRIX_KEY(0x01, 0x01, KEY_ESC)
+ MATRIX_KEY(0x01, 0x02, KEY_F4)
+ MATRIX_KEY(0x01, 0x03, KEY_G)
+ MATRIX_KEY(0x01, 0x04, KEY_F7)
+ MATRIX_KEY(0x01, 0x06, KEY_H)
+ MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
+ MATRIX_KEY(0x01, 0x09, KEY_F9)
+ MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
+
+ MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
+ MATRIX_KEY(0x02, 0x01, KEY_TAB)
+ MATRIX_KEY(0x02, 0x02, KEY_F3)
+ MATRIX_KEY(0x02, 0x03, KEY_T)
+ MATRIX_KEY(0x02, 0x04, KEY_F6)
+ MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
+ MATRIX_KEY(0x02, 0x06, KEY_Y)
+ MATRIX_KEY(0x02, 0x07, KEY_102ND)
+ MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
+ MATRIX_KEY(0x02, 0x09, KEY_F8)
+
+ MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
+ MATRIX_KEY(0x03, 0x02, KEY_F2)
+ MATRIX_KEY(0x03, 0x03, KEY_5)
+ MATRIX_KEY(0x03, 0x04, KEY_F5)
+ MATRIX_KEY(0x03, 0x06, KEY_6)
+ MATRIX_KEY(0x03, 0x08, KEY_MINUS)
+ MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
+
+ MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
+ MATRIX_KEY(0x04, 0x01, KEY_A)
+ MATRIX_KEY(0x04, 0x02, KEY_D)
+ MATRIX_KEY(0x04, 0x03, KEY_F)
+ MATRIX_KEY(0x04, 0x04, KEY_S)
+ MATRIX_KEY(0x04, 0x05, KEY_K)
+ MATRIX_KEY(0x04, 0x06, KEY_J)
+ MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
+ MATRIX_KEY(0x04, 0x09, KEY_L)
+ MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
+ MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
+
+ MATRIX_KEY(0x05, 0x01, KEY_Z)
+ MATRIX_KEY(0x05, 0x02, KEY_C)
+ MATRIX_KEY(0x05, 0x03, KEY_V)
+ MATRIX_KEY(0x05, 0x04, KEY_X)
+ MATRIX_KEY(0x05, 0x05, KEY_COMMA)
+ MATRIX_KEY(0x05, 0x06, KEY_M)
+ MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
+ MATRIX_KEY(0x05, 0x08, KEY_SLASH)
+ MATRIX_KEY(0x05, 0x09, KEY_DOT)
+ MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
+
+ MATRIX_KEY(0x06, 0x01, KEY_1)
+ MATRIX_KEY(0x06, 0x02, KEY_3)
+ MATRIX_KEY(0x06, 0x03, KEY_4)
+ MATRIX_KEY(0x06, 0x04, KEY_2)
+ MATRIX_KEY(0x06, 0x05, KEY_8)
+ MATRIX_KEY(0x06, 0x06, KEY_7)
+ MATRIX_KEY(0x06, 0x08, KEY_0)
+ MATRIX_KEY(0x06, 0x09, KEY_9)
+ MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
+ MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
+ MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
+
+ MATRIX_KEY(0x07, 0x01, KEY_Q)
+ MATRIX_KEY(0x07, 0x02, KEY_E)
+ MATRIX_KEY(0x07, 0x03, KEY_R)
+ MATRIX_KEY(0x07, 0x04, KEY_W)
+ MATRIX_KEY(0x07, 0x05, KEY_I)
+ MATRIX_KEY(0x07, 0x06, KEY_U)
+ MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
+ MATRIX_KEY(0x07, 0x08, KEY_P)
+ MATRIX_KEY(0x07, 0x09, KEY_O)
+ MATRIX_KEY(0x07, 0x0b, KEY_UP)
+ MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/dove-cubox-es.dts b/arch/arm/boot/dts/dove-cubox-es.dts
new file mode 100644
index 000000000000..e28ef056dd17
--- /dev/null
+++ b/arch/arm/boot/dts/dove-cubox-es.dts
@@ -0,0 +1,12 @@
+#include "dove-cubox.dts"
+
+/ {
+ model = "SolidRun CuBox (Engineering Sample)";
+ compatible = "solidrun,cubox-es", "solidrun,cubox", "marvell,dove";
+};
+
+&sdio0 {
+ /* sdio0 card detect is connected to wrong pin on CuBox ES */
+ cd-gpios = <&gpio0 12 1>;
+ pinctrl-0 = <&pmx_sdio0 &pmx_gpio_12>;
+};
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 7a70f4ca502a..aae7efc09b0b 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -111,9 +111,6 @@
&sdio0 {
status = "okay";
- /* sdio0 card detect is connected to wrong pin on CuBox */
- cd-gpios = <&gpio0 12 1>;
- pinctrl-0 = <&pmx_sdio0 &pmx_gpio_12>;
};
&spi0 {
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 3b891dd20993..a5441d5482a6 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -630,6 +630,20 @@
reg = <0xe8400 0x0c>;
ngpios = <8>;
};
+
+ lcd1: lcd-controller@810000 {
+ compatible = "marvell,dove-lcd";
+ reg = <0x810000 0x1000>;
+ interrupts = <46>;
+ status = "disabled";
+ };
+
+ lcd0: lcd-controller@820000 {
+ compatible = "marvell,dove-lcd";
+ reg = <0x820000 0x1000>;
+ interrupts = <47>;
+ status = "disabled";
+ };
};
};
};
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 83089540e324..50f8022905a1 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -496,3 +496,11 @@
};
};
};
+
+&usb2_phy1 {
+ phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+ phy-supply = <&ldousb_reg>;
+};
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 80127638b379..97f603c4483d 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -12,6 +12,9 @@
#include "skeleton.dtsi"
+#define MAX_SOURCES 400
+#define DIRECT_IRQ(irq) (MAX_SOURCES + irq)
+
/ {
#address-cells = <1>;
#size-cells = <1>;
@@ -45,6 +48,7 @@
compatible = "arm,cortex-a15-gic";
interrupt-controller;
#interrupt-cells = <3>;
+ arm,routable-irqs = <192>;
reg = <0x48211000 0x1000>,
<0x48212000 0x1000>,
<0x48214000 0x2000>,
@@ -79,8 +83,8 @@
ti,hwmods = "l3_main_1", "l3_main_2";
reg = <0x44000000 0x1000000>,
<0x45000000 0x1000>;
- interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
prm: prm@4ae06000 {
compatible = "ti,dra7-prm";
@@ -95,6 +99,75 @@
};
};
+ axi@0 {
+ compatible = "simple-bus";
+ #size-cells = <1>;
+ #address-cells = <1>;
+ ranges = <0x51000000 0x51000000 0x3000
+ 0x0 0x20000000 0x10000000>;
+ pcie@51000000 {
+ compatible = "ti,dra7-pcie";
+ reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
+ reg-names = "rc_dbics", "ti_conf", "config";
+ interrupts = <0 232 0x4>, <0 233 0x4>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x81000000 0 0 0x03000 0 0x00010000
+ 0x82000000 0 0x20013000 0x13000 0 0xffed000>;
+ #interrupt-cells = <1>;
+ num-lanes = <1>;
+ ti,hwmods = "pcie1";
+ phys = <&pcie1_phy>;
+ phy-names = "pcie-phy0";
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie1_intc 1>,
+ <0 0 0 2 &pcie1_intc 2>,
+ <0 0 0 3 &pcie1_intc 3>,
+ <0 0 0 4 &pcie1_intc 4>;
+ pcie1_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ axi@1 {
+ compatible = "simple-bus";
+ #size-cells = <1>;
+ #address-cells = <1>;
+ ranges = <0x51800000 0x51800000 0x3000
+ 0x0 0x30000000 0x10000000>;
+ status = "disabled";
+ pcie@51000000 {
+ compatible = "ti,dra7-pcie";
+ reg = <0x51800000 0x2000>, <0x51802000 0x14c>, <0x1000 0x2000>;
+ reg-names = "rc_dbics", "ti_conf", "config";
+ interrupts = <0 355 0x4>, <0 356 0x4>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x81000000 0 0 0x03000 0 0x00010000
+ 0x82000000 0 0x30013000 0x13000 0 0xffed000>;
+ #interrupt-cells = <1>;
+ num-lanes = <1>;
+ ti,hwmods = "pcie2";
+ phys = <&pcie2_phy>;
+ phy-names = "pcie-phy0";
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie2_intc 1>,
+ <0 0 0 2 &pcie2_intc 2>,
+ <0 0 0 3 &pcie2_intc 3>,
+ <0 0 0 4 &pcie2_intc 4>;
+ pcie2_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
cm_core_aon: cm_core_aon@4a005000 {
compatible = "ti,dra7-cm-core-aon";
reg = <0x4a005000 0x2000>;
@@ -155,10 +228,10 @@
sdma: dma-controller@4a056000 {
compatible = "ti,omap4430-sdma";
reg = <0x4a056000 0x1000>;
- interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <1>;
#dma-channels = <32>;
#dma-requests = <127>;
@@ -167,7 +240,7 @@
gpio1: gpio@4ae10000 {
compatible = "ti,omap4-gpio";
reg = <0x4ae10000 0x200>;
- interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio1";
gpio-controller;
#gpio-cells = <2>;
@@ -178,7 +251,7 @@
gpio2: gpio@48055000 {
compatible = "ti,omap4-gpio";
reg = <0x48055000 0x200>;
- interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio2";
gpio-controller;
#gpio-cells = <2>;
@@ -189,7 +262,7 @@
gpio3: gpio@48057000 {
compatible = "ti,omap4-gpio";
reg = <0x48057000 0x200>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio3";
gpio-controller;
#gpio-cells = <2>;
@@ -200,7 +273,7 @@
gpio4: gpio@48059000 {
compatible = "ti,omap4-gpio";
reg = <0x48059000 0x200>;
- interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio4";
gpio-controller;
#gpio-cells = <2>;
@@ -211,7 +284,7 @@
gpio5: gpio@4805b000 {
compatible = "ti,omap4-gpio";
reg = <0x4805b000 0x200>;
- interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio5";
gpio-controller;
#gpio-cells = <2>;
@@ -222,7 +295,7 @@
gpio6: gpio@4805d000 {
compatible = "ti,omap4-gpio";
reg = <0x4805d000 0x200>;
- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio6";
gpio-controller;
#gpio-cells = <2>;
@@ -233,7 +306,7 @@
gpio7: gpio@48051000 {
compatible = "ti,omap4-gpio";
reg = <0x48051000 0x200>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio7";
gpio-controller;
#gpio-cells = <2>;
@@ -244,7 +317,7 @@
gpio8: gpio@48053000 {
compatible = "ti,omap4-gpio";
reg = <0x48053000 0x200>;
- interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "gpio8";
gpio-controller;
#gpio-cells = <2>;
@@ -255,7 +328,7 @@
uart1: serial@4806a000 {
compatible = "ti,omap4-uart";
reg = <0x4806a000 0x100>;
- interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
clock-frequency = <48000000>;
status = "disabled";
@@ -264,7 +337,7 @@
uart2: serial@4806c000 {
compatible = "ti,omap4-uart";
reg = <0x4806c000 0x100>;
- interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart2";
clock-frequency = <48000000>;
status = "disabled";
@@ -273,7 +346,7 @@
uart3: serial@48020000 {
compatible = "ti,omap4-uart";
reg = <0x48020000 0x100>;
- interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart3";
clock-frequency = <48000000>;
status = "disabled";
@@ -282,7 +355,7 @@
uart4: serial@4806e000 {
compatible = "ti,omap4-uart";
reg = <0x4806e000 0x100>;
- interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart4";
clock-frequency = <48000000>;
status = "disabled";
@@ -291,7 +364,7 @@
uart5: serial@48066000 {
compatible = "ti,omap4-uart";
reg = <0x48066000 0x100>;
- interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart5";
clock-frequency = <48000000>;
status = "disabled";
@@ -300,7 +373,7 @@
uart6: serial@48068000 {
compatible = "ti,omap4-uart";
reg = <0x48068000 0x100>;
- interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart6";
clock-frequency = <48000000>;
status = "disabled";
@@ -309,6 +382,7 @@
uart7: serial@48420000 {
compatible = "ti,omap4-uart";
reg = <0x48420000 0x100>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart7";
clock-frequency = <48000000>;
status = "disabled";
@@ -317,6 +391,7 @@
uart8: serial@48422000 {
compatible = "ti,omap4-uart";
reg = <0x48422000 0x100>;
+ interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart8";
clock-frequency = <48000000>;
status = "disabled";
@@ -325,6 +400,7 @@
uart9: serial@48424000 {
compatible = "ti,omap4-uart";
reg = <0x48424000 0x100>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart9";
clock-frequency = <48000000>;
status = "disabled";
@@ -333,15 +409,133 @@
uart10: serial@4ae2b000 {
compatible = "ti,omap4-uart";
reg = <0x4ae2b000 0x100>;
+ interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart10";
clock-frequency = <48000000>;
status = "disabled";
};
+ mailbox1: mailbox@4a0f4000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4a0f4000 0x200>;
+ ti,hwmods = "mailbox1";
+ ti,mbox-num-users = <3>;
+ ti,mbox-num-fifos = <8>;
+ status = "disabled";
+ };
+
+ mailbox2: mailbox@4883a000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4883a000 0x200>;
+ ti,hwmods = "mailbox2";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox3: mailbox@4883c000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4883c000 0x200>;
+ ti,hwmods = "mailbox3";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox4: mailbox@4883e000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4883e000 0x200>;
+ ti,hwmods = "mailbox4";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox5: mailbox@48840000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48840000 0x200>;
+ ti,hwmods = "mailbox5";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox6: mailbox@48842000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48842000 0x200>;
+ ti,hwmods = "mailbox6";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox7: mailbox@48844000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48844000 0x200>;
+ ti,hwmods = "mailbox7";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox8: mailbox@48846000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48846000 0x200>;
+ ti,hwmods = "mailbox8";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox9: mailbox@4885e000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4885e000 0x200>;
+ ti,hwmods = "mailbox9";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox10: mailbox@48860000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48860000 0x200>;
+ ti,hwmods = "mailbox10";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox11: mailbox@48862000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48862000 0x200>;
+ ti,hwmods = "mailbox11";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox12: mailbox@48864000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48864000 0x200>;
+ ti,hwmods = "mailbox12";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
+ mailbox13: mailbox@48802000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x48802000 0x200>;
+ ti,hwmods = "mailbox13";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <12>;
+ status = "disabled";
+ };
+
timer1: timer@4ae18000 {
compatible = "ti,omap5430-timer";
reg = <0x4ae18000 0x80>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer1";
ti,timer-alwon;
};
@@ -349,28 +543,28 @@
timer2: timer@48032000 {
compatible = "ti,omap5430-timer";
reg = <0x48032000 0x80>;
- interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer2";
};
timer3: timer@48034000 {
compatible = "ti,omap5430-timer";
reg = <0x48034000 0x80>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer3";
};
timer4: timer@48036000 {
compatible = "ti,omap5430-timer";
reg = <0x48036000 0x80>;
- interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer4";
};
timer5: timer@48820000 {
compatible = "ti,omap5430-timer";
reg = <0x48820000 0x80>;
- interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer5";
ti,timer-dsp;
};
@@ -378,7 +572,7 @@
timer6: timer@48822000 {
compatible = "ti,omap5430-timer";
reg = <0x48822000 0x80>;
- interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer6";
ti,timer-dsp;
ti,timer-pwm;
@@ -387,7 +581,7 @@
timer7: timer@48824000 {
compatible = "ti,omap5430-timer";
reg = <0x48824000 0x80>;
- interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer7";
ti,timer-dsp;
};
@@ -395,7 +589,7 @@
timer8: timer@48826000 {
compatible = "ti,omap5430-timer";
reg = <0x48826000 0x80>;
- interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer8";
ti,timer-dsp;
ti,timer-pwm;
@@ -404,21 +598,21 @@
timer9: timer@4803e000 {
compatible = "ti,omap5430-timer";
reg = <0x4803e000 0x80>;
- interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer9";
};
timer10: timer@48086000 {
compatible = "ti,omap5430-timer";
reg = <0x48086000 0x80>;
- interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer10";
};
timer11: timer@48088000 {
compatible = "ti,omap5430-timer";
reg = <0x48088000 0x80>;
- interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer11";
ti,timer-pwm;
};
@@ -426,6 +620,7 @@
timer13: timer@48828000 {
compatible = "ti,omap5430-timer";
reg = <0x48828000 0x80>;
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer13";
status = "disabled";
};
@@ -433,6 +628,7 @@
timer14: timer@4882a000 {
compatible = "ti,omap5430-timer";
reg = <0x4882a000 0x80>;
+ interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer14";
status = "disabled";
};
@@ -440,6 +636,7 @@
timer15: timer@4882c000 {
compatible = "ti,omap5430-timer";
reg = <0x4882c000 0x80>;
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer15";
status = "disabled";
};
@@ -447,6 +644,7 @@
timer16: timer@4882e000 {
compatible = "ti,omap5430-timer";
reg = <0x4882e000 0x80>;
+ interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "timer16";
status = "disabled";
};
@@ -454,7 +652,7 @@
wdt2: wdt@4ae14000 {
compatible = "ti,omap4-wdt";
reg = <0x4ae14000 0x80>;
- interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "wd_timer2";
};
@@ -468,14 +666,14 @@
dmm@4e000000 {
compatible = "ti,omap5-dmm";
reg = <0x4e000000 0x800>;
- interrupts = <0 113 0x4>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "dmm";
};
i2c1: i2c@48070000 {
compatible = "ti,omap4-i2c";
reg = <0x48070000 0x100>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "i2c1";
@@ -485,7 +683,7 @@
i2c2: i2c@48072000 {
compatible = "ti,omap4-i2c";
reg = <0x48072000 0x100>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "i2c2";
@@ -495,7 +693,7 @@
i2c3: i2c@48060000 {
compatible = "ti,omap4-i2c";
reg = <0x48060000 0x100>;
- interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "i2c3";
@@ -505,7 +703,7 @@
i2c4: i2c@4807a000 {
compatible = "ti,omap4-i2c";
reg = <0x4807a000 0x100>;
- interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "i2c4";
@@ -515,7 +713,7 @@
i2c5: i2c@4807c000 {
compatible = "ti,omap4-i2c";
reg = <0x4807c000 0x100>;
- interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "i2c5";
@@ -525,7 +723,7 @@
mmc1: mmc@4809c000 {
compatible = "ti,omap4-hsmmc";
reg = <0x4809c000 0x400>;
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc1";
ti,dual-volt;
ti,needs-special-reset;
@@ -538,7 +736,7 @@
mmc2: mmc@480b4000 {
compatible = "ti,omap4-hsmmc";
reg = <0x480b4000 0x400>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc2";
ti,needs-special-reset;
dmas = <&sdma 47>, <&sdma 48>;
@@ -549,7 +747,7 @@
mmc3: mmc@480ad000 {
compatible = "ti,omap4-hsmmc";
reg = <0x480ad000 0x400>;
- interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc3";
ti,needs-special-reset;
dmas = <&sdma 77>, <&sdma 78>;
@@ -560,7 +758,7 @@
mmc4: mmc@480d1000 {
compatible = "ti,omap4-hsmmc";
reg = <0x480d1000 0x400>;
- interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc4";
ti,needs-special-reset;
dmas = <&sdma 57>, <&sdma 58>;
@@ -703,7 +901,7 @@
mcspi1: spi@48098000 {
compatible = "ti,omap4-mcspi";
reg = <0x48098000 0x200>;
- interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "mcspi1";
@@ -724,7 +922,7 @@
mcspi2: spi@4809a000 {
compatible = "ti,omap4-mcspi";
reg = <0x4809a000 0x200>;
- interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "mcspi2";
@@ -740,7 +938,7 @@
mcspi3: spi@480b8000 {
compatible = "ti,omap4-mcspi";
reg = <0x480b8000 0x200>;
- interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "mcspi3";
@@ -753,7 +951,7 @@
mcspi4: spi@480ba000 {
compatible = "ti,omap4-mcspi";
reg = <0x480ba000 0x200>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "mcspi4";
@@ -773,6 +971,7 @@
clocks = <&qspi_gfclk_div>;
clock-names = "fck";
num-cs = <4>;
+ interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -803,18 +1002,76 @@
clock-names = "sysclk";
#phy-cells = <0>;
};
+
+ pcie1_phy: pciephy@4a094000 {
+ compatible = "ti,phy-pipe3-pcie";
+ reg = <0x4a094000 0x80>, /* phy_rx */
+ <0x4a094400 0x64>; /* phy_tx */
+ reg-names = "phy_rx", "phy_tx";
+ ctrl-module = <&omap_control_pcie1phy>;
+ clocks = <&dpll_pcie_ref_ck>,
+ <&dpll_pcie_ref_m2ldo_ck>,
+ <&optfclk_pciephy1_32khz>,
+ <&optfclk_pciephy1_clk>,
+ <&optfclk_pciephy1_div_clk>,
+ <&optfclk_pciephy_div>;
+ clock-names = "dpll_ref", "dpll_ref_m2",
+ "wkupclk", "refclk",
+ "div-clk", "phy-div";
+ #phy-cells = <0>;
+ id = <1>;
+ ti,hwmods = "pcie1-phy";
+ };
+
+ pcie2_phy: pciephy@4a095000 {
+ compatible = "ti,phy-pipe3-pcie";
+ reg = <0x4a095000 0x80>, /* phy_rx */
+ <0x4a095400 0x64>; /* phy_tx */
+ reg-names = "phy_rx", "phy_tx";
+ ctrl-module = <&omap_control_pcie2phy>;
+ clocks = <&dpll_pcie_ref_ck>,
+ <&dpll_pcie_ref_m2ldo_ck>,
+ <&optfclk_pciephy2_32khz>,
+ <&optfclk_pciephy2_clk>,
+ <&optfclk_pciephy2_div_clk>,
+ <&optfclk_pciephy_div>;
+ clock-names = "dpll_ref", "dpll_ref_m2",
+ "wkupclk", "refclk",
+ "div-clk", "phy-div";
+ #phy-cells = <0>;
+ ti,hwmods = "pcie2-phy";
+ id = <2>;
+ status = "disabled";
+ };
};
sata: sata@4a141100 {
compatible = "snps,dwc-ahci";
reg = <0x4a140000 0x1100>, <0x4a141100 0x7>;
- interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
phys = <&sata_phy>;
phy-names = "sata-phy";
clocks = <&sata_ref_clk>;
ti,hwmods = "sata";
};
+ omap_control_pcie1phy: control-phy@0x4a003c40 {
+ compatible = "ti,control-phy-pcie";
+ reg = <0x4a003c40 0x4>, <0x4a003c14 0x4>, <0x4a003c34 0x4>;
+ reg-names = "power", "control_sma", "pcie_pcs";
+ clocks = <&sys_clkin1>;
+ clock-names = "sysclk";
+ };
+
+ omap_control_pcie2phy: control-pcie@0x4a003c44 {
+ compatible = "ti,control-phy-pcie";
+ reg = <0x4a003c44 0x4>, <0x4a003c14 0x4>, <0x4a003c34 0x4>;
+ reg-names = "power", "control_sma", "pcie_pcs";
+ clocks = <&sys_clkin1>;
+ clock-names = "sysclk";
+ status = "disabled";
+ };
+
omap_control_usb2phy1: control-phy@4a002300 {
compatible = "ti,control-phy-usb2";
reg = <0x4a002300 0x4>;
@@ -885,7 +1142,7 @@
compatible = "ti,dwc3";
ti,hwmods = "usb_otg_ss1";
reg = <0x48880000 0x10000>;
- interrupts = <0 77 4>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
utmi-mode = <2>;
@@ -893,7 +1150,7 @@
usb1: usb@48890000 {
compatible = "snps,dwc3";
reg = <0x48890000 0x17000>;
- interrupts = <0 76 4>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb2_phy1>, <&usb3_phy1>;
phy-names = "usb2-phy", "usb3-phy";
tx-fifo-resize;
@@ -906,7 +1163,7 @@
compatible = "ti,dwc3";
ti,hwmods = "usb_otg_ss2";
reg = <0x488c0000 0x10000>;
- interrupts = <0 92 4>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
utmi-mode = <2>;
@@ -914,7 +1171,7 @@
usb2: usb@488d0000 {
compatible = "snps,dwc3";
reg = <0x488d0000 0x17000>;
- interrupts = <0 78 4>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb2_phy2>;
phy-names = "usb2-phy";
tx-fifo-resize;
@@ -928,7 +1185,7 @@
compatible = "ti,dwc3";
ti,hwmods = "usb_otg_ss3";
reg = <0x48900000 0x10000>;
- /* interrupts = <0 TBD 4>; */
+ interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
utmi-mode = <2>;
@@ -937,7 +1194,7 @@
usb3: usb@48910000 {
compatible = "snps,dwc3";
reg = <0x48910000 0x17000>;
- /* interrupts = <0 93 4>; */
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
tx-fifo-resize;
maximum-speed = "high-speed";
dr_mode = "otg";
@@ -948,7 +1205,7 @@
compatible = "ti,dwc3";
ti,hwmods = "usb_otg_ss4";
reg = <0x48940000 0x10000>;
- /* interrupts = <0 TBD 4>; */
+ interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
utmi-mode = <2>;
@@ -957,7 +1214,7 @@
usb4: usb@48950000 {
compatible = "snps,dwc3";
reg = <0x48950000 0x17000>;
- /* interrupts = <0 TBD 4>; */
+ interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>;
tx-fifo-resize;
maximum-speed = "high-speed";
dr_mode = "otg";
@@ -967,7 +1224,7 @@
elm: elm@48078000 {
compatible = "ti,am3352-elm";
reg = <0x48078000 0xfc0>; /* device IO registers */
- interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "elm";
status = "disabled";
};
@@ -976,7 +1233,7 @@
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
reg = <0x50000000 0x37c>; /* device IO registers */
- interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
gpmc,num-cs = <8>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
@@ -994,6 +1251,17 @@
clock-names = "fck";
status = "disabled";
};
+
+ crossbar_mpu: crossbar@4a020000 {
+ compatible = "ti,irq-crossbar";
+ reg = <0x4a002a48 0x130>;
+ ti,max-irqs = <160>;
+ ti,max-crossbar-sources = <MAX_SOURCES>;
+ ti,reg-size = <2>;
+ ti,irqs-reserved = <0 1 2 3 5 6 131 132>;
+ ti,irqs-skip = <10 133 139 140>;
+ ti,irqs-safe-map = <0>;
+ };
};
};
diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index dc7a292fe939..2c05b3f017fa 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -1154,7 +1154,7 @@
apll_pcie_in_clk_mux: apll_pcie_in_clk_mux@4ae06118 {
compatible = "ti,mux-clock";
- clocks = <&dpll_pcie_ref_ck>, <&pciesref_acs_clk_ck>;
+ clocks = <&dpll_pcie_ref_m2ldo_ck>, <&pciesref_acs_clk_ck>;
#clock-cells = <0>;
reg = <0x021c 0x4>;
ti,bit-shift = <7>;
@@ -1167,16 +1167,33 @@
reg = <0x021c>, <0x0220>;
};
+ optfclk_pciephy1_32khz: optfclk_pciephy1_32khz@4a0093b0 {
+ compatible = "ti,gate-clock";
+ clocks = <&sys_32k_ck>;
+ #clock-cells = <0>;
+ reg = <0x13b0>;
+ ti,bit-shift = <8>;
+ };
+
+ optfclk_pciephy2_32khz: optfclk_pciephy2_32khz@4a0093b8 {
+ compatible = "ti,gate-clock";
+ clocks = <&sys_32k_ck>;
+ #clock-cells = <0>;
+ reg = <0x13b8>;
+ ti,bit-shift = <8>;
+ };
+
optfclk_pciephy_div: optfclk_pciephy_div@4a00821c {
compatible = "ti,divider-clock";
clocks = <&apll_pcie_ck>;
#clock-cells = <0>;
reg = <0x021c>;
+ ti,dividers = <2>, <1>;
ti,bit-shift = <8>;
ti,max-div = <2>;
};
- optfclk_pciephy_clk: optfclk_pciephy_clk@4a0093b0 {
+ optfclk_pciephy1_clk: optfclk_pciephy1_clk@4a0093b0 {
compatible = "ti,gate-clock";
clocks = <&apll_pcie_ck>;
#clock-cells = <0>;
@@ -1184,7 +1201,15 @@
ti,bit-shift = <9>;
};
- optfclk_pciephy_div_clk: optfclk_pciephy_div_clk@4a0093b0 {
+ optfclk_pciephy2_clk: optfclk_pciephy2_clk@4a0093b8 {
+ compatible = "ti,gate-clock";
+ clocks = <&apll_pcie_ck>;
+ #clock-cells = <0>;
+ reg = <0x13b8>;
+ ti,bit-shift = <9>;
+ };
+
+ optfclk_pciephy1_div_clk: optfclk_pciephy1_div_clk@4a0093b0 {
compatible = "ti,gate-clock";
clocks = <&optfclk_pciephy_div>;
#clock-cells = <0>;
@@ -1192,6 +1217,14 @@
ti,bit-shift = <10>;
};
+ optfclk_pciephy2_div_clk: optfclk_pciephy2_div_clk@4a0093b8 {
+ compatible = "ti,gate-clock";
+ clocks = <&optfclk_pciephy_div>;
+ #clock-cells = <0>;
+ reg = <0x13b8>;
+ ti,bit-shift = <10>;
+ };
+
apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
#clock-cells = <0>;
compatible = "fixed-factor-clock";
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
index e37985fa10e2..00eeed3721b6 100644
--- a/arch/arm/boot/dts/emev2.dtsi
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -31,11 +31,13 @@
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
+ clock-frequency = <533000000>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
+ clock-frequency = <533000000>;
};
};
diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
index 143b6d25bc80..8f941c2db7c6 100644
--- a/arch/arm/boot/dts/ethernut5.dts
+++ b/arch/arm/boot/dts/ethernut5.dts
@@ -20,6 +20,16 @@
reg = <0x20000000 0x08000000>;
};
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
+ };
+
ahb {
apb {
dbgu: serial@fffff200 {
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index 4d829685fdfb..f72969efe6d7 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -15,6 +15,12 @@
model = "Telit EVK-PRO3 for Telit GE863-PRO3";
compatible = "telit,evk-pro3", "atmel,at91sam9260", "atmel,at91sam9";
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+ };
+
ahb {
apb {
macb0: ethernet@fffc4000 {
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 3e678fa335bf..1d52de6370d5 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -39,6 +39,8 @@
i2c5 = &i2c_5;
i2c6 = &i2c_6;
i2c7 = &i2c_7;
+ serial0 = &serial_0;
+ serial1 = &serial_1;
};
cpus {
@@ -168,6 +170,15 @@
status = "disabled";
};
+ tmu: tmu@100C0000 {
+ compatible = "samsung,exynos3250-tmu";
+ reg = <0x100C0000 0x100>;
+ interrupts = <0 216 0>;
+ clocks = <&cmu CLK_TMU_APBIF>;
+ clock-names = "tmu_apbif";
+ status = "disabled";
+ };
+
gic: interrupt-controller@10481000 {
compatible = "arm,cortex-a15-gic";
#interrupt-cells = <3>;
@@ -195,7 +206,6 @@
wakeup-interrupt-controller {
compatible = "samsung,exynos4210-wakeup-eint";
- interrupt-parent = <&gic>;
interrupts = <0 48 0>;
};
};
@@ -234,7 +244,6 @@
compatible = "arm,amba-bus";
#address-cells = <1>;
#size-cells = <1>;
- interrupt-parent = <&gic>;
ranges;
pdma0: pdma@12680000 {
@@ -261,10 +270,11 @@
};
adc: adc@126C0000 {
- compatible = "samsung,exynos-adc-v3";
+ compatible = "samsung,exynos3250-adc",
+ "samsung,exynos-adc-v2";
reg = <0x126C0000 0x100>, <0x10020718 0x4>;
interrupts = <0 137 0>;
- clock-names = "adc", "sclk_tsadc";
+ clock-names = "adc", "sclk";
clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
#io-channel-cells = <1>;
io-channel-ranges;
@@ -277,6 +287,8 @@
interrupts = <0 109 0>;
clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_data &uart0_fctl>;
status = "disabled";
};
@@ -286,6 +298,8 @@
interrupts = <0 110 0>;
clocks = <&cmu CLK_UART1>, <&cmu CLK_SCLK_UART1>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_data>;
status = "disabled";
};
@@ -425,6 +439,19 @@
status = "disabled";
};
+ i2s2: i2s@13970000 {
+ compatible = "samsung,s3c6410-i2s";
+ reg = <0x13970000 0x100>;
+ interrupts = <0 126 0>;
+ clocks = <&cmu CLK_I2S>, <&cmu CLK_SCLK_I2S>;
+ clock-names = "iis", "i2s_opclk0";
+ dmas = <&pdma0 14>, <&pdma0 13>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&i2s2_bus>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
pwm: pwm@139D0000 {
compatible = "samsung,exynos4210-pwm";
reg = <0x139D0000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 17b22e9cc2aa..e0278ecbc816 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -44,6 +44,10 @@
fimc1 = &fimc_1;
fimc2 = &fimc_2;
fimc3 = &fimc_3;
+ serial0 = &serial_0;
+ serial1 = &serial_1;
+ serial2 = &serial_2;
+ serial3 = &serial_3;
};
clock_audss: clock-controller@03810000 {
@@ -123,6 +127,12 @@
reg = <0x10440000 0x1000>;
};
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupt-parent = <&combiner>;
+ interrupts = <2 2>, <3 2>;
+ };
+
sys_reg: syscon@10010000 {
compatible = "samsung,exynos4-sysreg", "syscon";
reg = <0x10010000 0x400>;
@@ -322,6 +332,23 @@
clocks = <&clock CLK_USB_HOST>;
clock-names = "usbhost";
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ phys = <&exynos_usbphy 1>;
+ status = "disabled";
+ };
+ port@1 {
+ reg = <1>;
+ phys = <&exynos_usbphy 2>;
+ status = "disabled";
+ };
+ port@2 {
+ reg = <2>;
+ phys = <&exynos_usbphy 3>;
+ status = "disabled";
+ };
};
ohci@12590000 {
@@ -331,6 +358,13 @@
clocks = <&clock CLK_USB_HOST>;
clock-names = "usbhost";
status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ phys = <&exynos_usbphy 1>;
+ status = "disabled";
+ };
};
i2s1: i2s@13960000 {
@@ -363,7 +397,7 @@
status = "disabled";
};
- serial@13800000 {
+ serial_0: serial@13800000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13800000 0x100>;
interrupts = <0 52 0>;
@@ -372,7 +406,7 @@
status = "disabled";
};
- serial@13810000 {
+ serial_1: serial@13810000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13810000 0x100>;
interrupts = <0 53 0>;
@@ -381,7 +415,7 @@
status = "disabled";
};
- serial@13820000 {
+ serial_2: serial@13820000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13820000 0x100>;
interrupts = <0 54 0>;
@@ -390,7 +424,7 @@
status = "disabled";
};
- serial@13830000 {
+ serial_3: serial@13830000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13830000 0x100>;
interrupts = <0 55 0>;
@@ -608,6 +642,7 @@
clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
clock-names = "sclk_fimd", "fimd";
samsung,power-domain = <&pd_lcd0>;
+ samsung,sysreg = <&sys_reg>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
index 636d16684750..676e6e0c8cf3 100644
--- a/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -168,6 +168,7 @@
};
spi_2: spi@13940000 {
+ cs-gpios = <&gpc1 2 0>;
status = "okay";
w25x80@0 {
@@ -178,7 +179,6 @@
spi-max-frequency = <1000000>;
controller-data {
- cs-gpio = <&gpc1 2 0>;
samsung,spi-feedback-delay = <0>;
};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index ee3001f38821..807bb5bf91fc 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -31,6 +31,16 @@
pinctrl2 = &pinctrl_2;
};
+ pmu_system_controller: system-controller@10020000 {
+ clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+ "clkout4", "clkout8", "clkout9";
+ clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+ <&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+ <&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+ <&clock CLK_XUSBXTI>;
+ #clock-cells = <1>;
+ };
+
sysram@02020000 {
compatible = "mmio-sram";
reg = <0x02020000 0x20000>;
@@ -93,12 +103,6 @@
#clock-cells = <1>;
};
- pmu {
- compatible = "arm,cortex-a9-pmu";
- interrupt-parent = <&combiner>;
- interrupts = <2 2>, <3 2>;
- };
-
pinctrl_0: pinctrl@11400000 {
compatible = "samsung,exynos4210-pinctrl";
reg = <0x11400000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
new file mode 100644
index 000000000000..6d6d23c83d30
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -0,0 +1,371 @@
+/*
+ * Common definition for Hardkernel's Exynos4412 based ODROID-X/X2/U2/U3 boards
+ * device tree source
+ *
+ * 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 <dt-bindings/input/input.h>
+#include "exynos4412.dtsi"
+
+/ {
+ firmware@0204F000 {
+ compatible = "samsung,secure-firmware";
+ reg = <0x0204F000 0x1000>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_power_key>;
+
+ power_key {
+ interrupt-parent = <&gpx1>;
+ interrupts = <3 0>;
+ gpios = <&gpx1 3 1>;
+ linux,code = <KEY_POWER>;
+ label = "power key";
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ i2s0: i2s@03830000 {
+ pinctrl-0 = <&i2s0_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+ clocks = <&clock_audss EXYNOS_I2S_BUS>,
+ <&clock_audss EXYNOS_DOUT_AUD_BUS>;
+ clock-names = "iis", "i2s_opclk0";
+ };
+
+ sound: sound {
+ compatible = "samsung,odroidx2-audio";
+ samsung,i2s-controller = <&i2s0>;
+ samsung,audio-codec = <&max98090>;
+ };
+
+ mmc@12550000 {
+ pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+ pinctrl-names = "default";
+ vmmc-supply = <&ldo20_reg &buck8_reg>;
+ status = "okay";
+
+ num-slots = <1>;
+ supports-highspeed;
+ broken-cd;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <8>;
+ };
+ };
+
+ watchdog@10060000 {
+ status = "okay";
+ };
+
+ rtc@10070000 {
+ status = "okay";
+ };
+
+ g2d@10800000 {
+ status = "okay";
+ };
+
+ camera {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+
+ fimc_0: fimc@11800000 {
+ status = "okay";
+ };
+
+ fimc_1: fimc@11810000 {
+ status = "okay";
+ };
+
+ fimc_2: fimc@11820000 {
+ status = "okay";
+ };
+
+ fimc_3: fimc@11830000 {
+ status = "okay";
+ };
+ };
+
+ sdhci@12530000 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+ pinctrl-names = "default";
+ vmmc-supply = <&ldo4_reg &ldo21_reg>;
+ cd-gpios = <&gpk2 2 0>;
+ cd-inverted;
+ status = "okay";
+ };
+
+ serial@13800000 {
+ status = "okay";
+ };
+
+ serial@13810000 {
+ status = "okay";
+ };
+
+ fixed-rate-clocks {
+ xxti {
+ compatible = "samsung,clock-xxti";
+ clock-frequency = <0>;
+ };
+
+ xusbxti {
+ compatible = "samsung,clock-xusbxti";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ i2c@13860000 {
+ pinctrl-0 = <&i2c0_bus>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ usb3503: usb3503@08 {
+ compatible = "smsc,usb3503";
+ reg = <0x08>;
+
+ intn-gpios = <&gpx3 0 0>;
+ connect-gpios = <&gpx3 4 0>;
+ reset-gpios = <&gpx3 5 0>;
+ initial-mode = <1>;
+ };
+
+ max77686: pmic@09 {
+ compatible = "maxim,max77686";
+ reg = <0x09>;
+ #clock-cells = <1>;
+
+ voltage-regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ALIVE_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDDQ_M1_2_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VDDQ_EXT_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VDDQ_MMC2_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "VDDQ_MMC1_3_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VDD10_MPLL_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VDD10_XPLL_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "VDD18_ABB1_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "VDD33_USB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "VDDQ_C2C_W_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "VDD18_ABB0_2_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "VDD10_HSIC_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "VDD18_HSIC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo20_reg: LDO20 {
+ regulator-name = "LDO20_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo21_reg: LDO21 {
+ regulator-name = "LDO21_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo25_reg: LDO25 {
+ regulator-name = "VDDQ_LCD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "vdd_mif";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "vdd_int";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "vdd_g3d";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-microvolt-offset = <50000>;
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-name = "VDDQ_CKEM1_2_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck6_reg: BUCK6 {
+ regulator-name = "BUCK6_1.35V";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-name = "BUCK7_2.0V";
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-always-on;
+ };
+
+ buck8_reg: BUCK8 {
+ regulator-name = "BUCK8_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+ };
+ };
+ };
+
+ i2c@13870000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_bus>;
+ status = "okay";
+ max98090: max98090@10 {
+ compatible = "maxim,max98090";
+ reg = <0x10>;
+ interrupt-parent = <&gpx0>;
+ interrupts = <0 0>;
+ };
+ };
+
+ exynos-usbphy@125B0000 {
+ status = "okay";
+ };
+
+ hsotg@12480000 {
+ status = "okay";
+ vusb_d-supply = <&ldo15_reg>;
+ vusb_a-supply = <&ldo12_reg>;
+ };
+
+ ehci: ehci@12580000 {
+ status = "okay";
+ };
+};
+
+&pinctrl_1 {
+ gpio_power_key: power_key {
+ samsung,pins = "gpx1-3";
+ samsung,pin-pud = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
new file mode 100644
index 000000000000..c8a64be55d07
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -0,0 +1,61 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-U3 board device tree source
+ *
+ * Copyright (c) 2014 Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-U3 board which is based
+ * on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+#include "exynos4412-odroid-common.dtsi"
+
+/ {
+ model = "Hardkernel ODROID-U3 board based on Exynos4412";
+ compatible = "hardkernel,odroid-u3", "samsung,exynos4412", "samsung,exynos4";
+
+ memory {
+ reg = <0x40000000 0x7FF00000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led1 {
+ label = "led1:heart";
+ gpios = <&gpc1 0 1>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&usb3503 {
+ clock-names = "refclk";
+ clocks = <&pmu_system_controller 0>;
+ refclk-frequency = <24000000>;
+};
+
+&ehci {
+ port@1 {
+ status = "okay";
+ };
+ port@2 {
+ status = "okay";
+ };
+};
+
+&sound {
+ compatible = "samsung,odroidu3-audio";
+ samsung,model = "Odroid-U3";
+ samsung,audio-routing =
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "Headphone Jack", "MICBIAS",
+ "IN1", "Headphone Jack",
+ "Speakers", "SPKL",
+ "Speakers", "SPKR";
+};
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 31db28a4bb33..cb1cfe7239c4 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -3,8 +3,8 @@
*
* Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
*
- * Device tree source file for Hardkernel's ODROID-X board which is based on
- * Samsung's Exynos4412 SoC.
+ * Device tree source file for Hardkernel's ODROID-X board which is based
+ * on Samsung's Exynos4412 SoC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -12,14 +12,14 @@
*/
/dts-v1/;
-#include "exynos4412.dtsi"
+#include "exynos4412-odroid-common.dtsi"
/ {
model = "Hardkernel ODROID-X board based on Exynos4412";
compatible = "hardkernel,odroid-x", "samsung,exynos4412", "samsung,exynos4";
memory {
- reg = <0x40000000 0x40000000>;
+ reg = <0x40000000 0x3FF00000>;
};
leds {
@@ -38,23 +38,25 @@
};
};
- mmc@12550000 {
- pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
- pinctrl-names = "default";
- vmmc-supply = <&ldo20_reg &buck8_reg>;
+ serial@13820000 {
status = "okay";
+ };
- num-slots = <1>;
- supports-highspeed;
- broken-cd;
- card-detect-delay = <200>;
- samsung,dw-mshc-ciu-div = <3>;
- samsung,dw-mshc-sdr-timing = <2 3>;
- samsung,dw-mshc-ddr-timing = <1 2>;
+ serial@13830000 {
+ status = "okay";
+ };
- slot@0 {
- reg = <0>;
- bus-width = <8>;
+ gpio_keys {
+ pinctrl-0 = <&gpio_power_key &gpio_home_key>;
+
+ home_key {
+ interrupt-parent = <&gpx2>;
+ interrupts = <2 0>;
+ gpios = <&gpx2 2 0>;
+ linux,code = <KEY_HOME>;
+ label = "home key";
+ debounce-interval = <10>;
+ gpio-key,wakeup;
};
};
@@ -65,242 +67,19 @@
regulator-max-microvolt = <3300000>;
gpio = <&gpa1 1 1>;
enable-active-high;
- regulator-boot-on;
- };
-
- rtc@10070000 {
- status = "okay";
- };
-
- sdhci@12530000 {
- bus-width = <4>;
- pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
- pinctrl-names = "default";
- vmmc-supply = <&ldo4_reg &ldo21_reg>;
- status = "okay";
- };
-
- serial@13800000 {
- status = "okay";
- };
-
- serial@13810000 {
- status = "okay";
- };
-
- serial@13820000 {
- status = "okay";
+ regulator-always-on;
};
+};
- serial@13830000 {
+&ehci {
+ port@1 {
status = "okay";
};
+};
- fixed-rate-clocks {
- xxti {
- compatible = "samsung,clock-xxti";
- clock-frequency = <0>;
- };
-
- xusbxti {
- compatible = "samsung,clock-xusbxti";
- clock-frequency = <24000000>;
- };
- };
-
- i2c@13860000 {
- pinctrl-0 = <&i2c0_bus>;
- pinctrl-names = "default";
- status = "okay";
-
- max77686: pmic@09 {
- compatible = "maxim,max77686";
- reg = <0x09>;
- #clock-cells = <1>;
-
- voltage-regulators {
- ldo1_reg: LDO1 {
- regulator-name = "VDD_ALIVE_1.0V";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo2_reg: LDO2 {
- regulator-name = "VDDQ_M1_2_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo3_reg: LDO3 {
- regulator-name = "VDDQ_EXT_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo4_reg: LDO4 {
- regulator-name = "VDDQ_MMC2_2.8V";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo5_reg: LDO5 {
- regulator-name = "VDDQ_MMC1_3_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo6_reg: LDO6 {
- regulator-name = "VDD10_MPLL_1.0V";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo7_reg: LDO7 {
- regulator-name = "VDD10_XPLL_1.0V";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo11_reg: LDO11 {
- regulator-name = "VDD18_ABB1_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo12_reg: LDO12 {
- regulator-name = "VDD33_USB_3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo13_reg: LDO13 {
- regulator-name = "VDDQ_C2C_W_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo14_reg: LDO14 {
- regulator-name = "VDD18_ABB0_2_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo15_reg: LDO15 {
- regulator-name = "VDD10_HSIC_1.0V";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo16_reg: LDO16 {
- regulator-name = "VDD18_HSIC_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo20_reg: LDO20 {
- regulator-name = "LDO20_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-boot-on;
- };
-
- ldo21_reg: LDO21 {
- regulator-name = "LDO21_3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- ldo25_reg: LDO25 {
- regulator-name = "VDDQ_LCD_1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck1_reg: BUCK1 {
- regulator-name = "vdd_mif";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck2_reg: BUCK2 {
- regulator-name = "vdd_arm";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1350000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck3_reg: BUCK3 {
- regulator-name = "vdd_int";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck4_reg: BUCK4 {
- regulator-name = "vdd_g3d";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1100000>;
- regulator-microvolt-offset = <50000>;
- };
-
- buck5_reg: BUCK5 {
- regulator-name = "VDDQ_CKEM1_2_1.2V";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck6_reg: BUCK6 {
- regulator-name = "BUCK6_1.35V";
- regulator-min-microvolt = <1350000>;
- regulator-max-microvolt = <1350000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck7_reg: BUCK7 {
- regulator-name = "BUCK7_2.0V";
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- regulator-always-on;
- };
-
- buck8_reg: BUCK8 {
- regulator-name = "BUCK8_2.8V";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- regulator-always-on;
- };
- };
- };
+&pinctrl_1 {
+ gpio_home_key: home_key {
+ samsung,pins = "gpx2-2";
+ samsung,pin-pud = <0>;
};
};
diff --git a/arch/arm/boot/dts/exynos4412-odroidx2.dts b/arch/arm/boot/dts/exynos4412-odroidx2.dts
new file mode 100644
index 000000000000..96b43f4497cc
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4412-odroidx2.dts
@@ -0,0 +1,32 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-X2 board device tree source
+ *
+ * Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-X2 board which is based
+ * on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include "exynos4412-odroidx.dts"
+
+/ {
+ model = "Hardkernel ODROID-X2 board based on Exynos4412";
+ compatible = "hardkernel,odroid-x2", "samsung,exynos4412", "samsung,exynos4";
+
+ memory {
+ reg = <0x40000000 0x7FF00000>;
+ };
+};
+
+&sound {
+ samsung,model = "Odroid-X2";
+ samsung,audio-routing =
+ "Headphone Jack", "HPL",
+ "Headphone Jack", "HPR",
+ "IN1", "Mic Jack",
+ "Mic Jack", "MICBIAS";
+};
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 77878447b312..11967f4561e0 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -589,6 +589,7 @@
spi_1: spi@13930000 {
pinctrl-names = "default";
pinctrl-0 = <&spi1_bus>;
+ cs-gpios = <&gpb 5 0>;
status = "okay";
s5c73m3_spi: s5c73m3 {
@@ -596,7 +597,6 @@
spi-max-frequency = <50000000>;
reg = <0>;
controller-data {
- cs-gpio = <&gpb 5 0>;
samsung,spi-feedback-delay = <2>;
};
};
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index c42a3e196cd5..d8bc059e172f 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -26,6 +26,10 @@
samsung,combiner-nr = <20>;
};
+ pmu {
+ interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
+ };
+
gic: interrupt-controller@10490000 {
cpu-offset = <0x4000>;
};
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index c5a943df1cd7..861bb919f6d3 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -31,12 +31,6 @@
mshc0 = &mshc_0;
};
- pmu {
- compatible = "arm,cortex-a9-pmu";
- interrupt-parent = <&combiner>;
- interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
- };
-
sysram@02020000 {
compatible = "mmio-sram";
reg = <0x02020000 0x40000>;
@@ -139,6 +133,13 @@
pmu_system_controller: system-controller@10020000 {
compatible = "samsung,exynos4212-pmu", "syscon";
+ clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
+ "clkout4", "clkout8", "clkout9";
+ clocks = <&clock CLK_OUT_DMC>, <&clock CLK_OUT_TOP>,
+ <&clock CLK_OUT_LEFTBUS>, <&clock CLK_OUT_RIGHTBUS>,
+ <&clock CLK_OUT_CPU>, <&clock CLK_XXTI>,
+ <&clock CLK_XUSBXTI>;
+ #clock-cells = <1>;
};
g2d@10800000 {
diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index 79d0608d6dcc..a0cc0b6f8f96 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -18,6 +18,13 @@
/ {
interrupt-parent = <&gic>;
+ aliases {
+ serial0 = &serial_0;
+ serial1 = &serial_1;
+ serial2 = &serial_2;
+ serial3 = &serial_3;
+ };
+
chipid@10000000 {
compatible = "samsung,exynos4210-chipid";
reg = <0x10000000 0x100>;
@@ -50,25 +57,25 @@
interrupts = <1 9 0xf04>;
};
- serial@12C00000 {
+ serial_0: serial@12C00000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C00000 0x100>;
interrupts = <0 51 0>;
};
- serial@12C10000 {
+ serial_1: serial@12C10000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C10000 0x100>;
interrupts = <0 52 0>;
};
- serial@12C20000 {
+ serial_2: serial@12C20000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C20000 0x100>;
interrupts = <0 53 0>;
};
- serial@12C30000 {
+ serial_3: serial@12C30000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C30000 0x100>;
interrupts = <0 54 0>;
@@ -87,6 +94,7 @@
reg = <0x14400000 0x40000>;
interrupt-names = "fifo", "vsync", "lcd_sys";
interrupts = <18 4>, <18 5>, <18 6>;
+ samsung,sysreg = <&sysreg_system_controller>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/exynos5250-cros-common.dtsi b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
index 89ac90f59e2e..e603e9c70142 100644
--- a/arch/arm/boot/dts/exynos5250-cros-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
@@ -27,177 +27,18 @@
i2c2_bus: i2c2-bus {
samsung,pin-pud = <0>;
};
-
- max77686_irq: max77686-irq {
- samsung,pins = "gpx3-2";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
- };
};
i2c@12C60000 {
status = "okay";
samsung,i2c-sda-delay = <100>;
samsung,i2c-max-bus-freq = <378000>;
-
- max77686@09 {
- compatible = "maxim,max77686";
- interrupt-parent = <&gpx3>;
- interrupts = <2 0>;
- pinctrl-names = "default";
- pinctrl-0 = <&max77686_irq>;
- wakeup-source;
- reg = <0x09>;
- #clock-cells = <1>;
-
- voltage-regulators {
- ldo1_reg: LDO1 {
- regulator-name = "P1.0V_LDO_OUT1";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo2_reg: LDO2 {
- regulator-name = "P1.8V_LDO_OUT2";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo3_reg: LDO3 {
- regulator-name = "P1.8V_LDO_OUT3";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo7_reg: LDO7 {
- regulator-name = "P1.1V_LDO_OUT7";
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- regulator-always-on;
- };
-
- ldo8_reg: LDO8 {
- regulator-name = "P1.0V_LDO_OUT8";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo10_reg: LDO10 {
- regulator-name = "P1.8V_LDO_OUT10";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo12_reg: LDO12 {
- regulator-name = "P3.0V_LDO_OUT12";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- regulator-always-on;
- };
-
- ldo14_reg: LDO14 {
- regulator-name = "P1.8V_LDO_OUT14";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- ldo15_reg: LDO15 {
- regulator-name = "P1.0V_LDO_OUT15";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- };
-
- ldo16_reg: LDO16 {
- regulator-name = "P1.8V_LDO_OUT16";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- buck1_reg: BUCK1 {
- regulator-name = "vdd_mif";
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck2_reg: BUCK2 {
- regulator-name = "vdd_arm";
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1350000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck3_reg: BUCK3 {
- regulator-name = "vdd_int";
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1200000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck4_reg: BUCK4 {
- regulator-name = "vdd_g3d";
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1300000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck5_reg: BUCK5 {
- regulator-name = "P1.8V_BUCK_OUT5";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
- };
-
- buck6_reg: BUCK6 {
- regulator-name = "P1.35V_BUCK_OUT6";
- regulator-min-microvolt = <1350000>;
- regulator-max-microvolt = <1350000>;
- regulator-always-on;
- };
-
- buck7_reg: BUCK7 {
- regulator-name = "P2.0V_BUCK_OUT7";
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- regulator-always-on;
- };
-
- buck8_reg: BUCK8 {
- regulator-name = "P2.85V_BUCK_OUT8";
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- regulator-always-on;
- };
- };
- };
};
i2c@12C70000 {
status = "okay";
samsung,i2c-sda-delay = <100>;
samsung,i2c-max-bus-freq = <378000>;
-
- trackpad {
- reg = <0x67>;
- compatible = "cypress,cyapa";
- interrupts = <2 0>;
- interrupt-parent = <&gpx1>;
- wakeup-source;
- };
};
i2c@12C80000 {
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index a794a705d404..b4b35adae565 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -44,6 +44,8 @@
max77686@09 {
compatible = "maxim,max77686";
reg = <0x09>;
+ interrupt-parent = <&gpx3>;
+ interrupts = <2 0>;
voltage-regulators {
ldo1_reg: LDO1 {
@@ -316,6 +318,7 @@
};
spi_1: spi@12d30000 {
+ cs-gpios = <&gpa2 5 0>;
status = "okay";
w25q80bw@0 {
@@ -326,7 +329,6 @@
spi-max-frequency = <1000000>;
controller-data {
- cs-gpio = <&gpa2 5 0>;
samsung,spi-feedback-delay = <0>;
};
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts
index 079fdf9e3f18..f2b8c4116541 100644
--- a/arch/arm/boot/dts/exynos5250-snow.dts
+++ b/arch/arm/boot/dts/exynos5250-snow.dts
@@ -137,7 +137,7 @@
sbs,poll-retry-count = <1>;
};
- ec: embedded-controller {
+ cros_ec: embedded-controller {
compatible = "google,cros-ec-i2c";
reg = <0x1e>;
interrupts = <6 0>;
@@ -145,95 +145,6 @@
pinctrl-names = "default";
pinctrl-0 = <&ec_irq>;
wakeup-source;
-
- keyboard-controller {
- compatible = "google,cros-ec-keyb";
- keypad,num-rows = <8>;
- keypad,num-columns = <13>;
- google,needs-ghost-filter;
- linux,keymap = <0x0001007d /* L_META */
- 0x0002003b /* F1 */
- 0x00030030 /* B */
- 0x00040044 /* F10 */
- 0x00060031 /* N */
- 0x0008000d /* = */
- 0x000a0064 /* R_ALT */
-
- 0x01010001 /* ESC */
- 0x0102003e /* F4 */
- 0x01030022 /* G */
- 0x01040041 /* F7 */
- 0x01060023 /* H */
- 0x01080028 /* ' */
- 0x01090043 /* F9 */
- 0x010b000e /* BKSPACE */
-
- 0x0200001d /* L_CTRL */
- 0x0201000f /* TAB */
- 0x0202003d /* F3 */
- 0x02030014 /* T */
- 0x02040040 /* F6 */
- 0x0205001b /* ] */
- 0x02060015 /* Y */
- 0x02070056 /* 102ND */
- 0x0208001a /* [ */
- 0x02090042 /* F8 */
-
- 0x03010029 /* GRAVE */
- 0x0302003c /* F2 */
- 0x03030006 /* 5 */
- 0x0304003f /* F5 */
- 0x03060007 /* 6 */
- 0x0308000c /* - */
- 0x030b002b /* \ */
-
- 0x04000061 /* R_CTRL */
- 0x0401001e /* A */
- 0x04020020 /* D */
- 0x04030021 /* F */
- 0x0404001f /* S */
- 0x04050025 /* K */
- 0x04060024 /* J */
- 0x04080027 /* ; */
- 0x04090026 /* L */
- 0x040a002b /* \ */
- 0x040b001c /* ENTER */
-
- 0x0501002c /* Z */
- 0x0502002e /* C */
- 0x0503002f /* V */
- 0x0504002d /* X */
- 0x05050033 /* , */
- 0x05060032 /* M */
- 0x0507002a /* L_SHIFT */
- 0x05080035 /* / */
- 0x05090034 /* . */
- 0x050B0039 /* SPACE */
-
- 0x06010002 /* 1 */
- 0x06020004 /* 3 */
- 0x06030005 /* 4 */
- 0x06040003 /* 2 */
- 0x06050009 /* 8 */
- 0x06060008 /* 7 */
- 0x0608000b /* 0 */
- 0x0609000a /* 9 */
- 0x060a0038 /* L_ALT */
- 0x060b006c /* DOWN */
- 0x060c006a /* RIGHT */
-
- 0x07010010 /* Q */
- 0x07020012 /* E */
- 0x07030013 /* R */
- 0x07040011 /* W */
- 0x07050017 /* I */
- 0x07060016 /* U */
- 0x07070036 /* R_SHIFT */
- 0x07080019 /* P */
- 0x07090018 /* O */
- 0x070b0067 /* UP */
- 0x070c0069>; /* LEFT */
- };
};
power-regulator {
@@ -351,6 +262,7 @@
sound {
compatible = "google,snow-audio-max98095";
+ samsung,model = "Snow-I2S-MAX98095";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98095>;
};
@@ -431,3 +343,170 @@
};
};
};
+
+&i2c_0 {
+ max77686@09 {
+ compatible = "maxim,max77686";
+ interrupt-parent = <&gpx3>;
+ interrupts = <2 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&max77686_irq>;
+ wakeup-source;
+ reg = <0x09>;
+ #clock-cells = <1>;
+
+ voltage-regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "P1.0V_LDO_OUT1";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "P1.8V_LDO_OUT2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "P1.8V_LDO_OUT3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "P1.1V_LDO_OUT7";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "P1.0V_LDO_OUT8";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "P1.8V_LDO_OUT10";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "P3.0V_LDO_OUT12";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "P1.8V_LDO_OUT14";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "P1.0V_LDO_OUT15";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "P1.8V_LDO_OUT16";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "vdd_mif";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "vdd_int";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "vdd_g3d";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-name = "P1.8V_BUCK_OUT5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck6_reg: BUCK6 {
+ regulator-name = "P1.35V_BUCK_OUT6";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-name = "P2.0V_BUCK_OUT7";
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-always-on;
+ };
+
+ buck8_reg: BUCK8 {
+ regulator-name = "P2.85V_BUCK_OUT8";
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c_1 {
+ trackpad {
+ reg = <0x67>;
+ compatible = "cypress,cyapa";
+ interrupts = <2 0>;
+ interrupt-parent = <&gpx1>;
+ wakeup-source;
+ };
+};
+
+&pinctrl_0 {
+ max77686_irq: max77686-irq {
+ samsung,pins = "gpx3-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+};
+
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 834fb5a5306f..492e1eff37bd 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -191,6 +191,9 @@
pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5250-pmu", "syscon";
reg = <0x10040000 0x5000>;
+ clock-names = "clkout16";
+ clocks = <&clock CLK_FIN_PLL>;
+ #clock-cells = <1>;
};
sysreg_system_controller: syscon@10050000 {
diff --git a/arch/arm/boot/dts/exynos5260.dtsi b/arch/arm/boot/dts/exynos5260.dtsi
index 5398a60207ca..36da38e29000 100644
--- a/arch/arm/boot/dts/exynos5260.dtsi
+++ b/arch/arm/boot/dts/exynos5260.dtsi
@@ -21,6 +21,10 @@
pinctrl0 = &pinctrl_0;
pinctrl1 = &pinctrl_1;
pinctrl2 = &pinctrl_2;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
};
cpus {
@@ -227,6 +231,11 @@
interrupts = <0 243 0>;
};
+ pmu_system_controller: system-controller@10D50000 {
+ compatible = "samsung,exynos5260-pmu", "syscon";
+ reg = <0x10D50000 0x10000>;
+ };
+
uart0: serial@12C00000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C00000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 3839c26f467f..731eefd23fa9 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -20,6 +20,12 @@
compatible = "samsung,exynos5410", "samsung,exynos5";
interrupt-parent = <&gic>;
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -28,24 +34,28 @@
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
+ clock-frequency = <1600000000>;
};
CPU1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x1>;
+ clock-frequency = <1600000000>;
};
CPU2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x2>;
+ clock-frequency = <1600000000>;
};
CPU3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x3>;
+ clock-frequency = <1600000000>;
};
};
@@ -87,6 +97,11 @@
reg = <0x10000000 0x100>;
};
+ pmu_system_controller: system-controller@10040000 {
+ compatible = "samsung,exynos5410-pmu", "syscon";
+ reg = <0x10040000 0x5000>;
+ };
+
mct: mct@101C0000 {
compatible = "samsung,exynos4210-mct";
reg = <0x101C0000 0xB00>;
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 1c5b8f9f4a36..228a6b1e0aa1 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -25,8 +25,18 @@
"google,pit", "google,peach","samsung,exynos5420",
"samsung,exynos5";
- memory {
- reg = <0x20000000 0x80000000>;
+ aliases {
+ /* Assign 20 so we don't get confused w/ builtin ones */
+ i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 1000000 0>;
+ brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
+ default-brightness-level = <7>;
+ pinctrl-0 = <&pwm0_out>;
+ pinctrl-names = "default";
};
fixed-rate-clocks {
@@ -50,18 +60,14 @@
};
};
- backlight {
- compatible = "pwm-backlight";
- pwms = <&pwm 0 1000000 0>;
- brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
- default-brightness-level = <7>;
- pinctrl-0 = <&pwm0_out>;
- pinctrl-names = "default";
+ memory {
+ reg = <0x20000000 0x80000000>;
};
sound {
compatible = "google,snow-audio-max98090";
+ samsung,model = "Peach-Pit-I2S-MAX98090";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&max98090>;
};
@@ -87,66 +93,92 @@
pinctrl-0 = <&usb301_vbus_en>;
enable-active-high;
};
-};
-&pinctrl_0 {
- max98090_irq: max98090-irq {
- samsung,pins = "gpx0-2";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ vbat: fixed-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vbat-supply";
+ regulator-boot-on;
+ regulator-always-on;
};
+};
- tpm_irq: tpm-irq {
- samsung,pins = "gpx1-0";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
- };
+&dp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp_hpd_gpio>;
+ samsung,color-space = <0>;
+ samsung,dynamic-range = <0>;
+ samsung,ycbcr-coeff = <0>;
+ samsung,color-depth = <1>;
+ samsung,link-rate = <0x06>;
+ samsung,lane-count = <2>;
+ samsung,hpd-gpio = <&gpx2 6 0>;
- power_key_irq: power-key-irq {
- samsung,pins = "gpx1-2";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
- };
+ display-timings {
+ native-mode = <&timing1>;
- hdmi_hpd_irq: hdmi-hpd-irq {
- samsung,pins = "gpx3-7";
- samsung,pin-function = <0>;
- samsung,pin-pud = <1>;
- samsung,pin-drv = <0>;
+ timing1: timing@1 {
+ clock-frequency = <70589280>;
+ hactive = <1366>;
+ vactive = <768>;
+ hfront-porch = <40>;
+ hback-porch = <40>;
+ hsync-len = <32>;
+ vback-porch = <10>;
+ vfront-porch = <12>;
+ vsync-len = <6>;
+ };
};
+};
- dp_hpd_gpio: dp_hpd_gpio {
- samsung,pins = "gpx2-6";
- samsung,pin-function = <0>;
- samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
- };
+&fimd {
+ status = "okay";
+ samsung,invert-vclk;
};
-&pinctrl_3 {
- usb300_vbus_en: usb300-vbus-en {
- samsung,pins = "gph0-0";
- samsung,pin-function = <1>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+&hdmi {
+ status = "okay";
+ hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_hpd_irq>;
+ ddc = <&i2c_2>;
+};
+
+&hsi2c_7 {
+ status = "okay";
+
+ max98090: codec@10 {
+ compatible = "maxim,max98090";
+ reg = <0x10>;
+ interrupts = <2 0>;
+ interrupt-parent = <&gpx0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&max98090_irq>;
};
+};
- usb301_vbus_en: usb301-vbus-en {
- samsung,pins = "gph0-1";
- samsung,pin-function = <1>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+&hsi2c_9 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tpm@20 {
+ compatible = "infineon,slb9645tt";
+ reg = <0x20>;
+
+ /* Unused irq; but still need to configure the pins */
+ pinctrl-names = "default";
+ pinctrl-0 = <&tpm_irq>;
};
};
-&rtc {
+&i2c_2 {
status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ samsung,i2c-slave-addr = <0x50>;
};
-&uart_3 {
+&i2s0 {
status = "okay";
};
@@ -189,46 +221,210 @@
};
};
-&hsi2c_7 {
- status = "okay";
- max98090: codec@10 {
- compatible = "maxim,max98090";
- reg = <0x10>;
- interrupts = <2 0>;
- interrupt-parent = <&gpx0>;
- pinctrl-names = "default";
- pinctrl-0 = <&max98090_irq>;
+&pinctrl_0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mask_tpm_reset>;
+
+ max98090_irq: max98090-irq {
+ samsung,pins = "gpx0-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ /* We need GPX0_6 to be low at sleep time; just keep it low always */
+ mask_tpm_reset: mask-tpm-reset {
+ samsung,pins = "gpx0-6";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ samsung,pin-val = <0>;
+ };
+
+ tpm_irq: tpm-irq {
+ samsung,pins = "gpx1-0";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ power_key_irq: power-key-irq {
+ samsung,pins = "gpx1-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ ec_irq: ec-irq {
+ samsung,pins = "gpx1-5";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ tps65090_irq: tps65090-irq {
+ samsung,pins = "gpx2-5";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ dp_hpd_gpio: dp_hpd_gpio {
+ samsung,pins = "gpx2-6";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ hdmi_hpd_irq: hdmi-hpd-irq {
+ samsung,pins = "gpx3-7";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <0>;
};
};
-&hsi2c_9 {
- status = "okay";
- clock-frequency = <400000>;
+&pinctrl_3 {
+ /* Drive SPI lines at x2 for better integrity */
+ spi2-bus {
+ samsung,pin-drv = <2>;
+ };
- tpm@20 {
- compatible = "infineon,slb9645tt";
- reg = <0x20>;
+ /* Drive SPI chip select at x2 for better integrity */
+ ec_spi_cs: ec-spi-cs {
+ samsung,pins = "gpb1-2";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <2>;
+ };
- /* Unused irq; but still need to configure the pins */
- pinctrl-names = "default";
- pinctrl-0 = <&tpm_irq>;
+ usb300_vbus_en: usb300-vbus-en {
+ samsung,pins = "gph0-0";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ usb301_vbus_en: usb301-vbus-en {
+ samsung,pins = "gph0-1";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
};
};
-&i2c_2 {
+&rtc {
status = "okay";
- samsung,i2c-sda-delay = <100>;
- samsung,i2c-max-bus-freq = <66000>;
- samsung,i2c-slave-addr = <0x50>;
};
-&hdmi {
+&spi_2 {
+ status = "okay";
+ num-cs = <1>;
+ samsung,spi-src-clk = <0>;
+ cs-gpios = <&gpb1 2 0>;
+
+ cros_ec: cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+ interrupt-parent = <&gpx1>;
+ interrupts = <5 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ec_spi_cs &ec_irq>;
+ reg = <0>;
+ spi-max-frequency = <3125000>;
+
+ controller-data {
+ samsung,spi-feedback-delay = <1>;
+ };
+
+ i2c-tunnel {
+ compatible = "google,cros-ec-i2c-tunnel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ google,remote-bus = <0>;
+
+ battery: sbs-battery@b {
+ compatible = "sbs,sbs-battery";
+ reg = <0xb>;
+ sbs,poll-retry-count = <1>;
+ sbs,i2c-retry-count = <2>;
+ };
+
+ power-regulator@48 {
+ compatible = "ti,tps65090";
+ reg = <0x48>;
+
+ /*
+ * Config irq to disable internal pulls
+ * even though we run in polling mode.
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&tps65090_irq>;
+
+ vsys1-supply = <&vbat>;
+ vsys2-supply = <&vbat>;
+ vsys3-supply = <&vbat>;
+ infet1-supply = <&vbat>;
+ infet2-supply = <&vbat>;
+ infet3-supply = <&vbat>;
+ infet4-supply = <&vbat>;
+ infet5-supply = <&vbat>;
+ infet6-supply = <&vbat>;
+ infet7-supply = <&vbat>;
+ vsys-l1-supply = <&vbat>;
+ vsys-l2-supply = <&vbat>;
+
+ regulators {
+ tps65090_dcdc1: dcdc1 {
+ ti,enable-ext-control;
+ };
+ tps65090_dcdc2: dcdc2 {
+ ti,enable-ext-control;
+ };
+ tps65090_dcdc3: dcdc3 {
+ ti,enable-ext-control;
+ };
+ tps65090_fet1: fet1 {
+ regulator-name = "vcd_led";
+ };
+ tps65090_fet2: fet2 {
+ regulator-name = "video_mid";
+ regulator-always-on;
+ };
+ tps65090_fet3: fet3 {
+ regulator-name = "wwan_r";
+ regulator-always-on;
+ };
+ tps65090_fet4: fet4 {
+ regulator-name = "sdcard";
+ regulator-always-on;
+ };
+ tps65090_fet5: fet5 {
+ regulator-name = "camout";
+ };
+ tps65090_fet6: fet6 {
+ regulator-name = "lcd_vdd";
+ };
+ tps65090_fet7: fet7 {
+ regulator-name = "video_mid_1a";
+ regulator-always-on;
+ };
+ tps65090_ldo1: ldo1 {
+ };
+ tps65090_ldo2: ldo2 {
+ };
+ };
+
+ charger {
+ compatible = "ti,tps65090-charger";
+ };
+ };
+ };
+ };
+};
+
+&uart_3 {
status = "okay";
- hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&hdmi_hpd_irq>;
- ddc = <&i2c_2>;
};
&usbdrd_phy0 {
@@ -248,40 +444,4 @@
timeout-sec = <32>;
};
-&i2s0 {
- status = "okay";
-};
-
-&fimd {
- status = "okay";
- samsung,invert-vclk;
-};
-
-&dp {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dp_hpd_gpio>;
- samsung,color-space = <0>;
- samsung,dynamic-range = <0>;
- samsung,ycbcr-coeff = <0>;
- samsung,color-depth = <1>;
- samsung,link-rate = <0x06>;
- samsung,lane-count = <2>;
- samsung,hpd-gpio = <&gpx2 6 0>;
-
- display-timings {
- native-mode = <&timing1>;
-
- timing1: timing@1 {
- clock-frequency = <70589280>;
- hactive = <1366>;
- vactive = <768>;
- hfront-porch = <40>;
- hback-porch = <40>;
- hsync-len = <32>;
- vback-porch = <10>;
- vfront-porch = <12>;
- vsync-len = <6>;
- };
- };
-};
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 15957227ffda..bfe056d9148c 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -265,11 +265,6 @@
clock-names = "oscclk", "pclk0", "clk0";
};
- disp_pd: power-domain@100440C0 {
- compatible = "samsung,exynos4210-pd";
- reg = <0x100440C0 0x20>;
- };
-
msc_pd: power-domain@10044120 {
compatible = "samsung,exynos4210-pd";
reg = <0x10044120 0x20>;
@@ -520,8 +515,26 @@
phy-names = "dp";
};
+ mipi_phy: video-phy@10040714 {
+ compatible = "samsung,s5pv210-mipi-video-phy";
+ reg = <0x10040714 12>;
+ #phy-cells = <1>;
+ };
+
+ dsi@14500000 {
+ compatible = "samsung,exynos5410-mipi-dsi";
+ reg = <0x14500000 0x10000>;
+ interrupts = <0 82 0>;
+ phys = <&mipi_phy 1>;
+ phy-names = "dsim";
+ clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
+ clock-names = "bus_clk", "pll_clk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
fimd: fimd@14400000 {
- samsung,power-domain = <&disp_pd>;
clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
clock-names = "sclk_fimd", "fimd";
};
@@ -727,6 +740,9 @@
pmu_system_controller: system-controller@10040000 {
compatible = "samsung,exynos5420-pmu", "syscon";
reg = <0x10040000 0x5000>;
+ clock-names = "clkout16";
+ clocks = <&clock CLK_FIN_PLL>;
+ #clock-cells = <1>;
};
sysreg_system_controller: syscon@10050000 {
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index ae3a17c791f6..8f3373cd7b87 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -18,6 +18,8 @@
interrupt-parent = <&gic>;
aliases {
+ serial0 = &serial_0;
+ serial1 = &serial_1;
spi0 = &spi_0;
tmuctrl0 = &tmuctrl_0;
tmuctrl1 = &tmuctrl_1;
@@ -102,7 +104,7 @@
>;
};
- serial@B0000 {
+ serial_0: serial@B0000 {
compatible = "samsung,exynos4210-uart";
reg = <0xB0000 0x1000>;
interrupts = <0 2 0>;
@@ -110,7 +112,7 @@
clock-names = "uart", "clk_uart_baud0";
};
- serial@C0000 {
+ serial_1: serial@C0000 {
compatible = "samsung,exynos4210-uart";
reg = <0xC0000 0x1000>;
interrupts = <0 3 0>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index f3af2079a063..f3ee48bbe05f 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -23,8 +23,18 @@
"google,pi", "google,peach", "samsung,exynos5800",
"samsung,exynos5";
- memory {
- reg = <0x20000000 0x80000000>;
+ aliases {
+ /* Assign 20 so we don't get confused w/ builtin ones */
+ i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 1000000 0>;
+ brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
+ default-brightness-level = <7>;
+ pinctrl-0 = <&pwm0_out>;
+ pinctrl-names = "default";
};
fixed-rate-clocks {
@@ -48,13 +58,16 @@
};
};
- backlight {
- compatible = "pwm-backlight";
- pwms = <&pwm 0 1000000 0>;
- brightness-levels = <0 100 500 1000 1500 2000 2500 2800>;
- default-brightness-level = <7>;
- pinctrl-0 = <&pwm0_out>;
- pinctrl-names = "default";
+ memory {
+ reg = <0x20000000 0x80000000>;
+ };
+
+ sound {
+ compatible = "google,snow-audio-max98091";
+
+ samsung,model = "Peach-Pi-I2S-MAX98091";
+ samsung,i2s-controller = <&i2s0>;
+ samsung,audio-codec = <&max98091>;
};
usb300_vbus_reg: regulator-usb300 {
@@ -78,59 +91,92 @@
pinctrl-0 = <&usb301_vbus_en>;
enable-active-high;
};
-};
-&pinctrl_0 {
- tpm_irq: tpm-irq {
- samsung,pins = "gpx1-0";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+ vbat: fixed-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vbat-supply";
+ regulator-boot-on;
+ regulator-always-on;
};
+};
- power_key_irq: power-key-irq {
- samsung,pins = "gpx1-2";
- samsung,pin-function = <0>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
- };
+&dp {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp_hpd_gpio>;
+ samsung,color-space = <0>;
+ samsung,dynamic-range = <0>;
+ samsung,ycbcr-coeff = <0>;
+ samsung,color-depth = <1>;
+ samsung,link-rate = <0x0a>;
+ samsung,lane-count = <2>;
+ samsung,hpd-gpio = <&gpx2 6 0>;
- dp_hpd_gpio: dp_hpd_gpio {
- samsung,pins = "gpx2-6";
- samsung,pin-function = <0>;
- samsung,pin-pud = <3>;
- samsung,pin-drv = <0>;
- };
+ display-timings {
+ native-mode = <&timing1>;
- hdmi_hpd_irq: hdmi-hpd-irq {
- samsung,pins = "gpx3-7";
- samsung,pin-function = <0>;
- samsung,pin-pud = <1>;
- samsung,pin-drv = <0>;
+ timing1: timing@1 {
+ clock-frequency = <150660000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hfront-porch = <60>;
+ hback-porch = <172>;
+ hsync-len = <80>;
+ vback-porch = <25>;
+ vfront-porch = <10>;
+ vsync-len = <10>;
+ };
};
};
-&pinctrl_3 {
- usb300_vbus_en: usb300-vbus-en {
- samsung,pins = "gph0-0";
- samsung,pin-function = <1>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+&fimd {
+ status = "okay";
+ samsung,invert-vclk;
+};
+
+&hdmi {
+ status = "okay";
+ hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmi_hpd_irq>;
+ ddc = <&i2c_2>;
+};
+
+&hsi2c_7 {
+ status = "okay";
+
+ max98091: codec@10 {
+ compatible = "maxim,max98091";
+ reg = <0x10>;
+ interrupts = <2 0>;
+ interrupt-parent = <&gpx0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&max98091_irq>;
};
+};
- usb301_vbus_en: usb301-vbus-en {
- samsung,pins = "gph0-1";
- samsung,pin-function = <1>;
- samsung,pin-pud = <0>;
- samsung,pin-drv = <0>;
+&hsi2c_9 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tpm@20 {
+ compatible = "infineon,slb9645tt";
+ reg = <0x20>;
+
+ /* Unused irq; but still need to configure the pins */
+ pinctrl-names = "default";
+ pinctrl-0 = <&tpm_irq>;
};
};
-&rtc {
+&i2c_2 {
status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+ samsung,i2c-slave-addr = <0x50>;
};
-&uart_3 {
+&i2s0 {
status = "okay";
};
@@ -173,66 +219,210 @@
};
};
-&dp {
- status = "okay";
+
+&pinctrl_0 {
pinctrl-names = "default";
- pinctrl-0 = <&dp_hpd_gpio>;
- samsung,color-space = <0>;
- samsung,dynamic-range = <0>;
- samsung,ycbcr-coeff = <0>;
- samsung,color-depth = <1>;
- samsung,link-rate = <0x0a>;
- samsung,lane-count = <2>;
- samsung,hpd-gpio = <&gpx2 6 0>;
+ pinctrl-0 = <&mask_tpm_reset>;
- display-timings {
- native-mode = <&timing1>;
+ max98091_irq: max98091-irq {
+ samsung,pins = "gpx0-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
- timing1: timing@1 {
- clock-frequency = <150660000>;
- hactive = <1920>;
- vactive = <1080>;
- hfront-porch = <60>;
- hback-porch = <172>;
- hsync-len = <80>;
- vback-porch = <25>;
- vfront-porch = <10>;
- vsync-len = <10>;
- };
+ /* We need GPX0_6 to be low at sleep time; just keep it low always */
+ mask_tpm_reset: mask-tpm-reset {
+ samsung,pins = "gpx0-6";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ samsung,pin-val = <0>;
};
-};
-&fimd {
- status = "okay";
- samsung,invert-vclk;
+ tpm_irq: tpm-irq {
+ samsung,pins = "gpx1-0";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ power_key_irq: power-key-irq {
+ samsung,pins = "gpx1-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ ec_irq: ec-irq {
+ samsung,pins = "gpx1-5";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ tps65090_irq: tps65090-irq {
+ samsung,pins = "gpx2-5";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ dp_hpd_gpio: dp_hpd_gpio {
+ samsung,pins = "gpx2-6";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ hdmi_hpd_irq: hdmi-hpd-irq {
+ samsung,pins = "gpx3-7";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <0>;
+ };
};
-&hsi2c_9 {
- status = "okay";
- clock-frequency = <400000>;
+&pinctrl_3 {
+ /* Drive SPI lines at x2 for better integrity */
+ spi2-bus {
+ samsung,pin-drv = <2>;
+ };
- tpm@20 {
- compatible = "infineon,slb9645tt";
- reg = <0x20>;
- /* Unused irq; but still need to configure the pins */
- pinctrl-names = "default";
- pinctrl-0 = <&tpm_irq>;
+ /* Drive SPI chip select at x2 for better integrity */
+ ec_spi_cs: ec-spi-cs {
+ samsung,pins = "gpb1-2";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <2>;
+ };
+
+ usb300_vbus_en: usb300-vbus-en {
+ samsung,pins = "gph0-0";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ usb301_vbus_en: usb301-vbus-en {
+ samsung,pins = "gph0-1";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
};
};
-&i2c_2 {
+&rtc {
status = "okay";
- samsung,i2c-sda-delay = <100>;
- samsung,i2c-max-bus-freq = <66000>;
- samsung,i2c-slave-addr = <0x50>;
};
-&hdmi {
+&spi_2 {
+ status = "okay";
+ num-cs = <1>;
+ samsung,spi-src-clk = <0>;
+ cs-gpios = <&gpb1 2 0>;
+
+ cros_ec: cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+ interrupt-parent = <&gpx1>;
+ interrupts = <5 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ec_spi_cs &ec_irq>;
+ reg = <0>;
+ spi-max-frequency = <3125000>;
+
+ controller-data {
+ samsung,spi-feedback-delay = <1>;
+ };
+
+ i2c-tunnel {
+ compatible = "google,cros-ec-i2c-tunnel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ google,remote-bus = <0>;
+
+ battery: sbs-battery@b {
+ compatible = "sbs,sbs-battery";
+ reg = <0xb>;
+ sbs,poll-retry-count = <1>;
+ sbs,i2c-retry-count = <2>;
+ };
+
+ power-regulator@48 {
+ compatible = "ti,tps65090";
+ reg = <0x48>;
+
+ /*
+ * Config irq to disable internal pulls
+ * even though we run in polling mode.
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&tps65090_irq>;
+
+ vsys1-supply = <&vbat>;
+ vsys2-supply = <&vbat>;
+ vsys3-supply = <&vbat>;
+ infet1-supply = <&vbat>;
+ infet2-supply = <&vbat>;
+ infet3-supply = <&vbat>;
+ infet4-supply = <&vbat>;
+ infet5-supply = <&vbat>;
+ infet6-supply = <&vbat>;
+ infet7-supply = <&vbat>;
+ vsys-l1-supply = <&vbat>;
+ vsys-l2-supply = <&vbat>;
+
+ regulators {
+ tps65090_dcdc1: dcdc1 {
+ ti,enable-ext-control;
+ };
+ tps65090_dcdc2: dcdc2 {
+ ti,enable-ext-control;
+ };
+ tps65090_dcdc3: dcdc3 {
+ ti,enable-ext-control;
+ };
+ tps65090_fet1: fet1 {
+ regulator-name = "vcd_led";
+ };
+ tps65090_fet2: fet2 {
+ regulator-name = "video_mid";
+ regulator-always-on;
+ };
+ tps65090_fet3: fet3 {
+ regulator-name = "wwan_r";
+ regulator-always-on;
+ };
+ tps65090_fet4: fet4 {
+ regulator-name = "sdcard";
+ regulator-always-on;
+ };
+ tps65090_fet5: fet5 {
+ regulator-name = "camout";
+ };
+ tps65090_fet6: fet6 {
+ regulator-name = "lcd_vdd";
+ };
+ tps65090_fet7: fet7 {
+ regulator-name = "video_mid_1a";
+ regulator-always-on;
+ };
+ tps65090_ldo1: ldo1 {
+ };
+ tps65090_ldo2: ldo2 {
+ };
+ };
+
+ charger {
+ compatible = "ti,tps65090-charger";
+ };
+ };
+ };
+ };
+};
+
+&uart_3 {
status = "okay";
- hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&hdmi_hpd_irq>;
- ddc = <&i2c_2>;
};
&usbdrd_phy0 {
@@ -251,3 +441,5 @@
&watchdog {
timeout-sec = <32>;
};
+
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/ge863-pro3.dtsi b/arch/arm/boot/dts/ge863-pro3.dtsi
index 230099bb31c8..0d0e62489d93 100644
--- a/arch/arm/boot/dts/ge863-pro3.dtsi
+++ b/arch/arm/boot/dts/ge863-pro3.dtsi
@@ -19,6 +19,10 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <6000000>;
};
+
+ main_xtal {
+ clock-frequency = <6000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
index 83a5b8685bd9..6cbb62e5c6a9 100644
--- a/arch/arm/boot/dts/hi3620.dtsi
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -33,6 +33,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ enable-method = "hisilicon,hi3620-smp";
cpu@0 {
device_type = "cpu";
diff --git a/arch/arm/boot/dts/hisi-x5hd2-dkb.dts b/arch/arm/boot/dts/hisi-x5hd2-dkb.dts
new file mode 100644
index 000000000000..05b44c272c9a
--- /dev/null
+++ b/arch/arm/boot/dts/hisi-x5hd2-dkb.dts
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013-2014 Linaro Ltd.
+ * Copyright (c) 2013-2014 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include "hisi-x5hd2.dtsi"
+
+/ {
+ model = "Hisilicon HIX5HD2 Development Board";
+ compatible = "hisilicon,hix5hd2";
+
+ chosen {
+ bootargs = "console=ttyAMA0,115200 earlyprintk";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "hisilicon,hix5hd2-smp";
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&l2>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000>;
+ };
+};
+
+&timer0 {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/hisi-x5hd2.dtsi b/arch/arm/boot/dts/hisi-x5hd2.dtsi
new file mode 100644
index 000000000000..f85ba2924ff7
--- /dev/null
+++ b/arch/arm/boot/dts/hisi-x5hd2.dtsi
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2013-2014 Linaro Ltd.
+ * Copyright (c) 2013-2014 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/hix5hd2-clock.h>
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ };
+
+ gic: interrupt-controller@f8a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base */
+ reg = <0xf8a01000 0x1000>, <0xf8a00100 0x100>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges = <0 0xf8000000 0x8000000>;
+
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ timer0: timer@00002000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x00002000 0x1000>;
+ /* timer00 & timer01 */
+ interrupts = <0 24 4>;
+ clocks = <&clock HIX5HD2_FIXED_24M>;
+ status = "disabled";
+ };
+
+ timer1: timer@00a29000 {
+ /*
+ * Only used in NORMAL state, not available ins
+ * SLOW or DOZE state.
+ * The rate is fixed in 24MHz.
+ */
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x00a29000 0x1000>;
+ /* timer10 & timer11 */
+ interrupts = <0 25 4>;
+ clocks = <&clock HIX5HD2_FIXED_24M>;
+ status = "disabled";
+ };
+
+ timer2: timer@00a2a000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x00a2a000 0x1000>;
+ /* timer20 & timer21 */
+ interrupts = <0 26 4>;
+ clocks = <&clock HIX5HD2_FIXED_24M>;
+ status = "disabled";
+ };
+
+ timer3: timer@00a2b000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x00a2b000 0x1000>;
+ /* timer30 & timer31 */
+ interrupts = <0 27 4>;
+ clocks = <&clock HIX5HD2_FIXED_24M>;
+ status = "disabled";
+ };
+
+ timer4: timer@00a81000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x00a81000 0x1000>;
+ /* timer30 & timer31 */
+ interrupts = <0 28 4>;
+ clocks = <&clock HIX5HD2_FIXED_24M>;
+ status = "disabled";
+ };
+
+ uart0: uart@00b00000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x00b00000 0x1000>;
+ interrupts = <0 49 4>;
+ clocks = <&clock HIX5HD2_FIXED_83M>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart@00006000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x00006000 0x1000>;
+ interrupts = <0 50 4>;
+ clocks = <&clock HIX5HD2_FIXED_83M>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart2: uart@00b02000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x00b02000 0x1000>;
+ interrupts = <0 51 4>;
+ clocks = <&clock HIX5HD2_FIXED_83M>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart3: uart@00b03000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x00b03000 0x1000>;
+ interrupts = <0 52 4>;
+ clocks = <&clock HIX5HD2_FIXED_83M>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart4: uart@00b04000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xb04000 0x1000>;
+ interrupts = <0 53 4>;
+ clocks = <&clock HIX5HD2_FIXED_83M>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+ };
+
+ local_timer@00a00600 {
+ compatible = "arm,cortex-a9-twd-timer";
+ reg = <0x00a00600 0x20>;
+ interrupts = <1 13 0xf01>;
+ };
+
+ l2: l2-cache {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a10000 0x100000>;
+ interrupts = <0 15 4>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ sysctrl: system-controller@00000000 {
+ compatible = "hisilicon,sysctrl";
+ reg = <0x00000000 0x1000>;
+ reboot-offset = <0x4>;
+ };
+
+ cpuctrl@00a22000 {
+ compatible = "hisilicon,cpuctrl";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x00a22000 0x2000>;
+ ranges = <0 0x00a22000 0x2000>;
+
+ clock: clock@0 {
+ compatible = "hisilicon,hix5hd2-clock";
+ reg = <0 0x2000>;
+ #clock-cells = <1>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
new file mode 100644
index 000000000000..68d0834a2d1e
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+ model = "Eukrea MBIMXSD25 with the CMO-QVGA Display";
+ compatible = "eukrea,mbimxsd25-baseboard-cmo-qvga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+ cmo_qvga: display {
+ model = "CMO-QVGA";
+ bits-per-pixel = <16>;
+ fsl,pcr = <0xcad08b80>;
+ bus-width = <18>;
+ native-mode = <&qvga_timings>;
+ display-timings {
+ qvga_timings: 320x240 {
+ clock-frequency = <6500000>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <30>;
+ hfront-porch = <38>;
+ vback-porch = <20>;
+ vfront-porch = <3>;
+ hsync-len = <15>;
+ vsync-len = <4>;
+ };
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_lcd_3v3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_lcd_3v3>;
+ regulator-name = "lcd-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&iomuxc {
+ imx25-eukrea-mbimxsd25-baseboard-cmo-qvga {
+ pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
+ fsl,pins = <MX25_PAD_PWM__GPIO_1_26 0x80000000>;
+ };
+ };
+};
+
+&lcdc {
+ display = <&cmo_qvga>;
+ fsl,lpccr = <0x00a903ff>;
+ lcd-supply = <&reg_lcd_3v3>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
new file mode 100644
index 000000000000..8eee2f65fe00
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+ model = "Eukrea MBIMXSD25 with the DVI-SVGA Display";
+ compatible = "eukrea,mbimxsd25-baseboard-dvi-svga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+ dvi_svga: display {
+ model = "DVI-SVGA";
+ bits-per-pixel = <16>;
+ fsl,pcr = <0xfa208b80>;
+ bus-width = <18>;
+ native-mode = <&dvi_svga_timings>;
+ display-timings {
+ dvi_svga_timings: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <75>;
+ hfront-porch = <75>;
+ vback-porch = <7>;
+ vfront-porch = <75>;
+ hsync-len = <7>;
+ vsync-len = <7>;
+ };
+ };
+ };
+};
+
+&lcdc {
+ display = <&dvi_svga>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
new file mode 100644
index 000000000000..447da6263169
--- /dev/null
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "imx25-eukrea-mbimxsd25-baseboard.dts"
+
+/ {
+ model = "Eukrea MBIMXSD25 with the DVI-VGA Display";
+ compatible = "eukrea,mbimxsd25-baseboard-dvi-vga", "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+ dvi_vga: display {
+ model = "DVI-VGA";
+ bits-per-pixel = <16>;
+ fsl,pcr = <0xfa208b80>;
+ bus-width = <18>;
+ native-mode = <&dvi_vga_timings>;
+ display-timings {
+ dvi_vga_timings: 640x480 {
+ clock-frequency = <31250000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <100>;
+ hfront-porch = <100>;
+ vback-porch = <7>;
+ vfront-porch = <100>;
+ hsync-len = <7>;
+ vsync-len = <7>;
+ };
+ };
+ };
+};
+
+&lcdc {
+ display = <&dvi_vga>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
index ad12da38fc92..ed1d0b4578ef 100644
--- a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
+++ b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
@@ -155,7 +155,6 @@
&ssi1 {
codec-handle = <&tlv320aic23>;
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
index c608942b8a3b..9c21b1583762 100644
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ b/arch/arm/boot/dts/imx25-pdk.dts
@@ -233,7 +233,6 @@
&ssi1 {
codec-handle = <&codec>;
- fsl,mode = "i2s-slave";
status = "okay";
};
@@ -249,3 +248,10 @@
dr_mode = "host";
status = "okay";
};
+
+&usbotg {
+ phy_type = "utmi";
+ dr_mode = "otg";
+ external-vbus-divider;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index bb74d9582b7e..c1740396b2c9 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -312,7 +312,7 @@
gpt4: timer@53f84000 {
compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
reg = <0x53f84000 0x4000>;
- clocks = <&clks 9>, <&clks 45>;
+ clocks = <&clks 95>, <&clks 47>;
clock-names = "ipg", "per";
interrupts = <1>;
};
@@ -320,7 +320,7 @@
gpt3: timer@53f88000 {
compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
reg = <0x53f88000 0x4000>;
- clocks = <&clks 9>, <&clks 47>;
+ clocks = <&clks 94>, <&clks 47>;
clock-names = "ipg", "per";
interrupts = <29>;
};
@@ -328,7 +328,7 @@
gpt2: timer@53f8c000 {
compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
reg = <0x53f8c000 0x4000>;
- clocks = <&clks 9>, <&clks 47>;
+ clocks = <&clks 93>, <&clks 47>;
clock-names = "ipg", "per";
interrupts = <53>;
};
@@ -336,7 +336,7 @@
gpt1: timer@53f90000 {
compatible = "fsl,imx25-gpt", "fsl,imx31-gpt";
reg = <0x53f90000 0x4000>;
- clocks = <&clks 9>, <&clks 47>;
+ clocks = <&clks 92>, <&clks 47>;
clock-names = "ipg", "per";
interrupts = <54>;
};
diff --git a/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi b/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
new file mode 100644
index 000000000000..e2242638ea0b
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx27.dtsi"
+
+/ {
+ model = "Eukrea CPUIMX27";
+ compatible = "eukrea,cpuimx27", "fsl,imx27";
+
+ memory {
+ reg = <0xa0000000 0x04000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "simple-bus";
+
+ clk14745600: clock@0 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <14745600>;
+ reg = <0>;
+ };
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pcf8563@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+};
+
+&nfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
+&owire {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_owire>;
+ status = "okay";
+};
+
+&sdhci2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdhc2>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh2>;
+ dr_mode = "host";
+ phy_type = "ulpi";
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ dr_mode = "otg";
+ phy_type = "ulpi";
+ disable-over-current;
+ status = "okay";
+};
+
+&weim {
+ status = "okay";
+
+ nor: nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0 0x00000000 0x04000000>;
+ bank-width = <2>;
+ linux,mtd-name = "physmap-flash.0";
+ fsl,weim-cs-timing = <0x00008f03 0xa0330d01 0x002208c0>;
+ };
+
+ uart8250@3,200000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart8250_1>;
+ compatible = "ns8250";
+ clocks = <&clk14745600>;
+ fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+ interrupts = <&gpio2 23 IRQ_TYPE_LEVEL_LOW>;
+ reg = <3 0x200000 0x1000>;
+ reg-shift = <1>;
+ reg-io-width = <1>;
+ no-loopback-test;
+ };
+
+ uart8250@3,400000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart8250_2>;
+ compatible = "ns8250";
+ clocks = <&clk14745600>;
+ fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+ interrupts = <&gpio2 22 IRQ_TYPE_LEVEL_LOW>;
+ reg = <3 0x400000 0x1000>;
+ reg-shift = <1>;
+ reg-io-width = <1>;
+ no-loopback-test;
+ };
+
+ uart8250@3,800000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart8250_3>;
+ compatible = "ns8250";
+ clocks = <&clk14745600>;
+ fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+ interrupts = <&gpio2 27 IRQ_TYPE_LEVEL_LOW>;
+ reg = <3 0x800000 0x1000>;
+ reg-shift = <1>;
+ reg-io-width = <1>;
+ no-loopback-test;
+ };
+
+ uart8250@3,1000000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart8250_4>;
+ compatible = "ns8250";
+ clocks = <&clk14745600>;
+ fsl,weim-cs-timing = <0x0000d603 0x0d1d0d01 0x00d20000>;
+ interrupts = <&gpio2 30 IRQ_TYPE_LEVEL_LOW>;
+ reg = <3 0x1000000 0x1000>;
+ reg-shift = <1>;
+ reg-io-width = <1>;
+ no-loopback-test;
+ };
+};
+
+&iomuxc {
+ imx27-eukrea-cpuimx27 {
+ pinctrl_fec: fecgrp {
+ fsl,pins = <
+ MX27_PAD_SD3_CMD__FEC_TXD0 0x0
+ MX27_PAD_SD3_CLK__FEC_TXD1 0x0
+ MX27_PAD_ATA_DATA0__FEC_TXD2 0x0
+ MX27_PAD_ATA_DATA1__FEC_TXD3 0x0
+ MX27_PAD_ATA_DATA2__FEC_RX_ER 0x0
+ MX27_PAD_ATA_DATA3__FEC_RXD1 0x0
+ MX27_PAD_ATA_DATA4__FEC_RXD2 0x0
+ MX27_PAD_ATA_DATA5__FEC_RXD3 0x0
+ MX27_PAD_ATA_DATA6__FEC_MDIO 0x0
+ MX27_PAD_ATA_DATA7__FEC_MDC 0x0
+ MX27_PAD_ATA_DATA8__FEC_CRS 0x0
+ MX27_PAD_ATA_DATA9__FEC_TX_CLK 0x0
+ MX27_PAD_ATA_DATA10__FEC_RXD0 0x0
+ MX27_PAD_ATA_DATA11__FEC_RX_DV 0x0
+ MX27_PAD_ATA_DATA12__FEC_RX_CLK 0x0
+ MX27_PAD_ATA_DATA13__FEC_COL 0x0
+ MX27_PAD_ATA_DATA14__FEC_TX_ER 0x0
+ MX27_PAD_ATA_DATA15__FEC_TX_EN 0x0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX27_PAD_I2C_DATA__I2C_DATA 0x0
+ MX27_PAD_I2C_CLK__I2C_CLK 0x0
+ >;
+ };
+
+ pinctrl_nfc: nfcgrp {
+ fsl,pins = <
+ MX27_PAD_NFRB__NFRB 0x0
+ MX27_PAD_NFCLE__NFCLE 0x0
+ MX27_PAD_NFWP_B__NFWP_B 0x0
+ MX27_PAD_NFCE_B__NFCE_B 0x0
+ MX27_PAD_NFALE__NFALE 0x0
+ MX27_PAD_NFRE_B__NFRE_B 0x0
+ MX27_PAD_NFWE_B__NFWE_B 0x0
+ >;
+ };
+
+ pinctrl_owire: owiregrp {
+ fsl,pins = <
+ MX27_PAD_RTCK__OWIRE 0x0
+ >;
+ };
+
+ pinctrl_sdhc2: sdhc2grp {
+ fsl,pins = <
+ MX27_PAD_SD2_CLK__SD2_CLK 0x0
+ MX27_PAD_SD2_CMD__SD2_CMD 0x0
+ MX27_PAD_SD2_D0__SD2_D0 0x0
+ MX27_PAD_SD2_D1__SD2_D1 0x0
+ MX27_PAD_SD2_D2__SD2_D2 0x0
+ MX27_PAD_SD2_D3__SD2_D3 0x0
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX27_PAD_USBH1_TXDM__UART4_TXD 0x0
+ MX27_PAD_USBH1_RXDP__UART4_RXD 0x0
+ MX27_PAD_USBH1_TXDP__UART4_CTS 0x0
+ MX27_PAD_USBH1_FS__UART4_RTS 0x0
+ >;
+ };
+
+ pinctrl_uart8250_1: uart82501grp {
+ fsl,pins = <
+ MX27_PAD_USB_PWR__GPIO2_23 0x0
+ >;
+ };
+
+ pinctrl_uart8250_2: uart82502grp {
+ fsl,pins = <
+ MX27_PAD_USBH1_SUSP__GPIO2_22 0x0
+ >;
+ };
+
+ pinctrl_uart8250_3: uart82503grp {
+ fsl,pins = <
+ MX27_PAD_USBH1_OE_B__GPIO2_27 0x0
+ >;
+ };
+
+ pinctrl_uart8250_4: uart82504grp {
+ fsl,pins = <
+ MX27_PAD_USBH1_RXDM__GPIO2_30 0x0
+ >;
+ };
+
+ pinctrl_usbh2: usbh2grp {
+ fsl,pins = <
+ MX27_PAD_USBH2_CLK__USBH2_CLK 0x0
+ MX27_PAD_USBH2_DIR__USBH2_DIR 0x0
+ MX27_PAD_USBH2_NXT__USBH2_NXT 0x0
+ MX27_PAD_USBH2_STP__USBH2_STP 0x0
+ MX27_PAD_CSPI2_SCLK__USBH2_DATA0 0x0
+ MX27_PAD_CSPI2_MOSI__USBH2_DATA1 0x0
+ MX27_PAD_CSPI2_MISO__USBH2_DATA2 0x0
+ MX27_PAD_CSPI2_SS1__USBH2_DATA3 0x0
+ MX27_PAD_CSPI2_SS2__USBH2_DATA4 0x0
+ MX27_PAD_CSPI1_SS2__USBH2_DATA5 0x0
+ MX27_PAD_CSPI2_SS0__USBH2_DATA6 0x0
+ MX27_PAD_USBH2_DATA7__USBH2_DATA7 0x0
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX27_PAD_USBOTG_CLK__USBOTG_CLK 0x0
+ MX27_PAD_USBOTG_DIR__USBOTG_DIR 0x0
+ MX27_PAD_USBOTG_NXT__USBOTG_NXT 0x0
+ MX27_PAD_USBOTG_STP__USBOTG_STP 0x0
+ MX27_PAD_USBOTG_DATA0__USBOTG_DATA0 0x0
+ MX27_PAD_USBOTG_DATA1__USBOTG_DATA1 0x0
+ MX27_PAD_USBOTG_DATA2__USBOTG_DATA2 0x0
+ MX27_PAD_USBOTG_DATA3__USBOTG_DATA3 0x0
+ MX27_PAD_USBOTG_DATA4__USBOTG_DATA4 0x0
+ MX27_PAD_USBOTG_DATA5__USBOTG_DATA5 0x0
+ MX27_PAD_USBOTG_DATA6__USBOTG_DATA6 0x0
+ MX27_PAD_USBOTG_DATA7__USBOTG_DATA7 0x0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
new file mode 100644
index 000000000000..2ab65fc4c1e1
--- /dev/null
+++ b/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx27-eukrea-cpuimx27.dtsi"
+
+/ {
+ model = "Eukrea MBIMXSD27";
+ compatible = "eukrea,mbimxsd27-baseboard", "eukrea,cpuimx27", "fsl,imx27";
+
+ display0: CMO-QVGA {
+ model = "CMO-QVGA";
+ native-mode = <&timing0>;
+ bits-per-pixel = <16>;
+ fsl,pcr = <0xfad08b80>;
+
+ display-timings {
+ timing0: 320x240 {
+ clock-frequency = <6500000>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <20>;
+ hsync-len = <30>;
+ hfront-porch = <38>;
+ vback-porch = <4>;
+ vsync-len = <3>;
+ vfront-porch = <15>;
+ };
+ };
+ };
+
+ backlight {
+ compatible = "gpio-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ gpios = <&gpio5 5 GPIO_ACTIVE_HIGH>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpioleds>;
+
+ led1 {
+ label = "system::live";
+ gpios = <&gpio6 16 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led2 {
+ label = "system::user";
+ gpios = <&gpio6 19 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "simple-bus";
+
+ reg_lcd: regulator@0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcdreg>;
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "LCD";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+};
+
+&cspi1 {
+ pinctrl-0 = <&pinctrl_cspi1>;
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ ads7846 {
+ compatible = "ti,ads7846";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_touch>;
+ reg = <0>;
+ interrupts = <&gpio4 25 IRQ_TYPE_LEVEL_LOW>;
+ spi-cpol;
+ spi-max-frequency = <1500000>;
+ ti,keep-vref-on;
+ };
+};
+
+&fb {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_imxfb>;
+ display = <&display0>;
+ lcd-supply = <&reg_lcd>;
+ fsl,dmacr = <0x00040060>;
+ fsl,lscr1 = <0x00120300>;
+ fsl,lpccr = <0x00a903ff>;
+ status = "okay";
+};
+
+&i2c1 {
+ codec: codec@1a {
+ compatible = "ti,tlv320aic23";
+ reg = <0x1a>;
+ };
+};
+
+&kpp {
+ linux,keymap = <
+ MATRIX_KEY(0, 0, KEY_UP)
+ MATRIX_KEY(0, 1, KEY_DOWN)
+ MATRIX_KEY(1, 0, KEY_RIGHT)
+ MATRIX_KEY(1, 1, KEY_LEFT)
+ >;
+ status = "okay";
+};
+
+&sdhci1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdhc1>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ssi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssi1>;
+ codec-handle = <&codec>;
+ status = "okay";
+};
+
+&uart1 {
+ fsl,uart-has-rtscts;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ fsl,uart-has-rtscts;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&uart3 {
+ fsl,uart-has-rtscts;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&iomuxc {
+ imx27-eukrea-cpuimx27-baseboard {
+ pinctrl_cspi1: cspi1grp {
+ fsl,pins = <
+ MX27_PAD_CSPI1_MISO__CSPI1_MISO 0x0
+ MX27_PAD_CSPI1_MOSI__CSPI1_MOSI 0x0
+ MX27_PAD_CSPI1_SCLK__CSPI1_SCLK 0x0
+ MX27_PAD_CSPI1_SS0__GPIO4_28 0x0 /* CS0 */
+ >;
+ };
+
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX27_PAD_PWMO__GPIO5_5 0x0
+ >;
+ };
+
+ pinctrl_gpioleds: gpioledsgrp {
+ fsl,pins = <
+ MX27_PAD_PC_PWRON__GPIO6_16 0x0
+ MX27_PAD_PC_CD2_B__GPIO6_19 0x0
+ >;
+ };
+
+ pinctrl_imxfb: imxfbgrp {
+ fsl,pins = <
+ MX27_PAD_LD0__LD0 0x0
+ MX27_PAD_LD1__LD1 0x0
+ MX27_PAD_LD2__LD2 0x0
+ MX27_PAD_LD3__LD3 0x0
+ MX27_PAD_LD4__LD4 0x0
+ MX27_PAD_LD5__LD5 0x0
+ MX27_PAD_LD6__LD6 0x0
+ MX27_PAD_LD7__LD7 0x0
+ MX27_PAD_LD8__LD8 0x0
+ MX27_PAD_LD9__LD9 0x0
+ MX27_PAD_LD10__LD10 0x0
+ MX27_PAD_LD11__LD11 0x0
+ MX27_PAD_LD12__LD12 0x0
+ MX27_PAD_LD13__LD13 0x0
+ MX27_PAD_LD14__LD14 0x0
+ MX27_PAD_LD15__LD15 0x0
+ MX27_PAD_LD16__LD16 0x0
+ MX27_PAD_LD17__LD17 0x0
+ MX27_PAD_CONTRAST__CONTRAST 0x0
+ MX27_PAD_OE_ACD__OE_ACD 0x0
+ MX27_PAD_HSYNC__HSYNC 0x0
+ MX27_PAD_VSYNC__VSYNC 0x0
+ >;
+ };
+
+ pinctrl_lcdreg: lcdreggrp {
+ fsl,pins = <
+ MX27_PAD_CLS__GPIO1_25 0x0
+ >;
+ };
+
+ pinctrl_sdhc1: sdhc1grp {
+ fsl,pins = <
+ MX27_PAD_SD1_CLK__SD1_CLK 0x0
+ MX27_PAD_SD1_CMD__SD1_CMD 0x0
+ MX27_PAD_SD1_D0__SD1_D0 0x0
+ MX27_PAD_SD1_D1__SD1_D1 0x0
+ MX27_PAD_SD1_D2__SD1_D2 0x0
+ MX27_PAD_SD1_D3__SD1_D3 0x0
+ >;
+ };
+
+ pinctrl_ssi1: ssi1grp {
+ fsl,pins = <
+ MX27_PAD_SSI4_CLK__SSI4_CLK 0x0
+ MX27_PAD_SSI4_FS__SSI4_FS 0x0
+ MX27_PAD_SSI4_RXDAT__SSI4_RXDAT 0x1
+ MX27_PAD_SSI4_TXDAT__SSI4_TXDAT 0x1
+ >;
+ };
+
+ pinctrl_touch: touchgrp {
+ fsl,pins = <
+ MX27_PAD_CSPI1_RDY__GPIO4_25 0x0 /* IRQ */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX27_PAD_UART1_TXD__UART1_TXD 0x0
+ MX27_PAD_UART1_RXD__UART1_RXD 0x0
+ MX27_PAD_UART1_CTS__UART1_CTS 0x0
+ MX27_PAD_UART1_RTS__UART1_RTS 0x0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX27_PAD_UART2_TXD__UART2_TXD 0x0
+ MX27_PAD_UART2_RXD__UART2_RXD 0x0
+ MX27_PAD_UART2_CTS__UART2_CTS 0x0
+ MX27_PAD_UART2_RTS__UART2_RTS 0x0
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX27_PAD_UART3_TXD__UART3_TXD 0x0
+ MX27_PAD_UART3_RXD__UART3_RXD 0x0
+ MX27_PAD_UART3_CTS__UART3_CTS 0x0
+ MX27_PAD_UART3_RTS__UART3_RTS 0x0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx27-pdk.dts b/arch/arm/boot/dts/imx27-pdk.dts
index 4c317716b510..49450dbbcab8 100644
--- a/arch/arm/boot/dts/imx27-pdk.dts
+++ b/arch/arm/boot/dts/imx27-pdk.dts
@@ -28,7 +28,7 @@
usbphy0: usbphy@0 {
compatible = "usb-nop-xceiv";
reg = <0>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX27_CLK_DUMMY>;
clock-names = "main_clk";
};
};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
index fe02bc7a24fd..538568b0de26 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -61,7 +61,7 @@
compatible = "usb-nop-xceiv";
reg = <2>;
vcc-supply = <&reg_5v0>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX27_CLK_DUMMY>;
clock-names = "main_clk";
};
};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
index 31e9f7049f73..b4e955e3be8d 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
+++ b/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
@@ -51,7 +51,7 @@
compatible = "usb-nop-xceiv";
reg = <0>;
vcc-supply = <&sw3_reg>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX27_CLK_DUMMY>;
clock-names = "main_clk";
};
};
@@ -310,7 +310,6 @@
&ssi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ssi1>;
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx27-pinfunc.h b/arch/arm/boot/dts/imx27-pinfunc.h
index f5387b4de577..597bb5f74dcc 100644
--- a/arch/arm/boot/dts/imx27-pinfunc.h
+++ b/arch/arm/boot/dts/imx27-pinfunc.h
@@ -101,14 +101,6 @@
#define MX27_PAD_CONTRAST__GPIO1_30 0x1e 0x032
#define MX27_PAD_OE_ACD__OE_ACD 0x1f 0x004
#define MX27_PAD_OE_ACD__GPIO1_31 0x1f 0x032
-#define MX27_PAD_UNUSED0__UNUSED0 0x20 0x004
-#define MX27_PAD_UNUSED0__GPIO2_0 0x20 0x032
-#define MX27_PAD_UNUSED1__UNUSED1 0x21 0x004
-#define MX27_PAD_UNUSED1__GPIO2_1 0x21 0x032
-#define MX27_PAD_UNUSED2__UNUSED2 0x22 0x004
-#define MX27_PAD_UNUSED2__GPIO2_2 0x22 0x032
-#define MX27_PAD_UNUSED3__UNUSED3 0x23 0x004
-#define MX27_PAD_UNUSED3__GPIO2_3 0x23 0x032
#define MX27_PAD_SD2_D0__SD2_D0 0x24 0x004
#define MX27_PAD_SD2_D0__MSHC_DATA0 0x24 0x005
#define MX27_PAD_SD2_D0__GPIO2_4 0x24 0x032
@@ -183,16 +175,6 @@
#define MX27_PAD_USBH1_RXDP__USBH1_RXDP 0x3f 0x004
#define MX27_PAD_USBH1_RXDP__UART4_RXD 0x3f 0x001
#define MX27_PAD_USBH1_RXDP__GPIO2_31 0x3f 0x032
-#define MX27_PAD_UNUSED4__UNUSED4 0x40 0x004
-#define MX27_PAD_UNUSED4__GPIO3_0 0x40 0x032
-#define MX27_PAD_UNUSED5__UNUSED5 0x41 0x004
-#define MX27_PAD_UNUSED5__GPIO3_1 0x41 0x032
-#define MX27_PAD_UNUSED6__UNUSED6 0x42 0x004
-#define MX27_PAD_UNUSED6__GPIO3_2 0x42 0x032
-#define MX27_PAD_UNUSED7__UNUSED7 0x43 0x004
-#define MX27_PAD_UNUSED7__GPIO3_3 0x43 0x032
-#define MX27_PAD_UNUSED8__UNUSED8 0x44 0x004
-#define MX27_PAD_UNUSED8__GPIO3_4 0x44 0x032
#define MX27_PAD_I2C2_SDA__I2C2_SDA 0x45 0x004
#define MX27_PAD_I2C2_SDA__GPIO3_5 0x45 0x032
#define MX27_PAD_I2C2_SCL__I2C2_SCL 0x46 0x004
@@ -422,18 +404,6 @@
#define MX27_PAD_USBOTG_CLK__GPIO5_24 0x98 0x032
#define MX27_PAD_USBOTG_DATA7__USBOTG_DATA7 0x99 0x004
#define MX27_PAD_USBOTG_DATA7__GPIO5_25 0x99 0x032
-#define MX27_PAD_UNUSED9__UNUSED9 0x9a 0x004
-#define MX27_PAD_UNUSED9__GPIO5_26 0x9a 0x032
-#define MX27_PAD_UNUSED10__UNUSED10 0x9b 0x004
-#define MX27_PAD_UNUSED10__GPIO5_27 0x9b 0x032
-#define MX27_PAD_UNUSED11__UNUSED11 0x9c 0x004
-#define MX27_PAD_UNUSED11__GPIO5_28 0x9c 0x032
-#define MX27_PAD_UNUSED12__UNUSED12 0x9d 0x004
-#define MX27_PAD_UNUSED12__GPIO5_29 0x9d 0x032
-#define MX27_PAD_UNUSED13__UNUSED13 0x9e 0x004
-#define MX27_PAD_UNUSED13__GPIO5_30 0x9e 0x032
-#define MX27_PAD_UNUSED14__UNUSED14 0x9f 0x004
-#define MX27_PAD_UNUSED14__GPIO5_31 0x9f 0x032
#define MX27_PAD_NFRB__NFRB 0xa0 0x000
#define MX27_PAD_NFRB__ETMTRACEPKT3 0xa0 0x005
#define MX27_PAD_NFRB__GPIO6_0 0xa0 0x032
@@ -506,21 +476,5 @@
#define MX27_PAD_ATA_DATA15__ETMTRACEPKT4 0xb7 0x005
#define MX27_PAD_ATA_DATA15__FEC_TX_EN 0xb7 0x006
#define MX27_PAD_ATA_DATA15__GPIO6_23 0xb7 0x032
-#define MX27_PAD_UNUSED15__UNUSED15 0xb8 0x004
-#define MX27_PAD_UNUSED15__GPIO6_24 0xb8 0x032
-#define MX27_PAD_UNUSED16__UNUSED16 0xb9 0x004
-#define MX27_PAD_UNUSED16__GPIO6_25 0xb9 0x032
-#define MX27_PAD_UNUSED17__UNUSED17 0xba 0x004
-#define MX27_PAD_UNUSED17__GPIO6_26 0xba 0x032
-#define MX27_PAD_UNUSED18__UNUSED18 0xbb 0x004
-#define MX27_PAD_UNUSED18__GPIO6_27 0xbb 0x032
-#define MX27_PAD_UNUSED19__UNUSED19 0xbc 0x004
-#define MX27_PAD_UNUSED19__GPIO6_28 0xbc 0x032
-#define MX27_PAD_UNUSED20__UNUSED20 0xbd 0x004
-#define MX27_PAD_UNUSED20__GPIO6_29 0xbd 0x032
-#define MX27_PAD_UNUSED21__UNUSED21 0xbe 0x004
-#define MX27_PAD_UNUSED21__GPIO6_30 0xbe 0x032
-#define MX27_PAD_UNUSED22__UNUSED22 0xbf 0x004
-#define MX27_PAD_UNUSED22__GPIO6_31 0xbf 0x032
#endif /* __DTS_IMX27_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index a75555c39533..107d713e1cbe 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -11,9 +11,11 @@
#include "skeleton.dtsi"
#include "imx27-pinfunc.h"
+
+#include <dt-bindings/clock/imx27-clock.h>
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/gpio/gpio.h>
/ {
aliases {
@@ -68,7 +70,7 @@
399000 1450000
>;
clock-latency = <62500>;
- clocks = <&clks 18>;
+ clocks = <&clks IMX27_CLK_CPU_DIV>;
voltage-tolerance = <5>;
};
};
@@ -91,7 +93,8 @@
compatible = "fsl,imx27-dma";
reg = <0x10001000 0x1000>;
interrupts = <32>;
- clocks = <&clks 50>, <&clks 70>;
+ clocks = <&clks IMX27_CLK_DMA_IPG_GATE>,
+ <&clks IMX27_CLK_DMA_AHB_GATE>;
clock-names = "ipg", "ahb";
#dma-cells = <1>;
#dma-channels = <16>;
@@ -101,14 +104,15 @@
compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
reg = <0x10002000 0x1000>;
interrupts = <27>;
- clocks = <&clks 74>;
+ clocks = <&clks IMX27_CLK_WDOG_IPG_GATE>;
};
gpt1: timer@10003000 {
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x10003000 0x1000>;
interrupts = <26>;
- clocks = <&clks 46>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT1_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -116,7 +120,8 @@
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x10004000 0x1000>;
interrupts = <25>;
- clocks = <&clks 45>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT2_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -124,7 +129,8 @@
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x10005000 0x1000>;
interrupts = <24>;
- clocks = <&clks 44>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT3_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -133,7 +139,8 @@
compatible = "fsl,imx27-pwm";
reg = <0x10006000 0x1000>;
interrupts = <23>;
- clocks = <&clks 34>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_PWM_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -141,14 +148,14 @@
compatible = "fsl,imx27-kpp", "fsl,imx21-kpp";
reg = <0x10008000 0x1000>;
interrupts = <21>;
- clocks = <&clks 37>;
+ clocks = <&clks IMX27_CLK_KPP_IPG_GATE>;
status = "disabled";
};
owire: owire@10009000 {
compatible = "fsl,imx27-owire", "fsl,imx21-owire";
reg = <0x10009000 0x1000>;
- clocks = <&clks 35>;
+ clocks = <&clks IMX27_CLK_OWIRE_IPG_GATE>;
status = "disabled";
};
@@ -156,7 +163,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1000a000 0x1000>;
interrupts = <20>;
- clocks = <&clks 81>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART1_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -165,7 +173,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1000b000 0x1000>;
interrupts = <19>;
- clocks = <&clks 80>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART2_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -174,7 +183,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1000c000 0x1000>;
interrupts = <18>;
- clocks = <&clks 79>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART3_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -183,7 +193,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1000d000 0x1000>;
interrupts = <17>;
- clocks = <&clks 78>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART4_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -194,7 +205,8 @@
compatible = "fsl,imx27-cspi";
reg = <0x1000e000 0x1000>;
interrupts = <16>;
- clocks = <&clks 53>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_CSPI1_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -205,7 +217,8 @@
compatible = "fsl,imx27-cspi";
reg = <0x1000f000 0x1000>;
interrupts = <15>;
- clocks = <&clks 52>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_CSPI2_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -215,7 +228,7 @@
compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
reg = <0x10010000 0x1000>;
interrupts = <14>;
- clocks = <&clks 26>;
+ clocks = <&clks IMX27_CLK_SSI1_IPG_GATE>;
dmas = <&dma 12>, <&dma 13>, <&dma 14>, <&dma 15>;
dma-names = "rx0", "tx0", "rx1", "tx1";
fsl,fifo-depth = <8>;
@@ -227,7 +240,7 @@
compatible = "fsl,imx27-ssi", "fsl,imx21-ssi";
reg = <0x10011000 0x1000>;
interrupts = <13>;
- clocks = <&clks 25>;
+ clocks = <&clks IMX27_CLK_SSI2_IPG_GATE>;
dmas = <&dma 8>, <&dma 9>, <&dma 10>, <&dma 11>;
dma-names = "rx0", "tx0", "rx1", "tx1";
fsl,fifo-depth = <8>;
@@ -240,7 +253,7 @@
compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
reg = <0x10012000 0x1000>;
interrupts = <12>;
- clocks = <&clks 40>;
+ clocks = <&clks IMX27_CLK_I2C1_IPG_GATE>;
status = "disabled";
};
@@ -248,7 +261,8 @@
compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
reg = <0x10013000 0x1000>;
interrupts = <11>;
- clocks = <&clks 30>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_SDHC1_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
dmas = <&dma 7>;
dma-names = "rx-tx";
@@ -259,7 +273,8 @@
compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
reg = <0x10014000 0x1000>;
interrupts = <10>;
- clocks = <&clks 29>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_SDHC2_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
dmas = <&dma 6>;
dma-names = "rx-tx";
@@ -276,6 +291,7 @@
gpio1: gpio@10015000 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015000 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -286,6 +302,7 @@
gpio2: gpio@10015100 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015100 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -296,6 +313,7 @@
gpio3: gpio@10015200 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015200 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -306,6 +324,7 @@
gpio4: gpio@10015300 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015300 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -316,6 +335,7 @@
gpio5: gpio@10015400 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015400 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -326,6 +346,7 @@
gpio6: gpio@10015500 {
compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
reg = <0x10015500 0x100>;
+ clocks = <&clks IMX27_CLK_GPIO_IPG_GATE>;
interrupts = <8>;
gpio-controller;
#gpio-cells = <2>;
@@ -337,7 +358,7 @@
audmux: audmux@10016000 {
compatible = "fsl,imx27-audmux", "fsl,imx21-audmux";
reg = <0x10016000 0x1000>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX27_CLK_DUMMY>;
clock-names = "audmux";
status = "disabled";
};
@@ -348,7 +369,8 @@
compatible = "fsl,imx27-cspi";
reg = <0x10017000 0x1000>;
interrupts = <6>;
- clocks = <&clks 51>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_CSPI3_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -357,7 +379,8 @@
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x10019000 0x1000>;
interrupts = <4>;
- clocks = <&clks 43>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT4_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -365,7 +388,8 @@
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x1001a000 0x1000>;
interrupts = <3>;
- clocks = <&clks 42>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT5_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
@@ -373,7 +397,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1001b000 0x1000>;
interrupts = <49>;
- clocks = <&clks 77>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART5_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -382,7 +407,8 @@
compatible = "fsl,imx27-uart", "fsl,imx21-uart";
reg = <0x1001c000 0x1000>;
interrupts = <48>;
- clocks = <&clks 78>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_UART6_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -393,7 +419,7 @@
compatible = "fsl,imx27-i2c", "fsl,imx21-i2c";
reg = <0x1001d000 0x1000>;
interrupts = <1>;
- clocks = <&clks 39>;
+ clocks = <&clks IMX27_CLK_I2C2_IPG_GATE>;
status = "disabled";
};
@@ -401,7 +427,8 @@
compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
reg = <0x1001e000 0x1000>;
interrupts = <9>;
- clocks = <&clks 28>, <&clks 60>;
+ clocks = <&clks IMX27_CLK_SDHC3_IPG_GATE>,
+ <&clks IMX27_CLK_PER2_GATE>;
clock-names = "ipg", "per";
dmas = <&dma 36>;
dma-names = "rx-tx";
@@ -412,7 +439,8 @@
compatible = "fsl,imx27-gpt", "fsl,imx1-gpt";
reg = <0x1001f000 0x1000>;
interrupts = <2>;
- clocks = <&clks 41>, <&clks 61>;
+ clocks = <&clks IMX27_CLK_GPT6_IPG_GATE>,
+ <&clks IMX27_CLK_PER1_GATE>;
clock-names = "ipg", "per";
};
};
@@ -428,7 +456,9 @@
compatible = "fsl,imx27-fb", "fsl,imx21-fb";
interrupts = <61>;
reg = <0x10021000 0x1000>;
- clocks = <&clks 36>, <&clks 65>, <&clks 59>;
+ clocks = <&clks IMX27_CLK_LCDC_IPG_GATE>,
+ <&clks IMX27_CLK_LCDC_AHB_GATE>,
+ <&clks IMX27_CLK_PER3_GATE>;
clock-names = "ipg", "ahb", "per";
status = "disabled";
};
@@ -437,7 +467,8 @@
compatible = "fsl,imx27-vpu";
reg = <0x10023000 0x0200>;
interrupts = <53>;
- clocks = <&clks 57>, <&clks 66>;
+ clocks = <&clks IMX27_CLK_VPU_BAUD_GATE>,
+ <&clks IMX27_CLK_VPU_AHB_GATE>;
clock-names = "per", "ahb";
iram = <&iram>;
};
@@ -446,7 +477,7 @@
compatible = "fsl,imx27-usb";
reg = <0x10024000 0x200>;
interrupts = <56>;
- clocks = <&clks 75>;
+ clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
fsl,usbmisc = <&usbmisc 0>;
status = "disabled";
};
@@ -455,7 +486,7 @@
compatible = "fsl,imx27-usb";
reg = <0x10024200 0x200>;
interrupts = <54>;
- clocks = <&clks 75>;
+ clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
fsl,usbmisc = <&usbmisc 1>;
status = "disabled";
};
@@ -464,7 +495,7 @@
compatible = "fsl,imx27-usb";
reg = <0x10024400 0x200>;
interrupts = <55>;
- clocks = <&clks 75>;
+ clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
fsl,usbmisc = <&usbmisc 2>;
status = "disabled";
};
@@ -473,14 +504,15 @@
#index-cells = <1>;
compatible = "fsl,imx27-usbmisc";
reg = <0x10024600 0x200>;
- clocks = <&clks 62>;
+ clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
};
sahara2: sahara@10025000 {
compatible = "fsl,imx27-sahara";
reg = <0x10025000 0x1000>;
interrupts = <59>;
- clocks = <&clks 32>, <&clks 64>;
+ clocks = <&clks IMX27_CLK_SAHARA_IPG_GATE>,
+ <&clks IMX27_CLK_SAHARA_AHB_GATE>;
clock-names = "ipg", "ahb";
};
@@ -494,14 +526,15 @@
compatible = "fsl,imx27-iim";
reg = <0x10028000 0x1000>;
interrupts = <62>;
- clocks = <&clks 38>;
+ clocks = <&clks IMX27_CLK_IIM_IPG_GATE>;
};
fec: ethernet@1002b000 {
compatible = "fsl,imx27-fec";
reg = <0x1002b000 0x4000>;
interrupts = <50>;
- clocks = <&clks 48>, <&clks 67>;
+ clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
+ <&clks IMX27_CLK_FEC_AHB_GATE>;
clock-names = "ipg", "ahb";
status = "disabled";
};
@@ -513,7 +546,7 @@
compatible = "fsl,imx27-nand";
reg = <0xd8000000 0x1000>;
interrupts = <29>;
- clocks = <&clks 54>;
+ clocks = <&clks IMX27_CLK_NFC_BAUD_GATE>;
status = "disabled";
};
@@ -522,7 +555,7 @@
#size-cells = <1>;
compatible = "fsl,imx27-weim";
reg = <0xd8002000 0x1000>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX27_CLK_EMI_AHB_GATE>;
ranges = <
0 0 0xc0000000 0x08000000
1 0 0xc8000000 0x08000000
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index ae7c3390e65a..b04b6b8850a7 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -53,6 +53,17 @@
fsl,pull-up = <MXS_PULL_DISABLE>;
};
+ mmc_pwr_cfa10036: mmc_pwr_cfa10036@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ 0x31c3 /*
+ MX28_PAD_PWM3__GPIO_3_28 */
+ >;
+ fsl,drive-strength = <0>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <0>;
+ };
+
};
ssp0: ssp@80010000 {
@@ -60,6 +71,7 @@
pinctrl-names = "default";
pinctrl-0 = <&mmc0_4bit_pins_a
&mmc0_cd_cfg &mmc0_sck_cfg>;
+ vmmc-supply = <&reg_vddio_sd0>;
bus-width = <4>;
status = "okay";
};
@@ -116,4 +128,14 @@
default-state = "on";
};
};
+
+ reg_vddio_sd0: vddio-sd0 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc_pwr_cfa10036>;
+ regulator-name = "vddio-sd0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 28 0>;
+ };
};
diff --git a/arch/arm/boot/dts/imx28-m28.dtsi b/arch/arm/boot/dts/imx28-m28.dtsi
new file mode 100644
index 000000000000..759cc56253dd
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-m28.dtsi
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28.dtsi"
+
+/ {
+ model = "DENX M28";
+ compatible = "denx,m28", "fsl,imx28";
+
+ memory {
+ reg = <0x40000000 0x08000000>;
+ };
+
+ apb@80000000 {
+ apbh@80000000 {
+ gpmi-nand@8000c000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+ status = "okay";
+
+ partition@0 {
+ label = "bootloader";
+ reg = <0x00000000 0x00300000>;
+ read-only;
+ };
+
+ partition@1 {
+ label = "environment";
+ reg = <0x00300000 0x00080000>;
+ };
+
+ partition@2 {
+ label = "redundant-environment";
+ reg = <0x00380000 0x00080000>;
+ };
+
+ partition@3 {
+ label = "kernel";
+ reg = <0x00400000 0x00400000>;
+ };
+
+ partition@4 {
+ label = "filesystem";
+ reg = <0x00800000 0x0f800000>;
+ };
+ };
+ };
+
+ apbx@80040000 {
+ i2c0: i2c@80058000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ rtc: rtc@68 {
+ compatible = "stm,m41t62";
+ reg = <0x68>;
+ };
+ };
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3p3v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index f0ad7b9b9d9a..b3c09ae3b928 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -10,52 +10,14 @@
*/
/dts-v1/;
-#include "imx28.dtsi"
+#include "imx28-m28.dtsi"
/ {
model = "DENX M28EVK";
compatible = "denx,m28evk", "fsl,imx28";
- memory {
- reg = <0x40000000 0x08000000>;
- };
-
apb@80000000 {
apbh@80000000 {
- gpmi-nand@8000c000 {
- #address-cells = <1>;
- #size-cells = <1>;
- pinctrl-names = "default";
- pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
- status = "okay";
-
- partition@0 {
- label = "bootloader";
- reg = <0x00000000 0x00300000>;
- read-only;
- };
-
- partition@1 {
- label = "environment";
- reg = <0x00300000 0x00080000>;
- };
-
- partition@2 {
- label = "redundant-environment";
- reg = <0x00380000 0x00080000>;
- };
-
- partition@3 {
- label = "kernel";
- reg = <0x00400000 0x00400000>;
- };
-
- partition@4 {
- label = "filesystem";
- reg = <0x00800000 0x0f800000>;
- };
- };
-
ssp0: ssp@80010000 {
compatible = "fsl,imx28-mmc";
pinctrl-names = "default";
@@ -175,10 +137,6 @@
};
i2c0: i2c@80058000 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
-
sgtl5000: codec@0a {
compatible = "fsl,sgtl5000";
reg = <0x0a>;
@@ -192,11 +150,6 @@
reg = <0x51>;
pagesize = <32>;
};
-
- rtc: rtc@68 {
- compatible = "stm,m41t62";
- reg = <0x68>;
- };
};
lradc@80050000 {
@@ -284,19 +237,6 @@
};
regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- reg_3p3v: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
reg_vddio_sd0: regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
diff --git a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
index f04ae91eea89..75b036700d31 100644
--- a/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
+++ b/arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts
@@ -133,7 +133,6 @@
&ssi1 {
codec-handle = <&tlv320aic23>;
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
index 4759abb49436..442e216ca9d9 100644
--- a/arch/arm/boot/dts/imx35.dtsi
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -193,6 +193,14 @@
#clock-cells = <1>;
};
+ gpt: timer@53f90000 {
+ compatible = "fsl,imx35-gpt", "fsl,imx31-gpt";
+ reg = <0x53f90000 0x4000>;
+ interrupts = <29>;
+ clocks = <&clks 9>, <&clks 50>;
+ clock-names = "ipg", "per";
+ };
+
gpio3: gpio@53fa4000 {
compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
reg = <0x53fa4000 0x4000>;
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
index 6a201cf54366..c0e0f60ab6b2 100644
--- a/arch/arm/boot/dts/imx50.dtsi
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -151,8 +151,10 @@
reg = <0x50014000 0x4000>;
interrupts = <30>;
clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+ dmas = <&sdma 24 1 0>,
+ <&sdma 25 1 0>;
+ dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
@@ -457,8 +459,10 @@
reg = <0x63fcc000 0x4000>;
interrupts = <29>;
clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+ dmas = <&sdma 28 0 0>,
+ <&sdma 29 0 0>;
+ dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index 181d77fa2fa6..56569cecaa78 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -203,6 +203,7 @@
reg = <0>;
interrupt-parent = <&gpio1>;
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,mc13xxx-uses-rtc;
regulators {
sw1_reg: sw1 {
@@ -392,7 +393,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
index 31cfb7f2b02e..34599c547459 100644
--- a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
+++ b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
@@ -255,7 +255,6 @@
&ssi2 {
codec-handle = <&tlv320aic23>;
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index bebbf3ba0d5e..17c05a6fa776 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -218,7 +218,6 @@
<&sdma 25 1 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
@@ -508,7 +507,6 @@
<&sdma 29 0 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
@@ -564,7 +562,6 @@
<&sdma 47 0 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <47 46 37 35>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx53-m53.dtsi b/arch/arm/boot/dts/imx53-m53.dtsi
new file mode 100644
index 000000000000..87a7fc709c2d
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-m53.dtsi
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx53.dtsi"
+
+/ {
+ model = "DENX M53";
+ compatible = "denx,imx53-m53", "fsl,imx53";
+
+ memory {
+ reg = <0x70000000 0x20000000>,
+ <0xb0000000 0x20000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3p2v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3P2V";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ regulator-always-on;
+ };
+
+ reg_backlight: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "lcd-supply";
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3200000>;
+ regulator-always-on;
+ };
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ stmpe610@41 {
+ compatible = "st,stmpe610";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x41>;
+ id = <0>;
+ blocks = <0x5>;
+ interrupts = <6 0x0>;
+ interrupt-parent = <&gpio7>;
+ irq-trigger = <0x1>;
+
+ stmpe_touchscreen {
+ compatible = "st,stmpe-ts";
+ reg = <0>;
+ st,sample-time = <4>;
+ st,mod-12b = <1>;
+ st,ref-sel = <0>;
+ st,adc-freq = <1>;
+ st,ave-ctrl = <3>;
+ st,touch-det-delay = <3>;
+ st,settling = <4>;
+ st,fraction-z = <7>;
+ st,i-drive = <1>;
+ };
+ };
+
+ eeprom: eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+
+ rtc: rtc@68 {
+ compatible = "stm,m41t62";
+ reg = <0x68>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx53-m53evk {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
+ MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
+ MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX53_PAD_EIM_D16__I2C2_SDA 0xc0000000
+ MX53_PAD_EIM_EB2__I2C2_SCL 0xc0000000
+ >;
+ };
+
+ pinctrl_nand: nandgrp {
+ fsl,pins = <
+ MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
+ MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
+ MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
+ MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
+ MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
+ MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
+ MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
+ MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
+ MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
+ MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
+ MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
+ MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
+ MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
+ MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
+ MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
+ >;
+ };
+ };
+};
+
+&nfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index c4956b0ffb35..d0e0f57eb432 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -10,17 +10,12 @@
*/
/dts-v1/;
-#include "imx53.dtsi"
+#include "imx53-m53.dtsi"
/ {
model = "DENX M53EVK";
compatible = "denx,imx53-m53evk", "fsl,imx53";
- memory {
- reg = <0x70000000 0x20000000>,
- <0xb0000000 0x20000000>;
- };
-
display1: display@di1 {
compatible = "fsl,imx-parallel-display";
interface-pix-fmt = "bgr666";
@@ -81,25 +76,6 @@
#address-cells = <1>;
#size-cells = <0>;
- reg_3p2v: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "3P2V";
- regulator-min-microvolt = <3200000>;
- regulator-max-microvolt = <3200000>;
- regulator-always-on;
- };
-
-
- reg_backlight: regulator@1 {
- compatible = "regulator-fixed";
- reg = <1>;
- regulator-name = "lcd-supply";
- regulator-min-microvolt = <3200000>;
- regulator-max-microvolt = <3200000>;
- regulator-always-on;
- };
-
reg_usbh1_vbus: regulator@3 {
compatible = "regulator-fixed";
reg = <3>;
@@ -174,50 +150,6 @@
};
};
-&i2c2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c2>;
- clock-frequency = <400000>;
- status = "okay";
-
- stmpe610@41 {
- compatible = "st,stmpe610";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x41>;
- id = <0>;
- blocks = <0x5>;
- interrupts = <6 0x0>;
- interrupt-parent = <&gpio7>;
- irq-trigger = <0x1>;
-
- stmpe_touchscreen {
- compatible = "st,stmpe-ts";
- reg = <0>;
- st,sample-time = <4>;
- st,mod-12b = <1>;
- st,ref-sel = <0>;
- st,adc-freq = <1>;
- st,ave-ctrl = <3>;
- st,touch-det-delay = <3>;
- st,settling = <4>;
- st,fraction-z = <7>;
- st,i-drive = <1>;
- };
- };
-
- eeprom: eeprom@50 {
- compatible = "atmel,24c128";
- reg = <0x50>;
- pagesize = <32>;
- };
-
- rtc: rtc@68 {
- compatible = "stm,m41t62";
- reg = <0x68>;
- };
-};
-
&i2c3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
@@ -229,11 +161,8 @@
pinctrl-0 = <&pinctrl_hog>;
imx53-m53evk {
- pinctrl_hog: hoggrp {
+ pinctrl_usb: usbgrp {
fsl,pins = <
- MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
- MX53_PAD_EIM_EB3__GPIO2_31 0x80000000
- MX53_PAD_PATA_DA_0__GPIO7_6 0x80000000
MX53_PAD_GPIO_2__GPIO1_2 0x80000000
MX53_PAD_GPIO_3__USBOH3_USBH1_OC 0x80000000
>;
@@ -302,13 +231,6 @@
>;
};
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX53_PAD_EIM_D16__I2C2_SDA 0xc0000000
- MX53_PAD_EIM_EB2__I2C2_SCL 0xc0000000
- >;
- };
-
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
@@ -353,26 +275,6 @@
>;
};
- pinctrl_nand: nandgrp {
- fsl,pins = <
- MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B 0x4
- MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B 0x4
- MX53_PAD_NANDF_CLE__EMI_NANDF_CLE 0x4
- MX53_PAD_NANDF_ALE__EMI_NANDF_ALE 0x4
- MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B 0xe0
- MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 0xe0
- MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 0x4
- MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 0xa4
- MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 0xa4
- MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 0xa4
- MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 0xa4
- MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 0xa4
- MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 0xa4
- MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 0xa4
- MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 0xa4
- >;
- };
-
pinctrl_pwm1: pwm1grp {
fsl,pins = <
MX53_PAD_DISP0_DAT8__PWM1_PWMO 0x5
@@ -408,14 +310,6 @@
remote-endpoint = <&display1_in>;
};
-&nfc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_nand>;
- nand-bus-width = <8>;
- nand-ecc-mode = "hw";
- status = "okay";
-};
-
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1>;
@@ -427,7 +321,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
@@ -450,6 +343,8 @@
};
&usbh1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb>;
vbus-supply = <&reg_usbh1_vbus>;
phy_type = "utmi";
status = "okay";
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
index 3e3f17aa93a1..2e44d2aba14e 100644
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ b/arch/arm/boot/dts/imx53-mba53.dts
@@ -225,7 +225,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
index fd8c60dde7de..181ae5ebf23f 100644
--- a/arch/arm/boot/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -141,7 +141,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/imx53-tx53.dtsi
index e348796ba689..704bd72cbfec 100644
--- a/arch/arm/boot/dts/imx53-tx53.dtsi
+++ b/arch/arm/boot/dts/imx53-tx53.dtsi
@@ -502,7 +502,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
codec-handle = <&sgtl5000>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/imx53-voipac-bsb.dts
index 7f6711a48615..c17d3ad6dba5 100644
--- a/arch/arm/boot/dts/imx53-voipac-bsb.dts
+++ b/arch/arm/boot/dts/imx53-voipac-bsb.dts
@@ -154,6 +154,5 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 6456a0084388..64fa27b36be0 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -108,7 +108,7 @@
clocks = <&clks IMX5_CLK_SATA_GATE>,
<&clks IMX5_CLK_SATA_REF>,
<&clks IMX5_CLK_AHB>;
- clock-names = "sata_gate", "sata_ref", "ahb";
+ clock-names = "sata", "sata_ref", "ahb";
status = "disabled";
};
@@ -231,7 +231,6 @@
<&sdma 25 1 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
@@ -260,6 +259,11 @@
};
};
+ aipstz1: bridge@53f00000 {
+ compatible = "fsl,imx53-aipstz";
+ reg = <0x53f00000 0x60>;
+ };
+
usbphy0: usbphy@0 {
compatible = "usb-nop-xceiv";
clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
@@ -572,6 +576,11 @@
reg = <0x60000000 0x10000000>;
ranges;
+ aipstz2: bridge@63f00000 {
+ compatible = "fsl,imx53-aipstz";
+ reg = <0x63f00000 0x60>;
+ };
+
iim: iim@63f98000 {
compatible = "fsl,imx53-iim", "fsl,imx27-iim";
reg = <0x63f98000 0x4000>;
@@ -661,7 +670,6 @@
<&sdma 29 0 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
@@ -689,7 +697,6 @@
<&sdma 47 0 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <47 46 45 44>; /* TX0 RX0 TX1 RX1 */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_4.dts b/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
new file mode 100644
index 000000000000..9cd06e5e59f0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-aristainetos_4.dts
@@ -0,0 +1,85 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-aristainetos.dtsi"
+
+/ {
+ model = "aristainetos i.MX6 Dual Lite Board 4";
+ compatible = "fsl,imx6dl";
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <7>;
+ enable-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ status = "okay";
+ };
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ soc {
+ display0: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu_disp>;
+ status = "okay";
+
+ display-timings {
+ 480x800p60 {
+ native-mode;
+ clock-frequency = <30000000>;
+ hactive = <480>;
+ vactive = <800>;
+ hfront-porch = <59>;
+ hback-porch = <10>;
+ hsync-len = <10>;
+ vback-porch = <15>;
+ vfront-porch = <15>;
+ vsync-len = <15>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+ };
+ };
+};
+
+&ecspi2 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
diff --git a/arch/arm/boot/dts/imx6dl-aristainetos_7.dts b/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
new file mode 100644
index 000000000000..b413e24288dc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-aristainetos_7.dts
@@ -0,0 +1,74 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-aristainetos.dtsi"
+
+/ {
+ model = "aristainetos i.MX6 Dual Lite Board 7";
+ compatible = "fsl,imx6dl";
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ soc {
+ display0: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu_disp>;
+ status = "okay";
+
+ display-timings {
+ 800x480p60 {
+ native-mode;
+ clock-frequency = <33246000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <88>;
+ hback-porch = <88>;
+ hsync-len = <80>;
+ vback-porch = <10>;
+ vfront-porch = <10>;
+ vsync-len = <25>;
+ vsync-active = <1>;
+ };
+ };
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 3000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw51xx.dts b/arch/arm/boot/dts/imx6dl-gw51xx.dts
index 4bd055f4c930..b2bd022fc6be 100644
--- a/arch/arm/boot/dts/imx6dl-gw51xx.dts
+++ b/arch/arm/boot/dts/imx6dl-gw51xx.dts
@@ -14,6 +14,6 @@
#include "imx6qdl-gw51xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 DualLite GW51XX";
+ model = "Gateworks Ventana i.MX6 DualLite/Solo GW51XX";
compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
};
diff --git a/arch/arm/boot/dts/imx6dl-gw52xx.dts b/arch/arm/boot/dts/imx6dl-gw52xx.dts
index c9136058f15e..a2e0b73fdd4a 100644
--- a/arch/arm/boot/dts/imx6dl-gw52xx.dts
+++ b/arch/arm/boot/dts/imx6dl-gw52xx.dts
@@ -14,6 +14,6 @@
#include "imx6qdl-gw52xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 DualLite GW52XX";
+ model = "Gateworks Ventana i.MX6 DualLite/Solo GW52XX";
compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
};
diff --git a/arch/arm/boot/dts/imx6dl-gw53xx.dts b/arch/arm/boot/dts/imx6dl-gw53xx.dts
index 61818a14fde6..6844b708d2f8 100644
--- a/arch/arm/boot/dts/imx6dl-gw53xx.dts
+++ b/arch/arm/boot/dts/imx6dl-gw53xx.dts
@@ -14,6 +14,6 @@
#include "imx6qdl-gw53xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 DualLite GW53XX";
+ model = "Gateworks Ventana i.MX6 DualLite/Solo GW53XX";
compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
};
diff --git a/arch/arm/boot/dts/imx6dl-gw54xx.dts b/arch/arm/boot/dts/imx6dl-gw54xx.dts
index ab38b6770a06..be915412f852 100644
--- a/arch/arm/boot/dts/imx6dl-gw54xx.dts
+++ b/arch/arm/boot/dts/imx6dl-gw54xx.dts
@@ -14,6 +14,6 @@
#include "imx6qdl-gw54xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 DualLite GW54XX";
+ model = "Gateworks Ventana i.MX6 DualLite/Solo GW54XX";
compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
};
diff --git a/arch/arm/boot/dts/imx6dl-rex-basic.dts b/arch/arm/boot/dts/imx6dl-rex-basic.dts
new file mode 100644
index 000000000000..b13845c2823b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-rex-basic.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-rex.dtsi"
+
+/ {
+ model = "Rex Basic i.MX6 Dual Lite Board";
+ compatible = "rex,imx6dl-rex-basic", "fsl,imx6dl";
+
+ memory {
+ reg = <0x10000000 0x20000000>;
+ };
+};
+
+&ecspi3 {
+ flash: m25p80@0 {
+ compatible = "sst,sst25vf016b";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts
index 909fafc0b650..43cb3fd76be7 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -254,7 +254,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
@@ -335,10 +334,10 @@
imx6-riotboard {
pinctrl_audmux: audmuxgrp {
fsl,pins = <
- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x8000000
- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x8000000
- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x8000000
- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x8000000
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* CAM_MCLK */
>;
};
@@ -376,7 +375,7 @@
fsl,pins = <
MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x80000000
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
@@ -389,9 +388,9 @@
MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 /* AR8035 pin strapping: MODE#1: pull up */
MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 /* AR8035 pin strapping: MODE#3: pull up */
MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 /* AR8035 pin strapping: MODE#0: pull down */
- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000 /* GPIO16 -> AR8035 25MHz */
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 /* GPIO16 -> AR8035 25MHz */
MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0 /* RGMII_nRST */
- MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* AR8035 interrupt */
+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x180b0 /* AR8035 interrupt */
MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1
>;
};
@@ -426,8 +425,8 @@
pinctrl_led: ledgrp {
fsl,pins = <
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000 /* user led0 */
- MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x80000000 /* user led1 */
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* user led0 */
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b1 /* user led1 */
>;
};
@@ -493,8 +492,8 @@
pinctrl_usbotg: usbotggrp {
fsl,pins = <
MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
- MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 /* MX6QDL_PAD_EIM_D22__USB_OTG_PWR */
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
>;
};
@@ -506,8 +505,8 @@
MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000 /* SD2 CD */
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* SD2 WP */
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 /* SD2 CD */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1f0b0 /* SD2 WP */
>;
};
@@ -519,8 +518,8 @@
MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 /* SD3 CD */
- MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x80000000 /* SD3 WP */
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* SD3 CD */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* SD3 WP */
>;
};
@@ -532,7 +531,7 @@
MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
- MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x80000000 /* SD4 RST (eMMC) */
+ MX6QDL_PAD_NANDF_ALE__GPIO6_IO08 0x17059 /* SD4 RST (eMMC) */
>;
};
};
diff --git a/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
new file mode 100644
index 000000000000..913bb9a0466a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6DL Module on CoMpact TFT";
+ compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 0>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ native-mode = <&ET070001DM6>;
+
+ ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&can1 {
+ status = "disabled";
+};
+
+&can2 {
+ xceiver-supply = <&reg_3v3>;
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+ status = "disabled";
+};
+
+&reg_can_xcvr {
+ status = "disabled";
+};
+
+&touchscreen {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6dl-tx6u-801x.dts b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
new file mode 100644
index 000000000000..5fe465c2814e
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6U-801x Module";
+ compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ VGA {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <48>;
+ hsync-len = <96>;
+ hfront-porch = <16>;
+ vback-porch = <31>;
+ vsync-len = <2>;
+ vfront-porch = <12>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETV570 {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <114>;
+ hsync-len = <30>;
+ hfront-porch = <16>;
+ vback-porch = <32>;
+ vsync-len = <3>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0350 {
+ clock-frequency = <6413760>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <34>;
+ hsync-len = <34>;
+ hfront-porch = <20>;
+ vback-porch = <15>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0430 {
+ clock-frequency = <9009000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hsync-len = <41>;
+ hfront-porch = <2>;
+ vback-porch = <2>;
+ vsync-len = <10>;
+ vfront-porch = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ ET0500 {
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0700 { /* same as ET0500 */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETQ570 {
+ clock-frequency = <6596040>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <38>;
+ hsync-len = <30>;
+ hfront-porch = <30>;
+ vback-porch = <16>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
diff --git a/arch/arm/boot/dts/imx6dl-tx6u-811x.dts b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts
new file mode 100644
index 000000000000..c275eecc9472
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-tx6u-811x.dts
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6U-811x Module";
+ compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+ aliases {
+ display = &lvds0;
+ lvds0 = &lvds0;
+ lvds1 = &lvds1;
+ };
+
+ backlight0: backlight0 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 0>;
+ power-supply = <&reg_lcd0_pwr>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ backlight1: backlight1 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 500000 0>;
+ power-supply = <&reg_lcd1_pwr>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+};
+
+&i2c3 {
+ polytouch2: eeti@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eeti>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <22 0>;
+ wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ linux,wakeup;
+ };
+};
+
+&iomuxc {
+ imx6dl-tx6u-811x {
+ pinctrl_eeti: eetigrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+ >;
+ };
+ };
+};
+
+&kpp {
+ status = "disabled"; /* pad conflict with backlight1 PWM */
+};
+
+&ldb {
+ status = "okay";
+
+ lvds0: lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ display-timings {
+ native-mode = <&lvds_timing0>;
+ lvds_timing0: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+
+ lvds1: lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "disabled";
+
+ display-timings {
+ native-mode = <&lvds_timing1>;
+ lvds_timing1: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts b/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
new file mode 100644
index 000000000000..f607d4f1d244
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-wandboard-revb1.dtsi"
+
+/ {
+ model = "Wandboard i.MX6 Dual Lite Board";
+ compatible = "wand,imx6dl-wandboard", "fsl,imx6dl";
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-wandboard.dts b/arch/arm/boot/dts/imx6dl-wandboard.dts
index e672891c1626..bbb616723097 100644
--- a/arch/arm/boot/dts/imx6dl-wandboard.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
#include "imx6dl.dtsi"
-#include "imx6qdl-wandboard.dtsi"
+#include "imx6qdl-wandboard-revc1.dtsi"
/ {
model = "Wandboard i.MX6 Dual Lite Board";
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 0a9c49d69d41..b453e0e28aee 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -35,8 +35,11 @@
396000 1175000
>;
clock-latency = <61036>; /* two CLK32 periods */
- clocks = <&clks 104>, <&clks 6>, <&clks 16>,
- <&clks 17>, <&clks 170>;
+ clocks = <&clks IMX6QDL_CLK_ARM>,
+ <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+ <&clks IMX6QDL_CLK_STEP>,
+ <&clks IMX6QDL_CLK_PLL1_SW>,
+ <&clks IMX6QDL_CLK_PLL1_SYS>;
clock-names = "arm", "pll2_pfd2_396m", "step",
"pll1_sw", "pll1_sys";
arm-supply = <&reg_arm>;
@@ -56,7 +59,7 @@
ocram: sram@00900000 {
compatible = "mmio-sram";
reg = <0x00900000 0x20000>;
- clocks = <&clks 142>;
+ clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
aips1: aips-bus@02000000 {
@@ -87,7 +90,7 @@
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021f8000 0x4000>;
interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 116>;
+ clocks = <&clks IMX6DL_CLK_I2C4>;
status = "disabled";
};
};
@@ -104,9 +107,9 @@
};
&ldb {
- clocks = <&clks 33>, <&clks 34>,
- <&clks 39>, <&clks 40>,
- <&clks 135>, <&clks 136>;
+ clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
clock-names = "di0_pll", "di1_pll",
"di0_sel", "di1_sel",
"di0", "di1";
diff --git a/arch/arm/boot/dts/imx6q-cubox-i.dts b/arch/arm/boot/dts/imx6q-cubox-i.dts
index bc5f31e3e892..9efd8b0c8011 100644
--- a/arch/arm/boot/dts/imx6q-cubox-i.dts
+++ b/arch/arm/boot/dts/imx6q-cubox-i.dts
@@ -13,4 +13,8 @@
&sata {
status = "okay";
+ fsl,transmit-level-mV = <1104>;
+ fsl,transmit-boost-mdB = <0>;
+ fsl,transmit-atten-16ths = <9>;
+ fsl,no-spread-spectrum;
};
diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
index e0302636aff5..8c1cb53464a0 100644
--- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
+++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
@@ -95,6 +95,12 @@
};
};
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1>;
+ status = "okay";
+};
+
&ecspi5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi5>;
@@ -118,6 +124,13 @@
status = "okay";
};
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+};
+
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
@@ -274,6 +287,13 @@
};
};
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -286,6 +306,13 @@
>;
};
+ pinctrl_can1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
+
pinctrl_ecspi5: ecspi5rp-1 {
fsl,pins = <
MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x80000000
@@ -316,6 +343,13 @@
>;
};
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
@@ -323,6 +357,19 @@
>;
};
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x100b1
+ >;
+ };
+
pinctrl_pfuze: pfuze100grp1 {
fsl,pins = <
MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
@@ -385,6 +432,13 @@
};
};
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio4 8 0>;
+ status = "okay";
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-gw51xx.dts b/arch/arm/boot/dts/imx6q-gw51xx.dts
index 0e1406e58eff..8e8bcd8fe0fb 100644
--- a/arch/arm/boot/dts/imx6q-gw51xx.dts
+++ b/arch/arm/boot/dts/imx6q-gw51xx.dts
@@ -14,6 +14,6 @@
#include "imx6qdl-gw51xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 Quad GW51XX";
+ model = "Gateworks Ventana i.MX6 Dual/Quad GW51XX";
compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
};
diff --git a/arch/arm/boot/dts/imx6q-gw52xx.dts b/arch/arm/boot/dts/imx6q-gw52xx.dts
index 5f71ddbc7f05..a12c47e5ee05 100644
--- a/arch/arm/boot/dts/imx6q-gw52xx.dts
+++ b/arch/arm/boot/dts/imx6q-gw52xx.dts
@@ -14,7 +14,7 @@
#include "imx6qdl-gw52xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 Quad GW52XX";
+ model = "Gateworks Ventana i.MX6 Dual/Quad GW52XX";
compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
};
diff --git a/arch/arm/boot/dts/imx6q-gw53xx.dts b/arch/arm/boot/dts/imx6q-gw53xx.dts
index 360c316b4740..d76aaa83dad0 100644
--- a/arch/arm/boot/dts/imx6q-gw53xx.dts
+++ b/arch/arm/boot/dts/imx6q-gw53xx.dts
@@ -14,7 +14,7 @@
#include "imx6qdl-gw53xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 Quad GW53XX";
+ model = "Gateworks Ventana i.MX6 Dual/Quad GW53XX";
compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
};
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
index 3689eaa58826..22e6f8e657d2 100644
--- a/arch/arm/boot/dts/imx6q-gw5400-a.dts
+++ b/arch/arm/boot/dts/imx6q-gw5400-a.dts
@@ -115,9 +115,9 @@
};
sound {
- compatible = "fsl,imx6q-sabrelite-sgtl5000",
+ compatible = "fsl,imx6q-ventana-sgtl5000",
"fsl,imx-audio-sgtl5000";
- model = "imx6q-sabrelite-sgtl5000";
+ model = "sgtl5000-audio";
ssi-controller = <&ssi1>;
audio-codec = <&codec>;
audio-routing =
@@ -504,7 +504,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-gw54xx.dts b/arch/arm/boot/dts/imx6q-gw54xx.dts
index ab518d66a75e..6e8f53e92a2d 100644
--- a/arch/arm/boot/dts/imx6q-gw54xx.dts
+++ b/arch/arm/boot/dts/imx6q-gw54xx.dts
@@ -14,7 +14,7 @@
#include "imx6qdl-gw54xx.dtsi"
/ {
- model = "Gateworks Ventana i.MX6 Quad GW54XX";
+ model = "Gateworks Ventana i.MX6 Dual/Quad GW54XX";
compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
};
diff --git a/arch/arm/boot/dts/imx6q-rex-pro.dts b/arch/arm/boot/dts/imx6q-rex-pro.dts
new file mode 100644
index 000000000000..3c2852b16f78
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-rex-pro.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-rex.dtsi"
+
+/ {
+ model = "Rex Pro i.MX6 Quad Board";
+ compatible = "rex,imx6q-rex-pro", "fsl,imx6q";
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+};
+
+&ecspi3 {
+ flash: m25p80@0 {
+ compatible = "sst,sst25vf032b";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
new file mode 100644
index 000000000000..b18fae10b2e3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6Q-1010 Module on CoMpact TFT";
+ compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 0>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ native-mode = <&ET070001DM6>;
+
+ ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&can1 {
+ status = "disabled";
+};
+
+&can2 {
+ xceiver-supply = <&reg_3v3>;
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+ status = "disabled";
+};
+
+&reg_can_xcvr {
+ status = "disabled";
+};
+
+&touchscreen {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1010.dts b/arch/arm/boot/dts/imx6q-tx6q-1010.dts
new file mode 100644
index 000000000000..b58ec9c966c8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tx6q-1010.dts
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6Q-1010 Module";
+ compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ VGA {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <48>;
+ hsync-len = <96>;
+ hfront-porch = <16>;
+ vback-porch = <31>;
+ vsync-len = <2>;
+ vfront-porch = <12>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETV570 {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <114>;
+ hsync-len = <30>;
+ hfront-porch = <16>;
+ vback-porch = <32>;
+ vsync-len = <3>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0350 {
+ clock-frequency = <6413760>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <34>;
+ hsync-len = <34>;
+ hfront-porch = <20>;
+ vback-porch = <15>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0430 {
+ clock-frequency = <9009000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hsync-len = <41>;
+ hfront-porch = <2>;
+ vback-porch = <2>;
+ vsync-len = <10>;
+ vfront-porch = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ ET0500 {
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0700 { /* same as ET0500 */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETQ570 {
+ clock-frequency = <6596040>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <38>;
+ hsync-len = <30>;
+ hfront-porch = <30>;
+ vback-porch = <16>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
new file mode 100644
index 000000000000..0bb9a9de62a9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6Q-1020 Module on CoMpact TFT";
+ compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 0>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ native-mode = <&ET070001DM6>;
+
+ ET070001DM6: CoMTFT { /* same as ET0700 but with inverted pixel clock */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&can1 {
+ status = "disabled";
+};
+
+&can2 {
+ xceiver-supply = <&reg_3v3>;
+};
+
+&ds1339 {
+ status = "disabled";
+};
+
+&gpmi {
+ status = "disabled";
+};
+
+&iomuxc {
+ imx6qdl-tx6 {
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1
+ MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1
+ >;
+ };
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&kpp {
+ status = "disabled";
+};
+
+&reg_can_xcvr {
+ status = "disabled";
+};
+
+&touchscreen {
+ status = "disabled";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ bus-width = <4>;
+ no-1-8-v;
+ fsl,wp-controller;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1020.dts b/arch/arm/boot/dts/imx6q-tx6q-1020.dts
new file mode 100644
index 000000000000..b96d80a35d39
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tx6q-1020.dts
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6Q-1020 Module";
+ compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+ aliases {
+ display = &display;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+ power-supply = <&reg_3v3>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ display: display@di0 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_disp0_1>;
+ status = "okay";
+
+ port {
+ display0_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ display-timings {
+ VGA {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <48>;
+ hsync-len = <96>;
+ hfront-porch = <16>;
+ vback-porch = <31>;
+ vsync-len = <2>;
+ vfront-porch = <12>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETV570 {
+ clock-frequency = <25200000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <114>;
+ hsync-len = <30>;
+ hfront-porch = <16>;
+ vback-porch = <32>;
+ vsync-len = <3>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0350 {
+ clock-frequency = <6413760>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <34>;
+ hsync-len = <34>;
+ hfront-porch = <20>;
+ vback-porch = <15>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0430 {
+ clock-frequency = <9009000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hsync-len = <41>;
+ hfront-porch = <2>;
+ vback-porch = <2>;
+ vsync-len = <10>;
+ vfront-porch = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ ET0500 {
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ET0700 { /* same as ET0500 */
+ clock-frequency = <33264000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+
+ ETQ570 {
+ clock-frequency = <6596040>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <38>;
+ hsync-len = <30>;
+ hfront-porch = <30>;
+ vback-porch = <16>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&ds1339 {
+ status = "disabled";
+};
+
+&gpmi {
+ status = "disabled";
+};
+
+&iomuxc {
+ imx6qdl-tx6 {
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1
+ MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1
+ >;
+ };
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&display0_in>;
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ bus-width = <4>;
+ no-1-8-v;
+ fsl,wp-controller;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-tx6q-1110.dts b/arch/arm/boot/dts/imx6q-tx6q-1110.dts
new file mode 100644
index 000000000000..88aa1e4c792d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tx6q-1110.dts
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+ model = "Ka-Ro electronics TX6Q-1110 Module";
+ compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+ aliases {
+ display = &lvds0;
+ lvds0 = &lvds0;
+ lvds1 = &lvds1;
+ };
+
+ backlight0: backlight0 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm2 0 500000 0>;
+ power-supply = <&reg_lcd0_pwr>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ backlight1: backlight1 {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 500000 0>;
+ power-supply = <&reg_lcd1_pwr>;
+ /*
+ * a poor man's way to create a 1:1 relationship between
+ * the PWM value and the actual duty cycle
+ */
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29
+ 30 31 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+};
+
+&i2c3 {
+ polytouch1: eeti@04 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_eeti>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <22 0>;
+ wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ linux,wakeup;
+ };
+};
+
+&iomuxc {
+ imx6q-tx6q-1110 {
+ pinctrl_eeti: eetigrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+ >;
+ };
+ };
+};
+
+&kpp {
+ status = "disabled"; /* pad conflict with backlight1 PWM */
+};
+
+&ldb {
+ status = "okay";
+
+ lvds0: lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ display-timings {
+ native-mode = <&lvds_timing0>;
+ lvds_timing0: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+
+ lvds1: lvds-channel@1 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "disabled";
+
+ display-timings {
+ native-mode = <&lvds_timing1>;
+ lvds_timing1: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts
index 6c561060bf5c..e3bff2ac00db 100644
--- a/arch/arm/boot/dts/imx6q-udoo.dts
+++ b/arch/arm/boot/dts/imx6q-udoo.dts
@@ -23,6 +23,23 @@
memory {
reg = <0x10000000 0x40000000>;
};
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_usb_h1_vbus: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
+ gpio = <&gpio7 12 0>;
+ };
+ };
};
&fec {
@@ -81,6 +98,13 @@
>;
};
+ pinctrl_usbh: usbhgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
+ MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
+ >;
+ };
+
pinctrl_usdhc3: usdhc3grp {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
@@ -104,6 +128,14 @@
status = "okay";
};
+&usbh1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh>;
+ vbus-supply = <&reg_usb_h1_vbus>;
+ clocks = <&clks 201>;
+ status = "okay";
+};
+
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
diff --git a/arch/arm/boot/dts/imx6q-wandboard-revb1.dts b/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
new file mode 100644
index 000000000000..20bf3c282623
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-wandboard-revb1.dtsi"
+
+/ {
+ model = "Wandboard i.MX6 Quad Board";
+ compatible = "wand,imx6q-wandboard", "fsl,imx6q";
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-wandboard.dts b/arch/arm/boot/dts/imx6q-wandboard.dts
index 36be17f207b1..4a8a6ee13e9f 100644
--- a/arch/arm/boot/dts/imx6q-wandboard.dts
+++ b/arch/arm/boot/dts/imx6q-wandboard.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
#include "imx6q.dtsi"
-#include "imx6qdl-wandboard.dtsi"
+#include "imx6qdl-wandboard-revc1.dtsi"
/ {
model = "Wandboard i.MX6 Quad Board";
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index addd3f881ce2..e9f3646d1760 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -43,8 +43,11 @@
396000 1175000
>;
clock-latency = <61036>; /* two CLK32 periods */
- clocks = <&clks 104>, <&clks 6>, <&clks 16>,
- <&clks 17>, <&clks 170>;
+ clocks = <&clks IMX6QDL_CLK_ARM>,
+ <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+ <&clks IMX6QDL_CLK_STEP>,
+ <&clks IMX6QDL_CLK_PLL1_SW>,
+ <&clks IMX6QDL_CLK_PLL1_SYS>;
clock-names = "arm", "pll2_pfd2_396m", "step",
"pll1_sw", "pll1_sys";
arm-supply = <&reg_arm>;
@@ -78,7 +81,7 @@
ocram: sram@00900000 {
compatible = "mmio-sram";
reg = <0x00900000 0x40000>;
- clocks = <&clks 142>;
+ clocks = <&clks IMX6QDL_CLK_OCRAM>;
};
aips-bus@02000000 { /* AIPS1 */
@@ -89,7 +92,8 @@
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02018000 0x4000>;
interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 116>, <&clks 116>;
+ clocks = <&clks IMX6Q_CLK_ECSPI5>,
+ <&clks IMX6Q_CLK_ECSPI5>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -140,7 +144,9 @@
compatible = "fsl,imx6q-ahci";
reg = <0x02200000 0x4000>;
interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 154>, <&clks 187>, <&clks 105>;
+ clocks = <&clks IMX6QDL_CLK_SATA>,
+ <&clks IMX6QDL_CLK_SATA_REF_100M>,
+ <&clks IMX6QDL_CLK_AHB>;
clock-names = "sata", "sata_ref", "ahb";
status = "disabled";
};
@@ -152,10 +158,20 @@
reg = <0x02800000 0x400000>;
interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
<0 7 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 133>, <&clks 134>, <&clks 137>;
+ clocks = <&clks IMX6QDL_CLK_IPU2>,
+ <&clks IMX6QDL_CLK_IPU2_DI0>,
+ <&clks IMX6QDL_CLK_IPU2_DI1>;
clock-names = "bus", "di0", "di1";
resets = <&src 4>;
+ ipu2_csi0: port@0 {
+ reg = <0>;
+ };
+
+ ipu2_csi1: port@1 {
+ reg = <1>;
+ };
+
ipu2_di0: port@2 {
#address-cells = <1>;
#size-cells = <0>;
@@ -230,9 +246,10 @@
};
&ldb {
- clocks = <&clks 33>, <&clks 34>,
- <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
- <&clks 135>, <&clks 136>;
+ clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+ <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+ <&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
+ <&clks IMX6QDL_CLK_LDB_DI0>, <&clks IMX6QDL_CLK_LDB_DI1>;
clock-names = "di0_pll", "di1_pll",
"di0_sel", "di1_sel", "di2_sel", "di3_sel",
"di0", "di1";
diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
new file mode 100644
index 000000000000..e6d9195a1da7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
@@ -0,0 +1,418 @@
+/*
+ * support fot the imx6 based aristainetos board
+ *
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_2p5v: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usbh1_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_aristainetos_usbh1_vbus>;
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usbotg_vbus: regulator@3 {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_aristainetos_usbotg_vbus>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ tmp103: tmp103@71 {
+ compatible = "ti,tmp103";
+ reg = <0x71>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ rtc@68 {
+ compatible = "dallas,m41t00";
+ reg = <0x68>;
+ };
+};
+
+&ecspi4 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio3 20 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi4>;
+ status = "okay";
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q128a11";
+ spi-max-frequency = <20000000>;
+ reg = <0>;
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usbh1_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usbotg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ vmmc-supply = <&reg_3p3v>;
+ cd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ vmmc-supply = <&reg_3p3v>;
+ cd-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog &pinctrl_gpio>;
+
+ imx6qdl-aristainetos {
+ pinctrl_aristainetos_usbh1_vbus: aristainetos-usbh1-vbus {
+ fsl,pins = <MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x130b0>;
+ };
+
+ pinctrl_aristainetos_usbotg_vbus: aristainetos-usbotg-vbus {
+ fsl,pins = <MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0>;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x1b0b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x1b0b0
+ >;
+ };
+
+ pinctrl_backlight: backlightgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b0
+ MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b0
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1
+ MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x100b1
+ >;
+ };
+
+ pinctrl_ecspi4: ecspi4grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
+ MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x100b1
+ MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x100b1
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x100b1
+ MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 /* WP pin */
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX 0x1b0b0
+ MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_gpio: gpiogrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x1b0b0
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x1b0b0
+ MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0
+ MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0
+ MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
+ MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0
+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
+
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x10
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_ipu_disp: ipudisp1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x20000
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x1b0b0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index 744c8a2d81f6..234e7b755232 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -121,9 +121,9 @@
};
sound {
- compatible = "fsl,imx6q-sabrelite-sgtl5000",
+ compatible = "fsl,imx6q-ventana-sgtl5000",
"fsl,imx-audio-sgtl5000";
- model = "imx6q-sabrelite-sgtl5000";
+ model = "sgtl5000-audio";
ssi-controller = <&ssi1>;
audio-codec = <&codec>;
audio-routing =
@@ -489,7 +489,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index adf150c1be90..143f84f7812c 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -124,9 +124,9 @@
};
sound {
- compatible = "fsl,imx6q-sabrelite-sgtl5000",
+ compatible = "fsl,imx6q-ventana-sgtl5000",
"fsl,imx-audio-sgtl5000";
- model = "imx6q-sabrelite-sgtl5000";
+ model = "sgtl5000-audio";
ssi-controller = <&ssi1>;
audio-codec = <&codec>;
audio-routing =
@@ -533,7 +533,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index 698d3063b295..16e7ad3d98ad 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -114,9 +114,9 @@
};
sound {
- compatible = "fsl,imx6q-sabrelite-sgtl5000",
+ compatible = "fsl,imx6q-ventana-sgtl5000",
"fsl,imx-audio-sgtl5000";
- model = "imx6q-sabrelite-sgtl5000";
+ model = "sgtl5000-audio";
ssi-controller = <&ssi1>;
audio-codec = <&codec>;
audio-routing =
@@ -555,12 +555,10 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index 4c4b17596c8b..42ff525ebe13 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -381,7 +381,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
index faa3494a69d4..2694aa84e187 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
@@ -301,6 +301,7 @@
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii";
phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ phy-supply = <&vdd_eth_io_reg>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi
new file mode 100644
index 000000000000..df7bcf86c156
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2014 FEDEVEL, Inc.
+ *
+ * Author: Robert Nelson <robertcnelson@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3p3v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usbh1_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ regulator-name = "usbh1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led>;
+
+ led0: usr {
+ label = "usr";
+ gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6-rex-sgtl5000",
+ "fsl,imx-audio-sgtl5000";
+ model = "imx6-rex-sgtl5000";
+ ssi-controller = <&ssi1>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HP_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <3>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+};
+
+&ecspi2 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+};
+
+&ecspi3 {
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&clks 201>;
+ VDDA-supply = <&reg_3p3v>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ eeprom@57 {
+ compatible = "at,24c02";
+ reg = <0x57>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-rex {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* SGTL5000 sys_mclk */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0
+ >;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ /* CS */
+ MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x000b1
+ >;
+ };
+
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT17__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT16__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT19__ECSPI2_SCLK 0x100b1
+ /* CS */
+ MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x000b1
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ /* Phy reset */
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x000b0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ /* user led */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbh1: usbh1grp {
+ fsl,pins = <
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x10b0
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ MX6QDL_PAD_EIM_D21__USB_OTG_OC 0x1b0b0
+ /* power enable, high active */
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x10b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ /* CD */
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0
+ /* WP */
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1f0b0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ /* CD */
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0
+ /* WP */
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1f0b0
+ >;
+ };
+ };
+};
+
+&ssi1 {
+ fsl,mode = "i2s-slave";
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usbh1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 6df6127bf835..0a36129152e0 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -381,7 +381,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 40ea36534643..ec43dde78525 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -340,6 +340,7 @@
MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
+ MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0
>;
};
@@ -512,7 +513,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
new file mode 100644
index 000000000000..f02b80b41d4f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
@@ -0,0 +1,696 @@
+/*
+ * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ aliases {
+ can0 = &can2;
+ can1 = &can1;
+ ethernet0 = &fec;
+ lcdif_23bit_pins_a = &pinctrl_disp0_1;
+ lcdif_24bit_pins_a = &pinctrl_disp0_2;
+ pwm0 = &pwm1;
+ pwm1 = &pwm2;
+ reg_can_xcvr = &reg_can_xcvr;
+ stk5led = &user_led;
+ usbotg = &usbotg;
+ sdhc0 = &usdhc1;
+ sdhc1 = &usdhc2;
+ };
+
+ memory {
+ reg = <0 0>; /* will be filled by U-Boot */
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ mclk: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <27000000>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_POWER>;
+ gpio-key,wakeup;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ user_led: user {
+ label = "Heartbeat";
+ gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_3v3_etn: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "3V3_ETN";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_etnphy_power>;
+ gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_2v5: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "2V5";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3v3: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_can_xcvr: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "CAN XCVR";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan_xcvr>;
+ gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+ enable-active-low;
+ };
+
+ reg_lcd0_pwr: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "LCD0 POWER";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcd0_pwr>;
+ gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_lcd1_pwr: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ regulator-name = "LCD1 POWER";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcd1_pwr>;
+ gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_usbh1_vbus: regulator@6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ regulator-name = "usbh1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1_vbus>;
+ gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usbotg_vbus: regulator@7 {
+ compatible = "regulator-fixed";
+ reg = <7>;
+ regulator-name = "usbotg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg_vbus>;
+ gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+ };
+
+ sound {
+ compatible = "karo,imx6qdl-tx6qdl-sgtl5000",
+ "fsl,imx-audio-sgtl5000";
+ model = "sgtl5000-audio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ ssi-controller = <&ssi1>;
+ audio-codec = <&sgtl5000>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HP_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <5>;
+ };
+};
+
+&audmux {
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ xceiver-supply = <&reg_can_xcvr>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ xceiver-supply = <&reg_can_xcvr>;
+ status = "okay";
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ fsl,spi-num-chipselects = <2>;
+ cs-gpios = <
+ &gpio2 30 GPIO_ACTIVE_HIGH
+ &gpio3 19 GPIO_ACTIVE_HIGH
+ >;
+ status = "okay";
+
+ spidev0: spi@0 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <54000000>;
+ };
+
+ spidev1: spi@1 {
+ compatible = "spidev";
+ reg = <1>;
+ spi-max-frequency = <54000000>;
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rmii";
+ phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>;
+ phy-supply = <&reg_3v3_etn>;
+ status = "okay";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ nand-on-flash-bbt;
+ fsl,no-blockmark-swap;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ ds1339: rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ sgtl5000: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ VDDA-supply = <&reg_2v5>;
+ VDDIO-supply = <&reg_3v3>;
+ clocks = <&mclk>;
+ };
+
+ polytouch: edt-ft5x06@38 {
+ compatible = "edt,edt-ft5x06";
+ reg = <0x38>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_edt_ft5x06>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <15 0>;
+ reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+ linux,wakeup;
+ };
+
+ touchscreen: tsc2007@48 {
+ compatible = "ti,tsc2007";
+ reg = <0x48>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc2007>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <26 0>;
+ gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;
+ ti,x-plate-ohms = <660>;
+ linux,wakeup;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-tx6 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b1 /* LED */
+ MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b1 /* PWR BTN */
+ >;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW1__AUD5_RXD 0x130b0 /* SSI1_RXD */
+ MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /* SSI1_TXD */
+ MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /* SSI1_CLK */
+ MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /* SSI1_FS */
+ >;
+ };
+
+ pinctrl_disp0_1: disp0grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ /* PAD DISP0_DAT0 is used for the Flexcan transceiver control */
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_disp0_2: disp0grp-2 {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x0b0b0
+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x0b0b0
+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x0b0b0
+ MX6QDL_PAD_GPIO_19__ECSPI1_RDY 0x0b0b0
+ MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x0b0b0 /* SPI CS0 */
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x0b0b0 /* SPI CS1 */
+ >;
+ };
+
+ pinctrl_edt_ft5x06: edt-ft5x06grp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0 /* Interrupt */
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 /* Reset */
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 /* Wake */
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ >;
+ };
+
+ pinctrl_etnphy_power: etnphy-pwrgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b1 /* ETN PHY POWER */
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0
+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan_xcvr: flexcan-xcvrgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b0 /* Flexcan XCVR enable */
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpminandgrp {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0x0b0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0x0b0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0x0b0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0x0b000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0x0b0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0x0b0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0x0b0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0x0b0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0x0b0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0x0b0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0x0b0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0x0b0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0x0b0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0x0b0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0x0b0b1
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_kpp: kppgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__KEY_COL6 0x1b0b1
+ MX6QDL_PAD_GPIO_4__KEY_COL7 0x1b0b1
+ MX6QDL_PAD_KEY_COL2__KEY_COL2 0x1b0b1
+ MX6QDL_PAD_KEY_COL3__KEY_COL3 0x1b0b1
+ MX6QDL_PAD_GPIO_2__KEY_ROW6 0x1b0b1
+ MX6QDL_PAD_GPIO_5__KEY_ROW7 0x1b0b1
+ MX6QDL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b1
+ MX6QDL_PAD_KEY_ROW3__KEY_ROW3 0x1b0b1
+ >;
+ };
+
+ pinctrl_lcd0_pwr: lcd0-pwrgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b1 /* LCD Reset */
+ >;
+ };
+
+ pinctrl_lcd1_pwr: lcd1-pwrgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b1 /* LCD Power Enable */
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__PWM2_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_tsc2007: tsc2007grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x1b0b0 /* Interrupt */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart1_rtscts: uart1_rtsctsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT1__UART1_RTS_B 0x1b0b1
+ MX6QDL_PAD_SD3_DAT0__UART1_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2_rtscts: uart2_rtsctsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
+ MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3_rtscts: uart3_rtsctsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT3__UART3_CTS_B 0x1b0b1
+ MX6QDL_PAD_SD3_RST__UART3_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbh1_vbus: usbh1-vbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0 /* USBH1_VBUSEN */
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x17059
+ >;
+ };
+
+ pinctrl_usbotg_vbus: usbotg-vbusgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* USBOTG_VBUSEN */
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x070b1
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x070b1
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x070b1
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x070b1
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x070b1
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x070b1
+ MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x170b0 /* SD1 CD */
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x070b1
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x070b1
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x070b1
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x070b1
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x070b1
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x070b1
+ MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x170b0 /* SD2 CD */
+ >;
+ };
+ };
+};
+
+&kpp {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_kpp>;
+ /* sample keymap */
+ /* row/col 0,1 are mapped to KPP row/col 6,7 */
+ linux,keymap = <
+ MATRIX_KEY(6, 6, KEY_POWER) /* 0x06060074 */
+ MATRIX_KEY(6, 7, KEY_KP0) /* 0x06070052 */
+ MATRIX_KEY(6, 2, KEY_KP1) /* 0x0602004f */
+ MATRIX_KEY(6, 3, KEY_KP2) /* 0x06030050 */
+ MATRIX_KEY(7, 6, KEY_KP3) /* 0x07060051 */
+ MATRIX_KEY(7, 7, KEY_KP4) /* 0x0707004b */
+ MATRIX_KEY(7, 2, KEY_KP5) /* 0x0702004c */
+ MATRIX_KEY(7, 3, KEY_KP6) /* 0x0703004d */
+ MATRIX_KEY(2, 6, KEY_KP7) /* 0x02060047 */
+ MATRIX_KEY(2, 7, KEY_KP8) /* 0x02070048 */
+ MATRIX_KEY(2, 2, KEY_KP9) /* 0x02020049 */
+ >;
+ status = "okay";
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ #pwm-cells = <3>;
+ status = "disabled";
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ #pwm-cells = <3>;
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usbh1_vbus>;
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usbotg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ dr_mode = "peripheral";
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ bus-width = <4>;
+ no-1-8-v;
+ cd-gpios = <&gpio7 2 0>;
+ fsl,wp-controller;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ no-1-8-v;
+ cd-gpios = <&gpio7 3 0>;
+ fsl,wp-controller;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
new file mode 100644
index 000000000000..ef7fa62b9898
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.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 "imx6qdl-wandboard.dtsi"
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-wandboard {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* GPIO_0_CLKO */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
+ MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x0f0b0 /* WL_REF_ON */
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x0f0b0 /* WL_RST_N */
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON */
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
+ MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x80000000 /* BT_ON */
+ MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x80000000 /* BT_WAKE */
+ MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x80000000 /* BT_HOST_WAKE */
+ >;
+ };
+ };
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ non-removable;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
new file mode 100644
index 000000000000..8d893a78cdf0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.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 "imx6qdl-wandboard.dtsi"
+
+&iomuxc {
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-wandboard {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* GPIO_0_CLKO */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x0f0b0 /* WIFI_ON (reset, active low) */
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x000b0 /* WL_REG_ON (unused) */
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE, input */
+ MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x0f0b0 /* GPIO5_IO31 (Wifi Power Enable) */
+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE (unused) */
+ MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x80000000 /* BT_ON */
+ MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x80000000 /* BT_WAKE */
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x80000000 /* BT_HOST_WAKE */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* RGMII_nRST */
+ >;
+ };
+ };
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index 5c6f10c43f65..5fb091675582 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -91,22 +91,8 @@
&iomuxc {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
imx6qdl-wandboard {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
- MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
- MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x80000000 /* WL_REF_ON */
- MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000 /* WL_RST_N */
- MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* WL_REG_ON */
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
- MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
- MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
- >;
- };
pinctrl_audmux: audmuxgrp {
fsl,pins = <
@@ -233,7 +219,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
@@ -269,13 +254,6 @@
status = "okay";
};
-&usdhc2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc2>;
- non-removable;
- status = "okay";
-};
-
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index ce0599134a69..c701af958006 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -10,6 +10,7 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <dt-bindings/clock/imx6qdl-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "skeleton.dtsi"
@@ -94,7 +95,7 @@
interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
#dma-cells = <1>;
dma-channels = <4>;
- clocks = <&clks 106>;
+ clocks = <&clks IMX6QDL_CLK_APBH_DMA>;
};
gpmi: gpmi-nand@00112000 {
@@ -105,8 +106,11 @@
reg-names = "gpmi-nand", "bch";
interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "bch";
- clocks = <&clks 152>, <&clks 153>, <&clks 151>,
- <&clks 150>, <&clks 149>;
+ clocks = <&clks IMX6QDL_CLK_GPMI_IO>,
+ <&clks IMX6QDL_CLK_GPMI_APB>,
+ <&clks IMX6QDL_CLK_GPMI_BCH>,
+ <&clks IMX6QDL_CLK_GPMI_BCH_APB>,
+ <&clks IMX6QDL_CLK_PER1_BCH>;
clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
"gpmi_bch_apb", "per1_bch";
dmas = <&dma_apbh 0>;
@@ -118,7 +122,7 @@
compatible = "arm,cortex-a9-twd-timer";
reg = <0x00a00600 0x20>;
interrupts = <1 13 0xf01>;
- clocks = <&clks 15>;
+ clocks = <&clks IMX6QDL_CLK_TWD>;
};
L2: l2-cache@00a02000 {
@@ -149,7 +153,9 @@
<0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 144>, <&clks 206>, <&clks 189>;
+ clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
+ <&clks IMX6QDL_CLK_LVDS1_GATE>,
+ <&clks IMX6QDL_CLK_PCIE_REF_125M>;
clock-names = "pcie", "pcie_bus", "pcie_phy";
status = "disabled";
};
@@ -180,11 +186,11 @@
dmas = <&sdma 14 18 0>,
<&sdma 15 18 0>;
dma-names = "rx", "tx";
- clocks = <&clks 197>, <&clks 3>,
- <&clks 197>, <&clks 107>,
- <&clks 0>, <&clks 118>,
- <&clks 0>, <&clks 139>,
- <&clks 0>;
+ clocks = <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_OSC>,
+ <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_DUMMY>,
+ <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>,
+ <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>,
+ <&clks IMX6QDL_CLK_DUMMY>;
clock-names = "core", "rxtx0",
"rxtx1", "rxtx2",
"rxtx3", "rxtx4",
@@ -199,7 +205,8 @@
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 112>, <&clks 112>;
+ clocks = <&clks IMX6QDL_CLK_ECSPI1>,
+ <&clks IMX6QDL_CLK_ECSPI1>;
clock-names = "ipg", "per";
dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
@@ -212,7 +219,8 @@
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 113>, <&clks 113>;
+ clocks = <&clks IMX6QDL_CLK_ECSPI2>,
+ <&clks IMX6QDL_CLK_ECSPI2>;
clock-names = "ipg", "per";
dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
dma-names = "rx", "tx";
@@ -225,7 +233,8 @@
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 114>, <&clks 114>;
+ clocks = <&clks IMX6QDL_CLK_ECSPI3>,
+ <&clks IMX6QDL_CLK_ECSPI3>;
clock-names = "ipg", "per";
dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
dma-names = "rx", "tx";
@@ -238,7 +247,8 @@
compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 115>, <&clks 115>;
+ clocks = <&clks IMX6QDL_CLK_ECSPI4>,
+ <&clks IMX6QDL_CLK_ECSPI4>;
clock-names = "ipg", "per";
dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
dma-names = "rx", "tx";
@@ -249,7 +259,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x02020000 0x4000>;
interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+ <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
dma-names = "rx", "tx";
@@ -263,46 +274,40 @@
ssi1: ssi@02028000 {
compatible = "fsl,imx6q-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x02028000 0x4000>;
interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 178>;
+ clocks = <&clks IMX6QDL_CLK_SSI1_IPG>;
dmas = <&sdma 37 1 0>,
<&sdma 38 1 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <38 37>;
status = "disabled";
};
ssi2: ssi@0202c000 {
compatible = "fsl,imx6q-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x0202c000 0x4000>;
interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 179>;
+ clocks = <&clks IMX6QDL_CLK_SSI2_IPG>;
dmas = <&sdma 41 1 0>,
<&sdma 42 1 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <42 41>;
status = "disabled";
};
ssi3: ssi@02030000 {
compatible = "fsl,imx6q-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x02030000 0x4000>;
interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 180>;
+ clocks = <&clks IMX6QDL_CLK_SSI3_IPG>;
dmas = <&sdma 45 1 0>,
<&sdma 46 1 0>;
dma-names = "rx", "tx";
fsl,fifo-depth = <15>;
- fsl,ssi-dma-events = <46 45>;
status = "disabled";
};
@@ -331,7 +336,8 @@
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02080000 0x4000>;
interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 145>;
+ clocks = <&clks IMX6QDL_CLK_IPG>,
+ <&clks IMX6QDL_CLK_PWM1>;
clock-names = "ipg", "per";
};
@@ -340,7 +346,8 @@
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02084000 0x4000>;
interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 146>;
+ clocks = <&clks IMX6QDL_CLK_IPG>,
+ <&clks IMX6QDL_CLK_PWM2>;
clock-names = "ipg", "per";
};
@@ -349,7 +356,8 @@
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x02088000 0x4000>;
interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 147>;
+ clocks = <&clks IMX6QDL_CLK_IPG>,
+ <&clks IMX6QDL_CLK_PWM3>;
clock-names = "ipg", "per";
};
@@ -358,7 +366,8 @@
compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
reg = <0x0208c000 0x4000>;
interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 62>, <&clks 148>;
+ clocks = <&clks IMX6QDL_CLK_IPG>,
+ <&clks IMX6QDL_CLK_PWM4>;
clock-names = "ipg", "per";
};
@@ -366,7 +375,8 @@
compatible = "fsl,imx6q-flexcan";
reg = <0x02090000 0x4000>;
interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 108>, <&clks 109>;
+ clocks = <&clks IMX6QDL_CLK_CAN1_IPG>,
+ <&clks IMX6QDL_CLK_CAN1_SERIAL>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -375,7 +385,8 @@
compatible = "fsl,imx6q-flexcan";
reg = <0x02094000 0x4000>;
interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 110>, <&clks 111>;
+ clocks = <&clks IMX6QDL_CLK_CAN2_IPG>,
+ <&clks IMX6QDL_CLK_CAN2_SERIAL>;
clock-names = "ipg", "per";
status = "disabled";
};
@@ -384,7 +395,8 @@
compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
reg = <0x02098000 0x4000>;
interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 119>, <&clks 120>;
+ clocks = <&clks IMX6QDL_CLK_GPT_IPG>,
+ <&clks IMX6QDL_CLK_GPT_IPG_PER>;
clock-names = "ipg", "per";
};
@@ -466,22 +478,25 @@
};
kpp: kpp@020b8000 {
+ compatible = "fsl,imx6q-kpp", "fsl,imx21-kpp";
reg = <0x020b8000 0x4000>;
interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6QDL_CLK_IPG>;
+ status = "disabled";
};
wdog1: wdog@020bc000 {
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020bc000 0x4000>;
interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX6QDL_CLK_DUMMY>;
};
wdog2: wdog@020c0000 {
compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
reg = <0x020c0000 0x4000>;
interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 0>;
+ clocks = <&clks IMX6QDL_CLK_DUMMY>;
status = "disabled";
};
@@ -599,14 +614,14 @@
interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
fsl,tempmon = <&anatop>;
fsl,tempmon-data = <&ocotp>;
- clocks = <&clks 172>;
+ clocks = <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
};
usbphy1: usbphy@020c9000 {
compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
reg = <0x020c9000 0x1000>;
interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 182>;
+ clocks = <&clks IMX6QDL_CLK_USBPHY1>;
fsl,anatop = <&anatop>;
};
@@ -614,7 +629,7 @@
compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
reg = <0x020ca000 0x1000>;
interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 183>;
+ clocks = <&clks IMX6QDL_CLK_USBPHY2>;
fsl,anatop = <&anatop>;
};
@@ -727,7 +742,8 @@
reg = <0x00120000 0x9000>;
interrupts = <0 115 0x04>;
gpr = <&gpr>;
- clocks = <&clks 123>, <&clks 124>;
+ clocks = <&clks IMX6QDL_CLK_HDMI_IAHB>,
+ <&clks IMX6QDL_CLK_HDMI_ISFR>;
clock-names = "iahb", "isfr";
status = "disabled";
@@ -762,7 +778,8 @@
compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 155>, <&clks 155>;
+ clocks = <&clks IMX6QDL_CLK_SDMA>,
+ <&clks IMX6QDL_CLK_SDMA>;
clock-names = "ipg", "ahb";
#dma-cells = <3>;
fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
@@ -790,7 +807,7 @@
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184000 0x200>;
interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
+ clocks = <&clks IMX6QDL_CLK_USBOH3>;
fsl,usbphy = <&usbphy1>;
fsl,usbmisc = <&usbmisc 0>;
status = "disabled";
@@ -800,7 +817,7 @@
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184200 0x200>;
interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
+ clocks = <&clks IMX6QDL_CLK_USBOH3>;
fsl,usbphy = <&usbphy2>;
fsl,usbmisc = <&usbmisc 1>;
status = "disabled";
@@ -810,7 +827,7 @@
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184400 0x200>;
interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
+ clocks = <&clks IMX6QDL_CLK_USBOH3>;
fsl,usbmisc = <&usbmisc 2>;
status = "disabled";
};
@@ -819,7 +836,7 @@
compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
reg = <0x02184600 0x200>;
interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 162>;
+ clocks = <&clks IMX6QDL_CLK_USBOH3>;
fsl,usbmisc = <&usbmisc 3>;
status = "disabled";
};
@@ -828,7 +845,7 @@
#index-cells = <1>;
compatible = "fsl,imx6q-usbmisc";
reg = <0x02184800 0x200>;
- clocks = <&clks 162>;
+ clocks = <&clks IMX6QDL_CLK_USBOH3>;
};
fec: ethernet@02188000 {
@@ -837,7 +854,9 @@
interrupts-extended =
<&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
<&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 117>, <&clks 117>, <&clks 190>;
+ clocks = <&clks IMX6QDL_CLK_ENET>,
+ <&clks IMX6QDL_CLK_ENET>,
+ <&clks IMX6QDL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp";
status = "disabled";
};
@@ -853,7 +872,9 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02190000 0x4000>;
interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 163>, <&clks 163>, <&clks 163>;
+ clocks = <&clks IMX6QDL_CLK_USDHC1>,
+ <&clks IMX6QDL_CLK_USDHC1>,
+ <&clks IMX6QDL_CLK_USDHC1>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
status = "disabled";
@@ -863,7 +884,9 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02194000 0x4000>;
interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 164>, <&clks 164>, <&clks 164>;
+ clocks = <&clks IMX6QDL_CLK_USDHC2>,
+ <&clks IMX6QDL_CLK_USDHC2>,
+ <&clks IMX6QDL_CLK_USDHC2>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
status = "disabled";
@@ -873,7 +896,9 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x02198000 0x4000>;
interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 165>, <&clks 165>, <&clks 165>;
+ clocks = <&clks IMX6QDL_CLK_USDHC3>,
+ <&clks IMX6QDL_CLK_USDHC3>,
+ <&clks IMX6QDL_CLK_USDHC3>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
status = "disabled";
@@ -883,7 +908,9 @@
compatible = "fsl,imx6q-usdhc";
reg = <0x0219c000 0x4000>;
interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 166>, <&clks 166>, <&clks 166>;
+ clocks = <&clks IMX6QDL_CLK_USDHC4>,
+ <&clks IMX6QDL_CLK_USDHC4>,
+ <&clks IMX6QDL_CLK_USDHC4>;
clock-names = "ipg", "ahb", "per";
bus-width = <4>;
status = "disabled";
@@ -895,7 +922,7 @@
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 125>;
+ clocks = <&clks IMX6QDL_CLK_I2C1>;
status = "disabled";
};
@@ -905,7 +932,7 @@
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021a4000 0x4000>;
interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 126>;
+ clocks = <&clks IMX6QDL_CLK_I2C2>;
status = "disabled";
};
@@ -915,7 +942,7 @@
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021a8000 0x4000>;
interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 127>;
+ clocks = <&clks IMX6QDL_CLK_I2C3>;
status = "disabled";
};
@@ -936,7 +963,7 @@
compatible = "fsl,imx6q-weim";
reg = <0x021b8000 0x4000>;
interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 196>;
+ clocks = <&clks IMX6QDL_CLK_EIM_SLOW>;
};
ocotp: ocotp@021bc000 {
@@ -996,7 +1023,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021e8000 0x4000>;
interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+ <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
dma-names = "rx", "tx";
@@ -1007,7 +1035,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021ec000 0x4000>;
interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+ <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
dma-names = "rx", "tx";
@@ -1018,7 +1047,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f0000 0x4000>;
interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+ <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
dma-names = "rx", "tx";
@@ -1029,7 +1059,8 @@
compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
reg = <0x021f4000 0x4000>;
interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 160>, <&clks 161>;
+ clocks = <&clks IMX6QDL_CLK_UART_IPG>,
+ <&clks IMX6QDL_CLK_UART_SERIAL>;
clock-names = "ipg", "per";
dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
dma-names = "rx", "tx";
@@ -1044,10 +1075,20 @@
reg = <0x02400000 0x400000>;
interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
<0 5 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks 130>, <&clks 131>, <&clks 132>;
+ clocks = <&clks IMX6QDL_CLK_IPU1>,
+ <&clks IMX6QDL_CLK_IPU1_DI0>,
+ <&clks IMX6QDL_CLK_IPU1_DI1>;
clock-names = "bus", "di0", "di1";
resets = <&src 2>;
+ ipu1_csi0: port@0 {
+ reg = <0>;
+ };
+
+ ipu1_csi1: port@1 {
+ reg = <1>;
+ };
+
ipu1_di0: port@2 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index a8d9a93fab85..3f9e041c0252 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -116,8 +116,9 @@
};
&fec {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_fec>;
+ pinctrl-1 = <&pinctrl_fec_sleep>;
phy-mode = "rmii";
status = "okay";
};
@@ -300,6 +301,19 @@
>;
};
+ pinctrl_fec_sleep: fecgrp-sleep {
+ fsl,pins = <
+ MX6SL_PAD_FEC_MDC__GPIO4_IO23 0x3080
+ MX6SL_PAD_FEC_CRS_DV__GPIO4_IO25 0x3080
+ MX6SL_PAD_FEC_RXD0__GPIO4_IO17 0x3080
+ MX6SL_PAD_FEC_RXD1__GPIO4_IO18 0x3080
+ MX6SL_PAD_FEC_TX_EN__GPIO4_IO22 0x3080
+ MX6SL_PAD_FEC_TXD0__GPIO4_IO24 0x3080
+ MX6SL_PAD_FEC_TXD1__GPIO4_IO16 0x3080
+ MX6SL_PAD_FEC_REF_CLK__GPIO4_IO26 0x3080
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1
@@ -475,7 +489,6 @@
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 57d4abe03a94..c75800ca8b35 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -227,8 +227,7 @@
ssi1: ssi@02028000 {
compatible = "fsl,imx6sl-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x02028000 0x4000>;
interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_SSI1>;
@@ -241,8 +240,7 @@
ssi2: ssi@0202c000 {
compatible = "fsl,imx6sl-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x0202c000 0x4000>;
interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_SSI2>;
@@ -255,8 +253,7 @@
ssi3: ssi@02030000 {
compatible = "fsl,imx6sl-ssi",
- "fsl,imx51-ssi",
- "fsl,imx21-ssi";
+ "fsl,imx51-ssi";
reg = <0x02030000 0x4000>;
interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_SSI3>;
@@ -403,6 +400,7 @@
reg = <0x020b8000 0x4000>;
interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_DUMMY>;
+ status = "disabled";
};
wdog1: wdog@020bc000 {
@@ -607,7 +605,7 @@
};
sdma: sdma@020ec000 {
- compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma";
+ compatible = "fsl,imx6sl-sdma", "fsl,imx6q-sdma";
reg = <0x020ec000 0x4000>;
interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_SDMA>,
diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h
new file mode 100644
index 000000000000..3e0b816dac08
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-pinfunc.h
@@ -0,0 +1,1544 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX6SX_PINFUNC_H
+#define __DTS_IMX6SX_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x0014 0x035C 0x07A8 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO00__USDHC1_VSELECT 0x0014 0x035C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO00__SPDIF_LOCK 0x0014 0x035C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO00__CCM_WAIT 0x0014 0x035C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO00__WDOG1_WDOG_ANY 0x0014 0x035C 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO00__GPIO1_IO_0 0x0014 0x035C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO00__SNVS_HP_WRAPPER_VIO_5 0x0014 0x035C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO00__PHY_DTB_1 0x0014 0x035C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x0018 0x0360 0x07AC 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO01__USDHC1_RESET_B 0x0018 0x0360 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO01__SPDIF_SR_CLK 0x0018 0x0360 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO01__CCM_STOP 0x0018 0x0360 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO01__WDOG3_WDOG_B 0x0018 0x0360 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO01__GPIO1_IO_1 0x0018 0x0360 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO01__SNVS_HP_WRAPPER_VIO_5_CTL 0x0018 0x0360 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO01__PHY_DTB_0 0x0018 0x0360 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x001C 0x0364 0x07B0 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO02__USDHC1_CD_B 0x001C 0x0364 0x0864 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO02__CSI2_MCLK 0x001C 0x0364 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO02__CCM_DI0_EXT_CLK 0x001C 0x0364 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO02__WDOG1_WDOG_B 0x001C 0x0364 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO02__GPIO1_IO_2 0x001C 0x0364 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO02__CCM_REF_EN_B 0x001C 0x0364 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO02__PHY_TDI 0x001C 0x0364 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x0020 0x0368 0x07B4 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO03__USDHC1_WP 0x0020 0x0368 0x0868 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO03__ENET1_REF_CLK_25M 0x0020 0x0368 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO03__CCM_DI1_EXT_CLK 0x0020 0x0368 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO03__WDOG2_WDOG_B 0x0020 0x0368 0x0000 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO03__GPIO1_IO_3 0x0020 0x0368 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO03__CCM_PLL3_BYP 0x0020 0x0368 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO03__PHY_TCK 0x0020 0x0368 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO04__UART1_RX 0x0024 0x036C 0x0830 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO04__UART1_TX 0x0024 0x036C 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO04__USDHC2_RESET_B 0x0024 0x036C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO04__ENET1_MDC 0x0024 0x036C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO04__OSC32K_32K_OUT 0x0024 0x036C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO04__ENET2_REF_CLK2 0x0024 0x036C 0x076C 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO04__GPIO1_IO_4 0x0024 0x036C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO04__CCM_PLL2_BYP 0x0024 0x036C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO04__PHY_TMS 0x0024 0x036C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO05__UART1_RX 0x0028 0x0370 0x0830 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO05__UART1_TX 0x0028 0x0370 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO05__USDHC2_VSELECT 0x0028 0x0370 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO05__ENET1_MDIO 0x0028 0x0370 0x0764 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO05__ASRC_ASRC_EXT_CLK 0x0028 0x0370 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO05__ENET1_REF_CLK1 0x0028 0x0370 0x0760 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO05__GPIO1_IO_5 0x0028 0x0370 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO05__SRC_TESTER_ACK 0x0028 0x0370 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO05__PHY_TDO 0x0028 0x0370 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART2_RX 0x002C 0x0374 0x0838 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART2_TX 0x002C 0x0374 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO06__USDHC2_CD_B 0x002C 0x0374 0x086C 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO06__ENET2_MDC 0x002C 0x0374 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO06__CSI1_MCLK 0x002C 0x0374 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO06__UART1_RTS_B 0x002C 0x0374 0x082C 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO06__GPIO1_IO_6 0x002C 0x0374 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO06__SRC_ANY_PU_RESET 0x002C 0x0374 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO06__OCOTP_CTRL_WRAPPER_FUSE_LATCHED 0x002C 0x0374 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO07__UART2_RX 0x0030 0x0378 0x0838 0x0 0x1
+#define MX6SX_PAD_GPIO1_IO07__UART2_TX 0x0030 0x0378 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO07__USDHC2_WP 0x0030 0x0378 0x0870 0x1 0x1
+#define MX6SX_PAD_GPIO1_IO07__ENET2_MDIO 0x0030 0x0378 0x0770 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO07__AUDMUX_MCLK 0x0030 0x0378 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO07__UART1_CTS_B 0x0030 0x0378 0x082C 0x4 0x1
+#define MX6SX_PAD_GPIO1_IO07__GPIO1_IO_7 0x0030 0x0378 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO07__SRC_EARLY_RESET 0x0030 0x0378 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO07__DCIC2_OUT 0x0030 0x0378 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO07__VDEC_DEBUG_44 0x0030 0x0378 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO08__USB_OTG1_OC 0x0034 0x037C 0x0860 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO08__WDOG1_WDOG_B 0x0034 0x037C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO08__SDMA_EXT_EVENT_0 0x0034 0x037C 0x081C 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO08__CCM_PMIC_RDY 0x0034 0x037C 0x069C 0x3 0x1
+#define MX6SX_PAD_GPIO1_IO08__UART2_RTS_B 0x0034 0x037C 0x0834 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO08__GPIO1_IO_8 0x0034 0x037C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO08__SRC_SYSTEM_RESET 0x0034 0x037C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO08__DCIC1_OUT 0x0034 0x037C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO08__VDEC_DEBUG_43 0x0034 0x037C 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO09__USB_OTG1_PWR 0x0038 0x0380 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO09__WDOG2_WDOG_B 0x0038 0x0380 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO09__SDMA_EXT_EVENT_1 0x0038 0x0380 0x0820 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO09__CCM_OUT0 0x0038 0x0380 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO09__UART2_CTS_B 0x0038 0x0380 0x0834 0x4 0x1
+#define MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x0038 0x0380 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO09__SRC_INT_BOOT 0x0038 0x0380 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO09__OBSERVE_MUX_OUT_4 0x0038 0x0380 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO09__VDEC_DEBUG_42 0x0038 0x0380 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x003C 0x0384 0x0624 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO10__SPDIF_EXT_CLK 0x003C 0x0384 0x0828 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO10__PWM1_OUT 0x003C 0x0384 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO10__CCM_OUT1 0x003C 0x0384 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO10__CSI1_FIELD 0x003C 0x0384 0x070C 0x4 0x1
+#define MX6SX_PAD_GPIO1_IO10__GPIO1_IO_10 0x003C 0x0384 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO10__CSU_CSU_INT_DEB 0x003C 0x0384 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO10__OBSERVE_MUX_OUT_3 0x003C 0x0384 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO10__VDEC_DEBUG_41 0x003C 0x0384 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO11__USB_OTG2_OC 0x0040 0x0388 0x085C 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO11__SPDIF_IN 0x0040 0x0388 0x0824 0x1 0x2
+#define MX6SX_PAD_GPIO1_IO11__PWM2_OUT 0x0040 0x0388 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO11__CCM_CLKO1 0x0040 0x0388 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO11__MLB_DATA 0x0040 0x0388 0x07EC 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO11__GPIO1_IO_11 0x0040 0x0388 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO11__CSU_CSU_ALARM_AUT_0 0x0040 0x0388 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO11__OBSERVE_MUX_OUT_2 0x0040 0x0388 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO11__VDEC_DEBUG_40 0x0040 0x0388 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO12__USB_OTG2_PWR 0x0044 0x038C 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO12__SPDIF_OUT 0x0044 0x038C 0x0000 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO12__PWM3_OUT 0x0044 0x038C 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO12__CCM_CLKO2 0x0044 0x038C 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO12__MLB_CLK 0x0044 0x038C 0x07E8 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x0044 0x038C 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO12__CSU_CSU_ALARM_AUT_1 0x0044 0x038C 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO12__OBSERVE_MUX_OUT_1 0x0044 0x038C 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO12__VDEC_DEBUG_39 0x0044 0x038C 0x0000 0x8 0x0
+#define MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x0048 0x0390 0x0000 0x0 0x0
+#define MX6SX_PAD_GPIO1_IO13__ANATOP_OTG2_ID 0x0048 0x0390 0x0628 0x1 0x0
+#define MX6SX_PAD_GPIO1_IO13__PWM4_OUT 0x0048 0x0390 0x0000 0x2 0x0
+#define MX6SX_PAD_GPIO1_IO13__CCM_OUT2 0x0048 0x0390 0x0000 0x3 0x0
+#define MX6SX_PAD_GPIO1_IO13__MLB_SIG 0x0048 0x0390 0x07F0 0x4 0x0
+#define MX6SX_PAD_GPIO1_IO13__GPIO1_IO_13 0x0048 0x0390 0x0000 0x5 0x0
+#define MX6SX_PAD_GPIO1_IO13__CSU_CSU_ALARM_AUT_2 0x0048 0x0390 0x0000 0x6 0x0
+#define MX6SX_PAD_GPIO1_IO13__OBSERVE_MUX_OUT_0 0x0048 0x0390 0x0000 0x7 0x0
+#define MX6SX_PAD_GPIO1_IO13__VDEC_DEBUG_38 0x0048 0x0390 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA00__CSI1_DATA_2 0x004C 0x0394 0x06A8 0x0 0x0
+#define MX6SX_PAD_CSI_DATA00__ESAI_TX_CLK 0x004C 0x0394 0x078C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x004C 0x0394 0x0684 0x2 0x1
+#define MX6SX_PAD_CSI_DATA00__I2C1_SCL 0x004C 0x0394 0x07A8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA00__UART6_RI_B 0x004C 0x0394 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA00__GPIO1_IO_14 0x004C 0x0394 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA00__WEIM_DATA_23 0x004C 0x0394 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x004C 0x0394 0x0800 0x7 0x0
+#define MX6SX_PAD_CSI_DATA00__VADC_DATA_4 0x004C 0x0394 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA00__MMDC_DEBUG_37 0x004C 0x0394 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA01__CSI1_DATA_3 0x0050 0x0398 0x06AC 0x0 0x0
+#define MX6SX_PAD_CSI_DATA01__ESAI_TX_FS 0x0050 0x0398 0x077C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x0050 0x0398 0x0688 0x2 0x1
+#define MX6SX_PAD_CSI_DATA01__I2C1_SDA 0x0050 0x0398 0x07AC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA01__UART6_DSR_B 0x0050 0x0398 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA01__GPIO1_IO_15 0x0050 0x0398 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA01__WEIM_DATA_22 0x0050 0x0398 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x0050 0x0398 0x0804 0x7 0x0
+#define MX6SX_PAD_CSI_DATA01__VADC_DATA_5 0x0050 0x0398 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA01__MMDC_DEBUG_38 0x0050 0x0398 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA02__CSI1_DATA_4 0x0054 0x039C 0x06B0 0x0 0x0
+#define MX6SX_PAD_CSI_DATA02__ESAI_RX_CLK 0x0054 0x039C 0x0788 0x1 0x1
+#define MX6SX_PAD_CSI_DATA02__AUDMUX_AUD6_RXC 0x0054 0x039C 0x067C 0x2 0x1
+#define MX6SX_PAD_CSI_DATA02__KPP_COL_5 0x0054 0x039C 0x07C8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA02__UART6_DTR_B 0x0054 0x039C 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA02__GPIO1_IO_16 0x0054 0x039C 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA02__WEIM_DATA_21 0x0054 0x039C 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA02__SAI1_RX_BCLK 0x0054 0x039C 0x07F4 0x7 0x0
+#define MX6SX_PAD_CSI_DATA02__VADC_DATA_6 0x0054 0x039C 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA02__MMDC_DEBUG_39 0x0054 0x039C 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA03__CSI1_DATA_5 0x0058 0x03A0 0x06B4 0x0 0x0
+#define MX6SX_PAD_CSI_DATA03__ESAI_RX_FS 0x0058 0x03A0 0x0778 0x1 0x1
+#define MX6SX_PAD_CSI_DATA03__AUDMUX_AUD6_RXFS 0x0058 0x03A0 0x0680 0x2 0x1
+#define MX6SX_PAD_CSI_DATA03__KPP_ROW_5 0x0058 0x03A0 0x07D4 0x3 0x0
+#define MX6SX_PAD_CSI_DATA03__UART6_DCD_B 0x0058 0x03A0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA03__GPIO1_IO_17 0x0058 0x03A0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA03__WEIM_DATA_20 0x0058 0x03A0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA03__SAI1_RX_SYNC 0x0058 0x03A0 0x07FC 0x7 0x0
+#define MX6SX_PAD_CSI_DATA03__VADC_DATA_7 0x0058 0x03A0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA03__MMDC_DEBUG_40 0x0058 0x03A0 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA04__CSI1_DATA_6 0x005C 0x03A4 0x06B8 0x0 0x0
+#define MX6SX_PAD_CSI_DATA04__ESAI_TX1 0x005C 0x03A4 0x0794 0x1 0x1
+#define MX6SX_PAD_CSI_DATA04__SPDIF_OUT 0x005C 0x03A4 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_DATA04__KPP_COL_6 0x005C 0x03A4 0x07CC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA04__UART6_RX 0x005C 0x03A4 0x0858 0x4 0x0
+#define MX6SX_PAD_CSI_DATA04__UART6_TX 0x005C 0x03A4 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x005C 0x03A4 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA04__WEIM_DATA_19 0x005C 0x03A4 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA04__PWM5_OUT 0x005C 0x03A4 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA04__VADC_DATA_8 0x005C 0x03A4 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA04__MMDC_DEBUG_41 0x005C 0x03A4 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA05__CSI1_DATA_7 0x0060 0x03A8 0x06BC 0x0 0x0
+#define MX6SX_PAD_CSI_DATA05__ESAI_TX4_RX1 0x0060 0x03A8 0x07A0 0x1 0x1
+#define MX6SX_PAD_CSI_DATA05__SPDIF_IN 0x0060 0x03A8 0x0824 0x2 0x1
+#define MX6SX_PAD_CSI_DATA05__KPP_ROW_6 0x0060 0x03A8 0x07D8 0x3 0x0
+#define MX6SX_PAD_CSI_DATA05__UART6_RX 0x0060 0x03A8 0x0858 0x4 0x1
+#define MX6SX_PAD_CSI_DATA05__UART6_TX 0x0060 0x03A8 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x0060 0x03A8 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA05__WEIM_DATA_18 0x0060 0x03A8 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA05__PWM6_OUT 0x0060 0x03A8 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA05__VADC_DATA_9 0x0060 0x03A8 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA05__MMDC_DEBUG_42 0x0060 0x03A8 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA06__CSI1_DATA_8 0x0064 0x03AC 0x06C0 0x0 0x0
+#define MX6SX_PAD_CSI_DATA06__ESAI_TX2_RX3 0x0064 0x03AC 0x0798 0x1 0x1
+#define MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x0064 0x03AC 0x07C0 0x2 0x2
+#define MX6SX_PAD_CSI_DATA06__KPP_COL_7 0x0064 0x03AC 0x07D0 0x3 0x0
+#define MX6SX_PAD_CSI_DATA06__UART6_RTS_B 0x0064 0x03AC 0x0854 0x4 0x0
+#define MX6SX_PAD_CSI_DATA06__GPIO1_IO_20 0x0064 0x03AC 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA06__WEIM_DATA_17 0x0064 0x03AC 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA06__DCIC2_OUT 0x0064 0x03AC 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA06__VADC_DATA_10 0x0064 0x03AC 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA06__MMDC_DEBUG_43 0x0064 0x03AC 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_DATA07__CSI1_DATA_9 0x0068 0x03B0 0x06C4 0x0 0x0
+#define MX6SX_PAD_CSI_DATA07__ESAI_TX3_RX2 0x0068 0x03B0 0x079C 0x1 0x1
+#define MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x0068 0x03B0 0x07C4 0x2 0x2
+#define MX6SX_PAD_CSI_DATA07__KPP_ROW_7 0x0068 0x03B0 0x07DC 0x3 0x0
+#define MX6SX_PAD_CSI_DATA07__UART6_CTS_B 0x0068 0x03B0 0x0854 0x4 0x1
+#define MX6SX_PAD_CSI_DATA07__GPIO1_IO_21 0x0068 0x03B0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_DATA07__WEIM_DATA_16 0x0068 0x03B0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_DATA07__DCIC1_OUT 0x0068 0x03B0 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_DATA07__VADC_DATA_11 0x0068 0x03B0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_DATA07__MMDC_DEBUG_44 0x0068 0x03B0 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_HSYNC__CSI1_HSYNC 0x006C 0x03B4 0x0700 0x0 0x0
+#define MX6SX_PAD_CSI_HSYNC__ESAI_TX0 0x006C 0x03B4 0x0790 0x1 0x1
+#define MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x006C 0x03B4 0x0678 0x2 0x1
+#define MX6SX_PAD_CSI_HSYNC__UART4_RTS_B 0x006C 0x03B4 0x0844 0x3 0x2
+#define MX6SX_PAD_CSI_HSYNC__MQS_LEFT 0x006C 0x03B4 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_HSYNC__GPIO1_IO_22 0x006C 0x03B4 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_HSYNC__WEIM_DATA_25 0x006C 0x03B4 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x006C 0x03B4 0x0000 0x7 0x0
+#define MX6SX_PAD_CSI_HSYNC__VADC_DATA_2 0x006C 0x03B4 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_HSYNC__MMDC_DEBUG_35 0x006C 0x03B4 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_MCLK__CSI1_MCLK 0x0070 0x03B8 0x0000 0x0 0x0
+#define MX6SX_PAD_CSI_MCLK__ESAI_TX_HF_CLK 0x0070 0x03B8 0x0784 0x1 0x1
+#define MX6SX_PAD_CSI_MCLK__OSC32K_32K_OUT 0x0070 0x03B8 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_MCLK__UART4_RX 0x0070 0x03B8 0x0848 0x3 0x2
+#define MX6SX_PAD_CSI_MCLK__UART4_TX 0x0070 0x03B8 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_MCLK__ANATOP_32K_OUT 0x0070 0x03B8 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_MCLK__GPIO1_IO_23 0x0070 0x03B8 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_MCLK__WEIM_DATA_26 0x0070 0x03B8 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_MCLK__CSI1_FIELD 0x0070 0x03B8 0x070C 0x7 0x0
+#define MX6SX_PAD_CSI_MCLK__VADC_DATA_1 0x0070 0x03B8 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_MCLK__MMDC_DEBUG_34 0x0070 0x03B8 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_PIXCLK__CSI1_PIXCLK 0x0074 0x03BC 0x0704 0x0 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ESAI_RX_HF_CLK 0x0074 0x03BC 0x0780 0x1 0x1
+#define MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x0074 0x03BC 0x0000 0x2 0x0
+#define MX6SX_PAD_CSI_PIXCLK__UART4_RX 0x0074 0x03BC 0x0848 0x3 0x3
+#define MX6SX_PAD_CSI_PIXCLK__UART4_TX 0x0074 0x03BC 0x0000 0x3 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ANATOP_24M_OUT 0x0074 0x03BC 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_PIXCLK__GPIO1_IO_24 0x0074 0x03BC 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_PIXCLK__WEIM_DATA_27 0x0074 0x03BC 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_PIXCLK__ESAI_TX_HF_CLK 0x0074 0x03BC 0x0784 0x7 0x2
+#define MX6SX_PAD_CSI_PIXCLK__VADC_CLK 0x0074 0x03BC 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_PIXCLK__MMDC_DEBUG_33 0x0074 0x03BC 0x0000 0x9 0x0
+#define MX6SX_PAD_CSI_VSYNC__CSI1_VSYNC 0x0078 0x03C0 0x0708 0x0 0x0
+#define MX6SX_PAD_CSI_VSYNC__ESAI_TX5_RX0 0x0078 0x03C0 0x07A4 0x1 0x1
+#define MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x0078 0x03C0 0x0674 0x2 0x1
+#define MX6SX_PAD_CSI_VSYNC__UART4_CTS_B 0x0078 0x03C0 0x0844 0x3 0x3
+#define MX6SX_PAD_CSI_VSYNC__MQS_RIGHT 0x0078 0x03C0 0x0000 0x4 0x0
+#define MX6SX_PAD_CSI_VSYNC__GPIO1_IO_25 0x0078 0x03C0 0x0000 0x5 0x0
+#define MX6SX_PAD_CSI_VSYNC__WEIM_DATA_24 0x0078 0x03C0 0x0000 0x6 0x0
+#define MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x0078 0x03C0 0x07F8 0x7 0x0
+#define MX6SX_PAD_CSI_VSYNC__VADC_DATA_3 0x0078 0x03C0 0x0000 0x8 0x0
+#define MX6SX_PAD_CSI_VSYNC__MMDC_DEBUG_36 0x0078 0x03C0 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_COL__ENET1_COL 0x007C 0x03C4 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_COL__ENET2_MDC 0x007C 0x03C4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_COL__AUDMUX_AUD4_TXC 0x007C 0x03C4 0x0654 0x2 0x1
+#define MX6SX_PAD_ENET1_COL__UART1_RI_B 0x007C 0x03C4 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_COL__SPDIF_EXT_CLK 0x007C 0x03C4 0x0828 0x4 0x1
+#define MX6SX_PAD_ENET1_COL__GPIO2_IO_0 0x007C 0x03C4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_COL__CSI2_DATA_23 0x007C 0x03C4 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_COL__LCDIF2_DATA_16 0x007C 0x03C4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_COL__VDEC_DEBUG_37 0x007C 0x03C4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_COL__PCIE_CTRL_DEBUG_31 0x007C 0x03C4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_CRS__ENET1_CRS 0x0080 0x03C8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_CRS__ENET2_MDIO 0x0080 0x03C8 0x0770 0x1 0x1
+#define MX6SX_PAD_ENET1_CRS__AUDMUX_AUD4_TXD 0x0080 0x03C8 0x0648 0x2 0x1
+#define MX6SX_PAD_ENET1_CRS__UART1_DCD_B 0x0080 0x03C8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_CRS__SPDIF_LOCK 0x0080 0x03C8 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_CRS__GPIO2_IO_1 0x0080 0x03C8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_CRS__CSI2_DATA_22 0x0080 0x03C8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_CRS__LCDIF2_DATA_17 0x0080 0x03C8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_CRS__VDEC_DEBUG_36 0x0080 0x03C8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_CRS__PCIE_CTRL_DEBUG_30 0x0080 0x03C8 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_MDC__ENET1_MDC 0x0084 0x03CC 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_MDC__ENET2_MDC 0x0084 0x03CC 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_MDC__AUDMUX_AUD3_RXFS 0x0084 0x03CC 0x0638 0x2 0x1
+#define MX6SX_PAD_ENET1_MDC__ANATOP_24M_OUT 0x0084 0x03CC 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_MDC__EPIT2_OUT 0x0084 0x03CC 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_MDC__GPIO2_IO_2 0x0084 0x03CC 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_MDC__USB_OTG1_PWR 0x0084 0x03CC 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_MDC__PWM7_OUT 0x0084 0x03CC 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0x0088 0x03D0 0x0764 0x0 0x1
+#define MX6SX_PAD_ENET1_MDIO__ENET2_MDIO 0x0088 0x03D0 0x0770 0x1 0x2
+#define MX6SX_PAD_ENET1_MDIO__AUDMUX_MCLK 0x0088 0x03D0 0x0000 0x2 0x0
+#define MX6SX_PAD_ENET1_MDIO__OSC32K_32K_OUT 0x0088 0x03D0 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_MDIO__EPIT1_OUT 0x0088 0x03D0 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_MDIO__GPIO2_IO_3 0x0088 0x03D0 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_MDIO__USB_OTG1_OC 0x0088 0x03D0 0x0860 0x6 0x1
+#define MX6SX_PAD_ENET1_MDIO__PWM8_OUT 0x0088 0x03D0 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__ENET1_RX_CLK 0x008C 0x03D4 0x0768 0x0 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__ENET1_REF_CLK_25M 0x008C 0x03D4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__AUDMUX_AUD4_TXFS 0x008C 0x03D4 0x0658 0x2 0x1
+#define MX6SX_PAD_ENET1_RX_CLK__UART1_DSR_B 0x008C 0x03D4 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__SPDIF_OUT 0x008C 0x03D4 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__GPIO2_IO_4 0x008C 0x03D4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__CSI2_DATA_21 0x008C 0x03D4 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__LCDIF2_DATA_18 0x008C 0x03D4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__VDEC_DEBUG_35 0x008C 0x03D4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_RX_CLK__PCIE_CTRL_DEBUG_29 0x008C 0x03D4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK 0x0090 0x03D8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x0090 0x03D8 0x0760 0x1 0x1
+#define MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD 0x0090 0x03D8 0x0644 0x2 0x1
+#define MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B 0x0090 0x03D8 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__SPDIF_SR_CLK 0x0090 0x03D8 0x0000 0x4 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__GPIO2_IO_5 0x0090 0x03D8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__CSI2_DATA_20 0x0090 0x03D8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__LCDIF2_DATA_19 0x0090 0x03D8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__VDEC_DEBUG_34 0x0090 0x03D8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET1_TX_CLK__PCIE_CTRL_DEBUG_28 0x0090 0x03D8 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_COL__ENET2_COL 0x0094 0x03DC 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_COL__ENET1_MDC 0x0094 0x03DC 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET2_COL__AUDMUX_AUD4_RXC 0x0094 0x03DC 0x064C 0x2 0x1
+#define MX6SX_PAD_ENET2_COL__UART1_RX 0x0094 0x03DC 0x0830 0x3 0x2
+#define MX6SX_PAD_ENET2_COL__UART1_TX 0x0094 0x03DC 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_COL__SPDIF_IN 0x0094 0x03DC 0x0824 0x4 0x3
+#define MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x0094 0x03DC 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_COL__ANATOP_OTG1_ID 0x0094 0x03DC 0x0624 0x6 0x1
+#define MX6SX_PAD_ENET2_COL__LCDIF2_DATA_20 0x0094 0x03DC 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_COL__VDEC_DEBUG_33 0x0094 0x03DC 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_COL__PCIE_CTRL_DEBUG_27 0x0094 0x03DC 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_CRS__ENET2_CRS 0x0098 0x03E0 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_CRS__ENET1_MDIO 0x0098 0x03E0 0x0764 0x1 0x2
+#define MX6SX_PAD_ENET2_CRS__AUDMUX_AUD4_RXFS 0x0098 0x03E0 0x0650 0x2 0x1
+#define MX6SX_PAD_ENET2_CRS__UART1_RX 0x0098 0x03E0 0x0830 0x3 0x3
+#define MX6SX_PAD_ENET2_CRS__UART1_TX 0x0098 0x03E0 0x0000 0x3 0x0
+#define MX6SX_PAD_ENET2_CRS__MLB_SIG 0x0098 0x03E0 0x07F0 0x4 0x1
+#define MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 0x0098 0x03E0 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_CRS__ANATOP_OTG2_ID 0x0098 0x03E0 0x0628 0x6 0x1
+#define MX6SX_PAD_ENET2_CRS__LCDIF2_DATA_21 0x0098 0x03E0 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_CRS__VDEC_DEBUG_32 0x0098 0x03E0 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_CRS__PCIE_CTRL_DEBUG_26 0x0098 0x03E0 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK 0x009C 0x03E4 0x0774 0x0 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x009C 0x03E4 0x0000 0x1 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__I2C3_SCL 0x009C 0x03E4 0x07B8 0x2 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__UART1_RTS_B 0x009C 0x03E4 0x082C 0x3 0x2
+#define MX6SX_PAD_ENET2_RX_CLK__MLB_DATA 0x009C 0x03E4 0x07EC 0x4 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8 0x009C 0x03E4 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__USB_OTG2_OC 0x009C 0x03E4 0x085C 0x6 0x1
+#define MX6SX_PAD_ENET2_RX_CLK__LCDIF2_DATA_22 0x009C 0x03E4 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__VDEC_DEBUG_31 0x009C 0x03E4 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_RX_CLK__PCIE_CTRL_DEBUG_25 0x009C 0x03E4 0x0000 0x9 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__ENET2_TX_CLK 0x00A0 0x03E8 0x0000 0x0 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x00A0 0x03E8 0x076C 0x1 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__I2C3_SDA 0x00A0 0x03E8 0x07BC 0x2 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__UART1_CTS_B 0x00A0 0x03E8 0x082C 0x3 0x3
+#define MX6SX_PAD_ENET2_TX_CLK__MLB_CLK 0x00A0 0x03E8 0x07E8 0x4 0x1
+#define MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 0x00A0 0x03E8 0x0000 0x5 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__USB_OTG2_PWR 0x00A0 0x03E8 0x0000 0x6 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__LCDIF2_DATA_23 0x00A0 0x03E8 0x0000 0x7 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__VDEC_DEBUG_30 0x00A0 0x03E8 0x0000 0x8 0x0
+#define MX6SX_PAD_ENET2_TX_CLK__PCIE_CTRL_DEBUG_24 0x00A0 0x03E8 0x0000 0x9 0x0
+#define MX6SX_PAD_KEY_COL0__KPP_COL_0 0x00A4 0x03EC 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL0__USDHC3_CD_B 0x00A4 0x03EC 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL0__UART6_RTS_B 0x00A4 0x03EC 0x0854 0x2 0x2
+#define MX6SX_PAD_KEY_COL0__ECSPI1_SCLK 0x00A4 0x03EC 0x0710 0x3 0x0
+#define MX6SX_PAD_KEY_COL0__AUDMUX_AUD5_TXC 0x00A4 0x03EC 0x066C 0x4 0x0
+#define MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x00A4 0x03EC 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL0__SDMA_EXT_EVENT_1 0x00A4 0x03EC 0x0820 0x6 0x1
+#define MX6SX_PAD_KEY_COL0__SAI2_TX_BCLK 0x00A4 0x03EC 0x0814 0x7 0x0
+#define MX6SX_PAD_KEY_COL0__VADC_DATA_0 0x00A4 0x03EC 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_COL1__KPP_COL_1 0x00A8 0x03F0 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL1__USDHC3_RESET_B 0x00A8 0x03F0 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL1__UART6_RX 0x00A8 0x03F0 0x0858 0x2 0x2
+#define MX6SX_PAD_KEY_COL1__UART6_TX 0x00A8 0x03F0 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_COL1__ECSPI1_MISO 0x00A8 0x03F0 0x0714 0x3 0x0
+#define MX6SX_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x00A8 0x03F0 0x0670 0x4 0x0
+#define MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x00A8 0x03F0 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL1__USDHC3_RESET 0x00A8 0x03F0 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL1__SAI2_TX_SYNC 0x00A8 0x03F0 0x0818 0x7 0x0
+#define MX6SX_PAD_KEY_COL2__KPP_COL_2 0x00AC 0x03F4 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL2__USDHC4_CD_B 0x00AC 0x03F4 0x0874 0x1 0x1
+#define MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x00AC 0x03F4 0x084C 0x2 0x2
+#define MX6SX_PAD_KEY_COL2__CAN1_TX 0x00AC 0x03F4 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL2__CANFD_TX1 0x00AC 0x03F4 0x0000 0x4 0x0
+#define MX6SX_PAD_KEY_COL2__GPIO2_IO_12 0x00AC 0x03F4 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL2__WEIM_DATA_30 0x00AC 0x03F4 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL2__ECSPI1_RDY 0x00AC 0x03F4 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_COL3__KPP_COL_3 0x00B0 0x03F8 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL3__USDHC4_LCTL 0x00B0 0x03F8 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL3__UART5_RX 0x00B0 0x03F8 0x0850 0x2 0x2
+#define MX6SX_PAD_KEY_COL3__UART5_TX 0x00B0 0x03F8 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_COL3__CAN2_TX 0x00B0 0x03F8 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL3__CANFD_TX2 0x00B0 0x03F8 0x0000 0x4 0x0
+#define MX6SX_PAD_KEY_COL3__GPIO2_IO_13 0x00B0 0x03F8 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL3__WEIM_DATA_28 0x00B0 0x03F8 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL3__ECSPI1_SS2 0x00B0 0x03F8 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_COL4__KPP_COL_4 0x00B4 0x03FC 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_COL4__ENET2_MDC 0x00B4 0x03FC 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_COL4__I2C3_SCL 0x00B4 0x03FC 0x07B8 0x2 0x2
+#define MX6SX_PAD_KEY_COL4__USDHC2_LCTL 0x00B4 0x03FC 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_COL4__AUDMUX_AUD5_RXC 0x00B4 0x03FC 0x0664 0x4 0x0
+#define MX6SX_PAD_KEY_COL4__GPIO2_IO_14 0x00B4 0x03FC 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_COL4__WEIM_CRE 0x00B4 0x03FC 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_COL4__SAI2_RX_BCLK 0x00B4 0x03FC 0x0808 0x7 0x0
+#define MX6SX_PAD_KEY_ROW0__KPP_ROW_0 0x00B8 0x0400 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW0__USDHC3_WP 0x00B8 0x0400 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW0__UART6_CTS_B 0x00B8 0x0400 0x0854 0x2 0x3
+#define MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI 0x00B8 0x0400 0x0718 0x3 0x0
+#define MX6SX_PAD_KEY_ROW0__AUDMUX_AUD5_TXD 0x00B8 0x0400 0x0660 0x4 0x0
+#define MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x00B8 0x0400 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW0__SDMA_EXT_EVENT_0 0x00B8 0x0400 0x081C 0x6 0x1
+#define MX6SX_PAD_KEY_ROW0__SAI2_TX_DATA_0 0x00B8 0x0400 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW0__GPU_IDLE 0x00B8 0x0400 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_ROW1__KPP_ROW_1 0x00BC 0x0404 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW1__USDHC4_VSELECT 0x00BC 0x0404 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW1__UART6_RX 0x00BC 0x0404 0x0858 0x2 0x3
+#define MX6SX_PAD_KEY_ROW1__UART6_TX 0x00BC 0x0404 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW1__ECSPI1_SS0 0x00BC 0x0404 0x071C 0x3 0x0
+#define MX6SX_PAD_KEY_ROW1__AUDMUX_AUD5_RXD 0x00BC 0x0404 0x065C 0x4 0x0
+#define MX6SX_PAD_KEY_ROW1__GPIO2_IO_16 0x00BC 0x0404 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW1__WEIM_DATA_31 0x00BC 0x0404 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW1__SAI2_RX_DATA_0 0x00BC 0x0404 0x080C 0x7 0x0
+#define MX6SX_PAD_KEY_ROW1__M4_NMI 0x00BC 0x0404 0x0000 0x8 0x0
+#define MX6SX_PAD_KEY_ROW2__KPP_ROW_2 0x00C0 0x0408 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW2__USDHC4_WP 0x00C0 0x0408 0x0878 0x1 0x1
+#define MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x00C0 0x0408 0x084C 0x2 0x3
+#define MX6SX_PAD_KEY_ROW2__CAN1_RX 0x00C0 0x0408 0x068C 0x3 0x1
+#define MX6SX_PAD_KEY_ROW2__CANFD_RX1 0x00C0 0x0408 0x0694 0x4 0x1
+#define MX6SX_PAD_KEY_ROW2__GPIO2_IO_17 0x00C0 0x0408 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW2__WEIM_DATA_29 0x00C0 0x0408 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW2__ECSPI1_SS3 0x00C0 0x0408 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW3__KPP_ROW_3 0x00C4 0x040C 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW3__USDHC3_LCTL 0x00C4 0x040C 0x0000 0x1 0x0
+#define MX6SX_PAD_KEY_ROW3__UART5_RX 0x00C4 0x040C 0x0850 0x2 0x3
+#define MX6SX_PAD_KEY_ROW3__UART5_TX 0x00C4 0x040C 0x0000 0x2 0x0
+#define MX6SX_PAD_KEY_ROW3__CAN2_RX 0x00C4 0x040C 0x0690 0x3 0x1
+#define MX6SX_PAD_KEY_ROW3__CANFD_RX2 0x00C4 0x040C 0x0698 0x4 0x1
+#define MX6SX_PAD_KEY_ROW3__GPIO2_IO_18 0x00C4 0x040C 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW3__WEIM_DTACK_B 0x00C4 0x040C 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW3__ECSPI1_SS1 0x00C4 0x040C 0x0000 0x7 0x0
+#define MX6SX_PAD_KEY_ROW4__KPP_ROW_4 0x00C8 0x0410 0x0000 0x0 0x0
+#define MX6SX_PAD_KEY_ROW4__ENET2_MDIO 0x00C8 0x0410 0x0770 0x1 0x3
+#define MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x00C8 0x0410 0x07BC 0x2 0x2
+#define MX6SX_PAD_KEY_ROW4__USDHC1_LCTL 0x00C8 0x0410 0x0000 0x3 0x0
+#define MX6SX_PAD_KEY_ROW4__AUDMUX_AUD5_RXFS 0x00C8 0x0410 0x0668 0x4 0x0
+#define MX6SX_PAD_KEY_ROW4__GPIO2_IO_19 0x00C8 0x0410 0x0000 0x5 0x0
+#define MX6SX_PAD_KEY_ROW4__WEIM_ACLK_FREERUN 0x00C8 0x0410 0x0000 0x6 0x0
+#define MX6SX_PAD_KEY_ROW4__SAI2_RX_SYNC 0x00C8 0x0410 0x0810 0x7 0x0
+#define MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x00CC 0x0414 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_CLK__LCDIF1_WR_RWN 0x00CC 0x0414 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_CLK__AUDMUX_AUD3_RXC 0x00CC 0x0414 0x0634 0x2 0x1
+#define MX6SX_PAD_LCD1_CLK__ENET1_1588_EVENT2_IN 0x00CC 0x0414 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_CLK__CSI1_DATA_16 0x00CC 0x0414 0x06DC 0x4 0x0
+#define MX6SX_PAD_LCD1_CLK__GPIO3_IO_0 0x00CC 0x0414 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_CLK__USDHC1_WP 0x00CC 0x0414 0x0868 0x6 0x0
+#define MX6SX_PAD_LCD1_CLK__SIM_M_HADDR_16 0x00CC 0x0414 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_CLK__VADC_TEST_0 0x00CC 0x0414 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_CLK__MMDC_DEBUG_0 0x00CC 0x0414 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x00D0 0x0418 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA00__WEIM_CS1_B 0x00D0 0x0418 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA00__M4_TRACE_0 0x00D0 0x0418 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA00__KITTEN_TRACE_0 0x00D0 0x0418 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA00__CSI1_DATA_20 0x00D0 0x0418 0x06EC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA00__GPIO3_IO_1 0x00D0 0x0418 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA00__SRC_BT_CFG_0 0x00D0 0x0418 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA00__SIM_M_HADDR_21 0x00D0 0x0418 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA00__VADC_TEST_5 0x00D0 0x0418 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA00__MMDC_DEBUG_5 0x00D0 0x0418 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x00D4 0x041C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA01__WEIM_CS2_B 0x00D4 0x041C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA01__M4_TRACE_1 0x00D4 0x041C 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA01__KITTEN_TRACE_1 0x00D4 0x041C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA01__CSI1_DATA_21 0x00D4 0x041C 0x06F0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA01__GPIO3_IO_2 0x00D4 0x041C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA01__SRC_BT_CFG_1 0x00D4 0x041C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA01__SIM_M_HADDR_22 0x00D4 0x041C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA01__VADC_TEST_6 0x00D4 0x041C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA01__MMDC_DEBUG_6 0x00D4 0x041C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x00D8 0x0420 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA02__WEIM_CS3_B 0x00D8 0x0420 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA02__M4_TRACE_2 0x00D8 0x0420 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA02__KITTEN_TRACE_2 0x00D8 0x0420 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA02__CSI1_DATA_22 0x00D8 0x0420 0x06F4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA02__GPIO3_IO_3 0x00D8 0x0420 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA02__SRC_BT_CFG_2 0x00D8 0x0420 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA02__SIM_M_HADDR_23 0x00D8 0x0420 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA02__VADC_TEST_7 0x00D8 0x0420 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA02__MMDC_DEBUG_7 0x00D8 0x0420 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x00DC 0x0424 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA03__WEIM_ADDR_24 0x00DC 0x0424 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA03__M4_TRACE_3 0x00DC 0x0424 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA03__KITTEN_TRACE_3 0x00DC 0x0424 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA03__CSI1_DATA_23 0x00DC 0x0424 0x06F8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA03__GPIO3_IO_4 0x00DC 0x0424 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA03__SRC_BT_CFG_3 0x00DC 0x0424 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA03__SIM_M_HADDR_24 0x00DC 0x0424 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA03__VADC_TEST_8 0x00DC 0x0424 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA03__MMDC_DEBUG_8 0x00DC 0x0424 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x00E0 0x0428 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA04__WEIM_ADDR_25 0x00E0 0x0428 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA04__KITTEN_TRACE_4 0x00E0 0x0428 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA04__CSI1_VSYNC 0x00E0 0x0428 0x0708 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA04__GPIO3_IO_5 0x00E0 0x0428 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA04__SRC_BT_CFG_4 0x00E0 0x0428 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA04__SIM_M_HADDR_25 0x00E0 0x0428 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA04__VADC_TEST_9 0x00E0 0x0428 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA04__MMDC_DEBUG_9 0x00E0 0x0428 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x00E4 0x042C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA05__WEIM_ADDR_26 0x00E4 0x042C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA05__KITTEN_TRACE_5 0x00E4 0x042C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA05__CSI1_HSYNC 0x00E4 0x042C 0x0700 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA05__GPIO3_IO_6 0x00E4 0x042C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA05__SRC_BT_CFG_5 0x00E4 0x042C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA05__SIM_M_HADDR_26 0x00E4 0x042C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA05__VADC_TEST_10 0x00E4 0x042C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA05__MMDC_DEBUG_10 0x00E4 0x042C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x00E8 0x0430 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA06__WEIM_EB_B_2 0x00E8 0x0430 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA06__KITTEN_TRACE_6 0x00E8 0x0430 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA06__CSI1_PIXCLK 0x00E8 0x0430 0x0704 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA06__GPIO3_IO_7 0x00E8 0x0430 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA06__SRC_BT_CFG_6 0x00E8 0x0430 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA06__SIM_M_HADDR_27 0x00E8 0x0430 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA06__VADC_TEST_11 0x00E8 0x0430 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA06__MMDC_DEBUG_11 0x00E8 0x0430 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x00EC 0x0434 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA07__WEIM_EB_B_3 0x00EC 0x0434 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA07__KITTEN_TRACE_7 0x00EC 0x0434 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA07__CSI1_MCLK 0x00EC 0x0434 0x0000 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA07__GPIO3_IO_8 0x00EC 0x0434 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA07__SRC_BT_CFG_7 0x00EC 0x0434 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA07__SIM_M_HADDR_28 0x00EC 0x0434 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA07__VADC_TEST_12 0x00EC 0x0434 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA07__MMDC_DEBUG_12 0x00EC 0x0434 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x00F0 0x0438 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA08__WEIM_AD_8 0x00F0 0x0438 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA08__KITTEN_TRACE_8 0x00F0 0x0438 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA08__CSI1_DATA_9 0x00F0 0x0438 0x06C4 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA08__GPIO3_IO_9 0x00F0 0x0438 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA08__SRC_BT_CFG_8 0x00F0 0x0438 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA08__SIM_M_HADDR_29 0x00F0 0x0438 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA08__VADC_TEST_13 0x00F0 0x0438 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA08__MMDC_DEBUG_13 0x00F0 0x0438 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x00F4 0x043C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA09__WEIM_AD_9 0x00F4 0x043C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA09__KITTEN_TRACE_9 0x00F4 0x043C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA09__CSI1_DATA_8 0x00F4 0x043C 0x06C0 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA09__GPIO3_IO_10 0x00F4 0x043C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA09__SRC_BT_CFG_9 0x00F4 0x043C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA09__SIM_M_HADDR_30 0x00F4 0x043C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA09__VADC_TEST_14 0x00F4 0x043C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA09__MMDC_DEBUG_14 0x00F4 0x043C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x00F8 0x0440 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA10__WEIM_AD_10 0x00F8 0x0440 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA10__KITTEN_TRACE_10 0x00F8 0x0440 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA10__CSI1_DATA_7 0x00F8 0x0440 0x06BC 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA10__GPIO3_IO_11 0x00F8 0x0440 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA10__SRC_BT_CFG_10 0x00F8 0x0440 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA10__SIM_M_HADDR_31 0x00F8 0x0440 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA10__VADC_TEST_15 0x00F8 0x0440 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA10__MMDC_DEBUG_15 0x00F8 0x0440 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x00FC 0x0444 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA11__WEIM_AD_11 0x00FC 0x0444 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA11__KITTEN_TRACE_11 0x00FC 0x0444 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA11__CSI1_DATA_6 0x00FC 0x0444 0x06B8 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA11__GPIO3_IO_12 0x00FC 0x0444 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA11__SRC_BT_CFG_11 0x00FC 0x0444 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA11__SIM_M_HBURST_0 0x00FC 0x0444 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA11__VADC_TEST_16 0x00FC 0x0444 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA11__MMDC_DEBUG_16 0x00FC 0x0444 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x0100 0x0448 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA12__WEIM_AD_12 0x0100 0x0448 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA12__KITTEN_TRACE_12 0x0100 0x0448 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA12__CSI1_DATA_5 0x0100 0x0448 0x06B4 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA12__GPIO3_IO_13 0x0100 0x0448 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA12__SRC_BT_CFG_12 0x0100 0x0448 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA12__SIM_M_HBURST_1 0x0100 0x0448 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA12__VADC_TEST_17 0x0100 0x0448 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA12__MMDC_DEBUG_17 0x0100 0x0448 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x0104 0x044C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA13__WEIM_AD_13 0x0104 0x044C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA13__KITTEN_TRACE_13 0x0104 0x044C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA13__CSI1_DATA_4 0x0104 0x044C 0x06B0 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA13__GPIO3_IO_14 0x0104 0x044C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA13__SRC_BT_CFG_13 0x0104 0x044C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA13__SIM_M_HBURST_2 0x0104 0x044C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA13__VADC_TEST_18 0x0104 0x044C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA13__MMDC_DEBUG_18 0x0104 0x044C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x0108 0x0450 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA14__WEIM_AD_14 0x0108 0x0450 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA14__KITTEN_TRACE_14 0x0108 0x0450 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA14__CSI1_DATA_3 0x0108 0x0450 0x06AC 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA14__GPIO3_IO_15 0x0108 0x0450 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA14__SRC_BT_CFG_14 0x0108 0x0450 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA14__SIM_M_HMASTLOCK 0x0108 0x0450 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA14__VADC_TEST_19 0x0108 0x0450 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA14__MMDC_DEBUG_19 0x0108 0x0450 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x010C 0x0454 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA15__WEIM_AD_15 0x010C 0x0454 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA15__KITTEN_TRACE_15 0x010C 0x0454 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA15__CSI1_DATA_2 0x010C 0x0454 0x06A8 0x4 0x1
+#define MX6SX_PAD_LCD1_DATA15__GPIO3_IO_16 0x010C 0x0454 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA15__SRC_BT_CFG_15 0x010C 0x0454 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA15__SIM_M_HPROT_0 0x010C 0x0454 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA15__VDEC_DEBUG_0 0x010C 0x0454 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA15__MMDC_DEBUG_20 0x010C 0x0454 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x0110 0x0458 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA16__WEIM_ADDR_16 0x0110 0x0458 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA16__M4_TRACE_CLK 0x0110 0x0458 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA16__KITTEN_TRACE_CLK 0x0110 0x0458 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA16__CSI1_DATA_1 0x0110 0x0458 0x06A4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA16__GPIO3_IO_17 0x0110 0x0458 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA16__SRC_BT_CFG_24 0x0110 0x0458 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA16__SIM_M_HPROT_1 0x0110 0x0458 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA16__VDEC_DEBUG_1 0x0110 0x0458 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA16__MMDC_DEBUG_21 0x0110 0x0458 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x0114 0x045C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA17__WEIM_ADDR_17 0x0114 0x045C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA17__KITTEN_TRACE_CTL 0x0114 0x045C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA17__CSI1_DATA_0 0x0114 0x045C 0x06A0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA17__GPIO3_IO_18 0x0114 0x045C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA17__SRC_BT_CFG_25 0x0114 0x045C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA17__SIM_M_HPROT_2 0x0114 0x045C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA17__VDEC_DEBUG_2 0x0114 0x045C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA17__MMDC_DEBUG_22 0x0114 0x045C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x0118 0x0460 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA18__WEIM_ADDR_18 0x0118 0x0460 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA18__M4_EVENTO 0x0118 0x0460 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA18__KITTEN_EVENTO 0x0118 0x0460 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA18__CSI1_DATA_15 0x0118 0x0460 0x06D8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA18__GPIO3_IO_19 0x0118 0x0460 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA18__SRC_BT_CFG_26 0x0118 0x0460 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA18__SIM_M_HPROT_3 0x0118 0x0460 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA18__VDEC_DEBUG_3 0x0118 0x0460 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA18__MMDC_DEBUG_23 0x0118 0x0460 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x011C 0x0464 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA19__WEIM_ADDR_19 0x011C 0x0464 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA19__M4_TRACE_SWO 0x011C 0x0464 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA19__CSI1_DATA_14 0x011C 0x0464 0x06D4 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA19__GPIO3_IO_20 0x011C 0x0464 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA19__SRC_BT_CFG_27 0x011C 0x0464 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA19__SIM_M_HREADYOUT 0x011C 0x0464 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA19__VDEC_DEBUG_4 0x011C 0x0464 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA19__MMDC_DEBUG_24 0x011C 0x0464 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x0120 0x0468 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA20__WEIM_ADDR_20 0x0120 0x0468 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA20__PWM8_OUT 0x0120 0x0468 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA20__ENET1_1588_EVENT2_OUT 0x0120 0x0468 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA20__CSI1_DATA_13 0x0120 0x0468 0x06D0 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA20__GPIO3_IO_21 0x0120 0x0468 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA20__SRC_BT_CFG_28 0x0120 0x0468 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA20__SIM_M_HRESP 0x0120 0x0468 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA20__VDEC_DEBUG_5 0x0120 0x0468 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA20__MMDC_DEBUG_25 0x0120 0x0468 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x0124 0x046C 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA21__WEIM_ADDR_21 0x0124 0x046C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA21__PWM7_OUT 0x0124 0x046C 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA21__ENET1_1588_EVENT3_OUT 0x0124 0x046C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA21__CSI1_DATA_12 0x0124 0x046C 0x06CC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA21__GPIO3_IO_22 0x0124 0x046C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA21__SRC_BT_CFG_29 0x0124 0x046C 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA21__SIM_M_HSIZE_0 0x0124 0x046C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA21__VDEC_DEBUG_6 0x0124 0x046C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA21__MMDC_DEBUG_26 0x0124 0x046C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x0128 0x0470 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA22__WEIM_ADDR_22 0x0128 0x0470 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA22__PWM6_OUT 0x0128 0x0470 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA22__ENET2_1588_EVENT2_OUT 0x0128 0x0470 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA22__CSI1_DATA_11 0x0128 0x0470 0x06C8 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA22__GPIO3_IO_23 0x0128 0x0470 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA22__SRC_BT_CFG_30 0x0128 0x0470 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA22__SIM_M_HSIZE_1 0x0128 0x0470 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA22__VDEC_DEBUG_7 0x0128 0x0470 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA22__MMDC_DEBUG_27 0x0128 0x0470 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x012C 0x0474 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_DATA23__WEIM_ADDR_23 0x012C 0x0474 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_DATA23__PWM5_OUT 0x012C 0x0474 0x0000 0x2 0x0
+#define MX6SX_PAD_LCD1_DATA23__ENET2_1588_EVENT3_OUT 0x012C 0x0474 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_DATA23__CSI1_DATA_10 0x012C 0x0474 0x06FC 0x4 0x0
+#define MX6SX_PAD_LCD1_DATA23__GPIO3_IO_24 0x012C 0x0474 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_DATA23__SRC_BT_CFG_31 0x012C 0x0474 0x0000 0x6 0x0
+#define MX6SX_PAD_LCD1_DATA23__SIM_M_HSIZE_2 0x012C 0x0474 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_DATA23__VDEC_DEBUG_8 0x012C 0x0474 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_DATA23__MMDC_DEBUG_28 0x012C 0x0474 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x0130 0x0478 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_ENABLE__LCDIF1_RD_E 0x0130 0x0478 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_ENABLE__AUDMUX_AUD3_TXC 0x0130 0x0478 0x063C 0x2 0x1
+#define MX6SX_PAD_LCD1_ENABLE__ENET1_1588_EVENT3_IN 0x0130 0x0478 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_ENABLE__CSI1_DATA_17 0x0130 0x0478 0x06E0 0x4 0x0
+#define MX6SX_PAD_LCD1_ENABLE__GPIO3_IO_25 0x0130 0x0478 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_ENABLE__USDHC1_CD_B 0x0130 0x0478 0x0864 0x6 0x0
+#define MX6SX_PAD_LCD1_ENABLE__SIM_M_HADDR_17 0x0130 0x0478 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_ENABLE__VADC_TEST_1 0x0130 0x0478 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_ENABLE__MMDC_DEBUG_1 0x0130 0x0478 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x0134 0x047C 0x07E0 0x0 0x0
+#define MX6SX_PAD_LCD1_HSYNC__LCDIF1_RS 0x0134 0x047C 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_HSYNC__AUDMUX_AUD3_TXD 0x0134 0x047C 0x0630 0x2 0x1
+#define MX6SX_PAD_LCD1_HSYNC__ENET2_1588_EVENT2_IN 0x0134 0x047C 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_HSYNC__CSI1_DATA_18 0x0134 0x047C 0x06E4 0x4 0x0
+#define MX6SX_PAD_LCD1_HSYNC__GPIO3_IO_26 0x0134 0x047C 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_HSYNC__USDHC2_WP 0x0134 0x047C 0x0870 0x6 0x0
+#define MX6SX_PAD_LCD1_HSYNC__SIM_M_HADDR_18 0x0134 0x047C 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_HSYNC__VADC_TEST_2 0x0134 0x047C 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_HSYNC__MMDC_DEBUG_2 0x0134 0x047C 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_RESET__LCDIF1_RESET 0x0138 0x0480 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_RESET__LCDIF1_CS 0x0138 0x0480 0x0000 0x1 0x0
+#define MX6SX_PAD_LCD1_RESET__AUDMUX_AUD3_RXD 0x0138 0x0480 0x062C 0x2 0x1
+#define MX6SX_PAD_LCD1_RESET__KITTEN_EVENTI 0x0138 0x0480 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_RESET__M4_EVENTI 0x0138 0x0480 0x0000 0x4 0x0
+#define MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x0138 0x0480 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_RESET__CCM_PMIC_RDY 0x0138 0x0480 0x069C 0x6 0x0
+#define MX6SX_PAD_LCD1_RESET__SIM_M_HADDR_20 0x0138 0x0480 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_RESET__VADC_TEST_4 0x0138 0x0480 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_RESET__MMDC_DEBUG_4 0x0138 0x0480 0x0000 0x9 0x0
+#define MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x013C 0x0484 0x0000 0x0 0x0
+#define MX6SX_PAD_LCD1_VSYNC__LCDIF1_BUSY 0x013C 0x0484 0x07E0 0x1 0x1
+#define MX6SX_PAD_LCD1_VSYNC__AUDMUX_AUD3_TXFS 0x013C 0x0484 0x0640 0x2 0x1
+#define MX6SX_PAD_LCD1_VSYNC__ENET2_1588_EVENT3_IN 0x013C 0x0484 0x0000 0x3 0x0
+#define MX6SX_PAD_LCD1_VSYNC__CSI1_DATA_19 0x013C 0x0484 0x06E8 0x4 0x0
+#define MX6SX_PAD_LCD1_VSYNC__GPIO3_IO_28 0x013C 0x0484 0x0000 0x5 0x0
+#define MX6SX_PAD_LCD1_VSYNC__USDHC2_CD_B 0x013C 0x0484 0x086C 0x6 0x0
+#define MX6SX_PAD_LCD1_VSYNC__SIM_M_HADDR_19 0x013C 0x0484 0x0000 0x7 0x0
+#define MX6SX_PAD_LCD1_VSYNC__VADC_TEST_3 0x013C 0x0484 0x0000 0x8 0x0
+#define MX6SX_PAD_LCD1_VSYNC__MMDC_DEBUG_3 0x013C 0x0484 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_ALE__RAWNAND_ALE 0x0140 0x0488 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_ALE__I2C3_SDA 0x0140 0x0488 0x07BC 0x1 0x0
+#define MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x0140 0x0488 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_ALE__ECSPI2_SS0 0x0140 0x0488 0x072C 0x3 0x0
+#define MX6SX_PAD_NAND_ALE__ESAI_TX3_RX2 0x0140 0x0488 0x079C 0x4 0x0
+#define MX6SX_PAD_NAND_ALE__GPIO4_IO_0 0x0140 0x0488 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_ALE__WEIM_CS0_B 0x0140 0x0488 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_ALE__TPSMP_HDATA_0 0x0140 0x0488 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_ALE__ANATOP_USBPHY1_TSTI_TX_EN 0x0140 0x0488 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_ALE__SDMA_DEBUG_PC_12 0x0140 0x0488 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CE0_B__RAWNAND_CE0_B 0x0144 0x048C 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CE0_B__USDHC2_VSELECT 0x0144 0x048C 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x0144 0x048C 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CE0_B__AUDMUX_AUD4_TXC 0x0144 0x048C 0x0654 0x3 0x0
+#define MX6SX_PAD_NAND_CE0_B__ESAI_TX_CLK 0x0144 0x048C 0x078C 0x4 0x0
+#define MX6SX_PAD_NAND_CE0_B__GPIO4_IO_1 0x0144 0x048C 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CE0_B__WEIM_LBA_B 0x0144 0x048C 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CE0_B__TPSMP_HDATA_3 0x0144 0x048C 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CE0_B__ANATOP_USBPHY1_TSTI_TX_HIZ 0x0144 0x048C 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CE0_B__SDMA_DEBUG_PC_9 0x0144 0x048C 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CE1_B__RAWNAND_CE1_B 0x0148 0x0490 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CE1_B__USDHC3_RESET_B 0x0148 0x0490 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x0148 0x0490 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CE1_B__AUDMUX_AUD4_TXD 0x0148 0x0490 0x0648 0x3 0x0
+#define MX6SX_PAD_NAND_CE1_B__ESAI_TX0 0x0148 0x0490 0x0790 0x4 0x0
+#define MX6SX_PAD_NAND_CE1_B__GPIO4_IO_2 0x0148 0x0490 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CE1_B__WEIM_OE 0x0148 0x0490 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CE1_B__TPSMP_HDATA_4 0x0148 0x0490 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CE1_B__ANATOP_USBPHY1_TSTI_TX_LS_MODE 0x0148 0x0490 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CE1_B__SDMA_DEBUG_PC_8 0x0148 0x0490 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_CLE__RAWNAND_CLE 0x014C 0x0494 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_CLE__I2C3_SCL 0x014C 0x0494 0x07B8 0x1 0x0
+#define MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x014C 0x0494 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_CLE__ECSPI2_SCLK 0x014C 0x0494 0x0720 0x3 0x0
+#define MX6SX_PAD_NAND_CLE__ESAI_TX2_RX3 0x014C 0x0494 0x0798 0x4 0x0
+#define MX6SX_PAD_NAND_CLE__GPIO4_IO_3 0x014C 0x0494 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_CLE__WEIM_BCLK 0x014C 0x0494 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_CLE__TPSMP_CLK 0x014C 0x0494 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_CLE__ANATOP_USBPHY1_TSTI_TX_DP 0x014C 0x0494 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_CLE__SDMA_DEBUG_PC_13 0x014C 0x0494 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA00__RAWNAND_DATA00 0x0150 0x0498 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA00__USDHC1_DATA4 0x0150 0x0498 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x0150 0x0498 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA00__ECSPI5_MISO 0x0150 0x0498 0x0754 0x3 0x0
+#define MX6SX_PAD_NAND_DATA00__ESAI_RX_CLK 0x0150 0x0498 0x0788 0x4 0x0
+#define MX6SX_PAD_NAND_DATA00__GPIO4_IO_4 0x0150 0x0498 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA00__WEIM_AD_0 0x0150 0x0498 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA00__TPSMP_HDATA_7 0x0150 0x0498 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA00__ANATOP_USBPHY1_TSTO_RX_DISCON_DET 0x0150 0x0498 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA00__SDMA_DEBUG_EVT_CHN_LINES_5 0x0150 0x0498 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA01__RAWNAND_DATA01 0x0154 0x049C 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA01__USDHC1_DATA5 0x0154 0x049C 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x0154 0x049C 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA01__ECSPI5_MOSI 0x0154 0x049C 0x0758 0x3 0x0
+#define MX6SX_PAD_NAND_DATA01__ESAI_RX_FS 0x0154 0x049C 0x0778 0x4 0x0
+#define MX6SX_PAD_NAND_DATA01__GPIO4_IO_5 0x0154 0x049C 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA01__WEIM_AD_1 0x0154 0x049C 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA01__TPSMP_HDATA_8 0x0154 0x049C 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA01__ANATOP_USBPHY1_TSTO_RX_HS_RXD 0x0154 0x049C 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA01__SDMA_DEBUG_EVT_CHN_LINES_4 0x0154 0x049C 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA02__RAWNAND_DATA02 0x0158 0x04A0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA02__USDHC1_DATA6 0x0158 0x04A0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x0158 0x04A0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA02__ECSPI5_SCLK 0x0158 0x04A0 0x0750 0x3 0x0
+#define MX6SX_PAD_NAND_DATA02__ESAI_TX_HF_CLK 0x0158 0x04A0 0x0784 0x4 0x0
+#define MX6SX_PAD_NAND_DATA02__GPIO4_IO_6 0x0158 0x04A0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA02__WEIM_AD_2 0x0158 0x04A0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA02__TPSMP_HDATA_9 0x0158 0x04A0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA02__ANATOP_USBPHY2_TSTO_PLL_CLK20DIV 0x0158 0x04A0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA02__SDMA_DEBUG_EVT_CHN_LINES_3 0x0158 0x04A0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA03__RAWNAND_DATA03 0x015C 0x04A4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA03__USDHC1_DATA7 0x015C 0x04A4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x015C 0x04A4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA03__ECSPI5_SS0 0x015C 0x04A4 0x075C 0x3 0x0
+#define MX6SX_PAD_NAND_DATA03__ESAI_RX_HF_CLK 0x015C 0x04A4 0x0780 0x4 0x0
+#define MX6SX_PAD_NAND_DATA03__GPIO4_IO_7 0x015C 0x04A4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA03__WEIM_AD_3 0x015C 0x04A4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA03__TPSMP_HDATA_10 0x015C 0x04A4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA03__ANATOP_USBPHY1_TSTO_RX_SQUELCH 0x015C 0x04A4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA03__SDMA_DEBUG_EVT_CHN_LINES_6 0x015C 0x04A4 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA04__RAWNAND_DATA04 0x0160 0x04A8 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA04__USDHC2_DATA4 0x0160 0x04A8 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA04__QSPI2_B_SS1_B 0x0160 0x04A8 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA04__UART3_RTS_B 0x0160 0x04A8 0x083C 0x3 0x0
+#define MX6SX_PAD_NAND_DATA04__AUDMUX_AUD4_RXFS 0x0160 0x04A8 0x0650 0x4 0x0
+#define MX6SX_PAD_NAND_DATA04__GPIO4_IO_8 0x0160 0x04A8 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA04__WEIM_AD_4 0x0160 0x04A8 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA04__TPSMP_HDATA_11 0x0160 0x04A8 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA04__ANATOP_USBPHY2_TSTO_RX_SQUELCH 0x0160 0x04A8 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA04__SDMA_DEBUG_CORE_STATE_0 0x0160 0x04A8 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA05__RAWNAND_DATA05 0x0164 0x04AC 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA05__USDHC2_DATA5 0x0164 0x04AC 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA05__QSPI2_B_DQS 0x0164 0x04AC 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA05__UART3_CTS_B 0x0164 0x04AC 0x083C 0x3 0x1
+#define MX6SX_PAD_NAND_DATA05__AUDMUX_AUD4_RXC 0x0164 0x04AC 0x064C 0x4 0x0
+#define MX6SX_PAD_NAND_DATA05__GPIO4_IO_9 0x0164 0x04AC 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA05__WEIM_AD_5 0x0164 0x04AC 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA05__TPSMP_HDATA_12 0x0164 0x04AC 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA05__ANATOP_USBPHY2_TSTO_RX_DISCON_DET 0x0164 0x04AC 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA05__SDMA_DEBUG_CORE_STATE_1 0x0164 0x04AC 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA06__RAWNAND_DATA06 0x0168 0x04B0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA06__USDHC2_DATA6 0x0168 0x04B0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA06__QSPI2_A_SS1_B 0x0168 0x04B0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA06__UART3_RX 0x0168 0x04B0 0x0840 0x3 0x0
+#define MX6SX_PAD_NAND_DATA06__UART3_TX 0x0168 0x04B0 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA06__PWM3_OUT 0x0168 0x04B0 0x0000 0x4 0x0
+#define MX6SX_PAD_NAND_DATA06__GPIO4_IO_10 0x0168 0x04B0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA06__WEIM_AD_6 0x0168 0x04B0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA06__TPSMP_HDATA_13 0x0168 0x04B0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA06__ANATOP_USBPHY2_TSTO_RX_FS_RXD 0x0168 0x04B0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA06__SDMA_DEBUG_CORE_STATE_2 0x0168 0x04B0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_DATA07__RAWNAND_DATA07 0x016C 0x04B4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_DATA07__USDHC2_DATA7 0x016C 0x04B4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_DATA07__QSPI2_A_DQS 0x016C 0x04B4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_DATA07__UART3_RX 0x016C 0x04B4 0x0840 0x3 0x1
+#define MX6SX_PAD_NAND_DATA07__UART3_TX 0x016C 0x04B4 0x0000 0x3 0x0
+#define MX6SX_PAD_NAND_DATA07__PWM4_OUT 0x016C 0x04B4 0x0000 0x4 0x0
+#define MX6SX_PAD_NAND_DATA07__GPIO4_IO_11 0x016C 0x04B4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_DATA07__WEIM_AD_7 0x016C 0x04B4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_DATA07__TPSMP_HDATA_14 0x016C 0x04B4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_DATA07__ANATOP_USBPHY1_TSTO_RX_FS_RXD 0x016C 0x04B4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_DATA07__SDMA_DEBUG_CORE_STATE_3 0x016C 0x04B4 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_RE_B__RAWNAND_RE_B 0x0170 0x04B8 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_RE_B__USDHC2_RESET_B 0x0170 0x04B8 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x0170 0x04B8 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_RE_B__AUDMUX_AUD4_TXFS 0x0170 0x04B8 0x0658 0x3 0x0
+#define MX6SX_PAD_NAND_RE_B__ESAI_TX_FS 0x0170 0x04B8 0x077C 0x4 0x0
+#define MX6SX_PAD_NAND_RE_B__GPIO4_IO_12 0x0170 0x04B8 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_RE_B__WEIM_RW 0x0170 0x04B8 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_RE_B__TPSMP_HDATA_5 0x0170 0x04B8 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_RE_B__ANATOP_USBPHY2_TSTO_RX_HS_RXD 0x0170 0x04B8 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_RE_B__SDMA_DEBUG_PC_7 0x0170 0x04B8 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_READY_B__RAWNAND_READY_B 0x0174 0x04BC 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_READY_B__USDHC1_VSELECT 0x0174 0x04BC 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x0174 0x04BC 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_READY_B__ECSPI2_MISO 0x0174 0x04BC 0x0724 0x3 0x0
+#define MX6SX_PAD_NAND_READY_B__ESAI_TX1 0x0174 0x04BC 0x0794 0x4 0x0
+#define MX6SX_PAD_NAND_READY_B__GPIO4_IO_13 0x0174 0x04BC 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_READY_B__WEIM_EB_B_1 0x0174 0x04BC 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_READY_B__TPSMP_HDATA_2 0x0174 0x04BC 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_READY_B__ANATOP_USBPHY1_TSTI_TX_DN 0x0174 0x04BC 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_READY_B__SDMA_DEBUG_PC_10 0x0174 0x04BC 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_WE_B__RAWNAND_WE_B 0x0178 0x04C0 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_WE_B__USDHC4_VSELECT 0x0178 0x04C0 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x0178 0x04C0 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_WE_B__AUDMUX_AUD4_RXD 0x0178 0x04C0 0x0644 0x3 0x0
+#define MX6SX_PAD_NAND_WE_B__ESAI_TX5_RX0 0x0178 0x04C0 0x07A4 0x4 0x0
+#define MX6SX_PAD_NAND_WE_B__GPIO4_IO_14 0x0178 0x04C0 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_WE_B__WEIM_WAIT 0x0178 0x04C0 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_WE_B__TPSMP_HDATA_6 0x0178 0x04C0 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_WE_B__ANATOP_USBPHY1_TSTO_PLL_CLK20DIV 0x0178 0x04C0 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_WE_B__SDMA_DEBUG_PC_6 0x0178 0x04C0 0x0000 0x9 0x0
+#define MX6SX_PAD_NAND_WP_B__RAWNAND_WP_B 0x017C 0x04C4 0x0000 0x0 0x0
+#define MX6SX_PAD_NAND_WP_B__USDHC1_RESET_B 0x017C 0x04C4 0x0000 0x1 0x0
+#define MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x017C 0x04C4 0x0000 0x2 0x0
+#define MX6SX_PAD_NAND_WP_B__ECSPI2_MOSI 0x017C 0x04C4 0x0728 0x3 0x0
+#define MX6SX_PAD_NAND_WP_B__ESAI_TX4_RX1 0x017C 0x04C4 0x07A0 0x4 0x0
+#define MX6SX_PAD_NAND_WP_B__GPIO4_IO_15 0x017C 0x04C4 0x0000 0x5 0x0
+#define MX6SX_PAD_NAND_WP_B__WEIM_EB_B_0 0x017C 0x04C4 0x0000 0x6 0x0
+#define MX6SX_PAD_NAND_WP_B__TPSMP_HDATA_1 0x017C 0x04C4 0x0000 0x7 0x0
+#define MX6SX_PAD_NAND_WP_B__ANATOP_USBPHY1_TSTI_TX_HS_MODE 0x017C 0x04C4 0x0000 0x8 0x0
+#define MX6SX_PAD_NAND_WP_B__SDMA_DEBUG_PC_11 0x017C 0x04C4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__QSPI1_A_DATA_0 0x0180 0x04C8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__USB_OTG2_OC 0x0180 0x04C8 0x085C 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA0__ECSPI1_MOSI 0x0180 0x04C8 0x0718 0x2 0x1
+#define MX6SX_PAD_QSPI1A_DATA0__ESAI_TX4_RX1 0x0180 0x04C8 0x07A0 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA0__CSI1_DATA_14 0x0180 0x04C8 0x06D4 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x0180 0x04C8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__WEIM_DATA_6 0x0180 0x04C8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__SIM_M_HADDR_3 0x0180 0x04C8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA0__SDMA_DEBUG_BUS_DEVICE_3 0x0180 0x04C8 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__QSPI1_A_DATA_1 0x0184 0x04CC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__ANATOP_OTG1_ID 0x0184 0x04CC 0x0624 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA1__ECSPI1_MISO 0x0184 0x04CC 0x0714 0x2 0x1
+#define MX6SX_PAD_QSPI1A_DATA1__ESAI_TX1 0x0184 0x04CC 0x0794 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA1__CSI1_DATA_13 0x0184 0x04CC 0x06D0 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA1__GPIO4_IO_17 0x0184 0x04CC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__WEIM_DATA_5 0x0184 0x04CC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__SIM_M_HADDR_4 0x0184 0x04CC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA1__SDMA_DEBUG_PC_0 0x0184 0x04CC 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__QSPI1_A_DATA_2 0x0188 0x04D0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__USB_OTG1_PWR 0x0188 0x04D0 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__ECSPI5_SS1 0x0188 0x04D0 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__ESAI_TX_CLK 0x0188 0x04D0 0x078C 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA2__CSI1_DATA_12 0x0188 0x04D0 0x06CC 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA2__GPIO4_IO_18 0x0188 0x04D0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__WEIM_DATA_4 0x0188 0x04D0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__SIM_M_HADDR_6 0x0188 0x04D0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA2__SDMA_DEBUG_PC_1 0x0188 0x04D0 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__QSPI1_A_DATA_3 0x018C 0x04D4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__USB_OTG1_OC 0x018C 0x04D4 0x0860 0x1 0x2
+#define MX6SX_PAD_QSPI1A_DATA3__ECSPI5_SS2 0x018C 0x04D4 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__ESAI_TX0 0x018C 0x04D4 0x0790 0x3 0x2
+#define MX6SX_PAD_QSPI1A_DATA3__CSI1_DATA_11 0x018C 0x04D4 0x06C8 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DATA3__GPIO4_IO_19 0x018C 0x04D4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__WEIM_DATA_3 0x018C 0x04D4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__SIM_M_HADDR_7 0x018C 0x04D4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DATA3__SDMA_DEBUG_PC_2 0x018C 0x04D4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_DQS__QSPI1_A_DQS 0x0190 0x04D8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_DQS__CAN2_TX 0x0190 0x04D8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_DQS__CANFD_TX2 0x0190 0x04D8 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1A_DQS__ECSPI5_MOSI 0x0190 0x04D8 0x0758 0x3 0x1
+#define MX6SX_PAD_QSPI1A_DQS__CSI1_DATA_15 0x0190 0x04D8 0x06D8 0x4 0x1
+#define MX6SX_PAD_QSPI1A_DQS__GPIO4_IO_20 0x0190 0x04D8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_DQS__WEIM_DATA_7 0x0190 0x04D8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_DQS__SIM_M_HADDR_13 0x0190 0x04D8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_DQS__SDMA_DEBUG_BUS_DEVICE_4 0x0190 0x04D8 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__QSPI1_A_SCLK 0x0194 0x04DC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__ANATOP_OTG2_ID 0x0194 0x04DC 0x0628 0x1 0x2
+#define MX6SX_PAD_QSPI1A_SCLK__ECSPI1_SCLK 0x0194 0x04DC 0x0710 0x2 0x1
+#define MX6SX_PAD_QSPI1A_SCLK__ESAI_TX2_RX3 0x0194 0x04DC 0x0798 0x3 0x2
+#define MX6SX_PAD_QSPI1A_SCLK__CSI1_DATA_1 0x0194 0x04DC 0x06A4 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SCLK__GPIO4_IO_21 0x0194 0x04DC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__WEIM_DATA_0 0x0194 0x04DC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__SIM_M_HADDR_0 0x0194 0x04DC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SCLK__SDMA_DEBUG_PC_5 0x0194 0x04DC 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__QSPI1_A_SS0_B 0x0198 0x04E0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__USB_OTG2_PWR 0x0198 0x04E0 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__ECSPI1_SS0 0x0198 0x04E0 0x071C 0x2 0x1
+#define MX6SX_PAD_QSPI1A_SS0_B__ESAI_TX3_RX2 0x0198 0x04E0 0x079C 0x3 0x2
+#define MX6SX_PAD_QSPI1A_SS0_B__CSI1_DATA_0 0x0198 0x04E0 0x06A0 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22 0x0198 0x04E0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__WEIM_DATA_1 0x0198 0x04E0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__SIM_M_HADDR_1 0x0198 0x04E0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SS0_B__SDMA_DEBUG_PC_4 0x0198 0x04E0 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__QSPI1_A_SS1_B 0x019C 0x04E4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX 0x019C 0x04E4 0x068C 0x1 0x2
+#define MX6SX_PAD_QSPI1A_SS1_B__CANFD_RX1 0x019C 0x04E4 0x0694 0x2 0x2
+#define MX6SX_PAD_QSPI1A_SS1_B__ECSPI5_MISO 0x019C 0x04E4 0x0754 0x3 0x1
+#define MX6SX_PAD_QSPI1A_SS1_B__CSI1_DATA_10 0x019C 0x04E4 0x06FC 0x4 0x1
+#define MX6SX_PAD_QSPI1A_SS1_B__GPIO4_IO_23 0x019C 0x04E4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__WEIM_DATA_2 0x019C 0x04E4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__SIM_M_HADDR_12 0x019C 0x04E4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1A_SS1_B__SDMA_DEBUG_PC_3 0x019C 0x04E4 0x0000 0x9 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__QSPI1_B_DATA_0 0x01A0 0x04E8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__UART3_CTS_B 0x01A0 0x04E8 0x083C 0x1 0x4
+#define MX6SX_PAD_QSPI1B_DATA0__ECSPI3_MOSI 0x01A0 0x04E8 0x0738 0x2 0x1
+#define MX6SX_PAD_QSPI1B_DATA0__ESAI_RX_FS 0x01A0 0x04E8 0x0778 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA0__CSI1_DATA_22 0x01A0 0x04E8 0x06F4 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA0__GPIO4_IO_24 0x01A0 0x04E8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__WEIM_DATA_14 0x01A0 0x04E8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA0__SIM_M_HADDR_9 0x01A0 0x04E8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__QSPI1_B_DATA_1 0x01A4 0x04EC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__UART3_RTS_B 0x01A4 0x04EC 0x083C 0x1 0x5
+#define MX6SX_PAD_QSPI1B_DATA1__ECSPI3_MISO 0x01A4 0x04EC 0x0734 0x2 0x1
+#define MX6SX_PAD_QSPI1B_DATA1__ESAI_RX_CLK 0x01A4 0x04EC 0x0788 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA1__CSI1_DATA_21 0x01A4 0x04EC 0x06F0 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25 0x01A4 0x04EC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__WEIM_DATA_13 0x01A4 0x04EC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA1__SIM_M_HADDR_8 0x01A4 0x04EC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__QSPI1_B_DATA_2 0x01A8 0x04F0 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__I2C2_SDA 0x01A8 0x04F0 0x07B4 0x1 0x2
+#define MX6SX_PAD_QSPI1B_DATA2__ECSPI5_RDY 0x01A8 0x04F0 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__ESAI_TX5_RX0 0x01A8 0x04F0 0x07A4 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA2__CSI1_DATA_20 0x01A8 0x04F0 0x06EC 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA2__GPIO4_IO_26 0x01A8 0x04F0 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__WEIM_DATA_12 0x01A8 0x04F0 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA2__SIM_M_HADDR_5 0x01A8 0x04F0 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__QSPI1_B_DATA_3 0x01AC 0x04F4 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__I2C2_SCL 0x01AC 0x04F4 0x07B0 0x1 0x2
+#define MX6SX_PAD_QSPI1B_DATA3__ECSPI5_SS3 0x01AC 0x04F4 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__ESAI_TX_FS 0x01AC 0x04F4 0x077C 0x3 0x2
+#define MX6SX_PAD_QSPI1B_DATA3__CSI1_DATA_19 0x01AC 0x04F4 0x06E8 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27 0x01AC 0x04F4 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__WEIM_DATA_11 0x01AC 0x04F4 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DATA3__SIM_M_HADDR_2 0x01AC 0x04F4 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_DQS__QSPI1_B_DQS 0x01B0 0x04F8 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_DQS__CAN1_TX 0x01B0 0x04F8 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_DQS__CANFD_TX1 0x01B0 0x04F8 0x0000 0x2 0x0
+#define MX6SX_PAD_QSPI1B_DQS__ECSPI5_SS0 0x01B0 0x04F8 0x075C 0x3 0x1
+#define MX6SX_PAD_QSPI1B_DQS__CSI1_DATA_23 0x01B0 0x04F8 0x06F8 0x4 0x1
+#define MX6SX_PAD_QSPI1B_DQS__GPIO4_IO_28 0x01B0 0x04F8 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_DQS__WEIM_DATA_15 0x01B0 0x04F8 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_DQS__SIM_M_HADDR_15 0x01B0 0x04F8 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__QSPI1_B_SCLK 0x01B4 0x04FC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__UART3_RX 0x01B4 0x04FC 0x0840 0x1 0x4
+#define MX6SX_PAD_QSPI1B_SCLK__UART3_TX 0x01B4 0x04FC 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__ECSPI3_SCLK 0x01B4 0x04FC 0x0730 0x2 0x1
+#define MX6SX_PAD_QSPI1B_SCLK__ESAI_RX_HF_CLK 0x01B4 0x04FC 0x0780 0x3 0x2
+#define MX6SX_PAD_QSPI1B_SCLK__CSI1_DATA_16 0x01B4 0x04FC 0x06DC 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SCLK__GPIO4_IO_29 0x01B4 0x04FC 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__WEIM_DATA_8 0x01B4 0x04FC 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SCLK__SIM_M_HADDR_11 0x01B4 0x04FC 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__QSPI1_B_SS0_B 0x01B8 0x0500 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__UART3_RX 0x01B8 0x0500 0x0840 0x1 0x5
+#define MX6SX_PAD_QSPI1B_SS0_B__UART3_TX 0x01B8 0x0500 0x0000 0x1 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__ECSPI3_SS0 0x01B8 0x0500 0x073C 0x2 0x1
+#define MX6SX_PAD_QSPI1B_SS0_B__ESAI_TX_HF_CLK 0x01B8 0x0500 0x0784 0x3 0x3
+#define MX6SX_PAD_QSPI1B_SS0_B__CSI1_DATA_17 0x01B8 0x0500 0x06E0 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SS0_B__GPIO4_IO_30 0x01B8 0x0500 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__WEIM_DATA_9 0x01B8 0x0500 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SS0_B__SIM_M_HADDR_10 0x01B8 0x0500 0x0000 0x7 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__QSPI1_B_SS1_B 0x01BC 0x0504 0x0000 0x0 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX 0x01BC 0x0504 0x0690 0x1 0x2
+#define MX6SX_PAD_QSPI1B_SS1_B__CANFD_RX2 0x01BC 0x0504 0x0698 0x2 0x2
+#define MX6SX_PAD_QSPI1B_SS1_B__ECSPI5_SCLK 0x01BC 0x0504 0x0750 0x3 0x1
+#define MX6SX_PAD_QSPI1B_SS1_B__CSI1_DATA_18 0x01BC 0x0504 0x06E4 0x4 0x1
+#define MX6SX_PAD_QSPI1B_SS1_B__GPIO4_IO_31 0x01BC 0x0504 0x0000 0x5 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__WEIM_DATA_10 0x01BC 0x0504 0x0000 0x6 0x0
+#define MX6SX_PAD_QSPI1B_SS1_B__SIM_M_HADDR_14 0x01BC 0x0504 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x01C0 0x0508 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD0__GPIO5_IO_0 0x01C0 0x0508 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD0__CSI2_DATA_10 0x01C0 0x0508 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD0__ANATOP_TESTI_0 0x01C0 0x0508 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD0__RAWNAND_TESTER_TRIGGER 0x01C0 0x0508 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD0__PCIE_CTRL_DEBUG_0 0x01C0 0x0508 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x01C4 0x050C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD1__GPIO5_IO_1 0x01C4 0x050C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD1__CSI2_DATA_11 0x01C4 0x050C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD1__ANATOP_TESTI_1 0x01C4 0x050C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD1__USDHC1_TESTER_TRIGGER 0x01C4 0x050C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD1__PCIE_CTRL_DEBUG_1 0x01C4 0x050C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x01C8 0x0510 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD2__GPIO5_IO_2 0x01C8 0x0510 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD2__CSI2_DATA_12 0x01C8 0x0510 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD2__ANATOP_TESTI_2 0x01C8 0x0510 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD2__USDHC2_TESTER_TRIGGER 0x01C8 0x0510 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD2__PCIE_CTRL_DEBUG_2 0x01C8 0x0510 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x01CC 0x0514 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RD3__GPIO5_IO_3 0x01CC 0x0514 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RD3__CSI2_DATA_13 0x01CC 0x0514 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RD3__ANATOP_TESTI_3 0x01CC 0x0514 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RD3__USDHC3_TESTER_TRIGGER 0x01CC 0x0514 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RD3__PCIE_CTRL_DEBUG_3 0x01CC 0x0514 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x01D0 0x0518 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__GPIO5_IO_4 0x01D0 0x0518 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__CSI2_DATA_14 0x01D0 0x0518 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__ANATOP_TESTO_0 0x01D0 0x0518 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__USDHC4_TESTER_TRIGGER 0x01D0 0x0518 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RX_CTL__PCIE_CTRL_DEBUG_4 0x01D0 0x0518 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x01D4 0x051C 0x0768 0x0 0x1
+#define MX6SX_PAD_RGMII1_RXC__ENET1_RX_ER 0x01D4 0x051C 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII1_RXC__GPIO5_IO_5 0x01D4 0x051C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_RXC__CSI2_DATA_15 0x01D4 0x051C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_RXC__ANATOP_TESTO_1 0x01D4 0x051C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_RXC__ECSPI1_TESTER_TRIGGER 0x01D4 0x051C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_RXC__PCIE_CTRL_DEBUG_5 0x01D4 0x051C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0x01D8 0x0520 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD0__SAI2_RX_SYNC 0x01D8 0x0520 0x0810 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD0__GPIO5_IO_6 0x01D8 0x0520 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD0__CSI2_DATA_16 0x01D8 0x0520 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD0__ANATOP_TESTO_2 0x01D8 0x0520 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD0__ECSPI2_TESTER_TRIGGER 0x01D8 0x0520 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD0__PCIE_CTRL_DEBUG_6 0x01D8 0x0520 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0x01DC 0x0524 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD1__SAI2_RX_BCLK 0x01DC 0x0524 0x0808 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD1__GPIO5_IO_7 0x01DC 0x0524 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD1__CSI2_DATA_17 0x01DC 0x0524 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD1__ANATOP_TESTO_3 0x01DC 0x0524 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD1__ECSPI3_TESTER_TRIGGER 0x01DC 0x0524 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD1__PCIE_CTRL_DEBUG_7 0x01DC 0x0524 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0x01E0 0x0528 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD2__SAI2_TX_SYNC 0x01E0 0x0528 0x0818 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD2__GPIO5_IO_8 0x01E0 0x0528 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD2__CSI2_DATA_18 0x01E0 0x0528 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD2__ANATOP_TESTO_4 0x01E0 0x0528 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD2__ECSPI4_TESTER_TRIGGER 0x01E0 0x0528 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD2__PCIE_CTRL_DEBUG_8 0x01E0 0x0528 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0x01E4 0x052C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TD3__SAI2_TX_BCLK 0x01E4 0x052C 0x0814 0x2 0x1
+#define MX6SX_PAD_RGMII1_TD3__GPIO5_IO_9 0x01E4 0x052C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TD3__CSI2_DATA_19 0x01E4 0x052C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TD3__ANATOP_TESTO_5 0x01E4 0x052C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TD3__ECSPI5_TESTER_TRIGGER 0x01E4 0x052C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TD3__PCIE_CTRL_DEBUG_9 0x01E4 0x052C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0x01E8 0x0530 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__SAI2_RX_DATA_0 0x01E8 0x0530 0x080C 0x2 0x1
+#define MX6SX_PAD_RGMII1_TX_CTL__GPIO5_IO_10 0x01E8 0x0530 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__CSI2_DATA_0 0x01E8 0x0530 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__ANATOP_TESTO_6 0x01E8 0x0530 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__QSPI1_TESTER_TRIGGER 0x01E8 0x0530 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TX_CTL__PCIE_CTRL_DEBUG_10 0x01E8 0x0530 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0x01EC 0x0534 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII1_TXC__ENET1_TX_ER 0x01EC 0x0534 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII1_TXC__SAI2_TX_DATA_0 0x01EC 0x0534 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII1_TXC__GPIO5_IO_11 0x01EC 0x0534 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII1_TXC__CSI2_DATA_1 0x01EC 0x0534 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII1_TXC__ANATOP_TESTO_7 0x01EC 0x0534 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII1_TXC__QSPI2_TESTER_TRIGGER 0x01EC 0x0534 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII1_TXC__PCIE_CTRL_DEBUG_11 0x01EC 0x0534 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x01F0 0x0538 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD0__PWM4_OUT 0x01F0 0x0538 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD0__GPIO5_IO_12 0x01F0 0x0538 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD0__CSI2_DATA_2 0x01F0 0x0538 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD0__ANATOP_TESTO_8 0x01F0 0x0538 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD0__VDEC_DEBUG_18 0x01F0 0x0538 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD0__PCIE_CTRL_DEBUG_12 0x01F0 0x0538 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x01F4 0x053C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD1__PWM3_OUT 0x01F4 0x053C 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD1__GPIO5_IO_13 0x01F4 0x053C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD1__CSI2_DATA_3 0x01F4 0x053C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD1__ANATOP_TESTO_9 0x01F4 0x053C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD1__VDEC_DEBUG_19 0x01F4 0x053C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD1__PCIE_CTRL_DEBUG_13 0x01F4 0x053C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x01F8 0x0540 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD2__PWM2_OUT 0x01F8 0x0540 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD2__GPIO5_IO_14 0x01F8 0x0540 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD2__CSI2_DATA_4 0x01F8 0x0540 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD2__ANATOP_TESTO_10 0x01F8 0x0540 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD2__VDEC_DEBUG_20 0x01F8 0x0540 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD2__PCIE_CTRL_DEBUG_14 0x01F8 0x0540 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x01FC 0x0544 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RD3__PWM1_OUT 0x01FC 0x0544 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_RD3__GPIO5_IO_15 0x01FC 0x0544 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RD3__CSI2_DATA_5 0x01FC 0x0544 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RD3__ANATOP_TESTO_11 0x01FC 0x0544 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RD3__VDEC_DEBUG_21 0x01FC 0x0544 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RD3__PCIE_CTRL_DEBUG_15 0x01FC 0x0544 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x0200 0x0548 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__GPIO5_IO_16 0x0200 0x0548 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__CSI2_DATA_6 0x0200 0x0548 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__ANATOP_TESTO_12 0x0200 0x0548 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__VDEC_DEBUG_22 0x0200 0x0548 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RX_CTL__PCIE_CTRL_DEBUG_16 0x0200 0x0548 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x0204 0x054C 0x0774 0x0 0x1
+#define MX6SX_PAD_RGMII2_RXC__ENET2_RX_ER 0x0204 0x054C 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII2_RXC__GPIO5_IO_17 0x0204 0x054C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_RXC__CSI2_DATA_7 0x0204 0x054C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_RXC__ANATOP_TESTO_13 0x0204 0x054C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_RXC__VDEC_DEBUG_23 0x0204 0x054C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_RXC__PCIE_CTRL_DEBUG_17 0x0204 0x054C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0x0208 0x0550 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD0__SAI1_RX_SYNC 0x0208 0x0550 0x07FC 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD0__PWM8_OUT 0x0208 0x0550 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD0__GPIO5_IO_18 0x0208 0x0550 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD0__CSI2_DATA_8 0x0208 0x0550 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD0__ANATOP_TESTO_14 0x0208 0x0550 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD0__VDEC_DEBUG_24 0x0208 0x0550 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD0__PCIE_CTRL_DEBUG_18 0x0208 0x0550 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0x020C 0x0554 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD1__SAI1_RX_BCLK 0x020C 0x0554 0x07F4 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD1__PWM7_OUT 0x020C 0x0554 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD1__GPIO5_IO_19 0x020C 0x0554 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD1__CSI2_DATA_9 0x020C 0x0554 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD1__ANATOP_TESTO_15 0x020C 0x0554 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD1__VDEC_DEBUG_25 0x020C 0x0554 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD1__PCIE_CTRL_DEBUG_19 0x020C 0x0554 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0x0210 0x0558 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD2__SAI1_TX_SYNC 0x0210 0x0558 0x0804 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD2__PWM6_OUT 0x0210 0x0558 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD2__GPIO5_IO_20 0x0210 0x0558 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD2__CSI2_VSYNC 0x0210 0x0558 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD2__SJC_FAIL 0x0210 0x0558 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD2__VDEC_DEBUG_26 0x0210 0x0558 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD2__PCIE_CTRL_DEBUG_20 0x0210 0x0558 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0x0214 0x055C 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TD3__SAI1_TX_BCLK 0x0214 0x055C 0x0800 0x2 0x1
+#define MX6SX_PAD_RGMII2_TD3__PWM5_OUT 0x0214 0x055C 0x0000 0x3 0x0
+#define MX6SX_PAD_RGMII2_TD3__GPIO5_IO_21 0x0214 0x055C 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TD3__CSI2_HSYNC 0x0214 0x055C 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TD3__SJC_JTAG_ACT 0x0214 0x055C 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TD3__VDEC_DEBUG_27 0x0214 0x055C 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TD3__PCIE_CTRL_DEBUG_21 0x0214 0x055C 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0x0218 0x0560 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__SAI1_RX_DATA_0 0x0218 0x0560 0x07F8 0x2 0x1
+#define MX6SX_PAD_RGMII2_TX_CTL__GPIO5_IO_22 0x0218 0x0560 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__CSI2_FIELD 0x0218 0x0560 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__SJC_DE_B 0x0218 0x0560 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__VDEC_DEBUG_28 0x0218 0x0560 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TX_CTL__PCIE_CTRL_DEBUG_22 0x0218 0x0560 0x0000 0x9 0x0
+#define MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0x021C 0x0564 0x0000 0x0 0x0
+#define MX6SX_PAD_RGMII2_TXC__ENET2_TX_ER 0x021C 0x0564 0x0000 0x1 0x0
+#define MX6SX_PAD_RGMII2_TXC__SAI1_TX_DATA_0 0x021C 0x0564 0x0000 0x2 0x0
+#define MX6SX_PAD_RGMII2_TXC__GPIO5_IO_23 0x021C 0x0564 0x0000 0x5 0x0
+#define MX6SX_PAD_RGMII2_TXC__CSI2_PIXCLK 0x021C 0x0564 0x0000 0x6 0x0
+#define MX6SX_PAD_RGMII2_TXC__SJC_DONE 0x021C 0x0564 0x0000 0x7 0x0
+#define MX6SX_PAD_RGMII2_TXC__VDEC_DEBUG_29 0x021C 0x0564 0x0000 0x8 0x0
+#define MX6SX_PAD_RGMII2_TXC__PCIE_CTRL_DEBUG_23 0x021C 0x0564 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_CLK__USDHC1_CLK 0x0220 0x0568 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_CLK__AUDMUX_AUD5_RXFS 0x0220 0x0568 0x0668 0x1 0x1
+#define MX6SX_PAD_SD1_CLK__WDOG2_WDOG_B 0x0220 0x0568 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_CLK__GPT_CLK 0x0220 0x0568 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_CLK__WDOG2_WDOG_RST_B_DEB 0x0220 0x0568 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_CLK__GPIO6_IO_0 0x0220 0x0568 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_CLK__ENET2_1588_EVENT1_OUT 0x0220 0x0568 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_CLK__CCM_OUT1 0x0220 0x0568 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_CLK__VADC_ADC_PROC_CLK 0x0220 0x0568 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_CLK__MMDC_DEBUG_45 0x0220 0x0568 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_CMD__USDHC1_CMD 0x0224 0x056C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_CMD__AUDMUX_AUD5_RXC 0x0224 0x056C 0x0664 0x1 0x1
+#define MX6SX_PAD_SD1_CMD__WDOG1_WDOG_B 0x0224 0x056C 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_CMD__GPT_COMPARE1 0x0224 0x056C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_CMD__WDOG1_WDOG_RST_B_DEB 0x0224 0x056C 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_CMD__GPIO6_IO_1 0x0224 0x056C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_CMD__ENET2_1588_EVENT1_IN 0x0224 0x056C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_CMD__CCM_CLKO1 0x0224 0x056C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_CMD__VADC_EXT_SYSCLK 0x0224 0x056C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_CMD__MMDC_DEBUG_46 0x0224 0x056C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA0__USDHC1_DATA0 0x0228 0x0570 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA0__AUDMUX_AUD5_RXD 0x0228 0x0570 0x065C 0x1 0x1
+#define MX6SX_PAD_SD1_DATA0__CAAM_WRAPPER_RNG_OSC_OBS 0x0228 0x0570 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA0__GPT_CAPTURE1 0x0228 0x0570 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA0__UART2_RX 0x0228 0x0570 0x0838 0x4 0x2
+#define MX6SX_PAD_SD1_DATA0__UART2_TX 0x0228 0x0570 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA0__GPIO6_IO_2 0x0228 0x0570 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA0__ENET1_1588_EVENT1_IN 0x0228 0x0570 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA0__CCM_OUT2 0x0228 0x0570 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA0__VADC_CLAMP_UP 0x0228 0x0570 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA0__MMDC_DEBUG_48 0x0228 0x0570 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA1__USDHC1_DATA1 0x022C 0x0574 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA1__AUDMUX_AUD5_TXC 0x022C 0x0574 0x066C 0x1 0x1
+#define MX6SX_PAD_SD1_DATA1__PWM4_OUT 0x022C 0x0574 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA1__GPT_CAPTURE2 0x022C 0x0574 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA1__UART2_RX 0x022C 0x0574 0x0838 0x4 0x3
+#define MX6SX_PAD_SD1_DATA1__UART2_TX 0x022C 0x0574 0x0000 0x4 0x0
+#define MX6SX_PAD_SD1_DATA1__GPIO6_IO_3 0x022C 0x0574 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA1__ENET1_1588_EVENT1_OUT 0x022C 0x0574 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA1__CCM_CLKO2 0x022C 0x0574 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA1__VADC_CLAMP_DOWN 0x022C 0x0574 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA1__MMDC_DEBUG_47 0x022C 0x0574 0x0000 0x9 0x0
+#define MX6SX_PAD_SD1_DATA2__USDHC1_DATA2 0x0230 0x0578 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA2__AUDMUX_AUD5_TXFS 0x0230 0x0578 0x0670 0x1 0x1
+#define MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x0230 0x0578 0x0000 0x2 0x0
+#define MX6SX_PAD_SD1_DATA2__GPT_COMPARE2 0x0230 0x0578 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA2__UART2_CTS_B 0x0230 0x0578 0x0834 0x4 0x2
+#define MX6SX_PAD_SD1_DATA2__GPIO6_IO_4 0x0230 0x0578 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA2__ECSPI4_RDY 0x0230 0x0578 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA2__CCM_OUT0 0x0230 0x0578 0x0000 0x7 0x0
+#define MX6SX_PAD_SD1_DATA2__VADC_EXT_PD_N 0x0230 0x0578 0x0000 0x8 0x0
+#define MX6SX_PAD_SD1_DATA3__USDHC1_DATA3 0x0234 0x057C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_TXD 0x0234 0x057C 0x0660 0x1 0x1
+#define MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_RXD 0x0234 0x057C 0x065C 0x2 0x2
+#define MX6SX_PAD_SD1_DATA3__GPT_COMPARE3 0x0234 0x057C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD1_DATA3__UART2_RTS_B 0x0234 0x057C 0x0834 0x4 0x3
+#define MX6SX_PAD_SD1_DATA3__GPIO6_IO_5 0x0234 0x057C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD1_DATA3__ECSPI4_SS1 0x0234 0x057C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD1_DATA3__CCM_PMIC_RDY 0x0234 0x057C 0x069C 0x7 0x2
+#define MX6SX_PAD_SD1_DATA3__VADC_RST_N 0x0234 0x057C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x0238 0x0580 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_CLK__AUDMUX_AUD6_RXFS 0x0238 0x0580 0x0680 0x1 0x2
+#define MX6SX_PAD_SD2_CLK__KPP_COL_5 0x0238 0x0580 0x07C8 0x2 0x1
+#define MX6SX_PAD_SD2_CLK__ECSPI4_SCLK 0x0238 0x0580 0x0740 0x3 0x1
+#define MX6SX_PAD_SD2_CLK__MLB_SIG 0x0238 0x0580 0x07F0 0x4 0x2
+#define MX6SX_PAD_SD2_CLK__GPIO6_IO_6 0x0238 0x0580 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_CLK__MQS_RIGHT 0x0238 0x0580 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_CLK__WDOG1_WDOG_ANY 0x0238 0x0580 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_CLK__VADC_CLAMP_CURRENT_5 0x0238 0x0580 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CLK__MMDC_DEBUG_29 0x0238 0x0580 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x023C 0x0584 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_CMD__AUDMUX_AUD6_RXC 0x023C 0x0584 0x067C 0x1 0x2
+#define MX6SX_PAD_SD2_CMD__KPP_ROW_5 0x023C 0x0584 0x07D4 0x2 0x1
+#define MX6SX_PAD_SD2_CMD__ECSPI4_MOSI 0x023C 0x0584 0x0748 0x3 0x1
+#define MX6SX_PAD_SD2_CMD__MLB_CLK 0x023C 0x0584 0x07E8 0x4 0x2
+#define MX6SX_PAD_SD2_CMD__GPIO6_IO_7 0x023C 0x0584 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_CMD__MQS_LEFT 0x023C 0x0584 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_CMD__WDOG3_WDOG_B 0x023C 0x0584 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_CMD__VADC_CLAMP_CURRENT_4 0x023C 0x0584 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_CMD__MMDC_DEBUG_30 0x023C 0x0584 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x0240 0x0588 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA0__AUDMUX_AUD6_RXD 0x0240 0x0588 0x0674 0x1 0x2
+#define MX6SX_PAD_SD2_DATA0__KPP_ROW_7 0x0240 0x0588 0x07DC 0x2 0x1
+#define MX6SX_PAD_SD2_DATA0__PWM1_OUT 0x0240 0x0588 0x0000 0x3 0x0
+#define MX6SX_PAD_SD2_DATA0__I2C4_SDA 0x0240 0x0588 0x07C4 0x4 0x3
+#define MX6SX_PAD_SD2_DATA0__GPIO6_IO_8 0x0240 0x0588 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA0__ECSPI4_SS3 0x0240 0x0588 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA0__UART4_RX 0x0240 0x0588 0x0848 0x7 0x4
+#define MX6SX_PAD_SD2_DATA0__UART4_TX 0x0240 0x0588 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA0__VADC_CLAMP_CURRENT_0 0x0240 0x0588 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA0__MMDC_DEBUG_50 0x0240 0x0588 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x0244 0x058C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA1__AUDMUX_AUD6_TXC 0x0244 0x058C 0x0684 0x1 0x2
+#define MX6SX_PAD_SD2_DATA1__KPP_COL_7 0x0244 0x058C 0x07D0 0x2 0x1
+#define MX6SX_PAD_SD2_DATA1__PWM2_OUT 0x0244 0x058C 0x0000 0x3 0x0
+#define MX6SX_PAD_SD2_DATA1__I2C4_SCL 0x0244 0x058C 0x07C0 0x4 0x3
+#define MX6SX_PAD_SD2_DATA1__GPIO6_IO_9 0x0244 0x058C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA1__ECSPI4_SS2 0x0244 0x058C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA1__UART4_RX 0x0244 0x058C 0x0848 0x7 0x5
+#define MX6SX_PAD_SD2_DATA1__UART4_TX 0x0244 0x058C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA1__VADC_CLAMP_CURRENT_1 0x0244 0x058C 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA1__MMDC_DEBUG_49 0x0244 0x058C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x0248 0x0590 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA2__AUDMUX_AUD6_TXFS 0x0248 0x0590 0x0688 0x1 0x2
+#define MX6SX_PAD_SD2_DATA2__KPP_ROW_6 0x0248 0x0590 0x07D8 0x2 0x1
+#define MX6SX_PAD_SD2_DATA2__ECSPI4_SS0 0x0248 0x0590 0x074C 0x3 0x1
+#define MX6SX_PAD_SD2_DATA2__SDMA_EXT_EVENT_0 0x0248 0x0590 0x081C 0x4 0x2
+#define MX6SX_PAD_SD2_DATA2__GPIO6_IO_10 0x0248 0x0590 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA2__SPDIF_OUT 0x0248 0x0590 0x0000 0x6 0x0
+#define MX6SX_PAD_SD2_DATA2__UART6_RX 0x0248 0x0590 0x0858 0x7 0x4
+#define MX6SX_PAD_SD2_DATA2__UART6_TX 0x0248 0x0590 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA2__VADC_CLAMP_CURRENT_2 0x0248 0x0590 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA2__MMDC_DEBUG_32 0x0248 0x0590 0x0000 0x9 0x0
+#define MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x024C 0x0594 0x0000 0x0 0x0
+#define MX6SX_PAD_SD2_DATA3__AUDMUX_AUD6_TXD 0x024C 0x0594 0x0678 0x1 0x2
+#define MX6SX_PAD_SD2_DATA3__KPP_COL_6 0x024C 0x0594 0x07CC 0x2 0x1
+#define MX6SX_PAD_SD2_DATA3__ECSPI4_MISO 0x024C 0x0594 0x0744 0x3 0x1
+#define MX6SX_PAD_SD2_DATA3__MLB_DATA 0x024C 0x0594 0x07EC 0x4 0x2
+#define MX6SX_PAD_SD2_DATA3__GPIO6_IO_11 0x024C 0x0594 0x0000 0x5 0x0
+#define MX6SX_PAD_SD2_DATA3__SPDIF_IN 0x024C 0x0594 0x0824 0x6 0x4
+#define MX6SX_PAD_SD2_DATA3__UART6_RX 0x024C 0x0594 0x0858 0x7 0x5
+#define MX6SX_PAD_SD2_DATA3__UART6_TX 0x024C 0x0594 0x0000 0x7 0x0
+#define MX6SX_PAD_SD2_DATA3__VADC_CLAMP_CURRENT_3 0x024C 0x0594 0x0000 0x8 0x0
+#define MX6SX_PAD_SD2_DATA3__MMDC_DEBUG_31 0x024C 0x0594 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x0250 0x0598 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_CLK__UART4_CTS_B 0x0250 0x0598 0x0844 0x1 0x0
+#define MX6SX_PAD_SD3_CLK__ECSPI4_SCLK 0x0250 0x0598 0x0740 0x2 0x0
+#define MX6SX_PAD_SD3_CLK__AUDMUX_AUD6_RXFS 0x0250 0x0598 0x0680 0x3 0x0
+#define MX6SX_PAD_SD3_CLK__LCDIF2_VSYNC 0x0250 0x0598 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_CLK__GPIO7_IO_0 0x0250 0x0598 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_CLK__LCDIF2_BUSY 0x0250 0x0598 0x07E4 0x6 0x0
+#define MX6SX_PAD_SD3_CLK__TPSMP_HDATA_29 0x0250 0x0598 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_CLK__SDMA_DEBUG_EVENT_CHANNEL_5 0x0250 0x0598 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x0254 0x059C 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_CMD__UART4_RX 0x0254 0x059C 0x0848 0x1 0x0
+#define MX6SX_PAD_SD3_CMD__UART4_TX 0x0254 0x059C 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_CMD__ECSPI4_MOSI 0x0254 0x059C 0x0748 0x2 0x0
+#define MX6SX_PAD_SD3_CMD__AUDMUX_AUD6_RXC 0x0254 0x059C 0x067C 0x3 0x0
+#define MX6SX_PAD_SD3_CMD__LCDIF2_HSYNC 0x0254 0x059C 0x07E4 0x4 0x1
+#define MX6SX_PAD_SD3_CMD__GPIO7_IO_1 0x0254 0x059C 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_CMD__LCDIF2_RS 0x0254 0x059C 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_CMD__TPSMP_HDATA_28 0x0254 0x059C 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_CMD__SDMA_DEBUG_EVENT_CHANNEL_4 0x0254 0x059C 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x0258 0x05A0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA0__I2C4_SCL 0x0258 0x05A0 0x07C0 0x1 0x0
+#define MX6SX_PAD_SD3_DATA0__ECSPI2_SS1 0x0258 0x05A0 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA0__AUDMUX_AUD6_RXD 0x0258 0x05A0 0x0674 0x3 0x0
+#define MX6SX_PAD_SD3_DATA0__LCDIF2_DATA_1 0x0258 0x05A0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA0__GPIO7_IO_2 0x0258 0x05A0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA0__DCIC1_OUT 0x0258 0x05A0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA0__TPSMP_HDATA_30 0x0258 0x05A0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA0__GPU_DEBUG_0 0x0258 0x05A0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA0__SDMA_DEBUG_EVT_CHN_LINES_0 0x0258 0x05A0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x025C 0x05A4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA1__I2C4_SDA 0x025C 0x05A4 0x07C4 0x1 0x0
+#define MX6SX_PAD_SD3_DATA1__ECSPI2_SS2 0x025C 0x05A4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA1__AUDMUX_AUD6_TXC 0x025C 0x05A4 0x0684 0x3 0x0
+#define MX6SX_PAD_SD3_DATA1__LCDIF2_DATA_0 0x025C 0x05A4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA1__GPIO7_IO_3 0x025C 0x05A4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA1__DCIC2_OUT 0x025C 0x05A4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA1__TPSMP_HDATA_31 0x025C 0x05A4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA1__GPU_DEBUG_1 0x025C 0x05A4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA1__SDMA_DEBUG_EVT_CHN_LINES_1 0x025C 0x05A4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x0260 0x05A8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA2__UART4_RTS_B 0x0260 0x05A8 0x0844 0x1 0x1
+#define MX6SX_PAD_SD3_DATA2__ECSPI4_SS0 0x0260 0x05A8 0x074C 0x2 0x0
+#define MX6SX_PAD_SD3_DATA2__AUDMUX_AUD6_TXFS 0x0260 0x05A8 0x0688 0x3 0x0
+#define MX6SX_PAD_SD3_DATA2__LCDIF2_CLK 0x0260 0x05A8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA2__GPIO7_IO_4 0x0260 0x05A8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA2__LCDIF2_WR_RWN 0x0260 0x05A8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA2__TPSMP_HDATA_26 0x0260 0x05A8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA2__GPU_DEBUG_2 0x0260 0x05A8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA2__SDMA_DEBUG_EVENT_CHANNEL_2 0x0260 0x05A8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x0264 0x05AC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA3__UART4_RX 0x0264 0x05AC 0x0848 0x1 0x1
+#define MX6SX_PAD_SD3_DATA3__UART4_TX 0x0264 0x05AC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA3__ECSPI4_MISO 0x0264 0x05AC 0x0744 0x2 0x0
+#define MX6SX_PAD_SD3_DATA3__AUDMUX_AUD6_TXD 0x0264 0x05AC 0x0678 0x3 0x0
+#define MX6SX_PAD_SD3_DATA3__LCDIF2_ENABLE 0x0264 0x05AC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA3__GPIO7_IO_5 0x0264 0x05AC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA3__LCDIF2_RD_E 0x0264 0x05AC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA3__TPSMP_HDATA_27 0x0264 0x05AC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA3__GPU_DEBUG_3 0x0264 0x05AC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA3__SDMA_DEBUG_EVENT_CHANNEL_3 0x0264 0x05AC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x0268 0x05B0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA4__CAN2_RX 0x0268 0x05B0 0x0690 0x1 0x0
+#define MX6SX_PAD_SD3_DATA4__CANFD_RX2 0x0268 0x05B0 0x0698 0x2 0x0
+#define MX6SX_PAD_SD3_DATA4__UART3_RX 0x0268 0x05B0 0x0840 0x3 0x2
+#define MX6SX_PAD_SD3_DATA4__UART3_TX 0x0268 0x05B0 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA4__LCDIF2_DATA_3 0x0268 0x05B0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA4__GPIO7_IO_6 0x0268 0x05B0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA4__ENET2_1588_EVENT0_IN 0x0268 0x05B0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA4__TPSMP_HTRANS_1 0x0268 0x05B0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA4__GPU_DEBUG_4 0x0268 0x05B0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA4__SDMA_DEBUG_BUS_DEVICE_0 0x0268 0x05B0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x026C 0x05B4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA5__CAN1_TX 0x026C 0x05B4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA5__CANFD_TX1 0x026C 0x05B4 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA5__UART3_RX 0x026C 0x05B4 0x0840 0x3 0x3
+#define MX6SX_PAD_SD3_DATA5__UART3_TX 0x026C 0x05B4 0x0000 0x3 0x0
+#define MX6SX_PAD_SD3_DATA5__LCDIF2_DATA_2 0x026C 0x05B4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA5__GPIO7_IO_7 0x026C 0x05B4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA5__ENET2_1588_EVENT0_OUT 0x026C 0x05B4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA5__SIM_M_HWRITE 0x026C 0x05B4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA5__GPU_DEBUG_5 0x026C 0x05B4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA5__SDMA_DEBUG_BUS_DEVICE_1 0x026C 0x05B4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x0270 0x05B8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA6__CAN2_TX 0x0270 0x05B8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD3_DATA6__CANFD_TX2 0x0270 0x05B8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x0270 0x05B8 0x083C 0x3 0x2
+#define MX6SX_PAD_SD3_DATA6__LCDIF2_DATA_4 0x0270 0x05B8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA6__GPIO7_IO_8 0x0270 0x05B8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA6__ENET1_1588_EVENT0_OUT 0x0270 0x05B8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA6__TPSMP_HTRANS_0 0x0270 0x05B8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA6__GPU_DEBUG_7 0x0270 0x05B8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA6__SDMA_DEBUG_EVT_CHN_LINES_7 0x0270 0x05B8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x0274 0x05BC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD3_DATA7__CAN1_RX 0x0274 0x05BC 0x068C 0x1 0x0
+#define MX6SX_PAD_SD3_DATA7__CANFD_RX1 0x0274 0x05BC 0x0694 0x2 0x0
+#define MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x0274 0x05BC 0x083C 0x3 0x3
+#define MX6SX_PAD_SD3_DATA7__LCDIF2_DATA_5 0x0274 0x05BC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD3_DATA7__GPIO7_IO_9 0x0274 0x05BC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD3_DATA7__ENET1_1588_EVENT0_IN 0x0274 0x05BC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD3_DATA7__TPSMP_HDATA_DIR 0x0274 0x05BC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD3_DATA7__GPU_DEBUG_6 0x0274 0x05BC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD3_DATA7__SDMA_DEBUG_EVT_CHN_LINES_2 0x0274 0x05BC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x0278 0x05C0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_CLK__RAWNAND_DATA15 0x0278 0x05C0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_CLK__ECSPI2_MISO 0x0278 0x05C0 0x0724 0x2 0x1
+#define MX6SX_PAD_SD4_CLK__AUDMUX_AUD3_RXFS 0x0278 0x05C0 0x0638 0x3 0x0
+#define MX6SX_PAD_SD4_CLK__LCDIF2_DATA_13 0x0278 0x05C0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_CLK__GPIO6_IO_12 0x0278 0x05C0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_CLK__ECSPI3_SS2 0x0278 0x05C0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_CLK__TPSMP_HDATA_20 0x0278 0x05C0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_CLK__VDEC_DEBUG_12 0x0278 0x05C0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_CLK__SDMA_DEBUG_EVENT_CHANNEL_SEL 0x0278 0x05C0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x027C 0x05C4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_CMD__RAWNAND_DATA14 0x027C 0x05C4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_CMD__ECSPI2_MOSI 0x027C 0x05C4 0x0728 0x2 0x1
+#define MX6SX_PAD_SD4_CMD__AUDMUX_AUD3_RXC 0x027C 0x05C4 0x0634 0x3 0x0
+#define MX6SX_PAD_SD4_CMD__LCDIF2_DATA_14 0x027C 0x05C4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_CMD__GPIO6_IO_13 0x027C 0x05C4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_CMD__ECSPI3_SS1 0x027C 0x05C4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_CMD__TPSMP_HDATA_19 0x027C 0x05C4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_CMD__VDEC_DEBUG_11 0x027C 0x05C4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_CMD__SDMA_DEBUG_CORE_RUN 0x027C 0x05C4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x0280 0x05C8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA0__RAWNAND_DATA10 0x0280 0x05C8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA0__ECSPI2_SS0 0x0280 0x05C8 0x072C 0x2 0x1
+#define MX6SX_PAD_SD4_DATA0__AUDMUX_AUD3_RXD 0x0280 0x05C8 0x062C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA0__LCDIF2_DATA_12 0x0280 0x05C8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA0__GPIO6_IO_14 0x0280 0x05C8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA0__ECSPI3_SS3 0x0280 0x05C8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA0__TPSMP_HDATA_21 0x0280 0x05C8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA0__VDEC_DEBUG_13 0x0280 0x05C8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA0__SDMA_DEBUG_MODE 0x0280 0x05C8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x0284 0x05CC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA1__RAWNAND_DATA11 0x0284 0x05CC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA1__ECSPI2_SCLK 0x0284 0x05CC 0x0720 0x2 0x1
+#define MX6SX_PAD_SD4_DATA1__AUDMUX_AUD3_TXC 0x0284 0x05CC 0x063C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA1__LCDIF2_DATA_11 0x0284 0x05CC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA1__GPIO6_IO_15 0x0284 0x05CC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA1__ECSPI3_RDY 0x0284 0x05CC 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA1__TPSMP_HDATA_22 0x0284 0x05CC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA1__VDEC_DEBUG_14 0x0284 0x05CC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA1__SDMA_DEBUG_BUS_ERROR 0x0284 0x05CC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x0288 0x05D0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA2__RAWNAND_DATA12 0x0288 0x05D0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA2__I2C2_SDA 0x0288 0x05D0 0x07B4 0x2 0x0
+#define MX6SX_PAD_SD4_DATA2__AUDMUX_AUD3_TXFS 0x0288 0x05D0 0x0640 0x3 0x0
+#define MX6SX_PAD_SD4_DATA2__LCDIF2_DATA_10 0x0288 0x05D0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA2__GPIO6_IO_16 0x0288 0x05D0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA2__ECSPI2_SS3 0x0288 0x05D0 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA2__TPSMP_HDATA_23 0x0288 0x05D0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA2__VDEC_DEBUG_15 0x0288 0x05D0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA2__SDMA_DEBUG_BUS_RWB 0x0288 0x05D0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x028C 0x05D4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA3__RAWNAND_DATA13 0x028C 0x05D4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA3__I2C2_SCL 0x028C 0x05D4 0x07B0 0x2 0x0
+#define MX6SX_PAD_SD4_DATA3__AUDMUX_AUD3_TXD 0x028C 0x05D4 0x0630 0x3 0x0
+#define MX6SX_PAD_SD4_DATA3__LCDIF2_DATA_9 0x028C 0x05D4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA3__GPIO6_IO_17 0x028C 0x05D4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA3__ECSPI2_RDY 0x028C 0x05D4 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA3__TPSMP_HDATA_24 0x028C 0x05D4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA3__VDEC_DEBUG_16 0x028C 0x05D4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA3__SDMA_DEBUG_MATCHED_DMBUS 0x028C 0x05D4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA4__USDHC4_DATA4 0x0290 0x05D8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA4__RAWNAND_DATA09 0x0290 0x05D8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA4__UART5_RX 0x0290 0x05D8 0x0850 0x2 0x0
+#define MX6SX_PAD_SD4_DATA4__UART5_TX 0x0290 0x05D8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA4__ECSPI3_SCLK 0x0290 0x05D8 0x0730 0x3 0x0
+#define MX6SX_PAD_SD4_DATA4__LCDIF2_DATA_8 0x0290 0x05D8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA4__GPIO6_IO_18 0x0290 0x05D8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x0290 0x05D8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_DATA4__TPSMP_HDATA_16 0x0290 0x05D8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA4__USB_OTG_HOST_MODE 0x0290 0x05D8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA4__SDMA_DEBUG_RTBUFFER_WRITE 0x0290 0x05D8 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA5__USDHC4_DATA5 0x0294 0x05DC 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA5__RAWNAND_CE2_B 0x0294 0x05DC 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA5__UART5_RX 0x0294 0x05DC 0x0850 0x2 0x1
+#define MX6SX_PAD_SD4_DATA5__UART5_TX 0x0294 0x05DC 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_DATA5__ECSPI3_MOSI 0x0294 0x05DC 0x0738 0x3 0x0
+#define MX6SX_PAD_SD4_DATA5__LCDIF2_DATA_7 0x0294 0x05DC 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA5__GPIO6_IO_19 0x0294 0x05DC 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA5__SPDIF_IN 0x0294 0x05DC 0x0824 0x6 0x0
+#define MX6SX_PAD_SD4_DATA5__TPSMP_HDATA_17 0x0294 0x05DC 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA5__VDEC_DEBUG_9 0x0294 0x05DC 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA5__SDMA_DEBUG_EVENT_CHANNEL_0 0x0294 0x05DC 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA6__USDHC4_DATA6 0x0298 0x05E0 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA6__RAWNAND_CE3_B 0x0298 0x05E0 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA6__UART5_RTS_B 0x0298 0x05E0 0x084C 0x2 0x0
+#define MX6SX_PAD_SD4_DATA6__ECSPI3_MISO 0x0298 0x05E0 0x0734 0x3 0x0
+#define MX6SX_PAD_SD4_DATA6__LCDIF2_DATA_6 0x0298 0x05E0 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x0298 0x05E0 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA6__USDHC4_WP 0x0298 0x05E0 0x0878 0x6 0x0
+#define MX6SX_PAD_SD4_DATA6__TPSMP_HDATA_18 0x0298 0x05E0 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA6__VDEC_DEBUG_10 0x0298 0x05E0 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA6__SDMA_DEBUG_EVENT_CHANNEL_1 0x0298 0x05E0 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_DATA7__USDHC4_DATA7 0x029C 0x05E4 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_DATA7__RAWNAND_DATA08 0x029C 0x05E4 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_DATA7__UART5_CTS_B 0x029C 0x05E4 0x084C 0x2 0x1
+#define MX6SX_PAD_SD4_DATA7__ECSPI3_SS0 0x029C 0x05E4 0x073C 0x3 0x0
+#define MX6SX_PAD_SD4_DATA7__LCDIF2_DATA_15 0x029C 0x05E4 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x029C 0x05E4 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_DATA7__USDHC4_CD_B 0x029C 0x05E4 0x0874 0x6 0x0
+#define MX6SX_PAD_SD4_DATA7__TPSMP_HDATA_15 0x029C 0x05E4 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_DATA7__USB_OTG_PWR_WAKE 0x029C 0x05E4 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_DATA7__SDMA_DEBUG_YIELD 0x029C 0x05E4 0x0000 0x9 0x0
+#define MX6SX_PAD_SD4_RESET_B__USDHC4_RESET_B 0x02A0 0x05E8 0x0000 0x0 0x0
+#define MX6SX_PAD_SD4_RESET_B__RAWNAND_DQS 0x02A0 0x05E8 0x0000 0x1 0x0
+#define MX6SX_PAD_SD4_RESET_B__USDHC4_RESET 0x02A0 0x05E8 0x0000 0x2 0x0
+#define MX6SX_PAD_SD4_RESET_B__AUDMUX_MCLK 0x02A0 0x05E8 0x0000 0x3 0x0
+#define MX6SX_PAD_SD4_RESET_B__LCDIF2_RESET 0x02A0 0x05E8 0x0000 0x4 0x0
+#define MX6SX_PAD_SD4_RESET_B__GPIO6_IO_22 0x02A0 0x05E8 0x0000 0x5 0x0
+#define MX6SX_PAD_SD4_RESET_B__LCDIF2_CS 0x02A0 0x05E8 0x0000 0x6 0x0
+#define MX6SX_PAD_SD4_RESET_B__TPSMP_HDATA_25 0x02A0 0x05E8 0x0000 0x7 0x0
+#define MX6SX_PAD_SD4_RESET_B__VDEC_DEBUG_17 0x02A0 0x05E8 0x0000 0x8 0x0
+#define MX6SX_PAD_SD4_RESET_B__SDMA_DEBUG_BUS_DEVICE_2 0x02A0 0x05E8 0x0000 0x9 0x0
+#define MX6SX_PAD_USB_H_DATA__USB_H_DATA 0x02A4 0x05EC 0x0000 0x0 0x0
+#define MX6SX_PAD_USB_H_DATA__PWM2_OUT 0x02A4 0x05EC 0x0000 0x1 0x0
+#define MX6SX_PAD_USB_H_DATA__ANATOP_24M_OUT 0x02A4 0x05EC 0x0000 0x2 0x0
+#define MX6SX_PAD_USB_H_DATA__I2C4_SDA 0x02A4 0x05EC 0x07C4 0x3 0x1
+#define MX6SX_PAD_USB_H_DATA__WDOG3_WDOG_B 0x02A4 0x05EC 0x0000 0x4 0x0
+#define MX6SX_PAD_USB_H_DATA__GPIO7_IO_10 0x02A4 0x05EC 0x0000 0x5 0x0
+#define MX6SX_PAD_USB_H_STROBE__USB_H_STROBE 0x02A8 0x05F0 0x0000 0x0 0x0
+#define MX6SX_PAD_USB_H_STROBE__PWM1_OUT 0x02A8 0x05F0 0x0000 0x1 0x0
+#define MX6SX_PAD_USB_H_STROBE__ANATOP_32K_OUT 0x02A8 0x05F0 0x0000 0x2 0x0
+#define MX6SX_PAD_USB_H_STROBE__I2C4_SCL 0x02A8 0x05F0 0x07C0 0x3 0x1
+#define MX6SX_PAD_USB_H_STROBE__WDOG3_WDOG_RST_B_DEB 0x02A8 0x05F0 0x0000 0x4 0x0
+#define MX6SX_PAD_USB_H_STROBE__GPIO7_IO_11 0x02A8 0x05F0 0x0000 0x5 0x0
+
+#endif /* __DTS_IMX6SX_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
new file mode 100644
index 000000000000..a3980d970590
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sx.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SoloX SDB Board";
+ compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vcc_sd3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_sd3>;
+ regulator-name = "VCC_SD3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg1_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg2>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_psu_5v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "PSU-5V0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ ssi-controller = <&ssi2>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
+ mux-int-port = <2>;
+ mux-ext-port = <6>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec: wm8962@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clks IMX6SX_CLK_AUDIO>;
+ DCVDD-supply = <&vgen4_reg>;
+ DBVDD-supply = <&vgen4_reg>;
+ AVDD-supply = <&vgen4_reg>;
+ CPVDD-supply = <&vgen4_reg>;
+ MICVDD-supply = <&vgen3_reg>;
+ PLLVDD-supply = <&vgen4_reg>;
+ SPKVDD1-supply = <&reg_psu_5v>;
+ SPKVDD2-supply = <&reg_psu_5v>;
+ };
+};
+
+&ssi2 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ non-removable;
+ no-1-8-v;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
+ vmmc-supply = <&vcc_sd3>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+ wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&iomuxc {
+ imx6x-sdb {
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
+ MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b1
+ MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+ MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_vcc_sd3: vccsd3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg2: usbot2ggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
+ MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
+ MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
new file mode 100644
index 000000000000..f4b9da65bc0f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -0,0 +1,1208 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/imx6sx-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6sx-pinfunc.h"
+#include "skeleton.dtsi"
+
+/ {
+ aliases {
+ can0 = &flexcan1;
+ can1 = &flexcan2;
+ ethernet0 = &fec1;
+ ethernet1 = &fec2;
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
+ gpio4 = &gpio5;
+ gpio5 = &gpio6;
+ gpio6 = &gpio7;
+ i2c0 = &i2c1;
+ i2c1 = &i2c2;
+ i2c2 = &i2c3;
+ i2c3 = &i2c4;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ mmc3 = &usdhc4;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ serial5 = &uart6;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
+ spi4 = &ecspi5;
+ usbphy0 = &usbphy1;
+ usbphy1 = &usbphy2;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 996000 1250000
+ 792000 1175000
+ 396000 1075000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC uV */
+ 996000 1175000
+ 792000 1175000
+ 396000 1175000
+ >;
+ clock-latency = <61036>; /* two CLK32 periods */
+ clocks = <&clks IMX6SX_CLK_ARM>,
+ <&clks IMX6SX_CLK_PLL2_PFD2>,
+ <&clks IMX6SX_CLK_STEP>,
+ <&clks IMX6SX_CLK_PLL1_SW>,
+ <&clks IMX6SX_CLK_PLL1_SYS>;
+ clock-names = "arm", "pll2_pfd2_396m", "step",
+ "pll1_sw", "pll1_sys";
+ arm-supply = <&reg_arm>;
+ soc-supply = <&reg_soc>;
+ };
+ };
+
+ intc: interrupt-controller@00a01000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x00a01000 0x1000>,
+ <0x00a00100 0x100>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ckil: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
+
+ osc: clock@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
+
+ ipp_di0: clock@2 {
+ compatible = "fixed-clock";
+ reg = <2>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di0";
+ };
+
+ ipp_di1: clock@3 {
+ compatible = "fixed-clock";
+ reg = <3>;
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di1";
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ ocram: sram@00900000 {
+ compatible = "mmio-sram";
+ reg = <0x00900000 0x20000>;
+ clocks = <&clks IMX6SX_CLK_OCRAM>;
+ };
+
+ L2: l2-cache@00a02000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x00a02000 0x1000>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ cache-unified;
+ cache-level = <2>;
+ arm,tag-latency = <4 2 3>;
+ arm,data-latency = <4 2 3>;
+ };
+
+ dma_apbh: dma-apbh@01804000 {
+ compatible = "fsl,imx6sx-dma-apbh", "fsl,imx28-dma-apbh";
+ reg = <0x01804000 0x2000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&clks IMX6SX_CLK_APBH_DMA>;
+ };
+
+ gpmi: gpmi-nand@01806000{
+ compatible = "fsl,imx6sx-gpmi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
+ reg-names = "gpmi-nand", "bch";
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bch";
+ clocks = <&clks IMX6SX_CLK_GPMI_IO>,
+ <&clks IMX6SX_CLK_GPMI_APB>,
+ <&clks IMX6SX_CLK_GPMI_BCH>,
+ <&clks IMX6SX_CLK_GPMI_BCH_APB>,
+ <&clks IMX6SX_CLK_PER1_BCH>;
+ clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
+ "gpmi_bch_apb", "per1_bch";
+ dmas = <&dma_apbh 0>;
+ dma-names = "rx-tx";
+ status = "disabled";
+ };
+
+ aips1: aips-bus@02000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x100000>;
+ ranges;
+
+ spba-bus@02000000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02000000 0x40000>;
+ ranges;
+
+ spdif: spdif@02004000 {
+ compatible = "fsl,imx6sx-spdif", "fsl,imx35-spdif";
+ reg = <0x02004000 0x4000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&sdma 14 18 0>,
+ <&sdma 15 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks IMX6SX_CLK_SPDIF>,
+ <&clks IMX6SX_CLK_OSC>,
+ <&clks IMX6SX_CLK_SPDIF>,
+ <&clks 0>, <&clks 0>, <&clks 0>,
+ <&clks IMX6SX_CLK_IPG>,
+ <&clks 0>, <&clks 0>,
+ <&clks IMX6SX_CLK_SPBA>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7", "dma";
+ status = "disabled";
+ };
+
+ ecspi1: ecspi@02008000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02008000 0x4000>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ECSPI1>,
+ <&clks IMX6SX_CLK_ECSPI1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi2: ecspi@0200c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0200c000 0x4000>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ECSPI2>,
+ <&clks IMX6SX_CLK_ECSPI2>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi3: ecspi@02010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02010000 0x4000>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ECSPI3>,
+ <&clks IMX6SX_CLK_ECSPI3>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ ecspi4: ecspi@02014000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ reg = <0x02014000 0x4000>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ECSPI4>,
+ <&clks IMX6SX_CLK_ECSPI4>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart1: serial@02020000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x02020000 0x4000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ esai: esai@02024000 {
+ reg = <0x02024000 0x4000>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ESAI_IPG>,
+ <&clks IMX6SX_CLK_ESAI_MEM>,
+ <&clks IMX6SX_CLK_ESAI_EXTAL>,
+ <&clks IMX6SX_CLK_ESAI_IPG>,
+ <&clks IMX6SX_CLK_SPBA>;
+ clock-names = "core", "mem", "extal",
+ "fsys", "dma";
+ status = "disabled";
+ };
+
+ ssi1: ssi@02028000 {
+ compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+ reg = <0x02028000 0x4000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SSI1_IPG>,
+ <&clks IMX6SX_CLK_SSI1>;
+ clock-names = "ipg", "baud";
+ dmas = <&sdma 37 1 0>, <&sdma 38 1 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ status = "disabled";
+ };
+
+ ssi2: ssi@0202c000 {
+ compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+ reg = <0x0202c000 0x4000>;
+ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SSI2_IPG>,
+ <&clks IMX6SX_CLK_SSI2>;
+ clock-names = "ipg", "baud";
+ dmas = <&sdma 41 1 0>, <&sdma 42 1 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ status = "disabled";
+ };
+
+ ssi3: ssi@02030000 {
+ compatible = "fsl,imx6sx-ssi", "fsl,imx51-ssi";
+ reg = <0x02030000 0x4000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SSI3_IPG>,
+ <&clks IMX6SX_CLK_SSI3>;
+ clock-names = "ipg", "baud";
+ dmas = <&sdma 45 1 0>, <&sdma 46 1 0>;
+ dma-names = "rx", "tx";
+ fsl,fifo-depth = <15>;
+ status = "disabled";
+ };
+
+ asrc: asrc@02034000 {
+ reg = <0x02034000 0x4000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ASRC_MEM>,
+ <&clks IMX6SX_CLK_ASRC_IPG>,
+ <&clks IMX6SX_CLK_SPDIF>,
+ <&clks IMX6SX_CLK_SPBA>;
+ clock-names = "mem", "ipg", "asrck", "dma";
+ dmas = <&sdma 17 20 1>, <&sdma 18 20 1>,
+ <&sdma 19 20 1>, <&sdma 20 20 1>,
+ <&sdma 21 20 1>, <&sdma 22 20 1>;
+ dma-names = "rxa", "rxb", "rxc",
+ "txa", "txb", "txc";
+ status = "okay";
+ };
+ };
+
+ pwm1: pwm@02080000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x02080000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM1>,
+ <&clks IMX6SX_CLK_PWM1>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm2: pwm@02084000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x02084000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM2>,
+ <&clks IMX6SX_CLK_PWM2>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@02088000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x02088000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM3>,
+ <&clks IMX6SX_CLK_PWM3>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm4: pwm@0208c000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x0208c000 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM4>,
+ <&clks IMX6SX_CLK_PWM4>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ flexcan1: can@02090000 {
+ compatible = "fsl,imx6sx-flexcan", "fsl,imx6q-flexcan";
+ reg = <0x02090000 0x4000>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_CAN1_IPG>,
+ <&clks IMX6SX_CLK_CAN1_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ flexcan2: can@02094000 {
+ compatible = "fsl,imx6sx-flexcan", "fsl,imx6q-flexcan";
+ reg = <0x02094000 0x4000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_CAN2_IPG>,
+ <&clks IMX6SX_CLK_CAN2_SERIAL>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ gpt: gpt@02098000 {
+ compatible = "fsl,imx6sx-gpt", "fsl,imx31-gpt";
+ reg = <0x02098000 0x4000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_GPT_BUS>,
+ <&clks IMX6SX_CLK_GPT_SERIAL>;
+ clock-names = "ipg", "per";
+ };
+
+ gpio1: gpio@0209c000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x0209c000 0x4000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@020a0000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020a0000 0x4000>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@020a4000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020a4000 0x4000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@020a8000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020a8000 0x4000>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio5: gpio@020ac000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020ac000 0x4000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio6: gpio@020b0000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020b0000 0x4000>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio7: gpio@020b4000 {
+ compatible = "fsl,imx6sx-gpio", "fsl,imx35-gpio";
+ reg = <0x020b4000 0x4000>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ kpp: kpp@020b8000 {
+ compatible = "fsl,imx6sx-kpp", "fsl,imx21-kpp";
+ reg = <0x020b8000 0x4000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DUMMY>;
+ status = "disabled";
+ };
+
+ wdog1: wdog@020bc000 {
+ compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+ reg = <0x020bc000 0x4000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DUMMY>;
+ };
+
+ wdog2: wdog@020c0000 {
+ compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+ reg = <0x020c0000 0x4000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DUMMY>;
+ status = "disabled";
+ };
+
+ clks: ccm@020c4000 {
+ compatible = "fsl,imx6sx-ccm";
+ reg = <0x020c4000 0x4000>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <1>;
+ clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+ clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+ };
+
+ anatop: anatop@020c8000 {
+ compatible = "fsl,imx6sx-anatop", "fsl,imx6q-anatop",
+ "syscon", "simple-bus";
+ reg = <0x020c8000 0x1000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+
+ regulator-1p1@110 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd1p1";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1375000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x110>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <4>;
+ anatop-min-voltage = <800000>;
+ anatop-max-voltage = <1375000>;
+ };
+
+ regulator-3p0@120 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd3p0";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3150000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x120>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0>;
+ anatop-min-voltage = <2625000>;
+ anatop-max-voltage = <3400000>;
+ };
+
+ regulator-2p5@130 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd2p5";
+ regulator-min-microvolt = <2100000>;
+ regulator-max-microvolt = <2875000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x130>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0>;
+ anatop-min-voltage = <2100000>;
+ anatop-max-voltage = <2875000>;
+ };
+
+ reg_arm: regulator-vddcore@140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddarm";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <0>;
+ anatop-vol-bit-width = <5>;
+ anatop-delay-reg-offset = <0x170>;
+ anatop-delay-bit-shift = <24>;
+ anatop-delay-bit-width = <2>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1450000>;
+ };
+
+ reg_pcie: regulator-vddpcie@140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddpcie";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1450000>;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <9>;
+ anatop-vol-bit-width = <5>;
+ anatop-delay-reg-offset = <0x170>;
+ anatop-delay-bit-shift = <26>;
+ anatop-delay-bit-width = <2>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1450000>;
+ };
+
+ reg_soc: regulator-vddsoc@140 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddsoc";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1450000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <18>;
+ anatop-vol-bit-width = <5>;
+ anatop-delay-reg-offset = <0x170>;
+ anatop-delay-bit-shift = <28>;
+ anatop-delay-bit-width = <2>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1450000>;
+ };
+ };
+
+ tempmon: tempmon {
+ compatible = "fsl,imx6sx-tempmon", "fsl,imx6q-tempmon";
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon = <&anatop>;
+ fsl,tempmon-data = <&ocotp>;
+ clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>;
+ };
+
+ usbphy1: usbphy@020c9000 {
+ compatible = "fsl,imx6sx-usbphy", "fsl,imx23-usbphy";
+ reg = <0x020c9000 0x1000>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USBPHY1>;
+ fsl,anatop = <&anatop>;
+ };
+
+ usbphy2: usbphy@020ca000 {
+ compatible = "fsl,imx6sx-usbphy", "fsl,imx23-usbphy";
+ reg = <0x020ca000 0x1000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USBPHY2>;
+ fsl,anatop = <&anatop>;
+ };
+
+ snvs: snvs@020cc000 {
+ compatible = "fsl,sec-v4.0-mon", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x020cc000 0x4000>;
+
+ snvs-rtc-lp@34 {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ reg = <0x34 0x58>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ epit1: epit@020d0000 {
+ reg = <0x020d0000 0x4000>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ epit2: epit@020d4000 {
+ reg = <0x020d4000 0x4000>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ src: src@020d8000 {
+ compatible = "fsl,imx6sx-src", "fsl,imx51-src";
+ reg = <0x020d8000 0x4000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
+
+ gpc: gpc@020dc000 {
+ compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
+ reg = <0x020dc000 0x4000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ iomuxc: iomuxc@020e0000 {
+ compatible = "fsl,imx6sx-iomuxc";
+ reg = <0x020e0000 0x4000>;
+ };
+
+ gpr: iomuxc-gpr@020e4000 {
+ compatible = "fsl,imx6sx-iomuxc-gpr",
+ "fsl,imx6q-iomuxc-gpr", "syscon";
+ reg = <0x020e4000 0x4000>;
+ };
+
+ sdma: sdma@020ec000 {
+ compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma";
+ reg = <0x020ec000 0x4000>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SDMA>,
+ <&clks IMX6SX_CLK_SDMA>;
+ clock-names = "ipg", "ahb";
+ #dma-cells = <3>;
+ /* imx6sx reuses imx6q sdma firmware */
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+ };
+ };
+
+ aips2: aips-bus@02100000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02100000 0x100000>;
+ ranges;
+
+ usbotg1: usb@02184000 {
+ compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+ reg = <0x02184000 0x200>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc 0>;
+ fsl,anatop = <&anatop>;
+ status = "disabled";
+ };
+
+ usbotg2: usb@02184200 {
+ compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+ reg = <0x02184200 0x200>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USBOH3>;
+ fsl,usbphy = <&usbphy2>;
+ fsl,usbmisc = <&usbmisc 1>;
+ status = "disabled";
+ };
+
+ usbh: usb@02184400 {
+ compatible = "fsl,imx6sx-usb", "fsl,imx27-usb";
+ reg = <0x02184400 0x200>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USBOH3>;
+ fsl,usbmisc = <&usbmisc 2>;
+ phy_type = "hsic";
+ fsl,anatop = <&anatop>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@02184800 {
+ #index-cells = <1>;
+ compatible = "fsl,imx6sx-usbmisc", "fsl,imx6q-usbmisc";
+ reg = <0x02184800 0x200>;
+ clocks = <&clks IMX6SX_CLK_USBOH3>;
+ };
+
+ fec1: ethernet@02188000 {
+ compatible = "fsl,imx6sx-fec", "fsl,imx6q-fec";
+ reg = <0x02188000 0x4000>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ENET>,
+ <&clks IMX6SX_CLK_ENET_AHB>,
+ <&clks IMX6SX_CLK_ENET_PTP>,
+ <&clks IMX6SX_CLK_ENET_REF>,
+ <&clks IMX6SX_CLK_ENET_PTP>;
+ clock-names = "ipg", "ahb", "ptp",
+ "enet_clk_ref", "enet_out";
+ status = "disabled";
+ };
+
+ mlb: mlb@0218c000 {
+ reg = <0x0218c000 0x4000>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_MLB>;
+ status = "disabled";
+ };
+
+ usdhc1: usdhc@02190000 {
+ compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ reg = <0x02190000 0x4000>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USDHC1>,
+ <&clks IMX6SX_CLK_USDHC1>,
+ <&clks IMX6SX_CLK_USDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usdhc2: usdhc@02194000 {
+ compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ reg = <0x02194000 0x4000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USDHC2>,
+ <&clks IMX6SX_CLK_USDHC2>,
+ <&clks IMX6SX_CLK_USDHC2>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usdhc3: usdhc@02198000 {
+ compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ reg = <0x02198000 0x4000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USDHC3>,
+ <&clks IMX6SX_CLK_USDHC3>,
+ <&clks IMX6SX_CLK_USDHC3>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ usdhc4: usdhc@0219c000 {
+ compatible = "fsl,imx6sx-usdhc", "fsl,imx6sl-usdhc";
+ reg = <0x0219c000 0x4000>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_USDHC4>,
+ <&clks IMX6SX_CLK_USDHC4>,
+ <&clks IMX6SX_CLK_USDHC4>;
+ clock-names = "ipg", "ahb", "per";
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@021a0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+ reg = <0x021a0000 0x4000>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_I2C1>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@021a4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+ reg = <0x021a4000 0x4000>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_I2C2>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@021a8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+ reg = <0x021a8000 0x4000>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_I2C3>;
+ status = "disabled";
+ };
+
+ mmdc: mmdc@021b0000 {
+ compatible = "fsl,imx6sx-mmdc", "fsl,imx6q-mmdc";
+ reg = <0x021b0000 0x4000>;
+ };
+
+ fec2: ethernet@021b4000 {
+ compatible = "fsl,imx6sx-fec";
+ reg = <0x021b4000 0x4000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ENET>,
+ <&clks IMX6SX_CLK_ENET_AHB>,
+ <&clks IMX6SX_CLK_ENET_PTP>,
+ <&clks IMX6SX_CLK_ENET2_REF_125M>,
+ <&clks IMX6SX_CLK_ENET_PTP>;
+ clock-names = "ipg", "ahb", "ptp",
+ "enet_clk_ref", "enet_out";
+ status = "disabled";
+ };
+
+ weim: weim@021b8000 {
+ compatible = "fsl,imx6sx-weim", "fsl,imx6q-weim";
+ reg = <0x021b8000 0x4000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_EIM_SLOW>;
+ };
+
+ ocotp: ocotp@021bc000 {
+ compatible = "fsl,imx6sx-ocotp", "syscon";
+ reg = <0x021bc000 0x4000>;
+ clocks = <&clks IMX6SX_CLK_OCOTP>;
+ };
+
+ sai1: sai@021d4000 {
+ compatible = "fsl,imx6sx-sai";
+ reg = <0x021d4000 0x4000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SAI1_IPG>,
+ <&clks IMX6SX_CLK_SAI1>,
+ <&clks 0>, <&clks 0>;
+ clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&sdma 31 23 0>, <&sdma 32 23 0>;
+ dma-source = <&gpr 0 15 0 16>;
+ status = "disabled";
+ };
+
+ audmux: audmux@021d8000 {
+ compatible = "fsl,imx6sx-audmux", "fsl,imx31-audmux";
+ reg = <0x021d8000 0x4000>;
+ status = "disabled";
+ };
+
+ sai2: sai@021dc000 {
+ compatible = "fsl,imx6sx-sai";
+ reg = <0x021dc000 0x4000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_SAI2_IPG>,
+ <&clks IMX6SX_CLK_SAI2>,
+ <&clks 0>, <&clks 0>;
+ clock-names = "bus", "mclk1", "mclk2", "mclk3";
+ dma-names = "rx", "tx";
+ dmas = <&sdma 33 23 0>, <&sdma 34 23 0>;
+ dma-source = <&gpr 0 17 0 18>;
+ status = "disabled";
+ };
+
+ qspi1: qspi@021e0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-qspi";
+ reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>;
+ reg-names = "QuadSPI", "QuadSPI-memory";
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_QSPI1>,
+ <&clks IMX6SX_CLK_QSPI1>;
+ clock-names = "qspi_en", "qspi";
+ status = "disabled";
+ };
+
+ qspi2: qspi@021e4000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-qspi";
+ reg = <0x021e4000 0x4000>, <0x70000000 0x10000000>;
+ reg-names = "QuadSPI", "QuadSPI-memory";
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_QSPI2>,
+ <&clks IMX6SX_CLK_QSPI2>;
+ clock-names = "qspi_en", "qspi";
+ status = "disabled";
+ };
+
+ uart2: serial@021e8000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x021e8000 0x4000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@021ec000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x021ec000 0x4000>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart4: serial@021f0000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x021f0000 0x4000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart5: serial@021f4000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x021f4000 0x4000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2c4: i2c@021f8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-i2c", "fsl,imx21-i2c";
+ reg = <0x021f8000 0x4000>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_I2C4>;
+ status = "disabled";
+ };
+ };
+
+ aips3: aips-bus@02200000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02200000 0x100000>;
+ ranges;
+
+ spba-bus@02200000 {
+ compatible = "fsl,spba-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x02240000 0x40000>;
+ ranges;
+
+ csi1: csi@02214000 {
+ reg = <0x02214000 0x4000>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
+ <&clks IMX6SX_CLK_CSI>,
+ <&clks IMX6SX_CLK_DCIC1>;
+ clock-names = "disp-axi", "csi_mclk", "dcic";
+ status = "disabled";
+ };
+
+ pxp: pxp@02218000 {
+ reg = <0x02218000 0x4000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PXP_AXI>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pxp-axi", "disp-axi";
+ status = "disabled";
+ };
+
+ csi2: csi@0221c000 {
+ reg = <0x0221c000 0x4000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DISPLAY_AXI>,
+ <&clks IMX6SX_CLK_CSI>,
+ <&clks IMX6SX_CLK_DCIC2>;
+ clock-names = "disp-axi", "csi_mclk", "dcic";
+ status = "disabled";
+ };
+
+ lcdif1: lcdif@02220000 {
+ reg = <0x02220000 0x4000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>,
+ <&clks IMX6SX_CLK_LCDIF_APB>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pix", "axi", "disp_axi";
+ status = "disabled";
+ };
+
+ lcdif2: lcdif@02224000 {
+ reg = <0x02224000 0x4000>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_LCDIF2_PIX>,
+ <&clks IMX6SX_CLK_LCDIF_APB>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pix", "axi", "disp_axi";
+ status = "disabled";
+ };
+
+ vadc: vadc@02228000 {
+ reg = <0x02228000 0x4000>, <0x0222c000 0x4000>;
+ reg-names = "vadc-vafe", "vadc-vdec";
+ clocks = <&clks IMX6SX_CLK_VADC>,
+ <&clks IMX6SX_CLK_CSI>;
+ clock-names = "vadc", "csi";
+ status = "disabled";
+ };
+ };
+
+ adc1: adc@02280000 {
+ compatible = "fsl,imx6sx-adc", "fsl,vf610-adc";
+ reg = <0x02280000 0x4000>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_IPG>;
+ clock-names = "adc";
+ status = "disabled";
+ };
+
+ adc2: adc@02284000 {
+ compatible = "fsl,imx6sx-adc", "fsl,vf610-adc";
+ reg = <0x02284000 0x4000>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_IPG>;
+ clock-names = "adc";
+ status = "disabled";
+ };
+
+ wdog3: wdog@02288000 {
+ compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
+ reg = <0x02288000 0x4000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_DUMMY>;
+ status = "disabled";
+ };
+
+ ecspi5: ecspi@0228c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ reg = <0x0228c000 0x4000>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_ECSPI5>,
+ <&clks IMX6SX_CLK_ECSPI5>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart6: serial@022a0000 {
+ compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+ reg = <0x022a0000 0x4000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_UART_IPG>,
+ <&clks IMX6SX_CLK_UART_SERIAL>;
+ clock-names = "ipg", "per";
+ dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ pwm5: pwm@022a4000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x022a4000 0x4000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM5>,
+ <&clks IMX6SX_CLK_PWM5>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm6: pwm@022a8000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x022a8000 0x4000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM6>,
+ <&clks IMX6SX_CLK_PWM6>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm7: pwm@022ac000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x022ac000 0x4000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM7>,
+ <&clks IMX6SX_CLK_PWM7>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+
+ pwm8: pwm@0022b0000 {
+ compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
+ reg = <0x0022b0000 0x4000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PWM8>,
+ <&clks IMX6SX_CLK_PWM8>;
+ clock-names = "ipg", "per";
+ #pwm-cells = <2>;
+ };
+ };
+
+ pcie: pcie@0x08000000 {
+ compatible = "fsl,imx6sx-pcie", "snps,dw-pcie";
+ reg = <0x08ffc000 0x4000>; /* DBI */
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ /* configuration space */
+ ranges = <0x00000800 0 0x08f00000 0x08f00000 0 0x00080000
+ /* downstream I/O */
+ 0x81000000 0 0 0x08f80000 0 0x00010000
+ /* non-prefetchable memory */
+ 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
+ <&clks IMX6SX_CLK_PCIE_AXI>,
+ <&clks IMX6SX_CLK_LVDS1_OUT>,
+ <&clks IMX6SX_CLK_DISPLAY_AXI>;
+ clock-names = "pcie_ref_125m", "pcie_axi",
+ "lvds_gate", "display_axi";
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index b10e6351da53..cf06e32ee108 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -8,6 +8,7 @@
/ {
model = "ARM Integrator/AP";
compatible = "arm,integrator-ap";
+ dma-ranges = <0x80000000 0x0 0x80000000>;
aliases {
arm,timer-primary = &timer2;
diff --git a/arch/arm/boot/dts/k2e-clocks.dtsi b/arch/arm/boot/dts/k2e-clocks.dtsi
index 90774d604bc1..598afe91c676 100644
--- a/arch/arm/boot/dts/k2e-clocks.dtsi
+++ b/arch/arm/boot/dts/k2e-clocks.dtsi
@@ -22,7 +22,7 @@ clocks {
#clock-cells = <0>;
compatible = "ti,keystone,pll-clock";
clocks = <&refclkpass>;
- clock-output-names = "pa-pll-clk";
+ clock-output-names = "papllclk";
reg = <0x02620358 4>;
reg-names = "control";
};
diff --git a/arch/arm/boot/dts/k2hk-clocks.dtsi b/arch/arm/boot/dts/k2hk-clocks.dtsi
index 96e65365afe3..d5adee3c0067 100644
--- a/arch/arm/boot/dts/k2hk-clocks.dtsi
+++ b/arch/arm/boot/dts/k2hk-clocks.dtsi
@@ -31,7 +31,7 @@ clocks {
#clock-cells = <0>;
compatible = "ti,keystone,pll-clock";
clocks = <&refclkpass>;
- clock-output-names = "pa-pll-clk";
+ clock-output-names = "papllclk";
reg = <0x02620358 4>;
reg-names = "control";
};
diff --git a/arch/arm/boot/dts/k2hk-evm.dts b/arch/arm/boot/dts/k2hk-evm.dts
index 1f90cbf27fd7..3223cc152a85 100644
--- a/arch/arm/boot/dts/k2hk-evm.dts
+++ b/arch/arm/boot/dts/k2hk-evm.dts
@@ -167,3 +167,15 @@
};
};
};
+
+&mdio {
+ ethphy0: ethernet-phy@0 {
+ compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/k2l-clocks.dtsi b/arch/arm/boot/dts/k2l-clocks.dtsi
index f584b80200f8..eb1e3e29f073 100644
--- a/arch/arm/boot/dts/k2l-clocks.dtsi
+++ b/arch/arm/boot/dts/k2l-clocks.dtsi
@@ -31,7 +31,7 @@ clocks {
#clock-cells = <0>;
compatible = "ti,keystone,pll-clock";
clocks = <&refclksys>;
- clock-output-names = "pa-pll-clk";
+ clock-output-names = "papllclk";
reg = <0x02620358 4>;
reg-names = "control";
};
diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/keystone-clocks.dtsi
index 93f82c7010ab..0c334b25781e 100644
--- a/arch/arm/boot/dts/keystone-clocks.dtsi
+++ b/arch/arm/boot/dts/keystone-clocks.dtsi
@@ -215,7 +215,7 @@ clocks {
clkpa: clkpa {
#clock-cells = <0>;
compatible = "ti,keystone,psc-clock";
- clocks = <&chipclk16>;
+ clocks = <&paclk13>;
clock-output-names = "pa";
reg = <0x0235001c 0xb00>, <0x02350008 0x400>;
reg-names = "control", "domain";
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index c1414cb81fd4..9e31fe7d31f8 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -266,5 +266,16 @@
ranges = <0 0 0x30000000 0x10000000
1 0 0x21000A00 0x00000100>;
};
+
+ mdio: mdio@02090300 {
+ compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x02090300 0x100>;
+ status = "disabled";
+ clocks = <&clkpa>;
+ clock-names = "fck";
+ bus_freq = <2500000>;
+ };
};
};
diff --git a/arch/arm/boot/dts/kirkwood-d2net.dts b/arch/arm/boot/dts/kirkwood-d2net.dts
new file mode 100644
index 000000000000..6b7856025001
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-d2net.dts
@@ -0,0 +1,42 @@
+/*
+ * Device Tree file for d2 Network v2
+ *
+ * Copyright (C) 2014 Simon Guinot <simon.guinot@sequanux.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.
+*/
+
+/dts-v1/;
+
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+ model = "LaCie d2 Network v2";
+ compatible = "lacie,d2net_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+
+ ns2-leds {
+ compatible = "lacie,ns2-leds";
+
+ blue-sata {
+ label = "d2net_v2:blue:sata";
+ slow-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+ cmd-gpio = <&gpio0 30 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ red-fail {
+ label = "d2net_v2:red:fail";
+ gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-net2big.dts b/arch/arm/boot/dts/kirkwood-net2big.dts
new file mode 100644
index 000000000000..53dc37a3b687
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-net2big.dts
@@ -0,0 +1,60 @@
+/*
+ * Device Tree file for LaCie 2Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+ model = "LaCie 2Big Network v2";
+ compatible = "lacie,net2big_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+};
+
+&regulators {
+ regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "hdd1power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+ };
+
+ clocks {
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+ };
+};
+
+&i2c0 {
+ g762@3e {
+ compatible = "gmt,g762";
+ reg = <0x3e>;
+ clocks = <&g762_clk>;
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-net5big.dts b/arch/arm/boot/dts/kirkwood-net5big.dts
new file mode 100644
index 000000000000..36155b749d9f
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-net5big.dts
@@ -0,0 +1,111 @@
+/*
+ * Device Tree file for LaCie 5Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+ model = "LaCie 5Big Network v2";
+ compatible = "lacie,net5big_v2", "lacie,netxbig", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x20000000>;
+ };
+
+};
+
+&regulators {
+ regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "hdd1power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+ };
+
+ regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "hdd2power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ };
+
+ regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "hdd3power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ regulator-name = "hdd4power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ clocks {
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+ };
+};
+
+&mdio {
+ ethphy1: ethernet-phy@1 {
+ reg = <0>;
+ };
+};
+
+&eth1 {
+ status = "okay";
+ ethernet1-port@0 {
+ phy-handle = <&ethphy1>;
+ };
+};
+
+
+&i2c0 {
+ g762@3e {
+ compatible = "gmt,g762";
+ reg = <0x3e>;
+ clocks = <&g762_clk>;
+ };
+};
diff --git a/arch/arm/boot/dts/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/kirkwood-netxbig.dtsi
new file mode 100644
index 000000000000..b0cfb7cd30b9
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-netxbig.dtsi
@@ -0,0 +1,154 @@
+/*
+ * Device Tree common file for LaCie 2Big and 5Big Network v2
+ *
+ * Copyright (C) 2014
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * Based on netxbig_v2-setup.c,
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+ chosen {
+ bootargs = "console=ttyS0,115200n8";
+ stdout-path = &uart0;
+ };
+
+ ocp@f1000000 {
+ serial@12000 {
+ status = "okay";
+ };
+
+ spi@10600 {
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mxicy,mx25l4005a";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ mode = <0>;
+
+ partition@0 {
+ reg = <0x0 0x80000>;
+ label = "u-boot";
+ };
+ };
+ };
+
+ sata@80000 {
+ status = "okay";
+ nr-ports = <2>;
+ };
+
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * button@1 and button@2 represent a three position rocker
+ * switch. Thus the conventional KEY_POWER does not fit
+ */
+ button@1 {
+ label = "Back power switch (on|auto)";
+ linux,code = <KEY_ESC>;
+ linux,input-type = <5>;
+ gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+ };
+ button@2 {
+ label = "Back power switch (auto|off)";
+ linux,code = <KEY_1>;
+ linux,input-type = <5>;
+ gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+ };
+ button@3 {
+ label = "Function button";
+ linux,code = <KEY_OPTION>;
+ gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+ };
+
+ };
+
+ gpio-poweroff {
+ compatible = "gpio-poweroff";
+ gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ regulators: regulators {
+ status = "okay";
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+
+ regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "hdd0power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+ };
+ };
+};
+
+&mdio {
+ status = "okay";
+
+ ethphy0: ethernet-phy@0 {
+ reg = <8>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ reg = <0>;
+ };
+};
+
+&eth0 {
+ status = "okay";
+ ethernet0-port@0 {
+ phy-handle = <&ethphy0>;
+ };
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+
+ pmx_button_function: pmx-button-function {
+ marvell,pins = "mpp34";
+ marvell,function = "gpio";
+ };
+ pmx_button_power_off: pmx-button-power-off {
+ marvell,pins = "mpp15";
+ marvell,function = "gpio";
+ };
+ pmx_button_power_on: pmx-button-power-on {
+ marvell,pins = "mpp13";
+ marvell,function = "gpio";
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c04";
+ pagesize = <16>;
+ reg = <0x50>;
+ };
+};
diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts
index 928f6eef2d59..e83e4f9310b8 100644
--- a/arch/arm/boot/dts/kizbox.dts
+++ b/arch/arm/boot/dts/kizbox.dts
@@ -30,6 +30,10 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/mpa1600.dts b/arch/arm/boot/dts/mpa1600.dts
index ccf9ea242f72..f0f5e1098928 100644
--- a/arch/arm/boot/dts/mpa1600.dts
+++ b/arch/arm/boot/dts/mpa1600.dts
@@ -25,6 +25,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <18432000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <18432000>;
+ };
};
ahb {
diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/boot/dts/mt6589-aquaris5.dts
index 201842a3769e..443b4467de15 100644
--- a/arch/arm/mach-s5pv210/include/mach/dma.h
+++ b/arch/arm/boot/dts/mt6589-aquaris5.dts
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@gmail.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
@@ -11,16 +11,15 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
+/dts-v1/;
+#include "mt6589.dtsi"
-/* This platform uses the common DMA API driver for PL330 */
-#include <plat/dma-pl330.h>
+/ {
+ model = "bq Aquaris5";
-#endif /* __MACH_DMA_H */
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mt6589.dtsi
new file mode 100644
index 000000000000..d0297a051549
--- /dev/null
+++ b/arch/arm/boot/dts/mt6589.dtsi
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+ compatible = "mediatek,mt6589";
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x1>;
+ };
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x2>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x3>;
+ };
+
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ system_clk: dummy13m {
+ compatible = "fixed-clock";
+ clock-frequency = <13000000>;
+ #clock-cells = <0>;
+ };
+
+ rtc_clk: dummy32k {
+ compatible = "fixed-clock";
+ clock-frequency = <32000>;
+ #clock-cells = <0>;
+ };
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ timer: timer@10008000 {
+ compatible = "mediatek,mt6577-timer";
+ reg = <0x10008000 0x80>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&system_clk>, <&rtc_clk>;
+ clock-names = "system-clk", "rtc-clk";
+ };
+
+ gic: interrupt-controller@10212000 {
+ compatible = "arm,cortex-a15-gic";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x10211000 0x1000>,
+ <0x10212000 0x1000>,
+ <0x10214000 0x2000>,
+ <0x10216000 0x2000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi
index e83b0468080c..9be3c1266378 100644
--- a/arch/arm/boot/dts/omap2420.dtsi
+++ b/arch/arm/boot/dts/omap2420.dtsi
@@ -157,6 +157,8 @@
interrupts = <26>, <34>;
interrupt-names = "dsp", "iva";
ti,hwmods = "mailbox";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <6>;
};
timer1: timer@48028000 {
@@ -182,3 +184,6 @@
&i2c2 {
compatible = "ti,omap2420-i2c";
};
+
+/include/ "omap24xx-clocks.dtsi"
+/include/ "omap2420-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
index c4e8013801ee..1a00f15d9096 100644
--- a/arch/arm/boot/dts/omap2430.dtsi
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -247,6 +247,8 @@
reg = <0x48094000 0x200>;
interrupts = <26>;
ti,hwmods = "mailbox";
+ ti,mbox-num-users = <4>;
+ ti,mbox-num-fifos = <6>;
};
timer1: timer@49018000 {
@@ -288,3 +290,6 @@
&i2c2 {
compatible = "ti,omap2430-i2c";
};
+
+/include/ "omap24xx-clocks.dtsi"
+/include/ "omap2430-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index b2891a9a6975..575a49bf968d 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -332,6 +332,8 @@
ti,hwmods = "mailbox";
reg = <0x48094000 0x200>;
interrupts = <26>;
+ ti,mbox-num-users = <2>;
+ ti,mbox-num-fifos = <2>;
};
mcspi1: spi@48098000 {
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 7e26d222bfe3..69408b53200d 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -649,6 +649,15 @@
};
};
+ mailbox: mailbox@4a0f4000 {
+ compatible = "ti,omap4-mailbox";
+ reg = <0x4a0f4000 0x200>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ ti,hwmods = "mailbox";
+ ti,mbox-num-users = <3>;
+ ti,mbox-num-fifos = <8>;
+ };
+
timer1: timer@4a318000 {
compatible = "ti,omap3430-timer";
reg = <0x4a318000 0x80>;
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 1e1b05768cec..159720d6c956 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -100,15 +100,33 @@
};
};
};
+
+ sound: sound {
+ compatible = "ti,abe-twl6040";
+ ti,model = "omap5-uevm";
+
+ ti,mclk-freq = <19200000>;
+
+ ti,mcpdm = <&mcpdm>;
+
+ ti,twl6040 = <&twl6040>;
+
+ /* Audio routing */
+ ti,audio-routing =
+ "Headset Stereophone", "HSOL",
+ "Headset Stereophone", "HSOR",
+ "Line Out", "AUXL",
+ "Line Out", "AUXR",
+ "HSMIC", "Headset Mic",
+ "Headset Mic", "Headset Mic Bias",
+ "AFML", "Line In",
+ "AFMR", "Line In";
+ };
};
&omap5_pmx_core {
pinctrl-names = "default";
pinctrl-0 = <
- &twl6040_pins
- &mcpdm_pins
- &mcbsp1_pins
- &mcbsp2_pins
&usbhost_pins
&led_gpio_pins
>;
@@ -306,6 +324,11 @@
ti,wakeup;
};
+ clk32kgaudio: palmas_clk32k@1 {
+ compatible = "ti,palmas-clk32kgaudio";
+ #clock-cells = <0>;
+ };
+
palmas_pmic {
compatible = "ti,palmas-pmic";
interrupt-parent = <&palmas>;
@@ -489,6 +512,25 @@
};
};
};
+
+ twl6040: twl@4b {
+ compatible = "ti,twl6040";
+ reg = <0x4b>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&twl6040_pins>;
+
+ interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
+ interrupt-parent = <&gic>;
+ ti,audpwron-gpio = <&gpio5 13 0>; /* gpio line 141 */
+
+ vio-supply = <&smps7_reg>;
+ v2v1-supply = <&smps9_reg>;
+ enable-active-high;
+
+ clocks = <&clk32kgaudio>;
+ clock-names = "clk32k";
+ };
};
&i2c5 {
@@ -505,8 +547,22 @@
};
};
-&mcbsp3 {
- status = "disabled";
+&mcpdm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcpdm_pins>;
+ status = "okay";
+};
+
+&mcbsp1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcbsp1_pins>;
+ status = "okay";
+};
+
+&mcbsp2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcbsp2_pins>;
+ status = "okay";
};
&usbhshost {
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index a4ed54988866..fc8df1739f39 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -640,6 +640,8 @@
reg = <0x4a0f4000 0x200>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mailbox";
+ ti,mbox-num-users = <3>;
+ ti,mbox-num-fifos = <8>;
};
timer1: timer@4ae18000 {
@@ -985,6 +987,66 @@
dma-names = "audio_tx";
};
};
+
+ abb_mpu: regulator-abb-mpu {
+ compatible = "ti,abb-v2";
+ regulator-name = "abb_mpu";
+ #address-cells = <0>;
+ #size-cells = <0>;
+ clocks = <&sys_clkin>;
+ ti,settling-time = <50>;
+ ti,clock-cycles = <16>;
+
+ reg = <0x4ae07cdc 0x8>, <0x4ae06014 0x4>,
+ <0x4a0021c4 0x8>, <0x4ae0c318 0x4>;
+ reg-names = "base-address", "int-address",
+ "efuse-address", "ldo-address";
+ ti,tranxdone-status-mask = <0x80>;
+ /* LDOVBBMPU_MUX_CTRL */
+ ti,ldovbb-override-mask = <0x400>;
+ /* LDOVBBMPU_VSET_OUT */
+ ti,ldovbb-vset-mask = <0x1F>;
+
+ /*
+ * NOTE: only FBB mode used but actual vset will
+ * determine final biasing
+ */
+ ti,abb_info = <
+ /*uV ABB efuse rbb_m fbb_m vset_m*/
+ 1060000 0 0x0 0 0x02000000 0x01F00000
+ 1250000 0 0x4 0 0x02000000 0x01F00000
+ >;
+ };
+
+ abb_mm: regulator-abb-mm {
+ compatible = "ti,abb-v2";
+ regulator-name = "abb_mm";
+ #address-cells = <0>;
+ #size-cells = <0>;
+ clocks = <&sys_clkin>;
+ ti,settling-time = <50>;
+ ti,clock-cycles = <16>;
+
+ reg = <0x4ae07ce4 0x8>, <0x4ae06010 0x4>,
+ <0x4a0021a4 0x8>, <0x4ae0c314 0x4>;
+ reg-names = "base-address", "int-address",
+ "efuse-address", "ldo-address";
+ ti,tranxdone-status-mask = <0x80000000>;
+ /* LDOVBBMM_MUX_CTRL */
+ ti,ldovbb-override-mask = <0x400>;
+ /* LDOVBBMM_VSET_OUT */
+ ti,ldovbb-vset-mask = <0x1F>;
+
+ /*
+ * NOTE: only FBB mode used but actual vset will
+ * determine final biasing
+ */
+ ti,abb_info = <
+ /*uV ABB efuse rbb_m fbb_m vset_m*/
+ 1025000 0 0x0 0 0x02000000 0x01F00000
+ 1120000 0 0x4 0 0x02000000 0x01F00000
+ >;
+ };
};
};
diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/pm9g45.dts
index 33ffabe9c4c8..66afcff67fde 100644
--- a/arch/arm/boot/dts/pm9g45.dts
+++ b/arch/arm/boot/dts/pm9g45.dts
@@ -29,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
index 56849b55e1c2..20705467f4c9 100644
--- a/arch/arm/boot/dts/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -57,3 +57,13 @@
&scif2 {
status = "okay";
};
+
+&spi4 {
+ status = "okay";
+
+ codec: codec@0 {
+ compatible = "wlf,wm8978";
+ reg = <0>;
+ spi-max-frequency = <5000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index f50fbc8f3bd9..bdee22541189 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -144,6 +144,7 @@
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
+ clock-frequency = <400000000>;
};
};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
index 70b1fff8f4a3..a860f32bca27 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
@@ -16,6 +16,10 @@
model = "APE6EVM";
compatible = "renesas,ape6evm-reference", "renesas,r8a73a4";
+ aliases {
+ serial0 = &scifa0;
+ };
+
chosen {
bootargs = "console=ttySC0,115200 ignore_loglevel rw";
};
@@ -90,9 +94,6 @@
};
&pfc {
- pinctrl-0 = <&scifa0_pins>;
- pinctrl-names = "default";
-
scifa0_pins: serial0 {
renesas,groups = "scifa0_data";
renesas,function = "scifa0";
@@ -123,6 +124,13 @@
status = "okay";
};
+&scifa0 {
+ pinctrl-0 = <&scifa0_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
&sdhi0 {
vmmc-supply = <&vcc_sdhi0>;
bus-width = <4>;
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 82c5ac825386..d8ec5058c351 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -252,6 +252,48 @@
status = "disabled";
};
+ scifa0: serial@e6c40000 {
+ compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
+ reg = <0 0xe6c40000 0 0x100>;
+ interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa1: serial@e6c50000 {
+ compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
+ reg = <0 0xe6c50000 0 0x100>;
+ interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb2: serial@e6c20000 {
+ compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+ reg = <0 0xe6c20000 0 0x100>;
+ interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb3: serial@e6c30000 {
+ compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+ reg = <0 0xe6c30000 0 0x100>;
+ interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb4: serial@e6ce0000 {
+ compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+ reg = <0 0xe6ce0000 0 0x100>;
+ interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb5: serial@e6cf0000 {
+ compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+ reg = <0 0xe6cf0000 0 0x100>;
+ interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
mmcif0: mmc@ee200000 {
compatible = "renesas,sh-mmcif";
reg = <0 0xee200000 0 0x80>;
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
index 486007d7ffe4..ee9e7d5c97a9 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
@@ -19,8 +19,12 @@
model = "armadillo 800 eva reference";
compatible = "renesas,armadillo800eva-reference", "renesas,r8a7740";
+ aliases {
+ serial1 = &scifa1;
+ };
+
chosen {
- bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
+ bootargs = "console=tty0 console=ttySC1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
};
memory {
@@ -104,17 +108,21 @@
leds {
compatible = "gpio-leds";
- led1 {
+ led3 {
gpios = <&pfc 102 GPIO_ACTIVE_HIGH>;
+ label = "LED3";
};
- led2 {
+ led4 {
gpios = <&pfc 111 GPIO_ACTIVE_HIGH>;
+ label = "LED4";
};
- led3 {
+ led5 {
gpios = <&pfc 110 GPIO_ACTIVE_HIGH>;
+ label = "LED5";
};
- led4 {
+ led6 {
gpios = <&pfc 177 GPIO_ACTIVE_HIGH>;
+ label = "LED6";
};
};
@@ -198,9 +206,6 @@
};
&pfc {
- pinctrl-0 = <&scifa1_pins>;
- pinctrl-names = "default";
-
ether_pins: ether {
renesas,groups = "gether_mii", "gether_int";
renesas,function = "gether";
@@ -252,6 +257,13 @@
status = "okay";
};
+&scifa1 {
+ pinctrl-0 = <&scifa1_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
&sdhi0 {
pinctrl-0 = <&sdhi0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 55d29f4d2ed6..bda18fb3d9e5 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -156,6 +156,69 @@
status = "disabled";
};
+ scifa0: serial@e6c40000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6c40000 0x100>;
+ interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa1: serial@e6c50000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6c50000 0x100>;
+ interrupts = <0 101 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa2: serial@e6c60000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6c60000 0x100>;
+ interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa3: serial@e6c70000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6c70000 0x100>;
+ interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa4: serial@e6c80000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6c80000 0x100>;
+ interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa5: serial@e6cb0000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6cb0000 0x100>;
+ interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa6: serial@e6cc0000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6cc0000 0x100>;
+ interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa7: serial@e6cd0000 {
+ compatible = "renesas,scifa-r8a7740", "renesas,scifa";
+ reg = <0xe6cd0000 0x100>;
+ interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb8: serial@e6c30000 {
+ compatible = "renesas,scifb-r8a7740", "renesas,scifb";
+ reg = <0xe6c30000 0x100>;
+ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pfc: pfc@e6050000 {
compatible = "renesas,pfc-r8a7740";
reg = <0xe6050000 0x8000>,
diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
index f76f6ec01e19..3342c74c5de8 100644
--- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -23,6 +23,10 @@
model = "bockw";
compatible = "renesas,bockw-reference", "renesas,r8a7778";
+ aliases {
+ serial0 = &scif0;
+ };
+
chosen {
bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
};
@@ -70,9 +74,6 @@
};
&pfc {
- pinctrl-0 = <&scif0_pins>;
- pinctrl-names = "default";
-
scif0_pins: serial0 {
renesas,groups = "scif0_data_a", "scif0_ctrl";
renesas,function = "scif0";
@@ -124,3 +125,10 @@
};
};
};
+
+&scif0 {
+ pinctrl-0 = <&scif0_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 3af0a2187493..ecfdf4b01b5a 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -156,6 +156,48 @@
status = "disabled";
};
+ scif0: serial@ffe40000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe40000 0x100>;
+ interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scif1: serial@ffe41000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe41000 0x100>;
+ interrupts = <0 71 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scif2: serial@ffe42000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe42000 0x100>;
+ interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scif3: serial@ffe43000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe43000 0x100>;
+ interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scif4: serial@ffe44000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe44000 0x100>;
+ interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scif5: serial@ffe45000 {
+ compatible = "renesas,scif-r8a7778", "renesas,scif";
+ reg = <0xffe45000 0x100>;
+ interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
mmcif: mmc@ffe4e000 {
compatible = "renesas,sh-mmcif";
reg = <0xffe4e000 0x100>;
diff --git a/arch/arm/boot/dts/r8a7779-marzen-reference.dts b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
deleted file mode 100644
index b27c6373ff4d..000000000000
--- a/arch/arm/boot/dts/r8a7779-marzen-reference.dts
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Reference Device Tree Source for the Marzen board
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- * Copyright (C) 2013 Simon Horman
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/dts-v1/;
-#include "r8a7779.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
-/ {
- model = "marzen";
- compatible = "renesas,marzen-reference", "renesas,r8a7779";
-
- chosen {
- bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on rw";
- };
-
- memory {
- device_type = "memory";
- reg = <0x60000000 0x40000000>;
- };
-
- fixedregulator3v3: fixedregulator@0 {
- compatible = "regulator-fixed";
- regulator-name = "fixed-3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- lan0@18000000 {
- compatible = "smsc,lan9220", "smsc,lan9115";
- reg = <0x18000000 0x100>;
- pinctrl-0 = <&lan0_pins>;
- pinctrl-names = "default";
-
- phy-mode = "mii";
- interrupt-parent = <&irqpin0>;
- interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
- smsc,irq-push-pull;
- reg-io-width = <4>;
- vddvario-supply = <&fixedregulator3v3>;
- vdd33a-supply = <&fixedregulator3v3>;
- };
-
- leds {
- compatible = "gpio-leds";
- led2 {
- gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
- };
- led3 {
- gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
- };
- led4 {
- gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
- };
- };
-};
-
-&irqpin0 {
- status = "okay";
-};
-
-&pfc {
- pinctrl-0 = <&scif2_pins &scif4_pins>;
- pinctrl-names = "default";
-
- lan0_pins: lan0 {
- intc {
- renesas,groups = "intc_irq1_b";
- renesas,function = "intc";
- };
- lbsc {
- renesas,groups = "lbsc_ex_cs0";
- renesas,function = "lbsc";
- };
- };
-
- scif2_pins: serial2 {
- renesas,groups = "scif2_data_c";
- renesas,function = "scif2";
- };
-
- scif4_pins: serial4 {
- renesas,groups = "scif4_data";
- renesas,function = "scif4";
- };
-
- sdhi0_pins: sd0 {
- renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
- renesas,function = "sdhi0";
- };
-
- hspi0_pins: hspi0 {
- renesas,groups = "hspi0";
- renesas,function = "hspi0";
- };
-};
-
-&sdhi0 {
- pinctrl-0 = <&sdhi0_pins>;
- pinctrl-names = "default";
-
- vmmc-supply = <&fixedregulator3v3>;
- bus-width = <4>;
- status = "okay";
-};
-
-&hspi0 {
- pinctrl-0 = <&hspi0_pins>;
- pinctrl-names = "default";
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts
index a7af2c2371f2..5745555df943 100644
--- a/arch/arm/boot/dts/r8a7779-marzen.dts
+++ b/arch/arm/boot/dts/r8a7779-marzen.dts
@@ -11,17 +11,131 @@
/dts-v1/;
#include "r8a7779.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "marzen";
compatible = "renesas,marzen", "renesas,r8a7779";
+ aliases {
+ serial2 = &scif2;
+ serial4 = &scif4;
+ };
+
chosen {
- bootargs = "console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on";
+ bootargs = "console=ttySC2,115200 ignore_loglevel root=/dev/nfs ip=on";
};
memory {
device_type = "memory";
reg = <0x60000000 0x40000000>;
};
+
+ fixedregulator3v3: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lan0@18000000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0x18000000 0x100>;
+ pinctrl-0 = <&lan0_pins>;
+ pinctrl-names = "default";
+
+ phy-mode = "mii";
+ interrupt-parent = <&irqpin0>;
+ interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+ smsc,irq-push-pull;
+ reg-io-width = <4>;
+ vddvario-supply = <&fixedregulator3v3>;
+ vdd33a-supply = <&fixedregulator3v3>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ led2 {
+ gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+ };
+ led3 {
+ gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+ };
+ led4 {
+ gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
+ };
+ };
+};
+
+&irqpin0 {
+ status = "okay";
+};
+
+&extal_clk {
+ clock-frequency = <31250000>;
+};
+
+&pfc {
+ lan0_pins: lan0 {
+ intc {
+ renesas,groups = "intc_irq1_b";
+ renesas,function = "intc";
+ };
+ lbsc {
+ renesas,groups = "lbsc_ex_cs0";
+ renesas,function = "lbsc";
+ };
+ };
+
+ scif2_pins: serial2 {
+ renesas,groups = "scif2_data_c";
+ renesas,function = "scif2";
+ };
+
+ scif4_pins: serial4 {
+ renesas,groups = "scif4_data";
+ renesas,function = "scif4";
+ };
+
+ sdhi0_pins: sd0 {
+ renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+ renesas,function = "sdhi0";
+ };
+
+ hspi0_pins: hspi0 {
+ renesas,groups = "hspi0";
+ renesas,function = "hspi0";
+ };
+};
+
+&scif2 {
+ pinctrl-0 = <&scif2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&scif4 {
+ pinctrl-0 = <&scif4_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&sdhi0 {
+ pinctrl-0 = <&sdhi0_pins>;
+ pinctrl-names = "default";
+
+ vmmc-supply = <&fixedregulator3v3>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&hspi0 {
+ pinctrl-0 = <&hspi0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index b517c8e6b420..58d0d952d60e 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -11,6 +11,7 @@
/include/ "skeleton.dtsi"
+#include <dt-bindings/clock/r8a7779-clock.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
@@ -25,21 +26,25 @@
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
+ clock-frequency = <1000000000>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
+ clock-frequency = <1000000000>;
};
cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
+ clock-frequency = <1000000000>;
};
cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
+ clock-frequency = <1000000000>;
};
};
@@ -49,13 +54,13 @@
spi2 = &hspi2;
};
- gic: interrupt-controller@f0001000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0xf0001000 0x1000>,
- <0xf0000100 0x100>;
- };
+ gic: interrupt-controller@f0001000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0xf0001000 0x1000>,
+ <0xf0000100 0x100>;
+ };
gpio0: gpio@ffc40000 {
compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
@@ -157,6 +162,7 @@
compatible = "renesas,i2c-r8a7779";
reg = <0xffc70000 0x1000>;
interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp0_clks R8A7779_CLK_I2C0>;
status = "disabled";
};
@@ -166,6 +172,7 @@
compatible = "renesas,i2c-r8a7779";
reg = <0xffc71000 0x1000>;
interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp0_clks R8A7779_CLK_I2C1>;
status = "disabled";
};
@@ -175,6 +182,7 @@
compatible = "renesas,i2c-r8a7779";
reg = <0xffc72000 0x1000>;
interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp0_clks R8A7779_CLK_I2C2>;
status = "disabled";
};
@@ -184,6 +192,67 @@
compatible = "renesas,i2c-r8a7779";
reg = <0xffc73000 0x1000>;
interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp0_clks R8A7779_CLK_I2C3>;
+ status = "disabled";
+ };
+
+ scif0: serial@ffe40000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe40000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
+ status = "disabled";
+ };
+
+ scif1: serial@ffe41000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe41000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
+ status = "disabled";
+ };
+
+ scif2: serial@ffe42000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe42000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
+ status = "disabled";
+ };
+
+ scif3: serial@ffe43000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe43000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
+ status = "disabled";
+ };
+
+ scif4: serial@ffe44000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe44000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
+ status = "disabled";
+ };
+
+ scif5: serial@ffe45000 {
+ compatible = "renesas,scif-r8a7779", "renesas,scif";
+ reg = <0xffe45000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 93 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>;
+ clock-names = "sci_ick";
status = "disabled";
};
@@ -201,12 +270,14 @@
compatible = "renesas,rcar-sata";
reg = <0xfc600000 0x2000>;
interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7779_CLK_SATA>;
};
sdhi0: sd@ffe4c000 {
compatible = "renesas,sdhi-r8a7779";
reg = <0xffe4c000 0x100>;
interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7779_CLK_SDHI0>;
cap-sd-highspeed;
cap-sdio-irq;
status = "disabled";
@@ -216,6 +287,7 @@
compatible = "renesas,sdhi-r8a7779";
reg = <0xffe4d000 0x100>;
interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7779_CLK_SDHI1>;
cap-sd-highspeed;
cap-sdio-irq;
status = "disabled";
@@ -225,6 +297,7 @@
compatible = "renesas,sdhi-r8a7779";
reg = <0xffe4e000 0x100>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7779_CLK_SDHI2>;
cap-sd-highspeed;
cap-sdio-irq;
status = "disabled";
@@ -234,6 +307,7 @@
compatible = "renesas,sdhi-r8a7779";
reg = <0xffe4f000 0x100>;
interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7779_CLK_SDHI3>;
cap-sd-highspeed;
cap-sdio-irq;
status = "disabled";
@@ -245,6 +319,7 @@
interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
status = "disabled";
};
@@ -254,6 +329,7 @@
interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
status = "disabled";
};
@@ -263,6 +339,150 @@
interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
+ clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
status = "disabled";
};
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* External root clock */
+ extal_clk: extal_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overriden by the board. */
+ clock-frequency = <0>;
+ clock-output-names = "extal";
+ };
+
+ /* Special CPG clocks */
+ cpg_clocks: clocks@ffc80000 {
+ compatible = "renesas,r8a7779-cpg-clocks";
+ reg = <0xffc80000 0x30>;
+ clocks = <&extal_clk>;
+ #clock-cells = <1>;
+ clock-output-names = "plla", "z", "zs", "s",
+ "s1", "p", "b", "out";
+ };
+
+ /* Fixed factor clocks */
+ i_clk: i_clk {
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+ #clock-cells = <0>;
+ clock-div = <2>;
+ clock-mult = <1>;
+ clock-output-names = "i";
+ };
+ s3_clk: s3_clk {
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+ #clock-cells = <0>;
+ clock-div = <8>;
+ clock-mult = <1>;
+ clock-output-names = "s3";
+ };
+ s4_clk: s4_clk {
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+ #clock-cells = <0>;
+ clock-div = <16>;
+ clock-mult = <1>;
+ clock-output-names = "s4";
+ };
+ g_clk: g_clk {
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
+ #clock-cells = <0>;
+ clock-div = <24>;
+ clock-mult = <1>;
+ clock-output-names = "g";
+ };
+
+ /* Gate clocks */
+ mstp0_clks: clocks@ffc80030 {
+ compatible = "renesas,r8a7779-mstp-clocks",
+ "renesas,cpg-mstp-clocks";
+ reg = <0xffc80030 4>;
+ clocks = <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_S1>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>;
+ #clock-cells = <1>;
+ renesas,clock-indices = <
+ R8A7779_CLK_HSPI R8A7779_CLK_TMU2
+ R8A7779_CLK_TMU1 R8A7779_CLK_TMU0
+ R8A7779_CLK_HSCIF1 R8A7779_CLK_HSCIF0
+ R8A7779_CLK_SCIF5 R8A7779_CLK_SCIF4
+ R8A7779_CLK_SCIF3 R8A7779_CLK_SCIF2
+ R8A7779_CLK_SCIF1 R8A7779_CLK_SCIF0
+ R8A7779_CLK_I2C3 R8A7779_CLK_I2C2
+ R8A7779_CLK_I2C1 R8A7779_CLK_I2C0
+ >;
+ clock-output-names =
+ "hspi", "tmu2", "tmu1", "tmu0", "hscif1",
+ "hscif0", "scif5", "scif4", "scif3", "scif2",
+ "scif1", "scif0", "i2c3", "i2c2", "i2c1",
+ "i2c0";
+ };
+ mstp1_clks: clocks@ffc80034 {
+ compatible = "renesas,r8a7779-mstp-clocks",
+ "renesas,cpg-mstp-clocks";
+ reg = <0xffc80034 4>, <0xffc80044 4>;
+ clocks = <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_S>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_P>,
+ <&cpg_clocks R8A7779_CLK_S>;
+ #clock-cells = <1>;
+ renesas,clock-indices = <
+ R8A7779_CLK_USB01 R8A7779_CLK_USB2
+ R8A7779_CLK_DU R8A7779_CLK_VIN2
+ R8A7779_CLK_VIN1 R8A7779_CLK_VIN0
+ R8A7779_CLK_ETHER R8A7779_CLK_SATA
+ R8A7779_CLK_PCIE R8A7779_CLK_VIN3
+ >;
+ clock-output-names =
+ "usb01", "usb2",
+ "du", "vin2",
+ "vin1", "vin0",
+ "ether", "sata",
+ "pcie", "vin3";
+ };
+ mstp3_clks: clocks@ffc8003c {
+ compatible = "renesas,r8a7779-mstp-clocks",
+ "renesas,cpg-mstp-clocks";
+ reg = <0xffc8003c 4>;
+ clocks = <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>,
+ <&s4_clk>, <&s4_clk>;
+ #clock-cells = <1>;
+ renesas,clock-indices = <
+ R8A7779_CLK_SDHI3 R8A7779_CLK_SDHI2
+ R8A7779_CLK_SDHI1 R8A7779_CLK_SDHI0
+ R8A7779_CLK_MMC1 R8A7779_CLK_MMC0
+ >;
+ clock-output-names =
+ "sdhi3", "sdhi2", "sdhi1", "sdhi0",
+ "mmc1", "mmc0";
+ };
+ };
};
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index dd2fe46073f2..856b4236b674 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -29,12 +29,12 @@
memory@40000000 {
device_type = "memory";
- reg = <0 0x40000000 0 0x80000000>;
+ reg = <0 0x40000000 0 0x40000000>;
};
memory@180000000 {
device_type = "memory";
- reg = <1 0x80000000 0 0x80000000>;
+ reg = <1 0x40000000 0 0xc0000000>;
};
lbsc {
@@ -204,6 +204,36 @@
"msiof1_tx";
renesas,function = "msiof1";
};
+
+ iic1_pins: iic1 {
+ renesas,groups = "iic1";
+ renesas,function = "iic1";
+ };
+
+ iic2_pins: iic2 {
+ renesas,groups = "iic2";
+ renesas,function = "iic2";
+ };
+
+ iic3_pins: iic3 {
+ renesas,groups = "iic3";
+ renesas,function = "iic3";
+ };
+
+ usb0_pins: usb0 {
+ renesas,groups = "usb0";
+ renesas,function = "usb0";
+ };
+
+ usb1_pins: usb1 {
+ renesas,groups = "usb1";
+ renesas,function = "usb1";
+ };
+
+ usb2_pins: usb2 {
+ renesas,groups = "usb2";
+ renesas,function = "usb2";
+ };
};
&ether {
@@ -317,3 +347,57 @@
cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
status = "okay";
};
+
+&cpu0 {
+ cpu0-supply = <&vdd_dvfs>;
+};
+
+&iic0 {
+ status = "ok";
+};
+
+&iic1 {
+ status = "ok";
+ pinctrl-0 = <&iic1_pins>;
+ pinctrl-names = "default";
+};
+
+&iic2 {
+ status = "ok";
+ pinctrl-0 = <&iic2_pins>;
+ pinctrl-names = "default";
+};
+
+&iic3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&iic3_pins>;
+ status = "okay";
+
+ vdd_dvfs: regulator@68 {
+ compatible = "diasemi,da9210";
+ reg = <0x68>;
+
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&pci0 {
+ status = "okay";
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
+};
+
+&pci1 {
+ status = "okay";
+ pinctrl-0 = <&usb1_pins>;
+ pinctrl-names = "default";
+};
+
+&pci2 {
+ status = "okay";
+ pinctrl-0 = <&usb2_pins>;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 7ff29601f962..d9ddecbb859c 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -44,6 +44,17 @@
compatible = "arm,cortex-a15";
reg = <0>;
clock-frequency = <1300000000>;
+ voltage-tolerance = <1>; /* 1% */
+ clocks = <&cpg_clocks R8A7790_CLK_Z>;
+ clock-latency = <300000>; /* 300 us */
+
+ /* kHz - uV - OPPs unknown yet */
+ operating-points = <1400000 1000000>,
+ <1225000 1000000>,
+ <1050000 1000000>,
+ < 875000 1000000>,
+ < 700000 1000000>,
+ < 350000 1000000>;
};
cpu1: cpu@1 {
@@ -476,6 +487,15 @@
clock-output-names = "extal";
};
+ /* External PCIe clock - can be overridden by the board */
+ pcie_bus_clk: pcie_bus_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "pcie_bus";
+ status = "disabled";
+ };
+
/*
* The external audio clocks are configured as 0 Hz fixed frequency clocks by
* default. Boards that provide audio clocks should override them.
@@ -754,17 +774,17 @@
reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>,
<&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>,
- <&hp_clk>, <&hp_clk>, <&rclk_clk>;
+ <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
#clock-cells = <1>;
renesas,clock-indices = <
R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0
- R8A7790_CLK_IIC0 R8A7790_CLK_IIC1 R8A7790_CLK_CMT1
+ R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1
>;
clock-output-names =
"iic2", "tpu0", "mmcif1", "sdhi3",
"sdhi2", "sdhi1", "sdhi0", "mmcif0",
- "iic0", "iic1", "cmt1";
+ "iic0", "pciec", "iic1", "ssusb", "cmt1";
};
mstp5_clks: mstp5_clks@e6150144 {
compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -824,6 +844,39 @@
"rcan1", "rcan0", "qspi_mod", "iic3",
"i2c3", "i2c2", "i2c1", "i2c0";
};
+ mstp10_clks: mstp10_clks@e6150998 {
+ compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
+ reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+ clocks = <&p_clk>,
+ <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+ <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+ <&p_clk>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>;
+
+ #clock-cells = <1>;
+ clock-indices = <
+ R8A7790_CLK_SSI_ALL
+ R8A7790_CLK_SSI9 R8A7790_CLK_SSI8 R8A7790_CLK_SSI7 R8A7790_CLK_SSI6 R8A7790_CLK_SSI5
+ R8A7790_CLK_SSI4 R8A7790_CLK_SSI3 R8A7790_CLK_SSI2 R8A7790_CLK_SSI1 R8A7790_CLK_SSI0
+ R8A7790_CLK_SCU_ALL
+ R8A7790_CLK_SCU_DVC1 R8A7790_CLK_SCU_DVC0
+ R8A7790_CLK_SCU_SRC9 R8A7790_CLK_SCU_SRC8 R8A7790_CLK_SCU_SRC7 R8A7790_CLK_SCU_SRC6 R8A7790_CLK_SCU_SRC5
+ R8A7790_CLK_SCU_SRC4 R8A7790_CLK_SCU_SRC3 R8A7790_CLK_SCU_SRC2 R8A7790_CLK_SCU_SRC1 R8A7790_CLK_SCU_SRC0
+ >;
+ clock-output-names =
+ "ssi-all",
+ "ssi9", "ssi8", "ssi7", "ssi6", "ssi5",
+ "ssi4", "ssi3", "ssi2", "ssi1", "ssi0",
+ "scu-all",
+ "scu-dvc1", "scu-dvc0",
+ "scu-src9", "scu-src8", "scu-src7", "scu-src6", "scu-src5",
+ "scu-src4", "scu-src3", "scu-src2", "scu-src1", "scu-src0";
+ };
};
qspi: spi@e6b10000 {
@@ -876,4 +929,152 @@
#size-cells = <0>;
status = "disabled";
};
+
+ pci0: pci@ee090000 {
+ compatible = "renesas,pci-r8a7790";
+ device_type = "pci";
+ clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+ reg = <0 0xee090000 0 0xc00>,
+ <0 0xee080000 0 0x1100>;
+ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
+ bus-range = <0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0 0xee080000 0 0xee080000 0 0x00010000>;
+ interrupt-map-mask = <0xff00 0 0 0x7>;
+ interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+ 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+ 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pci1: pci@ee0b0000 {
+ compatible = "renesas,pci-r8a7790";
+ device_type = "pci";
+ clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+ reg = <0 0xee0b0000 0 0xc00>,
+ <0 0xee0a0000 0 0x1100>;
+ interrupts = <0 112 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
+ bus-range = <1 1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0 0xee0a0000 0 0xee0a0000 0 0x00010000>;
+ interrupt-map-mask = <0xff00 0 0 0x7>;
+ interrupt-map = <0x0000 0 0 1 &gic 0 112 IRQ_TYPE_LEVEL_HIGH
+ 0x0800 0 0 1 &gic 0 112 IRQ_TYPE_LEVEL_HIGH
+ 0x1000 0 0 2 &gic 0 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pci2: pci@ee0d0000 {
+ compatible = "renesas,pci-r8a7790";
+ device_type = "pci";
+ clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
+ reg = <0 0xee0d0000 0 0xc00>,
+ <0 0xee0c0000 0 0x1100>;
+ interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
+ bus-range = <2 2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0 0xee0c0000 0 0xee0c0000 0 0x00010000>;
+ interrupt-map-mask = <0xff00 0 0 0x7>;
+ interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+ 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+ 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pciec: pcie@fe000000 {
+ compatible = "renesas,pcie-r8a7790";
+ reg = <0 0xfe000000 0 0x80000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+ 0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+ 0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+ 0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+ /* Map all possible DDR as inbound ranges */
+ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000
+ 0x43000000 1 0x80000000 1 0x80000000 0 0x80000000>;
+ interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>,
+ <0 117 IRQ_TYPE_LEVEL_HIGH>,
+ <0 118 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7790_CLK_PCIEC>, <&pcie_bus_clk>;
+ clock-names = "pcie", "pcie_bus";
+ status = "disabled";
+ };
+
+ rcar_sound: rcar_sound@0xec500000 {
+ #sound-dai-cells = <1>;
+ compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
+ interrupt-parent = <&gic>;
+ reg = <0 0xec500000 0 0x1000>, /* SCU */
+ <0 0xec5a0000 0 0x100>, /* ADG */
+ <0 0xec540000 0 0x1000>, /* SSIU */
+ <0 0xec541000 0 0x1280>; /* SSI */
+ clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+ <&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>,
+ <&mstp10_clks R8A7790_CLK_SSI7>, <&mstp10_clks R8A7790_CLK_SSI6>,
+ <&mstp10_clks R8A7790_CLK_SSI5>, <&mstp10_clks R8A7790_CLK_SSI4>,
+ <&mstp10_clks R8A7790_CLK_SSI3>, <&mstp10_clks R8A7790_CLK_SSI2>,
+ <&mstp10_clks R8A7790_CLK_SSI1>, <&mstp10_clks R8A7790_CLK_SSI0>,
+ <&mstp10_clks R8A7790_CLK_SCU_SRC9>, <&mstp10_clks R8A7790_CLK_SCU_SRC8>,
+ <&mstp10_clks R8A7790_CLK_SCU_SRC7>, <&mstp10_clks R8A7790_CLK_SCU_SRC6>,
+ <&mstp10_clks R8A7790_CLK_SCU_SRC5>, <&mstp10_clks R8A7790_CLK_SCU_SRC4>,
+ <&mstp10_clks R8A7790_CLK_SCU_SRC3>, <&mstp10_clks R8A7790_CLK_SCU_SRC2>,
+ <&mstp10_clks R8A7790_CLK_SCU_SRC1>, <&mstp10_clks R8A7790_CLK_SCU_SRC0>,
+ <&mstp10_clks R8A7790_CLK_SCU_DVC0>, <&mstp10_clks R8A7790_CLK_SCU_DVC1>,
+ <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>;
+ clock-names = "ssi-all",
+ "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
+ "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+ "src.9", "src.8", "src.7", "src.6", "src.5",
+ "src.4", "src.3", "src.2", "src.1", "src.0",
+ "dvc.0", "dvc.1",
+ "clk_a", "clk_b", "clk_c", "clk_i";
+
+ status = "disabled";
+
+ rcar_sound,dvc {
+ dvc0: dvc@0 { };
+ dvc1: dvc@1 { };
+ };
+
+ rcar_sound,src {
+ src0: src@0 { };
+ src1: src@1 { };
+ src2: src@2 { };
+ src3: src@3 { };
+ src4: src@4 { };
+ src5: src@5 { };
+ src6: src@6 { };
+ src7: src@7 { };
+ src8: src@8 { };
+ src9: src@9 { };
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+ };
+ };
};
diff --git a/arch/arm/boot/dts/r8a7791-henninger.dts b/arch/arm/boot/dts/r8a7791-henninger.dts
index cc6d992e8db2..3a2ef0a2a137 100644
--- a/arch/arm/boot/dts/r8a7791-henninger.dts
+++ b/arch/arm/boot/dts/r8a7791-henninger.dts
@@ -110,6 +110,11 @@
renesas,function = "sdhi2";
};
+ i2c2_pins: i2c2 {
+ renesas,groups = "i2c2";
+ renesas,function = "i2c2";
+ };
+
qspi_pins: spi0 {
renesas,groups = "qspi_ctrl", "qspi_data4";
renesas,function = "qspi";
@@ -120,6 +125,16 @@
"msiof0_tx";
renesas,function = "msiof0";
};
+
+ usb0_pins: usb0 {
+ renesas,groups = "usb0";
+ renesas,function = "usb0";
+ };
+
+ usb1_pins: usb1 {
+ renesas,groups = "usb1";
+ renesas,function = "usb1";
+ };
};
&scif0 {
@@ -146,7 +161,7 @@
};
&sata0 {
- status = "okay";
+ status = "okay";
};
&sdhi0 {
@@ -170,6 +185,14 @@
status = "okay";
};
+&i2c2 {
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
&qspi {
pinctrl-0 = <&qspi_pins>;
pinctrl-names = "default";
@@ -217,3 +240,23 @@
spi-cpha;
};
};
+
+&pci0 {
+ status = "okay";
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
+};
+
+&pci1 {
+ status = "okay";
+ pinctrl-0 = <&usb1_pins>;
+ pinctrl-names = "default";
+};
+
+&pcie_bus_clk {
+ status = "okay";
+};
+
+&pciec {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 05d44f9b202f..23486c081a69 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -215,25 +215,6 @@
clock-frequency = <20000000>;
};
-&i2c2 {
- pinctrl-0 = <&i2c2_pins>;
- pinctrl-names = "default";
-
- status = "okay";
- clock-frequency = <400000>;
-
- eeprom@50 {
- compatible = "renesas,24c02";
- reg = <0x50>;
- pagesize = <16>;
- };
-};
-
-&i2c6 {
- status = "okay";
- clock-frequency = <100000>;
-};
-
&pfc {
pinctrl-0 = <&du_pins>;
pinctrl-names = "default";
@@ -293,6 +274,21 @@
"msiof0_tx";
renesas,function = "msiof0";
};
+
+ i2c6_pins: i2c6 {
+ renesas,groups = "i2c6";
+ renesas,function = "i2c6";
+ };
+
+ usb0_pins: usb0 {
+ renesas,groups = "usb0";
+ renesas,function = "usb0";
+ };
+
+ usb1_pins: usb1 {
+ renesas,groups = "usb1";
+ renesas,function = "usb1";
+ };
};
&ether {
@@ -408,3 +404,58 @@
spi-cpha;
};
};
+
+&i2c2 {
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ eeprom@50 {
+ compatible = "renesas,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
+
+&i2c6 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c6_pins>;
+ status = "okay";
+ clock-frequency = <100000>;
+
+ vdd_dvfs: regulator@68 {
+ compatible = "diasemi,da9210";
+ reg = <0x68>;
+
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
+&pci0 {
+ status = "okay";
+ pinctrl-0 = <&usb0_pins>;
+ pinctrl-names = "default";
+};
+
+&pci1 {
+ status = "okay";
+ pinctrl-0 = <&usb1_pins>;
+ pinctrl-names = "default";
+};
+
+&pcie_bus_clk {
+ status = "okay";
+};
+
+&pciec {
+ status = "okay";
+};
+
+&cpu0 {
+ cpu0-supply = <&vdd_dvfs>;
+};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 79f68acfd5d4..0d82a4b3c650 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -45,6 +45,17 @@
compatible = "arm,cortex-a15";
reg = <0>;
clock-frequency = <1500000000>;
+ voltage-tolerance = <1>; /* 1% */
+ clocks = <&cpg_clocks R8A7791_CLK_Z>;
+ clock-latency = <300000>; /* 300 us */
+
+ /* kHz - uV - OPPs unknown yet */
+ operating-points = <1500000 1000000>,
+ <1312500 1000000>,
+ <1125000 1000000>,
+ < 937500 1000000>,
+ < 750000 1000000>,
+ < 375000 1000000>;
};
cpu1: cpu@1 {
@@ -521,6 +532,38 @@
clock-output-names = "extal";
};
+ /*
+ * The external audio clocks are configured as 0 Hz fixed frequency clocks by
+ * default. Boards that provide audio clocks should override them.
+ */
+ audio_clk_a: audio_clk_a {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "audio_clk_a";
+ };
+ audio_clk_b: audio_clk_b {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "audio_clk_b";
+ };
+ audio_clk_c: audio_clk_c {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "audio_clk_c";
+ };
+
+ /* External PCIe clock - can be overridden by the board */
+ pcie_bus_clk: pcie_bus_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <100000000>;
+ clock-output-names = "pcie_bus";
+ status = "disabled";
+ };
+
/* Special CPG clocks */
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,r8a7791-cpg-clocks",
@@ -743,30 +786,34 @@
compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>;
clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>,
- <&mp_clk>, <&mp_clk>, <&mp_clk>;
+ <&mp_clk>, <&mp_clk>, <&mp_clk>,
+ <&zs_clk>, <&zs_clk>;
#clock-cells = <1>;
renesas,clock-indices = <
R8A7791_CLK_SCIFA2 R8A7791_CLK_SCIFA1 R8A7791_CLK_SCIFA0
R8A7791_CLK_MSIOF2 R8A7791_CLK_SCIFB0 R8A7791_CLK_SCIFB1
R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2
+ R8A7791_CLK_SYS_DMAC1 R8A7791_CLK_SYS_DMAC0
>;
clock-output-names =
"scifa2", "scifa1", "scifa0", "msiof2", "scifb0",
- "scifb1", "msiof1", "scifb2";
+ "scifb1", "msiof1", "scifb2",
+ "sys-dmac1", "sys-dmac0";
};
mstp3_clks: mstp3_clks@e615013c {
compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7791_CLK_SD0>,
- <&mmc0_clk>, <&hp_clk>, <&hp_clk>, <&rclk_clk>;
+ <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
#clock-cells = <1>;
renesas,clock-indices = <
R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0
- R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_IIC1 R8A7791_CLK_CMT1
+ R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_PCIEC R8A7791_CLK_IIC1
+ R8A7791_CLK_SSUSB R8A7791_CLK_CMT1
>;
clock-output-names =
"tpu0", "sdhi2", "sdhi1", "sdhi0",
- "mmcif0", "i2c7", "i2c8", "cmt1";
+ "mmcif0", "i2c7", "pciec", "i2c8", "ssusb", "cmt1";
};
mstp5_clks: mstp5_clks@e6150144 {
compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -828,6 +875,39 @@
"rcan1", "rcan0", "qspi_mod", "i2c5", "i2c6", "i2c4", "i2c3", "i2c2",
"i2c1", "i2c0";
};
+ mstp10_clks: mstp10_clks@e6150998 {
+ compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
+ reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+ clocks = <&p_clk>,
+ <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+ <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+ <&p_clk>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
+ <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>;
+
+ #clock-cells = <1>;
+ clock-indices = <
+ R8A7791_CLK_SSI_ALL
+ R8A7791_CLK_SSI9 R8A7791_CLK_SSI8 R8A7791_CLK_SSI7 R8A7791_CLK_SSI6 R8A7791_CLK_SSI5
+ R8A7791_CLK_SSI4 R8A7791_CLK_SSI3 R8A7791_CLK_SSI2 R8A7791_CLK_SSI1 R8A7791_CLK_SSI0
+ R8A7791_CLK_SCU_ALL
+ R8A7791_CLK_SCU_DVC1 R8A7791_CLK_SCU_DVC0
+ R8A7791_CLK_SCU_SRC9 R8A7791_CLK_SCU_SRC8 R8A7791_CLK_SCU_SRC7 R8A7791_CLK_SCU_SRC6 R8A7791_CLK_SCU_SRC5
+ R8A7791_CLK_SCU_SRC4 R8A7791_CLK_SCU_SRC3 R8A7791_CLK_SCU_SRC2 R8A7791_CLK_SCU_SRC1 R8A7791_CLK_SCU_SRC0
+ >;
+ clock-output-names =
+ "ssi-all",
+ "ssi9", "ssi8", "ssi7", "ssi6", "ssi5",
+ "ssi4", "ssi3", "ssi2", "ssi1", "ssi0",
+ "scu-all",
+ "scu-dvc1", "scu-dvc0",
+ "scu-src9", "scu-src8", "scu-src7", "scu-src6", "scu-src5",
+ "scu-src4", "scu-src3", "scu-src2", "scu-src1", "scu-src0";
+ };
mstp11_clks: mstp11_clks@e615099c {
compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>;
@@ -880,4 +960,132 @@
#size-cells = <0>;
status = "disabled";
};
+
+ pci0: pci@ee090000 {
+ compatible = "renesas,pci-r8a7791";
+ device_type = "pci";
+ clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
+ reg = <0 0xee090000 0 0xc00>,
+ <0 0xee080000 0 0x1100>;
+ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
+ bus-range = <0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0 0xee080000 0 0xee080000 0 0x00010000>;
+ interrupt-map-mask = <0xff00 0 0 0x7>;
+ interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+ 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
+ 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pci1: pci@ee0d0000 {
+ compatible = "renesas,pci-r8a7791";
+ device_type = "pci";
+ clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
+ reg = <0 0xee0d0000 0 0xc00>,
+ <0 0xee0c0000 0 0x1100>;
+ interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+
+ bus-range = <1 1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x02000000 0 0xee0c0000 0 0xee0c0000 0 0x00010000>;
+ interrupt-map-mask = <0xff00 0 0 0x7>;
+ interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+ 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
+ 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pciec: pcie@fe000000 {
+ compatible = "renesas,pcie-r8a7791";
+ reg = <0 0xfe000000 0 0x80000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ bus-range = <0x00 0xff>;
+ device_type = "pci";
+ ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+ 0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+ 0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+ 0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+ /* Map all possible DDR as inbound ranges */
+ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000
+ 0x43000000 2 0x00000000 2 0x00000000 1 0x00000000>;
+ interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>,
+ <0 117 IRQ_TYPE_LEVEL_HIGH>,
+ <0 118 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 116 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7791_CLK_PCIEC>, <&pcie_bus_clk>;
+ clock-names = "pcie", "pcie_bus";
+ status = "disabled";
+ };
+
+ rcar_sound: rcar_sound@0xec500000 {
+ #sound-dai-cells = <1>;
+ compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
+ interrupt-parent = <&gic>;
+ reg = <0 0xec500000 0 0x1000>, /* SCU */
+ <0 0xec5a0000 0 0x100>, /* ADG */
+ <0 0xec540000 0 0x1000>, /* SSIU */
+ <0 0xec541000 0 0x1280>; /* SSI */
+ clocks = <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+ <&mstp10_clks R8A7791_CLK_SSI9>, <&mstp10_clks R8A7791_CLK_SSI8>,
+ <&mstp10_clks R8A7791_CLK_SSI7>, <&mstp10_clks R8A7791_CLK_SSI6>,
+ <&mstp10_clks R8A7791_CLK_SSI5>, <&mstp10_clks R8A7791_CLK_SSI4>,
+ <&mstp10_clks R8A7791_CLK_SSI3>, <&mstp10_clks R8A7791_CLK_SSI2>,
+ <&mstp10_clks R8A7791_CLK_SSI1>, <&mstp10_clks R8A7791_CLK_SSI0>,
+ <&mstp10_clks R8A7791_CLK_SCU_SRC9>, <&mstp10_clks R8A7791_CLK_SCU_SRC8>,
+ <&mstp10_clks R8A7791_CLK_SCU_SRC7>, <&mstp10_clks R8A7791_CLK_SCU_SRC6>,
+ <&mstp10_clks R8A7791_CLK_SCU_SRC5>, <&mstp10_clks R8A7791_CLK_SCU_SRC4>,
+ <&mstp10_clks R8A7791_CLK_SCU_SRC3>, <&mstp10_clks R8A7791_CLK_SCU_SRC2>,
+ <&mstp10_clks R8A7791_CLK_SCU_SRC1>, <&mstp10_clks R8A7791_CLK_SCU_SRC0>,
+ <&mstp10_clks R8A7791_CLK_SCU_DVC0>, <&mstp10_clks R8A7791_CLK_SCU_DVC1>,
+ <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>;
+ clock-names = "ssi-all",
+ "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
+ "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+ "src.9", "src.8", "src.7", "src.6", "src.5",
+ "src.4", "src.3", "src.2", "src.1", "src.0",
+ "dvc.0", "dvc.1",
+ "clk_a", "clk_b", "clk_c", "clk_i";
+
+ status = "disabled";
+
+ rcar_sound,dvc {
+ dvc0: dvc@0 { };
+ dvc1: dvc@1 { };
+ };
+
+ rcar_sound,src {
+ src0: src@0 { };
+ src1: src@1 { };
+ src2: src@2 { };
+ src3: src@3 { };
+ src4: src@4 { };
+ src5: src@5 { };
+ src6: src@6 { };
+ src7: src@7 { };
+ src8: src@8 { };
+ src9: src@9 { };
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
+ ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+ };
+ };
};
diff --git a/arch/arm/boot/dts/rk3066a-bqcurie2.dts b/arch/arm/boot/dts/rk3066a-bqcurie2.dts
index afb327322a4a..042f821d9e4d 100644
--- a/arch/arm/boot/dts/rk3066a-bqcurie2.dts
+++ b/arch/arm/boot/dts/rk3066a-bqcurie2.dts
@@ -24,87 +24,171 @@
reg = <0x60000000 0x40000000>;
};
- soc {
- uart0: serial@10124000 {
- status = "okay";
- };
+ vcc_sd0: fixed-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "sdmmc-supply";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+ startup-delay-us = <100000>;
+ vin-supply = <&vcc_io>;
+ };
- uart1: serial@10126000 {
- status = "okay";
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ autorepeat;
+
+ button@0 {
+ gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
+ linux,code = <116>;
+ label = "GPIO Key Power";
+ linux,input-type = <1>;
+ gpio-key,wakeup = <1>;
+ debounce-interval = <100>;
};
-
- uart2: serial@20064000 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_xfer>;
- status = "okay";
+ button@1 {
+ gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
+ linux,code = <104>;
+ label = "GPIO Key Vol-";
+ linux,input-type = <1>;
+ gpio-key,wakeup = <0>;
+ debounce-interval = <100>;
};
+ /* VOL+ comes somehow thru the ADC */
+ };
+};
- uart3: serial@20068000 {
- status = "okay";
- };
+&i2c1 {
+ status = "okay";
+ clock-frequency = <400000>;
- vcc_sd0: fixed-regulator {
- compatible = "regulator-fixed";
- regulator-name = "sdmmc-supply";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
- startup-delay-us = <100000>;
- };
+ tps: tps@2d {
+ reg = <0x2d>;
- dwmmc@10214000 { /* sdmmc */
- num-slots = <1>;
- status = "okay";
+ interrupt-parent = <&gpio6>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
- vmmc-supply = <&vcc_sd0>;
+ vcc5-supply = <&vcc_io>;
+ vcc6-supply = <&vcc_io>;
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- disable-wp;
+ regulators {
+ vcc_rtc: regulator@0 {
+ regulator-name = "vcc_rtc";
+ regulator-always-on;
};
- };
- dwmmc@10218000 { /* wifi */
- num-slots = <1>;
- status = "okay";
- non-removable;
+ vcc_io: regulator@1 {
+ regulator-name = "vcc_io";
+ regulator-always-on;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+ vdd_arm: regulator@2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
- slot@0 {
- reg = <0>;
- bus-width = <4>;
- disable-wp;
+ vcc_ddr: regulator@3 {
+ regulator-name = "vcc_ddr";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vcc18_cif: regulator@5 {
+ regulator-name = "vcc18_cif";
+ regulator-always-on;
+ };
+
+ vdd_11: regulator@6 {
+ regulator-name = "vdd_11";
+ regulator-always-on;
+ };
+
+ vcc_25: regulator@7 {
+ regulator-name = "vcc_25";
+ regulator-always-on;
+ };
+
+ vcc_18: regulator@8 {
+ regulator-name = "vcc_18";
+ regulator-always-on;
+ };
+
+ vcc25_hdmi: regulator@9 {
+ regulator-name = "vcc25_hdmi";
+ regulator-always-on;
+ };
+
+ vcca_33: regulator@10 {
+ regulator-name = "vcca_33";
+ regulator-always-on;
};
- };
- gpio-keys {
- compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- autorepeat;
-
- button@0 {
- gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
- linux,code = <116>;
- label = "GPIO Key Power";
- linux,input-type = <1>;
- gpio-key,wakeup = <1>;
- debounce-interval = <100>;
+ vcc_tp: regulator@11 {
+ regulator-name = "vcc_tp";
+ regulator-always-on;
};
- button@1 {
- gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
- linux,code = <104>;
- label = "GPIO Key Vol-";
- linux,input-type = <1>;
- gpio-key,wakeup = <0>;
- debounce-interval = <100>;
+
+ vcc28_cif: regulator@12 {
+ regulator-name = "vcc28_cif";
+ regulator-always-on;
};
- /* VOL+ comes somehow thru the ADC */
};
};
};
+
+/* must be included after &tps gets defined */
+#include "tps65910.dtsi"
+
+&mmc0 { /* sdmmc */
+ num-slots = <1>;
+ status = "okay";
+ vmmc-supply = <&vcc_sd0>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ disable-wp;
+ };
+};
+
+&mmc1 { /* wifi */
+ num-slots = <1>;
+ status = "okay";
+ non-removable;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ disable-wp;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3066a-clocks.dtsi b/arch/arm/boot/dts/rk3066a-clocks.dtsi
deleted file mode 100644
index 6e307fc4c451..000000000000
--- a/arch/arm/boot/dts/rk3066a-clocks.dtsi
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2013 MundoReader S.L.
- * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/ {
- clocks {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- /*
- * This is a dummy clock, to be used as placeholder on
- * other mux clocks when a specific parent clock is not
- * yet implemented. It should be dropped when the driver
- * is complete.
- */
- dummy: dummy {
- compatible = "fixed-clock";
- clock-frequency = <0>;
- #clock-cells = <0>;
- };
-
- xin24m: xin24m {
- compatible = "fixed-clock";
- clock-frequency = <24000000>;
- #clock-cells = <0>;
- };
-
- dummy48m: dummy48m {
- compatible = "fixed-clock";
- clock-frequency = <48000000>;
- #clock-cells = <0>;
- };
-
- dummy150m: dummy150m {
- compatible = "fixed-clock";
- clock-frequency = <150000000>;
- #clock-cells = <0>;
- };
-
- clk_gates0: gate-clk@200000d0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d0 0x4>;
- clocks = <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_core_periph", "gate_cpu_gpll",
- "gate_ddrphy", "gate_aclk_cpu",
- "gate_hclk_cpu", "gate_pclk_cpu",
- "gate_atclk_cpu", "gate_i2s0",
- "gate_i2s0_frac", "gate_i2s1",
- "gate_i2s1_frac", "gate_i2s2",
- "gate_i2s2_frac", "gate_spdif",
- "gate_spdif_frac", "gate_testclk";
-
- #clock-cells = <1>;
- };
-
- clk_gates1: gate-clk@200000d4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d4 0x4>;
- clocks = <&xin24m>, <&xin24m>,
- <&xin24m>, <&dummy>,
- <&dummy>, <&xin24m>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>;
-
- clock-output-names =
- "gate_timer0", "gate_timer1",
- "gate_timer2", "gate_jtag",
- "gate_aclk_lcdc1_src", "gate_otgphy0",
- "gate_otgphy1", "gate_ddr_gpll",
- "gate_uart0", "gate_frac_uart0",
- "gate_uart1", "gate_frac_uart1",
- "gate_uart2", "gate_frac_uart2",
- "gate_uart3", "gate_frac_uart3";
-
- #clock-cells = <1>;
- };
-
- clk_gates2: gate-clk@200000d8 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d8 0x4>;
- clocks = <&clk_gates2 1>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&clk_gates2 3>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy48m>,
- <&dummy>, <&dummy48m>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_periph_src", "gate_aclk_periph",
- "gate_hclk_periph", "gate_pclk_periph",
- "gate_smc", "gate_mac",
- "gate_hsadc", "gate_hsadc_frac",
- "gate_saradc", "gate_spi0",
- "gate_spi1", "gate_mmc0",
- "gate_mac_lbtest", "gate_mmc1",
- "gate_emmc", "gate_tsadc";
-
- #clock-cells = <1>;
- };
-
- clk_gates3: gate-clk@200000dc {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000dc 0x4>;
- clocks = <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
- "gate_dclk_lcdc1", "gate_pclkin_cif0",
- "gate_pclkin_cif1", "reserved",
- "reserved", "gate_cif0_out",
- "gate_cif1_out", "gate_aclk_vepu",
- "gate_hclk_vepu", "gate_aclk_vdpu",
- "gate_hclk_vdpu", "gate_gpu_src",
- "reserved", "gate_xin27m";
-
- #clock-cells = <1>;
- };
-
- clk_gates4: gate-clk@200000e0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e0 0x4>;
- clocks = <&clk_gates2 2>, <&clk_gates2 3>,
- <&clk_gates2 1>, <&clk_gates2 1>,
- <&clk_gates2 1>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates2 2>,
- <&clk_gates0 4>, <&clk_gates0 4>,
- <&clk_gates0 3>, <&clk_gates0 3>,
- <&clk_gates0 3>, <&clk_gates2 3>,
- <&clk_gates0 4>;
-
- clock-output-names =
- "gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
- "gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
- "gate_aclk_pei_niu", "gate_hclk_usb_peri",
- "gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
- "gate_hclk_cpubus", "gate_hclk_ahb2apb",
- "gate_aclk_strc_sys", "gate_aclk_l2mem_con",
- "gate_aclk_intmem", "gate_pclk_tsadc",
- "gate_hclk_hdmi";
-
- #clock-cells = <1>;
- };
-
- clk_gates5: gate-clk@200000e4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e4 0x4>;
- clocks = <&clk_gates0 3>, <&clk_gates2 1>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates0 4>, <&clk_gates0 5>,
- <&clk_gates2 1>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates4 5>,
- <&clk_gates4 5>, <&dummy>;
-
- clock-output-names =
- "gate_aclk_dmac1", "gate_aclk_dmac2",
- "gate_pclk_efuse", "gate_pclk_tzpc",
- "gate_pclk_grf", "gate_pclk_pmu",
- "gate_hclk_rom", "gate_pclk_ddrupctl",
- "gate_aclk_smc", "gate_hclk_nandc",
- "gate_hclk_mmc0", "gate_hclk_mmc1",
- "gate_hclk_emmc", "gate_hclk_otg0",
- "gate_hclk_otg1", "gate_aclk_gpu";
-
- #clock-cells = <1>;
- };
-
- clk_gates6: gate-clk@200000e8 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e8 0x4>;
- clocks = <&clk_gates3 0>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates1 4>,
- <&clk_gates0 4>, <&clk_gates3 0>,
- <&clk_gates0 4>, <&clk_gates1 4>,
- <&clk_gates3 0>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates1 4>,
- <&clk_gates0 4>, <&clk_gates3 0>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_aclk_lcdc0", "gate_hclk_lcdc0",
- "gate_hclk_lcdc1", "gate_aclk_lcdc1",
- "gate_hclk_cif0", "gate_aclk_cif0",
- "gate_hclk_cif1", "gate_aclk_cif1",
- "gate_aclk_ipp", "gate_hclk_ipp",
- "gate_hclk_rga", "gate_aclk_rga",
- "gate_hclk_vio_bus", "gate_aclk_vio0",
- "gate_aclk_vcodec", "gate_shclk_vio_h2h";
-
- #clock-cells = <1>;
- };
-
- clk_gates7: gate-clk@200000ec {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000ec 0x4>;
- clocks = <&clk_gates2 2>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates2 3>;
-
- clock-output-names =
- "gate_hclk_emac", "gate_hclk_spdif",
- "gate_hclk_i2s0_2ch", "gate_hclk_i2s1_2ch",
- "gate_hclk_i2s_8ch", "gate_hclk_hsadc",
- "gate_hclk_pidf", "gate_pclk_timer0",
- "gate_pclk_timer1", "gate_pclk_timer2",
- "gate_pclk_pwm01", "gate_pclk_pwm23",
- "gate_pclk_spi0", "gate_pclk_spi1",
- "gate_pclk_saradc", "gate_pclk_wdt";
-
- #clock-cells = <1>;
- };
-
- clk_gates8: gate-clk@200000f0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000f0 0x4>;
- clocks = <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&dummy>, <&clk_gates0 5>;
-
- clock-output-names =
- "gate_pclk_uart0", "gate_pclk_uart1",
- "gate_pclk_uart2", "gate_pclk_uart3",
- "gate_pclk_i2c0", "gate_pclk_i2c1",
- "gate_pclk_i2c2", "gate_pclk_i2c3",
- "gate_pclk_i2c4", "gate_pclk_gpio0",
- "gate_pclk_gpio1", "gate_pclk_gpio2",
- "gate_pclk_gpio3", "gate_pclk_gpio4",
- "reserved", "gate_pclk_gpio6";
-
- #clock-cells = <1>;
- };
-
- clk_gates9: gate-clk@200000f4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000f4 0x4>;
- clocks = <&dummy>, <&clk_gates0 5>,
- <&dummy>, <&dummy>,
- <&dummy>, <&clk_gates1 4>,
- <&clk_gates0 5>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>;
-
- clock-output-names =
- "gate_clk_core_dbg", "gate_pclk_dbg",
- "gate_clk_trace", "gate_atclk",
- "gate_clk_l2c", "gate_aclk_vio1",
- "gate_pclk_publ", "gate_aclk_intmem0",
- "gate_aclk_intmem1", "gate_aclk_intmem2",
- "gate_aclk_intmem3";
-
- #clock-cells = <1>;
- };
- };
-
-};
diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 4387cfd420ba..879a818fba51 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -15,8 +15,8 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3066a-cru.h>
#include "rk3xxx.dtsi"
-#include "rk3066a-clocks.dtsi"
/ {
compatible = "rockchip,rk3066a";
@@ -40,247 +40,392 @@
};
};
- soc {
- timer@20038000 {
- compatible = "snps,dw-apb-timer-osc";
- reg = <0x20038000 0x100>;
- interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates1 0>, <&clk_gates7 7>;
- clock-names = "timer", "pclk";
+ sram: sram@10080000 {
+ compatible = "mmio-sram";
+ reg = <0x10080000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10080000 0x10000>;
+
+ smp-sram@0 {
+ compatible = "rockchip,rk3066-smp-sram";
+ reg = <0x0 0x50>;
};
+ };
+
+ cru: clock-controller@20000000 {
+ compatible = "rockchip,rk3066a-cru";
+ reg = <0x20000000 0x1000>;
+ rockchip,grf = <&grf>;
- timer@2003a000 {
- compatible = "snps,dw-apb-timer-osc";
- reg = <0x2003a000 0x100>;
- interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates1 1>, <&clk_gates7 8>;
- clock-names = "timer", "pclk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ timer@2000e000 {
+ compatible = "snps,dw-apb-timer-osc";
+ reg = <0x2000e000 0x100>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_TIMER2>, <&cru PCLK_TIMER2>;
+ clock-names = "timer", "pclk";
+ };
+
+ timer@20038000 {
+ compatible = "snps,dw-apb-timer-osc";
+ reg = <0x20038000 0x100>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_TIMER0>, <&cru PCLK_TIMER0>;
+ clock-names = "timer", "pclk";
+ };
+
+ timer@2003a000 {
+ compatible = "snps,dw-apb-timer-osc";
+ reg = <0x2003a000 0x100>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_TIMER1>, <&cru PCLK_TIMER1>;
+ clock-names = "timer", "pclk";
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rk3066a-pinctrl";
+ rockchip,grf = <&grf>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ gpio0: gpio0@20034000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x20034000 0x100>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
};
- timer@2000e000 {
- compatible = "snps,dw-apb-timer-osc";
- reg = <0x2000e000 0x100>;
- interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates1 2>, <&clk_gates7 9>;
- clock-names = "timer", "pclk";
+ gpio1: gpio1@2003c000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x2003c000 0x100>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO1>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
};
- sram: sram@10080000 {
- compatible = "mmio-sram";
- reg = <0x10080000 0x10000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x10080000 0x10000>;
+ gpio2: gpio2@2003e000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x2003e000 0x100>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO2>;
- smp-sram@0 {
- compatible = "rockchip,rk3066-smp-sram";
- reg = <0x0 0x50>;
- };
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio3@20080000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x20080000 0x100>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO3>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
};
- pinctrl@20008000 {
- compatible = "rockchip,rk3066a-pinctrl";
- rockchip,grf = <&grf>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
+ gpio4: gpio4@20084000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x20084000 0x100>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO4>;
- gpio0: gpio0@20034000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x20034000 0x100>;
- interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 9>;
+ gpio-controller;
+ #gpio-cells = <2>;
- gpio-controller;
- #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ gpio6: gpio6@2000a000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x2000a000 0x100>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO6>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pcfg_pull_default: pcfg_pull_default {
+ bias-pull-pin-default;
+ };
+
+ pcfg_pull_none: pcfg_pull_none {
+ bias-disable;
+ };
+
+ i2c0 {
+ i2c0_xfer: i2c0-xfer {
+ rockchip,pins = <RK_GPIO2 28 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO2 29 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- gpio1: gpio1@2003c000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x2003c000 0x100>;
- interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 10>;
+ i2c1 {
+ i2c1_xfer: i2c1-xfer {
+ rockchip,pins = <RK_GPIO2 30 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO2 31 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ i2c2 {
+ i2c2_xfer: i2c2-xfer {
+ rockchip,pins = <RK_GPIO3 0 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ i2c3 {
+ i2c3_xfer: i2c3-xfer {
+ rockchip,pins = <RK_GPIO3 2 RK_FUNC_2 &pcfg_pull_none>,
+ <RK_GPIO3 3 RK_FUNC_2 &pcfg_pull_none>;
};
+ };
- gpio2: gpio2@2003e000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x2003e000 0x100>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 11>;
+ i2c4 {
+ i2c4_xfer: i2c4-xfer {
+ rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ pwm0 {
+ pwm0_out: pwm0-out {
+ rockchip,pins = <RK_GPIO0 3 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ pwm1 {
+ pwm1_out: pwm1-out {
+ rockchip,pins = <RK_GPIO0 4 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- gpio3: gpio3@20080000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x20080000 0x100>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 12>;
+ pwm2 {
+ pwm2_out: pwm2-out {
+ rockchip,pins = <RK_GPIO0 30 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ pwm3 {
+ pwm3_out: pwm3-out {
+ rockchip,pins = <RK_GPIO0 31 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ uart0 {
+ uart0_xfer: uart0-xfer {
+ rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
};
- gpio4: gpio4@20084000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x20084000 0x100>;
- interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 13>;
+ uart0_cts: uart0-cts {
+ rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ uart0_rts: uart0-rts {
+ rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
+ };
+ };
+
+ uart1 {
+ uart1_xfer: uart1-xfer {
+ rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ uart1_cts: uart1-cts {
+ rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
};
- gpio6: gpio6@2000a000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x2000a000 0x100>;
- interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 15>;
+ uart1_rts: uart1-rts {
+ rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ uart2 {
+ uart2_xfer: uart2-xfer {
+ rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
+ };
+ /* no rts / cts for uart2 */
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ uart3 {
+ uart3_xfer: uart3-xfer {
+ rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
};
- pcfg_pull_default: pcfg_pull_default {
- bias-pull-pin-default;
+ uart3_cts: uart3-cts {
+ rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
};
- pcfg_pull_none: pcfg_pull_none {
- bias-disable;
+ uart3_rts: uart3-rts {
+ rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
};
+ };
- uart0 {
- uart0_xfer: uart0-xfer {
- rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0 {
+ sd0_clk: sd0-clk {
+ rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart0_cts: uart0-cts {
- rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0_cmd: sd0-cmd {
+ rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart0_rts: uart0-rts {
- rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0_cd: sd0-cd {
+ rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
};
- uart1 {
- uart1_xfer: uart1-xfer {
- rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0_wp: sd0-wp {
+ rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart1_cts: uart1-cts {
- rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0_bus1: sd0-bus-width1 {
+ rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart1_rts: uart1-rts {
- rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd0_bus4: sd0-bus-width4 {
+ rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
};
+ };
- uart2 {
- uart2_xfer: uart2-xfer {
- rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
- };
- /* no rts / cts for uart2 */
+ sd1 {
+ sd1_clk: sd1-clk {
+ rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
};
- uart3 {
- uart3_xfer: uart3-xfer {
- rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd1_cmd: sd1-cmd {
+ rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart3_cts: uart3-cts {
- rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd1_cd: sd1-cd {
+ rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
+ };
- uart3_rts: uart3-rts {
- rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd1_wp: sd1-wp {
+ rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
};
- sd0 {
- sd0_clk: sd0-clk {
- rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd0_cmd: sd0-cmd {
- rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd0_cd: sd0-cd {
- rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd0_wp: sd0-wp {
- rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd0_bus1: sd0-bus-width1 {
- rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd0_bus4: sd0-bus-width4 {
- rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd1_bus1: sd1-bus-width1 {
+ rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
};
- sd1 {
- sd1_clk: sd1-clk {
- rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd1_cmd: sd1-cmd {
- rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd1_cd: sd1-cd {
- rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd1_wp: sd1-wp {
- rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd1_bus1: sd1-bus-width1 {
- rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
- };
-
- sd1_bus4: sd1-bus-width4 {
- rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
- <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
- };
+ sd1_bus4: sd1-bus-width4 {
+ rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
+ <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
};
};
};
};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_xfer>;
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_out>;
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm1_out>;
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_out>;
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_out>;
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+ compatible = "rockchip,rk3066-wdt", "snps,dw-wdt";
+};
diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi
deleted file mode 100644
index b1b92dc245ce..000000000000
--- a/arch/arm/boot/dts/rk3188-clocks.dtsi
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2013 MundoReader S.L.
- * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/ {
- clocks {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- /*
- * This is a dummy clock, to be used as placeholder on
- * other mux clocks when a specific parent clock is not
- * yet implemented. It should be dropped when the driver
- * is complete.
- */
- dummy: dummy {
- compatible = "fixed-clock";
- clock-frequency = <0>;
- #clock-cells = <0>;
- };
-
- xin24m: xin24m {
- compatible = "fixed-clock";
- clock-frequency = <24000000>;
- #clock-cells = <0>;
- };
-
- dummy48m: dummy48m {
- compatible = "fixed-clock";
- clock-frequency = <48000000>;
- #clock-cells = <0>;
- };
-
- dummy150m: dummy150m {
- compatible = "fixed-clock";
- clock-frequency = <150000000>;
- #clock-cells = <0>;
- };
-
- clk_gates0: gate-clk@200000d0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d0 0x4>;
- clocks = <&dummy150m>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_core_periph", "gate_cpu_gpll",
- "gate_ddrphy", "gate_aclk_cpu",
- "gate_hclk_cpu", "gate_pclk_cpu",
- "gate_atclk_cpu", "gate_aclk_core",
- "reserved", "gate_i2s0",
- "gate_i2s0_frac", "reserved",
- "reserved", "gate_spdif",
- "gate_spdif_frac", "gate_testclk";
-
- #clock-cells = <1>;
- };
-
- clk_gates1: gate-clk@200000d4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d4 0x4>;
- clocks = <&xin24m>, <&xin24m>,
- <&xin24m>, <&dummy>,
- <&dummy>, <&xin24m>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&xin24m>, <&dummy>;
-
- clock-output-names =
- "gate_timer0", "gate_timer1",
- "gate_timer3", "gate_jtag",
- "gate_aclk_lcdc1_src", "gate_otgphy0",
- "gate_otgphy1", "gate_ddr_gpll",
- "gate_uart0", "gate_frac_uart0",
- "gate_uart1", "gate_frac_uart1",
- "gate_uart2", "gate_frac_uart2",
- "gate_uart3", "gate_frac_uart3";
-
- #clock-cells = <1>;
- };
-
- clk_gates2: gate-clk@200000d8 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000d8 0x4>;
- clocks = <&clk_gates2 1>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&clk_gates2 3>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy48m>,
- <&dummy>, <&dummy48m>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_periph_src", "gate_aclk_periph",
- "gate_hclk_periph", "gate_pclk_periph",
- "gate_smc", "gate_mac",
- "gate_hsadc", "gate_hsadc_frac",
- "gate_saradc", "gate_spi0",
- "gate_spi1", "gate_mmc0",
- "gate_mac_lbtest", "gate_mmc1",
- "gate_emmc", "reserved";
-
- #clock-cells = <1>;
- };
-
- clk_gates3: gate-clk@200000dc {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000dc 0x4>;
- clocks = <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&xin24m>, <&xin24m>,
- <&dummy>, <&dummy>,
- <&xin24m>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&xin24m>, <&dummy>;
-
- clock-output-names =
- "gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
- "gate_dclk_lcdc1", "gate_pclkin_cif0",
- "gate_timer2", "gate_timer4",
- "gate_hsicphy", "gate_cif0_out",
- "gate_timer5", "gate_aclk_vepu",
- "gate_hclk_vepu", "gate_aclk_vdpu",
- "gate_hclk_vdpu", "reserved",
- "gate_timer6", "gate_aclk_gpu_src";
-
- #clock-cells = <1>;
- };
-
- clk_gates4: gate-clk@200000e0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e0 0x4>;
- clocks = <&clk_gates2 2>, <&clk_gates2 3>,
- <&clk_gates2 1>, <&clk_gates2 1>,
- <&clk_gates2 1>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates2 2>,
- <&clk_gates0 4>, <&clk_gates0 4>,
- <&clk_gates0 3>, <&dummy>,
- <&clk_gates0 3>, <&dummy>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
- "gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
- "gate_aclk_pei_niu", "gate_hclk_usb_peri",
- "gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
- "gate_hclk_cpubus", "gate_hclk_ahb2apb",
- "gate_aclk_strc_sys", "reserved",
- "gate_aclk_intmem", "reserved",
- "gate_hclk_imem1", "gate_hclk_imem0";
-
- #clock-cells = <1>;
- };
-
- clk_gates5: gate-clk@200000e4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e4 0x4>;
- clocks = <&clk_gates0 3>, <&clk_gates2 1>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates0 4>, <&clk_gates0 5>,
- <&clk_gates2 1>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates4 5>;
-
- clock-output-names =
- "gate_aclk_dmac1", "gate_aclk_dmac2",
- "gate_pclk_efuse", "gate_pclk_tzpc",
- "gate_pclk_grf", "gate_pclk_pmu",
- "gate_hclk_rom", "gate_pclk_ddrupctl",
- "gate_aclk_smc", "gate_hclk_nandc",
- "gate_hclk_mmc0", "gate_hclk_mmc1",
- "gate_hclk_emmc", "gate_hclk_otg0";
-
- #clock-cells = <1>;
- };
-
- clk_gates6: gate-clk@200000e8 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000e8 0x4>;
- clocks = <&clk_gates3 0>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates1 4>,
- <&clk_gates0 4>, <&clk_gates3 0>,
- <&dummy>, <&dummy>,
- <&clk_gates3 0>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&clk_gates1 4>,
- <&clk_gates0 4>, <&clk_gates3 0>;
-
- clock-output-names =
- "gate_aclk_lcdc0", "gate_hclk_lcdc0",
- "gate_hclk_lcdc1", "gate_aclk_lcdc1",
- "gate_hclk_cif0", "gate_aclk_cif0",
- "reserved", "reserved",
- "gate_aclk_ipp", "gate_hclk_ipp",
- "gate_hclk_rga", "gate_aclk_rga",
- "gate_hclk_vio_bus", "gate_aclk_vio0";
-
- #clock-cells = <1>;
- };
-
- clk_gates7: gate-clk@200000ec {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000ec 0x4>;
- clocks = <&clk_gates2 2>, <&clk_gates0 4>,
- <&clk_gates0 4>, <&dummy>,
- <&dummy>, <&clk_gates2 2>,
- <&clk_gates2 2>, <&clk_gates0 5>,
- <&dummy>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates2 3>;
-
- clock-output-names =
- "gate_hclk_emac", "gate_hclk_spdif",
- "gate_hclk_i2s0_2ch", "gate_hclk_otg1",
- "gate_hclk_hsic", "gate_hclk_hsadc",
- "gate_hclk_pidf", "gate_pclk_timer0",
- "reserved", "gate_pclk_timer2",
- "gate_pclk_pwm01", "gate_pclk_pwm23",
- "gate_pclk_spi0", "gate_pclk_spi1",
- "gate_pclk_saradc", "gate_pclk_wdt";
-
- #clock-cells = <1>;
- };
-
- clk_gates8: gate-clk@200000f0 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000f0 0x4>;
- clocks = <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&clk_gates2 3>,
- <&clk_gates2 3>, <&clk_gates0 5>,
- <&clk_gates0 5>, <&clk_gates0 5>,
- <&clk_gates2 3>, <&dummy>;
-
- clock-output-names =
- "gate_pclk_uart0", "gate_pclk_uart1",
- "gate_pclk_uart2", "gate_pclk_uart3",
- "gate_pclk_i2c0", "gate_pclk_i2c1",
- "gate_pclk_i2c2", "gate_pclk_i2c3",
- "gate_pclk_i2c4", "gate_pclk_gpio0",
- "gate_pclk_gpio1", "gate_pclk_gpio2",
- "gate_pclk_gpio3", "gate_aclk_gps";
-
- #clock-cells = <1>;
- };
-
- clk_gates9: gate-clk@200000f4 {
- compatible = "rockchip,rk2928-gate-clk";
- reg = <0x200000f4 0x4>;
- clocks = <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>,
- <&dummy>, <&dummy>;
-
- clock-output-names =
- "gate_clk_core_dbg", "gate_pclk_dbg",
- "gate_clk_trace", "gate_atclk",
- "gate_clk_l2c", "gate_aclk_vio1",
- "gate_pclk_publ", "gate_aclk_gpu";
-
- #clock-cells = <1>;
- };
- };
-
-};
diff --git a/arch/arm/boot/dts/rk3188-radxarock.dts b/arch/arm/boot/dts/rk3188-radxarock.dts
index a5eee55079cb..171b610db709 100644
--- a/arch/arm/boot/dts/rk3188-radxarock.dts
+++ b/arch/arm/boot/dts/rk3188-radxarock.dts
@@ -23,59 +23,205 @@
reg = <0x60000000 0x80000000>;
};
- soc {
- uart0: serial@10124000 {
- status = "okay";
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ autorepeat;
+
+ button@0 {
+ gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+ linux,code = <116>;
+ label = "GPIO Key Power";
+ linux,input-type = <1>;
+ gpio-key,wakeup = <1>;
+ debounce-interval = <100>;
};
+ };
- uart1: serial@10126000 {
- status = "okay";
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ green {
+ gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+ default-state = "off";
};
- uart2: serial@20064000 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_xfer>;
- status = "okay";
+ yellow {
+ gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+ default-state = "off";
};
- uart3: serial@20068000 {
- status = "okay";
+ sleep {
+ gpios = <&gpio0 15 0>;
+ default-state = "off";
};
+ };
- gpio-keys {
- compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- autorepeat;
-
- button@0 {
- gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
- linux,code = <116>;
- label = "GPIO Key Power";
- linux,input-type = <1>;
- gpio-key,wakeup = <1>;
- debounce-interval = <100>;
+ ir_recv: gpio-ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio0 10 1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_recv_pin>;
+ };
+
+ vcc_sd0: sdmmc-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "sdmmc-supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 1 GPIO_ACTIVE_LOW>;
+ startup-delay-us = <100000>;
+ vin-supply = <&vcc_io>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ act8846: act8846@5a {
+ compatible = "active-semi,act8846";
+ reg = <0x5a>;
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&act8846_dvs0_ctl>;
+
+ regulators {
+ vcc_ddr: REG1 {
+ regulator-name = "VCC_DDR";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ vdd_log: REG2 {
+ regulator-name = "VDD_LOG";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ vdd_arm: REG3 {
+ regulator-name = "VDD_ARM";
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ };
+
+ vcc_io: REG4 {
+ regulator-name = "VCC_IO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_10: REG5 {
+ regulator-name = "VDD_10";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ vdd_hdmi: REG6 {
+ regulator-name = "VDD_HDMI";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ vcc18: REG7 {
+ regulator-name = "VCC_18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
};
- };
- gpio-leds {
- compatible = "gpio-leds";
+ vcca_33: REG8 {
+ regulator-name = "VCCA_33";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vcc_rmii: REG9 {
+ regulator-name = "VCC_RMII";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
- green {
- gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
- default-state = "off";
+ vccio_wl: REG10 {
+ regulator-name = "VCCIO_WL";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
- yellow {
- gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
- default-state = "off";
+ vcc_18: REG11 {
+ regulator-name = "VCC18_IO";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
};
- sleep {
- gpios = <&gpio0 15 0>;
- default-state = "off";
+ vcc28: REG12 {
+ regulator-name = "VCC_28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
};
};
+ };
+};
+
+&mmc0 {
+ num-slots = <1>;
+ status = "okay";
+ vmmc-supply = <&vcc_sd0>;
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ disable-wp;
};
};
+
+&pinctrl {
+ pcfg_output_low: pcfg-output-low {
+ output-low;
+ };
+
+ act8846 {
+ act8846_dvs0_ctl: act8846-dvs0-ctl {
+ rockchip,pins = <RK_GPIO3 27 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+ };
+
+ ir-receiver {
+ ir_recv_pin: ir-recv-pin {
+ rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
index 238c996d4a7f..ee801a9c6b74 100644
--- a/arch/arm/boot/dts/rk3188.dtsi
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -15,8 +15,8 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3188-cru.h>
#include "rk3xxx.dtsi"
-#include "rk3188-clocks.dtsi"
/ {
compatible = "rockchip,rk3188";
@@ -52,215 +52,355 @@
};
};
- soc {
- global-timer@1013c200 {
- interrupts = <GIC_PPI 11 0xf04>;
+ sram: sram@10080000 {
+ compatible = "mmio-sram";
+ reg = <0x10080000 0x8000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10080000 0x8000>;
+
+ smp-sram@0 {
+ compatible = "rockchip,rk3066-smp-sram";
+ reg = <0x0 0x50>;
};
+ };
+
+ cru: clock-controller@20000000 {
+ compatible = "rockchip,rk3188-cru";
+ reg = <0x20000000 0x1000>;
+ rockchip,grf = <&grf>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rk3188-pinctrl";
+ rockchip,grf = <&grf>;
+ rockchip,pmu = <&pmu>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ gpio0: gpio0@0x2000a000 {
+ compatible = "rockchip,rk3188-gpio-bank0";
+ reg = <0x2000a000 0x100>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
- local-timer@1013c600 {
- interrupts = <GIC_PPI 13 0xf04>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
};
- sram: sram@10080000 {
- compatible = "mmio-sram";
- reg = <0x10080000 0x8000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x10080000 0x8000>;
+ gpio1: gpio1@0x2003c000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x2003c000 0x100>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO1>;
- smp-sram@0 {
- compatible = "rockchip,rk3066-smp-sram";
- reg = <0x0 0x50>;
- };
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
};
- pinctrl@20008000 {
- compatible = "rockchip,rk3188-pinctrl";
- rockchip,grf = <&grf>;
- rockchip,pmu = <&pmu>;
+ gpio2: gpio2@2003e000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x2003e000 0x100>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO2>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
+ gpio-controller;
+ #gpio-cells = <2>;
- gpio0: gpio0@0x2000a000 {
- compatible = "rockchip,rk3188-gpio-bank0";
- reg = <0x2000a000 0x100>;
- interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 9>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ gpio3: gpio3@20080000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0x20080000 0x100>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO3>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ gpio-controller;
+ #gpio-cells = <2>;
- gpio1: gpio1@0x2003c000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x2003c000 0x100>;
- interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ pcfg_pull_up: pcfg_pull_up {
+ bias-pull-up;
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pcfg_pull_down: pcfg_pull_down {
+ bias-pull-down;
+ };
- gpio2: gpio2@2003e000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x2003e000 0x100>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 11>;
+ pcfg_pull_none: pcfg_pull_none {
+ bias-disable;
+ };
+
+ i2c0 {
+ i2c0_xfer: i2c0-xfer {
+ rockchip,pins = <RK_GPIO1 24 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO1 25 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ i2c1 {
+ i2c1_xfer: i2c1-xfer {
+ rockchip,pins = <RK_GPIO1 26 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO1 27 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ i2c2 {
+ i2c2_xfer: i2c2-xfer {
+ rockchip,pins = <RK_GPIO1 28 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO1 29 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- gpio3: gpio3@20080000 {
- compatible = "rockchip,gpio-bank";
- reg = <0x20080000 0x100>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_gates8 12>;
+ i2c3 {
+ i2c3_xfer: i2c3-xfer {
+ rockchip,pins = <RK_GPIO3 14 RK_FUNC_2 &pcfg_pull_none>,
+ <RK_GPIO3 15 RK_FUNC_2 &pcfg_pull_none>;
+ };
+ };
- gpio-controller;
- #gpio-cells = <2>;
+ i2c4 {
+ i2c4_xfer: i2c4-xfer {
+ rockchip,pins = <RK_GPIO1 30 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO1 31 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
- interrupt-controller;
- #interrupt-cells = <2>;
+ pwm0 {
+ pwm0_out: pwm0-out {
+ rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- pcfg_pull_up: pcfg_pull_up {
- bias-pull-up;
+ pwm1 {
+ pwm1_out: pwm1-out {
+ rockchip,pins = <RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- pcfg_pull_down: pcfg_pull_down {
- bias-pull-down;
+ pwm2 {
+ pwm2_out: pwm2-out {
+ rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- pcfg_pull_none: pcfg_pull_none {
- bias-disable;
+ pwm3 {
+ pwm3_out: pwm3-out {
+ rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- uart0 {
- uart0_xfer: uart0-xfer {
- rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
- <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart0 {
+ uart0_xfer: uart0-xfer {
+ rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_up>,
+ <RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart0_cts: uart0-cts {
- rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart0_cts: uart0-cts {
+ rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart0_rts: uart0-rts {
- rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart0_rts: uart0-rts {
+ rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- uart1 {
- uart1_xfer: uart1-xfer {
- rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
- <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart1 {
+ uart1_xfer: uart1-xfer {
+ rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_up>,
+ <RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart1_cts: uart1-cts {
- rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart1_cts: uart1-cts {
+ rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart1_rts: uart1-rts {
- rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart1_rts: uart1-rts {
+ rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- uart2 {
- uart2_xfer: uart2-xfer {
- rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
- <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
- };
- /* no rts / cts for uart2 */
+ uart2 {
+ uart2_xfer: uart2-xfer {
+ rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_up>,
+ <RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
};
+ /* no rts / cts for uart2 */
+ };
- uart3 {
- uart3_xfer: uart3-xfer {
- rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
- <RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart3 {
+ uart3_xfer: uart3-xfer {
+ rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_up>,
+ <RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart3_cts: uart3-cts {
- rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart3_cts: uart3-cts {
+ rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
+ };
- uart3_rts: uart3-rts {
- rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
- };
+ uart3_rts: uart3-rts {
+ rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- sd0 {
- sd0_clk: sd0-clk {
- rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0 {
+ sd0_clk: sd0-clk {
+ rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_cmd: sd0-cmd {
- rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_cmd: sd0-cmd {
+ rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_cd: sd0-cd {
- rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_cd: sd0-cd {
+ rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_wp: sd0-wp {
- rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_wp: sd0-wp {
+ rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_pwr: sd0-pwr {
- rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_pwr: sd0-pwr {
+ rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_bus1: sd0-bus-width1 {
- rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_bus1: sd0-bus-width1 {
+ rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd0_bus4: sd0-bus-width4 {
- rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd0_bus4: sd0-bus-width4 {
+ rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
};
+ };
- sd1 {
- sd1_clk: sd1-clk {
- rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1 {
+ sd1_clk: sd1-clk {
+ rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd1_cmd: sd1-cmd {
- rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1_cmd: sd1-cmd {
+ rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd1_cd: sd1-cd {
- rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1_cd: sd1-cd {
+ rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd1_wp: sd1-wp {
- rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1_wp: sd1-wp {
+ rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd1_bus1: sd1-bus-width1 {
- rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1_bus1: sd1-bus-width1 {
+ rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
+ };
- sd1_bus4: sd1-bus-width4 {
- rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
- <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
- };
+ sd1_bus4: sd1-bus-width4 {
+ rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
+ <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
};
};
};
};
+
+&global_timer {
+ interrupts = <GIC_PPI 11 0xf04>;
+};
+
+&local_timer {
+ interrupts = <GIC_PPI 13 0xf04>;
+};
+
+&i2c0 {
+ compatible = "rockchip,rk3188-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_xfer>;
+};
+
+&i2c1 {
+ compatible = "rockchip,rk3188-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_xfer>;
+};
+
+&i2c2 {
+ compatible = "rockchip,rk3188-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_xfer>;
+};
+
+&i2c3 {
+ compatible = "rockchip,rk3188-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_xfer>;
+};
+
+&i2c4 {
+ compatible = "rockchip,rk3188-i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_xfer>;
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_out>;
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm1_out>;
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm2_out>;
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_out>;
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_xfer>;
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_xfer>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_xfer>;
+};
+
+&wdt {
+ compatible = "rockchip,rk3188-wdt", "snps,dw-wdt";
+};
diff --git a/arch/arm/boot/dts/rk3288-evb-act8846.dts b/arch/arm/boot/dts/rk3288-evb-act8846.dts
new file mode 100644
index 000000000000..7d59ff4de408
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-evb-act8846.dts
@@ -0,0 +1,134 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "rk3288-evb.dtsi"
+
+/ {
+ compatible = "rockchip,rk3288-evb-act8846", "rockchip,rk3288";
+};
+
+&i2c0 {
+ hym8563@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+
+ interrupt-parent = <&gpio0>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&hym8563_int>;
+
+ #clock-cells = <0>;
+ clock-output-names = "xin32k";
+ };
+
+ act8846: act8846@5a {
+ compatible = "active-semi,act8846";
+ reg = <0x5a>;
+ status = "okay";
+
+ regulators {
+ vcc_ddr: REG1 {
+ regulator-name = "VCC_DDR";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ vcc_io: REG2 {
+ regulator-name = "VCC_IO";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_log: REG3 {
+ regulator-name = "VDD_LOG";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ vcc_20: REG4 {
+ regulator-name = "VCC_20";
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-always-on;
+ };
+
+ vccio_sd: REG5 {
+ regulator-name = "VCCIO_SD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd10_lcd: REG6 {
+ regulator-name = "VDD10_LCD";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ vcca_codec: REG7 {
+ regulator-name = "VCCA_CODEC";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vcca_tp: REG8 {
+ regulator-name = "VCCA_TP";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vccio_pmu: REG9 {
+ regulator-name = "VCCIO_PMU";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_10: REG10 {
+ regulator-name = "VDD_10";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+
+ vcc_18: REG11 {
+ regulator-name = "VCC_18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vcc18_lcd: REG12 {
+ regulator-name = "VCC18_LCD";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ hym8563 {
+ hym8563_int: hym8563-int {
+ rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts
new file mode 100644
index 000000000000..9a88b6c66396
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts
@@ -0,0 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "rk3288-evb.dtsi"
+
+/ {
+ compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288";
+};
diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
new file mode 100644
index 000000000000..4f572093c8b4
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -0,0 +1,96 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+ memory {
+ reg = <0x0 0x80000000>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ autorepeat;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwrbtn>;
+
+ button@0 {
+ gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+ linux,code = <116>;
+ label = "GPIO Key Power";
+ linux,input-type = <1>;
+ gpio-key,wakeup = <1>;
+ debounce-interval = <100>;
+ };
+ };
+
+ /* This turns on USB vbus for both host0 (ehci) and host1 (dwc2) */
+ vcc_host: vcc-host-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&host_vbus_drv>;
+ regulator-name = "vcc_host";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&pinctrl {
+ buttons {
+ pwrbtn: pwrbtn {
+ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ usb {
+ host_vbus_drv: host-vbus-drv {
+ rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
new file mode 100644
index 000000000000..5950b0a53224
--- /dev/null
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -0,0 +1,595 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include "skeleton.dtsi"
+
+/ {
+ compatible = "rockchip,rk3288";
+
+ interrupt-parent = <&gic>;
+
+ aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@500 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a12";
+ reg = <0x500>;
+ };
+ cpu@501 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a12";
+ reg = <0x501>;
+ };
+ cpu@502 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a12";
+ reg = <0x502>;
+ };
+ cpu@503 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a12";
+ reg = <0x503>;
+ };
+ };
+
+ xin24m: oscillator {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ #clock-cells = <0>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ clock-frequency = <24000000>;
+ };
+
+ i2c1: i2c@ff140000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff140000 0x1000>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_xfer>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@ff150000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff150000 0x1000>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c3_xfer>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@ff160000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff160000 0x1000>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_xfer>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@ff170000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff170000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5_xfer>;
+ status = "disabled";
+ };
+
+ uart0: serial@ff180000 {
+ compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+ reg = <0xff180000 0x100>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+ clock-names = "baudclk", "apb_pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
+ status = "disabled";
+ };
+
+ uart1: serial@ff190000 {
+ compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+ reg = <0xff190000 0x100>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+ clock-names = "baudclk", "apb_pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_xfer>;
+ status = "disabled";
+ };
+
+ uart2: serial@ff690000 {
+ compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+ reg = <0xff690000 0x100>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+ clock-names = "baudclk", "apb_pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_xfer>;
+ status = "disabled";
+ };
+
+ uart3: serial@ff1b0000 {
+ compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+ reg = <0xff1b0000 0x100>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+ clock-names = "baudclk", "apb_pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_xfer>;
+ status = "disabled";
+ };
+
+ uart4: serial@ff1c0000 {
+ compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+ reg = <0xff1c0000 0x100>;
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+ clock-names = "baudclk", "apb_pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_xfer>;
+ status = "disabled";
+ };
+
+ usb_host0_ehci: usb@ff500000 {
+ compatible = "generic-ehci";
+ reg = <0xff500000 0x100>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_USBHOST0>;
+ clock-names = "usbhost";
+ status = "disabled";
+ };
+
+ /* NOTE: ohci@ff520000 doesn't actually work on hardware */
+
+ usb_hsic: usb@ff5c0000 {
+ compatible = "generic-ehci";
+ reg = <0xff5c0000 0x100>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_HSIC>;
+ clock-names = "usbhost";
+ status = "disabled";
+ };
+
+ i2c0: i2c@ff650000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff650000 0x1000>;
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_xfer>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@ff660000 {
+ compatible = "rockchip,rk3288-i2c";
+ reg = <0xff660000 0x1000>;
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_xfer>;
+ status = "disabled";
+ };
+
+ pmu: power-management@ff730000 {
+ compatible = "rockchip,rk3288-pmu", "syscon";
+ reg = <0xff730000 0x100>;
+ };
+
+ sgrf: syscon@ff740000 {
+ compatible = "rockchip,rk3288-sgrf", "syscon";
+ reg = <0xff740000 0x1000>;
+ };
+
+ cru: clock-controller@ff760000 {
+ compatible = "rockchip,rk3288-cru";
+ reg = <0xff760000 0x1000>;
+ rockchip,grf = <&grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ grf: syscon@ff770000 {
+ compatible = "rockchip,rk3288-grf", "syscon";
+ reg = <0xff770000 0x1000>;
+ };
+
+ wdt: watchdog@ff800000 {
+ compatible = "rockchip,rk3288-wdt", "snps,dw-wdt";
+ reg = <0xff800000 0x100>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@ffc01000 {
+ compatible = "arm,gic-400";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+
+ reg = <0xffc01000 0x1000>,
+ <0xffc02000 0x1000>,
+ <0xffc04000 0x2000>,
+ <0xffc06000 0x2000>;
+ interrupts = <GIC_PPI 9 0xf04>;
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rk3288-pinctrl";
+ rockchip,grf = <&grf>;
+ rockchip,pmu = <&pmu>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ gpio0: gpio0@ff750000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff750000 0x100>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio1: gpio1@ff780000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff780000 0x100>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO1>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio2@ff790000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff790000 0x100>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO2>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio3@ff7a0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7a0000 0x100>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO3>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio4@ff7b0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7b0000 0x100>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO4>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio5: gpio5@ff7c0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7c0000 0x100>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO5>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio6: gpio6@ff7d0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7d0000 0x100>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO6>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio7: gpio7@ff7e0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7e0000 0x100>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO7>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio8: gpio8@ff7f0000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff7f0000 0x100>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO8>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pcfg_pull_up: pcfg-pull-up {
+ bias-pull-up;
+ };
+
+ pcfg_pull_down: pcfg-pull-down {
+ bias-pull-down;
+ };
+
+ pcfg_pull_none: pcfg-pull-none {
+ bias-disable;
+ };
+
+ i2c0 {
+ i2c0_xfer: i2c0-xfer {
+ rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>,
+ <0 16 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ i2c1 {
+ i2c1_xfer: i2c1-xfer {
+ rockchip,pins = <8 4 RK_FUNC_1 &pcfg_pull_none>,
+ <8 5 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ i2c2 {
+ i2c2_xfer: i2c2-xfer {
+ rockchip,pins = <6 9 RK_FUNC_1 &pcfg_pull_none>,
+ <6 10 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ i2c3 {
+ i2c3_xfer: i2c3-xfer {
+ rockchip,pins = <2 16 RK_FUNC_1 &pcfg_pull_none>,
+ <2 17 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ i2c4 {
+ i2c4_xfer: i2c4-xfer {
+ rockchip,pins = <7 17 RK_FUNC_1 &pcfg_pull_none>,
+ <7 18 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ i2c5 {
+ i2c5_xfer: i2c5-xfer {
+ rockchip,pins = <7 19 RK_FUNC_1 &pcfg_pull_none>,
+ <7 20 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc {
+ sdmmc_clk: sdmmc-clk {
+ rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ sdmmc_cmd: sdmmc-cmd {
+ rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up>;
+ };
+
+ sdmmc_cd: sdmcc-cd {
+ rockchip,pins = <6 22 RK_FUNC_1 &pcfg_pull_up>;
+ };
+
+ sdmmc_bus1: sdmmc-bus1 {
+ rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>;
+ };
+
+ sdmmc_bus4: sdmmc-bus4 {
+ rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>,
+ <6 17 RK_FUNC_1 &pcfg_pull_up>,
+ <6 18 RK_FUNC_1 &pcfg_pull_up>,
+ <6 19 RK_FUNC_1 &pcfg_pull_up>;
+ };
+ };
+
+ emmc {
+ emmc_clk: emmc-clk {
+ rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none>;
+ };
+
+ emmc_cmd: emmc-cmd {
+ rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_up>;
+ };
+
+ emmc_pwr: emmc-pwr {
+ rockchip,pins = <3 9 RK_FUNC_2 &pcfg_pull_up>;
+ };
+
+ emmc_bus1: emmc-bus1 {
+ rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>;
+ };
+
+ emmc_bus4: emmc-bus4 {
+ rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+ <3 1 RK_FUNC_2 &pcfg_pull_up>,
+ <3 2 RK_FUNC_2 &pcfg_pull_up>,
+ <3 3 RK_FUNC_2 &pcfg_pull_up>;
+ };
+
+ emmc_bus8: emmc-bus8 {
+ rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+ <3 1 RK_FUNC_2 &pcfg_pull_up>,
+ <3 2 RK_FUNC_2 &pcfg_pull_up>,
+ <3 3 RK_FUNC_2 &pcfg_pull_up>,
+ <3 4 RK_FUNC_2 &pcfg_pull_up>,
+ <3 5 RK_FUNC_2 &pcfg_pull_up>,
+ <3 6 RK_FUNC_2 &pcfg_pull_up>,
+ <3 7 RK_FUNC_2 &pcfg_pull_up>;
+ };
+ };
+
+ uart0 {
+ uart0_xfer: uart0-xfer {
+ rockchip,pins = <4 16 RK_FUNC_1 &pcfg_pull_up>,
+ <4 17 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart0_cts: uart0-cts {
+ rockchip,pins = <4 18 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart0_rts: uart0-rts {
+ rockchip,pins = <4 19 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ uart1 {
+ uart1_xfer: uart1-xfer {
+ rockchip,pins = <5 8 RK_FUNC_1 &pcfg_pull_up>,
+ <5 9 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart1_cts: uart1-cts {
+ rockchip,pins = <5 10 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart1_rts: uart1-rts {
+ rockchip,pins = <5 11 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ uart2 {
+ uart2_xfer: uart2-xfer {
+ rockchip,pins = <7 22 RK_FUNC_1 &pcfg_pull_up>,
+ <7 23 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ /* no rts / cts for uart2 */
+ };
+
+ uart3 {
+ uart3_xfer: uart3-xfer {
+ rockchip,pins = <7 7 RK_FUNC_1 &pcfg_pull_up>,
+ <7 8 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart3_cts: uart3-cts {
+ rockchip,pins = <7 9 RK_FUNC_1 &pcfg_pull_none>;
+ };
+
+ uart3_rts: uart3-rts {
+ rockchip,pins = <7 10 RK_FUNC_1 &pcfg_pull_none>;
+ };
+ };
+
+ uart4 {
+ uart4_xfer: uart4-xfer {
+ rockchip,pins = <5 12 3 &pcfg_pull_up>,
+ <5 13 3 &pcfg_pull_none>;
+ };
+
+ uart4_cts: uart4-cts {
+ rockchip,pins = <5 14 3 &pcfg_pull_none>;
+ };
+
+ uart4_rts: uart4-rts {
+ rockchip,pins = <5 15 3 &pcfg_pull_none>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index 2adf1cc9e85d..8caf85d83901 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -20,120 +20,248 @@
/ {
interrupt-parent = <&gic>;
- soc {
+ aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ };
+
+ xin24m: oscillator {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ clock-output-names = "xin24m";
+ };
+
+ L2: l2-cache-controller@10138000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x10138000 0x1000>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ scu@1013c000 {
+ compatible = "arm,cortex-a9-scu";
+ reg = <0x1013c000 0x100>;
+ };
+
+ global_timer: global-timer@1013c200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x1013c200 0x20>;
+ interrupts = <GIC_PPI 11 0x304>;
+ clocks = <&cru CORE_PERI>;
+ };
+
+ local_timer: local-timer@1013c600 {
+ compatible = "arm,cortex-a9-twd-timer";
+ reg = <0x1013c600 0x20>;
+ interrupts = <GIC_PPI 13 0x304>;
+ clocks = <&cru CORE_PERI>;
+ };
+
+ gic: interrupt-controller@1013d000 {
+ compatible = "arm,cortex-a9-gic";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x1013d000 0x1000>,
+ <0x1013c100 0x0100>;
+ };
+
+ uart0: serial@10124000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x10124000 0x400>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clock-names = "baudclk", "apb_pclk";
+ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+ status = "disabled";
+ };
+
+ uart1: serial@10126000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x10126000 0x400>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clock-names = "baudclk", "apb_pclk";
+ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+ status = "disabled";
+ };
+
+ mmc0: dwmmc@10214000 {
+ compatible = "rockchip,rk2928-dw-mshc";
+ reg = <0x10214000 0x1000>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
- #size-cells = <1>;
- compatible = "simple-bus";
- ranges;
-
- scu@1013c000 {
- compatible = "arm,cortex-a9-scu";
- reg = <0x1013c000 0x100>;
- };
-
- pmu: pmu@20004000 {
- compatible = "rockchip,rk3066-pmu", "syscon";
- reg = <0x20004000 0x100>;
- };
-
- grf: grf@20008000 {
- compatible = "syscon";
- reg = <0x20008000 0x200>;
- };
-
- gic: interrupt-controller@1013d000 {
- compatible = "arm,cortex-a9-gic";
- interrupt-controller;
- #interrupt-cells = <3>;
- reg = <0x1013d000 0x1000>,
- <0x1013c100 0x0100>;
- };
-
- L2: l2-cache-controller@10138000 {
- compatible = "arm,pl310-cache";
- reg = <0x10138000 0x1000>;
- cache-unified;
- cache-level = <2>;
- };
-
- global-timer@1013c200 {
- compatible = "arm,cortex-a9-global-timer";
- reg = <0x1013c200 0x20>;
- interrupts = <GIC_PPI 11 0x304>;
- clocks = <&dummy150m>;
- };
-
- local-timer@1013c600 {
- compatible = "arm,cortex-a9-twd-timer";
- reg = <0x1013c600 0x20>;
- interrupts = <GIC_PPI 13 0x304>;
- clocks = <&dummy150m>;
- };
-
- uart0: serial@10124000 {
- compatible = "snps,dw-apb-uart";
- reg = <0x10124000 0x400>;
- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <1>;
- clocks = <&clk_gates1 8>;
- status = "disabled";
- };
-
- uart1: serial@10126000 {
- compatible = "snps,dw-apb-uart";
- reg = <0x10126000 0x400>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <1>;
- clocks = <&clk_gates1 10>;
- status = "disabled";
- };
-
- uart2: serial@20064000 {
- compatible = "snps,dw-apb-uart";
- reg = <0x20064000 0x400>;
- interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <1>;
- clocks = <&clk_gates1 12>;
- status = "disabled";
- };
-
- uart3: serial@20068000 {
- compatible = "snps,dw-apb-uart";
- reg = <0x20068000 0x400>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
- reg-shift = <2>;
- reg-io-width = <1>;
- clocks = <&clk_gates1 14>;
- status = "disabled";
- };
-
- dwmmc@10214000 {
- compatible = "rockchip,rk2928-dw-mshc";
- reg = <0x10214000 0x1000>;
- interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- clocks = <&clk_gates5 10>, <&clk_gates2 11>;
- clock-names = "biu", "ciu";
-
- status = "disabled";
- };
-
- dwmmc@10218000 {
- compatible = "rockchip,rk2928-dw-mshc";
- reg = <0x10218000 0x1000>;
- interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- clocks = <&clk_gates5 11>, <&clk_gates2 13>;
- clock-names = "biu", "ciu";
-
- status = "disabled";
- };
+ #size-cells = <0>;
+
+ clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
+ clock-names = "biu", "ciu";
+
+ status = "disabled";
+ };
+
+ mmc1: dwmmc@10218000 {
+ compatible = "rockchip,rk2928-dw-mshc";
+ reg = <0x10218000 0x1000>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>;
+ clock-names = "biu", "ciu";
+
+ status = "disabled";
+ };
+
+ pmu: pmu@20004000 {
+ compatible = "rockchip,rk3066-pmu", "syscon";
+ reg = <0x20004000 0x100>;
+ };
+
+ grf: grf@20008000 {
+ compatible = "syscon";
+ reg = <0x20008000 0x200>;
+ };
+
+ i2c0: i2c@2002d000 {
+ compatible = "rockchip,rk3066-i2c";
+ reg = <0x2002d000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+ rockchip,bus-index = <0>;
+
+ clock-names = "i2c";
+ clocks = <&cru PCLK_I2C0>;
+
+ status = "disabled";
+ };
+
+ i2c1: i2c@2002f000 {
+ compatible = "rockchip,rk3066-i2c";
+ reg = <0x2002f000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+
+ clocks = <&cru PCLK_I2C1>;
+ clock-names = "i2c";
+
+ status = "disabled";
+ };
+
+ pwm0: pwm@20030000 {
+ compatible = "rockchip,rk2928-pwm";
+ reg = <0x20030000 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cru PCLK_PWM01>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@20030010 {
+ compatible = "rockchip,rk2928-pwm";
+ reg = <0x20030010 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cru PCLK_PWM01>;
+ status = "disabled";
+ };
+
+ wdt: watchdog@2004c000 {
+ compatible = "snps,dw-wdt";
+ reg = <0x2004c000 0x100>;
+ clocks = <&cru PCLK_WDT>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@20050020 {
+ compatible = "rockchip,rk2928-pwm";
+ reg = <0x20050020 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cru PCLK_PWM23>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@20050030 {
+ compatible = "rockchip,rk2928-pwm";
+ reg = <0x20050030 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cru PCLK_PWM23>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@20056000 {
+ compatible = "rockchip,rk3066-i2c";
+ reg = <0x20056000 0x1000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+
+ clocks = <&cru PCLK_I2C2>;
+ clock-names = "i2c";
+
+ status = "disabled";
+ };
+
+ i2c3: i2c@2005a000 {
+ compatible = "rockchip,rk3066-i2c";
+ reg = <0x2005a000 0x1000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+
+ clocks = <&cru PCLK_I2C3>;
+ clock-names = "i2c";
+
+ status = "disabled";
+ };
+
+ i2c4: i2c@2005e000 {
+ compatible = "rockchip,rk3066-i2c";
+ reg = <0x2005e000 0x1000>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rockchip,grf = <&grf>;
+
+ clocks = <&cru PCLK_I2C4>;
+ clock-names = "i2c";
+
+ status = "disabled";
+ };
+
+ uart2: serial@20064000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x20064000 0x400>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clock-names = "baudclk", "apb_pclk";
+ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+ status = "disabled";
+ };
+
+ uart3: serial@20068000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x20068000 0x400>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clock-names = "baudclk", "apb_pclk";
+ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+ status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi
index 955e4a4f8c31..30b8f7e47454 100644
--- a/arch/arm/boot/dts/s3c2416.dtsi
+++ b/arch/arm/boot/dts/s3c2416.dtsi
@@ -16,6 +16,10 @@
model = "Samsung S3C2416 SoC";
compatible = "samsung,s3c2416";
+ aliases {
+ serial3 = &uart3;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -68,7 +72,7 @@
<&clocks SCLK_UART>;
};
- serial@5000C000 {
+ uart3: serial@5000C000 {
compatible = "samsung,s3c2440-uart";
reg = <0x5000C000 0x4000>;
interrupts = <1 18 24 4>, <1 18 25 4>;
diff --git a/arch/arm/boot/dts/s3c24xx.dtsi b/arch/arm/boot/dts/s3c24xx.dtsi
index 2d1d7dc9418a..5ed43b857cc4 100644
--- a/arch/arm/boot/dts/s3c24xx.dtsi
+++ b/arch/arm/boot/dts/s3c24xx.dtsi
@@ -16,6 +16,9 @@
aliases {
pinctrl0 = &pinctrl_0;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
};
intc:interrupt-controller@4a000000 {
@@ -46,21 +49,21 @@
#pwm-cells = <4>;
};
- serial@50000000 {
+ uart0: serial@50000000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50000000 0x4000>;
interrupts = <1 28 0 4>, <1 28 1 4>;
status = "disabled";
};
- serial@50004000 {
+ uart1: serial@50004000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50004000 0x4000>;
interrupts = <1 23 3 4>, <1 23 4 4>;
status = "disabled";
};
- serial@50008000 {
+ uart2: serial@50008000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50008000 0x4000>;
interrupts = <1 15 6 4>, <1 15 7 4>;
diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi
index 4e3be4d3493d..ff5bdaac987a 100644
--- a/arch/arm/boot/dts/s3c64xx.dtsi
+++ b/arch/arm/boot/dts/s3c64xx.dtsi
@@ -23,6 +23,10 @@
aliases {
i2c0 = &i2c0;
pinctrl0 = &pinctrl0;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
};
cpus {
diff --git a/arch/arm/boot/dts/s5pv210-aquila.dts b/arch/arm/boot/dts/s5pv210-aquila.dts
new file mode 100644
index 000000000000..aa31b84a707a
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-aquila.dts
@@ -0,0 +1,392 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Samsung Aquila board.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+ model = "Samsung Aquila based on S5PC110";
+ compatible = "samsung,aquila", "samsung,s5pv210";
+
+ aliases {
+ i2c3 = &i2c_pmic;
+ };
+
+ chosen {
+ bootargs = "console=ttySAC2,115200n8 root=/dev/mmcblk1p5 rw rootwait ignore_loglevel earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x30000000 0x05000000
+ 0x40000000 0x18000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vtf_reg: fixed-regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "V_TF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpios = <&mp05 4 0>;
+ enable-active-high;
+ };
+
+ pda_reg: fixed-regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_1.8V_PDA";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ reg = <1>;
+ };
+
+ bat_reg: fixed-regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_BAT";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ reg = <2>;
+ };
+ };
+
+ i2c_pmic: i2c-pmic {
+ compatible = "i2c-gpio";
+ gpios = <&gpj4 0 0>, /* sda */
+ <&gpj4 3 0>; /* scl */
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@66 {
+ compatible = "national,lp3974";
+ reg = <0x66>;
+
+ max8998,pmic-buck1-default-dvs-idx = <0>;
+ max8998,pmic-buck1-dvs-gpios = <&gph0 3 0>,
+ <&gph0 4 0>;
+ max8998,pmic-buck1-dvs-voltage = <1200000>, <1200000>,
+ <1200000>, <1200000>;
+
+ max8998,pmic-buck2-default-dvs-idx = <0>;
+ max8998,pmic-buck2-dvs-gpio = <&gph0 5 0>;
+ max8998,pmic-buck2-dvs-voltage = <1200000>, <1200000>;
+
+ regulators {
+ ldo2_reg: LDO2 {
+ regulator-name = "VALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VUSB+MIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VADC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "VTF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VCC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VCC_3.0V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "VUSB+VDAC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "VCC+VCAM_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "VPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "CAM_IO_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "CAM_ISP_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "CAM_A_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "CAM_CIF_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "CAM_AF_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "CAM_8M_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VARM_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "VINT_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "VCC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "CAM_CORE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ vichg_reg: ENVICHG {
+ regulator-name = "VICHG";
+ };
+
+ safeout1_reg: ESAFEOUT1 {
+ regulator-name = "SAFEOUT1";
+ regulator-always-on;
+ };
+
+ safeout2_reg: ESAFEOUT2 {
+ regulator-name = "SAFEOUT2";
+ regulator-boot-on;
+ };
+ };
+ };
+
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power-key {
+ gpios = <&gph2 6 1>;
+ linux,code = <KEY_POWER>;
+ label = "power";
+ debounce-interval = <1>;
+ gpio-key,wakeup;
+ };
+ };
+};
+
+&xusbxti {
+ clock-frequency = <24000000>;
+};
+
+&keypad {
+ linux,input-no-autorepeat;
+ linux,input-wakeup;
+ samsung,keypad-num-rows = <3>;
+ samsung,keypad-num-columns = <3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+ <&keypad_col0>, <&keypad_col1>, <&keypad_col2>;
+ status = "okay";
+
+ key_1 {
+ keypad,row = <0>;
+ keypad,column = <1>;
+ linux,code = <KEY_CONNECT>;
+ };
+
+ key_2 {
+ keypad,row = <0>;
+ keypad,column = <2>;
+ linux,code = <KEY_BACK>;
+ };
+
+ key_3 {
+ keypad,row = <1>;
+ keypad,column = <1>;
+ linux,code = <KEY_CAMERA_FOCUS>;
+ };
+
+ key_4 {
+ keypad,row = <1>;
+ keypad,column = <2>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ key_5 {
+ keypad,row = <2>;
+ keypad,column = <1>;
+ linux,code = <KEY_CAMERA>;
+ };
+
+ key_6 {
+ keypad,row = <2>;
+ keypad,column = <2>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&sdhci0 {
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+ vmmc-supply = <&ldo5_reg>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+ pinctrl-names = "default";
+};
+
+&sdhci2 {
+ bus-width = <4>;
+ cd-gpios = <&gph3 4 1>;
+ vmmc-supply = <&vtf_reg>;
+ cd-inverted;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &t_flash_detect>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&onenand {
+ status = "okay";
+};
+
+&hsotg {
+ vusb_a-supply = <&ldo3_reg>;
+ vusb_d-supply = <&ldo8_reg>;
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
+
+&fimd {
+ pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing {
+ clock-frequency = <0>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <16>;
+ hback-porch = <16>;
+ hsync-len = <2>;
+ vback-porch = <3>;
+ vfront-porch = <28>;
+ vsync-len = <1>;
+ };
+ };
+};
+
+&pinctrl0 {
+ t_flash_detect: t-flash-detect {
+ samsung,pins = "gph3-4";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/s5pv210-goni.dts b/arch/arm/boot/dts/s5pv210-goni.dts
new file mode 100644
index 000000000000..6387c77a6f7b
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-goni.dts
@@ -0,0 +1,449 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Samsung Goni board.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+ model = "Samsung Goni based on S5PC110";
+ compatible = "samsung,goni", "samsung,s5pv210";
+
+ aliases {
+ i2c3 = &i2c_pmic;
+ };
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p5 rw rootwait ignore_loglevel earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x30000000 0x05000000
+ 0x40000000 0x10000000
+ 0x50000000 0x08000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vtf_reg: fixed-regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_TF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ reg = <0>;
+ gpios = <&mp05 4 0>;
+ enable-active-high;
+ };
+
+ pda_reg: fixed-regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_1.8V_PDA";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ reg = <1>;
+ };
+
+ bat_reg: fixed-regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "V_BAT";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ reg = <2>;
+ };
+
+ tsp_reg: fixed-regulator@3 {
+ compatible = "regulator-fixed";
+ regulator-name = "TSP_VDD";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ reg = <3>;
+ gpios = <&gpj1 3 0>;
+ enable-active-high;
+ };
+ };
+
+ i2c_pmic: i2c-pmic {
+ compatible = "i2c-gpio";
+ gpios = <&gpj4 0 0>, /* sda */
+ <&gpj4 3 0>; /* scl */
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@66 {
+ compatible = "national,lp3974";
+ reg = <0x66>;
+
+ max8998,pmic-buck1-default-dvs-idx = <0>;
+ max8998,pmic-buck1-dvs-gpios = <&gph0 3 0>,
+ <&gph0 4 0>;
+ max8998,pmic-buck1-dvs-voltage = <1200000>, <1200000>,
+ <1200000>, <1200000>;
+
+ max8998,pmic-buck2-default-dvs-idx = <0>;
+ max8998,pmic-buck2-dvs-gpio = <&gph0 5 0>;
+ max8998,pmic-buck2-dvs-voltage = <1200000>, <1200000>;
+
+ regulators {
+ ldo2_reg: LDO2 {
+ regulator-name = "VALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VUSB+MIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VADC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "VTF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VCC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VLCD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "VUSB+VDAC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "VCC+VCAM_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "VPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "CAM_IO_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "CAM_ISP_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "CAM_A_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "CAM_CIF_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "CAM_AF_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "CAM_8M_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VARM_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "VINT_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "VCC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "CAM_CORE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power-key {
+ gpios = <&gph2 6 1>;
+ linux,code = <KEY_POWER>;
+ label = "power";
+ debounce-interval = <1>;
+ gpio-key,wakeup;
+ };
+ };
+};
+
+&xusbxti {
+ clock-frequency = <24000000>;
+};
+
+&keypad {
+ linux,input-no-autorepeat;
+ linux,input-wakeup;
+ samsung,keypad-num-rows = <3>;
+ samsung,keypad-num-columns = <3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+ <&keypad_col0>, <&keypad_col1>, <&keypad_col2>;
+ status = "okay";
+
+ key_1 {
+ keypad,row = <0>;
+ keypad,column = <1>;
+ linux,code = <KEY_CONNECT>;
+ };
+
+ key_2 {
+ keypad,row = <0>;
+ keypad,column = <2>;
+ linux,code = <KEY_BACK>;
+ };
+
+ key_3 {
+ keypad,row = <1>;
+ keypad,column = <1>;
+ linux,code = <KEY_CAMERA_FOCUS>;
+ };
+
+ key_4 {
+ keypad,row = <1>;
+ keypad,column = <2>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ key_5 {
+ keypad,row = <2>;
+ keypad,column = <1>;
+ linux,code = <KEY_CAMERA>;
+ };
+
+ key_6 {
+ keypad,row = <2>;
+ keypad,column = <2>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&sdhci0 {
+ bus-width = <4>;
+ non-removable;
+ vmmc-supply = <&ldo5_reg>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci2 {
+ bus-width = <4>;
+ cd-gpios = <&gph3 4 1>;
+ vmmc-supply = <&vtf_reg>;
+ cd-inverted;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&hsotg {
+ vusb_a-supply = <&ldo3_reg>;
+ vusb_d-supply = <&ldo8_reg>;
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
+
+&i2c2 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <400000>;
+ samsung,i2c-slave-addr = <0x10>;
+ status = "okay";
+
+ tsp@4a {
+ compatible = "atmel,maxtouch";
+ reg = <0x4a>;
+ interrupt-parent = <&gpj0>;
+ interrupts = <5 2>;
+
+ atmel,x-line = <17>;
+ atmel,y-line = <11>;
+ atmel,x-size = <800>;
+ atmel,y-size = <480>;
+ atmel,burst-length = <0x21>;
+ atmel,threshold = <0x28>;
+ atmel,orientation = <1>;
+
+ vdd-supply = <&tsp_reg>;
+ };
+};
+
+&i2c0 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <100000>;
+ samsung,i2c-slave-addr = <0x10>;
+ status = "okay";
+
+ noon010pc30: sensor@30 {
+ compatible = "siliconfile,noon010pc30";
+ reg = <0x30>;
+ vddio-supply = <&ldo11_reg>;
+ vdda-supply = <&ldo13_reg>;
+ vdd_core-supply = <&ldo14_reg>;
+
+ clock-frequency = <16000000>;
+ clocks = <&clock_cam 0>;
+ clock-names = "mclk";
+ nreset-gpios = <&gpb 2 0>;
+ nstby-gpios = <&gpb 0 0>;
+
+ port {
+ noon010pc30_ep: endpoint {
+ remote-endpoint = <&fimc0_ep>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ vsync-active = <1>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+};
+
+&camera {
+ pinctrl-0 = <&cam_port_a_io &cam_port_a_clk_active>;
+ pinctrl-1 = <&cam_port_a_io &cam_port_a_clk_idle>;
+ pinctrl-names = "default", "idle";
+
+ parallel-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* camera A input */
+ port@1 {
+ reg = <1>;
+ fimc0_ep: endpoint {
+ remote-endpoint = <&noon010pc30_ep>;
+ bus-width = <8>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pclk-sample = <0>;
+ };
+ };
+ };
+};
+
+&fimd {
+ pinctrl-0 = <&lcd_clk &lcd_data24>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing {
+ /* 480x800@55Hz */
+ clock-frequency = <23439570>;
+ hactive = <480>;
+ hfront-porch = <16>;
+ hback-porch = <16>;
+ hsync-len = <2>;
+ vactive = <800>;
+ vback-porch = <2>;
+ vfront-porch = <28>;
+ vsync-len = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+};
+
+&onenand {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/s5pv210-pinctrl.dtsi b/arch/arm/boot/dts/s5pv210-pinctrl.dtsi
new file mode 100644
index 000000000000..8c714088e3c6
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-pinctrl.dtsi
@@ -0,0 +1,839 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S5PV210 SoC. As device tree coverage for S5PV210 increases, additional
+ * nodes can be added to this 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.
+ */
+
+&pinctrl0 {
+ gpa0: gpa0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpa1: gpa1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc0: gpc0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc1: gpc1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd0: gpd0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd1: gpd1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe0: gpe0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe1: gpe1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf0: gpf0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf1: gpf1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf2: gpf2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpf3: gpf3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg0: gpg0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg1: gpg1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg2: gpg2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg3: gpg3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj0: gpj0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj1: gpj1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj2: gpj2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj3: gpj3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpj4: gpj4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpgi: gpgi {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp01: mp01 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp02: mp02 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp03: mp03 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp04: mp04 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp05: mp05 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp06: mp06 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ mp07: mp07 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gph0: gph0 {
+ gpio-controller;
+ interrupt-controller;
+ interrupt-parent = <&vic0>;
+ interrupts = <0>, <1>, <2>, <3>,
+ <4>, <5>, <6>, <7>;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gph1: gph1 {
+ gpio-controller;
+ interrupt-controller;
+ interrupt-parent = <&vic0>;
+ interrupts = <8>, <9>, <10>, <11>,
+ <12>, <13>, <14>, <15>;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gph2: gph2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ gph3: gph3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ };
+
+ uart0_data: uart0-data {
+ samsung,pins = "gpa0-0", "gpa0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart0_fctl: uart0-fctl {
+ samsung,pins = "gpa0-2", "gpa0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_data: uart1-data {
+ samsung,pins = "gpa0-4", "gpa0-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart1_fctl: uart1-fctl {
+ samsung,pins = "gpa0-6", "gpa0-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart2_data: uart2-data {
+ samsung,pins = "gpa1-0", "gpa1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart2_fctl: uart2-fctl {
+ samsung,pins = "gpa1-2", "gpa1-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart3_data: uart3-data {
+ samsung,pins = "gpa1-2", "gpa1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ uart_audio: uart-audio {
+ samsung,pins = "gpa1-2", "gpa1-3";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi0_bus: spi0-bus {
+ samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi1_bus: spi1-bus {
+ samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s0_bus: i2s0-bus {
+ samsung,pins = "gpi-0", "gpi-1", "gpi-2", "gpi-3",
+ "gpi-4", "gpi-5", "gpi-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s1_bus: i2s1-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s2_bus: i2s2-bus {
+ samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+ "gpc1-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pcm1_bus: pcm1-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ ac97_bus: ac97-bus {
+ samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+ "gpc0-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2s2_bus: i2s2-bus {
+ samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+ "gpc1-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pcm2_bus: pcm2-bus {
+ samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+ "gpc1-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ spdif_bus: spdif-bus {
+ samsung,pins = "gpc1-0", "gpc1-1";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ spi2_bus: spi2-bus {
+ samsung,pins = "gpc1-1", "gpc1-2", "gpc1-3", "gpc1-4";
+ samsung,pin-function = <5>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c0_bus: i2c0-bus {
+ samsung,pins = "gpd1-0", "gpd1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c1_bus: i2c1-bus {
+ samsung,pins = "gpd1-2", "gpd1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ i2c2_bus: i2c2-bus {
+ samsung,pins = "gpd1-4", "gpd1-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm0_out: pwm0-out {
+ samsung,pins = "gpd0-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm1_out: pwm1-out {
+ samsung,pins = "gpd0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm2_out: pwm2-out {
+ samsung,pins = "gpd0-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ pwm3_out: pwm3-out {
+ samsung,pins = "gpd0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row0: keypad-row-0 {
+ samsung,pins = "gph3-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row1: keypad-row-1 {
+ samsung,pins = "gph3-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row2: keypad-row-2 {
+ samsung,pins = "gph3-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row3: keypad-row-3 {
+ samsung,pins = "gph3-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row4: keypad-row-4 {
+ samsung,pins = "gph3-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row5: keypad-row-5 {
+ samsung,pins = "gph3-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row6: keypad-row-6 {
+ samsung,pins = "gph3-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_row7: keypad-row-7 {
+ samsung,pins = "gph3-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col0: keypad-col-0 {
+ samsung,pins = "gph2-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col1: keypad-col-1 {
+ samsung,pins = "gph2-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col2: keypad-col-2 {
+ samsung,pins = "gph2-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col3: keypad-col-3 {
+ samsung,pins = "gph2-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col4: keypad-col-4 {
+ samsung,pins = "gph2-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col5: keypad-col-5 {
+ samsung,pins = "gph2-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col6: keypad-col-6 {
+ samsung,pins = "gph2-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ keypad_col7: keypad-col-7 {
+ samsung,pins = "gph2-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ sd0_clk: sd0-clk {
+ samsung,pins = "gpg0-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_cmd: sd0-cmd {
+ samsung,pins = "gpg0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_cd: sd0-cd {
+ samsung,pins = "gpg0-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus1: sd0-bus-width1 {
+ samsung,pins = "gpg0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus4: sd0-bus-width4 {
+ samsung,pins = "gpg0-3", "gpg0-4", "gpg0-5", "gpg0-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd0_bus8: sd0-bus-width8 {
+ samsung,pins = "gpg1-3", "gpg1-4", "gpg1-5", "gpg1-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_clk: sd1-clk {
+ samsung,pins = "gpg1-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_cmd: sd1-cmd {
+ samsung,pins = "gpg1-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_cd: sd1-cd {
+ samsung,pins = "gpg1-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_bus1: sd1-bus-width1 {
+ samsung,pins = "gpg1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd1_bus4: sd1-bus-width4 {
+ samsung,pins = "gpg1-3", "gpg1-4", "gpg1-5", "gpg1-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_clk: sd2-clk {
+ samsung,pins = "gpg2-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_cmd: sd2-cmd {
+ samsung,pins = "gpg2-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_cd: sd2-cd {
+ samsung,pins = "gpg2-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus1: sd2-bus-width1 {
+ samsung,pins = "gpg2-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus4: sd2-bus-width4 {
+ samsung,pins = "gpg2-3", "gpg2-4", "gpg2-5", "gpg2-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd2_bus8: sd2-bus-width8 {
+ samsung,pins = "gpg3-3", "gpg3-4", "gpg3-5", "gpg3-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_clk: sd3-clk {
+ samsung,pins = "gpg3-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_cmd: sd3-cmd {
+ samsung,pins = "gpg3-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_cd: sd3-cd {
+ samsung,pins = "gpg3-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_bus1: sd3-bus-width1 {
+ samsung,pins = "gpg3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ sd3_bus4: sd3-bus-width4 {
+ samsung,pins = "gpg3-3", "gpg3-4", "gpg3-5", "gpg3-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <2>;
+ samsung,pin-drv = <3>;
+ };
+
+ eint0: ext-int0 {
+ samsung,pins = "gph0-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint8: ext-int8 {
+ samsung,pins = "gph1-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint15: ext-int15 {
+ samsung,pins = "gph1-7";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint16: ext-int16 {
+ samsung,pins = "gph2-0";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ eint31: ext-int31 {
+ samsung,pins = "gph3-7";
+ samsung,pin-function = <0xf>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_a_io: cam-port-a-io {
+ samsung,pins = "gpe0-0", "gpe0-1", "gpe0-2", "gpe0-3",
+ "gpe0-4", "gpe0-5", "gpe0-6", "gpe0-7",
+ "gpe1-0", "gpe1-1", "gpe1-2", "gpe1-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_a_clk_active: cam-port-a-clk-active {
+ samsung,pins = "gpe1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ cam_port_a_clk_idle: cam-port-a-clk-idle {
+ samsung,pins = "gpe1-3";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_b_io: cam-port-b-io {
+ samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
+ "gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
+ "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_b_clk_active: cam-port-b-clk-active {
+ samsung,pins = "gpj1-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ cam_port_b_clk_idle: cam-port-b-clk-idle {
+ samsung,pins = "gpj1-3";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <1>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_ctrl: lcd-ctrl {
+ samsung,pins = "gpd0-0", "gpd0-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_sync: lcd-sync {
+ samsung,pins = "gpf0-0", "gpf0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_clk: lcd-clk {
+ samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd_data24: lcd-data-width24 {
+ samsung,pins = "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7",
+ "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3",
+ "gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7",
+ "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+ "gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7",
+ "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/s5pv210-smdkc110.dts b/arch/arm/boot/dts/s5pv210-smdkc110.dts
new file mode 100644
index 000000000000..1eedab7ffe94
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-smdkc110.dts
@@ -0,0 +1,78 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for YIC System SMDC110 board.
+ *
+ * NOTE: This file is completely based on original board file for mach-smdkc110
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+ model = "YIC System SMDKC110 based on S5PC110";
+ compatible = "yic,smdkc110", "samsung,s5pv210";
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x20000000 0x20000000>;
+ };
+};
+
+&xusbxti {
+ clock-frequency = <24000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&rtc {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ audio-codec@1b {
+ compatible = "wlf,wm8580";
+ reg = <0x1b>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c08";
+ reg = <0x50>;
+ };
+};
+
+&i2s0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/s5pv210-smdkv210.dts b/arch/arm/boot/dts/s5pv210-smdkv210.dts
new file mode 100644
index 000000000000..cb8521899ec8
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-smdkv210.dts
@@ -0,0 +1,238 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for YIC System SMDV210 board.
+ *
+ * NOTE: This file is completely based on original board file for mach-smdkv210
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+ model = "YIC System SMDKV210 based on S5PV210";
+ compatible = "yic,smdkv210", "samsung,s5pv210";
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x20000000 0x40000000>;
+ };
+
+ ethernet@18000000 {
+ compatible = "davicom,dm9000";
+ reg = <0xA8000000 0x2 0xA8000002 0x2>;
+ interrupt-parent = <&gph1>;
+ interrupts = <1 4>;
+ local-mac-address = [00 00 de ad be ef];
+ davicom,no-eeprom;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 3 5000000 0>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_out>;
+ };
+};
+
+&xusbxti {
+ clock-frequency = <24000000>;
+};
+
+&keypad {
+ linux,input-no-autorepeat;
+ linux,input-wakeup;
+ samsung,keypad-num-rows = <8>;
+ samsung,keypad-num-columns = <8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&keypad_row0>, <&keypad_row1>, <&keypad_row2>,
+ <&keypad_row3>, <&keypad_row4>, <&keypad_row5>,
+ <&keypad_row6>, <&keypad_row7>,
+ <&keypad_col0>, <&keypad_col1>, <&keypad_col2>,
+ <&keypad_col3>, <&keypad_col4>, <&keypad_col5>,
+ <&keypad_col6>, <&keypad_col7>;
+ status = "okay";
+
+ key_1 {
+ keypad,row = <0>;
+ keypad,column = <3>;
+ linux,code = <KEY_1>;
+ };
+
+ key_2 {
+ keypad,row = <0>;
+ keypad,column = <4>;
+ linux,code = <KEY_2>;
+ };
+
+ key_3 {
+ keypad,row = <0>;
+ keypad,column = <5>;
+ linux,code = <KEY_3>;
+ };
+
+ key_4 {
+ keypad,row = <0>;
+ keypad,column = <6>;
+ linux,code = <KEY_4>;
+ };
+
+ key_5 {
+ keypad,row = <0
+ >;
+ keypad,column = <7>;
+ linux,code = <KEY_5>;
+ };
+
+ key_6 {
+ keypad,row = <1>;
+ keypad,column = <3>;
+ linux,code = <KEY_A>;
+ };
+ key_7 {
+ keypad,row = <1>;
+ keypad,column = <4>;
+ linux,code = <KEY_B>;
+ };
+
+ key_8 {
+ keypad,row = <1>;
+ keypad,column = <5>;
+ linux,code = <KEY_C>;
+ };
+
+ key_9 {
+ keypad,row = <1>;
+ keypad,column = <6>;
+ linux,code = <KEY_D>;
+ };
+
+ key_10 {
+ keypad,row = <1>;
+ keypad,column = <7>;
+ linux,code = <KEY_E>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&rtc {
+ status = "okay";
+};
+
+&sdhci0 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci1 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus1 &sd1_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci2 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci3 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_cd &sd3_bus1 &sd3_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&hsotg {
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
+
+&fimd {
+ pinctrl-0 = <&lcd_clk &lcd_data24>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing0>;
+
+ timing0: timing@0 {
+ /* 800x480@60Hz */
+ clock-frequency = <24373920>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <8>;
+ hback-porch = <13>;
+ hsync-len = <3>;
+ vback-porch = <7>;
+ vfront-porch = <5>;
+ vsync-len = <1>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+};
+
+&pwm {
+ samsung,pwm-outputs = <3>;
+};
+
+&i2c0 {
+ status = "okay";
+
+ audio-codec@1b {
+ compatible = "wlf,wm8580";
+ reg = <0x1b>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c08";
+ reg = <0x50>;
+ };
+};
+
+&i2s0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/s5pv210-torbreck.dts b/arch/arm/boot/dts/s5pv210-torbreck.dts
new file mode 100644
index 000000000000..622599fd2cfa
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210-torbreck.dts
@@ -0,0 +1,92 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Board device tree source for Torbreck board.
+ *
+ * NOTE: This file is completely based on original board file for mach-torbreck
+ * available in Linux 3.15 and intends to provide equivalent level of hardware
+ * support. Due to lack of hardware, _no_ testing has been performed.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "s5pv210.dtsi"
+
+/ {
+ model = "aESOP Torbreck based on S5PV210";
+ compatible = "aesop,torbreck", "samsung,s5pv210";
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x20000000 0x20000000>;
+ };
+};
+
+&xusbxti {
+ clock-frequency = <24000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&rtc {
+ status = "okay";
+};
+
+&sdhci0 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus1 &sd0_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci1 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus1 &sd1_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci2 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&sdhci3 {
+ bus-width = <4>;
+ pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_cd &sd3_bus1 &sd3_bus4>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&i2s0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/s5pv210.dtsi b/arch/arm/boot/dts/s5pv210.dtsi
new file mode 100644
index 000000000000..8344a0ee2b86
--- /dev/null
+++ b/arch/arm/boot/dts/s5pv210.dtsi
@@ -0,0 +1,633 @@
+/*
+ * Samsung's S5PV210 SoC device tree source
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics, Co. Ltd.
+ *
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S5PV210 SoC. As device tree coverage for S5PV210 increases, additional
+ * nodes can be added to this 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.
+*/
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/s5pv210.h>
+#include <dt-bindings/clock/s5pv210-audss.h>
+
+/ {
+ aliases {
+ csis0 = &csis0;
+ fimc0 = &fimc0;
+ fimc1 = &fimc1;
+ fimc2 = &fimc2;
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2s0 = &i2s0;
+ i2s1 = &i2s1;
+ i2s2 = &i2s2;
+ pinctrl0 = &pinctrl0;
+ spi0 = &spi0;
+ spi1 = &spi1;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a8";
+ reg = <0>;
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ external-clocks {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ xxti: oscillator@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "xxti";
+ #clock-cells = <0>;
+ };
+
+ xusbxti: oscillator@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ clock-frequency = <0>;
+ clock-output-names = "xusbxti";
+ #clock-cells = <0>;
+ };
+ };
+
+ onenand: onenand@b0000000 {
+ compatible = "samsung,s5pv210-onenand";
+ reg = <0xb0600000 0x2000>,
+ <0xb0000000 0x20000>,
+ <0xb0040000 0x20000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <31>;
+ clocks = <&clocks CLK_NANDXL>, <&clocks DOUT_FLASH>;
+ clock-names = "bus", "onenand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+ };
+
+ chipid@e0000000 {
+ compatible = "samsung,s5pv210-chipid";
+ reg = <0xe0000000 0x1000>;
+ };
+
+ clocks: clock-controller@e0100000 {
+ compatible = "samsung,s5pv210-clock", "simple-bus";
+ reg = <0xe0100000 0x10000>;
+ clock-names = "xxti", "xusbxti";
+ clocks = <&xxti>, <&xusbxti>;
+ #clock-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu_syscon: syscon@e0108000 {
+ compatible = "samsung-s5pv210-pmu", "syscon";
+ reg = <0xe0108000 0x8000>;
+ };
+ };
+
+ pinctrl0: pinctrl@e0200000 {
+ compatible = "samsung,s5pv210-pinctrl";
+ reg = <0xe0200000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <30>;
+
+ wakeup-interrupt-controller {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ interrupts = <16>;
+ interrupt-parent = <&vic0>;
+ };
+ };
+
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ pdma0: dma@e0900000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xe0900000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <19>;
+ clocks = <&clocks CLK_PDMA0>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ #dma-channels = <8>;
+ #dma-requests = <32>;
+ };
+
+ pdma1: dma@e0a00000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xe0a00000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <20>;
+ clocks = <&clocks CLK_PDMA1>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ #dma-channels = <8>;
+ #dma-requests = <32>;
+ };
+ };
+
+ spi0: spi@e1300000 {
+ compatible = "samsung,s5pv210-spi";
+ reg = <0xe1300000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <15>;
+ dmas = <&pdma0 7>, <&pdma0 6>;
+ dma-names = "tx", "rx";
+ clocks = <&clocks SCLK_SPI0>, <&clocks CLK_SPI0>;
+ clock-names = "spi", "spi_busclk0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_bus>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@e1400000 {
+ compatible = "samsung,s5pv210-spi";
+ reg = <0xe1400000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <16>;
+ dmas = <&pdma1 7>, <&pdma1 6>;
+ dma-names = "tx", "rx";
+ clocks = <&clocks SCLK_SPI1>, <&clocks CLK_SPI1>;
+ clock-names = "spi", "spi_busclk0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_bus>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ keypad: keypad@e1600000 {
+ compatible = "samsung,s5pv210-keypad";
+ reg = <0xe1600000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <25>;
+ clocks = <&clocks CLK_KEYIF>;
+ clock-names = "keypad";
+ status = "disabled";
+ };
+
+ i2c0: i2c@e1800000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0xe1800000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <14>;
+ clocks = <&clocks CLK_I2C0>;
+ clock-names = "i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_bus>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@e1a00000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0xe1a00000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <19>;
+ clocks = <&clocks CLK_I2C2>;
+ clock-names = "i2c";
+ pinctrl-0 = <&i2c2_bus>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ audio-subsystem {
+ compatible = "samsung,s5pv210-audss", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clk_audss: clock-controller@eee10000 {
+ compatible = "samsung,s5pv210-audss-clock";
+ reg = <0xeee10000 0x1000>;
+ clock-names = "hclk", "xxti",
+ "fout_epll",
+ "sclk_audio0";
+ clocks = <&clocks DOUT_HCLKP>, <&xxti>,
+ <&clocks FOUT_EPLL>,
+ <&clocks SCLK_AUDIO0>;
+ #clock-cells = <1>;
+ };
+
+ i2s0: i2s@eee30000 {
+ compatible = "samsung,s5pv210-i2s";
+ reg = <0xeee30000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <16>;
+ dma-names = "rx", "tx", "tx-sec";
+ dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
+ clock-names = "iis",
+ "i2s_opclk0",
+ "i2s_opclk1";
+ clocks = <&clk_audss CLK_I2S>,
+ <&clk_audss CLK_I2S>,
+ <&clk_audss CLK_DOUT_AUD_BUS>;
+ samsung,idma-addr = <0xc0010000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_bus>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+ };
+
+ i2s1: i2s@e2100000 {
+ compatible = "samsung,s3c6410-i2s";
+ reg = <0xe2100000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <17>;
+ dma-names = "rx", "tx";
+ dmas = <&pdma1 12>, <&pdma1 13>;
+ clock-names = "iis", "i2s_opclk0";
+ clocks = <&clocks CLK_I2S1>, <&clocks SCLK_AUDIO1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1_bus>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2s2: i2s@e2a00000 {
+ compatible = "samsung,s3c6410-i2s";
+ reg = <0xe2a00000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <18>;
+ dma-names = "rx", "tx";
+ dmas = <&pdma1 14>, <&pdma1 15>;
+ clock-names = "iis", "i2s_opclk0";
+ clocks = <&clocks CLK_I2S2>, <&clocks SCLK_AUDIO2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2_bus>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ pwm: pwm@e2500000 {
+ compatible = "samsung,s5pc100-pwm";
+ reg = <0xe2500000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <21>, <22>, <23>, <24>, <25>;
+ clock-names = "timers";
+ clocks = <&clocks CLK_PWM>;
+ #pwm-cells = <3>;
+ };
+
+ watchdog: watchdog@e2700000 {
+ compatible = "samsung,s3c2410-wdt";
+ reg = <0xe2700000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <26>;
+ clock-names = "watchdog";
+ clocks = <&clocks CLK_WDT>;
+ };
+
+ rtc: rtc@e2800000 {
+ compatible = "samsung,s3c6410-rtc";
+ reg = <0xe2800000 0x100>;
+ interrupt-parent = <&vic0>;
+ interrupts = <28>, <29>;
+ clocks = <&clocks CLK_RTC>;
+ clock-names = "rtc";
+ status = "disabled";
+ };
+
+ uart0: serial@e2900000 {
+ compatible = "samsung,s5pv210-uart";
+ reg = <0xe2900000 0x400>;
+ interrupt-parent = <&vic1>;
+ interrupts = <10>;
+ clock-names = "uart", "clk_uart_baud0",
+ "clk_uart_baud1";
+ clocks = <&clocks CLK_UART0>, <&clocks CLK_UART0>,
+ <&clocks SCLK_UART0>;
+ status = "disabled";
+ };
+
+ uart1: serial@e2900400 {
+ compatible = "samsung,s5pv210-uart";
+ reg = <0xe2900400 0x400>;
+ interrupt-parent = <&vic1>;
+ interrupts = <11>;
+ clock-names = "uart", "clk_uart_baud0",
+ "clk_uart_baud1";
+ clocks = <&clocks CLK_UART1>, <&clocks CLK_UART1>,
+ <&clocks SCLK_UART1>;
+ status = "disabled";
+ };
+
+ uart2: serial@e2900800 {
+ compatible = "samsung,s5pv210-uart";
+ reg = <0xe2900800 0x400>;
+ interrupt-parent = <&vic1>;
+ interrupts = <12>;
+ clock-names = "uart", "clk_uart_baud0",
+ "clk_uart_baud1";
+ clocks = <&clocks CLK_UART2>, <&clocks CLK_UART2>,
+ <&clocks SCLK_UART2>;
+ status = "disabled";
+ };
+
+ uart3: serial@e2900c00 {
+ compatible = "samsung,s5pv210-uart";
+ reg = <0xe2900c00 0x400>;
+ interrupt-parent = <&vic1>;
+ interrupts = <13>;
+ clock-names = "uart", "clk_uart_baud0",
+ "clk_uart_baud1";
+ clocks = <&clocks CLK_UART3>, <&clocks CLK_UART3>,
+ <&clocks SCLK_UART3>;
+ status = "disabled";
+ };
+
+ sdhci0: sdhci@eb000000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0xeb000000 0x100000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <26>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks CLK_HSMMC0>, <&clocks CLK_HSMMC0>,
+ <&clocks SCLK_MMC0>;
+ status = "disabled";
+ };
+
+ sdhci1: sdhci@eb100000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0xeb100000 0x100000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <27>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks CLK_HSMMC1>, <&clocks CLK_HSMMC1>,
+ <&clocks SCLK_MMC1>;
+ status = "disabled";
+ };
+
+ sdhci2: sdhci@eb200000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0xeb200000 0x100000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <28>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks CLK_HSMMC2>, <&clocks CLK_HSMMC2>,
+ <&clocks SCLK_MMC2>;
+ status = "disabled";
+ };
+
+ sdhci3: sdhci@eb300000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0xeb300000 0x100000>;
+ interrupt-parent = <&vic3>;
+ interrupts = <2>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.3";
+ clocks = <&clocks CLK_HSMMC3>, <&clocks CLK_HSMMC3>,
+ <&clocks SCLK_MMC3>;
+ status = "disabled";
+ };
+
+ hsotg: hsotg@ec000000 {
+ compatible = "samsung,s3c6400-hsotg";
+ reg = <0xec000000 0x20000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <24>;
+ clocks = <&clocks CLK_USB_OTG>;
+ clock-names = "otg";
+ phy-names = "usb2-phy";
+ phys = <&usbphy 0>;
+ status = "disabled";
+ };
+
+ usbphy: usbphy@ec100000 {
+ compatible = "samsung,s5pv210-usb2-phy";
+ reg = <0xec100000 0x100>;
+ samsung,pmureg-phandle = <&pmu_syscon>;
+ clocks = <&clocks CLK_USB_OTG>, <&xusbxti>;
+ clock-names = "phy", "ref";
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
+ ehci: ehci@ec200000 {
+ compatible = "samsung,exynos4210-ehci";
+ reg = <0xec200000 0x100>;
+ interrupts = <23>;
+ interrupt-parent = <&vic1>;
+ clocks = <&clocks CLK_USB_HOST>;
+ clock-names = "usbhost";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ port@0 {
+ reg = <0>;
+ phys = <&usbphy 1>;
+ };
+ };
+
+ ohci: ohci@ec300000 {
+ compatible = "samsung,exynos4210-ohci";
+ reg = <0xec300000 0x100>;
+ interrupts = <23>;
+ clocks = <&clocks CLK_USB_HOST>;
+ clock-names = "usbhost";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ port@0 {
+ reg = <0>;
+ phys = <&usbphy 1>;
+ };
+ };
+
+ mfc: codec@f1700000 {
+ compatible = "samsung,mfc-v5";
+ reg = <0xf1700000 0x10000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <14>;
+ clocks = <&clocks DOUT_MFC>, <&clocks CLK_MFC>;
+ clock-names = "sclk_mfc", "mfc";
+ };
+
+ vic0: interrupt-controller@f2000000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0xf2000000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@f2100000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0xf2100000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic2: interrupt-controller@f2200000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0xf2200000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic3: interrupt-controller@f2300000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0xf2300000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ fimd: fimd@f8000000 {
+ compatible = "samsung,exynos4210-fimd";
+ interrupt-parent = <&vic2>;
+ reg = <0xf8000000 0x20000>;
+ interrupt-names = "fifo", "vsync", "lcd_sys";
+ interrupts = <0>, <1>, <2>;
+ clocks = <&clocks SCLK_FIMD>, <&clocks CLK_FIMD>;
+ clock-names = "sclk_fimd", "fimd";
+ status = "disabled";
+ };
+
+ g2d: g2d@fa000000 {
+ compatible = "samsung,s5pv210-g2d";
+ reg = <0xfa000000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <9>;
+ clocks = <&clocks DOUT_G2D>, <&clocks CLK_G2D>;
+ clock-names = "sclk_fimg2d", "fimg2d";
+ };
+
+ mdma1: mdma@fa200000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xfa200000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <18>;
+ clocks = <&clocks CLK_MDMA>;
+ clock-names = "apb_pclk";
+ #dma-cells = <1>;
+ #dma-channels = <8>;
+ #dma-requests = <1>;
+ };
+
+ i2c1: i2c@fab00000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0xfab00000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <13>;
+ clocks = <&clocks CLK_I2C1>;
+ clock-names = "i2c";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_bus>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ camera: camera {
+ compatible = "samsung,fimc", "simple-bus";
+ pinctrl-names = "default";
+ pinctrl-0 = <>;
+ clocks = <&clocks SCLK_CAM0>, <&clocks SCLK_CAM1>;
+ clock-names = "sclk_cam0", "sclk_cam1";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clock_cam: clock-controller {
+ #clock-cells = <1>;
+ };
+
+ csis0: csis@fa600000 {
+ compatible = "samsung,s5pv210-csis";
+ reg = <0xfa600000 0x4000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <29>;
+ clocks = <&clocks CLK_CSIS>,
+ <&clocks SCLK_CSIS>;
+ clock-names = "clk_csis",
+ "sclk_csis";
+ bus-width = <4>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ fimc0: fimc@fb200000 {
+ compatible = "samsung,s5pv210-fimc";
+ reg = <0xfb200000 0x1000>;
+ interrupts = <5>;
+ interrupt-parent = <&vic2>;
+ clocks = <&clocks CLK_FIMC0>,
+ <&clocks SCLK_FIMC0>;
+ clock-names = "fimc",
+ "sclk_fimc";
+ samsung,pix-limits = <4224 8192 1920 4224>;
+ samsung,mainscaler-ext;
+ samsung,cam-if;
+ };
+
+ fimc1: fimc@fb300000 {
+ compatible = "samsung,s5pv210-fimc";
+ reg = <0xfb300000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <6>;
+ clocks = <&clocks CLK_FIMC1>,
+ <&clocks SCLK_FIMC1>;
+ clock-names = "fimc",
+ "sclk_fimc";
+ samsung,pix-limits = <4224 8192 1920 4224>;
+ samsung,mainscaler-ext;
+ samsung,cam-if;
+ };
+
+ fimc2: fimc@fb400000 {
+ compatible = "samsung,s5pv210-fimc";
+ reg = <0xfb400000 0x1000>;
+ interrupt-parent = <&vic2>;
+ interrupts = <7>;
+ clocks = <&clocks CLK_FIMC2>,
+ <&clocks SCLK_FIMC2>;
+ clock-names = "fimc",
+ "sclk_fimc";
+ samsung,pix-limits = <4224 8192 1920 4224>;
+ samsung,mainscaler-ext;
+ samsung,lcd-wb;
+ };
+ };
+ };
+};
+
+#include "s5pv210-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index e0b15a6e8897..45013b867c8d 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -58,19 +58,19 @@
reg = <0x20000000 0x8000000>;
};
- slow_xtal: slow_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ clocks {
+ slow_xtal: slow_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- main_xtal: main_xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
+ main_xtal: main_xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- clocks {
adc_op_clk: adc_op_clk{
compatible = "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/sama5d3_gmac.dtsi b/arch/arm/boot/dts/sama5d3_gmac.dtsi
index a6cb0508762f..de5ed59fb446 100644
--- a/arch/arm/boot/dts/sama5d3_gmac.dtsi
+++ b/arch/arm/boot/dts/sama5d3_gmac.dtsi
@@ -74,7 +74,7 @@
};
macb0: ethernet@f0028000 {
- compatible = "cdns,pc302-gem", "cdns,gem";
+ compatible = "atmel,sama5d3-gem";
reg = <0xf0028000 0x100>;
interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi
index b0b1331c1974..f7d8583eef82 100644
--- a/arch/arm/boot/dts/sama5d3xcm.dtsi
+++ b/arch/arm/boot/dts/sama5d3xcm.dtsi
@@ -18,12 +18,14 @@
reg = <0x20000000 0x20000000>;
};
- slow_xtal {
- clock-frequency = <32768>;
- };
+ clocks {
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
- main_xtal {
- clock-frequency = <12000000>;
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/sama5d3xmb.dtsi b/arch/arm/boot/dts/sama5d3xmb.dtsi
index 306eef0f97ef..b8c6f20e780c 100644
--- a/arch/arm/boot/dts/sama5d3xmb.dtsi
+++ b/arch/arm/boot/dts/sama5d3xmb.dtsi
@@ -45,6 +45,8 @@
wm8904: wm8904@1a {
compatible = "wm8904";
reg = <0x1a>;
+ clocks = <&pck0>;
+ clock-names = "mclk";
};
};
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
index a99171c8a782..18662aec2ec4 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -21,6 +21,10 @@
model = "KZM-A9-GT";
compatible = "renesas,kzm9g-reference", "renesas,sh73a0";
+ aliases {
+ serial4 = &scifa4;
+ };
+
cpus {
cpu@0 {
cpu0-supply = <&vdd_dvfs>;
@@ -35,7 +39,7 @@
};
chosen {
- bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200 rw";
+ bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel rw";
};
memory {
@@ -276,9 +280,6 @@
};
&pfc {
- pinctrl-0 = <&scifa4_pins>;
- pinctrl-names = "default";
-
i2c3_pins: i2c3 {
renesas,groups = "i2c3_1";
renesas,function = "i2c3";
@@ -318,6 +319,13 @@
};
};
+&scifa4 {
+ pinctrl-0 = <&scifa4_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
&sdhi0 {
pinctrl-0 = <&sdhi0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 5ecf552e1c00..910b79079d5a 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -235,6 +235,78 @@
status = "disabled";
};
+ scifa0: serial@e6c40000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6c40000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa1: serial@e6c50000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6c50000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa2: serial@e6c60000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6c60000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa3: serial@e6c70000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6c70000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa4: serial@e6c80000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6c80000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa5: serial@e6cb0000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6cb0000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa6: serial@e6cc0000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6cc0000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifa7: serial@e6cd0000 {
+ compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+ reg = <0xe6cd0000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ scifb8: serial@e6c30000 {
+ compatible = "renesas,scifb-sh73a0", "renesas,scifb";
+ reg = <0xe6c30000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
pfc: pfc@e6050000 {
compatible = "renesas,pfc-sh73a0";
reg = <0xe6050000 0x8000>,
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 4676f25e87a7..4d77ad690ed5 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -486,6 +486,8 @@
clock-names = "stmmaceth";
resets = <&rst EMAC0_RESET>;
reset-names = "stmmaceth";
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
status = "disabled";
};
@@ -500,6 +502,8 @@
clock-names = "stmmaceth";
resets = <&rst EMAC1_RESET>;
reset-names = "stmmaceth";
+ snps,multicast-filter-bins = <256>;
+ snps,perfect-filter-entries = <128>;
status = "disabled";
};
@@ -683,6 +687,7 @@
};
rst: rstmgr@ffd05000 {
+ #reset-cells = <1>;
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
};
diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index b56a801e42a2..d42c84b1df8d 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -106,6 +106,10 @@
status = "okay";
};
+ miphy@eb800000 {
+ status = "okay";
+ };
+
cf@b2800000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 122ae94076c8..fa5f2bb5f106 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -29,24 +29,111 @@
#gpio-cells = <2>;
};
- ahci@b1000000 {
+ miphy0: miphy@eb800000 {
+ compatible = "st,spear1310-miphy";
+ reg = <0xeb800000 0x4000>;
+ misc = <&misc>;
+ phy-id = <0>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
+ miphy1: miphy@eb804000 {
+ compatible = "st,spear1310-miphy";
+ reg = <0xeb804000 0x4000>;
+ misc = <&misc>;
+ phy-id = <1>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
+ miphy2: miphy@eb808000 {
+ compatible = "st,spear1310-miphy";
+ reg = <0xeb808000 0x4000>;
+ misc = <&misc>;
+ phy-id = <2>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
+ ahci0: ahci@b1000000 {
compatible = "snps,spear-ahci";
reg = <0xb1000000 0x10000>;
interrupts = <0 68 0x4>;
+ phys = <&miphy0 0>;
+ phy-names = "sata-phy";
status = "disabled";
};
- ahci@b1800000 {
+ ahci1: ahci@b1800000 {
compatible = "snps,spear-ahci";
reg = <0xb1800000 0x10000>;
interrupts = <0 69 0x4>;
+ phys = <&miphy1 0>;
+ phy-names = "sata-phy";
status = "disabled";
};
- ahci@b4000000 {
+ ahci2: ahci@b4000000 {
compatible = "snps,spear-ahci";
reg = <0xb4000000 0x10000>;
interrupts = <0 70 0x4>;
+ phys = <&miphy2 0>;
+ phy-names = "sata-phy";
+ status = "disabled";
+ };
+
+ pcie0: pcie@b1000000 {
+ compatible = "st,spear1340-pcie", "snps,dw-pcie";
+ reg = <0xb1000000 0x4000>;
+ interrupts = <0 68 0x4>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0x0 0 &gic 0 68 0x4>;
+ num-lanes = <1>;
+ phys = <&miphy0 1>;
+ phy-names = "pcie-phy";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x00000800 0 0x80000000 0x80000000 0 0x00020000 /* configuration space */
+ 0x81000000 0 0 0x80020000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x80030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
+ status = "disabled";
+ };
+
+ pcie1: pcie@b1800000 {
+ compatible = "st,spear1340-pcie", "snps,dw-pcie";
+ reg = <0xb1800000 0x4000>;
+ interrupts = <0 69 0x4>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0x0 0 &gic 0 69 0x4>;
+ num-lanes = <1>;
+ phys = <&miphy1 1>;
+ phy-names = "pcie-phy";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x00000800 0 0x90000000 0x90000000 0 0x00020000 /* configuration space */
+ 0x81000000 0 0 0x90020000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x90030000 0x90030000 0 0x0ffd0000>; /* non-prefetchable memory */
+ status = "disabled";
+ };
+
+ pcie2: pcie@b4000000 {
+ compatible = "st,spear1340-pcie", "snps,dw-pcie";
+ reg = <0xb4000000 0x4000>;
+ interrupts = <0 70 0x4>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0x0 0 &gic 0 70 0x4>;
+ num-lanes = <1>;
+ phys = <&miphy2 1>;
+ phy-names = "pcie-phy";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x00000800 0 0xc0000000 0xc0000000 0 0x00020000 /* configuration space */
+ 0x81000000 0 0 0xc0020000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0xc0030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index d6c30ae0a8d7..b23e05ed1d60 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -122,6 +122,10 @@
status = "okay";
};
+ miphy@eb800000 {
+ status = "okay";
+ };
+
dma@ea800000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index 54d128d35681..e71df0f2cb52 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -31,10 +31,38 @@
status = "disabled";
};
- ahci@b1000000 {
+ miphy0: miphy@eb800000 {
+ compatible = "st,spear1340-miphy";
+ reg = <0xeb800000 0x4000>;
+ misc = <&misc>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
+ ahci0: ahci@b1000000 {
compatible = "snps,spear-ahci";
reg = <0xb1000000 0x10000>;
interrupts = <0 72 0x4>;
+ phys = <&miphy0 0>;
+ phy-names = "sata-phy";
+ status = "disabled";
+ };
+
+ pcie0: pcie@b1000000 {
+ compatible = "st,spear1340-pcie", "snps,dw-pcie";
+ reg = <0xb1000000 0x4000>;
+ interrupts = <0 68 0x4>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0x0 0 &gic 0 68 0x4>;
+ num-lanes = <1>;
+ phys = <&miphy0 1>;
+ phy-names = "pcie-phy";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ ranges = <0x00000800 0 0x80000000 0x80000000 0 0x00020000 /* configuration space */
+ 0x81000000 0 0 0x80020000 0 0x00010000 /* downstream I/O */
+ 0x82000000 0 0x80030000 0xc0030000 0 0x0ffd0000>; /* non-prefetchable memory */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 4382547df58a..a6eb5436d26d 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -83,8 +83,8 @@
#size-cells = <1>;
compatible = "simple-bus";
ranges = <0x50000000 0x50000000 0x10000000
- 0xb0000000 0xb0000000 0x10000000
- 0xd0000000 0xd0000000 0x02000000
+ 0x80000000 0x80000000 0x20000000
+ 0xb0000000 0xb0000000 0x22000000
0xd8000000 0xd8000000 0x01000000
0xe0000000 0xe0000000 0x10000000>;
@@ -220,6 +220,11 @@
0xd8000000 0xd8000000 0x01000000
0xe0000000 0xe0000000 0x10000000>;
+ misc: syscon@e0700000 {
+ compatible = "st,spear1340-misc", "syscon";
+ reg = <0xe0700000 0x1000>;
+ };
+
gpio0: gpio@e0600000 {
compatible = "arm,pl061", "arm,primecell";
reg = <0xe0600000 0x1000>;
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index e41eedca3ce3..9d2323020d34 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -875,6 +875,10 @@
reg = <0x80119000 0x1000>;
interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma 41 0 0x2>, /* Logical - DevToMem */
+ <&dma 41 0 0x0>; /* Logical - MemToDev */
+ dma-names = "rx", "tx";
+
clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>;
clock-names = "sdi", "apb_pclk";
@@ -901,6 +905,10 @@
reg = <0x80008000 0x1000>;
interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dma 43 0 0x2>, /* Logical - DevToMem */
+ <&dma 43 0 0x0>; /* Logical - MemToDev */
+ dma-names = "rx", "tx";
+
clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
clock-names = "sdi", "apb_pclk";
@@ -929,6 +937,7 @@
interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
v-ape-supply = <&db8500_vape_reg>;
+ /* This DMA channel only exist on DB8500 v1 */
dmas = <&dma 30 0 0x10>; /* Logical - MemToDev - HighPrio */
dma-names = "tx";
@@ -962,6 +971,7 @@
interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
v-ape-supply = <&db8500_vape_reg>;
+ /* This DMA channel only exist on DB8500 v2 */
dmas = <&dma 30 0 0x12>; /* Logical - DevToMem - HighPrio */
dma-names = "rx";
diff --git a/arch/arm/boot/dts/ste-href-stuib.dtsi b/arch/arm/boot/dts/ste-href-stuib.dtsi
index 1c3574435ea8..84d7c5d883f2 100644
--- a/arch/arm/boot/dts/ste-href-stuib.dtsi
+++ b/arch/arm/boot/dts/ste-href-stuib.dtsi
@@ -42,6 +42,8 @@
interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio6>;
interrupt-controller;
+ vcc-supply = <&db8500_vsmps2_reg>;
+ vio-supply = <&db8500_vsmps2_reg>;
wakeup-source;
st,autosleep-timeout = <1024>;
diff --git a/arch/arm/boot/dts/ste-href-tvk1281618.dtsi b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
index c40565320978..18b65d1b14f2 100644
--- a/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
+++ b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
@@ -88,6 +88,43 @@
};
};
};
+ /* Sensors mounted on this board variant */
+ i2c@80128000 {
+ lsm303dlh@18 {
+ /* Accelerometer */
+ compatible = "st,lsm303dlh-accel";
+ st,drdy-int-pin = <1>;
+ reg = <0x18>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&accel_tvk_mode>;
+ };
+ lsm303dlm@1e {
+ /* Magnetometer */
+ compatible = "st,lsm303dlm-magn";
+ reg = <0x1e>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&magneto_tvk_mode>;
+ };
+ l3g4200d@68 {
+ /* Gyroscope */
+ compatible = "st,l3g4200d-gyro";
+ st,drdy-int-pin = <2>;
+ reg = <0x68>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ };
+ lsp001wm@5c {
+ /* Barometer/pressure sensor */
+ compatible = "st,lps001wp-press";
+ reg = <0x5c>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ };
+ };
pinctrl {
/* Pull up this GPIO pin */
tc35893 {
@@ -114,6 +151,28 @@
};
};
};
+ accelerometer {
+ accel_tvk_mode: accel_tvk {
+ /* Accelerometer interrupt lines 1 & 2 */
+ tvk_cfg {
+ ste,pins = "GPIO82_C1", "GPIO83_D3";
+ ste,config = <&gpio_in_pu>;
+ };
+ };
+ };
+ magnetometer {
+ magneto_tvk_mode: magneto_tvk {
+ /* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
+ tvk_cfg1 {
+ ste,pins = "GPIO31_V3";
+ ste,config = <&gpio_in_pu>;
+ };
+ tvk_cfg2 {
+ ste,pins = "GPIO32_V2";
+ ste,config = <&gpio_in_pd>;
+ };
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
index c2341061b943..bcc1f0c37f49 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -35,8 +35,6 @@
*/
pinctrl-names = "default";
pinctrl-0 = <&ipgpio_hrefv60_mode>,
- <&accel_hrefv60_mode>,
- <&magneto_hrefv60_mode>,
<&etm_hrefv60_mode>,
<&nahj_hrefv60_mode>,
<&nfc_hrefv60_mode>,
@@ -83,28 +81,6 @@
};
};
};
- accelerometer {
- accel_hrefv60_mode: accel_hrefv60 {
- /* Accelerometer interrupt lines 1 & 2 */
- hrefv60_cfg1 {
- ste,pins = "GPIO82_C1", "GPIO83_D3";
- ste,config = <&gpio_in_pu>;
- };
- };
- };
- magnetometer {
- magneto_hrefv60_mode: magneto_hrefv60 {
- /* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
- hrefv60_cfg1 {
- ste,pins = "GPIO31_V3";
- ste,config = <&gpio_in_pu>;
- };
- hrefv60_cfg2 {
- ste,pins = "GPIO32_V2";
- ste,config = <&gpio_in_pd>;
- };
- };
- };
etm {
/*
* Drive D19-D23 for the ETM PTM trace interface low,
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 474ef83229cd..4a2000c620ad 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -241,6 +241,40 @@
pinctrl-names = "default","sleep";
pinctrl-0 = <&i2c2_default_mode>;
pinctrl-1 = <&i2c2_sleep_mode>;
+ lsm303dlh@18 {
+ /* Accelerometer */
+ compatible = "st,lsm303dlh-accel";
+ st,drdy-int-pin = <1>;
+ reg = <0x18>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&accel_snowball_mode>;
+ };
+ lsm303dlm@1e {
+ /* Magnetometer */
+ compatible = "st,lsm303dlm-magn";
+ reg = <0x1e>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&magneto_snowball_mode>;
+ };
+ l3g4200d@68 {
+ /* Gyroscope */
+ compatible = "st,l3g4200d-gyro";
+ st,drdy-int-pin = <2>;
+ reg = <0x68>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ };
+ lsp001wm@5c {
+ /* Barometer/pressure sensor */
+ compatible = "st,lps001wp-press";
+ reg = <0x5c>;
+ vdd-supply = <&ab8500_ldo_aux1_reg>;
+ vddio-supply = <&db8500_vsmps2_reg>;
+ };
};
i2c@80110000 {
@@ -361,9 +395,7 @@
* can be moved over to being controlled by respective device.
*/
pinctrl-names = "default";
- pinctrl-0 = <&accel_snowball_mode>,
- <&magneto_snowball_mode>,
- <&gbf_snowball_mode>,
+ pinctrl-0 = <&gbf_snowball_mode>,
<&wlan_snowball_mode>;
ethernet {
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index 0b97c071dd56..9e99ade35e37 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -88,6 +88,12 @@
};
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -98,6 +104,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
};
diff --git a/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
new file mode 100644
index 000000000000..1763cc7ec023
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun4i-a10.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "BA10 tvbox";
+ compatible = "allwinner,ba10-tvbox", "allwinner,sun4i-a10";
+
+ soc@01c00000 {
+ emac: ethernet@01c0b000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_pins_a>;
+ phy = <&phy1>;
+ status = "okay";
+ };
+
+ mdio@01c0b080 {
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-inverted;
+ status = "okay";
+ };
+
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
+ pinctrl@01c20800 {
+ usb2_vbus_pin_a: usb2_vbus_pin@0 {
+ allwinner,pins = "PH12";
+ };
+ };
+
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ gpio = <&pio 7 12 0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index c200eacc66e8..3ce56bfbc0b5 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -80,6 +80,12 @@
};
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -90,6 +96,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
i2c1: i2c@01c2b000 {
diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
index 547fadcb984b..891ea446abae 100644
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
@@ -87,11 +87,32 @@
};
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
};
reg_emac_3v3: emac-3v3 {
diff --git a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
index f13723e18b86..6b0c37812ade 100644
--- a/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
+++ b/arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
@@ -40,12 +40,6 @@
status = "okay";
};
- i2c0: i2c@01c2ac00 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
- };
-
usbphy: phy@01c13400 {
usb1_vbus-supply = <&reg_usb1_vbus>;
usb2_vbus-supply = <&reg_usb2_vbus>;
@@ -67,6 +61,21 @@
ohci1: usb@01c1c400 {
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
};
reg_usb1_vbus: usb1-vbus {
diff --git a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
index c01cea50cf0c..b9ecce60f2e7 100644
--- a/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
+++ b/arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
@@ -52,11 +52,39 @@
status = "okay";
};
+ pinctrl@01c20800 {
+ ir0_pins_a: ir0@0 {
+ /* The ir receiver is not always populated */
+ allwinner,pull = <1>;
+ };
+ };
+
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
};
reg_usb1_vbus: usb1-vbus {
diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
index d46a7dbecef5..d046d568f5a1 100644
--- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
@@ -91,6 +91,21 @@
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
};
leds {
diff --git a/arch/arm/boot/dts/sun4i-a10-pcduino.dts b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
index fb03bccb78d2..6675bcd7860e 100644
--- a/arch/arm/boot/dts/sun4i-a10-pcduino.dts
+++ b/arch/arm/boot/dts/sun4i-a10-pcduino.dts
@@ -76,6 +76,15 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
};
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index d96e179490ce..459cb6377764 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -509,7 +509,7 @@
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
@@ -593,6 +593,20 @@
allwinner,drive = <0>;
allwinner,pull = <1>;
};
+
+ ir0_pins_a: ir0@0 {
+ allwinner,pins = "PB3","PB4";
+ allwinner,function = "ir0";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ ir1_pins_a: ir1@0 {
+ allwinner,pins = "PB22","PB23";
+ allwinner,function = "ir1";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {
@@ -621,6 +635,24 @@
status = "disabled";
};
+ ir0: ir@01c21800 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 6>, <&ir0_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <5>;
+ reg = <0x01c21800 0x40>;
+ status = "disabled";
+ };
+
+ ir1: ir@01c21c00 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 7>, <&ir1_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <6>;
+ reg = <0x01c21c00 0x40>;
+ status = "disabled";
+ };
+
sid: eeprom@01c23800 {
compatible = "allwinner,sun4i-a10-sid";
reg = <0x01c23800 0x10>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index b64f705d9008..24b0ad3a7c07 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -422,7 +422,7 @@
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 3b2a94c40f6e..bf86e65dd167 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -395,7 +395,7 @@
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
new file mode 100644
index 000000000000..f142065b3c1f
--- /dev/null
+++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2014 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun6i-a31.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "Merrii A31 Hummingbird";
+ compatible = "merrii,a31-hummingbird", "allwinner,sun6i-a31";
+
+ chosen {
+ bootargs = "earlyprintk console=ttyS0,115200";
+ };
+
+ soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_hummingbird>;
+ vmmc-supply = <&reg_vcc3v0>;
+ bus-width = <4>;
+ cd-gpios = <&pio 0 8 0>; /* PA8 */
+ cd-inverted;
+ status = "okay";
+ };
+
+ usbphy: phy@01c19400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c1a000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c1a400 {
+ status = "okay";
+ };
+
+ pio: pinctrl@01c20800 {
+ mmc0_pins_a: mmc0@0 {
+ /* external pull-ups missing for some pins */
+ allwinner,pull = <1>;
+ };
+
+ mmc0_cd_pin_hummingbird: mmc0_cd_pin@0 {
+ allwinner,pins = "PA8";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <1>;
+ };
+
+ usb1_vbus_pin_a: usb1_vbus_pin@0 {
+ allwinner,pins = "PH24";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+ };
+
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ /* pull-ups and devices require AXP221 DLDO3 */
+ status = "failed";
+ };
+
+ i2c1: i2c@01c2b000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_a>;
+ status = "okay";
+ };
+
+ i2c2: i2c@01c2b400 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_a>;
+ status = "okay";
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ gmac: ethernet@01c30000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_rgmii_a>;
+ phy = <&phy1>;
+ phy-mode = "rgmii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ pinctrl-0 = <&usb1_vbus_pin_a>;
+ gpio = <&pio 7 24 0>; /* PH24 */
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index a9dfa12eb735..44b07e512c24 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -23,6 +23,7 @@
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
+ ethernet0 = &gmac;
};
@@ -281,6 +282,34 @@
"usb_ohci0", "usb_ohci1",
"usb_ohci2";
};
+
+ /*
+ * The following two are dummy clocks, placeholders used in the gmac_tx
+ * clock. The gmac driver will choose one parent depending on the PHY
+ * interface mode, using clk_set_rate auto-reparenting.
+ * The actual TX clock rate is not controlled by the gmac_tx clock.
+ */
+ mii_phy_tx_clk: clk@1 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <25000000>;
+ clock-output-names = "mii_phy_tx";
+ };
+
+ gmac_int_tx_clk: clk@2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac_int_tx";
+ };
+
+ gmac_tx_clk: clk@01c200d0 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun7i-a20-gmac-clk";
+ reg = <0x01c200d0 0x4>;
+ clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>;
+ clock-output-names = "gmac_tx";
+ };
};
soc@01c00000 {
@@ -429,7 +458,7 @@
clocks = <&apb1_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
@@ -467,6 +496,48 @@
allwinner,drive = <2>;
allwinner,pull = <0>;
};
+
+ gmac_pins_mii_a: gmac_mii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+ "PA8", "PA9", "PA11",
+ "PA12", "PA13", "PA14", "PA19",
+ "PA20", "PA21", "PA22", "PA23",
+ "PA24", "PA26", "PA27";
+ allwinner,function = "gmac";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ gmac_pins_gmii_a: gmac_gmii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+ "PA4", "PA5", "PA6", "PA7",
+ "PA8", "PA9", "PA10", "PA11",
+ "PA12", "PA13", "PA14", "PA15",
+ "PA16", "PA17", "PA18", "PA19",
+ "PA20", "PA21", "PA22", "PA23",
+ "PA24", "PA25", "PA26", "PA27";
+ allwinner,function = "gmac";
+ /*
+ * data lines in GMII mode run at 125MHz and
+ * might need a higher signal drive strength
+ */
+ allwinner,drive = <2>;
+ allwinner,pull = <0>;
+ };
+
+ gmac_pins_rgmii_a: gmac_rgmii@0 {
+ allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+ "PA9", "PA10", "PA11",
+ "PA12", "PA13", "PA14", "PA19",
+ "PA20", "PA25", "PA26", "PA27";
+ allwinner,function = "gmac";
+ /*
+ * data lines in RGMII mode use DDR mode
+ * and need a higher signal drive strength
+ */
+ allwinner,drive = <3>;
+ allwinner,pull = <0>;
+ };
};
ahb1_rst: reset@01c202c0 {
@@ -621,6 +692,23 @@
status = "disabled";
};
+ gmac: ethernet@01c30000 {
+ compatible = "allwinner,sun7i-a20-gmac";
+ reg = <0x01c30000 0x1054>;
+ interrupts = <0 82 4>;
+ interrupt-names = "macirq";
+ clocks = <&ahb1_gates 17>, <&gmac_tx_clk>;
+ clock-names = "stmmaceth", "allwinner_gmac_tx";
+ resets = <&ahb1_rst 17>;
+ reset-names = "stmmaceth";
+ snps,pbl = <2>;
+ snps,fixed-burst;
+ snps,force_sf_dma_mode;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
timer@01c60000 {
compatible = "allwinner,sun6i-a31-hstimer", "allwinner,sun7i-a20-hstimer";
reg = <0x01c60000 0x1000>;
@@ -756,7 +844,7 @@
resets = <&apb0_rst 0>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
};
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index a5ad945197e8..53680983461a 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -66,6 +66,12 @@
};
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -76,6 +82,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
i2c1: i2c@01c2b000 {
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index b87fea901489..a6c1a3c717bc 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -100,6 +100,12 @@
status = "okay";
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
@@ -110,6 +116,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
i2c1: i2c@01c2b000 {
diff --git a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
index b77308e90199..6a67712d417a 100644
--- a/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
+++ b/arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
@@ -94,12 +94,34 @@
};
};
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
uart0: serial@01c28000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
gmac: ethernet@01c50000 {
pinctrl-names = "default";
pinctrl-0 = <&gmac_pins_mii_a>;
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index b759630bc9a9..9d669cdf031d 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -122,6 +122,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
};
i2c1: i2c@01c2b000 {
diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
new file mode 100644
index 000000000000..046dfc0d45d8
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-pcduino3.dts
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2014 Zoltan HERPAI
+ * Zoltan HERPAI <wigyori@uid0.hu>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "LinkSprite pcDuino3";
+ compatible = "linksprite,pcduino3", "allwinner,sun7i-a20";
+
+ soc@01c00000 {
+ mmc0: mmc@01c0f000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 1 0>; /* PH1 */
+ cd-inverted;
+ status = "okay";
+ };
+
+ usbphy: phy@01c13400 {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb@01c14000 {
+ status = "okay";
+ };
+
+ ohci0: usb@01c14400 {
+ status = "okay";
+ };
+
+ ahci: sata@01c18000 {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+ };
+
+ ehci1: usb@01c1c000 {
+ status = "okay";
+ };
+
+ ohci1: usb@01c1c400 {
+ status = "okay";
+ };
+
+ pinctrl@01c20800 {
+ ahci_pwr_pin_a: ahci_pwr_pin@0 {
+ allwinner,pins = "PH2";
+ };
+
+ led_pins_pcduino3: led_pins@0 {
+ allwinner,pins = "PH15", "PH16";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ key_pins_pcduino3: key_pins@0 {
+ allwinner,pins = "PH17", "PH18", "PH19";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+ };
+
+ ir0: ir@01c21800 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir0_pins_a>;
+ status = "okay";
+ };
+
+ uart0: serial@01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+
+ i2c0: i2c@01c2ac00 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 8>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ gmac: ethernet@01c50000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_pins_mii_a>;
+ phy = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins_pcduino3>;
+
+ tx {
+ label = "pcduino3:green:tx";
+ gpios = <&pio 7 15 GPIO_ACTIVE_LOW>;
+ };
+
+ rx {
+ label = "pcduino3:green:rx";
+ gpios = <&pio 7 16 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_pins_pcduino3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ button@0 {
+ label = "Key Back";
+ linux,code = <KEY_BACK>;
+ gpios = <&pio 7 17 GPIO_ACTIVE_LOW>;
+ };
+ button@1 {
+ label = "Key Home";
+ linux,code = <KEY_HOME>;
+ gpios = <&pio 7 18 GPIO_ACTIVE_LOW>;
+ };
+ button@2 {
+ label = "Key Menu";
+ linux,code = <KEY_MENU>;
+ gpios = <&pio 7 19 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ status = "okay";
+ };
+
+ reg_usb2_vbus: usb2-vbus {
+ status = "okay";
+ };
+
+ reg_ahci_5v: ahci-5v {
+ gpio = <&pio 7 2 0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 01e94664232a..4011628c7381 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -586,7 +586,7 @@
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
- #address-cells = <1>;
+ #interrupt-cells = <2>;
#size-cells = <0>;
#gpio-cells = <3>;
@@ -738,6 +738,20 @@
allwinner,drive = <2>;
allwinner,pull = <0>;
};
+
+ ir0_pins_a: ir0@0 {
+ allwinner,pins = "PB3","PB4";
+ allwinner,function = "ir0";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+
+ ir1_pins_a: ir1@0 {
+ allwinner,pins = "PB22","PB23";
+ allwinner,function = "ir1";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
};
timer@01c20c00 {
@@ -771,6 +785,24 @@
status = "disabled";
};
+ ir0: ir@01c21800 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 6>, <&ir0_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <0 5 4>;
+ reg = <0x01c21800 0x40>;
+ status = "disabled";
+ };
+
+ ir1: ir@01c21c00 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 7>, <&ir1_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <0 6 4>;
+ reg = <0x01c21c00 0x40>;
+ status = "disabled";
+ };
+
sid: eeprom@01c23800 {
compatible = "allwinner,sun7i-a20-sid";
reg = <0x01c23800 0x200>;
diff --git a/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts
new file mode 100644
index 000000000000..34002e3eba9d
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun8i-a23.dtsi"
+
+/ {
+ model = "Ippo Q8H Dual Core Tablet (v5)";
+ compatible = "ippo,q8h-v5", "allwinner,sun8i-a23";
+
+ chosen {
+ bootargs = "earlyprintk console=ttyS0,115200";
+ };
+
+ soc@01c00000 {
+ r_uart: serial@01f02800 {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
new file mode 100644
index 000000000000..54ac0787216a
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ interrupt-parent = <&gic>;
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &r_uart;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ };
+ };
+
+ memory {
+ reg = <0x40000000 0x40000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ osc24M: osc24M_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ };
+
+ osc32k: osc32k_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "osc32k";
+ };
+
+ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll1";
+ };
+
+ /* dummy clock until actually implemented */
+ pll6: pll6_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <600000000>;
+ clock-output-names = "pll6";
+ };
+
+ cpu: cpu_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-cpu-clk";
+ reg = <0x01c20050 0x4>;
+
+ /*
+ * PLL1 is listed twice here.
+ * While it looks suspicious, it's actually documented
+ * that way both in the datasheet and in the code from
+ * Allwinner.
+ */
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
+ clock-output-names = "cpu";
+ };
+
+ axi: axi_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-axi-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&cpu>;
+ clock-output-names = "axi";
+ };
+
+ ahb1_mux: ahb1_mux_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
+ clock-output-names = "ahb1_mux";
+ };
+
+ ahb1: ahb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-ahb-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1_mux>;
+ clock-output-names = "ahb1";
+ };
+
+ apb1: apb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1>;
+ clock-output-names = "apb1";
+ };
+
+ ahb1_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-a23-ahb1-gates-clk";
+ reg = <0x01c20060 0x8>;
+ clocks = <&ahb1>;
+ clock-output-names = "ahb1_mipidsi", "ahb1_dma",
+ "ahb1_mmc0", "ahb1_mmc1", "ahb1_mmc2",
+ "ahb1_nand", "ahb1_sdram",
+ "ahb1_hstimer", "ahb1_spi0",
+ "ahb1_spi1", "ahb1_otg", "ahb1_ehci",
+ "ahb1_ohci", "ahb1_ve", "ahb1_lcd",
+ "ahb1_csi", "ahb1_be", "ahb1_fe",
+ "ahb1_gpu", "ahb1_spinlock",
+ "ahb1_drc";
+ };
+
+ apb1_gates: clk@01c20068 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-a23-apb1-gates-clk";
+ reg = <0x01c20068 0x4>;
+ clocks = <&apb1>;
+ clock-output-names = "apb1_codec", "apb1_pio",
+ "apb1_daudio0", "apb1_daudio1";
+ };
+
+ apb2_mux: apb2_mux_clk@01c20058 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb1-mux-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+ clock-output-names = "apb2_mux";
+ };
+
+ apb2: apb2_clk@01c20058 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-apb2-div-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&apb2_mux>;
+ clock-output-names = "apb2";
+ };
+
+ apb2_gates: clk@01c2006c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-a23-apb2-gates-clk";
+ reg = <0x01c2006c 0x4>;
+ clocks = <&apb2>;
+ clock-output-names = "apb2_i2c0", "apb2_i2c1",
+ "apb2_i2c2", "apb2_uart0",
+ "apb2_uart1", "apb2_uart2",
+ "apb2_uart3", "apb2_uart4";
+ };
+ };
+
+ soc@01c00000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ ahb1_rst: reset@01c202c0 {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun6i-a31-clock-reset";
+ reg = <0x01c202c0 0xc>;
+ };
+
+ apb1_rst: reset@01c202d0 {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun6i-a31-clock-reset";
+ reg = <0x01c202d0 0x4>;
+ };
+
+ apb2_rst: reset@01c202d8 {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun6i-a31-clock-reset";
+ reg = <0x01c202d8 0x4>;
+ };
+
+ timer@01c20c00 {
+ compatible = "allwinner,sun4i-a10-timer";
+ reg = <0x01c20c00 0xa0>;
+ interrupts = <0 18 4>,
+ <0 19 4>;
+ clocks = <&osc24M>;
+ };
+
+ wdt0: watchdog@01c20ca0 {
+ compatible = "allwinner,sun6i-a31-wdt";
+ reg = <0x01c20ca0 0x20>;
+ interrupts = <0 25 4>;
+ };
+
+ uart0: serial@01c28000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28000 0x400>;
+ interrupts = <0 0 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb2_gates 16>;
+ resets = <&apb2_rst 16>;
+ status = "disabled";
+ };
+
+ uart1: serial@01c28400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28400 0x400>;
+ interrupts = <0 1 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb2_gates 17>;
+ resets = <&apb2_rst 17>;
+ status = "disabled";
+ };
+
+ uart2: serial@01c28800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28800 0x400>;
+ interrupts = <0 2 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb2_gates 18>;
+ resets = <&apb2_rst 18>;
+ status = "disabled";
+ };
+
+ uart3: serial@01c28c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28c00 0x400>;
+ interrupts = <0 3 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb2_gates 19>;
+ resets = <&apb2_rst 19>;
+ status = "disabled";
+ };
+
+ uart4: serial@01c29000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c29000 0x400>;
+ interrupts = <0 4 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb2_gates 20>;
+ resets = <&apb2_rst 20>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@01c81000 {
+ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+ reg = <0x01c81000 0x1000>,
+ <0x01c82000 0x1000>,
+ <0x01c84000 0x2000>,
+ <0x01c86000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <1 9 0xf04>;
+ };
+
+ prcm@01f01400 {
+ compatible = "allwinner,sun8i-a23-prcm";
+ reg = <0x01f01400 0x200>;
+
+ ar100: ar100_clk {
+ compatible = "fixed-factor-clock";
+ #clock-cells = <0>;
+ clock-div = <1>;
+ clock-mult = <1>;
+ clocks = <&osc24M>;
+ clock-output-names = "ar100";
+ };
+
+ ahb0: ahb0_clk {
+ compatible = "fixed-factor-clock";
+ #clock-cells = <0>;
+ clock-div = <1>;
+ clock-mult = <1>;
+ clocks = <&ar100>;
+ clock-output-names = "ahb0";
+ };
+
+ apb0: apb0_clk {
+ compatible = "allwinner,sun8i-a23-apb0-clk";
+ #clock-cells = <0>;
+ clocks = <&ahb0>;
+ clock-output-names = "apb0";
+ };
+
+ apb0_gates: apb0_gates_clk {
+ compatible = "allwinner,sun8i-a23-apb0-gates-clk";
+ #clock-cells = <1>;
+ clocks = <&apb0>;
+ clock-output-names = "apb0_pio", "apb0_timer",
+ "apb0_rsb", "apb0_uart",
+ "apb0_i2c";
+ };
+
+ apb0_rst: apb0_rst {
+ compatible = "allwinner,sun6i-a31-clock-reset";
+ #reset-cells = <1>;
+ };
+ };
+
+ r_uart: serial@01f02800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01f02800 0x400>;
+ interrupts = <0 38 4>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb0_gates 4>;
+ resets = <&apb0_rst 4>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/tegra114-roth.dts b/arch/arm/boot/dts/tegra114-roth.dts
index 0b0e8e07d965..c7c6825f11fb 100644
--- a/arch/arm/boot/dts/tegra114-roth.dts
+++ b/arch/arm/boot/dts/tegra114-roth.dts
@@ -28,6 +28,22 @@
reg = <0x80000000 0x79600000>;
};
+ host1x@50000000 {
+ dsi@54300000 {
+ status = "okay";
+
+ vdd-supply = <&vdd_1v2_ap>;
+
+ panel@0 {
+ compatible = "lg,lh500wx1-sd03";
+ reg = <0>;
+
+ power-supply = <&vdd_lcd>;
+ backlight = <&backlight>;
+ };
+ };
+ };
+
pinmux@70000868 {
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
@@ -244,7 +260,7 @@
nvidia,function = "sdmmc1";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
sdmmc1_cmd_pz1 {
nvidia,pins = "sdmmc1_cmd_pz1",
@@ -262,7 +278,7 @@
nvidia,function = "sdmmc3";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
sdmmc3_cmd_pa7 {
nvidia,pins = "sdmmc3_cmd_pa7",
@@ -290,7 +306,7 @@
nvidia,function = "sdmmc4";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
};
sdmmc4_cmd_pt7 {
nvidia,pins = "sdmmc4_cmd_pt7",
@@ -730,7 +746,6 @@
nvidia,pins = "drive_sdio1";
nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
nvidia,schmitt = <TEGRA_PIN_DISABLE>;
- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
nvidia,pull-down-strength = <36>;
nvidia,pull-up-strength = <20>;
nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOW>;
@@ -740,7 +755,6 @@
nvidia,pins = "drive_sdio3";
nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
nvidia,schmitt = <TEGRA_PIN_DISABLE>;
- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
nvidia,pull-down-strength = <36>;
nvidia,pull-up-strength = <20>;
nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
@@ -750,12 +764,10 @@
nvidia,pins = "drive_gma";
nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
nvidia,schmitt = <TEGRA_PIN_DISABLE>;
- nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>;
nvidia,pull-down-strength = <2>;
nvidia,pull-up-strength = <2>;
nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>;
- nvidia,drive-type = <1>;
};
};
};
@@ -815,7 +827,6 @@
regulator-name = "vdd-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
- regulator-always-on;
regulator-boot-on;
};
@@ -862,10 +873,11 @@
regulator-name = "vdd-2v8-display";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
+ regulator-always-on;
regulator-boot-on;
};
- ldo3 {
+ vdd_1v2_ap: ldo3 {
regulator-name = "avdd-1v2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
@@ -1052,7 +1064,7 @@
regulator-boot-on;
};
- regulator@1 {
+ vdd_lcd: regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
regulator-name = "vdd_lcd_1v8";
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index fdc559ab2db3..80b8eddb4105 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -220,6 +220,12 @@
interrupt-controller;
};
+ apbmisc@70000800 {
+ compatible = "nvidia,tegra114-apbmisc", "nvidia,tegra20-apbmisc";
+ reg = <0x70000800 0x64 /* Chip revision */
+ 0x70000008 0x04>; /* Strapping options */
+ };
+
pinmux: pinmux@70000868 {
compatible = "nvidia,tegra114-pinmux";
reg = <0x70000868 0x148 /* Pad control registers */
@@ -485,6 +491,15 @@
clock-names = "pclk", "clk32k_in";
};
+ fuse@7000f800 {
+ compatible = "nvidia,tegra114-efuse";
+ reg = <0x7000f800 0x400>;
+ clocks = <&tegra_car TEGRA114_CLK_FUSE>;
+ clock-names = "fuse";
+ resets = <&tegra_car 39>;
+ reset-names = "fuse";
+ };
+
iommu@70019010 {
compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
reg = <0x70019010 0x02c
@@ -657,6 +672,8 @@
<&tegra_car TEGRA114_CLK_PLL_U>,
<&tegra_car TEGRA114_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 22>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
@@ -667,6 +684,7 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -690,6 +708,8 @@
<&tegra_car TEGRA114_CLK_PLL_U>,
<&tegra_car TEGRA114_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 59>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index e31fb61a81d3..624b0fba2d0a 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1461,7 +1461,7 @@
regulator-max-microamp = <3500000>;
regulator-always-on;
regulator-boot-on;
- ams,external-control = <2>;
+ ams,ext-control = <2>;
};
sd1 {
@@ -1472,7 +1472,7 @@
regulator-max-microamp = <2500000>;
regulator-always-on;
regulator-boot-on;
- ams,external-control = <1>;
+ ams,ext-control = <1>;
};
vdd_1v35_lp0: sd2 {
@@ -1521,7 +1521,7 @@
regulator-max-microvolt = <1050000>;
regulator-boot-on;
regulator-always-on;
- ams,external-control = <1>;
+ ams,ext-control = <1>;
};
ldo1 {
@@ -1619,6 +1619,32 @@
nvidia,sys-clock-req-active-high;
};
+ padctl@0,7009f000 {
+ pinctrl-0 = <&padctl_default>;
+ pinctrl-names = "default";
+
+ padctl_default: pinmux {
+ usb3 {
+ nvidia,lanes = "pcie-0", "pcie-1";
+ nvidia,function = "usb3";
+ nvidia,iddq = <0>;
+ };
+
+ pcie {
+ nvidia,lanes = "pcie-2", "pcie-3",
+ "pcie-4";
+ nvidia,function = "pcie";
+ nvidia,iddq = <0>;
+ };
+
+ sata {
+ nvidia,lanes = "sata-0";
+ nvidia,function = "sata";
+ nvidia,iddq = <0>;
+ };
+ };
+ };
+
/* SD card */
sdhci@0,700b0400 {
status = "okay";
@@ -1633,6 +1659,7 @@
sdhci@0,700b0600 {
status = "okay";
bus-width = <8>;
+ non-removable;
};
ahub@0,70300000 {
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index f0bb84244025..70ad91d1a20b 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -682,7 +682,7 @@
regulator-max-microamp = <3500000>;
regulator-always-on;
regulator-boot-on;
- ams,external-control = <2>;
+ ams,ext-control = <2>;
};
sd1 {
@@ -693,7 +693,7 @@
regulator-max-microamp = <2500000>;
regulator-always-on;
regulator-boot-on;
- ams,external-control = <1>;
+ ams,ext-control = <1>;
};
vdd_1v35_lp0: sd2 {
@@ -742,7 +742,7 @@
regulator-max-microvolt = <1050000>;
regulator-boot-on;
regulator-always-on;
- ams,external-control = <1>;
+ ams,ext-control = <1>;
};
ldo1 {
@@ -816,7 +816,7 @@
spi@0,7000d400 {
status = "okay";
- cros-ec@0 {
+ cros_ec: cros-ec@0 {
compatible = "google,cros-ec-spi";
spi-max-frequency = <4000000>;
interrupt-parent = <&gpio>;
@@ -825,96 +825,30 @@
google,cros-ec-spi-msg-delay = <2000>;
- cros-ec-keyb {
- compatible = "google,cros-ec-keyb";
- keypad,num-rows = <8>;
- keypad,num-columns = <13>;
- google,needs-ghost-filter;
-
- linux,keymap = <
- MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
- MATRIX_KEY(0x00, 0x02, KEY_F1)
- MATRIX_KEY(0x00, 0x03, KEY_B)
- MATRIX_KEY(0x00, 0x04, KEY_F10)
- MATRIX_KEY(0x00, 0x06, KEY_N)
- MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
- MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
-
- MATRIX_KEY(0x01, 0x01, KEY_ESC)
- MATRIX_KEY(0x01, 0x02, KEY_F4)
- MATRIX_KEY(0x01, 0x03, KEY_G)
- MATRIX_KEY(0x01, 0x04, KEY_F7)
- MATRIX_KEY(0x01, 0x06, KEY_H)
- MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
- MATRIX_KEY(0x01, 0x09, KEY_F9)
- MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
-
- MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
- MATRIX_KEY(0x02, 0x01, KEY_TAB)
- MATRIX_KEY(0x02, 0x02, KEY_F3)
- MATRIX_KEY(0x02, 0x03, KEY_T)
- MATRIX_KEY(0x02, 0x04, KEY_F6)
- MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
- MATRIX_KEY(0x02, 0x06, KEY_Y)
- MATRIX_KEY(0x02, 0x07, KEY_102ND)
- MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
- MATRIX_KEY(0x02, 0x09, KEY_F8)
-
- MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
- MATRIX_KEY(0x03, 0x02, KEY_F2)
- MATRIX_KEY(0x03, 0x03, KEY_5)
- MATRIX_KEY(0x03, 0x04, KEY_F5)
- MATRIX_KEY(0x03, 0x06, KEY_6)
- MATRIX_KEY(0x03, 0x08, KEY_MINUS)
- MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
-
- MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
- MATRIX_KEY(0x04, 0x01, KEY_A)
- MATRIX_KEY(0x04, 0x02, KEY_D)
- MATRIX_KEY(0x04, 0x03, KEY_F)
- MATRIX_KEY(0x04, 0x04, KEY_S)
- MATRIX_KEY(0x04, 0x05, KEY_K)
- MATRIX_KEY(0x04, 0x06, KEY_J)
- MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
- MATRIX_KEY(0x04, 0x09, KEY_L)
- MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
- MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
-
- MATRIX_KEY(0x05, 0x01, KEY_Z)
- MATRIX_KEY(0x05, 0x02, KEY_C)
- MATRIX_KEY(0x05, 0x03, KEY_V)
- MATRIX_KEY(0x05, 0x04, KEY_X)
- MATRIX_KEY(0x05, 0x05, KEY_COMMA)
- MATRIX_KEY(0x05, 0x06, KEY_M)
- MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
- MATRIX_KEY(0x05, 0x08, KEY_SLASH)
- MATRIX_KEY(0x05, 0x09, KEY_DOT)
- MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
-
- MATRIX_KEY(0x06, 0x01, KEY_1)
- MATRIX_KEY(0x06, 0x02, KEY_3)
- MATRIX_KEY(0x06, 0x03, KEY_4)
- MATRIX_KEY(0x06, 0x04, KEY_2)
- MATRIX_KEY(0x06, 0x05, KEY_8)
- MATRIX_KEY(0x06, 0x06, KEY_7)
- MATRIX_KEY(0x06, 0x08, KEY_0)
- MATRIX_KEY(0x06, 0x09, KEY_9)
- MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
- MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
- MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
-
- MATRIX_KEY(0x07, 0x01, KEY_Q)
- MATRIX_KEY(0x07, 0x02, KEY_E)
- MATRIX_KEY(0x07, 0x03, KEY_R)
- MATRIX_KEY(0x07, 0x04, KEY_W)
- MATRIX_KEY(0x07, 0x05, KEY_I)
- MATRIX_KEY(0x07, 0x06, KEY_U)
- MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
- MATRIX_KEY(0x07, 0x08, KEY_P)
- MATRIX_KEY(0x07, 0x09, KEY_O)
- MATRIX_KEY(0x07, 0x0b, KEY_UP)
- MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
- >;
+ i2c-tunnel {
+ compatible = "google,cros-ec-i2c-tunnel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ google,remote-bus = <0>;
+
+ charger: bq24735@9 {
+ compatible = "ti,bq24735";
+ reg = <0x9>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(J, 0)
+ GPIO_ACTIVE_HIGH>;
+ ti,ac-detect-gpios = <&gpio
+ TEGRA_GPIO(J, 0)
+ GPIO_ACTIVE_HIGH>;
+ };
+
+ battery: sbs-battery@b {
+ compatible = "sbs,sbs-battery";
+ reg = <0xb>;
+ sbs,i2c-retry-count = <2>;
+ sbs,poll-retry-count = <1>;
+ };
};
};
};
@@ -940,6 +874,10 @@
nvidia,sys-clock-req-active-high;
};
+ hda@0,70030000 {
+ status = "okay";
+ };
+
sdhci@0,700b0400 {
cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -1205,3 +1143,5 @@
clock-names = "pll_a", "pll_a_out0", "mclk";
};
};
+
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 6e6bc4e8185c..03916efd6fa9 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -1,6 +1,7 @@
#include <dt-bindings/clock/tegra124-car.h>
#include <dt-bindings/gpio/tegra-gpio.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "skeleton.dtsi"
@@ -102,6 +103,21 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ gpu@0,57000000 {
+ compatible = "nvidia,gk20a";
+ reg = <0x0 0x57000000 0x0 0x01000000>,
+ <0x0 0x58000000 0x0 0x01000000>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "stall", "nonstall";
+ clocks = <&tegra_car TEGRA124_CLK_GPU>,
+ <&tegra_car TEGRA124_CLK_PLL_P_OUT5>;
+ clock-names = "gpu", "pwr";
+ resets = <&tegra_car 184>;
+ reset-names = "gpu";
+ status = "disabled";
+ };
+
timer@0,60005000 {
compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
reg = <0x0 0x60005000 0x0 0x400>;
@@ -179,6 +195,12 @@
#dma-cells = <1>;
};
+ apbmisc@0,70000800 {
+ compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc";
+ reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */
+ <0x0 0x7000E864 0x0 0x04>; /* Strapping options */
+ };
+
pinmux: pinmux@0,70000868 {
compatible = "nvidia,tegra124-pinmux";
reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
@@ -449,6 +471,39 @@
clock-names = "pclk", "clk32k_in";
};
+ fuse@0,7000f800 {
+ compatible = "nvidia,tegra124-efuse";
+ reg = <0x0 0x7000f800 0x0 0x400>;
+ clocks = <&tegra_car TEGRA124_CLK_FUSE>;
+ clock-names = "fuse";
+ resets = <&tegra_car 39>;
+ reset-names = "fuse";
+ };
+
+ hda@0,70030000 {
+ compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
+ reg = <0x0 0x70030000 0x0 0x10000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&tegra_car TEGRA124_CLK_HDA>,
+ <&tegra_car TEGRA124_CLK_HDA2HDMI>,
+ <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>;
+ clock-names = "hda", "hda2hdmi", "hdacodec_2x";
+ resets = <&tegra_car 125>, /* hda */
+ <&tegra_car 128>, /* hda2hdmi */
+ <&tegra_car 111>; /* hda2codec_2x */
+ reset-names = "hda", "hda2hdmi", "hdacodec_2x";
+ status = "disabled";
+ };
+
+ padctl: padctl@0,7009f000 {
+ compatible = "nvidia,tegra124-xusb-padctl";
+ reg = <0x0 0x7009f000 0x0 0x1000>;
+ resets = <&tegra_car 142>;
+ reset-names = "padctl";
+
+ #phy-cells = <1>;
+ };
+
sdhci@0,700b0000 {
compatible = "nvidia,tegra124-sdhci";
reg = <0x0 0x700b0000 0x0 0x200>;
@@ -613,6 +668,8 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 59>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
@@ -647,6 +704,8 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 22>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
@@ -657,6 +716,7 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -681,6 +741,8 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 58>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index f45aad688d9b..a37279af687c 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -562,10 +562,14 @@
};
pcie-controller@80003000 {
- pex-clk-supply = <&pci_clk_reg>;
- vdd-supply = <&pci_vdd_reg>;
status = "okay";
+ avdd-pex-supply = <&pci_vdd_reg>;
+ vdd-pex-supply = <&pci_vdd_reg>;
+ avdd-pex-pll-supply = <&pci_vdd_reg>;
+ avdd-plle-supply = <&pci_vdd_reg>;
+ vddio-pex-clk-supply = <&pci_clk_reg>;
+
pci@1,0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts
index 6d3a4cbc36cc..1b7c56b33aca 100644
--- a/arch/arm/boot/dts/tegra20-medcom-wide.dts
+++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts
@@ -10,6 +10,15 @@
status = "okay";
};
+ host1x@50000000 {
+ dc@54200000 {
+ rgb {
+ status = "okay";
+ nvidia,panel = <&panel>;
+ };
+ };
+ };
+
i2c@7000c000 {
wm8903: wm8903@1a {
compatible = "wlf,wm8903";
@@ -30,7 +39,7 @@
};
};
- backlight {
+ backlight: backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 5000000>;
@@ -38,6 +47,15 @@
default-brightness-level = <6>;
};
+ panel: panel {
+ compatible = "innolux,n156bge-l21", "simple-panel";
+
+ power-supply = <&vdd_1v8_reg>, <&vdd_3v3_reg>;
+ enable-gpios = <&gpio TEGRA_GPIO(B, 2) GPIO_ACTIVE_HIGH>;
+
+ backlight = <&backlight>;
+ };
+
sound {
compatible = "ad,tegra-audio-wm8903-medcom-wide",
"nvidia,tegra-audio-wm8903";
@@ -64,4 +82,45 @@
<&tegra_car TEGRA20_CLK_CDEV1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
+
+ regulators {
+ vcc_24v_reg: regulator@100 {
+ compatible = "regulator-fixed";
+ reg = <100>;
+ regulator-name = "vcc_24v";
+ regulator-min-microvolt = <24000000>;
+ regulator-max-microvolt = <24000000>;
+ regulator-always-on;
+ };
+
+ vdd_5v0_reg: regulator@101 {
+ compatible = "regulator-fixed";
+ reg = <101>;
+ regulator-name = "vdd_5v0";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ vdd_3v3_reg: regulator@102 {
+ compatible = "regulator-fixed";
+ reg = <102>;
+ regulator-name = "vdd_3v3";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_1v8_reg: regulator@103 {
+ compatible = "regulator-fixed";
+ reg = <103>;
+ regulator-name = "vdd_1v8";
+ vin-supply = <&vdd_3v3_reg>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 9a39a8001f78..d4438e30de45 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -296,7 +296,7 @@
request-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
slave-addr = <138>;
clocks = <&tegra_car TEGRA20_CLK_I2C3>,
- <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
+ <&tegra_car TEGRA20_CLK_PLL_P_OUT3>;
clock-names = "div-clk", "fast-clk";
resets = <&tegra_car 67>;
reset-names = "i2c";
@@ -589,8 +589,8 @@
GPIO_ACTIVE_HIGH>;
clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
- <&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
- <&tegra_car TEGRA20_CLK_CDEV1>;
+ <&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
+ <&tegra_car TEGRA20_CLK_CDEV1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
};
diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
index 29051a2ae0ae..a10b415bbdee 100644
--- a/arch/arm/boot/dts/tegra20-plutux.dts
+++ b/arch/arm/boot/dts/tegra20-plutux.dts
@@ -58,4 +58,45 @@
<&tegra_car TEGRA20_CLK_CDEV1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
+
+ regulators {
+ vcc_24v_reg: regulator@100 {
+ compatible = "regulator-fixed";
+ reg = <100>;
+ regulator-name = "vcc_24v";
+ regulator-min-microvolt = <24000000>;
+ regulator-max-microvolt = <24000000>;
+ regulator-always-on;
+ };
+
+ vdd_5v0_reg: regulator@101 {
+ compatible = "regulator-fixed";
+ reg = <101>;
+ regulator-name = "vdd_5v0";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ vdd_3v3_reg: regulator@102 {
+ compatible = "regulator-fixed";
+ reg = <102>;
+ regulator-name = "vdd_3v3";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_1v8_reg: regulator@103 {
+ compatible = "regulator-fixed";
+ reg = <103>;
+ regulator-name = "vdd_1v8";
+ vin-supply = <&vdd_3v3_reg>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index a1b0d965757f..80e7d386ce34 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -334,6 +334,7 @@
#gpio-cells = <2>;
gpio-controller;
+ /* vdd_5v0_reg must be provided by the base board */
sys-supply = <&vdd_5v0_reg>;
vin-sm0-supply = <&sys_reg>;
vin-sm1-supply = <&sys_reg>;
@@ -473,8 +474,11 @@
};
pcie-controller@80003000 {
- pex-clk-supply = <&pci_clk_reg>;
- vdd-supply = <&pci_vdd_reg>;
+ avdd-pex-supply = <&pci_vdd_reg>;
+ vdd-pex-supply = <&pci_vdd_reg>;
+ avdd-pex-pll-supply = <&pci_vdd_reg>;
+ avdd-plle-supply = <&pci_vdd_reg>;
+ vddio-pex-clk-supply = <&pci_clk_reg>;
};
usb@c5008000 {
@@ -511,15 +515,6 @@
#address-cells = <1>;
#size-cells = <0>;
- vdd_5v0_reg: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "vdd_5v0";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- };
-
pci_vdd_reg: regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
index 890562c667fb..c12d8bead2ee 100644
--- a/arch/arm/boot/dts/tegra20-tec.dts
+++ b/arch/arm/boot/dts/tegra20-tec.dts
@@ -67,4 +67,45 @@
<&tegra_car TEGRA20_CLK_CDEV1>;
clock-names = "pll_a", "pll_a_out0", "mclk";
};
+
+ regulators {
+ vcc_24v_reg: regulator@100 {
+ compatible = "regulator-fixed";
+ reg = <100>;
+ regulator-name = "vcc_24v";
+ regulator-min-microvolt = <24000000>;
+ regulator-max-microvolt = <24000000>;
+ regulator-always-on;
+ };
+
+ vdd_5v0_reg: regulator@101 {
+ compatible = "regulator-fixed";
+ reg = <101>;
+ regulator-name = "vdd_5v0";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ vdd_3v3_reg: regulator@102 {
+ compatible = "regulator-fixed";
+ reg = <102>;
+ regulator-name = "vdd_3v3";
+ vin-supply = <&vcc_24v_reg>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_1v8_reg: regulator@103 {
+ compatible = "regulator-fixed";
+ reg = <103>;
+ regulator-name = "vdd_1v8";
+ vin-supply = <&vdd_3v3_reg>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 216fa6d50c65..5ad87979ab13 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -318,8 +318,12 @@
pcie-controller@80003000 {
status = "okay";
- pex-clk-supply = <&pci_clk_reg>;
- vdd-supply = <&pci_vdd_reg>;
+
+ avdd-pex-supply = <&pci_vdd_reg>;
+ vdd-pex-supply = <&pci_vdd_reg>;
+ avdd-pex-pll-supply = <&pci_vdd_reg>;
+ avdd-plle-supply = <&pci_vdd_reg>;
+ vddio-pex-clk-supply = <&pci_clk_reg>;
pci@1,0 {
status = "okay";
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index a7ddf70df50b..1908f6937e53 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -236,6 +236,12 @@
interrupt-controller;
};
+ apbmisc@70000800 {
+ compatible = "nvidia,tegra20-apbmisc";
+ reg = <0x70000800 0x64 /* Chip revision */
+ 0x70000008 0x04>; /* Strapping options */
+ };
+
pinmux: pinmux@70000014 {
compatible = "nvidia,tegra20-pinmux";
reg = <0x70000014 0x10 /* Tri-state registers */
@@ -545,6 +551,15 @@
#size-cells = <0>;
};
+ fuse@7000f800 {
+ compatible = "nvidia,tegra20-efuse";
+ reg = <0x7000F800 0x400>;
+ clocks = <&tegra_car TEGRA20_CLK_FUSE>;
+ clock-names = "fuse";
+ resets = <&tegra_car 39>;
+ reset-names = "fuse";
+ };
+
pcie-controller@80003000 {
compatible = "nvidia,tegra20-pcie";
device_type = "pci";
@@ -630,6 +645,8 @@
<&tegra_car TEGRA20_CLK_CLK_M>,
<&tegra_car TEGRA20_CLK_USBD>;
clock-names = "reg", "pll_u", "timer", "utmi-pads";
+ resets = <&tegra_car 22>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,has-legacy-mode;
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
@@ -638,6 +655,7 @@
nvidia,xcvr-setup = <9>;
nvidia,xcvr-lsfslew = <1>;
nvidia,xcvr-lsrslew = <1>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -661,6 +679,8 @@
<&tegra_car TEGRA20_CLK_PLL_U>,
<&tegra_car TEGRA20_CLK_CDEV2>;
clock-names = "reg", "pll_u", "ulpi-link";
+ resets = <&tegra_car 58>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
status = "disabled";
};
@@ -685,6 +705,8 @@
<&tegra_car TEGRA20_CLK_CLK_M>,
<&tegra_car TEGRA20_CLK_USBD>;
clock-names = "reg", "pll_u", "timer", "utmi-pads";
+ resets = <&tegra_car 59>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
diff --git a/arch/arm/boot/dts/tegra30-apalis-eval.dts b/arch/arm/boot/dts/tegra30-apalis-eval.dts
new file mode 100644
index 000000000000..45d40f024585
--- /dev/null
+++ b/arch/arm/boot/dts/tegra30-apalis-eval.dts
@@ -0,0 +1,260 @@
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "tegra30-apalis.dtsi"
+
+/ {
+ model = "Toradex Apalis T30 on Apalis Evaluation Board";
+ compatible = "toradex,apalis_t30-eval", "toradex,apalis_t30", "nvidia,tegra30";
+
+ aliases {
+ rtc0 = "/i2c@7000c000/rtc@68";
+ rtc1 = "/i2c@7000d000/tps65911@2d";
+ rtc2 = "/rtc@7000e000";
+ };
+
+ pcie-controller@00003000 {
+ status = "okay";
+
+ pci@1,0 {
+ status = "okay";
+ };
+
+ pci@2,0 {
+ status = "okay";
+ };
+
+ pci@3,0 {
+ status = "okay";
+ };
+ };
+
+ host1x@50000000 {
+ dc@54200000 {
+ rgb {
+ status = "okay";
+ nvidia,panel = <&panel>;
+ };
+ };
+ hdmi@54280000 {
+ status = "okay";
+ };
+ };
+
+ serial@70006000 {
+ status = "okay";
+ };
+
+ serial@70006040 {
+ compatible = "nvidia,tegra30-hsuart";
+ status = "okay";
+ };
+
+ serial@70006200 {
+ compatible = "nvidia,tegra30-hsuart";
+ status = "okay";
+ };
+
+ serial@70006300 {
+ compatible = "nvidia,tegra30-hsuart";
+ status = "okay";
+ };
+
+ pwm@7000a000 {
+ status = "okay";
+ };
+
+ /*
+ * GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier
+ * board)
+ */
+ i2c@7000c000 {
+ status = "okay";
+ clock-frequency = <100000>;
+
+ pcie-switch@58 {
+ compatible = "plx,pex8605";
+ reg = <0x58>;
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc@68 {
+ compatible = "st,m41t00";
+ reg = <0x68>;
+ };
+ };
+
+ /* GEN2_I2C: unused */
+
+ /*
+ * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on
+ * carrier board)
+ */
+ cami2c: i2c@7000c500 {
+ status = "okay";
+ clock-frequency = <400000>;
+ };
+
+ /* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */
+ hdmiddc: i2c@7000c700 {
+ status = "okay";
+ };
+
+ /* SPI1: Apalis SPI1 */
+ spi@7000d400 {
+ status = "okay";
+ spi-max-frequency = <25000000>;
+ spidev0: spidev@1 {
+ compatible = "spidev";
+ reg = <1>;
+ spi-max-frequency = <25000000>;
+ };
+ };
+
+ /* SPI5: Apalis SPI2 */
+ spi@7000dc00 {
+ status = "okay";
+ spi-max-frequency = <25000000>;
+ spidev1: spidev@2 {
+ compatible = "spidev";
+ reg = <2>;
+ spi-max-frequency = <25000000>;
+ };
+ };
+
+ sd1: sdhci@78000000 {
+ status = "okay";
+ bus-width = <4>;
+ /* SD1_CD# */
+ cd-gpios = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ };
+
+ mmc1: sdhci@78000400 {
+ status = "okay";
+ bus-width = <8>;
+ /* MMC1_CD# */
+ cd-gpios = <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_LOW>;
+ no-1-8-v;
+ };
+
+ /* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */
+ usb@7d000000 {
+ status = "okay";
+ };
+
+ usb-phy@7d000000 {
+ status = "okay";
+ vbus-supply = <&usbo1_vbus_reg>;
+ };
+
+ /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
+ usb@7d004000 {
+ status = "okay";
+ };
+
+ usb-phy@7d004000 {
+ status = "okay";
+ vbus-supply = <&usbh_vbus_reg>;
+ };
+
+ /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
+ usb@7d008000 {
+ status = "okay";
+ };
+
+ usb-phy@7d008000 {
+ status = "okay";
+ vbus-supply = <&usbh_vbus_reg>;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+
+ /* PWM0 */
+ pwms = <&pwm 0 5000000>;
+ brightness-levels = <255 231 223 207 191 159 127 0>;
+ default-brightness-level = <6>;
+ /* BKL1_ON */
+ enable-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "Power";
+ gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+
+ panel: panel {
+ /*
+ * edt,et057090dhu: EDT 5.7" LCD TFT
+ * edt,et070080dh6: EDT 7.0" LCD TFT
+ */
+ compatible = "edt,et057090dhu", "simple-panel";
+
+ backlight = <&backlight>;
+ };
+
+ pwmleds {
+ compatible = "pwm-leds";
+
+ pwm1 {
+ label = "PWM1";
+ pwms = <&pwm 3 19600>;
+ max-brightness = <255>;
+ };
+
+ pwm2 {
+ label = "PWM2";
+ pwms = <&pwm 2 19600>;
+ max-brightness = <255>;
+ };
+
+ pwm3 {
+ label = "PWM3";
+ pwms = <&pwm 1 19600>;
+ max-brightness = <255>;
+ };
+ };
+
+ regulators {
+ sys_5v0_reg: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ /* USBO1_EN */
+ usbo1_vbus_reg: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "usbo1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio TEGRA_GPIO(T, 5) GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&sys_5v0_reg>;
+ };
+
+ /* USBH_EN */
+ usbh_vbus_reg: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usbh_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio TEGRA_GPIO(DD, 1) GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&sys_5v0_reg>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/tegra30-apalis.dtsi b/arch/arm/boot/dts/tegra30-apalis.dtsi
new file mode 100644
index 000000000000..8adaa7871dd3
--- /dev/null
+++ b/arch/arm/boot/dts/tegra30-apalis.dtsi
@@ -0,0 +1,678 @@
+#include "tegra30.dtsi"
+
+/*
+ * Toradex Apalis T30 Device Tree
+ * Compatible for Revisions 1GB: V1.0A; 2GB: V1.0B, V1.0C
+ */
+/ {
+ model = "Toradex Apalis T30";
+ compatible = "toradex,apalis_t30", "nvidia,tegra30";
+
+ pcie-controller@00003000 {
+ avdd-pexa-supply = <&vdd2_reg>;
+ vdd-pexa-supply = <&vdd2_reg>;
+ avdd-pexb-supply = <&vdd2_reg>;
+ vdd-pexb-supply = <&vdd2_reg>;
+ avdd-pex-pll-supply = <&vdd2_reg>;
+ avdd-plle-supply = <&ldo6_reg>;
+ vddio-pex-ctl-supply = <&sys_3v3_reg>;
+ hvdd-pex-supply = <&sys_3v3_reg>;
+
+ pci@1,0 {
+ nvidia,num-lanes = <4>;
+ };
+
+ pci@2,0 {
+ nvidia,num-lanes = <1>;
+ };
+
+ pci@3,0 {
+ nvidia,num-lanes = <1>;
+ };
+ };
+
+ host1x@50000000 {
+ hdmi@54280000 {
+ vdd-supply = <&sys_3v3_reg>;
+ pll-supply = <&vio_reg>;
+
+ nvidia,hpd-gpio =
+ <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
+ nvidia,ddc-i2c-bus = <&hdmiddc>;
+ };
+ };
+
+ pinmux@70000868 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&state_default>;
+
+ state_default: pinmux {
+ /* Apalis BKL1_ON */
+ pv2 {
+ nvidia,pins = "pv2";
+ nvidia,function = "rsvd4";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis BKL1_PWM */
+ uart3_rts_n_pc0 {
+ nvidia,pins = "uart3_rts_n_pc0";
+ nvidia,function = "pwm0";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ /* BKL1_PWM_EN#, disable TPS65911 PMIC PWM backlight */
+ uart3_cts_n_pa1 {
+ nvidia,pins = "uart3_cts_n_pa1";
+ nvidia,function = "rsvd1";
+ nvidia,pull = <TEGRA_PIN_PULL_UP>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis CAN1 on SPI6 */
+ spi2_cs0_n_px3 {
+ nvidia,pins = "spi2_cs0_n_px3",
+ "spi2_miso_px1",
+ "spi2_mosi_px0",
+ "spi2_sck_px2";
+ nvidia,function = "spi6";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ /* CAN_INT1 */
+ spi2_cs1_n_pw2 {
+ nvidia,pins = "spi2_cs1_n_pw2";
+ nvidia,function = "spi3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis CAN2 on SPI4 */
+ gmi_a16_pj7 {
+ nvidia,pins = "gmi_a16_pj7",
+ "gmi_a17_pb0",
+ "gmi_a18_pb1",
+ "gmi_a19_pk7";
+ nvidia,function = "spi4";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ /* CAN_INT2 */
+ spi2_cs2_n_pw3 {
+ nvidia,pins = "spi2_cs2_n_pw3";
+ nvidia,function = "spi3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis I2C3 */
+ cam_i2c_scl_pbb1 {
+ nvidia,pins = "cam_i2c_scl_pbb1",
+ "cam_i2c_sda_pbb2";
+ nvidia,function = "i2c3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ nvidia,lock = <TEGRA_PIN_DISABLE>;
+ nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis MMC1 */
+ sdmmc3_clk_pa6 {
+ nvidia,pins = "sdmmc3_clk_pa6",
+ "sdmmc3_cmd_pa7";
+ nvidia,function = "sdmmc3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ sdmmc3_dat0_pb7 {
+ nvidia,pins = "sdmmc3_dat0_pb7",
+ "sdmmc3_dat1_pb6",
+ "sdmmc3_dat2_pb5",
+ "sdmmc3_dat3_pb4",
+ "sdmmc3_dat4_pd1",
+ "sdmmc3_dat5_pd0",
+ "sdmmc3_dat6_pd3",
+ "sdmmc3_dat7_pd4";
+ nvidia,function = "sdmmc3";
+ nvidia,pull = <TEGRA_PIN_PULL_UP>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ /* Apalis MMC1_CD# */
+ pv3 {
+ nvidia,pins = "pv3";
+ nvidia,function = "rsvd2";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis PWM1 */
+ gpio_pu6 {
+ nvidia,pins = "gpio_pu6";
+ nvidia,function = "pwm3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis PWM2 */
+ gpio_pu5 {
+ nvidia,pins = "gpio_pu5";
+ nvidia,function = "pwm2";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis PWM3 */
+ gpio_pu4 {
+ nvidia,pins = "gpio_pu4";
+ nvidia,function = "pwm1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis PWM4 */
+ gpio_pu3 {
+ nvidia,pins = "gpio_pu3";
+ nvidia,function = "pwm0";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis RESET_MOCI# */
+ gmi_rst_n_pi4 {
+ nvidia,pins = "gmi_rst_n_pi4";
+ nvidia,function = "gmi";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis SD1 */
+ sdmmc1_clk_pz0 {
+ nvidia,pins = "sdmmc1_clk_pz0";
+ nvidia,function = "sdmmc1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ sdmmc1_cmd_pz1 {
+ nvidia,pins = "sdmmc1_cmd_pz1",
+ "sdmmc1_dat0_py7",
+ "sdmmc1_dat1_py6",
+ "sdmmc1_dat2_py5",
+ "sdmmc1_dat3_py4";
+ nvidia,function = "sdmmc1";
+ nvidia,pull = <TEGRA_PIN_PULL_UP>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ /* Apalis SD1_CD# */
+ clk2_req_pcc5 {
+ nvidia,pins = "clk2_req_pcc5";
+ nvidia,function = "rsvd2";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis SPI1 */
+ spi1_sck_px5 {
+ nvidia,pins = "spi1_sck_px5",
+ "spi1_mosi_px4",
+ "spi1_miso_px7",
+ "spi1_cs0_n_px6";
+ nvidia,function = "spi1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis SPI2 */
+ lcd_sck_pz4 {
+ nvidia,pins = "lcd_sck_pz4",
+ "lcd_sdout_pn5",
+ "lcd_sdin_pz2",
+ "lcd_cs0_n_pn4";
+ nvidia,function = "spi5";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis UART1 */
+ ulpi_data0 {
+ nvidia,pins = "ulpi_data0_po1",
+ "ulpi_data1_po2",
+ "ulpi_data2_po3",
+ "ulpi_data3_po4",
+ "ulpi_data4_po5",
+ "ulpi_data5_po6",
+ "ulpi_data6_po7",
+ "ulpi_data7_po0";
+ nvidia,function = "uarta";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis UART2 */
+ ulpi_clk_py0 {
+ nvidia,pins = "ulpi_clk_py0",
+ "ulpi_dir_py1",
+ "ulpi_nxt_py2",
+ "ulpi_stp_py3";
+ nvidia,function = "uartd";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis UART3 */
+ uart2_rxd_pc3 {
+ nvidia,pins = "uart2_rxd_pc3",
+ "uart2_txd_pc2";
+ nvidia,function = "uartb";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis UART4 */
+ uart3_rxd_pw7 {
+ nvidia,pins = "uart3_rxd_pw7",
+ "uart3_txd_pw6";
+ nvidia,function = "uartc";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis USBO1_EN */
+ gen2_i2c_scl_pt5 {
+ nvidia,pins = "gen2_i2c_scl_pt5";
+ nvidia,function = "rsvd4";
+ nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Apalis USBO1_OC# */
+ gen2_i2c_sda_pt6 {
+ nvidia,pins = "gen2_i2c_sda_pt6";
+ nvidia,function = "rsvd4";
+ nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* Apalis WAKE1_MICO */
+ pv1 {
+ nvidia,pins = "pv1";
+ nvidia,function = "rsvd1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* eMMC (On-module) */
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4",
+ "sdmmc4_rst_n_pcc3";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <TEGRA_PIN_PULL_UP>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* LVDS Transceiver Configuration */
+ pbb0 {
+ nvidia,pins = "pbb0",
+ "pbb7",
+ "pcc1",
+ "pcc2";
+ nvidia,function = "rsvd2";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,lock = <TEGRA_PIN_DISABLE>;
+ };
+ pbb3 {
+ nvidia,pins = "pbb3",
+ "pbb4",
+ "pbb5",
+ "pbb6";
+ nvidia,function = "displayb";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,lock = <TEGRA_PIN_DISABLE>;
+ };
+
+ /* Power I2C (On-module) */
+ pwr_i2c_scl_pz6 {
+ nvidia,pins = "pwr_i2c_scl_pz6",
+ "pwr_i2c_sda_pz7";
+ nvidia,function = "i2cpwr";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ nvidia,lock = <TEGRA_PIN_DISABLE>;
+ nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+ };
+
+ /*
+ * THERMD_ALERT#, unlatched I2C address pin of LM95245
+ * temperature sensor therefore requires disabling for
+ * now
+ */
+ lcd_dc1_pd2 {
+ nvidia,pins = "lcd_dc1_pd2";
+ nvidia,function = "rsvd3";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+
+ /* TOUCH_PEN_INT# */
+ pv0 {
+ nvidia,pins = "pv0";
+ nvidia,function = "rsvd1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ };
+ };
+ };
+
+ hdmiddc: i2c@7000c700 {
+ clock-frequency = <100000>;
+ };
+
+ /*
+ * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+ * touch screen controller
+ */
+ i2c@7000d000 {
+ status = "okay";
+ clock-frequency = <100000>;
+
+ pmic: tps65911@2d {
+ compatible = "ti,tps65911";
+ reg = <0x2d>;
+
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+
+ ti,system-power-controller;
+
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ vcc1-supply = <&sys_3v3_reg>;
+ vcc2-supply = <&sys_3v3_reg>;
+ vcc3-supply = <&vio_reg>;
+ vcc4-supply = <&sys_3v3_reg>;
+ vcc5-supply = <&sys_3v3_reg>;
+ vcc6-supply = <&vio_reg>;
+ vcc7-supply = <&sys_5v0_reg>;
+ vccio-supply = <&sys_3v3_reg>;
+
+ regulators {
+ /* SW1: +V1.35_VDDIO_DDR */
+ vdd1_reg: vdd1 {
+ regulator-name = "vddio_ddr_1v35";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ };
+
+ /* SW2: +V1.05 */
+ vdd2_reg: vdd2 {
+ regulator-name =
+ "vdd_pexa,vdd_pexb,vdd_sata";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ /* SW CTRL: +V1.0_VDD_CPU */
+ vddctrl_reg: vddctrl {
+ regulator-name = "vdd_cpu,vdd_sys";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-always-on;
+ };
+
+ /* SWIO: +V1.8 */
+ vio_reg: vio {
+ regulator-name = "vdd_1v8_gen";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ /* LDO1: unused */
+
+ /*
+ * EN_+V3.3 switching via FET:
+ * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
+ * see also v3_3 fixed supply
+ */
+ ldo2_reg: ldo2 {
+ regulator-name = "en_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ /* +V1.2_CSI */
+ ldo3_reg: ldo3 {
+ regulator-name =
+ "avdd_dsi_csi,pwrdet_mipi";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ /* +V1.2_VDD_RTC */
+ ldo4_reg: ldo4 {
+ regulator-name = "vdd_rtc";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ /*
+ * +V2.8_AVDD_VDAC:
+ * only required for analog RGB
+ */
+ ldo5_reg: ldo5 {
+ regulator-name = "avdd_vdac";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ /*
+ * +V1.05_AVDD_PLLE: avdd_plle should be 1.05V
+ * but LDO6 can't set voltage in 50mV
+ * granularity
+ */
+ ldo6_reg: ldo6 {
+ regulator-name = "avdd_plle";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ /* +V1.2_AVDD_PLL */
+ ldo7_reg: ldo7 {
+ regulator-name = "avdd_pll";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ /* +V1.0_VDD_DDR_HS */
+ ldo8_reg: ldo8 {
+ regulator-name = "vdd_ddr_hs";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ };
+ };
+ };
+
+ /* STMPE811 touch screen controller */
+ stmpe811@41 {
+ compatible = "st,stmpe811";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x41>;
+ interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
+ interrupt-controller;
+ id = <0>;
+ blocks = <0x5>;
+ irq-trigger = <0x1>;
+
+ stmpe_touchscreen {
+ compatible = "st,stmpe-ts";
+ reg = <0>;
+ /* 3.25 MHz ADC clock speed */
+ st,adc-freq = <1>;
+ /* 8 sample average control */
+ st,ave-ctrl = <3>;
+ /* 7 length fractional part in z */
+ st,fraction-z = <7>;
+ /*
+ * 50 mA typical 80 mA max touchscreen drivers
+ * current limit value
+ */
+ st,i-drive = <1>;
+ /* 12-bit ADC */
+ st,mod-12b = <1>;
+ /* internal ADC reference */
+ st,ref-sel = <0>;
+ /* ADC converstion time: 80 clocks */
+ st,sample-time = <4>;
+ /* 1 ms panel driver settling time */
+ st,settling = <3>;
+ /* 5 ms touch detect interrupt delay */
+ st,touch-det-delay = <5>;
+ };
+ };
+
+ /*
+ * LM95245 temperature sensor
+ * Note: OVERT_N directly connected to PMIC PWRDN
+ */
+ temp-sensor@4c {
+ compatible = "national,lm95245";
+ reg = <0x4c>;
+ };
+
+ /* SW: +V1.2_VDD_CORE */
+ tps62362@60 {
+ compatible = "ti,tps62362";
+ reg = <0x60>;
+
+ regulator-name = "tps62362-vout";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ ti,vsel0-state-low;
+ /* VSEL1: EN_CORE_DVFS_N low for DVFS */
+ ti,vsel1-state-low;
+ };
+ };
+
+ /* SPI4: CAN2 */
+ spi@7000da00 {
+ status = "okay";
+ spi-max-frequency = <10000000>;
+
+ can@1 {
+ compatible = "microchip,mcp2515";
+ reg = <1>;
+ clocks = <&clk16m>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>;
+ spi-max-frequency = <10000000>;
+ };
+ };
+
+ /* SPI6: CAN1 */
+ spi@7000de00 {
+ status = "okay";
+ spi-max-frequency = <10000000>;
+
+ can@0 {
+ compatible = "microchip,mcp2515";
+ reg = <0>;
+ clocks = <&clk16m>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(W, 2) GPIO_ACTIVE_LOW>;
+ spi-max-frequency = <10000000>;
+ };
+ };
+
+ pmc@7000e400 {
+ nvidia,invert-interrupt;
+ nvidia,suspend-mode = <1>;
+ nvidia,cpu-pwr-good-time = <5000>;
+ nvidia,cpu-pwr-off-time = <5000>;
+ nvidia,core-pwr-good-time = <3845 3845>;
+ nvidia,core-pwr-off-time = <0>;
+ nvidia,core-power-req-active-high;
+ nvidia,sys-clock-req-active-high;
+ };
+
+ sdhci@78000600 {
+ status = "okay";
+ bus-width = <8>;
+ non-removable;
+ };
+
+ clocks {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clk32k_in: clk@0 {
+ compatible = "fixed-clock";
+ reg=<0>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+ clk16m: clk@1 {
+ compatible = "fixed-clock";
+ reg=<1>;
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ clock-output-names = "clk16m";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sys_3v3_reg: regulator@100 {
+ compatible = "regulator-fixed";
+ reg = <100>;
+ regulator-name = "3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
index 3189791a9289..cee8f2246fdb 100644
--- a/arch/arm/boot/dts/tegra30-beaver.dts
+++ b/arch/arm/boot/dts/tegra30-beaver.dts
@@ -17,9 +17,15 @@
pcie-controller@00003000 {
status = "okay";
- pex-clk-supply = <&sys_3v3_pexs_reg>;
- vdd-supply = <&ldo1_reg>;
- avdd-supply = <&ldo2_reg>;
+
+ avdd-pexa-supply = <&ldo1_reg>;
+ vdd-pexa-supply = <&ldo1_reg>;
+ avdd-pexb-supply = <&ldo1_reg>;
+ vdd-pexb-supply = <&ldo1_reg>;
+ avdd-pex-pll-supply = <&ldo1_reg>;
+ avdd-plle-supply = <&ldo1_reg>;
+ vddio-pex-ctl-supply = <&sys_3v3_reg>;
+ hvdd-pex-supply = <&sys_3v3_pexs_reg>;
pci@1,0 {
status = "okay";
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index 0cf0848a82d8..206379546244 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -38,9 +38,14 @@
pcie-controller@00003000 {
status = "okay";
- pex-clk-supply = <&pex_hvdd_3v3_reg>;
- vdd-supply = <&ldo1_reg>;
- avdd-supply = <&ldo2_reg>;
+
+ /* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
+ avdd-pexb-supply = <&ldo1_reg>;
+ vdd-pexb-supply = <&ldo1_reg>;
+ avdd-pex-pll-supply = <&ldo1_reg>;
+ hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
+ vddio-pex-ctl-supply = <&sys_3v3_reg>;
+ avdd-plle-supply = <&ldo2_reg>;
pci@1,0 {
nvidia,num-lanes = <4>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index dec4fc823901..6b35c29278d7 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -335,6 +335,12 @@
interrupt-controller;
};
+ apbmisc@70000800 {
+ compatible = "nvidia,tegra30-apbmisc", "nvidia,tegra20-apbmisc";
+ reg = <0x70000800 0x64 /* Chip revision */
+ 0x70000008 0x04>; /* Strapping options */
+ };
+
pinmux: pinmux@70000868 {
compatible = "nvidia,tegra30-pinmux";
reg = <0x70000868 0xd4 /* Pad control registers */
@@ -631,6 +637,15 @@
nvidia,ahb = <&ahb>;
};
+ fuse@7000f800 {
+ compatible = "nvidia,tegra30-efuse";
+ reg = <0x7000f800 0x400>;
+ clocks = <&tegra_car TEGRA30_CLK_FUSE>;
+ clock-names = "fuse";
+ resets = <&tegra_car 39>;
+ reset-names = "fuse";
+ };
+
ahub@70080000 {
compatible = "nvidia,tegra30-ahub";
reg = <0x70080000 0x200
@@ -775,6 +790,8 @@
<&tegra_car TEGRA30_CLK_PLL_U>,
<&tegra_car TEGRA30_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 22>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
@@ -786,6 +803,7 @@
nvidia,xcvr-hsslew = <32>;
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -809,6 +827,8 @@
<&tegra_car TEGRA30_CLK_PLL_U>,
<&tegra_car TEGRA30_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 58>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <9>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
@@ -843,6 +863,8 @@
<&tegra_car TEGRA30_CLK_PLL_U>,
<&tegra_car TEGRA30_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
+ resets = <&tegra_car 59>, <&tegra_car 22>;
+ reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,elastic-limit = <16>;
diff --git a/arch/arm/boot/dts/tny_a9260_common.dtsi b/arch/arm/boot/dts/tny_a9260_common.dtsi
index 0e6d3de2e09e..ce7138c3af1b 100644
--- a/arch/arm/boot/dts/tny_a9260_common.dtsi
+++ b/arch/arm/boot/dts/tny_a9260_common.dtsi
@@ -24,6 +24,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/tny_a9263.dts b/arch/arm/boot/dts/tny_a9263.dts
index 0751a6a979a8..3043296345b7 100644
--- a/arch/arm/boot/dts/tny_a9263.dts
+++ b/arch/arm/boot/dts/tny_a9263.dts
@@ -29,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
index 285977682cf3..12edafefd44a 100644
--- a/arch/arm/boot/dts/usb_a9260_common.dtsi
+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
@@ -16,6 +16,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/usb_a9263.dts b/arch/arm/boot/dts/usb_a9263.dts
index 290e60383baf..68c0de36c339 100644
--- a/arch/arm/boot/dts/usb_a9263.dts
+++ b/arch/arm/boot/dts/usb_a9263.dts
@@ -29,6 +29,14 @@
compatible = "atmel,osc", "fixed-clock";
clock-frequency = <12000000>;
};
+
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
+ main_xtal {
+ clock-frequency = <12000000>;
+ };
};
ahb {
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
index e01e5a081def..27d0d9c8adf3 100644
--- a/arch/arm/boot/dts/versatile-ab.dts
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -15,10 +15,49 @@
i2c0 = &i2c0;
};
+ chosen {
+ stdout-path = &uart0;
+ };
+
memory {
reg = <0x0 0x08000000>;
};
+ xtal24mhz: xtal24mhz@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+
+ core-module@10000000 {
+ compatible = "arm,core-module-versatile", "syscon";
+ reg = <0x10000000 0x200>;
+
+ /* OSC1 on AB, OSC4 on PB */
+ osc1: cm_aux_osc@24M {
+ #clock-cells = <0>;
+ compatible = "arm,versatile-cm-auxosc";
+ clocks = <&xtal24mhz>;
+ };
+
+ /* The timer clock is the 24 MHz oscillator divided to 1MHz */
+ timclk: timclk@1M {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clock-div = <24>;
+ clock-mult = <1>;
+ clocks = <&xtal24mhz>;
+ };
+
+ pclk: pclk@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clock-div = <1>;
+ clock-mult = <1>;
+ clocks = <&xtal24mhz>;
+ };
+ };
+
flash@34000000 {
compatible = "arm,versatile-flash";
reg = <0x34000000 0x4000000>;
@@ -59,6 +98,8 @@
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x10140000 0x1000>;
+ clear-mask = <0xffffffff>;
+ valid-mask = <0xffffffff>;
};
sic: intc@10003000 {
@@ -68,69 +109,93 @@
reg = <0x10003000 0x1000>;
interrupt-parent = <&vic>;
interrupts = <31>; /* Cascaded to vic */
+ clear-mask = <0xffffffff>;
+ valid-mask = <0xffc203f8>;
};
dma@10130000 {
compatible = "arm,pl081", "arm,primecell";
reg = <0x10130000 0x1000>;
interrupts = <17>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
uart0: uart@101f1000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f1000 0x1000>;
interrupts = <12>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "uartclk", "apb_pclk";
};
uart1: uart@101f2000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f2000 0x1000>;
interrupts = <13>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "uartclk", "apb_pclk";
};
uart2: uart@101f3000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x101f3000 0x1000>;
interrupts = <14>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "uartclk", "apb_pclk";
};
smc@10100000 {
compatible = "arm,primecell";
reg = <0x10100000 0x1000>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
mpmc@10110000 {
compatible = "arm,primecell";
reg = <0x10110000 0x1000>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
display@10120000 {
compatible = "arm,pl110", "arm,primecell";
reg = <0x10120000 0x1000>;
interrupts = <16>;
+ clocks = <&osc1>, <&pclk>;
+ clock-names = "clcd", "apb_pclk";
};
sctl@101e0000 {
compatible = "arm,primecell";
reg = <0x101e0000 0x1000>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
watchdog@101e1000 {
compatible = "arm,primecell";
reg = <0x101e1000 0x1000>;
interrupts = <0>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
timer@101e2000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x101e2000 0x1000>;
interrupts = <4>;
+ clocks = <&timclk>, <&timclk>, <&pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
};
timer@101e3000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x101e3000 0x1000>;
interrupts = <5>;
+ clocks = <&timclk>, <&timclk>, <&pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
};
gpio0: gpio@101e4000 {
@@ -141,6 +206,8 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
gpio1: gpio@101e5000 {
@@ -151,24 +218,32 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
rtc@101e8000 {
compatible = "arm,pl030", "arm,primecell";
reg = <0x101e8000 0x1000>;
interrupts = <10>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
sci@101f0000 {
compatible = "arm,primecell";
reg = <0x101f0000 0x1000>;
interrupts = <15>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
ssp@101f4000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x101f4000 0x1000>;
interrupts = <11>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "SSPCLK", "apb_pclk";
};
fpga {
@@ -181,23 +256,31 @@
compatible = "arm,primecell";
reg = <0x4000 0x1000>;
interrupts = <24>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
mmc@5000 {
- compatible = "arm,primecell";
+ compatible = "arm,pl180", "arm,primecell";
reg = < 0x5000 0x1000>;
interrupts-extended = <&vic 22 &sic 2>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "mclk", "apb_pclk";
};
kmi@6000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x6000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <3>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
};
kmi@7000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x7000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <4>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
};
};
};
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 65f657711323..e36c1e82fea7 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -13,6 +13,8 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
gpio3: gpio@101e7000 {
@@ -23,6 +25,8 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
};
fpga {
@@ -31,20 +35,24 @@
reg = <0x9000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <6>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "uartclk", "apb_pclk";
};
sci@a000 {
compatible = "arm,primecell";
reg = <0xa000 0x1000>;
interrupt-parent = <&sic>;
interrupts = <5>;
+ clocks = <&xtal24mhz>;
+ clock-names = "apb_pclk";
};
mmc@b000 {
- compatible = "arm,primecell";
+ compatible = "arm,pl180", "arm,primecell";
reg = <0xb000 0x1000>;
interrupts-extended = <&vic 23 &sic 2>;
+ clocks = <&xtal24mhz>, <&pclk>;
+ clock-names = "mclk", "apb_pclk";
};
};
};
};
-
-#include <testcases.dtsi>
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 6cc314e7b8fb..583dd363c9dc 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -14,6 +14,8 @@
/ {
aliases {
+ can0 = &can0;
+ can1 = &can1;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -103,6 +105,16 @@
<&clks VF610_CLK_DMAMUX1>;
};
+ can0: flexcan@40020000 {
+ compatible = "fsl,vf610-flexcan";
+ reg = <0x40020000 0x4000>;
+ interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_FLEXCAN0>,
+ <&clks VF610_CLK_FLEXCAN0>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
uart0: serial@40027000 {
compatible = "fsl,vf610-lpuart";
reg = <0x40027000 0x1000>;
@@ -362,7 +374,7 @@
esdhc1: esdhc@400b2000 {
compatible = "fsl,imx53-esdhc";
- reg = <0x400b2000 0x4000>;
+ reg = <0x400b2000 0x1000>;
interrupts = <0 28 0x04>;
clocks = <&clks VF610_CLK_IPG_BUS>,
<&clks VF610_CLK_PLATFORM_BUS>,
@@ -405,6 +417,17 @@
clock-names = "ipg", "ahb", "ptp";
status = "disabled";
};
+
+ can1: flexcan@400d4000 {
+ compatible = "fsl,vf610-flexcan";
+ reg = <0x400d4000 0x4000>;
+ interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_FLEXCAN1>,
+ <&clks VF610_CLK_FLEXCAN1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
};
};
};
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 760bbc463c5b..6cc83d4c6c76 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -65,6 +65,48 @@
interrupt-parent = <&intc>;
ranges;
+ adc@f8007100 {
+ compatible = "xlnx,zynq-xadc-1.00.a";
+ reg = <0xf8007100 0x20>;
+ interrupts = <0 7 4>;
+ interrupt-parent = <&intc>;
+ clocks = <&clkc 12>;
+ };
+
+ can0: can@e0008000 {
+ compatible = "xlnx,zynq-can-1.0";
+ status = "disabled";
+ clocks = <&clkc 19>, <&clkc 36>;
+ clock-names = "can_clk", "pclk";
+ reg = <0xe0008000 0x1000>;
+ interrupts = <0 28 4>;
+ interrupt-parent = <&intc>;
+ tx-fifo-depth = <0x40>;
+ rx-fifo-depth = <0x40>;
+ };
+
+ can1: can@e0009000 {
+ compatible = "xlnx,zynq-can-1.0";
+ status = "disabled";
+ clocks = <&clkc 20>, <&clkc 37>;
+ clock-names = "can_clk", "pclk";
+ reg = <0xe0009000 0x1000>;
+ interrupts = <0 51 4>;
+ interrupt-parent = <&intc>;
+ tx-fifo-depth = <0x40>;
+ rx-fifo-depth = <0x40>;
+ };
+
+ gpio0: gpio@e000a000 {
+ compatible = "xlnx,zynq-gpio-1.0";
+ #gpio-cells = <2>;
+ clocks = <&clkc 42>;
+ gpio-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <0 20 4>;
+ reg = <0xe000a000 0x1000>;
+ };
+
i2c0: i2c@e0004000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
@@ -105,23 +147,47 @@
};
uart0: serial@e0000000 {
- compatible = "xlnx,xuartps";
+ compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
clocks = <&clkc 23>, <&clkc 40>;
- clock-names = "ref_clk", "aper_clk";
+ clock-names = "uart_clk", "pclk";
reg = <0xE0000000 0x1000>;
interrupts = <0 27 4>;
};
uart1: serial@e0001000 {
- compatible = "xlnx,xuartps";
+ compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
clocks = <&clkc 24>, <&clkc 41>;
- clock-names = "ref_clk", "aper_clk";
+ clock-names = "uart_clk", "pclk";
reg = <0xE0001000 0x1000>;
interrupts = <0 50 4>;
};
+ spi0: spi@e0006000 {
+ compatible = "xlnx,zynq-spi-r1p6";
+ reg = <0xe0006000 0x1000>;
+ status = "disabled";
+ interrupt-parent = <&intc>;
+ interrupts = <0 26 4>;
+ clocks = <&clkc 25>, <&clkc 34>;
+ clock-names = "ref_clk", "pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@e0007000 {
+ compatible = "xlnx,zynq-spi-r1p6";
+ reg = <0xe0007000 0x1000>;
+ status = "disabled";
+ interrupt-parent = <&intc>;
+ interrupts = <0 49 4>;
+ clocks = <&clkc 26>, <&clkc 35>;
+ clock-names = "ref_clk", "pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
gem0: ethernet@e000b000 {
compatible = "cdns,gem";
reg = <0xe000b000 0x4000>;
@@ -186,6 +252,22 @@
};
};
+ dmac_s: dmac@f8003000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xf8003000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 13 4>,
+ <0 14 4>, <0 15 4>,
+ <0 16 4>, <0 17 4>,
+ <0 40 4>, <0 41 4>,
+ <0 42 4>, <0 43 4>;
+ #dma-cells = <1>;
+ #dma-channels = <8>;
+ #dma-requests = <4>;
+ clocks = <&clkc 27>;
+ clock-names = "apb_pclk";
+ };
+
devcfg: devcfg@f8007000 {
compatible = "xlnx,zynq-devcfg-1.0";
reg = <0xf8007000 0x100>;
diff --git a/arch/arm/boot/dts/zynq-parallella.dts b/arch/arm/boot/dts/zynq-parallella.dts
new file mode 100644
index 000000000000..41afd9da6876
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-parallella.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * Derived from zynq-zed.dts:
+ *
+ * Copyright (C) 2011 Xilinx
+ * Copyright (C) 2012 National Instruments Corp.
+ * Copyright (C) 2013 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+ model = "Adapteva Parallella Board";
+ compatible = "adapteva,parallella", "xlnx,zynq-7000";
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait";
+ linux,stdout-path = "/amba/serial@e0001000";
+ };
+};
+
+&gem0 {
+ status = "okay";
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethernet_phy>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet_phy: ethernet-phy@0 {
+ /* Marvell 88E1318 */
+ compatible = "ethernet-phy-id0141.0e90",
+ "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ marvell,reg-init = <0x3 0x10 0xff00 0x1e>,
+ <0x3 0x11 0xfff0 0xa>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&sdhci1 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index 5e09cee33d42..835c3089c61c 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -29,6 +29,10 @@
};
+&can0 {
+ status = "okay";
+};
+
&gem0 {
status = "okay";
phy-mode = "rgmii";
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index 490f3dced749..6eaddc47c43d 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -58,16 +58,6 @@ static int read_mpidr(void)
}
/*
- * Get a global nanosecond time stamp for tracing.
- */
-static s64 get_ns(void)
-{
- struct timespec ts;
- getnstimeofday(&ts);
- return timespec_to_ns(&ts);
-}
-
-/*
* bL switcher core code.
*/
@@ -224,7 +214,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
*/
local_irq_disable();
local_fiq_disable();
- trace_cpu_migrate_begin(get_ns(), ob_mpidr);
+ trace_cpu_migrate_begin(ktime_get_real_ns(), ob_mpidr);
/* redirect GIC's SGIs to our counterpart */
gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
@@ -267,7 +257,7 @@ static int bL_switch_to(unsigned int new_cluster_id)
tdev->evtdev->next_event, 1);
}
- trace_cpu_migrate_finish(get_ns(), ib_mpidr);
+ trace_cpu_migrate_finish(ktime_get_real_ns(), ib_mpidr);
local_fiq_enable();
local_irq_enable();
@@ -558,7 +548,7 @@ int bL_switcher_get_logical_index(u32 mpidr)
static void bL_switcher_trace_trigger_cpu(void *__always_unused info)
{
- trace_cpu_migrate_current(get_ns(), read_mpidr());
+ trace_cpu_migrate_current(ktime_get_real_ns(), read_mpidr());
}
int bL_switcher_trace_trigger(void)
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 485be42519b9..88099175fc56 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -1414,6 +1414,34 @@ void edma_clear_event(unsigned channel)
}
EXPORT_SYMBOL(edma_clear_event);
+/*
+ * edma_assign_channel_eventq - move given channel to desired eventq
+ * Arguments:
+ * channel - channel number
+ * eventq_no - queue to move the channel
+ *
+ * Can be used to move a channel to a selected event queue.
+ */
+void edma_assign_channel_eventq(unsigned channel, enum dma_event_q eventq_no)
+{
+ unsigned ctlr;
+
+ ctlr = EDMA_CTLR(channel);
+ channel = EDMA_CHAN_SLOT(channel);
+
+ if (channel >= edma_cc[ctlr]->num_channels)
+ return;
+
+ /* default to low priority queue */
+ if (eventq_no == EVENTQ_DEFAULT)
+ eventq_no = edma_cc[ctlr]->default_queue;
+ if (eventq_no >= edma_cc[ctlr]->num_tc)
+ return;
+
+ map_dmach_queue(ctlr, channel, eventq_no);
+}
+EXPORT_SYMBOL(edma_assign_channel_eventq);
+
static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
struct edma *edma_cc)
{
@@ -1470,7 +1498,8 @@ static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
queue_priority_map[i][1] = -1;
pdata->queue_priority_mapping = queue_priority_map;
- pdata->default_queue = 0;
+ /* Default queue has the lowest priority */
+ pdata->default_queue = i - 1;
return 0;
}
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c
index f91136ab447e..3c165fc2dce2 100644
--- a/arch/arm/common/mcpm_entry.c
+++ b/arch/arm/common/mcpm_entry.c
@@ -12,11 +12,13 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irqflags.h>
+#include <linux/cpu_pm.h>
#include <asm/mcpm.h>
#include <asm/cacheflush.h>
#include <asm/idmap.h>
#include <asm/cputype.h>
+#include <asm/suspend.h>
extern unsigned long mcpm_entry_vectors[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER];
@@ -146,6 +148,56 @@ int mcpm_cpu_powered_up(void)
return 0;
}
+#ifdef CONFIG_ARM_CPU_SUSPEND
+
+static int __init nocache_trampoline(unsigned long _arg)
+{
+ void (*cache_disable)(void) = (void *)_arg;
+ unsigned int mpidr = read_cpuid_mpidr();
+ unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ phys_reset_t phys_reset;
+
+ mcpm_set_entry_vector(cpu, cluster, cpu_resume);
+ setup_mm_for_reboot();
+
+ __mcpm_cpu_going_down(cpu, cluster);
+ BUG_ON(!__mcpm_outbound_enter_critical(cpu, cluster));
+ cache_disable();
+ __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+ __mcpm_cpu_down(cpu, cluster);
+
+ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
+ phys_reset(virt_to_phys(mcpm_entry_point));
+ BUG();
+}
+
+int __init mcpm_loopback(void (*cache_disable)(void))
+{
+ int ret;
+
+ /*
+ * We're going to soft-restart the current CPU through the
+ * low-level MCPM code by leveraging the suspend/resume
+ * infrastructure. Let's play it safe by using cpu_pm_enter()
+ * in case the CPU init code path resets the VFP or similar.
+ */
+ local_irq_disable();
+ local_fiq_disable();
+ ret = cpu_pm_enter();
+ if (!ret) {
+ ret = cpu_suspend((unsigned long)cache_disable, nocache_trampoline);
+ cpu_pm_exit();
+ }
+ local_fiq_enable();
+ local_irq_enable();
+ if (ret)
+ pr_err("%s returned %d\n", __func__, ret);
+ return ret;
+}
+
+#endif
+
struct sync_struct mcpm_sync;
/*
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index fd6bff0c5b96..19211324772f 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -233,13 +233,13 @@ static void __init sp804_of_init(struct device_node *np)
if (IS_ERR(clk1))
clk1 = NULL;
- /* Get the 2nd clock if the timer has 2 timer clocks */
+ /* Get the 2nd clock if the timer has 3 timer clocks */
if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) {
clk2 = of_clk_get(np, 1);
if (IS_ERR(clk2)) {
pr_err("sp804: %s clock not found: %d\n", np->name,
(int)PTR_ERR(clk2));
- goto err;
+ clk2 = NULL;
}
} else
clk2 = clk1;
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index 065adddeee3e..d9675c68a399 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -96,6 +96,7 @@ CONFIG_I2C_GPIO=y
CONFIG_I2C_SH_MOBILE=y
# CONFIG_HWMON is not set
CONFIG_REGULATOR=y
+CONFIG_REGULATOR_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
@@ -127,6 +128,9 @@ CONFIG_USB_ETH=m
CONFIG_MMC=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_S35390A=y
CONFIG_DMADEVICES=y
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index 4bf72264b175..fbebcbce1e8c 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -27,6 +27,7 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM_MOBILE=y
CONFIG_ARM_THUMBEE=y
+CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
# CONFIG_COMPACTION is not set
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index e07a227ec0db..fc7d1683bf67 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -8,15 +8,17 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=3
-CONFIG_S3C24XX_PWM=y
-CONFIG_ARCH_EXYNOS5=y
-CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_ARCH_EXYNOS3=y
+CONFIG_EXYNOS5420_MCPM=y
CONFIG_SMP=y
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_BL_SWITCHER_DUMMY_IF=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_CMA=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ARM_APPENDED_DTB=y
@@ -24,6 +26,7 @@ CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
CONFIG_VFP=y
CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -34,6 +37,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_PROC_DEVICETREE=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
@@ -66,11 +71,22 @@ CONFIG_I2C=y
CONFIG_I2C_MUX=y
CONFIG_I2C_ARB_GPIO_CHALLENGE=y
CONFIG_I2C_EXYNOS5=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_SPI=y
+CONFIG_SPI_S3C64XX=y
CONFIG_I2C_S3C2410=y
CONFIG_DEBUG_GPIO=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_CHARGER_TPS65090=y
# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_EXYNOS_THERMAL_CORE=y
+CONFIG_WATCHDOG=y
+CONFIG_S3C2410_WATCHDOG=y
CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_MFD_CROS_EC_SPI=y
CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_SEC_CORE=y
@@ -80,6 +96,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_MAX8997=y
CONFIG_REGULATOR_MAX77686=y
+CONFIG_REGULATOR_S2MPA01=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_S5M8767=y
CONFIG_REGULATOR_TPS65090=y
@@ -88,28 +105,50 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_SIMPLE=y
CONFIG_EXYNOS_VIDEO=y
CONFIG_EXYNOS_MIPI_DSI=y
-CONFIG_EXYNOS_DP=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FONTS=y
CONFIG_FONT_7x14=y
CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SNOW=y
CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EXYNOS=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
-CONFIG_USB_PHY=y
-CONFIG_SAMSUNG_USB2PHY=y
-CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_USB_HSIC_USB3503=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_S5M=y
CONFIG_RTC_DRV_S3C=y
+CONFIG_DMADEVICES=y
+CONFIG_PL330_DMA=y
CONFIG_COMMON_CLK_MAX77686=y
+CONFIG_COMMON_CLK_S2MPS11=y
+CONFIG_EXYNOS_IOMMU=y
+CONFIG_IIO=y
+CONFIG_EXYNOS_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_SAMSUNG=y
+CONFIG_PHY_EXYNOS5250_SATA=y
+CONFIG_PHY_SAMSUNG_USB2=y
+CONFIG_PHY_EXYNOS4210_USB2=y
+CONFIG_PHY_EXYNOS4X12_USB2=y
+CONFIG_PHY_EXYNOS5250_USB2=y
+CONFIG_PHY_EXYNOS5_USBDRD=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
@@ -123,6 +162,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
diff --git a/arch/arm/configs/genmai_defconfig b/arch/arm/configs/genmai_defconfig
deleted file mode 100644
index d238fafb6762..000000000000
--- a/arch/arm/configs/genmai_defconfig
+++ /dev/null
@@ -1,122 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_SLAB=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_R7S72100=y
-CONFIG_MACH_GENMAI=y
-# CONFIG_SH_TIMER_CMT is not set
-# CONFIG_SH_TIMER_MTU2 is not set
-# CONFIG_SH_TIMER_TMU is not set
-# CONFIG_EM_TIMER_STI is not set
-CONFIG_ARM_ERRATA_430973=y
-CONFIG_ARM_ERRATA_458693=y
-CONFIG_ARM_ERRATA_460075=y
-CONFIG_ARM_ERRATA_743622=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_KEXEC=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-# CONFIG_NET_CORE is not set
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-CONFIG_SH_ETH=y
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=10
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_RIIC=y
-CONFIG_SPI=y
-CONFIG_SPI_RSPI=y
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
-CONFIG_RCAR_THERMAL=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_DRM=y
-CONFIG_DRM_RCAR_DU=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_SH_MMCIF=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_DMADEVICES=y
-CONFIG_SH_DMAE=y
-# CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_ARM_UNWIND is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/configs/hi3xxx_defconfig b/arch/arm/configs/hi3xxx_defconfig
index f186bdfa2369..9630687e7d07 100644
--- a/arch/arm/configs/hi3xxx_defconfig
+++ b/arch/arm/configs/hi3xxx_defconfig
@@ -3,7 +3,9 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_LZMA=y
+CONFIG_ARCH_HISI=y
CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HIX5HD2=y
CONFIG_SMP=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index bada59d93b67..63bde0efc041 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -1,6 +1,7 @@
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_LOG_BUF_SHIFT=14
@@ -35,10 +36,8 @@ CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
CONFIG_MACH_MX27_3DS=y
CONFIG_MACH_IMX27_VISSTRIM_M10=y
-CONFIG_MACH_IMX27LITE=y
CONFIG_MACH_PCA100=y
CONFIG_MACH_MXT_TD60=y
-CONFIG_MACH_IMX27IPCAM=y
CONFIG_MACH_IMX27_DT=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
@@ -159,6 +158,8 @@ CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 59b7e45142d8..16cfec4385c8 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -1,5 +1,6 @@
CONFIG_KERNEL_LZO=y
CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_LOG_BUF_SHIFT=18
@@ -31,11 +32,12 @@ CONFIG_MACH_IMX35_DT=y
CONFIG_MACH_PCM043=y
CONFIG_MACH_MX35_3DS=y
CONFIG_MACH_VPR200=y
-CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX51=y
CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SX=y
CONFIG_SOC_VF610=y
CONFIG_PCI=y
CONFIG_PCI_IMX6=y
@@ -67,6 +69,8 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_NETFILTER=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_RFKILL=y
@@ -160,6 +164,7 @@ CONFIG_SPI=y
CONFIG_SPI_IMX=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_MC9S08DZ60=y
+CONFIG_GPIO_STMPE=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_IMX2_WDT=y
@@ -242,6 +247,7 @@ CONFIG_RTC_DRV_SNVS=y
CONFIG_DMADEVICES=y
CONFIG_IMX_SDMA=y
CONFIG_MXS_DMA=y
+CONFIG_FSL_EDMA=y
CONFIG_STAGING=y
CONFIG_DRM_IMX=y
CONFIG_DRM_IMX_FB_HELPER=y
@@ -288,6 +294,7 @@ CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
deleted file mode 100644
index b9e480c10b10..000000000000
--- a/arch/arm/configs/kirkwood_defconfig
+++ /dev/null
@@ -1,181 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=19
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_KIRKWOOD=y
-CONFIG_MACH_D2NET_V2=y
-CONFIG_MACH_NET2BIG_V2=y
-CONFIG_MACH_NET5BIG_V2=y
-CONFIG_MACH_OPENRD_BASE=y
-CONFIG_MACH_OPENRD_CLIENT=y
-CONFIG_MACH_OPENRD_ULTIMATE=y
-CONFIG_MACH_RD88F6192_NAS=y
-CONFIG_MACH_RD88F6281=y
-CONFIG_MACH_T5325=y
-CONFIG_MACH_TS219=y
-CONFIG_MACH_TS41X=y
-CONFIG_ARCH_KIRKWOOD_DT=y
-CONFIG_MACH_MV88F6281GTW_GE_DT=y
-# CONFIG_CPU_FEROCEON_OLD_ID is not set
-CONFIG_PCI_MVEBU=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_HIGHMEM=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-CONFIG_CPU_IDLE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
-CONFIG_NET_PKTGEN=m
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ORION=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_EEPROM_AT24=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_SATA_MV=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
-CONFIG_MV643XX_ETH=y
-CONFIG_R8169=y
-CONFIG_MARVELL_PHY=y
-CONFIG_LIBERTAS=y
-CONFIG_LIBERTAS_SDIO=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MV64XXX=y
-CONFIG_SPI=y
-CONFIG_SPI_ORION=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SENSORS_ADT7475=y
-CONFIG_SENSORS_LM63=y
-CONFIG_SENSORS_LM75=y
-CONFIG_SENSORS_LM85=y
-CONFIG_THERMAL=y
-CONFIG_WATCHDOG=y
-CONFIG_ORION_WATCHDOG=y
-CONFIG_HID_DRAGONRISE=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_TWINHAN=y
-CONFIG_HID_NTRIG=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_HID_GREENASIA=y
-CONFIG_HID_SMARTJOYPLUS=y
-CONFIG_HID_TOPSEED=y
-CONFIG_HID_THRUSTMASTER=y
-CONFIG_HID_ZEROPLUS=y
-CONFIG_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_MMC=y
-CONFIG_SDIO_UART=y
-CONFIG_MMC_MVSDIO=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_RS5C372=y
-CONFIG_RTC_DRV_PCF8563=y
-CONFIG_RTC_DRV_S35390A=y
-CONFIG_RTC_DRV_MV=y
-CONFIG_DMADEVICES=y
-CONFIG_MV_XOR=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_MV_CESA=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/msm_defconfig b/arch/arm/configs/msm_defconfig
index 7f52dad97f51..dd18c9e527d6 100644
--- a/arch/arm/configs/msm_defconfig
+++ b/arch/arm/configs/msm_defconfig
@@ -45,7 +45,6 @@ CONFIG_RFKILL=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
diff --git a/arch/arm/configs/multi_v5_defconfig b/arch/arm/configs/multi_v5_defconfig
index 5ebfa8bf8509..018bef9fa7e8 100644
--- a/arch/arm/configs/multi_v5_defconfig
+++ b/arch/arm/configs/multi_v5_defconfig
@@ -11,6 +11,7 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_MVEBU=y
CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_NETXBIG=y
CONFIG_ARCH_MXC=y
CONFIG_MACH_IMX25_DT=y
CONFIG_MACH_IMX27_DT=y
@@ -94,6 +95,7 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_QNAP=y
CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_G762=y
CONFIG_SENSORS_LM63=y
CONFIG_SENSORS_LM75=y
CONFIG_SENSORS_LM85=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 534836497998..5fb95fb758d9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -19,15 +19,18 @@ CONFIG_MACH_DOVE=y
CONFIG_ARCH_BCM=y
CONFIG_ARCH_BCM_MOBILE=y
CONFIG_ARCH_BCM_5301X=y
+CONFIG_ARCH_BRCMSTB=y
CONFIG_ARCH_BERLIN=y
CONFIG_MACH_BERLIN_BG2=y
CONFIG_MACH_BERLIN_BG2CD=y
CONFIG_MACH_BERLIN_BG2Q=y
CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_HISI=y
CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HIX5HD2=y
CONFIG_ARCH_KEYSTONE=y
CONFIG_ARCH_MXC=y
-CONFIG_MACH_IMX51_DT=y
+CONFIG_SOC_IMX51=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
@@ -66,7 +69,6 @@ CONFIG_ARCH_VEXPRESS=y
CONFIG_ARCH_VEXPRESS_CA9X4=y
CONFIG_ARCH_WM8850=y
CONFIG_ARCH_ZYNQ=y
-CONFIG_NEON=y
CONFIG_TRUSTED_FOUNDATIONS=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
@@ -83,6 +85,7 @@ CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
+CONFIG_NEON=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -127,6 +130,7 @@ CONFIG_BLK_DEV_SR=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_ATA=y
CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_ST=y
CONFIG_AHCI_SUNXI=y
CONFIG_SATA_HIGHBANK=y
CONFIG_SATA_MV=y
@@ -134,6 +138,7 @@ CONFIG_NETDEVICES=y
CONFIG_SUN4I_EMAC=y
CONFIG_MACB=y
CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_IGB=y
CONFIG_MV643XX_ETH=y
CONFIG_MVNETA=y
CONFIG_KS8851=y
@@ -155,8 +160,11 @@ CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
CONFIG_KEYBOARD_SPEAR=y
+CONFIG_KEYBOARD_ST_KEYSCAN=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MPU3050=y
CONFIG_SERIO_AMBAKMI=y
@@ -195,6 +203,7 @@ CONFIG_I2C_EXYNOS5=y
CONFIG_I2C_MV64XXX=y
CONFIG_I2C_SIRF=y
CONFIG_I2C_TEGRA=y
+CONFIG_I2C_ST=y
CONFIG_SPI=y
CONFIG_SPI_OMAP24XX=y
CONFIG_SPI_ORION=y
@@ -222,8 +231,11 @@ CONFIG_POWER_RESET_AS3722=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_SUN6I=y
CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM95245=y
CONFIG_THERMAL=y
CONFIG_ARMADA_THERMAL=y
+CONFIG_ST_THERMAL_SYSCFG=y
+CONFIG_ST_THERMAL_MEMMAP=y
CONFIG_WATCHDOG=y
CONFIG_ORION_WATCHDOG=y
CONFIG_SUNXI_WATCHDOG=y
@@ -233,6 +245,7 @@ CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_SPI=y
CONFIG_MFD_MAX8907=y
CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_STMPE=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y
@@ -311,12 +324,16 @@ CONFIG_MMC_SDHCI_SPEAR=y
CONFIG_MMC_SDHCI_S3C=y
CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_SDHCI_BCM_KONA=y
+CONFIG_MMC_SDHCI_ST=y
CONFIG_MMC_OMAP=y
CONFIG_MMC_OMAP_HS=y
CONFIG_MMC_MVSDIO=y
CONFIG_MMC_SUNXI=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PWM=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_HIGHBANK_MC=y
@@ -368,6 +385,8 @@ CONFIG_PWM=y
CONFIG_PWM_TEGRA=y
CONFIG_PWM_VT8500=y
CONFIG_OMAP_USB2=y
+CONFIG_TI_PIPE3=y
+CONFIG_PHY_MIPHY365X=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_EXT4_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/arm/configs/mvebu_v5_defconfig b/arch/arm/configs/mvebu_v5_defconfig
index 27c732fdf21e..22058e18dfaa 100644
--- a/arch/arm/configs/mvebu_v5_defconfig
+++ b/arch/arm/configs/mvebu_v5_defconfig
@@ -12,6 +12,7 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_MVEBU=y
CONFIG_MACH_KIRKWOOD=y
+CONFIG_MACH_NETXBIG=y
# CONFIG_CPU_FEROCEON_OLD_ID is not set
CONFIG_PCI_MVEBU=y
CONFIG_PREEMPT=y
@@ -19,6 +20,8 @@ CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
@@ -36,6 +39,8 @@ CONFIG_NET_PKTGEN=m
CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
@@ -89,6 +94,7 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_QNAP=y
CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_G762=y
CONFIG_SENSORS_LM63=y
CONFIG_SENSORS_LM75=y
CONFIG_SENSORS_LM85=y
diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig
index b0bfefa23902..fdfda1fa9521 100644
--- a/arch/arm/configs/mvebu_v7_defconfig
+++ b/arch/arm/configs/mvebu_v7_defconfig
@@ -29,6 +29,10 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_MVEBU_V7_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_GENERIC=y
CONFIG_VFP=y
CONFIG_NET=y
CONFIG_INET=y
@@ -46,6 +50,7 @@ CONFIG_AHCI_MVEBU=y
CONFIG_SATA_MV=y
CONFIG_NETDEVICES=y
CONFIG_MVNETA=y
+CONFIG_MVPP2=y
CONFIG_MARVELL_PHY=y
CONFIG_MWIFIEX=y
CONFIG_MWIFIEX_SDIO=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index a9f992335eb2..c7906c2fd645 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -1,4 +1,5 @@
CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_TASKSTATS=y
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index ce541bb3c2de..115cda9f3260 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -26,8 +26,6 @@ CONFIG_ARCH_OMAP=y
CONFIG_ARCH_OMAP1=y
CONFIG_OMAP_RESET_CLOCKS=y
# CONFIG_OMAP_MUX is not set
-CONFIG_MAILBOX=y
-CONFIG_OMAP1_MBOX=y
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_DM_TIMER=y
CONFIG_ARCH_OMAP730=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 536a137863cb..f650f00e8cee 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -180,6 +180,7 @@ CONFIG_TWL4030_WATCHDOG=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TPS65218=y
CONFIG_MFD_TPS65910=y
CONFIG_TWL6040_CORE=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -188,6 +189,7 @@ CONFIG_REGULATOR_TI_ABB=y
CONFIG_REGULATOR_TPS65023=y
CONFIG_REGULATOR_TPS6507X=y
CONFIG_REGULATOR_TPS65217=y
+CONFIG_REGULATOR_TPS65218=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_TWL4030=y
CONFIG_REGULATOR_PBIAS=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index eb4d204bff47..f3142369f594 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -225,7 +225,6 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDETAPE=m
CONFIG_BLK_DEV_PLATFORM=y
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
diff --git a/arch/arm/configs/s5p64x0_defconfig b/arch/arm/configs/s5p64x0_defconfig
deleted file mode 100644
index ad6b61b0bd11..000000000000
--- a/arch/arm/configs/s5p64x0_defconfig
+++ /dev/null
@@ -1,68 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5P64X0=y
-CONFIG_S3C_BOOT_ERROR_RESET=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
-CONFIG_MACH_SMDK6440=y
-CONFIG_MACH_SMDK6450=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_CPU_32v6K=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
-CONFIG_FPE_NWFPE=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-# CONFIG_HWMON is not set
-CONFIG_DISPLAY_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_S3C_UART=1
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/s5pc100_defconfig b/arch/arm/configs/s5pc100_defconfig
deleted file mode 100644
index 41bafc94dd85..000000000000
--- a/arch/arm/configs/s5pc100_defconfig
+++ /dev/null
@@ -1,49 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_S5PC100=y
-CONFIG_MACH_SMDKC100=y
-CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=cramfs init=/linuxrc console=ttySAC2,115200 mem=128M"
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_EEPROM_AT24=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_SAMSUNG=y
-CONFIG_SERIAL_SAMSUNG_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_DEBUG=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_SDIO_UART=y
-CONFIG_MMC_SDHCI=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CRAMFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index 6d6437cbbc52..3b136144cc83 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -10,16 +10,20 @@ CONFIG_PERF_EVENTS=y
CONFIG_SLAB=y
CONFIG_ARCH_SHMOBILE_MULTI=y
CONFIG_ARCH_EMEV2=y
+CONFIG_ARCH_R7S72100=y
+CONFIG_ARCH_R8A7779=y
CONFIG_ARCH_R8A7790=y
CONFIG_ARCH_R8A7791=y
CONFIG_MACH_KOELSCH=y
CONFIG_MACH_LAGER=y
+CONFIG_MACH_MARZEN=y
# CONFIG_SWP_EMULATE is not set
CONFIG_CPU_BPREDICT_DISABLE=y
CONFIG_PL310_ERRATA_588369=y
CONFIG_ARM_ERRATA_754322=y
CONFIG_PCI=y
CONFIG_PCI_RCAR_GEN2=y
+CONFIG_PCI_RCAR_GEN2_PCIE=y
CONFIG_SMP=y
CONFIG_SCHED_MC=y
CONFIG_HAVE_ARM_ARCH_TIMER=y
@@ -33,6 +37,7 @@ CONFIG_KEXEC=y
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
@@ -82,6 +87,7 @@ CONFIG_I2C_RCAR=y
CONFIG_SPI=y
CONFIG_SPI_RSPI=y
CONFIG_SPI_SH_MSIOF=y
+CONFIG_SPI_SH_HSPI=y
CONFIG_GPIO_EM=y
CONFIG_GPIO_RCAR=y
# CONFIG_HWMON is not set
@@ -109,12 +115,14 @@ CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_RCAR=y
CONFIG_USB=y
-CONFIG_USB_RCAR_GEN2_PHY=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_RENESAS_USBHS=y
+CONFIG_USB_RCAR_PHY=y
+CONFIG_USB_RCAR_GEN2_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_USB_ETH=y
CONFIG_MMC=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_SH_MMCIF=y
@@ -141,3 +149,16 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_ARM_UNWIND is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_THERMAL=y
+CONFIG_GENERIC_CPUFREQ_CPU0=y
+CONFIG_REGULATOR_DA9210=y
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index e3a05e8801d8..d7a5855a5db8 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -11,6 +11,7 @@ CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
+CONFIG_HOTPLUG=y
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
@@ -40,6 +41,15 @@ CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
+CONFIG_CAN=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_GW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_C_CAN=y
+CONFIG_CAN_C_CAN_PLATFORM=y
+CONFIG_CAN_DEBUG_DEVICES=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_PROC_DEVICETREE=y
@@ -55,6 +65,14 @@ CONFIG_STMMAC_ETH=y
CONFIG_MICREL_PHY=y
# CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set
CONFIG_INPUT_EVDEV=y
+CONFIG_DWMAC_SOCFPGA=y
+CONFIG_PPS=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_GARP=y
+CONFIG_IPV6=y
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_LEGACY_PTY_COUNT=16
@@ -63,7 +81,12 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=2
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
CONFIG_SERIAL_8250_DW=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_DWAPB=y
# CONFIG_RTC_HCTOSYS is not set
+CONFIG_WATCHDOG=y
+CONFIG_DW_WATCHDOG=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
@@ -72,6 +95,7 @@ CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
+CONFIG_FHANDLE=y
CONFIG_VFAT_FS=y
CONFIG_NTFS_FS=y
CONFIG_NTFS_RW=y
@@ -86,5 +110,16 @@ CONFIG_DEBUG_INFO=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DEBUG_USER=y
CONFIG_XZ_DEC=y
+CONFIG_I2C=y
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_CHARDEV=y
CONFIG_MMC=y
CONFIG_MMC_DW=y
+CONFIG_PM=y
+CONFIG_SUSPEND=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+CONFIG_USB_DWC2_PLATFORM=y
diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 82eaa552ed14..d271b263f35d 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -11,13 +11,24 @@ CONFIG_ARCH_SPEAR13XX=y
CONFIG_MACH_SPEAR1310=y
CONFIG_MACH_SPEAR1340=y
# CONFIG_SWP_EMULATE is not set
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_SPEAR13XX=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
# CONFIG_ARM_CPU_TOPOLOGY is not set
+CONFIG_AEABI=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_VFP=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_MTD=y
CONFIG_MTD_OF_PARTS=y
@@ -27,6 +38,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_FSMC=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_BLK_DEV_SD=y
CONFIG_ATA=y
# CONFIG_SATA_PMP is not set
CONFIG_SATA_AHCI_PLATFORM=y
@@ -66,6 +78,7 @@ CONFIG_USB=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SPEAR=y
@@ -79,11 +92,14 @@ CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=m
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index fb25e2982f64..285c433a9aad 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -23,14 +23,11 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
-CONFIG_GPIO_PCA953X=y
CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_ARCH_TEGRA_114_SOC=y
CONFIG_ARCH_TEGRA_124_SOC=y
-CONFIG_TEGRA_EMC_SCALING_ENABLE=y
-CONFIG_TRUSTED_FOUNDATIONS=y
CONFIG_PCI=y
CONFIG_PCI_MSI=y
CONFIG_PCI_TEGRA=y
@@ -74,9 +71,6 @@ CONFIG_IPV6_MIP6=y
CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_CAN=y
-CONFIG_CAN_RAW=y
-CONFIG_CAN_BCM=y
-CONFIG_CAN_DEV=y
CONFIG_CAN_MCP251X=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
@@ -96,7 +90,6 @@ CONFIG_CMA_SIZE_MBYTES=64
CONFIG_MTD=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_SPI_NOR=y
-CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_AD525X_DPOT=y
CONFIG_AD525X_DPOT_I2C=y
@@ -111,6 +104,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_IGB=y
CONFIG_R8169=y
CONFIG_USB_PEGASUS=y
CONFIG_USB_USBNET=y
@@ -125,6 +119,8 @@ CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_TEGRA=y
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
@@ -135,6 +131,7 @@ CONFIG_SERIAL_TEGRA=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_MUX_PINCTRL=y
CONFIG_I2C_TEGRA=y
@@ -144,6 +141,7 @@ CONFIG_SPI_TEGRA20_SFLASH=y
CONFIG_SPI_TEGRA20_SLINK=y
CONFIG_PINCTRL_AS3722=y
CONFIG_PINCTRL_PALMAS=y
+CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_PALMAS=y
CONFIG_GPIO_TPS6586X=y
@@ -155,10 +153,12 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_AS3722=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM95245=y
CONFIG_MFD_AS3722=y
CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_SPI=y
CONFIG_MFD_MAX8907=y
+CONFIG_MFD_STMPE=y
CONFIG_MFD_PALMAS=y
CONFIG_MFD_TPS65090=y
CONFIG_MFD_TPS6586X=y
@@ -221,6 +221,7 @@ CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
@@ -291,5 +292,4 @@ CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_TEGRA_AES=y
CONFIG_CRC_CCITT=y
diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
index 81cda39860c5..b48fa341648d 100644
--- a/arch/arm/crypto/Makefile
+++ b/arch/arm/crypto/Makefile
@@ -5,10 +5,14 @@
obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
+obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
+obj-$(CONFIG_CRYPTO_SHA512_ARM_NEON) += sha512-arm-neon.o
aes-arm-y := aes-armv4.o aes_glue.o
aes-arm-bs-y := aesbs-core.o aesbs-glue.o
sha1-arm-y := sha1-armv4-large.o sha1_glue.o
+sha1-arm-neon-y := sha1-armv7-neon.o sha1_neon_glue.o
+sha512-arm-neon-y := sha512-armv7-neon.o sha512_neon_glue.o
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) > $(@)
diff --git a/arch/arm/crypto/aes-armv4.S b/arch/arm/crypto/aes-armv4.S
index 3a14ea8fe97e..ebb9761fb572 100644
--- a/arch/arm/crypto/aes-armv4.S
+++ b/arch/arm/crypto/aes-armv4.S
@@ -35,6 +35,7 @@
@ that is being targetted.
#include <linux/linkage.h>
+#include <asm/assembler.h>
.text
@@ -648,7 +649,7 @@ _armv4_AES_set_encrypt_key:
.Ldone: mov r0,#0
ldmia sp!,{r4-r12,lr}
-.Labrt: mov pc,lr
+.Labrt: ret lr
ENDPROC(private_AES_set_encrypt_key)
.align 5
diff --git a/arch/arm/crypto/sha1-armv7-neon.S b/arch/arm/crypto/sha1-armv7-neon.S
new file mode 100644
index 000000000000..50013c0e2864
--- /dev/null
+++ b/arch/arm/crypto/sha1-armv7-neon.S
@@ -0,0 +1,634 @@
+/* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
+ *
+ * Copyright © 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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/linkage.h>
+
+
+.syntax unified
+.code 32
+.fpu neon
+
+.text
+
+
+/* Context structure */
+
+#define state_h0 0
+#define state_h1 4
+#define state_h2 8
+#define state_h3 12
+#define state_h4 16
+
+
+/* Constants */
+
+#define K1 0x5A827999
+#define K2 0x6ED9EBA1
+#define K3 0x8F1BBCDC
+#define K4 0xCA62C1D6
+.align 4
+.LK_VEC:
+.LK1: .long K1, K1, K1, K1
+.LK2: .long K2, K2, K2, K2
+.LK3: .long K3, K3, K3, K3
+.LK4: .long K4, K4, K4, K4
+
+
+/* Register macros */
+
+#define RSTATE r0
+#define RDATA r1
+#define RNBLKS r2
+#define ROLDSTACK r3
+#define RWK lr
+
+#define _a r4
+#define _b r5
+#define _c r6
+#define _d r7
+#define _e r8
+
+#define RT0 r9
+#define RT1 r10
+#define RT2 r11
+#define RT3 r12
+
+#define W0 q0
+#define W1 q1
+#define W2 q2
+#define W3 q3
+#define W4 q4
+#define W5 q5
+#define W6 q6
+#define W7 q7
+
+#define tmp0 q8
+#define tmp1 q9
+#define tmp2 q10
+#define tmp3 q11
+
+#define qK1 q12
+#define qK2 q13
+#define qK3 q14
+#define qK4 q15
+
+
+/* Round function macros. */
+
+#define WK_offs(i) (((i) & 15) * 4)
+
+#define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ ldr RT3, [sp, WK_offs(i)]; \
+ pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ bic RT0, d, b; \
+ add e, e, a, ror #(32 - 5); \
+ and RT1, c, b; \
+ pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ add RT0, RT0, RT3; \
+ add e, e, RT1; \
+ ror b, #(32 - 30); \
+ pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ add e, e, RT0;
+
+#define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ ldr RT3, [sp, WK_offs(i)]; \
+ pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ eor RT0, d, b; \
+ add e, e, a, ror #(32 - 5); \
+ eor RT0, RT0, c; \
+ pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ add e, e, RT3; \
+ ror b, #(32 - 30); \
+ pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ add e, e, RT0; \
+
+#define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ ldr RT3, [sp, WK_offs(i)]; \
+ pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ eor RT0, b, c; \
+ and RT1, b, c; \
+ add e, e, a, ror #(32 - 5); \
+ pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ and RT0, RT0, d; \
+ add RT1, RT1, RT3; \
+ add e, e, RT0; \
+ ror b, #(32 - 30); \
+ pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+ add e, e, RT1;
+
+#define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define _R(a,b,c,d,e,f,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ _R_##f(a,b,c,d,e,i,pre1,pre2,pre3,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define R(a,b,c,d,e,f,i) \
+ _R_##f(a,b,c,d,e,i,dummy,dummy,dummy,i16,\
+ W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
+
+#define dummy(...)
+
+
+/* Input expansion macros. */
+
+/********* Precalc macros for rounds 0-15 *************************************/
+
+#define W_PRECALC_00_15() \
+ add RWK, sp, #(WK_offs(0)); \
+ \
+ vld1.32 {tmp0, tmp1}, [RDATA]!; \
+ vrev32.8 W0, tmp0; /* big => little */ \
+ vld1.32 {tmp2, tmp3}, [RDATA]!; \
+ vadd.u32 tmp0, W0, curK; \
+ vrev32.8 W7, tmp1; /* big => little */ \
+ vrev32.8 W6, tmp2; /* big => little */ \
+ vadd.u32 tmp1, W7, curK; \
+ vrev32.8 W5, tmp3; /* big => little */ \
+ vadd.u32 tmp2, W6, curK; \
+ vst1.32 {tmp0, tmp1}, [RWK]!; \
+ vadd.u32 tmp3, W5, curK; \
+ vst1.32 {tmp2, tmp3}, [RWK]; \
+
+#define WPRECALC_00_15_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vld1.32 {tmp0, tmp1}, [RDATA]!; \
+
+#define WPRECALC_00_15_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ add RWK, sp, #(WK_offs(0)); \
+
+#define WPRECALC_00_15_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vrev32.8 W0, tmp0; /* big => little */ \
+
+#define WPRECALC_00_15_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vld1.32 {tmp2, tmp3}, [RDATA]!; \
+
+#define WPRECALC_00_15_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp0, W0, curK; \
+
+#define WPRECALC_00_15_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vrev32.8 W7, tmp1; /* big => little */ \
+
+#define WPRECALC_00_15_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vrev32.8 W6, tmp2; /* big => little */ \
+
+#define WPRECALC_00_15_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp1, W7, curK; \
+
+#define WPRECALC_00_15_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vrev32.8 W5, tmp3; /* big => little */ \
+
+#define WPRECALC_00_15_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp2, W6, curK; \
+
+#define WPRECALC_00_15_10(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vst1.32 {tmp0, tmp1}, [RWK]!; \
+
+#define WPRECALC_00_15_11(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp3, W5, curK; \
+
+#define WPRECALC_00_15_12(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vst1.32 {tmp2, tmp3}, [RWK]; \
+
+
+/********* Precalc macros for rounds 16-31 ************************************/
+
+#define WPRECALC_16_31_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor tmp0, tmp0; \
+ vext.8 W, W_m16, W_m12, #8; \
+
+#define WPRECALC_16_31_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ add RWK, sp, #(WK_offs(i)); \
+ vext.8 tmp0, W_m04, tmp0, #4; \
+
+#define WPRECALC_16_31_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor tmp0, tmp0, W_m16; \
+ veor.32 W, W, W_m08; \
+
+#define WPRECALC_16_31_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor tmp1, tmp1; \
+ veor W, W, tmp0; \
+
+#define WPRECALC_16_31_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vshl.u32 tmp0, W, #1; \
+
+#define WPRECALC_16_31_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vext.8 tmp1, tmp1, W, #(16-12); \
+ vshr.u32 W, W, #31; \
+
+#define WPRECALC_16_31_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vorr tmp0, tmp0, W; \
+ vshr.u32 W, tmp1, #30; \
+
+#define WPRECALC_16_31_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vshl.u32 tmp1, tmp1, #2; \
+
+#define WPRECALC_16_31_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor tmp0, tmp0, W; \
+
+#define WPRECALC_16_31_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor W, tmp0, tmp1; \
+
+#define WPRECALC_16_31_10(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp0, W, curK; \
+
+#define WPRECALC_16_31_11(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vst1.32 {tmp0}, [RWK];
+
+
+/********* Precalc macros for rounds 32-79 ************************************/
+
+#define WPRECALC_32_79_0(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor W, W_m28; \
+
+#define WPRECALC_32_79_1(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vext.8 tmp0, W_m08, W_m04, #8; \
+
+#define WPRECALC_32_79_2(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor W, W_m16; \
+
+#define WPRECALC_32_79_3(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ veor W, tmp0; \
+
+#define WPRECALC_32_79_4(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ add RWK, sp, #(WK_offs(i&~3)); \
+
+#define WPRECALC_32_79_5(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vshl.u32 tmp1, W, #2; \
+
+#define WPRECALC_32_79_6(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vshr.u32 tmp0, W, #30; \
+
+#define WPRECALC_32_79_7(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vorr W, tmp0, tmp1; \
+
+#define WPRECALC_32_79_8(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vadd.u32 tmp0, W, curK; \
+
+#define WPRECALC_32_79_9(i,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
+ vst1.32 {tmp0}, [RWK];
+
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ *
+ * unsigned int
+ * sha1_transform_neon (void *ctx, const unsigned char *data,
+ * unsigned int nblks)
+ */
+.align 3
+ENTRY(sha1_transform_neon)
+ /* input:
+ * r0: ctx, CTX
+ * r1: data (64*nblks bytes)
+ * r2: nblks
+ */
+
+ cmp RNBLKS, #0;
+ beq .Ldo_nothing;
+
+ push {r4-r12, lr};
+ /*vpush {q4-q7};*/
+
+ adr RT3, .LK_VEC;
+
+ mov ROLDSTACK, sp;
+
+ /* Align stack. */
+ sub RT0, sp, #(16*4);
+ and RT0, #(~(16-1));
+ mov sp, RT0;
+
+ vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
+
+ /* Get the values of the chaining variables. */
+ ldm RSTATE, {_a-_e};
+
+ vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
+
+#undef curK
+#define curK qK1
+ /* Precalc 0-15. */
+ W_PRECALC_00_15();
+
+.Loop:
+ /* Transform 0-15 + Precalc 16-31. */
+ _R( _a, _b, _c, _d, _e, F1, 0,
+ WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 16,
+ W4, W5, W6, W7, W0, _, _, _ );
+ _R( _e, _a, _b, _c, _d, F1, 1,
+ WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 16,
+ W4, W5, W6, W7, W0, _, _, _ );
+ _R( _d, _e, _a, _b, _c, F1, 2,
+ WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16,
+ W4, W5, W6, W7, W0, _, _, _ );
+ _R( _c, _d, _e, _a, _b, F1, 3,
+ WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16,
+ W4, W5, W6, W7, W0, _, _, _ );
+
+#undef curK
+#define curK qK2
+ _R( _b, _c, _d, _e, _a, F1, 4,
+ WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20,
+ W3, W4, W5, W6, W7, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F1, 5,
+ WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20,
+ W3, W4, W5, W6, W7, _, _, _ );
+ _R( _e, _a, _b, _c, _d, F1, 6,
+ WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20,
+ W3, W4, W5, W6, W7, _, _, _ );
+ _R( _d, _e, _a, _b, _c, F1, 7,
+ WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,20,
+ W3, W4, W5, W6, W7, _, _, _ );
+
+ _R( _c, _d, _e, _a, _b, F1, 8,
+ WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 24,
+ W2, W3, W4, W5, W6, _, _, _ );
+ _R( _b, _c, _d, _e, _a, F1, 9,
+ WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 24,
+ W2, W3, W4, W5, W6, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F1, 10,
+ WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 24,
+ W2, W3, W4, W5, W6, _, _, _ );
+ _R( _e, _a, _b, _c, _d, F1, 11,
+ WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,24,
+ W2, W3, W4, W5, W6, _, _, _ );
+
+ _R( _d, _e, _a, _b, _c, F1, 12,
+ WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 28,
+ W1, W2, W3, W4, W5, _, _, _ );
+ _R( _c, _d, _e, _a, _b, F1, 13,
+ WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 28,
+ W1, W2, W3, W4, W5, _, _, _ );
+ _R( _b, _c, _d, _e, _a, F1, 14,
+ WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 28,
+ W1, W2, W3, W4, W5, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F1, 15,
+ WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,28,
+ W1, W2, W3, W4, W5, _, _, _ );
+
+ /* Transform 16-63 + Precalc 32-79. */
+ _R( _e, _a, _b, _c, _d, F1, 16,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _d, _e, _a, _b, _c, F1, 17,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _c, _d, _e, _a, _b, F1, 18,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 32,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _b, _c, _d, _e, _a, F1, 19,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 32,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+
+ _R( _a, _b, _c, _d, _e, F2, 20,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _e, _a, _b, _c, _d, F2, 21,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _d, _e, _a, _b, _c, F2, 22,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 36,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _c, _d, _e, _a, _b, F2, 23,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 36,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+
+#undef curK
+#define curK qK3
+ _R( _b, _c, _d, _e, _a, F2, 24,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _a, _b, _c, _d, _e, F2, 25,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _e, _a, _b, _c, _d, F2, 26,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 40,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _d, _e, _a, _b, _c, F2, 27,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 40,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+
+ _R( _c, _d, _e, _a, _b, F2, 28,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _b, _c, _d, _e, _a, F2, 29,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _a, _b, _c, _d, _e, F2, 30,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 44,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _e, _a, _b, _c, _d, F2, 31,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 44,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+
+ _R( _d, _e, _a, _b, _c, F2, 32,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48,
+ W4, W5, W6, W7, W0, W1, W2, W3);
+ _R( _c, _d, _e, _a, _b, F2, 33,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48,
+ W4, W5, W6, W7, W0, W1, W2, W3);
+ _R( _b, _c, _d, _e, _a, F2, 34,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 48,
+ W4, W5, W6, W7, W0, W1, W2, W3);
+ _R( _a, _b, _c, _d, _e, F2, 35,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 48,
+ W4, W5, W6, W7, W0, W1, W2, W3);
+
+ _R( _e, _a, _b, _c, _d, F2, 36,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52,
+ W3, W4, W5, W6, W7, W0, W1, W2);
+ _R( _d, _e, _a, _b, _c, F2, 37,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52,
+ W3, W4, W5, W6, W7, W0, W1, W2);
+ _R( _c, _d, _e, _a, _b, F2, 38,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 52,
+ W3, W4, W5, W6, W7, W0, W1, W2);
+ _R( _b, _c, _d, _e, _a, F2, 39,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 52,
+ W3, W4, W5, W6, W7, W0, W1, W2);
+
+ _R( _a, _b, _c, _d, _e, F3, 40,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56,
+ W2, W3, W4, W5, W6, W7, W0, W1);
+ _R( _e, _a, _b, _c, _d, F3, 41,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56,
+ W2, W3, W4, W5, W6, W7, W0, W1);
+ _R( _d, _e, _a, _b, _c, F3, 42,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 56,
+ W2, W3, W4, W5, W6, W7, W0, W1);
+ _R( _c, _d, _e, _a, _b, F3, 43,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 56,
+ W2, W3, W4, W5, W6, W7, W0, W1);
+
+#undef curK
+#define curK qK4
+ _R( _b, _c, _d, _e, _a, F3, 44,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60,
+ W1, W2, W3, W4, W5, W6, W7, W0);
+ _R( _a, _b, _c, _d, _e, F3, 45,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60,
+ W1, W2, W3, W4, W5, W6, W7, W0);
+ _R( _e, _a, _b, _c, _d, F3, 46,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 60,
+ W1, W2, W3, W4, W5, W6, W7, W0);
+ _R( _d, _e, _a, _b, _c, F3, 47,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 60,
+ W1, W2, W3, W4, W5, W6, W7, W0);
+
+ _R( _c, _d, _e, _a, _b, F3, 48,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _b, _c, _d, _e, _a, F3, 49,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _a, _b, _c, _d, _e, F3, 50,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 64,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+ _R( _e, _a, _b, _c, _d, F3, 51,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 64,
+ W0, W1, W2, W3, W4, W5, W6, W7);
+
+ _R( _d, _e, _a, _b, _c, F3, 52,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _c, _d, _e, _a, _b, F3, 53,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _b, _c, _d, _e, _a, F3, 54,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 68,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+ _R( _a, _b, _c, _d, _e, F3, 55,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 68,
+ W7, W0, W1, W2, W3, W4, W5, W6);
+
+ _R( _e, _a, _b, _c, _d, F3, 56,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _d, _e, _a, _b, _c, F3, 57,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _c, _d, _e, _a, _b, F3, 58,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 72,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+ _R( _b, _c, _d, _e, _a, F3, 59,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 72,
+ W6, W7, W0, W1, W2, W3, W4, W5);
+
+ subs RNBLKS, #1;
+
+ _R( _a, _b, _c, _d, _e, F4, 60,
+ WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _e, _a, _b, _c, _d, F4, 61,
+ WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _d, _e, _a, _b, _c, F4, 62,
+ WPRECALC_32_79_6, dummy, WPRECALC_32_79_7, 76,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+ _R( _c, _d, _e, _a, _b, F4, 63,
+ WPRECALC_32_79_8, dummy, WPRECALC_32_79_9, 76,
+ W5, W6, W7, W0, W1, W2, W3, W4);
+
+ beq .Lend;
+
+ /* Transform 64-79 + Precalc 0-15 of next block. */
+#undef curK
+#define curK qK1
+ _R( _b, _c, _d, _e, _a, F4, 64,
+ WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F4, 65,
+ WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _e, _a, _b, _c, _d, F4, 66,
+ WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _d, _e, _a, _b, _c, F4, 67,
+ WPRECALC_00_15_3, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+ _R( _c, _d, _e, _a, _b, F4, 68,
+ dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _b, _c, _d, _e, _a, F4, 69,
+ dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F4, 70,
+ WPRECALC_00_15_4, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _e, _a, _b, _c, _d, F4, 71,
+ WPRECALC_00_15_5, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+ _R( _d, _e, _a, _b, _c, F4, 72,
+ dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _c, _d, _e, _a, _b, F4, 73,
+ dummy, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _b, _c, _d, _e, _a, F4, 74,
+ WPRECALC_00_15_6, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _a, _b, _c, _d, _e, F4, 75,
+ WPRECALC_00_15_7, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+
+ _R( _e, _a, _b, _c, _d, F4, 76,
+ WPRECALC_00_15_8, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _d, _e, _a, _b, _c, F4, 77,
+ WPRECALC_00_15_9, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _c, _d, _e, _a, _b, F4, 78,
+ WPRECALC_00_15_10, dummy, dummy, _, _, _, _, _, _, _, _, _ );
+ _R( _b, _c, _d, _e, _a, F4, 79,
+ WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );
+
+ /* Update the chaining variables. */
+ ldm RSTATE, {RT0-RT3};
+ add _a, RT0;
+ ldr RT0, [RSTATE, #state_h4];
+ add _b, RT1;
+ add _c, RT2;
+ add _d, RT3;
+ add _e, RT0;
+ stm RSTATE, {_a-_e};
+
+ b .Loop;
+
+.Lend:
+ /* Transform 64-79 */
+ R( _b, _c, _d, _e, _a, F4, 64 );
+ R( _a, _b, _c, _d, _e, F4, 65 );
+ R( _e, _a, _b, _c, _d, F4, 66 );
+ R( _d, _e, _a, _b, _c, F4, 67 );
+ R( _c, _d, _e, _a, _b, F4, 68 );
+ R( _b, _c, _d, _e, _a, F4, 69 );
+ R( _a, _b, _c, _d, _e, F4, 70 );
+ R( _e, _a, _b, _c, _d, F4, 71 );
+ R( _d, _e, _a, _b, _c, F4, 72 );
+ R( _c, _d, _e, _a, _b, F4, 73 );
+ R( _b, _c, _d, _e, _a, F4, 74 );
+ R( _a, _b, _c, _d, _e, F4, 75 );
+ R( _e, _a, _b, _c, _d, F4, 76 );
+ R( _d, _e, _a, _b, _c, F4, 77 );
+ R( _c, _d, _e, _a, _b, F4, 78 );
+ R( _b, _c, _d, _e, _a, F4, 79 );
+
+ mov sp, ROLDSTACK;
+
+ /* Update the chaining variables. */
+ ldm RSTATE, {RT0-RT3};
+ add _a, RT0;
+ ldr RT0, [RSTATE, #state_h4];
+ add _b, RT1;
+ add _c, RT2;
+ add _d, RT3;
+ /*vpop {q4-q7};*/
+ add _e, RT0;
+ stm RSTATE, {_a-_e};
+
+ pop {r4-r12, pc};
+
+.Ldo_nothing:
+ bx lr
+ENDPROC(sha1_transform_neon)
diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c
index 76cd976230bc..84f2a756588b 100644
--- a/arch/arm/crypto/sha1_glue.c
+++ b/arch/arm/crypto/sha1_glue.c
@@ -23,32 +23,27 @@
#include <linux/types.h>
#include <crypto/sha.h>
#include <asm/byteorder.h>
+#include <asm/crypto/sha1.h>
-struct SHA1_CTX {
- uint32_t h0,h1,h2,h3,h4;
- u64 count;
- u8 data[SHA1_BLOCK_SIZE];
-};
-asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest,
+asmlinkage void sha1_block_data_order(u32 *digest,
const unsigned char *data, unsigned int rounds);
static int sha1_init(struct shash_desc *desc)
{
- struct SHA1_CTX *sctx = shash_desc_ctx(desc);
- memset(sctx, 0, sizeof(*sctx));
- sctx->h0 = SHA1_H0;
- sctx->h1 = SHA1_H1;
- sctx->h2 = SHA1_H2;
- sctx->h3 = SHA1_H3;
- sctx->h4 = SHA1_H4;
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ *sctx = (struct sha1_state){
+ .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+ };
+
return 0;
}
-static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data,
- unsigned int len, unsigned int partial)
+static int __sha1_update(struct sha1_state *sctx, const u8 *data,
+ unsigned int len, unsigned int partial)
{
unsigned int done = 0;
@@ -56,43 +51,44 @@ static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data,
if (partial) {
done = SHA1_BLOCK_SIZE - partial;
- memcpy(sctx->data + partial, data, done);
- sha1_block_data_order(sctx, sctx->data, 1);
+ memcpy(sctx->buffer + partial, data, done);
+ sha1_block_data_order(sctx->state, sctx->buffer, 1);
}
if (len - done >= SHA1_BLOCK_SIZE) {
const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
- sha1_block_data_order(sctx, data + done, rounds);
+ sha1_block_data_order(sctx->state, data + done, rounds);
done += rounds * SHA1_BLOCK_SIZE;
}
- memcpy(sctx->data, data + done, len - done);
+ memcpy(sctx->buffer, data + done, len - done);
return 0;
}
-static int sha1_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
+int sha1_update_arm(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
{
- struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+ struct sha1_state *sctx = shash_desc_ctx(desc);
unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
int res;
/* Handle the fast case right here */
if (partial + len < SHA1_BLOCK_SIZE) {
sctx->count += len;
- memcpy(sctx->data + partial, data, len);
+ memcpy(sctx->buffer + partial, data, len);
return 0;
}
res = __sha1_update(sctx, data, len, partial);
return res;
}
+EXPORT_SYMBOL_GPL(sha1_update_arm);
/* Add padding and return the message digest. */
static int sha1_final(struct shash_desc *desc, u8 *out)
{
- struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+ struct sha1_state *sctx = shash_desc_ctx(desc);
unsigned int i, index, padlen;
__be32 *dst = (__be32 *)out;
__be64 bits;
@@ -106,7 +102,7 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
/* We need to fill a whole block for __sha1_update() */
if (padlen <= 56) {
sctx->count += padlen;
- memcpy(sctx->data + index, padding, padlen);
+ memcpy(sctx->buffer + index, padding, padlen);
} else {
__sha1_update(sctx, padding, padlen, index);
}
@@ -114,7 +110,7 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
/* Store state in digest */
for (i = 0; i < 5; i++)
- dst[i] = cpu_to_be32(((u32 *)sctx)[i]);
+ dst[i] = cpu_to_be32(sctx->state[i]);
/* Wipe context */
memset(sctx, 0, sizeof(*sctx));
@@ -124,7 +120,7 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
static int sha1_export(struct shash_desc *desc, void *out)
{
- struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+ struct sha1_state *sctx = shash_desc_ctx(desc);
memcpy(out, sctx, sizeof(*sctx));
return 0;
}
@@ -132,7 +128,7 @@ static int sha1_export(struct shash_desc *desc, void *out)
static int sha1_import(struct shash_desc *desc, const void *in)
{
- struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+ struct sha1_state *sctx = shash_desc_ctx(desc);
memcpy(sctx, in, sizeof(*sctx));
return 0;
}
@@ -141,12 +137,12 @@ static int sha1_import(struct shash_desc *desc, const void *in)
static struct shash_alg alg = {
.digestsize = SHA1_DIGEST_SIZE,
.init = sha1_init,
- .update = sha1_update,
+ .update = sha1_update_arm,
.final = sha1_final,
.export = sha1_export,
.import = sha1_import,
- .descsize = sizeof(struct SHA1_CTX),
- .statesize = sizeof(struct SHA1_CTX),
+ .descsize = sizeof(struct sha1_state),
+ .statesize = sizeof(struct sha1_state),
.base = {
.cra_name = "sha1",
.cra_driver_name= "sha1-asm",
diff --git a/arch/arm/crypto/sha1_neon_glue.c b/arch/arm/crypto/sha1_neon_glue.c
new file mode 100644
index 000000000000..6f1b411b1d55
--- /dev/null
+++ b/arch/arm/crypto/sha1_neon_glue.c
@@ -0,0 +1,197 @@
+/*
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
+ * ARM NEON instructions.
+ *
+ * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is based on sha1_generic.c and sha1_ssse3_glue.c:
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ * Copyright (c) Chandramouli Narayanan <mouli@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 as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/crypto/sha1.h>
+
+
+asmlinkage void sha1_transform_neon(void *state_h, const char *data,
+ unsigned int rounds);
+
+
+static int sha1_neon_init(struct shash_desc *desc)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ *sctx = (struct sha1_state){
+ .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+ };
+
+ return 0;
+}
+
+static int __sha1_neon_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int done = 0;
+
+ sctx->count += len;
+
+ if (partial) {
+ done = SHA1_BLOCK_SIZE - partial;
+ memcpy(sctx->buffer + partial, data, done);
+ sha1_transform_neon(sctx->state, sctx->buffer, 1);
+ }
+
+ if (len - done >= SHA1_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+ sha1_transform_neon(sctx->state, data + done, rounds);
+ done += rounds * SHA1_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buffer, data + done, len - done);
+
+ return 0;
+}
+
+static int sha1_neon_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+ int res;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA1_BLOCK_SIZE) {
+ sctx->count += len;
+ memcpy(sctx->buffer + partial, data, len);
+
+ return 0;
+ }
+
+ if (!may_use_simd()) {
+ res = sha1_update_arm(desc, data, len);
+ } else {
+ kernel_neon_begin();
+ res = __sha1_neon_update(desc, data, len, partial);
+ kernel_neon_end();
+ }
+
+ return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_neon_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be32 *dst = (__be32 *)out;
+ __be64 bits;
+ static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+ bits = cpu_to_be64(sctx->count << 3);
+
+ /* Pad out to 56 mod 64 and append length */
+ index = sctx->count % SHA1_BLOCK_SIZE;
+ padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+ if (!may_use_simd()) {
+ sha1_update_arm(desc, padding, padlen);
+ sha1_update_arm(desc, (const u8 *)&bits, sizeof(bits));
+ } else {
+ kernel_neon_begin();
+ /* We need to fill a whole block for __sha1_neon_update() */
+ if (padlen <= 56) {
+ sctx->count += padlen;
+ memcpy(sctx->buffer + index, padding, padlen);
+ } else {
+ __sha1_neon_update(desc, padding, padlen, index);
+ }
+ __sha1_neon_update(desc, (const u8 *)&bits, sizeof(bits), 56);
+ kernel_neon_end();
+ }
+
+ /* Store state in digest */
+ for (i = 0; i < 5; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_neon_export(struct shash_desc *desc, void *out)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha1_neon_import(struct shash_desc *desc, const void *in)
+{
+ struct sha1_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+
+ return 0;
+}
+
+static struct shash_alg alg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .init = sha1_neon_init,
+ .update = sha1_neon_update,
+ .final = sha1_neon_final,
+ .export = sha1_neon_export,
+ .import = sha1_neon_import,
+ .descsize = sizeof(struct sha1_state),
+ .statesize = sizeof(struct sha1_state),
+ .base = {
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1-neon",
+ .cra_priority = 250,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static int __init sha1_neon_mod_init(void)
+{
+ if (!cpu_has_neon())
+ return -ENODEV;
+
+ return crypto_register_shash(&alg);
+}
+
+static void __exit sha1_neon_mod_fini(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_neon_mod_init);
+module_exit(sha1_neon_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, NEON accelerated");
+MODULE_ALIAS("sha1");
diff --git a/arch/arm/crypto/sha512-armv7-neon.S b/arch/arm/crypto/sha512-armv7-neon.S
new file mode 100644
index 000000000000..fe99472e507c
--- /dev/null
+++ b/arch/arm/crypto/sha512-armv7-neon.S
@@ -0,0 +1,455 @@
+/* sha512-armv7-neon.S - ARM/NEON assembly implementation of SHA-512 transform
+ *
+ * Copyright © 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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/linkage.h>
+
+
+.syntax unified
+.code 32
+.fpu neon
+
+.text
+
+/* structure of SHA512_CONTEXT */
+#define hd_a 0
+#define hd_b ((hd_a) + 8)
+#define hd_c ((hd_b) + 8)
+#define hd_d ((hd_c) + 8)
+#define hd_e ((hd_d) + 8)
+#define hd_f ((hd_e) + 8)
+#define hd_g ((hd_f) + 8)
+
+/* register macros */
+#define RK %r2
+
+#define RA d0
+#define RB d1
+#define RC d2
+#define RD d3
+#define RE d4
+#define RF d5
+#define RG d6
+#define RH d7
+
+#define RT0 d8
+#define RT1 d9
+#define RT2 d10
+#define RT3 d11
+#define RT4 d12
+#define RT5 d13
+#define RT6 d14
+#define RT7 d15
+
+#define RT01q q4
+#define RT23q q5
+#define RT45q q6
+#define RT67q q7
+
+#define RW0 d16
+#define RW1 d17
+#define RW2 d18
+#define RW3 d19
+#define RW4 d20
+#define RW5 d21
+#define RW6 d22
+#define RW7 d23
+#define RW8 d24
+#define RW9 d25
+#define RW10 d26
+#define RW11 d27
+#define RW12 d28
+#define RW13 d29
+#define RW14 d30
+#define RW15 d31
+
+#define RW01q q8
+#define RW23q q9
+#define RW45q q10
+#define RW67q q11
+#define RW89q q12
+#define RW1011q q13
+#define RW1213q q14
+#define RW1415q q15
+
+/***********************************************************************
+ * ARM assembly implementation of sha512 transform
+ ***********************************************************************/
+#define rounds2_0_63(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, rw01q, rw2, \
+ rw23q, rw1415q, rw9, rw10, interleave_op, arg1) \
+ /* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
+ vshr.u64 RT2, re, #14; \
+ vshl.u64 RT3, re, #64 - 14; \
+ interleave_op(arg1); \
+ vshr.u64 RT4, re, #18; \
+ vshl.u64 RT5, re, #64 - 18; \
+ vld1.64 {RT0}, [RK]!; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, re, #41; \
+ vshl.u64 RT5, re, #64 - 41; \
+ vadd.u64 RT0, RT0, rw0; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vmov.64 RT7, re; \
+ veor.64 RT1, RT2, RT3; \
+ vbsl.64 RT7, rf, rg; \
+ \
+ vadd.u64 RT1, RT1, rh; \
+ vshr.u64 RT2, ra, #28; \
+ vshl.u64 RT3, ra, #64 - 28; \
+ vadd.u64 RT1, RT1, RT0; \
+ vshr.u64 RT4, ra, #34; \
+ vshl.u64 RT5, ra, #64 - 34; \
+ vadd.u64 RT1, RT1, RT7; \
+ \
+ /* h = Sum0 (a) + Maj (a, b, c); */ \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, ra, #39; \
+ vshl.u64 RT5, ra, #64 - 39; \
+ veor.64 RT0, ra, rb; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vbsl.64 RT0, rc, rb; \
+ vadd.u64 rd, rd, RT1; /* d+=t1; */ \
+ veor.64 rh, RT2, RT3; \
+ \
+ /* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
+ vshr.u64 RT2, rd, #14; \
+ vshl.u64 RT3, rd, #64 - 14; \
+ vadd.u64 rh, rh, RT0; \
+ vshr.u64 RT4, rd, #18; \
+ vshl.u64 RT5, rd, #64 - 18; \
+ vadd.u64 rh, rh, RT1; /* h+=t1; */ \
+ vld1.64 {RT0}, [RK]!; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, rd, #41; \
+ vshl.u64 RT5, rd, #64 - 41; \
+ vadd.u64 RT0, RT0, rw1; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vmov.64 RT7, rd; \
+ veor.64 RT1, RT2, RT3; \
+ vbsl.64 RT7, re, rf; \
+ \
+ vadd.u64 RT1, RT1, rg; \
+ vshr.u64 RT2, rh, #28; \
+ vshl.u64 RT3, rh, #64 - 28; \
+ vadd.u64 RT1, RT1, RT0; \
+ vshr.u64 RT4, rh, #34; \
+ vshl.u64 RT5, rh, #64 - 34; \
+ vadd.u64 RT1, RT1, RT7; \
+ \
+ /* g = Sum0 (h) + Maj (h, a, b); */ \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, rh, #39; \
+ vshl.u64 RT5, rh, #64 - 39; \
+ veor.64 RT0, rh, ra; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vbsl.64 RT0, rb, ra; \
+ vadd.u64 rc, rc, RT1; /* c+=t1; */ \
+ veor.64 rg, RT2, RT3; \
+ \
+ /* w[0] += S1 (w[14]) + w[9] + S0 (w[1]); */ \
+ /* w[1] += S1 (w[15]) + w[10] + S0 (w[2]); */ \
+ \
+ /**** S0(w[1:2]) */ \
+ \
+ /* w[0:1] += w[9:10] */ \
+ /* RT23q = rw1:rw2 */ \
+ vext.u64 RT23q, rw01q, rw23q, #1; \
+ vadd.u64 rw0, rw9; \
+ vadd.u64 rg, rg, RT0; \
+ vadd.u64 rw1, rw10;\
+ vadd.u64 rg, rg, RT1; /* g+=t1; */ \
+ \
+ vshr.u64 RT45q, RT23q, #1; \
+ vshl.u64 RT67q, RT23q, #64 - 1; \
+ vshr.u64 RT01q, RT23q, #8; \
+ veor.u64 RT45q, RT45q, RT67q; \
+ vshl.u64 RT67q, RT23q, #64 - 8; \
+ veor.u64 RT45q, RT45q, RT01q; \
+ vshr.u64 RT01q, RT23q, #7; \
+ veor.u64 RT45q, RT45q, RT67q; \
+ \
+ /**** S1(w[14:15]) */ \
+ vshr.u64 RT23q, rw1415q, #6; \
+ veor.u64 RT01q, RT01q, RT45q; \
+ vshr.u64 RT45q, rw1415q, #19; \
+ vshl.u64 RT67q, rw1415q, #64 - 19; \
+ veor.u64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT45q, rw1415q, #61; \
+ veor.u64 RT23q, RT23q, RT67q; \
+ vshl.u64 RT67q, rw1415q, #64 - 61; \
+ veor.u64 RT23q, RT23q, RT45q; \
+ vadd.u64 rw01q, RT01q; /* w[0:1] += S(w[1:2]) */ \
+ veor.u64 RT01q, RT23q, RT67q;
+#define vadd_RT01q(rw01q) \
+ /* w[0:1] += S(w[14:15]) */ \
+ vadd.u64 rw01q, RT01q;
+
+#define dummy(_) /*_*/
+
+#define rounds2_64_79(ra, rb, rc, rd, re, rf, rg, rh, rw0, rw1, \
+ interleave_op1, arg1, interleave_op2, arg2) \
+ /* t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t]; */ \
+ vshr.u64 RT2, re, #14; \
+ vshl.u64 RT3, re, #64 - 14; \
+ interleave_op1(arg1); \
+ vshr.u64 RT4, re, #18; \
+ vshl.u64 RT5, re, #64 - 18; \
+ interleave_op2(arg2); \
+ vld1.64 {RT0}, [RK]!; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, re, #41; \
+ vshl.u64 RT5, re, #64 - 41; \
+ vadd.u64 RT0, RT0, rw0; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vmov.64 RT7, re; \
+ veor.64 RT1, RT2, RT3; \
+ vbsl.64 RT7, rf, rg; \
+ \
+ vadd.u64 RT1, RT1, rh; \
+ vshr.u64 RT2, ra, #28; \
+ vshl.u64 RT3, ra, #64 - 28; \
+ vadd.u64 RT1, RT1, RT0; \
+ vshr.u64 RT4, ra, #34; \
+ vshl.u64 RT5, ra, #64 - 34; \
+ vadd.u64 RT1, RT1, RT7; \
+ \
+ /* h = Sum0 (a) + Maj (a, b, c); */ \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, ra, #39; \
+ vshl.u64 RT5, ra, #64 - 39; \
+ veor.64 RT0, ra, rb; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vbsl.64 RT0, rc, rb; \
+ vadd.u64 rd, rd, RT1; /* d+=t1; */ \
+ veor.64 rh, RT2, RT3; \
+ \
+ /* t1 = g + Sum1 (d) + Ch (d, e, f) + k[t] + w[t]; */ \
+ vshr.u64 RT2, rd, #14; \
+ vshl.u64 RT3, rd, #64 - 14; \
+ vadd.u64 rh, rh, RT0; \
+ vshr.u64 RT4, rd, #18; \
+ vshl.u64 RT5, rd, #64 - 18; \
+ vadd.u64 rh, rh, RT1; /* h+=t1; */ \
+ vld1.64 {RT0}, [RK]!; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, rd, #41; \
+ vshl.u64 RT5, rd, #64 - 41; \
+ vadd.u64 RT0, RT0, rw1; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vmov.64 RT7, rd; \
+ veor.64 RT1, RT2, RT3; \
+ vbsl.64 RT7, re, rf; \
+ \
+ vadd.u64 RT1, RT1, rg; \
+ vshr.u64 RT2, rh, #28; \
+ vshl.u64 RT3, rh, #64 - 28; \
+ vadd.u64 RT1, RT1, RT0; \
+ vshr.u64 RT4, rh, #34; \
+ vshl.u64 RT5, rh, #64 - 34; \
+ vadd.u64 RT1, RT1, RT7; \
+ \
+ /* g = Sum0 (h) + Maj (h, a, b); */ \
+ veor.64 RT23q, RT23q, RT45q; \
+ vshr.u64 RT4, rh, #39; \
+ vshl.u64 RT5, rh, #64 - 39; \
+ veor.64 RT0, rh, ra; \
+ veor.64 RT23q, RT23q, RT45q; \
+ vbsl.64 RT0, rb, ra; \
+ vadd.u64 rc, rc, RT1; /* c+=t1; */ \
+ veor.64 rg, RT2, RT3;
+#define vadd_rg_RT0(rg) \
+ vadd.u64 rg, rg, RT0;
+#define vadd_rg_RT1(rg) \
+ vadd.u64 rg, rg, RT1; /* g+=t1; */
+
+.align 3
+ENTRY(sha512_transform_neon)
+ /* Input:
+ * %r0: SHA512_CONTEXT
+ * %r1: data
+ * %r2: u64 k[] constants
+ * %r3: nblks
+ */
+ push {%lr};
+
+ mov %lr, #0;
+
+ /* Load context to d0-d7 */
+ vld1.64 {RA-RD}, [%r0]!;
+ vld1.64 {RE-RH}, [%r0];
+ sub %r0, #(4*8);
+
+ /* Load input to w[16], d16-d31 */
+ /* NOTE: Assumes that on ARMv7 unaligned accesses are always allowed. */
+ vld1.64 {RW0-RW3}, [%r1]!;
+ vld1.64 {RW4-RW7}, [%r1]!;
+ vld1.64 {RW8-RW11}, [%r1]!;
+ vld1.64 {RW12-RW15}, [%r1]!;
+#ifdef __ARMEL__
+ /* byteswap */
+ vrev64.8 RW01q, RW01q;
+ vrev64.8 RW23q, RW23q;
+ vrev64.8 RW45q, RW45q;
+ vrev64.8 RW67q, RW67q;
+ vrev64.8 RW89q, RW89q;
+ vrev64.8 RW1011q, RW1011q;
+ vrev64.8 RW1213q, RW1213q;
+ vrev64.8 RW1415q, RW1415q;
+#endif
+
+ /* EABI says that d8-d15 must be preserved by callee. */
+ /*vpush {RT0-RT7};*/
+
+.Loop:
+ rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2,
+ RW23q, RW1415q, RW9, RW10, dummy, _);
+ b .Lenter_rounds;
+
+.Loop_rounds:
+ rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1, RW01q, RW2,
+ RW23q, RW1415q, RW9, RW10, vadd_RT01q, RW1415q);
+.Lenter_rounds:
+ rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3, RW23q, RW4,
+ RW45q, RW01q, RW11, RW12, vadd_RT01q, RW01q);
+ rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5, RW45q, RW6,
+ RW67q, RW23q, RW13, RW14, vadd_RT01q, RW23q);
+ rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7, RW67q, RW8,
+ RW89q, RW45q, RW15, RW0, vadd_RT01q, RW45q);
+ rounds2_0_63(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9, RW89q, RW10,
+ RW1011q, RW67q, RW1, RW2, vadd_RT01q, RW67q);
+ rounds2_0_63(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11, RW1011q, RW12,
+ RW1213q, RW89q, RW3, RW4, vadd_RT01q, RW89q);
+ add %lr, #16;
+ rounds2_0_63(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, RW1213q, RW14,
+ RW1415q, RW1011q, RW5, RW6, vadd_RT01q, RW1011q);
+ cmp %lr, #64;
+ rounds2_0_63(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, RW1415q, RW0,
+ RW01q, RW1213q, RW7, RW8, vadd_RT01q, RW1213q);
+ bne .Loop_rounds;
+
+ subs %r3, #1;
+
+ rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW0, RW1,
+ vadd_RT01q, RW1415q, dummy, _);
+ rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW2, RW3,
+ vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+ beq .Lhandle_tail;
+ vld1.64 {RW0-RW3}, [%r1]!;
+ rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5,
+ vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+ rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7,
+ vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+#ifdef __ARMEL__
+ vrev64.8 RW01q, RW01q;
+ vrev64.8 RW23q, RW23q;
+#endif
+ vld1.64 {RW4-RW7}, [%r1]!;
+ rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9,
+ vadd_rg_RT0, RA, vadd_rg_RT1, RA);
+ rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11,
+ vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+#ifdef __ARMEL__
+ vrev64.8 RW45q, RW45q;
+ vrev64.8 RW67q, RW67q;
+#endif
+ vld1.64 {RW8-RW11}, [%r1]!;
+ rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13,
+ vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+ rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15,
+ vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+#ifdef __ARMEL__
+ vrev64.8 RW89q, RW89q;
+ vrev64.8 RW1011q, RW1011q;
+#endif
+ vld1.64 {RW12-RW15}, [%r1]!;
+ vadd_rg_RT0(RA);
+ vadd_rg_RT1(RA);
+
+ /* Load context */
+ vld1.64 {RT0-RT3}, [%r0]!;
+ vld1.64 {RT4-RT7}, [%r0];
+ sub %r0, #(4*8);
+
+#ifdef __ARMEL__
+ vrev64.8 RW1213q, RW1213q;
+ vrev64.8 RW1415q, RW1415q;
+#endif
+
+ vadd.u64 RA, RT0;
+ vadd.u64 RB, RT1;
+ vadd.u64 RC, RT2;
+ vadd.u64 RD, RT3;
+ vadd.u64 RE, RT4;
+ vadd.u64 RF, RT5;
+ vadd.u64 RG, RT6;
+ vadd.u64 RH, RT7;
+
+ /* Store the first half of context */
+ vst1.64 {RA-RD}, [%r0]!;
+ sub RK, $(8*80);
+ vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
+ mov %lr, #0;
+ sub %r0, #(4*8);
+
+ b .Loop;
+
+.Lhandle_tail:
+ rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW4, RW5,
+ vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+ rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW6, RW7,
+ vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+ rounds2_64_79(RA, RB, RC, RD, RE, RF, RG, RH, RW8, RW9,
+ vadd_rg_RT0, RA, vadd_rg_RT1, RA);
+ rounds2_64_79(RG, RH, RA, RB, RC, RD, RE, RF, RW10, RW11,
+ vadd_rg_RT0, RG, vadd_rg_RT1, RG);
+ rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13,
+ vadd_rg_RT0, RE, vadd_rg_RT1, RE);
+ rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15,
+ vadd_rg_RT0, RC, vadd_rg_RT1, RC);
+
+ /* Load context to d16-d23 */
+ vld1.64 {RW0-RW3}, [%r0]!;
+ vadd_rg_RT0(RA);
+ vld1.64 {RW4-RW7}, [%r0];
+ vadd_rg_RT1(RA);
+ sub %r0, #(4*8);
+
+ vadd.u64 RA, RW0;
+ vadd.u64 RB, RW1;
+ vadd.u64 RC, RW2;
+ vadd.u64 RD, RW3;
+ vadd.u64 RE, RW4;
+ vadd.u64 RF, RW5;
+ vadd.u64 RG, RW6;
+ vadd.u64 RH, RW7;
+
+ /* Store the first half of context */
+ vst1.64 {RA-RD}, [%r0]!;
+
+ /* Clear used registers */
+ /* d16-d31 */
+ veor.u64 RW01q, RW01q;
+ veor.u64 RW23q, RW23q;
+ veor.u64 RW45q, RW45q;
+ veor.u64 RW67q, RW67q;
+ vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
+ veor.u64 RW89q, RW89q;
+ veor.u64 RW1011q, RW1011q;
+ veor.u64 RW1213q, RW1213q;
+ veor.u64 RW1415q, RW1415q;
+ /* d8-d15 */
+ /*vpop {RT0-RT7};*/
+ /* d0-d7 (q0-q3) */
+ veor.u64 %q0, %q0;
+ veor.u64 %q1, %q1;
+ veor.u64 %q2, %q2;
+ veor.u64 %q3, %q3;
+
+ pop {%pc};
+ENDPROC(sha512_transform_neon)
diff --git a/arch/arm/crypto/sha512_neon_glue.c b/arch/arm/crypto/sha512_neon_glue.c
new file mode 100644
index 000000000000..0d2758ff5e12
--- /dev/null
+++ b/arch/arm/crypto/sha512_neon_glue.c
@@ -0,0 +1,305 @@
+/*
+ * Glue code for the SHA512 Secure Hash Algorithm assembly implementation
+ * using NEON instructions.
+ *
+ * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is based on sha512_ssse3_glue.c:
+ * Copyright (C) 2013 Intel Corporation
+ * Author: Tim Chen <tim.c.chen@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 as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+#include <asm/simd.h>
+#include <asm/neon.h>
+
+
+static const u64 sha512_k[] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+
+asmlinkage void sha512_transform_neon(u64 *digest, const void *data,
+ const u64 k[], unsigned int num_blks);
+
+
+static int sha512_neon_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+
+ sctx->state[0] = SHA512_H0;
+ sctx->state[1] = SHA512_H1;
+ sctx->state[2] = SHA512_H2;
+ sctx->state[3] = SHA512_H3;
+ sctx->state[4] = SHA512_H4;
+ sctx->state[5] = SHA512_H5;
+ sctx->state[6] = SHA512_H6;
+ sctx->state[7] = SHA512_H7;
+ sctx->count[0] = sctx->count[1] = 0;
+
+ return 0;
+}
+
+static int __sha512_neon_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len, unsigned int partial)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ unsigned int done = 0;
+
+ sctx->count[0] += len;
+ if (sctx->count[0] < len)
+ sctx->count[1]++;
+
+ if (partial) {
+ done = SHA512_BLOCK_SIZE - partial;
+ memcpy(sctx->buf + partial, data, done);
+ sha512_transform_neon(sctx->state, sctx->buf, sha512_k, 1);
+ }
+
+ if (len - done >= SHA512_BLOCK_SIZE) {
+ const unsigned int rounds = (len - done) / SHA512_BLOCK_SIZE;
+
+ sha512_transform_neon(sctx->state, data + done, sha512_k,
+ rounds);
+
+ done += rounds * SHA512_BLOCK_SIZE;
+ }
+
+ memcpy(sctx->buf, data + done, len - done);
+
+ return 0;
+}
+
+static int sha512_neon_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+ int res;
+
+ /* Handle the fast case right here */
+ if (partial + len < SHA512_BLOCK_SIZE) {
+ sctx->count[0] += len;
+ if (sctx->count[0] < len)
+ sctx->count[1]++;
+ memcpy(sctx->buf + partial, data, len);
+
+ return 0;
+ }
+
+ if (!may_use_simd()) {
+ res = crypto_sha512_update(desc, data, len);
+ } else {
+ kernel_neon_begin();
+ res = __sha512_neon_update(desc, data, len, partial);
+ kernel_neon_end();
+ }
+
+ return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha512_neon_final(struct shash_desc *desc, u8 *out)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+ unsigned int i, index, padlen;
+ __be64 *dst = (__be64 *)out;
+ __be64 bits[2];
+ static const u8 padding[SHA512_BLOCK_SIZE] = { 0x80, };
+
+ /* save number of bits */
+ bits[1] = cpu_to_be64(sctx->count[0] << 3);
+ bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
+
+ /* Pad out to 112 mod 128 and append length */
+ index = sctx->count[0] & 0x7f;
+ padlen = (index < 112) ? (112 - index) : ((128+112) - index);
+
+ if (!may_use_simd()) {
+ crypto_sha512_update(desc, padding, padlen);
+ crypto_sha512_update(desc, (const u8 *)&bits, sizeof(bits));
+ } else {
+ kernel_neon_begin();
+ /* We need to fill a whole block for __sha512_neon_update() */
+ if (padlen <= 112) {
+ sctx->count[0] += padlen;
+ if (sctx->count[0] < padlen)
+ sctx->count[1]++;
+ memcpy(sctx->buf + index, padding, padlen);
+ } else {
+ __sha512_neon_update(desc, padding, padlen, index);
+ }
+ __sha512_neon_update(desc, (const u8 *)&bits,
+ sizeof(bits), 112);
+ kernel_neon_end();
+ }
+
+ /* Store state in digest */
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be64(sctx->state[i]);
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha512_neon_export(struct shash_desc *desc, void *out)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(out, sctx, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha512_neon_import(struct shash_desc *desc, const void *in)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+
+ memcpy(sctx, in, sizeof(*sctx));
+
+ return 0;
+}
+
+static int sha384_neon_init(struct shash_desc *desc)
+{
+ struct sha512_state *sctx = shash_desc_ctx(desc);
+
+ sctx->state[0] = SHA384_H0;
+ sctx->state[1] = SHA384_H1;
+ sctx->state[2] = SHA384_H2;
+ sctx->state[3] = SHA384_H3;
+ sctx->state[4] = SHA384_H4;
+ sctx->state[5] = SHA384_H5;
+ sctx->state[6] = SHA384_H6;
+ sctx->state[7] = SHA384_H7;
+
+ sctx->count[0] = sctx->count[1] = 0;
+
+ return 0;
+}
+
+static int sha384_neon_final(struct shash_desc *desc, u8 *hash)
+{
+ u8 D[SHA512_DIGEST_SIZE];
+
+ sha512_neon_final(desc, D);
+
+ memcpy(hash, D, SHA384_DIGEST_SIZE);
+ memset(D, 0, SHA512_DIGEST_SIZE);
+
+ return 0;
+}
+
+static struct shash_alg algs[] = { {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .init = sha512_neon_init,
+ .update = sha512_neon_update,
+ .final = sha512_neon_final,
+ .export = sha512_neon_export,
+ .import = sha512_neon_import,
+ .descsize = sizeof(struct sha512_state),
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha512",
+ .cra_driver_name = "sha512-neon",
+ .cra_priority = 250,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+}, {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .init = sha384_neon_init,
+ .update = sha512_neon_update,
+ .final = sha384_neon_final,
+ .export = sha512_neon_export,
+ .import = sha512_neon_import,
+ .descsize = sizeof(struct sha512_state),
+ .statesize = sizeof(struct sha512_state),
+ .base = {
+ .cra_name = "sha384",
+ .cra_driver_name = "sha384-neon",
+ .cra_priority = 250,
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
+} };
+
+static int __init sha512_neon_mod_init(void)
+{
+ if (!cpu_has_neon())
+ return -ENODEV;
+
+ return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit sha512_neon_mod_fini(void)
+{
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha512_neon_mod_init);
+module_exit(sha512_neon_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, NEON accelerated");
+
+MODULE_ALIAS("sha512");
+MODULE_ALIAS("sha384");
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index f5a357601983..70cd84eb7fda 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -22,6 +22,7 @@ generic-y += poll.h
generic-y += preempt.h
generic-y += resource.h
generic-y += rwsem.h
+generic-y += scatterlist.h
generic-y += sections.h
generic-y += segment.h
generic-y += sembuf.h
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 57f0584e8d97..f67fd3afebdf 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -24,6 +24,8 @@
#include <asm/domain.h>
#include <asm/opcodes-virt.h>
#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
#define IOMEM(x) (x)
@@ -179,10 +181,10 @@
* Get current thread_info.
*/
.macro get_thread_info, rd
- ARM( mov \rd, sp, lsr #13 )
+ ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT )
THUMB( mov \rd, sp )
- THUMB( lsr \rd, \rd, #13 )
- mov \rd, \rd, lsl #13
+ THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT )
+ mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
.endm
/*
@@ -425,4 +427,25 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif
.endm
+ .irp c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
+ .macro ret\c, reg
+#if __LINUX_ARM_ARCH__ < 6
+ mov\c pc, \reg
+#else
+ .ifeqs "\reg", "lr"
+ bx\c \reg
+ .else
+ mov\c pc, \reg
+ .endif
+#endif
+ .endm
+ .endr
+
+ .macro ret.w, reg
+ ret \reg
+#ifdef CONFIG_THUMB2_KERNEL
+ nop
+#endif
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 8c2b7321a478..963a2515906d 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -62,17 +62,18 @@
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_INTEL 0x69
-#define ARM_CPU_PART_ARM1136 0xB360
-#define ARM_CPU_PART_ARM1156 0xB560
-#define ARM_CPU_PART_ARM1176 0xB760
-#define ARM_CPU_PART_ARM11MPCORE 0xB020
-#define ARM_CPU_PART_CORTEX_A8 0xC080
-#define ARM_CPU_PART_CORTEX_A9 0xC090
-#define ARM_CPU_PART_CORTEX_A5 0xC050
-#define ARM_CPU_PART_CORTEX_A15 0xC0F0
-#define ARM_CPU_PART_CORTEX_A7 0xC070
-#define ARM_CPU_PART_CORTEX_A12 0xC0D0
-#define ARM_CPU_PART_CORTEX_A17 0xC0E0
+/* ARM implemented processors */
+#define ARM_CPU_PART_ARM1136 0x4100b360
+#define ARM_CPU_PART_ARM1156 0x4100b560
+#define ARM_CPU_PART_ARM1176 0x4100b760
+#define ARM_CPU_PART_ARM11MPCORE 0x4100b020
+#define ARM_CPU_PART_CORTEX_A8 0x4100c080
+#define ARM_CPU_PART_CORTEX_A9 0x4100c090
+#define ARM_CPU_PART_CORTEX_A5 0x4100c050
+#define ARM_CPU_PART_CORTEX_A7 0x4100c070
+#define ARM_CPU_PART_CORTEX_A12 0x4100c0d0
+#define ARM_CPU_PART_CORTEX_A17 0x4100c0e0
+#define ARM_CPU_PART_CORTEX_A15 0x4100c0f0
#define ARM_CPU_XSCALE_ARCH_MASK 0xe000
#define ARM_CPU_XSCALE_ARCH_V1 0x2000
@@ -171,14 +172,24 @@ static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
return (read_cpuid_id() & 0xFF000000) >> 24;
}
-static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
+/*
+ * The CPU part number is meaningless without referring to the CPU
+ * implementer: implementers are free to define their own part numbers
+ * which are permitted to clash with other implementer part numbers.
+ */
+static inline unsigned int __attribute_const__ read_cpuid_part(void)
+{
+ return read_cpuid_id() & 0xff00fff0;
+}
+
+static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void)
{
return read_cpuid_id() & 0xFFF0;
}
static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void)
{
- return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK;
+ return read_cpuid_id() & ARM_CPU_XSCALE_ARCH_MASK;
}
static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
diff --git a/arch/arm/include/asm/crypto/sha1.h b/arch/arm/include/asm/crypto/sha1.h
new file mode 100644
index 000000000000..75e6a417416b
--- /dev/null
+++ b/arch/arm/include/asm/crypto/sha1.h
@@ -0,0 +1,10 @@
+#ifndef ASM_ARM_CRYPTO_SHA1_H
+#define ASM_ARM_CRYPTO_SHA1_H
+
+#include <linux/crypto.h>
+#include <crypto/sha.h>
+
+extern int sha1_update_arm(struct shash_desc *desc, const u8 *data,
+ unsigned int len);
+
+#endif
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 88d61815f0c0..469a2b30fa27 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -35,5 +35,5 @@
\symbol_name:
mov r8, lr
arch_irq_handler_default
- mov pc, r8
+ ret r8
.endm
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index 74a8b84f3cb1..74be7c22035a 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -221,15 +221,6 @@
# endif
#endif
-#ifdef CONFIG_CPU_V7
-# ifdef CPU_NAME
-# undef MULTI_CPU
-# define MULTI_CPU
-# else
-# define CPU_NAME cpu_v7
-# endif
-#endif
-
#ifdef CONFIG_CPU_V7M
# ifdef CPU_NAME
# undef MULTI_CPU
@@ -248,6 +239,15 @@
# endif
#endif
+#ifdef CONFIG_CPU_V7
+/*
+ * Cortex-A9 needs a different suspend/resume function, so we need
+ * multiple CPU support for ARMv7 anyway.
+ */
+# undef MULTI_CPU
+# define MULTI_CPU
+#endif
+
#ifndef MULTI_CPU
#define cpu_proc_init __glue(CPU_NAME,_proc_init)
#define cpu_proc_fin __glue(CPU_NAME,_proc_fin)
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index 477e0206e016..504dcddebfcc 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -5,12 +5,6 @@
#define ARCH_NR_GPIOS CONFIG_ARCH_NR_GPIO
#endif
-/* not all ARM platforms necessarily support this API ... */
-#ifdef CONFIG_NEED_MACH_GPIO_H
-#include <mach/gpio.h>
-#endif
-
-#ifndef __ARM_GPIOLIB_COMPLEX
/* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
#include <asm-generic/gpio.h>
@@ -18,7 +12,6 @@
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
-#endif
/*
* Provide a default gpio_to_irq() which should satisfy every case.
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 53b3c4a50d5c..3a67bec72d0c 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -61,6 +61,24 @@
#define ARM_EXCEPTION_FIQ 6
#define ARM_EXCEPTION_HVC 7
+/*
+ * The rr_lo_hi macro swaps a pair of registers depending on
+ * current endianness. It is used in conjunction with ldrd and strd
+ * instructions that load/store a 64-bit value from/to memory to/from
+ * a pair of registers which are used with the mrrc and mcrr instructions.
+ * If used with the ldrd/strd instructions, the a1 parameter is the first
+ * source/destination register and the a2 parameter is the second
+ * source/destination register. Note that the ldrd/strd instructions
+ * already swap the bytes within the words correctly according to the
+ * endianness setting, but the order of the registers need to be effectively
+ * swapped when used with the mrrc/mcrr instructions.
+ */
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define rr_lo_hi(a1, a2) a2, a1
+#else
+#define rr_lo_hi(a1, a2) a1, a2
+#endif
+
#ifndef __ASSEMBLY__
struct kvm;
struct kvm_vcpu;
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 0fa90c962ac8..69b746955fca 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -185,9 +185,16 @@ static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
default:
return be32_to_cpu(data);
}
+ } else {
+ switch (len) {
+ case 1:
+ return data & 0xff;
+ case 2:
+ return le16_to_cpu(data & 0xffff);
+ default:
+ return le32_to_cpu(data);
+ }
}
-
- return data; /* Leave LE untouched */
}
static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
@@ -203,9 +210,16 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
default:
return cpu_to_be32(data);
}
+ } else {
+ switch (len) {
+ case 1:
+ return data & 0xff;
+ case 2:
+ return cpu_to_le16(data & 0xffff);
+ default:
+ return cpu_to_le32(data);
+ }
}
-
- return data; /* Leave LE untouched */
}
#endif /* __ARM_KVM_EMULATE_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 193ceaf01bfd..6dfb404f6c46 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -225,10 +225,12 @@ static inline int kvm_arch_dev_ioctl_check_extension(long ext)
return 0;
}
+static inline void vgic_arch_setup(const struct vgic_params *vgic)
+{
+ BUG_ON(vgic->type != VGIC_V2);
+}
+
int kvm_perf_init(void);
int kvm_perf_teardown(void);
-u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
-int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
-
#endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 5c7aa3c1519f..5cc0b0f5f72f 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -127,6 +127,18 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
(__boundary - 1 < (end) - 1)? __boundary: (end); \
})
+static inline bool kvm_page_empty(void *ptr)
+{
+ struct page *ptr_page = virt_to_page(ptr);
+ return page_count(ptr_page) == 1;
+}
+
+
+#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep)
+#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#define kvm_pud_table_empty(pudp) (0)
+
+
struct kvm;
#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l))
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index 94060adba174..57ff7f2a3084 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -217,6 +217,22 @@ int __mcpm_cluster_state(unsigned int cluster);
int __init mcpm_sync_init(
void (*power_up_setup)(unsigned int affinity_level));
+/**
+ * mcpm_loopback - make a run through the MCPM low-level code
+ *
+ * @cache_disable: pointer to function performing cache disabling
+ *
+ * This exercises the MCPM machinery by soft resetting the CPU and branching
+ * to the MCPM low-level entry code before returning to the caller.
+ * The @cache_disable function must do the necessary cache disabling to
+ * let the regular kernel init code turn it back on as if the CPU was
+ * hotplugged in. The MCPM state machine is set as if the cluster was
+ * initialized meaning the power_up_setup callback passed to mcpm_sync_init()
+ * will be invoked for all affinity levels. This may be useful to initialize
+ * some resources such as enabling the CCI that requires the cache to be off, or simply for testing purposes.
+ */
+int __init mcpm_loopback(void (*cache_disable)(void));
+
void __init mcpm_smp_set_ops(void);
#else
diff --git a/arch/arm/include/asm/mcs_spinlock.h b/arch/arm/include/asm/mcs_spinlock.h
new file mode 100644
index 000000000000..f652ad65840a
--- /dev/null
+++ b/arch/arm/include/asm/mcs_spinlock.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_MCS_LOCK_H
+#define __ASM_MCS_LOCK_H
+
+#ifdef CONFIG_SMP
+#include <asm/spinlock.h>
+
+/* MCS spin-locking. */
+#define arch_mcs_spin_lock_contended(lock) \
+do { \
+ /* Ensure prior stores are observed before we enter wfe. */ \
+ smp_mb(); \
+ while (!(smp_load_acquire(lock))) \
+ wfe(); \
+} while (0) \
+
+#define arch_mcs_spin_unlock_contended(lock) \
+do { \
+ smp_store_release(lock, 1); \
+ dsb_sev(); \
+} while (0)
+
+#endif /* CONFIG_SMP */
+#endif /* __ASM_MCS_LOCK_H */
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 2b751464d6ff..e731018869a7 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -91,9 +91,7 @@
* of this define that was meant to.
* Fortunately, there is no reference for this in noMMU mode, for now.
*/
-#ifndef TASK_SIZE
-#define TASK_SIZE (CONFIG_DRAM_SIZE)
-#endif
+#define TASK_SIZE UL(0xffffffff)
#ifndef TASK_UNMAPPED_BASE
#define TASK_UNMAPPED_BASE UL(0x00000000)
@@ -150,13 +148,11 @@
/*
* PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
- * memory. This is used for XIP and NoMMU kernels, or by kernels which
- * have their own mach/memory.h. Assembly code must always use
+ * memory. This is used for XIP and NoMMU kernels, and on platforms that don't
+ * have CONFIG_ARM_PATCH_PHYS_VIRT. Assembly code must always use
* PLAT_PHYS_OFFSET and not PHYS_OFFSET.
*/
-#ifndef PLAT_PHYS_OFFSET
#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
-#endif
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 755877527cf9..c3a83691af8e 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,15 +12,6 @@
#ifndef __ARM_PERF_EVENT_H__
#define __ARM_PERF_EVENT_H__
-/*
- * The ARMv7 CPU PMU supports up to 32 event counters.
- */
-#define ARMPMU_MAX_HWEVENTS 32
-
-#define HW_OP_UNSUPPORTED 0xFFFF
-#define C(_x) PERF_COUNT_HW_CACHE_##_x
-#define CACHE_OP_UNSUPPORTED 0xFFFF
-
#ifdef CONFIG_HW_PERF_EVENTS
struct pt_regs;
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h
index 626989fec4d3..9fd61c72a33a 100644
--- a/arch/arm/include/asm/pgtable-3level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
@@ -43,7 +43,7 @@
#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
#define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */
-#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
+#define PMD_SECT_AP2 (_AT(pmdval_t, 1) << 7) /* read only */
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
#define PMD_SECT_nG (_AT(pmdval_t, 1) << 11)
@@ -72,6 +72,7 @@
#define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1)
#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */
#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */
+#define PTE_AP2 (_AT(pteval_t, 1) << 7) /* AP[2] */
#define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
#define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */
#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 85c60adc8b60..06e0bc0f8b00 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -79,18 +79,19 @@
#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */
#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
-#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
#define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */
#define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */
-#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */
-#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */
+#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55)
+#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56)
#define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */
+#define L_PTE_RDONLY (_AT(pteval_t, 1) << 58) /* READ ONLY */
-#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
-#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56)
-#define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
+#define L_PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
+#define L_PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56)
+#define L_PMD_SECT_NONE (_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_RDONLY (_AT(pteval_t, 1) << 58)
/*
* To be used in assembly code with the upper page attributes.
@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT))
#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
-#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
+#define pmd_isset(pmd, val) ((u32)(val) == (val) ? pmd_val(pmd) & (val) \
+ : !!(pmd_val(pmd) & (val)))
+#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val)))
+
+#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF))
#define __HAVE_ARCH_PMD_WRITE
-#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
+#define pmd_write(pmd) (pmd_isclear((pmd), L_PMD_SECT_RDONLY))
+#define pmd_dirty(pmd) (pmd_isset((pmd), L_PMD_SECT_DIRTY))
#define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd))
#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd))
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#define pmd_trans_huge(pmd) (pmd_val(pmd) && !pmd_table(pmd))
+#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING))
#endif
#define PMD_BIT_FUNC(fn,op) \
static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
-PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
+PMD_BIT_FUNC(wrprotect, |= L_PMD_SECT_RDONLY);
PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
-PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
-PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING);
+PMD_BIT_FUNC(mkwrite, &= ~L_PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkdirty, |= L_PMD_SECT_DIRTY);
PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
#define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
- const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY |
- PMD_SECT_VALID | PMD_SECT_NONE;
+ const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY |
+ L_PMD_SECT_VALID | L_PMD_SECT_NONE;
pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
return pmd;
}
@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
BUG_ON(addr >= TASK_SIZE);
/* create a faulting entry if PROT_NONE protected */
- if (pmd_val(pmd) & PMD_SECT_NONE)
- pmd_val(pmd) &= ~PMD_SECT_VALID;
+ if (pmd_val(pmd) & L_PMD_SECT_NONE)
+ pmd_val(pmd) &= ~L_PMD_SECT_VALID;
+
+ if (pmd_write(pmd) && pmd_dirty(pmd))
+ pmd_val(pmd) &= ~PMD_SECT_AP2;
+ else
+ pmd_val(pmd) |= PMD_SECT_AP2;
*pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG);
flush_pmd_entry(pmdp);
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 5478e5d6ad89..01baef07cd0c 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -214,18 +214,22 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0)
+#define pte_isset(pte, val) ((u32)(val) == (val) ? pte_val(pte) & (val) \
+ : !!(pte_val(pte) & (val)))
+#define pte_isclear(pte, val) (!(pte_val(pte) & (val)))
+
#define pte_none(pte) (!pte_val(pte))
-#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
-#define pte_valid(pte) (pte_val(pte) & L_PTE_VALID)
+#define pte_present(pte) (pte_isset((pte), L_PTE_PRESENT))
+#define pte_valid(pte) (pte_isset((pte), L_PTE_VALID))
#define pte_accessible(mm, pte) (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
-#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
-#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
-#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
+#define pte_write(pte) (pte_isclear((pte), L_PTE_RDONLY))
+#define pte_dirty(pte) (pte_isset((pte), L_PTE_DIRTY))
+#define pte_young(pte) (pte_isset((pte), L_PTE_YOUNG))
+#define pte_exec(pte) (pte_isclear((pte), L_PTE_XN))
#define pte_special(pte) (0)
#define pte_valid_user(pte) \
- (pte_valid(pte) && (pte_val(pte) & L_PTE_USER) && pte_young(pte))
+ (pte_valid(pte) && pte_isset((pte), L_PTE_USER) && pte_young(pte))
#if __LINUX_ARM_ARCH__ < 6
static inline void __sync_icache_dcache(pte_t pteval)
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index ae1919be8f98..0b648c541293 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -42,6 +42,25 @@ struct arm_pmu_platdata {
#ifdef CONFIG_HW_PERF_EVENTS
+/*
+ * The ARMv7 CPU PMU supports up to 32 event counters.
+ */
+#define ARMPMU_MAX_HWEVENTS 32
+
+#define HW_OP_UNSUPPORTED 0xFFFF
+#define C(_x) PERF_COUNT_HW_CACHE_##_x
+#define CACHE_OP_UNSUPPORTED 0xFFFF
+
+#define PERF_MAP_ALL_UNSUPPORTED \
+ [0 ... PERF_COUNT_HW_MAX - 1] = HW_OP_UNSUPPORTED
+
+#define PERF_CACHE_MAP_ALL_UNSUPPORTED \
+[0 ... C(MAX) - 1] = { \
+ [0 ... C(OP_MAX) - 1] = { \
+ [0 ... C(RESULT_MAX) - 1] = CACHE_OP_UNSUPPORTED, \
+ }, \
+}
+
/* The events for a given PMU register set. */
struct pmu_hw_events {
/*
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index c3d5fc124a05..8a1e8e995dae 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -82,6 +82,8 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
#endif
+#define cpu_relax_lowlatency() cpu_relax()
+
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index c877654fe3bf..601264d983fa 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -84,6 +84,12 @@ static inline long regs_return_value(struct pt_regs *regs)
#define instruction_pointer(regs) (regs)->ARM_pc
+#ifdef CONFIG_THUMB2_KERNEL
+#define frame_pointer(regs) (regs)->ARM_r7
+#else
+#define frame_pointer(regs) (regs)->ARM_fp
+#endif
+
static inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val)
{
diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
deleted file mode 100644
index cefdb8f898a1..000000000000
--- a/arch/arm/include/asm/scatterlist.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASMARM_SCATTERLIST_H
-#define _ASMARM_SCATTERLIST_H
-
-#ifdef CONFIG_ARM_HAS_SG_CHAIN
-#define ARCH_HAS_SG_CHAIN
-#endif
-
-#include <asm/memory.h>
-#include <asm/types.h>
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASMARM_SCATTERLIST_H */
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 0393fbab8dd5..bfe163c40024 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -11,7 +11,7 @@
static inline bool scu_a9_has_base(void)
{
- return read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
+ return read_cpuid_part() == ARM_CPU_PART_CORTEX_A9;
}
static inline unsigned long scu_a9_get_base(void)
diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h
index 4d0a16441b29..7722201ead19 100644
--- a/arch/arm/include/asm/stacktrace.h
+++ b/arch/arm/include/asm/stacktrace.h
@@ -1,13 +1,28 @@
#ifndef __ASM_STACKTRACE_H
#define __ASM_STACKTRACE_H
+#include <asm/ptrace.h>
+
struct stackframe {
+ /*
+ * FP member should hold R7 when CONFIG_THUMB2_KERNEL is enabled
+ * and R11 otherwise.
+ */
unsigned long fp;
unsigned long sp;
unsigned long lr;
unsigned long pc;
};
+static __always_inline
+void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
+{
+ frame->fp = frame_pointer(regs);
+ frame->sp = regs->ARM_sp;
+ frame->lr = regs->ARM_lr;
+ frame->pc = regs->ARM_pc;
+}
+
extern int unwind_frame(struct stackframe *frame);
extern void walk_stackframe(struct stackframe *frame,
int (*fn)(struct stackframe *, void *), void *data);
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index e4e4208a9130..fc44d3761f9e 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -14,9 +14,10 @@
#include <linux/compiler.h>
#include <asm/fpstate.h>
+#include <asm/page.h>
#define THREAD_SIZE_ORDER 1
-#define THREAD_SIZE 8192
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_START_SP (THREAD_SIZE - 8)
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 75d95799b6e6..a4cd7af475e9 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -107,6 +107,8 @@ static inline void set_fs(mm_segment_t fs)
extern int __get_user_1(void *);
extern int __get_user_2(void *);
extern int __get_user_4(void *);
+extern int __get_user_lo8(void *);
+extern int __get_user_8(void *);
#define __GUP_CLOBBER_1 "lr", "cc"
#ifdef CONFIG_CPU_USE_DOMAINS
@@ -115,6 +117,8 @@ extern int __get_user_4(void *);
#define __GUP_CLOBBER_2 "lr", "cc"
#endif
#define __GUP_CLOBBER_4 "lr", "cc"
+#define __GUP_CLOBBER_lo8 "lr", "cc"
+#define __GUP_CLOBBER_8 "lr", "cc"
#define __get_user_x(__r2,__p,__e,__l,__s) \
__asm__ __volatile__ ( \
@@ -125,11 +129,19 @@ extern int __get_user_4(void *);
: "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s)
+/* narrowing a double-word get into a single 32bit word register: */
+#ifdef __ARMEB__
+#define __get_user_xb(__r2, __p, __e, __l, __s) \
+ __get_user_x(__r2, __p, __e, __l, lo8)
+#else
+#define __get_user_xb __get_user_x
+#endif
+
#define __get_user_check(x,p) \
({ \
unsigned long __limit = current_thread_info()->addr_limit - 1; \
register const typeof(*(p)) __user *__p asm("r0") = (p);\
- register unsigned long __r2 asm("r2"); \
+ register typeof(x) __r2 asm("r2"); \
register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
switch (sizeof(*(__p))) { \
@@ -142,6 +154,12 @@ extern int __get_user_4(void *);
case 4: \
__get_user_x(__r2, __p, __e, __l, 4); \
break; \
+ case 8: \
+ if (sizeof((x)) < 8) \
+ __get_user_xb(__r2, __p, __e, __l, 4); \
+ else \
+ __get_user_x(__r2, __p, __e, __l, 8); \
+ break; \
default: __e = __get_user_bad(); break; \
} \
x = (typeof(*(p))) __r2; \
@@ -224,7 +242,7 @@ static inline void set_fs(mm_segment_t fs)
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
#define user_addr_max() \
- (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL)
+ (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs())
/*
* The "__xxx" versions of the user access functions do not verify the
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 43876245fc57..32640c431a08 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -15,7 +15,17 @@
#include <uapi/asm/unistd.h>
-#define __NR_syscalls (384)
+/*
+ * This may need to be greater than __NR_last_syscall+1 in order to
+ * account for the padding in the syscall table
+ */
+#define __NR_syscalls (388)
+
+/*
+ * *NOTE*: This is a ghost syscall private to the kernel. Only the
+ * __kuser_cmpxchg code in entry-armv.S should be aware of its
+ * existence. Don't ever use this from user code.
+ */
#define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0)
#define __ARCH_WANT_STAT64
diff --git a/arch/arm/include/debug/clps711x.S b/arch/arm/include/debug/clps711x.S
new file mode 100644
index 000000000000..abe225436686
--- /dev/null
+++ b/arch/arm/include/debug/clps711x.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef CONFIG_DEBUG_CLPS711X_UART2
+#define CLPS711X_UART_PADDR (0x80000000 + 0x0000)
+#define CLPS711X_UART_VADDR (0xfeff0000 + 0x0000)
+#else
+#define CLPS711X_UART_PADDR (0x80000000 + 0x1000)
+#define CLPS711X_UART_VADDR (0xfeff0000 + 0x1000)
+#endif
+
+#define SYSFLG (0x0140)
+#define SYSFLG_UBUSY (1 << 11)
+#define UARTDR (0x0480)
+
+ .macro addruart, rp, rv, tmp
+ ldr \rv, =CLPS711X_UART_VADDR
+ ldr \rp, =CLPS711X_UART_PADDR
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UARTDR]
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #SYSFLG]
+ tst \rd, #SYSFLG_UBUSY
+ bne 1001b
+ .endm
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/include/debug/s5pv210.S
index 30b511a580aa..4f1a73e2c1a1 100644
--- a/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+++ b/arch/arm/include/debug/s5pv210.S
@@ -1,9 +1,6 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/debug-macro.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -12,8 +9,9 @@
/* pull in the relevant register and map files. */
-#include <linux/serial_s3c.h>
-#include <mach/map.h>
+#define S3C_ADDR_BASE 0xF6000000
+#define S3C_VA_UART S3C_ADDR_BASE + 0x01000000
+#define S5PV210_PA_UART 0xe2900000
/* note, for the boot process to work we have to keep the UART
* virtual address aligned to an 1MiB boundary for the L1
@@ -22,8 +20,8 @@
*/
.macro addruart, rp, rv, tmp
- ldr \rp, = S3C_PA_UART
- ldr \rv, = S3C_VA_UART
+ ldr \rp, =S5PV210_PA_UART
+ ldr \rv, =S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
@@ -33,9 +31,4 @@
#define fifo_full fifo_full_s5pv210
#define fifo_level fifo_level_s5pv210
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
#include <debug/samsung.S>
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index ba94446c72d9..3aaa75cae90c 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -409,11 +409,9 @@
#define __NR_sched_setattr (__NR_SYSCALL_BASE+380)
#define __NR_sched_getattr (__NR_SYSCALL_BASE+381)
#define __NR_renameat2 (__NR_SYSCALL_BASE+382)
-
-/*
- * This may need to be greater than __NR_last_syscall+1 in order to
- * account for the padding in the syscall table
- */
+#define __NR_seccomp (__NR_SYSCALL_BASE+383)
+#define __NR_getrandom (__NR_SYSCALL_BASE+384)
+#define __NR_memfd_create (__NR_SYSCALL_BASE+385)
/*
* The following SWIs are ARM private.
@@ -426,12 +424,6 @@
#define __ARM_NR_set_tls (__ARM_NR_BASE+5)
/*
- * *NOTE*: This is a ghost syscall private to the kernel. Only the
- * __kuser_cmpxchg code in entry-armv.S should be aware of its
- * existence. Don't ever use this from user code.
- */
-
-/*
* The following syscalls are obsolete and no longer available for EABI.
*/
#if !defined(__KERNEL__)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 85598b5d1efd..713e807621d2 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -182,13 +182,13 @@ int main(void)
DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
#ifdef CONFIG_KVM_ARM_VGIC
DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu));
- DEFINE(VGIC_CPU_HCR, offsetof(struct vgic_cpu, vgic_hcr));
- DEFINE(VGIC_CPU_VMCR, offsetof(struct vgic_cpu, vgic_vmcr));
- DEFINE(VGIC_CPU_MISR, offsetof(struct vgic_cpu, vgic_misr));
- DEFINE(VGIC_CPU_EISR, offsetof(struct vgic_cpu, vgic_eisr));
- DEFINE(VGIC_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_elrsr));
- DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
- DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
+ DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
+ DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
+ DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
+ DEFINE(VGIC_V2_CPU_EISR, offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
+ DEFINE(VGIC_V2_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
+ DEFINE(VGIC_V2_CPU_APR, offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
+ DEFINE(VGIC_V2_CPU_LR, offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
#ifdef CONFIG_KVM_ARM_TIMER
DEFINE(VCPU_TIMER_CNTV_CTL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 8f51bdcdacbb..9f899d8fdcca 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -392,6 +392,9 @@
/* 380 */ CALL(sys_sched_setattr)
CALL(sys_sched_getattr)
CALL(sys_renameat2)
+ CALL(sys_seccomp)
+ CALL(sys_getrandom)
+/* 385 */ CALL(sys_memfd_create)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 14f7c3b14632..78c91b5f97d4 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -90,7 +90,7 @@ ENTRY(printascii)
ldrneb r1, [r0], #1
teqne r1, #0
bne 1b
- mov pc, lr
+ ret lr
ENDPROC(printascii)
ENTRY(printch)
@@ -105,7 +105,7 @@ ENTRY(debug_ll_addr)
addruart r2, r3, ip
str r2, [r0]
str r3, [r1]
- mov pc, lr
+ ret lr
ENDPROC(debug_ll_addr)
#endif
@@ -116,7 +116,7 @@ ENTRY(printascii)
mov r0, #0x04 @ SYS_WRITE0
ARM( svc #0x123456 )
THUMB( svc #0xab )
- mov pc, lr
+ ret lr
ENDPROC(printascii)
ENTRY(printch)
@@ -125,14 +125,14 @@ ENTRY(printch)
mov r0, #0x03 @ SYS_WRITEC
ARM( svc #0x123456 )
THUMB( svc #0xab )
- mov pc, lr
+ ret lr
ENDPROC(printch)
ENTRY(debug_ll_addr)
mov r2, #0
str r2, [r0]
str r2, [r1]
- mov pc, lr
+ ret lr
ENDPROC(debug_ll_addr)
#endif
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 52a949a8077d..36276cdccfbc 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -224,7 +224,7 @@ svc_preempt:
1: bl preempt_schedule_irq @ irq en/disable is done inside
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
tst r0, #_TIF_NEED_RESCHED
- moveq pc, r8 @ go again
+ reteq r8 @ go again
b 1b
#endif
@@ -490,7 +490,7 @@ ENDPROC(__und_usr)
.pushsection .fixup, "ax"
.align 2
4: str r4, [sp, #S_PC] @ retry current instruction
- mov pc, r9
+ ret r9
.popsection
.pushsection __ex_table,"a"
.long 1b, 4b
@@ -552,7 +552,7 @@ call_fpe:
#endif
tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
- moveq pc, lr
+ reteq lr
and r8, r0, #0x00000f00 @ mask out CP number
THUMB( lsr r8, r8, #8 )
mov r7, #1
@@ -571,33 +571,33 @@ call_fpe:
THUMB( add pc, r8 )
nop
- movw_pc lr @ CP#0
+ ret.w lr @ CP#0
W(b) do_fpe @ CP#1 (FPE)
W(b) do_fpe @ CP#2 (FPE)
- movw_pc lr @ CP#3
+ ret.w lr @ CP#3
#ifdef CONFIG_CRUNCH
b crunch_task_enable @ CP#4 (MaverickCrunch)
b crunch_task_enable @ CP#5 (MaverickCrunch)
b crunch_task_enable @ CP#6 (MaverickCrunch)
#else
- movw_pc lr @ CP#4
- movw_pc lr @ CP#5
- movw_pc lr @ CP#6
+ ret.w lr @ CP#4
+ ret.w lr @ CP#5
+ ret.w lr @ CP#6
#endif
- movw_pc lr @ CP#7
- movw_pc lr @ CP#8
- movw_pc lr @ CP#9
+ ret.w lr @ CP#7
+ ret.w lr @ CP#8
+ ret.w lr @ CP#9
#ifdef CONFIG_VFP
W(b) do_vfp @ CP#10 (VFP)
W(b) do_vfp @ CP#11 (VFP)
#else
- movw_pc lr @ CP#10 (VFP)
- movw_pc lr @ CP#11 (VFP)
+ ret.w lr @ CP#10 (VFP)
+ ret.w lr @ CP#11 (VFP)
#endif
- movw_pc lr @ CP#12
- movw_pc lr @ CP#13
- movw_pc lr @ CP#14 (Debug)
- movw_pc lr @ CP#15 (Control)
+ ret.w lr @ CP#12
+ ret.w lr @ CP#13
+ ret.w lr @ CP#14 (Debug)
+ ret.w lr @ CP#15 (Control)
#ifdef NEED_CPU_ARCHITECTURE
.align 2
@@ -649,7 +649,7 @@ ENTRY(fp_enter)
.popsection
ENTRY(no_fp)
- mov pc, lr
+ ret lr
ENDPROC(no_fp)
__und_usr_fault_32:
@@ -745,7 +745,7 @@ ENDPROC(__switch_to)
#ifdef CONFIG_ARM_THUMB
bx \reg
#else
- mov pc, \reg
+ ret \reg
#endif
.endm
@@ -837,7 +837,7 @@ kuser_cmpxchg64_fixup:
#if __LINUX_ARM_ARCH__ < 6
bcc kuser_cmpxchg32_fixup
#endif
- mov pc, lr
+ ret lr
.previous
#else
@@ -905,7 +905,7 @@ kuser_cmpxchg32_fixup:
subs r8, r4, r7
rsbcss r8, r8, #(2b - 1b)
strcs r7, [sp, #S_PC]
- mov pc, lr
+ ret lr
.previous
#else
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 7139d4a7dea7..e52fe5a2d843 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
+#include <asm/assembler.h>
#include <asm/unistd.h>
#include <asm/ftrace.h>
#include <asm/unwind.h>
@@ -88,7 +89,7 @@ ENTRY(ret_from_fork)
cmp r5, #0
movne r0, r4
adrne lr, BSYM(1f)
- movne pc, r5
+ retne r5
1: get_thread_info tsk
b ret_slow_syscall
ENDPROC(ret_from_fork)
@@ -290,7 +291,7 @@ ENDPROC(ftrace_graph_caller_old)
.macro mcount_exit
ldmia sp!, {r0-r3, ip, lr}
- mov pc, ip
+ ret ip
.endm
ENTRY(__gnu_mcount_nc)
@@ -298,7 +299,7 @@ UNWIND(.fnstart)
#ifdef CONFIG_DYNAMIC_FTRACE
mov ip, lr
ldmia sp!, {lr}
- mov pc, ip
+ ret ip
#else
__mcount
#endif
@@ -333,12 +334,12 @@ return_to_handler:
bl ftrace_return_to_handler
mov lr, r0 @ r0 has real ret addr
ldmia sp!, {r0-r3}
- mov pc, lr
+ ret lr
#endif
ENTRY(ftrace_stub)
.Lftrace_stub:
- mov pc, lr
+ ret lr
ENDPROC(ftrace_stub)
#endif /* CONFIG_FUNCTION_TRACER */
@@ -561,7 +562,7 @@ sys_mmap2:
streq r5, [sp, #4]
beq sys_mmap_pgoff
mov r0, #-EINVAL
- mov pc, lr
+ ret lr
#else
str r5, [sp, #4]
b sys_mmap_pgoff
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 5d702f8900b1..8db307d0954b 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -240,12 +240,6 @@
movs pc, lr @ return & move spsr_svc into cpsr
.endm
- @
- @ 32-bit wide "mov pc, reg"
- @
- .macro movw_pc, reg
- mov pc, \reg
- .endm
#else /* CONFIG_THUMB2_KERNEL */
.macro svc_exit, rpsr, irq = 0
.if \irq != 0
@@ -304,14 +298,6 @@
movs pc, lr @ return & move spsr_svc into cpsr
.endm
#endif /* ifdef CONFIG_CPU_V7M / else */
-
- @
- @ 32-bit wide "mov pc, reg"
- @
- .macro movw_pc, reg
- mov pc, \reg
- nop
- .endm
#endif /* !CONFIG_THUMB2_KERNEL */
/*
diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S
index 207f9d652010..8dd26e1a9bd6 100644
--- a/arch/arm/kernel/fiqasm.S
+++ b/arch/arm/kernel/fiqasm.S
@@ -32,7 +32,7 @@ ENTRY(__set_fiq_regs)
ldr lr, [r0]
msr cpsr_c, r1 @ return to SVC mode
mov r0, r0 @ avoid hazard prior to ARMv4
- mov pc, lr
+ ret lr
ENDPROC(__set_fiq_regs)
ENTRY(__get_fiq_regs)
@@ -45,5 +45,5 @@ ENTRY(__get_fiq_regs)
str lr, [r0]
msr cpsr_c, r1 @ return to SVC mode
mov r0, r0 @ avoid hazard prior to ARMv4
- mov pc, lr
+ ret lr
ENDPROC(__get_fiq_regs)
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 572a38335c96..8733012d231f 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*
*/
+#include <asm/assembler.h>
#define ATAG_CORE 0x54410001
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
@@ -61,10 +62,10 @@ __vet_atags:
cmp r5, r6
bne 1f
-2: mov pc, lr @ atag/dtb pointer is ok
+2: ret lr @ atag/dtb pointer is ok
1: mov r2, #0
- mov pc, lr
+ ret lr
ENDPROC(__vet_atags)
/*
@@ -162,7 +163,7 @@ __lookup_processor_type:
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
-2: mov pc, lr
+2: ret lr
ENDPROC(__lookup_processor_type)
/*
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 716249cc2ee1..cc176b67c134 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -82,7 +82,7 @@ ENTRY(stext)
adr lr, BSYM(1f) @ return (PIC) address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
- THUMB( mov pc, r12 )
+ THUMB( ret r12 )
1: b __after_proc_init
ENDPROC(stext)
@@ -119,7 +119,7 @@ ENTRY(secondary_startup)
mov r13, r12 @ __secondary_switched address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
- THUMB( mov pc, r12 )
+ THUMB( ret r12 )
ENDPROC(secondary_startup)
ENTRY(__secondary_switched)
@@ -164,7 +164,7 @@ __after_proc_init:
#endif
mcr p15, 0, r0, c1, c0, 0 @ write control reg
#endif /* CONFIG_CPU_CP15 */
- mov pc, r13
+ ret r13
ENDPROC(__after_proc_init)
.ltorg
@@ -254,7 +254,7 @@ ENTRY(__setup_mpu)
orr r0, r0, #CR_M @ Set SCTRL.M (MPU on)
mcr p15, 0, r0, c1, c0, 0 @ Enable MPU
isb
- mov pc,lr
+ ret lr
ENDPROC(__setup_mpu)
#endif
#include "head-common.S"
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 2c35f0ff2fdc..664eee8c4a26 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -140,7 +140,7 @@ ENTRY(stext)
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
- THUMB( mov pc, r12 )
+ THUMB( ret r12 )
1: b __enable_mmu
ENDPROC(stext)
.ltorg
@@ -335,7 +335,7 @@ __create_page_tables:
sub r4, r4, #0x1000 @ point to the PGD table
mov r4, r4, lsr #ARCH_PGD_SHIFT
#endif
- mov pc, lr
+ ret lr
ENDPROC(__create_page_tables)
.ltorg
.align
@@ -383,7 +383,7 @@ ENTRY(secondary_startup)
ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
@ (return control reg)
THUMB( add r12, r10, #PROCINFO_INITFUNC )
- THUMB( mov pc, r12 )
+ THUMB( ret r12 )
ENDPROC(secondary_startup)
/*
@@ -468,7 +468,7 @@ ENTRY(__turn_mmu_on)
instr_sync
mov r3, r3
mov r3, r13
- mov pc, r3
+ ret r3
__turn_mmu_on_end:
ENDPROC(__turn_mmu_on)
.popsection
@@ -487,7 +487,7 @@ __fixup_smp:
orr r4, r4, #0x0000b000
orr r4, r4, #0x00000020 @ val 0x4100b020
teq r3, r4 @ ARM 11MPCore?
- moveq pc, lr @ yes, assume SMP
+ reteq lr @ yes, assume SMP
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
and r0, r0, #0xc0000000 @ multiprocessing extensions and
@@ -500,7 +500,7 @@ __fixup_smp:
orr r4, r4, #0x0000c000
orr r4, r4, #0x00000090
teq r3, r4 @ Check for ARM Cortex-A9
- movne pc, lr @ Not ARM Cortex-A9,
+ retne lr @ Not ARM Cortex-A9,
@ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the
@ below address check will need to be #ifdef'd or equivalent
@@ -512,7 +512,7 @@ __fixup_smp:
ARM_BE8(rev r0, r0) @ byteswap if big endian
and r0, r0, #0x3 @ number of CPUs
teq r0, #0x0 @ is 1?
- movne pc, lr
+ retne lr
__fixup_smp_on_up:
adr r0, 1f
@@ -539,7 +539,7 @@ smp_on_up:
.text
__do_fixup_smp_on_up:
cmp r4, r5
- movhs pc, lr
+ reths lr
ldmia r4!, {r0, r6}
ARM( str r6, [r0, r3] )
THUMB( add r0, r0, r3 )
@@ -672,7 +672,7 @@ ARM_BE8(rev16 ip, ip)
2: cmp r4, r5
ldrcc r7, [r4], #4 @ use branch for delay slot
bcc 1b
- mov pc, lr
+ ret lr
#endif
ENDPROC(__fixup_a_pv_table)
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index 797b1a6a4906..2a55373f49bf 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary)
* immediately.
*/
compare_cpu_mode_with_primary r4, r5, r6, r7
- movne pc, lr
+ retne lr
/*
* Once we have given up on one CPU, we do not try to install the
@@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary)
*/
cmp r4, #HYP_MODE
- movne pc, lr @ give up if the CPU is not in HYP mode
+ retne lr @ give up if the CPU is not in HYP mode
/*
* Configure HSCTLR to set correct exception endianness/instruction set
@@ -134,9 +134,7 @@ ENTRY(__hyp_stub_install_secondary)
mcr p15, 4, r7, c1, c1, 3 @ HSTR
THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE
-#ifdef CONFIG_CPU_BIG_ENDIAN
- orr r7, #(1 << 9) @ HSCTLR.EE
-#endif
+ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
mcr p15, 4, r7, c1, c0, 0 @ HSCTLR
mrc p15, 4, r7, c1, c1, 1 @ HDCR
@@ -201,7 +199,7 @@ ENDPROC(__hyp_get_vectors)
@ fall through
ENTRY(__hyp_set_vectors)
__HVC(0)
- mov pc, lr
+ ret lr
ENDPROC(__hyp_set_vectors)
#ifndef ZIMAGE
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index 2b32978ae905..ad58e565fe98 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -100,7 +100,7 @@ ENTRY(iwmmxt_task_enable)
get_thread_info r10
#endif
4: dec_preempt_count r10, r3
- mov pc, r9 @ normal exit from exception
+ ret r9 @ normal exit from exception
concan_save:
@@ -144,7 +144,7 @@ concan_dump:
wstrd wR15, [r1, #MMX_WR15]
2: teq r0, #0 @ anything to load?
- moveq pc, lr @ if not, return
+ reteq lr @ if not, return
concan_load:
@@ -177,10 +177,10 @@ concan_load:
@ clear CUP/MUP (only if r1 != 0)
teq r1, #0
mov r2, #0
- moveq pc, lr
+ reteq lr
tmcr wCon, r2
- mov pc, lr
+ ret lr
/*
* Back up Concan regs to save area and disable access to them
@@ -266,7 +266,7 @@ ENTRY(iwmmxt_task_copy)
mov r3, lr @ preserve return address
bl concan_dump
msr cpsr_c, ip @ restore interrupt mode
- mov pc, r3
+ ret r3
/*
* Restore Concan state from given memory address
@@ -302,7 +302,7 @@ ENTRY(iwmmxt_task_restore)
mov r3, lr @ preserve return address
bl concan_load
msr cpsr_c, ip @ restore interrupt mode
- mov pc, r3
+ ret r3
/*
* Concan handling on task switch
@@ -324,7 +324,7 @@ ENTRY(iwmmxt_task_switch)
add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area
ldr r2, [r2] @ get current Concan owner
teq r2, r3 @ next task owns it?
- movne pc, lr @ no: leave Concan disabled
+ retne lr @ no: leave Concan disabled
1: @ flip Concan access
XSC(eor r1, r1, #0x3)
@@ -351,7 +351,7 @@ ENTRY(iwmmxt_task_release)
eors r0, r0, r1 @ if equal...
streq r0, [r3] @ then clear ownership
msr cpsr_c, r2 @ restore interrupts
- mov pc, lr
+ ret lr
.data
concan_owner:
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 4238bcba9d60..266cba46db3e 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -560,11 +560,16 @@ user_backtrace(struct frame_tail __user *tail,
struct perf_callchain_entry *entry)
{
struct frame_tail buftail;
+ unsigned long err;
- /* Also check accessibility of one struct frame_tail beyond */
if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
return NULL;
- if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
+
+ pagefault_disable();
+ err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+ pagefault_enable();
+
+ if (err)
return NULL;
perf_callchain_store(entry, buftail.lr);
@@ -590,6 +595,10 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
}
perf_callchain_store(entry, regs->ARM_pc);
+
+ if (!current->mm)
+ return;
+
tail = (struct frame_tail __user *)regs->ARM_fp - 1;
while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
@@ -621,10 +630,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
return;
}
- fr.fp = regs->ARM_fp;
- fr.sp = regs->ARM_sp;
- fr.lr = regs->ARM_lr;
- fr.pc = regs->ARM_pc;
+ arm_get_current_stackframe(regs, &fr);
walk_stackframe(&fr, callchain_trace, entry);
}
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index af9e35e8836f..e6a6edbec613 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -233,14 +233,17 @@ static struct of_device_id cpu_pmu_of_device_ids[] = {
{.compatible = "arm,cortex-a7-pmu", .data = armv7_a7_pmu_init},
{.compatible = "arm,cortex-a5-pmu", .data = armv7_a5_pmu_init},
{.compatible = "arm,arm11mpcore-pmu", .data = armv6mpcore_pmu_init},
- {.compatible = "arm,arm1176-pmu", .data = armv6pmu_init},
- {.compatible = "arm,arm1136-pmu", .data = armv6pmu_init},
+ {.compatible = "arm,arm1176-pmu", .data = armv6_1176_pmu_init},
+ {.compatible = "arm,arm1136-pmu", .data = armv6_1136_pmu_init},
{.compatible = "qcom,krait-pmu", .data = krait_pmu_init},
{},
};
static struct platform_device_id cpu_pmu_plat_device_ids[] = {
{.name = "arm-pmu"},
+ {.name = "armv6-pmu"},
+ {.name = "armv7-pmu"},
+ {.name = "xscale-pmu"},
{},
};
@@ -250,40 +253,43 @@ static struct platform_device_id cpu_pmu_plat_device_ids[] = {
static int probe_current_pmu(struct arm_pmu *pmu)
{
int cpu = get_cpu();
- unsigned long implementor = read_cpuid_implementor();
- unsigned long part_number = read_cpuid_part_number();
int ret = -ENODEV;
pr_info("probing PMU on CPU %d\n", cpu);
+ switch (read_cpuid_part()) {
/* ARM Ltd CPUs. */
- if (implementor == ARM_CPU_IMP_ARM) {
- switch (part_number) {
- case ARM_CPU_PART_ARM1136:
- case ARM_CPU_PART_ARM1156:
- case ARM_CPU_PART_ARM1176:
- ret = armv6pmu_init(pmu);
- break;
- case ARM_CPU_PART_ARM11MPCORE:
- ret = armv6mpcore_pmu_init(pmu);
- break;
- case ARM_CPU_PART_CORTEX_A8:
- ret = armv7_a8_pmu_init(pmu);
- break;
- case ARM_CPU_PART_CORTEX_A9:
- ret = armv7_a9_pmu_init(pmu);
- break;
- }
- /* Intel CPUs [xscale]. */
- } else if (implementor == ARM_CPU_IMP_INTEL) {
- switch (xscale_cpu_arch_version()) {
- case ARM_CPU_XSCALE_ARCH_V1:
- ret = xscale1pmu_init(pmu);
- break;
- case ARM_CPU_XSCALE_ARCH_V2:
- ret = xscale2pmu_init(pmu);
- break;
+ case ARM_CPU_PART_ARM1136:
+ ret = armv6_1136_pmu_init(pmu);
+ break;
+ case ARM_CPU_PART_ARM1156:
+ ret = armv6_1156_pmu_init(pmu);
+ break;
+ case ARM_CPU_PART_ARM1176:
+ ret = armv6_1176_pmu_init(pmu);
+ break;
+ case ARM_CPU_PART_ARM11MPCORE:
+ ret = armv6mpcore_pmu_init(pmu);
+ break;
+ case ARM_CPU_PART_CORTEX_A8:
+ ret = armv7_a8_pmu_init(pmu);
+ break;
+ case ARM_CPU_PART_CORTEX_A9:
+ ret = armv7_a9_pmu_init(pmu);
+ break;
+
+ default:
+ if (read_cpuid_implementor() == ARM_CPU_IMP_INTEL) {
+ switch (xscale_cpu_arch_version()) {
+ case ARM_CPU_XSCALE_ARCH_V1:
+ ret = xscale1pmu_init(pmu);
+ break;
+ case ARM_CPU_XSCALE_ARCH_V2:
+ ret = xscale2pmu_init(pmu);
+ break;
+ }
}
+ break;
}
put_cpu();
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 03664b0e8fa4..abfeb04f3213 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -65,13 +65,11 @@ enum armv6_counters {
* accesses/misses in hardware.
*/
static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV6_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV6_PERFCTR_INSTR_EXEC,
- [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV6_PERFCTR_BR_MISPREDICT,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV6_PERFCTR_IBUF_STALL,
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV6_PERFCTR_LSU_FULL_STALL,
};
@@ -79,116 +77,31 @@ static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = {
static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- /*
- * The performance counters don't differentiate between read
- * and write accesses/misses so this isn't strictly correct,
- * but it's the best we can do. Writes and reads get
- * combined.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- /*
- * The ARM performance counters can count micro DTLB misses,
- * micro ITLB misses and main TLB misses. There isn't an event
- * for TLB misses, so use the micro misses here and if users
- * want the main TLB misses they can use a raw counter.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ /*
+ * The performance counters don't differentiate between read and write
+ * accesses/misses so this isn't strictly correct, but it's the best we
+ * can do. Writes and reads get combined.
+ */
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS,
+
+ /*
+ * The ARM performance counters can count micro DTLB misses, micro ITLB
+ * misses and main TLB misses. There isn't an event for TLB misses, so
+ * use the micro misses here and if users want the main TLB misses they
+ * can use a raw counter.
+ */
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS,
};
enum armv6mpcore_perf_types {
@@ -220,13 +133,11 @@ enum armv6mpcore_perf_types {
* accesses/misses in hardware.
*/
static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV6MPCORE_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_INSTR_EXEC,
- [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV6MPCORE_PERFCTR_BR_MISPREDICT,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV6MPCORE_PERFCTR_IBUF_STALL,
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV6MPCORE_PERFCTR_LSU_FULL_STALL,
};
@@ -234,114 +145,26 @@ static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = {
static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] =
- ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
- [C(RESULT_MISS)] =
- ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] =
- ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
- [C(RESULT_MISS)] =
- ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- /*
- * The ARM performance counters can count micro DTLB misses,
- * micro ITLB misses and main TLB misses. There isn't an event
- * for TLB misses, so use the micro misses here and if users
- * want the main TLB misses they can use a raw counter.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DCACHE_RDMISS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DCACHE_WRMISS,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+
+ /*
+ * The ARM performance counters can count micro DTLB misses, micro ITLB
+ * misses and main TLB misses. There isn't an event for TLB misses, so
+ * use the micro misses here and if users want the main TLB misses they
+ * can use a raw counter.
+ */
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS,
};
static inline unsigned long
@@ -653,9 +476,8 @@ static int armv6_map_event(struct perf_event *event)
&armv6_perf_cache_map, 0xFF);
}
-static int armv6pmu_init(struct arm_pmu *cpu_pmu)
+static void armv6pmu_init(struct arm_pmu *cpu_pmu)
{
- cpu_pmu->name = "v6";
cpu_pmu->handle_irq = armv6pmu_handle_irq;
cpu_pmu->enable = armv6pmu_enable_event;
cpu_pmu->disable = armv6pmu_disable_event;
@@ -667,7 +489,26 @@ static int armv6pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->map_event = armv6_map_event;
cpu_pmu->num_events = 3;
cpu_pmu->max_period = (1LLU << 32) - 1;
+}
+
+static int armv6_1136_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ armv6pmu_init(cpu_pmu);
+ cpu_pmu->name = "armv6_1136";
+ return 0;
+}
+static int armv6_1156_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ armv6pmu_init(cpu_pmu);
+ cpu_pmu->name = "armv6_1156";
+ return 0;
+}
+
+static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ armv6pmu_init(cpu_pmu);
+ cpu_pmu->name = "armv6_1176";
return 0;
}
@@ -687,7 +528,7 @@ static int armv6mpcore_map_event(struct perf_event *event)
static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
{
- cpu_pmu->name = "v6mpcore";
+ cpu_pmu->name = "armv6_11mpcore";
cpu_pmu->handle_irq = armv6pmu_handle_irq;
cpu_pmu->enable = armv6pmu_enable_event;
cpu_pmu->disable = armv6mpcore_pmu_disable_event;
@@ -703,7 +544,17 @@ static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
return 0;
}
#else
-static int armv6pmu_init(struct arm_pmu *cpu_pmu)
+static int armv6_1136_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ return -ENODEV;
+}
+
+static int armv6_1156_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ return -ENODEV;
+}
+
+static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
{
return -ENODEV;
}
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 1d37568c547a..116758b77f93 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -148,137 +148,62 @@ enum krait_perf_types {
* accesses/misses in hardware.
*/
static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
[PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A8_PERFCTR_STALL_ISIDE,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- /*
- * The performance counters don't differentiate between read
- * and write accesses/misses so this isn't strictly correct,
- * but it's the best we can do. Writes and reads get
- * combined.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ /*
+ * The performance counters don't differentiate between read and write
+ * accesses/misses so this isn't strictly correct, but it's the best we
+ * can do. Writes and reads get combined.
+ */
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+ [C(LL)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
+ [C(LL)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
+ [C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS,
+ [C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Cortex-A9 HW events mapping
*/
static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_A9_PERFCTR_INSTR_CORE_RENAME,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
[PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A9_PERFCTR_STALL_ICACHE,
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV7_A9_PERFCTR_STALL_DISPATCH,
};
@@ -286,238 +211,83 @@ static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- /*
- * The performance counters don't differentiate between read
- * and write accesses/misses so this isn't strictly correct,
- * but it's the best we can do. Writes and reads get
- * combined.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ /*
+ * The performance counters don't differentiate between read and write
+ * accesses/misses so this isn't strictly correct, but it's the best we
+ * can do. Writes and reads get combined.
+ */
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Cortex-A5 HW events mapping
*/
static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
[PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
- [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- /*
- * The prefetch counters don't differentiate between the I
- * side and the D side.
- */
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
- [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
+ [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+ /*
+ * The prefetch counters don't differentiate between the I side and the
+ * D side.
+ */
+ [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL,
+ [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Cortex-A15 HW events mapping
*/
static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -525,123 +295,48 @@ static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_A15_PERFCTR_PC_WRITE_SPEC,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
[PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES,
- [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- /*
- * Not all performance counters differentiate between read
- * and write accesses/misses so we're not always strictly
- * correct, but it's the best we can do. Writes and reads get
- * combined in these cases.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE,
+
+ /*
+ * Not all performance counters differentiate between read and write
+ * accesses/misses so we're not always strictly correct, but it's the
+ * best we can do. Writes and reads get combined in these cases.
+ */
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+ [C(LL)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ,
+ [C(LL)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ,
+ [C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE,
+ [C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Cortex-A7 HW events mapping
*/
static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -649,123 +344,48 @@ static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
[PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES,
- [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- /*
- * The performance counters don't differentiate between read
- * and write accesses/misses so this isn't strictly correct,
- * but it's the best we can do. Writes and reads get
- * combined.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ /*
+ * The performance counters don't differentiate between read and write
+ * accesses/misses so this isn't strictly correct, but it's the best we
+ * can do. Writes and reads get combined.
+ */
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+ [C(LL)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+ [C(LL)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
+ [C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+ [C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Cortex-A12 HW events mapping
*/
static const unsigned armv7_a12_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
@@ -773,138 +393,60 @@ static const unsigned armv7_a12_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_A12_PERFCTR_PC_WRITE_SPEC,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
[PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES,
- [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned armv7_a12_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- /*
- * Not all performance counters differentiate between read
- * and write accesses/misses so we're not always strictly
- * correct, but it's the best we can do. Writes and reads get
- * combined in these cases.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_A12_PERFCTR_PF_TLB_REFILL,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_READ,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L1_DCACHE_ACCESS_WRITE,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+ /*
+ * Not all performance counters differentiate between read and write
+ * accesses/misses so we're not always strictly correct, but it's the
+ * best we can do. Writes and reads get combined in these cases.
+ */
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+
+ [C(LL)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_READ,
+ [C(LL)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
+ [C(LL)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_A12_PERFCTR_L2_CACHE_ACCESS_WRITE,
+ [C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ [C(DTLB)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV7_A12_PERFCTR_PF_TLB_REFILL,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
* Krait HW events mapping
*/
static const unsigned krait_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
- [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
[PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
};
static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
- [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
[PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
};
@@ -912,110 +454,31 @@ static const unsigned krait_perf_map_no_branch[PERF_COUNT_HW_MAX] = {
static const unsigned krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- /*
- * The performance counters don't differentiate between read
- * and write accesses/misses so this isn't strictly correct,
- * but it's the best we can do. Writes and reads get
- * combined.
- */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ICACHE_ACCESS,
- [C(RESULT_MISS)] = KRAIT_PERFCTR_L1_ICACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_DTLB_ACCESS,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_DTLB_ACCESS,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ITLB_ACCESS,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ITLB_ACCESS,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
- [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ /*
+ * The performance counters don't differentiate between read and write
+ * accesses/misses so this isn't strictly correct, but it's the best we
+ * can do. Writes and reads get combined.
+ */
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ICACHE_ACCESS,
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = KRAIT_PERFCTR_L1_ICACHE_MISS,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_DTLB_ACCESS,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_DTLB_ACCESS,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ITLB_ACCESS,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = KRAIT_PERFCTR_L1_ITLB_ACCESS,
+
+ [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_READ)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
};
/*
@@ -1545,7 +1008,7 @@ static u32 armv7_read_num_pmnc_events(void)
static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A8";
+ cpu_pmu->name = "armv7_cortex_a8";
cpu_pmu->map_event = armv7_a8_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
return 0;
@@ -1554,7 +1017,7 @@ static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A9";
+ cpu_pmu->name = "armv7_cortex_a9";
cpu_pmu->map_event = armv7_a9_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
return 0;
@@ -1563,7 +1026,7 @@ static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A5";
+ cpu_pmu->name = "armv7_cortex_a5";
cpu_pmu->map_event = armv7_a5_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
return 0;
@@ -1572,7 +1035,7 @@ static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A15";
+ cpu_pmu->name = "armv7_cortex_a15";
cpu_pmu->map_event = armv7_a15_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1582,7 +1045,7 @@ static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A7";
+ cpu_pmu->name = "armv7_cortex_a7";
cpu_pmu->map_event = armv7_a7_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1592,7 +1055,7 @@ static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A12";
+ cpu_pmu->name = "armv7_cortex_a12";
cpu_pmu->map_event = armv7_a12_map_event;
cpu_pmu->num_events = armv7_read_num_pmnc_events();
cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
@@ -1602,7 +1065,7 @@ static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu)
static int armv7_a17_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7_a12_pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Cortex-A17";
+ cpu_pmu->name = "armv7_cortex_a17";
return 0;
}
@@ -1823,6 +1286,7 @@ static void krait_pmu_disable_event(struct perf_event *event)
unsigned long flags;
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
+ struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct pmu_hw_events *events = cpu_pmu->get_hw_events();
/* Disable counter and interrupt */
@@ -1848,6 +1312,7 @@ static void krait_pmu_enable_event(struct perf_event *event)
unsigned long flags;
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
+ struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct pmu_hw_events *events = cpu_pmu->get_hw_events();
/*
@@ -1981,7 +1446,7 @@ static void krait_pmu_clear_event_idx(struct pmu_hw_events *cpuc,
static int krait_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
- cpu_pmu->name = "ARMv7 Krait";
+ cpu_pmu->name = "armv7_krait";
/* Some early versions of Krait don't support PC write events */
if (of_property_read_bool(cpu_pmu->plat_device->dev.of_node,
"qcom,no-pc-write"))
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 63990c42fac9..08da0af550b7 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -48,118 +48,31 @@ enum xscale_counters {
};
static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
+ PERF_MAP_ALL_UNSUPPORTED,
[PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT,
[PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION,
- [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
- [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
[PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS,
- [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XSCALE_PERFCTR_ICACHE_NO_DELIVER,
- [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED,
};
static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
- [C(L1D)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(L1I)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(DTLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(ITLB)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(BPU)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
- [C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
- [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
- },
- },
+ PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+ [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
+ [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
+ [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
+
+ [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
+
+ [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
+ [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
+
+ [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
+ [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
};
#define XSCALE_PMU_ENABLE 0x001
@@ -442,7 +355,7 @@ static int xscale_map_event(struct perf_event *event)
static int xscale1pmu_init(struct arm_pmu *cpu_pmu)
{
- cpu_pmu->name = "xscale1";
+ cpu_pmu->name = "armv5_xscale1";
cpu_pmu->handle_irq = xscale1pmu_handle_irq;
cpu_pmu->enable = xscale1pmu_enable_event;
cpu_pmu->disable = xscale1pmu_disable_event;
@@ -812,7 +725,7 @@ static inline void xscale2pmu_write_counter(struct perf_event *event, u32 val)
static int xscale2pmu_init(struct arm_pmu *cpu_pmu)
{
- cpu_pmu->name = "xscale2";
+ cpu_pmu->name = "armv5_xscale2";
cpu_pmu->handle_irq = xscale2pmu_handle_irq;
cpu_pmu->enable = xscale2pmu_enable_event;
cpu_pmu->disable = xscale2pmu_disable_event;
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 95858966d84e..35e72585ec1d 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -3,6 +3,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/kexec.h>
.align 3 /* not needed for this code, but keeps fncpy() happy */
@@ -59,7 +60,7 @@ ENTRY(relocate_new_kernel)
mov r0,#0
ldr r1,kexec_mach_type
ldr r2,kexec_boot_atags
- ARM( mov pc, lr )
+ ARM( ret lr )
THUMB( bx lr )
.align
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8a16ee5d8a95..84db893dedc2 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -393,19 +393,34 @@ static void __init cpuid_init_hwcaps(void)
elf_hwcap |= HWCAP_LPAE;
}
-static void __init feat_v6_fixup(void)
+static void __init elf_hwcap_fixup(void)
{
- int id = read_cpuid_id();
-
- if ((id & 0xff0f0000) != 0x41070000)
- return;
+ unsigned id = read_cpuid_id();
+ unsigned sync_prim;
/*
* HWCAP_TLS is available only on 1136 r1p0 and later,
* see also kuser_get_tls_init.
*/
- if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0))
+ if (read_cpuid_part() == ARM_CPU_PART_ARM1136 &&
+ ((id >> 20) & 3) == 0) {
elf_hwcap &= ~HWCAP_TLS;
+ return;
+ }
+
+ /* Verify if CPUID scheme is implemented */
+ if ((id & 0x000f0000) != 0x000f0000)
+ return;
+
+ /*
+ * If the CPU supports LDREX/STREX and LDREXB/STREXB,
+ * avoid advertising SWP; it may not be atomic with
+ * multiprocessing cores.
+ */
+ sync_prim = ((read_cpuid_ext(CPUID_EXT_ISAR3) >> 8) & 0xf0) |
+ ((read_cpuid_ext(CPUID_EXT_ISAR4) >> 20) & 0x0f);
+ if (sync_prim >= 0x13)
+ elf_hwcap &= ~HWCAP_SWP;
}
/*
@@ -609,7 +624,7 @@ static void __init setup_processor(void)
#endif
erratum_a15_798181_init();
- feat_v6_fixup();
+ elf_hwcap_fixup();
cacheid_init();
cpu_init();
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 1b880db2a033..e1e60e5a7a27 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -107,7 +107,7 @@ ENTRY(cpu_resume_mmu)
instr_sync
mov r0, r0
mov r0, r0
- mov pc, r3 @ jump to virtual address
+ ret r3 @ jump to virtual address
ENDPROC(cpu_resume_mmu)
.popsection
cpu_resume_after_mmu:
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7c4fada440f0..9388a3d479e1 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -47,6 +47,9 @@
#include <asm/mach/arch.h>
#include <asm/mpu.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/ipi.h>
+
/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
@@ -430,38 +433,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
-static void (*smp_cross_call)(const struct cpumask *, unsigned int);
+static void (*__smp_cross_call)(const struct cpumask *, unsigned int);
void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
{
- if (!smp_cross_call)
- smp_cross_call = fn;
-}
-
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
- smp_cross_call(mask, IPI_CALL_FUNC);
-}
-
-void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
-{
- smp_cross_call(mask, IPI_WAKEUP);
-}
-
-void arch_send_call_function_single_ipi(int cpu)
-{
- smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+ if (!__smp_cross_call)
+ __smp_cross_call = fn;
}
-#ifdef CONFIG_IRQ_WORK
-void arch_irq_work_raise(void)
-{
- if (is_smp())
- smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
-}
-#endif
-
-static const char *ipi_types[NR_IPI] = {
+static const char *ipi_types[NR_IPI] __tracepoint_string = {
#define S(x,s) [x] = s
S(IPI_WAKEUP, "CPU wakeup interrupts"),
S(IPI_TIMER, "Timer broadcast interrupts"),
@@ -473,6 +453,12 @@ static const char *ipi_types[NR_IPI] = {
S(IPI_COMPLETION, "completion interrupts"),
};
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
+{
+ trace_ipi_raise(target, ipi_types[ipinr]);
+ __smp_cross_call(target, ipinr);
+}
+
void show_ipi_list(struct seq_file *p, int prec)
{
unsigned int cpu, i;
@@ -499,6 +485,29 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
return sum;
}
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+ smp_cross_call(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
+{
+ smp_cross_call(mask, IPI_WAKEUP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+ smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+#ifdef CONFIG_IRQ_WORK
+void arch_irq_work_raise(void)
+{
+ if (is_smp())
+ smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+}
+#endif
+
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
void tick_broadcast(const struct cpumask *mask)
{
@@ -556,8 +565,10 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
- if (ipinr < NR_IPI)
+ if ((unsigned)ipinr < NR_IPI) {
+ trace_ipi_entry(ipi_types[ipinr]);
__inc_irq_stat(cpu, ipi_irqs[ipinr]);
+ }
switch (ipinr) {
case IPI_WAKEUP:
@@ -612,6 +623,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
cpu, ipinr);
break;
}
+
+ if ((unsigned)ipinr < NR_IPI)
+ trace_ipi_exit(ipi_types[ipinr]);
set_irq_regs(old_regs);
}
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 1aafa0d785eb..72f9241ad5db 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -17,6 +17,8 @@
#include <asm/cputype.h>
#define SCU_CTRL 0x00
+#define SCU_ENABLE (1 << 0)
+#define SCU_STANDBY_ENABLE (1 << 5)
#define SCU_CONFIG 0x04
#define SCU_CPU_STATUS 0x08
#define SCU_INVALIDATE 0x0c
@@ -50,10 +52,16 @@ void scu_enable(void __iomem *scu_base)
scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
/* already enabled? */
- if (scu_ctrl & 1)
+ if (scu_ctrl & SCU_ENABLE)
return;
- scu_ctrl |= 1;
+ scu_ctrl |= SCU_ENABLE;
+
+ /* Cortex-A9 earlier than r2p0 has no standby bit in SCU */
+ if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090 &&
+ (read_cpuid_id() & 0x00f0000f) >= 0x00200000)
+ scu_ctrl |= SCU_STANDBY_ENABLE;
+
writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
/*
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 95d063620b76..2e72be4f623e 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -92,15 +92,19 @@ void erratum_a15_798181_init(void)
unsigned int midr = read_cpuid_id();
unsigned int revidr = read_cpuid(CPUID_REVIDR);
- /* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
- if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
- (revidr & 0x210) == 0x210) {
- return;
- }
- if (revidr & 0x10)
- erratum_a15_798181_handler = erratum_a15_798181_partial;
- else
+ /* Brahma-B15 r0p0..r0p2 affected
+ * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
+ if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+ else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
+ (revidr & 0x210) != 0x210) {
+ if (revidr & 0x10)
+ erratum_a15_798181_handler =
+ erratum_a15_798181_partial;
+ else
+ erratum_a15_798181_handler =
+ erratum_a15_798181_broadcast;
+ }
}
#endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index b1b89882b113..67ca8578c6d8 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -27,6 +27,7 @@
#include <linux/perf_event.h>
#include <asm/opcodes.h>
+#include <asm/system_info.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -266,6 +267,9 @@ static struct undef_hook swp_hook = {
*/
static int __init swp_emulation_init(void)
{
+ if (cpu_architecture() < CPU_ARCH_ARMv7)
+ return 0;
+
#ifdef CONFIG_PROC_FS
if (!proc_create("cpu/swp_emulation", S_IRUGO, NULL, &proc_status_fops))
return -ENOMEM;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 829a96d4a179..0cc7e58c47cc 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -50,10 +50,7 @@ unsigned long profile_pc(struct pt_regs *regs)
if (!in_lock_functions(regs->ARM_pc))
return regs->ARM_pc;
- frame.fp = regs->ARM_fp;
- frame.sp = regs->ARM_sp;
- frame.lr = regs->ARM_lr;
- frame.pc = regs->ARM_pc;
+ arm_get_current_stackframe(regs, &frame);
do {
int ret = unwind_frame(&frame);
if (ret < 0)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index abd2fc067736..c8e4bb714944 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -31,11 +31,13 @@
#include <asm/exception.h>
#include <asm/unistd.h>
#include <asm/traps.h>
+#include <asm/ptrace.h>
#include <asm/unwind.h>
#include <asm/tls.h>
#include <asm/system_misc.h>
#include <asm/opcodes.h>
+
static const char *handler[]= {
"prefetch abort",
"data abort",
@@ -184,7 +186,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
tsk = current;
if (regs) {
- fp = regs->ARM_fp;
+ fp = frame_pointer(regs);
mode = processor_mode(regs);
} else if (tsk != current) {
fp = thread_saved_fp(tsk);
@@ -719,7 +721,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
dump_instr("", regs);
if (user_mode(regs)) {
__show_regs(regs);
- c_backtrace(regs->ARM_fp, processor_mode(regs));
+ c_backtrace(frame_pointer(regs), processor_mode(regs));
}
}
#endif
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index e67682f02cb2..a61a1dfbb0db 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -479,12 +479,10 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
tsk = current;
if (regs) {
- frame.fp = regs->ARM_fp;
- frame.sp = regs->ARM_sp;
- frame.lr = regs->ARM_lr;
+ arm_get_current_stackframe(regs, &frame);
/* PC might be corrupted, use LR in that case. */
- frame.pc = kernel_text_address(regs->ARM_pc)
- ? regs->ARM_pc : regs->ARM_lr;
+ if (!kernel_text_address(regs->ARM_pc))
+ frame.pc = regs->ARM_lr;
} else if (tsk == current) {
frame.fp = (unsigned long)__builtin_frame_address(0);
frame.sp = current_sp;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 7bcee5c9b604..6f57cb94367f 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -318,7 +318,6 @@ SECTIONS
_end = .;
STABS_DEBUG
- .comment 0 : { *(.comment) }
}
/*
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 4be5bb150bdd..466bd299b1a8 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -23,7 +23,7 @@ config KVM
select HAVE_KVM_CPU_RELAX_INTERCEPT
select KVM_MMIO
select KVM_ARM_HOST
- depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
+ depends on ARM_VIRT_EXT && ARM_LPAE
---help---
Support hosting virtualized guest machines. You will also
need to select one or more of the processor modules below.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index 789bca9e64a7..f7057ed045b6 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,4 +21,5 @@ obj-y += kvm-arm.o init.o interrupts.o
obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
+obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 3c82b37c0f9e..a99e0cdf8ba2 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -155,16 +155,6 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
}
-void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
- struct kvm_memory_slot *dont)
-{
-}
-
-int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
- unsigned long npages)
-{
- return 0;
-}
/**
* kvm_arch_destroy_vm - destroy the VM data structure
@@ -184,7 +174,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
}
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
switch (ext) {
@@ -225,33 +215,6 @@ long kvm_arch_dev_ioctl(struct file *filp,
return -EINVAL;
}
-void kvm_arch_memslots_updated(struct kvm *kvm)
-{
-}
-
-int kvm_arch_prepare_memory_region(struct kvm *kvm,
- struct kvm_memory_slot *memslot,
- struct kvm_userspace_memory_region *mem,
- enum kvm_mr_change change)
-{
- return 0;
-}
-
-void kvm_arch_commit_memory_region(struct kvm *kvm,
- struct kvm_userspace_memory_region *mem,
- const struct kvm_memory_slot *old,
- enum kvm_mr_change change)
-{
-}
-
-void kvm_arch_flush_shadow_all(struct kvm *kvm)
-{
-}
-
-void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
- struct kvm_memory_slot *slot)
-{
-}
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index c58a35116f63..37a0fe1bb9bb 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -44,6 +44,31 @@ static u32 cache_levels;
/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
#define CSSELR_MAX 12
+/*
+ * kvm_vcpu_arch.cp15 holds cp15 registers as an array of u32, but some
+ * of cp15 registers can be viewed either as couple of two u32 registers
+ * or one u64 register. Current u64 register encoding is that least
+ * significant u32 word is followed by most significant u32 word.
+ */
+static inline void vcpu_cp15_reg64_set(struct kvm_vcpu *vcpu,
+ const struct coproc_reg *r,
+ u64 val)
+{
+ vcpu->arch.cp15[r->reg] = val & 0xffffffff;
+ vcpu->arch.cp15[r->reg + 1] = val >> 32;
+}
+
+static inline u64 vcpu_cp15_reg64_get(struct kvm_vcpu *vcpu,
+ const struct coproc_reg *r)
+{
+ u64 val;
+
+ val = vcpu->arch.cp15[r->reg + 1];
+ val = val << 32;
+ val = val | vcpu->arch.cp15[r->reg];
+ return val;
+}
+
int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
kvm_inject_undefined(vcpu);
@@ -682,17 +707,23 @@ static struct coproc_reg invariant_cp15[] = {
{ CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
};
+/*
+ * Reads a register value from a userspace address to a kernel
+ * variable. Make sure that register size matches sizeof(*__val).
+ */
static int reg_from_user(void *val, const void __user *uaddr, u64 id)
{
- /* This Just Works because we are little endian. */
if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
return -EFAULT;
return 0;
}
+/*
+ * Writes a register value to a userspace address from a kernel variable.
+ * Make sure that register size matches sizeof(*__val).
+ */
static int reg_to_user(void __user *uaddr, const void *val, u64 id)
{
- /* This Just Works because we are little endian. */
if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
return -EFAULT;
return 0;
@@ -702,6 +733,7 @@ static int get_invariant_cp15(u64 id, void __user *uaddr)
{
struct coproc_params params;
const struct coproc_reg *r;
+ int ret;
if (!index_to_params(id, &params))
return -ENOENT;
@@ -710,7 +742,15 @@ static int get_invariant_cp15(u64 id, void __user *uaddr)
if (!r)
return -ENOENT;
- return reg_to_user(uaddr, &r->val, id);
+ ret = -ENOENT;
+ if (KVM_REG_SIZE(id) == 4) {
+ u32 val = r->val;
+
+ ret = reg_to_user(uaddr, &val, id);
+ } else if (KVM_REG_SIZE(id) == 8) {
+ ret = reg_to_user(uaddr, &r->val, id);
+ }
+ return ret;
}
static int set_invariant_cp15(u64 id, void __user *uaddr)
@@ -718,7 +758,7 @@ static int set_invariant_cp15(u64 id, void __user *uaddr)
struct coproc_params params;
const struct coproc_reg *r;
int err;
- u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
+ u64 val;
if (!index_to_params(id, &params))
return -ENOENT;
@@ -726,7 +766,16 @@ static int set_invariant_cp15(u64 id, void __user *uaddr)
if (!r)
return -ENOENT;
- err = reg_from_user(&val, uaddr, id);
+ err = -ENOENT;
+ if (KVM_REG_SIZE(id) == 4) {
+ u32 val32;
+
+ err = reg_from_user(&val32, uaddr, id);
+ if (!err)
+ val = val32;
+ } else if (KVM_REG_SIZE(id) == 8) {
+ err = reg_from_user(&val, uaddr, id);
+ }
if (err)
return err;
@@ -1004,6 +1053,7 @@ int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
{
const struct coproc_reg *r;
void __user *uaddr = (void __user *)(long)reg->addr;
+ int ret;
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
return demux_c15_get(reg->id, uaddr);
@@ -1015,14 +1065,24 @@ int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
if (!r)
return get_invariant_cp15(reg->id, uaddr);
- /* Note: copies two regs if size is 64 bit. */
- return reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+ ret = -ENOENT;
+ if (KVM_REG_SIZE(reg->id) == 8) {
+ u64 val;
+
+ val = vcpu_cp15_reg64_get(vcpu, r);
+ ret = reg_to_user(uaddr, &val, reg->id);
+ } else if (KVM_REG_SIZE(reg->id) == 4) {
+ ret = reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+ }
+
+ return ret;
}
int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
{
const struct coproc_reg *r;
void __user *uaddr = (void __user *)(long)reg->addr;
+ int ret;
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
return demux_c15_set(reg->id, uaddr);
@@ -1034,8 +1094,18 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
if (!r)
return set_invariant_cp15(reg->id, uaddr);
- /* Note: copies two regs if size is 64 bit */
- return reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+ ret = -ENOENT;
+ if (KVM_REG_SIZE(reg->id) == 8) {
+ u64 val;
+
+ ret = reg_from_user(&val, uaddr, reg->id);
+ if (!ret)
+ vcpu_cp15_reg64_set(vcpu, r, val);
+ } else if (KVM_REG_SIZE(reg->id) == 4) {
+ ret = reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+ }
+
+ return ret;
}
static unsigned int num_demux_regs(void)
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index b23a59c1c522..813e49258690 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -124,16 +124,6 @@ static bool is_timer_reg(u64 index)
return false;
}
-int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
-{
- return 0;
-}
-
-u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
-{
- return 0;
-}
-
#else
#define NUM_TIMER_REGS 3
@@ -274,13 +264,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
int __attribute_const__ kvm_target_cpu(void)
{
- unsigned long implementor = read_cpuid_implementor();
- unsigned long part_number = read_cpuid_part_number();
-
- if (implementor != ARM_CPU_IMP_ARM)
- return -EINVAL;
-
- switch (part_number) {
+ switch (read_cpuid_part()) {
case ARM_CPU_PART_CORTEX_A7:
return KVM_ARM_TARGET_CORTEX_A7;
case ARM_CPU_PART_CORTEX_A15:
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index 1b9844d369cc..991415d978b6 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -17,6 +17,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/unified.h>
#include <asm/asm-offsets.h>
#include <asm/kvm_asm.h>
@@ -71,7 +72,7 @@ __do_hyp_init:
bne phase2 @ Yes, second stage init
@ Set the HTTBR to point to the hypervisor PGD pointer passed
- mcrr p15, 4, r2, r3, c2
+ mcrr p15, 4, rr_lo_hi(r2, r3), c2
@ Set the HTCR and VTCR to the same shareability and cacheability
@ settings as the non-secure TTBCR and with T0SZ == 0.
@@ -134,10 +135,10 @@ phase2:
ldr r0, =TRAMPOLINE_VA
adr r1, target
bfi r0, r1, #0, #PAGE_SHIFT
- mov pc, r0
+ ret r0
target: @ We're now in the trampoline code, switch page tables
- mcrr p15, 4, r2, r3, c2
+ mcrr p15, 4, rr_lo_hi(r2, r3), c2
isb
@ Invalidate the old TLBs
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index 0d68d4073068..01dcb0e752d9 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -52,7 +52,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
dsb ishst
add r0, r0, #KVM_VTTBR
ldrd r2, r3, [r0]
- mcrr p15, 6, r2, r3, c2 @ Write VTTBR
+ mcrr p15, 6, rr_lo_hi(r2, r3), c2 @ Write VTTBR
isb
mcr p15, 0, r0, c8, c3, 0 @ TLBIALLIS (rt ignored)
dsb ish
@@ -135,7 +135,7 @@ ENTRY(__kvm_vcpu_run)
ldr r1, [vcpu, #VCPU_KVM]
add r1, r1, #KVM_VTTBR
ldrd r2, r3, [r1]
- mcrr p15, 6, r2, r3, c2 @ Write VTTBR
+ mcrr p15, 6, rr_lo_hi(r2, r3), c2 @ Write VTTBR
@ We're all done, just restore the GPRs and go to the guest
restore_guest_regs
@@ -199,8 +199,13 @@ after_vfp_restore:
restore_host_regs
clrex @ Clear exclusive monitor
+#ifndef CONFIG_CPU_ENDIAN_BE8
mov r0, r1 @ Return the return code
mov r1, #0 @ Clear upper bits in return value
+#else
+ @ r1 already has return code
+ mov r0, #0 @ Clear upper bits in return value
+#endif /* CONFIG_CPU_ENDIAN_BE8 */
bx lr @ return to IOCTL
/********************************************************************
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index 76af93025574..98c8c5b9a87f 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -1,4 +1,5 @@
#include <linux/irqchip/arm-gic.h>
+#include <asm/assembler.h>
#define VCPU_USR_REG(_reg_nr) (VCPU_USR_REGS + (_reg_nr * 4))
#define VCPU_USR_SP (VCPU_USR_REG(13))
@@ -420,15 +421,23 @@ vcpu .req r0 @ vcpu pointer always in r0
ldr r8, [r2, #GICH_ELRSR0]
ldr r9, [r2, #GICH_ELRSR1]
ldr r10, [r2, #GICH_APR]
-
- str r3, [r11, #VGIC_CPU_HCR]
- str r4, [r11, #VGIC_CPU_VMCR]
- str r5, [r11, #VGIC_CPU_MISR]
- str r6, [r11, #VGIC_CPU_EISR]
- str r7, [r11, #(VGIC_CPU_EISR + 4)]
- str r8, [r11, #VGIC_CPU_ELRSR]
- str r9, [r11, #(VGIC_CPU_ELRSR + 4)]
- str r10, [r11, #VGIC_CPU_APR]
+ARM_BE8(rev r3, r3 )
+ARM_BE8(rev r4, r4 )
+ARM_BE8(rev r5, r5 )
+ARM_BE8(rev r6, r6 )
+ARM_BE8(rev r7, r7 )
+ARM_BE8(rev r8, r8 )
+ARM_BE8(rev r9, r9 )
+ARM_BE8(rev r10, r10 )
+
+ str r3, [r11, #VGIC_V2_CPU_HCR]
+ str r4, [r11, #VGIC_V2_CPU_VMCR]
+ str r5, [r11, #VGIC_V2_CPU_MISR]
+ str r6, [r11, #VGIC_V2_CPU_EISR]
+ str r7, [r11, #(VGIC_V2_CPU_EISR + 4)]
+ str r8, [r11, #VGIC_V2_CPU_ELRSR]
+ str r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
+ str r10, [r11, #VGIC_V2_CPU_APR]
/* Clear GICH_HCR */
mov r5, #0
@@ -436,9 +445,10 @@ vcpu .req r0 @ vcpu pointer always in r0
/* Save list registers */
add r2, r2, #GICH_LR0
- add r3, r11, #VGIC_CPU_LR
+ add r3, r11, #VGIC_V2_CPU_LR
ldr r4, [r11, #VGIC_CPU_NR_LR]
1: ldr r6, [r2], #4
+ARM_BE8(rev r6, r6 )
str r6, [r3], #4
subs r4, r4, #1
bne 1b
@@ -463,9 +473,12 @@ vcpu .req r0 @ vcpu pointer always in r0
add r11, vcpu, #VCPU_VGIC_CPU
/* We only restore a minimal set of registers */
- ldr r3, [r11, #VGIC_CPU_HCR]
- ldr r4, [r11, #VGIC_CPU_VMCR]
- ldr r8, [r11, #VGIC_CPU_APR]
+ ldr r3, [r11, #VGIC_V2_CPU_HCR]
+ ldr r4, [r11, #VGIC_V2_CPU_VMCR]
+ ldr r8, [r11, #VGIC_V2_CPU_APR]
+ARM_BE8(rev r3, r3 )
+ARM_BE8(rev r4, r4 )
+ARM_BE8(rev r8, r8 )
str r3, [r2, #GICH_HCR]
str r4, [r2, #GICH_VMCR]
@@ -473,9 +486,10 @@ vcpu .req r0 @ vcpu pointer always in r0
/* Restore list registers */
add r2, r2, #GICH_LR0
- add r3, r11, #VGIC_CPU_LR
+ add r3, r11, #VGIC_V2_CPU_LR
ldr r4, [r11, #VGIC_CPU_NR_LR]
1: ldr r6, [r3], #4
+ARM_BE8(rev r6, r6 )
str r6, [r2], #4
subs r4, r4, #1
bne 1b
@@ -506,7 +520,7 @@ vcpu .req r0 @ vcpu pointer always in r0
mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
isb
- mrrc p15, 3, r2, r3, c14 @ CNTV_CVAL
+ mrrc p15, 3, rr_lo_hi(r2, r3), c14 @ CNTV_CVAL
ldr r4, =VCPU_TIMER_CNTV_CVAL
add r5, vcpu, r4
strd r2, r3, [r5]
@@ -546,12 +560,12 @@ vcpu .req r0 @ vcpu pointer always in r0
ldr r2, [r4, #KVM_TIMER_CNTVOFF]
ldr r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
- mcrr p15, 4, r2, r3, c14 @ CNTVOFF
+ mcrr p15, 4, rr_lo_hi(r2, r3), c14 @ CNTVOFF
ldr r4, =VCPU_TIMER_CNTV_CVAL
add r5, vcpu, r4
ldrd r2, r3, [r5]
- mcrr p15, 3, r2, r3, c14 @ CNTV_CVAL
+ mcrr p15, 3, rr_lo_hi(r2, r3), c14 @ CNTV_CVAL
isb
ldr r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 16f804938b8f..16e7994bf347 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -90,104 +90,115 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
return p;
}
-static bool page_empty(void *ptr)
+static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
{
- struct page *ptr_page = virt_to_page(ptr);
- return page_count(ptr_page) == 1;
+ pud_t *pud_table __maybe_unused = pud_offset(pgd, 0);
+ pgd_clear(pgd);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ pud_free(NULL, pud_table);
+ put_page(virt_to_page(pgd));
}
static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
{
- if (pud_huge(*pud)) {
- pud_clear(pud);
- kvm_tlb_flush_vmid_ipa(kvm, addr);
- } else {
- pmd_t *pmd_table = pmd_offset(pud, 0);
- pud_clear(pud);
- kvm_tlb_flush_vmid_ipa(kvm, addr);
- pmd_free(NULL, pmd_table);
- }
+ pmd_t *pmd_table = pmd_offset(pud, 0);
+ VM_BUG_ON(pud_huge(*pud));
+ pud_clear(pud);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ pmd_free(NULL, pmd_table);
put_page(virt_to_page(pud));
}
static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
{
- if (kvm_pmd_huge(*pmd)) {
- pmd_clear(pmd);
- kvm_tlb_flush_vmid_ipa(kvm, addr);
- } else {
- pte_t *pte_table = pte_offset_kernel(pmd, 0);
- pmd_clear(pmd);
- kvm_tlb_flush_vmid_ipa(kvm, addr);
- pte_free_kernel(NULL, pte_table);
- }
+ pte_t *pte_table = pte_offset_kernel(pmd, 0);
+ VM_BUG_ON(kvm_pmd_huge(*pmd));
+ pmd_clear(pmd);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ pte_free_kernel(NULL, pte_table);
put_page(virt_to_page(pmd));
}
-static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
+static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
+ phys_addr_t addr, phys_addr_t end)
{
- if (pte_present(*pte)) {
- kvm_set_pte(pte, __pte(0));
- put_page(virt_to_page(pte));
- kvm_tlb_flush_vmid_ipa(kvm, addr);
- }
+ phys_addr_t start_addr = addr;
+ pte_t *pte, *start_pte;
+
+ start_pte = pte = pte_offset_kernel(pmd, addr);
+ do {
+ if (!pte_none(*pte)) {
+ kvm_set_pte(pte, __pte(0));
+ put_page(virt_to_page(pte));
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ }
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+
+ if (kvm_pte_table_empty(start_pte))
+ clear_pmd_entry(kvm, pmd, start_addr);
}
-static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
- unsigned long long start, u64 size)
+static void unmap_pmds(struct kvm *kvm, pud_t *pud,
+ phys_addr_t addr, phys_addr_t end)
{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long long addr = start, end = start + size;
- u64 next;
-
- while (addr < end) {
- pgd = pgdp + pgd_index(addr);
- pud = pud_offset(pgd, addr);
- pte = NULL;
- if (pud_none(*pud)) {
- addr = kvm_pud_addr_end(addr, end);
- continue;
- }
+ phys_addr_t next, start_addr = addr;
+ pmd_t *pmd, *start_pmd;
- if (pud_huge(*pud)) {
- /*
- * If we are dealing with a huge pud, just clear it and
- * move on.
- */
- clear_pud_entry(kvm, pud, addr);
- addr = kvm_pud_addr_end(addr, end);
- continue;
+ start_pmd = pmd = pmd_offset(pud, addr);
+ do {
+ next = kvm_pmd_addr_end(addr, end);
+ if (!pmd_none(*pmd)) {
+ if (kvm_pmd_huge(*pmd)) {
+ pmd_clear(pmd);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ put_page(virt_to_page(pmd));
+ } else {
+ unmap_ptes(kvm, pmd, addr, next);
+ }
}
+ } while (pmd++, addr = next, addr != end);
- pmd = pmd_offset(pud, addr);
- if (pmd_none(*pmd)) {
- addr = kvm_pmd_addr_end(addr, end);
- continue;
- }
+ if (kvm_pmd_table_empty(start_pmd))
+ clear_pud_entry(kvm, pud, start_addr);
+}
- if (!kvm_pmd_huge(*pmd)) {
- pte = pte_offset_kernel(pmd, addr);
- clear_pte_entry(kvm, pte, addr);
- next = addr + PAGE_SIZE;
- }
+static void unmap_puds(struct kvm *kvm, pgd_t *pgd,
+ phys_addr_t addr, phys_addr_t end)
+{
+ phys_addr_t next, start_addr = addr;
+ pud_t *pud, *start_pud;
- /*
- * If the pmd entry is to be cleared, walk back up the ladder
- */
- if (kvm_pmd_huge(*pmd) || (pte && page_empty(pte))) {
- clear_pmd_entry(kvm, pmd, addr);
- next = kvm_pmd_addr_end(addr, end);
- if (page_empty(pmd) && !page_empty(pud)) {
- clear_pud_entry(kvm, pud, addr);
- next = kvm_pud_addr_end(addr, end);
+ start_pud = pud = pud_offset(pgd, addr);
+ do {
+ next = kvm_pud_addr_end(addr, end);
+ if (!pud_none(*pud)) {
+ if (pud_huge(*pud)) {
+ pud_clear(pud);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ put_page(virt_to_page(pud));
+ } else {
+ unmap_pmds(kvm, pud, addr, next);
}
}
+ } while (pud++, addr = next, addr != end);
- addr = next;
- }
+ if (kvm_pud_table_empty(start_pud))
+ clear_pgd_entry(kvm, pgd, start_addr);
+}
+
+
+static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
+ phys_addr_t start, u64 size)
+{
+ pgd_t *pgd;
+ phys_addr_t addr = start, end = start + size;
+ phys_addr_t next;
+
+ pgd = pgdp + pgd_index(addr);
+ do {
+ next = kvm_pgd_addr_end(addr, end);
+ unmap_puds(kvm, pgd, addr, next);
+ } while (pgd++, addr = next, addr != end);
}
static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
@@ -748,6 +759,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
struct vm_area_struct *vma;
pfn_t pfn;
+ pgprot_t mem_type = PAGE_S2;
write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu));
if (fault_status == FSC_PERM && !write_fault) {
@@ -798,6 +810,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
if (is_error_pfn(pfn))
return -EFAULT;
+ if (kvm_is_mmio_pfn(pfn))
+ mem_type = PAGE_S2_DEVICE;
+
spin_lock(&kvm->mmu_lock);
if (mmu_notifier_retry(kvm, mmu_seq))
goto out_unlock;
@@ -805,7 +820,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
if (hugetlb) {
- pmd_t new_pmd = pfn_pmd(pfn, PAGE_S2);
+ pmd_t new_pmd = pfn_pmd(pfn, mem_type);
new_pmd = pmd_mkhuge(new_pmd);
if (writable) {
kvm_set_s2pmd_writable(&new_pmd);
@@ -814,13 +829,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE);
ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
} else {
- pte_t new_pte = pfn_pte(pfn, PAGE_S2);
+ pte_t new_pte = pfn_pte(pfn, mem_type);
if (writable) {
kvm_set_s2pte_writable(&new_pte);
kvm_set_pfn_dirty(pfn);
}
coherent_cache_guest_page(vcpu, hva, PAGE_SIZE);
- ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false);
+ ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte,
+ mem_type == PAGE_S2_DEVICE);
}
@@ -1100,3 +1116,49 @@ out:
free_hyp_pgds();
return err;
}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+ struct kvm_userspace_memory_region *mem,
+ const struct kvm_memory_slot *old,
+ enum kvm_mr_change change)
+{
+ gpa_t gpa = old->base_gfn << PAGE_SHIFT;
+ phys_addr_t size = old->npages << PAGE_SHIFT;
+ if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) {
+ spin_lock(&kvm->mmu_lock);
+ unmap_stage2_range(kvm, gpa, size);
+ spin_unlock(&kvm->mmu_lock);
+ }
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+ struct kvm_memory_slot *memslot,
+ struct kvm_userspace_memory_region *mem,
+ enum kvm_mr_change change)
+{
+ return 0;
+}
+
+void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
+ struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
+ unsigned long npages)
+{
+ return 0;
+}
+
+void kvm_arch_memslots_updated(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+ struct kvm_memory_slot *slot)
+{
+}
diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
index 638deb13da1c..b05e95840651 100644
--- a/arch/arm/lib/ashldi3.S
+++ b/arch/arm/lib/ashldi3.S
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA. */
#include <linux/linkage.h>
+#include <asm/assembler.h>
#ifdef __ARMEB__
#define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_llsl)
THUMB( lsrmi r3, al, ip )
THUMB( orrmi ah, ah, r3 )
mov al, al, lsl r2
- mov pc, lr
+ ret lr
ENDPROC(__ashldi3)
ENDPROC(__aeabi_llsl)
diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S
index 015e8aa5a1d1..275d7d2341a4 100644
--- a/arch/arm/lib/ashrdi3.S
+++ b/arch/arm/lib/ashrdi3.S
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA. */
#include <linux/linkage.h>
+#include <asm/assembler.h>
#ifdef __ARMEB__
#define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_lasr)
THUMB( lslmi r3, ah, ip )
THUMB( orrmi al, al, r3 )
mov ah, ah, asr r2
- mov pc, lr
+ ret lr
ENDPROC(__ashrdi3)
ENDPROC(__aeabi_lasr)
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 4102be617fce..fab5a50503ae 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -25,7 +25,7 @@
ENTRY(c_backtrace)
#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
- mov pc, lr
+ ret lr
ENDPROC(c_backtrace)
#else
stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index 9f12ed1eea86..7d807cfd8ef5 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,3 +1,4 @@
+#include <asm/assembler.h>
#include <asm/unwind.h>
#if __LINUX_ARM_ARCH__ >= 6
@@ -70,7 +71,7 @@ UNWIND( .fnstart )
\instr r2, r2, r3
str r2, [r1, r0, lsl #2]
restore_irqs ip
- mov pc, lr
+ ret lr
UNWIND( .fnend )
ENDPROC(\name )
.endm
@@ -98,7 +99,7 @@ UNWIND( .fnstart )
\store r2, [r1]
moveq r0, #0
restore_irqs ip
- mov pc, lr
+ ret lr
UNWIND( .fnend )
ENDPROC(\name )
.endm
diff --git a/arch/arm/lib/bswapsdi2.S b/arch/arm/lib/bswapsdi2.S
index 9fcdd154eff9..07cda737bb11 100644
--- a/arch/arm/lib/bswapsdi2.S
+++ b/arch/arm/lib/bswapsdi2.S
@@ -1,4 +1,5 @@
#include <linux/linkage.h>
+#include <asm/assembler.h>
#if __LINUX_ARM_ARCH__ >= 6
ENTRY(__bswapsi2)
@@ -18,7 +19,7 @@ ENTRY(__bswapsi2)
mov r3, r3, lsr #8
bic r3, r3, #0xff00
eor r0, r3, r0, ror #8
- mov pc, lr
+ ret lr
ENDPROC(__bswapsi2)
ENTRY(__bswapdi2)
@@ -31,6 +32,6 @@ ENTRY(__bswapdi2)
bic r1, r1, #0xff00
eor r1, r1, r0, ror #8
eor r0, r3, ip, ror #8
- mov pc, lr
+ ret lr
ENDPROC(__bswapdi2)
#endif
diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S
index 916c80f13ae7..ed1a421813cb 100644
--- a/arch/arm/lib/call_with_stack.S
+++ b/arch/arm/lib/call_with_stack.S
@@ -36,9 +36,9 @@ ENTRY(call_with_stack)
mov r0, r1
adr lr, BSYM(1f)
- mov pc, r2
+ ret r2
1: ldr lr, [sp]
ldr sp, [sp, #4]
- mov pc, lr
+ ret lr
ENDPROC(call_with_stack)
diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S
index 31d3cb34740d..984e0f29d548 100644
--- a/arch/arm/lib/csumpartial.S
+++ b/arch/arm/lib/csumpartial.S
@@ -97,7 +97,7 @@ td3 .req lr
#endif
#endif
adcnes sum, sum, td0 @ update checksum
- mov pc, lr
+ ret lr
ENTRY(csum_partial)
stmfd sp!, {buf, lr}
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
index d6e742d24007..10b45909610c 100644
--- a/arch/arm/lib/csumpartialcopygeneric.S
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <asm/assembler.h>
/*
* unsigned int
@@ -40,7 +41,7 @@ sum .req r3
adcs sum, sum, ip, put_byte_1 @ update checksum
strb ip, [dst], #1
tst dst, #2
- moveq pc, lr @ dst is now 32bit aligned
+ reteq lr @ dst is now 32bit aligned
.Ldst_16bit: load2b r8, ip
sub len, len, #2
@@ -48,7 +49,7 @@ sum .req r3
strb r8, [dst], #1
adcs sum, sum, ip, put_byte_1
strb ip, [dst], #1
- mov pc, lr @ dst is now 32bit aligned
+ ret lr @ dst is now 32bit aligned
/*
* Handle 0 to 7 bytes, with any alignment of source and
diff --git a/arch/arm/lib/delay-loop.S b/arch/arm/lib/delay-loop.S
index bc1033b897b4..518bf6e93f78 100644
--- a/arch/arm/lib/delay-loop.S
+++ b/arch/arm/lib/delay-loop.S
@@ -35,7 +35,7 @@ ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06
mul r0, r2, r0 @ max = 2^32-1
add r0, r0, r1, lsr #32-6
movs r0, r0, lsr #6
- moveq pc, lr
+ reteq lr
/*
* loops = r0 * HZ * loops_per_jiffy / 1000000
@@ -46,23 +46,23 @@ ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06
ENTRY(__loop_delay)
subs r0, r0, #1
#if 0
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
- movls pc, lr
+ retls lr
subs r0, r0, #1
#endif
bhi __loop_delay
- mov pc, lr
+ ret lr
ENDPROC(__loop_udelay)
ENDPROC(__loop_const_udelay)
ENDPROC(__loop_delay)
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
index 5306de350133..312d43eb686a 100644
--- a/arch/arm/lib/delay.c
+++ b/arch/arm/lib/delay.c
@@ -19,6 +19,7 @@
* Author: Will Deacon <will.deacon@arm.com>
*/
+#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -36,6 +37,7 @@ struct arm_delay_ops arm_delay_ops = {
static const struct delay_timer *delay_timer;
static bool delay_calibrated;
+static u64 delay_res;
int read_current_timer(unsigned long *timer_val)
{
@@ -47,6 +49,11 @@ int read_current_timer(unsigned long *timer_val)
}
EXPORT_SYMBOL_GPL(read_current_timer);
+static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+{
+ return (cyc * mult) >> shift;
+}
+
static void __timer_delay(unsigned long cycles)
{
cycles_t start = get_cycles();
@@ -69,18 +76,24 @@ static void __timer_udelay(unsigned long usecs)
void __init register_current_timer_delay(const struct delay_timer *timer)
{
- if (!delay_calibrated) {
- pr_info("Switching to timer-based delay loop\n");
+ u32 new_mult, new_shift;
+ u64 res;
+
+ clocks_calc_mult_shift(&new_mult, &new_shift, timer->freq,
+ NSEC_PER_SEC, 3600);
+ res = cyc_to_ns(1ULL, new_mult, new_shift);
+
+ if (!delay_calibrated && (!delay_res || (res < delay_res))) {
+ pr_info("Switching to timer-based delay loop, resolution %lluns\n", res);
delay_timer = timer;
lpj_fine = timer->freq / HZ;
+ delay_res = res;
/* cpufreq may scale loops_per_jiffy, so keep a private copy */
arm_delay_ops.ticks_per_jiffy = lpj_fine;
arm_delay_ops.delay = __timer_delay;
arm_delay_ops.const_udelay = __timer_const_udelay;
arm_delay_ops.udelay = __timer_udelay;
-
- delay_calibrated = true;
} else {
pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
}
@@ -91,3 +104,8 @@ unsigned long calibrate_delay_is_known(void)
delay_calibrated = true;
return lpj_fine;
}
+
+void calibration_delay_done(void)
+{
+ delay_calibrated = true;
+}
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index e55c4842c290..a9eafe4981eb 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -13,6 +13,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/unwind.h>
#ifdef __ARMEB__
@@ -97,7 +98,7 @@ UNWIND(.fnstart)
mov yl, #0
cmpeq xl, r4
movlo xh, xl
- movlo pc, lr
+ retlo lr
@ The division loop for lower bit positions.
@ Here we shift remainer bits leftwards rather than moving the
@@ -111,14 +112,14 @@ UNWIND(.fnstart)
subcs xh, xh, r4
movs ip, ip, lsr #1
bne 4b
- mov pc, lr
+ ret lr
@ The top part of remainder became zero. If carry is set
@ (the 33th bit) this is a false positive so resume the loop.
@ Otherwise, if lower part is also null then we are done.
6: bcs 5b
cmp xl, #0
- moveq pc, lr
+ reteq lr
@ We still have remainer bits in the low part. Bring them up.
@@ -144,7 +145,7 @@ UNWIND(.fnstart)
movs ip, ip, lsr #1
mov xh, #1
bne 4b
- mov pc, lr
+ ret lr
8: @ Division by a power of 2: determine what that divisor order is
@ then simply shift values around
@@ -184,13 +185,13 @@ UNWIND(.fnstart)
THUMB( orr yl, yl, xh )
mov xh, xl, lsl ip
mov xh, xh, lsr ip
- mov pc, lr
+ ret lr
@ eq -> division by 1: obvious enough...
9: moveq yl, xl
moveq yh, xh
moveq xh, #0
- moveq pc, lr
+ reteq lr
UNWIND(.fnend)
UNWIND(.fnstart)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 64f6bc1a9132..7848780e8834 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -35,7 +35,7 @@ ENTRY(_find_first_zero_bit_le)
2: cmp r2, r1 @ any more?
blo 1b
3: mov r0, r1 @ no free bits
- mov pc, lr
+ ret lr
ENDPROC(_find_first_zero_bit_le)
/*
@@ -76,7 +76,7 @@ ENTRY(_find_first_bit_le)
2: cmp r2, r1 @ any more?
blo 1b
3: mov r0, r1 @ no free bits
- mov pc, lr
+ ret lr
ENDPROC(_find_first_bit_le)
/*
@@ -114,7 +114,7 @@ ENTRY(_find_first_zero_bit_be)
2: cmp r2, r1 @ any more?
blo 1b
3: mov r0, r1 @ no free bits
- mov pc, lr
+ ret lr
ENDPROC(_find_first_zero_bit_be)
ENTRY(_find_next_zero_bit_be)
@@ -148,7 +148,7 @@ ENTRY(_find_first_bit_be)
2: cmp r2, r1 @ any more?
blo 1b
3: mov r0, r1 @ no free bits
- mov pc, lr
+ ret lr
ENDPROC(_find_first_bit_be)
ENTRY(_find_next_bit_be)
@@ -192,5 +192,5 @@ ENDPROC(_find_next_bit_be)
#endif
cmp r1, r0 @ Clamp to maxbit
movlo r0, r1
- mov pc, lr
+ ret lr
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 9b06bb41fca6..938600098b88 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -18,7 +18,7 @@
* Inputs: r0 contains the address
* r1 contains the address limit, which must be preserved
* Outputs: r0 is the error code
- * r2 contains the zero-extended value
+ * r2, r3 contains the zero-extended value
* lr corrupted
*
* No other registers must be altered. (see <asm/uaccess.h>
@@ -36,7 +36,7 @@ ENTRY(__get_user_1)
check_uaccess r0, 1, r1, r2, __get_user_bad
1: TUSER(ldrb) r2, [r0]
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__get_user_1)
ENTRY(__get_user_2)
@@ -56,25 +56,60 @@ rb .req r0
orr r2, rb, r2, lsl #8
#endif
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__get_user_2)
ENTRY(__get_user_4)
check_uaccess r0, 4, r1, r2, __get_user_bad
4: TUSER(ldr) r2, [r0]
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__get_user_4)
+ENTRY(__get_user_8)
+ check_uaccess r0, 8, r1, r2, __get_user_bad
+#ifdef CONFIG_THUMB2_KERNEL
+5: TUSER(ldr) r2, [r0]
+6: TUSER(ldr) r3, [r0, #4]
+#else
+5: TUSER(ldr) r2, [r0], #4
+6: TUSER(ldr) r3, [r0]
+#endif
+ mov r0, #0
+ ret lr
+ENDPROC(__get_user_8)
+
+#ifdef __ARMEB__
+ENTRY(__get_user_lo8)
+ check_uaccess r0, 8, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+ add r0, r0, #4
+7: ldrt r2, [r0]
+#else
+7: ldr r2, [r0, #4]
+#endif
+ mov r0, #0
+ ret lr
+ENDPROC(__get_user_lo8)
+#endif
+
+__get_user_bad8:
+ mov r3, #0
__get_user_bad:
mov r2, #0
mov r0, #-EFAULT
- mov pc, lr
+ ret lr
ENDPROC(__get_user_bad)
+ENDPROC(__get_user_bad8)
.pushsection __ex_table, "a"
.long 1b, __get_user_bad
.long 2b, __get_user_bad
.long 3b, __get_user_bad
.long 4b, __get_user_bad
+ .long 5b, __get_user_bad8
+ .long 6b, __get_user_bad8
+#ifdef __ARMEB__
+ .long 7b, __get_user_bad
+#endif
.popsection
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
index 9f4238987fe9..c31b2f3153f1 100644
--- a/arch/arm/lib/io-readsb.S
+++ b/arch/arm/lib/io-readsb.S
@@ -25,7 +25,7 @@
ENTRY(__raw_readsb)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
ands ip, r1, #3
bne .Linsb_align
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
index 7a7430950c79..2ed86fa5465f 100644
--- a/arch/arm/lib/io-readsl.S
+++ b/arch/arm/lib/io-readsl.S
@@ -12,7 +12,7 @@
ENTRY(__raw_readsl)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
ands ip, r1, #3
bne 3f
@@ -33,7 +33,7 @@ ENTRY(__raw_readsl)
stmcsia r1!, {r3, ip}
ldrne r3, [r0, #0]
strne r3, [r1, #0]
- mov pc, lr
+ ret lr
3: ldr r3, [r0]
cmp ip, #2
@@ -75,5 +75,5 @@ ENTRY(__raw_readsl)
strb r3, [r1, #1]
8: mov r3, ip, get_byte_0
strb r3, [r1, #0]
- mov pc, lr
+ ret lr
ENDPROC(__raw_readsl)
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
index 88487c8c4f23..413da9914529 100644
--- a/arch/arm/lib/io-readsw-armv3.S
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -27,11 +27,11 @@
strb r3, [r1], #1
subs r2, r2, #1
- moveq pc, lr
+ reteq lr
ENTRY(__raw_readsw)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
tst r1, #3
bne .Linsw_align
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
index 1f393d42593d..d9a45e9692ae 100644
--- a/arch/arm/lib/io-readsw-armv4.S
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -26,7 +26,7 @@
ENTRY(__raw_readsw)
teq r2, #0
- moveq pc, lr
+ reteq lr
tst r1, #3
bne .Linsw_align
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
index 68b92f4acaeb..a46bbc9b168b 100644
--- a/arch/arm/lib/io-writesb.S
+++ b/arch/arm/lib/io-writesb.S
@@ -45,7 +45,7 @@
ENTRY(__raw_writesb)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
ands ip, r1, #3
bne .Loutsb_align
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
index d0d104a0dd11..4ea2435988c1 100644
--- a/arch/arm/lib/io-writesl.S
+++ b/arch/arm/lib/io-writesl.S
@@ -12,7 +12,7 @@
ENTRY(__raw_writesl)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
ands ip, r1, #3
bne 3f
@@ -33,7 +33,7 @@ ENTRY(__raw_writesl)
ldrne r3, [r1, #0]
strcs ip, [r0, #0]
strne r3, [r0, #0]
- mov pc, lr
+ ret lr
3: bic r1, r1, #3
ldr r3, [r1], #4
@@ -47,7 +47,7 @@ ENTRY(__raw_writesl)
orr ip, ip, r3, lspush #16
str ip, [r0]
bne 4b
- mov pc, lr
+ ret lr
5: mov ip, r3, lspull #8
ldr r3, [r1], #4
@@ -55,7 +55,7 @@ ENTRY(__raw_writesl)
orr ip, ip, r3, lspush #24
str ip, [r0]
bne 5b
- mov pc, lr
+ ret lr
6: mov ip, r3, lspull #24
ldr r3, [r1], #4
@@ -63,5 +63,5 @@ ENTRY(__raw_writesl)
orr ip, ip, r3, lspush #8
str ip, [r0]
bne 6b
- mov pc, lr
+ ret lr
ENDPROC(__raw_writesl)
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
index 49b800419e32..121789eb6802 100644
--- a/arch/arm/lib/io-writesw-armv3.S
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -28,11 +28,11 @@
orr r3, r3, r3, lsl #16
str r3, [r0]
subs r2, r2, #1
- moveq pc, lr
+ reteq lr
ENTRY(__raw_writesw)
teq r2, #0 @ do we have to check for the zero len?
- moveq pc, lr
+ reteq lr
tst r1, #3
bne .Loutsw_align
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index ff4f71b579ee..269f90c51ad2 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -31,7 +31,7 @@
ENTRY(__raw_writesw)
teq r2, #0
- moveq pc, lr
+ reteq lr
ands r3, r1, #3
bne .Loutsw_align
@@ -96,5 +96,5 @@ ENTRY(__raw_writesw)
tst r2, #1
3: movne ip, r3, lsr #8
strneh ip, [r0]
- mov pc, lr
+ ret lr
ENDPROC(__raw_writesw)
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index c562f649734c..947567ff67f9 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -210,7 +210,7 @@ ENTRY(__aeabi_uidiv)
UNWIND(.fnstart)
subs r2, r1, #1
- moveq pc, lr
+ reteq lr
bcc Ldiv0
cmp r0, r1
bls 11f
@@ -220,16 +220,16 @@ UNWIND(.fnstart)
ARM_DIV_BODY r0, r1, r2, r3
mov r0, r2
- mov pc, lr
+ ret lr
11: moveq r0, #1
movne r0, #0
- mov pc, lr
+ ret lr
12: ARM_DIV2_ORDER r1, r2
mov r0, r0, lsr r2
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__udivsi3)
@@ -244,11 +244,11 @@ UNWIND(.fnstart)
moveq r0, #0
tsthi r1, r2 @ see if divisor is power of 2
andeq r0, r0, r2
- movls pc, lr
+ retls lr
ARM_MOD_BODY r0, r1, r2, r3
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__umodsi3)
@@ -274,23 +274,23 @@ UNWIND(.fnstart)
cmp ip, #0
rsbmi r0, r0, #0
- mov pc, lr
+ ret lr
10: teq ip, r0 @ same sign ?
rsbmi r0, r0, #0
- mov pc, lr
+ ret lr
11: movlo r0, #0
moveq r0, ip, asr #31
orreq r0, r0, #1
- mov pc, lr
+ ret lr
12: ARM_DIV2_ORDER r1, r2
cmp ip, #0
mov r0, r3, lsr r2
rsbmi r0, r0, #0
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__divsi3)
@@ -315,7 +315,7 @@ UNWIND(.fnstart)
10: cmp ip, #0
rsbmi r0, r0, #0
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__modsi3)
@@ -331,7 +331,7 @@ UNWIND(.save {r0, r1, ip, lr} )
ldmfd sp!, {r1, r2, ip, lr}
mul r3, r0, r2
sub r1, r1, r3
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__aeabi_uidivmod)
@@ -344,7 +344,7 @@ UNWIND(.save {r0, r1, ip, lr} )
ldmfd sp!, {r1, r2, ip, lr}
mul r3, r0, r2
sub r1, r1, r3
- mov pc, lr
+ ret lr
UNWIND(.fnend)
ENDPROC(__aeabi_idivmod)
diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S
index f83d449141f7..922dcd88b02b 100644
--- a/arch/arm/lib/lshrdi3.S
+++ b/arch/arm/lib/lshrdi3.S
@@ -27,6 +27,7 @@ Boston, MA 02110-1301, USA. */
#include <linux/linkage.h>
+#include <asm/assembler.h>
#ifdef __ARMEB__
#define al r1
@@ -47,7 +48,7 @@ ENTRY(__aeabi_llsr)
THUMB( lslmi r3, ah, ip )
THUMB( orrmi al, al, r3 )
mov ah, ah, lsr r2
- mov pc, lr
+ ret lr
ENDPROC(__lshrdi3)
ENDPROC(__aeabi_llsr)
diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S
index 1da86991d700..74a5bed6d999 100644
--- a/arch/arm/lib/memchr.S
+++ b/arch/arm/lib/memchr.S
@@ -22,5 +22,5 @@ ENTRY(memchr)
bne 1b
sub r0, r0, #1
2: movne r0, #0
- mov pc, lr
+ ret lr
ENDPROC(memchr)
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index 94b0650ea98f..671455c854fa 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -110,7 +110,7 @@ ENTRY(memset)
strneb r1, [ip], #1
tst r2, #1
strneb r1, [ip], #1
- mov pc, lr
+ ret lr
6: subs r2, r2, #4 @ 1 do we have enough
blt 5b @ 1 bytes to align with?
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S
index 3fbdef5f802a..385ccb306fa2 100644
--- a/arch/arm/lib/memzero.S
+++ b/arch/arm/lib/memzero.S
@@ -121,5 +121,5 @@ ENTRY(__memzero)
strneb r2, [r0], #1 @ 1
tst r1, #1 @ 1 a byte left over
strneb r2, [r0], #1 @ 1
- mov pc, lr @ 1
+ ret lr @ 1
ENDPROC(__memzero)
diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
index 36c91b4957e2..204305956925 100644
--- a/arch/arm/lib/muldi3.S
+++ b/arch/arm/lib/muldi3.S
@@ -11,6 +11,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#ifdef __ARMEB__
#define xh r0
@@ -41,7 +42,7 @@ ENTRY(__aeabi_lmul)
adc xh, xh, yh, lsr #16
adds xl, xl, ip, lsl #16
adc xh, xh, ip, lsr #16
- mov pc, lr
+ ret lr
ENDPROC(__muldi3)
ENDPROC(__aeabi_lmul)
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 3d73dcb959b0..38d660d3705f 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -36,7 +36,7 @@ ENTRY(__put_user_1)
check_uaccess r0, 1, r1, ip, __put_user_bad
1: TUSER(strb) r2, [r0]
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__put_user_1)
ENTRY(__put_user_2)
@@ -60,14 +60,14 @@ ENTRY(__put_user_2)
#endif
#endif /* CONFIG_THUMB2_KERNEL */
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__put_user_2)
ENTRY(__put_user_4)
check_uaccess r0, 4, r1, ip, __put_user_bad
4: TUSER(str) r2, [r0]
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__put_user_4)
ENTRY(__put_user_8)
@@ -80,12 +80,12 @@ ENTRY(__put_user_8)
6: TUSER(str) r3, [r0]
#endif
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(__put_user_8)
__put_user_bad:
mov r0, #-EFAULT
- mov pc, lr
+ ret lr
ENDPROC(__put_user_bad)
.pushsection __ex_table, "a"
diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S
index d8f2a1c1aea4..013d64c71e8d 100644
--- a/arch/arm/lib/strchr.S
+++ b/arch/arm/lib/strchr.S
@@ -23,5 +23,5 @@ ENTRY(strchr)
teq r2, r1
movne r0, #0
subeq r0, r0, #1
- mov pc, lr
+ ret lr
ENDPROC(strchr)
diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
index 302f20cd2423..3cec1c7482c4 100644
--- a/arch/arm/lib/strrchr.S
+++ b/arch/arm/lib/strrchr.S
@@ -22,5 +22,5 @@ ENTRY(strrchr)
teq r2, #0
bne 1b
mov r0, r3
- mov pc, lr
+ ret lr
ENDPROC(strrchr)
diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
index f0df6a91db04..ad4a6309141a 100644
--- a/arch/arm/lib/ucmpdi2.S
+++ b/arch/arm/lib/ucmpdi2.S
@@ -11,6 +11,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#ifdef __ARMEB__
#define xh r0
@@ -31,7 +32,7 @@ ENTRY(__ucmpdi2)
movlo r0, #0
moveq r0, #1
movhi r0, #2
- mov pc, lr
+ ret lr
ENDPROC(__ucmpdi2)
@@ -44,7 +45,7 @@ ENTRY(__aeabi_ulcmp)
movlo r0, #-1
moveq r0, #0
movhi r0, #1
- mov pc, lr
+ ret lr
ENDPROC(__aeabi_ulcmp)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 45b55e0f0db6..6cc6f7aebdae 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -113,14 +113,12 @@ config SOC_AT91RM9200
select HAVE_AT91_DBGU0
select MULTI_IRQ_HANDLER
select SPARSE_IRQ
- select AT91_USE_OLD_CLK
select HAVE_AT91_USB_CLK
config SOC_AT91SAM9260
bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
select HAVE_AT91_DBGU0
select SOC_AT91SAM9
- select AT91_USE_OLD_CLK
select HAVE_AT91_USB_CLK
help
Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -140,7 +138,6 @@ config SOC_AT91SAM9263
select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
select SOC_AT91SAM9
- select AT91_USE_OLD_CLK
select HAVE_AT91_USB_CLK
config SOC_AT91SAM9RL
@@ -155,7 +152,6 @@ config SOC_AT91SAM9G45
select HAVE_AT91_DBGU1
select HAVE_FB_ATMEL
select SOC_AT91SAM9
- select AT91_USE_OLD_CLK
select HAVE_AT91_UTMI
select HAVE_AT91_USB_CLK
help
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 787bb50a4dff..038702ee8bc6 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -26,10 +26,11 @@
#include "at91_aic.h"
#include "soc.h"
#include "generic.h"
-#include "clock.h"
#include "sam9_smc.h"
#include "pm.h"
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
/* --------------------------------------------------------------------
* Clocks
* -------------------------------------------------------------------- */
@@ -277,6 +278,9 @@ static void __init at91rm9200_register_clocks(void)
clk_register(&pck2);
clk_register(&pck3);
}
+#else
+#define at91rm9200_register_clocks NULL
+#endif
/* --------------------------------------------------------------------
* GPIO
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 3f4bb58aea54..74f1eaf97801 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -15,7 +15,7 @@
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
-#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index c3d22be73b7c..3477ba94c4c5 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -27,10 +27,11 @@
#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
-#include "clock.h"
#include "sam9_smc.h"
#include "pm.h"
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
/* --------------------------------------------------------------------
* Clocks
* -------------------------------------------------------------------- */
@@ -288,6 +289,9 @@ static void __init at91sam9260_register_clocks(void)
clk_register(&pck0);
clk_register(&pck1);
}
+#else
+#define at91sam9260_register_clocks NULL
+#endif
/* --------------------------------------------------------------------
* GPIO
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index f30290572293..810fa5f15a51 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -25,10 +25,11 @@
#include "at91_rstc.h"
#include "soc.h"
#include "generic.h"
-#include "clock.h"
#include "sam9_smc.h"
#include "pm.h"
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
/* --------------------------------------------------------------------
* Clocks
* -------------------------------------------------------------------- */
@@ -199,6 +200,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -280,6 +282,9 @@ static void __init at91sam9263_register_clocks(void)
clk_register(&pck2);
clk_register(&pck3);
}
+#else
+#define at91sam9263_register_clocks NULL
+#endif
/* --------------------------------------------------------------------
* GPIO
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 309390d8e2f8..cef0e2f57068 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1131,9 +1131,7 @@ static void __init at91_add_device_watchdog(void) {}
* PWM
* --------------------------------------------------------------------*/
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
static struct resource pwm_resources[] = {
[0] = {
.start = AT91SAM9263_BASE_PWMC,
@@ -1148,11 +1146,8 @@ static struct resource pwm_resources[] = {
};
static struct platform_device at91sam9263_pwm0_device = {
- .name = "atmel_pwm",
+ .name = "at91sam9rl-pwm",
.id = -1,
- .dev = {
- .platform_data = &pwm_mask,
- },
.resource = pwm_resources,
.num_resources = ARRAY_SIZE(pwm_resources),
};
@@ -1171,8 +1166,6 @@ void __init at91_add_device_pwm(u32 mask)
if (mask & (1 << AT91_PWM3))
at91_set_B_periph(AT91_PIN_PB29, 1); /* enable PWM3 */
- pwm_mask = mask;
-
platform_device_register(&at91sam9263_pwm0_device);
}
#else
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9d3d544ac19c..9d45496e4932 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -25,10 +25,11 @@
#include "at91_aic.h"
#include "soc.h"
#include "generic.h"
-#include "clock.h"
#include "sam9_smc.h"
#include "pm.h"
+#if defined(CONFIG_OLD_CLK_AT91)
+#include "clock.h"
/* --------------------------------------------------------------------
* Clocks
* -------------------------------------------------------------------- */
@@ -251,6 +252,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk),
+ CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
/* more usart lookup table for DT entries */
CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
@@ -331,6 +333,9 @@ static void __init at91sam9g45_register_clocks(void)
clk_register(&pck0);
clk_register(&pck1);
}
+#else
+#define at91sam9g45_register_clocks NULL
+#endif
/* --------------------------------------------------------------------
* GPIO
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 391ab6bb536a..21ab782cc8e9 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1334,9 +1334,7 @@ static void __init at91_add_device_watchdog(void) {}
* PWM
* --------------------------------------------------------------------*/
-#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
static struct resource pwm_resources[] = {
[0] = {
.start = AT91SAM9G45_BASE_PWMC,
@@ -1351,11 +1349,8 @@ static struct resource pwm_resources[] = {
};
static struct platform_device at91sam9g45_pwm0_device = {
- .name = "atmel_pwm",
+ .name = "at91sam9rl-pwm",
.id = -1,
- .dev = {
- .platform_data = &pwm_mask,
- },
.resource = pwm_resources,
.num_resources = ARRAY_SIZE(pwm_resources),
};
@@ -1374,8 +1369,6 @@ void __init at91_add_device_pwm(u32 mask)
if (mask & (1 << AT91_PWM3))
at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */
- pwm_mask = mask;
-
platform_device_register(&at91sam9g45_pwm0_device);
}
#else
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index a79960f57e6a..878d5015daab 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -200,6 +200,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
+ CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
CLKDEV_CON_ID("pioB", &pioB_clk),
CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 0b1d71a7d9bf..37d1c9ed4562 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -799,9 +799,7 @@ static void __init at91_add_device_watchdog(void) {}
* PWM
* --------------------------------------------------------------------*/
-#if defined(CONFIG_ATMEL_PWM)
-static u32 pwm_mask;
-
+#if IS_ENABLED(CONFIG_PWM_ATMEL)
static struct resource pwm_resources[] = {
[0] = {
.start = AT91SAM9RL_BASE_PWMC,
@@ -816,11 +814,8 @@ static struct resource pwm_resources[] = {
};
static struct platform_device at91sam9rl_pwm0_device = {
- .name = "atmel_pwm",
+ .name = "at91sam9rl-pwm",
.id = -1,
- .dev = {
- .platform_data = &pwm_mask,
- },
.resource = pwm_resources,
.num_resources = ARRAY_SIZE(pwm_resources),
};
@@ -839,8 +834,6 @@ void __init at91_add_device_pwm(u32 mask)
if (mask & (1 << AT91_PWM3))
at91_set_B_periph(AT91_PIN_PD8, 1); /* enable PWM3 */
- pwm_mask = mask;
-
platform_device_register(&at91sam9rl_pwm0_device);
}
#else
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index cd2726ee5add..fc446097f410 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -32,6 +32,8 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
#include <video/atmel_lcdc.h>
@@ -369,21 +371,47 @@ static struct gpio_led ek_leds[] = {
.name = "ds3",
.gpio = AT91_PIN_PB7,
.default_trigger = "heartbeat",
+ },
+#if !IS_ENABLED(CONFIG_LEDS_PWM)
+ {
+ .name = "ds1",
+ .gpio = AT91_PIN_PB8,
+ .active_low = 1,
+ .default_trigger = "none",
}
+#endif
};
/*
* PWM Leds
*/
-static struct gpio_led ek_pwm_led[] = {
- /* For now only DS1 is PWM-driven (by pwm1) */
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "ds1",
+ 5000, PWM_POLARITY_INVERSED),
+};
+
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct led_pwm pwm_leds[] = {
{
- .name = "ds1",
- .gpio = 1, /* is PWM channel number */
- .active_low = 1,
- .default_trigger = "none",
- }
+ .name = "ds1",
+ .max_brightness = 255,
+ },
+};
+
+static struct led_pwm_platform_data pwm_data = {
+ .num_leds = ARRAY_SIZE(pwm_leds),
+ .leds = pwm_leds,
+};
+
+static struct platform_device leds_pwm = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
};
+#endif
+
/*
* CAN
@@ -403,6 +431,12 @@ static struct at91_can_data ek_can_data = {
.transceiver_switch = sam9263ek_transceiver_switch,
};
+static struct platform_device *devices[] __initdata = {
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+ &leds_pwm,
+#endif
+};
+
static void __init ek_board_init(void)
{
/* Serial */
@@ -437,9 +471,14 @@ static void __init ek_board_init(void)
at91_add_device_ac97(&ek_ac97_data);
/* LEDs */
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
- at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+ at91_add_device_pwm(1 << AT91_PWM1);
+#endif
/* CAN */
at91_add_device_can(&ek_can_data);
+ /* Other platform devices */
+ platform_add_devices(devices, ARRAY_SIZE(devices));
}
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 1ea61328f30d..b227732b0c83 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -26,6 +26,8 @@
#include <linux/leds.h>
#include <linux/atmel-mci.h>
#include <linux/delay.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
#include <linux/platform_data/at91_adc.h>
@@ -416,7 +418,7 @@ static struct gpio_led ek_leds[] = {
.active_low = 1,
.default_trigger = "nand-disk",
},
-#if !(defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE))
+#if !IS_ENABLED(CONFIG_LEDS_PWM)
{ /* "right" led, green, userled1, pwm1 */
.name = "d7",
.gpio = AT91_PIN_PD31,
@@ -430,22 +432,41 @@ static struct gpio_led ek_leds[] = {
/*
* PWM Leds
*/
-static struct gpio_led ek_pwm_led[] = {
-#if defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE)
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "d7",
+ 5000, PWM_POLARITY_INVERSED),
+};
+
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct led_pwm pwm_leds[] = {
{ /* "right" led, green, userled1, pwm1 */
- .name = "d7",
- .gpio = 1, /* is PWM channel number */
- .active_low = 1,
- .default_trigger = "none",
+ .name = "d7",
+ .max_brightness = 255,
},
-#endif
};
+static struct led_pwm_platform_data pwm_data = {
+ .num_leds = ARRAY_SIZE(pwm_leds),
+ .leds = pwm_leds,
+};
+
+static struct platform_device leds_pwm = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+#endif
+
static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_SOC_CAMERA_OV2640) || \
defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
&isi_ov2640,
#endif
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+ &leds_pwm,
+#endif
};
static void __init ek_board_init(void)
@@ -486,7 +507,10 @@ static void __init ek_board_init(void)
at91_add_device_ac97(&ek_ac97_data);
/* LEDs */
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
- at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+ at91_add_device_pwm(1 << AT91_PWM1);
+#endif
/* Other platform devices */
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
index 4e773b55bc2d..836e9a537e0c 100644
--- a/arch/arm/mach-at91/board.h
+++ b/arch/arm/mach-at91/board.h
@@ -123,6 +123,5 @@ extern void __init at91_add_device_can(struct at91_can_data *data);
/* LEDs */
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
#endif
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
index 77c4d8fd03fd..eb22e3357e87 100644
--- a/arch/arm/mach-at91/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -54,40 +54,3 @@ void __init at91_gpio_leds(struct gpio_led *leds, int nr)
void __init at91_gpio_leds(struct gpio_led *leds, int nr) {}
#endif
-
-/* ------------------------------------------------------------------------- */
-
-#if defined (CONFIG_LEDS_ATMEL_PWM)
-
-/*
- * PWM Leds
- */
-
-static struct gpio_led_platform_data pwm_led_data;
-
-static struct platform_device at91_pwm_leds_device = {
- .name = "leds-atmel-pwm",
- .id = -1,
- .dev.platform_data = &pwm_led_data,
-};
-
-void __init at91_pwm_leds(struct gpio_led *leds, int nr)
-{
- int i;
- u32 pwm_mask = 0;
-
- if (!nr)
- return;
-
- for (i = 0; i < nr; i++)
- pwm_mask |= (1 << leds[i].gpio);
-
- pwm_led_data.leds = leds;
- pwm_led_data.num_leds = nr;
-
- at91_add_device_pwm(pwm_mask);
- platform_device_register(&at91_pwm_leds_device);
-}
-#else
-void __init at91_pwm_leds(struct gpio_led *leds, int nr){}
-#endif
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 41c839167e87..fc938005ad39 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -9,7 +9,6 @@ config ARCH_BCM_MOBILE
bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7
select ARCH_REQUIRE_GPIOLIB
select ARM_ERRATA_754322
- select ARM_ERRATA_764369 if SMP
select ARM_ERRATA_775420
select ARM_GIC
select GPIO_BCM_KONA
@@ -26,16 +25,18 @@ menu "Broadcom Mobile SoC Selection"
config ARCH_BCM_281XX
bool "Broadcom BCM281XX SoC family"
default y
+ select HAVE_SMP
help
- Enable support for the the BCM281XX family, which includes
+ Enable support for the BCM281XX family, which includes
BCM11130, BCM11140, BCM11351, BCM28145 and BCM28155
variants.
config ARCH_BCM_21664
bool "Broadcom BCM21664 SoC family"
default y
+ select HAVE_SMP
help
- Enable support for the the BCM21664 family, which includes
+ Enable support for the BCM21664 family, which includes
BCM21663 and BCM21664 variants.
config ARCH_BCM_MOBILE_L2_CACHE
@@ -49,6 +50,17 @@ config ARCH_BCM_MOBILE_SMC
bool
depends on ARCH_BCM_281XX || ARCH_BCM_21664
+config ARCH_BCM_MOBILE_SMP
+ bool "Broadcom mobile SoC SMP support"
+ depends on (ARCH_BCM_281XX || ARCH_BCM_21664) && SMP
+ default y
+ select HAVE_ARM_SCU
+ select ARM_ERRATA_764369
+ help
+ SMP support for the BCM281XX and BCM21664 SoC families.
+ Provided as an option so SMP support for SoCs of this type
+ can be disabled for an SMP-enabled kernel.
+
endmenu
endif
@@ -87,4 +99,20 @@ config ARCH_BCM_5301X
different SoC or with the older BCM47XX and BCM53XX based
network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
+config ARCH_BRCMSTB
+ bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
+ depends on MMU
+ select ARM_GIC
+ select MIGHT_HAVE_PCI
+ select HAVE_SMP
+ select HAVE_ARM_ARCH_TIMER
+ select BRCMSTB_GISB_ARB
+ select BRCMSTB_L2_IRQ
+ help
+ Say Y if you intend to run the kernel on a Broadcom ARM-based STB
+ chipset.
+
+ This enables support for Broadcom ARM-based set-top box chipsets,
+ including the 7445 family of chips.
+
endif
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 731292114975..67c492aabf4d 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -16,6 +16,9 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o
# BCM21664
obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
+# BCM281XX and BCM21664 SMP support
+obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += kona_smp.o
+
# BCM281XX and BCM21664 L2 cache control
obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o
@@ -30,3 +33,8 @@ obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o
# BCM5301X
obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o
+
+ifeq ($(CONFIG_ARCH_BRCMSTB),y)
+obj-y += brcmstb.o
+obj-$(CONFIG_SMP) += headsmp-brcmstb.o platsmp-brcmstb.o
+endif
diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index f0521cc0640d..82ad5687771f 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -60,8 +60,7 @@ static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
static void __init bcm21664_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table, NULL,
- &platform_bus);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
kona_l2_cache_init();
}
diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c
index 1ac59fc0cb15..2e367bd7c600 100644
--- a/arch/arm/mach-bcm/board_bcm281xx.c
+++ b/arch/arm/mach-bcm/board_bcm281xx.c
@@ -58,8 +58,7 @@ static void bcm281xx_restart(enum reboot_mode mode, const char *cmd)
static void __init bcm281xx_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table, NULL,
- &platform_bus);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
kona_l2_cache_init();
}
diff --git a/arch/arm/mach-bcm/brcmstb.c b/arch/arm/mach-bcm/brcmstb.c
new file mode 100644
index 000000000000..60a5afa06ed7
--- /dev/null
+++ b/arch/arm/mach-bcm/brcmstb.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013-2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static const char *brcmstb_match[] __initconst = {
+ "brcm,bcm7445",
+ "brcm,brcmstb",
+ NULL
+};
+
+DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
+ .dt_compat = brcmstb_match,
+MACHINE_END
diff --git a/arch/arm/mach-bcm/brcmstb.h b/arch/arm/mach-bcm/brcmstb.h
new file mode 100644
index 000000000000..ec0c3d112b36
--- /dev/null
+++ b/arch/arm/mach-bcm/brcmstb.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013-2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by 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 __BRCMSTB_H__
+#define __BRCMSTB_H__
+
+void brcmstb_secondary_startup(void);
+
+#endif /* __BRCMSTB_H__ */
diff --git a/arch/arm/mach-bcm/headsmp-brcmstb.S b/arch/arm/mach-bcm/headsmp-brcmstb.S
new file mode 100644
index 000000000000..199c1ea58248
--- /dev/null
+++ b/arch/arm/mach-bcm/headsmp-brcmstb.S
@@ -0,0 +1,33 @@
+/*
+ * SMP boot code for secondary CPUs
+ * Based on arch/arm/mach-tegra/headsmp.S
+ *
+ * Copyright (C) 2010 NVIDIA, Inc.
+ * Copyright (C) 2013-2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/assembler.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ .section ".text.head", "ax"
+
+ENTRY(brcmstb_secondary_startup)
+ /*
+ * Ensure CPU is in a sane state by disabling all IRQs and switching
+ * into SVC mode.
+ */
+ setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
+
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(brcmstb_secondary_startup)
diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/kona_smp.c
new file mode 100644
index 000000000000..66a0465528a5
--- /dev/null
+++ b/arch/arm/mach-bcm/kona_smp.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2014 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/sched.h>
+
+#include <asm/smp.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+/* Size of mapped Cortex A9 SCU address space */
+#define CORTEX_A9_SCU_SIZE 0x58
+
+#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
+#define BOOT_ADDR_CPUID_MASK 0x3
+
+/* Name of device node property defining secondary boot register location */
+#define OF_SECONDARY_BOOT "secondary-boot-reg"
+
+/* I/O address of register used to coordinate secondary core startup */
+static u32 secondary_boot;
+
+/*
+ * Enable the Cortex A9 Snoop Control Unit
+ *
+ * By the time this is called we already know there are multiple
+ * cores present. We assume we're running on a Cortex A9 processor,
+ * so any trouble getting the base address register or getting the
+ * SCU base is a problem.
+ *
+ * Return 0 if successful or an error code otherwise.
+ */
+static int __init scu_a9_enable(void)
+{
+ unsigned long config_base;
+ void __iomem *scu_base;
+
+ if (!scu_a9_has_base()) {
+ pr_err("no configuration base address register!\n");
+ return -ENXIO;
+ }
+
+ /* Config base address register value is zero for uniprocessor */
+ config_base = scu_a9_get_base();
+ if (!config_base) {
+ pr_err("hardware reports only one core\n");
+ return -ENOENT;
+ }
+
+ scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
+ if (!scu_base) {
+ pr_err("failed to remap config base (%lu/%u) for SCU\n",
+ config_base, CORTEX_A9_SCU_SIZE);
+ return -ENOMEM;
+ }
+
+ scu_enable(scu_base);
+
+ iounmap(scu_base); /* That's the last we'll need of this */
+
+ return 0;
+}
+
+static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
+{
+ static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
+ struct device_node *node;
+ int ret;
+
+ BUG_ON(secondary_boot); /* We're called only once */
+
+ /*
+ * This function is only called via smp_ops->smp_prepare_cpu().
+ * That only happens if a "/cpus" device tree node exists
+ * and has an "enable-method" property that selects the SMP
+ * operations defined herein.
+ */
+ node = of_find_node_by_path("/cpus");
+ BUG_ON(!node);
+
+ /*
+ * Our secondary enable method requires a "secondary-boot-reg"
+ * property to specify a register address used to request the
+ * ROM code boot a secondary code. If we have any trouble
+ * getting this we fall back to uniprocessor mode.
+ */
+ if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) {
+ pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n",
+ node->name);
+ ret = -ENOENT; /* Arrange to disable SMP */
+ goto out;
+ }
+
+ /*
+ * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
+ * returned, the SoC reported a uniprocessor configuration.
+ * We bail on any other error.
+ */
+ ret = scu_a9_enable();
+out:
+ of_node_put(node);
+ if (ret) {
+ /* Update the CPU present map to reflect uniprocessor mode */
+ BUG_ON(ret != -ENOENT);
+ pr_warn("disabling SMP\n");
+ init_cpu_present(&only_cpu_0);
+ }
+}
+
+/*
+ * The ROM code has the secondary cores looping, waiting for an event.
+ * When an event occurs each core examines the bottom two bits of the
+ * secondary boot register. When a core finds those bits contain its
+ * own core id, it performs initialization, including computing its boot
+ * address by clearing the boot register value's bottom two bits. The
+ * core signals that it is beginning its execution by writing its boot
+ * address back to the secondary boot register, and finally jumps to
+ * that address.
+ *
+ * So to start a core executing we need to:
+ * - Encode the (hardware) CPU id with the bottom bits of the secondary
+ * start address.
+ * - Write that value into the secondary boot register.
+ * - Generate an event to wake up the secondary CPU(s).
+ * - Wait for the secondary boot register to be re-written, which
+ * indicates the secondary core has started.
+ */
+static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ void __iomem *boot_reg;
+ phys_addr_t boot_func;
+ u64 start_clock;
+ u32 cpu_id;
+ u32 boot_val;
+ bool timeout = false;
+
+ cpu_id = cpu_logical_map(cpu);
+ if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
+ pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
+ return -EINVAL;
+ }
+
+ if (!secondary_boot) {
+ pr_err("required secondary boot register not specified\n");
+ return -EINVAL;
+ }
+
+ boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32));
+ if (!boot_reg) {
+ pr_err("unable to map boot register for cpu %u\n", cpu_id);
+ return -ENOSYS;
+ }
+
+ /*
+ * Secondary cores will start in secondary_startup(),
+ * defined in "arch/arm/kernel/head.S"
+ */
+ boot_func = virt_to_phys(secondary_startup);
+ BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
+ BUG_ON(boot_func > (phys_addr_t)U32_MAX);
+
+ /* The core to start is encoded in the low bits */
+ boot_val = (u32)boot_func | cpu_id;
+ writel_relaxed(boot_val, boot_reg);
+
+ sev();
+
+ /* The low bits will be cleared once the core has started */
+ start_clock = local_clock();
+ while (!timeout && readl_relaxed(boot_reg) == boot_val)
+ timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
+
+ iounmap(boot_reg);
+
+ if (!timeout)
+ return 0;
+
+ pr_err("timeout waiting for cpu %u to start\n", cpu_id);
+
+ return -ENOSYS;
+}
+
+static struct smp_operations bcm_smp_ops __initdata = {
+ .smp_prepare_cpus = bcm_smp_prepare_cpus,
+ .smp_boot_secondary = bcm_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
+ &bcm_smp_ops);
diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c
new file mode 100644
index 000000000000..af780e9c23a6
--- /dev/null
+++ b/arch/arm/mach-bcm/platsmp-brcmstb.c
@@ -0,0 +1,363 @@
+/*
+ * Broadcom STB CPU SMP and hotplug support for ARM
+ *
+ * Copyright (C) 2013-2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/printk.h>
+#include <linux/regmap.h>
+#include <linux/smp.h>
+#include <linux/mfd/syscon.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/mach-types.h>
+#include <asm/smp_plat.h>
+
+#include "brcmstb.h"
+
+enum {
+ ZONE_MAN_CLKEN_MASK = BIT(0),
+ ZONE_MAN_RESET_CNTL_MASK = BIT(1),
+ ZONE_MAN_MEM_PWR_MASK = BIT(4),
+ ZONE_RESERVED_1_MASK = BIT(5),
+ ZONE_MAN_ISO_CNTL_MASK = BIT(6),
+ ZONE_MANUAL_CONTROL_MASK = BIT(7),
+ ZONE_PWR_DN_REQ_MASK = BIT(9),
+ ZONE_PWR_UP_REQ_MASK = BIT(10),
+ ZONE_BLK_RST_ASSERT_MASK = BIT(12),
+ ZONE_PWR_OFF_STATE_MASK = BIT(25),
+ ZONE_PWR_ON_STATE_MASK = BIT(26),
+ ZONE_DPG_PWR_STATE_MASK = BIT(28),
+ ZONE_MEM_PWR_STATE_MASK = BIT(29),
+ ZONE_RESET_STATE_MASK = BIT(31),
+ CPU0_PWR_ZONE_CTRL_REG = 1,
+ CPU_RESET_CONFIG_REG = 2,
+};
+
+static void __iomem *cpubiuctrl_block;
+static void __iomem *hif_cont_block;
+static u32 cpu0_pwr_zone_ctrl_reg;
+static u32 cpu_rst_cfg_reg;
+static u32 hif_cont_reg;
+
+#ifdef CONFIG_HOTPLUG_CPU
+static DEFINE_PER_CPU_ALIGNED(int, per_cpu_sw_state);
+
+static int per_cpu_sw_state_rd(u32 cpu)
+{
+ sync_cache_r(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
+ return per_cpu(per_cpu_sw_state, cpu);
+}
+
+static void per_cpu_sw_state_wr(u32 cpu, int val)
+{
+ per_cpu(per_cpu_sw_state, cpu) = val;
+ dmb();
+ sync_cache_w(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
+ dsb_sev();
+}
+#else
+static inline void per_cpu_sw_state_wr(u32 cpu, int val) { }
+#endif
+
+static void __iomem *pwr_ctrl_get_base(u32 cpu)
+{
+ void __iomem *base = cpubiuctrl_block + cpu0_pwr_zone_ctrl_reg;
+ base += (cpu_logical_map(cpu) * 4);
+ return base;
+}
+
+static u32 pwr_ctrl_rd(u32 cpu)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ return readl_relaxed(base);
+}
+
+static void pwr_ctrl_wr(u32 cpu, u32 val)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ writel(val, base);
+}
+
+static void cpu_rst_cfg_set(u32 cpu, int set)
+{
+ u32 val;
+ val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
+ if (set)
+ val |= BIT(cpu_logical_map(cpu));
+ else
+ val &= ~BIT(cpu_logical_map(cpu));
+ writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
+}
+
+static void cpu_set_boot_addr(u32 cpu, unsigned long boot_addr)
+{
+ const int reg_ofs = cpu_logical_map(cpu) * 8;
+ writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
+ writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
+}
+
+static void brcmstb_cpu_boot(u32 cpu)
+{
+ pr_info("SMP: Booting CPU%d...\n", cpu);
+
+ /*
+ * set the reset vector to point to the secondary_startup
+ * routine
+ */
+ cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
+
+ /* unhalt the cpu */
+ cpu_rst_cfg_set(cpu, 0);
+}
+
+static void brcmstb_cpu_power_on(u32 cpu)
+{
+ /*
+ * The secondary cores power was cut, so we must go through
+ * power-on initialization.
+ */
+ u32 tmp;
+
+ pr_info("SMP: Powering up CPU%d...\n", cpu);
+
+ /* Request zone power up */
+ pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+
+ /* Wait for the power up FSM to complete */
+ do {
+ tmp = pwr_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+
+ per_cpu_sw_state_wr(cpu, 1);
+}
+
+static int brcmstb_cpu_get_power_state(u32 cpu)
+{
+ int tmp = pwr_ctrl_rd(cpu);
+ return (tmp & ZONE_RESET_STATE_MASK) ? 0 : 1;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void brcmstb_cpu_die(u32 cpu)
+{
+ v7_exit_coherency_flush(all);
+
+ /* Prevent all interrupts from reaching this CPU. */
+ arch_local_irq_disable();
+
+ /*
+ * Final full barrier to ensure everything before this instruction has
+ * quiesced.
+ */
+ isb();
+ dsb();
+
+ per_cpu_sw_state_wr(cpu, 0);
+
+ /* Sit and wait to die */
+ wfi();
+
+ /* We should never get here... */
+ panic("Spurious interrupt on CPU %d received!\n", cpu);
+}
+
+static int brcmstb_cpu_kill(u32 cpu)
+{
+ u32 tmp;
+
+ pr_info("SMP: Powering down CPU%d...\n", cpu);
+
+ while (per_cpu_sw_state_rd(cpu))
+ ;
+
+ /* Program zone reset */
+ pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
+ ZONE_PWR_DN_REQ_MASK);
+
+ /* Verify zone reset */
+ tmp = pwr_ctrl_rd(cpu);
+ if (!(tmp & ZONE_RESET_STATE_MASK))
+ pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
+ __func__, cpu);
+
+ /* Wait for power down */
+ do {
+ tmp = pwr_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+
+ /* Settle-time from Broadcom-internal DVT reference code */
+ udelay(7);
+
+ /* Assert reset on the CPU */
+ cpu_rst_cfg_set(cpu, 1);
+
+ return 1;
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
+{
+ int rc = 0;
+ char *name;
+ struct device_node *syscon_np = NULL;
+
+ name = "syscon-cpu";
+
+ syscon_np = of_parse_phandle(np, name, 0);
+ if (!syscon_np) {
+ pr_err("can't find phandle %s\n", name);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ cpubiuctrl_block = of_iomap(syscon_np, 0);
+ if (!cpubiuctrl_block) {
+ pr_err("iomap failed for cpubiuctrl_block\n");
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ rc = of_property_read_u32_index(np, name, CPU0_PWR_ZONE_CTRL_REG,
+ &cpu0_pwr_zone_ctrl_reg);
+ if (rc) {
+ pr_err("failed to read 1st entry from %s property (%d)\n", name,
+ rc);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ rc = of_property_read_u32_index(np, name, CPU_RESET_CONFIG_REG,
+ &cpu_rst_cfg_reg);
+ if (rc) {
+ pr_err("failed to read 2nd entry from %s property (%d)\n", name,
+ rc);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+cleanup:
+ if (syscon_np)
+ of_node_put(syscon_np);
+
+ return rc;
+}
+
+static int __init setup_hifcont_regs(struct device_node *np)
+{
+ int rc = 0;
+ char *name;
+ struct device_node *syscon_np = NULL;
+
+ name = "syscon-cont";
+
+ syscon_np = of_parse_phandle(np, name, 0);
+ if (!syscon_np) {
+ pr_err("can't find phandle %s\n", name);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ hif_cont_block = of_iomap(syscon_np, 0);
+ if (!hif_cont_block) {
+ pr_err("iomap failed for hif_cont_block\n");
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ /* offset is at top of hif_cont_block */
+ hif_cont_reg = 0;
+
+cleanup:
+ if (syscon_np)
+ of_node_put(syscon_np);
+
+ return rc;
+}
+
+static void __init brcmstb_cpu_ctrl_setup(unsigned int max_cpus)
+{
+ int rc;
+ struct device_node *np;
+ char *name;
+
+ name = "brcm,brcmstb-smpboot";
+ np = of_find_compatible_node(NULL, NULL, name);
+ if (!np) {
+ pr_err("can't find compatible node %s\n", name);
+ return;
+ }
+
+ rc = setup_hifcpubiuctrl_regs(np);
+ if (rc)
+ return;
+
+ rc = setup_hifcont_regs(np);
+ if (rc)
+ return;
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static void brcmstb_secondary_init(unsigned int cpu)
+{
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+static int brcmstb_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /* Bring up power to the core if necessary */
+ if (brcmstb_cpu_get_power_state(cpu) == 0)
+ brcmstb_cpu_power_on(cpu);
+
+ brcmstb_cpu_boot(cpu);
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return 0;
+}
+
+static struct smp_operations brcmstb_smp_ops __initdata = {
+ .smp_prepare_cpus = brcmstb_cpu_ctrl_setup,
+ .smp_secondary_init = brcmstb_secondary_init,
+ .smp_boot_secondary = brcmstb_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_kill = brcmstb_cpu_kill,
+ .cpu_die = brcmstb_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(brcmstb_smp, "brcm,brahma-b15", &brcmstb_smp_ops);
diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig
index 2631cfc5ab0d..24f85be71671 100644
--- a/arch/arm/mach-berlin/Kconfig
+++ b/arch/arm/mach-berlin/Kconfig
@@ -13,7 +13,9 @@ config MACH_BERLIN_BG2
bool "Marvell Armada 1500 (BG2)"
select CACHE_L2X0
select CPU_PJ4B
+ select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
+ select HAVE_SMP
select PINCTRL_BERLIN_BG2
config MACH_BERLIN_BG2CD
@@ -25,6 +27,7 @@ config MACH_BERLIN_BG2CD
config MACH_BERLIN_BG2Q
bool "Marvell Armada 1500 Pro (BG2-Q)"
select CACHE_L2X0
+ select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL_BERLIN_BG2Q
diff --git a/arch/arm/mach-berlin/Makefile b/arch/arm/mach-berlin/Makefile
index ab69fe956f49..c0719ecd1890 100644
--- a/arch/arm/mach-berlin/Makefile
+++ b/arch/arm/mach-berlin/Makefile
@@ -1 +1,2 @@
-obj-y += berlin.o
+obj-y += berlin.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-berlin/headsmp.S b/arch/arm/mach-berlin/headsmp.S
new file mode 100644
index 000000000000..4a4c56a58ad3
--- /dev/null
+++ b/arch/arm/mach-berlin/headsmp.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+ENTRY(berlin_secondary_startup)
+ ARM_BE8(setend be)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(berlin_secondary_startup)
+
+/*
+ * If the following instruction is set in the reset exception vector, CPUs
+ * will fetch the value of the software reset address vector when being
+ * reset.
+ */
+.global boot_inst
+boot_inst:
+ ldr pc, [pc, #140]
+
+ .align
diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c
new file mode 100644
index 000000000000..702e7982015a
--- /dev/null
+++ b/arch/arm/mach-berlin/platsmp.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+#define CPU_RESET 0x00
+
+#define RESET_VECT 0x00
+#define SW_RESET_ADDR 0x94
+
+extern void berlin_secondary_startup(void);
+extern u32 boot_inst;
+
+static void __iomem *cpu_ctrl;
+
+static inline void berlin_perform_reset_cpu(unsigned int cpu)
+{
+ u32 val;
+
+ val = readl(cpu_ctrl + CPU_RESET);
+ val |= BIT(cpu_logical_map(cpu));
+ writel(val, cpu_ctrl + CPU_RESET);
+}
+
+static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ if (!cpu_ctrl)
+ return -EFAULT;
+
+ /*
+ * Reset the CPU, making it to execute the instruction in the reset
+ * exception vector.
+ */
+ berlin_perform_reset_cpu(cpu);
+
+ return 0;
+}
+
+static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np;
+ void __iomem *scu_base;
+ void __iomem *vectors_base;
+
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ scu_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!scu_base)
+ return;
+
+ np = of_find_compatible_node(NULL, NULL, "marvell,berlin-cpu-ctrl");
+ cpu_ctrl = of_iomap(np, 0);
+ of_node_put(np);
+ if (!cpu_ctrl)
+ goto unmap_scu;
+
+ vectors_base = ioremap(CONFIG_VECTORS_BASE, SZ_32K);
+ if (!vectors_base)
+ goto unmap_scu;
+
+ scu_enable(scu_base);
+ flush_cache_all();
+
+ /*
+ * Write the first instruction the CPU will execute after being reset
+ * in the reset exception vector.
+ */
+ writel(boot_inst, vectors_base + RESET_VECT);
+
+ /*
+ * Write the secondary startup address into the SW reset address
+ * vector. This is used by boot_inst.
+ */
+ writel(virt_to_phys(berlin_secondary_startup), vectors_base + SW_RESET_ADDR);
+
+ iounmap(vectors_base);
+unmap_scu:
+ iounmap(scu_base);
+}
+
+static struct smp_operations berlin_smp_ops __initdata = {
+ .smp_prepare_cpus = berlin_smp_prepare_cpus,
+ .smp_boot_secondary = berlin_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);
diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c
index d62ca16d5394..45abf6bd5f68 100644
--- a/arch/arm/mach-clps711x/board-autcpu12.c
+++ b/arch/arm/mach-clps711x/board-autcpu12.c
@@ -266,7 +266,6 @@ MACHINE_START(AUTCPU12, "autronix autcpu12")
/* Maintainer: Thomas Gleixner */
.atag_offset = 0x20000,
.map_io = clps711x_map_io,
- .init_early = clps711x_init_early,
.init_irq = clps711x_init_irq,
.init_time = clps711x_timer_init,
.init_machine = autcpu12_init,
diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c
index e261a47f2aff..1ec378c334e5 100644
--- a/arch/arm/mach-clps711x/board-cdb89712.c
+++ b/arch/arm/mach-clps711x/board-cdb89712.c
@@ -140,7 +140,6 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712")
/* Maintainer: Ray Lehtiniemi */
.atag_offset = 0x100,
.map_io = clps711x_map_io,
- .init_early = clps711x_init_early,
.init_irq = clps711x_init_irq,
.init_time = clps711x_timer_init,
.init_machine = cdb89712_init,
diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c
index 94a7add88a3f..f9ca22b646bf 100644
--- a/arch/arm/mach-clps711x/board-clep7312.c
+++ b/arch/arm/mach-clps711x/board-clep7312.c
@@ -25,6 +25,7 @@
#include <asm/mach/arch.h>
#include "common.h"
+#include "devices.h"
static void __init
fixup_clep7312(struct tag *tags, char **cmdline)
@@ -37,8 +38,8 @@ MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
.atag_offset = 0x0100,
.fixup = fixup_clep7312,
.map_io = clps711x_map_io,
- .init_early = clps711x_init_early,
.init_irq = clps711x_init_irq,
.init_time = clps711x_timer_init,
+ .init_machine = clps711x_devices_init,
.restart = clps711x_restart,
MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c
index f9828f89972a..fdf54d40909a 100644
--- a/arch/arm/mach-clps711x/board-edb7211.c
+++ b/arch/arm/mach-clps711x/board-edb7211.c
@@ -148,26 +148,21 @@ fixup_edb7211(struct tag *tags, char **cmdline)
memblock_add(0xc1000000, SZ_8M);
}
-static void __init edb7211_init(void)
-{
- clps711x_devices_init();
-}
-
static void __init edb7211_init_late(void)
{
gpio_request_array(edb7211_gpios, ARRAY_SIZE(edb7211_gpios));
platform_device_register(&edb7211_flash_pdev);
- platform_device_register_data(&platform_bus, "platform-lcd", 0,
+ platform_device_register_data(NULL, "platform-lcd", 0,
&edb7211_lcd_power_pdata,
sizeof(edb7211_lcd_power_pdata));
- platform_device_register_data(&platform_bus, "generic-bl", 0,
+ platform_device_register_data(NULL, "generic-bl", 0,
&edb7211_lcd_backlight_pdata,
sizeof(edb7211_lcd_backlight_pdata));
platform_device_register_simple("video-clps711x", 0, NULL, 0);
platform_device_register_simple("cs89x0", 0, edb7211_cs8900_resource,
ARRAY_SIZE(edb7211_cs8900_resource));
- platform_device_register_data(&platform_bus, "i2c-gpio", 0,
+ platform_device_register_data(NULL, "i2c-gpio", 0,
&edb7211_i2c_pdata,
sizeof(edb7211_i2c_pdata));
}
@@ -178,10 +173,9 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
.fixup = fixup_edb7211,
.reserve = edb7211_reserve,
.map_io = clps711x_map_io,
- .init_early = clps711x_init_early,
.init_irq = clps711x_init_irq,
.init_time = clps711x_timer_init,
- .init_machine = edb7211_init,
+ .init_machine = clps711x_devices_init,
.init_late = edb7211_init_late,
.restart = clps711x_restart,
MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c
index 0cf0e51e6546..e68dd629bda2 100644
--- a/arch/arm/mach-clps711x/board-p720t.c
+++ b/arch/arm/mach-clps711x/board-p720t.c
@@ -348,14 +348,14 @@ static void __init p720t_init_late(void)
{
WARN_ON(gpio_request_array(p720t_gpios, ARRAY_SIZE(p720t_gpios)));
- platform_device_register_data(&platform_bus, "platform-lcd", 0,
+ platform_device_register_data(NULL, "platform-lcd", 0,
&p720t_lcd_power_pdata,
sizeof(p720t_lcd_power_pdata));
- platform_device_register_data(&platform_bus, "generic-bl", 0,
+ platform_device_register_data(NULL, "generic-bl", 0,
&p720t_lcd_backlight_pdata,
sizeof(p720t_lcd_backlight_pdata));
platform_device_register_simple("video-clps711x", 0, NULL, 0);
- platform_device_register_data(&platform_bus, "leds-gpio", 0,
+ platform_device_register_data(NULL, "leds-gpio", 0,
&p720t_gpio_led_pdata,
sizeof(p720t_gpio_led_pdata));
}
@@ -365,7 +365,6 @@ MACHINE_START(P720T, "ARM-Prospector720T")
.atag_offset = 0x100,
.fixup = fixup_p720t,
.map_io = clps711x_map_io,
- .init_early = clps711x_init_early,
.init_irq = clps711x_init_irq,
.init_time = clps711x_timer_init,
.init_machine = p720t_init,
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index aee81fa46ccf..2a6323b15782 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -193,15 +193,3 @@ void clps711x_restart(enum reboot_mode mode, const char *cmd)
{
soft_restart(0);
}
-
-static void clps711x_idle(void)
-{
- clps_writel(1, HALT);
- asm("mov r0, r0");
- asm("mov r0, r0");
-}
-
-void __init clps711x_init_early(void)
-{
- arm_pm_idle = clps711x_idle;
-}
diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h
index 7489139d5d63..f88189963898 100644
--- a/arch/arm/mach-clps711x/common.h
+++ b/arch/arm/mach-clps711x/common.h
@@ -13,7 +13,6 @@ extern void clps711x_map_io(void);
extern void clps711x_init_irq(void);
extern void clps711x_timer_init(void);
extern void clps711x_restart(enum reboot_mode mode, const char *cmd);
-extern void clps711x_init_early(void);
/* drivers/irqchip/irq-clps711x.c */
void clps711x_intc_init(phys_addr_t, resource_size_t);
diff --git a/arch/arm/mach-clps711x/devices.c b/arch/arm/mach-clps711x/devices.c
index 2001488a5ef2..0c689d3a6710 100644
--- a/arch/arm/mach-clps711x/devices.c
+++ b/arch/arm/mach-clps711x/devices.c
@@ -14,6 +14,15 @@
#include <mach/hardware.h>
+static const struct resource clps711x_cpuidle_res __initconst =
+ DEFINE_RES_MEM(CLPS711X_PHYS_BASE + HALT, SZ_128);
+
+static void __init clps711x_add_cpuidle(void)
+{
+ platform_device_register_simple("clps711x-cpuidle", PLATFORM_DEVID_NONE,
+ &clps711x_cpuidle_res, 1);
+}
+
static const phys_addr_t clps711x_gpios[][2] __initconst = {
{ PADR, PADDR },
{ PBDR, PBDDR },
@@ -83,6 +92,7 @@ static void __init clps711x_add_uart(void)
void __init clps711x_devices_init(void)
{
+ clps711x_add_cpuidle();
clps711x_add_gpio();
clps711x_add_syscon();
clps711x_add_uart();
diff --git a/arch/arm/mach-clps711x/include/mach/debug-macro.S b/arch/arm/mach-clps711x/include/mach/debug-macro.S
deleted file mode 100644
index cb3684f8dae0..000000000000
--- a/arch/arm/mach-clps711x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,38 +0,0 @@
-/* arch/arm/mach-clps711x/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <mach/hardware.h>
-
- .macro addruart, rp, rv, tmp
-#ifndef CONFIG_DEBUG_CLPS711X_UART2
- mov \rp, #0x0000 @ UART1
-#else
- mov \rp, #0x1000 @ UART2
-#endif
- orr \rv, \rp, #CLPS711X_VIRT_BASE
- orr \rp, \rp, #CLPS711X_PHYS_BASE
- .endm
-
- .macro senduart,rd,rx
- str \rd, [\rx, #0x0480] @ UARTDR
- .endm
-
- .macro waituart,rd,rx
- .endm
-
- .macro busyuart,rd,rx
-1001: ldr \rd, [\rx, #0x0140] @ SYSFLGx
- tst \rd, #1 << 11 @ UBUSYx
- bne 1001b
- .endm
-
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index 5d6afda1c0e8..833129c9f798 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -24,10 +24,7 @@
#include <mach/clps711x.h>
-#define IO_ADDRESS(x) (0xdc000000 + (((x) & 0x03ffffff) | \
- (((x) >> 2) & 0x3c000000)))
-
-#define CLPS711X_VIRT_BASE IOMEM(IO_ADDRESS(CLPS711X_PHYS_BASE))
+#define CLPS711X_VIRT_BASE IOMEM(0xfeff0000)
#ifndef __ASSEMBLY__
#define clps_readb(off) readb(CLPS711X_VIRT_BASE + (off))
diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S
index d4e9316ecacb..a5336a5e2739 100644
--- a/arch/arm/mach-davinci/sleep.S
+++ b/arch/arm/mach-davinci/sleep.S
@@ -213,7 +213,7 @@ ddr2clk_stop_done:
cmp ip, r0
bne ddr2clk_stop_done
- mov pc, lr
+ ret lr
ENDPROC(davinci_ddr_psc_config)
CACHE_FLUSH:
diff --git a/arch/arm/mach-ebsa110/include/mach/memory.h b/arch/arm/mach-ebsa110/include/mach/memory.h
index 8e49066ad850..866f8a1c6ff7 100644
--- a/arch/arm/mach-ebsa110/include/mach/memory.h
+++ b/arch/arm/mach-ebsa110/include/mach/memory.h
@@ -17,11 +17,6 @@
#define __ASM_ARCH_MEMORY_H
/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-/*
* Cache flushing area - SRAM
*/
#define FLUSH_BASE_PHYS 0x40000000
diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S
index e96923a3017b..ee0be2af5c61 100644
--- a/arch/arm/mach-ep93xx/crunch-bits.S
+++ b/arch/arm/mach-ep93xx/crunch-bits.S
@@ -198,7 +198,7 @@ crunch_load:
get_thread_info r10
#endif
2: dec_preempt_count r10, r3
- mov pc, lr
+ ret lr
/*
* Back up crunch regs to save area and disable access to them
@@ -277,7 +277,7 @@ ENTRY(crunch_task_copy)
mov r3, lr @ preserve return address
bl crunch_save
msr cpsr_c, ip @ restore interrupt mode
- mov pc, r3
+ ret r3
/*
* Restore crunch state from given memory address
@@ -310,4 +310,4 @@ ENTRY(crunch_task_restore)
mov r3, lr @ preserve return address
bl crunch_load
msr cpsr_c, ip @ restore interrupt mode
- mov pc, r3
+ ret r3
diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
deleted file mode 100644
index c9400cf0051c..000000000000
--- a/arch/arm/mach-ep93xx/include/mach/memory.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/memory.h
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-#elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET UL(0xc0000000)
-#elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET UL(0xd0000000)
-#elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET UL(0xe0000000)
-#elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
-#define PLAT_PHYS_OFFSET UL(0xf0000000)
-#else
-#error "Kconfig bug: No EP93xx PHYS_OFFSET set"
-#endif
-
-#endif
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 8f9b66c4ac78..2d0240f241b8 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -100,7 +100,6 @@ config SOC_EXYNOS5440
default y
depends on ARCH_EXYNOS5
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
- select ARCH_HAS_OPP
select HAVE_ARM_ARCH_TIMER
select AUTO_ZRELADDR
select MIGHT_HAVE_PCI
@@ -119,6 +118,7 @@ config EXYNOS5420_MCPM
bool "Exynos5420 Multi-Cluster PM support"
depends on MCPM && SOC_EXYNOS5420
select ARM_CCI
+ select ARM_CPU_SUSPEND
help
This is needed to provide CPU and cluster power management
on Exynos5420 implementing big.LITTLE.
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 1ee91763fa7c..47b904b3b973 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -111,25 +111,14 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
soc_is_exynos5420() || soc_is_exynos5800())
-void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
-
-struct map_desc;
extern void __iomem *sysram_ns_base_addr;
extern void __iomem *sysram_base_addr;
-void exynos_init_io(void);
-void exynos_restart(enum reboot_mode mode, const char *cmd);
+extern void __iomem *pmu_base_addr;
void exynos_sysram_init(void);
-void exynos_cpuidle_init(void);
-void exynos_cpufreq_init(void);
-void exynos_init_late(void);
void exynos_firmware_init(void);
-#ifdef CONFIG_PINCTRL_EXYNOS
extern u32 exynos_get_eint_wake_mask(void);
-#else
-static inline u32 exynos_get_eint_wake_mask(void) { return 0xffffffff; }
-#endif
#ifdef CONFIG_PM_SLEEP
extern void __init exynos_pm_init(void);
@@ -145,7 +134,7 @@ extern void exynos_cpu_die(unsigned int cpu);
/* PMU(Power Management Unit) support */
-#define PMU_TABLE_END NULL
+#define PMU_TABLE_END (-1U)
enum sys_powerdown {
SYS_AFTR,
@@ -155,7 +144,7 @@ enum sys_powerdown {
};
struct exynos_pmu_conf {
- void __iomem *reg;
+ unsigned int offset;
unsigned int val[NUM_SYS_POWERDOWN];
};
@@ -171,4 +160,14 @@ extern void exynos_enter_aftr(void);
extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void);
+static inline void pmu_raw_writel(u32 val, u32 offset)
+{
+ __raw_writel(val, pmu_base_addr + offset);
+}
+
+static inline u32 pmu_raw_readl(u32 offset)
+{
+ return __raw_readl(pmu_base_addr + offset);
+}
+
#endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 66c9b9614f3c..6a24e111d6e1 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -19,6 +19,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
+#include <linux/irqchip.h>
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
@@ -29,6 +30,9 @@
#include "common.h"
#include "mfc.h"
#include "regs-pmu.h"
+#include "regs-sys.h"
+
+void __iomem *pmu_base_addr;
static struct map_desc exynos4_iodesc[] __initdata = {
{
@@ -57,11 +61,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (unsigned long)S5P_VA_PMU,
- .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
- .length = SZ_64K,
- .type = MT_DEVICE,
- }, {
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
.pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
.length = SZ_4K,
@@ -135,19 +134,14 @@ static struct map_desc exynos5_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
.length = 144 * SZ_1K,
.type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_PMU,
- .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
- .length = SZ_64K,
- .type = MT_DEVICE,
},
};
-void exynos_restart(enum reboot_mode mode, const char *cmd)
+static void exynos_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
u32 val = 0x1;
- void __iomem *addr = EXYNOS_SWRESET;
+ void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
if (of_machine_is_compatible("samsung,exynos5440")) {
u32 status;
@@ -171,17 +165,6 @@ static struct platform_device exynos_cpuidle = {
.id = -1,
};
-void __init exynos_cpuidle_init(void)
-{
- if (soc_is_exynos4210() || soc_is_exynos5250())
- platform_device_register(&exynos_cpuidle);
-}
-
-void __init exynos_cpufreq_init(void)
-{
- platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-}
-
void __iomem *sysram_base_addr;
void __iomem *sysram_ns_base_addr;
@@ -204,7 +187,7 @@ void __init exynos_sysram_init(void)
}
}
-void __init exynos_init_late(void)
+static void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
/* to be supported later */
@@ -251,7 +234,7 @@ static void __init exynos_map_io(void)
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
}
-void __init exynos_init_io(void)
+static void __init exynos_init_io(void)
{
debug_ll_io_init();
@@ -263,6 +246,41 @@ void __init exynos_init_io(void)
exynos_map_io();
}
+static const struct of_device_id exynos_dt_pmu_match[] = {
+ { .compatible = "samsung,exynos3250-pmu" },
+ { .compatible = "samsung,exynos4210-pmu" },
+ { .compatible = "samsung,exynos4212-pmu" },
+ { .compatible = "samsung,exynos4412-pmu" },
+ { .compatible = "samsung,exynos5250-pmu" },
+ { .compatible = "samsung,exynos5260-pmu" },
+ { .compatible = "samsung,exynos5410-pmu" },
+ { .compatible = "samsung,exynos5420-pmu" },
+ { /*sentinel*/ },
+};
+
+static void exynos_map_pmu(void)
+{
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, exynos_dt_pmu_match);
+ if (np)
+ pmu_base_addr = of_iomap(np, 0);
+
+ if (!pmu_base_addr)
+ panic("failed to find exynos pmu register\n");
+}
+
+static void __init exynos_init_irq(void)
+{
+ irqchip_init();
+ /*
+ * Since platsmp.c needs pmu base address by the time
+ * DT is not unflatten so we can't use DT APIs before
+ * init_irq
+ */
+ exynos_map_pmu();
+}
+
static void __init exynos_dt_machine_init(void)
{
struct device_node *i2c_np;
@@ -298,8 +316,11 @@ static void __init exynos_dt_machine_init(void)
if (!IS_ENABLED(CONFIG_SMP))
exynos_sysram_init();
- exynos_cpuidle_init();
- exynos_cpufreq_init();
+ if (of_machine_is_compatible("samsung,exynos4210") ||
+ of_machine_is_compatible("samsung,exynos5250"))
+ platform_device_register(&exynos_cpuidle);
+
+ platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
@@ -352,6 +373,7 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
.smp = smp_ops(exynos_smp_ops),
.map_io = exynos_init_io,
.init_early = exynos_firmware_init,
+ .init_irq = exynos_init_irq,
.init_machine = exynos_dt_machine_init,
.init_late = exynos_init_late,
.dt_compat = exynos_dt_compat,
diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S
index cdd9d91e9933..b54f9701e421 100644
--- a/arch/arm/mach-exynos/headsmp.S
+++ b/arch/arm/mach-exynos/headsmp.S
@@ -1,5 +1,4 @@
/*
- * linux/arch/arm/mach-exynos4/headsmp.S
*
* Cloned from linux/arch/arm/mach-realview/headsmp.S
*
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index 920a4baa53cd..4d86961a7957 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -1,5 +1,4 @@
-/* linux arch/arm/mach-exynos4/hotplug.c
- *
+/*
* Cloned from linux/arch/arm/mach-realview/hotplug.c
*
* Copyright (C) 2002 ARM Ltd.
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 548269a60634..f0b7e92bad6c 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos/include/mach/map.h
- *
+/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
@@ -28,9 +27,6 @@
#define EXYNOS4_PA_SYSCON 0x10010000
#define EXYNOS5_PA_SYSCON 0x10050100
-#define EXYNOS4_PA_PMU 0x10020000
-#define EXYNOS5_PA_PMU 0x10040000
-
#define EXYNOS4_PA_CMU 0x10030000
#define EXYNOS5_PA_CMU 0x10010000
diff --git a/arch/arm/mach-exynos/include/mach/memory.h b/arch/arm/mach-exynos/include/mach/memory.h
index 2a4cdb7cb326..e19df1f18c0d 100644
--- a/arch/arm/mach-exynos/include/mach/memory.h
+++ b/arch/arm/mach-exynos/include/mach/memory.h
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/include/mach/memory.h
- *
+/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
diff --git a/arch/arm/mach-exynos/mcpm-exynos.c b/arch/arm/mach-exynos/mcpm-exynos.c
index ace0ed617476..b2f8b60cf0e9 100644
--- a/arch/arm/mach-exynos/mcpm-exynos.c
+++ b/arch/arm/mach-exynos/mcpm-exynos.c
@@ -26,6 +26,10 @@
#define EXYNOS5420_CPUS_PER_CLUSTER 4
#define EXYNOS5420_NR_CLUSTERS 2
+#define EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN BIT(9)
+#define EXYNOS5420_USE_ARM_CORE_DOWN_STATE BIT(29)
+#define EXYNOS5420_USE_L2_COMMON_UP_STATE BIT(30)
+
/*
* The common v7_exit_coherency_flush API could not be used because of the
* Erratum 799270 workaround. This macro is the same as the common one (in
@@ -51,7 +55,7 @@
"dsb\n\t" \
"ldmfd sp!, {fp, ip}" \
: \
- : "Ir" (S5P_INFORM0) \
+ : "Ir" (pmu_base_addr + S5P_INFORM0) \
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r9", "r10", "lr", "memory")
@@ -73,36 +77,9 @@ cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];
#define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster)
-static int exynos_cluster_power_control(unsigned int cluster, int enable)
-{
- unsigned int tries = 100;
- unsigned int val;
-
- if (enable) {
- exynos_cluster_power_up(cluster);
- val = S5P_CORE_LOCAL_PWR_EN;
- } else {
- exynos_cluster_power_down(cluster);
- val = 0;
- }
-
- /* Wait until cluster power control is applied */
- while (tries--) {
- if (exynos_cluster_power_state(cluster) == val)
- return 0;
-
- cpu_relax();
- }
- pr_debug("timed out waiting for cluster %u to power %s\n", cluster,
- enable ? "on" : "off");
-
- return -ETIMEDOUT;
-}
-
static int exynos_power_up(unsigned int cpu, unsigned int cluster)
{
unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
- int err = 0;
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
@@ -126,12 +103,9 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)
* cores.
*/
if (was_cluster_down)
- err = exynos_cluster_power_control(cluster, 1);
+ exynos_cluster_power_up(cluster);
- if (!err)
- exynos_cpu_power_up(cpunr);
- else
- exynos_cluster_power_control(cluster, 0);
+ exynos_cpu_power_up(cpunr);
} else if (cpu_use_count[cpu][cluster] != 2) {
/*
* The only possible values are:
@@ -147,7 +121,7 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)
arch_spin_unlock(&exynos_mcpm_lock);
local_irq_enable();
- return err;
+ return 0;
}
/*
@@ -178,9 +152,10 @@ static void exynos_power_down(void)
if (cpu_use_count[cpu][cluster] == 0) {
exynos_cpu_power_down(cpunr);
- if (exynos_cluster_unused(cluster))
- /* TODO: Turn off the cluster here to save power. */
+ if (exynos_cluster_unused(cluster)) {
+ exynos_cluster_power_down(cluster);
last_man = true;
+ }
} else if (cpu_use_count[cpu][cluster] == 1) {
/*
* A power_up request went ahead of us.
@@ -196,7 +171,7 @@ static void exynos_power_down(void)
if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
arch_spin_unlock(&exynos_mcpm_lock);
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
/*
* On the Cortex-A15 we need to disable
* L2 prefetching before flushing the cache.
@@ -257,10 +232,46 @@ static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
return -ETIMEDOUT; /* timeout */
}
+static void exynos_powered_up(void)
+{
+ unsigned int mpidr, cpu, cluster;
+
+ mpidr = read_cpuid_mpidr();
+ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+
+ arch_spin_lock(&exynos_mcpm_lock);
+ if (cpu_use_count[cpu][cluster] == 0)
+ cpu_use_count[cpu][cluster] = 1;
+ arch_spin_unlock(&exynos_mcpm_lock);
+}
+
+static void exynos_suspend(u64 residency)
+{
+ unsigned int mpidr, cpunr;
+
+ exynos_power_down();
+
+ /*
+ * Execution reaches here only if cpu did not power down.
+ * Hence roll back the changes done in exynos_power_down function.
+ *
+ * CAUTION: "This function requires the stack data to be visible through
+ * power down and can only be executed on processors like A15 and A7
+ * that hit the cache with the C bit clear in the SCTLR register."
+ */
+ mpidr = read_cpuid_mpidr();
+ cpunr = exynos_pmu_cpunr(mpidr);
+
+ exynos_cpu_power_up(cpunr);
+}
+
static const struct mcpm_platform_ops exynos_power_ops = {
.power_up = exynos_power_up,
.power_down = exynos_power_down,
.wait_for_powerdown = exynos_wait_for_powerdown,
+ .suspend = exynos_suspend,
+ .powered_up = exynos_powered_up,
};
static void __init exynos_mcpm_usage_count_init(void)
@@ -289,6 +300,19 @@ static void __naked exynos_pm_power_up_setup(unsigned int affinity_level)
"b cci_enable_port_for_self");
}
+static void __init exynos_cache_off(void)
+{
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+ /* disable L2 prefetching on the Cortex-A15 */
+ asm volatile(
+ "mcr p15, 1, %0, c15, c0, 3\n\t"
+ "isb\n\t"
+ "dsb"
+ : : "r" (0x400));
+ }
+ exynos_v7_exit_coherency_flush(all);
+}
+
static const struct of_device_id exynos_dt_mcpm_match[] = {
{ .compatible = "samsung,exynos5420" },
{ .compatible = "samsung,exynos5800" },
@@ -299,6 +323,7 @@ static int __init exynos_mcpm_init(void)
{
struct device_node *node;
void __iomem *ns_sram_base_addr;
+ unsigned int value, i;
int ret;
node = of_find_matching_node(NULL, exynos_dt_mcpm_match);
@@ -325,13 +350,15 @@ static int __init exynos_mcpm_init(void)
* To increase the stability of KFC reset we need to program
* the PMU SPARE3 register
*/
- __raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
+ pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
exynos_mcpm_usage_count_init();
ret = mcpm_platform_register(&exynos_power_ops);
if (!ret)
ret = mcpm_sync_init(exynos_pm_power_up_setup);
+ if (!ret)
+ ret = mcpm_loopback(exynos_cache_off); /* turn on the CCI */
if (ret) {
iounmap(ns_sram_base_addr);
return ret;
@@ -342,6 +369,26 @@ static int __init exynos_mcpm_init(void)
pr_info("Exynos MCPM support installed\n");
/*
+ * On Exynos5420/5800 for the A15 and A7 clusters:
+ *
+ * EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN ensures that all the cores
+ * in a cluster are turned off before turning off the cluster L2.
+ *
+ * EXYNOS5420_USE_ARM_CORE_DOWN_STATE ensures that a cores is powered
+ * off before waking it up.
+ *
+ * EXYNOS5420_USE_L2_COMMON_UP_STATE ensures that cluster L2 will be
+ * turned on before the first man is powered up.
+ */
+ for (i = 0; i < EXYNOS5420_NR_CLUSTERS; i++) {
+ value = pmu_raw_readl(EXYNOS_COMMON_OPTION(i));
+ value |= EXYNOS5420_ENABLE_AUTOMATIC_CORE_DOWN |
+ EXYNOS5420_USE_ARM_CORE_DOWN_STATE |
+ EXYNOS5420_USE_L2_COMMON_UP_STATE;
+ pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
+ }
+
+ /*
* U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
* as part of secondary_cpu_start(). Let's redirect it to the
* mcpm_entry_point().
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 50b9aad5e27b..a9f1cf759949 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -1,5 +1,4 @@
-/* linux/arch/arm/mach-exynos4/platsmp.c
- *
+ /*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
@@ -27,15 +26,83 @@
#include <asm/smp_scu.h>
#include <asm/firmware.h>
+#include <mach/map.h>
+
#include "common.h"
#include "regs-pmu.h"
extern void exynos4_secondary_startup(void);
+/**
+ * exynos_core_power_down : power down the specified cpu
+ * @cpu : the cpu to power down
+ *
+ * Power down the specified cpu. The sequence must be finished by a
+ * call to cpu_do_idle()
+ *
+ */
+void exynos_cpu_power_down(int cpu)
+{
+ pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+}
+
+/**
+ * exynos_cpu_power_up : power up the specified cpu
+ * @cpu : the cpu to power up
+ *
+ * Power up the specified cpu
+ */
+void exynos_cpu_power_up(int cpu)
+{
+ pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+ EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+}
+
+/**
+ * exynos_cpu_power_state : returns the power state of the cpu
+ * @cpu : the cpu to retrieve the power state from
+ *
+ */
+int exynos_cpu_power_state(int cpu)
+{
+ return (pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
+ S5P_CORE_LOCAL_PWR_EN);
+}
+
+/**
+ * exynos_cluster_power_down : power down the specified cluster
+ * @cluster : the cluster to power down
+ */
+void exynos_cluster_power_down(int cluster)
+{
+ pmu_raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
+}
+
+/**
+ * exynos_cluster_power_up : power up the specified cluster
+ * @cluster : the cluster to power up
+ */
+void exynos_cluster_power_up(int cluster)
+{
+ pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+ EXYNOS_COMMON_CONFIGURATION(cluster));
+}
+
+/**
+ * exynos_cluster_power_state : returns the power state of the cluster
+ * @cluster : the cluster to retrieve the power state from
+ *
+ */
+int exynos_cluster_power_state(int cluster)
+{
+ return (pmu_raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
+ S5P_CORE_LOCAL_PWR_EN);
+}
+
static inline void __iomem *cpu_boot_reg_base(void)
{
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
- return S5P_INFORM5;
+ return pmu_base_addr + S5P_INFORM5;
return sysram_base_addr;
}
@@ -190,7 +257,7 @@ static void __init exynos_smp_init_cpus(void)
void __iomem *scu_base = scu_base_addr();
unsigned int i, ncores;
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
else
/*
@@ -216,7 +283,7 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
exynos_sysram_init();
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
scu_enable(scu_base_addr());
/*
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 202ca73e49c4..abefacb45976 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -28,13 +28,13 @@
#include <asm/suspend.h>
#include <plat/pm-common.h>
-#include <plat/pll.h>
#include <plat/regs-srom.h>
#include <mach/map.h>
#include "common.h"
#include "regs-pmu.h"
+#include "regs-sys.h"
/**
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
@@ -100,102 +100,20 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
return -ENOENT;
}
-/**
- * exynos_core_power_down : power down the specified cpu
- * @cpu : the cpu to power down
- *
- * Power down the specified cpu. The sequence must be finished by a
- * call to cpu_do_idle()
- *
- */
-void exynos_cpu_power_down(int cpu)
-{
- __raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
-}
-
-/**
- * exynos_cpu_power_up : power up the specified cpu
- * @cpu : the cpu to power up
- *
- * Power up the specified cpu
- */
-void exynos_cpu_power_up(int cpu)
-{
- __raw_writel(S5P_CORE_LOCAL_PWR_EN,
- EXYNOS_ARM_CORE_CONFIGURATION(cpu));
-}
-
-/**
- * exynos_cpu_power_state : returns the power state of the cpu
- * @cpu : the cpu to retrieve the power state from
- *
- */
-int exynos_cpu_power_state(int cpu)
-{
- return (__raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
- S5P_CORE_LOCAL_PWR_EN);
-}
-
-/**
- * exynos_cluster_power_down : power down the specified cluster
- * @cluster : the cluster to power down
- */
-void exynos_cluster_power_down(int cluster)
-{
- __raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
-}
-
-/**
- * exynos_cluster_power_up : power up the specified cluster
- * @cluster : the cluster to power up
- */
-void exynos_cluster_power_up(int cluster)
-{
- __raw_writel(S5P_CORE_LOCAL_PWR_EN,
- EXYNOS_COMMON_CONFIGURATION(cluster));
-}
-
-/**
- * exynos_cluster_power_state : returns the power state of the cluster
- * @cluster : the cluster to retrieve the power state from
- *
- */
-int exynos_cluster_power_state(int cluster)
-{
- return (__raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
- S5P_CORE_LOCAL_PWR_EN);
-}
-
#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
- S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
- (sysram_base_addr + 0x24) : S5P_INFORM0))
+ pmu_base_addr + S5P_INFORM7 : \
+ (samsung_rev() == EXYNOS4210_REV_1_0 ? \
+ (sysram_base_addr + 0x24) : \
+ pmu_base_addr + S5P_INFORM0))
#define EXYNOS_BOOT_VECTOR_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
- S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
- (sysram_base_addr + 0x20) : S5P_INFORM1))
+ pmu_base_addr + S5P_INFORM6 : \
+ (samsung_rev() == EXYNOS4210_REV_1_0 ? \
+ (sysram_base_addr + 0x20) : \
+ pmu_base_addr + S5P_INFORM1))
#define S5P_CHECK_AFTR 0xFCBA0D10
#define S5P_CHECK_SLEEP 0x00000BAD
-/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
-static void exynos_set_wakeupmask(long mask)
-{
- __raw_writel(mask, S5P_WAKEUP_MASK);
-}
-
-static void exynos_cpu_set_boot_vector(long flags)
-{
- __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
- __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
-}
-
-void exynos_enter_aftr(void)
-{
- exynos_set_wakeupmask(0x0000ff3e);
- exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
- /* Set value of power down register for aftr mode */
- exynos_sys_powerdown_conf(SYS_AFTR);
-}
-
/* For Cortex-A9 Diagnostic and Power control register */
static unsigned int save_arm_register[2];
@@ -235,6 +153,82 @@ static void exynos_cpu_restore_register(void)
: "cc");
}
+static void exynos_pm_central_suspend(void)
+{
+ unsigned long tmp;
+
+ /* Setting Central Sequence Register for power down mode */
+ tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+ pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+}
+
+static int exynos_pm_central_resume(void)
+{
+ unsigned long tmp;
+
+ /*
+ * If PMU failed while entering sleep mode, WFI will be
+ * ignored by PMU and then exiting cpu_do_idle().
+ * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+ * in this situation.
+ */
+ tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+ tmp |= S5P_CENTRAL_LOWPWR_CFG;
+ pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ /* clear the wakeup state register */
+ pmu_raw_writel(0x0, S5P_WAKEUP_STAT);
+ /* No need to perform below restore code */
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
+static void exynos_set_wakeupmask(long mask)
+{
+ pmu_raw_writel(mask, S5P_WAKEUP_MASK);
+}
+
+static void exynos_cpu_set_boot_vector(long flags)
+{
+ __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
+ __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
+}
+
+static int exynos_aftr_finisher(unsigned long flags)
+{
+ exynos_set_wakeupmask(0x0000ff3e);
+ exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
+ /* Set value of power down register for aftr mode */
+ exynos_sys_powerdown_conf(SYS_AFTR);
+ cpu_do_idle();
+
+ return 1;
+}
+
+void exynos_enter_aftr(void)
+{
+ cpu_pm_enter();
+
+ exynos_pm_central_suspend();
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+ exynos_cpu_save_register();
+
+ cpu_suspend(0, exynos_aftr_finisher);
+
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
+ scu_enable(S5P_VA_SCU);
+ exynos_cpu_restore_register();
+ }
+
+ exynos_pm_central_resume();
+
+ cpu_pm_exit();
+}
+
static int exynos_cpu_suspend(unsigned long arg)
{
#ifdef CONFIG_CACHE_L2X0
@@ -256,37 +250,27 @@ static void exynos_pm_prepare(void)
unsigned int tmp;
/* Set wake-up mask registers */
- __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
- __raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
+ pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+ pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (soc_is_exynos5250()) {
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
- tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
+ tmp = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
- __raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
+ pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
}
/* Set value of power down register for sleep mode */
exynos_sys_powerdown_conf(SYS_SLEEP);
- __raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+ pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
/* ensure at least INFORM0 has the resume address */
- __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
-}
-
-static void exynos_pm_central_suspend(void)
-{
- unsigned long tmp;
-
- /* Setting Central Sequence Register for power down mode */
- tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
- tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
- __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
static int exynos_pm_suspend(void)
@@ -298,54 +282,31 @@ static int exynos_pm_suspend(void)
/* Setting SEQ_OPTION register */
tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
- __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+ pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register();
return 0;
}
-static int exynos_pm_central_resume(void)
-{
- unsigned long tmp;
-
- /*
- * If PMU failed while entering sleep mode, WFI will be
- * ignored by PMU and then exiting cpu_do_idle().
- * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
- * in this situation.
- */
- tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
- if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
- tmp |= S5P_CENTRAL_LOWPWR_CFG;
- __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
- /* clear the wakeup state register */
- __raw_writel(0x0, S5P_WAKEUP_STAT);
- /* No need to perform below restore code */
- return -1;
- }
-
- return 0;
-}
-
static void exynos_pm_resume(void)
{
if (exynos_pm_central_resume())
goto early_wakeup;
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_restore_register();
/* For release retention */
- __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
- __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+ pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
if (soc_is_exynos5250())
s3c_pm_do_restore(exynos5_sys_save,
@@ -353,13 +314,13 @@ static void exynos_pm_resume(void)
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
scu_enable(S5P_VA_SCU);
early_wakeup:
/* Clear SLEEP mode set in INFORM1 */
- __raw_writel(0x0, S5P_INFORM1);
+ pmu_raw_writel(0x0, S5P_INFORM1);
return;
}
@@ -403,7 +364,7 @@ static int exynos_suspend_enter(suspend_state_t state)
s3c_pm_restore_uarts();
S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
- __raw_readl(S5P_WAKEUP_STAT));
+ pmu_raw_readl(S5P_WAKEUP_STAT));
s3c_pm_check_restore();
@@ -431,52 +392,17 @@ static const struct platform_suspend_ops exynos_suspend_ops = {
.valid = suspend_valid_only_mem,
};
-static int exynos_cpu_pm_notifier(struct notifier_block *self,
- unsigned long cmd, void *v)
-{
- int cpu = smp_processor_id();
-
- switch (cmd) {
- case CPU_PM_ENTER:
- if (cpu == 0) {
- exynos_pm_central_suspend();
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
- exynos_cpu_save_register();
- }
- break;
-
- case CPU_PM_EXIT:
- if (cpu == 0) {
- if (read_cpuid_part_number() ==
- ARM_CPU_PART_CORTEX_A9) {
- scu_enable(S5P_VA_SCU);
- exynos_cpu_restore_register();
- }
- exynos_pm_central_resume();
- }
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block exynos_cpu_pm_notifier_block = {
- .notifier_call = exynos_cpu_pm_notifier,
-};
-
void __init exynos_pm_init(void)
{
u32 tmp;
- cpu_pm_register_notifier(&exynos_cpu_pm_notifier_block);
-
/* Platform-specific GIC callback */
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
/* All wakeup disable */
- tmp = __raw_readl(S5P_WAKEUP_MASK);
+ tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
tmp |= ((0xFF << 8) | (0x1F << 1));
- __raw_writel(tmp, S5P_WAKEUP_MASK);
+ pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
register_syscore_ops(&exynos_pm_syscore_ops);
suspend_set_ops(&exynos_suspend_ops);
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 797cb134bfff..fd76e1b5a471 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -23,8 +23,7 @@
#include <linux/of_platform.h>
#include <linux/sched.h>
-#include "regs-pmu.h"
-
+#define INT_LOCAL_PWR_EN 0x7
#define MAX_CLK_PER_DOMAIN 4
/*
@@ -63,13 +62,13 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
}
}
- pwr = power_on ? S5P_INT_LOCAL_PWR_EN : 0;
+ pwr = power_on ? INT_LOCAL_PWR_EN : 0;
__raw_writel(pwr, base);
/* Wait max 1ms */
timeout = 10;
- while ((__raw_readl(base + 0x4) & S5P_INT_LOCAL_PWR_EN) != pwr) {
+ while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
if (!timeout) {
op = (power_on) ? "enable" : "disable";
pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -231,7 +230,7 @@ static __init int exynos4_pm_init_power_domain(void)
no_clk:
platform_set_drvdata(pdev, pd);
- on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN;
+ on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
pm_genpd_init(&pd->pd, NULL, !on);
}
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c
index fb0deda3b3a4..ff9d23f0a7d9 100644
--- a/arch/arm/mach-exynos/pmu.c
+++ b/arch/arm/mach-exynos/pmu.c
@@ -11,7 +11,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/bug.h>
#include "common.h"
#include "regs-pmu.h"
@@ -19,7 +18,7 @@
static const struct exynos_pmu_conf *exynos_pmu_config;
static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
- /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+ /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
{ S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } },
{ S5P_DIS_IRQ_CORE0, { 0x0, 0x0, 0x0 } },
{ S5P_DIS_IRQ_CENTRAL0, { 0x0, 0x0, 0x0 } },
@@ -213,7 +212,7 @@ static const struct exynos_pmu_conf exynos4412_pmu_config[] = {
};
static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
- /* { .reg = address, .val = { AFTR, LPA, SLEEP } */
+ /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
{ EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
{ EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
@@ -316,7 +315,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
{ PMU_TABLE_END,},
};
-static void __iomem * const exynos5_list_both_cnt_feed[] = {
+static unsigned int const exynos5_list_both_cnt_feed[] = {
EXYNOS5_ARM_CORE0_OPTION,
EXYNOS5_ARM_CORE1_OPTION,
EXYNOS5_ARM_COMMON_OPTION,
@@ -330,7 +329,7 @@ static void __iomem * const exynos5_list_both_cnt_feed[] = {
EXYNOS5_TOP_PWR_SYSMEM_OPTION,
};
-static void __iomem * const exynos5_list_diable_wfi_wfe[] = {
+static unsigned int const exynos5_list_diable_wfi_wfe[] = {
EXYNOS5_ARM_CORE1_OPTION,
EXYNOS5_FSYS_ARM_OPTION,
EXYNOS5_ISP_ARM_OPTION,
@@ -345,27 +344,27 @@ static void exynos5_init_pmu(void)
* Enable both SC_FEEDBACK and SC_COUNTER
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
- tmp = __raw_readl(exynos5_list_both_cnt_feed[i]);
+ tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
tmp |= (EXYNOS5_USE_SC_FEEDBACK |
EXYNOS5_USE_SC_COUNTER);
- __raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
+ pmu_raw_writel(tmp, exynos5_list_both_cnt_feed[i]);
}
/*
* SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable
*/
- tmp = __raw_readl(EXYNOS5_ARM_COMMON_OPTION);
+ tmp = pmu_raw_readl(EXYNOS5_ARM_COMMON_OPTION);
tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
- __raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
+ pmu_raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION);
/*
* Disable WFI/WFE on XXX_OPTION
*/
for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
- tmp = __raw_readl(exynos5_list_diable_wfi_wfe[i]);
+ tmp = pmu_raw_readl(exynos5_list_diable_wfi_wfe[i]);
tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
EXYNOS5_OPTION_USE_STANDBYWFI);
- __raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
+ pmu_raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
}
}
@@ -376,14 +375,14 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
if (soc_is_exynos5250())
exynos5_init_pmu();
- for (i = 0; (exynos_pmu_config[i].reg != PMU_TABLE_END) ; i++)
- __raw_writel(exynos_pmu_config[i].val[mode],
- exynos_pmu_config[i].reg);
+ for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
+ pmu_raw_writel(exynos_pmu_config[i].val[mode],
+ exynos_pmu_config[i].offset);
if (soc_is_exynos4412()) {
- for (i = 0; exynos4412_pmu_config[i].reg != PMU_TABLE_END ; i++)
- __raw_writel(exynos4412_pmu_config[i].val[mode],
- exynos4412_pmu_config[i].reg);
+ for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++)
+ pmu_raw_writel(exynos4412_pmu_config[i].val[mode],
+ exynos4412_pmu_config[i].offset);
}
}
@@ -404,13 +403,13 @@ static int __init exynos_pmu_init(void)
* When SYS_WDTRESET is set, watchdog timer reset request
* is ignored by power management unit.
*/
- value = __raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+ value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
value &= ~EXYNOS5_SYS_WDTRESET;
- __raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+ pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
- value = __raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+ value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
value &= ~EXYNOS5_SYS_WDTRESET;
- __raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+ pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
exynos_pmu_config = exynos5250_pmu_config;
pr_info("EXYNOS5250 PMU Initialize\n");
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h
index 1d13b08708f0..96a1569262b5 100644
--- a/arch/arm/mach-exynos/regs-pmu.h
+++ b/arch/arm/mach-exynos/regs-pmu.h
@@ -12,304 +12,298 @@
#ifndef __ASM_ARCH_REGS_PMU_H
#define __ASM_ARCH_REGS_PMU_H __FILE__
-#include <mach/map.h>
-
-#define S5P_PMUREG(x) (S5P_VA_PMU + (x))
-#define S5P_SYSREG(x) (S3C_VA_SYS + (x))
-
-#define S5P_CENTRAL_SEQ_CONFIGURATION S5P_PMUREG(0x0200)
+#define S5P_CENTRAL_SEQ_CONFIGURATION 0x0200
#define S5P_CENTRAL_LOWPWR_CFG (1 << 16)
-#define S5P_CENTRAL_SEQ_OPTION S5P_PMUREG(0x0208)
+#define S5P_CENTRAL_SEQ_OPTION 0x0208
#define S5P_USE_STANDBY_WFI0 (1 << 16)
#define S5P_USE_STANDBY_WFE0 (1 << 24)
-#define EXYNOS_SWRESET S5P_PMUREG(0x0400)
-#define EXYNOS5440_SWRESET S5P_PMUREG(0x00C4)
+#define EXYNOS_SWRESET 0x0400
+#define EXYNOS5440_SWRESET 0x00C4
-#define S5P_WAKEUP_STAT S5P_PMUREG(0x0600)
-#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
-#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
+#define S5P_WAKEUP_STAT 0x0600
+#define S5P_EINT_WAKEUP_MASK 0x0604
+#define S5P_WAKEUP_MASK 0x0608
-#define S5P_INFORM0 S5P_PMUREG(0x0800)
-#define S5P_INFORM1 S5P_PMUREG(0x0804)
-#define S5P_INFORM5 S5P_PMUREG(0x0814)
-#define S5P_INFORM6 S5P_PMUREG(0x0818)
-#define S5P_INFORM7 S5P_PMUREG(0x081C)
-#define S5P_PMU_SPARE3 S5P_PMUREG(0x090C)
+#define S5P_INFORM0 0x0800
+#define S5P_INFORM1 0x0804
+#define S5P_INFORM5 0x0814
+#define S5P_INFORM6 0x0818
+#define S5P_INFORM7 0x081C
+#define S5P_PMU_SPARE3 0x090C
-#define S5P_ARM_CORE0_LOWPWR S5P_PMUREG(0x1000)
-#define S5P_DIS_IRQ_CORE0 S5P_PMUREG(0x1004)
-#define S5P_DIS_IRQ_CENTRAL0 S5P_PMUREG(0x1008)
-#define S5P_ARM_CORE1_LOWPWR S5P_PMUREG(0x1010)
-#define S5P_DIS_IRQ_CORE1 S5P_PMUREG(0x1014)
-#define S5P_DIS_IRQ_CENTRAL1 S5P_PMUREG(0x1018)
-#define S5P_ARM_COMMON_LOWPWR S5P_PMUREG(0x1080)
-#define S5P_L2_0_LOWPWR S5P_PMUREG(0x10C0)
-#define S5P_L2_1_LOWPWR S5P_PMUREG(0x10C4)
-#define S5P_CMU_ACLKSTOP_LOWPWR S5P_PMUREG(0x1100)
-#define S5P_CMU_SCLKSTOP_LOWPWR S5P_PMUREG(0x1104)
-#define S5P_CMU_RESET_LOWPWR S5P_PMUREG(0x110C)
-#define S5P_APLL_SYSCLK_LOWPWR S5P_PMUREG(0x1120)
-#define S5P_MPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1124)
-#define S5P_VPLL_SYSCLK_LOWPWR S5P_PMUREG(0x1128)
-#define S5P_EPLL_SYSCLK_LOWPWR S5P_PMUREG(0x112C)
-#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR S5P_PMUREG(0x1138)
-#define S5P_CMU_RESET_GPSALIVE_LOWPWR S5P_PMUREG(0x113C)
-#define S5P_CMU_CLKSTOP_CAM_LOWPWR S5P_PMUREG(0x1140)
-#define S5P_CMU_CLKSTOP_TV_LOWPWR S5P_PMUREG(0x1144)
-#define S5P_CMU_CLKSTOP_MFC_LOWPWR S5P_PMUREG(0x1148)
-#define S5P_CMU_CLKSTOP_G3D_LOWPWR S5P_PMUREG(0x114C)
-#define S5P_CMU_CLKSTOP_LCD0_LOWPWR S5P_PMUREG(0x1150)
-#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR S5P_PMUREG(0x1158)
-#define S5P_CMU_CLKSTOP_GPS_LOWPWR S5P_PMUREG(0x115C)
-#define S5P_CMU_RESET_CAM_LOWPWR S5P_PMUREG(0x1160)
-#define S5P_CMU_RESET_TV_LOWPWR S5P_PMUREG(0x1164)
-#define S5P_CMU_RESET_MFC_LOWPWR S5P_PMUREG(0x1168)
-#define S5P_CMU_RESET_G3D_LOWPWR S5P_PMUREG(0x116C)
-#define S5P_CMU_RESET_LCD0_LOWPWR S5P_PMUREG(0x1170)
-#define S5P_CMU_RESET_MAUDIO_LOWPWR S5P_PMUREG(0x1178)
-#define S5P_CMU_RESET_GPS_LOWPWR S5P_PMUREG(0x117C)
-#define S5P_TOP_BUS_LOWPWR S5P_PMUREG(0x1180)
-#define S5P_TOP_RETENTION_LOWPWR S5P_PMUREG(0x1184)
-#define S5P_TOP_PWR_LOWPWR S5P_PMUREG(0x1188)
-#define S5P_LOGIC_RESET_LOWPWR S5P_PMUREG(0x11A0)
-#define S5P_ONENAND_MEM_LOWPWR S5P_PMUREG(0x11C0)
-#define S5P_G2D_ACP_MEM_LOWPWR S5P_PMUREG(0x11C8)
-#define S5P_USBOTG_MEM_LOWPWR S5P_PMUREG(0x11CC)
-#define S5P_HSMMC_MEM_LOWPWR S5P_PMUREG(0x11D0)
-#define S5P_CSSYS_MEM_LOWPWR S5P_PMUREG(0x11D4)
-#define S5P_SECSS_MEM_LOWPWR S5P_PMUREG(0x11D8)
-#define S5P_PAD_RETENTION_DRAM_LOWPWR S5P_PMUREG(0x1200)
-#define S5P_PAD_RETENTION_MAUDIO_LOWPWR S5P_PMUREG(0x1204)
-#define S5P_PAD_RETENTION_GPIO_LOWPWR S5P_PMUREG(0x1220)
-#define S5P_PAD_RETENTION_UART_LOWPWR S5P_PMUREG(0x1224)
-#define S5P_PAD_RETENTION_MMCA_LOWPWR S5P_PMUREG(0x1228)
-#define S5P_PAD_RETENTION_MMCB_LOWPWR S5P_PMUREG(0x122C)
-#define S5P_PAD_RETENTION_EBIA_LOWPWR S5P_PMUREG(0x1230)
-#define S5P_PAD_RETENTION_EBIB_LOWPWR S5P_PMUREG(0x1234)
-#define S5P_PAD_RETENTION_ISOLATION_LOWPWR S5P_PMUREG(0x1240)
-#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR S5P_PMUREG(0x1260)
-#define S5P_XUSBXTI_LOWPWR S5P_PMUREG(0x1280)
-#define S5P_XXTI_LOWPWR S5P_PMUREG(0x1284)
-#define S5P_EXT_REGULATOR_LOWPWR S5P_PMUREG(0x12C0)
-#define S5P_GPIO_MODE_LOWPWR S5P_PMUREG(0x1300)
-#define S5P_GPIO_MODE_MAUDIO_LOWPWR S5P_PMUREG(0x1340)
-#define S5P_CAM_LOWPWR S5P_PMUREG(0x1380)
-#define S5P_TV_LOWPWR S5P_PMUREG(0x1384)
-#define S5P_MFC_LOWPWR S5P_PMUREG(0x1388)
-#define S5P_G3D_LOWPWR S5P_PMUREG(0x138C)
-#define S5P_LCD0_LOWPWR S5P_PMUREG(0x1390)
-#define S5P_MAUDIO_LOWPWR S5P_PMUREG(0x1398)
-#define S5P_GPS_LOWPWR S5P_PMUREG(0x139C)
-#define S5P_GPS_ALIVE_LOWPWR S5P_PMUREG(0x13A0)
+#define S5P_ARM_CORE0_LOWPWR 0x1000
+#define S5P_DIS_IRQ_CORE0 0x1004
+#define S5P_DIS_IRQ_CENTRAL0 0x1008
+#define S5P_ARM_CORE1_LOWPWR 0x1010
+#define S5P_DIS_IRQ_CORE1 0x1014
+#define S5P_DIS_IRQ_CENTRAL1 0x1018
+#define S5P_ARM_COMMON_LOWPWR 0x1080
+#define S5P_L2_0_LOWPWR 0x10C0
+#define S5P_L2_1_LOWPWR 0x10C4
+#define S5P_CMU_ACLKSTOP_LOWPWR 0x1100
+#define S5P_CMU_SCLKSTOP_LOWPWR 0x1104
+#define S5P_CMU_RESET_LOWPWR 0x110C
+#define S5P_APLL_SYSCLK_LOWPWR 0x1120
+#define S5P_MPLL_SYSCLK_LOWPWR 0x1124
+#define S5P_VPLL_SYSCLK_LOWPWR 0x1128
+#define S5P_EPLL_SYSCLK_LOWPWR 0x112C
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR 0x1138
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR 0x113C
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR 0x1140
+#define S5P_CMU_CLKSTOP_TV_LOWPWR 0x1144
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR 0x1148
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR 0x114C
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR 0x1150
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR 0x1158
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR 0x115C
+#define S5P_CMU_RESET_CAM_LOWPWR 0x1160
+#define S5P_CMU_RESET_TV_LOWPWR 0x1164
+#define S5P_CMU_RESET_MFC_LOWPWR 0x1168
+#define S5P_CMU_RESET_G3D_LOWPWR 0x116C
+#define S5P_CMU_RESET_LCD0_LOWPWR 0x1170
+#define S5P_CMU_RESET_MAUDIO_LOWPWR 0x1178
+#define S5P_CMU_RESET_GPS_LOWPWR 0x117C
+#define S5P_TOP_BUS_LOWPWR 0x1180
+#define S5P_TOP_RETENTION_LOWPWR 0x1184
+#define S5P_TOP_PWR_LOWPWR 0x1188
+#define S5P_LOGIC_RESET_LOWPWR 0x11A0
+#define S5P_ONENAND_MEM_LOWPWR 0x11C0
+#define S5P_G2D_ACP_MEM_LOWPWR 0x11C8
+#define S5P_USBOTG_MEM_LOWPWR 0x11CC
+#define S5P_HSMMC_MEM_LOWPWR 0x11D0
+#define S5P_CSSYS_MEM_LOWPWR 0x11D4
+#define S5P_SECSS_MEM_LOWPWR 0x11D8
+#define S5P_PAD_RETENTION_DRAM_LOWPWR 0x1200
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR 0x1204
+#define S5P_PAD_RETENTION_GPIO_LOWPWR 0x1220
+#define S5P_PAD_RETENTION_UART_LOWPWR 0x1224
+#define S5P_PAD_RETENTION_MMCA_LOWPWR 0x1228
+#define S5P_PAD_RETENTION_MMCB_LOWPWR 0x122C
+#define S5P_PAD_RETENTION_EBIA_LOWPWR 0x1230
+#define S5P_PAD_RETENTION_EBIB_LOWPWR 0x1234
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR 0x1240
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR 0x1260
+#define S5P_XUSBXTI_LOWPWR 0x1280
+#define S5P_XXTI_LOWPWR 0x1284
+#define S5P_EXT_REGULATOR_LOWPWR 0x12C0
+#define S5P_GPIO_MODE_LOWPWR 0x1300
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR 0x1340
+#define S5P_CAM_LOWPWR 0x1380
+#define S5P_TV_LOWPWR 0x1384
+#define S5P_MFC_LOWPWR 0x1388
+#define S5P_G3D_LOWPWR 0x138C
+#define S5P_LCD0_LOWPWR 0x1390
+#define S5P_MAUDIO_LOWPWR 0x1398
+#define S5P_GPS_LOWPWR 0x139C
+#define S5P_GPS_ALIVE_LOWPWR 0x13A0
-#define EXYNOS_ARM_CORE0_CONFIGURATION S5P_PMUREG(0x2000)
+#define EXYNOS_ARM_CORE0_CONFIGURATION 0x2000
#define EXYNOS_ARM_CORE_CONFIGURATION(_nr) \
(EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
#define EXYNOS_ARM_CORE_STATUS(_nr) \
(EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
-#define EXYNOS_ARM_COMMON_CONFIGURATION S5P_PMUREG(0x2500)
+#define EXYNOS_ARM_COMMON_CONFIGURATION 0x2500
#define EXYNOS_COMMON_CONFIGURATION(_nr) \
(EXYNOS_ARM_COMMON_CONFIGURATION + (0x80 * (_nr)))
#define EXYNOS_COMMON_STATUS(_nr) \
(EXYNOS_COMMON_CONFIGURATION(_nr) + 0x4)
+#define EXYNOS_COMMON_OPTION(_nr) \
+ (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
-#define S5P_PAD_RET_MAUDIO_OPTION S5P_PMUREG(0x3028)
-#define S5P_PAD_RET_GPIO_OPTION S5P_PMUREG(0x3108)
-#define S5P_PAD_RET_UART_OPTION S5P_PMUREG(0x3128)
-#define S5P_PAD_RET_MMCA_OPTION S5P_PMUREG(0x3148)
-#define S5P_PAD_RET_MMCB_OPTION S5P_PMUREG(0x3168)
-#define S5P_PAD_RET_EBIA_OPTION S5P_PMUREG(0x3188)
-#define S5P_PAD_RET_EBIB_OPTION S5P_PMUREG(0x31A8)
+#define S5P_PAD_RET_MAUDIO_OPTION 0x3028
+#define S5P_PAD_RET_GPIO_OPTION 0x3108
+#define S5P_PAD_RET_UART_OPTION 0x3128
+#define S5P_PAD_RET_MMCA_OPTION 0x3148
+#define S5P_PAD_RET_MMCB_OPTION 0x3168
+#define S5P_PAD_RET_EBIA_OPTION 0x3188
+#define S5P_PAD_RET_EBIB_OPTION 0x31A8
#define S5P_CORE_LOCAL_PWR_EN 0x3
-#define S5P_INT_LOCAL_PWR_EN 0x7
/* Only for EXYNOS4210 */
-#define S5P_CMU_CLKSTOP_LCD1_LOWPWR S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_LCD1_LOWPWR S5P_PMUREG(0x1174)
-#define S5P_MODIMIF_MEM_LOWPWR S5P_PMUREG(0x11C4)
-#define S5P_PCIE_MEM_LOWPWR S5P_PMUREG(0x11E0)
-#define S5P_SATA_MEM_LOWPWR S5P_PMUREG(0x11E4)
-#define S5P_LCD1_LOWPWR S5P_PMUREG(0x1394)
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR 0x1154
+#define S5P_CMU_RESET_LCD1_LOWPWR 0x1174
+#define S5P_MODIMIF_MEM_LOWPWR 0x11C4
+#define S5P_PCIE_MEM_LOWPWR 0x11E0
+#define S5P_SATA_MEM_LOWPWR 0x11E4
+#define S5P_LCD1_LOWPWR 0x1394
/* Only for EXYNOS4x12 */
-#define S5P_ISP_ARM_LOWPWR S5P_PMUREG(0x1050)
-#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR S5P_PMUREG(0x1054)
-#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR S5P_PMUREG(0x1058)
-#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1110)
-#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR S5P_PMUREG(0x1114)
-#define S5P_CMU_RESET_COREBLK_LOWPWR S5P_PMUREG(0x111C)
-#define S5P_MPLLUSER_SYSCLK_LOWPWR S5P_PMUREG(0x1130)
-#define S5P_CMU_CLKSTOP_ISP_LOWPWR S5P_PMUREG(0x1154)
-#define S5P_CMU_RESET_ISP_LOWPWR S5P_PMUREG(0x1174)
-#define S5P_TOP_BUS_COREBLK_LOWPWR S5P_PMUREG(0x1190)
-#define S5P_TOP_RETENTION_COREBLK_LOWPWR S5P_PMUREG(0x1194)
-#define S5P_TOP_PWR_COREBLK_LOWPWR S5P_PMUREG(0x1198)
-#define S5P_OSCCLK_GATE_LOWPWR S5P_PMUREG(0x11A4)
-#define S5P_LOGIC_RESET_COREBLK_LOWPWR S5P_PMUREG(0x11B0)
-#define S5P_OSCCLK_GATE_COREBLK_LOWPWR S5P_PMUREG(0x11B4)
-#define S5P_HSI_MEM_LOWPWR S5P_PMUREG(0x11C4)
-#define S5P_ROTATOR_MEM_LOWPWR S5P_PMUREG(0x11DC)
-#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR S5P_PMUREG(0x123C)
-#define S5P_PAD_ISOLATION_COREBLK_LOWPWR S5P_PMUREG(0x1250)
-#define S5P_GPIO_MODE_COREBLK_LOWPWR S5P_PMUREG(0x1320)
-#define S5P_TOP_ASB_RESET_LOWPWR S5P_PMUREG(0x1344)
-#define S5P_TOP_ASB_ISOLATION_LOWPWR S5P_PMUREG(0x1348)
-#define S5P_ISP_LOWPWR S5P_PMUREG(0x1394)
-#define S5P_DRAM_FREQ_DOWN_LOWPWR S5P_PMUREG(0x13B0)
-#define S5P_DDRPHY_DLLOFF_LOWPWR S5P_PMUREG(0x13B4)
-#define S5P_CMU_SYSCLK_ISP_LOWPWR S5P_PMUREG(0x13B8)
-#define S5P_CMU_SYSCLK_GPS_LOWPWR S5P_PMUREG(0x13BC)
-#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR S5P_PMUREG(0x13C0)
+#define S5P_ISP_ARM_LOWPWR 0x1050
+#define S5P_DIS_IRQ_ISP_ARM_LOCAL_LOWPWR 0x1054
+#define S5P_DIS_IRQ_ISP_ARM_CENTRAL_LOWPWR 0x1058
+#define S5P_CMU_ACLKSTOP_COREBLK_LOWPWR 0x1110
+#define S5P_CMU_SCLKSTOP_COREBLK_LOWPWR 0x1114
+#define S5P_CMU_RESET_COREBLK_LOWPWR 0x111C
+#define S5P_MPLLUSER_SYSCLK_LOWPWR 0x1130
+#define S5P_CMU_CLKSTOP_ISP_LOWPWR 0x1154
+#define S5P_CMU_RESET_ISP_LOWPWR 0x1174
+#define S5P_TOP_BUS_COREBLK_LOWPWR 0x1190
+#define S5P_TOP_RETENTION_COREBLK_LOWPWR 0x1194
+#define S5P_TOP_PWR_COREBLK_LOWPWR 0x1198
+#define S5P_OSCCLK_GATE_LOWPWR 0x11A4
+#define S5P_LOGIC_RESET_COREBLK_LOWPWR 0x11B0
+#define S5P_OSCCLK_GATE_COREBLK_LOWPWR 0x11B4
+#define S5P_HSI_MEM_LOWPWR 0x11C4
+#define S5P_ROTATOR_MEM_LOWPWR 0x11DC
+#define S5P_PAD_RETENTION_GPIO_COREBLK_LOWPWR 0x123C
+#define S5P_PAD_ISOLATION_COREBLK_LOWPWR 0x1250
+#define S5P_GPIO_MODE_COREBLK_LOWPWR 0x1320
+#define S5P_TOP_ASB_RESET_LOWPWR 0x1344
+#define S5P_TOP_ASB_ISOLATION_LOWPWR 0x1348
+#define S5P_ISP_LOWPWR 0x1394
+#define S5P_DRAM_FREQ_DOWN_LOWPWR 0x13B0
+#define S5P_DDRPHY_DLLOFF_LOWPWR 0x13B4
+#define S5P_CMU_SYSCLK_ISP_LOWPWR 0x13B8
+#define S5P_CMU_SYSCLK_GPS_LOWPWR 0x13BC
+#define S5P_LPDDR_PHY_DLL_LOCK_LOWPWR 0x13C0
-#define S5P_ARM_L2_0_OPTION S5P_PMUREG(0x2608)
-#define S5P_ARM_L2_1_OPTION S5P_PMUREG(0x2628)
-#define S5P_ONENAND_MEM_OPTION S5P_PMUREG(0x2E08)
-#define S5P_HSI_MEM_OPTION S5P_PMUREG(0x2E28)
-#define S5P_G2D_ACP_MEM_OPTION S5P_PMUREG(0x2E48)
-#define S5P_USBOTG_MEM_OPTION S5P_PMUREG(0x2E68)
-#define S5P_HSMMC_MEM_OPTION S5P_PMUREG(0x2E88)
-#define S5P_CSSYS_MEM_OPTION S5P_PMUREG(0x2EA8)
-#define S5P_SECSS_MEM_OPTION S5P_PMUREG(0x2EC8)
-#define S5P_ROTATOR_MEM_OPTION S5P_PMUREG(0x2F48)
+#define S5P_ARM_L2_0_OPTION 0x2608
+#define S5P_ARM_L2_1_OPTION 0x2628
+#define S5P_ONENAND_MEM_OPTION 0x2E08
+#define S5P_HSI_MEM_OPTION 0x2E28
+#define S5P_G2D_ACP_MEM_OPTION 0x2E48
+#define S5P_USBOTG_MEM_OPTION 0x2E68
+#define S5P_HSMMC_MEM_OPTION 0x2E88
+#define S5P_CSSYS_MEM_OPTION 0x2EA8
+#define S5P_SECSS_MEM_OPTION 0x2EC8
+#define S5P_ROTATOR_MEM_OPTION 0x2F48
/* Only for EXYNOS4412 */
-#define S5P_ARM_CORE2_LOWPWR S5P_PMUREG(0x1020)
-#define S5P_DIS_IRQ_CORE2 S5P_PMUREG(0x1024)
-#define S5P_DIS_IRQ_CENTRAL2 S5P_PMUREG(0x1028)
-#define S5P_ARM_CORE3_LOWPWR S5P_PMUREG(0x1030)
-#define S5P_DIS_IRQ_CORE3 S5P_PMUREG(0x1034)
-#define S5P_DIS_IRQ_CENTRAL3 S5P_PMUREG(0x1038)
+#define S5P_ARM_CORE2_LOWPWR 0x1020
+#define S5P_DIS_IRQ_CORE2 0x1024
+#define S5P_DIS_IRQ_CENTRAL2 0x1028
+#define S5P_ARM_CORE3_LOWPWR 0x1030
+#define S5P_DIS_IRQ_CORE3 0x1034
+#define S5P_DIS_IRQ_CENTRAL3 0x1038
/* For EXYNOS5 */
-#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
-
-#define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408)
-#define EXYNOS5_MASK_WDTRESET_REQUEST S5P_PMUREG(0x040C)
+#define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408
+#define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C
#define EXYNOS5_SYS_WDTRESET (1 << 20)
-#define EXYNOS5_ARM_CORE0_SYS_PWR_REG S5P_PMUREG(0x1000)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1004)
-#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1008)
-#define EXYNOS5_ARM_CORE1_SYS_PWR_REG S5P_PMUREG(0x1010)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1014)
-#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1018)
-#define EXYNOS5_FSYS_ARM_SYS_PWR_REG S5P_PMUREG(0x1040)
-#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1048)
-#define EXYNOS5_ISP_ARM_SYS_PWR_REG S5P_PMUREG(0x1050)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG S5P_PMUREG(0x1054)
-#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG S5P_PMUREG(0x1058)
-#define EXYNOS5_ARM_COMMON_SYS_PWR_REG S5P_PMUREG(0x1080)
-#define EXYNOS5_ARM_L2_SYS_PWR_REG S5P_PMUREG(0x10C0)
-#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG S5P_PMUREG(0x1100)
-#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG S5P_PMUREG(0x1104)
-#define EXYNOS5_CMU_RESET_SYS_PWR_REG S5P_PMUREG(0x110C)
-#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1120)
-#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1124)
-#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x112C)
-#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG S5P_PMUREG(0x1130)
-#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG S5P_PMUREG(0x1134)
-#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG S5P_PMUREG(0x1138)
-#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1140)
-#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1144)
-#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1148)
-#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x114C)
-#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1150)
-#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1154)
-#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1164)
-#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG S5P_PMUREG(0x1170)
-#define EXYNOS5_TOP_BUS_SYS_PWR_REG S5P_PMUREG(0x1180)
-#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG S5P_PMUREG(0x1184)
-#define EXYNOS5_TOP_PWR_SYS_PWR_REG S5P_PMUREG(0x1188)
-#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1190)
-#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1194)
-#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1198)
-#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG S5P_PMUREG(0x11A0)
-#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG S5P_PMUREG(0x11A4)
-#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x11B0)
-#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x11B4)
-#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG S5P_PMUREG(0x11C0)
-#define EXYNOS5_G2D_MEM_SYS_PWR_REG S5P_PMUREG(0x11C8)
-#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG S5P_PMUREG(0x11CC)
-#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG S5P_PMUREG(0x11D0)
-#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG S5P_PMUREG(0x11D4)
-#define EXYNOS5_SECSS_MEM_SYS_PWR_REG S5P_PMUREG(0x11D8)
-#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG S5P_PMUREG(0x11DC)
-#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG S5P_PMUREG(0x11E0)
-#define EXYNOS5_INTROM_MEM_SYS_PWR_REG S5P_PMUREG(0x11E4)
-#define EXYNOS5_JPEG_MEM_SYS_PWR_REG S5P_PMUREG(0x11E8)
-#define EXYNOS5_HSI_MEM_SYS_PWR_REG S5P_PMUREG(0x11EC)
-#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG S5P_PMUREG(0x11F4)
-#define EXYNOS5_SATA_MEM_SYS_PWR_REG S5P_PMUREG(0x11FC)
-#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG S5P_PMUREG(0x1200)
-#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG S5P_PMUREG(0x1204)
-#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG S5P_PMUREG(0x1208)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG S5P_PMUREG(0x1220)
-#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG S5P_PMUREG(0x1224)
-#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG S5P_PMUREG(0x1228)
-#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG S5P_PMUREG(0x122C)
-#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG S5P_PMUREG(0x1230)
-#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG S5P_PMUREG(0x1234)
-#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG S5P_PMUREG(0x1238)
-#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x123C)
-#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG S5P_PMUREG(0x1240)
-#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1250)
-#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG S5P_PMUREG(0x1260)
-#define EXYNOS5_XUSBXTI_SYS_PWR_REG S5P_PMUREG(0x1280)
-#define EXYNOS5_XXTI_SYS_PWR_REG S5P_PMUREG(0x1284)
-#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG S5P_PMUREG(0x12C0)
-#define EXYNOS5_GPIO_MODE_SYS_PWR_REG S5P_PMUREG(0x1300)
-#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG S5P_PMUREG(0x1320)
-#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG S5P_PMUREG(0x1340)
-#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG S5P_PMUREG(0x1344)
-#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG S5P_PMUREG(0x1348)
-#define EXYNOS5_GSCL_SYS_PWR_REG S5P_PMUREG(0x1400)
-#define EXYNOS5_ISP_SYS_PWR_REG S5P_PMUREG(0x1404)
-#define EXYNOS5_MFC_SYS_PWR_REG S5P_PMUREG(0x1408)
-#define EXYNOS5_G3D_SYS_PWR_REG S5P_PMUREG(0x140C)
-#define EXYNOS5_DISP1_SYS_PWR_REG S5P_PMUREG(0x1414)
-#define EXYNOS5_MAU_SYS_PWR_REG S5P_PMUREG(0x1418)
-#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG S5P_PMUREG(0x1480)
-#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG S5P_PMUREG(0x1484)
-#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG S5P_PMUREG(0x1488)
-#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG S5P_PMUREG(0x148C)
-#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG S5P_PMUREG(0x1494)
-#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG S5P_PMUREG(0x1498)
-#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG S5P_PMUREG(0x14C0)
-#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG S5P_PMUREG(0x14C4)
-#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG S5P_PMUREG(0x14C8)
-#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG S5P_PMUREG(0x14CC)
-#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG S5P_PMUREG(0x14D4)
-#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG S5P_PMUREG(0x14D8)
-#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG S5P_PMUREG(0x1580)
-#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG S5P_PMUREG(0x1584)
-#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG S5P_PMUREG(0x1588)
-#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG S5P_PMUREG(0x158C)
-#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG S5P_PMUREG(0x1594)
-#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG S5P_PMUREG(0x1598)
+#define EXYNOS5_ARM_CORE0_SYS_PWR_REG 0x1000
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004
+#define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008
+#define EXYNOS5_ARM_CORE1_SYS_PWR_REG 0x1010
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG 0x1014
+#define EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG 0x1018
+#define EXYNOS5_FSYS_ARM_SYS_PWR_REG 0x1040
+#define EXYNOS5_DIS_IRQ_FSYS_ARM_CENTRAL_SYS_PWR_REG 0x1048
+#define EXYNOS5_ISP_ARM_SYS_PWR_REG 0x1050
+#define EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1054
+#define EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1058
+#define EXYNOS5_ARM_COMMON_SYS_PWR_REG 0x1080
+#define EXYNOS5_ARM_L2_SYS_PWR_REG 0x10C0
+#define EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG 0x1100
+#define EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG 0x1104
+#define EXYNOS5_CMU_RESET_SYS_PWR_REG 0x110C
+#define EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG 0x1120
+#define EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG 0x1124
+#define EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG 0x112C
+#define EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG 0x1130
+#define EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG 0x1134
+#define EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG 0x1138
+#define EXYNOS5_APLL_SYSCLK_SYS_PWR_REG 0x1140
+#define EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG 0x1144
+#define EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG 0x1148
+#define EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG 0x114C
+#define EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG 0x1150
+#define EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG 0x1154
+#define EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG 0x1164
+#define EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG 0x1170
+#define EXYNOS5_TOP_BUS_SYS_PWR_REG 0x1180
+#define EXYNOS5_TOP_RETENTION_SYS_PWR_REG 0x1184
+#define EXYNOS5_TOP_PWR_SYS_PWR_REG 0x1188
+#define EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG 0x1190
+#define EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG 0x1194
+#define EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG 0x1198
+#define EXYNOS5_LOGIC_RESET_SYS_PWR_REG 0x11A0
+#define EXYNOS5_OSCCLK_GATE_SYS_PWR_REG 0x11A4
+#define EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG 0x11B0
+#define EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG 0x11B4
+#define EXYNOS5_USBOTG_MEM_SYS_PWR_REG 0x11C0
+#define EXYNOS5_G2D_MEM_SYS_PWR_REG 0x11C8
+#define EXYNOS5_USBDRD_MEM_SYS_PWR_REG 0x11CC
+#define EXYNOS5_SDMMC_MEM_SYS_PWR_REG 0x11D0
+#define EXYNOS5_CSSYS_MEM_SYS_PWR_REG 0x11D4
+#define EXYNOS5_SECSS_MEM_SYS_PWR_REG 0x11D8
+#define EXYNOS5_ROTATOR_MEM_SYS_PWR_REG 0x11DC
+#define EXYNOS5_INTRAM_MEM_SYS_PWR_REG 0x11E0
+#define EXYNOS5_INTROM_MEM_SYS_PWR_REG 0x11E4
+#define EXYNOS5_JPEG_MEM_SYS_PWR_REG 0x11E8
+#define EXYNOS5_HSI_MEM_SYS_PWR_REG 0x11EC
+#define EXYNOS5_MCUIOP_MEM_SYS_PWR_REG 0x11F4
+#define EXYNOS5_SATA_MEM_SYS_PWR_REG 0x11FC
+#define EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200
+#define EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG 0x1204
+#define EXYNOS5_PAD_RETENTION_EFNAND_SYS_PWR_REG 0x1208
+#define EXYNOS5_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220
+#define EXYNOS5_PAD_RETENTION_UART_SYS_PWR_REG 0x1224
+#define EXYNOS5_PAD_RETENTION_MMCA_SYS_PWR_REG 0x1228
+#define EXYNOS5_PAD_RETENTION_MMCB_SYS_PWR_REG 0x122C
+#define EXYNOS5_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230
+#define EXYNOS5_PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234
+#define EXYNOS5_PAD_RETENTION_SPI_SYS_PWR_REG 0x1238
+#define EXYNOS5_PAD_RETENTION_GPIO_SYSMEM_SYS_PWR_REG 0x123C
+#define EXYNOS5_PAD_ISOLATION_SYS_PWR_REG 0x1240
+#define EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG 0x1250
+#define EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG 0x1260
+#define EXYNOS5_XUSBXTI_SYS_PWR_REG 0x1280
+#define EXYNOS5_XXTI_SYS_PWR_REG 0x1284
+#define EXYNOS5_EXT_REGULATOR_SYS_PWR_REG 0x12C0
+#define EXYNOS5_GPIO_MODE_SYS_PWR_REG 0x1300
+#define EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG 0x1320
+#define EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG 0x1340
+#define EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG 0x1344
+#define EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG 0x1348
+#define EXYNOS5_GSCL_SYS_PWR_REG 0x1400
+#define EXYNOS5_ISP_SYS_PWR_REG 0x1404
+#define EXYNOS5_MFC_SYS_PWR_REG 0x1408
+#define EXYNOS5_G3D_SYS_PWR_REG 0x140C
+#define EXYNOS5_DISP1_SYS_PWR_REG 0x1414
+#define EXYNOS5_MAU_SYS_PWR_REG 0x1418
+#define EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG 0x1480
+#define EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG 0x1484
+#define EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1488
+#define EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG 0x148C
+#define EXYNOS5_CMU_CLKSTOP_DISP1_SYS_PWR_REG 0x1494
+#define EXYNOS5_CMU_CLKSTOP_MAU_SYS_PWR_REG 0x1498
+#define EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG 0x14C0
+#define EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG 0x14C4
+#define EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG 0x14C8
+#define EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG 0x14CC
+#define EXYNOS5_CMU_SYSCLK_DISP1_SYS_PWR_REG 0x14D4
+#define EXYNOS5_CMU_SYSCLK_MAU_SYS_PWR_REG 0x14D8
+#define EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG 0x1580
+#define EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG 0x1584
+#define EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG 0x1588
+#define EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG 0x158C
+#define EXYNOS5_CMU_RESET_DISP1_SYS_PWR_REG 0x1594
+#define EXYNOS5_CMU_RESET_MAU_SYS_PWR_REG 0x1598
-#define EXYNOS5_ARM_CORE0_OPTION S5P_PMUREG(0x2008)
-#define EXYNOS5_ARM_CORE1_OPTION S5P_PMUREG(0x2088)
-#define EXYNOS5_FSYS_ARM_OPTION S5P_PMUREG(0x2208)
-#define EXYNOS5_ISP_ARM_OPTION S5P_PMUREG(0x2288)
-#define EXYNOS5_ARM_COMMON_OPTION S5P_PMUREG(0x2408)
-#define EXYNOS5_ARM_L2_OPTION S5P_PMUREG(0x2608)
-#define EXYNOS5_TOP_PWR_OPTION S5P_PMUREG(0x2C48)
-#define EXYNOS5_TOP_PWR_SYSMEM_OPTION S5P_PMUREG(0x2CC8)
-#define EXYNOS5_JPEG_MEM_OPTION S5P_PMUREG(0x2F48)
-#define EXYNOS5_GSCL_OPTION S5P_PMUREG(0x4008)
-#define EXYNOS5_ISP_OPTION S5P_PMUREG(0x4028)
-#define EXYNOS5_MFC_OPTION S5P_PMUREG(0x4048)
-#define EXYNOS5_G3D_OPTION S5P_PMUREG(0x4068)
-#define EXYNOS5_DISP1_OPTION S5P_PMUREG(0x40A8)
-#define EXYNOS5_MAU_OPTION S5P_PMUREG(0x40C8)
+#define EXYNOS5_ARM_CORE0_OPTION 0x2008
+#define EXYNOS5_ARM_CORE1_OPTION 0x2088
+#define EXYNOS5_FSYS_ARM_OPTION 0x2208
+#define EXYNOS5_ISP_ARM_OPTION 0x2288
+#define EXYNOS5_ARM_COMMON_OPTION 0x2408
+#define EXYNOS5_ARM_L2_OPTION 0x2608
+#define EXYNOS5_TOP_PWR_OPTION 0x2C48
+#define EXYNOS5_TOP_PWR_SYSMEM_OPTION 0x2CC8
+#define EXYNOS5_JPEG_MEM_OPTION 0x2F48
+#define EXYNOS5_GSCL_OPTION 0x4008
+#define EXYNOS5_ISP_OPTION 0x4028
+#define EXYNOS5_MFC_OPTION 0x4048
+#define EXYNOS5_G3D_OPTION 0x4068
+#define EXYNOS5_DISP1_OPTION 0x40A8
+#define EXYNOS5_MAU_OPTION 0x40C8
#define EXYNOS5_USE_SC_FEEDBACK (1 << 1)
#define EXYNOS5_USE_SC_COUNTER (1 << 0)
@@ -323,4 +317,13 @@
#define EXYNOS5420_SWRESET_KFC_SEL 0x3
+#include <asm/cputype.h>
+#define MAX_CPUS_IN_CLUSTER 4
+
+static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
+{
+ return ((MPIDR_AFFINITY_LEVEL(mpidr, 1) * MAX_CPUS_IN_CLUSTER)
+ + MPIDR_AFFINITY_LEVEL(mpidr, 0));
+}
+
#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-exynos/regs-sys.h b/arch/arm/mach-exynos/regs-sys.h
new file mode 100644
index 000000000000..84332b0dd7a6
--- /dev/null
+++ b/arch/arm/mach-exynos/regs-sys.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - system register definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SYS_H
+#define __ASM_ARCH_REGS_SYS_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SYSREG(x) (S3C_VA_SYS + (x))
+
+/* For EXYNOS5 */
+#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234)
+
+#endif /* __ASM_ARCH_REGS_SYS_H */
diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h
index 5c6df377f969..6f2ecccdf323 100644
--- a/arch/arm/mach-footbridge/include/mach/memory.h
+++ b/arch/arm/mach-footbridge/include/mach/memory.h
@@ -59,11 +59,6 @@ extern unsigned long __bus_to_pfn(unsigned long);
*/
#define FLUSH_BASE 0xf9000000
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
#define FLUSH_BASE_PHYS 0x50000000
#endif
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index a5960e2ac090..31aa866c3317 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -2,7 +2,6 @@ config ARCH_HIGHBANK
bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7
select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
select ARCH_HAS_HOLES_MEMORYMODEL
- select ARCH_HAS_OPP
select ARCH_SUPPORTS_BIG_ENDIAN
select ARM_AMBA
select ARM_ERRATA_764369 if SMP
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index feee4dbb0760..984882943f77 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -1,12 +1,36 @@
-config ARCH_HI3xxx
- bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
+config ARCH_HISI
+ bool "Hisilicon SoC Support"
+ depends on ARCH_MULTIPLATFORM
select ARM_AMBA
select ARM_GIC
select ARM_TIMER_SP804
+ select POWER_RESET
+ select POWER_RESET_HISI
+ select POWER_SUPPLY
+
+if ARCH_HISI
+
+menu "Hisilicon platform type"
+
+config ARCH_HI3xxx
+ bool "Hisilicon Hi36xx family" if ARCH_MULTI_V7
+ select CACHE_L2X0
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select PINCTRL
+ select PINCTRL_SINGLE
+ help
+ Support for Hisilicon Hi36xx SoC family
+
+config ARCH_HIX5HD2
+ bool "Hisilicon X5HD2 family" if ARCH_MULTI_V7
select CACHE_L2X0
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL
select PINCTRL_SINGLE
help
- Support for Hisilicon Hi36xx/Hi37xx processor family
+ Support for Hisilicon HIX5HD2 SoC family
+endmenu
+
+endif
diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile
index 2ae1b59267c2..ee2506b9cde3 100644
--- a/arch/arm/mach-hisi/Makefile
+++ b/arch/arm/mach-hisi/Makefile
@@ -3,4 +3,4 @@
#
obj-y += hisilicon.o
-obj-$(CONFIG_SMP) += platsmp.o hotplug.o
+obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.o
diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index af23ec204538..88b1f487d065 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -12,4 +12,9 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
extern int hi3xxx_cpu_kill(unsigned int cpu);
extern void hi3xxx_set_cpu(int cpu, bool enable);
+extern void hix5hd2_secondary_startup(void);
+extern struct smp_operations hix5hd2_smp_ops;
+extern void hix5hd2_set_cpu(int cpu, bool enable);
+extern void hix5hd2_cpu_die(unsigned int cpu);
+
#endif
diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S
new file mode 100644
index 000000000000..278889c00b77
--- /dev/null
+++ b/arch/arm/mach-hisi/headsmp.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2014 Hisilicon Limited.
+ * Copyright (c) 2014 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ __CPUINIT
+
+ENTRY(hix5hd2_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index 741faf3e7100..7cda6dda3cd0 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -14,16 +14,10 @@
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-
-#include <asm/proc-fns.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include "core.h"
-
#define HI3620_SYSCTRL_PHYS_BASE 0xfc802000
#define HI3620_SYSCTRL_VIRT_BASE 0xfe802000
@@ -51,32 +45,6 @@ static void __init hi3620_map_io(void)
iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc));
}
-static void hi3xxx_restart(enum reboot_mode mode, const char *cmd)
-{
- struct device_node *np;
- void __iomem *base;
- int offset;
-
- np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
- if (!np) {
- pr_err("failed to find hisilicon,sysctrl node\n");
- return;
- }
- base = of_iomap(np, 0);
- if (!base) {
- pr_err("failed to map address in hisilicon,sysctrl node\n");
- return;
- }
- if (of_property_read_u32(np, "reboot-offset", &offset) < 0) {
- pr_err("failed to find reboot-offset property\n");
- return;
- }
- writel_relaxed(0xdeadbeef, base + offset);
-
- while (1)
- cpu_do_idle();
-}
-
static const char *hi3xxx_compat[] __initconst = {
"hisilicon,hi3620-hi4511",
NULL,
@@ -85,6 +53,13 @@ static const char *hi3xxx_compat[] __initconst = {
DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
.map_io = hi3620_map_io,
.dt_compat = hi3xxx_compat,
- .smp = smp_ops(hi3xxx_smp_ops),
- .restart = hi3xxx_restart,
+MACHINE_END
+
+static const char *hix5hd2_compat[] __initconst = {
+ "hisilicon,hix5hd2",
+ NULL,
+};
+
+DT_MACHINE_START(HIX5HD2_DT, "Hisilicon HIX5HD2 (Flattened Device Tree)")
+ .dt_compat = hix5hd2_compat,
MACHINE_END
diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c
index abd441b0c604..84e6919f68c7 100644
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -57,6 +57,14 @@
#define CPU0_NEON_SRST_REQ_EN (1 << 4)
#define CPU0_SRST_REQ_EN (1 << 0)
+#define HIX5HD2_PERI_CRG20 0x50
+#define CRG20_CPU1_RESET (1 << 17)
+
+#define HIX5HD2_PERI_PMC0 0x1000
+#define PMC0_CPU1_WAIT_MTCOMS_ACK (1 << 8)
+#define PMC0_CPU1_PMC_ENABLE (1 << 7)
+#define PMC0_CPU1_POWERDOWN (1 << 3)
+
enum {
HI3620_CTRL,
ERROR_CTRL,
@@ -157,6 +165,50 @@ void hi3xxx_set_cpu(int cpu, bool enable)
set_cpu_hi3620(cpu, enable);
}
+static bool hix5hd2_hotplug_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
+ if (np) {
+ ctrl_base = of_iomap(np, 0);
+ return true;
+ }
+ return false;
+}
+
+void hix5hd2_set_cpu(int cpu, bool enable)
+{
+ u32 val = 0;
+
+ if (!ctrl_base)
+ if (!hix5hd2_hotplug_init())
+ BUG();
+
+ if (enable) {
+ /* power on cpu1 */
+ val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+ val &= ~(PMC0_CPU1_WAIT_MTCOMS_ACK | PMC0_CPU1_POWERDOWN);
+ val |= PMC0_CPU1_PMC_ENABLE;
+ writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+ /* unreset */
+ val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+ val &= ~CRG20_CPU1_RESET;
+ writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+ } else {
+ /* power down cpu1 */
+ val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
+ val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
+ val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
+ writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
+
+ /* reset */
+ val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
+ val |= CRG20_CPU1_RESET;
+ writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
+ }
+}
+
static inline void cpu_enter_lowpower(void)
{
unsigned int v;
@@ -199,4 +251,10 @@ int hi3xxx_cpu_kill(unsigned int cpu)
hi3xxx_set_cpu(cpu, false);
return 1;
}
+
+void hix5hd2_cpu_die(unsigned int cpu)
+{
+ flush_cache_all();
+ hix5hd2_set_cpu(cpu, false);
+}
#endif
diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index 471f1ee3be2b..575dd8285f1f 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -17,6 +17,8 @@
#include "core.h"
+#define HIX5HD2_BOOT_ADDRESS 0xffff0000
+
static void __iomem *ctrl_base;
void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
@@ -35,11 +37,9 @@ int hi3xxx_get_cpu_jump(int cpu)
return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
}
-static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hisi_enable_scu_a9(void)
{
- struct device_node *np = NULL;
unsigned long base = 0;
- u32 offset = 0;
void __iomem *scu_base = NULL;
if (scu_a9_has_base()) {
@@ -52,6 +52,14 @@ static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
scu_enable(scu_base);
iounmap(scu_base);
}
+}
+
+static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np = NULL;
+ u32 offset = 0;
+
+ hisi_enable_scu_a9();
if (!ctrl_base) {
np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
if (!np) {
@@ -87,3 +95,42 @@ struct smp_operations hi3xxx_smp_ops __initdata = {
.cpu_kill = hi3xxx_cpu_kill,
#endif
};
+
+static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
+{
+ hisi_enable_scu_a9();
+}
+
+void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
+{
+ void __iomem *virt;
+
+ virt = ioremap(start_addr, PAGE_SIZE);
+
+ writel_relaxed(0xe51ff004, virt); /* ldr pc, [rc, #-4] */
+ writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */
+ iounmap(virt);
+}
+
+static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ phys_addr_t jumpaddr;
+
+ jumpaddr = virt_to_phys(hix5hd2_secondary_startup);
+ hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
+ hix5hd2_set_cpu(cpu, true);
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+ return 0;
+}
+
+
+struct smp_operations hix5hd2_smp_ops __initdata = {
+ .smp_prepare_cpus = hix5hd2_smp_prepare_cpus,
+ .smp_boot_secondary = hix5hd2_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = hix5hd2_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
+CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 4b5185748f74..9de84a215abd 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -1,6 +1,5 @@
menuconfig ARCH_MXC
bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
- select ARCH_HAS_OPP
select ARCH_REQUIRE_GPIOLIB
select ARM_CPU_SUSPEND if PM
select CLKSRC_MMIO
@@ -65,18 +64,8 @@ config IMX_HAVE_IOMUX_V1
config ARCH_MXC_IOMUX_V3
bool
-config ARCH_MX1
- bool
-
-config ARCH_MX25
- bool
-
-config MACH_MX27
- bool
-
config SOC_IMX1
bool
- select ARCH_MX1
select CPU_ARM920T
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
@@ -89,7 +78,6 @@ config SOC_IMX21
config SOC_IMX25
bool
- select ARCH_MX25
select ARCH_MXC_IOMUX_V3
select CPU_ARM926T
select MXC_AVIC
@@ -100,7 +88,6 @@ config SOC_IMX27
select ARCH_HAS_OPP
select CPU_ARM926T
select IMX_HAVE_IOMUX_V1
- select MACH_MX27
select MXC_AVIC
select PINCTRL_IMX27
@@ -119,18 +106,6 @@ config SOC_IMX35
select PINCTRL_IMX35
select SMP_ON_UP if SMP
-config SOC_IMX5
- bool
- select ARCH_HAS_OPP
- select ARCH_MXC_IOMUX_V3
- select MXC_TZIC
-
-config SOC_IMX51
- bool
- select HAVE_IMX_SRC
- select PINCTRL_IMX51
- select SOC_IMX5
-
if ARCH_MULTI_V4T
comment "MX1 platforms:"
@@ -366,15 +341,6 @@ config MACH_IMX27_VISSTRIM_M10
This includes specific configurations for the board and its
peripherals.
-config MACH_IMX27LITE
- bool "LogicPD MX27 LITEKIT platform"
- select IMX_HAVE_PLATFORM_IMX_SSI
- select IMX_HAVE_PLATFORM_IMX_UART
- select SOC_IMX27
- help
- Include support for MX27 LITEKIT platform. This includes specific
- configurations for the board and its peripherals.
-
config MACH_PCA100
bool "Phytec phyCARD-s (pca100)"
select IMX_HAVE_PLATFORM_FSL_USB2_UDC
@@ -406,15 +372,6 @@ config MACH_MXT_TD60
Include support for i-MXT (aka td60) platform. This
includes specific configurations for the module and its peripherals.
-config MACH_IMX27IPCAM
- bool "IMX27 IPCAM platform"
- select IMX_HAVE_PLATFORM_IMX2_WDT
- select IMX_HAVE_PLATFORM_IMX_UART
- select SOC_IMX27
- help
- Include support for IMX27 IPCAM platform. This includes specific
- configurations for the board and its peripherals.
-
config MACH_IMX27_DT
bool "Support i.MX27 platforms from device tree"
select SOC_IMX27
@@ -700,24 +657,29 @@ if ARCH_MULTI_V7
comment "Device tree only"
+config SOC_IMX5
+ bool
+ select ARCH_HAS_OPP
+ select HAVE_IMX_SRC
+ select MXC_TZIC
+
config SOC_IMX50
bool "i.MX50 support"
- select HAVE_IMX_SRC
select PINCTRL_IMX50
select SOC_IMX5
help
This enables support for Freescale i.MX50 processor.
-config MACH_IMX51_DT
+config SOC_IMX51
bool "i.MX51 support"
- select SOC_IMX51
+ select PINCTRL_IMX51
+ select SOC_IMX5
help
This enables support for Freescale i.MX51 processor
config SOC_IMX53
bool "i.MX53 support"
- select HAVE_IMX_SRC
select PINCTRL_IMX53
select SOC_IMX5
@@ -734,8 +696,6 @@ config SOC_IMX6
select HAVE_IMX_MMDC
select HAVE_IMX_SRC
select MFD_SYSCON
- select PL310_ERRATA_588369 if CACHE_L2X0
- select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
config SOC_IMX6Q
@@ -771,8 +731,6 @@ config SOC_VF610
select ARM_GIC
select PINCTRL_VF610
select VF_PIT_TIMER
- select PL310_ERRATA_588369 if CACHE_L2X0
- select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
help
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index bbe93bbfd003..ac88599ca080 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y)
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o clk.o \
@@ -31,6 +31,8 @@ ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
+# i.MX6SX reuses i.MX6Q cpuidle driver
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
endif
ifdef CONFIG_SND_IMX_SOC
@@ -38,9 +40,6 @@ obj-y += ssi-fiq.o
obj-y += ssi-fiq-ksym.o
endif
-# Support for CMOS sensor interface
-obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
-
# i.MX1 based machines
obj-$(CONFIG_ARCH_MX1ADS) += mach-mx1ads.o
obj-$(CONFIG_MACH_SCB9328) += mach-scb9328.o
@@ -60,13 +59,11 @@ obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
-obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
obj-$(CONFIG_MACH_IMX27_VISSTRIM_M10) += mach-imx27_visstrim_m10.o
obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
-obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o
obj-$(CONFIG_MACH_IMX27_DT) += imx27-dt.o
# i.MX31 based machines
@@ -109,8 +106,8 @@ obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
-obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
+obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
diff --git a/arch/arm/mach-imx/clk-imx1.c b/arch/arm/mach-imx/clk-imx1.c
index 7f739be3de2c..37c307a8d896 100644
--- a/arch/arm/mach-imx/clk-imx1.c
+++ b/arch/arm/mach-imx/clk-imx1.c
@@ -15,100 +15,103 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/clk.h>
-#include <linux/io.h>
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx1-clock.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
-/* CCM register addresses */
-#define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
-
-#define CCM_CSCR IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
-#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
-#define CCM_PCDR IO_ADDR_CCM(0x20)
-
-/* SCM register addresses */
-#define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
-
-#define SCM_GCCR IO_ADDR_SCM(0xc)
-
static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", };
static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m",
"prem", "fclk", };
-enum imx1_clks {
- dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, mpll_gate,
- spll, spll_gate, mcu, fclk, hclk, clk48m, per1, per2, per3, clko,
- uart3_gate, ssi2_gate, brom_gate, dma_gate, csi_gate, mma_gate,
- usbd_gate, clk_max
-};
+static struct clk *clk[IMX1_CLK_MAX];
+static struct clk_onecell_data clk_data;
-static struct clk *clk[clk_max];
+static void __iomem *ccm __initdata;
+#define CCM_CSCR (ccm + 0x0000)
+#define CCM_MPCTL0 (ccm + 0x0004)
+#define CCM_SPCTL0 (ccm + 0x000c)
+#define CCM_PCDR (ccm + 0x0020)
+#define SCM_GCCR (ccm + 0x0810)
-int __init mx1_clocks_init(unsigned long fref)
+static void __init _mx1_clocks_init(unsigned long fref)
{
- int i;
+ clk[IMX1_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+ clk[IMX1_CLK_CLK32] = imx_obtain_fixed_clock("clk32", fref);
+ clk[IMX1_CLK_CLK16M_EXT] = imx_clk_fixed("clk16m_ext", 16000000);
+ clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
+ clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
+ clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks));
+ clk[IMX1_CLK_MPLL] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
+ clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
+ clk[IMX1_CLK_SPLL] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
+ clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+ clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
+ clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1);
+ clk[IMX1_CLK_HCLK] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4);
+ clk[IMX1_CLK_CLK48M] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3);
+ clk[IMX1_CLK_PER1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4);
+ clk[IMX1_CLK_PER2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4);
+ clk[IMX1_CLK_PER3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7);
+ clk[IMX1_CLK_CLKO] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+ clk[IMX1_CLK_UART3_GATE] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6);
+ clk[IMX1_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5);
+ clk[IMX1_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4);
+ clk[IMX1_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3);
+ clk[IMX1_CLK_CSI_GATE] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
+ clk[IMX1_CLK_MMA_GATE] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
+ clk[IMX1_CLK_USBD_GATE] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
+
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
+}
- clk[dummy] = imx_clk_fixed("dummy", 0);
- clk[clk32] = imx_clk_fixed("clk32", fref);
- clk[clk16m_ext] = imx_clk_fixed("clk16m_ext", 16000000);
- clk[clk16m] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
- clk[clk32_premult] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
- clk[prem] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks,
- ARRAY_SIZE(prem_sel_clks));
- clk[mpll] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
- clk[mpll_gate] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
- clk[spll] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
- clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
- clk[mcu] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
- clk[fclk] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1);
- clk[hclk] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4);
- clk[clk48m] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3);
- clk[per1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4);
- clk[per2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4);
- clk[per3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7);
- clk[clko] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks,
- ARRAY_SIZE(clko_sel_clks));
- clk[uart3_gate] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6);
- clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5);
- clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4);
- clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3);
- clk[csi_gate] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2);
- clk[mma_gate] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1);
- clk[usbd_gate] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0);
+int __init mx1_clocks_init(unsigned long fref)
+{
+ ccm = MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("imx1 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ _mx1_clocks_init(fref);
- clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma");
- clk_register_clkdev(clk[hclk], "ipg", "imx1-dma");
- clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
- clk_register_clkdev(clk[hclk], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[per1], "per", "imx1-uart.0");
- clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.0");
- clk_register_clkdev(clk[per1], "per", "imx1-uart.1");
- clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1");
- clk_register_clkdev(clk[per1], "per", "imx1-uart.2");
- clk_register_clkdev(clk[uart3_gate], "ipg", "imx1-uart.2");
- clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0");
- clk_register_clkdev(clk[per2], "per", "imx1-cspi.0");
- clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0");
- clk_register_clkdev(clk[per2], "per", "imx1-cspi.1");
- clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1");
- clk_register_clkdev(clk[per2], "per", "imx1-fb.0");
- clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0");
- clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0");
+ clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX1_CLK_DMA_GATE], "ahb", "imx1-dma");
+ clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-dma");
+ clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.0");
+ clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.0");
+ clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.1");
+ clk_register_clkdev(clk[IMX1_CLK_HCLK], "ipg", "imx1-uart.1");
+ clk_register_clkdev(clk[IMX1_CLK_PER1], "per", "imx1-uart.2");
+ clk_register_clkdev(clk[IMX1_CLK_UART3_GATE], "ipg", "imx1-uart.2");
+ clk_register_clkdev(clk[IMX1_CLK_HCLK], NULL, "imx1-i2c.0");
+ clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.0");
+ clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.0");
+ clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-cspi.1");
+ clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-cspi.1");
+ clk_register_clkdev(clk[IMX1_CLK_PER2], "per", "imx1-fb.0");
+ clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0");
+ clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0");
mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
return 0;
}
+
+static void __init mx1_clocks_init_dt(struct device_node *np)
+{
+ ccm = of_iomap(np, 0);
+ BUG_ON(!ccm);
+
+ _mx1_clocks_init(32768);
+
+ clk_data.clks = clk;
+ clk_data.clk_num = ARRAY_SIZE(clk);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(imx1_ccm, "fsl,imx1-ccm", mx1_clocks_init_dt);
diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c
index bdc2e4630a08..4b4c75339aa6 100644
--- a/arch/arm/mach-imx/clk-imx21.c
+++ b/arch/arm/mach-imx/clk-imx21.c
@@ -7,178 +7,165 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
*/
#include <linux/clk.h>
-#include <linux/clkdev.h>
#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/err.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx21-clock.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
-#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
+static void __iomem *ccm __initdata;
/* Register offsets */
-#define CCM_CSCR IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
-#define CCM_MPCTL1 IO_ADDR_CCM(0x8)
-#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
-#define CCM_SPCTL1 IO_ADDR_CCM(0x10)
-#define CCM_OSC26MCTL IO_ADDR_CCM(0x14)
-#define CCM_PCDR0 IO_ADDR_CCM(0x18)
-#define CCM_PCDR1 IO_ADDR_CCM(0x1c)
-#define CCM_PCCR0 IO_ADDR_CCM(0x20)
-#define CCM_PCCR1 IO_ADDR_CCM(0x24)
-#define CCM_CCSR IO_ADDR_CCM(0x28)
-#define CCM_PMCTL IO_ADDR_CCM(0x2c)
-#define CCM_PMCOUNT IO_ADDR_CCM(0x30)
-#define CCM_WKGDCTL IO_ADDR_CCM(0x34)
-
-static const char *mpll_sel_clks[] = { "fpm", "ckih", };
-static const char *spll_sel_clks[] = { "fpm", "ckih", };
-
-enum imx21_clks {
- ckil, ckih, fpm, mpll_sel, spll_sel, mpll, spll, fclk, hclk, ipg, per1,
- per2, per3, per4, uart1_ipg_gate, uart2_ipg_gate, uart3_ipg_gate,
- uart4_ipg_gate, gpt1_ipg_gate, gpt2_ipg_gate, gpt3_ipg_gate,
- pwm_ipg_gate, sdhc1_ipg_gate, sdhc2_ipg_gate, lcdc_ipg_gate,
- lcdc_hclk_gate, cspi3_ipg_gate, cspi2_ipg_gate, cspi1_ipg_gate,
- per4_gate, csi_hclk_gate, usb_div, usb_gate, usb_hclk_gate, ssi1_gate,
- ssi2_gate, nfc_div, nfc_gate, dma_gate, dma_hclk_gate, brom_gate,
- emma_gate, emma_hclk_gate, slcdc_gate, slcdc_hclk_gate, wdog_gate,
- gpio_gate, i2c_gate, kpp_gate, owire_gate, rtc_gate, clk_max
-};
-
-static struct clk *clk[clk_max];
+#define CCM_CSCR (ccm + 0x00)
+#define CCM_MPCTL0 (ccm + 0x04)
+#define CCM_SPCTL0 (ccm + 0x0c)
+#define CCM_PCDR0 (ccm + 0x18)
+#define CCM_PCDR1 (ccm + 0x1c)
+#define CCM_PCCR0 (ccm + 0x20)
+#define CCM_PCCR1 (ccm + 0x24)
+
+static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", };
+static const char *mpll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
+static const char *spll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
+static const char *ssi_sel_clks[] = { "spll_gate", "mpll_gate", };
+
+static struct clk *clk[IMX21_CLK_MAX];
+static struct clk_onecell_data clk_data;
+
+static void __init _mx21_clocks_init(unsigned long lref, unsigned long href)
+{
+ BUG_ON(!ccm);
+
+ clk[IMX21_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+ clk[IMX21_CLK_CKIL] = imx_obtain_fixed_clock("ckil", lref);
+ clk[IMX21_CLK_CKIH] = imx_obtain_fixed_clock("ckih", href);
+ clk[IMX21_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
+ clk[IMX21_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3);
+
+ clk[IMX21_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
+ clk[IMX21_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+ clk[IMX21_CLK_FPM_GATE] = imx_clk_gate("fpm_gate", "fpm", CCM_CSCR, 2);
+ clk[IMX21_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
+ clk[IMX21_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
+ clk[IMX21_CLK_IPG] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
+ clk[IMX21_CLK_HCLK] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
+ clk[IMX21_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
+ clk[IMX21_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks, ARRAY_SIZE(spll_sel_clks));
+ clk[IMX21_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 19, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+ clk[IMX21_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 20, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+ clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3);
+ clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3);
+
+ clk[IMX21_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
+
+ clk[IMX21_CLK_SPLL] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
+
+ clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4);
+ clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
+ clk[IMX21_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
+
+ clk[IMX21_CLK_PER1] = imx_clk_divider("per1", "mpll_gate", CCM_PCDR1, 0, 6);
+ clk[IMX21_CLK_PER2] = imx_clk_divider("per2", "mpll_gate", CCM_PCDR1, 8, 6);
+ clk[IMX21_CLK_PER3] = imx_clk_divider("per3", "mpll_gate", CCM_PCDR1, 16, 6);
+ clk[IMX21_CLK_PER4] = imx_clk_divider("per4", "mpll_gate", CCM_PCDR1, 24, 6);
+
+ clk[IMX21_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
+ clk[IMX21_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
+ clk[IMX21_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
+ clk[IMX21_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
+ clk[IMX21_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
+ clk[IMX21_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
+ clk[IMX21_CLK_SSI1_GATE] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
+ clk[IMX21_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
+ clk[IMX21_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
+ clk[IMX21_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
+ clk[IMX21_CLK_GPIO_GATE] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
+ clk[IMX21_CLK_I2C_GATE] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
+ clk[IMX21_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
+ clk[IMX21_CLK_USB_GATE] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
+ clk[IMX21_CLK_EMMA_GATE] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
+ clk[IMX21_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ipg", CCM_PCCR0, 16);
+ clk[IMX21_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ipg", CCM_PCCR0, 17);
+ clk[IMX21_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
+ clk[IMX21_CLK_NFC_GATE] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
+ clk[IMX21_CLK_SLCDC_HCLK_GATE] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
+ clk[IMX21_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
+ clk[IMX21_CLK_BMI_GATE] = imx_clk_gate("bmi_gate", "hclk", CCM_PCCR0, 23);
+ clk[IMX21_CLK_USB_HCLK_GATE] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
+ clk[IMX21_CLK_SLCDC_GATE] = imx_clk_gate("slcdc_gate", "hclk", CCM_PCCR0, 25);
+ clk[IMX21_CLK_LCDC_HCLK_GATE] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
+ clk[IMX21_CLK_EMMA_HCLK_GATE] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
+ clk[IMX21_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
+ clk[IMX21_CLK_DMA_HCLK_GATE] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
+ clk[IMX21_CLK_CSI_HCLK_GATE] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
+
+ clk[IMX21_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
+ clk[IMX21_CLK_WDOG_GATE] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
+ clk[IMX21_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
+ clk[IMX21_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
+ clk[IMX21_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
+ clk[IMX21_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
+ clk[IMX21_CLK_RTC_GATE] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
+ clk[IMX21_CLK_KPP_GATE] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
+ clk[IMX21_CLK_OWIRE_GATE] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
+
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
+}
-/*
- * must be called very early to get information about the
- * available clock rate when the timer framework starts
- */
int __init mx21_clocks_init(unsigned long lref, unsigned long href)
{
- int i;
-
- clk[ckil] = imx_clk_fixed("ckil", lref);
- clk[ckih] = imx_clk_fixed("ckih", href);
- clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
- clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
- ARRAY_SIZE(mpll_sel_clks));
- clk[spll_sel] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks,
- ARRAY_SIZE(spll_sel_clks));
- clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
- clk[spll] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
- clk[fclk] = imx_clk_divider("fclk", "mpll", CCM_CSCR, 29, 3);
- clk[hclk] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
- clk[ipg] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
- clk[per1] = imx_clk_divider("per1", "mpll", CCM_PCDR1, 0, 6);
- clk[per2] = imx_clk_divider("per2", "mpll", CCM_PCDR1, 8, 6);
- clk[per3] = imx_clk_divider("per3", "mpll", CCM_PCDR1, 16, 6);
- clk[per4] = imx_clk_divider("per4", "mpll", CCM_PCDR1, 24, 6);
- clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
- clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
- clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
- clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
- clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
- clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
- clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
- clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
- clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
- clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
- clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
- clk[lcdc_hclk_gate] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
- clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
- clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
- clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
- clk[per4_gate] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
- clk[csi_hclk_gate] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
- clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 26, 3);
- clk[usb_gate] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
- clk[usb_hclk_gate] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
- clk[ssi1_gate] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
- clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
- clk[nfc_div] = imx_clk_divider("nfc_div", "ipg", CCM_PCDR0, 12, 4);
- clk[nfc_gate] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
- clk[dma_gate] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
- clk[dma_hclk_gate] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
- clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
- clk[emma_gate] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
- clk[emma_hclk_gate] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
- clk[slcdc_gate] = imx_clk_gate("slcdc_gate", "ipg", CCM_PCCR0, 25);
- clk[slcdc_hclk_gate] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
- clk[wdog_gate] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
- clk[gpio_gate] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
- clk[i2c_gate] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
- clk[kpp_gate] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
- clk[owire_gate] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
- clk[rtc_gate] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
-
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX21 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
-
- clk_register_clkdev(clk[per1], "per1", NULL);
- clk_register_clkdev(clk[per2], "per2", NULL);
- clk_register_clkdev(clk[per3], "per3", NULL);
- clk_register_clkdev(clk[per4], "per4", NULL);
- clk_register_clkdev(clk[per1], "per", "imx21-uart.0");
- clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
- clk_register_clkdev(clk[per1], "per", "imx21-uart.1");
- clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
- clk_register_clkdev(clk[per1], "per", "imx21-uart.2");
- clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
- clk_register_clkdev(clk[per1], "per", "imx21-uart.3");
- clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
- clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[per1], "per", "imx-gpt.0");
- clk_register_clkdev(clk[gpt2_ipg_gate], "ipg", "imx-gpt.1");
- clk_register_clkdev(clk[per1], "per", "imx-gpt.1");
- clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2");
- clk_register_clkdev(clk[per1], "per", "imx-gpt.2");
- clk_register_clkdev(clk[per2], "per", "imx21-cspi.0");
- clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx21-cspi.0");
- clk_register_clkdev(clk[per2], "per", "imx21-cspi.1");
- clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx21-cspi.1");
- clk_register_clkdev(clk[per2], "per", "imx21-cspi.2");
- clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx21-cspi.2");
- clk_register_clkdev(clk[per3], "per", "imx21-fb.0");
- clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
- clk_register_clkdev(clk[lcdc_hclk_gate], "ahb", "imx21-fb.0");
- clk_register_clkdev(clk[usb_gate], "per", "imx21-hcd.0");
- clk_register_clkdev(clk[usb_hclk_gate], "ahb", "imx21-hcd.0");
- clk_register_clkdev(clk[nfc_gate], NULL, "imx21-nand.0");
- clk_register_clkdev(clk[dma_hclk_gate], "ahb", "imx21-dma");
- clk_register_clkdev(clk[dma_gate], "ipg", "imx21-dma");
- clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
- clk_register_clkdev(clk[i2c_gate], NULL, "imx21-i2c.0");
- clk_register_clkdev(clk[kpp_gate], NULL, "mxc-keypad");
- clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
- clk_register_clkdev(clk[brom_gate], "brom", NULL);
- clk_register_clkdev(clk[emma_gate], "emma", NULL);
- clk_register_clkdev(clk[slcdc_gate], "slcdc", NULL);
- clk_register_clkdev(clk[gpio_gate], "gpio", NULL);
- clk_register_clkdev(clk[rtc_gate], "rtc", NULL);
- clk_register_clkdev(clk[csi_hclk_gate], "csi", NULL);
- clk_register_clkdev(clk[ssi1_gate], "ssi1", NULL);
- clk_register_clkdev(clk[ssi2_gate], "ssi2", NULL);
- clk_register_clkdev(clk[sdhc1_ipg_gate], "sdhc1", NULL);
- clk_register_clkdev(clk[sdhc2_ipg_gate], "sdhc2", NULL);
+ ccm = ioremap(MX21_CCM_BASE_ADDR, SZ_2K);
+
+ _mx21_clocks_init(lref, href);
+
+ clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.0");
+ clk_register_clkdev(clk[IMX21_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
+ clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.1");
+ clk_register_clkdev(clk[IMX21_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
+ clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.2");
+ clk_register_clkdev(clk[IMX21_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
+ clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.3");
+ clk_register_clkdev(clk[IMX21_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
+ clk_register_clkdev(clk[IMX21_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.0");
+ clk_register_clkdev(clk[IMX21_CLK_CSPI1_IPG_GATE], "ipg", "imx21-cspi.0");
+ clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.1");
+ clk_register_clkdev(clk[IMX21_CLK_CSPI2_IPG_GATE], "ipg", "imx21-cspi.1");
+ clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.2");
+ clk_register_clkdev(clk[IMX21_CLK_CSPI3_IPG_GATE], "ipg", "imx21-cspi.2");
+ clk_register_clkdev(clk[IMX21_CLK_PER3], "per", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX21_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX21_CLK_LCDC_HCLK_GATE], "ahb", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX21_CLK_USB_GATE], "per", "imx21-hcd.0");
+ clk_register_clkdev(clk[IMX21_CLK_USB_HCLK_GATE], "ahb", "imx21-hcd.0");
+ clk_register_clkdev(clk[IMX21_CLK_NFC_GATE], NULL, "imx21-nand.0");
+ clk_register_clkdev(clk[IMX21_CLK_DMA_HCLK_GATE], "ahb", "imx21-dma");
+ clk_register_clkdev(clk[IMX21_CLK_DMA_GATE], "ipg", "imx21-dma");
+ clk_register_clkdev(clk[IMX21_CLK_WDOG_GATE], NULL, "imx2-wdt.0");
+ clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0");
+ clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0");
mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1);
return 0;
}
+
+static void __init mx21_clocks_init_dt(struct device_node *np)
+{
+ ccm = of_iomap(np, 0);
+
+ _mx21_clocks_init(32768, 26000000);
+
+ clk_data.clks = clk;
+ clk_data.clk_num = ARRAY_SIZE(clk);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(imx27_ccm, "fsl,imx21-ccm", mx21_clocks_init_dt);
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index ae578c096ad8..59c0c8558c6b 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -32,8 +32,6 @@
#include "hardware.h"
#include "mx25.h"
-#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
-
#define CCM_MPCTL 0x00
#define CCM_UPCTL 0x04
#define CCM_CCTL 0x08
@@ -56,7 +54,7 @@
#define CCM_LTR3 0x4c
#define CCM_MCR 0x64
-#define ccm(x) (CRM_BASE + (x))
+#define ccm(x) (ccm_base + (x))
static struct clk_onecell_data clk_data;
@@ -91,9 +89,10 @@ enum mx25_clks {
static struct clk *clk[clk_max];
-static int __init __mx25_clocks_init(unsigned long osc_rate)
+static int __init __mx25_clocks_init(unsigned long osc_rate,
+ void __iomem *ccm_base)
{
- int i;
+ BUG_ON(!ccm_base);
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[osc] = imx_clk_fixed("osc", osc_rate);
@@ -224,19 +223,13 @@ static int __init __mx25_clocks_init(unsigned long osc_rate)
/* CCM_CGCR2(19): reserved in datasheet, but used as wdt in FSL kernel */
clk[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", ccm(CCM_CGCR2), 19);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX25 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_prepare_enable(clk[emi_ahb]);
/* Clock source for gpt must be derived from AHB */
clk_set_parent(clk[per5_sel], clk[ahb]);
- clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-
/*
* Let's initially set up CLKO parent as ipg, since this configuration
* is used on some imx25 board designs to clock the audio codec.
@@ -248,8 +241,14 @@ static int __init __mx25_clocks_init(unsigned long osc_rate)
int __init mx25_clocks_init(void)
{
- __mx25_clocks_init(24000000);
+ void __iomem *ccm;
+ ccm = ioremap(MX25_CRM_BASE_ADDR, SZ_16K);
+
+ __mx25_clocks_init(24000000, ccm);
+
+ clk_register_clkdev(clk[gpt1_ipg], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
/* i.mx25 has the i.mx21 type uart */
clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
@@ -314,29 +313,27 @@ int __init mx25_clocks_init(void)
return 0;
}
-int __init mx25_clocks_init_dt(void)
+static void __init mx25_clocks_init_dt(struct device_node *np)
{
- struct device_node *np;
+ struct device_node *refnp;
unsigned long osc_rate = 24000000;
+ void __iomem *ccm;
/* retrieve the freqency of fixed clocks from device tree */
- for_each_compatible_node(np, NULL, "fixed-clock") {
+ for_each_compatible_node(refnp, NULL, "fixed-clock") {
u32 rate;
- if (of_property_read_u32(np, "clock-frequency", &rate))
+ if (of_property_read_u32(refnp, "clock-frequency", &rate))
continue;
- if (of_device_is_compatible(np, "fsl,imx-osc"))
+ if (of_device_is_compatible(refnp, "fsl,imx-osc"))
osc_rate = rate;
}
- np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
+ ccm = of_iomap(np, 0);
+ __mx25_clocks_init(osc_rate, ccm);
+
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-
- __mx25_clocks_init(osc_rate);
-
- mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt"));
-
- return 0;
}
+CLK_OF_DECLARE(imx25_ccm, "fsl,imx25-ccm", mx25_clocks_init_dt);
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index 317a662626d6..ab6349ec23b9 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -1,61 +1,36 @@
#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <linux/clk-provider.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/imx27-clock.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
-#define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
+static void __iomem *ccm __initdata;
/* Register offsets */
-#define CCM_CSCR IO_ADDR_CCM(0x0)
-#define CCM_MPCTL0 IO_ADDR_CCM(0x4)
-#define CCM_MPCTL1 IO_ADDR_CCM(0x8)
-#define CCM_SPCTL0 IO_ADDR_CCM(0xc)
-#define CCM_SPCTL1 IO_ADDR_CCM(0x10)
-#define CCM_OSC26MCTL IO_ADDR_CCM(0x14)
-#define CCM_PCDR0 IO_ADDR_CCM(0x18)
-#define CCM_PCDR1 IO_ADDR_CCM(0x1c)
-#define CCM_PCCR0 IO_ADDR_CCM(0x20)
-#define CCM_PCCR1 IO_ADDR_CCM(0x24)
-#define CCM_CCSR IO_ADDR_CCM(0x28)
-#define CCM_PMCTL IO_ADDR_CCM(0x2c)
-#define CCM_PMCOUNT IO_ADDR_CCM(0x30)
-#define CCM_WKGDCTL IO_ADDR_CCM(0x34)
-
-#define CCM_CSCR_UPDATE_DIS (1 << 31)
-#define CCM_CSCR_SSI2 (1 << 23)
-#define CCM_CSCR_SSI1 (1 << 22)
-#define CCM_CSCR_VPU (1 << 21)
-#define CCM_CSCR_MSHC (1 << 20)
-#define CCM_CSCR_SPLLRES (1 << 19)
-#define CCM_CSCR_MPLLRES (1 << 18)
-#define CCM_CSCR_SP (1 << 17)
-#define CCM_CSCR_MCU (1 << 16)
-#define CCM_CSCR_OSC26MDIV (1 << 4)
-#define CCM_CSCR_OSC26M (1 << 3)
-#define CCM_CSCR_FPM (1 << 2)
-#define CCM_CSCR_SPEN (1 << 1)
-#define CCM_CSCR_MPEN (1 << 0)
-
-/* i.MX27 TO 2+ */
-#define CCM_CSCR_ARM_SRC (1 << 15)
-
-#define CCM_SPCTL1_LF (1 << 15)
-#define CCM_SPCTL1_BRMO (1 << 6)
+#define CCM_CSCR (ccm + 0x00)
+#define CCM_MPCTL0 (ccm + 0x04)
+#define CCM_MPCTL1 (ccm + 0x08)
+#define CCM_SPCTL0 (ccm + 0x0c)
+#define CCM_SPCTL1 (ccm + 0x10)
+#define CCM_PCDR0 (ccm + 0x18)
+#define CCM_PCDR1 (ccm + 0x1c)
+#define CCM_PCCR0 (ccm + 0x20)
+#define CCM_PCCR1 (ccm + 0x24)
+#define CCM_CCSR (ccm + 0x28)
static const char *vpu_sel_clks[] = { "spll", "mpll_main2", };
static const char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
static const char *mpll_sel_clks[] = { "fpm", "mpll_osc_sel", };
-static const char *mpll_osc_sel_clks[] = { "ckih", "ckih_div1p5", };
+static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", };
static const char *clko_sel_clks[] = {
- "ckil", "fpm", "ckih", "ckih",
- "ckih", "mpll", "spll", "cpu_div",
+ "ckil", "fpm", "ckih_gate", "ckih_gate",
+ "ckih_gate", "mpll", "spll", "cpu_div",
"ahb", "ipg", "per1_div", "per2_div",
"per3_div", "per4_div", "ssi1_div", "ssi2_div",
"nfc_div", "mshc_div", "vpu_div", "60m",
@@ -64,239 +39,220 @@ static const char *clko_sel_clks[] = {
static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
-enum mx27_clks {
- dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
- per2_div, per3_div, per4_div, vpu_sel, vpu_div, usb_div, cpu_sel,
- clko_sel, cpu_div, clko_div, ssi1_sel, ssi2_sel, ssi1_div, ssi2_div,
- clko_en, ssi2_ipg_gate, ssi1_ipg_gate, slcdc_ipg_gate, sdhc3_ipg_gate,
- sdhc2_ipg_gate, sdhc1_ipg_gate, scc_ipg_gate, sahara_ipg_gate,
- rtc_ipg_gate, pwm_ipg_gate, owire_ipg_gate, lcdc_ipg_gate,
- kpp_ipg_gate, iim_ipg_gate, i2c2_ipg_gate, i2c1_ipg_gate,
- gpt6_ipg_gate, gpt5_ipg_gate, gpt4_ipg_gate, gpt3_ipg_gate,
- gpt2_ipg_gate, gpt1_ipg_gate, gpio_ipg_gate, fec_ipg_gate,
- emma_ipg_gate, dma_ipg_gate, cspi3_ipg_gate, cspi2_ipg_gate,
- cspi1_ipg_gate, nfc_baud_gate, ssi2_baud_gate, ssi1_baud_gate,
- vpu_baud_gate, per4_gate, per3_gate, per2_gate, per1_gate,
- usb_ahb_gate, slcdc_ahb_gate, sahara_ahb_gate, lcdc_ahb_gate,
- vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
- csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
- uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
- uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
- mpll_sel, spll_gate, mshc_div, rtic_ipg_gate, mshc_ipg_gate,
- rtic_ahb_gate, mshc_baud_gate, clk_max
-};
-
-static struct clk *clk[clk_max];
+static struct clk *clk[IMX27_CLK_MAX];
static struct clk_onecell_data clk_data;
-int __init mx27_clocks_init(unsigned long fref)
+static void __init _mx27_clocks_init(unsigned long fref)
{
- int i;
- struct device_node *np;
-
- clk[dummy] = imx_clk_fixed("dummy", 0);
- clk[ckih] = imx_clk_fixed("ckih", fref);
- clk[ckil] = imx_clk_fixed("ckil", 32768);
- clk[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
- clk[ckih_div1p5] = imx_clk_fixed_factor("ckih_div1p5", "ckih", 2, 3);
+ BUG_ON(!ccm);
- clk[mpll_osc_sel] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1,
- mpll_osc_sel_clks,
- ARRAY_SIZE(mpll_osc_sel_clks));
- clk[mpll_sel] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks,
- ARRAY_SIZE(mpll_sel_clks));
- clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
- clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
- clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
- clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
+ clk[IMX27_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+ clk[IMX27_CLK_CKIH] = imx_clk_fixed("ckih", fref);
+ clk[IMX27_CLK_CKIL] = imx_clk_fixed("ckil", 32768);
+ clk[IMX27_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
+ clk[IMX27_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3);
+ clk[IMX27_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
+ clk[IMX27_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
+ clk[IMX27_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
+ clk[IMX27_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
+ clk[IMX27_CLK_SPLL] = imx_clk_pllv1("spll", "ckih_gate", CCM_SPCTL0);
+ clk[IMX27_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
+ clk[IMX27_CLK_MPLL_MAIN2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
- clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
- clk[ipg] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
+ clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
+ clk[IMX27_CLK_IPG] = imx_clk_fixed_factor("ipg", "ahb", 1, 2);
} else {
- clk[ahb] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
- clk[ipg] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
+ clk[IMX27_CLK_AHB] = imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 9, 4);
+ clk[IMX27_CLK_IPG] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1);
}
- clk[mshc_div] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6);
- clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
- clk[per1_div] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
- clk[per2_div] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
- clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
- clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
- clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
- clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
- clk[usb_div] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
- clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
- clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+ clk[IMX27_CLK_MSHC_DIV] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6);
+ clk[IMX27_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
+ clk[IMX27_CLK_PER1_DIV] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
+ clk[IMX27_CLK_PER2_DIV] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
+ clk[IMX27_CLK_PER3_DIV] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
+ clk[IMX27_CLK_PER4_DIV] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
+ clk[IMX27_CLK_VPU_SEL] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
+ clk[IMX27_CLK_VPU_DIV] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
+ clk[IMX27_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
+ clk[IMX27_CLK_CPU_SEL] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
+ clk[IMX27_CLK_CLKO_SEL] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
+
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
- clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
+ clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
else
- clk[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
- clk[clko_div] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
- clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
- clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
- clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
- clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
- clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
- clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
- clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
- clk[slcdc_ipg_gate] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
- clk[sdhc3_ipg_gate] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
- clk[sdhc2_ipg_gate] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
- clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
- clk[scc_ipg_gate] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
- clk[sahara_ipg_gate] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
- clk[rtic_ipg_gate] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8);
- clk[rtc_ipg_gate] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
- clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
- clk[owire_ipg_gate] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
- clk[mshc_ipg_gate] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13);
- clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
- clk[kpp_ipg_gate] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
- clk[iim_ipg_gate] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
- clk[i2c2_ipg_gate] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
- clk[i2c1_ipg_gate] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
- clk[gpt6_ipg_gate] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
- clk[gpt5_ipg_gate] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
- clk[gpt4_ipg_gate] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
- clk[gpt3_ipg_gate] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
- clk[gpt2_ipg_gate] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
- clk[gpt1_ipg_gate] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
- clk[gpio_ipg_gate] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
- clk[fec_ipg_gate] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
- clk[emma_ipg_gate] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
- clk[dma_ipg_gate] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
- clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
- clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
- clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
- clk[mshc_baud_gate] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2);
- clk[nfc_baud_gate] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1, 3);
- clk[ssi2_baud_gate] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1, 4);
- clk[ssi1_baud_gate] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1, 5);
- clk[vpu_baud_gate] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1, 6);
- clk[per4_gate] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1, 7);
- clk[per3_gate] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1, 8);
- clk[per2_gate] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1, 9);
- clk[per1_gate] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
- clk[usb_ahb_gate] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
- clk[slcdc_ahb_gate] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
- clk[sahara_ahb_gate] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
- clk[rtic_ahb_gate] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14);
- clk[lcdc_ahb_gate] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
- clk[vpu_ahb_gate] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
- clk[fec_ahb_gate] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
- clk[emma_ahb_gate] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
- clk[emi_ahb_gate] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
- clk[dma_ahb_gate] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
- clk[csi_ahb_gate] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
- clk[brom_ahb_gate] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
- clk[ata_ahb_gate] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
- clk[wdog_ipg_gate] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
- clk[usb_ipg_gate] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
- clk[uart6_ipg_gate] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
- clk[uart5_ipg_gate] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
- clk[uart4_ipg_gate] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
- clk[uart3_ipg_gate] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
- clk[uart2_ipg_gate] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
- clk[uart1_ipg_gate] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
+ clk[IMX27_CLK_CPU_DIV] = imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 13, 3);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX27 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ clk[IMX27_CLK_CLKO_DIV] = imx_clk_divider("clko_div", "clko_sel", CCM_PCDR0, 22, 3);
+ clk[IMX27_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+ clk[IMX27_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
+ clk[IMX27_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
+ clk[IMX27_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
+ clk[IMX27_CLK_CLKO_EN] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
+ clk[IMX27_CLK_SSI2_IPG_GATE] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
+ clk[IMX27_CLK_SSI1_IPG_GATE] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
+ clk[IMX27_CLK_SLCDC_IPG_GATE] = imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
+ clk[IMX27_CLK_SDHC3_IPG_GATE] = imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
+ clk[IMX27_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
+ clk[IMX27_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
+ clk[IMX27_CLK_SCC_IPG_GATE] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
+ clk[IMX27_CLK_SAHARA_IPG_GATE] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
+ clk[IMX27_CLK_RTIC_IPG_GATE] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8);
+ clk[IMX27_CLK_RTC_IPG_GATE] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
+ clk[IMX27_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
+ clk[IMX27_CLK_OWIRE_IPG_GATE] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
+ clk[IMX27_CLK_MSHC_IPG_GATE] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13);
+ clk[IMX27_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
+ clk[IMX27_CLK_KPP_IPG_GATE] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
+ clk[IMX27_CLK_IIM_IPG_GATE] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
+ clk[IMX27_CLK_I2C2_IPG_GATE] = imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
+ clk[IMX27_CLK_I2C1_IPG_GATE] = imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
+ clk[IMX27_CLK_GPT6_IPG_GATE] = imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
+ clk[IMX27_CLK_GPT5_IPG_GATE] = imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
+ clk[IMX27_CLK_GPT4_IPG_GATE] = imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
+ clk[IMX27_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
+ clk[IMX27_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
+ clk[IMX27_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
+ clk[IMX27_CLK_GPIO_IPG_GATE] = imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
+ clk[IMX27_CLK_FEC_IPG_GATE] = imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
+ clk[IMX27_CLK_EMMA_IPG_GATE] = imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
+ clk[IMX27_CLK_DMA_IPG_GATE] = imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
+ clk[IMX27_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
+ clk[IMX27_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
+ clk[IMX27_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
+ clk[IMX27_CLK_MSHC_BAUD_GATE] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2);
+ clk[IMX27_CLK_NFC_BAUD_GATE] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1, 3);
+ clk[IMX27_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1, 4);
+ clk[IMX27_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1, 5);
+ clk[IMX27_CLK_VPU_BAUD_GATE] = imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1, 6);
+ clk[IMX27_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1, 7);
+ clk[IMX27_CLK_PER3_GATE] = imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1, 8);
+ clk[IMX27_CLK_PER2_GATE] = imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1, 9);
+ clk[IMX27_CLK_PER1_GATE] = imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
+ clk[IMX27_CLK_USB_AHB_GATE] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
+ clk[IMX27_CLK_SLCDC_AHB_GATE] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
+ clk[IMX27_CLK_SAHARA_AHB_GATE] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
+ clk[IMX27_CLK_RTIC_AHB_GATE] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14);
+ clk[IMX27_CLK_LCDC_AHB_GATE] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
+ clk[IMX27_CLK_VPU_AHB_GATE] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
+ clk[IMX27_CLK_FEC_AHB_GATE] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
+ clk[IMX27_CLK_EMMA_AHB_GATE] = imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
+ clk[IMX27_CLK_EMI_AHB_GATE] = imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
+ clk[IMX27_CLK_DMA_AHB_GATE] = imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
+ clk[IMX27_CLK_CSI_AHB_GATE] = imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
+ clk[IMX27_CLK_BROM_AHB_GATE] = imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
+ clk[IMX27_CLK_ATA_AHB_GATE] = imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
+ clk[IMX27_CLK_WDOG_IPG_GATE] = imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
+ clk[IMX27_CLK_USB_IPG_GATE] = imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
+ clk[IMX27_CLK_UART6_IPG_GATE] = imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
+ clk[IMX27_CLK_UART5_IPG_GATE] = imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
+ clk[IMX27_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
+ clk[IMX27_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
+ clk[IMX27_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
+ clk[IMX27_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
- np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
- if (np) {
- clk_data.clks = clk;
- clk_data.clk_num = ARRAY_SIZE(clk);
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- }
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
- clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.0");
- clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.1");
- clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.2");
- clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.3");
- clk_register_clkdev(clk[uart5_ipg_gate], "ipg", "imx21-uart.4");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.4");
- clk_register_clkdev(clk[uart6_ipg_gate], "ipg", "imx21-uart.5");
- clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.5");
- clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.0");
- clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0");
- clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0");
- clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1");
- clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.1");
- clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.2");
- clk_register_clkdev(clk[sdhc2_ipg_gate], "ipg", "imx21-mmc.2");
- clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.0");
- clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx27-cspi.0");
- clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.1");
- clk_register_clkdev(clk[cspi2_ipg_gate], "ipg", "imx27-cspi.1");
- clk_register_clkdev(clk[per2_gate], "per", "imx27-cspi.2");
- clk_register_clkdev(clk[cspi3_ipg_gate], "ipg", "imx27-cspi.2");
- clk_register_clkdev(clk[per3_gate], "per", "imx21-fb.0");
- clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx21-fb.0");
- clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
- clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
- clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
- clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
- clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27");
- clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27");
- clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
- clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
- clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
- clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
- clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.1");
- clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.1");
- clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
- clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.2");
- clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.2");
- clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
- clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
- clk_register_clkdev(clk[nfc_baud_gate], NULL, "imx27-nand.0");
- clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
- clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
- clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx27-dma");
- clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx27-dma");
- clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
- clk_register_clkdev(clk[fec_ahb_gate], "ahb", "imx27-fec.0");
- clk_register_clkdev(clk[wdog_ipg_gate], NULL, "imx2-wdt.0");
- clk_register_clkdev(clk[i2c1_ipg_gate], NULL, "imx21-i2c.0");
- clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx21-i2c.1");
- clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");
- clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad");
- clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "imx27-camera.0");
- clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "imx27-camera.0");
- clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0");
- clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0");
- clk_register_clkdev(clk[cpu_div], NULL, "cpu0");
+ clk_register_clkdev(clk[IMX27_CLK_CPU_DIV], NULL, "cpu0");
- mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
-
- clk_prepare_enable(clk[emi_ahb_gate]);
+ clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
imx_print_silicon_rev("i.MX27", mx27_revision());
+}
+
+int __init mx27_clocks_init(unsigned long fref)
+{
+ ccm = ioremap(MX27_CCM_BASE_ADDR, SZ_4K);
+
+ _mx27_clocks_init(fref);
+
+ clk_register_clkdev(clk[IMX27_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.0");
+ clk_register_clkdev(clk[IMX27_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.1");
+ clk_register_clkdev(clk[IMX27_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.2");
+ clk_register_clkdev(clk[IMX27_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.3");
+ clk_register_clkdev(clk[IMX27_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.4");
+ clk_register_clkdev(clk[IMX27_CLK_UART6_IPG_GATE], "ipg", "imx21-uart.5");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx21-uart.5");
+ clk_register_clkdev(clk[IMX27_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER1_GATE], "per", "imx-gpt.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.0");
+ clk_register_clkdev(clk[IMX27_CLK_SDHC1_IPG_GATE], "ipg", "imx21-mmc.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.1");
+ clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.1");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx21-mmc.2");
+ clk_register_clkdev(clk[IMX27_CLK_SDHC2_IPG_GATE], "ipg", "imx21-mmc.2");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.0");
+ clk_register_clkdev(clk[IMX27_CLK_CSPI1_IPG_GATE], "ipg", "imx27-cspi.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.1");
+ clk_register_clkdev(clk[IMX27_CLK_CSPI2_IPG_GATE], "ipg", "imx27-cspi.1");
+ clk_register_clkdev(clk[IMX27_CLK_PER2_GATE], "per", "imx27-cspi.2");
+ clk_register_clkdev(clk[IMX27_CLK_CSPI3_IPG_GATE], "ipg", "imx27-cspi.2");
+ clk_register_clkdev(clk[IMX27_CLK_PER3_GATE], "per", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX27_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX27_CLK_LCDC_AHB_GATE], "ahb", "imx21-fb.0");
+ clk_register_clkdev(clk[IMX27_CLK_CSI_AHB_GATE], "ahb", "imx27-camera.0");
+ clk_register_clkdev(clk[IMX27_CLK_PER4_GATE], "per", "imx27-camera.0");
+ clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "imx-udc-mx27");
+ clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "imx-udc-mx27");
+ clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "imx-udc-mx27");
+ clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.0");
+ clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.0");
+ clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.0");
+ clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.1");
+ clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.1");
+ clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.1");
+ clk_register_clkdev(clk[IMX27_CLK_USB_DIV], "per", "mxc-ehci.2");
+ clk_register_clkdev(clk[IMX27_CLK_USB_IPG_GATE], "ipg", "mxc-ehci.2");
+ clk_register_clkdev(clk[IMX27_CLK_USB_AHB_GATE], "ahb", "mxc-ehci.2");
+ clk_register_clkdev(clk[IMX27_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0");
+ clk_register_clkdev(clk[IMX27_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1");
+ clk_register_clkdev(clk[IMX27_CLK_NFC_BAUD_GATE], NULL, "imx27-nand.0");
+ clk_register_clkdev(clk[IMX27_CLK_VPU_BAUD_GATE], "per", "coda-imx27.0");
+ clk_register_clkdev(clk[IMX27_CLK_VPU_AHB_GATE], "ahb", "coda-imx27.0");
+ clk_register_clkdev(clk[IMX27_CLK_DMA_AHB_GATE], "ahb", "imx27-dma");
+ clk_register_clkdev(clk[IMX27_CLK_DMA_IPG_GATE], "ipg", "imx27-dma");
+ clk_register_clkdev(clk[IMX27_CLK_FEC_IPG_GATE], "ipg", "imx27-fec.0");
+ clk_register_clkdev(clk[IMX27_CLK_FEC_AHB_GATE], "ahb", "imx27-fec.0");
+ clk_register_clkdev(clk[IMX27_CLK_WDOG_IPG_GATE], NULL, "imx2-wdt.0");
+ clk_register_clkdev(clk[IMX27_CLK_I2C1_IPG_GATE], NULL, "imx21-i2c.0");
+ clk_register_clkdev(clk[IMX27_CLK_I2C2_IPG_GATE], NULL, "imx21-i2c.1");
+ clk_register_clkdev(clk[IMX27_CLK_OWIRE_IPG_GATE], NULL, "mxc_w1.0");
+ clk_register_clkdev(clk[IMX27_CLK_KPP_IPG_GATE], NULL, "imx-keypad");
+ clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "emma-ahb", "imx27-camera.0");
+ clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "emma-ipg", "imx27-camera.0");
+ clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0");
+ clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0");
+
+ mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
return 0;
}
-int __init mx27_clocks_init_dt(void)
+static void __init mx27_clocks_init_dt(struct device_node *np)
{
- struct device_node *np;
+ struct device_node *refnp;
u32 fref = 26000000; /* default */
- for_each_compatible_node(np, NULL, "fixed-clock") {
- if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
+ for_each_compatible_node(refnp, NULL, "fixed-clock") {
+ if (!of_device_is_compatible(refnp, "fsl,imx-osc26m"))
continue;
- if (!of_property_read_u32(np, "clock-frequency", &fref))
+ if (!of_property_read_u32(refnp, "clock-frequency", &fref))
break;
}
- return mx27_clocks_init(fref);
+ ccm = of_iomap(np, 0);
+
+ _mx27_clocks_init(fref);
+
+ clk_data.clks = clk;
+ clk_data.clk_num = ARRAY_SIZE(clk);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
+CLK_OF_DECLARE(imx27_ccm, "fsl,imx27-ccm", mx27_clocks_init_dt);
diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c
index 4a9de0835eb1..286ef422cebc 100644
--- a/arch/arm/mach-imx/clk-imx31.c
+++ b/arch/arm/mach-imx/clk-imx31.c
@@ -51,7 +51,6 @@ static struct clk_onecell_data clk_data;
int __init mx31_clocks_init(unsigned long fref)
{
void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
- int i;
struct device_node *np;
clk[dummy] = imx_clk_fixed("dummy", 0);
@@ -114,10 +113,7 @@ int __init mx31_clocks_init(unsigned long fref)
clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MXC_CCM_CGR2, 10);
clk[firi_gate] = imx_clk_gate2("firi_gate", "upll", base+MXC_CCM_CGR2, 12);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("imx31 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index 71c86a2f856d..a0d2b57fd376 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -75,7 +75,6 @@ int __init mx35_clocks_init(void)
u32 pdr0, consumer_sel, hsp_sel;
struct arm_ahb_div *aad;
unsigned char *hsp_div;
- u32 i;
pdr0 = __raw_readl(base + MXC_CCM_PDR0);
consumer_sel = (pdr0 >> 16) & 0xf;
@@ -200,10 +199,7 @@ int __init mx35_clocks_init(void)
clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MX35_CCM_CGR3, 2);
clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "ahb", base + MX35_CCM_CGR3, 4);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX35 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 21d2b111c83d..72d65214223e 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -18,11 +18,54 @@
#include <linux/of_irq.h>
#include <dt-bindings/clock/imx5-clock.h>
-#include "crm-regs-imx5.h"
#include "clk.h"
#include "common.h"
#include "hardware.h"
+#define MX51_DPLL1_BASE 0x83f80000
+#define MX51_DPLL2_BASE 0x83f84000
+#define MX51_DPLL3_BASE 0x83f88000
+
+#define MX53_DPLL1_BASE 0x63f80000
+#define MX53_DPLL2_BASE 0x63f84000
+#define MX53_DPLL3_BASE 0x63f88000
+#define MX53_DPLL4_BASE 0x63f8c000
+
+#define MXC_CCM_CCR (ccm_base + 0x00)
+#define MXC_CCM_CCDR (ccm_base + 0x04)
+#define MXC_CCM_CSR (ccm_base + 0x08)
+#define MXC_CCM_CCSR (ccm_base + 0x0c)
+#define MXC_CCM_CACRR (ccm_base + 0x10)
+#define MXC_CCM_CBCDR (ccm_base + 0x14)
+#define MXC_CCM_CBCMR (ccm_base + 0x18)
+#define MXC_CCM_CSCMR1 (ccm_base + 0x1c)
+#define MXC_CCM_CSCMR2 (ccm_base + 0x20)
+#define MXC_CCM_CSCDR1 (ccm_base + 0x24)
+#define MXC_CCM_CS1CDR (ccm_base + 0x28)
+#define MXC_CCM_CS2CDR (ccm_base + 0x2c)
+#define MXC_CCM_CDCDR (ccm_base + 0x30)
+#define MXC_CCM_CHSCDR (ccm_base + 0x34)
+#define MXC_CCM_CSCDR2 (ccm_base + 0x38)
+#define MXC_CCM_CSCDR3 (ccm_base + 0x3c)
+#define MXC_CCM_CSCDR4 (ccm_base + 0x40)
+#define MXC_CCM_CWDR (ccm_base + 0x44)
+#define MXC_CCM_CDHIPR (ccm_base + 0x48)
+#define MXC_CCM_CDCR (ccm_base + 0x4c)
+#define MXC_CCM_CTOR (ccm_base + 0x50)
+#define MXC_CCM_CLPCR (ccm_base + 0x54)
+#define MXC_CCM_CISR (ccm_base + 0x58)
+#define MXC_CCM_CIMR (ccm_base + 0x5c)
+#define MXC_CCM_CCOSR (ccm_base + 0x60)
+#define MXC_CCM_CGPR (ccm_base + 0x64)
+#define MXC_CCM_CCGR0 (ccm_base + 0x68)
+#define MXC_CCM_CCGR1 (ccm_base + 0x6c)
+#define MXC_CCM_CCGR2 (ccm_base + 0x70)
+#define MXC_CCM_CCGR3 (ccm_base + 0x74)
+#define MXC_CCM_CCGR4 (ccm_base + 0x78)
+#define MXC_CCM_CCGR5 (ccm_base + 0x7c)
+#define MXC_CCM_CCGR6 (ccm_base + 0x80)
+#define MXC_CCM_CCGR7 (ccm_base + 0x84)
+
/* Low-power Audio Playback Mode clock */
static const char *lp_apm_sel[] = { "osc", };
@@ -86,17 +129,15 @@ static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
static struct clk *clk[IMX5_CLK_END];
static struct clk_onecell_data clk_data;
-static void __init mx5_clocks_common_init(unsigned long rate_ckil,
- unsigned long rate_osc, unsigned long rate_ckih1,
- unsigned long rate_ckih2)
+static void __init mx5_clocks_common_init(void __iomem *ccm_base)
{
- int i;
+ imx5_pm_set_ccm_base(ccm_base);
clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
- clk[IMX5_CLK_CKIL] = imx_obtain_fixed_clock("ckil", rate_ckil);
- clk[IMX5_CLK_OSC] = imx_obtain_fixed_clock("osc", rate_osc);
- clk[IMX5_CLK_CKIH1] = imx_obtain_fixed_clock("ckih1", rate_ckih1);
- clk[IMX5_CLK_CKIH2] = imx_obtain_fixed_clock("ckih2", rate_ckih2);
+ clk[IMX5_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
+ clk[IMX5_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
+ clk[IMX5_CLK_CKIH1] = imx_obtain_fixed_clock("ckih1", 0);
+ clk[IMX5_CLK_CKIH2] = imx_obtain_fixed_clock("ckih2", 0);
clk[IMX5_CLK_PERIPH_APM] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
@@ -244,58 +285,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
clk[IMX5_CLK_SAHARA_IPG_GATE] = imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14);
clk[IMX5_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX5 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
-
- clk_register_clkdev(clk[IMX5_CLK_GPT_HF_GATE], "per", "imx-gpt.0");
- clk_register_clkdev(clk[IMX5_CLK_GPT_IPG_GATE], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[IMX5_CLK_UART1_PER_GATE], "per", "imx21-uart.0");
- clk_register_clkdev(clk[IMX5_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
- clk_register_clkdev(clk[IMX5_CLK_UART2_PER_GATE], "per", "imx21-uart.1");
- clk_register_clkdev(clk[IMX5_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
- clk_register_clkdev(clk[IMX5_CLK_UART3_PER_GATE], "per", "imx21-uart.2");
- clk_register_clkdev(clk[IMX5_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
- clk_register_clkdev(clk[IMX5_CLK_UART4_PER_GATE], "per", "imx21-uart.3");
- clk_register_clkdev(clk[IMX5_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
- clk_register_clkdev(clk[IMX5_CLK_UART5_PER_GATE], "per", "imx21-uart.4");
- clk_register_clkdev(clk[IMX5_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4");
- clk_register_clkdev(clk[IMX5_CLK_ECSPI1_PER_GATE], "per", "imx51-ecspi.0");
- clk_register_clkdev(clk[IMX5_CLK_ECSPI1_IPG_GATE], "ipg", "imx51-ecspi.0");
- clk_register_clkdev(clk[IMX5_CLK_ECSPI2_PER_GATE], "per", "imx51-ecspi.1");
- clk_register_clkdev(clk[IMX5_CLK_ECSPI2_IPG_GATE], "ipg", "imx51-ecspi.1");
- clk_register_clkdev(clk[IMX5_CLK_CSPI_IPG_GATE], NULL, "imx35-cspi.2");
- clk_register_clkdev(clk[IMX5_CLK_I2C1_GATE], NULL, "imx21-i2c.0");
- clk_register_clkdev(clk[IMX5_CLK_I2C2_GATE], NULL, "imx21-i2c.1");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.0");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.0");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.0");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.1");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.1");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.1");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.2");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.2");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.2");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "imx-udc-mx51");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "imx-udc-mx51");
- clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "imx-udc-mx51");
- clk_register_clkdev(clk[IMX5_CLK_NFC_GATE], NULL, "imx51-nand");
- clk_register_clkdev(clk[IMX5_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0");
- clk_register_clkdev(clk[IMX5_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1");
- clk_register_clkdev(clk[IMX5_CLK_SSI3_IPG_GATE], NULL, "imx-ssi.2");
- clk_register_clkdev(clk[IMX5_CLK_SDMA_GATE], NULL, "imx35-sdma");
clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
- clk_register_clkdev(clk[IMX5_CLK_IIM_GATE], "iim", NULL);
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.0");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.1");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx-keypad");
- clk_register_clkdev(clk[IMX5_CLK_IPU_DI1_GATE], "di1", "imx-tve.0");
clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
- clk_register_clkdev(clk[IMX5_CLK_EPIT1_IPG_GATE], "ipg", "imx-epit.0");
- clk_register_clkdev(clk[IMX5_CLK_EPIT1_HF_GATE], "per", "imx-epit.0");
- clk_register_clkdev(clk[IMX5_CLK_EPIT2_IPG_GATE], "ipg", "imx-epit.1");
- clk_register_clkdev(clk[IMX5_CLK_EPIT2_HF_GATE], "per", "imx-epit.1");
/* Set SDHC parents to be PLL2 */
clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
@@ -322,12 +313,26 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
static void __init mx50_clocks_init(struct device_node *np)
{
+ void __iomem *ccm_base;
+ void __iomem *pll_base;
unsigned long r;
- int i;
- clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
- clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
- clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
+ pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+ ccm_base = of_iomap(np, 0);
+ WARN_ON(!ccm_base);
+
+ mx5_clocks_common_init(ccm_base);
clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
@@ -349,17 +354,12 @@ static void __init mx50_clocks_init(struct device_node *np)
clk[IMX5_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
clk[IMX5_CLK_CKO2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX50 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- mx5_clocks_common_init(0, 0, 0, 0);
-
/* set SDHC root clock to 200MHZ*/
clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
@@ -370,21 +370,32 @@ static void __init mx50_clocks_init(struct device_node *np)
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
-
- mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt"));
}
CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
-int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
- unsigned long rate_ckih1, unsigned long rate_ckih2)
+static void __init mx51_clocks_init(struct device_node *np)
{
- int i;
+ void __iomem *ccm_base;
+ void __iomem *pll_base;
u32 val;
- struct device_node *np;
- clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
- clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
- clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
+ pll_base = ioremap(MX51_DPLL1_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX51_DPLL2_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX51_DPLL3_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+ ccm_base = of_iomap(np, 0);
+ WARN_ON(!ccm_base);
+
+ mx5_clocks_common_init(ccm_base);
+
clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
@@ -417,35 +428,12 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel));
clk[IMX5_CLK_SPDIF1_GATE] = imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28);
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX51 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
- np = of_find_compatible_node(NULL, NULL, "fsl,imx51-ccm");
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
-
- clk_register_clkdev(clk[IMX5_CLK_HSI2C_GATE], NULL, "imx21-i2c.2");
- clk_register_clkdev(clk[IMX5_CLK_MX51_MIPI], "mipi_hsp", NULL);
- clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx27-fec.0");
- clk_register_clkdev(clk[IMX5_CLK_USB_PHY_GATE], "phy", "mxc-ehci.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx51.0");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx51.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx51.1");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.1");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx51.1");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx51.2");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.2");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx51.2");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx51.3");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.3");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx51.3");
-
/* set the usboh3 parent to pll2_sw */
clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
@@ -453,9 +441,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
- /* System timer */
- mxc_timer_init(MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_INT_GPT);
-
clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
imx_print_silicon_rev("i.MX51", mx51_revision());
clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
@@ -474,25 +459,35 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
val = readl(MXC_CCM_CLPCR);
val |= 1 << 23;
writel(val, MXC_CCM_CLPCR);
-
- return 0;
-}
-
-static void __init mx51_clocks_init_dt(struct device_node *np)
-{
- mx51_clocks_init(0, 0, 0, 0);
}
-CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
+CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
static void __init mx53_clocks_init(struct device_node *np)
{
- int i;
+ void __iomem *ccm_base;
+ void __iomem *pll_base;
unsigned long r;
- clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
- clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
- clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
- clk[IMX5_CLK_PLL4_SW] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
+ pll_base = ioremap(MX53_DPLL1_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX53_DPLL2_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX53_DPLL3_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL3_SW] = imx_clk_pllv2("pll3_sw", "osc", pll_base);
+
+ pll_base = ioremap(MX53_DPLL4_BASE, SZ_16K);
+ WARN_ON(!pll_base);
+ clk[IMX5_CLK_PLL4_SW] = imx_clk_pllv2("pll4_sw", "osc", pll_base);
+
+ ccm_base = of_iomap(np, 0);
+ WARN_ON(!ccm_base);
+
+ mx5_clocks_common_init(ccm_base);
clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
@@ -543,33 +538,12 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_SPDIF_XTAL_SEL] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX53 clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- mx5_clocks_common_init(0, 0, 0, 0);
-
- clk_register_clkdev(clk[IMX5_CLK_I2C3_GATE], NULL, "imx21-i2c.2");
- clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx25-fec.0");
- clk_register_clkdev(clk[IMX5_CLK_USB_PHY1_GATE], "usb_phy1", "mxc-ehci.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx53.0");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx53.0");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx53.1");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.1");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx53.1");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx53.2");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.2");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx53.2");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx53.3");
- clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.3");
- clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx53.3");
-
/* set SDHC root clock to 200MHZ*/
clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
@@ -583,7 +557,5 @@ static void __init mx53_clocks_init(struct device_node *np)
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
-
- mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt"));
}
CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 8556c787e59c..6cceb7765c14 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <dt-bindings/clock/imx6qdl-clock.h>
#include "clk.h"
#include "common.h"
@@ -73,48 +74,13 @@ static const char *lvds_sels[] = {
"pcie_ref_125m", "sata_ref_100m",
};
-enum mx6q_clks {
- dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
- pll3_pfd0_720m, pll3_pfd1_540m, pll3_pfd2_508m, pll3_pfd3_454m,
- pll2_198m, pll3_120m, pll3_80m, pll3_60m, twd, step, pll1_sw,
- periph_pre, periph2_pre, periph_clk2_sel, periph2_clk2_sel, axi_sel,
- esai_sel, asrc_sel, spdif_sel, gpu2d_axi, gpu3d_axi, gpu2d_core_sel,
- gpu3d_core_sel, gpu3d_shader_sel, ipu1_sel, ipu2_sel, ldb_di0_sel,
- ldb_di1_sel, ipu1_di0_pre_sel, ipu1_di1_pre_sel, ipu2_di0_pre_sel,
- ipu2_di1_pre_sel, ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel,
- ipu2_di1_sel, hsi_tx_sel, pcie_axi_sel, ssi1_sel, ssi2_sel, ssi3_sel,
- usdhc1_sel, usdhc2_sel, usdhc3_sel, usdhc4_sel, enfc_sel, emi_sel,
- emi_slow_sel, vdo_axi_sel, vpu_axi_sel, cko1_sel, periph, periph2,
- periph_clk2, periph2_clk2, ipg, ipg_per, esai_pred, esai_podf,
- asrc_pred, asrc_podf, spdif_pred, spdif_podf, can_root, ecspi_root,
- gpu2d_core_podf, gpu3d_core_podf, gpu3d_shader, ipu1_podf, ipu2_podf,
- ldb_di0_podf, ldb_di1_podf, ipu1_di0_pre, ipu1_di1_pre, ipu2_di0_pre,
- ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, ssi2_pred, ssi2_podf,
- ssi3_pred, ssi3_podf, uart_serial_podf, usdhc1_podf, usdhc2_podf,
- usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, emi_podf,
- emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf,
- mmdc_ch1_axi_podf, arm, ahb, apbh_dma, asrc, can1_ipg, can1_serial,
- can2_ipg, can2_serial, ecspi1, ecspi2, ecspi3, ecspi4, ecspi5, enet,
- esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
- hdmi_isfr, i2c1, i2c2, i2c3, iim, enfc, ipu1, ipu1_di0, ipu1_di1, ipu2,
- ipu2_di0, ldb_di0, ldb_di1, ipu2_di1, hsi_tx, mlb, mmdc_ch0_axi,
- mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4, per1_bch,
- gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
- ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
- usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
- pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
- ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
- sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
- usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
- spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
- lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, esai_ahb, clk_max
-};
-
-static struct clk *clk[clk_max];
+static struct clk *clk[IMX6QDL_CLK_END];
static struct clk_onecell_data clk_data;
-static enum mx6q_clks const clks_init_on[] __initconst = {
- mmdc_ch0_axi, rom, arm,
+static unsigned int const clks_init_on[] __initconst = {
+ IMX6QDL_CLK_MMDC_CH0_AXI,
+ IMX6QDL_CLK_ROM,
+ IMX6QDL_CLK_ARM,
};
static struct clk_div_table clk_enet_ref_table[] = {
@@ -149,10 +115,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
int i;
int ret;
- clk[dummy] = imx_clk_fixed("dummy", 0);
- clk[ckil] = imx_obtain_fixed_clock("ckil", 0);
- clk[ckih] = imx_obtain_fixed_clock("ckih1", 0);
- clk[osc] = imx_obtain_fixed_clock("osc", 0);
+ clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+ clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
+ clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0);
+ clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
base = of_iomap(np, 0);
@@ -166,14 +132,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
video_div_table[2].div = 1;
};
- /* type name parent_name base div_mask */
- clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f);
- clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1);
- clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3);
- clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f);
- clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f);
- clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3);
- clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3);
+ /* type name parent_name base div_mask */
+ clk[IMX6QDL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f);
+ clk[IMX6QDL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1);
+ clk[IMX6QDL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3);
+ clk[IMX6QDL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f);
+ clk[IMX6QDL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f);
+ clk[IMX6QDL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3);
+ clk[IMX6QDL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3);
/*
* Bit 20 is the reserved and read-only bit, we do this only for:
@@ -181,28 +147,28 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
* - Keep refcount when do usbphy clk_enable/disable, in that case,
* the clk framework may need to enable/disable usbphy's parent
*/
- clk[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
- clk[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+ clk[IMX6QDL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+ clk[IMX6QDL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
/*
* usbphy*_gate needs to be on after system boots up, and software
* never needs to control it anymore.
*/
- clk[usbphy1_gate] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
- clk[usbphy2_gate] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+ clk[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+ clk[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
- clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
- clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+ clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
+ clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
- clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
- clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
+ clk[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
+ clk[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
- clk[enet_ref] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+ clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
base + 0xe0, 0, 2, 0, clk_enet_ref_table,
&imx_ccm_lock);
- clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
- clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+ clk[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+ clk[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
/*
* lvds1_gate and lvds2_gate are pseudo-gates. Both can be
@@ -210,29 +176,29 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
* the "output_enable" bit as a gate, even though it's really just
* enabling clock output.
*/
- clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
- clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
-
- /* name parent_name reg idx */
- clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
- clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
- clk[pll2_pfd2_396m] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
- clk[pll3_pfd0_720m] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
- clk[pll3_pfd1_540m] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
- clk[pll3_pfd2_508m] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
- clk[pll3_pfd3_454m] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
-
- /* name parent_name mult div */
- clk[pll2_198m] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
- clk[pll3_120m] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
- clk[pll3_80m] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
- clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
- clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);
-
- clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
- clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10);
+ clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11);
+
+ /* name parent_name reg idx */
+ clk[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
+ clk[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
+ clk[IMX6QDL_CLK_PLL3_PFD0_720M] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
+ clk[IMX6QDL_CLK_PLL3_PFD1_540M] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
+ clk[IMX6QDL_CLK_PLL3_PFD2_508M] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
+ clk[IMX6QDL_CLK_PLL3_PFD3_454M] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
+
+ /* name parent_name mult div */
+ clk[IMX6QDL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+ clk[IMX6QDL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4);
+ clk[IMX6QDL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
+ clk[IMX6QDL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
+ clk[IMX6QDL_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2);
+
+ clk[IMX6QDL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[IMX6QDL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
np = ccm_node;
base = of_iomap(np, 0);
@@ -240,262 +206,254 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
imx6q_pm_set_ccm_base(base);
- /* name reg shift width parent_names num_parents */
- clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
- clk[pll1_sw] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
- clk[periph_pre] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
- clk[periph2_pre] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
- clk[periph_clk2_sel] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
- clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
- clk[axi_sel] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
- clk[esai_sel] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
- clk[asrc_sel] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
- clk[spdif_sel] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
- clk[gpu2d_axi] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
- clk[gpu3d_axi] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
- clk[gpu2d_core_sel] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels, ARRAY_SIZE(gpu2d_core_sels));
- clk[gpu3d_core_sel] = imx_clk_mux("gpu3d_core_sel", base + 0x18, 4, 2, gpu3d_core_sels, ARRAY_SIZE(gpu3d_core_sels));
- clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
- clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
- clk[ipu1_di0_sel] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
- clk[ipu1_di1_sel] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
- clk[ipu2_di0_sel] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
- clk[ipu2_di1_sel] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
- clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels));
- clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
- clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
- clk[ssi2_sel] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
- clk[ssi3_sel] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
- clk[usdhc1_sel] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
- clk[usdhc2_sel] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
- clk[usdhc3_sel] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
- clk[usdhc4_sel] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
- clk[enfc_sel] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels));
- clk[emi_sel] = imx_clk_fixup_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels), imx_cscmr1_fixup);
- clk[emi_slow_sel] = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels, ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup);
- clk[vdo_axi_sel] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
- clk[vpu_axi_sel] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels));
- clk[cko1_sel] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
- clk[cko2_sel] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
- clk[cko] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
-
- /* name reg shift width busy: reg, shift parent_names num_parents */
- clk[periph] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
- clk[periph2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
-
- /* name parent_name reg shift width */
- clk[periph_clk2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
- clk[periph2_clk2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
- clk[ipg] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
- clk[ipg_per] = imx_clk_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup);
- clk[esai_pred] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3);
- clk[esai_podf] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3);
- clk[asrc_pred] = imx_clk_divider("asrc_pred", "asrc_sel", base + 0x30, 12, 3);
- clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3);
- clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
- clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
- clk[can_root] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
- clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
- clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3);
- clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3);
- clk[gpu3d_shader] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3);
- clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
- clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
- clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
- clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
- clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
- clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
- clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
- clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
- clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
- clk[ipu2_di1_pre] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", base + 0x38, 12, 3);
- clk[hsi_tx_podf] = imx_clk_divider("hsi_tx_podf", "hsi_tx_sel", base + 0x30, 29, 3);
- clk[ssi1_pred] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3);
- clk[ssi1_podf] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6);
- clk[ssi2_pred] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3);
- clk[ssi2_podf] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6);
- clk[ssi3_pred] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3);
- clk[ssi3_podf] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6);
- clk[uart_serial_podf] = imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6);
- clk[usdhc1_podf] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
- clk[usdhc2_podf] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
- clk[usdhc3_podf] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3);
- clk[usdhc4_podf] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3);
- clk[enfc_pred] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
- clk[enfc_podf] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
- clk[emi_podf] = imx_clk_fixup_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup);
- clk[emi_slow_podf] = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup);
- clk[vpu_axi_podf] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3);
- clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
- clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3);
-
- /* name parent_name reg shift width busy: reg, shift */
- clk[axi] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
- clk[mmdc_ch0_axi_podf] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph", base + 0x14, 19, 3, base + 0x48, 4);
- clk[mmdc_ch1_axi_podf] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
- clk[arm] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
- clk[ahb] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
-
- /* name parent_name reg shift */
- clk[apbh_dma] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4);
- clk[asrc] = imx_clk_gate2("asrc", "asrc_podf", base + 0x68, 6);
- clk[can1_ipg] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
- clk[can1_serial] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16);
- clk[can2_ipg] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
- clk[can2_serial] = imx_clk_gate2("can2_serial", "can_root", base + 0x68, 20);
- clk[ecspi1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0);
- clk[ecspi2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2);
- clk[ecspi3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4);
- clk[ecspi4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6);
+ /* name reg shift width parent_names num_parents */
+ clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+ clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clk[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clk[IMX6QDL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clk[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clk[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
+ clk[IMX6QDL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ clk[IMX6QDL_CLK_ASRC_SEL] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ clk[IMX6QDL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
+ clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
+ clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
+ clk[IMX6QDL_CLK_GPU2D_CORE_SEL] = imx_clk_mux("gpu2d_core_sel", base + 0x18, 16, 2, gpu2d_core_sels, ARRAY_SIZE(gpu2d_core_sels));
+ clk[IMX6QDL_CLK_GPU3D_CORE_SEL] = imx_clk_mux("gpu3d_core_sel", base + 0x18, 4, 2, gpu3d_core_sels, ARRAY_SIZE(gpu3d_core_sels));
+ clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
+ clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
+ clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
+ clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU1_DI0_SEL] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU1_DI1_SEL] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU2_DI0_SEL] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_IPU2_DI1_SEL] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_HSI_TX_SEL] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels));
+ clk[IMX6QDL_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels));
+ clk[IMX6QDL_CLK_SSI1_SEL] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_SSI2_SEL] = imx_clk_fixup_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_SSI3_SEL] = imx_clk_fixup_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_USDHC1_SEL] = imx_clk_fixup_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_USDHC2_SEL] = imx_clk_fixup_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_USDHC3_SEL] = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_USDHC4_SEL] = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels));
+ clk[IMX6QDL_CLK_EMI_SEL] = imx_clk_fixup_mux("emi_sel", base + 0x1c, 27, 2, emi_sels, ARRAY_SIZE(emi_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_EMI_SLOW_SEL] = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels, ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
+ clk[IMX6QDL_CLK_VPU_AXI_SEL] = imx_clk_mux("vpu_axi_sel", base + 0x18, 14, 2, vpu_axi_sels, ARRAY_SIZE(vpu_axi_sels));
+ clk[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
+ clk[IMX6QDL_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
+ clk[IMX6QDL_CLK_CKO] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels));
+
+ /* name reg shift width busy: reg, shift parent_names num_parents */
+ clk[IMX6QDL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+ clk[IMX6QDL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+ /* name parent_name reg shift width */
+ clk[IMX6QDL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
+ clk[IMX6QDL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
+ clk[IMX6QDL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
+ clk[IMX6QDL_CLK_IPG_PER] = imx_clk_fixup_divider("ipg_per", "ipg", base + 0x1c, 0, 6, imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3);
+ clk[IMX6QDL_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3);
+ clk[IMX6QDL_CLK_ASRC_PRED] = imx_clk_divider("asrc_pred", "asrc_sel", base + 0x30, 12, 3);
+ clk[IMX6QDL_CLK_ASRC_PODF] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3);
+ clk[IMX6QDL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
+ clk[IMX6QDL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
+ clk[IMX6QDL_CLK_CAN_ROOT] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
+ clk[IMX6QDL_CLK_ECSPI_ROOT] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
+ clk[IMX6QDL_CLK_GPU2D_CORE_PODF] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3);
+ clk[IMX6QDL_CLK_GPU3D_CORE_PODF] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3);
+ clk[IMX6QDL_CLK_GPU3D_SHADER] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3);
+ clk[IMX6QDL_CLK_IPU1_PODF] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
+ clk[IMX6QDL_CLK_IPU2_PODF] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
+ clk[IMX6QDL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clk[IMX6QDL_CLK_LDB_DI0_PODF] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
+ clk[IMX6QDL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clk[IMX6QDL_CLK_LDB_DI1_PODF] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
+ clk[IMX6QDL_CLK_IPU1_DI0_PRE] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
+ clk[IMX6QDL_CLK_IPU1_DI1_PRE] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
+ clk[IMX6QDL_CLK_IPU2_DI0_PRE] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
+ clk[IMX6QDL_CLK_IPU2_DI1_PRE] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", base + 0x38, 12, 3);
+ clk[IMX6QDL_CLK_HSI_TX_PODF] = imx_clk_divider("hsi_tx_podf", "hsi_tx_sel", base + 0x30, 29, 3);
+ clk[IMX6QDL_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3);
+ clk[IMX6QDL_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6);
+ clk[IMX6QDL_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3);
+ clk[IMX6QDL_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6);
+ clk[IMX6QDL_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3);
+ clk[IMX6QDL_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6);
+ clk[IMX6QDL_CLK_UART_SERIAL_PODF] = imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6);
+ clk[IMX6QDL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
+ clk[IMX6QDL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
+ clk[IMX6QDL_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3);
+ clk[IMX6QDL_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3);
+ clk[IMX6QDL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
+ clk[IMX6QDL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
+ clk[IMX6QDL_CLK_EMI_PODF] = imx_clk_fixup_divider("emi_podf", "emi_sel", base + 0x1c, 20, 3, imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_EMI_SLOW_PODF] = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel", base + 0x1c, 23, 3, imx_cscmr1_fixup);
+ clk[IMX6QDL_CLK_VPU_AXI_PODF] = imx_clk_divider("vpu_axi_podf", "vpu_axi_sel", base + 0x24, 25, 3);
+ clk[IMX6QDL_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
+ clk[IMX6QDL_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3);
+
+ /* name parent_name reg shift width busy: reg, shift */
+ clk[IMX6QDL_CLK_AXI] = imx_clk_busy_divider("axi", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
+ clk[IMX6QDL_CLK_MMDC_CH0_AXI_PODF] = imx_clk_busy_divider("mmdc_ch0_axi_podf", "periph", base + 0x14, 19, 3, base + 0x48, 4);
+ clk[IMX6QDL_CLK_MMDC_CH1_AXI_PODF] = imx_clk_busy_divider("mmdc_ch1_axi_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
+ clk[IMX6QDL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
+ clk[IMX6QDL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
+
+ /* name parent_name reg shift */
+ clk[IMX6QDL_CLK_APBH_DMA] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4);
+ clk[IMX6QDL_CLK_ASRC] = imx_clk_gate2("asrc", "asrc_podf", base + 0x68, 6);
+ clk[IMX6QDL_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
+ clk[IMX6QDL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16);
+ clk[IMX6QDL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
+ clk[IMX6QDL_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_root", base + 0x68, 20);
+ clk[IMX6QDL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0);
+ clk[IMX6QDL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2);
+ clk[IMX6QDL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4);
+ clk[IMX6QDL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6);
if (cpu_is_imx6dl())
- /* ecspi5 is replaced with i2c4 on imx6dl & imx6s */
- clk[ecspi5] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8);
+ clk[IMX6DL_CLK_I2C4] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8);
else
- clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
- clk[enet] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
- clk[esai] = imx_clk_gate2_shared("esai", "esai_podf", base + 0x6c, 16, &share_count_esai);
- clk[esai_ahb] = imx_clk_gate2_shared("esai_ahb", "ahb", base + 0x6c, 16, &share_count_esai);
- clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
- clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
+ clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
+ clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
+ clk[IMX6QDL_CLK_ESAI] = imx_clk_gate2_shared("esai", "esai_podf", base + 0x6c, 16, &share_count_esai);
+ clk[IMX6QDL_CLK_ESAI_AHB] = imx_clk_gate2_shared("esai_ahb", "ahb", base + 0x6c, 16, &share_count_esai);
+ clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
+ clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
if (cpu_is_imx6dl())
/*
* The multiplexer and divider of imx6q clock gpu3d_shader get
* redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl.
*/
- clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24);
+ clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu3d_shader", base + 0x6c, 24);
else
- clk[gpu2d_core] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
- clk[gpu3d_core] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26);
- clk[hdmi_iahb] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0);
- clk[hdmi_isfr] = imx_clk_gate2("hdmi_isfr", "pll3_pfd1_540m", base + 0x70, 4);
- clk[i2c1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6);
- clk[i2c2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8);
- clk[i2c3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);
- clk[iim] = imx_clk_gate2("iim", "ipg", base + 0x70, 12);
- clk[enfc] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14);
- clk[vdoa] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26);
- clk[ipu1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0);
- clk[ipu1_di0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2);
- clk[ipu1_di1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4);
- clk[ipu2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6);
- clk[ipu2_di0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8);
- clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12);
- clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14);
- clk[ipu2_di1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10);
- clk[hsi_tx] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16);
+ clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
+ clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26);
+ clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0);
+ clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "pll3_pfd1_540m", base + 0x70, 4);
+ clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6);
+ clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8);
+ clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);
+ clk[IMX6QDL_CLK_IIM] = imx_clk_gate2("iim", "ipg", base + 0x70, 12);
+ clk[IMX6QDL_CLK_ENFC] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14);
+ clk[IMX6QDL_CLK_VDOA] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26);
+ clk[IMX6QDL_CLK_IPU1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0);
+ clk[IMX6QDL_CLK_IPU1_DI0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2);
+ clk[IMX6QDL_CLK_IPU1_DI1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4);
+ clk[IMX6QDL_CLK_IPU2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6);
+ clk[IMX6QDL_CLK_IPU2_DI0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8);
+ clk[IMX6QDL_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12);
+ clk[IMX6QDL_CLK_LDB_DI1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14);
+ clk[IMX6QDL_CLK_IPU2_DI1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10);
+ clk[IMX6QDL_CLK_HSI_TX] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16);
if (cpu_is_imx6dl())
/*
* The multiplexer and divider of the imx6q clock gpu2d get
* redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl.
*/
- clk[mlb] = imx_clk_gate2("mlb", "gpu2d_core_podf", base + 0x74, 18);
+ clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb", "gpu2d_core_podf", base + 0x74, 18);
else
- clk[mlb] = imx_clk_gate2("mlb", "axi", base + 0x74, 18);
- clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20);
- clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22);
- clk[ocram] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28);
- clk[openvg_axi] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30);
- clk[pcie_axi] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0);
- clk[per1_bch] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12);
- clk[pwm1] = imx_clk_gate2("pwm1", "ipg_per", base + 0x78, 16);
- clk[pwm2] = imx_clk_gate2("pwm2", "ipg_per", base + 0x78, 18);
- clk[pwm3] = imx_clk_gate2("pwm3", "ipg_per", base + 0x78, 20);
- clk[pwm4] = imx_clk_gate2("pwm4", "ipg_per", base + 0x78, 22);
- clk[gpmi_bch_apb] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24);
- clk[gpmi_bch] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26);
- clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28);
- clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30);
- clk[rom] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
- clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4);
- clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
- clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
- clk[spdif] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14);
- clk[ssi1_ipg] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18);
- clk[ssi2_ipg] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20);
- clk[ssi3_ipg] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22);
- clk[uart_ipg] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24);
- clk[uart_serial] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26);
- clk[usboh3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
- clk[usdhc1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
- clk[usdhc2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
- clk[usdhc3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
- clk[usdhc4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
- clk[eim_slow] = imx_clk_gate2("eim_slow", "emi_slow_podf", base + 0x80, 10);
- clk[vdo_axi] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12);
- clk[vpu_axi] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14);
- clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
- clk[cko2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24);
-
- for (i = 0; i < ARRAY_SIZE(clk); i++)
- if (IS_ERR(clk[i]))
- pr_err("i.MX6q clk %d: register failed with %ld\n",
- i, PTR_ERR(clk[i]));
+ clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb", "axi", base + 0x74, 18);
+ clk[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20);
+ clk[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22);
+ clk[IMX6QDL_CLK_OCRAM] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28);
+ clk[IMX6QDL_CLK_OPENVG_AXI] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30);
+ clk[IMX6QDL_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0);
+ clk[IMX6QDL_CLK_PER1_BCH] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12);
+ clk[IMX6QDL_CLK_PWM1] = imx_clk_gate2("pwm1", "ipg_per", base + 0x78, 16);
+ clk[IMX6QDL_CLK_PWM2] = imx_clk_gate2("pwm2", "ipg_per", base + 0x78, 18);
+ clk[IMX6QDL_CLK_PWM3] = imx_clk_gate2("pwm3", "ipg_per", base + 0x78, 20);
+ clk[IMX6QDL_CLK_PWM4] = imx_clk_gate2("pwm4", "ipg_per", base + 0x78, 22);
+ clk[IMX6QDL_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24);
+ clk[IMX6QDL_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26);
+ clk[IMX6QDL_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28);
+ clk[IMX6QDL_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30);
+ clk[IMX6QDL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
+ clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4);
+ clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
+ clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
+ clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14);
+ clk[IMX6QDL_CLK_SSI1_IPG] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18);
+ clk[IMX6QDL_CLK_SSI2_IPG] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20);
+ clk[IMX6QDL_CLK_SSI3_IPG] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22);
+ clk[IMX6QDL_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24);
+ clk[IMX6QDL_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26);
+ clk[IMX6QDL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
+ clk[IMX6QDL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
+ clk[IMX6QDL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
+ clk[IMX6QDL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
+ clk[IMX6QDL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
+ clk[IMX6QDL_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "emi_slow_podf", base + 0x80, 10);
+ clk[IMX6QDL_CLK_VDO_AXI] = imx_clk_gate2("vdo_axi", "vdo_axi_sel", base + 0x80, 12);
+ clk[IMX6QDL_CLK_VPU_AXI] = imx_clk_gate2("vpu_axi", "vpu_axi_podf", base + 0x80, 14);
+ clk[IMX6QDL_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
+ clk[IMX6QDL_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24);
+
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
- clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
- clk_register_clkdev(clk[enet_ref], "enet_ref", NULL);
+ clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
cpu_is_imx6dl()) {
- clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
- clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
+ clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
}
- clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
- clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
- clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
- clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
- clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
- clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
- clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
- clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_SEL], clk[IMX6QDL_CLK_IPU1_DI0_PRE]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_SEL], clk[IMX6QDL_CLK_IPU1_DI1_PRE]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], clk[IMX6QDL_CLK_IPU2_DI0_PRE]);
+ clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_SEL], clk[IMX6QDL_CLK_IPU2_DI1_PRE]);
/*
* The gpmi needs 100MHz frequency in the EDO/Sync mode,
* We can not get the 100MHz from the pll2_pfd0_352m.
* So choose pll2_pfd2_396m as enfc_sel's parent.
*/
- clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]);
+ clk_set_parent(clk[IMX6QDL_CLK_ENFC_SEL], clk[IMX6QDL_CLK_PLL2_PFD2_396M]);
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clk[clks_init_on[i]]);
if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
- clk_prepare_enable(clk[usbphy1_gate]);
- clk_prepare_enable(clk[usbphy2_gate]);
+ clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY1_GATE]);
+ clk_prepare_enable(clk[IMX6QDL_CLK_USBPHY2_GATE]);
}
/*
* Let's initially set up CLKO with OSC24M, since this configuration
* is widely used by imx6q board designs to clock audio codec.
*/
- ret = clk_set_parent(clk[cko2_sel], clk[osc]);
+ ret = clk_set_parent(clk[IMX6QDL_CLK_CKO2_SEL], clk[IMX6QDL_CLK_OSC]);
if (!ret)
- ret = clk_set_parent(clk[cko], clk[cko2]);
+ ret = clk_set_parent(clk[IMX6QDL_CLK_CKO], clk[IMX6QDL_CLK_CKO2]);
if (ret)
pr_warn("failed to set up CLKO: %d\n", ret);
/* Audio-related clocks configuration */
- clk_set_parent(clk[spdif_sel], clk[pll3_pfd3_454m]);
+ clk_set_parent(clk[IMX6QDL_CLK_SPDIF_SEL], clk[IMX6QDL_CLK_PLL3_PFD3_454M]);
/* All existing boards with PCIe use LVDS1 */
if (IS_ENABLED(CONFIG_PCI_IMX6))
- clk_set_parent(clk[lvds1_sel], clk[sata_ref_100m]);
+ clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
-
- mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"));
}
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index 5408ca70c8d6..fef46faf692f 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -348,18 +348,12 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6);
clks[IMX6SL_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8);
- for (i = 0; i < ARRAY_SIZE(clks); i++)
- if (IS_ERR(clks[i]))
- pr_err("i.MX6SL clk %d: register failed with %ld\n",
- i, PTR_ERR(clks[i]));
+ imx_check_clocks(clks, ARRAY_SIZE(clks));
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
- clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
-
/* Ensure the AHB clk is at 132MHz. */
ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
if (ret)
@@ -383,8 +377,5 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
- mxc_timer_init_dt(np);
}
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c
index 72f8902235d1..ecde72bdfe88 100644
--- a/arch/arm/mach-imx/clk-imx6sx.c
+++ b/arch/arm/mach-imx/clk-imx6sx.c
@@ -124,6 +124,9 @@ static struct clk_div_table video_div_table[] = {
static u32 share_count_asrc;
static u32 share_count_audio;
static u32 share_count_esai;
+static u32 share_count_ssi1;
+static u32 share_count_ssi2;
+static u32 share_count_ssi3;
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
@@ -409,12 +412,12 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio);
clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
- clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18);
- clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20);
- clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22);
- clks[IMX6SX_CLK_SSI1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18);
- clks[IMX6SX_CLK_SSI2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20);
- clks[IMX6SX_CLK_SSI3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22);
+ clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
+ clks[IMX6SX_CLK_SSI1] = imx_clk_gate2_shared("ssi1", "ssi1_podf", base + 0x7c, 18, &share_count_ssi1);
+ clks[IMX6SX_CLK_SSI2] = imx_clk_gate2_shared("ssi2", "ssi2_podf", base + 0x7c, 20, &share_count_ssi2);
+ clks[IMX6SX_CLK_SSI3] = imx_clk_gate2_shared("ssi3", "ssi3_podf", base + 0x7c, 22, &share_count_ssi3);
clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24);
clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26);
clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28);
@@ -443,17 +446,12 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* mask handshake of mmdc */
writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
- for (i = 0; i < ARRAY_SIZE(clks); i++)
- if (IS_ERR(clks[i]))
- pr_err("i.MX6sx clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
+ imx_check_clocks(clks, ARRAY_SIZE(clks));
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
- clk_register_clkdev(clks[IMX6SX_CLK_GPT_BUS], "ipg", "imx-gpt.0");
- clk_register_clkdev(clks[IMX6SX_CLK_GPT_SERIAL], "per", "imx-gpt.0");
-
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
@@ -517,8 +515,5 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-gpt");
- mxc_timer_init_dt(np);
}
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index 22dc3ee21fd4..f60d6d569ce3 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -295,14 +295,18 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(1));
- clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(0));
- clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(4));
+ clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus", CCM_CSCDR2, 11);
+ clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en", CCM_CCGR0, CCM_CCGRx_CGn(0));
+ clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus", CCM_CSCDR2, 12);
+ clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en", CCM_CCGR9, CCM_CCGRx_CGn(4));
clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(4));
clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5));
clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
+ imx_check_clocks(clk, ARRAY_SIZE(clk));
+
clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2);
clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2);
diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c
index edc35df7bed4..df12b5307175 100644
--- a/arch/arm/mach-imx/clk.c
+++ b/arch/arm/mach-imx/clk.c
@@ -7,6 +7,16 @@
DEFINE_SPINLOCK(imx_ccm_lock);
+void __init imx_check_clocks(struct clk *clks[], unsigned int count)
+{
+ unsigned i;
+
+ for (i = 0; i < count; i++)
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX clk %u: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+}
+
static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
{
struct of_phandle_args phandle;
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index e29f6ebe9f39..d5ba76fee115 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -6,6 +6,8 @@
extern spinlock_t imx_ccm_lock;
+void imx_check_clocks(struct clk *clks[], unsigned int count);
+
extern void imx_cscmr1_fixup(u32 *val);
struct clk *imx_clk_pllv1(const char *name, const char *parent,
@@ -95,6 +97,13 @@ static inline struct clk *imx_clk_gate(const char *name, const char *parent,
shift, 0, &imx_ccm_lock);
}
+static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
+ void __iomem *reg, u8 shift)
+{
+ return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+ shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parents, int num_parents)
{
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 9ab785ce13e8..22ba8973bcb9 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -19,6 +19,7 @@ struct pt_regs;
struct clk;
struct device_node;
enum mxc_cpu_pwr_mode;
+struct of_device_id;
void mx1_map_io(void);
void mx21_map_io(void);
@@ -26,48 +27,34 @@ void mx25_map_io(void);
void mx27_map_io(void);
void mx31_map_io(void);
void mx35_map_io(void);
-void mx51_map_io(void);
-void mx53_map_io(void);
void imx1_init_early(void);
void imx21_init_early(void);
void imx25_init_early(void);
void imx27_init_early(void);
void imx31_init_early(void);
void imx35_init_early(void);
-void imx51_init_early(void);
-void imx53_init_early(void);
void mxc_init_irq(void __iomem *);
-void tzic_init_irq(void __iomem *);
+void tzic_init_irq(void);
void mx1_init_irq(void);
void mx21_init_irq(void);
void mx25_init_irq(void);
void mx27_init_irq(void);
void mx31_init_irq(void);
void mx35_init_irq(void);
-void mx51_init_irq(void);
-void mx53_init_irq(void);
void imx1_soc_init(void);
void imx21_soc_init(void);
void imx25_soc_init(void);
void imx27_soc_init(void);
void imx31_soc_init(void);
void imx35_soc_init(void);
-void imx51_soc_init(void);
-void imx51_init_late(void);
-void imx53_init_late(void);
void epit_timer_init(void __iomem *base, int irq);
void mxc_timer_init(void __iomem *, int);
-void mxc_timer_init_dt(struct device_node *);
int mx1_clocks_init(unsigned long fref);
int mx21_clocks_init(unsigned long lref, unsigned long fref);
int mx25_clocks_init(void);
int mx27_clocks_init(unsigned long fref);
int mx31_clocks_init(unsigned long fref);
int mx35_clocks_init(void);
-int mx51_clocks_init(unsigned long ckil, unsigned long osc,
- unsigned long ckih1, unsigned long ckih2);
-int mx25_clocks_init_dt(void);
-int mx27_clocks_init_dt(void);
int mx31_clocks_init_dt(void);
struct platform_device *mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
@@ -75,8 +62,10 @@ void mxc_set_cpu_type(unsigned int type);
void mxc_restart(enum reboot_mode, const char *);
void mxc_arch_reset_init(void __iomem *);
void mxc_arch_reset_init_dt(void);
+int mx51_revision(void);
int mx53_revision(void);
void imx_set_aips(void __iomem *);
+void imx_aips_allow_unprivileged_access(const char *compat);
int mxc_device_init(void);
void imx_set_soc_revision(unsigned int rev);
unsigned int imx_get_soc_revision(void);
@@ -117,7 +106,7 @@ static inline void imx_scu_standby_enable(void) {}
#endif
void imx_src_init(void);
void imx_gpc_init(void);
-void imx_gpc_pre_suspend(void);
+void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
@@ -127,7 +116,7 @@ void imx_anatop_init(void);
void imx_anatop_pre_suspend(void);
void imx_anatop_post_resume(void);
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-void imx6q_set_int_mem_clk_lpm(void);
+void imx6q_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
void imx_cpu_die(unsigned int cpu);
@@ -144,12 +133,17 @@ static inline void imx6_suspend(void __iomem *ocram_vbase) {}
void imx6q_pm_init(void);
void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
+void imx6sx_pm_init(void);
void imx6q_pm_set_ccm_base(void __iomem *base);
#ifdef CONFIG_PM
-void imx5_pm_init(void);
+void imx51_pm_init(void);
+void imx53_pm_init(void);
+void imx5_pm_set_ccm_base(void __iomem *base);
#else
-static inline void imx5_pm_init(void) {}
+static inline void imx51_pm_init(void) {}
+static inline void imx53_pm_init(void) {}
+static inline void imx5_pm_set_ccm_base(void __iomem *base) {}
#endif
#ifdef CONFIG_NEON
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
index c1c99a72c6a1..3403bac94a31 100644
--- a/arch/arm/mach-imx/cpu-imx5.c
+++ b/arch/arm/mach-imx/cpu-imx5.c
@@ -16,6 +16,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
#include "hardware.h"
#include "common.h"
@@ -24,10 +26,26 @@ static int mx5_cpu_rev = -1;
#define IIM_SREV 0x24
+static u32 imx5_read_srev_reg(const char *compat)
+{
+ void __iomem *iim_base;
+ struct device_node *np;
+ u32 srev;
+
+ np = of_find_compatible_node(NULL, NULL, compat);
+ iim_base = of_iomap(np, 0);
+ WARN_ON(!iim_base);
+
+ srev = readl(iim_base + IIM_SREV) & 0xff;
+
+ iounmap(iim_base);
+
+ return srev;
+}
+
static int get_mx51_srev(void)
{
- void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
- u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+ u32 rev = imx5_read_srev_reg("fsl,imx51-iim");
switch (rev) {
case 0x0:
@@ -77,8 +95,7 @@ int __init mx51_neon_fixup(void)
static int get_mx53_srev(void)
{
- void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
- u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+ u32 rev = imx5_read_srev_reg("fsl,imx53-iim");
switch (rev) {
case 0x0:
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index bbe8ff1f0412..df42c14ff749 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -2,6 +2,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
@@ -60,6 +61,18 @@ void __init imx_set_aips(void __iomem *base)
__raw_writel(reg, base + 0x50);
}
+void __init imx_aips_allow_unprivileged_access(
+ const char *compat)
+{
+ void __iomem *aips_base_addr;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, compat) {
+ aips_base_addr = of_iomap(np, 0);
+ imx_set_aips(aips_base_addr);
+ }
+}
+
struct device * __init imx_soc_device_init(void)
{
struct soc_device_attribute *soc_dev_attr;
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index 6bcae0479049..10844d3bb926 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -13,6 +13,7 @@
#include "common.h"
#include "cpuidle.h"
+#include "hardware.h"
static atomic_t master = ATOMIC_INIT(0);
static DEFINE_SPINLOCK(master_lock);
@@ -66,10 +67,11 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
int __init imx6q_cpuidle_init(void)
{
/* Need to enable SCU standby for entering WAIT modes */
- imx_scu_standby_enable();
+ if (!cpu_is_imx6sx())
+ imx_scu_standby_enable();
/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
- imx6q_set_int_mem_clk_lpm();
+ imx6q_set_int_mem_clk_lpm(true);
return cpuidle_register(&imx6q_cpuidle_driver, NULL);
}
diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h
deleted file mode 100644
index 5e3f1f0f4cab..000000000000
--- a/arch/arm/mach-imx/crm-regs-imx5.h
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-
-#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
-
-/*MX53*/
-#define MX53_CCM_BASE MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
-#define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
-#define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
-#define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR)
-
-/* PLL Register Offsets */
-#define MXC_PLL_DP_CTL 0x00
-#define MXC_PLL_DP_CONFIG 0x04
-#define MXC_PLL_DP_OP 0x08
-#define MXC_PLL_DP_MFD 0x0C
-#define MXC_PLL_DP_MFN 0x10
-#define MXC_PLL_DP_MFNMINUS 0x14
-#define MXC_PLL_DP_MFNPLUS 0x18
-#define MXC_PLL_DP_HFS_OP 0x1C
-#define MXC_PLL_DP_HFS_MFD 0x20
-#define MXC_PLL_DP_HFS_MFN 0x24
-#define MXC_PLL_DP_MFN_TOGC 0x28
-#define MXC_PLL_DP_DESTAT 0x2c
-
-/* PLL Register Bit definitions */
-#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000
-#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000
-#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12
-#define MXC_PLL_DP_CTL_ADE 0x800
-#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8)
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8
-#define MXC_PLL_DP_CTL_HFSM 0x80
-#define MXC_PLL_DP_CTL_PRE 0x40
-#define MXC_PLL_DP_CTL_UPEN 0x20
-#define MXC_PLL_DP_CTL_RST 0x10
-#define MXC_PLL_DP_CTL_RCP 0x8
-#define MXC_PLL_DP_CTL_PLM 0x4
-#define MXC_PLL_DP_CTL_BRM0 0x2
-#define MXC_PLL_DP_CTL_LRF 0x1
-
-#define MXC_PLL_DP_CONFIG_BIST 0x8
-#define MXC_PLL_DP_CONFIG_SJC_CE 0x4
-#define MXC_PLL_DP_CONFIG_AREN 0x2
-#define MXC_PLL_DP_CONFIG_LDREQ 0x1
-
-#define MXC_PLL_DP_OP_MFI_OFFSET 4
-#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4)
-#define MXC_PLL_DP_OP_PDF_OFFSET 0
-#define MXC_PLL_DP_OP_PDF_MASK 0xF
-
-#define MXC_PLL_DP_MFD_OFFSET 0
-#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_OFFSET 0x0
-#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17)
-#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16)
-#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0
-#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF
-
-#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31)
-#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF
-
-/* Register addresses of CCM*/
-#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CCGR7 (MX51_CCM_BASE + 0x84)
-
-#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84)
-
-/* Define the bits in register CCR */
-#define MXC_CCM_CCR_COSC_EN (1 << 12)
-#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11)
-#define MXC_CCM_CCR_CAMP2_EN (1 << 10)
-#define MXC_CCM_CCR_CAMP1_EN (1 << 9)
-#define MXC_CCM_CCR_FPM_EN (1 << 8)
-#define MXC_CCM_CCR_OSCNT_OFFSET (0)
-#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
-
-/* Define the bits in register CCDR */
-#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18)
-#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
-#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16)
-
-/* Define the bits in register CSR */
-#define MXC_CCM_CSR_COSR_READY (1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE (1 << 4)
-#define MXC_CCM_CSR_CAMP2_READY (1 << 3)
-#define MXC_CCM_CSR_CAMP1_READY (1 << 2)
-#define MXC_CCM_CSR_FPM_READY (1 << 1)
-#define MXC_CCM_CSR_REF_EN_B (1 << 0)
-
-/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7)
-#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0
-#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */
-#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
-#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
-#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5)
-#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3)
-#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk,
- 1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
-
-/* Define the bits in register CACRR */
-#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
-
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL (0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F)
-
-/* Define the bits in register CDHIPR */
-#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
-#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY (1 << 8)
-#define MXC_CCM_CDHIPR_DDR_PODF_BUSY (1 << 7)
-#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6)
-#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
-#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4)
-#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3)
-#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2)
-#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1)
-#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0)
-
-/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3)
-
-/* Define the bits in register CLPCR */
-#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22)
-#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21)
-#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20)
-#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19)
-#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11)
-#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
-#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET (0)
-#define MXC_CCM_CLPCR_LPM_MASK (0x3)
-
-/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
-#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19)
-#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18)
-#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16)
-#define MXC_CCM_CISR_COSC_READY (0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5)
-#define MXC_CCM_CISR_CKIH_READY (0x1 << 4)
-#define MXC_CCM_CISR_FPM_READY (0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1 (0x1)
-
-/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25)
-#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19)
-#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18)
-#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17)
-#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5)
-#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4)
-#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3)
-#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2)
-#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1)
-#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1)
-
-/* Define the bits in register CCOSR */
-#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24)
-#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21)
-#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
-#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16)
-#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
-#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7)
-#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4)
-#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4)
-#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0)
-#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF)
-
-/* Define the bits in registers CGPR */
-#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4)
-#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7)
-
-/* Define the bits in registers CCGRx */
-#define MXC_CCM_CCGRx_CG_MASK 0x3
-#define MXC_CCM_CCGRx_MOD_OFF 0x0
-#define MXC_CCM_CCGRx_MOD_ON 0x3
-#define MXC_CCM_CCGRx_MOD_IDLE 0x1
-
-#define MXC_CCM_CCGRx_CG15_MASK (0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK (0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK (0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK (0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK (0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK (0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK (0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK (0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK (0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK (0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK (0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK (0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK (0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK (0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET 30
-#define MXC_CCM_CCGRx_CG14_OFFSET 28
-#define MXC_CCM_CCGRx_CG13_OFFSET 26
-#define MXC_CCM_CCGRx_CG12_OFFSET 24
-#define MXC_CCM_CCGRx_CG11_OFFSET 22
-#define MXC_CCM_CCGRx_CG10_OFFSET 20
-#define MXC_CCM_CCGRx_CG9_OFFSET 18
-#define MXC_CCM_CCGRx_CG8_OFFSET 16
-#define MXC_CCM_CCGRx_CG7_OFFSET 14
-#define MXC_CCM_CCGRx_CG6_OFFSET 12
-#define MXC_CCM_CCGRx_CG5_OFFSET 10
-#define MXC_CCM_CCGRx_CG4_OFFSET 8
-#define MXC_CCM_CCGRx_CG3_OFFSET 6
-#define MXC_CCM_CCGRx_CG2_OFFSET 4
-#define MXC_CCM_CCGRx_CG1_OFFSET 2
-#define MXC_CCM_CCGRx_CG0_OFFSET 0
-
-#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300)
-
-/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24)
-
-/* DVFS CORE */
-#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00)
-#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04)
-#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08)
-#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C)
-#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10)
-#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14)
-#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18)
-#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C)
-#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20)
-#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24)
-#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28)
-#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C)
-#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30)
-#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34)
-#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38)
-#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C)
-#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40)
-
-/* GPC */
-#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET 8
-#define MXC_GPC_PGR_ARMPG_MASK (3 << 8)
-
-/* PGC */
-#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0)
-#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC)
-#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0)
-#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC)
-#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0)
-#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC)
-
-#define MXC_PGCR_PCR 1
-#define MXC_SRPGCR_PCR 1
-#define MXC_EMPGCR_PCR 1
-#define MXC_PGSR_PSR 1
-
-
-#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0)
-#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1)
-
-/* SRPG */
-#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0)
-#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4)
-#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8)
-
-#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0)
-#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4)
-#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0)
-#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4)
-#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0)
-#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4)
-#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8)
-
-#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0)
-#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4)
-#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8)
-
-#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0)
-#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4)
-#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8)
-
-#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h
deleted file mode 100644
index 26389f35a2b2..000000000000
--- a/arch/arm/mach-imx/devices-imx51.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "devices/devices-common.h"
-
-extern const struct imx_fec_data imx51_fec_data;
-#define imx51_add_fec(pdata) \
- imx_add_fec(&imx51_fec_data, pdata)
-
-extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
-#define imx51_add_fsl_usb2_udc(pdata) \
- imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
-
-extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
-#define imx51_add_imx_i2c(id, pdata) \
- imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
-#define imx51_add_hsi2c(pdata) \
- imx51_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
-#define imx51_add_imx_ssi(id, pdata) \
- imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
-#define imx51_add_imx_uart(id, pdata) \
- imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
-
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
-#define imx51_add_mxc_ehci_otg(pdata) \
- imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
-#define imx51_add_mxc_ehci_hs(id, pdata) \
- imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
-
-extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
-#define imx51_add_mxc_nand(pdata) \
- imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
-#define imx51_add_sdhci_esdhc_imx(id, pdata) \
- imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx51_cspi_data;
-#define imx51_add_cspi(pdata) \
- imx_add_spi_imx(&imx51_cspi_data, pdata)
-
-extern const struct imx_spi_imx_data imx51_ecspi_data[];
-#define imx51_add_ecspi(id, pdata) \
- imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id) \
- imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
-
-extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
-#define imx51_add_imx_keypad(pdata) \
- imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx51_pata_imx_data;
-#define imx51_add_pata_imx() \
- imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig
index 2d260a5a307c..1d2cc1805f3e 100644
--- a/arch/arm/mach-imx/devices/Kconfig
+++ b/arch/arm/mach-imx/devices/Kconfig
@@ -1,6 +1,6 @@
config IMX_HAVE_PLATFORM_FEC
bool
- default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
+ default y if SOC_IMX25 || SOC_IMX27 || SOC_IMX35
config IMX_HAVE_PLATFORM_FLEXCAN
bool
@@ -10,7 +10,6 @@ config IMX_HAVE_PLATFORM_FSL_USB2_UDC
config IMX_HAVE_PLATFORM_GPIO_KEYS
bool
- default y if SOC_IMX51
config IMX_HAVE_PLATFORM_IMX21_HCD
bool
@@ -43,15 +42,9 @@ config IMX_HAVE_PLATFORM_IMX_SSI
config IMX_HAVE_PLATFORM_IMX_UART
bool
-config IMX_HAVE_PLATFORM_IMX_UDC
- bool
-
config IMX_HAVE_PLATFORM_IPU_CORE
bool
-config IMX_HAVE_PLATFORM_MX1_CAMERA
- bool
-
config IMX_HAVE_PLATFORM_MX2_CAMERA
bool
diff --git a/arch/arm/mach-imx/devices/Makefile b/arch/arm/mach-imx/devices/Makefile
index 1cbc14cd80d1..8fdb12b4ca7e 100644
--- a/arch/arm/mach-imx/devices/Makefile
+++ b/arch/arm/mach-imx/devices/Makefile
@@ -16,9 +16,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD) += platform-imx-keypad.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_PATA_IMX) += platform-pata_imx.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UDC) += platform-imx_udc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IPU_CORE) += platform-ipu-core.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_MX1_CAMERA) += platform-mx1-camera.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o
diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h
index 61352a80bb59..67f7fb13050d 100644
--- a/arch/arm/mach-imx/devices/devices-common.h
+++ b/arch/arm/mach-imx/devices/devices-common.h
@@ -176,22 +176,6 @@ struct platform_device *__init imx_add_imx_uart_1irq(
const struct imx_imx_uart_1irq_data *data,
const struct imxuart_platform_data *pdata);
-#include <linux/platform_data/usb-imx_udc.h>
-struct imx_imx_udc_data {
- resource_size_t iobase;
- resource_size_t iosize;
- resource_size_t irq0;
- resource_size_t irq1;
- resource_size_t irq2;
- resource_size_t irq3;
- resource_size_t irq4;
- resource_size_t irq5;
- resource_size_t irq6;
-};
-struct platform_device *__init imx_add_imx_udc(
- const struct imx_imx_udc_data *data,
- const struct imxusb_platform_data *pdata);
-
#include <linux/platform_data/video-mx3fb.h>
#include <linux/platform_data/camera-mx3.h>
struct imx_ipu_core_data {
@@ -208,16 +192,6 @@ struct platform_device *__init imx_add_mx3_sdc_fb(
const struct imx_ipu_core_data *data,
struct mx3fb_platform_data *pdata);
-#include <linux/platform_data/camera-mx1.h>
-struct imx_mx1_camera_data {
- resource_size_t iobase;
- resource_size_t iosize;
- resource_size_t irq;
-};
-struct platform_device *__init imx_add_mx1_camera(
- const struct imx_mx1_camera_data *data,
- const struct mx1_camera_pdata *pdata);
-
#include <linux/platform_data/camera-mx2.h>
struct imx_mx2_camera_data {
const char *devid;
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
index 1b4366a0e7c0..8eab5440da28 100644
--- a/arch/arm/mach-imx/devices/devices.c
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -24,12 +24,10 @@
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
- .parent = &platform_bus,
};
struct device mxc_ahb_bus = {
.init_name = "mxc_ahb",
- .parent = &platform_bus,
};
int __init mxc_device_init(void)
diff --git a/arch/arm/mach-imx/devices/platform-fec.c b/arch/arm/mach-imx/devices/platform-fec.c
index 63eba08f87b1..d86f9250b4ee 100644
--- a/arch/arm/mach-imx/devices/platform-fec.c
+++ b/arch/arm/mach-imx/devices/platform-fec.c
@@ -35,18 +35,6 @@ const struct imx_fec_data imx35_fec_data __initconst =
imx_fec_data_entry_single(MX35, "imx27-fec");
#endif
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx27 type fec */
-const struct imx_fec_data imx51_fec_data __initconst =
- imx_fec_data_entry_single(MX51, "imx27-fec");
-#endif
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx25 type fec */
-const struct imx_fec_data imx53_fec_data __initconst =
- imx_fec_data_entry_single(MX53, "imx25-fec");
-#endif
-
struct platform_device *__init imx_add_fec(
const struct imx_fec_data *data,
const struct fec_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
index 3c06bd96e9cc..23b0061347cb 100644
--- a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
@@ -38,11 +38,6 @@ const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27");
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
- imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51");
-#endif
-
struct platform_device *__init imx_add_fsl_usb2_udc(
const struct imx_fsl_usb2_udc_data *data,
const struct fsl_usb2_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-imx-i2c.c b/arch/arm/mach-imx/devices/platform-imx-i2c.c
index 57d342e85c2f..644ac2689882 100644
--- a/arch/arm/mach-imx/devices/platform-imx-i2c.c
+++ b/arch/arm/mach-imx/devices/platform-imx-i2c.c
@@ -70,32 +70,6 @@ const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
-#define imx51_imx_i2c_data_entry(_id, _hwid) \
- imx_imx_i2c_data_entry(MX51, "imx21-i2c", _id, _hwid, SZ_4K)
- imx51_imx_i2c_data_entry(0, 1),
- imx51_imx_i2c_data_entry(1, 2),
- {
- .devid = "imx21-i2c",
- .id = 2,
- .iobase = MX51_HSI2C_DMA_BASE_ADDR,
- .iosize = SZ_16K,
- .irq = MX51_INT_HS_I2C,
- },
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_i2c_data imx53_imx_i2c_data[] __initconst = {
-#define imx53_imx_i2c_data_entry(_id, _hwid) \
- imx_imx_i2c_data_entry(MX53, "imx21-i2c", _id, _hwid, SZ_4K)
- imx53_imx_i2c_data_entry(0, 1),
- imx53_imx_i2c_data_entry(1, 2),
- imx53_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_imx_i2c(
const struct imx_imx_i2c_data *data,
const struct imxi2c_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-imx-keypad.c b/arch/arm/mach-imx/devices/platform-imx-keypad.c
index 8f22a4c98a4c..f42200b7aca9 100644
--- a/arch/arm/mach-imx/devices/platform-imx-keypad.c
+++ b/arch/arm/mach-imx/devices/platform-imx-keypad.c
@@ -41,16 +41,6 @@ const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst =
imx_imx_keypad_data_entry_single(MX35, SZ_16);
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst =
- imx_imx_keypad_data_entry_single(MX51, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_keypad_data imx53_imx_keypad_data __initconst =
- imx_imx_keypad_data_entry_single(MX53, SZ_16);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_imx_keypad(
const struct imx_imx_keypad_data *data,
const struct matrix_keymap_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-imx-ssi.c b/arch/arm/mach-imx/devices/platform-imx-ssi.c
index bfcb8f3dfa8d..1c7c721ebff1 100644
--- a/arch/arm/mach-imx/devices/platform-imx-ssi.c
+++ b/arch/arm/mach-imx/devices/platform-imx-ssi.c
@@ -66,26 +66,6 @@ const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_ssi_data imx51_imx_ssi_data[] __initconst = {
-#define imx51_imx_ssi_data_entry(_id, _hwid) \
- imx_imx_ssi_data_entry(MX51, _id, _hwid, SZ_16K)
- imx51_imx_ssi_data_entry(0, 1),
- imx51_imx_ssi_data_entry(1, 2),
- imx51_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_ssi_data imx53_imx_ssi_data[] __initconst = {
-#define imx53_imx_ssi_data_entry(_id, _hwid) \
- imx_imx_ssi_data_entry(MX53, _id, _hwid, SZ_16K)
- imx53_imx_ssi_data_entry(0, 1),
- imx53_imx_ssi_data_entry(1, 2),
- imx53_imx_ssi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_imx_ssi(
const struct imx_imx_ssi_data *data,
const struct imx_ssi_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-imx-uart.c b/arch/arm/mach-imx/devices/platform-imx-uart.c
index faac4aa6ca6d..8c01836bc1d4 100644
--- a/arch/arm/mach-imx/devices/platform-imx-uart.c
+++ b/arch/arm/mach-imx/devices/platform-imx-uart.c
@@ -94,28 +94,6 @@ const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
-#define imx51_imx_uart_data_entry(_id, _hwid) \
- imx_imx_uart_1irq_data_entry(MX51, _id, _hwid, SZ_4K)
- imx51_imx_uart_data_entry(0, 1),
- imx51_imx_uart_data_entry(1, 2),
- imx51_imx_uart_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx_uart_1irq_data imx53_imx_uart_data[] __initconst = {
-#define imx53_imx_uart_data_entry(_id, _hwid) \
- imx_imx_uart_1irq_data_entry(MX53, _id, _hwid, SZ_4K)
- imx53_imx_uart_data_entry(0, 1),
- imx53_imx_uart_data_entry(1, 2),
- imx53_imx_uart_data_entry(2, 3),
- imx53_imx_uart_data_entry(3, 4),
- imx53_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_imx_uart_3irq(
const struct imx_imx_uart_3irq_data *data,
const struct imxuart_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-imx2-wdt.c b/arch/arm/mach-imx/devices/platform-imx2-wdt.c
index ec75d6413686..54f63bc25ca4 100644
--- a/arch/arm/mach-imx/devices/platform-imx2-wdt.c
+++ b/arch/arm/mach-imx/devices/platform-imx2-wdt.c
@@ -45,24 +45,6 @@ const struct imx_imx2_wdt_data imx35_imx2_wdt_data __initconst =
imx_imx2_wdt_data_entry_single(MX35, 0, , SZ_16K);
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
-#define imx51_imx2_wdt_data_entry(_id, _hwid) \
- imx_imx2_wdt_data_entry(MX51, _id, _hwid, SZ_16K)
- imx51_imx2_wdt_data_entry(0, 1),
- imx51_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
-#define imx53_imx2_wdt_data_entry(_id, _hwid) \
- imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
- imx53_imx2_wdt_data_entry(0, 1),
- imx53_imx2_wdt_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_imx2_wdt(
const struct imx_imx2_wdt_data *data)
{
diff --git a/arch/arm/mach-imx/devices/platform-imx_udc.c b/arch/arm/mach-imx/devices/platform-imx_udc.c
deleted file mode 100644
index 5ced7e4e2c71..000000000000
--- a/arch/arm/mach-imx/devices/platform-imx_udc.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "../hardware.h"
-#include "devices-common.h"
-
-#define imx_imx_udc_data_entry_single(soc, _size) \
- { \
- .iobase = soc ## _USBD_BASE_ADDR, \
- .iosize = _size, \
- .irq0 = soc ## _INT_USBD0, \
- .irq1 = soc ## _INT_USBD1, \
- .irq2 = soc ## _INT_USBD2, \
- .irq3 = soc ## _INT_USBD3, \
- .irq4 = soc ## _INT_USBD4, \
- .irq5 = soc ## _INT_USBD5, \
- .irq6 = soc ## _INT_USBD6, \
- }
-
-#define imx_imx_udc_data_entry(soc, _size) \
- [_id] = imx_imx_udc_data_entry_single(soc, _size)
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_imx_udc_data imx1_imx_udc_data __initconst =
- imx_imx_udc_data_entry_single(MX1, SZ_4K);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_imx_udc(
- const struct imx_imx_udc_data *data,
- const struct imxusb_platform_data *pdata)
-{
- struct resource res[] = {
- {
- .start = data->iobase,
- .end = data->iobase + data->iosize - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = data->irq0,
- .end = data->irq0,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq1,
- .end = data->irq1,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq2,
- .end = data->irq2,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq3,
- .end = data->irq3,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq4,
- .end = data->irq4,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq5,
- .end = data->irq5,
- .flags = IORESOURCE_IRQ,
- }, {
- .start = data->irq6,
- .end = data->irq6,
- .flags = IORESOURCE_IRQ,
- },
- };
-
- return imx_add_platform_device("imx_udc", 0,
- res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/mach-imx/devices/platform-mx1-camera.c b/arch/arm/mach-imx/devices/platform-mx1-camera.c
deleted file mode 100644
index 2c6788131080..000000000000
--- a/arch/arm/mach-imx/devices/platform-mx1-camera.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "../hardware.h"
-#include "devices-common.h"
-
-#define imx_mx1_camera_data_entry_single(soc, _size) \
- { \
- .iobase = soc ## _CSI ## _BASE_ADDR, \
- .iosize = _size, \
- .irq = soc ## _INT_CSI, \
- }
-
-#ifdef CONFIG_SOC_IMX1
-const struct imx_mx1_camera_data imx1_mx1_camera_data __initconst =
- imx_mx1_camera_data_entry_single(MX1, 10);
-#endif /* ifdef CONFIG_SOC_IMX1 */
-
-struct platform_device *__init imx_add_mx1_camera(
- const struct imx_mx1_camera_data *data,
- const struct mx1_camera_pdata *pdata)
-{
- struct resource res[] = {
- {
- .start = data->iobase,
- .end = data->iobase + data->iosize - 1,
- .flags = IORESOURCE_MEM,
- }, {
- .start = data->irq,
- .end = data->irq,
- .flags = IORESOURCE_IRQ,
- },
- };
- return imx_add_platform_device_dmamask("mx1-camera", 0,
- res, ARRAY_SIZE(res),
- pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/mach-imx/devices/platform-mxc-ehci.c b/arch/arm/mach-imx/devices/platform-mxc-ehci.c
index 5d4bbbfde641..296353662ff0 100644
--- a/arch/arm/mach-imx/devices/platform-mxc-ehci.c
+++ b/arch/arm/mach-imx/devices/platform-mxc-ehci.c
@@ -50,15 +50,6 @@ const struct imx_mxc_ehci_data imx35_mxc_ehci_hs_data __initconst =
imx_mxc_ehci_data_entry_single(MX35, 1, HS);
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data __initconst =
- imx_mxc_ehci_data_entry_single(MX51, 0, OTG);
-const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[] __initconst = {
- imx_mxc_ehci_data_entry_single(MX51, 1, HS1),
- imx_mxc_ehci_data_entry_single(MX51, 2, HS2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
struct platform_device *__init imx_add_mxc_ehci(
const struct imx_mxc_ehci_data *data,
const struct mxc_usbh_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-mxc_nand.c b/arch/arm/mach-imx/devices/platform-mxc_nand.c
index 7af1c53e42b5..fa618a34f462 100644
--- a/arch/arm/mach-imx/devices/platform-mxc_nand.c
+++ b/arch/arm/mach-imx/devices/platform-mxc_nand.c
@@ -54,11 +54,6 @@ const struct imx_mxc_nand_data imx35_mxc_nand_data __initconst =
imx_mxc_nand_data_entry_single(MX35, "imx25-nand", SZ_8K);
#endif
-#ifdef CONFIG_SOC_IMX51
-const struct imx_mxc_nand_data imx51_mxc_nand_data __initconst =
- imx_mxc_nandv3_data_entry_single(MX51, "imx51-nand", SZ_16K);
-#endif
-
struct platform_device *__init imx_add_mxc_nand(
const struct imx_mxc_nand_data *data,
const struct mxc_nand_platform_data *pdata)
diff --git a/arch/arm/mach-imx/devices/platform-mxc_rnga.c b/arch/arm/mach-imx/devices/platform-mxc_rnga.c
index c58404badb59..851fbc8af7a9 100644
--- a/arch/arm/mach-imx/devices/platform-mxc_rnga.c
+++ b/arch/arm/mach-imx/devices/platform-mxc_rnga.c
@@ -48,9 +48,6 @@ static int __init imxXX_add_mxc_rnga(void)
#endif /* if defined(CONFIG_SOC_IMX31) */
ret = ERR_PTR(-ENODEV);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
-
- return 0;
+ return PTR_ERR_OR_ZERO(ret);
}
arch_initcall(imxXX_add_mxc_rnga);
diff --git a/arch/arm/mach-imx/devices/platform-pata_imx.c b/arch/arm/mach-imx/devices/platform-pata_imx.c
index e4ec11c8ce55..1c7f895a69d2 100644
--- a/arch/arm/mach-imx/devices/platform-pata_imx.c
+++ b/arch/arm/mach-imx/devices/platform-pata_imx.c
@@ -28,16 +28,6 @@ const struct imx_pata_imx_data imx35_pata_imx_data __initconst =
imx_pata_imx_data_entry_single(MX35, SZ_16K);
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_pata_imx_data imx51_pata_imx_data __initconst =
- imx_pata_imx_data_entry_single(MX51, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_pata_imx_data imx53_pata_imx_data __initconst =
- imx_pata_imx_data_entry_single(MX53, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_pata_imx(
const struct imx_pata_imx_data *data)
{
diff --git a/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c b/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
index e66a4e316311..fb8d4a2ad48c 100644
--- a/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/mach-imx/devices/platform-sdhci-esdhc-imx.c
@@ -43,30 +43,6 @@ imx35_sdhci_esdhc_imx_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-const struct imx_sdhci_esdhc_imx_data
-imx51_sdhci_esdhc_imx_data[] __initconst = {
-#define imx51_sdhci_esdhc_imx_data_entry(_id, _hwid) \
- imx_sdhci_esdhc_imx_data_entry(MX51, "sdhci-esdhc-imx51", _id, _hwid)
- imx51_sdhci_esdhc_imx_data_entry(0, 1),
- imx51_sdhci_esdhc_imx_data_entry(1, 2),
- imx51_sdhci_esdhc_imx_data_entry(2, 3),
- imx51_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-const struct imx_sdhci_esdhc_imx_data
-imx53_sdhci_esdhc_imx_data[] __initconst = {
-#define imx53_sdhci_esdhc_imx_data_entry(_id, _hwid) \
- imx_sdhci_esdhc_imx_data_entry(MX53, "sdhci-esdhc-imx53", _id, _hwid)
- imx53_sdhci_esdhc_imx_data_entry(0, 1),
- imx53_sdhci_esdhc_imx_data_entry(1, 2),
- imx53_sdhci_esdhc_imx_data_entry(2, 3),
- imx53_sdhci_esdhc_imx_data_entry(3, 4),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
static const struct esdhc_platform_data default_esdhc_pdata __initconst = {
.wp_type = ESDHC_WP_NONE,
.cd_type = ESDHC_CD_NONE,
diff --git a/arch/arm/mach-imx/devices/platform-spi_imx.c b/arch/arm/mach-imx/devices/platform-spi_imx.c
index 8880bcb11e05..aca825d74c48 100644
--- a/arch/arm/mach-imx/devices/platform-spi_imx.c
+++ b/arch/arm/mach-imx/devices/platform-spi_imx.c
@@ -79,33 +79,6 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
-#ifdef CONFIG_SOC_IMX51
-/* i.mx51 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx51_cspi_data __initconst =
- imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
-#define imx51_ecspi_data_entry(_id, _hwid) \
- imx_spi_imx_data_entry(MX51, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
- imx51_ecspi_data_entry(0, 1),
- imx51_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
-#ifdef CONFIG_SOC_IMX53
-/* i.mx53 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx53_cspi_data __initconst =
- imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 2, , SZ_4K);
-
-/* i.mx53 has the i.mx51 type ecspi */
-const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
-#define imx53_ecspi_data_entry(_id, _hwid) \
- imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
- imx53_ecspi_data_entry(0, 1),
- imx53_ecspi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX53 */
-
struct platform_device *__init imx_add_spi_imx(
const struct imx_spi_imx_data *data,
const struct spi_imx_master *pdata)
diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c
index 134c190e3003..42a5a3d14c5f 100644
--- a/arch/arm/mach-imx/ehci-imx25.c
+++ b/arch/arm/mach-imx/ehci-imx25.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/platform_data/usb-ehci-mxc.h>
+#include "ehci.h"
#include "hardware.h"
#define USBCTRL_OTGBASE_OFFSET 0x600
diff --git a/arch/arm/mach-imx/ehci-imx27.c b/arch/arm/mach-imx/ehci-imx27.c
index 448d9115539d..c56974346c16 100644
--- a/arch/arm/mach-imx/ehci-imx27.c
+++ b/arch/arm/mach-imx/ehci-imx27.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/platform_data/usb-ehci-mxc.h>
+#include "ehci.h"
#include "hardware.h"
#define USBCTRL_OTGBASE_OFFSET 0x600
diff --git a/arch/arm/mach-imx/ehci-imx31.c b/arch/arm/mach-imx/ehci-imx31.c
index 05de4e1e39d7..bede21d9b981 100644
--- a/arch/arm/mach-imx/ehci-imx31.c
+++ b/arch/arm/mach-imx/ehci-imx31.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/platform_data/usb-ehci-mxc.h>
+#include "ehci.h"
#include "hardware.h"
#define USBCTRL_OTGBASE_OFFSET 0x600
diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c
index 554e7cccff53..f424a543755c 100644
--- a/arch/arm/mach-imx/ehci-imx35.c
+++ b/arch/arm/mach-imx/ehci-imx35.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/platform_data/usb-ehci-mxc.h>
+#include "ehci.h"
#include "hardware.h"
#define USBCTRL_OTGBASE_OFFSET 0x600
diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c
deleted file mode 100644
index e49710b10c68..000000000000
--- a/arch/arm/mach-imx/ehci-imx5.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/platform_data/usb-ehci-mxc.h>
-
-#include "hardware.h"
-
-#define MXC_OTG_OFFSET 0
-#define MXC_H1_OFFSET 0x200
-#define MXC_H2_OFFSET 0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT (1 << 12) /* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT (1 << 11) /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT (1 << 8) /* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_POL_BIT (1 << 9) /* OTG Polarity of Overcurrent */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) /* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_POL_BIT (1 << 6) /* UH1 Polarity of Overcurrent */
-#define MXC_H1_OC_DIS_BIT (1 << 5) /* UH1 Disable Overcurrent Event */
-#define MXC_OTG_PHYCTRL_PWR_POL_BIT (1 << 3) /* OTG Power Pin Polarity */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT (1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT (1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT (1 << 4)
-
-#define MXC_USBCMD_OFFSET 0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
-
-int mx51_initialize_usb_hw(int port, unsigned int flags)
-{
- unsigned int v;
- void __iomem *usb_base;
- void __iomem *usbotg_base;
- void __iomem *usbother_base;
- int ret = 0;
-
- usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
- if (!usb_base) {
- printk(KERN_ERR "%s(): ioremap failed\n", __func__);
- return -ENOMEM;
- }
-
- switch (port) {
- case 0: /* OTG port */
- usbotg_base = usb_base + MXC_OTG_OFFSET;
- break;
- case 1: /* Host 1 port */
- usbotg_base = usb_base + MXC_H1_OFFSET;
- break;
- case 2: /* Host 2 port */
- usbotg_base = usb_base + MXC_H2_OFFSET;
- break;
- default:
- printk(KERN_ERR"%s no such port %d\n", __func__, port);
- ret = -ENOENT;
- goto error;
- }
- usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
- switch (port) {
- case 0: /*OTG port */
- if (flags & MXC_EHCI_INTERNAL_PHY) {
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
- v |= MXC_OTG_PHYCTRL_OC_POL_BIT;
- else
- v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT;
- if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
- /* OC/USBPWR is used */
- v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
- } else {
- /* OC/USBPWR is not used */
- v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
- }
- if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
- v |= MXC_OTG_PHYCTRL_PWR_POL_BIT;
- else
- v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT;
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED)
- v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
- else
- v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_OTG_UCTRL_OPM_BIT;
- else
- v |= MXC_OTG_UCTRL_OPM_BIT;
- __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
- }
- break;
- case 1: /* Host 1 */
- /*Host ULPI */
- v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED) {
- /* HOST1 wakeup/ULPI intr enable */
- v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
- } else {
- /* HOST1 wakeup/ULPI intr disable */
- v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
- }
-
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask unused*/
- else
- v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
- __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
- v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
- if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
- v |= MXC_H1_OC_POL_BIT;
- else
- v &= ~MXC_H1_OC_POL_BIT;
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
- else
- v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
- __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
- v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
- if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
- /* Interrupt Threshold Control:Immediate (no threshold) */
- v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
- __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
- break;
- case 2: /* Host 2 ULPI */
- v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
- if (flags & MXC_EHCI_WAKEUP_ENABLED) {
- /* HOST1 wakeup/ULPI intr enable */
- v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
- } else {
- /* HOST1 wakeup/ULPI intr disable */
- v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
- }
-
- if (flags & MXC_EHCI_POWER_PINS_ENABLED)
- v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask unused*/
- else
- v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
- __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
- break;
- }
-
-error:
- iounmap(usb_base);
- return ret;
-}
-
diff --git a/arch/arm/mach-imx/ehci.h b/arch/arm/mach-imx/ehci.h
new file mode 100644
index 000000000000..0e060023db8b
--- /dev/null
+++ b/arch/arm/mach-imx/ehci.h
@@ -0,0 +1,43 @@
+#ifndef __MACH_IMX_EHCI_H
+#define __MACH_IMX_EHCI_H
+
+/* values for portsc field */
+#define MXC_EHCI_PHY_LOW_POWER_SUSPEND (1 << 23)
+#define MXC_EHCI_FORCE_FS (1 << 24)
+#define MXC_EHCI_UTMI_8BIT (0 << 28)
+#define MXC_EHCI_UTMI_16BIT (1 << 28)
+#define MXC_EHCI_SERIAL (1 << 29)
+#define MXC_EHCI_MODE_UTMI (0 << 30)
+#define MXC_EHCI_MODE_PHILIPS (1 << 30)
+#define MXC_EHCI_MODE_ULPI (2 << 30)
+#define MXC_EHCI_MODE_SERIAL (3 << 30)
+
+/* values for flags field */
+#define MXC_EHCI_INTERFACE_DIFF_UNI (0 << 0)
+#define MXC_EHCI_INTERFACE_DIFF_BI (1 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_UNI (2 << 0)
+#define MXC_EHCI_INTERFACE_SINGLE_BI (3 << 0)
+#define MXC_EHCI_INTERFACE_MASK (0xf)
+
+#define MXC_EHCI_POWER_PINS_ENABLED (1 << 5)
+#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH (1 << 6)
+#define MXC_EHCI_OC_PIN_ACTIVE_LOW (1 << 7)
+#define MXC_EHCI_TTL_ENABLED (1 << 8)
+
+#define MXC_EHCI_INTERNAL_PHY (1 << 9)
+#define MXC_EHCI_IPPUE_DOWN (1 << 10)
+#define MXC_EHCI_IPPUE_UP (1 << 11)
+#define MXC_EHCI_WAKEUP_ENABLED (1 << 12)
+#define MXC_EHCI_ITC_NO_THRESHOLD (1 << 13)
+
+#define MXC_USBCTRL_OFFSET 0
+#define MXC_USB_PHY_CTR_FUNC_OFFSET 0x8
+#define MXC_USB_PHY_CTR_FUNC2_OFFSET 0xc
+#define MXC_USBH2CTRL_OFFSET 0x14
+
+int mx25_initialize_usb_hw(int port, unsigned int flags);
+int mx31_initialize_usb_hw(int port, unsigned int flags);
+int mx35_initialize_usb_hw(int port, unsigned int flags);
+int mx27_initialize_usb_hw(int port, unsigned int flags);
+
+#endif /* __MACH_IMX_EHCI_H */
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 586e0171a652..82ea74e68482 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -27,13 +27,14 @@ static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
-void imx_gpc_pre_suspend(void)
+void imx_gpc_pre_suspend(bool arm_power_off)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Tell GPC to power off ARM core when suspend */
- writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+ if (arm_power_off)
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++) {
gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index abf43bb47eca..66b2b564c463 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -105,8 +105,6 @@
#include "mxc.h"
-#include "mx51.h"
-#include "mx53.h"
#include "mx3x.h"
#include "mx31.h"
#include "mx35.h"
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
index 42a65e067443..cf8032bae277 100644
--- a/arch/arm/mach-imx/imx25-dt.c
+++ b/arch/arm/mach-imx/imx25-dt.c
@@ -29,16 +29,10 @@ static const char * const imx25_dt_board_compat[] __initconst = {
NULL
};
-static void __init imx25_timer_init(void)
-{
- mx25_clocks_init_dt();
-}
-
DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
.map_io = mx25_map_io,
.init_early = imx25_init_early,
.init_irq = mx25_init_irq,
- .init_time = imx25_timer_init,
.init_machine = imx25_dt_init,
.dt_compat = imx25_dt_board_compat,
.restart = mxc_restart,
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index 17bd4058133d..080e66c6a1d0 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -34,16 +34,10 @@ static const char * const imx27_dt_board_compat[] __initconst = {
NULL
};
-static void __init imx27_timer_init(void)
-{
- mx27_clocks_init_dt();
-}
-
DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
.map_io = mx27_map_io,
.init_early = imx27_init_early,
.init_irq = mx27_init_irq,
- .init_time = imx27_timer_init,
.init_machine = imx27_dt_init,
.dt_compat = imx27_dt_board_compat,
.restart = mxc_restart,
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
index 581f4d6c9b8a..418dbc82adc4 100644
--- a/arch/arm/mach-imx/imx31-dt.c
+++ b/arch/arm/mach-imx/imx31-dt.c
@@ -25,7 +25,7 @@ static void __init imx31_dt_init(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
-static const char *imx31_dt_board_compat[] __initconst = {
+static const char * const imx31_dt_board_compat[] __initconst = {
"fsl,imx31",
NULL
};
diff --git a/arch/arm/mach-imx/imx35-dt.c b/arch/arm/mach-imx/imx35-dt.c
index a62854c59240..584fbe105579 100644
--- a/arch/arm/mach-imx/imx35-dt.c
+++ b/arch/arm/mach-imx/imx35-dt.c
@@ -34,7 +34,7 @@ static void __init imx35_irq_init(void)
mx35_init_irq();
}
-static const char *imx35_dt_board_compat[] __initconst = {
+static const char * const imx35_dt_board_compat[] __initconst = {
"fsl,imx35",
NULL
};
diff --git a/arch/arm/mach-imx/iomux-mx51.h b/arch/arm/mach-imx/iomux-mx51.h
deleted file mode 100644
index 75bbcc4aa2d2..000000000000
--- a/arch/arm/mach-imx/iomux-mx51.h
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_IOMUX_MX51_H__
-#define __MACH_IOMUX_MX51_H__
-
-#include "iomux-v3.h"
-#define __NA_ 0x000
-
-
-/* Pad control groupings */
-#define MX51_UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_HIGH | \
- PAD_CTL_HYS | PAD_CTL_SRE_FAST)
-#define MX51_I2C_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
- PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
- PAD_CTL_HYS)
-#define MX51_ESDHC_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_ODE | \
- PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
- PAD_CTL_HYS)
-#define MX51_USBH1_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
- PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP | \
- PAD_CTL_HYS | PAD_CTL_PUE)
-#define MX51_ECSPI_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_HYS | \
- PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
-#define MX51_SDHCI_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
- PAD_CTL_PUS_47K_UP | PAD_CTL_PUE | \
- PAD_CTL_SRE_FAST | PAD_CTL_DVS)
-#define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE_FAST)
-
-#define MX51_PAD_CTRL_2 (PAD_CTL_PKE | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_3 (PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_CTRL_4 (PAD_CTL_PKE | PAD_CTL_DVS | PAD_CTL_HYS)
-#define MX51_PAD_CTRL_5 (PAD_CTL_DVS | PAD_CTL_DSE_HIGH)
-
-/*
- * The naming convention for the pad modes is MX51_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO<unit>_<num>
- * See also iomux-v3.h
- */
-
-/* Raw pin modes without pad control */
-/* PAD MUX ALT INPSE PATH PADCTRL */
-
-/* The same pins as above but with the default pad control values applied */
-#define MX51_PAD_EIM_D16__AUD4_RXFS IOMUX_PAD(0x3f0, 0x05c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__AUD5_TXD IOMUX_PAD(0x3f0, 0x05c, 7, 0x8d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__EIM_D16 IOMUX_PAD(0x3f0, 0x05c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__GPIO2_0 IOMUX_PAD(0x3f0, 0x05c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D16__I2C1_SDA IOMUX_PAD(0x3f0, 0x05c, 0x14, 0x9b4, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D16__UART2_CTS IOMUX_PAD(0x3f0, 0x05c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D16__USBH2_DATA0 IOMUX_PAD(0x3f0, 0x05c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__AUD5_RXD IOMUX_PAD(0x3f4, 0x060, 7, 0x8d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__EIM_D17 IOMUX_PAD(0x3f4, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__GPIO2_1 IOMUX_PAD(0x3f4, 0x060, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART2_RXD IOMUX_PAD(0x3f4, 0x060, 3, 0x9ec, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__UART3_CTS IOMUX_PAD(0x3f4, 0x060, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D17__USBH2_DATA1 IOMUX_PAD(0x3f4, 0x060, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__AUD5_TXC IOMUX_PAD(0x3f8, 0x064, 7, 0x8e4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__EIM_D18 IOMUX_PAD(0x3f8, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__GPIO2_2 IOMUX_PAD(0x3f8, 0x064, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART2_TXD IOMUX_PAD(0x3f8, 0x064, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__UART3_RTS IOMUX_PAD(0x3f8, 0x064, 4, 0x9f0, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D18__USBH2_DATA2 IOMUX_PAD(0x3f8, 0x064, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD4_RXC IOMUX_PAD(0x3fc, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__AUD5_TXFS IOMUX_PAD(0x3fc, 0x068, 7, 0x8e8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__EIM_D19 IOMUX_PAD(0x3fc, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__GPIO2_3 IOMUX_PAD(0x3fc, 0x068, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D19__I2C1_SCL IOMUX_PAD(0x3fc, 0x068, 0x14, 0x9b0, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D19__UART2_RTS IOMUX_PAD(0x3fc, 0x068, 3, 0x9e8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D19__USBH2_DATA3 IOMUX_PAD(0x3fc, 0x068, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__AUD4_TXD IOMUX_PAD(0x400, 0x06c, 5, 0x8c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__EIM_D20 IOMUX_PAD(0x400, 0x06c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__GPIO2_4 IOMUX_PAD(0x400, 0x06c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__SRTC_ALARM_DEB IOMUX_PAD(0x400, 0x06c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D20__USBH2_DATA4 IOMUX_PAD(0x400, 0x06c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__AUD4_RXD IOMUX_PAD(0x404, 0x070, 5, 0x8c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__EIM_D21 IOMUX_PAD(0x404, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__GPIO2_5 IOMUX_PAD(0x404, 0x070, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__SRTC_ALARM_DEB IOMUX_PAD(0x404, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D21__USBH2_DATA5 IOMUX_PAD(0x404, 0x070, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__AUD4_TXC IOMUX_PAD(0x408, 0x074, 5, 0x8cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__EIM_D22 IOMUX_PAD(0x408, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__GPIO2_6 IOMUX_PAD(0x408, 0x074, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D22__USBH2_DATA6 IOMUX_PAD(0x408, 0x074, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__AUD4_TXFS IOMUX_PAD(0x40c, 0x078, 5, 0x8d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__EIM_D23 IOMUX_PAD(0x40c, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__GPIO2_7 IOMUX_PAD(0x40c, 0x078, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__SPDIF_OUT1 IOMUX_PAD(0x40c, 0x078, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D23__USBH2_DATA7 IOMUX_PAD(0x40c, 0x078, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__AUD6_RXFS IOMUX_PAD(0x410, 0x07c, 5, 0x8f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__EIM_D24 IOMUX_PAD(0x410, 0x07c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__GPIO2_8 IOMUX_PAD(0x410, 0x07c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D24__I2C2_SDA IOMUX_PAD(0x410, 0x07c, 0x14, 0x9bc, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D24__UART3_CTS IOMUX_PAD(0x410, 0x07c, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D24__USBOTG_DATA0 IOMUX_PAD(0x410, 0x07c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__EIM_D25 IOMUX_PAD(0x414, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__KEY_COL6 IOMUX_PAD(0x414, 0x080, 1, 0x9c8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART2_CTS IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__UART3_RXD IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D25__USBOTG_DATA1 IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D25__GPT_CMPOUT1 IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__EIM_D26 IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__KEY_COL7 IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART2_RTS IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__UART3_TXD IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D26__USBOTG_DATA2 IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D26__GPT_CMPOUT2 IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__AUD6_RXC IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__EIM_D27 IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__GPIO2_9 IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_D27__I2C2_SCL IOMUX_PAD(0x41c, 0x088, 0x14, 0x9b8, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_EIM_D27__UART3_RTS IOMUX_PAD(0x41c, 0x088, 3, 0x9f0, 3, MX51_UART_PAD_CTRL)
-#define MX51_PAD_EIM_D27__USBOTG_DATA3 IOMUX_PAD(0x41c, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__AUD6_TXD IOMUX_PAD(0x420, 0x08c, 5, 0x8f0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__EIM_D28 IOMUX_PAD(0x420, 0x08c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__KEY_ROW4 IOMUX_PAD(0x420, 0x08c, 1, 0x9d0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D28__USBOTG_DATA4 IOMUX_PAD(0x420, 0x08c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__AUD6_RXD IOMUX_PAD(0x424, 0x090, 5, 0x8ec, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__EIM_D29 IOMUX_PAD(0x424, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__KEY_ROW5 IOMUX_PAD(0x424, 0x090, 1, 0x9d4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D29__USBOTG_DATA5 IOMUX_PAD(0x424, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__AUD6_TXC IOMUX_PAD(0x428, 0x094, 5, 0x8fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__EIM_D30 IOMUX_PAD(0x428, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__KEY_ROW6 IOMUX_PAD(0x428, 0x094, 1, 0x9d8, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D30__USBOTG_DATA6 IOMUX_PAD(0x428, 0x094, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__AUD6_TXFS IOMUX_PAD(0x42c, 0x098, 5, 0x900, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__EIM_D31 IOMUX_PAD(0x42c, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__KEY_ROW7 IOMUX_PAD(0x42c, 0x098, 1, 0x9dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_D31__USBOTG_DATA7 IOMUX_PAD(0x42c, 0x098, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__EIM_A16 IOMUX_PAD(0x430, 0x09c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__GPIO2_10 IOMUX_PAD(0x430, 0x09c, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A16__OSC_FREQ_SEL0 IOMUX_PAD(0x430, 0x09c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__EIM_A17 IOMUX_PAD(0x434, 0x0a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__GPIO2_11 IOMUX_PAD(0x434, 0x0a0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A17__OSC_FREQ_SEL1 IOMUX_PAD(0x434, 0x0a0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__BOOT_LPB0 IOMUX_PAD(0x438, 0x0a4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__EIM_A18 IOMUX_PAD(0x438, 0x0a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A18__GPIO2_12 IOMUX_PAD(0x438, 0x0a4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__BOOT_LPB1 IOMUX_PAD(0x43c, 0x0a8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__EIM_A19 IOMUX_PAD(0x43c, 0x0a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A19__GPIO2_13 IOMUX_PAD(0x43c, 0x0a8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__BOOT_UART_SRC0 IOMUX_PAD(0x440, 0x0ac, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__EIM_A20 IOMUX_PAD(0x440, 0x0ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A20__GPIO2_14 IOMUX_PAD(0x440, 0x0ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__BOOT_UART_SRC1 IOMUX_PAD(0x444, 0x0b0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__EIM_A21 IOMUX_PAD(0x444, 0x0b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A21__GPIO2_15 IOMUX_PAD(0x444, 0x0b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__EIM_A22 IOMUX_PAD(0x448, 0x0b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A22__GPIO2_16 IOMUX_PAD(0x448, 0x0b4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__BOOT_HPN_EN IOMUX_PAD(0x44c, 0x0b8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__EIM_A23 IOMUX_PAD(0x44c, 0x0b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A23__GPIO2_17 IOMUX_PAD(0x44c, 0x0b8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__EIM_A24 IOMUX_PAD(0x450, 0x0bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__GPIO2_18 IOMUX_PAD(0x450, 0x0bc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A24__USBH2_CLK IOMUX_PAD(0x450, 0x0bc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__DISP1_PIN4 IOMUX_PAD(0x454, 0x0c0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__EIM_A25 IOMUX_PAD(0x454, 0x0c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__GPIO2_19 IOMUX_PAD(0x454, 0x0c0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A25__USBH2_DIR IOMUX_PAD(0x454, 0x0c0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__CSI1_DATA_EN IOMUX_PAD(0x458, 0x0c4, 5, 0x9a0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__DISP2_EXT_CLK IOMUX_PAD(0x458, 0x0c4, 6, 0x908, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__EIM_A26 IOMUX_PAD(0x458, 0x0c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__GPIO2_20 IOMUX_PAD(0x458, 0x0c4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A26__USBH2_STP IOMUX_PAD(0x458, 0x0c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__CSI2_DATA_EN IOMUX_PAD(0x45c, 0x0c8, 5, 0x99c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__DISP1_PIN1 IOMUX_PAD(0x45c, 0x0c8, 6, 0x9a4, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__EIM_A27 IOMUX_PAD(0x45c, 0x0c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__GPIO2_21 IOMUX_PAD(0x45c, 0x0c8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_A27__USBH2_NXT IOMUX_PAD(0x45c, 0x0c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB0__EIM_EB0 IOMUX_PAD(0x460, 0x0cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB1__EIM_EB1 IOMUX_PAD(0x464, 0x0d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__AUD5_RXFS IOMUX_PAD(0x468, 0x0d4, 6, 0x8e0, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__CSI1_D2 IOMUX_PAD(0x468, 0x0d4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__EIM_EB2 IOMUX_PAD(0x468, 0x0d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__FEC_MDIO (IOMUX_PAD(0x468, 0x0d4, 3, 0x954, 0, 0) | \
- MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP | PAD_CTL_PKE | PAD_CTL_SRE_FAST | \
- PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS))
-#define MX51_PAD_EIM_EB2__GPIO2_22 IOMUX_PAD(0x468, 0x0d4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB2__GPT_CMPOUT1 IOMUX_PAD(0x468, 0x0d4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__AUD5_RXC IOMUX_PAD(0x46c, 0x0d8, 6, 0x8dc, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__CSI1_D3 IOMUX_PAD(0x46c, 0x0d8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__EIM_EB3 IOMUX_PAD(0x46c, 0x0d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__FEC_RDATA1 IOMUX_PAD(0x46c, 0x0d8, 3, 0x95c, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPIO2_23 IOMUX_PAD(0x46c, 0x0d8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_EB3__GPT_CMPOUT2 IOMUX_PAD(0x46c, 0x0d8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__EIM_OE IOMUX_PAD(0x470, 0x0dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_OE__GPIO2_24 IOMUX_PAD(0x470, 0x0dc, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__EIM_CS0 IOMUX_PAD(0x474, 0x0e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS0__GPIO2_25 IOMUX_PAD(0x474, 0x0e0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__EIM_CS1 IOMUX_PAD(0x478, 0x0e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS1__GPIO2_26 IOMUX_PAD(0x478, 0x0e4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__AUD5_TXD IOMUX_PAD(0x47c, 0x0e8, 6, 0x8d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__CSI1_D4 IOMUX_PAD(0x47c, 0x0e8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__EIM_CS2 IOMUX_PAD(0x47c, 0x0e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__FEC_RDATA2 IOMUX_PAD(0x47c, 0x0e8, 3, 0x960, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__GPIO2_27 IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS2__USBOTG_STP IOMUX_PAD(0x47c, 0x0e8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__AUD5_RXD IOMUX_PAD(0x480, 0x0ec, 6, 0x8d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__CSI1_D5 IOMUX_PAD(0x480, 0x0ec, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__EIM_CS3 IOMUX_PAD(0x480, 0x0ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__FEC_RDATA3 IOMUX_PAD(0x480, 0x0ec, 3, 0x964, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__GPIO2_28 IOMUX_PAD(0x480, 0x0ec, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS3__USBOTG_NXT IOMUX_PAD(0x480, 0x0ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__AUD5_TXC IOMUX_PAD(0x484, 0x0f0, 6, 0x8e4, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__CSI1_D6 IOMUX_PAD(0x484, 0x0f0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__EIM_CS4 IOMUX_PAD(0x484, 0x0f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__FEC_RX_ER IOMUX_PAD(0x484, 0x0f0, 3, 0x970, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS4__GPIO2_29 IOMUX_PAD(0x484, 0x0f0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS4__USBOTG_CLK IOMUX_PAD(0x484, 0x0f0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__AUD5_TXFS IOMUX_PAD(0x488, 0x0f4, 6, 0x8e8, 1, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__CSI1_D7 IOMUX_PAD(0x488, 0x0f4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__DISP1_EXT_CLK IOMUX_PAD(0x488, 0x0f4, 4, 0x904, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__EIM_CS5 IOMUX_PAD(0x488, 0x0f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__FEC_CRS IOMUX_PAD(0x488, 0x0f4, 3, 0x950, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_EIM_CS5__GPIO2_30 IOMUX_PAD(0x488, 0x0f4, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CS5__USBOTG_DIR IOMUX_PAD(0x488, 0x0f4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__EIM_DTACK IOMUX_PAD(0x48c, 0x0f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DTACK__GPIO2_31 IOMUX_PAD(0x48c, 0x0f8, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__EIM_LBA IOMUX_PAD(0x494, 0x0fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_LBA__GPIO3_1 IOMUX_PAD(0x494, 0x0fc, 1, 0x978, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__EIM_CRE IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_CRE__GPIO3_2 IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__DRAM_CS1 IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DRAM_CS1__CCM_CLKO IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__GPIO3_3 IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__NANDF_WE_B IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__PATA_DIOW IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0 IOMUX_PAD(0x4e4, 0x108, 2, 0x93c, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__GPIO3_4 IOMUX_PAD(0x4e8, 0x10c, 3, 0x984, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__NANDF_RE_B IOMUX_PAD(0x4e8, 0x10c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__PATA_DIOR IOMUX_PAD(0x4e8, 0x10c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1 IOMUX_PAD(0x4e8, 0x10c, 2, 0x940, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__GPIO3_5 IOMUX_PAD(0x4ec, 0x110, 3, 0x988, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__NANDF_ALE IOMUX_PAD(0x4ec, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN IOMUX_PAD(0x4ec, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__GPIO3_6 IOMUX_PAD(0x4f0, 0x114, 3, 0x98c, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__NANDF_CLE IOMUX_PAD(0x4f0, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CLE__PATA_RESET_B IOMUX_PAD(0x4f0, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__GPIO3_7 IOMUX_PAD(0x4f4, 0x118, 3, 0x990, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__NANDF_WP_B IOMUX_PAD(0x4f4, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__PATA_DMACK IOMUX_PAD(0x4f4, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2 IOMUX_PAD(0x4f4, 0x118, 2, 0x944, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__ECSPI2_SS1 IOMUX_PAD(0x4f8, 0x11c, 5, 0x930, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__GPIO3_8 IOMUX_PAD(0x4f8, 0x11c, 3, 0x994, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__NANDF_RB0 IOMUX_PAD(0x4f8, 0x11c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__PATA_DMARQ IOMUX_PAD(0x4f8, 0x11c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB0__SD3_DATA3 IOMUX_PAD(0x4f8, 0x11c, 2, 0x948, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__CSPI_MOSI IOMUX_PAD(0x4fc, 0x120, 6, 0x91c, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__ECSPI2_RDY IOMUX_PAD(0x4fc, 0x120, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPIO3_9 IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__NANDF_RB1 IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__PATA_IORDY IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2 IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__DISP2_WAIT IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB2__GPIO3_10 IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__NANDF_RB2 IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3 IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB2__USBH3_NXT IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__DISP1_WAIT IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__FEC_RX_CLK IOMUX_PAD(0x504, 0x128, 1, 0x968, 0, MX51_PAD_CTRL_2)
-#define MX51_PAD_NANDF_RB3__GPIO3_11 IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__NANDF_RB3 IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_CLK IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__GPIO_NAND IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO_NAND__PATA_INTRQ IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__GPIO3_16 IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS0__NANDF_CS0 IOMUX_PAD(0x518, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__GPIO3_17 IOMUX_PAD(0x51c, 0x134, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS1__NANDF_CS1 IOMUX_PAD(0x51c, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__CSPI_SCLK IOMUX_PAD(0x520, 0x138, 6, 0x914, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__FEC_TX_ER IOMUX_PAD(0x520, 0x138, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS2__GPIO3_18 IOMUX_PAD(0x520, 0x138, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__NANDF_CS2 IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__PATA_CS_0 IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS2__SD4_CLK IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS3__GPIO3_19 IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__NANDF_CS3 IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__PATA_CS_1 IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__SD4_DAT0 IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__FEC_TDATA1 IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS4__GPIO3_20 IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__NANDF_CS4 IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__PATA_DA_0 IOMUX_PAD(0x528, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__SD4_DAT1 IOMUX_PAD(0x528, 0x140, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS4__USBH3_STP IOMUX_PAD(0x528, 0x140, 7, 0xa24, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__FEC_TDATA2 IOMUX_PAD(0x52c, 0x144, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS5__GPIO3_21 IOMUX_PAD(0x52c, 0x144, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__NANDF_CS5 IOMUX_PAD(0x52c, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__PATA_DA_1 IOMUX_PAD(0x52c, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__SD4_DAT2 IOMUX_PAD(0x52c, 0x144, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS5__USBH3_DIR IOMUX_PAD(0x52c, 0x144, 7, 0xa1c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__CSPI_SS3 IOMUX_PAD(0x530, 0x148, 7, 0x928, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__FEC_TDATA3 IOMUX_PAD(0x530, 0x148, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS6__GPIO3_22 IOMUX_PAD(0x530, 0x148, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__NANDF_CS6 IOMUX_PAD(0x530, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__PATA_DA_2 IOMUX_PAD(0x530, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS6__SD4_DAT3 IOMUX_PAD(0x530, 0x148, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__FEC_TX_EN IOMUX_PAD(0x534, 0x14c, 1, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_CS7__GPIO3_23 IOMUX_PAD(0x534, 0x14c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__NANDF_CS7 IOMUX_PAD(0x534, 0x14c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_CS7__SD3_CLK IOMUX_PAD(0x534, 0x14c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 IOMUX_PAD(0x538, 0x150, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_RDY_INT__GPIO3_24 IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__GPIO3_25 IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__NANDF_D15 IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__PATA_DATA15 IOMUX_PAD(0x53c, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D15__SD3_DAT7 IOMUX_PAD(0x53c, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__ECSPI2_SS3 IOMUX_PAD(0x540, 0x158, 2, 0x934, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__GPIO3_26 IOMUX_PAD(0x540, 0x158, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__NANDF_D14 IOMUX_PAD(0x540, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__PATA_DATA14 IOMUX_PAD(0x540, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D14__SD3_DAT6 IOMUX_PAD(0x540, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__ECSPI2_SS2 IOMUX_PAD(0x544, 0x15c, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__GPIO3_27 IOMUX_PAD(0x544, 0x15c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__NANDF_D13 IOMUX_PAD(0x544, 0x15c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__PATA_DATA13 IOMUX_PAD(0x544, 0x15c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D13__SD3_DAT5 IOMUX_PAD(0x544, 0x15c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__ECSPI2_SS1 IOMUX_PAD(0x548, 0x160, 2, 0x930, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__GPIO3_28 IOMUX_PAD(0x548, 0x160, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__NANDF_D12 IOMUX_PAD(0x548, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__PATA_DATA12 IOMUX_PAD(0x548, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D12__SD3_DAT4 IOMUX_PAD(0x548, 0x160, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__FEC_RX_DV IOMUX_PAD(0x54c, 0x164, 2, 0x96c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__GPIO3_29 IOMUX_PAD(0x54c, 0x164, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__NANDF_D11 IOMUX_PAD(0x54c, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__PATA_DATA11 IOMUX_PAD(0x54c, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D11__SD3_DATA3 IOMUX_PAD(0x54c, 0x164, 5, 0x948, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__GPIO3_30 IOMUX_PAD(0x550, 0x168, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__NANDF_D10 IOMUX_PAD(0x550, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__PATA_DATA10 IOMUX_PAD(0x550, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D10__SD3_DATA2 IOMUX_PAD(0x550, 0x168, 5, 0x944, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__FEC_RDATA0 IOMUX_PAD(0x554, 0x16c, 0x12, 0x958, 0, MX51_PAD_CTRL_4)
-#define MX51_PAD_NANDF_D9__GPIO3_31 IOMUX_PAD(0x554, 0x16c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__NANDF_D9 IOMUX_PAD(0x554, 0x16c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__PATA_DATA9 IOMUX_PAD(0x554, 0x16c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D9__SD3_DATA1 IOMUX_PAD(0x554, 0x16c, 5, 0x940, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__FEC_TDATA0 IOMUX_PAD(0x558, 0x170, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_NANDF_D8__GPIO4_0 IOMUX_PAD(0x558, 0x170, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__NANDF_D8 IOMUX_PAD(0x558, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__PATA_DATA8 IOMUX_PAD(0x558, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D8__SD3_DATA0 IOMUX_PAD(0x558, 0x170, 5, 0x93c, 1, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__GPIO4_1 IOMUX_PAD(0x55c, 0x174, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__NANDF_D7 IOMUX_PAD(0x55c, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__PATA_DATA7 IOMUX_PAD(0x55c, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D7__USBH3_DATA0 IOMUX_PAD(0x55c, 0x174, 5, 0x9fc, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__GPIO4_2 IOMUX_PAD(0x560, 0x178, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__NANDF_D6 IOMUX_PAD(0x560, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__PATA_DATA6 IOMUX_PAD(0x560, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__SD4_LCTL IOMUX_PAD(0x560, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D6__USBH3_DATA1 IOMUX_PAD(0x560, 0x178, 5, 0xa00, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__GPIO4_3 IOMUX_PAD(0x564, 0x17c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__NANDF_D5 IOMUX_PAD(0x564, 0x17c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__PATA_DATA5 IOMUX_PAD(0x564, 0x17c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__SD4_WP IOMUX_PAD(0x564, 0x17c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D5__USBH3_DATA2 IOMUX_PAD(0x564, 0x17c, 5, 0xa04, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__GPIO4_4 IOMUX_PAD(0x568, 0x180, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__NANDF_D4 IOMUX_PAD(0x568, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__PATA_DATA4 IOMUX_PAD(0x568, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__SD4_CD IOMUX_PAD(0x568, 0x180, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D4__USBH3_DATA3 IOMUX_PAD(0x568, 0x180, 5, 0xa08, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__GPIO4_5 IOMUX_PAD(0x56c, 0x184, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__NANDF_D3 IOMUX_PAD(0x56c, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__PATA_DATA3 IOMUX_PAD(0x56c, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__SD4_DAT4 IOMUX_PAD(0x56c, 0x184, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D3__USBH3_DATA4 IOMUX_PAD(0x56c, 0x184, 5, 0xa0c, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__GPIO4_6 IOMUX_PAD(0x570, 0x188, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__NANDF_D2 IOMUX_PAD(0x570, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__PATA_DATA2 IOMUX_PAD(0x570, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__SD4_DAT5 IOMUX_PAD(0x570, 0x188, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D2__USBH3_DATA5 IOMUX_PAD(0x570, 0x188, 5, 0xa10, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__GPIO4_7 IOMUX_PAD(0x574, 0x18c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__NANDF_D1 IOMUX_PAD(0x574, 0x18c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__PATA_DATA1 IOMUX_PAD(0x574, 0x18c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__SD4_DAT6 IOMUX_PAD(0x574, 0x18c, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D1__USBH3_DATA6 IOMUX_PAD(0x574, 0x18c, 5, 0xa14, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__GPIO4_8 IOMUX_PAD(0x578, 0x190, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__NANDF_D0 IOMUX_PAD(0x578, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__PATA_DATA0 IOMUX_PAD(0x578, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__SD4_DAT7 IOMUX_PAD(0x578, 0x190, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_NANDF_D0__USBH3_DATA7 IOMUX_PAD(0x578, 0x190, 5, 0xa18, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__CSI1_D8 IOMUX_PAD(0x57c, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D8__GPIO3_12 IOMUX_PAD(0x57c, 0x194, 3, 0x998, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__CSI1_D9 IOMUX_PAD(0x580, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D9__GPIO3_13 IOMUX_PAD(0x580, 0x198, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_D10__CSI1_D10 IOMUX_PAD(0x584, 0x19c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D11__CSI1_D11 IOMUX_PAD(0x588, 0x1a0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D12__CSI1_D12 IOMUX_PAD(0x58c, 0x1a4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D13__CSI1_D13 IOMUX_PAD(0x590, 0x1a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D14__CSI1_D14 IOMUX_PAD(0x594, 0x1ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D15__CSI1_D15 IOMUX_PAD(0x598, 0x1b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D16__CSI1_D16 IOMUX_PAD(0x59c, 0x1b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D17__CSI1_D17 IOMUX_PAD(0x5a0, 0x1b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D18__CSI1_D18 IOMUX_PAD(0x5a4, 0x1bc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_D19__CSI1_D19 IOMUX_PAD(0x5a8, 0x1c0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__CSI1_VSYNC IOMUX_PAD(0x5ac, 0x1c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_VSYNC__GPIO3_14 IOMUX_PAD(0x5ac, 0x1c4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__CSI1_HSYNC IOMUX_PAD(0x5b0, 0x1c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_HSYNC__GPIO3_15 IOMUX_PAD(0x5b0, 0x1c8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI1_PIXCLK__CSI1_PIXCLK IOMUX_PAD(0x5b4, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI1_MCLK__CSI1_MCLK IOMUX_PAD(0x5b8, __NA_, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__CSI2_D12 IOMUX_PAD(0x5bc, 0x1cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D12__GPIO4_9 IOMUX_PAD(0x5bc, 0x1cc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__CSI2_D13 IOMUX_PAD(0x5c0, 0x1d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D13__GPIO4_10 IOMUX_PAD(0x5c0, 0x1d0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D14__CSI2_D14 IOMUX_PAD(0x5c4, 0x1d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D15__CSI2_D15 IOMUX_PAD(0x5c8, 0x1d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D16__CSI2_D16 IOMUX_PAD(0x5cc, 0x1dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D17__CSI2_D17 IOMUX_PAD(0x5d0, 0x1e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__CSI2_D18 IOMUX_PAD(0x5d4, 0x1e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D18__GPIO4_11 IOMUX_PAD(0x5d4, 0x1e4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__CSI2_D19 IOMUX_PAD(0x5d8, 0x1e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_D19__GPIO4_12 IOMUX_PAD(0x5d8, 0x1e8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__CSI2_VSYNC IOMUX_PAD(0x5dc, 0x1ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_VSYNC__GPIO4_13 IOMUX_PAD(0x5dc, 0x1ec, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__CSI2_HSYNC IOMUX_PAD(0x5e0, 0x1f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_HSYNC__GPIO4_14 IOMUX_PAD(0x5e0, 0x1f0, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__CSI2_PIXCLK IOMUX_PAD(0x5e4, 0x1f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_CSI2_PIXCLK__GPIO4_15 IOMUX_PAD(0x5e4, 0x1f4, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__GPIO4_16 IOMUX_PAD(0x5e8, 0x1f8, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_CLK__I2C1_CLK IOMUX_PAD(0x5e8, 0x1f8, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__GPIO4_17 IOMUX_PAD(0x5ec, 0x1fc, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_I2C1_DAT__I2C1_DAT IOMUX_PAD(0x5ec, 0x1fc, 0x10, __NA_, 0, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__AUD3_TXD IOMUX_PAD(0x5f0, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_TXD__GPIO4_18 IOMUX_PAD(0x5f0, 0x200, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__AUD3_RXD IOMUX_PAD(0x5f4, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__GPIO4_19 IOMUX_PAD(0x5f4, 0x204, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_RXD__UART3_RXD IOMUX_PAD(0x5f4, 0x204, 1, 0x9f4, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__AUD3_TXC IOMUX_PAD(0x5f8, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_CK__GPIO4_20 IOMUX_PAD(0x5f8, 0x208, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__AUD3_TXFS IOMUX_PAD(0x5fc, 0x20c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__GPIO4_21 IOMUX_PAD(0x5fc, 0x20c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_AUD3_BB_FS__UART3_TXD IOMUX_PAD(0x5fc, 0x20c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI IOMUX_PAD(0x600, 0x210, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__GPIO4_22 IOMUX_PAD(0x600, 0x210, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MOSI__I2C1_SDA IOMUX_PAD(0x600, 0x210, 0x11, 0x9b4, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__AUD4_RXD IOMUX_PAD(0x604, 0x214, 1, 0x8c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__ECSPI1_MISO IOMUX_PAD(0x604, 0x214, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_MISO__GPIO4_23 IOMUX_PAD(0x604, 0x214, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__AUD4_TXC IOMUX_PAD(0x608, 0x218, 1, 0x8cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__ECSPI1_SS0 IOMUX_PAD(0x608, 0x218, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS0__GPIO4_24 IOMUX_PAD(0x608, 0x218, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__AUD4_TXD IOMUX_PAD(0x60c, 0x21c, 1, 0x8c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__ECSPI1_SS1 IOMUX_PAD(0x60c, 0x21c, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SS1__GPIO4_25 IOMUX_PAD(0x60c, 0x21c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__AUD4_TXFS IOMUX_PAD(0x610, 0x220, 1, 0x8d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__ECSPI1_RDY IOMUX_PAD(0x610, 0x220, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_RDY__GPIO4_26 IOMUX_PAD(0x610, 0x220, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK IOMUX_PAD(0x614, 0x224, 0, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__GPIO4_27 IOMUX_PAD(0x614, 0x224, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_CSPI1_SCLK__I2C1_SCL IOMUX_PAD(0x614, 0x224, 0x11, 0x9b0, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__GPIO4_28 IOMUX_PAD(0x618, 0x228, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x618, 0x228, 0, 0x9e4, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__GPIO4_29 IOMUX_PAD(0x61c, 0x22c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__PWM2_PWMO IOMUX_PAD(0x61c, 0x22c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x61c, 0x22c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__GPIO4_30 IOMUX_PAD(0x620, 0x230, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_RTS__UART1_RTS IOMUX_PAD(0x620, 0x230, 0, 0x9e0, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__GPIO4_31 IOMUX_PAD(0x624, 0x234, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART1_CTS__UART1_CTS IOMUX_PAD(0x624, 0x234, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__FIRI_TXD IOMUX_PAD(0x628, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__GPIO1_20 IOMUX_PAD(0x628, 0x238, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_RXD__UART2_RXD IOMUX_PAD(0x628, 0x238, 0, 0x9ec, 2, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__FIRI_RXD IOMUX_PAD(0x62c, 0x23c, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__GPIO1_21 IOMUX_PAD(0x62c, 0x23c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART2_TXD__UART2_TXD IOMUX_PAD(0x62c, 0x23c, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__CSI1_D0 IOMUX_PAD(0x630, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__GPIO1_22 IOMUX_PAD(0x630, 0x240, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART1_DTR IOMUX_PAD(0x630, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_RXD__UART3_RXD IOMUX_PAD(0x630, 0x240, 1, 0x9f4, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__CSI1_D1 IOMUX_PAD(0x634, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__GPIO1_23 IOMUX_PAD(0x634, 0x244, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART1_DSR IOMUX_PAD(0x634, 0x244, 0, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_UART3_TXD__UART3_TXD IOMUX_PAD(0x634, 0x244, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__GPIO1_24 IOMUX_PAD(0x638, 0x248, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__OWIRE_LINE IOMUX_PAD(0x638, 0x248, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_OWIRE_LINE__SPDIF_OUT IOMUX_PAD(0x638, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW0__KEY_ROW0 IOMUX_PAD(0x63c, 0x24c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW1__KEY_ROW1 IOMUX_PAD(0x640, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW2__KEY_ROW2 IOMUX_PAD(0x644, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_ROW3__KEY_ROW3 IOMUX_PAD(0x648, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__KEY_COL0 IOMUX_PAD(0x64c, 0x25c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL0__PLL1_BYP IOMUX_PAD(0x64c, 0x25c, 7, 0x90c, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__KEY_COL1 IOMUX_PAD(0x650, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL1__PLL2_BYP IOMUX_PAD(0x650, 0x260, 7, 0x910, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__KEY_COL2 IOMUX_PAD(0x654, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL2__PLL3_BYP IOMUX_PAD(0x654, 0x264, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL3__KEY_COL3 IOMUX_PAD(0x658, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__I2C2_SCL IOMUX_PAD(0x65c, 0x26c, 0x13, 0x9b8, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__KEY_COL4 IOMUX_PAD(0x65c, 0x26c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__SPDIF_OUT1 IOMUX_PAD(0x65c, 0x26c, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART1_RI IOMUX_PAD(0x65c, 0x26c, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL4__UART3_RTS IOMUX_PAD(0x65c, 0x26c, 2, 0x9f0, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__I2C2_SDA IOMUX_PAD(0x660, 0x270, 0x13, 0x9bc, 1, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__KEY_COL5 IOMUX_PAD(0x660, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART1_DCD IOMUX_PAD(0x660, 0x270, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_KEY_COL5__UART3_CTS IOMUX_PAD(0x660, 0x270, 2, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__CSPI_SCLK IOMUX_PAD(0x678, 0x278, 1, 0x914, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__GPIO1_25 IOMUX_PAD(0x678, 0x278, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__I2C2_SCL IOMUX_PAD(0x678, 0x278, 0x15, 0x9b8, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_CLK__USBH1_CLK IOMUX_PAD(0x678, 0x278, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__CSPI_MOSI IOMUX_PAD(0x67c, 0x27c, 1, 0x91c, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__GPIO1_26 IOMUX_PAD(0x67c, 0x27c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__I2C2_SDA IOMUX_PAD(0x67c, 0x27c, 0x15, 0x9bc, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_USBH1_DIR__USBH1_DIR IOMUX_PAD(0x67c, 0x27c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__CSPI_RDY IOMUX_PAD(0x680, 0x280, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__GPIO1_27 IOMUX_PAD(0x680, 0x280, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__UART3_RXD IOMUX_PAD(0x680, 0x280, 5, 0x9f4, 6, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_STP__USBH1_STP IOMUX_PAD(0x680, 0x280, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__CSPI_MISO IOMUX_PAD(0x684, 0x284, 1, 0x918, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__GPIO1_28 IOMUX_PAD(0x684, 0x284, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__UART3_TXD IOMUX_PAD(0x684, 0x284, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_NXT__USBH1_NXT IOMUX_PAD(0x684, 0x284, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__GPIO1_11 IOMUX_PAD(0x688, 0x288, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__UART2_CTS IOMUX_PAD(0x688, 0x288, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA0__USBH1_DATA0 IOMUX_PAD(0x688, 0x288, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__GPIO1_12 IOMUX_PAD(0x68c, 0x28c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__UART2_RXD IOMUX_PAD(0x68c, 0x28c, 1, 0x9ec, 4, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA1__USBH1_DATA1 IOMUX_PAD(0x68c, 0x28c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__GPIO1_13 IOMUX_PAD(0x690, 0x290, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__UART2_TXD IOMUX_PAD(0x690, 0x290, 1, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA2__USBH1_DATA2 IOMUX_PAD(0x690, 0x290, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__GPIO1_14 IOMUX_PAD(0x694, 0x294, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__UART2_RTS IOMUX_PAD(0x694, 0x294, 1, 0x9e8, 5, MX51_UART_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA3__USBH1_DATA3 IOMUX_PAD(0x694, 0x294, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__CSPI_SS0 IOMUX_PAD(0x698, 0x298, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__GPIO1_15 IOMUX_PAD(0x698, 0x298, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA4__USBH1_DATA4 IOMUX_PAD(0x698, 0x298, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__CSPI_SS1 IOMUX_PAD(0x69c, 0x29c, 1, 0x920, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__GPIO1_16 IOMUX_PAD(0x69c, 0x29c, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA5__USBH1_DATA5 IOMUX_PAD(0x69c, 0x29c, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__CSPI_SS3 IOMUX_PAD(0x6a0, 0x2a0, 1, 0x928, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__GPIO1_17 IOMUX_PAD(0x6a0, 0x2a0, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA6__USBH1_DATA6 IOMUX_PAD(0x6a0, 0x2a0, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI1_SS3 IOMUX_PAD(0x6a4, 0x2a4, 1, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__ECSPI2_SS3 IOMUX_PAD(0x6a4, 0x2a4, 5, 0x934, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__GPIO1_18 IOMUX_PAD(0x6a4, 0x2a4, 2, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_USBH1_DATA7__USBH1_DATA7 IOMUX_PAD(0x6a4, 0x2a4, 0, __NA_, 0, MX51_USBH1_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__DI1_PIN11 IOMUX_PAD(0x6a8, 0x2a8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__ECSPI1_SS2 IOMUX_PAD(0x6a8, 0x2a8, 7, __NA_, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_DI1_PIN11__GPIO3_0 IOMUX_PAD(0x6a8, 0x2a8, 4, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__DI1_PIN12 IOMUX_PAD(0x6ac, 0x2ac, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN12__GPIO3_1 IOMUX_PAD(0x6ac, 0x2ac, 4, 0x978, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__DI1_PIN13 IOMUX_PAD(0x6b0, 0x2b0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN13__GPIO3_2 IOMUX_PAD(0x6b0, 0x2b0, 4, 0x97c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__DI1_D0_CS IOMUX_PAD(0x6b4, 0x2b4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D0_CS__GPIO3_3 IOMUX_PAD(0x6b4, 0x2b4, 4, 0x980, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DI1_D1_CS IOMUX_PAD(0x6b8, 0x2b8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN14 IOMUX_PAD(0x6b8, 0x2b8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__DISP1_PIN5 IOMUX_PAD(0x6b8, 0x2b8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_D1_CS__GPIO3_4 IOMUX_PAD(0x6b8, 0x2b8, 4, 0x984, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISP1_PIN1 IOMUX_PAD(0x6bc, 0x2bc, 2, 0x9a4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__DISPB2_SER_DIN IOMUX_PAD(0x6bc, 0x2bc, 0, 0x9c4, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIN__GPIO3_5 IOMUX_PAD(0x6bc, 0x2bc, 4, 0x988, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISP1_PIN6 IOMUX_PAD(0x6c0, 0x2c0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__DISPB2_SER_DIO IOMUX_PAD(0x6c0, 0x2c0, 0, 0x9c4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_DIO__GPIO3_6 IOMUX_PAD(0x6c0, 0x2c0, 4, 0x98c, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN17 IOMUX_PAD(0x6c4, 0x2c4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISP1_PIN7 IOMUX_PAD(0x6c4, 0x2c4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__DISPB2_SER_CLK IOMUX_PAD(0x6c4, 0x2c4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_CLK__GPIO3_7 IOMUX_PAD(0x6c4, 0x2c4, 4, 0x990, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_EXT_CLK IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN16 IOMUX_PAD(0x6c8, 0x2c8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISP1_PIN8 IOMUX_PAD(0x6c8, 0x2c8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__DISPB2_SER_RS IOMUX_PAD(0x6c8, 0x2c8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISPB2_SER_RS__GPIO3_8 IOMUX_PAD(0x6c8, 0x2c8, 4, 0x994, 1, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT0__DISP1_DAT0 IOMUX_PAD(0x6cc, 0x2cc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT1__DISP1_DAT1 IOMUX_PAD(0x6d0, 0x2d0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT2__DISP1_DAT2 IOMUX_PAD(0x6d4, 0x2d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT3__DISP1_DAT3 IOMUX_PAD(0x6d8, 0x2d8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT4__DISP1_DAT4 IOMUX_PAD(0x6dc, 0x2dc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT5__DISP1_DAT5 IOMUX_PAD(0x6e0, 0x2e0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__BOOT_USB_SRC IOMUX_PAD(0x6e4, 0x2e4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT6__DISP1_DAT6 IOMUX_PAD(0x6e4, 0x2e4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__BOOT_EEPROM_CFG IOMUX_PAD(0x6e8, 0x2e8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT7__DISP1_DAT7 IOMUX_PAD(0x6e8, 0x2e8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__BOOT_SRC0 IOMUX_PAD(0x6ec, 0x2ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT8__DISP1_DAT8 IOMUX_PAD(0x6ec, 0x2ec, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__BOOT_SRC1 IOMUX_PAD(0x6f0, 0x2f0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT9__DISP1_DAT9 IOMUX_PAD(0x6f0, 0x2f0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__BOOT_SPARE_SIZE IOMUX_PAD(0x6f4, 0x2f4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT10__DISP1_DAT10 IOMUX_PAD(0x6f4, 0x2f4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__BOOT_LPB_FREQ2 IOMUX_PAD(0x6f8, 0x2f8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT11__DISP1_DAT11 IOMUX_PAD(0x6f8, 0x2f8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__BOOT_MLC_SEL IOMUX_PAD(0x6fc, 0x2fc, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT12__DISP1_DAT12 IOMUX_PAD(0x6fc, 0x2fc, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__BOOT_MEM_CTL0 IOMUX_PAD(0x700, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT13__DISP1_DAT13 IOMUX_PAD(0x700, 0x300, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__BOOT_MEM_CTL1 IOMUX_PAD(0x704, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT14__DISP1_DAT14 IOMUX_PAD(0x704, 0x304, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__BOOT_BUS_WIDTH IOMUX_PAD(0x708, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT15__DISP1_DAT15 IOMUX_PAD(0x708, 0x308, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__BOOT_PAGE_SIZE0 IOMUX_PAD(0x70c, 0x30c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT16__DISP1_DAT16 IOMUX_PAD(0x70c, 0x30c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__BOOT_PAGE_SIZE1 IOMUX_PAD(0x710, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT17__DISP1_DAT17 IOMUX_PAD(0x710, 0x310, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__BOOT_WEIM_MUXED0 IOMUX_PAD(0x714, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP1_DAT18 IOMUX_PAD(0x714, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN11 IOMUX_PAD(0x714, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT18__DISP2_PIN5 IOMUX_PAD(0x714, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__BOOT_WEIM_MUXED1 IOMUX_PAD(0x718, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP1_DAT19 IOMUX_PAD(0x718, 0x318, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN12 IOMUX_PAD(0x718, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT19__DISP2_PIN6 IOMUX_PAD(0x718, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__BOOT_MEM_TYPE0 IOMUX_PAD(0x71c, 0x31c, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP1_DAT20 IOMUX_PAD(0x71c, 0x31c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN13 IOMUX_PAD(0x71c, 0x31c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT20__DISP2_PIN7 IOMUX_PAD(0x71c, 0x31c, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__BOOT_MEM_TYPE1 IOMUX_PAD(0x720, 0x320, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP1_DAT21 IOMUX_PAD(0x720, 0x320, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN14 IOMUX_PAD(0x720, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT21__DISP2_PIN8 IOMUX_PAD(0x720, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__BOOT_LPB_FREQ0 IOMUX_PAD(0x724, 0x324, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP1_DAT22 IOMUX_PAD(0x724, 0x324, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_D0_CS IOMUX_PAD(0x724, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT22__DISP2_DAT16 IOMUX_PAD(0x724, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__BOOT_LPB_FREQ1 IOMUX_PAD(0x728, 0x328, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP1_DAT23 IOMUX_PAD(0x728, 0x328, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_D1_CS IOMUX_PAD(0x728, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_DAT17 IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP1_DAT23__DISP2_SER_CS IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN3__DI1_PIN3 IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN2__DI1_PIN2 IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI1_PIN15__DI1_PIN15 IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP1_SER_CLK IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP2__DISP2_WAIT IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__CSI1_DATA_EN IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__DISP1_SER_DIO IOMUX_PAD(0x744, 0x33c, 0, 0x9c0, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP3__FEC_TX_ER IOMUX_PAD(0x744, 0x33c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN4__CSI2_DATA_EN IOMUX_PAD(0x748, 0x340, 3, 0x99c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__DI2_PIN4 IOMUX_PAD(0x748, 0x340, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN4__FEC_CRS IOMUX_PAD(0x748, 0x340, 2, 0x950, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__DI2_PIN2 IOMUX_PAD(0x74c, 0x344, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN2__FEC_MDC IOMUX_PAD(0x74c, 0x344, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DI2_PIN3__DI2_PIN3 IOMUX_PAD(0x750, 0x348, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_PIN3__FEC_MDIO IOMUX_PAD(0x750, 0x348, 2, 0x954, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK IOMUX_PAD(0x754, 0x34c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 IOMUX_PAD(0x754, 0x34c, 2, 0x95c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DI2_PIN15 IOMUX_PAD(0x758, 0x350, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP1_SER_DIN IOMUX_PAD(0x758, 0x350, 0, 0x9c0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__DISP2_PIN1 IOMUX_PAD(0x758, 0x350, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DI_GP4__FEC_RDATA2 IOMUX_PAD(0x758, 0x350, 2, 0x960, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__DISP2_DAT0 IOMUX_PAD(0x75c, 0x354, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__FEC_RDATA3 IOMUX_PAD(0x75c, 0x354, 2, 0x964, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__KEY_COL6 IOMUX_PAD(0x75c, 0x354, 4, 0x9c8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__UART3_RXD IOMUX_PAD(0x75c, 0x354, 5, 0x9f4, 8, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT0__USBH3_CLK IOMUX_PAD(0x75c, 0x354, 3, 0x9f8, 1, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__DISP2_DAT1 IOMUX_PAD(0x760, 0x358, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__FEC_RX_ER IOMUX_PAD(0x760, 0x358, 2, 0x970, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__KEY_COL7 IOMUX_PAD(0x760, 0x358, 4, 0x9cc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__UART3_TXD IOMUX_PAD(0x760, 0x358, 5, __NA_, 0, MX51_UART_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT1__USBH3_DIR IOMUX_PAD(0x760, 0x358, 3, 0xa1c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT2__DISP2_DAT2 IOMUX_PAD(0x764, 0x35c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT3__DISP2_DAT3 IOMUX_PAD(0x768, 0x360, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT4__DISP2_DAT4 IOMUX_PAD(0x76c, 0x364, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT5__DISP2_DAT5 IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__DISP2_DAT6 IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__FEC_TDATA1 IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__KEY_ROW4 IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT6__USBH3_STP IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__DISP2_DAT7 IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__FEC_TDATA2 IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__KEY_ROW5 IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT7__USBH3_NXT IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__DISP2_DAT8 IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__FEC_TDATA3 IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__KEY_ROW6 IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT8__USBH3_DATA0 IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__AUD6_RXC IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__DISP2_DAT9 IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__FEC_TX_EN IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT9__USBH3_DATA1 IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_DAT10 IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__DISP2_SER_CS IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__FEC_COL IOMUX_PAD(0x784, 0x37c, 2, 0x94c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__KEY_ROW7 IOMUX_PAD(0x784, 0x37c, 4, 0x9dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT10__USBH3_DATA2 IOMUX_PAD(0x784, 0x37c, 3, 0xa04, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__AUD6_TXD IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__DISP2_DAT11 IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__FEC_RX_CLK IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT11__USBH3_DATA3 IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__AUD6_RXD IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__DISP2_DAT12 IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__FEC_RX_DV IOMUX_PAD(0x78c, 0x384, 2, 0x96c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT12__USBH3_DATA4 IOMUX_PAD(0x78c, 0x384, 3, 0xa0c, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__AUD6_TXC IOMUX_PAD(0x790, 0x388, 4, 0x8fc, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__DISP2_DAT13 IOMUX_PAD(0x790, 0x388, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT13__FEC_TX_CLK IOMUX_PAD(0x790, 0x388, 2, 0x974, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT13__USBH3_DATA5 IOMUX_PAD(0x790, 0x388, 3, 0xa10, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__AUD6_TXFS IOMUX_PAD(0x794, 0x38c, 4, 0x900, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__DISP2_DAT14 IOMUX_PAD(0x794, 0x38c, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT14__FEC_RDATA0 IOMUX_PAD(0x794, 0x38c, 2, 0x958, 1, MX51_PAD_CTRL_4)
-#define MX51_PAD_DISP2_DAT14__USBH3_DATA6 IOMUX_PAD(0x794, 0x38c, 3, 0xa14, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__AUD6_RXFS IOMUX_PAD(0x798, 0x390, 4, 0x8f8, 1, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP1_SER_CS IOMUX_PAD(0x798, 0x390, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__DISP2_DAT15 IOMUX_PAD(0x798, 0x390, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_DISP2_DAT15__FEC_TDATA0 IOMUX_PAD(0x798, 0x390, 2, __NA_, 0, MX51_PAD_CTRL_5)
-#define MX51_PAD_DISP2_DAT15__USBH3_DATA7 IOMUX_PAD(0x798, 0x390, 3, 0xa18, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__AUD5_RXFS IOMUX_PAD(0x79c, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__CSPI_MOSI IOMUX_PAD(0x79c, 0x394, 2, 0x91c, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x79c, 0x394, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__AUD5_RXC IOMUX_PAD(0x7a0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__CSPI_SCLK IOMUX_PAD(0x7a0, 0x398, 2, 0x914, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x7a0, 0x398, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD1_DATA0__AUD5_TXD IOMUX_PAD(0x7a4, 0x39c, 1, 0x8d8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__CSPI_MISO IOMUX_PAD(0x7a4, 0x39c, 2, 0x918, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x7a4, 0x39c, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA0__EIM_DA0 IOMUX_PAD(__NA_, 0x01c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA1__EIM_DA1 IOMUX_PAD(__NA_, 0x020, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA2__EIM_DA2 IOMUX_PAD(__NA_, 0x024, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA3__EIM_DA3 IOMUX_PAD(__NA_, 0x028, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__AUD5_RXD IOMUX_PAD(0x7a8, 0x3a0, 1, 0x8d4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x7a8, 0x3a0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA4__EIM_DA4 IOMUX_PAD(__NA_, 0x02c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA5__EIM_DA5 IOMUX_PAD(__NA_, 0x030, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA6__EIM_DA6 IOMUX_PAD(__NA_, 0x034, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA7__EIM_DA7 IOMUX_PAD(__NA_, 0x038, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__AUD5_TXC IOMUX_PAD(0x7ac, 0x3a4, 1, 0x8e4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x7ac, 0x3a4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_EIM_DA10__EIM_DA10 IOMUX_PAD(__NA_, 0x044, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA11__EIM_DA11 IOMUX_PAD(__NA_, 0x048, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA8__EIM_DA8 IOMUX_PAD(__NA_, 0x03c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA9__EIM_DA9 IOMUX_PAD(__NA_, 0x040, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__AUD5_TXFS IOMUX_PAD(0x7b0, 0x3a8, 1, 0x8e8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__CSPI_SS1 IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__CSPI_SS2 IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_0__SD1_CD IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__CSPI_MISO IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_1__SD1_WP IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_EIM_DA12__EIM_DA12 IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA13__EIM_DA13 IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA14__EIM_DA14 IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_EIM_DA15__EIM_DA15 IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__I2C1_SCL IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__I2C1_SDA IOMUX_PAD(0x7c0, 0x3b8, 0x11, 0x9b4, 2, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK IOMUX_PAD(0x7c0, 0x3b8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
-#define MX51_PAD_SD2_DATA0__CSPI_MISO IOMUX_PAD(0x7c4, 0x3bc, 2, 0x918, 3, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD1_DAT4 IOMUX_PAD(0x7c4, 0x3bc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD1_DAT5 IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD1_DAT6 IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD1_DAT7 IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__CCM_OUT_2 IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__I2C2_SCL IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PLL1_BYP IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_2__PWM1_PWMO IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__I2C2_SDA IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__CCM_CLKO2 IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__GPT_CLKIN IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PLL2_BYP IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_3__PWM2_PWMO IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__DISP2_EXT_CLK IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__EIM_RDY IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__WDOG1_WDOG_B IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_4__GPT_CAPIN1 IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CSI2_MCLK IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__DISP2_PIN16 IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__WDOG2_WDOG_B IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_5__CCM_CLKO IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__DISP2_PIN17 IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__REF_EN_B IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_6__GPT_CAPIN2 IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__CCM_OUT_0 IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SD2_WP IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_7__SPDIF_OUT1 IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CSI2_DATA_EN IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__SD2_CD IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__USBH3_PWR IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_8__CCM_CLKO2 IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_OUT_1 IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_D1_CS IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__DISP2_SER_CS IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__SD2_LCTL IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__USBH3_OC IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO1_9__CCM_CLKO IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 39406b7e3228..a7e9bd26a552 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -50,6 +50,7 @@
#include "common.h"
#include "devices-imx31.h"
#include "crmregs-imx3.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 75b7b6aa2720..e6d4b9929571 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -36,6 +36,7 @@
#include "common.h"
#include "devices-imx27.h"
+#include "ehci.h"
#include "eukrea-baseboards.h"
#include "hardware.h"
#include "iomux-mx27.h"
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 1ffa27169045..62a6e02f4763 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -39,6 +39,7 @@
#include "common.h"
#include "devices-imx35.h"
+#include "ehci.h"
#include "eukrea-baseboards.h"
#include "hardware.h"
#include "iomux-mx35.h"
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index e978dda1434c..b2ee6e009fe4 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -35,6 +35,7 @@
#include "common.h"
#include "devices-imx25.h"
+#include "ehci.h"
#include "eukrea-baseboards.h"
#include "hardware.h"
#include "iomux-mx25.h"
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index b61bd8ed5568..ede2bdbb5dd5 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -43,6 +43,7 @@
#include "common.h"
#include "devices-imx27.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx27.h"
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
deleted file mode 100644
index bb3ca0429680..000000000000
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Author: Fabio Estevam <fabio.estevam@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "hardware.h"
-#include "common.h"
-#include "devices-imx27.h"
-#include "iomux-mx27.h"
-
-static const int mx27ipcam_pins[] __initconst = {
- /* UART1 */
- PE12_PF_UART1_TXD,
- PE13_PF_UART1_RXD,
- /* FEC */
- PD0_AIN_FEC_TXD0,
- PD1_AIN_FEC_TXD1,
- PD2_AIN_FEC_TXD2,
- PD3_AIN_FEC_TXD3,
- PD4_AOUT_FEC_RX_ER,
- PD5_AOUT_FEC_RXD1,
- PD6_AOUT_FEC_RXD2,
- PD7_AOUT_FEC_RXD3,
- PD8_AF_FEC_MDIO,
- PD9_AIN_FEC_MDC,
- PD10_AOUT_FEC_CRS,
- PD11_AOUT_FEC_TX_CLK,
- PD12_AOUT_FEC_RXD0,
- PD13_AOUT_FEC_RX_DV,
- PD14_AOUT_FEC_RX_CLK,
- PD15_AOUT_FEC_COL,
- PD16_AIN_FEC_TX_ER,
- PF23_AIN_FEC_TX_EN,
-};
-
-static void __init mx27ipcam_init(void)
-{
- imx27_soc_init();
-
- mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
- "mx27ipcam");
-
- imx27_add_imx_uart0(NULL);
- imx27_add_fec(NULL);
- imx27_add_imx2_wdt();
-}
-
-static void __init mx27ipcam_timer_init(void)
-{
- mx27_clocks_init(25000000);
-}
-
-MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
- /* maintainer: Freescale Semiconductor, Inc. */
- .atag_offset = 0x100,
- .map_io = mx27_map_io,
- .init_early = imx27_init_early,
- .init_irq = mx27_init_irq,
- .init_time = mx27ipcam_timer_init,
- .init_machine = mx27ipcam_init,
- .restart = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
deleted file mode 100644
index 9992089d3ad1..000000000000
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- * Copyright 2009 Daniel Schaeffer (daniel.schaeffer@timesys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices-imx27.h"
-#include "hardware.h"
-#include "iomux-mx27.h"
-
-static const int mx27lite_pins[] __initconst = {
- /* UART1 */
- PE12_PF_UART1_TXD,
- PE13_PF_UART1_RXD,
- PE14_PF_UART1_CTS,
- PE15_PF_UART1_RTS,
- /* FEC */
- PD0_AIN_FEC_TXD0,
- PD1_AIN_FEC_TXD1,
- PD2_AIN_FEC_TXD2,
- PD3_AIN_FEC_TXD3,
- PD4_AOUT_FEC_RX_ER,
- PD5_AOUT_FEC_RXD1,
- PD6_AOUT_FEC_RXD2,
- PD7_AOUT_FEC_RXD3,
- PD8_AF_FEC_MDIO,
- PD9_AIN_FEC_MDC,
- PD10_AOUT_FEC_CRS,
- PD11_AOUT_FEC_TX_CLK,
- PD12_AOUT_FEC_RXD0,
- PD13_AOUT_FEC_RX_DV,
- PD14_AOUT_FEC_RX_CLK,
- PD15_AOUT_FEC_COL,
- PD16_AIN_FEC_TX_ER,
- PF23_AIN_FEC_TX_EN,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
- .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static void __init mx27lite_init(void)
-{
- imx27_soc_init();
-
- mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
- "imx27lite");
- imx27_add_imx_uart0(&uart_pdata);
- imx27_add_fec(NULL);
-}
-
-static void __init mx27lite_timer_init(void)
-{
- mx27_clocks_init(26000000);
-}
-
-MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
- .atag_offset = 0x100,
- .map_io = mx27_map_io,
- .init_early = imx27_init_early,
- .init_irq = mx27_init_irq,
- .init_time = mx27lite_timer_init,
- .init_machine = mx27lite_init,
- .restart = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx50.c b/arch/arm/mach-imx/mach-imx50.c
index b899c0b59afd..b1e56a94a382 100644
--- a/arch/arm/mach-imx/mach-imx50.c
+++ b/arch/arm/mach-imx/mach-imx50.c
@@ -23,14 +23,13 @@ static void __init imx50_dt_init(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
-static const char *imx50_dt_board_compat[] __initconst = {
+static const char * const imx50_dt_board_compat[] __initconst = {
"fsl,imx50",
NULL
};
DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
- .map_io = mx53_map_io,
- .init_irq = mx53_init_irq,
+ .init_irq = tzic_init_irq,
.init_machine = imx50_dt_init,
.dt_compat = imx50_dt_board_compat,
.restart = mxc_restart,
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/mach-imx51.c
index b8cd968faa52..c77deb3f0893 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/mach-imx51.c
@@ -10,6 +10,7 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <linux/io.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
@@ -17,27 +18,63 @@
#include <asm/mach/time.h>
#include "common.h"
-#include "mx51.h"
+#include "hardware.h"
+
+static void __init imx51_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX51);
+}
+
+/*
+ * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
+ * the Freescale marketing division. However this did not remove the
+ * hardware from the chip which still needs to be configured for proper
+ * IPU support.
+ */
+#define MX51_MIPI_HSC_BASE 0x83fdc000
+static void __init imx51_ipu_mipi_setup(void)
+{
+ void __iomem *hsc_addr;
+
+ hsc_addr = ioremap(MX51_MIPI_HSC_BASE, SZ_16K);
+ WARN_ON(!hsc_addr);
+
+ /* setup MIPI module to legacy mode */
+ __raw_writel(0xf00, hsc_addr);
+
+ /* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
+ __raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
+ hsc_addr + 0x800);
+
+ iounmap(hsc_addr);
+}
static void __init imx51_dt_init(void)
{
struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
mxc_arch_reset_init_dt();
+ imx51_ipu_mipi_setup();
+ imx_src_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_full(&devinfo);
}
-static const char *imx51_dt_board_compat[] __initconst = {
+static void __init imx51_init_late(void)
+{
+ mx51_neon_fixup();
+ imx51_pm_init();
+}
+
+static const char * const imx51_dt_board_compat[] __initconst = {
"fsl,imx51",
NULL
};
DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
- .map_io = mx51_map_io,
.init_early = imx51_init_early,
- .init_irq = mx51_init_irq,
+ .init_irq = tzic_init_irq,
.init_machine = imx51_dt_init,
.init_late = imx51_init_late,
.dt_compat = imx51_dt_board_compat,
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 2bad387956c0..03dd6ea13acc 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -22,24 +22,35 @@
#include "common.h"
#include "hardware.h"
-#include "mx53.h"
+
+static void __init imx53_init_early(void)
+{
+ mxc_set_cpu_type(MXC_CPU_MX53);
+}
static void __init imx53_dt_init(void)
{
mxc_arch_reset_init_dt();
+ imx_src_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
+}
+
+static void __init imx53_init_late(void)
+{
+ imx53_pm_init();
}
-static const char *imx53_dt_board_compat[] __initconst = {
+static const char * const imx53_dt_board_compat[] __initconst = {
"fsl,imx53",
NULL
};
DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
- .map_io = mx53_map_io,
.init_early = imx53_init_early,
- .init_irq = mx53_init_irq,
+ .init_irq = tzic_init_irq,
.init_machine = imx53_dt_init,
.init_late = imx53_init_late,
.dt_compat = imx53_dt_board_compat,
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index e60456d85c9d..d51c6e99a2e9 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -320,7 +320,7 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;
- if (val != OCOTP_CFG3_SPEED_1P2GHZ)
+ if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q())
if (dev_pm_opp_disable(cpu_dev, 1200000000))
pr_warn("failed to disable 1.2 GHz OPP\n");
if (val < OCOTP_CFG3_SPEED_996MHZ)
@@ -396,7 +396,7 @@ static void __init imx6q_init_irq(void)
irqchip_init();
}
-static const char *imx6q_dt_compat[] __initconst = {
+static const char * const imx6q_dt_compat[] __initconst = {
"fsl,imx6dl",
"fsl,imx6q",
NULL,
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index ad323385115c..ed263a21d928 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -70,7 +70,7 @@ static void __init imx6sl_init_irq(void)
irqchip_init();
}
-static const char *imx6sl_dt_compat[] __initconst = {
+static const char * const imx6sl_dt_compat[] __initconst = {
"fsl,imx6sl",
NULL,
};
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 02fccf6033ac..673a734165ba 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -12,6 +12,7 @@
#include <asm/mach/map.h>
#include "common.h"
+#include "cpuidle.h"
static void __init imx6sx_init_machine(void)
{
@@ -26,6 +27,7 @@ static void __init imx6sx_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
imx_anatop_init();
+ imx6sx_pm_init();
}
static void __init imx6sx_init_irq(void)
@@ -37,7 +39,12 @@ static void __init imx6sx_init_irq(void)
irqchip_init();
}
-static const char *imx6sx_dt_compat[] __initconst = {
+static void __init imx6sx_init_late(void)
+{
+ imx6q_cpuidle_init();
+}
+
+static const char * const imx6sx_dt_compat[] __initconst = {
"fsl,imx6sx",
NULL,
};
@@ -47,5 +54,6 @@ DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)")
.init_irq = imx6sx_init_irq,
.init_machine = imx6sx_init_machine,
.dt_compat = imx6sx_dt_compat,
+ .init_late = imx6sx_init_late,
.restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index ea1fa199c148..0d01e367b062 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -39,6 +39,7 @@
#include "common.h"
#include "devices-imx25.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx25.h"
#include "mx25.h"
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 435a5428a678..9ef4640f3660 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -40,6 +40,7 @@
#include "3ds_debugboard.h"
#include "common.h"
#include "devices-imx27.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx27.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 2f834ce8f39c..eb1c3477c48a 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -245,7 +245,7 @@ static void __init mx27ads_regulator_init(void)
vchip->set = vgpio_set;
gpiochip_add(vchip);
- platform_device_register_data(&platform_bus, "reg-fixed-voltage",
+ platform_device_register_data(NULL, "reg-fixed-voltage",
PLATFORM_DEVID_AUTO,
&mx27ads_lcd_regulator_pdata,
sizeof(mx27ads_lcd_regulator_pdata));
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 4217871a9653..453f41a2c5a9 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -40,6 +40,7 @@
#include "3ds_debugboard.h"
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index eee042fa2768..e9549a3c0223 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -45,6 +45,7 @@
#include "board-mx31lilly.h"
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index fa15d0b6118d..57eac6f45fab 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -42,6 +42,7 @@
#include "board-mx31lite.h"
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 08730f238449..bb6f8a52a6b8 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -47,6 +47,7 @@
#include "board-mx31moboard.h"
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
@@ -434,10 +435,8 @@ static int __init moboard_usbh2_init(void)
return -ENODEV;
pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
static const struct gpio_led mx31moboard_leds[] __initconst = {
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 4e8b184d773b..72cd77d21f63 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -50,6 +50,7 @@
#include "3ds_debugboard.h"
#include "common.h"
#include "devices-imx35.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx35.h"
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index 12212378c672..2d1c50bd8bdf 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -36,6 +36,7 @@
#include "common.h"
#include "devices-imx27.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx27.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 81b8affb9448..8eb1570f7851 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -45,6 +45,7 @@
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "pcm037.h"
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 6c56fb5553c7..ee862ad6b6fc 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -36,6 +36,7 @@
#include "board-pcm038.h"
#include "common.h"
#include "devices-imx27.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx27.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index c62b5d261345..b623bcaca76c 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -35,6 +35,7 @@
#include "common.h"
#include "devices-imx35.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx35.h"
#include "ulpi.h"
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index c44602758120..ee7e57b752a7 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -20,7 +20,7 @@ static void __init vf610_init_machine(void)
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
-static const char *vf610_dt_compat[] __initconst = {
+static const char * const vf610_dt_compat[] __initconst = {
"fsl,vf610",
NULL,
};
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 872b3c6ba408..97836e94451c 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -34,6 +34,7 @@
#include "common.h"
#include "devices-imx35.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx35.h"
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
deleted file mode 100644
index 4c112021aa4e..000000000000
--- a/arch/arm/mach-imx/mm-imx5.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/of_address.h>
-
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices/devices-common.h"
-#include "hardware.h"
-#include "iomux-v3.h"
-
-/*
- * Define the MX51 memory map.
- */
-static struct map_desc mx51_io_desc[] __initdata = {
- imx_map_entry(MX51, TZIC, MT_DEVICE),
- imx_map_entry(MX51, IRAM, MT_DEVICE),
- imx_map_entry(MX51, AIPS1, MT_DEVICE),
- imx_map_entry(MX51, SPBA0, MT_DEVICE),
- imx_map_entry(MX51, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX53 memory map.
- */
-static struct map_desc mx53_io_desc[] __initdata = {
- imx_map_entry(MX53, TZIC, MT_DEVICE),
- imx_map_entry(MX53, AIPS1, MT_DEVICE),
- imx_map_entry(MX53, SPBA0, MT_DEVICE),
- imx_map_entry(MX53, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx51_map_io(void)
-{
- iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
-}
-
-void __init mx53_map_io(void)
-{
- iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
-}
-
-/*
- * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
- * the Freescale marketing division. However this did not remove the
- * hardware from the chip which still needs to be configured for proper
- * IPU support.
- */
-static void __init imx51_ipu_mipi_setup(void)
-{
- void __iomem *hsc_addr;
- hsc_addr = MX51_IO_ADDRESS(MX51_MIPI_HSC_BASE_ADDR);
-
- /* setup MIPI module to legacy mode */
- __raw_writel(0xf00, hsc_addr);
-
- /* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
- __raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
- hsc_addr + 0x800);
-}
-
-void __init imx51_init_early(void)
-{
- imx51_ipu_mipi_setup();
- mxc_set_cpu_type(MXC_CPU_MX51);
- mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
- imx_src_init();
-}
-
-void __init imx53_init_early(void)
-{
- mxc_set_cpu_type(MXC_CPU_MX53);
- imx_src_init();
-}
-
-void __init mx51_init_irq(void)
-{
- tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
-}
-
-void __init mx53_init_irq(void)
-{
- struct device_node *np;
- void __iomem *base;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx53-tzic");
- base = of_iomap(np, 0);
- WARN_ON(!base);
-
- tzic_init_irq(base);
-}
-
-static struct sdma_platform_data imx51_sdma_pdata __initdata = {
- .fw_name = "sdma-imx51.bin",
-};
-
-static const struct resource imx51_audmux_res[] __initconst = {
- DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
-};
-
-void __init imx51_soc_init(void)
-{
- mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
- mxc_device_init();
-
- /* i.mx51 has the i.mx35 type gpio */
- mxc_register_gpio("imx35-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
- mxc_register_gpio("imx35-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
- mxc_register_gpio("imx35-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
- mxc_register_gpio("imx35-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
-
- pinctrl_provide_dummies();
-
- /* i.mx51 has the i.mx35 type sdma */
- imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
-
- /* Setup AIPS registers */
- imx_set_aips(MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR));
- imx_set_aips(MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR));
-
- /* i.mx51 has the i.mx31 type audmux */
- platform_device_register_simple("imx31-audmux", 0, imx51_audmux_res,
- ARRAY_SIZE(imx51_audmux_res));
-}
-
-void __init imx51_init_late(void)
-{
- mx51_neon_fixup();
- imx5_pm_init();
-}
-
-void __init imx53_init_late(void)
-{
- imx5_pm_init();
-}
diff --git a/arch/arm/mach-imx/mx1-camera-fiq-ksym.c b/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
deleted file mode 100644
index fb38436ca67f..000000000000
--- a/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Exported ksyms of ARCH_MX1
- *
- * Copyright (C) 2008, Darius Augulis <augulis.darius@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-
-#include <linux/platform_data/camera-mx1.h>
-
-/* IMX camera FIQ handler */
-EXPORT_SYMBOL(mx1_camera_sof_fiq_start);
-EXPORT_SYMBOL(mx1_camera_sof_fiq_end);
diff --git a/arch/arm/mach-imx/mx1-camera-fiq.S b/arch/arm/mach-imx/mx1-camera-fiq.S
deleted file mode 100644
index 9c69aa65bf17..000000000000
--- a/arch/arm/mach-imx/mx1-camera-fiq.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * Based on linux/arch/arm/lib/floppydma.S
- * Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
- .text
- .global mx1_camera_sof_fiq_end
- .global mx1_camera_sof_fiq_start
-mx1_camera_sof_fiq_start:
- @ enable dma
- ldr r12, [r9]
- orr r12, r12, #0x00000001
- str r12, [r9]
- @ unmask DMA interrupt
- ldr r12, [r8]
- bic r12, r12, r13
- str r12, [r8]
- @ disable SOF interrupt
- ldr r12, [r10]
- bic r12, r12, #0x00010000
- str r12, [r10]
- @ clear SOF flag
- mov r12, #0x00010000
- str r12, [r11]
- @ return from FIQ
- subs pc, lr, #4
-mx1_camera_sof_fiq_end:
diff --git a/arch/arm/mach-imx/mx31moboard-devboard.c b/arch/arm/mach-imx/mx31moboard-devboard.c
index 52d5b1574721..1e91a0918e83 100644
--- a/arch/arm/mach-imx/mx31moboard-devboard.c
+++ b/arch/arm/mach-imx/mx31moboard-devboard.c
@@ -24,6 +24,7 @@
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
@@ -213,10 +214,8 @@ static int __init devboard_usbh1_init(void)
usbh1_pdata.otg = phy;
pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
diff --git a/arch/arm/mach-imx/mx31moboard-marxbot.c b/arch/arm/mach-imx/mx31moboard-marxbot.c
index a4f43e90f3c1..2e895a82a6eb 100644
--- a/arch/arm/mach-imx/mx31moboard-marxbot.c
+++ b/arch/arm/mach-imx/mx31moboard-marxbot.c
@@ -28,6 +28,7 @@
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
@@ -327,10 +328,8 @@ static int __init marxbot_usbh1_init(void)
usbh1_pdata.otg = phy;
pdev = imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
static const struct fsl_usb2_platform_data usb_pdata __initconst = {
diff --git a/arch/arm/mach-imx/mx31moboard-smartbot.c b/arch/arm/mach-imx/mx31moboard-smartbot.c
index 04ae45dbfaa7..89fc35a64448 100644
--- a/arch/arm/mach-imx/mx31moboard-smartbot.c
+++ b/arch/arm/mach-imx/mx31moboard-smartbot.c
@@ -28,6 +28,7 @@
#include "board-mx31moboard.h"
#include "common.h"
#include "devices-imx31.h"
+#include "ehci.h"
#include "hardware.h"
#include "iomux-mx3.h"
#include "ulpi.h"
@@ -141,10 +142,8 @@ static int __init smartbot_otg_host_init(void)
return -ENODEV;
pdev = imx31_add_mxc_ehci_otg(&otg_host_pdata);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
#else
static inline int smartbot_otg_host_init(void) { return 0; }
diff --git a/arch/arm/mach-imx/mx51.h b/arch/arm/mach-imx/mx51.h
deleted file mode 100644
index af844f76261a..000000000000
--- a/arch/arm/mach-imx/mx51.h
+++ /dev/null
@@ -1,346 +0,0 @@
-#ifndef __MACH_MX51_H__
-#define __MACH_MX51_H__
-
-/*
- * IROM
- */
-#define MX51_IROM_BASE_ADDR 0x0
-#define MX51_IROM_SIZE SZ_64K
-
-/*
- * IRAM
- */
-#define MX51_IRAM_BASE_ADDR 0x1ffe0000 /* internal ram */
-#define MX51_IRAM_PARTITIONS 16
-#define MX51_IRAM_SIZE (MX51_IRAM_PARTITIONS * SZ_8K) /* 128KB */
-
-#define MX51_GPU_BASE_ADDR 0x20000000
-#define MX51_GPU_CTRL_BASE_ADDR 0x30000000
-#define MX51_IPU_CTRL_BASE_ADDR 0x40000000
-
-/*
- * SPBA global module enabled #0
- */
-#define MX51_SPBA0_BASE_ADDR 0x70000000
-#define MX51_SPBA0_SIZE SZ_1M
-
-#define MX51_ESDHC1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x04000)
-#define MX51_ESDHC2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x08000)
-#define MX51_UART3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x0c000)
-#define MX51_ECSPI1_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x10000)
-#define MX51_SSI2_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x14000)
-#define MX51_ESDHC3_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x20000)
-#define MX51_ESDHC4_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x24000)
-#define MX51_SPDIF_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x28000)
-#define MX51_ATA_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x30000)
-#define MX51_SLIM_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x34000)
-#define MX51_HSI2C_DMA_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x38000)
-#define MX51_SPBA_CTRL_BASE_ADDR (MX51_SPBA0_BASE_ADDR + 0x3c000)
-
-/*
- * AIPS 1
- */
-#define MX51_AIPS1_BASE_ADDR 0x73f00000
-#define MX51_AIPS1_SIZE SZ_1M
-
-#define MX51_USB_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x80000)
-#define MX51_USB_OTG_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0000)
-#define MX51_USB_HS1_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0200)
-#define MX51_USB_HS2_BASE_ADDR (MX51_USB_BASE_ADDR + 0x0400)
-#define MX51_GPIO1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x84000)
-#define MX51_GPIO2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x88000)
-#define MX51_GPIO3_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x8c000)
-#define MX51_GPIO4_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x90000)
-#define MX51_KPP_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x94000)
-#define MX51_WDOG1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x98000)
-#define MX51_WDOG2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0x9c000)
-#define MX51_GPT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa0000)
-#define MX51_SRTC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa4000)
-#define MX51_IOMUXC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xa8000)
-#define MX51_EPIT1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xac000)
-#define MX51_EPIT2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb0000)
-#define MX51_PWM1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb4000)
-#define MX51_PWM2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xb8000)
-#define MX51_UART1_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xbc000)
-#define MX51_UART2_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xc0000)
-#define MX51_SRC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd0000)
-#define MX51_CCM_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd4000)
-#define MX51_GPC_BASE_ADDR (MX51_AIPS1_BASE_ADDR + 0xd8000)
-
-/*
- * AIPS 2
- */
-#define MX51_AIPS2_BASE_ADDR 0x83f00000
-#define MX51_AIPS2_SIZE SZ_1M
-
-#define MX51_PLL1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x80000)
-#define MX51_PLL2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x84000)
-#define MX51_PLL3_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x88000)
-#define MX51_AHBMAX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x94000)
-#define MX51_IIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x98000)
-#define MX51_CSU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0x9c000)
-#define MX51_ARM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa0000)
-#define MX51_OWIRE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa4000)
-#define MX51_FIRI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xa8000)
-#define MX51_ECSPI2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xac000)
-#define MX51_SDMA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb0000)
-#define MX51_SCC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb4000)
-#define MX51_ROMCP_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xb8000)
-#define MX51_RTIC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xbc000)
-#define MX51_CSPI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc0000)
-#define MX51_I2C2_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc4000)
-#define MX51_I2C1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xc8000)
-#define MX51_SSI1_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xcc000)
-#define MX51_AUDMUX_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd0000)
-#define MX51_M4IF_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd8000)
-#define MX51_ESDCTL_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xd9000)
-#define MX51_WEIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xda000)
-#define MX51_NFC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdb000)
-#define MX51_EMI_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdbf00)
-#define MX51_MIPI_HSC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xdc000)
-#define MX51_ATA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe0000)
-#define MX51_SIM_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe4000)
-#define MX51_SSI3_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xe8000)
-#define MX51_FEC_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xec000)
-#define MX51_TVE_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf0000)
-#define MX51_VPU_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf4000)
-#define MX51_SAHARA_BASE_ADDR (MX51_AIPS2_BASE_ADDR + 0xf8000)
-
-#define MX51_CSD0_BASE_ADDR 0x90000000
-#define MX51_CSD1_BASE_ADDR 0xa0000000
-#define MX51_CS0_BASE_ADDR 0xb0000000
-#define MX51_CS1_BASE_ADDR 0xb8000000
-#define MX51_CS2_BASE_ADDR 0xc0000000
-#define MX51_CS3_BASE_ADDR 0xc8000000
-#define MX51_CS4_BASE_ADDR 0xcc000000
-#define MX51_CS5_BASE_ADDR 0xce000000
-
-/*
- * NFC
- */
-#define MX51_NFC_AXI_BASE_ADDR 0xcfff0000 /* NAND flash AXI */
-#define MX51_NFC_AXI_SIZE SZ_64K
-
-#define MX51_GPU2D_BASE_ADDR 0xd0000000
-#define MX51_TZIC_BASE_ADDR 0xe0000000
-#define MX51_TZIC_SIZE SZ_16K
-
-#define MX51_IO_P2V(x) IMX_IO_P2V(x)
-#define MX51_IO_ADDRESS(x) IOMEM(MX51_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX51_SPBA_SDHC1 0x04
-#define MX51_SPBA_SDHC2 0x08
-#define MX51_SPBA_UART3 0x0c
-#define MX51_SPBA_CSPI1 0x10
-#define MX51_SPBA_SSI2 0x14
-#define MX51_SPBA_SDHC3 0x20
-#define MX51_SPBA_SDHC4 0x24
-#define MX51_SPBA_SPDIF 0x28
-#define MX51_SPBA_ATA 0x30
-#define MX51_SPBA_SLIM 0x34
-#define MX51_SPBA_HSI2C 0x38
-#define MX51_SPBA_CTRL 0x3c
-
-/*
- * Defines for modules using static and dynamic DMA channels
- */
-#define MX51_MXC_DMA_CHANNEL_IRAM 30
-#define MX51_MXC_DMA_CHANNEL_SPDIF_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
-#ifdef CONFIG_SDMA_IRAM
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX (MX51_MXC_DMA_CHANNEL_IRAM + 1)
-#else /*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
-#endif /*CONFIG_SDMA_IRAM */
-#define MX51_MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_CSPI3_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
-#define MX51_MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
-
-#define MX51_IS_MEM_DEVICE_NONSHARED(x) 0
-
-/*
- * DMA request assignments
- */
-#define MX51_DMA_REQ_VPU 0
-#define MX51_DMA_REQ_GPC 1
-#define MX51_DMA_REQ_ATA_RX 2
-#define MX51_DMA_REQ_ATA_TX 3
-#define MX51_DMA_REQ_ATA_TX_END 4
-#define MX51_DMA_REQ_SLIM_B 5
-#define MX51_DMA_REQ_CSPI1_RX 6
-#define MX51_DMA_REQ_CSPI1_TX 7
-#define MX51_DMA_REQ_CSPI2_RX 8
-#define MX51_DMA_REQ_CSPI2_TX 9
-#define MX51_DMA_REQ_HS_I2C_TX 10
-#define MX51_DMA_REQ_HS_I2C_RX 11
-#define MX51_DMA_REQ_FIRI_RX 12
-#define MX51_DMA_REQ_FIRI_TX 13
-#define MX51_DMA_REQ_EXTREQ1 14
-#define MX51_DMA_REQ_GPU 15
-#define MX51_DMA_REQ_UART2_RX 16
-#define MX51_DMA_REQ_UART2_TX 17
-#define MX51_DMA_REQ_UART1_RX 18
-#define MX51_DMA_REQ_UART1_TX 19
-#define MX51_DMA_REQ_SDHC1 20
-#define MX51_DMA_REQ_SDHC2 21
-#define MX51_DMA_REQ_SSI2_RX1 22
-#define MX51_DMA_REQ_SSI2_TX1 23
-#define MX51_DMA_REQ_SSI2_RX0 24
-#define MX51_DMA_REQ_SSI2_TX0 25
-#define MX51_DMA_REQ_SSI1_RX1 26
-#define MX51_DMA_REQ_SSI1_TX1 27
-#define MX51_DMA_REQ_SSI1_RX0 28
-#define MX51_DMA_REQ_SSI1_TX0 29
-#define MX51_DMA_REQ_EMI_RD 30
-#define MX51_DMA_REQ_CTI2_0 31
-#define MX51_DMA_REQ_EMI_WR 32
-#define MX51_DMA_REQ_CTI2_1 33
-#define MX51_DMA_REQ_EPIT2 34
-#define MX51_DMA_REQ_SSI3_RX1 35
-#define MX51_DMA_REQ_IPU 36
-#define MX51_DMA_REQ_SSI3_TX1 37
-#define MX51_DMA_REQ_CSPI_RX 38
-#define MX51_DMA_REQ_CSPI_TX 39
-#define MX51_DMA_REQ_SDHC3 40
-#define MX51_DMA_REQ_SDHC4 41
-#define MX51_DMA_REQ_SLIM_B_TX 42
-#define MX51_DMA_REQ_UART3_RX 43
-#define MX51_DMA_REQ_UART3_TX 44
-#define MX51_DMA_REQ_SPDIF 45
-#define MX51_DMA_REQ_SSI3_RX0 46
-#define MX51_DMA_REQ_SSI3_TX0 47
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX51_INT_BASE (NR_IRQS_LEGACY + 0)
-#define MX51_INT_RESV0 (NR_IRQS_LEGACY + 0)
-#define MX51_INT_ESDHC1 (NR_IRQS_LEGACY + 1)
-#define MX51_INT_ESDHC2 (NR_IRQS_LEGACY + 2)
-#define MX51_INT_ESDHC3 (NR_IRQS_LEGACY + 3)
-#define MX51_INT_ESDHC4 (NR_IRQS_LEGACY + 4)
-#define MX51_INT_RESV5 (NR_IRQS_LEGACY + 5)
-#define MX51_INT_SDMA (NR_IRQS_LEGACY + 6)
-#define MX51_INT_IOMUX (NR_IRQS_LEGACY + 7)
-#define MX51_INT_NFC (NR_IRQS_LEGACY + 8)
-#define MX51_INT_VPU (NR_IRQS_LEGACY + 9)
-#define MX51_INT_IPU_ERR (NR_IRQS_LEGACY + 10)
-#define MX51_INT_IPU_SYN (NR_IRQS_LEGACY + 11)
-#define MX51_INT_GPU (NR_IRQS_LEGACY + 12)
-#define MX51_INT_RESV13 (NR_IRQS_LEGACY + 13)
-#define MX51_INT_USB_HS1 (NR_IRQS_LEGACY + 14)
-#define MX51_INT_EMI (NR_IRQS_LEGACY + 15)
-#define MX51_INT_USB_HS2 (NR_IRQS_LEGACY + 16)
-#define MX51_INT_USB_HS3 (NR_IRQS_LEGACY + 17)
-#define MX51_INT_USB_OTG (NR_IRQS_LEGACY + 18)
-#define MX51_INT_SAHARA_H0 (NR_IRQS_LEGACY + 19)
-#define MX51_INT_SAHARA_H1 (NR_IRQS_LEGACY + 20)
-#define MX51_INT_SCC_SMN (NR_IRQS_LEGACY + 21)
-#define MX51_INT_SCC_STZ (NR_IRQS_LEGACY + 22)
-#define MX51_INT_SCC_SCM (NR_IRQS_LEGACY + 23)
-#define MX51_INT_SRTC_NTZ (NR_IRQS_LEGACY + 24)
-#define MX51_INT_SRTC_TZ (NR_IRQS_LEGACY + 25)
-#define MX51_INT_RTIC (NR_IRQS_LEGACY + 26)
-#define MX51_INT_CSU (NR_IRQS_LEGACY + 27)
-#define MX51_INT_SLIM_B (NR_IRQS_LEGACY + 28)
-#define MX51_INT_SSI1 (NR_IRQS_LEGACY + 29)
-#define MX51_INT_SSI2 (NR_IRQS_LEGACY + 30)
-#define MX51_INT_UART1 (NR_IRQS_LEGACY + 31)
-#define MX51_INT_UART2 (NR_IRQS_LEGACY + 32)
-#define MX51_INT_UART3 (NR_IRQS_LEGACY + 33)
-#define MX51_INT_RESV34 (NR_IRQS_LEGACY + 34)
-#define MX51_INT_RESV35 (NR_IRQS_LEGACY + 35)
-#define MX51_INT_ECSPI1 (NR_IRQS_LEGACY + 36)
-#define MX51_INT_ECSPI2 (NR_IRQS_LEGACY + 37)
-#define MX51_INT_CSPI (NR_IRQS_LEGACY + 38)
-#define MX51_INT_GPT (NR_IRQS_LEGACY + 39)
-#define MX51_INT_EPIT1 (NR_IRQS_LEGACY + 40)
-#define MX51_INT_EPIT2 (NR_IRQS_LEGACY + 41)
-#define MX51_INT_GPIO1_INT7 (NR_IRQS_LEGACY + 42)
-#define MX51_INT_GPIO1_INT6 (NR_IRQS_LEGACY + 43)
-#define MX51_INT_GPIO1_INT5 (NR_IRQS_LEGACY + 44)
-#define MX51_INT_GPIO1_INT4 (NR_IRQS_LEGACY + 45)
-#define MX51_INT_GPIO1_INT3 (NR_IRQS_LEGACY + 46)
-#define MX51_INT_GPIO1_INT2 (NR_IRQS_LEGACY + 47)
-#define MX51_INT_GPIO1_INT1 (NR_IRQS_LEGACY + 48)
-#define MX51_INT_GPIO1_INT0 (NR_IRQS_LEGACY + 49)
-#define MX51_INT_GPIO1_LOW (NR_IRQS_LEGACY + 50)
-#define MX51_INT_GPIO1_HIGH (NR_IRQS_LEGACY + 51)
-#define MX51_INT_GPIO2_LOW (NR_IRQS_LEGACY + 52)
-#define MX51_INT_GPIO2_HIGH (NR_IRQS_LEGACY + 53)
-#define MX51_INT_GPIO3_LOW (NR_IRQS_LEGACY + 54)
-#define MX51_INT_GPIO3_HIGH (NR_IRQS_LEGACY + 55)
-#define MX51_INT_GPIO4_LOW (NR_IRQS_LEGACY + 56)
-#define MX51_INT_GPIO4_HIGH (NR_IRQS_LEGACY + 57)
-#define MX51_INT_WDOG1 (NR_IRQS_LEGACY + 58)
-#define MX51_INT_WDOG2 (NR_IRQS_LEGACY + 59)
-#define MX51_INT_KPP (NR_IRQS_LEGACY + 60)
-#define MX51_INT_PWM1 (NR_IRQS_LEGACY + 61)
-#define MX51_INT_I2C1 (NR_IRQS_LEGACY + 62)
-#define MX51_INT_I2C2 (NR_IRQS_LEGACY + 63)
-#define MX51_INT_HS_I2C (NR_IRQS_LEGACY + 64)
-#define MX51_INT_RESV65 (NR_IRQS_LEGACY + 65)
-#define MX51_INT_RESV66 (NR_IRQS_LEGACY + 66)
-#define MX51_INT_SIM_IPB (NR_IRQS_LEGACY + 67)
-#define MX51_INT_SIM_DAT (NR_IRQS_LEGACY + 68)
-#define MX51_INT_IIM (NR_IRQS_LEGACY + 69)
-#define MX51_INT_ATA (NR_IRQS_LEGACY + 70)
-#define MX51_INT_CCM1 (NR_IRQS_LEGACY + 71)
-#define MX51_INT_CCM2 (NR_IRQS_LEGACY + 72)
-#define MX51_INT_GPC1 (NR_IRQS_LEGACY + 73)
-#define MX51_INT_GPC2 (NR_IRQS_LEGACY + 74)
-#define MX51_INT_SRC (NR_IRQS_LEGACY + 75)
-#define MX51_INT_NM (NR_IRQS_LEGACY + 76)
-#define MX51_INT_PMU (NR_IRQS_LEGACY + 77)
-#define MX51_INT_CTI_IRQ (NR_IRQS_LEGACY + 78)
-#define MX51_INT_CTI1_TG0 (NR_IRQS_LEGACY + 79)
-#define MX51_INT_CTI1_TG1 (NR_IRQS_LEGACY + 80)
-#define MX51_INT_MCG_ERR (NR_IRQS_LEGACY + 81)
-#define MX51_INT_MCG_TMR (NR_IRQS_LEGACY + 82)
-#define MX51_INT_MCG_FUNC (NR_IRQS_LEGACY + 83)
-#define MX51_INT_GPU2_IRQ (NR_IRQS_LEGACY + 84)
-#define MX51_INT_GPU2_BUSY (NR_IRQS_LEGACY + 85)
-#define MX51_INT_RESV86 (NR_IRQS_LEGACY + 86)
-#define MX51_INT_FEC (NR_IRQS_LEGACY + 87)
-#define MX51_INT_OWIRE (NR_IRQS_LEGACY + 88)
-#define MX51_INT_CTI1_TG2 (NR_IRQS_LEGACY + 89)
-#define MX51_INT_SJC (NR_IRQS_LEGACY + 90)
-#define MX51_INT_SPDIF (NR_IRQS_LEGACY + 91)
-#define MX51_INT_TVE (NR_IRQS_LEGACY + 92)
-#define MX51_INT_FIRI (NR_IRQS_LEGACY + 93)
-#define MX51_INT_PWM2 (NR_IRQS_LEGACY + 94)
-#define MX51_INT_SLIM_EXP (NR_IRQS_LEGACY + 95)
-#define MX51_INT_SSI3 (NR_IRQS_LEGACY + 96)
-#define MX51_INT_EMI_BOOT (NR_IRQS_LEGACY + 97)
-#define MX51_INT_CTI1_TG3 (NR_IRQS_LEGACY + 98)
-#define MX51_INT_SMC_RX (NR_IRQS_LEGACY + 99)
-#define MX51_INT_VPU_IDLE (NR_IRQS_LEGACY + 100)
-#define MX51_INT_EMI_NFC (NR_IRQS_LEGACY + 101)
-#define MX51_INT_GPU_IDLE (NR_IRQS_LEGACY + 102)
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx51_revision(void);
-extern void mx51_display_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX51_H__ */
diff --git a/arch/arm/mach-imx/mx53.h b/arch/arm/mach-imx/mx53.h
deleted file mode 100644
index f829d1c22501..000000000000
--- a/arch/arm/mach-imx/mx53.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef __MACH_MX53_H__
-#define __MACH_MX53_H__
-
-/*
- * IROM
- */
-#define MX53_IROM_BASE_ADDR 0x0
-#define MX53_IROM_SIZE SZ_64K
-
-/* TZIC */
-#define MX53_TZIC_BASE_ADDR 0x0FFFC000
-#define MX53_TZIC_SIZE SZ_16K
-
-/*
- * AHCI SATA
- */
-#define MX53_SATA_BASE_ADDR 0x10000000
-
-/*
- * NFC
- */
-#define MX53_NFC_AXI_BASE_ADDR 0xF7FF0000 /* NAND flash AXI */
-#define MX53_NFC_AXI_SIZE SZ_64K
-
-/*
- * IRAM
- */
-#define MX53_IRAM_BASE_ADDR 0xF8000000 /* internal ram */
-#define MX53_IRAM_PARTITIONS 16
-#define MX53_IRAM_SIZE (MX53_IRAM_PARTITIONS * SZ_8K) /* 128KB */
-
-/*
- * Graphics Memory of GPU
- */
-#define MX53_IPU_CTRL_BASE_ADDR 0x18000000
-#define MX53_GPU2D_BASE_ADDR 0x20000000
-#define MX53_GPU_BASE_ADDR 0x30000000
-#define MX53_GPU_GMEM_BASE_ADDR 0xF8020000
-
-#define MX53_DEBUG_BASE_ADDR 0x40000000
-#define MX53_DEBUG_SIZE SZ_1M
-#define MX53_ETB_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00001000)
-#define MX53_ETM_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00002000)
-#define MX53_TPIU_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00003000)
-#define MX53_CTI0_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00004000)
-#define MX53_CTI1_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00005000)
-#define MX53_CTI2_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00006000)
-#define MX53_CTI3_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00007000)
-#define MX53_CORTEX_DBG_BASE_ADDR (MX53_DEBUG_BASE_ADDR + 0x00008000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX53_SPBA0_BASE_ADDR 0x50000000
-#define MX53_SPBA0_SIZE SZ_1M
-
-#define MX53_ESDHC1_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00004000)
-#define MX53_ESDHC2_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00008000)
-#define MX53_UART3_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX53_ECSPI1_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00010000)
-#define MX53_SSI2_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00014000)
-#define MX53_ESDHC3_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00020000)
-#define MX53_ESDHC4_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00024000)
-#define MX53_SPDIF_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00028000)
-#define MX53_ASRC_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x0002C000)
-#define MX53_ATA_DMA_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00030000)
-#define MX53_SLIM_DMA_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00034000)
-#define MX53_HSI2C_DMA_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00038000)
-#define MX53_SPBA_CTRL_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x0003C000)
-
-/*
- * AIPS 1
- */
-#define MX53_AIPS1_BASE_ADDR 0x53F00000
-#define MX53_AIPS1_SIZE SZ_1M
-
-#define MX53_OTG_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00080000)
-#define MX53_GPIO1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00084000)
-#define MX53_GPIO2_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00088000)
-#define MX53_GPIO3_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x0008C000)
-#define MX53_GPIO4_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00090000)
-#define MX53_KPP_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00094000)
-#define MX53_WDOG1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x00098000)
-#define MX53_WDOG2_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x0009C000)
-#define MX53_GPT1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000A0000)
-#define MX53_SRTC_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000A4000)
-#define MX53_IOMUXC_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000A8000)
-#define MX53_EPIT1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000AC000)
-#define MX53_EPIT2_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000B0000)
-#define MX53_PWM1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000B4000)
-#define MX53_PWM2_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000B8000)
-#define MX53_UART1_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000BC000)
-#define MX53_UART2_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000C0000)
-#define MX53_SRC_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000D0000)
-#define MX53_CCM_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000D4000)
-#define MX53_GPC_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000D8000)
-#define MX53_GPIO5_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000DC000)
-#define MX53_GPIO6_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000E0000)
-#define MX53_GPIO7_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000E4000)
-#define MX53_ATA_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000E8000)
-#define MX53_I2C3_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000EC000)
-#define MX53_UART4_BASE_ADDR (MX53_AIPS1_BASE_ADDR + 0x000F0000)
-
-/*
- * AIPS 2
- */
-#define MX53_AIPS2_BASE_ADDR 0x63F00000
-#define MX53_AIPS2_SIZE SZ_1M
-
-#define MX53_PLL1_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00080000)
-#define MX53_PLL2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00084000)
-#define MX53_PLL3_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00088000)
-#define MX53_PLL4_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x0008C000)
-#define MX53_UART5_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00090000)
-#define MX53_AHBMAX_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00094000)
-#define MX53_IIM_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x00098000)
-#define MX53_CSU_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x0009C000)
-#define MX53_ARM_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A0000)
-#define MX53_OWIRE_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A4000)
-#define MX53_FIRI_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX53_ECSPI2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000AC000)
-#define MX53_SDMA_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B0000)
-#define MX53_SCC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B4000)
-#define MX53_ROMCP_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B8000)
-#define MX53_RTIC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX53_CSPI_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C0000)
-#define MX53_I2C2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C4000)
-#define MX53_I2C1_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C8000)
-#define MX53_SSI1_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000CC000)
-#define MX53_AUDMUX_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000D0000)
-#define MX53_RTC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000D4000)
-#define MX53_M4IF_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000D8000)
-#define MX53_ESDCTL_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000D9000)
-#define MX53_WEIM_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000DA000)
-#define MX53_NFC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000DB000)
-#define MX53_EMI_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000DBF00)
-#define MX53_MIPI_HSC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000DC000)
-#define MX53_MLB_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000E4000)
-#define MX53_SSI3_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000E8000)
-#define MX53_FEC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000EC000)
-#define MX53_TVE_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000F0000)
-#define MX53_VPU_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000F4000)
-#define MX53_SAHARA_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000F8000)
-#define MX53_PTP_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000FC000)
-
-/*
- * Memory regions and CS
- */
-#define MX53_CSD0_BASE_ADDR 0x70000000
-#define MX53_CSD1_BASE_ADDR 0xB0000000
-#define MX53_CS0_BASE_ADDR 0xF0000000
-#define MX53_CS1_32MB_BASE_ADDR 0xF2000000
-#define MX53_CS1_64MB_BASE_ADDR 0xF4000000
-#define MX53_CS2_64MB_BASE_ADDR 0xF4000000
-#define MX53_CS2_96MB_BASE_ADDR 0xF6000000
-#define MX53_CS3_BASE_ADDR 0xF6000000
-
-#define MX53_IO_P2V(x) IMX_IO_P2V(x)
-#define MX53_IO_ADDRESS(x) IOMEM(MX53_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX53_SPBA_SDHC1 0x04
-#define MX53_SPBA_SDHC2 0x08
-#define MX53_SPBA_UART3 0x0C
-#define MX53_SPBA_CSPI1 0x10
-#define MX53_SPBA_SSI2 0x14
-#define MX53_SPBA_SDHC3 0x20
-#define MX53_SPBA_SDHC4 0x24
-#define MX53_SPBA_SPDIF 0x28
-#define MX53_SPBA_ATA 0x30
-#define MX53_SPBA_SLIM 0x34
-#define MX53_SPBA_HSI2C 0x38
-#define MX53_SPBA_CTRL 0x3C
-
-/*
- * DMA request assignments
- */
-#define MX53_DMA_REQ_SSI3_TX0 47
-#define MX53_DMA_REQ_SSI3_RX0 46
-#define MX53_DMA_REQ_SSI3_TX1 45
-#define MX53_DMA_REQ_SSI3_RX1 44
-#define MX53_DMA_REQ_UART3_TX 43
-#define MX53_DMA_REQ_UART3_RX 42
-#define MX53_DMA_REQ_ESAI_TX 41
-#define MX53_DMA_REQ_ESAI_RX 40
-#define MX53_DMA_REQ_CSPI_TX 39
-#define MX53_DMA_REQ_CSPI_RX 38
-#define MX53_DMA_REQ_ASRC_DMA6 37
-#define MX53_DMA_REQ_ASRC_DMA5 36
-#define MX53_DMA_REQ_ASRC_DMA4 35
-#define MX53_DMA_REQ_ASRC_DMA3 34
-#define MX53_DMA_REQ_ASRC_DMA2 33
-#define MX53_DMA_REQ_ASRC_DMA1 32
-#define MX53_DMA_REQ_EMI_WR 31
-#define MX53_DMA_REQ_EMI_RD 30
-#define MX53_DMA_REQ_SSI1_TX0 29
-#define MX53_DMA_REQ_SSI1_RX0 28
-#define MX53_DMA_REQ_SSI1_TX1 27
-#define MX53_DMA_REQ_SSI1_RX1 26
-#define MX53_DMA_REQ_SSI2_TX0 25
-#define MX53_DMA_REQ_SSI2_RX0 24
-#define MX53_DMA_REQ_SSI2_TX1 23
-#define MX53_DMA_REQ_SSI2_RX1 22
-#define MX53_DMA_REQ_I2C2_SDHC2 21
-#define MX53_DMA_REQ_I2C1_SDHC1 20
-#define MX53_DMA_REQ_UART1_TX 19
-#define MX53_DMA_REQ_UART1_RX 18
-#define MX53_DMA_REQ_UART5_TX 17
-#define MX53_DMA_REQ_UART5_RX 16
-#define MX53_DMA_REQ_SPDIF_TX 15
-#define MX53_DMA_REQ_SPDIF_RX 14
-#define MX53_DMA_REQ_UART2_FIRI_TX 13
-#define MX53_DMA_REQ_UART2_FIRI_RX 12
-#define MX53_DMA_REQ_SDHC4 11
-#define MX53_DMA_REQ_I2C3_SDHC3 10
-#define MX53_DMA_REQ_CSPI2_TX 9
-#define MX53_DMA_REQ_CSPI2_RX 8
-#define MX53_DMA_REQ_CSPI1_TX 7
-#define MX53_DMA_REQ_CSPI1_RX 6
-#define MX53_DMA_REQ_IPU 5
-#define MX53_DMA_REQ_ATA_TX_END 4
-#define MX53_DMA_REQ_ATA_UART4_TX 3
-#define MX53_DMA_REQ_ATA_UART4_RX 2
-#define MX53_DMA_REQ_GPC 1
-#define MX53_DMA_REQ_VPU 0
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX53_INT_RESV0 (NR_IRQS_LEGACY + 0)
-#define MX53_INT_ESDHC1 (NR_IRQS_LEGACY + 1)
-#define MX53_INT_ESDHC2 (NR_IRQS_LEGACY + 2)
-#define MX53_INT_ESDHC3 (NR_IRQS_LEGACY + 3)
-#define MX53_INT_ESDHC4 (NR_IRQS_LEGACY + 4)
-#define MX53_INT_DAP (NR_IRQS_LEGACY + 5)
-#define MX53_INT_SDMA (NR_IRQS_LEGACY + 6)
-#define MX53_INT_IOMUX (NR_IRQS_LEGACY + 7)
-#define MX53_INT_NFC (NR_IRQS_LEGACY + 8)
-#define MX53_INT_VPU (NR_IRQS_LEGACY + 9)
-#define MX53_INT_IPU_ERR (NR_IRQS_LEGACY + 10)
-#define MX53_INT_IPU_SYN (NR_IRQS_LEGACY + 11)
-#define MX53_INT_GPU (NR_IRQS_LEGACY + 12)
-#define MX53_INT_UART4 (NR_IRQS_LEGACY + 13)
-#define MX53_INT_USB_H1 (NR_IRQS_LEGACY + 14)
-#define MX53_INT_EMI (NR_IRQS_LEGACY + 15)
-#define MX53_INT_USB_H2 (NR_IRQS_LEGACY + 16)
-#define MX53_INT_USB_H3 (NR_IRQS_LEGACY + 17)
-#define MX53_INT_USB_OTG (NR_IRQS_LEGACY + 18)
-#define MX53_INT_SAHARA_H0 (NR_IRQS_LEGACY + 19)
-#define MX53_INT_SAHARA_H1 (NR_IRQS_LEGACY + 20)
-#define MX53_INT_SCC_SMN (NR_IRQS_LEGACY + 21)
-#define MX53_INT_SCC_STZ (NR_IRQS_LEGACY + 22)
-#define MX53_INT_SCC_SCM (NR_IRQS_LEGACY + 23)
-#define MX53_INT_SRTC_NTZ (NR_IRQS_LEGACY + 24)
-#define MX53_INT_SRTC_TZ (NR_IRQS_LEGACY + 25)
-#define MX53_INT_RTIC (NR_IRQS_LEGACY + 26)
-#define MX53_INT_CSU (NR_IRQS_LEGACY + 27)
-#define MX53_INT_SATA (NR_IRQS_LEGACY + 28)
-#define MX53_INT_SSI1 (NR_IRQS_LEGACY + 29)
-#define MX53_INT_SSI2 (NR_IRQS_LEGACY + 30)
-#define MX53_INT_UART1 (NR_IRQS_LEGACY + 31)
-#define MX53_INT_UART2 (NR_IRQS_LEGACY + 32)
-#define MX53_INT_UART3 (NR_IRQS_LEGACY + 33)
-#define MX53_INT_RTC (NR_IRQS_LEGACY + 34)
-#define MX53_INT_PTP (NR_IRQS_LEGACY + 35)
-#define MX53_INT_ECSPI1 (NR_IRQS_LEGACY + 36)
-#define MX53_INT_ECSPI2 (NR_IRQS_LEGACY + 37)
-#define MX53_INT_CSPI (NR_IRQS_LEGACY + 38)
-#define MX53_INT_GPT (NR_IRQS_LEGACY + 39)
-#define MX53_INT_EPIT1 (NR_IRQS_LEGACY + 40)
-#define MX53_INT_EPIT2 (NR_IRQS_LEGACY + 41)
-#define MX53_INT_GPIO1_INT7 (NR_IRQS_LEGACY + 42)
-#define MX53_INT_GPIO1_INT6 (NR_IRQS_LEGACY + 43)
-#define MX53_INT_GPIO1_INT5 (NR_IRQS_LEGACY + 44)
-#define MX53_INT_GPIO1_INT4 (NR_IRQS_LEGACY + 45)
-#define MX53_INT_GPIO1_INT3 (NR_IRQS_LEGACY + 46)
-#define MX53_INT_GPIO1_INT2 (NR_IRQS_LEGACY + 47)
-#define MX53_INT_GPIO1_INT1 (NR_IRQS_LEGACY + 48)
-#define MX53_INT_GPIO1_INT0 (NR_IRQS_LEGACY + 49)
-#define MX53_INT_GPIO1_LOW (NR_IRQS_LEGACY + 50)
-#define MX53_INT_GPIO1_HIGH (NR_IRQS_LEGACY + 51)
-#define MX53_INT_GPIO2_LOW (NR_IRQS_LEGACY + 52)
-#define MX53_INT_GPIO2_HIGH (NR_IRQS_LEGACY + 53)
-#define MX53_INT_GPIO3_LOW (NR_IRQS_LEGACY + 54)
-#define MX53_INT_GPIO3_HIGH (NR_IRQS_LEGACY + 55)
-#define MX53_INT_GPIO4_LOW (NR_IRQS_LEGACY + 56)
-#define MX53_INT_GPIO4_HIGH (NR_IRQS_LEGACY + 57)
-#define MX53_INT_WDOG1 (NR_IRQS_LEGACY + 58)
-#define MX53_INT_WDOG2 (NR_IRQS_LEGACY + 59)
-#define MX53_INT_KPP (NR_IRQS_LEGACY + 60)
-#define MX53_INT_PWM1 (NR_IRQS_LEGACY + 61)
-#define MX53_INT_I2C1 (NR_IRQS_LEGACY + 62)
-#define MX53_INT_I2C2 (NR_IRQS_LEGACY + 63)
-#define MX53_INT_I2C3 (NR_IRQS_LEGACY + 64)
-#define MX53_INT_MLB (NR_IRQS_LEGACY + 65)
-#define MX53_INT_ASRC (NR_IRQS_LEGACY + 66)
-#define MX53_INT_SPDIF (NR_IRQS_LEGACY + 67)
-#define MX53_INT_SIM_DAT (NR_IRQS_LEGACY + 68)
-#define MX53_INT_IIM (NR_IRQS_LEGACY + 69)
-#define MX53_INT_ATA (NR_IRQS_LEGACY + 70)
-#define MX53_INT_CCM1 (NR_IRQS_LEGACY + 71)
-#define MX53_INT_CCM2 (NR_IRQS_LEGACY + 72)
-#define MX53_INT_GPC1 (NR_IRQS_LEGACY + 73)
-#define MX53_INT_GPC2 (NR_IRQS_LEGACY + 74)
-#define MX53_INT_SRC (NR_IRQS_LEGACY + 75)
-#define MX53_INT_NM (NR_IRQS_LEGACY + 76)
-#define MX53_INT_PMU (NR_IRQS_LEGACY + 77)
-#define MX53_INT_CTI_IRQ (NR_IRQS_LEGACY + 78)
-#define MX53_INT_CTI1_TG0 (NR_IRQS_LEGACY + 79)
-#define MX53_INT_CTI1_TG1 (NR_IRQS_LEGACY + 80)
-#define MX53_INT_ESAI (NR_IRQS_LEGACY + 81)
-#define MX53_INT_CAN1 (NR_IRQS_LEGACY + 82)
-#define MX53_INT_CAN2 (NR_IRQS_LEGACY + 83)
-#define MX53_INT_GPU2_IRQ (NR_IRQS_LEGACY + 84)
-#define MX53_INT_GPU2_BUSY (NR_IRQS_LEGACY + 85)
-#define MX53_INT_UART5 (NR_IRQS_LEGACY + 86)
-#define MX53_INT_FEC (NR_IRQS_LEGACY + 87)
-#define MX53_INT_OWIRE (NR_IRQS_LEGACY + 88)
-#define MX53_INT_CTI1_TG2 (NR_IRQS_LEGACY + 89)
-#define MX53_INT_SJC (NR_IRQS_LEGACY + 90)
-#define MX53_INT_TVE (NR_IRQS_LEGACY + 92)
-#define MX53_INT_FIRI (NR_IRQS_LEGACY + 93)
-#define MX53_INT_PWM2 (NR_IRQS_LEGACY + 94)
-#define MX53_INT_SLIM_EXP (NR_IRQS_LEGACY + 95)
-#define MX53_INT_SSI3 (NR_IRQS_LEGACY + 96)
-#define MX53_INT_EMI_BOOT (NR_IRQS_LEGACY + 97)
-#define MX53_INT_CTI1_TG3 (NR_IRQS_LEGACY + 98)
-#define MX53_INT_SMC_RX (NR_IRQS_LEGACY + 99)
-#define MX53_INT_VPU_IDLE (NR_IRQS_LEGACY + 100)
-#define MX53_INT_EMI_NFC (NR_IRQS_LEGACY + 101)
-#define MX53_INT_GPU_IDLE (NR_IRQS_LEGACY + 102)
-#define MX53_INT_GPIO5_LOW (NR_IRQS_LEGACY + 103)
-#define MX53_INT_GPIO5_HIGH (NR_IRQS_LEGACY + 104)
-#define MX53_INT_GPIO6_LOW (NR_IRQS_LEGACY + 105)
-#define MX53_INT_GPIO6_HIGH (NR_IRQS_LEGACY + 106)
-#define MX53_INT_GPIO7_LOW (NR_IRQS_LEGACY + 107)
-#define MX53_INT_GPIO7_HIGH (NR_IRQS_LEGACY + 108)
-
-#endif /* ifndef __MACH_MX53_H__ */
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 75d6a37e1ae4..a39b69ef4301 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -154,10 +154,17 @@ extern unsigned int __mxc_cpu_type;
#endif
#ifndef __ASSEMBLY__
+#ifdef CONFIG_SOC_IMX6SL
static inline bool cpu_is_imx6sl(void)
{
return __mxc_cpu_type == MXC_CPU_IMX6SL;
}
+#else
+static inline bool cpu_is_imx6sl(void)
+{
+ return false;
+}
+#endif
static inline bool cpu_is_imx6dl(void)
{
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index 58aeaf5baaf6..f1f80ab73e69 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -19,9 +19,26 @@
#include "common.h"
#include "cpuidle.h"
-#include "crm-regs-imx5.h"
#include "hardware.h"
+#define MXC_CCM_CLPCR 0x54
+#define MXC_CCM_CLPCR_LPM_OFFSET 0
+#define MXC_CCM_CLPCR_LPM_MASK 0x3
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET 9
+#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
+#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
+
+#define MXC_CORTEXA8_PLAT_LPC 0xc
+#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1)
+
+#define MXC_SRPG_NEON_SRPGCR 0x280
+#define MXC_SRPG_ARM_SRPGCR 0x2a0
+#define MXC_SRPG_EMPGC0_SRPGCR 0x2c0
+#define MXC_SRPG_EMPGC1_SRPGCR 0x2d0
+
+#define MXC_SRPGCR_PCR 1
+
/*
* The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
* This is also the lowest power state possible without affecting
@@ -32,6 +49,30 @@
*/
#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
+struct imx5_pm_data {
+ phys_addr_t cortex_addr;
+ phys_addr_t gpc_addr;
+};
+
+static const struct imx5_pm_data imx51_pm_data __initconst = {
+ .cortex_addr = 0x83fa0000,
+ .gpc_addr = 0x73fd8000,
+};
+
+static const struct imx5_pm_data imx53_pm_data __initconst = {
+ .cortex_addr = 0x63fa0000,
+ .gpc_addr = 0x53fd8000,
+};
+
+static void __iomem *ccm_base;
+static void __iomem *cortex_base;
+static void __iomem *gpc_base;
+
+void __init imx5_pm_set_ccm_base(void __iomem *base)
+{
+ ccm_base = base;
+}
+
/*
* set cpu low power mode before WFI instruction. This function is called
* mx5 because it can be used for mx51, and mx53.
@@ -43,12 +84,16 @@ static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
int stop_mode = 0;
/* always allow platform to issue a deep sleep mode request */
- plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+ plat_lpc = __raw_readl(cortex_base + MXC_CORTEXA8_PLAT_LPC) &
~(MXC_CORTEXA8_PLAT_LPC_DSM);
- ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
- arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
- empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
- empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+ ccm_clpcr = __raw_readl(ccm_base + MXC_CCM_CLPCR) &
+ ~(MXC_CCM_CLPCR_LPM_MASK);
+ arm_srpgcr = __raw_readl(gpc_base + MXC_SRPG_ARM_SRPGCR) &
+ ~(MXC_SRPGCR_PCR);
+ empgc0 = __raw_readl(gpc_base + MXC_SRPG_EMPGC0_SRPGCR) &
+ ~(MXC_SRPGCR_PCR);
+ empgc1 = __raw_readl(gpc_base + MXC_SRPG_EMPGC1_SRPGCR) &
+ ~(MXC_SRPGCR_PCR);
switch (mode) {
case WAIT_CLOCKED:
@@ -82,17 +127,17 @@ static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
return;
}
- __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
- __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
- __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
- __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+ __raw_writel(plat_lpc, cortex_base + MXC_CORTEXA8_PLAT_LPC);
+ __raw_writel(ccm_clpcr, ccm_base + MXC_CCM_CLPCR);
+ __raw_writel(arm_srpgcr, gpc_base + MXC_SRPG_ARM_SRPGCR);
+ __raw_writel(arm_srpgcr, gpc_base + MXC_SRPG_NEON_SRPGCR);
if (stop_mode) {
empgc0 |= MXC_SRPGCR_PCR;
empgc1 |= MXC_SRPGCR_PCR;
- __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
- __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+ __raw_writel(empgc0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(empgc1, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
}
}
@@ -114,8 +159,8 @@ static int mx5_suspend_enter(suspend_state_t state)
flush_cache_all();
/*clear the EMPGC0/1 bits */
- __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
- __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ __raw_writel(0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
}
cpu_do_idle();
@@ -149,7 +194,7 @@ static void imx5_pm_idle(void)
imx5_cpu_do_idle();
}
-static int __init imx5_pm_common_init(void)
+static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
{
int ret;
struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
@@ -163,15 +208,28 @@ static int __init imx5_pm_common_init(void)
arm_pm_idle = imx5_pm_idle;
+ cortex_base = ioremap(data->cortex_addr, SZ_16K);
+ gpc_base = ioremap(data->gpc_addr, SZ_16K);
+ WARN_ON(!ccm_base || !cortex_base || !gpc_base);
+
/* Set the registers to the default cpu idle state. */
mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
- return imx5_cpuidle_init();
+ ret = imx5_cpuidle_init();
+ if (ret)
+ pr_warn("%s: cpuidle init failed %d\n", __func__, ret);
+
+ suspend_set_ops(&mx5_suspend_ops);
+
+ return 0;
+}
+
+void __init imx51_pm_init(void)
+{
+ imx5_pm_common_init(&imx51_pm_data);
}
-void __init imx5_pm_init(void)
+void __init imx53_pm_init(void)
{
- int ret = imx5_pm_common_init();
- if (!ret)
- suspend_set_ops(&mx5_suspend_ops);
+ imx5_pm_common_init(&imx53_pm_data);
}
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 9392a8f4ef24..5c3af8f993d0 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -129,6 +129,14 @@ static const u32 imx6sl_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x320, /* SDCKE0, SDCKE1, RESET */
};
+static const u32 imx6sx_mmdc_io_offset[] __initconst = {
+ 0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
+ 0x60c, 0x610, 0x61c, 0x620, /* GPR_B0DS ~ GPR_B3DS */
+ 0x300, 0x2fc, 0x32c, 0x5f4, /* CAS, RAS, SDCLK_0, GPR_ADDS */
+ 0x310, 0x314, 0x5f8, 0x608, /* SODT0, SODT1, MODE_CTL, MODE */
+ 0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
+};
+
static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
.cpu_type = MXC_CPU_IMX6Q,
.mmdc_compat = "fsl,imx6q-mmdc",
@@ -159,6 +167,16 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
.mmdc_io_offset = imx6sl_mmdc_io_offset,
};
+static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
+ .cpu_type = MXC_CPU_IMX6SX,
+ .mmdc_compat = "fsl,imx6sx-mmdc",
+ .src_compat = "fsl,imx6sx-src",
+ .iomuxc_compat = "fsl,imx6sx-iomuxc",
+ .gpc_compat = "fsl,imx6sx-gpc",
+ .mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
+ .mmdc_io_offset = imx6sx_mmdc_io_offset,
+};
+
/*
* This structure is for passing necessary data for low level ocram
* suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
@@ -181,11 +199,13 @@ struct imx6_cpu_pm_info {
u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */
} __aligned(8);
-void imx6q_set_int_mem_clk_lpm(void)
+void imx6q_set_int_mem_clk_lpm(bool enable)
{
u32 val = readl_relaxed(ccm_base + CGPR);
- val |= BM_CGPR_INT_MEM_CLK_LPM;
+ val &= ~BM_CGPR_INT_MEM_CLK_LPM;
+ if (enable)
+ val |= BM_CGPR_INT_MEM_CLK_LPM;
writel_relaxed(val, ccm_base + CGPR);
}
@@ -254,6 +274,14 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
break;
case STOP_POWER_ON:
val |= 0x2 << BP_CLPCR_LPM;
+ val &= ~BM_CLPCR_VSTBY;
+ val &= ~BM_CLPCR_SBYOS;
+ if (cpu_is_imx6sl())
+ val |= BM_CLPCR_BYPASS_PMIC_READY;
+ if (cpu_is_imx6sl() || cpu_is_imx6sx())
+ val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ else
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
case WAIT_UNCLOCKED_POWER_OFF:
val |= 0x1 << BP_CLPCR_LPM;
@@ -265,12 +293,12 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
val |= 0x3 << BP_CLPCR_STBY_COUNT;
val |= BM_CLPCR_VSTBY;
val |= BM_CLPCR_SBYOS;
- if (cpu_is_imx6sl()) {
+ if (cpu_is_imx6sl())
val |= BM_CLPCR_BYPASS_PMIC_READY;
+ if (cpu_is_imx6sl() || cpu_is_imx6sx())
val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
- } else {
+ else
val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
- }
break;
default:
return -EINVAL;
@@ -314,8 +342,22 @@ static int imx6q_suspend_finish(unsigned long val)
static int imx6q_pm_enter(suspend_state_t state)
{
switch (state) {
+ case PM_SUSPEND_STANDBY:
+ imx6q_set_lpm(STOP_POWER_ON);
+ imx6q_set_int_mem_clk_lpm(true);
+ imx_gpc_pre_suspend(false);
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(true);
+ /* Zzz ... */
+ cpu_do_idle();
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(false);
+ imx_gpc_post_resume();
+ imx6q_set_lpm(WAIT_CLOCKED);
+ break;
case PM_SUSPEND_MEM:
imx6q_set_lpm(STOP_POWER_OFF);
+ imx6q_set_int_mem_clk_lpm(false);
imx6q_enable_wb(true);
/*
* For suspend into ocram, asm code already take care of
@@ -323,7 +365,7 @@ static int imx6q_pm_enter(suspend_state_t state)
*/
if (!imx6_suspend_in_ocram_fn)
imx6q_enable_rbc(true);
- imx_gpc_pre_suspend();
+ imx_gpc_pre_suspend(true);
imx_anatop_pre_suspend();
imx_set_cpu_jump(0, v7_cpu_resume);
/* Zzz ... */
@@ -334,6 +376,7 @@ static int imx6q_pm_enter(suspend_state_t state)
imx_gpc_post_resume();
imx6q_enable_rbc(false);
imx6q_enable_wb(false);
+ imx6q_set_int_mem_clk_lpm(true);
imx6q_set_lpm(WAIT_CLOCKED);
break;
default:
@@ -343,9 +386,14 @@ static int imx6q_pm_enter(suspend_state_t state)
return 0;
}
+static int imx6q_pm_valid(suspend_state_t state)
+{
+ return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
+}
+
static const struct platform_suspend_ops imx6q_pm_ops = {
.enter = imx6q_pm_enter,
- .valid = suspend_valid_only_mem,
+ .valid = imx6q_pm_valid,
};
void __init imx6q_pm_set_ccm_base(void __iomem *base)
@@ -549,3 +597,8 @@ void __init imx6sl_pm_init(void)
{
imx6_pm_common_init(&imx6sl_pm_data);
}
+
+void __init imx6sx_pm_init(void)
+{
+ imx6_pm_common_init(&imx6sx_pm_data);
+}
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index fe123b079c05..74b50f1982db 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -10,6 +10,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/hardware/cache-l2x0.h>
#include "hardware.h"
@@ -301,7 +302,7 @@ rbc_loop:
resume_mmdc
/* return to suspend finish */
- mov pc, lr
+ ret lr
resume:
/* invalidate L1 I-cache first */
@@ -325,7 +326,7 @@ resume:
mov r5, #0x1
resume_mmdc
- mov pc, lr
+ ret lr
ENDPROC(imx6_suspend)
/*
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index 3b0733edb68c..d14c33fd6b03 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -42,7 +42,10 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
{
unsigned int wcr_enable;
- if (wdog_clk)
+ if (!wdog_base)
+ goto reset_fallback;
+
+ if (!IS_ERR(wdog_clk))
clk_enable(wdog_clk);
if (cpu_is_mx1())
@@ -70,6 +73,7 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
/* delay to allow the serial port to show the message */
mdelay(50);
+reset_fallback:
/* we'll take a jump through zero as a poor second */
soft_restart(0);
}
@@ -79,13 +83,10 @@ void __init mxc_arch_reset_init(void __iomem *base)
wdog_base = base;
wdog_clk = clk_get_sys("imx2-wdt.0", NULL);
- if (IS_ERR(wdog_clk)) {
+ if (IS_ERR(wdog_clk))
pr_warn("%s: failed to get wdog clock\n", __func__);
- wdog_clk = NULL;
- return;
- }
-
- clk_prepare(wdog_clk);
+ else
+ clk_prepare(wdog_clk);
}
void __init mxc_arch_reset_init_dt(void)
@@ -97,13 +98,10 @@ void __init mxc_arch_reset_init_dt(void)
WARN_ON(!wdog_base);
wdog_clk = of_clk_get(np, 0);
- if (IS_ERR(wdog_clk)) {
+ if (IS_ERR(wdog_clk))
pr_warn("%s: failed to get wdog clock\n", __func__);
- wdog_clk = NULL;
- return;
- }
-
- clk_prepare(wdog_clk);
+ else
+ clk_prepare(wdog_clk);
}
#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index bed081e58262..bf92e5a351c0 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -290,25 +290,20 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
return 0;
}
-void __init mxc_timer_init(void __iomem *base, int irq)
+static void __init _mxc_timer_init(int irq,
+ struct clk *clk_per, struct clk *clk_ipg)
{
uint32_t tctl_val;
- struct clk *timer_clk;
- struct clk *timer_ipg_clk;
- timer_clk = clk_get_sys("imx-gpt.0", "per");
- if (IS_ERR(timer_clk)) {
+ if (IS_ERR(clk_per)) {
pr_err("i.MX timer: unable to get clk\n");
return;
}
- timer_ipg_clk = clk_get_sys("imx-gpt.0", "ipg");
- if (!IS_ERR(timer_ipg_clk))
- clk_prepare_enable(timer_ipg_clk);
-
- clk_prepare_enable(timer_clk);
+ if (!IS_ERR(clk_ipg))
+ clk_prepare_enable(clk_ipg);
- timer_base = base;
+ clk_prepare_enable(clk_per);
/*
* Initialise to a known state (all timers off, and timing reset)
@@ -325,21 +320,45 @@ void __init mxc_timer_init(void __iomem *base, int irq)
__raw_writel(tctl_val, timer_base + MXC_TCTL);
/* init and register the timer to the framework */
- mxc_clocksource_init(timer_clk);
- mxc_clockevent_init(timer_clk);
+ mxc_clocksource_init(clk_per);
+ mxc_clockevent_init(clk_per);
/* Make irqs happen */
setup_irq(irq, &mxc_timer_irq);
}
-void __init mxc_timer_init_dt(struct device_node *np)
+void __init mxc_timer_init(void __iomem *base, int irq)
{
- void __iomem *base;
+ struct clk *clk_per = clk_get_sys("imx-gpt.0", "per");
+ struct clk *clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
+
+ timer_base = base;
+
+ _mxc_timer_init(irq, clk_per, clk_ipg);
+}
+
+static void __init mxc_timer_init_dt(struct device_node *np)
+{
+ struct clk *clk_per, *clk_ipg;
int irq;
- base = of_iomap(np, 0);
- WARN_ON(!base);
+ if (timer_base)
+ return;
+
+ timer_base = of_iomap(np, 0);
+ WARN_ON(!timer_base);
irq = irq_of_parse_and_map(np, 0);
- mxc_timer_init(base, irq);
+ clk_per = of_clk_get_by_name(np, "per");
+ clk_ipg = of_clk_get_by_name(np, "ipg");
+
+ _mxc_timer_init(irq, clk_per, clk_ipg);
}
+CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx50_timer, "fsl,imx50-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx51_timer, "fsl,imx51-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx53_timer, "fsl,imx53-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6q_timer, "fsl,imx6q-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6sl_timer, "fsl,imx6sl-gpt", mxc_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(mx6sx_timer, "fsl,imx6sx-gpt", mxc_timer_init_dt);
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c
index 7828af4b2022..1d4f384ca773 100644
--- a/arch/arm/mach-imx/tzic.c
+++ b/arch/arm/mach-imx/tzic.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/mach/irq.h>
#include <asm/exception.h>
@@ -153,13 +154,16 @@ static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
* interrupts. It registers the interrupt enable and disable functions
* to the kernel for each interrupt source.
*/
-void __init tzic_init_irq(void __iomem *irqbase)
+void __init tzic_init_irq(void)
{
struct device_node *np;
int irq_base;
int i;
- tzic_base = irqbase;
+ np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
+ tzic_base = of_iomap(np, 0);
+ WARN_ON(!tzic_base);
+
/* put the TZIC into the reset value with
* all interrupts disabled
*/
@@ -181,7 +185,6 @@ void __init tzic_init_irq(void __iomem *irqbase)
irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
WARN_ON(irq_base < 0);
- np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
&irq_domain_simple_ops, NULL);
WARN_ON(!domain);
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index 64f8e2564a37..c455e974bbfe 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -17,7 +17,6 @@ config ARCH_INTEGRATOR_CP
bool "Support Integrator/CP platform"
select ARCH_CINTEGRATOR
select ARM_TIMER_SP804
- select PLAT_VERSATILE_CLCD
select SERIAL_AMBA_PL011 if TTY
select SERIAL_AMBA_PL011_CONSOLE if TTY
select SOC_BUS
diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h
deleted file mode 100644
index 334d5e271889..000000000000
--- a/arch/arm/mach-integrator/include/mach/memory.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-integrator/include/mach/memory.h
- *
- * Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
-#define BUS_OFFSET UL(0x80000000)
-#define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET)
-#define __bus_to_virt(x) ((x) - BUS_OFFSET + PAGE_OFFSET)
-#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
-#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
-
-#endif
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 660ca6feff40..8ca290b479b1 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -31,7 +31,7 @@
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/irqchip/versatile-fpga.h>
+#include <linux/irqchip.h>
#include <linux/mtd/physmap.h>
#include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h>
@@ -439,15 +439,10 @@ static void __init ap_of_timer_init(void)
integrator_clockevent_init(rate, base, irq);
}
-static const struct of_device_id fpga_irq_of_match[] __initconst = {
- { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
- { /* Sentinel */ }
-};
-
static void __init ap_init_irq_of(void)
{
cm_init();
- of_irq_init(fpga_irq_of_match);
+ irqchip_init();
}
/* For the Device Tree, add in the UART callbacks as AUXDATA */
@@ -558,7 +553,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
.map_io = ap_map_io,
.init_early = ap_init_early,
.init_irq = ap_init_irq_of,
- .handle_irq = fpga_handle_irq,
.init_time = ap_of_timer_init,
.init_machine = ap_init_of,
.restart = integrator_restart,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 0e57f8f820a5..cca02eb75eb5 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -18,9 +18,10 @@
#include <linux/amba/bus.h>
#include <linux/amba/kmi.h>
#include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/amba/mmci.h>
#include <linux/io.h>
-#include <linux/irqchip/versatile-fpga.h>
+#include <linux/irqchip.h>
#include <linux/gfp.h>
#include <linux/mtd/physmap.h>
#include <linux/of_irq.h>
@@ -36,8 +37,6 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
-#include <plat/clcd.h>
-
#include "hardware.h"
#include "cm.h"
#include "common.h"
@@ -235,15 +234,10 @@ static void __init intcp_init_early(void)
sched_clock_register(intcp_read_sched_clock, 32, 24000000);
}
-static const struct of_device_id fpga_irq_of_match[] __initconst = {
- { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
- { /* Sentinel */ }
-};
-
static void __init intcp_init_irq_of(void)
{
cm_init();
- of_irq_init(fpga_irq_of_match);
+ irqchip_init();
}
/*
@@ -329,7 +323,6 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
.map_io = intcp_map_io,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq_of,
- .handle_irq = fpga_handle_irq,
.init_machine = intcp_init_of,
.restart = integrator_restart,
.dt_compat = intcp_dt_board_compat,
diff --git a/arch/arm/mach-iop13xx/include/mach/iop13xx.h b/arch/arm/mach-iop13xx/include/mach/iop13xx.h
index 17b40279e0a4..9311ee2126d6 100644
--- a/arch/arm/mach-iop13xx/include/mach/iop13xx.h
+++ b/arch/arm/mach-iop13xx/include/mach/iop13xx.h
@@ -3,7 +3,7 @@
#ifndef __ASSEMBLY__
-#include <linux/reboot.h>
+enum reboot_mode;
/* The ATU offsets can change based on the strapping */
extern u32 iop13xx_atux_pmmr_offset;
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index 7c032d0ab24a..59307e787588 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -3,11 +3,6 @@
#include <mach/hardware.h>
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-
#ifndef __ASSEMBLY__
#if defined(CONFIG_ARCH_IOP13XX)
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index bca96f433495..53c316f7301e 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -20,6 +20,7 @@
#include <linux/dma-mapping.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
+#include <linux/reboot.h>
#ifdef CONFIG_MTD_PHYSMAP
#include <linux/mtd/physmap.h>
#endif
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
deleted file mode 100644
index df4b26340ae4..000000000000
--- a/arch/arm/mach-kirkwood/Kconfig
+++ /dev/null
@@ -1,111 +0,0 @@
-if ARCH_KIRKWOOD
-
-menu "Marvell Kirkwood Implementations"
-
-config KIRKWOOD_LEGACY
- bool
-
-config MACH_D2NET_V2
- bool "LaCie d2 Network v2 NAS Board"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- LaCie d2 Network v2 NAS.
-
-config MACH_NET2BIG_V2
- bool "LaCie 2Big Network v2 NAS Board"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- LaCie 2Big Network v2 NAS.
-
-config MACH_NET5BIG_V2
- bool "LaCie 5Big Network v2 NAS Board"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- LaCie 5Big Network v2 NAS.
-
-config MACH_OPENRD
- select KIRKWOOD_LEGACY
- bool
-
-config MACH_OPENRD_BASE
- bool "Marvell OpenRD Base Board"
- select MACH_OPENRD
- help
- Say 'Y' here if you want your kernel to support the
- Marvell OpenRD Base Board.
-
-config MACH_OPENRD_CLIENT
- bool "Marvell OpenRD Client Board"
- select MACH_OPENRD
- help
- Say 'Y' here if you want your kernel to support the
- Marvell OpenRD Client Board.
-
-config MACH_OPENRD_ULTIMATE
- bool "Marvell OpenRD Ultimate Board"
- select MACH_OPENRD
- help
- Say 'Y' here if you want your kernel to support the
- Marvell OpenRD Ultimate Board.
-
-config MACH_RD88F6192_NAS
- bool "Marvell RD-88F6192-NAS Reference Board"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- Marvell RD-88F6192-NAS Reference Board.
-
-config MACH_RD88F6281
- bool "Marvell RD-88F6281 Reference Board"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- Marvell RD-88F6281 Reference Board.
-
-config MACH_T5325
- bool "HP t5325 Thin Client"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- HP t5325 Thin Client.
-
-config MACH_TS219
- bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and
- TS-219P+ Turbo NAS devices.
-
-config MACH_TS41X
- bool "QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo NAS"
- select KIRKWOOD_LEGACY
- help
- Say 'Y' here if you want your kernel to support the
- QNAP TS-410, TS-410U, TS-419P, TS-419P+ and TS-419U Turbo
- NAS devices.
-
-comment "Device tree entries"
-
-config ARCH_KIRKWOOD_DT
- bool "Marvell Kirkwood Flattened Device Tree"
- select KIRKWOOD_CLK
- select OF_IRQ
- select ORION_IRQCHIP
- select ORION_TIMER
- select POWER_SUPPLY
- select POWER_RESET
- select POWER_RESET_GPIO
- select REGULATOR
- select REGULATOR_FIXED_VOLTAGE
- select USE_OF
- help
- Say 'Y' here if you want your kernel to support the
- Marvell Kirkwood using flattened device tree.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
deleted file mode 100644
index 3a72c5c6e747..000000000000
--- a/arch/arm/mach-kirkwood/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-obj-$(CONFIG_KIRKWOOD_LEGACY) += irq.o mpp.o common.o pcie.o
-obj-$(CONFIG_PM) += pm.o
-
-obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o lacie_v2-common.o
-obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o
-obj-$(CONFIG_MACH_RD88F6192_NAS) += rd88f6192-nas-setup.o
-obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o
-obj-$(CONFIG_MACH_T5325) += t5325-setup.o
-obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o
-obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o
-
-obj-$(CONFIG_ARCH_KIRKWOOD_DT) += board-dt.o
diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot
deleted file mode 100644
index 760a0efe7580..000000000000
--- a/arch/arm/mach-kirkwood/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
- zreladdr-y += 0x00008000
-params_phys-y := 0x00000100
-initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
deleted file mode 100644
index ff18ff20f71f..000000000000
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
- *
- * arch/arm/mach-kirkwood/board-dt.c
- *
- * Flattened Device Tree board initialization
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_net.h>
-#include <linux/of_platform.h>
-#include <linux/dma-mapping.h>
-#include <linux/irqchip.h>
-#include <asm/hardware/cache-feroceon-l2.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/bridge-regs.h>
-#include <plat/common.h>
-#include <plat/pcie.h>
-#include "pm.h"
-
-static struct map_desc kirkwood_io_desc[] __initdata = {
- {
- .virtual = (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
- .pfn = __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
- .length = KIRKWOOD_REGS_SIZE,
- .type = MT_DEVICE,
- },
-};
-
-static void __init kirkwood_map_io(void)
-{
- iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
-}
-
-static struct resource kirkwood_cpufreq_resources[] = {
- [0] = {
- .start = CPU_CONTROL_PHYS,
- .end = CPU_CONTROL_PHYS + 3,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device kirkwood_cpufreq_device = {
- .name = "kirkwood-cpufreq",
- .id = -1,
- .num_resources = ARRAY_SIZE(kirkwood_cpufreq_resources),
- .resource = kirkwood_cpufreq_resources,
-};
-
-static void __init kirkwood_cpufreq_init(void)
-{
- platform_device_register(&kirkwood_cpufreq_device);
-}
-
-static struct resource kirkwood_cpuidle_resource[] = {
- {
- .flags = IORESOURCE_MEM,
- .start = DDR_OPERATION_BASE,
- .end = DDR_OPERATION_BASE + 3,
- },
-};
-
-static struct platform_device kirkwood_cpuidle = {
- .name = "kirkwood_cpuidle",
- .id = -1,
- .resource = kirkwood_cpuidle_resource,
- .num_resources = 1,
-};
-
-static void __init kirkwood_cpuidle_init(void)
-{
- platform_device_register(&kirkwood_cpuidle);
-}
-
-/* Temporary here since mach-mvebu has a function we can use */
-static void kirkwood_restart(enum reboot_mode mode, const char *cmd)
-{
- /*
- * Enable soft reset to assert RSTOUTn.
- */
- writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
- /*
- * Assert soft reset.
- */
- writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
- while (1)
- ;
-}
-
-#define MV643XX_ETH_MAC_ADDR_LOW 0x0414
-#define MV643XX_ETH_MAC_ADDR_HIGH 0x0418
-
-static void __init kirkwood_dt_eth_fixup(void)
-{
- struct device_node *np;
-
- /*
- * The ethernet interfaces forget the MAC address assigned by u-boot
- * if the clocks are turned off. Usually, u-boot on kirkwood boards
- * has no DT support to properly set local-mac-address property.
- * As a workaround, we get the MAC address from mv643xx_eth registers
- * and update the port device node if no valid MAC address is set.
- */
- for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
- struct device_node *pnp = of_get_parent(np);
- struct clk *clk;
- struct property *pmac;
- void __iomem *io;
- u8 *macaddr;
- u32 reg;
-
- if (!pnp)
- continue;
-
- /* skip disabled nodes or nodes with valid MAC address*/
- if (!of_device_is_available(pnp) || of_get_mac_address(np))
- goto eth_fixup_skip;
-
- clk = of_clk_get(pnp, 0);
- if (IS_ERR(clk))
- goto eth_fixup_skip;
-
- io = of_iomap(pnp, 0);
- if (!io)
- goto eth_fixup_no_map;
-
- /* ensure port clock is not gated to not hang CPU */
- clk_prepare_enable(clk);
-
- /* store MAC address register contents in local-mac-address */
- pr_err(FW_INFO "%s: local-mac-address is not set\n",
- np->full_name);
-
- pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
- if (!pmac)
- goto eth_fixup_no_mem;
-
- pmac->value = pmac + 1;
- pmac->length = 6;
- pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
- if (!pmac->name) {
- kfree(pmac);
- goto eth_fixup_no_mem;
- }
-
- macaddr = pmac->value;
- reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
- macaddr[0] = (reg >> 24) & 0xff;
- macaddr[1] = (reg >> 16) & 0xff;
- macaddr[2] = (reg >> 8) & 0xff;
- macaddr[3] = reg & 0xff;
-
- reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
- macaddr[4] = (reg >> 8) & 0xff;
- macaddr[5] = reg & 0xff;
-
- of_update_property(np, pmac);
-
-eth_fixup_no_mem:
- iounmap(io);
- clk_disable_unprepare(clk);
-eth_fixup_no_map:
- clk_put(clk);
-eth_fixup_skip:
- of_node_put(pnp);
- }
-}
-
-/*
- * Disable propagation of mbus errors to the CPU local bus, as this
- * causes mbus errors (which can occur for example for PCI aborts) to
- * throw CPU aborts, which we're not set up to deal with.
- */
-static void __init kirkwood_disable_mbus_error_propagation(void)
-{
- void __iomem *cpu_config;
-
- cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
- writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
- iounmap(cpu_config);
-}
-
-static void __init kirkwood_dt_init(void)
-{
- kirkwood_disable_mbus_error_propagation();
-
- BUG_ON(mvebu_mbus_dt_init(false));
-
-#ifdef CONFIG_CACHE_FEROCEON_L2
- feroceon_of_init();
-#endif
- kirkwood_cpufreq_init();
- kirkwood_cpuidle_init();
-
- kirkwood_pm_init();
- kirkwood_dt_eth_fixup();
-
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const kirkwood_dt_board_compat[] = {
- "marvell,kirkwood",
- NULL
-};
-
-DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
- /* Maintainer: Jason Cooper <jason@lakedaemon.net> */
- .map_io = kirkwood_map_io,
- .init_machine = kirkwood_dt_init,
- .restart = kirkwood_restart,
- .dt_compat = kirkwood_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
deleted file mode 100644
index 255f33a3903c..000000000000
--- a/arch/arm/mach-kirkwood/common.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/common.c
- *
- * Core functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/ata_platform.h>
-#include <linux/mtd/nand.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk-provider.h>
-#include <linux/spinlock.h>
-#include <linux/mv643xx_i2c.h>
-#include <linux/timex.h>
-#include <linux/kexec.h>
-#include <linux/reboot.h>
-#include <net/dsa.h>
-#include <asm/page.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <asm/hardware/cache-feroceon-l2.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
-#include <linux/platform_data/asoc-kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include <linux/platform_data/mtd-orion_nand.h>
-#include <linux/platform_data/usb-ehci-orion.h>
-#include <plat/common.h>
-#include <plat/time.h>
-#include <linux/platform_data/dma-mv_xor.h>
-#include "common.h"
-#include "pm.h"
-
-/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
-#define KIRKWOOD_MBUS_NAND_TARGET 0x01
-#define KIRKWOOD_MBUS_NAND_ATTR 0x2f
-#define KIRKWOOD_MBUS_SRAM_TARGET 0x03
-#define KIRKWOOD_MBUS_SRAM_ATTR 0x01
-
-/*****************************************************************************
- * I/O Address Mapping
- ****************************************************************************/
-static struct map_desc kirkwood_io_desc[] __initdata = {
- {
- .virtual = (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
- .pfn = __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
- .length = KIRKWOOD_REGS_SIZE,
- .type = MT_DEVICE,
- },
-};
-
-void __init kirkwood_map_io(void)
-{
- iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
-}
-
-/*****************************************************************************
- * CLK tree
- ****************************************************************************/
-
-static void enable_sata0(void)
-{
- /* Enable PLL and IVREF */
- writel(readl(SATA0_PHY_MODE_2) | 0xf, SATA0_PHY_MODE_2);
- /* Enable PHY */
- writel(readl(SATA0_IF_CTRL) & ~0x200, SATA0_IF_CTRL);
-}
-
-static void disable_sata0(void)
-{
- /* Disable PLL and IVREF */
- writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
- /* Disable PHY */
- writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
-}
-
-static void enable_sata1(void)
-{
- /* Enable PLL and IVREF */
- writel(readl(SATA1_PHY_MODE_2) | 0xf, SATA1_PHY_MODE_2);
- /* Enable PHY */
- writel(readl(SATA1_IF_CTRL) & ~0x200, SATA1_IF_CTRL);
-}
-
-static void disable_sata1(void)
-{
- /* Disable PLL and IVREF */
- writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
- /* Disable PHY */
- writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
-}
-
-static void disable_pcie0(void)
-{
- writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
- while (1)
- if (readl(PCIE_STATUS) & 0x1)
- break;
- writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
-}
-
-static void disable_pcie1(void)
-{
- u32 dev, rev;
-
- kirkwood_pcie_id(&dev, &rev);
-
- if (dev == MV88F6282_DEV_ID) {
- writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
- while (1)
- if (readl(PCIE1_STATUS) & 0x1)
- break;
- writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
- }
-}
-
-/* An extended version of the gated clk. This calls fn_en()/fn_dis
- * before enabling/disabling the clock. We use this to turn on/off
- * PHYs etc. */
-struct clk_gate_fn {
- struct clk_gate gate;
- void (*fn_en)(void);
- void (*fn_dis)(void);
-};
-
-#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
-#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
-
-static int clk_gate_fn_enable(struct clk_hw *hw)
-{
- struct clk_gate *gate = to_clk_gate(hw);
- struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
- int ret;
-
- ret = clk_gate_ops.enable(hw);
- if (!ret && gate_fn->fn_en)
- gate_fn->fn_en();
-
- return ret;
-}
-
-static void clk_gate_fn_disable(struct clk_hw *hw)
-{
- struct clk_gate *gate = to_clk_gate(hw);
- struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
-
- if (gate_fn->fn_dis)
- gate_fn->fn_dis();
-
- clk_gate_ops.disable(hw);
-}
-
-static struct clk_ops clk_gate_fn_ops;
-
-static struct clk __init *clk_register_gate_fn(struct device *dev,
- const char *name,
- const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 bit_idx,
- u8 clk_gate_flags, spinlock_t *lock,
- void (*fn_en)(void), void (*fn_dis)(void))
-{
- struct clk_gate_fn *gate_fn;
- struct clk *clk;
- struct clk_init_data init;
-
- gate_fn = kzalloc(sizeof(struct clk_gate_fn), GFP_KERNEL);
- if (!gate_fn) {
- pr_err("%s: could not allocate gated clk\n", __func__);
- return ERR_PTR(-ENOMEM);
- }
-
- init.name = name;
- init.ops = &clk_gate_fn_ops;
- init.flags = flags;
- init.parent_names = (parent_name ? &parent_name : NULL);
- init.num_parents = (parent_name ? 1 : 0);
-
- /* struct clk_gate assignments */
- gate_fn->gate.reg = reg;
- gate_fn->gate.bit_idx = bit_idx;
- gate_fn->gate.flags = clk_gate_flags;
- gate_fn->gate.lock = lock;
- gate_fn->gate.hw.init = &init;
- gate_fn->fn_en = fn_en;
- gate_fn->fn_dis = fn_dis;
-
- /* ops is the gate ops, but with our enable/disable functions */
- if (clk_gate_fn_ops.enable != clk_gate_fn_enable ||
- clk_gate_fn_ops.disable != clk_gate_fn_disable) {
- clk_gate_fn_ops = clk_gate_ops;
- clk_gate_fn_ops.enable = clk_gate_fn_enable;
- clk_gate_fn_ops.disable = clk_gate_fn_disable;
- }
-
- clk = clk_register(dev, &gate_fn->gate.hw);
-
- if (IS_ERR(clk))
- kfree(gate_fn);
-
- return clk;
-}
-
-static DEFINE_SPINLOCK(gating_lock);
-static struct clk *tclk;
-
-static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
-{
- return clk_register_gate(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
- bit_idx, 0, &gating_lock);
-}
-
-static struct clk __init *kirkwood_register_gate_fn(const char *name,
- u8 bit_idx,
- void (*fn_en)(void),
- void (*fn_dis)(void))
-{
- return clk_register_gate_fn(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
- bit_idx, 0, &gating_lock, fn_en, fn_dis);
-}
-
-static struct clk *ge0, *ge1;
-
-void __init kirkwood_clk_init(void)
-{
- struct clk *runit, *sata0, *sata1, *usb0, *sdio;
- struct clk *crypto, *xor0, *xor1, *pex0, *pex1, *audio;
-
- tclk = clk_register_fixed_rate(NULL, "tclk", NULL,
- CLK_IS_ROOT, kirkwood_tclk);
-
- runit = kirkwood_register_gate("runit", CGC_BIT_RUNIT);
- ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0);
- ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1);
- sata0 = kirkwood_register_gate_fn("sata0", CGC_BIT_SATA0,
- enable_sata0, disable_sata0);
- sata1 = kirkwood_register_gate_fn("sata1", CGC_BIT_SATA1,
- enable_sata1, disable_sata1);
- usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0);
- sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO);
- crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
- xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0);
- xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1);
- pex0 = kirkwood_register_gate_fn("pex0", CGC_BIT_PEX0,
- NULL, disable_pcie0);
- pex1 = kirkwood_register_gate_fn("pex1", CGC_BIT_PEX1,
- NULL, disable_pcie1);
- audio = kirkwood_register_gate("audio", CGC_BIT_AUDIO);
- kirkwood_register_gate("tdm", CGC_BIT_TDM);
- kirkwood_register_gate("tsu", CGC_BIT_TSU);
-
- /* clkdev entries, mapping clks to devices */
- orion_clkdev_add(NULL, "orion_spi.0", runit);
- orion_clkdev_add(NULL, "orion_spi.1", runit);
- orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", ge0);
- orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", ge1);
- orion_clkdev_add(NULL, "orion_wdt", tclk);
- orion_clkdev_add("0", "sata_mv.0", sata0);
- orion_clkdev_add("1", "sata_mv.0", sata1);
- orion_clkdev_add(NULL, "orion-ehci.0", usb0);
- orion_clkdev_add(NULL, "orion_nand", runit);
- orion_clkdev_add(NULL, "mvsdio", sdio);
- orion_clkdev_add(NULL, "mv_crypto", crypto);
- orion_clkdev_add(NULL, MV_XOR_NAME ".0", xor0);
- orion_clkdev_add(NULL, MV_XOR_NAME ".1", xor1);
- orion_clkdev_add("0", "pcie", pex0);
- orion_clkdev_add("1", "pcie", pex1);
- orion_clkdev_add(NULL, "mvebu-audio", audio);
- orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
- orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".1", runit);
-
- /* Marvell says runit is used by SPI, UART, NAND, TWSI, ...,
- * so should never be gated.
- */
- clk_prepare_enable(runit);
-}
-
-/*****************************************************************************
- * EHCI0
- ****************************************************************************/
-void __init kirkwood_ehci_init(void)
-{
- orion_ehci_init(USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
-}
-
-
-/*****************************************************************************
- * GE00
- ****************************************************************************/
-void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
-{
- orion_ge00_init(eth_data,
- GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
- IRQ_KIRKWOOD_GE00_ERR, 1600);
- /* The interface forgets the MAC address assigned by u-boot if
- the clock is turned off, so claim the clk now. */
- clk_prepare_enable(ge0);
-}
-
-
-/*****************************************************************************
- * GE01
- ****************************************************************************/
-void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
-{
- orion_ge01_init(eth_data,
- GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
- IRQ_KIRKWOOD_GE01_ERR, 1600);
- clk_prepare_enable(ge1);
-}
-
-
-/*****************************************************************************
- * Ethernet switch
- ****************************************************************************/
-void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq)
-{
- orion_ge00_switch_init(d, irq);
-}
-
-
-/*****************************************************************************
- * NAND flash
- ****************************************************************************/
-static struct resource kirkwood_nand_resource = {
- .flags = IORESOURCE_MEM,
- .start = KIRKWOOD_NAND_MEM_PHYS_BASE,
- .end = KIRKWOOD_NAND_MEM_PHYS_BASE +
- KIRKWOOD_NAND_MEM_SIZE - 1,
-};
-
-static struct orion_nand_data kirkwood_nand_data = {
- .cle = 0,
- .ale = 1,
- .width = 8,
-};
-
-static struct platform_device kirkwood_nand_flash = {
- .name = "orion_nand",
- .id = -1,
- .dev = {
- .platform_data = &kirkwood_nand_data,
- },
- .resource = &kirkwood_nand_resource,
- .num_resources = 1,
-};
-
-void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
- int chip_delay)
-{
- kirkwood_nand_data.parts = parts;
- kirkwood_nand_data.nr_parts = nr_parts;
- kirkwood_nand_data.chip_delay = chip_delay;
- platform_device_register(&kirkwood_nand_flash);
-}
-
-void __init kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
- int (*dev_ready)(struct mtd_info *))
-{
- kirkwood_nand_data.parts = parts;
- kirkwood_nand_data.nr_parts = nr_parts;
- kirkwood_nand_data.dev_ready = dev_ready;
- platform_device_register(&kirkwood_nand_flash);
-}
-
-/*****************************************************************************
- * SoC RTC
- ****************************************************************************/
-static void __init kirkwood_rtc_init(void)
-{
- orion_rtc_init(RTC_PHYS_BASE, IRQ_KIRKWOOD_RTC);
-}
-
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
-{
- orion_sata_init(sata_data, SATA_PHYS_BASE, IRQ_KIRKWOOD_SATA);
-}
-
-
-/*****************************************************************************
- * SD/SDIO/MMC
- ****************************************************************************/
-static struct resource mvsdio_resources[] = {
- [0] = {
- .start = SDIO_PHYS_BASE,
- .end = SDIO_PHYS_BASE + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_KIRKWOOD_SDIO,
- .end = IRQ_KIRKWOOD_SDIO,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 mvsdio_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device kirkwood_sdio = {
- .name = "mvsdio",
- .id = -1,
- .dev = {
- .dma_mask = &mvsdio_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
- .num_resources = ARRAY_SIZE(mvsdio_resources),
- .resource = mvsdio_resources,
-};
-
-void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
-{
- u32 dev, rev;
-
- kirkwood_pcie_id(&dev, &rev);
- if (rev == 0 && dev != MV88F6282_DEV_ID) /* catch all Kirkwood Z0's */
- mvsdio_data->clock = 100000000;
- else
- mvsdio_data->clock = 200000000;
- kirkwood_sdio.dev.platform_data = mvsdio_data;
- platform_device_register(&kirkwood_sdio);
-}
-
-
-/*****************************************************************************
- * SPI
- ****************************************************************************/
-void __init kirkwood_spi_init(void)
-{
- orion_spi_init(SPI_PHYS_BASE);
-}
-
-
-/*****************************************************************************
- * I2C
- ****************************************************************************/
-void __init kirkwood_i2c_init(void)
-{
- orion_i2c_init(I2C_PHYS_BASE, IRQ_KIRKWOOD_TWSI, 8);
-}
-
-
-/*****************************************************************************
- * UART0
- ****************************************************************************/
-
-void __init kirkwood_uart0_init(void)
-{
- orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
- IRQ_KIRKWOOD_UART_0, tclk);
-}
-
-
-/*****************************************************************************
- * UART1
- ****************************************************************************/
-void __init kirkwood_uart1_init(void)
-{
- orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
- IRQ_KIRKWOOD_UART_1, tclk);
-}
-
-/*****************************************************************************
- * Cryptographic Engines and Security Accelerator (CESA)
- ****************************************************************************/
-void __init kirkwood_crypto_init(void)
-{
- orion_crypto_init(CRYPTO_PHYS_BASE, KIRKWOOD_SRAM_PHYS_BASE,
- KIRKWOOD_SRAM_SIZE, IRQ_KIRKWOOD_CRYPTO);
-}
-
-
-/*****************************************************************************
- * XOR0
- ****************************************************************************/
-void __init kirkwood_xor0_init(void)
-{
- orion_xor0_init(XOR0_PHYS_BASE, XOR0_HIGH_PHYS_BASE,
- IRQ_KIRKWOOD_XOR_00, IRQ_KIRKWOOD_XOR_01);
-}
-
-
-/*****************************************************************************
- * XOR1
- ****************************************************************************/
-void __init kirkwood_xor1_init(void)
-{
- orion_xor1_init(XOR1_PHYS_BASE, XOR1_HIGH_PHYS_BASE,
- IRQ_KIRKWOOD_XOR_10, IRQ_KIRKWOOD_XOR_11);
-}
-
-
-/*****************************************************************************
- * Watchdog
- ****************************************************************************/
-void __init kirkwood_wdt_init(void)
-{
- orion_wdt_init();
-}
-
-/*****************************************************************************
- * CPU idle
- ****************************************************************************/
-static struct resource kirkwood_cpuidle_resource[] = {
- {
- .flags = IORESOURCE_MEM,
- .start = DDR_OPERATION_BASE,
- .end = DDR_OPERATION_BASE + 3,
- },
-};
-
-static struct platform_device kirkwood_cpuidle = {
- .name = "kirkwood_cpuidle",
- .id = -1,
- .resource = kirkwood_cpuidle_resource,
- .num_resources = 1,
-};
-
-void __init kirkwood_cpuidle_init(void)
-{
- platform_device_register(&kirkwood_cpuidle);
-}
-
-/*****************************************************************************
- * Time handling
- ****************************************************************************/
-void __init kirkwood_init_early(void)
-{
- orion_time_set_base(TIMER_VIRT_BASE);
-}
-
-int kirkwood_tclk;
-
-static int __init kirkwood_find_tclk(void)
-{
- u32 dev, rev;
-
- kirkwood_pcie_id(&dev, &rev);
-
- if (dev == MV88F6281_DEV_ID || dev == MV88F6282_DEV_ID)
- if (((readl(SAMPLE_AT_RESET) >> 21) & 1) == 0)
- return 200000000;
-
- return 166666667;
-}
-
-void __init kirkwood_timer_init(void)
-{
- kirkwood_tclk = kirkwood_find_tclk();
-
- orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
- IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
-}
-
-/*****************************************************************************
- * Audio
- ****************************************************************************/
-static struct resource kirkwood_audio_resources[] = {
- [0] = {
- .start = AUDIO_PHYS_BASE,
- .end = AUDIO_PHYS_BASE + SZ_16K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_KIRKWOOD_I2S,
- .end = IRQ_KIRKWOOD_I2S,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct kirkwood_asoc_platform_data kirkwood_audio_data = {
- .burst = 128,
-};
-
-static struct platform_device kirkwood_audio_device = {
- .name = "mvebu-audio",
- .id = -1,
- .num_resources = ARRAY_SIZE(kirkwood_audio_resources),
- .resource = kirkwood_audio_resources,
- .dev = {
- .platform_data = &kirkwood_audio_data,
- },
-};
-
-void __init kirkwood_audio_init(void)
-{
- platform_device_register(&kirkwood_audio_device);
-}
-
-/*****************************************************************************
- * CPU Frequency
- ****************************************************************************/
-static struct resource kirkwood_cpufreq_resources[] = {
- [0] = {
- .start = CPU_CONTROL_PHYS,
- .end = CPU_CONTROL_PHYS + 3,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device kirkwood_cpufreq_device = {
- .name = "kirkwood-cpufreq",
- .id = -1,
- .num_resources = ARRAY_SIZE(kirkwood_cpufreq_resources),
- .resource = kirkwood_cpufreq_resources,
-};
-
-void __init kirkwood_cpufreq_init(void)
-{
- platform_device_register(&kirkwood_cpufreq_device);
-}
-
-/*****************************************************************************
- * General
- ****************************************************************************/
-/*
- * Identify device ID and revision.
- */
-char * __init kirkwood_id(void)
-{
- u32 dev, rev;
-
- kirkwood_pcie_id(&dev, &rev);
-
- if (dev == MV88F6281_DEV_ID) {
- if (rev == MV88F6281_REV_Z0)
- return "MV88F6281-Z0";
- else if (rev == MV88F6281_REV_A0)
- return "MV88F6281-A0";
- else if (rev == MV88F6281_REV_A1)
- return "MV88F6281-A1";
- else
- return "MV88F6281-Rev-Unsupported";
- } else if (dev == MV88F6192_DEV_ID) {
- if (rev == MV88F6192_REV_Z0)
- return "MV88F6192-Z0";
- else if (rev == MV88F6192_REV_A0)
- return "MV88F6192-A0";
- else if (rev == MV88F6192_REV_A1)
- return "MV88F6192-A1";
- else
- return "MV88F6192-Rev-Unsupported";
- } else if (dev == MV88F6180_DEV_ID) {
- if (rev == MV88F6180_REV_A0)
- return "MV88F6180-Rev-A0";
- else if (rev == MV88F6180_REV_A1)
- return "MV88F6180-Rev-A1";
- else
- return "MV88F6180-Rev-Unsupported";
- } else if (dev == MV88F6282_DEV_ID) {
- if (rev == MV88F6282_REV_A0)
- return "MV88F6282-Rev-A0";
- else if (rev == MV88F6282_REV_A1)
- return "MV88F6282-Rev-A1";
- else
- return "MV88F6282-Rev-Unsupported";
- } else {
- return "Device-Unknown";
- }
-}
-
-void __init kirkwood_setup_wins(void)
-{
- mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_NAND_TARGET,
- KIRKWOOD_MBUS_NAND_ATTR,
- KIRKWOOD_NAND_MEM_PHYS_BASE,
- KIRKWOOD_NAND_MEM_SIZE);
- mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_SRAM_TARGET,
- KIRKWOOD_MBUS_SRAM_ATTR,
- KIRKWOOD_SRAM_PHYS_BASE,
- KIRKWOOD_SRAM_SIZE);
-}
-
-void __init kirkwood_l2_init(void)
-{
-#ifdef CONFIG_CACHE_FEROCEON_L2
-#ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
- writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG);
- feroceon_l2_init(1);
-#else
- writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG);
- feroceon_l2_init(0);
-#endif
-#endif
-}
-
-void __init kirkwood_init(void)
-{
- pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
-
- /*
- * Disable propagation of mbus errors to the CPU local bus,
- * as this causes mbus errors (which can occur for example
- * for PCI aborts) to throw CPU aborts, which we're not set
- * up to deal with.
- */
- writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
-
- BUG_ON(mvebu_mbus_init("marvell,kirkwood-mbus",
- BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
- DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ));
-
- kirkwood_setup_wins();
-
- kirkwood_l2_init();
-
- /* Setup root of clk tree */
- kirkwood_clk_init();
-
- /* internal devices that every board has */
- kirkwood_rtc_init();
- kirkwood_wdt_init();
- kirkwood_xor0_init();
- kirkwood_xor1_init();
- kirkwood_crypto_init();
-
- kirkwood_pm_init();
- kirkwood_cpuidle_init();
-#ifdef CONFIG_KEXEC
- kexec_reinit = kirkwood_enable_pcie;
-#endif
-}
-
-void kirkwood_restart(enum reboot_mode mode, const char *cmd)
-{
- /*
- * Enable soft reset to assert RSTOUTn.
- */
- writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
-
- /*
- * Assert soft reset.
- */
- writel(SOFT_RESET, SYSTEM_SOFT_RESET);
-
- while (1)
- ;
-}
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
deleted file mode 100644
index 832a4e2ab8d7..000000000000
--- a/arch/arm/mach-kirkwood/common.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/common.h
- *
- * Core functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ARCH_KIRKWOOD_COMMON_H
-#define __ARCH_KIRKWOOD_COMMON_H
-
-#include <linux/reboot.h>
-
-struct dsa_platform_data;
-struct mv643xx_eth_platform_data;
-struct mv_sata_platform_data;
-struct mvsdio_platform_data;
-struct mtd_partition;
-struct mtd_info;
-struct kirkwood_asoc_platform_data;
-
-#define KW_PCIE0 (1 << 0)
-#define KW_PCIE1 (1 << 1)
-
-/*
- * Basic Kirkwood init functions used early by machine-setup.
- */
-void kirkwood_map_io(void);
-void kirkwood_init(void);
-void kirkwood_init_early(void);
-void kirkwood_init_irq(void);
-
-void kirkwood_setup_wins(void);
-
-void kirkwood_enable_pcie(void);
-void kirkwood_pcie_id(u32 *dev, u32 *rev);
-
-void kirkwood_ehci_init(void);
-void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data);
-void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data);
-void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
-void kirkwood_pcie_init(unsigned int portmask);
-void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
-void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
-void kirkwood_spi_init(void);
-void kirkwood_i2c_init(void);
-void kirkwood_uart0_init(void);
-void kirkwood_uart1_init(void);
-void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
-void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
- int (*dev_ready)(struct mtd_info *));
-void kirkwood_audio_init(void);
-void kirkwood_cpuidle_init(void);
-void kirkwood_cpufreq_init(void);
-
-void kirkwood_restart(enum reboot_mode, const char *);
-void kirkwood_clk_init(void);
-
-/* early init functions not converted to fdt yet */
-char *kirkwood_id(void);
-void kirkwood_l2_init(void);
-void kirkwood_wdt_init(void);
-void kirkwood_xor0_init(void);
-void kirkwood_xor1_init(void);
-void kirkwood_crypto_init(void);
-
-extern int kirkwood_tclk;
-extern void kirkwood_timer_init(void);
-
-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
-
-#endif
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
deleted file mode 100644
index 453418063c1e..000000000000
--- a/arch/arm/mach-kirkwood/d2net_v2-setup.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/d2net_v2-setup.c
- *
- * LaCie d2 Network Space v2 Board Setup
- *
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/leds-kirkwood-ns2.h>
-#include "common.h"
-#include "mpp.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data d2net_v2_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-
-static struct mv_sata_platform_data d2net_v2_sata_data = {
- .n_ports = 2,
-};
-
-/*****************************************************************************
- * GPIO keys
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_PUSH_BUTTON 34
-#define D2NET_V2_GPIO_POWER_SWITCH_ON 13
-#define D2NET_V2_GPIO_POWER_SWITCH_OFF 15
-
-#define D2NET_V2_SWITCH_POWER_ON 0x1
-#define D2NET_V2_SWITCH_POWER_OFF 0x2
-
-static struct gpio_keys_button d2net_v2_buttons[] = {
- [0] = {
- .type = EV_SW,
- .code = D2NET_V2_SWITCH_POWER_ON,
- .gpio = D2NET_V2_GPIO_POWER_SWITCH_ON,
- .desc = "Back power switch (on|auto)",
- .active_low = 0,
- },
- [1] = {
- .type = EV_SW,
- .code = D2NET_V2_SWITCH_POWER_OFF,
- .gpio = D2NET_V2_GPIO_POWER_SWITCH_OFF,
- .desc = "Back power switch (auto|off)",
- .active_low = 0,
- },
- [2] = {
- .code = KEY_POWER,
- .gpio = D2NET_V2_GPIO_PUSH_BUTTON,
- .desc = "Front Push Button",
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data d2net_v2_button_data = {
- .buttons = d2net_v2_buttons,
- .nbuttons = ARRAY_SIZE(d2net_v2_buttons),
-};
-
-static struct platform_device d2net_v2_gpio_buttons = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &d2net_v2_button_data,
- },
-};
-
-/*****************************************************************************
- * GPIO LEDs
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_RED_LED 12
-
-static struct gpio_led d2net_v2_gpio_led_pins[] = {
- {
- .name = "d2net_v2:red:fail",
- .gpio = D2NET_V2_GPIO_RED_LED,
- },
-};
-
-static struct gpio_led_platform_data d2net_v2_gpio_leds_data = {
- .num_leds = ARRAY_SIZE(d2net_v2_gpio_led_pins),
- .leds = d2net_v2_gpio_led_pins,
-};
-
-static struct platform_device d2net_v2_gpio_leds = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &d2net_v2_gpio_leds_data,
- },
-};
-
-/*****************************************************************************
- * Dual-GPIO CPLD LEDs
- ****************************************************************************/
-
-#define D2NET_V2_GPIO_BLUE_LED_SLOW 29
-#define D2NET_V2_GPIO_BLUE_LED_CMD 30
-
-static struct ns2_led d2net_v2_led_pins[] = {
- {
- .name = "d2net_v2:blue:sata",
- .cmd = D2NET_V2_GPIO_BLUE_LED_CMD,
- .slow = D2NET_V2_GPIO_BLUE_LED_SLOW,
- },
-};
-
-static struct ns2_led_platform_data d2net_v2_leds_data = {
- .num_leds = ARRAY_SIZE(d2net_v2_led_pins),
- .leds = d2net_v2_led_pins,
-};
-
-static struct platform_device d2net_v2_leds = {
- .name = "leds-ns2",
- .id = -1,
- .dev = {
- .platform_data = &d2net_v2_leds_data,
- },
-};
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-
-static unsigned int d2net_v2_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP6_SYSRST_OUTn,
- MPP7_GPO, /* Request power-off */
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP12_GPO, /* Red led */
- MPP13_GPIO, /* Rear power switch (on|auto) */
- MPP14_GPIO, /* USB fuse */
- MPP15_GPIO, /* Rear power switch (auto|off) */
- MPP16_GPIO, /* SATA 0 power */
- MPP21_SATA0_ACTn,
- MPP24_GPIO, /* USB mode select */
- MPP26_GPIO, /* USB device vbus */
- MPP28_GPIO, /* USB enable host vbus */
- MPP29_GPIO, /* Blue led (slow register) */
- MPP30_GPIO, /* Blue led (command register) */
- MPP34_GPIO, /* Power button (1 = Released, 0 = Pushed) */
- MPP35_GPIO, /* Inhibit power-off */
- 0
-};
-
-#define D2NET_V2_GPIO_POWER_OFF 7
-
-static void d2net_v2_power_off(void)
-{
- gpio_set_value(D2NET_V2_GPIO_POWER_OFF, 1);
-}
-
-static void __init d2net_v2_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(d2net_v2_mpp_config);
-
- lacie_v2_hdd_power_init(1);
-
- kirkwood_ehci_init();
- kirkwood_ge00_init(&d2net_v2_ge00_data);
- kirkwood_sata_init(&d2net_v2_sata_data);
- kirkwood_uart0_init();
- lacie_v2_register_flash();
- lacie_v2_register_i2c_devices();
-
- platform_device_register(&d2net_v2_leds);
- platform_device_register(&d2net_v2_gpio_leds);
- platform_device_register(&d2net_v2_gpio_buttons);
-
- if (gpio_request(D2NET_V2_GPIO_POWER_OFF, "power-off") == 0 &&
- gpio_direction_output(D2NET_V2_GPIO_POWER_OFF, 0) == 0)
- pm_power_off = d2net_v2_power_off;
- else
- pr_err("d2net_v2: failed to configure power-off GPIO\n");
-}
-
-MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
- .atag_offset = 0x100,
- .init_machine = d2net_v2_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
deleted file mode 100644
index 1c37082c8b39..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/bridge-regs.h
- *
- * Mbus-L to Mbus Bridge Registers
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_BRIDGE_REGS_H
-#define __ASM_ARCH_BRIDGE_REGS_H
-
-#include <mach/kirkwood.h>
-
-#define CPU_CONFIG (BRIDGE_VIRT_BASE + 0x0100)
-#define CPU_CONFIG_PHYS (BRIDGE_PHYS_BASE + 0x0100)
-#define CPU_CONFIG_ERROR_PROP 0x00000004
-
-#define CPU_CONTROL (BRIDGE_VIRT_BASE + 0x0104)
-#define CPU_CONTROL_PHYS (BRIDGE_PHYS_BASE + 0x0104)
-#define CPU_RESET 0x00000002
-
-#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
-#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
-#define SOFT_RESET_OUT_EN 0x00000004
-
-#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
-#define SOFT_RESET 0x00000001
-
-#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE + 0x0110)
-
-#define BRIDGE_INT_TIMER1_CLR (~0x0004)
-
-#define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE + 0x0200)
-#define IRQ_CAUSE_LOW_OFF 0x0000
-#define IRQ_MASK_LOW_OFF 0x0004
-#define IRQ_CAUSE_HIGH_OFF 0x0010
-#define IRQ_MASK_HIGH_OFF 0x0014
-
-#define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE + 0x0300)
-#define TIMER_PHYS_BASE (BRIDGE_PHYS_BASE + 0x0300)
-
-#define L2_CONFIG_REG (BRIDGE_VIRT_BASE + 0x0128)
-#define L2_WRITETHROUGH 0x00000010
-
-#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE + 0x11c)
-#define CGC_BIT_GE0 (0)
-#define CGC_BIT_PEX0 (2)
-#define CGC_BIT_USB0 (3)
-#define CGC_BIT_SDIO (4)
-#define CGC_BIT_TSU (5)
-#define CGC_BIT_DUNIT (6)
-#define CGC_BIT_RUNIT (7)
-#define CGC_BIT_XOR0 (8)
-#define CGC_BIT_AUDIO (9)
-#define CGC_BIT_SATA0 (14)
-#define CGC_BIT_SATA1 (15)
-#define CGC_BIT_XOR1 (16)
-#define CGC_BIT_CRYPTO (17)
-#define CGC_BIT_PEX1 (18)
-#define CGC_BIT_GE1 (19)
-#define CGC_BIT_TDM (20)
-#define CGC_GE0 (1 << 0)
-#define CGC_PEX0 (1 << 2)
-#define CGC_USB0 (1 << 3)
-#define CGC_SDIO (1 << 4)
-#define CGC_TSU (1 << 5)
-#define CGC_DUNIT (1 << 6)
-#define CGC_RUNIT (1 << 7)
-#define CGC_XOR0 (1 << 8)
-#define CGC_AUDIO (1 << 9)
-#define CGC_POWERSAVE (1 << 11)
-#define CGC_SATA0 (1 << 14)
-#define CGC_SATA1 (1 << 15)
-#define CGC_XOR1 (1 << 16)
-#define CGC_CRYPTO (1 << 17)
-#define CGC_PEX1 (1 << 18)
-#define CGC_GE1 (1 << 19)
-#define CGC_TDM (1 << 20)
-#define CGC_RESERVED (0x6 << 21)
-
-#define MEMORY_PM_CTRL (BRIDGE_VIRT_BASE + 0x118)
-#define MEMORY_PM_CTRL_PHYS (BRIDGE_PHYS_BASE + 0x118)
-
-#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/entry-macro.S b/arch/arm/mach-kirkwood/include/mach/entry-macro.S
deleted file mode 100644
index 82db29f7af8f..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/entry-macro.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Marvell Kirkwood platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/bridge-regs.h>
-
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =IRQ_VIRT_BASE
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- @ check low interrupts
- ldr \irqstat, [\base, #IRQ_CAUSE_LOW_OFF]
- ldr \tmp, [\base, #IRQ_MASK_LOW_OFF]
- mov \irqnr, #31
- ands \irqstat, \irqstat, \tmp
- bne 1001f
-
- @ if no low interrupts set, check high interrupts
- ldr \irqstat, [\base, #IRQ_CAUSE_HIGH_OFF]
- ldr \tmp, [\base, #IRQ_MASK_HIGH_OFF]
- mov \irqnr, #63
- ands \irqstat, \irqstat, \tmp
-
- @ find first active interrupt source
-1001: clzne \irqstat, \irqstat
- subne \irqnr, \irqnr, \irqstat
- .endm
diff --git a/arch/arm/mach-kirkwood/include/mach/irqs.h b/arch/arm/mach-kirkwood/include/mach/irqs.h
deleted file mode 100644
index 2bf8161e3b51..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/irqs.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/irqs.h
- *
- * IRQ definitions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-/*
- * Low Interrupt Controller
- */
-#define IRQ_KIRKWOOD_HIGH_SUM 0
-#define IRQ_KIRKWOOD_BRIDGE 1
-#define IRQ_KIRKWOOD_HOST2CPU 2
-#define IRQ_KIRKWOOD_CPU2HOST 3
-#define IRQ_KIRKWOOD_XOR_00 5
-#define IRQ_KIRKWOOD_XOR_01 6
-#define IRQ_KIRKWOOD_XOR_10 7
-#define IRQ_KIRKWOOD_XOR_11 8
-#define IRQ_KIRKWOOD_PCIE 9
-#define IRQ_KIRKWOOD_PCIE1 10
-#define IRQ_KIRKWOOD_GE00_SUM 11
-#define IRQ_KIRKWOOD_GE01_SUM 15
-#define IRQ_KIRKWOOD_USB 19
-#define IRQ_KIRKWOOD_SATA 21
-#define IRQ_KIRKWOOD_CRYPTO 22
-#define IRQ_KIRKWOOD_SPI 23
-#define IRQ_KIRKWOOD_I2S 24
-#define IRQ_KIRKWOOD_TS_0 26
-#define IRQ_KIRKWOOD_SDIO 28
-#define IRQ_KIRKWOOD_TWSI 29
-#define IRQ_KIRKWOOD_AVB 30
-#define IRQ_KIRKWOOD_TDMI 31
-
-/*
- * High Interrupt Controller
- */
-#define IRQ_KIRKWOOD_UART_0 33
-#define IRQ_KIRKWOOD_UART_1 34
-#define IRQ_KIRKWOOD_GPIO_LOW_0_7 35
-#define IRQ_KIRKWOOD_GPIO_LOW_8_15 36
-#define IRQ_KIRKWOOD_GPIO_LOW_16_23 37
-#define IRQ_KIRKWOOD_GPIO_LOW_24_31 38
-#define IRQ_KIRKWOOD_GPIO_HIGH_0_7 39
-#define IRQ_KIRKWOOD_GPIO_HIGH_8_15 40
-#define IRQ_KIRKWOOD_GPIO_HIGH_16_23 41
-#define IRQ_KIRKWOOD_GE00_ERR 46
-#define IRQ_KIRKWOOD_GE01_ERR 47
-#define IRQ_KIRKWOOD_RTC 53
-
-/*
- * KIRKWOOD General Purpose Pins
- */
-#define IRQ_KIRKWOOD_GPIO_START 64
-#define NR_GPIO_IRQS 50
-
-#define NR_IRQS (IRQ_KIRKWOOD_GPIO_START + NR_GPIO_IRQS)
-
-
-#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
deleted file mode 100644
index 92976cef3910..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/kirkwood.h
- *
- * Generic definitions for Marvell Kirkwood SoC flavors:
- * 88F6180, 88F6192 and 88F6281.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_KIRKWOOD_H
-#define __ASM_ARCH_KIRKWOOD_H
-
-/*
- * Marvell Kirkwood address maps.
- *
- * phys
- * e0000000 PCIe #0 Memory space
- * e8000000 PCIe #1 Memory space
- * f1000000 on-chip peripheral registers
- * f2000000 PCIe #0 I/O space
- * f3000000 PCIe #1 I/O space
- * f4000000 NAND controller address window
- * f5000000 Security Accelerator SRAM
- *
- * virt phys size
- * fed00000 f1000000 1M on-chip peripheral registers
- * fee00000 f2000000 1M PCIe #0 I/O space
- * fef00000 f3000000 1M PCIe #1 I/O space
- */
-
-#define KIRKWOOD_SRAM_PHYS_BASE 0xf5000000
-#define KIRKWOOD_SRAM_SIZE SZ_2K
-
-#define KIRKWOOD_NAND_MEM_PHYS_BASE 0xf4000000
-#define KIRKWOOD_NAND_MEM_SIZE SZ_1K
-
-#define KIRKWOOD_PCIE1_IO_PHYS_BASE 0xf3000000
-#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00010000
-#define KIRKWOOD_PCIE1_IO_SIZE SZ_64K
-
-#define KIRKWOOD_PCIE_IO_PHYS_BASE 0xf2000000
-#define KIRKWOOD_PCIE_IO_BUS_BASE 0x00000000
-#define KIRKWOOD_PCIE_IO_SIZE SZ_64K
-
-#define KIRKWOOD_REGS_PHYS_BASE 0xf1000000
-#define KIRKWOOD_REGS_VIRT_BASE IOMEM(0xfed00000)
-#define KIRKWOOD_REGS_SIZE SZ_1M
-
-#define KIRKWOOD_PCIE_MEM_PHYS_BASE 0xe0000000
-#define KIRKWOOD_PCIE_MEM_BUS_BASE 0xe0000000
-#define KIRKWOOD_PCIE_MEM_SIZE SZ_128M
-
-#define KIRKWOOD_PCIE1_MEM_PHYS_BASE 0xe8000000
-#define KIRKWOOD_PCIE1_MEM_BUS_BASE 0xe8000000
-#define KIRKWOOD_PCIE1_MEM_SIZE SZ_128M
-
-/*
- * Register Map
- */
-#define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x00000)
-#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000)
-#define DDR_WINDOW_CPU_BASE (DDR_PHYS_BASE + 0x1500)
-#define DDR_WINDOW_CPU_SZ (0x20)
-#define DDR_OPERATION_BASE (DDR_PHYS_BASE + 0x1418)
-
-#define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x10000)
-#define DEV_BUS_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x10000)
-#define SAMPLE_AT_RESET (DEV_BUS_VIRT_BASE + 0x0030)
-#define DEVICE_ID (DEV_BUS_VIRT_BASE + 0x0034)
-#define GPIO_LOW_VIRT_BASE (DEV_BUS_VIRT_BASE + 0x0100)
-#define GPIO_HIGH_VIRT_BASE (DEV_BUS_VIRT_BASE + 0x0140)
-#define RTC_PHYS_BASE (DEV_BUS_PHYS_BASE + 0x0300)
-#define SPI_PHYS_BASE (DEV_BUS_PHYS_BASE + 0x0600)
-#define I2C_PHYS_BASE (DEV_BUS_PHYS_BASE + 0x1000)
-#define UART0_PHYS_BASE (DEV_BUS_PHYS_BASE + 0x2000)
-#define UART0_VIRT_BASE (DEV_BUS_VIRT_BASE + 0x2000)
-#define UART1_PHYS_BASE (DEV_BUS_PHYS_BASE + 0x2100)
-#define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE + 0x2100)
-
-#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x20000)
-#define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x20000)
-#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE)
-#define BRIDGE_WINS_SZ (0x80)
-
-#define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x30000)
-
-#define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x40000)
-#define PCIE_LINK_CTRL (PCIE_VIRT_BASE + 0x70)
-#define PCIE_STATUS (PCIE_VIRT_BASE + 0x1a04)
-#define PCIE1_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x44000)
-#define PCIE1_LINK_CTRL (PCIE1_VIRT_BASE + 0x70)
-#define PCIE1_STATUS (PCIE1_VIRT_BASE + 0x1a04)
-
-#define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x50000)
-
-#define XOR0_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x60800)
-#define XOR0_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x60800)
-#define XOR1_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x60900)
-#define XOR1_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x60900)
-#define XOR0_HIGH_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x60A00)
-#define XOR0_HIGH_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x60A00)
-#define XOR1_HIGH_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x60B00)
-#define XOR1_HIGH_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x60B00)
-
-#define GE00_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x70000)
-#define GE01_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x74000)
-
-#define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x80000)
-#define SATA_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x80000)
-#define SATA0_IF_CTRL (SATA_VIRT_BASE + 0x2050)
-#define SATA0_PHY_MODE_2 (SATA_VIRT_BASE + 0x2330)
-#define SATA1_IF_CTRL (SATA_VIRT_BASE + 0x4050)
-#define SATA1_PHY_MODE_2 (SATA_VIRT_BASE + 0x4330)
-
-#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x90000)
-
-#define AUDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0xA0000)
-#define AUDIO_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0xA0000)
-
-/*
- * Supported devices and revisions.
- */
-#define MV88F6281_DEV_ID 0x6281
-#define MV88F6281_REV_Z0 0
-#define MV88F6281_REV_A0 2
-#define MV88F6281_REV_A1 3
-
-#define MV88F6192_DEV_ID 0x6192
-#define MV88F6192_REV_Z0 0
-#define MV88F6192_REV_A0 2
-#define MV88F6192_REV_A1 3
-
-#define MV88F6180_DEV_ID 0x6180
-#define MV88F6180_REV_A0 2
-#define MV88F6180_REV_A1 3
-
-#define MV88F6282_DEV_ID 0x6282
-#define MV88F6282_REV_A0 0
-#define MV88F6282_REV_A1 1
-#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/uncompress.h b/arch/arm/mach-kirkwood/include/mach/uncompress.h
deleted file mode 100644
index 5bca5534021f..000000000000
--- a/arch/arm/mach-kirkwood/include/mach/uncompress.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/uncompress.h
- *
- * 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/serial_reg.h>
-#include <mach/kirkwood.h>
-
-#define SERIAL_BASE ((unsigned char *)UART0_PHYS_BASE)
-
-static void putc(const char c)
-{
- unsigned char *base = SERIAL_BASE;
- int i;
-
- for (i = 0; i < 0x1000; i++) {
- if (base[UART_LSR << 2] & UART_LSR_THRE)
- break;
- barrier();
- }
-
- base[UART_TX << 2] = c;
-}
-
-static void flush(void)
-{
- unsigned char *base = SERIAL_BASE;
- unsigned char mask;
- int i;
-
- mask = UART_LSR_TEMT | UART_LSR_THRE;
-
- for (i = 0; i < 0x1000; i++) {
- if ((base[UART_LSR << 2] & mask) == mask)
- break;
- barrier();
- }
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
deleted file mode 100644
index 2c47a8ad0e27..000000000000
--- a/arch/arm/mach-kirkwood/irq.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/irq.c
- *
- * Kirkwood IRQ handling.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <asm/exception.h>
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include <plat/orion-gpio.h>
-#include <plat/irq.h>
-#include "common.h"
-
-static int __initdata gpio0_irqs[4] = {
- IRQ_KIRKWOOD_GPIO_LOW_0_7,
- IRQ_KIRKWOOD_GPIO_LOW_8_15,
- IRQ_KIRKWOOD_GPIO_LOW_16_23,
- IRQ_KIRKWOOD_GPIO_LOW_24_31,
-};
-
-static int __initdata gpio1_irqs[4] = {
- IRQ_KIRKWOOD_GPIO_HIGH_0_7,
- IRQ_KIRKWOOD_GPIO_HIGH_8_15,
- IRQ_KIRKWOOD_GPIO_HIGH_16_23,
- 0,
-};
-
-#ifdef CONFIG_MULTI_IRQ_HANDLER
-/*
- * Compiling with both non-DT and DT support enabled, will
- * break asm irq handler used by non-DT boards. Therefore,
- * we provide a C-style irq handler even for non-DT boards,
- * if MULTI_IRQ_HANDLER is set.
- */
-
-static void __iomem *kirkwood_irq_base = IRQ_VIRT_BASE;
-
-asmlinkage void
-__exception_irq_entry kirkwood_legacy_handle_irq(struct pt_regs *regs)
-{
- u32 stat;
-
- stat = readl_relaxed(kirkwood_irq_base + IRQ_CAUSE_LOW_OFF);
- stat &= readl_relaxed(kirkwood_irq_base + IRQ_MASK_LOW_OFF);
- if (stat) {
- unsigned int hwirq = __fls(stat);
- handle_IRQ(hwirq, regs);
- return;
- }
- stat = readl_relaxed(kirkwood_irq_base + IRQ_CAUSE_HIGH_OFF);
- stat &= readl_relaxed(kirkwood_irq_base + IRQ_MASK_HIGH_OFF);
- if (stat) {
- unsigned int hwirq = 32 + __fls(stat);
- handle_IRQ(hwirq, regs);
- return;
- }
-}
-#endif
-
-void __init kirkwood_init_irq(void)
-{
- orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
- orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
-
-#ifdef CONFIG_MULTI_IRQ_HANDLER
- set_handle_irq(kirkwood_legacy_handle_irq);
-#endif
-
- /*
- * Initialize gpiolib for GPIOs 0-49.
- */
- orion_gpio_init(NULL, 0, 32, GPIO_LOW_VIRT_BASE, 0,
- IRQ_KIRKWOOD_GPIO_START, gpio0_irqs);
- orion_gpio_init(NULL, 32, 18, GPIO_HIGH_VIRT_BASE, 0,
- IRQ_KIRKWOOD_GPIO_START + 32, gpio1_irqs);
-}
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.c b/arch/arm/mach-kirkwood/lacie_v2-common.c
deleted file mode 100644
index 8e3e4331c380..000000000000
--- a/arch/arm/mach-kirkwood/lacie_v2-common.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/lacie_v2-common.c
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
-#include <linux/gpio.h>
-#include <asm/mach/time.h>
-#include <mach/kirkwood.h>
-#include <mach/irqs.h>
-#include <plat/time.h>
-#include "common.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
- ****************************************************************************/
-
-static struct mtd_partition lacie_v2_flash_parts[] = {
- {
- .name = "u-boot",
- .size = MTDPART_SIZ_FULL,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
-};
-
-static const struct flash_platform_data lacie_v2_flash = {
- .type = "mx25l4005a",
- .name = "spi_flash",
- .parts = lacie_v2_flash_parts,
- .nr_parts = ARRAY_SIZE(lacie_v2_flash_parts),
-};
-
-static struct spi_board_info __initdata lacie_v2_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &lacie_v2_flash,
- .irq = -1,
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- },
-};
-
-void __init lacie_v2_register_flash(void)
-{
- spi_register_board_info(lacie_v2_spi_slave_info,
- ARRAY_SIZE(lacie_v2_spi_slave_info));
- kirkwood_spi_init();
-}
-
-/*****************************************************************************
- * I2C devices
- ****************************************************************************/
-
-static struct at24_platform_data at24c04 = {
- .byte_len = SZ_4K / 8,
- .page_size = 16,
-};
-
-/*
- * i2c addr | chip | description
- * 0x50 | HT24LC04 | eeprom (512B)
- */
-
-static struct i2c_board_info __initdata lacie_v2_i2c_info[] = {
- {
- I2C_BOARD_INFO("24c04", 0x50),
- .platform_data = &at24c04,
- }
-};
-
-void __init lacie_v2_register_i2c_devices(void)
-{
- kirkwood_i2c_init();
- i2c_register_board_info(0, lacie_v2_i2c_info,
- ARRAY_SIZE(lacie_v2_i2c_info));
-}
-
-/*****************************************************************************
- * Hard Disk power
- ****************************************************************************/
-
-static int __initdata lacie_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 };
-
-void __init lacie_v2_hdd_power_init(int hdd_num)
-{
- int i;
- int err;
-
- /* Power up all hard disks. */
- for (i = 0; i < hdd_num; i++) {
- err = gpio_request(lacie_v2_gpio_hdd_power[i], NULL);
- if (err == 0) {
- err = gpio_direction_output(
- lacie_v2_gpio_hdd_power[i], 1);
- /* Free the HDD power GPIOs. This allow user-space to
- * configure them via the gpiolib sysfs interface. */
- gpio_free(lacie_v2_gpio_hdd_power[i]);
- }
- if (err)
- pr_err("Failed to power up HDD%d\n", i + 1);
- }
-}
diff --git a/arch/arm/mach-kirkwood/lacie_v2-common.h b/arch/arm/mach-kirkwood/lacie_v2-common.h
deleted file mode 100644
index fc64f578536e..000000000000
--- a/arch/arm/mach-kirkwood/lacie_v2-common.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/lacie_v2-common.h
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
-#define __ARCH_KIRKWOOD_LACIE_V2_COMMON_H
-
-void lacie_v2_register_flash(void);
-void lacie_v2_register_i2c_devices(void);
-void lacie_v2_hdd_power_init(int hdd_num);
-
-#endif
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
deleted file mode 100644
index e96fd71abd76..000000000000
--- a/arch/arm/mach-kirkwood/mpp.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/mpp.c
- *
- * MPP functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <plat/mpp.h>
-#include "common.h"
-#include "mpp.h"
-
-static unsigned int __init kirkwood_variant(void)
-{
- u32 dev, rev;
-
- kirkwood_pcie_id(&dev, &rev);
-
- if (dev == MV88F6281_DEV_ID && rev >= MV88F6281_REV_A0)
- return MPP_F6281_MASK;
- if (dev == MV88F6282_DEV_ID)
- return MPP_F6282_MASK;
- if (dev == MV88F6192_DEV_ID && rev >= MV88F6192_REV_A0)
- return MPP_F6192_MASK;
- if (dev == MV88F6180_DEV_ID)
- return MPP_F6180_MASK;
-
- pr_err("MPP setup: unknown kirkwood variant (dev %#x rev %#x)\n",
- dev, rev);
- return 0;
-}
-
-void __init kirkwood_mpp_conf(unsigned int *mpp_list)
-{
- orion_mpp_conf(mpp_list, kirkwood_variant(),
- MPP_MAX, DEV_BUS_VIRT_BASE);
-}
diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
deleted file mode 100644
index d5a0d1da2e0e..000000000000
--- a/arch/arm/mach-kirkwood/mpp.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * linux/arch/arm/mach-kirkwood/mpp.h -- Multi Purpose Pins
- *
- * Copyright 2009: Marvell Technology Group Ltd.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __KIRKWOOD_MPP_H
-#define __KIRKWOOD_MPP_H
-
-#define MPP(_num, _sel, _in, _out, _F6180, _F6190, _F6192, _F6281, _F6282) ( \
- /* MPP number */ ((_num) & 0xff) | \
- /* MPP select value */ (((_sel) & 0xf) << 8) | \
- /* may be input signal */ ((!!(_in)) << 12) | \
- /* may be output signal */ ((!!(_out)) << 13) | \
- /* available on F6180 */ ((!!(_F6180)) << 14) | \
- /* available on F6190 */ ((!!(_F6190)) << 15) | \
- /* available on F6192 */ ((!!(_F6192)) << 16) | \
- /* available on F6281 */ ((!!(_F6281)) << 17) | \
- /* available on F6282 */ ((!!(_F6282)) << 18))
-
- /* num sel i o 6180 6190 6192 6281 6282 */
-
-#define MPP_F6180_MASK MPP( 0, 0x0, 0, 0, 1, 0, 0, 0, 0 )
-#define MPP_F6190_MASK MPP( 0, 0x0, 0, 0, 0, 1, 0, 0, 0 )
-#define MPP_F6192_MASK MPP( 0, 0x0, 0, 0, 0, 0, 1, 0, 0 )
-#define MPP_F6281_MASK MPP( 0, 0x0, 0, 0, 0, 0, 0, 1, 0 )
-#define MPP_F6282_MASK MPP( 0, 0x0, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP0_GPIO MPP( 0, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP0_NF_IO2 MPP( 0, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP0_SPI_SCn MPP( 0, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP1_GPO MPP( 1, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP1_NF_IO3 MPP( 1, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP1_SPI_MOSI MPP( 1, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP2_GPO MPP( 2, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP2_NF_IO4 MPP( 2, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP2_SPI_SCK MPP( 2, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP3_GPO MPP( 3, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP3_NF_IO5 MPP( 3, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP3_SPI_MISO MPP( 3, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP4_GPIO MPP( 4, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP4_NF_IO6 MPP( 4, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP4_UART0_RXD MPP( 4, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP4_SATA1_ACTn MPP( 4, 0x5, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP4_LCD_VGA_HSYNC MPP( 4, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP4_PTP_CLK MPP( 4, 0xd, 0, 0, 1, 1, 1, 1, 0 )
-
-#define MPP5_GPO MPP( 5, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP5_NF_IO7 MPP( 5, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP5_UART0_TXD MPP( 5, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP5_PTP_TRIG_GEN MPP( 5, 0x4, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP5_SATA0_ACTn MPP( 5, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP5_LCD_VGA_VSYNC MPP( 5, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP6_SYSRST_OUTn MPP( 6, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP6_SPI_MOSI MPP( 6, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP6_PTP_TRIG_GEN MPP( 6, 0x3, 0, 0, 1, 1, 1, 1, 0 )
-
-#define MPP7_GPO MPP( 7, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP7_PEX_RST_OUTn MPP( 7, 0x1, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP7_SPI_SCn MPP( 7, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP7_PTP_TRIG_GEN MPP( 7, 0x3, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP7_LCD_PWM MPP( 7, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP8_GPIO MPP( 8, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP8_TW0_SDA MPP( 8, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP8_UART0_RTS MPP( 8, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP8_UART1_RTS MPP( 8, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP8_MII0_RXERR MPP( 8, 0x4, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP8_SATA1_PRESENTn MPP( 8, 0x5, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP8_PTP_CLK MPP( 8, 0xc, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP8_MII0_COL MPP( 8, 0xd, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP9_GPIO MPP( 9, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP9_TW0_SCK MPP( 9, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP9_UART0_CTS MPP( 9, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP9_UART1_CTS MPP( 9, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP9_SATA0_PRESENTn MPP( 9, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP9_PTP_EVENT_REQ MPP( 9, 0xc, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP9_MII0_CRS MPP( 9, 0xd, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP10_GPO MPP( 10, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_SPI_SCK MPP( 10, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 0, 1, 1, 1, 1, 0 )
-
-#define MPP11_GPIO MPP( 11, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP11_SPI_MISO MPP( 11, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP11_UART0_RXD MPP( 11, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_CLK MPP( 11, 0xd, 0, 0, 1, 1, 1, 1, 0 )
-#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-
-#define MPP12_GPO MPP( 12, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP12_GPIO MPP( 12, 0x0, 1, 1, 0, 0, 0, 1, 0 )
-#define MPP12_SD_CLK MPP( 12, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP12_TW1_SDA MPP( 12, 0xd, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP13_GPIO MPP( 13, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP13_SD_CMD MPP( 13, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP13_UART1_TXD MPP( 13, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP13_AU_SPDIFRMCLK MPP( 13, 0xa, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP13_LCDPWM MPP( 13, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP14_GPIO MPP( 14, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP14_SD_D0 MPP( 14, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP14_UART1_RXD MPP( 14, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP14_SATA1_PRESENTn MPP( 14, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP14_AU_SPDIFI MPP( 14, 0xa, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP14_AU_I2SDI MPP( 14, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP14_MII0_COL MPP( 14, 0xd, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP15_GPIO MPP( 15, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP15_SD_D1 MPP( 15, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP15_UART0_RTS MPP( 15, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP15_UART1_TXD MPP( 15, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP15_SATA0_ACTn MPP( 15, 0x4, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP15_SPI_CSn MPP( 15, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP16_GPIO MPP( 16, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP16_SD_D2 MPP( 16, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP16_UART0_CTS MPP( 16, 0x2, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP16_UART1_RXD MPP( 16, 0x3, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP16_SATA1_ACTn MPP( 16, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP16_LCD_EXT_REF_CLK MPP( 16, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP16_MII0_CRS MPP( 16, 0xd, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP17_GPIO MPP( 17, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP17_SD_D3 MPP( 17, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP17_SATA0_PRESENTn MPP( 17, 0x4, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP17_SATA1_ACTn MPP( 17, 0xa, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP17_TW1_SCK MPP( 17, 0xd, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP18_GPO MPP( 18, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP18_NF_IO0 MPP( 18, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-#define MPP18_PEX0_CLKREQ MPP( 18, 0x2, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP19_GPO MPP( 19, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP19_NF_IO1 MPP( 19, 0x1, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP20_GPIO MPP( 20, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP20_TSMP0 MPP( 20, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP20_TDM_CH0_TX_QL MPP( 20, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP20_GE1_TXD0 MPP( 20, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP20_AU_SPDIFI MPP( 20, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP20_SATA1_ACTn MPP( 20, 0x5, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP20_LCD_D0 MPP( 20, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP21_GPIO MPP( 21, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP21_TSMP1 MPP( 21, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP21_TDM_CH0_RX_QL MPP( 21, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP21_GE1_TXD1 MPP( 21, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP21_AU_SPDIFO MPP( 21, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP21_SATA0_ACTn MPP( 21, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP21_LCD_D1 MPP( 21, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP22_GPIO MPP( 22, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP22_TSMP2 MPP( 22, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP22_TDM_CH2_TX_QL MPP( 22, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP22_GE1_TXD2 MPP( 22, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP22_AU_SPDIFRMKCLK MPP( 22, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP22_SATA1_PRESENTn MPP( 22, 0x5, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP22_LCD_D2 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP23_GPIO MPP( 23, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP23_TSMP3 MPP( 23, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP23_TDM_CH2_RX_QL MPP( 23, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP23_GE1_TXD3 MPP( 23, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP23_AU_I2SBCLK MPP( 23, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP23_SATA0_PRESENTn MPP( 23, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP23_LCD_D3 MPP( 23, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP24_GPIO MPP( 24, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP24_TSMP4 MPP( 24, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP24_TDM_SPI_CS0 MPP( 24, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP24_GE1_RXD0 MPP( 24, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP24_AU_I2SDO MPP( 24, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP24_LCD_D4 MPP( 24, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP25_GPIO MPP( 25, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP25_TSMP5 MPP( 25, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP25_TDM_SPI_SCK MPP( 25, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP25_GE1_RXD1 MPP( 25, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP25_AU_I2SLRCLK MPP( 25, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP25_LCD_D5 MPP( 25, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP26_GPIO MPP( 26, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP26_TSMP6 MPP( 26, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP26_TDM_SPI_MISO MPP( 26, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP26_GE1_RXD2 MPP( 26, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP26_AU_I2SMCLK MPP( 26, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP26_LCD_D6 MPP( 26, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP27_GPIO MPP( 27, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP27_TSMP7 MPP( 27, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP27_TDM_SPI_MOSI MPP( 27, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP27_GE1_RXD3 MPP( 27, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP27_AU_I2SDI MPP( 27, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP27_LCD_D7 MPP( 27, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP28_GPIO MPP( 28, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP28_TSMP8 MPP( 28, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP28_TDM_CODEC_INTn MPP( 28, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP28_GE1_COL MPP( 28, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP28_AU_EXTCLK MPP( 28, 0x4, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP28_LCD_D8 MPP( 28, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP29_GPIO MPP( 29, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP29_TSMP9 MPP( 29, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP29_TDM_CODEC_RSTn MPP( 29, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP29_GE1_TCLK MPP( 29, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP29_LCD_D9 MPP( 29, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP30_GPIO MPP( 30, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP30_TSMP10 MPP( 30, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP30_TDM_PCLK MPP( 30, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP30_GE1_RXCTL MPP( 30, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP30_LCD_D10 MPP( 30, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP31_GPIO MPP( 31, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP31_TSMP11 MPP( 31, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP31_TDM_FS MPP( 31, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP31_GE1_RXCLK MPP( 31, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP31_LCD_D11 MPP( 31, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP32_GPIO MPP( 32, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP32_TSMP12 MPP( 32, 0x1, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP32_TDM_DRX MPP( 32, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP32_GE1_TCLKOUT MPP( 32, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP32_LCD_D12 MPP( 32, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP33_GPO MPP( 33, 0x0, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP33_TDM_DTX MPP( 33, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP33_GE1_TXCTL MPP( 33, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP33_LCD_D13 MPP( 33, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP34_GPIO MPP( 34, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP34_TDM_SPI_CS1 MPP( 34, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP34_GE1_TXEN MPP( 34, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP34_SATA1_ACTn MPP( 34, 0x5, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP34_LCD_D14 MPP( 34, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP35_GPIO MPP( 35, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP35_TDM_CH0_TX_QL MPP( 35, 0x2, 0, 0, 0, 0, 1, 1, 1 )
-#define MPP35_GE1_RXERR MPP( 35, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP35_SATA0_ACTn MPP( 35, 0x5, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP35_LCD_D15 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP35_MII0_RXERR MPP( 35, 0xc, 0, 0, 1, 1, 1, 1, 1 )
-
-#define MPP36_GPIO MPP( 36, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP36_TSMP0 MPP( 36, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP36_TDM_SPI_CS1 MPP( 36, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP36_AU_SPDIFI MPP( 36, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP36_TW1_SDA MPP( 36, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP37_GPIO MPP( 37, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP37_TSMP1 MPP( 37, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP37_TDM_CH2_TX_QL MPP( 37, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP37_AU_SPDIFO MPP( 37, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP37_TW1_SCK MPP( 37, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP38_GPIO MPP( 38, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP38_TSMP2 MPP( 38, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP38_TDM_CH2_RX_QL MPP( 38, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP38_AU_SPDIFRMLCLK MPP( 38, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP38_LCD_D18 MPP( 38, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP39_GPIO MPP( 39, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP39_TSMP3 MPP( 39, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP39_TDM_SPI_CS0 MPP( 39, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP39_AU_I2SBCLK MPP( 39, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP39_LCD_D19 MPP( 39, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP40_GPIO MPP( 40, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP40_TSMP4 MPP( 40, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP40_TDM_SPI_SCK MPP( 40, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP40_AU_I2SDO MPP( 40, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP40_LCD_D20 MPP( 40, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP41_GPIO MPP( 41, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP41_TSMP5 MPP( 41, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP41_TDM_SPI_MISO MPP( 41, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP41_AU_I2SLRCLK MPP( 41, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP41_LCD_D21 MPP( 41, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP42_GPIO MPP( 42, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP42_TSMP6 MPP( 42, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP42_TDM_SPI_MOSI MPP( 42, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP42_AU_I2SMCLK MPP( 42, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP42_LCD_D22 MPP( 42, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP43_GPIO MPP( 43, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP43_TSMP7 MPP( 43, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP43_TDM_CODEC_INTn MPP( 43, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP43_AU_I2SDI MPP( 43, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP43_LCD_D23 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP44_GPIO MPP( 44, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP44_TSMP8 MPP( 44, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP44_TDM_CODEC_RSTn MPP( 44, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP44_AU_EXTCLK MPP( 44, 0x4, 0, 0, 1, 0, 0, 1, 1 )
-#define MPP44_LCD_CLK MPP( 44, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP45_GPIO MPP( 45, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP45_TSMP9 MPP( 45, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP45_TDM_PCLK MPP( 45, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP245_LCD_E MPP( 45, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP46_GPIO MPP( 46, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP46_TSMP10 MPP( 46, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP46_TDM_FS MPP( 46, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP46_LCD_HSYNC MPP( 46, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP47_GPIO MPP( 47, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP47_TSMP11 MPP( 47, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP47_TDM_DRX MPP( 47, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP47_LCD_VSYNC MPP( 47, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP48_GPIO MPP( 48, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP48_TSMP12 MPP( 48, 0x1, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP48_LCD_D16 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP49_GPIO MPP( 49, 0x0, 1, 1, 0, 0, 0, 1, 0 )
-#define MPP49_GPO MPP( 49, 0x0, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP49_TSMP9 MPP( 49, 0x1, 0, 0, 0, 0, 0, 1, 0 )
-#define MPP49_TDM_CH0_RX_QL MPP( 49, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP49_PTP_CLK MPP( 49, 0x5, 0, 0, 0, 0, 0, 1, 0 )
-#define MPP49_PEX0_CLKREQ MPP( 49, 0xa, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP49_LCD_D17 MPP( 49, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-
-#define MPP_MAX 49
-
-void kirkwood_mpp_conf(unsigned int *mpp_list);
-
-#endif
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
deleted file mode 100644
index 913d032cdb19..000000000000
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/netxbig_v2-setup.c
- *
- * LaCie 2Big and 5Big Network v2 board setup
- *
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/leds-kirkwood-netxbig.h>
-#include "common.h"
-#include "mpp.h"
-#include "lacie_v2-common.h"
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data netxbig_v2_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(0),
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-
-static struct mv_sata_platform_data netxbig_v2_sata_data = {
- .n_ports = 2,
-};
-
-/*****************************************************************************
- * GPIO keys
- ****************************************************************************/
-
-#define NETXBIG_V2_GPIO_SWITCH_POWER_ON 13
-#define NETXBIG_V2_GPIO_SWITCH_POWER_OFF 15
-#define NETXBIG_V2_GPIO_FUNC_BUTTON 34
-
-#define NETXBIG_V2_SWITCH_POWER_ON 0x1
-#define NETXBIG_V2_SWITCH_POWER_OFF 0x2
-
-static struct gpio_keys_button netxbig_v2_buttons[] = {
- [0] = {
- .type = EV_SW,
- .code = NETXBIG_V2_SWITCH_POWER_ON,
- .gpio = NETXBIG_V2_GPIO_SWITCH_POWER_ON,
- .desc = "Back power switch (on|auto)",
- .active_low = 1,
- },
- [1] = {
- .type = EV_SW,
- .code = NETXBIG_V2_SWITCH_POWER_OFF,
- .gpio = NETXBIG_V2_GPIO_SWITCH_POWER_OFF,
- .desc = "Back power switch (auto|off)",
- .active_low = 1,
- },
- [2] = {
- .code = KEY_OPTION,
- .gpio = NETXBIG_V2_GPIO_FUNC_BUTTON,
- .desc = "Function button",
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data netxbig_v2_button_data = {
- .buttons = netxbig_v2_buttons,
- .nbuttons = ARRAY_SIZE(netxbig_v2_buttons),
-};
-
-static struct platform_device netxbig_v2_gpio_buttons = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &netxbig_v2_button_data,
- },
-};
-
-/*****************************************************************************
- * GPIO extension LEDs
- ****************************************************************************/
-
-/*
- * The LEDs are controlled by a CPLD and can be configured through a GPIO
- * extension bus:
- *
- * - address register : bit [0-2] -> GPIO [47-49]
- * - data register : bit [0-2] -> GPIO [44-46]
- * - enable register : GPIO 29
- */
-
-static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
-static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
-
-static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
- .addr = netxbig_v2_gpio_ext_addr,
- .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
- .data = netxbig_v2_gpio_ext_data,
- .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
- .enable = 29,
-};
-
-/*
- * Address register selection:
- *
- * addr | register
- * ----------------------------
- * 0 | front LED
- * 1 | front LED brightness
- * 2 | SATA LED brightness
- * 3 | SATA0 LED
- * 4 | SATA1 LED
- * 5 | SATA2 LED
- * 6 | SATA3 LED
- * 7 | SATA4 LED
- *
- * Data register configuration:
- *
- * data | LED brightness
- * -------------------------------------------------
- * 0 | min (off)
- * - | -
- * 7 | max
- *
- * data | front LED mode
- * -------------------------------------------------
- * 0 | fix off
- * 1 | fix blue on
- * 2 | fix red on
- * 3 | blink blue on=1 sec and blue off=1 sec
- * 4 | blink red on=1 sec and red off=1 sec
- * 5 | blink blue on=2.5 sec and red on=0.5 sec
- * 6 | blink blue on=1 sec and red on=1 sec
- * 7 | blink blue on=0.5 sec and blue off=2.5 sec
- *
- * data | SATA LED mode
- * -------------------------------------------------
- * 0 | fix off
- * 1 | SATA activity blink
- * 2 | fix red on
- * 3 | blink blue on=1 sec and blue off=1 sec
- * 4 | blink red on=1 sec and red off=1 sec
- * 5 | blink blue on=2.5 sec and red on=0.5 sec
- * 6 | blink blue on=1 sec and red on=1 sec
- * 7 | fix blue on
- */
-
-static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 2,
- [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
- [NETXBIG_LED_TIMER1] = 4,
- [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
-};
-
-static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 1,
- [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
- [NETXBIG_LED_TIMER1] = 3,
- [NETXBIG_LED_TIMER2] = 7,
-};
-
-static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 7,
- [NETXBIG_LED_SATA] = 1,
- [NETXBIG_LED_TIMER1] = 3,
- [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
-};
-
-static struct netxbig_led_timer netxbig_v2_led_timer[] = {
- [0] = {
- .delay_on = 500,
- .delay_off = 500,
- .mode = NETXBIG_LED_TIMER1,
- },
- [1] = {
- .delay_on = 500,
- .delay_off = 1000,
- .mode = NETXBIG_LED_TIMER2,
- },
-};
-
-#define NETXBIG_LED(_name, maddr, mval, baddr) \
- { .name = _name, \
- .mode_addr = maddr, \
- .mode_val = mval, \
- .bright_addr = baddr }
-
-static struct netxbig_led net2big_v2_leds_ctrl[] = {
- NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
- NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
- NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
-};
-
-static struct netxbig_led_platform_data net2big_v2_leds_data = {
- .gpio_ext = &netxbig_v2_gpio_ext,
- .timer = netxbig_v2_led_timer,
- .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
- .leds = net2big_v2_leds_ctrl,
- .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
-};
-
-static struct netxbig_led net5big_v2_leds_ctrl[] = {
- NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
- NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
- NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata5", 7, netxbig_v2_red_mled, 2),
-};
-
-static struct netxbig_led_platform_data net5big_v2_leds_data = {
- .gpio_ext = &netxbig_v2_gpio_ext,
- .timer = netxbig_v2_led_timer,
- .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
- .leds = net5big_v2_leds_ctrl,
- .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
-};
-
-static struct platform_device netxbig_v2_leds = {
- .name = "leds-netxbig",
- .id = -1,
- .dev = {
- .platform_data = &net2big_v2_leds_data,
- },
-};
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-
-static unsigned int net2big_v2_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP6_SYSRST_OUTn,
- MPP7_GPO, /* Request power-off */
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP13_GPIO, /* Rear power switch (on|auto) */
- MPP14_GPIO, /* USB fuse alarm */
- MPP15_GPIO, /* Rear power switch (auto|off) */
- MPP16_GPIO, /* SATA HDD1 power */
- MPP17_GPIO, /* SATA HDD2 power */
- MPP20_SATA1_ACTn,
- MPP21_SATA0_ACTn,
- MPP24_GPIO, /* USB mode select */
- MPP26_GPIO, /* USB device vbus */
- MPP28_GPIO, /* USB enable host vbus */
- MPP29_GPIO, /* GPIO extension ALE */
- MPP34_GPIO, /* Rear Push button */
- MPP35_GPIO, /* Inhibit switch power-off */
- MPP36_GPIO, /* SATA HDD1 presence */
- MPP37_GPIO, /* SATA HDD2 presence */
- MPP40_GPIO, /* eSATA presence */
- MPP44_GPIO, /* GPIO extension (data 0) */
- MPP45_GPIO, /* GPIO extension (data 1) */
- MPP46_GPIO, /* GPIO extension (data 2) */
- MPP47_GPIO, /* GPIO extension (addr 0) */
- MPP48_GPIO, /* GPIO extension (addr 1) */
- MPP49_GPIO, /* GPIO extension (addr 2) */
- 0
-};
-
-static unsigned int net5big_v2_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP6_SYSRST_OUTn,
- MPP7_GPO, /* Request power-off */
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP13_GPIO, /* Rear power switch (on|auto) */
- MPP14_GPIO, /* USB fuse alarm */
- MPP15_GPIO, /* Rear power switch (auto|off) */
- MPP16_GPIO, /* SATA HDD1 power */
- MPP17_GPIO, /* SATA HDD2 power */
- MPP20_GE1_TXD0,
- MPP21_GE1_TXD1,
- MPP22_GE1_TXD2,
- MPP23_GE1_TXD3,
- MPP24_GE1_RXD0,
- MPP25_GE1_RXD1,
- MPP26_GE1_RXD2,
- MPP27_GE1_RXD3,
- MPP28_GPIO, /* USB enable host vbus */
- MPP29_GPIO, /* GPIO extension ALE */
- MPP30_GE1_RXCTL,
- MPP31_GE1_RXCLK,
- MPP32_GE1_TCLKOUT,
- MPP33_GE1_TXCTL,
- MPP34_GPIO, /* Rear Push button */
- MPP35_GPIO, /* Inhibit switch power-off */
- MPP36_GPIO, /* SATA HDD1 presence */
- MPP37_GPIO, /* SATA HDD2 presence */
- MPP38_GPIO, /* SATA HDD3 presence */
- MPP39_GPIO, /* SATA HDD4 presence */
- MPP40_GPIO, /* SATA HDD5 presence */
- MPP41_GPIO, /* SATA HDD3 power */
- MPP42_GPIO, /* SATA HDD4 power */
- MPP43_GPIO, /* SATA HDD5 power */
- MPP44_GPIO, /* GPIO extension (data 0) */
- MPP45_GPIO, /* GPIO extension (data 1) */
- MPP46_GPIO, /* GPIO extension (data 2) */
- MPP47_GPIO, /* GPIO extension (addr 0) */
- MPP48_GPIO, /* GPIO extension (addr 1) */
- MPP49_GPIO, /* GPIO extension (addr 2) */
- 0
-};
-
-#define NETXBIG_V2_GPIO_POWER_OFF 7
-
-static void netxbig_v2_power_off(void)
-{
- gpio_set_value(NETXBIG_V2_GPIO_POWER_OFF, 1);
-}
-
-static void __init netxbig_v2_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- if (machine_is_net2big_v2())
- kirkwood_mpp_conf(net2big_v2_mpp_config);
- else
- kirkwood_mpp_conf(net5big_v2_mpp_config);
-
- if (machine_is_net2big_v2())
- lacie_v2_hdd_power_init(2);
- else
- lacie_v2_hdd_power_init(5);
-
- kirkwood_ehci_init();
- kirkwood_ge00_init(&netxbig_v2_ge00_data);
- if (machine_is_net5big_v2())
- kirkwood_ge01_init(&netxbig_v2_ge01_data);
- kirkwood_sata_init(&netxbig_v2_sata_data);
- kirkwood_uart0_init();
- lacie_v2_register_flash();
- lacie_v2_register_i2c_devices();
-
- if (machine_is_net5big_v2())
- netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
- platform_device_register(&netxbig_v2_leds);
- platform_device_register(&netxbig_v2_gpio_buttons);
-
- if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 &&
- gpio_direction_output(NETXBIG_V2_GPIO_POWER_OFF, 0) == 0)
- pm_power_off = netxbig_v2_power_off;
- else
- pr_err("netxbig_v2: failed to configure power-off GPIO\n");
-}
-
-#ifdef CONFIG_MACH_NET2BIG_V2
-MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
- .atag_offset = 0x100,
- .init_machine = netxbig_v2_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_NET5BIG_V2
-MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
- .atag_offset = 0x100,
- .init_machine = netxbig_v2_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
deleted file mode 100644
index e5cf84103583..000000000000
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/openrd-setup.c
- *
- * Marvell OpenRD (Base|Client|Ultimate) Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition openrd_nand_parts[] = {
- {
- .name = "u-boot",
- .offset = 0,
- .size = SZ_1M,
- .mask_flags = MTD_WRITEABLE
- }, {
- .name = "uImage",
- .offset = MTDPART_OFS_NXTBLK,
- .size = SZ_4M
- }, {
- .name = "root",
- .offset = MTDPART_OFS_NXTBLK,
- .size = MTDPART_SIZ_FULL
- },
-};
-
-static struct mv643xx_eth_platform_data openrd_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data openrd_ge01_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(24),
-};
-
-static struct mv_sata_platform_data openrd_sata_data = {
- .n_ports = 2,
-};
-
-static struct mvsdio_platform_data openrd_mvsdio_data = {
- .gpio_card_detect = 29, /* MPP29 used as SD card detect */
- .gpio_write_protect = -1,
-};
-
-static unsigned int openrd_mpp_config[] __initdata = {
- MPP12_SD_CLK,
- MPP13_SD_CMD,
- MPP14_SD_D0,
- MPP15_SD_D1,
- MPP16_SD_D2,
- MPP17_SD_D3,
- MPP28_GPIO,
- MPP29_GPIO,
- MPP34_GPIO,
- 0
-};
-
-/* Configure MPP for UART1 */
-static unsigned int openrd_uart1_mpp_config[] __initdata = {
- MPP13_UART1_TXD,
- MPP14_UART1_RXD,
- 0
-};
-
-static struct i2c_board_info i2c_board_info[] __initdata = {
- {
- I2C_BOARD_INFO("cs42l51", 0x4a),
- },
-};
-
-static struct platform_device openrd_client_audio_device = {
- .name = "openrd-client-audio",
- .id = -1,
-};
-
-static int __initdata uart1;
-
-static int __init sd_uart_selection(char *str)
-{
- uart1 = -EINVAL;
-
- /* Default is SD. Change if required, for UART */
- if (!str)
- return 0;
-
- if (!strncmp(str, "232", 3)) {
- uart1 = 232;
- } else if (!strncmp(str, "485", 3)) {
- /* OpenRD-Base doesn't have RS485. Treat is as an
- * unknown argument & just have default setting -
- * which is SD */
- if (machine_is_openrd_base()) {
- uart1 = -ENODEV;
- return 1;
- }
-
- uart1 = 485;
- }
- return 1;
-}
-/* Parse boot_command_line string kw_openrd_init_uart1=232/485 */
-__setup("kw_openrd_init_uart1=", sd_uart_selection);
-
-static int __init uart1_mpp_config(void)
-{
- kirkwood_mpp_conf(openrd_uart1_mpp_config);
-
- if (gpio_request(34, "SD_UART1_SEL")) {
- pr_err("GPIO request 34 failed for SD/UART1 selection\n");
- return -EIO;
- }
-
- if (gpio_request(28, "RS232_RS485_SEL")) {
- pr_err("GPIO request 28 failed for RS232/RS485 selection\n");
- gpio_free(34);
- return -EIO;
- }
-
- /* Select UART1
- * Pin # 34: 0 => UART1, 1 => SD */
- gpio_direction_output(34, 0);
-
- /* Select RS232 OR RS485
- * Pin # 28: 0 => RS232, 1 => RS485 */
- if (uart1 == 232)
- gpio_direction_output(28, 0);
- else
- gpio_direction_output(28, 1);
-
- gpio_free(34);
- gpio_free(28);
-
- return 0;
-}
-
-static void __init openrd_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(openrd_mpp_config);
-
- kirkwood_uart0_init();
- kirkwood_nand_init(openrd_nand_parts, ARRAY_SIZE(openrd_nand_parts),
- 25);
-
- kirkwood_ehci_init();
-
- if (machine_is_openrd_ultimate()) {
- openrd_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
- openrd_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
- }
-
- kirkwood_ge00_init(&openrd_ge00_data);
- if (!machine_is_openrd_base())
- kirkwood_ge01_init(&openrd_ge01_data);
-
- kirkwood_sata_init(&openrd_sata_data);
-
- kirkwood_i2c_init();
-
- if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
- platform_device_register(&openrd_client_audio_device);
- i2c_register_board_info(0, i2c_board_info,
- ARRAY_SIZE(i2c_board_info));
- kirkwood_audio_init();
- }
-
- if (uart1 <= 0) {
- if (uart1 < 0)
- pr_err("Invalid kernel parameter to select UART1. Defaulting to SD. ERROR CODE: %d\n",
- uart1);
-
- /* Select SD
- * Pin # 34: 0 => UART1, 1 => SD */
- if (gpio_request(34, "SD_UART1_SEL")) {
- pr_err("GPIO request 34 failed for SD/UART1 selection\n");
- } else {
-
- gpio_direction_output(34, 1);
- gpio_free(34);
- kirkwood_sdio_init(&openrd_mvsdio_data);
- }
- } else {
- if (!uart1_mpp_config())
- kirkwood_uart1_init();
- }
-}
-
-static int __init openrd_pci_init(void)
-{
- if (machine_is_openrd_base() ||
- machine_is_openrd_client() ||
- machine_is_openrd_ultimate())
- kirkwood_pcie_init(KW_PCIE0);
-
- return 0;
-}
-subsys_initcall(openrd_pci_init);
-
-#ifdef CONFIG_MACH_OPENRD_BASE
-MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
- /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .atag_offset = 0x100,
- .init_machine = openrd_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_OPENRD_CLIENT
-MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
- /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .atag_offset = 0x100,
- .init_machine = openrd_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
-#endif
-
-#ifdef CONFIG_MACH_OPENRD_ULTIMATE
-MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
- /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
- .atag_offset = 0x100,
- .init_machine = openrd_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
deleted file mode 100644
index 12d86f39f380..000000000000
--- a/arch/arm/mach-kirkwood/pcie.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/pcie.c
- *
- * PCIe functions for Marvell Kirkwood SoCs
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/mbus.h>
-#include <video/vga.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <plat/pcie.h>
-#include <mach/bridge-regs.h>
-#include "common.h"
-
-/* These can go away once Kirkwood uses the mvebu-mbus DT binding */
-#define KIRKWOOD_MBUS_PCIE0_MEM_TARGET 0x4
-#define KIRKWOOD_MBUS_PCIE0_MEM_ATTR 0xe8
-#define KIRKWOOD_MBUS_PCIE0_IO_TARGET 0x4
-#define KIRKWOOD_MBUS_PCIE0_IO_ATTR 0xe0
-#define KIRKWOOD_MBUS_PCIE1_MEM_TARGET 0x4
-#define KIRKWOOD_MBUS_PCIE1_MEM_ATTR 0xd8
-#define KIRKWOOD_MBUS_PCIE1_IO_TARGET 0x4
-#define KIRKWOOD_MBUS_PCIE1_IO_ATTR 0xd0
-
-static void kirkwood_enable_pcie_clk(const char *port)
-{
- struct clk *clk;
-
- clk = clk_get_sys("pcie", port);
- if (IS_ERR(clk)) {
- pr_err("PCIE clock %s missing\n", port);
- return;
- }
- clk_prepare_enable(clk);
- clk_put(clk);
-}
-
-/* This function is called very early in the boot when probing the
- hardware to determine what we actually are, and what rate tclk is
- ticking at. Hence calling kirkwood_enable_pcie_clk() is not
- possible since the clk tree has not been created yet. */
-void kirkwood_enable_pcie(void)
-{
- u32 curr = readl(CLOCK_GATING_CTRL);
- if (!(curr & CGC_PEX0))
- writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
-}
-
-void kirkwood_pcie_id(u32 *dev, u32 *rev)
-{
- kirkwood_enable_pcie();
- *dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
- *rev = orion_pcie_rev(PCIE_VIRT_BASE);
-}
-
-struct pcie_port {
- u8 root_bus_nr;
- void __iomem *base;
- spinlock_t conf_lock;
- int irq;
- struct resource res;
-};
-
-static int pcie_port_map[2];
-static int num_pcie_ports;
-
-static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
-{
- /*
- * Don't go out when trying to access --
- * 1. nonexisting device on local bus
- * 2. where there's no device connected (no link)
- */
- if (bus == pp->root_bus_nr && dev == 0)
- return 1;
-
- if (!orion_pcie_link_up(pp->base))
- return 0;
-
- if (bus == pp->root_bus_nr && dev != 1)
- return 0;
-
- return 1;
-}
-
-
-/*
- * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
- * and then reading the PCIE_CONF_DATA register. Need to make sure these
- * transactions are atomic.
- */
-
-static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
- int size, u32 *val)
-{
- struct pci_sys_data *sys = bus->sysdata;
- struct pcie_port *pp = sys->private_data;
- unsigned long flags;
- int ret;
-
- if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- spin_lock_irqsave(&pp->conf_lock, flags);
- ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
- spin_unlock_irqrestore(&pp->conf_lock, flags);
-
- return ret;
-}
-
-static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
- int where, int size, u32 val)
-{
- struct pci_sys_data *sys = bus->sysdata;
- struct pcie_port *pp = sys->private_data;
- unsigned long flags;
- int ret;
-
- if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- spin_lock_irqsave(&pp->conf_lock, flags);
- ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
- spin_unlock_irqrestore(&pp->conf_lock, flags);
-
- return ret;
-}
-
-static struct pci_ops pcie_ops = {
- .read = pcie_rd_conf,
- .write = pcie_wr_conf,
-};
-
-static void __init pcie0_ioresources_init(struct pcie_port *pp)
-{
- pp->base = PCIE_VIRT_BASE;
- pp->irq = IRQ_KIRKWOOD_PCIE;
-
- /*
- * IORESOURCE_MEM
- */
- pp->res.name = "PCIe 0 MEM";
- pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
- pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
- pp->res.flags = IORESOURCE_MEM;
-}
-
-static void __init pcie1_ioresources_init(struct pcie_port *pp)
-{
- pp->base = PCIE1_VIRT_BASE;
- pp->irq = IRQ_KIRKWOOD_PCIE1;
-
- /*
- * IORESOURCE_MEM
- */
- pp->res.name = "PCIe 1 MEM";
- pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
- pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
- pp->res.flags = IORESOURCE_MEM;
-}
-
-static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
-{
- struct pcie_port *pp;
- int index;
-
- if (nr >= num_pcie_ports)
- return 0;
-
- index = pcie_port_map[nr];
- pr_info("PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
-
- pp = kzalloc(sizeof(*pp), GFP_KERNEL);
- if (!pp)
- panic("PCIe: failed to allocate pcie_port data");
- sys->private_data = pp;
- pp->root_bus_nr = sys->busnr;
- spin_lock_init(&pp->conf_lock);
-
- switch (index) {
- case 0:
- kirkwood_enable_pcie_clk("0");
- pcie0_ioresources_init(pp);
- pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
- break;
- case 1:
- kirkwood_enable_pcie_clk("1");
- pcie1_ioresources_init(pp);
- pci_ioremap_io(SZ_64K * sys->busnr,
- KIRKWOOD_PCIE1_IO_PHYS_BASE);
- break;
- default:
- panic("PCIe setup: invalid controller %d", index);
- }
-
- if (request_resource(&iomem_resource, &pp->res))
- panic("Request PCIe%d Memory resource failed\n", index);
-
- pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
-
- /*
- * Generic PCIe unit setup.
- */
- orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
-
- orion_pcie_setup(pp->base);
-
- 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 rc_pci_fixup(struct pci_dev *dev)
-{
- 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;
- dev->resource[i].flags = 0;
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
-
-static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
- u8 pin)
-{
- struct pci_sys_data *sys = dev->sysdata;
- struct pcie_port *pp = sys->private_data;
-
- return pp->irq;
-}
-
-static struct hw_pci kirkwood_pci __initdata = {
- .setup = kirkwood_pcie_setup,
- .map_irq = kirkwood_pcie_map_irq,
- .ops = &pcie_ops,
-};
-
-static void __init add_pcie_port(int index, void __iomem *base)
-{
- pcie_port_map[num_pcie_ports++] = index;
- pr_info("Kirkwood PCIe port %d: link %s\n", index,
- orion_pcie_link_up(base) ? "up" : "down");
-}
-
-void __init kirkwood_pcie_init(unsigned int portmask)
-{
- mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE0_IO_TARGET,
- KIRKWOOD_MBUS_PCIE0_IO_ATTR,
- KIRKWOOD_PCIE_IO_PHYS_BASE,
- KIRKWOOD_PCIE_IO_SIZE,
- KIRKWOOD_PCIE_IO_BUS_BASE);
- mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE0_MEM_TARGET,
- KIRKWOOD_MBUS_PCIE0_MEM_ATTR,
- KIRKWOOD_PCIE_MEM_PHYS_BASE,
- KIRKWOOD_PCIE_MEM_SIZE);
- mvebu_mbus_add_window_remap_by_id(KIRKWOOD_MBUS_PCIE1_IO_TARGET,
- KIRKWOOD_MBUS_PCIE1_IO_ATTR,
- KIRKWOOD_PCIE1_IO_PHYS_BASE,
- KIRKWOOD_PCIE1_IO_SIZE,
- KIRKWOOD_PCIE1_IO_BUS_BASE);
- mvebu_mbus_add_window_by_id(KIRKWOOD_MBUS_PCIE1_MEM_TARGET,
- KIRKWOOD_MBUS_PCIE1_MEM_ATTR,
- KIRKWOOD_PCIE1_MEM_PHYS_BASE,
- KIRKWOOD_PCIE1_MEM_SIZE);
-
- vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
-
- if (portmask & KW_PCIE0)
- add_pcie_port(0, PCIE_VIRT_BASE);
-
- if (portmask & KW_PCIE1)
- add_pcie_port(1, PCIE1_VIRT_BASE);
-
- kirkwood_pci.nr_controllers = num_pcie_ports;
- pci_common_init(&kirkwood_pci);
-}
diff --git a/arch/arm/mach-kirkwood/pm.c b/arch/arm/mach-kirkwood/pm.c
deleted file mode 100644
index 8e5e0329d04c..000000000000
--- a/arch/arm/mach-kirkwood/pm.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Power Management driver for Marvell Kirkwood SoCs
- *
- * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/suspend.h>
-#include <linux/io.h>
-#include <mach/bridge-regs.h>
-#include "common.h"
-
-static void __iomem *ddr_operation_base;
-static void __iomem *memory_pm_ctrl;
-
-static void kirkwood_low_power(void)
-{
- u32 mem_pm_ctrl;
-
- mem_pm_ctrl = readl(memory_pm_ctrl);
-
- /* Set peripherals to low-power mode */
- writel_relaxed(~0, memory_pm_ctrl);
-
- /* Set DDR in self-refresh */
- writel_relaxed(0x7, ddr_operation_base);
-
- /*
- * Set CPU in wait-for-interrupt state.
- * This disables the CPU core clocks,
- * the array clocks, and also the L2 controller.
- */
- cpu_do_idle();
-
- writel_relaxed(mem_pm_ctrl, memory_pm_ctrl);
-}
-
-static int kirkwood_suspend_enter(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_STANDBY:
- kirkwood_low_power();
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int kirkwood_pm_valid_standby(suspend_state_t state)
-{
- return state == PM_SUSPEND_STANDBY;
-}
-
-static const struct platform_suspend_ops kirkwood_suspend_ops = {
- .enter = kirkwood_suspend_enter,
- .valid = kirkwood_pm_valid_standby,
-};
-
-void __init kirkwood_pm_init(void)
-{
- ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
- memory_pm_ctrl = ioremap(MEMORY_PM_CTRL_PHYS, 4);
-
- suspend_set_ops(&kirkwood_suspend_ops);
-}
diff --git a/arch/arm/mach-kirkwood/pm.h b/arch/arm/mach-kirkwood/pm.h
deleted file mode 100644
index 21e7530f368b..000000000000
--- a/arch/arm/mach-kirkwood/pm.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Power Management driver for Marvell Kirkwood SoCs
- *
- * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.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 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ARCH_KIRKWOOD_PM_H
-#define __ARCH_KIRKWOOD_PM_H
-
-#ifdef CONFIG_PM
-void kirkwood_pm_init(void);
-#else
-static inline void kirkwood_pm_init(void) {};
-#endif
-
-#endif
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
deleted file mode 100644
index e4fd3129d36f..000000000000
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
- *
- * Marvell RD-88F6192-NAS Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <plat/orion-gpio.h>
-#include "common.h"
-
-#define RD88F6192_GPIO_USB_VBUS 10
-
-static struct mv643xx_eth_platform_data rd88f6192_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data rd88f6192_sata_data = {
- .n_ports = 2,
-};
-
-static const struct flash_platform_data rd88F6192_spi_slave_data = {
- .type = "m25p128",
-};
-
-static struct spi_board_info __initdata rd88F6192_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &rd88F6192_spi_slave_data,
- .irq = -1,
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- },
-};
-
-static void __init rd88f6192_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
-
- orion_gpio_set_valid(RD88F6192_GPIO_USB_VBUS, 1);
- if (gpio_request(RD88F6192_GPIO_USB_VBUS, "USB VBUS") != 0 ||
- gpio_direction_output(RD88F6192_GPIO_USB_VBUS, 1) != 0)
- pr_err("RD-88F6192-NAS: failed to setup USB VBUS GPIO\n");
-
- kirkwood_ehci_init();
- kirkwood_ge00_init(&rd88f6192_ge00_data);
- kirkwood_sata_init(&rd88f6192_sata_data);
- spi_register_board_info(rd88F6192_spi_slave_info,
- ARRAY_SIZE(rd88F6192_spi_slave_info));
- kirkwood_spi_init();
- kirkwood_uart0_init();
-}
-
-static int __init rd88f6192_pci_init(void)
-{
- if (machine_is_rd88f6192_nas())
- kirkwood_pcie_init(KW_PCIE0);
-
- return 0;
-}
-subsys_initcall(rd88f6192_pci_init);
-
-MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
- /* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .atag_offset = 0x100,
- .init_machine = rd88f6192_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
deleted file mode 100644
index 5154bd2a3ad3..000000000000
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/rd88f6281-setup.c
- *
- * Marvell RD-88F6281 Reference Board Setup
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ethtool.h>
-#include <net/dsa.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <linux/platform_data/mmc-mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition rd88f6281_nand_parts[] = {
- {
- .name = "u-boot",
- .offset = 0,
- .size = SZ_1M
- }, {
- .name = "uImage",
- .offset = MTDPART_OFS_NXTBLK,
- .size = SZ_2M
- }, {
- .name = "root",
- .offset = MTDPART_OFS_NXTBLK,
- .size = MTDPART_SIZ_FULL
- },
-};
-
-static struct mv643xx_eth_platform_data rd88f6281_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_NONE,
- .speed = SPEED_1000,
- .duplex = DUPLEX_FULL,
-};
-
-static struct dsa_chip_data rd88f6281_switch_chip_data = {
- .port_names[0] = "lan1",
- .port_names[1] = "lan2",
- .port_names[2] = "lan3",
- .port_names[3] = "lan4",
- .port_names[5] = "cpu",
-};
-
-static struct dsa_platform_data rd88f6281_switch_plat_data = {
- .nr_chips = 1,
- .chip = &rd88f6281_switch_chip_data,
-};
-
-static struct mv643xx_eth_platform_data rd88f6281_ge01_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(11),
-};
-
-static struct mv_sata_platform_data rd88f6281_sata_data = {
- .n_ports = 2,
-};
-
-static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
- .gpio_card_detect = 28,
- .gpio_write_protect = -1,
-};
-
-static unsigned int rd88f6281_mpp_config[] __initdata = {
- MPP28_GPIO,
- 0
-};
-
-static void __init rd88f6281_init(void)
-{
- u32 dev, rev;
-
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(rd88f6281_mpp_config);
-
- kirkwood_nand_init(rd88f6281_nand_parts,
- ARRAY_SIZE(rd88f6281_nand_parts),
- 25);
- kirkwood_ehci_init();
-
- kirkwood_ge00_init(&rd88f6281_ge00_data);
- kirkwood_pcie_id(&dev, &rev);
- if (rev == MV88F6281_REV_A0) {
- rd88f6281_switch_chip_data.sw_addr = 10;
- kirkwood_ge01_init(&rd88f6281_ge01_data);
- } else {
- rd88f6281_switch_chip_data.port_names[4] = "wan";
- }
- kirkwood_ge00_switch_init(&rd88f6281_switch_plat_data, NO_IRQ);
-
- kirkwood_sata_init(&rd88f6281_sata_data);
- kirkwood_sdio_init(&rd88f6281_mvsdio_data);
- kirkwood_uart0_init();
-}
-
-static int __init rd88f6281_pci_init(void)
-{
- if (machine_is_rd88f6281())
- kirkwood_pcie_init(KW_PCIE0);
-
- return 0;
-}
-subsys_initcall(rd88f6281_pci_init);
-
-MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
- /* Maintainer: Saeed Bishara <saeed@marvell.com> */
- .atag_offset = 0x100,
- .init_machine = rd88f6281_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
deleted file mode 100644
index 8736f8c97518..000000000000
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- *
- * HP t5325 Thin Client setup
- *
- * Copyright (C) 2010 Martin Michlmayr <tbm@cyrius.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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <sound/alc5623.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition hp_t5325_partitions[] = {
- {
- .name = "u-boot env",
- .size = SZ_64K,
- .offset = SZ_512K + SZ_256K,
- },
- {
- .name = "permanent u-boot env",
- .size = SZ_64K,
- .offset = MTDPART_OFS_APPEND,
- .mask_flags = MTD_WRITEABLE,
- },
- {
- .name = "HP env",
- .size = SZ_64K,
- .offset = MTDPART_OFS_APPEND,
- },
- {
- .name = "u-boot",
- .size = SZ_512K,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE,
- },
- {
- .name = "SSD firmware",
- .size = SZ_256K,
- .offset = SZ_512K,
- },
-};
-
-static const struct flash_platform_data hp_t5325_flash = {
- .type = "mx25l8005",
- .name = "spi_flash",
- .parts = hp_t5325_partitions,
- .nr_parts = ARRAY_SIZE(hp_t5325_partitions),
-};
-
-static struct spi_board_info __initdata hp_t5325_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &hp_t5325_flash,
- .irq = -1,
- },
-};
-
-static struct mv643xx_eth_platform_data hp_t5325_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data hp_t5325_sata_data = {
- .n_ports = 2,
-};
-
-static struct gpio_keys_button hp_t5325_buttons[] = {
- {
- .code = KEY_POWER,
- .gpio = 45,
- .desc = "Power",
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data hp_t5325_button_data = {
- .buttons = hp_t5325_buttons,
- .nbuttons = ARRAY_SIZE(hp_t5325_buttons),
-};
-
-static struct platform_device hp_t5325_button_device = {
- .name = "gpio-keys",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &hp_t5325_button_data,
- }
-};
-
-static struct platform_device hp_t5325_audio_device = {
- .name = "t5325-audio",
- .id = -1,
-};
-
-static unsigned int hp_t5325_mpp_config[] __initdata = {
- MPP0_NF_IO2,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP4_NF_IO6,
- MPP5_NF_IO7,
- MPP6_SYSRST_OUTn,
- MPP7_SPI_SCn,
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP12_SD_CLK,
- MPP13_GPIO,
- MPP14_GPIO,
- MPP15_GPIO,
- MPP16_GPIO,
- MPP17_GPIO,
- MPP18_NF_IO0,
- MPP19_NF_IO1,
- MPP20_GPIO,
- MPP21_GPIO,
- MPP22_GPIO,
- MPP23_GPIO,
- MPP32_GPIO,
- MPP33_GE1_TXCTL,
- MPP39_AU_I2SBCLK,
- MPP40_AU_I2SDO,
- MPP43_AU_I2SDI,
- MPP41_AU_I2SLRCLK,
- MPP42_AU_I2SMCLK,
- MPP45_GPIO, /* Power button */
- MPP48_GPIO, /* Board power off */
- 0
-};
-
-static struct alc5623_platform_data alc5621_data = {
- .add_ctrl = 0x3700,
- .jack_det_ctrl = 0x4810,
-};
-
-static struct i2c_board_info i2c_board_info[] __initdata = {
- {
- I2C_BOARD_INFO("alc5621", 0x1a),
- .platform_data = &alc5621_data,
- },
-};
-
-#define HP_T5325_GPIO_POWER_OFF 48
-
-static void hp_t5325_power_off(void)
-{
- gpio_set_value(HP_T5325_GPIO_POWER_OFF, 1);
-}
-
-static void __init hp_t5325_init(void)
-{
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(hp_t5325_mpp_config);
-
- kirkwood_uart0_init();
- spi_register_board_info(hp_t5325_spi_slave_info,
- ARRAY_SIZE(hp_t5325_spi_slave_info));
- kirkwood_spi_init();
- kirkwood_i2c_init();
- kirkwood_ge00_init(&hp_t5325_ge00_data);
- kirkwood_sata_init(&hp_t5325_sata_data);
- kirkwood_ehci_init();
- platform_device_register(&hp_t5325_button_device);
- platform_device_register(&hp_t5325_audio_device);
-
- i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
- kirkwood_audio_init();
-
- if (gpio_request(HP_T5325_GPIO_POWER_OFF, "power-off") == 0 &&
- gpio_direction_output(HP_T5325_GPIO_POWER_OFF, 0) == 0)
- pm_power_off = hp_t5325_power_off;
- else
- pr_err("t5325: failed to configure power-off GPIO\n");
-}
-
-static int __init hp_t5325_pci_init(void)
-{
- if (machine_is_t5325())
- kirkwood_pcie_init(KW_PCIE0);
-
- return 0;
-}
-subsys_initcall(hp_t5325_pci_init);
-
-MACHINE_START(T5325, "HP t5325 Thin Client")
- /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .atag_offset = 0x100,
- .init_machine = hp_t5325_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
deleted file mode 100644
index e1267d6b468f..000000000000
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *
- * QNAP TS-11x/TS-21x Turbo NAS Board Setup
- *
- * Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com>
- * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-#include "tsx1x-common.h"
-
-static struct i2c_board_info __initdata qnap_ts219_i2c_rtc = {
- I2C_BOARD_INFO("s35390a", 0x30),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data qnap_ts219_sata_data = {
- .n_ports = 2,
-};
-
-static struct gpio_keys_button qnap_ts219_buttons[] = {
- {
- .code = KEY_COPY,
- .gpio = 15,
- .desc = "USB Copy",
- .active_low = 1,
- },
- {
- .code = KEY_RESTART,
- .gpio = 16,
- .desc = "Reset",
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data qnap_ts219_button_data = {
- .buttons = qnap_ts219_buttons,
- .nbuttons = ARRAY_SIZE(qnap_ts219_buttons),
-};
-
-static struct platform_device qnap_ts219_button_device = {
- .name = "gpio-keys",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &qnap_ts219_button_data,
- }
-};
-
-static unsigned int qnap_ts219_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP4_SATA1_ACTn,
- MPP5_SATA0_ACTn,
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP13_UART1_TXD, /* PIC controller */
- MPP14_UART1_RXD, /* PIC controller */
- MPP15_GPIO, /* USB Copy button (on devices with 88F6281) */
- MPP16_GPIO, /* Reset button (on devices with 88F6281) */
- MPP36_GPIO, /* RAM: 0: 256 MB, 1: 512 MB */
- MPP37_GPIO, /* Reset button (on devices with 88F6282) */
- MPP43_GPIO, /* USB Copy button (on devices with 88F6282) */
- MPP44_GPIO, /* Board ID: 0: TS-11x, 1: TS-21x */
- 0
-};
-
-static void __init qnap_ts219_init(void)
-{
- u32 dev, rev;
-
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(qnap_ts219_mpp_config);
-
- kirkwood_uart0_init();
- kirkwood_uart1_init(); /* A PIC controller is connected here. */
- qnap_tsx1x_register_flash();
- kirkwood_i2c_init();
- i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
-
- kirkwood_pcie_id(&dev, &rev);
- if (dev == MV88F6282_DEV_ID) {
- qnap_ts219_buttons[0].gpio = 43; /* USB Copy button */
- qnap_ts219_buttons[1].gpio = 37; /* Reset button */
- qnap_ts219_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
- }
-
- kirkwood_ge00_init(&qnap_ts219_ge00_data);
- kirkwood_sata_init(&qnap_ts219_sata_data);
- kirkwood_ehci_init();
- platform_device_register(&qnap_ts219_button_device);
-
- pm_power_off = qnap_tsx1x_power_off;
-
-}
-
-static int __init ts219_pci_init(void)
-{
- if (machine_is_ts219())
- kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
-
- return 0;
-}
-subsys_initcall(ts219_pci_init);
-
-MACHINE_START(TS219, "QNAP TS-119/TS-219")
- /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .atag_offset = 0x100,
- .init_machine = qnap_ts219_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
deleted file mode 100644
index 81d585806b2f..000000000000
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *
- * QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS Board Setup
- *
- * Copyright (C) 2009-2010 Martin Michlmayr <tbm@cyrius.com>
- * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "mpp.h"
-#include "tsx1x-common.h"
-
-/* for the PCIe reset workaround */
-#include <plat/pcie.h>
-
-
-#define QNAP_TS41X_JUMPER_JP1 45
-
-static struct i2c_board_info __initdata qnap_ts41x_i2c_rtc = {
- I2C_BOARD_INFO("s35390a", 0x30),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts41x_ge00_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv643xx_eth_platform_data qnap_ts41x_ge01_data = {
- .phy_addr = MV643XX_ETH_PHY_ADDR(0),
-};
-
-static struct mv_sata_platform_data qnap_ts41x_sata_data = {
- .n_ports = 2,
-};
-
-static struct gpio_keys_button qnap_ts41x_buttons[] = {
- {
- .code = KEY_COPY,
- .gpio = 43,
- .desc = "USB Copy",
- .active_low = 1,
- },
- {
- .code = KEY_RESTART,
- .gpio = 37,
- .desc = "Reset",
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data qnap_ts41x_button_data = {
- .buttons = qnap_ts41x_buttons,
- .nbuttons = ARRAY_SIZE(qnap_ts41x_buttons),
-};
-
-static struct platform_device qnap_ts41x_button_device = {
- .name = "gpio-keys",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &qnap_ts41x_button_data,
- }
-};
-
-static unsigned int qnap_ts41x_mpp_config[] __initdata = {
- MPP0_SPI_SCn,
- MPP1_SPI_MOSI,
- MPP2_SPI_SCK,
- MPP3_SPI_MISO,
- MPP6_SYSRST_OUTn,
- MPP7_PEX_RST_OUTn,
- MPP8_TW0_SDA,
- MPP9_TW0_SCK,
- MPP10_UART0_TXD,
- MPP11_UART0_RXD,
- MPP13_UART1_TXD, /* PIC controller */
- MPP14_UART1_RXD, /* PIC controller */
- MPP15_SATA0_ACTn,
- MPP16_SATA1_ACTn,
- MPP20_GE1_TXD0,
- MPP21_GE1_TXD1,
- MPP22_GE1_TXD2,
- MPP23_GE1_TXD3,
- MPP24_GE1_RXD0,
- MPP25_GE1_RXD1,
- MPP26_GE1_RXD2,
- MPP27_GE1_RXD3,
- MPP30_GE1_RXCTL,
- MPP31_GE1_RXCLK,
- MPP32_GE1_TCLKOUT,
- MPP33_GE1_TXCTL,
- MPP36_GPIO, /* RAM: 0: 256 MB, 1: 512 MB */
- MPP37_GPIO, /* Reset button */
- MPP43_GPIO, /* USB Copy button */
- MPP44_GPIO, /* Board ID: 0: TS-419U, 1: TS-419 */
- MPP45_GPIO, /* JP1: 0: LCD, 1: serial console */
- MPP46_GPIO, /* External SATA HDD1 error indicator */
- MPP47_GPIO, /* External SATA HDD2 error indicator */
- MPP48_GPIO, /* External SATA HDD3 error indicator */
- MPP49_GPIO, /* External SATA HDD4 error indicator */
- 0
-};
-
-static void __init qnap_ts41x_init(void)
-{
- u32 dev, rev;
-
- /*
- * Basic setup. Needs to be called early.
- */
- kirkwood_init();
- kirkwood_mpp_conf(qnap_ts41x_mpp_config);
-
- kirkwood_uart0_init();
- kirkwood_uart1_init(); /* A PIC controller is connected here. */
- qnap_tsx1x_register_flash();
- kirkwood_i2c_init();
- i2c_register_board_info(0, &qnap_ts41x_i2c_rtc, 1);
-
- kirkwood_pcie_id(&dev, &rev);
- if (dev == MV88F6282_DEV_ID) {
- qnap_ts41x_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
- qnap_ts41x_ge01_data.phy_addr = MV643XX_ETH_PHY_ADDR(1);
- }
- kirkwood_ge00_init(&qnap_ts41x_ge00_data);
- kirkwood_ge01_init(&qnap_ts41x_ge01_data);
-
- kirkwood_sata_init(&qnap_ts41x_sata_data);
- kirkwood_ehci_init();
- platform_device_register(&qnap_ts41x_button_device);
-
- pm_power_off = qnap_tsx1x_power_off;
-
- if (gpio_request(QNAP_TS41X_JUMPER_JP1, "JP1") == 0)
- gpio_export(QNAP_TS41X_JUMPER_JP1, 0);
-}
-
-static int __init ts41x_pci_init(void)
-{
- if (machine_is_ts41x()) {
- u32 dev, rev;
-
- /*
- * Without this explicit reset, the PCIe SATA controller
- * (Marvell 88sx7042/sata_mv) is known to stop working
- * after a few minutes.
- */
- orion_pcie_reset(PCIE_VIRT_BASE);
-
- kirkwood_pcie_id(&dev, &rev);
- if (dev == MV88F6282_DEV_ID)
- kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
- else
- kirkwood_pcie_init(KW_PCIE0);
- }
- return 0;
-}
-subsys_initcall(ts41x_pci_init);
-
-MACHINE_START(TS41X, "QNAP TS-41x")
- /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
- .atag_offset = 0x100,
- .init_machine = qnap_ts41x_init,
- .map_io = kirkwood_map_io,
- .init_early = kirkwood_init_early,
- .init_irq = kirkwood_init_irq,
- .init_time = kirkwood_timer_init,
- .restart = kirkwood_restart,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/tsx1x-common.c b/arch/arm/mach-kirkwood/tsx1x-common.c
deleted file mode 100644
index cec87cef76ca..000000000000
--- a/arch/arm/mach-kirkwood/tsx1x-common.c
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/serial_reg.h>
-#include <mach/kirkwood.h>
-#include "common.h"
-#include "tsx1x-common.h"
-
-/*
- * QNAP TS-x1x Boards flash
- */
-
-/****************************************************************************
- * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the
- * partitions on the device because we want to keep compatibility with
- * the QNAP firmware.
- * Layout as used by QNAP:
- * 0x00000000-0x00080000 : "U-Boot"
- * 0x00200000-0x00400000 : "Kernel"
- * 0x00400000-0x00d00000 : "RootFS"
- * 0x00d00000-0x01000000 : "RootFS2"
- * 0x00080000-0x000c0000 : "U-Boot Config"
- * 0x000c0000-0x00200000 : "NAS Config"
- *
- * We'll use "RootFS1" instead of "RootFS" to stay compatible with the layout
- * used by the QNAP TS-109/TS-209.
- *
- ***************************************************************************/
-
-static struct mtd_partition qnap_tsx1x_partitions[] = {
- {
- .name = "U-Boot",
- .size = 0x00080000,
- .offset = 0,
- .mask_flags = MTD_WRITEABLE,
- }, {
- .name = "Kernel",
- .size = 0x00200000,
- .offset = 0x00200000,
- }, {
- .name = "RootFS1",
- .size = 0x00900000,
- .offset = 0x00400000,
- }, {
- .name = "RootFS2",
- .size = 0x00300000,
- .offset = 0x00d00000,
- }, {
- .name = "U-Boot Config",
- .size = 0x00040000,
- .offset = 0x00080000,
- }, {
- .name = "NAS Config",
- .size = 0x00140000,
- .offset = 0x000c0000,
- },
-};
-
-static const struct flash_platform_data qnap_tsx1x_flash = {
- .type = "m25p128",
- .name = "spi_flash",
- .parts = qnap_tsx1x_partitions,
- .nr_parts = ARRAY_SIZE(qnap_tsx1x_partitions),
-};
-
-static struct spi_board_info __initdata qnap_tsx1x_spi_slave_info[] = {
- {
- .modalias = "m25p80",
- .platform_data = &qnap_tsx1x_flash,
- .irq = -1,
- .max_speed_hz = 20000000,
- .bus_num = 0,
- .chip_select = 0,
- },
-};
-
-void __init qnap_tsx1x_register_flash(void)
-{
- spi_register_board_info(qnap_tsx1x_spi_slave_info,
- ARRAY_SIZE(qnap_tsx1x_spi_slave_info));
- kirkwood_spi_init();
-}
-
-
-/*****************************************************************************
- * QNAP TS-x1x specific power off method via UART1-attached PIC
- ****************************************************************************/
-
-#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
-
-void qnap_tsx1x_power_off(void)
-{
- /* 19200 baud divisor */
- const unsigned divisor = ((kirkwood_tclk + (8 * 19200)) / (16 * 19200));
-
- pr_info("%s: triggering power-off...\n", __func__);
-
- /* hijack UART1 and reset into sane state (19200,8n1) */
- writel(0x83, UART1_REG(LCR));
- writel(divisor & 0xff, UART1_REG(DLL));
- writel((divisor >> 8) & 0xff, UART1_REG(DLM));
- writel(0x03, UART1_REG(LCR));
- writel(0x00, UART1_REG(IER));
- writel(0x00, UART1_REG(FCR));
- writel(0x00, UART1_REG(MCR));
-
- /* send the power-off command 'A' to PIC */
- writel('A', UART1_REG(TX));
-}
-
diff --git a/arch/arm/mach-kirkwood/tsx1x-common.h b/arch/arm/mach-kirkwood/tsx1x-common.h
deleted file mode 100644
index 7fa037361b55..000000000000
--- a/arch/arm/mach-kirkwood/tsx1x-common.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ARCH_KIRKWOOD_TSX1X_COMMON_H
-#define __ARCH_KIRKWOOD_TSX1X_COMMON_H
-
-extern void __init qnap_tsx1x_register_flash(void);
-extern void qnap_tsx1x_power_off(void);
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
index 95e731a7ed6a..ab0d27fa8969 100644
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ b/arch/arm/mach-ks8695/include/mach/memory.h
@@ -15,11 +15,6 @@
#include <mach/hardware.h>
-/*
- * Physical SRAM offset.
- */
-#define PLAT_PHYS_OFFSET KS8695_SDRAM_PA
-
#ifndef __ASSEMBLY__
#ifdef CONFIG_PCI
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
new file mode 100644
index 000000000000..2c043a210db0
--- /dev/null
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -0,0 +1,6 @@
+config ARCH_MEDIATEK
+ bool "Mediatek MT6589 SoC" if ARCH_MULTI_V7
+ select ARM_GIC
+ select MTK_TIMER
+ help
+ Support for Mediatek Cortex-A7 Quad-Core-SoC MT6589.
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
new file mode 100644
index 000000000000..43e619f56172
--- /dev/null
+++ b/arch/arm/mach-mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
diff --git a/arch/arm/mach-s5pc100/include/mach/dma.h b/arch/arm/mach-mediatek/mediatek.c
index 201842a3769e..f2acf075350d 100644
--- a/arch/arm/mach-s5pc100/include/mach/dma.h
+++ b/arch/arm/mach-mediatek/mediatek.c
@@ -1,6 +1,8 @@
/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Device Tree support for Mediatek SoCs
+ *
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Matthias Brugger <matthias.bgg@gmail.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
@@ -11,16 +13,15 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/init.h>
+#include <asm/mach/arch.h>
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common DMA API driver for PL330 */
-#include <plat/dma-pl330.h>
+static const char * const mediatek_board_dt_compat[] = {
+ "mediatek,mt6589",
+ NULL,
+};
-#endif /* __MACH_DMA_H */
+DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+ .dt_compat = mediatek_board_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
index fbd7ee8e4897..8c78f2b16452 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
@@ -23,7 +23,6 @@
#define SM_nCS0_nCS0 MFP_CFG(SM_nCS0, AF0)
#define SM_ADV_SM_ADV MFP_CFG(SM_ADV, AF0)
#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0)
-#define SM_SCLK_SM_SCLK MFP_CFG(SM_SCLK, AF0)
#define SM_BE0_SM_BE0 MFP_CFG(SM_BE0, AF1)
#define SM_BE1_SM_BE1 MFP_CFG(SM_BE1, AF1)
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 9b26976fb084..a6b50e62a495 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -106,7 +106,4 @@ config MSM_GPIOMUX
help
Support for MSM V1 TLMM GPIOMUX architecture.
-config MSM_SCM
- bool
-
endif
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index b9bc599a5fd0..c1e4567a5ab3 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -14,11 +14,15 @@ menuconfig ARCH_MVEBU
if ARCH_MVEBU
+config MACH_MVEBU_ANY
+ bool
+
config MACH_MVEBU_V7
bool
select ARMADA_370_XP_TIMER
select CACHE_L2X0
select ARM_CPU_SUSPEND
+ select MACH_MVEBU_ANY
config MACH_ARMADA_370
bool "Marvell Armada 370 boards" if ARCH_MULTI_V7
@@ -75,6 +79,7 @@ config MACH_DOVE
select CACHE_L2X0
select CPU_PJ4
select DOVE_CLK
+ select MACH_MVEBU_ANY
select ORION_IRQCHIP
select ORION_TIMER
select PINCTRL_DOVE
@@ -87,6 +92,7 @@ config MACH_KIRKWOOD
select ARCH_REQUIRE_GPIOLIB
select CPU_FEROCEON
select KIRKWOOD_CLK
+ select MACH_MVEBU_ANY
select ORION_IRQCHIP
select ORION_TIMER
select PCI
@@ -96,4 +102,11 @@ config MACH_KIRKWOOD
Say 'Y' here if you want your kernel to support boards based
on the Marvell Kirkwood device tree.
+config MACH_NETXBIG
+ bool "LaCie 2Big and 5Big Network v2"
+ depends on MACH_KIRKWOOD
+ help
+ Say 'Y' here if you want your kernel to support the
+ LaCie 2Big and 5Big Network v2
+
endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 1636cdbef01a..e24136b42765 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -4,13 +4,13 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
CFLAGS_pmsu.o := -march=armv7-a
-obj-y += system-controller.o mvebu-soc-id.o
+obj-$(CONFIG_MACH_MVEBU_ANY) += system-controller.o mvebu-soc-id.o
ifeq ($(CONFIG_MACH_MVEBU_V7),y)
obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
-obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o
+obj-$(CONFIG_MACH_NETXBIG) += netxbig.o
diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h
index c3465f5b1250..84cd90d9b860 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.h
+++ b/arch/arm/mach-mvebu/armada-370-xp.h
@@ -24,4 +24,6 @@ void armada_xp_secondary_startup(void);
extern struct smp_operations armada_xp_smp_ops;
#endif
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
+
#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index b2524d689f21..6478626e3ff6 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -34,14 +34,14 @@
#include "coherency.h"
#include "mvebu-soc-id.h"
+static void __iomem *scu_base;
+
/*
* Enables the SCU when available. Obviously, this is only useful on
* Cortex-A based SOCs, not on PJ4B based ones.
*/
static void __init mvebu_scu_enable(void)
{
- void __iomem *scu_base;
-
struct device_node *np =
of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
if (np) {
@@ -51,6 +51,11 @@ static void __init mvebu_scu_enable(void)
}
}
+void __iomem *mvebu_get_scu_base(void)
+{
+ return scu_base;
+}
+
/*
* Early versions of Armada 375 SoC have a bug where the BootROM
* leaves an external data abort pending. The kernel is hit by this
@@ -125,8 +130,16 @@ static void __init thermal_quirk(void)
{
struct device_node *np;
u32 dev, rev;
+ int res;
- if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > ARMADA_375_Z1_REV)
+ /*
+ * The early SoC Z1 revision needs a quirk to be applied in order
+ * for the thermal controller to work properly. This quirk breaks
+ * the thermal support if applied on a SoC that doesn't need it,
+ * so we enforce the SoC revision to be known.
+ */
+ res = mvebu_get_soc_id(&dev, &rev);
+ if (res < 0 || (res == 0 && rev > ARMADA_375_Z1_REV))
return;
for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
@@ -160,7 +173,8 @@ static void __init thermal_quirk(void)
/*
* The thermal controller needs some quirk too, so let's change
- * the compatible string to reflect this.
+ * the compatible string to reflect this and allow the driver
+ * the take the necessary action.
*/
prop = kzalloc(sizeof(*prop), GFP_KERNEL);
prop->name = kstrdup("compatible", GFP_KERNEL);
diff --git a/arch/arm/mach-mvebu/board.h b/arch/arm/mach-mvebu/board.h
index 9c7bb4386f8b..98e32cc2ef3d 100644
--- a/arch/arm/mach-mvebu/board.h
+++ b/arch/arm/mach-mvebu/board.h
@@ -13,4 +13,9 @@
#ifndef __ARCH_MVEBU_BOARD_H
#define __ARCH_MVEBU_BOARD_H
+#ifdef CONFIG_MACH_NETXBIG
+void netxbig_init(void);
+#else
+static inline void netxbig_init(void) {};
+#endif
#endif
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S
index 510c29e079ca..f5d881b5d0f7 100644
--- a/arch/arm/mach-mvebu/coherency_ll.S
+++ b/arch/arm/mach-mvebu/coherency_ll.S
@@ -46,7 +46,7 @@ ENTRY(ll_get_coherency_base)
ldr r1, =coherency_base
ldr r1, [r1]
2:
- mov pc, lr
+ ret lr
ENDPROC(ll_get_coherency_base)
/*
@@ -63,7 +63,7 @@ ENTRY(ll_get_coherency_cpumask)
mov r2, #(1 << 24)
lsl r3, r2, r3
ARM_BE8(rev r3, r3)
- mov pc, lr
+ ret lr
ENDPROC(ll_get_coherency_cpumask)
/*
@@ -94,7 +94,7 @@ ENTRY(ll_add_cpu_to_smp_group)
strex r1, r2, [r0]
cmp r1, #0
bne 1b
- mov pc, lr
+ ret lr
ENDPROC(ll_add_cpu_to_smp_group)
ENTRY(ll_enable_coherency)
@@ -118,7 +118,7 @@ ENTRY(ll_enable_coherency)
bne 1b
dsb
mov r0, #0
- mov pc, lr
+ ret lr
ENDPROC(ll_enable_coherency)
ENTRY(ll_disable_coherency)
@@ -141,7 +141,7 @@ ENTRY(ll_disable_coherency)
cmp r1, #0
bne 1b
dsb
- mov pc, lr
+ ret lr
ENDPROC(ll_disable_coherency)
.align 2
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
index b67fb7a10d8b..3ccb40c3bf94 100644
--- a/arch/arm/mach-mvebu/common.h
+++ b/arch/arm/mach-mvebu/common.h
@@ -21,7 +21,8 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd);
int mvebu_cpu_reset_deassert(int cpu);
void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr);
void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr);
+int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
-void armada_xp_cpu_die(unsigned int cpu);
+void __iomem *mvebu_get_scu_base(void);
#endif
diff --git a/arch/arm/mach-mvebu/cpu-reset.c b/arch/arm/mach-mvebu/cpu-reset.c
index 4a8f9eebebea..60fb53787004 100644
--- a/arch/arm/mach-mvebu/cpu-reset.c
+++ b/arch/arm/mach-mvebu/cpu-reset.c
@@ -67,7 +67,7 @@ static int mvebu_cpu_reset_map(struct device_node *np, int res_idx)
return 0;
}
-int __init mvebu_cpu_reset_init(void)
+static int __init mvebu_cpu_reset_init(void)
{
struct device_node *np;
int res_idx;
diff --git a/arch/arm/mach-mvebu/headsmp-a9.S b/arch/arm/mach-mvebu/headsmp-a9.S
index da5bb292b91c..be51c998c0cd 100644
--- a/arch/arm/mach-mvebu/headsmp-a9.S
+++ b/arch/arm/mach-mvebu/headsmp-a9.S
@@ -18,21 +18,6 @@
#include <asm/assembler.h>
__CPUINIT
-#define CPU_RESUME_ADDR_REG 0xf10182d4
-
-.global armada_375_smp_cpu1_enable_code_start
-.global armada_375_smp_cpu1_enable_code_end
-
-armada_375_smp_cpu1_enable_code_start:
-ARM_BE8(setend be)
- adr r0, 1f
- ldr r0, [r0]
- ldr r1, [r0]
-ARM_BE8(rev r1, r1)
- mov pc, r1
-1:
- .word CPU_RESUME_ADDR_REG
-armada_375_smp_cpu1_enable_code_end:
ENTRY(mvebu_cortex_a9_secondary_startup)
ARM_BE8(setend be)
diff --git a/arch/arm/mach-mvebu/hotplug.c b/arch/arm/mach-mvebu/hotplug.c
deleted file mode 100644
index d95e91047168..000000000000
--- a/arch/arm/mach-mvebu/hotplug.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Symmetric Multi Processing (SMP) support for Armada XP
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <asm/proc-fns.h>
-#include "common.h"
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void __ref armada_xp_cpu_die(unsigned int cpu)
-{
- cpu_do_idle();
-
- /* We should never return from idle */
- panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
-}
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index 46f105913c84..6b5310828eb2 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -180,6 +180,9 @@ static void __init kirkwood_dt_init(void)
kirkwood_pm_init();
kirkwood_dt_eth_fixup();
+ if (of_machine_is_compatible("lacie,netxbig"))
+ netxbig_init();
+
of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
}
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c
index d0f35b4d4a23..a99434bcee84 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.c
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.c
@@ -25,6 +25,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
+#include "common.h"
#include "mvebu-soc-id.h"
#define PCIE_DEV_ID_OFF 0x0
@@ -51,10 +52,10 @@ int mvebu_get_soc_id(u32 *dev, u32 *rev)
*rev = soc_rev;
return 0;
} else
- return -1;
+ return -ENODEV;
}
-static int __init mvebu_soc_id_init(void)
+static int __init get_soc_id_by_pci(void)
{
struct device_node *np;
int ret = 0;
@@ -129,6 +130,22 @@ clk_err:
return ret;
}
+
+static int __init mvebu_soc_id_init(void)
+{
+
+ /*
+ * First try to get the ID and the revision by the system
+ * register and use PCI registers only if it is not possible
+ */
+ if (!mvebu_system_controller_get_soc_id(&soc_dev_id, &soc_rev)) {
+ is_id_valid = true;
+ pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
+ return 0;
+ }
+
+ return get_soc_id_by_pci();
+}
early_initcall(mvebu_soc_id_init);
static int __init mvebu_soc_device(void)
diff --git a/arch/arm/mach-mvebu/netxbig.c b/arch/arm/mach-mvebu/netxbig.c
new file mode 100644
index 000000000000..94b11b6585a4
--- /dev/null
+++ b/arch/arm/mach-mvebu/netxbig.c
@@ -0,0 +1,191 @@
+/*
+ * arch/arm/mach-mvbu/board-netxbig.c
+ *
+ * LaCie 2Big and 5Big Network v2 board setup
+ *
+ * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/leds-kirkwood-netxbig.h>
+#include "common.h"
+
+/*****************************************************************************
+ * GPIO extension LEDs
+ ****************************************************************************/
+
+/*
+ * The LEDs are controlled by a CPLD and can be configured through a GPIO
+ * extension bus:
+ *
+ * - address register : bit [0-2] -> GPIO [47-49]
+ * - data register : bit [0-2] -> GPIO [44-46]
+ * - enable register : GPIO 29
+ */
+
+static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
+static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
+
+static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
+ .addr = netxbig_v2_gpio_ext_addr,
+ .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
+ .data = netxbig_v2_gpio_ext_data,
+ .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
+ .enable = 29,
+};
+
+/*
+ * Address register selection:
+ *
+ * addr | register
+ * ----------------------------
+ * 0 | front LED
+ * 1 | front LED brightness
+ * 2 | SATA LED brightness
+ * 3 | SATA0 LED
+ * 4 | SATA1 LED
+ * 5 | SATA2 LED
+ * 6 | SATA3 LED
+ * 7 | SATA4 LED
+ *
+ * Data register configuration:
+ *
+ * data | LED brightness
+ * -------------------------------------------------
+ * 0 | min (off)
+ * - | -
+ * 7 | max
+ *
+ * data | front LED mode
+ * -------------------------------------------------
+ * 0 | fix off
+ * 1 | fix blue on
+ * 2 | fix red on
+ * 3 | blink blue on=1 sec and blue off=1 sec
+ * 4 | blink red on=1 sec and red off=1 sec
+ * 5 | blink blue on=2.5 sec and red on=0.5 sec
+ * 6 | blink blue on=1 sec and red on=1 sec
+ * 7 | blink blue on=0.5 sec and blue off=2.5 sec
+ *
+ * data | SATA LED mode
+ * -------------------------------------------------
+ * 0 | fix off
+ * 1 | SATA activity blink
+ * 2 | fix red on
+ * 3 | blink blue on=1 sec and blue off=1 sec
+ * 4 | blink red on=1 sec and red off=1 sec
+ * 5 | blink blue on=2.5 sec and red on=0.5 sec
+ * 6 | blink blue on=1 sec and red on=1 sec
+ * 7 | fix blue on
+ */
+
+static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 2,
+ [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
+ [NETXBIG_LED_TIMER1] = 4,
+ [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
+};
+
+static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 1,
+ [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
+ [NETXBIG_LED_TIMER1] = 3,
+ [NETXBIG_LED_TIMER2] = 7,
+};
+
+static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
+ [NETXBIG_LED_OFF] = 0,
+ [NETXBIG_LED_ON] = 7,
+ [NETXBIG_LED_SATA] = 1,
+ [NETXBIG_LED_TIMER1] = 3,
+ [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
+};
+
+static struct netxbig_led_timer netxbig_v2_led_timer[] = {
+ [0] = {
+ .delay_on = 500,
+ .delay_off = 500,
+ .mode = NETXBIG_LED_TIMER1,
+ },
+ [1] = {
+ .delay_on = 500,
+ .delay_off = 1000,
+ .mode = NETXBIG_LED_TIMER2,
+ },
+};
+
+#define NETXBIG_LED(_name, maddr, mval, baddr) \
+ { .name = _name, \
+ .mode_addr = maddr, \
+ .mode_val = mval, \
+ .bright_addr = baddr }
+
+static struct netxbig_led net2big_v2_leds_ctrl[] = {
+ NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
+ NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
+ NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
+};
+
+static struct netxbig_led_platform_data net2big_v2_leds_data = {
+ .gpio_ext = &netxbig_v2_gpio_ext,
+ .timer = netxbig_v2_led_timer,
+ .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
+ .leds = net2big_v2_leds_ctrl,
+ .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
+};
+
+static struct netxbig_led net5big_v2_leds_ctrl[] = {
+ NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
+ NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
+ NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
+ NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
+ NETXBIG_LED("net5big-v2:red:sata4", 7, netxbig_v2_red_mled, 2),
+};
+
+static struct netxbig_led_platform_data net5big_v2_leds_data = {
+ .gpio_ext = &netxbig_v2_gpio_ext,
+ .timer = netxbig_v2_led_timer,
+ .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
+ .leds = net5big_v2_leds_ctrl,
+ .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
+};
+
+static struct platform_device netxbig_v2_leds = {
+ .name = "leds-netxbig",
+ .id = -1,
+ .dev = {
+ .platform_data = &net2big_v2_leds_data,
+ },
+};
+
+void __init netxbig_init(void)
+{
+
+ if (of_machine_is_compatible("lacie,net5big_v2"))
+ netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
+ platform_device_register(&netxbig_v2_leds);
+}
diff --git a/arch/arm/mach-mvebu/platsmp-a9.c b/arch/arm/mach-mvebu/platsmp-a9.c
index 96c2c59e34b6..47a71a924b96 100644
--- a/arch/arm/mach-mvebu/platsmp-a9.c
+++ b/arch/arm/mach-mvebu/platsmp-a9.c
@@ -20,33 +20,8 @@
#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
#include "common.h"
-#include "mvebu-soc-id.h"
#include "pmsu.h"
-#define CRYPT0_ENG_ID 41
-#define CRYPT0_ENG_ATTR 0x1
-#define SRAM_PHYS_BASE 0xFFFF0000
-
-#define BOOTROM_BASE 0xFFF00000
-#define BOOTROM_SIZE 0x100000
-
-extern unsigned char armada_375_smp_cpu1_enable_code_end;
-extern unsigned char armada_375_smp_cpu1_enable_code_start;
-
-void armada_375_smp_cpu1_enable_wa(void)
-{
- void __iomem *sram_virt_base;
-
- mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
- mvebu_mbus_add_window_by_id(CRYPT0_ENG_ID, CRYPT0_ENG_ATTR,
- SRAM_PHYS_BASE, SZ_64K);
- sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K);
-
- memcpy(sram_virt_base, &armada_375_smp_cpu1_enable_code_start,
- &armada_375_smp_cpu1_enable_code_end
- - &armada_375_smp_cpu1_enable_code_start);
-}
-
extern void mvebu_cortex_a9_secondary_startup(void);
static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
@@ -63,21 +38,10 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
* address.
*/
hw_cpu = cpu_logical_map(cpu);
-
- if (of_machine_is_compatible("marvell,armada375")) {
- u32 dev, rev;
-
- if (mvebu_get_soc_id(&dev, &rev) == 0 &&
- rev == ARMADA_375_Z1_REV)
- armada_375_smp_cpu1_enable_wa();
-
+ if (of_machine_is_compatible("marvell,armada375"))
mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup);
- }
- else {
- mvebu_pmsu_set_cpu_boot_addr(hw_cpu,
- mvebu_cortex_a9_secondary_startup);
- }
-
+ else
+ mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup);
smp_wmb();
ret = mvebu_cpu_reset_deassert(hw_cpu);
if (ret) {
@@ -91,9 +55,6 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
.smp_boot_secondary = mvebu_cortex_a9_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
- .cpu_die = armada_xp_cpu_die,
-#endif
};
CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index 88b976b31719..895dc373c8a1 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -67,6 +67,7 @@ static void __init set_secondary_cpus_clock(void)
if (!cpu_clk)
return;
clk_set_rate(cpu_clk, rate);
+ clk_prepare_enable(cpu_clk);
}
}
@@ -78,6 +79,17 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
hw_cpu = cpu_logical_map(cpu);
mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
+
+ /*
+ * This is needed to wake up CPUs in the offline state after
+ * using CPU hotplug.
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ /*
+ * This is needed to take secondary CPUs out of reset on the
+ * initial boot.
+ */
ret = mvebu_cpu_reset_deassert(hw_cpu);
if (ret) {
pr_warn("unable to boot CPU: %d\n", ret);
@@ -87,6 +99,19 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
return 0;
}
+/*
+ * When a CPU is brought back online, either through CPU hotplug, or
+ * because of the boot of a kexec'ed kernel, the PMSU configuration
+ * for this CPU might be in the deep idle state, preventing this CPU
+ * from receiving interrupts. Here, we therefore take out the current
+ * CPU from this state, which was entered by armada_xp_cpu_die()
+ * below.
+ */
+static void armada_xp_secondary_init(unsigned int cpu)
+{
+ mvebu_v7_pmsu_idle_exit();
+}
+
static void __init armada_xp_smp_init_cpus(void)
{
unsigned int ncores = num_possible_cpus();
@@ -122,12 +147,36 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
panic("The address for the BootROM is incorrect");
}
+#ifdef CONFIG_HOTPLUG_CPU
+static void armada_xp_cpu_die(unsigned int cpu)
+{
+ /*
+ * CPU hotplug is implemented by putting offline CPUs into the
+ * deep idle sleep state.
+ */
+ armada_370_xp_pmsu_idle_enter(true);
+}
+
+/*
+ * We need a dummy function, so that platform_can_cpu_hotplug() knows
+ * we support CPU hotplug. However, the function does not need to do
+ * anything, because CPUs going offline can enter the deep idle state
+ * by themselves, without any help from a still alive CPU.
+ */
+static int armada_xp_cpu_kill(unsigned int cpu)
+{
+ return 1;
+}
+#endif
+
struct smp_operations armada_xp_smp_ops __initdata = {
.smp_init_cpus = armada_xp_smp_init_cpus,
.smp_prepare_cpus = armada_xp_smp_prepare_cpus,
.smp_boot_secondary = armada_xp_boot_secondary,
+ .smp_secondary_init = armada_xp_secondary_init,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = armada_xp_cpu_die,
+ .cpu_kill = armada_xp_cpu_kill,
#endif
};
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 25aa8237d668..8a70a51533fd 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -18,22 +18,29 @@
#define pr_fmt(fmt) "mvebu-pmsu: " fmt
+#include <linux/clk.h>
#include <linux/cpu_pm.h>
-#include <linux/kernel.h>
+#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/of_address.h>
#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mbus.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
-#include <linux/smp.h>
+#include <linux/pm_opp.h>
#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
+#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>
#include <asm/tlbflush.h>
#include "common.h"
+#include "armada-370-xp.h"
-static void __iomem *pmsu_mp_base;
#define PMSU_BASE_OFFSET 0x100
#define PMSU_REG_SIZE 0x1000
@@ -57,20 +64,45 @@ static void __iomem *pmsu_mp_base;
#define PMSU_STATUS_AND_MASK_IRQ_MASK BIT(24)
#define PMSU_STATUS_AND_MASK_FIQ_MASK BIT(25)
+#define PMSU_EVENT_STATUS_AND_MASK(cpu) ((cpu * 0x100) + 0x120)
+#define PMSU_EVENT_STATUS_AND_MASK_DFS_DONE BIT(1)
+#define PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK BIT(17)
+
#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x124)
/* PMSU fabric registers */
#define L2C_NFABRIC_PM_CTL 0x4
#define L2C_NFABRIC_PM_CTL_PWR_DOWN BIT(20)
+/* PMSU delay registers */
+#define PMSU_POWERDOWN_DELAY 0xF04
+#define PMSU_POWERDOWN_DELAY_PMU BIT(1)
+#define PMSU_POWERDOWN_DELAY_MASK 0xFFFE
+#define PMSU_DFLT_ARMADA38X_DELAY 0x64
+
+/* CA9 MPcore SoC Control registers */
+
+#define MPCORE_RESET_CTL 0x64
+#define MPCORE_RESET_CTL_L2 BIT(0)
+#define MPCORE_RESET_CTL_DEBUG BIT(16)
+
+#define SRAM_PHYS_BASE 0xFFFF0000
+#define BOOTROM_BASE 0xFFF00000
+#define BOOTROM_SIZE 0x100000
+
+#define ARMADA_370_CRYPT0_ENG_TARGET 0x9
+#define ARMADA_370_CRYPT0_ENG_ATTR 0x1
+
extern void ll_disable_coherency(void);
extern void ll_enable_coherency(void);
extern void armada_370_xp_cpu_resume(void);
+extern void armada_38x_cpu_resume(void);
-static struct platform_device armada_xp_cpuidle_device = {
- .name = "cpuidle-armada-370-xp",
-};
+static phys_addr_t pmsu_mp_phys_base;
+static void __iomem *pmsu_mp_base;
+
+static void *mvebu_cpu_resume;
static struct of_device_id of_pmsu_table[] = {
{ .compatible = "marvell,armada-370-pmsu", },
@@ -85,7 +117,49 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr)
PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
}
-static int __init armada_370_xp_pmsu_init(void)
+extern unsigned char mvebu_boot_wa_start;
+extern unsigned char mvebu_boot_wa_end;
+
+/*
+ * This function sets up the boot address workaround needed for SMP
+ * boot on Armada 375 Z1 and cpuidle on Armada 370. It unmaps the
+ * BootROM Mbus window, and instead remaps a crypto SRAM into which a
+ * custom piece of code is copied to replace the problematic BootROM.
+ */
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+ unsigned int crypto_eng_attribute,
+ phys_addr_t resume_addr_reg)
+{
+ void __iomem *sram_virt_base;
+ u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start;
+
+ mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
+ mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute,
+ SRAM_PHYS_BASE, SZ_64K);
+
+ sram_virt_base = ioremap(SRAM_PHYS_BASE, SZ_64K);
+ if (!sram_virt_base) {
+ pr_err("Unable to map SRAM to setup the boot address WA\n");
+ return -ENOMEM;
+ }
+
+ memcpy(sram_virt_base, &mvebu_boot_wa_start, code_len);
+
+ /*
+ * The last word of the code copied in SRAM must contain the
+ * physical base address of the PMSU register. We
+ * intentionally store this address in the native endianness
+ * of the system.
+ */
+ __raw_writel((unsigned long)resume_addr_reg,
+ sram_virt_base + code_len - 4);
+
+ iounmap(sram_virt_base);
+
+ return 0;
+}
+
+static int __init mvebu_v7_pmsu_init(void)
{
struct device_node *np;
struct resource res;
@@ -116,6 +190,8 @@ static int __init armada_370_xp_pmsu_init(void)
goto out;
}
+ pmsu_mp_phys_base = res.start;
+
pmsu_mp_base = ioremap(res.start, resource_size(&res));
if (!pmsu_mp_base) {
pr_err("unable to map registers\n");
@@ -129,7 +205,7 @@ static int __init armada_370_xp_pmsu_init(void)
return ret;
}
-static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
+static void mvebu_v7_pmsu_enable_l2_powerdown_onidle(void)
{
u32 reg;
@@ -142,14 +218,20 @@ static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL);
}
+enum pmsu_idle_prepare_flags {
+ PMSU_PREPARE_NORMAL = 0,
+ PMSU_PREPARE_DEEP_IDLE = BIT(0),
+ PMSU_PREPARE_SNOOP_DISABLE = BIT(1),
+};
+
/* No locking is needed because we only access per-CPU registers */
-void armada_370_xp_pmsu_idle_prepare(bool deepidle)
+static int mvebu_v7_pmsu_idle_prepare(unsigned long flags)
{
unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
u32 reg;
if (pmsu_mp_base == NULL)
- return;
+ return -EINVAL;
/*
* Adjust the PMSU configuration to wait for WFI signal, enable
@@ -167,22 +249,34 @@ void armada_370_xp_pmsu_idle_prepare(bool deepidle)
reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
/* ask HW to power down the L2 Cache if needed */
- if (deepidle)
+ if (flags & PMSU_PREPARE_DEEP_IDLE)
reg |= PMSU_CONTROL_AND_CONFIG_L2_PWDDN;
/* request power down */
reg |= PMSU_CONTROL_AND_CONFIG_PWDDN_REQ;
writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
- /* Disable snoop disable by HW - SW is taking care of it */
- reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
- reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
- writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+ if (flags & PMSU_PREPARE_SNOOP_DISABLE) {
+ /* Disable snoop disable by HW - SW is taking care of it */
+ reg = readl(pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+ reg |= PMSU_CPU_POWER_DOWN_DIS_SNP_Q_SKIP;
+ writel(reg, pmsu_mp_base + PMSU_CPU_POWER_DOWN_CONTROL(hw_cpu));
+ }
+
+ return 0;
}
-static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle)
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
{
- armada_370_xp_pmsu_idle_prepare(deepidle);
+ unsigned long flags = PMSU_PREPARE_SNOOP_DISABLE;
+ int ret;
+
+ if (deepidle)
+ flags |= PMSU_PREPARE_DEEP_IDLE;
+
+ ret = mvebu_v7_pmsu_idle_prepare(flags);
+ if (ret)
+ return ret;
v7_exit_coherency_flush(all);
@@ -208,25 +302,50 @@ static noinline int do_armada_370_xp_cpu_suspend(unsigned long deepidle)
"isb "
: : : "r0");
- pr_warn("Failed to suspend the system\n");
+ pr_debug("Failed to suspend the system\n");
return 0;
}
static int armada_370_xp_cpu_suspend(unsigned long deepidle)
{
- return cpu_suspend(deepidle, do_armada_370_xp_cpu_suspend);
+ return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
+}
+
+static int armada_38x_do_cpu_suspend(unsigned long deepidle)
+{
+ unsigned long flags = 0;
+
+ if (deepidle)
+ flags |= PMSU_PREPARE_DEEP_IDLE;
+
+ mvebu_v7_pmsu_idle_prepare(flags);
+ /*
+ * Already flushed cache, but do it again as the outer cache
+ * functions dirty the cache with spinlocks
+ */
+ v7_exit_coherency_flush(louis);
+
+ scu_power_mode(mvebu_get_scu_base(), SCU_PM_POWEROFF);
+
+ cpu_do_idle();
+
+ return 1;
+}
+
+static int armada_38x_cpu_suspend(unsigned long deepidle)
+{
+ return cpu_suspend(false, armada_38x_do_cpu_suspend);
}
/* No locking is needed because we only access per-CPU registers */
-static noinline void armada_370_xp_pmsu_idle_restore(void)
+void mvebu_v7_pmsu_idle_exit(void)
{
unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
u32 reg;
if (pmsu_mp_base == NULL)
return;
-
/* cancel ask HW to power down the L2 Cache if possible */
reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(hw_cpu));
reg &= ~PMSU_CONTROL_AND_CONFIG_L2_PWDDN;
@@ -241,53 +360,292 @@ static noinline void armada_370_xp_pmsu_idle_restore(void)
writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(hw_cpu));
}
-static int armada_370_xp_cpu_pm_notify(struct notifier_block *self,
+static int mvebu_v7_cpu_pm_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
if (action == CPU_PM_ENTER) {
unsigned int hw_cpu = cpu_logical_map(smp_processor_id());
- mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_370_xp_cpu_resume);
+ mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cpu_resume);
} else if (action == CPU_PM_EXIT) {
- armada_370_xp_pmsu_idle_restore();
+ mvebu_v7_pmsu_idle_exit();
}
return NOTIFY_OK;
}
-static struct notifier_block armada_370_xp_cpu_pm_notifier = {
- .notifier_call = armada_370_xp_cpu_pm_notify,
+static struct notifier_block mvebu_v7_cpu_pm_notifier = {
+ .notifier_call = mvebu_v7_cpu_pm_notify,
};
-int __init armada_370_xp_cpu_pm_init(void)
+static struct platform_device mvebu_v7_cpuidle_device;
+
+static __init int armada_370_cpuidle_init(void)
{
struct device_node *np;
+ phys_addr_t redirect_reg;
+
+ np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
+ if (!np)
+ return -ENODEV;
+ of_node_put(np);
/*
- * Check that all the requirements are available to enable
- * cpuidle. So far, it is only supported on Armada XP, cpuidle
- * needs the coherency fabric and the PMSU enabled
+ * On Armada 370, there is "a slow exit process from the deep
+ * idle state due to heavy L1/L2 cache cleanup operations
+ * performed by the BootROM software". To avoid this, we
+ * replace the restart code of the bootrom by a a simple jump
+ * to the boot address. Then the code located at this boot
+ * address will take care of the initialization.
*/
+ redirect_reg = pmsu_mp_phys_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(0);
+ mvebu_setup_boot_addr_wa(ARMADA_370_CRYPT0_ENG_TARGET,
+ ARMADA_370_CRYPT0_ENG_ATTR,
+ redirect_reg);
- if (!of_machine_is_compatible("marvell,armadaxp"))
- return 0;
+ mvebu_cpu_resume = armada_370_xp_cpu_resume;
+ mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+ mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
+
+ return 0;
+}
+
+static __init int armada_38x_cpuidle_init(void)
+{
+ struct device_node *np;
+ void __iomem *mpsoc_base;
+ u32 reg;
+
+ np = of_find_compatible_node(NULL, NULL,
+ "marvell,armada-380-coherency-fabric");
+ if (!np)
+ return -ENODEV;
+ of_node_put(np);
+
+ np = of_find_compatible_node(NULL, NULL,
+ "marvell,armada-380-mpcore-soc-ctrl");
+ if (!np)
+ return -ENODEV;
+ mpsoc_base = of_iomap(np, 0);
+ BUG_ON(!mpsoc_base);
+ of_node_put(np);
+
+ /* Set up reset mask when powering down the cpus */
+ reg = readl(mpsoc_base + MPCORE_RESET_CTL);
+ reg |= MPCORE_RESET_CTL_L2;
+ reg |= MPCORE_RESET_CTL_DEBUG;
+ writel(reg, mpsoc_base + MPCORE_RESET_CTL);
+ iounmap(mpsoc_base);
+
+ /* Set up delay */
+ reg = readl(pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+ reg &= ~PMSU_POWERDOWN_DELAY_MASK;
+ reg |= PMSU_DFLT_ARMADA38X_DELAY;
+ reg |= PMSU_POWERDOWN_DELAY_PMU;
+ writel(reg, pmsu_mp_base + PMSU_POWERDOWN_DELAY);
+
+ mvebu_cpu_resume = armada_38x_cpu_resume;
+ mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend;
+ mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x";
+
+ return 0;
+}
+
+static __init int armada_xp_cpuidle_init(void)
+{
+ struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
if (!np)
- return 0;
+ return -ENODEV;
of_node_put(np);
+ mvebu_cpu_resume = armada_370_xp_cpu_resume;
+ mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
+ mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
+
+ return 0;
+}
+
+static int __init mvebu_v7_cpu_pm_init(void)
+{
+ struct device_node *np;
+ int ret;
+
np = of_find_matching_node(NULL, of_pmsu_table);
if (!np)
return 0;
of_node_put(np);
- armada_370_xp_pmsu_enable_l2_powerdown_onidle();
- armada_xp_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
- platform_device_register(&armada_xp_cpuidle_device);
- cpu_pm_register_notifier(&armada_370_xp_cpu_pm_notifier);
+ if (of_machine_is_compatible("marvell,armadaxp"))
+ ret = armada_xp_cpuidle_init();
+ else if (of_machine_is_compatible("marvell,armada370"))
+ ret = armada_370_cpuidle_init();
+ else if (of_machine_is_compatible("marvell,armada380"))
+ ret = armada_38x_cpuidle_init();
+ else
+ return 0;
+
+ if (ret)
+ return ret;
+
+ mvebu_v7_pmsu_enable_l2_powerdown_onidle();
+ platform_device_register(&mvebu_v7_cpuidle_device);
+ cpu_pm_register_notifier(&mvebu_v7_cpu_pm_notifier);
+
+ return 0;
+}
+
+arch_initcall(mvebu_v7_cpu_pm_init);
+early_initcall(mvebu_v7_pmsu_init);
+
+static void mvebu_pmsu_dfs_request_local(void *data)
+{
+ u32 reg;
+ u32 cpu = smp_processor_id();
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* Prepare to enter idle */
+ reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+ reg |= PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT |
+ PMSU_STATUS_AND_MASK_IRQ_MASK |
+ PMSU_STATUS_AND_MASK_FIQ_MASK;
+ writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+
+ /* Request the DFS transition */
+ reg = readl(pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(cpu));
+ reg |= PMSU_CONTROL_AND_CONFIG_DFS_REQ;
+ writel(reg, pmsu_mp_base + PMSU_CONTROL_AND_CONFIG(cpu));
+
+ /* The fact of entering idle will trigger the DFS transition */
+ wfi();
+
+ /*
+ * We're back from idle, the DFS transition has completed,
+ * clear the idle wait indication.
+ */
+ reg = readl(pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+ reg &= ~PMSU_STATUS_AND_MASK_CPU_IDLE_WAIT;
+ writel(reg, pmsu_mp_base + PMSU_STATUS_AND_MASK(cpu));
+
+ local_irq_restore(flags);
+}
+
+int mvebu_pmsu_dfs_request(int cpu)
+{
+ unsigned long timeout;
+ int hwcpu = cpu_logical_map(cpu);
+ u32 reg;
+
+ /* Clear any previous DFS DONE event */
+ reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+ reg &= ~PMSU_EVENT_STATUS_AND_MASK_DFS_DONE;
+ writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+ /* Mask the DFS done interrupt, since we are going to poll */
+ reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+ reg |= PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK;
+ writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+ /* Trigger the DFS on the appropriate CPU */
+ smp_call_function_single(cpu, mvebu_pmsu_dfs_request_local,
+ NULL, false);
+
+ /* Poll until the DFS done event is generated */
+ timeout = jiffies + HZ;
+ while (time_before(jiffies, timeout)) {
+ reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+ if (reg & PMSU_EVENT_STATUS_AND_MASK_DFS_DONE)
+ break;
+ udelay(10);
+ }
+
+ if (time_after(jiffies, timeout))
+ return -ETIME;
+
+ /* Restore the DFS mask to its original state */
+ reg = readl(pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+ reg &= ~PMSU_EVENT_STATUS_AND_MASK_DFS_DONE_MASK;
+ writel(reg, pmsu_mp_base + PMSU_EVENT_STATUS_AND_MASK(hwcpu));
+
+ return 0;
+}
+
+static int __init armada_xp_pmsu_cpufreq_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ int ret, cpu;
+
+ if (!of_machine_is_compatible("marvell,armadaxp"))
+ return 0;
+
+ /*
+ * In order to have proper cpufreq handling, we need to ensure
+ * that the Device Tree description of the CPU clock includes
+ * the definition of the PMU DFS registers. If not, we do not
+ * register the clock notifier and the cpufreq driver. This
+ * piece of code is only for compatibility with old Device
+ * Trees.
+ */
+ np = of_find_compatible_node(NULL, NULL, "marvell,armada-xp-cpu-clock");
+ if (!np)
+ return 0;
+
+ ret = of_address_to_resource(np, 1, &res);
+ if (ret) {
+ pr_warn(FW_WARN "not enabling cpufreq, deprecated armada-xp-cpu-clock binding\n");
+ of_node_put(np);
+ return 0;
+ }
+
+ of_node_put(np);
+
+ /*
+ * For each CPU, this loop registers the operating points
+ * supported (which are the nominal CPU frequency and half of
+ * it), and registers the clock notifier that will take care
+ * of doing the PMSU part of a frequency transition.
+ */
+ for_each_possible_cpu(cpu) {
+ struct device *cpu_dev;
+ struct clk *clk;
+ int ret;
+
+ cpu_dev = get_cpu_device(cpu);
+ if (!cpu_dev) {
+ pr_err("Cannot get CPU %d\n", cpu);
+ continue;
+ }
+
+ clk = clk_get(cpu_dev, 0);
+ if (IS_ERR(clk)) {
+ pr_err("Cannot get clock for CPU %d\n", cpu);
+ return PTR_ERR(clk);
+ }
+
+ /*
+ * In case of a failure of dev_pm_opp_add(), we don't
+ * bother with cleaning up the registered OPP (there's
+ * no function to do so), and simply cancel the
+ * registration of the cpufreq device.
+ */
+ ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
+ if (ret) {
+ clk_put(clk);
+ return ret;
+ }
+
+ ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
+ if (ret) {
+ clk_put(clk);
+ return ret;
+ }
+ }
+ platform_device_register_simple("cpufreq-generic", -1, NULL, 0);
return 0;
}
-arch_initcall(armada_370_xp_cpu_pm_init);
-early_initcall(armada_370_xp_pmsu_init);
+device_initcall(armada_xp_pmsu_cpufreq_init);
diff --git a/arch/arm/mach-mvebu/pmsu.h b/arch/arm/mach-mvebu/pmsu.h
index 07a737c6b95d..6b58c1fe2b0d 100644
--- a/arch/arm/mach-mvebu/pmsu.h
+++ b/arch/arm/mach-mvebu/pmsu.h
@@ -12,5 +12,10 @@
#define __MACH_MVEBU_PMSU_H
int armada_xp_boot_cpu(unsigned int cpu_id, void *phys_addr);
+int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
+ unsigned int crypto_eng_attribute,
+ phys_addr_t resume_addr_reg);
+
+void mvebu_v7_pmsu_idle_exit(void);
#endif /* __MACH_370_XP_PMSU_H */
diff --git a/arch/arm/mach-mvebu/pmsu_ll.S b/arch/arm/mach-mvebu/pmsu_ll.S
index fc3de68d8c54..a945756cfb45 100644
--- a/arch/arm/mach-mvebu/pmsu_ll.S
+++ b/arch/arm/mach-mvebu/pmsu_ll.S
@@ -23,3 +23,39 @@ ARM_BE8(setend be ) @ go BE8 if entered LE
b cpu_resume
ENDPROC(armada_370_xp_cpu_resume)
+ENTRY(armada_38x_cpu_resume)
+ /* do we need it for Armada 38x*/
+ARM_BE8(setend be ) @ go BE8 if entered LE
+ bl v7_invalidate_l1
+ mrc p15, 4, r1, c15, c0 @ get SCU base address
+ orr r1, r1, #0x8 @ SCU CPU Power Status Register
+ mrc 15, 0, r0, cr0, cr0, 5 @ get the CPU ID
+ and r0, r0, #15
+ add r1, r1, r0
+ mov r0, #0x0
+ strb r0, [r1] @ switch SCU power state to Normal mode
+ b cpu_resume
+ENDPROC(armada_38x_cpu_resume)
+
+.global mvebu_boot_wa_start
+.global mvebu_boot_wa_end
+
+/* The following code will be executed from SRAM */
+ENTRY(mvebu_boot_wa_start)
+mvebu_boot_wa_start:
+ARM_BE8(setend be)
+ adr r0, 1f
+ ldr r0, [r0] @ load the address of the
+ @ resume register
+ ldr r0, [r0] @ load the value in the
+ @ resume register
+ARM_BE8(rev r0, r0) @ the value is stored LE
+ mov pc, r0 @ jump to this value
+/*
+ * the last word of this piece of code will be filled by the physical
+ * address of the boot address register just after being copied in SRAM
+ */
+1:
+ .long .
+mvebu_boot_wa_end:
+ENDPROC(mvebu_boot_wa_end)
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
index 0c5524ac75b7..a068cb5c2ce8 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -28,8 +28,14 @@
#include <linux/io.h>
#include <linux/reboot.h>
#include "common.h"
+#include "mvebu-soc-id.h"
+#include "pmsu.h"
+
+#define ARMADA_375_CRYPT0_ENG_TARGET 41
+#define ARMADA_375_CRYPT0_ENG_ATTR 1
static void __iomem *system_controller_base;
+static phys_addr_t system_controller_phys_base;
struct mvebu_system_controller {
u32 rstoutn_mask_offset;
@@ -39,6 +45,9 @@ struct mvebu_system_controller {
u32 system_soft_reset;
u32 resume_boot_addr;
+
+ u32 dev_id;
+ u32 rev_id;
};
static struct mvebu_system_controller *mvebu_sc;
@@ -47,6 +56,8 @@ static const struct mvebu_system_controller armada_370_xp_system_controller = {
.system_soft_reset_offset = 0x64,
.rstoutn_mask_reset_out_en = 0x1,
.system_soft_reset = 0x1,
+ .dev_id = 0x38,
+ .rev_id = 0x3c,
};
static const struct mvebu_system_controller armada_375_system_controller = {
@@ -55,6 +66,8 @@ static const struct mvebu_system_controller armada_375_system_controller = {
.rstoutn_mask_reset_out_en = 0x1,
.system_soft_reset = 0x1,
.resume_boot_addr = 0xd4,
+ .dev_id = 0x38,
+ .rev_id = 0x3c,
};
static const struct mvebu_system_controller orion_system_controller = {
@@ -101,11 +114,45 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd)
;
}
+int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev)
+{
+ if (of_machine_is_compatible("marvell,armada380") &&
+ system_controller_base) {
+ *dev = readl(system_controller_base + mvebu_sc->dev_id) >> 16;
+ *rev = (readl(system_controller_base + mvebu_sc->rev_id) >> 8)
+ & 0xF;
+ return 0;
+ } else
+ return -ENODEV;
+}
+
#ifdef CONFIG_SMP
+void mvebu_armada375_smp_wa_init(void)
+{
+ u32 dev, rev;
+ phys_addr_t resume_addr_reg;
+
+ if (mvebu_get_soc_id(&dev, &rev) != 0)
+ return;
+
+ if (rev != ARMADA_375_Z1_REV)
+ return;
+
+ resume_addr_reg = system_controller_phys_base +
+ mvebu_sc->resume_boot_addr;
+ mvebu_setup_boot_addr_wa(ARMADA_375_CRYPT0_ENG_TARGET,
+ ARMADA_375_CRYPT0_ENG_ATTR,
+ resume_addr_reg);
+}
+
void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr)
{
BUG_ON(system_controller_base == NULL);
BUG_ON(mvebu_sc->resume_boot_addr == 0);
+
+ if (of_machine_is_compatible("marvell,armada375"))
+ mvebu_armada375_smp_wa_init();
+
writel(virt_to_phys(boot_addr), system_controller_base +
mvebu_sc->resume_boot_addr);
}
@@ -119,7 +166,10 @@ static int __init mvebu_system_controller_init(void)
np = of_find_matching_node_and_match(NULL, of_system_controller_table,
&match);
if (np) {
+ struct resource res;
system_controller_base = of_iomap(np, 0);
+ of_address_to_resource(np, 0, &res);
+ system_controller_phys_base = res.start;
mvebu_sc = (struct mvebu_system_controller *)match->data;
of_node_put(np);
}
diff --git a/arch/arm/mach-omap1/include/mach/memory.h b/arch/arm/mach-omap1/include/mach/memory.h
index 3c2530523111..058a4f7d44c5 100644
--- a/arch/arm/mach-omap1/include/mach/memory.h
+++ b/arch/arm/mach-omap1/include/mach/memory.h
@@ -6,11 +6,6 @@
#define __ASM_ARCH_MEMORY_H
/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-
-/*
* Bus address is physical address, except for OMAP-1510 Local Bus.
* OMAP-1510 bus address is translated into a Local Bus address if the
* OMAP bus type is lbus. We do the address translation based on the
diff --git a/arch/arm/mach-omap1/ocpi.c b/arch/arm/mach-omap1/ocpi.c
index 238170cab5b7..44a3d19eb481 100644
--- a/arch/arm/mach-omap1/ocpi.c
+++ b/arch/arm/mach-omap1/ocpi.c
@@ -55,7 +55,6 @@ static struct clk *ocpi_ck;
/*
* Enables device access to OMAP buses via the OCPI bridge
- * FIXME: Add locking
*/
int ocpi_enable(void)
{
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 1c1ed737f7ab..e7189dcc9309 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -15,7 +15,6 @@ config ARCH_OMAP3
bool "TI OMAP3"
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
- select ARCH_HAS_OPP
select ARM_CPU_SUSPEND if PM
select OMAP_INTERCONNECT
select PM_OPP if PM
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 8ca99e9321e3..69bbcba8842f 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -176,13 +176,11 @@ obj-$(CONFIG_SOC_DRA7XX) += clockdomains7xx_data.o
# Clock framework
obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o
-obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_sys.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
-obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o clkt2xxx_osc.o
+obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
-obj-$(CONFIG_SOC_OMAP2420) += cclock2420_data.o
-obj-$(CONFIG_SOC_OMAP2430) += clock2430.o cclock2430_data.o
+obj-$(CONFIG_SOC_OMAP2430) += clock2430.o
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
@@ -202,6 +200,7 @@ obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
obj-$(CONFIG_SOC_OMAP2430) += opp2430_data.o
# hwmod data
+obj-y += omap_hwmod_common_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_interconnect_data.o
@@ -232,10 +231,6 @@ obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
obj-y += $(iommu-m) $(iommu-y)
-ifneq ($(CONFIG_TIDSPBRIDGE),)
-obj-y += dsp.o
-endif
-
# OMAP2420 MSDI controller integration support ("MMC")
obj-$(CONFIG_SOC_OMAP2420) += msdi.o
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 7da48bc42bbf..70b904c010c6 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -336,7 +336,7 @@ static int __init early_touchbook_revision(char *p)
if (!p)
return 0;
- return strict_strtoul(p, 10, &touchbook_revision);
+ return kstrtoul(p, 10, &touchbook_revision);
}
early_param("tbr", early_touchbook_revision);
diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c
deleted file mode 100644
index 3662f4d4c8ea..000000000000
--- a/arch/arm/mach-omap2/cclock2420_data.c
+++ /dev/null
@@ -1,1931 +0,0 @@
-/*
- * OMAP2420 clock data
- *
- * Copyright (C) 2005-2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- * Updated to COMMON clk format by Rajendra Nayak <rnayak@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR
-
-/*
- * 2420 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- * many cases the parent is selectable. The set parent calls will
- * also switch sources.
- *
- * Several sources are given initial rates which may be wrong, this will
- * be fixed up in the init func.
- *
- * Things are broadly separated below by clock domains. It is
- * noteworthy that most peripherals have dependencies on multiple clock
- * domains. Many get their interface clocks from the L4 domain, but get
- * functional clocks from fixed sources or other core domain derived
- * clocks.
- */
-
-DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
-
-static struct clk osc_ck;
-
-static const struct clk_ops osc_ck_ops = {
- .recalc_rate = &omap2_osc_clk_recalc,
-};
-
-static struct clk_hw_omap osc_ck_hw = {
- .hw = {
- .clk = &osc_ck,
- },
-};
-
-static struct clk osc_ck = {
- .name = "osc_ck",
- .ops = &osc_ck_ops,
- .hw = &osc_ck_hw.hw,
- .flags = CLK_IS_ROOT,
-};
-
-DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-static struct clk sys_ck;
-
-static const char *sys_ck_parent_names[] = {
- "osc_ck",
-};
-
-static const struct clk_ops sys_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .recalc_rate = &omap2xxx_sys_clk_recalc,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
-
-static struct dpll_data dpll_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP24XX_DPLL_MULT_MASK,
- .div1_mask = OMAP24XX_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP24XX_EN_DPLL_MASK,
- .max_multiplier = 1023,
- .min_divider = 1,
- .max_divider = 16,
-};
-
-static struct clk dpll_ck;
-
-static const char *dpll_ck_parent_names[] = {
- "sys_ck",
-};
-
-static const struct clk_ops dpll_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .get_parent = &omap2_init_dpll_parent,
- .recalc_rate = &omap2_dpllcore_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap2_reprogram_dpllcore,
-};
-
-static struct clk_hw_omap dpll_ck_hw = {
- .hw = {
- .clk = &dpll_ck,
- },
- .ops = &clkhwops_omap2xxx_dpll,
- .dpll_data = &dpll_dd,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
-
-static struct clk core_ck;
-
-static const char *core_ck_parent_names[] = {
- "dpll_ck",
-};
-
-static const struct clk_ops core_ck_ops = {
- .init = &omap2_init_clk_clkdm,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-
-DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk aes_ick;
-
-static const char *aes_ick_parent_names[] = {
- "l4_ck",
-};
-
-static const struct clk_ops aes_ick_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes_ick_hw = {
- .hw = {
- .clk = &aes_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_AES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk apll54_ck;
-
-static const struct clk_ops apll54_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_clk_apll54_enable,
- .disable = &omap2_clk_apll54_disable,
- .recalc_rate = &omap2_clk_apll54_recalc,
-};
-
-static struct clk_hw_omap apll54_ck_hw = {
- .hw = {
- .clk = &apll54_ck,
- },
- .ops = &clkhwops_apll54,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
-
-static struct clk apll96_ck;
-
-static const struct clk_ops apll96_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_clk_apll96_enable,
- .disable = &omap2_clk_apll96_disable,
- .recalc_rate = &omap2_clk_apll96_recalc,
-};
-
-static struct clk_hw_omap apll96_ck_hw = {
- .hw = {
- .clk = &apll96_ck,
- },
- .ops = &clkhwops_apll96,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
-
-static struct clk func_96m_ck;
-
-static const char *func_96m_ck_parent_names[] = {
- "apll96_ck",
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(func_96m_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(func_96m_ck, func_96m_ck_parent_names, core_ck_ops);
-
-static struct clk cam_fck;
-
-static const char *cam_fck_parent_names[] = {
- "func_96m_ck",
-};
-
-static struct clk_hw_omap cam_fck_hw = {
- .hw = {
- .clk = &cam_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk cam_ick;
-
-static struct clk_hw_omap cam_ick_hw = {
- .hw = {
- .clk = &cam_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk des_ick;
-
-static struct clk_hw_omap des_ick_hw = {
- .hw = {
- .clk = &des_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_DES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate dsp_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 12, .val = 12, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel dsp_fck_clksel[] = {
- { .parent = &core_ck, .rates = dsp_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *dsp_fck_parent_names[] = {
- "core_ck",
-};
-
-static const struct clk_ops dsp_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_DSP_MASK,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
- dsp_fck_parent_names, dsp_fck_ops);
-
-static const struct clksel dsp_ick_clksel[] = {
- { .parent = &dsp_fck, .rates = dsp_ick_rates },
- { .parent = NULL },
-};
-
-static const char *dsp_ick_parent_names[] = {
- "dsp_fck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_ick, "dsp_clkdm", dsp_ick_clksel,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_DSP_IF_MASK,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
- OMAP2420_EN_DSP_IPI_SHIFT, &clkhwops_iclk_wait,
- dsp_ick_parent_names, dsp_fck_ops);
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 8, .val = 8, .flags = RATE_IN_24XX },
- { .div = 9, .val = 9, .flags = RATE_IN_24XX },
- { .div = 12, .val = 12, .flags = RATE_IN_24XX },
- { .div = 16, .val = 16, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
- { .parent = &core_ck, .rates = dss1_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *dss1_fck_parent_names[] = {
- "sys_ck", "core_ck",
-};
-
-static struct clk dss1_fck;
-
-static const struct clk_ops dss1_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_DSS1_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_DSS1_SHIFT, NULL,
- dss1_fck_parent_names, dss1_fck_ops);
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel func_48m_clksel[] = {
- { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
- { .parent = &alt_ck, .rates = func_48m_alt_rates },
- { .parent = NULL },
-};
-
-static const char *func_48m_ck_parent_names[] = {
- "apll96_ck", "alt_ck",
-};
-
-static struct clk func_48m_ck;
-
-static const struct clk_ops func_48m_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-static struct clk_hw_omap func_48m_ck_hw = {
- .hw = {
- .clk = &func_48m_ck,
- },
- .clksel = func_48m_clksel,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
-
-static const struct clksel dss2_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
- { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
- { .parent = NULL },
-};
-
-static const char *dss2_fck_parent_names[] = {
- "sys_ck", "func_48m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_DSS2_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_DSS2_SHIFT, NULL,
- dss2_fck_parent_names, dss1_fck_ops);
-
-static const char *func_54m_ck_parent_names[] = {
- "apll54_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH,
- 0x0, NULL);
-
-static struct clk dss_54m_fck;
-
-static const char *dss_54m_fck_parent_names[] = {
- "func_54m_ck",
-};
-
-static struct clk_hw_omap dss_54m_fck_hw = {
- .hw = {
- .clk = &dss_54m_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
-
-static struct clk dss_ick;
-
-static struct clk_hw_omap dss_ick_hw = {
- .hw = {
- .clk = &dss_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk eac_fck;
-
-static struct clk_hw_omap eac_fck_hw = {
- .hw = {
- .clk = &eac_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_EAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(eac_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk eac_ick;
-
-static struct clk_hw_omap eac_ick_hw = {
- .hw = {
- .clk = &eac_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_EAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(eac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk emul_ck;
-
-static struct clk_hw_omap emul_ck_hw = {
- .hw = {
- .clk = &emul_ck,
- },
- .enable_reg = OMAP2420_PRCM_CLKEMUL_CTRL,
- .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
-
-static struct clk fac_fck;
-
-static const char *fac_fck_parent_names[] = {
- "func_12m_ck",
-};
-
-static struct clk_hw_omap fac_fck_hw = {
- .hw = {
- .clk = &fac_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk fac_ick;
-
-static struct clk_hw_omap fac_ick_hw = {
- .hw = {
- .clk = &fac_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel gfx_fck_clksel[] = {
- { .parent = &core_l3_ck, .rates = gfx_l3_rates },
- { .parent = NULL },
-};
-
-static const char *gfx_2d_fck_parent_names[] = {
- "core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
- OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- OMAP_CLKSEL_GFX_MASK,
- OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
- gfx_2d_fck_parent_names, dsp_fck_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
- OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- OMAP_CLKSEL_GFX_MASK,
- OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
- gfx_2d_fck_parent_names, dsp_fck_ops);
-
-static struct clk gfx_ick;
-
-static const char *gfx_ick_parent_names[] = {
- "core_l3_ck",
-};
-
-static struct clk_hw_omap gfx_ick_hw = {
- .hw = {
- .clk = &gfx_ick,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .clkdm_name = "gfx_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk gpios_fck;
-
-static const char *gpios_fck_parent_names[] = {
- "func_32k_ck",
-};
-
-static struct clk_hw_omap gpios_fck_hw = {
- .hw = {
- .clk = &gpios_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk gpios_ick;
-
-static const char *gpios_ick_parent_names[] = {
- "sys_ck",
-};
-
-static struct clk_hw_omap gpios_ick_hw = {
- .hw = {
- .clk = &gpios_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk gpmc_fck;
-
-static struct clk_hw_omap gpmc_fck_hw = {
- .hw = {
- .clk = &gpmc_fck,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
-
-static const struct clksel_rate gpt_alt_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
- { .parent = &func_32k_ck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = &alt_ck, .rates = gpt_alt_rates },
- { .parent = NULL },
-};
-
-static const char *gpt10_fck_parent_names[] = {
- "func_32k_ck", "sys_ck", "alt_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT10_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt10_ick;
-
-static struct clk_hw_omap gpt10_ick_hw = {
- .hw = {
- .clk = &gpt10_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT11_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt11_ick;
-
-static struct clk_hw_omap gpt11_ick_hw = {
- .hw = {
- .clk = &gpt11_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT12_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt12_ick;
-
-static struct clk_hw_omap gpt12_ick_hw = {
- .hw = {
- .clk = &gpt12_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clk_ops gpt1_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_GPT1_MASK,
- OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, gpt1_fck_ops);
-
-static struct clk gpt1_ick;
-
-static struct clk_hw_omap gpt1_ick_hw = {
- .hw = {
- .clk = &gpt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT2_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt2_ick;
-
-static struct clk_hw_omap gpt2_ick_hw = {
- .hw = {
- .clk = &gpt2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT3_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt3_ick;
-
-static struct clk_hw_omap gpt3_ick_hw = {
- .hw = {
- .clk = &gpt3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT4_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt4_ick;
-
-static struct clk_hw_omap gpt4_ick_hw = {
- .hw = {
- .clk = &gpt4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT5_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt5_ick;
-
-static struct clk_hw_omap gpt5_ick_hw = {
- .hw = {
- .clk = &gpt5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT6_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt6_ick;
-
-static struct clk_hw_omap gpt6_ick_hw = {
- .hw = {
- .clk = &gpt6_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT7_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt7_ick;
-
-static struct clk_hw_omap gpt7_ick_hw = {
- .hw = {
- .clk = &gpt7_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT8_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt8_ick;
-
-static struct clk_hw_omap gpt8_ick_hw = {
- .hw = {
- .clk = &gpt8_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT9_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt9_ick;
-
-static struct clk_hw_omap gpt9_ick_hw = {
- .hw = {
- .clk = &gpt9_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk hdq_fck;
-
-static struct clk_hw_omap hdq_fck_hw = {
- .hw = {
- .clk = &hdq_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk hdq_ick;
-
-static struct clk_hw_omap hdq_ick_hw = {
- .hw = {
- .clk = &hdq_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c1_fck;
-
-static struct clk_hw_omap i2c1_fck_hw = {
- .hw = {
- .clk = &i2c1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk i2c1_ick;
-
-static struct clk_hw_omap i2c1_ick_hw = {
- .hw = {
- .clk = &i2c1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c2_fck;
-
-static struct clk_hw_omap i2c2_fck_hw = {
- .hw = {
- .clk = &i2c2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk i2c2_ick;
-
-static struct clk_hw_omap i2c2_ick_hw = {
- .hw = {
- .clk = &i2c2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(iva1_ifck, "iva1_clkdm", dsp_fck_clksel,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- OMAP2420_CLKSEL_IVA_MASK,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- OMAP2420_EN_IVA_COP_SHIFT, &clkhwops_wait,
- dsp_fck_parent_names, dsp_fck_ops);
-
-static struct clk iva1_mpu_int_ifck;
-
-static const char *iva1_mpu_int_ifck_parent_names[] = {
- "iva1_ifck",
-};
-
-static const struct clk_ops iva1_mpu_int_ifck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap_fixed_divisor_recalc,
-};
-
-static struct clk_hw_omap iva1_mpu_int_ifck_hw = {
- .hw = {
- .clk = &iva1_mpu_int_ifck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- .enable_bit = OMAP2420_EN_IVA_MPU_SHIFT,
- .clkdm_name = "iva1_clkdm",
- .fixed_div = 2,
-};
-
-DEFINE_STRUCT_CLK(iva1_mpu_int_ifck, iva1_mpu_int_ifck_parent_names,
- iva1_mpu_int_ifck_ops);
-
-static struct clk mailboxes_ick;
-
-static struct clk_hw_omap mailboxes_ick_hw = {
- .hw = {
- .clk = &mailboxes_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL },
-};
-
-static const char *mcbsp1_fck_parent_names[] = {
- "func_96m_ck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP1_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp1_ick;
-
-static struct clk_hw_omap mcbsp1_ick_hw = {
- .hw = {
- .clk = &mcbsp1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP2_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp2_ick;
-
-static struct clk_hw_omap mcbsp2_ick_hw = {
- .hw = {
- .clk = &mcbsp2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_fck;
-
-static const char *mcspi1_fck_parent_names[] = {
- "func_48m_ck",
-};
-
-static struct clk_hw_omap mcspi1_fck_hw = {
- .hw = {
- .clk = &mcspi1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_ick;
-
-static struct clk_hw_omap mcspi1_ick_hw = {
- .hw = {
- .clk = &mcspi1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_fck;
-
-static struct clk_hw_omap mcspi2_fck_hw = {
- .hw = {
- .clk = &mcspi2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_ick;
-
-static struct clk_hw_omap mcspi2_ick_hw = {
- .hw = {
- .clk = &mcspi2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmc_fck;
-
-static struct clk_hw_omap mmc_fck_hw = {
- .hw = {
- .clk = &mmc_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_MMC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmc_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmc_ick;
-
-static struct clk_hw_omap mmc_ick_hw = {
- .hw = {
- .clk = &mmc_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_MMC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmc_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk mpu_wdt_fck;
-
-static struct clk_hw_omap mpu_wdt_fck_hw = {
- .hw = {
- .clk = &mpu_wdt_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk mpu_wdt_ick;
-
-static struct clk_hw_omap mpu_wdt_ick_hw = {
- .hw = {
- .clk = &mpu_wdt_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk mspro_fck;
-
-static struct clk_hw_omap mspro_fck_hw = {
- .hw = {
- .clk = &mspro_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mspro_ick;
-
-static struct clk_hw_omap mspro_ick_hw = {
- .hw = {
- .clk = &mspro_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk omapctrl_ick;
-
-static struct clk_hw_omap omapctrl_ick_hw = {
- .hw = {
- .clk = &omapctrl_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk pka_ick;
-
-static struct clk_hw_omap pka_ick_hw = {
- .hw = {
- .clk = &pka_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_PKA_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk rng_ick;
-
-static struct clk_hw_omap rng_ick_hw = {
- .hw = {
- .clk = &rng_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_RNG_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk sdma_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
-DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdma_ick;
-
-static struct clk_hw_omap sdma_ick_hw = {
- .hw = {
- .clk = &sdma_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdrc_ick;
-
-static struct clk_hw_omap sdrc_ick_hw = {
- .hw = {
- .clk = &sdrc_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDRC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sha_ick;
-
-static struct clk_hw_omap sha_ick_hw = {
- .hw = {
- .clk = &sha_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_SHA_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk ssi_l4_ick;
-
-static struct clk_hw_omap ssi_l4_ick_hw = {
- .hw = {
- .clk = &ssi_l4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
- { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *ssi_ssr_sst_fck_parent_names[] = {
- "core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
- ssi_ssr_sst_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_SSI_MASK,
- OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
- ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
-
-static struct clk sync_32k_ick;
-
-static struct clk_hw_omap sync_32k_ick_hw = {
- .hw = {
- .clk = &sync_32k_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_clkout_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
- { .parent = &core_ck, .rates = common_clkout_src_core_rates },
- { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
- { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
- { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
- { .parent = NULL },
-};
-
-static const char *sys_clkout_src_parent_names[] = {
- "core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
- OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
- OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
- NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
- OMAP2420_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
- OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout2_src, "wkup_clkdm",
- common_clkout_src_clksel, OMAP2420_PRCM_CLKOUT_CTRL,
- OMAP2420_CLKOUT2_SOURCE_MASK,
- OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_EN_SHIFT,
- NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout2, "sys_clkout2_src", &sys_clkout2_src, 0x0,
- OMAP2420_PRCM_CLKOUT_CTRL, OMAP2420_CLKOUT2_DIV_SHIFT,
- OMAP2420_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-static struct clk uart1_fck;
-
-static struct clk_hw_omap uart1_fck_hw = {
- .hw = {
- .clk = &uart1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart1_ick;
-
-static struct clk_hw_omap uart1_ick_hw = {
- .hw = {
- .clk = &uart1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart2_fck;
-
-static struct clk_hw_omap uart2_fck_hw = {
- .hw = {
- .clk = &uart2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart2_ick;
-
-static struct clk_hw_omap uart2_ick_hw = {
- .hw = {
- .clk = &uart2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart3_fck;
-
-static struct clk_hw_omap uart3_fck_hw = {
- .hw = {
- .clk = &uart3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart3_ick;
-
-static struct clk_hw_omap uart3_ick_hw = {
- .hw = {
- .clk = &uart3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk usb_fck;
-
-static struct clk_hw_omap usb_fck_hw = {
- .hw = {
- .clk = &usb_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
- { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
- { .parent = NULL },
-};
-
-static const char *usb_l4_ick_parent_names[] = {
- "core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_USB_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
- usb_l4_ick_parent_names, dsp_fck_ops);
-
-static struct clk virt_prcm_set;
-
-static const char *virt_prcm_set_parent_names[] = {
- "mpu_ck",
-};
-
-static const struct clk_ops virt_prcm_set_ops = {
- .recalc_rate = &omap2_table_mpu_recalc,
- .set_rate = &omap2_select_table_rate,
- .round_rate = &omap2_round_to_table_rate,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
-DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
-
-static const struct clksel_rate vlynq_fck_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel_rate vlynq_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_242X },
- { .div = 2, .val = 2, .flags = RATE_IN_242X },
- { .div = 3, .val = 3, .flags = RATE_IN_242X },
- { .div = 4, .val = 4, .flags = RATE_IN_242X },
- { .div = 6, .val = 6, .flags = RATE_IN_242X },
- { .div = 8, .val = 8, .flags = RATE_IN_242X },
- { .div = 9, .val = 9, .flags = RATE_IN_242X },
- { .div = 12, .val = 12, .flags = RATE_IN_242X },
- { .div = 16, .val = 16, .flags = RATE_IN_242X },
- { .div = 18, .val = 18, .flags = RATE_IN_242X },
- { .div = 0 }
-};
-
-static const struct clksel vlynq_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = vlynq_fck_96m_rates },
- { .parent = &core_ck, .rates = vlynq_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *vlynq_fck_parent_names[] = {
- "func_96m_ck", "core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(vlynq_fck, "core_l3_clkdm", vlynq_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP2420_CLKSEL_VLYNQ_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP2420_EN_VLYNQ_SHIFT, &clkhwops_wait,
- vlynq_fck_parent_names, dss1_fck_ops);
-
-static struct clk vlynq_ick;
-
-static struct clk_hw_omap vlynq_ick_hw = {
- .hw = {
- .clk = &vlynq_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_VLYNQ_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(vlynq_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt1_ick;
-
-static struct clk_hw_omap wdt1_ick_hw = {
- .hw = {
- .clk = &wdt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt3_fck;
-
-static struct clk_hw_omap wdt3_fck_hw = {
- .hw = {
- .clk = &wdt3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP2420_EN_WDT3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt3_ick;
-
-static struct clk_hw_omap wdt3_ick_hw = {
- .hw = {
- .clk = &wdt3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_WDT3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt4_fck;
-
-static struct clk_hw_omap wdt4_fck_hw = {
- .hw = {
- .clk = &wdt4_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_fck, gpios_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt4_ick;
-
-static struct clk_hw_omap wdt4_ick_hw = {
- .hw = {
- .clk = &wdt4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2420_clks[] = {
- /* external root sources */
- CLK(NULL, "func_32k_ck", &func_32k_ck),
- CLK(NULL, "secure_32k_ck", &secure_32k_ck),
- CLK(NULL, "osc_ck", &osc_ck),
- CLK(NULL, "sys_ck", &sys_ck),
- CLK(NULL, "alt_ck", &alt_ck),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks),
- /* internal analog sources */
- CLK(NULL, "dpll_ck", &dpll_ck),
- CLK(NULL, "apll96_ck", &apll96_ck),
- CLK(NULL, "apll54_ck", &apll54_ck),
- /* internal prcm root sources */
- CLK(NULL, "func_54m_ck", &func_54m_ck),
- CLK(NULL, "core_ck", &core_ck),
- CLK(NULL, "func_96m_ck", &func_96m_ck),
- CLK(NULL, "func_48m_ck", &func_48m_ck),
- CLK(NULL, "func_12m_ck", &func_12m_ck),
- CLK(NULL, "sys_clkout_src", &sys_clkout_src),
- CLK(NULL, "sys_clkout", &sys_clkout),
- CLK(NULL, "sys_clkout2_src", &sys_clkout2_src),
- CLK(NULL, "sys_clkout2", &sys_clkout2),
- CLK(NULL, "emul_ck", &emul_ck),
- /* mpu domain clocks */
- CLK(NULL, "mpu_ck", &mpu_ck),
- /* dsp domain clocks */
- CLK(NULL, "dsp_fck", &dsp_fck),
- CLK(NULL, "dsp_ick", &dsp_ick),
- CLK(NULL, "iva1_ifck", &iva1_ifck),
- CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck),
- /* GFX domain clocks */
- CLK(NULL, "gfx_3d_fck", &gfx_3d_fck),
- CLK(NULL, "gfx_2d_fck", &gfx_2d_fck),
- CLK(NULL, "gfx_ick", &gfx_ick),
- /* DSS domain clocks */
- CLK("omapdss_dss", "ick", &dss_ick),
- CLK(NULL, "dss_ick", &dss_ick),
- CLK(NULL, "dss1_fck", &dss1_fck),
- CLK(NULL, "dss2_fck", &dss2_fck),
- CLK(NULL, "dss_54m_fck", &dss_54m_fck),
- /* L3 domain clocks */
- CLK(NULL, "core_l3_ck", &core_l3_ck),
- CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick),
- /* L4 domain clocks */
- CLK(NULL, "l4_ck", &l4_ck),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick),
- /* virtual meta-group clock */
- CLK(NULL, "virt_prcm_set", &virt_prcm_set),
- /* general l4 interface ck, multi-parent functional clk */
- CLK(NULL, "gpt1_ick", &gpt1_ick),
- CLK(NULL, "gpt1_fck", &gpt1_fck),
- CLK(NULL, "gpt2_ick", &gpt2_ick),
- CLK(NULL, "gpt2_fck", &gpt2_fck),
- CLK(NULL, "gpt3_ick", &gpt3_ick),
- CLK(NULL, "gpt3_fck", &gpt3_fck),
- CLK(NULL, "gpt4_ick", &gpt4_ick),
- CLK(NULL, "gpt4_fck", &gpt4_fck),
- CLK(NULL, "gpt5_ick", &gpt5_ick),
- CLK(NULL, "gpt5_fck", &gpt5_fck),
- CLK(NULL, "gpt6_ick", &gpt6_ick),
- CLK(NULL, "gpt6_fck", &gpt6_fck),
- CLK(NULL, "gpt7_ick", &gpt7_ick),
- CLK(NULL, "gpt7_fck", &gpt7_fck),
- CLK(NULL, "gpt8_ick", &gpt8_ick),
- CLK(NULL, "gpt8_fck", &gpt8_fck),
- CLK(NULL, "gpt9_ick", &gpt9_ick),
- CLK(NULL, "gpt9_fck", &gpt9_fck),
- CLK(NULL, "gpt10_ick", &gpt10_ick),
- CLK(NULL, "gpt10_fck", &gpt10_fck),
- CLK(NULL, "gpt11_ick", &gpt11_ick),
- CLK(NULL, "gpt11_fck", &gpt11_fck),
- CLK(NULL, "gpt12_ick", &gpt12_ick),
- CLK(NULL, "gpt12_fck", &gpt12_fck),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick),
- CLK(NULL, "mcbsp2_ick", &mcbsp2_ick),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck),
- CLK(NULL, "uart1_ick", &uart1_ick),
- CLK(NULL, "uart1_fck", &uart1_fck),
- CLK(NULL, "uart2_ick", &uart2_ick),
- CLK(NULL, "uart2_fck", &uart2_fck),
- CLK(NULL, "uart3_ick", &uart3_ick),
- CLK(NULL, "uart3_fck", &uart3_fck),
- CLK(NULL, "gpios_ick", &gpios_ick),
- CLK(NULL, "gpios_fck", &gpios_fck),
- CLK("omap_wdt", "ick", &mpu_wdt_ick),
- CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick),
- CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck),
- CLK(NULL, "sync_32k_ick", &sync_32k_ick),
- CLK(NULL, "wdt1_ick", &wdt1_ick),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick),
- CLK("omap24xxcam", "fck", &cam_fck),
- CLK(NULL, "cam_fck", &cam_fck),
- CLK("omap24xxcam", "ick", &cam_ick),
- CLK(NULL, "cam_ick", &cam_ick),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick),
- CLK(NULL, "wdt4_ick", &wdt4_ick),
- CLK(NULL, "wdt4_fck", &wdt4_fck),
- CLK(NULL, "wdt3_ick", &wdt3_ick),
- CLK(NULL, "wdt3_fck", &wdt3_fck),
- CLK(NULL, "mspro_ick", &mspro_ick),
- CLK(NULL, "mspro_fck", &mspro_fck),
- CLK("mmci-omap.0", "ick", &mmc_ick),
- CLK(NULL, "mmc_ick", &mmc_ick),
- CLK("mmci-omap.0", "fck", &mmc_fck),
- CLK(NULL, "mmc_fck", &mmc_fck),
- CLK(NULL, "fac_ick", &fac_ick),
- CLK(NULL, "fac_fck", &fac_fck),
- CLK(NULL, "eac_ick", &eac_ick),
- CLK(NULL, "eac_fck", &eac_fck),
- CLK("omap_hdq.0", "ick", &hdq_ick),
- CLK(NULL, "hdq_ick", &hdq_ick),
- CLK("omap_hdq.0", "fck", &hdq_fck),
- CLK(NULL, "hdq_fck", &hdq_fck),
- CLK("omap_i2c.1", "ick", &i2c1_ick),
- CLK(NULL, "i2c1_ick", &i2c1_ick),
- CLK(NULL, "i2c1_fck", &i2c1_fck),
- CLK("omap_i2c.2", "ick", &i2c2_ick),
- CLK(NULL, "i2c2_ick", &i2c2_ick),
- CLK(NULL, "i2c2_fck", &i2c2_fck),
- CLK(NULL, "gpmc_fck", &gpmc_fck),
- CLK(NULL, "sdma_fck", &sdma_fck),
- CLK(NULL, "sdma_ick", &sdma_ick),
- CLK(NULL, "sdrc_ick", &sdrc_ick),
- CLK(NULL, "vlynq_ick", &vlynq_ick),
- CLK(NULL, "vlynq_fck", &vlynq_fck),
- CLK(NULL, "des_ick", &des_ick),
- CLK("omap-sham", "ick", &sha_ick),
- CLK(NULL, "sha_ick", &sha_ick),
- CLK("omap_rng", "ick", &rng_ick),
- CLK(NULL, "rng_ick", &rng_ick),
- CLK("omap-aes", "ick", &aes_ick),
- CLK(NULL, "aes_ick", &aes_ick),
- CLK(NULL, "pka_ick", &pka_ick),
- CLK(NULL, "usb_fck", &usb_fck),
- CLK("musb-hdrc", "fck", &osc_ck),
- CLK(NULL, "timer_32k_ck", &func_32k_ck),
- CLK(NULL, "timer_sys_ck", &sys_ck),
- CLK(NULL, "timer_ext_ck", &alt_ck),
- CLK(NULL, "cpufreq_ck", &virt_prcm_set),
-};
-
-
-static const char *enable_init_clks[] = {
- "apll96_ck",
- "apll54_ck",
- "sync_32k_ick",
- "omapctrl_ick",
- "gpmc_fck",
- "sdrc_ick",
-};
-
-/*
- * init code
- */
-
-int __init omap2420_clk_init(void)
-{
- prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL;
- cpu_mask = RATE_IN_242X;
- rate_table = omap2420_rate_table;
-
- omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
-
- omap2xxx_clkt_vps_check_bootloader_rates();
-
- omap_clocks_register(omap2420_clks, ARRAY_SIZE(omap2420_clks));
-
- omap2xxx_clkt_vps_late_init();
-
- omap2_clk_disable_autoidle_all();
-
- omap2_clk_enable_init_clocks(enable_init_clks,
- ARRAY_SIZE(enable_init_clks));
-
- pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (clk_get_rate(&sys_ck) / 1000000),
- (clk_get_rate(&sys_ck) / 100000) % 10,
- (clk_get_rate(&dpll_ck) / 1000000),
- (clk_get_rate(&mpu_ck) / 1000000));
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
deleted file mode 100644
index 5e4b037bb24c..000000000000
--- a/arch/arm/mach-omap2/cclock2430_data.c
+++ /dev/null
@@ -1,2048 +0,0 @@
-/*
- * OMAP2430 clock data
- *
- * Copyright (C) 2005-2009, 2012 Texas Instruments, Inc.
- * Copyright (C) 2004-2011 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clk-private.h>
-#include <linux/list.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock2xxx.h"
-#include "opp2xxx.h"
-#include "cm2xxx.h"
-#include "prm2xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm-regbits-24xx.h"
-#include "sdrc.h"
-#include "control.h"
-
-#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR
-
-/*
- * 2430 clock tree.
- *
- * NOTE:In many cases here we are assigning a 'default' parent. In
- * many cases the parent is selectable. The set parent calls will
- * also switch sources.
- *
- * Several sources are given initial rates which may be wrong, this will
- * be fixed up in the init func.
- *
- * Things are broadly separated below by clock domains. It is
- * noteworthy that most peripherals have dependencies on multiple clock
- * domains. Many get their interface clocks from the L4 domain, but get
- * functional clocks from fixed sources or other core domain derived
- * clocks.
- */
-
-DEFINE_CLK_FIXED_RATE(alt_ck, CLK_IS_ROOT, 54000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(func_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(mcbsp_clks, CLK_IS_ROOT, 0x0, 0x0);
-
-static struct clk osc_ck;
-
-static const struct clk_ops osc_ck_ops = {
- .enable = &omap2_enable_osc_ck,
- .disable = omap2_disable_osc_ck,
- .recalc_rate = &omap2_osc_clk_recalc,
-};
-
-static struct clk_hw_omap osc_ck_hw = {
- .hw = {
- .clk = &osc_ck,
- },
-};
-
-static struct clk osc_ck = {
- .name = "osc_ck",
- .ops = &osc_ck_ops,
- .hw = &osc_ck_hw.hw,
- .flags = CLK_IS_ROOT,
-};
-
-DEFINE_CLK_FIXED_RATE(secure_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-static struct clk sys_ck;
-
-static const char *sys_ck_parent_names[] = {
- "osc_ck",
-};
-
-static const struct clk_ops sys_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .recalc_rate = &omap2xxx_sys_clk_recalc,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(sys_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(sys_ck, sys_ck_parent_names, sys_ck_ops);
-
-static struct dpll_data dpll_dd = {
- .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .mult_mask = OMAP24XX_DPLL_MULT_MASK,
- .div1_mask = OMAP24XX_DPLL_DIV_MASK,
- .clk_bypass = &sys_ck,
- .clk_ref = &sys_ck,
- .control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_mask = OMAP24XX_EN_DPLL_MASK,
- .max_multiplier = 1023,
- .min_divider = 1,
- .max_divider = 16,
-};
-
-static struct clk dpll_ck;
-
-static const char *dpll_ck_parent_names[] = {
- "sys_ck",
-};
-
-static const struct clk_ops dpll_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .get_parent = &omap2_init_dpll_parent,
- .recalc_rate = &omap2_dpllcore_recalc,
- .round_rate = &omap2_dpll_round_rate,
- .set_rate = &omap2_reprogram_dpllcore,
-};
-
-static struct clk_hw_omap dpll_ck_hw = {
- .hw = {
- .clk = &dpll_ck,
- },
- .ops = &clkhwops_omap2xxx_dpll,
- .dpll_data = &dpll_dd,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dpll_ck, dpll_ck_parent_names, dpll_ck_ops);
-
-static struct clk core_ck;
-
-static const char *core_ck_parent_names[] = {
- "dpll_ck",
-};
-
-static const struct clk_ops core_ck_ops = {
- .init = &omap2_init_clk_clkdm,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(core_ck, "wkup_clkdm");
-DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-
-DEFINE_CLK_DIVIDER(core_l3_ck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_L3_SHIFT, OMAP24XX_CLKSEL_L3_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(l4_ck, "core_l3_ck", &core_l3_ck, 0x0,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_L4_SHIFT, OMAP24XX_CLKSEL_L4_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk aes_ick;
-
-static const char *aes_ick_parent_names[] = {
- "l4_ck",
-};
-
-static const struct clk_ops aes_ick_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap aes_ick_hw = {
- .hw = {
- .clk = &aes_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_AES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(aes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk apll54_ck;
-
-static const struct clk_ops apll54_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_clk_apll54_enable,
- .disable = &omap2_clk_apll54_disable,
- .recalc_rate = &omap2_clk_apll54_recalc,
-};
-
-static struct clk_hw_omap apll54_ck_hw = {
- .hw = {
- .clk = &apll54_ck,
- },
- .ops = &clkhwops_apll54,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_54M_PLL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll54_ck, dpll_ck_parent_names, apll54_ck_ops);
-
-static struct clk apll96_ck;
-
-static const struct clk_ops apll96_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_clk_apll96_enable,
- .disable = &omap2_clk_apll96_disable,
- .recalc_rate = &omap2_clk_apll96_recalc,
-};
-
-static struct clk_hw_omap apll96_ck_hw = {
- .hw = {
- .clk = &apll96_ck,
- },
- .ops = &clkhwops_apll96,
- .enable_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
- .enable_bit = OMAP24XX_EN_96M_PLL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(apll96_ck, dpll_ck_parent_names, apll96_ck_ops);
-
-static const char *func_96m_ck_parent_names[] = {
- "apll96_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_96m_ck, func_96m_ck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), OMAP2430_96M_SOURCE_SHIFT,
- OMAP2430_96M_SOURCE_WIDTH, 0x0, NULL);
-
-static struct clk cam_fck;
-
-static const char *cam_fck_parent_names[] = {
- "func_96m_ck",
-};
-
-static struct clk_hw_omap cam_fck_hw = {
- .hw = {
- .clk = &cam_fck,
- },
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk cam_ick;
-
-static struct clk_hw_omap cam_ick_hw = {
- .hw = {
- .clk = &cam_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_CAM_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(cam_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk des_ick;
-
-static struct clk_hw_omap des_ick_hw = {
- .hw = {
- .clk = &des_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_DES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(des_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate dsp_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dsp_fck_clksel[] = {
- { .parent = &core_ck, .rates = dsp_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *dsp_fck_parent_names[] = {
- "core_ck",
-};
-
-static struct clk dsp_fck;
-
-static const struct clk_ops dsp_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dsp_fck, "dsp_clkdm", dsp_fck_clksel,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_DSP_MASK,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
- dsp_fck_parent_names, dsp_fck_ops);
-
-static const struct clksel_rate dss1_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss1_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_24XX },
- { .div = 6, .val = 6, .flags = RATE_IN_24XX },
- { .div = 8, .val = 8, .flags = RATE_IN_24XX },
- { .div = 9, .val = 9, .flags = RATE_IN_24XX },
- { .div = 12, .val = 12, .flags = RATE_IN_24XX },
- { .div = 16, .val = 16, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel dss1_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss1_fck_sys_rates },
- { .parent = &core_ck, .rates = dss1_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *dss1_fck_parent_names[] = {
- "sys_ck", "core_ck",
-};
-
-static const struct clk_ops dss1_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss1_fck, "dss_clkdm", dss1_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_DSS1_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_DSS1_SHIFT, NULL,
- dss1_fck_parent_names, dss1_fck_ops);
-
-static const struct clksel_rate dss2_fck_sys_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate dss2_fck_48m_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate func_48m_apll96_rates[] = {
- { .div = 2, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate func_48m_alt_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel func_48m_clksel[] = {
- { .parent = &apll96_ck, .rates = func_48m_apll96_rates },
- { .parent = &alt_ck, .rates = func_48m_alt_rates },
- { .parent = NULL },
-};
-
-static const char *func_48m_ck_parent_names[] = {
- "apll96_ck", "alt_ck",
-};
-
-static struct clk func_48m_ck;
-
-static const struct clk_ops func_48m_ck_ops = {
- .init = &omap2_init_clk_clkdm,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-static struct clk_hw_omap func_48m_ck_hw = {
- .hw = {
- .clk = &func_48m_ck,
- },
- .clksel = func_48m_clksel,
- .clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP24XX_48M_SOURCE_MASK,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(func_48m_ck, func_48m_ck_parent_names, func_48m_ck_ops);
-
-static const struct clksel dss2_fck_clksel[] = {
- { .parent = &sys_ck, .rates = dss2_fck_sys_rates },
- { .parent = &func_48m_ck, .rates = dss2_fck_48m_rates },
- { .parent = NULL },
-};
-
-static const char *dss2_fck_parent_names[] = {
- "sys_ck", "func_48m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(dss2_fck, "dss_clkdm", dss2_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_DSS2_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_DSS2_SHIFT, NULL,
- dss2_fck_parent_names, dss1_fck_ops);
-
-static const char *func_54m_ck_parent_names[] = {
- "apll54_ck", "alt_ck",
-};
-
-DEFINE_CLK_MUX(func_54m_ck, func_54m_ck_parent_names, NULL, 0x0,
- OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
- OMAP24XX_54M_SOURCE_SHIFT, OMAP24XX_54M_SOURCE_WIDTH, 0x0, NULL);
-
-static struct clk dss_54m_fck;
-
-static const char *dss_54m_fck_parent_names[] = {
- "func_54m_ck",
-};
-
-static struct clk_hw_omap dss_54m_fck_hw = {
- .hw = {
- .clk = &dss_54m_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_TV_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_54m_fck, dss_54m_fck_parent_names, aes_ick_ops);
-
-static struct clk dss_ick;
-
-static struct clk_hw_omap dss_ick_hw = {
- .hw = {
- .clk = &dss_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_DSS1_SHIFT,
- .clkdm_name = "dss_clkdm",
-};
-
-DEFINE_STRUCT_CLK(dss_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk emul_ck;
-
-static struct clk_hw_omap emul_ck_hw = {
- .hw = {
- .clk = &emul_ck,
- },
- .enable_reg = OMAP2430_PRCM_CLKEMUL_CTRL,
- .enable_bit = OMAP24XX_EMULATION_EN_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(emul_ck, dss_54m_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_FIXED_FACTOR(func_12m_ck, "func_48m_ck", &func_48m_ck, 0x0, 1, 4);
-
-static struct clk fac_fck;
-
-static const char *fac_fck_parent_names[] = {
- "func_12m_ck",
-};
-
-static struct clk_hw_omap fac_fck_hw = {
- .hw = {
- .clk = &fac_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk fac_ick;
-
-static struct clk_hw_omap fac_ick_hw = {
- .hw = {
- .clk = &fac_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_FAC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(fac_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel gfx_fck_clksel[] = {
- { .parent = &core_l3_ck, .rates = gfx_l3_rates },
- { .parent = NULL },
-};
-
-static const char *gfx_2d_fck_parent_names[] = {
- "core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_2d_fck, "gfx_clkdm", gfx_fck_clksel,
- OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- OMAP_CLKSEL_GFX_MASK,
- OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- OMAP24XX_EN_2D_SHIFT, &clkhwops_wait,
- gfx_2d_fck_parent_names, dsp_fck_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gfx_3d_fck, "gfx_clkdm", gfx_fck_clksel,
- OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
- OMAP_CLKSEL_GFX_MASK,
- OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
- OMAP24XX_EN_3D_SHIFT, &clkhwops_wait,
- gfx_2d_fck_parent_names, dsp_fck_ops);
-
-static struct clk gfx_ick;
-
-static const char *gfx_ick_parent_names[] = {
- "core_l3_ck",
-};
-
-static struct clk_hw_omap gfx_ick_hw = {
- .hw = {
- .clk = &gfx_ick,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
- .enable_bit = OMAP_EN_GFX_SHIFT,
- .clkdm_name = "gfx_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gfx_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk gpio5_fck;
-
-static const char *gpio5_fck_parent_names[] = {
- "func_32k_ck",
-};
-
-static struct clk_hw_omap gpio5_fck_hw = {
- .hw = {
- .clk = &gpio5_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk gpio5_ick;
-
-static struct clk_hw_omap gpio5_ick_hw = {
- .hw = {
- .clk = &gpio5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_GPIO5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpio5_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk gpios_fck;
-
-static struct clk_hw_omap gpios_fck_hw = {
- .hw = {
- .clk = &gpios_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk gpios_ick;
-
-static const char *gpios_ick_parent_names[] = {
- "sys_ck",
-};
-
-static struct clk_hw_omap gpios_ick_hw = {
- .hw = {
- .clk = &gpios_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPIOS_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpios_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk gpmc_fck;
-
-static struct clk_hw_omap gpmc_fck_hw = {
- .hw = {
- .clk = &gpmc_fck,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpmc_fck, gfx_ick_parent_names, core_ck_ops);
-
-static const struct clksel_rate gpt_alt_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel omap24xx_gpt_clksel[] = {
- { .parent = &func_32k_ck, .rates = gpt_32k_rates },
- { .parent = &sys_ck, .rates = gpt_sys_rates },
- { .parent = &alt_ck, .rates = gpt_alt_rates },
- { .parent = NULL },
-};
-
-static const char *gpt10_fck_parent_names[] = {
- "func_32k_ck", "sys_ck", "alt_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt10_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT10_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT10_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt10_ick;
-
-static struct clk_hw_omap gpt10_ick_hw = {
- .hw = {
- .clk = &gpt10_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT10_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt10_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt11_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT11_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT11_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt11_ick;
-
-static struct clk_hw_omap gpt11_ick_hw = {
- .hw = {
- .clk = &gpt11_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT11_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt11_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt12_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT12_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT12_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt12_ick;
-
-static struct clk_hw_omap gpt12_ick_hw = {
- .hw = {
- .clk = &gpt12_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT12_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt12_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clk_ops gpt1_fck_ops = {
- .init = &omap2_init_clk_clkdm,
- .enable = &omap2_dflt_clk_enable,
- .disable = &omap2_dflt_clk_disable,
- .is_enabled = &omap2_dflt_clk_is_enabled,
- .recalc_rate = &omap2_clksel_recalc,
- .set_rate = &omap2_clksel_set_rate,
- .round_rate = &omap2_clksel_round_rate,
- .get_parent = &omap2_clksel_find_parent_index,
- .set_parent = &omap2_clksel_set_parent,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt1_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_GPT1_MASK,
- OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- OMAP24XX_EN_GPT1_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, gpt1_fck_ops);
-
-static struct clk gpt1_ick;
-
-static struct clk_hw_omap gpt1_ick_hw = {
- .hw = {
- .clk = &gpt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_GPT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt2_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT2_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT2_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt2_ick;
-
-static struct clk_hw_omap gpt2_ick_hw = {
- .hw = {
- .clk = &gpt2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt3_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT3_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT3_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt3_ick;
-
-static struct clk_hw_omap gpt3_ick_hw = {
- .hw = {
- .clk = &gpt3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt4_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT4_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT4_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt4_ick;
-
-static struct clk_hw_omap gpt4_ick_hw = {
- .hw = {
- .clk = &gpt4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt5_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT5_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT5_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt5_ick;
-
-static struct clk_hw_omap gpt5_ick_hw = {
- .hw = {
- .clk = &gpt5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt5_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt6_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT6_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT6_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt6_ick;
-
-static struct clk_hw_omap gpt6_ick_hw = {
- .hw = {
- .clk = &gpt6_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT6_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt6_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt7_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT7_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT7_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt7_ick;
-
-static struct clk_hw_omap gpt7_ick_hw = {
- .hw = {
- .clk = &gpt7_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT7_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt7_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk gpt8_fck;
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt8_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT8_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT8_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt8_ick;
-
-static struct clk_hw_omap gpt8_ick_hw = {
- .hw = {
- .clk = &gpt8_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT8_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt8_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(gpt9_fck, "core_l4_clkdm", omap24xx_gpt_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2),
- OMAP24XX_CLKSEL_GPT9_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_GPT9_SHIFT, &clkhwops_wait,
- gpt10_fck_parent_names, dss1_fck_ops);
-
-static struct clk gpt9_ick;
-
-static struct clk_hw_omap gpt9_ick_hw = {
- .hw = {
- .clk = &gpt9_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_GPT9_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(gpt9_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk hdq_fck;
-
-static struct clk_hw_omap hdq_fck_hw = {
- .hw = {
- .clk = &hdq_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_fck, fac_fck_parent_names, aes_ick_ops);
-
-static struct clk hdq_ick;
-
-static struct clk_hw_omap hdq_ick_hw = {
- .hw = {
- .clk = &hdq_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_HDQ_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(hdq_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c1_ick;
-
-static struct clk_hw_omap i2c1_ick_hw = {
- .hw = {
- .clk = &i2c1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2c2_ick;
-
-static struct clk_hw_omap i2c2_ick_hw = {
- .hw = {
- .clk = &i2c2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP2420_EN_I2C2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2c2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk i2chs1_fck;
-
-static struct clk_hw_omap i2chs1_fck_hw = {
- .hw = {
- .clk = &i2chs1_fck,
- },
- .ops = &clkhwops_omap2430_i2chs_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_I2CHS1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2chs1_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk i2chs2_fck;
-
-static struct clk_hw_omap i2chs2_fck_hw = {
- .hw = {
- .clk = &i2chs2_fck,
- },
- .ops = &clkhwops_omap2430_i2chs_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_I2CHS2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(i2chs2_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk icr_ick;
-
-static struct clk_hw_omap icr_ick_hw = {
- .hw = {
- .clk = &icr_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP2430_EN_ICR_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(icr_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel dsp_ick_clksel[] = {
- { .parent = &dsp_fck, .rates = dsp_ick_rates },
- { .parent = NULL },
-};
-
-static const char *iva2_1_ick_parent_names[] = {
- "dsp_fck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(iva2_1_ick, "dsp_clkdm", dsp_ick_clksel,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_DSP_IF_MASK,
- OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
- OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, &clkhwops_wait,
- iva2_1_ick_parent_names, dsp_fck_ops);
-
-static struct clk mailboxes_ick;
-
-static struct clk_hw_omap mailboxes_ick_hw = {
- .hw = {
- .clk = &mailboxes_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mailboxes_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_mcbsp_96m_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel mcbsp_fck_clksel[] = {
- { .parent = &func_96m_ck, .rates = common_mcbsp_96m_rates },
- { .parent = &mcbsp_clks, .rates = common_mcbsp_mcbsp_rates },
- { .parent = NULL },
-};
-
-static const char *mcbsp1_fck_parent_names[] = {
- "func_96m_ck", "mcbsp_clks",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP1_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_MCBSP1_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp1_ick;
-
-static struct clk_hw_omap mcbsp1_ick_hw = {
- .hw = {
- .clk = &mcbsp1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp1_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
- OMAP2_MCBSP2_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- OMAP24XX_EN_MCBSP2_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp2_ick;
-
-static struct clk_hw_omap mcbsp2_ick_hw = {
- .hw = {
- .clk = &mcbsp2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCBSP2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp2_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- OMAP2_MCBSP3_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- OMAP2430_EN_MCBSP3_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp3_ick;
-
-static struct clk_hw_omap mcbsp3_ick_hw = {
- .hw = {
- .clk = &mcbsp3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp3_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- OMAP2_MCBSP4_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- OMAP2430_EN_MCBSP4_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp4_ick;
-
-static struct clk_hw_omap mcbsp4_ick_hw = {
- .hw = {
- .clk = &mcbsp4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp4_ick, aes_ick_parent_names, aes_ick_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp5_fck, "core_l4_clkdm", mcbsp_fck_clksel,
- OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
- OMAP2_MCBSP5_CLKS_MASK,
- OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- OMAP2430_EN_MCBSP5_SHIFT, &clkhwops_wait,
- mcbsp1_fck_parent_names, dss1_fck_ops);
-
-static struct clk mcbsp5_ick;
-
-static struct clk_hw_omap mcbsp5_ick_hw = {
- .hw = {
- .clk = &mcbsp5_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCBSP5_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcbsp5_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_fck;
-
-static const char *mcspi1_fck_parent_names[] = {
- "func_48m_ck",
-};
-
-static struct clk_hw_omap mcspi1_fck_hw = {
- .hw = {
- .clk = &mcspi1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi1_ick;
-
-static struct clk_hw_omap mcspi1_ick_hw = {
- .hw = {
- .clk = &mcspi1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_fck;
-
-static struct clk_hw_omap mcspi2_fck_hw = {
- .hw = {
- .clk = &mcspi2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi2_ick;
-
-static struct clk_hw_omap mcspi2_ick_hw = {
- .hw = {
- .clk = &mcspi2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MCSPI2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mcspi3_fck;
-
-static struct clk_hw_omap mcspi3_fck_hw = {
- .hw = {
- .clk = &mcspi3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk mcspi3_ick;
-
-static struct clk_hw_omap mcspi3_ick_hw = {
- .hw = {
- .clk = &mcspi3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MCSPI3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mcspi3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate mdm_ick_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_243X },
- { .div = 4, .val = 4, .flags = RATE_IN_243X },
- { .div = 6, .val = 6, .flags = RATE_IN_243X },
- { .div = 9, .val = 9, .flags = RATE_IN_243X },
- { .div = 0 }
-};
-
-static const struct clksel mdm_ick_clksel[] = {
- { .parent = &core_ck, .rates = mdm_ick_core_rates },
- { .parent = NULL },
-};
-
-static const char *mdm_ick_parent_names[] = {
- "core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(mdm_ick, "mdm_clkdm", mdm_ick_clksel,
- OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
- OMAP2430_CLKSEL_MDM_MASK,
- OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
- OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
- &clkhwops_iclk_wait, mdm_ick_parent_names,
- dsp_fck_ops);
-
-static struct clk mdm_intc_ick;
-
-static struct clk_hw_omap mdm_intc_ick_hw = {
- .hw = {
- .clk = &mdm_intc_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MDM_INTC_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mdm_intc_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mdm_osc_ck;
-
-static struct clk_hw_omap mdm_osc_ck_hw = {
- .hw = {
- .clk = &mdm_osc_ck,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
- .enable_bit = OMAP2430_EN_OSC_SHIFT,
- .clkdm_name = "mdm_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mdm_osc_ck, sys_ck_parent_names, aes_ick_ops);
-
-static struct clk mmchs1_fck;
-
-static struct clk_hw_omap mmchs1_fck_hw = {
- .hw = {
- .clk = &mmchs1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchs1_ick;
-
-static struct clk_hw_omap mmchs1_ick_hw = {
- .hw = {
- .clk = &mmchs1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmchs2_fck;
-
-static struct clk_hw_omap mmchs2_fck_hw = {
- .hw = {
- .clk = &mmchs2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchs2_ick;
-
-static struct clk_hw_omap mmchs2_ick_hw = {
- .hw = {
- .clk = &mmchs2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_MMCHS2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchs2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk mmchsdb1_fck;
-
-static struct clk_hw_omap mmchsdb1_fck_hw = {
- .hw = {
- .clk = &mmchsdb1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHSDB1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchsdb1_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk mmchsdb2_fck;
-
-static struct clk_hw_omap mmchsdb2_fck_hw = {
- .hw = {
- .clk = &mmchsdb2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP2430_EN_MMCHSDB2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mmchsdb2_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-DEFINE_CLK_DIVIDER(mpu_ck, "core_ck", &core_ck, 0x0,
- OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
- OMAP24XX_CLKSEL_MPU_SHIFT, OMAP24XX_CLKSEL_MPU_WIDTH,
- CLK_DIVIDER_ONE_BASED, NULL);
-
-static struct clk mpu_wdt_fck;
-
-static struct clk_hw_omap mpu_wdt_fck_hw = {
- .hw = {
- .clk = &mpu_wdt_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk mpu_wdt_ick;
-
-static struct clk_hw_omap mpu_wdt_ick_hw = {
- .hw = {
- .clk = &mpu_wdt_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mpu_wdt_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk mspro_fck;
-
-static struct clk_hw_omap mspro_fck_hw = {
- .hw = {
- .clk = &mspro_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_fck, cam_fck_parent_names, aes_ick_ops);
-
-static struct clk mspro_ick;
-
-static struct clk_hw_omap mspro_ick_hw = {
- .hw = {
- .clk = &mspro_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_MSPRO_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(mspro_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk omapctrl_ick;
-
-static struct clk_hw_omap omapctrl_ick_hw = {
- .hw = {
- .clk = &omapctrl_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(omapctrl_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk pka_ick;
-
-static struct clk_hw_omap pka_ick_hw = {
- .hw = {
- .clk = &pka_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_PKA_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(pka_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk rng_ick;
-
-static struct clk_hw_omap rng_ick_hw = {
- .hw = {
- .clk = &rng_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_RNG_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(rng_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk sdma_fck;
-
-DEFINE_STRUCT_CLK_HW_OMAP(sdma_fck, "core_l3_clkdm");
-DEFINE_STRUCT_CLK(sdma_fck, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdma_ick;
-
-static struct clk_hw_omap sdma_ick_hw = {
- .hw = {
- .clk = &sdma_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdma_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sdrc_ick;
-
-static struct clk_hw_omap sdrc_ick_hw = {
- .hw = {
- .clk = &sdrc_ick,
- },
- .ops = &clkhwops_iclk,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
- .enable_bit = OMAP2430_EN_SDRC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sdrc_ick, gfx_ick_parent_names, core_ck_ops);
-
-static struct clk sha_ick;
-
-static struct clk_hw_omap sha_ick_hw = {
- .hw = {
- .clk = &sha_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
- .enable_bit = OMAP24XX_EN_SHA_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sha_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk ssi_l4_ick;
-
-static struct clk_hw_omap ssi_l4_ick_hw = {
- .hw = {
- .clk = &ssi_l4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_SSI_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ssi_l4_ick, aes_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate ssi_ssr_sst_fck_core_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 3, .val = 3, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 5, .val = 5, .flags = RATE_IN_243X },
- { .div = 0 }
-};
-
-static const struct clksel ssi_ssr_sst_fck_clksel[] = {
- { .parent = &core_ck, .rates = ssi_ssr_sst_fck_core_rates },
- { .parent = NULL },
-};
-
-static const char *ssi_ssr_sst_fck_parent_names[] = {
- "core_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_sst_fck, "core_l3_clkdm",
- ssi_ssr_sst_fck_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_SSI_MASK,
- OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- OMAP24XX_EN_SSI_SHIFT, &clkhwops_wait,
- ssi_ssr_sst_fck_parent_names, dsp_fck_ops);
-
-static struct clk sync_32k_ick;
-
-static struct clk_hw_omap sync_32k_ick_hw = {
- .hw = {
- .clk = &sync_32k_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT,
- .flags = ENABLE_ON_INIT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(sync_32k_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static const struct clksel_rate common_clkout_src_core_rates[] = {
- { .div = 1, .val = 0, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_sys_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_96m_rates[] = {
- { .div = 1, .val = 2, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel_rate common_clkout_src_54m_rates[] = {
- { .div = 1, .val = 3, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel common_clkout_src_clksel[] = {
- { .parent = &core_ck, .rates = common_clkout_src_core_rates },
- { .parent = &sys_ck, .rates = common_clkout_src_sys_rates },
- { .parent = &func_96m_ck, .rates = common_clkout_src_96m_rates },
- { .parent = &func_54m_ck, .rates = common_clkout_src_54m_rates },
- { .parent = NULL },
-};
-
-static const char *sys_clkout_src_parent_names[] = {
- "core_ck", "sys_ck", "func_96m_ck", "func_54m_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(sys_clkout_src, "wkup_clkdm", common_clkout_src_clksel,
- OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_SOURCE_MASK,
- OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_EN_SHIFT,
- NULL, sys_clkout_src_parent_names, gpt1_fck_ops);
-
-DEFINE_CLK_DIVIDER(sys_clkout, "sys_clkout_src", &sys_clkout_src, 0x0,
- OMAP2430_PRCM_CLKOUT_CTRL, OMAP24XX_CLKOUT_DIV_SHIFT,
- OMAP24XX_CLKOUT_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-static struct clk uart1_fck;
-
-static struct clk_hw_omap uart1_fck_hw = {
- .hw = {
- .clk = &uart1_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart1_ick;
-
-static struct clk_hw_omap uart1_ick_hw = {
- .hw = {
- .clk = &uart1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART1_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart1_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart2_fck;
-
-static struct clk_hw_omap uart2_fck_hw = {
- .hw = {
- .clk = &uart2_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart2_ick;
-
-static struct clk_hw_omap uart2_ick_hw = {
- .hw = {
- .clk = &uart2_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_UART2_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart2_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk uart3_fck;
-
-static struct clk_hw_omap uart3_fck_hw = {
- .hw = {
- .clk = &uart3_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static struct clk uart3_ick;
-
-static struct clk_hw_omap uart3_ick_hw = {
- .hw = {
- .clk = &uart3_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP24XX_EN_UART3_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(uart3_ick, aes_ick_parent_names, aes_ick_ops);
-
-static struct clk usb_fck;
-
-static struct clk_hw_omap usb_fck_hw = {
- .hw = {
- .clk = &usb_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
- .enable_bit = OMAP24XX_EN_USB_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usb_fck, mcspi1_fck_parent_names, aes_ick_ops);
-
-static const struct clksel_rate usb_l4_ick_core_l3_rates[] = {
- { .div = 1, .val = 1, .flags = RATE_IN_24XX },
- { .div = 2, .val = 2, .flags = RATE_IN_24XX },
- { .div = 4, .val = 4, .flags = RATE_IN_24XX },
- { .div = 0 }
-};
-
-static const struct clksel usb_l4_ick_clksel[] = {
- { .parent = &core_l3_ck, .rates = usb_l4_ick_core_l3_rates },
- { .parent = NULL },
-};
-
-static const char *usb_l4_ick_parent_names[] = {
- "core_l3_ck",
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(usb_l4_ick, "core_l4_clkdm", usb_l4_ick_clksel,
- OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
- OMAP24XX_CLKSEL_USB_MASK,
- OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- OMAP24XX_EN_USB_SHIFT, &clkhwops_iclk_wait,
- usb_l4_ick_parent_names, dsp_fck_ops);
-
-static struct clk usbhs_ick;
-
-static struct clk_hw_omap usbhs_ick_hw = {
- .hw = {
- .clk = &usbhs_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
- .enable_bit = OMAP2430_EN_USBHS_SHIFT,
- .clkdm_name = "core_l3_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usbhs_ick, gfx_ick_parent_names, aes_ick_ops);
-
-static struct clk virt_prcm_set;
-
-static const char *virt_prcm_set_parent_names[] = {
- "mpu_ck",
-};
-
-static const struct clk_ops virt_prcm_set_ops = {
- .recalc_rate = &omap2_table_mpu_recalc,
- .set_rate = &omap2_select_table_rate,
- .round_rate = &omap2_round_to_table_rate,
-};
-
-DEFINE_STRUCT_CLK_HW_OMAP(virt_prcm_set, NULL);
-DEFINE_STRUCT_CLK(virt_prcm_set, virt_prcm_set_parent_names, virt_prcm_set_ops);
-
-static struct clk wdt1_ick;
-
-static struct clk_hw_omap wdt1_ick_hw = {
- .hw = {
- .clk = &wdt1_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
- .enable_bit = OMAP24XX_EN_WDT1_SHIFT,
- .clkdm_name = "wkup_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
-
-static struct clk wdt4_fck;
-
-static struct clk_hw_omap wdt4_fck_hw = {
- .hw = {
- .clk = &wdt4_fck,
- },
- .ops = &clkhwops_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_fck, gpio5_fck_parent_names, aes_ick_ops);
-
-static struct clk wdt4_ick;
-
-static struct clk_hw_omap wdt4_ick_hw = {
- .hw = {
- .clk = &wdt4_ick,
- },
- .ops = &clkhwops_iclk_wait,
- .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
- .enable_bit = OMAP24XX_EN_WDT4_SHIFT,
- .clkdm_name = "core_l4_clkdm",
-};
-
-DEFINE_STRUCT_CLK(wdt4_ick, aes_ick_parent_names, aes_ick_ops);
-
-/*
- * clkdev integration
- */
-
-static struct omap_clk omap2430_clks[] = {
- /* external root sources */
- CLK(NULL, "func_32k_ck", &func_32k_ck),
- CLK(NULL, "secure_32k_ck", &secure_32k_ck),
- CLK(NULL, "osc_ck", &osc_ck),
- CLK("twl", "fck", &osc_ck),
- CLK(NULL, "sys_ck", &sys_ck),
- CLK(NULL, "alt_ck", &alt_ck),
- CLK(NULL, "mcbsp_clks", &mcbsp_clks),
- /* internal analog sources */
- CLK(NULL, "dpll_ck", &dpll_ck),
- CLK(NULL, "apll96_ck", &apll96_ck),
- CLK(NULL, "apll54_ck", &apll54_ck),
- /* internal prcm root sources */
- CLK(NULL, "func_54m_ck", &func_54m_ck),
- CLK(NULL, "core_ck", &core_ck),
- CLK(NULL, "func_96m_ck", &func_96m_ck),
- CLK(NULL, "func_48m_ck", &func_48m_ck),
- CLK(NULL, "func_12m_ck", &func_12m_ck),
- CLK(NULL, "sys_clkout_src", &sys_clkout_src),
- CLK(NULL, "sys_clkout", &sys_clkout),
- CLK(NULL, "emul_ck", &emul_ck),
- /* mpu domain clocks */
- CLK(NULL, "mpu_ck", &mpu_ck),
- /* dsp domain clocks */
- CLK(NULL, "dsp_fck", &dsp_fck),
- CLK(NULL, "iva2_1_ick", &iva2_1_ick),
- /* GFX domain clocks */
- CLK(NULL, "gfx_3d_fck", &gfx_3d_fck),
- CLK(NULL, "gfx_2d_fck", &gfx_2d_fck),
- CLK(NULL, "gfx_ick", &gfx_ick),
- /* Modem domain clocks */
- CLK(NULL, "mdm_ick", &mdm_ick),
- CLK(NULL, "mdm_osc_ck", &mdm_osc_ck),
- /* DSS domain clocks */
- CLK("omapdss_dss", "ick", &dss_ick),
- CLK(NULL, "dss_ick", &dss_ick),
- CLK(NULL, "dss1_fck", &dss1_fck),
- CLK(NULL, "dss2_fck", &dss2_fck),
- CLK(NULL, "dss_54m_fck", &dss_54m_fck),
- /* L3 domain clocks */
- CLK(NULL, "core_l3_ck", &core_l3_ck),
- CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck),
- CLK(NULL, "usb_l4_ick", &usb_l4_ick),
- /* L4 domain clocks */
- CLK(NULL, "l4_ck", &l4_ck),
- CLK(NULL, "ssi_l4_ick", &ssi_l4_ick),
- /* virtual meta-group clock */
- CLK(NULL, "virt_prcm_set", &virt_prcm_set),
- /* general l4 interface ck, multi-parent functional clk */
- CLK(NULL, "gpt1_ick", &gpt1_ick),
- CLK(NULL, "gpt1_fck", &gpt1_fck),
- CLK(NULL, "gpt2_ick", &gpt2_ick),
- CLK(NULL, "gpt2_fck", &gpt2_fck),
- CLK(NULL, "gpt3_ick", &gpt3_ick),
- CLK(NULL, "gpt3_fck", &gpt3_fck),
- CLK(NULL, "gpt4_ick", &gpt4_ick),
- CLK(NULL, "gpt4_fck", &gpt4_fck),
- CLK(NULL, "gpt5_ick", &gpt5_ick),
- CLK(NULL, "gpt5_fck", &gpt5_fck),
- CLK(NULL, "gpt6_ick", &gpt6_ick),
- CLK(NULL, "gpt6_fck", &gpt6_fck),
- CLK(NULL, "gpt7_ick", &gpt7_ick),
- CLK(NULL, "gpt7_fck", &gpt7_fck),
- CLK(NULL, "gpt8_ick", &gpt8_ick),
- CLK(NULL, "gpt8_fck", &gpt8_fck),
- CLK(NULL, "gpt9_ick", &gpt9_ick),
- CLK(NULL, "gpt9_fck", &gpt9_fck),
- CLK(NULL, "gpt10_ick", &gpt10_ick),
- CLK(NULL, "gpt10_fck", &gpt10_fck),
- CLK(NULL, "gpt11_ick", &gpt11_ick),
- CLK(NULL, "gpt11_fck", &gpt11_fck),
- CLK(NULL, "gpt12_ick", &gpt12_ick),
- CLK(NULL, "gpt12_fck", &gpt12_fck),
- CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
- CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
- CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
- CLK("omap-mcbsp.2", "ick", &mcbsp2_ick),
- CLK(NULL, "mcbsp2_ick", &mcbsp2_ick),
- CLK(NULL, "mcbsp2_fck", &mcbsp2_fck),
- CLK("omap-mcbsp.3", "ick", &mcbsp3_ick),
- CLK(NULL, "mcbsp3_ick", &mcbsp3_ick),
- CLK(NULL, "mcbsp3_fck", &mcbsp3_fck),
- CLK("omap-mcbsp.4", "ick", &mcbsp4_ick),
- CLK(NULL, "mcbsp4_ick", &mcbsp4_ick),
- CLK(NULL, "mcbsp4_fck", &mcbsp4_fck),
- CLK("omap-mcbsp.5", "ick", &mcbsp5_ick),
- CLK(NULL, "mcbsp5_ick", &mcbsp5_ick),
- CLK(NULL, "mcbsp5_fck", &mcbsp5_fck),
- CLK("omap2_mcspi.1", "ick", &mcspi1_ick),
- CLK(NULL, "mcspi1_ick", &mcspi1_ick),
- CLK(NULL, "mcspi1_fck", &mcspi1_fck),
- CLK("omap2_mcspi.2", "ick", &mcspi2_ick),
- CLK(NULL, "mcspi2_ick", &mcspi2_ick),
- CLK(NULL, "mcspi2_fck", &mcspi2_fck),
- CLK("omap2_mcspi.3", "ick", &mcspi3_ick),
- CLK(NULL, "mcspi3_ick", &mcspi3_ick),
- CLK(NULL, "mcspi3_fck", &mcspi3_fck),
- CLK(NULL, "uart1_ick", &uart1_ick),
- CLK(NULL, "uart1_fck", &uart1_fck),
- CLK(NULL, "uart2_ick", &uart2_ick),
- CLK(NULL, "uart2_fck", &uart2_fck),
- CLK(NULL, "uart3_ick", &uart3_ick),
- CLK(NULL, "uart3_fck", &uart3_fck),
- CLK(NULL, "gpios_ick", &gpios_ick),
- CLK(NULL, "gpios_fck", &gpios_fck),
- CLK("omap_wdt", "ick", &mpu_wdt_ick),
- CLK(NULL, "mpu_wdt_ick", &mpu_wdt_ick),
- CLK(NULL, "mpu_wdt_fck", &mpu_wdt_fck),
- CLK(NULL, "sync_32k_ick", &sync_32k_ick),
- CLK(NULL, "wdt1_ick", &wdt1_ick),
- CLK(NULL, "omapctrl_ick", &omapctrl_ick),
- CLK(NULL, "icr_ick", &icr_ick),
- CLK("omap24xxcam", "fck", &cam_fck),
- CLK(NULL, "cam_fck", &cam_fck),
- CLK("omap24xxcam", "ick", &cam_ick),
- CLK(NULL, "cam_ick", &cam_ick),
- CLK(NULL, "mailboxes_ick", &mailboxes_ick),
- CLK(NULL, "wdt4_ick", &wdt4_ick),
- CLK(NULL, "wdt4_fck", &wdt4_fck),
- CLK(NULL, "mspro_ick", &mspro_ick),
- CLK(NULL, "mspro_fck", &mspro_fck),
- CLK(NULL, "fac_ick", &fac_ick),
- CLK(NULL, "fac_fck", &fac_fck),
- CLK("omap_hdq.0", "ick", &hdq_ick),
- CLK(NULL, "hdq_ick", &hdq_ick),
- CLK("omap_hdq.1", "fck", &hdq_fck),
- CLK(NULL, "hdq_fck", &hdq_fck),
- CLK("omap_i2c.1", "ick", &i2c1_ick),
- CLK(NULL, "i2c1_ick", &i2c1_ick),
- CLK(NULL, "i2chs1_fck", &i2chs1_fck),
- CLK("omap_i2c.2", "ick", &i2c2_ick),
- CLK(NULL, "i2c2_ick", &i2c2_ick),
- CLK(NULL, "i2chs2_fck", &i2chs2_fck),
- CLK(NULL, "gpmc_fck", &gpmc_fck),
- CLK(NULL, "sdma_fck", &sdma_fck),
- CLK(NULL, "sdma_ick", &sdma_ick),
- CLK(NULL, "sdrc_ick", &sdrc_ick),
- CLK(NULL, "des_ick", &des_ick),
- CLK("omap-sham", "ick", &sha_ick),
- CLK(NULL, "sha_ick", &sha_ick),
- CLK("omap_rng", "ick", &rng_ick),
- CLK(NULL, "rng_ick", &rng_ick),
- CLK("omap-aes", "ick", &aes_ick),
- CLK(NULL, "aes_ick", &aes_ick),
- CLK(NULL, "pka_ick", &pka_ick),
- CLK(NULL, "usb_fck", &usb_fck),
- CLK("musb-omap2430", "ick", &usbhs_ick),
- CLK(NULL, "usbhs_ick", &usbhs_ick),
- CLK("omap_hsmmc.0", "ick", &mmchs1_ick),
- CLK(NULL, "mmchs1_ick", &mmchs1_ick),
- CLK(NULL, "mmchs1_fck", &mmchs1_fck),
- CLK("omap_hsmmc.1", "ick", &mmchs2_ick),
- CLK(NULL, "mmchs2_ick", &mmchs2_ick),
- CLK(NULL, "mmchs2_fck", &mmchs2_fck),
- CLK(NULL, "gpio5_ick", &gpio5_ick),
- CLK(NULL, "gpio5_fck", &gpio5_fck),
- CLK(NULL, "mdm_intc_ick", &mdm_intc_ick),
- CLK("omap_hsmmc.0", "mmchsdb_fck", &mmchsdb1_fck),
- CLK(NULL, "mmchsdb1_fck", &mmchsdb1_fck),
- CLK("omap_hsmmc.1", "mmchsdb_fck", &mmchsdb2_fck),
- CLK(NULL, "mmchsdb2_fck", &mmchsdb2_fck),
- CLK(NULL, "timer_32k_ck", &func_32k_ck),
- CLK(NULL, "timer_sys_ck", &sys_ck),
- CLK(NULL, "timer_ext_ck", &alt_ck),
- CLK(NULL, "cpufreq_ck", &virt_prcm_set),
-};
-
-static const char *enable_init_clks[] = {
- "apll96_ck",
- "apll54_ck",
- "sync_32k_ick",
- "omapctrl_ick",
- "gpmc_fck",
- "sdrc_ick",
-};
-
-/*
- * init code
- */
-
-int __init omap2430_clk_init(void)
-{
- prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL;
- cpu_mask = RATE_IN_243X;
- rate_table = omap2430_rate_table;
-
- omap2xxx_clkt_dpllcore_init(&dpll_ck_hw.hw);
-
- omap2xxx_clkt_vps_check_bootloader_rates();
-
- omap_clocks_register(omap2430_clks, ARRAY_SIZE(omap2430_clks));
-
- omap2xxx_clkt_vps_late_init();
-
- omap2_clk_disable_autoidle_all();
-
- omap2_clk_enable_init_clocks(enable_init_clks,
- ARRAY_SIZE(enable_init_clks));
-
- pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
- (clk_get_rate(&sys_ck) / 1000000),
- (clk_get_rate(&sys_ck) / 100000) % 10,
- (clk_get_rate(&dpll_ck) / 1000000),
- (clk_get_rate(&mpu_ck) / 1000000));
-
- return 0;
-}
diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
deleted file mode 100644
index 0717dff1bc04..000000000000
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * OMAP2xxx osc_clk-specific clock code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-
-/*
- * XXX This does not actually enable the osc_ck, since the osc_ck must
- * be running for this function to be called. Instead, this function
- * is used to disable an autoidle mode on the osc_ck. The existing
- * clk_enable/clk_disable()-based usecounting for osc_ck should be
- * replaced with autoidle-based usecounting.
- */
-int omap2_enable_osc_ck(struct clk_hw *clk)
-{
- u32 pcc;
-
- pcc = readl_relaxed(prcm_clksrc_ctrl);
-
- writel_relaxed(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
-
- return 0;
-}
-
-/*
- * XXX This does not actually disable the osc_ck, since doing so would
- * immediately halt the system. Instead, this function is used to
- * enable an autoidle mode on the osc_ck. The existing
- * clk_enable/clk_disable()-based usecounting for osc_ck should be
- * replaced with autoidle-based usecounting.
- */
-void omap2_disable_osc_ck(struct clk_hw *clk)
-{
- u32 pcc;
-
- pcc = readl_relaxed(prcm_clksrc_ctrl);
-
- writel_relaxed(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
-}
-
-unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
- unsigned long parent_rate)
-{
- return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
-}
diff --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c
deleted file mode 100644
index 58dd3a9b726c..000000000000
--- a/arch/arm/mach-omap2/clkt2xxx_sys.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * OMAP2xxx sys_clk-specific clock code
- *
- * Copyright (C) 2005-2008 Texas Instruments, Inc.
- * Copyright (C) 2004-2010 Nokia Corporation
- *
- * Contacts:
- * Richard Woodruff <r-woodruff2@ti.com>
- * Paul Walmsley
- *
- * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
- * Gordon McNutt and RidgeRun, 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.
- */
-#undef DEBUG
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include "clock.h"
-#include "clock2xxx.h"
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-
-void __iomem *prcm_clksrc_ctrl;
-
-u32 omap2xxx_get_sysclkdiv(void)
-{
- u32 div;
-
- div = readl_relaxed(prcm_clksrc_ctrl);
- div &= OMAP_SYSCLKDIV_MASK;
- div >>= OMAP_SYSCLKDIV_SHIFT;
-
- return div;
-}
-
-unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
- unsigned long parent_rate)
-{
- return parent_rate / omap2xxx_get_sysclkdiv();
-}
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 67fd26a18441..f251a14cbf16 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -21,10 +21,7 @@
#include <asm/div64.h>
-#include "soc.h"
#include "clock.h"
-#include "cm-regbits-24xx.h"
-#include "cm-regbits-34xx.h"
/* DPLL rate rounding: minimum DPLL multiplier, divider values */
#define DPLL_MIN_MULTIPLIER 2
@@ -44,20 +41,12 @@
#define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \
(DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
-/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
-#define OMAP3430_DPLL_FINT_BAND1_MIN 750000
-#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
-#define OMAP3430_DPLL_FINT_BAND2_MIN 7500000
-#define OMAP3430_DPLL_FINT_BAND2_MAX 21000000
-
/*
* DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
* From device data manual section 4.3 "DPLL and DLL Specifications".
*/
#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN 500000
#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX 2500000
-#define OMAP3PLUS_DPLL_FINT_MIN 32000
-#define OMAP3PLUS_DPLL_FINT_MAX 52000000
/* _dpll_test_fint() return codes */
#define DPLL_FINT_UNDERFLOW -1
@@ -87,33 +76,31 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
/* DPLL divider must result in a valid jitter correction val */
fint = __clk_get_rate(__clk_get_parent(clk->hw.clk)) / n;
- if (cpu_is_omap24xx()) {
- /* Should not be called for OMAP2, so warn if it is called */
- WARN(1, "No fint limits available for OMAP2!\n");
- return DPLL_FINT_INVALID;
- } else if (cpu_is_omap3430()) {
- fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
- fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
- } else if (dd->flags & DPLL_J_TYPE) {
+ if (dd->flags & DPLL_J_TYPE) {
fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
} else {
- fint_min = OMAP3PLUS_DPLL_FINT_MIN;
- fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+ fint_min = ti_clk_features.fint_min;
+ fint_max = ti_clk_features.fint_max;
+ }
+
+ if (!fint_min || !fint_max) {
+ WARN(1, "No fint limits available!\n");
+ return DPLL_FINT_INVALID;
}
- if (fint < fint_min) {
+ if (fint < ti_clk_features.fint_min) {
pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
n);
dd->max_divider = n;
ret = DPLL_FINT_UNDERFLOW;
- } else if (fint > fint_max) {
+ } else if (fint > ti_clk_features.fint_max) {
pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
n);
dd->min_divider = n;
ret = DPLL_FINT_INVALID;
- } else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
- fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
+ } else if (fint > ti_clk_features.fint_band1_max &&
+ fint < ti_clk_features.fint_band2_min) {
pr_debug("rejecting n=%d due to Fint failure\n", n);
ret = DPLL_FINT_INVALID;
}
@@ -185,6 +172,34 @@ static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
return r;
}
+/**
+ * _omap2_dpll_is_in_bypass - check if DPLL is in bypass mode or not
+ * @v: bitfield value of the DPLL enable
+ *
+ * Checks given DPLL enable bitfield to see whether the DPLL is in bypass
+ * mode or not. Returns 1 if the DPLL is in bypass, 0 otherwise.
+ */
+static int _omap2_dpll_is_in_bypass(u32 v)
+{
+ u8 mask, val;
+
+ mask = ti_clk_features.dpll_bypass_vals;
+
+ /*
+ * Each set bit in the mask corresponds to a bypass value equal
+ * to the bitshift. Go through each set-bit in the mask and
+ * compare against the given register value.
+ */
+ while (mask) {
+ val = __ffs(mask);
+ mask ^= (1 << val);
+ if (v == val)
+ return 1;
+ }
+
+ return 0;
+}
+
/* Public functions */
u8 omap2_init_dpll_parent(struct clk_hw *hw)
{
@@ -201,20 +216,9 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
v >>= __ffs(dd->enable_mask);
/* Reparent the struct clk in case the dpll is in bypass */
- if (cpu_is_omap24xx()) {
- if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
- v == OMAP2XXX_EN_DPLL_FRBYPASS)
- return 1;
- } else if (cpu_is_omap34xx()) {
- if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
- v == OMAP3XXX_EN_DPLL_FRBYPASS)
- return 1;
- } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
- if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
- v == OMAP4XXX_EN_DPLL_FRBYPASS ||
- v == OMAP4XXX_EN_DPLL_MNBYPASS)
- return 1;
- }
+ if (_omap2_dpll_is_in_bypass(v))
+ return 1;
+
return 0;
}
@@ -247,20 +251,8 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
v &= dd->enable_mask;
v >>= __ffs(dd->enable_mask);
- if (cpu_is_omap24xx()) {
- if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
- v == OMAP2XXX_EN_DPLL_FRBYPASS)
- return __clk_get_rate(dd->clk_bypass);
- } else if (cpu_is_omap34xx()) {
- if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
- v == OMAP3XXX_EN_DPLL_FRBYPASS)
- return __clk_get_rate(dd->clk_bypass);
- } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) {
- if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
- v == OMAP4XXX_EN_DPLL_FRBYPASS ||
- v == OMAP4XXX_EN_DPLL_MNBYPASS)
- return __clk_get_rate(dd->clk_bypass);
- }
+ if (_omap2_dpll_is_in_bypass(v))
+ return __clk_get_rate(dd->clk_bypass);
v = omap2_clk_readl(clk, dd->mult_div1_reg);
dpll_mult = v & dd->mult_mask;
@@ -293,10 +285,13 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
int m, n, r, scaled_max_m;
+ int min_delta_m = INT_MAX, min_delta_n = INT_MAX;
unsigned long scaled_rt_rp;
unsigned long new_rate = 0;
struct dpll_data *dd;
unsigned long ref_rate;
+ long delta;
+ long prev_min_delta = LONG_MAX;
const char *clk_name;
if (!clk || !clk->dpll_data)
@@ -342,23 +337,34 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
if (r == DPLL_MULT_UNDERFLOW)
continue;
+ /* skip rates above our target rate */
+ delta = target_rate - new_rate;
+ if (delta < 0)
+ continue;
+
+ if (delta < prev_min_delta) {
+ prev_min_delta = delta;
+ min_delta_m = m;
+ min_delta_n = n;
+ }
+
pr_debug("clock: %s: m = %d: n = %d: new_rate = %lu\n",
clk_name, m, n, new_rate);
- if (target_rate == new_rate) {
- dd->last_rounded_m = m;
- dd->last_rounded_n = n;
- dd->last_rounded_rate = target_rate;
+ if (delta == 0)
break;
- }
}
- if (target_rate != new_rate) {
+ if (prev_min_delta == LONG_MAX) {
pr_debug("clock: %s: cannot round to rate %lu\n",
clk_name, target_rate);
return ~0;
}
- return target_rate;
+ dd->last_rounded_m = min_delta_m;
+ dd->last_rounded_n = min_delta_n;
+ dd->last_rounded_rate = target_rate - prev_min_delta;
+
+ return dd->last_rounded_rate;
}
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
index 333f0a666171..55eb579aeae1 100644
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -14,11 +14,11 @@
#include <linux/clk-provider.h>
#include <linux/io.h>
-
#include "clock.h"
-#include "clock2xxx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
+
+/* Register offsets */
+#define CM_AUTOIDLE 0x30
+#define CM_ICLKEN 0x10
/* Private functions */
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 591581a66532..500530d1364a 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -47,6 +47,24 @@
u16 cpu_mask;
/*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features ti_clk_features;
+
+/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
+#define OMAP3430_DPLL_FINT_BAND1_MIN 750000
+#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
+#define OMAP3430_DPLL_FINT_BAND2_MIN 7500000
+#define OMAP3430_DPLL_FINT_BAND2_MAX 21000000
+
+/*
+ * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
+ * From device data manual section 4.3 "DPLL and DLL Specifications".
+ */
+#define OMAP3PLUS_DPLL_FINT_MIN 32000
+#define OMAP3PLUS_DPLL_FINT_MAX 52000000
+
+/*
* clkdm_control: if true, then when a clock is enabled in the
* hardware, its clockdomain will first be enabled; and when a clock
* is disabled in the hardware, its clockdomain will be disabled
@@ -82,27 +100,6 @@ u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
}
/*
- * Used for clocks that have the same value as the parent clock,
- * divided by some factor
- */
-unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct clk_hw_omap *oclk;
-
- if (!hw) {
- pr_warn("%s: hw is NULL\n", __func__);
- return -EINVAL;
- }
-
- oclk = to_clk_hw_omap(hw);
-
- WARN_ON(!oclk->fixed_div);
-
- return parent_rate / oclk->fixed_div;
-}
-
-/*
* OMAP2+ specific clock functions
*/
@@ -287,13 +284,7 @@ void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
* 34xx reverses this, just to keep us on our toes
* AM35xx uses both, depending on the module.
*/
- if (cpu_is_omap24xx())
- *idlest_val = OMAP24XX_CM_IDLEST_VAL;
- else if (cpu_is_omap34xx())
- *idlest_val = OMAP34XX_CM_IDLEST_VAL;
- else
- BUG();
-
+ *idlest_val = ti_clk_features.cm_idlest_val;
}
/**
@@ -731,3 +722,53 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
(clk_get_rate(core_ck) / 1000000),
(clk_get_rate(mpu_ck) / 1000000));
}
+
+/**
+ * ti_clk_init_features - init clock features struct for the SoC
+ *
+ * Initializes the clock features struct based on the SoC type.
+ */
+void __init ti_clk_init_features(void)
+{
+ /* Fint setup for DPLLs */
+ if (cpu_is_omap3430()) {
+ ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
+ ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
+ ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
+ ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
+ } else {
+ ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
+ ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
+ }
+
+ /* Bypass value setup for DPLLs */
+ if (cpu_is_omap24xx()) {
+ ti_clk_features.dpll_bypass_vals |=
+ (1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
+ (1 << OMAP2XXX_EN_DPLL_FRBYPASS);
+ } else if (cpu_is_omap34xx()) {
+ ti_clk_features.dpll_bypass_vals |=
+ (1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
+ (1 << OMAP3XXX_EN_DPLL_FRBYPASS);
+ } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
+ soc_is_omap54xx() || soc_is_dra7xx()) {
+ ti_clk_features.dpll_bypass_vals |=
+ (1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
+ (1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
+ (1 << OMAP4XXX_EN_DPLL_MNBYPASS);
+ }
+
+ /* Jitter correction only available on OMAP343X */
+ if (cpu_is_omap343x())
+ ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
+
+ /* Idlest value for interface clocks.
+ * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+ * 34xx reverses this, just to keep us on our toes
+ * AM35xx uses both, depending on the module.
+ */
+ if (cpu_is_omap24xx())
+ ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
+ else if (cpu_is_omap34xx())
+ ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 12f54d428d7c..4592a2762592 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -101,31 +101,6 @@ struct clockdomain;
}; \
DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
-#define DEFINE_CLK_OMAP_HSDIVIDER(_name, _parent_name, \
- _parent_ptr, _flags, \
- _clksel_reg, _clksel_mask) \
- static const struct clksel _name##_div[] = { \
- { \
- .parent = _parent_ptr, \
- .rates = div31_1to31_rates \
- }, \
- { .parent = NULL }, \
- }; \
- static struct clk _name; \
- static const char *_name##_parent_names[] = { \
- _parent_name, \
- }; \
- static struct clk_hw_omap _name##_hw = { \
- .hw = { \
- .clk = &_name, \
- }, \
- .clksel = _name##_div, \
- .clksel_reg = _clksel_reg, \
- .clksel_mask = _clksel_mask, \
- .ops = &clkhwops_omap4_dpllmx, \
- }; \
- DEFINE_STRUCT_CLK(_name, _name##_parent_names, omap_hsdivider_ops);
-
/* struct clksel_rate.flags possibilities */
#define RATE_IN_242X (1 << 0)
#define RATE_IN_243X (1 << 1)
@@ -178,9 +153,6 @@ struct clksel {
const struct clksel_rate *rates;
};
-unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
- unsigned long parent_rate);
-
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
#define CORE_CLK_SRC_32K 0x0
#define CORE_CLK_SRC_DPLL 0x1
@@ -248,6 +220,23 @@ void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
extern u16 cpu_mask;
+/*
+ * Clock features setup. Used instead of CPU type checks.
+ */
+struct ti_clk_features {
+ u32 flags;
+ long fint_min;
+ long fint_max;
+ long fint_band1_max;
+ long fint_band2_min;
+ u8 dpll_bypass_vals;
+ u8 cm_idlest_val;
+};
+
+#define TI_CLK_DPLL_HAS_FREQSEL (1 << 0)
+
+extern struct ti_clk_features ti_clk_features;
+
extern const struct clkops clkops_omap2_dflt_wait;
extern const struct clkops clkops_dummy;
extern const struct clkops clkops_omap2_dflt;
@@ -286,4 +275,6 @@ extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
extern void omap_clocks_register(struct omap_clk *oclks, int cnt);
+
+void __init ti_clk_init_features(void);
#endif
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h
index 45f41a411603..a090225ceeba 100644
--- a/arch/arm/mach-omap2/clock2xxx.h
+++ b/arch/arm/mach-omap2/clock2xxx.h
@@ -45,8 +45,6 @@ int omap2430_clk_init(void);
#define omap2430_clk_init() do { } while(0)
#endif
-extern void __iomem *prcm_clksrc_ctrl;
-
extern struct clk_hw *dclk_hw;
int omap2_enable_osc_ck(struct clk_hw *hw);
void omap2_disable_osc_ck(struct clk_hw *hw);
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index 8538669cc2ad..d7a5d11cbcbf 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -107,6 +107,7 @@
#define OMAP24XX_AUTO_DPLL_SHIFT 0
#define OMAP24XX_AUTO_DPLL_MASK (0x3 << 0)
#define OMAP24XX_APLLS_CLKIN_SHIFT 23
+#define OMAP24XX_APLLS_CLKIN_WIDTH 3
#define OMAP24XX_APLLS_CLKIN_MASK (0x7 << 23)
#define OMAP24XX_DPLL_MULT_MASK (0x3ff << 12)
#define OMAP24XX_DPLL_DIV_MASK (0xf << 8)
diff --git a/arch/arm/mach-omap2/cm2_7xx.h b/arch/arm/mach-omap2/cm2_7xx.h
index 9ad7594e7622..e966e3a3c931 100644
--- a/arch/arm/mach-omap2/cm2_7xx.h
+++ b/arch/arm/mach-omap2/cm2_7xx.h
@@ -357,6 +357,10 @@
#define DRA7XX_CM_L3INIT_SATA_CLKCTRL DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x0088)
#define DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET 0x00a0
#define DRA7XX_CM_PCIE_STATICDEP_OFFSET 0x00a4
+#define DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL_OFFSET 0x00b0
+#define DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x00b0)
+#define DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL_OFFSET 0x00b8
+#define DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL DRA7XX_CM_CORE_REGADDR(DRA7XX_CM_CORE_L3INIT_INST, 0x00b8)
#define DRA7XX_CM_GMAC_CLKSTCTRL_OFFSET 0x00c0
#define DRA7XX_CM_GMAC_STATICDEP_OFFSET 0x00c4
#define DRA7XX_CM_GMAC_DYNAMICDEP_OFFSET 0x00c8
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 2dabb9ecb986..484cdadfb187 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -14,7 +14,6 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/platform_data/dsp-omap.h>
#include "common.h"
#include "omap-secure.h"
@@ -30,7 +29,6 @@ int __weak omap_secure_ram_reserve_memblock(void)
void __init omap_reserve(void)
{
- omap_dsp_reserve_sdram_memblock();
omap_secure_ram_reserve_memblock();
omap_barrier_reserve_memblock();
}
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 751f3549bf6f..da041b4ab29c 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -44,8 +44,7 @@ struct omap3_scratchpad {
};
struct omap3_scratchpad_prcm_block {
- u32 prm_clksrc_ctrl;
- u32 prm_clksel;
+ u32 prm_contents[2];
u32 cm_contents[11];
u32 prcm_block_size;
};
@@ -281,14 +280,11 @@ void omap3_clear_scratchpad_contents(void)
u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
void __iomem *v_addr;
u32 offset = 0;
+
v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
- if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
- OMAP3430_GLOBAL_COLD_RST_MASK) {
+ if (omap3xxx_prm_clear_global_cold_reset()) {
for ( ; offset <= max_offset; offset += 0x4)
writel_relaxed(0x0, (v_addr + offset));
- omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
- OMAP3430_GR_MOD,
- OMAP3_PRM_RSTST_OFFSET);
}
}
@@ -314,7 +310,8 @@ void omap3_save_scratchpad_contents(void)
scratchpad_contents.public_restore_ptr =
virt_to_phys(omap3_restore_3630);
else if (omap_rev() != OMAP3430_REV_ES3_0 &&
- omap_rev() != OMAP3430_REV_ES3_1)
+ omap_rev() != OMAP3430_REV_ES3_1 &&
+ omap_rev() != OMAP3430_REV_ES3_1_2)
scratchpad_contents.public_restore_ptr =
virt_to_phys(omap3_restore);
else
@@ -331,13 +328,7 @@ void omap3_save_scratchpad_contents(void)
scratchpad_contents.sdrc_block_offset = 0x64;
/* Populate the PRCM block contents */
- prcm_block_contents.prm_clksrc_ctrl =
- omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
- OMAP3_PRM_CLKSRC_CTRL_OFFSET);
- prcm_block_contents.prm_clksel =
- omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
- OMAP3_PRM_CLKSEL_OFFSET);
-
+ omap3_prm_save_scratchpad_contents(prcm_block_contents.prm_contents);
omap3_cm_save_scratchpad_contents(prcm_block_contents.cm_contents);
prcm_block_contents.prcm_block_size = 0x0;
@@ -474,7 +465,6 @@ void omap3_control_save_context(void)
control_context.csi = omap_ctrl_readl(OMAP343X_CONTROL_CSI);
control_context.padconf_sys_nirq =
omap_ctrl_readl(OMAP343X_CONTROL_PADCONF_SYSNIRQ);
- return;
}
void omap3_control_restore_context(void)
@@ -532,7 +522,6 @@ void omap3_control_restore_context(void)
omap_ctrl_writel(control_context.csi, OMAP343X_CONTROL_CSI);
omap_ctrl_writel(control_context.padconf_sys_nirq,
OMAP343X_CONTROL_PADCONF_SYSNIRQ);
- return;
}
void omap3630_ctrl_disable_rta(void)
@@ -575,9 +564,50 @@ int omap3_ctrl_save_padconf(void)
* Sets the bootmode for IVA2 to idle. This is needed by the PM code to
* force disable IVA2 so that it does not prevent any low-power states.
*/
-void omap3_ctrl_set_iva_bootmode_idle(void)
+static void __init omap3_ctrl_set_iva_bootmode_idle(void)
{
omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
OMAP343X_CONTROL_IVA2_BOOTMOD);
}
+
+/**
+ * omap3_ctrl_setup_d2d_padconf - setup stacked modem pads for idle
+ *
+ * Sets up the pads controlling the stacked modem in such way that the
+ * device can enter idle.
+ */
+static void __init omap3_ctrl_setup_d2d_padconf(void)
+{
+ u16 mask, padconf;
+
+ /*
+ * In a stand alone OMAP3430 where there is not a stacked
+ * modem for the D2D Idle Ack and D2D MStandby must be pulled
+ * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
+ * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up.
+ */
+ mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
+ padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
+ padconf |= mask;
+ omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
+
+ padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
+ padconf |= mask;
+ omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
+}
+
+/**
+ * omap3_ctrl_init - does static initializations for control module
+ *
+ * Initializes system control module. This sets up the sysconfig autoidle,
+ * and sets up modem and iva2 so that they can be idled properly.
+ */
+void __init omap3_ctrl_init(void)
+{
+ omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
+
+ omap3_ctrl_set_iva_bootmode_idle();
+
+ omap3_ctrl_setup_d2d_padconf();
+}
#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index da054801b114..a3c013345c45 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -16,11 +16,6 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
#define __ARCH_ARM_MACH_OMAP2_CONTROL_H
-#include "ctrl_module_core_44xx.h"
-#include "ctrl_module_wkup_44xx.h"
-#include "ctrl_module_pad_core_44xx.h"
-#include "ctrl_module_pad_wkup_44xx.h"
-
#include "am33xx.h"
#ifndef __ASSEMBLY__
@@ -254,6 +249,39 @@
/* TI81XX CONTROL_DEVCONF register offsets */
#define TI81XX_CONTROL_DEVICE_ID (TI81XX_CONTROL_DEVCONF + 0x000)
+/* OMAP4 CONTROL MODULE */
+#define OMAP4_CTRL_MODULE_PAD_WKUP 0x4a31e000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2 0x0604
+#define OMAP4_CTRL_MODULE_CORE_STATUS 0x02c4
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1 0x0218
+#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR 0x0304
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY 0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX 0x0608
+
+/* OMAP4 CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT 29
+#define OMAP4_DSI2_LANEENABLE_MASK (0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT 24
+#define OMAP4_DSI1_LANEENABLE_MASK (0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT 19
+#define OMAP4_DSI1_PIPD_MASK (0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT 14
+#define OMAP4_DSI2_PIPD_MASK (0x1f << 14)
+
+/* OMAP4 CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT 24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK (0x1f << 24)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT 29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK (0x3 << 29)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT 21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK (1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT 19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK (0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT 18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK (1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT 16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK (0x3 << 16)
+
/* OMAP54XX CONTROL STATUS register */
#define OMAP5XXX_CONTROL_STATUS 0x134
#define OMAP5_DEVICETYPE_MASK (0x7 << 6)
@@ -427,7 +455,7 @@ extern void omap_ctrl_write_dsp_boot_addr(u32 bootaddr);
extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
extern void omap3630_ctrl_disable_rta(void);
extern int omap3_ctrl_save_padconf(void);
-extern void omap3_ctrl_set_iva_bootmode_idle(void);
+void omap3_ctrl_init(void);
extern void omap2_set_globals_control(void __iomem *ctrl,
void __iomem *ctrl_pad);
#else
diff --git a/arch/arm/mach-omap2/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/ctrl_module_core_44xx.h
deleted file mode 100644
index 01970824e0e5..000000000000
--- a/arch/arm/mach-omap2/ctrl_module_core_44xx.h
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_CORE 0x4a002000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_CORE_IP_REVISION 0x0000
-#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO 0x0004
-#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG 0x0010
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0 0x0200
-#define OMAP4_CTRL_MODULE_CORE_ID_CODE 0x0204
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1 0x0208
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2 0x020c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3 0x0210
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0 0x0214
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1 0x0218
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF 0x021c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP 0x0228
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP 0x0260
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0 0x0264
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1 0x0268
-#define OMAP4_CTRL_MODULE_CORE_STATUS 0x02c4
-#define OMAP4_CTRL_MODULE_CORE_DEV_CONF 0x0300
-#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR 0x0304
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL 0x0314
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL 0x0318
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL 0x0320
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL 0x0324
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL 0x0328
-#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR 0x032c
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0 0x0330
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1 0x0334
-#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL 0x033c
-#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL 0x0340
-#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL 0x0350
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL 0x0400
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU 0x0408
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0 0x042c
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1 0x0430
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2 0x0434
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3 0x0438
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0 0x0440
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1 0x0444
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2 0x0448
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL 0x044c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL 0x0450
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL 0x0454
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0 0x0480
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1 0x0484
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2 0x0488
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3 0x048c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4 0x0490
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5 0x0494
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6 0x0498
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7 0x049c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8 0x04a0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9 0x04a4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10 0x04a8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11 0x04ac
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12 0x04b0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13 0x04b4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14 0x04b8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15 0x04bc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16 0x04c0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17 0x04c4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18 0x04c8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19 0x04cc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20 0x04d0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21 0x04d4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22 0x04d8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23 0x04dc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24 0x04e0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25 0x04e4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26 0x04e8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27 0x04ec
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28 0x04f0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29 0x04f4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30 0x04f8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31 0x04fc
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT 30
-#define OMAP4_IP_REV_SCHEME_MASK (0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT 16
-#define OMAP4_IP_REV_FUNC_MASK (0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT 11
-#define OMAP4_IP_REV_RTL_MASK (0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT 8
-#define OMAP4_IP_REV_MAJOR_MASK (0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT 6
-#define OMAP4_IP_REV_CUSTOM_MASK (0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT 0
-#define OMAP4_IP_REV_MINOR_MASK (0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT 0
-#define OMAP4_IP_HWINFO_MASK (0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT 2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK (0x3 << 2)
-
-/* STD_FUSE_DIE_ID_0 */
-#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT 0
-#define OMAP4_STD_FUSE_DIE_ID_0_MASK (0xffffffff << 0)
-
-/* ID_CODE */
-#define OMAP4_STD_FUSE_IDCODE_SHIFT 0
-#define OMAP4_STD_FUSE_IDCODE_MASK (0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_1 */
-#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT 0
-#define OMAP4_STD_FUSE_DIE_ID_1_MASK (0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_2 */
-#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT 0
-#define OMAP4_STD_FUSE_DIE_ID_2_MASK (0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_3 */
-#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT 0
-#define OMAP4_STD_FUSE_DIE_ID_3_MASK (0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_0 */
-#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT 0
-#define OMAP4_STD_FUSE_PROD_ID_0_MASK (0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_1 */
-#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT 0
-#define OMAP4_STD_FUSE_PROD_ID_1_MASK (0xffffffff << 0)
-
-/* STD_FUSE_USB_CONF */
-#define OMAP4_USB_PROD_ID_SHIFT 16
-#define OMAP4_USB_PROD_ID_MASK (0xffff << 16)
-#define OMAP4_USB_VENDOR_ID_SHIFT 0
-#define OMAP4_USB_VENDOR_ID_MASK (0xffff << 0)
-
-/* STD_FUSE_OPP_VDD_WKUP */
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT 0
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK (0xffffffff << 0)
-
-/* STD_FUSE_OPP_BGAP */
-#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT 0
-#define OMAP4_STD_FUSE_OPP_BGAP_MASK (0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_0 */
-#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT 0
-#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK (0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_1 */
-#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT 0
-#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK (0xffffffff << 0)
-
-/* STATUS */
-#define OMAP4_ATTILA_CONF_SHIFT 11
-#define OMAP4_ATTILA_CONF_MASK (0x3 << 11)
-#define OMAP4_DEVICE_TYPE_SHIFT 8
-#define OMAP4_DEVICE_TYPE_MASK (0x7 << 8)
-#define OMAP4_SYS_BOOT_SHIFT 0
-#define OMAP4_SYS_BOOT_MASK (0xff << 0)
-
-/* DEV_CONF */
-#define OMAP4_DEV_CONF_SHIFT 1
-#define OMAP4_DEV_CONF_MASK (0x7fffffff << 1)
-#define OMAP4_USBPHY_PD_SHIFT 0
-#define OMAP4_USBPHY_PD_MASK (1 << 0)
-
-/* LDOVBB_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT 26
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK (1 << 26)
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT 21
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK (0x1f << 21)
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT 16
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK (0x1f << 16)
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT 10
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK (1 << 10)
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT 5
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK (0x1f << 5)
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT 0
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK (0x1f << 0)
-
-/* LDOVBB_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT 26
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK (1 << 26)
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT 21
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK (0x1f << 21)
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT 16
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK (0x1f << 16)
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT 10
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK (1 << 10)
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT 5
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK (0x1f << 5)
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT 0
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK (0x1f << 0)
-
-/* LDOSRAM_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT 26
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK (1 << 26)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT 21
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK (0x1f << 21)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT 16
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK (0x1f << 16)
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT 10
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK (1 << 10)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT 5
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK (0x1f << 5)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT 0
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK (0x1f << 0)
-
-/* LDOSRAM_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT 26
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK (1 << 26)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT 21
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK (0x1f << 21)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT 16
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK (0x1f << 16)
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT 10
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK (1 << 10)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT 5
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK (0x1f << 5)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT 0
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK (0x1f << 0)
-
-/* LDOSRAM_CORE_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT 26
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK (1 << 26)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT 21
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK (0x1f << 21)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT 16
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK (0x1f << 16)
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT 10
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK (1 << 10)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT 5
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK (0x1f << 5)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT 0
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK (0x1f << 0)
-
-/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT 12
-#define OMAP4_BGAP_TEMPSOFF_MASK (1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT 11
-#define OMAP4_BGAP_TSHUT_MASK (1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT 9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK (1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT 8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0)
-
-/* DPLL_NWELL_TRIM_0 */
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT 29
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK (1 << 29)
-#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT 24
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK (0x1f << 24)
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT 23
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK (1 << 23)
-#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT 18
-#define OMAP4_DPLL_PER_NWELL_TRIM_MASK (0x1f << 18)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT 17
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK (1 << 17)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT 12
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK (0x1f << 12)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT 11
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK (1 << 11)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT 6
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK (0x1f << 6)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT 5
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK (1 << 5)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT 0
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK (0x1f << 0)
-
-/* DPLL_NWELL_TRIM_1 */
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT 29
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK (1 << 29)
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT 24
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK (0x1f << 24)
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT 23
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK (1 << 23)
-#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT 18
-#define OMAP4_DPLL_USB_NWELL_TRIM_MASK (0x1f << 18)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT 17
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK (1 << 17)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT 12
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK (0x1f << 12)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT 11
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK (1 << 11)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT 6
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK (0x1f << 6)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT 5
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK (1 << 5)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT 0
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK (0x1f << 0)
-
-/* USBOTGHS_CONTROL */
-#define OMAP4_DISCHRGVBUS_SHIFT 8
-#define OMAP4_DISCHRGVBUS_MASK (1 << 8)
-#define OMAP4_CHRGVBUS_SHIFT 7
-#define OMAP4_CHRGVBUS_MASK (1 << 7)
-#define OMAP4_DRVVBUS_SHIFT 6
-#define OMAP4_DRVVBUS_MASK (1 << 6)
-#define OMAP4_IDPULLUP_SHIFT 5
-#define OMAP4_IDPULLUP_MASK (1 << 5)
-#define OMAP4_IDDIG_SHIFT 4
-#define OMAP4_IDDIG_MASK (1 << 4)
-#define OMAP4_SESSEND_SHIFT 3
-#define OMAP4_SESSEND_MASK (1 << 3)
-#define OMAP4_VBUSVALID_SHIFT 2
-#define OMAP4_VBUSVALID_MASK (1 << 2)
-#define OMAP4_BVALID_SHIFT 1
-#define OMAP4_BVALID_MASK (1 << 1)
-#define OMAP4_AVALID_SHIFT 0
-#define OMAP4_AVALID_MASK (1 << 0)
-
-/* DSS_CONTROL */
-#define OMAP4_DSS_MUX6_SELECT_SHIFT 0
-#define OMAP4_DSS_MUX6_SELECT_MASK (1 << 0)
-
-/* HWOBS_CONTROL */
-#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT 3
-#define OMAP4_HWOBS_CLKDIV_SEL_MASK (0x1f << 3)
-#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT 2
-#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK (1 << 2)
-#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT 1
-#define OMAP4_HWOBS_ALL_ONE_MODE_MASK (1 << 1)
-#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT 0
-#define OMAP4_HWOBS_MACRO_ENABLE_MASK (1 << 0)
-
-/* DEBOBS_FINAL_MUX_SEL */
-#define OMAP4_SELECT_SHIFT 0
-#define OMAP4_SELECT_MASK (0xffffffff << 0)
-
-/* DEBOBS_MMR_MPU */
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT 0
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK (0xf << 0)
-
-/* CONF_SDMA_REQ_SEL0 */
-#define OMAP4_MULT_SHIFT 0
-#define OMAP4_MULT_MASK (0x7f << 0)
-
-/* CONF_CLK_SEL0 */
-#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT 0
-#define OMAP4_MULT_CONF_CLK_SEL0_MASK (0x7 << 0)
-
-/* CONF_CLK_SEL1 */
-#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT 0
-#define OMAP4_MULT_CONF_CLK_SEL1_MASK (0x7 << 0)
-
-/* CONF_CLK_SEL2 */
-#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT 0
-#define OMAP4_MULT_CONF_CLK_SEL2_MASK (0x7 << 0)
-
-/* CONF_DPLL_FREQLOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT 0
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK (0x7 << 0)
-
-/* CONF_DPLL_TINITZ_SEL */
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT 0
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK (0x7 << 0)
-
-/* CONF_DPLL_PHASELOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT 0
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK (0x7 << 0)
-
-/* CONF_DEBUG_SEL_TST_0 */
-#define OMAP4_MODE_SHIFT 0
-#define OMAP4_MODE_MASK (0xf << 0)
-
-#endif
diff --git a/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h
deleted file mode 100644
index c88420de1151..000000000000
--- a/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_CORE 0x4a100000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION 0x0000
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO 0x0004
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG 0x0010
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0 0x01d8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1 0x01dc
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2 0x01e0
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3 0x01e4
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4 0x01e8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5 0x01ec
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6 0x01f0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL 0x05a0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE 0x05a4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0 0x05a8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1 0x05ac
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0 0x05b0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1 0x05b4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0 0x05b8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1 0x05bc
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2 0x05c0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC 0x05c4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS 0x05c8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE 0x0600
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0 0x0604
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX 0x0608
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC 0x060c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY 0x0610
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2 0x0614
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY 0x0618
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP 0x061c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE 0x0620
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1 0x0624
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1 0x0628
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI 0x062c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB 0x0630
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ 0x0634
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0 0x0638
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1 0x063c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2 0x0640
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3 0x0644
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0 0x0648
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1 0x064c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2 0x0650
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3 0x0654
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD 0x0658
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C 0x065c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW 0x0660
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R 0x0664
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0 0x0668
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1 0x0700
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2 0x0704
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3 0x0708
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4 0x070c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT 30
-#define OMAP4_IP_REV_SCHEME_MASK (0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT 16
-#define OMAP4_IP_REV_FUNC_MASK (0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT 11
-#define OMAP4_IP_REV_RTL_MASK (0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT 8
-#define OMAP4_IP_REV_MAJOR_MASK (0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT 6
-#define OMAP4_IP_REV_CUSTOM_MASK (0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT 0
-#define OMAP4_IP_REV_MINOR_MASK (0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT 0
-#define OMAP4_IP_HWINFO_MASK (0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT 2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK (0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_1 */
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_2 */
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_3 */
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_4 */
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_5 */
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT 31
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK (1 << 31)
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT 30
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK (1 << 30)
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT 29
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK (1 << 29)
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT 28
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK (1 << 28)
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT 27
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK (1 << 27)
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT 26
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK (1 << 26)
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT 25
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK (1 << 25)
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* PADCONF_WAKEUPEVENT_6 */
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* CONTROL_PADCONF_GLOBAL */
-#define OMAP4_FORCE_OFFMODE_EN_SHIFT 31
-#define OMAP4_FORCE_OFFMODE_EN_MASK (1 << 31)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_BANK0_SHIFT 31
-#define OMAP4_VDDS_DV_BANK0_MASK (1 << 31)
-#define OMAP4_VDDS_DV_BANK1_SHIFT 30
-#define OMAP4_VDDS_DV_BANK1_MASK (1 << 30)
-#define OMAP4_VDDS_DV_BANK3_SHIFT 29
-#define OMAP4_VDDS_DV_BANK3_MASK (1 << 29)
-#define OMAP4_VDDS_DV_BANK4_SHIFT 28
-#define OMAP4_VDDS_DV_BANK4_MASK (1 << 28)
-#define OMAP4_VDDS_DV_BANK5_SHIFT 27
-#define OMAP4_VDDS_DV_BANK5_MASK (1 << 27)
-#define OMAP4_VDDS_DV_BANK6_SHIFT 26
-#define OMAP4_VDDS_DV_BANK6_MASK (1 << 26)
-#define OMAP4_VDDS_DV_C2C_SHIFT 25
-#define OMAP4_VDDS_DV_C2C_MASK (1 << 25)
-#define OMAP4_VDDS_DV_CAM_SHIFT 24
-#define OMAP4_VDDS_DV_CAM_MASK (1 << 24)
-#define OMAP4_VDDS_DV_GPMC_SHIFT 23
-#define OMAP4_VDDS_DV_GPMC_MASK (1 << 23)
-#define OMAP4_VDDS_DV_SDMMC2_SHIFT 22
-#define OMAP4_VDDS_DV_SDMMC2_MASK (1 << 22)
-
-/* CONTROL_SMART1IO_PADCONF_0 */
-#define OMAP4_ABE_DR0_SC_SHIFT 30
-#define OMAP4_ABE_DR0_SC_MASK (0x3 << 30)
-#define OMAP4_CAM_DR0_SC_SHIFT 28
-#define OMAP4_CAM_DR0_SC_MASK (0x3 << 28)
-#define OMAP4_FREF_DR2_SC_SHIFT 26
-#define OMAP4_FREF_DR2_SC_MASK (0x3 << 26)
-#define OMAP4_FREF_DR3_SC_SHIFT 24
-#define OMAP4_FREF_DR3_SC_MASK (0x3 << 24)
-#define OMAP4_GPIO_DR8_SC_SHIFT 22
-#define OMAP4_GPIO_DR8_SC_MASK (0x3 << 22)
-#define OMAP4_GPIO_DR9_SC_SHIFT 20
-#define OMAP4_GPIO_DR9_SC_MASK (0x3 << 20)
-#define OMAP4_GPMC_DR2_SC_SHIFT 18
-#define OMAP4_GPMC_DR2_SC_MASK (0x3 << 18)
-#define OMAP4_GPMC_DR3_SC_SHIFT 16
-#define OMAP4_GPMC_DR3_SC_MASK (0x3 << 16)
-#define OMAP4_GPMC_DR6_SC_SHIFT 14
-#define OMAP4_GPMC_DR6_SC_MASK (0x3 << 14)
-#define OMAP4_HDMI_DR0_SC_SHIFT 12
-#define OMAP4_HDMI_DR0_SC_MASK (0x3 << 12)
-#define OMAP4_MCSPI1_DR0_SC_SHIFT 10
-#define OMAP4_MCSPI1_DR0_SC_MASK (0x3 << 10)
-#define OMAP4_UART1_DR0_SC_SHIFT 8
-#define OMAP4_UART1_DR0_SC_MASK (0x3 << 8)
-#define OMAP4_UART3_DR0_SC_SHIFT 6
-#define OMAP4_UART3_DR0_SC_MASK (0x3 << 6)
-#define OMAP4_UART3_DR1_SC_SHIFT 4
-#define OMAP4_UART3_DR1_SC_MASK (0x3 << 4)
-#define OMAP4_UNIPRO_DR0_SC_SHIFT 2
-#define OMAP4_UNIPRO_DR0_SC_MASK (0x3 << 2)
-#define OMAP4_UNIPRO_DR1_SC_SHIFT 0
-#define OMAP4_UNIPRO_DR1_SC_MASK (0x3 << 0)
-
-/* CONTROL_SMART1IO_PADCONF_1 */
-#define OMAP4_ABE_DR0_LB_SHIFT 30
-#define OMAP4_ABE_DR0_LB_MASK (0x3 << 30)
-#define OMAP4_CAM_DR0_LB_SHIFT 28
-#define OMAP4_CAM_DR0_LB_MASK (0x3 << 28)
-#define OMAP4_FREF_DR2_LB_SHIFT 26
-#define OMAP4_FREF_DR2_LB_MASK (0x3 << 26)
-#define OMAP4_FREF_DR3_LB_SHIFT 24
-#define OMAP4_FREF_DR3_LB_MASK (0x3 << 24)
-#define OMAP4_GPIO_DR8_LB_SHIFT 22
-#define OMAP4_GPIO_DR8_LB_MASK (0x3 << 22)
-#define OMAP4_GPIO_DR9_LB_SHIFT 20
-#define OMAP4_GPIO_DR9_LB_MASK (0x3 << 20)
-#define OMAP4_GPMC_DR2_LB_SHIFT 18
-#define OMAP4_GPMC_DR2_LB_MASK (0x3 << 18)
-#define OMAP4_GPMC_DR3_LB_SHIFT 16
-#define OMAP4_GPMC_DR3_LB_MASK (0x3 << 16)
-#define OMAP4_GPMC_DR6_LB_SHIFT 14
-#define OMAP4_GPMC_DR6_LB_MASK (0x3 << 14)
-#define OMAP4_HDMI_DR0_LB_SHIFT 12
-#define OMAP4_HDMI_DR0_LB_MASK (0x3 << 12)
-#define OMAP4_MCSPI1_DR0_LB_SHIFT 10
-#define OMAP4_MCSPI1_DR0_LB_MASK (0x3 << 10)
-#define OMAP4_UART1_DR0_LB_SHIFT 8
-#define OMAP4_UART1_DR0_LB_MASK (0x3 << 8)
-#define OMAP4_UART3_DR0_LB_SHIFT 6
-#define OMAP4_UART3_DR0_LB_MASK (0x3 << 6)
-#define OMAP4_UART3_DR1_LB_SHIFT 4
-#define OMAP4_UART3_DR1_LB_MASK (0x3 << 4)
-#define OMAP4_UNIPRO_DR0_LB_SHIFT 2
-#define OMAP4_UNIPRO_DR0_LB_MASK (0x3 << 2)
-#define OMAP4_UNIPRO_DR1_LB_SHIFT 0
-#define OMAP4_UNIPRO_DR1_LB_MASK (0x3 << 0)
-
-/* CONTROL_SMART2IO_PADCONF_0 */
-#define OMAP4_C2C_DR0_LB_SHIFT 31
-#define OMAP4_C2C_DR0_LB_MASK (1 << 31)
-#define OMAP4_DPM_DR1_LB_SHIFT 30
-#define OMAP4_DPM_DR1_LB_MASK (1 << 30)
-#define OMAP4_DPM_DR2_LB_SHIFT 29
-#define OMAP4_DPM_DR2_LB_MASK (1 << 29)
-#define OMAP4_DPM_DR3_LB_SHIFT 28
-#define OMAP4_DPM_DR3_LB_MASK (1 << 28)
-#define OMAP4_GPIO_DR0_LB_SHIFT 27
-#define OMAP4_GPIO_DR0_LB_MASK (1 << 27)
-#define OMAP4_GPIO_DR1_LB_SHIFT 26
-#define OMAP4_GPIO_DR1_LB_MASK (1 << 26)
-#define OMAP4_GPIO_DR10_LB_SHIFT 25
-#define OMAP4_GPIO_DR10_LB_MASK (1 << 25)
-#define OMAP4_GPIO_DR2_LB_SHIFT 24
-#define OMAP4_GPIO_DR2_LB_MASK (1 << 24)
-#define OMAP4_GPMC_DR0_LB_SHIFT 23
-#define OMAP4_GPMC_DR0_LB_MASK (1 << 23)
-#define OMAP4_GPMC_DR1_LB_SHIFT 22
-#define OMAP4_GPMC_DR1_LB_MASK (1 << 22)
-#define OMAP4_GPMC_DR4_LB_SHIFT 21
-#define OMAP4_GPMC_DR4_LB_MASK (1 << 21)
-#define OMAP4_GPMC_DR5_LB_SHIFT 20
-#define OMAP4_GPMC_DR5_LB_MASK (1 << 20)
-#define OMAP4_GPMC_DR7_LB_SHIFT 19
-#define OMAP4_GPMC_DR7_LB_MASK (1 << 19)
-#define OMAP4_HSI2_DR0_LB_SHIFT 18
-#define OMAP4_HSI2_DR0_LB_MASK (1 << 18)
-#define OMAP4_HSI2_DR1_LB_SHIFT 17
-#define OMAP4_HSI2_DR1_LB_MASK (1 << 17)
-#define OMAP4_HSI2_DR2_LB_SHIFT 16
-#define OMAP4_HSI2_DR2_LB_MASK (1 << 16)
-#define OMAP4_KPD_DR0_LB_SHIFT 15
-#define OMAP4_KPD_DR0_LB_MASK (1 << 15)
-#define OMAP4_KPD_DR1_LB_SHIFT 14
-#define OMAP4_KPD_DR1_LB_MASK (1 << 14)
-#define OMAP4_PDM_DR0_LB_SHIFT 13
-#define OMAP4_PDM_DR0_LB_MASK (1 << 13)
-#define OMAP4_SDMMC2_DR0_LB_SHIFT 12
-#define OMAP4_SDMMC2_DR0_LB_MASK (1 << 12)
-#define OMAP4_SDMMC3_DR0_LB_SHIFT 11
-#define OMAP4_SDMMC3_DR0_LB_MASK (1 << 11)
-#define OMAP4_SDMMC4_DR0_LB_SHIFT 10
-#define OMAP4_SDMMC4_DR0_LB_MASK (1 << 10)
-#define OMAP4_SDMMC4_DR1_LB_SHIFT 9
-#define OMAP4_SDMMC4_DR1_LB_MASK (1 << 9)
-#define OMAP4_SPI3_DR0_LB_SHIFT 8
-#define OMAP4_SPI3_DR0_LB_MASK (1 << 8)
-#define OMAP4_SPI3_DR1_LB_SHIFT 7
-#define OMAP4_SPI3_DR1_LB_MASK (1 << 7)
-#define OMAP4_UART3_DR2_LB_SHIFT 6
-#define OMAP4_UART3_DR2_LB_MASK (1 << 6)
-#define OMAP4_UART3_DR3_LB_SHIFT 5
-#define OMAP4_UART3_DR3_LB_MASK (1 << 5)
-#define OMAP4_UART3_DR4_LB_SHIFT 4
-#define OMAP4_UART3_DR4_LB_MASK (1 << 4)
-#define OMAP4_UART3_DR5_LB_SHIFT 3
-#define OMAP4_UART3_DR5_LB_MASK (1 << 3)
-#define OMAP4_USBA0_DR1_LB_SHIFT 2
-#define OMAP4_USBA0_DR1_LB_MASK (1 << 2)
-#define OMAP4_USBA_DR2_LB_SHIFT 1
-#define OMAP4_USBA_DR2_LB_MASK (1 << 1)
-
-/* CONTROL_SMART2IO_PADCONF_1 */
-#define OMAP4_USBB1_DR0_LB_SHIFT 31
-#define OMAP4_USBB1_DR0_LB_MASK (1 << 31)
-#define OMAP4_USBB2_DR0_LB_SHIFT 30
-#define OMAP4_USBB2_DR0_LB_MASK (1 << 30)
-#define OMAP4_USBA0_DR0_LB_SHIFT 29
-#define OMAP4_USBA0_DR0_LB_MASK (1 << 29)
-
-/* CONTROL_SMART3IO_PADCONF_0 */
-#define OMAP4_DMIC_DR0_MB_SHIFT 30
-#define OMAP4_DMIC_DR0_MB_MASK (0x3 << 30)
-#define OMAP4_GPIO_DR3_MB_SHIFT 28
-#define OMAP4_GPIO_DR3_MB_MASK (0x3 << 28)
-#define OMAP4_GPIO_DR4_MB_SHIFT 26
-#define OMAP4_GPIO_DR4_MB_MASK (0x3 << 26)
-#define OMAP4_GPIO_DR5_MB_SHIFT 24
-#define OMAP4_GPIO_DR5_MB_MASK (0x3 << 24)
-#define OMAP4_GPIO_DR6_MB_SHIFT 22
-#define OMAP4_GPIO_DR6_MB_MASK (0x3 << 22)
-#define OMAP4_HSI_DR1_MB_SHIFT 20
-#define OMAP4_HSI_DR1_MB_MASK (0x3 << 20)
-#define OMAP4_HSI_DR2_MB_SHIFT 18
-#define OMAP4_HSI_DR2_MB_MASK (0x3 << 18)
-#define OMAP4_HSI_DR3_MB_SHIFT 16
-#define OMAP4_HSI_DR3_MB_MASK (0x3 << 16)
-#define OMAP4_MCBSP2_DR0_MB_SHIFT 14
-#define OMAP4_MCBSP2_DR0_MB_MASK (0x3 << 14)
-#define OMAP4_MCSPI4_DR0_MB_SHIFT 12
-#define OMAP4_MCSPI4_DR0_MB_MASK (0x3 << 12)
-#define OMAP4_MCSPI4_DR1_MB_SHIFT 10
-#define OMAP4_MCSPI4_DR1_MB_MASK (0x3 << 10)
-#define OMAP4_SDMMC3_DR0_MB_SHIFT 8
-#define OMAP4_SDMMC3_DR0_MB_MASK (0x3 << 8)
-#define OMAP4_SPI2_DR0_MB_SHIFT 0
-#define OMAP4_SPI2_DR0_MB_MASK (0x3 << 0)
-
-/* CONTROL_SMART3IO_PADCONF_1 */
-#define OMAP4_SPI2_DR1_MB_SHIFT 30
-#define OMAP4_SPI2_DR1_MB_MASK (0x3 << 30)
-#define OMAP4_SPI2_DR2_MB_SHIFT 28
-#define OMAP4_SPI2_DR2_MB_MASK (0x3 << 28)
-#define OMAP4_UART2_DR0_MB_SHIFT 26
-#define OMAP4_UART2_DR0_MB_MASK (0x3 << 26)
-#define OMAP4_UART2_DR1_MB_SHIFT 24
-#define OMAP4_UART2_DR1_MB_MASK (0x3 << 24)
-#define OMAP4_UART4_DR0_MB_SHIFT 22
-#define OMAP4_UART4_DR0_MB_MASK (0x3 << 22)
-#define OMAP4_HSI_DR0_MB_SHIFT 20
-#define OMAP4_HSI_DR0_MB_MASK (0x3 << 20)
-
-/* CONTROL_SMART3IO_PADCONF_2 */
-#define OMAP4_DMIC_DR0_LB_SHIFT 31
-#define OMAP4_DMIC_DR0_LB_MASK (1 << 31)
-#define OMAP4_GPIO_DR3_LB_SHIFT 30
-#define OMAP4_GPIO_DR3_LB_MASK (1 << 30)
-#define OMAP4_GPIO_DR4_LB_SHIFT 29
-#define OMAP4_GPIO_DR4_LB_MASK (1 << 29)
-#define OMAP4_GPIO_DR5_LB_SHIFT 28
-#define OMAP4_GPIO_DR5_LB_MASK (1 << 28)
-#define OMAP4_GPIO_DR6_LB_SHIFT 27
-#define OMAP4_GPIO_DR6_LB_MASK (1 << 27)
-#define OMAP4_HSI_DR1_LB_SHIFT 26
-#define OMAP4_HSI_DR1_LB_MASK (1 << 26)
-#define OMAP4_HSI_DR2_LB_SHIFT 25
-#define OMAP4_HSI_DR2_LB_MASK (1 << 25)
-#define OMAP4_HSI_DR3_LB_SHIFT 24
-#define OMAP4_HSI_DR3_LB_MASK (1 << 24)
-#define OMAP4_MCBSP2_DR0_LB_SHIFT 23
-#define OMAP4_MCBSP2_DR0_LB_MASK (1 << 23)
-#define OMAP4_MCSPI4_DR0_LB_SHIFT 22
-#define OMAP4_MCSPI4_DR0_LB_MASK (1 << 22)
-#define OMAP4_MCSPI4_DR1_LB_SHIFT 21
-#define OMAP4_MCSPI4_DR1_LB_MASK (1 << 21)
-#define OMAP4_SLIMBUS2_DR0_LB_SHIFT 18
-#define OMAP4_SLIMBUS2_DR0_LB_MASK (1 << 18)
-#define OMAP4_SPI2_DR0_LB_SHIFT 16
-#define OMAP4_SPI2_DR0_LB_MASK (1 << 16)
-#define OMAP4_SPI2_DR1_LB_SHIFT 15
-#define OMAP4_SPI2_DR1_LB_MASK (1 << 15)
-#define OMAP4_SPI2_DR2_LB_SHIFT 14
-#define OMAP4_SPI2_DR2_LB_MASK (1 << 14)
-#define OMAP4_UART2_DR0_LB_SHIFT 13
-#define OMAP4_UART2_DR0_LB_MASK (1 << 13)
-#define OMAP4_UART2_DR1_LB_SHIFT 12
-#define OMAP4_UART2_DR1_LB_MASK (1 << 12)
-#define OMAP4_UART4_DR0_LB_SHIFT 11
-#define OMAP4_UART4_DR0_LB_MASK (1 << 11)
-#define OMAP4_HSI_DR0_LB_SHIFT 10
-#define OMAP4_HSI_DR0_LB_MASK (1 << 10)
-
-/* CONTROL_USBB_HSIC */
-#define OMAP4_USBB2_DR1_SR_SHIFT 30
-#define OMAP4_USBB2_DR1_SR_MASK (0x3 << 30)
-#define OMAP4_USBB2_DR1_I_SHIFT 27
-#define OMAP4_USBB2_DR1_I_MASK (0x7 << 27)
-#define OMAP4_USBB1_DR1_SR_SHIFT 25
-#define OMAP4_USBB1_DR1_SR_MASK (0x3 << 25)
-#define OMAP4_USBB1_DR1_I_SHIFT 22
-#define OMAP4_USBB1_DR1_I_MASK (0x7 << 22)
-#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT 20
-#define OMAP4_USBB1_HSIC_DATA_WD_MASK (0x3 << 20)
-#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT 18
-#define OMAP4_USBB1_HSIC_STROBE_WD_MASK (0x3 << 18)
-#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT 16
-#define OMAP4_USBB2_HSIC_DATA_WD_MASK (0x3 << 16)
-#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT 14
-#define OMAP4_USBB2_HSIC_STROBE_WD_MASK (0x3 << 14)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT 13
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK (1 << 13)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT 11
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK (0x3 << 11)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT 10
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK (1 << 10)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT 8
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK (0x3 << 8)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT 7
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK (1 << 7)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT 5
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK (0x3 << 5)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT 4
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK (1 << 4)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT 2
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK (0x3 << 2)
-
-/* CONTROL_SLIMBUS */
-#define OMAP4_SLIMBUS1_DR0_MB_SHIFT 30
-#define OMAP4_SLIMBUS1_DR0_MB_MASK (0x3 << 30)
-#define OMAP4_SLIMBUS1_DR1_MB_SHIFT 28
-#define OMAP4_SLIMBUS1_DR1_MB_MASK (0x3 << 28)
-#define OMAP4_SLIMBUS2_DR0_MB_SHIFT 26
-#define OMAP4_SLIMBUS2_DR0_MB_MASK (0x3 << 26)
-#define OMAP4_SLIMBUS2_DR1_MB_SHIFT 24
-#define OMAP4_SLIMBUS2_DR1_MB_MASK (0x3 << 24)
-#define OMAP4_SLIMBUS2_DR2_MB_SHIFT 22
-#define OMAP4_SLIMBUS2_DR2_MB_MASK (0x3 << 22)
-#define OMAP4_SLIMBUS2_DR3_MB_SHIFT 20
-#define OMAP4_SLIMBUS2_DR3_MB_MASK (0x3 << 20)
-#define OMAP4_SLIMBUS1_DR0_LB_SHIFT 19
-#define OMAP4_SLIMBUS1_DR0_LB_MASK (1 << 19)
-#define OMAP4_SLIMBUS2_DR1_LB_SHIFT 18
-#define OMAP4_SLIMBUS2_DR1_LB_MASK (1 << 18)
-
-/* CONTROL_PBIASLITE */
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT 31
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK (1 << 31)
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT 30
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK (1 << 30)
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT 29
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK (1 << 29)
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT 28
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK (1 << 28)
-#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT 27
-#define OMAP4_USIM_PBIASLITE_VMODE_MASK (1 << 27)
-#define OMAP4_MMC1_PWRDNZ_SHIFT 26
-#define OMAP4_MMC1_PWRDNZ_MASK (1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT 25
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK (1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT 24
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK (1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT 23
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK (1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT 22
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK (1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT 21
-#define OMAP4_MMC1_PBIASLITE_VMODE_MASK (1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT 20
-#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK (1 << 20)
-
-/* CONTROL_I2C_0 */
-#define OMAP4_I2C4_SDA_GLFENB_SHIFT 31
-#define OMAP4_I2C4_SDA_GLFENB_MASK (1 << 31)
-#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT 29
-#define OMAP4_I2C4_SDA_LOAD_BITS_MASK (0x3 << 29)
-#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT 28
-#define OMAP4_I2C4_SDA_PULLUPRESX_MASK (1 << 28)
-#define OMAP4_I2C3_SDA_GLFENB_SHIFT 27
-#define OMAP4_I2C3_SDA_GLFENB_MASK (1 << 27)
-#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT 25
-#define OMAP4_I2C3_SDA_LOAD_BITS_MASK (0x3 << 25)
-#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT 24
-#define OMAP4_I2C3_SDA_PULLUPRESX_MASK (1 << 24)
-#define OMAP4_I2C2_SDA_GLFENB_SHIFT 23
-#define OMAP4_I2C2_SDA_GLFENB_MASK (1 << 23)
-#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT 21
-#define OMAP4_I2C2_SDA_LOAD_BITS_MASK (0x3 << 21)
-#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT 20
-#define OMAP4_I2C2_SDA_PULLUPRESX_MASK (1 << 20)
-#define OMAP4_I2C1_SDA_GLFENB_SHIFT 19
-#define OMAP4_I2C1_SDA_GLFENB_MASK (1 << 19)
-#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT 17
-#define OMAP4_I2C1_SDA_LOAD_BITS_MASK (0x3 << 17)
-#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT 16
-#define OMAP4_I2C1_SDA_PULLUPRESX_MASK (1 << 16)
-#define OMAP4_I2C4_SCL_GLFENB_SHIFT 15
-#define OMAP4_I2C4_SCL_GLFENB_MASK (1 << 15)
-#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT 13
-#define OMAP4_I2C4_SCL_LOAD_BITS_MASK (0x3 << 13)
-#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT 12
-#define OMAP4_I2C4_SCL_PULLUPRESX_MASK (1 << 12)
-#define OMAP4_I2C3_SCL_GLFENB_SHIFT 11
-#define OMAP4_I2C3_SCL_GLFENB_MASK (1 << 11)
-#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT 9
-#define OMAP4_I2C3_SCL_LOAD_BITS_MASK (0x3 << 9)
-#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT 8
-#define OMAP4_I2C3_SCL_PULLUPRESX_MASK (1 << 8)
-#define OMAP4_I2C2_SCL_GLFENB_SHIFT 7
-#define OMAP4_I2C2_SCL_GLFENB_MASK (1 << 7)
-#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT 5
-#define OMAP4_I2C2_SCL_LOAD_BITS_MASK (0x3 << 5)
-#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT 4
-#define OMAP4_I2C2_SCL_PULLUPRESX_MASK (1 << 4)
-#define OMAP4_I2C1_SCL_GLFENB_SHIFT 3
-#define OMAP4_I2C1_SCL_GLFENB_MASK (1 << 3)
-#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT 1
-#define OMAP4_I2C1_SCL_LOAD_BITS_MASK (0x3 << 1)
-#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT 0
-#define OMAP4_I2C1_SCL_PULLUPRESX_MASK (1 << 0)
-
-/* CONTROL_CAMERA_RX */
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT 31
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK (1 << 31)
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT 29
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK (0x3 << 29)
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT 24
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK (0x1f << 24)
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT 22
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK (0x3 << 22)
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT 21
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK (1 << 21)
-#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT 19
-#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK (0x3 << 19)
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT 18
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK (1 << 18)
-#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT 16
-#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK (0x3 << 16)
-
-/* CONTROL_AVDAC */
-#define OMAP4_AVDAC_ACEN_SHIFT 31
-#define OMAP4_AVDAC_ACEN_MASK (1 << 31)
-#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT 30
-#define OMAP4_AVDAC_TVOUTBYPASS_MASK (1 << 30)
-#define OMAP4_AVDAC_INPUTINV_SHIFT 29
-#define OMAP4_AVDAC_INPUTINV_MASK (1 << 29)
-#define OMAP4_AVDAC_CTL_SHIFT 13
-#define OMAP4_AVDAC_CTL_MASK (0xffff << 13)
-#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT 12
-#define OMAP4_AVDAC_CTL_WR_ACK_MASK (1 << 12)
-
-/* CONTROL_HDMI_TX_PHY */
-#define OMAP4_HDMITXPHY_PADORDER_SHIFT 31
-#define OMAP4_HDMITXPHY_PADORDER_MASK (1 << 31)
-#define OMAP4_HDMITXPHY_TXVALID_SHIFT 30
-#define OMAP4_HDMITXPHY_TXVALID_MASK (1 << 30)
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT 29
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK (1 << 29)
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT 28
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK (1 << 28)
-
-/* CONTROL_MMC2 */
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT 31
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK (1 << 31)
-
-/* CONTROL_DSIPHY */
-#define OMAP4_DSI2_LANEENABLE_SHIFT 29
-#define OMAP4_DSI2_LANEENABLE_MASK (0x7 << 29)
-#define OMAP4_DSI1_LANEENABLE_SHIFT 24
-#define OMAP4_DSI1_LANEENABLE_MASK (0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT 19
-#define OMAP4_DSI1_PIPD_MASK (0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT 14
-#define OMAP4_DSI2_PIPD_MASK (0x1f << 14)
-
-/* CONTROL_MCBSPLP */
-#define OMAP4_ALBCTRLRX_FSX_SHIFT 31
-#define OMAP4_ALBCTRLRX_FSX_MASK (1 << 31)
-#define OMAP4_ALBCTRLRX_CLKX_SHIFT 30
-#define OMAP4_ALBCTRLRX_CLKX_MASK (1 << 30)
-#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT 29
-#define OMAP4_ABE_MCBSP1_DR_EN_MASK (1 << 29)
-
-/* CONTROL_USB2PHYCORE */
-#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT 31
-#define OMAP4_USB2PHY_AUTORESUME_EN_MASK (1 << 31)
-#define OMAP4_USB2PHY_DISCHGDET_SHIFT 30
-#define OMAP4_USB2PHY_DISCHGDET_MASK (1 << 30)
-#define OMAP4_USB2PHY_GPIOMODE_SHIFT 29
-#define OMAP4_USB2PHY_GPIOMODE_MASK (1 << 29)
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT 28
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK (1 << 28)
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT 27
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK (1 << 27)
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT 26
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK (1 << 26)
-#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT 25
-#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK (1 << 25)
-#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT 24
-#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK (1 << 24)
-#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT 21
-#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK (0x7 << 21)
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT 20
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK (1 << 20)
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT 19
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK (1 << 19)
-#define OMAP4_USB2PHY_DATADET_SHIFT 18
-#define OMAP4_USB2PHY_DATADET_MASK (1 << 18)
-#define OMAP4_USB2PHY_SINKONDP_SHIFT 17
-#define OMAP4_USB2PHY_SINKONDP_MASK (1 << 17)
-#define OMAP4_USB2PHY_SRCONDM_SHIFT 16
-#define OMAP4_USB2PHY_SRCONDM_MASK (1 << 16)
-#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT 15
-#define OMAP4_USB2PHY_RESTARTCHGDET_MASK (1 << 15)
-#define OMAP4_USB2PHY_CHGDETDONE_SHIFT 14
-#define OMAP4_USB2PHY_CHGDETDONE_MASK (1 << 14)
-#define OMAP4_USB2PHY_CHGDETECTED_SHIFT 13
-#define OMAP4_USB2PHY_CHGDETECTED_MASK (1 << 13)
-#define OMAP4_USB2PHY_MCPCPUEN_SHIFT 12
-#define OMAP4_USB2PHY_MCPCPUEN_MASK (1 << 12)
-#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT 11
-#define OMAP4_USB2PHY_MCPCMODEEN_MASK (1 << 11)
-#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT 10
-#define OMAP4_USB2PHY_RESETDONEMCLK_MASK (1 << 10)
-#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT 9
-#define OMAP4_USB2PHY_UTMIRESETDONE_MASK (1 << 9)
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT 8
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK (1 << 8)
-#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT 7
-#define OMAP4_USB2PHY_DATAPOLARITYN_MASK (1 << 7)
-#define OMAP4_USBDPLL_FREQLOCK_SHIFT 6
-#define OMAP4_USBDPLL_FREQLOCK_MASK (1 << 6)
-#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT 5
-#define OMAP4_USB2PHY_RESETDONETCLK_MASK (1 << 5)
-
-/* CONTROL_I2C_1 */
-#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT 31
-#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK (1 << 31)
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT 29
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK (0x3 << 29)
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT 28
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK (1 << 28)
-#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT 27
-#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK (1 << 27)
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT 25
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK (0x3 << 25)
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT 24
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK (1 << 24)
-#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT 23
-#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK (1 << 23)
-#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT 22
-#define OMAP4_HDMI_DDC_SDA_NMODE_MASK (1 << 22)
-#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT 21
-#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK (1 << 21)
-#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT 20
-#define OMAP4_HDMI_DDC_SCL_NMODE_MASK (1 << 20)
-
-/* CONTROL_MMC1 */
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT 31
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK (1 << 31)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT 30
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK (1 << 30)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT 29
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK (1 << 29)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT 28
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK (1 << 28)
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT 27
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK (1 << 27)
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT 26
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK (1 << 26)
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT 25
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK (1 << 25)
-#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT 24
-#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK (1 << 24)
-#define OMAP4_USB_FD_CDEN_SHIFT 23
-#define OMAP4_USB_FD_CDEN_MASK (1 << 23)
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT 22
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK (1 << 22)
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT 21
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK (1 << 21)
-
-/* CONTROL_HSI */
-#define OMAP4_HSI1_CALLOOP_SEL_SHIFT 31
-#define OMAP4_HSI1_CALLOOP_SEL_MASK (1 << 31)
-#define OMAP4_HSI1_CALMUX_SEL_SHIFT 30
-#define OMAP4_HSI1_CALMUX_SEL_MASK (1 << 30)
-#define OMAP4_HSI2_CALLOOP_SEL_SHIFT 29
-#define OMAP4_HSI2_CALLOOP_SEL_MASK (1 << 29)
-#define OMAP4_HSI2_CALMUX_SEL_SHIFT 28
-#define OMAP4_HSI2_CALMUX_SEL_MASK (1 << 28)
-
-/* CONTROL_USB */
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT 31
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK (1 << 31)
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT 30
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK (1 << 30)
-
-/* CONTROL_HDQ */
-#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT 31
-#define OMAP4_HDQ_SIO_PWRDNZ_MASK (1 << 31)
-
-/* CONTROL_LPDDR2IO1_0 */
-#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT 30
-#define OMAP4_LPDDR2IO1_GR4_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR4_I_SHIFT 27
-#define OMAP4_LPDDR2IO1_GR4_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT 25
-#define OMAP4_LPDDR2IO1_GR4_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT 22
-#define OMAP4_LPDDR2IO1_GR3_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR3_I_SHIFT 19
-#define OMAP4_LPDDR2IO1_GR3_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT 17
-#define OMAP4_LPDDR2IO1_GR3_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT 14
-#define OMAP4_LPDDR2IO1_GR2_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR2_I_SHIFT 11
-#define OMAP4_LPDDR2IO1_GR2_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT 9
-#define OMAP4_LPDDR2IO1_GR2_WD_MASK (0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT 6
-#define OMAP4_LPDDR2IO1_GR1_SR_MASK (0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR1_I_SHIFT 3
-#define OMAP4_LPDDR2IO1_GR1_I_MASK (0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT 1
-#define OMAP4_LPDDR2IO1_GR1_WD_MASK (0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_1 */
-#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT 30
-#define OMAP4_LPDDR2IO1_GR8_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR8_I_SHIFT 27
-#define OMAP4_LPDDR2IO1_GR8_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT 25
-#define OMAP4_LPDDR2IO1_GR8_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT 22
-#define OMAP4_LPDDR2IO1_GR7_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR7_I_SHIFT 19
-#define OMAP4_LPDDR2IO1_GR7_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT 17
-#define OMAP4_LPDDR2IO1_GR7_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT 14
-#define OMAP4_LPDDR2IO1_GR6_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR6_I_SHIFT 11
-#define OMAP4_LPDDR2IO1_GR6_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT 9
-#define OMAP4_LPDDR2IO1_GR6_WD_MASK (0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT 6
-#define OMAP4_LPDDR2IO1_GR5_SR_MASK (0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR5_I_SHIFT 3
-#define OMAP4_LPDDR2IO1_GR5_I_MASK (0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT 1
-#define OMAP4_LPDDR2IO1_GR5_WD_MASK (0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_2 */
-#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT 30
-#define OMAP4_LPDDR2IO1_GR11_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR11_I_SHIFT 27
-#define OMAP4_LPDDR2IO1_GR11_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT 25
-#define OMAP4_LPDDR2IO1_GR11_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT 22
-#define OMAP4_LPDDR2IO1_GR10_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR10_I_SHIFT 19
-#define OMAP4_LPDDR2IO1_GR10_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT 17
-#define OMAP4_LPDDR2IO1_GR10_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT 14
-#define OMAP4_LPDDR2IO1_GR9_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR9_I_SHIFT 11
-#define OMAP4_LPDDR2IO1_GR9_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT 9
-#define OMAP4_LPDDR2IO1_GR9_WD_MASK (0x3 << 9)
-
-/* CONTROL_LPDDR2IO1_3 */
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT 31
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK (1 << 31)
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT 30
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK (1 << 30)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT 29
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK (1 << 29)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT 28
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK (1 << 28)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT 27
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK (1 << 27)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT 26
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK (1 << 26)
-#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT 25
-#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK (1 << 25)
-#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT 24
-#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK (1 << 24)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT 23
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK (1 << 23)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT 22
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK (1 << 22)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT 21
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK (1 << 21)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT 20
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK (1 << 20)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT 19
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK (1 << 19)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT 18
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK (1 << 18)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT 17
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK (1 << 17)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT 16
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK (1 << 16)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT 15
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK (1 << 15)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT 14
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK (1 << 14)
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT 13
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK (1 << 13)
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT 12
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK (1 << 12)
-
-/* CONTROL_LPDDR2IO2_0 */
-#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT 30
-#define OMAP4_LPDDR2IO2_GR4_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR4_I_SHIFT 27
-#define OMAP4_LPDDR2IO2_GR4_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT 25
-#define OMAP4_LPDDR2IO2_GR4_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT 22
-#define OMAP4_LPDDR2IO2_GR3_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR3_I_SHIFT 19
-#define OMAP4_LPDDR2IO2_GR3_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT 17
-#define OMAP4_LPDDR2IO2_GR3_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT 14
-#define OMAP4_LPDDR2IO2_GR2_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR2_I_SHIFT 11
-#define OMAP4_LPDDR2IO2_GR2_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT 9
-#define OMAP4_LPDDR2IO2_GR2_WD_MASK (0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT 6
-#define OMAP4_LPDDR2IO2_GR1_SR_MASK (0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR1_I_SHIFT 3
-#define OMAP4_LPDDR2IO2_GR1_I_MASK (0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT 1
-#define OMAP4_LPDDR2IO2_GR1_WD_MASK (0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_1 */
-#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT 30
-#define OMAP4_LPDDR2IO2_GR8_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR8_I_SHIFT 27
-#define OMAP4_LPDDR2IO2_GR8_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT 25
-#define OMAP4_LPDDR2IO2_GR8_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT 22
-#define OMAP4_LPDDR2IO2_GR7_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR7_I_SHIFT 19
-#define OMAP4_LPDDR2IO2_GR7_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT 17
-#define OMAP4_LPDDR2IO2_GR7_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT 14
-#define OMAP4_LPDDR2IO2_GR6_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR6_I_SHIFT 11
-#define OMAP4_LPDDR2IO2_GR6_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT 9
-#define OMAP4_LPDDR2IO2_GR6_WD_MASK (0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT 6
-#define OMAP4_LPDDR2IO2_GR5_SR_MASK (0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR5_I_SHIFT 3
-#define OMAP4_LPDDR2IO2_GR5_I_MASK (0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT 1
-#define OMAP4_LPDDR2IO2_GR5_WD_MASK (0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_2 */
-#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT 30
-#define OMAP4_LPDDR2IO2_GR11_SR_MASK (0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR11_I_SHIFT 27
-#define OMAP4_LPDDR2IO2_GR11_I_MASK (0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT 25
-#define OMAP4_LPDDR2IO2_GR11_WD_MASK (0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT 22
-#define OMAP4_LPDDR2IO2_GR10_SR_MASK (0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR10_I_SHIFT 19
-#define OMAP4_LPDDR2IO2_GR10_I_MASK (0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT 17
-#define OMAP4_LPDDR2IO2_GR10_WD_MASK (0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT 14
-#define OMAP4_LPDDR2IO2_GR9_SR_MASK (0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR9_I_SHIFT 11
-#define OMAP4_LPDDR2IO2_GR9_I_MASK (0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT 9
-#define OMAP4_LPDDR2IO2_GR9_WD_MASK (0x3 << 9)
-
-/* CONTROL_LPDDR2IO2_3 */
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT 31
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK (1 << 31)
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT 30
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK (1 << 30)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT 29
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK (1 << 29)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT 28
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK (1 << 28)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT 27
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK (1 << 27)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT 26
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK (1 << 26)
-#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT 25
-#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK (1 << 25)
-#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT 24
-#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK (1 << 24)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT 23
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK (1 << 23)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT 22
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK (1 << 22)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT 21
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK (1 << 21)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT 20
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK (1 << 20)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT 19
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK (1 << 19)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT 18
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK (1 << 18)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT 17
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK (1 << 17)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT 16
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK (1 << 16)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT 15
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK (1 << 15)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT 14
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK (1 << 14)
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT 13
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK (1 << 13)
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT 12
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK (1 << 12)
-
-/* CONTROL_BUS_HOLD */
-#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT 31
-#define OMAP4_ABE_DMIC_DIN3_EN_MASK (1 << 31)
-#define OMAP4_MCSPI1_CS3_EN_SHIFT 30
-#define OMAP4_MCSPI1_CS3_EN_MASK (1 << 30)
-
-/* CONTROL_C2C */
-#define OMAP4_MIRROR_MODE_EN_SHIFT 31
-#define OMAP4_MIRROR_MODE_EN_MASK (1 << 31)
-#define OMAP4_C2C_SPARE_SHIFT 24
-#define OMAP4_C2C_SPARE_MASK (0x7f << 24)
-
-/* CORE_CONTROL_SPARE_RW */
-#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT 0
-#define OMAP4_CORE_CONTROL_SPARE_RW_MASK (0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R */
-#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT 0
-#define OMAP4_CORE_CONTROL_SPARE_R_MASK (0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R_C0 */
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT 31
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK (1 << 31)
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT 30
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK (1 << 30)
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT 29
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK (1 << 29)
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT 28
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK (1 << 28)
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT 27
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK (1 << 27)
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT 26
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK (1 << 26)
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT 25
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK (1 << 25)
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT 24
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK (1 << 24)
-
-/* CONTROL_EFUSE_1 */
-#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT 24
-#define OMAP4_AVDAC_TRIM_BYTE3_MASK (0x7f << 24)
-#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT 16
-#define OMAP4_AVDAC_TRIM_BYTE2_MASK (0xff << 16)
-#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT 8
-#define OMAP4_AVDAC_TRIM_BYTE1_MASK (0xff << 8)
-#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT 0
-#define OMAP4_AVDAC_TRIM_BYTE0_MASK (0xff << 0)
-
-/* CONTROL_EFUSE_2 */
-#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT 31
-#define OMAP4_EFUSE_SMART2TEST_P0_MASK (1 << 31)
-#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT 30
-#define OMAP4_EFUSE_SMART2TEST_P1_MASK (1 << 30)
-#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT 29
-#define OMAP4_EFUSE_SMART2TEST_P2_MASK (1 << 29)
-#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT 28
-#define OMAP4_EFUSE_SMART2TEST_P3_MASK (1 << 28)
-#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT 27
-#define OMAP4_EFUSE_SMART2TEST_N0_MASK (1 << 27)
-#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT 26
-#define OMAP4_EFUSE_SMART2TEST_N1_MASK (1 << 26)
-#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT 25
-#define OMAP4_EFUSE_SMART2TEST_N2_MASK (1 << 25)
-#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT 24
-#define OMAP4_EFUSE_SMART2TEST_N3_MASK (1 << 24)
-#define OMAP4_LPDDR2_PTV_N1_SHIFT 23
-#define OMAP4_LPDDR2_PTV_N1_MASK (1 << 23)
-#define OMAP4_LPDDR2_PTV_N2_SHIFT 22
-#define OMAP4_LPDDR2_PTV_N2_MASK (1 << 22)
-#define OMAP4_LPDDR2_PTV_N3_SHIFT 21
-#define OMAP4_LPDDR2_PTV_N3_MASK (1 << 21)
-#define OMAP4_LPDDR2_PTV_N4_SHIFT 20
-#define OMAP4_LPDDR2_PTV_N4_MASK (1 << 20)
-#define OMAP4_LPDDR2_PTV_N5_SHIFT 19
-#define OMAP4_LPDDR2_PTV_N5_MASK (1 << 19)
-#define OMAP4_LPDDR2_PTV_P1_SHIFT 18
-#define OMAP4_LPDDR2_PTV_P1_MASK (1 << 18)
-#define OMAP4_LPDDR2_PTV_P2_SHIFT 17
-#define OMAP4_LPDDR2_PTV_P2_MASK (1 << 17)
-#define OMAP4_LPDDR2_PTV_P3_SHIFT 16
-#define OMAP4_LPDDR2_PTV_P3_MASK (1 << 16)
-#define OMAP4_LPDDR2_PTV_P4_SHIFT 15
-#define OMAP4_LPDDR2_PTV_P4_MASK (1 << 15)
-#define OMAP4_LPDDR2_PTV_P5_SHIFT 14
-#define OMAP4_LPDDR2_PTV_P5_MASK (1 << 14)
-
-/* CONTROL_EFUSE_3 */
-#define OMAP4_STD_FUSE_SPARE_1_SHIFT 24
-#define OMAP4_STD_FUSE_SPARE_1_MASK (0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_2_SHIFT 16
-#define OMAP4_STD_FUSE_SPARE_2_MASK (0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_3_SHIFT 8
-#define OMAP4_STD_FUSE_SPARE_3_MASK (0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_4_SHIFT 0
-#define OMAP4_STD_FUSE_SPARE_4_MASK (0xff << 0)
-
-/* CONTROL_EFUSE_4 */
-#define OMAP4_STD_FUSE_SPARE_5_SHIFT 24
-#define OMAP4_STD_FUSE_SPARE_5_MASK (0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_6_SHIFT 16
-#define OMAP4_STD_FUSE_SPARE_6_MASK (0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_7_SHIFT 8
-#define OMAP4_STD_FUSE_SPARE_7_MASK (0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_8_SHIFT 0
-#define OMAP4_STD_FUSE_SPARE_8_MASK (0xff << 0)
-
-#endif
diff --git a/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h
deleted file mode 100644
index 17c9b37042c0..000000000000
--- a/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_WKUP 0x4a31e000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION 0x0000
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO 0x0004
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG 0x0010
-#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0 0x007c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0 0x05a0
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1 0x05a4
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE 0x05a8
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR 0x05ac
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO 0x0600
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2 0x0604
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG 0x0608
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS 0x060c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW 0x0614
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R 0x0618
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0 0x061c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT 30
-#define OMAP4_IP_REV_SCHEME_MASK (0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT 16
-#define OMAP4_IP_REV_FUNC_MASK (0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT 11
-#define OMAP4_IP_REV_RTL_MASK (0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT 8
-#define OMAP4_IP_REV_MAJOR_MASK (0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT 6
-#define OMAP4_IP_REV_CUSTOM_MASK (0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT 0
-#define OMAP4_IP_REV_MINOR_MASK (0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT 0
-#define OMAP4_IP_HWINFO_MASK (0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT 2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK (0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT 24
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK (1 << 24)
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT 23
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK (1 << 23)
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT 22
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK (1 << 22)
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT 21
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK (1 << 21)
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT 20
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK (1 << 20)
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT 19
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK (1 << 19)
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT 18
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK (1 << 18)
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT 17
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK (1 << 17)
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT 16
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 16)
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT 15
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK (1 << 15)
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT 14
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK (1 << 14)
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT 13
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK (1 << 13)
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT 12
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 12)
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT 11
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK (1 << 11)
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT 10
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 10)
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT 9
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK (1 << 9)
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT 8
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK (1 << 8)
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT 7
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK (1 << 7)
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT 6
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK (1 << 6)
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT 5
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK (1 << 5)
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT 4
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK (1 << 4)
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT 3
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK (1 << 3)
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT 2
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK (1 << 2)
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT 1
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK (1 << 1)
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT 0
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK (1 << 0)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_0 */
-#define OMAP4_FREF_DR0_SC_SHIFT 30
-#define OMAP4_FREF_DR0_SC_MASK (0x3 << 30)
-#define OMAP4_FREF_DR1_SC_SHIFT 28
-#define OMAP4_FREF_DR1_SC_MASK (0x3 << 28)
-#define OMAP4_FREF_DR4_SC_SHIFT 26
-#define OMAP4_FREF_DR4_SC_MASK (0x3 << 26)
-#define OMAP4_FREF_DR5_SC_SHIFT 24
-#define OMAP4_FREF_DR5_SC_MASK (0x3 << 24)
-#define OMAP4_FREF_DR6_SC_SHIFT 22
-#define OMAP4_FREF_DR6_SC_MASK (0x3 << 22)
-#define OMAP4_FREF_DR7_SC_SHIFT 20
-#define OMAP4_FREF_DR7_SC_MASK (0x3 << 20)
-#define OMAP4_GPIO_DR7_SC_SHIFT 18
-#define OMAP4_GPIO_DR7_SC_MASK (0x3 << 18)
-#define OMAP4_DPM_DR0_SC_SHIFT 14
-#define OMAP4_DPM_DR0_SC_MASK (0x3 << 14)
-#define OMAP4_SIM_DR0_SC_SHIFT 12
-#define OMAP4_SIM_DR0_SC_MASK (0x3 << 12)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_1 */
-#define OMAP4_FREF_DR0_LB_SHIFT 30
-#define OMAP4_FREF_DR0_LB_MASK (0x3 << 30)
-#define OMAP4_FREF_DR1_LB_SHIFT 28
-#define OMAP4_FREF_DR1_LB_MASK (0x3 << 28)
-#define OMAP4_FREF_DR4_LB_SHIFT 26
-#define OMAP4_FREF_DR4_LB_MASK (0x3 << 26)
-#define OMAP4_FREF_DR5_LB_SHIFT 24
-#define OMAP4_FREF_DR5_LB_MASK (0x3 << 24)
-#define OMAP4_FREF_DR6_LB_SHIFT 22
-#define OMAP4_FREF_DR6_LB_MASK (0x3 << 22)
-#define OMAP4_FREF_DR7_LB_SHIFT 20
-#define OMAP4_FREF_DR7_LB_MASK (0x3 << 20)
-#define OMAP4_GPIO_DR7_LB_SHIFT 18
-#define OMAP4_GPIO_DR7_LB_MASK (0x3 << 18)
-#define OMAP4_DPM_DR0_LB_SHIFT 14
-#define OMAP4_DPM_DR0_LB_MASK (0x3 << 14)
-#define OMAP4_SIM_DR0_LB_SHIFT 12
-#define OMAP4_SIM_DR0_LB_MASK (0x3 << 12)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_FREF_SHIFT 31
-#define OMAP4_VDDS_DV_FREF_MASK (1 << 31)
-#define OMAP4_VDDS_DV_BANK2_SHIFT 30
-#define OMAP4_VDDS_DV_BANK2_MASK (1 << 30)
-
-/* CONTROL_XTAL_OSCILLATOR */
-#define OMAP4_OSCILLATOR_BOOST_SHIFT 31
-#define OMAP4_OSCILLATOR_BOOST_MASK (1 << 31)
-#define OMAP4_OSCILLATOR_OS_OUT_SHIFT 30
-#define OMAP4_OSCILLATOR_OS_OUT_MASK (1 << 30)
-
-/* CONTROL_USIMIO */
-#define OMAP4_PAD_USIM_CLK_LOW_SHIFT 31
-#define OMAP4_PAD_USIM_CLK_LOW_MASK (1 << 31)
-#define OMAP4_PAD_USIM_RST_LOW_SHIFT 29
-#define OMAP4_PAD_USIM_RST_LOW_MASK (1 << 29)
-#define OMAP4_USIM_PWRDNZ_SHIFT 28
-#define OMAP4_USIM_PWRDNZ_MASK (1 << 28)
-
-/* CONTROL_I2C_2 */
-#define OMAP4_SR_SDA_GLFENB_SHIFT 31
-#define OMAP4_SR_SDA_GLFENB_MASK (1 << 31)
-#define OMAP4_SR_SDA_LOAD_BITS_SHIFT 29
-#define OMAP4_SR_SDA_LOAD_BITS_MASK (0x3 << 29)
-#define OMAP4_SR_SDA_PULLUPRESX_SHIFT 28
-#define OMAP4_SR_SDA_PULLUPRESX_MASK (1 << 28)
-#define OMAP4_SR_SCL_GLFENB_SHIFT 27
-#define OMAP4_SR_SCL_GLFENB_MASK (1 << 27)
-#define OMAP4_SR_SCL_LOAD_BITS_SHIFT 25
-#define OMAP4_SR_SCL_LOAD_BITS_MASK (0x3 << 25)
-#define OMAP4_SR_SCL_PULLUPRESX_SHIFT 24
-#define OMAP4_SR_SCL_PULLUPRESX_MASK (1 << 24)
-
-/* CONTROL_JTAG */
-#define OMAP4_JTAG_NTRST_EN_SHIFT 31
-#define OMAP4_JTAG_NTRST_EN_MASK (1 << 31)
-#define OMAP4_JTAG_TCK_EN_SHIFT 30
-#define OMAP4_JTAG_TCK_EN_MASK (1 << 30)
-#define OMAP4_JTAG_RTCK_EN_SHIFT 29
-#define OMAP4_JTAG_RTCK_EN_MASK (1 << 29)
-#define OMAP4_JTAG_TDI_EN_SHIFT 28
-#define OMAP4_JTAG_TDI_EN_MASK (1 << 28)
-#define OMAP4_JTAG_TDO_EN_SHIFT 27
-#define OMAP4_JTAG_TDO_EN_MASK (1 << 27)
-
-/* CONTROL_SYS */
-#define OMAP4_SYS_NRESWARM_PIPU_SHIFT 31
-#define OMAP4_SYS_NRESWARM_PIPU_MASK (1 << 31)
-
-/* WKUP_CONTROL_SPARE_RW */
-#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT 0
-#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK (0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R */
-#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT 0
-#define OMAP4_WKUP_CONTROL_SPARE_R_MASK (0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R_C0 */
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT 31
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK (1 << 31)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT 30
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK (1 << 30)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT 29
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK (1 << 29)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT 28
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK (1 << 28)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT 27
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK (1 << 27)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT 26
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK (1 << 26)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT 25
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK (1 << 25)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT 24
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK (1 << 24)
-
-#endif
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index b6f8f348296e..324f02bf8a51 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -432,9 +432,9 @@ static int __init omap2_init_devices(void)
*/
omap_init_audio();
omap_init_camera();
- omap_init_mbox();
/* If dtb is there, the devices will be created dynamically */
if (!of_have_populated_dt()) {
+ omap_init_mbox();
omap_init_mcspi();
omap_init_sham();
omap_init_aes();
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index a6d2cf1f8d02..e1a56d87599e 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -259,6 +259,9 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
d->dev_caps |= HS_CHANNELS_RESERVED;
+ if (platform_get_irq_byname(pdev, "0") < 0)
+ d->dev_caps |= DMA_ENGINE_HANDLE_IRQ;
+
/* Check the capabilities register for descriptor loading feature */
if (dma_read(CAPS_0, 0) & DMA_HAS_DESCRIPTOR_CAPS)
dma_common_ch_end = CCDN;
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 6d7ba37e2257..ac3d789ac3cd 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -28,11 +28,8 @@
#include <linux/bitops.h>
#include <linux/clkdev.h>
-#include "soc.h"
#include "clockdomain.h"
#include "clock.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-34xx.h"
/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
#define DPLL_AUTOIDLE_DISABLE 0x0
@@ -310,7 +307,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
* Set jitter correction. Jitter correction applicable for OMAP343X
* only since freqsel field is no longer present on other devices.
*/
- if (cpu_is_omap343x()) {
+ if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
v = omap2_clk_readl(clk, dd->control_reg);
v &= ~dd->freqsel_mask;
v |= freqsel << __ffs(dd->freqsel_mask);
@@ -478,6 +475,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct clk *new_parent = NULL;
+ unsigned long rrate;
u16 freqsel = 0;
struct dpll_data *dd;
int ret;
@@ -505,14 +503,22 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
__clk_prepare(dd->clk_ref);
clk_enable(dd->clk_ref);
- if (dd->last_rounded_rate != rate)
- rate = __clk_round_rate(hw->clk, rate);
+ /* XXX this check is probably pointless in the CCF context */
+ if (dd->last_rounded_rate != rate) {
+ rrate = __clk_round_rate(hw->clk, rate);
+ if (rrate != rate) {
+ pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
+ __func__, __clk_get_name(hw->clk),
+ rrate, rate);
+ rate = rrate;
+ }
+ }
if (dd->last_rounded_rate == 0)
return -EINVAL;
/* Freqsel is available only on OMAP343X devices */
- if (cpu_is_omap343x()) {
+ if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
freqsel = _omap3_dpll_compute_freqsel(clk,
dd->last_rounded_n);
WARN_ON(!freqsel);
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 52f9438b92f2..4613f1e86988 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -15,10 +15,7 @@
#include <linux/io.h>
#include <linux/bitops.h>
-#include "soc.h"
#include "clock.h"
-#include "clock44xx.h"
-#include "cm-regbits-44xx.h"
/*
* Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
@@ -29,13 +26,23 @@
#define OMAP4_DPLL_LP_FINT_MAX 1000000
#define OMAP4_DPLL_LP_FOUT_MAX 100000000
+/*
+ * Bitfield declarations
+ */
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK (1 << 8)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK (1 << 10)
+#define OMAP4430_DPLL_REGM4XEN_MASK (1 << 11)
+
+/* Static rate multiplier for OMAP4 REGM4XEN clocks */
+#define OMAP4430_REGM4XEN_MULT 4
+
/* Supported only on OMAP4 */
int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
{
u32 v;
u32 mask;
- if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ if (!clk || !clk->clksel_reg)
return -EINVAL;
mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -54,7 +61,7 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
u32 v;
u32 mask;
- if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ if (!clk || !clk->clksel_reg)
return;
mask = clk->flags & CLOCK_CLKOUTX2 ?
@@ -72,7 +79,7 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
u32 v;
u32 mask;
- if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+ if (!clk || !clk->clksel_reg)
return;
mask = clk->flags & CLOCK_CLKOUTX2 ?
diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c
deleted file mode 100644
index f7492df1cbba..000000000000
--- a/arch/arm/mach-omap2/dsp.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * TI's OMAP DSP platform device registration
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.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.
- */
-
-/*
- * XXX The function pointers to the PRM/CM functions are incorrect and
- * should be removed. No device driver should be changing PRM/CM bits
- * directly; that's a layering violation -- those bits are the responsibility
- * of the OMAP PM core code.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/memblock.h>
-
-#include "control.h"
-#include "cm2xxx_3xxx.h"
-#include "prm2xxx_3xxx.h"
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
-#include "omap-pm.h"
-#endif
-#include "soc.h"
-
-#include <linux/platform_data/dsp-omap.h>
-
-static struct platform_device *omap_dsp_pdev;
-
-static struct omap_dsp_platform_data omap_dsp_pdata __initdata = {
-#ifdef CONFIG_TIDSPBRIDGE_DVFS
- .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
- .dsp_get_opp = omap_pm_dsp_get_opp,
- .cpu_set_freq = omap_pm_cpu_set_freq,
- .cpu_get_freq = omap_pm_cpu_get_freq,
-#endif
- .dsp_prm_read = omap2_prm_read_mod_reg,
- .dsp_prm_write = omap2_prm_write_mod_reg,
- .dsp_prm_rmw_bits = omap2_prm_rmw_mod_reg_bits,
- .dsp_cm_read = omap2_cm_read_mod_reg,
- .dsp_cm_write = omap2_cm_write_mod_reg,
- .dsp_cm_rmw_bits = omap2_cm_rmw_mod_reg_bits,
-
- .set_bootaddr = omap_ctrl_write_dsp_boot_addr,
- .set_bootmode = omap_ctrl_write_dsp_boot_mode,
-};
-
-static phys_addr_t omap_dsp_phys_mempool_base;
-
-void __init omap_dsp_reserve_sdram_memblock(void)
-{
- phys_addr_t size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE;
- phys_addr_t paddr;
-
- if (!cpu_is_omap34xx())
- return;
-
- if (!size)
- return;
-
- paddr = arm_memblock_steal(size, SZ_1M);
- if (!paddr) {
- pr_err("%s: failed to reserve %llx bytes\n",
- __func__, (unsigned long long)size);
- return;
- }
-
- omap_dsp_phys_mempool_base = paddr;
-}
-
-static phys_addr_t omap_dsp_get_mempool_base(void)
-{
- return omap_dsp_phys_mempool_base;
-}
-
-static int __init omap_dsp_init(void)
-{
- struct platform_device *pdev;
- int err = -ENOMEM;
- struct omap_dsp_platform_data *pdata = &omap_dsp_pdata;
-
- if (!cpu_is_omap34xx())
- return 0;
-
- pdata->phys_mempool_base = omap_dsp_get_mempool_base();
-
- if (pdata->phys_mempool_base) {
- pdata->phys_mempool_size = CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE;
- pr_info("%s: %llx bytes @ %llx\n", __func__,
- (unsigned long long)pdata->phys_mempool_size,
- (unsigned long long)pdata->phys_mempool_base);
- }
-
- pdev = platform_device_alloc("omap-dsp", -1);
- if (!pdev)
- goto err_out;
-
- err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
- if (err)
- goto err_out;
-
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
-
- omap_dsp_pdev = pdev;
- return 0;
-
-err_out:
- platform_device_put(pdev);
- return err;
-}
-module_init(omap_dsp_init);
-
-static void __exit omap_dsp_exit(void)
-{
- if (!cpu_is_omap34xx())
- return;
-
- platform_device_unregister(omap_dsp_pdev);
-}
-module_exit(omap_dsp_exit);
-
-MODULE_AUTHOR("Hiroshi DOYU");
-MODULE_DESCRIPTION("TI's OMAP DSP platform device registration");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 93914d220069..8897ad7035fd 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -24,25 +24,6 @@
/* minimum size for IO mapping */
#define NAND_IO_SIZE 4
-static struct resource gpmc_nand_resource[] = {
- {
- .flags = IORESOURCE_MEM,
- },
- {
- .flags = IORESOURCE_IRQ,
- },
- {
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device gpmc_nand_device = {
- .name = "omap2-nand",
- .id = 0,
- .num_resources = ARRAY_SIZE(gpmc_nand_resource),
- .resource = gpmc_nand_resource,
-};
-
static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
{
/* platforms which support all ECC schemes */
@@ -95,43 +76,41 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
{
int err = 0;
struct gpmc_settings s;
- struct device *dev = &gpmc_nand_device.dev;
-
- memset(&s, 0, sizeof(struct gpmc_settings));
+ struct platform_device *pdev;
+ struct resource gpmc_nand_res[] = {
+ { .flags = IORESOURCE_MEM, },
+ { .flags = IORESOURCE_IRQ, },
+ { .flags = IORESOURCE_IRQ, },
+ };
- gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+ BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
- (unsigned long *)&gpmc_nand_resource[0].start);
+ (unsigned long *)&gpmc_nand_res[0].start);
if (err < 0) {
- dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
- gpmc_nand_data->cs, err);
+ pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n",
+ gpmc_nand_data->cs, err);
return err;
}
-
- gpmc_nand_resource[0].end = gpmc_nand_resource[0].start +
- NAND_IO_SIZE - 1;
-
- gpmc_nand_resource[1].start =
- gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
- gpmc_nand_resource[2].start =
- gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
+ gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
+ gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
+ gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
if (gpmc_t) {
err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
if (err < 0) {
- dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+ pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
return err;
}
}
+ memset(&s, 0, sizeof(struct gpmc_settings));
if (gpmc_nand_data->of_node)
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
else
gpmc_set_legacy(gpmc_nand_data, &s);
s.device_nand = true;
-
err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
if (err < 0)
goto out_free_cs;
@@ -143,18 +122,34 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
- dev_err(dev, "Unsupported NAND ECC scheme selected\n");
- return -EINVAL;
+ pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
+ err = -EINVAL;
+ goto out_free_cs;
}
- err = platform_device_register(&gpmc_nand_device);
- if (err < 0) {
- dev_err(dev, "Unable to register NAND device\n");
- goto out_free_cs;
+
+ pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs);
+ if (pdev) {
+ err = platform_device_add_resources(pdev, gpmc_nand_res,
+ ARRAY_SIZE(gpmc_nand_res));
+ if (!err)
+ pdev->dev.platform_data = gpmc_nand_data;
+ } else {
+ err = -ENOMEM;
+ }
+ if (err)
+ goto out_free_pdev;
+
+ err = platform_device_add(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to register NAND device\n");
+ goto out_free_pdev;
}
return 0;
+out_free_pdev:
+ platform_device_put(pdev);
out_free_cs:
gpmc_cs_free(gpmc_nand_data->cs);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8f559450c876..5d0667c119f6 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -53,6 +53,7 @@
#include "prm2xxx.h"
#include "prm3xxx.h"
#include "prm44xx.h"
+#include "opp2xxx.h"
/*
* omap_clk_soc_init: points to a function that does the SoC-specific
@@ -410,7 +411,8 @@ void __init omap2420_init_early(void)
omap242x_clockdomains_init();
omap2420_hwmod_init();
omap_hwmod_init_postsetup();
- omap_clk_soc_init = omap2420_clk_init;
+ omap_clk_soc_init = omap2420_dt_clk_init;
+ rate_table = omap2420_rate_table;
}
void __init omap2420_init_late(void)
@@ -439,7 +441,8 @@ void __init omap2430_init_early(void)
omap243x_clockdomains_init();
omap2430_hwmod_init();
omap_hwmod_init_postsetup();
- omap_clk_soc_init = omap2430_clk_init;
+ omap_clk_soc_init = omap2430_dt_clk_init;
+ rate_table = omap2430_rate_table;
}
void __init omap2430_init_late(void)
@@ -728,6 +731,8 @@ int __init omap_clk_init(void)
if (!omap_clk_soc_init)
return 0;
+ ti_clk_init_features();
+
ret = of_prcm_init();
if (!ret)
ret = omap_clk_soc_init();
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f62f7537d899..ac8a249779f2 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -681,29 +681,19 @@ static ssize_t omap_mux_dbg_signal_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- char buf[OMAP_MUX_MAX_ARG_CHAR];
struct seq_file *seqf;
struct omap_mux *m;
- unsigned long val;
- int buf_size, ret;
+ u16 val;
+ int ret;
struct omap_mux_partition *partition;
if (count > OMAP_MUX_MAX_ARG_CHAR)
return -EINVAL;
- memset(buf, 0, sizeof(buf));
- buf_size = min(count, sizeof(buf) - 1);
-
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
-
- ret = strict_strtoul(buf, 0x10, &val);
+ ret = kstrtou16_from_user(user_buf, count, 0x10, &val);
if (ret < 0)
return ret;
- if (val > 0xffff)
- return -EINVAL;
-
seqf = file->private_data;
m = seqf->private;
@@ -711,7 +701,7 @@ static ssize_t omap_mux_dbg_signal_write(struct file *file,
if (!partition)
return -ENODEV;
- omap_mux_write(partition, (u16)val, m->reg_offset);
+ omap_mux_write(partition, val, m->reg_offset);
*ppos += count;
return count;
@@ -917,14 +907,14 @@ static void __init omap_mux_set_cmdline_signals(void)
while ((token = strsep(&next_opt, ",")) != NULL) {
char *keyval, *name;
- unsigned long val;
+ u16 val;
keyval = token;
name = strsep(&keyval, "=");
if (name) {
int res;
- res = strict_strtoul(keyval, 0x10, &val);
+ res = kstrtou16(keyval, 0x10, &val);
if (res < 0)
continue;
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index f1fab5684a24..4068350f9059 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -34,8 +34,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
pdata->name = oh->name;
pdata->nr_tlb_entries = a->nr_tlb_entries;
- pdata->da_start = a->da_start;
- pdata->da_end = a->da_end;
if (oh->rst_lines_cnt == 1) {
pdata->reset_name = oh->rst_lines->name;
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 2f15979c2e9c..65b1647092bd 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -16,7 +16,6 @@
#include <linux/i2c-omap.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "omap_hwmod.h"
@@ -163,18 +162,6 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
};
/* mailbox */
-static struct omap_mbox_dev_info omap2420_mailbox_info[] = {
- { .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 },
- { .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 },
-};
-
-static struct omap_mbox_pdata omap2420_mailbox_attrs = {
- .num_users = 4,
- .num_fifos = 6,
- .info_cnt = ARRAY_SIZE(omap2420_mailbox_info),
- .info = omap2420_mailbox_info,
-};
-
static struct omap_hwmod omap2420_mailbox_hwmod = {
.name = "mailbox",
.class = &omap2xxx_mailbox_hwmod_class,
@@ -188,7 +175,6 @@ static struct omap_hwmod omap2420_mailbox_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &omap2420_mailbox_attrs,
};
/*
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 6d1b60902179..c2555cb95e71 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -17,7 +17,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "omap_hwmod.h"
@@ -161,17 +160,6 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
};
/* mailbox */
-static struct omap_mbox_dev_info omap2430_mailbox_info[] = {
- { .name = "dsp", .tx_id = 0, .rx_id = 1 },
-};
-
-static struct omap_mbox_pdata omap2430_mailbox_attrs = {
- .num_users = 4,
- .num_fifos = 6,
- .info_cnt = ARRAY_SIZE(omap2430_mailbox_info),
- .info = omap2430_mailbox_info,
-};
-
static struct omap_hwmod omap2430_mailbox_hwmod = {
.name = "mailbox",
.class = &omap2xxx_mailbox_hwmod_class,
@@ -185,7 +173,6 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &omap2430_mailbox_attrs,
};
/* mcspi3 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
index 0413daba2dba..c1e98d589100 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
@@ -152,15 +152,6 @@ struct omap_hwmod_addr_space omap2_dma_system_addrs[] = {
{ }
};
-struct omap_hwmod_addr_space omap2_mailbox_addrs[] = {
- {
- .pa_start = 0x48094000,
- .pa_end = 0x48094000 + SZ_512 - 1,
- .flags = ADDR_TYPE_RT,
- },
- { }
-};
-
struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
{
.name = "mpu",
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index 5da7a42a6d90..c6c6384de867 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -37,46 +37,6 @@ struct omap_hwmod_class omap2_uart_class = {
};
/*
- * 'dss' class
- * display sub-system
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
- SYSS_HAS_RESET_STATUS),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dss_hwmod_class = {
- .name = "dss",
- .sysc = &omap2_dss_sysc,
- .reset = omap_dss_reset,
-};
-
-/*
- * 'rfbi' class
- * remote frame buffer interface
- */
-
-static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_rfbi_hwmod_class = {
- .name = "rfbi",
- .sysc = &omap2_rfbi_sysc,
-};
-
-/*
* 'venc' class
* video encoder
*/
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
index e2db378b849e..8f5989d48a80 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
@@ -317,21 +317,11 @@ struct omap_hwmod_ocp_if am33xx_l4_per__i2c3 = {
.user = OCP_USER_MPU,
};
-static struct omap_hwmod_addr_space am33xx_mailbox_addrs[] = {
- {
- .pa_start = 0x480C8000,
- .pa_end = 0x480C8000 + (SZ_4K - 1),
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
/* l4 ls -> mailbox */
struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
.master = &am33xx_l4_ls_hwmod,
.slave = &am33xx_mailbox_hwmod,
.clk = "l4ls_gclk",
- .addr = am33xx_mailbox_addrs,
.user = OCP_USER_MPU,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 1cd0cfdc03e0..e9516b454e76 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -2986,8 +2986,6 @@ static struct omap_hwmod_class omap3xxx_mmu_hwmod_class = {
/* mmu isp */
static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
- .da_start = 0x0,
- .da_end = 0xfffff000,
.nr_tlb_entries = 8,
};
@@ -3026,8 +3024,6 @@ static struct omap_hwmod omap3xxx_mmu_isp_hwmod = {
/* mmu iva */
static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
- .da_start = 0x11000000,
- .da_end = 0xfffff000,
.nr_tlb_entries = 32,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
index 5c2cc8083fdd..fea01aa3ef42 100644
--- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
@@ -19,6 +19,8 @@
#include "omap_hwmod.h"
#include "omap_hwmod_33xx_43xx_common_data.h"
#include "prcm43xx.h"
+#include "omap_hwmod_common_data.h"
+
/* IP blocks */
static struct omap_hwmod am43xx_l4_hs_hwmod = {
@@ -415,6 +417,72 @@ static struct omap_hwmod am43xx_qspi_hwmod = {
},
};
+/* dss */
+
+static struct omap_hwmod am43xx_dss_core_hwmod = {
+ .name = "dss_core",
+ .class = &omap2_dss_hwmod_class,
+ .clkdm_name = "dss_clkdm",
+ .main_clk = "disp_clk",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/* dispc */
+
+struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = {
+ .manager_count = 1,
+ .has_framedonetv_irq = 0
+};
+
+static struct omap_hwmod_class_sysconfig am43xx_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_MIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am43xx_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &am43xx_dispc_sysc,
+};
+
+static struct omap_hwmod am43xx_dss_dispc_hwmod = {
+ .name = "dss_dispc",
+ .class = &am43xx_dispc_hwmod_class,
+ .clkdm_name = "dss_clkdm",
+ .main_clk = "disp_clk",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+ },
+ },
+ .dev_attr = &am43xx_dss_dispc_dev_attr,
+};
+
+/* rfbi */
+
+static struct omap_hwmod am43xx_dss_rfbi_hwmod = {
+ .name = "dss_rfbi",
+ .class = &omap2_rfbi_hwmod_class,
+ .clkdm_name = "dss_clkdm",
+ .main_clk = "disp_clk",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET,
+ },
+ },
+};
+
/* Interfaces */
static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
.master = &am33xx_l3_main_hwmod,
@@ -654,6 +722,34 @@ static struct omap_hwmod_ocp_if am43xx_l3_s__qspi = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+static struct omap_hwmod_ocp_if am43xx_dss__l3_main = {
+ .master = &am43xx_dss_core_hwmod,
+ .slave = &am33xx_l3_main_hwmod,
+ .clk = "l3_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am43xx_dss_core_hwmod,
+ .clk = "l4ls_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_dispc = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am43xx_dss_dispc_hwmod,
+ .clk = "l4ls_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am43xx_dss_rfbi_hwmod,
+ .clk = "l4ls_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_l4_wkup__synctimer,
&am43xx_l4_ls__timer8,
@@ -748,6 +844,10 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
&am43xx_l4_ls__ocp2scp1,
&am43xx_l3_s__usbotgss0,
&am43xx_l3_s__usbotgss1,
+ &am43xx_dss__l3_main,
+ &am43xx_l4_ls__dss,
+ &am43xx_l4_ls__dss_dispc,
+ &am43xx_l4_ls__dss_rfbi,
NULL,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 41e54f759934..44e5634bba34 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2084,8 +2084,6 @@ static struct omap_hwmod_class omap44xx_mmu_hwmod_class = {
/* mmu ipu */
static struct omap_mmu_dev_attr mmu_ipu_dev_attr = {
- .da_start = 0x0,
- .da_end = 0xfffff000,
.nr_tlb_entries = 32,
};
@@ -2133,8 +2131,6 @@ static struct omap_hwmod omap44xx_mmu_ipu_hwmod = {
/* mmu dsp */
static struct omap_mmu_dev_attr mmu_dsp_dev_attr = {
- .da_start = 0x0,
- .da_end = 0xfffff000,
.nr_tlb_entries = 32,
};
@@ -4142,21 +4138,11 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
- {
- .pa_start = 0x4a0f4000,
- .pa_end = 0x4a0f41ff,
- .flags = ADDR_TYPE_RT
- },
- { }
-};
-
/* l4_cfg -> mailbox */
static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
.master = &omap44xx_l4_cfg_hwmod,
.slave = &omap44xx_mailbox_hwmod,
.clk = "l4_div_ck",
- .addr = omap44xx_mailbox_addrs,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 284324f2b98a..2757abf87fbc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -273,6 +273,56 @@ static struct omap_hwmod dra7xx_ctrl_module_wkup_hwmod = {
};
/*
+ * 'gmac' class
+ * cpsw/gmac sub system
+ */
+static struct omap_hwmod_class_sysconfig dra7xx_gmac_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x8,
+ .syss_offs = 0x4,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSS_HAS_RESET_STATUS),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+ MSTANDBY_NO),
+ .sysc_fields = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dra7xx_gmac_hwmod_class = {
+ .name = "gmac",
+ .sysc = &dra7xx_gmac_sysc,
+};
+
+static struct omap_hwmod dra7xx_gmac_hwmod = {
+ .name = "gmac",
+ .class = &dra7xx_gmac_hwmod_class,
+ .clkdm_name = "gmac_clkdm",
+ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+ .main_clk = "dpll_gmac_ck",
+ .mpu_rt_idx = 1,
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_GMAC_GMAC_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_GMAC_GMAC_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/*
+ * 'mdio' class
+ */
+static struct omap_hwmod_class dra7xx_mdio_hwmod_class = {
+ .name = "davinci_mdio",
+};
+
+static struct omap_hwmod dra7xx_mdio_hwmod = {
+ .name = "davinci_mdio",
+ .class = &dra7xx_mdio_hwmod_class,
+ .clkdm_name = "gmac_clkdm",
+ .main_clk = "dpll_gmac_ck",
+};
+
+/*
* 'dcan' class
*
*/
@@ -343,19 +393,10 @@ static struct omap_dma_dev_attr dma_dev_attr = {
};
/* dma_system */
-static struct omap_hwmod_irq_info dra7xx_dma_system_irqs[] = {
- { .name = "0", .irq = 12 + DRA7XX_IRQ_GIC_START },
- { .name = "1", .irq = 13 + DRA7XX_IRQ_GIC_START },
- { .name = "2", .irq = 14 + DRA7XX_IRQ_GIC_START },
- { .name = "3", .irq = 15 + DRA7XX_IRQ_GIC_START },
- { .irq = -1 }
-};
-
static struct omap_hwmod dra7xx_dma_system_hwmod = {
.name = "dma_system",
.class = &dra7xx_dma_hwmod_class,
.clkdm_name = "dma_clkdm",
- .mpu_irqs = dra7xx_dma_system_irqs,
.main_clk = "l3_iclk_div",
.prcm = {
.omap4 = {
@@ -939,6 +980,194 @@ static struct omap_hwmod dra7xx_i2c5_hwmod = {
};
/*
+ * 'mailbox' class
+ *
+ */
+
+static struct omap_hwmod_class_sysconfig dra7xx_mailbox_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+ SYSC_HAS_SOFTRESET),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class dra7xx_mailbox_hwmod_class = {
+ .name = "mailbox",
+ .sysc = &dra7xx_mailbox_sysc,
+};
+
+/* mailbox1 */
+static struct omap_hwmod dra7xx_mailbox1_hwmod = {
+ .name = "mailbox1",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX1_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX1_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox2 */
+static struct omap_hwmod dra7xx_mailbox2_hwmod = {
+ .name = "mailbox2",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX2_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX2_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox3 */
+static struct omap_hwmod dra7xx_mailbox3_hwmod = {
+ .name = "mailbox3",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX3_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX3_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox4 */
+static struct omap_hwmod dra7xx_mailbox4_hwmod = {
+ .name = "mailbox4",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX4_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX4_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox5 */
+static struct omap_hwmod dra7xx_mailbox5_hwmod = {
+ .name = "mailbox5",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX5_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX5_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox6 */
+static struct omap_hwmod dra7xx_mailbox6_hwmod = {
+ .name = "mailbox6",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX6_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX6_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox7 */
+static struct omap_hwmod dra7xx_mailbox7_hwmod = {
+ .name = "mailbox7",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX7_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX7_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox8 */
+static struct omap_hwmod dra7xx_mailbox8_hwmod = {
+ .name = "mailbox8",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX8_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX8_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox9 */
+static struct omap_hwmod dra7xx_mailbox9_hwmod = {
+ .name = "mailbox9",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX9_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX9_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox10 */
+static struct omap_hwmod dra7xx_mailbox10_hwmod = {
+ .name = "mailbox10",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX10_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX10_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox11 */
+static struct omap_hwmod dra7xx_mailbox11_hwmod = {
+ .name = "mailbox11",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX11_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX11_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox12 */
+static struct omap_hwmod dra7xx_mailbox12_hwmod = {
+ .name = "mailbox12",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX12_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX12_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/* mailbox13 */
+static struct omap_hwmod dra7xx_mailbox13_hwmod = {
+ .name = "mailbox13",
+ .class = &dra7xx_mailbox_hwmod_class,
+ .clkdm_name = "l4cfg_clkdm",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX13_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L4CFG_MAILBOX13_CONTEXT_OFFSET,
+ },
+ },
+};
+
+/*
* 'mcspi' class
*
*/
@@ -1215,6 +1444,97 @@ static struct omap_hwmod dra7xx_ocp2scp1_hwmod = {
},
};
+/* ocp2scp3 */
+static struct omap_hwmod dra7xx_ocp2scp3_hwmod = {
+ .name = "ocp2scp3",
+ .class = &dra7xx_ocp2scp_hwmod_class,
+ .clkdm_name = "l3init_clkdm",
+ .main_clk = "l4_root_clk_div",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L3INIT_OCP2SCP3_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_HWCTRL,
+ },
+ },
+};
+
+/*
+ * 'PCIE' class
+ *
+ */
+
+static struct omap_hwmod_class dra7xx_pcie_hwmod_class = {
+ .name = "pcie",
+};
+
+/* pcie1 */
+static struct omap_hwmod dra7xx_pcie1_hwmod = {
+ .name = "pcie1",
+ .class = &dra7xx_pcie_hwmod_class,
+ .clkdm_name = "pcie_clkdm",
+ .main_clk = "l4_root_clk_div",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/* pcie2 */
+static struct omap_hwmod dra7xx_pcie2_hwmod = {
+ .name = "pcie2",
+ .class = &dra7xx_pcie_hwmod_class,
+ .clkdm_name = "pcie_clkdm",
+ .main_clk = "l4_root_clk_div",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_PCIE_CLKSTCTRL_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/*
+ * 'PCIE PHY' class
+ *
+ */
+
+static struct omap_hwmod_class dra7xx_pcie_phy_hwmod_class = {
+ .name = "pcie-phy",
+};
+
+/* pcie1 phy */
+static struct omap_hwmod dra7xx_pcie1_phy_hwmod = {
+ .name = "pcie1-phy",
+ .class = &dra7xx_pcie_phy_hwmod_class,
+ .clkdm_name = "l3init_clkdm",
+ .main_clk = "l4_root_clk_div",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L3INIT_PCIESS1_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L3INIT_PCIESS1_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/* pcie2 phy */
+static struct omap_hwmod dra7xx_pcie2_phy_hwmod = {
+ .name = "pcie2-phy",
+ .class = &dra7xx_pcie_phy_hwmod_class,
+ .clkdm_name = "l3init_clkdm",
+ .main_clk = "l4_root_clk_div",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_L3INIT_PCIESS2_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_L3INIT_PCIESS2_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
/*
* 'qspi' class
*
@@ -1249,6 +1569,38 @@ static struct omap_hwmod dra7xx_qspi_hwmod = {
};
/*
+ * 'rtcss' class
+ *
+ */
+static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = {
+ .sysc_offs = 0x0078,
+ .sysc_flags = SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ SIDLE_SMART_WKUP),
+ .sysc_fields = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dra7xx_rtcss_hwmod_class = {
+ .name = "rtcss",
+ .sysc = &dra7xx_rtcss_sysc,
+};
+
+/* rtcss */
+static struct omap_hwmod dra7xx_rtcss_hwmod = {
+ .name = "rtcss",
+ .class = &dra7xx_rtcss_hwmod_class,
+ .clkdm_name = "rtc_clkdm",
+ .main_clk = "sys_32k_ck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = DRA7XX_CM_RTC_RTCSS_CLKCTRL_OFFSET,
+ .context_offs = DRA7XX_RM_RTC_RTCSS_CONTEXT_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+};
+
+/*
* 'sata' class
*
*/
@@ -2007,6 +2359,19 @@ static struct omap_hwmod_ocp_if dra7xx_l4_wkup__ctrl_module_wkup = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__cpgmac0 = {
+ .master = &dra7xx_l4_per2_hwmod,
+ .slave = &dra7xx_gmac_hwmod,
+ .clk = "dpll_gmac_ck",
+ .user = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if dra7xx_gmac__mdio = {
+ .master = &dra7xx_gmac_hwmod,
+ .slave = &dra7xx_mdio_hwmod,
+ .user = OCP_USER_MPU,
+};
+
/* l4_wkup -> dcan1 */
static struct omap_hwmod_ocp_if dra7xx_l4_wkup__dcan1 = {
.master = &dra7xx_l4_wkup_hwmod,
@@ -2254,6 +2619,110 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c5 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+/* l4_cfg -> mailbox1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_mailbox1_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox2 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox2_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox3 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox3 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox3_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox4 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox4 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox4_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox5 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox5 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox5_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox6 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox6 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox6_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox7 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox7 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox7_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox8 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox8 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox8_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox9 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox9 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox9_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox10 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox10 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox10_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox11 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox11 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox11_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox12 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox12 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox12_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> mailbox13 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox13 = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_mailbox13_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
/* l4_per1 -> mcspi1 */
static struct omap_hwmod_ocp_if dra7xx_l4_per1__mcspi1 = {
.master = &dra7xx_l4_per1_hwmod,
@@ -2334,6 +2803,62 @@ static struct omap_hwmod_ocp_if dra7xx_l4_cfg__ocp2scp1 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+/* l4_cfg -> ocp2scp3 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__ocp2scp3 = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_ocp2scp3_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> pcie1 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__pcie1 = {
+ .master = &dra7xx_l3_main_1_hwmod,
+ .slave = &dra7xx_pcie1_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie1 = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_pcie1_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> pcie2 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__pcie2 = {
+ .master = &dra7xx_l3_main_1_hwmod,
+ .slave = &dra7xx_pcie2_hwmod,
+ .clk = "l3_iclk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie2 = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_pcie2_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie1 phy */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie1_phy = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_pcie1_phy_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> pcie2 phy */
+static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pcie2_phy = {
+ .master = &dra7xx_l4_cfg_hwmod,
+ .slave = &dra7xx_pcie2_phy_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
static struct omap_hwmod_addr_space dra7xx_qspi_addrs[] = {
{
.pa_start = 0x4b300000,
@@ -2352,6 +2877,14 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__qspi = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+/* l4_per3 -> rtcss */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__rtcss = {
+ .master = &dra7xx_l4_per3_hwmod,
+ .slave = &dra7xx_rtcss_hwmod,
+ .clk = "l4_root_clk_div",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
static struct omap_hwmod_addr_space dra7xx_sata_addrs[] = {
{
.name = "sysc",
@@ -2650,6 +3183,8 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
&dra7xx_l4_wkup__ctrl_module_wkup,
&dra7xx_l4_wkup__dcan1,
&dra7xx_l4_per2__dcan2,
+ &dra7xx_l4_per2__cpgmac0,
+ &dra7xx_gmac__mdio,
&dra7xx_l4_cfg__dma_system,
&dra7xx_l3_main_1__dss,
&dra7xx_l3_main_1__dispc,
@@ -2670,6 +3205,19 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
&dra7xx_l4_per1__i2c3,
&dra7xx_l4_per1__i2c4,
&dra7xx_l4_per1__i2c5,
+ &dra7xx_l4_cfg__mailbox1,
+ &dra7xx_l4_per3__mailbox2,
+ &dra7xx_l4_per3__mailbox3,
+ &dra7xx_l4_per3__mailbox4,
+ &dra7xx_l4_per3__mailbox5,
+ &dra7xx_l4_per3__mailbox6,
+ &dra7xx_l4_per3__mailbox7,
+ &dra7xx_l4_per3__mailbox8,
+ &dra7xx_l4_per3__mailbox9,
+ &dra7xx_l4_per3__mailbox10,
+ &dra7xx_l4_per3__mailbox11,
+ &dra7xx_l4_per3__mailbox12,
+ &dra7xx_l4_per3__mailbox13,
&dra7xx_l4_per1__mcspi1,
&dra7xx_l4_per1__mcspi2,
&dra7xx_l4_per1__mcspi3,
@@ -2680,7 +3228,15 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
&dra7xx_l4_per1__mmc4,
&dra7xx_l4_cfg__mpu,
&dra7xx_l4_cfg__ocp2scp1,
+ &dra7xx_l4_cfg__ocp2scp3,
+ &dra7xx_l3_main_1__pcie1,
+ &dra7xx_l4_cfg__pcie1,
+ &dra7xx_l3_main_1__pcie2,
+ &dra7xx_l4_cfg__pcie2,
+ &dra7xx_l4_cfg__pcie1_phy,
+ &dra7xx_l4_cfg__pcie2_phy,
&dra7xx_l3_main_1__qspi,
+ &dra7xx_l4_per3__rtcss,
&dra7xx_l4_cfg__sata,
&dra7xx_l4_cfg__smartreflex_core,
&dra7xx_l4_cfg__smartreflex_mpu,
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 2c38c6b0ee03..11ed5a17dd77 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -33,7 +33,6 @@ extern struct omap_hwmod_addr_space omap2_mcspi1_addr_space[];
extern struct omap_hwmod_addr_space omap2_mcspi2_addr_space[];
extern struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[];
extern struct omap_hwmod_addr_space omap2_dma_system_addrs[];
-extern struct omap_hwmod_addr_space omap2_mailbox_addrs[];
extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
extern struct omap_hwmod_addr_space omap2_hdq1w_addr_space[];
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c
new file mode 100644
index 000000000000..f21664da25a2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_common_ipblock_data.c
@@ -0,0 +1,55 @@
+/*
+ * omap_hwmod_common_ipblock_data.c - common IP block data for OMAP2+
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap_hwmod.h"
+#include "omap_hwmod_common_data.h"
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dss_hwmod_class = {
+ .name = "dss",
+ .sysc = &omap2_dss_sysc,
+ .reset = omap_dss_reset,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+ SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_rfbi_hwmod_class = {
+ .name = "rfbi",
+ .sysc = &omap2_rfbi_sysc,
+};
+
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index a5ea988ff340..fe01c5a03aa2 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -75,9 +75,9 @@ static int omap2_enter_full_retention(void)
/* Clear old wake-up events */
/* REVISIT: These write to reserved bits? */
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
- omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+ omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -104,23 +104,18 @@ no_sleep:
clk_enable(osc_ck);
/* clear CORE wake-up events */
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
- omap2_prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
+ omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);
/* MPU domain wake events */
- l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
- if (l & 0x01)
- omap2_prm_write_mod_reg(0x01, OCP_MOD,
- OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
- if (l & 0x20)
- omap2_prm_write_mod_reg(0x20, OCP_MOD,
- OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+ omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+ 0x1);
- /* Mask future PRCM-to-MPU interrupts */
- omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
+ omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
+ 0x20);
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
@@ -148,9 +143,9 @@ static void omap2_enter_mpu_retention(void)
* it is in retention mode. */
if (omap2_allow_mpu_retention()) {
/* REVISIT: These write to reserved bits? */
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
- omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+ omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+ omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
/* Try to enter MPU retention */
pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -249,6 +244,10 @@ static void __init prcm_setup_regs(void)
/* Enable wake-up events */
omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
WKUP_MOD, PM_WKEN);
+
+ /* Enable SYS_CLKEN control when all domains idle */
+ omap2_prm_set_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, OMAP24XX_GR_MOD,
+ OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
}
int __init omap2_pm_init(void)
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 507d8eeaab95..3f80929a5f7e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -133,60 +133,13 @@ static void omap3_save_secure_ram_context(void)
}
}
-/*
- * PRCM Interrupt Handler Helper Function
- *
- * The purpose of this function is to clear any wake-up events latched
- * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
- * may occur whilst attempting to clear a PM_WKST_x register and thus
- * set another bit in this register. A while loop is used to ensure
- * that any peripheral wake-up events occurring while attempting to
- * clear the PM_WKST_x are detected and cleared.
- */
-static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
-{
- u32 wkst, fclk, iclk, clken;
- u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
- u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
- u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
- u16 grpsel_off = (regs == 3) ?
- OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
- int c = 0;
-
- wkst = omap2_prm_read_mod_reg(module, wkst_off);
- wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
- wkst &= ~ignore_bits;
- if (wkst) {
- iclk = omap2_cm_read_mod_reg(module, iclk_off);
- fclk = omap2_cm_read_mod_reg(module, fclk_off);
- while (wkst) {
- clken = wkst;
- omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
- /*
- * For USBHOST, we don't know whether HOST1 or
- * HOST2 woke us up, so enable both f-clocks
- */
- if (module == OMAP3430ES2_USBHOST_MOD)
- clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
- omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
- omap2_prm_write_mod_reg(wkst, module, wkst_off);
- wkst = omap2_prm_read_mod_reg(module, wkst_off);
- wkst &= ~ignore_bits;
- c++;
- }
- omap2_cm_write_mod_reg(iclk, module, iclk_off);
- omap2_cm_write_mod_reg(fclk, module, fclk_off);
- }
-
- return c;
-}
-
static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
{
int c;
- c = prcm_clear_mod_irqs(WKUP_MOD, 1,
- ~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
+ c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+ ~(OMAP3430_ST_IO_MASK |
+ OMAP3430_ST_IO_CHAIN_MASK));
return c ? IRQ_HANDLED : IRQ_NONE;
}
@@ -200,13 +153,14 @@ static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
* these are handled in a separate handler to avoid acking
* IO events before parsing in mux code
*/
- c = prcm_clear_mod_irqs(WKUP_MOD, 1,
- OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK);
- c += prcm_clear_mod_irqs(CORE_MOD, 1, 0);
- c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
+ c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
+ OMAP3430_ST_IO_MASK |
+ OMAP3430_ST_IO_CHAIN_MASK);
+ c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 1, 0);
+ c += omap3xxx_prm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
if (omap_rev() > OMAP3430_REV_ES1_0) {
- c += prcm_clear_mod_irqs(CORE_MOD, 3, 0);
- c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
+ c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 3, 0);
+ c += omap3xxx_prm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
}
return c ? IRQ_HANDLED : IRQ_NONE;
@@ -399,159 +353,11 @@ restore:
#define omap3_pm_suspend NULL
#endif /* CONFIG_SUSPEND */
-
-/**
- * omap3_iva_idle(): ensure IVA is in idle so it can be put into
- * retention
- *
- * In cases where IVA2 is activated by bootcode, it may prevent
- * full-chip retention or off-mode because it is not idle. This
- * function forces the IVA2 into idle state so it can go
- * into retention/off and thus allow full-chip retention/off.
- *
- **/
-static void __init omap3_iva_idle(void)
-{
- /* ensure IVA2 clock is disabled */
- omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
- /* if no clock activity, nothing else to do */
- if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
- OMAP3430_CLKACTIVITY_IVA2_MASK))
- return;
-
- /* Reset IVA2 */
- omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
- OMAP3430_RST2_IVA2_MASK |
- OMAP3430_RST3_IVA2_MASK,
- OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
- /* Enable IVA2 clock */
- omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
- OMAP3430_IVA2_MOD, CM_FCLKEN);
-
- /* Set IVA2 boot mode to 'idle' */
- omap3_ctrl_set_iva_bootmode_idle();
-
- /* Un-reset IVA2 */
- omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-
- /* Disable IVA2 clock */
- omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
-
- /* Reset IVA2 */
- omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
- OMAP3430_RST2_IVA2_MASK |
- OMAP3430_RST3_IVA2_MASK,
- OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
-}
-
-static void __init omap3_d2d_idle(void)
-{
- u16 mask, padconf;
-
- /* In a stand alone OMAP3430 where there is not a stacked
- * modem for the D2D Idle Ack and D2D MStandby must be pulled
- * high. S CONTROL_PADCONF_SAD2D_IDLEACK and
- * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */
- mask = (1 << 4) | (1 << 3); /* pull-up, enabled */
- padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY);
- padconf |= mask;
- omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY);
-
- padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK);
- padconf |= mask;
- omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK);
-
- /* reset modem */
- omap2_prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
- OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
- CORE_MOD, OMAP2_RM_RSTCTRL);
- omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
-}
-
static void __init prcm_setup_regs(void)
{
- u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
- OMAP3630_EN_UART4_MASK : 0;
- u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
- OMAP3630_GRPSEL_UART4_MASK : 0;
-
- /* XXX This should be handled by hwmod code or SCM init code */
- omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
-
- /*
- * Enable control of expternal oscillator through
- * sys_clkreq. In the long run clock framework should
- * take care of this.
- */
- omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
- 1 << OMAP_AUTOEXTCLKMODE_SHIFT,
- OMAP3430_GR_MOD,
- OMAP3_PRM_CLKSRC_CTRL_OFFSET);
-
- /* setup wakup source */
- omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
- OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
- WKUP_MOD, PM_WKEN);
- /* No need to write EN_IO, that is always enabled */
- omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
- OMAP3430_GRPSEL_GPT1_MASK |
- OMAP3430_GRPSEL_GPT12_MASK,
- WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-
- /* Enable PM_WKEN to support DSS LPR */
- omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
- OMAP3430_DSS_MOD, PM_WKEN);
-
- /* Enable wakeups in PER */
- omap2_prm_write_mod_reg(omap3630_en_uart4_mask |
- OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
- OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
- OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
- OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
- OMAP3430_EN_MCBSP4_MASK,
- OMAP3430_PER_MOD, PM_WKEN);
- /* and allow them to wake up MPU */
- omap2_prm_write_mod_reg(omap3630_grpsel_uart4_mask |
- OMAP3430_GRPSEL_GPIO2_MASK |
- OMAP3430_GRPSEL_GPIO3_MASK |
- OMAP3430_GRPSEL_GPIO4_MASK |
- OMAP3430_GRPSEL_GPIO5_MASK |
- OMAP3430_GRPSEL_GPIO6_MASK |
- OMAP3430_GRPSEL_UART3_MASK |
- OMAP3430_GRPSEL_MCBSP2_MASK |
- OMAP3430_GRPSEL_MCBSP3_MASK |
- OMAP3430_GRPSEL_MCBSP4_MASK,
- OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
-
- /* Don't attach IVA interrupts */
- if (omap3_has_iva()) {
- omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
- omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
- omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
- omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
- OMAP3430_PM_IVAGRPSEL);
- }
-
- /* Clear any pending 'reset' flags */
- omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
- omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
-
- /* Clear any pending PRCM interrupts */
- omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
- /*
- * We need to idle iva2_pwrdm even on am3703 with no iva2.
- */
- omap3_iva_idle();
+ omap3_ctrl_init();
- omap3_d2d_idle();
+ omap3_prm_init_pm(cpu_is_omap3630(), omap3_has_iva());
}
void omap3_pm_off_mode_enable(int enable)
diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h
index 7785be984edd..ad7b3e9977f8 100644
--- a/arch/arm/mach-omap2/prcm43xx.h
+++ b/arch/arm/mach-omap2/prcm43xx.h
@@ -142,5 +142,6 @@
#define AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET 0x05B8
#define AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET 0x0268
#define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET 0x05C0
+#define AM43XX_CM_PER_DSS_CLKCTRL_OFFSET 0x0a20
#endif
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
index a3a3cca2bcc4..86958050547a 100644
--- a/arch/arm/mach-omap2/prm2xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -114,6 +114,24 @@ void omap2xxx_prm_dpll_reset(void)
omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
}
+/**
+ * omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
+ * @module: PRM module to clear wakeups from
+ * @regs: register offset to clear
+ * @wkst_mask: wakeup status mask to clear
+ *
+ * Clears wakeup status bits for a given module, so that the device can
+ * re-enter idle.
+ */
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
+{
+ u32 wkst;
+
+ wkst = omap2_prm_read_mod_reg(module, regs);
+ wkst &= wkst_mask;
+ omap2_prm_write_mod_reg(wkst, module, regs);
+}
+
int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
{
omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h
index d2cb6365716f..d73414139292 100644
--- a/arch/arm/mach-omap2/prm2xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx.h
@@ -125,6 +125,7 @@ extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
extern void omap2xxx_prm_dpll_reset(void);
+void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
extern int __init omap2xxx_prm_init(void);
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index 4bd7a2dca8af..2458be6fc67b 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -26,6 +26,8 @@
#include "prm2xxx_3xxx.h"
#include "cm2xxx_3xxx.h"
#include "prm-regbits-34xx.h"
+#include "cm3xxx.h"
+#include "cm-regbits-34xx.h"
static const struct omap_prcm_irq omap3_prcm_irqs[] = {
OMAP_PRCM_IRQ("wkup", 0, 0),
@@ -206,6 +208,167 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask)
}
/**
+ * omap3xxx_prm_clear_mod_irqs - clear wake-up events from PRCM interrupt
+ * @module: PRM module to clear wakeups from
+ * @regs: register set to clear, 1 or 3
+ * @ignore_bits: wakeup status bits to ignore
+ *
+ * The purpose of this function is to clear any wake-up events latched
+ * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
+ * may occur whilst attempting to clear a PM_WKST_x register and thus
+ * set another bit in this register. A while loop is used to ensure
+ * that any peripheral wake-up events occurring while attempting to
+ * clear the PM_WKST_x are detected and cleared.
+ */
+int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
+{
+ u32 wkst, fclk, iclk, clken;
+ u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
+ u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
+ u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1;
+ u16 grpsel_off = (regs == 3) ?
+ OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL;
+ int c = 0;
+
+ wkst = omap2_prm_read_mod_reg(module, wkst_off);
+ wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
+ wkst &= ~ignore_bits;
+ if (wkst) {
+ iclk = omap2_cm_read_mod_reg(module, iclk_off);
+ fclk = omap2_cm_read_mod_reg(module, fclk_off);
+ while (wkst) {
+ clken = wkst;
+ omap2_cm_set_mod_reg_bits(clken, module, iclk_off);
+ /*
+ * For USBHOST, we don't know whether HOST1 or
+ * HOST2 woke us up, so enable both f-clocks
+ */
+ if (module == OMAP3430ES2_USBHOST_MOD)
+ clken |= 1 << OMAP3430ES2_EN_USBHOST2_SHIFT;
+ omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
+ omap2_prm_write_mod_reg(wkst, module, wkst_off);
+ wkst = omap2_prm_read_mod_reg(module, wkst_off);
+ wkst &= ~ignore_bits;
+ c++;
+ }
+ omap2_cm_write_mod_reg(iclk, module, iclk_off);
+ omap2_cm_write_mod_reg(fclk, module, fclk_off);
+ }
+
+ return c;
+}
+
+/**
+ * omap3_prm_reset_modem - toggle reset signal for modem
+ *
+ * Toggles the reset signal to modem IP block. Required to allow
+ * OMAP3430 without stacked modem to idle properly.
+ */
+void __init omap3_prm_reset_modem(void)
+{
+ omap2_prm_write_mod_reg(
+ OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON_MASK |
+ OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST_MASK,
+ CORE_MOD, OMAP2_RM_RSTCTRL);
+ omap2_prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
+ * omap3_prm_init_pm - initialize PM related registers for PRM
+ * @has_uart4: SoC has UART4
+ * @has_iva: SoC has IVA
+ *
+ * Initializes PRM registers for PM use. Called from PM init.
+ */
+void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
+{
+ u32 en_uart4_mask;
+ u32 grpsel_uart4_mask;
+
+ /*
+ * Enable control of expternal oscillator through
+ * sys_clkreq. In the long run clock framework should
+ * take care of this.
+ */
+ omap2_prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK,
+ 1 << OMAP_AUTOEXTCLKMODE_SHIFT,
+ OMAP3430_GR_MOD,
+ OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+ /* setup wakup source */
+ omap2_prm_write_mod_reg(OMAP3430_EN_IO_MASK | OMAP3430_EN_GPIO1_MASK |
+ OMAP3430_EN_GPT1_MASK | OMAP3430_EN_GPT12_MASK,
+ WKUP_MOD, PM_WKEN);
+ /* No need to write EN_IO, that is always enabled */
+ omap2_prm_write_mod_reg(OMAP3430_GRPSEL_GPIO1_MASK |
+ OMAP3430_GRPSEL_GPT1_MASK |
+ OMAP3430_GRPSEL_GPT12_MASK,
+ WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
+
+ /* Enable PM_WKEN to support DSS LPR */
+ omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
+ OMAP3430_DSS_MOD, PM_WKEN);
+
+ if (has_uart4) {
+ en_uart4_mask = OMAP3630_EN_UART4_MASK;
+ grpsel_uart4_mask = OMAP3630_GRPSEL_UART4_MASK;
+ }
+
+ /* Enable wakeups in PER */
+ omap2_prm_write_mod_reg(en_uart4_mask |
+ OMAP3430_EN_GPIO2_MASK |
+ OMAP3430_EN_GPIO3_MASK |
+ OMAP3430_EN_GPIO4_MASK |
+ OMAP3430_EN_GPIO5_MASK |
+ OMAP3430_EN_GPIO6_MASK |
+ OMAP3430_EN_UART3_MASK |
+ OMAP3430_EN_MCBSP2_MASK |
+ OMAP3430_EN_MCBSP3_MASK |
+ OMAP3430_EN_MCBSP4_MASK,
+ OMAP3430_PER_MOD, PM_WKEN);
+
+ /* and allow them to wake up MPU */
+ omap2_prm_write_mod_reg(grpsel_uart4_mask |
+ OMAP3430_GRPSEL_GPIO2_MASK |
+ OMAP3430_GRPSEL_GPIO3_MASK |
+ OMAP3430_GRPSEL_GPIO4_MASK |
+ OMAP3430_GRPSEL_GPIO5_MASK |
+ OMAP3430_GRPSEL_GPIO6_MASK |
+ OMAP3430_GRPSEL_UART3_MASK |
+ OMAP3430_GRPSEL_MCBSP2_MASK |
+ OMAP3430_GRPSEL_MCBSP3_MASK |
+ OMAP3430_GRPSEL_MCBSP4_MASK,
+ OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
+
+ /* Don't attach IVA interrupts */
+ if (has_iva) {
+ omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+ omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+ omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+ omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
+ OMAP3430_PM_IVAGRPSEL);
+ }
+
+ /* Clear any pending 'reset' flags */
+ omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
+ omap2_prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD,
+ OMAP2_RM_RSTST);
+
+ /* Clear any pending PRCM interrupts */
+ omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
+ /* We need to idle iva2_pwrdm even on am3703 with no iva2. */
+ omap3xxx_prm_iva_idle();
+
+ omap3_prm_reset_modem();
+}
+
+/**
* omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
*
* Clear any previously-latched I/O wakeup events and ensure that the
@@ -276,6 +439,76 @@ static u32 omap3xxx_prm_read_reset_sources(void)
return r;
}
+/**
+ * omap3xxx_prm_iva_idle - ensure IVA is in idle so it can be put into retention
+ *
+ * In cases where IVA2 is activated by bootcode, it may prevent
+ * full-chip retention or off-mode because it is not idle. This
+ * function forces the IVA2 into idle state so it can go
+ * into retention/off and thus allow full-chip retention/off.
+ */
+void omap3xxx_prm_iva_idle(void)
+{
+ /* ensure IVA2 clock is disabled */
+ omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+ /* if no clock activity, nothing else to do */
+ if (!(omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) &
+ OMAP3430_CLKACTIVITY_IVA2_MASK))
+ return;
+
+ /* Reset IVA2 */
+ omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+ OMAP3430_RST2_IVA2_MASK |
+ OMAP3430_RST3_IVA2_MASK,
+ OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+
+ /* Enable IVA2 clock */
+ omap2_cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_MASK,
+ OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+ /* Un-reset IVA2 */
+ omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+
+ /* Disable IVA2 clock */
+ omap2_cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
+
+ /* Reset IVA2 */
+ omap2_prm_write_mod_reg(OMAP3430_RST1_IVA2_MASK |
+ OMAP3430_RST2_IVA2_MASK |
+ OMAP3430_RST3_IVA2_MASK,
+ OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
+}
+
+/**
+ * omap3xxx_prm_clear_global_cold_reset - checks the global cold reset status
+ * and clears it if asserted
+ *
+ * Checks if cold-reset has occurred and clears the status bit if yes. Returns
+ * 1 if cold-reset has occurred, 0 otherwise.
+ */
+int omap3xxx_prm_clear_global_cold_reset(void)
+{
+ if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
+ OMAP3430_GLOBAL_COLD_RST_MASK) {
+ omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
+ OMAP3430_GR_MOD,
+ OMAP3_PRM_RSTST_OFFSET);
+ return 1;
+ }
+
+ return 0;
+}
+
+void omap3_prm_save_scratchpad_contents(u32 *ptr)
+{
+ *ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+ OMAP3_PRM_CLKSRC_CTRL_OFFSET);
+
+ *ptr++ = omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
+ OMAP3_PRM_CLKSEL_OFFSET);
+}
+
/* Powerdomain low-level functions */
static int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 1dacfc5b1959..bc37d42a8704 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -162,6 +162,12 @@ extern void omap3xxx_prm_dpll3_reset(void);
extern int __init omap3xxx_prm_init(void);
extern u32 omap3xxx_prm_get_reset_sources(void);
+int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
+void omap3xxx_prm_iva_idle(void);
+void omap3_prm_reset_modem(void);
+int omap3xxx_prm_clear_global_cold_reset(void);
+void omap3_prm_save_scratchpad_contents(u32 *ptr);
+void omap3_prm_init_pm(bool has_uart4, bool has_iva);
#endif /* __ASSEMBLER */
diff --git a/arch/arm/mach-omap2/prm7xx.h b/arch/arm/mach-omap2/prm7xx.h
index d92a8404edc7..4bb50fbf29be 100644
--- a/arch/arm/mach-omap2/prm7xx.h
+++ b/arch/arm/mach-omap2/prm7xx.h
@@ -374,6 +374,10 @@
#define DRA7XX_RM_L3INIT_IEEE1500_2_OCP_CONTEXT_OFFSET 0x007c
#define DRA7XX_PM_L3INIT_SATA_WKDEP_OFFSET 0x0088
#define DRA7XX_RM_L3INIT_SATA_CONTEXT_OFFSET 0x008c
+#define DRA7XX_PM_L3INIT_PCIESS1_WKDEP_OFFSET 0x00b0
+#define DRA7XX_RM_L3INIT_PCIESS1_CONTEXT_OFFSET 0x00b4
+#define DRA7XX_PM_L3INIT_PCIESS2_WKDEP_OFFSET 0x00b8
+#define DRA7XX_RM_L3INIT_PCIESS2_CONTEXT_OFFSET 0x00bc
#define DRA7XX_RM_GMAC_GMAC_CONTEXT_OFFSET 0x00d4
#define DRA7XX_RM_L3INIT_OCP2SCP1_CONTEXT_OFFSET 0x00e4
#define DRA7XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET 0x00ec
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 25e8b8232115..76ca320f007c 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -472,6 +472,8 @@ static struct of_device_id omap_prcm_dt_match_table[] = {
{ .compatible = "ti,am3-scrm" },
{ .compatible = "ti,am4-prcm" },
{ .compatible = "ti,am4-scrm" },
+ { .compatible = "ti,omap2-prcm" },
+ { .compatible = "ti,omap2-scrm" },
{ .compatible = "ti,omap3-prm" },
{ .compatible = "ti,omap3-cm" },
{ .compatible = "ti,omap3-scrm" },
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index 9086ce03ae12..b84a0122d823 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -10,6 +10,7 @@
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/smp_scu.h>
#include <asm/memory.h>
#include <asm/hardware/cache-l2x0.h>
@@ -334,7 +335,7 @@ ENDPROC(omap4_cpu_resume)
#ifndef CONFIG_OMAP4_ERRATA_I688
ENTRY(omap_bus_sync)
- mov pc, lr
+ ret lr
ENDPROC(omap_bus_sync)
#endif
diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S
index 680a7c56cc3e..2c88ff2d0236 100644
--- a/arch/arm/mach-omap2/sram242x.S
+++ b/arch/arm/mach-omap2/sram242x.S
@@ -101,7 +101,7 @@ i_dll_wait:
i_dll_delay:
subs r4, r4, #0x1
bne i_dll_delay
- mov pc, lr
+ ret lr
/*
* shift up or down voltage, use R9 as input to tell level.
@@ -125,7 +125,7 @@ volt_delay:
ldr r7, [r3] @ get timer value
cmp r5, r7 @ time up?
bhi volt_delay @ not yet->branch
- mov pc, lr @ back to caller.
+ ret lr @ back to caller.
omap242x_sdi_cm_clksel2_pll:
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
@@ -220,7 +220,7 @@ volt_delay_c:
ldr r7, [r10] @ get timer value
cmp r8, r7 @ time up?
bhi volt_delay_c @ not yet->branch
- mov pc, lr @ back to caller
+ ret lr @ back to caller
omap242x_srs_cm_clksel2_pll:
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S
index a1e9edd673f4..d5deb9761fc7 100644
--- a/arch/arm/mach-omap2/sram243x.S
+++ b/arch/arm/mach-omap2/sram243x.S
@@ -101,7 +101,7 @@ i_dll_wait:
i_dll_delay:
subs r4, r4, #0x1
bne i_dll_delay
- mov pc, lr
+ ret lr
/*
* shift up or down voltage, use R9 as input to tell level.
@@ -125,7 +125,7 @@ volt_delay:
ldr r7, [r3] @ get timer value
cmp r5, r7 @ time up?
bhi volt_delay @ not yet->branch
- mov pc, lr @ back to caller.
+ ret lr @ back to caller.
omap243x_sdi_cm_clksel2_pll:
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
@@ -220,7 +220,7 @@ volt_delay_c:
ldr r7, [r10] @ get timer value
cmp r8, r7 @ time up?
bhi volt_delay_c @ not yet->branch
- mov pc, lr @ back to caller
+ ret lr @ back to caller
omap243x_srs_cm_clksel2_pll:
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index e832bc7b8e2d..8333400898fb 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -95,7 +95,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
dev_t.t_avdp_w = t_scsnh_advnh;
dev_t.cyc_aavdh_we = 3;
dev_t.cyc_wpl = 6;
- dev_t.t_ce_rdyz = 7000;
gpmc_calc_timings(&t, &tusb_sync, &dev_t);
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 648867a8caa8..2fe1824c6dcb 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -4,7 +4,7 @@
# Common support (must be linked before board specific support)
obj-y += clock.o devices.o generic.o irq.o \
- time.o reset.o
+ reset.o
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
# Generic drivers that other drivers may depend upon
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 43596e0ed051..d897292712eb 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -90,7 +90,7 @@ int __init parse_balloon3_features(char *arg)
if (!arg)
return 0;
- return strict_strtoul(arg, 0, &balloon3_features_present);
+ return kstrtoul(arg, 0, &balloon3_features_present);
}
early_param("balloon3_features", parse_balloon3_features);
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 91dd1c7cdbcd..06022b235730 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -514,7 +514,7 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = {
.gpio_pullup = CORGI_GPIO_USB_PULLUP,
};
-#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MASTER)
+#if IS_ENABLED(CONFIG_SPI_PXA2XX)
static struct pxa2xx_spi_master corgi_spi_info = {
.num_chipselect = 3,
};
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 42254175fcf4..630fa916bbc6 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -25,11 +25,13 @@
#include <asm/mach/map.h>
#include <asm/mach-types.h>
+#include <mach/irqs.h>
#include <mach/reset.h>
#include <mach/smemc.h>
#include <mach/pxa3xx-regs.h>
#include "generic.h"
+#include <clocksource/pxa.h>
void clear_reset_status(unsigned int mask)
{
@@ -57,6 +59,15 @@ unsigned long get_clock_tick_rate(void)
EXPORT_SYMBOL(get_clock_tick_rate);
/*
+ * For non device-tree builds, keep legacy timer init
+ */
+void pxa_timer_init(void)
+{
+ pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
+ get_clock_tick_rate());
+}
+
+/*
* Get the clock frequency as reflected by CCCR and the turbo flag.
* We assume these values have been applied via a fcs.
* If info is not 0 we also display the current settings.
@@ -79,19 +90,15 @@ EXPORT_SYMBOL(get_clk_frequency_khz);
*/
static struct map_desc common_io_desc[] __initdata = {
{ /* Devs */
- .virtual = 0xf2000000,
- .pfn = __phys_to_pfn(0x40000000),
- .length = 0x02000000,
- .type = MT_DEVICE
- }, { /* UNCACHED_PHYS_0 */
- .virtual = 0xff000000,
- .pfn = __phys_to_pfn(0x00000000),
- .length = 0x00100000,
+ .virtual = (unsigned long)PERIPH_VIRT,
+ .pfn = __phys_to_pfn(PERIPH_PHYS),
+ .length = PERIPH_SIZE,
.type = MT_DEVICE
}
};
void __init pxa_map_io(void)
{
+ debug_ll_io_init();
iotable_init(ARRAY_AND_SIZE(common_io_desc));
}
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index ccb06e485520..8d63c211b22f 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -19,8 +19,8 @@
* Workarounds for at least 2 errata so far require this.
* The mapping is set in mach-pxa/generic.c.
*/
-#define UNCACHED_PHYS_0 0xff000000
-#define UNCACHED_ADDR UNCACHED_PHYS_0
+#define UNCACHED_PHYS_0 0xfe000000
+#define UNCACHED_PHYS_0_SIZE 0x00100000
/*
* Intel PXA2xx internal register mapping:
diff --git a/arch/arm/mach-pxa/mioa701_bootresume.S b/arch/arm/mach-pxa/mioa701_bootresume.S
index 324d25a48c85..81591491ab94 100644
--- a/arch/arm/mach-pxa/mioa701_bootresume.S
+++ b/arch/arm/mach-pxa/mioa701_bootresume.S
@@ -29,7 +29,7 @@ ENTRY(mioa701_jumpaddr)
str r1, [r0] @ Early disable resume for next boot
ldr r0, mioa701_jumpaddr @ (Murphy's Law)
ldr r0, [r0]
- mov pc, r0
+ ret r0
2:
ENTRY(mioa701_bootstrap_lg)
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index f2c28972084d..66e4a2b6316e 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -331,7 +331,12 @@ static struct map_desc pxa25x_io_desc[] __initdata = {
{ /* Mem Ctl */
.virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA2XX_SMEMC_BASE),
- .length = 0x00200000,
+ .length = SMEMC_SIZE,
+ .type = MT_DEVICE
+ }, { /* UNCACHED_PHYS_0 */
+ .virtual = UNCACHED_PHYS_0,
+ .pfn = __phys_to_pfn(0x00000000),
+ .length = UNCACHED_PHYS_0_SIZE,
.type = MT_DEVICE
},
};
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 301471a07a10..b040d7d14888 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -402,12 +402,12 @@ static struct map_desc pxa27x_io_desc[] __initdata = {
{ /* Mem Ctl */
.virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA2XX_SMEMC_BASE),
- .length = 0x00200000,
+ .length = SMEMC_SIZE,
.type = MT_DEVICE
- }, { /* IMem ctl */
- .virtual = 0xfe000000,
- .pfn = __phys_to_pfn(0x58000000),
- .length = 0x00100000,
+ }, { /* UNCACHED_PHYS_0 */
+ .virtual = UNCACHED_PHYS_0,
+ .pfn = __phys_to_pfn(0x00000000),
+ .length = UNCACHED_PHYS_0_SIZE,
.type = MT_DEVICE
},
};
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 87011f3de69d..593ccd35ca97 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -416,7 +416,7 @@ static struct map_desc pxa3xx_io_desc[] __initdata = {
{ /* Mem Ctl */
.virtual = (unsigned long)SMEMC_VIRT,
.pfn = __phys_to_pfn(PXA3XX_SMEMC_BASE),
- .length = 0x00200000,
+ .length = SMEMC_SIZE,
.type = MT_DEVICE
}
};
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 1e544be9905d..6c5b3ffd2cd3 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -157,7 +157,7 @@ pxa_cpu_do_suspend:
@ Do not reorder...
@ Intel PXA270 Specification Update notes problems performing
@ external accesses after SDRAM is put in self-refresh mode
- @ (see Errata 39 ...hangs when entering self-refresh mode)
+ @ (see Errata 38 ...hangs when entering self-refresh mode)
@ force address lines low by reading at physical address 0
ldr r3, [r2]
diff --git a/arch/arm/mach-pxa/standby.S b/arch/arm/mach-pxa/standby.S
index 29f5f5c180b7..eab1645bb4ad 100644
--- a/arch/arm/mach-pxa/standby.S
+++ b/arch/arm/mach-pxa/standby.S
@@ -29,7 +29,7 @@ ENTRY(pxa_cpu_standby)
.align 5
1: mcr p14, 0, r2, c7, c0, 0 @ put the system into Standby
str r1, [r0] @ make sure PSSR_PH/STS are clear
- mov pc, lr
+ ret lr
#endif
@@ -108,7 +108,7 @@ ENTRY(pm_enter_standby_start)
bic r0, r0, #0x20000000
str r0, [r1, #PXA3_DMCIER]
- mov pc, lr
+ ret lr
ENTRY(pm_enter_standby_end)
#endif
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
deleted file mode 100644
index fca174e3865d..000000000000
--- a/arch/arm/mach-pxa/time.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * arch/arm/mach-pxa/time.c
- *
- * PXA clocksource, clockevents, and OST interrupt handlers.
- * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
- *
- * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
- * by MontaVista Software, Inc. (Nico, your code rocks!)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/clockchips.h>
-#include <linux/sched_clock.h>
-
-#include <asm/div64.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <mach/regs-ost.h>
-#include <mach/irqs.h>
-
-/*
- * This is PXA's sched_clock implementation. This has a resolution
- * of at least 308 ns and a maximum value of 208 days.
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 582 seconds between successive
- * calls to sched_clock() which should always be the case in practice.
- */
-
-static u64 notrace pxa_read_sched_clock(void)
-{
- return readl_relaxed(OSCR);
-}
-
-
-#define MIN_OSCR_DELTA 16
-
-static irqreturn_t
-pxa_ost0_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *c = dev_id;
-
- /* Disarm the compare/match, signal the event. */
- writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
- writel_relaxed(OSSR_M0, OSSR);
- c->event_handler(c);
-
- return IRQ_HANDLED;
-}
-
-static int
-pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
-{
- unsigned long next, oscr;
-
- writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER);
- next = readl_relaxed(OSCR) + delta;
- writel_relaxed(next, OSMR0);
- oscr = readl_relaxed(OSCR);
-
- return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
-}
-
-static void
-pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
-{
- switch (mode) {
- case CLOCK_EVT_MODE_ONESHOT:
- writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
- writel_relaxed(OSSR_M0, OSSR);
- break;
-
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- /* initializing, released, or preparing for suspend */
- writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER);
- writel_relaxed(OSSR_M0, OSSR);
- break;
-
- case CLOCK_EVT_MODE_RESUME:
- case CLOCK_EVT_MODE_PERIODIC:
- break;
- }
-}
-
-#ifdef CONFIG_PM
-static unsigned long osmr[4], oier, oscr;
-
-static void pxa_timer_suspend(struct clock_event_device *cedev)
-{
- osmr[0] = readl_relaxed(OSMR0);
- osmr[1] = readl_relaxed(OSMR1);
- osmr[2] = readl_relaxed(OSMR2);
- osmr[3] = readl_relaxed(OSMR3);
- oier = readl_relaxed(OIER);
- oscr = readl_relaxed(OSCR);
-}
-
-static void pxa_timer_resume(struct clock_event_device *cedev)
-{
- /*
- * Ensure that we have at least MIN_OSCR_DELTA between match
- * register 0 and the OSCR, to guarantee that we will receive
- * the one-shot timer interrupt. We adjust OSMR0 in preference
- * to OSCR to guarantee that OSCR is monotonically incrementing.
- */
- if (osmr[0] - oscr < MIN_OSCR_DELTA)
- osmr[0] += MIN_OSCR_DELTA;
-
- writel_relaxed(osmr[0], OSMR0);
- writel_relaxed(osmr[1], OSMR1);
- writel_relaxed(osmr[2], OSMR2);
- writel_relaxed(osmr[3], OSMR3);
- writel_relaxed(oier, OIER);
- writel_relaxed(oscr, OSCR);
-}
-#else
-#define pxa_timer_suspend NULL
-#define pxa_timer_resume NULL
-#endif
-
-static struct clock_event_device ckevt_pxa_osmr0 = {
- .name = "osmr0",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .rating = 200,
- .set_next_event = pxa_osmr0_set_next_event,
- .set_mode = pxa_osmr0_set_mode,
- .suspend = pxa_timer_suspend,
- .resume = pxa_timer_resume,
-};
-
-static struct irqaction pxa_ost0_irq = {
- .name = "ost0",
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
- .handler = pxa_ost0_interrupt,
- .dev_id = &ckevt_pxa_osmr0,
-};
-
-void __init pxa_timer_init(void)
-{
- unsigned long clock_tick_rate = get_clock_tick_rate();
-
- writel_relaxed(0, OIER);
- writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
- sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
-
- ckevt_pxa_osmr0.cpumask = cpumask_of(0);
-
- setup_irq(IRQ_OST0, &pxa_ost0_irq);
-
- clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
- clocksource_mmio_readl_up);
- clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
- MIN_OSCR_DELTA * 2, 0x7fffffff);
-}
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 41f27f667ca8..de3b08073fe7 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -769,7 +769,7 @@ static unsigned long viper_tpm;
static int __init viper_tpm_setup(char *str)
{
- return strict_strtoul(str, 10, &viper_tpm) >= 0;
+ return kstrtoul(str, 10, &viper_tpm) >= 0;
}
__setup("tpm=", viper_tpm_setup);
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 8c1b39a0caa0..850e506926df 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/io.h>
#include <linux/smsc911x.h>
#include <linux/ata_platform.h>
@@ -48,7 +49,6 @@
#include <mach/irqs.h>
#include <asm/hardware/timer-sp.h>
-#include <plat/clcd.h>
#include <plat/sched_clock.h>
#include "core.h"
diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h
index db09170e3832..23e7a313f75d 100644
--- a/arch/arm/mach-realview/include/mach/memory.h
+++ b/arch/arm/mach-realview/include/mach/memory.h
@@ -20,15 +20,6 @@
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
-/*
- * Physical DRAM offset.
- */
-#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
-#define PLAT_PHYS_OFFSET UL(0x70000000)
-#else
-#define PLAT_PHYS_OFFSET UL(0x00000000)
-#endif
-
#ifdef CONFIG_SPARSEMEM
/*
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1caee6d548b8..d1686696ca41 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -2,9 +2,11 @@ config ARCH_ROCKCHIP
bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7
select PINCTRL
select PINCTRL_ROCKCHIP
+ select ARCH_HAS_RESET_CONTROLLER
select ARCH_REQUIRE_GPIOLIB
select ARM_GIC
select CACHE_L2X0
+ select HAVE_ARM_ARCH_TIMER
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select DW_APB_TIMER_OF
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 4377a1436a98..b29d8ead4cf2 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -1,2 +1,4 @@
+CFLAGS_platsmp.o := -march=armv7-a
+
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 910835d4ccf4..189684f55927 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -21,6 +21,7 @@
#include <linux/of_address.h>
#include <asm/cacheflush.h>
+#include <asm/cp15.h>
#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
#include <asm/mach/map.h>
@@ -178,8 +179,27 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
pmu_set_power_domain(0 + i, false);
}
+#ifdef CONFIG_HOTPLUG_CPU
+static int rockchip_cpu_kill(unsigned int cpu)
+{
+ pmu_set_power_domain(0 + cpu, false);
+ return 1;
+}
+
+static void rockchip_cpu_die(unsigned int cpu)
+{
+ v7_exit_coherency_flush(louis);
+ while(1)
+ cpu_do_idle();
+}
+#endif
+
static struct smp_operations rockchip_smp_ops __initdata = {
.smp_prepare_cpus = rockchip_smp_prepare_cpus,
.smp_boot_secondary = rockchip_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_kill = rockchip_cpu_kill,
+ .cpu_die = rockchip_cpu_die,
+#endif
};
CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 968cc348e624..8ab9e0e7ff04 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -29,6 +29,7 @@ static const char * const rockchip_board_dt_compat[] = {
"rockchip,rk3066a",
"rockchip,rk3066b",
"rockchip,rk3188",
+ "rockchip,rk3288",
NULL,
};
diff --git a/arch/arm/mach-rpc/include/mach/memory.h b/arch/arm/mach-rpc/include/mach/memory.h
index 18a221093bf5..b7e49571417d 100644
--- a/arch/arm/mach-rpc/include/mach/memory.h
+++ b/arch/arm/mach-rpc/include/mach/memory.h
@@ -19,11 +19,6 @@
#define __ASM_ARCH_MEMORY_H
/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x10000000)
-
-/*
* Cache flushing area - ROM
*/
#define FLUSH_BASE_PHYS 0x00000000
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index c0763b837745..44fa95df9262 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -49,9 +49,7 @@
#include <plat/cpu.h>
#include <plat/devs.h>
-#include <plat/clock.h>
#include <plat/cpu-freq.h>
-#include <plat/pll.h>
#include <plat/pwm-core.h>
#include <plat/watchdog-reset.h>
diff --git a/arch/arm/mach-s3c24xx/iotiming-s3c2412.c b/arch/arm/mach-s3c24xx/iotiming-s3c2412.c
index bd064c05c473..28b13951de87 100644
--- a/arch/arm/mach-s3c24xx/iotiming-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/iotiming-s3c2412.c
@@ -29,7 +29,6 @@
#include <plat/cpu.h>
#include <plat/cpu-freq-core.h>
-#include <plat/clock.h>
#include <mach/s3c2412.h>
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index fbf5487ae5d1..c9a99bbad545 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -60,7 +60,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/gpio-cfg.h>
-#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/samsung-time.h>
@@ -73,6 +72,10 @@
#define H1940_LATCH_BIT(x) (1 << ((x) + 16 - S3C_GPIO_END))
+#define S3C24XX_PLL_MDIV_SHIFT (12)
+#define S3C24XX_PLL_PDIV_SHIFT (4)
+#define S3C24XX_PLL_SDIV_SHIFT (0)
+
static struct map_desc h1940_iodesc[] __initdata = {
[0] = {
.virtual = (unsigned long)H1940_LATCH,
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index e81ea82c55f9..7804d3c6991b 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -48,7 +48,6 @@
#include <linux/mtd/partitions.h>
#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/pm.h>
@@ -243,7 +242,7 @@ static int __init jive_mtdset(char *options)
if (options == NULL || options[0] == '\0')
return 0;
- if (strict_strtoul(options, 10, &set)) {
+ if (kstrtoul(options, 10, &set)) {
printk(KERN_ERR "failed to parse mtdset=%s\n", options);
return 0;
}
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index fb3b80e44595..10726bf84920 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -43,7 +43,6 @@
#include <mach/gpio-samsung.h>
#include <mach/fb.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index fa6f30d23601..24189e8e8560 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -44,7 +44,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index ef5d5ea33182..0ed77614dcfe 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -38,7 +38,6 @@
#include <mach/fb.h>
#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index 9104c2be36c9..9d4f64750698 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -42,7 +42,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index 7eab88829883..5ffe828cd659 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -41,8 +41,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/watchdog-reset.h>
@@ -83,10 +81,6 @@ void __init s3c2410_map_io(void)
iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
}
-void __init_or_cpufreq s3c2410_setup_clocks(void)
-{
-}
-
struct bus_type s3c2410_subsys = {
.name = "s3c2410-core",
.dev_name = "s3c2410-core",
diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c
index d49f52fbc842..569f3f5a6c71 100644
--- a/arch/arm/mach-s3c24xx/s3c2412.c
+++ b/arch/arm/mach-s3c24xx/s3c2412.c
@@ -37,12 +37,10 @@
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
-#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/cpu-freq.h>
#include <plat/devs.h>
#include <plat/nand-core.h>
-#include <plat/pll.h>
#include <plat/pm.h>
#include <plat/regs-spi.h>
@@ -171,10 +169,6 @@ void __init s3c2412_map_io(void)
iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
}
-void __init_or_cpufreq s3c2412_setup_clocks(void)
-{
-}
-
/* need to register the subsystem before we actually register the device, and
* we also need to ensure that it has been initialised before any of the
* drivers even try to use it (even if not on an s3c2412 based system)
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c
index fb9da2b603a2..7b043349f1c8 100644
--- a/arch/arm/mach-s3c24xx/s3c2442.c
+++ b/arch/arm/mach-s3c24xx/s3c2442.c
@@ -43,7 +43,6 @@
#include <mach/regs-clock.h>
-#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/pm.h>
diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c
index 4a64bcc9eb51..d1c3e65785a1 100644
--- a/arch/arm/mach-s3c24xx/s3c244x.c
+++ b/arch/arm/mach-s3c24xx/s3c244x.c
@@ -38,11 +38,9 @@
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/pm.h>
-#include <plat/pll.h>
#include <plat/nand-core.h>
#include <plat/watchdog-reset.h>
@@ -78,10 +76,6 @@ void __init s3c244x_map_io(void)
s3c2410_device_dclk.name = "s3c2440-dclk";
}
-void __init_or_cpufreq s3c244x_setup_clocks(void)
-{
-}
-
/* Since the S3C2442 and S3C2440 share items, put both subsystems here */
struct bus_type s3c2440_subsys = {
diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2410.S b/arch/arm/mach-s3c24xx/sleep-s3c2410.S
index c9b91223697c..875ba8911127 100644
--- a/arch/arm/mach-s3c24xx/sleep-s3c2410.S
+++ b/arch/arm/mach-s3c24xx/sleep-s3c2410.S
@@ -66,4 +66,4 @@ s3c2410_do_sleep:
streq r8, [r5] @ SDRAM power-down config
streq r9, [r6] @ CPU sleep
1: beq 1b
- mov pc, r14
+ ret lr
diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2412.S b/arch/arm/mach-s3c24xx/sleep-s3c2412.S
index 5adaceb7da13..6bf5b4d8743c 100644
--- a/arch/arm/mach-s3c24xx/sleep-s3c2412.S
+++ b/arch/arm/mach-s3c24xx/sleep-s3c2412.S
@@ -65,4 +65,4 @@ s3c2412_sleep_enter1:
strne r9, [r3]
bne s3c2412_sleep_enter1
- mov pc, r14
+ ret lr
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 55eb6a69655b..60576dfbea8d 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -45,7 +45,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <mach/regs-gpio.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 4b0199fff9f5..fe116334afda 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -58,7 +58,6 @@
#include <linux/platform_data/spi-s3c64xx.h>
#include <plat/keypad.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/adc.h>
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 72cee08c8bf5..19e8feb908fd 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -39,7 +39,6 @@
#include <plat/fb.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 67f06a9ae656..4bae7dc49eea 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -40,7 +40,6 @@
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/fb.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/samsung-time.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 78dd6f73c072..b3d13537a7f0 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -28,7 +28,6 @@
#include <mach/regs-gpio.h>
#include <mach/gpio-samsung.h>
-#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <linux/platform_data/i2c-s3c2410.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index c85d1cbe769f..910749768340 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -30,7 +30,6 @@
#include <mach/hardware.h>
#include <mach/map.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <linux/platform_data/i2c-s3c2410.h>
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index c6a8b2ab0240..1dc86d76b530 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -63,7 +63,6 @@
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
#include <plat/adc.h>
diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c
index 8c42807bf579..1ce48c54cd9c 100644
--- a/arch/arm/mach-s3c64xx/s3c6400.c
+++ b/arch/arm/mach-s3c64xx/s3c6400.c
@@ -39,7 +39,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
-#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/iic-core.h>
#include <plat/onenand-core.h>
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
index 5be3f09bac92..b2a7930548d9 100644
--- a/arch/arm/mach-s3c64xx/s3c6410.c
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -40,7 +40,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
-#include <plat/clock.h>
#include <plat/sdhci.h>
#include <plat/ata-core.h>
#include <plat/adc-core.h>
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
deleted file mode 100644
index 26003e23796d..000000000000
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ /dev/null
@@ -1,102 +0,0 @@
-# arch/arm/mach-s5p64x0/Kconfig
-#
-# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-# http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-if ARCH_S5P64X0
-
-config CPU_S5P6440
- bool
- select ARM_AMBA
- select PL330_DMA if DMADEVICES
- select S5P_SLEEP if PM
- select SAMSUNG_WAKEMASK if PM
- help
- Enable S5P6440 CPU support
-
-config CPU_S5P6450
- bool
- select ARM_AMBA
- select PL330_DMA if DMADEVICES
- select S5P_SLEEP if PM
- select SAMSUNG_WAKEMASK if PM
- help
- Enable S5P6450 CPU support
-
-config S5P64X0_SETUP_FB_24BPP
- bool
- help
- Common setup code for S5P64X0 based boards with a LCD display
- through RGB interface.
-
-config S5P64X0_SETUP_I2C1
- bool
- help
- Common setup code for i2c bus 1.
-
-config S5P64X0_SETUP_SPI
- bool
- help
- Common setup code for SPI GPIO configurations
-
-config S5P64X0_SETUP_SDHCI_GPIO
- bool
- help
- Common setup code for SDHCI gpio.
-
-# machine support
-
-config MACH_SMDK6440
- bool "SMDK6440"
- select CPU_S5P6440
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_I2C1
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S5P64X0_SETUP_FB_24BPP
- select S5P64X0_SETUP_I2C1
- select S5P64X0_SETUP_SDHCI_GPIO
- select SAMSUNG_DEV_ADC
- select SAMSUNG_DEV_BACKLIGHT
- select SAMSUNG_DEV_PWM
- select SAMSUNG_DEV_TS
- help
- Machine support for the Samsung SMDK6440
-
-config MACH_SMDK6450
- bool "SMDK6450"
- select CPU_S5P6450
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_I2C1
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S5P64X0_SETUP_FB_24BPP
- select S5P64X0_SETUP_I2C1
- select S5P64X0_SETUP_SDHCI_GPIO
- select SAMSUNG_DEV_ADC
- select SAMSUNG_DEV_BACKLIGHT
- select SAMSUNG_DEV_PWM
- select SAMSUNG_DEV_TS
- help
- Machine support for the Samsung SMDK6450
-
-menu "Use 8-bit SDHCI bus width"
-
-config S5P64X0_SD_CH1_8BIT
- bool "SDHCI Channel 1 (Slot 1)"
- depends on MACH_SMDK6450 || MACH_SMDK6440
- help
- Support SDHCI Channel 1 8-bit bus.
- If selected, Channel 2 is disabled.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile
deleted file mode 100644
index 12bb951187a4..000000000000
--- a/arch/arm/mach-s5p64x0/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-# arch/arm/mach-s5p64x0/Makefile
-#
-# Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
-# http://www.samsung.com
-#
-# Licensed under GPLv2
-
-obj-y :=
-obj-m :=
-obj-n :=
-obj- :=
-
-# Core
-
-obj-y += common.o clock.o
-obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o
-obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o
-
-obj-$(CONFIG_PM) += pm.o irq-pm.o
-
-obj-y += dma.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o
-obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o
-
-# device support
-
-obj-y += dev-audio.o
-
-obj-y += setup-i2c0.o
-obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o
-obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP) += setup-fb-24bpp.o
-obj-$(CONFIG_S5P64X0_SETUP_SPI) += setup-spi.o
-obj-$(CONFIG_S5P64X0_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
diff --git a/arch/arm/mach-s5p64x0/Makefile.boot b/arch/arm/mach-s5p64x0/Makefile.boot
deleted file mode 100644
index 79ece4055b02..000000000000
--- a/arch/arm/mach-s5p64x0/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y += 0x20008000
-params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
deleted file mode 100644
index ae34a1d5e10a..000000000000
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock-s5p6440.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P6440 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "clock.h"
-#include "common.h"
-
-static u32 epll_div[][5] = {
- { 36000000, 0, 48, 1, 4 },
- { 48000000, 0, 32, 1, 3 },
- { 60000000, 0, 40, 1, 3 },
- { 72000000, 0, 48, 1, 3 },
- { 84000000, 0, 28, 1, 2 },
- { 96000000, 0, 32, 1, 2 },
- { 32768000, 45264, 43, 1, 4 },
- { 45158000, 6903, 30, 1, 3 },
- { 49152000, 50332, 32, 1, 3 },
- { 67738000, 10398, 45, 1, 3 },
- { 73728000, 9961, 49, 1, 3 }
-};
-
-static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
-
- if (clk->rate == rate) /* Return if nothing changed */
- return 0;
-
- epll_con = __raw_readl(S5P64X0_EPLL_CON);
- epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
-
- epll_con_k &= ~(PLL90XX_KDIV_MASK);
- epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
- epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
- (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
- (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
- break;
- }
- }
-
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
- return -EINVAL;
- }
-
- __raw_writel(epll_con, S5P64X0_EPLL_CON);
- __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
-
- printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
- clk->rate, rate);
-
- clk->rate = rate;
-
- return 0;
-}
-
-static struct clk_ops s5p6440_epll_ops = {
- .get_rate = s5p_epll_get_rate,
- .set_rate = s5p6440_epll_set_rate,
-};
-
-static struct clksrc_clk clk_hclk = {
- .clk = {
- .name = "clk_hclk",
- .parent = &clk_armclk.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
- .clk = {
- .name = "clk_pclk",
- .parent = &clk_hclk.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
-};
-static struct clksrc_clk clk_hclk_low = {
- .clk = {
- .name = "clk_hclk_low",
- },
- .sources = &clkset_hclk_low,
- .reg_src = { .reg = S5P64X0_SYS_OTHERS, .shift = 6, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
- .clk = {
- .name = "clk_pclk_low",
- .parent = &clk_hclk_low.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
- {
- .name = "nand",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_mem_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "post",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 5)
- }, {
- .name = "2d",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "dma",
- .devname = "dma-pl330",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.0",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.1",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 18),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.2",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 19),
- }, {
- .name = "otg",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 20)
- }, {
- .name = "irom",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 25),
- }, {
- .name = "lcd",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk1_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "hclk_fimgvg",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk1_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "tsi",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "watchdog",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "rtc",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "timers",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "pcm",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "adc",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "i2c",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "spi",
- .devname = "s5p64x0-spi.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "spi",
- .devname = "s5p64x0-spi.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 22),
- }, {
- .name = "gps",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 25),
- }, {
- .name = "dsim",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 28),
- }, {
- .name = "etm",
- .parent = &clk_pclk.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 29),
- }, {
- .name = "dmc0",
- .parent = &clk_pclk.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 30),
- }, {
- .name = "pclk_fimgvg",
- .parent = &clk_pclk.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 31),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.0",
- .parent = &clk_48m,
- .enable = s5p64x0_sclk_ctrl,
- .ctrlbit = (1 << 27),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.1",
- .parent = &clk_48m,
- .enable = s5p64x0_sclk_ctrl,
- .ctrlbit = (1 << 28),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.2",
- .parent = &clk_48m,
- .enable = s5p64x0_sclk_ctrl,
- .ctrlbit = (1 << 29),
- },
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
- {
- .name = "intc",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "mem",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.2",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.3",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "gpio",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 18),
- },
-};
-
-static struct clk clk_iis_cd_v40 = {
- .name = "iis_cdclk_v40",
-};
-
-static struct clk clk_pcm_cd = {
- .name = "pcm_cdclk",
-};
-
-static struct clk *clkset_group1_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_group1 = {
- .sources = clkset_group1_list,
- .nr_sources = ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_uart_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
- .sources = clkset_uart_list,
- .nr_sources = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_audio_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_fin_epll,
- &clk_iis_cd_v40,
- &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio = {
- .sources = clkset_audio_list,
- .nr_sources = ARRAY_SIZE(clkset_audio_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_post",
- .ctrlbit = (1 << 10),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_dispcon",
- .ctrlbit = (1 << 1),
- .enable = s5p64x0_sclk1_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimgvg",
- .ctrlbit = (1 << 2),
- .enable = s5p64x0_sclk1_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
- },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
- .ctrlbit = (1 << 24),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
- .ctrlbit = (1 << 25),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
- .ctrlbit = (1 << 26),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uclk = {
- .clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 5),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
-};
-
-static struct clk clk_i2s0 = {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 26),
-};
-
-static struct clksrc_clk clk_audio_bus2 = {
- .clk = {
- .name = "sclk_audio2",
- .devname = "samsung-i2s.0",
- .ctrlbit = (1 << 11),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_audio,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 0, .size = 3 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5p64x0-spi.0",
- .ctrlbit = (1 << 20),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5p64x0-spi.1",
- .ctrlbit = (1 << 21),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_mout_mpll,
- &clk_dout_mpll,
- &clk_armclk,
- &clk_hclk,
- &clk_pclk,
- &clk_hclk_low,
- &clk_pclk_low,
-};
-
-static struct clk dummy_apb_pclk = {
- .name = "apb_pclk",
- .id = -1,
-};
-
-static struct clk *clk_cdev[] = {
- &clk_i2s0,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
- &clk_sclk_uclk,
- &clk_sclk_spi0,
- &clk_sclk_spi1,
- &clk_sclk_mmc0,
- &clk_sclk_mmc1,
- &clk_sclk_mmc2,
- &clk_audio_bus2,
-};
-
-static struct clk_lookup s5p6440_clk_lookup[] = {
- CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
- CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
- CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
- CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
- CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus2.clk),
-};
-
-void __init_or_cpufreq s5p6440_setup_clocks(void)
-{
- struct clk *xtal_clk;
-
- unsigned long xtal;
- unsigned long fclk;
- unsigned long hclk;
- unsigned long hclk_low;
- unsigned long pclk;
- unsigned long pclk_low;
-
- unsigned long apll;
- unsigned long mpll;
- unsigned long epll;
- unsigned int ptr;
-
- /* Set S5P6440 functions for clk_fout_epll */
-
- clk_fout_epll.enable = s5p_epll_enable;
- clk_fout_epll.ops = &s5p6440_epll_ops;
-
- clk_48m.enable = s5p64x0_clk48m_ctrl;
-
- xtal_clk = clk_get(NULL, "ext_xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
- clk_put(xtal_clk);
-
- apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
- mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
- epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
- __raw_readl(S5P64X0_EPLL_CON_K));
-
- clk_fout_apll.rate = apll;
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
-
- printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
- " E=%ld.%ldMHz\n",
- print_mhz(apll), print_mhz(mpll), print_mhz(epll));
-
- fclk = clk_get_rate(&clk_armclk.clk);
- hclk = clk_get_rate(&clk_hclk.clk);
- pclk = clk_get_rate(&clk_pclk.clk);
- hclk_low = clk_get_rate(&clk_hclk_low.clk);
- pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
- printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
- " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
- print_mhz(hclk), print_mhz(hclk_low),
- print_mhz(pclk), print_mhz(pclk_low));
-
- clk_f.rate = fclk;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
- &clk_ext,
- &clk_iis_cd_v40,
- &clk_pcm_cd,
-};
-
-void __init s5p6440_register_clocks(void)
-{
- int ptr;
- unsigned int cnt;
-
- s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
- for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
- s3c_disable_clocks(clk_cdev[cnt], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
- for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
- s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- clkdev_add_table(s5p6440_clk_lookup, ARRAY_SIZE(s5p6440_clk_lookup));
-
- s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
deleted file mode 100644
index 0b3ca2ed53e9..000000000000
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock-s5p6450.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P6450 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "clock.h"
-#include "common.h"
-
-static struct clksrc_clk clk_mout_dpll = {
- .clk = {
- .name = "mout_dpll",
- },
- .sources = &clk_src_dpll,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 5, .size = 1 },
-};
-
-static u32 epll_div[][5] = {
- { 133000000, 27307, 55, 2, 2 },
- { 100000000, 43691, 41, 2, 2 },
- { 480000000, 0, 80, 2, 0 },
-};
-
-static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
-
- if (clk->rate == rate) /* Return if nothing changed */
- return 0;
-
- epll_con = __raw_readl(S5P64X0_EPLL_CON);
- epll_con_k = __raw_readl(S5P64X0_EPLL_CON_K);
-
- epll_con_k &= ~(PLL90XX_KDIV_MASK);
- epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
-
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
- epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
- (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
- (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
- break;
- }
- }
-
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
- return -EINVAL;
- }
-
- __raw_writel(epll_con, S5P64X0_EPLL_CON);
- __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K);
-
- printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
- clk->rate, rate);
-
- clk->rate = rate;
-
- return 0;
-}
-
-static struct clk_ops s5p6450_epll_ops = {
- .get_rate = s5p_epll_get_rate,
- .set_rate = s5p6450_epll_set_rate,
-};
-
-static struct clksrc_clk clk_dout_epll = {
- .clk = {
- .name = "dout_epll",
- .parent = &clk_mout_epll.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_mout_hclk_sel = {
- .clk = {
- .name = "mout_hclk_sel",
- },
- .sources = &clkset_hclk_low,
- .reg_src = { .reg = S5P64X0_OTHERS, .shift = 15, .size = 1 },
-};
-
-static struct clk *clkset_hclk_list[] = {
- &clk_mout_hclk_sel.clk,
- &clk_armclk.clk,
-};
-
-static struct clksrc_sources clkset_hclk = {
- .sources = clkset_hclk_list,
- .nr_sources = ARRAY_SIZE(clkset_hclk_list),
-};
-
-static struct clksrc_clk clk_hclk = {
- .clk = {
- .name = "clk_hclk",
- },
- .sources = &clkset_hclk,
- .reg_src = { .reg = S5P64X0_OTHERS, .shift = 14, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk = {
- .clk = {
- .name = "clk_pclk",
- .parent = &clk_hclk.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 12, .size = 4 },
-};
-static struct clksrc_clk clk_dout_pwm_ratio0 = {
- .clk = {
- .name = "clk_dout_pwm_ratio0",
- .parent = &clk_mout_hclk_sel.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_to_wdt_pwm = {
- .clk = {
- .name = "clk_pclk_to_wdt_pwm",
- .parent = &clk_dout_pwm_ratio0.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 20, .size = 4 },
-};
-
-static struct clksrc_clk clk_hclk_low = {
- .clk = {
- .name = "clk_hclk_low",
- },
- .sources = &clkset_hclk_low,
- .reg_src = { .reg = S5P64X0_OTHERS, .shift = 6, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_low = {
- .clk = {
- .name = "clk_pclk_low",
- .parent = &clk_hclk_low.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 12, .size = 4 },
-};
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
- {
- .name = "usbhost",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "dma",
- .devname = "dma-pl330",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.0",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.1",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 18),
- }, {
- .name = "hsmmc",
- .devname = "s3c-sdhci.2",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 19),
- }, {
- .name = "usbotg",
- .parent = &clk_hclk_low.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 20),
- }, {
- .name = "lcd",
- .parent = &clk_h,
- .enable = s5p64x0_hclk1_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "watchdog",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "rtc",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "adc",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "spi",
- .devname = "s5p64x0-spi.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "spi",
- .devname = "s5p64x0-spi.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 22),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 27),
- }, {
- .name = "dmc0",
- .parent = &clk_pclk.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 30),
- }
-};
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
- {
- .name = "intc",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "mem",
- .parent = &clk_hclk.clk,
- .enable = s5p64x0_hclk0_ctrl,
- .ctrlbit = (1 << 21),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.2",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.3",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "timers",
- .parent = &clk_pclk_to_wdt_pwm.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "gpio",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 18),
- },
-};
-
-static struct clk *clkset_uart_list[] = {
- &clk_dout_epll.clk,
- &clk_dout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
- .sources = clkset_uart_list,
- .nr_sources = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_mali_list[] = {
- &clk_mout_epll.clk,
- &clk_mout_apll.clk,
- &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_mali = {
- .sources = clkset_mali_list,
- .nr_sources = ARRAY_SIZE(clkset_mali_list),
-};
-
-static struct clk *clkset_group2_list[] = {
- &clk_dout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_ext_xtal_mux,
-};
-
-static struct clksrc_sources clkset_group2 = {
- .sources = clkset_group2_list,
- .nr_sources = ARRAY_SIZE(clkset_group2_list),
-};
-
-static struct clk *clkset_dispcon_list[] = {
- &clk_dout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_ext_xtal_mux,
- &clk_mout_dpll.clk,
-};
-
-static struct clksrc_sources clkset_dispcon = {
- .sources = clkset_dispcon_list,
- .nr_sources = ARRAY_SIZE(clkset_dispcon_list),
-};
-
-static struct clk *clkset_hsmmc44_list[] = {
- &clk_dout_epll.clk,
- &clk_dout_mpll.clk,
- &clk_ext_xtal_mux,
- &s5p_clk_27m,
- &clk_48m,
-};
-
-static struct clksrc_sources clkset_hsmmc44 = {
- .sources = clkset_hsmmc44_list,
- .nr_sources = ARRAY_SIZE(clkset_hsmmc44_list),
-};
-
-static struct clk *clkset_sclk_audio0_list[] = {
- [0] = &clk_dout_epll.clk,
- [1] = &clk_dout_mpll.clk,
- [2] = &clk_ext_xtal_mux,
- [3] = NULL,
- [4] = NULL,
-};
-
-static struct clksrc_sources clkset_sclk_audio0 = {
- .sources = clkset_sclk_audio0_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
- .clk = {
- .name = "audio-bus",
- .devname = "samsung-i2s.0",
- .enable = s5p64x0_sclk_ctrl,
- .ctrlbit = (1 << 8),
- .parent = &clk_dout_epll.clk,
- },
- .sources = &clkset_sclk_audio0,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 10, .size = 3 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_fimc",
- .ctrlbit = (1 << 10),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 26, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "aclk_mali",
- .ctrlbit = (1 << 2),
- .enable = s5p64x0_sclk1_ctrl,
- },
- .sources = &clkset_mali,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_2d",
- .ctrlbit = (1 << 12),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_mali,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 30, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_usi",
- .ctrlbit = (1 << 7),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 10, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_camif",
- .ctrlbit = (1 << 6),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 28, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_dispcon",
- .ctrlbit = (1 << 1),
- .enable = s5p64x0_sclk1_ctrl,
- },
- .sources = &clkset_dispcon,
- .reg_src = { .reg = S5P64X0_CLK_SRC1, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV3, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_hsmmc44",
- .ctrlbit = (1 << 30),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_hsmmc44,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 6, .size = 3 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 28, .size = 4 },
- },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
- .ctrlbit = (1 << 24),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
- .ctrlbit = (1 << 25),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
- .ctrlbit = (1 << 26),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uclk = {
- .clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 5),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5p64x0-spi.0",
- .ctrlbit = (1 << 20),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5p64x0-spi.1",
- .ctrlbit = (1 << 21),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-static struct clk clk_i2s0 = {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 26),
-};
-
-static struct clk clk_i2s1 = {
- .name = "iis",
- .devname = "samsung-i2s.1",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 15),
-};
-
-static struct clk clk_i2s2 = {
- .name = "iis",
- .devname = "samsung-i2s.2",
- .parent = &clk_pclk_low.clk,
- .enable = s5p64x0_pclk_ctrl,
- .ctrlbit = (1 << 16),
-};
-
-static struct clk *clk_cdev[] = {
- &clk_i2s0,
- &clk_i2s1,
- &clk_i2s2,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
- &clk_sclk_uclk,
- &clk_sclk_spi0,
- &clk_sclk_spi1,
- &clk_sclk_mmc0,
- &clk_sclk_mmc1,
- &clk_sclk_mmc2,
- &clk_sclk_audio0,
-};
-
-static struct clk_lookup s5p6450_clk_lookup[] = {
- CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
- CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
- CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
- CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
- CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_sclk_audio0.clk),
- CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
- CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_dout_epll,
- &clk_mout_mpll,
- &clk_dout_mpll,
- &clk_armclk,
- &clk_mout_hclk_sel,
- &clk_dout_pwm_ratio0,
- &clk_pclk_to_wdt_pwm,
- &clk_hclk,
- &clk_pclk,
- &clk_hclk_low,
- &clk_pclk_low,
-};
-
-static struct clk dummy_apb_pclk = {
- .name = "apb_pclk",
- .id = -1,
-};
-
-void __init_or_cpufreq s5p6450_setup_clocks(void)
-{
- struct clk *xtal_clk;
-
- unsigned long xtal;
- unsigned long fclk;
- unsigned long hclk;
- unsigned long hclk_low;
- unsigned long pclk;
- unsigned long pclk_low;
-
- unsigned long apll;
- unsigned long mpll;
- unsigned long epll;
- unsigned long dpll;
- unsigned int ptr;
-
- /* Set S5P6450 functions for clk_fout_epll */
-
- clk_fout_epll.enable = s5p_epll_enable;
- clk_fout_epll.ops = &s5p6450_epll_ops;
-
- clk_48m.enable = s5p64x0_clk48m_ctrl;
-
- xtal_clk = clk_get(NULL, "ext_xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
- clk_put(xtal_clk);
-
- apll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_APLL_CON), pll_4502);
- mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P64X0_MPLL_CON), pll_4502);
- epll = s5p_get_pll90xx(xtal, __raw_readl(S5P64X0_EPLL_CON),
- __raw_readl(S5P64X0_EPLL_CON_K));
- dpll = s5p_get_pll46xx(xtal, __raw_readl(S5P6450_DPLL_CON),
- __raw_readl(S5P6450_DPLL_CON_K), pll_4650c);
-
- clk_fout_apll.rate = apll;
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_fout_dpll.rate = dpll;
-
- printk(KERN_INFO "S5P6450: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
- " E=%ld.%ldMHz, D=%ld.%ldMHz\n",
- print_mhz(apll), print_mhz(mpll), print_mhz(epll),
- print_mhz(dpll));
-
- fclk = clk_get_rate(&clk_armclk.clk);
- hclk = clk_get_rate(&clk_hclk.clk);
- pclk = clk_get_rate(&clk_pclk.clk);
- hclk_low = clk_get_rate(&clk_hclk_low.clk);
- pclk_low = clk_get_rate(&clk_pclk_low.clk);
-
- printk(KERN_INFO "S5P6450: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
- " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
- print_mhz(hclk), print_mhz(hclk_low),
- print_mhz(pclk), print_mhz(pclk_low));
-
- clk_f.rate = fclk;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-void __init s5p6450_register_clocks(void)
-{
- int ptr;
- unsigned int cnt;
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
-
- s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
- for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
- s3c_disable_clocks(clk_cdev[cnt], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
- for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
- s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup));
-
- s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c
deleted file mode 100644
index 57e718957ef3..000000000000
--- a/arch/arm/mach-s5p64x0/clock.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-struct clksrc_clk clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- .id = -1,
- },
- .sources = &clk_src_apll,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-struct clksrc_clk clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- .id = -1,
- },
- .sources = &clk_src_mpll,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 1, .size = 1 },
-};
-
-struct clksrc_clk clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- .id = -1,
- },
- .sources = &clk_src_epll,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 2, .size = 1 },
-};
-
-enum perf_level {
- L0 = 532*1000,
- L1 = 266*1000,
- L2 = 133*1000,
-};
-
-static const u32 clock_table[][3] = {
- /*{ARM_CLK, DIVarm, DIVhclk}*/
- {L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
- {L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
- {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)},
-};
-
-static unsigned long s5p64x0_armclk_get_rate(struct clk *clk)
-{
- unsigned long rate = clk_get_rate(clk->parent);
- u32 clkdiv;
-
- /* divisor mask starts at bit0, so no need to shift */
- clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
-
- return rate / (clkdiv + 1);
-}
-
-static unsigned long s5p64x0_armclk_round_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 iter;
-
- for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
- if (rate > clock_table[iter][0])
- return clock_table[iter-1][0];
- }
-
- return clock_table[ARRAY_SIZE(clock_table) - 1][0];
-}
-
-static int s5p64x0_armclk_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 round_tmp;
- u32 iter;
- u32 clk_div0_tmp;
- u32 cur_rate = clk->ops->get_rate(clk);
- unsigned long flags;
-
- round_tmp = clk->ops->round_rate(clk, rate);
- if (round_tmp == cur_rate)
- return 0;
-
-
- for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
- if (round_tmp == clock_table[iter][0])
- break;
- }
-
- if (iter >= ARRAY_SIZE(clock_table))
- iter = ARRAY_SIZE(clock_table) - 1;
-
- local_irq_save(flags);
- if (cur_rate > round_tmp) {
- /* Frequency Down */
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
- clk_div0_tmp |= clock_table[iter][1];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
- ~(S5P64X0_CLKDIV0_HCLK_MASK);
- clk_div0_tmp |= clock_table[iter][2];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
-
- } else {
- /* Frequency Up */
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
- ~(S5P64X0_CLKDIV0_HCLK_MASK);
- clk_div0_tmp |= clock_table[iter][2];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
-
- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
- clk_div0_tmp |= clock_table[iter][1];
- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
- }
- local_irq_restore(flags);
-
- clk->rate = clock_table[iter][0];
-
- return 0;
-}
-
-static struct clk_ops s5p64x0_clkarm_ops = {
- .get_rate = s5p64x0_armclk_get_rate,
- .set_rate = s5p64x0_armclk_set_rate,
- .round_rate = s5p64x0_armclk_round_rate,
-};
-
-struct clksrc_clk clk_armclk = {
- .clk = {
- .name = "armclk",
- .id = 1,
- .parent = &clk_mout_apll.clk,
- .ops = &s5p64x0_clkarm_ops,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 0, .size = 4 },
-};
-
-struct clksrc_clk clk_dout_mpll = {
- .clk = {
- .name = "dout_mpll",
- .id = -1,
- .parent = &clk_mout_mpll.clk,
- },
- .reg_div = { .reg = S5P64X0_CLK_DIV0, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_hclk_low_list[] = {
- &clk_mout_apll.clk,
- &clk_mout_mpll.clk,
-};
-
-struct clksrc_sources clkset_hclk_low = {
- .sources = clkset_hclk_low_list,
- .nr_sources = ARRAY_SIZE(clkset_hclk_low_list),
-};
-
-int s5p64x0_pclk_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_PCLK, clk, enable);
-}
-
-int s5p64x0_hclk0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK0, clk, enable);
-}
-
-int s5p64x0_hclk1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_HCLK1, clk, enable);
-}
-
-int s5p64x0_sclk_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK0, clk, enable);
-}
-
-int s5p64x0_sclk1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_SCLK1, clk, enable);
-}
-
-int s5p64x0_mem_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P64X0_CLK_GATE_MEM0, clk, enable);
-}
-
-int s5p64x0_clk48m_ctrl(struct clk *clk, int enable)
-{
- unsigned long flags;
- u32 val;
-
- /* can't rely on clock lock, this register has other usages */
- local_irq_save(flags);
-
- val = __raw_readl(S5P64X0_OTHERS);
- if (enable)
- val |= S5P64X0_OTHERS_USB_SIG_MASK;
- else
- val &= ~S5P64X0_OTHERS_USB_SIG_MASK;
-
- __raw_writel(val, S5P64X0_OTHERS);
-
- local_irq_restore(flags);
-
- return 0;
-}
diff --git a/arch/arm/mach-s5p64x0/clock.h b/arch/arm/mach-s5p64x0/clock.h
deleted file mode 100644
index 28b8e3c6bd24..000000000000
--- a/arch/arm/mach-s5p64x0/clock.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Header file for s5p64x0 clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __MACH_S5P64X0_CLOCK_H
-#define __MACH_S5P64X0_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk clk_mout_apll;
-extern struct clksrc_clk clk_mout_mpll;
-extern struct clksrc_clk clk_mout_epll;
-
-extern int s5p64x0_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p64x0_epll_get_rate(struct clk *clk);
-
-extern struct clksrc_clk clk_armclk;
-extern struct clksrc_clk clk_dout_mpll;
-
-extern struct clksrc_sources clkset_hclk_low;
-
-extern int s5p64x0_pclk_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_hclk0_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_hclk1_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_sclk_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_sclk1_ctrl(struct clk *clk, int enable);
-extern int s5p64x0_mem_ctrl(struct clk *clk, int enable);
-
-extern int s5p64x0_clk48m_ctrl(struct clk *clk, int enable);
-
-#endif /* __MACH_S5P64X0_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c
deleted file mode 100644
index 9a43be002d78..000000000000
--- a/arch/arm/mach-s5p64x0/common.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Common Codes for S5P64X0 machines
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/reboot.h>
-
-#include <asm/irq.h>
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/pm.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/fb-core.h>
-#include <plat/spi-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/pwm-core.h>
-#include <plat/regs-irqtype.h>
-#include <plat/watchdog-reset.h>
-
-#include "common.h"
-
-static const char name_s5p6440[] = "S5P6440";
-static const char name_s5p6450[] = "S5P6450";
-
-static struct cpu_table cpu_ids[] __initdata = {
- {
- .idcode = S5P6440_CPU_ID,
- .idmask = S5P64XX_CPU_MASK,
- .map_io = s5p6440_map_io,
- .init_clocks = s5p6440_init_clocks,
- .init_uarts = s5p6440_init_uarts,
- .init = s5p64x0_init,
- .name = name_s5p6440,
- }, {
- .idcode = S5P6450_CPU_ID,
- .idmask = S5P64XX_CPU_MASK,
- .map_io = s5p6450_map_io,
- .init_clocks = s5p6450_init_clocks,
- .init_uarts = s5p6450_init_uarts,
- .init = s5p64x0_init,
- .name = name_s5p6450,
- },
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5p64x0_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S5P_VA_CHIPID,
- .pfn = __phys_to_pfn(S5P64X0_PA_CHIPID),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_SYS,
- .pfn = __phys_to_pfn(S5P64X0_PA_SYSCON),
- .length = SZ_64K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_TIMER,
- .pfn = __phys_to_pfn(S5P64X0_PA_TIMER),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_WATCHDOG,
- .pfn = __phys_to_pfn(S5P64X0_PA_WDT),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_SROMC,
- .pfn = __phys_to_pfn(S5P64X0_PA_SROMC),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_GPIO,
- .pfn = __phys_to_pfn(S5P64X0_PA_GPIO),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC0,
- .pfn = __phys_to_pfn(S5P64X0_PA_VIC0),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC1,
- .pfn = __phys_to_pfn(S5P64X0_PA_VIC1),
- .length = SZ_16K,
- .type = MT_DEVICE,
- },
-};
-
-static struct map_desc s5p6440_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S3C_VA_UART,
- .pfn = __phys_to_pfn(S5P6440_PA_UART(0)),
- .length = SZ_4K,
- .type = MT_DEVICE,
- },
-};
-
-static struct map_desc s5p6450_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S3C_VA_UART,
- .pfn = __phys_to_pfn(S5P6450_PA_UART(0)),
- .length = SZ_512K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_UART + SZ_512K,
- .pfn = __phys_to_pfn(S5P6450_PA_UART(5)),
- .length = SZ_4K,
- .type = MT_DEVICE,
- },
-};
-
-static void s5p64x0_idle(void)
-{
- unsigned long val;
-
- val = __raw_readl(S5P64X0_PWR_CFG);
- val &= ~(0x3 << 5);
- val |= (0x1 << 5);
- __raw_writel(val, S5P64X0_PWR_CFG);
-
- cpu_do_idle();
-}
-
-static struct samsung_pwm_variant s5p64x0_pwm_variant = {
- .bits = 32,
- .div_base = 0,
- .has_tint_cstat = true,
- .tclk_mask = 0,
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
- s5p64x0_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
- s5p64x0_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
- unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
- IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
- IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
- };
-
- samsung_pwm_clocksource_init(S3C_VA_TIMER,
- timer_irqs, &s5p64x0_pwm_variant);
-}
-
-/*
- * s5p64x0_map_io
- *
- * register the standard CPU IO areas
- */
-
-void __init s5p64x0_init_io(struct map_desc *mach_desc, int size)
-{
- /* initialize the io descriptors we need for initialization */
- iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
- if (mach_desc)
- iotable_init(mach_desc, size);
-
- /* detect cpu id and rev. */
- s5p_init_cpu(S5P64X0_SYS_ID);
-
- s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
- samsung_wdt_reset_init(S3C_VA_WATCHDOG);
-
- samsung_pwm_set_platdata(&s5p64x0_pwm_variant);
-}
-
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_map_io(void)
-{
- /* initialize any device information early */
- s3c_adc_setname("s3c64xx-adc");
- s3c_fb_setname("s5p64x0-fb");
- s3c64xx_spi_setname("s5p64x0-spi");
-
- s5p64x0_default_sdhci0();
- s5p64x0_default_sdhci1();
- s5p6440_default_sdhci2();
-
- iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc));
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_map_io(void)
-{
- /* initialize any device information early */
- s3c_adc_setname("s3c64xx-adc");
- s3c_fb_setname("s5p64x0-fb");
- s3c64xx_spi_setname("s5p64x0-spi");
-
- s5p64x0_default_sdhci0();
- s5p64x0_default_sdhci1();
- s5p6450_default_sdhci2();
-
- iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
-}
-#endif
-
-/*
- * s5p64x0_init_clocks
- *
- * register and setup the CPU clocks
- */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
- s5p6440_register_clocks();
- s5p6440_setup_clocks();
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
- s5p6450_register_clocks();
- s5p6450_setup_clocks();
-}
-#endif
-
-/*
- * s5p64x0_init_irq
- *
- * register the CPU interrupts
- */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_irq(void)
-{
- /* S5P6440 supports 2 VIC */
- u32 vic[2];
-
- /*
- * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
- * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
- */
- vic[0] = 0xff800ae7;
- vic[1] = 0xffbf23e5;
-
- s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_irq(void)
-{
- /* S5P6450 supports only 2 VIC */
- u32 vic[2];
-
- /*
- * VIC0 is missing IRQ_VIC0[(13-15), (21-22)]
- * VIC1 is missing IRQ VIC1[12, 14, 23]
- */
- vic[0] = 0xff9f1fff;
- vic[1] = 0xff7fafff;
-
- s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-#endif
-
-struct bus_type s5p64x0_subsys = {
- .name = "s5p64x0-core",
- .dev_name = "s5p64x0-core",
-};
-
-static struct device s5p64x0_dev = {
- .bus = &s5p64x0_subsys,
-};
-
-static int __init s5p64x0_core_init(void)
-{
- return subsys_system_register(&s5p64x0_subsys, NULL);
-}
-core_initcall(s5p64x0_core_init);
-
-int __init s5p64x0_init(void)
-{
- printk(KERN_INFO "S5P64X0(S5P6440/S5P6450): Initializing architecture\n");
-
- /* set idle function */
- arm_pm_idle = s5p64x0_idle;
-
- return device_register(&s5p64x0_dev);
-}
-
-/* uart registration process */
-#ifdef CONFIG_CPU_S5P6440
-void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- int uart;
-
- for (uart = 0; uart < no; uart++) {
- s5p_uart_resources[uart].resources->start = S5P6440_PA_UART(uart);
- s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
- }
-
- s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-#endif
-
-#define eint_offset(irq) ((irq) - IRQ_EINT(0))
-
-static int s5p64x0_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
- int offs = eint_offset(data->irq);
- int shift;
- u32 ctrl, mask;
- u32 newvalue = 0;
-
- if (offs > 15)
- return -EINVAL;
-
- switch (type) {
- case IRQ_TYPE_NONE:
- printk(KERN_WARNING "No edge setting!\n");
- break;
- case IRQ_TYPE_EDGE_RISING:
- newvalue = S3C2410_EXTINT_RISEEDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- newvalue = S3C2410_EXTINT_FALLEDGE;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- newvalue = S3C2410_EXTINT_BOTHEDGE;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- newvalue = S3C2410_EXTINT_LOWLEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- newvalue = S3C2410_EXTINT_HILEV;
- break;
- default:
- printk(KERN_ERR "No such irq type %d", type);
- return -EINVAL;
- }
-
- shift = (offs / 2) * 4;
- mask = 0x7 << shift;
-
- ctrl = __raw_readl(S5P64X0_EINT0CON0) & ~mask;
- ctrl |= newvalue << shift;
- __raw_writel(ctrl, S5P64X0_EINT0CON0);
-
- /* Configure the GPIO pin for 6450 or 6440 based on CPU ID */
- if (soc_is_s5p6450())
- s3c_gpio_cfgpin(S5P6450_GPN(offs), S3C_GPIO_SFN(2));
- else
- s3c_gpio_cfgpin(S5P6440_GPN(offs), S3C_GPIO_SFN(2));
-
- return 0;
-}
-
-/*
- * s5p64x0_irq_demux_eint
- *
- * This function demuxes the IRQ from the group0 external interrupts,
- * from IRQ_EINT(0) to IRQ_EINT(15). It is designed to be inlined into
- * the specific handlers s5p64x0_irq_demux_eintX_Y.
- */
-static inline void s5p64x0_irq_demux_eint(unsigned int start, unsigned int end)
-{
- u32 status = __raw_readl(S5P64X0_EINT0PEND);
- u32 mask = __raw_readl(S5P64X0_EINT0MASK);
- unsigned int irq;
-
- status &= ~mask;
- status >>= start;
- status &= (1 << (end - start + 1)) - 1;
-
- for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
- if (status & 1)
- generic_handle_irq(irq);
- status >>= 1;
- }
-}
-
-static void s5p64x0_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
- s5p64x0_irq_demux_eint(0, 3);
-}
-
-static void s5p64x0_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
-{
- s5p64x0_irq_demux_eint(4, 11);
-}
-
-static void s5p64x0_irq_demux_eint12_15(unsigned int irq,
- struct irq_desc *desc)
-{
- s5p64x0_irq_demux_eint(12, 15);
-}
-
-static int s5p64x0_alloc_gc(void)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- gc = irq_alloc_generic_chip("s5p64x0-eint", 1, S5P_IRQ_EINT_BASE,
- S5P_VA_GPIO, handle_level_irq);
- if (!gc) {
- printk(KERN_ERR "%s: irq_alloc_generic_chip for group 0"
- "external interrupts failed\n", __func__);
- return -EINVAL;
- }
-
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = s5p64x0_irq_eint_set_type;
- ct->chip.irq_set_wake = s3c_irqext_wake;
- ct->regs.ack = EINT0PEND_OFFSET;
- ct->regs.mask = EINT0MASK_OFFSET;
- irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
- return 0;
-}
-
-static int __init s5p64x0_init_irq_eint(void)
-{
- int ret = s5p64x0_alloc_gc();
- irq_set_chained_handler(IRQ_EINT0_3, s5p64x0_irq_demux_eint0_3);
- irq_set_chained_handler(IRQ_EINT4_11, s5p64x0_irq_demux_eint4_11);
- irq_set_chained_handler(IRQ_EINT12_15, s5p64x0_irq_demux_eint12_15);
-
- return ret;
-}
-arch_initcall(s5p64x0_init_irq_eint);
-
-void s5p64x0_restart(enum reboot_mode mode, const char *cmd)
-{
- if (mode != REBOOT_SOFT)
- samsung_wdt_reset();
-
- soft_restart(0);
-}
diff --git a/arch/arm/mach-s5p64x0/common.h b/arch/arm/mach-s5p64x0/common.h
deleted file mode 100644
index cbe7f3d731d0..000000000000
--- a/arch/arm/mach-s5p64x0/common.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Common Header for S5P64X0 machines
- *
- * 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 __ARCH_ARM_MACH_S5P64X0_COMMON_H
-#define __ARCH_ARM_MACH_S5P64X0_COMMON_H
-
-#include <linux/reboot.h>
-
-void s5p6440_init_irq(void);
-void s5p6450_init_irq(void);
-void s5p64x0_init_io(struct map_desc *mach_desc, int size);
-
-void s5p6440_register_clocks(void);
-void s5p6440_setup_clocks(void);
-
-void s5p6450_register_clocks(void);
-void s5p6450_setup_clocks(void);
-
-void s5p64x0_restart(enum reboot_mode mode, const char *cmd);
-extern int s5p64x0_init(void);
-
-#ifdef CONFIG_CPU_S5P6440
-
-extern void s5p6440_map_io(void);
-extern void s5p6440_init_clocks(int xtal);
-
-extern void s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6440_init_clocks NULL
-#define s5p6440_init_uarts NULL
-#define s5p6440_map_io NULL
-#endif
-
-#ifdef CONFIG_CPU_S5P6450
-
-extern void s5p6450_map_io(void);
-extern void s5p6450_init_clocks(int xtal);
-
-extern void s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#else
-#define s5p6450_init_clocks NULL
-#define s5p6450_init_uarts NULL
-#define s5p6450_map_io NULL
-#endif
-
-#endif /* __ARCH_ARM_MACH_S5P64X0_COMMON_H */
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
deleted file mode 100644
index 723d4773c323..000000000000
--- a/arch/arm/mach-s5p64x0/dev-audio.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5p6440_cfg_i2s(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5P6440_GPC(4), 2, S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin(S5P6440_GPC(7), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin_range(S5P6440_GPH(6), 4, S3C_GPIO_SFN(5));
- break;
- default:
- printk(KERN_ERR "Invalid Device %d\n", pdev->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s5p6440_i2s_pdata = {
- .cfg_gpio = s5p6440_cfg_i2s,
- .type = {
- .i2s = {
- .quirks = QUIRK_PRI_6CHAN,
- },
- },
-};
-
-static struct resource s5p64x0_i2s0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P64X0_PA_I2S, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
-};
-
-struct platform_device s5p6440_device_iis = {
- .name = "samsung-i2s",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p64x0_i2s0_resource),
- .resource = s5p64x0_i2s0_resource,
- .dev = {
- .platform_data = &s5p6440_i2s_pdata,
- },
-};
-
-static int s5p6450_cfg_i2s(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5));
- break;
- case 1:
- s3c_gpio_cfgpin(S5P6440_GPB(4), S3C_GPIO_SFN(5));
- s3c_gpio_cfgpin_range(S5P6450_GPC(0), 4, S3C_GPIO_SFN(5));
- break;
- case 2:
- s3c_gpio_cfgpin_range(S5P6450_GPK(0), 5, S3C_GPIO_SFN(5));
- break;
- default:
- printk(KERN_ERR "Invalid Device %d\n", pdev->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s5p6450_i2s0_pdata = {
- .cfg_gpio = s5p6450_cfg_i2s,
- .type = {
- .i2s = {
- .quirks = QUIRK_PRI_6CHAN,
- },
- },
-};
-
-struct platform_device s5p6450_device_iis0 = {
- .name = "samsung-i2s",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p64x0_i2s0_resource),
- .resource = s5p64x0_i2s0_resource,
- .dev = {
- .platform_data = &s5p6450_i2s0_pdata,
- },
-};
-
-static struct s3c_audio_pdata s5p6450_i2s_pdata = {
- .cfg_gpio = s5p6450_cfg_i2s,
-};
-
-static struct resource s5p6450_i2s1_resource[] = {
- [0] = DEFINE_RES_MEM(S5P6450_PA_I2S1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5p6450_device_iis1 = {
- .name = "samsung-i2s",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5p6450_i2s1_resource),
- .resource = s5p6450_i2s1_resource,
- .dev = {
- .platform_data = &s5p6450_i2s_pdata,
- },
-};
-
-static struct resource s5p6450_i2s2_resource[] = {
- [0] = DEFINE_RES_MEM(S5P6450_PA_I2S2, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5p6450_device_iis2 = {
- .name = "samsung-i2s",
- .id = 2,
- .num_resources = ARRAY_SIZE(s5p6450_i2s2_resource),
- .resource = s5p6450_i2s2_resource,
- .dev = {
- .platform_data = &s5p6450_i2s_pdata,
- },
-};
-
-/* PCM Controller platform_devices */
-
-static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5P6440_GPR(6), 3, S3C_GPIO_SFN(2));
- s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(2));
- break;
-
- default:
- printk(KERN_DEBUG "Invalid PCM Controller number!");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s5p6440_pcm_pdata = {
- .cfg_gpio = s5p6440_pcm_cfg_gpio,
-};
-
-static struct resource s5p6440_pcm0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P64X0_PA_PCM, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5p6440_device_pcm = {
- .name = "samsung-pcm",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource),
- .resource = s5p6440_pcm0_resource,
- .dev = {
- .platform_data = &s5p6440_pcm_pdata,
- },
-};
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
deleted file mode 100644
index 9c4ce085f585..000000000000
--- a/arch/arm/mach-s5p64x0/dma.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/dma.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/regs-clock.h>
-#include <mach/dma.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-static u8 s5p6440_pdma_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_PCM0_TX,
- DMACH_PCM0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI0_RX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_SPI1_TX,
- DMACH_SPI1_RX,
-};
-
-static struct dma_pl330_platdata s5p6440_pdma_pdata = {
- .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
- .peri_id = s5p6440_pdma_peri,
-};
-
-static u8 s5p6450_pdma_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_UART4_RX,
- DMACH_UART4_TX,
- DMACH_PCM0_TX,
- DMACH_PCM0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI0_RX,
- DMACH_PCM1_TX,
- DMACH_PCM1_RX,
- DMACH_PCM2_TX,
- DMACH_PCM2_RX,
- DMACH_SPI1_TX,
- DMACH_SPI1_RX,
- DMACH_USI_TX,
- DMACH_USI_RX,
- DMACH_MAX,
- DMACH_I2S1_TX,
- DMACH_I2S1_RX,
- DMACH_I2S2_TX,
- DMACH_I2S2_RX,
- DMACH_PWM,
- DMACH_UART5_RX,
- DMACH_UART5_TX,
-};
-
-static struct dma_pl330_platdata s5p6450_pdma_pdata = {
- .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
- .peri_id = s5p6450_pdma_peri,
-};
-
-static AMBA_AHB_DEVICE(s5p64x0_pdma, "dma-pl330", 0x00041330,
- S5P64X0_PA_PDMA, {IRQ_DMA0}, NULL);
-
-static int __init s5p64x0_dma_init(void)
-{
- if (soc_is_s5p6450()) {
- dma_cap_set(DMA_SLAVE, s5p6450_pdma_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5p6450_pdma_pdata.cap_mask);
- s5p64x0_pdma_device.dev.platform_data = &s5p6450_pdma_pdata;
- } else {
- dma_cap_set(DMA_SLAVE, s5p6440_pdma_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5p6440_pdma_pdata.cap_mask);
- s5p64x0_pdma_device.dev.platform_data = &s5p6440_pdma_pdata;
- }
-
- amba_device_register(&s5p64x0_pdma_device, &iomem_resource);
-
- return 0;
-}
-arch_initcall(s5p64x0_dma_init);
diff --git a/arch/arm/mach-s5p64x0/i2c.h b/arch/arm/mach-s5p64x0/i2c.h
deleted file mode 100644
index 1e5bb4ea200d..000000000000
--- a/arch/arm/mach-s5p64x0/i2c.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 I2C configuration
- *
- * 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.
-*/
-
-extern void s5p6440_i2c0_cfg_gpio(struct platform_device *dev);
-extern void s5p6440_i2c1_cfg_gpio(struct platform_device *dev);
-
-extern void s5p6450_i2c0_cfg_gpio(struct platform_device *dev);
-extern void s5p6450_i2c1_cfg_gpio(struct platform_device *dev);
diff --git a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S b/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
deleted file mode 100644
index 8759e7882bcb..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/debug-macro.S
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <linux/serial_s3c.h>
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
- .macro addruart, rp, rv, tmp
- mov \rp, #0xE0000000
- orr \rp, \rp, #0x00100000
- ldr \rp, [\rp, #0x118 ]
- and \rp, \rp, #0xff000
- teq \rp, #0x50000 @@ S5P6450
- ldreq \rp, =0xEC800000
- movne \rp, #0xEC000000 @@ S5P6440
- ldrne \rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
- add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
- add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
- .endm
-
-#include <debug/samsung.S>
diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h
deleted file mode 100644
index 06cd3c9b16ac..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/gpio.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/gpio.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* GPIO bank sizes */
-
-#define S5P6440_GPIO_A_NR (6)
-#define S5P6440_GPIO_B_NR (7)
-#define S5P6440_GPIO_C_NR (8)
-#define S5P6440_GPIO_F_NR (16)
-#define S5P6440_GPIO_G_NR (7)
-#define S5P6440_GPIO_H_NR (10)
-#define S5P6440_GPIO_I_NR (16)
-#define S5P6440_GPIO_J_NR (12)
-#define S5P6440_GPIO_N_NR (16)
-#define S5P6440_GPIO_P_NR (8)
-#define S5P6440_GPIO_R_NR (15)
-
-#define S5P6450_GPIO_A_NR (6)
-#define S5P6450_GPIO_B_NR (7)
-#define S5P6450_GPIO_C_NR (8)
-#define S5P6450_GPIO_D_NR (8)
-#define S5P6450_GPIO_F_NR (16)
-#define S5P6450_GPIO_G_NR (14)
-#define S5P6450_GPIO_H_NR (10)
-#define S5P6450_GPIO_I_NR (16)
-#define S5P6450_GPIO_J_NR (12)
-#define S5P6450_GPIO_K_NR (5)
-#define S5P6450_GPIO_N_NR (16)
-#define S5P6450_GPIO_P_NR (11)
-#define S5P6450_GPIO_Q_NR (14)
-#define S5P6450_GPIO_R_NR (15)
-#define S5P6450_GPIO_S_NR (8)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5P64X0_GPIO_NEXT(__gpio) \
- ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p6440_gpio_number {
- S5P6440_GPIO_A_START = 0,
- S5P6440_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_A),
- S5P6440_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_B),
- S5P6440_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_C),
- S5P6440_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_F),
- S5P6440_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_G),
- S5P6440_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_H),
- S5P6440_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_I),
- S5P6440_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_J),
- S5P6440_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_N),
- S5P6440_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6440_GPIO_P),
-};
-
-enum s5p6450_gpio_number {
- S5P6450_GPIO_A_START = 0,
- S5P6450_GPIO_B_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_A),
- S5P6450_GPIO_C_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_B),
- S5P6450_GPIO_D_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_C),
- S5P6450_GPIO_F_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_D),
- S5P6450_GPIO_G_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_F),
- S5P6450_GPIO_H_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_G),
- S5P6450_GPIO_I_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_H),
- S5P6450_GPIO_J_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_I),
- S5P6450_GPIO_K_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_J),
- S5P6450_GPIO_N_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_K),
- S5P6450_GPIO_P_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_N),
- S5P6450_GPIO_Q_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_P),
- S5P6450_GPIO_R_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_Q),
- S5P6450_GPIO_S_START = S5P64X0_GPIO_NEXT(S5P6450_GPIO_R),
-};
-
-/* GPIO number definitions */
-
-#define S5P6440_GPA(_nr) (S5P6440_GPIO_A_START + (_nr))
-#define S5P6440_GPB(_nr) (S5P6440_GPIO_B_START + (_nr))
-#define S5P6440_GPC(_nr) (S5P6440_GPIO_C_START + (_nr))
-#define S5P6440_GPF(_nr) (S5P6440_GPIO_F_START + (_nr))
-#define S5P6440_GPG(_nr) (S5P6440_GPIO_G_START + (_nr))
-#define S5P6440_GPH(_nr) (S5P6440_GPIO_H_START + (_nr))
-#define S5P6440_GPI(_nr) (S5P6440_GPIO_I_START + (_nr))
-#define S5P6440_GPJ(_nr) (S5P6440_GPIO_J_START + (_nr))
-#define S5P6440_GPN(_nr) (S5P6440_GPIO_N_START + (_nr))
-#define S5P6440_GPP(_nr) (S5P6440_GPIO_P_START + (_nr))
-#define S5P6440_GPR(_nr) (S5P6440_GPIO_R_START + (_nr))
-
-#define S5P6450_GPA(_nr) (S5P6450_GPIO_A_START + (_nr))
-#define S5P6450_GPB(_nr) (S5P6450_GPIO_B_START + (_nr))
-#define S5P6450_GPC(_nr) (S5P6450_GPIO_C_START + (_nr))
-#define S5P6450_GPD(_nr) (S5P6450_GPIO_D_START + (_nr))
-#define S5P6450_GPF(_nr) (S5P6450_GPIO_F_START + (_nr))
-#define S5P6450_GPG(_nr) (S5P6450_GPIO_G_START + (_nr))
-#define S5P6450_GPH(_nr) (S5P6450_GPIO_H_START + (_nr))
-#define S5P6450_GPI(_nr) (S5P6450_GPIO_I_START + (_nr))
-#define S5P6450_GPJ(_nr) (S5P6450_GPIO_J_START + (_nr))
-#define S5P6450_GPK(_nr) (S5P6450_GPIO_K_START + (_nr))
-#define S5P6450_GPN(_nr) (S5P6450_GPIO_N_START + (_nr))
-#define S5P6450_GPP(_nr) (S5P6450_GPIO_P_START + (_nr))
-#define S5P6450_GPQ(_nr) (S5P6450_GPIO_Q_START + (_nr))
-#define S5P6450_GPR(_nr) (S5P6450_GPIO_R_START + (_nr))
-#define S5P6450_GPS(_nr) (S5P6450_GPIO_S_START + (_nr))
-
-/* the end of the S5P64X0 specific gpios */
-
-#define S5P6440_GPIO_END (S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
-#define S5P6450_GPIO_END (S5P6450_GPS(S5P6450_GPIO_S_NR) + 1)
-
-#define S5P64X0_GPIO_END (S5P6440_GPIO_END > S5P6450_GPIO_END ? \
- S5P6440_GPIO_END : S5P6450_GPIO_END)
-
-#define S3C_GPIO_END S5P64X0_GPIO_END
-
-/* define the number of gpios we need to the one after the last GPIO range */
-
-#define ARCH_NR_GPIOS (S5P64X0_GPIO_END + CONFIG_SAMSUNG_GPIO_EXTRA)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/hardware.h b/arch/arm/mach-s5p64x0/include/mach/hardware.h
deleted file mode 100644
index d3e87996dd9a..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/hardware.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Hardware support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
deleted file mode 100644
index 53982db9d259..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/irqs.h
- *
- * Copyright 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0 */
-
-#define IRQ_EINT0_3 S5P_IRQ_VIC0(0)
-#define IRQ_EINT4_11 S5P_IRQ_VIC0(1)
-#define IRQ_RTC_TIC S5P_IRQ_VIC0(2)
-#define IRQ_IIS1 S5P_IRQ_VIC0(3) /* for only S5P6450 */
-#define IRQ_IIS2 S5P_IRQ_VIC0(4) /* for only S5P6450 */
-#define IRQ_IIC1 S5P_IRQ_VIC0(5)
-#define IRQ_I2SV40 S5P_IRQ_VIC0(6)
-#define IRQ_GPS S5P_IRQ_VIC0(7) /* for only S5P6450 */
-
-#define IRQ_2D S5P_IRQ_VIC0(11)
-#define IRQ_TIMER0_VIC S5P_IRQ_VIC0(23)
-#define IRQ_TIMER1_VIC S5P_IRQ_VIC0(24)
-#define IRQ_TIMER2_VIC S5P_IRQ_VIC0(25)
-#define IRQ_WDT S5P_IRQ_VIC0(26)
-#define IRQ_TIMER3_VIC S5P_IRQ_VIC0(27)
-#define IRQ_TIMER4_VIC S5P_IRQ_VIC0(28)
-#define IRQ_DISPCON0 S5P_IRQ_VIC0(29)
-#define IRQ_DISPCON1 S5P_IRQ_VIC0(30)
-#define IRQ_DISPCON2 S5P_IRQ_VIC0(31)
-
-/* VIC1 */
-
-#define IRQ_EINT12_15 S5P_IRQ_VIC1(0)
-#define IRQ_PCM0 S5P_IRQ_VIC1(2)
-#define IRQ_PCM1 S5P_IRQ_VIC1(3) /* for only S5P6450 */
-#define IRQ_PCM2 S5P_IRQ_VIC1(4) /* for only S5P6450 */
-#define IRQ_UART0 S5P_IRQ_VIC1(5)
-#define IRQ_UART1 S5P_IRQ_VIC1(6)
-#define IRQ_UART2 S5P_IRQ_VIC1(7)
-#define IRQ_UART3 S5P_IRQ_VIC1(8)
-#define IRQ_DMA0 S5P_IRQ_VIC1(9)
-#define IRQ_UART4 S5P_IRQ_VIC1(10) /* S5P6450 */
-#define IRQ_UART5 S5P_IRQ_VIC1(11) /* S5P6450 */
-#define IRQ_NFC S5P_IRQ_VIC1(13)
-#define IRQ_USI S5P_IRQ_VIC1(15) /* S5P6450 */
-#define IRQ_SPI0 S5P_IRQ_VIC1(16)
-#define IRQ_SPI1 S5P_IRQ_VIC1(17)
-#define IRQ_HSMMC2 S5P_IRQ_VIC1(17) /* Shared */
-#define IRQ_IIC S5P_IRQ_VIC1(18)
-#define IRQ_DISPCON3 S5P_IRQ_VIC1(19)
-#define IRQ_EINT_GROUPS S5P_IRQ_VIC1(21)
-#define IRQ_PMU S5P_IRQ_VIC1(23) /* S5P6440 */
-#define IRQ_HSMMC0 S5P_IRQ_VIC1(24)
-#define IRQ_HSMMC1 S5P_IRQ_VIC1(25)
-#define IRQ_OTG S5P_IRQ_VIC1(26)
-#define IRQ_DSI S5P_IRQ_VIC1(27)
-#define IRQ_RTC_ALARM S5P_IRQ_VIC1(28)
-#define IRQ_TSI S5P_IRQ_VIC1(29)
-#define IRQ_PENDN S5P_IRQ_VIC1(30)
-#define IRQ_TC IRQ_PENDN
-#define IRQ_ADC S5P_IRQ_VIC1(31)
-
-/* UART interrupts, S5P6450 has 5 UARTs */
-#define IRQ_S5P_UART_BASE4 (96)
-#define IRQ_S5P_UART_BASE5 (100)
-
-#define IRQ_S5P_UART_RX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX4 (IRQ_S5P_UART_BASE4 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR4 (IRQ_S5P_UART_BASE4 + UART_IRQ_ERR)
-
-#define IRQ_S5P_UART_RX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_RXD)
-#define IRQ_S5P_UART_TX5 (IRQ_S5P_UART_BASE5 + UART_IRQ_TXD)
-#define IRQ_S5P_UART_ERR5 (IRQ_S5P_UART_BASE5 + UART_IRQ_ERR)
-
-/* S3C compatibilty defines */
-#define IRQ_S3CUART_RX4 IRQ_S5P_UART_RX4
-#define IRQ_S3CUART_RX5 IRQ_S5P_UART_RX5
-
-#define IRQ_I2S0 IRQ_I2SV40
-
-#define IRQ_LCD_FIFO IRQ_DISPCON0
-#define IRQ_LCD_VSYNC IRQ_DISPCON1
-#define IRQ_LCD_SYSTEM IRQ_DISPCON2
-
-/* S5P6450 EINT feature will be added */
-
-/*
- * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
- * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
- * after the pair of VICs.
- */
-
-#define S5P_IRQ_EINT_BASE (S5P_IRQ_VIC1(31) + 6)
-
-#define S5P_EINT(x) ((x) + S5P_IRQ_EINT_BASE)
-
-#define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE)
-/*
- * S5P6440 has 0-15 external interrupts in group 0. Only these can be used
- * to wake up from sleep. If request is beyond this range, by mistake, a large
- * return value for an irq number should be indication of something amiss.
- */
-#define S5P_EINT_BASE2 (0xf0000000)
-
-/*
- * Next the external interrupt groups. These are similar to the IRQ_EINT(x)
- * that they are sourced from the GPIO pins but with a different scheme for
- * priority and source indication.
- *
- * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
- * interrupts, but for historical reasons they are kept apart from these
- * next interrupts.
- *
- * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
- * machine specific support files.
- */
-
-/* Actually, #6 and #7 are missing in the EINT_GROUP1 */
-#define IRQ_EINT_GROUP1_NR (15)
-#define IRQ_EINT_GROUP2_NR (8)
-#define IRQ_EINT_GROUP5_NR (7)
-#define IRQ_EINT_GROUP6_NR (10)
-/* Actually, #0, #1 and #2 are missing in the EINT_GROUP8 */
-#define IRQ_EINT_GROUP8_NR (11)
-
-#define IRQ_EINT_GROUP_BASE S5P_EINT(16)
-#define IRQ_EINT_GROUP1_BASE (IRQ_EINT_GROUP_BASE + 0)
-#define IRQ_EINT_GROUP2_BASE (IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
-#define IRQ_EINT_GROUP5_BASE (IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
-#define IRQ_EINT_GROUP6_BASE (IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
-#define IRQ_EINT_GROUP8_BASE (IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
-
-#define IRQ_EINT_GROUP(grp, x) (IRQ_EINT_GROUP##grp##_BASE + (x))
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h
deleted file mode 100644
index 50a6e96d6389..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/map.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/map.h
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5P64X0_PA_SDRAM 0x20000000
-
-#define S5P64X0_PA_CHIPID 0xE0000000
-
-#define S5P64X0_PA_SYSCON 0xE0100000
-
-#define S5P64X0_PA_GPIO 0xE0308000
-
-#define S5P64X0_PA_VIC0 0xE4000000
-#define S5P64X0_PA_VIC1 0xE4100000
-
-#define S5P64X0_PA_SROMC 0xE7000000
-
-#define S5P64X0_PA_PDMA 0xE9000000
-
-#define S5P64X0_PA_TIMER 0xEA000000
-#define S5P64X0_PA_RTC 0xEA100000
-#define S5P64X0_PA_WDT 0xEA200000
-
-#define S5P6440_PA_IIC0 0xEC104000
-#define S5P6440_PA_IIC1 0xEC20F000
-#define S5P6450_PA_IIC0 0xEC100000
-#define S5P6450_PA_IIC1 0xEC200000
-
-#define S5P64X0_PA_SPI0 0xEC400000
-#define S5P64X0_PA_SPI1 0xEC500000
-
-#define S5P64X0_PA_HSOTG 0xED100000
-
-#define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000))
-
-#define S5P64X0_PA_FB 0xEE000000
-
-#define S5P64X0_PA_I2S 0xF2000000
-#define S5P6450_PA_I2S1 0xF2800000
-#define S5P6450_PA_I2S2 0xF2900000
-
-#define S5P64X0_PA_PCM 0xF2100000
-
-#define S5P64X0_PA_ADC 0xF3000000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_HSMMC0 S5P64X0_PA_HSMMC(0)
-#define S3C_PA_HSMMC1 S5P64X0_PA_HSMMC(1)
-#define S3C_PA_HSMMC2 S5P64X0_PA_HSMMC(2)
-#define S3C_PA_IIC S5P6440_PA_IIC0
-#define S3C_PA_IIC1 S5P6440_PA_IIC1
-#define S3C_PA_RTC S5P64X0_PA_RTC
-#define S3C_PA_WDT S5P64X0_PA_WDT
-#define S3C_PA_FB S5P64X0_PA_FB
-#define S3C_PA_SPI0 S5P64X0_PA_SPI0
-#define S3C_PA_SPI1 S5P64X0_PA_SPI1
-
-#define S5P_PA_CHIPID S5P64X0_PA_CHIPID
-#define S5P_PA_SROMC S5P64X0_PA_SROMC
-#define S5P_PA_SYSCON S5P64X0_PA_SYSCON
-#define S5P_PA_TIMER S5P64X0_PA_TIMER
-
-#define SAMSUNG_PA_ADC S5P64X0_PA_ADC
-#define SAMSUNG_PA_TIMER S5P64X0_PA_TIMER
-
-/* UART */
-
-#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET))
-#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000))
-
-#define S5P_PA_UART0 S5P6450_PA_UART(0)
-#define S5P_PA_UART1 S5P6450_PA_UART(1)
-#define S5P_PA_UART2 S5P6450_PA_UART(2)
-#define S5P_PA_UART3 S5P6450_PA_UART(3)
-#define S5P_PA_UART4 S5P6450_PA_UART(4)
-#define S5P_PA_UART5 S5P6450_PA_UART(5)
-
-#define S5P_SZ_UART SZ_256
-#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/pm-core.h b/arch/arm/mach-s5p64x0/include/mach/pm-core.h
deleted file mode 100644
index 1e0eb65b2b82..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/pm-core.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c
- *
- * Based on PM core support for S3C64XX by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/serial_s3c.h>
-
-#include <mach/regs-gpio.h>
-
-static inline void s3c_pm_debug_init_uart(void)
-{
- u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK);
-
- /*
- * As a note, since the S5P64X0 UARTs generally have multiple
- * clock sources, we simply enable PCLK at the moment and hope
- * that the resume settings for the UART are suitable for the
- * use with PCLK.
- */
- tmp |= S5P64X0_CLK_GATE_PCLK_UART0;
- tmp |= S5P64X0_CLK_GATE_PCLK_UART1;
- tmp |= S5P64X0_CLK_GATE_PCLK_UART2;
- tmp |= S5P64X0_CLK_GATE_PCLK_UART3;
-
- __raw_writel(tmp, S5P64X0_CLK_GATE_PCLK);
- udelay(10);
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
- /* VIC should have already been taken care of */
-
- /* clear any pending EINT0 interrupts */
- __raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void) { }
-static inline void s3c_pm_arch_show_resume_irqs(void) { }
-
-/*
- * make these defines, we currently do not have any need to change
- * the IRQ wake controls depending on the CPU we are running on
- */
-#define s3c_irqwake_eintallow ((1 << 16) - 1)
-#define s3c_irqwake_intallow (~0)
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
- struct pm_uart_save *save)
-{
- u32 ucon = __raw_readl(regs + S3C2410_UCON);
- u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
- u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
- u32 new_ucon;
- u32 delta;
-
- /*
- * S5P64X0 UART blocks only support level interrupts, so ensure that
- * when we restore unused UART blocks we force the level interrupt
- * settings.
- */
- save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
-
- /*
- * We have a constraint on changing the clock type of the UART
- * between UCLKx and PCLK, so ensure that when we restore UCON
- * that the CLK field is correctly modified if the bootloader
- * has changed anything.
- */
- if (ucon_clk != save_clk) {
- new_ucon = save->ucon;
- delta = ucon_clk ^ save_clk;
-
- /*
- * change from UCLKx => wrong PCLK,
- * either UCLK can be tested for by a bit-test
- * with UCLK0
- */
- if (ucon_clk & S3C6400_UCON_UCLK0 &&
- !(save_clk & S3C6400_UCON_UCLK0) &&
- delta & S3C6400_UCON_PCLK2) {
- new_ucon &= ~S3C6400_UCON_UCLK0;
- } else if (delta == S3C6400_UCON_PCLK2) {
- /*
- * as a precaution, don't change from
- * PCLK2 => PCLK or vice-versa
- */
- new_ucon ^= S3C6400_UCON_PCLK2;
- }
-
- S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
- ucon, new_ucon, save->ucon);
- save->ucon = new_ucon;
- }
-}
-
-static inline void s3c_pm_restored_gpios(void)
-{
- /* ensure sleep mode has been cleared from the system */
- __raw_writel(0, S5P64X0_SLPEN);
-}
-
-static inline void samsung_pm_saved_gpios(void)
-{
- /*
- * turn on the sleep mode and keep it there, as it seems that during
- * suspend the xCON registers get re-set and thus you can end up with
- * problems between going to sleep and resuming.
- */
- __raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN);
-}
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
deleted file mode 100644
index bd91112c813c..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
-
-#define S5P64X0_APLL_CON S5P_CLKREG(0x0C)
-#define S5P64X0_MPLL_CON S5P_CLKREG(0x10)
-#define S5P64X0_EPLL_CON S5P_CLKREG(0x14)
-#define S5P64X0_EPLL_CON_K S5P_CLKREG(0x18)
-
-#define S5P64X0_CLK_SRC0 S5P_CLKREG(0x1C)
-
-#define S5P64X0_CLK_DIV0 S5P_CLKREG(0x20)
-#define S5P64X0_CLK_DIV1 S5P_CLKREG(0x24)
-#define S5P64X0_CLK_DIV2 S5P_CLKREG(0x28)
-
-#define S5P64X0_CLK_GATE_HCLK0 S5P_CLKREG(0x30)
-#define S5P64X0_CLK_GATE_PCLK S5P_CLKREG(0x34)
-#define S5P64X0_CLK_GATE_SCLK0 S5P_CLKREG(0x38)
-#define S5P64X0_CLK_GATE_MEM0 S5P_CLKREG(0x3C)
-
-#define S5P64X0_CLK_DIV3 S5P_CLKREG(0x40)
-
-#define S5P64X0_CLK_GATE_HCLK1 S5P_CLKREG(0x44)
-#define S5P64X0_CLK_GATE_SCLK1 S5P_CLKREG(0x48)
-
-#define S5P6450_DPLL_CON S5P_CLKREG(0x50)
-#define S5P6450_DPLL_CON_K S5P_CLKREG(0x54)
-
-#define S5P64X0_AHB_CON0 S5P_CLKREG(0x100)
-#define S5P64X0_CLK_SRC1 S5P_CLKREG(0x10C)
-
-#define S5P64X0_SYS_ID S5P_CLKREG(0x118)
-#define S5P64X0_SYS_OTHERS S5P_CLKREG(0x11C)
-
-#define S5P64X0_PWR_CFG S5P_CLKREG(0x804)
-#define S5P64X0_EINT_WAKEUP_MASK S5P_CLKREG(0x808)
-#define S5P64X0_SLEEP_CFG S5P_CLKREG(0x818)
-#define S5P64X0_PWR_STABLE S5P_CLKREG(0x828)
-
-#define S5P64X0_OTHERS S5P_CLKREG(0x900)
-#define S5P64X0_WAKEUP_STAT S5P_CLKREG(0x908)
-
-#define S5P64X0_INFORM0 S5P_CLKREG(0xA00)
-
-#define S5P64X0_CLKDIV0_HCLK_SHIFT (8)
-#define S5P64X0_CLKDIV0_HCLK_MASK (0xF << S5P64X0_CLKDIV0_HCLK_SHIFT)
-
-/* HCLK GATE Registers */
-#define S5P64X0_CLK_GATE_HCLK1_FIMGVG (1 << 2)
-#define S5P64X0_CLK_GATE_SCLK1_FIMGVG (1 << 2)
-
-/* PCLK GATE Registers */
-#define S5P64X0_CLK_GATE_PCLK_UART3 (1 << 4)
-#define S5P64X0_CLK_GATE_PCLK_UART2 (1 << 3)
-#define S5P64X0_CLK_GATE_PCLK_UART1 (1 << 2)
-#define S5P64X0_CLK_GATE_PCLK_UART0 (1 << 1)
-
-#define S5P64X0_PWR_CFG_MMC1_DISABLE (1 << 15)
-#define S5P64X0_PWR_CFG_MMC0_DISABLE (1 << 14)
-#define S5P64X0_PWR_CFG_RTC_TICK_DISABLE (1 << 11)
-#define S5P64X0_PWR_CFG_RTC_ALRM_DISABLE (1 << 10)
-#define S5P64X0_PWR_CFG_WFI_MASK (3 << 5)
-#define S5P64X0_PWR_CFG_WFI_SLEEP (3 << 5)
-
-#define S5P64X0_SLEEP_CFG_OSC_EN (1 << 0)
-
-#define S5P64X0_PWR_STABLE_PWR_CNT_VAL4 (4 << 0)
-
-#define S5P6450_OTHERS_DISABLE_INT (1 << 31)
-#define S5P64X0_OTHERS_RET_UART (1 << 26)
-#define S5P64X0_OTHERS_RET_MMC1 (1 << 25)
-#define S5P64X0_OTHERS_RET_MMC0 (1 << 24)
-#define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16)
-
-/* Compatibility defines */
-
-#define ARM_CLK_DIV S5P64X0_CLK_DIV0
-#define ARM_DIV_RATIO_SHIFT 0
-#define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT)
-
-#define S5P_EPLL_CON S5P64X0_EPLL_CON
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
deleted file mode 100644
index cfdfa4fdadf2..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - GPIO register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-/* Base addresses for each of the banks */
-
-#define S5P64X0_GPA_BASE (S5P_VA_GPIO + 0x0000)
-#define S5P64X0_GPB_BASE (S5P_VA_GPIO + 0x0020)
-#define S5P64X0_GPC_BASE (S5P_VA_GPIO + 0x0040)
-#define S5P64X0_GPF_BASE (S5P_VA_GPIO + 0x00A0)
-#define S5P64X0_GPG_BASE (S5P_VA_GPIO + 0x00C0)
-#define S5P64X0_GPH_BASE (S5P_VA_GPIO + 0x00E0)
-#define S5P64X0_GPI_BASE (S5P_VA_GPIO + 0x0100)
-#define S5P64X0_GPJ_BASE (S5P_VA_GPIO + 0x0120)
-#define S5P64X0_GPN_BASE (S5P_VA_GPIO + 0x0830)
-#define S5P64X0_GPP_BASE (S5P_VA_GPIO + 0x0160)
-#define S5P64X0_GPR_BASE (S5P_VA_GPIO + 0x0290)
-
-#define S5P6450_GPD_BASE (S5P_VA_GPIO + 0x0060)
-#define S5P6450_GPK_BASE (S5P_VA_GPIO + 0x0140)
-#define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180)
-#define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300)
-
-#define S5P64X0_SPCON0 (S5P_VA_GPIO + 0x1A0)
-#define S5P64X0_SPCON0_LCD_SEL_MASK (0x3 << 0)
-#define S5P64X0_SPCON0_LCD_SEL_RGB (0x1 << 0)
-#define S5P64X0_SPCON1 (S5P_VA_GPIO + 0x2B0)
-
-#define S5P64X0_MEM0CONSLP0 (S5P_VA_GPIO + 0x1C0)
-#define S5P64X0_MEM0CONSLP1 (S5P_VA_GPIO + 0x1C4)
-#define S5P64X0_MEM0DRVCON (S5P_VA_GPIO + 0x1D0)
-#define S5P64X0_MEM1DRVCON (S5P_VA_GPIO + 0x1D4)
-
-#define S5P64X0_EINT12CON (S5P_VA_GPIO + 0x200)
-#define S5P64X0_EINT12FLTCON (S5P_VA_GPIO + 0x220)
-#define S5P64X0_EINT12MASK (S5P_VA_GPIO + 0x240)
-
-/* External interrupt control registers for group0 */
-
-#define EINT0CON0_OFFSET (0x900)
-#define EINT0FLTCON0_OFFSET (0x910)
-#define EINT0FLTCON1_OFFSET (0x914)
-#define EINT0MASK_OFFSET (0x920)
-#define EINT0PEND_OFFSET (0x924)
-
-#define S5P64X0_EINT0CON0 (S5P_VA_GPIO + EINT0CON0_OFFSET)
-#define S5P64X0_EINT0FLTCON0 (S5P_VA_GPIO + EINT0FLTCON0_OFFSET)
-#define S5P64X0_EINT0FLTCON1 (S5P_VA_GPIO + EINT0FLTCON1_OFFSET)
-#define S5P64X0_EINT0MASK (S5P_VA_GPIO + EINT0MASK_OFFSET)
-#define S5P64X0_EINT0PEND (S5P_VA_GPIO + EINT0PEND_OFFSET)
-
-#define S5P64X0_SLPEN (S5P_VA_GPIO + 0x930)
-#define S5P64X0_SLPEN_USE_xSLP (1 << 0)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
deleted file mode 100644
index d60397d1ff40..000000000000
--- a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p64x0/irq-pm.c b/arch/arm/mach-s5p64x0/irq-pm.c
deleted file mode 100644
index 2ed921e095dc..000000000000
--- a/arch/arm/mach-s5p64x0/irq-pm.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/irq-pm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 - Interrupt handling Power Management
- *
- * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/syscore_ops.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/io.h>
-
-#include <plat/pm.h>
-
-#include <mach/regs-gpio.h>
-
-static struct sleep_save irq_save[] = {
- SAVE_ITEM(S5P64X0_EINT0CON0),
- SAVE_ITEM(S5P64X0_EINT0FLTCON0),
- SAVE_ITEM(S5P64X0_EINT0FLTCON1),
- SAVE_ITEM(S5P64X0_EINT0MASK),
-};
-
-static struct irq_grp_save {
- u32 con;
- u32 fltcon;
- u32 mask;
-} eint_grp_save[4];
-
-#ifdef CONFIG_SERIAL_SAMSUNG
-static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
-#endif
-
-static int s5p64x0_irq_pm_suspend(void)
-{
- struct irq_grp_save *grp = eint_grp_save;
- int i;
-
- S3C_PMDBG("%s: suspending IRQs\n", __func__);
-
- s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-
-#ifdef CONFIG_SERIAL_SAMSUNG
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
- irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
-#endif
-
- for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
- grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4));
- grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4));
- grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4));
- }
-
- return 0;
-}
-
-static void s5p64x0_irq_pm_resume(void)
-{
- struct irq_grp_save *grp = eint_grp_save;
- int i;
-
- S3C_PMDBG("%s: resuming IRQs\n", __func__);
-
- s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-
-#ifdef CONFIG_SERIAL_SAMSUNG
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
- __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
-#endif
-
- for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
- __raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4));
- __raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4));
- __raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4));
- }
-
- S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
-}
-
-static struct syscore_ops s5p64x0_irq_syscore_ops = {
- .suspend = s5p64x0_irq_pm_suspend,
- .resume = s5p64x0_irq_pm_resume,
-};
-
-static int __init s5p64x0_syscore_init(void)
-{
- register_syscore_ops(&s5p64x0_irq_syscore_ops);
-
- return 0;
-}
-core_initcall(s5p64x0_syscore_init);
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
deleted file mode 100644
index 6840e197cb2d..000000000000
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/mach-smdk6440.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/pwm_backlight.h>
-#include <linux/fb.h>
-#include <linux/mmc/host.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pll.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-
-#include "common.h"
-#include "i2c.h"
-
-#define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDK6440_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDK6440_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S3C2440_UFCON_TXTRIG16 | \
- S3C2410_UFCON_RXTRIG8)
-
-static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDK6440_UCON_DEFAULT,
- .ulcon = SMDK6440_ULCON_DEFAULT,
- .ufcon = SMDK6440_UFCON_DEFAULT,
- },
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdk6440_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 24,
- .xres = 800,
- .yres = 480,
-};
-
-static struct fb_videomode smdk6440_lcd_timing = {
- .left_margin = 8,
- .right_margin = 13,
- .upper_margin = 7,
- .lower_margin = 5,
- .hsync_len = 3,
- .vsync_len = 1,
- .xres = 800,
- .yres = 480,
-};
-
-static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
- .win[0] = &smdk6440_fb_win0,
- .vtiming = &smdk6440_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
-};
-
-/* LCD power controller */
-static void smdk6440_lte480_reset_power(struct plat_lcd_data *pd,
- unsigned int power)
-{
- int err;
-
- if (power) {
- err = gpio_request(S5P6440_GPN(5), "GPN");
- if (err) {
- printk(KERN_ERR "failed to request GPN for lcd reset\n");
- return;
- }
-
- gpio_direction_output(S5P6440_GPN(5), 1);
- gpio_set_value(S5P6440_GPN(5), 0);
- gpio_set_value(S5P6440_GPN(5), 1);
- gpio_free(S5P6440_GPN(5));
- }
-}
-
-static struct plat_lcd_data smdk6440_lcd_power_data = {
- .set_power = smdk6440_lte480_reset_power,
-};
-
-static struct platform_device smdk6440_lcd_lte480wv = {
- .name = "platform-lcd",
- .dev.parent = &s3c_device_fb.dev,
- .dev.platform_data = &smdk6440_lcd_power_data,
-};
-
-static struct platform_device *smdk6440_devices[] __initdata = {
- &s3c_device_adc,
- &s3c_device_rtc,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &samsung_device_pwm,
- &s3c_device_ts,
- &s3c_device_wdt,
- &s5p6440_device_iis,
- &s3c_device_fb,
- &smdk6440_lcd_lte480wv,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc0_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc1_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_INTERNAL,
-#if defined(CONFIG_S5P64X0_SD_CH1_8BIT)
- .max_width = 8,
- .host_caps = MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdk6440_hsmmc2_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
- .flags = 0,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
- .cfg_gpio = s5p6440_i2c0_cfg_gpio,
-};
-
-static struct s3c2410_platform_i2c s5p6440_i2c1_data __initdata = {
- .flags = 0,
- .bus_num = 1,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
- .cfg_gpio = s5p6440_i2c1_cfg_gpio,
-};
-
-static struct i2c_board_info smdk6440_i2c_devs0[] __initdata = {
- { I2C_BOARD_INFO("24c08", 0x50), },
- { I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdk6440_i2c_devs1[] __initdata = {
- /* To be populated */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
- .no = S5P6440_GPF(15),
- .func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdk6440_bl_data = {
- .pwm_id = 1,
- .enable_gpio = -1,
-};
-
-static void __init smdk6440_map_io(void)
-{
- s5p64x0_init_io(NULL, 0);
- s3c24xx_init_clocks(12000000);
- s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void s5p6440_set_lcd_interface(void)
-{
- unsigned int cfg;
-
- /* select TFT LCD type (RGB I/F) */
- cfg = __raw_readl(S5P64X0_SPCON0);
- cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
- cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
- __raw_writel(cfg, S5P64X0_SPCON0);
-}
-
-static void __init smdk6440_machine_init(void)
-{
- s3c24xx_ts_set_platdata(NULL);
-
- s3c_i2c0_set_platdata(&s5p6440_i2c0_data);
- s3c_i2c1_set_platdata(&s5p6440_i2c1_data);
- i2c_register_board_info(0, smdk6440_i2c_devs0,
- ARRAY_SIZE(smdk6440_i2c_devs0));
- i2c_register_board_info(1, smdk6440_i2c_devs1,
- ARRAY_SIZE(smdk6440_i2c_devs1));
-
- s5p6440_set_lcd_interface();
- s3c_fb_set_platdata(&smdk6440_lcd_pdata);
-
- s3c_sdhci0_set_platdata(&smdk6440_hsmmc0_pdata);
- s3c_sdhci1_set_platdata(&smdk6440_hsmmc1_pdata);
- s3c_sdhci2_set_platdata(&smdk6440_hsmmc2_pdata);
-
- platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
-
- samsung_bl_set(&smdk6440_bl_gpio_info, &smdk6440_bl_data);
-}
-
-MACHINE_START(SMDK6440, "SMDK6440")
- /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .atag_offset = 0x100,
-
- .init_irq = s5p6440_init_irq,
- .map_io = smdk6440_map_io,
- .init_machine = smdk6440_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5p64x0_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
deleted file mode 100644
index fa1341c074ca..000000000000
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/mach-smdk6450.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/pwm_backlight.h>
-#include <linux/fb.h>
-#include <linux/mmc/host.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pll.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/fb.h>
-#include <plat/sdhci.h>
-
-#include "common.h"
-#include "i2c.h"
-
-#define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDK6450_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDK6450_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S3C2440_UFCON_TXTRIG16 | \
- S3C2410_UFCON_RXTRIG8)
-
-static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
- [4] = {
- .hwport = 4,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
-#endif
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
- [5] = {
- .hwport = 5,
- .flags = 0,
- .ucon = SMDK6450_UCON_DEFAULT,
- .ulcon = SMDK6450_ULCON_DEFAULT,
- .ufcon = SMDK6450_UFCON_DEFAULT,
- },
-#endif
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdk6450_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 24,
- .xres = 800,
- .yres = 480,
-};
-
-static struct fb_videomode smdk6450_lcd_timing = {
- .left_margin = 8,
- .right_margin = 13,
- .upper_margin = 7,
- .lower_margin = 5,
- .hsync_len = 3,
- .vsync_len = 1,
- .xres = 800,
- .yres = 480,
-};
-
-static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
- .win[0] = &smdk6450_fb_win0,
- .vtiming = &smdk6450_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
-};
-
-/* LCD power controller */
-static void smdk6450_lte480_reset_power(struct plat_lcd_data *pd,
- unsigned int power)
-{
- int err;
-
- if (power) {
- err = gpio_request(S5P6450_GPN(5), "GPN");
- if (err) {
- printk(KERN_ERR "failed to request GPN for lcd reset\n");
- return;
- }
-
- gpio_direction_output(S5P6450_GPN(5), 1);
- gpio_set_value(S5P6450_GPN(5), 0);
- gpio_set_value(S5P6450_GPN(5), 1);
- gpio_free(S5P6450_GPN(5));
- }
-}
-
-static struct plat_lcd_data smdk6450_lcd_power_data = {
- .set_power = smdk6450_lte480_reset_power,
-};
-
-static struct platform_device smdk6450_lcd_lte480wv = {
- .name = "platform-lcd",
- .dev.parent = &s3c_device_fb.dev,
- .dev.platform_data = &smdk6450_lcd_power_data,
-};
-
-static struct platform_device *smdk6450_devices[] __initdata = {
- &s3c_device_adc,
- &s3c_device_rtc,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &samsung_device_pwm,
- &s3c_device_ts,
- &s3c_device_wdt,
- &s5p6450_device_iis0,
- &s3c_device_fb,
- &smdk6450_lcd_lte480wv,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- /* s5p6450_device_spi0 will be added */
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc0_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc1_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_NONE,
-#if defined(CONFIG_S5P64X0_SD_CH1_8BIT)
- .max_width = 8,
- .host_caps = MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdk6450_hsmmc2_pdata __initdata = {
- .cd_type = S3C_SDHCI_CD_NONE,
-};
-
-static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = {
- .flags = 0,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
- .cfg_gpio = s5p6450_i2c0_cfg_gpio,
-};
-
-static struct s3c2410_platform_i2c s5p6450_i2c1_data __initdata = {
- .flags = 0,
- .bus_num = 1,
- .slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
- .cfg_gpio = s5p6450_i2c1_cfg_gpio,
-};
-
-static struct i2c_board_info smdk6450_i2c_devs0[] __initdata = {
- { I2C_BOARD_INFO("wm8580", 0x1b), },
- { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung KS24C080C EEPROM */
-};
-
-static struct i2c_board_info smdk6450_i2c_devs1[] __initdata = {
- { I2C_BOARD_INFO("24c128", 0x57), },/* Samsung S524AD0XD1 EEPROM */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
- .no = S5P6450_GPF(15),
- .func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdk6450_bl_data = {
- .pwm_id = 1,
- .enable_gpio = -1,
-};
-
-static void __init smdk6450_map_io(void)
-{
- s5p64x0_init_io(NULL, 0);
- s3c24xx_init_clocks(19200000);
- s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void s5p6450_set_lcd_interface(void)
-{
- unsigned int cfg;
-
- /* select TFT LCD type (RGB I/F) */
- cfg = __raw_readl(S5P64X0_SPCON0);
- cfg &= ~S5P64X0_SPCON0_LCD_SEL_MASK;
- cfg |= S5P64X0_SPCON0_LCD_SEL_RGB;
- __raw_writel(cfg, S5P64X0_SPCON0);
-}
-
-static void __init smdk6450_machine_init(void)
-{
- s3c24xx_ts_set_platdata(NULL);
-
- s3c_i2c0_set_platdata(&s5p6450_i2c0_data);
- s3c_i2c1_set_platdata(&s5p6450_i2c1_data);
- i2c_register_board_info(0, smdk6450_i2c_devs0,
- ARRAY_SIZE(smdk6450_i2c_devs0));
- i2c_register_board_info(1, smdk6450_i2c_devs1,
- ARRAY_SIZE(smdk6450_i2c_devs1));
-
- s5p6450_set_lcd_interface();
- s3c_fb_set_platdata(&smdk6450_lcd_pdata);
-
- s3c_sdhci0_set_platdata(&smdk6450_hsmmc0_pdata);
- s3c_sdhci1_set_platdata(&smdk6450_hsmmc1_pdata);
- s3c_sdhci2_set_platdata(&smdk6450_hsmmc2_pdata);
-
- platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices));
-
- samsung_bl_set(&smdk6450_bl_gpio_info, &smdk6450_bl_data);
-}
-
-MACHINE_START(SMDK6450, "SMDK6450")
- /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .atag_offset = 0x100,
-
- .init_irq = s5p6450_init_irq,
- .map_io = smdk6450_map_io,
- .init_machine = smdk6450_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5p64x0_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c
deleted file mode 100644
index ec8229cee716..000000000000
--- a/arch/arm/mach-s5p64x0/pm.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/pm.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P64X0 Power Management Support
- *
- * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/suspend.h>
-#include <linux/syscore_ops.h>
-#include <linux/io.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/wakeup-mask.h>
-
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-
-static struct sleep_save s5p64x0_core_save[] = {
- SAVE_ITEM(S5P64X0_APLL_CON),
- SAVE_ITEM(S5P64X0_MPLL_CON),
- SAVE_ITEM(S5P64X0_EPLL_CON),
- SAVE_ITEM(S5P64X0_EPLL_CON_K),
- SAVE_ITEM(S5P64X0_CLK_SRC0),
- SAVE_ITEM(S5P64X0_CLK_SRC1),
- SAVE_ITEM(S5P64X0_CLK_DIV0),
- SAVE_ITEM(S5P64X0_CLK_DIV1),
- SAVE_ITEM(S5P64X0_CLK_DIV2),
- SAVE_ITEM(S5P64X0_CLK_DIV3),
- SAVE_ITEM(S5P64X0_CLK_GATE_MEM0),
- SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1),
- SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1),
-};
-
-static struct sleep_save s5p64x0_misc_save[] = {
- SAVE_ITEM(S5P64X0_AHB_CON0),
- SAVE_ITEM(S5P64X0_SPCON0),
- SAVE_ITEM(S5P64X0_SPCON1),
- SAVE_ITEM(S5P64X0_MEM0CONSLP0),
- SAVE_ITEM(S5P64X0_MEM0CONSLP1),
- SAVE_ITEM(S5P64X0_MEM0DRVCON),
- SAVE_ITEM(S5P64X0_MEM1DRVCON),
-};
-
-/* DPLL is present only in S5P6450 */
-static struct sleep_save s5p6450_core_save[] = {
- SAVE_ITEM(S5P6450_DPLL_CON),
- SAVE_ITEM(S5P6450_DPLL_CON_K),
-};
-
-void s3c_pm_configure_extint(void)
-{
- __raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK);
-}
-
-void s3c_pm_restore_core(void)
-{
- __raw_writel(0, S5P64X0_EINT_WAKEUP_MASK);
-
- s3c_pm_do_restore_core(s5p64x0_core_save,
- ARRAY_SIZE(s5p64x0_core_save));
-
- if (soc_is_s5p6450())
- s3c_pm_do_restore_core(s5p6450_core_save,
- ARRAY_SIZE(s5p6450_core_save));
-
- s3c_pm_do_restore(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
-}
-
-void s3c_pm_save_core(void)
-{
- s3c_pm_do_save(s5p64x0_misc_save, ARRAY_SIZE(s5p64x0_misc_save));
-
- if (soc_is_s5p6450())
- s3c_pm_do_save(s5p6450_core_save,
- ARRAY_SIZE(s5p6450_core_save));
-
- s3c_pm_do_save(s5p64x0_core_save, ARRAY_SIZE(s5p64x0_core_save));
-}
-
-static int s5p64x0_cpu_suspend(unsigned long arg)
-{
- unsigned long tmp = 0;
-
- /*
- * Issue the standby signal into the pm unit. Note, we
- * issue a write-buffer drain just in case.
- */
- asm("b 1f\n\t"
- ".align 5\n\t"
- "1:\n\t"
- "mcr p15, 0, %0, c7, c10, 5\n\t"
- "mcr p15, 0, %0, c7, c10, 4\n\t"
- "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp));
-
- pr_info("Failed to suspend the system\n");
- return 1; /* Aborting suspend */
-}
-
-/* mapping of interrupts to parts of the wakeup mask */
-static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = {
- { .irq = IRQ_RTC_ALARM, .bit = S5P64X0_PWR_CFG_RTC_ALRM_DISABLE, },
- { .irq = IRQ_RTC_TIC, .bit = S5P64X0_PWR_CFG_RTC_TICK_DISABLE, },
- { .irq = IRQ_HSMMC0, .bit = S5P64X0_PWR_CFG_MMC0_DISABLE, },
- { .irq = IRQ_HSMMC1, .bit = S5P64X0_PWR_CFG_MMC1_DISABLE, },
-};
-
-static void s5p64x0_pm_prepare(void)
-{
- u32 tmp;
-
- samsung_sync_wakemask(S5P64X0_PWR_CFG,
- s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs));
-
- /* store the resume address in INFORM0 register */
- __raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0);
-
- /* setup clock gating for FIMGVG block */
- __raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \
- (S5P64X0_CLK_GATE_HCLK1_FIMGVG)), S5P64X0_CLK_GATE_HCLK1);
- __raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \
- (S5P64X0_CLK_GATE_SCLK1_FIMGVG)), S5P64X0_CLK_GATE_SCLK1);
-
- /* Configure the stabilization counter with wait time required */
- __raw_writel(S5P64X0_PWR_STABLE_PWR_CNT_VAL4, S5P64X0_PWR_STABLE);
-
- /* set WFI to SLEEP mode configuration */
- tmp = __raw_readl(S5P64X0_SLEEP_CFG);
- tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN);
- __raw_writel(tmp, S5P64X0_SLEEP_CFG);
-
- tmp = __raw_readl(S5P64X0_PWR_CFG);
- tmp &= ~(S5P64X0_PWR_CFG_WFI_MASK);
- tmp |= S5P64X0_PWR_CFG_WFI_SLEEP;
- __raw_writel(tmp, S5P64X0_PWR_CFG);
-
- /*
- * set OTHERS register to disable interrupt before going to
- * sleep. This bit is present only in S5P6450, it is reserved
- * in S5P6440.
- */
- if (soc_is_s5p6450()) {
- tmp = __raw_readl(S5P64X0_OTHERS);
- tmp |= S5P6450_OTHERS_DISABLE_INT;
- __raw_writel(tmp, S5P64X0_OTHERS);
- }
-
- /* ensure previous wakeup state is cleared before sleeping */
- __raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), S5P64X0_WAKEUP_STAT);
-
-}
-
-static int s5p64x0_pm_add(struct device *dev, struct subsys_interface *sif)
-{
- pm_cpu_prep = s5p64x0_pm_prepare;
- pm_cpu_sleep = s5p64x0_cpu_suspend;
-
- return 0;
-}
-
-static struct subsys_interface s5p64x0_pm_interface = {
- .name = "s5p64x0_pm",
- .subsys = &s5p64x0_subsys,
- .add_dev = s5p64x0_pm_add,
-};
-
-static __init int s5p64x0_pm_drvinit(void)
-{
- s3c_pm_init();
-
- return subsys_interface_register(&s5p64x0_pm_interface);
-}
-arch_initcall(s5p64x0_pm_drvinit);
-
-static void s5p64x0_pm_resume(void)
-{
- u32 tmp;
-
- tmp = __raw_readl(S5P64X0_OTHERS);
- tmp |= (S5P64X0_OTHERS_RET_MMC0 | S5P64X0_OTHERS_RET_MMC1 | \
- S5P64X0_OTHERS_RET_UART);
- __raw_writel(tmp , S5P64X0_OTHERS);
-}
-
-static struct syscore_ops s5p64x0_pm_syscore_ops = {
- .resume = s5p64x0_pm_resume,
-};
-
-static __init int s5p64x0_pm_syscore_init(void)
-{
- register_syscore_ops(&s5p64x0_pm_syscore_ops);
-
- return 0;
-}
-arch_initcall(s5p64x0_pm_syscore_init);
diff --git a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c b/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
deleted file mode 100644
index f346ee4af54d..000000000000
--- a/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-fb-24bpp.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Base S5P64X0 GPIO setup information for LCD framebuffer
- *
- * 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/fb.h>
-#include <linux/gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <plat/gpio-cfg.h>
-
-void s5p64x0_fb_gpio_setup_24bpp(void)
-{
- if (soc_is_s5p6440()) {
- s3c_gpio_cfgrange_nopull(S5P6440_GPI(0), 16, S3C_GPIO_SFN(2));
- s3c_gpio_cfgrange_nopull(S5P6440_GPJ(0), 12, S3C_GPIO_SFN(2));
- } else if (soc_is_s5p6450()) {
- s3c_gpio_cfgrange_nopull(S5P6450_GPI(0), 16, S3C_GPIO_SFN(2));
- s3c_gpio_cfgrange_nopull(S5P6450_GPJ(0), 12, S3C_GPIO_SFN(2));
- }
-}
diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c
deleted file mode 100644
index 569b76ac98cb..000000000000
--- a/arch/arm/mach-s5p64x0/setup-i2c0.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64x0/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-
-#include "i2c.h"
-
-void s5p6440_i2c0_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5P6440_GPB(5), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
-
-void s5p6450_i2c0_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5P6450_GPB(5), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c
deleted file mode 100644
index 867374e6d0bc..000000000000
--- a/arch/arm/mach-s5p64x0/setup-i2c1.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64xx/setup-i2c1.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * I2C1 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-
-#include "i2c.h"
-
-void s5p6440_i2c1_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5P6440_GPR(9), 2,
- S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
-}
-
-void s5p6450_i2c1_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5P6450_GPR(9), 2,
- S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
-}
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev) { }
diff --git a/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c b/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c
deleted file mode 100644
index 8410af0d12bf..000000000000
--- a/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P64X0 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * 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/io.h>
-#include <linux/gpio.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-#include <plat/cpu.h>
-
-void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG pins to special-function 2 */
- if (soc_is_s5p6450())
- s3c_gpio_cfgrange_nopull(S5P6450_GPG(0), 2 + width,
- S3C_GPIO_SFN(2));
- else
- s3c_gpio_cfgrange_nopull(S5P6440_GPG(0), 2 + width,
- S3C_GPIO_SFN(2));
-
- /* Set GPG[6] pin to special-function 2 - MMC0 CDn */
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- if (soc_is_s5p6450()) {
- s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(2));
- } else {
- s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(2));
- }
- }
-}
-
-void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set GPH[0:1] pins to special-function 2 - CLK and CMD */
- if (soc_is_s5p6450())
- s3c_gpio_cfgrange_nopull(S5P6450_GPH(0), 2, S3C_GPIO_SFN(2));
- else
- s3c_gpio_cfgrange_nopull(S5P6440_GPH(0), 2 , S3C_GPIO_SFN(2));
-
- switch (width) {
- case 8:
- /* Set data pins GPH[6:9] special-function 2 */
- if (soc_is_s5p6450())
- s3c_gpio_cfgrange_nopull(S5P6450_GPH(6), 4,
- S3C_GPIO_SFN(2));
- else
- s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4,
- S3C_GPIO_SFN(2));
- case 4:
- /* set data pins GPH[2:5] special-function 2 */
- if (soc_is_s5p6450())
- s3c_gpio_cfgrange_nopull(S5P6450_GPH(2), 4,
- S3C_GPIO_SFN(2));
- else
- s3c_gpio_cfgrange_nopull(S5P6440_GPH(2), 4,
- S3C_GPIO_SFN(2));
- default:
- break;
- }
-
- /* Set GPG[6] pin to special-funtion 3 : MMC1 CDn */
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- if (soc_is_s5p6450()) {
- s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(3));
- } else {
- s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(3));
- }
- }
-}
-
-void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
- /* Set GPC[4:5] pins to special-function 3 - CLK and CMD */
- s3c_gpio_cfgrange_nopull(S5P6440_GPC(4), 2, S3C_GPIO_SFN(3));
-
- /* Set data pins GPH[6:9] pins to special-function 3 */
- s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, S3C_GPIO_SFN(3));
-}
-
-void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
- /* Set all the necessary GPG pins to special-function 3 */
- s3c_gpio_cfgrange_nopull(S5P6450_GPG(7), 2 + width, S3C_GPIO_SFN(3));
-}
diff --git a/arch/arm/mach-s5p64x0/setup-spi.c b/arch/arm/mach-s5p64x0/setup-spi.c
deleted file mode 100644
index 7664356720ca..000000000000
--- a/arch/arm/mach-s5p64x0/setup-spi.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
- if (soc_is_s5p6450())
- s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- else
- s3c_gpio_cfgall_range(S5P6440_GPC(0), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
- if (soc_is_s5p6450())
- s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- else
- s3c_gpio_cfgall_range(S5P6440_GPC(4), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
deleted file mode 100644
index c5e3a969b063..000000000000
--- a/arch/arm/mach-s5pc100/Kconfig
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2009 Samsung Electronics Co.
-# Byungho Min <bhmin@samsung.com>
-#
-# Licensed under GPLv2
-
-# Configuration options for the S5PC100 CPU
-
-if ARCH_S5PC100
-
-config CPU_S5PC100
- bool
- select ARM_AMBA
- select PL330_DMA if DMADEVICES
- select S5P_EXT_INT
- help
- Enable S5PC100 CPU support
-
-config S5PC100_SETUP_FB_24BPP
- bool
- help
- Common setup code for S5PC1XX with an 24bpp RGB display helper.
-
-config S5PC100_SETUP_I2C1
- bool
- help
- Common setup code for i2c bus 1.
-
-config S5PC100_SETUP_IDE
- bool
- help
- Common setup code for S5PC100 IDE GPIO configurations
-
-config S5PC100_SETUP_KEYPAD
- bool
- help
- Common setup code for KEYPAD GPIO configurations.
-
-config S5PC100_SETUP_SDHCI
- bool
- select S5PC100_SETUP_SDHCI_GPIO
- help
- Internal helper functions for S5PC100 based SDHCI systems
-
-config S5PC100_SETUP_SDHCI_GPIO
- bool
- help
- Common setup code for SDHCI gpio.
-
-config S5PC100_SETUP_SPI
- bool
- help
- Common setup code for SPI GPIO configurations.
-
-config MACH_SMDKC100
- bool "SMDKC100"
- select CPU_S5PC100
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_I2C1
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S5PC100_SETUP_FB_24BPP
- select S5PC100_SETUP_I2C1
- select S5PC100_SETUP_IDE
- select S5PC100_SETUP_KEYPAD
- select S5PC100_SETUP_SDHCI
- select S5P_DEV_FIMC0
- select S5P_DEV_FIMC1
- select S5P_DEV_FIMC2
- select SAMSUNG_DEV_ADC
- select SAMSUNG_DEV_BACKLIGHT
- select SAMSUNG_DEV_IDE
- select SAMSUNG_DEV_KEYPAD
- select SAMSUNG_DEV_PWM
- select SAMSUNG_DEV_TS
- help
- Machine support for the Samsung SMDKC100
-
-endif
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
deleted file mode 100644
index 118c711f74e8..000000000000
--- a/arch/arm/mach-s5pc100/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# arch/arm/mach-s5pc100/Makefile
-#
-# Copyright 2009 Samsung Electronics Co.
-#
-# Licensed under GPLv2
-
-obj-y :=
-obj-m :=
-obj-n :=
-obj- :=
-
-# Core
-
-obj-y += common.o clock.o
-
-obj-y += dma.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDKC100) += mach-smdkc100.o
-
-# device support
-
-obj-y += dev-audio.o
-
-obj-y += setup-i2c0.o
-obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o
-obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o
-obj-$(CONFIG_S5PC100_SETUP_IDE) += setup-ide.o
-obj-$(CONFIG_S5PC100_SETUP_KEYPAD) += setup-keypad.o
-obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
-obj-$(CONFIG_S5PC100_SETUP_SPI) += setup-spi.o
diff --git a/arch/arm/mach-s5pc100/Makefile.boot b/arch/arm/mach-s5pc100/Makefile.boot
deleted file mode 100644
index 79ece4055b02..000000000000
--- a/arch/arm/mach-s5pc100/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y += 0x20008000
-params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
deleted file mode 100644
index d0dc10ee7729..000000000000
--- a/arch/arm/mach-s5pc100/clock.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PC100 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-static struct clk s5p_clk_otgphy = {
- .name = "otg_phy",
-};
-
-static struct clk dummy_apb_pclk = {
- .name = "apb_pclk",
- .id = -1,
-};
-
-static struct clk *clk_src_mout_href_list[] = {
- [0] = &s5p_clk_27m,
- [1] = &clk_fin_hpll,
-};
-
-static struct clksrc_sources clk_src_mout_href = {
- .sources = clk_src_mout_href_list,
- .nr_sources = ARRAY_SIZE(clk_src_mout_href_list),
-};
-
-static struct clksrc_clk clk_mout_href = {
- .clk = {
- .name = "mout_href",
- },
- .sources = &clk_src_mout_href,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
-};
-
-static struct clk *clk_src_mout_48m_list[] = {
- [0] = &clk_xusbxti,
- [1] = &s5p_clk_otgphy,
-};
-
-static struct clksrc_sources clk_src_mout_48m = {
- .sources = clk_src_mout_48m_list,
- .nr_sources = ARRAY_SIZE(clk_src_mout_48m_list),
-};
-
-static struct clksrc_clk clk_mout_48m = {
- .clk = {
- .name = "mout_48m",
- },
- .sources = &clk_src_mout_48m,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- },
- .sources = &clk_src_mpll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
-};
-
-
-static struct clksrc_clk clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- },
- .sources = &clk_src_apll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- },
- .sources = &clk_src_epll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
-};
-
-static struct clk *clk_src_mout_hpll_list[] = {
- [0] = &s5p_clk_27m,
-};
-
-static struct clksrc_sources clk_src_mout_hpll = {
- .sources = clk_src_mout_hpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_mout_hpll_list),
-};
-
-static struct clksrc_clk clk_mout_hpll = {
- .clk = {
- .name = "mout_hpll",
- },
- .sources = &clk_src_mout_hpll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_apll = {
- .clk = {
- .name = "div_apll",
- .parent = &clk_mout_apll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_arm = {
- .clk = {
- .name = "div_arm",
- .parent = &clk_div_apll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_d0_bus = {
- .clk = {
- .name = "div_d0_bus",
- .parent = &clk_div_arm.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_pclkd0 = {
- .clk = {
- .name = "div_pclkd0",
- .parent = &clk_div_d0_bus.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_secss = {
- .clk = {
- .name = "div_secss",
- .parent = &clk_div_d0_bus.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_apll2 = {
- .clk = {
- .name = "div_apll2",
- .parent = &clk_mout_apll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 },
-};
-
-static struct clk *clk_src_mout_am_list[] = {
- [0] = &clk_mout_mpll.clk,
- [1] = &clk_div_apll2.clk,
-};
-
-static struct clksrc_sources clk_src_mout_am = {
- .sources = clk_src_mout_am_list,
- .nr_sources = ARRAY_SIZE(clk_src_mout_am_list),
-};
-
-static struct clksrc_clk clk_mout_am = {
- .clk = {
- .name = "mout_am",
- },
- .sources = &clk_src_mout_am,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_d1_bus = {
- .clk = {
- .name = "div_d1_bus",
- .parent = &clk_mout_am.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_mpll2 = {
- .clk = {
- .name = "div_mpll2",
- .parent = &clk_mout_am.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_mpll = {
- .clk = {
- .name = "div_mpll",
- .parent = &clk_mout_am.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 },
-};
-
-static struct clk *clk_src_mout_onenand_list[] = {
- [0] = &clk_div_d0_bus.clk,
- [1] = &clk_div_d1_bus.clk,
-};
-
-static struct clksrc_sources clk_src_mout_onenand = {
- .sources = clk_src_mout_onenand_list,
- .nr_sources = ARRAY_SIZE(clk_src_mout_onenand_list),
-};
-
-static struct clksrc_clk clk_mout_onenand = {
- .clk = {
- .name = "mout_onenand",
- },
- .sources = &clk_src_mout_onenand,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk clk_div_onenand = {
- .clk = {
- .name = "div_onenand",
- .parent = &clk_mout_onenand.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 },
-};
-
-static struct clksrc_clk clk_div_pclkd1 = {
- .clk = {
- .name = "div_pclkd1",
- .parent = &clk_div_d1_bus.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_div_cam = {
- .clk = {
- .name = "div_cam",
- .parent = &clk_div_mpll2.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 },
-};
-
-static struct clksrc_clk clk_div_hdmi = {
- .clk = {
- .name = "div_hdmi",
- .parent = &clk_mout_hpll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 },
-};
-
-static u32 epll_div[][4] = {
- { 32750000, 131, 3, 4 },
- { 32768000, 131, 3, 4 },
- { 36000000, 72, 3, 3 },
- { 45000000, 90, 3, 3 },
- { 45158000, 90, 3, 3 },
- { 45158400, 90, 3, 3 },
- { 48000000, 96, 3, 3 },
- { 49125000, 131, 4, 3 },
- { 49152000, 131, 4, 3 },
- { 60000000, 120, 3, 3 },
- { 67737600, 226, 5, 3 },
- { 67738000, 226, 5, 3 },
- { 73800000, 246, 5, 3 },
- { 73728000, 246, 5, 3 },
- { 72000000, 144, 3, 3 },
- { 84000000, 168, 3, 3 },
- { 96000000, 96, 3, 2 },
- { 144000000, 144, 3, 2 },
- { 192000000, 96, 3, 1 }
-};
-
-static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int epll_con;
- unsigned int i;
-
- if (clk->rate == rate) /* Return if nothing changed */
- return 0;
-
- epll_con = __raw_readl(S5P_EPLL_CON);
-
- epll_con &= ~(PLL65XX_MDIV_MASK | PLL65XX_PDIV_MASK | PLL65XX_SDIV_MASK);
-
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con |= (epll_div[i][1] << PLL65XX_MDIV_SHIFT) |
- (epll_div[i][2] << PLL65XX_PDIV_SHIFT) |
- (epll_div[i][3] << PLL65XX_SDIV_SHIFT);
- break;
- }
- }
-
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
- return -EINVAL;
- }
-
- __raw_writel(epll_con, S5P_EPLL_CON);
-
- printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
- clk->rate, rate);
-
- clk->rate = rate;
-
- return 0;
-}
-
-static struct clk_ops s5pc100_epll_ops = {
- .get_rate = s5p_epll_get_rate,
- .set_rate = s5pc100_epll_set_rate,
-};
-
-static int s5pc100_d0_0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D00, clk, enable);
-}
-
-static int s5pc100_d0_1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D01, clk, enable);
-}
-
-static int s5pc100_d0_2_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D02, clk, enable);
-}
-
-static int s5pc100_d1_0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D10, clk, enable);
-}
-
-static int s5pc100_d1_1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D11, clk, enable);
-}
-
-static int s5pc100_d1_2_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D12, clk, enable);
-}
-
-static int s5pc100_d1_3_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D13, clk, enable);
-}
-
-static int s5pc100_d1_4_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D14, clk, enable);
-}
-
-static int s5pc100_d1_5_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_D15, clk, enable);
-}
-
-static int s5pc100_sclk0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_SCLK0, clk, enable);
-}
-
-static int s5pc100_sclk1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_SCLK1, clk, enable);
-}
-
-/*
- * The following clocks will be disabled during clock initialization. It is
- * recommended to keep the following clocks disabled until the driver requests
- * for enabling the clock.
- */
-static struct clk init_clocks_off[] = {
- {
- .name = "cssys",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "secss",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "g2d",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "mdma",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "cfcon",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "nfcon",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "onenandc",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "sdm",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_2_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "seckey",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_2_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "modemif",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "otg",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "usbhost",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "dma",
- .devname = "dma-pl330.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "dma",
- .devname = "dma-pl330.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "lcd",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "rotator",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "fimc",
- .devname = "s5p-fimc.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "fimc",
- .devname = "s5p-fimc.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "fimc",
- .devname = "s5p-fimc.2",
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "jpeg",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "mipi-dsim",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "mipi-csis",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_1_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "g3d",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "tv",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_2_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "vp",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_2_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "mixer",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_2_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "hdmi",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_2_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "mfc",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_2_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "apc",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "iec",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "systimer",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "watchdog",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "rtc",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "spi",
- .devname = "s5pc100-spi.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "spi",
- .devname = "s5pc100-spi.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "spi",
- .devname = "s5pc100-spi.2",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "irda",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = "ccan",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = "ccan",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 11),
- }, {
- .name = "hsitx",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 12),
- }, {
- .name = "hsirx",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 13),
- }, {
- .name = "ac97",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "pcm",
- .devname = "samsung-pcm.0",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "pcm",
- .devname = "samsung-pcm.1",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "spdif",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "adc",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "keypad",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.0",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 15),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.1",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 16),
- }, {
- .name = "mmc_48m",
- .devname = "s3c-sdhci.2",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 17),
- },
-};
-
-static struct clk clk_hsmmc2 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.2",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 7),
-};
-
-static struct clk clk_hsmmc1 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 6),
-};
-
-static struct clk clk_hsmmc0 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_0_ctrl,
- .ctrlbit = (1 << 5),
-};
-
-static struct clk clk_48m_spi0 = {
- .name = "spi_48m",
- .devname = "s5pc100-spi.0",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 7),
-};
-
-static struct clk clk_48m_spi1 = {
- .name = "spi_48m",
- .devname = "s5pc100-spi.1",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 8),
-};
-
-static struct clk clk_48m_spi2 = {
- .name = "spi_48m",
- .devname = "s5pc100-spi.2",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 9),
-};
-
-static struct clk clk_i2s0 = {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 0),
-};
-
-static struct clk clk_i2s1 = {
- .name = "iis",
- .devname = "samsung-i2s.1",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 1),
-};
-
-static struct clk clk_i2s2 = {
- .name = "iis",
- .devname = "samsung-i2s.2",
- .parent = &clk_div_pclkd1.clk,
- .enable = s5pc100_d1_5_ctrl,
- .ctrlbit = (1 << 2),
-};
-
-static struct clk clk_vclk54m = {
- .name = "vclk_54m",
- .rate = 54000000,
-};
-
-static struct clk clk_i2scdclk0 = {
- .name = "i2s_cdclk0",
-};
-
-static struct clk clk_i2scdclk1 = {
- .name = "i2s_cdclk1",
-};
-
-static struct clk clk_i2scdclk2 = {
- .name = "i2s_cdclk2",
-};
-
-static struct clk clk_pcmcdclk0 = {
- .name = "pcm_cdclk0",
-};
-
-static struct clk clk_pcmcdclk1 = {
- .name = "pcm_cdclk1",
-};
-
-static struct clk *clk_src_group1_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll2.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group1 = {
- .sources = clk_src_group1_list,
- .nr_sources = ARRAY_SIZE(clk_src_group1_list),
-};
-
-static struct clk *clk_src_group2_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_group2 = {
- .sources = clk_src_group2_list,
- .nr_sources = ARRAY_SIZE(clk_src_group2_list),
-};
-
-static struct clk *clk_src_group3_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_i2scdclk0,
- [4] = &clk_pcmcdclk0,
- [5] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group3 = {
- .sources = clk_src_group3_list,
- .nr_sources = ARRAY_SIZE(clk_src_group3_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "samsung-pcm.0",
- .ctrlbit = (1 << 8),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group3,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
-};
-
-static struct clk *clk_src_group4_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_i2scdclk1,
- [4] = &clk_pcmcdclk1,
- [5] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group4 = {
- .sources = clk_src_group4_list,
- .nr_sources = ARRAY_SIZE(clk_src_group4_list),
-};
-
-static struct clksrc_clk clk_sclk_audio1 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "samsung-pcm.1",
- .ctrlbit = (1 << 9),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group4,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
-};
-
-static struct clk *clk_src_group5_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_i2scdclk2,
- [4] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_group5 = {
- .sources = clk_src_group5_list,
- .nr_sources = ARRAY_SIZE(clk_src_group5_list),
-};
-
-static struct clksrc_clk clk_sclk_audio2 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "samsung-pcm.2",
- .ctrlbit = (1 << 10),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_group5,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
-};
-
-static struct clk *clk_src_group6_list[] = {
- [0] = &s5p_clk_27m,
- [1] = &clk_vclk54m,
- [2] = &clk_div_hdmi.clk,
-};
-
-static struct clksrc_sources clk_src_group6 = {
- .sources = clk_src_group6_list,
- .nr_sources = ARRAY_SIZE(clk_src_group6_list),
-};
-
-static struct clk *clk_src_group7_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_mout_hpll.clk,
- [3] = &clk_vclk54m,
-};
-
-static struct clksrc_sources clk_src_group7 = {
- .sources = clk_src_group7_list,
- .nr_sources = ARRAY_SIZE(clk_src_group7_list),
-};
-
-static struct clk *clk_src_mmc0_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
-};
-
-static struct clksrc_sources clk_src_mmc0 = {
- .sources = clk_src_mmc0_list,
- .nr_sources = ARRAY_SIZE(clk_src_mmc0_list),
-};
-
-static struct clk *clk_src_mmc12_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_mmc12 = {
- .sources = clk_src_mmc12_list,
- .nr_sources = ARRAY_SIZE(clk_src_mmc12_list),
-};
-
-static struct clk *clk_src_irda_usb_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_div_mpll.clk,
- [2] = &clk_fin_epll,
- [3] = &clk_mout_hpll.clk,
-};
-
-static struct clksrc_sources clk_src_irda_usb = {
- .sources = clk_src_irda_usb_list,
- .nr_sources = ARRAY_SIZE(clk_src_irda_usb_list),
-};
-
-static struct clk *clk_src_pwi_list[] = {
- [0] = &clk_fin_epll,
- [1] = &clk_mout_epll.clk,
- [2] = &clk_div_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_pwi = {
- .sources = clk_src_pwi_list,
- .nr_sources = ARRAY_SIZE(clk_src_pwi_list),
-};
-
-static struct clk *clk_sclk_spdif_list[] = {
- [0] = &clk_sclk_audio0.clk,
- [1] = &clk_sclk_audio1.clk,
- [2] = &clk_sclk_audio2.clk,
-};
-
-static struct clksrc_sources clk_src_sclk_spdif = {
- .sources = clk_sclk_spdif_list,
- .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list),
-};
-
-static struct clksrc_clk clk_sclk_spdif = {
- .clk = {
- .name = "sclk_spdif",
- .ctrlbit = (1 << 11),
- .enable = s5pc100_sclk1_ctrl,
- .ops = &s5p_sclk_spdif_ops,
- },
- .sources = &clk_src_sclk_spdif,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 },
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_mixer",
- .ctrlbit = (1 << 6),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_group6,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 },
- }, {
- .clk = {
- .name = "sclk_lcd",
- .ctrlbit = (1 << 0),
- .enable = s5pc100_sclk1_ctrl,
-
- },
- .sources = &clk_src_group7,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 12, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5p-fimc.0",
- .ctrlbit = (1 << 1),
- .enable = s5pc100_sclk1_ctrl,
-
- },
- .sources = &clk_src_group7,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5p-fimc.1",
- .ctrlbit = (1 << 2),
- .enable = s5pc100_sclk1_ctrl,
-
- },
- .sources = &clk_src_group7,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 20, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5p-fimc.2",
- .ctrlbit = (1 << 3),
- .enable = s5pc100_sclk1_ctrl,
-
- },
- .sources = &clk_src_group7,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 24, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_irda",
- .ctrlbit = (1 << 10),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_irda_usb,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_irda",
- .ctrlbit = (1 << 10),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_mmc12,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_pwi",
- .ctrlbit = (1 << 1),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_pwi,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 0, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 3 },
- }, {
- .clk = {
- .name = "sclk_uhost",
- .ctrlbit = (1 << 11),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_irda_usb,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 20, .size = 4 },
- },
-};
-
-static struct clksrc_clk clk_sclk_uart = {
- .clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 3),
- .enable = s5pc100_sclk0_ctrl,
- },
- .sources = &clk_src_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
- .ctrlbit = (1 << 12),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_mmc0,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
- .ctrlbit = (1 << 13),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_mmc12,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
- .ctrlbit = (1 << 14),
- .enable = s5pc100_sclk1_ctrl,
- },
- .sources = &clk_src_mmc12,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5pc100-spi.0",
- .ctrlbit = (1 << 4),
- .enable = s5pc100_sclk0_ctrl,
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5pc100-spi.1",
- .ctrlbit = (1 << 5),
- .enable = s5pc100_sclk0_ctrl,
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi2 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5pc100-spi.2",
- .ctrlbit = (1 << 6),
- .enable = s5pc100_sclk0_ctrl,
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_mout_mpll,
- &clk_mout_hpll,
- &clk_mout_href,
- &clk_mout_48m,
- &clk_div_apll,
- &clk_div_arm,
- &clk_div_d0_bus,
- &clk_div_pclkd0,
- &clk_div_secss,
- &clk_div_apll2,
- &clk_mout_am,
- &clk_div_d1_bus,
- &clk_div_mpll2,
- &clk_div_mpll,
- &clk_mout_onenand,
- &clk_div_onenand,
- &clk_div_pclkd1,
- &clk_div_cam,
- &clk_div_hdmi,
- &clk_sclk_audio0,
- &clk_sclk_audio1,
- &clk_sclk_audio2,
- &clk_sclk_spdif,
-};
-
-static struct clk *clk_cdev[] = {
- &clk_hsmmc0,
- &clk_hsmmc1,
- &clk_hsmmc2,
- &clk_48m_spi0,
- &clk_48m_spi1,
- &clk_48m_spi2,
- &clk_i2s0,
- &clk_i2s1,
- &clk_i2s2,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
- &clk_sclk_uart,
- &clk_sclk_mmc0,
- &clk_sclk_mmc1,
- &clk_sclk_mmc2,
- &clk_sclk_spi0,
- &clk_sclk_spi1,
- &clk_sclk_spi2,
-};
-
-void __init_or_cpufreq s5pc100_setup_clocks(void)
-{
- unsigned long xtal;
- unsigned long arm;
- unsigned long hclkd0;
- unsigned long hclkd1;
- unsigned long pclkd0;
- unsigned long pclkd1;
- unsigned long apll;
- unsigned long mpll;
- unsigned long epll;
- unsigned long hpll;
- unsigned int ptr;
-
- /* Set S5PC100 functions for clk_fout_epll */
- clk_fout_epll.enable = s5p_epll_enable;
- clk_fout_epll.ops = &s5pc100_epll_ops;
-
- printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
- xtal = clk_get_rate(&clk_xtal);
-
- printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
- apll = s5p_get_pll65xx(xtal, __raw_readl(S5P_APLL_CON));
- mpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_MPLL_CON));
- epll = s5p_get_pll65xx(xtal, __raw_readl(S5P_EPLL_CON));
- hpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_HPLL_CON));
-
- printk(KERN_INFO "S5PC100: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz, E=%ld.%ldMHz, H=%ld.%ldMHz\n",
- print_mhz(apll), print_mhz(mpll), print_mhz(epll), print_mhz(hpll));
-
- clk_fout_apll.rate = apll;
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_mout_hpll.clk.rate = hpll;
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-
- arm = clk_get_rate(&clk_div_arm.clk);
- hclkd0 = clk_get_rate(&clk_div_d0_bus.clk);
- pclkd0 = clk_get_rate(&clk_div_pclkd0.clk);
- hclkd1 = clk_get_rate(&clk_div_d1_bus.clk);
- pclkd1 = clk_get_rate(&clk_div_pclkd1.clk);
-
- printk(KERN_INFO "S5PC100: HCLKD0=%ld.%ldMHz, HCLKD1=%ld.%ldMHz, PCLKD0=%ld.%ldMHz, PCLKD1=%ld.%ldMHz\n",
- print_mhz(hclkd0), print_mhz(hclkd1), print_mhz(pclkd0), print_mhz(pclkd1));
-
- clk_f.rate = arm;
- clk_h.rate = hclkd1;
- clk_p.rate = pclkd1;
-}
-
-/*
- * The following clocks will be enabled during clock initialization.
- */
-static struct clk init_clocks[] = {
- {
- .name = "tzic",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "intc",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_0_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "ebi",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "intmem",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 4),
- }, {
- .name = "sromc",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "dmc",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "chipid",
- .parent = &clk_div_d0_bus.clk,
- .enable = s5pc100_d0_1_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "gpio",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.0",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.1",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 1),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.2",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 2),
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.3",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_4_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "timers",
- .parent = &clk_div_d1_bus.clk,
- .enable = s5pc100_d1_3_ctrl,
- .ctrlbit = (1 << 6),
- },
-};
-
-static struct clk *clks[] __initdata = {
- &clk_ext,
- &clk_i2scdclk0,
- &clk_i2scdclk1,
- &clk_i2scdclk2,
- &clk_pcmcdclk0,
- &clk_pcmcdclk1,
-};
-
-static struct clk_lookup s5pc100_clk_lookup[] = {
- CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
- CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uart.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
- CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
- CLKDEV_INIT("s5pc100-spi.0", "spi_busclk1", &clk_48m_spi0),
- CLKDEV_INIT("s5pc100-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
- CLKDEV_INIT("s5pc100-spi.1", "spi_busclk1", &clk_48m_spi1),
- CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
- CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
- CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
- CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
- CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
-};
-
-void __init s5pc100_register_clocks(void)
-{
- int ptr;
-
- s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
- for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
- s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- clkdev_add_table(s5pc100_clk_lookup, ARRAY_SIZE(s5pc100_clk_lookup));
-
- s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
- for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
- s3c_disable_clocks(clk_cdev[ptr], 1);
-
- s3c24xx_register_clock(&dummy_apb_pclk);
-}
diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c
deleted file mode 100644
index 6a41bf7dacf6..000000000000
--- a/arch/arm/mach-s5pc100/common.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * Common Codes for S5PC100
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/reboot.h>
-
-#include <asm/irq.h>
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/ata-core.h>
-#include <plat/fb-core.h>
-#include <plat/iic-core.h>
-#include <plat/onenand-core.h>
-#include <plat/pwm-core.h>
-#include <plat/spi-core.h>
-#include <plat/watchdog-reset.h>
-
-#include "common.h"
-
-static const char name_s5pc100[] = "S5PC100";
-
-static struct cpu_table cpu_ids[] __initdata = {
- {
- .idcode = S5PC100_CPU_ID,
- .idmask = S5PC100_CPU_MASK,
- .map_io = s5pc100_map_io,
- .init_clocks = s5pc100_init_clocks,
- .init_uarts = s5pc100_init_uarts,
- .init = s5pc100_init,
- .name = name_s5pc100,
- },
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5pc100_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S5P_VA_CHIPID,
- .pfn = __phys_to_pfn(S5PC100_PA_CHIPID),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_SYS,
- .pfn = __phys_to_pfn(S5PC100_PA_SYSCON),
- .length = SZ_64K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_TIMER,
- .pfn = __phys_to_pfn(S5PC100_PA_TIMER),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_WATCHDOG,
- .pfn = __phys_to_pfn(S5PC100_PA_WATCHDOG),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_SROMC,
- .pfn = __phys_to_pfn(S5PC100_PA_SROMC),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_SYSTIMER,
- .pfn = __phys_to_pfn(S5PC100_PA_SYSTIMER),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_GPIO,
- .pfn = __phys_to_pfn(S5PC100_PA_GPIO),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC0,
- .pfn = __phys_to_pfn(S5PC100_PA_VIC0),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC1,
- .pfn = __phys_to_pfn(S5PC100_PA_VIC1),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC2,
- .pfn = __phys_to_pfn(S5PC100_PA_VIC2),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_UART,
- .pfn = __phys_to_pfn(S3C_PA_UART),
- .length = SZ_512K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5PC100_VA_OTHERS,
- .pfn = __phys_to_pfn(S5PC100_PA_OTHERS),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }
-};
-
-static struct samsung_pwm_variant s5pc100_pwm_variant = {
- .bits = 32,
- .div_base = 0,
- .has_tint_cstat = true,
- .tclk_mask = (1 << 5),
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
- s5pc100_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
- s5pc100_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
- unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
- IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
- IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
- };
-
- samsung_pwm_clocksource_init(S3C_VA_TIMER,
- timer_irqs, &s5pc100_pwm_variant);
-}
-
-/*
- * s5pc100_map_io
- *
- * register the standard CPU IO areas
- */
-
-void __init s5pc100_init_io(struct map_desc *mach_desc, int size)
-{
- /* initialize the io descriptors we need for initialization */
- iotable_init(s5pc100_iodesc, ARRAY_SIZE(s5pc100_iodesc));
- if (mach_desc)
- iotable_init(mach_desc, size);
-
- /* detect cpu id and rev. */
- s5p_init_cpu(S5P_VA_CHIPID);
-
- s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
-
- samsung_pwm_set_platdata(&s5pc100_pwm_variant);
-}
-
-void __init s5pc100_map_io(void)
-{
- /* initialise device information early */
- s5pc100_default_sdhci0();
- s5pc100_default_sdhci1();
- s5pc100_default_sdhci2();
-
- s3c_adc_setname("s3c64xx-adc");
-
- /* the i2c devices are directly compatible with s3c2440 */
- s3c_i2c0_setname("s3c2440-i2c");
- s3c_i2c1_setname("s3c2440-i2c");
-
- s3c_onenand_setname("s5pc100-onenand");
- s3c_fb_setname("s5pc100-fb");
- s3c_cfcon_setname("s5pc100-pata");
-
- s3c64xx_spi_setname("s5pc100-spi");
-}
-
-void __init s5pc100_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
- s5pc100_register_clocks();
- s5pc100_setup_clocks();
- samsung_wdt_reset_init(S3C_VA_WATCHDOG);
-}
-
-void __init s5pc100_init_irq(void)
-{
- u32 vic[] = {~0, ~0, ~0};
-
- /* VIC0, VIC1, and VIC2 are fully populated. */
- s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-static struct bus_type s5pc100_subsys = {
- .name = "s5pc100-core",
- .dev_name = "s5pc100-core",
-};
-
-static struct device s5pc100_dev = {
- .bus = &s5pc100_subsys,
-};
-
-static int __init s5pc100_core_init(void)
-{
- return subsys_system_register(&s5pc100_subsys, NULL);
-}
-core_initcall(s5pc100_core_init);
-
-int __init s5pc100_init(void)
-{
- printk(KERN_INFO "S5PC100: Initializing architecture\n");
- return device_register(&s5pc100_dev);
-}
-
-/* uart registration process */
-
-void __init s5pc100_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
-}
-
-void s5pc100_restart(enum reboot_mode mode, const char *cmd)
-{
- if (mode != REBOOT_SOFT)
- samsung_wdt_reset();
-
- soft_restart(0);
-}
diff --git a/arch/arm/mach-s5pc100/common.h b/arch/arm/mach-s5pc100/common.h
deleted file mode 100644
index 08d782d65d7b..000000000000
--- a/arch/arm/mach-s5pc100/common.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Common Header for S5PC100 machines
- *
- * 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 __ARCH_ARM_MACH_S5PC100_COMMON_H
-#define __ARCH_ARM_MACH_S5PC100_COMMON_H
-
-#include <linux/reboot.h>
-
-void s5pc100_init_io(struct map_desc *mach_desc, int size);
-void s5pc100_init_irq(void);
-
-void s5pc100_register_clocks(void);
-void s5pc100_setup_clocks(void);
-
-void s5pc100_restart(enum reboot_mode mode, const char *cmd);
-
-extern int s5pc100_init(void);
-extern void s5pc100_map_io(void);
-extern void s5pc100_init_clocks(int xtal);
-extern void s5pc100_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-#endif /* __ARCH_ARM_MACH_S5PC100_COMMON_H */
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c
deleted file mode 100644
index 46f488b09391..000000000000
--- a/arch/arm/mach-s5pc100/dev-audio.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static int s5pc100_cfg_i2s(struct platform_device *pdev)
-{
- /* configure GPIO for i2s port */
- switch (pdev->id) {
- case 0: /* Dedicated pins */
- break;
- case 1:
- s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2));
- break;
- case 2:
- s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4));
- break;
- default:
- printk(KERN_ERR "Invalid Device %d\n", pdev->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
- .cfg_gpio = s5pc100_cfg_i2s,
- .type = {
- .i2s = {
- .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
- | QUIRK_NEED_RSTCLR,
- },
- },
-};
-
-static struct resource s5pc100_iis0_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_I2S0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
- [3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
-};
-
-struct platform_device s5pc100_device_iis0 = {
- .name = "samsung-i2s",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5pc100_iis0_resource),
- .resource = s5pc100_iis0_resource,
- .dev = {
- .platform_data = &i2sv5_pdata,
- },
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
- .cfg_gpio = s5pc100_cfg_i2s,
-};
-
-static struct resource s5pc100_iis1_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_I2S1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5pc100_device_iis1 = {
- .name = "samsung-i2s",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5pc100_iis1_resource),
- .resource = s5pc100_iis1_resource,
- .dev = {
- .platform_data = &i2sv3_pdata,
- },
-};
-
-static struct resource s5pc100_iis2_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_I2S2, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5pc100_device_iis2 = {
- .name = "samsung-i2s",
- .id = 2,
- .num_resources = ARRAY_SIZE(s5pc100_iis2_resource),
- .resource = s5pc100_iis2_resource,
- .dev = {
- .platform_data = &i2sv3_pdata,
- },
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pc100_pcm_cfg_gpio(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(5));
- break;
-
- case 1:
- s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(3));
- break;
-
- default:
- printk(KERN_DEBUG "Invalid PCM Controller number!");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
- .cfg_gpio = s5pc100_pcm_cfg_gpio,
-};
-
-static struct resource s5pc100_pcm0_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_PCM0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5pc100_device_pcm0 = {
- .name = "samsung-pcm",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5pc100_pcm0_resource),
- .resource = s5pc100_pcm0_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
-
-static struct resource s5pc100_pcm1_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_PCM1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
-};
-
-struct platform_device s5pc100_device_pcm1 = {
- .name = "samsung-pcm",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5pc100_pcm1_resource),
- .resource = s5pc100_pcm1_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev)
-{
- return s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pc100_ac97_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_AC97, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
- [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
- [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
- [4] = DEFINE_RES_IRQ(IRQ_AC97),
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
- .cfg_gpio = s5pc100_ac97_cfg_gpio,
-};
-
-static u64 s5pc100_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pc100_device_ac97 = {
- .name = "samsung-ac97",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pc100_ac97_resource),
- .resource = s5pc100_ac97_resource,
- .dev = {
- .platform_data = &s3c_ac97_pdata,
- .dma_mask = &s5pc100_ac97_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-/* S/PDIF Controller platform_device */
-static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev)
-{
- s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3));
-
- return 0;
-}
-
-static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev)
-{
- s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3));
-
- return 0;
-}
-
-static struct resource s5pc100_spdif_resource[] = {
- [0] = DEFINE_RES_MEM(S5PC100_PA_SPDIF, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_SPDIF),
-};
-
-static struct s3c_audio_pdata s5p_spdif_pdata = {
- .cfg_gpio = s5pc100_spdif_cfg_gpd,
-};
-
-static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pc100_device_spdif = {
- .name = "samsung-spdif",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pc100_spdif_resource),
- .resource = s5pc100_spdif_resource,
- .dev = {
- .platform_data = &s5p_spdif_pdata,
- .dma_mask = &s5pc100_spdif_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-void __init s5pc100_spdif_setup_gpio(int gpio)
-{
- if (gpio == S5PC100_SPDIF_GPD)
- s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd;
- else
- s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3;
-}
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
deleted file mode 100644
index b1418409709e..000000000000
--- a/arch/arm/mach-s5pc100/dma.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/dma.h>
-
-static u8 pdma0_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_IRDA,
- DMACH_I2S0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0S_TX,
- DMACH_I2S1_RX,
- DMACH_I2S1_TX,
- DMACH_I2S2_RX,
- DMACH_I2S2_TX,
- DMACH_SPI0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI1_RX,
- DMACH_SPI1_TX,
- DMACH_SPI2_RX,
- DMACH_SPI2_TX,
- DMACH_AC97_MICIN,
- DMACH_AC97_PCMIN,
- DMACH_AC97_PCMOUT,
- DMACH_EXTERNAL,
- DMACH_PWM,
- DMACH_SPDIF,
- DMACH_HSI_RX,
- DMACH_HSI_TX,
-};
-
-static struct dma_pl330_platdata s5pc100_pdma0_pdata = {
- .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
- .peri_id = pdma0_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pc100_pdma0, "dma-pl330.0", 0x00041330,
- S5PC100_PA_PDMA0, {IRQ_PDMA0}, &s5pc100_pdma0_pdata);
-
-static u8 pdma1_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_IRDA,
- DMACH_I2S0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0S_TX,
- DMACH_I2S1_RX,
- DMACH_I2S1_TX,
- DMACH_I2S2_RX,
- DMACH_I2S2_TX,
- DMACH_SPI0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI1_RX,
- DMACH_SPI1_TX,
- DMACH_SPI2_RX,
- DMACH_SPI2_TX,
- DMACH_PCM0_RX,
- DMACH_PCM0_TX,
- DMACH_PCM1_RX,
- DMACH_PCM1_TX,
- DMACH_MSM_REQ0,
- DMACH_MSM_REQ1,
- DMACH_MSM_REQ2,
- DMACH_MSM_REQ3,
-};
-
-static struct dma_pl330_platdata s5pc100_pdma1_pdata = {
- .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
- .peri_id = pdma1_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pc100_pdma1, "dma-pl330.1", 0x00041330,
- S5PC100_PA_PDMA1, {IRQ_PDMA1}, &s5pc100_pdma1_pdata);
-
-static int __init s5pc100_dma_init(void)
-{
- dma_cap_set(DMA_SLAVE, s5pc100_pdma0_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5pc100_pdma0_pdata.cap_mask);
- amba_device_register(&s5pc100_pdma0_device, &iomem_resource);
-
- dma_cap_set(DMA_SLAVE, s5pc100_pdma1_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5pc100_pdma1_pdata.cap_mask);
- amba_device_register(&s5pc100_pdma1_device, &iomem_resource);
-
- return 0;
-}
-arch_initcall(s5pc100_dma_init);
diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S
deleted file mode 100644
index 22c23859e45e..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/debug-macro.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/debug-macro.S
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- *
- * Based on mach-s3c6400/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <linux/serial_s3c.h>
-#include <mach/map.h>
-
- /* note, for the boot process to work we have to keep the UART
- * virtual address aligned to an 1MiB boundary for the L1
- * mapping the head code makes. We keep the UART virtual address
- * aligned and add in the offset when we load the value here.
- */
-
- .macro addruart, rp, rv, tmp
- ldr \rp, = S3C_PA_UART
- ldr \rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
- add \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
- add \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
- .endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <debug/samsung.S>
diff --git a/arch/arm/mach-s5pc100/include/mach/entry-macro.S b/arch/arm/mach-s5pc100/include/mach/entry-macro.S
deleted file mode 100644
index bad0700457db..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/entry-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/entry-macro.S
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * Based on mach-s3c6400/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for the Samsung S5PC1XX series
- *
- * 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.
-*/
-
- .macro get_irqnr_preamble, base, tmp
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- .endm
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h
deleted file mode 100644
index 5e1a924b595f..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/gpio.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/gpio.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - GPIO lib support
- *
- * Base on mach-s3c6400/include/mach/gpio.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* GPIO bank sizes */
-#define S5PC100_GPIO_A0_NR (8)
-#define S5PC100_GPIO_A1_NR (5)
-#define S5PC100_GPIO_B_NR (8)
-#define S5PC100_GPIO_C_NR (5)
-#define S5PC100_GPIO_D_NR (7)
-#define S5PC100_GPIO_E0_NR (8)
-#define S5PC100_GPIO_E1_NR (6)
-#define S5PC100_GPIO_F0_NR (8)
-#define S5PC100_GPIO_F1_NR (8)
-#define S5PC100_GPIO_F2_NR (8)
-#define S5PC100_GPIO_F3_NR (4)
-#define S5PC100_GPIO_G0_NR (8)
-#define S5PC100_GPIO_G1_NR (3)
-#define S5PC100_GPIO_G2_NR (7)
-#define S5PC100_GPIO_G3_NR (7)
-#define S5PC100_GPIO_H0_NR (8)
-#define S5PC100_GPIO_H1_NR (8)
-#define S5PC100_GPIO_H2_NR (8)
-#define S5PC100_GPIO_H3_NR (8)
-#define S5PC100_GPIO_I_NR (8)
-#define S5PC100_GPIO_J0_NR (8)
-#define S5PC100_GPIO_J1_NR (5)
-#define S5PC100_GPIO_J2_NR (8)
-#define S5PC100_GPIO_J3_NR (8)
-#define S5PC100_GPIO_J4_NR (4)
-#define S5PC100_GPIO_K0_NR (8)
-#define S5PC100_GPIO_K1_NR (6)
-#define S5PC100_GPIO_K2_NR (8)
-#define S5PC100_GPIO_K3_NR (8)
-#define S5PC100_GPIO_L0_NR (8)
-#define S5PC100_GPIO_L1_NR (8)
-#define S5PC100_GPIO_L2_NR (8)
-#define S5PC100_GPIO_L3_NR (8)
-#define S5PC100_GPIO_L4_NR (8)
-
-/* GPIO bank numbes */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5PC100_GPIO_NEXT(__gpio) \
- ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
- S5PC100_GPIO_A0_START = 0,
- S5PC100_GPIO_A1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A0),
- S5PC100_GPIO_B_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A1),
- S5PC100_GPIO_C_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_B),
- S5PC100_GPIO_D_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_C),
- S5PC100_GPIO_E0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_D),
- S5PC100_GPIO_E1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E0),
- S5PC100_GPIO_F0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E1),
- S5PC100_GPIO_F1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F0),
- S5PC100_GPIO_F2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F1),
- S5PC100_GPIO_F3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F2),
- S5PC100_GPIO_G0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F3),
- S5PC100_GPIO_G1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G0),
- S5PC100_GPIO_G2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G1),
- S5PC100_GPIO_G3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G2),
- S5PC100_GPIO_H0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G3),
- S5PC100_GPIO_H1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H0),
- S5PC100_GPIO_H2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H1),
- S5PC100_GPIO_H3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H2),
- S5PC100_GPIO_I_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H3),
- S5PC100_GPIO_J0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_I),
- S5PC100_GPIO_J1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J0),
- S5PC100_GPIO_J2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J1),
- S5PC100_GPIO_J3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J2),
- S5PC100_GPIO_J4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J3),
- S5PC100_GPIO_K0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J4),
- S5PC100_GPIO_K1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K0),
- S5PC100_GPIO_K2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K1),
- S5PC100_GPIO_K3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K2),
- S5PC100_GPIO_L0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K3),
- S5PC100_GPIO_L1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L0),
- S5PC100_GPIO_L2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L1),
- S5PC100_GPIO_L3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L2),
- S5PC100_GPIO_L4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L3),
- S5PC100_GPIO_END = S5PC100_GPIO_NEXT(S5PC100_GPIO_L4),
-};
-
-/* S5PC100 GPIO number definitions. */
-#define S5PC100_GPA0(_nr) (S5PC100_GPIO_A0_START + (_nr))
-#define S5PC100_GPA1(_nr) (S5PC100_GPIO_A1_START + (_nr))
-#define S5PC100_GPB(_nr) (S5PC100_GPIO_B_START + (_nr))
-#define S5PC100_GPC(_nr) (S5PC100_GPIO_C_START + (_nr))
-#define S5PC100_GPD(_nr) (S5PC100_GPIO_D_START + (_nr))
-#define S5PC100_GPE0(_nr) (S5PC100_GPIO_E0_START + (_nr))
-#define S5PC100_GPE1(_nr) (S5PC100_GPIO_E1_START + (_nr))
-#define S5PC100_GPF0(_nr) (S5PC100_GPIO_F0_START + (_nr))
-#define S5PC100_GPF1(_nr) (S5PC100_GPIO_F1_START + (_nr))
-#define S5PC100_GPF2(_nr) (S5PC100_GPIO_F2_START + (_nr))
-#define S5PC100_GPF3(_nr) (S5PC100_GPIO_F3_START + (_nr))
-#define S5PC100_GPG0(_nr) (S5PC100_GPIO_G0_START + (_nr))
-#define S5PC100_GPG1(_nr) (S5PC100_GPIO_G1_START + (_nr))
-#define S5PC100_GPG2(_nr) (S5PC100_GPIO_G2_START + (_nr))
-#define S5PC100_GPG3(_nr) (S5PC100_GPIO_G3_START + (_nr))
-#define S5PC100_GPH0(_nr) (S5PC100_GPIO_H0_START + (_nr))
-#define S5PC100_GPH1(_nr) (S5PC100_GPIO_H1_START + (_nr))
-#define S5PC100_GPH2(_nr) (S5PC100_GPIO_H2_START + (_nr))
-#define S5PC100_GPH3(_nr) (S5PC100_GPIO_H3_START + (_nr))
-#define S5PC100_GPI(_nr) (S5PC100_GPIO_I_START + (_nr))
-#define S5PC100_GPJ0(_nr) (S5PC100_GPIO_J0_START + (_nr))
-#define S5PC100_GPJ1(_nr) (S5PC100_GPIO_J1_START + (_nr))
-#define S5PC100_GPJ2(_nr) (S5PC100_GPIO_J2_START + (_nr))
-#define S5PC100_GPJ3(_nr) (S5PC100_GPIO_J3_START + (_nr))
-#define S5PC100_GPJ4(_nr) (S5PC100_GPIO_J4_START + (_nr))
-#define S5PC100_GPK0(_nr) (S5PC100_GPIO_K0_START + (_nr))
-#define S5PC100_GPK1(_nr) (S5PC100_GPIO_K1_START + (_nr))
-#define S5PC100_GPK2(_nr) (S5PC100_GPIO_K2_START + (_nr))
-#define S5PC100_GPK3(_nr) (S5PC100_GPIO_K3_START + (_nr))
-#define S5PC100_GPL0(_nr) (S5PC100_GPIO_L0_START + (_nr))
-#define S5PC100_GPL1(_nr) (S5PC100_GPIO_L1_START + (_nr))
-#define S5PC100_GPL2(_nr) (S5PC100_GPIO_L2_START + (_nr))
-#define S5PC100_GPL3(_nr) (S5PC100_GPIO_L3_START + (_nr))
-#define S5PC100_GPL4(_nr) (S5PC100_GPIO_L4_START + (_nr))
-
-/* It used the end of the S5PC100 gpios */
-#define S3C_GPIO_END S5PC100_GPIO_END
-
-/* define the number of gpios we need to the one after the MP04() range */
-#define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/hardware.h b/arch/arm/mach-s5pc100/include/mach/hardware.h
deleted file mode 100644
index 6b38618c2fd9..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/hardware.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/hardware.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - Hardware support
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
deleted file mode 100644
index d2eb4757381f..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/irqs.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - IRQ definitions
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0: system, DMA, timer */
-#define IRQ_EINT16_31 S5P_IRQ_VIC0(16)
-#define IRQ_BATF S5P_IRQ_VIC0(17)
-#define IRQ_MDMA S5P_IRQ_VIC0(18)
-#define IRQ_PDMA0 S5P_IRQ_VIC0(19)
-#define IRQ_PDMA1 S5P_IRQ_VIC0(20)
-#define IRQ_TIMER0_VIC S5P_IRQ_VIC0(21)
-#define IRQ_TIMER1_VIC S5P_IRQ_VIC0(22)
-#define IRQ_TIMER2_VIC S5P_IRQ_VIC0(23)
-#define IRQ_TIMER3_VIC S5P_IRQ_VIC0(24)
-#define IRQ_TIMER4_VIC S5P_IRQ_VIC0(25)
-#define IRQ_SYSTIMER S5P_IRQ_VIC0(26)
-#define IRQ_WDT S5P_IRQ_VIC0(27)
-#define IRQ_RTC_ALARM S5P_IRQ_VIC0(28)
-#define IRQ_RTC_TIC S5P_IRQ_VIC0(29)
-#define IRQ_GPIOINT S5P_IRQ_VIC0(30)
-
-/* VIC1: ARM, power, memory, connectivity */
-#define IRQ_PMU S5P_IRQ_VIC1(0)
-#define IRQ_CORTEX1 S5P_IRQ_VIC1(1)
-#define IRQ_CORTEX2 S5P_IRQ_VIC1(2)
-#define IRQ_CORTEX3 S5P_IRQ_VIC1(3)
-#define IRQ_CORTEX4 S5P_IRQ_VIC1(4)
-#define IRQ_IEMAPC S5P_IRQ_VIC1(5)
-#define IRQ_IEMIEC S5P_IRQ_VIC1(6)
-#define IRQ_ONENAND S5P_IRQ_VIC1(7)
-#define IRQ_NFC S5P_IRQ_VIC1(8)
-#define IRQ_CFCON S5P_IRQ_VIC1(9)
-#define IRQ_UART0 S5P_IRQ_VIC1(10)
-#define IRQ_UART1 S5P_IRQ_VIC1(11)
-#define IRQ_UART2 S5P_IRQ_VIC1(12)
-#define IRQ_UART3 S5P_IRQ_VIC1(13)
-#define IRQ_IIC S5P_IRQ_VIC1(14)
-#define IRQ_SPI0 S5P_IRQ_VIC1(15)
-#define IRQ_SPI1 S5P_IRQ_VIC1(16)
-#define IRQ_SPI2 S5P_IRQ_VIC1(17)
-#define IRQ_IRDA S5P_IRQ_VIC1(18)
-#define IRQ_IIC2 S5P_IRQ_VIC1(19)
-#define IRQ_IIC3 S5P_IRQ_VIC1(20)
-#define IRQ_HSIRX S5P_IRQ_VIC1(21)
-#define IRQ_HSITX S5P_IRQ_VIC1(22)
-#define IRQ_UHOST S5P_IRQ_VIC1(23)
-#define IRQ_OTG S5P_IRQ_VIC1(24)
-#define IRQ_MSM S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC0 S5P_IRQ_VIC1(26)
-#define IRQ_HSMMC1 S5P_IRQ_VIC1(27)
-#define IRQ_HSMMC2 S5P_IRQ_VIC1(28)
-#define IRQ_MIPICSI S5P_IRQ_VIC1(29)
-#define IRQ_MIPIDSI S5P_IRQ_VIC1(30)
-
-/* VIC2: multimedia, audio, security */
-#define IRQ_LCD0 S5P_IRQ_VIC2(0)
-#define IRQ_LCD1 S5P_IRQ_VIC2(1)
-#define IRQ_LCD2 S5P_IRQ_VIC2(2)
-#define IRQ_LCD3 S5P_IRQ_VIC2(3)
-#define IRQ_ROTATOR S5P_IRQ_VIC2(4)
-#define IRQ_FIMC0 S5P_IRQ_VIC2(5)
-#define IRQ_FIMC1 S5P_IRQ_VIC2(6)
-#define IRQ_FIMC2 S5P_IRQ_VIC2(7)
-#define IRQ_JPEG S5P_IRQ_VIC2(8)
-#define IRQ_2D S5P_IRQ_VIC2(9)
-#define IRQ_3D S5P_IRQ_VIC2(10)
-#define IRQ_MIXER S5P_IRQ_VIC2(11)
-#define IRQ_HDMI S5P_IRQ_VIC2(12)
-#define IRQ_IIC1 S5P_IRQ_VIC2(13)
-#define IRQ_MFC S5P_IRQ_VIC2(14)
-#define IRQ_TVENC S5P_IRQ_VIC2(15)
-#define IRQ_I2S0 S5P_IRQ_VIC2(16)
-#define IRQ_I2S1 S5P_IRQ_VIC2(17)
-#define IRQ_I2S2 S5P_IRQ_VIC2(18)
-#define IRQ_AC97 S5P_IRQ_VIC2(19)
-#define IRQ_PCM0 S5P_IRQ_VIC2(20)
-#define IRQ_PCM1 S5P_IRQ_VIC2(21)
-#define IRQ_SPDIF S5P_IRQ_VIC2(22)
-#define IRQ_ADC S5P_IRQ_VIC2(23)
-#define IRQ_PENDN S5P_IRQ_VIC2(24)
-#define IRQ_TC IRQ_PENDN
-#define IRQ_KEYPAD S5P_IRQ_VIC2(25)
-#define IRQ_CG S5P_IRQ_VIC2(26)
-#define IRQ_SEC S5P_IRQ_VIC2(27)
-#define IRQ_SECRX S5P_IRQ_VIC2(28)
-#define IRQ_SECTX S5P_IRQ_VIC2(29)
-#define IRQ_SDMIRQ S5P_IRQ_VIC2(30)
-#define IRQ_SDMFIQ S5P_IRQ_VIC2(31)
-#define IRQ_VIC_END S5P_IRQ_VIC2(31)
-
-#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
-#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
-
-/* GPIO interrupt */
-#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
-#define S5P_GPIOINT_GROUP_MAXNR 21
-
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
-
-/* Compatibility */
-#define IRQ_LCD_FIFO IRQ_LCD0
-#define IRQ_LCD_VSYNC IRQ_LCD1
-#define IRQ_LCD_SYSTEM IRQ_LCD2
-
-#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
deleted file mode 100644
index 2550b6112b82..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/map.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5PC100_PA_SDRAM 0x20000000
-
-#define S5PC100_PA_ONENAND 0xE7100000
-#define S5PC100_PA_ONENAND_BUF 0xB0000000
-
-#define S5PC100_PA_CHIPID 0xE0000000
-
-#define S5PC100_PA_SYSCON 0xE0100000
-
-#define S5PC100_PA_OTHERS 0xE0200000
-
-#define S5PC100_PA_GPIO 0xE0300000
-
-#define S5PC100_PA_VIC0 0xE4000000
-#define S5PC100_PA_VIC1 0xE4100000
-#define S5PC100_PA_VIC2 0xE4200000
-
-#define S5PC100_PA_SROMC 0xE7000000
-
-#define S5PC100_PA_CFCON 0xE7800000
-
-#define S5PC100_PA_MDMA 0xE8100000
-#define S5PC100_PA_PDMA0 0xE9000000
-#define S5PC100_PA_PDMA1 0xE9200000
-
-#define S5PC100_PA_TIMER 0xEA000000
-#define S5PC100_PA_SYSTIMER 0xEA100000
-#define S5PC100_PA_WATCHDOG 0xEA200000
-#define S5PC100_PA_RTC 0xEA300000
-
-#define S5PC100_PA_UART 0xEC000000
-
-#define S5PC100_PA_IIC0 0xEC100000
-#define S5PC100_PA_IIC1 0xEC200000
-
-#define S5PC100_PA_SPI0 0xEC300000
-#define S5PC100_PA_SPI1 0xEC400000
-#define S5PC100_PA_SPI2 0xEC500000
-
-#define S5PC100_PA_USB_HSOTG 0xED200000
-#define S5PC100_PA_USB_HSPHY 0xED300000
-
-#define S5PC100_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000))
-
-#define S5PC100_PA_FB 0xEE000000
-
-#define S5PC100_PA_FIMC0 0xEE200000
-#define S5PC100_PA_FIMC1 0xEE300000
-#define S5PC100_PA_FIMC2 0xEE400000
-
-#define S5PC100_PA_I2S0 0xF2000000
-#define S5PC100_PA_I2S1 0xF2100000
-#define S5PC100_PA_I2S2 0xF2200000
-
-#define S5PC100_PA_AC97 0xF2300000
-
-#define S5PC100_PA_PCM0 0xF2400000
-#define S5PC100_PA_PCM1 0xF2500000
-
-#define S5PC100_PA_SPDIF 0xF2600000
-
-#define S5PC100_PA_TSADC 0xF3000000
-
-#define S5PC100_PA_KEYPAD 0xF3100000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_FB S5PC100_PA_FB
-#define S3C_PA_HSMMC0 S5PC100_PA_HSMMC(0)
-#define S3C_PA_HSMMC1 S5PC100_PA_HSMMC(1)
-#define S3C_PA_HSMMC2 S5PC100_PA_HSMMC(2)
-#define S3C_PA_IIC S5PC100_PA_IIC0
-#define S3C_PA_IIC1 S5PC100_PA_IIC1
-#define S3C_PA_KEYPAD S5PC100_PA_KEYPAD
-#define S3C_PA_ONENAND S5PC100_PA_ONENAND
-#define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF
-#define S3C_PA_RTC S5PC100_PA_RTC
-#define S3C_PA_TSADC S5PC100_PA_TSADC
-#define S3C_PA_USB_HSOTG S5PC100_PA_USB_HSOTG
-#define S3C_PA_USB_HSPHY S5PC100_PA_USB_HSPHY
-#define S3C_PA_WDT S5PC100_PA_WATCHDOG
-#define S3C_PA_SPI0 S5PC100_PA_SPI0
-#define S3C_PA_SPI1 S5PC100_PA_SPI1
-#define S3C_PA_SPI2 S5PC100_PA_SPI2
-
-#define S5P_PA_CHIPID S5PC100_PA_CHIPID
-#define S5P_PA_FIMC0 S5PC100_PA_FIMC0
-#define S5P_PA_FIMC1 S5PC100_PA_FIMC1
-#define S5P_PA_FIMC2 S5PC100_PA_FIMC2
-#define S5P_PA_SDRAM S5PC100_PA_SDRAM
-#define S5P_PA_SROMC S5PC100_PA_SROMC
-#define S5P_PA_SYSCON S5PC100_PA_SYSCON
-#define S5P_PA_TIMER S5PC100_PA_TIMER
-
-#define SAMSUNG_PA_ADC S5PC100_PA_TSADC
-#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON
-#define SAMSUNG_PA_KEYPAD S5PC100_PA_KEYPAD
-#define SAMSUNG_PA_TIMER S5PC100_PA_TIMER
-
-#define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000)
-
-#define S3C_SZ_ONENAND_BUF (SZ_256M - SZ_32M)
-
-/* UART */
-
-#define S3C_PA_UART S5PC100_PA_UART
-
-#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0 S5P_PA_UART(0)
-#define S5P_PA_UART1 S5P_PA_UART(1)
-#define S5P_PA_UART2 S5P_PA_UART(2)
-#define S5P_PA_UART3 S5P_PA_UART(3)
-
-#define S5P_SZ_UART SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-clock.h b/arch/arm/mach-s5pc100/include/mach/regs-clock.h
deleted file mode 100644
index bc92da2e0ba2..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/regs-clock.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/regs-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PC100 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
-
-#define S5PC100_REG_OTHERS(x) (S5PC100_VA_OTHERS + (x))
-
-#define S5P_APLL_LOCK S5P_CLKREG(0x00)
-#define S5P_MPLL_LOCK S5P_CLKREG(0x04)
-#define S5P_EPLL_LOCK S5P_CLKREG(0x08)
-#define S5P_HPLL_LOCK S5P_CLKREG(0x0C)
-
-#define S5P_APLL_CON S5P_CLKREG(0x100)
-#define S5P_MPLL_CON S5P_CLKREG(0x104)
-#define S5P_EPLL_CON S5P_CLKREG(0x108)
-#define S5P_HPLL_CON S5P_CLKREG(0x10C)
-
-#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
-#define S5P_CLK_SRC1 S5P_CLKREG(0x204)
-#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
-#define S5P_CLK_SRC3 S5P_CLKREG(0x20C)
-
-#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
-#define S5P_CLK_DIV1 S5P_CLKREG(0x304)
-#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
-#define S5P_CLK_DIV3 S5P_CLKREG(0x30C)
-#define S5P_CLK_DIV4 S5P_CLKREG(0x310)
-
-#define S5P_CLK_OUT S5P_CLKREG(0x400)
-
-#define S5P_CLKGATE_D00 S5P_CLKREG(0x500)
-#define S5P_CLKGATE_D01 S5P_CLKREG(0x504)
-#define S5P_CLKGATE_D02 S5P_CLKREG(0x508)
-
-#define S5P_CLKGATE_D10 S5P_CLKREG(0x520)
-#define S5P_CLKGATE_D11 S5P_CLKREG(0x524)
-#define S5P_CLKGATE_D12 S5P_CLKREG(0x528)
-#define S5P_CLKGATE_D13 S5P_CLKREG(0x52C)
-#define S5P_CLKGATE_D14 S5P_CLKREG(0x530)
-#define S5P_CLKGATE_D15 S5P_CLKREG(0x534)
-
-#define S5P_CLKGATE_D20 S5P_CLKREG(0x540)
-
-#define S5P_CLKGATE_SCLK0 S5P_CLKREG(0x560)
-#define S5P_CLKGATE_SCLK1 S5P_CLKREG(0x564)
-
-/* CLKDIV0 */
-#define S5P_CLKDIV0_D0_MASK (0x7<<8)
-#define S5P_CLKDIV0_D0_SHIFT (8)
-#define S5P_CLKDIV0_PCLKD0_MASK (0x7<<12)
-#define S5P_CLKDIV0_PCLKD0_SHIFT (12)
-
-/* CLKDIV1 */
-#define S5P_CLKDIV1_D1_MASK (0x7<<12)
-#define S5P_CLKDIV1_D1_SHIFT (12)
-#define S5P_CLKDIV1_PCLKD1_MASK (0x7<<16)
-#define S5P_CLKDIV1_PCLKD1_SHIFT (16)
-
-#define S5PC100_SWRESET S5PC100_REG_OTHERS(0x000)
-#define S5PC100_MEM_SYS_CFG S5PC100_REG_OTHERS(0x200)
-
-#define S5PC100_SWRESET_RESETVAL 0xc100
-
-#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
deleted file mode 100644
index 0bf73209ec7b..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* linux/arch/arm/plat-s5pc100/include/plat/regs-gpio.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - GPIO register definitions
- */
-
-#ifndef __ASM_MACH_S5PC100_REGS_GPIO_H
-#define __ASM_MACH_S5PC100_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-#define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00)
-#define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4))
-
-#define S5PC100EINT30FLTCON0 (S5P_VA_GPIO + 0xE80)
-#define S5P_EINT_FLTCON(x) (S5PC100EINT30FLTCON0 + ((x) * 0x4))
-
-#define S5PC100EINT30MASK (S5P_VA_GPIO + 0xF00)
-#define S5P_EINT_MASK(x) (S5PC100EINT30MASK + ((x) * 0x4))
-
-#define S5PC100EINT30PEND (S5P_VA_GPIO + 0xF40)
-#define S5P_EINT_PEND(x) (S5PC100EINT30PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE S3C_GPIO_SFN(0x2)
-
-#define EINT_GPIO_0(x) S5PC100_GPH0(x)
-#define EINT_GPIO_1(x) S5PC100_GPH1(x)
-#define EINT_GPIO_2(x) S5PC100_GPH2(x)
-#define EINT_GPIO_3(x) S5PC100_GPH3(x)
-
-#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */
-
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-irq.h b/arch/arm/mach-s5pc100/include/mach/regs-irq.h
deleted file mode 100644
index 761627897f30..000000000000
--- a/arch/arm/mach-s5pc100/include/mach/regs-irq.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/regs-irq.h
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
deleted file mode 100644
index 668af3ac31f3..000000000000
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/mach-smdkc100.c
- *
- * Copyright 2009 Samsung Electronics Co.
- * Author: Byungho Min <bhmin@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/gpio-cfg.h>
-
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <plat/adc.h>
-#include <plat/keypad.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <linux/platform_data/asoc-s3c.h>
-#include <plat/backlight.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC100_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDKC100_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S3C2440_UFCON_RXTRIG8 | \
- S3C2440_UFCON_TXTRIG16)
-
-static struct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDKC100_UCON_DEFAULT,
- .ulcon = SMDKC100_ULCON_DEFAULT,
- .ufcon = SMDKC100_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDKC100_UCON_DEFAULT,
- .ulcon = SMDKC100_ULCON_DEFAULT,
- .ufcon = SMDKC100_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDKC100_UCON_DEFAULT,
- .ulcon = SMDKC100_ULCON_DEFAULT,
- .ufcon = SMDKC100_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDKC100_UCON_DEFAULT,
- .ulcon = SMDKC100_ULCON_DEFAULT,
- .ufcon = SMDKC100_UFCON_DEFAULT,
- },
-};
-
-/* I2C0 */
-static struct i2c_board_info i2c_devs0[] __initdata = {
- {I2C_BOARD_INFO("wm8580", 0x1b),},
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c_devs1[] __initdata = {
-};
-
-/* LCD power controller */
-static void smdkc100_lcd_power_set(struct plat_lcd_data *pd,
- unsigned int power)
-{
- if (power) {
- /* module reset */
- gpio_direction_output(S5PC100_GPH0(6), 1);
- mdelay(100);
- gpio_direction_output(S5PC100_GPH0(6), 0);
- mdelay(10);
- gpio_direction_output(S5PC100_GPH0(6), 1);
- mdelay(10);
- }
-}
-
-static struct plat_lcd_data smdkc100_lcd_power_data = {
- .set_power = smdkc100_lcd_power_set,
-};
-
-static struct platform_device smdkc100_lcd_powerdev = {
- .name = "platform-lcd",
- .dev.parent = &s3c_device_fb.dev,
- .dev.platform_data = &smdkc100_lcd_power_data,
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win smdkc100_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 16,
- .xres = 800,
- .yres = 480,
-};
-
-static struct fb_videomode smdkc100_lcd_timing = {
- .left_margin = 8,
- .right_margin = 13,
- .upper_margin = 7,
- .lower_margin = 5,
- .hsync_len = 3,
- .vsync_len = 1,
- .xres = 800,
- .yres = 480,
- .refresh = 80,
-};
-
-static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = {
- .win[0] = &smdkc100_fb_win0,
- .vtiming = &smdkc100_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = s5pc100_fb_gpio_setup_24bpp,
-};
-
-static struct s3c_ide_platdata smdkc100_ide_pdata __initdata = {
- .setup_gpio = s5pc100_ide_setup_gpio,
-};
-
-static uint32_t smdkc100_keymap[] __initdata = {
- /* KEY(row, col, keycode) */
- KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
- KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
- KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
- KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
-};
-
-static struct matrix_keymap_data smdkc100_keymap_data __initdata = {
- .keymap = smdkc100_keymap,
- .keymap_size = ARRAY_SIZE(smdkc100_keymap),
-};
-
-static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = {
- .keymap_data = &smdkc100_keymap_data,
- .rows = 2,
- .cols = 8,
-};
-
-static struct platform_device *smdkc100_devices[] __initdata = {
- &s3c_device_adc,
- &s3c_device_cfcon,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &s3c_device_fb,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &samsung_device_pwm,
- &s3c_device_ts,
- &s3c_device_wdt,
- &smdkc100_lcd_powerdev,
- &s5pc100_device_iis0,
- &samsung_device_keypad,
- &s5pc100_device_ac97,
- &s3c_device_rtc,
- &s5p_device_fimc0,
- &s5p_device_fimc1,
- &s5p_device_fimc2,
- &s5pc100_device_spdif,
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
- .no = S5PC100_GPD(0),
- .func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkc100_bl_data = {
- .pwm_id = 0,
- .enable_gpio = -1,
-};
-
-static void __init smdkc100_map_io(void)
-{
- s5pc100_init_io(NULL, 0);
- s3c24xx_init_clocks(12000000);
- s3c24xx_init_uarts(smdkc100_uartcfgs, ARRAY_SIZE(smdkc100_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init smdkc100_machine_init(void)
-{
- s3c24xx_ts_set_platdata(NULL);
-
- /* I2C */
- s3c_i2c0_set_platdata(NULL);
- s3c_i2c1_set_platdata(NULL);
- i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
- i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
- s3c_fb_set_platdata(&smdkc100_lcd_pdata);
- s3c_ide_set_platdata(&smdkc100_ide_pdata);
-
- samsung_keypad_set_platdata(&smdkc100_keypad_data);
-
- s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
-
- /* LCD init */
- gpio_request(S5PC100_GPH0(6), "GPH0");
- smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
-
- platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
-
- samsung_bl_set(&smdkc100_bl_gpio_info, &smdkc100_bl_data);
-}
-
-MACHINE_START(SMDKC100, "SMDKC100")
- /* Maintainer: Byungho Min <bhmin@samsung.com> */
- .atag_offset = 0x100,
- .init_irq = s5pc100_init_irq,
- .map_io = smdkc100_map_io,
- .init_machine = smdkc100_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5pc100_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c
deleted file mode 100644
index 8978e4cf9ed5..000000000000
--- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pc100/setup-fb-24bpp.c
- *
- * Copyright 2009 Samsung Electronics
- *
- * Base S5PC100 setup information for 24bpp LCD framebuffer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <plat/fb.h>
-#include <plat/gpio-cfg.h>
-
-#define DISR_OFFSET 0x7008
-
-static void s5pc100_fb_setgpios(unsigned int base, unsigned int nr)
-{
- s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
-}
-
-void s5pc100_fb_gpio_setup_24bpp(void)
-{
- s5pc100_fb_setgpios(S5PC100_GPF0(0), 8);
- s5pc100_fb_setgpios(S5PC100_GPF1(0), 8);
- s5pc100_fb_setgpios(S5PC100_GPF2(0), 8);
- s5pc100_fb_setgpios(S5PC100_GPF3(0), 4);
-}
diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c
deleted file mode 100644
index 89a6a769d622..000000000000
--- a/arch/arm/mach-s5pc100/setup-i2c0.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-i2c0.c
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * Base S5PC100 I2C bus 0 gpio configuration
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5PC100_GPD(3), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c
deleted file mode 100644
index faa667ef02cb..000000000000
--- a/arch/arm/mach-s5pc100/setup-i2c1.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-i2c1.c
- *
- * Copyright 2009 Samsung Electronics Co.
- * Byungho Min <bhmin@samsung.com>
- *
- * Base S5PC100 I2C bus 1 gpio configuration
- *
- * Based on plat-s3c64xx/setup-i2c1.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5PC100_GPD(5), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c
deleted file mode 100644
index 223aae044466..000000000000
--- a/arch/arm/mach-s5pc100/setup-ide.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5PC100 setup information for IDE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/regs-clock.h>
-#include <plat/gpio-cfg.h>
-
-static void s5pc100_ide_cfg_gpios(unsigned int base, unsigned int nr)
-{
- s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
-
- for (; nr > 0; nr--, base++)
- s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-void s5pc100_ide_setup_gpio(void)
-{
- u32 reg;
-
- /* Independent CF interface, CF chip select configuration */
- reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f);
- writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG);
-
- /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
- s5pc100_ide_cfg_gpios(S5PC100_GPJ0(0), 8);
-
- /*CF_Data[0 - 7] */
- s5pc100_ide_cfg_gpios(S5PC100_GPJ2(0), 8);
-
- /* CF_Data[8 - 15] */
- s5pc100_ide_cfg_gpios(S5PC100_GPJ3(0), 8);
-
- /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
- s5pc100_ide_cfg_gpios(S5PC100_GPJ4(0), 4);
-
- /* EBI_OE, EBI_WE */
- s3c_gpio_cfgpin_range(S5PC100_GPK0(6), 2, S3C_GPIO_SFN(0));
-
- /* CF_OE, CF_WE */
- s3c_gpio_cfgrange_nopull(S5PC100_GPK1(6), 8, S3C_GPIO_SFN(2));
-
- /* CF_CD */
- s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PC100_GPK3(5), S3C_GPIO_PULL_NONE);
-}
diff --git a/arch/arm/mach-s5pc100/setup-keypad.c b/arch/arm/mach-s5pc100/setup-keypad.c
deleted file mode 100644
index ada377f0c206..000000000000
--- a/arch/arm/mach-s5pc100/setup-keypad.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-keypad.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * GPIO configuration for S5PC100 KeyPad device
- *
- * 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/gpio.h>
-#include <plat/gpio-cfg.h>
-
-void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
-{
- /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
- s3c_gpio_cfgrange_nopull(S5PC100_GPH3(0), rows, S3C_GPIO_SFN(3));
-
- /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
- s3c_gpio_cfgrange_nopull(S5PC100_GPH2(0), cols, S3C_GPIO_SFN(3));
-}
diff --git a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
deleted file mode 100644
index 6010c0310cb5..000000000000
--- a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s5pc100/setup-sdhci-gpio.c
- *
- * Copyright 2009 Samsung Eletronics
- *
- * S5PC100 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-
-void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
- unsigned int num;
-
- num = width;
- /* In case of 8 width, we should decrease the 2 */
- if (width == 8)
- num = width - 2;
-
- /* Set all the necessary GPG0/GPG1 pins to special-function 0 */
- s3c_gpio_cfgrange_nopull(S5PC100_GPG0(0), 2 + num, S3C_GPIO_SFN(2));
-
- if (width == 8)
- s3c_gpio_cfgrange_nopull(S5PC100_GPG1(0), 2, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PC100_GPG1(2), S3C_GPIO_SFN(2));
- }
-}
-
-void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG2 pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PC100_GPG2(0), 2 + width, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PC100_GPG2(6), S3C_GPIO_SFN(2));
- }
-}
-
-void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG3 pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PC100_GPG3(0), 2 + width, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PC100_GPG3(6), S3C_GPIO_SFN(2));
- }
-}
diff --git a/arch/arm/mach-s5pc100/setup-spi.c b/arch/arm/mach-s5pc100/setup-spi.c
deleted file mode 100644
index 183567961de1..000000000000
--- a/arch/arm/mach-s5pc100/setup-spi.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
- s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
- s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI2
-int s3c64xx_spi2_cfg_gpio(void)
-{
- s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
- s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgall_range(S5PC100_GPB(2), 2,
- S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index f60f2862856d..330bfc8fcd52 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -7,193 +7,28 @@
# Configuration options for the S5PV210/S5PC110
+config ARCH_S5PV210
+ bool "Samsung S5PV210/S5PC110" if ARCH_MULTI_V7
+ select ARCH_HAS_HOLES_MEMORYMODEL
+ select ARCH_REQUIRE_GPIOLIB
+ select ARM_VIC
+ select CLKSRC_SAMSUNG_PWM
+ select COMMON_CLK_SAMSUNG
+ select HAVE_S3C2410_I2C if I2C
+ select HAVE_S3C2410_WATCHDOG if WATCHDOG
+ select HAVE_S3C_RTC if RTC_CLASS
+ select PINCTRL
+ select PINCTRL_EXYNOS
+ help
+ Samsung S5PV210/S5PC110 series based systems
+
if ARCH_S5PV210
config CPU_S5PV210
- bool
+ def_bool y
select ARM_AMBA
select PL330_DMA if DMADEVICES
- select S5P_EXT_INT
- select S5P_PM if PM
- select S5P_SLEEP if PM
help
Enable S5PV210 CPU support
-config S5PV210_SETUP_I2C1
- bool
- help
- Common setup code for i2c bus 1.
-
-config S5PV210_SETUP_I2C2
- bool
- help
- Common setup code for i2c bus 2.
-
-config S5PV210_SETUP_IDE
- bool
- help
- Common setup code for S5PV210 IDE GPIO configurations
-
-config S5PV210_SETUP_FB_24BPP
- bool
- help
- Common setup code for S5PV210 with an 24bpp RGB display helper.
-
-config S5PV210_SETUP_KEYPAD
- bool
- help
- Common setup code for keypad.
-
-config S5PV210_SETUP_SDHCI
- bool
- select S5PV210_SETUP_SDHCI_GPIO
- help
- Internal helper functions for S5PV210 based SDHCI systems
-
-config S5PV210_SETUP_SDHCI_GPIO
- bool
- help
- Common setup code for SDHCI gpio.
-
-config S5PV210_SETUP_FIMC
- bool
- help
- Common setup code for the camera interfaces.
-
-config S5PV210_SETUP_SPI
- bool
- help
- Common setup code for SPI GPIO configurations.
-
-config S5PV210_SETUP_USB_PHY
- bool
- help
- Common setup code for USB PHY controller
-
-menu "S5PC110 Machines"
-
-config MACH_AQUILA
- bool "Aquila"
- select CPU_S5PV210
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S5PV210_SETUP_FB_24BPP
- select S5PV210_SETUP_SDHCI
- select S5PV210_SETUP_USB_PHY
- select S5P_DEV_FIMC0
- select S5P_DEV_FIMC1
- select S5P_DEV_FIMC2
- select S5P_DEV_ONENAND
- help
- Machine support for the Samsung Aquila target based on S5PC110 SoC
-
-config MACH_GONI
- bool "GONI"
- select CPU_S5PV210
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_I2C1
- select S3C_DEV_I2C2
- select S3C_DEV_USB_HSOTG
- select S5PV210_SETUP_FB_24BPP
- select S5PV210_SETUP_FIMC
- select S5PV210_SETUP_I2C1
- select S5PV210_SETUP_I2C2
- select S5PV210_SETUP_KEYPAD
- select S5PV210_SETUP_SDHCI
- select S5PV210_SETUP_USB_PHY
- select S5P_DEV_FIMC0
- select S5P_DEV_FIMC1
- select S5P_DEV_FIMC2
- select S5P_DEV_MFC
- select S5P_DEV_ONENAND
- select S5P_DEV_TV
- select S5P_GPIO_INT
- select SAMSUNG_DEV_KEYPAD
- help
- Machine support for Samsung GONI board
- S5PC110(MCP) is one of package option of S5PV210
-
-config MACH_SMDKC110
- bool "SMDKC110"
- select CPU_S5PV210
- select S3C_DEV_I2C1
- select S3C_DEV_I2C2
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S5PV210_SETUP_I2C1
- select S5PV210_SETUP_I2C2
- select S5PV210_SETUP_IDE
- select S5P_DEV_FIMC0
- select S5P_DEV_FIMC1
- select S5P_DEV_FIMC2
- select S5P_DEV_MFC
- select SAMSUNG_DEV_IDE
- help
- Machine support for Samsung SMDKC110
- S5PC110(MCP) is one of package option of S5PV210
-
-endmenu
-
-menu "S5PV210 Machines"
-
-config MACH_SMDKV210
- bool "SMDKV210"
- select CPU_S5PV210
- select S3C_DEV_FB
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_HSMMC3
- select S3C_DEV_I2C1
- select S3C_DEV_I2C2
- select S3C_DEV_RTC
- select S3C_DEV_USB_HSOTG
- select S3C_DEV_WDT
- select S5PV210_SETUP_FB_24BPP
- select S5PV210_SETUP_I2C1
- select S5PV210_SETUP_I2C2
- select S5PV210_SETUP_IDE
- select S5PV210_SETUP_KEYPAD
- select S5PV210_SETUP_SDHCI
- select S5PV210_SETUP_USB_PHY
- select S5P_DEV_FIMC0
- select S5P_DEV_FIMC1
- select S5P_DEV_FIMC2
- select S5P_DEV_JPEG
- select S5P_DEV_MFC
- select SAMSUNG_DEV_ADC
- select SAMSUNG_DEV_BACKLIGHT
- select SAMSUNG_DEV_IDE
- select SAMSUNG_DEV_KEYPAD
- select SAMSUNG_DEV_PWM
- select SAMSUNG_DEV_TS
- help
- Machine support for Samsung SMDKV210
-
-config MACH_TORBRECK
- bool "Torbreck"
- select ARCH_SPARSEMEM_ENABLE
- select CPU_S5PV210
- select S3C_DEV_HSMMC
- select S3C_DEV_HSMMC1
- select S3C_DEV_HSMMC2
- select S3C_DEV_HSMMC3
- select S3C_DEV_I2C1
- select S3C_DEV_I2C2
- select S3C_DEV_RTC
- select S3C_DEV_WDT
- select S5PV210_SETUP_I2C1
- select S5PV210_SETUP_I2C2
- select S5PV210_SETUP_SDHCI
- select SAMSUNG_DEV_IDE
- help
- Machine support for aESOP Torbreck
-
-endmenu
-
endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 1c4e41998a10..7dc2d0e25a83 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -5,6 +5,8 @@
#
# Licensed under GPLv2
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)/arch/arm/plat-samsung/include
+
obj-y :=
obj-m :=
obj-n :=
@@ -12,31 +14,8 @@ obj- :=
# Core
-obj-y += common.o clock.o
-
-obj-$(CONFIG_PM) += pm.o
-
-obj-y += dma.o
+obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
# machine support
-obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o
-obj-$(CONFIG_MACH_GONI) += mach-goni.o
-obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
-obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o
-obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o
-
-# device support
-
-obj-y += dev-audio.o
-
-obj-y += setup-i2c0.o
-obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o
-obj-$(CONFIG_S5PV210_SETUP_FIMC) += setup-fimc.o
-obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
-obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
-obj-$(CONFIG_S5PV210_SETUP_IDE) += setup-ide.o
-obj-$(CONFIG_S5PV210_SETUP_KEYPAD) += setup-keypad.o
-obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
-obj-$(CONFIG_S5PV210_SETUP_SPI) += setup-spi.o
-obj-$(CONFIG_S5PV210_SETUP_USB_PHY) += setup-usb-phy.o
+obj-y += s5pv210.o
diff --git a/arch/arm/mach-s5pv210/Makefile.boot b/arch/arm/mach-s5pv210/Makefile.boot
deleted file mode 100644
index 79ece4055b02..000000000000
--- a/arch/arm/mach-s5pv210/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y += 0x20008000
-params_phys-y := 0x20000100
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
deleted file mode 100644
index ca463724a3df..000000000000
--- a/arch/arm/mach-s5pv210/clock.c
+++ /dev/null
@@ -1,1365 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-#include <mach/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include "common.h"
-
-static unsigned long xtal;
-
-static struct clksrc_clk clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- },
- .sources = &clk_src_apll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- },
- .sources = &clk_src_epll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- },
- .sources = &clk_src_mpll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_armclk_list[] = {
- [0] = &clk_mout_apll.clk,
- [1] = &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_armclk = {
- .sources = clkset_armclk_list,
- .nr_sources = ARRAY_SIZE(clkset_armclk_list),
-};
-
-static struct clksrc_clk clk_armclk = {
- .clk = {
- .name = "armclk",
- },
- .sources = &clkset_armclk,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_hclk_msys = {
- .clk = {
- .name = "hclk_msys",
- .parent = &clk_armclk.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_pclk_msys = {
- .clk = {
- .name = "pclk_msys",
- .parent = &clk_hclk_msys.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_sclk_a2m = {
- .clk = {
- .name = "sclk_a2m",
- .parent = &clk_mout_apll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
-};
-
-static struct clk *clkset_hclk_sys_list[] = {
- [0] = &clk_mout_mpll.clk,
- [1] = &clk_sclk_a2m.clk,
-};
-
-static struct clksrc_sources clkset_hclk_sys = {
- .sources = clkset_hclk_sys_list,
- .nr_sources = ARRAY_SIZE(clkset_hclk_sys_list),
-};
-
-static struct clksrc_clk clk_hclk_dsys = {
- .clk = {
- .name = "hclk_dsys",
- },
- .sources = &clkset_hclk_sys,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_dsys = {
- .clk = {
- .name = "pclk_dsys",
- .parent = &clk_hclk_dsys.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk clk_hclk_psys = {
- .clk = {
- .name = "hclk_psys",
- },
- .sources = &clkset_hclk_sys,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_pclk_psys = {
- .clk = {
- .name = "pclk_psys",
- .parent = &clk_hclk_psys.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
-};
-
-static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
-}
-
-static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
-}
-
-static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
-}
-
-static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
-}
-
-static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
-}
-
-static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
-}
-
-static int s5pv210_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
- return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-static struct clk clk_sclk_hdmi27m = {
- .name = "sclk_hdmi27m",
- .rate = 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
- .name = "sclk_hdmiphy",
-};
-
-static struct clk clk_sclk_usbphy0 = {
- .name = "sclk_usbphy0",
-};
-
-static struct clk clk_sclk_usbphy1 = {
- .name = "sclk_usbphy1",
-};
-
-static struct clk clk_pcmcdclk0 = {
- .name = "pcmcdclk",
-};
-
-static struct clk clk_pcmcdclk1 = {
- .name = "pcmcdclk",
-};
-
-static struct clk clk_pcmcdclk2 = {
- .name = "pcmcdclk",
-};
-
-static struct clk *clkset_vpllsrc_list[] = {
- [0] = &clk_fin_vpll,
- [1] = &clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources clkset_vpllsrc = {
- .sources = clkset_vpllsrc_list,
- .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk clk_vpllsrc = {
- .clk = {
- .name = "vpll_src",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 7),
- },
- .sources = &clkset_vpllsrc,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
-};
-
-static struct clk *clkset_sclk_vpll_list[] = {
- [0] = &clk_vpllsrc.clk,
- [1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources clkset_sclk_vpll = {
- .sources = clkset_sclk_vpll_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk clk_sclk_vpll = {
- .clk = {
- .name = "sclk_vpll",
- },
- .sources = &clkset_sclk_vpll,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
-};
-
-static struct clk *clkset_moutdmc0src_list[] = {
- [0] = &clk_sclk_a2m.clk,
- [1] = &clk_mout_mpll.clk,
- [2] = NULL,
- [3] = NULL,
-};
-
-static struct clksrc_sources clkset_moutdmc0src = {
- .sources = clkset_moutdmc0src_list,
- .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list),
-};
-
-static struct clksrc_clk clk_mout_dmc0 = {
- .clk = {
- .name = "mout_dmc0",
- },
- .sources = &clkset_moutdmc0src,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
-};
-
-static struct clksrc_clk clk_sclk_dmc0 = {
- .clk = {
- .name = "sclk_dmc0",
- .parent = &clk_mout_dmc0.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
-};
-
-static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
-{
- return clk_get_rate(clk->parent) / 2;
-}
-
-static struct clk_ops clk_hclk_imem_ops = {
- .get_rate = s5pv210_clk_imem_get_rate,
-};
-
-static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk)
-{
- return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
-}
-
-static struct clk_ops clk_fout_apll_ops = {
- .get_rate = s5pv210_clk_fout_apll_get_rate,
-};
-
-static struct clk init_clocks_off[] = {
- {
- .name = "rot",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1<<29),
- }, {
- .name = "fimc",
- .devname = "s5pv210-fimc.0",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 24),
- }, {
- .name = "fimc",
- .devname = "s5pv210-fimc.1",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 25),
- }, {
- .name = "fimc",
- .devname = "s5pv210-fimc.2",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 26),
- }, {
- .name = "jpeg",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 28),
- }, {
- .name = "mfc",
- .devname = "s5p-mfc",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 16),
- }, {
- .name = "dac",
- .devname = "s5p-sdo",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = "mixer",
- .devname = "s5p-mixer",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1 << 9),
- }, {
- .name = "vp",
- .devname = "s5p-mixer",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "hdmi",
- .devname = "s5pv210-hdmi",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1 << 11),
- }, {
- .name = "hdmiphy",
- .devname = "s5pv210-hdmi",
- .enable = s5pv210_clk_hdmiphy_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "dacphy",
- .devname = "s5p-sdo",
- .enable = exynos4_clk_dac_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "otg",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1<<16),
- }, {
- .name = "usb-host",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1<<17),
- }, {
- .name = "lcd",
- .parent = &clk_hclk_dsys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1<<0),
- }, {
- .name = "cfcon",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1<<25),
- }, {
- .name = "systimer",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<16),
- }, {
- .name = "watchdog",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<22),
- }, {
- .name = "rtc",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<15),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.0",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<7),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.1",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 10),
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.2",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<9),
- }, {
- .name = "i2c",
- .devname = "s3c2440-hdmiphy-i2c",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 11),
- }, {
- .name = "spi",
- .devname = "s5pv210-spi.0",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<12),
- }, {
- .name = "spi",
- .devname = "s5pv210-spi.1",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<13),
- }, {
- .name = "spi",
- .devname = "s5pv210-spi.2",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<14),
- }, {
- .name = "timers",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<23),
- }, {
- .name = "adc",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<24),
- }, {
- .name = "keypad",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<21),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .parent = &clk_p,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<4),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.1",
- .parent = &clk_p,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "iis",
- .devname = "samsung-i2s.2",
- .parent = &clk_p,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 6),
- }, {
- .name = "spdif",
- .parent = &clk_p,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 0),
- },
-};
-
-static struct clk init_clocks[] = {
- {
- .name = "hclk_imem",
- .parent = &clk_hclk_msys.clk,
- .ctrlbit = (1 << 5),
- .enable = s5pv210_clk_ip0_ctrl,
- .ops = &clk_hclk_imem_ops,
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.0",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 17),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.1",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 18),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.2",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 19),
- }, {
- .name = "uart",
- .devname = "s5pv210-uart.3",
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1 << 20),
- }, {
- .name = "sromc",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1 << 26),
- },
-};
-
-static struct clk clk_hsmmc0 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.0",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip2_ctrl,
- .ctrlbit = (1<<16),
-};
-
-static struct clk clk_hsmmc1 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.1",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip2_ctrl,
- .ctrlbit = (1<<17),
-};
-
-static struct clk clk_hsmmc2 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.2",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip2_ctrl,
- .ctrlbit = (1<<18),
-};
-
-static struct clk clk_hsmmc3 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.3",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip2_ctrl,
- .ctrlbit = (1<<19),
-};
-
-static struct clk clk_pdma0 = {
- .name = "pdma0",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 3),
-};
-
-static struct clk clk_pdma1 = {
- .name = "pdma1",
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 4),
-};
-
-static struct clk *clkset_uart_list[] = {
- [6] = &clk_mout_mpll.clk,
- [7] = &clk_mout_epll.clk,
-};
-
-static struct clksrc_sources clkset_uart = {
- .sources = clkset_uart_list,
- .nr_sources = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_group1_list[] = {
- [0] = &clk_sclk_a2m.clk,
- [1] = &clk_mout_mpll.clk,
- [2] = &clk_mout_epll.clk,
- [3] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group1 = {
- .sources = clkset_group1_list,
- .nr_sources = ARRAY_SIZE(clkset_group1_list),
-};
-
-static struct clk *clkset_sclk_onenand_list[] = {
- [0] = &clk_hclk_psys.clk,
- [1] = &clk_hclk_dsys.clk,
-};
-
-static struct clksrc_sources clkset_sclk_onenand = {
- .sources = clkset_sclk_onenand_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_onenand_list),
-};
-
-static struct clk *clkset_sclk_dac_list[] = {
- [0] = &clk_sclk_vpll.clk,
- [1] = &clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources clkset_sclk_dac = {
- .sources = clkset_sclk_dac_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk clk_sclk_dac = {
- .clk = {
- .name = "sclk_dac",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 2),
- },
- .sources = &clkset_sclk_dac,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_pixel = {
- .clk = {
- .name = "sclk_pixel",
- .parent = &clk_sclk_vpll.clk,
- },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
-};
-
-static struct clk *clkset_sclk_hdmi_list[] = {
- [0] = &clk_sclk_pixel.clk,
- [1] = &clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources clkset_sclk_hdmi = {
- .sources = clkset_sclk_hdmi_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk clk_sclk_hdmi = {
- .clk = {
- .name = "sclk_hdmi",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &clkset_sclk_hdmi,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_sclk_mixer_list[] = {
- [0] = &clk_sclk_dac.clk,
- [1] = &clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources clkset_sclk_mixer = {
- .sources = clkset_sclk_mixer_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk clk_sclk_mixer = {
- .clk = {
- .name = "sclk_mixer",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 1),
- },
- .sources = &clkset_sclk_mixer,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *sclk_tv[] = {
- &clk_sclk_dac,
- &clk_sclk_pixel,
- &clk_sclk_hdmi,
- &clk_sclk_mixer,
-};
-
-static struct clk *clkset_sclk_audio0_list[] = {
- [0] = &clk_ext_xtal_mux,
- [1] = &clk_pcmcdclk0,
- [2] = &clk_sclk_hdmi27m,
- [3] = &clk_sclk_usbphy0,
- [4] = &clk_sclk_usbphy1,
- [5] = &clk_sclk_hdmiphy,
- [6] = &clk_mout_mpll.clk,
- [7] = &clk_mout_epll.clk,
- [8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio0 = {
- .sources = clkset_sclk_audio0_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list),
-};
-
-static struct clksrc_clk clk_sclk_audio0 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "soc-audio.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &clkset_sclk_audio0,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
-};
-
-static struct clk *clkset_sclk_audio1_list[] = {
- [0] = &clk_ext_xtal_mux,
- [1] = &clk_pcmcdclk1,
- [2] = &clk_sclk_hdmi27m,
- [3] = &clk_sclk_usbphy0,
- [4] = &clk_sclk_usbphy1,
- [5] = &clk_sclk_hdmiphy,
- [6] = &clk_mout_mpll.clk,
- [7] = &clk_mout_epll.clk,
- [8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio1 = {
- .sources = clkset_sclk_audio1_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_audio1_list),
-};
-
-static struct clksrc_clk clk_sclk_audio1 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "soc-audio.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 25),
- },
- .sources = &clkset_sclk_audio1,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
-};
-
-static struct clk *clkset_sclk_audio2_list[] = {
- [0] = &clk_ext_xtal_mux,
- [1] = &clk_pcmcdclk0,
- [2] = &clk_sclk_hdmi27m,
- [3] = &clk_sclk_usbphy0,
- [4] = &clk_sclk_usbphy1,
- [5] = &clk_sclk_hdmiphy,
- [6] = &clk_mout_mpll.clk,
- [7] = &clk_mout_epll.clk,
- [8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_sclk_audio2 = {
- .sources = clkset_sclk_audio2_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_audio2_list),
-};
-
-static struct clksrc_clk clk_sclk_audio2 = {
- .clk = {
- .name = "sclk_audio",
- .devname = "soc-audio.2",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 26),
- },
- .sources = &clkset_sclk_audio2,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
-};
-
-static struct clk *clkset_sclk_spdif_list[] = {
- [0] = &clk_sclk_audio0.clk,
- [1] = &clk_sclk_audio1.clk,
- [2] = &clk_sclk_audio2.clk,
-};
-
-static struct clksrc_sources clkset_sclk_spdif = {
- .sources = clkset_sclk_spdif_list,
- .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list),
-};
-
-static struct clksrc_clk clk_sclk_spdif = {
- .clk = {
- .name = "sclk_spdif",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 27),
- .ops = &s5p_sclk_spdif_ops,
- },
- .sources = &clkset_sclk_spdif,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
-};
-
-static struct clk *clkset_group2_list[] = {
- [0] = &clk_ext_xtal_mux,
- [1] = &clk_xusbxti,
- [2] = &clk_sclk_hdmi27m,
- [3] = &clk_sclk_usbphy0,
- [4] = &clk_sclk_usbphy1,
- [5] = &clk_sclk_hdmiphy,
- [6] = &clk_mout_mpll.clk,
- [7] = &clk_mout_epll.clk,
- [8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group2 = {
- .sources = clkset_group2_list,
- .nr_sources = ARRAY_SIZE(clkset_group2_list),
-};
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "sclk_dmc",
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_onenand",
- },
- .sources = &clkset_sclk_onenand,
- .reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5pv210-fimc.0",
- .enable = s5pv210_clk_mask1_ctrl,
- .ctrlbit = (1 << 2),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5pv210-fimc.1",
- .enable = s5pv210_clk_mask1_ctrl,
- .ctrlbit = (1 << 3),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimc",
- .devname = "s5pv210-fimc.2",
- .enable = s5pv210_clk_mask1_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_cam0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 3),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_cam1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_fimd",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 5),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_mfc",
- .devname = "s5p-mfc",
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 16),
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_g2d",
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_g3d",
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_csis",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 6),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_pwi",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 29),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_pwm",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 19),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
- },
-};
-
-static struct clksrc_clk clk_sclk_uart0 = {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart1 = {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 13),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart2 = {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.2",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 14),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_uart3 = {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.3",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 15),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 9),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 10),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_mmc3 = {
- .clk = {
- .name = "sclk_mmc",
- .devname = "s3c-sdhci.3",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 11),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5pv210-spi.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 16),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
- };
-
-static struct clksrc_clk clk_sclk_spi1 = {
- .clk = {
- .name = "sclk_spi",
- .devname = "s5pv210-spi.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 17),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
- };
-
-
-static struct clksrc_clk *clksrc_cdev[] = {
- &clk_sclk_uart0,
- &clk_sclk_uart1,
- &clk_sclk_uart2,
- &clk_sclk_uart3,
- &clk_sclk_mmc0,
- &clk_sclk_mmc1,
- &clk_sclk_mmc2,
- &clk_sclk_mmc3,
- &clk_sclk_spi0,
- &clk_sclk_spi1,
-};
-
-static struct clk *clk_cdev[] = {
- &clk_hsmmc0,
- &clk_hsmmc1,
- &clk_hsmmc2,
- &clk_hsmmc3,
- &clk_pdma0,
- &clk_pdma1,
-};
-
-/* Clock initialisation code */
-static struct clksrc_clk *sysclks[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_mout_mpll,
- &clk_armclk,
- &clk_hclk_msys,
- &clk_sclk_a2m,
- &clk_hclk_dsys,
- &clk_hclk_psys,
- &clk_pclk_msys,
- &clk_pclk_dsys,
- &clk_pclk_psys,
- &clk_vpllsrc,
- &clk_sclk_vpll,
- &clk_mout_dmc0,
- &clk_sclk_dmc0,
- &clk_sclk_audio0,
- &clk_sclk_audio1,
- &clk_sclk_audio2,
- &clk_sclk_spdif,
-};
-
-static u32 epll_div[][6] = {
- { 48000000, 0, 48, 3, 3, 0 },
- { 96000000, 0, 48, 3, 2, 0 },
- { 144000000, 1, 72, 3, 2, 0 },
- { 192000000, 0, 48, 3, 1, 0 },
- { 288000000, 1, 72, 3, 1, 0 },
- { 32750000, 1, 65, 3, 4, 35127 },
- { 32768000, 1, 65, 3, 4, 35127 },
- { 45158400, 0, 45, 3, 3, 10355 },
- { 45000000, 0, 45, 3, 3, 10355 },
- { 45158000, 0, 45, 3, 3, 10355 },
- { 49125000, 0, 49, 3, 3, 9961 },
- { 49152000, 0, 49, 3, 3, 9961 },
- { 67737600, 1, 67, 3, 3, 48366 },
- { 67738000, 1, 67, 3, 3, 48366 },
- { 73800000, 1, 73, 3, 3, 47710 },
- { 73728000, 1, 73, 3, 3, 47710 },
- { 36000000, 1, 32, 3, 4, 0 },
- { 60000000, 1, 60, 3, 3, 0 },
- { 72000000, 1, 72, 3, 3, 0 },
- { 80000000, 1, 80, 3, 3, 0 },
- { 84000000, 0, 42, 3, 2, 0 },
- { 50000000, 0, 50, 3, 3, 0 },
-};
-
-static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int epll_con, epll_con_k;
- unsigned int i;
-
- /* Return if nothing changed */
- if (clk->rate == rate)
- return 0;
-
- epll_con = __raw_readl(S5P_EPLL_CON);
- epll_con_k = __raw_readl(S5P_EPLL_CON1);
-
- epll_con_k &= ~PLL46XX_KDIV_MASK;
- epll_con &= ~(1 << 27 |
- PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
- PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
- PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
- for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
- if (epll_div[i][0] == rate) {
- epll_con_k |= epll_div[i][5] << 0;
- epll_con |= (epll_div[i][1] << 27 |
- epll_div[i][2] << PLL46XX_MDIV_SHIFT |
- epll_div[i][3] << PLL46XX_PDIV_SHIFT |
- epll_div[i][4] << PLL46XX_SDIV_SHIFT);
- break;
- }
- }
-
- if (i == ARRAY_SIZE(epll_div)) {
- printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
- __func__);
- return -EINVAL;
- }
-
- __raw_writel(epll_con, S5P_EPLL_CON);
- __raw_writel(epll_con_k, S5P_EPLL_CON1);
-
- printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
- clk->rate, rate);
-
- clk->rate = rate;
-
- return 0;
-}
-
-static struct clk_ops s5pv210_epll_ops = {
- .set_rate = s5pv210_epll_set_rate,
- .get_rate = s5p_epll_get_rate,
-};
-
-static u32 vpll_div[][5] = {
- { 54000000, 3, 53, 3, 0 },
- { 108000000, 3, 53, 2, 0 },
-};
-
-static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-
-static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned int vpll_con;
- unsigned int i;
-
- /* Return if nothing changed */
- if (clk->rate == rate)
- return 0;
-
- vpll_con = __raw_readl(S5P_VPLL_CON);
- vpll_con &= ~(0x1 << 27 | \
- PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | \
- PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | \
- PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
-
- for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
- if (vpll_div[i][0] == rate) {
- vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
- vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
- vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
- vpll_con |= vpll_div[i][4] << 27;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(vpll_div)) {
- printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
- __func__);
- return -EINVAL;
- }
-
- __raw_writel(vpll_con, S5P_VPLL_CON);
-
- /* Wait for VPLL lock */
- while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
- continue;
-
- clk->rate = rate;
- return 0;
-}
-static struct clk_ops s5pv210_vpll_ops = {
- .get_rate = s5pv210_vpll_get_rate,
- .set_rate = s5pv210_vpll_set_rate,
-};
-
-void __init_or_cpufreq s5pv210_setup_clocks(void)
-{
- struct clk *xtal_clk;
- unsigned long vpllsrc;
- unsigned long armclk;
- unsigned long hclk_msys;
- unsigned long hclk_dsys;
- unsigned long hclk_psys;
- unsigned long pclk_msys;
- unsigned long pclk_dsys;
- unsigned long pclk_psys;
- unsigned long apll;
- unsigned long mpll;
- unsigned long epll;
- unsigned long vpll;
- unsigned int ptr;
- u32 clkdiv0, clkdiv1;
-
- /* Set functions for clk_fout_epll */
- clk_fout_epll.enable = s5p_epll_enable;
- clk_fout_epll.ops = &s5pv210_epll_ops;
-
- printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
- clkdiv0 = __raw_readl(S5P_CLK_DIV0);
- clkdiv1 = __raw_readl(S5P_CLK_DIV1);
-
- printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
- __func__, clkdiv0, clkdiv1);
-
- xtal_clk = clk_get(NULL, "xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
- clk_put(xtal_clk);
-
- printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
- apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
- mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
- epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON),
- __raw_readl(S5P_EPLL_CON1), pll_4600);
- vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
- vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
-
- clk_fout_apll.ops = &clk_fout_apll_ops;
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_fout_vpll.ops = &s5pv210_vpll_ops;
- clk_fout_vpll.rate = vpll;
-
- printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
- apll, mpll, epll, vpll);
-
- armclk = clk_get_rate(&clk_armclk.clk);
- hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
- hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
- hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
- pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
- pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
- pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
-
- printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
- "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
- armclk, hclk_msys, hclk_dsys, hclk_psys,
- pclk_msys, pclk_dsys, pclk_psys);
-
- clk_f.rate = armclk;
- clk_h.rate = hclk_psys;
- clk_p.rate = pclk_psys;
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
- &clk_sclk_hdmi27m,
- &clk_sclk_hdmiphy,
- &clk_sclk_usbphy0,
- &clk_sclk_usbphy1,
- &clk_pcmcdclk0,
- &clk_pcmcdclk1,
- &clk_pcmcdclk2,
-};
-
-static struct clk_lookup s5pv210_clk_lookup[] = {
- CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
- CLKDEV_INIT("s5pv210-uart.0", "clk_uart_baud1", &clk_sclk_uart0.clk),
- CLKDEV_INIT("s5pv210-uart.1", "clk_uart_baud1", &clk_sclk_uart1.clk),
- CLKDEV_INIT("s5pv210-uart.2", "clk_uart_baud1", &clk_sclk_uart2.clk),
- CLKDEV_INIT("s5pv210-uart.3", "clk_uart_baud1", &clk_sclk_uart3.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
- CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.0", &clk_hsmmc3),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
- CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
- CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
- CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
- CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
- CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0),
- CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1),
-};
-
-void __init s5pv210_register_clocks(void)
-{
- int ptr;
-
- s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
- for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
- s3c_register_clksrc(sysclks[ptr], 1);
-
- for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
- s3c_register_clksrc(sclk_tv[ptr], 1);
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
- s3c_register_clksrc(clksrc_cdev[ptr], 1);
-
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- clkdev_add_table(s5pv210_clk_lookup, ARRAY_SIZE(s5pv210_clk_lookup));
-
- s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
- for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
- s3c_disable_clocks(clk_cdev[ptr], 1);
-
-}
diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c
deleted file mode 100644
index 7024dcd0e40a..000000000000
--- a/arch/arm/mach-s5pv210/common.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Common Codes for S5PV210
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <clocksource/samsung_pwm.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-
-#include <asm/proc-fns.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/adc-core.h>
-#include <plat/ata-core.h>
-#include <plat/fb-core.h>
-#include <plat/fimc-core.h>
-#include <plat/iic-core.h>
-#include <plat/keypad-core.h>
-#include <plat/pwm-core.h>
-#include <plat/tv-core.h>
-#include <plat/spi-core.h>
-
-#include "common.h"
-
-static const char name_s5pv210[] = "S5PV210/S5PC110";
-
-static struct cpu_table cpu_ids[] __initdata = {
- {
- .idcode = S5PV210_CPU_ID,
- .idmask = S5PV210_CPU_MASK,
- .map_io = s5pv210_map_io,
- .init_clocks = s5pv210_init_clocks,
- .init_uarts = s5pv210_init_uarts,
- .init = s5pv210_init,
- .name = name_s5pv210,
- },
-};
-
-/* Initial IO mappings */
-
-static struct map_desc s5pv210_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S5P_VA_CHIPID,
- .pfn = __phys_to_pfn(S5PV210_PA_CHIPID),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_SYS,
- .pfn = __phys_to_pfn(S5PV210_PA_SYSCON),
- .length = SZ_64K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_TIMER,
- .pfn = __phys_to_pfn(S5PV210_PA_TIMER),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_WATCHDOG,
- .pfn = __phys_to_pfn(S5PV210_PA_WATCHDOG),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_SROMC,
- .pfn = __phys_to_pfn(S5PV210_PA_SROMC),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_SYSTIMER,
- .pfn = __phys_to_pfn(S5PV210_PA_SYSTIMER),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_GPIO,
- .pfn = __phys_to_pfn(S5PV210_PA_GPIO),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC0,
- .pfn = __phys_to_pfn(S5PV210_PA_VIC0),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC1,
- .pfn = __phys_to_pfn(S5PV210_PA_VIC1),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC2,
- .pfn = __phys_to_pfn(S5PV210_PA_VIC2),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)VA_VIC3,
- .pfn = __phys_to_pfn(S5PV210_PA_VIC3),
- .length = SZ_16K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_UART,
- .pfn = __phys_to_pfn(S3C_PA_UART),
- .length = SZ_512K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_DMC0,
- .pfn = __phys_to_pfn(S5PV210_PA_DMC0),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S5P_VA_DMC1,
- .pfn = __phys_to_pfn(S5PV210_PA_DMC1),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)S3C_VA_USB_HSPHY,
- .pfn =__phys_to_pfn(S5PV210_PA_HSPHY),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }
-};
-
-void s5pv210_restart(enum reboot_mode mode, const char *cmd)
-{
- __raw_writel(0x1, S5P_SWRESET);
-}
-
-static struct samsung_pwm_variant s5pv210_pwm_variant = {
- .bits = 32,
- .div_base = 0,
- .has_tint_cstat = true,
- .tclk_mask = (1 << 5),
-};
-
-void __init samsung_set_timer_source(unsigned int event, unsigned int source)
-{
- s5pv210_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
- s5pv210_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
-}
-
-void __init samsung_timer_init(void)
-{
- unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
- IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
- IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
- };
-
- samsung_pwm_clocksource_init(S3C_VA_TIMER,
- timer_irqs, &s5pv210_pwm_variant);
-}
-
-/*
- * s5pv210_map_io
- *
- * register the standard cpu IO areas
- */
-
-void __init s5pv210_init_io(struct map_desc *mach_desc, int size)
-{
- /* initialize the io descriptors we need for initialization */
- iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
- if (mach_desc)
- iotable_init(mach_desc, size);
-
- /* detect cpu id and rev. */
- s5p_init_cpu(S5P_VA_CHIPID);
-
- s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
-
- samsung_pwm_set_platdata(&s5pv210_pwm_variant);
-}
-
-void __init s5pv210_map_io(void)
-{
- /* initialise device information early */
- s5pv210_default_sdhci0();
- s5pv210_default_sdhci1();
- s5pv210_default_sdhci2();
- s5pv210_default_sdhci3();
-
- s3c_adc_setname("samsung-adc-v3");
-
- s3c_cfcon_setname("s5pv210-pata");
-
- s3c_fimc_setname(0, "s5pv210-fimc");
- s3c_fimc_setname(1, "s5pv210-fimc");
- s3c_fimc_setname(2, "s5pv210-fimc");
-
- /* the i2c devices are directly compatible with s3c2440 */
- s3c_i2c0_setname("s3c2440-i2c");
- s3c_i2c1_setname("s3c2440-i2c");
- s3c_i2c2_setname("s3c2440-i2c");
-
- s3c_fb_setname("s5pv210-fb");
-
- /* Use s5pv210-keypad instead of samsung-keypad */
- samsung_keypad_setname("s5pv210-keypad");
-
- /* setup TV devices */
- s5p_hdmi_setname("s5pv210-hdmi");
-
- s3c64xx_spi_setname("s5pv210-spi");
-}
-
-void __init s5pv210_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
- s3c24xx_register_baseclocks(xtal);
- s5p_register_clocks(xtal);
- s5pv210_register_clocks();
- s5pv210_setup_clocks();
-}
-
-void __init s5pv210_init_irq(void)
-{
- u32 vic[4]; /* S5PV210 supports 4 VIC */
-
- /* All the VICs are fully populated. */
- vic[0] = ~0;
- vic[1] = ~0;
- vic[2] = ~0;
- vic[3] = ~0;
-
- s5p_init_irq(vic, ARRAY_SIZE(vic));
-}
-
-struct bus_type s5pv210_subsys = {
- .name = "s5pv210-core",
- .dev_name = "s5pv210-core",
-};
-
-static struct device s5pv210_dev = {
- .bus = &s5pv210_subsys,
-};
-
-static int __init s5pv210_core_init(void)
-{
- return subsys_system_register(&s5pv210_subsys, NULL);
-}
-core_initcall(s5pv210_core_init);
-
-int __init s5pv210_init(void)
-{
- printk(KERN_INFO "S5PV210: Initializing architecture\n");
- return device_register(&s5pv210_dev);
-}
-
-/* uart registration process */
-
-void __init s5pv210_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff --git a/arch/arm/mach-s5pv210/common.h b/arch/arm/mach-s5pv210/common.h
index fe1beb54e548..2ad387c1ecf0 100644
--- a/arch/arm/mach-s5pv210/common.h
+++ b/arch/arm/mach-s5pv210/common.h
@@ -12,19 +12,12 @@
#ifndef __ARCH_ARM_MACH_S5PV210_COMMON_H
#define __ARCH_ARM_MACH_S5PV210_COMMON_H
-#include <linux/reboot.h>
-
-void s5pv210_init_io(struct map_desc *mach_desc, int size);
-void s5pv210_init_irq(void);
-
-void s5pv210_register_clocks(void);
-void s5pv210_setup_clocks(void);
-
-void s5pv210_restart(enum reboot_mode mode, const char *cmd);
-
-extern int s5pv210_init(void);
-extern void s5pv210_map_io(void);
-extern void s5pv210_init_clocks(int xtal);
-extern void s5pv210_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+#ifdef CONFIG_PM_SLEEP
+u32 exynos_get_eint_wake_mask(void);
+void s5pv210_cpu_resume(void);
+void s5pv210_pm_init(void);
+#else
+static inline void s5pv210_pm_init(void) {}
+#endif
#endif /* __ARCH_ARM_MACH_S5PV210_COMMON_H */
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
deleted file mode 100644
index 2d67361ef431..000000000000
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <linux/platform_data/asoc-s3c.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-#define S5PV210_AUDSS_INT_MEM (0xC0000000)
-
-static int s5pv210_cfg_i2s(struct platform_device *pdev)
-{
- /* configure GPIO for i2s port */
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2));
- break;
- case 1:
- s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2));
- break;
- case 2:
- s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4));
- break;
- default:
- printk(KERN_ERR "Invalid Device %d\n", pdev->id);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
- .cfg_gpio = s5pv210_cfg_i2s,
- .type = {
- .i2s = {
- .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
- | QUIRK_NEED_RSTCLR,
- .idma_addr = S5PV210_AUDSS_INT_MEM,
- },
- },
-};
-
-static struct resource s5pv210_iis0_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_IIS0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S0_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S0_RX),
- [3] = DEFINE_RES_DMA(DMACH_I2S0S_TX),
-};
-
-struct platform_device s5pv210_device_iis0 = {
- .name = "samsung-i2s",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5pv210_iis0_resource),
- .resource = s5pv210_iis0_resource,
- .dev = {
- .platform_data = &i2sv5_pdata,
- },
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
- .cfg_gpio = s5pv210_cfg_i2s,
-};
-
-static struct resource s5pv210_iis1_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_IIS1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S1_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S1_RX),
-};
-
-struct platform_device s5pv210_device_iis1 = {
- .name = "samsung-i2s",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5pv210_iis1_resource),
- .resource = s5pv210_iis1_resource,
- .dev = {
- .platform_data = &i2sv3_pdata,
- },
-};
-
-static struct resource s5pv210_iis2_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_IIS2, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_I2S2_TX),
- [2] = DEFINE_RES_DMA(DMACH_I2S2_RX),
-};
-
-struct platform_device s5pv210_device_iis2 = {
- .name = "samsung-i2s",
- .id = 2,
- .num_resources = ARRAY_SIZE(s5pv210_iis2_resource),
- .resource = s5pv210_iis2_resource,
- .dev = {
- .platform_data = &i2sv3_pdata,
- },
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev)
-{
- switch (pdev->id) {
- case 0:
- s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3));
- break;
- case 1:
- s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3));
- break;
- case 2:
- s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2));
- break;
- default:
- printk(KERN_DEBUG "Invalid PCM Controller number!");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
- .cfg_gpio = s5pv210_pcm_cfg_gpio,
-};
-
-static struct resource s5pv210_pcm0_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_PCM0, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
-};
-
-struct platform_device s5pv210_device_pcm0 = {
- .name = "samsung-pcm",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5pv210_pcm0_resource),
- .resource = s5pv210_pcm0_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
-
-static struct resource s5pv210_pcm1_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_PCM1, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
-};
-
-struct platform_device s5pv210_device_pcm1 = {
- .name = "samsung-pcm",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5pv210_pcm1_resource),
- .resource = s5pv210_pcm1_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
-
-static struct resource s5pv210_pcm2_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_PCM2, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_PCM2_TX),
- [2] = DEFINE_RES_DMA(DMACH_PCM2_RX),
-};
-
-struct platform_device s5pv210_device_pcm2 = {
- .name = "samsung-pcm",
- .id = 2,
- .num_resources = ARRAY_SIZE(s5pv210_pcm2_resource),
- .resource = s5pv210_pcm2_resource,
- .dev = {
- .platform_data = &s3c_pcm_pdata,
- },
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev)
-{
- return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pv210_ac97_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_AC97, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
- [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
- [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
- [4] = DEFINE_RES_IRQ(IRQ_AC97),
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
- .cfg_gpio = s5pv210_ac97_cfg_gpio,
-};
-
-static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv210_device_ac97 = {
- .name = "samsung-ac97",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pv210_ac97_resource),
- .resource = s5pv210_ac97_resource,
- .dev = {
- .platform_data = &s3c_ac97_pdata,
- .dma_mask = &s5pv210_ac97_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-/* S/PDIF Controller platform_device */
-
-static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev)
-{
- s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3));
-
- return 0;
-}
-
-static struct resource s5pv210_spdif_resource[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_SPDIF, SZ_256),
- [1] = DEFINE_RES_DMA(DMACH_SPDIF),
-};
-
-static struct s3c_audio_pdata samsung_spdif_pdata = {
- .cfg_gpio = s5pv210_spdif_cfg_gpio,
-};
-
-static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv210_device_spdif = {
- .name = "samsung-spdif",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5pv210_spdif_resource),
- .resource = s5pv210_spdif_resource,
- .dev = {
- .platform_data = &samsung_spdif_pdata,
- .dma_mask = &s5pv210_spdif_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
deleted file mode 100644
index b8337e248b09..000000000000
--- a/arch/arm/mach-s5pv210/dma.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/dma.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
-
-#include <asm/irq.h>
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/dma.h>
-
-static u8 pdma0_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_MAX,
- DMACH_I2S0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0S_TX,
- DMACH_I2S1_RX,
- DMACH_I2S1_TX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_SPI0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI1_RX,
- DMACH_SPI1_TX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_AC97_MICIN,
- DMACH_AC97_PCMIN,
- DMACH_AC97_PCMOUT,
- DMACH_MAX,
- DMACH_PWM,
- DMACH_SPDIF,
-};
-
-static struct dma_pl330_platdata s5pv210_pdma0_pdata = {
- .nr_valid_peri = ARRAY_SIZE(pdma0_peri),
- .peri_id = pdma0_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pv210_pdma0, "dma-pl330.0", 0x00041330,
- S5PV210_PA_PDMA0, {IRQ_PDMA0}, &s5pv210_pdma0_pdata);
-
-static u8 pdma1_peri[] = {
- DMACH_UART0_RX,
- DMACH_UART0_TX,
- DMACH_UART1_RX,
- DMACH_UART1_TX,
- DMACH_UART2_RX,
- DMACH_UART2_TX,
- DMACH_UART3_RX,
- DMACH_UART3_TX,
- DMACH_MAX,
- DMACH_I2S0_RX,
- DMACH_I2S0_TX,
- DMACH_I2S0S_TX,
- DMACH_I2S1_RX,
- DMACH_I2S1_TX,
- DMACH_I2S2_RX,
- DMACH_I2S2_TX,
- DMACH_SPI0_RX,
- DMACH_SPI0_TX,
- DMACH_SPI1_RX,
- DMACH_SPI1_TX,
- DMACH_MAX,
- DMACH_MAX,
- DMACH_PCM0_RX,
- DMACH_PCM0_TX,
- DMACH_PCM1_RX,
- DMACH_PCM1_TX,
- DMACH_MSM_REQ0,
- DMACH_MSM_REQ1,
- DMACH_MSM_REQ2,
- DMACH_MSM_REQ3,
- DMACH_PCM2_RX,
- DMACH_PCM2_TX,
-};
-
-static struct dma_pl330_platdata s5pv210_pdma1_pdata = {
- .nr_valid_peri = ARRAY_SIZE(pdma1_peri),
- .peri_id = pdma1_peri,
-};
-
-static AMBA_AHB_DEVICE(s5pv210_pdma1, "dma-pl330.1", 0x00041330,
- S5PV210_PA_PDMA1, {IRQ_PDMA1}, &s5pv210_pdma1_pdata);
-
-static int __init s5pv210_dma_init(void)
-{
- dma_cap_set(DMA_SLAVE, s5pv210_pdma0_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5pv210_pdma0_pdata.cap_mask);
- amba_device_register(&s5pv210_pdma0_device, &iomem_resource);
-
- dma_cap_set(DMA_SLAVE, s5pv210_pdma1_pdata.cap_mask);
- dma_cap_set(DMA_CYCLIC, s5pv210_pdma1_pdata.cap_mask);
- amba_device_register(&s5pv210_pdma1_device, &iomem_resource);
-
- return 0;
-}
-arch_initcall(s5pv210_dma_init);
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h
deleted file mode 100644
index 6c8b903c02e4..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/gpio.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-/* Practically, GPIO banks up to MP03 are the configurable gpio banks */
-
-/* GPIO bank sizes */
-#define S5PV210_GPIO_A0_NR (8)
-#define S5PV210_GPIO_A1_NR (4)
-#define S5PV210_GPIO_B_NR (8)
-#define S5PV210_GPIO_C0_NR (5)
-#define S5PV210_GPIO_C1_NR (5)
-#define S5PV210_GPIO_D0_NR (4)
-#define S5PV210_GPIO_D1_NR (6)
-#define S5PV210_GPIO_E0_NR (8)
-#define S5PV210_GPIO_E1_NR (5)
-#define S5PV210_GPIO_F0_NR (8)
-#define S5PV210_GPIO_F1_NR (8)
-#define S5PV210_GPIO_F2_NR (8)
-#define S5PV210_GPIO_F3_NR (6)
-#define S5PV210_GPIO_G0_NR (7)
-#define S5PV210_GPIO_G1_NR (7)
-#define S5PV210_GPIO_G2_NR (7)
-#define S5PV210_GPIO_G3_NR (7)
-#define S5PV210_GPIO_H0_NR (8)
-#define S5PV210_GPIO_H1_NR (8)
-#define S5PV210_GPIO_H2_NR (8)
-#define S5PV210_GPIO_H3_NR (8)
-#define S5PV210_GPIO_I_NR (7)
-#define S5PV210_GPIO_J0_NR (8)
-#define S5PV210_GPIO_J1_NR (6)
-#define S5PV210_GPIO_J2_NR (8)
-#define S5PV210_GPIO_J3_NR (8)
-#define S5PV210_GPIO_J4_NR (5)
-
-#define S5PV210_GPIO_MP01_NR (8)
-#define S5PV210_GPIO_MP02_NR (4)
-#define S5PV210_GPIO_MP03_NR (8)
-#define S5PV210_GPIO_MP04_NR (8)
-#define S5PV210_GPIO_MP05_NR (8)
-
-/* GPIO bank numbers */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S5PV210_GPIO_NEXT(__gpio) \
- ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
- S5PV210_GPIO_A0_START = 0,
- S5PV210_GPIO_A1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_A0),
- S5PV210_GPIO_B_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_A1),
- S5PV210_GPIO_C0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_B),
- S5PV210_GPIO_C1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_C0),
- S5PV210_GPIO_D0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_C1),
- S5PV210_GPIO_D1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_D0),
- S5PV210_GPIO_E0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_D1),
- S5PV210_GPIO_E1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_E0),
- S5PV210_GPIO_F0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_E1),
- S5PV210_GPIO_F1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_F0),
- S5PV210_GPIO_F2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_F1),
- S5PV210_GPIO_F3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_F2),
- S5PV210_GPIO_G0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_F3),
- S5PV210_GPIO_G1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_G0),
- S5PV210_GPIO_G2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_G1),
- S5PV210_GPIO_G3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_G2),
- S5PV210_GPIO_H0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_G3),
- S5PV210_GPIO_H1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_H0),
- S5PV210_GPIO_H2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_H1),
- S5PV210_GPIO_H3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_H2),
- S5PV210_GPIO_I_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_H3),
- S5PV210_GPIO_J0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_I),
- S5PV210_GPIO_J1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J0),
- S5PV210_GPIO_J2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),
- S5PV210_GPIO_J3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J2),
- S5PV210_GPIO_J4_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J3),
- S5PV210_GPIO_MP01_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J4),
- S5PV210_GPIO_MP02_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01),
- S5PV210_GPIO_MP03_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02),
- S5PV210_GPIO_MP04_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03),
- S5PV210_GPIO_MP05_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP04),
-};
-
-/* S5PV210 GPIO number definitions */
-#define S5PV210_GPA0(_nr) (S5PV210_GPIO_A0_START + (_nr))
-#define S5PV210_GPA1(_nr) (S5PV210_GPIO_A1_START + (_nr))
-#define S5PV210_GPB(_nr) (S5PV210_GPIO_B_START + (_nr))
-#define S5PV210_GPC0(_nr) (S5PV210_GPIO_C0_START + (_nr))
-#define S5PV210_GPC1(_nr) (S5PV210_GPIO_C1_START + (_nr))
-#define S5PV210_GPD0(_nr) (S5PV210_GPIO_D0_START + (_nr))
-#define S5PV210_GPD1(_nr) (S5PV210_GPIO_D1_START + (_nr))
-#define S5PV210_GPE0(_nr) (S5PV210_GPIO_E0_START + (_nr))
-#define S5PV210_GPE1(_nr) (S5PV210_GPIO_E1_START + (_nr))
-#define S5PV210_GPF0(_nr) (S5PV210_GPIO_F0_START + (_nr))
-#define S5PV210_GPF1(_nr) (S5PV210_GPIO_F1_START + (_nr))
-#define S5PV210_GPF2(_nr) (S5PV210_GPIO_F2_START + (_nr))
-#define S5PV210_GPF3(_nr) (S5PV210_GPIO_F3_START + (_nr))
-#define S5PV210_GPG0(_nr) (S5PV210_GPIO_G0_START + (_nr))
-#define S5PV210_GPG1(_nr) (S5PV210_GPIO_G1_START + (_nr))
-#define S5PV210_GPG2(_nr) (S5PV210_GPIO_G2_START + (_nr))
-#define S5PV210_GPG3(_nr) (S5PV210_GPIO_G3_START + (_nr))
-#define S5PV210_GPH0(_nr) (S5PV210_GPIO_H0_START + (_nr))
-#define S5PV210_GPH1(_nr) (S5PV210_GPIO_H1_START + (_nr))
-#define S5PV210_GPH2(_nr) (S5PV210_GPIO_H2_START + (_nr))
-#define S5PV210_GPH3(_nr) (S5PV210_GPIO_H3_START + (_nr))
-#define S5PV210_GPI(_nr) (S5PV210_GPIO_I_START + (_nr))
-#define S5PV210_GPJ0(_nr) (S5PV210_GPIO_J0_START + (_nr))
-#define S5PV210_GPJ1(_nr) (S5PV210_GPIO_J1_START + (_nr))
-#define S5PV210_GPJ2(_nr) (S5PV210_GPIO_J2_START + (_nr))
-#define S5PV210_GPJ3(_nr) (S5PV210_GPIO_J3_START + (_nr))
-#define S5PV210_GPJ4(_nr) (S5PV210_GPIO_J4_START + (_nr))
-#define S5PV210_MP01(_nr) (S5PV210_GPIO_MP01_START + (_nr))
-#define S5PV210_MP02(_nr) (S5PV210_GPIO_MP02_START + (_nr))
-#define S5PV210_MP03(_nr) (S5PV210_GPIO_MP03_START + (_nr))
-#define S5PV210_MP04(_nr) (S5PV210_GPIO_MP04_START + (_nr))
-#define S5PV210_MP05(_nr) (S5PV210_GPIO_MP05_START + (_nr))
-
-/* the end of the S5PV210 specific gpios */
-#define S5PV210_GPIO_END (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + 1)
-#define S3C_GPIO_END S5PV210_GPIO_END
-
-/* define the number of gpios we need to the one after the MP05() range */
-#define ARCH_NR_GPIOS (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + \
- CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/hardware.h b/arch/arm/mach-s5pv210/include/mach/hardware.h
deleted file mode 100644
index fada7a392d09..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/hardware.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - Hardware support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
deleted file mode 100644
index 5e0de3a31f3d..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/irqs.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* VIC0: System, DMA, Timer */
-
-#define IRQ_EINT16_31 S5P_IRQ_VIC0(16)
-#define IRQ_BATF S5P_IRQ_VIC0(17)
-#define IRQ_MDMA S5P_IRQ_VIC0(18)
-#define IRQ_PDMA0 S5P_IRQ_VIC0(19)
-#define IRQ_PDMA1 S5P_IRQ_VIC0(20)
-#define IRQ_TIMER0_VIC S5P_IRQ_VIC0(21)
-#define IRQ_TIMER1_VIC S5P_IRQ_VIC0(22)
-#define IRQ_TIMER2_VIC S5P_IRQ_VIC0(23)
-#define IRQ_TIMER3_VIC S5P_IRQ_VIC0(24)
-#define IRQ_TIMER4_VIC S5P_IRQ_VIC0(25)
-#define IRQ_SYSTIMER S5P_IRQ_VIC0(26)
-#define IRQ_WDT S5P_IRQ_VIC0(27)
-#define IRQ_RTC_ALARM S5P_IRQ_VIC0(28)
-#define IRQ_RTC_TIC S5P_IRQ_VIC0(29)
-#define IRQ_GPIOINT S5P_IRQ_VIC0(30)
-#define IRQ_FIMC3 S5P_IRQ_VIC0(31)
-
-/* VIC1: ARM, Power, Memory, Connectivity, Storage */
-
-#define IRQ_PMU S5P_IRQ_VIC1(0)
-#define IRQ_CORTEX1 S5P_IRQ_VIC1(1)
-#define IRQ_CORTEX2 S5P_IRQ_VIC1(2)
-#define IRQ_CORTEX3 S5P_IRQ_VIC1(3)
-#define IRQ_CORTEX4 S5P_IRQ_VIC1(4)
-#define IRQ_IEMAPC S5P_IRQ_VIC1(5)
-#define IRQ_IEMIEC S5P_IRQ_VIC1(6)
-#define IRQ_ONENAND S5P_IRQ_VIC1(7)
-#define IRQ_NFC S5P_IRQ_VIC1(8)
-#define IRQ_CFCON S5P_IRQ_VIC1(9)
-#define IRQ_UART0 S5P_IRQ_VIC1(10)
-#define IRQ_UART1 S5P_IRQ_VIC1(11)
-#define IRQ_UART2 S5P_IRQ_VIC1(12)
-#define IRQ_UART3 S5P_IRQ_VIC1(13)
-#define IRQ_IIC S5P_IRQ_VIC1(14)
-#define IRQ_SPI0 S5P_IRQ_VIC1(15)
-#define IRQ_SPI1 S5P_IRQ_VIC1(16)
-#define IRQ_SPI2 S5P_IRQ_VIC1(17)
-#define IRQ_IRDA S5P_IRQ_VIC1(18)
-#define IRQ_IIC2 S5P_IRQ_VIC1(19)
-#define IRQ_IIC_HDMIPHY S5P_IRQ_VIC1(20)
-#define IRQ_HSIRX S5P_IRQ_VIC1(21)
-#define IRQ_HSITX S5P_IRQ_VIC1(22)
-#define IRQ_UHOST S5P_IRQ_VIC1(23)
-#define IRQ_OTG S5P_IRQ_VIC1(24)
-#define IRQ_MSM S5P_IRQ_VIC1(25)
-#define IRQ_HSMMC0 S5P_IRQ_VIC1(26)
-#define IRQ_HSMMC1 S5P_IRQ_VIC1(27)
-#define IRQ_HSMMC2 S5P_IRQ_VIC1(28)
-#define IRQ_MIPI_CSIS S5P_IRQ_VIC1(29)
-#define IRQ_MIPIDSI S5P_IRQ_VIC1(30)
-#define IRQ_ONENAND_AUDI S5P_IRQ_VIC1(31)
-
-/* VIC2: Multimedia, Audio, Security */
-
-#define IRQ_LCD0 S5P_IRQ_VIC2(0)
-#define IRQ_LCD1 S5P_IRQ_VIC2(1)
-#define IRQ_LCD2 S5P_IRQ_VIC2(2)
-#define IRQ_LCD3 S5P_IRQ_VIC2(3)
-#define IRQ_ROTATOR S5P_IRQ_VIC2(4)
-#define IRQ_FIMC0 S5P_IRQ_VIC2(5)
-#define IRQ_FIMC1 S5P_IRQ_VIC2(6)
-#define IRQ_FIMC2 S5P_IRQ_VIC2(7)
-#define IRQ_JPEG S5P_IRQ_VIC2(8)
-#define IRQ_2D S5P_IRQ_VIC2(9)
-#define IRQ_3D S5P_IRQ_VIC2(10)
-#define IRQ_MIXER S5P_IRQ_VIC2(11)
-#define IRQ_HDMI S5P_IRQ_VIC2(12)
-#define IRQ_IIC1 S5P_IRQ_VIC2(13)
-#define IRQ_MFC S5P_IRQ_VIC2(14)
-#define IRQ_SDO S5P_IRQ_VIC2(15)
-#define IRQ_I2S0 S5P_IRQ_VIC2(16)
-#define IRQ_I2S1 S5P_IRQ_VIC2(17)
-#define IRQ_I2S2 S5P_IRQ_VIC2(18)
-#define IRQ_AC97 S5P_IRQ_VIC2(19)
-#define IRQ_PCM0 S5P_IRQ_VIC2(20)
-#define IRQ_PCM1 S5P_IRQ_VIC2(21)
-#define IRQ_SPDIF S5P_IRQ_VIC2(22)
-#define IRQ_ADC S5P_IRQ_VIC2(23)
-#define IRQ_PENDN S5P_IRQ_VIC2(24)
-#define IRQ_TC IRQ_PENDN
-#define IRQ_KEYPAD S5P_IRQ_VIC2(25)
-#define IRQ_CG S5P_IRQ_VIC2(26)
-#define IRQ_SSS_INT S5P_IRQ_VIC2(27)
-#define IRQ_SSS_HASH S5P_IRQ_VIC2(28)
-#define IRQ_PCM2 S5P_IRQ_VIC2(29)
-#define IRQ_SDMIRQ S5P_IRQ_VIC2(30)
-#define IRQ_SDMFIQ S5P_IRQ_VIC2(31)
-
-/* VIC3: Etc */
-
-#define IRQ_IPC S5P_IRQ_VIC3(0)
-#define IRQ_HOSTIF S5P_IRQ_VIC3(1)
-#define IRQ_HSMMC3 S5P_IRQ_VIC3(2)
-#define IRQ_CEC S5P_IRQ_VIC3(3)
-#define IRQ_TSI S5P_IRQ_VIC3(4)
-#define IRQ_MDNIE0 S5P_IRQ_VIC3(5)
-#define IRQ_MDNIE1 S5P_IRQ_VIC3(6)
-#define IRQ_MDNIE2 S5P_IRQ_VIC3(7)
-#define IRQ_MDNIE3 S5P_IRQ_VIC3(8)
-#define IRQ_VIC_END S5P_IRQ_VIC3(31)
-
-#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
-#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
-
-/* GPIO interrupt */
-#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
-#define S5P_GPIOINT_GROUP_MAXNR 22
-
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
-
-/* Compatibility */
-#define IRQ_LCD_FIFO IRQ_LCD0
-#define IRQ_LCD_VSYNC IRQ_LCD1
-#define IRQ_LCD_SYSTEM IRQ_LCD2
-#define IRQ_MIPI_CSIS0 IRQ_MIPI_CSIS
-
-#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
deleted file mode 100644
index 763929aca52d..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/map.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-#include <plat/map-s5p.h>
-
-#define S5PV210_PA_SDRAM 0x20000000
-
-#define S5PV210_PA_SROM_BANK5 0xA8000000
-
-#define S5PC110_PA_ONENAND 0xB0000000
-#define S5PC110_PA_ONENAND_DMA 0xB0600000
-
-#define S5PV210_PA_CHIPID 0xE0000000
-
-#define S5PV210_PA_SYSCON 0xE0100000
-
-#define S5PV210_PA_GPIO 0xE0200000
-
-#define S5PV210_PA_SPDIF 0xE1100000
-
-#define S5PV210_PA_SPI0 0xE1300000
-#define S5PV210_PA_SPI1 0xE1400000
-
-#define S5PV210_PA_KEYPAD 0xE1600000
-
-#define S5PV210_PA_ADC 0xE1700000
-
-#define S5PV210_PA_IIC0 0xE1800000
-#define S5PV210_PA_IIC1 0xFAB00000
-#define S5PV210_PA_IIC2 0xE1A00000
-
-#define S5PV210_PA_AC97 0xE2200000
-
-#define S5PV210_PA_PCM0 0xE2300000
-#define S5PV210_PA_PCM1 0xE1200000
-#define S5PV210_PA_PCM2 0xE2B00000
-
-#define S5PV210_PA_TIMER 0xE2500000
-#define S5PV210_PA_SYSTIMER 0xE2600000
-#define S5PV210_PA_WATCHDOG 0xE2700000
-#define S5PV210_PA_RTC 0xE2800000
-
-#define S5PV210_PA_UART 0xE2900000
-
-#define S5PV210_PA_SROMC 0xE8000000
-
-#define S5PV210_PA_CFCON 0xE8200000
-
-#define S5PV210_PA_MFC 0xF1700000
-
-#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
-
-#define S5PV210_PA_HSOTG 0xEC000000
-#define S5PV210_PA_HSPHY 0xEC100000
-
-#define S5PV210_PA_IIS0 0xEEE30000
-#define S5PV210_PA_IIS1 0xE2100000
-#define S5PV210_PA_IIS2 0xE2A00000
-
-#define S5PV210_PA_DMC0 0xF0000000
-#define S5PV210_PA_DMC1 0xF1400000
-
-#define S5PV210_PA_VIC0 0xF2000000
-#define S5PV210_PA_VIC1 0xF2100000
-#define S5PV210_PA_VIC2 0xF2200000
-#define S5PV210_PA_VIC3 0xF2300000
-
-#define S5PV210_PA_FB 0xF8000000
-
-#define S5PV210_PA_MDMA 0xFA200000
-#define S5PV210_PA_PDMA0 0xE0900000
-#define S5PV210_PA_PDMA1 0xE0A00000
-
-#define S5PV210_PA_MIPI_CSIS 0xFA600000
-
-#define S5PV210_PA_FIMC0 0xFB200000
-#define S5PV210_PA_FIMC1 0xFB300000
-#define S5PV210_PA_FIMC2 0xFB400000
-
-#define S5PV210_PA_JPEG 0xFB600000
-
-#define S5PV210_PA_SDO 0xF9000000
-#define S5PV210_PA_VP 0xF9100000
-#define S5PV210_PA_MIXER 0xF9200000
-#define S5PV210_PA_HDMI 0xFA100000
-#define S5PV210_PA_IIC_HDMIPHY 0xFA900000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_FB S5PV210_PA_FB
-#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0)
-#define S3C_PA_HSMMC1 S5PV210_PA_HSMMC(1)
-#define S3C_PA_HSMMC2 S5PV210_PA_HSMMC(2)
-#define S3C_PA_HSMMC3 S5PV210_PA_HSMMC(3)
-#define S3C_PA_IIC S5PV210_PA_IIC0
-#define S3C_PA_IIC1 S5PV210_PA_IIC1
-#define S3C_PA_IIC2 S5PV210_PA_IIC2
-#define S3C_PA_RTC S5PV210_PA_RTC
-#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG
-#define S3C_PA_WDT S5PV210_PA_WATCHDOG
-#define S3C_PA_SPI0 S5PV210_PA_SPI0
-#define S3C_PA_SPI1 S5PV210_PA_SPI1
-
-#define S5P_PA_CHIPID S5PV210_PA_CHIPID
-#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
-#define S5P_PA_FIMC1 S5PV210_PA_FIMC1
-#define S5P_PA_FIMC2 S5PV210_PA_FIMC2
-#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS
-#define S5P_PA_MFC S5PV210_PA_MFC
-#define S5P_PA_IIC_HDMIPHY S5PV210_PA_IIC_HDMIPHY
-
-#define S5P_PA_SDO S5PV210_PA_SDO
-#define S5P_PA_VP S5PV210_PA_VP
-#define S5P_PA_MIXER S5PV210_PA_MIXER
-#define S5P_PA_HDMI S5PV210_PA_HDMI
-
-#define S5P_PA_ONENAND S5PC110_PA_ONENAND
-#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA
-#define S5P_PA_SDRAM S5PV210_PA_SDRAM
-#define S5P_PA_SROMC S5PV210_PA_SROMC
-#define S5P_PA_SYSCON S5PV210_PA_SYSCON
-#define S5P_PA_TIMER S5PV210_PA_TIMER
-
-#define S5P_PA_JPEG S5PV210_PA_JPEG
-
-#define SAMSUNG_PA_ADC S5PV210_PA_ADC
-#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON
-#define SAMSUNG_PA_KEYPAD S5PV210_PA_KEYPAD
-#define SAMSUNG_PA_TIMER S5PV210_PA_TIMER
-
-/* UART */
-
-#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-
-#define S3C_PA_UART S5PV210_PA_UART
-
-#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0 S5P_PA_UART(0)
-#define S5P_PA_UART1 S5P_PA_UART(1)
-#define S5P_PA_UART2 S5P_PA_UART(2)
-#define S5P_PA_UART3 S5P_PA_UART(3)
-
-#define S5P_SZ_UART SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h
deleted file mode 100644
index 2d3cfa221d5f..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/memory.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/memory.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#define PLAT_PHYS_OFFSET UL(0x20000000)
-
-/*
- * Sparsemem support
- * Physical memory can be located from 0x20000000 to 0x7fffffff,
- * so MAX_PHYSMEM_BITS is 31.
- */
-
-#define MAX_PHYSMEM_BITS 31
-#define SECTION_SIZE_BITS 28
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
deleted file mode 100644
index eba8aea63ed8..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/pm-core.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-static inline void s3c_pm_debug_init_uart(void)
-{
- /* nothing here yet */
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
- __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
- __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void)
-{
- /* nothing here yet */
-}
-
-static inline void s3c_pm_arch_show_resume_irqs(void)
-{
- /* nothing here yet */
-}
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
- struct pm_uart_save *save)
-{
- /* nothing here yet */
-}
-
-static inline void s3c_pm_restored_gpios(void) { }
-static inline void samsung_pm_saved_gpios(void) { }
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index e345584d4c34..b14ffcd7f6cc 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -13,7 +13,7 @@
#ifndef __ASM_ARCH_REGS_CLOCK_H
#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-#include <mach/map.h>
+#include <plat/map-base.h>
#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
deleted file mode 100644
index de0c89976078..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5PV210 - GPIO (including EINT) register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-#define S5PV210_EINT30CON (S5P_VA_GPIO + 0xE00)
-#define S5P_EINT_CON(x) (S5PV210_EINT30CON + ((x) * 0x4))
-
-#define S5PV210_EINT30FLTCON0 (S5P_VA_GPIO + 0xE80)
-#define S5P_EINT_FLTCON(x) (S5PV210_EINT30FLTCON0 + ((x) * 0x4))
-
-#define S5PV210_EINT30MASK (S5P_VA_GPIO + 0xF00)
-#define S5P_EINT_MASK(x) (S5PV210_EINT30MASK + ((x) * 0x4))
-
-#define S5PV210_EINT30PEND (S5P_VA_GPIO + 0xF40)
-#define S5P_EINT_PEND(x) (S5PV210_EINT30PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x) S5PV210_GPH0(x)
-#define EINT_GPIO_1(x) S5PV210_GPH1(x)
-#define EINT_GPIO_2(x) S5PV210_GPH2(x)
-#define EINT_GPIO_3(x) S5PV210_GPH3(x)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
deleted file mode 100644
index d8bc1e6c7aaa..000000000000
--- a/arch/arm/mach-s5pv210/include/mach/regs-irq.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/regs-irq.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
deleted file mode 100644
index cc37edacda26..000000000000
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-aquila.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
-#include <linux/mfd/max8998.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/regulator/fixed.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <plat/fimc-core.h>
-#include <plat/sdhci.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define AQUILA_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define AQUILA_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define AQUILA_UFCON_DEFAULT S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = AQUILA_UCON_DEFAULT,
- .ulcon = AQUILA_ULCON_DEFAULT,
- /*
- * Actually UART0 can support 256 bytes fifo, but aquila board
- * supports 128 bytes fifo because of initial chip bug
- */
- .ufcon = AQUILA_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG128 | S5PV210_UFCON_RXTRIG128,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = AQUILA_UCON_DEFAULT,
- .ulcon = AQUILA_ULCON_DEFAULT,
- .ufcon = AQUILA_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = AQUILA_UCON_DEFAULT,
- .ulcon = AQUILA_ULCON_DEFAULT,
- .ufcon = AQUILA_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = AQUILA_UCON_DEFAULT,
- .ulcon = AQUILA_ULCON_DEFAULT,
- .ufcon = AQUILA_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
- },
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win aquila_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 16,
- .xres = 480,
- .yres = 800,
-};
-
-static struct s3c_fb_pd_win aquila_fb_win1 = {
- .max_bpp = 32,
- .default_bpp = 16,
- .xres = 480,
- .yres = 800,
-};
-
-static struct fb_videomode aquila_lcd_timing = {
- .left_margin = 16,
- .right_margin = 16,
- .upper_margin = 3,
- .lower_margin = 28,
- .hsync_len = 2,
- .vsync_len = 2,
- .xres = 480,
- .yres = 800,
-};
-
-static struct s3c_fb_platdata aquila_lcd_pdata __initdata = {
- .win[0] = &aquila_fb_win0,
- .win[1] = &aquila_fb_win1,
- .vtiming = &aquila_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
- VIDCON1_INV_VCLK | VIDCON1_INV_VDEN,
- .setup_gpio = s5pv210_fb_gpio_setup_24bpp,
-};
-
-/* MAX8998 regulators */
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-
-static struct regulator_init_data aquila_ldo2_data = {
- .constraints = {
- .name = "VALIVE_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .always_on = 1,
- .state_mem = {
- .enabled = 1,
- },
- },
-};
-
-static struct regulator_init_data aquila_ldo3_data = {
- .constraints = {
- .name = "VUSB+MIPI_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo4_data = {
- .constraints = {
- .name = "VDAC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo5_data = {
- .constraints = {
- .name = "VTF_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo6_data = {
- .constraints = {
- .name = "VCC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo7_data = {
- .constraints = {
- .name = "VCC_3.0V",
- .min_uV = 3000000,
- .max_uV = 3000000,
- .apply_uV = 1,
- .boot_on = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo8_data = {
- .constraints = {
- .name = "VUSB+VADC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo9_data = {
- .constraints = {
- .name = "VCC+VCAM_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo10_data = {
- .constraints = {
- .name = "VPLL_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .boot_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo11_data = {
- .constraints = {
- .name = "CAM_IO_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo12_data = {
- .constraints = {
- .name = "CAM_ISP_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo13_data = {
- .constraints = {
- .name = "CAM_A_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo14_data = {
- .constraints = {
- .name = "CAM_CIF_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo15_data = {
- .constraints = {
- .name = "CAM_AF_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo16_data = {
- .constraints = {
- .name = "VMIPI_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data aquila_ldo17_data = {
- .constraints = {
- .name = "CAM_8M_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-/* BUCK */
-static struct regulator_consumer_supply buck1_consumer =
- REGULATOR_SUPPLY("vddarm", NULL);
-
-static struct regulator_consumer_supply buck2_consumer =
- REGULATOR_SUPPLY("vddint", NULL);
-
-static struct regulator_init_data aquila_buck1_data = {
- .constraints = {
- .name = "VARM_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &buck1_consumer,
-};
-
-static struct regulator_init_data aquila_buck2_data = {
- .constraints = {
- .name = "VINT_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &buck2_consumer,
-};
-
-static struct regulator_init_data aquila_buck3_data = {
- .constraints = {
- .name = "VCC_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .state_mem = {
- .enabled = 1,
- },
- },
-};
-
-static struct regulator_init_data aquila_buck4_data = {
- .constraints = {
- .name = "CAM_CORE_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct max8998_regulator_data aquila_regulators[] = {
- { MAX8998_LDO2, &aquila_ldo2_data },
- { MAX8998_LDO3, &aquila_ldo3_data },
- { MAX8998_LDO4, &aquila_ldo4_data },
- { MAX8998_LDO5, &aquila_ldo5_data },
- { MAX8998_LDO6, &aquila_ldo6_data },
- { MAX8998_LDO7, &aquila_ldo7_data },
- { MAX8998_LDO8, &aquila_ldo8_data },
- { MAX8998_LDO9, &aquila_ldo9_data },
- { MAX8998_LDO10, &aquila_ldo10_data },
- { MAX8998_LDO11, &aquila_ldo11_data },
- { MAX8998_LDO12, &aquila_ldo12_data },
- { MAX8998_LDO13, &aquila_ldo13_data },
- { MAX8998_LDO14, &aquila_ldo14_data },
- { MAX8998_LDO15, &aquila_ldo15_data },
- { MAX8998_LDO16, &aquila_ldo16_data },
- { MAX8998_LDO17, &aquila_ldo17_data },
- { MAX8998_BUCK1, &aquila_buck1_data },
- { MAX8998_BUCK2, &aquila_buck2_data },
- { MAX8998_BUCK3, &aquila_buck3_data },
- { MAX8998_BUCK4, &aquila_buck4_data },
-};
-
-static struct max8998_platform_data aquila_max8998_pdata = {
- .num_regulators = ARRAY_SIZE(aquila_regulators),
- .regulators = aquila_regulators,
- .buck1_set1 = S5PV210_GPH0(3),
- .buck1_set2 = S5PV210_GPH0(4),
- .buck2_set3 = S5PV210_GPH0(5),
- .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
- .buck2_voltage = { 1200000, 1200000 },
-};
-#endif
-
-static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
- REGULATOR_SUPPLY("DBVDD", "5-001a"),
- REGULATOR_SUPPLY("AVDD2", "5-001a"),
- REGULATOR_SUPPLY("CPVDD", "5-001a"),
-};
-
-static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
- REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
- REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
-};
-
-static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
- .constraints = {
- .always_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
- .consumer_supplies = wm8994_fixed_voltage0_supplies,
-};
-
-static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
- .constraints = {
- .always_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
- .consumer_supplies = wm8994_fixed_voltage1_supplies,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
- .supply_name = "VCC_1.8V_PDA",
- .microvolts = 1800000,
- .gpio = -EINVAL,
- .init_data = &wm8994_fixed_voltage0_init_data,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
- .supply_name = "V_BAT",
- .microvolts = 3700000,
- .gpio = -EINVAL,
- .init_data = &wm8994_fixed_voltage1_init_data,
-};
-
-static struct platform_device wm8994_fixed_voltage0 = {
- .name = "reg-fixed-voltage",
- .id = 0,
- .dev = {
- .platform_data = &wm8994_fixed_voltage0_config,
- },
-};
-
-static struct platform_device wm8994_fixed_voltage1 = {
- .name = "reg-fixed-voltage",
- .id = 1,
- .dev = {
- .platform_data = &wm8994_fixed_voltage1_config,
- },
-};
-
-static struct regulator_consumer_supply wm8994_avdd1_supply =
- REGULATOR_SUPPLY("AVDD1", "5-001a");
-
-static struct regulator_consumer_supply wm8994_dcvdd_supply =
- REGULATOR_SUPPLY("DCVDD", "5-001a");
-
-static struct regulator_init_data wm8994_ldo1_data = {
- .constraints = {
- .name = "AVDD1_3.0V",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &wm8994_avdd1_supply,
-};
-
-static struct regulator_init_data wm8994_ldo2_data = {
- .constraints = {
- .name = "DCVDD_1.0V",
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &wm8994_dcvdd_supply,
-};
-
-static struct wm8994_pdata wm8994_platform_data = {
- /* configure gpio1 function: 0x0001(Logic level input/output) */
- .gpio_defaults[0] = 0x0001,
- /* configure gpio3/4/5/7 function for AIF2 voice */
- .gpio_defaults[2] = 0x8100,
- .gpio_defaults[3] = 0x8100,
- .gpio_defaults[4] = 0x8100,
- .gpio_defaults[6] = 0x0100,
- /* configure gpio8/9/10/11 function for AIF3 BT */
- .gpio_defaults[7] = 0x8100,
- .gpio_defaults[8] = 0x0100,
- .gpio_defaults[9] = 0x0100,
- .gpio_defaults[10] = 0x0100,
- .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */
- .ldo[1] = { 0, &wm8994_ldo2_data },
-};
-
-/* GPIO I2C PMIC */
-#define AP_I2C_GPIO_PMIC_BUS_4 4
-static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = {
- .sda_pin = S5PV210_GPJ4(0), /* XMSMCSN */
- .scl_pin = S5PV210_GPJ4(3), /* XMSMIRQN */
-};
-
-static struct platform_device aquila_i2c_gpio_pmic = {
- .name = "i2c-gpio",
- .id = AP_I2C_GPIO_PMIC_BUS_4,
- .dev = {
- .platform_data = &aquila_i2c_gpio_pmic_data,
- },
-};
-
-static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
- {
- /* 0xCC when SRAD = 0 */
- I2C_BOARD_INFO("max8998", 0xCC >> 1),
- .platform_data = &aquila_max8998_pdata,
- },
-#endif
-};
-
-/* GPIO I2C AP 1.8V */
-#define AP_I2C_GPIO_BUS_5 5
-static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = {
- .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
- .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
-};
-
-static struct platform_device aquila_i2c_gpio5 = {
- .name = "i2c-gpio",
- .id = AP_I2C_GPIO_BUS_5,
- .dev = {
- .platform_data = &aquila_i2c_gpio5_data,
- },
-};
-
-static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
- {
- /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
- I2C_BOARD_INFO("wm8994", 0x1a),
- .platform_data = &wm8994_platform_data,
- },
-};
-
-/* PMIC Power button */
-static struct gpio_keys_button aquila_gpio_keys_table[] = {
- {
- .code = KEY_POWER,
- .gpio = S5PV210_GPH2(6),
- .desc = "gpio-keys: KEY_POWER",
- .type = EV_KEY,
- .active_low = 1,
- .wakeup = 1,
- .debounce_interval = 1,
- },
-};
-
-static struct gpio_keys_platform_data aquila_gpio_keys_data = {
- .buttons = aquila_gpio_keys_table,
- .nbuttons = ARRAY_SIZE(aquila_gpio_keys_table),
-};
-
-static struct platform_device aquila_device_gpiokeys = {
- .name = "gpio-keys",
- .dev = {
- .platform_data = &aquila_gpio_keys_data,
- },
-};
-
-static void __init aquila_pmic_init(void)
-{
- /* AP_PMIC_IRQ: EINT7 */
- s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf));
- s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP);
-
- /* nPower: EINT22 */
- s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf));
- s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP);
-}
-
-/* MoviNAND */
-static struct s3c_sdhci_platdata aquila_hsmmc0_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_PERMANENT,
-};
-
-/* Wireless LAN */
-static struct s3c_sdhci_platdata aquila_hsmmc1_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_EXTERNAL,
- /* ext_cd_{init,cleanup} callbacks will be added later */
-};
-
-/* External Flash */
-#define AQUILA_EXT_FLASH_EN S5PV210_MP05(4)
-#define AQUILA_EXT_FLASH_CD S5PV210_GPH3(4)
-static struct s3c_sdhci_platdata aquila_hsmmc2_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = AQUILA_EXT_FLASH_CD,
- .ext_cd_gpio_invert = 1,
-};
-
-static void aquila_setup_sdhci(void)
-{
- gpio_request_one(AQUILA_EXT_FLASH_EN, GPIOF_OUT_INIT_HIGH, "FLASH_EN");
-
- s3c_sdhci0_set_platdata(&aquila_hsmmc0_data);
- s3c_sdhci1_set_platdata(&aquila_hsmmc1_data);
- s3c_sdhci2_set_platdata(&aquila_hsmmc2_data);
-};
-
-/* Audio device */
-static struct platform_device aquila_device_audio = {
- .name = "smdk-audio",
- .id = -1,
-};
-
-static struct platform_device *aquila_devices[] __initdata = {
- &aquila_i2c_gpio_pmic,
- &aquila_i2c_gpio5,
- &aquila_device_gpiokeys,
- &aquila_device_audio,
- &s3c_device_fb,
- &s5p_device_onenand,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &s5p_device_fimc0,
- &s5p_device_fimc1,
- &s5p_device_fimc2,
- &s5p_device_fimc_md,
- &s5pv210_device_iis0,
- &wm8994_fixed_voltage0,
- &wm8994_fixed_voltage1,
-};
-
-static void __init aquila_sound_init(void)
-{
- unsigned int gpio;
-
- /* CODEC_XTAL_EN
- *
- * The Aquila board have a oscillator which provide main clock
- * to WM8994 codec. The oscillator provide 24MHz clock to WM8994
- * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator.
- * */
- gpio = S5PV210_GPH3(2); /* XEINT_26 */
- gpio_request(gpio, "CODEC_XTAL_EN");
- s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-
- /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
- * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
- * because it needs 24MHz clock to operate WM8994 codec.
- */
- __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
-}
-
-static void __init aquila_map_io(void)
-{
- s5pv210_init_io(NULL, 0);
- s3c24xx_init_clocks(24000000);
- s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init aquila_machine_init(void)
-{
- /* PMIC */
- aquila_pmic_init();
- i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
- ARRAY_SIZE(i2c_gpio_pmic_devs));
- /* SDHCI */
- aquila_setup_sdhci();
-
- s3c_fimc_setname(0, "s5p-fimc");
- s3c_fimc_setname(1, "s5p-fimc");
- s3c_fimc_setname(2, "s5p-fimc");
-
- /* SOUND */
- aquila_sound_init();
- i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
- ARRAY_SIZE(i2c_gpio5_devs));
-
- /* FB */
- s3c_fb_set_platdata(&aquila_lcd_pdata);
-
- platform_add_devices(aquila_devices, ARRAY_SIZE(aquila_devices));
-}
-
-MACHINE_START(AQUILA, "Aquila")
- /* Maintainers:
- Marek Szyprowski <m.szyprowski@samsung.com>
- Kyungmin Park <kyungmin.park@samsung.com> */
- .atag_offset = 0x100,
- .init_irq = s5pv210_init_irq,
- .map_io = aquila_map_io,
- .init_machine = aquila_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5pv210_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
deleted file mode 100644
index c1ce921c4088..000000000000
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-goni.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/fb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/mfd/max8998.h>
-#include <linux/mfd/wm8994/pdata.h>
-#include <linux/regulator/fixed.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_gpio.h>
-#include <linux/lcd.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/interrupt.h>
-#include <linux/platform_data/s3c-hsotg.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/fb.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/keypad.h>
-#include <plat/sdhci.h>
-#include <plat/clock.h>
-#include <plat/samsung-time.h>
-#include <plat/mfc.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define GONI_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define GONI_UFCON_DEFAULT S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = GONI_UCON_DEFAULT,
- .ulcon = GONI_ULCON_DEFAULT,
- .ufcon = GONI_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG256 | S5PV210_UFCON_RXTRIG256,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = GONI_UCON_DEFAULT,
- .ulcon = GONI_ULCON_DEFAULT,
- .ufcon = GONI_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG64 | S5PV210_UFCON_RXTRIG64,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = GONI_UCON_DEFAULT,
- .ulcon = GONI_ULCON_DEFAULT,
- .ufcon = GONI_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = GONI_UCON_DEFAULT,
- .ulcon = GONI_ULCON_DEFAULT,
- .ufcon = GONI_UFCON_DEFAULT |
- S5PV210_UFCON_TXTRIG16 | S5PV210_UFCON_RXTRIG16,
- },
-};
-
-/* Frame Buffer */
-static struct s3c_fb_pd_win goni_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 16,
- .xres = 480,
- .yres = 800,
- .virtual_x = 480,
- .virtual_y = 2 * 800,
-};
-
-static struct fb_videomode goni_lcd_timing = {
- .left_margin = 16,
- .right_margin = 16,
- .upper_margin = 2,
- .lower_margin = 28,
- .hsync_len = 2,
- .vsync_len = 1,
- .xres = 480,
- .yres = 800,
- .refresh = 55,
-};
-
-static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
- .win[0] = &goni_fb_win0,
- .vtiming = &goni_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
- VIDCON0_CLKSEL_LCD,
- .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
- | VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = s5pv210_fb_gpio_setup_24bpp,
-};
-
-static int lcd_power_on(struct lcd_device *ld, int enable)
-{
- return 1;
-}
-
-static int reset_lcd(struct lcd_device *ld)
-{
- static unsigned int first = 1;
- int reset_gpio = -1;
-
- reset_gpio = S5PV210_MP05(5);
-
- if (first) {
- gpio_request(reset_gpio, "MLCD_RST");
- first = 0;
- }
-
- gpio_direction_output(reset_gpio, 1);
- return 1;
-}
-
-static struct lcd_platform_data goni_lcd_platform_data = {
- .reset = reset_lcd,
- .power_on = lcd_power_on,
- .lcd_enabled = 0,
- .reset_delay = 120, /* 120ms */
- .power_on_delay = 25, /* 25ms */
- .power_off_delay = 200, /* 200ms */
-};
-
-#define LCD_BUS_NUM 3
-static struct spi_board_info spi_board_info[] __initdata = {
- {
- .modalias = "s6e63m0",
- .platform_data = &goni_lcd_platform_data,
- .max_speed_hz = 1200000,
- .bus_num = LCD_BUS_NUM,
- .chip_select = 0,
- .mode = SPI_MODE_3,
- .controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */
- },
-};
-
-static struct spi_gpio_platform_data lcd_spi_gpio_data = {
- .sck = S5PV210_MP04(1), /* DISPLAY_CLK */
- .mosi = S5PV210_MP04(3), /* DISPLAY_SI */
- .miso = SPI_GPIO_NO_MISO,
- .num_chipselect = 1,
-};
-
-static struct platform_device goni_spi_gpio = {
- .name = "spi_gpio",
- .id = LCD_BUS_NUM,
- .dev = {
- .parent = &s3c_device_fb.dev,
- .platform_data = &lcd_spi_gpio_data,
- },
-};
-
-/* KEYPAD */
-static uint32_t keymap[] __initdata = {
- /* KEY(row, col, keycode) */
- KEY(0, 1, KEY_MENU), /* Send */
- KEY(0, 2, KEY_BACK), /* End */
- KEY(1, 1, KEY_CONFIG), /* Half shot */
- KEY(1, 2, KEY_VOLUMEUP),
- KEY(2, 1, KEY_CAMERA), /* Full shot */
- KEY(2, 2, KEY_VOLUMEDOWN),
-};
-
-static struct matrix_keymap_data keymap_data __initdata = {
- .keymap = keymap,
- .keymap_size = ARRAY_SIZE(keymap),
-};
-
-static struct samsung_keypad_platdata keypad_data __initdata = {
- .keymap_data = &keymap_data,
- .rows = 3,
- .cols = 3,
-};
-
-/* Radio */
-static struct i2c_board_info i2c1_devs[] __initdata = {
- {
- I2C_BOARD_INFO("si470x", 0x10),
- },
-};
-
-static void __init goni_radio_init(void)
-{
- int gpio;
-
- gpio = S5PV210_GPJ2(4); /* XMSMDATA_4 */
- gpio_request(gpio, "FM_INT");
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
- i2c1_devs[0].irq = gpio_to_irq(gpio);
-
- gpio = S5PV210_GPJ2(5); /* XMSMDATA_5 */
- gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "FM_RST");
-}
-
-/* TSP */
-static struct mxt_platform_data qt602240_platform_data = {
- .irqflags = IRQF_TRIGGER_FALLING,
-};
-
-static struct s3c2410_platform_i2c i2c2_data __initdata = {
- .flags = 0,
- .bus_num = 2,
- .slave_addr = 0x10,
- .frequency = 400 * 1000,
- .sda_delay = 100,
-};
-
-static struct i2c_board_info i2c2_devs[] __initdata = {
- {
- I2C_BOARD_INFO("qt602240_ts", 0x4a),
- .platform_data = &qt602240_platform_data,
- },
-};
-
-static void __init goni_tsp_init(void)
-{
- int gpio;
-
- gpio = S5PV210_GPJ1(3); /* XMSMADDR_11 */
- gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "TSP_LDO_ON");
- gpio_export(gpio, 0);
-
- gpio = S5PV210_GPJ0(5); /* XMSMADDR_5 */
- gpio_request(gpio, "TSP_INT");
-
- s5p_register_gpio_interrupt(gpio);
- s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
- s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
- i2c2_devs[0].irq = gpio_to_irq(gpio);
-}
-
-/* USB OTG */
-static struct s3c_hsotg_plat goni_hsotg_pdata;
-
-/* MAX8998 regulators */
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
-
-static struct regulator_consumer_supply goni_ldo3_consumers[] = {
- REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
-};
-
-static struct regulator_consumer_supply goni_ldo5_consumers[] = {
- REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-};
-
-static struct regulator_consumer_supply goni_ldo8_consumers[] = {
- REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
- REGULATOR_SUPPLY("vdd33a_dac", "s5p-sdo"),
-};
-
-static struct regulator_consumer_supply goni_ldo11_consumers[] = {
- REGULATOR_SUPPLY("vddio", "0-0030"), /* "CAM_IO_2.8V" */
-};
-
-static struct regulator_consumer_supply goni_ldo13_consumers[] = {
- REGULATOR_SUPPLY("vdda", "0-0030"), /* "CAM_A_2.8V" */
-};
-
-static struct regulator_consumer_supply goni_ldo14_consumers[] = {
- REGULATOR_SUPPLY("vdd_core", "0-0030"), /* "CAM_CIF_1.8V" */
-};
-
-static struct regulator_init_data goni_ldo2_data = {
- .constraints = {
- .name = "VALIVE_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .always_on = 1,
- .state_mem = {
- .enabled = 1,
- },
- },
-};
-
-static struct regulator_init_data goni_ldo3_data = {
- .constraints = {
- .name = "VUSB+MIPI_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo3_consumers),
- .consumer_supplies = goni_ldo3_consumers,
-};
-
-static struct regulator_init_data goni_ldo4_data = {
- .constraints = {
- .name = "VDAC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo5_data = {
- .constraints = {
- .name = "VTF_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
- .consumer_supplies = goni_ldo5_consumers,
-};
-
-static struct regulator_init_data goni_ldo6_data = {
- .constraints = {
- .name = "VCC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo7_data = {
- .constraints = {
- .name = "VLCD_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo8_data = {
- .constraints = {
- .name = "VUSB+VADC_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo8_consumers),
- .consumer_supplies = goni_ldo8_consumers,
-};
-
-static struct regulator_init_data goni_ldo9_data = {
- .constraints = {
- .name = "VCC+VCAM_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo10_data = {
- .constraints = {
- .name = "VPLL_1.1V",
- .min_uV = 1100000,
- .max_uV = 1100000,
- .apply_uV = 1,
- .boot_on = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo11_data = {
- .constraints = {
- .name = "CAM_IO_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo11_consumers),
- .consumer_supplies = goni_ldo11_consumers,
-};
-
-static struct regulator_init_data goni_ldo12_data = {
- .constraints = {
- .name = "CAM_ISP_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo13_data = {
- .constraints = {
- .name = "CAM_A_2.8V",
- .min_uV = 2800000,
- .max_uV = 2800000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo13_consumers),
- .consumer_supplies = goni_ldo13_consumers,
-};
-
-static struct regulator_init_data goni_ldo14_data = {
- .constraints = {
- .name = "CAM_CIF_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(goni_ldo14_consumers),
- .consumer_supplies = goni_ldo14_consumers,
-};
-
-static struct regulator_init_data goni_ldo15_data = {
- .constraints = {
- .name = "CAM_AF_3.3V",
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo16_data = {
- .constraints = {
- .name = "VMIPI_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- },
-};
-
-static struct regulator_init_data goni_ldo17_data = {
- .constraints = {
- .name = "VCC_3.0V_LCD",
- .min_uV = 3000000,
- .max_uV = 3000000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-/* BUCK */
-static struct regulator_consumer_supply buck1_consumer =
- REGULATOR_SUPPLY("vddarm", NULL);
-
-static struct regulator_consumer_supply buck2_consumer =
- REGULATOR_SUPPLY("vddint", NULL);
-
-static struct regulator_consumer_supply buck3_consumer =
- REGULATOR_SUPPLY("vdet", "s5p-sdo");
-
-
-static struct regulator_init_data goni_buck1_data = {
- .constraints = {
- .name = "VARM_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &buck1_consumer,
-};
-
-static struct regulator_init_data goni_buck2_data = {
- .constraints = {
- .name = "VINT_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &buck2_consumer,
-};
-
-static struct regulator_init_data goni_buck3_data = {
- .constraints = {
- .name = "VCC_1.8V",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = 1,
- .state_mem = {
- .enabled = 1,
- },
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &buck3_consumer,
-};
-
-static struct regulator_init_data goni_buck4_data = {
- .constraints = {
- .name = "CAM_CORE_1.2V",
- .min_uV = 1200000,
- .max_uV = 1200000,
- .apply_uV = 1,
- .always_on = 1,
- },
-};
-
-static struct max8998_regulator_data goni_regulators[] = {
- { MAX8998_LDO2, &goni_ldo2_data },
- { MAX8998_LDO3, &goni_ldo3_data },
- { MAX8998_LDO4, &goni_ldo4_data },
- { MAX8998_LDO5, &goni_ldo5_data },
- { MAX8998_LDO6, &goni_ldo6_data },
- { MAX8998_LDO7, &goni_ldo7_data },
- { MAX8998_LDO8, &goni_ldo8_data },
- { MAX8998_LDO9, &goni_ldo9_data },
- { MAX8998_LDO10, &goni_ldo10_data },
- { MAX8998_LDO11, &goni_ldo11_data },
- { MAX8998_LDO12, &goni_ldo12_data },
- { MAX8998_LDO13, &goni_ldo13_data },
- { MAX8998_LDO14, &goni_ldo14_data },
- { MAX8998_LDO15, &goni_ldo15_data },
- { MAX8998_LDO16, &goni_ldo16_data },
- { MAX8998_LDO17, &goni_ldo17_data },
- { MAX8998_BUCK1, &goni_buck1_data },
- { MAX8998_BUCK2, &goni_buck2_data },
- { MAX8998_BUCK3, &goni_buck3_data },
- { MAX8998_BUCK4, &goni_buck4_data },
-};
-
-static struct max8998_platform_data goni_max8998_pdata = {
- .num_regulators = ARRAY_SIZE(goni_regulators),
- .regulators = goni_regulators,
- .buck1_set1 = S5PV210_GPH0(3),
- .buck1_set2 = S5PV210_GPH0(4),
- .buck2_set3 = S5PV210_GPH0(5),
- .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 },
- .buck2_voltage = { 1200000, 1200000 },
-};
-#endif
-
-static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
- REGULATOR_SUPPLY("DBVDD", "5-001a"),
- REGULATOR_SUPPLY("AVDD2", "5-001a"),
- REGULATOR_SUPPLY("CPVDD", "5-001a"),
-};
-
-static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
- REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
- REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
-};
-
-static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
- .constraints = {
- .always_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
- .consumer_supplies = wm8994_fixed_voltage0_supplies,
-};
-
-static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
- .constraints = {
- .always_on = 1,
- },
- .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
- .consumer_supplies = wm8994_fixed_voltage1_supplies,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
- .supply_name = "VCC_1.8V_PDA",
- .microvolts = 1800000,
- .gpio = -EINVAL,
- .init_data = &wm8994_fixed_voltage0_init_data,
-};
-
-static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
- .supply_name = "V_BAT",
- .microvolts = 3700000,
- .gpio = -EINVAL,
- .init_data = &wm8994_fixed_voltage1_init_data,
-};
-
-static struct platform_device wm8994_fixed_voltage0 = {
- .name = "reg-fixed-voltage",
- .id = 0,
- .dev = {
- .platform_data = &wm8994_fixed_voltage0_config,
- },
-};
-
-static struct platform_device wm8994_fixed_voltage1 = {
- .name = "reg-fixed-voltage",
- .id = 1,
- .dev = {
- .platform_data = &wm8994_fixed_voltage1_config,
- },
-};
-
-static struct regulator_consumer_supply wm8994_avdd1_supply =
- REGULATOR_SUPPLY("AVDD1", "5-001a");
-
-static struct regulator_consumer_supply wm8994_dcvdd_supply =
- REGULATOR_SUPPLY("DCVDD", "5-001a");
-
-static struct regulator_init_data wm8994_ldo1_data = {
- .constraints = {
- .name = "AVDD1_3.0V",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &wm8994_avdd1_supply,
-};
-
-static struct regulator_init_data wm8994_ldo2_data = {
- .constraints = {
- .name = "DCVDD_1.0V",
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &wm8994_dcvdd_supply,
-};
-
-static struct wm8994_pdata wm8994_platform_data = {
- /* configure gpio1 function: 0x0001(Logic level input/output) */
- .gpio_defaults[0] = 0x0001,
- /* configure gpio3/4/5/7 function for AIF2 voice */
- .gpio_defaults[2] = 0x8100,
- .gpio_defaults[3] = 0x8100,
- .gpio_defaults[4] = 0x8100,
- .gpio_defaults[6] = 0x0100,
- /* configure gpio8/9/10/11 function for AIF3 BT */
- .gpio_defaults[7] = 0x8100,
- .gpio_defaults[8] = 0x0100,
- .gpio_defaults[9] = 0x0100,
- .gpio_defaults[10] = 0x0100,
- .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */
- .ldo[1] = { 0, &wm8994_ldo2_data },
-};
-
-/* GPIO I2C PMIC */
-#define AP_I2C_GPIO_PMIC_BUS_4 4
-static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = {
- .sda_pin = S5PV210_GPJ4(0), /* XMSMCSN */
- .scl_pin = S5PV210_GPJ4(3), /* XMSMIRQN */
-};
-
-static struct platform_device goni_i2c_gpio_pmic = {
- .name = "i2c-gpio",
- .id = AP_I2C_GPIO_PMIC_BUS_4,
- .dev = {
- .platform_data = &goni_i2c_gpio_pmic_data,
- },
-};
-
-static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = {
-#if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
- {
- /* 0xCC when SRAD = 0 */
- I2C_BOARD_INFO("max8998", 0xCC >> 1),
- .platform_data = &goni_max8998_pdata,
- },
-#endif
-};
-
-/* GPIO I2C AP 1.8V */
-#define AP_I2C_GPIO_BUS_5 5
-static struct i2c_gpio_platform_data goni_i2c_gpio5_data = {
- .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */
- .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */
-};
-
-static struct platform_device goni_i2c_gpio5 = {
- .name = "i2c-gpio",
- .id = AP_I2C_GPIO_BUS_5,
- .dev = {
- .platform_data = &goni_i2c_gpio5_data,
- },
-};
-
-static struct i2c_board_info i2c_gpio5_devs[] __initdata = {
- {
- /* CS/ADDR = low 0x34 (FYI: high = 0x36) */
- I2C_BOARD_INFO("wm8994", 0x1a),
- .platform_data = &wm8994_platform_data,
- },
-};
-
-/* PMIC Power button */
-static struct gpio_keys_button goni_gpio_keys_table[] = {
- {
- .code = KEY_POWER,
- .gpio = S5PV210_GPH2(6),
- .desc = "gpio-keys: KEY_POWER",
- .type = EV_KEY,
- .active_low = 1,
- .wakeup = 1,
- .debounce_interval = 1,
- },
-};
-
-static struct gpio_keys_platform_data goni_gpio_keys_data = {
- .buttons = goni_gpio_keys_table,
- .nbuttons = ARRAY_SIZE(goni_gpio_keys_table),
-};
-
-static struct platform_device goni_device_gpiokeys = {
- .name = "gpio-keys",
- .dev = {
- .platform_data = &goni_gpio_keys_data,
- },
-};
-
-static void __init goni_pmic_init(void)
-{
- /* AP_PMIC_IRQ: EINT7 */
- s3c_gpio_cfgpin(S5PV210_GPH0(7), S3C_GPIO_SFN(0xf));
- s3c_gpio_setpull(S5PV210_GPH0(7), S3C_GPIO_PULL_UP);
-
- /* nPower: EINT22 */
- s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_SFN(0xf));
- s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP);
-}
-
-/* MoviNAND */
-static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_PERMANENT,
-};
-
-/* Wireless LAN */
-static struct s3c_sdhci_platdata goni_hsmmc1_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_EXTERNAL,
- /* ext_cd_{init,cleanup} callbacks will be added later */
-};
-
-/* External Flash */
-#define GONI_EXT_FLASH_EN S5PV210_MP05(4)
-#define GONI_EXT_FLASH_CD S5PV210_GPH3(4)
-static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = {
- .max_width = 4,
- .cd_type = S3C_SDHCI_CD_GPIO,
- .ext_cd_gpio = GONI_EXT_FLASH_CD,
- .ext_cd_gpio_invert = 1,
-};
-
-static struct regulator_consumer_supply mmc2_supplies[] = {
- REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
-};
-
-static struct regulator_init_data mmc2_fixed_voltage_init_data = {
- .constraints = {
- .name = "V_TF_2.8V",
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(mmc2_supplies),
- .consumer_supplies = mmc2_supplies,
-};
-
-static struct fixed_voltage_config mmc2_fixed_voltage_config = {
- .supply_name = "EXT_FLASH_EN",
- .microvolts = 2800000,
- .gpio = GONI_EXT_FLASH_EN,
- .enable_high = true,
- .init_data = &mmc2_fixed_voltage_init_data,
-};
-
-static struct platform_device mmc2_fixed_voltage = {
- .name = "reg-fixed-voltage",
- .id = 2,
- .dev = {
- .platform_data = &mmc2_fixed_voltage_config,
- },
-};
-
-static void goni_setup_sdhci(void)
-{
- s3c_sdhci0_set_platdata(&goni_hsmmc0_data);
- s3c_sdhci1_set_platdata(&goni_hsmmc1_data);
- s3c_sdhci2_set_platdata(&goni_hsmmc2_data);
-};
-
-/* Audio device */
-static struct platform_device goni_device_audio = {
- .name = "smdk-audio",
- .id = -1,
-};
-
-static struct platform_device *goni_devices[] __initdata = {
- &s3c_device_fb,
- &s5p_device_onenand,
- &goni_spi_gpio,
- &goni_i2c_gpio_pmic,
- &goni_i2c_gpio5,
- &goni_device_audio,
- &mmc2_fixed_voltage,
- &goni_device_gpiokeys,
- &s5p_device_mfc,
- &s5p_device_mfc_l,
- &s5p_device_mfc_r,
- &s5p_device_mixer,
- &s5p_device_sdo,
- &s3c_device_i2c0,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &s5pv210_device_iis0,
- &s3c_device_usb_hsotg,
- &samsung_device_keypad,
- &s3c_device_i2c1,
- &s3c_device_i2c2,
- &wm8994_fixed_voltage0,
- &wm8994_fixed_voltage1,
-};
-
-static void __init goni_sound_init(void)
-{
- /* Ths main clock of WM8994 codec uses the output of CLKOUT pin.
- * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS)
- * because it needs 24MHz clock to operate WM8994 codec.
- */
- __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS);
-}
-
-static void __init goni_map_io(void)
-{
- s5pv210_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
- s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init goni_reserve(void)
-{
- s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init goni_machine_init(void)
-{
- /* Radio: call before I2C 1 registeration */
- goni_radio_init();
-
- /* I2C0 */
- s3c_i2c0_set_platdata(NULL);
-
- /* I2C1 */
- s3c_i2c1_set_platdata(NULL);
- i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-
- /* TSP: call before I2C 2 registeration */
- goni_tsp_init();
-
- /* I2C2 */
- s3c_i2c2_set_platdata(&i2c2_data);
- i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs));
-
- /* PMIC */
- goni_pmic_init();
- i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs,
- ARRAY_SIZE(i2c_gpio_pmic_devs));
- /* SDHCI */
- goni_setup_sdhci();
-
- /* SOUND */
- goni_sound_init();
- i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs,
- ARRAY_SIZE(i2c_gpio5_devs));
-
- /* FB */
- s3c_fb_set_platdata(&goni_lcd_pdata);
-
- s3c_hsotg_set_platdata(&goni_hsotg_pdata);
-
- /* SPI */
- spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-
- /* KEYPAD */
- samsung_keypad_set_platdata(&keypad_data);
-
- platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
-}
-
-MACHINE_START(GONI, "GONI")
- /* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
- .atag_offset = 0x100,
- .init_irq = s5pv210_init_irq,
- .map_io = goni_map_io,
- .init_machine = goni_machine_init,
- .init_time = samsung_timer_init,
- .reserve = &goni_reserve,
- .restart = s5pv210_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
deleted file mode 100644
index 448e1d2eeed6..000000000000
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-smdkc110.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/i2c.h>
-#include <linux/device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/pm.h>
-#include <plat/samsung-time.h>
-#include <plat/mfc.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC110_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDKC110_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S5PV210_UFCON_TXTRIG4 | \
- S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDKC110_UCON_DEFAULT,
- .ulcon = SMDKC110_ULCON_DEFAULT,
- .ufcon = SMDKC110_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDKC110_UCON_DEFAULT,
- .ulcon = SMDKC110_ULCON_DEFAULT,
- .ufcon = SMDKC110_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDKC110_UCON_DEFAULT,
- .ulcon = SMDKC110_ULCON_DEFAULT,
- .ufcon = SMDKC110_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDKC110_UCON_DEFAULT,
- .ulcon = SMDKC110_ULCON_DEFAULT,
- .ufcon = SMDKC110_UFCON_DEFAULT,
- },
-};
-
-static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = {
- .setup_gpio = s5pv210_ide_setup_gpio,
-};
-
-static struct platform_device *smdkc110_devices[] __initdata = {
- &s5pv210_device_iis0,
- &s5pv210_device_ac97,
- &s5pv210_device_spdif,
- &s3c_device_cfcon,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &s3c_device_i2c2,
- &s3c_device_rtc,
- &s3c_device_wdt,
- &s5p_device_fimc0,
- &s5p_device_fimc1,
- &s5p_device_fimc2,
- &s5p_device_fimc_md,
- &s5p_device_mfc,
- &s5p_device_mfc_l,
- &s5p_device_mfc_r,
-};
-
-static struct i2c_board_info smdkc110_i2c_devs0[] __initdata = {
- { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */
- { I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdkc110_i2c_devs1[] __initdata = {
- /* To Be Updated */
-};
-
-static struct i2c_board_info smdkc110_i2c_devs2[] __initdata = {
- /* To Be Updated */
-};
-
-static void __init smdkc110_map_io(void)
-{
- s5pv210_init_io(NULL, 0);
- s3c24xx_init_clocks(24000000);
- s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init smdkc110_reserve(void)
-{
- s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init smdkc110_machine_init(void)
-{
- s3c_pm_init();
-
- s3c_i2c0_set_platdata(NULL);
- s3c_i2c1_set_platdata(NULL);
- s3c_i2c2_set_platdata(NULL);
- i2c_register_board_info(0, smdkc110_i2c_devs0,
- ARRAY_SIZE(smdkc110_i2c_devs0));
- i2c_register_board_info(1, smdkc110_i2c_devs1,
- ARRAY_SIZE(smdkc110_i2c_devs1));
- i2c_register_board_info(2, smdkc110_i2c_devs2,
- ARRAY_SIZE(smdkc110_i2c_devs2));
-
- s3c_ide_set_platdata(&smdkc110_ide_pdata);
-
- platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
-}
-
-MACHINE_START(SMDKC110, "SMDKC110")
- /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .atag_offset = 0x100,
- .init_irq = s5pv210_init_irq,
- .map_io = smdkc110_map_io,
- .init_machine = smdkc110_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5pv210_restart,
- .reserve = &smdkc110_reserve,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
deleted file mode 100644
index 2a6655fb63e7..000000000000
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-smdkv210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-#include <linux/device.h>
-#include <linux/dm9000.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/pwm_backlight.h>
-#include <linux/platform_data/s3c-hsotg.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <video/platform_lcd.h>
-#include <video/samsung_fimd.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/regs-srom.h>
-#include <plat/gpio-cfg.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/adc.h>
-#include <linux/platform_data/touchscreen-s3c2410.h>
-#include <linux/platform_data/ata-samsung_cf.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/keypad.h>
-#include <plat/pm.h>
-#include <plat/fb.h>
-#include <plat/samsung-time.h>
-#include <plat/backlight.h>
-#include <plat/mfc.h>
-#include <plat/clock.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKV210_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define SMDKV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S5PV210_UFCON_TXTRIG4 | \
- S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = SMDKV210_UCON_DEFAULT,
- .ulcon = SMDKV210_ULCON_DEFAULT,
- .ufcon = SMDKV210_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = SMDKV210_UCON_DEFAULT,
- .ulcon = SMDKV210_ULCON_DEFAULT,
- .ufcon = SMDKV210_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = SMDKV210_UCON_DEFAULT,
- .ulcon = SMDKV210_ULCON_DEFAULT,
- .ufcon = SMDKV210_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = SMDKV210_UCON_DEFAULT,
- .ulcon = SMDKV210_ULCON_DEFAULT,
- .ufcon = SMDKV210_UFCON_DEFAULT,
- },
-};
-
-static struct s3c_ide_platdata smdkv210_ide_pdata __initdata = {
- .setup_gpio = s5pv210_ide_setup_gpio,
-};
-
-static uint32_t smdkv210_keymap[] __initdata = {
- /* KEY(row, col, keycode) */
- KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
- KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
- KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
- KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
-};
-
-static struct matrix_keymap_data smdkv210_keymap_data __initdata = {
- .keymap = smdkv210_keymap,
- .keymap_size = ARRAY_SIZE(smdkv210_keymap),
-};
-
-static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = {
- .keymap_data = &smdkv210_keymap_data,
- .rows = 8,
- .cols = 8,
-};
-
-static struct resource smdkv210_dm9000_resources[] = {
- [0] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5, 1),
- [1] = DEFINE_RES_MEM(S5PV210_PA_SROM_BANK5 + 2, 1),
- [2] = DEFINE_RES_NAMED(IRQ_EINT(9), 1, NULL, IORESOURCE_IRQ \
- | IORESOURCE_IRQ_HIGHLEVEL),
-};
-
-static struct dm9000_plat_data smdkv210_dm9000_platdata = {
- .flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
- .dev_addr = { 0x00, 0x09, 0xc0, 0xff, 0xec, 0x48 },
-};
-
-static struct platform_device smdkv210_dm9000 = {
- .name = "dm9000",
- .id = -1,
- .num_resources = ARRAY_SIZE(smdkv210_dm9000_resources),
- .resource = smdkv210_dm9000_resources,
- .dev = {
- .platform_data = &smdkv210_dm9000_platdata,
- },
-};
-
-static void smdkv210_lte480wv_set_power(struct plat_lcd_data *pd,
- unsigned int power)
-{
- if (power) {
-#if !defined(CONFIG_BACKLIGHT_PWM)
- gpio_request_one(S5PV210_GPD0(3), GPIOF_OUT_INIT_HIGH, "GPD0");
- gpio_free(S5PV210_GPD0(3));
-#endif
-
- /* fire nRESET on power up */
- gpio_request_one(S5PV210_GPH0(6), GPIOF_OUT_INIT_HIGH, "GPH0");
-
- gpio_set_value(S5PV210_GPH0(6), 0);
- mdelay(10);
-
- gpio_set_value(S5PV210_GPH0(6), 1);
- mdelay(10);
-
- gpio_free(S5PV210_GPH0(6));
- } else {
-#if !defined(CONFIG_BACKLIGHT_PWM)
- gpio_request_one(S5PV210_GPD0(3), GPIOF_OUT_INIT_LOW, "GPD0");
- gpio_free(S5PV210_GPD0(3));
-#endif
- }
-}
-
-static struct plat_lcd_data smdkv210_lcd_lte480wv_data = {
- .set_power = smdkv210_lte480wv_set_power,
-};
-
-static struct platform_device smdkv210_lcd_lte480wv = {
- .name = "platform-lcd",
- .dev.parent = &s3c_device_fb.dev,
- .dev.platform_data = &smdkv210_lcd_lte480wv_data,
-};
-
-static struct s3c_fb_pd_win smdkv210_fb_win0 = {
- .max_bpp = 32,
- .default_bpp = 24,
- .xres = 800,
- .yres = 480,
-};
-
-static struct fb_videomode smdkv210_lcd_timing = {
- .left_margin = 13,
- .right_margin = 8,
- .upper_margin = 7,
- .lower_margin = 5,
- .hsync_len = 3,
- .vsync_len = 1,
- .xres = 800,
- .yres = 480,
-};
-
-static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
- .win[0] = &smdkv210_fb_win0,
- .vtiming = &smdkv210_lcd_timing,
- .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
- .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
- .setup_gpio = s5pv210_fb_gpio_setup_24bpp,
-};
-
-/* USB OTG */
-static struct s3c_hsotg_plat smdkv210_hsotg_pdata;
-
-static struct platform_device *smdkv210_devices[] __initdata = {
- &s3c_device_adc,
- &s3c_device_cfcon,
- &s3c_device_fb,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &s3c_device_hsmmc3,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &s3c_device_i2c2,
- &samsung_device_pwm,
- &s3c_device_rtc,
- &s3c_device_ts,
- &s3c_device_usb_hsotg,
- &s3c_device_wdt,
- &s5p_device_fimc0,
- &s5p_device_fimc1,
- &s5p_device_fimc2,
- &s5p_device_fimc_md,
- &s5p_device_jpeg,
- &s5p_device_mfc,
- &s5p_device_mfc_l,
- &s5p_device_mfc_r,
- &s5pv210_device_ac97,
- &s5pv210_device_iis0,
- &s5pv210_device_spdif,
- &samsung_asoc_idma,
- &samsung_device_keypad,
- &smdkv210_dm9000,
- &smdkv210_lcd_lte480wv,
-};
-
-static void __init smdkv210_dm9000_init(void)
-{
- unsigned int tmp;
-
- gpio_request(S5PV210_MP01(5), "nCS5");
- s3c_gpio_cfgpin(S5PV210_MP01(5), S3C_GPIO_SFN(2));
- gpio_free(S5PV210_MP01(5));
-
- tmp = (5 << S5P_SROM_BCX__TACC__SHIFT);
- __raw_writel(tmp, S5P_SROM_BC5);
-
- tmp = __raw_readl(S5P_SROM_BW);
- tmp &= (S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS5__SHIFT);
- tmp |= (1 << S5P_SROM_BW__NCS5__SHIFT);
- __raw_writel(tmp, S5P_SROM_BW);
-}
-
-static struct i2c_board_info smdkv210_i2c_devs0[] __initdata = {
- { I2C_BOARD_INFO("24c08", 0x50), }, /* Samsung S524AD0XD1 */
- { I2C_BOARD_INFO("wm8580", 0x1b), },
-};
-
-static struct i2c_board_info smdkv210_i2c_devs1[] __initdata = {
- /* To Be Updated */
-};
-
-static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
- /* To Be Updated */
-};
-
-/* LCD Backlight data */
-static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
- .no = S5PV210_GPD0(3),
- .func = S3C_GPIO_SFN(2),
-};
-
-static struct platform_pwm_backlight_data smdkv210_bl_data = {
- .pwm_id = 3,
- .pwm_period_ns = 1000,
- .enable_gpio = -1,
-};
-
-static void __init smdkv210_map_io(void)
-{
- s5pv210_init_io(NULL, 0);
- s3c24xx_init_clocks(clk_xusbxti.rate);
- s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
-}
-
-static void __init smdkv210_reserve(void)
-{
- s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
-}
-
-static void __init smdkv210_machine_init(void)
-{
- s3c_pm_init();
-
- smdkv210_dm9000_init();
-
- samsung_keypad_set_platdata(&smdkv210_keypad_data);
- s3c24xx_ts_set_platdata(NULL);
-
- s3c_i2c0_set_platdata(NULL);
- s3c_i2c1_set_platdata(NULL);
- s3c_i2c2_set_platdata(NULL);
- i2c_register_board_info(0, smdkv210_i2c_devs0,
- ARRAY_SIZE(smdkv210_i2c_devs0));
- i2c_register_board_info(1, smdkv210_i2c_devs1,
- ARRAY_SIZE(smdkv210_i2c_devs1));
- i2c_register_board_info(2, smdkv210_i2c_devs2,
- ARRAY_SIZE(smdkv210_i2c_devs2));
-
- s3c_ide_set_platdata(&smdkv210_ide_pdata);
-
- s3c_fb_set_platdata(&smdkv210_lcd0_pdata);
-
- s3c_hsotg_set_platdata(&smdkv210_hsotg_pdata);
-
- platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
-
- samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
-}
-
-MACHINE_START(SMDKV210, "SMDKV210")
- /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
- .atag_offset = 0x100,
- .init_irq = s5pv210_init_irq,
- .map_io = smdkv210_map_io,
- .init_machine = smdkv210_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5pv210_restart,
- .reserve = &smdkv210_reserve,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
deleted file mode 100644
index 157805529f26..000000000000
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/mach-torbreck.c
- *
- * Copyright (c) 2010 aESOP Community
- * http://www.aesop.or.kr/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/samsung-time.h>
-
-#include "common.h"
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define TORBRECK_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
- S3C2410_UCON_RXILEVEL | \
- S3C2410_UCON_TXIRQMODE | \
- S3C2410_UCON_RXIRQMODE | \
- S3C2410_UCON_RXFIFO_TOI | \
- S3C2443_UCON_RXERR_IRQEN)
-
-#define TORBRECK_ULCON_DEFAULT S3C2410_LCON_CS8
-
-#define TORBRECK_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
- S5PV210_UFCON_TXTRIG4 | \
- S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = {
- [0] = {
- .hwport = 0,
- .flags = 0,
- .ucon = TORBRECK_UCON_DEFAULT,
- .ulcon = TORBRECK_ULCON_DEFAULT,
- .ufcon = TORBRECK_UFCON_DEFAULT,
- },
- [1] = {
- .hwport = 1,
- .flags = 0,
- .ucon = TORBRECK_UCON_DEFAULT,
- .ulcon = TORBRECK_ULCON_DEFAULT,
- .ufcon = TORBRECK_UFCON_DEFAULT,
- },
- [2] = {
- .hwport = 2,
- .flags = 0,
- .ucon = TORBRECK_UCON_DEFAULT,
- .ulcon = TORBRECK_ULCON_DEFAULT,
- .ufcon = TORBRECK_UFCON_DEFAULT,
- },
- [3] = {
- .hwport = 3,
- .flags = 0,
- .ucon = TORBRECK_UCON_DEFAULT,
- .ulcon = TORBRECK_ULCON_DEFAULT,
- .ufcon = TORBRECK_UFCON_DEFAULT,
- },
-};
-
-static struct platform_device *torbreck_devices[] __initdata = {
- &s5pv210_device_iis0,
- &s3c_device_cfcon,
- &s3c_device_hsmmc0,
- &s3c_device_hsmmc1,
- &s3c_device_hsmmc2,
- &s3c_device_hsmmc3,
- &s3c_device_i2c0,
- &s3c_device_i2c1,
- &s3c_device_i2c2,
- &s3c_device_rtc,
- &s3c_device_wdt,
-};
-
-static struct i2c_board_info torbreck_i2c_devs0[] __initdata = {
- /* To Be Updated */
-};
-
-static struct i2c_board_info torbreck_i2c_devs1[] __initdata = {
- /* To Be Updated */
-};
-
-static struct i2c_board_info torbreck_i2c_devs2[] __initdata = {
- /* To Be Updated */
-};
-
-static void __init torbreck_map_io(void)
-{
- s5pv210_init_io(NULL, 0);
- s3c24xx_init_clocks(24000000);
- s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
- samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
-}
-
-static void __init torbreck_machine_init(void)
-{
- s3c_i2c0_set_platdata(NULL);
- s3c_i2c1_set_platdata(NULL);
- s3c_i2c2_set_platdata(NULL);
- i2c_register_board_info(0, torbreck_i2c_devs0,
- ARRAY_SIZE(torbreck_i2c_devs0));
- i2c_register_board_info(1, torbreck_i2c_devs1,
- ARRAY_SIZE(torbreck_i2c_devs1));
- i2c_register_board_info(2, torbreck_i2c_devs2,
- ARRAY_SIZE(torbreck_i2c_devs2));
-
- platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices));
-}
-
-MACHINE_START(TORBRECK, "TORBRECK")
- /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
- .atag_offset = 0x100,
- .init_irq = s5pv210_init_irq,
- .map_io = torbreck_map_io,
- .init_machine = torbreck_machine_init,
- .init_time = samsung_timer_init,
- .restart = s5pv210_restart,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 3cf3f9c8ddd1..123163dd2ab0 100644
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s5pv210/pm.c
*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* S5PV210 - Power Management support
@@ -19,65 +19,28 @@
#include <linux/syscore_ops.h>
#include <linux/io.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
+#include <asm/cacheflush.h>
+#include <asm/suspend.h>
+
+#include <plat/pm-common.h>
-#include <mach/regs-irq.h>
#include <mach/regs-clock.h>
-static struct sleep_save s5pv210_core_save[] = {
- /* Clock source */
- SAVE_ITEM(S5P_CLK_SRC0),
- SAVE_ITEM(S5P_CLK_SRC1),
- SAVE_ITEM(S5P_CLK_SRC2),
- SAVE_ITEM(S5P_CLK_SRC3),
- SAVE_ITEM(S5P_CLK_SRC4),
- SAVE_ITEM(S5P_CLK_SRC5),
- SAVE_ITEM(S5P_CLK_SRC6),
-
- /* Clock source Mask */
- SAVE_ITEM(S5P_CLK_SRC_MASK0),
- SAVE_ITEM(S5P_CLK_SRC_MASK1),
-
- /* Clock Divider */
- SAVE_ITEM(S5P_CLK_DIV0),
- SAVE_ITEM(S5P_CLK_DIV1),
- SAVE_ITEM(S5P_CLK_DIV2),
- SAVE_ITEM(S5P_CLK_DIV3),
- SAVE_ITEM(S5P_CLK_DIV4),
- SAVE_ITEM(S5P_CLK_DIV5),
- SAVE_ITEM(S5P_CLK_DIV6),
- SAVE_ITEM(S5P_CLK_DIV7),
-
- /* Clock Main Gate */
- SAVE_ITEM(S5P_CLKGATE_MAIN0),
- SAVE_ITEM(S5P_CLKGATE_MAIN1),
- SAVE_ITEM(S5P_CLKGATE_MAIN2),
-
- /* Clock source Peri Gate */
- SAVE_ITEM(S5P_CLKGATE_PERI0),
- SAVE_ITEM(S5P_CLKGATE_PERI1),
-
- /* Clock source SCLK Gate */
- SAVE_ITEM(S5P_CLKGATE_SCLK0),
- SAVE_ITEM(S5P_CLKGATE_SCLK1),
-
- /* Clock IP Clock gate */
- SAVE_ITEM(S5P_CLKGATE_IP0),
- SAVE_ITEM(S5P_CLKGATE_IP1),
- SAVE_ITEM(S5P_CLKGATE_IP2),
- SAVE_ITEM(S5P_CLKGATE_IP3),
- SAVE_ITEM(S5P_CLKGATE_IP4),
-
- /* Clock Blcok and Bus gate */
- SAVE_ITEM(S5P_CLKGATE_BLOCK),
- SAVE_ITEM(S5P_CLKGATE_BUS0),
+#include "common.h"
+static struct sleep_save s5pv210_core_save[] = {
/* Clock ETC */
- SAVE_ITEM(S5P_CLK_OUT),
SAVE_ITEM(S5P_MDNIE_SEL),
};
+/*
+ * VIC wake-up support (TODO)
+ */
+static u32 s5pv210_irqwake_intmask = 0xffffffff;
+
+/*
+ * Suspend helpers.
+ */
static int s5pv210_cpu_suspend(unsigned long arg)
{
unsigned long tmp;
@@ -102,8 +65,12 @@ static void s5pv210_pm_prepare(void)
{
unsigned int tmp;
+ /* Set wake-up mask registers */
+ __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+ __raw_writel(s5pv210_irqwake_intmask, S5P_WAKEUP_MASK);
+
/* ensure at least INFORM0 has the resume address */
- __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+ __raw_writel(virt_to_phys(s5pv210_cpu_resume), S5P_INFORM0);
tmp = __raw_readl(S5P_SLEEP_CFG);
tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
@@ -123,26 +90,70 @@ static void s5pv210_pm_prepare(void)
s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
}
-static int s5pv210_pm_add(struct device *dev, struct subsys_interface *sif)
+/*
+ * Suspend operations.
+ */
+static int s5pv210_suspend_enter(suspend_state_t state)
{
- pm_cpu_prep = s5pv210_pm_prepare;
- pm_cpu_sleep = s5pv210_cpu_suspend;
+ int ret;
+
+ s3c_pm_debug_init();
+
+ S3C_PMDBG("%s: suspending the system...\n", __func__);
+
+ S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
+ s5pv210_irqwake_intmask, exynos_get_eint_wake_mask());
+
+ if (s5pv210_irqwake_intmask == -1U
+ && exynos_get_eint_wake_mask() == -1U) {
+ pr_err("%s: No wake-up sources!\n", __func__);
+ pr_err("%s: Aborting sleep\n", __func__);
+ return -EINVAL;
+ }
+
+ s3c_pm_save_uarts();
+ s5pv210_pm_prepare();
+ flush_cache_all();
+ s3c_pm_check_store();
+
+ ret = cpu_suspend(0, s5pv210_cpu_suspend);
+ if (ret)
+ return ret;
+
+ s3c_pm_restore_uarts();
+
+ S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
+ __raw_readl(S5P_WAKEUP_STAT));
+
+ s3c_pm_check_restore();
+
+ S3C_PMDBG("%s: resuming the system...\n", __func__);
return 0;
}
-static struct subsys_interface s5pv210_pm_interface = {
- .name = "s5pv210_pm",
- .subsys = &s5pv210_subsys,
- .add_dev = s5pv210_pm_add,
-};
+static int s5pv210_suspend_prepare(void)
+{
+ s3c_pm_check_prepare();
-static __init int s5pv210_pm_drvinit(void)
+ return 0;
+}
+
+static void s5pv210_suspend_finish(void)
{
- return subsys_interface_register(&s5pv210_pm_interface);
+ s3c_pm_check_cleanup();
}
-arch_initcall(s5pv210_pm_drvinit);
+static const struct platform_suspend_ops s5pv210_suspend_ops = {
+ .enter = s5pv210_suspend_enter,
+ .prepare = s5pv210_suspend_prepare,
+ .finish = s5pv210_suspend_finish,
+ .valid = suspend_valid_only_mem,
+};
+
+/*
+ * Syscore operations used to delay restore of certain registers.
+ */
static void s5pv210_pm_resume(void)
{
u32 tmp;
@@ -159,9 +170,11 @@ static struct syscore_ops s5pv210_pm_syscore_ops = {
.resume = s5pv210_pm_resume,
};
-static __init int s5pv210_pm_syscore_init(void)
+/*
+ * Initialization entry point.
+ */
+void __init s5pv210_pm_init(void)
{
register_syscore_ops(&s5pv210_pm_syscore_ops);
- return 0;
+ suspend_set_ops(&s5pv210_suspend_ops);
}
-arch_initcall(s5pv210_pm_syscore_init);
diff --git a/arch/arm/mach-s5pv210/s5pv210.c b/arch/arm/mach-s5pv210/s5pv210.c
new file mode 100644
index 000000000000..53feff33d129
--- /dev/null
+++ b/arch/arm/mach-s5pv210/s5pv210.c
@@ -0,0 +1,77 @@
+/*
+ * Samsung's S5PC110/S5PV210 flattened device tree enabled machine.
+ *
+ * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
+ * Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ * Tomasz Figa <t.figa@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+
+#include <plat/map-base.h>
+#include <mach/regs-clock.h>
+
+#include "common.h"
+
+static int __init s5pv210_fdt_map_sys(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ struct map_desc iodesc;
+ const __be32 *reg;
+ int len;
+
+ if (!of_flat_dt_is_compatible(node, "samsung,s5pv210-clock"))
+ return 0;
+
+ reg = of_get_flat_dt_prop(node, "reg", &len);
+ if (reg == NULL || len != (sizeof(unsigned long) * 2))
+ return 0;
+
+ iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
+ iodesc.length = be32_to_cpu(reg[1]) - 1;
+ iodesc.virtual = (unsigned long)S3C_VA_SYS;
+ iodesc.type = MT_DEVICE;
+ iotable_init(&iodesc, 1);
+
+ return 1;
+}
+
+static void __init s5pv210_dt_map_io(void)
+{
+ debug_ll_io_init();
+
+ of_scan_flat_dt(s5pv210_fdt_map_sys, NULL);
+}
+
+static void s5pv210_dt_restart(enum reboot_mode mode, const char *cmd)
+{
+ __raw_writel(0x1, S5P_SWRESET);
+}
+
+static void __init s5pv210_dt_init_late(void)
+{
+ platform_device_register_simple("s5pv210-cpufreq", -1, NULL, 0);
+ s5pv210_pm_init();
+}
+
+static char const *s5pv210_dt_compat[] __initconst = {
+ "samsung,s5pc110",
+ "samsung,s5pv210",
+ NULL
+};
+
+DT_MACHINE_START(S5PV210_DT, "Samsung S5PC110/S5PV210-based board")
+ .dt_compat = s5pv210_dt_compat,
+ .map_io = s5pv210_dt_map_io,
+ .restart = s5pv210_dt_restart,
+ .init_late = s5pv210_dt_init_late,
+MACHINE_END
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c
deleted file mode 100644
index 55103c8220b3..000000000000
--- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* linux/arch/arm/plat-s5pv210/setup-fb-24bpp.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Base s5pv210 setup information for 24bpp LCD framebuffer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <plat/fb.h>
-#include <mach/regs-clock.h>
-#include <plat/gpio-cfg.h>
-
-static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr)
-{
- s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2));
-
- for (; nr > 0; nr--, base++)
- s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-
-void s5pv210_fb_gpio_setup_24bpp(void)
-{
- s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8);
- s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8);
- s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8);
- s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4);
-
- /* Set DISPLAY_CONTROL register for Display path selection.
- *
- * ouput | RGB | I80 | ITU
- * -----------------------------------
- * 00 | MIE | FIMD | FIMD
- * 01 | MDNIE | MDNIE | FIMD
- * 10 | FIMD | FIMD | FIMD
- * 11 | FIMD | FIMD | FIMD
- */
- writel(0x2, S5P_MDNIE_SEL);
-}
diff --git a/arch/arm/mach-s5pv210/setup-fimc.c b/arch/arm/mach-s5pv210/setup-fimc.c
deleted file mode 100644
index 54cc5b11be0b..000000000000
--- a/arch/arm/mach-s5pv210/setup-fimc.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5PV210 camera interface GPIO configuration.
- *
- * 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/gpio.h>
-#include <plat/gpio-cfg.h>
-#include <plat/camport.h>
-
-int s5pv210_fimc_setup_gpio(enum s5p_camport_id id)
-{
- u32 gpio8, gpio5;
- int ret;
-
- switch (id) {
- case S5P_CAMPORT_A:
- gpio8 = S5PV210_GPE0(0);
- gpio5 = S5PV210_GPE1(0);
- break;
-
- case S5P_CAMPORT_B:
- gpio8 = S5PV210_GPJ0(0);
- gpio5 = S5PV210_GPJ1(0);
- break;
-
- default:
- WARN(1, "Wrong camport id: %d\n", id);
- return -EINVAL;
- }
-
- ret = s3c_gpio_cfgall_range(gpio8, 8, S3C_GPIO_SFN(2),
- S3C_GPIO_PULL_UP);
- if (ret)
- return ret;
-
- return s3c_gpio_cfgall_range(gpio5, 5, S3C_GPIO_SFN(2),
- S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c
deleted file mode 100644
index 4a15849766c0..000000000000
--- a/arch/arm/mach-s5pv210/setup-i2c0.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c
deleted file mode 100644
index 4777f6b97a92..000000000000
--- a/arch/arm/mach-s5pv210/setup-i2c1.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c1.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * I2C1 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c1.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c
deleted file mode 100644
index bbce6c74b915..000000000000
--- a/arch/arm/mach-s5pv210/setup-i2c2.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-i2c2.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * I2C2 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gpio.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c2_cfg_gpio(struct platform_device *dev)
-{
- s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c
deleted file mode 100644
index ea123d546bd2..000000000000
--- a/arch/arm/mach-s5pv210/setup-ide.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-ide.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5PV210 setup information for IDE
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-
-static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr)
-{
- s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4));
-
- for (; nr > 0; nr--, base++)
- s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4);
-}
-
-void s5pv210_ide_setup_gpio(void)
-{
- /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
- s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8);
-
- /* CF_Data[0 - 7] */
- s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8);
-
- /* CF_Data[8 - 15] */
- s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8);
-
- /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
- s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4);
-}
diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c
deleted file mode 100644
index c56420a52f48..000000000000
--- a/arch/arm/mach-s5pv210/setup-keypad.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv210/setup-keypad.c
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
-{
- /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */
- s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3));
-
- /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */
- s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3));
-}
diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
deleted file mode 100644
index 0512ada00522..000000000000
--- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* linux/arch/arm/plat-s5pc1xx/setup-sdhci-gpio.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5PV210 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/sdhci.h>
-
-void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG0/GPG1 pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2));
-
- switch (width) {
- case 8:
- /* GPG1[3:6] special-function 3 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
- case 4:
- /* GPG0[3:6] special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
- default:
- break;
- }
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
- }
-}
-
-void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG1[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2));
-
- /* Data pin GPG1[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
- }
-}
-
-void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG2[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2));
-
- switch (width) {
- case 8:
- /* Data pin GPG3[3:6] to special-function 3 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3));
- case 4:
- /* Data pin GPG2[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2));
- default:
- break;
- }
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
- }
-}
-
-void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
-{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG3[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2));
-
- /* Data pin GPG3[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG3(2), S3C_GPIO_SFN(2));
- }
-}
diff --git a/arch/arm/mach-s5pv210/setup-spi.c b/arch/arm/mach-s5pv210/setup-spi.c
deleted file mode 100644
index 81aecc162f82..000000000000
--- a/arch/arm/mach-s5pv210/setup-spi.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/setup-spi.c
- *
- * Copyright (C) 2011 Samsung Electronics Ltd.
- * http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/gpio.h>
-#include <plat/gpio-cfg.h>
-
-#ifdef CONFIG_S3C64XX_DEV_SPI0
-int s3c64xx_spi0_cfg_gpio(void)
-{
- s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgall_range(S5PV210_GPB(2), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C64XX_DEV_SPI1
-int s3c64xx_spi1_cfg_gpio(void)
-{
- s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgall_range(S5PV210_GPB(6), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
- return 0;
-}
-#endif
diff --git a/arch/arm/mach-s5pv210/setup-usb-phy.c b/arch/arm/mach-s5pv210/setup-usb-phy.c
deleted file mode 100644
index b2ee5333f89c..000000000000
--- a/arch/arm/mach-s5pv210/setup-usb-phy.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-usb-hsotg-phy.h>
-#include <plat/usb-phy.h>
-
-#define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C)
-#define S5PV210_USB_PHY0_EN (1 << 0)
-#define S5PV210_USB_PHY1_EN (1 << 1)
-
-static int s5pv210_usb_otgphy_init(struct platform_device *pdev)
-{
- struct clk *xusbxti;
- u32 phyclk;
-
- writel(readl(S5PV210_USB_PHY_CON) | S5PV210_USB_PHY0_EN,
- S5PV210_USB_PHY_CON);
-
- /* set clock frequency for PLL */
- phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
-
- xusbxti = clk_get(&pdev->dev, "xusbxti");
- if (xusbxti && !IS_ERR(xusbxti)) {
- switch (clk_get_rate(xusbxti)) {
- case 12 * MHZ:
- phyclk |= S3C_PHYCLK_CLKSEL_12M;
- break;
- case 24 * MHZ:
- phyclk |= S3C_PHYCLK_CLKSEL_24M;
- break;
- default:
- case 48 * MHZ:
- /* default reference clock */
- break;
- }
- clk_put(xusbxti);
- }
-
- /* TODO: select external clock/oscillator */
- writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
-
- /* set to normal OTG PHY */
- writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
- mdelay(1);
-
- /* reset OTG PHY and Link */
- writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
- S3C_RSTCON);
- udelay(20); /* at-least 10uS */
- writel(0, S3C_RSTCON);
-
- return 0;
-}
-
-static int s5pv210_usb_otgphy_exit(struct platform_device *pdev)
-{
- writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
- S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
-
- writel(readl(S5PV210_USB_PHY_CON) & ~S5PV210_USB_PHY0_EN,
- S5PV210_USB_PHY_CON);
-
- return 0;
-}
-
-int s5p_usb_phy_init(struct platform_device *pdev, int type)
-{
- if (type == USB_PHY_TYPE_DEVICE)
- return s5pv210_usb_otgphy_init(pdev);
-
- return -EINVAL;
-}
-
-int s5p_usb_phy_exit(struct platform_device *pdev, int type)
-{
- if (type == USB_PHY_TYPE_DEVICE)
- return s5pv210_usb_otgphy_exit(pdev);
-
- return -EINVAL;
-}
diff --git a/arch/arm/plat-samsung/s5p-sleep.S b/arch/arm/mach-s5pv210/sleep.S
index 25c68ceb9e2b..7c43ddd33ba8 100644
--- a/arch/arm/plat-samsung/s5p-sleep.S
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Common S5P Sleep Code
+ * S5PV210 Sleep Code
* Based on S3C64XX sleep code by:
* Ben Dooks, (c) 2008 Simtec Electronics
*
@@ -10,16 +10,7 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
+ */
#include <linux/linkage.h>
@@ -40,6 +31,6 @@
* resume code entry for bootloader to call
*/
-ENTRY(s3c_cpu_resume)
+ENTRY(s5pv210_cpu_resume)
b cpu_resume
-ENDPROC(s3c_cpu_resume)
+ENDPROC(s5pv210_cpu_resume)
diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h
index 12d376795abc..2054051eb797 100644
--- a/arch/arm/mach-sa1100/include/mach/memory.h
+++ b/arch/arm/mach-sa1100/include/mach/memory.h
@@ -10,11 +10,6 @@
#include <asm/sizes.h>
/*
- * Physical DRAM offset is 0xc0000000 on the SA1100
- */
-#define PLAT_PHYS_OFFSET UL(0xc0000000)
-
-/*
* Because of the wide memory address space between physical RAM banks on the
* SA1100, it's much convenient to use Linux's SparseMEM support to implement
* our memory map representation. Assuming all memory nodes have equal access
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 798073057e51..e15dff790dbb 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -12,6 +12,7 @@ menuconfig ARCH_SHMOBILE_MULTI
select NO_IOPORT_MAP
select PINCTRL
select ARCH_REQUIRE_GPIOLIB
+ select ARCH_HAS_OPP
if ARCH_SHMOBILE_MULTI
@@ -25,6 +26,11 @@ config ARCH_R7S72100
bool "RZ/A1H (R7S72100)"
select SYS_SUPPORTS_SH_MTU2
+config ARCH_R8A7779
+ bool "R-Car H1 (R8A77790)"
+ select RENESAS_INTC_IRQPIN
+ select SYS_SUPPORTS_SH_TMU
+
config ARCH_R8A7790
bool "R-Car H2 (R8A77900)"
select RENESAS_IRQC
@@ -51,6 +57,11 @@ config MACH_LAGER
depends on ARCH_R8A7790
select MICREL_PHY if SH_ETH
+config MACH_MARZEN
+ bool "MARZEN board"
+ depends on ARCH_R8A7779
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+
comment "Renesas ARM SoCs System Configuration"
endif
@@ -85,7 +96,6 @@ config ARCH_R8A73A4
select CPU_V7
select SH_CLK_CPG
select RENESAS_IRQC
- select ARCH_HAS_OPP
select SYS_SUPPORTS_SH_CMT
select SYS_SUPPORTS_SH_TMU
@@ -234,19 +244,6 @@ config MACH_MARZEN
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select USE_OF
-config MACH_MARZEN_REFERENCE
- bool "MARZEN board - Reference Device Tree Implementation"
- depends on ARCH_R8A7779
- select ARCH_REQUIRE_GPIOLIB
- select REGULATOR_FIXED_VOLTAGE if REGULATOR
- select USE_OF
- ---help---
- Use reference implementation of Marzen board support
- which makes use of device tree at the expense
- of not supporting a number of devices.
-
- This is intended to aid developers
-
config MACH_LAGER
bool "Lager board"
depends on ARCH_R8A7790
@@ -263,7 +260,6 @@ config MACH_KOELSCH
config MACH_KZM9G
bool "KZM-A9-GT board"
depends on ARCH_SH73A0
- select ARCH_HAS_OPP
select ARCH_REQUIRE_GPIOLIB
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select SND_SOC_AK4642 if SND_SIMPLE_CARD
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 38d5fe825e93..fe3878a1a69a 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -34,31 +34,39 @@ obj-$(CONFIG_ARCH_R8A7791) += clock-r8a7791.o
obj-$(CONFIG_ARCH_R7S72100) += clock-r7s72100.o
endif
+# CPU reset vector handling objects
+cpu-y := platsmp.o headsmp.o
+cpu-$(CONFIG_ARCH_R8A7790) += platsmp-apmu.o
+cpu-$(CONFIG_ARCH_R8A7791) += platsmp-apmu.o
+
# SMP objects
-smp-y := platsmp.o headsmp.o
+smp-y := $(cpu-y)
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
-smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o
-smp-$(CONFIG_ARCH_R8A7791) += smp-r8a7791.o platsmp-apmu.o
+smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o
+smp-$(CONFIG_ARCH_R8A7791) += smp-r8a7791.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
-# IRQ objects
-obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
-
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o pm-rmobile.o
obj-$(CONFIG_ARCH_SH73A0) += pm-sh73a0.o
obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o pm-rmobile.o
obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o pm-rcar.o
-obj-$(CONFIG_ARCH_R8A7790) += pm-r8a7790.o pm-rcar.o
+obj-$(CONFIG_ARCH_R8A7790) += pm-r8a7790.o pm-rcar.o $(cpu-y)
+obj-$(CONFIG_ARCH_R8A7791) += pm-r8a7791.o pm-rcar.o $(cpu-y)
+
+# IRQ objects
+obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
# Board objects
ifdef CONFIG_ARCH_SHMOBILE_MULTI
obj-$(CONFIG_MACH_GENMAI) += board-genmai-reference.o
obj-$(CONFIG_MACH_KOELSCH) += board-koelsch-reference.o
obj-$(CONFIG_MACH_LAGER) += board-lager-reference.o
+obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o
else
obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o
obj-$(CONFIG_MACH_APE6EVM_REFERENCE) += board-ape6evm-reference.o
@@ -67,7 +75,6 @@ obj-$(CONFIG_MACH_BOCKW) += board-bockw.o
obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o
obj-$(CONFIG_MACH_GENMAI) += board-genmai.o
obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
-obj-$(CONFIG_MACH_MARZEN_REFERENCE) += board-marzen-reference.o
obj-$(CONFIG_MACH_LAGER) += board-lager.o
obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += board-armadillo800eva-reference.o
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
index 918fccffa1b6..ebf97d4bcfd8 100644
--- a/arch/arm/mach-shmobile/Makefile.boot
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -13,7 +13,6 @@ loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000
loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
-loadaddr-$(CONFIG_MACH_MARZEN_REFERENCE) += 0x60008000
__ZRELADDR := $(sort $(loadaddr-y))
zreladdr-y += $(__ZRELADDR)
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
index 3276afcf3cc9..2f7723e5fe91 100644
--- a/arch/arm/mach-shmobile/board-ape6evm-reference.c
+++ b/arch/arm/mach-shmobile/board-ape6evm-reference.c
@@ -24,11 +24,13 @@
#include <linux/pinctrl/machine.h>
#include <linux/platform_device.h>
#include <linux/sh_clk.h>
-#include <mach/common.h>
-#include <mach/r8a73a4.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "r8a73a4.h"
+
static void __init ape6evm_add_standard_devices(void)
{
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index fe071a9130b7..1585b8830b13 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -33,12 +33,14 @@
#include <linux/regulator/machine.h>
#include <linux/sh_clk.h>
#include <linux/smsc911x.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a73a4.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a73a4.h"
+
/* LEDS */
static struct gpio_led ape6evm_leds[] = {
{
@@ -248,29 +250,29 @@ static void __init ape6evm_add_standard_devices(void)
regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
- platform_device_register_resndata(&platform_bus, "smsc911x", -1,
+ platform_device_register_resndata(NULL, "smsc911x", -1,
lan9220_res, ARRAY_SIZE(lan9220_res),
&lan9220_data, sizeof(lan9220_data));
regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
- platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
+ platform_device_register_resndata(NULL, "sh_mmcif", 0,
mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
&mmcif0_pdata, sizeof(mmcif0_pdata));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 2,
&vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_pdata, sizeof(sdhi0_pdata));
regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_pdata, sizeof(sdhi1_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&ape6evm_keys_pdata,
sizeof(ape6evm_keys_pdata));
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&ape6evm_leds_pdata,
sizeof(ape6evm_leds_pdata));
}
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
index f660fbb96e0b..84bc6cb6d5aa 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
@@ -24,11 +24,13 @@
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/io.h>
-#include <mach/common.h>
-#include <mach/r8a7740.h>
+
#include <asm/mach/arch.h>
#include <asm/hardware/cache-l2x0.h>
+#include "common.h"
+#include "r8a7740.h"
+
/*
* CON1 Camera Module
* CON2 Extension Bus
@@ -53,11 +55,11 @@
* CON22 Serial
* CON23 LAN
* CON24 USB3
- * LED1 Camera LED(Yellow)
+ * LED1 Camera LED (Yellow)
* LED2 Power LED (Green)
- * ED3-LED6 User LED(Yellow)
- * LED7 LAN link LED(Green)
- * LED8 LAN activity LED(Yellow)
+ * LED3-LED6 User LED (Yellow)
+ * LED7 LAN link LED (Green)
+ * LED8 LAN activity LED (Yellow)
*/
/*
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 30fcac73a540..6dbaad611a92 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -45,9 +45,7 @@
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/i2c-gpio.h>
#include <linux/reboot.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7740.h>
+
#include <media/mt9t112.h>
#include <media/sh_mobile_ceu.h>
#include <media/soc_camera.h>
@@ -62,6 +60,10 @@
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
+#include "common.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
#include "sh-gpio.h"
/*
@@ -578,6 +580,40 @@ static struct platform_device hdmi_lcdc_device = {
},
};
+/* LEDS */
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "LED3",
+ .gpio = 102,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED4",
+ .gpio = 111,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED5",
+ .gpio = 110,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED6",
+ .gpio = 177,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ },
+};
+
+static struct gpio_led_platform_data leds_gpio_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &leds_gpio_info,
+ },
+};
+
/* GPIO KEY */
#define GPIO_KEY(c, g, d, ...) \
{ .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
@@ -998,6 +1034,8 @@ static struct platform_device fsi_wm8978_device = {
.id = 0,
.dev = {
.platform_data = &fsi_wm8978_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
},
};
@@ -1021,6 +1059,8 @@ static struct platform_device fsi_hdmi_device = {
.id = 1,
.dev = {
.platform_data = &fsi2_hdmi_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
},
};
@@ -1069,6 +1109,7 @@ static struct platform_device *eva_devices[] __initdata = {
&lcdc0_device,
&pwm_device,
&pwm_backlight_device,
+ &leds_gpio_device,
&gpio_keys_device,
&sh_eth_device,
&vcc_sdhi0,
diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c
index 027373f8de82..ba840cd333b9 100644
--- a/arch/arm/mach-shmobile/board-bockw-reference.c
+++ b/arch/arm/mach-shmobile/board-bockw-reference.c
@@ -19,10 +19,12 @@
*/
#include <linux/of_platform.h>
-#include <mach/common.h>
-#include <mach/r8a7778.h>
+
#include <asm/mach/arch.h>
+#include "common.h"
+#include "r8a7778.h"
+
/*
* see board-bock.c for checking detail of dip-switch
*/
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index f444be2f241e..8a83eb39d3f1 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -34,14 +34,16 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb/renesas_usbhs.h>
+
#include <media/soc_camera.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7778.h>
#include <asm/mach/arch.h>
#include <sound/rcar_snd.h>
#include <sound/simple_card.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
#define FPGA 0x18200000
#define IRQ0MR 0x30
#define COMCTLR 0x101c
@@ -177,7 +179,7 @@ static struct renesas_usbhs_platform_info usbhs_info __initdata = {
#define USB1_DEVICE "renesas_usbhs"
#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() \
platform_device_register_resndata( \
- &platform_bus, "renesas_usbhs", -1, \
+ NULL, "renesas_usbhs", -1, \
usbhsf_resources, \
ARRAY_SIZE(usbhsf_resources), \
&usbhs_info, sizeof(struct renesas_usbhs_platform_info))
@@ -236,7 +238,6 @@ static struct sh_eth_plat_data ether_platform_data __initdata = {
};
static struct platform_device_info ether_info __initdata = {
- .parent = &platform_bus,
.name = "r8a777x-ether",
.id = -1,
.res = ether_resources,
@@ -322,7 +323,6 @@ static struct resource vin##idx##_resources[] __initdata = { \
}; \
\
static struct platform_device_info vin##idx##_info __initdata = { \
- .parent = &platform_bus, \
.name = "r8a7778-vin", \
.id = idx, \
.res = vin##idx##_resources, \
@@ -621,10 +621,10 @@ static void __init bockw_init(void)
/* VIN1 has a pin conflict with Ether */
if (!IS_ENABLED(CONFIG_SH_ETH))
platform_device_register_full(&vin1_info);
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 0,
&iclink0_ml86v7667,
sizeof(iclink0_ml86v7667));
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 1,
&iclink1_ml86v7667,
sizeof(iclink1_ml86v7667));
@@ -637,12 +637,12 @@ static void __init bockw_init(void)
r8a7778_pinmux_init();
platform_device_register_resndata(
- &platform_bus, "sh_mmcif", -1,
+ NULL, "sh_mmcif", -1,
mmc_resources, ARRAY_SIZE(mmc_resources),
&sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data));
platform_device_register_resndata(
- &platform_bus, "rcar_usb_phy", -1,
+ NULL, "rcar_usb_phy", -1,
usb_phy_resources,
ARRAY_SIZE(usb_phy_resources),
&usb_phy_platform_data,
@@ -668,7 +668,7 @@ static void __init bockw_init(void)
iowrite16(val, fpga + IRQ0MR);
platform_device_register_resndata(
- &platform_bus, "smsc911x", -1,
+ NULL, "smsc911x", -1,
smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
&smsc911x_data, sizeof(smsc911x_data));
}
@@ -685,7 +685,7 @@ static void __init bockw_init(void)
iounmap(base);
platform_device_register_resndata(
- &platform_bus, "sh_mobile_sdhi", 0,
+ NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
}
@@ -700,7 +700,7 @@ static void __init bockw_init(void)
"ak4554-adc-dac", 1, NULL, 0);
pdev = platform_device_register_resndata(
- &platform_bus, "rcar_sound", -1,
+ NULL, "rcar_sound", -1,
rsnd_resources, ARRAY_SIZE(rsnd_resources),
&rsnd_info, sizeof(rsnd_info));
@@ -710,7 +710,6 @@ static void __init bockw_init(void)
for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
struct platform_device_info cardinfo = {
- .parent = &platform_bus,
.name = "asoc-simple-card",
.id = i,
.data = &rsnd_card_info[i],
diff --git a/arch/arm/mach-shmobile/board-genmai-reference.c b/arch/arm/mach-shmobile/board-genmai-reference.c
index 2ff6ad6e608e..e5448f7b868a 100644
--- a/arch/arm/mach-shmobile/board-genmai-reference.c
+++ b/arch/arm/mach-shmobile/board-genmai-reference.c
@@ -20,12 +20,14 @@
#include <linux/kernel.h>
#include <linux/of_platform.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r7s72100.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "clock.h"
+#include "common.h"
+#include "r7s72100.h"
+
/*
* This is a really crude hack to provide clkdev support to platform
* devices until they get moved to DT.
@@ -47,7 +49,7 @@ static const char * const genmai_boards_compat_dt[] __initconst = {
};
DT_MACHINE_START(GENMAI_DT, "genmai")
- .init_early = r7s72100_init_early,
+ .init_early = shmobile_init_delay,
.init_machine = genmai_add_standard_devices,
.dt_compat = genmai_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-genmai.c b/arch/arm/mach-shmobile/board-genmai.c
index c94201ee8596..7bf2d8057535 100644
--- a/arch/arm/mach-shmobile/board-genmai.c
+++ b/arch/arm/mach-shmobile/board-genmai.c
@@ -25,12 +25,14 @@
#include <linux/sh_eth.h>
#include <linux/spi/rspi.h>
#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r7s72100.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "irqs.h"
+#include "r7s72100.h"
+
/* Ether */
static const struct sh_eth_plat_data ether_pdata __initconst = {
.phy = 0x00, /* PD60610 */
@@ -46,7 +48,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r7s72100-ether",
.id = -1,
.res = ether_resources,
@@ -76,7 +77,7 @@ static const struct rspi_plat_data rspi_pdata __initconst = {
};
#define r7s72100_register_rspi(idx) \
- platform_device_register_resndata(&platform_bus, "rspi-rz", idx, \
+ platform_device_register_resndata(NULL, "rspi-rz", idx, \
rspi##idx##_resources, \
ARRAY_SIZE(rspi##idx##_resources), \
&rspi_pdata, sizeof(rspi_pdata))
@@ -118,7 +119,7 @@ R7S72100_SCIF(6, 0xe800a000, gic_iid(245));
R7S72100_SCIF(7, 0xe800a800, gic_iid(249));
#define r7s72100_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -154,7 +155,7 @@ static const char * const genmai_boards_compat_dt[] __initconst = {
};
DT_MACHINE_START(GENMAI_DT, "genmai")
- .init_early = r7s72100_init_early,
+ .init_early = shmobile_init_delay,
.init_machine = genmai_add_standard_devices,
.dt_compat = genmai_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index d322a162b4b0..3ff88c138896 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -23,13 +23,15 @@
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/platform_data/rcar-du.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/rcar-gen2.h>
-#include <mach/r8a7791.h>
+
#include <asm/mach/arch.h>
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
/* DU */
static struct rcar_du_encoder_data koelsch_du_encoders[] = {
{
@@ -92,24 +94,9 @@ static const struct clk_name clk_names[] __initconst = {
{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
};
-/*
- * This is a really crude hack to work around core platform clock issues
- */
-static const struct clk_name clk_enables[] __initconst = {
- { "ether", NULL, "ee700000.ethernet" },
- { "i2c2", NULL, "e6530000.i2c" },
- { "msiof0", NULL, "e6e20000.spi" },
- { "qspi_mod", NULL, "e6b10000.spi" },
- { "sdhi0", NULL, "ee100000.sd" },
- { "sdhi1", NULL, "ee140000.sd" },
- { "sdhi2", NULL, "ee160000.sd" },
- { "thermal", NULL, "e61f0000.thermal" },
-};
-
static void __init koelsch_add_standard_devices(void)
{
shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
- shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
r8a7791_add_dt_devices();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -128,5 +115,6 @@ DT_MACHINE_START(KOELSCH_DT, "koelsch")
.init_time = rcar_gen2_timer_init,
.init_machine = koelsch_add_standard_devices,
.init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = koelsch_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
index c6c68892caa3..b7d5bc7659cd 100644
--- a/arch/arm/mach-shmobile/board-koelsch.c
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -45,13 +45,15 @@
#include <linux/spi/flash.h>
#include <linux/spi/rspi.h>
#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
/* DU */
static struct rcar_du_encoder_data koelsch_du_encoders[] = {
{
@@ -118,7 +120,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r8a7791-ether",
.id = -1,
.res = ether_resources,
@@ -230,7 +231,6 @@ static const struct resource sata0_resources[] __initconst = {
};
static const struct platform_device_info sata0_info __initconst = {
- .parent = &platform_bus,
.name = "sata-r8a7791",
.id = 0,
.res = sata0_resources,
@@ -439,13 +439,13 @@ static void __init koelsch_add_standard_devices(void)
r8a7791_pinmux_init();
r8a7791_add_standard_devices();
platform_device_register_full(&ether_info);
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&koelsch_leds_pdata,
sizeof(koelsch_leds_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&koelsch_keys_pdata,
sizeof(koelsch_keys_pdata));
- platform_device_register_resndata(&platform_bus, "qspi", 0,
+ platform_device_register_resndata(NULL, "qspi", 0,
qspi_resources,
ARRAY_SIZE(qspi_resources),
&qspi_pdata, sizeof(qspi_pdata));
@@ -460,28 +460,28 @@ static void __init koelsch_add_standard_devices(void)
koelsch_add_i2c(4);
koelsch_add_i2c(5);
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 0,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 0,
&vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 1,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 1,
&vcc_sdhi1_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+ platform_device_register_data(NULL, "reg-fixed-voltage", 2,
&vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 0,
+ platform_device_register_data(NULL, "gpio-regulator", 0,
&vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 1,
+ platform_device_register_data(NULL, "gpio-regulator", 1,
&vccq_sdhi1_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", 2,
+ platform_device_register_data(NULL, "gpio-regulator", 2,
&vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
&sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
@@ -526,5 +526,6 @@ DT_MACHINE_START(KOELSCH_DT, "koelsch")
.init_time = rcar_gen2_timer_init,
.init_machine = koelsch_init,
.init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = koelsch_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c
index a735a1d80c28..5d2621f202d1 100644
--- a/arch/arm/mach-shmobile/board-kzm9g-reference.c
+++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c
@@ -25,12 +25,14 @@
#include <linux/irq.h>
#include <linux/input.h>
#include <linux/of_platform.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
+
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "sh73a0.h"
+
static void __init kzm_init(void)
{
sh73a0_add_standard_devices_dt();
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index f94ec8ca42c1..f8bc7f8f86ad 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -41,16 +41,18 @@
#include <linux/usb/r8a66597.h>
#include <linux/usb/renesas_usbhs.h>
#include <linux/videodev2.h>
+
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <video/sh_mobile_lcdc.h>
+#include "common.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
/*
* external GPIO
*/
@@ -603,6 +605,8 @@ static struct platform_device fsi_ak4648_device = {
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4648_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
},
};
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 749832e3f33c..41c808e56005 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -22,13 +22,15 @@
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/platform_data/rcar-du.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/rcar-gen2.h>
-#include <mach/r8a7790.h>
+
#include <asm/mach/arch.h>
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
/* DU */
static struct rcar_du_encoder_data lager_du_encoders[] = {
{
@@ -98,23 +100,9 @@ static const struct clk_name clk_names[] __initconst = {
{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
};
-/*
- * This is a really crude hack to work around core platform clock issues
- */
-static const struct clk_name clk_enables[] __initconst = {
- { "ether", NULL, "ee700000.ethernet" },
- { "msiof1", NULL, "e6e10000.spi" },
- { "mmcif1", NULL, "ee220000.mmc" },
- { "qspi_mod", NULL, "e6b10000.spi" },
- { "sdhi0", NULL, "ee100000.sd" },
- { "sdhi2", NULL, "ee140000.sd" },
- { "thermal", NULL, "e61f0000.thermal" },
-};
-
static void __init lager_add_standard_devices(void)
{
shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
- shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
r8a7790_add_dt_devices();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -129,9 +117,10 @@ static const char *lager_boards_compat_dt[] __initdata = {
DT_MACHINE_START(LAGER_DT, "lager")
.smp = smp_ops(r8a7790_smp_ops),
- .init_early = r8a7790_init_early,
+ .init_early = shmobile_init_delay,
.init_time = rcar_gen2_timer_init,
.init_machine = lager_add_standard_devices,
.init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = lager_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f8b1e05463cc..e1d8215da0b0 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -31,6 +31,8 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/camera-rcar.h>
#include <linux/platform_data/gpio-rcar.h>
@@ -43,22 +45,23 @@
#include <linux/regulator/gpio-regulator.h>
#include <linux/regulator/machine.h>
#include <linux/sh_eth.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/rspi.h>
+#include <linux/spi/spi.h>
#include <linux/usb/phy.h>
#include <linux/usb/renesas_usbhs.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7790.h>
+
#include <media/soc_camera.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/mtd.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/rspi.h>
-#include <linux/spi/spi.h>
#include <sound/rcar_snd.h>
#include <sound/simple_card.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
/*
* SSI-AK4643
*
@@ -277,7 +280,6 @@ static const struct resource ether_resources[] __initconst = {
};
static const struct platform_device_info ether_info __initconst = {
- .parent = &platform_bus,
.name = "r8a7790-ether",
.id = -1,
.res = ether_resources,
@@ -354,7 +356,6 @@ static void __init lager_add_vin_device(unsigned idx,
struct rcar_vin_platform_data *pdata)
{
struct platform_device_info vin_info = {
- .parent = &platform_bus,
.name = "r8a7790-vin",
.id = idx,
.res = &vin_resources[idx * 2],
@@ -391,7 +392,7 @@ LAGER_CAMERA(1, "adv7180", 0x20, NULL, RCAR_VIN_BT656);
static void __init lager_add_camera1_device(void)
{
- platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
+ platform_device_register_data(NULL, "soc-camera-pdrv", 1,
&cam1_link, sizeof(cam1_link));
lager_add_vin_device(1, &vin1_pdata);
}
@@ -403,7 +404,6 @@ static const struct resource sata1_resources[] __initconst = {
};
static const struct platform_device_info sata1_info __initconst = {
- .parent = &platform_bus,
.name = "sata-r8a7790",
.id = 1,
.res = sata1_resources,
@@ -533,7 +533,7 @@ static struct usbhs_private usbhs_priv __initdata = {
static void __init lager_register_usbhs(void)
{
usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
- platform_device_register_resndata(&platform_bus,
+ platform_device_register_resndata(NULL,
"renesas_usbhs", -1,
usbhs_resources,
ARRAY_SIZE(usbhs_resources),
@@ -608,7 +608,6 @@ static struct asoc_simple_card_info rsnd_card_info = {
static void __init lager_add_rsnd_device(void)
{
struct platform_device_info cardinfo = {
- .parent = &platform_bus,
.name = "asoc-simple-card",
.id = -1,
.data = &rsnd_card_info,
@@ -620,7 +619,7 @@ static void __init lager_add_rsnd_device(void)
ARRAY_SIZE(i2c2_devices));
platform_device_register_resndata(
- &platform_bus, "rcar_sound", -1,
+ NULL, "rcar_sound", -1,
rsnd_resources, ARRAY_SIZE(rsnd_resources),
&rsnd_info, sizeof(rsnd_info));
@@ -663,7 +662,6 @@ static const struct resource pci1_resources[] __initconst = {
};
static const struct platform_device_info pci1_info __initconst = {
- .parent = &platform_bus,
.name = "pci-rcar-gen2",
.id = 1,
.res = pci1_resources,
@@ -684,7 +682,6 @@ static const struct resource pci2_resources[] __initconst = {
};
static const struct platform_device_info pci2_info __initconst = {
- .parent = &platform_bus,
.name = "pci-rcar-gen2",
.id = 2,
.res = pci2_resources,
@@ -795,16 +792,16 @@ static void __init lager_add_standard_devices(void)
r8a7790_pinmux_init();
r8a7790_add_standard_devices();
- platform_device_register_data(&platform_bus, "leds-gpio", -1,
+ platform_device_register_data(NULL, "leds-gpio", -1,
&lager_leds_pdata,
sizeof(lager_leds_pdata));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&lager_keys_pdata,
sizeof(lager_keys_pdata));
regulator_register_always_on(fixed_regulator_idx++,
"fixed-3.3V", fixed3v3_power_consumers,
ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
- platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
+ platform_device_register_resndata(NULL, "sh_mmcif", 1,
mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
&mmcif1_pdata, sizeof(mmcif1_pdata));
@@ -812,27 +809,27 @@ static void __init lager_add_standard_devices(void)
lager_add_du_device();
- platform_device_register_resndata(&platform_bus, "qspi", 0,
+ platform_device_register_resndata(NULL, "qspi", 0,
qspi_resources,
ARRAY_SIZE(qspi_resources),
&qspi_pdata, sizeof(qspi_pdata));
spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+ platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
&vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+ platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++,
&vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+ platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
&vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
- platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+ platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++,
&vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
lager_add_camera1_device();
platform_device_register_full(&sata1_info);
- platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
+ platform_device_register_resndata(NULL, "usb_phy_rcar_gen2",
-1, usbhs_phy_resources,
ARRAY_SIZE(usbhs_phy_resources),
&usbhs_phy_pdata,
@@ -843,10 +840,10 @@ static void __init lager_add_standard_devices(void)
lager_add_rsnd_device();
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
- platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 2,
+ platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
&sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
}
@@ -886,9 +883,10 @@ static const char * const lager_boards_compat_dt[] __initconst = {
DT_MACHINE_START(LAGER_DT, "lager")
.smp = smp_ops(r8a7790_smp_ops),
- .init_early = r8a7790_init_early,
+ .init_early = shmobile_init_delay,
.init_time = rcar_gen2_timer_init,
.init_machine = lager_init,
.init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = lager_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 0ff4d8e45cf7..79f448e93abb 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -47,10 +47,11 @@
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/smsc911x.h>
-#include <linux/sh_intc.h>
+#include <linux/sh_clk.h>
#include <linux/tca6416_keypad.h>
#include <linux/usb/renesas_usbhs.h>
#include <linux/dma-mapping.h>
+
#include <video/sh_mobile_hdmi.h>
#include <video/sh_mobile_lcdc.h>
#include <media/sh_mobile_ceu.h>
@@ -58,15 +59,14 @@
#include <media/soc_camera_platform.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
-
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/sh7372.h>
-
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include "common.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
#include "sh-gpio.h"
+#include "sh7372.h"
/*
* Address Interface BusWidth note
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
.id = 1,
.dev = {
.platform_data = &fsi2_hdmi_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
},
};
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi2_ak4643_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
},
};
diff --git a/arch/arm/mach-shmobile/board-marzen-reference.c b/arch/arm/mach-shmobile/board-marzen-reference.c
index 2773936bf7dc..21b3e1ca2261 100644
--- a/arch/arm/mach-shmobile/board-marzen-reference.c
+++ b/arch/arm/mach-shmobile/board-marzen-reference.c
@@ -19,19 +19,42 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <mach/r8a7779.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
+#include <linux/clk/shmobile.h>
+#include <linux/clocksource.h>
+#include <linux/of_platform.h>
+
#include <asm/irq.h>
#include <asm/mach/arch.h>
+#include "clock.h"
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
+static void __init marzen_init_timer(void)
+{
+ r8a7779_clocks_init(r8a7779_read_mode_pins());
+ clocksource_of_init();
+}
+
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] __initconst = {
+ { "tmu0", "fck", "sh-tmu.0" },
+};
+
static void __init marzen_init(void)
{
+ shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
r8a7779_add_standard_devices_dt();
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
r8a7779_init_irq_extpin_dt(1); /* IRQ1 as individual interrupt */
}
static const char *marzen_boards_compat_dt[] __initdata = {
+ "renesas,marzen",
"renesas,marzen-reference",
NULL,
};
@@ -39,7 +62,8 @@ static const char *marzen_boards_compat_dt[] __initdata = {
DT_MACHINE_START(MARZEN, "marzen")
.smp = smp_ops(r8a7779_smp_ops),
.map_io = r8a7779_map_io,
- .init_early = r8a7779_init_delay,
+ .init_early = shmobile_init_delay,
+ .init_time = marzen_init_timer,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = r8a7779_init_irq_dt,
.init_machine = marzen_init,
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index d832a4477b4b..e5cf4201e769 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -41,14 +41,16 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
+
#include <media/soc_camera.h>
-#include <mach/r8a7779.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/traps.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
/* Fixed 3.3V regulator to be used by SDHI0 */
static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -272,7 +274,6 @@ static struct resource vin##idx##_resources[] __initdata = { \
}; \
\
static struct platform_device_info vin##idx##_info __initdata = { \
- .parent = &platform_bus, \
.name = "r8a7779-vin", \
.id = idx, \
.res = vin##idx##_resources, \
diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c
index df187484de5d..3eb2ec401e0c 100644
--- a/arch/arm/mach-shmobile/clock-r7s72100.c
+++ b/arch/arm/mach-shmobile/clock-r7s72100.c
@@ -19,8 +19,9 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/common.h>
-#include <mach/r7s72100.h>
+
+#include "common.h"
+#include "r7s72100.h"
/* Frequency Control Registers */
#define FRQCR 0xfcfe0010
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
index b5bc22c6a858..c2330ea1802c 100644
--- a/arch/arm/mach-shmobile/clock-r8a73a4.c
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -22,8 +22,8 @@
#include <linux/kernel.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "common.h"
+#include "clock.h"
#define CPG_BASE 0xe6150000
#define CPG_LEN 0x270
@@ -574,11 +574,17 @@ static struct clk_lookup lookups[] = {
/* MSTP */
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+ CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]),
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+ CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]),
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
+ CLKDEV_DEV_ID("e6c20000.serial", &mstp_clks[MSTP206]),
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
+ CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP207]),
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
+ CLKDEV_DEV_ID("e6ce0000.serial", &mstp_clks[MSTP216]),
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
+ CLKDEV_DEV_ID("e6cf0000.serial", &mstp_clks[MSTP217]),
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("e6700020.dma-controller", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
@@ -598,6 +604,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.1", &mstp_clks[MSTP329]),
+ CLKDEV_ICK_ID("fck", "e6130000.timer", &mstp_clks[MSTP329]),
CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 50931e3c97c7..0794f0426e70 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -22,9 +22,10 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r8a7740.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7740.h"
/*
* | MDx | XTAL1/EXTAL1 | System | EXTALR |
@@ -555,27 +556,27 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
- CLKDEV_DEV_ID("e6c80000.sci", &mstp_clks[MSTP200]),
+ CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]),
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
- CLKDEV_DEV_ID("e6c70000.sci", &mstp_clks[MSTP201]),
+ CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]),
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]),
- CLKDEV_DEV_ID("e6c60000.sci", &mstp_clks[MSTP202]),
+ CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]),
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
- CLKDEV_DEV_ID("e6c50000.sci", &mstp_clks[MSTP203]),
+ CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]),
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
- CLKDEV_DEV_ID("e6c40000.sci", &mstp_clks[MSTP204]),
+ CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]),
CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
- CLKDEV_DEV_ID("e6c30000.sci", &mstp_clks[MSTP206]),
+ CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP206]),
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
- CLKDEV_DEV_ID("e6cb0000.sci", &mstp_clks[MSTP207]),
+ CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]),
CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]),
CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
- CLKDEV_DEV_ID("e6cd0000.sci", &mstp_clks[MSTP222]),
+ CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP222]),
CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
- CLKDEV_DEV_ID("e6cc0000.sci", &mstp_clks[MSTP230]),
+ CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP230]),
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
CLKDEV_DEV_ID("fe1f0000.sound", &mstp_clks[MSTP328]),
@@ -598,8 +599,11 @@ static struct clk_lookup lookups[] = {
/* ICK */
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP111]),
+ CLKDEV_ICK_ID("fck", "fff90000.timer", &mstp_clks[MSTP111]),
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]),
+ CLKDEV_ICK_ID("fck", "fff80000.timer", &mstp_clks[MSTP125]),
CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]),
+ CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]),
CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index 13f8f3ab8840..67980a08a601 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -39,8 +39,8 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
#define MSTPCR0 IOMEM(0xffc80030)
#define MSTPCR1 IOMEM(0xffc80034)
@@ -202,11 +202,17 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+ CLKDEV_DEV_ID("ffe40000.serial", &mstp_clks[MSTP026]), /* SCIF0 */
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+ CLKDEV_DEV_ID("ffe41000.serial", &mstp_clks[MSTP025]), /* SCIF1 */
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+ CLKDEV_DEV_ID("ffe42000.serial", &mstp_clks[MSTP024]), /* SCIF2 */
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+ CLKDEV_DEV_ID("ffe43000.serial", &mstp_clks[MSTP023]), /* SCIF3 */
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+ CLKDEV_DEV_ID("ffe44000.serial", &mstp_clks[MSTP022]), /* SCIF4 */
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+ CLKDEV_DEV_ID("ffe45000.serial", &mstp_clks[MSTP021]), /* SCIF5 */
CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
@@ -238,7 +244,9 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("fck", "ffd80000.timer", &mstp_clks[MSTP016]),
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("fck", "ffd81000.timer", &mstp_clks[MSTP015]),
};
void __init r8a7778_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index a13298bd37a8..c51f9db3f66f 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -23,8 +23,11 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include <linux/sh_timer.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7779.h"
/*
* MD1 = 1 MD1 = 0
@@ -52,9 +55,6 @@
#define MSTPCR3 IOMEM(0xffc8003c)
#define MSTPSR1 IOMEM(0xffc80044)
-#define MODEMR 0xffcc0020
-
-
/* ioremap() through clock mapping mandatory to avoid
* collision with ARM coherent DMA virtual memory range.
*/
@@ -207,14 +207,9 @@ static struct clk_lookup lookups[] = {
void __init r8a7779_clock_init(void)
{
- void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
- u32 mode;
+ u32 mode = r8a7779_read_mode_pins();
int k, ret = 0;
- BUG_ON(!modemr);
- mode = ioread32(modemr);
- iounmap(modemr);
-
if (mode & MD(1)) {
plla_clk.rate = 1500000000;
@@ -268,3 +263,13 @@ void __init r8a7779_clock_init(void)
else
panic("failed to setup r8a7779 clocks\n");
}
+
+/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
+void __init __weak r8a7779_register_twd(void) { }
+
+void __init r8a7779_earlytimer_init(void)
+{
+ r8a7779_clock_init();
+ r8a7779_register_twd();
+ shmobile_earlytimer_init();
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 296a057109e4..17435c1aa2fe 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -22,9 +22,11 @@
#include <linux/kernel.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/r8a7790.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
/*
* MD EXTAL PLL0 PLL1 PLL3
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
index e2fdfcc14436..10e193d707f5 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -23,9 +23,9 @@
#include <linux/kernel.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/rcar-gen2.h>
+#include "clock.h"
+#include "common.h"
+#include "rcar-gen2.h"
/*
* MD EXTAL PLL0 PLL1 PLL3
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index d16d9ca7f79e..7071676145c4 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -21,8 +21,8 @@
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
/* SH7372 registers */
#define FRQCRA IOMEM(0xe6150000)
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 0d9cd1fe0212..d8c4048b9e33 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -22,8 +22,8 @@
#include <linux/sh_clk.h>
#include <linux/clkdev.h>
#include <asm/processor.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
#define FRQCRA IOMEM(0xe6150000)
#define FRQCRB IOMEM(0xe6150004)
@@ -638,16 +638,25 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
+ CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP219]), /* SCIFA7 */
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
+ CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), /* SCIFA5 */
CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
+ CLKDEV_DEV_ID("0xe6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+ CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), /* SCIFA0 */
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+ CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]), /* SCIFA1 */
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
+ CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]), /* SCIFA2 */
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
+ CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]), /* SCIFA3 */
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
+ CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]), /* SCIFA4 */
CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
+ CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP331]), /* SCIFA6 */
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */
CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
@@ -681,6 +690,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk),
CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk),
CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]), /* CMT1 */
+ CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]), /* CMT1 */
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), /* TMU0 */
};
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index e7232a0373b9..806f94038cc4 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -25,7 +25,7 @@
#ifdef CONFIG_COMMON_CLK
#include <linux/clk.h>
#include <linux/clkdev.h>
-#include <mach/clock.h>
+#include "clock.h"
void __init shmobile_clk_workaround(const struct clk_name *clks,
int nr_clks, bool enable)
@@ -49,8 +49,8 @@ void __init shmobile_clk_workaround(const struct clk_name *clks,
#else /* CONFIG_COMMON_CLK */
#include <linux/sh_clk.h>
#include <linux/export.h>
-#include <mach/clock.h>
-#include <mach/common.h>
+#include "clock.h"
+#include "common.h"
unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk)
{
diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/clock.h
index 31b6417463e6..31b6417463e6 100644
--- a/arch/arm/mach-shmobile/include/mach/clock.h
+++ b/arch/arm/mach-shmobile/clock.h
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/common.h
index f7a360edcc35..98056081f0da 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/common.h
@@ -35,8 +35,10 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
#ifdef CONFIG_SUSPEND
int shmobile_suspend_init(void);
+void shmobile_smp_apmu_suspend_init(void);
#else
static inline int shmobile_suspend_init(void) { return 0; }
+static inline void shmobile_smp_apmu_suspend_init(void) { }
#endif
#ifdef CONFIG_CPU_IDLE
@@ -45,12 +47,19 @@ int shmobile_cpuidle_init(void);
static inline int shmobile_cpuidle_init(void) { return 0; }
#endif
+#ifdef CONFIG_CPU_FREQ
+int shmobile_cpufreq_init(void);
+#else
+static inline int shmobile_cpufreq_init(void) { return 0; }
+#endif
+
extern void __iomem *shmobile_scu_base;
static inline void __init shmobile_init_late(void)
{
shmobile_suspend_init();
shmobile_cpuidle_init();
+ shmobile_cpufreq_init();
}
#endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/console.c b/arch/arm/mach-shmobile/console.c
index 9411a5bf4fd6..f2e79f2376e1 100644
--- a/arch/arm/mach-shmobile/console.c
+++ b/arch/arm/mach-shmobile/console.c
@@ -19,8 +19,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <mach/common.h>
#include <asm/mach/map.h>
+#include "common.h"
void __init shmobile_setup_console(void)
{
diff --git a/arch/arm/mach-shmobile/cpufreq.c b/arch/arm/mach-shmobile/cpufreq.c
new file mode 100644
index 000000000000..8a24b2be46ae
--- /dev/null
+++ b/arch/arm/mach-shmobile/cpufreq.c
@@ -0,0 +1,17 @@
+/*
+ * CPUFreq support code for SH-Mobile ARM
+ *
+ * Copyright (C) 2014 Gaku Inami
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+
+int __init shmobile_cpufreq_init(void)
+{
+ platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
+ return 0;
+}
diff --git a/arch/arm/mach-shmobile/include/mach/dma-register.h b/arch/arm/mach-shmobile/dma-register.h
index 97c40bd9b94f..97c40bd9b94f 100644
--- a/arch/arm/mach-shmobile/include/mach/dma-register.h
+++ b/arch/arm/mach-shmobile/dma-register.h
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index e5be5c88644b..50c491567e11 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -10,14 +10,18 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/assembler.h>
#include <asm/memory.h>
+#ifdef CONFIG_SMP
ENTRY(shmobile_invalidate_start)
bl v7_invalidate_l1
b secondary_startup
ENDPROC(shmobile_invalidate_start)
+#endif
/*
* Reset vector for secondary CPUs.
@@ -68,14 +72,14 @@ shmobile_smp_boot_find_mpidr:
shmobile_smp_boot_next:
add r1, r1, #1
- cmp r1, #CONFIG_NR_CPUS
+ cmp r1, #NR_CPUS
blo shmobile_smp_boot_find_mpidr
b shmobile_smp_sleep
shmobile_smp_boot_found:
ldr r0, [r7, r1, lsl #2]
- mov pc, r9
+ ret r9
ENDPROC(shmobile_smp_boot)
ENTRY(shmobile_smp_sleep)
@@ -85,10 +89,10 @@ ENDPROC(shmobile_smp_sleep)
.globl shmobile_smp_mpidr
shmobile_smp_mpidr:
-1: .space CONFIG_NR_CPUS * 4
+1: .space NR_CPUS * 4
.globl shmobile_smp_fn
shmobile_smp_fn:
-2: .space CONFIG_NR_CPUS * 4
+2: .space NR_CPUS * 4
.globl shmobile_smp_arg
shmobile_smp_arg:
-3: .space CONFIG_NR_CPUS * 4
+3: .space NR_CPUS * 4
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index d241bfd6926d..5aee83f079e2 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -1,24 +1,10 @@
#ifndef __ASM_MACH_IRQS_H
#define __ASM_MACH_IRQS_H
-#include <linux/sh_intc.h>
-
-/* GIC */
-#define gic_spi(nr) ((nr) + 32)
-#define gic_iid(nr) (nr) /* ICCIAR / interrupt ID */
-
-/* INTCS */
-#define INTCS_VECT_BASE 0x3400
-#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
-#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
+/* Stuck here until drivers/pinctl/sh-pfc gets rid of legacy code */
/* External IRQ pins */
#define IRQPIN_BASE 2000
#define irq_pin(nr) ((nr) + IRQPIN_BASE)
-/* GPIO IRQ */
-#define _GPIO_IRQ_BASE 2500
-#define GPIO_IRQ_BASE(x) (_GPIO_IRQ_BASE + (32 * x))
-#define GPIO_IRQ(x, y) (_GPIO_IRQ_BASE + (32 * x) + y)
-
#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index a91caad7db7c..e2af00b1bd9d 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -22,11 +22,10 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/sh_intc.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "intc.h"
+#include "irqs.h"
enum {
UNUSED_INTCA = 0,
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 19a26f4579b3..44457a94897b 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -22,15 +22,16 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/sh_intc.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
-#include <mach/intc.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include "intc.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
enum {
UNUSED = 0,
diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/intc.h
index a5603c76cfe0..a5603c76cfe0 100644
--- a/arch/arm/mach-shmobile/include/mach/intc.h
+++ b/arch/arm/mach-shmobile/intc.h
diff --git a/arch/arm/mach-shmobile/irqs.h b/arch/arm/mach-shmobile/irqs.h
new file mode 100644
index 000000000000..4ff2d2aa94f0
--- /dev/null
+++ b/arch/arm/mach-shmobile/irqs.h
@@ -0,0 +1,21 @@
+#ifndef __SHMOBILE_IRQS_H
+#define __SHMOBILE_IRQS_H
+
+#include <linux/sh_intc.h>
+#include <mach/irqs.h>
+
+/* GIC */
+#define gic_spi(nr) ((nr) + 32)
+#define gic_iid(nr) (nr) /* ICCIAR / interrupt ID */
+
+/* INTCS */
+#define INTCS_VECT_BASE 0x3400
+#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
+#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
+
+/* GPIO IRQ */
+#define _GPIO_IRQ_BASE 2500
+#define GPIO_IRQ_BASE(x) (_GPIO_IRQ_BASE + (32 * x))
+#define GPIO_IRQ(x, y) (_GPIO_IRQ_BASE + (32 * x) + y)
+
+#endif /* __SHMOBILE_IRQS_H */
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
index 8cb641c00fdb..2c06810d3a70 100644
--- a/arch/arm/mach-shmobile/platsmp-apmu.c
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -7,27 +7,32 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/cpu_pm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/of_address.h>
#include <linux/smp.h>
+#include <linux/suspend.h>
+#include <linux/threads.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
+#include <asm/proc-fns.h>
#include <asm/smp_plat.h>
-#include <mach/common.h>
+#include <asm/suspend.h>
+#include "common.h"
static struct {
void __iomem *iomem;
int bit;
-} apmu_cpus[CONFIG_NR_CPUS];
+} apmu_cpus[NR_CPUS];
#define WUPCR_OFFS 0x10
#define PSTR_OFFS 0x40
#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
-static int apmu_power_on(void __iomem *p, int bit)
+static int __maybe_unused apmu_power_on(void __iomem *p, int bit)
{
/* request power on */
writel_relaxed(BIT(bit), p + WUPCR_OFFS);
@@ -46,7 +51,7 @@ static int apmu_power_off(void __iomem *p, int bit)
return 0;
}
-static int apmu_power_off_poll(void __iomem *p, int bit)
+static int __maybe_unused apmu_power_off_poll(void __iomem *p, int bit)
{
int k;
@@ -69,7 +74,7 @@ static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
static void apmu_init_cpu(struct resource *res, int cpu, int bit)
{
- if (apmu_cpus[cpu].iomem)
+ if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem)
return;
apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
@@ -133,6 +138,7 @@ void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
apmu_parse_cfg(apmu_init_cpu);
}
+#ifdef CONFIG_SMP
int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/* For this particular CPU register boot vector */
@@ -140,8 +146,9 @@ int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
return apmu_wrap(cpu, apmu_power_on);
}
+#endif
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
/* nicked from arch/arm/mach-exynos/hotplug.c */
static inline void cpu_enter_lowpower_a15(void)
{
@@ -172,16 +179,40 @@ static inline void cpu_enter_lowpower_a15(void)
dsb();
}
-void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
{
- /* For this particular CPU deregister boot vector */
- shmobile_smp_hook(cpu, 0, 0);
/* Select next sleep mode using the APMU */
apmu_wrap(cpu, apmu_power_off);
/* Do ARM specific CPU shutdown */
cpu_enter_lowpower_a15();
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+ unsigned int v;
+
+ asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
+ " orr %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " orr %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (CR_C), "Ir" (0x40)
+ : "cc");
+}
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU)
+void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+ /* For this particular CPU deregister boot vector */
+ shmobile_smp_hook(cpu, 0, 0);
+
+ /* Shutdown CPU core */
+ shmobile_smp_apmu_cpu_shutdown(cpu);
/* jump to shared mach-shmobile sleep / reset code */
shmobile_smp_sleep();
@@ -192,3 +223,25 @@ int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
return apmu_wrap(cpu, apmu_power_off_poll);
}
#endif
+
+#if defined(CONFIG_SUSPEND)
+static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
+{
+ shmobile_smp_hook(cpu, virt_to_phys(cpu_resume), 0);
+ shmobile_smp_apmu_cpu_shutdown(cpu);
+ cpu_do_idle(); /* WFI selects Core Standby */
+ return 1;
+}
+
+static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
+{
+ cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
+ cpu_leave_lowpower();
+ return 0;
+}
+
+void __init shmobile_smp_apmu_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
index 673ad6e80869..64663110ab6c 100644
--- a/arch/arm/mach-shmobile/platsmp-scu.c
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -15,7 +15,7 @@
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
-#include <mach/common.h>
+#include "common.h"
static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
unsigned long action, void *hcpu)
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 9ebc246b8d7d..3923e09e966d 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
-#include <mach/common.h>
+#include "common.h"
extern unsigned long shmobile_smp_fn[];
extern unsigned long shmobile_smp_arg[];
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 40b87aa1d448..a0d44d537fa0 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -10,8 +10,8 @@
*/
#include <linux/console.h>
#include <linux/suspend.h>
-#include <mach/pm-rmobile.h>
-#include <mach/common.h>
+#include "common.h"
+#include "pm-rmobile.h"
#ifdef CONFIG_PM
static int r8a7740_pd_a4s_suspend(void)
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
index d6fe189b2df6..69f70b7f7fb2 100644
--- a/arch/arm/mach-shmobile/pm-r8a7779.c
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -13,20 +13,33 @@
#include <linux/suspend.h>
#include <linux/err.h>
#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/console.h>
+
#include <asm/io.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7779.h>
+
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
/* SYSC */
#define SYSCIER 0x0c
#define SYSCIMR 0x10
+struct r8a7779_pm_domain {
+ struct generic_pm_domain genpd;
+ struct rcar_sysc_ch ch;
+};
+
+static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+{
+ return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
+}
+
#if defined(CONFIG_PM) || defined(CONFIG_SMP)
static void __init r8a7779_sysc_init(void)
diff --git a/arch/arm/mach-shmobile/pm-r8a7790.c b/arch/arm/mach-shmobile/pm-r8a7790.c
index fc82839e2c2a..80e8d95e54d3 100644
--- a/arch/arm/mach-shmobile/pm-r8a7790.c
+++ b/arch/arm/mach-shmobile/pm-r8a7790.c
@@ -11,9 +11,21 @@
*/
#include <linux/kernel.h>
+#include <linux/smp.h>
#include <asm/io.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7790.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7790.h"
+
+/* RST */
+#define RST 0xe6160000
+#define CA15BAR 0x0020
+#define CA7BAR 0x0030
+#define CA15RESCNT 0x0040
+#define CA7RESCNT 0x0044
+
+/* On-chip RAM */
+#define MERAM 0xe8080000
/* SYSC */
#define SYSCIER 0x0c
@@ -38,8 +50,33 @@ static inline void r8a7790_sysc_init(void) {}
void __init r8a7790_pm_init(void)
{
+ void __iomem *p;
+ u32 bar;
static int once;
- if (!once++)
- r8a7790_sysc_init();
+ if (once++)
+ return;
+
+ /* MERAM for jump stub, because BAR requires 256KB aligned address */
+ p = ioremap_nocache(MERAM, shmobile_boot_size);
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ iounmap(p);
+
+ /* setup reset vectors */
+ p = ioremap_nocache(RST, 0x63);
+ bar = (MERAM >> 8) & 0xfffffc00;
+ writel_relaxed(bar, p + CA15BAR);
+ writel_relaxed(bar, p + CA7BAR);
+ writel_relaxed(bar | 0x10, p + CA15BAR);
+ writel_relaxed(bar | 0x10, p + CA7BAR);
+
+ /* de-assert reset for all CPUs */
+ writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+ p + CA15RESCNT);
+ writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
+ p + CA7RESCNT);
+ iounmap(p);
+
+ r8a7790_sysc_init();
+ shmobile_smp_apmu_suspend_init();
}
diff --git a/arch/arm/mach-shmobile/pm-r8a7791.c b/arch/arm/mach-shmobile/pm-r8a7791.c
new file mode 100644
index 000000000000..25f107bb3657
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-r8a7791.c
@@ -0,0 +1,73 @@
+/*
+ * r8a7791 Power management support
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7791.h"
+
+#define RST 0xe6160000
+#define CA15BAR 0x0020
+#define CA15RESCNT 0x0040
+#define RAM 0xe6300000
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init r8a7791_sysc_init(void)
+{
+ void __iomem *base = rcar_sysc_init(0xe6180000);
+
+ /* enable all interrupt sources, but do not use interrupt handler */
+ iowrite32(0x0131000e, base + SYSCIER);
+ iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_SMP */
+
+static inline void r8a7791_sysc_init(void) {}
+
+#endif /* CONFIG_SMP */
+
+void __init r8a7791_pm_init(void)
+{
+ void __iomem *p;
+ u32 bar;
+ static int once;
+
+ if (once++)
+ return;
+
+ /* RAM for jump stub, because BAR requires 256KB aligned address */
+ p = ioremap_nocache(RAM, shmobile_boot_size);
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ iounmap(p);
+
+ /* setup reset vectors */
+ p = ioremap_nocache(RST, 0x63);
+ bar = (RAM >> 8) & 0xfffffc00;
+ writel_relaxed(bar, p + CA15BAR);
+ writel_relaxed(bar | 0x10, p + CA15BAR);
+
+ /* enable clocks to all CPUs */
+ writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+ p + CA15RESCNT);
+ iounmap(p);
+
+ r8a7791_sysc_init();
+ shmobile_smp_apmu_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c
index 1f465a12d1b1..34b8a5674f85 100644
--- a/arch/arm/mach-shmobile/pm-rcar.c
+++ b/arch/arm/mach-shmobile/pm-rcar.c
@@ -13,7 +13,7 @@
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <asm/io.h>
-#include <mach/pm-rcar.h>
+#include "pm-rcar.h"
/* SYSC */
#define SYSCSR 0x00
diff --git a/arch/arm/mach-shmobile/include/mach/pm-rcar.h b/arch/arm/mach-shmobile/pm-rcar.h
index ef3a1ef628f1..ef3a1ef628f1 100644
--- a/arch/arm/mach-shmobile/include/mach/pm-rcar.h
+++ b/arch/arm/mach-shmobile/pm-rcar.h
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
index f710235aff2f..ebdd16e94a84 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.c
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -17,7 +17,7 @@
#include <linux/pm.h>
#include <linux/pm_clock.h>
#include <asm/io.h>
-#include <mach/pm-rmobile.h>
+#include "pm-rmobile.h"
/* SYSC */
#define SPDCR IOMEM(0xe6180008)
diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h
index 690553a06887..690553a06887 100644
--- a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+++ b/arch/arm/mach-shmobile/pm-rmobile.h
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 0de75fd394b9..7e5c2676c489 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -21,13 +21,15 @@
#include <linux/irq.h>
#include <linux/bitrev.h>
#include <linux/console.h>
+
#include <asm/cpuidle.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <asm/suspend.h>
-#include <mach/common.h>
-#include <mach/sh7372.h>
-#include <mach/pm-rmobile.h>
+
+#include "common.h"
+#include "pm-rmobile.h"
+#include "sh7372.h"
/* DBG */
#define DBGREG1 IOMEM(0xe6100020)
diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c
index 99086e98fbbc..a7e466817965 100644
--- a/arch/arm/mach-shmobile/pm-sh73a0.c
+++ b/arch/arm/mach-shmobile/pm-sh73a0.c
@@ -9,7 +9,7 @@
*/
#include <linux/suspend.h>
-#include <mach/common.h>
+#include "common.h"
#ifdef CONFIG_SUSPEND
static int sh73a0_enter_suspend(suspend_state_t suspend_state)
diff --git a/arch/arm/mach-shmobile/include/mach/r7s72100.h b/arch/arm/mach-shmobile/r7s72100.h
index 5f34b20ecd4a..efb723c88dd0 100644
--- a/arch/arm/mach-shmobile/include/mach/r7s72100.h
+++ b/arch/arm/mach-shmobile/r7s72100.h
@@ -3,6 +3,5 @@
void r7s72100_add_dt_devices(void);
void r7s72100_clock_init(void);
-void r7s72100_init_early(void);
#endif /* __ASM_R7S72100_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/r8a73a4.h
index ce8bdd1d8a8a..ce8bdd1d8a8a 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a73a4.h
+++ b/arch/arm/mach-shmobile/r8a73a4.h
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/r8a7740.h
index 5e3c9ec06303..1d1a5fd78b6b 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/r8a7740.h
@@ -19,8 +19,6 @@
#ifndef __ASM_R8A7740_H__
#define __ASM_R8A7740_H__
-#include <mach/pm-rmobile.h>
-
/*
* MD_CKx pin
*/
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/r8a7778.h
index f4076a50e970..f4076a50e970 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ b/arch/arm/mach-shmobile/r8a7778.h
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/r8a7779.h
index 88eeceaf1088..5415c719dc19 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/r8a7779.h
@@ -2,8 +2,6 @@
#define __ASM_R8A7779_H__
#include <linux/sh_clk.h>
-#include <linux/pm_domain.h>
-#include <mach/pm-rcar.h>
/* HPB-DMA slave IDs */
enum {
@@ -12,17 +10,6 @@ enum {
HPBDMA_SLAVE_SDHI0_RX,
};
-struct r8a7779_pm_domain {
- struct generic_pm_domain genpd;
- struct rcar_sysc_ch ch;
-};
-
-static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
-{
- return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
-}
-
-extern void r8a7779_init_delay(void);
extern void r8a7779_init_irq_extpin(int irlm);
extern void r8a7779_init_irq_extpin_dt(int irlm);
extern void r8a7779_init_irq_dt(void);
@@ -32,6 +19,7 @@ extern void r8a7779_add_early_devices(void);
extern void r8a7779_add_standard_devices(void);
extern void r8a7779_add_standard_devices_dt(void);
extern void r8a7779_init_late(void);
+extern u32 r8a7779_read_mode_pins(void);
extern void r8a7779_clock_init(void);
extern void r8a7779_pinmux_init(void);
extern void r8a7779_pm_init(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/r8a7790.h
index 0b95babe84ba..459827f1369b 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/r8a7790.h
@@ -1,8 +1,6 @@
#ifndef __ASM_R8A7790_H__
#define __ASM_R8A7790_H__
-#include <mach/rcar-gen2.h>
-
/* DMA slave IDs */
enum {
RCAR_DMA_SLAVE_INVALID,
@@ -33,7 +31,6 @@ void r8a7790_add_dt_devices(void);
void r8a7790_clock_init(void);
void r8a7790_pinmux_init(void);
void r8a7790_pm_init(void);
-void r8a7790_init_early(void);
extern struct smp_operations r8a7790_smp_ops;
#endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7791.h b/arch/arm/mach-shmobile/r8a7791.h
index 664274cc4b64..86eae7bceb6f 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7791.h
+++ b/arch/arm/mach-shmobile/r8a7791.h
@@ -5,6 +5,7 @@ void r8a7791_add_standard_devices(void);
void r8a7791_add_dt_devices(void);
void r8a7791_clock_init(void);
void r8a7791_pinmux_init(void);
+void r8a7791_pm_init(void);
extern struct smp_operations r8a7791_smp_ops;
#endif /* __ASM_R8A7791_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/rcar-gen2.h b/arch/arm/mach-shmobile/rcar-gen2.h
index 43f606eb2d82..ce53cb5f53a1 100644
--- a/arch/arm/mach-shmobile/include/mach/rcar-gen2.h
+++ b/arch/arm/mach-shmobile/rcar-gen2.h
@@ -4,5 +4,6 @@
void rcar_gen2_timer_init(void);
#define MD(nr) BIT(nr)
u32 rcar_gen2_read_mode_pins(void);
+void rcar_gen2_reserve(void);
#endif /* __ASM_RCAR_GEN2_H__ */
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index d953ff6e78a2..b06a9e8f59a5 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -16,14 +16,13 @@
* 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-provider.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/of_platform.h>
-#include <mach/common.h>
+#include <linux/mm.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include "common.h"
static struct map_desc emev2_io_desc[] __initdata = {
#ifdef CONFIG_SMP
@@ -42,17 +41,6 @@ static void __init emev2_map_io(void)
iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
}
-static void __init emev2_init_delay(void)
-{
- shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
-}
-
-static void __init emev2_add_standard_devices_dt(void)
-{
- of_clk_init(NULL);
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
static const char *emev2_boards_compat_dt[] __initconst = {
"renesas,emev2",
NULL,
@@ -63,8 +51,7 @@ extern struct smp_operations emev2_smp_ops;
DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
.smp = smp_ops(emev2_smp_ops),
.map_io = emev2_map_io,
- .init_early = emev2_init_delay,
- .init_machine = emev2_add_standard_devices_dt,
+ .init_early = shmobile_init_delay,
.init_late = shmobile_init_late,
.dt_compat = emev2_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r7s72100.c b/arch/arm/mach-shmobile/setup-r7s72100.c
index 412e179429cd..f3b3b14ba972 100644
--- a/arch/arm/mach-shmobile/setup-r7s72100.c
+++ b/arch/arm/mach-shmobile/setup-r7s72100.c
@@ -22,18 +22,20 @@
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r7s72100.h>
+
#include <asm/mach/arch.h>
+#include "common.h"
+#include "irqs.h"
+#include "r7s72100.h"
+
static struct resource mtu2_resources[] __initdata = {
DEFINE_RES_MEM(0xfcff0000, 0x400),
DEFINE_RES_IRQ_NAMED(gic_iid(139), "tgi0a"),
};
#define r7s72100_register_mtu2() \
- platform_device_register_resndata(&platform_bus, "sh-mtu2", \
+ platform_device_register_resndata(NULL, "sh-mtu2", \
-1, mtu2_resources, \
ARRAY_SIZE(mtu2_resources), \
NULL, 0)
@@ -43,11 +45,6 @@ void __init r7s72100_add_dt_devices(void)
r7s72100_register_mtu2();
}
-void __init r7s72100_init_early(void)
-{
- shmobile_setup_delay(400, 1, 3); /* Cortex-A9 @ 400MHz */
-}
-
#ifdef CONFIG_USE_OF
static const char *r7s72100_boards_compat_dt[] __initdata = {
"renesas,r7s72100",
@@ -55,7 +52,7 @@ static const char *r7s72100_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
- .init_early = r7s72100_init_early,
+ .init_early = shmobile_init_delay,
.dt_compat = r7s72100_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 9333770cfac2..6683072a9d98 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -24,12 +24,14 @@
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/r8a73a4.h>
+
#include <asm/mach/arch.h>
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "r8a73a4.h"
+
static const struct resource pfc_resources[] = {
DEFINE_RES_MEM(0xe6050000, 0x9000),
};
@@ -68,7 +70,7 @@ R8A73A4_SCIFB(4, 0xe6ce0000, gic_spi(150)); /* SCIFB2 */
R8A73A4_SCIFB(5, 0xe6cf0000, gic_spi(151)); /* SCIFB3 */
#define r8a73a4_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -149,7 +151,7 @@ static const struct resource irqc1_resources[] = {
};
#define r8a73a4_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
@@ -179,7 +181,7 @@ static struct resource cmt1_resources[] = {
};
#define r8a7790_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
@@ -187,12 +189,6 @@ static struct resource cmt1_resources[] = {
void __init r8a73a4_add_dt_devices(void)
{
- r8a73a4_register_scif(0);
- r8a73a4_register_scif(1);
- r8a73a4_register_scif(2);
- r8a73a4_register_scif(3);
- r8a73a4_register_scif(4);
- r8a73a4_register_scif(5);
r8a7790_register_cmt(1);
}
@@ -280,13 +276,19 @@ static struct resource dma_resources[] = {
};
#define r8a73a4_register_dmac() \
- platform_device_register_resndata(&platform_bus, "sh-dma-engine", 0, \
+ platform_device_register_resndata(NULL, "sh-dma-engine", 0, \
dma_resources, ARRAY_SIZE(dma_resources), \
&dma_pdata, sizeof(dma_pdata))
void __init r8a73a4_add_standard_devices(void)
{
r8a73a4_add_dt_devices();
+ r8a73a4_register_scif(0);
+ r8a73a4_register_scif(1);
+ r8a73a4_register_scif(2);
+ r8a73a4_register_scif(3);
+ r8a73a4_register_scif(4);
+ r8a73a4_register_scif(5);
r8a73a4_register_irqc(0);
r8a73a4_register_irqc(1);
r8a73a4_register_thermal();
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 35dec233301e..3d5eacaba3e6 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -31,16 +31,18 @@
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
#include <linux/platform_data/sh_ipmmu.h>
-#include <mach/dma-register.h>
-#include <mach/r8a7740.h>
-#include <mach/pm-rmobile.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
+
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
+
static struct map_desc r8a7740_io_desc[] __initdata = {
/*
* for CPGA/INTC/PFC
@@ -310,6 +312,10 @@ static struct platform_device ipmmu_device = {
};
static struct platform_device *r8a7740_devices_dt[] __initdata = {
+ &cmt1_device,
+};
+
+static struct platform_device *r8a7740_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
@@ -319,10 +325,6 @@ static struct platform_device *r8a7740_devices_dt[] __initdata = {
&scif6_device,
&scif7_device,
&scif8_device,
- &cmt1_device,
-};
-
-static struct platform_device *r8a7740_early_devices[] __initdata = {
&irqpin0_device,
&irqpin1_device,
&irqpin2_device,
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index d311ef903b39..f00a488dcf43 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -37,12 +37,14 @@
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/dma-mapping.h>
-#include <mach/irqs.h>
-#include <mach/r8a7778.h>
-#include <mach/common.h>
+
#include <asm/mach/arch.h>
#include <asm/hardware/cache-l2x0.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
/* SCIF */
#define R8A7778_SCIF(index, baseaddr, irq) \
static struct plat_sci_port scif##index##_platform_data = { \
@@ -64,7 +66,7 @@ R8A7778_SCIF(4, 0xffe44000, gic_iid(0x6a));
R8A7778_SCIF(5, 0xffe45000, gic_iid(0x6b));
#define r8a7778_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -84,7 +86,7 @@ static struct resource sh_tmu0_resources[] = {
#define r8a7778_register_tmu(idx) \
platform_device_register_resndata( \
- &platform_bus, "sh-tmu", idx, \
+ NULL, "sh-tmu", idx, \
sh_tmu##idx##_resources, \
ARRAY_SIZE(sh_tmu##idx##_resources), \
&sh_tmu##idx##_platform_data, \
@@ -173,7 +175,6 @@ static struct resource ohci_resources[] __initdata = {
#define USB_PLATFORM_INFO(hci) \
static struct platform_device_info hci##_info __initdata = { \
- .parent = &platform_bus, \
.name = #hci "-platform", \
.id = -1, \
.res = hci##_resources, \
@@ -212,7 +213,7 @@ R8A7778_GPIO(4);
#define r8a7778_register_gpio(idx) \
platform_device_register_resndata( \
- &platform_bus, "gpio_rcar", idx, \
+ NULL, "gpio_rcar", idx, \
r8a7778_gpio##idx##_resources, \
ARRAY_SIZE(r8a7778_gpio##idx##_resources), \
&r8a7778_gpio##idx##_platform_data, \
@@ -292,12 +293,6 @@ void __init r8a7778_add_dt_devices(void)
}
#endif
- r8a7778_register_scif(0);
- r8a7778_register_scif(1);
- r8a7778_register_scif(2);
- r8a7778_register_scif(3);
- r8a7778_register_scif(4);
- r8a7778_register_scif(5);
r8a7778_register_tmu(0);
}
@@ -496,8 +491,8 @@ static struct resource hpb_dmae_resources[] __initdata = {
static void __init r8a7778_register_hpb_dmae(void)
{
- platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
- hpb_dmae_resources,
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
@@ -506,6 +501,12 @@ static void __init r8a7778_register_hpb_dmae(void)
void __init r8a7778_add_standard_devices(void)
{
r8a7778_add_dt_devices();
+ r8a7778_register_scif(0);
+ r8a7778_register_scif(1);
+ r8a7778_register_scif(2);
+ r8a7778_register_scif(3);
+ r8a7778_register_scif(4);
+ r8a7778_register_scif(5);
r8a7778_register_i2c(0);
r8a7778_register_i2c(1);
r8a7778_register_i2c(2);
@@ -565,7 +566,7 @@ void __init r8a7778_init_irq_extpin(int irlm)
r8a7778_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
- &platform_bus, "renesas_intc_irqpin", -1,
+ NULL, "renesas_intc_irqpin", -1,
irqpin_resources, ARRAY_SIZE(irqpin_resources),
&irqpin_platform_data, sizeof(irqpin_platform_data));
}
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index aba4ed652d54..236c1befb9e3 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -40,15 +40,17 @@
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/pm_runtime.h>
-#include <mach/irqs.h>
-#include <mach/r8a7779.h>
-#include <mach/common.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/mach/map.h>
#include <asm/hardware/cache-l2x0.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
static struct map_desc r8a7779_io_desc[] __initdata = {
/* 2M entity map for 0xf0000000 (MPCORE) */
{
@@ -123,7 +125,7 @@ void __init r8a7779_init_irq_extpin(int irlm)
r8a7779_init_irq_extpin_dt(irlm);
if (irlm)
platform_device_register_resndata(
- &platform_bus, "renesas_intc_irqpin", -1,
+ NULL, "renesas_intc_irqpin", -1,
irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
&irqpin0_platform_data, sizeof(irqpin0_platform_data));
}
@@ -632,24 +634,24 @@ static struct resource hpb_dmae_resources[] __initdata = {
static void __init r8a7779_register_hpb_dmae(void)
{
- platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
- hpb_dmae_resources,
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
ARRAY_SIZE(hpb_dmae_resources),
&dma_platform_data,
sizeof(dma_platform_data));
}
static struct platform_device *r8a7779_devices_dt[] __initdata = {
+ &tmu0_device,
+};
+
+static struct platform_device *r8a7779_standard_devices[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
&scif3_device,
&scif4_device,
&scif5_device,
- &tmu0_device,
-};
-
-static struct platform_device *r8a7779_standard_devices[] __initdata = {
&i2c0_device,
&i2c1_device,
&i2c2_device,
@@ -674,16 +676,6 @@ void __init r8a7779_add_standard_devices(void)
r8a7779_register_hpb_dmae();
}
-/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
-void __init __weak r8a7779_register_twd(void) { }
-
-void __init r8a7779_earlytimer_init(void)
-{
- r8a7779_clock_init();
- r8a7779_register_twd();
- shmobile_earlytimer_init();
-}
-
void __init r8a7779_add_early_devices(void)
{
early_platform_add_devices(r8a7779_devices_dt,
@@ -747,19 +739,28 @@ void __init r8a7779_init_irq_dt(void)
__raw_writel(0x003fee3f, INT2SMSKCR4);
}
-void __init r8a7779_init_delay(void)
+void __init r8a7779_add_standard_devices_dt(void)
{
- shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
+ platform_add_devices(r8a7779_devices_dt,
+ ARRAY_SIZE(r8a7779_devices_dt));
}
-void __init r8a7779_add_standard_devices_dt(void)
+#define MODEMR 0xffcc0020
+
+u32 __init r8a7779_read_mode_pins(void)
{
- /* clocks are setup late during boot in the case of DT */
- r8a7779_clock_init();
+ static u32 mode;
+ static bool mode_valid;
+
+ if (!mode_valid) {
+ void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+ mode_valid = true;
+ }
- platform_add_devices(r8a7779_devices_dt,
- ARRAY_SIZE(r8a7779_devices_dt));
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ return mode;
}
static const char *r8a7779_compat_dt[] __initdata = {
@@ -769,7 +770,7 @@ static const char *r8a7779_compat_dt[] __initdata = {
DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
.map_io = r8a7779_map_io,
- .init_early = r8a7779_init_delay,
+ .init_early = shmobile_init_delay,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = r8a7779_init_irq_dt,
.init_machine = r8a7779_add_standard_devices_dt,
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 6bd08b127fa4..0c12b01bb9e3 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -26,12 +26,15 @@
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/r8a7790.h>
+
#include <asm/mach/arch.h>
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
/* Audio-DMAC */
#define AUDIO_DMAC_SLAVE(_id, _addr, t, r) \
{ \
@@ -113,7 +116,7 @@ static struct resource r8a7790_audio_dmac_resources[] = {
#define r8a7790_register_audio_dmac(id) \
platform_device_register_resndata( \
- &platform_bus, "sh-dma-engine", id, \
+ NULL, "sh-dma-engine", id, \
&r8a7790_audio_dmac_resources[id * 3], 3, \
&r8a7790_audio_dmac_platform_data, \
sizeof(r8a7790_audio_dmac_platform_data))
@@ -149,7 +152,7 @@ R8A7790_GPIO(4);
R8A7790_GPIO(5);
#define r8a7790_register_gpio(idx) \
- platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+ platform_device_register_resndata(NULL, "gpio_rcar", idx, \
r8a7790_gpio##idx##_resources, \
ARRAY_SIZE(r8a7790_gpio##idx##_resources), \
&r8a7790_gpio##idx##_platform_data, \
@@ -227,7 +230,7 @@ R8A7790_HSCIF(8, 0xe62c0000, gic_spi(154)); /* HSCIF0 */
R8A7790_HSCIF(9, 0xe62c8000, gic_spi(155)); /* HSCIF1 */
#define r8a7790_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -246,7 +249,7 @@ static const struct resource irqc0_resources[] __initconst = {
};
#define r8a7790_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
@@ -273,7 +276,7 @@ static struct resource cmt0_resources[] = {
};
#define r8a7790_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
@@ -307,13 +310,6 @@ void __init r8a7790_add_standard_devices(void)
r8a7790_register_audio_dmac(1);
}
-void __init r8a7790_init_early(void)
-{
-#ifndef CONFIG_ARM_ARCH_TIMER
- shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
-#endif
-}
-
#ifdef CONFIG_USE_OF
static const char * const r8a7790_boards_compat_dt[] __initconst = {
@@ -323,8 +319,10 @@ static const char * const r8a7790_boards_compat_dt[] __initconst = {
DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
.smp = smp_ops(r8a7790_smp_ops),
- .init_early = r8a7790_init_early,
+ .init_early = shmobile_init_delay,
.init_time = rcar_gen2_timer_init,
+ .init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = r8a7790_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
index 04a96ddb3224..d47d8b16a43f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7791.c
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -26,12 +26,14 @@
#include <linux/platform_data/irq-renesas-irqc.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
-#include <mach/common.h>
-#include <mach/irqs.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
+
#include <asm/mach/arch.h>
+#include "common.h"
+#include "irqs.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
static const struct resource pfc_resources[] __initconst = {
DEFINE_RES_MEM(0xe6060000, 0x250),
};
@@ -65,7 +67,7 @@ R8A7791_GPIO(6, 0xe6055400, 32);
R8A7791_GPIO(7, 0xe6055800, 26);
#define r8a7791_register_gpio(idx) \
- platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+ platform_device_register_resndata(NULL, "gpio_rcar", idx, \
r8a7791_gpio##idx##_resources, \
ARRAY_SIZE(r8a7791_gpio##idx##_resources), \
&r8a7791_gpio##idx##_platform_data, \
@@ -122,7 +124,7 @@ R8A7791_SCIFA(13, 0xe6c78000, gic_spi(30)); /* SCIFA4 */
R8A7791_SCIFA(14, 0xe6c80000, gic_spi(31)); /* SCIFA5 */
#define r8a7791_register_scif(index) \
- platform_device_register_resndata(&platform_bus, "sh-sci", index, \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
scif##index##_resources, \
ARRAY_SIZE(scif##index##_resources), \
&scif##index##_platform_data, \
@@ -138,7 +140,7 @@ static struct resource cmt0_resources[] = {
};
#define r8a7791_register_cmt(idx) \
- platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
+ platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \
idx, cmt##idx##_resources, \
ARRAY_SIZE(cmt##idx##_resources), \
&cmt##idx##_platform_data, \
@@ -163,7 +165,7 @@ static struct resource irqc0_resources[] = {
};
#define r8a7791_register_irqc(idx) \
- platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+ platform_device_register_resndata(NULL, "renesas_irqc", \
idx, irqc##idx##_resources, \
ARRAY_SIZE(irqc##idx##_resources), \
&irqc##idx##_data, \
@@ -217,6 +219,8 @@ DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
.smp = smp_ops(r8a7791_smp_ops),
.init_early = shmobile_init_delay,
.init_time = rcar_gen2_timer_init,
+ .init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
.dt_compat = r8a7791_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 542c5a47173f..42d5b4308923 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -20,11 +20,14 @@
#include <linux/clk/shmobile.h>
#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/dma-contiguous.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <mach/common.h>
-#include <mach/rcar-gen2.h>
+#include <linux/of_fdt.h>
#include <asm/mach/arch.h>
+#include "common.h"
+#include "rcar-gen2.h"
#define MODEMR 0xe6160060
@@ -110,3 +113,72 @@ void __init rcar_gen2_timer_init(void)
#endif
clocksource_of_init();
}
+
+struct memory_reserve_config {
+ u64 reserved;
+ u64 base, size;
+};
+
+static int __init rcar_gen2_scan_mem(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ const __be32 *reg, *endp;
+ int l;
+ struct memory_reserve_config *mrc = data;
+ u64 lpae_start = 1ULL << 32;
+
+ /* We are scanning "memory" nodes only */
+ if (type == NULL || strcmp(type, "memory"))
+ return 0;
+
+ reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ if (reg == NULL)
+ reg = of_get_flat_dt_prop(node, "reg", &l);
+ if (reg == NULL)
+ return 0;
+
+ endp = reg + (l / sizeof(__be32));
+ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+ u64 base, size;
+
+ base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+ size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+ if (base >= lpae_start)
+ continue;
+
+ if ((base + size) >= lpae_start)
+ size = lpae_start - base;
+
+ if (size < mrc->reserved)
+ continue;
+
+ if (base < mrc->base)
+ continue;
+
+ /* keep the area at top near the 32-bit legacy limit */
+ mrc->base = base + size - mrc->reserved;
+ mrc->size = mrc->reserved;
+ }
+
+ return 0;
+}
+
+struct cma *rcar_gen2_dma_contiguous;
+
+void __init rcar_gen2_reserve(void)
+{
+ struct memory_reserve_config mrc;
+
+ /* reserve 256 MiB at the top of the physical legacy 32-bit space */
+ memset(&mrc, 0, sizeof(mrc));
+ mrc.reserved = SZ_256M;
+
+ of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
+#ifdef CONFIG_DMA_CMA
+ if (mrc.size)
+ dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
+ &rcar_gen2_dma_contiguous, true);
+#endif
+}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2a8b9f2a2f54..9cdfcdfd38fc 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -29,20 +29,22 @@
#include <linux/io.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
-#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
#include <linux/pm_domain.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/sh_ipmmu.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/sh7372.h>
-#include <mach/common.h>
+
#include <asm/mach/map.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "sh7372.h"
+
static struct map_desc sh7372_io_desc[] __initdata = {
/* create a 1:1 entity map for 0xe6xxxxxx
* used by CPGA, INTC and PFC.
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index ad00724a2269..2c802ae9b241 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -29,19 +29,20 @@
#include <linux/io.h>
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
-#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
#include <linux/platform_data/sh_ipmmu.h>
#include <linux/platform_data/irq-renesas-intc-irqpin.h>
-#include <mach/dma-register.h>
-#include <mach/irqs.h>
-#include <mach/sh73a0.h>
-#include <mach/common.h>
+
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
static struct map_desc sh73a0_io_desc[] __initdata = {
/* create a 1:1 entity map for 0xe6xxxxxx
* used by CPGA, INTC and PFC.
@@ -696,6 +697,10 @@ static struct platform_device irqpin3_device = {
};
static struct platform_device *sh73a0_devices_dt[] __initdata = {
+ &cmt1_device,
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
@@ -705,10 +710,6 @@ static struct platform_device *sh73a0_devices_dt[] __initdata = {
&scif6_device,
&scif7_device,
&scif8_device,
- &cmt1_device,
-};
-
-static struct platform_device *sh73a0_early_devices[] __initdata = {
&tmu0_device,
&ipmmu_device,
};
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/sh7372.h
index 854a9f0ca040..4ad960d5075b 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/sh7372.h
@@ -11,10 +11,6 @@
#ifndef __ASM_SH7372_H__
#define __ASM_SH7372_H__
-#include <linux/sh_clk.h>
-#include <linux/pm_domain.h>
-#include <mach/pm-rmobile.h>
-
/* DMA slave IDs */
enum {
SHDMA_SLAVE_INVALID,
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/sh73a0.h
index 359b582dc270..359b582dc270 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/sh73a0.h
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 2dfd748da7f3..6ff1df1df9a7 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -23,9 +23,9 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/delay.h>
-#include <mach/common.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
+#include "common.h"
#define EMEV2_SCU_BASE 0x1e000000
#define EMEV2_SMU_BASE 0xe0110000
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index e7a3201473d0..3100e355c3fd 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -23,14 +23,16 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/delay.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7779.h>
+
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
+
#define AVECR IOMEM(0xfe700040)
#define R8A7779_SCU_BASE 0xf0000000
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
index 591052799e8f..2311694636e1 100644
--- a/arch/arm/mach-shmobile/smp-r8a7790.c
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -17,17 +17,12 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/io.h>
+
#include <asm/smp_plat.h>
-#include <mach/common.h>
-#include <mach/pm-rcar.h>
-#include <mach/r8a7790.h>
-#define RST 0xe6160000
-#define CA15BAR 0x0020
-#define CA7BAR 0x0030
-#define CA15RESCNT 0x0040
-#define CA7RESCNT 0x0044
-#define MERAM 0xe8080000
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7790.h"
static struct rcar_sysc_ch r8a7790_ca15_scu = {
.chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
@@ -41,32 +36,9 @@ static struct rcar_sysc_ch r8a7790_ca7_scu = {
static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
{
- void __iomem *p;
- u32 bar;
-
/* let APMU code install data related to shmobile_boot_vector */
shmobile_smp_apmu_prepare_cpus(max_cpus);
- /* MERAM for jump stub, because BAR requires 256KB aligned address */
- p = ioremap_nocache(MERAM, shmobile_boot_size);
- memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
- iounmap(p);
-
- /* setup reset vectors */
- p = ioremap_nocache(RST, 0x63);
- bar = (MERAM >> 8) & 0xfffffc00;
- writel_relaxed(bar, p + CA15BAR);
- writel_relaxed(bar, p + CA7BAR);
- writel_relaxed(bar | 0x10, p + CA15BAR);
- writel_relaxed(bar | 0x10, p + CA7BAR);
-
- /* enable clocks to all CPUs */
- writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
- p + CA15RESCNT);
- writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
- p + CA7RESCNT);
- iounmap(p);
-
/* turn on power to SCU */
r8a7790_pm_init();
rcar_sysc_power_up(&r8a7790_ca15_scu);
diff --git a/arch/arm/mach-shmobile/smp-r8a7791.c b/arch/arm/mach-shmobile/smp-r8a7791.c
index ec979529f30f..f743386166fb 100644
--- a/arch/arm/mach-shmobile/smp-r8a7791.c
+++ b/arch/arm/mach-shmobile/smp-r8a7791.c
@@ -17,39 +17,19 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/io.h>
+
#include <asm/smp_plat.h>
-#include <mach/common.h>
-#include <mach/r8a7791.h>
-#include <mach/rcar-gen2.h>
-#define RST 0xe6160000
-#define CA15BAR 0x0020
-#define CA15RESCNT 0x0040
-#define RAM 0xe6300000
+#include "common.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
{
- void __iomem *p;
- u32 bar;
-
/* let APMU code install data related to shmobile_boot_vector */
shmobile_smp_apmu_prepare_cpus(max_cpus);
- /* RAM for jump stub, because BAR requires 256KB aligned address */
- p = ioremap_nocache(RAM, shmobile_boot_size);
- memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
- iounmap(p);
-
- /* setup reset vectors */
- p = ioremap_nocache(RST, 0x63);
- bar = (RAM >> 8) & 0xfffffc00;
- writel_relaxed(bar, p + CA15BAR);
- writel_relaxed(bar | 0x10, p + CA15BAR);
-
- /* enable clocks to all CPUs */
- writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
- p + CA15RESCNT);
- iounmap(p);
+ r8a7791_pm_init();
}
static int r8a7791_smp_boot_secondary(unsigned int cpu,
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 13ba36a6831f..22d8f87b23e9 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -22,11 +22,13 @@
#include <linux/smp.h>
#include <linux/io.h>
#include <linux/delay.h>
-#include <mach/common.h>
-#include <mach/sh73a0.h>
+
#include <asm/smp_plat.h>
#include <asm/smp_twd.h>
+#include "common.h"
+#include "sh73a0.h"
+
#define WUPCR IOMEM(0xe6151010)
#define SRESCR IOMEM(0xe6151018)
#define PSTR IOMEM(0xe6151040)
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index 68bc0b82226d..942efdc82a62 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -59,29 +59,37 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
void __init shmobile_init_delay(void)
{
- struct device_node *np, *parent;
- u32 max_freq, freq;
-
- max_freq = 0;
-
- parent = of_find_node_by_path("/cpus");
- if (parent) {
- for_each_child_of_node(parent, np) {
- if (!of_property_read_u32(np, "clock-frequency", &freq))
- max_freq = max(max_freq, freq);
- }
- of_node_put(parent);
- }
+ struct device_node *np, *cpus;
+ bool is_a8_a9 = false;
+ bool is_a15 = false;
+ u32 max_freq = 0;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (!cpus)
+ return;
+
+ for_each_child_of_node(cpus, np) {
+ u32 freq;
+
+ if (!of_property_read_u32(np, "clock-frequency", &freq))
+ max_freq = max(max_freq, freq);
- if (max_freq) {
- if (of_find_compatible_node(NULL, NULL, "arm,cortex-a8"))
- shmobile_setup_delay_hz(max_freq, 1, 3);
- else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
- shmobile_setup_delay_hz(max_freq, 1, 3);
- else if (of_find_compatible_node(NULL, NULL, "arm,cortex-a15"))
- if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
- shmobile_setup_delay_hz(max_freq, 2, 4);
+ if (of_device_is_compatible(np, "arm,cortex-a8") ||
+ of_device_is_compatible(np, "arm,cortex-a9"))
+ is_a8_a9 = true;
+ else if (of_device_is_compatible(np, "arm,cortex-a15"))
+ is_a15 = true;
}
+
+ of_node_put(cpus);
+
+ if (!max_freq)
+ return;
+
+ if (is_a8_a9)
+ shmobile_setup_delay_hz(max_freq, 1, 3);
+ else if (is_a15 && !IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
+ shmobile_setup_delay_hz(max_freq, 2, 4);
}
static void __init shmobile_late_time_init(void)
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index 90df2022276a..6fd4dc88160b 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -19,6 +19,8 @@ config ARCH_SPEAR13XX
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select PINCTRL
+ select MFD_SYSCON
+ select MIGHT_HAVE_PCI
help
Supports for ARM's SPEAR13XX family
@@ -27,12 +29,14 @@ if ARCH_SPEAR13XX
config MACH_SPEAR1310
bool "SPEAr1310 Machine support with Device Tree"
select PINCTRL_SPEAR1310
+ select PHY_ST_SPEAR1310_MIPHY
help
Supports ST SPEAr1310 machine configured via the device-tree
config MACH_SPEAR1340
bool "SPEAr1340 Machine support with Device Tree"
select PINCTRL_SPEAR1340
+ select PHY_ST_SPEAR1340_MIPHY
help
Supports ST SPEAr1340 machine configured via the device-tree
diff --git a/arch/arm/mach-spear/include/mach/spear.h b/arch/arm/mach-spear/include/mach/spear.h
index 5cdc53d9b653..f2d6a0176575 100644
--- a/arch/arm/mach-spear/include/mach/spear.h
+++ b/arch/arm/mach-spear/include/mach/spear.h
@@ -52,10 +52,10 @@
#ifdef CONFIG_ARCH_SPEAR13XX
#define PERIP_GRP2_BASE UL(0xB3000000)
-#define VA_PERIP_GRP2_BASE IOMEM(0xFE000000)
+#define VA_PERIP_GRP2_BASE IOMEM(0xF9000000)
#define MCIF_SDHCI_BASE UL(0xB3000000)
#define SYSRAM0_BASE UL(0xB3800000)
-#define VA_SYSRAM0_BASE IOMEM(0xFE800000)
+#define VA_SYSRAM0_BASE IOMEM(0xF9800000)
#define SYS_LOCATION (VA_SYSRAM0_BASE + 0x600)
#define PERIP_GRP1_BASE UL(0xE0000000)
diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c
index 824b12a56a42..d9ce4d8000f0 100644
--- a/arch/arm/mach-spear/spear1310.c
+++ b/arch/arm/mach-spear/spear1310.c
@@ -42,7 +42,7 @@ static const char * const spear1310_dt_board_compat[] = {
* PHYSICAL VIRTUAL
* 0xD8000000 0xFA000000
*/
-struct map_desc spear1310_io_desc[] __initdata = {
+static struct map_desc spear1310_io_desc[] __initdata = {
{
.virtual = VA_SPEAR1310_RAS_GRP1_BASE,
.pfn = __phys_to_pfn(SPEAR1310_RAS_GRP1_BASE),
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
index 7b6bff7154e1..3f3c0f124bd3 100644
--- a/arch/arm/mach-spear/spear1340.c
+++ b/arch/arm/mach-spear/spear1340.c
@@ -13,136 +13,13 @@
#define pr_fmt(fmt) "SPEAr1340: " fmt
-#include <linux/ahci_platform.h>
-#include <linux/amba/serial.h>
-#include <linux/delay.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include "generic.h"
-#include <mach/spear.h>
-
-/* FIXME: Move SATA PHY code into a standalone driver */
-
-/* Base addresses */
-#define SPEAR1340_SATA_BASE UL(0xB1000000)
-
-/* Power Management Registers */
-#define SPEAR1340_PCM_CFG (VA_MISC_BASE + 0x100)
-#define SPEAR1340_PCM_WKUP_CFG (VA_MISC_BASE + 0x104)
-#define SPEAR1340_SWITCH_CTR (VA_MISC_BASE + 0x108)
-
-#define SPEAR1340_PERIP1_SW_RST (VA_MISC_BASE + 0x318)
-#define SPEAR1340_PERIP2_SW_RST (VA_MISC_BASE + 0x31C)
-#define SPEAR1340_PERIP3_SW_RST (VA_MISC_BASE + 0x320)
-
-/* PCIE - SATA configuration registers */
-#define SPEAR1340_PCIE_SATA_CFG (VA_MISC_BASE + 0x424)
- /* PCIE CFG MASks */
- #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT (1 << 11)
- #define SPEAR1340_PCIE_CFG_POWERUP_RESET (1 << 10)
- #define SPEAR1340_PCIE_CFG_CORE_CLK_EN (1 << 9)
- #define SPEAR1340_PCIE_CFG_AUX_CLK_EN (1 << 8)
- #define SPEAR1340_SATA_CFG_TX_CLK_EN (1 << 4)
- #define SPEAR1340_SATA_CFG_RX_CLK_EN (1 << 3)
- #define SPEAR1340_SATA_CFG_POWERUP_RESET (1 << 2)
- #define SPEAR1340_SATA_CFG_PM_CLK_EN (1 << 1)
- #define SPEAR1340_PCIE_SATA_SEL_PCIE (0)
- #define SPEAR1340_PCIE_SATA_SEL_SATA (1)
- #define SPEAR1340_SATA_PCIE_CFG_MASK 0xF1F
- #define SPEAR1340_PCIE_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_PCIE | \
- SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
- SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
- SPEAR1340_PCIE_CFG_POWERUP_RESET | \
- SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
- #define SPEAR1340_SATA_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_SATA | \
- SPEAR1340_SATA_CFG_PM_CLK_EN | \
- SPEAR1340_SATA_CFG_POWERUP_RESET | \
- SPEAR1340_SATA_CFG_RX_CLK_EN | \
- SPEAR1340_SATA_CFG_TX_CLK_EN)
-
-#define SPEAR1340_PCIE_MIPHY_CFG (VA_MISC_BASE + 0x428)
- #define SPEAR1340_MIPHY_OSC_BYPASS_EXT (1 << 31)
- #define SPEAR1340_MIPHY_CLK_REF_DIV2 (1 << 27)
- #define SPEAR1340_MIPHY_CLK_REF_DIV4 (2 << 27)
- #define SPEAR1340_MIPHY_CLK_REF_DIV8 (3 << 27)
- #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x) (x << 0)
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
- (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
- SPEAR1340_MIPHY_CLK_REF_DIV2 | \
- SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
- (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
- (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
- SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-
-/* SATA device registration */
-static int sata_miphy_init(struct device *dev, void __iomem *addr)
-{
- writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
- writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
- SPEAR1340_PCIE_MIPHY_CFG);
- /* Switch on sata power domain */
- writel((readl(SPEAR1340_PCM_CFG) | (0x800)), SPEAR1340_PCM_CFG);
- msleep(20);
- /* Disable PCIE SATA Controller reset */
- writel((readl(SPEAR1340_PERIP1_SW_RST) & (~0x1000)),
- SPEAR1340_PERIP1_SW_RST);
- msleep(20);
-
- return 0;
-}
-
-void sata_miphy_exit(struct device *dev)
-{
- writel(0, SPEAR1340_PCIE_SATA_CFG);
- writel(0, SPEAR1340_PCIE_MIPHY_CFG);
-
- /* Enable PCIE SATA Controller reset */
- writel((readl(SPEAR1340_PERIP1_SW_RST) | (0x1000)),
- SPEAR1340_PERIP1_SW_RST);
- msleep(20);
- /* Switch off sata power domain */
- writel((readl(SPEAR1340_PCM_CFG) & (~0x800)), SPEAR1340_PCM_CFG);
- msleep(20);
-}
-
-int sata_suspend(struct device *dev)
-{
- if (dev->power.power_state.event == PM_EVENT_FREEZE)
- return 0;
-
- sata_miphy_exit(dev);
-
- return 0;
-}
-
-int sata_resume(struct device *dev)
-{
- if (dev->power.power_state.event == PM_EVENT_THAW)
- return 0;
-
- return sata_miphy_init(dev, NULL);
-}
-
-static struct ahci_platform_data sata_pdata = {
- .init = sata_miphy_init,
- .exit = sata_miphy_exit,
- .suspend = sata_suspend,
- .resume = sata_resume,
-};
-
-/* Add SPEAr1340 auxdata to pass platform data */
-static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
- &sata_pdata),
- {}
-};
static void __init spear1340_dt_init(void)
{
- of_platform_populate(NULL, of_default_bus_match_table,
- spear1340_auxdata_lookup, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
}
diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c
index c9897ea38980..2e463a93468d 100644
--- a/arch/arm/mach-spear/spear13xx.c
+++ b/arch/arm/mach-spear/spear13xx.c
@@ -52,12 +52,12 @@ void __init spear13xx_l2x0_init(void)
/*
* Following will create 16MB static virtual/physical mappings
* PHYSICAL VIRTUAL
- * 0xB3000000 0xFE000000
+ * 0xB3000000 0xF9000000
* 0xE0000000 0xFD000000
* 0xEC000000 0xFC000000
* 0xED000000 0xFB000000
*/
-struct map_desc spear13xx_io_desc[] __initdata = {
+static struct map_desc spear13xx_io_desc[] __initdata = {
{
.virtual = (unsigned long)VA_PERIP_GRP2_BASE,
.pfn = __phys_to_pfn(PERIP_GRP2_BASE),
diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c
index fa2c33ffac04..d4b624f8dfcb 100644
--- a/arch/arm/mach-sti/platsmp.c
+++ b/arch/arm/mach-sti/platsmp.c
@@ -36,7 +36,7 @@ static void write_pen_release(int val)
static DEFINE_SPINLOCK(boot_lock);
-void sti_secondary_init(unsigned int cpu)
+static void sti_secondary_init(unsigned int cpu)
{
trace_hardirqs_off();
@@ -53,7 +53,7 @@ void sti_secondary_init(unsigned int cpu)
spin_unlock(&boot_lock);
}
-int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
@@ -97,7 +97,7 @@ int sti_boot_secondary(unsigned int cpu, struct task_struct *idle)
return pen_release != -1 ? -ENOSYS : 0;
}
-void __init sti_smp_prepare_cpus(unsigned int max_cpus)
+static void __init sti_smp_prepare_cpus(unsigned int max_cpus)
{
void __iomem *scu_base = NULL;
struct device_node *np = of_find_compatible_node(
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 0fbd4f156bfa..1aaa1e15ef70 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
select CLKSRC_MMIO
select GENERIC_IRQ_CHIP
select PINCTRL
- select PINCTRL_SUNXI
select SUN4I_TIMER
if ARCH_SUNXI
@@ -35,4 +34,12 @@ config MACH_SUN7I
select HAVE_ARM_ARCH_TIMER
select SUN5I_HSTIMER
+config MACH_SUN8I
+ bool "Allwinner A23 (sun8i) SoCs support"
+ default ARCH_SUNXI
+ select ARCH_HAS_RESET_CONTROLLER
+ select ARM_GIC
+ select MFD_SUN6I_PRCM
+ select RESET_CONTROLLER
+
endif
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index b6085084e0ff..42d4753683ce 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -130,3 +130,12 @@ DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family")
.dt_compat = sun7i_board_dt_compat,
.restart = sun4i_restart,
MACHINE_END
+
+static const char * const sun8i_board_dt_compat[] = {
+ "allwinner,sun8i-a23",
+ NULL,
+};
+
+DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family")
+ .dt_compat = sun8i_board_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 6fbfbb77dcd9..e48a74458c25 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,24 +2,18 @@ asflags-y += -march=armv7-a
obj-y += io.o
obj-y += irq.o
-obj-y += fuse.o
-obj-y += pmc.o
obj-y += flowctrl.o
-obj-y += powergate.o
-obj-y += apbio.o
obj-y += pm.o
obj-y += reset.o
obj-y += reset-handler.o
obj-y += sleep.o
obj-y += tegra.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-tegra20.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o
endif
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
@@ -28,7 +22,6 @@ endif
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
deleted file mode 100644
index bc471973cf04..000000000000
--- a/arch/arm/mach-tegra/apbio.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2010 NVIDIA Corporation.
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-
-#include "apbio.h"
-#include "iomap.h"
-
-#if defined(CONFIG_TEGRA20_APB_DMA)
-static DEFINE_MUTEX(tegra_apb_dma_lock);
-static u32 *tegra_apb_bb;
-static dma_addr_t tegra_apb_bb_phys;
-static DECLARE_COMPLETION(tegra_apb_wait);
-
-static u32 tegra_apb_readl_direct(unsigned long offset);
-static void tegra_apb_writel_direct(u32 value, unsigned long offset);
-
-static struct dma_chan *tegra_apb_dma_chan;
-static struct dma_slave_config dma_sconfig;
-
-static bool tegra_apb_dma_init(void)
-{
- dma_cap_mask_t mask;
-
- mutex_lock(&tegra_apb_dma_lock);
-
- /* Check to see if we raced to setup */
- if (tegra_apb_dma_chan)
- goto skip_init;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL);
- if (!tegra_apb_dma_chan) {
- /*
- * This is common until the device is probed, so don't
- * shout about it.
- */
- pr_debug("%s: can not allocate dma channel\n", __func__);
- goto err_dma_alloc;
- }
-
- tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
- &tegra_apb_bb_phys, GFP_KERNEL);
- if (!tegra_apb_bb) {
- pr_err("%s: can not allocate bounce buffer\n", __func__);
- goto err_buff_alloc;
- }
-
- dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- dma_sconfig.src_maxburst = 1;
- dma_sconfig.dst_maxburst = 1;
-
-skip_init:
- mutex_unlock(&tegra_apb_dma_lock);
- return true;
-
-err_buff_alloc:
- dma_release_channel(tegra_apb_dma_chan);
- tegra_apb_dma_chan = NULL;
-
-err_dma_alloc:
- mutex_unlock(&tegra_apb_dma_lock);
- return false;
-}
-
-static void apb_dma_complete(void *args)
-{
- complete(&tegra_apb_wait);
-}
-
-static int do_dma_transfer(unsigned long apb_add,
- enum dma_transfer_direction dir)
-{
- struct dma_async_tx_descriptor *dma_desc;
- int ret;
-
- if (dir == DMA_DEV_TO_MEM)
- dma_sconfig.src_addr = apb_add;
- else
- dma_sconfig.dst_addr = apb_add;
-
- ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig);
- if (ret)
- return ret;
-
- dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan,
- tegra_apb_bb_phys, sizeof(u32), dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!dma_desc)
- return -EINVAL;
-
- dma_desc->callback = apb_dma_complete;
- dma_desc->callback_param = NULL;
-
- reinit_completion(&tegra_apb_wait);
-
- dmaengine_submit(dma_desc);
- dma_async_issue_pending(tegra_apb_dma_chan);
- ret = wait_for_completion_timeout(&tegra_apb_wait,
- msecs_to_jiffies(50));
-
- if (WARN(ret == 0, "apb read dma timed out")) {
- dmaengine_terminate_all(tegra_apb_dma_chan);
- return -EFAULT;
- }
- return 0;
-}
-
-static u32 tegra_apb_readl_using_dma(unsigned long offset)
-{
- int ret;
-
- if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
- return tegra_apb_readl_direct(offset);
-
- mutex_lock(&tegra_apb_dma_lock);
- ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
- if (ret < 0) {
- pr_err("error in reading offset 0x%08lx using dma\n", offset);
- *(u32 *)tegra_apb_bb = 0;
- }
- mutex_unlock(&tegra_apb_dma_lock);
- return *((u32 *)tegra_apb_bb);
-}
-
-static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
-{
- int ret;
-
- if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) {
- tegra_apb_writel_direct(value, offset);
- return;
- }
-
- mutex_lock(&tegra_apb_dma_lock);
- *((u32 *)tegra_apb_bb) = value;
- ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
- if (ret < 0)
- pr_err("error in writing offset 0x%08lx using dma\n", offset);
- mutex_unlock(&tegra_apb_dma_lock);
-}
-#else
-#define tegra_apb_readl_using_dma tegra_apb_readl_direct
-#define tegra_apb_writel_using_dma tegra_apb_writel_direct
-#endif
-
-typedef u32 (*apbio_read_fptr)(unsigned long offset);
-typedef void (*apbio_write_fptr)(u32 value, unsigned long offset);
-
-static apbio_read_fptr apbio_read;
-static apbio_write_fptr apbio_write;
-
-static u32 tegra_apb_readl_direct(unsigned long offset)
-{
- return readl(IO_ADDRESS(offset));
-}
-
-static void tegra_apb_writel_direct(u32 value, unsigned long offset)
-{
- writel(value, IO_ADDRESS(offset));
-}
-
-void tegra_apb_io_init(void)
-{
- /* Need to use dma only when it is Tegra20 based platform */
- if (of_machine_is_compatible("nvidia,tegra20") ||
- !of_have_populated_dt()) {
- apbio_read = tegra_apb_readl_using_dma;
- apbio_write = tegra_apb_writel_using_dma;
- } else {
- apbio_read = tegra_apb_readl_direct;
- apbio_write = tegra_apb_writel_direct;
- }
-}
-
-u32 tegra_apb_readl(unsigned long offset)
-{
- return apbio_read(offset);
-}
-
-void tegra_apb_writel(u32 value, unsigned long offset)
-{
- apbio_write(value, offset);
-}
diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h
deleted file mode 100644
index f05d71c303c7..000000000000
--- a/arch/arm/mach-tegra/apbio.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 NVIDIA Corporation.
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_APBIO_H
-#define __MACH_TEGRA_APBIO_H
-
-void tegra_apb_io_init(void);
-u32 tegra_apb_readl(unsigned long offset);
-void tegra_apb_writel(u32 value, unsigned long offset);
-#endif
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 9c6029ba526f..fbe74c6806f3 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -17,9 +17,10 @@
*
*/
+#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
-#include <linux/gpio/driver.h>
#include <linux/rfkill-gpio.h>
+
#include "board.h"
static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index bcf5dbf69d58..da90c89296b9 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -28,13 +28,6 @@
void __init tegra_map_common_io(void);
void __init tegra_init_irq(void);
-int __init tegra_powergate_init(void);
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
-int __init tegra_powergate_debugfs_init(void);
-#else
-static inline int tegra_powergate_debugfs_init(void) { return 0; }
-#endif
-
void __init tegra_paz00_wifikill_init(void);
#endif
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index b5fb7c110c64..e3ebdce3e71f 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -14,16 +14,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <asm/firmware.h>
+#include <linux/clockchips.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <asm/firmware.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/cpuidle.h>
-#include <asm/suspend.h>
#include <asm/smp_plat.h>
+#include <asm/suspend.h>
#include "pm.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index b82dcaee2ef4..b30bf5cba65b 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -19,23 +19,23 @@
* more details.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/clk/tegra.h>
+#include <linux/clockchips.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <linux/clk/tegra.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/cpuidle.h>
#include <asm/proc-fns.h>
-#include <asm/suspend.h>
#include <asm/smp_plat.h>
+#include <asm/suspend.h>
-#include "pm.h"
-#include "sleep.h"
+#include "flowctrl.h"
#include "iomap.h"
#include "irq.h"
-#include "flowctrl.h"
+#include "pm.h"
+#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
static bool abort_flag;
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index ed2a2a7bae4d..35561274f6cf 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -19,17 +19,17 @@
* more details.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/clk/tegra.h>
+#include <linux/clockchips.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
-#include <linux/clockchips.h>
-#include <linux/clk/tegra.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/cpuidle.h>
#include <asm/proc-fns.h>
-#include <asm/suspend.h>
#include <asm/smp_plat.h>
+#include <asm/suspend.h>
#include "pm.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 7bc5d8d667fe..316563141add 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -24,12 +24,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include "fuse.h"
+#include <soc/tegra/fuse.h>
+
#include "cpuidle.h"
void __init tegra_cpuidle_init(void)
{
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_cpuidle_init();
@@ -49,7 +50,7 @@ void __init tegra_cpuidle_init(void)
void tegra_cpuidle_pcie_irqs_in_use(void)
{
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_cpuidle_pcie_irqs_in_use();
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index ce8ab8abf061..ec55d1de1b55 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -18,14 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/cpumask.h>
#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/io.h>
-#include <linux/cpumask.h>
+#include <linux/kernel.h>
+
+#include <soc/tegra/fuse.h>
#include "flowctrl.h"
#include "iomap.h"
-#include "fuse.h"
static u8 flowctrl_offset_halt_cpu[] = {
FLOW_CTRL_HALT_CPU0_EVENTS,
@@ -76,7 +77,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
int i;
reg = flowctrl_read_cpu_csr(cpuid);
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
/* clear wfe bitmap */
reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
@@ -117,7 +118,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
/* Disable powergating via flow controller for CPU0 */
reg = flowctrl_read_cpu_csr(cpuid);
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
/* clear wfe bitmap */
reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
deleted file mode 100644
index c9ac23b385be..000000000000
--- a/arch/arm/mach-tegra/fuse.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * arch/arm/mach-tegra/fuse.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- *
- * Author:
- * Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/random.h>
-#include <linux/clk.h>
-#include <linux/tegra-soc.h>
-
-#include "fuse.h"
-#include "iomap.h"
-#include "apbio.h"
-
-/* Tegra20 only */
-#define FUSE_UID_LOW 0x108
-#define FUSE_UID_HIGH 0x10c
-
-/* Tegra30 and later */
-#define FUSE_VENDOR_CODE 0x200
-#define FUSE_FAB_CODE 0x204
-#define FUSE_LOT_CODE_0 0x208
-#define FUSE_LOT_CODE_1 0x20c
-#define FUSE_WAFER_ID 0x210
-#define FUSE_X_COORDINATE 0x214
-#define FUSE_Y_COORDINATE 0x218
-
-#define FUSE_SKU_INFO 0x110
-
-#define TEGRA20_FUSE_SPARE_BIT 0x200
-#define TEGRA30_FUSE_SPARE_BIT 0x244
-
-int tegra_sku_id;
-int tegra_cpu_process_id;
-int tegra_core_process_id;
-int tegra_chip_id;
-int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
-int tegra_soc_speedo_id;
-enum tegra_revision tegra_revision;
-
-static struct clk *fuse_clk;
-static int tegra_fuse_spare_bit;
-static void (*tegra_init_speedo_data)(void);
-
-/* The BCT to use at boot is specified by board straps that can be read
- * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
- */
-int tegra_bct_strapping;
-
-#define STRAP_OPT 0x008
-#define GMI_AD0 (1 << 4)
-#define GMI_AD1 (1 << 5)
-#define RAM_ID_MASK (GMI_AD0 | GMI_AD1)
-#define RAM_CODE_SHIFT 4
-
-static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
- [TEGRA_REVISION_UNKNOWN] = "unknown",
- [TEGRA_REVISION_A01] = "A01",
- [TEGRA_REVISION_A02] = "A02",
- [TEGRA_REVISION_A03] = "A03",
- [TEGRA_REVISION_A03p] = "A03 prime",
- [TEGRA_REVISION_A04] = "A04",
-};
-
-static void tegra_fuse_enable_clk(void)
-{
- if (IS_ERR(fuse_clk))
- fuse_clk = clk_get_sys(NULL, "fuse");
- if (IS_ERR(fuse_clk))
- return;
- clk_prepare_enable(fuse_clk);
-}
-
-static void tegra_fuse_disable_clk(void)
-{
- if (IS_ERR(fuse_clk))
- return;
- clk_disable_unprepare(fuse_clk);
-}
-
-u32 tegra_fuse_readl(unsigned long offset)
-{
- return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
-}
-
-bool tegra_spare_fuse(int bit)
-{
- bool ret;
-
- tegra_fuse_enable_clk();
-
- ret = tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
-
- tegra_fuse_disable_clk();
-
- return ret;
-}
-
-static enum tegra_revision tegra_get_revision(u32 id)
-{
- u32 minor_rev = (id >> 16) & 0xf;
-
- switch (minor_rev) {
- case 1:
- return TEGRA_REVISION_A01;
- case 2:
- return TEGRA_REVISION_A02;
- case 3:
- if (tegra_chip_id == TEGRA20 &&
- (tegra_spare_fuse(18) || tegra_spare_fuse(19)))
- return TEGRA_REVISION_A03p;
- else
- return TEGRA_REVISION_A03;
- case 4:
- return TEGRA_REVISION_A04;
- default:
- return TEGRA_REVISION_UNKNOWN;
- }
-}
-
-static void tegra_get_process_id(void)
-{
- u32 reg;
-
- tegra_fuse_enable_clk();
-
- reg = tegra_fuse_readl(tegra_fuse_spare_bit);
- tegra_cpu_process_id = (reg >> 6) & 3;
- reg = tegra_fuse_readl(tegra_fuse_spare_bit);
- tegra_core_process_id = (reg >> 12) & 3;
-
- tegra_fuse_disable_clk();
-}
-
-u32 tegra_read_chipid(void)
-{
- return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
-}
-
-static void __init tegra20_fuse_init_randomness(void)
-{
- u32 randomness[2];
-
- randomness[0] = tegra_fuse_readl(FUSE_UID_LOW);
- randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH);
-
- add_device_randomness(randomness, sizeof(randomness));
-}
-
-/* Applies to Tegra30 or later */
-static void __init tegra30_fuse_init_randomness(void)
-{
- u32 randomness[7];
-
- randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE);
- randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE);
- randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0);
- randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1);
- randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID);
- randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE);
- randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE);
-
- add_device_randomness(randomness, sizeof(randomness));
-}
-
-void __init tegra_init_fuse(void)
-{
- u32 id;
- u32 randomness[5];
-
- u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
- reg |= 1 << 28;
- writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
-
- /*
- * Enable FUSE clock. This needs to be hardcoded because the clock
- * subsystem is not active during early boot.
- */
- reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
- reg |= 1 << 7;
- writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
- fuse_clk = ERR_PTR(-EINVAL);
-
- reg = tegra_fuse_readl(FUSE_SKU_INFO);
- randomness[0] = reg;
- tegra_sku_id = reg & 0xFF;
-
- reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
- randomness[1] = reg;
- tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
-
- id = tegra_read_chipid();
- randomness[2] = id;
- tegra_chip_id = (id >> 8) & 0xff;
-
- switch (tegra_chip_id) {
- case TEGRA20:
- tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
- tegra_init_speedo_data = &tegra20_init_speedo_data;
- break;
- case TEGRA30:
- tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
- tegra_init_speedo_data = &tegra30_init_speedo_data;
- break;
- case TEGRA114:
- tegra_init_speedo_data = &tegra114_init_speedo_data;
- break;
- default:
- pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
- tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
- tegra_init_speedo_data = &tegra_get_process_id;
- }
-
- tegra_revision = tegra_get_revision(id);
- tegra_init_speedo_data();
- randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id;
- randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id;
-
- add_device_randomness(randomness, sizeof(randomness));
- switch (tegra_chip_id) {
- case TEGRA20:
- tegra20_fuse_init_randomness();
- break;
- case TEGRA30:
- case TEGRA114:
- default:
- tegra30_fuse_init_randomness();
- break;
- }
-
- pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
- tegra_revision_name[tegra_revision],
- tegra_sku_id, tegra_cpu_process_id,
- tegra_core_process_id);
-}
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
deleted file mode 100644
index c01d04785d67..000000000000
--- a/arch/arm/mach-tegra/fuse.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- *
- * Author:
- * Colin Cross <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_FUSE_H
-#define __MACH_TEGRA_FUSE_H
-
-#define SKU_ID_T20 8
-#define SKU_ID_T25SE 20
-#define SKU_ID_AP25 23
-#define SKU_ID_T25 24
-#define SKU_ID_AP25E 27
-#define SKU_ID_T25E 28
-
-#define TEGRA20 0x20
-#define TEGRA30 0x30
-#define TEGRA114 0x35
-#define TEGRA124 0x40
-
-#ifndef __ASSEMBLY__
-enum tegra_revision {
- TEGRA_REVISION_UNKNOWN = 0,
- TEGRA_REVISION_A01,
- TEGRA_REVISION_A02,
- TEGRA_REVISION_A03,
- TEGRA_REVISION_A03p,
- TEGRA_REVISION_A04,
- TEGRA_REVISION_MAX,
-};
-
-extern int tegra_sku_id;
-extern int tegra_cpu_process_id;
-extern int tegra_core_process_id;
-extern int tegra_chip_id;
-extern int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
-extern int tegra_soc_speedo_id;
-extern enum tegra_revision tegra_revision;
-
-extern int tegra_bct_strapping;
-
-unsigned long long tegra_chip_uid(void);
-void tegra_init_fuse(void);
-bool tegra_spare_fuse(int bit);
-u32 tegra_fuse_readl(unsigned long offset);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void tegra20_init_speedo_data(void);
-#else
-static inline void tegra20_init_speedo_data(void) {}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-void tegra30_init_speedo_data(void);
-#else
-static inline void tegra30_init_speedo_data(void) {}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
-void tegra114_init_speedo_data(void);
-#else
-static inline void tegra114_init_speedo_data(void) {}
-#endif
-#endif /* __ASSEMBLY__ */
-
-#endif
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index ff26af26bd0c..6fc71f1534b0 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -7,13 +7,16 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+#include <linux/clk/tegra.h>
#include <linux/kernel.h>
#include <linux/smp.h>
-#include <linux/clk/tegra.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
#include <asm/smp_plat.h>
-#include "fuse.h"
#include "sleep.h"
static void (*tegra_hotplug_shutdown)(void);
@@ -36,6 +39,11 @@ int tegra_cpu_kill(unsigned cpu)
*/
void __ref tegra_cpu_die(unsigned int cpu)
{
+ if (!tegra_hotplug_shutdown) {
+ WARN(1, "hotplug is not yet initialized\n");
+ return;
+ }
+
/* Clean L1 data cache */
tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
@@ -46,17 +54,23 @@ void __ref tegra_cpu_die(unsigned int cpu)
BUG();
}
-void __init tegra_hotplug_init(void)
+static int __init tegra_hotplug_init(void)
{
if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
- return;
+ return 0;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+ if (!soc_is_tegra())
+ return 0;
+
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+
+ return 0;
}
+pure_initcall(tegra_hotplug_init);
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index bb9c9c29d181..352de159d2c5 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -18,14 +18,14 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/init.h>
-#include <linux/mm.h>
#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
-#include <asm/page.h>
#include <asm/mach/map.h>
+#include <asm/page.h>
#include "board.h"
#include "iomap.h"
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 1a74d562dca1..da7be13aecce 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -17,14 +17,14 @@
*
*/
-#include <linux/kernel.h>
#include <linux/cpu_pm.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
#include <linux/syscore_ops.h>
#include "board.h"
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 929d1046e2b4..b45086666648 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -11,27 +11,28 @@
* 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/errno.h>
+
+#include <linux/clk/tegra.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/clk/tegra.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
-#include <asm/smp_scu.h>
#include <asm/smp_plat.h>
-
-#include "fuse.h"
-#include "flowctrl.h"
-#include "reset.h"
-#include "pmc.h"
+#include <asm/smp_scu.h>
#include "common.h"
+#include "flowctrl.h"
#include "iomap.h"
+#include "reset.h"
static cpumask_t tegra_cpu_init_mask;
@@ -170,13 +171,13 @@ static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
static int tegra_boot_secondary(unsigned int cpu,
struct task_struct *idle)
{
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
return tegra20_boot_secondary(cpu, idle);
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
return tegra30_boot_secondary(cpu, idle);
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
return tegra114_boot_secondary(cpu, idle);
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
return tegra114_boot_secondary(cpu, idle);
return -EINVAL;
diff --git a/arch/arm/mach-tegra/pm-tegra20.c b/arch/arm/mach-tegra/pm-tegra20.c
index d65e1d786400..39ac2b723f2e 100644
--- a/arch/arm/mach-tegra/pm-tegra20.c
+++ b/arch/arm/mach-tegra/pm-tegra20.c
@@ -13,6 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include <linux/kernel.h>
#include "pm.h"
diff --git a/arch/arm/mach-tegra/pm-tegra30.c b/arch/arm/mach-tegra/pm-tegra30.c
index 8fa326d6ff1a..46cc19de9916 100644
--- a/arch/arm/mach-tegra/pm-tegra30.c
+++ b/arch/arm/mach-tegra/pm-tegra30.c
@@ -13,6 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include <linux/kernel.h>
#include "pm.h"
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index f55b05a29b55..b0f48a3946fa 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -16,30 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
+#include <linux/clk/tegra.h>
#include <linux/cpumask.h>
-#include <linux/delay.h>
#include <linux/cpu_pm.h>
-#include <linux/suspend.h>
+#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/clk/tegra.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pm.h>
+#include <soc/tegra/pmc.h>
-#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
-#include <asm/suspend.h>
#include <asm/idmap.h>
#include <asm/proc-fns.h>
+#include <asm/smp_plat.h>
+#include <asm/suspend.h>
#include <asm/tlbflush.h>
-#include "iomap.h"
-#include "reset.h"
#include "flowctrl.h"
-#include "fuse.h"
+#include "iomap.h"
#include "pm.h"
-#include "pmc.h"
+#include "reset.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
@@ -53,7 +55,7 @@ static int (*tegra_sleep_func)(unsigned long v2p);
static void tegra_tear_down_cpu_init(void)
{
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra_tear_down_cpu = tegra20_tear_down_cpu;
@@ -143,7 +145,7 @@ bool tegra_set_cpu_in_lp2(void)
if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
last_cpu = true;
- else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1)
+ else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1)
tegra20_cpu_set_resettable_soon();
spin_unlock(&tegra_lp2_lock);
@@ -166,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
return 0;
}
+static void tegra_pm_set(enum tegra_suspend_mode mode)
+{
+ u32 value;
+
+ switch (tegra_get_chip_id()) {
+ case TEGRA20:
+ case TEGRA30:
+ break;
+ default:
+ /* Turn off CRAIL */
+ value = flowctrl_read_cpu_csr(0);
+ value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
+ value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
+ flowctrl_write_cpu_csr(0, value);
+ break;
+ }
+
+ tegra_pmc_enter_suspend_mode(mode);
+}
+
void tegra_idle_lp2_last(void)
{
- tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
+ tegra_pm_set(TEGRA_SUSPEND_LP2);
cpu_cluster_pm_enter();
suspend_cpu_complex();
@@ -212,7 +234,7 @@ static int tegra_sleep_core(unsigned long v2p)
*/
static bool tegra_lp1_iram_hook(void)
{
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_lp1_iram_hook();
@@ -242,7 +264,7 @@ static bool tegra_lp1_iram_hook(void)
static bool tegra_sleep_core_init(void)
{
- switch (tegra_chip_id) {
+ switch (tegra_get_chip_id()) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_sleep_core_init();
@@ -267,8 +289,6 @@ static bool tegra_sleep_core_init(void)
static void tegra_suspend_enter_lp1(void)
{
- tegra_pmc_suspend();
-
/* copy the reset vector & SDRAM shutdown code into IRAM */
memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
iram_save_size);
@@ -280,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
static void tegra_suspend_exit_lp1(void)
{
- tegra_pmc_resume();
-
/* restore IRAM */
memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
iram_save_size);
@@ -306,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
pr_info("Entering suspend state %s\n", lp_state[mode]);
- tegra_pmc_pm_set(mode);
+ tegra_pm_set(mode);
local_fiq_disable();
@@ -354,7 +372,6 @@ void __init tegra_init_suspend(void)
return;
tegra_tear_down_cpu_init();
- tegra_pmc_suspend_init();
if (mode >= TEGRA_SUSPEND_LP1) {
if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index f4a89698e5b0..83bc87583446 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -21,12 +21,11 @@
#ifndef _MACH_TEGRA_PM_H_
#define _MACH_TEGRA_PM_H_
-#include "pmc.h"
-
struct tegra_lp1_iram {
void *start_addr;
void *end_addr;
};
+
extern struct tegra_lp1_iram tegra_lp1_iram;
extern void (*tegra_sleep_core_finish)(unsigned long v2p);
@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void);
extern void (*tegra_tear_down_cpu)(void);
#ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
- enum tegra_suspend_mode mode);
void tegra_init_suspend(void);
#else
-static inline enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
- enum tegra_suspend_mode mode)
-{
- return TEGRA_SUSPEND_NONE;
-}
static inline void tegra_init_suspend(void) {}
#endif
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
deleted file mode 100644
index 7c7123e7557b..000000000000
--- a/arch/arm/mach-tegra/pmc.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/tegra-powergate.h>
-
-#include "flowctrl.h"
-#include "fuse.h"
-#include "pm.h"
-#include "pmc.h"
-#include "sleep.h"
-
-#define TEGRA_POWER_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
-#define TEGRA_POWER_SYSCLK_OE (1 << 11) /* system clock enable */
-#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
-#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
-#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
-
-#define PMC_CTRL 0x0
-#define PMC_CTRL_INTR_LOW (1 << 17)
-#define PMC_PWRGATE_TOGGLE 0x30
-#define PMC_PWRGATE_TOGGLE_START (1 << 8)
-#define PMC_REMOVE_CLAMPING 0x34
-#define PMC_PWRGATE_STATUS 0x38
-
-#define PMC_SCRATCH0 0x50
-#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
-#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
-#define PMC_SCRATCH0_MODE_RCM (1 << 1)
-#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
- PMC_SCRATCH0_MODE_BOOTLOADER | \
- PMC_SCRATCH0_MODE_RCM)
-
-#define PMC_CPUPWRGOOD_TIMER 0xc8
-#define PMC_CPUPWROFF_TIMER 0xcc
-
-static u8 tegra_cpu_domains[] = {
- 0xFF, /* not available for CPU0 */
- TEGRA_POWERGATE_CPU1,
- TEGRA_POWERGATE_CPU2,
- TEGRA_POWERGATE_CPU3,
-};
-static DEFINE_SPINLOCK(tegra_powergate_lock);
-
-static void __iomem *tegra_pmc_base;
-static bool tegra_pmc_invert_interrupt;
-static struct clk *tegra_pclk;
-
-struct pmc_pm_data {
- u32 cpu_good_time; /* CPU power good time in uS */
- u32 cpu_off_time; /* CPU power off time in uS */
- u32 core_osc_time; /* Core power good osc time in uS */
- u32 core_pmu_time; /* Core power good pmu time in uS */
- u32 core_off_time; /* Core power off time in uS */
- bool corereq_high; /* Core power request active-high */
- bool sysclkreq_high; /* System clock request active-high */
- bool combined_req; /* Combined pwr req for CPU & Core */
- bool cpu_pwr_good_en; /* CPU power good signal is enabled */
- u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */
- u32 lp0_vec_size; /* The size of LP0 warm boot code */
- enum tegra_suspend_mode suspend_mode;
-};
-static struct pmc_pm_data pmc_pm_data;
-
-static inline u32 tegra_pmc_readl(u32 reg)
-{
- return readl(tegra_pmc_base + reg);
-}
-
-static inline void tegra_pmc_writel(u32 val, u32 reg)
-{
- writel(val, tegra_pmc_base + reg);
-}
-
-static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
-{
- if (cpuid <= 0 || cpuid >= num_possible_cpus())
- return -EINVAL;
- return tegra_cpu_domains[cpuid];
-}
-
-static bool tegra_pmc_powergate_is_powered(int id)
-{
- return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
-}
-
-static int tegra_pmc_powergate_set(int id, bool new_state)
-{
- bool old_state;
- unsigned long flags;
-
- spin_lock_irqsave(&tegra_powergate_lock, flags);
-
- old_state = tegra_pmc_powergate_is_powered(id);
- WARN_ON(old_state == new_state);
-
- tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
-
- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-
- return 0;
-}
-
-static int tegra_pmc_powergate_remove_clamping(int id)
-{
- u32 mask;
-
- /*
- * Tegra has a bug where PCIE and VDE clamping masks are
- * swapped relatively to the partition ids.
- */
- if (id == TEGRA_POWERGATE_VDEC)
- mask = (1 << TEGRA_POWERGATE_PCIE);
- else if (id == TEGRA_POWERGATE_PCIE)
- mask = (1 << TEGRA_POWERGATE_VDEC);
- else
- mask = (1 << id);
-
- tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
-
- return 0;
-}
-
-bool tegra_pmc_cpu_is_powered(int cpuid)
-{
- int id;
-
- id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
- if (id < 0)
- return false;
- return tegra_pmc_powergate_is_powered(id);
-}
-
-int tegra_pmc_cpu_power_on(int cpuid)
-{
- int id;
-
- id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
- if (id < 0)
- return id;
- return tegra_pmc_powergate_set(id, true);
-}
-
-int tegra_pmc_cpu_remove_clamping(int cpuid)
-{
- int id;
-
- id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
- if (id < 0)
- return id;
- return tegra_pmc_powergate_remove_clamping(id);
-}
-
-void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
-{
- u32 val;
-
- val = tegra_pmc_readl(PMC_SCRATCH0);
- val &= ~PMC_SCRATCH0_MODE_MASK;
-
- if (cmd) {
- if (strcmp(cmd, "recovery") == 0)
- val |= PMC_SCRATCH0_MODE_RECOVERY;
-
- if (strcmp(cmd, "bootloader") == 0)
- val |= PMC_SCRATCH0_MODE_BOOTLOADER;
-
- if (strcmp(cmd, "forced-recovery") == 0)
- val |= PMC_SCRATCH0_MODE_RCM;
- }
-
- tegra_pmc_writel(val, PMC_SCRATCH0);
-
- val = tegra_pmc_readl(0);
- val |= 0x10;
- tegra_pmc_writel(val, 0);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
-{
- unsigned long long ticks;
- unsigned long long pclk;
- static unsigned long tegra_last_pclk;
-
- if (WARN_ON_ONCE(rate <= 0))
- pclk = 100000000;
- else
- pclk = rate;
-
- if ((rate != tegra_last_pclk)) {
- ticks = (us_on * pclk) + 999999ull;
- do_div(ticks, 1000000);
- tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
-
- ticks = (us_off * pclk) + 999999ull;
- do_div(ticks, 1000000);
- tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
- wmb();
- }
- tegra_last_pclk = pclk;
-}
-
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
-{
- return pmc_pm_data.suspend_mode;
-}
-
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
-{
- if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
- return;
-
- pmc_pm_data.suspend_mode = mode;
-}
-
-void tegra_pmc_suspend(void)
-{
- tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
-}
-
-void tegra_pmc_resume(void)
-{
- tegra_pmc_writel(0x0, PMC_SCRATCH41);
-}
-
-void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
-{
- u32 reg, csr_reg;
- unsigned long rate = 0;
-
- reg = tegra_pmc_readl(PMC_CTRL);
- reg |= TEGRA_POWER_CPU_PWRREQ_OE;
- reg &= ~TEGRA_POWER_EFFECT_LP0;
-
- switch (tegra_chip_id) {
- case TEGRA20:
- case TEGRA30:
- break;
- default:
- /* Turn off CRAIL */
- csr_reg = flowctrl_read_cpu_csr(0);
- csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
- csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
- flowctrl_write_cpu_csr(0, csr_reg);
- break;
- }
-
- switch (mode) {
- case TEGRA_SUSPEND_LP1:
- rate = 32768;
- break;
- case TEGRA_SUSPEND_LP2:
- rate = clk_get_rate(tegra_pclk);
- break;
- default:
- break;
- }
-
- set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
- rate);
-
- tegra_pmc_writel(reg, PMC_CTRL);
-}
-
-void tegra_pmc_suspend_init(void)
-{
- u32 reg;
-
- /* Always enable CPU power request */
- reg = tegra_pmc_readl(PMC_CTRL);
- reg |= TEGRA_POWER_CPU_PWRREQ_OE;
- tegra_pmc_writel(reg, PMC_CTRL);
-
- reg = tegra_pmc_readl(PMC_CTRL);
-
- if (!pmc_pm_data.sysclkreq_high)
- reg |= TEGRA_POWER_SYSCLK_POLARITY;
- else
- reg &= ~TEGRA_POWER_SYSCLK_POLARITY;
-
- /* configure the output polarity while the request is tristated */
- tegra_pmc_writel(reg, PMC_CTRL);
-
- /* now enable the request */
- reg |= TEGRA_POWER_SYSCLK_OE;
- tegra_pmc_writel(reg, PMC_CTRL);
-}
-#endif
-
-static const struct of_device_id matches[] __initconst = {
- { .compatible = "nvidia,tegra124-pmc" },
- { .compatible = "nvidia,tegra114-pmc" },
- { .compatible = "nvidia,tegra30-pmc" },
- { .compatible = "nvidia,tegra20-pmc" },
- { }
-};
-
-void __init tegra_pmc_init_irq(void)
-{
- struct device_node *np;
- u32 val;
-
- np = of_find_matching_node(NULL, matches);
- BUG_ON(!np);
-
- tegra_pmc_base = of_iomap(np, 0);
-
- tegra_pmc_invert_interrupt = of_property_read_bool(np,
- "nvidia,invert-interrupt");
-
- val = tegra_pmc_readl(PMC_CTRL);
- if (tegra_pmc_invert_interrupt)
- val |= PMC_CTRL_INTR_LOW;
- else
- val &= ~PMC_CTRL_INTR_LOW;
- tegra_pmc_writel(val, PMC_CTRL);
-}
-
-void __init tegra_pmc_init(void)
-{
- struct device_node *np;
- u32 prop;
- enum tegra_suspend_mode suspend_mode;
- u32 core_good_time[2] = {0, 0};
- u32 lp0_vec[2] = {0, 0};
-
- np = of_find_matching_node(NULL, matches);
- BUG_ON(!np);
-
- tegra_pclk = of_clk_get_by_name(np, "pclk");
- WARN_ON(IS_ERR(tegra_pclk));
-
- /* Grabbing the power management configurations */
- if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
- suspend_mode = TEGRA_SUSPEND_NONE;
- } else {
- switch (prop) {
- case 0:
- suspend_mode = TEGRA_SUSPEND_LP0;
- break;
- case 1:
- suspend_mode = TEGRA_SUSPEND_LP1;
- break;
- case 2:
- suspend_mode = TEGRA_SUSPEND_LP2;
- break;
- default:
- suspend_mode = TEGRA_SUSPEND_NONE;
- break;
- }
- }
- suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
-
- if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
- suspend_mode = TEGRA_SUSPEND_NONE;
- pmc_pm_data.cpu_good_time = prop;
-
- if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
- suspend_mode = TEGRA_SUSPEND_NONE;
- pmc_pm_data.cpu_off_time = prop;
-
- if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
- core_good_time, ARRAY_SIZE(core_good_time)))
- suspend_mode = TEGRA_SUSPEND_NONE;
- pmc_pm_data.core_osc_time = core_good_time[0];
- pmc_pm_data.core_pmu_time = core_good_time[1];
-
- if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
- &prop))
- suspend_mode = TEGRA_SUSPEND_NONE;
- pmc_pm_data.core_off_time = prop;
-
- pmc_pm_data.corereq_high = of_property_read_bool(np,
- "nvidia,core-power-req-active-high");
-
- pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
- "nvidia,sys-clock-req-active-high");
-
- pmc_pm_data.combined_req = of_property_read_bool(np,
- "nvidia,combined-power-req");
-
- pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
- "nvidia,cpu-pwr-good-en");
-
- if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
- ARRAY_SIZE(lp0_vec)))
- if (suspend_mode == TEGRA_SUSPEND_LP0)
- suspend_mode = TEGRA_SUSPEND_LP1;
-
- pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
- pmc_pm_data.lp0_vec_size = lp0_vec[1];
-
- pmc_pm_data.suspend_mode = suspend_mode;
-}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
deleted file mode 100644
index 59e19c344298..000000000000
--- a/arch/arm/mach-tegra/pmc.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __MACH_TEGRA_PMC_H
-#define __MACH_TEGRA_PMC_H
-
-#include <linux/reboot.h>
-
-enum tegra_suspend_mode {
- TEGRA_SUSPEND_NONE = 0,
- TEGRA_SUSPEND_LP2, /* CPU voltage off */
- TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
- TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
- TEGRA_MAX_SUSPEND_MODE,
-};
-
-#ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
-void tegra_pmc_suspend(void);
-void tegra_pmc_resume(void);
-void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
-void tegra_pmc_suspend_init(void);
-#endif
-
-bool tegra_pmc_cpu_is_powered(int cpuid);
-int tegra_pmc_cpu_power_on(int cpuid);
-int tegra_pmc_cpu_remove_clamping(int cpuid);
-
-void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
-
-void tegra_pmc_init_irq(void);
-void tegra_pmc_init(void);
-
-#endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
deleted file mode 100644
index 4cefc5cd6bed..000000000000
--- a/arch/arm/mach-tegra/powergate.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * drivers/powergate/tegra-powergate.c
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- * Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/reset.h>
-#include <linux/seq_file.h>
-#include <linux/spinlock.h>
-#include <linux/clk/tegra.h>
-#include <linux/tegra-powergate.h>
-
-#include "fuse.h"
-#include "iomap.h"
-
-#define DPD_SAMPLE 0x020
-#define DPD_SAMPLE_ENABLE (1 << 0)
-#define DPD_SAMPLE_DISABLE (0 << 0)
-
-#define PWRGATE_TOGGLE 0x30
-#define PWRGATE_TOGGLE_START (1 << 8)
-
-#define REMOVE_CLAMPING 0x34
-
-#define PWRGATE_STATUS 0x38
-
-#define IO_DPD_REQ 0x1b8
-#define IO_DPD_REQ_CODE_IDLE (0 << 30)
-#define IO_DPD_REQ_CODE_OFF (1 << 30)
-#define IO_DPD_REQ_CODE_ON (2 << 30)
-#define IO_DPD_REQ_CODE_MASK (3 << 30)
-
-#define IO_DPD_STATUS 0x1bc
-#define IO_DPD2_REQ 0x1c0
-#define IO_DPD2_STATUS 0x1c4
-#define SEL_DPD_TIM 0x1c8
-
-#define GPU_RG_CNTRL 0x2d4
-
-static int tegra_num_powerdomains;
-static int tegra_num_cpu_domains;
-static const u8 *tegra_cpu_domains;
-
-static const u8 tegra30_cpu_domains[] = {
- TEGRA_POWERGATE_CPU,
- TEGRA_POWERGATE_CPU1,
- TEGRA_POWERGATE_CPU2,
- TEGRA_POWERGATE_CPU3,
-};
-
-static const u8 tegra114_cpu_domains[] = {
- TEGRA_POWERGATE_CPU0,
- TEGRA_POWERGATE_CPU1,
- TEGRA_POWERGATE_CPU2,
- TEGRA_POWERGATE_CPU3,
-};
-
-static const u8 tegra124_cpu_domains[] = {
- TEGRA_POWERGATE_CPU0,
- TEGRA_POWERGATE_CPU1,
- TEGRA_POWERGATE_CPU2,
- TEGRA_POWERGATE_CPU3,
-};
-
-static DEFINE_SPINLOCK(tegra_powergate_lock);
-
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-
-static u32 pmc_read(unsigned long reg)
-{
- return readl(pmc + reg);
-}
-
-static void pmc_write(u32 val, unsigned long reg)
-{
- writel(val, pmc + reg);
-}
-
-static int tegra_powergate_set(int id, bool new_state)
-{
- bool status;
- unsigned long flags;
-
- spin_lock_irqsave(&tegra_powergate_lock, flags);
-
- status = pmc_read(PWRGATE_STATUS) & (1 << id);
-
- if (status == new_state) {
- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
- return 0;
- }
-
- pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
-
- spin_unlock_irqrestore(&tegra_powergate_lock, flags);
-
- return 0;
-}
-
-int tegra_powergate_power_on(int id)
-{
- if (id < 0 || id >= tegra_num_powerdomains)
- return -EINVAL;
-
- return tegra_powergate_set(id, true);
-}
-
-int tegra_powergate_power_off(int id)
-{
- if (id < 0 || id >= tegra_num_powerdomains)
- return -EINVAL;
-
- return tegra_powergate_set(id, false);
-}
-EXPORT_SYMBOL(tegra_powergate_power_off);
-
-int tegra_powergate_is_powered(int id)
-{
- u32 status;
-
- if (id < 0 || id >= tegra_num_powerdomains)
- return -EINVAL;
-
- status = pmc_read(PWRGATE_STATUS) & (1 << id);
- return !!status;
-}
-
-int tegra_powergate_remove_clamping(int id)
-{
- u32 mask;
-
- if (id < 0 || id >= tegra_num_powerdomains)
- return -EINVAL;
-
- /*
- * The Tegra124 GPU has a separate register (with different semantics)
- * to remove clamps.
- */
- if (tegra_chip_id == TEGRA124) {
- if (id == TEGRA_POWERGATE_3D) {
- pmc_write(0, GPU_RG_CNTRL);
- return 0;
- }
- }
-
- /*
- * Tegra 2 has a bug where PCIE and VDE clamping masks are
- * swapped relatively to the partition ids
- */
- if (id == TEGRA_POWERGATE_VDEC)
- mask = (1 << TEGRA_POWERGATE_PCIE);
- else if (id == TEGRA_POWERGATE_PCIE)
- mask = (1 << TEGRA_POWERGATE_VDEC);
- else
- mask = (1 << id);
-
- pmc_write(mask, REMOVE_CLAMPING);
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_powergate_remove_clamping);
-
-/* Must be called with clk disabled, and returns with clk enabled */
-int tegra_powergate_sequence_power_up(int id, struct clk *clk,
- struct reset_control *rst)
-{
- int ret;
-
- reset_control_assert(rst);
-
- ret = tegra_powergate_power_on(id);
- if (ret)
- goto err_power;
-
- ret = clk_prepare_enable(clk);
- if (ret)
- goto err_clk;
-
- udelay(10);
-
- ret = tegra_powergate_remove_clamping(id);
- if (ret)
- goto err_clamp;
-
- udelay(10);
- reset_control_deassert(rst);
-
- return 0;
-
-err_clamp:
- clk_disable_unprepare(clk);
-err_clk:
- tegra_powergate_power_off(id);
-err_power:
- return ret;
-}
-EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
-
-int tegra_cpu_powergate_id(int cpuid)
-{
- if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
- return tegra_cpu_domains[cpuid];
-
- return -EINVAL;
-}
-
-int __init tegra_powergate_init(void)
-{
- switch (tegra_chip_id) {
- case TEGRA20:
- tegra_num_powerdomains = 7;
- break;
- case TEGRA30:
- tegra_num_powerdomains = 14;
- tegra_num_cpu_domains = 4;
- tegra_cpu_domains = tegra30_cpu_domains;
- break;
- case TEGRA114:
- tegra_num_powerdomains = 23;
- tegra_num_cpu_domains = 4;
- tegra_cpu_domains = tegra114_cpu_domains;
- break;
- case TEGRA124:
- tegra_num_powerdomains = 25;
- tegra_num_cpu_domains = 4;
- tegra_cpu_domains = tegra124_cpu_domains;
- break;
- default:
- /* Unknown Tegra variant. Disable powergating */
- tegra_num_powerdomains = 0;
- break;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static const char * const *powergate_name;
-
-static const char * const powergate_name_t20[] = {
- [TEGRA_POWERGATE_CPU] = "cpu",
- [TEGRA_POWERGATE_3D] = "3d",
- [TEGRA_POWERGATE_VENC] = "venc",
- [TEGRA_POWERGATE_VDEC] = "vdec",
- [TEGRA_POWERGATE_PCIE] = "pcie",
- [TEGRA_POWERGATE_L2] = "l2",
- [TEGRA_POWERGATE_MPE] = "mpe",
-};
-
-static const char * const powergate_name_t30[] = {
- [TEGRA_POWERGATE_CPU] = "cpu0",
- [TEGRA_POWERGATE_3D] = "3d0",
- [TEGRA_POWERGATE_VENC] = "venc",
- [TEGRA_POWERGATE_VDEC] = "vdec",
- [TEGRA_POWERGATE_PCIE] = "pcie",
- [TEGRA_POWERGATE_L2] = "l2",
- [TEGRA_POWERGATE_MPE] = "mpe",
- [TEGRA_POWERGATE_HEG] = "heg",
- [TEGRA_POWERGATE_SATA] = "sata",
- [TEGRA_POWERGATE_CPU1] = "cpu1",
- [TEGRA_POWERGATE_CPU2] = "cpu2",
- [TEGRA_POWERGATE_CPU3] = "cpu3",
- [TEGRA_POWERGATE_CELP] = "celp",
- [TEGRA_POWERGATE_3D1] = "3d1",
-};
-
-static const char * const powergate_name_t114[] = {
- [TEGRA_POWERGATE_CPU] = "crail",
- [TEGRA_POWERGATE_3D] = "3d",
- [TEGRA_POWERGATE_VENC] = "venc",
- [TEGRA_POWERGATE_VDEC] = "vdec",
- [TEGRA_POWERGATE_MPE] = "mpe",
- [TEGRA_POWERGATE_HEG] = "heg",
- [TEGRA_POWERGATE_CPU1] = "cpu1",
- [TEGRA_POWERGATE_CPU2] = "cpu2",
- [TEGRA_POWERGATE_CPU3] = "cpu3",
- [TEGRA_POWERGATE_CELP] = "celp",
- [TEGRA_POWERGATE_CPU0] = "cpu0",
- [TEGRA_POWERGATE_C0NC] = "c0nc",
- [TEGRA_POWERGATE_C1NC] = "c1nc",
- [TEGRA_POWERGATE_DIS] = "dis",
- [TEGRA_POWERGATE_DISB] = "disb",
- [TEGRA_POWERGATE_XUSBA] = "xusba",
- [TEGRA_POWERGATE_XUSBB] = "xusbb",
- [TEGRA_POWERGATE_XUSBC] = "xusbc",
-};
-
-static const char * const powergate_name_t124[] = {
- [TEGRA_POWERGATE_CPU] = "crail",
- [TEGRA_POWERGATE_3D] = "3d",
- [TEGRA_POWERGATE_VENC] = "venc",
- [TEGRA_POWERGATE_PCIE] = "pcie",
- [TEGRA_POWERGATE_VDEC] = "vdec",
- [TEGRA_POWERGATE_L2] = "l2",
- [TEGRA_POWERGATE_MPE] = "mpe",
- [TEGRA_POWERGATE_HEG] = "heg",
- [TEGRA_POWERGATE_SATA] = "sata",
- [TEGRA_POWERGATE_CPU1] = "cpu1",
- [TEGRA_POWERGATE_CPU2] = "cpu2",
- [TEGRA_POWERGATE_CPU3] = "cpu3",
- [TEGRA_POWERGATE_CELP] = "celp",
- [TEGRA_POWERGATE_CPU0] = "cpu0",
- [TEGRA_POWERGATE_C0NC] = "c0nc",
- [TEGRA_POWERGATE_C1NC] = "c1nc",
- [TEGRA_POWERGATE_SOR] = "sor",
- [TEGRA_POWERGATE_DIS] = "dis",
- [TEGRA_POWERGATE_DISB] = "disb",
- [TEGRA_POWERGATE_XUSBA] = "xusba",
- [TEGRA_POWERGATE_XUSBB] = "xusbb",
- [TEGRA_POWERGATE_XUSBC] = "xusbc",
- [TEGRA_POWERGATE_VIC] = "vic",
- [TEGRA_POWERGATE_IRAM] = "iram",
-};
-
-static int powergate_show(struct seq_file *s, void *data)
-{
- int i;
-
- seq_printf(s, " powergate powered\n");
- seq_printf(s, "------------------\n");
-
- for (i = 0; i < tegra_num_powerdomains; i++) {
- if (!powergate_name[i])
- continue;
-
- seq_printf(s, " %9s %7s\n", powergate_name[i],
- tegra_powergate_is_powered(i) ? "yes" : "no");
- }
-
- return 0;
-}
-
-static int powergate_open(struct inode *inode, struct file *file)
-{
- return single_open(file, powergate_show, inode->i_private);
-}
-
-static const struct file_operations powergate_fops = {
- .open = powergate_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-int __init tegra_powergate_debugfs_init(void)
-{
- struct dentry *d;
-
- switch (tegra_chip_id) {
- case TEGRA20:
- powergate_name = powergate_name_t20;
- break;
- case TEGRA30:
- powergate_name = powergate_name_t30;
- break;
- case TEGRA114:
- powergate_name = powergate_name_t114;
- break;
- case TEGRA124:
- powergate_name = powergate_name_t124;
- break;
- }
-
- if (powergate_name) {
- d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
- &powergate_fops);
- if (!d)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-#endif
-
-static int tegra_io_rail_prepare(int id, unsigned long *request,
- unsigned long *status, unsigned int *bit)
-{
- unsigned long rate, value;
- struct clk *clk;
-
- *bit = id % 32;
-
- /*
- * There are two sets of 30 bits to select IO rails, but bits 30 and
- * 31 are control bits rather than IO rail selection bits.
- */
- if (id > 63 || *bit == 30 || *bit == 31)
- return -EINVAL;
-
- if (id < 32) {
- *status = IO_DPD_STATUS;
- *request = IO_DPD_REQ;
- } else {
- *status = IO_DPD2_STATUS;
- *request = IO_DPD2_REQ;
- }
-
- clk = clk_get_sys(NULL, "pclk");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- rate = clk_get_rate(clk);
- clk_put(clk);
-
- pmc_write(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-
- /* must be at least 200 ns, in APB (PCLK) clock cycles */
- value = DIV_ROUND_UP(1000000000, rate);
- value = DIV_ROUND_UP(200, value);
- pmc_write(value, SEL_DPD_TIM);
-
- return 0;
-}
-
-static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
- unsigned long val, unsigned long timeout)
-{
- unsigned long value;
-
- timeout = jiffies + msecs_to_jiffies(timeout);
-
- while (time_after(timeout, jiffies)) {
- value = pmc_read(offset);
- if ((value & mask) == val)
- return 0;
-
- usleep_range(250, 1000);
- }
-
- return -ETIMEDOUT;
-}
-
-static void tegra_io_rail_unprepare(void)
-{
- pmc_write(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
-}
-
-int tegra_io_rail_power_on(int id)
-{
- unsigned long request, status, value;
- unsigned int bit, mask;
- int err;
-
- err = tegra_io_rail_prepare(id, &request, &status, &bit);
- if (err < 0)
- return err;
-
- mask = 1 << bit;
-
- value = pmc_read(request);
- value |= mask;
- value &= ~IO_DPD_REQ_CODE_MASK;
- value |= IO_DPD_REQ_CODE_OFF;
- pmc_write(value, request);
-
- err = tegra_io_rail_poll(status, mask, 0, 250);
- if (err < 0)
- return err;
-
- tegra_io_rail_unprepare();
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_io_rail_power_on);
-
-int tegra_io_rail_power_off(int id)
-{
- unsigned long request, status, value;
- unsigned int bit, mask;
- int err;
-
- err = tegra_io_rail_prepare(id, &request, &status, &bit);
- if (err < 0)
- return err;
-
- mask = 1 << bit;
-
- value = pmc_read(request);
- value |= mask;
- value &= ~IO_DPD_REQ_CODE_MASK;
- value |= IO_DPD_REQ_CODE_ON;
- pmc_write(value, request);
-
- err = tegra_io_rail_poll(status, mask, mask, 250);
- if (err < 0)
- return err;
-
- tegra_io_rail_unprepare();
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_io_rail_power_off);
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 578d4d1ad648..7b2baab0f0bd 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -14,14 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/linkage.h>
+
+#include <soc/tegra/fuse.h>
-#include <asm/cache.h>
#include <asm/asm-offsets.h>
+#include <asm/cache.h>
#include "flowctrl.h"
-#include "fuse.h"
#include "iomap.h"
#include "reset.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 146fe8e0ae7c..894c5c472184 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -14,20 +14,21 @@
*
*/
+#include <linux/bitops.h>
+#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/io.h>
-#include <linux/cpumask.h>
-#include <linux/bitops.h>
+
+#include <soc/tegra/fuse.h>
#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
#include <asm/firmware.h>
+#include <asm/hardware/cache-l2x0.h>
#include "iomap.h"
#include "irammap.h"
#include "reset.h"
#include "sleep.h"
-#include "fuse.h"
#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
TEGRA_IRAM_RESET_HANDLER_OFFSET)
@@ -53,12 +54,10 @@ static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
* Prevent further modifications to the physical reset vector.
* NOTE: Has no effect on chips prior to Tegra30.
*/
- if (tegra_chip_id != TEGRA20) {
- reg = readl(sb_ctrl);
- reg |= 2;
- writel(reg, sb_ctrl);
- wmb();
- }
+ reg = readl(sb_ctrl);
+ reg |= 2;
+ writel(reg, sb_ctrl);
+ wmb();
}
static void __init tegra_cpu_reset_handler_enable(void)
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index aaaf3abd2688..be4bc5f853f5 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -78,7 +78,7 @@ ENTRY(tegra20_hotplug_shutdown)
/* Put this CPU down */
cpu_id r0
bl tegra20_cpu_shutdown
- mov pc, lr @ should never get here
+ ret lr @ should never get here
ENDPROC(tegra20_hotplug_shutdown)
/*
@@ -96,7 +96,7 @@ ENDPROC(tegra20_hotplug_shutdown)
*/
ENTRY(tegra20_cpu_shutdown)
cmp r0, #0
- moveq pc, lr @ must not be called for CPU 0
+ reteq lr @ must not be called for CPU 0
mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
mov r12, #CPU_RESETTABLE
str r12, [r1]
@@ -117,7 +117,7 @@ ENTRY(tegra20_cpu_shutdown)
cpu_id r3
cmp r3, r0
beq .
- mov pc, lr
+ ret lr
ENDPROC(tegra20_cpu_shutdown)
#endif
@@ -164,7 +164,7 @@ ENTRY(tegra_pen_lock)
cmpeq r12, r0 @ !turn == cpu?
beq 1b @ while !turn == cpu && flag[!cpu] == 1
- mov pc, lr @ locked
+ ret lr @ locked
ENDPROC(tegra_pen_lock)
ENTRY(tegra_pen_unlock)
@@ -176,7 +176,7 @@ ENTRY(tegra_pen_unlock)
addne r2, r3, #PMC_SCRATCH39
mov r12, #0
str r12, [r2]
- mov pc, lr
+ ret lr
ENDPROC(tegra_pen_unlock)
/*
@@ -189,7 +189,7 @@ ENTRY(tegra20_cpu_clear_resettable)
mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
mov r12, #CPU_NOT_RESETTABLE
str r12, [r1]
- mov pc, lr
+ ret lr
ENDPROC(tegra20_cpu_clear_resettable)
/*
@@ -202,7 +202,7 @@ ENTRY(tegra20_cpu_set_resettable_soon)
mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
mov r12, #CPU_RESETTABLE_SOON
str r12, [r1]
- mov pc, lr
+ ret lr
ENDPROC(tegra20_cpu_set_resettable_soon)
/*
@@ -217,7 +217,7 @@ ENTRY(tegra20_cpu_is_resettable_soon)
cmp r12, #CPU_RESETTABLE_SOON
moveq r0, #1
movne r0, #0
- mov pc, lr
+ ret lr
ENDPROC(tegra20_cpu_is_resettable_soon)
/*
@@ -239,7 +239,7 @@ ENTRY(tegra20_sleep_core_finish)
mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
- mov pc, r3
+ ret r3
ENDPROC(tegra20_sleep_core_finish)
/*
@@ -402,7 +402,7 @@ exit_selfrefresh_loop:
mov32 r0, TEGRA_PMC_BASE
ldr r0, [r0, #PMC_SCRATCH41]
- mov pc, r0 @ jump to tegra_resume
+ ret r0 @ jump to tegra_resume
ENDPROC(tegra20_lp1_reset)
/*
@@ -455,7 +455,7 @@ tegra20_switch_cpu_to_clk32k:
mov r0, #0 /* brust policy = 32KHz */
str r0, [r5, #CLK_RESET_SCLK_BURST]
- mov pc, lr
+ ret lr
/*
* tegra20_enter_sleep
@@ -535,7 +535,7 @@ padsave_done:
adr r2, tegra20_sclk_save
str r0, [r2]
dsb
- mov pc, lr
+ ret lr
tegra20_sdram_pad_address:
.word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index b16d4a57fa59..5d8d13aeab93 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -16,14 +16,15 @@
#include <linux/linkage.h>
-#include <asm/assembler.h>
+#include <soc/tegra/fuse.h>
+
#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
#include <asm/cache.h>
+#include "flowctrl.h"
#include "irammap.h"
-#include "fuse.h"
#include "sleep.h"
-#include "flowctrl.h"
#define EMC_CFG 0xc
#define EMC_ADR_CFG 0x10
@@ -142,7 +143,7 @@ ENTRY(tegra30_hotplug_shutdown)
/* Powergate this CPU */
mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
bl tegra30_cpu_shutdown
- mov pc, lr @ should never get here
+ ret lr @ should never get here
ENDPROC(tegra30_hotplug_shutdown)
/*
@@ -161,7 +162,7 @@ ENTRY(tegra30_cpu_shutdown)
bne _no_cpu0_chk @ It's not Tegra30
cmp r3, #0
- moveq pc, lr @ Must never be called for CPU 0
+ reteq lr @ Must never be called for CPU 0
_no_cpu0_chk:
ldr r12, =TEGRA_FLOW_CTRL_VIRT
@@ -266,7 +267,7 @@ ENTRY(tegra30_sleep_core_finish)
mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
- mov pc, r3
+ ret r3
ENDPROC(tegra30_sleep_core_finish)
/*
@@ -285,7 +286,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish)
mov r0, #0 @ power mode flags (!hotplug)
bl tegra30_cpu_shutdown
mov r0, #1 @ never return here
- mov pc, r7
+ ret r7
ENDPROC(tegra30_sleep_cpu_secondary_finish)
/*
@@ -529,7 +530,7 @@ __no_dual_emc_chanl:
mov32 r0, TEGRA_PMC_BASE
ldr r0, [r0, #PMC_SCRATCH41]
- mov pc, r0 @ jump to tegra_resume
+ ret r0 @ jump to tegra_resume
ENDPROC(tegra30_lp1_reset)
.align L1_CACHE_SHIFT
@@ -659,7 +660,7 @@ _no_pll_in_iddq:
mov r0, #0 /* brust policy = 32KHz */
str r0, [r5, #CLK_RESET_SCLK_BURST]
- mov pc, lr
+ ret lr
/*
* tegra30_enter_sleep
@@ -819,7 +820,7 @@ pmc_io_dpd_skip:
dsb
- mov pc, lr
+ ret lr
.ltorg
/* dummy symbol for end of IRAM */
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 8d06213fbc47..f024a5109e8e 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -87,7 +87,7 @@ ENTRY(tegra_init_l2_for_a15)
mcrne p15, 0x1, r0, c9, c0, 2
_exit_init_l2_a15:
- mov pc, lr
+ ret lr
ENDPROC(tegra_init_l2_for_a15)
/*
@@ -111,7 +111,7 @@ ENTRY(tegra_sleep_cpu_finish)
add r3, r3, r0
mov r0, r1
- mov pc, r3
+ ret r3
ENDPROC(tegra_sleep_cpu_finish)
/*
@@ -139,7 +139,7 @@ ENTRY(tegra_shut_off_mmu)
moveq r3, #0
streq r3, [r2, #L2X0_CTRL]
#endif
- mov pc, r0
+ ret r0
ENDPROC(tegra_shut_off_mmu)
.popsection
@@ -156,6 +156,6 @@ ENTRY(tegra_switch_cpu_to_pllp)
str r0, [r5, #CLK_RESET_CCLK_BURST]
mov r0, #0
str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
- mov pc, lr
+ ret lr
ENDPROC(tegra_switch_cpu_to_pllp)
#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 339fe42cd6fb..92d46ec1361a 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -130,9 +130,6 @@ void tegra_disable_clean_inv_dcache(u32 flag);
#ifdef CONFIG_HOTPLUG_CPU
void tegra20_hotplug_shutdown(void);
void tegra30_hotplug_shutdown(void);
-void tegra_hotplug_init(void);
-#else
-static inline void tegra_hotplug_init(void) {}
#endif
void tegra20_cpu_shutdown(int cpu);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 15ac9fcc96b1..5ef5173dec83 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -16,40 +16,40 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
#include <linux/clk.h>
+#include <linux/clk/tegra.h>
#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
#include <linux/irqdomain.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pda_power.h>
-#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <linux/clk/tegra.h>
-#include <linux/irqchip.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
#include <asm/hardware/cache-l2x0.h>
-#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/trusted_foundations.h>
-#include "apbio.h"
#include "board.h"
#include "common.h"
#include "cpuidle.h"
-#include "fuse.h"
#include "iomap.h"
#include "irq.h"
-#include "pmc.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
@@ -73,16 +73,11 @@ u32 tegra_uart_config[3] = {
static void __init tegra_init_early(void)
{
of_register_trusted_foundations();
- tegra_apb_io_init();
- tegra_init_fuse();
tegra_cpu_reset_handler_init();
- tegra_powergate_init();
- tegra_hotplug_init();
}
static void __init tegra_dt_init_irq(void)
{
- tegra_pmc_init_irq();
tegra_init_irq();
irqchip_init();
tegra_legacy_irq_syscore_init();
@@ -94,8 +89,6 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
- tegra_pmc_init();
-
tegra_clocks_apply_init_table();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -103,8 +96,9 @@ static void __init tegra_dt_init(void)
goto out;
soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
- soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
- soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
+ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d",
+ tegra_sku_info.revision);
+ soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
@@ -144,7 +138,6 @@ static void __init tegra_dt_init_late(void)
tegra_init_suspend();
tegra_cpuidle_init();
- tegra_powergate_debugfs_init();
for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
if (of_machine_is_compatible(board_init_funcs[i].machine)) {
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index a4e139aa2441..32d744e91ec2 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -796,7 +796,7 @@ static struct ab8500_regulator_reg_init ab8505_reg_init[] = {
INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX6, 0x00, 0x00),
};
-struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
+static struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
/* supplies to the display/camera */
[AB8505_LDO_AUX1] = {
.constraints = {
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 842ebedbdd1c..e97ee556f92f 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -7,17 +7,15 @@
#include <linux/io.h>
#include <linux/of.h>
-#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include "db8500-regs.h"
#include "id.h"
-static void __iomem *l2x0_base;
-
static int __init ux500_l2x0_unlock(void)
{
int i;
+ void __iomem *l2x0_base = __io_address(U8500_L2CC_BASE);
/*
* Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions
@@ -45,23 +43,15 @@ static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)
static int __init ux500_l2x0_init(void)
{
- if (cpu_is_u8500_family() || cpu_is_ux540_family())
- l2x0_base = __io_address(U8500_L2CC_BASE);
- else
- /* Non-Ux500 platform */
+ /* Multiplatform guard */
+ if (!((cpu_is_u8500_family() || cpu_is_ux540_family())))
return -ENODEV;
/* Unlock before init */
ux500_l2x0_unlock();
-
outer_cache.write_sec = ux500_l2c310_write_sec;
-
- if (of_have_populated_dt())
- l2x0_of_init(0, ~0);
- else
- l2x0_init(l2x0_base, 0, ~0);
+ l2x0_of_init(0, ~0);
return 0;
}
-
early_initcall(ux500_l2x0_init);
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index fa308f07fae5..6f63954c8bde 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -33,11 +33,11 @@
#include "db8500-regs.h"
#include "id.h"
-struct ab8500_platform_data ab8500_platdata = {
+static struct ab8500_platform_data ab8500_platdata = {
.regulator = &ab8500_regulator_plat_data,
};
-struct prcmu_pdata db8500_prcmu_pdata = {
+static struct prcmu_pdata db8500_prcmu_pdata = {
.ab_platdata = &ab8500_platdata,
.version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
.legacy_offset = DB8500_PRCMU_LEGACY_OFFSET,
@@ -82,7 +82,7 @@ static struct map_desc u9540_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K),
};
-void __init u8500_map_io(void)
+static void __init u8500_map_io(void)
{
/*
* Map the UARTs early so that the DEBUG_LL stuff continues to work.
@@ -119,7 +119,7 @@ static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
return ret;
}
-struct arm_pmu_platdata db8500_pmu_platdata = {
+static struct arm_pmu_platdata db8500_pmu_platdata = {
.handle_irq = db8500_pmu_handler,
};
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index db16b5a04ad5..dbb2970ee7da 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -125,7 +125,7 @@ static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
soc_dev_attr->revision = ux500_get_revision();
}
-struct device_attribute ux500_soc_attr =
+static const struct device_attribute ux500_soc_attr =
__ATTR(process, S_IRUGO, ux500_get_process, NULL);
struct device * __init ux500_soc_device_init(const char *soc_id)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 87efda0aa348..ff28d8ad1ed7 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -16,7 +16,7 @@
#include "db8500-regs.h"
#include "id.h"
-const static struct of_device_id prcmu_timer_of_match[] __initconst = {
+static const struct of_device_id prcmu_timer_of_match[] __initconst = {
{ .compatible = "stericsson,db8500-prcmu-timer-4", },
{ },
};
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index be83ba25f81b..08fb8c89f414 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -28,6 +28,7 @@
#include <linux/of_platform.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/amba/pl061.h>
#include <linux/amba/mmci.h>
#include <linux/amba/pl022.h>
@@ -53,7 +54,6 @@
#include <mach/platform.h>
#include <asm/hardware/timer-sp.h>
-#include <plat/clcd.h>
#include <plat/sched_clock.h>
#include "core.h"
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
index 3621b000a0f6..9f9bc61ca64b 100644
--- a/arch/arm/mach-versatile/versatile_dt.c
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -44,7 +44,6 @@ static const char *versatile_dt_match[] __initconst = {
DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
.map_io = versatile_map_io,
.init_early = versatile_init_early,
- .init_irq = versatile_init_irq,
.init_machine = versatile_dt_init,
.dt_compat = versatile_dt_match,
.restart = versatile_restart,
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index d8b9330f896a..b2cfba16c4e8 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -13,7 +13,6 @@ menuconfig ARCH_VEXPRESS
select ICST
select NO_IOPORT_MAP
select PLAT_VERSATILE
- select PLAT_VERSATILE_CLCD
select POWER_RESET
select POWER_RESET_VEXPRESS
select POWER_SUPPLY
@@ -64,7 +63,6 @@ config ARCH_VEXPRESS_DCSCB
config ARCH_VEXPRESS_SPC
bool "Versatile Express Serial Power Controller (SPC)"
- select ARCH_HAS_OPP
select PM_OPP
help
The TC2 (A15x2 A7x3) versatile express core tile integrates a logic
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 86150d7a2e7d..27bea049380a 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -8,6 +8,7 @@
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
+#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/clkdev.h>
#include <linux/vexpress.h>
#include <linux/irqchip/arm-gic.h>
@@ -29,8 +30,6 @@
#include <mach/motherboard.h>
#include <mach/irqs.h>
-#include <plat/clcd.h>
-
static struct map_desc ct_ca9x4_io_desc[] __initdata = {
{
.virtual = V2T_PERIPH,
diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c
index b743a0ae02ce..2fb78b4648cb 100644
--- a/arch/arm/mach-vexpress/tc2_pm.c
+++ b/arch/arm/mach-vexpress/tc2_pm.c
@@ -152,7 +152,7 @@ static void tc2_pm_down(u64 residency)
if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
arch_spin_unlock(&tc2_pm_lock);
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A15) {
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
/*
* On the Cortex-A15 we need to disable
* L2 prefetching before flushing the cache.
@@ -323,6 +323,21 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
" b cci_enable_port_for_self ");
}
+static void __init tc2_cache_off(void)
+{
+ pr_info("TC2: disabling cache during MCPM loopback test\n");
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+ /* disable L2 prefetching on the Cortex-A15 */
+ asm volatile(
+ "mcr p15, 1, %0, c15, c0, 3 \n\t"
+ "isb \n\t"
+ "dsb "
+ : : "r" (0x400) );
+ }
+ v7_exit_coherency_flush(all);
+ cci_disable_port_by_cpu(read_cpuid_mpidr());
+}
+
static int __init tc2_pm_init(void)
{
int ret, irq;
@@ -370,6 +385,8 @@ static int __init tc2_pm_init(void)
ret = mcpm_platform_register(&tc2_pm_power_ops);
if (!ret) {
mcpm_sync_init(tc2_pm_power_up_setup);
+ /* test if we can (re)enable the CCI on our own */
+ BUG_ON(mcpm_loopback(tc2_cache_off) != 0);
pr_info("TC2 power management initialized\n");
}
return ret;
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 4a73464cb11b..2da7be31e7e2 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -44,7 +44,7 @@
static void __iomem *pmc_base;
-void vt8500_restart(enum reboot_mode mode, const char *cmd)
+static void vt8500_restart(enum reboot_mode mode, const char *cmd)
{
if (pmc_base)
writel(1, pmc_base + VT8500_PMSR_REG);
@@ -60,7 +60,7 @@ static struct map_desc vt8500_io_desc[] __initdata = {
},
};
-void __init vt8500_map_io(void)
+static void __init vt8500_map_io(void)
{
iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
}
@@ -72,7 +72,7 @@ static void vt8500_power_off(void)
asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
}
-void __init vt8500_init(void)
+static void __init vt8500_init(void)
{
struct device_node *np;
#if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505)
diff --git a/arch/arm/mach-w90x900/cpu.c b/arch/arm/mach-w90x900/cpu.c
index b1eabaad50a5..213230ee57d1 100644
--- a/arch/arm/mach-w90x900/cpu.c
+++ b/arch/arm/mach-w90x900/cpu.c
@@ -178,7 +178,8 @@ static int __init nuc900_set_cpufreq(char *str)
if (!*str)
return 0;
- strict_strtoul(str, 0, &cpufreq);
+ if (kstrtoul(str, 0, &cpufreq))
+ return 0;
nuc900_clock_source(NULL, "ext");
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index 0c164f81e72d..aaa5162c1509 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -1,6 +1,5 @@
config ARCH_ZYNQ
bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
- select ARCH_HAS_OPP
select ARCH_SUPPORTS_BIG_ENDIAN
select ARM_AMBA
select ARM_GIC
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c348eaee7ee2..ae69809a9e47 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -669,7 +669,7 @@ config ARM_VIRT_EXT
details.
config SWP_EMULATE
- bool "Emulate SWP/SWPB instructions"
+ bool "Emulate SWP/SWPB instructions" if !SMP
depends on CPU_V7
default y if SMP
select HAVE_PROC_CPU if PROC_FS
@@ -854,7 +854,7 @@ config OUTER_CACHE_SYNC
config CACHE_FEROCEON_L2
bool "Enable the Feroceon L2 cache controller"
- depends on ARCH_KIRKWOOD || ARCH_MV78XX0 || ARCH_MVEBU
+ depends on ARCH_MV78XX0 || ARCH_MVEBU
default y
select OUTER_CACHE
help
@@ -907,8 +907,8 @@ config PL310_ERRATA_588369
They are architecturally defined to behave as the execution of a
clean operation followed immediately by an invalidate operation,
both performing to the same memory location. This functionality
- is not correctly implemented in PL310 as clean lines are not
- invalidated as a result of these operations.
+ is not correctly implemented in PL310 prior to r2p0 (fixed in r2p0)
+ as clean lines are not invalidated as a result of these operations.
config PL310_ERRATA_727915
bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
@@ -918,7 +918,8 @@ config PL310_ERRATA_727915
PL310 can handle normal accesses while it is in progress. Under very
rare circumstances, due to this erratum, write data can be lost when
PL310 treats a cacheable write transaction during a Clean &
- Invalidate by Way operation.
+ Invalidate by Way operation. Revisions prior to r3p1 are affected by
+ this errata (fixed in r3p1).
config PL310_ERRATA_753970
bool "PL310 errata: cache sync operation may be faulty"
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index b8cb1a2688a0..0c1ab49e5f7b 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -76,6 +76,7 @@
static unsigned long ai_user;
static unsigned long ai_sys;
+static void *ai_sys_last_pc;
static unsigned long ai_skipped;
static unsigned long ai_half;
static unsigned long ai_word;
@@ -130,7 +131,7 @@ static const char *usermode_action[] = {
static int alignment_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "User:\t\t%lu\n", ai_user);
- seq_printf(m, "System:\t\t%lu\n", ai_sys);
+ seq_printf(m, "System:\t\t%lu (%pF)\n", ai_sys, ai_sys_last_pc);
seq_printf(m, "Skipped:\t%lu\n", ai_skipped);
seq_printf(m, "Half:\t\t%lu\n", ai_half);
seq_printf(m, "Word:\t\t%lu\n", ai_word);
@@ -794,6 +795,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
goto user;
ai_sys += 1;
+ ai_sys_last_pc = (void *)instruction_pointer(regs);
fixup:
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index e505befe51b5..2f0c58836ae7 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -15,6 +15,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/memory.h>
#include <asm/page.h>
@@ -45,7 +46,7 @@
ENTRY(fa_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(fa_flush_icache_all)
/*
@@ -71,7 +72,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer
mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -99,7 +100,7 @@ ENTRY(fa_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -135,7 +136,7 @@ ENTRY(fa_coherent_user_range)
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -155,7 +156,7 @@ ENTRY(fa_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -181,7 +182,7 @@ fa_dma_inv_range:
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -199,7 +200,7 @@ fa_dma_clean_range:
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start,end)
@@ -214,7 +215,7 @@ ENTRY(fa_dma_flush_range)
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -237,7 +238,7 @@ ENDPROC(fa_dma_map_area)
* - dir - DMA direction
*/
ENTRY(fa_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(fa_dma_unmap_area)
.globl fa_flush_kern_cache_louis
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 7c3fb41a462e..5f2c988a06ac 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -665,7 +665,7 @@ static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, v
static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
{
unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK;
- bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
+ bool cortex_a9 = read_cpuid_part() == ARM_CPU_PART_CORTEX_A9;
if (rev >= L310_CACHE_ID_RTL_R2P0) {
if (cortex_a9) {
diff --git a/arch/arm/mm/cache-nop.S b/arch/arm/mm/cache-nop.S
index 8e12ddca0031..f1cc9861031f 100644
--- a/arch/arm/mm/cache-nop.S
+++ b/arch/arm/mm/cache-nop.S
@@ -5,11 +5,12 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include "proc-macros.S"
ENTRY(nop_flush_icache_all)
- mov pc, lr
+ ret lr
ENDPROC(nop_flush_icache_all)
.globl nop_flush_kern_cache_all
@@ -29,7 +30,7 @@ ENDPROC(nop_flush_icache_all)
ENTRY(nop_coherent_user_range)
mov r0, 0
- mov pc, lr
+ ret lr
ENDPROC(nop_coherent_user_range)
.globl nop_flush_kern_dcache_area
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index a7ba68f59f0c..91e3adf155cb 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -9,6 +9,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/page.h>
#include "proc-macros.S"
@@ -18,7 +19,7 @@
* Unconditionally clean and invalidate the entire icache.
*/
ENTRY(v4_flush_icache_all)
- mov pc, lr
+ ret lr
ENDPROC(v4_flush_icache_all)
/*
@@ -40,7 +41,7 @@ ENTRY(v4_flush_kern_cache_all)
#ifdef CONFIG_CPU_CP15
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 @ flush ID cache
- mov pc, lr
+ ret lr
#else
/* FALLTHROUGH */
#endif
@@ -59,7 +60,7 @@ ENTRY(v4_flush_user_cache_range)
#ifdef CONFIG_CPU_CP15
mov ip, #0
mcr p15, 0, ip, c7, c7, 0 @ flush ID cache
- mov pc, lr
+ ret lr
#else
/* FALLTHROUGH */
#endif
@@ -89,7 +90,7 @@ ENTRY(v4_coherent_kern_range)
*/
ENTRY(v4_coherent_user_range)
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -116,7 +117,7 @@ ENTRY(v4_dma_flush_range)
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 @ flush ID cache
#endif
- mov pc, lr
+ ret lr
/*
* dma_unmap_area(start, size, dir)
@@ -136,7 +137,7 @@ ENTRY(v4_dma_unmap_area)
* - dir - DMA direction
*/
ENTRY(v4_dma_map_area)
- mov pc, lr
+ ret lr
ENDPROC(v4_dma_unmap_area)
ENDPROC(v4_dma_map_area)
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index cd4945321407..2522f8c8fbb1 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -9,6 +9,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/memory.h>
#include <asm/page.h>
#include "proc-macros.S"
@@ -58,7 +59,7 @@ flush_base:
ENTRY(v4wb_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(v4wb_flush_icache_all)
/*
@@ -94,7 +95,7 @@ __flush_whole_cache:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -122,7 +123,7 @@ ENTRY(v4wb_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -170,7 +171,7 @@ ENTRY(v4wb_coherent_user_range)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
@@ -195,7 +196,7 @@ v4wb_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -212,7 +213,7 @@ v4wb_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -248,7 +249,7 @@ ENDPROC(v4wb_dma_map_area)
* - dir - DMA direction
*/
ENTRY(v4wb_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(v4wb_dma_unmap_area)
.globl v4wb_flush_kern_cache_louis
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index 11e5e5838bc5..a0982ce49007 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -13,6 +13,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/page.h>
#include "proc-macros.S"
@@ -48,7 +49,7 @@
ENTRY(v4wt_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(v4wt_flush_icache_all)
/*
@@ -71,7 +72,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -94,7 +95,7 @@ ENTRY(v4wt_flush_user_cache_range)
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -126,7 +127,7 @@ ENTRY(v4wt_coherent_user_range)
cmp r0, r1
blo 1b
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -160,7 +161,7 @@ v4wt_dma_inv_range:
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -192,7 +193,7 @@ ENTRY(v4wt_dma_unmap_area)
* - dir - DMA direction
*/
ENTRY(v4wt_dma_map_area)
- mov pc, lr
+ ret lr
ENDPROC(v4wt_dma_unmap_area)
ENDPROC(v4wt_dma_map_area)
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index d8fd4d4bd3d4..24659952c278 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -51,7 +51,7 @@ ENTRY(v6_flush_icache_all)
#else
mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache
#endif
- mov pc, lr
+ ret lr
ENDPROC(v6_flush_icache_all)
/*
@@ -73,7 +73,7 @@ ENTRY(v6_flush_kern_cache_all)
#else
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
#endif
- mov pc, lr
+ ret lr
/*
* v6_flush_cache_all()
@@ -98,7 +98,7 @@ ENTRY(v6_flush_user_cache_all)
* - we have a VIPT cache.
*/
ENTRY(v6_flush_user_cache_range)
- mov pc, lr
+ ret lr
/*
* v6_coherent_kern_range(start,end)
@@ -150,7 +150,7 @@ ENTRY(v6_coherent_user_range)
#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
#endif
- mov pc, lr
+ ret lr
/*
* Fault handling for the cache operation above. If the virtual address in r0
@@ -158,7 +158,7 @@ ENTRY(v6_coherent_user_range)
*/
9001:
mov r0, #-EFAULT
- mov pc, lr
+ ret lr
UNWIND(.fnend )
ENDPROC(v6_coherent_user_range)
ENDPROC(v6_coherent_kern_range)
@@ -188,7 +188,7 @@ ENTRY(v6_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4
#endif
- mov pc, lr
+ ret lr
/*
@@ -239,7 +239,7 @@ v6_dma_inv_range:
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* v6_dma_clean_range(start,end)
@@ -262,7 +262,7 @@ v6_dma_clean_range:
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* v6_dma_flush_range(start,end)
@@ -290,7 +290,7 @@ ENTRY(v6_dma_flush_range)
blo 1b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -323,7 +323,7 @@ ENTRY(v6_dma_unmap_area)
teq r2, #DMA_TO_DEVICE
bne v6_dma_inv_range
#endif
- mov pc, lr
+ ret lr
ENDPROC(v6_dma_unmap_area)
.globl v6_flush_kern_cache_louis
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 615c99e38ba1..b966656d2c2d 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -61,7 +61,7 @@ ENTRY(v7_invalidate_l1)
bgt 1b
dsb st
isb
- mov pc, lr
+ ret lr
ENDPROC(v7_invalidate_l1)
/*
@@ -76,7 +76,7 @@ ENTRY(v7_flush_icache_all)
mov r0, #0
ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable
ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_icache_all)
/*
@@ -94,7 +94,7 @@ ENTRY(v7_flush_dcache_louis)
ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr
#ifdef CONFIG_ARM_ERRATA_643719
ALT_SMP(mrceq p15, 0, r2, c0, c0, 0) @ read main ID register
- ALT_UP(moveq pc, lr) @ LoUU is zero, so nothing to do
+ ALT_UP(reteq lr) @ LoUU is zero, so nothing to do
ldreq r1, =0x410fc090 @ ID of ARM Cortex A9 r0p?
biceq r2, r2, #0x0000000f @ clear minor revision number
teqeq r2, r1 @ test for errata affected core and if so...
@@ -102,7 +102,7 @@ ENTRY(v7_flush_dcache_louis)
#endif
ALT_SMP(mov r3, r3, lsr #20) @ r3 = LoUIS * 2
ALT_UP(mov r3, r3, lsr #26) @ r3 = LoUU * 2
- moveq pc, lr @ return if level == 0
+ reteq lr @ return if level == 0
mov r10, #0 @ r10 (starting level) = 0
b flush_levels @ start flushing cache levels
ENDPROC(v7_flush_dcache_louis)
@@ -168,7 +168,7 @@ finished:
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
dsb st
isb
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_dcache_all)
/*
@@ -191,7 +191,7 @@ ENTRY(v7_flush_kern_cache_all)
ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} )
THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} )
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_kern_cache_all)
/*
@@ -209,7 +209,7 @@ ENTRY(v7_flush_kern_cache_louis)
ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate
ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} )
THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} )
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_kern_cache_louis)
/*
@@ -235,7 +235,7 @@ ENTRY(v7_flush_user_cache_all)
* - we have a VIPT cache.
*/
ENTRY(v7_flush_user_cache_range)
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_user_cache_all)
ENDPROC(v7_flush_user_cache_range)
@@ -296,7 +296,7 @@ ENTRY(v7_coherent_user_range)
ALT_UP(mcr p15, 0, r0, c7, c5, 6) @ invalidate BTB
dsb ishst
isb
- mov pc, lr
+ ret lr
/*
* Fault handling for the cache operation above. If the virtual address in r0
@@ -307,7 +307,7 @@ ENTRY(v7_coherent_user_range)
dsb
#endif
mov r0, #-EFAULT
- mov pc, lr
+ ret lr
UNWIND(.fnend )
ENDPROC(v7_coherent_kern_range)
ENDPROC(v7_coherent_user_range)
@@ -336,7 +336,7 @@ ENTRY(v7_flush_kern_dcache_area)
cmp r0, r1
blo 1b
dsb st
- mov pc, lr
+ ret lr
ENDPROC(v7_flush_kern_dcache_area)
/*
@@ -369,7 +369,7 @@ v7_dma_inv_range:
cmp r0, r1
blo 1b
dsb st
- mov pc, lr
+ ret lr
ENDPROC(v7_dma_inv_range)
/*
@@ -391,7 +391,7 @@ v7_dma_clean_range:
cmp r0, r1
blo 1b
dsb st
- mov pc, lr
+ ret lr
ENDPROC(v7_dma_clean_range)
/*
@@ -413,7 +413,7 @@ ENTRY(v7_dma_flush_range)
cmp r0, r1
blo 1b
dsb st
- mov pc, lr
+ ret lr
ENDPROC(v7_dma_flush_range)
/*
@@ -439,7 +439,7 @@ ENTRY(v7_dma_unmap_area)
add r1, r1, r0
teq r2, #DMA_TO_DEVICE
bne v7_dma_inv_range
- mov pc, lr
+ ret lr
ENDPROC(v7_dma_unmap_area)
__INITDATA
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 1f88db06b133..7a996aaa061e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -26,6 +26,7 @@
#include <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/sizes.h>
+#include <linux/cma.h>
#include <asm/memory.h>
#include <asm/highmem.h>
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
index c508f41a43bc..59424937e52b 100644
--- a/arch/arm/mm/dump.c
+++ b/arch/arm/mm/dump.c
@@ -126,8 +126,8 @@ static const struct prot_bits section_bits[] = {
.val = PMD_SECT_USER,
.set = "USR",
}, {
- .mask = PMD_SECT_RDONLY,
- .val = PMD_SECT_RDONLY,
+ .mask = L_PMD_SECT_RDONLY,
+ .val = L_PMD_SECT_RDONLY,
.set = "ro",
.clear = "RW",
#elif __LINUX_ARM_ARCH__ >= 6
diff --git a/arch/arm/mm/l2c-l2x0-resume.S b/arch/arm/mm/l2c-l2x0-resume.S
index 99b05f21a59a..fda415e4ca8f 100644
--- a/arch/arm/mm/l2c-l2x0-resume.S
+++ b/arch/arm/mm/l2c-l2x0-resume.S
@@ -6,6 +6,7 @@
* This code can only be used to if you are running in the secure world.
*/
#include <linux/linkage.h>
+#include <asm/assembler.h>
#include <asm/hardware/cache-l2x0.h>
.text
@@ -27,7 +28,7 @@ ENTRY(l2c310_early_resume)
@ Check that the address has been initialised
teq r1, #0
- moveq pc, lr
+ reteq lr
@ The prefetch and power control registers are revision dependent
@ and can be written whether or not the L2 cache is enabled
@@ -41,7 +42,7 @@ ENTRY(l2c310_early_resume)
@ Don't setup the L2 cache if it is already enabled
ldr r0, [r1, #L2X0_CTRL]
tst r0, #L2X0_CTRL_EN
- movne pc, lr
+ retne lr
str r3, [r1, #L310_TAG_LATENCY_CTRL]
str r4, [r1, #L310_DATA_LATENCY_CTRL]
@@ -51,7 +52,7 @@ ENTRY(l2c310_early_resume)
str r2, [r1, #L2X0_AUX_CTRL]
mov r9, #L2X0_CTRL_EN
str r9, [r1, #L2X0_CTRL]
- mov pc, lr
+ ret lr
ENDPROC(l2c310_early_resume)
.align
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e3ba8d112a2..8348ed6b2efe 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1434,23 +1434,64 @@ void __init early_paging_init(const struct machine_desc *mdesc,
dsb(ishst);
isb();
- /* remap level 1 table */
+ /*
+ * FIXME: This code is not architecturally compliant: we modify
+ * the mappings in-place, indeed while they are in use by this
+ * very same code. This may lead to unpredictable behaviour of
+ * the CPU.
+ *
+ * Even modifying the mappings in a separate page table does
+ * not resolve this.
+ *
+ * The architecture strongly recommends that when a mapping is
+ * changed, that it is changed by first going via an invalid
+ * mapping and back to the new mapping. This is to ensure that
+ * no TLB conflicts (caused by the TLB having more than one TLB
+ * entry match a translation) can occur. However, doing that
+ * here will result in unmapping the code we are running.
+ */
+ pr_warn("WARNING: unsafe modification of in-place page tables - tainting kernel\n");
+ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+
+ /*
+ * Remap level 1 table. This changes the physical addresses
+ * used to refer to the level 2 page tables to the high
+ * physical address alias, leaving everything else the same.
+ */
for (i = 0; i < PTRS_PER_PGD; pud0++, i++) {
set_pud(pud0,
__pud(__pa(pmd0) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
pmd0 += PTRS_PER_PMD;
}
- /* remap pmds for kernel mapping */
+ /*
+ * Remap the level 2 table, pointing the mappings at the high
+ * physical address alias of these pages.
+ */
phys = __pa(map_start);
do {
*pmdk++ = __pmd(phys | pmdprot);
phys += PMD_SIZE;
} while (phys < map_end);
+ /*
+ * Ensure that the above updates are flushed out of the cache.
+ * This is not strictly correct; on a system where the caches
+ * are coherent with each other, but the MMU page table walks
+ * may not be coherent, flush_cache_all() may be a no-op, and
+ * this will fail.
+ */
flush_cache_all();
+
+ /*
+ * Re-write the TTBR values to point them at the high physical
+ * alias of the page tables. We expect __va() will work on
+ * cpu_get_pgd(), which returns the value of TTBR0.
+ */
cpu_switch_mm(pgd0, &init_mm);
cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
+
+ /* Finally flush any stale TLB values. */
local_flush_bp_all();
local_flush_tlb_all();
}
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index d1a2d05971e0..86ee5d47ce3c 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -73,7 +73,7 @@
* cpu_arm1020_proc_init()
*/
ENTRY(cpu_arm1020_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm1020_proc_fin()
@@ -83,7 +83,7 @@ ENTRY(cpu_arm1020_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm1020_reset(loc)
@@ -107,7 +107,7 @@ ENTRY(cpu_arm1020_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm1020_reset)
.popsection
@@ -117,7 +117,7 @@ ENDPROC(cpu_arm1020_reset)
.align 5
ENTRY(cpu_arm1020_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -133,7 +133,7 @@ ENTRY(arm1020_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
#endif
- mov pc, lr
+ ret lr
ENDPROC(arm1020_flush_icache_all)
/*
@@ -169,7 +169,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -200,7 +200,7 @@ ENTRY(arm1020_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -242,7 +242,7 @@ ENTRY(arm1020_coherent_user_range)
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -264,7 +264,7 @@ ENTRY(arm1020_flush_kern_dcache_area)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -297,7 +297,7 @@ arm1020_dma_inv_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -320,7 +320,7 @@ arm1020_dma_clean_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -342,7 +342,7 @@ ENTRY(arm1020_dma_flush_range)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -365,7 +365,7 @@ ENDPROC(arm1020_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm1020_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm1020_dma_unmap_area)
.globl arm1020_flush_kern_cache_louis
@@ -384,7 +384,7 @@ ENTRY(cpu_arm1020_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
#endif
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -423,7 +423,7 @@ ENTRY(cpu_arm1020_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
/*
* cpu_arm1020_set_pte(ptep, pte)
@@ -441,7 +441,7 @@ ENTRY(cpu_arm1020_set_pte_ext)
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm1020_setup, #function
__arm1020_setup:
@@ -460,7 +460,7 @@ __arm1020_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .R.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm1020_setup, . - __arm1020_setup
/*
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 9d89405c3d03..a6331d78601f 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -73,7 +73,7 @@
* cpu_arm1020e_proc_init()
*/
ENTRY(cpu_arm1020e_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm1020e_proc_fin()
@@ -83,7 +83,7 @@ ENTRY(cpu_arm1020e_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm1020e_reset(loc)
@@ -107,7 +107,7 @@ ENTRY(cpu_arm1020e_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm1020e_reset)
.popsection
@@ -117,7 +117,7 @@ ENDPROC(cpu_arm1020e_reset)
.align 5
ENTRY(cpu_arm1020e_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -133,7 +133,7 @@ ENTRY(arm1020e_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
#endif
- mov pc, lr
+ ret lr
ENDPROC(arm1020e_flush_icache_all)
/*
@@ -168,7 +168,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -197,7 +197,7 @@ ENTRY(arm1020e_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -236,7 +236,7 @@ ENTRY(arm1020e_coherent_user_range)
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -257,7 +257,7 @@ ENTRY(arm1020e_flush_kern_dcache_area)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -286,7 +286,7 @@ arm1020e_dma_inv_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -308,7 +308,7 @@ arm1020e_dma_clean_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -328,7 +328,7 @@ ENTRY(arm1020e_dma_flush_range)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -351,7 +351,7 @@ ENDPROC(arm1020e_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm1020e_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm1020e_dma_unmap_area)
.globl arm1020e_flush_kern_cache_louis
@@ -369,7 +369,7 @@ ENTRY(cpu_arm1020e_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
#endif
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -407,7 +407,7 @@ ENTRY(cpu_arm1020e_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm1020e_set_pte(ptep, pte)
@@ -423,7 +423,7 @@ ENTRY(cpu_arm1020e_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
#endif
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm1020e_setup, #function
__arm1020e_setup:
@@ -441,7 +441,7 @@ __arm1020e_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .R.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm1020e_setup, . - __arm1020e_setup
/*
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 6f01a0ae3b30..a126b7a59928 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -62,7 +62,7 @@
* cpu_arm1022_proc_init()
*/
ENTRY(cpu_arm1022_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm1022_proc_fin()
@@ -72,7 +72,7 @@ ENTRY(cpu_arm1022_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm1022_reset(loc)
@@ -96,7 +96,7 @@ ENTRY(cpu_arm1022_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm1022_reset)
.popsection
@@ -106,7 +106,7 @@ ENDPROC(cpu_arm1022_reset)
.align 5
ENTRY(cpu_arm1022_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -122,7 +122,7 @@ ENTRY(arm1022_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
#endif
- mov pc, lr
+ ret lr
ENDPROC(arm1022_flush_icache_all)
/*
@@ -156,7 +156,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -185,7 +185,7 @@ ENTRY(arm1022_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -225,7 +225,7 @@ ENTRY(arm1022_coherent_user_range)
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -246,7 +246,7 @@ ENTRY(arm1022_flush_kern_dcache_area)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -275,7 +275,7 @@ arm1022_dma_inv_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -297,7 +297,7 @@ arm1022_dma_clean_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -317,7 +317,7 @@ ENTRY(arm1022_dma_flush_range)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -340,7 +340,7 @@ ENDPROC(arm1022_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm1022_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm1022_dma_unmap_area)
.globl arm1022_flush_kern_cache_louis
@@ -358,7 +358,7 @@ ENTRY(cpu_arm1022_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
#endif
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -389,7 +389,7 @@ ENTRY(cpu_arm1022_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm1022_set_pte_ext(ptep, pte, ext)
@@ -405,7 +405,7 @@ ENTRY(cpu_arm1022_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
#endif
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm1022_setup, #function
__arm1022_setup:
@@ -423,7 +423,7 @@ __arm1022_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .R..............
#endif
- mov pc, lr
+ ret lr
.size __arm1022_setup, . - __arm1022_setup
/*
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 4799a24b43e6..fc294067e977 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -62,7 +62,7 @@
* cpu_arm1026_proc_init()
*/
ENTRY(cpu_arm1026_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm1026_proc_fin()
@@ -72,7 +72,7 @@ ENTRY(cpu_arm1026_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm1026_reset(loc)
@@ -96,7 +96,7 @@ ENTRY(cpu_arm1026_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm1026_reset)
.popsection
@@ -106,7 +106,7 @@ ENDPROC(cpu_arm1026_reset)
.align 5
ENTRY(cpu_arm1026_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -122,7 +122,7 @@ ENTRY(arm1026_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
#endif
- mov pc, lr
+ ret lr
ENDPROC(arm1026_flush_icache_all)
/*
@@ -151,7 +151,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -180,7 +180,7 @@ ENTRY(arm1026_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
#endif
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -219,7 +219,7 @@ ENTRY(arm1026_coherent_user_range)
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -240,7 +240,7 @@ ENTRY(arm1026_flush_kern_dcache_area)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -269,7 +269,7 @@ arm1026_dma_inv_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -291,7 +291,7 @@ arm1026_dma_clean_range:
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -311,7 +311,7 @@ ENTRY(arm1026_dma_flush_range)
blo 1b
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -334,7 +334,7 @@ ENDPROC(arm1026_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm1026_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm1026_dma_unmap_area)
.globl arm1026_flush_kern_cache_louis
@@ -352,7 +352,7 @@ ENTRY(cpu_arm1026_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
#endif
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -378,7 +378,7 @@ ENTRY(cpu_arm1026_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm1026_set_pte_ext(ptep, pte, ext)
@@ -394,7 +394,7 @@ ENTRY(cpu_arm1026_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
#endif
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm1026_setup, #function
__arm1026_setup:
@@ -417,7 +417,7 @@ __arm1026_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .R.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm1026_setup, . - __arm1026_setup
/*
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index d42c37f9f5bc..2baa66b3ac9b 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -51,14 +51,14 @@
*/
ENTRY(cpu_arm720_dcache_clean_area)
ENTRY(cpu_arm720_proc_init)
- mov pc, lr
+ ret lr
ENTRY(cpu_arm720_proc_fin)
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* Function: arm720_proc_do_idle(void)
@@ -66,7 +66,7 @@ ENTRY(cpu_arm720_proc_fin)
* Purpose : put the processor in proper idle mode
*/
ENTRY(cpu_arm720_do_idle)
- mov pc, lr
+ ret lr
/*
* Function: arm720_switch_mm(unsigned long pgd_phys)
@@ -81,7 +81,7 @@ ENTRY(cpu_arm720_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ update page table ptr
mcr p15, 0, r1, c8, c7, 0 @ flush TLB (v4)
#endif
- mov pc, lr
+ ret lr
/*
* Function: arm720_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext)
@@ -94,7 +94,7 @@ ENTRY(cpu_arm720_set_pte_ext)
#ifdef CONFIG_MMU
armv3_set_pte_ext wc_disable=0
#endif
- mov pc, lr
+ ret lr
/*
* Function: arm720_reset
@@ -112,7 +112,7 @@ ENTRY(cpu_arm720_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x2100 @ ..v....s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm720_reset)
.popsection
@@ -128,7 +128,7 @@ __arm710_setup:
bic r0, r0, r5
ldr r5, arm710_cr1_set
orr r0, r0, r5
- mov pc, lr @ __ret (head.S)
+ ret lr @ __ret (head.S)
.size __arm710_setup, . - __arm710_setup
/*
@@ -156,7 +156,7 @@ __arm720_setup:
mrc p15, 0, r0, c1, c0 @ get control register
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr @ __ret (head.S)
+ ret lr @ __ret (head.S)
.size __arm720_setup, . - __arm720_setup
/*
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 9b0ae90cbf17..ac1ea6b3bce4 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -32,7 +32,7 @@ ENTRY(cpu_arm740_proc_init)
ENTRY(cpu_arm740_do_idle)
ENTRY(cpu_arm740_dcache_clean_area)
ENTRY(cpu_arm740_switch_mm)
- mov pc, lr
+ ret lr
/*
* cpu_arm740_proc_fin()
@@ -42,7 +42,7 @@ ENTRY(cpu_arm740_proc_fin)
bic r0, r0, #0x3f000000 @ bank/f/lock/s
bic r0, r0, #0x0000000c @ w-buffer/cache
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm740_reset(loc)
@@ -56,7 +56,7 @@ ENTRY(cpu_arm740_reset)
mrc p15, 0, ip, c1, c0, 0 @ get ctrl register
bic ip, ip, #0x0000000c @ ............wc..
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm740_reset)
.popsection
@@ -115,7 +115,7 @@ __arm740_setup:
@ need some benchmark
orr r0, r0, #0x0000000d @ MPU/Cache/WB
- mov pc, lr
+ ret lr
.size __arm740_setup, . - __arm740_setup
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index f6cc3f63ce39..bf6ba4bc30ff 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -32,13 +32,13 @@ ENTRY(cpu_arm7tdmi_proc_init)
ENTRY(cpu_arm7tdmi_do_idle)
ENTRY(cpu_arm7tdmi_dcache_clean_area)
ENTRY(cpu_arm7tdmi_switch_mm)
- mov pc, lr
+ ret lr
/*
* cpu_arm7tdmi_proc_fin()
*/
ENTRY(cpu_arm7tdmi_proc_fin)
- mov pc, lr
+ ret lr
/*
* Function: cpu_arm7tdmi_reset(loc)
@@ -47,13 +47,13 @@ ENTRY(cpu_arm7tdmi_proc_fin)
*/
.pushsection .idmap.text, "ax"
ENTRY(cpu_arm7tdmi_reset)
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm7tdmi_reset)
.popsection
.type __arm7tdmi_setup, #function
__arm7tdmi_setup:
- mov pc, lr
+ ret lr
.size __arm7tdmi_setup, . - __arm7tdmi_setup
__INITDATA
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 549557df6d57..22bf8dde4f84 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -63,7 +63,7 @@
* cpu_arm920_proc_init()
*/
ENTRY(cpu_arm920_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm920_proc_fin()
@@ -73,7 +73,7 @@ ENTRY(cpu_arm920_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm920_reset(loc)
@@ -97,7 +97,7 @@ ENTRY(cpu_arm920_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm920_reset)
.popsection
@@ -107,7 +107,7 @@ ENDPROC(cpu_arm920_reset)
.align 5
ENTRY(cpu_arm920_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -120,7 +120,7 @@ ENTRY(cpu_arm920_do_idle)
ENTRY(arm920_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm920_flush_icache_all)
/*
@@ -151,7 +151,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -177,7 +177,7 @@ ENTRY(arm920_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -211,7 +211,7 @@ ENTRY(arm920_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -231,7 +231,7 @@ ENTRY(arm920_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -257,7 +257,7 @@ arm920_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -276,7 +276,7 @@ arm920_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -293,7 +293,7 @@ ENTRY(arm920_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -316,7 +316,7 @@ ENDPROC(arm920_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm920_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm920_dma_unmap_area)
.globl arm920_flush_kern_cache_louis
@@ -332,7 +332,7 @@ ENTRY(cpu_arm920_dcache_clean_area)
add r0, r0, #CACHE_DLINESIZE
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -367,7 +367,7 @@ ENTRY(cpu_arm920_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm920_set_pte(ptep, pte, ext)
@@ -382,7 +382,7 @@ ENTRY(cpu_arm920_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm920_suspend_size
@@ -423,7 +423,7 @@ __arm920_setup:
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __arm920_setup, . - __arm920_setup
/*
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 2a758b06c6f6..0c6d5ac5a6d4 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -65,7 +65,7 @@
* cpu_arm922_proc_init()
*/
ENTRY(cpu_arm922_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm922_proc_fin()
@@ -75,7 +75,7 @@ ENTRY(cpu_arm922_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm922_reset(loc)
@@ -99,7 +99,7 @@ ENTRY(cpu_arm922_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm922_reset)
.popsection
@@ -109,7 +109,7 @@ ENDPROC(cpu_arm922_reset)
.align 5
ENTRY(cpu_arm922_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
@@ -122,7 +122,7 @@ ENTRY(cpu_arm922_do_idle)
ENTRY(arm922_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm922_flush_icache_all)
/*
@@ -153,7 +153,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -179,7 +179,7 @@ ENTRY(arm922_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -213,7 +213,7 @@ ENTRY(arm922_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -233,7 +233,7 @@ ENTRY(arm922_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -259,7 +259,7 @@ arm922_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -278,7 +278,7 @@ arm922_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -295,7 +295,7 @@ ENTRY(arm922_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -318,7 +318,7 @@ ENDPROC(arm922_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm922_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm922_dma_unmap_area)
.globl arm922_flush_kern_cache_louis
@@ -336,7 +336,7 @@ ENTRY(cpu_arm922_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
#endif
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -371,7 +371,7 @@ ENTRY(cpu_arm922_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm922_set_pte_ext(ptep, pte, ext)
@@ -386,7 +386,7 @@ ENTRY(cpu_arm922_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm922_setup, #function
__arm922_setup:
@@ -401,7 +401,7 @@ __arm922_setup:
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __arm922_setup, . - __arm922_setup
/*
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index ba0d58e1a2a2..c32d073282ea 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -86,7 +86,7 @@
* cpu_arm925_proc_init()
*/
ENTRY(cpu_arm925_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm925_proc_fin()
@@ -96,7 +96,7 @@ ENTRY(cpu_arm925_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm925_reset(loc)
@@ -129,7 +129,7 @@ ENDPROC(cpu_arm925_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
/*
* cpu_arm925_do_idle()
@@ -145,7 +145,7 @@ ENTRY(cpu_arm925_do_idle)
mcr p15, 0, r2, c1, c0, 0 @ Disable I cache
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -155,7 +155,7 @@ ENTRY(cpu_arm925_do_idle)
ENTRY(arm925_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm925_flush_icache_all)
/*
@@ -188,7 +188,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -225,7 +225,7 @@ ENTRY(arm925_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -259,7 +259,7 @@ ENTRY(arm925_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -279,7 +279,7 @@ ENTRY(arm925_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -307,7 +307,7 @@ arm925_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -328,7 +328,7 @@ arm925_dma_clean_range:
blo 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -350,7 +350,7 @@ ENTRY(arm925_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -373,7 +373,7 @@ ENDPROC(arm925_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm925_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm925_dma_unmap_area)
.globl arm925_flush_kern_cache_louis
@@ -390,7 +390,7 @@ ENTRY(cpu_arm925_dcache_clean_area)
bhi 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -419,7 +419,7 @@ ENTRY(cpu_arm925_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm925_set_pte_ext(ptep, pte, ext)
@@ -436,7 +436,7 @@ ENTRY(cpu_arm925_set_pte_ext)
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif /* CONFIG_MMU */
- mov pc, lr
+ ret lr
.type __arm925_setup, #function
__arm925_setup:
@@ -469,7 +469,7 @@ __arm925_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .1.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm925_setup, . - __arm925_setup
/*
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 0f098f407c9f..252b2503038d 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -55,7 +55,7 @@
* cpu_arm926_proc_init()
*/
ENTRY(cpu_arm926_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_arm926_proc_fin()
@@ -65,7 +65,7 @@ ENTRY(cpu_arm926_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm926_reset(loc)
@@ -89,7 +89,7 @@ ENTRY(cpu_arm926_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm926_reset)
.popsection
@@ -111,7 +111,7 @@ ENTRY(cpu_arm926_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable
msr cpsr_c, r3 @ Restore FIQ state
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -121,7 +121,7 @@ ENTRY(cpu_arm926_do_idle)
ENTRY(arm926_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm926_flush_icache_all)
/*
@@ -151,7 +151,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -188,7 +188,7 @@ ENTRY(arm926_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -222,7 +222,7 @@ ENTRY(arm926_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -242,7 +242,7 @@ ENTRY(arm926_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -270,7 +270,7 @@ arm926_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -291,7 +291,7 @@ arm926_dma_clean_range:
blo 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -313,7 +313,7 @@ ENTRY(arm926_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -336,7 +336,7 @@ ENDPROC(arm926_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm926_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm926_dma_unmap_area)
.globl arm926_flush_kern_cache_louis
@@ -353,7 +353,7 @@ ENTRY(cpu_arm926_dcache_clean_area)
bhi 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -380,7 +380,7 @@ ENTRY(cpu_arm926_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
#endif
- mov pc, lr
+ ret lr
/*
* cpu_arm926_set_pte_ext(ptep, pte, ext)
@@ -397,7 +397,7 @@ ENTRY(cpu_arm926_set_pte_ext)
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm926_suspend_size
@@ -448,7 +448,7 @@ __arm926_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x4000 @ .1.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm926_setup, . - __arm926_setup
/*
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 1c39a704ff6e..e5212d489377 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -31,7 +31,7 @@
*/
ENTRY(cpu_arm940_proc_init)
ENTRY(cpu_arm940_switch_mm)
- mov pc, lr
+ ret lr
/*
* cpu_arm940_proc_fin()
@@ -41,7 +41,7 @@ ENTRY(cpu_arm940_proc_fin)
bic r0, r0, #0x00001000 @ i-cache
bic r0, r0, #0x00000004 @ d-cache
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm940_reset(loc)
@@ -58,7 +58,7 @@ ENTRY(cpu_arm940_reset)
bic ip, ip, #0x00000005 @ .............c.p
bic ip, ip, #0x00001000 @ i-cache
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm940_reset)
.popsection
@@ -68,7 +68,7 @@ ENDPROC(cpu_arm940_reset)
.align 5
ENTRY(cpu_arm940_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -78,7 +78,7 @@ ENTRY(cpu_arm940_do_idle)
ENTRY(arm940_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm940_flush_icache_all)
/*
@@ -122,7 +122,7 @@ ENTRY(arm940_flush_user_cache_range)
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -170,7 +170,7 @@ ENTRY(arm940_flush_kern_dcache_area)
bcs 1b @ segments 7 to 0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -191,7 +191,7 @@ arm940_dma_inv_range:
subs r1, r1, #1 << 4
bcs 1b @ segments 7 to 0
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -215,7 +215,7 @@ ENTRY(cpu_arm940_dcache_clean_area)
bcs 1b @ segments 7 to 0
#endif
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -241,7 +241,7 @@ ENTRY(arm940_dma_flush_range)
subs r1, r1, #1 << 4
bcs 1b @ segments 7 to 0
mcr p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -264,7 +264,7 @@ ENDPROC(arm940_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm940_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm940_dma_unmap_area)
.globl arm940_flush_kern_cache_louis
@@ -337,7 +337,7 @@ __arm940_setup:
orr r0, r0, #0x00001000 @ I-cache
orr r0, r0, #0x00000005 @ MPU/D-cache
- mov pc, lr
+ ret lr
.size __arm940_setup, . - __arm940_setup
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 0289cd905e73..b3dd9b2d0b8e 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -38,7 +38,7 @@
*/
ENTRY(cpu_arm946_proc_init)
ENTRY(cpu_arm946_switch_mm)
- mov pc, lr
+ ret lr
/*
* cpu_arm946_proc_fin()
@@ -48,7 +48,7 @@ ENTRY(cpu_arm946_proc_fin)
bic r0, r0, #0x00001000 @ i-cache
bic r0, r0, #0x00000004 @ d-cache
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_arm946_reset(loc)
@@ -65,7 +65,7 @@ ENTRY(cpu_arm946_reset)
bic ip, ip, #0x00000005 @ .............c.p
bic ip, ip, #0x00001000 @ i-cache
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm946_reset)
.popsection
@@ -75,7 +75,7 @@ ENDPROC(cpu_arm946_reset)
.align 5
ENTRY(cpu_arm946_do_idle)
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -85,7 +85,7 @@ ENTRY(cpu_arm946_do_idle)
ENTRY(arm946_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(arm946_flush_icache_all)
/*
@@ -117,7 +117,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ flush I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -156,7 +156,7 @@ ENTRY(arm946_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -191,7 +191,7 @@ ENTRY(arm946_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -212,7 +212,7 @@ ENTRY(arm946_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -239,7 +239,7 @@ arm946_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -260,7 +260,7 @@ arm946_dma_clean_range:
blo 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -284,7 +284,7 @@ ENTRY(arm946_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -307,7 +307,7 @@ ENDPROC(arm946_dma_map_area)
* - dir - DMA direction
*/
ENTRY(arm946_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(arm946_dma_unmap_area)
.globl arm946_flush_kern_cache_louis
@@ -324,7 +324,7 @@ ENTRY(cpu_arm946_dcache_clean_area)
bhi 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.type __arm946_setup, #function
__arm946_setup:
@@ -392,7 +392,7 @@ __arm946_setup:
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
orr r0, r0, #0x00004000 @ .1.. .... .... ....
#endif
- mov pc, lr
+ ret lr
.size __arm946_setup, . - __arm946_setup
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index f51197ba754a..8227322bbb8f 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -32,13 +32,13 @@ ENTRY(cpu_arm9tdmi_proc_init)
ENTRY(cpu_arm9tdmi_do_idle)
ENTRY(cpu_arm9tdmi_dcache_clean_area)
ENTRY(cpu_arm9tdmi_switch_mm)
- mov pc, lr
+ ret lr
/*
* cpu_arm9tdmi_proc_fin()
*/
ENTRY(cpu_arm9tdmi_proc_fin)
- mov pc, lr
+ ret lr
/*
* Function: cpu_arm9tdmi_reset(loc)
@@ -47,13 +47,13 @@ ENTRY(cpu_arm9tdmi_proc_fin)
*/
.pushsection .idmap.text, "ax"
ENTRY(cpu_arm9tdmi_reset)
- mov pc, r0
+ ret r0
ENDPROC(cpu_arm9tdmi_reset)
.popsection
.type __arm9tdmi_setup, #function
__arm9tdmi_setup:
- mov pc, lr
+ ret lr
.size __arm9tdmi_setup, . - __arm9tdmi_setup
__INITDATA
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 2dfc0f1d3bfd..c494886892ba 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -32,7 +32,7 @@
* cpu_fa526_proc_init()
*/
ENTRY(cpu_fa526_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_fa526_proc_fin()
@@ -44,7 +44,7 @@ ENTRY(cpu_fa526_proc_fin)
mcr p15, 0, r0, c1, c0, 0 @ disable caches
nop
nop
- mov pc, lr
+ ret lr
/*
* cpu_fa526_reset(loc)
@@ -72,7 +72,7 @@ ENTRY(cpu_fa526_reset)
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
nop
nop
- mov pc, r0
+ ret r0
ENDPROC(cpu_fa526_reset)
.popsection
@@ -81,7 +81,7 @@ ENDPROC(cpu_fa526_reset)
*/
.align 4
ENTRY(cpu_fa526_do_idle)
- mov pc, lr
+ ret lr
ENTRY(cpu_fa526_dcache_clean_area)
@@ -90,7 +90,7 @@ ENTRY(cpu_fa526_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -117,7 +117,7 @@ ENTRY(cpu_fa526_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB
#endif
- mov pc, lr
+ ret lr
/*
* cpu_fa526_set_pte_ext(ptep, pte, ext)
@@ -133,7 +133,7 @@ ENTRY(cpu_fa526_set_pte_ext)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
.type __fa526_setup, #function
__fa526_setup:
@@ -162,7 +162,7 @@ __fa526_setup:
bic r0, r0, r5
ldr r5, fa526_cr1_set
orr r0, r0, r5
- mov pc, lr
+ ret lr
.size __fa526_setup, . - __fa526_setup
/*
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index db79b62c92fb..03a1b75f2e16 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -69,7 +69,7 @@ ENTRY(cpu_feroceon_proc_init)
movne r2, r2, lsr #2 @ turned into # of sets
sub r2, r2, #(1 << 5)
stmia r1, {r2, r3}
- mov pc, lr
+ ret lr
/*
* cpu_feroceon_proc_fin()
@@ -86,7 +86,7 @@ ENTRY(cpu_feroceon_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_feroceon_reset(loc)
@@ -110,7 +110,7 @@ ENTRY(cpu_feroceon_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_feroceon_reset)
.popsection
@@ -124,7 +124,7 @@ ENTRY(cpu_feroceon_do_idle)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -134,7 +134,7 @@ ENTRY(cpu_feroceon_do_idle)
ENTRY(feroceon_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(feroceon_flush_icache_all)
/*
@@ -169,7 +169,7 @@ __flush_whole_cache:
mov ip, #0
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -198,7 +198,7 @@ ENTRY(feroceon_flush_user_cache_range)
tst r2, #VM_EXEC
mov ip, #0
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -233,7 +233,7 @@ ENTRY(feroceon_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -254,7 +254,7 @@ ENTRY(feroceon_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.align 5
ENTRY(feroceon_range_flush_kern_dcache_area)
@@ -268,7 +268,7 @@ ENTRY(feroceon_range_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -295,7 +295,7 @@ feroceon_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.align 5
feroceon_range_dma_inv_range:
@@ -311,7 +311,7 @@ feroceon_range_dma_inv_range:
mcr p15, 5, r0, c15, c14, 0 @ D inv range start
mcr p15, 5, r1, c15, c14, 1 @ D inv range top
msr cpsr_c, r2 @ restore interrupts
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -331,7 +331,7 @@ feroceon_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.align 5
feroceon_range_dma_clean_range:
@@ -344,7 +344,7 @@ feroceon_range_dma_clean_range:
mcr p15, 5, r1, c15, c13, 1 @ D clean range top
msr cpsr_c, r2 @ restore interrupts
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -362,7 +362,7 @@ ENTRY(feroceon_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.align 5
ENTRY(feroceon_range_dma_flush_range)
@@ -375,7 +375,7 @@ ENTRY(feroceon_range_dma_flush_range)
mcr p15, 5, r1, c15, c15, 1 @ D clean/inv range top
msr cpsr_c, r2 @ restore interrupts
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -412,7 +412,7 @@ ENDPROC(feroceon_range_dma_map_area)
* - dir - DMA direction
*/
ENTRY(feroceon_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(feroceon_dma_unmap_area)
.globl feroceon_flush_kern_cache_louis
@@ -461,7 +461,7 @@ ENTRY(cpu_feroceon_dcache_clean_area)
bhi 1b
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -490,9 +490,9 @@ ENTRY(cpu_feroceon_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, r2
+ ret r2
#else
- mov pc, lr
+ ret lr
#endif
/*
@@ -512,7 +512,7 @@ ENTRY(cpu_feroceon_set_pte_ext)
#endif
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
/* Suspend/resume support: taken from arch/arm/mm/proc-arm926.S */
.globl cpu_feroceon_suspend_size
@@ -554,7 +554,7 @@ __feroceon_setup:
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __feroceon_setup, . - __feroceon_setup
/*
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 40acba595731..53d393455f13 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -45,7 +45,7 @@
* cpu_mohawk_proc_init()
*/
ENTRY(cpu_mohawk_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_mohawk_proc_fin()
@@ -55,7 +55,7 @@ ENTRY(cpu_mohawk_proc_fin)
bic r0, r0, #0x1800 @ ...iz...........
bic r0, r0, #0x0006 @ .............ca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_mohawk_reset(loc)
@@ -79,7 +79,7 @@ ENTRY(cpu_mohawk_reset)
bic ip, ip, #0x0007 @ .............cam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_mohawk_reset)
.popsection
@@ -93,7 +93,7 @@ ENTRY(cpu_mohawk_do_idle)
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
- mov pc, lr
+ ret lr
/*
* flush_icache_all()
@@ -103,7 +103,7 @@ ENTRY(cpu_mohawk_do_idle)
ENTRY(mohawk_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(mohawk_flush_icache_all)
/*
@@ -128,7 +128,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
mcrne p15, 0, ip, c7, c10, 0 @ drain write buffer
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, flags)
@@ -158,7 +158,7 @@ ENTRY(mohawk_flush_user_cache_range)
blo 1b
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -194,7 +194,7 @@ ENTRY(mohawk_coherent_user_range)
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
mov r0, #0
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -214,7 +214,7 @@ ENTRY(mohawk_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -240,7 +240,7 @@ mohawk_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -259,7 +259,7 @@ mohawk_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -277,7 +277,7 @@ ENTRY(mohawk_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -300,7 +300,7 @@ ENDPROC(mohawk_dma_map_area)
* - dir - DMA direction
*/
ENTRY(mohawk_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(mohawk_dma_unmap_area)
.globl mohawk_flush_kern_cache_louis
@@ -315,7 +315,7 @@ ENTRY(cpu_mohawk_dcache_clean_area)
subs r1, r1, #CACHE_DLINESIZE
bhi 1b
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
/*
* cpu_mohawk_switch_mm(pgd)
@@ -333,7 +333,7 @@ ENTRY(cpu_mohawk_switch_mm)
orr r0, r0, #0x18 @ cache the page table in L2
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, lr
+ ret lr
/*
* cpu_mohawk_set_pte_ext(ptep, pte, ext)
@@ -346,7 +346,7 @@ ENTRY(cpu_mohawk_set_pte_ext)
mov r0, r0
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mov pc, lr
+ ret lr
.globl cpu_mohawk_suspend_size
.equ cpu_mohawk_suspend_size, 4 * 6
@@ -400,7 +400,7 @@ __mohawk_setup:
mrc p15, 0, r0, c1, c0 @ get control register
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __mohawk_setup, . - __mohawk_setup
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index c45319c8f1d9..8008a0461cf5 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -38,7 +38,7 @@
ENTRY(cpu_sa110_proc_init)
mov r0, #0
mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching
- mov pc, lr
+ ret lr
/*
* cpu_sa110_proc_fin()
@@ -50,7 +50,7 @@ ENTRY(cpu_sa110_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_sa110_reset(loc)
@@ -74,7 +74,7 @@ ENTRY(cpu_sa110_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_sa110_reset)
.popsection
@@ -103,7 +103,7 @@ ENTRY(cpu_sa110_do_idle)
mov r0, r0 @ safety
mov r0, r0 @ safety
mcr p15, 0, r0, c15, c1, 2 @ enable clock switching
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -121,7 +121,7 @@ ENTRY(cpu_sa110_dcache_clean_area)
add r0, r0, #DCACHELINESIZE
subs r1, r1, #DCACHELINESIZE
bhi 1b
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -141,7 +141,7 @@ ENTRY(cpu_sa110_switch_mm)
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
ldr pc, [sp], #4
#else
- mov pc, lr
+ ret lr
#endif
/*
@@ -157,7 +157,7 @@ ENTRY(cpu_sa110_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
.type __sa110_setup, #function
__sa110_setup:
@@ -173,7 +173,7 @@ __sa110_setup:
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __sa110_setup, . - __sa110_setup
/*
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 09d241ae2dbe..89f97ac648a9 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -43,7 +43,7 @@ ENTRY(cpu_sa1100_proc_init)
mov r0, #0
mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching
mcr p15, 0, r0, c9, c0, 5 @ Allow read-buffer operations from userland
- mov pc, lr
+ ret lr
/*
* cpu_sa1100_proc_fin()
@@ -58,7 +58,7 @@ ENTRY(cpu_sa1100_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x000e @ ............wca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_sa1100_reset(loc)
@@ -82,7 +82,7 @@ ENTRY(cpu_sa1100_reset)
bic ip, ip, #0x000f @ ............wcam
bic ip, ip, #0x1100 @ ...i...s........
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
- mov pc, r0
+ ret r0
ENDPROC(cpu_sa1100_reset)
.popsection
@@ -113,7 +113,7 @@ ENTRY(cpu_sa1100_do_idle)
mcr p15, 0, r0, c15, c8, 2 @ wait for interrupt
mov r0, r0 @ safety
mcr p15, 0, r0, c15, c1, 2 @ enable clock switching
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -131,7 +131,7 @@ ENTRY(cpu_sa1100_dcache_clean_area)
add r0, r0, #DCACHELINESIZE
subs r1, r1, #DCACHELINESIZE
bhi 1b
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -152,7 +152,7 @@ ENTRY(cpu_sa1100_switch_mm)
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
ldr pc, [sp], #4
#else
- mov pc, lr
+ ret lr
#endif
/*
@@ -168,7 +168,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
mcr p15, 0, r0, c7, c10, 4 @ drain WB
#endif
- mov pc, lr
+ ret lr
.globl cpu_sa1100_suspend_size
.equ cpu_sa1100_suspend_size, 4 * 3
@@ -211,7 +211,7 @@ __sa1100_setup:
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __sa1100_setup, . - __sa1100_setup
/*
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 32b3558321c4..d0390f4b3f18 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -36,14 +36,14 @@
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
ENTRY(cpu_v6_proc_init)
- mov pc, lr
+ ret lr
ENTRY(cpu_v6_proc_fin)
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x0006 @ .............ca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_v6_reset(loc)
@@ -62,7 +62,7 @@ ENTRY(cpu_v6_reset)
mcr p15, 0, r1, c1, c0, 0 @ disable MMU
mov r1, #0
mcr p15, 0, r1, c7, c5, 4 @ ISB
- mov pc, r0
+ ret r0
ENDPROC(cpu_v6_reset)
.popsection
@@ -77,14 +77,14 @@ ENTRY(cpu_v6_do_idle)
mov r1, #0
mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
- mov pc, lr
+ ret lr
ENTRY(cpu_v6_dcache_clean_area)
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
add r0, r0, #D_CACHE_LINE_SIZE
subs r1, r1, #D_CACHE_LINE_SIZE
bhi 1b
- mov pc, lr
+ ret lr
/*
* cpu_v6_switch_mm(pgd_phys, tsk)
@@ -113,7 +113,7 @@ ENTRY(cpu_v6_switch_mm)
#endif
mcr p15, 0, r1, c13, c0, 1 @ set context ID
#endif
- mov pc, lr
+ ret lr
/*
* cpu_v6_set_pte_ext(ptep, pte, ext)
@@ -131,7 +131,7 @@ ENTRY(cpu_v6_set_pte_ext)
#ifdef CONFIG_MMU
armv6_set_pte_ext cpu_v6
#endif
- mov pc, lr
+ ret lr
/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
.globl cpu_v6_suspend_size
@@ -241,7 +241,7 @@ __v6_setup:
mcreq p15, 0, r5, c1, c0, 1 @ write aux control reg
orreq r0, r0, #(1 << 21) @ low interrupt latency configuration
#endif
- mov pc, lr @ return to head.S:__ret
+ ret lr @ return to head.S:__ret
/*
* V X F I D LR
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 1f52915f2b28..ed448d8a596b 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -59,7 +59,7 @@ ENTRY(cpu_v7_switch_mm)
mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
isb
#endif
- mov pc, lr
+ bx lr
ENDPROC(cpu_v7_switch_mm)
/*
@@ -106,7 +106,7 @@ ENTRY(cpu_v7_set_pte_ext)
ALT_SMP(W(nop))
ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte
#endif
- mov pc, lr
+ bx lr
ENDPROC(cpu_v7_set_pte_ext)
/*
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index 22e3ad63500c..1a24e9232ec8 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -19,6 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <asm/assembler.h>
#define TTB_IRGN_NC (0 << 8)
#define TTB_IRGN_WBWA (1 << 8)
@@ -61,7 +62,7 @@ ENTRY(cpu_v7_switch_mm)
mcrr p15, 0, rpgdl, rpgdh, c2 @ set TTB 0
isb
#endif
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_switch_mm)
#ifdef __ARMEB__
@@ -86,13 +87,18 @@ ENTRY(cpu_v7_set_pte_ext)
tst rh, #1 << (57 - 32) @ L_PTE_NONE
bicne rl, #L_PTE_VALID
bne 1f
- tst rh, #1 << (55 - 32) @ L_PTE_DIRTY
- orreq rl, #L_PTE_RDONLY
+
+ eor ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to
+ @ test for !L_PTE_DIRTY || L_PTE_RDONLY
+ tst ip, #1 << (55 - 32) | 1 << (58 - 32)
+ orrne rl, #PTE_AP2
+ biceq rl, #PTE_AP2
+
1: strd r2, r3, [r0]
ALT_SMP(W(nop))
ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte
#endif
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_set_pte_ext)
/*
@@ -140,12 +146,11 @@ ENDPROC(cpu_v7_set_pte_ext)
mov \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
mov \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT @ lower bits
addls \ttbr1, \ttbr1, #TTBR1_OFFSET
- mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
+ adcls \tmp, \tmp, #0
+ mcrr p15, 1, \ttbr1, \tmp, c2 @ load TTBR1
mov \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
mov \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT @ lower bits
- mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
- mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
- mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
+ mcrr p15, 0, \ttbr0, \tmp, c2 @ load TTBR0
.endm
/*
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 3db2c2f04a30..b5d67db20897 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -26,7 +26,7 @@
#endif
ENTRY(cpu_v7_proc_init)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_proc_init)
ENTRY(cpu_v7_proc_fin)
@@ -34,7 +34,7 @@ ENTRY(cpu_v7_proc_fin)
bic r0, r0, #0x1000 @ ...i............
bic r0, r0, #0x0006 @ .............ca.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_proc_fin)
/*
@@ -71,20 +71,20 @@ ENDPROC(cpu_v7_reset)
ENTRY(cpu_v7_do_idle)
dsb @ WFI may enter a low-power mode
wfi
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_do_idle)
ENTRY(cpu_v7_dcache_clean_area)
ALT_SMP(W(nop)) @ MP extensions imply L1 PTW
ALT_UP_B(1f)
- mov pc, lr
+ ret lr
1: dcache_line_size r2, r3
2: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
add r0, r0, r2
subs r1, r1, r2
bhi 2b
dsb ishst
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7_dcache_clean_area)
string cpu_v7_name, "ARMv7 Processor"
@@ -152,6 +152,40 @@ ENTRY(cpu_v7_do_resume)
ENDPROC(cpu_v7_do_resume)
#endif
+/*
+ * Cortex-A9 processor functions
+ */
+ globl_equ cpu_ca9mp_proc_init, cpu_v7_proc_init
+ globl_equ cpu_ca9mp_proc_fin, cpu_v7_proc_fin
+ globl_equ cpu_ca9mp_reset, cpu_v7_reset
+ globl_equ cpu_ca9mp_do_idle, cpu_v7_do_idle
+ globl_equ cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area
+ globl_equ cpu_ca9mp_switch_mm, cpu_v7_switch_mm
+ globl_equ cpu_ca9mp_set_pte_ext, cpu_v7_set_pte_ext
+.globl cpu_ca9mp_suspend_size
+.equ cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2
+#ifdef CONFIG_ARM_CPU_SUSPEND
+ENTRY(cpu_ca9mp_do_suspend)
+ stmfd sp!, {r4 - r5}
+ mrc p15, 0, r4, c15, c0, 1 @ Diagnostic register
+ mrc p15, 0, r5, c15, c0, 0 @ Power register
+ stmia r0!, {r4 - r5}
+ ldmfd sp!, {r4 - r5}
+ b cpu_v7_do_suspend
+ENDPROC(cpu_ca9mp_do_suspend)
+
+ENTRY(cpu_ca9mp_do_resume)
+ ldmia r0!, {r4 - r5}
+ mrc p15, 0, r10, c15, c0, 1 @ Read Diagnostic register
+ teq r4, r10 @ Already restored?
+ mcrne p15, 0, r4, c15, c0, 1 @ No, so restore it
+ mrc p15, 0, r10, c15, c0, 0 @ Read Power register
+ teq r5, r10 @ Already restored?
+ mcrne p15, 0, r5, c15, c0, 0 @ No, so restore it
+ b cpu_v7_do_resume
+ENDPROC(cpu_ca9mp_do_resume)
+#endif
+
#ifdef CONFIG_CPU_PJ4B
globl_equ cpu_pj4b_switch_mm, cpu_v7_switch_mm
globl_equ cpu_pj4b_set_pte_ext, cpu_v7_set_pte_ext
@@ -163,7 +197,7 @@ ENTRY(cpu_pj4b_do_idle)
dsb @ WFI may enter a low-power mode
wfi
dsb @barrier
- mov pc, lr
+ ret lr
ENDPROC(cpu_pj4b_do_idle)
#else
globl_equ cpu_pj4b_do_idle, cpu_v7_do_idle
@@ -184,16 +218,16 @@ ENDPROC(cpu_pj4b_do_suspend)
ENTRY(cpu_pj4b_do_resume)
ldmia r0!, {r6 - r10}
- mcr p15, 1, r6, c15, c1, 0 @ save CP15 - extra features
- mcr p15, 1, r7, c15, c2, 0 @ save CP15 - Aux Func Modes Ctrl 0
- mcr p15, 1, r8, c15, c1, 2 @ save CP15 - Aux Debug Modes Ctrl 2
- mcr p15, 1, r9, c15, c1, 1 @ save CP15 - Aux Debug Modes Ctrl 1
- mcr p15, 0, r10, c9, c14, 0 @ save CP15 - PMC
+ mcr p15, 1, r6, c15, c1, 0 @ restore CP15 - extra features
+ mcr p15, 1, r7, c15, c2, 0 @ restore CP15 - Aux Func Modes Ctrl 0
+ mcr p15, 1, r8, c15, c1, 2 @ restore CP15 - Aux Debug Modes Ctrl 2
+ mcr p15, 1, r9, c15, c1, 1 @ restore CP15 - Aux Debug Modes Ctrl 1
+ mcr p15, 0, r10, c9, c14, 0 @ restore CP15 - PMC
b cpu_v7_do_resume
ENDPROC(cpu_pj4b_do_resume)
#endif
.globl cpu_pj4b_suspend_size
-.equ cpu_pj4b_suspend_size, 4 * 14
+.equ cpu_pj4b_suspend_size, cpu_v7_suspend_size + 4 * 5
#endif
@@ -216,6 +250,7 @@ __v7_cr7mp_setup:
__v7_ca7mp_setup:
__v7_ca12mp_setup:
__v7_ca15mp_setup:
+__v7_b15mp_setup:
__v7_ca17mp_setup:
mov r10, #0
1:
@@ -407,7 +442,7 @@ __v7_setup:
bic r0, r0, r5 @ clear bits them
orr r0, r0, r6 @ set them
THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions
- mov pc, lr @ return to head.S:__ret
+ ret lr @ return to head.S:__ret
ENDPROC(__v7_setup)
.align 2
@@ -418,6 +453,7 @@ __v7_setup_stack:
@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+ define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
#ifdef CONFIG_CPU_PJ4B
define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
#endif
@@ -470,7 +506,7 @@ __v7_ca5mp_proc_info:
__v7_ca9mp_proc_info:
.long 0x410fc090
.long 0xff0ffff0
- __v7_proc __v7_ca9mp_setup
+ __v7_proc __v7_ca9mp_setup, proc_fns = ca9mp_processor_functions
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
#endif /* CONFIG_ARM_LPAE */
@@ -528,6 +564,16 @@ __v7_ca15mp_proc_info:
.size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
/*
+ * Broadcom Corporation Brahma-B15 processor.
+ */
+ .type __v7_b15mp_proc_info, #object
+__v7_b15mp_proc_info:
+ .long 0x420f00f0
+ .long 0xff0ffff0
+ __v7_proc __v7_b15mp_setup, hwcaps = HWCAP_IDIV
+ .size __v7_b15mp_proc_info, . - __v7_b15mp_proc_info
+
+ /*
* ARM Ltd. Cortex A17 processor.
*/
.type __v7_ca17mp_proc_info, #object
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
index 1ca37c72f12f..d1e68b553d3b 100644
--- a/arch/arm/mm/proc-v7m.S
+++ b/arch/arm/mm/proc-v7m.S
@@ -16,11 +16,11 @@
#include "proc-macros.S"
ENTRY(cpu_v7m_proc_init)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_proc_init)
ENTRY(cpu_v7m_proc_fin)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_proc_fin)
/*
@@ -34,7 +34,7 @@ ENDPROC(cpu_v7m_proc_fin)
*/
.align 5
ENTRY(cpu_v7m_reset)
- mov pc, r0
+ ret r0
ENDPROC(cpu_v7m_reset)
/*
@@ -46,18 +46,18 @@ ENDPROC(cpu_v7m_reset)
*/
ENTRY(cpu_v7m_do_idle)
wfi
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_do_idle)
ENTRY(cpu_v7m_dcache_clean_area)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_dcache_clean_area)
/*
* There is no MMU, so here is nothing to do.
*/
ENTRY(cpu_v7m_switch_mm)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_switch_mm)
.globl cpu_v7m_suspend_size
@@ -65,11 +65,11 @@ ENDPROC(cpu_v7m_switch_mm)
#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_v7m_do_suspend)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_do_suspend)
ENTRY(cpu_v7m_do_resume)
- mov pc, lr
+ ret lr
ENDPROC(cpu_v7m_do_resume)
#endif
@@ -120,7 +120,7 @@ __v7m_setup:
ldr r12, [r0, V7M_SCB_CCR] @ system control register
orr r12, #V7M_SCB_CCR_STKALIGN
str r12, [r0, V7M_SCB_CCR]
- mov pc, lr
+ ret lr
ENDPROC(__v7m_setup)
.align 2
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index dc1645890042..f8acdfece036 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -83,7 +83,7 @@
* Nothing too exciting at the moment
*/
ENTRY(cpu_xsc3_proc_init)
- mov pc, lr
+ ret lr
/*
* cpu_xsc3_proc_fin()
@@ -93,7 +93,7 @@ ENTRY(cpu_xsc3_proc_fin)
bic r0, r0, #0x1800 @ ...IZ...........
bic r0, r0, #0x0006 @ .............CA.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_xsc3_reset(loc)
@@ -119,7 +119,7 @@ ENTRY(cpu_xsc3_reset)
@ CAUTION: MMU turned off from this point. We count on the pipeline
@ already containing those two last instructions to survive.
mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
- mov pc, r0
+ ret r0
ENDPROC(cpu_xsc3_reset)
.popsection
@@ -138,7 +138,7 @@ ENDPROC(cpu_xsc3_reset)
ENTRY(cpu_xsc3_do_idle)
mov r0, #1
mcr p14, 0, r0, c7, c0, 0 @ go to idle
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -150,7 +150,7 @@ ENTRY(cpu_xsc3_do_idle)
ENTRY(xsc3_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(xsc3_flush_icache_all)
/*
@@ -176,7 +176,7 @@ __flush_whole_cache:
mcrne p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB
mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, vm_flags)
@@ -205,7 +205,7 @@ ENTRY(xsc3_flush_user_cache_range)
mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -232,7 +232,7 @@ ENTRY(xsc3_coherent_user_range)
mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -253,7 +253,7 @@ ENTRY(xsc3_flush_kern_dcache_area)
mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -277,7 +277,7 @@ xsc3_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -294,7 +294,7 @@ xsc3_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -311,7 +311,7 @@ ENTRY(xsc3_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ data write barrier
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -334,7 +334,7 @@ ENDPROC(xsc3_dma_map_area)
* - dir - DMA direction
*/
ENTRY(xsc3_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(xsc3_dma_unmap_area)
.globl xsc3_flush_kern_cache_louis
@@ -348,7 +348,7 @@ ENTRY(cpu_xsc3_dcache_clean_area)
add r0, r0, #CACHELINESIZE
subs r1, r1, #CACHELINESIZE
bhi 1b
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -406,7 +406,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
orr r2, r2, ip
xscale_set_pte_ext_epilogue
- mov pc, lr
+ ret lr
.ltorg
.align
@@ -478,7 +478,7 @@ __xsc3_setup:
bic r0, r0, r5 @ ..V. ..R. .... ..A.
orr r0, r0, r6 @ ..VI Z..S .... .C.M (mmu)
@ ...I Z..S .... .... (uc)
- mov pc, lr
+ ret lr
.size __xsc3_setup, . - __xsc3_setup
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index d19b1cfcad91..23259f104c66 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -118,7 +118,7 @@ ENTRY(cpu_xscale_proc_init)
mrc p15, 0, r1, c1, c0, 1
bic r1, r1, #1
mcr p15, 0, r1, c1, c0, 1
- mov pc, lr
+ ret lr
/*
* cpu_xscale_proc_fin()
@@ -128,7 +128,7 @@ ENTRY(cpu_xscale_proc_fin)
bic r0, r0, #0x1800 @ ...IZ...........
bic r0, r0, #0x0006 @ .............CA.
mcr p15, 0, r0, c1, c0, 0 @ disable caches
- mov pc, lr
+ ret lr
/*
* cpu_xscale_reset(loc)
@@ -160,7 +160,7 @@ ENTRY(cpu_xscale_reset)
@ CAUTION: MMU turned off from this point. We count on the pipeline
@ already containing those two last instructions to survive.
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
- mov pc, r0
+ ret r0
ENDPROC(cpu_xscale_reset)
.popsection
@@ -179,7 +179,7 @@ ENDPROC(cpu_xscale_reset)
ENTRY(cpu_xscale_do_idle)
mov r0, #1
mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE
- mov pc, lr
+ ret lr
/* ================================= CACHE ================================ */
@@ -191,7 +191,7 @@ ENTRY(cpu_xscale_do_idle)
ENTRY(xscale_flush_icache_all)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
- mov pc, lr
+ ret lr
ENDPROC(xscale_flush_icache_all)
/*
@@ -216,7 +216,7 @@ __flush_whole_cache:
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB
mcrne p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* flush_user_cache_range(start, end, vm_flags)
@@ -245,7 +245,7 @@ ENTRY(xscale_flush_user_cache_range)
tst r2, #VM_EXEC
mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB
mcrne p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* coherent_kern_range(start, end)
@@ -269,7 +269,7 @@ ENTRY(xscale_coherent_kern_range)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* coherent_user_range(start, end)
@@ -291,7 +291,7 @@ ENTRY(xscale_coherent_user_range)
mov r0, #0
mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* flush_kern_dcache_area(void *addr, size_t size)
@@ -312,7 +312,7 @@ ENTRY(xscale_flush_kern_dcache_area)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* dma_inv_range(start, end)
@@ -336,7 +336,7 @@ xscale_dma_inv_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* dma_clean_range(start, end)
@@ -353,7 +353,7 @@ xscale_dma_clean_range:
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* dma_flush_range(start, end)
@@ -371,7 +371,7 @@ ENTRY(xscale_dma_flush_range)
cmp r0, r1
blo 1b
mcr p15, 0, r0, c7, c10, 4 @ Drain Write (& Fill) Buffer
- mov pc, lr
+ ret lr
/*
* dma_map_area(start, size, dir)
@@ -407,7 +407,7 @@ ENDPROC(xscale_80200_A0_A1_dma_map_area)
* - dir - DMA direction
*/
ENTRY(xscale_dma_unmap_area)
- mov pc, lr
+ ret lr
ENDPROC(xscale_dma_unmap_area)
.globl xscale_flush_kern_cache_louis
@@ -458,7 +458,7 @@ ENTRY(cpu_xscale_dcache_clean_area)
add r0, r0, #CACHELINESIZE
subs r1, r1, #CACHELINESIZE
bhi 1b
- mov pc, lr
+ ret lr
/* =============================== PageTable ============================== */
@@ -521,7 +521,7 @@ ENTRY(cpu_xscale_set_pte_ext)
orr r2, r2, ip
xscale_set_pte_ext_epilogue
- mov pc, lr
+ ret lr
.ltorg
.align
@@ -572,7 +572,7 @@ __xscale_setup:
mrc p15, 0, r0, c1, c0, 0 @ get control register
bic r0, r0, r5
orr r0, r0, r6
- mov pc, lr
+ ret lr
.size __xscale_setup, . - __xscale_setup
/*
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S
index d3ddcf9a76ca..d2d9ecbe0aac 100644
--- a/arch/arm/mm/tlb-fa.S
+++ b/arch/arm/mm/tlb-fa.S
@@ -18,6 +18,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
@@ -37,7 +38,7 @@ ENTRY(fa_flush_user_tlb_range)
vma_vm_mm ip, r2
act_mm r3 @ get current->active_mm
eors r3, ip, r3 @ == mm ?
- movne pc, lr @ no, we dont do anything
+ retne lr @ no, we dont do anything
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
bic r0, r0, #0x0ff
@@ -47,7 +48,7 @@ ENTRY(fa_flush_user_tlb_range)
cmp r0, r1
blo 1b
mcr p15, 0, r3, c7, c10, 4 @ data write barrier
- mov pc, lr
+ ret lr
ENTRY(fa_flush_kern_tlb_range)
@@ -61,7 +62,7 @@ ENTRY(fa_flush_kern_tlb_range)
blo 1b
mcr p15, 0, r3, c7, c10, 4 @ data write barrier
mcr p15, 0, r3, c7, c5, 4 @ prefetch flush (isb)
- mov pc, lr
+ ret lr
__INITDATA
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index 17a025ade573..a2b5dca42048 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -14,6 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
@@ -33,7 +34,7 @@ ENTRY(v4_flush_user_tlb_range)
vma_vm_mm ip, r2
act_mm r3 @ get current->active_mm
eors r3, ip, r3 @ == mm ?
- movne pc, lr @ no, we dont do anything
+ retne lr @ no, we dont do anything
.v4_flush_kern_tlb_range:
bic r0, r0, #0x0ff
bic r0, r0, #0xf00
@@ -41,7 +42,7 @@ ENTRY(v4_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
/*
* v4_flush_kern_tlb_range(start, end)
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index c04598fa4d4a..5a093b458dbc 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -14,6 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
@@ -33,7 +34,7 @@ ENTRY(v4wb_flush_user_tlb_range)
vma_vm_mm ip, r2
act_mm r3 @ get current->active_mm
eors r3, ip, r3 @ == mm ?
- movne pc, lr @ no, we dont do anything
+ retne lr @ no, we dont do anything
vma_vm_flags r2, r2
mcr p15, 0, r3, c7, c10, 4 @ drain WB
tst r2, #VM_EXEC
@@ -44,7 +45,7 @@ ENTRY(v4wb_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
/*
* v4_flush_kern_tlb_range(start, end)
@@ -65,7 +66,7 @@ ENTRY(v4wb_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
__INITDATA
diff --git a/arch/arm/mm/tlb-v4wbi.S b/arch/arm/mm/tlb-v4wbi.S
index 1f6062b6c1c1..058861548f68 100644
--- a/arch/arm/mm/tlb-v4wbi.S
+++ b/arch/arm/mm/tlb-v4wbi.S
@@ -14,6 +14,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
#include <asm/asm-offsets.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
@@ -32,7 +33,7 @@ ENTRY(v4wbi_flush_user_tlb_range)
vma_vm_mm ip, r2
act_mm r3 @ get current->active_mm
eors r3, ip, r3 @ == mm ?
- movne pc, lr @ no, we dont do anything
+ retne lr @ no, we dont do anything
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
vma_vm_flags r2, r2
@@ -44,7 +45,7 @@ ENTRY(v4wbi_flush_user_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
ENTRY(v4wbi_flush_kern_tlb_range)
mov r3, #0
@@ -56,7 +57,7 @@ ENTRY(v4wbi_flush_kern_tlb_range)
add r0, r0, #PAGE_SZ
cmp r0, r1
blo 1b
- mov pc, lr
+ ret lr
__INITDATA
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index eca07f550a0b..6f689be638bd 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
#include <asm/page.h>
#include <asm/tlbflush.h>
#include "proc-macros.S"
@@ -55,7 +56,7 @@ ENTRY(v6wbi_flush_user_tlb_range)
cmp r0, r1
blo 1b
mcr p15, 0, ip, c7, c10, 4 @ data synchronization barrier
- mov pc, lr
+ ret lr
/*
* v6wbi_flush_kern_tlb_range(start,end)
@@ -84,7 +85,7 @@ ENTRY(v6wbi_flush_kern_tlb_range)
blo 1b
mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier
mcr p15, 0, r2, c7, c5, 4 @ prefetch flush (isb)
- mov pc, lr
+ ret lr
__INIT
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 355308767bae..e5101a3bc57c 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -57,7 +57,7 @@ ENTRY(v7wbi_flush_user_tlb_range)
cmp r0, r1
blo 1b
dsb ish
- mov pc, lr
+ ret lr
ENDPROC(v7wbi_flush_user_tlb_range)
/*
@@ -86,7 +86,7 @@ ENTRY(v7wbi_flush_kern_tlb_range)
blo 1b
dsb ish
isb
- mov pc, lr
+ ret lr
ENDPROC(v7wbi_flush_kern_tlb_range)
__INIT
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index fb5503ce016f..a37b989a2f91 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -56,7 +56,7 @@
#define FLAG_NEED_X_RESET (1 << 0)
struct jit_ctx {
- const struct sk_filter *skf;
+ const struct bpf_prog *skf;
unsigned idx;
unsigned prologue_bytes;
int ret0_fp_idx;
@@ -465,7 +465,7 @@ static inline void update_on_xread(struct jit_ctx *ctx)
static int build_body(struct jit_ctx *ctx)
{
void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
- const struct sk_filter *prog = ctx->skf;
+ const struct bpf_prog *prog = ctx->skf;
const struct sock_filter *inst;
unsigned i, load_order, off, condt;
int imm12;
@@ -857,7 +857,7 @@ b_epilogue:
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct jit_ctx ctx;
unsigned tmp_idx;
@@ -926,7 +926,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index d18dde95b8aa..5d65be1f1e8a 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -19,7 +19,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#include <asm/assembler.h>
#include <asm/opcodes.h>
/* This is the kernel's entry point into the floating point emulator.
@@ -92,7 +92,7 @@ emulate:
mov r0, r6 @ prepare for EmulateAll()
bl EmulateAll @ emulate the instruction
cmp r0, #0 @ was emulation successful
- moveq pc, r4 @ no, return failure
+ reteq r4 @ no, return failure
next:
.Lx1: ldrt r6, [r5], #4 @ get the next instruction and
@@ -102,7 +102,7 @@ next:
teq r2, #0x0C000000
teqne r2, #0x0D000000
teqne r2, #0x0E000000
- movne pc, r9 @ return ok if not a fp insn
+ retne r9 @ return ok if not a fp insn
str r5, [sp, #S_PC] @ update PC copy in regs
@@ -115,7 +115,7 @@ next:
@ plain LDR instruction. Weird, but it seems harmless.
.pushsection .fixup,"ax"
.align 2
-.Lfix: mov pc, r9 @ let the user eat segfaults
+.Lfix: ret r9 @ let the user eat segfaults
.popsection
.pushsection __ex_table,"a"
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index 99c63d4b6af8..cc649a1e46da 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -33,12 +33,14 @@ static struct op_perf_name {
char *perf_name;
char *op_name;
} op_perf_name_map[] = {
- { "xscale1", "arm/xscale1" },
- { "xscale1", "arm/xscale2" },
- { "v6", "arm/armv6" },
- { "v6mpcore", "arm/mpcore" },
- { "ARMv7 Cortex-A8", "arm/armv7" },
- { "ARMv7 Cortex-A9", "arm/armv7-ca9" },
+ { "armv5_xscale1", "arm/xscale1" },
+ { "armv5_xscale2", "arm/xscale2" },
+ { "armv6_1136", "arm/armv6" },
+ { "armv6_1156", "arm/armv6" },
+ { "armv6_1176", "arm/armv6" },
+ { "armv6_11mpcore", "arm/mpcore" },
+ { "armv7_cortex_a8", "arm/armv7" },
+ { "armv7_cortex_a9", "arm/armv7-ca9" },
};
char *op_name_from_perf_id(void)
@@ -107,10 +109,7 @@ static void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
if (!user_mode(regs)) {
struct stackframe frame;
- frame.fp = regs->ARM_fp;
- frame.sp = regs->ARM_sp;
- frame.lr = regs->ARM_lr;
- frame.pc = regs->ARM_pc;
+ arm_get_current_stackframe(regs, &frame);
walk_stackframe(&frame, report_trace, &depth);
return;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index b5608b1f9fbd..c2baa8ede543 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -698,6 +698,8 @@ int omap_request_dma(int dev_id, const char *dev_name,
unsigned long flags;
struct omap_dma_lch *chan;
+ WARN(strcmp(dev_name, "DMA engine"), "Using deprecated platform DMA API - please update to DMA engine");
+
spin_lock_irqsave(&dma_chan_lock, flags);
for (ch = 0; ch < dma_chan_count; ch++) {
if (free_ch == -1 && dma_chan[ch].dev_id == -1) {
@@ -2100,7 +2102,7 @@ static int omap_system_dma_probe(struct platform_device *pdev)
omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
DMA_DEFAULT_FIFO_DEPTH, 0);
- if (dma_omap2plus()) {
+ if (dma_omap2plus() && !(d->dev_caps & DMA_ENGINE_HANDLE_IRQ)) {
strcpy(irq_name, "0");
dma_irq = platform_get_irq_byname(pdev, irq_name);
if (dma_irq < 0) {
@@ -2145,7 +2147,8 @@ static int omap_system_dma_remove(struct platform_device *pdev)
char irq_name[4];
strcpy(irq_name, "0");
dma_irq = platform_get_irq_byname(pdev, irq_name);
- remove_irq(dma_irq, &omap24xx_dma_irq);
+ if (dma_irq >= 0)
+ remove_irq(dma_irq, &omap24xx_dma_irq);
} else {
int irq_rel = 0;
for ( ; irq_rel < dma_chan_count; irq_rel++) {
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 301b892d97d9..c87aefbf3a13 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -6,30 +6,16 @@
config PLAT_SAMSUNG
bool
- depends on PLAT_S3C24XX || ARCH_S3C64XX || PLAT_S5P || ARCH_EXYNOS
+ depends on PLAT_S3C24XX || ARCH_S3C64XX || ARCH_EXYNOS || ARCH_S5PV210
default y
select GENERIC_IRQ_CHIP
select NO_IOPORT_MAP
help
Base platform code for all Samsung SoC based systems
-config PLAT_S5P
- bool
- depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
- default y
- select ARCH_REQUIRE_GPIOLIB
- select ARM_VIC
- select NO_IOPORT_MAP
- select PLAT_SAMSUNG
- select S3C_GPIO_TRACK
- select S5P_GPIO_DRVSTR
- select SAMSUNG_CLKSRC if !COMMON_CLK
- help
- Base platform code for Samsung's S5P series SoC.
-
config SAMSUNG_PM
bool
- depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || S5P_PM)
+ depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX)
default y
help
Base platform power management code for samsung code
@@ -65,65 +51,6 @@ config SAMSUNG_ATAGS
if SAMSUNG_ATAGS
-# clock options
-
-config SAMSUNG_CLOCK
- bool
- default y if !COMMON_CLK
-
-config SAMSUNG_CLKSRC
- bool
- help
- Select the clock code for the clksrc implementation
- used by newer systems such as the S3C64XX.
-
-config S5P_CLOCK
- def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
- help
- Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
-
-# options for IRQ support
-
-config S5P_IRQ
- def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
- help
- Support common interrupt part for ARCH_S5P SoCs
-
-config S5P_EXT_INT
- bool
- help
- Use the external interrupts (other than GPIO interrupts.)
- Note: Do not choose this for S5P6440 and S5P6450.
-
-config S5P_GPIO_INT
- bool
- help
- Common code for the GPIO interrupts (other than external interrupts.)
-
-# options for gpio configuration support
-
-config S5P_GPIO_DRVSTR
- bool
- help
- Internal configuration to get and set correct GPIO driver strength
- helper
-
-config SAMSUNG_GPIO_EXTRA
- int "Number of additional GPIO pins"
- default 128 if SAMSUNG_GPIO_EXTRA128
- default 64 if SAMSUNG_GPIO_EXTRA64
- default 0
- help
- Use additional GPIO space in addition to the GPIO's the SOC
- provides. This allows expanding the GPIO space for use with
- GPIO expanders.
-
-config SAMSUNG_GPIO_EXTRA64
- bool
-
-config SAMSUNG_GPIO_EXTRA128
- bool
-
config S3C_GPIO_SPACE
int "Space between gpio banks"
default 0
@@ -139,12 +66,6 @@ config S3C_GPIO_TRACK
Internal configuration option to enable the s3c specific gpio
chip tracking if the platform requires it.
-# uart options
-
-config S5P_DEV_UART
- def_bool y
- depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
-
# ADC driver
config S3C_ADC
@@ -302,66 +223,6 @@ config SAMSUNG_DEV_BACKLIGHT
help
Compile in platform device definition LCD backlight with PWM Timer
-config S5P_DEV_CSIS0
- bool
- help
- Compile in platform device definitions for MIPI-CSIS channel 0
-
-config S5P_DEV_CSIS1
- bool
- help
- Compile in platform device definitions for MIPI-CSIS channel 1
-
-config S5P_DEV_FIMC0
- bool
- help
- Compile in platform device definitions for FIMC controller 0
-
-config S5P_DEV_FIMC1
- bool
- help
- Compile in platform device definitions for FIMC controller 1
-
-config S5P_DEV_FIMC2
- bool
- help
- Compile in platform device definitions for FIMC controller 2
-
-config S5P_DEV_FIMC3
- bool
- help
- Compile in platform device definitions for FIMC controller 3
-
-config S5P_DEV_FIMD0
- bool
- help
- Compile in platform device definitions for FIMD controller 0
-
-config S5P_DEV_G2D
- bool
- help
- Compile in platform device definitions for G2D device
-
-config S5P_DEV_I2C_HDMIPHY
- bool
- help
- Compile in platform device definitions for I2C HDMIPHY controller
-
-config S5P_DEV_JPEG
- bool
- help
- Compile in platform device definitions for JPEG codec
-
-config S5P_DEV_ONENAND
- bool
- help
- Compile in platform device definition for OneNAND controller
-
-config S5P_DEV_TV
- bool
- help
- Compile in platform device definition for TV interface
-
config S3C24XX_PWM
bool "PWM device support"
select PWM
@@ -382,12 +243,6 @@ config S3C_DMA
help
Internal configuration for S3C DMA core
-config S5P_IRQ_PM
- bool
- default y if S5P_PM
- help
- Legacy IRQ power management for S5P platforms
-
config SAMSUNG_PM_GPIO
bool
default y if GPIO_SAMSUNG && PM
@@ -397,7 +252,7 @@ config SAMSUNG_PM_GPIO
config SAMSUNG_DMADEV
bool "Use legacy Samsung DMA abstraction"
- depends on CPU_S5PV210 || CPU_S5PC100 || ARCH_S5P64X0 || ARCH_S3C64XX
+ depends on CPU_S5PV210 || ARCH_S3C64XX
select DMADEVICES
default y
help
@@ -470,18 +325,6 @@ config SAMSUNG_WDT_RESET
Compile support for system restart by triggering watchdog reset.
Used on SoCs that do not provide dedicated reset control.
-config S5P_PM
- bool
- help
- Common code for power management support on S5P and newer SoCs
- Note: Do not select this for S5P6440 and S5P6450.
-
-config S5P_SLEEP
- bool
- help
- Internal config node to apply common S5P sleep management code.
- Can be selected by S5P and newer SoCs with similar sleep procedure.
-
config DEBUG_S3C_UART
depends on PLAT_SAMSUNG
int
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 5e5beaa9ae15..5fe175017f07 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -5,7 +5,6 @@
# Licensed under GPLv2
ccflags-$(CONFIG_ARCH_MULTI_V7) += -I$(srctree)/$(src)/include
-ccflags-$(CONFIG_ARCH_EXYNOS) += -I$(srctree)/arch/arm/mach-exynos/include
obj-y :=
obj-m :=
@@ -16,15 +15,6 @@ obj- :=
obj-y += init.o cpu.o
-obj-$(CONFIG_SAMSUNG_CLOCK) += clock.o
-
-obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
-obj-$(CONFIG_S5P_CLOCK) += s5p-clock.o
-
-obj-$(CONFIG_S5P_IRQ) += s5p-irq.o
-obj-$(CONFIG_S5P_EXT_INT) += s5p-irq-eint.o
-obj-$(CONFIG_S5P_GPIO_INT) += s5p-irq-gpioint.o
-
# ADC
obj-$(CONFIG_S3C_ADC) += adc.o
@@ -36,7 +26,6 @@ obj-$(CONFIG_SAMSUNG_ATAGS) += platformdata.o
obj-$(CONFIG_SAMSUNG_ATAGS) += devs.o
obj-$(CONFIG_SAMSUNG_ATAGS) += dev-uart.o
obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o
-obj-$(CONFIG_S5P_DEV_UART) += s5p-dev-uart.o
obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
@@ -58,7 +47,3 @@ obj-$(CONFIG_SAMSUNG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o
obj-$(CONFIG_SAMSUNG_WDT_RESET) += watchdog-reset.o
-
-obj-$(CONFIG_S5P_PM) += s5p-pm.o
-obj-$(CONFIG_S5P_IRQ_PM) += s5p-irq-pm.o
-obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 79690f2f6d3f..468352633101 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -43,7 +43,7 @@ enum s3c_cpu_type {
TYPE_ADCV1, /* S3C24XX */
TYPE_ADCV11, /* S3C2443 */
TYPE_ADCV12, /* S3C2416, S3C2450 */
- TYPE_ADCV2, /* S3C64XX, S5P64X0, S5PC100 */
+ TYPE_ADCV2, /* S3C64XX */
TYPE_ADCV3, /* S5PV210, S5PC110, EXYNOS4210 */
};
diff --git a/arch/arm/plat-samsung/clock-clksrc.c b/arch/arm/plat-samsung/clock-clksrc.c
deleted file mode 100644
index 786a4107a157..000000000000
--- a/arch/arm/plat-samsung/clock-clksrc.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* linux/arch/arm/plat-samsung/clock-clksrc.c
- *
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/cpu-freq.h>
-
-static inline struct clksrc_clk *to_clksrc(struct clk *clk)
-{
- return container_of(clk, struct clksrc_clk, clk);
-}
-
-static inline u32 bit_mask(u32 shift, u32 nr_bits)
-{
- u32 mask = 0xffffffff >> (32 - nr_bits);
-
- return mask << shift;
-}
-
-static unsigned long s3c_getrate_clksrc(struct clk *clk)
-{
- struct clksrc_clk *sclk = to_clksrc(clk);
- unsigned long rate = clk_get_rate(clk->parent);
- u32 clkdiv = __raw_readl(sclk->reg_div.reg);
- u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
-
- clkdiv &= mask;
- clkdiv >>= sclk->reg_div.shift;
- clkdiv++;
-
- rate /= clkdiv;
- return rate;
-}
-
-static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate)
-{
- struct clksrc_clk *sclk = to_clksrc(clk);
- void __iomem *reg = sclk->reg_div.reg;
- unsigned int div;
- u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
- u32 val;
-
- rate = clk_round_rate(clk, rate);
- div = clk_get_rate(clk->parent) / rate;
- if (div > (1 << sclk->reg_div.size))
- return -EINVAL;
-
- val = __raw_readl(reg);
- val &= ~mask;
- val |= (div - 1) << sclk->reg_div.shift;
- __raw_writel(val, reg);
-
- return 0;
-}
-
-static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent)
-{
- struct clksrc_clk *sclk = to_clksrc(clk);
- struct clksrc_sources *srcs = sclk->sources;
- u32 clksrc = __raw_readl(sclk->reg_src.reg);
- u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size);
- int src_nr = -1;
- int ptr;
-
- for (ptr = 0; ptr < srcs->nr_sources; ptr++)
- if (srcs->sources[ptr] == parent) {
- src_nr = ptr;
- break;
- }
-
- if (src_nr >= 0) {
- clk->parent = parent;
-
- clksrc &= ~mask;
- clksrc |= src_nr << sclk->reg_src.shift;
-
- __raw_writel(clksrc, sclk->reg_src.reg);
- return 0;
- }
-
- return -EINVAL;
-}
-
-static unsigned long s3c_roundrate_clksrc(struct clk *clk,
- unsigned long rate)
-{
- struct clksrc_clk *sclk = to_clksrc(clk);
- unsigned long parent_rate = clk_get_rate(clk->parent);
- int max_div = 1 << sclk->reg_div.size;
- int div;
-
- if (rate >= parent_rate)
- rate = parent_rate;
- else {
- div = parent_rate / rate;
- if (parent_rate % rate)
- div++;
-
- if (div == 0)
- div = 1;
- if (div > max_div)
- div = max_div;
-
- rate = parent_rate / div;
- }
-
- return rate;
-}
-
-/* Clock initialisation code */
-
-void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce)
-{
- struct clksrc_sources *srcs = clk->sources;
- u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size);
- u32 clksrc;
-
- if (!clk->reg_src.reg) {
- if (!clk->clk.parent)
- printk(KERN_ERR "%s: no parent clock specified\n",
- clk->clk.name);
- return;
- }
-
- clksrc = __raw_readl(clk->reg_src.reg);
- clksrc &= mask;
- clksrc >>= clk->reg_src.shift;
-
- if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
- printk(KERN_ERR "%s: bad source %d\n",
- clk->clk.name, clksrc);
- return;
- }
-
- clk->clk.parent = srcs->sources[clksrc];
-
- if (announce)
- printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
- clk->clk.name, clk->clk.parent->name, clksrc,
- clk_get_rate(&clk->clk));
-}
-
-static struct clk_ops clksrc_ops = {
- .set_parent = s3c_setparent_clksrc,
- .get_rate = s3c_getrate_clksrc,
- .set_rate = s3c_setrate_clksrc,
- .round_rate = s3c_roundrate_clksrc,
-};
-
-static struct clk_ops clksrc_ops_nodiv = {
- .set_parent = s3c_setparent_clksrc,
-};
-
-static struct clk_ops clksrc_ops_nosrc = {
- .get_rate = s3c_getrate_clksrc,
- .set_rate = s3c_setrate_clksrc,
- .round_rate = s3c_roundrate_clksrc,
-};
-
-void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
-{
- int ret;
-
- for (; size > 0; size--, clksrc++) {
- if (!clksrc->reg_div.reg && !clksrc->reg_src.reg)
- printk(KERN_ERR "%s: clock %s has no registers set\n",
- __func__, clksrc->clk.name);
-
- /* fill in the default functions */
-
- if (!clksrc->clk.ops) {
- if (!clksrc->reg_div.reg)
- clksrc->clk.ops = &clksrc_ops_nodiv;
- else if (!clksrc->reg_src.reg)
- clksrc->clk.ops = &clksrc_ops_nosrc;
- else
- clksrc->clk.ops = &clksrc_ops;
- }
-
- /* setup the clocksource, but do not announce it
- * as it may be re-set by the setup routines
- * called after the rest of the clocks have been
- * registered
- */
- s3c_set_clksrc(clksrc, false);
-
- ret = s3c24xx_register_clock(&clksrc->clk);
-
- if (ret < 0) {
- printk(KERN_ERR "%s: failed to register %s (%d)\n",
- __func__, clksrc->clk.name, ret);
- }
- }
-}
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
deleted file mode 100644
index d103ac1a52af..000000000000
--- a/arch/arm/plat-samsung/clock.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/clock.c
- *
- * Copyright 2004-2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- ** Copyright (C) 2004 ARM Limited.
- ** Written by Deep Blue Solutions Limited.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#if defined(CONFIG_DEBUG_FS)
-#include <linux/debugfs.h>
-#endif
-
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-#include <linux/serial_core.h>
-#include <linux/serial_s3c.h> /* for s3c24xx_uart_devs */
-
-/* clock information */
-
-static LIST_HEAD(clocks);
-
-/* We originally used an mutex here, but some contexts (see resume)
- * are calling functions such as clk_set_parent() with IRQs disabled
- * causing an BUG to be triggered.
- */
-DEFINE_SPINLOCK(clocks_lock);
-
-/* Global watchdog clock used by arch_wtd_reset() callback */
-struct clk *s3c2410_wdtclk;
-static int __init s3c_wdt_reset_init(void)
-{
- s3c2410_wdtclk = clk_get(NULL, "watchdog");
- if (IS_ERR(s3c2410_wdtclk))
- printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
- return 0;
-}
-arch_initcall(s3c_wdt_reset_init);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
-{
- return 0;
-}
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- if (IS_ERR(clk) || clk == NULL)
- return -EINVAL;
-
- clk_enable(clk->parent);
-
- spin_lock_irqsave(&clocks_lock, flags);
-
- if ((clk->usage++) == 0)
- (clk->enable)(clk, 1);
-
- spin_unlock_irqrestore(&clocks_lock, flags);
- return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- if (IS_ERR(clk) || clk == NULL)
- return;
-
- spin_lock_irqsave(&clocks_lock, flags);
-
- if ((--clk->usage) == 0)
- (clk->enable)(clk, 0);
-
- spin_unlock_irqrestore(&clocks_lock, flags);
- clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- if (IS_ERR_OR_NULL(clk))
- return 0;
-
- if (clk->rate != 0)
- return clk->rate;
-
- if (clk->ops != NULL && clk->ops->get_rate != NULL)
- return (clk->ops->get_rate)(clk);
-
- if (clk->parent != NULL)
- return clk_get_rate(clk->parent);
-
- return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
- return (clk->ops->round_rate)(clk, rate);
-
- return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long flags;
- int ret;
-
- if (IS_ERR_OR_NULL(clk))
- return -EINVAL;
-
- /* We do not default just do a clk->rate = rate as
- * the clock may have been made this way by choice.
- */
-
- WARN_ON(clk->ops == NULL);
- WARN_ON(clk->ops && clk->ops->set_rate == NULL);
-
- if (clk->ops == NULL || clk->ops->set_rate == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(&clocks_lock, flags);
- ret = (clk->ops->set_rate)(clk, rate);
- spin_unlock_irqrestore(&clocks_lock, flags);
-
- return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
-{
- return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- unsigned long flags;
- int ret = 0;
-
- if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
- return -EINVAL;
-
- spin_lock_irqsave(&clocks_lock, flags);
-
- if (clk->ops && clk->ops->set_parent)
- ret = (clk->ops->set_parent)(clk, parent);
-
- spin_unlock_irqrestore(&clocks_lock, flags);
-
- return ret;
-}
-
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-int clk_default_setrate(struct clk *clk, unsigned long rate)
-{
- clk->rate = rate;
- return 0;
-}
-
-struct clk_ops clk_ops_def_setrate = {
- .set_rate = clk_default_setrate,
-};
-
-struct clk clk_xtal = {
- .name = "xtal",
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_ext = {
- .name = "ext",
-};
-
-struct clk clk_epll = {
- .name = "epll",
-};
-
-struct clk clk_mpll = {
- .name = "mpll",
- .ops = &clk_ops_def_setrate,
-};
-
-struct clk clk_upll = {
- .name = "upll",
- .parent = NULL,
- .ctrlbit = 0,
-};
-
-struct clk clk_f = {
- .name = "fclk",
- .rate = 0,
- .parent = &clk_mpll,
- .ctrlbit = 0,
-};
-
-struct clk clk_h = {
- .name = "hclk",
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
- .ops = &clk_ops_def_setrate,
-};
-
-struct clk clk_p = {
- .name = "pclk",
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
- .ops = &clk_ops_def_setrate,
-};
-
-struct clk clk_usb_bus = {
- .name = "usb-bus",
- .rate = 0,
- .parent = &clk_upll,
-};
-
-
-struct clk s3c24xx_uclk = {
- .name = "uclk",
-};
-
-/* initialise the clock system */
-
-/**
- * s3c24xx_register_clock() - register a clock
- * @clk: The clock to register
- *
- * Add the specified clock to the list of clocks known by the system.
- */
-int s3c24xx_register_clock(struct clk *clk)
-{
- if (clk->enable == NULL)
- clk->enable = clk_null_enable;
-
- /* fill up the clk_lookup structure and register it*/
- clk->lookup.dev_id = clk->devname;
- clk->lookup.con_id = clk->name;
- clk->lookup.clk = clk;
- clkdev_add(&clk->lookup);
-
- return 0;
-}
-
-/**
- * s3c24xx_register_clocks() - register an array of clock pointers
- * @clks: Pointer to an array of struct clk pointers
- * @nr_clks: The number of clocks in the @clks array.
- *
- * Call s3c24xx_register_clock() for all the clock pointers contained
- * in the @clks list. Returns the number of failures.
- */
-int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
-{
- int fails = 0;
-
- for (; nr_clks > 0; nr_clks--, clks++) {
- if (s3c24xx_register_clock(*clks) < 0) {
- struct clk *clk = *clks;
- printk(KERN_ERR "%s: failed to register %p: %s\n",
- __func__, clk, clk->name);
- fails++;
- }
- }
-
- return fails;
-}
-
-/**
- * s3c_register_clocks() - register an array of clocks
- * @clkp: Pointer to the first clock in the array.
- * @nr_clks: Number of clocks to register.
- *
- * Call s3c24xx_register_clock() on the @clkp array given, printing an
- * error if it fails to register the clock (unlikely).
- */
-void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
-{
- int ret;
-
- for (; nr_clks > 0; nr_clks--, clkp++) {
- ret = s3c24xx_register_clock(clkp);
-
- if (ret < 0) {
- printk(KERN_ERR "Failed to register clock %s (%d)\n",
- clkp->name, ret);
- }
- }
-}
-
-/**
- * s3c_disable_clocks() - disable an array of clocks
- * @clkp: Pointer to the first clock in the array.
- * @nr_clks: Number of clocks to register.
- *
- * for internal use only at initialisation time. disable the clocks in the
- * @clkp array.
- */
-
-void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
-{
- for (; nr_clks > 0; nr_clks--, clkp++)
- (clkp->enable)(clkp, 0);
-}
-
-/* initialise all the clocks */
-
-int __init s3c24xx_register_baseclocks(unsigned long xtal)
-{
- printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
-
- clk_xtal.rate = xtal;
-
- /* register our clocks */
-
- if (s3c24xx_register_clock(&clk_xtal) < 0)
- printk(KERN_ERR "failed to register master xtal\n");
-
- if (s3c24xx_register_clock(&clk_mpll) < 0)
- printk(KERN_ERR "failed to register mpll clock\n");
-
- if (s3c24xx_register_clock(&clk_upll) < 0)
- printk(KERN_ERR "failed to register upll clock\n");
-
- if (s3c24xx_register_clock(&clk_f) < 0)
- printk(KERN_ERR "failed to register cpu fclk\n");
-
- if (s3c24xx_register_clock(&clk_h) < 0)
- printk(KERN_ERR "failed to register cpu hclk\n");
-
- if (s3c24xx_register_clock(&clk_p) < 0)
- printk(KERN_ERR "failed to register cpu pclk\n");
-
- return 0;
-}
-
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-/* debugfs support to trace clock tree hierarchy and attributes */
-
-static struct dentry *clk_debugfs_root;
-
-static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
-{
- struct clk *child;
- const char *state;
- char buf[255] = { 0 };
- int n = 0;
-
- if (c->name)
- n = snprintf(buf, sizeof(buf) - 1, "%s", c->name);
-
- if (c->devname)
- n += snprintf(buf + n, sizeof(buf) - 1 - n, ":%s", c->devname);
-
- state = (c->usage > 0) ? "on" : "off";
-
- seq_printf(s, "%*s%-*s %-6s %-3d %-10lu\n",
- level * 3 + 1, "",
- 50 - level * 3, buf,
- state, c->usage, clk_get_rate(c));
-
- list_for_each_entry(child, &clocks, list) {
- if (child->parent != c)
- continue;
-
- clock_tree_show_one(s, child, level + 1);
- }
-}
-
-static int clock_tree_show(struct seq_file *s, void *data)
-{
- struct clk *c;
- unsigned long flags;
-
- seq_printf(s, " clock state ref rate\n");
- seq_printf(s, "----------------------------------------------------\n");
-
- spin_lock_irqsave(&clocks_lock, flags);
-
- list_for_each_entry(c, &clocks, list)
- if (c->parent == NULL)
- clock_tree_show_one(s, c, 0);
-
- spin_unlock_irqrestore(&clocks_lock, flags);
- return 0;
-}
-
-static int clock_tree_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clock_tree_show, inode->i_private);
-}
-
-static const struct file_operations clock_tree_fops = {
- .open = clock_tree_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int clock_rate_show(void *data, u64 *val)
-{
- struct clk *c = data;
- *val = clk_get_rate(c);
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_rate_show, NULL, "%llu\n");
-
-static int clk_debugfs_register_one(struct clk *c)
-{
- int err;
- struct dentry *d;
- struct clk *pa = c->parent;
- char s[255];
- char *p = s;
-
- p += sprintf(p, "%s", c->devname);
-
- d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
- if (!d)
- return -ENOMEM;
-
- c->dent = d;
-
- d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
-
- d = debugfs_create_file("rate", S_IRUGO, c->dent, c, &clock_rate_fops);
- if (!d) {
- err = -ENOMEM;
- goto err_out;
- }
- return 0;
-
-err_out:
- debugfs_remove_recursive(c->dent);
- return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
- int err;
- struct clk *pa = c->parent;
-
- if (pa && !pa->dent) {
- err = clk_debugfs_register(pa);
- if (err)
- return err;
- }
-
- if (!c->dent) {
- err = clk_debugfs_register_one(c);
- if (err)
- return err;
- }
- return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
- struct clk *c;
- struct dentry *d;
- int err = -ENOMEM;
-
- d = debugfs_create_dir("clock", NULL);
- if (!d)
- return -ENOMEM;
- clk_debugfs_root = d;
-
- d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
- &clock_tree_fops);
- if (!d)
- goto err_out;
-
- list_for_each_entry(c, &clocks, list) {
- err = clk_debugfs_register(c);
- if (err)
- goto err_out;
- }
- return 0;
-
-err_out:
- debugfs_remove_recursive(clk_debugfs_root);
- return err;
-}
-late_initcall(clk_debugfs_init);
-
-#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c
index 364963a0a344..360618ee39e5 100644
--- a/arch/arm/plat-samsung/cpu.c
+++ b/arch/arm/plat-samsung/cpu.c
@@ -15,8 +15,7 @@
#include <linux/init.h>
#include <linux/io.h>
-
-#include <mach/map.h>
+#include <plat/map-base.h>
#include <plat/cpu.h>
unsigned long samsung_cpu_id;
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index ead4f1c94058..83c7d154bde0 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -53,7 +53,6 @@
#include <linux/platform_data/ata-samsung_cf.h>
#include <plat/fb.h>
#include <plat/fb-s3c2410.h>
-#include <plat/hdmi.h>
#include <linux/platform_data/hwmon-s3c.h>
#include <linux/platform_data/i2c-s3c2410.h>
#include <plat/keypad.h>
@@ -145,23 +144,6 @@ struct platform_device s3c_device_camif = {
};
#endif /* CONFIG_CPU_S3C2440 */
-/* ASOC DMA */
-
-#ifdef CONFIG_PLAT_S5P
-static struct resource samsung_asoc_idma_resource = DEFINE_RES_IRQ(IRQ_I2S0);
-
-struct platform_device samsung_asoc_idma = {
- .name = "samsung-idma",
- .id = -1,
- .num_resources = 1,
- .resource = &samsung_asoc_idma_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- }
-};
-#endif
-
/* FB */
#ifdef CONFIG_S3C_DEV_FB
@@ -190,151 +172,6 @@ void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
}
#endif /* CONFIG_S3C_DEV_FB */
-/* FIMC */
-
-#ifdef CONFIG_S5P_DEV_FIMC0
-static struct resource s5p_fimc0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_FIMC0, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_FIMC0),
-};
-
-struct platform_device s5p_device_fimc0 = {
- .name = "s5p-fimc",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p_fimc0_resource),
- .resource = s5p_fimc0_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-struct platform_device s5p_device_fimc_md = {
- .name = "s5p-fimc-md",
- .id = -1,
-};
-#endif /* CONFIG_S5P_DEV_FIMC0 */
-
-#ifdef CONFIG_S5P_DEV_FIMC1
-static struct resource s5p_fimc1_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_FIMC1, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_FIMC1),
-};
-
-struct platform_device s5p_device_fimc1 = {
- .name = "s5p-fimc",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5p_fimc1_resource),
- .resource = s5p_fimc1_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#endif /* CONFIG_S5P_DEV_FIMC1 */
-
-#ifdef CONFIG_S5P_DEV_FIMC2
-static struct resource s5p_fimc2_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_FIMC2, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_FIMC2),
-};
-
-struct platform_device s5p_device_fimc2 = {
- .name = "s5p-fimc",
- .id = 2,
- .num_resources = ARRAY_SIZE(s5p_fimc2_resource),
- .resource = s5p_fimc2_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#endif /* CONFIG_S5P_DEV_FIMC2 */
-
-#ifdef CONFIG_S5P_DEV_FIMC3
-static struct resource s5p_fimc3_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_FIMC3, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_FIMC3),
-};
-
-struct platform_device s5p_device_fimc3 = {
- .name = "s5p-fimc",
- .id = 3,
- .num_resources = ARRAY_SIZE(s5p_fimc3_resource),
- .resource = s5p_fimc3_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#endif /* CONFIG_S5P_DEV_FIMC3 */
-
-/* G2D */
-
-#ifdef CONFIG_S5P_DEV_G2D
-static struct resource s5p_g2d_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_G2D, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_2D),
-};
-
-struct platform_device s5p_device_g2d = {
- .name = "s5p-g2d",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p_g2d_resource),
- .resource = s5p_g2d_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#endif /* CONFIG_S5P_DEV_G2D */
-
-#ifdef CONFIG_S5P_DEV_JPEG
-static struct resource s5p_jpeg_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_JPEG, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_JPEG),
-};
-
-struct platform_device s5p_device_jpeg = {
- .name = "s5p-jpeg",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p_jpeg_resource),
- .resource = s5p_jpeg_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#endif /* CONFIG_S5P_DEV_JPEG */
-
-/* FIMD0 */
-
-#ifdef CONFIG_S5P_DEV_FIMD0
-static struct resource s5p_fimd0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
- [1] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_VSYNC, "vsync"),
- [2] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_FIFO, "fifo"),
- [3] = DEFINE_RES_IRQ_NAMED(IRQ_FIMD0_SYSTEM, "lcd_sys"),
-};
-
-struct platform_device s5p_device_fimd0 = {
- .name = "s5p-fb",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p_fimd0_resource),
- .resource = s5p_fimd0_resource,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
-{
- s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
- &s5p_device_fimd0);
-}
-#endif /* CONFIG_S5P_DEV_FIMD0 */
-
/* HWMON */
#ifdef CONFIG_S3C_DEV_HWMON
@@ -722,60 +559,6 @@ void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd)
}
#endif /* CONFIG_S3C_DEV_I2C7 */
-/* I2C HDMIPHY */
-
-#ifdef CONFIG_S5P_DEV_I2C_HDMIPHY
-static struct resource s5p_i2c_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_IIC_HDMIPHY, SZ_4K),
- [1] = DEFINE_RES_IRQ(IRQ_IIC_HDMIPHY),
-};
-
-struct platform_device s5p_device_i2c_hdmiphy = {
- .name = "s3c2440-hdmiphy-i2c",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_i2c_resource),
- .resource = s5p_i2c_resource,
-};
-
-void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
-{
- struct s3c2410_platform_i2c *npd;
-
- if (!pd) {
- pd = &default_i2c_data;
-
- if (soc_is_s5pv210())
- pd->bus_num = 3;
- else
- pd->bus_num = 0;
- }
-
- npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
- &s5p_device_i2c_hdmiphy);
-}
-
-static struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
-
-void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
- struct i2c_board_info *mhl_info, int mhl_bus)
-{
- struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata;
-
- if (soc_is_s5pv210())
- pd->hdmiphy_bus = 3;
- else
- pd->hdmiphy_bus = 0;
-
- pd->hdmiphy_info = hdmiphy_info;
- pd->mhl_info = mhl_info;
- pd->mhl_bus = mhl_bus;
-
- s3c_set_platdata(pd, sizeof(struct s5p_hdmi_platform_data),
- &s5p_device_hdmi);
-}
-
-#endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
-
/* I2S */
#ifdef CONFIG_PLAT_S3C24XX
@@ -879,36 +662,6 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
}
#endif /* CONFIG_PLAT_S3C24XX */
-/* MIPI CSIS */
-
-#ifdef CONFIG_S5P_DEV_CSIS0
-static struct resource s5p_mipi_csis0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS0, SZ_16K),
- [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS0),
-};
-
-struct platform_device s5p_device_mipi_csis0 = {
- .name = "s5p-mipi-csis",
- .id = 0,
- .num_resources = ARRAY_SIZE(s5p_mipi_csis0_resource),
- .resource = s5p_mipi_csis0_resource,
-};
-#endif /* CONFIG_S5P_DEV_CSIS0 */
-
-#ifdef CONFIG_S5P_DEV_CSIS1
-static struct resource s5p_mipi_csis1_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_MIPI_CSIS1, SZ_16K),
- [1] = DEFINE_RES_IRQ(IRQ_MIPI_CSIS1),
-};
-
-struct platform_device s5p_device_mipi_csis1 = {
- .name = "s5p-mipi-csis",
- .id = 1,
- .num_resources = ARRAY_SIZE(s5p_mipi_csis1_resource),
- .resource = s5p_mipi_csis1_resource,
-};
-#endif
-
/* NAND */
#ifdef CONFIG_S3C_DEV_NAND
@@ -1052,43 +805,6 @@ void __init s3c64xx_onenand1_set_platdata(struct onenand_platform_data *pdata)
}
#endif /* CONFIG_S3C64XX_DEV_ONENAND1 */
-#ifdef CONFIG_S5P_DEV_ONENAND
-static struct resource s5p_onenand_resources[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_ONENAND, SZ_128K),
- [1] = DEFINE_RES_MEM(S5P_PA_ONENAND_DMA, SZ_8K),
- [2] = DEFINE_RES_IRQ(IRQ_ONENAND_AUDI),
-};
-
-struct platform_device s5p_device_onenand = {
- .name = "s5pc110-onenand",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_onenand_resources),
- .resource = s5p_onenand_resources,
-};
-#endif /* CONFIG_S5P_DEV_ONENAND */
-
-/* PMU */
-
-#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
-static struct resource s5p_pmu_resource[] = {
- DEFINE_RES_IRQ(IRQ_PMU)
-};
-
-static struct platform_device s5p_device_pmu = {
- .name = "arm-pmu",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_pmu_resource),
- .resource = s5p_pmu_resource,
-};
-
-static int __init s5p_pmu_init(void)
-{
- platform_device_register(&s5p_device_pmu);
- return 0;
-}
-arch_initcall(s5p_pmu_init);
-#endif /* CONFIG_PLAT_S5P */
-
/* PWM Timer */
#ifdef CONFIG_SAMSUNG_DEV_PWM
@@ -1251,52 +967,6 @@ void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd)
}
#endif /* CONFIG_SAMSUNG_DEV_TS */
-/* TV */
-
-#ifdef CONFIG_S5P_DEV_TV
-
-static struct resource s5p_hdmi_resources[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_HDMI, SZ_1M),
- [1] = DEFINE_RES_IRQ(IRQ_HDMI),
-};
-
-struct platform_device s5p_device_hdmi = {
- .name = "s5p-hdmi",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_hdmi_resources),
- .resource = s5p_hdmi_resources,
-};
-
-static struct resource s5p_sdo_resources[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_SDO, SZ_64K),
- [1] = DEFINE_RES_IRQ(IRQ_SDO),
-};
-
-struct platform_device s5p_device_sdo = {
- .name = "s5p-sdo",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_sdo_resources),
- .resource = s5p_sdo_resources,
-};
-
-static struct resource s5p_mixer_resources[] = {
- [0] = DEFINE_RES_MEM_NAMED(S5P_PA_MIXER, SZ_64K, "mxr"),
- [1] = DEFINE_RES_MEM_NAMED(S5P_PA_VP, SZ_64K, "vp"),
- [2] = DEFINE_RES_IRQ_NAMED(IRQ_MIXER, "irq"),
-};
-
-struct platform_device s5p_device_mixer = {
- .name = "s5p-mixer",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_mixer_resources),
- .resource = s5p_mixer_resources,
- .dev = {
- .dma_mask = &samsung_device_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- }
-};
-#endif /* CONFIG_S5P_DEV_TV */
-
/* USB */
#ifdef CONFIG_S3C_DEV_USB_HOST
diff --git a/arch/arm/plat-samsung/include/plat/camport.h b/arch/arm/plat-samsung/include/plat/camport.h
deleted file mode 100644
index a5708bf84b3a..000000000000
--- a/arch/arm/plat-samsung/include/plat/camport.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5P series camera interface helper functions
- *
- * 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_SAMSUNG_CAMPORT_H_
-#define __PLAT_SAMSUNG_CAMPORT_H_ __FILE__
-
-enum s5p_camport_id {
- S5P_CAMPORT_A,
- S5P_CAMPORT_B,
-};
-
-/*
- * The helper functions to configure GPIO for the camera parallel bus.
- * The camera port can be multiplexed with any FIMC entity, even multiple
- * FIMC entities are allowed to be attached to a single port simultaneously.
- * These functions are to be used in the board setup code.
- */
-int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
-int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
-
-#endif /* __PLAT_SAMSUNG_CAMPORT_H */
diff --git a/arch/arm/plat-samsung/include/plat/clock-clksrc.h b/arch/arm/plat-samsung/include/plat/clock-clksrc.h
deleted file mode 100644
index 50a8ca7c3760..000000000000
--- a/arch/arm/plat-samsung/include/plat/clock-clksrc.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h
- *
- * Parts taken from arch/arm/plat-s3c64xx/clock.c
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * Copyright 2009 Ben Dooks <ben-linux@fluff.org>
- * Copyright 2009 Harald Welte
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/**
- * struct clksrc_sources - list of sources for a given clock
- * @sources: array of pointers to clocks
- * @nr_sources: The size of @sources
- */
-struct clksrc_sources {
- unsigned int nr_sources;
- struct clk **sources;
-};
-
-/**
- * struct clksrc_reg - register definition for clock control bits
- * @reg: pointer to the register in virtual memory.
- * @shift: the shift in bits to where the bitfield is.
- * @size: the size in bits of the bitfield.
- *
- * This specifies the size and position of the bits we are interested
- * in within the register specified by @reg.
- */
-struct clksrc_reg {
- void __iomem *reg;
- unsigned short shift;
- unsigned short size;
-};
-
-/**
- * struct clksrc_clk - class of clock for newer style samsung devices.
- * @clk: the standard clock representation
- * @sources: the sources for this clock
- * @reg_src: the register definition for selecting the clock's source
- * @reg_div: the register definition for the clock's output divisor
- *
- * This clock implements the features required by the newer SoCs where
- * the standard clock block provides an input mux and a post-mux divisor
- * to provide the periperhal's clock.
- *
- * The array of @sources provides the mapping of mux position to the
- * clock, and @reg_src shows the code where to modify to change the mux
- * position. The @reg_div defines how to change the divider settings on
- * the output.
- */
-struct clksrc_clk {
- struct clk clk;
- struct clksrc_sources *sources;
-
- struct clksrc_reg reg_src;
- struct clksrc_reg reg_div;
-};
-
-/**
- * s3c_set_clksrc() - setup the clock from the register settings
- * @clk: The clock to setup.
- * @announce: true to announce the setting to printk().
- *
- * Setup the clock from the current register settings, for when the
- * kernel boots or if it is resuming from a possibly unknown state.
- */
-extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce);
-
-/**
- * s3c_register_clksrc() register clocks from an array of clksrc clocks
- * @srcs: The array of clocks to register
- * @size: The size of the @srcs array.
- *
- * Initialise and register the array of clocks described by @srcs.
- */
-extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size);
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
deleted file mode 100644
index 63239f409807..000000000000
--- a/arch/arm/plat-samsung/include/plat/clock.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/clock.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- * http://www.simtec.co.uk/products/SWLINUX/
- * Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_CLOCK_H
-#define __ASM_PLAT_CLOCK_H __FILE__
-
-#include <linux/spinlock.h>
-#include <linux/clkdev.h>
-
-struct clk;
-
-/**
- * struct clk_ops - standard clock operations
- * @set_rate: set the clock rate, see clk_set_rate().
- * @get_rate: get the clock rate, see clk_get_rate().
- * @round_rate: round a given clock rate, see clk_round_rate().
- * @set_parent: set the clock's parent, see clk_set_parent().
- *
- * Group the common clock implementations together so that we
- * don't have to keep setting the same fields again. We leave
- * enable in struct clk.
- *
- * Adding an extra layer of indirection into the process should
- * not be a problem as it is unlikely these operations are going
- * to need to be called quickly.
- */
-struct clk_ops {
- int (*set_rate)(struct clk *c, unsigned long rate);
- unsigned long (*get_rate)(struct clk *c);
- unsigned long (*round_rate)(struct clk *c, unsigned long rate);
- int (*set_parent)(struct clk *c, struct clk *parent);
-};
-
-struct clk {
- struct list_head list;
- struct module *owner;
- struct clk *parent;
- const char *name;
- const char *devname;
- int id;
- int usage;
- unsigned long rate;
- unsigned long ctrlbit;
-
- struct clk_ops *ops;
- int (*enable)(struct clk *, int enable);
- struct clk_lookup lookup;
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
- struct dentry *dent; /* For visible tree hierarchy */
-#endif
-};
-
-/* other clocks which may be registered by board support */
-
-extern struct clk s3c24xx_dclk0;
-extern struct clk s3c24xx_dclk1;
-extern struct clk s3c24xx_clkout0;
-extern struct clk s3c24xx_clkout1;
-extern struct clk s3c24xx_uclk;
-
-extern struct clk clk_usb_bus;
-
-/* core clock support */
-
-extern struct clk clk_f;
-extern struct clk clk_h;
-extern struct clk clk_p;
-extern struct clk clk_mpll;
-extern struct clk clk_upll;
-extern struct clk clk_epll;
-extern struct clk clk_xtal;
-extern struct clk clk_ext;
-
-/* S3C2443/S3C2416 specific clocks */
-extern struct clksrc_clk clk_epllref;
-extern struct clksrc_clk clk_esysclk;
-
-/* S3C24XX UART clocks */
-extern struct clk s3c24xx_clk_uart0;
-extern struct clk s3c24xx_clk_uart1;
-extern struct clk s3c24xx_clk_uart2;
-
-/* S3C64XX specific clocks */
-extern struct clk clk_h2;
-extern struct clk clk_27m;
-extern struct clk clk_48m;
-extern struct clk clk_xusbxti;
-
-extern int clk_default_setrate(struct clk *clk, unsigned long rate);
-extern struct clk_ops clk_ops_def_setrate;
-
-/* exports for arch/arm/mach-s3c2410
- *
- * Please DO NOT use these outside of arch/arm/mach-s3c2410
-*/
-
-extern spinlock_t clocks_lock;
-
-extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
-
-extern int s3c24xx_register_clock(struct clk *clk);
-extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
-
-extern void s3c_register_clocks(struct clk *clk, int nr_clks);
-extern void s3c_disable_clocks(struct clk *clkp, int nr_clks);
-
-extern int s3c24xx_register_baseclocks(unsigned long xtal);
-
-extern void s5p_register_clocks(unsigned long xtal_freq);
-
-extern void s3c24xx_setup_clocks(unsigned long fclk,
- unsigned long hclk,
- unsigned long pclk);
-
-extern void s3c2410_setup_clocks(void);
-extern void s3c2412_setup_clocks(void);
-extern void s3c244x_setup_clocks(void);
-
-/* S3C2410 specific clock functions */
-
-extern int s3c2410_baseclk_add(void);
-
-/* S3C2443/S3C2416 specific clock functions */
-
-typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base);
-
-extern void s3c2443_common_setup_clocks(pll_fn get_mpll);
-extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
- unsigned int *divs, int nr_divs,
- int divmask);
-
-extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable);
-extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable);
-
-/* S3C64XX specific functions and clocks */
-
-extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
-
-/* Global watchdog clock used by arch_wtd_reset() callback */
-
-extern struct clk *s3c2410_wdtclk;
-
-#endif /* __ASM_PLAT_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
index 72d4178ad23b..317c52303288 100644
--- a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
+++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
@@ -140,7 +140,6 @@ struct s3c_cpufreq_config {
* any frequency changes. This is really only need by devices like the
* S3C2410 where there is no or limited divider between the PLL and the
* ARMCLK.
- * @resume_clocks: Update the clocks on resume.
* @get_iotiming: Get the current IO timing data, mainly for use at start.
* @set_iotiming: Update the IO timings from the cached copies calculated
* from the @calc_iotiming entry when changing the frequency.
@@ -169,8 +168,6 @@ struct s3c_cpufreq_info {
/* driver routines */
- void (*resume_clocks)(void);
-
int (*get_iotiming)(struct s3c_cpufreq_config *cfg,
struct s3c_iotimings *timings);
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 5a237db9f9eb..61d14f3a0426 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -33,13 +33,6 @@ extern unsigned long samsung_cpu_id;
#define S3C6410_CPU_ID 0x36410000
#define S3C64XX_CPU_MASK 0xFFFFF000
-#define S5P6440_CPU_ID 0x56440000
-#define S5P6450_CPU_ID 0x36450000
-#define S5P64XX_CPU_MASK 0xFFFFF000
-
-#define S5PC100_CPU_ID 0x43100000
-#define S5PC100_CPU_MASK 0xFFFFF000
-
#define S5PV210_CPU_ID 0x43110000
#define S5PV210_CPU_MASK 0xFFFFF000
@@ -54,10 +47,6 @@ IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
IS_SAMSUNG_CPU(s3c2412, S3C2412_CPU_ID, S3C2412_CPU_MASK)
IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK)
-IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK)
-IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \
@@ -86,30 +75,6 @@ IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK)
# define soc_is_s3c64xx() 0
#endif
-#if defined(CONFIG_CPU_S5P6440)
-# define soc_is_s5p6440() is_samsung_s5p6440()
-#else
-# define soc_is_s5p6440() 0
-#endif
-
-#if defined(CONFIG_CPU_S5P6450)
-# define soc_is_s5p6450() is_samsung_s5p6450()
-#else
-# define soc_is_s5p6450() 0
-#endif
-
-#if defined(CONFIG_CPU_S5PC100)
-# define soc_is_s5pc100() is_samsung_s5pc100()
-#else
-# define soc_is_s5pc100() 0
-#endif
-
-#if defined(CONFIG_CPU_S5PV210)
-# define soc_is_s5pv210() is_samsung_s5pv210()
-#else
-# define soc_is_s5pv210() 0
-#endif
-
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
#ifndef KHZ
@@ -145,12 +110,9 @@ extern void s3c_init_cpu(unsigned long idcode,
/* core initialisation functions */
-extern void s5p_init_irq(u32 *vic, u32 num_vic);
-
extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
extern void s3c64xx_init_cpu(void);
-extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void);
@@ -177,9 +139,5 @@ extern struct bus_type s3c2440_subsys;
extern struct bus_type s3c2442_subsys;
extern struct bus_type s3c2443_subsys;
extern struct bus_type s3c6410_subsys;
-extern struct bus_type s5p64x0_subsys;
-extern struct bus_type s5pv210_subsys;
-
-extern void (*s5pc1xx_idle)(void);
#endif
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index eece188ed188..e23fed311e5f 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -25,9 +25,6 @@ struct s3c24xx_uart_resources {
extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
-extern struct s3c24xx_uart_resources s5p_uart_resources[];
-extern struct s3c24xx_uart_resources exynos4_uart_resources[];
-extern struct s3c24xx_uart_resources exynos5_uart_resources[];
extern struct platform_device *s3c24xx_uart_devs[];
extern struct platform_device *s3c24xx_uart_src[];
@@ -75,62 +72,6 @@ extern struct platform_device s3c_device_usb_hsotg;
extern struct platform_device s3c_device_usb_hsudc;
extern struct platform_device s3c_device_wdt;
-extern struct platform_device s5p_device_fimc0;
-extern struct platform_device s5p_device_fimc1;
-extern struct platform_device s5p_device_fimc2;
-extern struct platform_device s5p_device_fimc3;
-extern struct platform_device s5p_device_fimc_md;
-extern struct platform_device s5p_device_jpeg;
-extern struct platform_device s5p_device_g2d;
-extern struct platform_device s5p_device_fimd0;
-extern struct platform_device s5p_device_hdmi;
-extern struct platform_device s5p_device_i2c_hdmiphy;
-extern struct platform_device s5p_device_mfc;
-extern struct platform_device s5p_device_mfc_l;
-extern struct platform_device s5p_device_mfc_r;
-extern struct platform_device s5p_device_mipi_csis0;
-extern struct platform_device s5p_device_mipi_csis1;
-extern struct platform_device s5p_device_mixer;
-extern struct platform_device s5p_device_onenand;
-extern struct platform_device s5p_device_sdo;
-
-extern struct platform_device s5p6440_device_iis;
-extern struct platform_device s5p6440_device_pcm;
-
-extern struct platform_device s5p6450_device_iis0;
-extern struct platform_device s5p6450_device_iis1;
-extern struct platform_device s5p6450_device_iis2;
-extern struct platform_device s5p6450_device_pcm0;
-
-
-extern struct platform_device s5pc100_device_ac97;
-extern struct platform_device s5pc100_device_iis0;
-extern struct platform_device s5pc100_device_iis1;
-extern struct platform_device s5pc100_device_iis2;
-extern struct platform_device s5pc100_device_pcm0;
-extern struct platform_device s5pc100_device_pcm1;
-extern struct platform_device s5pc100_device_spdif;
-
-extern struct platform_device s5pv210_device_ac97;
-extern struct platform_device s5pv210_device_iis0;
-extern struct platform_device s5pv210_device_iis1;
-extern struct platform_device s5pv210_device_iis2;
-extern struct platform_device s5pv210_device_pcm0;
-extern struct platform_device s5pv210_device_pcm1;
-extern struct platform_device s5pv210_device_pcm2;
-extern struct platform_device s5pv210_device_spdif;
-
-extern struct platform_device exynos4_device_ac97;
-extern struct platform_device exynos4_device_ahci;
-extern struct platform_device exynos4_device_i2s0;
-extern struct platform_device exynos4_device_i2s1;
-extern struct platform_device exynos4_device_i2s2;
-extern struct platform_device exynos4_device_ohci;
-extern struct platform_device exynos4_device_pcm0;
-extern struct platform_device exynos4_device_pcm1;
-extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_spdif;
-
extern struct platform_device samsung_asoc_idma;
extern struct platform_device samsung_device_keypad;
extern struct platform_device samsung_device_pwm;
diff --git a/arch/arm/plat-samsung/include/plat/fb-core.h b/arch/arm/plat-samsung/include/plat/fb-core.h
index 6abcbf139cee..bca383efcf6d 100644
--- a/arch/arm/plat-samsung/include/plat/fb-core.h
+++ b/arch/arm/plat-samsung/include/plat/fb-core.h
@@ -26,19 +26,4 @@ static inline void s3c_fb_setname(char *name)
#endif
}
-/* Re-define device name depending on support. */
-static inline void s5p_fb_setname(int id, char *name)
-{
- switch (id) {
-#ifdef CONFIG_S5P_DEV_FIMD0
- case 0:
- s5p_device_fimd0.name = name;
- break;
-#endif
- default:
- printk(KERN_ERR "%s: invalid device id(%d)\n", __func__, id);
- break;
- }
-}
-
#endif /* __ASM_PLAT_FB_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index 9ae507270785..b89f8f208515 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -26,46 +26,10 @@
extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
/**
- * s5p_fimd0_set_platdata() - Setup the FB device with platform data.
- * @pd: The platform data to set. The data is copied from the passed structure
- * so the machine data can mark the data __initdata so that any unused
- * machines will end up dumping their data at runtime.
- */
-extern void s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd);
-
-/**
* s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
*
* Initialise the GPIO for an 24bpp LCD display on the RGB interface.
*/
extern void s3c64xx_fb_gpio_setup_24bpp(void);
-/**
- * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5pc100_fb_gpio_setup_24bpp(void);
-
-/**
- * s5pv210_fb_gpio_setup_24bpp() - S5PV210/S5PC110 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5pv210_fb_gpio_setup_24bpp(void);
-
-/**
- * exynos4_fimd0_gpio_setup_24bpp() - Exynos4 setup function for 24bpp LCD0
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface 0.
- */
-extern void exynos4_fimd0_gpio_setup_24bpp(void);
-
-/**
- * s5p64x0_fb_gpio_setup_24bpp() - S5P6440/S5P6450 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5p64x0_fb_gpio_setup_24bpp(void);
-
#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h b/arch/arm/plat-samsung/include/plat/fimc-core.h
deleted file mode 100644
index 1d6cb2b8b094..000000000000
--- a/arch/arm/plat-samsung/include/plat/fimc-core.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * arch/arm/plat-samsung/include/plat/fimc-core.h
- *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * Samsung camera interface driver core functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_PLAT_FIMC_CORE_H
-#define __ASM_PLAT_FIMC_CORE_H __FILE__
-
-/*
- * These functions are only for use with the core support code, such as
- * the CPU-specific initialization code.
- */
-
-/* Re-define device name to differentiate the subsystem in various SoCs. */
-static inline void s3c_fimc_setname(int id, char *name)
-{
- switch (id) {
-#ifdef CONFIG_S5P_DEV_FIMC0
- case 0:
- s5p_device_fimc0.name = name;
- break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC1
- case 1:
- s5p_device_fimc1.name = name;
- break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC2
- case 2:
- s5p_device_fimc2.name = name;
- break;
-#endif
-#ifdef CONFIG_S5P_DEV_FIMC3
- case 3:
- s5p_device_fimc3.name = name;
- break;
-#endif
- default:
- break;
- }
-}
-
-#endif /* __ASM_PLAT_FIMC_CORE_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index 08740eed050c..b5294eff18b5 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -27,7 +27,6 @@
#include <linux/types.h>
typedef unsigned int __bitwise__ samsung_gpio_pull_t;
-typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
/* forward declaration if gpio-core.h hasn't been included */
struct samsung_gpio_chip;
@@ -180,67 +179,4 @@ static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size,
return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE);
}
-/* Define values for the drvstr available for each gpio pin.
- *
- * These values control the value of the output signal driver strength,
- * configurable on most pins on the S5P series.
- */
-#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x0)
-#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x2)
-#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x1)
-#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x3)
-
-/**
- * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin
- * @pin: The pin number to get the settings for
- *
- * Read the driver streght value for the specified pin.
-*/
-extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);
-
-/**
- * s3c_gpio_set_drvstr() - set the driver streght value of a gpio pin
- * @pin: The pin number to configure the driver streght value
- * @drvstr: The new value of the driver strength
- *
- * This function sets the driver strength value for the specified pin.
- * It will return 0 if successful, or a negative error code if the pin
- * cannot support the requested setting.
-*/
-extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
-
-/**
- * s5p_register_gpio_interrupt() - register interrupt support for a gpio group
- * @pin: The pin number from the group to be registered
- *
- * This function registers gpio interrupt support for the group that the
- * specified pin belongs to.
- *
- * The total number of gpio pins is quite large ob s5p series. Registering
- * irq support for all of them would be a resource waste. Because of that the
- * interrupt support for standard gpio pins is registered dynamically.
- *
- * It will return the irq number of the interrupt that has been registered
- * or -ENOMEM if no more gpio interrupts can be registered. It is allowed
- * to call this function more than once for the same gpio group (the group
- * will be registered only once).
- */
-extern int s5p_register_gpio_interrupt(int pin);
-
-/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
- * registration (see s5p_register_gpio_interrupt function)
- * @chain_irq: chained irq number for the gpio int handler for this bank
- * @start: start gpio group number of this bank
- * @nr_groups: number of gpio groups handled by this bank
- *
- * This functions registers initial information about gpio banks that
- * can be later used by the s5p_register_gpio_interrupt() function to
- * enable support for gpio interrupt for particular gpio group.
- */
-#ifdef CONFIG_S5P_GPIO_INT
-extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
-#else
-#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
-#endif
-
#endif /* __PLAT_GPIO_CFG_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index cf5aae5b0975..6ce11bfdc37e 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -14,6 +14,9 @@
#ifndef __PLAT_SAMSUNG_GPIO_CORE_H
#define __PLAT_SAMSUNG_GPIO_CORE_H
+/* Bring in machine-local definitions, especially S3C_GPIO_END */
+#include <mach/gpio-samsung.h>
+
#define GPIOCON_OFF (0x00)
#define GPIODAT_OFF (0x04)
diff --git a/arch/arm/plat-samsung/include/plat/hdmi.h b/arch/arm/plat-samsung/include/plat/hdmi.h
deleted file mode 100644
index 331d046ac2c5..000000000000
--- a/arch/arm/plat-samsung/include/plat/hdmi.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_HDMI_H
-#define __PLAT_SAMSUNG_HDMI_H __FILE__
-
-extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
- struct i2c_board_info *mhl_info, int mhl_bus);
-
-#endif /* __PLAT_SAMSUNG_HDMI_H */
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
deleted file mode 100644
index 039001c0ef05..000000000000
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/irqs.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P Common IRQ support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_SAMSUNG_IRQS_H
-#define __PLAT_SAMSUNG_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S5P_IRQ_OFFSET (32)
-
-#define S5P_IRQ(x) ((x) + S5P_IRQ_OFFSET)
-
-#define S5P_VIC0_BASE S5P_IRQ(0)
-#define S5P_VIC1_BASE S5P_IRQ(32)
-#define S5P_VIC2_BASE S5P_IRQ(64)
-#define S5P_VIC3_BASE S5P_IRQ(96)
-
-#define VIC_BASE(x) (S5P_VIC0_BASE + ((x)*32))
-
-#define IRQ_VIC0_BASE S5P_VIC0_BASE
-#define IRQ_VIC1_BASE S5P_VIC1_BASE
-#define IRQ_VIC2_BASE S5P_VIC2_BASE
-
-/* VIC based IRQs */
-
-#define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x))
-#define S5P_IRQ_VIC1(x) (S5P_VIC1_BASE + (x))
-#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
-#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
-
-#define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
- : ((x) - 16 + S5P_EINT_BASE2))
-
-#define EINT_OFFSET(irq) ((irq) < S5P_EINT_BASE2 ? \
- ((irq) - S5P_EINT_BASE1) : \
- ((irq) + 16 - S5P_EINT_BASE2))
-
-#define IRQ_EINT_BIT(x) EINT_OFFSET(x)
-
-/* Typically only a few gpio chips require gpio interrupt support.
- To avoid memory waste irq descriptors are allocated only for
- S5P_GPIOINT_GROUP_COUNT chips, each with total number of
- S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged
- to any gpio chip with the s5p_register_gpio_interrupt() function */
-#define S5P_GPIOINT_GROUP_COUNT 4
-#define S5P_GPIOINT_GROUP_SIZE 8
-#define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE)
-
-/* IRQ types common for all s5p platforms */
-#define S5P_IRQ_TYPE_LEVEL_LOW (0x00)
-#define S5P_IRQ_TYPE_LEVEL_HIGH (0x01)
-#define S5P_IRQ_TYPE_EDGE_FALLING (0x02)
-#define S5P_IRQ_TYPE_EDGE_RISING (0x03)
-#define S5P_IRQ_TYPE_EDGE_BOTH (0x04)
-
-#endif /* __PLAT_SAMSUNG_IRQS_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c18678610bc0..f5b9d3ff9cd4 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -15,7 +15,6 @@
#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
#define S5P_VA_CMU S3C_ADDR(0x02100000)
-#define S5P_VA_PMU S3C_ADDR(0x02180000)
#define S5P_VA_GPIO S3C_ADDR(0x02200000)
#define S5P_VA_GPIO1 S5P_VA_GPIO
#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
diff --git a/arch/arm/plat-samsung/include/plat/mfc.h b/arch/arm/plat-samsung/include/plat/mfc.h
deleted file mode 100644
index 033654e91e22..000000000000
--- a/arch/arm/plat-samsung/include/plat/mfc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_MFC_H
-#define __PLAT_SAMSUNG_MFC_H __FILE__
-
-struct s5p_mfc_dt_meminfo {
- unsigned long loff;
- unsigned long lsize;
- unsigned long roff;
- unsigned long rsize;
- char *compatible;
-};
-
-/**
- * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver
- * @rbase: base address for MFC 'right' memory interface
- * @rsize: size of the memory reserved for MFC 'right' interface
- * @lbase: base address for MFC 'left' memory interface
- * @lsize: size of the memory reserved for MFC 'left' interface
- *
- * This function reserves system memory for both MFC device memory
- * interfaces and registers it to respective struct device entries as
- * coherent memory.
- */
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
- phys_addr_t lbase, unsigned int lsize);
-
-#endif /* __PLAT_SAMSUNG_MFC_H */
diff --git a/arch/arm/plat-samsung/include/plat/pll.h b/arch/arm/plat-samsung/include/plat/pll.h
deleted file mode 100644
index 357af7c1c664..000000000000
--- a/arch/arm/plat-samsung/include/plat/pll.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/pll.h
- *
- * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * Samsung PLL codes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <asm/div64.h>
-
-#define S3C24XX_PLL_MDIV_MASK (0xFF)
-#define S3C24XX_PLL_PDIV_MASK (0x1F)
-#define S3C24XX_PLL_SDIV_MASK (0x3)
-#define S3C24XX_PLL_MDIV_SHIFT (12)
-#define S3C24XX_PLL_PDIV_SHIFT (4)
-#define S3C24XX_PLL_SDIV_SHIFT (0)
-
-static inline unsigned int s3c24xx_get_pll(unsigned int pllval,
- unsigned int baseclk)
-{
- unsigned int mdiv, pdiv, sdiv;
- uint64_t fvco;
-
- mdiv = (pllval >> S3C24XX_PLL_MDIV_SHIFT) & S3C24XX_PLL_MDIV_MASK;
- pdiv = (pllval >> S3C24XX_PLL_PDIV_SHIFT) & S3C24XX_PLL_PDIV_MASK;
- sdiv = (pllval >> S3C24XX_PLL_SDIV_SHIFT) & S3C24XX_PLL_SDIV_MASK;
-
- fvco = (uint64_t)baseclk * (mdiv + 8);
- do_div(fvco, (pdiv + 2) << sdiv);
-
- return (unsigned int)fvco;
-}
-
-#define S3C2416_PLL_MDIV_MASK (0x3FF)
-#define S3C2416_PLL_PDIV_MASK (0x3F)
-#define S3C2416_PLL_SDIV_MASK (0x7)
-#define S3C2416_PLL_MDIV_SHIFT (14)
-#define S3C2416_PLL_PDIV_SHIFT (5)
-#define S3C2416_PLL_SDIV_SHIFT (0)
-
-static inline unsigned int s3c2416_get_pll(unsigned int pllval,
- unsigned int baseclk)
-{
- unsigned int mdiv, pdiv, sdiv;
- uint64_t fvco;
-
- mdiv = (pllval >> S3C2416_PLL_MDIV_SHIFT) & S3C2416_PLL_MDIV_MASK;
- pdiv = (pllval >> S3C2416_PLL_PDIV_SHIFT) & S3C2416_PLL_PDIV_MASK;
- sdiv = (pllval >> S3C2416_PLL_SDIV_SHIFT) & S3C2416_PLL_SDIV_MASK;
-
- fvco = (uint64_t)baseclk * mdiv;
- do_div(fvco, (pdiv << sdiv));
-
- return (unsigned int)fvco;
-}
-
-#define S3C6400_PLL_MDIV_MASK (0x3FF)
-#define S3C6400_PLL_PDIV_MASK (0x3F)
-#define S3C6400_PLL_SDIV_MASK (0x7)
-#define S3C6400_PLL_MDIV_SHIFT (16)
-#define S3C6400_PLL_PDIV_SHIFT (8)
-#define S3C6400_PLL_SDIV_SHIFT (0)
-
-static inline unsigned long s3c6400_get_pll(unsigned long baseclk,
- u32 pllcon)
-{
- u32 mdiv, pdiv, sdiv;
- u64 fvco = baseclk;
-
- mdiv = (pllcon >> S3C6400_PLL_MDIV_SHIFT) & S3C6400_PLL_MDIV_MASK;
- pdiv = (pllcon >> S3C6400_PLL_PDIV_SHIFT) & S3C6400_PLL_PDIV_MASK;
- sdiv = (pllcon >> S3C6400_PLL_SDIV_SHIFT) & S3C6400_PLL_SDIV_MASK;
-
- fvco *= mdiv;
- do_div(fvco, (pdiv << sdiv));
-
- return (unsigned long)fvco;
-}
-
-#define PLL6553X_MDIV_MASK (0x7F)
-#define PLL6553X_PDIV_MASK (0x1F)
-#define PLL6553X_SDIV_MASK (0x3)
-#define PLL6553X_KDIV_MASK (0xFFFF)
-#define PLL6553X_MDIV_SHIFT (16)
-#define PLL6553X_PDIV_SHIFT (8)
-#define PLL6553X_SDIV_SHIFT (0)
-
-static inline unsigned long s3c_get_pll6553x(unsigned long baseclk,
- u32 pll_con0, u32 pll_con1)
-{
- unsigned long result;
- u32 mdiv, pdiv, sdiv, kdiv;
- u64 tmp;
-
- mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
- pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
- sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
- kdiv = pll_con1 & PLL6553X_KDIV_MASK;
-
- /*
- * We need to multiple baseclk by mdiv (the integer part) and kdiv
- * which is in 2^16ths, so shift mdiv up (does not overflow) and
- * add kdiv before multiplying. The use of tmp is to avoid any
- * overflows before shifting bac down into result when multipling
- * by the mdiv and kdiv pair.
- */
-
- tmp = baseclk;
- tmp *= (mdiv << 16) + kdiv;
- do_div(tmp, (pdiv << sdiv));
- result = tmp >> 16;
-
- return result;
-}
-
-#define PLL35XX_MDIV_MASK (0x3FF)
-#define PLL35XX_PDIV_MASK (0x3F)
-#define PLL35XX_SDIV_MASK (0x7)
-#define PLL35XX_MDIV_SHIFT (16)
-#define PLL35XX_PDIV_SHIFT (8)
-#define PLL35XX_SDIV_SHIFT (0)
-
-static inline unsigned long s5p_get_pll35xx(unsigned long baseclk, u32 pll_con)
-{
- u32 mdiv, pdiv, sdiv;
- u64 fvco = baseclk;
-
- mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
- pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
- sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
-
- fvco *= mdiv;
- do_div(fvco, (pdiv << sdiv));
-
- return (unsigned long)fvco;
-}
-
-#define PLL36XX_KDIV_MASK (0xFFFF)
-#define PLL36XX_MDIV_MASK (0x1FF)
-#define PLL36XX_PDIV_MASK (0x3F)
-#define PLL36XX_SDIV_MASK (0x7)
-#define PLL36XX_MDIV_SHIFT (16)
-#define PLL36XX_PDIV_SHIFT (8)
-#define PLL36XX_SDIV_SHIFT (0)
-
-static inline unsigned long s5p_get_pll36xx(unsigned long baseclk,
- u32 pll_con0, u32 pll_con1)
-{
- unsigned long result;
- u32 mdiv, pdiv, sdiv, kdiv;
- u64 tmp;
-
- mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
- pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
- sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
- kdiv = pll_con1 & PLL36XX_KDIV_MASK;
-
- tmp = baseclk;
-
- tmp *= (mdiv << 16) + kdiv;
- do_div(tmp, (pdiv << sdiv));
- result = tmp >> 16;
-
- return result;
-}
-
-#define PLL45XX_MDIV_MASK (0x3FF)
-#define PLL45XX_PDIV_MASK (0x3F)
-#define PLL45XX_SDIV_MASK (0x7)
-#define PLL45XX_MDIV_SHIFT (16)
-#define PLL45XX_PDIV_SHIFT (8)
-#define PLL45XX_SDIV_SHIFT (0)
-
-enum pll45xx_type_t {
- pll_4500,
- pll_4502,
- pll_4508
-};
-
-static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
- enum pll45xx_type_t pll_type)
-{
- u32 mdiv, pdiv, sdiv;
- u64 fvco = baseclk;
-
- mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
- pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
- sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
-
- if (pll_type == pll_4508)
- sdiv = sdiv - 1;
-
- fvco *= mdiv;
- do_div(fvco, (pdiv << sdiv));
-
- return (unsigned long)fvco;
-}
-
-/* CON0 bit-fields */
-#define PLL46XX_MDIV_MASK (0x1FF)
-#define PLL46XX_PDIV_MASK (0x3F)
-#define PLL46XX_SDIV_MASK (0x7)
-#define PLL46XX_LOCKED_SHIFT (29)
-#define PLL46XX_MDIV_SHIFT (16)
-#define PLL46XX_PDIV_SHIFT (8)
-#define PLL46XX_SDIV_SHIFT (0)
-
-/* CON1 bit-fields */
-#define PLL46XX_MRR_MASK (0x1F)
-#define PLL46XX_MFR_MASK (0x3F)
-#define PLL46XX_KDIV_MASK (0xFFFF)
-#define PLL4650C_KDIV_MASK (0xFFF)
-#define PLL46XX_MRR_SHIFT (24)
-#define PLL46XX_MFR_SHIFT (16)
-#define PLL46XX_KDIV_SHIFT (0)
-
-enum pll46xx_type_t {
- pll_4600,
- pll_4650,
- pll_4650c,
-};
-
-static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
- u32 pll_con0, u32 pll_con1,
- enum pll46xx_type_t pll_type)
-{
- unsigned long result;
- u32 mdiv, pdiv, sdiv, kdiv;
- u64 tmp;
-
- mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
- pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
- sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
- kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
- if (pll_type == pll_4650c)
- kdiv = pll_con1 & PLL4650C_KDIV_MASK;
- else
- kdiv = pll_con1 & PLL46XX_KDIV_MASK;
-
- tmp = baseclk;
-
- if (pll_type == pll_4600) {
- tmp *= (mdiv << 16) + kdiv;
- do_div(tmp, (pdiv << sdiv));
- result = tmp >> 16;
- } else {
- tmp *= (mdiv << 10) + kdiv;
- do_div(tmp, (pdiv << sdiv));
- result = tmp >> 10;
- }
-
- return result;
-}
-
-#define PLL90XX_MDIV_MASK (0xFF)
-#define PLL90XX_PDIV_MASK (0x3F)
-#define PLL90XX_SDIV_MASK (0x7)
-#define PLL90XX_KDIV_MASK (0xffff)
-#define PLL90XX_LOCKED_SHIFT (29)
-#define PLL90XX_MDIV_SHIFT (16)
-#define PLL90XX_PDIV_SHIFT (8)
-#define PLL90XX_SDIV_SHIFT (0)
-#define PLL90XX_KDIV_SHIFT (0)
-
-static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
- u32 pll_con, u32 pll_conk)
-{
- unsigned long result;
- u32 mdiv, pdiv, sdiv, kdiv;
- u64 tmp;
-
- mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
- pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
- sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
- kdiv = pll_conk & PLL90XX_KDIV_MASK;
-
- /*
- * We need to multiple baseclk by mdiv (the integer part) and kdiv
- * which is in 2^16ths, so shift mdiv up (does not overflow) and
- * add kdiv before multiplying. The use of tmp is to avoid any
- * overflows before shifting bac down into result when multipling
- * by the mdiv and kdiv pair.
- */
-
- tmp = baseclk;
- tmp *= (mdiv << 16) + kdiv;
- do_div(tmp, (pdiv << sdiv));
- result = tmp >> 16;
-
- return result;
-}
-
-#define PLL65XX_MDIV_MASK (0x3FF)
-#define PLL65XX_PDIV_MASK (0x3F)
-#define PLL65XX_SDIV_MASK (0x7)
-#define PLL65XX_MDIV_SHIFT (16)
-#define PLL65XX_PDIV_SHIFT (8)
-#define PLL65XX_SDIV_SHIFT (0)
-
-static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con)
-{
- u32 mdiv, pdiv, sdiv;
- u64 fvco = baseclk;
-
- mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK;
- pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK;
- sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK;
-
- fvco *= mdiv;
- do_div(fvco, (pdiv << sdiv));
-
- return (unsigned long)fvco;
-}
diff --git a/arch/arm/plat-samsung/include/plat/s5p-clock.h b/arch/arm/plat-samsung/include/plat/s5p-clock.h
deleted file mode 100644
index 8364b4bea8b8..000000000000
--- a/arch/arm/plat-samsung/include/plat/s5p-clock.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s5p-clock.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Header file for s5p clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_S5P_CLOCK_H
-#define __ASM_PLAT_S5P_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_bpll clk_ext_xtal_mux
-#define clk_fin_cpll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-#define clk_fin_dpll clk_ext_xtal_mux
-#define clk_fin_vpll clk_ext_xtal_mux
-#define clk_fin_hpll clk_ext_xtal_mux
-
-extern struct clk clk_ext_xtal_mux;
-extern struct clk clk_xusbxti;
-extern struct clk clk_48m;
-extern struct clk s5p_clk_27m;
-extern struct clk clk_fout_apll;
-extern struct clk clk_fout_bpll;
-extern struct clk clk_fout_bpll_div2;
-extern struct clk clk_fout_cpll;
-extern struct clk clk_fout_mpll;
-extern struct clk clk_fout_mpll_div2;
-extern struct clk clk_fout_epll;
-extern struct clk clk_fout_dpll;
-extern struct clk clk_fout_vpll;
-extern struct clk clk_arm;
-extern struct clk clk_vpll;
-
-extern struct clksrc_sources clk_src_apll;
-extern struct clksrc_sources clk_src_bpll;
-extern struct clksrc_sources clk_src_bpll_fout;
-extern struct clksrc_sources clk_src_cpll;
-extern struct clksrc_sources clk_src_mpll;
-extern struct clksrc_sources clk_src_mpll_fout;
-extern struct clksrc_sources clk_src_epll;
-extern struct clksrc_sources clk_src_dpll;
-
-extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
-
-/* Common EPLL operations for S5P platform */
-extern int s5p_epll_enable(struct clk *clk, int enable);
-extern unsigned long s5p_epll_get_rate(struct clk *clk);
-
-/* SPDIF clk operations common for S5PC100/V210/C110 and Exynos4 */
-extern int s5p_spdif_set_rate(struct clk *clk, unsigned long rate);
-extern unsigned long s5p_spdif_get_rate(struct clk *clk);
-
-extern struct clk_ops s5p_sclk_spdif_ops;
-#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index bf650218b40e..2787553c3ae2 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -56,22 +56,7 @@ extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
/* S3C2416 SDHCI setup */
@@ -151,115 +136,6 @@ static inline void s3c6400_default_sdhci2(void) { }
#endif /* CONFIG_S3C64XX_SETUP_SDHCI */
-/* S5P64X0 SDHCI setup */
-
-#ifdef CONFIG_S5P64X0_SETUP_SDHCI_GPIO
-static inline void s5p64x0_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
- s3c_hsmmc0_def_platdata.cfg_gpio = s5p64x0_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5p64x0_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
- s3c_hsmmc1_def_platdata.cfg_gpio = s5p64x0_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5p6440_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
- s3c_hsmmc2_def_platdata.cfg_gpio = s5p6440_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-static inline void s5p6450_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
- s3c_hsmmc2_def_platdata.cfg_gpio = s5p6450_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5p64x0_default_sdhci0(void) { }
-static inline void s5p64x0_default_sdhci1(void) { }
-static inline void s5p6440_default_sdhci2(void) { }
-static inline void s5p6450_default_sdhci2(void) { }
-
-#endif /* CONFIG_S5P64X0_SETUP_SDHCI_GPIO */
-
-/* S5PC100 SDHCI setup */
-
-#ifdef CONFIG_S5PC100_SETUP_SDHCI
-static inline void s5pc100_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
- s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5pc100_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
- s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5pc100_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
- s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5pc100_default_sdhci0(void) { }
-static inline void s5pc100_default_sdhci1(void) { }
-static inline void s5pc100_default_sdhci2(void) { }
-
-#endif /* CONFIG_S5PC100_SETUP_SDHCI */
-
-/* S5PV210 SDHCI setup */
-
-#ifdef CONFIG_S5PV210_SETUP_SDHCI
-static inline void s5pv210_default_sdhci0(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC
- s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci1(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC1
- s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci2(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC2
- s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
-#endif
-}
-
-static inline void s5pv210_default_sdhci3(void)
-{
-#ifdef CONFIG_S3C_DEV_HSMMC3
- s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
-#endif
-}
-
-#else
-static inline void s5pv210_default_sdhci0(void) { }
-static inline void s5pv210_default_sdhci1(void) { }
-static inline void s5pv210_default_sdhci2(void) { }
-static inline void s5pv210_default_sdhci3(void) { }
-
-#endif /* CONFIG_S5PV210_SETUP_SDHCI */
-
static inline void s3c_sdhci_setname(int id, char *name)
{
switch (id) {
diff --git a/arch/arm/plat-samsung/include/plat/tv-core.h b/arch/arm/plat-samsung/include/plat/tv-core.h
deleted file mode 100644
index 3bc34f3ce28f..000000000000
--- a/arch/arm/plat-samsung/include/plat/tv-core.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/arm/plat-samsung/include/plat/tv.h
- *
- * Copyright 2011 Samsung Electronics Co., Ltd.
- * Tomasz Stanislawski <t.stanislaws@samsung.com>
- *
- * Samsung TV driver core functions
- *
- * 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 __SAMSUNG_PLAT_TV_H
-#define __SAMSUNG_PLAT_TV_H __FILE__
-
-/*
- * These functions are only for use with the core support code, such as
- * the CPU-specific initialization code.
- */
-
-/* Re-define device name to differentiate the subsystem in various SoCs. */
-static inline void s5p_hdmi_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
- s5p_device_hdmi.name = name;
-#endif
-}
-
-static inline void s5p_mixer_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
- s5p_device_mixer.name = name;
-#endif
-}
-
-static inline void s5p_sdo_setname(char *name)
-{
-#ifdef CONFIG_S5P_DEV_TV
- s5p_device_sdo.name = name;
-#endif
-}
-
-#endif /* __SAMSUNG_PLAT_TV_H */
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c
index a1f925f3121f..11fbbc26e49f 100644
--- a/arch/arm/plat-samsung/init.c
+++ b/arch/arm/plat-samsung/init.c
@@ -30,7 +30,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
-#include <plat/clock.h>
static struct cpu_table *cpu;
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index da268813901b..f9a09262f2fa 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -19,9 +19,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
#include <mach/gpio-samsung.h>
-#endif
#include <plat/gpio-core.h>
#include <plat/pm.h>
@@ -196,7 +194,7 @@ struct samsung_gpio_pm samsung_gpio_pm_2bit = {
.resume = samsung_gpio_pm_2bit_resume,
};
-#if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P)
+#if defined(CONFIG_ARCH_S3C64XX)
static void samsung_gpio_pm_4bit_save(struct samsung_gpio_chip *chip)
{
chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
@@ -306,7 +304,7 @@ struct samsung_gpio_pm samsung_gpio_pm_4bit = {
.save = samsung_gpio_pm_4bit_save,
.resume = samsung_gpio_pm_4bit_resume,
};
-#endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */
+#endif /* CONFIG_ARCH_S3C64XX */
/**
* samsung_pm_save_gpio() - save gpio chip data for suspend
diff --git a/arch/arm/plat-samsung/s5p-clock.c b/arch/arm/plat-samsung/s5p-clock.c
deleted file mode 100644
index 48a159911037..000000000000
--- a/arch/arm/plat-samsung/s5p-clock.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P - Common clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/s5p-clock.h>
-
-/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
- * clk_ext_xtal_mux.
-*/
-struct clk clk_ext_xtal_mux = {
- .name = "ext_xtal",
- .id = -1,
-};
-
-struct clk clk_xusbxti = {
- .name = "xusbxti",
- .id = -1,
- .rate = 24000000,
-};
-
-struct clk s5p_clk_27m = {
- .name = "clk_27m",
- .id = -1,
- .rate = 27000000,
-};
-
-/* 48MHz USB Phy clock output */
-struct clk clk_48m = {
- .name = "clk_48m",
- .id = -1,
- .rate = 48000000,
-};
-
-/* APLL clock output
- * No need .ctrlbit, this is always on
-*/
-struct clk clk_fout_apll = {
- .name = "fout_apll",
- .id = -1,
-};
-
-/* BPLL clock output */
-
-struct clk clk_fout_bpll = {
- .name = "fout_bpll",
- .id = -1,
-};
-
-struct clk clk_fout_bpll_div2 = {
- .name = "fout_bpll_div2",
- .id = -1,
-};
-
-/* CPLL clock output */
-
-struct clk clk_fout_cpll = {
- .name = "fout_cpll",
- .id = -1,
-};
-
-/* MPLL clock output
- * No need .ctrlbit, this is always on
-*/
-struct clk clk_fout_mpll = {
- .name = "fout_mpll",
- .id = -1,
-};
-
-struct clk clk_fout_mpll_div2 = {
- .name = "fout_mpll_div2",
- .id = -1,
-};
-
-/* EPLL clock output */
-struct clk clk_fout_epll = {
- .name = "fout_epll",
- .id = -1,
- .ctrlbit = (1 << 31),
-};
-
-/* DPLL clock output */
-struct clk clk_fout_dpll = {
- .name = "fout_dpll",
- .id = -1,
- .ctrlbit = (1 << 31),
-};
-
-/* VPLL clock output */
-struct clk clk_fout_vpll = {
- .name = "fout_vpll",
- .id = -1,
- .ctrlbit = (1 << 31),
-};
-
-/* Possible clock sources for APLL Mux */
-static struct clk *clk_src_apll_list[] = {
- [0] = &clk_fin_apll,
- [1] = &clk_fout_apll,
-};
-
-struct clksrc_sources clk_src_apll = {
- .sources = clk_src_apll_list,
- .nr_sources = ARRAY_SIZE(clk_src_apll_list),
-};
-
-/* Possible clock sources for BPLL Mux */
-static struct clk *clk_src_bpll_list[] = {
- [0] = &clk_fin_bpll,
- [1] = &clk_fout_bpll,
-};
-
-struct clksrc_sources clk_src_bpll = {
- .sources = clk_src_bpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_bpll_list),
-};
-
-static struct clk *clk_src_bpll_fout_list[] = {
- [0] = &clk_fout_bpll_div2,
- [1] = &clk_fout_bpll,
-};
-
-struct clksrc_sources clk_src_bpll_fout = {
- .sources = clk_src_bpll_fout_list,
- .nr_sources = ARRAY_SIZE(clk_src_bpll_fout_list),
-};
-
-/* Possible clock sources for CPLL Mux */
-static struct clk *clk_src_cpll_list[] = {
- [0] = &clk_fin_cpll,
- [1] = &clk_fout_cpll,
-};
-
-struct clksrc_sources clk_src_cpll = {
- .sources = clk_src_cpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_cpll_list),
-};
-
-/* Possible clock sources for MPLL Mux */
-static struct clk *clk_src_mpll_list[] = {
- [0] = &clk_fin_mpll,
- [1] = &clk_fout_mpll,
-};
-
-struct clksrc_sources clk_src_mpll = {
- .sources = clk_src_mpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_mpll_list),
-};
-
-static struct clk *clk_src_mpll_fout_list[] = {
- [0] = &clk_fout_mpll_div2,
- [1] = &clk_fout_mpll,
-};
-
-struct clksrc_sources clk_src_mpll_fout = {
- .sources = clk_src_mpll_fout_list,
- .nr_sources = ARRAY_SIZE(clk_src_mpll_fout_list),
-};
-
-/* Possible clock sources for EPLL Mux */
-static struct clk *clk_src_epll_list[] = {
- [0] = &clk_fin_epll,
- [1] = &clk_fout_epll,
-};
-
-struct clksrc_sources clk_src_epll = {
- .sources = clk_src_epll_list,
- .nr_sources = ARRAY_SIZE(clk_src_epll_list),
-};
-
-/* Possible clock sources for DPLL Mux */
-static struct clk *clk_src_dpll_list[] = {
- [0] = &clk_fin_dpll,
- [1] = &clk_fout_dpll,
-};
-
-struct clksrc_sources clk_src_dpll = {
- .sources = clk_src_dpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_dpll_list),
-};
-
-struct clk clk_vpll = {
- .name = "vpll",
- .id = -1,
-};
-
-int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
-{
- unsigned int ctrlbit = clk->ctrlbit;
- u32 con;
-
- con = __raw_readl(reg);
- con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
- __raw_writel(con, reg);
- return 0;
-}
-
-int s5p_epll_enable(struct clk *clk, int enable)
-{
- unsigned int ctrlbit = clk->ctrlbit;
- unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
-
- if (enable)
- __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
- else
- __raw_writel(epll_con, S5P_EPLL_CON);
-
- return 0;
-}
-
-unsigned long s5p_epll_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-
-int s5p_spdif_set_rate(struct clk *clk, unsigned long rate)
-{
- struct clk *pclk;
- int ret;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- ret = pclk->ops->set_rate(pclk, rate);
- clk_put(pclk);
-
- return ret;
-}
-
-unsigned long s5p_spdif_get_rate(struct clk *clk)
-{
- struct clk *pclk;
- int rate;
-
- pclk = clk_get_parent(clk);
- if (IS_ERR(pclk))
- return -EINVAL;
-
- rate = pclk->ops->get_rate(pclk);
- clk_put(pclk);
-
- return rate;
-}
-
-struct clk_ops s5p_sclk_spdif_ops = {
- .set_rate = s5p_spdif_set_rate,
- .get_rate = s5p_spdif_get_rate,
-};
-
-static struct clk *s5p_clks[] __initdata = {
- &clk_ext_xtal_mux,
- &clk_48m,
- &s5p_clk_27m,
- &clk_fout_apll,
- &clk_fout_mpll,
- &clk_fout_epll,
- &clk_fout_dpll,
- &clk_fout_vpll,
- &clk_vpll,
- &clk_xusbxti,
-};
-
-void __init s5p_register_clocks(unsigned long xtal_freq)
-{
- int ret;
-
- clk_ext_xtal_mux.rate = xtal_freq;
-
- ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
- if (ret > 0)
- printk(KERN_ERR "Failed to register s5p clocks\n");
-}
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c
index 469b86260fe3..0b04b6b0fa30 100644
--- a/arch/arm/plat-samsung/s5p-dev-mfc.c
+++ b/arch/arm/plat-samsung/s5p-dev-mfc.c
@@ -17,56 +17,16 @@
#include <linux/of_fdt.h>
#include <linux/of.h>
-#include <plat/mfc.h>
-
-#ifdef CONFIG_SAMSUNG_ATAGS
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <plat/devs.h>
-
-static struct resource s5p_mfc_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_MFC, SZ_64K),
- [1] = DEFINE_RES_IRQ(IRQ_MFC),
-};
-
-struct platform_device s5p_device_mfc = {
- .name = "s5p-mfc",
- .id = -1,
- .num_resources = ARRAY_SIZE(s5p_mfc_resource),
- .resource = s5p_mfc_resource,
-};
-
-/*
- * MFC hardware has 2 memory interfaces which are modelled as two separate
- * platform devices to let dma-mapping distinguish between them.
- *
- * MFC parent device (s5p_device_mfc) must be registered before memory
- * interface specific devices (s5p_device_mfc_l and s5p_device_mfc_r).
- */
-
-struct platform_device s5p_device_mfc_l = {
- .name = "s5p-mfc-l",
- .id = -1,
- .dev = {
- .parent = &s5p_device_mfc.dev,
- .dma_mask = &s5p_device_mfc_l.dev.coherent_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-struct platform_device s5p_device_mfc_r = {
- .name = "s5p-mfc-r",
- .id = -1,
- .dev = {
- .parent = &s5p_device_mfc.dev,
- .dma_mask = &s5p_device_mfc_r.dev.coherent_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-#else
static struct platform_device s5p_device_mfc_l;
static struct platform_device s5p_device_mfc_r;
-#endif
+
+struct s5p_mfc_dt_meminfo {
+ unsigned long loff;
+ unsigned long lsize;
+ unsigned long roff;
+ unsigned long rsize;
+ char *compatible;
+};
struct s5p_mfc_reserved_mem {
phys_addr_t base;
@@ -77,7 +37,7 @@ struct s5p_mfc_reserved_mem {
static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
-void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
+static void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize)
{
int i;
@@ -100,28 +60,6 @@ void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
}
}
-#ifdef CONFIG_SAMSUNG_ATAGS
-static int __init s5p_mfc_memory_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
- struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
- if (!area->base)
- continue;
-
- if (dma_declare_coherent_memory(area->dev, area->base,
- area->base, area->size,
- DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
- printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
- area->size, (unsigned long) area->base);
- }
- return 0;
-}
-device_initcall(s5p_mfc_memory_init);
-#endif
-
-#ifdef CONFIG_OF
int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
int depth, void *data)
{
@@ -154,4 +92,3 @@ int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
return 1;
}
-#endif
diff --git a/arch/arm/plat-samsung/s5p-dev-uart.c b/arch/arm/plat-samsung/s5p-dev-uart.c
deleted file mode 100644
index 8c4487af98c8..000000000000
--- a/arch/arm/plat-samsung/s5p-dev-uart.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2009,2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Base S5P UART resource and device definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
- /* Serial port registrations */
-
-static struct resource s5p_uart0_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_UART0, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART0),
-};
-
-static struct resource s5p_uart1_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_UART1, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART1),
-};
-
-static struct resource s5p_uart2_resource[] = {
- [0] = DEFINE_RES_MEM(S5P_PA_UART2, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART2),
-};
-
-static struct resource s5p_uart3_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
- [0] = DEFINE_RES_MEM(S5P_PA_UART3, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART3),
-#endif
-};
-
-static struct resource s5p_uart4_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 4
- [0] = DEFINE_RES_MEM(S5P_PA_UART4, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART4),
-#endif
-};
-
-static struct resource s5p_uart5_resource[] = {
-#if CONFIG_SERIAL_SAMSUNG_UARTS > 5
- [0] = DEFINE_RES_MEM(S5P_PA_UART5, S5P_SZ_UART),
- [1] = DEFINE_RES_IRQ(IRQ_UART5),
-#endif
-};
-
-struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
- [0] = {
- .resources = s5p_uart0_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart0_resource),
- },
- [1] = {
- .resources = s5p_uart1_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart1_resource),
- },
- [2] = {
- .resources = s5p_uart2_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart2_resource),
- },
- [3] = {
- .resources = s5p_uart3_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart3_resource),
- },
- [4] = {
- .resources = s5p_uart4_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart4_resource),
- },
- [5] = {
- .resources = s5p_uart5_resource,
- .nr_resources = ARRAY_SIZE(s5p_uart5_resource),
- },
-};
diff --git a/arch/arm/plat-samsung/s5p-irq-eint.c b/arch/arm/plat-samsung/s5p-irq-eint.c
deleted file mode 100644
index ebee4dc11a94..000000000000
--- a/arch/arm/plat-samsung/s5p-irq-eint.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P - IRQ EINT support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/irqchip/arm-vic.h>
-#include <linux/of.h>
-
-#include <plat/regs-irqtype.h>
-
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-
-#include <plat/gpio-cfg.h>
-#include <mach/regs-gpio.h>
-
-static inline void s5p_irq_eint_mask(struct irq_data *data)
-{
- u32 mask;
-
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
- mask |= eint_irq_to_bit(data->irq);
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_eint_unmask(struct irq_data *data)
-{
- u32 mask;
-
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
- mask &= ~(eint_irq_to_bit(data->irq));
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-}
-
-static inline void s5p_irq_eint_ack(struct irq_data *data)
-{
- __raw_writel(eint_irq_to_bit(data->irq),
- S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_eint_maskack(struct irq_data *data)
-{
- /* compiler should in-line these */
- s5p_irq_eint_mask(data);
- s5p_irq_eint_ack(data);
-}
-
-static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
- int offs = EINT_OFFSET(data->irq);
- int shift;
- u32 ctrl, mask;
- u32 newvalue = 0;
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- newvalue = S5P_IRQ_TYPE_EDGE_RISING;
- break;
-
- case IRQ_TYPE_EDGE_FALLING:
- newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
- break;
-
- case IRQ_TYPE_EDGE_BOTH:
- newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
- break;
-
- case IRQ_TYPE_LEVEL_LOW:
- newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
- break;
-
- case IRQ_TYPE_LEVEL_HIGH:
- newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
- break;
-
- default:
- printk(KERN_ERR "No such irq type %d", type);
- return -EINVAL;
- }
-
- shift = (offs & 0x7) * 4;
- mask = 0x7 << shift;
-
- ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
- ctrl &= ~mask;
- ctrl |= newvalue << shift;
- __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
-
- if ((0 <= offs) && (offs < 8))
- s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-
- else if ((8 <= offs) && (offs < 16))
- s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-
- else if ((16 <= offs) && (offs < 24))
- s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-
- else if ((24 <= offs) && (offs < 32))
- s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-
- else
- printk(KERN_ERR "No such irq number %d", offs);
-
- return 0;
-}
-
-static struct irq_chip s5p_irq_eint = {
- .name = "s5p-eint",
- .irq_mask = s5p_irq_eint_mask,
- .irq_unmask = s5p_irq_eint_unmask,
- .irq_mask_ack = s5p_irq_eint_maskack,
- .irq_ack = s5p_irq_eint_ack,
- .irq_set_type = s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
- .irq_set_wake = s3c_irqext_wake,
-#endif
-};
-
-/* s5p_irq_demux_eint
- *
- * This function demuxes the IRQ from the group0 external interrupts,
- * from EINTs 16 to 31. It is designed to be inlined into the specific
- * handler s5p_irq_demux_eintX_Y.
- *
- * Each EINT pend/mask registers handle eight of them.
- */
-static inline void s5p_irq_demux_eint(unsigned int start)
-{
- u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
- u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
- unsigned int irq;
-
- status &= ~mask;
- status &= 0xff;
-
- while (status) {
- irq = fls(status) - 1;
- generic_handle_irq(irq + start);
- status &= ~(1 << irq);
- }
-}
-
-static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
- s5p_irq_demux_eint(IRQ_EINT(16));
- s5p_irq_demux_eint(IRQ_EINT(24));
-}
-
-static inline void s5p_irq_vic_eint_mask(struct irq_data *data)
-{
- void __iomem *base = irq_data_get_irq_chip_data(data);
-
- s5p_irq_eint_mask(data);
- writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR);
-}
-
-static void s5p_irq_vic_eint_unmask(struct irq_data *data)
-{
- void __iomem *base = irq_data_get_irq_chip_data(data);
-
- s5p_irq_eint_unmask(data);
- writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE);
-}
-
-static inline void s5p_irq_vic_eint_ack(struct irq_data *data)
-{
- __raw_writel(eint_irq_to_bit(data->irq),
- S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5p_irq_vic_eint_maskack(struct irq_data *data)
-{
- s5p_irq_vic_eint_mask(data);
- s5p_irq_vic_eint_ack(data);
-}
-
-static struct irq_chip s5p_irq_vic_eint = {
- .name = "s5p_vic_eint",
- .irq_mask = s5p_irq_vic_eint_mask,
- .irq_unmask = s5p_irq_vic_eint_unmask,
- .irq_mask_ack = s5p_irq_vic_eint_maskack,
- .irq_ack = s5p_irq_vic_eint_ack,
- .irq_set_type = s5p_irq_eint_set_type,
-#ifdef CONFIG_PM
- .irq_set_wake = s3c_irqext_wake,
-#endif
-};
-
-static int __init s5p_init_irq_eint(void)
-{
- int irq;
-
- if (of_have_populated_dt())
- return -ENODEV;
-
- for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
- irq_set_chip(irq, &s5p_irq_vic_eint);
-
- for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
- irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-
- irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
- return 0;
-}
-
-arch_initcall(s5p_init_irq_eint);
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c
deleted file mode 100644
index fafdb059043a..000000000000
--- a/arch/arm/plat-samsung/s5p-irq-gpioint.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * Author: Kyungmin Park <kyungmin.park@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- * Author: Marek Szyprowski <m.szyprowski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-
-#include <mach/map.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-
-#define GPIO_BASE(chip) ((void __iomem *)((unsigned long)((chip)->base) & 0xFFFFF000u))
-
-#define CON_OFFSET 0x700
-#define MASK_OFFSET 0x900
-#define PEND_OFFSET 0xA00
-#define REG_OFFSET(x) ((x) << 2)
-
-struct s5p_gpioint_bank {
- struct list_head list;
- int start;
- int nr_groups;
- int irq;
- struct samsung_gpio_chip **chips;
- void (*handler)(unsigned int, struct irq_desc *);
-};
-
-static LIST_HEAD(banks);
-
-static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct irq_chip_type *ct = gc->chip_types;
- unsigned int shift = (d->irq - gc->irq_base) << 2;
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- type = S5P_IRQ_TYPE_EDGE_RISING;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- type = S5P_IRQ_TYPE_EDGE_FALLING;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- type = S5P_IRQ_TYPE_EDGE_BOTH;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- type = S5P_IRQ_TYPE_LEVEL_HIGH;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- type = S5P_IRQ_TYPE_LEVEL_LOW;
- break;
- case IRQ_TYPE_NONE:
- default:
- printk(KERN_WARNING "No irq type\n");
- return -EINVAL;
- }
-
- gc->type_cache &= ~(0x7 << shift);
- gc->type_cache |= type << shift;
- writel(gc->type_cache, gc->reg_base + ct->regs.type);
- return 0;
-}
-
-static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
-{
- struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
- int group, pend_offset, mask_offset;
- unsigned int pend, mask;
-
- struct irq_chip *chip = irq_get_chip(irq);
- chained_irq_enter(chip, desc);
-
- for (group = 0; group < bank->nr_groups; group++) {
- struct samsung_gpio_chip *chip = bank->chips[group];
- if (!chip)
- continue;
-
- pend_offset = REG_OFFSET(group);
- pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
- if (!pend)
- continue;
-
- mask_offset = REG_OFFSET(group);
- mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
- pend &= ~mask;
-
- while (pend) {
- int offset = fls(pend) - 1;
- int real_irq = chip->irq_base + offset;
- generic_handle_irq(real_irq);
- pend &= ~BIT(offset);
- }
- }
- chained_irq_exit(chip, desc);
-}
-
-static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
-{
- static int used_gpioint_groups = 0;
- int group = chip->group;
- struct s5p_gpioint_bank *b, *bank = NULL;
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
- return -ENOMEM;
-
- list_for_each_entry(b, &banks, list) {
- if (group >= b->start && group < b->start + b->nr_groups) {
- bank = b;
- break;
- }
- }
- if (!bank)
- return -EINVAL;
-
- if (!bank->handler) {
- bank->chips = kzalloc(sizeof(struct samsung_gpio_chip *) *
- bank->nr_groups, GFP_KERNEL);
- if (!bank->chips)
- return -ENOMEM;
-
- irq_set_chained_handler(bank->irq, s5p_gpioint_handler);
- irq_set_handler_data(bank->irq, bank);
- bank->handler = s5p_gpioint_handler;
- printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
- bank->irq);
- }
-
- /*
- * chained GPIO irq has been successfully registered, allocate new gpio
- * int group and assign irq nubmers
- */
- chip->irq_base = S5P_GPIOINT_BASE +
- used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
- used_gpioint_groups++;
-
- bank->chips[group - bank->start] = chip;
-
- gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
- GPIO_BASE(chip),
- handle_level_irq);
- if (!gc)
- return -ENOMEM;
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack_set_bit;
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = s5p_gpioint_set_type,
- ct->regs.ack = PEND_OFFSET + REG_OFFSET(group - bank->start);
- ct->regs.mask = MASK_OFFSET + REG_OFFSET(group - bank->start);
- ct->regs.type = CON_OFFSET + REG_OFFSET(group - bank->start);
- irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
- IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
- return 0;
-}
-
-int __init s5p_register_gpio_interrupt(int pin)
-{
- struct samsung_gpio_chip *my_chip = samsung_gpiolib_getchip(pin);
- int offset, group;
- int ret;
-
- if (!my_chip)
- return -EINVAL;
-
- offset = pin - my_chip->chip.base;
- group = my_chip->group;
-
- /* check if the group has been already registered */
- if (my_chip->irq_base)
- goto success;
-
- /* register gpio group */
- ret = s5p_gpioint_add(my_chip);
- if (ret == 0) {
- my_chip->chip.to_irq = samsung_gpiolib_to_irq;
- printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
- group);
- goto success;
- }
- return ret;
-success:
- my_chip->bitmap_gpio_int |= BIT(offset);
-
- return my_chip->irq_base + offset;
-}
-
-int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
-{
- struct s5p_gpioint_bank *bank;
-
- bank = kzalloc(sizeof(*bank), GFP_KERNEL);
- if (!bank)
- return -ENOMEM;
-
- bank->start = start;
- bank->nr_groups = nr_groups;
- bank->irq = chain_irq;
-
- list_add_tail(&bank->list, &banks);
- return 0;
-}
diff --git a/arch/arm/plat-samsung/s5p-irq-pm.c b/arch/arm/plat-samsung/s5p-irq-pm.c
deleted file mode 100644
index 52b16943617e..000000000000
--- a/arch/arm/plat-samsung/s5p-irq-pm.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Based on arch/arm/plat-s3c24xx/irq-pm.c,
- * Copyright (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-
-#include <plat/cpu.h>
-#include <plat/irqs.h>
-#include <plat/pm.h>
-#include <mach/map.h>
-
-#include <mach/regs-gpio.h>
-#include <mach/regs-irq.h>
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM,
- * as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow = 0x00000006L;
-unsigned long s3c_irqwake_eintallow = 0xffffffffL;
-
-int s3c_irq_wake(struct irq_data *data, unsigned int state)
-{
- unsigned long irqbit;
- unsigned int irq_rtc_tic, irq_rtc_alarm;
-
- irq_rtc_tic = IRQ_RTC_TIC;
- irq_rtc_alarm = IRQ_RTC_ALARM;
-
- if (data->irq == irq_rtc_tic || data->irq == irq_rtc_alarm) {
- irqbit = 1 << (data->irq + 1 - irq_rtc_alarm);
-
- if (!state)
- s3c_irqwake_intmask |= irqbit;
- else
- s3c_irqwake_intmask &= ~irqbit;
- } else {
- return -ENOENT;
- }
-
- return 0;
-}
-
-static struct sleep_save eint_save[] = {
- SAVE_ITEM(S5P_EINT_CON(0)),
- SAVE_ITEM(S5P_EINT_CON(1)),
- SAVE_ITEM(S5P_EINT_CON(2)),
- SAVE_ITEM(S5P_EINT_CON(3)),
-
- SAVE_ITEM(S5P_EINT_FLTCON(0)),
- SAVE_ITEM(S5P_EINT_FLTCON(1)),
- SAVE_ITEM(S5P_EINT_FLTCON(2)),
- SAVE_ITEM(S5P_EINT_FLTCON(3)),
- SAVE_ITEM(S5P_EINT_FLTCON(4)),
- SAVE_ITEM(S5P_EINT_FLTCON(5)),
- SAVE_ITEM(S5P_EINT_FLTCON(6)),
- SAVE_ITEM(S5P_EINT_FLTCON(7)),
-
- SAVE_ITEM(S5P_EINT_MASK(0)),
- SAVE_ITEM(S5P_EINT_MASK(1)),
- SAVE_ITEM(S5P_EINT_MASK(2)),
- SAVE_ITEM(S5P_EINT_MASK(3)),
-};
-
-int s3c24xx_irq_suspend(void)
-{
- s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save));
-
- return 0;
-}
-
-void s3c24xx_irq_resume(void)
-{
- s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save));
-}
-
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
deleted file mode 100644
index ddfaca9c79d8..000000000000
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * S5P - Interrupt handling
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-vic.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <plat/cpu.h>
-
-void __init s5p_init_irq(u32 *vic, u32 num_vic)
-{
-#ifdef CONFIG_ARM_VIC
- int irq;
-
- /* initialize the VICs */
- for (irq = 0; irq < num_vic; irq++)
- vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
-#endif
-}
diff --git a/arch/arm/plat-samsung/s5p-pm.c b/arch/arm/plat-samsung/s5p-pm.c
deleted file mode 100644
index 0747468f0936..000000000000
--- a/arch/arm/plat-samsung/s5p-pm.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * S5P Power Manager (Suspend-To-RAM) support
- *
- * Based on arch/arm/plat-s3c24xx/pm.c
- * Copyright (c) 2004,2006 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/suspend.h>
-#include <plat/pm.h>
-
-#define PFX "s5p pm: "
-
-/* s3c_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
-
-void s3c_pm_configure_extint(void)
-{
- /* nothing here yet */
-}
-
-void s3c_pm_restore_core(void)
-{
- /* nothing here yet */
-}
-
-void s3c_pm_save_core(void)
-{
- /* nothing here yet */
-}
-
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index fce41e93b6a4..a301ca2c7d00 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -3,9 +3,6 @@ if PLAT_VERSATILE
config PLAT_VERSATILE_CLOCK
bool
-config PLAT_VERSATILE_CLCD
- bool
-
config PLAT_VERSATILE_SCHED_CLOCK
def_bool y
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 2e0c472958ae..03c4900ac3f4 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,6 +1,5 @@
ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
-obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/plat-versatile/include/plat/clcd.h b/arch/arm/plat-versatile/include/plat/clcd.h
deleted file mode 100644
index 6bb6a1d2019b..000000000000
--- a/arch/arm/plat-versatile/include/plat/clcd.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PLAT_CLCD_H
-#define PLAT_CLCD_H
-
-struct clcd_panel *versatile_clcd_get_panel(const char *);
-int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long);
-int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *);
-void versatile_clcd_remove_dma(struct clcd_fb *);
-
-#endif
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index fe6ca574d093..2e78760f3495 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -34,7 +34,7 @@ ENDPROC(do_vfp)
ENTRY(vfp_null_entry)
dec_preempt_count_ti r10, r4
- mov pc, lr
+ ret lr
ENDPROC(vfp_null_entry)
.align 2
@@ -49,7 +49,7 @@ ENTRY(vfp_testing_entry)
dec_preempt_count_ti r10, r4
ldr r0, VFP_arch_address
str r0, [r0] @ set to non-zero value
- mov pc, r9 @ we have handled the fault
+ ret r9 @ we have handled the fault
ENDPROC(vfp_testing_entry)
.align 2
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index be807625ed8c..cda654cbf2c2 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -183,7 +183,7 @@ vfp_hw_state_valid:
@ always subtract 4 from the following
@ instruction address.
dec_preempt_count_ti r10, r4
- mov pc, r9 @ we think we have handled things
+ ret r9 @ we think we have handled things
look_for_VFP_exceptions:
@@ -202,7 +202,7 @@ look_for_VFP_exceptions:
DBGSTR "not VFP"
dec_preempt_count_ti r10, r4
- mov pc, lr
+ ret lr
process_exception:
DBGSTR "bounce"
@@ -234,7 +234,7 @@ ENTRY(vfp_save_state)
VFPFMRX r12, FPINST2 @ FPINST2 if needed (and present)
1:
stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
- mov pc, lr
+ ret lr
ENDPROC(vfp_save_state)
.align
@@ -245,7 +245,7 @@ vfp_current_hw_state_address:
#ifdef CONFIG_THUMB2_KERNEL
adr \tmp, 1f
add \tmp, \tmp, \base, lsl \shift
- mov pc, \tmp
+ ret \tmp
#else
add pc, pc, \base, lsl \shift
mov r0, r0
@@ -257,10 +257,10 @@ ENTRY(vfp_get_float)
tbl_branch r0, r3, #3
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0
- mov pc, lr
+ ret lr
.org 1b + 8
1: mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
ENDPROC(vfp_get_float)
@@ -269,10 +269,10 @@ ENTRY(vfp_put_float)
tbl_branch r1, r3, #3
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0
- mov pc, lr
+ ret lr
.org 1b + 8
1: mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
ENDPROC(vfp_put_float)
@@ -281,14 +281,14 @@ ENTRY(vfp_get_double)
tbl_branch r0, r3, #3
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: fmrrd r0, r1, d\dr
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
#ifdef CONFIG_VFPv3
@ d16 - d31 registers
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
#endif
@@ -296,21 +296,21 @@ ENTRY(vfp_get_double)
@ virtual register 16 (or 32 if VFPv3) for compare with zero
mov r0, #0
mov r1, #0
- mov pc, lr
+ ret lr
ENDPROC(vfp_get_double)
ENTRY(vfp_put_double)
tbl_branch r2, r3, #3
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: fmdrr d\dr, r0, r1
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
#ifdef CONFIG_VFPv3
@ d16 - d31 registers
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1: mcrr p11, 3, r0, r1, c\dr @ fmdrr r0, r1, d\dr
- mov pc, lr
+ ret lr
.org 1b + 8
.endr
#endif
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 1e632430570b..98544c5f86e9 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -181,8 +181,7 @@ static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
struct sched_shutdown r = { .reason = SHUTDOWN_reboot };
int rc;
rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
- if (rc)
- BUG();
+ BUG_ON(rc);
}
static void xen_power_off(void)
@@ -190,8 +189,7 @@ static void xen_power_off(void)
struct sched_shutdown r = { .reason = SHUTDOWN_poweroff };
int rc;
rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
- if (rc)
- BUG();
+ BUG_ON(rc);
}
static int xen_cpu_notification(struct notifier_block *self,
diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c
index 91cf08ba1e95..e43791829ace 100644
--- a/arch/arm/xen/grant-table.c
+++ b/arch/arm/xen/grant-table.c
@@ -45,14 +45,7 @@ void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
return;
}
-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
- unsigned long max_nr_gframes,
- grant_status_t **__shared)
-{
- return -ENOSYS;
-}
-
-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
+int arch_gnttab_init(unsigned long nr_shared)
{
return 0;
}
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
index 44e3a5f10c4c..f00e08075938 100644
--- a/arch/arm/xen/hypercall.S
+++ b/arch/arm/xen/hypercall.S
@@ -58,7 +58,7 @@
ENTRY(HYPERVISOR_##hypercall) \
mov r12, #__HYPERVISOR_##hypercall; \
__HVC(XEN_IMM); \
- mov pc, lr; \
+ ret lr; \
ENDPROC(HYPERVISOR_##hypercall)
#define HYPERCALL0 HYPERCALL_SIMPLE
@@ -74,7 +74,7 @@ ENTRY(HYPERVISOR_##hypercall) \
mov r12, #__HYPERVISOR_##hypercall; \
__HVC(XEN_IMM); \
ldm sp!, {r4} \
- mov pc, lr \
+ ret lr \
ENDPROC(HYPERVISOR_##hypercall)
.text
@@ -101,5 +101,5 @@ ENTRY(privcmd_call)
ldr r4, [sp, #4]
__HVC(XEN_IMM)
ldm sp!, {r4}
- mov pc, lr
+ ret lr
ENDPROC(privcmd_call);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 839f48c26ef0..fd4e81a4e1ce 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1,7 +1,7 @@
config ARM64
def_bool y
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
- select ARCH_HAS_OPP
+ select ARCH_HAS_SG_CHAIN
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_SUPPORTS_ATOMIC_RMW
@@ -11,6 +11,8 @@ config ARM64
select ARM_AMBA
select ARM_ARCH_TIMER
select ARM_GIC
+ select AUDIT_ARCH_COMPAT_GENERIC
+ select ARM_GIC_V3
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
select COMMON_CLK
@@ -29,10 +31,12 @@ config ARM64
select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select HARDIRQS_SW_RESEND
+ select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
select HAVE_C_RECORDMCOUNT
+ select HAVE_CC_STACKPROTECTOR
select HAVE_DEBUG_BUGVERBOSE
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_API_DEBUG
@@ -63,6 +67,7 @@ config ARM64
select RTC_LIB
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
+ select HAVE_CONTEXT_TRACKING
help
ARM 64-bit (AArch64) Linux support.
@@ -155,14 +160,63 @@ endmenu
menu "Kernel Features"
+choice
+ prompt "Page size"
+ default ARM64_4K_PAGES
+ help
+ Page size (translation granule) configuration.
+
+config ARM64_4K_PAGES
+ bool "4KB"
+ help
+ This feature enables 4KB pages support.
+
config ARM64_64K_PAGES
- bool "Enable 64KB pages support"
+ bool "64KB"
help
This feature enables 64KB pages support (4KB by default)
allowing only two levels of page tables and faster TLB
look-up. AArch32 emulation is not available when this feature
is enabled.
+endchoice
+
+choice
+ prompt "Virtual address space size"
+ default ARM64_VA_BITS_39 if ARM64_4K_PAGES
+ default ARM64_VA_BITS_42 if ARM64_64K_PAGES
+ help
+ Allows choosing one of multiple possible virtual address
+ space sizes. The level of translation table is determined by
+ a combination of page size and virtual address space size.
+
+config ARM64_VA_BITS_39
+ bool "39-bit"
+ depends on ARM64_4K_PAGES
+
+config ARM64_VA_BITS_42
+ bool "42-bit"
+ depends on ARM64_64K_PAGES
+
+config ARM64_VA_BITS_48
+ bool "48-bit"
+ depends on BROKEN
+
+endchoice
+
+config ARM64_VA_BITS
+ int
+ default 39 if ARM64_VA_BITS_39
+ default 42 if ARM64_VA_BITS_42
+ default 48 if ARM64_VA_BITS_48
+
+config ARM64_PGTABLE_LEVELS
+ int
+ default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42
+ default 3 if ARM64_64K_PAGES && ARM64_VA_BITS_48
+ default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39
+ default 4 if ARM64_4K_PAGES && ARM64_VA_BITS_48
+
config CPU_BIG_ENDIAN
bool "Build big-endian kernel"
help
@@ -294,12 +348,18 @@ config CMDLINE_FORCE
This is useful if you cannot or don't want to change the
command-line options your boot loader passes to the kernel.
+config EFI_STUB
+ bool
+
config EFI
bool "UEFI runtime support"
depends on OF && !CPU_BIG_ENDIAN
select LIBFDT
select UCS2_STRING
select EFI_PARAMS_FROM_FDT
+ select EFI_RUNTIME_WRAPPERS
+ select EFI_STUB
+ select EFI_ARMSTUB
default y
help
This option provides support for runtime services provided
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 1c1b75629842..4ee8e90b7a45 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -28,4 +28,19 @@ config PID_IN_CONTEXTIDR
instructions during context switch. Say Y here only if you are
planning to use hardware trace tools with this kernel.
+config ARM64_RANDOMIZE_TEXT_OFFSET
+ bool "Randomize TEXT_OFFSET at build time"
+ help
+ Say Y here if you want the image load offset (AKA TEXT_OFFSET)
+ of the kernel to be randomized at build-time. When selected,
+ this option will cause TEXT_OFFSET to be randomized upon any
+ build of the kernel, and the offset will be reflected in the
+ text_offset field of the resulting Image. This can be used to
+ fuzz-test bootloaders which respect text_offset.
+
+ This option is intended for bootloader and/or kernel testing
+ only. Bootloaders must make no assumptions regarding the value
+ of TEXT_OFFSET and platforms must not require a specific
+ value.
+
endmenu
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 8185a913c5ed..57833546bf00 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -38,7 +38,11 @@ CHECKFLAGS += -D__aarch64__
head-y := arch/arm64/kernel/head.o
# The byte offset of the kernel image in RAM from the start of RAM.
+ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
+TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%04x0\n", int(65535 * rand())}')
+else
TEXT_OFFSET := 0x00080000
+endif
export TEXT_OFFSET GZFLAGS
@@ -48,6 +52,7 @@ core-$(CONFIG_XEN) += arch/arm64/xen/
core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
+libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/
# Default target when executing plain make
KBUILD_IMAGE := Image.gz
diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
index 6541962f5d70..b2f56229aa5e 100644
--- a/arch/arm64/boot/dts/apm-mustang.dts
+++ b/arch/arm64/boot/dts/apm-mustang.dts
@@ -28,3 +28,7 @@
&serial0 {
status = "ok";
};
+
+&menet {
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index 40aa96ce13c4..c0aceef7f5b3 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -167,14 +167,13 @@
clock-output-names = "ethclk";
};
- eth8clk: eth8clk {
+ menetclk: menetclk {
compatible = "apm,xgene-device-clock";
#clock-cells = <1>;
clocks = <&ethclk 0>;
- clock-names = "eth8clk";
reg = <0x0 0x1702C000 0x0 0x1000>;
reg-names = "csr-reg";
- clock-output-names = "eth8clk";
+ clock-output-names = "menetclk";
};
sataphy1clk: sataphy1clk@1f21c000 {
@@ -397,5 +396,30 @@
#clock-cells = <1>;
clocks = <&rtcclk 0>;
};
+
+ menet: ethernet@17020000 {
+ compatible = "apm,xgene-enet";
+ status = "disabled";
+ reg = <0x0 0x17020000 0x0 0xd100>,
+ <0x0 0X17030000 0x0 0X400>,
+ <0x0 0X10000000 0x0 0X200>;
+ reg-names = "enet_csr", "ring_csr", "ring_cmd";
+ interrupts = <0x0 0x3c 0x4>;
+ dma-coherent;
+ clocks = <&menetclk 0>;
+ local-mac-address = [00 01 73 00 00 01];
+ phy-connection-type = "rgmii";
+ phy-handle = <&menetphy>;
+ mdio {
+ compatible = "apm,xgene-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ menetphy: menetphy@3 {
+ compatible = "ethernet-phy-id001c.c915";
+ reg = <0x3>;
+ };
+
+ };
+ };
};
};
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 3421f316f5dc..1e52b741d806 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -52,8 +52,11 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
@@ -65,6 +68,7 @@ CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_NETDEVICES=y
CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
# CONFIG_WLAN is not set
@@ -76,6 +80,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_VIRTIO_CONSOLE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
CONFIG_REGULATOR=y
@@ -90,6 +95,7 @@ CONFIG_USB_ISP1760_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_ARMMMCI=y
+CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MMIO=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT2_FS=y
@@ -107,6 +113,7 @@ CONFIG_HUGETLBFS=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
+CONFIG_9P_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_VIRTUALIZATION=y
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index 2070a56ecc46..a3f935fde975 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -35,4 +35,4 @@ AFLAGS_aes-neon.o := -DINTERLEAVE=4
CFLAGS_aes-glue-ce.o := -DUSE_V8_CRYPTO_EXTENSIONS
$(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
- $(call if_changed_dep,cc_o_c)
+ $(call if_changed_rule,cc_o_c)
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index a5176cf32dad..f2defe1c380c 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -138,19 +138,10 @@ static inline void __flush_icache_all(void)
#define flush_icache_page(vma,page) do { } while (0)
/*
- * flush_cache_vmap() is used when creating mappings (eg, via vmap,
- * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT
- * caches, since the direct-mappings of these pages may contain cached
- * data, we need to do a full cache flush to ensure that writebacks
- * don't corrupt data placed into these pages via the new mappings.
+ * Not required on AArch64 (PIPT or VIPT non-aliasing D-cache).
*/
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
- /*
- * set_pte_at() called from vmap_pte_range() does not
- * have a DSB after cleaning the cache line.
- */
- dsb(ish);
}
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
index 4b23e758d5e0..7a2e0762cb40 100644
--- a/arch/arm64/include/asm/cachetype.h
+++ b/arch/arm64/include/asm/cachetype.h
@@ -30,10 +30,14 @@
#ifndef __ASSEMBLY__
-static inline u32 icache_policy(void)
-{
- return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK;
-}
+#include <linux/bitops.h>
+
+#define CTR_L1IP(ctr) (((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
+
+#define ICACHEF_ALIASING BIT(0)
+#define ICACHEF_AIVIVT BIT(1)
+
+extern unsigned long __icache_flags;
/*
* Whilst the D-side always behaves as PIPT on AArch64, aliasing is
@@ -41,12 +45,12 @@ static inline u32 icache_policy(void)
*/
static inline int icache_is_aliasing(void)
{
- return icache_policy() != ICACHE_POLICY_PIPT;
+ return test_bit(ICACHEF_ALIASING, &__icache_flags);
}
static inline int icache_is_aivivt(void)
{
- return icache_policy() == ICACHE_POLICY_AIVIVT;
+ return test_bit(ICACHEF_AIVIVT, &__icache_flags);
}
static inline u32 cache_type_cwg(void)
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
new file mode 100644
index 000000000000..056443086019
--- /dev/null
+++ b/arch/arm64/include/asm/cpu.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CPU_H
+#define __ASM_CPU_H
+
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+
+/*
+ * Records attributes of an individual CPU.
+ */
+struct cpuinfo_arm64 {
+ struct cpu cpu;
+ u32 reg_ctr;
+ u32 reg_cntfrq;
+ u32 reg_dczid;
+ u32 reg_midr;
+
+ u64 reg_id_aa64isar0;
+ u64 reg_id_aa64isar1;
+ u64 reg_id_aa64mmfr0;
+ u64 reg_id_aa64mmfr1;
+ u64 reg_id_aa64pfr0;
+ u64 reg_id_aa64pfr1;
+
+ u32 reg_id_isar0;
+ u32 reg_id_isar1;
+ u32 reg_id_isar2;
+ u32 reg_id_isar3;
+ u32 reg_id_isar4;
+ u32 reg_id_isar5;
+ u32 reg_id_mmfr0;
+ u32 reg_id_mmfr1;
+ u32 reg_id_mmfr2;
+ u32 reg_id_mmfr3;
+ u32 reg_id_pfr0;
+ u32 reg_id_pfr1;
+};
+
+DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
+
+void cpuinfo_store_cpu(void);
+void __init cpuinfo_store_boot_cpu(void);
+
+#endif /* __ASM_CPU_H */
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 27f54a7cc81b..379d0b874328 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -18,6 +18,8 @@
#define INVALID_HWID ULONG_MAX
+#define MPIDR_UP_BITMASK (0x1 << 30)
+#define MPIDR_MT_BITMASK (0x1 << 24)
#define MPIDR_HWID_BITMASK 0xff00ffffff
#define MPIDR_LEVEL_BITS_SHIFT 3
@@ -36,15 +38,34 @@
__val; \
})
+#define MIDR_REVISION_MASK 0xf
+#define MIDR_REVISION(midr) ((midr) & MIDR_REVISION_MASK)
+#define MIDR_PARTNUM_SHIFT 4
+#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
+#define MIDR_PARTNUM(midr) \
+ (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
+#define MIDR_ARCHITECTURE_SHIFT 16
+#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_ARCHITECTURE(midr) \
+ (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_VARIANT_SHIFT 20
+#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
+#define MIDR_VARIANT(midr) \
+ (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
+#define MIDR_IMPLEMENTOR_SHIFT 24
+#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT)
+#define MIDR_IMPLEMENTOR(midr) \
+ (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
+
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_APM 0x50
-#define ARM_CPU_PART_AEM_V8 0xD0F0
-#define ARM_CPU_PART_FOUNDATION 0xD000
-#define ARM_CPU_PART_CORTEX_A53 0xD030
-#define ARM_CPU_PART_CORTEX_A57 0xD070
+#define ARM_CPU_PART_AEM_V8 0xD0F
+#define ARM_CPU_PART_FOUNDATION 0xD00
+#define ARM_CPU_PART_CORTEX_A57 0xD07
+#define ARM_CPU_PART_CORTEX_A53 0xD03
-#define APM_CPU_PART_POTENZA 0x0000
+#define APM_CPU_PART_POTENZA 0x000
#ifndef __ASSEMBLY__
@@ -65,12 +86,12 @@ static inline u64 __attribute_const__ read_cpuid_mpidr(void)
static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
{
- return (read_cpuid_id() & 0xFF000000) >> 24;
+ return MIDR_IMPLEMENTOR(read_cpuid_id());
}
static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
{
- return (read_cpuid_id() & 0xFFF0);
+ return MIDR_PARTNUM(read_cpuid_id());
}
static inline u32 __attribute_const__ read_cpuid_cachetype(void)
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index 6e9b5b36921c..7fb343779498 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -18,6 +18,15 @@
#ifdef __KERNEL__
+/* Low-level stepping controls. */
+#define DBG_MDSCR_SS (1 << 0)
+#define DBG_SPSR_SS (1 << 21)
+
+/* MDSCR_EL1 enabling bits */
+#define DBG_MDSCR_KDE (1 << 13)
+#define DBG_MDSCR_MDE (1 << 15)
+#define DBG_MDSCR_MASK ~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
+
#define DBG_ESR_EVT(x) (((x) >> 27) & 0x7)
/* AArch64 */
@@ -73,11 +82,6 @@
#define CACHE_FLUSH_IS_SAFE 1
-enum debug_el {
- DBG_ACTIVE_EL0 = 0,
- DBG_ACTIVE_EL1,
-};
-
/* AArch32 */
#define DBG_ESR_EVT_BKPT 0x4
#define DBG_ESR_EVT_VECC 0x5
@@ -115,6 +119,11 @@ void unregister_break_hook(struct break_hook *hook);
u8 debug_monitors_arch(void);
+enum debug_el {
+ DBG_ACTIVE_EL0 = 0,
+ DBG_ACTIVE_EL1,
+};
+
void enable_debug_monitors(enum debug_el el);
void disable_debug_monitors(enum debug_el el);
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 5a46c4e7f539..a34fd3b12e2b 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -2,6 +2,7 @@
#define _ASM_EFI_H
#include <asm/io.h>
+#include <asm/neon.h>
#ifdef CONFIG_EFI
extern void efi_init(void);
@@ -11,4 +12,36 @@ extern void efi_idmap_init(void);
#define efi_idmap_init()
#endif
+#define efi_call_virt(f, ...) \
+({ \
+ efi_##f##_t *__f = efi.systab->runtime->f; \
+ efi_status_t __s; \
+ \
+ kernel_neon_begin(); \
+ __s = __f(__VA_ARGS__); \
+ kernel_neon_end(); \
+ __s; \
+})
+
+#define __efi_call_virt(f, ...) \
+({ \
+ efi_##f##_t *__f = efi.systab->runtime->f; \
+ \
+ kernel_neon_begin(); \
+ __f(__VA_ARGS__); \
+ kernel_neon_end(); \
+})
+
+/* arch specific definitions used by the stub code */
+
+/*
+ * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
+ * start of kernel and may not cross a 2MiB boundary. We set alignment to
+ * 2MiB so we know it won't cross a 2MiB boundary.
+ */
+#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
+#define MAX_FDT_OFFSET SZ_512M
+
+#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+
#endif /* _ASM_EFI_H */
diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h
index 768414d55e64..007618b8188c 100644
--- a/arch/arm64/include/asm/fpsimdmacros.h
+++ b/arch/arm64/include/asm/fpsimdmacros.h
@@ -40,6 +40,19 @@
str w\tmpnr, [\state, #16 * 2 + 4]
.endm
+.macro fpsimd_restore_fpcr state, tmp
+ /*
+ * Writes to fpcr may be self-synchronising, so avoid restoring
+ * the register if it hasn't changed.
+ */
+ mrs \tmp, fpcr
+ cmp \tmp, \state
+ b.eq 9999f
+ msr fpcr, \state
+9999:
+.endm
+
+/* Clobbers \state */
.macro fpsimd_restore state, tmpnr
ldp q0, q1, [\state, #16 * 0]
ldp q2, q3, [\state, #16 * 2]
@@ -60,7 +73,7 @@
ldr w\tmpnr, [\state, #16 * 2]
msr fpsr, x\tmpnr
ldr w\tmpnr, [\state, #16 * 2 + 4]
- msr fpcr, x\tmpnr
+ fpsimd_restore_fpcr x\tmpnr, \state
.endm
.altmacro
@@ -84,7 +97,7 @@
.macro fpsimd_restore_partial state, tmpnr1, tmpnr2
ldp w\tmpnr1, w\tmpnr2, [\state]
msr fpsr, x\tmpnr1
- msr fpcr, x\tmpnr2
+ fpsimd_restore_fpcr x\tmpnr2, x\tmpnr1
adr x\tmpnr1, 0f
ldr w\tmpnr2, [\state, #8]
add \state, \state, x\tmpnr2, lsl #4
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 3d6903006a8a..cc83520459ed 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -76,9 +76,10 @@
*/
#define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
- HCR_AMO | HCR_IMO | HCR_FMO | \
- HCR_SWIO | HCR_TIDCP | HCR_RW)
+ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+#define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO)
+
/* Hyp System Control Register (SCTLR_EL2) bits */
#define SCTLR_EL2_EE (1 << 25)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 9fcd54b1e16d..483842180f8f 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -18,6 +18,8 @@
#ifndef __ARM_KVM_ASM_H__
#define __ARM_KVM_ASM_H__
+#include <asm/virt.h>
+
/*
* 0 is reserved as an invalid value.
* Order *must* be kept in sync with the hyp switch code.
@@ -43,14 +45,25 @@
#define AMAIR_EL1 19 /* Aux Memory Attribute Indirection Register */
#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */
#define PAR_EL1 21 /* Physical Address Register */
+#define MDSCR_EL1 22 /* Monitor Debug System Control Register */
+#define DBGBCR0_EL1 23 /* Debug Breakpoint Control Registers (0-15) */
+#define DBGBCR15_EL1 38
+#define DBGBVR0_EL1 39 /* Debug Breakpoint Value Registers (0-15) */
+#define DBGBVR15_EL1 54
+#define DBGWCR0_EL1 55 /* Debug Watchpoint Control Registers (0-15) */
+#define DBGWCR15_EL1 70
+#define DBGWVR0_EL1 71 /* Debug Watchpoint Value Registers (0-15) */
+#define DBGWVR15_EL1 86
+#define MDCCINT_EL1 87 /* Monitor Debug Comms Channel Interrupt Enable Reg */
+
/* 32bit specific registers. Keep them at the end of the range */
-#define DACR32_EL2 22 /* Domain Access Control Register */
-#define IFSR32_EL2 23 /* Instruction Fault Status Register */
-#define FPEXC32_EL2 24 /* Floating-Point Exception Control Register */
-#define DBGVCR32_EL2 25 /* Debug Vector Catch Register */
-#define TEECR32_EL1 26 /* ThumbEE Configuration Register */
-#define TEEHBR32_EL1 27 /* ThumbEE Handler Base Register */
-#define NR_SYS_REGS 28
+#define DACR32_EL2 88 /* Domain Access Control Register */
+#define IFSR32_EL2 89 /* Instruction Fault Status Register */
+#define FPEXC32_EL2 90 /* Floating-Point Exception Control Register */
+#define DBGVCR32_EL2 91 /* Debug Vector Catch Register */
+#define TEECR32_EL1 92 /* ThumbEE Configuration Register */
+#define TEEHBR32_EL1 93 /* ThumbEE Handler Base Register */
+#define NR_SYS_REGS 94
/* 32bit mapping */
#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
@@ -82,11 +95,23 @@
#define c10_AMAIR0 (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */
#define c10_AMAIR1 (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */
#define c14_CNTKCTL (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */
-#define NR_CP15_REGS (NR_SYS_REGS * 2)
+
+#define cp14_DBGDSCRext (MDSCR_EL1 * 2)
+#define cp14_DBGBCR0 (DBGBCR0_EL1 * 2)
+#define cp14_DBGBVR0 (DBGBVR0_EL1 * 2)
+#define cp14_DBGBXVR0 (cp14_DBGBVR0 + 1)
+#define cp14_DBGWCR0 (DBGWCR0_EL1 * 2)
+#define cp14_DBGWVR0 (DBGWVR0_EL1 * 2)
+#define cp14_DBGDCCINT (MDCCINT_EL1 * 2)
+
+#define NR_COPRO_REGS (NR_SYS_REGS * 2)
#define ARM_EXCEPTION_IRQ 0
#define ARM_EXCEPTION_TRAP 1
+#define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
+#define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
+
#ifndef __ASSEMBLY__
struct kvm;
struct kvm_vcpu;
@@ -96,13 +121,21 @@ extern char __kvm_hyp_init_end[];
extern char __kvm_hyp_vector[];
-extern char __kvm_hyp_code_start[];
-extern char __kvm_hyp_code_end[];
+#define __kvm_hyp_code_start __hyp_text_start
+#define __kvm_hyp_code_end __hyp_text_end
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+
+extern u64 __vgic_v3_get_ich_vtr_el2(void);
+
+extern char __save_vgic_v2_state[];
+extern char __restore_vgic_v2_state[];
+extern char __save_vgic_v3_state[];
+extern char __restore_vgic_v3_state[];
+
#endif
#endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h
index 9a59301cd014..0b52377a6c11 100644
--- a/arch/arm64/include/asm/kvm_coproc.h
+++ b/arch/arm64/include/asm/kvm_coproc.h
@@ -39,7 +39,8 @@ void kvm_register_target_sys_reg_table(unsigned int target,
struct kvm_sys_reg_target_table *table);
int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index dd8ecfc3f995..fdc3e21abd8d 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -213,6 +213,17 @@ static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
default:
return be64_to_cpu(data);
}
+ } else {
+ switch (len) {
+ case 1:
+ return data & 0xff;
+ case 2:
+ return le16_to_cpu(data & 0xffff);
+ case 4:
+ return le32_to_cpu(data & 0xffffffff);
+ default:
+ return le64_to_cpu(data);
+ }
}
return data; /* Leave LE untouched */
@@ -233,6 +244,17 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
default:
return cpu_to_be64(data);
}
+ } else {
+ switch (len) {
+ case 1:
+ return data & 0xff;
+ case 2:
+ return cpu_to_le16(data & 0xffff);
+ case 4:
+ return cpu_to_le32(data & 0xffffffff);
+ default:
+ return cpu_to_le64(data);
+ }
}
return data; /* Leave LE untouched */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 92242ce06309..e10c45a578e3 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -86,7 +86,7 @@ struct kvm_cpu_context {
struct kvm_regs gp_regs;
union {
u64 sys_regs[NR_SYS_REGS];
- u32 cp15[NR_CP15_REGS];
+ u32 copro[NR_COPRO_REGS];
};
};
@@ -101,6 +101,9 @@ struct kvm_vcpu_arch {
/* Exception Information */
struct kvm_vcpu_fault_info fault;
+ /* Debug state */
+ u64 debug_flags;
+
/* Pointer to host CPU context */
kvm_cpu_context_t *host_cpu_context;
@@ -138,7 +141,20 @@ struct kvm_vcpu_arch {
#define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
#define vcpu_sys_reg(v,r) ((v)->arch.ctxt.sys_regs[(r)])
-#define vcpu_cp15(v,r) ((v)->arch.ctxt.cp15[(r)])
+/*
+ * CP14 and CP15 live in the same array, as they are backed by the
+ * same system registers.
+ */
+#define vcpu_cp14(v,r) ((v)->arch.ctxt.copro[(r)])
+#define vcpu_cp15(v,r) ((v)->arch.ctxt.copro[(r)])
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r))
+#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r) + 1)
+#else
+#define vcpu_cp15_64_high(v,r) vcpu_cp15((v),(r) + 1)
+#define vcpu_cp15_64_low(v,r) vcpu_cp15((v),(r))
+#endif
struct kvm_vm_stat {
u32 remote_tlb_flush;
@@ -200,4 +216,32 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
hyp_stack_ptr, vector_ptr);
}
+struct vgic_sr_vectors {
+ void *save_vgic;
+ void *restore_vgic;
+};
+
+static inline void vgic_arch_setup(const struct vgic_params *vgic)
+{
+ extern struct vgic_sr_vectors __vgic_sr_vectors;
+
+ switch(vgic->type)
+ {
+ case VGIC_V2:
+ __vgic_sr_vectors.save_vgic = __save_vgic_v2_state;
+ __vgic_sr_vectors.restore_vgic = __restore_vgic_v2_state;
+ break;
+
+#ifdef CONFIG_ARM_GIC_V3
+ case VGIC_V3:
+ __vgic_sr_vectors.save_vgic = __save_vgic_v3_state;
+ __vgic_sr_vectors.restore_vgic = __restore_vgic_v3_state;
+ break;
+#endif
+
+ default:
+ BUG();
+ }
+}
+
#endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 7d29847a893b..8e138c7c53ac 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -125,6 +125,21 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
#define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end)
#define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end)
+static inline bool kvm_page_empty(void *ptr)
+{
+ struct page *ptr_page = virt_to_page(ptr);
+ return page_count(ptr_page) == 1;
+}
+
+#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep)
+#ifndef CONFIG_ARM64_64K_PAGES
+#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#else
+#define kvm_pmd_table_empty(pmdp) (0)
+#endif
+#define kvm_pud_table_empty(pudp) (0)
+
+
struct kvm;
#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l))
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 902eb708804a..ccc7087d3c4e 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -41,11 +41,7 @@
* The module space lives between the addresses given by TASK_SIZE
* and PAGE_OFFSET - it must be within 128MB of the kernel text.
*/
-#ifdef CONFIG_ARM64_64K_PAGES
-#define VA_BITS (42)
-#else
-#define VA_BITS (39)
-#endif
+#define VA_BITS (CONFIG_ARM64_VA_BITS)
#define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1))
#define MODULES_END (PAGE_OFFSET)
#define MODULES_VADDR (MODULES_END - SZ_64M)
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
index 46bf66628b6a..22b16232bd60 100644
--- a/arch/arm64/include/asm/page.h
+++ b/arch/arm64/include/asm/page.h
@@ -28,17 +28,26 @@
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
-/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
-#define __HAVE_ARCH_GATE_AREA 1
-
-#ifndef __ASSEMBLY__
-
+/*
+ * The idmap and swapper page tables need some space reserved in the kernel
+ * image. Both require pgd, pud (4 levels only) and pmd tables to (section)
+ * map the kernel. With the 64K page configuration, swapper and idmap need to
+ * map to pte level. The swapper also maps the FDT (see __create_page_tables
+ * for more information).
+ */
#ifdef CONFIG_ARM64_64K_PAGES
-#include <asm/pgtable-2level-types.h>
+#define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS)
#else
-#include <asm/pgtable-3level-types.h>
+#define SWAPPER_PGTABLE_LEVELS (CONFIG_ARM64_PGTABLE_LEVELS - 1)
#endif
+#define SWAPPER_DIR_SIZE (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
+#define IDMAP_DIR_SIZE (SWAPPER_DIR_SIZE)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/pgtable-types.h>
+
extern void __cpu_clear_user_page(void *p, unsigned long user);
extern void __cpu_copy_user_page(void *to, const void *from,
unsigned long user);
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index 9bea6e74a001..d5bed02073d6 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -26,7 +26,7 @@
#define check_pgt_cache() do { } while (0)
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
@@ -44,7 +44,27 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
}
-#endif /* CONFIG_ARM64_64K_PAGES */
+#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ return (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+ BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+ free_page((unsigned long)pud);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+ set_pgd(pgd, __pgd(__pa(pud) | PUD_TYPE_TABLE));
+}
+
+#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
extern pgd_t *pgd_alloc(struct mm_struct *mm);
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
diff --git a/arch/arm64/include/asm/pgtable-2level-hwdef.h b/arch/arm64/include/asm/pgtable-2level-hwdef.h
deleted file mode 100644
index 2593b490c56a..000000000000
--- a/arch/arm64/include/asm/pgtable-2level-hwdef.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H
-#define __ASM_PGTABLE_2LEVEL_HWDEF_H
-
-/*
- * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has
- * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not
- * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each
- * entry representing 512MB. The user and kernel address spaces are limited to
- * 4TB in the 64KB page configuration.
- */
-#define PTRS_PER_PTE 8192
-#define PTRS_PER_PGD 8192
-
-/*
- * PGDIR_SHIFT determines the size a top-level page table entry can map.
- */
-#define PGDIR_SHIFT 29
-#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT 29
-#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT)
-#define SECTION_MASK (~(SECTION_SIZE-1))
-
-#endif
diff --git a/arch/arm64/include/asm/pgtable-2level-types.h b/arch/arm64/include/asm/pgtable-2level-types.h
deleted file mode 100644
index 5f101e63dfc1..000000000000
--- a/arch/arm64/include/asm/pgtable-2level-types.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_2LEVEL_TYPES_H
-#define __ASM_PGTABLE_2LEVEL_TYPES_H
-
-#include <asm/types.h>
-
-typedef u64 pteval_t;
-typedef u64 pgdval_t;
-typedef pgdval_t pmdval_t;
-
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { pteval_t pte; } pte_t;
-typedef struct { pgdval_t pgd; } pgd_t;
-typedef struct { pteval_t pgprot; } pgprot_t;
-
-#define pte_val(x) ((x).pte)
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-#else /* !STRICT_MM_TYPECHECKS */
-
-typedef pteval_t pte_t;
-typedef pgdval_t pgd_t;
-typedef pteval_t pgprot_t;
-
-#define pte_val(x) (x)
-#define pgd_val(x) (x)
-#define pgprot_val(x) (x)
-
-#define __pte(x) (x)
-#define __pgd(x) (x)
-#define __pgprot(x) (x)
-
-#endif /* STRICT_MM_TYPECHECKS */
-
-#include <asm-generic/pgtable-nopmd.h>
-
-#endif /* __ASM_PGTABLE_2LEVEL_TYPES_H */
diff --git a/arch/arm64/include/asm/pgtable-3level-hwdef.h b/arch/arm64/include/asm/pgtable-3level-hwdef.h
deleted file mode 100644
index 3dbf941d7767..000000000000
--- a/arch/arm64/include/asm/pgtable-3level-hwdef.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_PGTABLE_3LEVEL_HWDEF_H
-#define __ASM_PGTABLE_3LEVEL_HWDEF_H
-
-/*
- * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has
- * 512 entries of 8 bytes each, occupying a 4K page. The first level table
- * covers a range of 512GB, each entry representing 1GB. The user and kernel
- * address spaces are limited to 512GB each.
- */
-#define PTRS_PER_PTE 512
-#define PTRS_PER_PMD 512
-#define PTRS_PER_PGD 512
-
-/*
- * PGDIR_SHIFT determines the size a top-level page table entry can map.
- */
-#define PGDIR_SHIFT 30
-#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-/*
- * PMD_SHIFT determines the size a middle-level page table entry can map.
- */
-#define PMD_SHIFT 21
-#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-
-/*
- * section address mask and size definitions.
- */
-#define SECTION_SHIFT 21
-#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT)
-#define SECTION_MASK (~(SECTION_SIZE-1))
-
-#endif
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 955e8c5f0afb..88174e0bfafe 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -16,18 +16,50 @@
#ifndef __ASM_PGTABLE_HWDEF_H
#define __ASM_PGTABLE_HWDEF_H
-#ifdef CONFIG_ARM64_64K_PAGES
-#include <asm/pgtable-2level-hwdef.h>
-#else
-#include <asm/pgtable-3level-hwdef.h>
+#define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3))
+
+/*
+ * PMD_SHIFT determines the size a level 2 page table entry can map.
+ */
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+#define PMD_SHIFT ((PAGE_SHIFT - 3) * 2 + 3)
+#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PTRS_PER_PMD PTRS_PER_PTE
+#endif
+
+/*
+ * PUD_SHIFT determines the size a level 1 page table entry can map.
+ */
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+#define PUD_SHIFT ((PAGE_SHIFT - 3) * 3 + 3)
+#define PUD_SIZE (_AC(1, UL) << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
+#define PTRS_PER_PUD PTRS_PER_PTE
#endif
/*
+ * PGDIR_SHIFT determines the size a top-level page table entry can map
+ * (depending on the configuration, this level can be 0, 1 or 2).
+ */
+#define PGDIR_SHIFT ((PAGE_SHIFT - 3) * CONFIG_ARM64_PGTABLE_LEVELS + 3)
+#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+#define PTRS_PER_PGD (1 << (VA_BITS - PGDIR_SHIFT))
+
+/*
+ * Section address mask and size definitions.
+ */
+#define SECTION_SHIFT PMD_SHIFT
+#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT)
+#define SECTION_MASK (~(SECTION_SIZE-1))
+
+/*
* Hardware page table definitions.
*
* Level 1 descriptor (PUD).
*/
-
+#define PUD_TYPE_TABLE (_AT(pudval_t, 3) << 0)
#define PUD_TABLE_BIT (_AT(pgdval_t, 1) << 1)
#define PUD_TYPE_MASK (_AT(pgdval_t, 3) << 0)
#define PUD_TYPE_SECT (_AT(pgdval_t, 1) << 0)
diff --git a/arch/arm64/include/asm/pgtable-3level-types.h b/arch/arm64/include/asm/pgtable-types.h
index 4e94424938a4..ca9df80af896 100644
--- a/arch/arm64/include/asm/pgtable-3level-types.h
+++ b/arch/arm64/include/asm/pgtable-types.h
@@ -1,7 +1,10 @@
/*
- * Copyright (C) 2012 ARM Ltd.
+ * Page table types definitions.
*
- * This program is free software; you can redistribute it and/or modify
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.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.
*
@@ -13,13 +16,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __ASM_PGTABLE_3LEVEL_TYPES_H
-#define __ASM_PGTABLE_3LEVEL_TYPES_H
+
+#ifndef __ASM_PGTABLE_TYPES_H
+#define __ASM_PGTABLE_TYPES_H
#include <asm/types.h>
typedef u64 pteval_t;
typedef u64 pmdval_t;
+typedef u64 pudval_t;
typedef u64 pgdval_t;
#undef STRICT_MM_TYPECHECKS
@@ -30,39 +35,61 @@ typedef u64 pgdval_t;
* These are used to make use of C type-checking..
*/
typedef struct { pteval_t pte; } pte_t;
+#define pte_val(x) ((x).pte)
+#define __pte(x) ((pte_t) { (x) } )
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
typedef struct { pmdval_t pmd; } pmd_t;
-typedef struct { pgdval_t pgd; } pgd_t;
-typedef struct { pteval_t pgprot; } pgprot_t;
+#define pmd_val(x) ((x).pmd)
+#define __pmd(x) ((pmd_t) { (x) } )
+#endif
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((x).pmd)
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+typedef struct { pudval_t pud; } pud_t;
+#define pud_val(x) ((x).pud)
+#define __pud(x) ((pud_t) { (x) } )
+#endif
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
+typedef struct { pgdval_t pgd; } pgd_t;
+#define pgd_val(x) ((x).pgd)
#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
+
+typedef struct { pteval_t pgprot; } pgprot_t;
+#define pgprot_val(x) ((x).pgprot)
+#define __pgprot(x) ((pgprot_t) { (x) } )
#else /* !STRICT_MM_TYPECHECKS */
typedef pteval_t pte_t;
-typedef pmdval_t pmd_t;
-typedef pgdval_t pgd_t;
-typedef pteval_t pgprot_t;
-
#define pte_val(x) (x)
-#define pmd_val(x) (x)
-#define pgd_val(x) (x)
-#define pgprot_val(x) (x)
-
#define __pte(x) (x)
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+typedef pmdval_t pmd_t;
+#define pmd_val(x) (x)
#define __pmd(x) (x)
+#endif
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+typedef pudval_t pud_t;
+#define pud_val(x) (x)
+#define __pud(x) (x)
+#endif
+
+typedef pgdval_t pgd_t;
+#define pgd_val(x) (x)
#define __pgd(x) (x)
+
+typedef pteval_t pgprot_t;
+#define pgprot_val(x) (x)
#define __pgprot(x) (x)
-#endif /* STRICT_MM_TYPECHECKS */
+#endif /* STRICT_MM_TYPECHECKS */
+#if CONFIG_ARM64_PGTABLE_LEVELS == 2
+#include <asm-generic/pgtable-nopmd.h>
+#elif CONFIG_ARM64_PGTABLE_LEVELS == 3
#include <asm-generic/pgtable-nopud.h>
+#endif
-#endif /* __ASM_PGTABLE_3LEVEL_TYPES_H */
+#endif /* __ASM_PGTABLE_TYPES_H */
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e0ccceb317d9..ffe1ba0506d1 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -33,9 +33,16 @@
/*
* VMALLOC and SPARSEMEM_VMEMMAP ranges.
+ *
+ * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
+ * (rounded up to PUD_SIZE).
+ * VMALLOC_START: beginning of the kernel VA space
+ * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
+ * fixed mappings and modules
*/
+#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
#define VMALLOC_START (UL(0xffffffffffffffff) << VA_BITS)
-#define VMALLOC_END (PAGE_OFFSET - UL(0x400000000) - SZ_64K)
+#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
@@ -44,14 +51,9 @@
#ifndef __ASSEMBLY__
extern void __pte_error(const char *file, int line, unsigned long val);
extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pud_error(const char *file, int line, unsigned long val);
extern void __pgd_error(const char *file, int line, unsigned long val);
-#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
-#ifndef CONFIG_ARM64_64K_PAGES
-#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
-#endif
-#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
-
#ifdef CONFIG_SMP
#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
@@ -112,6 +114,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
extern struct page *empty_zero_page;
#define ZERO_PAGE(vaddr) (empty_zero_page)
+#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
+
#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
#define pfn_pte(pfn,prot) (__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
@@ -119,6 +123,10 @@ extern struct page *empty_zero_page;
#define pte_none(pte) (!pte_val(pte))
#define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0))
#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
+
+/* Find an entry in the third-level page table. */
+#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + pte_index(addr))
#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr))
@@ -138,6 +146,8 @@ extern struct page *empty_zero_page;
#define pte_valid_user(pte) \
((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
+#define pte_valid_not_user(pte) \
+ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
static inline pte_t pte_wrprotect(pte_t pte)
{
@@ -184,6 +194,15 @@ static inline pte_t pte_mkspecial(pte_t pte)
static inline void set_pte(pte_t *ptep, pte_t pte)
{
*ptep = pte;
+
+ /*
+ * Only if the new pte is valid and kernel, otherwise TLB maintenance
+ * or update_mmu_cache() have the necessary barriers.
+ */
+ if (pte_valid_not_user(pte)) {
+ dsb(ishst);
+ isb();
+ }
}
extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
@@ -303,6 +322,7 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
{
*pmdp = pmd;
dsb(ishst);
+ isb();
}
static inline void pmd_clear(pmd_t *pmdp)
@@ -323,7 +343,9 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
*/
#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot)
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+
+#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
#define pud_none(pud) (!pud_val(pud))
#define pud_bad(pud) (!(pud_val(pud) & 2))
@@ -333,6 +355,7 @@ static inline void set_pud(pud_t *pudp, pud_t pud)
{
*pudp = pud;
dsb(ishst);
+ isb();
}
static inline void pud_clear(pud_t *pudp)
@@ -345,7 +368,51 @@ static inline pmd_t *pud_page_vaddr(pud_t pud)
return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
}
-#endif /* CONFIG_ARM64_64K_PAGES */
+/* Find an entry in the second-level page table. */
+#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
+{
+ return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
+}
+
+#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
+
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+
+#define pud_ERROR(pud) __pud_error(__FILE__, __LINE__, pud_val(pud))
+
+#define pgd_none(pgd) (!pgd_val(pgd))
+#define pgd_bad(pgd) (!(pgd_val(pgd) & 2))
+#define pgd_present(pgd) (pgd_val(pgd))
+
+static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
+{
+ *pgdp = pgd;
+ dsb(ishst);
+}
+
+static inline void pgd_clear(pgd_t *pgdp)
+{
+ set_pgd(pgdp, __pgd(0));
+}
+
+static inline pud_t *pgd_page_vaddr(pgd_t pgd)
+{
+ return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
+}
+
+/* Find an entry in the frst-level page table. */
+#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+
+static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
+{
+ return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
+}
+
+#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
+
+#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
/* to find an entry in a page-table-directory */
#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
@@ -355,18 +422,6 @@ static inline pmd_t *pud_page_vaddr(pud_t pud)
/* to find an entry in a kernel page-table-directory */
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
-/* Find an entry in the second-level page table.. */
-#ifndef CONFIG_ARM64_64K_PAGES
-#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
-static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
-{
- return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
-}
-#endif
-
-/* Find an entry in the third-level page table.. */
-#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
@@ -383,9 +438,6 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
-#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
-#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
-
/*
* Encode and decode a swap entry:
* bits 0-1: present (must be zero)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 34de2a8f7d93..3df21feeabdd 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -129,6 +129,7 @@ extern void release_thread(struct task_struct *);
unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
/* Thread switching */
extern struct task_struct *cpu_switch_to(struct task_struct *prev,
@@ -137,8 +138,8 @@ extern struct task_struct *cpu_switch_to(struct task_struct *prev,
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
-#define KSTK_EIP(tsk) task_pt_regs(tsk)->pc
-#define KSTK_ESP(tsk) task_pt_regs(tsk)->sp
+#define KSTK_EIP(tsk) ((unsigned long)task_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk) ((unsigned long)task_pt_regs(tsk)->sp)
/*
* Prefetching support
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index 7c275e3b640f..eeaa97559bab 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -24,22 +24,21 @@
extern const compat_ulong_t aarch32_sigret_code[6];
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs);
+int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs);
void compat_setup_restart_syscall(struct pt_regs *regs);
#else
-static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
+static inline int compat_setup_frame(int usid, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
return -ENOSYS;
}
-static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *set,
+static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
return -ENOSYS;
diff --git a/arch/arm64/include/asm/stackprotector.h b/arch/arm64/include/asm/stackprotector.h
new file mode 100644
index 000000000000..fe5e287dc56b
--- /dev/null
+++ b/arch/arm64/include/asm/stackprotector.h
@@ -0,0 +1,38 @@
+/*
+ * GCC stack protector support.
+ *
+ * Stack protector works by putting predefined pattern at the start of
+ * the stack frame and verifying that it hasn't been overwritten when
+ * returning from the function. The pattern is called stack canary
+ * and gcc expects it to be defined by a global variable called
+ * "__stack_chk_guard" on ARM. This unfortunately means that on SMP
+ * we cannot have a different canary value per task.
+ */
+
+#ifndef __ASM_STACKPROTECTOR_H
+#define __ASM_STACKPROTECTOR_H
+
+#include <linux/random.h>
+#include <linux/version.h>
+
+extern unsigned long __stack_chk_guard;
+
+/*
+ * Initialize the stackprotector canary value.
+ *
+ * NOTE: this must only be called from functions that never return,
+ * and it must always be inlined.
+ */
+static __always_inline void boot_init_stack_canary(void)
+{
+ unsigned long canary;
+
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= LINUX_VERSION_CODE;
+
+ current->stack_canary = canary;
+ __stack_chk_guard = current->stack_canary;
+}
+
+#endif /* _ASM_STACKPROTECTOR_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 383771eb0b87..709a574468f0 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -16,6 +16,8 @@
#ifndef __ASM_SYSCALL_H
#define __ASM_SYSCALL_H
+#include <uapi/linux/audit.h>
+#include <linux/compat.h>
#include <linux/err.h>
extern const void *sys_call_table[];
@@ -105,4 +107,16 @@ static inline void syscall_set_arguments(struct task_struct *task,
memcpy(&regs->regs[i], args, n * sizeof(args[0]));
}
+/*
+ * We don't care about endianness (__AUDIT_ARCH_LE bit) here because
+ * AArch64 has the same system calls both on little- and big- endian.
+ */
+static inline int syscall_get_arch(void)
+{
+ if (is_compat_task())
+ return AUDIT_ARCH_ARM;
+
+ return AUDIT_ARCH_AARCH64;
+}
+
#endif /* __ASM_SYSCALL_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
new file mode 100644
index 000000000000..5c89df0acbcb
--- /dev/null
+++ b/arch/arm64/include/asm/sysreg.h
@@ -0,0 +1,60 @@
+/*
+ * Macros for accessing system registers with older binutils.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SYSREG_H
+#define __ASM_SYSREG_H
+
+#define sys_reg(op0, op1, crn, crm, op2) \
+ ((((op0)-2)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
+
+#ifdef __ASSEMBLY__
+
+ .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
+ .equ __reg_num_x\num, \num
+ .endr
+ .equ __reg_num_xzr, 31
+
+ .macro mrs_s, rt, sreg
+ .inst 0xd5300000|(\sreg)|(__reg_num_\rt)
+ .endm
+
+ .macro msr_s, sreg, rt
+ .inst 0xd5100000|(\sreg)|(__reg_num_\rt)
+ .endm
+
+#else
+
+asm(
+" .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
+" .equ __reg_num_x\\num, \\num\n"
+" .endr\n"
+" .equ __reg_num_xzr, 31\n"
+"\n"
+" .macro mrs_s, rt, sreg\n"
+" .inst 0xd5300000|(\\sreg)|(__reg_num_\\rt)\n"
+" .endm\n"
+"\n"
+" .macro msr_s, sreg, rt\n"
+" .inst 0xd5100000|(\\sreg)|(__reg_num_\\rt)\n"
+" .endm\n"
+);
+
+#endif
+
+#endif /* __ASM_SYSREG_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index e40b6d06d515..45108d802f5e 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -103,6 +103,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 1
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
+#define TIF_NOHZ 7
#define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9
#define TIF_SYSCALL_TRACEPOINT 10
@@ -118,6 +119,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
+#define _TIF_NOHZ (1 << TIF_NOHZ)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
@@ -128,7 +130,8 @@ static inline struct thread_info *current_thread_info(void)
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
- _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
+ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
+ _TIF_NOHZ)
#endif /* __KERNEL__ */
#endif /* __ASM_THREAD_INFO_H */
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
index 80e2c08900d6..62731ef9749a 100644
--- a/arch/arm64/include/asm/tlb.h
+++ b/arch/arm64/include/asm/tlb.h
@@ -91,7 +91,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
tlb_remove_page(tlb, pte);
}
-#ifndef CONFIG_ARM64_64K_PAGES
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
unsigned long addr)
{
@@ -100,6 +100,15 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
}
#endif
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
+ unsigned long addr)
+{
+ tlb_add_flush(tlb, addr);
+ tlb_remove_page(tlb, virt_to_page(pudp));
+}
+#endif
+
static inline void __tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp,
unsigned long address)
{
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index b9349c4513ea..73f0ce570fb3 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -98,8 +98,8 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
dsb(ish);
}
-static inline void flush_tlb_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
+static inline void __flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
{
unsigned long asid = (unsigned long)ASID(vma->vm_mm) << 48;
unsigned long addr;
@@ -112,7 +112,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
dsb(ish);
}
-static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+static inline void __flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
unsigned long addr;
start >>= 12;
@@ -122,6 +122,30 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
asm("tlbi vaae1is, %0" : : "r"(addr));
dsb(ish);
+ isb();
+}
+
+/*
+ * This is meant to avoid soft lock-ups on large TLB flushing ranges and not
+ * necessarily a performance improvement.
+ */
+#define MAX_TLB_RANGE (1024UL << PAGE_SHIFT)
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ if ((end - start) <= MAX_TLB_RANGE)
+ __flush_tlb_range(vma, start, end);
+ else
+ flush_tlb_mm(vma->vm_mm);
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ if ((end - start) <= MAX_TLB_RANGE)
+ __flush_tlb_kernel_range(start, end);
+ else
+ flush_tlb_all();
}
/*
@@ -131,8 +155,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
{
/*
- * set_pte() does not have a DSB, so make sure that the page table
- * write is visible.
+ * set_pte() does not have a DSB for user mappings, so make sure that
+ * the page table write is visible.
*/
dsb(ishst);
}
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index e5f47df00c24..4bc95d27e063 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -26,7 +26,24 @@
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
+
+/*
+ * Compat syscall numbers used by the AArch64 kernel.
+ */
+#define __NR_compat_restart_syscall 0
+#define __NR_compat_sigreturn 119
+#define __NR_compat_rt_sigreturn 173
+
+/*
+ * The following SVCs are ARM private.
+ */
+#define __ARM_NR_COMPAT_BASE 0x0f0000
+#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2)
+#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5)
+
+#define __NR_compat_syscalls 383
#endif
+
#define __ARCH_WANT_SYS_CLONE
#include <uapi/asm/unistd.h>
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index c8d8fc17bd5a..e242600c4046 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -21,403 +21,769 @@
#define __SYSCALL(x, y)
#endif
-__SYSCALL(0, sys_restart_syscall)
-__SYSCALL(1, sys_exit)
-__SYSCALL(2, sys_fork)
-__SYSCALL(3, sys_read)
-__SYSCALL(4, sys_write)
-__SYSCALL(5, compat_sys_open)
-__SYSCALL(6, sys_close)
-__SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */
-__SYSCALL(8, sys_creat)
-__SYSCALL(9, sys_link)
-__SYSCALL(10, sys_unlink)
-__SYSCALL(11, compat_sys_execve)
-__SYSCALL(12, sys_chdir)
-__SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */
-__SYSCALL(14, sys_mknod)
-__SYSCALL(15, sys_chmod)
-__SYSCALL(16, sys_lchown16)
-__SYSCALL(17, sys_ni_syscall) /* 17 was sys_break */
-__SYSCALL(18, sys_ni_syscall) /* 18 was sys_stat */
-__SYSCALL(19, compat_sys_lseek)
-__SYSCALL(20, sys_getpid)
-__SYSCALL(21, compat_sys_mount)
-__SYSCALL(22, sys_ni_syscall) /* 22 was sys_umount */
-__SYSCALL(23, sys_setuid16)
-__SYSCALL(24, sys_getuid16)
-__SYSCALL(25, sys_ni_syscall) /* 25 was sys_stime */
-__SYSCALL(26, compat_sys_ptrace)
-__SYSCALL(27, sys_ni_syscall) /* 27 was sys_alarm */
-__SYSCALL(28, sys_ni_syscall) /* 28 was sys_fstat */
-__SYSCALL(29, sys_pause)
-__SYSCALL(30, sys_ni_syscall) /* 30 was sys_utime */
-__SYSCALL(31, sys_ni_syscall) /* 31 was sys_stty */
-__SYSCALL(32, sys_ni_syscall) /* 32 was sys_gtty */
-__SYSCALL(33, sys_access)
-__SYSCALL(34, sys_nice)
-__SYSCALL(35, sys_ni_syscall) /* 35 was sys_ftime */
-__SYSCALL(36, sys_sync)
-__SYSCALL(37, sys_kill)
-__SYSCALL(38, sys_rename)
-__SYSCALL(39, sys_mkdir)
-__SYSCALL(40, sys_rmdir)
-__SYSCALL(41, sys_dup)
-__SYSCALL(42, sys_pipe)
-__SYSCALL(43, compat_sys_times)
-__SYSCALL(44, sys_ni_syscall) /* 44 was sys_prof */
-__SYSCALL(45, sys_brk)
-__SYSCALL(46, sys_setgid16)
-__SYSCALL(47, sys_getgid16)
-__SYSCALL(48, sys_ni_syscall) /* 48 was sys_signal */
-__SYSCALL(49, sys_geteuid16)
-__SYSCALL(50, sys_getegid16)
-__SYSCALL(51, sys_acct)
-__SYSCALL(52, sys_umount)
-__SYSCALL(53, sys_ni_syscall) /* 53 was sys_lock */
-__SYSCALL(54, compat_sys_ioctl)
-__SYSCALL(55, compat_sys_fcntl)
-__SYSCALL(56, sys_ni_syscall) /* 56 was sys_mpx */
-__SYSCALL(57, sys_setpgid)
-__SYSCALL(58, sys_ni_syscall) /* 58 was sys_ulimit */
-__SYSCALL(59, sys_ni_syscall) /* 59 was sys_olduname */
-__SYSCALL(60, sys_umask)
-__SYSCALL(61, sys_chroot)
-__SYSCALL(62, compat_sys_ustat)
-__SYSCALL(63, sys_dup2)
-__SYSCALL(64, sys_getppid)
-__SYSCALL(65, sys_getpgrp)
-__SYSCALL(66, sys_setsid)
-__SYSCALL(67, compat_sys_sigaction)
-__SYSCALL(68, sys_ni_syscall) /* 68 was sys_sgetmask */
-__SYSCALL(69, sys_ni_syscall) /* 69 was sys_ssetmask */
-__SYSCALL(70, sys_setreuid16)
-__SYSCALL(71, sys_setregid16)
-__SYSCALL(72, sys_sigsuspend)
-__SYSCALL(73, compat_sys_sigpending)
-__SYSCALL(74, sys_sethostname)
-__SYSCALL(75, compat_sys_setrlimit)
-__SYSCALL(76, sys_ni_syscall) /* 76 was compat_sys_getrlimit */
-__SYSCALL(77, compat_sys_getrusage)
-__SYSCALL(78, compat_sys_gettimeofday)
-__SYSCALL(79, compat_sys_settimeofday)
-__SYSCALL(80, sys_getgroups16)
-__SYSCALL(81, sys_setgroups16)
-__SYSCALL(82, sys_ni_syscall) /* 82 was compat_sys_select */
-__SYSCALL(83, sys_symlink)
-__SYSCALL(84, sys_ni_syscall) /* 84 was sys_lstat */
-__SYSCALL(85, sys_readlink)
-__SYSCALL(86, sys_uselib)
-__SYSCALL(87, sys_swapon)
-__SYSCALL(88, sys_reboot)
-__SYSCALL(89, sys_ni_syscall) /* 89 was sys_readdir */
-__SYSCALL(90, sys_ni_syscall) /* 90 was sys_mmap */
-__SYSCALL(91, sys_munmap)
-__SYSCALL(92, compat_sys_truncate)
-__SYSCALL(93, compat_sys_ftruncate)
-__SYSCALL(94, sys_fchmod)
-__SYSCALL(95, sys_fchown16)
-__SYSCALL(96, sys_getpriority)
-__SYSCALL(97, sys_setpriority)
-__SYSCALL(98, sys_ni_syscall) /* 98 was sys_profil */
-__SYSCALL(99, compat_sys_statfs)
-__SYSCALL(100, compat_sys_fstatfs)
-__SYSCALL(101, sys_ni_syscall) /* 101 was sys_ioperm */
-__SYSCALL(102, sys_ni_syscall) /* 102 was sys_socketcall */
-__SYSCALL(103, sys_syslog)
-__SYSCALL(104, compat_sys_setitimer)
-__SYSCALL(105, compat_sys_getitimer)
-__SYSCALL(106, compat_sys_newstat)
-__SYSCALL(107, compat_sys_newlstat)
-__SYSCALL(108, compat_sys_newfstat)
-__SYSCALL(109, sys_ni_syscall) /* 109 was sys_uname */
-__SYSCALL(110, sys_ni_syscall) /* 110 was sys_iopl */
-__SYSCALL(111, sys_vhangup)
-__SYSCALL(112, sys_ni_syscall) /* 112 was sys_idle */
-__SYSCALL(113, sys_ni_syscall) /* 113 was sys_syscall */
-__SYSCALL(114, compat_sys_wait4)
-__SYSCALL(115, sys_swapoff)
-__SYSCALL(116, compat_sys_sysinfo)
-__SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */
-__SYSCALL(118, sys_fsync)
-__SYSCALL(119, compat_sys_sigreturn_wrapper)
-__SYSCALL(120, sys_clone)
-__SYSCALL(121, sys_setdomainname)
-__SYSCALL(122, sys_newuname)
-__SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */
-__SYSCALL(124, compat_sys_adjtimex)
-__SYSCALL(125, sys_mprotect)
-__SYSCALL(126, compat_sys_sigprocmask)
-__SYSCALL(127, sys_ni_syscall) /* 127 was sys_create_module */
-__SYSCALL(128, sys_init_module)
-__SYSCALL(129, sys_delete_module)
-__SYSCALL(130, sys_ni_syscall) /* 130 was sys_get_kernel_syms */
-__SYSCALL(131, sys_quotactl)
-__SYSCALL(132, sys_getpgid)
-__SYSCALL(133, sys_fchdir)
-__SYSCALL(134, sys_bdflush)
-__SYSCALL(135, sys_sysfs)
-__SYSCALL(136, sys_personality)
-__SYSCALL(137, sys_ni_syscall) /* 137 was sys_afs_syscall */
-__SYSCALL(138, sys_setfsuid16)
-__SYSCALL(139, sys_setfsgid16)
-__SYSCALL(140, sys_llseek)
-__SYSCALL(141, compat_sys_getdents)
-__SYSCALL(142, compat_sys_select)
-__SYSCALL(143, sys_flock)
-__SYSCALL(144, sys_msync)
-__SYSCALL(145, compat_sys_readv)
-__SYSCALL(146, compat_sys_writev)
-__SYSCALL(147, sys_getsid)
-__SYSCALL(148, sys_fdatasync)
-__SYSCALL(149, compat_sys_sysctl)
-__SYSCALL(150, sys_mlock)
-__SYSCALL(151, sys_munlock)
-__SYSCALL(152, sys_mlockall)
-__SYSCALL(153, sys_munlockall)
-__SYSCALL(154, sys_sched_setparam)
-__SYSCALL(155, sys_sched_getparam)
-__SYSCALL(156, sys_sched_setscheduler)
-__SYSCALL(157, sys_sched_getscheduler)
-__SYSCALL(158, sys_sched_yield)
-__SYSCALL(159, sys_sched_get_priority_max)
-__SYSCALL(160, sys_sched_get_priority_min)
-__SYSCALL(161, compat_sys_sched_rr_get_interval)
-__SYSCALL(162, compat_sys_nanosleep)
-__SYSCALL(163, sys_mremap)
-__SYSCALL(164, sys_setresuid16)
-__SYSCALL(165, sys_getresuid16)
-__SYSCALL(166, sys_ni_syscall) /* 166 was sys_vm86 */
-__SYSCALL(167, sys_ni_syscall) /* 167 was sys_query_module */
-__SYSCALL(168, sys_poll)
-__SYSCALL(169, sys_ni_syscall)
-__SYSCALL(170, sys_setresgid16)
-__SYSCALL(171, sys_getresgid16)
-__SYSCALL(172, sys_prctl)
-__SYSCALL(173, compat_sys_rt_sigreturn_wrapper)
-__SYSCALL(174, compat_sys_rt_sigaction)
-__SYSCALL(175, compat_sys_rt_sigprocmask)
-__SYSCALL(176, compat_sys_rt_sigpending)
-__SYSCALL(177, compat_sys_rt_sigtimedwait)
-__SYSCALL(178, compat_sys_rt_sigqueueinfo)
-__SYSCALL(179, compat_sys_rt_sigsuspend)
-__SYSCALL(180, compat_sys_pread64_wrapper)
-__SYSCALL(181, compat_sys_pwrite64_wrapper)
-__SYSCALL(182, sys_chown16)
-__SYSCALL(183, sys_getcwd)
-__SYSCALL(184, sys_capget)
-__SYSCALL(185, sys_capset)
-__SYSCALL(186, compat_sys_sigaltstack)
-__SYSCALL(187, compat_sys_sendfile)
-__SYSCALL(188, sys_ni_syscall) /* 188 reserved */
-__SYSCALL(189, sys_ni_syscall) /* 189 reserved */
-__SYSCALL(190, sys_vfork)
-__SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */
-__SYSCALL(192, sys_mmap_pgoff)
-__SYSCALL(193, compat_sys_truncate64_wrapper)
-__SYSCALL(194, compat_sys_ftruncate64_wrapper)
-__SYSCALL(195, sys_stat64)
-__SYSCALL(196, sys_lstat64)
-__SYSCALL(197, sys_fstat64)
-__SYSCALL(198, sys_lchown)
-__SYSCALL(199, sys_getuid)
-__SYSCALL(200, sys_getgid)
-__SYSCALL(201, sys_geteuid)
-__SYSCALL(202, sys_getegid)
-__SYSCALL(203, sys_setreuid)
-__SYSCALL(204, sys_setregid)
-__SYSCALL(205, sys_getgroups)
-__SYSCALL(206, sys_setgroups)
-__SYSCALL(207, sys_fchown)
-__SYSCALL(208, sys_setresuid)
-__SYSCALL(209, sys_getresuid)
-__SYSCALL(210, sys_setresgid)
-__SYSCALL(211, sys_getresgid)
-__SYSCALL(212, sys_chown)
-__SYSCALL(213, sys_setuid)
-__SYSCALL(214, sys_setgid)
-__SYSCALL(215, sys_setfsuid)
-__SYSCALL(216, sys_setfsgid)
-__SYSCALL(217, compat_sys_getdents64)
-__SYSCALL(218, sys_pivot_root)
-__SYSCALL(219, sys_mincore)
-__SYSCALL(220, sys_madvise)
-__SYSCALL(221, compat_sys_fcntl64)
-__SYSCALL(222, sys_ni_syscall) /* 222 for tux */
-__SYSCALL(223, sys_ni_syscall) /* 223 is unused */
-__SYSCALL(224, sys_gettid)
-__SYSCALL(225, compat_sys_readahead_wrapper)
-__SYSCALL(226, sys_setxattr)
-__SYSCALL(227, sys_lsetxattr)
-__SYSCALL(228, sys_fsetxattr)
-__SYSCALL(229, sys_getxattr)
-__SYSCALL(230, sys_lgetxattr)
-__SYSCALL(231, sys_fgetxattr)
-__SYSCALL(232, sys_listxattr)
-__SYSCALL(233, sys_llistxattr)
-__SYSCALL(234, sys_flistxattr)
-__SYSCALL(235, sys_removexattr)
-__SYSCALL(236, sys_lremovexattr)
-__SYSCALL(237, sys_fremovexattr)
-__SYSCALL(238, sys_tkill)
-__SYSCALL(239, sys_sendfile64)
-__SYSCALL(240, compat_sys_futex)
-__SYSCALL(241, compat_sys_sched_setaffinity)
-__SYSCALL(242, compat_sys_sched_getaffinity)
-__SYSCALL(243, compat_sys_io_setup)
-__SYSCALL(244, sys_io_destroy)
-__SYSCALL(245, compat_sys_io_getevents)
-__SYSCALL(246, compat_sys_io_submit)
-__SYSCALL(247, sys_io_cancel)
-__SYSCALL(248, sys_exit_group)
-__SYSCALL(249, compat_sys_lookup_dcookie)
-__SYSCALL(250, sys_epoll_create)
-__SYSCALL(251, sys_epoll_ctl)
-__SYSCALL(252, sys_epoll_wait)
-__SYSCALL(253, sys_remap_file_pages)
-__SYSCALL(254, sys_ni_syscall) /* 254 for set_thread_area */
-__SYSCALL(255, sys_ni_syscall) /* 255 for get_thread_area */
-__SYSCALL(256, sys_set_tid_address)
-__SYSCALL(257, compat_sys_timer_create)
-__SYSCALL(258, compat_sys_timer_settime)
-__SYSCALL(259, compat_sys_timer_gettime)
-__SYSCALL(260, sys_timer_getoverrun)
-__SYSCALL(261, sys_timer_delete)
-__SYSCALL(262, compat_sys_clock_settime)
-__SYSCALL(263, compat_sys_clock_gettime)
-__SYSCALL(264, compat_sys_clock_getres)
-__SYSCALL(265, compat_sys_clock_nanosleep)
-__SYSCALL(266, compat_sys_statfs64_wrapper)
-__SYSCALL(267, compat_sys_fstatfs64_wrapper)
-__SYSCALL(268, sys_tgkill)
-__SYSCALL(269, compat_sys_utimes)
-__SYSCALL(270, compat_sys_fadvise64_64_wrapper)
-__SYSCALL(271, sys_pciconfig_iobase)
-__SYSCALL(272, sys_pciconfig_read)
-__SYSCALL(273, sys_pciconfig_write)
-__SYSCALL(274, compat_sys_mq_open)
-__SYSCALL(275, sys_mq_unlink)
-__SYSCALL(276, compat_sys_mq_timedsend)
-__SYSCALL(277, compat_sys_mq_timedreceive)
-__SYSCALL(278, compat_sys_mq_notify)
-__SYSCALL(279, compat_sys_mq_getsetattr)
-__SYSCALL(280, compat_sys_waitid)
-__SYSCALL(281, sys_socket)
-__SYSCALL(282, sys_bind)
-__SYSCALL(283, sys_connect)
-__SYSCALL(284, sys_listen)
-__SYSCALL(285, sys_accept)
-__SYSCALL(286, sys_getsockname)
-__SYSCALL(287, sys_getpeername)
-__SYSCALL(288, sys_socketpair)
-__SYSCALL(289, sys_send)
-__SYSCALL(290, sys_sendto)
-__SYSCALL(291, compat_sys_recv)
-__SYSCALL(292, compat_sys_recvfrom)
-__SYSCALL(293, sys_shutdown)
-__SYSCALL(294, compat_sys_setsockopt)
-__SYSCALL(295, compat_sys_getsockopt)
-__SYSCALL(296, compat_sys_sendmsg)
-__SYSCALL(297, compat_sys_recvmsg)
-__SYSCALL(298, sys_semop)
-__SYSCALL(299, sys_semget)
-__SYSCALL(300, compat_sys_semctl)
-__SYSCALL(301, compat_sys_msgsnd)
-__SYSCALL(302, compat_sys_msgrcv)
-__SYSCALL(303, sys_msgget)
-__SYSCALL(304, compat_sys_msgctl)
-__SYSCALL(305, compat_sys_shmat)
-__SYSCALL(306, sys_shmdt)
-__SYSCALL(307, sys_shmget)
-__SYSCALL(308, compat_sys_shmctl)
-__SYSCALL(309, sys_add_key)
-__SYSCALL(310, sys_request_key)
-__SYSCALL(311, compat_sys_keyctl)
-__SYSCALL(312, compat_sys_semtimedop)
-__SYSCALL(313, sys_ni_syscall)
-__SYSCALL(314, sys_ioprio_set)
-__SYSCALL(315, sys_ioprio_get)
-__SYSCALL(316, sys_inotify_init)
-__SYSCALL(317, sys_inotify_add_watch)
-__SYSCALL(318, sys_inotify_rm_watch)
-__SYSCALL(319, compat_sys_mbind)
-__SYSCALL(320, compat_sys_get_mempolicy)
-__SYSCALL(321, compat_sys_set_mempolicy)
-__SYSCALL(322, compat_sys_openat)
-__SYSCALL(323, sys_mkdirat)
-__SYSCALL(324, sys_mknodat)
-__SYSCALL(325, sys_fchownat)
-__SYSCALL(326, compat_sys_futimesat)
-__SYSCALL(327, sys_fstatat64)
-__SYSCALL(328, sys_unlinkat)
-__SYSCALL(329, sys_renameat)
-__SYSCALL(330, sys_linkat)
-__SYSCALL(331, sys_symlinkat)
-__SYSCALL(332, sys_readlinkat)
-__SYSCALL(333, sys_fchmodat)
-__SYSCALL(334, sys_faccessat)
-__SYSCALL(335, compat_sys_pselect6)
-__SYSCALL(336, compat_sys_ppoll)
-__SYSCALL(337, sys_unshare)
-__SYSCALL(338, compat_sys_set_robust_list)
-__SYSCALL(339, compat_sys_get_robust_list)
-__SYSCALL(340, sys_splice)
-__SYSCALL(341, compat_sys_sync_file_range2_wrapper)
-__SYSCALL(342, sys_tee)
-__SYSCALL(343, compat_sys_vmsplice)
-__SYSCALL(344, compat_sys_move_pages)
-__SYSCALL(345, sys_getcpu)
-__SYSCALL(346, compat_sys_epoll_pwait)
-__SYSCALL(347, compat_sys_kexec_load)
-__SYSCALL(348, compat_sys_utimensat)
-__SYSCALL(349, compat_sys_signalfd)
-__SYSCALL(350, sys_timerfd_create)
-__SYSCALL(351, sys_eventfd)
-__SYSCALL(352, compat_sys_fallocate_wrapper)
-__SYSCALL(353, compat_sys_timerfd_settime)
-__SYSCALL(354, compat_sys_timerfd_gettime)
-__SYSCALL(355, compat_sys_signalfd4)
-__SYSCALL(356, sys_eventfd2)
-__SYSCALL(357, sys_epoll_create1)
-__SYSCALL(358, sys_dup3)
-__SYSCALL(359, sys_pipe2)
-__SYSCALL(360, sys_inotify_init1)
-__SYSCALL(361, compat_sys_preadv)
-__SYSCALL(362, compat_sys_pwritev)
-__SYSCALL(363, compat_sys_rt_tgsigqueueinfo)
-__SYSCALL(364, sys_perf_event_open)
-__SYSCALL(365, compat_sys_recvmmsg)
-__SYSCALL(366, sys_accept4)
-__SYSCALL(367, sys_fanotify_init)
-__SYSCALL(368, compat_sys_fanotify_mark)
-__SYSCALL(369, sys_prlimit64)
-__SYSCALL(370, sys_name_to_handle_at)
-__SYSCALL(371, compat_sys_open_by_handle_at)
-__SYSCALL(372, compat_sys_clock_adjtime)
-__SYSCALL(373, sys_syncfs)
-__SYSCALL(374, compat_sys_sendmmsg)
-__SYSCALL(375, sys_setns)
-__SYSCALL(376, compat_sys_process_vm_readv)
-__SYSCALL(377, compat_sys_process_vm_writev)
-__SYSCALL(378, sys_kcmp)
-__SYSCALL(379, sys_finit_module)
-__SYSCALL(380, sys_sched_setattr)
-__SYSCALL(381, sys_sched_getattr)
-__SYSCALL(382, sys_renameat2)
-
-#define __NR_compat_syscalls 383
-
-/*
- * Compat syscall numbers used by the AArch64 kernel.
- */
-#define __NR_compat_restart_syscall 0
-#define __NR_compat_sigreturn 119
-#define __NR_compat_rt_sigreturn 173
-
-
-/*
- * The following SVCs are ARM private.
- */
-#define __ARM_NR_COMPAT_BASE 0x0f0000
-#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2)
-#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5)
+#define __NR_restart_syscall 0
+__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
+#define __NR_exit 1
+__SYSCALL(__NR_exit, sys_exit)
+#define __NR_fork 2
+__SYSCALL(__NR_fork, sys_fork)
+#define __NR_read 3
+__SYSCALL(__NR_read, sys_read)
+#define __NR_write 4
+__SYSCALL(__NR_write, sys_write)
+#define __NR_open 5
+__SYSCALL(__NR_open, compat_sys_open)
+#define __NR_close 6
+__SYSCALL(__NR_close, sys_close)
+ /* 7 was sys_waitpid */
+__SYSCALL(7, sys_ni_syscall)
+#define __NR_creat 8
+__SYSCALL(__NR_creat, sys_creat)
+#define __NR_link 9
+__SYSCALL(__NR_link, sys_link)
+#define __NR_unlink 10
+__SYSCALL(__NR_unlink, sys_unlink)
+#define __NR_execve 11
+__SYSCALL(__NR_execve, compat_sys_execve)
+#define __NR_chdir 12
+__SYSCALL(__NR_chdir, sys_chdir)
+ /* 13 was sys_time */
+__SYSCALL(13, sys_ni_syscall)
+#define __NR_mknod 14
+__SYSCALL(__NR_mknod, sys_mknod)
+#define __NR_chmod 15
+__SYSCALL(__NR_chmod, sys_chmod)
+#define __NR_lchown 16
+__SYSCALL(__NR_lchown, sys_lchown16)
+ /* 17 was sys_break */
+__SYSCALL(17, sys_ni_syscall)
+ /* 18 was sys_stat */
+__SYSCALL(18, sys_ni_syscall)
+#define __NR_lseek 19
+__SYSCALL(__NR_lseek, compat_sys_lseek)
+#define __NR_getpid 20
+__SYSCALL(__NR_getpid, sys_getpid)
+#define __NR_mount 21
+__SYSCALL(__NR_mount, compat_sys_mount)
+ /* 22 was sys_umount */
+__SYSCALL(22, sys_ni_syscall)
+#define __NR_setuid 23
+__SYSCALL(__NR_setuid, sys_setuid16)
+#define __NR_getuid 24
+__SYSCALL(__NR_getuid, sys_getuid16)
+ /* 25 was sys_stime */
+__SYSCALL(25, sys_ni_syscall)
+#define __NR_ptrace 26
+__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+ /* 27 was sys_alarm */
+__SYSCALL(27, sys_ni_syscall)
+ /* 28 was sys_fstat */
+__SYSCALL(28, sys_ni_syscall)
+#define __NR_pause 29
+__SYSCALL(__NR_pause, sys_pause)
+ /* 30 was sys_utime */
+__SYSCALL(30, sys_ni_syscall)
+ /* 31 was sys_stty */
+__SYSCALL(31, sys_ni_syscall)
+ /* 32 was sys_gtty */
+__SYSCALL(32, sys_ni_syscall)
+#define __NR_access 33
+__SYSCALL(__NR_access, sys_access)
+#define __NR_nice 34
+__SYSCALL(__NR_nice, sys_nice)
+ /* 35 was sys_ftime */
+__SYSCALL(35, sys_ni_syscall)
+#define __NR_sync 36
+__SYSCALL(__NR_sync, sys_sync)
+#define __NR_kill 37
+__SYSCALL(__NR_kill, sys_kill)
+#define __NR_rename 38
+__SYSCALL(__NR_rename, sys_rename)
+#define __NR_mkdir 39
+__SYSCALL(__NR_mkdir, sys_mkdir)
+#define __NR_rmdir 40
+__SYSCALL(__NR_rmdir, sys_rmdir)
+#define __NR_dup 41
+__SYSCALL(__NR_dup, sys_dup)
+#define __NR_pipe 42
+__SYSCALL(__NR_pipe, sys_pipe)
+#define __NR_times 43
+__SYSCALL(__NR_times, compat_sys_times)
+ /* 44 was sys_prof */
+__SYSCALL(44, sys_ni_syscall)
+#define __NR_brk 45
+__SYSCALL(__NR_brk, sys_brk)
+#define __NR_setgid 46
+__SYSCALL(__NR_setgid, sys_setgid16)
+#define __NR_getgid 47
+__SYSCALL(__NR_getgid, sys_getgid16)
+ /* 48 was sys_signal */
+__SYSCALL(48, sys_ni_syscall)
+#define __NR_geteuid 49
+__SYSCALL(__NR_geteuid, sys_geteuid16)
+#define __NR_getegid 50
+__SYSCALL(__NR_getegid, sys_getegid16)
+#define __NR_acct 51
+__SYSCALL(__NR_acct, sys_acct)
+#define __NR_umount2 52
+__SYSCALL(__NR_umount2, sys_umount)
+ /* 53 was sys_lock */
+__SYSCALL(53, sys_ni_syscall)
+#define __NR_ioctl 54
+__SYSCALL(__NR_ioctl, compat_sys_ioctl)
+#define __NR_fcntl 55
+__SYSCALL(__NR_fcntl, compat_sys_fcntl)
+ /* 56 was sys_mpx */
+__SYSCALL(56, sys_ni_syscall)
+#define __NR_setpgid 57
+__SYSCALL(__NR_setpgid, sys_setpgid)
+ /* 58 was sys_ulimit */
+__SYSCALL(58, sys_ni_syscall)
+ /* 59 was sys_olduname */
+__SYSCALL(59, sys_ni_syscall)
+#define __NR_umask 60
+__SYSCALL(__NR_umask, sys_umask)
+#define __NR_chroot 61
+__SYSCALL(__NR_chroot, sys_chroot)
+#define __NR_ustat 62
+__SYSCALL(__NR_ustat, compat_sys_ustat)
+#define __NR_dup2 63
+__SYSCALL(__NR_dup2, sys_dup2)
+#define __NR_getppid 64
+__SYSCALL(__NR_getppid, sys_getppid)
+#define __NR_getpgrp 65
+__SYSCALL(__NR_getpgrp, sys_getpgrp)
+#define __NR_setsid 66
+__SYSCALL(__NR_setsid, sys_setsid)
+#define __NR_sigaction 67
+__SYSCALL(__NR_sigaction, compat_sys_sigaction)
+ /* 68 was sys_sgetmask */
+__SYSCALL(68, sys_ni_syscall)
+ /* 69 was sys_ssetmask */
+__SYSCALL(69, sys_ni_syscall)
+#define __NR_setreuid 70
+__SYSCALL(__NR_setreuid, sys_setreuid16)
+#define __NR_setregid 71
+__SYSCALL(__NR_setregid, sys_setregid16)
+#define __NR_sigsuspend 72
+__SYSCALL(__NR_sigsuspend, sys_sigsuspend)
+#define __NR_sigpending 73
+__SYSCALL(__NR_sigpending, compat_sys_sigpending)
+#define __NR_sethostname 74
+__SYSCALL(__NR_sethostname, sys_sethostname)
+#define __NR_setrlimit 75
+__SYSCALL(__NR_setrlimit, compat_sys_setrlimit)
+ /* 76 was compat_sys_getrlimit */
+__SYSCALL(76, sys_ni_syscall)
+#define __NR_getrusage 77
+__SYSCALL(__NR_getrusage, compat_sys_getrusage)
+#define __NR_gettimeofday 78
+__SYSCALL(__NR_gettimeofday, compat_sys_gettimeofday)
+#define __NR_settimeofday 79
+__SYSCALL(__NR_settimeofday, compat_sys_settimeofday)
+#define __NR_getgroups 80
+__SYSCALL(__NR_getgroups, sys_getgroups16)
+#define __NR_setgroups 81
+__SYSCALL(__NR_setgroups, sys_setgroups16)
+ /* 82 was compat_sys_select */
+__SYSCALL(82, sys_ni_syscall)
+#define __NR_symlink 83
+__SYSCALL(__NR_symlink, sys_symlink)
+ /* 84 was sys_lstat */
+__SYSCALL(84, sys_ni_syscall)
+#define __NR_readlink 85
+__SYSCALL(__NR_readlink, sys_readlink)
+#define __NR_uselib 86
+__SYSCALL(__NR_uselib, sys_uselib)
+#define __NR_swapon 87
+__SYSCALL(__NR_swapon, sys_swapon)
+#define __NR_reboot 88
+__SYSCALL(__NR_reboot, sys_reboot)
+ /* 89 was sys_readdir */
+__SYSCALL(89, sys_ni_syscall)
+ /* 90 was sys_mmap */
+__SYSCALL(90, sys_ni_syscall)
+#define __NR_munmap 91
+__SYSCALL(__NR_munmap, sys_munmap)
+#define __NR_truncate 92
+__SYSCALL(__NR_truncate, compat_sys_truncate)
+#define __NR_ftruncate 93
+__SYSCALL(__NR_ftruncate, compat_sys_ftruncate)
+#define __NR_fchmod 94
+__SYSCALL(__NR_fchmod, sys_fchmod)
+#define __NR_fchown 95
+__SYSCALL(__NR_fchown, sys_fchown16)
+#define __NR_getpriority 96
+__SYSCALL(__NR_getpriority, sys_getpriority)
+#define __NR_setpriority 97
+__SYSCALL(__NR_setpriority, sys_setpriority)
+ /* 98 was sys_profil */
+__SYSCALL(98, sys_ni_syscall)
+#define __NR_statfs 99
+__SYSCALL(__NR_statfs, compat_sys_statfs)
+#define __NR_fstatfs 100
+__SYSCALL(__NR_fstatfs, compat_sys_fstatfs)
+ /* 101 was sys_ioperm */
+__SYSCALL(101, sys_ni_syscall)
+ /* 102 was sys_socketcall */
+__SYSCALL(102, sys_ni_syscall)
+#define __NR_syslog 103
+__SYSCALL(__NR_syslog, sys_syslog)
+#define __NR_setitimer 104
+__SYSCALL(__NR_setitimer, compat_sys_setitimer)
+#define __NR_getitimer 105
+__SYSCALL(__NR_getitimer, compat_sys_getitimer)
+#define __NR_stat 106
+__SYSCALL(__NR_stat, compat_sys_newstat)
+#define __NR_lstat 107
+__SYSCALL(__NR_lstat, compat_sys_newlstat)
+#define __NR_fstat 108
+__SYSCALL(__NR_fstat, compat_sys_newfstat)
+ /* 109 was sys_uname */
+__SYSCALL(109, sys_ni_syscall)
+ /* 110 was sys_iopl */
+__SYSCALL(110, sys_ni_syscall)
+#define __NR_vhangup 111
+__SYSCALL(__NR_vhangup, sys_vhangup)
+ /* 112 was sys_idle */
+__SYSCALL(112, sys_ni_syscall)
+ /* 113 was sys_syscall */
+__SYSCALL(113, sys_ni_syscall)
+#define __NR_wait4 114
+__SYSCALL(__NR_wait4, compat_sys_wait4)
+#define __NR_swapoff 115
+__SYSCALL(__NR_swapoff, sys_swapoff)
+#define __NR_sysinfo 116
+__SYSCALL(__NR_sysinfo, compat_sys_sysinfo)
+ /* 117 was sys_ipc */
+__SYSCALL(117, sys_ni_syscall)
+#define __NR_fsync 118
+__SYSCALL(__NR_fsync, sys_fsync)
+#define __NR_sigreturn 119
+__SYSCALL(__NR_sigreturn, compat_sys_sigreturn_wrapper)
+#define __NR_clone 120
+__SYSCALL(__NR_clone, sys_clone)
+#define __NR_setdomainname 121
+__SYSCALL(__NR_setdomainname, sys_setdomainname)
+#define __NR_uname 122
+__SYSCALL(__NR_uname, sys_newuname)
+ /* 123 was sys_modify_ldt */
+__SYSCALL(123, sys_ni_syscall)
+#define __NR_adjtimex 124
+__SYSCALL(__NR_adjtimex, compat_sys_adjtimex)
+#define __NR_mprotect 125
+__SYSCALL(__NR_mprotect, sys_mprotect)
+#define __NR_sigprocmask 126
+__SYSCALL(__NR_sigprocmask, compat_sys_sigprocmask)
+ /* 127 was sys_create_module */
+__SYSCALL(127, sys_ni_syscall)
+#define __NR_init_module 128
+__SYSCALL(__NR_init_module, sys_init_module)
+#define __NR_delete_module 129
+__SYSCALL(__NR_delete_module, sys_delete_module)
+ /* 130 was sys_get_kernel_syms */
+__SYSCALL(130, sys_ni_syscall)
+#define __NR_quotactl 131
+__SYSCALL(__NR_quotactl, sys_quotactl)
+#define __NR_getpgid 132
+__SYSCALL(__NR_getpgid, sys_getpgid)
+#define __NR_fchdir 133
+__SYSCALL(__NR_fchdir, sys_fchdir)
+#define __NR_bdflush 134
+__SYSCALL(__NR_bdflush, sys_bdflush)
+#define __NR_sysfs 135
+__SYSCALL(__NR_sysfs, sys_sysfs)
+#define __NR_personality 136
+__SYSCALL(__NR_personality, sys_personality)
+ /* 137 was sys_afs_syscall */
+__SYSCALL(137, sys_ni_syscall)
+#define __NR_setfsuid 138
+__SYSCALL(__NR_setfsuid, sys_setfsuid16)
+#define __NR_setfsgid 139
+__SYSCALL(__NR_setfsgid, sys_setfsgid16)
+#define __NR__llseek 140
+__SYSCALL(__NR__llseek, sys_llseek)
+#define __NR_getdents 141
+__SYSCALL(__NR_getdents, compat_sys_getdents)
+#define __NR__newselect 142
+__SYSCALL(__NR__newselect, compat_sys_select)
+#define __NR_flock 143
+__SYSCALL(__NR_flock, sys_flock)
+#define __NR_msync 144
+__SYSCALL(__NR_msync, sys_msync)
+#define __NR_readv 145
+__SYSCALL(__NR_readv, compat_sys_readv)
+#define __NR_writev 146
+__SYSCALL(__NR_writev, compat_sys_writev)
+#define __NR_getsid 147
+__SYSCALL(__NR_getsid, sys_getsid)
+#define __NR_fdatasync 148
+__SYSCALL(__NR_fdatasync, sys_fdatasync)
+#define __NR__sysctl 149
+__SYSCALL(__NR__sysctl, compat_sys_sysctl)
+#define __NR_mlock 150
+__SYSCALL(__NR_mlock, sys_mlock)
+#define __NR_munlock 151
+__SYSCALL(__NR_munlock, sys_munlock)
+#define __NR_mlockall 152
+__SYSCALL(__NR_mlockall, sys_mlockall)
+#define __NR_munlockall 153
+__SYSCALL(__NR_munlockall, sys_munlockall)
+#define __NR_sched_setparam 154
+__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
+#define __NR_sched_getparam 155
+__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
+#define __NR_sched_setscheduler 156
+__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
+#define __NR_sched_getscheduler 157
+__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
+#define __NR_sched_yield 158
+__SYSCALL(__NR_sched_yield, sys_sched_yield)
+#define __NR_sched_get_priority_max 159
+__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
+#define __NR_sched_get_priority_min 160
+__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
+#define __NR_sched_rr_get_interval 161
+__SYSCALL(__NR_sched_rr_get_interval, compat_sys_sched_rr_get_interval)
+#define __NR_nanosleep 162
+__SYSCALL(__NR_nanosleep, compat_sys_nanosleep)
+#define __NR_mremap 163
+__SYSCALL(__NR_mremap, sys_mremap)
+#define __NR_setresuid 164
+__SYSCALL(__NR_setresuid, sys_setresuid16)
+#define __NR_getresuid 165
+__SYSCALL(__NR_getresuid, sys_getresuid16)
+ /* 166 was sys_vm86 */
+__SYSCALL(166, sys_ni_syscall)
+ /* 167 was sys_query_module */
+__SYSCALL(167, sys_ni_syscall)
+#define __NR_poll 168
+__SYSCALL(__NR_poll, sys_poll)
+#define __NR_nfsservctl 169
+__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
+#define __NR_setresgid 170
+__SYSCALL(__NR_setresgid, sys_setresgid16)
+#define __NR_getresgid 171
+__SYSCALL(__NR_getresgid, sys_getresgid16)
+#define __NR_prctl 172
+__SYSCALL(__NR_prctl, sys_prctl)
+#define __NR_rt_sigreturn 173
+__SYSCALL(__NR_rt_sigreturn, compat_sys_rt_sigreturn_wrapper)
+#define __NR_rt_sigaction 174
+__SYSCALL(__NR_rt_sigaction, compat_sys_rt_sigaction)
+#define __NR_rt_sigprocmask 175
+__SYSCALL(__NR_rt_sigprocmask, compat_sys_rt_sigprocmask)
+#define __NR_rt_sigpending 176
+__SYSCALL(__NR_rt_sigpending, compat_sys_rt_sigpending)
+#define __NR_rt_sigtimedwait 177
+__SYSCALL(__NR_rt_sigtimedwait, compat_sys_rt_sigtimedwait)
+#define __NR_rt_sigqueueinfo 178
+__SYSCALL(__NR_rt_sigqueueinfo, compat_sys_rt_sigqueueinfo)
+#define __NR_rt_sigsuspend 179
+__SYSCALL(__NR_rt_sigsuspend, compat_sys_rt_sigsuspend)
+#define __NR_pread64 180
+__SYSCALL(__NR_pread64, compat_sys_pread64_wrapper)
+#define __NR_pwrite64 181
+__SYSCALL(__NR_pwrite64, compat_sys_pwrite64_wrapper)
+#define __NR_chown 182
+__SYSCALL(__NR_chown, sys_chown16)
+#define __NR_getcwd 183
+__SYSCALL(__NR_getcwd, sys_getcwd)
+#define __NR_capget 184
+__SYSCALL(__NR_capget, sys_capget)
+#define __NR_capset 185
+__SYSCALL(__NR_capset, sys_capset)
+#define __NR_sigaltstack 186
+__SYSCALL(__NR_sigaltstack, compat_sys_sigaltstack)
+#define __NR_sendfile 187
+__SYSCALL(__NR_sendfile, compat_sys_sendfile)
+ /* 188 reserved */
+__SYSCALL(188, sys_ni_syscall)
+ /* 189 reserved */
+__SYSCALL(189, sys_ni_syscall)
+#define __NR_vfork 190
+__SYSCALL(__NR_vfork, sys_vfork)
+#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
+__SYSCALL(__NR_ugetrlimit, compat_sys_getrlimit) /* SuS compliant getrlimit */
+#define __NR_mmap2 192
+__SYSCALL(__NR_mmap2, sys_mmap_pgoff)
+#define __NR_truncate64 193
+__SYSCALL(__NR_truncate64, compat_sys_truncate64_wrapper)
+#define __NR_ftruncate64 194
+__SYSCALL(__NR_ftruncate64, compat_sys_ftruncate64_wrapper)
+#define __NR_stat64 195
+__SYSCALL(__NR_stat64, sys_stat64)
+#define __NR_lstat64 196
+__SYSCALL(__NR_lstat64, sys_lstat64)
+#define __NR_fstat64 197
+__SYSCALL(__NR_fstat64, sys_fstat64)
+#define __NR_lchown32 198
+__SYSCALL(__NR_lchown32, sys_lchown)
+#define __NR_getuid32 199
+__SYSCALL(__NR_getuid32, sys_getuid)
+#define __NR_getgid32 200
+__SYSCALL(__NR_getgid32, sys_getgid)
+#define __NR_geteuid32 201
+__SYSCALL(__NR_geteuid32, sys_geteuid)
+#define __NR_getegid32 202
+__SYSCALL(__NR_getegid32, sys_getegid)
+#define __NR_setreuid32 203
+__SYSCALL(__NR_setreuid32, sys_setreuid)
+#define __NR_setregid32 204
+__SYSCALL(__NR_setregid32, sys_setregid)
+#define __NR_getgroups32 205
+__SYSCALL(__NR_getgroups32, sys_getgroups)
+#define __NR_setgroups32 206
+__SYSCALL(__NR_setgroups32, sys_setgroups)
+#define __NR_fchown32 207
+__SYSCALL(__NR_fchown32, sys_fchown)
+#define __NR_setresuid32 208
+__SYSCALL(__NR_setresuid32, sys_setresuid)
+#define __NR_getresuid32 209
+__SYSCALL(__NR_getresuid32, sys_getresuid)
+#define __NR_setresgid32 210
+__SYSCALL(__NR_setresgid32, sys_setresgid)
+#define __NR_getresgid32 211
+__SYSCALL(__NR_getresgid32, sys_getresgid)
+#define __NR_chown32 212
+__SYSCALL(__NR_chown32, sys_chown)
+#define __NR_setuid32 213
+__SYSCALL(__NR_setuid32, sys_setuid)
+#define __NR_setgid32 214
+__SYSCALL(__NR_setgid32, sys_setgid)
+#define __NR_setfsuid32 215
+__SYSCALL(__NR_setfsuid32, sys_setfsuid)
+#define __NR_setfsgid32 216
+__SYSCALL(__NR_setfsgid32, sys_setfsgid)
+#define __NR_getdents64 217
+__SYSCALL(__NR_getdents64, compat_sys_getdents64)
+#define __NR_pivot_root 218
+__SYSCALL(__NR_pivot_root, sys_pivot_root)
+#define __NR_mincore 219
+__SYSCALL(__NR_mincore, sys_mincore)
+#define __NR_madvise 220
+__SYSCALL(__NR_madvise, sys_madvise)
+#define __NR_fcntl64 221
+__SYSCALL(__NR_fcntl64, compat_sys_fcntl64)
+ /* 222 for tux */
+__SYSCALL(222, sys_ni_syscall)
+ /* 223 is unused */
+__SYSCALL(223, sys_ni_syscall)
+#define __NR_gettid 224
+__SYSCALL(__NR_gettid, sys_gettid)
+#define __NR_readahead 225
+__SYSCALL(__NR_readahead, compat_sys_readahead_wrapper)
+#define __NR_setxattr 226
+__SYSCALL(__NR_setxattr, sys_setxattr)
+#define __NR_lsetxattr 227
+__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
+#define __NR_fsetxattr 228
+__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
+#define __NR_getxattr 229
+__SYSCALL(__NR_getxattr, sys_getxattr)
+#define __NR_lgetxattr 230
+__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
+#define __NR_fgetxattr 231
+__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+#define __NR_listxattr 232
+__SYSCALL(__NR_listxattr, sys_listxattr)
+#define __NR_llistxattr 233
+__SYSCALL(__NR_llistxattr, sys_llistxattr)
+#define __NR_flistxattr 234
+__SYSCALL(__NR_flistxattr, sys_flistxattr)
+#define __NR_removexattr 235
+__SYSCALL(__NR_removexattr, sys_removexattr)
+#define __NR_lremovexattr 236
+__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+#define __NR_fremovexattr 237
+__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+#define __NR_tkill 238
+__SYSCALL(__NR_tkill, sys_tkill)
+#define __NR_sendfile64 239
+__SYSCALL(__NR_sendfile64, sys_sendfile64)
+#define __NR_futex 240
+__SYSCALL(__NR_futex, compat_sys_futex)
+#define __NR_sched_setaffinity 241
+__SYSCALL(__NR_sched_setaffinity, compat_sys_sched_setaffinity)
+#define __NR_sched_getaffinity 242
+__SYSCALL(__NR_sched_getaffinity, compat_sys_sched_getaffinity)
+#define __NR_io_setup 243
+__SYSCALL(__NR_io_setup, compat_sys_io_setup)
+#define __NR_io_destroy 244
+__SYSCALL(__NR_io_destroy, sys_io_destroy)
+#define __NR_io_getevents 245
+__SYSCALL(__NR_io_getevents, compat_sys_io_getevents)
+#define __NR_io_submit 246
+__SYSCALL(__NR_io_submit, compat_sys_io_submit)
+#define __NR_io_cancel 247
+__SYSCALL(__NR_io_cancel, sys_io_cancel)
+#define __NR_exit_group 248
+__SYSCALL(__NR_exit_group, sys_exit_group)
+#define __NR_lookup_dcookie 249
+__SYSCALL(__NR_lookup_dcookie, compat_sys_lookup_dcookie)
+#define __NR_epoll_create 250
+__SYSCALL(__NR_epoll_create, sys_epoll_create)
+#define __NR_epoll_ctl 251
+__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
+#define __NR_epoll_wait 252
+__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
+#define __NR_remap_file_pages 253
+__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
+ /* 254 for set_thread_area */
+__SYSCALL(254, sys_ni_syscall)
+ /* 255 for get_thread_area */
+__SYSCALL(255, sys_ni_syscall)
+#define __NR_set_tid_address 256
+__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
+#define __NR_timer_create 257
+__SYSCALL(__NR_timer_create, compat_sys_timer_create)
+#define __NR_timer_settime 258
+__SYSCALL(__NR_timer_settime, compat_sys_timer_settime)
+#define __NR_timer_gettime 259
+__SYSCALL(__NR_timer_gettime, compat_sys_timer_gettime)
+#define __NR_timer_getoverrun 260
+__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
+#define __NR_timer_delete 261
+__SYSCALL(__NR_timer_delete, sys_timer_delete)
+#define __NR_clock_settime 262
+__SYSCALL(__NR_clock_settime, compat_sys_clock_settime)
+#define __NR_clock_gettime 263
+__SYSCALL(__NR_clock_gettime, compat_sys_clock_gettime)
+#define __NR_clock_getres 264
+__SYSCALL(__NR_clock_getres, compat_sys_clock_getres)
+#define __NR_clock_nanosleep 265
+__SYSCALL(__NR_clock_nanosleep, compat_sys_clock_nanosleep)
+#define __NR_statfs64 266
+__SYSCALL(__NR_statfs64, compat_sys_statfs64_wrapper)
+#define __NR_fstatfs64 267
+__SYSCALL(__NR_fstatfs64, compat_sys_fstatfs64_wrapper)
+#define __NR_tgkill 268
+__SYSCALL(__NR_tgkill, sys_tgkill)
+#define __NR_utimes 269
+__SYSCALL(__NR_utimes, compat_sys_utimes)
+#define __NR_arm_fadvise64_64 270
+__SYSCALL(__NR_arm_fadvise64_64, compat_sys_fadvise64_64_wrapper)
+#define __NR_pciconfig_iobase 271
+__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase)
+#define __NR_pciconfig_read 272
+__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read)
+#define __NR_pciconfig_write 273
+__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write)
+#define __NR_mq_open 274
+__SYSCALL(__NR_mq_open, compat_sys_mq_open)
+#define __NR_mq_unlink 275
+__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+#define __NR_mq_timedsend 276
+__SYSCALL(__NR_mq_timedsend, compat_sys_mq_timedsend)
+#define __NR_mq_timedreceive 277
+__SYSCALL(__NR_mq_timedreceive, compat_sys_mq_timedreceive)
+#define __NR_mq_notify 278
+__SYSCALL(__NR_mq_notify, compat_sys_mq_notify)
+#define __NR_mq_getsetattr 279
+__SYSCALL(__NR_mq_getsetattr, compat_sys_mq_getsetattr)
+#define __NR_waitid 280
+__SYSCALL(__NR_waitid, compat_sys_waitid)
+#define __NR_socket 281
+__SYSCALL(__NR_socket, sys_socket)
+#define __NR_bind 282
+__SYSCALL(__NR_bind, sys_bind)
+#define __NR_connect 283
+__SYSCALL(__NR_connect, sys_connect)
+#define __NR_listen 284
+__SYSCALL(__NR_listen, sys_listen)
+#define __NR_accept 285
+__SYSCALL(__NR_accept, sys_accept)
+#define __NR_getsockname 286
+__SYSCALL(__NR_getsockname, sys_getsockname)
+#define __NR_getpeername 287
+__SYSCALL(__NR_getpeername, sys_getpeername)
+#define __NR_socketpair 288
+__SYSCALL(__NR_socketpair, sys_socketpair)
+#define __NR_send 289
+__SYSCALL(__NR_send, sys_send)
+#define __NR_sendto 290
+__SYSCALL(__NR_sendto, sys_sendto)
+#define __NR_recv 291
+__SYSCALL(__NR_recv, compat_sys_recv)
+#define __NR_recvfrom 292
+__SYSCALL(__NR_recvfrom, compat_sys_recvfrom)
+#define __NR_shutdown 293
+__SYSCALL(__NR_shutdown, sys_shutdown)
+#define __NR_setsockopt 294
+__SYSCALL(__NR_setsockopt, compat_sys_setsockopt)
+#define __NR_getsockopt 295
+__SYSCALL(__NR_getsockopt, compat_sys_getsockopt)
+#define __NR_sendmsg 296
+__SYSCALL(__NR_sendmsg, compat_sys_sendmsg)
+#define __NR_recvmsg 297
+__SYSCALL(__NR_recvmsg, compat_sys_recvmsg)
+#define __NR_semop 298
+__SYSCALL(__NR_semop, sys_semop)
+#define __NR_semget 299
+__SYSCALL(__NR_semget, sys_semget)
+#define __NR_semctl 300
+__SYSCALL(__NR_semctl, compat_sys_semctl)
+#define __NR_msgsnd 301
+__SYSCALL(__NR_msgsnd, compat_sys_msgsnd)
+#define __NR_msgrcv 302
+__SYSCALL(__NR_msgrcv, compat_sys_msgrcv)
+#define __NR_msgget 303
+__SYSCALL(__NR_msgget, sys_msgget)
+#define __NR_msgctl 304
+__SYSCALL(__NR_msgctl, compat_sys_msgctl)
+#define __NR_shmat 305
+__SYSCALL(__NR_shmat, compat_sys_shmat)
+#define __NR_shmdt 306
+__SYSCALL(__NR_shmdt, sys_shmdt)
+#define __NR_shmget 307
+__SYSCALL(__NR_shmget, sys_shmget)
+#define __NR_shmctl 308
+__SYSCALL(__NR_shmctl, compat_sys_shmctl)
+#define __NR_add_key 309
+__SYSCALL(__NR_add_key, sys_add_key)
+#define __NR_request_key 310
+__SYSCALL(__NR_request_key, sys_request_key)
+#define __NR_keyctl 311
+__SYSCALL(__NR_keyctl, compat_sys_keyctl)
+#define __NR_semtimedop 312
+__SYSCALL(__NR_semtimedop, compat_sys_semtimedop)
+#define __NR_vserver 313
+__SYSCALL(__NR_vserver, sys_ni_syscall)
+#define __NR_ioprio_set 314
+__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
+#define __NR_ioprio_get 315
+__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
+#define __NR_inotify_init 316
+__SYSCALL(__NR_inotify_init, sys_inotify_init)
+#define __NR_inotify_add_watch 317
+__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
+#define __NR_inotify_rm_watch 318
+__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
+#define __NR_mbind 319
+__SYSCALL(__NR_mbind, compat_sys_mbind)
+#define __NR_get_mempolicy 320
+__SYSCALL(__NR_get_mempolicy, compat_sys_get_mempolicy)
+#define __NR_set_mempolicy 321
+__SYSCALL(__NR_set_mempolicy, compat_sys_set_mempolicy)
+#define __NR_openat 322
+__SYSCALL(__NR_openat, compat_sys_openat)
+#define __NR_mkdirat 323
+__SYSCALL(__NR_mkdirat, sys_mkdirat)
+#define __NR_mknodat 324
+__SYSCALL(__NR_mknodat, sys_mknodat)
+#define __NR_fchownat 325
+__SYSCALL(__NR_fchownat, sys_fchownat)
+#define __NR_futimesat 326
+__SYSCALL(__NR_futimesat, compat_sys_futimesat)
+#define __NR_fstatat64 327
+__SYSCALL(__NR_fstatat64, sys_fstatat64)
+#define __NR_unlinkat 328
+__SYSCALL(__NR_unlinkat, sys_unlinkat)
+#define __NR_renameat 329
+__SYSCALL(__NR_renameat, sys_renameat)
+#define __NR_linkat 330
+__SYSCALL(__NR_linkat, sys_linkat)
+#define __NR_symlinkat 331
+__SYSCALL(__NR_symlinkat, sys_symlinkat)
+#define __NR_readlinkat 332
+__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#define __NR_fchmodat 333
+__SYSCALL(__NR_fchmodat, sys_fchmodat)
+#define __NR_faccessat 334
+__SYSCALL(__NR_faccessat, sys_faccessat)
+#define __NR_pselect6 335
+__SYSCALL(__NR_pselect6, compat_sys_pselect6)
+#define __NR_ppoll 336
+__SYSCALL(__NR_ppoll, compat_sys_ppoll)
+#define __NR_unshare 337
+__SYSCALL(__NR_unshare, sys_unshare)
+#define __NR_set_robust_list 338
+__SYSCALL(__NR_set_robust_list, compat_sys_set_robust_list)
+#define __NR_get_robust_list 339
+__SYSCALL(__NR_get_robust_list, compat_sys_get_robust_list)
+#define __NR_splice 340
+__SYSCALL(__NR_splice, sys_splice)
+#define __NR_sync_file_range2 341
+__SYSCALL(__NR_sync_file_range2, compat_sys_sync_file_range2_wrapper)
+#define __NR_tee 342
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_vmsplice 343
+__SYSCALL(__NR_vmsplice, compat_sys_vmsplice)
+#define __NR_move_pages 344
+__SYSCALL(__NR_move_pages, compat_sys_move_pages)
+#define __NR_getcpu 345
+__SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_epoll_pwait 346
+__SYSCALL(__NR_epoll_pwait, compat_sys_epoll_pwait)
+#define __NR_kexec_load 347
+__SYSCALL(__NR_kexec_load, compat_sys_kexec_load)
+#define __NR_utimensat 348
+__SYSCALL(__NR_utimensat, compat_sys_utimensat)
+#define __NR_signalfd 349
+__SYSCALL(__NR_signalfd, compat_sys_signalfd)
+#define __NR_timerfd_create 350
+__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
+#define __NR_eventfd 351
+__SYSCALL(__NR_eventfd, sys_eventfd)
+#define __NR_fallocate 352
+__SYSCALL(__NR_fallocate, compat_sys_fallocate_wrapper)
+#define __NR_timerfd_settime 353
+__SYSCALL(__NR_timerfd_settime, compat_sys_timerfd_settime)
+#define __NR_timerfd_gettime 354
+__SYSCALL(__NR_timerfd_gettime, compat_sys_timerfd_gettime)
+#define __NR_signalfd4 355
+__SYSCALL(__NR_signalfd4, compat_sys_signalfd4)
+#define __NR_eventfd2 356
+__SYSCALL(__NR_eventfd2, sys_eventfd2)
+#define __NR_epoll_create1 357
+__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
+#define __NR_dup3 358
+__SYSCALL(__NR_dup3, sys_dup3)
+#define __NR_pipe2 359
+__SYSCALL(__NR_pipe2, sys_pipe2)
+#define __NR_inotify_init1 360
+__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
+#define __NR_preadv 361
+__SYSCALL(__NR_preadv, compat_sys_preadv)
+#define __NR_pwritev 362
+__SYSCALL(__NR_pwritev, compat_sys_pwritev)
+#define __NR_rt_tgsigqueueinfo 363
+__SYSCALL(__NR_rt_tgsigqueueinfo, compat_sys_rt_tgsigqueueinfo)
+#define __NR_perf_event_open 364
+__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+#define __NR_recvmmsg 365
+__SYSCALL(__NR_recvmmsg, compat_sys_recvmmsg)
+#define __NR_accept4 366
+__SYSCALL(__NR_accept4, sys_accept4)
+#define __NR_fanotify_init 367
+__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
+#define __NR_fanotify_mark 368
+__SYSCALL(__NR_fanotify_mark, compat_sys_fanotify_mark)
+#define __NR_prlimit64 369
+__SYSCALL(__NR_prlimit64, sys_prlimit64)
+#define __NR_name_to_handle_at 370
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at 371
+__SYSCALL(__NR_open_by_handle_at, compat_sys_open_by_handle_at)
+#define __NR_clock_adjtime 372
+__SYSCALL(__NR_clock_adjtime, compat_sys_clock_adjtime)
+#define __NR_syncfs 373
+__SYSCALL(__NR_syncfs, sys_syncfs)
+#define __NR_sendmmsg 374
+__SYSCALL(__NR_sendmmsg, compat_sys_sendmmsg)
+#define __NR_setns 375
+__SYSCALL(__NR_setns, sys_setns)
+#define __NR_process_vm_readv 376
+__SYSCALL(__NR_process_vm_readv, compat_sys_process_vm_readv)
+#define __NR_process_vm_writev 377
+__SYSCALL(__NR_process_vm_writev, compat_sys_process_vm_writev)
+#define __NR_kcmp 378
+__SYSCALL(__NR_kcmp, sys_kcmp)
+#define __NR_finit_module 379
+__SYSCALL(__NR_finit_module, sys_finit_module)
+#define __NR_sched_setattr 380
+__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+#define __NR_sched_getattr 381
+__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+#define __NR_renameat2 382
+__SYSCALL(__NR_renameat2, sys_renameat2)
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 215ad4649dd7..7a5df5252dd7 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -50,6 +50,10 @@ static inline bool is_hyp_mode_mismatched(void)
return __boot_cpu_mode[0] != __boot_cpu_mode[1];
}
+/* The section containing the hypervisor text */
+extern char __hyp_text_start[];
+extern char __hyp_text_end[];
+
#endif /* __ASSEMBLY__ */
#endif /* ! __ASM__VIRT_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index cdaedad3afe5..df7ef8768fc2 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -4,8 +4,7 @@
CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
-CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \
- -I$(src)/../../../scripts/dtc/libfdt
+CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_insn.o = -pg
@@ -15,7 +14,8 @@ CFLAGS_REMOVE_return_address.o = -pg
arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
entry-fpsimd.o process.o ptrace.o setup.o signal.o \
sys.o stacktrace.o time.o traps.o io.o vdso.o \
- hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
+ hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \
+ cpuinfo.o
arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
sys_compat.o
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 646f888387cd..9a9fce090d58 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -120,6 +120,7 @@ int main(void)
DEFINE(VCPU_ESR_EL2, offsetof(struct kvm_vcpu, arch.fault.esr_el2));
DEFINE(VCPU_FAR_EL2, offsetof(struct kvm_vcpu, arch.fault.far_el2));
DEFINE(VCPU_HPFAR_EL2, offsetof(struct kvm_vcpu, arch.fault.hpfar_el2));
+ DEFINE(VCPU_DEBUG_FLAGS, offsetof(struct kvm_vcpu, arch.debug_flags));
DEFINE(VCPU_HCR_EL2, offsetof(struct kvm_vcpu, arch.hcr_el2));
DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines));
DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context));
@@ -129,13 +130,24 @@ int main(void)
DEFINE(KVM_TIMER_ENABLED, offsetof(struct kvm, arch.timer.enabled));
DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu));
- DEFINE(VGIC_CPU_HCR, offsetof(struct vgic_cpu, vgic_hcr));
- DEFINE(VGIC_CPU_VMCR, offsetof(struct vgic_cpu, vgic_vmcr));
- DEFINE(VGIC_CPU_MISR, offsetof(struct vgic_cpu, vgic_misr));
- DEFINE(VGIC_CPU_EISR, offsetof(struct vgic_cpu, vgic_eisr));
- DEFINE(VGIC_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_elrsr));
- DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
- DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
+ DEFINE(VGIC_SAVE_FN, offsetof(struct vgic_sr_vectors, save_vgic));
+ DEFINE(VGIC_RESTORE_FN, offsetof(struct vgic_sr_vectors, restore_vgic));
+ DEFINE(VGIC_SR_VECTOR_SZ, sizeof(struct vgic_sr_vectors));
+ DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
+ DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
+ DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
+ DEFINE(VGIC_V2_CPU_EISR, offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
+ DEFINE(VGIC_V2_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
+ DEFINE(VGIC_V2_CPU_APR, offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
+ DEFINE(VGIC_V2_CPU_LR, offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
+ DEFINE(VGIC_V3_CPU_HCR, offsetof(struct vgic_cpu, vgic_v3.vgic_hcr));
+ DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr));
+ DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr));
+ DEFINE(VGIC_V3_CPU_EISR, offsetof(struct vgic_cpu, vgic_v3.vgic_eisr));
+ DEFINE(VGIC_V3_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v3.vgic_elrsr));
+ DEFINE(VGIC_V3_CPU_AP0R, offsetof(struct vgic_cpu, vgic_v3.vgic_ap0r));
+ DEFINE(VGIC_V3_CPU_AP1R, offsetof(struct vgic_cpu, vgic_v3.vgic_ap1r));
+ DEFINE(VGIC_V3_CPU_LR, offsetof(struct vgic_cpu, vgic_v3.vgic_lr));
DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr));
DEFINE(KVM_VGIC_VCTRL, offsetof(struct kvm, arch.vgic.vctrl_base));
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index d62d12fb36c8..cce952440c64 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -30,8 +30,8 @@ const struct cpu_operations *cpu_ops[NR_CPUS];
static const struct cpu_operations *supported_cpu_ops[] __initconst = {
#ifdef CONFIG_SMP
&smp_spin_table_ops,
- &cpu_psci_ops,
#endif
+ &cpu_psci_ops,
NULL,
};
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
new file mode 100644
index 000000000000..f798f66634af
--- /dev/null
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -0,0 +1,192 @@
+/*
+ * Record and handle CPU attributes.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <asm/arch_timer.h>
+#include <asm/cachetype.h>
+#include <asm/cpu.h>
+#include <asm/cputype.h>
+
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/smp.h>
+
+/*
+ * In case the boot CPU is hotpluggable, we record its initial state and
+ * current state separately. Certain system registers may contain different
+ * values depending on configuration at or after reset.
+ */
+DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
+static struct cpuinfo_arm64 boot_cpu_data;
+
+static char *icache_policy_str[] = {
+ [ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
+ [ICACHE_POLICY_AIVIVT] = "AIVIVT",
+ [ICACHE_POLICY_VIPT] = "VIPT",
+ [ICACHE_POLICY_PIPT] = "PIPT",
+};
+
+unsigned long __icache_flags;
+
+static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
+{
+ unsigned int cpu = smp_processor_id();
+ u32 l1ip = CTR_L1IP(info->reg_ctr);
+
+ if (l1ip != ICACHE_POLICY_PIPT)
+ set_bit(ICACHEF_ALIASING, &__icache_flags);
+ if (l1ip == ICACHE_POLICY_AIVIVT);
+ set_bit(ICACHEF_AIVIVT, &__icache_flags);
+
+ pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
+}
+
+static int check_reg_mask(char *name, u64 mask, u64 boot, u64 cur, int cpu)
+{
+ if ((boot & mask) == (cur & mask))
+ return 0;
+
+ pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016lx, CPU%d: %#016lx\n",
+ name, (unsigned long)boot, cpu, (unsigned long)cur);
+
+ return 1;
+}
+
+#define CHECK_MASK(field, mask, boot, cur, cpu) \
+ check_reg_mask(#field, mask, (boot)->reg_ ## field, (cur)->reg_ ## field, cpu)
+
+#define CHECK(field, boot, cur, cpu) \
+ CHECK_MASK(field, ~0ULL, boot, cur, cpu)
+
+/*
+ * Verify that CPUs don't have unexpected differences that will cause problems.
+ */
+static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
+{
+ unsigned int cpu = smp_processor_id();
+ struct cpuinfo_arm64 *boot = &boot_cpu_data;
+ unsigned int diff = 0;
+
+ /*
+ * The kernel can handle differing I-cache policies, but otherwise
+ * caches should look identical. Userspace JITs will make use of
+ * *minLine.
+ */
+ diff |= CHECK_MASK(ctr, 0xffff3fff, boot, cur, cpu);
+
+ /*
+ * Userspace may perform DC ZVA instructions. Mismatched block sizes
+ * could result in too much or too little memory being zeroed if a
+ * process is preempted and migrated between CPUs.
+ */
+ diff |= CHECK(dczid, boot, cur, cpu);
+
+ /* If different, timekeeping will be broken (especially with KVM) */
+ diff |= CHECK(cntfrq, boot, cur, cpu);
+
+ /*
+ * Even in big.LITTLE, processors should be identical instruction-set
+ * wise.
+ */
+ diff |= CHECK(id_aa64isar0, boot, cur, cpu);
+ diff |= CHECK(id_aa64isar1, boot, cur, cpu);
+
+ /*
+ * Differing PARange support is fine as long as all peripherals and
+ * memory are mapped within the minimum PARange of all CPUs.
+ * Linux should not care about secure memory.
+ * ID_AA64MMFR1 is currently RES0.
+ */
+ diff |= CHECK_MASK(id_aa64mmfr0, 0xffffffffffff0ff0, boot, cur, cpu);
+ diff |= CHECK(id_aa64mmfr1, boot, cur, cpu);
+
+ /*
+ * EL3 is not our concern.
+ * ID_AA64PFR1 is currently RES0.
+ */
+ diff |= CHECK_MASK(id_aa64pfr0, 0xffffffffffff0fff, boot, cur, cpu);
+ diff |= CHECK(id_aa64pfr1, boot, cur, cpu);
+
+ /*
+ * If we have AArch32, we care about 32-bit features for compat. These
+ * registers should be RES0 otherwise.
+ */
+ diff |= CHECK(id_isar0, boot, cur, cpu);
+ diff |= CHECK(id_isar1, boot, cur, cpu);
+ diff |= CHECK(id_isar2, boot, cur, cpu);
+ diff |= CHECK(id_isar3, boot, cur, cpu);
+ diff |= CHECK(id_isar4, boot, cur, cpu);
+ diff |= CHECK(id_isar5, boot, cur, cpu);
+ diff |= CHECK(id_mmfr0, boot, cur, cpu);
+ diff |= CHECK(id_mmfr1, boot, cur, cpu);
+ diff |= CHECK(id_mmfr2, boot, cur, cpu);
+ diff |= CHECK(id_mmfr3, boot, cur, cpu);
+ diff |= CHECK(id_pfr0, boot, cur, cpu);
+ diff |= CHECK(id_pfr1, boot, cur, cpu);
+
+ /*
+ * Mismatched CPU features are a recipe for disaster. Don't even
+ * pretend to support them.
+ */
+ WARN_TAINT_ONCE(diff, TAINT_CPU_OUT_OF_SPEC,
+ "Unsupported CPU feature variation.");
+}
+
+static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
+{
+ info->reg_cntfrq = arch_timer_get_cntfrq();
+ info->reg_ctr = read_cpuid_cachetype();
+ info->reg_dczid = read_cpuid(DCZID_EL0);
+ info->reg_midr = read_cpuid_id();
+
+ info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
+ info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
+ info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
+ info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
+ info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
+ info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
+
+ info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
+ info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
+ info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
+ info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
+ info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
+ info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
+ info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
+ info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
+ info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
+ info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
+ info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
+ info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
+
+ cpuinfo_detect_icache_policy(info);
+}
+
+void cpuinfo_store_cpu(void)
+{
+ struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
+ __cpuinfo_store_cpu(info);
+ cpuinfo_sanity_check(info);
+}
+
+void __init cpuinfo_store_boot_cpu(void)
+{
+ struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
+ __cpuinfo_store_cpu(info);
+
+ boot_cpu_data = *info;
+}
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index a7fb874b595e..b056369fd47d 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -30,15 +30,6 @@
#include <asm/cputype.h>
#include <asm/system_misc.h>
-/* Low-level stepping controls. */
-#define DBG_MDSCR_SS (1 << 0)
-#define DBG_SPSR_SS (1 << 21)
-
-/* MDSCR_EL1 enabling bits */
-#define DBG_MDSCR_KDE (1 << 13)
-#define DBG_MDSCR_MDE (1 << 15)
-#define DBG_MDSCR_MASK ~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
-
/* Determine debug architecture. */
u8 debug_monitors_arch(void)
{
@@ -315,20 +306,20 @@ static int brk_handler(unsigned long addr, unsigned int esr,
{
siginfo_t info;
- if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
- return 0;
+ if (user_mode(regs)) {
+ info = (siginfo_t) {
+ .si_signo = SIGTRAP,
+ .si_errno = 0,
+ .si_code = TRAP_BRKPT,
+ .si_addr = (void __user *)instruction_pointer(regs),
+ };
- if (!user_mode(regs))
+ force_sig_info(SIGTRAP, &info, current);
+ } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
+ pr_warning("Unexpected kernel BRK exception at EL1\n");
return -EFAULT;
+ }
- info = (siginfo_t) {
- .si_signo = SIGTRAP,
- .si_errno = 0,
- .si_code = TRAP_BRKPT,
- .si_addr = (void __user *)instruction_pointer(regs),
- };
-
- force_sig_info(SIGTRAP, &info, current);
return 0;
}
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
index e786e6cdc400..1317fef8dde9 100644
--- a/arch/arm64/kernel/efi-stub.c
+++ b/arch/arm64/kernel/efi-stub.c
@@ -10,46 +10,16 @@
*
*/
#include <linux/efi.h>
-#include <linux/libfdt.h>
+#include <asm/efi.h>
#include <asm/sections.h>
-/*
- * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
- * start of kernel and may not cross a 2MiB boundary. We set alignment to
- * 2MiB so we know it won't cross a 2MiB boundary.
- */
-#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
-#define MAX_FDT_OFFSET SZ_512M
-
-#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
-
-static void efi_char16_printk(efi_system_table_t *sys_table_arg,
- efi_char16_t *str);
-
-static efi_status_t efi_open_volume(efi_system_table_t *sys_table,
- void *__image, void **__fh);
-static efi_status_t efi_file_close(void *handle);
-
-static efi_status_t
-efi_file_read(void *handle, unsigned long *size, void *addr);
-
-static efi_status_t
-efi_file_size(efi_system_table_t *sys_table, void *__fh,
- efi_char16_t *filename_16, void **handle, u64 *file_sz);
-
-/* Include shared EFI stub code */
-#include "../../../drivers/firmware/efi/efi-stub-helper.c"
-#include "../../../drivers/firmware/efi/fdt.c"
-#include "../../../drivers/firmware/efi/arm-stub.c"
-
-
-static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
- unsigned long *image_addr,
- unsigned long *image_size,
- unsigned long *reserve_addr,
- unsigned long *reserve_size,
- unsigned long dram_base,
- efi_loaded_image_t *image)
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+ unsigned long *image_addr,
+ unsigned long *image_size,
+ unsigned long *reserve_addr,
+ unsigned long *reserve_size,
+ unsigned long dram_base,
+ efi_loaded_image_t *image)
{
efi_status_t status;
unsigned long kernel_size, kernel_memsize = 0;
@@ -69,7 +39,7 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
if (*image_addr != (dram_base + TEXT_OFFSET)) {
pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
efi_free(sys_table, kernel_memsize, *image_addr);
- return EFI_ERROR;
+ return EFI_LOAD_ERROR;
}
*image_size = kernel_memsize;
}
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 14db1f6e8d7f..e72f3100958f 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -414,13 +414,24 @@ static int __init arm64_enter_virtual_mode(void)
for_each_efi_memory_desc(&memmap, md) {
if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;
- if (remap_region(md, &virt_md))
- ++count;
+ if (!remap_region(md, &virt_md))
+ goto err_unmap;
+ ++count;
}
efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
- if (efi.systab)
- set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+ if (!efi.systab) {
+ /*
+ * If we have no virtual mapping for the System Table at this
+ * point, the memory map doesn't cover the physical offset where
+ * it resides. This means the System Table will be inaccessible
+ * to Runtime Services themselves once the virtual mapping is
+ * installed.
+ */
+ pr_err("Failed to remap EFI System Table -- buggy firmware?\n");
+ goto err_unmap;
+ }
+ set_bit(EFI_SYSTEM_TABLES, &efi.flags);
local_irq_save(flags);
cpu_switch_mm(idmap_pg_dir, &init_mm);
@@ -449,21 +460,18 @@ static int __init arm64_enter_virtual_mode(void)
/* Set up runtime services function pointers */
runtime = efi.systab->runtime;
- efi.get_time = runtime->get_time;
- efi.set_time = runtime->set_time;
- efi.get_wakeup_time = runtime->get_wakeup_time;
- efi.set_wakeup_time = runtime->set_wakeup_time;
- efi.get_variable = runtime->get_variable;
- efi.get_next_variable = runtime->get_next_variable;
- efi.set_variable = runtime->set_variable;
- efi.query_variable_info = runtime->query_variable_info;
- efi.update_capsule = runtime->update_capsule;
- efi.query_capsule_caps = runtime->query_capsule_caps;
- efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
- efi.reset_system = runtime->reset_system;
-
+ efi_native_runtime_setup();
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
return 0;
+
+err_unmap:
+ /* unmap all mappings that succeeded: there are 'count' of those */
+ for (virt_md = virtmap; count--; virt_md += memmap.desc_size) {
+ md = virt_md;
+ iounmap((__force void __iomem *)md->virt_addr);
+ }
+ kfree(virtmap);
+ return -1;
}
early_initcall(arm64_enter_virtual_mode);
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index d358ccacfc00..c44a82f146b1 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -52,7 +52,7 @@ ENDPROC(fpsimd_load_state)
ENTRY(fpsimd_save_partial_state)
fpsimd_save_partial x0, 1, 8, 9
ret
-ENDPROC(fpsimd_load_partial_state)
+ENDPROC(fpsimd_save_partial_state)
/*
* Load the bottom n FP registers.
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index aa5f9fcbf9ee..38e704e597f7 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -96,11 +96,6 @@
* - ftrace_graph_caller to set up an exit hook
*/
ENTRY(_mcount)
-#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
- ldr x0, =ftrace_trace_stop
- ldr x0, [x0] // if ftrace_trace_stop
- ret // return;
-#endif
mcount_enter
ldr x0, =ftrace_trace_function
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 9ce04ba6bcb0..f0b5e5120a87 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -27,7 +27,32 @@
#include <asm/esr.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
-#include <asm/unistd32.h>
+
+/*
+ * Context tracking subsystem. Used to instrument transitions
+ * between user and kernel mode.
+ */
+ .macro ct_user_exit, syscall = 0
+#ifdef CONFIG_CONTEXT_TRACKING
+ bl context_tracking_user_exit
+ .if \syscall == 1
+ /*
+ * Save/restore needed during syscalls. Restore syscall arguments from
+ * the values already saved on stack during kernel_entry.
+ */
+ ldp x0, x1, [sp]
+ ldp x2, x3, [sp, #S_X2]
+ ldp x4, x5, [sp, #S_X4]
+ ldp x6, x7, [sp, #S_X6]
+ .endif
+#endif
+ .endm
+
+ .macro ct_user_enter
+#ifdef CONFIG_CONTEXT_TRACKING
+ bl context_tracking_user_enter
+#endif
+ .endm
/*
* Bad Abort numbers
@@ -91,6 +116,7 @@
.macro kernel_exit, el, ret = 0
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
.if \el == 0
+ ct_user_enter
ldr x23, [sp, #S_SP] // load return stack pointer
.endif
.if \ret
@@ -353,7 +379,6 @@ el0_sync:
lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
cmp x24, #ESR_EL1_EC_SVC64 // SVC in 64-bit state
b.eq el0_svc
- adr lr, ret_to_user
cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
b.eq el0_da
cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
@@ -382,7 +407,6 @@ el0_sync_compat:
lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
cmp x24, #ESR_EL1_EC_SVC32 // SVC in 32-bit state
b.eq el0_svc_compat
- adr lr, ret_to_user
cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
b.eq el0_da
cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
@@ -425,48 +449,59 @@ el0_da:
/*
* Data abort handling
*/
- mrs x0, far_el1
- bic x0, x0, #(0xff << 56)
+ mrs x26, far_el1
// enable interrupts before calling the main handler
enable_dbg_and_irq
+ ct_user_exit
+ bic x0, x26, #(0xff << 56)
mov x1, x25
mov x2, sp
+ adr lr, ret_to_user
b do_mem_abort
el0_ia:
/*
* Instruction abort handling
*/
- mrs x0, far_el1
+ mrs x26, far_el1
// enable interrupts before calling the main handler
enable_dbg_and_irq
+ ct_user_exit
+ mov x0, x26
orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts
mov x2, sp
+ adr lr, ret_to_user
b do_mem_abort
el0_fpsimd_acc:
/*
* Floating Point or Advanced SIMD access
*/
enable_dbg
+ ct_user_exit
mov x0, x25
mov x1, sp
+ adr lr, ret_to_user
b do_fpsimd_acc
el0_fpsimd_exc:
/*
* Floating Point or Advanced SIMD exception
*/
enable_dbg
+ ct_user_exit
mov x0, x25
mov x1, sp
+ adr lr, ret_to_user
b do_fpsimd_exc
el0_sp_pc:
/*
* Stack or PC alignment exception handling
*/
- mrs x0, far_el1
+ mrs x26, far_el1
// enable interrupts before calling the main handler
enable_dbg_and_irq
+ mov x0, x26
mov x1, x25
mov x2, sp
+ adr lr, ret_to_user
b do_sp_pc_abort
el0_undef:
/*
@@ -474,7 +509,9 @@ el0_undef:
*/
// enable interrupts before calling the main handler
enable_dbg_and_irq
+ ct_user_exit
mov x0, sp
+ adr lr, ret_to_user
b do_undefinstr
el0_dbg:
/*
@@ -486,12 +523,15 @@ el0_dbg:
mov x2, sp
bl do_debug_exception
enable_dbg
+ ct_user_exit
b ret_to_user
el0_inv:
enable_dbg
+ ct_user_exit
mov x0, sp
mov x1, #BAD_SYNC
mrs x2, esr_el1
+ adr lr, ret_to_user
b bad_mode
ENDPROC(el0_sync)
@@ -504,6 +544,7 @@ el0_irq_naked:
bl trace_hardirqs_off
#endif
+ ct_user_exit
irq_handler
#ifdef CONFIG_TRACE_IRQFLAGS
@@ -608,6 +649,7 @@ el0_svc:
el0_svc_naked: // compat entry point
stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
enable_dbg_and_irq
+ ct_user_exit 1
ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
tst x16, #_TIF_SYSCALL_WORK
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index a2c1195abb7f..144f10567f82 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -22,6 +22,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/irqchip/arm-gic-v3.h>
#include <asm/assembler.h>
#include <asm/ptrace.h>
@@ -35,37 +36,31 @@
#include <asm/page.h>
#include <asm/virt.h>
-/*
- * swapper_pg_dir is the virtual address of the initial page table. We place
- * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has
- * 2 pages and is placed below swapper_pg_dir.
- */
#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
-#if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000
-#error KERNEL_RAM_VADDR must start at 0xXXX80000
+#if (TEXT_OFFSET & 0xf) != 0
+#error TEXT_OFFSET must be at least 16B aligned
+#elif (PAGE_OFFSET & 0xfffff) != 0
+#error PAGE_OFFSET must be at least 2MB aligned
+#elif TEXT_OFFSET > 0xfffff
+#error TEXT_OFFSET must be less than 2MB
#endif
-#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
-#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
-
- .globl swapper_pg_dir
- .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE
-
- .globl idmap_pg_dir
- .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE
-
- .macro pgtbl, ttb0, ttb1, phys
- add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE
- sub \ttb0, \ttb1, #IDMAP_DIR_SIZE
+ .macro pgtbl, ttb0, ttb1, virt_to_phys
+ ldr \ttb1, =swapper_pg_dir
+ ldr \ttb0, =idmap_pg_dir
+ add \ttb1, \ttb1, \virt_to_phys
+ add \ttb0, \ttb0, \virt_to_phys
.endm
#ifdef CONFIG_ARM64_64K_PAGES
#define BLOCK_SHIFT PAGE_SHIFT
#define BLOCK_SIZE PAGE_SIZE
+#define TABLE_SHIFT PMD_SHIFT
#else
#define BLOCK_SHIFT SECTION_SHIFT
#define BLOCK_SIZE SECTION_SIZE
+#define TABLE_SHIFT PUD_SHIFT
#endif
#define KERNEL_START KERNEL_RAM_VADDR
@@ -120,9 +115,9 @@ efi_head:
b stext // branch to kernel start, magic
.long 0 // reserved
#endif
- .quad TEXT_OFFSET // Image load offset from start of RAM
- .quad 0 // reserved
- .quad 0 // reserved
+ .quad _kernel_offset_le // Image load offset from start of RAM, little-endian
+ .quad _kernel_size_le // Effective size of kernel image, little-endian
+ .quad _kernel_flags_le // Informative flags, little-endian
.quad 0 // reserved
.quad 0 // reserved
.quad 0 // reserved
@@ -295,6 +290,23 @@ CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
msr cnthctl_el2, x0
msr cntvoff_el2, xzr // Clear virtual offset
+#ifdef CONFIG_ARM_GIC_V3
+ /* GICv3 system register access */
+ mrs x0, id_aa64pfr0_el1
+ ubfx x0, x0, #24, #4
+ cmp x0, #1
+ b.ne 3f
+
+ mrs_s x0, ICC_SRE_EL2
+ orr x0, x0, #ICC_SRE_EL2_SRE // Set ICC_SRE_EL2.SRE==1
+ orr x0, x0, #ICC_SRE_EL2_ENABLE // Set ICC_SRE_EL2.Enable==1
+ msr_s ICC_SRE_EL2, x0
+ isb // Make sure SRE is now set
+ msr_s ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
+
+3:
+#endif
+
/* Populate ID registers. */
mrs x0, midr_el1
mrs x1, mpidr_el1
@@ -413,7 +425,7 @@ ENTRY(secondary_startup)
mov x23, x0 // x23=current cpu_table
cbz x23, __error_p // invalid processor (x23=0)?
- pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1
+ pgtbl x25, x26, x28 // x25=TTBR0, x26=TTBR1
ldr x12, [x23, #CPU_INFO_SETUP]
add x12, x12, x28 // __virt_to_phys
blr x12 // initialise processor
@@ -455,8 +467,13 @@ ENDPROC(__enable_mmu)
* x27 = *virtual* address to jump to upon completion
*
* other registers depend on the function called upon completion
+ *
+ * We align the entire function to the smallest power of two larger than it to
+ * ensure it fits within a single block map entry. Otherwise were PHYS_OFFSET
+ * close to the end of a 512MB or 1GB block we might require an additional
+ * table to map the entire function.
*/
- .align 6
+ .align 4
__turn_mmu_on:
msr sctlr_el1, x0
isb
@@ -479,17 +496,38 @@ ENDPROC(__calc_phys_offset)
.quad PAGE_OFFSET
/*
- * Macro to populate the PGD for the corresponding block entry in the next
- * level (tbl) for the given virtual address.
+ * Macro to create a table entry to the next page.
+ *
+ * tbl: page table address
+ * virt: virtual address
+ * shift: #imm page table shift
+ * ptrs: #imm pointers per table page
+ *
+ * Preserves: virt
+ * Corrupts: tmp1, tmp2
+ * Returns: tbl -> next level table page address
+ */
+ .macro create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
+ lsr \tmp1, \virt, #\shift
+ and \tmp1, \tmp1, #\ptrs - 1 // table index
+ add \tmp2, \tbl, #PAGE_SIZE
+ orr \tmp2, \tmp2, #PMD_TYPE_TABLE // address of next table and entry type
+ str \tmp2, [\tbl, \tmp1, lsl #3]
+ add \tbl, \tbl, #PAGE_SIZE // next level table page
+ .endm
+
+/*
+ * Macro to populate the PGD (and possibily PUD) for the corresponding
+ * block entry in the next level (tbl) for the given virtual address.
*
- * Preserves: pgd, tbl, virt
+ * Preserves: tbl, next, virt
* Corrupts: tmp1, tmp2
*/
- .macro create_pgd_entry, pgd, tbl, virt, tmp1, tmp2
- lsr \tmp1, \virt, #PGDIR_SHIFT
- and \tmp1, \tmp1, #PTRS_PER_PGD - 1 // PGD index
- orr \tmp2, \tbl, #3 // PGD entry table type
- str \tmp2, [\pgd, \tmp1, lsl #3]
+ .macro create_pgd_entry, tbl, virt, tmp1, tmp2
+ create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
+#if SWAPPER_PGTABLE_LEVELS == 3
+ create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2
+#endif
.endm
/*
@@ -522,7 +560,7 @@ ENDPROC(__calc_phys_offset)
* - pgd entry for fixed mappings (TTBR1)
*/
__create_page_tables:
- pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses
+ pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses
mov x27, lr
/*
@@ -550,10 +588,10 @@ __create_page_tables:
/*
* Create the identity mapping.
*/
- add x0, x25, #PAGE_SIZE // section table address
+ mov x0, x25 // idmap_pg_dir
ldr x3, =KERNEL_START
add x3, x3, x28 // __pa(KERNEL_START)
- create_pgd_entry x25, x0, x3, x5, x6
+ create_pgd_entry x0, x3, x5, x6
ldr x6, =KERNEL_END
mov x5, x3 // __pa(KERNEL_START)
add x6, x6, x28 // __pa(KERNEL_END)
@@ -562,9 +600,9 @@ __create_page_tables:
/*
* Map the kernel image (starting with PHYS_OFFSET).
*/
- add x0, x26, #PAGE_SIZE // section table address
+ mov x0, x26 // swapper_pg_dir
mov x5, #PAGE_OFFSET
- create_pgd_entry x26, x0, x5, x3, x6
+ create_pgd_entry x0, x5, x3, x6
ldr x6, =KERNEL_END
mov x3, x24 // phys offset
create_block_map x0, x7, x3, x5, x6
@@ -586,13 +624,6 @@ __create_page_tables:
create_block_map x0, x7, x3, x5, x6
1:
/*
- * Create the pgd entry for the fixed mappings.
- */
- ldr x5, =FIXADDR_TOP // Fixed mapping virtual address
- add x0, x26, #2 * PAGE_SIZE // section table address
- create_pgd_entry x26, x0, x5, x6, x7
-
- /*
* Since the page tables have been populated with non-cacheable
* accesses (MMU disabled), invalidate the idmap and swapper page
* tables again to remove any speculatively loaded cache lines.
@@ -611,7 +642,7 @@ ENDPROC(__create_page_tables)
__switch_data:
.quad __mmap_switched
.quad __bss_start // x6
- .quad _end // x7
+ .quad __bss_stop // x7
.quad processor_id // x4
.quad __fdt_pointer // x5
.quad memstart_addr // x6
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 0959611d9ff1..a272f335c289 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/linkage.h>
+#include <linux/irqchip/arm-gic-v3.h>
#include <asm/assembler.h>
#include <asm/ptrace.h>
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
new file mode 100644
index 000000000000..8fae0756e175
--- /dev/null
+++ b/arch/arm64/kernel/image.h
@@ -0,0 +1,62 @@
+/*
+ * Linker script macros to generate Image header fields.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IMAGE_H
+#define __ASM_IMAGE_H
+
+#ifndef LINKER_SCRIPT
+#error This file should only be included in vmlinux.lds.S
+#endif
+
+/*
+ * There aren't any ELF relocations we can use to endian-swap values known only
+ * at link time (e.g. the subtraction of two symbol addresses), so we must get
+ * the linker to endian-swap certain values before emitting them.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define DATA_LE64(data) \
+ ((((data) & 0x00000000000000ff) << 56) | \
+ (((data) & 0x000000000000ff00) << 40) | \
+ (((data) & 0x0000000000ff0000) << 24) | \
+ (((data) & 0x00000000ff000000) << 8) | \
+ (((data) & 0x000000ff00000000) >> 8) | \
+ (((data) & 0x0000ff0000000000) >> 24) | \
+ (((data) & 0x00ff000000000000) >> 40) | \
+ (((data) & 0xff00000000000000) >> 56))
+#else
+#define DATA_LE64(data) ((data) & 0xffffffffffffffff)
+#endif
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define __HEAD_FLAG_BE 1
+#else
+#define __HEAD_FLAG_BE 0
+#endif
+
+#define __HEAD_FLAGS (__HEAD_FLAG_BE << 0)
+
+/*
+ * These will output as part of the Image header, which should be little-endian
+ * regardless of the endianness of the kernel. While constant values could be
+ * endian swapped in head.S, all are done here for consistency.
+ */
+#define HEAD_SYMBOLS \
+ _kernel_size_le = DATA_LE64(_end - _text); \
+ _kernel_offset_le = DATA_LE64(TEXT_OFFSET); \
+ _kernel_flags_le = DATA_LE64(__HEAD_FLAGS);
+
+#endif /* __ASM_IMAGE_H */
diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S
index 7787208e8cc6..997e6b27ff6a 100644
--- a/arch/arm64/kernel/kuser32.S
+++ b/arch/arm64/kernel/kuser32.S
@@ -28,7 +28,7 @@
* See Documentation/arm/kernel_user_helpers.txt for formal definitions.
*/
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
.align 5
.globl __kuser_helper_start
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 43b7c34f92cb..1309d64aa926 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -51,6 +51,12 @@
#include <asm/processor.h>
#include <asm/stacktrace.h>
+#ifdef CONFIG_CC_STACKPROTECTOR
+#include <linux/stackprotector.h>
+unsigned long __stack_chk_guard __read_mostly;
+EXPORT_SYMBOL(__stack_chk_guard);
+#endif
+
static void setup_restart(void)
{
/*
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 9e9798f91172..553954771a67 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -235,7 +235,7 @@ static void psci_sys_poweroff(void)
* PSCI Function IDs for v0.2+ are well defined so use
* standard values.
*/
-static int psci_0_2_init(struct device_node *np)
+static int __init psci_0_2_init(struct device_node *np)
{
int err, ver;
@@ -296,7 +296,7 @@ out_put_node:
/*
* PSCI < v0.2 get PSCI Function IDs via DT.
*/
-static int psci_0_1_init(struct device_node *np)
+static int __init psci_0_1_init(struct device_node *np)
{
u32 id;
int err;
@@ -434,9 +434,11 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
return 0;
}
#endif
+#endif
const struct cpu_operations cpu_psci_ops = {
.name = "psci",
+#ifdef CONFIG_SMP
.cpu_init = cpu_psci_cpu_init,
.cpu_prepare = cpu_psci_cpu_prepare,
.cpu_boot = cpu_psci_cpu_boot,
@@ -445,6 +447,6 @@ const struct cpu_operations cpu_psci_ops = {
.cpu_die = cpu_psci_cpu_die,
.cpu_kill = cpu_psci_cpu_kill,
#endif
+#endif
};
-#endif
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 9fde010c945f..0310811bd77d 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/audit.h>
#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -39,6 +40,7 @@
#include <asm/compat.h>
#include <asm/debug-monitors.h>
#include <asm/pgtable.h>
+#include <asm/syscall.h>
#include <asm/traps.h>
#include <asm/system_misc.h>
@@ -1113,11 +1115,20 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, regs->syscallno);
+#ifdef CONFIG_AUDITSYSCALL
+ audit_syscall_entry(syscall_get_arch(), regs->syscallno,
+ regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]);
+#endif
+
return regs->syscallno;
}
asmlinkage void syscall_trace_exit(struct pt_regs *regs)
{
+#ifdef CONFIG_AUDITSYSCALL
+ audit_syscall_exit(regs);
+#endif
+
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_exit(regs, regs_return_value(regs));
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 46d1125571f6..f6f0ccf35ae6 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -45,6 +45,7 @@
#include <linux/efi.h>
#include <asm/fixmap.h>
+#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/elf.h>
#include <asm/cputable.h>
@@ -77,7 +78,6 @@ unsigned int compat_elf_hwcap2 __read_mostly;
#endif
static const char *cpu_name;
-static const char *machine_name;
phys_addr_t __fdt_pointer __initdata;
/*
@@ -219,6 +219,8 @@ static void __init setup_processor(void)
sprintf(init_utsname()->machine, ELF_PLATFORM);
elf_hwcap = 0;
+ cpuinfo_store_boot_cpu();
+
/*
* Check for sane CTR_EL0.CWG value.
*/
@@ -307,8 +309,6 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
while (true)
cpu_relax();
}
-
- machine_name = of_flat_dt_get_machine_name();
}
/*
@@ -417,14 +417,12 @@ static int __init arm64_device_init(void)
}
arch_initcall_sync(arm64_device_init);
-static DEFINE_PER_CPU(struct cpu, cpu_data);
-
static int __init topology_init(void)
{
int i;
for_each_possible_cpu(i) {
- struct cpu *cpu = &per_cpu(cpu_data, i);
+ struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
cpu->hotpluggable = 1;
register_cpu(cpu, i);
}
@@ -449,10 +447,21 @@ static int c_show(struct seq_file *m, void *v)
{
int i;
- seq_printf(m, "Processor\t: %s rev %d (%s)\n",
- cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
+ /*
+ * Dump out the common processor features in a single line. Userspace
+ * should read the hwcaps with getauxval(AT_HWCAP) rather than
+ * attempting to parse this.
+ */
+ seq_puts(m, "features\t:");
+ for (i = 0; hwcap_str[i]; i++)
+ if (elf_hwcap & (1 << i))
+ seq_printf(m, " %s", hwcap_str[i]);
+ seq_puts(m, "\n\n");
for_each_online_cpu(i) {
+ struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
+ u32 midr = cpuinfo->reg_midr;
+
/*
* glibc reads /proc/cpuinfo to determine the number of
* online processors, looking for lines beginning with
@@ -461,25 +470,13 @@ static int c_show(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
seq_printf(m, "processor\t: %d\n", i);
#endif
+ seq_printf(m, "implementer\t: 0x%02x\n",
+ MIDR_IMPLEMENTOR(midr));
+ seq_printf(m, "variant\t\t: 0x%x\n", MIDR_VARIANT(midr));
+ seq_printf(m, "partnum\t\t: 0x%03x\n", MIDR_PARTNUM(midr));
+ seq_printf(m, "revision\t: 0x%x\n\n", MIDR_REVISION(midr));
}
- /* dump out the processor features */
- seq_puts(m, "Features\t: ");
-
- for (i = 0; hwcap_str[i]; i++)
- if (elf_hwcap & (1 << i))
- seq_printf(m, "%s ", hwcap_str[i]);
-
- seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
- seq_printf(m, "CPU architecture: AArch64\n");
- seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
- seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
- seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
-
- seq_puts(m, "\n");
-
- seq_printf(m, "Hardware\t: %s\n", machine_name);
-
return 0;
}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 6357b9c6c90e..6fa792137eda 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
return err;
}
-static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka,
+static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs)
{
unsigned long sp, sp_top;
struct rt_sigframe __user *frame;
- sp = sp_top = regs->sp;
-
- /*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
+ sp = sp_top = sigsp(regs->sp, ksig);
sp = (sp - sizeof(struct rt_sigframe)) & ~15;
frame = (struct rt_sigframe __user *)sp;
@@ -253,13 +247,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->regs[30] = (unsigned long)sigtramp;
}
-static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs);
+ frame = get_sigframe(ksig, regs);
if (!frame)
return 1;
@@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(frame, regs, set);
if (err == 0) {
- setup_return(regs, ka, frame, usig);
- if (ka->sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, info);
+ setup_return(regs, &ksig->ka, frame, usig);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
regs->regs[2] = (unsigned long)&frame->uc;
}
@@ -291,13 +285,12 @@ static void setup_restart_syscall(struct pt_regs *regs)
/*
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save();
- int usig = sig;
+ int usig = ksig->sig;
int ret;
/*
@@ -310,13 +303,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
* Set up the stack frame
*/
if (is_compat_task()) {
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = compat_setup_rt_frame(usig, ka, info, oldset,
- regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
else
- ret = compat_setup_frame(usig, ka, oldset, regs);
+ ret = compat_setup_frame(usig, ksig, oldset, regs);
} else {
- ret = setup_rt_frame(usig, ka, info, oldset, regs);
+ ret = setup_rt_frame(usig, ksig, oldset, regs);
}
/*
@@ -324,18 +316,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
ret |= !valid_user_regs(&regs->user_regs);
- if (ret != 0) {
- force_sigsegv(sig, tsk);
- return;
- }
-
/*
* Fast forward the stepping logic so we step into the signal
* handler.
*/
- user_fastforward_single_step(tsk);
+ if (!ret)
+ user_fastforward_single_step(tsk);
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -350,10 +338,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
static void do_signal(struct pt_regs *regs)
{
unsigned long continue_addr = 0, restart_addr = 0;
- struct k_sigaction ka;
- siginfo_t info;
- int signr, retval = 0;
+ int retval = 0;
int syscall = (int)regs->syscallno;
+ struct ksignal ksig;
/*
* If we were from a system call, check for system call restarting...
@@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *regs)
* Get the signal to deliver. When running under ptrace, at this point
* the debugger may change all of our registers.
*/
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/*
* Depending on the signal settings, we may need to revert the
* decision to restart the system call, but skip this if a
@@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *regs)
(retval == -ERESTARTNOHAND ||
retval == -ERESTART_RESTARTBLOCK ||
(retval == -ERESTARTSYS &&
- !(ka.sa.sa_flags & SA_RESTART)))) {
+ !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
regs->regs[0] = -EINTR;
regs->pc = continue_addr;
}
- handle_signal(signr, &ka, &info, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 3491c638f172..1b9ad02837cf 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -27,7 +27,7 @@
#include <asm/fpsimd.h>
#include <asm/signal32.h>
#include <asm/uaccess.h>
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
struct compat_sigcontext {
/* We always set these two fields to 0 */
@@ -407,20 +407,14 @@ badframe:
return 0;
}
-static void __user *compat_get_sigframe(struct k_sigaction *ka,
+static void __user *compat_get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
int framesize)
{
- compat_ulong_t sp = regs->compat_sp;
+ compat_ulong_t sp = sigsp(regs->compat_sp, ksig);
void __user *frame;
/*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- /*
* ATPCS B01 mandates 8-byte alignment
*/
frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7));
@@ -520,18 +514,18 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,
/*
* 32-bit signal handling routines called from signal.c
*/
-int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+int compat_setup_rt_frame(int usig, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
struct compat_rt_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame)
return 1;
- err |= copy_siginfo_to_user32(&frame->info, info);
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
__put_user_error(0, &frame->sig.uc.uc_flags, err);
__put_user_error(0, &frame->sig.uc.uc_link, err);
@@ -541,7 +535,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= compat_setup_sigframe(&frame->sig, regs, set);
if (err == 0) {
- compat_setup_return(regs, ka, frame->sig.retcode, frame, usig);
+ compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
}
@@ -549,13 +543,13 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
return err;
}
-int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
struct compat_sigframe __user *frame;
int err = 0;
- frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame)
return 1;
@@ -564,7 +558,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
err |= compat_setup_sigframe(frame, regs, set);
if (err == 0)
- compat_setup_return(regs, ka, frame->retcode, frame, usig);
+ compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
return err;
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 40f38f46c8e0..474339718105 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -39,6 +39,7 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
+#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/cpu_ops.h>
#include <asm/mmu_context.h>
@@ -50,6 +51,9 @@
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/ipi.h>
+
/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
@@ -155,6 +159,11 @@ asmlinkage void secondary_start_kernel(void)
cpu_ops[cpu]->cpu_postboot();
/*
+ * Log the CPU info before it is marked online and might get read.
+ */
+ cpuinfo_store_cpu();
+
+ /*
* Enable GIC and timers.
*/
notify_cpu_starting(cpu);
@@ -307,8 +316,6 @@ void __init smp_prepare_boot_cpu(void)
set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
}
-static void (*smp_cross_call)(const struct cpumask *, unsigned int);
-
/*
* Enumerate the possible CPU set from the device tree and build the
* cpu logical map array containing MPIDR values related to logical
@@ -463,32 +470,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
+static void (*__smp_cross_call)(const struct cpumask *, unsigned int);
void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
{
- smp_cross_call = fn;
-}
-
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
- smp_cross_call(mask, IPI_CALL_FUNC);
-}
-
-void arch_send_call_function_single_ipi(int cpu)
-{
- smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+ __smp_cross_call = fn;
}
-#ifdef CONFIG_IRQ_WORK
-void arch_irq_work_raise(void)
-{
- if (smp_cross_call)
- smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
-}
-#endif
-
-static const char *ipi_types[NR_IPI] = {
-#define S(x,s) [x - IPI_RESCHEDULE] = s
+static const char *ipi_types[NR_IPI] __tracepoint_string = {
+#define S(x,s) [x] = s
S(IPI_RESCHEDULE, "Rescheduling interrupts"),
S(IPI_CALL_FUNC, "Function call interrupts"),
S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
@@ -497,12 +487,18 @@ static const char *ipi_types[NR_IPI] = {
S(IPI_IRQ_WORK, "IRQ work interrupts"),
};
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
+{
+ trace_ipi_raise(target, ipi_types[ipinr]);
+ __smp_cross_call(target, ipinr);
+}
+
void show_ipi_list(struct seq_file *p, int prec)
{
unsigned int cpu, i;
for (i = 0; i < NR_IPI; i++) {
- seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE,
+ seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
seq_printf(p, "%10u ",
@@ -522,6 +518,24 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
return sum;
}
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+ smp_cross_call(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+ smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+#ifdef CONFIG_IRQ_WORK
+void arch_irq_work_raise(void)
+{
+ if (__smp_cross_call)
+ smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+}
+#endif
+
static DEFINE_RAW_SPINLOCK(stop_lock);
/*
@@ -553,8 +567,10 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
- if (ipinr >= IPI_RESCHEDULE && ipinr < IPI_RESCHEDULE + NR_IPI)
- __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_RESCHEDULE]);
+ if ((unsigned)ipinr < NR_IPI) {
+ trace_ipi_entry(ipi_types[ipinr]);
+ __inc_irq_stat(cpu, ipi_irqs[ipinr]);
+ }
switch (ipinr) {
case IPI_RESCHEDULE:
@@ -599,6 +615,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
break;
}
+
+ if ((unsigned)ipinr < NR_IPI)
+ trace_ipi_exit(ipi_types[ipinr]);
set_irq_regs(old_regs);
}
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 1fa9ce4afd8f..55a99b9a97e0 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -119,7 +119,7 @@ int cpu_suspend(unsigned long arg)
extern struct sleep_save_sp sleep_save_sp;
extern phys_addr_t sleep_idmap_phys;
-static int cpu_suspend_init(void)
+static int __init cpu_suspend_init(void)
{
void *ctx_ptr;
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 26e9c4eeaba8..de2b0226e06d 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -26,7 +26,7 @@
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
-#include <asm/unistd32.h>
+#include <asm/unistd.h>
static inline void
do_compat_cache_op(unsigned long start, unsigned long end, int flags)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 43514f905916..b6ee26b0939a 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -20,6 +20,7 @@
#include <linux/of.h>
#include <linux/sched.h>
+#include <asm/cputype.h>
#include <asm/topology.h>
static int __init get_cpu_for_node(struct device_node *node)
@@ -188,13 +189,9 @@ static int __init parse_dt_topology(void)
* Check that all cores are in the topology; the SMP code will
* only mark cores described in the DT as possible.
*/
- for_each_possible_cpu(cpu) {
- if (cpu_topology[cpu].cluster_id == -1) {
- pr_err("CPU%d: No topology information specified\n",
- cpu);
+ for_each_possible_cpu(cpu)
+ if (cpu_topology[cpu].cluster_id == -1)
ret = -EINVAL;
- }
- }
out_map:
of_node_put(map);
@@ -219,14 +216,6 @@ static void update_siblings_masks(unsigned int cpuid)
struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
int cpu;
- if (cpuid_topo->cluster_id == -1) {
- /*
- * DT does not contain topology information for this cpu.
- */
- pr_debug("CPU%u: No topology information configured\n", cpuid);
- return;
- }
-
/* update core and thread sibling masks */
for_each_possible_cpu(cpu) {
cpu_topo = &cpu_topology[cpu];
@@ -249,6 +238,36 @@ static void update_siblings_masks(unsigned int cpuid)
void store_cpu_topology(unsigned int cpuid)
{
+ struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
+ u64 mpidr;
+
+ if (cpuid_topo->cluster_id != -1)
+ goto topology_populated;
+
+ mpidr = read_cpuid_mpidr();
+
+ /* Uniprocessor systems can rely on default topology values */
+ if (mpidr & MPIDR_UP_BITMASK)
+ return;
+
+ /* Create cpu topology mapping based on MPIDR. */
+ if (mpidr & MPIDR_MT_BITMASK) {
+ /* Multiprocessor system : Multi-threads per core */
+ cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
+ } else {
+ /* Multiprocessor system : Single-thread per core */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+ cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ }
+
+ pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
+ cpuid, cpuid_topo->cluster_id, cpuid_topo->core_id,
+ cpuid_topo->thread_id, mpidr);
+
+topology_populated:
update_siblings_masks(cpuid);
}
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index c43cfa9b8304..02cd3f023e9a 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -156,7 +156,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
frame.pc = thread_saved_pc(tsk);
}
- printk("Call trace:\n");
+ pr_emerg("Call trace:\n");
while (1) {
unsigned long where = frame.pc;
int ret;
@@ -331,17 +331,22 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
void __pte_error(const char *file, int line, unsigned long val)
{
- printk("%s:%d: bad pte %016lx.\n", file, line, val);
+ pr_crit("%s:%d: bad pte %016lx.\n", file, line, val);
}
void __pmd_error(const char *file, int line, unsigned long val)
{
- printk("%s:%d: bad pmd %016lx.\n", file, line, val);
+ pr_crit("%s:%d: bad pmd %016lx.\n", file, line, val);
+}
+
+void __pud_error(const char *file, int line, unsigned long val)
+{
+ pr_crit("%s:%d: bad pud %016lx.\n", file, line, val);
}
void __pgd_error(const char *file, int line, unsigned long val)
{
- printk("%s:%d: bad pgd %016lx.\n", file, line, val);
+ pr_crit("%s:%d: bad pgd %016lx.\n", file, line, val);
}
void __init trap_init(void)
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 50384fec56c4..32aeea083d93 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -88,22 +88,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
{
struct mm_struct *mm = current->mm;
unsigned long addr = AARCH32_VECTORS_BASE;
- int ret;
+ static struct vm_special_mapping spec = {
+ .name = "[vectors]",
+ .pages = vectors_page,
+
+ };
+ void *ret;
down_write(&mm->mmap_sem);
current->mm->context.vdso = (void *)addr;
/* Map vectors page at the high address. */
- ret = install_special_mapping(mm, addr, PAGE_SIZE,
- VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC,
- vectors_page);
+ ret = _install_special_mapping(mm, addr, PAGE_SIZE,
+ VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC,
+ &spec);
up_write(&mm->mmap_sem);
- return ret;
+ return PTR_ERR_OR_ZERO(ret);
}
#endif /* CONFIG_COMPAT */
+static struct vm_special_mapping vdso_spec[2];
+
static int __init vdso_init(void)
{
int i;
@@ -114,8 +121,8 @@ static int __init vdso_init(void)
}
vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
- pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
- vdso_pages + 1, vdso_pages, 1L, &vdso_start);
+ pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+ vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
/* Allocate the vDSO pagelist, plus a page for the data. */
vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
@@ -123,12 +130,23 @@ static int __init vdso_init(void)
if (vdso_pagelist == NULL)
return -ENOMEM;
+ /* Grab the vDSO data page. */
+ vdso_pagelist[0] = virt_to_page(vdso_data);
+
/* Grab the vDSO code pages. */
for (i = 0; i < vdso_pages; i++)
- vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+ vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
- /* Grab the vDSO data page. */
- vdso_pagelist[i] = virt_to_page(vdso_data);
+ /* Populate the special mapping structures */
+ vdso_spec[0] = (struct vm_special_mapping) {
+ .name = "[vvar]",
+ .pages = vdso_pagelist,
+ };
+
+ vdso_spec[1] = (struct vm_special_mapping) {
+ .name = "[vdso]",
+ .pages = &vdso_pagelist[1],
+ };
return 0;
}
@@ -138,71 +156,42 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp)
{
struct mm_struct *mm = current->mm;
- unsigned long vdso_base, vdso_mapping_len;
- int ret;
+ unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
+ void *ret;
+ vdso_text_len = vdso_pages << PAGE_SHIFT;
/* Be sure to map the data page */
- vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+ vdso_mapping_len = vdso_text_len + PAGE_SIZE;
down_write(&mm->mmap_sem);
vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
if (IS_ERR_VALUE(vdso_base)) {
- ret = vdso_base;
+ ret = ERR_PTR(vdso_base);
goto up_fail;
}
- mm->context.vdso = (void *)vdso_base;
-
- ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
- VM_READ|VM_EXEC|
- VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
- vdso_pagelist);
- if (ret) {
- mm->context.vdso = NULL;
+ ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
+ VM_READ|VM_MAYREAD,
+ &vdso_spec[0]);
+ if (IS_ERR(ret))
goto up_fail;
- }
-
-up_fail:
- up_write(&mm->mmap_sem);
-
- return ret;
-}
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
- /*
- * We can re-use the vdso pointer in mm_context_t for identifying
- * the vectors page for compat applications. The vDSO will always
- * sit above TASK_UNMAPPED_BASE and so we don't need to worry about
- * it conflicting with the vectors base.
- */
- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) {
-#ifdef CONFIG_COMPAT
- if (vma->vm_start == AARCH32_VECTORS_BASE)
- return "[vectors]";
-#endif
- return "[vdso]";
- }
- return NULL;
-}
+ vdso_base += PAGE_SIZE;
+ mm->context.vdso = (void *)vdso_base;
+ ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
+ VM_READ|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+ &vdso_spec[1]);
+ if (IS_ERR(ret))
+ goto up_fail;
-/*
- * We define AT_SYSINFO_EHDR, so we need these function stubs to keep
- * Linux happy.
- */
-int in_gate_area_no_mm(unsigned long addr)
-{
- return 0;
-}
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
+ up_write(&mm->mmap_sem);
return 0;
-}
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
+up_fail:
+ mm->context.vdso = NULL;
+ up_write(&mm->mmap_sem);
+ return PTR_ERR(ret);
}
/*
@@ -211,7 +200,7 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
void update_vsyscall(struct timekeeper *tk)
{
struct timespec xtime_coarse;
- u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
+ u32 use_syscall = strcmp(tk->tkr.clock->name, "arch_sys_counter");
++vdso_data->tb_seq_count;
smp_wmb();
@@ -224,11 +213,11 @@ void update_vsyscall(struct timekeeper *tk)
vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
if (!use_syscall) {
- vdso_data->cs_cycle_last = tk->clock->cycle_last;
+ vdso_data->cs_cycle_last = tk->tkr.cycle_last;
vdso_data->xtime_clock_sec = tk->xtime_sec;
- vdso_data->xtime_clock_nsec = tk->xtime_nsec;
- vdso_data->cs_mult = tk->mult;
- vdso_data->cs_shift = tk->shift;
+ vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
+ vdso_data->cs_mult = tk->tkr.mult;
+ vdso_data->cs_shift = tk->tkr.shift;
}
smp_wmb();
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 6d20b7d162d8..ff3bddea482d 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -43,13 +43,13 @@ $(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
$(call if_changed,vdsosym)
# Assembly rules for the .S files
-$(obj-vdso): %.o: %.S
+$(obj-vdso): %.o: %.S FORCE
$(call if_changed_dep,vdsoas)
# Actual build commands
-quiet_cmd_vdsold = VDSOL $@
+quiet_cmd_vdsold = VDSOL $@
cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
-quiet_cmd_vdsoas = VDSOA $@
+quiet_cmd_vdsoas = VDSOA $@
cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
# Install commands for the unstripped file
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
index 8154b8d1c826..beca249bc2f3 100644
--- a/arch/arm64/kernel/vdso/vdso.lds.S
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -28,6 +28,7 @@ OUTPUT_ARCH(aarch64)
SECTIONS
{
+ PROVIDE(_vdso_data = . - PAGE_SIZE);
. = VDSO_LBASE + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
@@ -57,9 +58,6 @@ SECTIONS
_end = .;
PROVIDE(end = .);
- . = ALIGN(PAGE_SIZE);
- PROVIDE(_vdso_data = .);
-
/DISCARD/ : {
*(.note.GNU-stack)
*(.data .data.* .gnu.linkonce.d.* .sdata*)
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index f1e6d5c032e1..97f0c0429dfa 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -9,6 +9,8 @@
#include <asm/memory.h>
#include <asm/page.h>
+#include "image.h"
+
#define ARM_EXIT_KEEP(x)
#define ARM_EXIT_DISCARD(x) x
@@ -104,9 +106,18 @@ SECTIONS
_edata = .;
BSS_SECTION(0, 0, 0)
+
+ . = ALIGN(PAGE_SIZE);
+ idmap_pg_dir = .;
+ . += IDMAP_DIR_SIZE;
+ swapper_pg_dir = .;
+ . += SWAPPER_DIR_SIZE;
+
_end = .;
STABS_DEBUG
+
+ HEAD_SYMBOLS
}
/*
@@ -114,3 +125,8 @@ SECTIONS
*/
ASSERT(((__hyp_idmap_text_start + PAGE_SIZE) > __hyp_idmap_text_end),
"HYP init code too big")
+
+/*
+ * If padding is applied before .head.text, virt<->phys conversions will fail.
+ */
+ASSERT(_text == (PAGE_OFFSET + TEXT_OFFSET), "HEAD is misaligned")
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 72a9fd583ad3..32a096174b94 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,4 +20,8 @@ kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 60b5c31f3c10..8d1ec2887a26 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -136,13 +136,67 @@ static unsigned long num_core_regs(void)
}
/**
+ * ARM64 versions of the TIMER registers, always available on arm64
+ */
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+ switch (index) {
+ case KVM_REG_ARM_TIMER_CTL:
+ case KVM_REG_ARM_TIMER_CNT:
+ case KVM_REG_ARM_TIMER_CVAL:
+ return true;
+ }
+ return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+ if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+ return -EFAULT;
+ uindices++;
+ if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+ return -EFAULT;
+ uindices++;
+ if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ void __user *uaddr = (void __user *)(long)reg->addr;
+ u64 val;
+ int ret;
+
+ ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id));
+ if (ret != 0)
+ return ret;
+
+ return kvm_arm_timer_set_reg(vcpu, reg->id, val);
+}
+
+static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ void __user *uaddr = (void __user *)(long)reg->addr;
+ u64 val;
+
+ val = kvm_arm_timer_get_reg(vcpu, reg->id);
+ return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+}
+
+/**
* kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
*
* This is for all registers.
*/
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
{
- return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu);
+ return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
+ + NUM_TIMER_REGS;
}
/**
@@ -154,6 +208,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
{
unsigned int i;
const u64 core_reg = KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE;
+ int ret;
for (i = 0; i < sizeof(struct kvm_regs) / sizeof(__u32); i++) {
if (put_user(core_reg | i, uindices))
@@ -161,6 +216,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
uindices++;
}
+ ret = copy_timer_indices(vcpu, uindices);
+ if (ret)
+ return ret;
+ uindices += NUM_TIMER_REGS;
+
return kvm_arm_copy_sys_reg_indices(vcpu, uindices);
}
@@ -174,6 +234,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
return get_core_reg(vcpu, reg);
+ if (is_timer_reg(reg->id))
+ return get_timer_reg(vcpu, reg);
+
return kvm_arm_sys_reg_get_reg(vcpu, reg);
}
@@ -187,6 +250,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
return set_core_reg(vcpu, reg);
+ if (is_timer_reg(reg->id))
+ return set_timer_reg(vcpu, reg);
+
return kvm_arm_sys_reg_set_reg(vcpu, reg);
}
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 182415e1a952..e28be510380c 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -73,9 +73,9 @@ static exit_handle_fn arm_exit_handlers[] = {
[ESR_EL2_EC_WFI] = kvm_handle_wfx,
[ESR_EL2_EC_CP15_32] = kvm_handle_cp15_32,
[ESR_EL2_EC_CP15_64] = kvm_handle_cp15_64,
- [ESR_EL2_EC_CP14_MR] = kvm_handle_cp14_access,
+ [ESR_EL2_EC_CP14_MR] = kvm_handle_cp14_32,
[ESR_EL2_EC_CP14_LS] = kvm_handle_cp14_load_store,
- [ESR_EL2_EC_CP14_64] = kvm_handle_cp14_access,
+ [ESR_EL2_EC_CP14_64] = kvm_handle_cp14_64,
[ESR_EL2_EC_HVC32] = handle_hvc,
[ESR_EL2_EC_SMC32] = handle_smc,
[ESR_EL2_EC_HVC64] = handle_hvc,
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index b0d1512acf08..b72aa9f9215c 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -16,11 +16,11 @@
*/
#include <linux/linkage.h>
-#include <linux/irqchip/arm-gic.h>
#include <asm/assembler.h>
#include <asm/memory.h>
#include <asm/asm-offsets.h>
+#include <asm/debug-monitors.h>
#include <asm/fpsimdmacros.h>
#include <asm/kvm.h>
#include <asm/kvm_asm.h>
@@ -36,9 +36,6 @@
.pushsection .hyp.text, "ax"
.align PAGE_SHIFT
-__kvm_hyp_code_start:
- .globl __kvm_hyp_code_start
-
.macro save_common_regs
// x2: base address for cpu context
// x3: tmp register
@@ -215,6 +212,7 @@ __kvm_hyp_code_start:
mrs x22, amair_el1
mrs x23, cntkctl_el1
mrs x24, par_el1
+ mrs x25, mdscr_el1
stp x4, x5, [x3]
stp x6, x7, [x3, #16]
@@ -226,7 +224,202 @@ __kvm_hyp_code_start:
stp x18, x19, [x3, #112]
stp x20, x21, [x3, #128]
stp x22, x23, [x3, #144]
- str x24, [x3, #160]
+ stp x24, x25, [x3, #160]
+.endm
+
+.macro save_debug
+ // x2: base address for cpu context
+ // x3: tmp register
+
+ mrs x26, id_aa64dfr0_el1
+ ubfx x24, x26, #12, #4 // Extract BRPs
+ ubfx x25, x26, #20, #4 // Extract WRPs
+ mov w26, #15
+ sub w24, w26, w24 // How many BPs to skip
+ sub w25, w26, w25 // How many WPs to skip
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ mrs x20, dbgbcr15_el1
+ mrs x19, dbgbcr14_el1
+ mrs x18, dbgbcr13_el1
+ mrs x17, dbgbcr12_el1
+ mrs x16, dbgbcr11_el1
+ mrs x15, dbgbcr10_el1
+ mrs x14, dbgbcr9_el1
+ mrs x13, dbgbcr8_el1
+ mrs x12, dbgbcr7_el1
+ mrs x11, dbgbcr6_el1
+ mrs x10, dbgbcr5_el1
+ mrs x9, dbgbcr4_el1
+ mrs x8, dbgbcr3_el1
+ mrs x7, dbgbcr2_el1
+ mrs x6, dbgbcr1_el1
+ mrs x5, dbgbcr0_el1
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+
+1:
+ str x20, [x3, #(15 * 8)]
+ str x19, [x3, #(14 * 8)]
+ str x18, [x3, #(13 * 8)]
+ str x17, [x3, #(12 * 8)]
+ str x16, [x3, #(11 * 8)]
+ str x15, [x3, #(10 * 8)]
+ str x14, [x3, #(9 * 8)]
+ str x13, [x3, #(8 * 8)]
+ str x12, [x3, #(7 * 8)]
+ str x11, [x3, #(6 * 8)]
+ str x10, [x3, #(5 * 8)]
+ str x9, [x3, #(4 * 8)]
+ str x8, [x3, #(3 * 8)]
+ str x7, [x3, #(2 * 8)]
+ str x6, [x3, #(1 * 8)]
+ str x5, [x3, #(0 * 8)]
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ mrs x20, dbgbvr15_el1
+ mrs x19, dbgbvr14_el1
+ mrs x18, dbgbvr13_el1
+ mrs x17, dbgbvr12_el1
+ mrs x16, dbgbvr11_el1
+ mrs x15, dbgbvr10_el1
+ mrs x14, dbgbvr9_el1
+ mrs x13, dbgbvr8_el1
+ mrs x12, dbgbvr7_el1
+ mrs x11, dbgbvr6_el1
+ mrs x10, dbgbvr5_el1
+ mrs x9, dbgbvr4_el1
+ mrs x8, dbgbvr3_el1
+ mrs x7, dbgbvr2_el1
+ mrs x6, dbgbvr1_el1
+ mrs x5, dbgbvr0_el1
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+
+1:
+ str x20, [x3, #(15 * 8)]
+ str x19, [x3, #(14 * 8)]
+ str x18, [x3, #(13 * 8)]
+ str x17, [x3, #(12 * 8)]
+ str x16, [x3, #(11 * 8)]
+ str x15, [x3, #(10 * 8)]
+ str x14, [x3, #(9 * 8)]
+ str x13, [x3, #(8 * 8)]
+ str x12, [x3, #(7 * 8)]
+ str x11, [x3, #(6 * 8)]
+ str x10, [x3, #(5 * 8)]
+ str x9, [x3, #(4 * 8)]
+ str x8, [x3, #(3 * 8)]
+ str x7, [x3, #(2 * 8)]
+ str x6, [x3, #(1 * 8)]
+ str x5, [x3, #(0 * 8)]
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ mrs x20, dbgwcr15_el1
+ mrs x19, dbgwcr14_el1
+ mrs x18, dbgwcr13_el1
+ mrs x17, dbgwcr12_el1
+ mrs x16, dbgwcr11_el1
+ mrs x15, dbgwcr10_el1
+ mrs x14, dbgwcr9_el1
+ mrs x13, dbgwcr8_el1
+ mrs x12, dbgwcr7_el1
+ mrs x11, dbgwcr6_el1
+ mrs x10, dbgwcr5_el1
+ mrs x9, dbgwcr4_el1
+ mrs x8, dbgwcr3_el1
+ mrs x7, dbgwcr2_el1
+ mrs x6, dbgwcr1_el1
+ mrs x5, dbgwcr0_el1
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+
+1:
+ str x20, [x3, #(15 * 8)]
+ str x19, [x3, #(14 * 8)]
+ str x18, [x3, #(13 * 8)]
+ str x17, [x3, #(12 * 8)]
+ str x16, [x3, #(11 * 8)]
+ str x15, [x3, #(10 * 8)]
+ str x14, [x3, #(9 * 8)]
+ str x13, [x3, #(8 * 8)]
+ str x12, [x3, #(7 * 8)]
+ str x11, [x3, #(6 * 8)]
+ str x10, [x3, #(5 * 8)]
+ str x9, [x3, #(4 * 8)]
+ str x8, [x3, #(3 * 8)]
+ str x7, [x3, #(2 * 8)]
+ str x6, [x3, #(1 * 8)]
+ str x5, [x3, #(0 * 8)]
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ mrs x20, dbgwvr15_el1
+ mrs x19, dbgwvr14_el1
+ mrs x18, dbgwvr13_el1
+ mrs x17, dbgwvr12_el1
+ mrs x16, dbgwvr11_el1
+ mrs x15, dbgwvr10_el1
+ mrs x14, dbgwvr9_el1
+ mrs x13, dbgwvr8_el1
+ mrs x12, dbgwvr7_el1
+ mrs x11, dbgwvr6_el1
+ mrs x10, dbgwvr5_el1
+ mrs x9, dbgwvr4_el1
+ mrs x8, dbgwvr3_el1
+ mrs x7, dbgwvr2_el1
+ mrs x6, dbgwvr1_el1
+ mrs x5, dbgwvr0_el1
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+
+1:
+ str x20, [x3, #(15 * 8)]
+ str x19, [x3, #(14 * 8)]
+ str x18, [x3, #(13 * 8)]
+ str x17, [x3, #(12 * 8)]
+ str x16, [x3, #(11 * 8)]
+ str x15, [x3, #(10 * 8)]
+ str x14, [x3, #(9 * 8)]
+ str x13, [x3, #(8 * 8)]
+ str x12, [x3, #(7 * 8)]
+ str x11, [x3, #(6 * 8)]
+ str x10, [x3, #(5 * 8)]
+ str x9, [x3, #(4 * 8)]
+ str x8, [x3, #(3 * 8)]
+ str x7, [x3, #(2 * 8)]
+ str x6, [x3, #(1 * 8)]
+ str x5, [x3, #(0 * 8)]
+
+ mrs x21, mdccint_el1
+ str x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
.endm
.macro restore_sysregs
@@ -245,7 +438,7 @@ __kvm_hyp_code_start:
ldp x18, x19, [x3, #112]
ldp x20, x21, [x3, #128]
ldp x22, x23, [x3, #144]
- ldr x24, [x3, #160]
+ ldp x24, x25, [x3, #160]
msr vmpidr_el2, x4
msr csselr_el1, x5
@@ -268,6 +461,198 @@ __kvm_hyp_code_start:
msr amair_el1, x22
msr cntkctl_el1, x23
msr par_el1, x24
+ msr mdscr_el1, x25
+.endm
+
+.macro restore_debug
+ // x2: base address for cpu context
+ // x3: tmp register
+
+ mrs x26, id_aa64dfr0_el1
+ ubfx x24, x26, #12, #4 // Extract BRPs
+ ubfx x25, x26, #20, #4 // Extract WRPs
+ mov w26, #15
+ sub w24, w26, w24 // How many BPs to skip
+ sub w25, w26, w25 // How many WPs to skip
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ ldr x20, [x3, #(15 * 8)]
+ ldr x19, [x3, #(14 * 8)]
+ ldr x18, [x3, #(13 * 8)]
+ ldr x17, [x3, #(12 * 8)]
+ ldr x16, [x3, #(11 * 8)]
+ ldr x15, [x3, #(10 * 8)]
+ ldr x14, [x3, #(9 * 8)]
+ ldr x13, [x3, #(8 * 8)]
+ ldr x12, [x3, #(7 * 8)]
+ ldr x11, [x3, #(6 * 8)]
+ ldr x10, [x3, #(5 * 8)]
+ ldr x9, [x3, #(4 * 8)]
+ ldr x8, [x3, #(3 * 8)]
+ ldr x7, [x3, #(2 * 8)]
+ ldr x6, [x3, #(1 * 8)]
+ ldr x5, [x3, #(0 * 8)]
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ msr dbgbcr15_el1, x20
+ msr dbgbcr14_el1, x19
+ msr dbgbcr13_el1, x18
+ msr dbgbcr12_el1, x17
+ msr dbgbcr11_el1, x16
+ msr dbgbcr10_el1, x15
+ msr dbgbcr9_el1, x14
+ msr dbgbcr8_el1, x13
+ msr dbgbcr7_el1, x12
+ msr dbgbcr6_el1, x11
+ msr dbgbcr5_el1, x10
+ msr dbgbcr4_el1, x9
+ msr dbgbcr3_el1, x8
+ msr dbgbcr2_el1, x7
+ msr dbgbcr1_el1, x6
+ msr dbgbcr0_el1, x5
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ ldr x20, [x3, #(15 * 8)]
+ ldr x19, [x3, #(14 * 8)]
+ ldr x18, [x3, #(13 * 8)]
+ ldr x17, [x3, #(12 * 8)]
+ ldr x16, [x3, #(11 * 8)]
+ ldr x15, [x3, #(10 * 8)]
+ ldr x14, [x3, #(9 * 8)]
+ ldr x13, [x3, #(8 * 8)]
+ ldr x12, [x3, #(7 * 8)]
+ ldr x11, [x3, #(6 * 8)]
+ ldr x10, [x3, #(5 * 8)]
+ ldr x9, [x3, #(4 * 8)]
+ ldr x8, [x3, #(3 * 8)]
+ ldr x7, [x3, #(2 * 8)]
+ ldr x6, [x3, #(1 * 8)]
+ ldr x5, [x3, #(0 * 8)]
+
+ adr x26, 1f
+ add x26, x26, x24, lsl #2
+ br x26
+1:
+ msr dbgbvr15_el1, x20
+ msr dbgbvr14_el1, x19
+ msr dbgbvr13_el1, x18
+ msr dbgbvr12_el1, x17
+ msr dbgbvr11_el1, x16
+ msr dbgbvr10_el1, x15
+ msr dbgbvr9_el1, x14
+ msr dbgbvr8_el1, x13
+ msr dbgbvr7_el1, x12
+ msr dbgbvr6_el1, x11
+ msr dbgbvr5_el1, x10
+ msr dbgbvr4_el1, x9
+ msr dbgbvr3_el1, x8
+ msr dbgbvr2_el1, x7
+ msr dbgbvr1_el1, x6
+ msr dbgbvr0_el1, x5
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ ldr x20, [x3, #(15 * 8)]
+ ldr x19, [x3, #(14 * 8)]
+ ldr x18, [x3, #(13 * 8)]
+ ldr x17, [x3, #(12 * 8)]
+ ldr x16, [x3, #(11 * 8)]
+ ldr x15, [x3, #(10 * 8)]
+ ldr x14, [x3, #(9 * 8)]
+ ldr x13, [x3, #(8 * 8)]
+ ldr x12, [x3, #(7 * 8)]
+ ldr x11, [x3, #(6 * 8)]
+ ldr x10, [x3, #(5 * 8)]
+ ldr x9, [x3, #(4 * 8)]
+ ldr x8, [x3, #(3 * 8)]
+ ldr x7, [x3, #(2 * 8)]
+ ldr x6, [x3, #(1 * 8)]
+ ldr x5, [x3, #(0 * 8)]
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ msr dbgwcr15_el1, x20
+ msr dbgwcr14_el1, x19
+ msr dbgwcr13_el1, x18
+ msr dbgwcr12_el1, x17
+ msr dbgwcr11_el1, x16
+ msr dbgwcr10_el1, x15
+ msr dbgwcr9_el1, x14
+ msr dbgwcr8_el1, x13
+ msr dbgwcr7_el1, x12
+ msr dbgwcr6_el1, x11
+ msr dbgwcr5_el1, x10
+ msr dbgwcr4_el1, x9
+ msr dbgwcr3_el1, x8
+ msr dbgwcr2_el1, x7
+ msr dbgwcr1_el1, x6
+ msr dbgwcr0_el1, x5
+
+ add x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ ldr x20, [x3, #(15 * 8)]
+ ldr x19, [x3, #(14 * 8)]
+ ldr x18, [x3, #(13 * 8)]
+ ldr x17, [x3, #(12 * 8)]
+ ldr x16, [x3, #(11 * 8)]
+ ldr x15, [x3, #(10 * 8)]
+ ldr x14, [x3, #(9 * 8)]
+ ldr x13, [x3, #(8 * 8)]
+ ldr x12, [x3, #(7 * 8)]
+ ldr x11, [x3, #(6 * 8)]
+ ldr x10, [x3, #(5 * 8)]
+ ldr x9, [x3, #(4 * 8)]
+ ldr x8, [x3, #(3 * 8)]
+ ldr x7, [x3, #(2 * 8)]
+ ldr x6, [x3, #(1 * 8)]
+ ldr x5, [x3, #(0 * 8)]
+
+ adr x26, 1f
+ add x26, x26, x25, lsl #2
+ br x26
+1:
+ msr dbgwvr15_el1, x20
+ msr dbgwvr14_el1, x19
+ msr dbgwvr13_el1, x18
+ msr dbgwvr12_el1, x17
+ msr dbgwvr11_el1, x16
+ msr dbgwvr10_el1, x15
+ msr dbgwvr9_el1, x14
+ msr dbgwvr8_el1, x13
+ msr dbgwvr7_el1, x12
+ msr dbgwvr6_el1, x11
+ msr dbgwvr5_el1, x10
+ msr dbgwvr4_el1, x9
+ msr dbgwvr3_el1, x8
+ msr dbgwvr2_el1, x7
+ msr dbgwvr1_el1, x6
+ msr dbgwvr0_el1, x5
+
+ ldr x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
+ msr mdccint_el1, x21
.endm
.macro skip_32bit_state tmp, target
@@ -282,6 +667,35 @@ __kvm_hyp_code_start:
tbz \tmp, #12, \target
.endm
+.macro skip_debug_state tmp, target
+ ldr \tmp, [x0, #VCPU_DEBUG_FLAGS]
+ tbz \tmp, #KVM_ARM64_DEBUG_DIRTY_SHIFT, \target
+.endm
+
+.macro compute_debug_state target
+ // Compute debug state: If any of KDE, MDE or KVM_ARM64_DEBUG_DIRTY
+ // is set, we do a full save/restore cycle and disable trapping.
+ add x25, x0, #VCPU_CONTEXT
+
+ // Check the state of MDSCR_EL1
+ ldr x25, [x25, #CPU_SYSREG_OFFSET(MDSCR_EL1)]
+ and x26, x25, #DBG_MDSCR_KDE
+ and x25, x25, #DBG_MDSCR_MDE
+ adds xzr, x25, x26
+ b.eq 9998f // Nothing to see there
+
+ // If any interesting bits was set, we must set the flag
+ mov x26, #KVM_ARM64_DEBUG_DIRTY
+ str x26, [x0, #VCPU_DEBUG_FLAGS]
+ b 9999f // Don't skip restore
+
+9998:
+ // Otherwise load the flags from memory in case we recently
+ // trapped
+ skip_debug_state x25, \target
+9999:
+.endm
+
.macro save_guest_32bit_state
skip_32bit_state x3, 1f
@@ -297,10 +711,13 @@ __kvm_hyp_code_start:
mrs x4, dacr32_el2
mrs x5, ifsr32_el2
mrs x6, fpexc32_el2
- mrs x7, dbgvcr32_el2
stp x4, x5, [x3]
- stp x6, x7, [x3, #16]
+ str x6, [x3, #16]
+ skip_debug_state x8, 2f
+ mrs x7, dbgvcr32_el2
+ str x7, [x3, #24]
+2:
skip_tee_state x8, 1f
add x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
@@ -323,12 +740,15 @@ __kvm_hyp_code_start:
add x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
ldp x4, x5, [x3]
- ldp x6, x7, [x3, #16]
+ ldr x6, [x3, #16]
msr dacr32_el2, x4
msr ifsr32_el2, x5
msr fpexc32_el2, x6
- msr dbgvcr32_el2, x7
+ skip_debug_state x8, 2f
+ ldr x7, [x3, #24]
+ msr dbgvcr32_el2, x7
+2:
skip_tee_state x8, 1f
add x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
@@ -339,11 +759,8 @@ __kvm_hyp_code_start:
.endm
.macro activate_traps
- ldr x2, [x0, #VCPU_IRQ_LINES]
- ldr x1, [x0, #VCPU_HCR_EL2]
- orr x2, x2, x1
- msr hcr_el2, x2
-
+ ldr x2, [x0, #VCPU_HCR_EL2]
+ msr hcr_el2, x2
ldr x2, =(CPTR_EL2_TTA)
msr cptr_el2, x2
@@ -353,6 +770,14 @@ __kvm_hyp_code_start:
mrs x2, mdcr_el2
and x2, x2, #MDCR_EL2_HPMN_MASK
orr x2, x2, #(MDCR_EL2_TPM | MDCR_EL2_TPMCR)
+ orr x2, x2, #(MDCR_EL2_TDRA | MDCR_EL2_TDOSA)
+
+ // Check for KVM_ARM64_DEBUG_DIRTY, and set debug to trap
+ // if not dirty.
+ ldr x3, [x0, #VCPU_DEBUG_FLAGS]
+ tbnz x3, #KVM_ARM64_DEBUG_DIRTY_SHIFT, 1f
+ orr x2, x2, #MDCR_EL2_TDA
+1:
msr mdcr_el2, x2
.endm
@@ -379,100 +804,33 @@ __kvm_hyp_code_start:
.endm
/*
- * Save the VGIC CPU state into memory
- * x0: Register pointing to VCPU struct
- * Do not corrupt x1!!!
+ * Call into the vgic backend for state saving
*/
.macro save_vgic_state
- /* Get VGIC VCTRL base into x2 */
- ldr x2, [x0, #VCPU_KVM]
- kern_hyp_va x2
- ldr x2, [x2, #KVM_VGIC_VCTRL]
- kern_hyp_va x2
- cbz x2, 2f // disabled
-
- /* Compute the address of struct vgic_cpu */
- add x3, x0, #VCPU_VGIC_CPU
-
- /* Save all interesting registers */
- ldr w4, [x2, #GICH_HCR]
- ldr w5, [x2, #GICH_VMCR]
- ldr w6, [x2, #GICH_MISR]
- ldr w7, [x2, #GICH_EISR0]
- ldr w8, [x2, #GICH_EISR1]
- ldr w9, [x2, #GICH_ELRSR0]
- ldr w10, [x2, #GICH_ELRSR1]
- ldr w11, [x2, #GICH_APR]
-CPU_BE( rev w4, w4 )
-CPU_BE( rev w5, w5 )
-CPU_BE( rev w6, w6 )
-CPU_BE( rev w7, w7 )
-CPU_BE( rev w8, w8 )
-CPU_BE( rev w9, w9 )
-CPU_BE( rev w10, w10 )
-CPU_BE( rev w11, w11 )
-
- str w4, [x3, #VGIC_CPU_HCR]
- str w5, [x3, #VGIC_CPU_VMCR]
- str w6, [x3, #VGIC_CPU_MISR]
- str w7, [x3, #VGIC_CPU_EISR]
- str w8, [x3, #(VGIC_CPU_EISR + 4)]
- str w9, [x3, #VGIC_CPU_ELRSR]
- str w10, [x3, #(VGIC_CPU_ELRSR + 4)]
- str w11, [x3, #VGIC_CPU_APR]
-
- /* Clear GICH_HCR */
- str wzr, [x2, #GICH_HCR]
-
- /* Save list registers */
- add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
- add x3, x3, #VGIC_CPU_LR
-1: ldr w5, [x2], #4
-CPU_BE( rev w5, w5 )
- str w5, [x3], #4
- sub w4, w4, #1
- cbnz w4, 1b
-2:
+ adr x24, __vgic_sr_vectors
+ ldr x24, [x24, VGIC_SAVE_FN]
+ kern_hyp_va x24
+ blr x24
+ mrs x24, hcr_el2
+ mov x25, #HCR_INT_OVERRIDE
+ neg x25, x25
+ and x24, x24, x25
+ msr hcr_el2, x24
.endm
/*
- * Restore the VGIC CPU state from memory
- * x0: Register pointing to VCPU struct
+ * Call into the vgic backend for state restoring
*/
.macro restore_vgic_state
- /* Get VGIC VCTRL base into x2 */
- ldr x2, [x0, #VCPU_KVM]
- kern_hyp_va x2
- ldr x2, [x2, #KVM_VGIC_VCTRL]
- kern_hyp_va x2
- cbz x2, 2f // disabled
-
- /* Compute the address of struct vgic_cpu */
- add x3, x0, #VCPU_VGIC_CPU
-
- /* We only restore a minimal set of registers */
- ldr w4, [x3, #VGIC_CPU_HCR]
- ldr w5, [x3, #VGIC_CPU_VMCR]
- ldr w6, [x3, #VGIC_CPU_APR]
-CPU_BE( rev w4, w4 )
-CPU_BE( rev w5, w5 )
-CPU_BE( rev w6, w6 )
-
- str w4, [x2, #GICH_HCR]
- str w5, [x2, #GICH_VMCR]
- str w6, [x2, #GICH_APR]
-
- /* Restore list registers */
- add x2, x2, #GICH_LR0
- ldr w4, [x3, #VGIC_CPU_NR_LR]
- add x3, x3, #VGIC_CPU_LR
-1: ldr w5, [x3], #4
-CPU_BE( rev w5, w5 )
- str w5, [x2], #4
- sub w4, w4, #1
- cbnz w4, 1b
-2:
+ mrs x24, hcr_el2
+ ldr x25, [x0, #VCPU_IRQ_LINES]
+ orr x24, x24, #HCR_INT_OVERRIDE
+ orr x24, x24, x25
+ msr hcr_el2, x24
+ adr x24, __vgic_sr_vectors
+ ldr x24, [x24, #VGIC_RESTORE_FN]
+ kern_hyp_va x24
+ blr x24
.endm
.macro save_timer_state
@@ -537,6 +895,14 @@ __restore_sysregs:
restore_sysregs
ret
+__save_debug:
+ save_debug
+ ret
+
+__restore_debug:
+ restore_debug
+ ret
+
__save_fpsimd:
save_fpsimd
ret
@@ -568,6 +934,9 @@ ENTRY(__kvm_vcpu_run)
bl __save_fpsimd
bl __save_sysregs
+ compute_debug_state 1f
+ bl __save_debug
+1:
activate_traps
activate_vm
@@ -579,6 +948,10 @@ ENTRY(__kvm_vcpu_run)
bl __restore_sysregs
bl __restore_fpsimd
+
+ skip_debug_state x3, 1f
+ bl __restore_debug
+1:
restore_guest_32bit_state
restore_guest_regs
@@ -595,6 +968,10 @@ __kvm_vcpu_return:
save_guest_regs
bl __save_fpsimd
bl __save_sysregs
+
+ skip_debug_state x3, 1f
+ bl __save_debug
+1:
save_guest_32bit_state
save_timer_state
@@ -609,6 +986,14 @@ __kvm_vcpu_return:
bl __restore_sysregs
bl __restore_fpsimd
+
+ skip_debug_state x3, 1f
+ // Clear the dirty flag for the next run, as all the state has
+ // already been saved. Note that we nuke the whole 64bit word.
+ // If we ever add more flags, we'll have to be more careful...
+ str xzr, [x0, #VCPU_DEBUG_FLAGS]
+ bl __restore_debug
+1:
restore_host_regs
mov x0, x1
@@ -653,6 +1038,12 @@ ENTRY(__kvm_flush_vm_context)
ret
ENDPROC(__kvm_flush_vm_context)
+ // struct vgic_sr_vectors __vgi_sr_vectors;
+ .align 3
+ENTRY(__vgic_sr_vectors)
+ .skip VGIC_SR_VECTOR_SZ
+ENDPROC(__vgic_sr_vectors)
+
__kvm_hyp_panic:
// Guess the context by looking at VTTBR:
// If zero, then we're already a host.
@@ -830,7 +1221,7 @@ el1_trap:
mrs x2, far_el2
2: mrs x0, tpidr_el2
- str x1, [x0, #VCPU_ESR_EL2]
+ str w1, [x0, #VCPU_ESR_EL2]
str x2, [x0, #VCPU_FAR_EL2]
str x3, [x0, #VCPU_HPFAR_EL2]
@@ -880,7 +1271,4 @@ ENTRY(__kvm_hyp_vector)
ventry el1_error_invalid // Error 32-bit EL1
ENDPROC(__kvm_hyp_vector)
-__kvm_hyp_code_end:
- .globl __kvm_hyp_code_end
-
.popsection
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index c59a1bdab5eb..5805e7c4a4dd 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -30,6 +30,7 @@
#include <asm/kvm_mmu.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
+#include <asm/debug-monitors.h>
#include <trace/events/kvm.h>
#include "sys_regs.h"
@@ -137,10 +138,11 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
if (!p->is_aarch32) {
vcpu_sys_reg(vcpu, r->reg) = val;
} else {
- vcpu_cp15(vcpu, r->reg) = val & 0xffffffffUL;
if (!p->is_32bit)
- vcpu_cp15(vcpu, r->reg + 1) = val >> 32;
+ vcpu_cp15_64_high(vcpu, r->reg) = val >> 32;
+ vcpu_cp15_64_low(vcpu, r->reg) = val & 0xffffffffUL;
}
+
return true;
}
@@ -163,18 +165,9 @@ static bool access_sctlr(struct kvm_vcpu *vcpu,
return true;
}
-/*
- * We could trap ID_DFR0 and tell the guest we don't support performance
- * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was
- * NAKed, so it will read the PMCR anyway.
- *
- * Therefore we tell the guest we have 0 counters. Unfortunately, we
- * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
- * all PM registers, which doesn't crash the guest kernel at least.
- */
-static bool pm_fake(struct kvm_vcpu *vcpu,
- const struct sys_reg_params *p,
- const struct sys_reg_desc *r)
+static bool trap_raz_wi(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
{
if (p->is_write)
return ignore_write(vcpu, p);
@@ -182,6 +175,73 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
return read_zero(vcpu, p);
}
+static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ if (p->is_write) {
+ return ignore_write(vcpu, p);
+ } else {
+ *vcpu_reg(vcpu, p->Rt) = (1 << 3);
+ return true;
+ }
+}
+
+static bool trap_dbgauthstatus_el1(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ if (p->is_write) {
+ return ignore_write(vcpu, p);
+ } else {
+ u32 val;
+ asm volatile("mrs %0, dbgauthstatus_el1" : "=r" (val));
+ *vcpu_reg(vcpu, p->Rt) = val;
+ return true;
+ }
+}
+
+/*
+ * We want to avoid world-switching all the DBG registers all the
+ * time:
+ *
+ * - If we've touched any debug register, it is likely that we're
+ * going to touch more of them. It then makes sense to disable the
+ * traps and start doing the save/restore dance
+ * - If debug is active (DBG_MDSCR_KDE or DBG_MDSCR_MDE set), it is
+ * then mandatory to save/restore the registers, as the guest
+ * depends on them.
+ *
+ * For this, we use a DIRTY bit, indicating the guest has modified the
+ * debug registers, used as follow:
+ *
+ * On guest entry:
+ * - If the dirty bit is set (because we're coming back from trapping),
+ * disable the traps, save host registers, restore guest registers.
+ * - If debug is actively in use (DBG_MDSCR_KDE or DBG_MDSCR_MDE set),
+ * set the dirty bit, disable the traps, save host registers,
+ * restore guest registers.
+ * - Otherwise, enable the traps
+ *
+ * On guest exit:
+ * - If the dirty bit is set, save guest registers, restore host
+ * registers and clear the dirty bit. This ensure that the host can
+ * now use the debug registers.
+ */
+static bool trap_debug_regs(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ if (p->is_write) {
+ vcpu_sys_reg(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+ vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ } else {
+ *vcpu_reg(vcpu, p->Rt) = vcpu_sys_reg(vcpu, r->reg);
+ }
+
+ return true;
+}
+
static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{
u64 amair;
@@ -198,9 +258,39 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
vcpu_sys_reg(vcpu, MPIDR_EL1) = (1UL << 31) | (vcpu->vcpu_id & 0xff);
}
+/* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
+#define DBG_BCR_BVR_WCR_WVR_EL1(n) \
+ /* DBGBVRn_EL1 */ \
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b100), \
+ trap_debug_regs, reset_val, (DBGBVR0_EL1 + (n)), 0 }, \
+ /* DBGBCRn_EL1 */ \
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b101), \
+ trap_debug_regs, reset_val, (DBGBCR0_EL1 + (n)), 0 }, \
+ /* DBGWVRn_EL1 */ \
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b110), \
+ trap_debug_regs, reset_val, (DBGWVR0_EL1 + (n)), 0 }, \
+ /* DBGWCRn_EL1 */ \
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b111), \
+ trap_debug_regs, reset_val, (DBGWCR0_EL1 + (n)), 0 }
+
/*
* Architected system registers.
* Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
+ *
+ * We could trap ID_DFR0 and tell the guest we don't support performance
+ * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was
+ * NAKed, so it will read the PMCR anyway.
+ *
+ * Therefore we tell the guest we have 0 counters. Unfortunately, we
+ * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
+ * all PM registers, which doesn't crash the guest kernel at least.
+ *
+ * Debug handling: We do trap most, if not all debug related system
+ * registers. The implementation is good enough to ensure that a guest
+ * can use these with minimal performance degradation. The drawback is
+ * that we don't implement any of the external debug, none of the
+ * OSlock protocol. This should be revisited if we ever encounter a
+ * more demanding guest...
*/
static const struct sys_reg_desc sys_reg_descs[] = {
/* DC ISW */
@@ -213,12 +303,71 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010),
access_dcsw },
+ DBG_BCR_BVR_WCR_WVR_EL1(0),
+ DBG_BCR_BVR_WCR_WVR_EL1(1),
+ /* MDCCINT_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm(0b0010), Op2(0b000),
+ trap_debug_regs, reset_val, MDCCINT_EL1, 0 },
+ /* MDSCR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0000), CRm(0b0010), Op2(0b010),
+ trap_debug_regs, reset_val, MDSCR_EL1, 0 },
+ DBG_BCR_BVR_WCR_WVR_EL1(2),
+ DBG_BCR_BVR_WCR_WVR_EL1(3),
+ DBG_BCR_BVR_WCR_WVR_EL1(4),
+ DBG_BCR_BVR_WCR_WVR_EL1(5),
+ DBG_BCR_BVR_WCR_WVR_EL1(6),
+ DBG_BCR_BVR_WCR_WVR_EL1(7),
+ DBG_BCR_BVR_WCR_WVR_EL1(8),
+ DBG_BCR_BVR_WCR_WVR_EL1(9),
+ DBG_BCR_BVR_WCR_WVR_EL1(10),
+ DBG_BCR_BVR_WCR_WVR_EL1(11),
+ DBG_BCR_BVR_WCR_WVR_EL1(12),
+ DBG_BCR_BVR_WCR_WVR_EL1(13),
+ DBG_BCR_BVR_WCR_WVR_EL1(14),
+ DBG_BCR_BVR_WCR_WVR_EL1(15),
+
+ /* MDRAR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b000),
+ trap_raz_wi },
+ /* OSLAR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b100),
+ trap_raz_wi },
+ /* OSLSR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0001), Op2(0b100),
+ trap_oslsr_el1 },
+ /* OSDLR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0011), Op2(0b100),
+ trap_raz_wi },
+ /* DBGPRCR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0001), CRm(0b0100), Op2(0b100),
+ trap_raz_wi },
+ /* DBGCLAIMSET_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1000), Op2(0b110),
+ trap_raz_wi },
+ /* DBGCLAIMCLR_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1001), Op2(0b110),
+ trap_raz_wi },
+ /* DBGAUTHSTATUS_EL1 */
+ { Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b110),
+ trap_dbgauthstatus_el1 },
+
/* TEECR32_EL1 */
{ Op0(0b10), Op1(0b010), CRn(0b0000), CRm(0b0000), Op2(0b000),
NULL, reset_val, TEECR32_EL1, 0 },
/* TEEHBR32_EL1 */
{ Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b0000), Op2(0b000),
NULL, reset_val, TEEHBR32_EL1, 0 },
+
+ /* MDCCSR_EL1 */
+ { Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0001), Op2(0b000),
+ trap_raz_wi },
+ /* DBGDTR_EL0 */
+ { Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0100), Op2(0b000),
+ trap_raz_wi },
+ /* DBGDTR[TR]X_EL0 */
+ { Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0101), Op2(0b000),
+ trap_raz_wi },
+
/* DBGVCR32_EL2 */
{ Op0(0b10), Op1(0b100), CRn(0b0000), CRm(0b0111), Op2(0b000),
NULL, reset_val, DBGVCR32_EL2, 0 },
@@ -260,10 +409,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* PMINTENSET_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
- pm_fake },
+ trap_raz_wi },
/* PMINTENCLR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b010),
- pm_fake },
+ trap_raz_wi },
/* MAIR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000),
@@ -292,43 +441,43 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* PMCR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b000),
- pm_fake },
+ trap_raz_wi },
/* PMCNTENSET_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b001),
- pm_fake },
+ trap_raz_wi },
/* PMCNTENCLR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b010),
- pm_fake },
+ trap_raz_wi },
/* PMOVSCLR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b011),
- pm_fake },
+ trap_raz_wi },
/* PMSWINC_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b100),
- pm_fake },
+ trap_raz_wi },
/* PMSELR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b101),
- pm_fake },
+ trap_raz_wi },
/* PMCEID0_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b110),
- pm_fake },
+ trap_raz_wi },
/* PMCEID1_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b111),
- pm_fake },
+ trap_raz_wi },
/* PMCCNTR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b000),
- pm_fake },
+ trap_raz_wi },
/* PMXEVTYPER_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b001),
- pm_fake },
+ trap_raz_wi },
/* PMXEVCNTR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b010),
- pm_fake },
+ trap_raz_wi },
/* PMUSERENR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b000),
- pm_fake },
+ trap_raz_wi },
/* PMOVSSET_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b011),
- pm_fake },
+ trap_raz_wi },
/* TPIDR_EL0 */
{ Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b010),
@@ -348,13 +497,161 @@ static const struct sys_reg_desc sys_reg_descs[] = {
NULL, reset_val, FPEXC32_EL2, 0x70 },
};
+static bool trap_dbgidr(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ if (p->is_write) {
+ return ignore_write(vcpu, p);
+ } else {
+ u64 dfr = read_cpuid(ID_AA64DFR0_EL1);
+ u64 pfr = read_cpuid(ID_AA64PFR0_EL1);
+ u32 el3 = !!((pfr >> 12) & 0xf);
+
+ *vcpu_reg(vcpu, p->Rt) = ((((dfr >> 20) & 0xf) << 28) |
+ (((dfr >> 12) & 0xf) << 24) |
+ (((dfr >> 28) & 0xf) << 20) |
+ (6 << 16) | (el3 << 14) | (el3 << 12));
+ return true;
+ }
+}
+
+static bool trap_debug32(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *p,
+ const struct sys_reg_desc *r)
+{
+ if (p->is_write) {
+ vcpu_cp14(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt);
+ vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ } else {
+ *vcpu_reg(vcpu, p->Rt) = vcpu_cp14(vcpu, r->reg);
+ }
+
+ return true;
+}
+
+#define DBG_BCR_BVR_WCR_WVR(n) \
+ /* DBGBVRn */ \
+ { Op1( 0), CRn( 0), CRm((n)), Op2( 4), trap_debug32, \
+ NULL, (cp14_DBGBVR0 + (n) * 2) }, \
+ /* DBGBCRn */ \
+ { Op1( 0), CRn( 0), CRm((n)), Op2( 5), trap_debug32, \
+ NULL, (cp14_DBGBCR0 + (n) * 2) }, \
+ /* DBGWVRn */ \
+ { Op1( 0), CRn( 0), CRm((n)), Op2( 6), trap_debug32, \
+ NULL, (cp14_DBGWVR0 + (n) * 2) }, \
+ /* DBGWCRn */ \
+ { Op1( 0), CRn( 0), CRm((n)), Op2( 7), trap_debug32, \
+ NULL, (cp14_DBGWCR0 + (n) * 2) }
+
+#define DBGBXVR(n) \
+ { Op1( 0), CRn( 1), CRm((n)), Op2( 1), trap_debug32, \
+ NULL, cp14_DBGBXVR0 + n * 2 }
+
+/*
+ * Trapped cp14 registers. We generally ignore most of the external
+ * debug, on the principle that they don't really make sense to a
+ * guest. Revisit this one day, whould this principle change.
+ */
+static const struct sys_reg_desc cp14_regs[] = {
+ /* DBGIDR */
+ { Op1( 0), CRn( 0), CRm( 0), Op2( 0), trap_dbgidr },
+ /* DBGDTRRXext */
+ { Op1( 0), CRn( 0), CRm( 0), Op2( 2), trap_raz_wi },
+
+ DBG_BCR_BVR_WCR_WVR(0),
+ /* DBGDSCRint */
+ { Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
+ DBG_BCR_BVR_WCR_WVR(1),
+ /* DBGDCCINT */
+ { Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
+ /* DBGDSCRext */
+ { Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
+ DBG_BCR_BVR_WCR_WVR(2),
+ /* DBGDTR[RT]Xint */
+ { Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
+ /* DBGDTR[RT]Xext */
+ { Op1( 0), CRn( 0), CRm( 3), Op2( 2), trap_raz_wi },
+ DBG_BCR_BVR_WCR_WVR(3),
+ DBG_BCR_BVR_WCR_WVR(4),
+ DBG_BCR_BVR_WCR_WVR(5),
+ /* DBGWFAR */
+ { Op1( 0), CRn( 0), CRm( 6), Op2( 0), trap_raz_wi },
+ /* DBGOSECCR */
+ { Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
+ DBG_BCR_BVR_WCR_WVR(6),
+ /* DBGVCR */
+ { Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
+ DBG_BCR_BVR_WCR_WVR(7),
+ DBG_BCR_BVR_WCR_WVR(8),
+ DBG_BCR_BVR_WCR_WVR(9),
+ DBG_BCR_BVR_WCR_WVR(10),
+ DBG_BCR_BVR_WCR_WVR(11),
+ DBG_BCR_BVR_WCR_WVR(12),
+ DBG_BCR_BVR_WCR_WVR(13),
+ DBG_BCR_BVR_WCR_WVR(14),
+ DBG_BCR_BVR_WCR_WVR(15),
+
+ /* DBGDRAR (32bit) */
+ { Op1( 0), CRn( 1), CRm( 0), Op2( 0), trap_raz_wi },
+
+ DBGBXVR(0),
+ /* DBGOSLAR */
+ { Op1( 0), CRn( 1), CRm( 0), Op2( 4), trap_raz_wi },
+ DBGBXVR(1),
+ /* DBGOSLSR */
+ { Op1( 0), CRn( 1), CRm( 1), Op2( 4), trap_oslsr_el1 },
+ DBGBXVR(2),
+ DBGBXVR(3),
+ /* DBGOSDLR */
+ { Op1( 0), CRn( 1), CRm( 3), Op2( 4), trap_raz_wi },
+ DBGBXVR(4),
+ /* DBGPRCR */
+ { Op1( 0), CRn( 1), CRm( 4), Op2( 4), trap_raz_wi },
+ DBGBXVR(5),
+ DBGBXVR(6),
+ DBGBXVR(7),
+ DBGBXVR(8),
+ DBGBXVR(9),
+ DBGBXVR(10),
+ DBGBXVR(11),
+ DBGBXVR(12),
+ DBGBXVR(13),
+ DBGBXVR(14),
+ DBGBXVR(15),
+
+ /* DBGDSAR (32bit) */
+ { Op1( 0), CRn( 2), CRm( 0), Op2( 0), trap_raz_wi },
+
+ /* DBGDEVID2 */
+ { Op1( 0), CRn( 7), CRm( 0), Op2( 7), trap_raz_wi },
+ /* DBGDEVID1 */
+ { Op1( 0), CRn( 7), CRm( 1), Op2( 7), trap_raz_wi },
+ /* DBGDEVID */
+ { Op1( 0), CRn( 7), CRm( 2), Op2( 7), trap_raz_wi },
+ /* DBGCLAIMSET */
+ { Op1( 0), CRn( 7), CRm( 8), Op2( 6), trap_raz_wi },
+ /* DBGCLAIMCLR */
+ { Op1( 0), CRn( 7), CRm( 9), Op2( 6), trap_raz_wi },
+ /* DBGAUTHSTATUS */
+ { Op1( 0), CRn( 7), CRm(14), Op2( 6), trap_dbgauthstatus_el1 },
+};
+
+/* Trapped cp14 64bit registers */
+static const struct sys_reg_desc cp14_64_regs[] = {
+ /* DBGDRAR (64bit) */
+ { Op1( 0), CRm( 1), .access = trap_raz_wi },
+
+ /* DBGDSAR (64bit) */
+ { Op1( 0), CRm( 2), .access = trap_raz_wi },
+};
+
/*
* Trapped cp15 registers. TTBR0/TTBR1 get a double encoding,
* depending on the way they are accessed (as a 32bit or a 64bit
* register).
*/
static const struct sys_reg_desc cp15_regs[] = {
- { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
{ Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR },
{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
{ Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
@@ -374,26 +671,30 @@ static const struct sys_reg_desc cp15_regs[] = {
{ Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw },
{ Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
- { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 3), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 5), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 6), pm_fake },
- { Op1( 0), CRn( 9), CRm(12), Op2( 7), pm_fake },
- { Op1( 0), CRn( 9), CRm(13), Op2( 0), pm_fake },
- { Op1( 0), CRn( 9), CRm(13), Op2( 1), pm_fake },
- { Op1( 0), CRn( 9), CRm(13), Op2( 2), pm_fake },
- { Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake },
- { Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake },
- { Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake },
+ /* PMU */
+ { Op1( 0), CRn( 9), CRm(12), Op2( 0), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 1), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 2), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 3), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 5), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 6), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(12), Op2( 7), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(13), Op2( 0), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(13), Op2( 1), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(13), Op2( 2), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(14), Op2( 0), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(14), Op2( 1), trap_raz_wi },
+ { Op1( 0), CRn( 9), CRm(14), Op2( 2), trap_raz_wi },
{ Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR },
{ Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
{ Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
{ Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
{ Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
+};
+static const struct sys_reg_desc cp15_64_regs[] = {
+ { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
{ Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
};
@@ -454,26 +755,29 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
return 1;
}
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- kvm_inject_undefined(vcpu);
- return 1;
-}
-
-static void emulate_cp15(struct kvm_vcpu *vcpu,
- const struct sys_reg_params *params)
+/*
+ * emulate_cp -- tries to match a sys_reg access in a handling table, and
+ * call the corresponding trap handler.
+ *
+ * @params: pointer to the descriptor of the access
+ * @table: array of trap descriptors
+ * @num: size of the trap descriptor array
+ *
+ * Return 0 if the access has been handled, and -1 if not.
+ */
+static int emulate_cp(struct kvm_vcpu *vcpu,
+ const struct sys_reg_params *params,
+ const struct sys_reg_desc *table,
+ size_t num)
{
- size_t num;
- const struct sys_reg_desc *table, *r;
+ const struct sys_reg_desc *r;
- table = get_target_table(vcpu->arch.target, false, &num);
+ if (!table)
+ return -1; /* Not handled */
- /* Search target-specific then generic table. */
r = find_reg(params, table, num);
- if (!r)
- r = find_reg(params, cp15_regs, ARRAY_SIZE(cp15_regs));
- if (likely(r)) {
+ if (r) {
/*
* Not having an accessor means that we have
* configured a trap that we don't know how to
@@ -485,22 +789,51 @@ static void emulate_cp15(struct kvm_vcpu *vcpu,
if (likely(r->access(vcpu, params, r))) {
/* Skip instruction, since it was emulated */
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
- return;
}
- /* If access function fails, it should complain. */
+
+ /* Handled */
+ return 0;
}
- kvm_err("Unsupported guest CP15 access at: %08lx\n", *vcpu_pc(vcpu));
+ /* Not handled */
+ return -1;
+}
+
+static void unhandled_cp_access(struct kvm_vcpu *vcpu,
+ struct sys_reg_params *params)
+{
+ u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+ int cp;
+
+ switch(hsr_ec) {
+ case ESR_EL2_EC_CP15_32:
+ case ESR_EL2_EC_CP15_64:
+ cp = 15;
+ break;
+ case ESR_EL2_EC_CP14_MR:
+ case ESR_EL2_EC_CP14_64:
+ cp = 14;
+ break;
+ default:
+ WARN_ON((cp = -1));
+ }
+
+ kvm_err("Unsupported guest CP%d access at: %08lx\n",
+ cp, *vcpu_pc(vcpu));
print_sys_reg_instr(params);
kvm_inject_undefined(vcpu);
}
/**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * kvm_handle_cp_64 -- handles a mrrc/mcrr trap on a guest CP15 access
* @vcpu: The VCPU pointer
* @run: The kvm_run struct
*/
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *global,
+ size_t nr_global,
+ const struct sys_reg_desc *target_specific,
+ size_t nr_specific)
{
struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -529,8 +862,14 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
*vcpu_reg(vcpu, params.Rt) = val;
}
- emulate_cp15(vcpu, &params);
+ if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
+ goto out;
+ if (!emulate_cp(vcpu, &params, global, nr_global))
+ goto out;
+ unhandled_cp_access(vcpu, &params);
+
+out:
/* Do the opposite hack for the read side */
if (!params.is_write) {
u64 val = *vcpu_reg(vcpu, params.Rt);
@@ -546,7 +885,11 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
* @vcpu: The VCPU pointer
* @run: The kvm_run struct
*/
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *global,
+ size_t nr_global,
+ const struct sys_reg_desc *target_specific,
+ size_t nr_specific)
{
struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu);
@@ -561,10 +904,51 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
params.Op1 = (hsr >> 14) & 0x7;
params.Op2 = (hsr >> 17) & 0x7;
- emulate_cp15(vcpu, &params);
+ if (!emulate_cp(vcpu, &params, target_specific, nr_specific))
+ return 1;
+ if (!emulate_cp(vcpu, &params, global, nr_global))
+ return 1;
+
+ unhandled_cp_access(vcpu, &params);
return 1;
}
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ const struct sys_reg_desc *target_specific;
+ size_t num;
+
+ target_specific = get_target_table(vcpu->arch.target, false, &num);
+ return kvm_handle_cp_64(vcpu,
+ cp15_64_regs, ARRAY_SIZE(cp15_64_regs),
+ target_specific, num);
+}
+
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ const struct sys_reg_desc *target_specific;
+ size_t num;
+
+ target_specific = get_target_table(vcpu->arch.target, false, &num);
+ return kvm_handle_cp_32(vcpu,
+ cp15_regs, ARRAY_SIZE(cp15_regs),
+ target_specific, num);
+}
+
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ return kvm_handle_cp_64(vcpu,
+ cp14_64_regs, ARRAY_SIZE(cp14_64_regs),
+ NULL, 0);
+}
+
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ return kvm_handle_cp_32(vcpu,
+ cp14_regs, ARRAY_SIZE(cp14_regs),
+ NULL, 0);
+}
+
static int emulate_sys_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_params *params)
{
@@ -776,17 +1160,15 @@ static struct sys_reg_desc invariant_sys_regs[] = {
NULL, get_ctr_el0 },
};
-static int reg_from_user(void *val, const void __user *uaddr, u64 id)
+static int reg_from_user(u64 *val, const void __user *uaddr, u64 id)
{
- /* This Just Works because we are little endian. */
if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
return -EFAULT;
return 0;
}
-static int reg_to_user(void __user *uaddr, const void *val, u64 id)
+static int reg_to_user(void __user *uaddr, const u64 *val, u64 id)
{
- /* This Just Works because we are little endian. */
if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
return -EFAULT;
return 0;
@@ -962,7 +1344,7 @@ static unsigned int num_demux_regs(void)
static int write_demux_regids(u64 __user *uindices)
{
- u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
+ u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
unsigned int i;
val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
@@ -1069,14 +1451,32 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
return write_demux_regids(uindices);
}
+static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 1; i < n; i++) {
+ if (cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
+ kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void kvm_sys_reg_table_init(void)
{
unsigned int i;
struct sys_reg_desc clidr;
/* Make sure tables are unique and in order. */
- for (i = 1; i < ARRAY_SIZE(sys_reg_descs); i++)
- BUG_ON(cmp_sys_reg(&sys_reg_descs[i-1], &sys_reg_descs[i]) >= 0);
+ BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs)));
+ BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs)));
+ BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs)));
+ BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
+ BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs)));
+ BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs)));
/* We abuse the reset function to overwrite the table itself. */
for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
diff --git a/arch/arm64/kvm/vgic-v2-switch.S b/arch/arm64/kvm/vgic-v2-switch.S
new file mode 100644
index 000000000000..ae211772f991
--- /dev/null
+++ b/arch/arm64/kvm/vgic-v2-switch.S
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
+
+ .text
+ .pushsection .hyp.text, "ax"
+
+/*
+ * Save the VGIC CPU state into memory
+ * x0: Register pointing to VCPU struct
+ * Do not corrupt x1!!!
+ */
+ENTRY(__save_vgic_v2_state)
+__save_vgic_v2_state:
+ /* Get VGIC VCTRL base into x2 */
+ ldr x2, [x0, #VCPU_KVM]
+ kern_hyp_va x2
+ ldr x2, [x2, #KVM_VGIC_VCTRL]
+ kern_hyp_va x2
+ cbz x2, 2f // disabled
+
+ /* Compute the address of struct vgic_cpu */
+ add x3, x0, #VCPU_VGIC_CPU
+
+ /* Save all interesting registers */
+ ldr w4, [x2, #GICH_HCR]
+ ldr w5, [x2, #GICH_VMCR]
+ ldr w6, [x2, #GICH_MISR]
+ ldr w7, [x2, #GICH_EISR0]
+ ldr w8, [x2, #GICH_EISR1]
+ ldr w9, [x2, #GICH_ELRSR0]
+ ldr w10, [x2, #GICH_ELRSR1]
+ ldr w11, [x2, #GICH_APR]
+CPU_BE( rev w4, w4 )
+CPU_BE( rev w5, w5 )
+CPU_BE( rev w6, w6 )
+CPU_BE( rev w7, w7 )
+CPU_BE( rev w8, w8 )
+CPU_BE( rev w9, w9 )
+CPU_BE( rev w10, w10 )
+CPU_BE( rev w11, w11 )
+
+ str w4, [x3, #VGIC_V2_CPU_HCR]
+ str w5, [x3, #VGIC_V2_CPU_VMCR]
+ str w6, [x3, #VGIC_V2_CPU_MISR]
+ str w7, [x3, #VGIC_V2_CPU_EISR]
+ str w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
+ str w9, [x3, #VGIC_V2_CPU_ELRSR]
+ str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
+ str w11, [x3, #VGIC_V2_CPU_APR]
+
+ /* Clear GICH_HCR */
+ str wzr, [x2, #GICH_HCR]
+
+ /* Save list registers */
+ add x2, x2, #GICH_LR0
+ ldr w4, [x3, #VGIC_CPU_NR_LR]
+ add x3, x3, #VGIC_V2_CPU_LR
+1: ldr w5, [x2], #4
+CPU_BE( rev w5, w5 )
+ str w5, [x3], #4
+ sub w4, w4, #1
+ cbnz w4, 1b
+2:
+ ret
+ENDPROC(__save_vgic_v2_state)
+
+/*
+ * Restore the VGIC CPU state from memory
+ * x0: Register pointing to VCPU struct
+ */
+ENTRY(__restore_vgic_v2_state)
+__restore_vgic_v2_state:
+ /* Get VGIC VCTRL base into x2 */
+ ldr x2, [x0, #VCPU_KVM]
+ kern_hyp_va x2
+ ldr x2, [x2, #KVM_VGIC_VCTRL]
+ kern_hyp_va x2
+ cbz x2, 2f // disabled
+
+ /* Compute the address of struct vgic_cpu */
+ add x3, x0, #VCPU_VGIC_CPU
+
+ /* We only restore a minimal set of registers */
+ ldr w4, [x3, #VGIC_V2_CPU_HCR]
+ ldr w5, [x3, #VGIC_V2_CPU_VMCR]
+ ldr w6, [x3, #VGIC_V2_CPU_APR]
+CPU_BE( rev w4, w4 )
+CPU_BE( rev w5, w5 )
+CPU_BE( rev w6, w6 )
+
+ str w4, [x2, #GICH_HCR]
+ str w5, [x2, #GICH_VMCR]
+ str w6, [x2, #GICH_APR]
+
+ /* Restore list registers */
+ add x2, x2, #GICH_LR0
+ ldr w4, [x3, #VGIC_CPU_NR_LR]
+ add x3, x3, #VGIC_V2_CPU_LR
+1: ldr w5, [x3], #4
+CPU_BE( rev w5, w5 )
+ str w5, [x2], #4
+ sub w4, w4, #1
+ cbnz w4, 1b
+2:
+ ret
+ENDPROC(__restore_vgic_v2_state)
+
+ .popsection
diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S
new file mode 100644
index 000000000000..d16046999e06
--- /dev/null
+++ b/arch/arm64/kvm/vgic-v3-switch.S
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/irqchip/arm-gic-v3.h>
+
+#include <asm/assembler.h>
+#include <asm/memory.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+
+ .text
+ .pushsection .hyp.text, "ax"
+
+/*
+ * We store LRs in reverse order to let the CPU deal with streaming
+ * access. Use this macro to make it look saner...
+ */
+#define LR_OFFSET(n) (VGIC_V3_CPU_LR + (15 - n) * 8)
+
+/*
+ * Save the VGIC CPU state into memory
+ * x0: Register pointing to VCPU struct
+ * Do not corrupt x1!!!
+ */
+.macro save_vgic_v3_state
+ // Compute the address of struct vgic_cpu
+ add x3, x0, #VCPU_VGIC_CPU
+
+ // Make sure stores to the GIC via the memory mapped interface
+ // are now visible to the system register interface
+ dsb st
+
+ // Save all interesting registers
+ mrs_s x4, ICH_HCR_EL2
+ mrs_s x5, ICH_VMCR_EL2
+ mrs_s x6, ICH_MISR_EL2
+ mrs_s x7, ICH_EISR_EL2
+ mrs_s x8, ICH_ELSR_EL2
+
+ str w4, [x3, #VGIC_V3_CPU_HCR]
+ str w5, [x3, #VGIC_V3_CPU_VMCR]
+ str w6, [x3, #VGIC_V3_CPU_MISR]
+ str w7, [x3, #VGIC_V3_CPU_EISR]
+ str w8, [x3, #VGIC_V3_CPU_ELRSR]
+
+ msr_s ICH_HCR_EL2, xzr
+
+ mrs_s x21, ICH_VTR_EL2
+ mvn w22, w21
+ ubfiz w23, w22, 2, 4 // w23 = (15 - ListRegs) * 4
+
+ adr x24, 1f
+ add x24, x24, x23
+ br x24
+
+1:
+ mrs_s x20, ICH_LR15_EL2
+ mrs_s x19, ICH_LR14_EL2
+ mrs_s x18, ICH_LR13_EL2
+ mrs_s x17, ICH_LR12_EL2
+ mrs_s x16, ICH_LR11_EL2
+ mrs_s x15, ICH_LR10_EL2
+ mrs_s x14, ICH_LR9_EL2
+ mrs_s x13, ICH_LR8_EL2
+ mrs_s x12, ICH_LR7_EL2
+ mrs_s x11, ICH_LR6_EL2
+ mrs_s x10, ICH_LR5_EL2
+ mrs_s x9, ICH_LR4_EL2
+ mrs_s x8, ICH_LR3_EL2
+ mrs_s x7, ICH_LR2_EL2
+ mrs_s x6, ICH_LR1_EL2
+ mrs_s x5, ICH_LR0_EL2
+
+ adr x24, 1f
+ add x24, x24, x23
+ br x24
+
+1:
+ str x20, [x3, #LR_OFFSET(15)]
+ str x19, [x3, #LR_OFFSET(14)]
+ str x18, [x3, #LR_OFFSET(13)]
+ str x17, [x3, #LR_OFFSET(12)]
+ str x16, [x3, #LR_OFFSET(11)]
+ str x15, [x3, #LR_OFFSET(10)]
+ str x14, [x3, #LR_OFFSET(9)]
+ str x13, [x3, #LR_OFFSET(8)]
+ str x12, [x3, #LR_OFFSET(7)]
+ str x11, [x3, #LR_OFFSET(6)]
+ str x10, [x3, #LR_OFFSET(5)]
+ str x9, [x3, #LR_OFFSET(4)]
+ str x8, [x3, #LR_OFFSET(3)]
+ str x7, [x3, #LR_OFFSET(2)]
+ str x6, [x3, #LR_OFFSET(1)]
+ str x5, [x3, #LR_OFFSET(0)]
+
+ tbnz w21, #29, 6f // 6 bits
+ tbz w21, #30, 5f // 5 bits
+ // 7 bits
+ mrs_s x20, ICH_AP0R3_EL2
+ str w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
+ mrs_s x19, ICH_AP0R2_EL2
+ str w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
+6: mrs_s x18, ICH_AP0R1_EL2
+ str w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
+5: mrs_s x17, ICH_AP0R0_EL2
+ str w17, [x3, #VGIC_V3_CPU_AP0R]
+
+ tbnz w21, #29, 6f // 6 bits
+ tbz w21, #30, 5f // 5 bits
+ // 7 bits
+ mrs_s x20, ICH_AP1R3_EL2
+ str w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
+ mrs_s x19, ICH_AP1R2_EL2
+ str w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
+6: mrs_s x18, ICH_AP1R1_EL2
+ str w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
+5: mrs_s x17, ICH_AP1R0_EL2
+ str w17, [x3, #VGIC_V3_CPU_AP1R]
+
+ // Restore SRE_EL1 access and re-enable SRE at EL1.
+ mrs_s x5, ICC_SRE_EL2
+ orr x5, x5, #ICC_SRE_EL2_ENABLE
+ msr_s ICC_SRE_EL2, x5
+ isb
+ mov x5, #1
+ msr_s ICC_SRE_EL1, x5
+.endm
+
+/*
+ * Restore the VGIC CPU state from memory
+ * x0: Register pointing to VCPU struct
+ */
+.macro restore_vgic_v3_state
+ // Disable SRE_EL1 access. Necessary, otherwise
+ // ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens...
+ msr_s ICC_SRE_EL1, xzr
+ isb
+
+ // Compute the address of struct vgic_cpu
+ add x3, x0, #VCPU_VGIC_CPU
+
+ // Restore all interesting registers
+ ldr w4, [x3, #VGIC_V3_CPU_HCR]
+ ldr w5, [x3, #VGIC_V3_CPU_VMCR]
+
+ msr_s ICH_HCR_EL2, x4
+ msr_s ICH_VMCR_EL2, x5
+
+ mrs_s x21, ICH_VTR_EL2
+
+ tbnz w21, #29, 6f // 6 bits
+ tbz w21, #30, 5f // 5 bits
+ // 7 bits
+ ldr w20, [x3, #(VGIC_V3_CPU_AP1R + 3*4)]
+ msr_s ICH_AP1R3_EL2, x20
+ ldr w19, [x3, #(VGIC_V3_CPU_AP1R + 2*4)]
+ msr_s ICH_AP1R2_EL2, x19
+6: ldr w18, [x3, #(VGIC_V3_CPU_AP1R + 1*4)]
+ msr_s ICH_AP1R1_EL2, x18
+5: ldr w17, [x3, #VGIC_V3_CPU_AP1R]
+ msr_s ICH_AP1R0_EL2, x17
+
+ tbnz w21, #29, 6f // 6 bits
+ tbz w21, #30, 5f // 5 bits
+ // 7 bits
+ ldr w20, [x3, #(VGIC_V3_CPU_AP0R + 3*4)]
+ msr_s ICH_AP0R3_EL2, x20
+ ldr w19, [x3, #(VGIC_V3_CPU_AP0R + 2*4)]
+ msr_s ICH_AP0R2_EL2, x19
+6: ldr w18, [x3, #(VGIC_V3_CPU_AP0R + 1*4)]
+ msr_s ICH_AP0R1_EL2, x18
+5: ldr w17, [x3, #VGIC_V3_CPU_AP0R]
+ msr_s ICH_AP0R0_EL2, x17
+
+ and w22, w21, #0xf
+ mvn w22, w21
+ ubfiz w23, w22, 2, 4 // w23 = (15 - ListRegs) * 4
+
+ adr x24, 1f
+ add x24, x24, x23
+ br x24
+
+1:
+ ldr x20, [x3, #LR_OFFSET(15)]
+ ldr x19, [x3, #LR_OFFSET(14)]
+ ldr x18, [x3, #LR_OFFSET(13)]
+ ldr x17, [x3, #LR_OFFSET(12)]
+ ldr x16, [x3, #LR_OFFSET(11)]
+ ldr x15, [x3, #LR_OFFSET(10)]
+ ldr x14, [x3, #LR_OFFSET(9)]
+ ldr x13, [x3, #LR_OFFSET(8)]
+ ldr x12, [x3, #LR_OFFSET(7)]
+ ldr x11, [x3, #LR_OFFSET(6)]
+ ldr x10, [x3, #LR_OFFSET(5)]
+ ldr x9, [x3, #LR_OFFSET(4)]
+ ldr x8, [x3, #LR_OFFSET(3)]
+ ldr x7, [x3, #LR_OFFSET(2)]
+ ldr x6, [x3, #LR_OFFSET(1)]
+ ldr x5, [x3, #LR_OFFSET(0)]
+
+ adr x24, 1f
+ add x24, x24, x23
+ br x24
+
+1:
+ msr_s ICH_LR15_EL2, x20
+ msr_s ICH_LR14_EL2, x19
+ msr_s ICH_LR13_EL2, x18
+ msr_s ICH_LR12_EL2, x17
+ msr_s ICH_LR11_EL2, x16
+ msr_s ICH_LR10_EL2, x15
+ msr_s ICH_LR9_EL2, x14
+ msr_s ICH_LR8_EL2, x13
+ msr_s ICH_LR7_EL2, x12
+ msr_s ICH_LR6_EL2, x11
+ msr_s ICH_LR5_EL2, x10
+ msr_s ICH_LR4_EL2, x9
+ msr_s ICH_LR3_EL2, x8
+ msr_s ICH_LR2_EL2, x7
+ msr_s ICH_LR1_EL2, x6
+ msr_s ICH_LR0_EL2, x5
+
+ // Ensure that the above will have reached the
+ // (re)distributors. This ensure the guest will read
+ // the correct values from the memory-mapped interface.
+ isb
+ dsb sy
+
+ // Prevent the guest from touching the GIC system registers
+ mrs_s x5, ICC_SRE_EL2
+ and x5, x5, #~ICC_SRE_EL2_ENABLE
+ msr_s ICC_SRE_EL2, x5
+.endm
+
+ENTRY(__save_vgic_v3_state)
+ save_vgic_v3_state
+ ret
+ENDPROC(__save_vgic_v3_state)
+
+ENTRY(__restore_vgic_v3_state)
+ restore_vgic_v3_state
+ ret
+ENDPROC(__restore_vgic_v3_state)
+
+ENTRY(__vgic_v3_get_ich_vtr_el2)
+ mrs_s x0, ICH_VTR_EL2
+ ret
+ENDPROC(__vgic_v3_get_ich_vtr_el2)
+
+ .popsection
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index bcc965e2cce1..41cb6d3d6075 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -62,6 +62,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
pud = pud_offset(pgd, addr);
+ printk(", *pud=%016llx", pud_val(*pud));
if (pud_none(*pud) || pud_bad(*pud))
break;
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index e90c5426fe14..5b4526ee3a01 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -33,6 +33,7 @@
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
+#include <asm/fixmap.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/sizes.h>
@@ -137,20 +138,16 @@ void __init arm64_memblock_init(void)
{
phys_addr_t dma_phys_limit = 0;
- /* Register the kernel text, kernel data and initrd with memblock */
+ /*
+ * Register the kernel text, kernel data, initrd, and initial
+ * pagetables with memblock.
+ */
memblock_reserve(__pa(_text), _end - _text);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
#endif
- /*
- * Reserve the page tables. These are already in use,
- * and can only be in node 0.
- */
- memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
- memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
-
early_init_fdt_scan_reserved_mem();
/* 4GB maximum for 32-bit only capable devices */
@@ -269,26 +266,33 @@ void __init mem_init(void)
#define MLK(b, t) b, t, ((t) - (b)) >> 10
#define MLM(b, t) b, t, ((t) - (b)) >> 20
+#define MLG(b, t) b, t, ((t) - (b)) >> 30
#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
pr_notice("Virtual kernel memory layout:\n"
- " vmalloc : 0x%16lx - 0x%16lx (%6ld MB)\n"
+ " vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n"
#ifdef CONFIG_SPARSEMEM_VMEMMAP
- " vmemmap : 0x%16lx - 0x%16lx (%6ld MB)\n"
+ " vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n"
+ " 0x%16lx - 0x%16lx (%6ld MB actual)\n"
#endif
+ " PCI I/O : 0x%16lx - 0x%16lx (%6ld MB)\n"
+ " fixed : 0x%16lx - 0x%16lx (%6ld KB)\n"
" modules : 0x%16lx - 0x%16lx (%6ld MB)\n"
" memory : 0x%16lx - 0x%16lx (%6ld MB)\n"
- " .init : 0x%p" " - 0x%p" " (%6ld kB)\n"
- " .text : 0x%p" " - 0x%p" " (%6ld kB)\n"
- " .data : 0x%p" " - 0x%p" " (%6ld kB)\n",
- MLM(VMALLOC_START, VMALLOC_END),
+ " .init : 0x%p" " - 0x%p" " (%6ld KB)\n"
+ " .text : 0x%p" " - 0x%p" " (%6ld KB)\n"
+ " .data : 0x%p" " - 0x%p" " (%6ld KB)\n",
+ MLG(VMALLOC_START, VMALLOC_END),
#ifdef CONFIG_SPARSEMEM_VMEMMAP
+ MLG((unsigned long)vmemmap,
+ (unsigned long)vmemmap + VMEMMAP_SIZE),
MLM((unsigned long)virt_to_page(PAGE_OFFSET),
(unsigned long)virt_to_page(high_memory)),
#endif
+ MLM((unsigned long)PCI_IOBASE, (unsigned long)PCI_IOBASE + SZ_16M),
+ MLK(FIXADDR_START, FIXADDR_TOP),
MLM(MODULES_VADDR, MODULES_END),
MLM(PAGE_OFFSET, (unsigned long)high_memory),
-
MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_text, _etext),
MLK_ROUNDUP(_sdata, _edata));
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 7ec328392ae0..fa324bd5a5c4 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -103,19 +103,28 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
}
EXPORT_SYMBOL(ioremap_cache);
-#ifndef CONFIG_ARM64_64K_PAGES
static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
+#endif
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
#endif
-static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+static inline pud_t * __init early_ioremap_pud(unsigned long addr)
{
pgd_t *pgd;
- pud_t *pud;
pgd = pgd_offset_k(addr);
BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
- pud = pud_offset(pgd, addr);
+ return pud_offset(pgd, addr);
+}
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+ pud_t *pud = early_ioremap_pud(addr);
+
BUG_ON(pud_none(*pud) || pud_bad(*pud));
return pmd_offset(pud, addr);
@@ -132,13 +141,18 @@ static inline pte_t * __init early_ioremap_pte(unsigned long addr)
void __init early_ioremap_init(void)
{
+ pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
+ unsigned long addr = fix_to_virt(FIX_BTMAP_BEGIN);
- pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
-#ifndef CONFIG_ARM64_64K_PAGES
- /* need to populate pmd for 4k pagesize only */
+ pgd = pgd_offset_k(addr);
+ pgd_populate(&init_mm, pgd, bm_pud);
+ pud = pud_offset(pgd, addr);
+ pud_populate(&init_mm, pud, bm_pmd);
+ pmd = pmd_offset(pud, addr);
pmd_populate_kernel(&init_mm, pmd, bm_pte);
-#endif
+
/*
* The boot-ioremap range spans multiple pmds, for which
* we are not prepared:
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index c43f1dd19489..c55567283cde 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -32,6 +32,7 @@
#include <asm/setup.h>
#include <asm/sizes.h>
#include <asm/tlb.h>
+#include <asm/memblock.h>
#include <asm/mmu_context.h>
#include "mm.h"
@@ -204,9 +205,16 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
unsigned long end, unsigned long phys,
int map_io)
{
- pud_t *pud = pud_offset(pgd, addr);
+ pud_t *pud;
unsigned long next;
+ if (pgd_none(*pgd)) {
+ pud = early_alloc(PTRS_PER_PUD * sizeof(pud_t));
+ pgd_populate(&init_mm, pgd, pud);
+ }
+ BUG_ON(pgd_bad(*pgd));
+
+ pud = pud_offset(pgd, addr);
do {
next = pud_addr_end(addr, end);
@@ -290,10 +298,10 @@ static void __init map_mem(void)
* memory addressable from the initial direct kernel mapping.
*
* The initial direct kernel mapping, located at swapper_pg_dir,
- * gives us PGDIR_SIZE memory starting from PHYS_OFFSET (which must be
+ * gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
* aligned to 2MB as per Documentation/arm64/booting.txt).
*/
- limit = PHYS_OFFSET + PGDIR_SIZE;
+ limit = PHYS_OFFSET + PUD_SIZE;
memblock_set_current_limit(limit);
/* map all the memory banks */
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index 1ba09e4c02b1..91146b416cdb 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -17,6 +17,8 @@
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/atmel_serial.h>
@@ -155,21 +157,28 @@ static struct platform_device rmt_ts_device = {
#ifdef CONFIG_BOARD_MRMT_BL_PWM
/* PWM LEDs: LCD Backlight, etc */
-static struct gpio_led rmt_pwm_led[] = {
- /* here the "gpio" is actually a PWM channel */
- { .name = "backlight", .gpio = PWM_CH_BL, },
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1",
+ 5000, PWM_POLARITY_INVERSED),
};
-static struct gpio_led_platform_data rmt_pwm_led_data = {
- .num_leds = ARRAY_SIZE(rmt_pwm_led),
- .leds = rmt_pwm_led,
+static struct led_pwm pwm_leds[] = {
+ {
+ .name = "backlight",
+ .max_brightness = 255,
+ },
+};
+
+static struct led_pwm_platform_data pwm_data = {
+ .num_leds = ARRAY_SIZE(pwm_leds),
+ .leds = pwm_leds,
};
-static struct platform_device rmt_pwm_led_dev = {
- .name = "leds-atmel-pwm",
- .id = -1,
- .dev = {
- .platform_data = &rmt_pwm_led_data,
+static struct platform_device leds_pwm = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &pwm_data,
},
};
#endif
@@ -325,7 +334,8 @@ static int __init mrmt1_init(void)
#ifdef CONFIG_BOARD_MRMT_BL_PWM
/* Use PWM for Backlight controls */
at32_add_device_pwm(1 << PWM_CH_BL);
- platform_device_register(&rmt_pwm_led_dev);
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+ platform_device_register(&leds_pwm);
#else
/* Backlight always on */
udelay( 1 );
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 1f121497b517..234cb071c601 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -18,7 +18,10 @@
#include <linux/gpio.h>
#include <linux/leds.h>
#include <linux/atmel-mci.h>
-#include <linux/atmel-pwm-bl.h>
+#include <linux/pwm.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@@ -33,6 +36,8 @@
#include <mach/board.h>
#include <mach/portmux.h>
+#define PWM_BL_CH 2
+
/* Oscillator frequencies. These are board-specific */
unsigned long at32_board_osc_rates[3] = {
[0] = 32768, /* 32.768 kHz on RTC osc */
@@ -227,29 +232,36 @@ void __init favr32_setup_leds(void)
platform_device_register(&favr32_led_dev);
}
-static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = {
- .pwm_channel = 2,
- .pwm_frequency = 200000,
- .pwm_compare_max = 345,
- .pwm_duty_max = 345,
- .pwm_duty_min = 90,
- .pwm_active_low = 1,
- .gpio_on = GPIO_PIN_PA(28),
- .on_active_low = 0,
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("at91sam9rl-pwm", PWM_BL_CH, "pwm-backlight.0", NULL,
+ 5000, PWM_POLARITY_INVERSED),
};
-static struct platform_device atmel_pwm_bl_dev = {
- .name = "atmel-pwm-bl",
- .id = 0,
- .dev = {
- .platform_data = &atmel_pwm_bl_pdata,
+static struct regulator_consumer_supply fixed_power_consumers[] = {
+ REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
+static struct platform_pwm_backlight_data pwm_bl_data = {
+ .enable_gpio = GPIO_PIN_PA(28),
+ .max_brightness = 255,
+ .dft_brightness = 255,
+ .lth_brightness = 50,
+};
+
+static struct platform_device pwm_bl_device = {
+ .name = "pwm-backlight",
+ .dev = {
+ .platform_data = &pwm_bl_data,
},
};
static void __init favr32_setup_atmel_pwm_bl(void)
{
- platform_device_register(&atmel_pwm_bl_dev);
- at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0);
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+ regulator_register_always_on(0, "fixed", fixed_power_consumers,
+ ARRAY_SIZE(fixed_power_consumers), 3300000);
+ platform_device_register(&pwm_bl_device);
+ at32_select_gpio(pwm_bl_data.enable_gpio, 0);
}
void __init setup_board(void)
@@ -339,7 +351,7 @@ static int __init favr32_init(void)
set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
- at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
+ at32_add_device_pwm(1 << PWM_BL_CH);
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
at32_add_device_mci(0, &mci0_data);
at32_add_device_usba(0, NULL);
diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c
index 776c3cb9b6e4..e86280ccd8fa 100644
--- a/arch/avr32/boards/hammerhead/flash.c
+++ b/arch/avr32/boards/hammerhead/flash.c
@@ -190,14 +190,19 @@ static int __init hammerhead_usbh_init(void)
/* setup gclk0 to run from osc1 */
gclk = clk_get(NULL, "gclk0");
- if (IS_ERR(gclk))
+ if (IS_ERR(gclk)) {
+ ret = PTR_ERR(gclk);
goto err_gclk;
+ }
osc = clk_get(NULL, "osc1");
- if (IS_ERR(osc))
+ if (IS_ERR(osc)) {
+ ret = PTR_ERR(osc);
goto err_osc;
+ }
- if (clk_set_parent(gclk, osc)) {
+ ret = clk_set_parent(gclk, osc);
+ if (ret < 0) {
pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
goto err_set_clk;
}
diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c
index ed137e335796..83d896cc2aed 100644
--- a/arch/avr32/boards/merisc/setup.c
+++ b/arch/avr32/boards/merisc/setup.c
@@ -22,6 +22,8 @@
#include <linux/irq.h>
#include <linux/fb.h>
#include <linux/atmel-mci.h>
+#include <linux/pwm.h>
+#include <linux/leds_pwm.h>
#include <asm/io.h>
#include <asm/setup.h>
@@ -167,24 +169,29 @@ static struct i2c_board_info __initdata i2c_info[] = {
},
};
-#ifdef CONFIG_LEDS_ATMEL_PWM
-static struct gpio_led stk_pwm_led[] = {
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("at91sam9rl-pwm", 0, "leds_pwm", "backlight",
+ 5000, PWM_POLARITY_NORMAL),
+};
+
+static struct led_pwm pwm_leds[] = {
{
.name = "backlight",
- .gpio = 0, /* PWM channel 0 (LCD backlight) */
+ .max_brightness = 255,
},
};
-static struct gpio_led_platform_data stk_pwm_led_data = {
- .num_leds = ARRAY_SIZE(stk_pwm_led),
- .leds = stk_pwm_led,
+static struct led_pwm_platform_data pwm_data = {
+ .num_leds = ARRAY_SIZE(pwm_leds),
+ .leds = pwm_leds,
};
-static struct platform_device stk_pwm_led_dev = {
- .name = "leds-atmel-pwm",
- .id = -1,
- .dev = {
- .platform_data = &stk_pwm_led_data,
+static struct platform_device leds_pwm = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &pwm_data,
},
};
#endif
@@ -278,9 +285,10 @@ static int __init merisc_init(void)
at32_add_device_mci(0, &mci0_data);
-#ifdef CONFIG_LEDS_ATMEL_PWM
+#if IS_ENABLED(CONFIG_LEDS_PWM)
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
at32_add_device_pwm((1 << 0) | (1 << 2));
- platform_device_register(&stk_pwm_led_dev);
+ platform_device_register(&leds_pwm);
#else
at32_add_device_pwm((1 << 2));
#endif
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig
index 9a57da44eb6f..6838781e966f 100644
--- a/arch/avr32/configs/atngw100_mrmt_defconfig
+++ b/arch/avr32/configs/atngw100_mrmt_defconfig
@@ -56,7 +56,6 @@ CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_DATAFLASH=y
CONFIG_BLK_DEV_LOOP=y
-CONFIG_ATMEL_PWM=y
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MACB=y
@@ -104,8 +103,8 @@ CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=y
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -114,6 +113,8 @@ CONFIG_RTC_DRV_S35390A=m
CONFIG_RTC_DRV_AT32AP700X=m
CONFIG_DMADEVICES=y
CONFIG_UIO=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 2813dd2b9138..b056820eef33 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -64,7 +64,6 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=m
# CONFIG_SCSI_PROC_FS is not set
@@ -133,14 +132,16 @@ CONFIG_MMC_TEST=m
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig
index f8ff3a3baad4..0cd23a303da1 100644
--- a/arch/avr32/configs/atstk1003_defconfig
+++ b/arch/avr32/configs/atstk1003_defconfig
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=m
# CONFIG_SCSI_PROC_FS is not set
@@ -112,14 +111,16 @@ CONFIG_MMC_TEST=m
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index 992228e54e38..ac1041f5f85a 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=m
# CONFIG_SCSI_PROC_FS is not set
@@ -111,14 +110,16 @@ CONFIG_MMC_TEST=m
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index b8e698b0d1fa..ea4f670cb995 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -67,7 +67,6 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_MISC_DEVICES=y
-CONFIG_ATMEL_PWM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=m
# CONFIG_SCSI_PROC_FS is not set
@@ -136,14 +135,16 @@ CONFIG_MMC_TEST=m
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index 07bed3f7eb5e..b3eb67dc05ac 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -67,7 +67,6 @@ CONFIG_MTD_PHYSMAP=y
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=m
-CONFIG_ATMEL_PWM=m
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=m
CONFIG_NETDEVICES=y
@@ -108,7 +107,7 @@ CONFIG_FB=y
CONFIG_FB_ATMEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_BACKLIGHT_ATMEL_PWM=m
+CONFIG_BACKLIGHT_PWM=m
CONFIG_SOUND=m
CONFIG_SOUND_PRIME=m
# CONFIG_HID_SUPPORT is not set
@@ -123,7 +122,6 @@ CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=m
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
@@ -132,6 +130,8 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT32AP700X=y
CONFIG_DMADEVICES=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig
index 91df6b2986be..b9ef4cc85d08 100644
--- a/arch/avr32/configs/merisc_defconfig
+++ b/arch/avr32/configs/merisc_defconfig
@@ -55,7 +55,6 @@ CONFIG_MTD_ABSENT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_BLOCK2MTD=y
CONFIG_BLK_DEV_LOOP=y
-CONFIG_ATMEL_PWM=y
CONFIG_ATMEL_SSC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
@@ -103,12 +102,14 @@ CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_ATMEL_PWM=y
+CONFIG_LEDS_PWM=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_DRV_PCF8563=y
CONFIG_DMADEVICES=y
CONFIG_UIO=y
+CONFIG_PWM=y
+CONFIG_PWM_ATMEL=m
CONFIG_EXT2_FS=y
# CONFIG_DNOTIFY is not set
CONFIG_FUSE_FS=y
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h
index 972adcc1e8f4..941593c7d9f3 100644
--- a/arch/avr32/include/asm/processor.h
+++ b/arch/avr32/include/asm/processor.h
@@ -92,6 +92,7 @@ extern struct avr32_cpuinfo boot_cpu_data;
#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#define cpu_sync_pipeline() asm volatile("sub pc, -2" : : : "memory")
struct cpu_context {
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index b80c0b3d2bab..d309fbcc3bd6 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
}
static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
{
- unsigned long sp = regs->sp;
-
- if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ unsigned long sp = sigsp(regs->sp, ksig);
return (void __user *)((sp - framesize) & ~3);
}
static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
err = -EFAULT;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto out;
@@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
&frame->retcode);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Set up the ucontext */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err)
goto out;
- regs->r12 = sig;
+ regs->r12 = ksig->sig;
regs->r11 = (unsigned long) &frame->info;
regs->r10 = (unsigned long) &frame->uc;
regs->sp = (unsigned long) frame;
- if (ka->sa.sa_flags & SA_RESTORER)
- regs->lr = (unsigned long)ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
else {
printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
current->comm, current->pid);
@@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
- current->comm, current->pid, sig, regs->sp,
- regs->pc, ka->sa.sa_handler, regs->lr);
+ current->comm, current->pid, ksig->sig, regs->sp,
+ regs->pc, ksig->ka.sa.sa_handler, regs->lr);
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
out:
return err;
@@ -208,15 +204,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
}
static inline void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- struct pt_regs *regs, int syscall)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall)
{
int ret;
/*
* Set up the stack frame
*/
- ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
+ ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
/*
* Check that the resulting registers are sane
@@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/*
* Block the signal if we were successful.
*/
- if (ret != 0)
- force_sigsegv(sig, current);
- else
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/
static void do_signal(struct pt_regs *regs, int syscall)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which is why we may in
@@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ get_signal(&ksig);
if (syscall) {
switch (regs->r12) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
- if (signr > 0) {
+ if (ksig.sig > 0) {
regs->r12 = -EINTR;
break;
}
/* fall through */
case -ERESTARTSYS:
- if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
+ if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->r12 = -EINTR;
break;
}
@@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *regs, int syscall)
}
}
- if (signr == 0) {
+ if (!ksig.sig) {
/* No signal to deliver -- put the saved sigmask back */
restore_saved_sigmask();
return;
}
- handle_signal(signr, &ka, &info, regs, syscall);
+ handle_signal(&ksig, regs, syscall);
}
asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index a1f4d1e91b52..db85b5ec3351 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1553,7 +1553,7 @@ static struct resource atmel_pwm0_resource[] __initdata = {
IRQ(24),
};
static struct clk atmel_pwm0_mck = {
- .name = "pwm_clk",
+ .name = "at91sam9rl-pwm",
.parent = &pbb_clk,
.mode = pbb_clk_mode,
.get_rate = pbb_clk_get_rate,
@@ -1568,7 +1568,7 @@ struct platform_device *__init at32_add_device_pwm(u32 mask)
if (!mask)
return NULL;
- pdev = platform_device_alloc("atmel_pwm", 0);
+ pdev = platform_device_alloc("at91sam9rl-pwm", 0);
if (!pdev)
return NULL;
@@ -1576,9 +1576,6 @@ struct platform_device *__init at32_add_device_pwm(u32 mask)
ARRAY_SIZE(atmel_pwm0_resource)))
goto out_free_pdev;
- if (platform_device_add_data(pdev, &mask, sizeof(mask)))
- goto out_free_pdev;
-
pin_mask = 0;
if (mask & (1 << 0))
pin_mask |= (1 << 28);
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index f81e7b989fff..ed30699cc635 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -18,7 +18,6 @@ config BLACKFIN
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_IDE
select HAVE_KERNEL_GZIP if RAMKERNEL
select HAVE_KERNEL_BZIP2 if RAMKERNEL
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index d0e72e9475a6..7acd46653df3 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -99,7 +99,7 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
#define cpu_relax() smp_mb()
-
+#define cpu_relax_lowlatency() cpu_relax()
/* Get the Silicon Revision of the chip */
static inline uint32_t __pure bfin_revid(void)
diff --git a/arch/blackfin/kernel/ftrace-entry.S b/arch/blackfin/kernel/ftrace-entry.S
index 7eed00bbd26d..28d059540424 100644
--- a/arch/blackfin/kernel/ftrace-entry.S
+++ b/arch/blackfin/kernel/ftrace-entry.S
@@ -33,15 +33,6 @@ ENDPROC(__mcount)
* function will be waiting there. mmmm pie.
*/
ENTRY(_ftrace_caller)
-# ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
- /* optional micro optimization: return if stopped */
- p1.l = _function_trace_stop;
- p1.h = _function_trace_stop;
- r3 = [p1];
- cc = r3 == 0;
- if ! cc jump _ftrace_stub (bp);
-# endif
-
/* save first/second/third function arg and the return register */
[--sp] = r2;
[--sp] = r0;
@@ -83,15 +74,6 @@ ENDPROC(_ftrace_caller)
/* See documentation for _ftrace_caller */
ENTRY(__mcount)
-# ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
- /* optional micro optimization: return if stopped */
- p1.l = _function_trace_stop;
- p1.h = _function_trace_stop;
- r3 = [p1];
- cc = r3 == 0;
- if ! cc jump _ftrace_stub (bp);
-# endif
-
/* save third function arg early so we can do testing below */
[--sp] = r2;
diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c
index 974e55496db3..ea2032013cc2 100644
--- a/arch/blackfin/kernel/perf_event.c
+++ b/arch/blackfin/kernel/perf_event.c
@@ -389,14 +389,6 @@ static int bfin_pmu_event_init(struct perf_event *event)
if (attr->exclude_hv || attr->exclude_idle)
return -EPERM;
- /*
- * All of the on-chip counters are "limited", in that they have
- * no interrupts, and are therefore unable to do sampling without
- * further work and timer assistance.
- */
- if (hwc->sample_period)
- return -EINVAL;
-
ret = 0;
switch (attr->type) {
case PERF_TYPE_RAW:
@@ -490,6 +482,13 @@ static int __init bfin_pmu_init(void)
{
int ret;
+ /*
+ * All of the on-chip counters are "limited", in that they have
+ * no interrupts, and are therefore unable to do sampling without
+ * further work and timer assistance.
+ */
+ pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
ret = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
if (!ret)
perf_cpu_notifier(bfin_pmu_notifier);
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index b022af6c48f8..ef275571d885 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -135,40 +135,31 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
return err;
}
-static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+static inline void *get_sigframe(struct ksignal *ksig,
size_t frame_size)
{
- unsigned long usp;
+ unsigned long usp = sigsp(rdusp(), ksig);
- /* Default to using normal stack. */
- usp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!on_sig_stack(usp))
- usp = current->sas_ss_sp + current->sas_ss_size;
- }
return (void *)((usp - frame_size) & -8UL);
}
static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
- sigset_t * set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
- && sig < 32
+ && ksig->sig < 32
? current_thread_info()->exec_domain->
- signal_invmap[sig] : sig), &frame->sig);
+ signal_invmap[ksig->sig] : ksig->sig), &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -183,7 +174,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
/* Set up registers for signal handler */
if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor *) ka->sa.sa_handler;
+ (struct fdpic_func_descriptor *) ksig->ka.sa.sa_handler;
u32 pc, p3;
err |= __get_user(pc, &funcptr->text);
err |= __get_user(p3, &funcptr->GOT);
@@ -192,7 +183,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
regs->pc = pc;
regs->p3 = p3;
} else
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
wrusp((unsigned long)frame);
regs->rets = SIGRETURN_STUB;
@@ -237,20 +228,19 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
* OK, we're invoking a handler
*/
static void
-handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
+ int ret;
+
/* are we from a system call? to see pt_regs->orig_p0 */
if (regs->orig_p0 >= 0)
/* If so, check system call restarting.. */
- handle_restart(regs, ka, 1);
+ handle_restart(regs, &ksig->ka, 1);
/* set up the stack frame */
- if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
- force_sigsegv(sig, current);
- else
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
+
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -264,16 +254,13 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
*/
asmlinkage void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
current->thread.esp0 = (unsigned long)regs;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h
index b9eb3da7f278..f2ef31be2f8b 100644
--- a/arch/c6x/include/asm/processor.h
+++ b/arch/c6x/include/asm/processor.h
@@ -121,6 +121,7 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(task) (task_pt_regs(task)->sp)
#define cpu_relax() do { } while (0)
+#define cpu_relax_lowlatency() cpu_relax()
extern const struct seq_operations cpuinfo_op;
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c
index 3998b24e26f2..fe68226f6c4d 100644
--- a/arch/c6x/kernel/signal.c
+++ b/arch/c6x/kernel/signal.c
@@ -127,17 +127,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
return err;
}
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
unsigned long framesize)
{
- unsigned long sp = regs->sp;
-
- /*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
- sp = current->sas_ss_sp + current->sas_ss_size;
+ unsigned long sp = sigsp(regs->sp, ksig);
/*
* No matter what happens, 'sp' must be dword
@@ -146,21 +140,21 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
return (void __user *)((sp - framesize) & ~7);
}
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
unsigned long __user *retcode;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto segv_and_exit;
+ return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -188,7 +182,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
#undef COPY
if (err)
- goto segv_and_exit;
+ return -EFAULT;
flush_icache_range((unsigned long) &frame->retcode,
(unsigned long) &frame->retcode + RETCODE_SIZE);
@@ -198,10 +192,10 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Change user context to branch to signal handler */
regs->sp = (unsigned long) frame - 8;
regs->b3 = (unsigned long) retcode;
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
/* Give the signal number to the handler */
- regs->a4 = signr;
+ regs->a4 = ksig->sig;
/*
* For realtime signals we must also set the second and third
@@ -212,10 +206,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
regs->a6 = (unsigned long)&frame->uc;
return 0;
-
-segv_and_exit:
- force_sigsegv(signr, current);
- return -EFAULT;
}
static inline void
@@ -245,10 +235,11 @@ do_restart:
/*
* handle the actual delivery of a signal to userspace
*/
-static void handle_signal(int sig,
- siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs, int syscall)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
+ int syscall)
{
+ int ret;
+
/* Are we from a system call? */
if (syscall) {
/* If so, check system call restarting.. */
@@ -259,7 +250,7 @@ static void handle_signal(int sig,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->a4 = -EINTR;
break;
}
@@ -272,9 +263,8 @@ static void handle_signal(int sig,
}
/* Set up the stack frame */
- if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
- return;
- signal_delivered(sig, info, ka, regs, 0);
+ ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -282,18 +272,15 @@ static void handle_signal(int sig,
*/
static void do_signal(struct pt_regs *regs, int syscall)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
/* we want the common case to go fast, which is why we may in certain
* cases get here from kernel mode */
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- handle_signal(signr, &info, &ka, regs, syscall);
+ if (get_signal(&ksig)) {
+ handle_signal(&ksig, regs, syscall);
return;
}
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 61ce6273a895..9b32d338838b 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -203,15 +203,9 @@ static int setup_sigcontext(struct sigcontext __user *sc,
* - usually on the stack. */
static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
{
- unsigned long sp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
+ unsigned long sp = sigsp(rdusp(), ksig);
/* make sure the frame is dword-aligned */
@@ -228,33 +222,33 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
* user-mode trampoline.
*/
-static int setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct sigframe __user *frame;
unsigned long return_ip;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- return_ip = (unsigned long)ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else {
/* trampoline - the desired return ip is the retcode itself */
return_ip = (unsigned long)&frame->retcode;
@@ -265,42 +259,38 @@ static int setup_frame(int sig, struct k_sigaction *ka,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
- regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */
+ regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* what we enter NOW */
regs->srp = return_ip; /* what we enter LATER */
- regs->r10 = sig; /* first argument is signo */
+ regs->r10 = ksig->sig; /* first argument is signo */
/* actually move the usp to reflect the stacked frame */
wrusp((unsigned long)frame);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
unsigned long return_ip;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -312,12 +302,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, rdusp());
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- return_ip = (unsigned long)ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else {
/* trampoline - the desired return ip is the retcode itself */
return_ip = (unsigned long)&frame->retcode;
@@ -329,18 +319,18 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* TODO what is the current->exec_domain stuff and invmap ? */
/* Set up registers for signal handler */
/* What we enter NOW */
- regs->irp = (unsigned long) ka->sa.sa_handler;
+ regs->irp = (unsigned long) ksig->ka.sa.sa_handler;
/* What we enter LATER */
regs->srp = return_ip;
/* First argument is signo */
- regs->r10 = sig;
+ regs->r10 = ksig->sig;
/* Second argument is (siginfo_t *) */
regs->r11 = (unsigned long)&frame->info;
/* Third argument is unused */
@@ -350,19 +340,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
wrusp((unsigned long)frame);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
-static inline void handle_signal(int canrestart, unsigned long sig,
- siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs)
+static inline void handle_signal(int canrestart, struct ksignal *ksig,
+ struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -383,7 +368,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
/* ERESTARTSYS means to restart the syscall if
* there is no handler or the handler was
* registered with SA_RESTART */
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r10 = -EINTR;
break;
}
@@ -396,13 +381,12 @@ static inline void handle_signal(int canrestart, unsigned long sig,
}
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(ksig, oldset, regs);
- if (ret == 0)
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -419,9 +403,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
void do_signal(int canrestart, struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which
@@ -432,10 +414,9 @@ void do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(canrestart, signr, &info, &ka, regs);
+ handle_signal(canrestart, &ksig, regs);
return;
}
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 01d1375c9004..78ce3b1c9bcb 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -189,17 +189,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
/* Figure out where to put the new signal frame - usually on the stack. */
static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
{
- unsigned long sp;
-
- sp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!on_sig_stack(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
+ unsigned long sp = sigsp(rdusp(), ksig);
/* Make sure the frame is dword-aligned. */
sp &= ~3;
@@ -215,23 +207,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
* trampoline.
*/
static int
-setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
- struct pt_regs * regs)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
int err;
unsigned long return_ip;
struct signal_frame __user *frame;
err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
@@ -239,14 +230,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Set up to return from user-space. If provided, use a stub
* already located in user-space.
*/
- if (ka->sa.sa_flags & SA_RESTORER) {
- return_ip = (unsigned long)ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else {
/* Trampoline - the desired return ip is in the signal return page. */
return_ip = cris_signal_return_page;
@@ -264,7 +255,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Set up registers for signal handler.
@@ -273,42 +264,37 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
* Where the code enter later.
* First argument, signo.
*/
- regs->erp = (unsigned long) ka->sa.sa_handler;
+ regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
regs->srp = return_ip;
- regs->r10 = sig;
+ regs->r10 = ksig->sig;
/* Actually move the USP to reflect the stacked frame. */
wrusp((unsigned long)frame);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
int err;
unsigned long return_ip;
struct rt_signal_frame __user *frame;
err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
/* TODO: what is the current->exec_domain stuff and invmap ? */
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
@@ -317,14 +303,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, rdusp());
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Set up to return from user-space. If provided, use a stub
* already located in user-space.
*/
- if (ka->sa.sa_flags & SA_RESTORER) {
- return_ip = (unsigned long) ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ return_ip = (unsigned long) ksig->ka.sa.sa_restorer;
} else {
/* Trampoline - the desired return ip is in the signal return page. */
return_ip = cris_signal_return_page + 6;
@@ -345,7 +331,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Set up registers for signal handler.
@@ -356,9 +342,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Second argument is (siginfo_t *).
* Third argument is unused.
*/
- regs->erp = (unsigned long) ka->sa.sa_handler;
+ regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
regs->srp = return_ip;
- regs->r10 = sig;
+ regs->r10 = ksig->sig;
regs->r11 = (unsigned long) &frame->info;
regs->r12 = 0;
@@ -366,17 +352,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
wrusp((unsigned long)frame);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/* Invoke a signal handler to, well, handle the signal. */
static inline void
-handle_signal(int canrestart, unsigned long sig,
- siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs * regs)
+handle_signal(int canrestart, struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -404,7 +384,7 @@ handle_signal(int canrestart, unsigned long sig,
* there is no handler, or the handler
* was registered with SA_RESTART.
*/
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r10 = -EINTR;
break;
}
@@ -423,13 +403,12 @@ handle_signal(int canrestart, unsigned long sig,
}
/* Set up the stack frame. */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(ksig, oldset, regs);
- if (ret == 0)
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -446,9 +425,7 @@ handle_signal(int canrestart, unsigned long sig,
void
do_signal(int canrestart, struct pt_regs *regs)
{
- int signr;
- siginfo_t info;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* The common case should go fast, which is why this point is
@@ -458,11 +435,9 @@ do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(canrestart, signr, &info, &ka, regs);
+ handle_signal(canrestart, &ksig, regs);
return;
}
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index afff5105909d..31742dfadff9 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -13,6 +13,7 @@ generic-y += linkage.h
generic-y += mcs_spinlock.h
generic-y += module.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
generic-y += vga.h
generic-y += xor.h
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h
index 15b815df29c1..862126b58116 100644
--- a/arch/cris/include/asm/processor.h
+++ b/arch/cris/include/asm/processor.h
@@ -63,6 +63,7 @@ static inline void release_thread(struct task_struct *dead_task)
#define init_stack (init_thread_union.stack)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
void default_idle(void);
diff --git a/arch/cris/include/asm/scatterlist.h b/arch/cris/include/asm/scatterlist.h
deleted file mode 100644
index f11f8f40ec4a..000000000000
--- a/arch/cris/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_CRIS_SCATTERLIST_H
-#define __ASM_CRIS_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(__ASM_CRIS_SCATTERLIST_H) */
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 87b95eb8aee5..5b73921b6e9d 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -5,4 +5,5 @@ generic-y += exec.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
diff --git a/arch/frv/include/asm/scatterlist.h b/arch/frv/include/asm/scatterlist.h
deleted file mode 100644
index 0e5eb3018468..000000000000
--- a/arch/frv/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !_ASM_SCATTERLIST_H */
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d822700d4f15..dc3d59de0870 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
/*
* Determine which stack to use..
*/
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
size_t frame_size)
{
- unsigned long sp;
-
- /* Default to using normal stack */
- sp = __frame->sp;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
+ unsigned long sp = sigsp(__frame->sp, ksig);
return (void __user *) ((sp - frame_size) & ~7UL);
@@ -180,17 +171,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
/*
*
*/
-static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
+static int setup_frame(struct ksignal *ksig, sigset_t *set)
{
struct sigframe __user *frame;
- int rsig;
+ int rsig, sig = ksig->sig;
set_fs(USER_DS);
- frame = get_sigframe(ka, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
rsig = sig;
if (sig < 32 &&
@@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
rsig = __current_thread_info->exec_domain->signal_invmap[sig];
if (__put_user(rsig, &frame->sig) < 0)
- goto give_sigsegv;
+ return -EFAULT;
if (setup_sigcontext(&frame->sc, set->sig[0]))
- goto give_sigsegv;
+ return -EFAULT;
if (_NSIG_WORDS > 1) {
if (__copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* Set up to return from userspace. If provided, use a stub
* already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
- goto give_sigsegv;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode) < 0)
+ return -EFAULT;
}
else {
/* Set up the following code on the stack:
@@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1]))
- goto give_sigsegv;
+ return -EFAULT;
flush_icache_range((unsigned long) frame->retcode,
(unsigned long) (frame->retcode + 2));
@@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
/* Set up registers for the signal handler */
if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+ (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
struct fdpic_func_descriptor desc;
if (copy_from_user(&desc, funcptr, sizeof(desc)))
- goto give_sigsegv;
+ return -EFAULT;
__frame->pc = desc.text;
__frame->gr15 = desc.GOT;
} else {
- __frame->pc = (unsigned long) ka->sa.sa_handler;
+ __frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
__frame->gr15 = 0;
}
@@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
-
} /* end setup_frame() */
/*****************************************************************************/
/*
*
*/
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set)
{
struct rt_sigframe __user *frame;
- int rsig;
+ int rsig, sig = ksig->sig;
set_fs(USER_DS);
- frame = get_sigframe(ka, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
rsig = sig;
if (sig < 32 &&
@@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user(rsig, &frame->sig) ||
__put_user(&frame->info, &frame->pinfo) ||
__put_user(&frame->uc, &frame->puc))
- goto give_sigsegv;
+ return -EFAULT;
- if (copy_siginfo_to_user(&frame->info, info))
- goto give_sigsegv;
+ if (copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
/* Create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) ||
__put_user(NULL, &frame->uc.uc_link) ||
__save_altstack(&frame->uc.uc_stack, __frame->sp))
- goto give_sigsegv;
+ return -EFAULT;
if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
- goto give_sigsegv;
+ return -EFAULT;
if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
* already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
- goto give_sigsegv;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+ return -EFAULT;
}
else {
/* Set up the following code on the stack:
@@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1]))
- goto give_sigsegv;
+ return -EFAULT;
flush_icache_range((unsigned long) frame->retcode,
(unsigned long) (frame->retcode + 2));
@@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
+ (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
struct fdpic_func_descriptor desc;
if (copy_from_user(&desc, funcptr, sizeof(desc)))
- goto give_sigsegv;
+ return -EFAULT;
__frame->pc = desc.text;
__frame->gr15 = desc.GOT;
} else {
- __frame->pc = (unsigned long) ka->sa.sa_handler;
+ __frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
__frame->gr15 = 0;
}
@@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sig, current->comm, current->pid, frame, __frame->pc,
frame->pretcode);
#endif
-
return 0;
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
-
} /* end setup_rt_frame() */
/*****************************************************************************/
/*
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka)
+static void handle_signal(struct ksignal *ksig)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -378,7 +357,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
__frame->gr8 = -EINTR;
break;
}
@@ -392,16 +371,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
}
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset);
else
- ret = setup_frame(sig, ka, oldset);
-
- if (ret)
- return;
+ ret = setup_frame(ksig, oldset);
- signal_delivered(sig, info, ka, __frame,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */
/*****************************************************************************/
@@ -412,13 +387,10 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
*/
static void do_signal(void)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
- signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
- if (signr > 0) {
- handle_signal(signr, &info, &ka);
+ if (get_signal(&ksig)) {
+ handle_signal(&ksig);
return;
}
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 0fd6138f6203..4dc89d1f9c48 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -23,7 +23,6 @@ config HEXAGON
select GENERIC_IOMAP
select GENERIC_SMP_IDLE_THREAD
select STACKTRACE_SUPPORT
- select KTIME_SCALAR
select GENERIC_CLOCKEVENTS
select GENERIC_CLOCKEVENTS_BROADCAST
select MODULES_USE_ELF_RELA
diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h
index f4ca594fdf8c..263511719a4a 100644
--- a/arch/hexagon/include/asm/cache.h
+++ b/arch/hexagon/include/asm/cache.h
@@ -28,7 +28,7 @@
#define __cacheline_aligned __aligned(L1_CACHE_BYTES)
#define ____cacheline_aligned __aligned(L1_CACHE_BYTES)
-/* See http://kerneltrap.org/node/15100 */
+/* See http://lwn.net/Articles/262554/ */
#define __read_mostly
#endif
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index 45a825402f63..d8501137c8d0 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -56,6 +56,7 @@ struct thread_struct {
}
#define cpu_relax() __vmyield()
+#define cpu_relax_lowlatency() cpu_relax()
/*
* Decides where the kernel will search for a free chunk of vm space during
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index d7c73874b515..eadd70e47e7e 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -36,18 +36,10 @@ struct rt_sigframe {
struct ucontext uc;
};
-static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size)
{
- unsigned long sp = regs->r29;
-
- /* check if we would overflow the alt stack */
- if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
- return (void __user __force *)-1UL;
-
- /* Switch to signal stack if appropriate */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ unsigned long sp = sigsp(regs->r29, ksig);
return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
}
@@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_regs *regs,
/*
* Setup signal stack frame with siginfo structure
*/
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
int err = 0;
struct rt_sigframe __user *frame;
struct hexagon_vdso *vdso = current->mm->context.vdso;
- frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+ frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
- goto sigsegv;
+ return -EFAULT;
- if (copy_siginfo_to_user(&frame->info, info))
- goto sigsegv;
+ if (copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
/* The on-stack signal trampoline is no longer executed;
* however, the libgcc signal frame unwinding code checks for
@@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
if (err)
- goto sigsegv;
+ return -EFAULT;
/* Load r0/r1 pair with signumber/siginfo pointer... */
regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
- | (unsigned long long)signr;
+ | (unsigned long long)ksig->sig;
regs->r02 = (unsigned long) &frame->uc;
regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
pt_psp(regs) = (unsigned long) frame;
- pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
+ pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
return 0;
-
-sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
/*
* Setup invocation of signal handler
*/
-static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
+ int ret;
+
/*
* If we're handling a signal that aborted a system call,
* set up the error return value before adding the signal
@@ -173,7 +162,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
regs->r00 = -EINTR;
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r00 = -EINTR;
break;
}
@@ -193,11 +182,9 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
* only set up the rt_frame flavor.
*/
/* If there was an error on setup, no signal was delivered. */
- if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
- return;
+ ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -205,17 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
*/
void do_signal(struct pt_regs *regs)
{
- struct k_sigaction sigact;
- siginfo_t info;
- int signo;
+ struct ksignal ksig;
if (!user_mode(regs))
return;
- signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
-
- if (signo > 0) {
- handle_signal(signo, &info, &sigact, regs);
+ if (get_signal(&ksig)) {
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 2f3abcf8f6bc..64aefb76bd69 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -10,6 +10,7 @@ config IA64
select ARCH_MIGHT_HAVE_PC_SERIO
select PCI if (!IA64_HP_SIM)
select ACPI if (!IA64_HP_SIM)
+ select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
select PM if (!IA64_HP_SIM)
select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
@@ -27,6 +28,7 @@ config IA64
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
select HAVE_VIRT_CPU_ACCOUNTING
+ select ARCH_HAS_SG_CHAIN
select VIRT_TO_BUS
select ARCH_DISCARD_MEMBLOCK
select GENERIC_IRQ_PROBE
@@ -547,6 +549,8 @@ source "drivers/sn/Kconfig"
config KEXEC
bool "kexec system call"
depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index f37238f45bcd..5441b14994fc 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -76,7 +76,7 @@ vmlinux.gz: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
unwcheck: vmlinux
- -$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $<
+ -$(Q)READELF=$(READELF) $(PYTHON) $(srctree)/arch/ia64/scripts/unwcheck.py $<
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 0da4aa2602ae..e8317d2d6c8d 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -5,5 +5,6 @@ generic-y += hash.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
generic-y += vtime.h
diff --git a/arch/ia64/include/asm/acenv.h b/arch/ia64/include/asm/acenv.h
index 3f9eaeec9873..35ff13afbf34 100644
--- a/arch/ia64/include/asm/acenv.h
+++ b/arch/ia64/include/asm/acenv.h
@@ -19,8 +19,6 @@
/* Asm macros */
-#ifdef CONFIG_ACPI
-
static inline int
ia64_acpi_acquire_global_lock(unsigned int *lock)
{
@@ -51,6 +49,4 @@ ia64_acpi_release_global_lock(unsigned int *lock)
#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \
((Acq) = ia64_acpi_release_global_lock(&facs->global_lock))
-#endif
-
#endif /* _ASM_IA64_ACENV_H */
diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h
index 75dc59a793d6..a1d91ab4c5ef 100644
--- a/arch/ia64/include/asm/acpi.h
+++ b/arch/ia64/include/asm/acpi.h
@@ -40,6 +40,11 @@ extern int acpi_lapic;
#define acpi_noirq 0 /* ACPI always enabled on IA64 */
#define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
#define acpi_strict 1 /* no ACPI spec workarounds on IA64 */
+
+static inline bool acpi_has_cpu_in_madt(void)
+{
+ return !!acpi_lapic;
+}
#endif
#define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
static inline void disable_acpi(void) { }
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 0d2bcb37ec35..bee0acd52f7e 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -426,6 +426,7 @@ extern void iounmap (volatile void __iomem *addr);
extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
#define early_memremap(phys_addr, size) early_ioremap(phys_addr, size)
extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
+#define early_memunmap(addr, size) early_iounmap(addr, size)
static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
{
return ioremap(phys_addr, size);
diff --git a/arch/ia64/include/asm/page.h b/arch/ia64/include/asm/page.h
index f1e1b2e3cdb3..1f1bf144fe62 100644
--- a/arch/ia64/include/asm/page.h
+++ b/arch/ia64/include/asm/page.h
@@ -231,4 +231,6 @@ get_order (unsigned long size)
#define PERCPU_ADDR (-PERCPU_PAGE_SIZE)
#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE)
+#define __HAVE_ARCH_GATE_AREA 1
+
#endif /* _ASM_IA64_PAGE_H */
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index efd1b927ccb7..c7367130ab14 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -548,6 +548,7 @@ ia64_eoi (void)
}
#define cpu_relax() ia64_hint(ia64_hint_pause)
+#define cpu_relax_lowlatency() cpu_relax()
static inline int
ia64_get_irr(unsigned int vector)
diff --git a/arch/ia64/include/asm/scatterlist.h b/arch/ia64/include/asm/scatterlist.h
deleted file mode 100644
index 08fd93bff1db..000000000000
--- a/arch/ia64/include/asm/scatterlist.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_IA64_SCATTERLIST_H
-#define _ASM_IA64_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_IA64_SCATTERLIST_H */
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index fb13dc5e8f8c..4254f5d3218c 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -11,7 +11,7 @@
-#define NR_syscalls 315 /* length of syscall table */
+#define NR_syscalls 316 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 7de0a2d65da4..99801c3be914 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -328,5 +328,6 @@
#define __NR_sched_setattr 1336
#define __NR_sched_getattr 1337
#define __NR_renameat2 1338
+#define __NR_getrandom 1339
#endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index ba3d03503e84..4c13837a9269 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1776,6 +1776,7 @@ sys_call_table:
data8 sys_sched_setattr
data8 sys_sched_getattr
data8 sys_renameat2
+ data8 sys_getrandom
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 55d4ba47a907..deed6fa96bb0 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -662,7 +662,7 @@ void
machine_restart (char *restart_cmd)
{
(void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
- (*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
+ efi_reboot(REBOOT_WARM, NULL);
}
void
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 33cab9a8adff..6d92170be457 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -309,12 +309,11 @@ force_sigsegv_info (int sig, void __user *addr)
si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
si.si_addr = addr;
force_sig_info(SIGSEGV, &si, current);
- return 0;
+ return 1;
}
static long
-setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
- struct sigscratch *scr)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
{
extern char __kernel_sigtramp[];
unsigned long tramp_addr, new_rbs = 0, new_sp;
@@ -323,7 +322,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
new_sp = scr->pt.r12;
tramp_addr = (unsigned long) __kernel_sigtramp;
- if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (ksig->ka.sa.sa_flags & SA_ONSTACK) {
int onstack = sas_ss_flags(new_sp);
if (onstack == 0) {
@@ -347,29 +346,29 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
*/
check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
if (!likely(on_sig_stack(check_sp)))
- return force_sigsegv_info(sig, (void __user *)
+ return force_sigsegv_info(ksig->sig, (void __user *)
check_sp);
}
}
frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- return force_sigsegv_info(sig, frame);
+ return force_sigsegv_info(ksig->sig, frame);
- err = __put_user(sig, &frame->arg0);
+ err = __put_user(ksig->sig, &frame->arg0);
err |= __put_user(&frame->info, &frame->arg1);
err |= __put_user(&frame->sc, &frame->arg2);
err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
- err |= __put_user(ka->sa.sa_handler, &frame->handler);
+ err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
err |= setup_sigcontext(&frame->sc, set, scr);
if (unlikely(err))
- return force_sigsegv_info(sig, frame);
+ return force_sigsegv_info(ksig->sig, frame);
scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */
scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
@@ -394,22 +393,20 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n",
- current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
+ current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
#endif
- return 1;
+ return 0;
}
static long
-handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- struct sigscratch *scr)
+handle_signal (struct ksignal *ksig, struct sigscratch *scr)
{
- if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
- return 0;
+ int ret = setup_frame(ksig, sigmask_to_save(), scr);
- signal_delivered(sig, info, ka, &scr->pt,
- test_thread_flag(TIF_SINGLESTEP));
+ if (!ret)
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
- return 1;
+ return ret;
}
/*
@@ -419,17 +416,16 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
void
ia64_do_signal (struct sigscratch *scr, long in_syscall)
{
- struct k_sigaction ka;
- siginfo_t info;
long restart = in_syscall;
long errno = scr->pt.r8;
+ struct ksignal ksig;
/*
* This only loops in the rare cases of handle_signal() failing, in which case we
* need to push through a forced SIGSEGV.
*/
while (1) {
- int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL);
+ get_signal(&ksig);
/*
* get_signal_to_deliver() may have run a debugger (via notify_parent())
@@ -446,7 +442,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
*/
restart = 0;
- if (signr <= 0)
+ if (ksig.sig <= 0)
break;
if (unlikely(restart)) {
@@ -458,7 +454,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
break;
case ERESTARTSYS:
- if ((ka.sa.sa_flags & SA_RESTART) == 0) {
+ if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
scr->pt.r8 = EINTR;
/* note: scr->pt.r10 is already -1 */
break;
@@ -473,7 +469,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV...
*/
- if (handle_signal(signr, &ka, &info, scr))
+ if (handle_signal(&ksig, scr))
return;
}
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 71c52bc7c28d..9a0104a38cd3 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -384,21 +384,6 @@ static struct irqaction timer_irqaction = {
.name = "timer"
};
-static struct platform_device rtc_efi_dev = {
- .name = "rtc-efi",
- .id = -1,
-};
-
-static int __init rtc_init(void)
-{
- if (platform_device_register(&rtc_efi_dev) < 0)
- printk(KERN_ERR "unable to register rtc device...\n");
-
- /* not necessarily an error */
- return 0;
-}
-module_init(rtc_init);
-
void read_persistent_clock(struct timespec *ts)
{
efi_gettimeofday(ts);
@@ -441,7 +426,7 @@ void update_vsyscall_tz(void)
}
void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
- struct clocksource *c, u32 mult)
+ struct clocksource *c, u32 mult, cycle_t cycle_last)
{
write_seqcount_begin(&fsyscall_gtod_data.seq);
@@ -450,7 +435,7 @@ void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
fsyscall_gtod_data.clk_mult = mult;
fsyscall_gtod_data.clk_shift = c->shift;
fsyscall_gtod_data.clk_fsys_mmio = c->archdata.fsys_mmio;
- fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
+ fsyscall_gtod_data.clk_cycle_last = cycle_last;
/* copy kernel time structures */
fsyscall_gtod_data.wall_time.tv_sec = wall->tv_sec;
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index 990b86420cc6..3d50ea955c4c 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -25,6 +25,7 @@ config KVM
select PREEMPT_NOTIFIERS
select ANON_INODES
select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
select HAVE_KVM_IRQ_ROUTING
select KVM_APIC_ARCHITECTURE
select KVM_MMIO
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 6a4309bb821a..0729ba6acddf 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -190,7 +190,7 @@ void kvm_arch_check_processor_compat(void *rtn)
*(int *)rtn = 0;
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 25c350264a41..6b3345758d3e 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -278,6 +278,37 @@ setup_gate (void)
ia64_patch_gate();
}
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+ gate_vma.vm_mm = NULL;
+ gate_vma.vm_start = FIXADDR_USER_START;
+ gate_vma.vm_end = FIXADDR_USER_END;
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+ gate_vma.vm_page_prot = __P101;
+
+ return 0;
+}
+__initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+ return &gate_vma;
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+ if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END))
+ return 1;
+ return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+ return in_gate_area_no_mm(addr);
+}
+
void ia64_mmu_init(void *my_cpu_data)
{
unsigned long pta, impl_va_bits;
@@ -631,7 +662,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
pgdat = NODE_DATA(nid);
- zone = pgdat->node_zones + ZONE_NORMAL;
+ zone = pgdat->node_zones +
+ zone_for_memory(nid, start, size, ZONE_NORMAL);
ret = __add_pages(nid, zone, start_pfn, nr_pages);
if (ret)
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c
index 1fe9aa5068ea..ec73b2cf912a 100644
--- a/arch/ia64/pci/fixup.c
+++ b/arch/ia64/pci/fixup.c
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/vgaarb.h>
+#include <linux/screen_info.h>
#include <asm/machvec.h>
@@ -37,6 +38,27 @@ static void pci_fixup_video(struct pci_dev *pdev)
return;
/* Maybe, this machine supports legacy memory map. */
+ if (!vga_default_device()) {
+ resource_size_t start, end;
+ int i;
+
+ /* Does firmware framebuffer belong to us? */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+ continue;
+
+ start = pci_resource_start(pdev, i);
+ end = pci_resource_end(pdev, i);
+
+ if (!start || !end)
+ continue;
+
+ if (screen_info.lfb_base >= start &&
+ (screen_info.lfb_base + screen_info.lfb_size) < end)
+ vga_set_default_device(pdev);
+ }
+ }
+
/* Is VGA routed to us? */
bus = pdev->bus;
while (bus) {
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index cad775a1a157..b2eb48490754 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -114,7 +114,7 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
if (mode & BTE_USE_ANY) {
nasid_to_try[1] = my_nasid;
} else {
- nasid_to_try[1] = (int)NULL;
+ nasid_to_try[1] = 0;
}
} else {
/* try local then remote */
@@ -122,7 +122,7 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
if (mode & BTE_USE_ANY) {
nasid_to_try[1] = NASID_GET(dest);
} else {
- nasid_to_try[1] = (int)NULL;
+ nasid_to_try[1] = 0;
}
}
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 53b01b8e2f19..36182c84363c 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -579,7 +579,7 @@ void sn_cpu_init(void)
(sn_prom_type == 1) ? "real" : "fake");
}
- memset(pda, 0, sizeof(pda));
+ memset(pda, 0, sizeof(*pda));
if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2,
&sn_hub_info->nasid_bitmask,
&sn_hub_info->nasid_shift,
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 67779a74b62d..accc10a3dc78 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += module.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index 5767367550c6..9f8fd9bef70f 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -133,5 +133,6 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.sp)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#endif /* _ASM_M32R_PROCESSOR_H */
diff --git a/arch/m32r/include/asm/scatterlist.h b/arch/m32r/include/asm/scatterlist.h
deleted file mode 100644
index 7370b8b6243e..000000000000
--- a/arch/m32r/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_M32R_SCATTERLIST_H
-#define _ASM_M32R_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_M32R_SCATTERLIST_H */
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index d503568cb753..95408b8f130a 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -162,28 +162,22 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* Determine which stack to use..
*/
static inline void __user *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
{
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (sas_ss_flags(sp) == 0)
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
-
- return (void __user *)((sp - frame_size) & -8ul);
+ return (void __user *)((sigsp(sp, ksig) - frame_size) & -8ul);
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
int err = 0;
- int signal;
+ int signal, sig = ksig->sig;
- frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+ frame = get_sigframe(ksig, regs->spu, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -193,13 +187,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(signal, &frame->sig);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -208,17 +202,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. */
- regs->lr = (unsigned long)ka->sa.sa_restorer;
+ regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
/* Set up registers for signal handler */
regs->spu = (unsigned long)frame;
regs->r0 = signal; /* Arg for signal handler */
regs->r1 = (unsigned long)&frame->info;
regs->r2 = (unsigned long)&frame->uc;
- regs->bpc = (unsigned long)ka->sa.sa_handler;
+ regs->bpc = (unsigned long)ksig->ka.sa.sa_handler;
set_fs(USER_DS);
@@ -228,10 +222,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
static int prev_insn(struct pt_regs *regs)
@@ -252,9 +242,10 @@ static int prev_insn(struct pt_regs *regs)
*/
static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
+ int ret;
+
/* Are we from a system call? */
if (regs->syscall_nr >= 0) {
/* If so, check system call restarting.. */
@@ -265,7 +256,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r0 = -EINTR;
break;
}
@@ -278,10 +269,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
}
/* Set up the stack frame */
- if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
- return;
+ ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -291,9 +281,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/
static void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which
@@ -304,8 +292,7 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
@@ -313,7 +300,7 @@ static void do_signal(struct pt_regs *regs)
*/
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 87b7c7581b1d..3ff8c9a25335 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -91,6 +91,8 @@ config MMU_SUN3
config KEXEC
bool "kexec system call"
depends on M68KCLASSIC
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index d7eac833a94f..399df883c8bb 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -257,7 +257,6 @@ CONFIG_BLK_DEV_GAYLE=y
CONFIG_BLK_DEV_BUDDHA=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 650ee75de6cd..be16740c0749 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 3142e69342fa..391e185d73be 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_FALCON_IDE=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 0daa8a172f30..d0e705d1a063 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 88af78f7bad9..fdc7e9672249 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -244,7 +244,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 66f915574a85..3d345641d5a0 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -251,7 +251,6 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_MAC_IDE=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 5eaa49924fa6..59aa42096000 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -273,7 +273,6 @@ CONFIG_BLK_DEV_MAC_IDE=y
CONFIG_BLK_DEV_Q40IDE=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 324d0b4d8351..066b24af095e 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -241,7 +241,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index f0cb4338952e..9326ea664a5b 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -242,7 +242,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index d6cf0880c463..d7d1101e31b5 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -249,7 +249,6 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_Q40IDE=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index f4e88d1c7472..98522e8fb852 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 49f4032c1ad6..5128a8c3f4e3 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -239,7 +239,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h
index c527fc2ecf82..11859b86b1f9 100644
--- a/arch/m68k/include/asm/pgtable_no.h
+++ b/arch/m68k/include/asm/pgtable_no.h
@@ -46,11 +46,6 @@ static inline int pte_file(pte_t pte) { return 0; }
#define ZERO_PAGE(vaddr) (virt_to_page(0))
/*
- * These would be in other places but having them here reduces the diffs.
- */
-extern unsigned int kobjsize(const void *objp);
-
-/*
* No page table caches to initialise.
*/
#define pgtable_cache_init() do { } while (0)
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index b0768a657920..20dda1d4b860 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -176,5 +176,6 @@ unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) ((tsk)->thread.esp0))
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#endif
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
index f868506e3350..0931388de47f 100644
--- a/arch/m68k/include/asm/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
@@ -12,10 +12,6 @@
#include <asm/tlb.h>
-/* FIXME - when we get this compiling */
-/* erm, now that it's compiling, what do we do with it? */
-#define _KERNPG_TABLE 0
-
extern const char bad_pmd_string[];
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
diff --git a/arch/m68k/include/asm/virtconvert.h b/arch/m68k/include/asm/virtconvert.h
index f35229b8651d..b8a82fb1cef8 100644
--- a/arch/m68k/include/asm/virtconvert.h
+++ b/arch/m68k/include/asm/virtconvert.h
@@ -26,16 +26,12 @@ static inline void *phys_to_virt(unsigned long address)
}
/* Permanent address of a page. */
-#ifdef CONFIG_MMU
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#if defined(CONFIG_MMU) && defined(CONFIG_SINGLE_MEMORY_CHUNK)
#define page_to_phys(page) \
__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
#else
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#endif
-#else
-#define page_to_phys(page) (((page) - mem_map) << PAGE_SHIFT)
-#endif
/*
* IO bus memory addresses are 1:1 with the physical address,
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 57fd286e4b0b..967a8b7e1527 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -835,38 +835,30 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
}
static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, size_t frame_size)
{
- unsigned long usp;
-
- /* Default to using normal stack. */
- usp = rdusp();
+ unsigned long usp = sigsp(rdusp(), ksig);
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!sas_ss_flags(usp))
- usp = current->sas_ss_sp + current->sas_ss_size;
- }
return (void __user *)((usp - frame_size) & -8UL);
}
-static int setup_frame (int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct sigframe __user *frame;
int fsize = frame_extra_sizes(regs->format);
struct sigcontext context;
- int err = 0;
+ int err = 0, sig = ksig->sig;
if (fsize < 0) {
#ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n",
regs->format);
#endif
- goto give_sigsegv;
+ return -EFAULT;
}
- frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
+ frame = get_sigframe(ksig, sizeof(*frame) + fsize);
if (fsize)
err |= copy_to_user (frame + 1, regs + 1, fsize);
@@ -899,7 +891,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
#endif
if (err)
- goto give_sigsegv;
+ return -EFAULT;
push_cache ((unsigned long) &frame->retcode);
@@ -908,7 +900,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
* to destroy is successfully copied to sigframe.
*/
wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
adjustformat(regs);
/*
@@ -934,28 +926,24 @@ static int setup_frame (int sig, struct k_sigaction *ka,
tregs->sr = regs->sr;
}
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return err;
}
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
int fsize = frame_extra_sizes(regs->format);
- int err = 0;
+ int err = 0, sig = ksig->sig;
if (fsize < 0) {
#ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n",
regs->format);
#endif
- goto give_sigsegv;
+ return -EFAULT;
}
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, sizeof(*frame));
if (fsize)
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
@@ -968,7 +956,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
&frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -996,7 +984,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
#endif /* CONFIG_MMU */
if (err)
- goto give_sigsegv;
+ return -EFAULT;
push_cache ((unsigned long) &frame->retcode);
@@ -1005,7 +993,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
* to destroy is successfully copied to sigframe.
*/
wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
adjustformat(regs);
/*
@@ -1031,10 +1019,6 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
tregs->sr = regs->sr;
}
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return err;
}
static inline void
@@ -1074,26 +1058,22 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
* OK, we're invoking a handler
*/
static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
- struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int err;
/* are we from a system call? */
if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */
- handle_restart(regs, ka, 1);
+ handle_restart(regs, &ksig->ka, 1);
/* set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- err = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ err = setup_rt_frame(ksig, oldset, regs);
else
- err = setup_frame(sig, ka, oldset, regs);
-
- if (err)
- return;
+ err = setup_frame(ksig, oldset, regs);
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(err, ksig, 0);
if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000;
@@ -1108,16 +1088,13 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
*/
static void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- struct k_sigaction ka;
- int signr;
+ struct ksignal ksig;
current->thread.esp0 = (unsigned long) regs;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index 499b7610eaaf..0b389a81c43a 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -13,7 +13,6 @@ config METAG
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h
index a8a37477c66e..881071c07942 100644
--- a/arch/metag/include/asm/processor.h
+++ b/arch/metag/include/asm/processor.h
@@ -155,6 +155,7 @@ unsigned long get_wchan(struct task_struct *p);
#define user_stack_pointer(regs) ((regs)->ctx.AX[0].U0)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
extern void setup_priv(void);
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c
index 0a2385fa2a1d..04b7d4f8429a 100644
--- a/arch/metag/kernel/cachepart.c
+++ b/arch/metag/kernel/cachepart.c
@@ -55,7 +55,7 @@ unsigned int get_global_icache_size(void)
return (get_icache_size() * ((temp >> SYSC_xCPARTG_AND_S) + 1)) >> 4;
}
-static unsigned int get_thread_cache_size(unsigned int cache, int thread_id)
+static int get_thread_cache_size(unsigned int cache, int thread_id)
{
unsigned int cache_size;
unsigned int t_cache_part;
@@ -94,7 +94,7 @@ static unsigned int get_thread_cache_size(unsigned int cache, int thread_id)
void check_for_cache_aliasing(int thread_id)
{
- unsigned int thread_cache_size;
+ int thread_cache_size;
unsigned int cache_type;
for (cache_type = ICACHE; cache_type <= DCACHE; cache_type++) {
thread_cache_size =
diff --git a/arch/metag/kernel/ftrace_stub.S b/arch/metag/kernel/ftrace_stub.S
index e70bff745bdd..3acc288217c0 100644
--- a/arch/metag/kernel/ftrace_stub.S
+++ b/arch/metag/kernel/ftrace_stub.S
@@ -16,13 +16,6 @@ _mcount_wrapper:
.global _ftrace_caller
.type _ftrace_caller,function
_ftrace_caller:
- MOVT D0Re0,#HI(_function_trace_stop)
- ADD D0Re0,D0Re0,#LO(_function_trace_stop)
- GETD D0Re0,[D0Re0]
- CMP D0Re0,#0
- BEQ $Lcall_stub
- MOV PC,D0.4
-$Lcall_stub:
MSETL [A0StP], D0Ar6, D0Ar4, D0Ar2, D0.4
MOV D1Ar1, D0.4
MOV D0Ar2, D1RtP
@@ -42,13 +35,6 @@ _ftrace_call:
.global _mcount_wrapper
.type _mcount_wrapper,function
_mcount_wrapper:
- MOVT D0Re0,#HI(_function_trace_stop)
- ADD D0Re0,D0Re0,#LO(_function_trace_stop)
- GETD D0Re0,[D0Re0]
- CMP D0Re0,#0
- BEQ $Lcall_mcount
- MOV PC,D0.4
-$Lcall_mcount:
MSETL [A0StP], D0Ar6, D0Ar4, D0Ar2, D0.4
MOV D1Ar1, D0.4
MOV D0Ar2, D1RtP
diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c
index 5cc4d4dcf3cf..02c08737f6aa 100644
--- a/arch/metag/kernel/perf/perf_event.c
+++ b/arch/metag/kernel/perf/perf_event.c
@@ -568,16 +568,6 @@ static int _hw_perf_event_init(struct perf_event *event)
return -EINVAL;
/*
- * Early cores have "limited" counters - they have no overflow
- * interrupts - and so are unable to do sampling without extra work
- * and timer assistance.
- */
- if (metag_pmu->max_period == 0) {
- if (hwc->sample_period)
- return -EINVAL;
- }
-
- /*
* Don't assign an index until the event is placed into the hardware.
* -1 signifies that we're still deciding where to put it. On SMP
* systems each core has its own set of counters, so we can't do any
@@ -866,6 +856,15 @@ static int __init init_hw_perf_events(void)
pr_info("enabled with %s PMU driver, %d counters available\n",
metag_pmu->name, metag_pmu->max_events);
+ /*
+ * Early cores have "limited" counters - they have no overflow
+ * interrupts - and so are unable to do sampling without extra work
+ * and timer assistance.
+ */
+ if (metag_pmu->max_period == 0) {
+ metag_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+ }
+
/* Initialise the active events and reservation mutex */
atomic_set(&metag_pmu->active_events, 0);
mutex_init(&metag_pmu->reserve_mutex);
diff --git a/arch/metag/kernel/signal.c b/arch/metag/kernel/signal.c
index b9e4a82d2bd4..0d100d5c1407 100644
--- a/arch/metag/kernel/signal.c
+++ b/arch/metag/kernel/signal.c
@@ -140,13 +140,9 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
/*
* Determine which stack to use..
*/
-static void __user *get_sigframe(struct k_sigaction *ka, unsigned long sp,
- size_t frame_size)
+static void __user *get_sigframe(struct ksignal *ksig, unsigned long sp)
{
- /* Meta stacks grows upwards */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
- sp = current->sas_ss_sp;
-
+ sp = sigsp(sp, ksig);
sp = (sp + 7) & ~7; /* 8byte align stack */
return (void __user *)sp;
@@ -159,7 +155,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
int err;
unsigned long code;
- frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame));
+ frame = get_sigframe(ksig, regs->REG_SP);
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT;
diff --git a/arch/metag/mm/hugetlbpage.c b/arch/metag/mm/hugetlbpage.c
index 3c52fa6d0f8e..3c32075d2945 100644
--- a/arch/metag/mm/hugetlbpage.c
+++ b/arch/metag/mm/hugetlbpage.c
@@ -173,7 +173,7 @@ new_search:
mm->context.part_huge = 0;
return addr;
}
- if (vma && (vma->vm_flags & MAP_HUGETLB)) {
+ if (vma->vm_flags & MAP_HUGETLB) {
/* space after a huge vma in 2nd level page table? */
if (vma->vm_end & HUGEPT_MASK) {
after_huge = 1;
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 9ae08541e30d..40e1c1dd0e24 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -22,7 +22,6 @@ config MICROBLAZE
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_GRAPH_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_FUNCTION_TRACER
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 35b3ecaf25d5..27a3acda6c19 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -7,5 +7,6 @@ generic-y += exec.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += syscalls.h
generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/delay.h b/arch/microblaze/include/asm/delay.h
index 66fc24c24238..60cb39deb533 100644
--- a/arch/microblaze/include/asm/delay.h
+++ b/arch/microblaze/include/asm/delay.h
@@ -61,13 +61,29 @@ extern inline void __udelay(unsigned int x)
extern void __bad_udelay(void); /* deliberately undefined */
extern void __bad_ndelay(void); /* deliberately undefined */
-#define udelay(n) (__builtin_constant_p(n) ? \
- ((n) > __MAX_UDELAY ? __bad_udelay() : __udelay((n) * (19 * HZ))) : \
- __udelay((n) * (19 * HZ)))
+#define udelay(n) \
+ ({ \
+ if (__builtin_constant_p(n)) { \
+ if ((n) / __MAX_UDELAY >= 1) \
+ __bad_udelay(); \
+ else \
+ __udelay((n) * (19 * HZ)); \
+ } else { \
+ __udelay((n) * (19 * HZ)); \
+ } \
+ })
-#define ndelay(n) (__builtin_constant_p(n) ? \
- ((n) > __MAX_NDELAY ? __bad_ndelay() : __udelay((n) * HZ)) : \
- __udelay((n) * HZ))
+#define ndelay(n) \
+ ({ \
+ if (__builtin_constant_p(n)) { \
+ if ((n) / __MAX_NDELAY >= 1) \
+ __bad_ndelay(); \
+ else \
+ __udelay((n) * HZ); \
+ } else { \
+ __udelay((n) * HZ); \
+ } \
+ })
#define muldiv(a, b, c) (((a)*(b))/(c))
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 9d31b057c355..497a988d79c2 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -22,6 +22,7 @@
extern const struct seq_operations cpuinfo_op;
# define cpu_relax() barrier()
+# define cpu_relax_lowlatency() cpu_relax()
#define task_pt_regs(tsk) \
(((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h
deleted file mode 100644
index 35d786fe93ae..000000000000
--- a/arch/microblaze/include/asm/scatterlist.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/scatterlist.h>
diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h
index 8d0791b49b31..4e1ddc930a68 100644
--- a/arch/microblaze/include/uapi/asm/unistd.h
+++ b/arch/microblaze/include/uapi/asm/unistd.h
@@ -398,5 +398,6 @@
#define __NR_finit_module 380
#define __NR_sched_setattr 381
#define __NR_sched_getattr 382
+#define __NR_renameat2 383
#endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c
index bbcd2533766c..fc7b48a52cd5 100644
--- a/arch/microblaze/kernel/ftrace.c
+++ b/arch/microblaze/kernel/ftrace.c
@@ -27,6 +27,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
unsigned long return_hooker = (unsigned long)
&return_to_handler;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S
index fc1e1322ce4c..fed9da5de8c4 100644
--- a/arch/microblaze/kernel/mcount.S
+++ b/arch/microblaze/kernel/mcount.S
@@ -91,11 +91,6 @@ ENTRY(ftrace_caller)
#endif /* CONFIG_DYNAMIC_FTRACE */
SAVE_REGS
swi r15, r1, 0;
- /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */
- lwi r5, r0, function_trace_stop;
- bneid r5, end;
- nop;
- /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#ifndef CONFIG_DYNAMIC_FTRACE
lwi r5, r0, ftrace_graph_return;
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 49a07a4d76d0..8955a3829cf0 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -145,22 +145,19 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* Determine which stack to use..
*/
static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
{
/* Default to using normal stack */
- unsigned long sp = regs->r1;
-
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ unsigned long sp = sigsp(regs->r1, ksig);
return (void __user *)((sp - frame_size) & -8UL);
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
unsigned long address = 0;
#ifdef CONFIG_MMU
@@ -168,10 +165,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
pte_t *ptep;
#endif
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -179,8 +176,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- if (info)
- err |= copy_siginfo_to_user(&frame->info, info);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -227,7 +224,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
flush_dcache_range(address, address + 8);
#endif
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->r1 = (unsigned long) frame;
@@ -237,7 +234,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
/* Offset to handle microblaze rtid r14, 0 */
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
set_fs(USER_DS);
@@ -247,10 +244,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/* Handle restarting system calls */
@@ -283,23 +276,15 @@ do_restart:
*/
static void
-handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
- else
- ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
+ ret = setup_rt_frame(ksig, oldset, regs);
- if (ret)
- return;
-
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -313,21 +298,19 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
static void do_signal(struct pt_regs *regs, int in_syscall)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
+
#ifdef DEBUG_SIG
pr_info("do signal: %p %d\n", regs, in_syscall);
pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
regs->r12, current_thread_info()->flags);
#endif
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
if (in_syscall)
- handle_restart(regs, &ka, 1);
- handle_signal(signr, &ka, &info, regs);
+ handle_restart(regs, &ksig.ka, 1);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 329dfbad810b..1a23d5d5480c 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -380,6 +380,7 @@ ENTRY(sys_call_table)
.long sys_process_vm_readv
.long sys_process_vm_writev
.long sys_kcmp
- .long sys_finit_module
+ .long sys_finit_module /* 380 */
.long sys_sched_setattr
.long sys_sched_getattr
+ .long sys_renameat2
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
index 844960e8ae18..70c7ae6a3fb5 100644
--- a/arch/microblaze/lib/Makefile
+++ b/arch/microblaze/lib/Makefile
@@ -18,14 +18,6 @@ endif
lib-y += uaccess_old.o
-lib-y += ashldi3.o
-lib-y += ashrdi3.o
-lib-y += cmpdi2.o
-lib-y += divsi3.o
-lib-y += lshrdi3.o
-lib-y += modsi3.o
-lib-y += muldi3.o
-lib-y += mulsi3.o
-lib-y += ucmpdi2.o
-lib-y += udivsi3.o
-lib-y += umodsi3.o
+# libgcc-style stuff needed in the kernel
+obj-y += ashldi3.o ashrdi3.o cmpdi2.o divsi3.o lshrdi3.o modsi3.o
+obj-y += muldi3.o mulsi3.o ucmpdi2.o udivsi3.o umodsi3.o
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4e238e6e661c..df51e78a72cc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,7 +15,6 @@ config MIPS
select HAVE_BPF_JIT if !CPU_MICROMIPS
select ARCH_HAVE_CUSTOM_GPIO_H
select HAVE_FUNCTION_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_C_RECORDMCOUNT
@@ -72,6 +71,7 @@ config MIPS_ALCHEMY
select SYS_SUPPORTS_APM_EMULATION
select ARCH_REQUIRE_GPIOLIB
select SYS_SUPPORTS_ZBOOT
+ select COMMON_CLK
config AR7
bool "Texas Instruments AR7"
@@ -130,6 +130,8 @@ config BCM47XX
select SYS_SUPPORTS_MIPS16
select SYS_HAS_EARLY_PRINTK
select USE_GENERIC_EARLY_PRINTK_8250
+ select GPIOLIB
+ select LEDS_GPIO_REGISTER
help
Support for BCM47XX based boards
@@ -138,6 +140,7 @@ config BCM63XX
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
+ select SYNC_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
@@ -2057,6 +2060,7 @@ config MIPS_CPS
support is unavailable.
config MIPS_CPS_PM
+ select MIPS_CPC
bool
config MIPS_GIC_IPI
@@ -2110,9 +2114,9 @@ config CPU_MICROMIPS
microMIPS ISA
config CPU_HAS_MSA
- bool "Support for the MIPS SIMD Architecture"
+ bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
depends on CPU_SUPPORTS_MSA
- default y
+ depends on 64BIT || MIPS_O32_FP64_SUPPORT
help
MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
and a set of SIMD instructions to operate on them. When this option
@@ -2392,6 +2396,8 @@ source "kernel/Kconfig.preempt"
config KEXEC
bool "Kexec system call"
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index a8521de14791..9336509f47ad 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -151,8 +151,10 @@ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
-Wa,--trap
cflags-$(CONFIG_CPU_RM7000) += $(call cc-option,-march=rm7000,-march=r5000) \
-Wa,--trap
-cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
-Wa,--trap
+cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-mno-mdmx)
+cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-mno-mips3d)
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
-Wa,--trap
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 25a59a23547e..1e3b102389ef 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -85,10 +85,10 @@ void __init board_setup(void)
#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
/* Initialize sys_pinfunc */
- au_writel(SYS_PF_NI2, SYS_PINFUNC);
+ alchemy_wrsys(SYS_PF_NI2, AU1000_SYS_PINFUNC);
/* Initialize GPIO */
- au_writel(~0, KSEG1ADDR(AU1000_SYS_PHYS_ADDR) + SYS_TRIOUTCLR);
+ alchemy_wrsys(~0, AU1000_SYS_TRIOUTCLR);
alchemy_gpio_direction_output(0, 0); /* Disable M66EN (PCI 66MHz) */
alchemy_gpio_direction_output(3, 1); /* Disable PCI CLKRUN# */
alchemy_gpio_direction_output(1, 1); /* Enable EXT_IO3 */
diff --git a/arch/mips/alchemy/board-xxs1500.c b/arch/mips/alchemy/board-xxs1500.c
index 3fb814be0e91..0fc53e08a894 100644
--- a/arch/mips/alchemy/board-xxs1500.c
+++ b/arch/mips/alchemy/board-xxs1500.c
@@ -87,9 +87,9 @@ void __init board_setup(void)
alchemy_gpio2_enable();
/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
- pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
+ pin_func = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PF_UR3;
pin_func |= SYS_PF_UR3;
- au_writel(pin_func, SYS_PINFUNC);
+ alchemy_wrsys(pin_func, AU1000_SYS_PINFUNC);
/* Enable UART */
alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index cb83d8d21aef..f64744f3b59f 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -5,8 +5,8 @@
# Makefile for the Alchemy Au1xx0 CPUs, generic files.
#
-obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
- sleeper.o dma.o dbdma.o vss.o irq.o usb.o
+obj-y += prom.o time.o clock.o platform.o power.o \
+ setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
# optional gpiolib support
ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
new file mode 100644
index 000000000000..d7557cde271a
--- /dev/null
+++ b/arch/mips/alchemy/common/clock.c
@@ -0,0 +1,1094 @@
+/*
+ * Alchemy clocks.
+ *
+ * Exposes all configurable internal clock sources to the clk framework.
+ *
+ * We have:
+ * - Root source, usually 12MHz supplied by an external crystal
+ * - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
+ *
+ * Dividers:
+ * - 6 clock dividers with:
+ * * selectable source [one of the PLLs],
+ * * output divided between [2 .. 512 in steps of 2] (!Au1300)
+ * or [1 .. 256 in steps of 1] (Au1300),
+ * * can be enabled individually.
+ *
+ * - up to 6 "internal" (fixed) consumers which:
+ * * take either AUXPLL or one of the above 6 dividers as input,
+ * * divide this input by 1, 2, or 4 (and 3 on Au1300).
+ * * can be disabled separately.
+ *
+ * Misc clocks:
+ * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
+ * depends on board design and should be set by bootloader, read-only.
+ * - peripheral clock: half the rate of sysbus clock, source for a lot
+ * of peripheral blocks, read-only.
+ * - memory clock: clk rate to main memory chips, depends on board
+ * design and is read-only,
+ * - lrclk: the static bus clock signal for synchronous operation.
+ * depends on board design, must be set by bootloader,
+ * but may be required to correctly configure devices attached to
+ * the static bus. The Au1000/1500/1100 manuals call it LCLK, on
+ * later models it's called RCLK.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* Base clock: 12MHz is the default in all databooks, and I haven't
+ * found any board yet which uses a different rate.
+ */
+#define ALCHEMY_ROOTCLK_RATE 12000000
+
+/*
+ * the internal sources which can be driven by the PLLs and dividers.
+ * Names taken from the databooks, refer to them for more information,
+ * especially which ones are share a clock line.
+ */
+static const char * const alchemy_au1300_intclknames[] = {
+ "lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
+ "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1200_intclknames[] = {
+ "lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1550_intclknames[] = {
+ "usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
+ "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1100_intclknames[] = {
+ "usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1500_intclknames[] = {
+ NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1000_intclknames[] = {
+ "irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
+ "EXTCLK1"
+};
+
+/* aliases for a few on-chip sources which are either shared
+ * or have gone through name changes.
+ */
+static struct clk_aliastable {
+ char *alias;
+ char *base;
+ int cputype;
+} alchemy_clk_aliases[] __initdata = {
+ { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
+ { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
+ { "irda_clk", "usb_clk", ALCHEMY_CPU_AU1100 },
+ { "usbh_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
+ { "usbd_clk", "usb_clk", ALCHEMY_CPU_AU1550 },
+ { "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
+ { "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
+ { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
+ { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
+ { "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+ { "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+ { "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+ { "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+
+ { NULL, NULL, 0 },
+};
+
+#define IOMEM(x) ((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
+
+/* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
+static spinlock_t alchemy_clk_fg0_lock;
+static spinlock_t alchemy_clk_fg1_lock;
+static spinlock_t alchemy_clk_csrc_lock;
+
+/* CPU Core clock *****************************************************/
+
+static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long t;
+
+ /*
+ * On early Au1000, sys_cpupll was write-only. Since these
+ * silicon versions of Au1000 are not sold, we don't bend
+ * over backwards trying to determine the frequency.
+ */
+ if (unlikely(au1xxx_cpu_has_pll_wo()))
+ t = 396000000;
+ else {
+ t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
+ t *= parent_rate;
+ }
+
+ return t;
+}
+
+static struct clk_ops alchemy_clkops_cpu = {
+ .recalc_rate = alchemy_clk_cpu_recalc,
+};
+
+static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
+ int ctype)
+{
+ struct clk_init_data id;
+ struct clk_hw *h;
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return ERR_PTR(-ENOMEM);
+
+ id.name = ALCHEMY_CPU_CLK;
+ id.parent_names = &parent_name;
+ id.num_parents = 1;
+ id.flags = CLK_IS_BASIC;
+ id.ops = &alchemy_clkops_cpu;
+ h->init = &id;
+
+ return clk_register(NULL, h);
+}
+
+/* AUXPLLs ************************************************************/
+
+struct alchemy_auxpll_clk {
+ struct clk_hw hw;
+ unsigned long reg; /* au1300 has also AUXPLL2 */
+ int maxmult; /* max multiplier */
+};
+#define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
+
+static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+
+ return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
+}
+
+static int alchemy_clk_aux_setr(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+ unsigned long d = rate;
+
+ if (rate)
+ d /= parent_rate;
+ else
+ d = 0;
+
+ /* minimum is 84MHz, max is 756-1032 depending on variant */
+ if (((d < 7) && (d != 0)) || (d > a->maxmult))
+ return -EINVAL;
+
+ alchemy_wrsys(d, a->reg);
+ return 0;
+}
+
+static long alchemy_clk_aux_roundr(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+ unsigned long mult;
+
+ if (!rate || !*parent_rate)
+ return 0;
+
+ mult = rate / (*parent_rate);
+
+ if (mult && (mult < 7))
+ mult = 7;
+ if (mult > a->maxmult)
+ mult = a->maxmult;
+
+ return (*parent_rate) * mult;
+}
+
+static struct clk_ops alchemy_clkops_aux = {
+ .recalc_rate = alchemy_clk_aux_recalc,
+ .set_rate = alchemy_clk_aux_setr,
+ .round_rate = alchemy_clk_aux_roundr,
+};
+
+static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
+ char *name, int maxmult,
+ unsigned long reg)
+{
+ struct clk_init_data id;
+ struct clk *c;
+ struct alchemy_auxpll_clk *a;
+
+ a = kzalloc(sizeof(*a), GFP_KERNEL);
+ if (!a)
+ return ERR_PTR(-ENOMEM);
+
+ id.name = name;
+ id.parent_names = &parent_name;
+ id.num_parents = 1;
+ id.flags = CLK_GET_RATE_NOCACHE;
+ id.ops = &alchemy_clkops_aux;
+
+ a->reg = reg;
+ a->maxmult = maxmult;
+ a->hw.init = &id;
+
+ c = clk_register(NULL, &a->hw);
+ if (!IS_ERR(c))
+ clk_register_clkdev(c, name, NULL);
+ else
+ kfree(a);
+
+ return c;
+}
+
+/* sysbus_clk *********************************************************/
+
+static struct clk __init *alchemy_clk_setup_sysbus(const char *pn)
+{
+ unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
+ struct clk *c;
+
+ c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
+ pn, 0, 1, v);
+ if (!IS_ERR(c))
+ clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
+ return c;
+}
+
+/* Peripheral Clock ***************************************************/
+
+static struct clk __init *alchemy_clk_setup_periph(const char *pn)
+{
+ /* Peripheral clock runs at half the rate of sysbus clk */
+ struct clk *c;
+
+ c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
+ pn, 0, 1, 2);
+ if (!IS_ERR(c))
+ clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
+ return c;
+}
+
+/* mem clock **********************************************************/
+
+static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
+{
+ void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
+ unsigned long v;
+ struct clk *c;
+ int div;
+
+ switch (ct) {
+ case ALCHEMY_CPU_AU1550:
+ case ALCHEMY_CPU_AU1200:
+ v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+ div = (v & (1 << 15)) ? 1 : 2;
+ break;
+ case ALCHEMY_CPU_AU1300:
+ v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+ div = (v & (1 << 31)) ? 1 : 2;
+ break;
+ case ALCHEMY_CPU_AU1000:
+ case ALCHEMY_CPU_AU1500:
+ case ALCHEMY_CPU_AU1100:
+ default:
+ div = 2;
+ break;
+ }
+
+ c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
+ 0, 1, div);
+ if (!IS_ERR(c))
+ clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
+ return c;
+}
+
+/* lrclk: external synchronous static bus clock ***********************/
+
+static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
+{
+ /* MEM_STCFG0[15:13] = divisor.
+ * L/RCLK = periph_clk / (divisor + 1)
+ * On Au1000, Au1500, Au1100 it's called LCLK,
+ * on later models it's called RCLK, but it's the same thing.
+ */
+ struct clk *c;
+ unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
+
+ v = (v & 7) + 1;
+ c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
+ pn, 0, 1, v);
+ if (!IS_ERR(c))
+ clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
+ return c;
+}
+
+/* Clock dividers and muxes *******************************************/
+
+/* data for fgen and csrc mux-dividers */
+struct alchemy_fgcs_clk {
+ struct clk_hw hw;
+ spinlock_t *reglock; /* register lock */
+ unsigned long reg; /* SYS_FREQCTRL0/1 */
+ int shift; /* offset in register */
+ int parent; /* parent before disable [Au1300] */
+ int isen; /* is it enabled? */
+ int *dt; /* dividertable for csrc */
+};
+#define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
+
+static long alchemy_calc_div(unsigned long rate, unsigned long prate,
+ int scale, int maxdiv, unsigned long *rv)
+{
+ long div1, div2;
+
+ div1 = prate / rate;
+ if ((prate / div1) > rate)
+ div1++;
+
+ if (scale == 2) { /* only div-by-multiple-of-2 possible */
+ if (div1 & 1)
+ div1++; /* stay <=prate */
+ }
+
+ div2 = (div1 / scale) - 1; /* value to write to register */
+
+ if (div2 > maxdiv)
+ div2 = maxdiv;
+ if (rv)
+ *rv = div2;
+
+ div1 = ((div2 + 1) * scale);
+ return div1;
+}
+
+static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_clk,
+ int scale, int maxdiv)
+{
+ struct clk *pc, *bpc, *free;
+ long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
+ int j;
+
+ lastdiff = INT_MAX;
+ bpr = 0;
+ bpc = NULL;
+ br = -EINVAL;
+ free = NULL;
+
+ /* look at the rates each enabled parent supplies and select
+ * the one that gets closest to but not over the requested rate.
+ */
+ for (j = 0; j < 7; j++) {
+ pc = clk_get_parent_by_index(hw->clk, j);
+ if (!pc)
+ break;
+
+ /* if this parent is currently unused, remember it.
+ * XXX: I know it's a layering violation, but it works
+ * so well.. (if (!clk_has_active_children(pc)) )
+ */
+ if (pc->prepare_count == 0) {
+ if (!free)
+ free = pc;
+ }
+
+ pr = clk_get_rate(pc);
+ if (pr < rate)
+ continue;
+
+ /* what can hardware actually provide */
+ tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+ nr = pr / tdv;
+ diff = rate - nr;
+ if (nr > rate)
+ continue;
+
+ if (diff < lastdiff) {
+ lastdiff = diff;
+ bpr = pr;
+ bpc = pc;
+ br = nr;
+ }
+ if (diff == 0)
+ break;
+ }
+
+ /* if we couldn't get the exact rate we wanted from the enabled
+ * parents, maybe we can tell an available disabled/inactive one
+ * to give us a rate we can divide down to the requested rate.
+ */
+ if (lastdiff && free) {
+ for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
+ tpr = rate * j;
+ if (tpr < 0)
+ break;
+ pr = clk_round_rate(free, tpr);
+
+ tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+ nr = pr / tdv;
+ diff = rate - nr;
+ if (nr > rate)
+ continue;
+ if (diff < lastdiff) {
+ lastdiff = diff;
+ bpr = pr;
+ bpc = free;
+ br = nr;
+ }
+ if (diff == 0)
+ break;
+ }
+ }
+
+ *best_parent_rate = bpr;
+ *best_parent_clk = bpc;
+ return br;
+}
+
+static int alchemy_clk_fgv1_en(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v, flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v |= (1 << 1) << c->shift;
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
+
+ return v & 1;
+}
+
+static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v, flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~((1 << 1) << c->shift);
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v, flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ if (index)
+ v |= (1 << c->shift);
+ else
+ v &= ~(1 << c->shift);
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+ return (alchemy_rdsys(c->reg) >> c->shift) & 1;
+}
+
+static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long div, v, flags, ret;
+ int sh = c->shift + 2;
+
+ if (!rate || !parent_rate || rate > (parent_rate / 2))
+ return -EINVAL;
+ ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~(0xff << sh);
+ v |= div << sh;
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
+
+ v = ((v & 0xff) + 1) * 2;
+ return parent_rate / v;
+}
+
+static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_clk)
+{
+ return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+ best_parent_clk, 2, 512);
+}
+
+/* Au1000, Au1100, Au15x0, Au12x0 */
+static struct clk_ops alchemy_clkops_fgenv1 = {
+ .recalc_rate = alchemy_clk_fgv1_recalc,
+ .determine_rate = alchemy_clk_fgv1_detr,
+ .set_rate = alchemy_clk_fgv1_setr,
+ .set_parent = alchemy_clk_fgv1_setp,
+ .get_parent = alchemy_clk_fgv1_getp,
+ .enable = alchemy_clk_fgv1_en,
+ .disable = alchemy_clk_fgv1_dis,
+ .is_enabled = alchemy_clk_fgv1_isen,
+};
+
+static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
+{
+ unsigned long v = alchemy_rdsys(c->reg);
+
+ v &= ~(3 << c->shift);
+ v |= (c->parent & 3) << c->shift;
+ alchemy_wrsys(v, c->reg);
+ c->isen = 1;
+}
+
+static int alchemy_clk_fgv2_en(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long flags;
+
+ /* enable by setting the previous parent clock */
+ spin_lock_irqsave(c->reglock, flags);
+ __alchemy_clk_fgv2_en(c);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+ return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
+}
+
+static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v, flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~(3 << c->shift); /* set input mux to "disabled" state */
+ alchemy_wrsys(v, c->reg);
+ c->isen = 0;
+ spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ c->parent = index + 1; /* value to write to register */
+ if (c->isen)
+ __alchemy_clk_fgv2_en(c);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long flags, v;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = c->parent - 1;
+ spin_unlock_irqrestore(c->reglock, flags);
+ return v;
+}
+
+/* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
+ * dividers behave exactly as on previous models (dividers are multiples
+ * of 2); with the bit set, dividers are multiples of 1, halving their
+ * range, but making them also much more flexible.
+ */
+static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ int sh = c->shift + 2;
+ unsigned long div, v, flags, ret;
+
+ if (!rate || !parent_rate || rate > parent_rate)
+ return -EINVAL;
+
+ v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */
+ ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
+ v ? 256 : 512, &div);
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~(0xff << sh);
+ v |= (div & 0xff) << sh;
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ int sh = c->shift + 2;
+ unsigned long v, t;
+
+ v = alchemy_rdsys(c->reg);
+ t = parent_rate / (((v >> sh) & 0xff) + 1);
+ if ((v & (1 << 30)) == 0) /* test scale bit */
+ t /= 2;
+
+ return t;
+}
+
+static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_clk)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ int scale, maxdiv;
+
+ if (alchemy_rdsys(c->reg) & (1 << 30)) {
+ scale = 1;
+ maxdiv = 256;
+ } else {
+ scale = 2;
+ maxdiv = 512;
+ }
+
+ return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+ best_parent_clk, scale, maxdiv);
+}
+
+/* Au1300 larger input mux, no separate disable bit, flexible divider */
+static struct clk_ops alchemy_clkops_fgenv2 = {
+ .recalc_rate = alchemy_clk_fgv2_recalc,
+ .determine_rate = alchemy_clk_fgv2_detr,
+ .set_rate = alchemy_clk_fgv2_setr,
+ .set_parent = alchemy_clk_fgv2_setp,
+ .get_parent = alchemy_clk_fgv2_getp,
+ .enable = alchemy_clk_fgv2_en,
+ .disable = alchemy_clk_fgv2_dis,
+ .is_enabled = alchemy_clk_fgv2_isen,
+};
+
+static const char * const alchemy_clk_fgv1_parents[] = {
+ ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgv2_parents[] = {
+ ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgen_names[] = {
+ ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+ ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
+
+static int __init alchemy_clk_init_fgens(int ctype)
+{
+ struct clk *c;
+ struct clk_init_data id;
+ struct alchemy_fgcs_clk *a;
+ unsigned long v;
+ int i, ret;
+
+ switch (ctype) {
+ case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+ id.ops = &alchemy_clkops_fgenv1;
+ id.parent_names = (const char **)alchemy_clk_fgv1_parents;
+ id.num_parents = 2;
+ break;
+ case ALCHEMY_CPU_AU1300:
+ id.ops = &alchemy_clkops_fgenv2;
+ id.parent_names = (const char **)alchemy_clk_fgv2_parents;
+ id.num_parents = 3;
+ break;
+ default:
+ return -ENODEV;
+ }
+ id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+ a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+ if (!a)
+ return -ENOMEM;
+
+ spin_lock_init(&alchemy_clk_fg0_lock);
+ spin_lock_init(&alchemy_clk_fg1_lock);
+ ret = 0;
+ for (i = 0; i < 6; i++) {
+ id.name = alchemy_clk_fgen_names[i];
+ a->shift = 10 * (i < 3 ? i : i - 3);
+ if (i > 2) {
+ a->reg = AU1000_SYS_FREQCTRL1;
+ a->reglock = &alchemy_clk_fg1_lock;
+ } else {
+ a->reg = AU1000_SYS_FREQCTRL0;
+ a->reglock = &alchemy_clk_fg0_lock;
+ }
+
+ /* default to first parent if bootloader has set
+ * the mux to disabled state.
+ */
+ if (ctype == ALCHEMY_CPU_AU1300) {
+ v = alchemy_rdsys(a->reg);
+ a->parent = (v >> a->shift) & 3;
+ if (!a->parent) {
+ a->parent = 1;
+ a->isen = 0;
+ } else
+ a->isen = 1;
+ }
+
+ a->hw.init = &id;
+ c = clk_register(NULL, &a->hw);
+ if (IS_ERR(c))
+ ret++;
+ else
+ clk_register_clkdev(c, id.name, NULL);
+ a++;
+ }
+
+ return ret;
+}
+
+/* internal sources muxes *********************************************/
+
+static int alchemy_clk_csrc_isen(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v = alchemy_rdsys(c->reg);
+
+ return (((v >> c->shift) >> 2) & 7) != 0;
+}
+
+static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
+{
+ unsigned long v = alchemy_rdsys(c->reg);
+
+ v &= ~((7 << 2) << c->shift);
+ v |= ((c->parent & 7) << 2) << c->shift;
+ alchemy_wrsys(v, c->reg);
+ c->isen = 1;
+}
+
+static int alchemy_clk_csrc_en(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long flags;
+
+ /* enable by setting the previous parent clock */
+ spin_lock_irqsave(c->reglock, flags);
+ __alchemy_clk_csrc_en(c);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static void alchemy_clk_csrc_dis(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v, flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~((3 << 2) << c->shift); /* mux to "disabled" state */
+ alchemy_wrsys(v, c->reg);
+ c->isen = 0;
+ spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(c->reglock, flags);
+ c->parent = index + 1; /* value to write to register */
+ if (c->isen)
+ __alchemy_clk_csrc_en(c);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+ return c->parent - 1;
+}
+
+static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
+
+ return parent_rate / c->dt[v];
+}
+
+static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ unsigned long d, v, flags;
+ int i;
+
+ if (!rate || !parent_rate || rate > parent_rate)
+ return -EINVAL;
+
+ d = (parent_rate + (rate / 2)) / rate;
+ if (d > 4)
+ return -EINVAL;
+ if ((d == 3) && (c->dt[2] != 3))
+ d = 4;
+
+ for (i = 0; i < 4; i++)
+ if (c->dt[i] == d)
+ break;
+
+ if (i >= 4)
+ return -EINVAL; /* oops */
+
+ spin_lock_irqsave(c->reglock, flags);
+ v = alchemy_rdsys(c->reg);
+ v &= ~(3 << c->shift);
+ v |= (i & 3) << c->shift;
+ alchemy_wrsys(v, c->reg);
+ spin_unlock_irqrestore(c->reglock, flags);
+
+ return 0;
+}
+
+static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_clk)
+{
+ struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+ int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
+
+ return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+ best_parent_clk, scale, 4);
+}
+
+static struct clk_ops alchemy_clkops_csrc = {
+ .recalc_rate = alchemy_clk_csrc_recalc,
+ .determine_rate = alchemy_clk_csrc_detr,
+ .set_rate = alchemy_clk_csrc_setr,
+ .set_parent = alchemy_clk_csrc_setp,
+ .get_parent = alchemy_clk_csrc_getp,
+ .enable = alchemy_clk_csrc_en,
+ .disable = alchemy_clk_csrc_dis,
+ .is_enabled = alchemy_clk_csrc_isen,
+};
+
+static const char * const alchemy_clk_csrc_parents[] = {
+ /* disabled at index 0 */ ALCHEMY_AUXPLL_CLK,
+ ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+ ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
+};
+
+/* divider tables */
+static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 }; /* rest */
+static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 }; /* Au1300 */
+
+static int __init alchemy_clk_setup_imux(int ctype)
+{
+ struct alchemy_fgcs_clk *a;
+ const char * const *names;
+ struct clk_init_data id;
+ unsigned long v;
+ int i, ret, *dt;
+ struct clk *c;
+
+ id.ops = &alchemy_clkops_csrc;
+ id.parent_names = (const char **)alchemy_clk_csrc_parents;
+ id.num_parents = 7;
+ id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+ dt = alchemy_csrc_dt1;
+ switch (ctype) {
+ case ALCHEMY_CPU_AU1000:
+ names = alchemy_au1000_intclknames;
+ break;
+ case ALCHEMY_CPU_AU1500:
+ names = alchemy_au1500_intclknames;
+ break;
+ case ALCHEMY_CPU_AU1100:
+ names = alchemy_au1100_intclknames;
+ break;
+ case ALCHEMY_CPU_AU1550:
+ names = alchemy_au1550_intclknames;
+ break;
+ case ALCHEMY_CPU_AU1200:
+ names = alchemy_au1200_intclknames;
+ break;
+ case ALCHEMY_CPU_AU1300:
+ dt = alchemy_csrc_dt2;
+ names = alchemy_au1300_intclknames;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+ if (!a)
+ return -ENOMEM;
+
+ spin_lock_init(&alchemy_clk_csrc_lock);
+ ret = 0;
+
+ for (i = 0; i < 6; i++) {
+ id.name = names[i];
+ if (!id.name)
+ goto next;
+
+ a->shift = i * 5;
+ a->reg = AU1000_SYS_CLKSRC;
+ a->reglock = &alchemy_clk_csrc_lock;
+ a->dt = dt;
+
+ /* default to first parent clock if mux is initially
+ * set to disabled state.
+ */
+ v = alchemy_rdsys(a->reg);
+ a->parent = ((v >> a->shift) >> 2) & 7;
+ if (!a->parent) {
+ a->parent = 1;
+ a->isen = 0;
+ } else
+ a->isen = 1;
+
+ a->hw.init = &id;
+ c = clk_register(NULL, &a->hw);
+ if (IS_ERR(c))
+ ret++;
+ else
+ clk_register_clkdev(c, id.name, NULL);
+next:
+ a++;
+ }
+
+ return ret;
+}
+
+
+/**********************************************************************/
+
+
+#define ERRCK(x) \
+ if (IS_ERR(x)) { \
+ ret = PTR_ERR(x); \
+ goto out; \
+ }
+
+static int __init alchemy_clk_init(void)
+{
+ int ctype = alchemy_get_cputype(), ret, i;
+ struct clk_aliastable *t = alchemy_clk_aliases;
+ struct clk *c;
+
+ /* Root of the Alchemy clock tree: external 12MHz crystal osc */
+ c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
+ CLK_IS_ROOT,
+ ALCHEMY_ROOTCLK_RATE);
+ ERRCK(c)
+
+ /* CPU core clock */
+ c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
+ ERRCK(c)
+
+ /* AUXPLLs: max 1GHz on Au1300, 748MHz on older models */
+ i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
+ c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
+ i, AU1000_SYS_AUXPLL);
+ ERRCK(c)
+
+ if (ctype == ALCHEMY_CPU_AU1300) {
+ c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
+ ALCHEMY_AUXPLL2_CLK, i,
+ AU1300_SYS_AUXPLL2);
+ ERRCK(c)
+ }
+
+ /* sysbus clock: cpu core clock divided by 2, 3 or 4 */
+ c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
+ ERRCK(c)
+
+ /* peripheral clock: runs at half rate of sysbus clk */
+ c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
+ ERRCK(c)
+
+ /* SDR/DDR memory clock */
+ c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
+ ERRCK(c)
+
+ /* L/RCLK: external static bus clock for synchronous mode */
+ c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
+ ERRCK(c)
+
+ /* Frequency dividers 0-5 */
+ ret = alchemy_clk_init_fgens(ctype);
+ if (ret) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* diving muxes for internal sources */
+ ret = alchemy_clk_setup_imux(ctype);
+ if (ret) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ /* set up aliases drivers might look for */
+ while (t->base) {
+ if (t->cputype == ctype)
+ clk_add_alias(t->alias, NULL, t->base, NULL);
+ t++;
+ }
+
+ pr_info("Alchemy clocktree installed\n");
+ return 0;
+
+out:
+ return ret;
+}
+postcore_initcall(alchemy_clk_init);
diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c
deleted file mode 100644
index f38298a8b98c..000000000000
--- a/arch/mips/alchemy/common/clocks.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Simple Au1xx0 clocks routines.
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/time.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK 12000000
-
-static unsigned int au1x00_clock; /* Hz */
-static unsigned long uart_baud_base;
-
-/*
- * Set the au1000_clock
- */
-void set_au1x00_speed(unsigned int new_freq)
-{
- au1x00_clock = new_freq;
-}
-
-unsigned int get_au1x00_speed(void)
-{
- return au1x00_clock;
-}
-EXPORT_SYMBOL(get_au1x00_speed);
-
-/*
- * The UART baud base is not known at compile time ... if
- * we want to be able to use the same code on different
- * speed CPUs.
- */
-unsigned long get_au1x00_uart_baud_base(void)
-{
- return uart_baud_base;
-}
-
-void set_au1x00_uart_baud_base(unsigned long new_baud_base)
-{
- uart_baud_base = new_baud_base;
-}
-
-/*
- * We read the real processor speed from the PLL. This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists. If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly. This function is further convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register. -- Dan
- */
-unsigned long au1xxx_calc_clock(void)
-{
- unsigned long cpu_speed;
-
- /*
- * On early Au1000, sys_cpupll was write-only. Since these
- * silicon versions of Au1000 are not sold by AMD, we don't bend
- * over backwards trying to determine the frequency.
- */
- if (au1xxx_cpu_has_pll_wo())
- cpu_speed = 396000000;
- else
- cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
-
- /* On Alchemy CPU:counter ratio is 1:1 */
- mips_hpt_frequency = cpu_speed;
- /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
- set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
- & 0x03) + 2) * 16));
-
- set_au1x00_speed(cpu_speed);
-
- return cpu_speed;
-}
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 19d5642c16d9..745695db5ba0 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -341,7 +341,7 @@ u32 au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
(dtp->dev_flags & DEV_FLAGS_SYNC))
i |= DDMA_CFG_SYNC;
cp->ddma_cfg = i;
- au_sync();
+ wmb(); /* drain writebuffer */
/*
* Return a non-zero value that can be used to find the channel
@@ -631,7 +631,7 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
*/
dma_cache_wback_inv((unsigned long)buf, nbytes);
dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
- au_sync();
+ wmb(); /* drain writebuffer */
dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
ctp->chan_ptr->ddma_dbell = 0;
@@ -693,7 +693,7 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
*/
dma_cache_inv((unsigned long)buf, nbytes);
dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
- au_sync();
+ wmb(); /* drain writebuffer */
dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
ctp->chan_ptr->ddma_dbell = 0;
@@ -760,7 +760,7 @@ void au1xxx_dbdma_stop(u32 chanid)
cp = ctp->chan_ptr;
cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */
- au_sync();
+ wmb(); /* drain writebuffer */
while (!(cp->ddma_stat & DDMA_STAT_H)) {
udelay(1);
halt_timeout++;
@@ -771,7 +771,7 @@ void au1xxx_dbdma_stop(u32 chanid)
}
/* clear current desc valid and doorbell */
cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
- au_sync();
+ wmb(); /* drain writebuffer */
}
EXPORT_SYMBOL(au1xxx_dbdma_stop);
@@ -789,9 +789,9 @@ void au1xxx_dbdma_start(u32 chanid)
cp = ctp->chan_ptr;
cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
- au_sync();
+ wmb(); /* drain writebuffer */
cp->ddma_dbell = 0;
- au_sync();
+ wmb(); /* drain writebuffer */
}
EXPORT_SYMBOL(au1xxx_dbdma_start);
@@ -832,7 +832,7 @@ u32 au1xxx_get_dma_residue(u32 chanid)
/* This is only valid if the channel is stopped. */
rv = cp->ddma_bytecnt;
- au_sync();
+ wmb(); /* drain writebuffer */
return rv;
}
@@ -868,7 +868,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
au1x_dma_chan_t *cp;
intstat = dbdma_gptr->ddma_intstat;
- au_sync();
+ wmb(); /* drain writebuffer */
chan_index = __ffs(intstat);
ctp = chan_tab_ptr[chan_index];
@@ -877,7 +877,7 @@ static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
/* Reset interrupt. */
cp->ddma_irq = 0;
- au_sync();
+ wmb(); /* drain writebuffer */
if (ctp->chan_callback)
ctp->chan_callback(irq, ctp->chan_callparam);
@@ -1061,7 +1061,7 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
dbdma_gptr->ddma_config = 0;
dbdma_gptr->ddma_throttle = 0;
dbdma_gptr->ddma_inten = 0xffff;
- au_sync();
+ wmb(); /* drain writebuffer */
ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr);
if (ret)
diff --git a/arch/mips/alchemy/common/dma.c b/arch/mips/alchemy/common/dma.c
index 9b624e2c0fcf..4fb6207b883b 100644
--- a/arch/mips/alchemy/common/dma.c
+++ b/arch/mips/alchemy/common/dma.c
@@ -141,17 +141,17 @@ void dump_au1000_dma_channel(unsigned int dmanr)
printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
printk(KERN_INFO " mode = 0x%08x\n",
- au_readl(chan->io + DMA_MODE_SET));
+ __raw_readl(chan->io + DMA_MODE_SET));
printk(KERN_INFO " addr = 0x%08x\n",
- au_readl(chan->io + DMA_PERIPHERAL_ADDR));
+ __raw_readl(chan->io + DMA_PERIPHERAL_ADDR));
printk(KERN_INFO " start0 = 0x%08x\n",
- au_readl(chan->io + DMA_BUFFER0_START));
+ __raw_readl(chan->io + DMA_BUFFER0_START));
printk(KERN_INFO " start1 = 0x%08x\n",
- au_readl(chan->io + DMA_BUFFER1_START));
+ __raw_readl(chan->io + DMA_BUFFER1_START));
printk(KERN_INFO " count0 = 0x%08x\n",
- au_readl(chan->io + DMA_BUFFER0_COUNT));
+ __raw_readl(chan->io + DMA_BUFFER0_COUNT));
printk(KERN_INFO " count1 = 0x%08x\n",
- au_readl(chan->io + DMA_BUFFER1_COUNT));
+ __raw_readl(chan->io + DMA_BUFFER1_COUNT));
}
/*
@@ -204,7 +204,8 @@ int request_au1000_dma(int dev_id, const char *dev_str,
}
/* fill it in */
- chan->io = KSEG1ADDR(AU1000_DMA_PHYS_ADDR) + i * DMA_CHANNEL_LEN;
+ chan->io = (void __iomem *)(KSEG1ADDR(AU1000_DMA_PHYS_ADDR) +
+ i * DMA_CHANNEL_LEN);
chan->dev_id = dev_id;
chan->dev_str = dev_str;
chan->fifo_addr = dev->fifo_addr;
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c
index 63a71817a00c..6cb60abfdcc9 100644
--- a/arch/mips/alchemy/common/irq.c
+++ b/arch/mips/alchemy/common/irq.c
@@ -389,13 +389,12 @@ static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
return -EINVAL;
local_irq_save(flags);
- wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
+ wakemsk = alchemy_rdsys(AU1000_SYS_WAKEMSK);
if (on)
wakemsk |= 1 << bit;
else
wakemsk &= ~(1 << bit);
- __raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
- wmb();
+ alchemy_wrsys(wakemsk, AU1000_SYS_WAKEMSK);
local_irq_restore(flags);
return 0;
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 9837a134a6d6..d77a64f4c78b 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -11,6 +11,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -99,10 +100,20 @@ static struct platform_device au1xx0_uart_device = {
static void __init alchemy_setup_uarts(int ctype)
{
- unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
+ long uartclk;
int s = sizeof(struct plat_serial8250_port);
int c = alchemy_get_uarts(ctype);
struct plat_serial8250_port *ports;
+ struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
+
+ if (IS_ERR(clk))
+ return;
+ if (clk_prepare_enable(clk)) {
+ clk_put(clk);
+ return;
+ }
+ uartclk = clk_get_rate(clk);
+ clk_put(clk);
ports = kzalloc(s * (c + 1), GFP_KERNEL);
if (!ports) {
@@ -420,7 +431,7 @@ static void __init alchemy_setup_macs(int ctype)
memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
/* Register second MAC if enabled in pinfunc */
- if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) {
+ if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
ret = platform_device_register(&au1xxx_eth1_device);
if (ret)
printk(KERN_INFO "Alchemy: failed to register MAC1\n");
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index bdb28dee8fdd..921ed30b440c 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -54,28 +54,28 @@ static unsigned int sleep_static_memctlr[4][3];
static void save_core_regs(void)
{
/* Clocks and PLLs. */
- sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
- sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
- sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
- sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
- sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
+ sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
+ sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
+ sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
+ sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
+ sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
/* pin mux config */
- sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
+ sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
/* Save the static memory controller configuration. */
- sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
- sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
- sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
- sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
- sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
- sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
- sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
- sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
- sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
- sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
- sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
- sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+ sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
+ sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
+ sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
+ sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
+ sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
+ sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
+ sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
+ sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
+ sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
+ sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
+ sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
+ sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
}
static void restore_core_regs(void)
@@ -85,30 +85,28 @@ static void restore_core_regs(void)
* one of those Au1000 with a write-only PLL, where we dont
* have a valid value)
*/
- au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
- au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
- au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
- au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+ alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
+ alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
+ alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
+ alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
if (!au1xxx_cpu_has_pll_wo())
- au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
- au_sync();
+ alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
- au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
- au_sync();
+ alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
/* Restore the static memory controller configuration. */
- au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
- au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
- au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
- au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
- au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
- au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
- au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
- au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
- au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
- au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
- au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
- au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+ alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
+ alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
+ alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
+ alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
+ alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
+ alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
+ alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
+ alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
+ alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
+ alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
+ alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
+ alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
}
void au_sleep(void)
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index 8267e3c97721..ea8f41869e56 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -27,12 +27,9 @@
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
#include <asm/dma-coherence.h>
#include <asm/mipsregs.h>
-#include <asm/time.h>
#include <au1000.h>
@@ -41,18 +38,6 @@ extern void set_cpuspec(void);
void __init plat_mem_setup(void)
{
- unsigned long est_freq;
-
- /* determine core clock */
- est_freq = au1xxx_calc_clock();
- est_freq += 5000; /* round */
- est_freq -= est_freq % 10000;
- printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
- est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
-
- /* this is faster than wasting cycles trying to approximate it */
- preset_lpj = (est_freq >> 1) / HZ;
-
if (au1xxx_cpu_needs_config_od())
/* Various early Au1xx0 errata corrected by this */
set_c0_config(1 << 19); /* Set Config[OD] */
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c
index 93fa586d52e2..50e17e13c18b 100644
--- a/arch/mips/alchemy/common/time.c
+++ b/arch/mips/alchemy/common/time.c
@@ -46,7 +46,7 @@
static cycle_t au1x_counter1_read(struct clocksource *cs)
{
- return au_readl(SYS_RTCREAD);
+ return alchemy_rdsys(AU1000_SYS_RTCREAD);
}
static struct clocksource au1x_counter1_clocksource = {
@@ -60,12 +60,11 @@ static struct clocksource au1x_counter1_clocksource = {
static int au1x_rtcmatch2_set_next_event(unsigned long delta,
struct clock_event_device *cd)
{
- delta += au_readl(SYS_RTCREAD);
+ delta += alchemy_rdsys(AU1000_SYS_RTCREAD);
/* wait for register access */
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+ while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21)
;
- au_writel(delta, SYS_RTCMATCH2);
- au_sync();
+ alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2);
return 0;
}
@@ -112,31 +111,29 @@ static int __init alchemy_time_init(unsigned int m2int)
* (the 32S bit seems to be stuck set to 1 once a single clock-
* edge is detected, hence the timeouts).
*/
- if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+ if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK))
goto cntr_err;
/*
* setup counter 1 (RTC) to tick at full speed
*/
t = 0xffffff;
- while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
+ while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t)
asm volatile ("nop");
if (!t)
goto cntr_err;
- au_writel(0, SYS_RTCTRIM); /* 32.768 kHz */
- au_sync();
+ alchemy_wrsys(0, AU1000_SYS_RTCTRIM); /* 32.768 kHz */
t = 0xffffff;
- while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+ while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
asm volatile ("nop");
if (!t)
goto cntr_err;
- au_writel(0, SYS_RTCWRITE);
- au_sync();
+ alchemy_wrsys(0, AU1000_SYS_RTCWRITE);
t = 0xffffff;
- while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+ while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
asm volatile ("nop");
if (!t)
goto cntr_err;
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
index d193dbea84a1..297805ade849 100644
--- a/arch/mips/alchemy/common/usb.c
+++ b/arch/mips/alchemy/common/usb.c
@@ -9,6 +9,7 @@
*
*/
+#include <linux/clk.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -387,10 +388,25 @@ static inline void au1200_usb_init(void)
udelay(1000);
}
-static inline void au1000_usb_init(unsigned long rb, int reg)
+static inline int au1000_usb_init(unsigned long rb, int reg)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
unsigned long r = __raw_readl(base);
+ struct clk *c;
+
+ /* 48MHz check. Don't init if no one can provide it */
+ c = clk_get(NULL, "usbh_clk");
+ if (IS_ERR(c))
+ return -ENODEV;
+ if (clk_round_rate(c, 48000000) != 48000000) {
+ clk_put(c);
+ return -ENODEV;
+ }
+ if (clk_set_rate(c, 48000000)) {
+ clk_put(c);
+ return -ENODEV;
+ }
+ clk_put(c);
#if defined(__BIG_ENDIAN)
r |= USBHEN_BE;
@@ -400,6 +416,8 @@ static inline void au1000_usb_init(unsigned long rb, int reg)
__raw_writel(r, base);
wmb();
udelay(1000);
+
+ return 0;
}
@@ -407,8 +425,15 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
unsigned long r = __raw_readl(base + creg);
+ struct clk *c = clk_get(NULL, "usbh_clk");
+
+ if (IS_ERR(c))
+ return;
if (enable) {
+ if (clk_prepare_enable(c))
+ goto out;
+
__raw_writel(r | USBHEN_CE, base + creg);
wmb();
udelay(1000);
@@ -423,7 +448,10 @@ static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
} else {
__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
wmb();
+ clk_disable_unprepare(c);
}
+out:
+ clk_put(c);
}
static inline int au1000_usb_control(int block, int enable, unsigned long rb,
@@ -457,11 +485,11 @@ int alchemy_usb_control(int block, int enable)
case ALCHEMY_CPU_AU1500:
case ALCHEMY_CPU_AU1100:
ret = au1000_usb_control(block, enable,
- AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+ AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
break;
case ALCHEMY_CPU_AU1550:
ret = au1000_usb_control(block, enable,
- AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+ AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
break;
case ALCHEMY_CPU_AU1200:
ret = au1200_usb_control(block, enable);
@@ -569,14 +597,18 @@ static struct syscore_ops alchemy_usb_pm_ops = {
static int __init alchemy_usb_init(void)
{
+ int ret = 0;
+
switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1000:
case ALCHEMY_CPU_AU1500:
case ALCHEMY_CPU_AU1100:
- au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+ ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
+ AU1000_OHCICFG);
break;
case ALCHEMY_CPU_AU1550:
- au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+ ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
+ AU1550_OHCICFG);
break;
case ALCHEMY_CPU_AU1200:
au1200_usb_init();
@@ -586,8 +618,9 @@ static int __init alchemy_usb_init(void)
break;
}
- register_syscore_ops(&alchemy_usb_pm_ops);
+ if (!ret)
+ register_syscore_ops(&alchemy_usb_pm_ops);
- return 0;
+ return ret;
}
arch_initcall(alchemy_usb_init);
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 92dd929d4057..001102e197f1 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/init.h>
@@ -496,6 +497,7 @@ int __init db1000_dev_setup(void)
int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
int c0, c1, d0, d1, s0, s1, flashsize = 32, twosocks = 1;
unsigned long pfc;
+ struct clk *c, *p;
if (board == BCSR_WHOAMI_DB1500) {
c0 = AU1500_GPIO2_INT;
@@ -518,14 +520,25 @@ int __init db1000_dev_setup(void)
gpio_direction_input(20); /* sd1 cd# */
/* spi_gpio on SSI0 pins */
- pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
+ pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
pfc |= (1 << 0); /* SSI0 pins as GPIOs */
- __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
- wmb();
+ alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
spi_register_board_info(db1100_spi_info,
ARRAY_SIZE(db1100_spi_info));
+ /* link LCD clock to AUXPLL */
+ p = clk_get(NULL, "auxpll_clk");
+ c = clk_get(NULL, "lcd_intclk");
+ if (!IS_ERR(c) && !IS_ERR(p)) {
+ clk_set_parent(c, p);
+ clk_set_rate(c, clk_get_rate(p));
+ }
+ if (!IS_ERR(c))
+ clk_put(c);
+ if (!IS_ERR(p))
+ clk_put(p);
+
platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
platform_device_register(&db1100_spi_dev);
} else if (board == BCSR_WHOAMI_DB1000) {
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 9e46667f2597..776188908dfc 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
@@ -129,7 +130,6 @@ static int __init db1200_detect_board(void)
int __init db1200_board_setup(void)
{
- unsigned long freq0, clksrc, div, pfc;
unsigned short whoami;
if (db1200_detect_board())
@@ -149,34 +149,6 @@ int __init db1200_board_setup(void)
" Board-ID %d Daughtercard ID %d\n", get_system_type(),
(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
- /* SMBus/SPI on PSC0, Audio on PSC1 */
- pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
- pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
- pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
- pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
- __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
- wmb();
-
- /* Clock configurations: PSC0: ~50MHz via Clkgen0, derived from
- * CPU clock; all other clock generators off/unused.
- */
- div = (get_au1x00_speed() + 25000000) / 50000000;
- if (div & 1)
- div++;
- div = ((div >> 1) - 1) & 0xff;
-
- freq0 = div << SYS_FC_FRDIV0_BIT;
- __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
- wmb();
- freq0 |= SYS_FC_FE0; /* enable F0 */
- __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
- wmb();
-
- /* psc0_intclk comes 1:1 from F0 */
- clksrc = SYS_CS_MUX_FQ0 << SYS_CS_ME0_BIT;
- __raw_writel(clksrc, (void __iomem *)SYS_CLKSRC);
- wmb();
-
return 0;
}
@@ -250,7 +222,7 @@ static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static int au1200_nand_device_ready(struct mtd_info *mtd)
{
- return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+ return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}
static struct mtd_partition db1200_nand_parts[] = {
@@ -847,6 +819,7 @@ int __init db1200_dev_setup(void)
unsigned long pfc;
unsigned short sw;
int swapped, bid;
+ struct clk *c;
bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
if ((bid == BCSR_WHOAMI_PB1200_DDR1) ||
@@ -859,6 +832,24 @@ int __init db1200_dev_setup(void)
irq_set_irq_type(AU1200_GPIO7_INT, IRQ_TYPE_LEVEL_LOW);
bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
+ /* SMBus/SPI on PSC0, Audio on PSC1 */
+ pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
+ pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
+ pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
+ pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
+ alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
+
+ /* get 50MHz for I2C driver on PSC0 */
+ c = clk_get(NULL, "psc0_intclk");
+ if (!IS_ERR(c)) {
+ pfc = clk_round_rate(c, 50000000);
+ if ((pfc < 1) || (abs(50000000 - pfc) > 2500000))
+ pr_warn("DB1200: cant get I2C close to 50MHz\n");
+ else
+ clk_set_rate(c, pfc);
+ clk_put(c);
+ }
+
/* insert/eject pairs: one of both is always screaming. To avoid
* issues they must not be automatically enabled when initially
* requested.
@@ -886,7 +877,7 @@ int __init db1200_dev_setup(void)
* As a result, in SPI mode, OTG simply won't work (PSC0 uses
* it as an input pin which is pulled high on the boards).
*/
- pfc = __raw_readl((void __iomem *)SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
+ pfc = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
/* switch off OTG VBUS supply */
gpio_request(215, "otg-vbus");
@@ -912,8 +903,7 @@ int __init db1200_dev_setup(void)
printk(KERN_INFO " S6.8 ON : PSC0 mode SPI\n");
printk(KERN_INFO " OTG port VBUS supply disabled\n");
}
- __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
- wmb();
+ alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
/* Audio: DIP7 selects I2S(0)/AC97(1), but need I2C for I2S!
* so: DIP7=1 || DIP8=0 => AC97, DIP7=0 && DIP8=1 => I2S
@@ -932,6 +922,11 @@ int __init db1200_dev_setup(void)
}
/* Audio PSC clock is supplied externally. (FIXME: platdata!!) */
+ c = clk_get(NULL, "psc1_intclk");
+ if (!IS_ERR(c)) {
+ clk_prepare_enable(c);
+ clk_put(c);
+ }
__raw_writel(PSC_SEL_CLK_SERCLK,
(void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
wmb();
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index 1aed6be4de10..ef93ee3f6a2c 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -4,6 +4,7 @@
* (c) 2009 Manuel Lauss <manuel.lauss@googlemail.com>
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
@@ -169,7 +170,7 @@ static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static int au1300_nand_device_ready(struct mtd_info *mtd)
{
- return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+ return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}
static struct mtd_partition db1300_nand_parts[] = {
@@ -731,6 +732,7 @@ static struct platform_device *db1300_dev[] __initdata = {
int __init db1300_dev_setup(void)
{
int swapped, cpldirq;
+ struct clk *c;
/* setup CPLD IRQ muxer */
cpldirq = au1300_gpio_to_irq(AU1300_PIN_EXTCLK1);
@@ -761,6 +763,11 @@ int __init db1300_dev_setup(void)
(void __iomem *)KSEG1ADDR(AU1300_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET);
wmb();
/* I2C uses internal 48MHz EXTCLK1 */
+ c = clk_get(NULL, "psc3_intclk");
+ if (!IS_ERR(c)) {
+ clk_prepare_enable(c);
+ clk_put(c);
+ }
__raw_writel(PSC_SEL_CLK_INTCLK,
(void __iomem *)KSEG1ADDR(AU1300_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET);
wmb();
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index bbd8d9884702..7e89936f763e 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -4,6 +4,7 @@
* (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
*/
+#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
@@ -31,16 +32,16 @@
static void __init db1550_hw_setup(void)
{
void __iomem *base;
+ unsigned long v;
/* complete SPI setup: link psc0_intclk to a 48MHz source,
* and assign GPIO16 to PSC0_SYNC1 (SPI cs# line) as well as PSC1_SYNC
* for AC97 on PB1550.
*/
- base = (void __iomem *)SYS_CLKSRC;
- __raw_writel(__raw_readl(base) | 0x000001e0, base);
- base = (void __iomem *)SYS_PINFUNC;
- __raw_writel(__raw_readl(base) | 1 | SYS_PF_PSC1_S1, base);
- wmb();
+ v = alchemy_rdsys(AU1000_SYS_CLKSRC);
+ alchemy_wrsys(v | 0x000001e0, AU1000_SYS_CLKSRC);
+ v = alchemy_rdsys(AU1000_SYS_PINFUNC);
+ alchemy_wrsys(v | 1 | SYS_PF_PSC1_S1, AU1000_SYS_PINFUNC);
/* reset the AC97 codec now, the reset time in the psc-ac97 driver
* is apparently too short although it's ridiculous as it is.
@@ -151,7 +152,7 @@ static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
static int au1550_nand_device_ready(struct mtd_info *mtd)
{
- return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+ return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
}
static struct mtd_partition db1550_nand_parts[] = {
@@ -217,7 +218,7 @@ static struct platform_device pb1550_nand_dev = {
static void __init pb1550_nand_setup(void)
{
- int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) |
+ int boot_swapboot = (alchemy_rdsmem(AU1000_MEM_STSTAT) & (0x7 << 1)) |
((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
gpio_direction_input(206); /* de-assert NAND CS# */
@@ -574,6 +575,7 @@ static void __init pb1550_devices(void)
int __init db1550_dev_setup(void)
{
int swapped, id;
+ struct clk *c;
id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550);
@@ -582,6 +584,17 @@ int __init db1550_dev_setup(void)
spi_register_board_info(db1550_spi_devs,
ARRAY_SIZE(db1550_i2c_devs));
+ c = clk_get(NULL, "psc0_intclk");
+ if (!IS_ERR(c)) {
+ clk_prepare_enable(c);
+ clk_put(c);
+ }
+ c = clk_get(NULL, "psc2_intclk");
+ if (!IS_ERR(c)) {
+ clk_prepare_enable(c);
+ clk_put(c);
+ }
+
/* Audio PSC clock is supplied by codecs (PSC1, 3) FIXME: platdata!! */
__raw_writel(PSC_SEL_CLK_SERCLK,
(void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c
index 61e90fe9eab1..bfeb8f3c0be6 100644
--- a/arch/mips/alchemy/devboards/pm.c
+++ b/arch/mips/alchemy/devboards/pm.c
@@ -45,23 +45,20 @@ static int db1x_pm_enter(suspend_state_t state)
alchemy_gpio1_input_enable();
/* clear and setup wake cause and source */
- au_writel(0, SYS_WAKEMSK);
- au_sync();
- au_writel(0, SYS_WAKESRC);
- au_sync();
+ alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+ alchemy_wrsys(0, AU1000_SYS_WAKESRC);
- au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
- au_sync();
+ alchemy_wrsys(db1x_pm_wakemsk, AU1000_SYS_WAKEMSK);
/* setup 1Hz-timer-based wakeup: wait for reg access */
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+ while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
asm volatile ("nop");
- au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
- au_sync();
+ alchemy_wrsys(alchemy_rdsys(AU1000_SYS_TOYREAD) + db1x_pm_sleep_secs,
+ AU1000_SYS_TOYMATCH2);
/* wait for value to really hit the register */
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+ while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
asm volatile ("nop");
/* ...and now the sandman can come! */
@@ -102,12 +99,10 @@ static void db1x_pm_end(void)
/* read and store wakeup source, the clear the register. To
* be able to clear it, WAKEMSK must be cleared first.
*/
- db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
-
- au_writel(0, SYS_WAKEMSK);
- au_writel(0, SYS_WAKESRC);
- au_sync();
+ db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
+ alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+ alchemy_wrsys(0, AU1000_SYS_WAKESRC);
}
static const struct platform_suspend_ops db1x_pm_ops = {
@@ -242,17 +237,13 @@ static int __init pm_init(void)
* for confirmation since there's plenty of time from here to
* the next suspend cycle.
*/
- if (au_readl(SYS_TOYTRIM) != 32767) {
- au_writel(32767, SYS_TOYTRIM);
- au_sync();
- }
+ if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767)
+ alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
- db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+ db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
- au_writel(0, SYS_WAKESRC);
- au_sync();
- au_writel(0, SYS_WAKEMSK);
- au_sync();
+ alchemy_wrsys(0, AU1000_SYS_WAKESRC);
+ alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
suspend_set_ops(&db1x_pm_ops);
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index 09cb6f7aa3db..fc21d3659fa0 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -11,8 +11,6 @@ config BCM47XX_SSB
select SSB_DRIVER_PCICORE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select SSB_DRIVER_GPIO
- select GPIOLIB
- select LEDS_GPIO_REGISTER
default y
help
Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -22,6 +20,7 @@ config BCM47XX_SSB
config BCM47XX_BCMA
bool "BCMA Support for Broadcom BCM47XX"
select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_HIGHMEM
select CPU_MIPSR2_IRQ_VI
select BCMA
select BCMA_HOST_SOC
@@ -29,8 +28,6 @@ config BCM47XX_BCMA
select BCMA_HOST_PCI if PCI
select BCMA_DRIVER_PCI_HOSTMODE if PCI
select BCMA_DRIVER_GPIO
- select GPIOLIB
- select LEDS_GPIO_REGISTER
default y
help
Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h
index 0194c3b9a729..f1cc9d0495d8 100644
--- a/arch/mips/bcm47xx/bcm47xx_private.h
+++ b/arch/mips/bcm47xx/bcm47xx_private.h
@@ -3,6 +3,9 @@
#include <linux/kernel.h>
+/* prom.c */
+void __init bcm47xx_prom_highmem_init(void);
+
/* buttons.c */
int __init bcm47xx_buttons_register(void);
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
index 44ab1be68c3c..b3ae068ca4fa 100644
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -58,6 +58,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst =
static const
struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
{{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
+ {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
{{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
{{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
{{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
@@ -80,6 +81,14 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initcons
{ {0}, NULL},
};
+/* hardware_version, boardnum */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
+ {{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
+ {{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
+ { {0}, NULL},
+};
+
/* productid */
static const
struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
@@ -98,7 +107,7 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
/* ModelId */
static const
struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
- {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+ {{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
{{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
{{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
{{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
@@ -180,9 +189,9 @@ struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = {
{{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
{{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
{{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
{ {0}, NULL},
};
@@ -237,6 +246,15 @@ static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
}
}
+ if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
+ for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+ if (!strstarts(buf1, e2->value1) &&
+ !strcmp(buf2, e2->value2))
+ return &e2->board;
+ }
+ }
+
if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
if (!strcmp(buf1, e1->value1))
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 49a1ce06844b..913182bcafb8 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -56,6 +56,11 @@ bcm47xx_buttons_asus_wl330ge[] __initconst = {
};
static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500g[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
bcm47xx_buttons_asus_wl500gd[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
@@ -265,7 +270,7 @@ bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
};
static const struct gpio_keys_button
-bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
@@ -288,6 +293,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
+/* Microsoft */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_microsoft_nm700[] __initconst = {
+ BCM47XX_GPIO_KEY(7, KEY_RESTART),
+};
+
/* Motorola */
static const struct gpio_keys_button
@@ -329,6 +341,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
};
static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
+ BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
@@ -395,6 +413,9 @@ int __init bcm47xx_buttons_register(void)
case BCM47XX_BOARD_ASUS_WL330GE:
err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
break;
+ case BCM47XX_BOARD_ASUS_WL500G:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
+ break;
case BCM47XX_BOARD_ASUS_WL500GD:
err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
break;
@@ -501,12 +522,14 @@ int __init bcm47xx_buttons_register(void)
case BCM47XX_BOARD_LINKSYS_WRT310NV1:
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
break;
- case BCM47XX_BOARD_LINKSYS_WRT54G:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
- break;
case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
+ break;
case BCM47XX_BOARD_LINKSYS_WRT610NV1:
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
break;
@@ -517,6 +540,10 @@ int __init bcm47xx_buttons_register(void)
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
break;
+ case BCM47XX_BOARD_MICROSOFT_MN700:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
+ break;
+
case BCM47XX_BOARD_MOTOROLA_WE800G:
err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
break;
@@ -536,6 +563,9 @@ int __init bcm47xx_buttons_register(void)
case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
break;
+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
+ break;
case BCM47XX_BOARD_NETGEAR_WNR834BV2:
err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
break;
diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c
index adcb547a91c3..903a656d4119 100644
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -35,6 +35,15 @@ bcm47xx_leds_asus_rtn12[] __initconst = {
};
static const struct gpio_led
+bcm47xx_leds_asus_rtn15u[] __initconst = {
+ /* TODO: Add "wlan" LED */
+ BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
bcm47xx_leds_asus_rtn16[] __initconst = {
BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -42,8 +51,8 @@ bcm47xx_leds_asus_rtn16[] __initconst = {
static const struct gpio_led
bcm47xx_leds_asus_rtn66u[] __initconst = {
- BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
};
static const struct gpio_led
@@ -64,6 +73,11 @@ bcm47xx_leds_asus_wl330ge[] __initconst = {
};
static const struct gpio_led
+bcm47xx_leds_asus_wl500g[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
bcm47xx_leds_asus_wl500gd[] __initconst = {
BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
};
@@ -216,8 +230,8 @@ bcm47xx_leds_linksys_e1000v1[] __initconst = {
static const struct gpio_led
bcm47xx_leds_linksys_e1000v21[] __initconst = {
- BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
};
@@ -292,7 +306,7 @@ bcm47xx_leds_linksys_wrt310nv1[] __initconst = {
};
static const struct gpio_led
-bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -306,6 +320,24 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __initconst = {
BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
};
+/* Verified on: WRT54GS V1.0 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
+ BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Verified on: WRT54GL V1.1 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
+ BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
static const struct gpio_led
bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -325,11 +357,17 @@ bcm47xx_leds_linksys_wrt610nv2[] __initconst = {
static const struct gpio_led
bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
- BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Microsoft */
+
+static const struct gpio_led
+bcm47xx_leds_microsoft_nm700[] __initconst = {
+ BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
};
/* Motorola */
@@ -377,6 +415,15 @@ bcm47xx_leds_netgear_wndr4500v1[] __initconst = {
};
static const struct gpio_led
+bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -417,6 +464,9 @@ void __init bcm47xx_leds_register(void)
case BCM47XX_BOARD_ASUS_RTN12:
bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
break;
+ case BCM47XX_BOARD_ASUS_RTN15U:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
+ break;
case BCM47XX_BOARD_ASUS_RTN16:
bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
break;
@@ -432,6 +482,9 @@ void __init bcm47xx_leds_register(void)
case BCM47XX_BOARD_ASUS_WL330GE:
bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
break;
+ case BCM47XX_BOARD_ASUS_WL500G:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
+ break;
case BCM47XX_BOARD_ASUS_WL500GD:
bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
break;
@@ -538,12 +591,18 @@ void __init bcm47xx_leds_register(void)
case BCM47XX_BOARD_LINKSYS_WRT310NV1:
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
break;
- case BCM47XX_BOARD_LINKSYS_WRT54G:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
- break;
case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+ break;
case BCM47XX_BOARD_LINKSYS_WRT610NV1:
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
break;
@@ -554,6 +613,10 @@ void __init bcm47xx_leds_register(void)
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
break;
+ case BCM47XX_BOARD_MICROSOFT_MN700:
+ bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
+ break;
+
case BCM47XX_BOARD_MOTOROLA_WE800G:
bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
break;
@@ -570,6 +633,9 @@ void __init bcm47xx_leds_register(void)
case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
break;
+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
+ break;
case BCM47XX_BOARD_NETGEAR_WNR834BV2:
bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
break;
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index 1a03a2f43496..1b170bf5f7f0 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -51,6 +51,8 @@ __init void bcm47xx_set_system_type(u16 chip_id)
chip_id);
}
+static unsigned long lowmem __initdata;
+
static __init void prom_init_mem(void)
{
unsigned long mem;
@@ -87,6 +89,7 @@ static __init void prom_init_mem(void)
if (!memcmp(prom_init, prom_init + mem, 32))
break;
}
+ lowmem = mem;
/* Ignoring the last page when ddr size is 128M. Cached
* accesses to last page is causing the processor to prefetch
@@ -95,7 +98,6 @@ static __init void prom_init_mem(void)
*/
if (c->cputype == CPU_74K && (mem == (128 << 20)))
mem -= 0x1000;
-
add_memory_region(0, mem, BOOT_MEM_RAM);
}
@@ -114,3 +116,67 @@ void __init prom_init(void)
void __init prom_free_prom_memory(void)
{
}
+
+#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
+
+#define EXTVBASE 0xc0000000
+#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
+
+#include <asm/tlbflush.h>
+
+/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
+ * dropped. Calling it at this stage causes a hang.
+ */
+void __cpuinit early_tlb_init(void)
+{
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
+ temp_tlb_entry = current_cpu_data.tlbsize - 1;
+ local_flush_tlb_all();
+}
+
+void __init bcm47xx_prom_highmem_init(void)
+{
+ unsigned long off = (unsigned long)prom_init;
+ unsigned long extmem = 0;
+ bool highmem_region = false;
+
+ if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
+ return;
+
+ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
+ highmem_region = true;
+
+ if (lowmem != 128 << 20 || !highmem_region)
+ return;
+
+ early_tlb_init();
+
+ /* Add one temporary TLB entry to map SDRAM Region 2.
+ * Physical Virtual
+ * 0x80000000 0xc0000000 (1st: 256MB)
+ * 0x90000000 0xd0000000 (2nd: 256MB)
+ */
+ add_temporary_entry(ENTRYLO(0x80000000),
+ ENTRYLO(0x80000000 + (256 << 20)),
+ EXTVBASE, PM_256M);
+
+ off = EXTVBASE + __pa(off);
+ for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
+ if (!memcmp(prom_init, (void *)(off + extmem), 16))
+ break;
+ }
+ extmem -= lowmem;
+
+ early_tlb_init();
+
+ if (!extmem)
+ return;
+
+ pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
+ extmem >> 20);
+
+ /* TODO: Register extra memory */
+}
+
+#endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 63a4b0e915dc..2b63e7e7d3d3 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -59,12 +59,12 @@ static void bcm47xx_machine_restart(char *command)
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
- ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 3);
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
- bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 3);
break;
#endif
}
@@ -218,6 +218,9 @@ void __init plat_mem_setup(void)
bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
bcm47xx_register_bcma();
bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
+#ifdef CONFIG_HIGHMEM
+ bcm47xx_prom_highmem_init();
+#endif
#endif
} else {
printk(KERN_INFO "bcm47xx: using ssb bus\n");
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
index da4cdb16844e..41226b68de3d 100644
--- a/arch/mips/bcm47xx/sprom.c
+++ b/arch/mips/bcm47xx/sprom.c
@@ -28,6 +28,8 @@
#include <bcm47xx.h>
#include <bcm47xx_nvram.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
static void create_key(const char *prefix, const char *postfix,
const char *name, char *buf, int len)
@@ -631,6 +633,33 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
}
}
+static bool bcm47xx_is_valid_mac(u8 *mac)
+{
+ return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
+}
+
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
+{
+ u8 *oui = mac + ETH_ALEN/2 - 1;
+ u8 *p = mac + ETH_ALEN - 1;
+
+ do {
+ (*p) += num;
+ if (*p > num)
+ break;
+ p--;
+ num = 1;
+ } while (p != oui);
+
+ if (p == oui) {
+ pr_err("unable to fetch mac address\n");
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static int mac_addr_used = 2;
+
static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
const char *prefix, bool fallback)
{
@@ -648,6 +677,25 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+
+ /* The address prefix 00:90:4C is used by Broadcom in their initial
+ configuration. When a mac address with the prefix 00:90:4C is used
+ all devices from the same series are sharing the same mac address.
+ To prevent mac address collisions we replace them with a mac address
+ based on the base address. */
+ if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
+ u8 mac[6];
+
+ nvram_read_macaddr(NULL, "et0macaddr", mac, false);
+ if (bcm47xx_is_valid_mac(mac)) {
+ int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
+
+ if (!err) {
+ ether_addr_copy(sprom->il0mac, mac);
+ mac_addr_used++;
+ }
+ }
+ }
}
static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c
index fd4e76c00a42..536f64443031 100644
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -24,7 +24,9 @@ EXPORT_SYMBOL(bcm63xx_regs_base);
const int *bcm63xx_irqs;
EXPORT_SYMBOL(bcm63xx_irqs);
-static u16 bcm63xx_cpu_id;
+u16 bcm63xx_cpu_id __read_mostly;
+EXPORT_SYMBOL(bcm63xx_cpu_id);
+
static u8 bcm63xx_cpu_rev;
static unsigned int bcm63xx_cpu_freq;
static unsigned int bcm63xx_memory_size;
@@ -97,13 +99,6 @@ static const int bcm6368_irqs[] = {
};
-u16 __bcm63xx_get_cpu_id(void)
-{
- return bcm63xx_cpu_id;
-}
-
-EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
-
u8 bcm63xx_get_cpu_rev(void)
{
return bcm63xx_cpu_rev;
diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c
index 52bc01df9bfe..e8284771d620 100644
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -14,7 +14,6 @@
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
-#ifdef BCMCPU_RUNTIME_DETECT
static const unsigned long bcm6348_regs_enetdmac[] = {
[ENETDMAC_CHANCFG] = ENETDMAC_CHANCFG_REG,
[ENETDMAC_IR] = ENETDMAC_IR_REG,
@@ -43,9 +42,6 @@ static __init void bcm63xx_enetdmac_regs_init(void)
else
bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
}
-#else
-static __init void bcm63xx_enetdmac_regs_init(void) { }
-#endif
static struct resource shared_res[] = {
{
diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c
index d12daed749bc..ad448e41e3bd 100644
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -18,7 +18,6 @@
#include <bcm63xx_dev_spi.h>
#include <bcm63xx_regs.h>
-#ifdef BCMCPU_RUNTIME_DETECT
/*
* register offsets
*/
@@ -41,9 +40,6 @@ static __init void bcm63xx_spi_regs_init(void)
BCMCPU_IS_6362() || BCMCPU_IS_6368())
bcm63xx_regs_spi = bcm6358_regs_spi;
}
-#else
-static __init void bcm63xx_spi_regs_init(void) { }
-#endif
static struct resource spi_resources[] = {
{
diff --git a/arch/mips/bcm63xx/gpio.c b/arch/mips/bcm63xx/gpio.c
index a6c2135dbf38..468bc7b99cd3 100644
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -18,19 +18,6 @@
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
-#ifndef BCMCPU_RUNTIME_DETECT
-#define gpio_out_low_reg GPIO_DATA_LO_REG
-#ifdef CONFIG_BCM63XX_CPU_6345
-#ifdef gpio_out_low_reg
-#undef gpio_out_low_reg
-#define gpio_out_low_reg GPIO_DATA_LO_REG_6345
-#endif /* gpio_out_low_reg */
-#endif /* CONFIG_BCM63XX_CPU_6345 */
-
-static inline void bcm63xx_gpio_out_low_reg_init(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
static u32 gpio_out_low_reg;
static void bcm63xx_gpio_out_low_reg_init(void)
@@ -44,7 +31,6 @@ static void bcm63xx_gpio_out_low_reg_init(void)
break;
}
}
-#endif /* ! BCMCPU_RUNTIME_DETECT */
static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
static u32 gpio_out_low, gpio_out_high;
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index 1525f8a3841b..37eb2d1fa69a 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/irq.h>
+#include <linux/spinlock.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <bcm63xx_cpu.h>
@@ -19,222 +20,20 @@
#include <bcm63xx_io.h>
#include <bcm63xx_irq.h>
-static void __dispatch_internal(void) __maybe_unused;
-static void __dispatch_internal_64(void) __maybe_unused;
-static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
-
-#ifndef BCMCPU_RUNTIME_DETECT
-#ifdef CONFIG_BCM63XX_CPU_3368
-#define irq_stat_reg PERF_IRQSTAT_3368_REG
-#define irq_mask_reg PERF_IRQMASK_3368_REG
-#define irq_bits 32
-#define is_ext_irq_cascaded 0
-#define ext_irq_start 0
-#define ext_irq_end 0
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_3368
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-#define irq_stat_reg PERF_IRQSTAT_6328_REG
-#define irq_mask_reg PERF_IRQMASK_6328_REG
-#define irq_bits 64
-#define is_ext_irq_cascaded 1
-#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6328
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-#define irq_stat_reg PERF_IRQSTAT_6338_REG
-#define irq_mask_reg PERF_IRQMASK_6338_REG
-#define irq_bits 32
-#define is_ext_irq_cascaded 0
-#define ext_irq_start 0
-#define ext_irq_end 0
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6338
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-#define irq_stat_reg PERF_IRQSTAT_6345_REG
-#define irq_mask_reg PERF_IRQMASK_6345_REG
-#define irq_bits 32
-#define is_ext_irq_cascaded 0
-#define ext_irq_start 0
-#define ext_irq_end 0
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6345
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-#define irq_stat_reg PERF_IRQSTAT_6348_REG
-#define irq_mask_reg PERF_IRQMASK_6348_REG
-#define irq_bits 32
-#define is_ext_irq_cascaded 0
-#define ext_irq_start 0
-#define ext_irq_end 0
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6348
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-#define irq_stat_reg PERF_IRQSTAT_6358_REG
-#define irq_mask_reg PERF_IRQMASK_6358_REG
-#define irq_bits 32
-#define is_ext_irq_cascaded 1
-#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-#define irq_stat_reg PERF_IRQSTAT_6362_REG
-#define irq_mask_reg PERF_IRQMASK_6362_REG
-#define irq_bits 64
-#define is_ext_irq_cascaded 1
-#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count 4
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6362
-#define ext_irq_cfg_reg2 0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-#define irq_stat_reg PERF_IRQSTAT_6368_REG
-#define irq_mask_reg PERF_IRQMASK_6368_REG
-#define irq_bits 64
-#define is_ext_irq_cascaded 1
-#define ext_irq_start (BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end (BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE)
-#define ext_irq_count 6
-#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6368
-#define ext_irq_cfg_reg2 PERF_EXTIRQ_CFG_REG2_6368
-#endif
-
-#if irq_bits == 32
-#define dispatch_internal __dispatch_internal
-#define internal_irq_mask __internal_irq_mask_32
-#define internal_irq_unmask __internal_irq_unmask_32
-#else
-#define dispatch_internal __dispatch_internal_64
-#define internal_irq_mask __internal_irq_mask_64
-#define internal_irq_unmask __internal_irq_unmask_64
-#endif
-#define irq_stat_addr (bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
-#define irq_mask_addr (bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
+static DEFINE_SPINLOCK(ipic_lock);
+static DEFINE_SPINLOCK(epic_lock);
-static inline void bcm63xx_init_irq(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
-
-static u32 irq_stat_addr, irq_mask_addr;
-static void (*dispatch_internal)(void);
+static u32 irq_stat_addr[2];
+static u32 irq_mask_addr[2];
+static void (*dispatch_internal)(int cpu);
static int is_ext_irq_cascaded;
static unsigned int ext_irq_count;
static unsigned int ext_irq_start, ext_irq_end;
static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(unsigned int irq);
-static void (*internal_irq_unmask)(unsigned int irq);
+static void (*internal_irq_mask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
-static void bcm63xx_init_irq(void)
-{
- int irq_bits;
-
- irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
- irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
-
- switch (bcm63xx_get_cpu_id()) {
- case BCM3368_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_3368_REG;
- irq_mask_addr += PERF_IRQMASK_3368_REG;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
- break;
- case BCM6328_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6328_REG;
- irq_mask_addr += PERF_IRQMASK_6328_REG;
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
- break;
- case BCM6338_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6338_REG;
- irq_mask_addr += PERF_IRQMASK_6338_REG;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
- break;
- case BCM6345_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6345_REG;
- irq_mask_addr += PERF_IRQMASK_6345_REG;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
- break;
- case BCM6348_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6348_REG;
- irq_mask_addr += PERF_IRQMASK_6348_REG;
- irq_bits = 32;
- ext_irq_count = 4;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
- break;
- case BCM6358_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6358_REG;
- irq_mask_addr += PERF_IRQMASK_6358_REG;
- irq_bits = 32;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
- break;
- case BCM6362_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6362_REG;
- irq_mask_addr += PERF_IRQMASK_6362_REG;
- irq_bits = 64;
- ext_irq_count = 4;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
- break;
- case BCM6368_CPU_ID:
- irq_stat_addr += PERF_IRQSTAT_6368_REG;
- irq_mask_addr += PERF_IRQMASK_6368_REG;
- irq_bits = 64;
- ext_irq_count = 6;
- is_ext_irq_cascaded = 1;
- ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
- ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
- ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
- ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
- break;
- default:
- BUG();
- }
-
- if (irq_bits == 32) {
- dispatch_internal = __dispatch_internal;
- internal_irq_mask = __internal_irq_mask_32;
- internal_irq_unmask = __internal_irq_unmask_32;
- } else {
- dispatch_internal = __dispatch_internal_64;
- internal_irq_mask = __internal_irq_mask_64;
- internal_irq_unmask = __internal_irq_unmask_64;
- }
-}
-#endif /* ! BCMCPU_RUNTIME_DETECT */
static inline u32 get_ext_irq_perf_reg(int irq)
{
@@ -252,53 +51,113 @@ static inline void handle_internal(int intbit)
do_IRQ(intbit + IRQ_INTERNAL_BASE);
}
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+ const struct cpumask *m)
+{
+ bool enable = cpu_online(cpu);
+
+#ifdef CONFIG_SMP
+ if (m)
+ enable &= cpu_isset(cpu, *m);
+ else if (irqd_affinity_was_set(d))
+ enable &= cpu_isset(cpu, *d->affinity);
+#endif
+ return enable;
+}
+
/*
* dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
* prioritize any interrupt relatively to another. the static counter
* will resume the loop where it ended the last time we left this
* function.
*/
-static void __dispatch_internal(void)
-{
- u32 pending;
- static int i;
-
- pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
- if (!pending)
- return ;
-
- while (1) {
- int to_call = i;
-
- i = (i + 1) & 0x1f;
- if (pending & (1 << to_call)) {
- handle_internal(to_call);
- break;
- }
- }
+#define BUILD_IPIC_INTERNAL(width) \
+void __dispatch_internal_##width(int cpu) \
+{ \
+ u32 pending[width / 32]; \
+ unsigned int src, tgt; \
+ bool irqs_pending = false; \
+ static unsigned int i[2]; \
+ unsigned int *next = &i[cpu]; \
+ unsigned long flags; \
+ \
+ /* read registers in reverse order */ \
+ spin_lock_irqsave(&ipic_lock, flags); \
+ for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
+ u32 val; \
+ \
+ val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
+ val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
+ pending[--tgt] = val; \
+ \
+ if (val) \
+ irqs_pending = true; \
+ } \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
+ \
+ if (!irqs_pending) \
+ return; \
+ \
+ while (1) { \
+ unsigned int to_call = *next; \
+ \
+ *next = (*next + 1) & (width - 1); \
+ if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
+ handle_internal(to_call); \
+ break; \
+ } \
+ } \
+} \
+ \
+static void __internal_irq_mask_##width(struct irq_data *d) \
+{ \
+ u32 val; \
+ unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
+ unsigned reg = (irq / 32) ^ (width/32 - 1); \
+ unsigned bit = irq & 0x1f; \
+ unsigned long flags; \
+ int cpu; \
+ \
+ spin_lock_irqsave(&ipic_lock, flags); \
+ for_each_present_cpu(cpu) { \
+ if (!irq_mask_addr[cpu]) \
+ break; \
+ \
+ val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+ val &= ~(1 << bit); \
+ bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+ } \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
+} \
+ \
+static void __internal_irq_unmask_##width(struct irq_data *d, \
+ const struct cpumask *m) \
+{ \
+ u32 val; \
+ unsigned irq = d->irq - IRQ_INTERNAL_BASE; \
+ unsigned reg = (irq / 32) ^ (width/32 - 1); \
+ unsigned bit = irq & 0x1f; \
+ unsigned long flags; \
+ int cpu; \
+ \
+ spin_lock_irqsave(&ipic_lock, flags); \
+ for_each_present_cpu(cpu) { \
+ if (!irq_mask_addr[cpu]) \
+ break; \
+ \
+ val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+ if (enable_irq_for_cpu(cpu, d, m)) \
+ val |= (1 << bit); \
+ else \
+ val &= ~(1 << bit); \
+ bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+ } \
+ spin_unlock_irqrestore(&ipic_lock, flags); \
}
-static void __dispatch_internal_64(void)
-{
- u64 pending;
- static int i;
-
- pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
-
- if (!pending)
- return ;
-
- while (1) {
- int to_call = i;
-
- i = (i + 1) & 0x3f;
- if (pending & (1ull << to_call)) {
- handle_internal(to_call);
- break;
- }
- }
-}
+BUILD_IPIC_INTERNAL(32);
+BUILD_IPIC_INTERNAL(64);
asmlinkage void plat_irq_dispatch(void)
{
@@ -317,8 +176,11 @@ asmlinkage void plat_irq_dispatch(void)
if (cause & CAUSEF_IP1)
do_IRQ(1);
if (cause & CAUSEF_IP2)
- dispatch_internal();
- if (!is_ext_irq_cascaded) {
+ dispatch_internal(0);
+ if (is_ext_irq_cascaded) {
+ if (cause & CAUSEF_IP3)
+ dispatch_internal(1);
+ } else {
if (cause & CAUSEF_IP3)
do_IRQ(IRQ_EXT_0);
if (cause & CAUSEF_IP4)
@@ -335,50 +197,14 @@ asmlinkage void plat_irq_dispatch(void)
* internal IRQs operations: only mask/unmask on PERF irq mask
* register.
*/
-static void __internal_irq_mask_32(unsigned int irq)
-{
- u32 mask;
-
- mask = bcm_readl(irq_mask_addr);
- mask &= ~(1 << irq);
- bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_mask_64(unsigned int irq)
-{
- u64 mask;
-
- mask = bcm_readq(irq_mask_addr);
- mask &= ~(1ull << irq);
- bcm_writeq(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_32(unsigned int irq)
-{
- u32 mask;
-
- mask = bcm_readl(irq_mask_addr);
- mask |= (1 << irq);
- bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_64(unsigned int irq)
-{
- u64 mask;
-
- mask = bcm_readq(irq_mask_addr);
- mask |= (1ull << irq);
- bcm_writeq(mask, irq_mask_addr);
-}
-
static void bcm63xx_internal_irq_mask(struct irq_data *d)
{
- internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
+ internal_irq_mask(d);
}
static void bcm63xx_internal_irq_unmask(struct irq_data *d)
{
- internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
+ internal_irq_unmask(d, NULL);
}
/*
@@ -389,8 +215,10 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -399,16 +227,20 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
reg &= ~EXTIRQ_CFG_MASK(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
+
if (is_ext_irq_cascaded)
- internal_irq_mask(irq + ext_irq_start);
+ internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
}
static void bcm63xx_external_irq_unmask(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -417,17 +249,21 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d)
reg |= EXTIRQ_CFG_MASK(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
if (is_ext_irq_cascaded)
- internal_irq_unmask(irq + ext_irq_start);
+ internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+ NULL);
}
static void bcm63xx_external_irq_clear(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
+ unsigned long flags;
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
if (BCMCPU_IS_6348())
@@ -436,6 +272,7 @@ static void bcm63xx_external_irq_clear(struct irq_data *d)
reg |= EXTIRQ_CFG_CLEAR(irq % 4);
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
}
static int bcm63xx_external_irq_set_type(struct irq_data *d,
@@ -444,6 +281,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
u32 reg, regaddr;
int levelsense, sense, bothedge;
+ unsigned long flags;
flow_type &= IRQ_TYPE_SENSE_MASK;
@@ -478,6 +316,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
}
regaddr = get_ext_irq_perf_reg(irq);
+ spin_lock_irqsave(&epic_lock, flags);
reg = bcm_perf_readl(regaddr);
irq %= 4;
@@ -522,6 +361,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
}
bcm_perf_writel(reg, regaddr);
+ spin_unlock_irqrestore(&epic_lock, flags);
irqd_set_trigger_type(d, flow_type);
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -532,6 +372,18 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
return IRQ_SET_MASK_OK_NOCOPY;
}
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+ const struct cpumask *dest,
+ bool force)
+{
+ if (!irqd_irq_disabled(data))
+ internal_irq_unmask(data, dest);
+
+ return 0;
+}
+#endif
+
static struct irq_chip bcm63xx_internal_irq_chip = {
.name = "bcm63xx_ipic",
.irq_mask = bcm63xx_internal_irq_mask,
@@ -554,12 +406,130 @@ static struct irqaction cpu_ip2_cascade_action = {
.flags = IRQF_NO_THREAD,
};
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+ .handler = no_action,
+ .name = "cascade_ip3",
+ .flags = IRQF_NO_THREAD,
+};
+#endif
+
static struct irqaction cpu_ext_cascade_action = {
.handler = no_action,
.name = "cascade_extirq",
.flags = IRQF_NO_THREAD,
};
+static void bcm63xx_init_irq(void)
+{
+ int irq_bits;
+
+ irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
+ irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
+ irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
+ irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM3368_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
+ irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
+ irq_stat_addr[1] = 0;
+ irq_stat_addr[1] = 0;
+ irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+ break;
+ case BCM6328_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
+ irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+ irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
+ irq_stat_addr[1] += PERF_IRQMASK_6328_REG(1);
+ irq_bits = 64;
+ ext_irq_count = 4;
+ is_ext_irq_cascaded = 1;
+ ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+ ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+ break;
+ case BCM6338_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
+ irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
+ irq_stat_addr[1] = 0;
+ irq_mask_addr[1] = 0;
+ irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+ break;
+ case BCM6345_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
+ irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
+ irq_stat_addr[1] = 0;
+ irq_mask_addr[1] = 0;
+ irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+ break;
+ case BCM6348_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
+ irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
+ irq_stat_addr[1] = 0;
+ irq_mask_addr[1] = 0;
+ irq_bits = 32;
+ ext_irq_count = 4;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+ break;
+ case BCM6358_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
+ irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
+ irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
+ irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
+ irq_bits = 32;
+ ext_irq_count = 4;
+ is_ext_irq_cascaded = 1;
+ ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+ ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+ break;
+ case BCM6362_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
+ irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
+ irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
+ irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
+ irq_bits = 64;
+ ext_irq_count = 4;
+ is_ext_irq_cascaded = 1;
+ ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+ ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+ break;
+ case BCM6368_CPU_ID:
+ irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
+ irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
+ irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
+ irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
+ irq_bits = 64;
+ ext_irq_count = 6;
+ is_ext_irq_cascaded = 1;
+ ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+ ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
+ ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+ break;
+ default:
+ BUG();
+ }
+
+ if (irq_bits == 32) {
+ dispatch_internal = __dispatch_internal_32;
+ internal_irq_mask = __internal_irq_mask_32;
+ internal_irq_unmask = __internal_irq_unmask_32;
+ } else {
+ dispatch_internal = __dispatch_internal_64;
+ internal_irq_mask = __internal_irq_mask_64;
+ internal_irq_unmask = __internal_irq_unmask_64;
+ }
+}
+
void __init arch_init_irq(void)
{
int i;
@@ -580,4 +550,14 @@ void __init arch_init_irq(void)
}
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+ if (is_ext_irq_cascaded) {
+ setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+ bcm63xx_internal_irq_chip.irq_set_affinity =
+ bcm63xx_internal_set_affinity;
+
+ cpumask_clear(irq_default_affinity);
+ cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+ }
+#endif
}
diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c
index acbeb1fe7c57..d1fe51edf5e6 100644
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -125,8 +125,6 @@
#define BCM6368_RESET_PCIE 0
#define BCM6368_RESET_PCIE_EXT 0
-#ifdef BCMCPU_RUNTIME_DETECT
-
/*
* core reset bits
*/
@@ -188,64 +186,6 @@ static int __init bcm63xx_reset_bits_init(void)
return 0;
}
-#else
-
-#ifdef CONFIG_BCM63XX_CPU_3368
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(3368)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6328
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6328)
-};
-#define reset_reg PERF_SOFTRESET_6328_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6338
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6338)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6345
-static const u32 bcm63xx_reset_bits[] = { };
-#define reset_reg 0
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6348
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6348)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6358
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6358)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6362
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6362)
-};
-#define reset_reg PERF_SOFTRESET_6362_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6368
-static const u32 bcm63xx_reset_bits[] = {
- __GEN_RESET_BITS_TABLE(6368)
-};
-#define reset_reg PERF_SOFTRESET_6368_REG
-#endif
-
-static int __init bcm63xx_reset_bits_init(void) { return 0; }
-#endif
static DEFINE_SPINLOCK(reset_mutex);
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index c00c4ddf4514..b49c7adbfa89 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -67,10 +67,24 @@ void error(char *x)
#include "../../../../lib/decompress_unxz.c"
#endif
+unsigned long __stack_chk_guard;
+
+void __stack_chk_guard_setup(void)
+{
+ __stack_chk_guard = 0x000a0dff;
+}
+
+void __stack_chk_fail(void)
+{
+ error("stack-protector: Kernel stack is corrupted\n");
+}
+
void decompress_kernel(unsigned long boot_heap_start)
{
unsigned long zimage_start, zimage_size;
+ __stack_chk_guard_setup();
+
zimage_start = (unsigned long)(&__image_begin);
zimage_size = (unsigned long)(&__image_end) -
(unsigned long)(&__image_begin);
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index b764df64be40..5dfef84b9576 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -186,6 +186,15 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return 7 - ipd_port;
else
return -1;
+ case CVMX_BOARD_TYPE_CUST_DSR1000N:
+ /*
+ * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1)
+ * connect to a switch (BCM53115).
+ */
+ if (ipd_port == 2)
+ return 8;
+ else
+ return -1;
}
/* Some unknown board. Somebody forgot to update this function... */
@@ -274,6 +283,18 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
return result;
}
break;
+ case CVMX_BOARD_TYPE_CUST_DSR1000N:
+ if (ipd_port == 0 || ipd_port == 1) {
+ /* Ports 0 and 1 connect to a switch (BCM53115). */
+ result.s.link_up = 1;
+ result.s.full_duplex = 1;
+ result.s.speed = 1000;
+ return result;
+ } else {
+ /* Port 2 uses a Broadcom PHY (B5081). */
+ is_broadcom_phy = 1;
+ }
+ break;
}
phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
@@ -738,6 +759,7 @@ enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(vo
case CVMX_BOARD_TYPE_LANAI2_G:
case CVMX_BOARD_TYPE_NIC10E_66:
case CVMX_BOARD_TYPE_UBNT_E100:
+ case CVMX_BOARD_TYPE_CUST_DSR1000N:
return USB_CLOCK_TYPE_CRYSTAL_12;
case CVMX_BOARD_TYPE_NIC10E:
return USB_CLOCK_TYPE_REF_12;
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c b/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
index 45f18cce31a9..6f9609e63a65 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-sgmii.c
@@ -317,10 +317,14 @@ static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports)
for (index = 0; index < num_ports; index++) {
int ipd_port = cvmx_helper_get_ipd_port(interface, index);
__cvmx_helper_sgmii_hardware_init_one_time(interface, index);
- __cvmx_helper_sgmii_link_set(ipd_port,
- __cvmx_helper_sgmii_link_get
- (ipd_port));
-
+ /* Linux kernel driver will call ....link_set with the
+ * proper link state. In the simulator there is no
+ * link state polling and hence it is set from
+ * here.
+ */
+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
+ __cvmx_helper_sgmii_link_set(ipd_port,
+ __cvmx_helper_sgmii_link_get(ipd_port));
}
return 0;
diff --git a/arch/mips/cavium-octeon/oct_ilm.c b/arch/mips/cavium-octeon/oct_ilm.c
index 71b213dbb621..2d68a39f1443 100644
--- a/arch/mips/cavium-octeon/oct_ilm.c
+++ b/arch/mips/cavium-octeon/oct_ilm.c
@@ -194,8 +194,7 @@ err_irq:
static __exit void oct_ilm_module_exit(void)
{
disable_timer(TIMER_NUM);
- if (dir)
- debugfs_remove_recursive(dir);
+ debugfs_remove_recursive(dir);
free_irq(OCTEON_IRQ_TIMER0 + TIMER_NUM, 0);
}
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index a7b3ae104d8c..ecd903dd1c45 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -84,9 +84,14 @@ static void octeon_smp_hotplug_setup(void)
#ifdef CONFIG_HOTPLUG_CPU
struct linux_app_boot_info *labi;
+ if (!setup_max_cpus)
+ return;
+
labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
- if (labi->labi_signature != LABI_SIGNATURE)
- panic("The bootloader version on this board is incorrect.");
+ if (labi->labi_signature != LABI_SIGNATURE) {
+ pr_info("The bootloader on this board does not support HOTPLUG_CPU.");
+ return;
+ }
octeon_bootloader_entry_addr = labi->InitTLBStart_addr;
#endif
@@ -129,7 +134,8 @@ static void octeon_smp_setup(void)
* will assign CPU numbers for possible cores as well. Cores
* are always consecutively numberd from 0.
*/
- for (id = 0; id < num_cores && id < NR_CPUS; id++) {
+ for (id = 0; setup_max_cpus && octeon_bootloader_entry_addr &&
+ id < num_cores && id < NR_CPUS; id++) {
if (!(core_mask & (1 << id))) {
set_cpu_possible(cpus, true);
__cpu_number_map[id] = cpus;
@@ -192,14 +198,6 @@ static void octeon_init_secondary(void)
*/
void octeon_prepare_cpus(unsigned int max_cpus)
{
-#ifdef CONFIG_HOTPLUG_CPU
- struct linux_app_boot_info *labi;
-
- labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
- if (labi->labi_signature != LABI_SIGNATURE)
- panic("The bootloader version on this board is incorrect.");
-#endif
/*
* Only the low order mailbox bits are used for IPIs, leave
* the other bits alone.
@@ -237,6 +235,9 @@ static int octeon_cpu_disable(void)
if (cpu == 0)
return -EBUSY;
+ if (!octeon_bootloader_entry_addr)
+ return -ENOTSUPP;
+
set_cpu_online(cpu, false);
cpu_clear(cpu, cpu_callin_map);
local_irq_disable();
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
index dace58268ce1..b2476a1c4aaa 100644
--- a/arch/mips/configs/cavium_octeon_defconfig
+++ b/arch/mips/configs/cavium_octeon_defconfig
@@ -124,7 +124,6 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_STAGING=y
CONFIG_OCTEON_ETHERNET=y
-# CONFIG_NET_VENDOR_SILICOM is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig
index a64b30b96a0d..46e8f7676a15 100644
--- a/arch/mips/configs/db1xxx_defconfig
+++ b/arch/mips/configs/db1xxx_defconfig
@@ -116,7 +116,6 @@ CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_SPI_NOR=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_AT25=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_MULTI_LUN=y
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 87d0340837aa..ebc011c51e5a 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -45,7 +45,6 @@ CONFIG_VLAN_8021Q=m
CONFIG_CONNECTOR=m
CONFIG_BLK_DEV_LOOP=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 936ec5a5ed8d..57ed466e00db 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -219,7 +219,6 @@ CONFIG_ATA_OVER_ETH=m
# CONFIG_MISC_DEVICES is not set
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 0e36abcd39cc..cc0756021398 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -106,7 +106,6 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
# CONFIG_MISC_DEVICES is not set
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 7bbd52194fc3..70ffe9b55829 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -54,7 +54,6 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_SGI_IOC4=y
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 0315ee37a20b..2575302aa2be 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -208,7 +208,6 @@ CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
index ea1761f0f917..4cb787ff273e 100644
--- a/arch/mips/configs/loongson3_defconfig
+++ b/arch/mips/configs/loongson3_defconfig
@@ -1,6 +1,6 @@
CONFIG_MACH_LOONGSON=y
CONFIG_SWIOTLB=y
-CONFIG_LEMOTE_MACH3A=y
+CONFIG_LOONGSON_MACH3X=y
CONFIG_CPU_LOONGSON3=y
CONFIG_64BIT=y
CONFIG_PAGE_SIZE_16KB=y
@@ -120,7 +120,6 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index b745b6a9f322..e18741ea1771 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -253,7 +253,6 @@ CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=m
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig
index 4f7d952d8517..cf0e01f814e1 100644
--- a/arch/mips/configs/malta_kvm_defconfig
+++ b/arch/mips/configs/malta_kvm_defconfig
@@ -254,7 +254,6 @@ CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=m
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig
index e36681c24ddc..edd9ec9cb678 100644
--- a/arch/mips/configs/malta_kvm_guest_defconfig
+++ b/arch/mips/configs/malta_kvm_guest_defconfig
@@ -254,7 +254,6 @@ CONFIG_BLK_DEV_IT8213=m
CONFIG_BLK_DEV_TC86C001=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=m
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index 4c2c0c4b9bb1..0f08e4623ee4 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -134,7 +134,6 @@ CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_SGI_IOC4=m
CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=m
CONFIG_CHR_DEV_SG=m
diff --git a/arch/mips/configs/nlm_xlp_defconfig b/arch/mips/configs/nlm_xlp_defconfig
index 5468b1c7b2a5..2f660e9a0da6 100644
--- a/arch/mips/configs/nlm_xlp_defconfig
+++ b/arch/mips/configs/nlm_xlp_defconfig
@@ -334,7 +334,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_CDROM_PKTCDVD=y
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
@@ -346,10 +345,8 @@ CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_TGT_ATTRS=y
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_ISCSI_TCP=m
CONFIG_LIBFCOE=m
CONFIG_SCSI_DEBUG=m
diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig
index 44b473420d51..c6f84655c98a 100644
--- a/arch/mips/configs/nlm_xlr_defconfig
+++ b/arch/mips/configs/nlm_xlr_defconfig
@@ -311,7 +311,6 @@ CONFIG_CDROM_PKTCDVD=y
CONFIG_MISC_DEVICES=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
@@ -323,10 +322,8 @@ CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_TGT_ATTRS=y
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_ISCSI_TCP=m
CONFIG_LIBFCOE=m
CONFIG_SCSI_DEBUG=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 73e7bf49461c..29d79ae8a823 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -221,7 +221,6 @@ CONFIG_ATA_OVER_ETH=m
CONFIG_SGI_IOC4=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index d99b1905a1ba..9327b3af32cd 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -39,7 +39,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_XIP=y
# CONFIG_MISC_DEVICES is not set
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_SCAN_ASYNC=y
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index c415c4f0e5c2..a967289b7970 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -44,7 +44,6 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_XIP=y
# CONFIG_MISC_DEVICES is not set
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SCAN_ASYNC=y
# CONFIG_SCSI_LOWLEVEL is not set
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 05439187891d..335e5290ec75 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -15,4 +15,5 @@ generic-y += segment.h
generic-y += serial.h
generic-y += trace_clock.h
generic-y += ucontext.h
+generic-y += user.h
generic-y += xor.h
diff --git a/arch/mips/include/asm/abi.h b/arch/mips/include/asm/abi.h
index 909bb6984866..7186bb51b89b 100644
--- a/arch/mips/include/asm/abi.h
+++ b/arch/mips/include/asm/abi.h
@@ -13,13 +13,11 @@
#include <asm/siginfo.h>
struct mips_abi {
- int (* const setup_frame)(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr,
- sigset_t *set);
+ int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set);
const unsigned long signal_return_offset;
- int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr,
- sigset_t *set, siginfo_t *info);
+ int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set);
const unsigned long rt_signal_return_offset;
const unsigned long restart;
};
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 3f745459fdb5..3b0e51d5a613 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -52,7 +52,7 @@
*/
#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
#define XPHYSADDR(a) ((_ACAST64_(a)) & \
- _CONST64_(0x000000ffffffffff))
+ _CONST64_(0x0000ffffffffffff))
#ifdef CONFIG_64BIT
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 935543f14538..cd9a98bc8f60 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -10,6 +10,7 @@
#include <asm/hazards.h>
#include <asm/asm-offsets.h>
+#include <asm/msa.h>
#ifdef CONFIG_32BIT
#include <asm/asmmacro-32.h>
@@ -378,9 +379,19 @@
st_d 29, THREAD_FPR29, \thread
st_d 30, THREAD_FPR30, \thread
st_d 31, THREAD_FPR31, \thread
+ .set push
+ .set noat
+ cfcmsa $1, MSA_CSR
+ sw $1, THREAD_MSA_CSR(\thread)
+ .set pop
.endm
.macro msa_restore_all thread
+ .set push
+ .set noat
+ lw $1, THREAD_MSA_CSR(\thread)
+ ctcmsa MSA_CSR, $1
+ .set pop
ld_d 0, THREAD_FPR0, \thread
ld_d 1, THREAD_FPR1, \thread
ld_d 2, THREAD_FPR2, \thread
@@ -415,4 +426,24 @@
ld_d 31, THREAD_FPR31, \thread
.endm
+ .macro msa_init_upper wd
+#ifdef CONFIG_64BIT
+ insert_d \wd, 1
+#else
+ insert_w \wd, 2
+ insert_w \wd, 3
+#endif
+ .if 31-\wd
+ msa_init_upper (\wd+1)
+ .endif
+ .endm
+
+ .macro msa_init_all_upper
+ .set push
+ .set noat
+ not $1, zero
+ msa_init_upper 0
+ .set pop
+ .endm
+
#endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 7c8816f7b7c4..bae6b0fa8ab5 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -559,7 +559,13 @@ static inline int fls(int x)
int r;
if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
- __asm__("clz %0, %1" : "=r" (x) : "r" (x));
+ __asm__(
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
return 32 - x;
}
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index c1516cc0285f..d0352983b94d 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -32,6 +32,14 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
#define cop2_present 1
#define cop2_lazy_restore 0
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+#define cop2_save(r)
+#define cop2_restore(r)
+
+#define cop2_present 1
+#define cop2_lazy_restore 1
+
#else
#define cop2_present 0
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index c7d8c997d93e..e079598ae051 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -29,6 +29,15 @@
#ifndef cpu_has_eva
#define cpu_has_eva (cpu_data[0].options & MIPS_CPU_EVA)
#endif
+#ifndef cpu_has_htw
+#define cpu_has_htw (cpu_data[0].options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_has_rixiex
+#define cpu_has_rixiex (cpu_data[0].options & MIPS_CPU_RIXIEX)
+#endif
+#ifndef cpu_has_maar
+#define cpu_has_maar (cpu_data[0].options & MIPS_CPU_MAAR)
+#endif
/*
* For the moment we don't consider R6000 and R8000 so we can assume that
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index 47d5967ce7ef..d5f42c168001 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -44,8 +44,8 @@ struct cpuinfo_mips {
/*
* Capability and feature descriptor structure for MIPS CPU
*/
- unsigned long options;
unsigned long ases;
+ unsigned long long options;
unsigned int udelay_val;
unsigned int processor_id;
unsigned int fpu_id;
@@ -61,6 +61,7 @@ struct cpuinfo_mips {
struct cache_desc scache; /* Secondary cache */
struct cache_desc tcache; /* Tertiary/split secondary cache */
int srsets; /* Shadow register sets */
+ int package;/* physical package number */
int core; /* physical core number */
#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
@@ -115,7 +116,7 @@ struct proc_cpuinfo_notifier_args {
#ifdef CONFIG_MIPS_MT_SMP
# define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id)
#else
-# define cpu_vpe_id(cpuinfo) 0
+# define cpu_vpe_id(cpuinfo) ({ (void)cpuinfo; 0; })
#endif
#endif /* __ASM_CPU_INFO_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 129d08701e91..dfdc77ed1839 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -233,6 +233,8 @@
#define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003
#define PRID_REV_LOONGSON3A 0x0005
+#define PRID_REV_LOONGSON3B_R1 0x0006
+#define PRID_REV_LOONGSON3B_R2 0x0007
/*
* Older processors used to encode processor version and revision in two
@@ -335,34 +337,37 @@ enum cpu_type_enum {
/*
* CPU Option encodings
*/
-#define MIPS_CPU_TLB 0x00000001 /* CPU has TLB */
-#define MIPS_CPU_4KEX 0x00000002 /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE 0x00000004 /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE 0x00000008 /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE 0x00000010 /* TX3900-style caches */
-#define MIPS_CPU_FPU 0x00000020 /* CPU has FPU */
-#define MIPS_CPU_32FPR 0x00000040 /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER 0x00000080 /* Cycle count/compare */
-#define MIPS_CPU_WATCH 0x00000100 /* watchpoint registers */
-#define MIPS_CPU_DIVEC 0x00000200 /* dedicated interrupt vector */
-#define MIPS_CPU_VCE 0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P 0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S 0x00001000 /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK 0x00002000 /* Machine check exception */
-#define MIPS_CPU_EJTAG 0x00004000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX 0x00008000 /* no FPU exception */
-#define MIPS_CPU_LLSC 0x00010000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES 0x00020000 /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH 0x00040000 /* CPU has usable prefetch */
-#define MIPS_CPU_VINT 0x00080000 /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC 0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI 0x00200000 /* CPU has ULRI feature */
-#define MIPS_CPU_PCI 0x00400000 /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI 0x00800000 /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS 0x01000000 /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV 0x02000000 /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS 0x04000000 /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA 0x80000000 /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_TLB 0x00000001ull /* CPU has TLB */
+#define MIPS_CPU_4KEX 0x00000002ull /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE 0x00000004ull /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE 0x00000008ull /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE 0x00000010ull /* TX3900-style caches */
+#define MIPS_CPU_FPU 0x00000020ull /* CPU has FPU */
+#define MIPS_CPU_32FPR 0x00000040ull /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER 0x00000080ull /* Cycle count/compare */
+#define MIPS_CPU_WATCH 0x00000100ull /* watchpoint registers */
+#define MIPS_CPU_DIVEC 0x00000200ull /* dedicated interrupt vector */
+#define MIPS_CPU_VCE 0x00000400ull /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P 0x00000800ull /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S 0x00001000ull /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK 0x00002000ull /* Machine check exception */
+#define MIPS_CPU_EJTAG 0x00004000ull /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX 0x00008000ull /* no FPU exception */
+#define MIPS_CPU_LLSC 0x00010000ull /* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES 0x00020000ull /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH 0x00040000ull /* CPU has usable prefetch */
+#define MIPS_CPU_VINT 0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC 0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI 0x00200000ull /* CPU has ULRI feature */
+#define MIPS_CPU_PCI 0x00400000ull /* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI 0x00800000ull /* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS 0x01000000ull /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV 0x02000000ull /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS 0x04000000ull /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA 0x80000000ull /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */
/*
* CPU ASE encodings
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index d4144056e928..1d38fe0edd2d 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -339,23 +339,6 @@ do { \
#endif /* CONFIG_64BIT */
-struct pt_regs;
-struct task_struct;
-
-extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
-
-#ifndef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(elf_regs, regs) \
- elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
-#endif
-#ifndef ELF_CORE_COPY_TASK_REGS
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#endif
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \
- dump_task_fpu(tsk, elf_fpregs)
-
#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE PAGE_SIZE
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index a939574f8293..4d0aeda68397 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -21,6 +21,7 @@
#include <asm/hazards.h>
#include <asm/processor.h>
#include <asm/current.h>
+#include <asm/msa.h>
#ifdef CONFIG_MIPS_MT_FPAFF
#include <asm/mips_mt.h>
@@ -141,13 +142,21 @@ static inline int own_fpu(int restore)
static inline void lose_fpu(int save)
{
preempt_disable();
- if (is_fpu_owner()) {
+ if (is_msa_enabled()) {
+ if (save) {
+ save_msa(current);
+ asm volatile("cfc1 %0, $31"
+ : "=r"(current->thread.fpu.fcr31));
+ }
+ disable_msa();
+ clear_thread_flag(TIF_USEDMSA);
+ } else if (is_fpu_owner()) {
if (save)
_save_fp(current);
- KSTK_STATUS(current) &= ~ST0_CU1;
- clear_thread_flag(TIF_USEDFPU);
__disable_fpu();
}
+ KSTK_STATUS(current) &= ~ST0_CU1;
+ clear_thread_flag(TIF_USEDFPU);
preempt_enable();
}
@@ -155,8 +164,6 @@ static inline int init_fpu(void)
{
int ret = 0;
- preempt_disable();
-
if (cpu_has_fpu) {
ret = __own_fpu();
if (!ret)
@@ -164,8 +171,6 @@ static inline int init_fpu(void)
} else
fpu_emulator_init_fpu();
- preempt_enable();
-
return ret;
}
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 10f6a99f92c2..3f20b2111d56 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -14,6 +14,8 @@
#include <linux/bitmap.h>
#include <linux/threads.h>
+#include <irq.h>
+
#undef GICISBYTELITTLEENDIAN
/* Constants */
@@ -22,8 +24,6 @@
#define GIC_TRIG_EDGE 1
#define GIC_TRIG_LEVEL 0
-#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
-
#define MSK(n) ((1 << (n)) - 1)
#define REG32(addr) (*(volatile unsigned int *) (addr))
#define REG(base, offs) REG32((unsigned long)(base) + offs##_##OFS)
@@ -43,18 +43,17 @@
#ifdef GICISBYTELITTLEENDIAN
#define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data))
#define GICWRITE(reg, data) ((reg) = cpu_to_le32(data))
-#define GICBIS(reg, bits) \
- ({unsigned int data; \
- GICREAD(reg, data); \
- data |= bits; \
- GICWRITE(reg, data); \
- })
-
#else
#define GICREAD(reg, data) ((data) = (reg))
#define GICWRITE(reg, data) ((reg) = (data))
-#define GICBIS(reg, bits) ((reg) |= (bits))
#endif
+#define GICBIS(reg, mask, bits) \
+ do { u32 data; \
+ GICREAD((reg), data); \
+ data &= ~(mask); \
+ data |= ((bits) & (mask)); \
+ GICWRITE((reg), data); \
+ } while (0)
/* GIC Address Space */
@@ -170,13 +169,15 @@
#define GIC_SH_SET_POLARITY_OFS 0x0100
#define GIC_SET_POLARITY(intr, pol) \
GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
- GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
+ GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+ (pol) << GIC_INTR_BIT(intr))
/* Triggering : Reset Value is always 0 */
#define GIC_SH_SET_TRIGGER_OFS 0x0180
#define GIC_SET_TRIGGER(intr, trig) \
GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
- GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
+ GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+ (trig) << GIC_INTR_BIT(intr))
/* Mask manipulation */
#define GIC_SH_SMASK_OFS 0x0380
@@ -306,18 +307,6 @@
GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
-struct gic_pcpu_mask {
- DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
-};
-
-struct gic_pending_regs {
- DECLARE_BITMAP(pending, GIC_NUM_INTRS);
-};
-
-struct gic_intrmask_regs {
- DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
-};
-
/*
* Interrupt Meta-data specification. The ipiflag helps
* in building ipi_map.
@@ -329,8 +318,7 @@ struct gic_intr_map {
unsigned int polarity; /* Polarity : +/- */
unsigned int trigtype; /* Trigger : Edge/Levl */
unsigned int flags; /* Misc flags */
-#define GIC_FLAG_IPI 0x01
-#define GIC_FLAG_TRANSPARENT 0x02
+#define GIC_FLAG_TRANSPARENT 0x01
};
/*
@@ -386,6 +374,7 @@ extern unsigned int plat_ipi_call_int_xlate(unsigned int);
extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
extern void gic_bind_eic_interrupt(int irq, int set);
extern unsigned int gic_get_timer_pending(void);
+extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
extern unsigned int gic_get_int(void);
extern void gic_enable_interrupt(int irq_vec);
extern void gic_disable_interrupt(int irq_vec);
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index b0aa95565752..7a3fc67bd7f9 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -359,13 +359,17 @@ enum emulation_result {
#define MIPS3_PG_FRAME 0x3fffffc0
#define VPN2_MASK 0xffffe000
-#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \
+#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && \
((x).tlb_lo1 & MIPS3_PG_G))
#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK)
#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK)
-#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \
- ? ((x).tlb_lo1 & MIPS3_PG_V) \
+#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) \
+ ? ((x).tlb_lo1 & MIPS3_PG_V) \
: ((x).tlb_lo0 & MIPS3_PG_V))
+#define TLB_HI_VPN2_HIT(x, y) ((TLB_VPN2(x) & ~(x).tlb_mask) == \
+ ((y) & VPN2_MASK & ~(x).tlb_mask))
+#define TLB_HI_ASID_HIT(x, y) (TLB_IS_GLOBAL(x) || \
+ TLB_ASID(x) == ((y) & ASID_MASK))
struct kvm_mips_tlb {
long tlb_mask;
@@ -760,7 +764,7 @@ extern int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc,
struct kvm_vcpu *vcpu);
/* Misc */
-extern int kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
+extern void kvm_mips_dump_stats(struct kvm_vcpu *vcpu);
extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm);
diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h
new file mode 100644
index 000000000000..6c62b0f899c0
--- /dev/null
+++ b/arch/mips/include/asm/maar.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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.
+ */
+
+#ifndef __MIPS_ASM_MIPS_MAAR_H__
+#define __MIPS_ASM_MIPS_MAAR_H__
+
+#include <asm/hazards.h>
+#include <asm/mipsregs.h>
+
+/**
+ * platform_maar_init() - perform platform-level MAAR configuration
+ * @num_pairs: The number of MAAR pairs present in the system.
+ *
+ * Platforms should implement this function such that it configures as many
+ * MAAR pairs as required, from 0 up to the maximum of num_pairs-1, and returns
+ * the number that were used. Any further MAARs will be configured to be
+ * invalid. The default implementation of this function will simply indicate
+ * that it has configured 0 MAAR pairs.
+ *
+ * Return: The number of MAAR pairs configured.
+ */
+unsigned __weak platform_maar_init(unsigned num_pairs);
+
+/**
+ * write_maar_pair() - write to a pair of MAARs
+ * @idx: The index of the pair (ie. use MAARs idx*2 & (idx*2)+1).
+ * @lower: The lowest address that the MAAR pair will affect. Must be
+ * aligned to a 2^16 byte boundary.
+ * @upper: The highest address that the MAAR pair will affect. Must be
+ * aligned to one byte before a 2^16 byte boundary.
+ * @attrs: The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ * MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Program the pair of MAAR registers specified by idx to apply the attributes
+ * specified by attrs to the range of addresses from lower to higher.
+ */
+static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
+ phys_addr_t upper, unsigned attrs)
+{
+ /* Addresses begin at bit 16, but are shifted right 4 bits */
+ BUG_ON(lower & (0xffff | ~(MIPS_MAAR_ADDR << 4)));
+ BUG_ON(((upper & 0xffff) != 0xffff)
+ || ((upper & ~0xffffull) & ~(MIPS_MAAR_ADDR << 4)));
+
+ /* Automatically set MIPS_MAAR_V */
+ attrs |= MIPS_MAAR_V;
+
+ /* Write the upper address & attributes (only MIPS_MAAR_V matters) */
+ write_c0_maari(idx << 1);
+ back_to_back_c0_hazard();
+ write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
+ back_to_back_c0_hazard();
+
+ /* Write the lower address & attributes */
+ write_c0_maari((idx << 1) | 0x1);
+ back_to_back_c0_hazard();
+ write_c0_maar((lower >> 4) | attrs);
+ back_to_back_c0_hazard();
+}
+
+/**
+ * struct maar_config - MAAR configuration data
+ * @lower: The lowest address that the MAAR pair will affect. Must be
+ * aligned to a 2^16 byte boundary.
+ * @upper: The highest address that the MAAR pair will affect. Must be
+ * aligned to one byte before a 2^16 byte boundary.
+ * @attrs: The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ * MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Describes the configuration of a pair of Memory Accessibility Attribute
+ * Registers - applying attributes from attrs to the range of physical
+ * addresses from lower to upper inclusive.
+ */
+struct maar_config {
+ phys_addr_t lower;
+ phys_addr_t upper;
+ unsigned attrs;
+};
+
+/**
+ * maar_config() - configure MAARs according to provided data
+ * @cfg: Pointer to an array of struct maar_config.
+ * @num_cfg: The number of structs in the cfg array.
+ * @num_pairs: The number of MAAR pairs present in the system.
+ *
+ * Configures as many MAARs as are present and specified in the cfg
+ * array with the values taken from the cfg array.
+ *
+ * Return: The number of MAAR pairs configured.
+ */
+static inline unsigned maar_config(const struct maar_config *cfg,
+ unsigned num_cfg, unsigned num_pairs)
+{
+ unsigned i;
+
+ for (i = 0; i < min(num_cfg, num_pairs); i++)
+ write_maar_pair(i, cfg[i].lower, cfg[i].upper, cfg[i].attrs);
+
+ return i;
+}
+
+#endif /* __MIPS_ASM_MIPS_MAAR_H__ */
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index b4c3ecb17d48..a7eec3364a64 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -34,6 +34,558 @@
#ifndef _AU1000_H_
#define _AU1000_H_
+/* SOC Interrupt numbers */
+/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
+#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 8)
+#define AU1000_INTC0_INT_LAST (AU1000_INTC0_INT_BASE + 31)
+#define AU1000_INTC1_INT_BASE (AU1000_INTC0_INT_LAST + 1)
+#define AU1000_INTC1_INT_LAST (AU1000_INTC1_INT_BASE + 31)
+#define AU1000_MAX_INTR AU1000_INTC1_INT_LAST
+
+/* Au1300-style (GPIC): 1 controller with up to 128 sources */
+#define ALCHEMY_GPIC_INT_BASE (MIPS_CPU_IRQ_BASE + 8)
+#define ALCHEMY_GPIC_INT_NUM 128
+#define ALCHEMY_GPIC_INT_LAST (ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
+
+/* common clock names, shared among all variants. AUXPLL2 is Au1300 */
+#define ALCHEMY_ROOT_CLK "root_clk"
+#define ALCHEMY_CPU_CLK "cpu_clk"
+#define ALCHEMY_AUXPLL_CLK "auxpll_clk"
+#define ALCHEMY_AUXPLL2_CLK "auxpll2_clk"
+#define ALCHEMY_SYSBUS_CLK "sysbus_clk"
+#define ALCHEMY_PERIPH_CLK "periph_clk"
+#define ALCHEMY_MEM_CLK "mem_clk"
+#define ALCHEMY_LR_CLK "lr_clk"
+#define ALCHEMY_FG0_CLK "fg0_clk"
+#define ALCHEMY_FG1_CLK "fg1_clk"
+#define ALCHEMY_FG2_CLK "fg2_clk"
+#define ALCHEMY_FG3_CLK "fg3_clk"
+#define ALCHEMY_FG4_CLK "fg4_clk"
+#define ALCHEMY_FG5_CLK "fg5_clk"
+
+/* Au1300 peripheral interrupt numbers */
+#define AU1300_FIRST_INT (ALCHEMY_GPIC_INT_BASE)
+#define AU1300_UART1_INT (AU1300_FIRST_INT + 17)
+#define AU1300_UART2_INT (AU1300_FIRST_INT + 25)
+#define AU1300_UART3_INT (AU1300_FIRST_INT + 27)
+#define AU1300_SD1_INT (AU1300_FIRST_INT + 32)
+#define AU1300_SD2_INT (AU1300_FIRST_INT + 38)
+#define AU1300_PSC0_INT (AU1300_FIRST_INT + 48)
+#define AU1300_PSC1_INT (AU1300_FIRST_INT + 52)
+#define AU1300_PSC2_INT (AU1300_FIRST_INT + 56)
+#define AU1300_PSC3_INT (AU1300_FIRST_INT + 60)
+#define AU1300_NAND_INT (AU1300_FIRST_INT + 62)
+#define AU1300_DDMA_INT (AU1300_FIRST_INT + 75)
+#define AU1300_MMU_INT (AU1300_FIRST_INT + 76)
+#define AU1300_MPU_INT (AU1300_FIRST_INT + 77)
+#define AU1300_GPU_INT (AU1300_FIRST_INT + 78)
+#define AU1300_UDMA_INT (AU1300_FIRST_INT + 79)
+#define AU1300_TOY_INT (AU1300_FIRST_INT + 80)
+#define AU1300_TOY_MATCH0_INT (AU1300_FIRST_INT + 81)
+#define AU1300_TOY_MATCH1_INT (AU1300_FIRST_INT + 82)
+#define AU1300_TOY_MATCH2_INT (AU1300_FIRST_INT + 83)
+#define AU1300_RTC_INT (AU1300_FIRST_INT + 84)
+#define AU1300_RTC_MATCH0_INT (AU1300_FIRST_INT + 85)
+#define AU1300_RTC_MATCH1_INT (AU1300_FIRST_INT + 86)
+#define AU1300_RTC_MATCH2_INT (AU1300_FIRST_INT + 87)
+#define AU1300_UART0_INT (AU1300_FIRST_INT + 88)
+#define AU1300_SD0_INT (AU1300_FIRST_INT + 89)
+#define AU1300_USB_INT (AU1300_FIRST_INT + 90)
+#define AU1300_LCD_INT (AU1300_FIRST_INT + 91)
+#define AU1300_BSA_INT (AU1300_FIRST_INT + 92)
+#define AU1300_MPE_INT (AU1300_FIRST_INT + 93)
+#define AU1300_ITE_INT (AU1300_FIRST_INT + 94)
+#define AU1300_AES_INT (AU1300_FIRST_INT + 95)
+#define AU1300_CIM_INT (AU1300_FIRST_INT + 96)
+
+/**********************************************************************/
+
+/*
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
+ */
+
+#define AU1000_AC97_PHYS_ADDR 0x10000000 /* 012 */
+#define AU1300_ROM_PHYS_ADDR 0x10000000 /* 5 */
+#define AU1300_OTP_PHYS_ADDR 0x10002000 /* 5 */
+#define AU1300_VSS_PHYS_ADDR 0x10003000 /* 5 */
+#define AU1300_UART0_PHYS_ADDR 0x10100000 /* 5 */
+#define AU1300_UART1_PHYS_ADDR 0x10101000 /* 5 */
+#define AU1300_UART2_PHYS_ADDR 0x10102000 /* 5 */
+#define AU1300_UART3_PHYS_ADDR 0x10103000 /* 5 */
+#define AU1000_USB_OHCI_PHYS_ADDR 0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR 0x10200000 /* 0123 */
+#define AU1300_GPIC_PHYS_ADDR 0x10200000 /* 5 */
+#define AU1000_IRDA_PHYS_ADDR 0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR 0x10300000 /* 45 */
+#define AU1000_IC0_PHYS_ADDR 0x10400000 /* 01234 */
+#define AU1300_GPU_PHYS_ADDR 0x10500000 /* 5 */
+#define AU1000_MAC0_PHYS_ADDR 0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR 0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR 0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR 0x10600000 /* 245 */
+#define AU1300_SD1_PHYS_ADDR 0x10601000 /* 5 */
+#define AU1300_SD2_PHYS_ADDR 0x10602000 /* 5 */
+#define AU1100_SD1_PHYS_ADDR 0x10680000 /* 24 */
+#define AU1300_SYS_PHYS_ADDR 0x10900000 /* 5 */
+#define AU1550_PSC2_PHYS_ADDR 0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR 0x10B00000 /* 3 */
+#define AU1300_PSC0_PHYS_ADDR 0x10A00000 /* 5 */
+#define AU1300_PSC1_PHYS_ADDR 0x10A01000 /* 5 */
+#define AU1300_PSC2_PHYS_ADDR 0x10A02000 /* 5 */
+#define AU1300_PSC3_PHYS_ADDR 0x10A03000 /* 5 */
+#define AU1000_I2S_PHYS_ADDR 0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR 0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR 0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR 0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR 0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR 0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR 0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR 0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR 0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR 0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR 0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR 0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR 0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR 0x11900000 /* 012345 */
+#define AU1550_PSC0_PHYS_ADDR 0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR 0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR 0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR 0x14001000 /* 01234 */
+#define AU1300_UDMA_PHYS_ADDR 0x14001800 /* 5 */
+#define AU1000_DMA_PHYS_ADDR 0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR 0x14002000 /* 345 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR 0x14003000 /* 345 */
+#define AU1000_MACDMA0_PHYS_ADDR 0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR 0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR 0x14004000 /* 45 */
+#define AU1500_PCI_PHYS_ADDR 0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR 0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR 0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR 0x14012000 /* 4 */
+#define AU1300_MAEITE_PHYS_ADDR 0x14010000 /* 5 */
+#define AU1300_MAEMPE_PHYS_ADDR 0x14014000 /* 5 */
+#define AU1550_USB_OHCI_PHYS_ADDR 0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR 0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR 0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR 0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR 0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR 0x14022000 /* 4 */
+#define AU1300_USB_EHCI_PHYS_ADDR 0x14020000 /* 5 */
+#define AU1300_USB_OHCI0_PHYS_ADDR 0x14020400 /* 5 */
+#define AU1300_USB_OHCI1_PHYS_ADDR 0x14020800 /* 5 */
+#define AU1300_USB_CTL_PHYS_ADDR 0x14021000 /* 5 */
+#define AU1300_USB_OTG_PHYS_ADDR 0x14022000 /* 5 */
+#define AU1300_MAEBSA_PHYS_ADDR 0x14030000 /* 5 */
+#define AU1100_LCD_PHYS_ADDR 0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR 0x15000000 /* 45 */
+#define AU1500_PCI_MEM_PHYS_ADDR 0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR 0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR 0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR 0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR 0xF00000000ULL /* 012345 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL /* 012345 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL /* 012345 */
+
+/**********************************************************************/
+
+
+/*
+ * Au1300 GPIO+INT controller (GPIC) register offsets and bits
+ * Registers are 128bits (0x10 bytes), divided into 4 "banks".
+ */
+#define AU1300_GPIC_PINVAL 0x0000
+#define AU1300_GPIC_PINVALCLR 0x0010
+#define AU1300_GPIC_IPEND 0x0020
+#define AU1300_GPIC_PRIENC 0x0030
+#define AU1300_GPIC_IEN 0x0040 /* int_mask in manual */
+#define AU1300_GPIC_IDIS 0x0050 /* int_maskclr in manual */
+#define AU1300_GPIC_DMASEL 0x0060
+#define AU1300_GPIC_DEVSEL 0x0080
+#define AU1300_GPIC_DEVCLR 0x0090
+#define AU1300_GPIC_RSTVAL 0x00a0
+/* pin configuration space. one 32bit register for up to 128 IRQs */
+#define AU1300_GPIC_PINCFG 0x1000
+
+#define GPIC_GPIO_TO_BIT(gpio) \
+ (1 << ((gpio) & 0x1f))
+
+#define GPIC_GPIO_BANKOFF(gpio) \
+ (((gpio) >> 5) * 4)
+
+/* Pin Control bits: who owns the pin, what does it do */
+#define GPIC_CFG_PC_GPIN 0
+#define GPIC_CFG_PC_DEV 1
+#define GPIC_CFG_PC_GPOLOW 2
+#define GPIC_CFG_PC_GPOHIGH 3
+#define GPIC_CFG_PC_MASK 3
+
+/* assign pin to MIPS IRQ line */
+#define GPIC_CFG_IL_SET(x) (((x) & 3) << 2)
+#define GPIC_CFG_IL_MASK (3 << 2)
+
+/* pin interrupt type setup */
+#define GPIC_CFG_IC_OFF (0 << 4)
+#define GPIC_CFG_IC_LEVEL_LOW (1 << 4)
+#define GPIC_CFG_IC_LEVEL_HIGH (2 << 4)
+#define GPIC_CFG_IC_EDGE_FALL (5 << 4)
+#define GPIC_CFG_IC_EDGE_RISE (6 << 4)
+#define GPIC_CFG_IC_EDGE_BOTH (7 << 4)
+#define GPIC_CFG_IC_MASK (7 << 4)
+
+/* allow interrupt to wake cpu from 'wait' */
+#define GPIC_CFG_IDLEWAKE (1 << 7)
+
+/***********************************************************************/
+
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0 0x0000
+#define AU1000_MEM_SDMODE1 0x0004
+#define AU1000_MEM_SDMODE2 0x0008
+#define AU1000_MEM_SDADDR0 0x000C
+#define AU1000_MEM_SDADDR1 0x0010
+#define AU1000_MEM_SDADDR2 0x0014
+#define AU1000_MEM_SDREFCFG 0x0018
+#define AU1000_MEM_SDPRECMD 0x001C
+#define AU1000_MEM_SDAUTOREF 0x0020
+#define AU1000_MEM_SDWRMD0 0x0024
+#define AU1000_MEM_SDWRMD1 0x0028
+#define AU1000_MEM_SDWRMD2 0x002C
+#define AU1000_MEM_SDSLEEP 0x0030
+#define AU1000_MEM_SDSMCKE 0x0034
+
+/* MEM_SDMODE register content definitions */
+#define MEM_SDMODE_F (1 << 22)
+#define MEM_SDMODE_SR (1 << 21)
+#define MEM_SDMODE_BS (1 << 20)
+#define MEM_SDMODE_RS (3 << 18)
+#define MEM_SDMODE_CS (7 << 15)
+#define MEM_SDMODE_TRAS (15 << 11)
+#define MEM_SDMODE_TMRD (3 << 9)
+#define MEM_SDMODE_TWR (3 << 7)
+#define MEM_SDMODE_TRP (3 << 5)
+#define MEM_SDMODE_TRCD (3 << 3)
+#define MEM_SDMODE_TCL (7 << 0)
+
+#define MEM_SDMODE_BS_2Bank (0 << 20)
+#define MEM_SDMODE_BS_4Bank (1 << 20)
+#define MEM_SDMODE_RS_11Row (0 << 18)
+#define MEM_SDMODE_RS_12Row (1 << 18)
+#define MEM_SDMODE_RS_13Row (2 << 18)
+#define MEM_SDMODE_RS_N(N) ((N) << 18)
+#define MEM_SDMODE_CS_7Col (0 << 15)
+#define MEM_SDMODE_CS_8Col (1 << 15)
+#define MEM_SDMODE_CS_9Col (2 << 15)
+#define MEM_SDMODE_CS_10Col (3 << 15)
+#define MEM_SDMODE_CS_11Col (4 << 15)
+#define MEM_SDMODE_CS_N(N) ((N) << 15)
+#define MEM_SDMODE_TRAS_N(N) ((N) << 11)
+#define MEM_SDMODE_TMRD_N(N) ((N) << 9)
+#define MEM_SDMODE_TWR_N(N) ((N) << 7)
+#define MEM_SDMODE_TRP_N(N) ((N) << 5)
+#define MEM_SDMODE_TRCD_N(N) ((N) << 3)
+#define MEM_SDMODE_TCL_N(N) ((N) << 0)
+
+/* MEM_SDADDR register contents definitions */
+#define MEM_SDADDR_E (1 << 20)
+#define MEM_SDADDR_CSBA (0x03FF << 10)
+#define MEM_SDADDR_CSMASK (0x03FF << 0)
+#define MEM_SDADDR_CSBA_N(N) ((N) & (0x03FF << 22) >> 12)
+#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF << 22) >> 22)
+
+/* MEM_SDREFCFG register content definitions */
+#define MEM_SDREFCFG_TRC (15 << 28)
+#define MEM_SDREFCFG_TRPM (3 << 26)
+#define MEM_SDREFCFG_E (1 << 25)
+#define MEM_SDREFCFG_RE (0x1ffffff << 0)
+#define MEM_SDREFCFG_TRC_N(N) ((N) << MEM_SDREFCFG_TRC)
+#define MEM_SDREFCFG_TRPM_N(N) ((N) << MEM_SDREFCFG_TRPM)
+#define MEM_SDREFCFG_REF_N(N) (N)
+
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0 0x0800
+#define AU1550_MEM_SDMODE1 0x0808
+#define AU1550_MEM_SDMODE2 0x0810
+#define AU1550_MEM_SDADDR0 0x0820
+#define AU1550_MEM_SDADDR1 0x0828
+#define AU1550_MEM_SDADDR2 0x0830
+#define AU1550_MEM_SDCONFIGA 0x0840
+#define AU1550_MEM_SDCONFIGB 0x0848
+#define AU1550_MEM_SDSTAT 0x0850
+#define AU1550_MEM_SDERRADDR 0x0858
+#define AU1550_MEM_SDSTRIDE0 0x0860
+#define AU1550_MEM_SDSTRIDE1 0x0868
+#define AU1550_MEM_SDSTRIDE2 0x0870
+#define AU1550_MEM_SDWRMD0 0x0880
+#define AU1550_MEM_SDWRMD1 0x0888
+#define AU1550_MEM_SDWRMD2 0x0890
+#define AU1550_MEM_SDPRECMD 0x08C0
+#define AU1550_MEM_SDAUTOREF 0x08C8
+#define AU1550_MEM_SDSREF 0x08D0
+#define AU1550_MEM_SDSLEEP MEM_SDSREF
+
+/* Static Bus Controller register offsets */
+#define AU1000_MEM_STCFG0 0x000
+#define AU1000_MEM_STTIME0 0x004
+#define AU1000_MEM_STADDR0 0x008
+#define AU1000_MEM_STCFG1 0x010
+#define AU1000_MEM_STTIME1 0x014
+#define AU1000_MEM_STADDR1 0x018
+#define AU1000_MEM_STCFG2 0x020
+#define AU1000_MEM_STTIME2 0x024
+#define AU1000_MEM_STADDR2 0x028
+#define AU1000_MEM_STCFG3 0x030
+#define AU1000_MEM_STTIME3 0x034
+#define AU1000_MEM_STADDR3 0x038
+#define AU1000_MEM_STNDCTL 0x100
+#define AU1000_MEM_STSTAT 0x104
+
+#define MEM_STNAND_CMD 0x0
+#define MEM_STNAND_ADDR 0x4
+#define MEM_STNAND_DATA 0x20
+
+
+/* Programmable Counters 0 and 1 */
+#define AU1000_SYS_CNTRCTRL 0x14
+# define SYS_CNTRL_E1S (1 << 23)
+# define SYS_CNTRL_T1S (1 << 20)
+# define SYS_CNTRL_M21 (1 << 19)
+# define SYS_CNTRL_M11 (1 << 18)
+# define SYS_CNTRL_M01 (1 << 17)
+# define SYS_CNTRL_C1S (1 << 16)
+# define SYS_CNTRL_BP (1 << 14)
+# define SYS_CNTRL_EN1 (1 << 13)
+# define SYS_CNTRL_BT1 (1 << 12)
+# define SYS_CNTRL_EN0 (1 << 11)
+# define SYS_CNTRL_BT0 (1 << 10)
+# define SYS_CNTRL_E0 (1 << 8)
+# define SYS_CNTRL_E0S (1 << 7)
+# define SYS_CNTRL_32S (1 << 5)
+# define SYS_CNTRL_T0S (1 << 4)
+# define SYS_CNTRL_M20 (1 << 3)
+# define SYS_CNTRL_M10 (1 << 2)
+# define SYS_CNTRL_M00 (1 << 1)
+# define SYS_CNTRL_C0S (1 << 0)
+
+/* Programmable Counter 0 Registers */
+#define AU1000_SYS_TOYTRIM 0x00
+#define AU1000_SYS_TOYWRITE 0x04
+#define AU1000_SYS_TOYMATCH0 0x08
+#define AU1000_SYS_TOYMATCH1 0x0c
+#define AU1000_SYS_TOYMATCH2 0x10
+#define AU1000_SYS_TOYREAD 0x40
+
+/* Programmable Counter 1 Registers */
+#define AU1000_SYS_RTCTRIM 0x44
+#define AU1000_SYS_RTCWRITE 0x48
+#define AU1000_SYS_RTCMATCH0 0x4c
+#define AU1000_SYS_RTCMATCH1 0x50
+#define AU1000_SYS_RTCMATCH2 0x54
+#define AU1000_SYS_RTCREAD 0x58
+
+
+/* GPIO */
+#define AU1000_SYS_PINFUNC 0x2C
+# define SYS_PF_USB (1 << 15) /* 2nd USB device/host */
+# define SYS_PF_U3 (1 << 14) /* GPIO23/U3TXD */
+# define SYS_PF_U2 (1 << 13) /* GPIO22/U2TXD */
+# define SYS_PF_U1 (1 << 12) /* GPIO21/U1TXD */
+# define SYS_PF_SRC (1 << 11) /* GPIO6/SROMCKE */
+# define SYS_PF_CK5 (1 << 10) /* GPIO3/CLK5 */
+# define SYS_PF_CK4 (1 << 9) /* GPIO2/CLK4 */
+# define SYS_PF_IRF (1 << 8) /* GPIO15/IRFIRSEL */
+# define SYS_PF_UR3 (1 << 7) /* GPIO[14:9]/UART3 */
+# define SYS_PF_I2D (1 << 6) /* GPIO8/I2SDI */
+# define SYS_PF_I2S (1 << 5) /* I2S/GPIO[29:31] */
+# define SYS_PF_NI2 (1 << 4) /* NI2/GPIO[24:28] */
+# define SYS_PF_U0 (1 << 3) /* U0TXD/GPIO20 */
+# define SYS_PF_RD (1 << 2) /* IRTXD/GPIO19 */
+# define SYS_PF_A97 (1 << 1) /* AC97/SSL1 */
+# define SYS_PF_S0 (1 << 0) /* SSI_0/GPIO[16:18] */
+
+/* Au1100 only */
+# define SYS_PF_PC (1 << 18) /* PCMCIA/GPIO[207:204] */
+# define SYS_PF_LCD (1 << 17) /* extern lcd/GPIO[203:200] */
+# define SYS_PF_CS (1 << 16) /* EXTCLK0/32KHz to gpio2 */
+# define SYS_PF_EX0 (1 << 9) /* GPIO2/clock */
+
+/* Au1550 only. Redefines lots of pins */
+# define SYS_PF_PSC2_MASK (7 << 17)
+# define SYS_PF_PSC2_AC97 0
+# define SYS_PF_PSC2_SPI 0
+# define SYS_PF_PSC2_I2S (1 << 17)
+# define SYS_PF_PSC2_SMBUS (3 << 17)
+# define SYS_PF_PSC2_GPIO (7 << 17)
+# define SYS_PF_PSC3_MASK (7 << 20)
+# define SYS_PF_PSC3_AC97 0
+# define SYS_PF_PSC3_SPI 0
+# define SYS_PF_PSC3_I2S (1 << 20)
+# define SYS_PF_PSC3_SMBUS (3 << 20)
+# define SYS_PF_PSC3_GPIO (7 << 20)
+# define SYS_PF_PSC1_S1 (1 << 1)
+# define SYS_PF_MUST_BE_SET ((1 << 5) | (1 << 2))
+
+/* Au1200 only */
+#define SYS_PINFUNC_DMA (1 << 31)
+#define SYS_PINFUNC_S0A (1 << 30)
+#define SYS_PINFUNC_S1A (1 << 29)
+#define SYS_PINFUNC_LP0 (1 << 28)
+#define SYS_PINFUNC_LP1 (1 << 27)
+#define SYS_PINFUNC_LD16 (1 << 26)
+#define SYS_PINFUNC_LD8 (1 << 25)
+#define SYS_PINFUNC_LD1 (1 << 24)
+#define SYS_PINFUNC_LD0 (1 << 23)
+#define SYS_PINFUNC_P1A (3 << 21)
+#define SYS_PINFUNC_P1B (1 << 20)
+#define SYS_PINFUNC_FS3 (1 << 19)
+#define SYS_PINFUNC_P0A (3 << 17)
+#define SYS_PINFUNC_CS (1 << 16)
+#define SYS_PINFUNC_CIM (1 << 15)
+#define SYS_PINFUNC_P1C (1 << 14)
+#define SYS_PINFUNC_U1T (1 << 12)
+#define SYS_PINFUNC_U1R (1 << 11)
+#define SYS_PINFUNC_EX1 (1 << 10)
+#define SYS_PINFUNC_EX0 (1 << 9)
+#define SYS_PINFUNC_U0R (1 << 8)
+#define SYS_PINFUNC_MC (1 << 7)
+#define SYS_PINFUNC_S0B (1 << 6)
+#define SYS_PINFUNC_S0C (1 << 5)
+#define SYS_PINFUNC_P0B (1 << 4)
+#define SYS_PINFUNC_U0T (1 << 3)
+#define SYS_PINFUNC_S1B (1 << 2)
+
+/* Power Management */
+#define AU1000_SYS_SCRATCH0 0x18
+#define AU1000_SYS_SCRATCH1 0x1c
+#define AU1000_SYS_WAKEMSK 0x34
+#define AU1000_SYS_ENDIAN 0x38
+#define AU1000_SYS_POWERCTRL 0x3c
+#define AU1000_SYS_WAKESRC 0x5c
+#define AU1000_SYS_SLPPWR 0x78
+#define AU1000_SYS_SLEEP 0x7c
+
+#define SYS_WAKEMSK_D2 (1 << 9)
+#define SYS_WAKEMSK_M2 (1 << 8)
+#define SYS_WAKEMSK_GPIO(x) (1 << (x))
+
+/* Clock Controller */
+#define AU1000_SYS_FREQCTRL0 0x20
+#define AU1000_SYS_FREQCTRL1 0x24
+#define AU1000_SYS_CLKSRC 0x28
+#define AU1000_SYS_CPUPLL 0x60
+#define AU1000_SYS_AUXPLL 0x64
+#define AU1300_SYS_AUXPLL2 0x68
+
+
+/**********************************************************************/
+
+
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI. When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
+ */
+#define ALCHEMY_PCI_MEMWIN_START (AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END (ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
+
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START 0x00001000
+#define ALCHEMY_PCI_IOWIN_END 0x0000FFFF
+
+#ifdef CONFIG_PCI
+
+#define IOPORT_RESOURCE_START 0x00001000 /* skip legacy probing */
+#define IOPORT_RESOURCE_END 0xffffffff
+#define IOMEM_RESOURCE_START 0x10000000
+#define IOMEM_RESOURCE_END 0xfffffffffULL
+
+#else
+
+/* Don't allow any legacy ports probing */
+#define IOPORT_RESOURCE_START 0x10000000
+#define IOPORT_RESOURCE_END 0xffffffff
+#define IOMEM_RESOURCE_START 0x10000000
+#define IOMEM_RESOURCE_END 0xfffffffffULL
+
+#endif
+
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM 0x0000
+#define PCI_REG_CONFIG 0x0004
+#define PCI_REG_B2BMASK_CCH 0x0008
+#define PCI_REG_B2BBASE0_VID 0x000C
+#define PCI_REG_B2BBASE1_SID 0x0010
+#define PCI_REG_MWMASK_DEV 0x0014
+#define PCI_REG_MWBASE_REV_CCL 0x0018
+#define PCI_REG_ERR_ADDR 0x001C
+#define PCI_REG_SPEC_INTACK 0x0020
+#define PCI_REG_ID 0x0100
+#define PCI_REG_STATCMD 0x0104
+#define PCI_REG_CLASSREV 0x0108
+#define PCI_REG_PARAM 0x010C
+#define PCI_REG_MBAR 0x0110
+#define PCI_REG_TIMEOUT 0x0140
+
+/* PCI controller block register bits */
+#define PCI_CMEM_E (1 << 28) /* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x) (((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x) ((x) & 0x3fff)
+#define PCI_CONFIG_ERD (1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET (1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF (1 << 25) /* fatal error */
+#define PCI_CONFIG_EP (1 << 24) /* parity error */
+#define PCI_CONFIG_EM (1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM (1 << 22) /* bad master error */
+#define PCI_CONFIG_PD (1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME (1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC (1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA (1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP (1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS (1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM (1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM (1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT (1 << 9) /* int on target abort (as target) */
+#define PCI_CONFIG_IPB (1 << 8) /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO (0 << 6) /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR (1 << 6) /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT (2 << 6) /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL (3 << 6) /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST (1 << 5) /* swap data by target transactions */
+#define PCI_CONFIG_SM (1 << 4) /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN (1 << 3) /* enable internal arbiter */
+#define PCI_CONFIG_R2H (1 << 2) /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H (1 << 1) /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH (1 << 0) /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x) (((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x) ((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x) (((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x) ((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x) (((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x) ((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x) ((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x) (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x) ((x) & 0xff)
+#define PCI_ID_DID(x) (((x) & 0xffff) << 16)
+#define PCI_ID_VID(x) ((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x) (((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x) ((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x) (((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x) ((x) & 0xff)
+#define PCI_PARAM_BIST(x) (((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x) (((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x) (((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x) ((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x) (((x) & 0xff) << 8) /* max retries */
+#define PCI_TIMEOUT_TO(x) ((x) & 0xff) /* target ready timeout */
+
+
+/**********************************************************************/
+
#ifndef _LANGUAGE_ASSEMBLY
@@ -45,52 +597,36 @@
#include <asm/cpu.h>
-/* cpu pipeline flush */
-void static inline au_sync(void)
+/* helpers to access the SYS_* registers */
+static inline unsigned long alchemy_rdsys(int regofs)
{
- __asm__ volatile ("sync");
-}
+ void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
-void static inline au_sync_udelay(int us)
-{
- __asm__ volatile ("sync");
- udelay(us);
+ return __raw_readl(b + regofs);
}
-void static inline au_sync_delay(int ms)
+static inline void alchemy_wrsys(unsigned long v, int regofs)
{
- __asm__ volatile ("sync");
- mdelay(ms);
-}
+ void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
-void static inline au_writeb(u8 val, unsigned long reg)
-{
- *(volatile u8 *)reg = val;
+ __raw_writel(v, b + regofs);
+ wmb(); /* drain writebuffer */
}
-void static inline au_writew(u16 val, unsigned long reg)
+/* helpers to access static memctrl registers */
+static inline unsigned long alchemy_rdsmem(int regofs)
{
- *(volatile u16 *)reg = val;
-}
+ void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
-void static inline au_writel(u32 val, unsigned long reg)
-{
- *(volatile u32 *)reg = val;
+ return __raw_readl(b + regofs);
}
-static inline u8 au_readb(unsigned long reg)
+static inline void alchemy_wrsmem(unsigned long v, int regofs)
{
- return *(volatile u8 *)reg;
-}
+ void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
-static inline u16 au_readw(unsigned long reg)
-{
- return *(volatile u16 *)reg;
-}
-
-static inline u32 au_readl(unsigned long reg)
-{
- return *(volatile u32 *)reg;
+ __raw_writel(v, b + regofs);
+ wmb(); /* drain writebuffer */
}
/* Early Au1000 have a write-only SYS_CPUPLL register. */
@@ -192,19 +728,20 @@ static inline void alchemy_uart_enable(u32 uart_phys)
/* reset, enable clock, deassert reset */
if ((__raw_readl(addr + 0x100) & 3) != 3) {
__raw_writel(0, addr + 0x100);
- wmb();
+ wmb(); /* drain writebuffer */
__raw_writel(1, addr + 0x100);
- wmb();
+ wmb(); /* drain writebuffer */
}
__raw_writel(3, addr + 0x100);
- wmb();
+ wmb(); /* drain writebuffer */
}
static inline void alchemy_uart_disable(u32 uart_phys)
{
void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+
__raw_writel(0, addr + 0x100); /* UART_MOD_CNTRL */
- wmb();
+ wmb(); /* drain writebuffer */
}
static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
@@ -223,7 +760,7 @@ static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
} while (--timeout);
__raw_writel(c, base + 0x04); /* tx */
- wmb();
+ wmb(); /* drain writebuffer */
}
/* return number of ethernet MACs on a given cputype */
@@ -240,20 +777,13 @@ static inline int alchemy_get_macs(int type)
return 0;
}
-/* arch/mips/au1000/common/clocks.c */
-extern void set_au1x00_speed(unsigned int new_freq);
-extern unsigned int get_au1x00_speed(void);
-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
-extern unsigned long get_au1x00_uart_baud_base(void);
-extern unsigned long au1xxx_calc_clock(void);
-
/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
void alchemy_sleep_au1000(void);
void alchemy_sleep_au1550(void);
void alchemy_sleep_au1300(void);
void au_sleep(void);
-/* USB: drivers/usb/host/alchemy-common.c */
+/* USB: arch/mips/alchemy/common/usb.c */
enum alchemy_usb_block {
ALCHEMY_USB_OHCI0,
ALCHEMY_USB_UDC0,
@@ -272,6 +802,20 @@ struct alchemy_pci_platdata {
unsigned long pci_cfg_clr;
};
+/* The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's
+ * not used to select FIR/SIR mode on the transceiver but as a GPIO.
+ * Instead a CPLD has to be told about the mode. The driver calls the
+ * set_phy_mode() function in addition to driving the IRFIRSEL pin.
+ */
+#define AU1000_IRDA_PHY_MODE_OFF 0
+#define AU1000_IRDA_PHY_MODE_SIR 1
+#define AU1000_IRDA_PHY_MODE_FIR 2
+
+struct au1k_irda_platform_data {
+ void (*set_phy_mode)(int mode);
+};
+
+
/* Multifunction pins: Each of these pins can either be assigned to the
* GPIO controller or a on-chip peripheral.
* Call "au1300_pinfunc_to_dev()" or "au1300_pinfunc_to_gpio()" to
@@ -344,20 +888,6 @@ enum au1300_vss_block {
extern void au1300_vss_block_control(int block, int enable);
-
-/* SOC Interrupt numbers */
-/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
-#define AU1000_INTC0_INT_BASE (MIPS_CPU_IRQ_BASE + 8)
-#define AU1000_INTC0_INT_LAST (AU1000_INTC0_INT_BASE + 31)
-#define AU1000_INTC1_INT_BASE (AU1000_INTC0_INT_LAST + 1)
-#define AU1000_INTC1_INT_LAST (AU1000_INTC1_INT_BASE + 31)
-#define AU1000_MAX_INTR AU1000_INTC1_INT_LAST
-
-/* Au1300-style (GPIC): 1 controller with up to 128 sources */
-#define ALCHEMY_GPIC_INT_BASE (MIPS_CPU_IRQ_BASE + 8)
-#define ALCHEMY_GPIC_INT_NUM 128
-#define ALCHEMY_GPIC_INT_LAST (ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
-
enum soc_au1000_ints {
AU1000_FIRST_INT = AU1000_INTC0_INT_BASE,
AU1000_UART0_INT = AU1000_FIRST_INT,
@@ -678,885 +1208,4 @@ enum soc_au1200_ints {
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
-/* Au1300 peripheral interrupt numbers */
-#define AU1300_FIRST_INT (ALCHEMY_GPIC_INT_BASE)
-#define AU1300_UART1_INT (AU1300_FIRST_INT + 17)
-#define AU1300_UART2_INT (AU1300_FIRST_INT + 25)
-#define AU1300_UART3_INT (AU1300_FIRST_INT + 27)
-#define AU1300_SD1_INT (AU1300_FIRST_INT + 32)
-#define AU1300_SD2_INT (AU1300_FIRST_INT + 38)
-#define AU1300_PSC0_INT (AU1300_FIRST_INT + 48)
-#define AU1300_PSC1_INT (AU1300_FIRST_INT + 52)
-#define AU1300_PSC2_INT (AU1300_FIRST_INT + 56)
-#define AU1300_PSC3_INT (AU1300_FIRST_INT + 60)
-#define AU1300_NAND_INT (AU1300_FIRST_INT + 62)
-#define AU1300_DDMA_INT (AU1300_FIRST_INT + 75)
-#define AU1300_MMU_INT (AU1300_FIRST_INT + 76)
-#define AU1300_MPU_INT (AU1300_FIRST_INT + 77)
-#define AU1300_GPU_INT (AU1300_FIRST_INT + 78)
-#define AU1300_UDMA_INT (AU1300_FIRST_INT + 79)
-#define AU1300_TOY_INT (AU1300_FIRST_INT + 80)
-#define AU1300_TOY_MATCH0_INT (AU1300_FIRST_INT + 81)
-#define AU1300_TOY_MATCH1_INT (AU1300_FIRST_INT + 82)
-#define AU1300_TOY_MATCH2_INT (AU1300_FIRST_INT + 83)
-#define AU1300_RTC_INT (AU1300_FIRST_INT + 84)
-#define AU1300_RTC_MATCH0_INT (AU1300_FIRST_INT + 85)
-#define AU1300_RTC_MATCH1_INT (AU1300_FIRST_INT + 86)
-#define AU1300_RTC_MATCH2_INT (AU1300_FIRST_INT + 87)
-#define AU1300_UART0_INT (AU1300_FIRST_INT + 88)
-#define AU1300_SD0_INT (AU1300_FIRST_INT + 89)
-#define AU1300_USB_INT (AU1300_FIRST_INT + 90)
-#define AU1300_LCD_INT (AU1300_FIRST_INT + 91)
-#define AU1300_BSA_INT (AU1300_FIRST_INT + 92)
-#define AU1300_MPE_INT (AU1300_FIRST_INT + 93)
-#define AU1300_ITE_INT (AU1300_FIRST_INT + 94)
-#define AU1300_AES_INT (AU1300_FIRST_INT + 95)
-#define AU1300_CIM_INT (AU1300_FIRST_INT + 96)
-
-/**********************************************************************/
-
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
- */
-
-#define AU1000_AC97_PHYS_ADDR 0x10000000 /* 012 */
-#define AU1300_ROM_PHYS_ADDR 0x10000000 /* 5 */
-#define AU1300_OTP_PHYS_ADDR 0x10002000 /* 5 */
-#define AU1300_VSS_PHYS_ADDR 0x10003000 /* 5 */
-#define AU1300_UART0_PHYS_ADDR 0x10100000 /* 5 */
-#define AU1300_UART1_PHYS_ADDR 0x10101000 /* 5 */
-#define AU1300_UART2_PHYS_ADDR 0x10102000 /* 5 */
-#define AU1300_UART3_PHYS_ADDR 0x10103000 /* 5 */
-#define AU1000_USB_OHCI_PHYS_ADDR 0x10100000 /* 012 */
-#define AU1000_USB_UDC_PHYS_ADDR 0x10200000 /* 0123 */
-#define AU1300_GPIC_PHYS_ADDR 0x10200000 /* 5 */
-#define AU1000_IRDA_PHYS_ADDR 0x10300000 /* 02 */
-#define AU1200_AES_PHYS_ADDR 0x10300000 /* 45 */
-#define AU1000_IC0_PHYS_ADDR 0x10400000 /* 01234 */
-#define AU1300_GPU_PHYS_ADDR 0x10500000 /* 5 */
-#define AU1000_MAC0_PHYS_ADDR 0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR 0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR 0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR 0x10600000 /* 245 */
-#define AU1300_SD1_PHYS_ADDR 0x10601000 /* 5 */
-#define AU1300_SD2_PHYS_ADDR 0x10602000 /* 5 */
-#define AU1100_SD1_PHYS_ADDR 0x10680000 /* 24 */
-#define AU1300_SYS_PHYS_ADDR 0x10900000 /* 5 */
-#define AU1550_PSC2_PHYS_ADDR 0x10A00000 /* 3 */
-#define AU1550_PSC3_PHYS_ADDR 0x10B00000 /* 3 */
-#define AU1300_PSC0_PHYS_ADDR 0x10A00000 /* 5 */
-#define AU1300_PSC1_PHYS_ADDR 0x10A01000 /* 5 */
-#define AU1300_PSC2_PHYS_ADDR 0x10A02000 /* 5 */
-#define AU1300_PSC3_PHYS_ADDR 0x10A03000 /* 5 */
-#define AU1000_I2S_PHYS_ADDR 0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR 0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR 0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR 0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR 0x11100000 /* 01234 */
-#define AU1200_SWCNT_PHYS_ADDR 0x1110010C /* 4 */
-#define AU1000_UART1_PHYS_ADDR 0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR 0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR 0x11400000 /* 0123 */
-#define AU1000_SSI0_PHYS_ADDR 0x11600000 /* 02 */
-#define AU1000_SSI1_PHYS_ADDR 0x11680000 /* 02 */
-#define AU1500_GPIO2_PHYS_ADDR 0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR 0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR 0x11900000 /* 012345 */
-#define AU1550_PSC0_PHYS_ADDR 0x11A00000 /* 34 */
-#define AU1550_PSC1_PHYS_ADDR 0x11B00000 /* 34 */
-#define AU1000_MEM_PHYS_ADDR 0x14000000 /* 01234 */
-#define AU1000_STATIC_MEM_PHYS_ADDR 0x14001000 /* 01234 */
-#define AU1300_UDMA_PHYS_ADDR 0x14001800 /* 5 */
-#define AU1000_DMA_PHYS_ADDR 0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR 0x14002000 /* 345 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR 0x14003000 /* 345 */
-#define AU1000_MACDMA0_PHYS_ADDR 0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR 0x14004200 /* 0123 */
-#define AU1200_CIM_PHYS_ADDR 0x14004000 /* 45 */
-#define AU1500_PCI_PHYS_ADDR 0x14005000 /* 13 */
-#define AU1550_PE_PHYS_ADDR 0x14008000 /* 3 */
-#define AU1200_MAEBE_PHYS_ADDR 0x14010000 /* 4 */
-#define AU1200_MAEFE_PHYS_ADDR 0x14012000 /* 4 */
-#define AU1300_MAEITE_PHYS_ADDR 0x14010000 /* 5 */
-#define AU1300_MAEMPE_PHYS_ADDR 0x14014000 /* 5 */
-#define AU1550_USB_OHCI_PHYS_ADDR 0x14020000 /* 3 */
-#define AU1200_USB_CTL_PHYS_ADDR 0x14020000 /* 4 */
-#define AU1200_USB_OTG_PHYS_ADDR 0x14020020 /* 4 */
-#define AU1200_USB_OHCI_PHYS_ADDR 0x14020100 /* 4 */
-#define AU1200_USB_EHCI_PHYS_ADDR 0x14020200 /* 4 */
-#define AU1200_USB_UDC_PHYS_ADDR 0x14022000 /* 4 */
-#define AU1300_USB_EHCI_PHYS_ADDR 0x14020000 /* 5 */
-#define AU1300_USB_OHCI0_PHYS_ADDR 0x14020400 /* 5 */
-#define AU1300_USB_OHCI1_PHYS_ADDR 0x14020800 /* 5 */
-#define AU1300_USB_CTL_PHYS_ADDR 0x14021000 /* 5 */
-#define AU1300_USB_OTG_PHYS_ADDR 0x14022000 /* 5 */
-#define AU1300_MAEBSA_PHYS_ADDR 0x14030000 /* 5 */
-#define AU1100_LCD_PHYS_ADDR 0x15000000 /* 2 */
-#define AU1200_LCD_PHYS_ADDR 0x15000000 /* 45 */
-#define AU1500_PCI_MEM_PHYS_ADDR 0x400000000ULL /* 13 */
-#define AU1500_PCI_IO_PHYS_ADDR 0x500000000ULL /* 13 */
-#define AU1500_PCI_CONFIG0_PHYS_ADDR 0x600000000ULL /* 13 */
-#define AU1500_PCI_CONFIG1_PHYS_ADDR 0x680000000ULL /* 13 */
-#define AU1000_PCMCIA_IO_PHYS_ADDR 0xF00000000ULL /* 012345 */
-#define AU1000_PCMCIA_ATTR_PHYS_ADDR 0xF40000000ULL /* 012345 */
-#define AU1000_PCMCIA_MEM_PHYS_ADDR 0xF80000000ULL /* 012345 */
-
-/**********************************************************************/
-
-
-/*
- * Au1300 GPIO+INT controller (GPIC) register offsets and bits
- * Registers are 128bits (0x10 bytes), divided into 4 "banks".
- */
-#define AU1300_GPIC_PINVAL 0x0000
-#define AU1300_GPIC_PINVALCLR 0x0010
-#define AU1300_GPIC_IPEND 0x0020
-#define AU1300_GPIC_PRIENC 0x0030
-#define AU1300_GPIC_IEN 0x0040 /* int_mask in manual */
-#define AU1300_GPIC_IDIS 0x0050 /* int_maskclr in manual */
-#define AU1300_GPIC_DMASEL 0x0060
-#define AU1300_GPIC_DEVSEL 0x0080
-#define AU1300_GPIC_DEVCLR 0x0090
-#define AU1300_GPIC_RSTVAL 0x00a0
-/* pin configuration space. one 32bit register for up to 128 IRQs */
-#define AU1300_GPIC_PINCFG 0x1000
-
-#define GPIC_GPIO_TO_BIT(gpio) \
- (1 << ((gpio) & 0x1f))
-
-#define GPIC_GPIO_BANKOFF(gpio) \
- (((gpio) >> 5) * 4)
-
-/* Pin Control bits: who owns the pin, what does it do */
-#define GPIC_CFG_PC_GPIN 0
-#define GPIC_CFG_PC_DEV 1
-#define GPIC_CFG_PC_GPOLOW 2
-#define GPIC_CFG_PC_GPOHIGH 3
-#define GPIC_CFG_PC_MASK 3
-
-/* assign pin to MIPS IRQ line */
-#define GPIC_CFG_IL_SET(x) (((x) & 3) << 2)
-#define GPIC_CFG_IL_MASK (3 << 2)
-
-/* pin interrupt type setup */
-#define GPIC_CFG_IC_OFF (0 << 4)
-#define GPIC_CFG_IC_LEVEL_LOW (1 << 4)
-#define GPIC_CFG_IC_LEVEL_HIGH (2 << 4)
-#define GPIC_CFG_IC_EDGE_FALL (5 << 4)
-#define GPIC_CFG_IC_EDGE_RISE (6 << 4)
-#define GPIC_CFG_IC_EDGE_BOTH (7 << 4)
-#define GPIC_CFG_IC_MASK (7 << 4)
-
-/* allow interrupt to wake cpu from 'wait' */
-#define GPIC_CFG_IDLEWAKE (1 << 7)
-
-/***********************************************************************/
-
-/* Au1000 SDRAM memory controller register offsets */
-#define AU1000_MEM_SDMODE0 0x0000
-#define AU1000_MEM_SDMODE1 0x0004
-#define AU1000_MEM_SDMODE2 0x0008
-#define AU1000_MEM_SDADDR0 0x000C
-#define AU1000_MEM_SDADDR1 0x0010
-#define AU1000_MEM_SDADDR2 0x0014
-#define AU1000_MEM_SDREFCFG 0x0018
-#define AU1000_MEM_SDPRECMD 0x001C
-#define AU1000_MEM_SDAUTOREF 0x0020
-#define AU1000_MEM_SDWRMD0 0x0024
-#define AU1000_MEM_SDWRMD1 0x0028
-#define AU1000_MEM_SDWRMD2 0x002C
-#define AU1000_MEM_SDSLEEP 0x0030
-#define AU1000_MEM_SDSMCKE 0x0034
-
-/* MEM_SDMODE register content definitions */
-#define MEM_SDMODE_F (1 << 22)
-#define MEM_SDMODE_SR (1 << 21)
-#define MEM_SDMODE_BS (1 << 20)
-#define MEM_SDMODE_RS (3 << 18)
-#define MEM_SDMODE_CS (7 << 15)
-#define MEM_SDMODE_TRAS (15 << 11)
-#define MEM_SDMODE_TMRD (3 << 9)
-#define MEM_SDMODE_TWR (3 << 7)
-#define MEM_SDMODE_TRP (3 << 5)
-#define MEM_SDMODE_TRCD (3 << 3)
-#define MEM_SDMODE_TCL (7 << 0)
-
-#define MEM_SDMODE_BS_2Bank (0 << 20)
-#define MEM_SDMODE_BS_4Bank (1 << 20)
-#define MEM_SDMODE_RS_11Row (0 << 18)
-#define MEM_SDMODE_RS_12Row (1 << 18)
-#define MEM_SDMODE_RS_13Row (2 << 18)
-#define MEM_SDMODE_RS_N(N) ((N) << 18)
-#define MEM_SDMODE_CS_7Col (0 << 15)
-#define MEM_SDMODE_CS_8Col (1 << 15)
-#define MEM_SDMODE_CS_9Col (2 << 15)
-#define MEM_SDMODE_CS_10Col (3 << 15)
-#define MEM_SDMODE_CS_11Col (4 << 15)
-#define MEM_SDMODE_CS_N(N) ((N) << 15)
-#define MEM_SDMODE_TRAS_N(N) ((N) << 11)
-#define MEM_SDMODE_TMRD_N(N) ((N) << 9)
-#define MEM_SDMODE_TWR_N(N) ((N) << 7)
-#define MEM_SDMODE_TRP_N(N) ((N) << 5)
-#define MEM_SDMODE_TRCD_N(N) ((N) << 3)
-#define MEM_SDMODE_TCL_N(N) ((N) << 0)
-
-/* MEM_SDADDR register contents definitions */
-#define MEM_SDADDR_E (1 << 20)
-#define MEM_SDADDR_CSBA (0x03FF << 10)
-#define MEM_SDADDR_CSMASK (0x03FF << 0)
-#define MEM_SDADDR_CSBA_N(N) ((N) & (0x03FF << 22) >> 12)
-#define MEM_SDADDR_CSMASK_N(N) ((N)&(0x03FF << 22) >> 22)
-
-/* MEM_SDREFCFG register content definitions */
-#define MEM_SDREFCFG_TRC (15 << 28)
-#define MEM_SDREFCFG_TRPM (3 << 26)
-#define MEM_SDREFCFG_E (1 << 25)
-#define MEM_SDREFCFG_RE (0x1ffffff << 0)
-#define MEM_SDREFCFG_TRC_N(N) ((N) << MEM_SDREFCFG_TRC)
-#define MEM_SDREFCFG_TRPM_N(N) ((N) << MEM_SDREFCFG_TRPM)
-#define MEM_SDREFCFG_REF_N(N) (N)
-
-/* Au1550 SDRAM Register Offsets */
-#define AU1550_MEM_SDMODE0 0x0800
-#define AU1550_MEM_SDMODE1 0x0808
-#define AU1550_MEM_SDMODE2 0x0810
-#define AU1550_MEM_SDADDR0 0x0820
-#define AU1550_MEM_SDADDR1 0x0828
-#define AU1550_MEM_SDADDR2 0x0830
-#define AU1550_MEM_SDCONFIGA 0x0840
-#define AU1550_MEM_SDCONFIGB 0x0848
-#define AU1550_MEM_SDSTAT 0x0850
-#define AU1550_MEM_SDERRADDR 0x0858
-#define AU1550_MEM_SDSTRIDE0 0x0860
-#define AU1550_MEM_SDSTRIDE1 0x0868
-#define AU1550_MEM_SDSTRIDE2 0x0870
-#define AU1550_MEM_SDWRMD0 0x0880
-#define AU1550_MEM_SDWRMD1 0x0888
-#define AU1550_MEM_SDWRMD2 0x0890
-#define AU1550_MEM_SDPRECMD 0x08C0
-#define AU1550_MEM_SDAUTOREF 0x08C8
-#define AU1550_MEM_SDSREF 0x08D0
-#define AU1550_MEM_SDSLEEP MEM_SDSREF
-
-/* Static Bus Controller */
-#define MEM_STCFG0 0xB4001000
-#define MEM_STTIME0 0xB4001004
-#define MEM_STADDR0 0xB4001008
-
-#define MEM_STCFG1 0xB4001010
-#define MEM_STTIME1 0xB4001014
-#define MEM_STADDR1 0xB4001018
-
-#define MEM_STCFG2 0xB4001020
-#define MEM_STTIME2 0xB4001024
-#define MEM_STADDR2 0xB4001028
-
-#define MEM_STCFG3 0xB4001030
-#define MEM_STTIME3 0xB4001034
-#define MEM_STADDR3 0xB4001038
-
-#define MEM_STNDCTL 0xB4001100
-#define MEM_STSTAT 0xB4001104
-
-#define MEM_STNAND_CMD 0x0
-#define MEM_STNAND_ADDR 0x4
-#define MEM_STNAND_DATA 0x20
-
-
-/* Programmable Counters 0 and 1 */
-#define SYS_BASE 0xB1900000
-#define SYS_COUNTER_CNTRL (SYS_BASE + 0x14)
-# define SYS_CNTRL_E1S (1 << 23)
-# define SYS_CNTRL_T1S (1 << 20)
-# define SYS_CNTRL_M21 (1 << 19)
-# define SYS_CNTRL_M11 (1 << 18)
-# define SYS_CNTRL_M01 (1 << 17)
-# define SYS_CNTRL_C1S (1 << 16)
-# define SYS_CNTRL_BP (1 << 14)
-# define SYS_CNTRL_EN1 (1 << 13)
-# define SYS_CNTRL_BT1 (1 << 12)
-# define SYS_CNTRL_EN0 (1 << 11)
-# define SYS_CNTRL_BT0 (1 << 10)
-# define SYS_CNTRL_E0 (1 << 8)
-# define SYS_CNTRL_E0S (1 << 7)
-# define SYS_CNTRL_32S (1 << 5)
-# define SYS_CNTRL_T0S (1 << 4)
-# define SYS_CNTRL_M20 (1 << 3)
-# define SYS_CNTRL_M10 (1 << 2)
-# define SYS_CNTRL_M00 (1 << 1)
-# define SYS_CNTRL_C0S (1 << 0)
-
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM (SYS_BASE + 0)
-#define SYS_TOYWRITE (SYS_BASE + 4)
-#define SYS_TOYMATCH0 (SYS_BASE + 8)
-#define SYS_TOYMATCH1 (SYS_BASE + 0xC)
-#define SYS_TOYMATCH2 (SYS_BASE + 0x10)
-#define SYS_TOYREAD (SYS_BASE + 0x40)
-
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM (SYS_BASE + 0x44)
-#define SYS_RTCWRITE (SYS_BASE + 0x48)
-#define SYS_RTCMATCH0 (SYS_BASE + 0x4C)
-#define SYS_RTCMATCH1 (SYS_BASE + 0x50)
-#define SYS_RTCMATCH2 (SYS_BASE + 0x54)
-#define SYS_RTCREAD (SYS_BASE + 0x58)
-
-/* I2S Controller */
-#define I2S_DATA 0xB1000000
-# define I2S_DATA_MASK 0xffffff
-#define I2S_CONFIG 0xB1000004
-# define I2S_CONFIG_XU (1 << 25)
-# define I2S_CONFIG_XO (1 << 24)
-# define I2S_CONFIG_RU (1 << 23)
-# define I2S_CONFIG_RO (1 << 22)
-# define I2S_CONFIG_TR (1 << 21)
-# define I2S_CONFIG_TE (1 << 20)
-# define I2S_CONFIG_TF (1 << 19)
-# define I2S_CONFIG_RR (1 << 18)
-# define I2S_CONFIG_RE (1 << 17)
-# define I2S_CONFIG_RF (1 << 16)
-# define I2S_CONFIG_PD (1 << 11)
-# define I2S_CONFIG_LB (1 << 10)
-# define I2S_CONFIG_IC (1 << 9)
-# define I2S_CONFIG_FM_BIT 7
-# define I2S_CONFIG_FM_MASK (0x3 << I2S_CONFIG_FM_BIT)
-# define I2S_CONFIG_FM_I2S (0x0 << I2S_CONFIG_FM_BIT)
-# define I2S_CONFIG_FM_LJ (0x1 << I2S_CONFIG_FM_BIT)
-# define I2S_CONFIG_FM_RJ (0x2 << I2S_CONFIG_FM_BIT)
-# define I2S_CONFIG_TN (1 << 6)
-# define I2S_CONFIG_RN (1 << 5)
-# define I2S_CONFIG_SZ_BIT 0
-# define I2S_CONFIG_SZ_MASK (0x1F << I2S_CONFIG_SZ_BIT)
-
-#define I2S_CONTROL 0xB1000008
-# define I2S_CONTROL_D (1 << 1)
-# define I2S_CONTROL_CE (1 << 0)
-
-
-/* Ethernet Controllers */
-
-/* 4 byte offsets from AU1000_ETH_BASE */
-#define MAC_CONTROL 0x0
-# define MAC_RX_ENABLE (1 << 2)
-# define MAC_TX_ENABLE (1 << 3)
-# define MAC_DEF_CHECK (1 << 5)
-# define MAC_SET_BL(X) (((X) & 0x3) << 6)
-# define MAC_AUTO_PAD (1 << 8)
-# define MAC_DISABLE_RETRY (1 << 10)
-# define MAC_DISABLE_BCAST (1 << 11)
-# define MAC_LATE_COL (1 << 12)
-# define MAC_HASH_MODE (1 << 13)
-# define MAC_HASH_ONLY (1 << 15)
-# define MAC_PASS_ALL (1 << 16)
-# define MAC_INVERSE_FILTER (1 << 17)
-# define MAC_PROMISCUOUS (1 << 18)
-# define MAC_PASS_ALL_MULTI (1 << 19)
-# define MAC_FULL_DUPLEX (1 << 20)
-# define MAC_NORMAL_MODE 0
-# define MAC_INT_LOOPBACK (1 << 21)
-# define MAC_EXT_LOOPBACK (1 << 22)
-# define MAC_DISABLE_RX_OWN (1 << 23)
-# define MAC_BIG_ENDIAN (1 << 30)
-# define MAC_RX_ALL (1 << 31)
-#define MAC_ADDRESS_HIGH 0x4
-#define MAC_ADDRESS_LOW 0x8
-#define MAC_MCAST_HIGH 0xC
-#define MAC_MCAST_LOW 0x10
-#define MAC_MII_CNTRL 0x14
-# define MAC_MII_BUSY (1 << 0)
-# define MAC_MII_READ 0
-# define MAC_MII_WRITE (1 << 1)
-# define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
-# define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
-#define MAC_MII_DATA 0x18
-#define MAC_FLOW_CNTRL 0x1C
-# define MAC_FLOW_CNTRL_BUSY (1 << 0)
-# define MAC_FLOW_CNTRL_ENABLE (1 << 1)
-# define MAC_PASS_CONTROL (1 << 2)
-# define MAC_SET_PAUSE(X) (((X) & 0xffff) << 16)
-#define MAC_VLAN1_TAG 0x20
-#define MAC_VLAN2_TAG 0x24
-
-/* Ethernet Controller Enable */
-
-# define MAC_EN_CLOCK_ENABLE (1 << 0)
-# define MAC_EN_RESET0 (1 << 1)
-# define MAC_EN_TOSS (0 << 2)
-# define MAC_EN_CACHEABLE (1 << 3)
-# define MAC_EN_RESET1 (1 << 4)
-# define MAC_EN_RESET2 (1 << 5)
-# define MAC_DMA_RESET (1 << 6)
-
-/* Ethernet Controller DMA Channels */
-
-#define MAC0_TX_DMA_ADDR 0xB4004000
-#define MAC1_TX_DMA_ADDR 0xB4004200
-/* offsets from MAC_TX_RING_ADDR address */
-#define MAC_TX_BUFF0_STATUS 0x0
-# define TX_FRAME_ABORTED (1 << 0)
-# define TX_JAB_TIMEOUT (1 << 1)
-# define TX_NO_CARRIER (1 << 2)
-# define TX_LOSS_CARRIER (1 << 3)
-# define TX_EXC_DEF (1 << 4)
-# define TX_LATE_COLL_ABORT (1 << 5)
-# define TX_EXC_COLL (1 << 6)
-# define TX_UNDERRUN (1 << 7)
-# define TX_DEFERRED (1 << 8)
-# define TX_LATE_COLL (1 << 9)
-# define TX_COLL_CNT_MASK (0xF << 10)
-# define TX_PKT_RETRY (1 << 31)
-#define MAC_TX_BUFF0_ADDR 0x4
-# define TX_DMA_ENABLE (1 << 0)
-# define TX_T_DONE (1 << 1)
-# define TX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
-#define MAC_TX_BUFF0_LEN 0x8
-#define MAC_TX_BUFF1_STATUS 0x10
-#define MAC_TX_BUFF1_ADDR 0x14
-#define MAC_TX_BUFF1_LEN 0x18
-#define MAC_TX_BUFF2_STATUS 0x20
-#define MAC_TX_BUFF2_ADDR 0x24
-#define MAC_TX_BUFF2_LEN 0x28
-#define MAC_TX_BUFF3_STATUS 0x30
-#define MAC_TX_BUFF3_ADDR 0x34
-#define MAC_TX_BUFF3_LEN 0x38
-
-#define MAC0_RX_DMA_ADDR 0xB4004100
-#define MAC1_RX_DMA_ADDR 0xB4004300
-/* offsets from MAC_RX_RING_ADDR */
-#define MAC_RX_BUFF0_STATUS 0x0
-# define RX_FRAME_LEN_MASK 0x3fff
-# define RX_WDOG_TIMER (1 << 14)
-# define RX_RUNT (1 << 15)
-# define RX_OVERLEN (1 << 16)
-# define RX_COLL (1 << 17)
-# define RX_ETHER (1 << 18)
-# define RX_MII_ERROR (1 << 19)
-# define RX_DRIBBLING (1 << 20)
-# define RX_CRC_ERROR (1 << 21)
-# define RX_VLAN1 (1 << 22)
-# define RX_VLAN2 (1 << 23)
-# define RX_LEN_ERROR (1 << 24)
-# define RX_CNTRL_FRAME (1 << 25)
-# define RX_U_CNTRL_FRAME (1 << 26)
-# define RX_MCAST_FRAME (1 << 27)
-# define RX_BCAST_FRAME (1 << 28)
-# define RX_FILTER_FAIL (1 << 29)
-# define RX_PACKET_FILTER (1 << 30)
-# define RX_MISSED_FRAME (1 << 31)
-
-# define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN | \
- RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
- RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
-#define MAC_RX_BUFF0_ADDR 0x4
-# define RX_DMA_ENABLE (1 << 0)
-# define RX_T_DONE (1 << 1)
-# define RX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
-# define RX_SET_BUFF_ADDR(X) ((X) & 0xffffffc0)
-#define MAC_RX_BUFF1_STATUS 0x10
-#define MAC_RX_BUFF1_ADDR 0x14
-#define MAC_RX_BUFF2_STATUS 0x20
-#define MAC_RX_BUFF2_ADDR 0x24
-#define MAC_RX_BUFF3_STATUS 0x30
-#define MAC_RX_BUFF3_ADDR 0x34
-
-/* SSIO */
-#define SSI0_STATUS 0xB1600000
-# define SSI_STATUS_BF (1 << 4)
-# define SSI_STATUS_OF (1 << 3)
-# define SSI_STATUS_UF (1 << 2)
-# define SSI_STATUS_D (1 << 1)
-# define SSI_STATUS_B (1 << 0)
-#define SSI0_INT 0xB1600004
-# define SSI_INT_OI (1 << 3)
-# define SSI_INT_UI (1 << 2)
-# define SSI_INT_DI (1 << 1)
-#define SSI0_INT_ENABLE 0xB1600008
-# define SSI_INTE_OIE (1 << 3)
-# define SSI_INTE_UIE (1 << 2)
-# define SSI_INTE_DIE (1 << 1)
-#define SSI0_CONFIG 0xB1600020
-# define SSI_CONFIG_AO (1 << 24)
-# define SSI_CONFIG_DO (1 << 23)
-# define SSI_CONFIG_ALEN_BIT 20
-# define SSI_CONFIG_ALEN_MASK (0x7 << 20)
-# define SSI_CONFIG_DLEN_BIT 16
-# define SSI_CONFIG_DLEN_MASK (0x7 << 16)
-# define SSI_CONFIG_DD (1 << 11)
-# define SSI_CONFIG_AD (1 << 10)
-# define SSI_CONFIG_BM_BIT 8
-# define SSI_CONFIG_BM_MASK (0x3 << 8)
-# define SSI_CONFIG_CE (1 << 7)
-# define SSI_CONFIG_DP (1 << 6)
-# define SSI_CONFIG_DL (1 << 5)
-# define SSI_CONFIG_EP (1 << 4)
-#define SSI0_ADATA 0xB1600024
-# define SSI_AD_D (1 << 24)
-# define SSI_AD_ADDR_BIT 16
-# define SSI_AD_ADDR_MASK (0xff << 16)
-# define SSI_AD_DATA_BIT 0
-# define SSI_AD_DATA_MASK (0xfff << 0)
-#define SSI0_CLKDIV 0xB1600028
-#define SSI0_CONTROL 0xB1600100
-# define SSI_CONTROL_CD (1 << 1)
-# define SSI_CONTROL_E (1 << 0)
-
-/* SSI1 */
-#define SSI1_STATUS 0xB1680000
-#define SSI1_INT 0xB1680004
-#define SSI1_INT_ENABLE 0xB1680008
-#define SSI1_CONFIG 0xB1680020
-#define SSI1_ADATA 0xB1680024
-#define SSI1_CLKDIV 0xB1680028
-#define SSI1_ENABLE 0xB1680100
-
-/*
- * Register content definitions
- */
-#define SSI_STATUS_BF (1 << 4)
-#define SSI_STATUS_OF (1 << 3)
-#define SSI_STATUS_UF (1 << 2)
-#define SSI_STATUS_D (1 << 1)
-#define SSI_STATUS_B (1 << 0)
-
-/* SSI_INT */
-#define SSI_INT_OI (1 << 3)
-#define SSI_INT_UI (1 << 2)
-#define SSI_INT_DI (1 << 1)
-
-/* SSI_INTEN */
-#define SSI_INTEN_OIE (1 << 3)
-#define SSI_INTEN_UIE (1 << 2)
-#define SSI_INTEN_DIE (1 << 1)
-
-#define SSI_CONFIG_AO (1 << 24)
-#define SSI_CONFIG_DO (1 << 23)
-#define SSI_CONFIG_ALEN (7 << 20)
-#define SSI_CONFIG_DLEN (15 << 16)
-#define SSI_CONFIG_DD (1 << 11)
-#define SSI_CONFIG_AD (1 << 10)
-#define SSI_CONFIG_BM (3 << 8)
-#define SSI_CONFIG_CE (1 << 7)
-#define SSI_CONFIG_DP (1 << 6)
-#define SSI_CONFIG_DL (1 << 5)
-#define SSI_CONFIG_EP (1 << 4)
-#define SSI_CONFIG_ALEN_N(N) ((N-1) << 20)
-#define SSI_CONFIG_DLEN_N(N) ((N-1) << 16)
-#define SSI_CONFIG_BM_HI (0 << 8)
-#define SSI_CONFIG_BM_LO (1 << 8)
-#define SSI_CONFIG_BM_CY (2 << 8)
-
-#define SSI_ADATA_D (1 << 24)
-#define SSI_ADATA_ADDR (0xFF << 16)
-#define SSI_ADATA_DATA 0x0FFF
-#define SSI_ADATA_ADDR_N(N) (N << 16)
-
-#define SSI_ENABLE_CD (1 << 1)
-#define SSI_ENABLE_E (1 << 0)
-
-
-/*
- * The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's not
- * used to select FIR/SIR mode on the transceiver but as a GPIO. Instead a
- * CPLD has to be told about the mode.
- */
-#define AU1000_IRDA_PHY_MODE_OFF 0
-#define AU1000_IRDA_PHY_MODE_SIR 1
-#define AU1000_IRDA_PHY_MODE_FIR 2
-
-struct au1k_irda_platform_data {
- void(*set_phy_mode)(int mode);
-};
-
-
-/* GPIO */
-#define SYS_PINFUNC 0xB190002C
-# define SYS_PF_USB (1 << 15) /* 2nd USB device/host */
-# define SYS_PF_U3 (1 << 14) /* GPIO23/U3TXD */
-# define SYS_PF_U2 (1 << 13) /* GPIO22/U2TXD */
-# define SYS_PF_U1 (1 << 12) /* GPIO21/U1TXD */
-# define SYS_PF_SRC (1 << 11) /* GPIO6/SROMCKE */
-# define SYS_PF_CK5 (1 << 10) /* GPIO3/CLK5 */
-# define SYS_PF_CK4 (1 << 9) /* GPIO2/CLK4 */
-# define SYS_PF_IRF (1 << 8) /* GPIO15/IRFIRSEL */
-# define SYS_PF_UR3 (1 << 7) /* GPIO[14:9]/UART3 */
-# define SYS_PF_I2D (1 << 6) /* GPIO8/I2SDI */
-# define SYS_PF_I2S (1 << 5) /* I2S/GPIO[29:31] */
-# define SYS_PF_NI2 (1 << 4) /* NI2/GPIO[24:28] */
-# define SYS_PF_U0 (1 << 3) /* U0TXD/GPIO20 */
-# define SYS_PF_RD (1 << 2) /* IRTXD/GPIO19 */
-# define SYS_PF_A97 (1 << 1) /* AC97/SSL1 */
-# define SYS_PF_S0 (1 << 0) /* SSI_0/GPIO[16:18] */
-
-/* Au1100 only */
-# define SYS_PF_PC (1 << 18) /* PCMCIA/GPIO[207:204] */
-# define SYS_PF_LCD (1 << 17) /* extern lcd/GPIO[203:200] */
-# define SYS_PF_CS (1 << 16) /* EXTCLK0/32KHz to gpio2 */
-# define SYS_PF_EX0 (1 << 9) /* GPIO2/clock */
-
-/* Au1550 only. Redefines lots of pins */
-# define SYS_PF_PSC2_MASK (7 << 17)
-# define SYS_PF_PSC2_AC97 0
-# define SYS_PF_PSC2_SPI 0
-# define SYS_PF_PSC2_I2S (1 << 17)
-# define SYS_PF_PSC2_SMBUS (3 << 17)
-# define SYS_PF_PSC2_GPIO (7 << 17)
-# define SYS_PF_PSC3_MASK (7 << 20)
-# define SYS_PF_PSC3_AC97 0
-# define SYS_PF_PSC3_SPI 0
-# define SYS_PF_PSC3_I2S (1 << 20)
-# define SYS_PF_PSC3_SMBUS (3 << 20)
-# define SYS_PF_PSC3_GPIO (7 << 20)
-# define SYS_PF_PSC1_S1 (1 << 1)
-# define SYS_PF_MUST_BE_SET ((1 << 5) | (1 << 2))
-
-/* Au1200 only */
-#define SYS_PINFUNC_DMA (1 << 31)
-#define SYS_PINFUNC_S0A (1 << 30)
-#define SYS_PINFUNC_S1A (1 << 29)
-#define SYS_PINFUNC_LP0 (1 << 28)
-#define SYS_PINFUNC_LP1 (1 << 27)
-#define SYS_PINFUNC_LD16 (1 << 26)
-#define SYS_PINFUNC_LD8 (1 << 25)
-#define SYS_PINFUNC_LD1 (1 << 24)
-#define SYS_PINFUNC_LD0 (1 << 23)
-#define SYS_PINFUNC_P1A (3 << 21)
-#define SYS_PINFUNC_P1B (1 << 20)
-#define SYS_PINFUNC_FS3 (1 << 19)
-#define SYS_PINFUNC_P0A (3 << 17)
-#define SYS_PINFUNC_CS (1 << 16)
-#define SYS_PINFUNC_CIM (1 << 15)
-#define SYS_PINFUNC_P1C (1 << 14)
-#define SYS_PINFUNC_U1T (1 << 12)
-#define SYS_PINFUNC_U1R (1 << 11)
-#define SYS_PINFUNC_EX1 (1 << 10)
-#define SYS_PINFUNC_EX0 (1 << 9)
-#define SYS_PINFUNC_U0R (1 << 8)
-#define SYS_PINFUNC_MC (1 << 7)
-#define SYS_PINFUNC_S0B (1 << 6)
-#define SYS_PINFUNC_S0C (1 << 5)
-#define SYS_PINFUNC_P0B (1 << 4)
-#define SYS_PINFUNC_U0T (1 << 3)
-#define SYS_PINFUNC_S1B (1 << 2)
-
-/* Power Management */
-#define SYS_SCRATCH0 0xB1900018
-#define SYS_SCRATCH1 0xB190001C
-#define SYS_WAKEMSK 0xB1900034
-#define SYS_ENDIAN 0xB1900038
-#define SYS_POWERCTRL 0xB190003C
-#define SYS_WAKESRC 0xB190005C
-#define SYS_SLPPWR 0xB1900078
-#define SYS_SLEEP 0xB190007C
-
-#define SYS_WAKEMSK_D2 (1 << 9)
-#define SYS_WAKEMSK_M2 (1 << 8)
-#define SYS_WAKEMSK_GPIO(x) (1 << (x))
-
-/* Clock Controller */
-#define SYS_FREQCTRL0 0xB1900020
-# define SYS_FC_FRDIV2_BIT 22
-# define SYS_FC_FRDIV2_MASK (0xff << SYS_FC_FRDIV2_BIT)
-# define SYS_FC_FE2 (1 << 21)
-# define SYS_FC_FS2 (1 << 20)
-# define SYS_FC_FRDIV1_BIT 12
-# define SYS_FC_FRDIV1_MASK (0xff << SYS_FC_FRDIV1_BIT)
-# define SYS_FC_FE1 (1 << 11)
-# define SYS_FC_FS1 (1 << 10)
-# define SYS_FC_FRDIV0_BIT 2
-# define SYS_FC_FRDIV0_MASK (0xff << SYS_FC_FRDIV0_BIT)
-# define SYS_FC_FE0 (1 << 1)
-# define SYS_FC_FS0 (1 << 0)
-#define SYS_FREQCTRL1 0xB1900024
-# define SYS_FC_FRDIV5_BIT 22
-# define SYS_FC_FRDIV5_MASK (0xff << SYS_FC_FRDIV5_BIT)
-# define SYS_FC_FE5 (1 << 21)
-# define SYS_FC_FS5 (1 << 20)
-# define SYS_FC_FRDIV4_BIT 12
-# define SYS_FC_FRDIV4_MASK (0xff << SYS_FC_FRDIV4_BIT)
-# define SYS_FC_FE4 (1 << 11)
-# define SYS_FC_FS4 (1 << 10)
-# define SYS_FC_FRDIV3_BIT 2
-# define SYS_FC_FRDIV3_MASK (0xff << SYS_FC_FRDIV3_BIT)
-# define SYS_FC_FE3 (1 << 1)
-# define SYS_FC_FS3 (1 << 0)
-#define SYS_CLKSRC 0xB1900028
-# define SYS_CS_ME1_BIT 27
-# define SYS_CS_ME1_MASK (0x7 << SYS_CS_ME1_BIT)
-# define SYS_CS_DE1 (1 << 26)
-# define SYS_CS_CE1 (1 << 25)
-# define SYS_CS_ME0_BIT 22
-# define SYS_CS_ME0_MASK (0x7 << SYS_CS_ME0_BIT)
-# define SYS_CS_DE0 (1 << 21)
-# define SYS_CS_CE0 (1 << 20)
-# define SYS_CS_MI2_BIT 17
-# define SYS_CS_MI2_MASK (0x7 << SYS_CS_MI2_BIT)
-# define SYS_CS_DI2 (1 << 16)
-# define SYS_CS_CI2 (1 << 15)
-
-# define SYS_CS_ML_BIT 7
-# define SYS_CS_ML_MASK (0x7 << SYS_CS_ML_BIT)
-# define SYS_CS_DL (1 << 6)
-# define SYS_CS_CL (1 << 5)
-
-# define SYS_CS_MUH_BIT 12
-# define SYS_CS_MUH_MASK (0x7 << SYS_CS_MUH_BIT)
-# define SYS_CS_DUH (1 << 11)
-# define SYS_CS_CUH (1 << 10)
-# define SYS_CS_MUD_BIT 7
-# define SYS_CS_MUD_MASK (0x7 << SYS_CS_MUD_BIT)
-# define SYS_CS_DUD (1 << 6)
-# define SYS_CS_CUD (1 << 5)
-
-# define SYS_CS_MIR_BIT 2
-# define SYS_CS_MIR_MASK (0x7 << SYS_CS_MIR_BIT)
-# define SYS_CS_DIR (1 << 1)
-# define SYS_CS_CIR (1 << 0)
-
-# define SYS_CS_MUX_AUX 0x1
-# define SYS_CS_MUX_FQ0 0x2
-# define SYS_CS_MUX_FQ1 0x3
-# define SYS_CS_MUX_FQ2 0x4
-# define SYS_CS_MUX_FQ3 0x5
-# define SYS_CS_MUX_FQ4 0x6
-# define SYS_CS_MUX_FQ5 0x7
-#define SYS_CPUPLL 0xB1900060
-#define SYS_AUXPLL 0xB1900064
-
-/* AC97 Controller */
-#define AC97C_CONFIG 0xB0000000
-# define AC97C_RECV_SLOTS_BIT 13
-# define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
-# define AC97C_XMIT_SLOTS_BIT 3
-# define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
-# define AC97C_SG (1 << 2)
-# define AC97C_SYNC (1 << 1)
-# define AC97C_RESET (1 << 0)
-#define AC97C_STATUS 0xB0000004
-# define AC97C_XU (1 << 11)
-# define AC97C_XO (1 << 10)
-# define AC97C_RU (1 << 9)
-# define AC97C_RO (1 << 8)
-# define AC97C_READY (1 << 7)
-# define AC97C_CP (1 << 6)
-# define AC97C_TR (1 << 5)
-# define AC97C_TE (1 << 4)
-# define AC97C_TF (1 << 3)
-# define AC97C_RR (1 << 2)
-# define AC97C_RE (1 << 1)
-# define AC97C_RF (1 << 0)
-#define AC97C_DATA 0xB0000008
-#define AC97C_CMD 0xB000000C
-# define AC97C_WD_BIT 16
-# define AC97C_READ (1 << 7)
-# define AC97C_INDEX_MASK 0x7f
-#define AC97C_CNTRL 0xB0000010
-# define AC97C_RS (1 << 1)
-# define AC97C_CE (1 << 0)
-
-
-/* The PCI chip selects are outside the 32bit space, and since we can't
- * just program the 36bit addresses into BARs, we have to take a chunk
- * out of the 32bit space and reserve it for PCI. When these addresses
- * are ioremap()ed, they'll be fixed up to the real 36bit address before
- * being passed to the real ioremap function.
- */
-#define ALCHEMY_PCI_MEMWIN_START (AU1500_PCI_MEM_PHYS_ADDR >> 4)
-#define ALCHEMY_PCI_MEMWIN_END (ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
-
-/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
- * adjust the device's resources.
- */
-#define ALCHEMY_PCI_IOWIN_START 0x00001000
-#define ALCHEMY_PCI_IOWIN_END 0x0000FFFF
-
-#ifdef CONFIG_PCI
-
-#define IOPORT_RESOURCE_START 0x00001000 /* skip legacy probing */
-#define IOPORT_RESOURCE_END 0xffffffff
-#define IOMEM_RESOURCE_START 0x10000000
-#define IOMEM_RESOURCE_END 0xfffffffffULL
-
-#else
-
-/* Don't allow any legacy ports probing */
-#define IOPORT_RESOURCE_START 0x10000000
-#define IOPORT_RESOURCE_END 0xffffffff
-#define IOMEM_RESOURCE_START 0x10000000
-#define IOMEM_RESOURCE_END 0xfffffffffULL
-
-#endif
-
-/* PCI controller block register offsets */
-#define PCI_REG_CMEM 0x0000
-#define PCI_REG_CONFIG 0x0004
-#define PCI_REG_B2BMASK_CCH 0x0008
-#define PCI_REG_B2BBASE0_VID 0x000C
-#define PCI_REG_B2BBASE1_SID 0x0010
-#define PCI_REG_MWMASK_DEV 0x0014
-#define PCI_REG_MWBASE_REV_CCL 0x0018
-#define PCI_REG_ERR_ADDR 0x001C
-#define PCI_REG_SPEC_INTACK 0x0020
-#define PCI_REG_ID 0x0100
-#define PCI_REG_STATCMD 0x0104
-#define PCI_REG_CLASSREV 0x0108
-#define PCI_REG_PARAM 0x010C
-#define PCI_REG_MBAR 0x0110
-#define PCI_REG_TIMEOUT 0x0140
-
-/* PCI controller block register bits */
-#define PCI_CMEM_E (1 << 28) /* enable cacheable memory */
-#define PCI_CMEM_CMBASE(x) (((x) & 0x3fff) << 14)
-#define PCI_CMEM_CMMASK(x) ((x) & 0x3fff)
-#define PCI_CONFIG_ERD (1 << 27) /* pci error during R/W */
-#define PCI_CONFIG_ET (1 << 26) /* error in target mode */
-#define PCI_CONFIG_EF (1 << 25) /* fatal error */
-#define PCI_CONFIG_EP (1 << 24) /* parity error */
-#define PCI_CONFIG_EM (1 << 23) /* multiple errors */
-#define PCI_CONFIG_BM (1 << 22) /* bad master error */
-#define PCI_CONFIG_PD (1 << 20) /* PCI Disable */
-#define PCI_CONFIG_BME (1 << 19) /* Byte Mask Enable for reads */
-#define PCI_CONFIG_NC (1 << 16) /* mark mem access non-coherent */
-#define PCI_CONFIG_IA (1 << 15) /* INTA# enabled (target mode) */
-#define PCI_CONFIG_IP (1 << 13) /* int on PCI_PERR# */
-#define PCI_CONFIG_IS (1 << 12) /* int on PCI_SERR# */
-#define PCI_CONFIG_IMM (1 << 11) /* int on master abort */
-#define PCI_CONFIG_ITM (1 << 10) /* int on target abort (as master) */
-#define PCI_CONFIG_ITT (1 << 9) /* int on target abort (as target) */
-#define PCI_CONFIG_IPB (1 << 8) /* int on PERR# in bus master acc */
-#define PCI_CONFIG_SIC_NO (0 << 6) /* no byte mask changes */
-#define PCI_CONFIG_SIC_BA_ADR (1 << 6) /* on byte/hw acc, invert adr bits */
-#define PCI_CONFIG_SIC_HWA_DAT (2 << 6) /* on halfword acc, swap data */
-#define PCI_CONFIG_SIC_ALL (3 << 6) /* swap data bytes on all accesses */
-#define PCI_CONFIG_ST (1 << 5) /* swap data by target transactions */
-#define PCI_CONFIG_SM (1 << 4) /* swap data from PCI ctl */
-#define PCI_CONFIG_AEN (1 << 3) /* enable internal arbiter */
-#define PCI_CONFIG_R2H (1 << 2) /* REQ2# to hi-prio arbiter */
-#define PCI_CONFIG_R1H (1 << 1) /* REQ1# to hi-prio arbiter */
-#define PCI_CONFIG_CH (1 << 0) /* PCI ctl to hi-prio arbiter */
-#define PCI_B2BMASK_B2BMASK(x) (((x) & 0xffff) << 16)
-#define PCI_B2BMASK_CCH(x) ((x) & 0xffff) /* 16 upper bits of class code */
-#define PCI_B2BBASE0_VID_B0(x) (((x) & 0xffff) << 16)
-#define PCI_B2BBASE0_VID_SV(x) ((x) & 0xffff)
-#define PCI_B2BBASE1_SID_B1(x) (((x) & 0xffff) << 16)
-#define PCI_B2BBASE1_SID_SI(x) ((x) & 0xffff)
-#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
-#define PCI_MWMASKDEV_DEVID(x) ((x) & 0xffff)
-#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
-#define PCI_MWBASEREVCCL_REV(x) (((x) & 0xff) << 8)
-#define PCI_MWBASEREVCCL_CCL(x) ((x) & 0xff)
-#define PCI_ID_DID(x) (((x) & 0xffff) << 16)
-#define PCI_ID_VID(x) ((x) & 0xffff)
-#define PCI_STATCMD_STATUS(x) (((x) & 0xffff) << 16)
-#define PCI_STATCMD_CMD(x) ((x) & 0xffff)
-#define PCI_CLASSREV_CLASS(x) (((x) & 0x00ffffff) << 8)
-#define PCI_CLASSREV_REV(x) ((x) & 0xff)
-#define PCI_PARAM_BIST(x) (((x) & 0xff) << 24)
-#define PCI_PARAM_HT(x) (((x) & 0xff) << 16)
-#define PCI_PARAM_LT(x) (((x) & 0xff) << 8)
-#define PCI_PARAM_CLS(x) ((x) & 0xff)
-#define PCI_TIMEOUT_RETRIES(x) (((x) & 0xff) << 8) /* max retries */
-#define PCI_TIMEOUT_TO(x) ((x) & 0xff) /* target ready timeout */
-
#endif
diff --git a/arch/mips/include/asm/mach-au1x00/au1000_dma.h b/arch/mips/include/asm/mach-au1x00/au1000_dma.h
index 7cedca5a305c..0a0cd4270c6f 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000_dma.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000_dma.h
@@ -106,7 +106,7 @@ enum {
struct dma_chan {
int dev_id; /* this channel is allocated if >= 0, */
/* free otherwise */
- unsigned int io;
+ void __iomem *io;
const char *dev_str;
int irq;
void *irq_dev;
@@ -157,7 +157,7 @@ static inline void enable_dma_buffer0(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
+ __raw_writel(DMA_BE0, chan->io + DMA_MODE_SET);
}
static inline void enable_dma_buffer1(unsigned int dmanr)
@@ -166,7 +166,7 @@ static inline void enable_dma_buffer1(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
+ __raw_writel(DMA_BE1, chan->io + DMA_MODE_SET);
}
static inline void enable_dma_buffers(unsigned int dmanr)
{
@@ -174,7 +174,7 @@ static inline void enable_dma_buffers(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
+ __raw_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
}
static inline void start_dma(unsigned int dmanr)
@@ -183,7 +183,7 @@ static inline void start_dma(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_GO, chan->io + DMA_MODE_SET);
+ __raw_writel(DMA_GO, chan->io + DMA_MODE_SET);
}
#define DMA_HALT_POLL 0x5000
@@ -195,11 +195,11 @@ static inline void halt_dma(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
+ __raw_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
/* Poll the halt bit */
for (i = 0; i < DMA_HALT_POLL; i++)
- if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
+ if (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
break;
if (i == DMA_HALT_POLL)
printk(KERN_INFO "halt_dma: HALT poll expired!\n");
@@ -215,7 +215,7 @@ static inline void disable_dma(unsigned int dmanr)
halt_dma(dmanr);
/* Now we can disable the buffers */
- au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
+ __raw_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
}
static inline int dma_halted(unsigned int dmanr)
@@ -224,7 +224,7 @@ static inline int dma_halted(unsigned int dmanr)
if (!chan)
return 1;
- return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
+ return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
}
/* Initialize a DMA channel. */
@@ -239,14 +239,14 @@ static inline void init_dma(unsigned int dmanr)
disable_dma(dmanr);
/* Set device FIFO address */
- au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
+ __raw_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
if (chan->irq)
mode |= DMA_IE;
- au_writel(~mode, chan->io + DMA_MODE_CLEAR);
- au_writel(mode, chan->io + DMA_MODE_SET);
+ __raw_writel(~mode, chan->io + DMA_MODE_CLEAR);
+ __raw_writel(mode, chan->io + DMA_MODE_SET);
}
/*
@@ -283,7 +283,7 @@ static inline int get_dma_active_buffer(unsigned int dmanr)
if (!chan)
return -1;
- return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
+ return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
}
/*
@@ -304,7 +304,7 @@ static inline void set_dma_fifo_addr(unsigned int dmanr, unsigned int a)
if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
return;
- au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
+ __raw_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
}
/*
@@ -316,7 +316,7 @@ static inline void clear_dma_done0(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
+ __raw_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
}
static inline void clear_dma_done1(unsigned int dmanr)
@@ -325,7 +325,7 @@ static inline void clear_dma_done1(unsigned int dmanr)
if (!chan)
return;
- au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
+ __raw_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
}
/*
@@ -344,7 +344,7 @@ static inline void set_dma_addr0(unsigned int dmanr, unsigned int a)
if (!chan)
return;
- au_writel(a, chan->io + DMA_BUFFER0_START);
+ __raw_writel(a, chan->io + DMA_BUFFER0_START);
}
/*
@@ -356,7 +356,7 @@ static inline void set_dma_addr1(unsigned int dmanr, unsigned int a)
if (!chan)
return;
- au_writel(a, chan->io + DMA_BUFFER1_START);
+ __raw_writel(a, chan->io + DMA_BUFFER1_START);
}
@@ -370,7 +370,7 @@ static inline void set_dma_count0(unsigned int dmanr, unsigned int count)
if (!chan)
return;
count &= DMA_COUNT_MASK;
- au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+ __raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
}
/*
@@ -383,7 +383,7 @@ static inline void set_dma_count1(unsigned int dmanr, unsigned int count)
if (!chan)
return;
count &= DMA_COUNT_MASK;
- au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+ __raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
}
/*
@@ -396,8 +396,8 @@ static inline void set_dma_count(unsigned int dmanr, unsigned int count)
if (!chan)
return;
count &= DMA_COUNT_MASK;
- au_writel(count, chan->io + DMA_BUFFER0_COUNT);
- au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+ __raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
+ __raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
}
/*
@@ -410,7 +410,7 @@ static inline unsigned int get_dma_buffer_done(unsigned int dmanr)
if (!chan)
return 0;
- return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
+ return __raw_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
}
@@ -437,10 +437,10 @@ static inline int get_dma_residue(unsigned int dmanr)
if (!chan)
return 0;
- curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
+ curBufCntReg = (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
- count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
+ count = __raw_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
count <<= 1;
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
index 796afd051c35..9785e4ebb450 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
@@ -25,20 +25,20 @@
#define MAKE_IRQ(intc, off) (AU1000_INTC##intc##_INT_BASE + (off))
/* GPIO1 registers within SYS_ area */
-#define SYS_TRIOUTRD 0x100
-#define SYS_TRIOUTCLR 0x100
-#define SYS_OUTPUTRD 0x108
-#define SYS_OUTPUTSET 0x108
-#define SYS_OUTPUTCLR 0x10C
-#define SYS_PINSTATERD 0x110
-#define SYS_PININPUTEN 0x110
+#define AU1000_SYS_TRIOUTRD 0x100
+#define AU1000_SYS_TRIOUTCLR 0x100
+#define AU1000_SYS_OUTPUTRD 0x108
+#define AU1000_SYS_OUTPUTSET 0x108
+#define AU1000_SYS_OUTPUTCLR 0x10C
+#define AU1000_SYS_PINSTATERD 0x110
+#define AU1000_SYS_PININPUTEN 0x110
/* register offsets within GPIO2 block */
-#define GPIO2_DIR 0x00
-#define GPIO2_OUTPUT 0x08
-#define GPIO2_PINSTATE 0x0C
-#define GPIO2_INTENABLE 0x10
-#define GPIO2_ENABLE 0x14
+#define AU1000_GPIO2_DIR 0x00
+#define AU1000_GPIO2_OUTPUT 0x08
+#define AU1000_GPIO2_PINSTATE 0x0C
+#define AU1000_GPIO2_INTENABLE 0x10
+#define AU1000_GPIO2_ENABLE 0x14
struct gpio;
@@ -217,26 +217,21 @@ static inline int au1200_irq_to_gpio(int irq)
*/
static inline void alchemy_gpio1_set_value(int gpio, int v)
{
- void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
- unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
- __raw_writel(mask, base + r);
- wmb();
+ unsigned long r = v ? AU1000_SYS_OUTPUTSET : AU1000_SYS_OUTPUTCLR;
+ alchemy_wrsys(mask, r);
}
static inline int alchemy_gpio1_get_value(int gpio)
{
- void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
- return __raw_readl(base + SYS_PINSTATERD) & mask;
+ return alchemy_rdsys(AU1000_SYS_PINSTATERD) & mask;
}
static inline int alchemy_gpio1_direction_input(int gpio)
{
- void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
- __raw_writel(mask, base + SYS_TRIOUTCLR);
- wmb();
+ alchemy_wrsys(mask, AU1000_SYS_TRIOUTCLR);
return 0;
}
@@ -279,13 +274,13 @@ static inline void __alchemy_gpio2_mod_dir(int gpio, int to_out)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
- unsigned long d = __raw_readl(base + GPIO2_DIR);
+ unsigned long d = __raw_readl(base + AU1000_GPIO2_DIR);
if (to_out)
d |= mask;
else
d &= ~mask;
- __raw_writel(d, base + GPIO2_DIR);
+ __raw_writel(d, base + AU1000_GPIO2_DIR);
wmb();
}
@@ -294,14 +289,15 @@ static inline void alchemy_gpio2_set_value(int gpio, int v)
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
unsigned long mask;
mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
- __raw_writel(mask, base + GPIO2_OUTPUT);
+ __raw_writel(mask, base + AU1000_GPIO2_OUTPUT);
wmb();
}
static inline int alchemy_gpio2_get_value(int gpio)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
- return __raw_readl(base + GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+ return __raw_readl(base + AU1000_GPIO2_PINSTATE) &
+ (1 << (gpio - ALCHEMY_GPIO2_BASE));
}
static inline int alchemy_gpio2_direction_input(int gpio)
@@ -352,12 +348,12 @@ static inline int alchemy_gpio2_to_irq(int gpio)
static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
- unsigned long r = __raw_readl(base + GPIO2_INTENABLE);
+ unsigned long r = __raw_readl(base + AU1000_GPIO2_INTENABLE);
if (en)
r |= 1 << gpio2;
else
r &= ~(1 << gpio2);
- __raw_writel(r, base + GPIO2_INTENABLE);
+ __raw_writel(r, base + AU1000_GPIO2_INTENABLE);
wmb();
}
@@ -434,9 +430,9 @@ static inline void alchemy_gpio2_disable_int(int gpio2)
static inline void alchemy_gpio2_enable(void)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
- __raw_writel(3, base + GPIO2_ENABLE); /* reset, clock enabled */
+ __raw_writel(3, base + AU1000_GPIO2_ENABLE); /* reset, clock enabled */
wmb();
- __raw_writel(1, base + GPIO2_ENABLE); /* clock enabled */
+ __raw_writel(1, base + AU1000_GPIO2_ENABLE); /* clock enabled */
wmb();
}
@@ -448,7 +444,7 @@ static inline void alchemy_gpio2_enable(void)
static inline void alchemy_gpio2_disable(void)
{
void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
- __raw_writel(2, base + GPIO2_ENABLE); /* reset, clock disabled */
+ __raw_writel(2, base + AU1000_GPIO2_ENABLE); /* reset, clock disabled */
wmb();
}
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
index bba7399a49a3..1f5643b89a91 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -18,6 +18,7 @@ enum bcm47xx_board {
BCM47XX_BOARD_ASUS_WL300G,
BCM47XX_BOARD_ASUS_WL320GE,
BCM47XX_BOARD_ASUS_WL330GE,
+ BCM47XX_BOARD_ASUS_WL500G,
BCM47XX_BOARD_ASUS_WL500GD,
BCM47XX_BOARD_ASUS_WL500GPV1,
BCM47XX_BOARD_ASUS_WL500GPV2,
@@ -70,11 +71,15 @@ enum bcm47xx_board {
BCM47XX_BOARD_LINKSYS_WRT310NV1,
BCM47XX_BOARD_LINKSYS_WRT310NV2,
BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
- BCM47XX_BOARD_LINKSYS_WRT54G,
+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
BCM47XX_BOARD_LINKSYS_WRT610NV1,
BCM47XX_BOARD_LINKSYS_WRT610NV2,
BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+ BCM47XX_BOARD_MICROSOFT_MN700,
+
BCM47XX_BOARD_MOTOROLA_WE800G,
BCM47XX_BOARD_MOTOROLA_WR850GP,
BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
index 3112f08f0c72..56bb19219d48 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -19,118 +19,68 @@
#define BCM6368_CPU_ID 0x6368
void __init bcm63xx_cpu_init(void);
-u16 __bcm63xx_get_cpu_id(void);
u8 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void);
+static inline u16 __pure __bcm63xx_get_cpu_id(const u16 cpu_id)
+{
+ switch (cpu_id) {
#ifdef CONFIG_BCM63XX_CPU_3368
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM3368_CPU_ID
-# endif
-# define BCMCPU_IS_3368() (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
-#else
-# define BCMCPU_IS_3368() (0)
+ case BCM3368_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6328
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6328_CPU_ID
-# endif
-# define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
-#else
-# define BCMCPU_IS_6328() (0)
+ case BCM6328_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6338
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6338_CPU_ID
-# endif
-# define BCMCPU_IS_6338() (bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
-#else
-# define BCMCPU_IS_6338() (0)
+ case BCM6338_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6345
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6345_CPU_ID
-# endif
-# define BCMCPU_IS_6345() (bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
-#else
-# define BCMCPU_IS_6345() (0)
+ case BCM6345_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6348_CPU_ID
-# endif
-# define BCMCPU_IS_6348() (bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
-#else
-# define BCMCPU_IS_6348() (0)
+ case BCM6348_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6358_CPU_ID
-# endif
-# define BCMCPU_IS_6358() (bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
-#else
-# define BCMCPU_IS_6358() (0)
+ case BCM6358_CPU_ID:
#endif
#ifdef CONFIG_BCM63XX_CPU_6362
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6362_CPU_ID
-# endif
-# define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
-#else
-# define BCMCPU_IS_6362() (0)
+ case BCM6362_CPU_ID:
#endif
-
#ifdef CONFIG_BCM63XX_CPU_6368
-# ifdef bcm63xx_get_cpu_id
-# undef bcm63xx_get_cpu_id
-# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
-# define BCMCPU_RUNTIME_DETECT
-# else
-# define bcm63xx_get_cpu_id() BCM6368_CPU_ID
-# endif
-# define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
-#else
-# define BCMCPU_IS_6368() (0)
+ case BCM6368_CPU_ID:
#endif
+ break;
+ default:
+ unreachable();
+ }
-#ifndef bcm63xx_get_cpu_id
-#error "No CPU support configured"
-#endif
+ return cpu_id;
+}
+
+extern u16 bcm63xx_cpu_id;
+
+static inline u16 __pure bcm63xx_get_cpu_id(void)
+{
+ const u16 cpu_id = bcm63xx_cpu_id;
+
+ return __bcm63xx_get_cpu_id(cpu_id);
+}
+
+#define BCMCPU_IS_3368() (bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
+#define BCMCPU_IS_6338() (bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
+#define BCMCPU_IS_6345() (bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
+#define BCMCPU_IS_6348() (bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
+#define BCMCPU_IS_6358() (bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
+#define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
+#define BCMCPU_IS_6368() (bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
/*
* While registers sets are (mostly) the same across 63xx CPU, base
@@ -598,55 +548,6 @@ enum bcm63xx_regs_set {
extern const unsigned long *bcm63xx_regs_base;
-#define __GEN_RSET_BASE(__cpu, __rset) \
- case RSET_## __rset : \
- return BCM_## __cpu ##_## __rset ##_BASE;
-
-#define __GEN_RSET(__cpu) \
- switch (set) { \
- __GEN_RSET_BASE(__cpu, DSL_LMEM) \
- __GEN_RSET_BASE(__cpu, PERF) \
- __GEN_RSET_BASE(__cpu, TIMER) \
- __GEN_RSET_BASE(__cpu, WDT) \
- __GEN_RSET_BASE(__cpu, UART0) \
- __GEN_RSET_BASE(__cpu, UART1) \
- __GEN_RSET_BASE(__cpu, GPIO) \
- __GEN_RSET_BASE(__cpu, SPI) \
- __GEN_RSET_BASE(__cpu, HSSPI) \
- __GEN_RSET_BASE(__cpu, UDC0) \
- __GEN_RSET_BASE(__cpu, OHCI0) \
- __GEN_RSET_BASE(__cpu, OHCI_PRIV) \
- __GEN_RSET_BASE(__cpu, USBH_PRIV) \
- __GEN_RSET_BASE(__cpu, USBD) \
- __GEN_RSET_BASE(__cpu, USBDMA) \
- __GEN_RSET_BASE(__cpu, MPI) \
- __GEN_RSET_BASE(__cpu, PCMCIA) \
- __GEN_RSET_BASE(__cpu, PCIE) \
- __GEN_RSET_BASE(__cpu, DSL) \
- __GEN_RSET_BASE(__cpu, ENET0) \
- __GEN_RSET_BASE(__cpu, ENET1) \
- __GEN_RSET_BASE(__cpu, ENETDMA) \
- __GEN_RSET_BASE(__cpu, ENETDMAC) \
- __GEN_RSET_BASE(__cpu, ENETDMAS) \
- __GEN_RSET_BASE(__cpu, ENETSW) \
- __GEN_RSET_BASE(__cpu, EHCI0) \
- __GEN_RSET_BASE(__cpu, SDRAM) \
- __GEN_RSET_BASE(__cpu, MEMC) \
- __GEN_RSET_BASE(__cpu, DDR) \
- __GEN_RSET_BASE(__cpu, M2M) \
- __GEN_RSET_BASE(__cpu, ATM) \
- __GEN_RSET_BASE(__cpu, XTM) \
- __GEN_RSET_BASE(__cpu, XTMDMA) \
- __GEN_RSET_BASE(__cpu, XTMDMAC) \
- __GEN_RSET_BASE(__cpu, XTMDMAS) \
- __GEN_RSET_BASE(__cpu, PCM) \
- __GEN_RSET_BASE(__cpu, PCMDMA) \
- __GEN_RSET_BASE(__cpu, PCMDMAC) \
- __GEN_RSET_BASE(__cpu, PCMDMAS) \
- __GEN_RSET_BASE(__cpu, RNG) \
- __GEN_RSET_BASE(__cpu, MISC) \
- }
-
#define __GEN_CPU_REGS_TABLE(__cpu) \
[RSET_DSL_LMEM] = BCM_## __cpu ##_DSL_LMEM_BASE, \
[RSET_PERF] = BCM_## __cpu ##_PERF_BASE, \
@@ -693,36 +594,7 @@ extern const unsigned long *bcm63xx_regs_base;
static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
{
-#ifdef BCMCPU_RUNTIME_DETECT
return bcm63xx_regs_base[set];
-#else
-#ifdef CONFIG_BCM63XX_CPU_3368
- __GEN_RSET(3368)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
- __GEN_RSET(6328)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
- __GEN_RSET(6338)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
- __GEN_RSET(6345)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
- __GEN_RSET(6348)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
- __GEN_RSET(6358)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
- __GEN_RSET(6362)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
- __GEN_RSET(6368)
-#endif
-#endif
- /* unreached */
- return 0;
}
/*
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
index 753953e86242..466fc85899f4 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
@@ -112,55 +112,9 @@ enum bcm63xx_regs_enetdmac {
static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg)
{
-#ifdef BCMCPU_RUNTIME_DETECT
extern const unsigned long *bcm63xx_regs_enetdmac;
return bcm63xx_regs_enetdmac[reg];
-#else
-#ifdef CONFIG_BCM63XX_CPU_6345
- switch (reg) {
- case ENETDMAC_CHANCFG:
- return ENETDMA_6345_CHANCFG_REG;
- case ENETDMAC_IR:
- return ENETDMA_6345_IR_REG;
- case ENETDMAC_IRMASK:
- return ENETDMA_6345_IRMASK_REG;
- case ENETDMAC_MAXBURST:
- return ENETDMA_6345_MAXBURST_REG;
- case ENETDMAC_BUFALLOC:
- return ENETDMA_6345_BUFALLOC_REG;
- case ENETDMAC_RSTART:
- return ENETDMA_6345_RSTART_REG;
- case ENETDMAC_FC:
- return ENETDMA_6345_FC_REG;
- case ENETDMAC_LEN:
- return ENETDMA_6345_LEN_REG;
- }
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6328) || \
- defined(CONFIG_BCM63XX_CPU_6338) || \
- defined(CONFIG_BCM63XX_CPU_6348) || \
- defined(CONFIG_BCM63XX_CPU_6358) || \
- defined(CONFIG_BCM63XX_CPU_6362) || \
- defined(CONFIG_BCM63XX_CPU_6368)
- switch (reg) {
- case ENETDMAC_CHANCFG:
- return ENETDMAC_CHANCFG_REG;
- case ENETDMAC_IR:
- return ENETDMAC_IR_REG;
- case ENETDMAC_IRMASK:
- return ENETDMAC_IRMASK_REG;
- case ENETDMAC_MAXBURST:
- return ENETDMAC_MAXBURST_REG;
- case ENETDMAC_BUFALLOC:
- case ENETDMAC_RSTART:
- case ENETDMAC_FC:
- case ENETDMAC_LEN:
- return 0;
- }
-#endif
-#endif
- return 0;
}
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
index c426cabc620a..25737655d141 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
@@ -30,26 +30,6 @@ enum bcm63xx_regs_spi {
SPI_RX_DATA,
};
-#define __GEN_SPI_RSET_BASE(__cpu, __rset) \
- case SPI_## __rset: \
- return SPI_## __cpu ##_## __rset;
-
-#define __GEN_SPI_RSET(__cpu) \
- switch (reg) { \
- __GEN_SPI_RSET_BASE(__cpu, CMD) \
- __GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \
- __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \
- __GEN_SPI_RSET_BASE(__cpu, INT_MASK) \
- __GEN_SPI_RSET_BASE(__cpu, ST) \
- __GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \
- __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \
- __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \
- __GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \
- __GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \
- __GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \
- __GEN_SPI_RSET_BASE(__cpu, RX_DATA) \
- }
-
#define __GEN_SPI_REGS_TABLE(__cpu) \
[SPI_CMD] = SPI_## __cpu ##_CMD, \
[SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \
@@ -66,20 +46,9 @@ enum bcm63xx_regs_spi {
static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
{
-#ifdef BCMCPU_RUNTIME_DETECT
extern const unsigned long *bcm63xx_regs_spi;
return bcm63xx_regs_spi[reg];
-#else
-#if defined(CONFIG_BCM63XX_CPU_6338) || defined(CONFIG_BCM63XX_CPU_6348)
- __GEN_SPI_RSET(6348)
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6358) || defined(CONFIG_BCM63XX_CPU_6362) || \
- defined(CONFIG_BCM63XX_CPU_6368)
- __GEN_SPI_RSET(6358)
-#endif
-#endif
- return 0;
}
#endif /* BCM63XX_DEV_SPI_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index ab427f8814e6..4794067cb5a7 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -215,23 +215,23 @@
/* Interrupt Mask register */
#define PERF_IRQMASK_3368_REG 0xc
-#define PERF_IRQMASK_6328_REG 0x20
+#define PERF_IRQMASK_6328_REG(x) (0x20 + (x) * 0x10)
#define PERF_IRQMASK_6338_REG 0xc
#define PERF_IRQMASK_6345_REG 0xc
#define PERF_IRQMASK_6348_REG 0xc
-#define PERF_IRQMASK_6358_REG 0xc
-#define PERF_IRQMASK_6362_REG 0x20
-#define PERF_IRQMASK_6368_REG 0x20
+#define PERF_IRQMASK_6358_REG(x) (0xc + (x) * 0x2c)
+#define PERF_IRQMASK_6362_REG(x) (0x20 + (x) * 0x10)
+#define PERF_IRQMASK_6368_REG(x) (0x20 + (x) * 0x10)
/* Interrupt Status register */
#define PERF_IRQSTAT_3368_REG 0x10
-#define PERF_IRQSTAT_6328_REG 0x28
+#define PERF_IRQSTAT_6328_REG(x) (0x28 + (x) * 0x10)
#define PERF_IRQSTAT_6338_REG 0x10
#define PERF_IRQSTAT_6345_REG 0x10
#define PERF_IRQSTAT_6348_REG 0x10
-#define PERF_IRQSTAT_6358_REG 0x10
-#define PERF_IRQSTAT_6362_REG 0x28
-#define PERF_IRQSTAT_6368_REG 0x28
+#define PERF_IRQSTAT_6358_REG(x) (0x10 + (x) * 0x2c)
+#define PERF_IRQSTAT_6362_REG(x) (0x28 + (x) * 0x10)
+#define PERF_IRQSTAT_6368_REG(x) (0x28 + (x) * 0x10)
/* External Interrupt Configuration register */
#define PERF_EXTIRQ_CFG_REG_3368 0x14
diff --git a/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
index e9c408e8ff4c..bc1167dbd4e3 100644
--- a/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
@@ -24,7 +24,7 @@
#define cpu_has_smartmips 0
#define cpu_has_vtag_icache 0
-#if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCM63XX_CPU_6348) || defined(CONFIG_BCM63XX_CPU_6345) || defined(CONFIG_BCM63XX_CPU_6338))
+#if !defined(CONFIG_SYS_HAS_CPU_BMIPS4350)
#define cpu_has_dc_aliases 0
#endif
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 829a7ec185fb..3388fc53599e 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -146,6 +146,9 @@ struct boot_params {
struct loongson_system_configuration {
u32 nr_cpus;
+ u32 nr_nodes;
+ int cores_per_node;
+ int cores_per_package;
enum loongson_cpu_type cputype;
u64 ht_control_base;
u64 pci_mem_start_addr;
@@ -160,4 +163,5 @@ struct loongson_system_configuration {
extern struct efi_memory_map_loongson *loongson_memmap;
extern struct loongson_system_configuration loongson_sysconf;
+extern int cpuhotplug_workaround;
#endif
diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
new file mode 100644
index 000000000000..df5fca8eeb80
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
+ */
+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+
+/*
+ * Override macros used in arch/mips/kernel/head.S.
+ */
+ .macro kernel_entry_setup
+#ifdef CONFIG_CPU_LOONGSON3
+ .set push
+ .set mips64
+ /* Set LPA on LOONGSON3 config3 */
+ mfc0 t0, $16, 3
+ or t0, (0x1 << 7)
+ mtc0 t0, $16, 3
+ /* Set ELPA on LOONGSON3 pagegrain */
+ li t0, (0x1 << 29)
+ mtc0 t0, $5, 1
+ _ehb
+ .set pop
+#endif
+ .endm
+
+/*
+ * Do SMP slave processor setup.
+ */
+ .macro smp_slave_setup
+#ifdef CONFIG_CPU_LOONGSON3
+ .set push
+ .set mips64
+ /* Set LPA on LOONGSON3 config3 */
+ mfc0 t0, $16, 3
+ or t0, (0x1 << 7)
+ mtc0 t0, $16, 3
+ /* Set ELPA on LOONGSON3 pagegrain */
+ li t0, (0x1 << 29)
+ mtc0 t0, $5, 1
+ _ehb
+ .set pop
+#endif
+ .endm
+
+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index f3fd1eb8e3dd..92bf76c21441 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -249,8 +249,15 @@ static inline void do_perfcnt_IRQ(void)
#define LOONGSON_PXARB_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x68)
#define LOONGSON_PXARB_STATUS LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
-/* Chip Config */
-#define LOONGSON_CHIPCFG0 LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#define MAX_PACKAGES 4
+
+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
+extern u64 loongson_chipcfg[MAX_PACKAGES];
+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
+
+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
+extern u64 loongson_freqctrl[MAX_PACKAGES];
+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
/* pcimap */
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 1b1f592fa2be..228e37847a36 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -24,10 +24,10 @@
#endif
-#ifdef CONFIG_LEMOTE_MACH3A
+#ifdef CONFIG_LOONGSON_MACH3X
#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
-#endif /* CONFIG_LEMOTE_MACH3A */
+#endif /* CONFIG_LOONGSON_MACH3X */
#endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h
new file mode 100644
index 000000000000..37c08a27b4f0
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/mmzone.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ * Insititute of Computing Technology
+ * Author: Xiang Gao, gaoxiang@ict.ac.cn
+ * Huacai Chen, chenhc@lemote.com
+ * Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_MACH_MMZONE_H
+#define _ASM_MACH_MMZONE_H
+
+#include <boot_param.h>
+#define NODE_ADDRSPACE_SHIFT 44
+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
+
+#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
+
+#define LEVELS_PER_SLICE 128
+
+struct slice_data {
+ unsigned long irq_enable_mask[2];
+ int level_to_irq[LEVELS_PER_SLICE];
+};
+
+struct hub_data {
+ cpumask_t h_cpus;
+ unsigned long slice_map;
+ unsigned long irq_alloc_mask[2];
+ struct slice_data slice[2];
+};
+
+struct node_data {
+ struct pglist_data pglist;
+ struct hub_data hub;
+ cpumask_t cpumask;
+};
+
+extern struct node_data *__node_data[];
+
+#define NODE_DATA(n) (&__node_data[(n)]->pglist)
+#define hub_data(n) (&__node_data[(n)]->hub)
+
+extern void setup_zero_pages(void);
+extern void __init prom_init_numa_memory(void);
+
+#endif /* _ASM_MACH_MMZONE_H */
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
new file mode 100644
index 000000000000..5598ba77d2ef
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/topology.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_MACH_TOPOLOGY_H
+#define _ASM_MACH_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#define cpu_to_node(cpu) ((cpu) >> 2)
+#define parent_node(node) (node)
+#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)
+
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *);
+
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
+
+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+
+#define node_distance(from, to) (__node_distances[(from)][(to)])
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_MACH_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h
index 47cfe64efbb0..f2c13d211abb 100644
--- a/arch/mips/include/asm/mach-malta/irq.h
+++ b/arch/mips/include/asm/mach-malta/irq.h
@@ -2,6 +2,7 @@
#define __ASM_MACH_MIPS_IRQ_H
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
#define NR_IRQS 256
#include_next <irq.h>
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h
index 5d154cfbcf4c..d8106f75b9af 100644
--- a/arch/mips/include/asm/mach-sead3/irq.h
+++ b/arch/mips/include/asm/mach-sead3/irq.h
@@ -1,6 +1,7 @@
#ifndef __ASM_MACH_MIPS_IRQ_H
#define __ASM_MACH_MIPS_IRQ_H
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
#define NR_IRQS 256
diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h
index b2048d1bcc1c..5368891d424b 100644
--- a/arch/mips/include/asm/mips-boards/bonito64.h
+++ b/arch/mips/include/asm/mips-boards/bonito64.h
@@ -414,7 +414,6 @@ extern unsigned long _pcictrl_bonito_pcicfg;
#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
-#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
#define BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
#define BONITO_PCITOPHYS(WIN, ADDR, CFG) ( \
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 98e9754a4b6b..cf3b580c3df6 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -265,6 +265,7 @@
#define PG_XIE (_ULCAST_(1) << 30)
#define PG_ELPA (_ULCAST_(1) << 29)
#define PG_ESP (_ULCAST_(1) << 28)
+#define PG_IEC (_ULCAST_(1) << 27)
/*
* R4x00 interrupt enable / cause bits
@@ -630,7 +631,6 @@
#define MIPS_CONF4_MMUSIZEEXT_SHIFT (0)
#define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0)
#define MIPS_CONF4_FTLBSETS_SHIFT (0)
-#define MIPS_CONF4_FTLBSETS_SHIFT (0)
#define MIPS_CONF4_FTLBSETS (_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT)
#define MIPS_CONF4_FTLBWAYS_SHIFT (4)
#define MIPS_CONF4_FTLBWAYS (_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT)
@@ -652,6 +652,7 @@
#define MIPS_CONF5_NF (_ULCAST_(1) << 0)
#define MIPS_CONF5_UFR (_ULCAST_(1) << 2)
+#define MIPS_CONF5_MRP (_ULCAST_(1) << 3)
#define MIPS_CONF5_MSAEN (_ULCAST_(1) << 27)
#define MIPS_CONF5_EVA (_ULCAST_(1) << 28)
#define MIPS_CONF5_CV (_ULCAST_(1) << 29)
@@ -668,6 +669,12 @@
#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
+/* MAAR bit definitions */
+#define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
+#define MIPS_MAAR_ADDR_SHIFT 12
+#define MIPS_MAAR_S (_ULCAST_(1) << 1)
+#define MIPS_MAAR_V (_ULCAST_(1) << 0)
+
/* EntryHI bit definition */
#define MIPS_ENTRYHI_EHINV (_ULCAST_(1) << 10)
@@ -706,6 +713,37 @@
#define MIPS_SEGCFG_MK _ULCAST_(1)
#define MIPS_SEGCFG_UK _ULCAST_(0)
+#define MIPS_PWFIELD_GDI_SHIFT 24
+#define MIPS_PWFIELD_GDI_MASK 0x3f000000
+#define MIPS_PWFIELD_UDI_SHIFT 18
+#define MIPS_PWFIELD_UDI_MASK 0x00fc0000
+#define MIPS_PWFIELD_MDI_SHIFT 12
+#define MIPS_PWFIELD_MDI_MASK 0x0003f000
+#define MIPS_PWFIELD_PTI_SHIFT 6
+#define MIPS_PWFIELD_PTI_MASK 0x00000fc0
+#define MIPS_PWFIELD_PTEI_SHIFT 0
+#define MIPS_PWFIELD_PTEI_MASK 0x0000003f
+
+#define MIPS_PWSIZE_GDW_SHIFT 24
+#define MIPS_PWSIZE_GDW_MASK 0x3f000000
+#define MIPS_PWSIZE_UDW_SHIFT 18
+#define MIPS_PWSIZE_UDW_MASK 0x00fc0000
+#define MIPS_PWSIZE_MDW_SHIFT 12
+#define MIPS_PWSIZE_MDW_MASK 0x0003f000
+#define MIPS_PWSIZE_PTW_SHIFT 6
+#define MIPS_PWSIZE_PTW_MASK 0x00000fc0
+#define MIPS_PWSIZE_PTEW_SHIFT 0
+#define MIPS_PWSIZE_PTEW_MASK 0x0000003f
+
+#define MIPS_PWCTL_PWEN_SHIFT 31
+#define MIPS_PWCTL_PWEN_MASK 0x80000000
+#define MIPS_PWCTL_DPH_SHIFT 7
+#define MIPS_PWCTL_DPH_MASK 0x00000080
+#define MIPS_PWCTL_HUGEPG_SHIFT 6
+#define MIPS_PWCTL_HUGEPG_MASK 0x00000060
+#define MIPS_PWCTL_PSN_SHIFT 0
+#define MIPS_PWCTL_PSN_MASK 0x0000003f
+
#ifndef __ASSEMBLY__
/*
@@ -1044,6 +1082,11 @@ do { \
#define write_c0_config6(val) __write_32bit_c0_register($16, 6, val)
#define write_c0_config7(val) __write_32bit_c0_register($16, 7, val)
+#define read_c0_maar() __read_ulong_c0_register($17, 1)
+#define write_c0_maar(val) __write_ulong_c0_register($17, 1, val)
+#define read_c0_maari() __read_32bit_c0_register($17, 2)
+#define write_c0_maari(val) __write_32bit_c0_register($17, 2, val)
+
/*
* The WatchLo register. There may be up to 8 of them.
*/
@@ -1201,6 +1244,19 @@ do { \
#define read_c0_segctl2() __read_32bit_c0_register($5, 4)
#define write_c0_segctl2(val) __write_32bit_c0_register($5, 4, val)
+/* Hardware Page Table Walker */
+#define read_c0_pwbase() __read_ulong_c0_register($5, 5)
+#define write_c0_pwbase(val) __write_ulong_c0_register($5, 5, val)
+
+#define read_c0_pwfield() __read_ulong_c0_register($5, 6)
+#define write_c0_pwfield(val) __write_ulong_c0_register($5, 6, val)
+
+#define read_c0_pwsize() __read_ulong_c0_register($5, 7)
+#define write_c0_pwsize(val) __write_ulong_c0_register($5, 7, val)
+
+#define read_c0_pwctl() __read_32bit_c0_register($6, 6)
+#define write_c0_pwctl(val) __write_32bit_c0_register($6, 6, val)
+
/* Cavium OCTEON (cnMIPS) */
#define read_c0_cvmcount() __read_ulong_c0_register($9, 6)
#define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val)
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 2e373da5f8e9..2f82568a3ee4 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -20,10 +20,20 @@
#include <asm/tlbflush.h>
#include <asm-generic/mm_hooks.h>
+#define htw_set_pwbase(pgd) \
+do { \
+ if (cpu_has_htw) { \
+ write_c0_pwbase(pgd); \
+ back_to_back_c0_hazard(); \
+ htw_reset(); \
+ } \
+} while (0)
+
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
do { \
extern void tlbmiss_handler_setup_pgd(unsigned long); \
tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \
+ htw_set_pwbase((unsigned long)pgd); \
} while (0)
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index 538f6d482db8..af5638b12c75 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -12,8 +12,11 @@
#include <asm/mipsregs.h>
+#ifndef __ASSEMBLY__
+
extern void _save_msa(struct task_struct *);
extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
static inline void enable_msa(void)
{
@@ -112,10 +115,10 @@ static inline unsigned int read_msa_##name(void) \
" .set push\n" \
" .set noat\n" \
" .insn\n" \
- " .word #CFC_MSA_INSN | (" #cs " << 11)\n" \
+ " .word %1 | (" #cs " << 11)\n" \
" move %0, $1\n" \
" .set pop\n" \
- : "=r"(reg)); \
+ : "=r"(reg) : "i"(CFC_MSA_INSN)); \
return reg; \
} \
\
@@ -126,22 +129,13 @@ static inline void write_msa_##name(unsigned int val) \
" .set noat\n" \
" move $1, %0\n" \
" .insn\n" \
- " .word #CTC_MSA_INSN | (" #cs " << 6)\n" \
+ " .word %1 | (" #cs " << 6)\n" \
" .set pop\n" \
- : : "r"(val)); \
+ : : "r"(val), "i"(CTC_MSA_INSN)); \
}
#endif /* !TOOLCHAIN_SUPPORTS_MSA */
-#define MSA_IR 0
-#define MSA_CSR 1
-#define MSA_ACCESS 2
-#define MSA_SAVE 3
-#define MSA_MODIFY 4
-#define MSA_REQUEST 5
-#define MSA_MAP 6
-#define MSA_UNMAP 7
-
__BUILD_MSA_CTL_REG(ir, 0)
__BUILD_MSA_CTL_REG(csr, 1)
__BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +145,17 @@ __BUILD_MSA_CTL_REG(request, 5)
__BUILD_MSA_CTL_REG(map, 6)
__BUILD_MSA_CTL_REG(unmap, 7)
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR 0
+#define MSA_CSR 1
+#define MSA_ACCESS 2
+#define MSA_SAVE 3
+#define MSA_MODIFY 4
+#define MSA_REQUEST 5
+#define MSA_MAP 6
+#define MSA_UNMAP 7
+
/* MSA Implementation Register (MSAIR) */
#define MSA_IR_REVB 0
#define MSA_IR_REVF (_ULCAST_(0xff) << MSA_IR_REVB)
diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
index 7b7818d1e4d5..2298199a287e 100644
--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h
+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
@@ -228,6 +228,7 @@ enum cvmx_board_types_enum {
*/
CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
CVMX_BOARD_TYPE_UBNT_E100 = 20002,
+ CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
/* The remaining range is reserved for future use. */
@@ -327,6 +328,7 @@ static inline const char *cvmx_board_type_to_string(enum
/* Customer private range */
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
}
return "Unsupported Board";
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
index b4204c179b97..cd7d6064bcbe 100644
--- a/arch/mips/include/asm/pgtable-32.h
+++ b/arch/mips/include/asm/pgtable-32.h
@@ -18,6 +18,18 @@
#include <asm-generic/pgtable-nopmd.h>
+extern int temp_tlb_entry __cpuinitdata;
+
+/*
+ * - add_temporary_entry() add a temporary TLB entry. We use TLB entries
+ * starting at the top and working down. This is for populating the
+ * TLB before trap_init() puts the TLB miss handler in place. It
+ * should be used only for entries matching the actual page tables,
+ * to prevent inconsistencies.
+ */
+extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask);
+
/*
* Basically we have the same two-level (which is the logical three level
* Linux page table layout folded) page tables as the i386. Some day
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 539ddd148bbb..027c74db13f9 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -97,6 +97,31 @@ extern void paging_init(void);
#define pmd_page_vaddr(pmd) pmd_val(pmd)
+#define htw_stop() \
+do { \
+ if (cpu_has_htw) \
+ write_c0_pwctl(read_c0_pwctl() & \
+ ~(1 << MIPS_PWCTL_PWEN_SHIFT)); \
+} while(0)
+
+#define htw_start() \
+do { \
+ if (cpu_has_htw) \
+ write_c0_pwctl(read_c0_pwctl() | \
+ (1 << MIPS_PWCTL_PWEN_SHIFT)); \
+} while(0)
+
+
+#define htw_reset() \
+do { \
+ if (cpu_has_htw) { \
+ htw_stop(); \
+ back_to_back_c0_hazard(); \
+ htw_start(); \
+ back_to_back_c0_hazard(); \
+ } \
+} while(0)
+
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
#define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
@@ -131,6 +156,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
null.pte_low = null.pte_high = _PAGE_GLOBAL;
set_pte_at(mm, addr, ptep, null);
+ htw_reset();
}
#else
@@ -168,6 +194,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
else
#endif
set_pte_at(mm, addr, ptep, __pte(0));
+ htw_reset();
}
#endif
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index ad70cba8daff..05f08438a7c4 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -238,7 +238,13 @@ typedef struct {
unsigned long seg;
} mm_segment_t;
-#define ARCH_MIN_TASKALIGN 8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN 16
+# define FPU_ALIGN __aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN 8
+# define FPU_ALIGN
+#endif
struct mips_abi;
@@ -255,7 +261,7 @@ struct thread_struct {
unsigned long cp0_status;
/* Saved fpu/fpu emulator stuff. */
- struct mips_fpu_struct fpu;
+ struct mips_fpu_struct fpu FPU_ALIGN;
#ifdef CONFIG_MIPS_MT_FPAFF
/* Emulated instruction count */
unsigned long emulated_fp;
@@ -367,6 +373,7 @@ unsigned long get_wchan(struct task_struct *p);
#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
/*
* Return_address is a replacement for __builtin_return_address(count)
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 7e6e682aece3..fc783f843bdc 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -23,7 +23,7 @@
struct pt_regs {
#ifdef CONFIG_32BIT
/* Pad bytes for argument save space on the stack. */
- unsigned long pad0[6];
+ unsigned long pad0[8];
#endif
/* Saved main processor registers. */
@@ -47,8 +47,10 @@ struct pt_regs {
struct task_struct;
-extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
-extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
+extern int ptrace_getregs(struct task_struct *child,
+ struct user_pt_regs __user *data);
+extern int ptrace_setregs(struct task_struct *child,
+ struct user_pt_regs __user *data);
extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 0b8bd28a0df1..4520adc8699b 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -19,6 +19,9 @@
#include <asm/mipsmtregs.h>
#include <asm/uaccess.h> /* for segment_eq() */
+extern void (*r4k_blast_dcache)(void);
+extern void (*r4k_blast_icache)(void);
+
/*
* This macro return a properly sign-extended address suitable as base address
* for indexed cache operations. Two issues here:
diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index 910e71a12466..84dc7e2e27a8 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -1,128 +1 @@
-/*
- * Various register offset definitions for debuggers, core file
- * examiners and whatnot.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1999 Ralf Baechle
- * Copyright (C) 1995, 1999 Silicon Graphics
- */
-#ifndef __ASM_MIPS_REG_H
-#define __ASM_MIPS_REG_H
-
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0 6
-#define EF_R1 7
-#define EF_R2 8
-#define EF_R3 9
-#define EF_R4 10
-#define EF_R5 11
-#define EF_R6 12
-#define EF_R7 13
-#define EF_R8 14
-#define EF_R9 15
-#define EF_R10 16
-#define EF_R11 17
-#define EF_R12 18
-#define EF_R13 19
-#define EF_R14 20
-#define EF_R15 21
-#define EF_R16 22
-#define EF_R17 23
-#define EF_R18 24
-#define EF_R19 25
-#define EF_R20 26
-#define EF_R21 27
-#define EF_R22 28
-#define EF_R23 29
-#define EF_R24 30
-#define EF_R25 31
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26 32
-#define EF_R27 33
-
-#define EF_R28 34
-#define EF_R29 35
-#define EF_R30 36
-#define EF_R31 37
-
-/*
- * Saved special registers
- */
-#define EF_LO 38
-#define EF_HI 39
-
-#define EF_CP0_EPC 40
-#define EF_CP0_BADVADDR 41
-#define EF_CP0_STATUS 42
-#define EF_CP0_CAUSE 43
-#define EF_UNUSED0 44
-
-#define EF_SIZE 180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0 0
-#define EF_R1 1
-#define EF_R2 2
-#define EF_R3 3
-#define EF_R4 4
-#define EF_R5 5
-#define EF_R6 6
-#define EF_R7 7
-#define EF_R8 8
-#define EF_R9 9
-#define EF_R10 10
-#define EF_R11 11
-#define EF_R12 12
-#define EF_R13 13
-#define EF_R14 14
-#define EF_R15 15
-#define EF_R16 16
-#define EF_R17 17
-#define EF_R18 18
-#define EF_R19 19
-#define EF_R20 20
-#define EF_R21 21
-#define EF_R22 22
-#define EF_R23 23
-#define EF_R24 24
-#define EF_R25 25
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26 26
-#define EF_R27 27
-
-
-#define EF_R28 28
-#define EF_R29 29
-#define EF_R30 30
-#define EF_R31 31
-
-/*
- * Saved special registers
- */
-#define EF_LO 32
-#define EF_HI 33
-
-#define EF_CP0_EPC 34
-#define EF_CP0_BADVADDR 35
-#define EF_CP0_STATUS 36
-#define EF_CP0_CAUSE 37
-
-#define EF_SIZE 304 /* size in bytes */
-
-#endif /* CONFIG_64BIT */
-
-#endif /* __ASM_MIPS_REG_H */
+#include <uapi/asm/reg.h>
diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h
index a06a08a9afc6..326c16ebd589 100644
--- a/arch/mips/include/asm/smp-cps.h
+++ b/arch/mips/include/asm/smp-cps.h
@@ -31,11 +31,19 @@ extern void mips_cps_core_init(void);
extern struct vpe_boot_config *mips_cps_boot_vpes(void);
-extern bool mips_cps_smp_in_use(void);
-
extern void mips_cps_pm_save(void);
extern void mips_cps_pm_restore(void);
+#ifdef CONFIG_MIPS_CPS
+
+extern bool mips_cps_smp_in_use(void);
+
+#else /* !CONFIG_MIPS_CPS */
+
+static inline bool mips_cps_smp_in_use(void) { return false; }
+
+#endif /* !CONFIG_MIPS_CPS */
+
#else /* __ASSEMBLY__ */
.extern mips_cps_bootcfg;
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index b037334fca22..1e0f20a9cdda 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -22,6 +22,7 @@
extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
+extern cpumask_t cpu_core_map[];
#define raw_smp_processor_id() (current_thread_info()->cpu)
@@ -36,6 +37,11 @@ extern int __cpu_logical_map[NR_CPUS];
#define NO_PROC_ID (-1)
+#define topology_physical_package_id(cpu) (cpu_data[cpu].package)
+#define topology_core_id(cpu) (cpu_data[cpu].core)
+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu])
+
#define SMP_RESCHEDULE_YOURSELF 0x1 /* XXX braindead */
#define SMP_CALL_FUNCTION 0x2
/* Octeon - Tell another core to flush its icache */
diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
index d2da53c2c2f8..b1071c1e54f5 100644
--- a/arch/mips/include/asm/sparsemem.h
+++ b/arch/mips/include/asm/sparsemem.h
@@ -11,7 +11,7 @@
#else
# define SECTION_SIZE_BITS 28
#endif
-#define MAX_PHYSMEM_BITS 35
+#define MAX_PHYSMEM_BITS 48
#endif /* CONFIG_SPARSEMEM */
#endif /* _MIPS_SPARSEMEM_H */
diff --git a/arch/mips/include/asm/user.h b/arch/mips/include/asm/user.h
deleted file mode 100644
index 6bad61b0a53a..000000000000
--- a/arch/mips/include/asm/user.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
- */
-#ifndef _ASM_USER_H
-#define _ASM_USER_H
-
-#include <asm/page.h>
-#include <asm/reg.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the irix-core). The file
- * contents are as follows:
- *
- * upage: 1 page consisting of a user struct that tells gdb
- * what is present in the file. Directly after this is a
- * copy of the task_struct, which is currently not used by gdb,
- * but it may come in handy at some point. All of the registers
- * are stored as part of the upage. The upage should always be
- * only one page long.
- * data: The data segment follows next. We use current->end_text to
- * current->brk to pick up all of the user variables, plus any memory
- * that may have been sbrk'ed. No attempt is made to determine if a
- * page is demand-zero or if a page is totally unused, we just cover
- * the entire range. All of the addresses are rounded in such a way
- * that an integral number of pages is written.
- * stack: We need the stack information in order to get a meaningful
- * backtrace. We need to write the data from usp to
- * current->start_stack, so we round each of these in order to be able
- * to write an integer number of pages.
- */
-struct user {
- unsigned long regs[EF_SIZE / /* integer and fp regs */
- sizeof(unsigned long) + 64];
- size_t u_tsize; /* text size (pages) */
- size_t u_dsize; /* data size (pages) */
- size_t u_ssize; /* stack size (pages) */
- unsigned long start_code; /* text starting address */
- unsigned long start_data; /* data starting address */
- unsigned long start_stack; /* stack starting address */
- long int signal; /* signal causing core dump */
- unsigned long u_ar0; /* help gdb find registers */
- unsigned long magic; /* identifies a core file */
- char u_comm[32]; /* user command name */
-};
-
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_DATA_START_ADDR (u.start_data)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _ASM_USER_H */
diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
index b26f7e317279..bbcfb8ba8106 100644
--- a/arch/mips/include/uapi/asm/ptrace.h
+++ b/arch/mips/include/uapi/asm/ptrace.h
@@ -22,24 +22,27 @@
#define DSP_CONTROL 77
#define ACX 78
-#ifndef __KERNEL__
/*
- * This struct defines the way the registers are stored on the stack during a
- * system call/exception. As usual the registers k0/k1 aren't being saved.
+ * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
+ * format is the same for both 32- and 64-bit processes. Registers for 32-bit
+ * processes are sign extended.
*/
+#ifdef __KERNEL__
+struct user_pt_regs {
+#else
struct pt_regs {
+#endif
/* Saved main processor registers. */
- unsigned long regs[32];
+ __u64 regs[32];
/* Saved special registers. */
- unsigned long cp0_status;
- unsigned long hi;
- unsigned long lo;
- unsigned long cp0_badvaddr;
- unsigned long cp0_cause;
- unsigned long cp0_epc;
+ __u64 lo;
+ __u64 hi;
+ __u64 cp0_epc;
+ __u64 cp0_badvaddr;
+ __u64 cp0_status;
+ __u64 cp0_cause;
} __attribute__ ((aligned (8)));
-#endif /* __KERNEL__ */
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
#define PTRACE_GETREGS 12
diff --git a/arch/mips/include/uapi/asm/reg.h b/arch/mips/include/uapi/asm/reg.h
new file mode 100644
index 000000000000..081e377f4f02
--- /dev/null
+++ b/arch/mips/include/uapi/asm/reg.h
@@ -0,0 +1,206 @@
+/*
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999 Silicon Graphics
+ */
+#ifndef __UAPI_ASM_MIPS_REG_H
+#define __UAPI_ASM_MIPS_REG_H
+
+#define MIPS32_EF_R0 6
+#define MIPS32_EF_R1 7
+#define MIPS32_EF_R2 8
+#define MIPS32_EF_R3 9
+#define MIPS32_EF_R4 10
+#define MIPS32_EF_R5 11
+#define MIPS32_EF_R6 12
+#define MIPS32_EF_R7 13
+#define MIPS32_EF_R8 14
+#define MIPS32_EF_R9 15
+#define MIPS32_EF_R10 16
+#define MIPS32_EF_R11 17
+#define MIPS32_EF_R12 18
+#define MIPS32_EF_R13 19
+#define MIPS32_EF_R14 20
+#define MIPS32_EF_R15 21
+#define MIPS32_EF_R16 22
+#define MIPS32_EF_R17 23
+#define MIPS32_EF_R18 24
+#define MIPS32_EF_R19 25
+#define MIPS32_EF_R20 26
+#define MIPS32_EF_R21 27
+#define MIPS32_EF_R22 28
+#define MIPS32_EF_R23 29
+#define MIPS32_EF_R24 30
+#define MIPS32_EF_R25 31
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS32_EF_R26 32
+#define MIPS32_EF_R27 33
+
+#define MIPS32_EF_R28 34
+#define MIPS32_EF_R29 35
+#define MIPS32_EF_R30 36
+#define MIPS32_EF_R31 37
+
+/*
+ * Saved special registers
+ */
+#define MIPS32_EF_LO 38
+#define MIPS32_EF_HI 39
+
+#define MIPS32_EF_CP0_EPC 40
+#define MIPS32_EF_CP0_BADVADDR 41
+#define MIPS32_EF_CP0_STATUS 42
+#define MIPS32_EF_CP0_CAUSE 43
+#define MIPS32_EF_UNUSED0 44
+
+#define MIPS32_EF_SIZE 180
+
+#define MIPS64_EF_R0 0
+#define MIPS64_EF_R1 1
+#define MIPS64_EF_R2 2
+#define MIPS64_EF_R3 3
+#define MIPS64_EF_R4 4
+#define MIPS64_EF_R5 5
+#define MIPS64_EF_R6 6
+#define MIPS64_EF_R7 7
+#define MIPS64_EF_R8 8
+#define MIPS64_EF_R9 9
+#define MIPS64_EF_R10 10
+#define MIPS64_EF_R11 11
+#define MIPS64_EF_R12 12
+#define MIPS64_EF_R13 13
+#define MIPS64_EF_R14 14
+#define MIPS64_EF_R15 15
+#define MIPS64_EF_R16 16
+#define MIPS64_EF_R17 17
+#define MIPS64_EF_R18 18
+#define MIPS64_EF_R19 19
+#define MIPS64_EF_R20 20
+#define MIPS64_EF_R21 21
+#define MIPS64_EF_R22 22
+#define MIPS64_EF_R23 23
+#define MIPS64_EF_R24 24
+#define MIPS64_EF_R25 25
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS64_EF_R26 26
+#define MIPS64_EF_R27 27
+
+
+#define MIPS64_EF_R28 28
+#define MIPS64_EF_R29 29
+#define MIPS64_EF_R30 30
+#define MIPS64_EF_R31 31
+
+/*
+ * Saved special registers
+ */
+#define MIPS64_EF_LO 32
+#define MIPS64_EF_HI 33
+
+#define MIPS64_EF_CP0_EPC 34
+#define MIPS64_EF_CP0_BADVADDR 35
+#define MIPS64_EF_CP0_STATUS 36
+#define MIPS64_EF_CP0_CAUSE 37
+
+#define MIPS64_EF_SIZE 304 /* size in bytes */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+#define EF_R0 MIPS32_EF_R0
+#define EF_R1 MIPS32_EF_R1
+#define EF_R2 MIPS32_EF_R2
+#define EF_R3 MIPS32_EF_R3
+#define EF_R4 MIPS32_EF_R4
+#define EF_R5 MIPS32_EF_R5
+#define EF_R6 MIPS32_EF_R6
+#define EF_R7 MIPS32_EF_R7
+#define EF_R8 MIPS32_EF_R8
+#define EF_R9 MIPS32_EF_R9
+#define EF_R10 MIPS32_EF_R10
+#define EF_R11 MIPS32_EF_R11
+#define EF_R12 MIPS32_EF_R12
+#define EF_R13 MIPS32_EF_R13
+#define EF_R14 MIPS32_EF_R14
+#define EF_R15 MIPS32_EF_R15
+#define EF_R16 MIPS32_EF_R16
+#define EF_R17 MIPS32_EF_R17
+#define EF_R18 MIPS32_EF_R18
+#define EF_R19 MIPS32_EF_R19
+#define EF_R20 MIPS32_EF_R20
+#define EF_R21 MIPS32_EF_R21
+#define EF_R22 MIPS32_EF_R22
+#define EF_R23 MIPS32_EF_R23
+#define EF_R24 MIPS32_EF_R24
+#define EF_R25 MIPS32_EF_R25
+#define EF_R26 MIPS32_EF_R26
+#define EF_R27 MIPS32_EF_R27
+#define EF_R28 MIPS32_EF_R28
+#define EF_R29 MIPS32_EF_R29
+#define EF_R30 MIPS32_EF_R30
+#define EF_R31 MIPS32_EF_R31
+#define EF_LO MIPS32_EF_LO
+#define EF_HI MIPS32_EF_HI
+#define EF_CP0_EPC MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0 MIPS32_EF_UNUSED0
+#define EF_SIZE MIPS32_EF_SIZE
+
+#elif _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+
+#define EF_R0 MIPS64_EF_R0
+#define EF_R1 MIPS64_EF_R1
+#define EF_R2 MIPS64_EF_R2
+#define EF_R3 MIPS64_EF_R3
+#define EF_R4 MIPS64_EF_R4
+#define EF_R5 MIPS64_EF_R5
+#define EF_R6 MIPS64_EF_R6
+#define EF_R7 MIPS64_EF_R7
+#define EF_R8 MIPS64_EF_R8
+#define EF_R9 MIPS64_EF_R9
+#define EF_R10 MIPS64_EF_R10
+#define EF_R11 MIPS64_EF_R11
+#define EF_R12 MIPS64_EF_R12
+#define EF_R13 MIPS64_EF_R13
+#define EF_R14 MIPS64_EF_R14
+#define EF_R15 MIPS64_EF_R15
+#define EF_R16 MIPS64_EF_R16
+#define EF_R17 MIPS64_EF_R17
+#define EF_R18 MIPS64_EF_R18
+#define EF_R19 MIPS64_EF_R19
+#define EF_R20 MIPS64_EF_R20
+#define EF_R21 MIPS64_EF_R21
+#define EF_R22 MIPS64_EF_R22
+#define EF_R23 MIPS64_EF_R23
+#define EF_R24 MIPS64_EF_R24
+#define EF_R25 MIPS64_EF_R25
+#define EF_R26 MIPS64_EF_R26
+#define EF_R27 MIPS64_EF_R27
+#define EF_R28 MIPS64_EF_R28
+#define EF_R29 MIPS64_EF_R29
+#define EF_R30 MIPS64_EF_R30
+#define EF_R31 MIPS64_EF_R31
+#define EF_LO MIPS64_EF_LO
+#define EF_HI MIPS64_EF_HI
+#define EF_CP0_EPC MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE MIPS64_EF_CP0_CAUSE
+#define EF_SIZE MIPS64_EF_SIZE
+
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#endif /* __UAPI_ASM_MIPS_REG_H */
diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h
index 5805414777e0..9bc13eaf9d67 100644
--- a/arch/mips/include/uapi/asm/unistd.h
+++ b/arch/mips/include/uapi/asm/unistd.h
@@ -372,16 +372,17 @@
#define __NR_sched_setattr (__NR_Linux + 349)
#define __NR_sched_getattr (__NR_Linux + 350)
#define __NR_renameat2 (__NR_Linux + 351)
+#define __NR_seccomp (__NR_Linux + 352)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 351
+#define __NR_Linux_syscalls 352
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 351
+#define __NR_O32_Linux_syscalls 352
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -701,16 +702,17 @@
#define __NR_sched_setattr (__NR_Linux + 309)
#define __NR_sched_getattr (__NR_Linux + 310)
#define __NR_renameat2 (__NR_Linux + 311)
+#define __NR_seccomp (__NR_Linux + 312)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 311
+#define __NR_Linux_syscalls 312
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 311
+#define __NR_64_Linux_syscalls 312
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -1034,15 +1036,16 @@
#define __NR_sched_setattr (__NR_Linux + 313)
#define __NR_sched_getattr (__NR_Linux + 314)
#define __NR_renameat2 (__NR_Linux + 315)
+#define __NR_seccomp (__NR_Linux + 316)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 315
+#define __NR_Linux_syscalls 316
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 315
+#define __NR_N32_Linux_syscalls 316
#endif /* _UAPI_ASM_UNISTD_H */
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 088e92a79ae6..c454525e7695 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c
index a8acdeff267e..325422d0d453 100644
--- a/arch/mips/jz4740/clock-debugfs.c
+++ b/arch/mips/jz4740/clock-debugfs.c
@@ -87,8 +87,7 @@ void jz4740_clock_debugfs_add_clk(struct clk *clk)
/* TODO: Locking */
void jz4740_clock_debugfs_update_parent(struct clk *clk)
{
- if (clk->debugfs_parent_entry)
- debugfs_remove(clk->debugfs_parent_entry);
+ debugfs_remove(clk->debugfs_parent_entry);
if (clk->parent) {
char parent_path[100];
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index a447101cf9f1..0b12f273cb2e 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -59,7 +59,7 @@ struct platform_device jz4740_usb_ohci_device = {
/* USB Device Controller */
struct platform_device jz4740_udc_xceiv_device = {
- .name = "usb_phy_gen_xceiv",
+ .name = "usb_phy_generic",
.id = 0,
};
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 4bb5107511e2..b1d84bd4efb3 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -234,6 +234,7 @@ void output_thread_fpu_defines(void)
thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+ OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
BLANK();
}
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 7faf5f2bee25..928767858b86 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -72,22 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#include <asm/processor.h>
-/*
- * When this file is selected, we are definitely running a 64bit kernel.
- * So using the right regs define in asm/reg.h
- */
-#define WANT_COMPAT_REG_H
-
-/* These MUST be defined before elf.h gets included */
-extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest) \
-({ \
- int __res = 1; \
- elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk)); \
- __res; \
-})
-
#include <linux/module.h>
#include <linux/elfcore.h>
#include <linux/compat.h>
@@ -145,28 +129,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
value->tv_usec = rem / NSEC_PER_USEC;
}
-void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
-{
- int i;
-
- for (i = 0; i < EF_R0; i++)
- grp[i] = 0;
- grp[EF_R0] = 0;
- for (i = 1; i <= 31; i++)
- grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
- grp[EF_R26] = 0;
- grp[EF_R27] = 0;
- grp[EF_LO] = (elf_greg_t) regs->lo;
- grp[EF_HI] = (elf_greg_t) regs->hi;
- grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
- grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
- grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
- grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
- grp[EF_UNUSED0] = 0;
-#endif
-}
-
MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index d74f957c561e..e34b10be782e 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -54,6 +54,20 @@ static int __init dsp_disable(char *s)
__setup("nodsp", dsp_disable);
+static int mips_htw_disabled;
+
+static int __init htw_disable(char *s)
+{
+ mips_htw_disabled = 1;
+ cpu_data[0].options &= ~MIPS_CPU_HTW;
+ write_c0_pwctl(read_c0_pwctl() &
+ ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+
+ return 1;
+}
+
+__setup("nohtw", htw_disable);
+
static inline void check_errata(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -130,14 +144,13 @@ static inline int __cpu_has_fpu(void)
static inline unsigned long cpu_get_msa_id(void)
{
- unsigned long status, conf5, msa_id;
+ unsigned long status, msa_id;
status = read_c0_status();
__enable_fpu(FPU_64BIT);
- conf5 = read_c0_config5();
enable_msa();
msa_id = read_msa_ir();
- write_c0_config5(conf5);
+ disable_msa();
write_c0_status(status);
return msa_id;
}
@@ -321,6 +334,9 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_SEGMENTS;
if (config3 & MIPS_CONF3_MSA)
c->ases |= MIPS_ASE_MSA;
+ /* Only tested on 32-bit cores */
+ if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
+ c->options |= MIPS_CPU_HTW;
return config3 & MIPS_CONF_M;
}
@@ -389,6 +405,8 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
if (config5 & MIPS_CONF5_EVA)
c->options |= MIPS_CPU_EVA;
+ if (config5 & MIPS_CONF5_MRP)
+ c->options |= MIPS_CPU_MAAR;
return config5 & MIPS_CONF_M;
}
@@ -421,6 +439,15 @@ static void decode_configs(struct cpuinfo_mips *c)
mips_probe_watch_registers(c);
+ if (cpu_has_rixi) {
+ /* Enable the RIXI exceptions */
+ write_c0_pagegrain(read_c0_pagegrain() | PG_IEC);
+ back_to_back_c0_hazard();
+ /* Verify the IEC bit is set */
+ if (read_c0_pagegrain() & PG_IEC)
+ c->options |= MIPS_CPU_RIXIEX;
+ }
+
#ifndef CONFIG_MIPS_CPS
if (cpu_has_mips_r2) {
c->core = get_ebase_cpunum();
@@ -740,6 +767,12 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "ICT Loongson-3";
set_elf_platform(cpu, "loongson3a");
break;
+ case PRID_REV_LOONGSON3B_R1:
+ case PRID_REV_LOONGSON3B_R2:
+ c->cputype = CPU_LOONGSON3;
+ __cpu_name[cpu] = "ICT Loongson-3";
+ set_elf_platform(cpu, "loongson3b");
+ break;
}
set_isa(c, MIPS_CPU_ISA_III);
@@ -1187,6 +1220,12 @@ void cpu_probe(void)
if (mips_dsp_disabled)
c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
+ if (mips_htw_disabled) {
+ c->options &= ~MIPS_CPU_HTW;
+ write_c0_pwctl(read_c0_pwctl() &
+ ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+ }
+
if (c->options & MIPS_CPU_FPU) {
c->fpu_id = cpu_get_fpu_id();
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 60e7e5e45af1..937c54bc8ccc 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -63,7 +63,7 @@ static inline int in_kernel_space(unsigned long ip)
((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
static unsigned int insn_jal_ftrace_caller __read_mostly;
-static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
+static unsigned int insn_la_mcount[2] __read_mostly;
static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
static inline void ftrace_dyn_arch_init_insns(void)
@@ -71,10 +71,10 @@ static inline void ftrace_dyn_arch_init_insns(void)
u32 *buf;
unsigned int v1;
- /* lui v1, hi16_mcount */
+ /* la v1, _mcount */
v1 = 3;
- buf = (u32 *)&insn_lui_v1_hi16_mcount;
- UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
+ buf = (u32 *)&insn_la_mcount[0];
+ UASM_i_LA(&buf, v1, MCOUNT_ADDR);
/* jal (ftrace_caller + 8), jump over the first two instruction */
buf = (u32 *)&insn_jal_ftrace_caller;
@@ -111,14 +111,47 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
unsigned int new_code2)
{
int faulted;
+ mm_segment_t old_fs;
safe_store_code(new_code1, ip, faulted);
if (unlikely(faulted))
return -EFAULT;
- safe_store_code(new_code2, ip + 4, faulted);
+
+ ip += 4;
+ safe_store_code(new_code2, ip, faulted);
if (unlikely(faulted))
return -EFAULT;
+
+ ip -= 4;
+ old_fs = get_fs();
+ set_fs(get_ds());
flush_icache_range(ip, ip + 8);
+ set_fs(old_fs);
+
+ return 0;
+}
+
+static int ftrace_modify_code_2r(unsigned long ip, unsigned int new_code1,
+ unsigned int new_code2)
+{
+ int faulted;
+ mm_segment_t old_fs;
+
+ ip += 4;
+ safe_store_code(new_code2, ip, faulted);
+ if (unlikely(faulted))
+ return -EFAULT;
+
+ ip -= 4;
+ safe_store_code(new_code1, ip, faulted);
+ if (unlikely(faulted))
+ return -EFAULT;
+
+ old_fs = get_fs();
+ set_fs(get_ds());
+ flush_icache_range(ip, ip + 8);
+ set_fs(old_fs);
+
return 0;
}
#endif
@@ -130,13 +163,14 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
*
* move at, ra
* jal _mcount --> nop
+ * sub sp, sp, 8 --> nop (CONFIG_32BIT)
*
* 2. For modules:
*
* 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop (CONFIG_32BIT)
* move at, ra
* move $12, ra_address
* jalr v1
@@ -145,7 +179,7 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
* 2.2 For the Other situations
*
* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
- * addiu v1, v1, low_16bit_of_mcount
+ * addiu v1, v1, low_16bit_of_mcount --> nop (CONFIG_32BIT)
* move at, ra
* jalr v1
* nop | move $12, ra_address | sub sp, sp, 8
@@ -184,10 +218,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned int new;
unsigned long ip = rec->ip;
- new = in_kernel_space(ip) ? insn_jal_ftrace_caller :
- insn_lui_v1_hi16_mcount;
+ new = in_kernel_space(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
+#ifdef CONFIG_64BIT
return ftrace_modify_code(ip, new);
+#else
+ return ftrace_modify_code_2r(ip, new, in_kernel_space(ip) ?
+ INSN_NOP : insn_la_mcount[1]);
+#endif
}
#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
@@ -302,6 +340,9 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
&return_to_handler;
int faulted, insns;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 88e4c323382c..9e9d8b9a5b97 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -28,6 +28,18 @@ unsigned int gic_irq_flags[GIC_NUM_INTRS];
/* The index into this array is the vector # of the interrupt. */
struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
+struct gic_pcpu_mask {
+ DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+};
+
+struct gic_pending_regs {
+ DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+};
+
+struct gic_intrmask_regs {
+ DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+};
+
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
static struct gic_pending_regs pending_regs[NR_CPUS];
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
@@ -177,7 +189,7 @@ unsigned int gic_compare_int(void)
return 0;
}
-unsigned int gic_get_int(void)
+void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
{
unsigned int i;
unsigned long *pending, *intrmask, *pcpu_mask;
@@ -202,8 +214,17 @@ unsigned int gic_get_int(void)
bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+ bitmap_and(dst, src, pending, GIC_NUM_INTRS);
+}
- return find_first_bit(pending, GIC_NUM_INTRS);
+unsigned int gic_get_int(void)
+{
+ DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
+
+ bitmap_fill(interrupts, GIC_NUM_INTRS);
+ gic_get_int_mask(interrupts, interrupts);
+
+ return find_first_bit(interrupts, GIC_NUM_INTRS);
}
static void gic_mask_irq(struct irq_data *d)
@@ -269,11 +290,13 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
/* Setup Intr to Pin mapping */
if (pin & GIC_MAP_TO_NMI_MSK) {
+ int i;
+
GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
/* FIXME: hack to route NMI to all cpu's */
- for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
+ for (i = 0; i < NR_CPUS; i += 32) {
GICWRITE(GIC_REG_ADDR(SHARED,
- GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
+ GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
0xffffffff);
}
} else {
@@ -299,9 +322,10 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
/* Init Intr Masks */
GIC_CLR_INTR_MASK(intr);
+
/* Initialise per-cpu Interrupt software masks */
- if (flags & GIC_FLAG_IPI)
- set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+ set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+
if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
GIC_SET_INTR_MASK(intr);
if (trigtype == GIC_TRIG_EDGE)
@@ -340,8 +364,6 @@ static void __init gic_basic_init(int numintrs, int numvpes,
cpu = intrmap[i].cpunum;
if (cpu == GIC_UNUSED)
continue;
- if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
- continue;
gic_setup_intr(i,
intrmap[i].cpunum,
intrmap[i].pin + pin_offset,
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 539b6294b613..5d25462de8a6 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -74,16 +74,25 @@ _mcount:
#endif
/* When tracing is activated, it calls ftrace_caller+8 (aka here) */
- lw t1, function_trace_stop
- bnez t1, ftrace_stub
- nop
-
MCOUNT_SAVE_REGS
#ifdef KBUILD_MCOUNT_RA_ADDRESS
PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp)
#endif
PTR_SUBU a0, ra, 8 /* arg1: self address */
+ PTR_LA t1, _stext
+ sltu t2, a0, t1 /* t2 = (a0 < _stext) */
+ PTR_LA t1, _etext
+ sltu t3, t1, a0 /* t3 = (a0 > _etext) */
+ or t1, t2, t3
+ beqz t1, ftrace_call
+ nop
+#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
+ PTR_SUBU a0, a0, 16 /* arg1: adjust to module's recorded callsite */
+#else
+ PTR_SUBU a0, a0, 12
+#endif
+
.globl ftrace_call
ftrace_call:
nop /* a placeholder for the call to a real tracing function */
@@ -105,9 +114,6 @@ ftrace_stub:
#else /* ! CONFIG_DYNAMIC_FTRACE */
NESTED(_mcount, PT_SIZE, ra)
- lw t1, function_trace_stop
- bnez t1, ftrace_stub
- nop
PTR_LA t1, ftrace_stub
PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */
bne t1, t2, static_trace
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 4f2d9dece7ab..14bf74b0f51c 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1386,6 +1386,9 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
/* proAptiv */
#define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b) \
((b) == 0 || (b) == 1)
+/* P5600 */
+#define IS_BOTH_COUNTERS_P5600_EVENT(b) \
+ ((b) == 0 || (b) == 1)
/* 1004K */
#define IS_BOTH_COUNTERS_1004K_EVENT(b) \
@@ -1420,20 +1423,23 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
/*
- * User can use 0-255 raw events, where 0-127 for the events of even
- * counters, and 128-255 for odd counters. Note that bit 7 is used to
- * indicate the parity. So, for example, when user wants to take the
- * Event Num of 15 for odd counters (by referring to the user manual),
- * then 128 needs to be added to 15 as the input for the event config,
- * i.e., 143 (0x8F) to be used.
+ * For most cores the user can use 0-255 raw events, where 0-127 for the events
+ * of even counters, and 128-255 for odd counters. Note that bit 7 is used to
+ * indicate the even/odd bank selector. So, for example, when user wants to take
+ * the Event Num of 15 for odd counters (by referring to the user manual), then
+ * 128 needs to be added to 15 as the input for the event config, i.e., 143 (0x8F)
+ * to be used.
+ *
+ * Some newer cores have even more events, in which case the user can use raw
+ * events 0-511, where 0-255 are for the events of even counters, and 256-511
+ * are for odd counters, so bit 8 is used to indicate the even/odd bank selector.
*/
static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
{
+ /* currently most cores have 7-bit event numbers */
unsigned int raw_id = config & 0xff;
unsigned int base_id = raw_id & 0x7f;
- raw_event.event_id = base_id;
-
switch (current_cpu_type()) {
case CPU_24K:
if (IS_BOTH_COUNTERS_24K_EVENT(base_id))
@@ -1485,6 +1491,19 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_event.range = P;
#endif
break;
+ case CPU_P5600:
+ /* 8-bit event numbers */
+ raw_id = config & 0x1ff;
+ base_id = raw_id & 0xff;
+ if (IS_BOTH_COUNTERS_P5600_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 255 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+ raw_event.range = P;
+#endif
+ break;
case CPU_1004K:
if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1523,6 +1542,8 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
}
+ raw_event.event_id = base_id;
+
return &raw_event;
}
@@ -1633,6 +1654,11 @@ init_hw_perf_events(void)
mipspmu.general_event_map = &mipsxxcore_event_map2;
mipspmu.cache_event_map = &mipsxxcore_cache_map2;
break;
+ case CPU_P5600:
+ mipspmu.name = "mips/P5600";
+ mipspmu.general_event_map = &mipsxxcore_event_map2;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+ break;
case CPU_1004K:
mipspmu.name = "mips/1004K";
mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index c4c2069d3a20..06147179a175 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -149,8 +149,12 @@ int cps_pm_enter_state(enum cps_pm_state state)
/* Setup the VPE to run mips_cps_pm_restore when started again */
if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ /* Power gating relies upon CPS SMP */
+ if (!mips_cps_smp_in_use())
+ return -EINVAL;
+
core_cfg = &mips_cps_core_bootcfg[core];
- vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id];
+ vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(&current_cpu_data)];
vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
vpe_cfg->gp = (unsigned long)current_thread_info();
vpe_cfg->sp = 0;
@@ -376,6 +380,10 @@ static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
memset(relocs, 0, sizeof(relocs));
if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ /* Power gating relies upon CPS SMP */
+ if (!mips_cps_smp_in_use())
+ goto out_err;
+
/*
* Save CPU state. Note the non-standard calling convention
* with the return address placed in v0 to avoid clobbering
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 037a44d962f3..097fc8d14e42 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -113,6 +113,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (cpu_has_vz) seq_printf(m, "%s", " vz");
if (cpu_has_msa) seq_printf(m, "%s", " msa");
if (cpu_has_eva) seq_printf(m, "%s", " eva");
+ if (cpu_has_htw) seq_printf(m, "%s", " htw");
seq_printf(m, "\n");
if (cpu_has_mmips) {
@@ -123,6 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
cpu_data[n].srsets);
seq_printf(m, "kscratch registers\t: %d\n",
hweight8(cpu_data[n].kscratch_mask));
+ seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 0a1ec0f3beff..636b0745d7c7 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -21,7 +21,6 @@
#include <linux/mman.h>
#include <linux/personality.h>
#include <linux/sys.h>
-#include <linux/user.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/kallsyms.h>
@@ -36,6 +35,7 @@
#include <asm/pgtable.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
+#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/elf.h>
@@ -66,6 +66,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
clear_used_math();
clear_fpu_owner();
init_dsp();
+ clear_thread_flag(TIF_USEDMSA);
clear_thread_flag(TIF_MSA_CTX_LIVE);
disable_msa();
regs->cp0_epc = pc;
@@ -141,6 +142,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
clear_tsk_thread_flag(p, TIF_USEDFPU);
+ clear_tsk_thread_flag(p, TIF_USEDMSA);
+ clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
#ifdef CONFIG_MIPS_MT_FPAFF
clear_tsk_thread_flag(p, TIF_FPUBOUND);
@@ -152,61 +155,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
return 0;
}
-/* Fill in the fpu structure for a core dump.. */
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
-{
- int i;
-
- for (i = 0; i < NUM_FPU_REGS; i++)
- memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
-
- memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
- sizeof(current->thread.fpu.fcr31));
-
- return 1;
-}
-
-void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
-{
- int i;
-
- for (i = 0; i < EF_R0; i++)
- gp[i] = 0;
- gp[EF_R0] = 0;
- for (i = 1; i <= 31; i++)
- gp[EF_R0 + i] = regs->regs[i];
- gp[EF_R26] = 0;
- gp[EF_R27] = 0;
- gp[EF_LO] = regs->lo;
- gp[EF_HI] = regs->hi;
- gp[EF_CP0_EPC] = regs->cp0_epc;
- gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
- gp[EF_CP0_STATUS] = regs->cp0_status;
- gp[EF_CP0_CAUSE] = regs->cp0_cause;
-#ifdef EF_UNUSED0
- gp[EF_UNUSED0] = 0;
-#endif
-}
-
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
- elf_dump_regs(*regs, task_pt_regs(tsk));
- return 1;
-}
-
-int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
-{
- int i;
-
- for (i = 0; i < NUM_FPU_REGS; i++)
- memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
-
- memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
- sizeof(t->thread.fpu.fcr31));
-
- return 1;
-}
-
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f639ccd5060c..645b3c4fcfba 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -24,7 +24,6 @@
#include <linux/ptrace.h>
#include <linux/regset.h>
#include <linux/smp.h>
-#include <linux/user.h>
#include <linux/security.h>
#include <linux/tracehook.h>
#include <linux/audit.h>
@@ -63,7 +62,7 @@ void ptrace_disable(struct task_struct *child)
* for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
* Registers are sign extended to fill the available space.
*/
-int ptrace_getregs(struct task_struct *child, __s64 __user *data)
+int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
{
struct pt_regs *regs;
int i;
@@ -74,13 +73,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
regs = task_pt_regs(child);
for (i = 0; i < 32; i++)
- __put_user((long)regs->regs[i], data + i);
- __put_user((long)regs->lo, data + EF_LO - EF_R0);
- __put_user((long)regs->hi, data + EF_HI - EF_R0);
- __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
- __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
- __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
- __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+ __put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
+ __put_user((long)regs->lo, (__s64 __user *)&data->lo);
+ __put_user((long)regs->hi, (__s64 __user *)&data->hi);
+ __put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
+ __put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
+ __put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
+ __put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
return 0;
}
@@ -90,7 +89,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
* the 64-bit format. On a 32-bit kernel only the lower order half
* (according to endianness) will be used.
*/
-int ptrace_setregs(struct task_struct *child, __s64 __user *data)
+int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
{
struct pt_regs *regs;
int i;
@@ -101,10 +100,10 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
regs = task_pt_regs(child);
for (i = 0; i < 32; i++)
- __get_user(regs->regs[i], data + i);
- __get_user(regs->lo, data + EF_LO - EF_R0);
- __get_user(regs->hi, data + EF_HI - EF_R0);
- __get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+ __get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
+ __get_user(regs->lo, (__s64 __user *)&data->lo);
+ __get_user(regs->hi, (__s64 __user *)&data->hi);
+ __get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
/* badvaddr, status, and cause may not be written. */
@@ -129,7 +128,7 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
}
__put_user(child->thread.fpu.fcr31, data + 64);
- __put_user(current_cpu_data.fpu_id, data + 65);
+ __put_user(boot_cpu_data.fpu_id, data + 65);
return 0;
}
@@ -151,6 +150,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
}
__get_user(child->thread.fpu.fcr31, data + 64);
+ child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
/* FIR may not be written. */
@@ -246,36 +246,160 @@ int ptrace_set_watch_regs(struct task_struct *child,
/* regset get/set implementations */
-static int gpr_get(struct task_struct *target,
- const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
{
struct pt_regs *regs = task_pt_regs(target);
+ u32 uregs[ELF_NGREG] = {};
+ unsigned i;
+
+ for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+ /* k0/k1 are copied as zero. */
+ if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+ continue;
+
+ uregs[i] = regs->regs[i - MIPS32_EF_R0];
+ }
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- regs, 0, sizeof(*regs));
+ uregs[MIPS32_EF_LO] = regs->lo;
+ uregs[MIPS32_EF_HI] = regs->hi;
+ uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+ uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+ uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+ uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+ sizeof(uregs));
}
-static int gpr_set(struct task_struct *target,
- const struct user_regset *regset,
- unsigned int pos, unsigned int count,
- const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
{
- struct pt_regs newregs;
- int ret;
+ struct pt_regs *regs = task_pt_regs(target);
+ u32 uregs[ELF_NGREG];
+ unsigned start, num_regs, i;
+ int err;
+
+ start = pos / sizeof(u32);
+ num_regs = count / sizeof(u32);
+
+ if (start + num_regs > ELF_NGREG)
+ return -EIO;
+
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+ sizeof(uregs));
+ if (err)
+ return err;
+
+ for (i = start; i < num_regs; i++) {
+ /*
+ * Cast all values to signed here so that if this is a 64-bit
+ * kernel, the supplied 32-bit values will be sign extended.
+ */
+ switch (i) {
+ case MIPS32_EF_R1 ... MIPS32_EF_R25:
+ /* k0/k1 are ignored. */
+ case MIPS32_EF_R28 ... MIPS32_EF_R31:
+ regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+ break;
+ case MIPS32_EF_LO:
+ regs->lo = (s32)uregs[i];
+ break;
+ case MIPS32_EF_HI:
+ regs->hi = (s32)uregs[i];
+ break;
+ case MIPS32_EF_CP0_EPC:
+ regs->cp0_epc = (s32)uregs[i];
+ break;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ u64 uregs[ELF_NGREG] = {};
+ unsigned i;
+
+ for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+ /* k0/k1 are copied as zero. */
+ if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+ continue;
+
+ uregs[i] = regs->regs[i - MIPS64_EF_R0];
+ }
+
+ uregs[MIPS64_EF_LO] = regs->lo;
+ uregs[MIPS64_EF_HI] = regs->hi;
+ uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+ uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+ uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+ uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+ sizeof(uregs));
+}
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &newregs,
- 0, sizeof(newregs));
- if (ret)
- return ret;
+static int gpr64_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+ u64 uregs[ELF_NGREG];
+ unsigned start, num_regs, i;
+ int err;
+
+ start = pos / sizeof(u64);
+ num_regs = count / sizeof(u64);
- *task_pt_regs(target) = newregs;
+ if (start + num_regs > ELF_NGREG)
+ return -EIO;
+
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+ sizeof(uregs));
+ if (err)
+ return err;
+
+ for (i = start; i < num_regs; i++) {
+ switch (i) {
+ case MIPS64_EF_R1 ... MIPS64_EF_R25:
+ /* k0/k1 are ignored. */
+ case MIPS64_EF_R28 ... MIPS64_EF_R31:
+ regs->regs[i - MIPS64_EF_R0] = uregs[i];
+ break;
+ case MIPS64_EF_LO:
+ regs->lo = uregs[i];
+ break;
+ case MIPS64_EF_HI:
+ regs->hi = uregs[i];
+ break;
+ case MIPS64_EF_CP0_EPC:
+ regs->cp0_epc = uregs[i];
+ break;
+ }
+ }
return 0;
}
+#endif /* CONFIG_64BIT */
+
static int fpr_get(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
@@ -337,14 +461,16 @@ enum mips_regset {
REGSET_FPR,
};
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
static const struct user_regset mips_regsets[] = {
[REGSET_GPR] = {
.core_note_type = NT_PRSTATUS,
.n = ELF_NGREG,
.size = sizeof(unsigned int),
.align = sizeof(unsigned int),
- .get = gpr_get,
- .set = gpr_set,
+ .get = gpr32_get,
+ .set = gpr32_set,
},
[REGSET_FPR] = {
.core_note_type = NT_PRFPREG,
@@ -364,14 +490,18 @@ static const struct user_regset_view user_mips_view = {
.n = ARRAY_SIZE(mips_regsets),
};
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
static const struct user_regset mips64_regsets[] = {
[REGSET_GPR] = {
.core_note_type = NT_PRSTATUS,
.n = ELF_NGREG,
.size = sizeof(unsigned long),
.align = sizeof(unsigned long),
- .get = gpr_get,
- .set = gpr_set,
+ .get = gpr64_get,
+ .set = gpr64_set,
},
[REGSET_FPR] = {
.core_note_type = NT_PRFPREG,
@@ -384,25 +514,26 @@ static const struct user_regset mips64_regsets[] = {
};
static const struct user_regset_view user_mips64_view = {
- .name = "mips",
+ .name = "mips64",
.e_machine = ELF_ARCH,
.ei_osabi = ELF_OSABI,
.regsets = mips64_regsets,
- .n = ARRAY_SIZE(mips_regsets),
+ .n = ARRAY_SIZE(mips64_regsets),
};
+#endif /* CONFIG_64BIT */
+
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
#ifdef CONFIG_32BIT
return &user_mips_view;
-#endif
-
+#else
#ifdef CONFIG_MIPS32_O32
- if (test_thread_flag(TIF_32BIT_REGS))
- return &user_mips_view;
+ if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+ return &user_mips_view;
#endif
-
return &user_mips64_view;
+#endif
}
long arch_ptrace(struct task_struct *child, long request,
@@ -480,7 +611,7 @@ long arch_ptrace(struct task_struct *child, long request,
break;
case FPC_EIR:
/* implementation / version register */
- tmp = current_cpu_data.fpu_id;
+ tmp = boot_cpu_data.fpu_id;
break;
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
@@ -565,7 +696,7 @@ long arch_ptrace(struct task_struct *child, long request,
break;
#endif
case FPC_CSR:
- child->thread.fpu.fcr31 = data;
+ child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
break;
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index b40c3ca60ee5..283b5a1967d1 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -22,7 +22,6 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/smp.h>
-#include <linux/user.h>
#include <linux/security.h>
#include <asm/cpu.h>
@@ -32,6 +31,7 @@
#include <asm/mipsmtregs.h>
#include <asm/pgtable.h>
#include <asm/page.h>
+#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
@@ -129,7 +129,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break;
case FPC_EIR:
/* implementation / version register */
- tmp = current_cpu_data.fpu_id;
+ tmp = boot_cpu_data.fpu_id;
break;
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
@@ -256,11 +256,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
}
case PTRACE_GETREGS:
- ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
+ ret = ptrace_getregs(child,
+ (struct user_pt_regs __user *) (__u64) data);
break;
case PTRACE_SETREGS:
- ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
+ ret = ptrace_setregs(child,
+ (struct user_pt_regs __user *) (__u64) data);
break;
case PTRACE_GETFPREGS:
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 81ca3f70fe29..4c4ec1812420 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -64,8 +64,10 @@
/* Check whether we're saving scalar or vector context. */
bgtz a3, 1f
- /* Save 128b MSA vector context. */
+ /* Save 128b MSA vector context + scalar FP control & status. */
+ cfc1 t1, fcr31
msa_save_all a0
+ sw t1, THREAD_FCR31(a0)
b 2f
1: /* Save 32b/64b scalar FP context. */
@@ -142,6 +144,11 @@ LEAF(_restore_msa)
jr ra
END(_restore_msa)
+LEAF(_init_msa_upper)
+ msa_init_all_upper
+ jr ra
+ END(_init_msa_upper)
+
#endif
/*
diff --git a/arch/mips/kernel/rtlx-cmp.c b/arch/mips/kernel/rtlx-cmp.c
index 758fb3cd2326..d26dcc4b46e7 100644
--- a/arch/mips/kernel/rtlx-cmp.c
+++ b/arch/mips/kernel/rtlx-cmp.c
@@ -77,6 +77,9 @@ int __init rtlx_module_init(void)
dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
"%s%d", RTLX_MODULE_NAME, i);
if (IS_ERR(dev)) {
+ while (i--)
+ device_destroy(mt_class, MKDEV(major, i));
+
err = PTR_ERR(dev);
goto out_chrdev;
}
diff --git a/arch/mips/kernel/rtlx-mt.c b/arch/mips/kernel/rtlx-mt.c
index 5a66b975989e..cb95470e2e69 100644
--- a/arch/mips/kernel/rtlx-mt.c
+++ b/arch/mips/kernel/rtlx-mt.c
@@ -103,6 +103,9 @@ int __init rtlx_module_init(void)
dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
"%s%d", RTLX_MODULE_NAME, i);
if (IS_ERR(dev)) {
+ while (i--)
+ device_destroy(mt_class, MKDEV(major, i));
+
err = PTR_ERR(dev);
goto out_chrdev;
}
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 3245474f19d5..f93b4cbec739 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -67,8 +67,6 @@ NESTED(handle_sys, PT_SIZE, sp)
/*
* Ok, copy the args from the luser stack to the kernel stack.
- * t3 is the precomputed number of instruction bytes needed to
- * load or store arguments 6-8.
*/
.set push
@@ -495,8 +493,8 @@ EXPORT(sys_call_table)
PTR sys_tgkill
PTR sys_utimes
PTR sys_mbind
- PTR sys_ni_syscall /* sys_get_mempolicy */
- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
+ PTR sys_get_mempolicy
+ PTR sys_set_mempolicy /* 4270 */
PTR sys_mq_open
PTR sys_mq_unlink
PTR sys_mq_timedsend
@@ -578,3 +576,4 @@ EXPORT(sys_call_table)
PTR sys_sched_setattr
PTR sys_sched_getattr /* 4350 */
PTR sys_renameat2
+ PTR sys_seccomp
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be2fedd4ae33..03ebd9979ad2 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -347,8 +347,8 @@ EXPORT(sys_call_table)
PTR sys_tgkill /* 5225 */
PTR sys_utimes
PTR sys_mbind
- PTR sys_ni_syscall /* sys_get_mempolicy */
- PTR sys_ni_syscall /* sys_set_mempolicy */
+ PTR sys_get_mempolicy
+ PTR sys_set_mempolicy
PTR sys_mq_open /* 5230 */
PTR sys_mq_unlink
PTR sys_mq_timedsend
@@ -431,4 +431,5 @@ EXPORT(sys_call_table)
PTR sys_sched_setattr
PTR sys_sched_getattr /* 5310 */
PTR sys_renameat2
+ PTR sys_seccomp
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index c1dbcda4b816..ebc9228e2e15 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -162,7 +162,7 @@ EXPORT(sysn32_call_table)
PTR sys_getpeername
PTR sys_socketpair
PTR compat_sys_setsockopt
- PTR sys_getsockopt
+ PTR compat_sys_getsockopt
PTR __sys_clone /* 6055 */
PTR __sys_fork
PTR compat_sys_execve
@@ -339,9 +339,9 @@ EXPORT(sysn32_call_table)
PTR compat_sys_clock_nanosleep
PTR sys_tgkill
PTR compat_sys_utimes /* 6230 */
- PTR sys_ni_syscall /* sys_mbind */
- PTR sys_ni_syscall /* sys_get_mempolicy */
- PTR sys_ni_syscall /* sys_set_mempolicy */
+ PTR compat_sys_mbind
+ PTR compat_sys_get_mempolicy
+ PTR compat_sys_set_mempolicy
PTR compat_sys_mq_open
PTR sys_mq_unlink /* 6235 */
PTR compat_sys_mq_timedsend
@@ -358,7 +358,7 @@ EXPORT(sysn32_call_table)
PTR sys_inotify_init
PTR sys_inotify_add_watch
PTR sys_inotify_rm_watch
- PTR sys_migrate_pages /* 6250 */
+ PTR compat_sys_migrate_pages /* 6250 */
PTR sys_openat
PTR sys_mkdirat
PTR sys_mknodat
@@ -379,7 +379,7 @@ EXPORT(sysn32_call_table)
PTR sys_sync_file_range
PTR sys_tee
PTR compat_sys_vmsplice /* 6270 */
- PTR sys_move_pages
+ PTR compat_sys_move_pages
PTR compat_sys_set_robust_list
PTR compat_sys_get_robust_list
PTR compat_sys_kexec_load
@@ -424,4 +424,5 @@ EXPORT(sysn32_call_table)
PTR sys_sched_setattr
PTR sys_sched_getattr
PTR sys_renameat2 /* 6315 */
+ PTR sys_seccomp
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index f1343ccd7ed7..13b964fddc4a 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -473,9 +473,9 @@ EXPORT(sys32_call_table)
PTR compat_sys_clock_nanosleep /* 4265 */
PTR sys_tgkill
PTR compat_sys_utimes
- PTR sys_ni_syscall /* sys_mbind */
- PTR sys_ni_syscall /* sys_get_mempolicy */
- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
+ PTR compat_sys_mbind
+ PTR compat_sys_get_mempolicy
+ PTR compat_sys_set_mempolicy /* 4270 */
PTR compat_sys_mq_open
PTR sys_mq_unlink
PTR compat_sys_mq_timedsend
@@ -492,7 +492,7 @@ EXPORT(sys32_call_table)
PTR sys_inotify_init
PTR sys_inotify_add_watch /* 4285 */
PTR sys_inotify_rm_watch
- PTR sys_migrate_pages
+ PTR compat_sys_migrate_pages
PTR compat_sys_openat
PTR sys_mkdirat
PTR sys_mknodat /* 4290 */
@@ -557,4 +557,5 @@ EXPORT(sys32_call_table)
PTR sys_sched_setattr
PTR sys_sched_getattr /* 4350 */
PTR sys_renameat2
+ PTR sys_seccomp
.size sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index a842154d57dc..7c1fe2b42d40 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(void)
* Initialize the bootmem allocator. It also setup initrd related data
* if needed.
*/
-#ifdef CONFIG_SGI_IP27
+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
static void __init bootmem_init(void)
{
@@ -729,6 +729,25 @@ static void __init resource_init(void)
}
}
+#ifdef CONFIG_SMP
+static void __init prefill_possible_map(void)
+{
+ int i, possible = num_possible_cpus();
+
+ if (possible > nr_cpu_ids)
+ possible = nr_cpu_ids;
+
+ for (i = 0; i < possible; i++)
+ set_cpu_possible(i, true);
+ for (; i < NR_CPUS; i++)
+ set_cpu_possible(i, false);
+
+ nr_cpu_ids = possible;
+}
+#else
+static inline void prefill_possible_map(void) {}
+#endif
+
void __init setup_arch(char **cmdline_p)
{
cpu_probe();
@@ -752,6 +771,7 @@ void __init setup_arch(char **cmdline_p)
resource_init();
plat_smp_setup();
+ prefill_possible_map();
cpu_cache_init();
}
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
index 9c60d09e62a7..06805e09bcd3 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -22,7 +22,7 @@
/*
* Determine which stack to use..
*/
-extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size);
/* Check and clear pending FPU exceptions in saved CSR */
extern int fpcsr_pending(unsigned int __user *fpcsr);
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9e60d117e41e..1d57605e4615 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
return err;
}
-void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size)
{
unsigned long sp;
@@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
*/
sp -= 32;
- /* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ sp = sigsp(sp, ksig);
return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
}
@@ -428,20 +426,20 @@ badframe:
}
#ifdef CONFIG_TRAD_SIGNALS
-static int setup_frame(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr, sigset_t *set)
+static int setup_frame(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto give_sigsegv;
+ return -EFAULT;
err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Arguments to signal handler:
@@ -453,37 +451,32 @@ static int setup_frame(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to the
* struct sigframe.
*/
- regs->regs[ 4] = signr;
+ regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
#endif
-static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr, sigset_t *set,
- siginfo_t *info)
+static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto give_sigsegv;
+ return -EFAULT;
/* Create siginfo. */
- err |= copy_siginfo_to_user(&frame->rs_info, info);
+ err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Arguments to signal handler:
@@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe.
*/
- regs->regs[ 4] = signr;
+ regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
struct mips_abi mips_abi = {
@@ -534,8 +523,7 @@ struct mips_abi mips_abi = {
.restart = __NR_restart_syscall
};
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -557,7 +545,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[2] = EINTR;
break;
case ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR;
break;
}
@@ -571,29 +559,23 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[0] = 0; /* Don't deal with this again. */
}
- if (sig_uses_siginfo(ka))
+ if (sig_uses_siginfo(&ksig->ka))
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
- ka, regs, sig, oldset, info);
+ ksig, regs, oldset);
else
- ret = abi->setup_frame(vdso + abi->signal_return_offset,
- ka, regs, sig, oldset);
-
- if (ret)
- return;
+ ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
+ regs, oldset);
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
static void do_signal(struct pt_regs *regs)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index bae2e6ee2109..d69179c0d49d 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -490,21 +490,21 @@ badframe:
force_sig(SIGSEGV, current);
}
-static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr, sigset_t *set)
+static int setup_frame_32(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct sigframe32 __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto give_sigsegv;
+ return -EFAULT;
err |= setup_sigcontext32(regs, &frame->sf_sc);
err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Arguments to signal handler:
@@ -516,37 +516,32 @@ static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to the
* struct sigframe.
*/
- regs->regs[ 4] = signr;
+ regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
-static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr, sigset_t *set,
- siginfo_t *info)
+static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct rt_sigframe32 __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto give_sigsegv;
+ return -EFAULT;
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
- err |= copy_siginfo_to_user32(&frame->rs_info, info);
+ err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -556,7 +551,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Arguments to signal handler:
@@ -568,22 +563,18 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe32.
*/
- regs->regs[ 4] = signr;
+ regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
/*
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index b2241bb9cac1..f1d4751eead0 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -102,18 +102,18 @@ badframe:
force_sig(SIGSEGV, current);
}
-static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
- struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
+static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct rt_sigframe_n32 __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- goto give_sigsegv;
+ return -EFAULT;
/* Create siginfo. */
- err |= copy_siginfo_to_user32(&frame->rs_info, info);
+ err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -123,7 +123,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/*
* Arguments to signal handler:
@@ -135,22 +135,18 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe.
*/
- regs->regs[ 4] = signr;
+ regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]);
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
struct mips_abi mips_abi_n32 = {
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 949f2c6827a0..e6e16a1d4add 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -14,13 +14,14 @@
#include <linux/smp.h>
#include <linux/types.h>
-#include <asm/cacheflush.h>
+#include <asm/bcache.h>
#include <asm/gic.h>
#include <asm/mips-cm.h>
#include <asm/mips-cpc.h>
#include <asm/mips_mt.h>
#include <asm/mipsregs.h>
#include <asm/pm-cps.h>
+#include <asm/r4kcache.h>
#include <asm/smp-cps.h>
#include <asm/time.h>
#include <asm/uasm.h>
@@ -132,8 +133,11 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
entry_code = (u32 *)&mips_cps_core_entry;
UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
uasm_i_addiu(&entry_code, 16, 0, cca);
- dma_cache_wback_inv((unsigned long)&mips_cps_core_entry,
- (void *)entry_code - (void *)&mips_cps_core_entry);
+ blast_dcache_range((unsigned long)&mips_cps_core_entry,
+ (unsigned long)entry_code);
+ bc_wback_inv((unsigned long)&mips_cps_core_entry,
+ (void *)entry_code - (void *)&mips_cps_core_entry);
+ __sync();
/* Allocate core boot configuration structs */
mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
@@ -360,7 +364,7 @@ void play_dead(void)
static void wait_for_sibling_halt(void *ptr_cpu)
{
unsigned cpu = (unsigned)ptr_cpu;
- unsigned vpe_id = cpu_data[cpu].vpe_id;
+ unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
unsigned halted;
unsigned long flags;
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 3babf6e4f894..21f23add04f4 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -288,6 +288,7 @@ struct plat_smp_ops vsmp_smp_ops = {
.prepare_cpus = vsmp_prepare_cpus,
};
+#ifdef CONFIG_PROC_FS
static int proc_cpuinfo_chain_call(struct notifier_block *nfb,
unsigned long action_unused, void *data)
{
@@ -309,3 +310,4 @@ static int __init proc_cpuinfo_notifier_init(void)
}
subsys_initcall(proc_cpuinfo_notifier_init);
+#endif
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9bad52ede903..c94c4e92e17d 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -59,9 +59,16 @@ EXPORT_SYMBOL(smp_num_siblings);
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map);
+/* representing the core map of multi-core chips of each logical CPU */
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(cpu_core_map);
+
/* representing cpus for which sibling maps can be computed */
static cpumask_t cpu_sibling_setup_map;
+/* representing cpus for which core maps can be computed */
+static cpumask_t cpu_core_setup_map;
+
cpumask_t cpu_coherent_mask;
static inline void set_cpu_sibling_map(int cpu)
@@ -72,7 +79,8 @@ static inline void set_cpu_sibling_map(int cpu)
if (smp_num_siblings > 1) {
for_each_cpu_mask(i, cpu_sibling_setup_map) {
- if (cpu_data[cpu].core == cpu_data[i].core) {
+ if (cpu_data[cpu].package == cpu_data[i].package &&
+ cpu_data[cpu].core == cpu_data[i].core) {
cpu_set(i, cpu_sibling_map[cpu]);
cpu_set(cpu, cpu_sibling_map[i]);
}
@@ -81,6 +89,20 @@ static inline void set_cpu_sibling_map(int cpu)
cpu_set(cpu, cpu_sibling_map[cpu]);
}
+static inline void set_cpu_core_map(int cpu)
+{
+ int i;
+
+ cpu_set(cpu, cpu_core_setup_map);
+
+ for_each_cpu_mask(i, cpu_core_setup_map) {
+ if (cpu_data[cpu].package == cpu_data[i].package) {
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
+ }
+ }
+}
+
struct plat_smp_ops *mp_ops;
EXPORT_SYMBOL(mp_ops);
@@ -122,6 +144,7 @@ asmlinkage void start_secondary(void)
set_cpu_online(cpu, true);
set_cpu_sibling_map(cpu);
+ set_cpu_core_map(cpu);
cpu_set(cpu, cpu_callin_map);
@@ -175,6 +198,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
current_thread_info()->cpu = 0;
mp_ops->prepare_cpus(max_cpus);
set_cpu_sibling_map(0);
+ set_cpu_core_map(0);
#ifndef CONFIG_HOTPLUG_CPU
init_cpu_present(cpu_possible_mask);
#endif
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 51706d6dd5b0..22b19c275044 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -90,6 +90,7 @@ extern asmlinkage void handle_mt(void);
extern asmlinkage void handle_dsp(void);
extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
+extern void tlb_do_page_fault_0(void);
void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -1088,13 +1089,19 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
static int enable_restore_fp_context(int msa)
{
- int err, was_fpu_owner;
+ int err, was_fpu_owner, prior_msa;
if (!used_math()) {
/* First time FP context user. */
+ preempt_disable();
err = init_fpu();
- if (msa && !err)
+ if (msa && !err) {
enable_msa();
+ _init_msa_upper();
+ set_thread_flag(TIF_USEDMSA);
+ set_thread_flag(TIF_MSA_CTX_LIVE);
+ }
+ preempt_enable();
if (!err)
set_used_math();
return err;
@@ -1134,10 +1141,11 @@ static int enable_restore_fp_context(int msa)
* This task is using or has previously used MSA. Thus we require
* that Status.FR == 1.
*/
+ preempt_disable();
was_fpu_owner = is_fpu_owner();
- err = own_fpu(0);
+ err = own_fpu_inatomic(0);
if (err)
- return err;
+ goto out;
enable_msa();
write_msa_csr(current->thread.fpu.msacsr);
@@ -1146,13 +1154,42 @@ static int enable_restore_fp_context(int msa)
/*
* If this is the first time that the task is using MSA and it has
* previously used scalar FP in this time slice then we already nave
- * FP context which we shouldn't clobber.
+ * FP context which we shouldn't clobber. We do however need to clear
+ * the upper 64b of each vector register so that this task has no
+ * opportunity to see data left behind by another.
*/
- if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
- return 0;
+ prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+ if (!prior_msa && was_fpu_owner) {
+ _init_msa_upper();
+
+ goto out;
+ }
+
+ if (!prior_msa) {
+ /*
+ * Restore the least significant 64b of each vector register
+ * from the existing scalar FP context.
+ */
+ _restore_fp(current);
+
+ /*
+ * The task has not formerly used MSA, so clear the upper 64b
+ * of each vector register such that it cannot see data left
+ * behind by another task.
+ */
+ _init_msa_upper();
+ } else {
+ /* We need to restore the vector context. */
+ restore_msa(current);
+
+ /* Restore the scalar FP control & status register */
+ if (!was_fpu_owner)
+ asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+ }
+
+out:
+ preempt_enable();
- /* We need to restore the vector context. */
- restore_msa(current);
return 0;
}
@@ -2114,6 +2151,12 @@ void __init trap_init(void)
set_except_vector(15, handle_fpe);
set_except_vector(16, handle_ftlb);
+
+ if (cpu_has_rixiex) {
+ set_except_vector(19, tlb_do_page_fault_0);
+ set_except_vector(20, tlb_do_page_fault_0);
+ }
+
set_except_vector(21, handle_msa);
set_except_vector(22, handle_mdmx);
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 2b3517214d6d..e11906dff885 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -690,7 +690,6 @@ static void emulate_load_store_insn(struct pt_regs *regs,
case sdc1_op:
die_if_kernel("Unaligned FP access in kernel code", regs);
BUG_ON(!used_math());
- BUG_ON(!is_fpu_owner());
lose_fpu(1); /* Save FPU state for the emulator. */
res = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile
index 78d87bbc99db..401fe027c261 100644
--- a/arch/mips/kvm/Makefile
+++ b/arch/mips/kvm/Makefile
@@ -5,9 +5,9 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm
-kvm-objs := $(common-objs) kvm_mips.o kvm_mips_emul.o kvm_locore.o \
- kvm_mips_int.o kvm_mips_stats.o kvm_mips_commpage.o \
- kvm_mips_dyntrans.o kvm_trap_emul.o
+kvm-objs := $(common-objs) mips.o emulate.o locore.o \
+ interrupt.o stats.o commpage.o \
+ dyntrans.o trap_emul.o
obj-$(CONFIG_KVM) += kvm.o
-obj-y += kvm_cb.o kvm_tlb.o
+obj-y += callback.o tlb.o
diff --git a/arch/mips/kvm/kvm_cb.c b/arch/mips/kvm/callback.c
index 313c2e37b978..313c2e37b978 100644
--- a/arch/mips/kvm/kvm_cb.c
+++ b/arch/mips/kvm/callback.c
diff --git a/arch/mips/kvm/commpage.c b/arch/mips/kvm/commpage.c
new file mode 100644
index 000000000000..2d6e976d1add
--- /dev/null
+++ b/arch/mips/kvm/commpage.c
@@ -0,0 +1,33 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * commpage, currently used for Virtual COP0 registers.
+ * Mapped into the guest kernel @ 0x0.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+#include <linux/kvm_host.h>
+
+#include "commpage.h"
+
+void kvm_mips_commpage_init(struct kvm_vcpu *vcpu)
+{
+ struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage;
+
+ /* Specific init values for fields */
+ vcpu->arch.cop0 = &page->cop0;
+}
diff --git a/arch/mips/kvm/commpage.h b/arch/mips/kvm/commpage.h
new file mode 100644
index 000000000000..08c5fa2bbc0f
--- /dev/null
+++ b/arch/mips/kvm/commpage.h
@@ -0,0 +1,24 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: commpage: mapped into get kernel space
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+#ifndef __KVM_MIPS_COMMPAGE_H__
+#define __KVM_MIPS_COMMPAGE_H__
+
+struct kvm_mips_commpage {
+ /* COP0 state is mapped into Guest kernel via commpage */
+ struct mips_coproc cop0;
+};
+
+#define KVM_MIPS_COMM_EIDI_OFFSET 0x0
+
+extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu);
+
+#endif /* __KVM_MIPS_COMMPAGE_H__ */
diff --git a/arch/mips/kvm/kvm_mips_dyntrans.c b/arch/mips/kvm/dyntrans.c
index b80e41d858fd..521121bdebff 100644
--- a/arch/mips/kvm/kvm_mips_dyntrans.c
+++ b/arch/mips/kvm/dyntrans.c
@@ -1,13 +1,13 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Binary Patching for privileged instructions, reduces traps.
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: Binary Patching for privileged instructions, reduces traps.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/errno.h>
#include <linux/err.h>
@@ -18,7 +18,7 @@
#include <linux/bootmem.h>
#include <asm/cacheflush.h>
-#include "kvm_mips_comm.h"
+#include "commpage.h"
#define SYNCI_TEMPLATE 0x041f0000
#define SYNCI_BASE(x) (((x) >> 21) & 0x1f)
@@ -28,9 +28,8 @@
#define CLEAR_TEMPLATE 0x00000020
#define SW_TEMPLATE 0xac000000
-int
-kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
- struct kvm_vcpu *vcpu)
+int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
+ struct kvm_vcpu *vcpu)
{
int result = 0;
unsigned long kseg0_opc;
@@ -47,12 +46,11 @@ kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc,
}
/*
- * Address based CACHE instructions are transformed into synci(s). A little heavy
- * for just D-cache invalidates, but avoids an expensive trap
+ * Address based CACHE instructions are transformed into synci(s). A little
+ * heavy for just D-cache invalidates, but avoids an expensive trap
*/
-int
-kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
- struct kvm_vcpu *vcpu)
+int kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
+ struct kvm_vcpu *vcpu)
{
int result = 0;
unsigned long kseg0_opc;
@@ -72,8 +70,7 @@ kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc,
return result;
}
-int
-kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+int kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
{
int32_t rt, rd, sel;
uint32_t mfc0_inst;
@@ -115,8 +112,7 @@ kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
return 0;
}
-int
-kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
+int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
{
int32_t rt, rd, sel;
uint32_t mtc0_inst = SW_TEMPLATE;
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/emulate.c
index 8d4840090082..fb3e8dfd1ff6 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/emulate.c
@@ -1,13 +1,13 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Instruction/Exception emulation
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: Instruction/Exception emulation
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/errno.h>
#include <linux/err.h>
@@ -29,9 +29,9 @@
#include <asm/r4kcache.h>
#define CONFIG_MIPS_MT
-#include "kvm_mips_opcode.h"
-#include "kvm_mips_int.h"
-#include "kvm_mips_comm.h"
+#include "opcode.h"
+#include "interrupt.h"
+#include "commpage.h"
#include "trace.h"
@@ -51,18 +51,14 @@ unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
if (epc & 3)
goto unaligned;
- /*
- * Read the instruction
- */
+ /* Read the instruction */
insn.word = kvm_get_inst((uint32_t *) epc, vcpu);
if (insn.word == KVM_INVALID_INST)
return KVM_INVALID_INST;
switch (insn.i_format.opcode) {
- /*
- * jr and jalr are in r_format format.
- */
+ /* jr and jalr are in r_format format. */
case spec_op:
switch (insn.r_format.func) {
case jalr_op:
@@ -124,18 +120,16 @@ unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
dspcontrol = rddsp(0x01);
- if (dspcontrol >= 32) {
+ if (dspcontrol >= 32)
epc = epc + 4 + (insn.i_format.simmediate << 2);
- } else
+ else
epc += 8;
nextpc = epc;
break;
}
break;
- /*
- * These are unconditional and in j_format.
- */
+ /* These are unconditional and in j_format. */
case jal_op:
arch->gprs[31] = instpc + 8;
case j_op:
@@ -146,9 +140,7 @@ unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
nextpc = epc;
break;
- /*
- * These are conditional and in i_format.
- */
+ /* These are conditional and in i_format. */
case beq_op:
case beql_op:
if (arch->gprs[insn.i_format.rs] ==
@@ -189,22 +181,20 @@ unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu,
nextpc = epc;
break;
- /*
- * And now the FPA/cp1 branch instructions.
- */
+ /* And now the FPA/cp1 branch instructions. */
case cop1_op:
- printk("%s: unsupported cop1_op\n", __func__);
+ kvm_err("%s: unsupported cop1_op\n", __func__);
break;
}
return nextpc;
unaligned:
- printk("%s: unaligned epc\n", __func__);
+ kvm_err("%s: unaligned epc\n", __func__);
return nextpc;
sigill:
- printk("%s: DSP branch but not DSP ASE\n", __func__);
+ kvm_err("%s: DSP branch but not DSP ASE\n", __func__);
return nextpc;
}
@@ -219,7 +209,8 @@ enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
er = EMULATE_FAIL;
} else {
vcpu->arch.pc = branch_pc;
- kvm_debug("BD update_pc(): New PC: %#lx\n", vcpu->arch.pc);
+ kvm_debug("BD update_pc(): New PC: %#lx\n",
+ vcpu->arch.pc);
}
} else
vcpu->arch.pc += 4;
@@ -240,6 +231,7 @@ enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause)
static inline int kvm_mips_count_disabled(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
+
return (vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) ||
(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC);
}
@@ -392,7 +384,6 @@ static ktime_t kvm_mips_freeze_hrtimer(struct kvm_vcpu *vcpu,
return now;
}
-
/**
* kvm_mips_resume_hrtimer() - Resume hrtimer, updating expiry.
* @vcpu: Virtual CPU.
@@ -760,8 +751,8 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
kvm_clear_c0_guest_status(cop0, ST0_ERL);
vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
} else {
- printk("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
- vcpu->arch.pc);
+ kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
+ vcpu->arch.pc);
er = EMULATE_FAIL;
}
@@ -770,8 +761,6 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
{
- enum emulation_result er = EMULATE_DONE;
-
kvm_debug("[%#lx] !!!WAIT!!! (%#lx)\n", vcpu->arch.pc,
vcpu->arch.pending_exceptions);
@@ -781,8 +770,9 @@ enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
vcpu->arch.wait = 1;
kvm_vcpu_block(vcpu);
- /* We we are runnable, then definitely go off to user space to check if any
- * I/O interrupts are pending.
+ /*
+ * We we are runnable, then definitely go off to user space to
+ * check if any I/O interrupts are pending.
*/
if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) {
clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
@@ -790,20 +780,20 @@ enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu)
}
}
- return er;
+ return EMULATE_DONE;
}
-/* XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that we can catch
- * this, if things ever change
+/*
+ * XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that
+ * we can catch this, if things ever change
*/
enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
- enum emulation_result er = EMULATE_FAIL;
uint32_t pc = vcpu->arch.pc;
- printk("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0));
- return er;
+ kvm_err("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0));
+ return EMULATE_FAIL;
}
/* Write Guest TLB Entry @ Index */
@@ -811,88 +801,76 @@ enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
int index = kvm_read_c0_guest_index(cop0);
- enum emulation_result er = EMULATE_DONE;
struct kvm_mips_tlb *tlb = NULL;
uint32_t pc = vcpu->arch.pc;
if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
- printk("%s: illegal index: %d\n", __func__, index);
- printk
- ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
- pc, index, kvm_read_c0_guest_entryhi(cop0),
- kvm_read_c0_guest_entrylo0(cop0),
- kvm_read_c0_guest_entrylo1(cop0),
- kvm_read_c0_guest_pagemask(cop0));
+ kvm_debug("%s: illegal index: %d\n", __func__, index);
+ kvm_debug("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+ pc, index, kvm_read_c0_guest_entryhi(cop0),
+ kvm_read_c0_guest_entrylo0(cop0),
+ kvm_read_c0_guest_entrylo1(cop0),
+ kvm_read_c0_guest_pagemask(cop0));
index = (index & ~0x80000000) % KVM_MIPS_GUEST_TLB_SIZE;
}
tlb = &vcpu->arch.guest_tlb[index];
-#if 1
- /* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
+ /*
+ * Probe the shadow host TLB for the entry being overwritten, if one
+ * matches, invalidate it
+ */
kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
-#endif
tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
- kvm_debug
- ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
- pc, index, kvm_read_c0_guest_entryhi(cop0),
- kvm_read_c0_guest_entrylo0(cop0), kvm_read_c0_guest_entrylo1(cop0),
- kvm_read_c0_guest_pagemask(cop0));
+ kvm_debug("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n",
+ pc, index, kvm_read_c0_guest_entryhi(cop0),
+ kvm_read_c0_guest_entrylo0(cop0),
+ kvm_read_c0_guest_entrylo1(cop0),
+ kvm_read_c0_guest_pagemask(cop0));
- return er;
+ return EMULATE_DONE;
}
/* Write Guest TLB Entry @ Random Index */
enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
- enum emulation_result er = EMULATE_DONE;
struct kvm_mips_tlb *tlb = NULL;
uint32_t pc = vcpu->arch.pc;
int index;
-#if 1
get_random_bytes(&index, sizeof(index));
index &= (KVM_MIPS_GUEST_TLB_SIZE - 1);
-#else
- index = jiffies % KVM_MIPS_GUEST_TLB_SIZE;
-#endif
-
- if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) {
- printk("%s: illegal index: %d\n", __func__, index);
- return EMULATE_FAIL;
- }
tlb = &vcpu->arch.guest_tlb[index];
-#if 1
- /* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */
+ /*
+ * Probe the shadow host TLB for the entry being overwritten, if one
+ * matches, invalidate it
+ */
kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi);
-#endif
tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0);
tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0);
tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0);
tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0);
- kvm_debug
- ("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n",
- pc, index, kvm_read_c0_guest_entryhi(cop0),
- kvm_read_c0_guest_entrylo0(cop0),
- kvm_read_c0_guest_entrylo1(cop0));
+ kvm_debug("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n",
+ pc, index, kvm_read_c0_guest_entryhi(cop0),
+ kvm_read_c0_guest_entrylo0(cop0),
+ kvm_read_c0_guest_entrylo1(cop0));
- return er;
+ return EMULATE_DONE;
}
enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
long entryhi = kvm_read_c0_guest_entryhi(cop0);
- enum emulation_result er = EMULATE_DONE;
uint32_t pc = vcpu->arch.pc;
int index = -1;
@@ -903,12 +881,12 @@ enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu)
kvm_debug("[%#x] COP0_TLBP (entryhi: %#lx), index: %d\n", pc, entryhi,
index);
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
+ uint32_t cause, struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
enum emulation_result er = EMULATE_DONE;
@@ -922,9 +900,8 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
*/
curr_pc = vcpu->arch.pc;
er = update_pc(vcpu, cause);
- if (er == EMULATE_FAIL) {
+ if (er == EMULATE_FAIL)
return er;
- }
copz = (inst >> 21) & 0x1f;
rt = (inst >> 16) & 0x1f;
@@ -949,7 +926,7 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
er = kvm_mips_emul_tlbp(vcpu);
break;
case rfe_op:
- printk("!!!COP0_RFE!!!\n");
+ kvm_err("!!!COP0_RFE!!!\n");
break;
case eret_op:
er = kvm_mips_emul_eret(vcpu);
@@ -973,8 +950,7 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
kvm_mips_trans_mfc0(inst, opc, vcpu);
#endif
- }
- else {
+ } else {
vcpu->arch.gprs[rt] = cop0->reg[rd][sel];
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
@@ -999,8 +975,8 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
if ((rd == MIPS_CP0_TLB_INDEX)
&& (vcpu->arch.gprs[rt] >=
KVM_MIPS_GUEST_TLB_SIZE)) {
- printk("Invalid TLB Index: %ld",
- vcpu->arch.gprs[rt]);
+ kvm_err("Invalid TLB Index: %ld",
+ vcpu->arch.gprs[rt]);
er = EMULATE_FAIL;
break;
}
@@ -1010,21 +986,19 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
kvm_change_c0_guest_ebase(cop0,
~(C0_EBASE_CORE_MASK),
vcpu->arch.gprs[rt]);
- printk("MTCz, cop0->reg[EBASE]: %#lx\n",
- kvm_read_c0_guest_ebase(cop0));
+ kvm_err("MTCz, cop0->reg[EBASE]: %#lx\n",
+ kvm_read_c0_guest_ebase(cop0));
} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
uint32_t nasid =
- vcpu->arch.gprs[rt] & ASID_MASK;
- if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
- &&
+ vcpu->arch.gprs[rt] & ASID_MASK;
+ if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
((kvm_read_c0_guest_entryhi(cop0) &
ASID_MASK) != nasid)) {
-
- kvm_debug
- ("MTCz, change ASID from %#lx to %#lx\n",
- kvm_read_c0_guest_entryhi(cop0) &
- ASID_MASK,
- vcpu->arch.gprs[rt] & ASID_MASK);
+ kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
+ kvm_read_c0_guest_entryhi(cop0)
+ & ASID_MASK,
+ vcpu->arch.gprs[rt]
+ & ASID_MASK);
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
@@ -1049,7 +1023,10 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
kvm_write_c0_guest_status(cop0,
vcpu->arch.gprs[rt]);
- /* Make sure that CU1 and NMI bits are never set */
+ /*
+ * Make sure that CU1 and NMI bits are
+ * never set
+ */
kvm_clear_c0_guest_status(cop0,
(ST0_CU1 | ST0_NMI));
@@ -1058,6 +1035,7 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
#endif
} else if ((rd == MIPS_CP0_CAUSE) && (sel == 0)) {
uint32_t old_cause, new_cause;
+
old_cause = kvm_read_c0_guest_cause(cop0);
new_cause = vcpu->arch.gprs[rt];
/* Update R/W bits */
@@ -1082,9 +1060,8 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
break;
case dmtc_op:
- printk
- ("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
- vcpu->arch.pc, rt, rd, sel);
+ kvm_err("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n",
+ vcpu->arch.pc, rt, rd, sel);
er = EMULATE_FAIL;
break;
@@ -1115,7 +1092,10 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
cop0->reg[MIPS_CP0_STATUS][2] & 0xf;
uint32_t pss =
(cop0->reg[MIPS_CP0_STATUS][2] >> 6) & 0xf;
- /* We don't support any shadow register sets, so SRSCtl[PSS] == SRSCtl[CSS] = 0 */
+ /*
+ * We don't support any shadow register sets, so
+ * SRSCtl[PSS] == SRSCtl[CSS] = 0
+ */
if (css || pss) {
er = EMULATE_FAIL;
break;
@@ -1126,21 +1106,17 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
}
break;
default:
- printk
- ("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n",
- vcpu->arch.pc, copz);
+ kvm_err("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n",
+ vcpu->arch.pc, copz);
er = EMULATE_FAIL;
break;
}
}
done:
- /*
- * Rollback PC only if emulation was unsuccessful
- */
- if (er == EMULATE_FAIL) {
+ /* Rollback PC only if emulation was unsuccessful */
+ if (er == EMULATE_FAIL)
vcpu->arch.pc = curr_pc;
- }
dont_update_pc:
/*
@@ -1152,9 +1128,9 @@ dont_update_pc:
return er;
}
-enum emulation_result
-kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DO_MMIO;
int32_t op, base, rt, offset;
@@ -1252,24 +1228,21 @@ kvm_mips_emulate_store(uint32_t inst, uint32_t cause,
break;
default:
- printk("Store not yet supported");
+ kvm_err("Store not yet supported");
er = EMULATE_FAIL;
break;
}
- /*
- * Rollback PC if emulation was unsuccessful
- */
- if (er == EMULATE_FAIL) {
+ /* Rollback PC if emulation was unsuccessful */
+ if (er == EMULATE_FAIL)
vcpu->arch.pc = curr_pc;
- }
return er;
}
-enum emulation_result
-kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DO_MMIO;
int32_t op, base, rt, offset;
@@ -1364,7 +1337,7 @@ kvm_mips_emulate_load(uint32_t inst, uint32_t cause,
break;
default:
- printk("Load not yet supported");
+ kvm_err("Load not yet supported");
er = EMULATE_FAIL;
break;
}
@@ -1383,7 +1356,7 @@ int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
gfn = va >> PAGE_SHIFT;
if (gfn >= kvm->arch.guest_pmap_npages) {
- printk("%s: Invalid gfn: %#llx\n", __func__, gfn);
+ kvm_err("%s: Invalid gfn: %#llx\n", __func__, gfn);
kvm_mips_dump_host_tlbs();
kvm_arch_vcpu_dump_regs(vcpu);
return -1;
@@ -1391,7 +1364,8 @@ int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
pfn = kvm->arch.guest_pmap[gfn];
pa = (pfn << PAGE_SHIFT) | offset;
- printk("%s: va: %#lx, unmapped: %#x\n", __func__, va, CKSEG0ADDR(pa));
+ kvm_debug("%s: va: %#lx, unmapped: %#x\n", __func__, va,
+ CKSEG0ADDR(pa));
local_flush_icache_range(CKSEG0ADDR(pa), 32);
return 0;
@@ -1410,13 +1384,12 @@ int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
#define MIPS_CACHE_DCACHE 0x1
#define MIPS_CACHE_SEC 0x3
-enum emulation_result
-kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
+ uint32_t cause,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
- extern void (*r4k_blast_dcache) (void);
- extern void (*r4k_blast_icache) (void);
enum emulation_result er = EMULATE_DONE;
int32_t offset, cache, op_inst, op, base;
struct kvm_vcpu_arch *arch = &vcpu->arch;
@@ -1443,22 +1416,23 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
kvm_debug("CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
cache, op, base, arch->gprs[base], offset);
- /* Treat INDEX_INV as a nop, basically issued by Linux on startup to invalidate
- * the caches entirely by stepping through all the ways/indexes
+ /*
+ * Treat INDEX_INV as a nop, basically issued by Linux on startup to
+ * invalidate the caches entirely by stepping through all the
+ * ways/indexes
*/
if (op == MIPS_CACHE_OP_INDEX_INV) {
- kvm_debug
- ("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
- vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
- arch->gprs[base], offset);
+ kvm_debug("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+ vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
+ arch->gprs[base], offset);
if (cache == MIPS_CACHE_DCACHE)
r4k_blast_dcache();
else if (cache == MIPS_CACHE_ICACHE)
r4k_blast_icache();
else {
- printk("%s: unsupported CACHE INDEX operation\n",
- __func__);
+ kvm_err("%s: unsupported CACHE INDEX operation\n",
+ __func__);
return EMULATE_FAIL;
}
@@ -1470,21 +1444,19 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
preempt_disable();
if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
-
- if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) {
+ if (kvm_mips_host_tlb_lookup(vcpu, va) < 0)
kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
- }
} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
int index;
/* If an entry already exists then skip */
- if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0) {
+ if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0)
goto skip_fault;
- }
- /* If address not in the guest TLB, then give the guest a fault, the
- * resulting handler will do the right thing
+ /*
+ * If address not in the guest TLB, then give the guest a fault,
+ * the resulting handler will do the right thing
*/
index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
(kvm_read_c0_guest_entryhi
@@ -1499,23 +1471,28 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
goto dont_update_pc;
} else {
struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
- /* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
+ /*
+ * Check if the entry is valid, if not then setup a TLB
+ * invalid exception to the guest
+ */
if (!TLB_IS_VALID(*tlb, va)) {
er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
run, vcpu);
preempt_enable();
goto dont_update_pc;
} else {
- /* We fault an entry from the guest tlb to the shadow host TLB */
+ /*
+ * We fault an entry from the guest tlb to the
+ * shadow host TLB
+ */
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
NULL,
NULL);
}
}
} else {
- printk
- ("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
- cache, op, base, arch->gprs[base], offset);
+ kvm_err("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+ cache, op, base, arch->gprs[base], offset);
er = EMULATE_FAIL;
preempt_enable();
goto dont_update_pc;
@@ -1530,7 +1507,10 @@ skip_fault:
flush_dcache_line(va);
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
- /* Replace the CACHE instruction, with a SYNCI, not the same, but avoids a trap */
+ /*
+ * Replace the CACHE instruction, with a SYNCI, not the same,
+ * but avoids a trap
+ */
kvm_mips_trans_cache_va(inst, opc, vcpu);
#endif
} else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) {
@@ -1542,9 +1522,8 @@ skip_fault:
kvm_mips_trans_cache_va(inst, opc, vcpu);
#endif
} else {
- printk
- ("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
- cache, op, base, arch->gprs[base], offset);
+ kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
+ cache, op, base, arch->gprs[base], offset);
er = EMULATE_FAIL;
preempt_enable();
goto dont_update_pc;
@@ -1552,28 +1531,23 @@ skip_fault:
preempt_enable();
- dont_update_pc:
- /*
- * Rollback PC
- */
+dont_update_pc:
+ /* Rollback PC */
vcpu->arch.pc = curr_pc;
- done:
+done:
return er;
}
-enum emulation_result
-kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DONE;
uint32_t inst;
- /*
- * Fetch the instruction.
- */
- if (cause & CAUSEF_BD) {
+ /* Fetch the instruction. */
+ if (cause & CAUSEF_BD)
opc += 1;
- }
inst = kvm_get_inst(opc, vcpu);
@@ -1601,8 +1575,8 @@ kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
break;
default:
- printk("Instruction emulation not supported (%p/%#x)\n", opc,
- inst);
+ kvm_err("Instruction emulation not supported (%p/%#x)\n", opc,
+ inst);
kvm_arch_vcpu_dump_regs(vcpu);
er = EMULATE_FAIL;
break;
@@ -1611,9 +1585,10 @@ kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc,
return er;
}
-enum emulation_result
-kvm_mips_emulate_syscall(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_syscall(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
@@ -1638,20 +1613,20 @@ kvm_mips_emulate_syscall(unsigned long cause, uint32_t *opc,
arch->pc = KVM_GUEST_KSEG0 + 0x180;
} else {
- printk("Trying to deliver SYSCALL when EXL is already set\n");
+ kvm_err("Trying to deliver SYSCALL when EXL is already set\n");
er = EMULATE_FAIL;
}
return er;
}
-enum emulation_result
-kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) |
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
@@ -1688,16 +1663,16 @@ kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
unsigned long entryhi =
(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
@@ -1734,16 +1709,16 @@ kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
@@ -1778,16 +1753,16 @@ kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
@@ -1822,13 +1797,13 @@ kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
- return er;
+ return EMULATE_DONE;
}
/* TLBMOD: store into address matching TLB with Dirty bit off */
-enum emulation_result
-kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DONE;
#ifdef DEBUG
@@ -1837,9 +1812,7 @@ kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
int index;
- /*
- * If address not in the guest TLB, then we are in trouble
- */
+ /* If address not in the guest TLB, then we are in trouble */
index = kvm_mips_guest_tlb_lookup(vcpu, entryhi);
if (index < 0) {
/* XXXKYMA Invalidate and retry */
@@ -1856,15 +1829,15 @@ kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc,
return er;
}
-enum emulation_result
-kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1895,16 +1868,16 @@ kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_fpu_exc(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_fpu_exc(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
- enum emulation_result er = EMULATE_DONE;
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1924,12 +1897,13 @@ kvm_mips_emulate_fpu_exc(unsigned long cause, uint32_t *opc,
(T_COP_UNUSABLE << CAUSEB_EXCCODE));
kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE));
- return er;
+ return EMULATE_DONE;
}
-enum emulation_result
-kvm_mips_emulate_ri_exc(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_ri_exc(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
@@ -1961,9 +1935,10 @@ kvm_mips_emulate_ri_exc(unsigned long cause, uint32_t *opc,
return er;
}
-enum emulation_result
-kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
@@ -1988,16 +1963,14 @@ kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc,
arch->pc = KVM_GUEST_KSEG0 + 0x180;
} else {
- printk("Trying to deliver BP when EXL is already set\n");
+ kvm_err("Trying to deliver BP when EXL is already set\n");
er = EMULATE_FAIL;
}
return er;
}
-/*
- * ll/sc, rdhwr, sync emulation
- */
+/* ll/sc, rdhwr, sync emulation */
#define OPCODE 0xfc000000
#define BASE 0x03e00000
@@ -2012,9 +1985,9 @@ kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc,
#define SYNC 0x0000000f
#define RDHWR 0x0000003b
-enum emulation_result
-kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
struct kvm_vcpu_arch *arch = &vcpu->arch;
@@ -2031,16 +2004,14 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
if (er == EMULATE_FAIL)
return er;
- /*
- * Fetch the instruction.
- */
+ /* Fetch the instruction. */
if (cause & CAUSEF_BD)
opc += 1;
inst = kvm_get_inst(opc, vcpu);
if (inst == KVM_INVALID_INST) {
- printk("%s: Cannot get inst @ %p\n", __func__, opc);
+ kvm_err("%s: Cannot get inst @ %p\n", __func__, opc);
return EMULATE_FAIL;
}
@@ -2099,15 +2070,15 @@ emulate_ri:
return kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
}
-enum emulation_result
-kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
+enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
+ struct kvm_run *run)
{
unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
enum emulation_result er = EMULATE_DONE;
unsigned long curr_pc;
if (run->mmio.len > sizeof(*gpr)) {
- printk("Bad MMIO length: %d", run->mmio.len);
+ kvm_err("Bad MMIO length: %d", run->mmio.len);
er = EMULATE_FAIL;
goto done;
}
@@ -2142,18 +2113,18 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
if (vcpu->arch.pending_load_cause & CAUSEF_BD)
- kvm_debug
- ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
- vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
- vcpu->mmio_needed);
+ kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
+ vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
+ vcpu->mmio_needed);
done:
return er;
}
-static enum emulation_result
-kvm_mips_emulate_exc(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+static enum emulation_result kvm_mips_emulate_exc(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
struct mips_coproc *cop0 = vcpu->arch.cop0;
@@ -2181,16 +2152,17 @@ kvm_mips_emulate_exc(unsigned long cause, uint32_t *opc,
exccode, kvm_read_c0_guest_epc(cop0),
kvm_read_c0_guest_badvaddr(cop0));
} else {
- printk("Trying to deliver EXC when EXL is already set\n");
+ kvm_err("Trying to deliver EXC when EXL is already set\n");
er = EMULATE_FAIL;
}
return er;
}
-enum emulation_result
-kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_check_privilege(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DONE;
uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
@@ -2215,10 +2187,13 @@ kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
break;
case T_TLB_LD_MISS:
- /* We we are accessing Guest kernel space, then send an address error exception to the guest */
+ /*
+ * We we are accessing Guest kernel space, then send an
+ * address error exception to the guest
+ */
if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
- printk("%s: LD MISS @ %#lx\n", __func__,
- badvaddr);
+ kvm_debug("%s: LD MISS @ %#lx\n", __func__,
+ badvaddr);
cause &= ~0xff;
cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE);
er = EMULATE_PRIV_FAIL;
@@ -2226,10 +2201,13 @@ kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
break;
case T_TLB_ST_MISS:
- /* We we are accessing Guest kernel space, then send an address error exception to the guest */
+ /*
+ * We we are accessing Guest kernel space, then send an
+ * address error exception to the guest
+ */
if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) {
- printk("%s: ST MISS @ %#lx\n", __func__,
- badvaddr);
+ kvm_debug("%s: ST MISS @ %#lx\n", __func__,
+ badvaddr);
cause &= ~0xff;
cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE);
er = EMULATE_PRIV_FAIL;
@@ -2237,8 +2215,8 @@ kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
break;
case T_ADDR_ERR_ST:
- printk("%s: address error ST @ %#lx\n", __func__,
- badvaddr);
+ kvm_debug("%s: address error ST @ %#lx\n", __func__,
+ badvaddr);
if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
cause &= ~0xff;
cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE);
@@ -2246,8 +2224,8 @@ kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
er = EMULATE_PRIV_FAIL;
break;
case T_ADDR_ERR_LD:
- printk("%s: address error LD @ %#lx\n", __func__,
- badvaddr);
+ kvm_debug("%s: address error LD @ %#lx\n", __func__,
+ badvaddr);
if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
cause &= ~0xff;
cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE);
@@ -2260,21 +2238,23 @@ kvm_mips_check_privilege(unsigned long cause, uint32_t *opc,
}
}
- if (er == EMULATE_PRIV_FAIL) {
+ if (er == EMULATE_PRIV_FAIL)
kvm_mips_emulate_exc(cause, opc, run, vcpu);
- }
+
return er;
}
-/* User Address (UA) fault, this could happen if
+/*
+ * User Address (UA) fault, this could happen if
* (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
* case we pass on the fault to the guest kernel and let it handle it.
* (2) TLB entry is present in the Guest TLB but not in the shadow, in this
* case we inject the TLB from the Guest TLB into the shadow host TLB
*/
-enum emulation_result
-kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
- struct kvm_run *run, struct kvm_vcpu *vcpu)
+enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
+ uint32_t *opc,
+ struct kvm_run *run,
+ struct kvm_vcpu *vcpu)
{
enum emulation_result er = EMULATE_DONE;
uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;
@@ -2284,10 +2264,11 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx, entryhi: %#lx\n",
vcpu->arch.host_cp0_badvaddr, vcpu->arch.host_cp0_entryhi);
- /* KVM would not have got the exception if this entry was valid in the shadow host TLB
- * Check the Guest TLB, if the entry is not there then send the guest an
- * exception. The guest exc handler should then inject an entry into the
- * guest TLB
+ /*
+ * KVM would not have got the exception if this entry was valid in the
+ * shadow host TLB. Check the Guest TLB, if the entry is not there then
+ * send the guest an exception. The guest exc handler should then inject
+ * an entry into the guest TLB.
*/
index = kvm_mips_guest_tlb_lookup(vcpu,
(va & VPN2_MASK) |
@@ -2299,13 +2280,17 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
} else if (exccode == T_TLB_ST_MISS) {
er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);
} else {
- printk("%s: invalid exc code: %d\n", __func__, exccode);
+ kvm_err("%s: invalid exc code: %d\n", __func__,
+ exccode);
er = EMULATE_FAIL;
}
} else {
struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];
- /* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */
+ /*
+ * Check if the entry is valid, if not then setup a TLB invalid
+ * exception to the guest
+ */
if (!TLB_IS_VALID(*tlb, va)) {
if (exccode == T_TLB_LD_MISS) {
er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,
@@ -2314,15 +2299,17 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
er = kvm_mips_emulate_tlbinv_st(cause, opc, run,
vcpu);
} else {
- printk("%s: invalid exc code: %d\n", __func__,
- exccode);
+ kvm_err("%s: invalid exc code: %d\n", __func__,
+ exccode);
er = EMULATE_FAIL;
}
} else {
- kvm_debug
- ("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
- tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
- /* OK we have a Guest TLB entry, now inject it into the shadow host TLB */
+ kvm_debug("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",
+ tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1);
+ /*
+ * OK we have a Guest TLB entry, now inject it into the
+ * shadow host TLB
+ */
kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
NULL);
}
diff --git a/arch/mips/kvm/kvm_mips_int.c b/arch/mips/kvm/interrupt.c
index 1e5de16afe29..9b4445940c2b 100644
--- a/arch/mips/kvm/kvm_mips_int.c
+++ b/arch/mips/kvm/interrupt.c
@@ -1,13 +1,13 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Interrupt delivery
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: Interrupt delivery
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/errno.h>
#include <linux/err.h>
@@ -20,7 +20,7 @@
#include <linux/kvm_host.h>
-#include "kvm_mips_int.h"
+#include "interrupt.h"
void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
{
@@ -34,7 +34,8 @@ void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority)
void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu)
{
- /* Cause bits to reflect the pending timer interrupt,
+ /*
+ * Cause bits to reflect the pending timer interrupt,
* the EXC code will be set when we are actually
* delivering the interrupt:
*/
@@ -51,12 +52,13 @@ void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu)
kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER);
}
-void
-kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
+void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu,
+ struct kvm_mips_interrupt *irq)
{
int intr = (int)irq->irq;
- /* Cause bits to reflect the pending IO interrupt,
+ /*
+ * Cause bits to reflect the pending IO interrupt,
* the EXC code will be set when we are actually
* delivering the interrupt:
*/
@@ -83,11 +85,11 @@ kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
}
-void
-kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
- struct kvm_mips_interrupt *irq)
+void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
+ struct kvm_mips_interrupt *irq)
{
int intr = (int)irq->irq;
+
switch (intr) {
case -2:
kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0));
@@ -111,9 +113,8 @@ kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu,
}
/* Deliver the interrupt of the corresponding priority, if possible. */
-int
-kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
- uint32_t cause)
+int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+ uint32_t cause)
{
int allowed = 0;
uint32_t exccode;
@@ -164,7 +165,6 @@ kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
/* Are we allowed to deliver the interrupt ??? */
if (allowed) {
-
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
kvm_write_c0_guest_epc(cop0, arch->pc);
@@ -195,9 +195,8 @@ kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
return allowed;
}
-int
-kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
- uint32_t cause)
+int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority,
+ uint32_t cause)
{
return 1;
}
diff --git a/arch/mips/kvm/kvm_mips_int.h b/arch/mips/kvm/interrupt.h
index 20da7d29eede..4ab4bdfad703 100644
--- a/arch/mips/kvm/kvm_mips_int.h
+++ b/arch/mips/kvm/interrupt.h
@@ -1,14 +1,15 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Interrupts
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: Interrupts
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
-/* MIPS Exception Priorities, exceptions (including interrupts) are queued up
+/*
+ * MIPS Exception Priorities, exceptions (including interrupts) are queued up
* for the guest in the order specified by their priorities
*/
@@ -27,6 +28,9 @@
#define MIPS_EXC_MAX 12
/* XXXSL More to follow */
+extern char mips32_exception[], mips32_exceptionEnd[];
+extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
+
#define C_TI (_ULCAST_(1) << 30)
#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0)
diff --git a/arch/mips/kvm/kvm_mips_comm.h b/arch/mips/kvm/kvm_mips_comm.h
deleted file mode 100644
index a4a8c85cc8f7..000000000000
--- a/arch/mips/kvm/kvm_mips_comm.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: commpage: mapped into get kernel space
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#ifndef __KVM_MIPS_COMMPAGE_H__
-#define __KVM_MIPS_COMMPAGE_H__
-
-struct kvm_mips_commpage {
- struct mips_coproc cop0; /* COP0 state is mapped into Guest kernel via commpage */
-};
-
-#define KVM_MIPS_COMM_EIDI_OFFSET 0x0
-
-extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu);
-
-#endif /* __KVM_MIPS_COMMPAGE_H__ */
diff --git a/arch/mips/kvm/kvm_mips_commpage.c b/arch/mips/kvm/kvm_mips_commpage.c
deleted file mode 100644
index 3873b1ecc40f..000000000000
--- a/arch/mips/kvm/kvm_mips_commpage.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* commpage, currently used for Virtual COP0 registers.
-* Mapped into the guest kernel @ 0x0.
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/bootmem.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/mmu_context.h>
-
-#include <linux/kvm_host.h>
-
-#include "kvm_mips_comm.h"
-
-void kvm_mips_commpage_init(struct kvm_vcpu *vcpu)
-{
- struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage;
- memset(page, 0, sizeof(struct kvm_mips_commpage));
-
- /* Specific init values for fields */
- vcpu->arch.cop0 = &page->cop0;
- memset(vcpu->arch.cop0, 0, sizeof(struct mips_coproc));
-
- return;
-}
diff --git a/arch/mips/kvm/kvm_mips_opcode.h b/arch/mips/kvm/kvm_mips_opcode.h
deleted file mode 100644
index 86d3b4cc348b..000000000000
--- a/arch/mips/kvm/kvm_mips_opcode.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
-
-/*
- * Define opcode values not defined in <asm/isnt.h>
- */
-
-#ifndef __KVM_MIPS_OPCODE_H__
-#define __KVM_MIPS_OPCODE_H__
-
-/* COP0 Ops */
-#define mfmcz_op 0x0b /* 01011 */
-#define wrpgpr_op 0x0e /* 01110 */
-
-/* COP0 opcodes (only if COP0 and CO=1): */
-#define wait_op 0x20 /* 100000 */
-
-#endif /* __KVM_MIPS_OPCODE_H__ */
diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/locore.S
index 033ac343e72c..d7279c03c517 100644
--- a/arch/mips/kvm/kvm_locore.S
+++ b/arch/mips/kvm/locore.S
@@ -16,7 +16,6 @@
#include <asm/stackframe.h>
#include <asm/asm-offsets.h>
-
#define _C_LABEL(x) x
#define MIPSX(name) mips32_ ## name
#define CALLFRAME_SIZ 32
@@ -91,7 +90,10 @@ FEXPORT(__kvm_mips_vcpu_run)
LONG_S $24, PT_R24(k1)
LONG_S $25, PT_R25(k1)
- /* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */
+ /*
+ * XXXKYMA k0/k1 not saved, not being used if we got here through
+ * an ioctl()
+ */
LONG_S $28, PT_R28(k1)
LONG_S $29, PT_R29(k1)
@@ -132,7 +134,10 @@ FEXPORT(__kvm_mips_vcpu_run)
/* Save the kernel gp as well */
LONG_S gp, VCPU_HOST_GP(k1)
- /* Setup status register for running the guest in UM, interrupts are disabled */
+ /*
+ * Setup status register for running the guest in UM, interrupts
+ * are disabled
+ */
li k0, (ST0_EXL | KSU_USER | ST0_BEV)
mtc0 k0, CP0_STATUS
ehb
@@ -152,7 +157,6 @@ FEXPORT(__kvm_mips_vcpu_run)
mtc0 k0, CP0_STATUS
ehb
-
/* Set Guest EPC */
LONG_L t0, VCPU_PC(k1)
mtc0 t0, CP0_EPC
@@ -165,7 +169,7 @@ FEXPORT(__kvm_mips_load_asid)
INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */
INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID /* else user */
1:
- /* t1: contains the base of the ASID array, need to get the cpu id */
+ /* t1: contains the base of the ASID array, need to get the cpu id */
LONG_L t2, TI_CPU($28) /* smp_processor_id */
INT_SLL t2, t2, 2 /* x4 */
REG_ADDU t3, t1, t2
@@ -229,9 +233,7 @@ FEXPORT(__kvm_mips_load_k0k1)
eret
VECTOR(MIPSX(exception), unknown)
-/*
- * Find out what mode we came from and jump to the proper handler.
- */
+/* Find out what mode we came from and jump to the proper handler. */
mtc0 k0, CP0_ERROREPC #01: Save guest k0
ehb #02:
@@ -239,7 +241,8 @@ VECTOR(MIPSX(exception), unknown)
INT_SRL k0, k0, 10 #03: Get rid of CPUNum
INT_SLL k0, k0, 10 #04
LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000
- INT_ADDIU k0, k0, 0x2000 #06: Exception handler is installed @ offset 0x2000
+ INT_ADDIU k0, k0, 0x2000 #06: Exception handler is
+ # installed @ offset 0x2000
j k0 #07: jump to the function
nop #08: branch delay slot
VECTOR_END(MIPSX(exceptionEnd))
@@ -248,7 +251,6 @@ VECTOR_END(MIPSX(exceptionEnd))
/*
* Generic Guest exception handler. We end up here when the guest
* does something that causes a trap to kernel mode.
- *
*/
NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
/* Get the VCPU pointer from DDTATA_LO */
@@ -290,9 +292,7 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
LONG_S $30, VCPU_R30(k1)
LONG_S $31, VCPU_R31(k1)
- /* We need to save hi/lo and restore them on
- * the way out
- */
+ /* We need to save hi/lo and restore them on the way out */
mfhi t0
LONG_S t0, VCPU_HI(k1)
@@ -321,8 +321,10 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
/* Save pointer to run in s0, will be saved by the compiler */
move s0, a0
- /* Save Host level EPC, BadVaddr and Cause to VCPU, useful to
- * process the exception */
+ /*
+ * Save Host level EPC, BadVaddr and Cause to VCPU, useful to
+ * process the exception
+ */
mfc0 k0,CP0_EPC
LONG_S k0, VCPU_PC(k1)
@@ -351,7 +353,6 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
LONG_L k0, VCPU_HOST_EBASE(k1)
mtc0 k0,CP0_EBASE
-
/* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
.set at
and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
@@ -369,7 +370,8 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
/* Saved host state */
INT_ADDIU sp, sp, -PT_SIZE
- /* XXXKYMA do we need to load the host ASID, maybe not because the
+ /*
+ * XXXKYMA do we need to load the host ASID, maybe not because the
* kernel entries are marked GLOBAL, need to verify
*/
@@ -383,9 +385,11 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
/* Jump to handler */
FEXPORT(__kvm_mips_jump_to_handler)
- /* XXXKYMA: not sure if this is safe, how large is the stack??
+ /*
+ * XXXKYMA: not sure if this is safe, how large is the stack??
* Now jump to the kvm_mips_handle_exit() to see if we can deal
- * with this in the kernel */
+ * with this in the kernel
+ */
PTR_LA t9, kvm_mips_handle_exit
jalr.hb t9
INT_ADDIU sp, sp, -CALLFRAME_SIZ /* BD Slot */
@@ -394,7 +398,8 @@ FEXPORT(__kvm_mips_jump_to_handler)
di
ehb
- /* XXXKYMA: k0/k1 could have been blown away if we processed
+ /*
+ * XXXKYMA: k0/k1 could have been blown away if we processed
* an exception while we were handling the exception from the
* guest, reload k1
*/
@@ -402,7 +407,8 @@ FEXPORT(__kvm_mips_jump_to_handler)
move k1, s1
INT_ADDIU k1, k1, VCPU_HOST_ARCH
- /* Check return value, should tell us if we are returning to the
+ /*
+ * Check return value, should tell us if we are returning to the
* host (handle I/O etc)or resuming the guest
*/
andi t0, v0, RESUME_HOST
@@ -521,8 +527,10 @@ __kvm_mips_return_to_host:
LONG_L $0, PT_R0(k1)
LONG_L $1, PT_R1(k1)
- /* r2/v0 is the return code, shift it down by 2 (arithmetic)
- * to recover the err code */
+ /*
+ * r2/v0 is the return code, shift it down by 2 (arithmetic)
+ * to recover the err code
+ */
INT_SRA k0, v0, 2
move $2, k0
@@ -566,7 +574,6 @@ __kvm_mips_return_to_host:
PTR_LI k0, 0x2000000F
mtc0 k0, CP0_HWRENA
-
/* Restore RA, which is the address we will return to */
LONG_L ra, PT_R31(k1)
j ra
diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/mips.c
index f3c56a182fd8..cd7114147ae7 100644
--- a/arch/mips/kvm/kvm_mips.c
+++ b/arch/mips/kvm/mips.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ */
#include <linux/errno.h>
#include <linux/err.h>
@@ -21,8 +21,8 @@
#include <linux/kvm_host.h>
-#include "kvm_mips_int.h"
-#include "kvm_mips_comm.h"
+#include "interrupt.h"
+#include "commpage.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -31,38 +31,41 @@
#define VECTORSPACING 0x100 /* for EI/VI mode */
#endif
-#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
+#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x)
struct kvm_stats_debugfs_item debugfs_entries[] = {
- { "wait", VCPU_STAT(wait_exits) },
- { "cache", VCPU_STAT(cache_exits) },
- { "signal", VCPU_STAT(signal_exits) },
- { "interrupt", VCPU_STAT(int_exits) },
- { "cop_unsuable", VCPU_STAT(cop_unusable_exits) },
- { "tlbmod", VCPU_STAT(tlbmod_exits) },
- { "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits) },
- { "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits) },
- { "addrerr_st", VCPU_STAT(addrerr_st_exits) },
- { "addrerr_ld", VCPU_STAT(addrerr_ld_exits) },
- { "syscall", VCPU_STAT(syscall_exits) },
- { "resvd_inst", VCPU_STAT(resvd_inst_exits) },
- { "break_inst", VCPU_STAT(break_inst_exits) },
- { "flush_dcache", VCPU_STAT(flush_dcache_exits) },
- { "halt_wakeup", VCPU_STAT(halt_wakeup) },
+ { "wait", VCPU_STAT(wait_exits), KVM_STAT_VCPU },
+ { "cache", VCPU_STAT(cache_exits), KVM_STAT_VCPU },
+ { "signal", VCPU_STAT(signal_exits), KVM_STAT_VCPU },
+ { "interrupt", VCPU_STAT(int_exits), KVM_STAT_VCPU },
+ { "cop_unsuable", VCPU_STAT(cop_unusable_exits), KVM_STAT_VCPU },
+ { "tlbmod", VCPU_STAT(tlbmod_exits), KVM_STAT_VCPU },
+ { "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits), KVM_STAT_VCPU },
+ { "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits), KVM_STAT_VCPU },
+ { "addrerr_st", VCPU_STAT(addrerr_st_exits), KVM_STAT_VCPU },
+ { "addrerr_ld", VCPU_STAT(addrerr_ld_exits), KVM_STAT_VCPU },
+ { "syscall", VCPU_STAT(syscall_exits), KVM_STAT_VCPU },
+ { "resvd_inst", VCPU_STAT(resvd_inst_exits), KVM_STAT_VCPU },
+ { "break_inst", VCPU_STAT(break_inst_exits), KVM_STAT_VCPU },
+ { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
+ { "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU },
{NULL}
};
static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu)
{
int i;
+
for_each_possible_cpu(i) {
vcpu->arch.guest_kernel_asid[i] = 0;
vcpu->arch.guest_user_asid[i] = 0;
}
+
return 0;
}
-/* XXXKYMA: We are simulatoring a processor that has the WII bit set in Config7, so we
- * are "runnable" if interrupts are pending
+/*
+ * XXXKYMA: We are simulatoring a processor that has the WII bit set in
+ * Config7, so we are "runnable" if interrupts are pending
*/
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
@@ -94,16 +97,17 @@ void kvm_arch_hardware_unsetup(void)
void kvm_arch_check_processor_compat(void *rtn)
{
- int *r = (int *)rtn;
- *r = 0;
- return;
+ *(int *)rtn = 0;
}
static void kvm_mips_init_tlbs(struct kvm *kvm)
{
unsigned long wired;
- /* Add a wired entry to the TLB, it is used to map the commpage to the Guest kernel */
+ /*
+ * Add a wired entry to the TLB, it is used to map the commpage to
+ * the Guest kernel
+ */
wired = read_c0_wired();
write_c0_wired(wired + 1);
mtc0_tlbw_hazard();
@@ -130,7 +134,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1);
}
-
return 0;
}
@@ -185,8 +188,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
}
}
-long
-kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+long kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl,
+ unsigned long arg)
{
return -ENOIOCTLCMD;
}
@@ -207,20 +210,20 @@ void kvm_arch_memslots_updated(struct kvm *kvm)
}
int kvm_arch_prepare_memory_region(struct kvm *kvm,
- struct kvm_memory_slot *memslot,
- struct kvm_userspace_memory_region *mem,
- enum kvm_mr_change change)
+ struct kvm_memory_slot *memslot,
+ struct kvm_userspace_memory_region *mem,
+ enum kvm_mr_change change)
{
return 0;
}
void kvm_arch_commit_memory_region(struct kvm *kvm,
- struct kvm_userspace_memory_region *mem,
- const struct kvm_memory_slot *old,
- enum kvm_mr_change change)
+ struct kvm_userspace_memory_region *mem,
+ const struct kvm_memory_slot *old,
+ enum kvm_mr_change change)
{
unsigned long npages = 0;
- int i, err = 0;
+ int i;
kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n",
__func__, kvm, mem->slot, mem->guest_phys_addr,
@@ -238,21 +241,17 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
if (!kvm->arch.guest_pmap) {
kvm_err("Failed to allocate guest PMAP");
- err = -ENOMEM;
- goto out;
+ return;
}
kvm_debug("Allocated space for Guest PMAP Table (%ld pages) @ %p\n",
npages, kvm->arch.guest_pmap);
/* Now setup the page table */
- for (i = 0; i < npages; i++) {
+ for (i = 0; i < npages; i++)
kvm->arch.guest_pmap[i] = KVM_INVALID_PAGE;
- }
}
}
-out:
- return;
}
void kvm_arch_flush_shadow_all(struct kvm *kvm)
@@ -270,8 +269,6 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
- extern char mips32_exception[], mips32_exceptionEnd[];
- extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
int err, size, offset;
void *gebase;
int i;
@@ -290,14 +287,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
kvm_debug("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu);
- /* Allocate space for host mode exception handlers that handle
+ /*
+ * Allocate space for host mode exception handlers that handle
* guest mode exits
*/
- if (cpu_has_veic || cpu_has_vint) {
+ if (cpu_has_veic || cpu_has_vint)
size = 0x200 + VECTORSPACING * 64;
- } else {
+ else
size = 0x4000;
- }
/* Save Linux EBASE */
vcpu->arch.host_ebase = (void *)read_c0_ebase();
@@ -345,7 +342,10 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
local_flush_icache_range((unsigned long)gebase,
(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
- /* Allocate comm page for guest kernel, a TLB will be reserved for mapping GVA @ 0xFFFF8000 to this page */
+ /*
+ * Allocate comm page for guest kernel, a TLB will be reserved for
+ * mapping GVA @ 0xFFFF8000 to this page
+ */
vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL);
if (!vcpu->arch.kseg0_commpage) {
@@ -392,9 +392,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
kvm_arch_vcpu_free(vcpu);
}
-int
-kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
- struct kvm_guest_debug *dbg)
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+ struct kvm_guest_debug *dbg)
{
return -ENOIOCTLCMD;
}
@@ -431,8 +430,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
return r;
}
-int
-kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
+int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
+ struct kvm_mips_interrupt *irq)
{
int intr = (int)irq->irq;
struct kvm_vcpu *dvcpu = NULL;
@@ -459,23 +458,20 @@ kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq)
dvcpu->arch.wait = 0;
- if (waitqueue_active(&dvcpu->wq)) {
+ if (waitqueue_active(&dvcpu->wq))
wake_up_interruptible(&dvcpu->wq);
- }
return 0;
}
-int
-kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
- struct kvm_mp_state *mp_state)
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
{
return -ENOIOCTLCMD;
}
-int
-kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
- struct kvm_mp_state *mp_state)
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
{
return -ENOIOCTLCMD;
}
@@ -632,10 +628,12 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
}
if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
u64 __user *uaddr64 = (u64 __user *)(long)reg->addr;
+
return put_user(v, uaddr64);
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32) {
u32 __user *uaddr32 = (u32 __user *)(long)reg->addr;
u32 v32 = (u32)v;
+
return put_user(v32, uaddr32);
} else {
return -EINVAL;
@@ -728,8 +726,8 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
return 0;
}
-long
-kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
+ unsigned long arg)
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
@@ -739,6 +737,7 @@ kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
case KVM_SET_ONE_REG:
case KVM_GET_ONE_REG: {
struct kvm_one_reg reg;
+
if (copy_from_user(&reg, argp, sizeof(reg)))
return -EFAULT;
if (ioctl == KVM_SET_ONE_REG)
@@ -773,6 +772,7 @@ kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
case KVM_INTERRUPT:
{
struct kvm_mips_interrupt irq;
+
r = -EFAULT;
if (copy_from_user(&irq, argp, sizeof(irq)))
goto out;
@@ -791,9 +791,7 @@ out:
return r;
}
-/*
- * Get (and clear) the dirty memory log for a memory slot.
- */
+/* Get (and clear) the dirty memory log for a memory slot. */
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
{
struct kvm_memory_slot *memslot;
@@ -815,8 +813,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
ga = memslot->base_gfn << PAGE_SHIFT;
ga_end = ga + (memslot->npages << PAGE_SHIFT);
- printk("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga,
- ga_end);
+ kvm_info("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga,
+ ga_end);
n = kvm_dirty_bitmap_bytes(memslot);
memset(memslot->dirty_bitmap, 0, n);
@@ -843,16 +841,12 @@ long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
int kvm_arch_init(void *opaque)
{
- int ret;
-
if (kvm_mips_callbacks) {
kvm_err("kvm: module already exists\n");
return -EEXIST;
}
- ret = kvm_mips_emulation_init(&kvm_mips_callbacks);
-
- return ret;
+ return kvm_mips_emulation_init(&kvm_mips_callbacks);
}
void kvm_arch_exit(void)
@@ -860,14 +854,14 @@ void kvm_arch_exit(void)
kvm_mips_callbacks = NULL;
}
-int
-kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
{
return -ENOIOCTLCMD;
}
-int
-kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
{
return -ENOIOCTLCMD;
}
@@ -892,7 +886,7 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
@@ -923,24 +917,25 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu)
if (!vcpu)
return -1;
- printk("VCPU Register Dump:\n");
- printk("\tpc = 0x%08lx\n", vcpu->arch.pc);
- printk("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
+ kvm_debug("VCPU Register Dump:\n");
+ kvm_debug("\tpc = 0x%08lx\n", vcpu->arch.pc);
+ kvm_debug("\texceptions: %08lx\n", vcpu->arch.pending_exceptions);
for (i = 0; i < 32; i += 4) {
- printk("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i,
+ kvm_debug("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i,
vcpu->arch.gprs[i],
vcpu->arch.gprs[i + 1],
vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]);
}
- printk("\thi: 0x%08lx\n", vcpu->arch.hi);
- printk("\tlo: 0x%08lx\n", vcpu->arch.lo);
+ kvm_debug("\thi: 0x%08lx\n", vcpu->arch.hi);
+ kvm_debug("\tlo: 0x%08lx\n", vcpu->arch.lo);
cop0 = vcpu->arch.cop0;
- printk("\tStatus: 0x%08lx, Cause: 0x%08lx\n",
- kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0));
+ kvm_debug("\tStatus: 0x%08lx, Cause: 0x%08lx\n",
+ kvm_read_c0_guest_status(cop0),
+ kvm_read_c0_guest_cause(cop0));
- printk("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0));
+ kvm_debug("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0));
return 0;
}
@@ -980,14 +975,11 @@ static void kvm_mips_comparecount_func(unsigned long data)
kvm_mips_callbacks->queue_timer_int(vcpu);
vcpu->arch.wait = 0;
- if (waitqueue_active(&vcpu->wq)) {
+ if (waitqueue_active(&vcpu->wq))
wake_up_interruptible(&vcpu->wq);
- }
}
-/*
- * low level hrtimer wake routine.
- */
+/* low level hrtimer wake routine */
static enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer)
{
struct kvm_vcpu *vcpu;
@@ -1008,11 +1000,10 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{
- return;
}
-int
-kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, struct kvm_translation *tr)
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+ struct kvm_translation *tr)
{
return 0;
}
@@ -1023,8 +1014,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
return kvm_mips_callbacks->vcpu_setup(vcpu);
}
-static
-void kvm_mips_set_c0_status(void)
+static void kvm_mips_set_c0_status(void)
{
uint32_t status = read_c0_status();
@@ -1054,7 +1044,10 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
run->exit_reason = KVM_EXIT_UNKNOWN;
run->ready_for_interrupt_injection = 1;
- /* Set the appropriate status bits based on host CPU features, before we hit the scheduler */
+ /*
+ * Set the appropriate status bits based on host CPU features,
+ * before we hit the scheduler
+ */
kvm_mips_set_c0_status();
local_irq_enable();
@@ -1062,7 +1055,8 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n",
cause, opc, run, vcpu);
- /* Do a privilege check, if in UM most of these exit conditions end up
+ /*
+ * Do a privilege check, if in UM most of these exit conditions end up
* causing an exception to be delivered to the Guest Kernel
*/
er = kvm_mips_check_privilege(cause, opc, run, vcpu);
@@ -1081,9 +1075,8 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
++vcpu->stat.int_exits;
trace_kvm_exit(vcpu, INT_EXITS);
- if (need_resched()) {
+ if (need_resched())
cond_resched();
- }
ret = RESUME_GUEST;
break;
@@ -1095,9 +1088,8 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS);
ret = kvm_mips_callbacks->handle_cop_unusable(vcpu);
/* XXXKYMA: Might need to return to user space */
- if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN) {
+ if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN)
ret = RESUME_HOST;
- }
break;
case T_TLB_MOD:
@@ -1107,10 +1099,9 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
break;
case T_TLB_ST_MISS:
- kvm_debug
- ("TLB ST fault: cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
- badvaddr);
+ kvm_debug("TLB ST fault: cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
+ badvaddr);
++vcpu->stat.tlbmiss_st_exits;
trace_kvm_exit(vcpu, TLBMISS_ST_EXITS);
@@ -1157,10 +1148,9 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
break;
default:
- kvm_err
- ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n",
- exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
- kvm_read_c0_guest_status(vcpu->arch.cop0));
+ kvm_err("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n",
+ exccode, opc, kvm_get_inst(opc, vcpu), badvaddr,
+ kvm_read_c0_guest_status(vcpu->arch.cop0));
kvm_arch_vcpu_dump_regs(vcpu);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
@@ -1175,7 +1165,7 @@ skip_emul:
kvm_mips_deliver_interrupts(vcpu, cause);
if (!(ret & RESUME_HOST)) {
- /* Only check for signals if not already exiting to userspace */
+ /* Only check for signals if not already exiting to userspace */
if (signal_pending(current)) {
run->exit_reason = KVM_EXIT_INTR;
ret = (-EINTR << 2) | RESUME_HOST;
@@ -1196,11 +1186,13 @@ int __init kvm_mips_init(void)
if (ret)
return ret;
- /* On MIPS, kernel modules are executed from "mapped space", which requires TLBs.
- * The TLB handling code is statically linked with the rest of the kernel (kvm_tlb.c)
- * to avoid the possibility of double faulting. The issue is that the TLB code
- * references routines that are part of the the KVM module,
- * which are only available once the module is loaded.
+ /*
+ * On MIPS, kernel modules are executed from "mapped space", which
+ * requires TLBs. The TLB handling code is statically linked with
+ * the rest of the kernel (tlb.c) to avoid the possibility of
+ * double faulting. The issue is that the TLB code references
+ * routines that are part of the the KVM module, which are only
+ * available once the module is loaded.
*/
kvm_mips_gfn_to_pfn = gfn_to_pfn;
kvm_mips_release_pfn_clean = kvm_release_pfn_clean;
diff --git a/arch/mips/kvm/opcode.h b/arch/mips/kvm/opcode.h
new file mode 100644
index 000000000000..03a6ae84c7df
--- /dev/null
+++ b/arch/mips/kvm/opcode.h
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
+
+/* Define opcode values not defined in <asm/isnt.h> */
+
+#ifndef __KVM_MIPS_OPCODE_H__
+#define __KVM_MIPS_OPCODE_H__
+
+/* COP0 Ops */
+#define mfmcz_op 0x0b /* 01011 */
+#define wrpgpr_op 0x0e /* 01110 */
+
+/* COP0 opcodes (only if COP0 and CO=1): */
+#define wait_op 0x20 /* 100000 */
+
+#endif /* __KVM_MIPS_OPCODE_H__ */
diff --git a/arch/mips/kvm/kvm_mips_stats.c b/arch/mips/kvm/stats.c
index 075904bcac1b..a74d6024c5ad 100644
--- a/arch/mips/kvm/kvm_mips_stats.c
+++ b/arch/mips/kvm/stats.c
@@ -1,13 +1,13 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: COP0 access histogram
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: COP0 access histogram
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/kvm_host.h>
@@ -63,20 +63,18 @@ char *kvm_cop0_str[N_MIPS_COPROC_REGS] = {
"DESAVE"
};
-int kvm_mips_dump_stats(struct kvm_vcpu *vcpu)
+void kvm_mips_dump_stats(struct kvm_vcpu *vcpu)
{
#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS
int i, j;
- printk("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id);
+ kvm_info("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id);
for (i = 0; i < N_MIPS_COPROC_REGS; i++) {
for (j = 0; j < N_MIPS_COPROC_SEL; j++) {
if (vcpu->arch.cop0->stat[i][j])
- printk("%s[%d]: %lu\n", kvm_cop0_str[i], j,
- vcpu->arch.cop0->stat[i][j]);
+ kvm_info("%s[%d]: %lu\n", kvm_cop0_str[i], j,
+ vcpu->arch.cop0->stat[i][j]);
}
}
#endif
-
- return 0;
}
diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/tlb.c
index 8a5a700ad8de..bbcd82242059 100644
--- a/arch/mips/kvm/kvm_tlb.c
+++ b/arch/mips/kvm/tlb.c
@@ -1,14 +1,14 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
-* TLB handlers run from KSEG0
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS TLB handling, this file is part of the Linux host kernel so that
+ * TLB handlers run from KSEG0
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/sched.h>
#include <linux/smp.h>
@@ -18,7 +18,6 @@
#include <linux/kvm_host.h>
#include <linux/srcu.h>
-
#include <asm/cpu.h>
#include <asm/bootinfo.h>
#include <asm/mmu_context.h>
@@ -39,13 +38,13 @@ atomic_t kvm_mips_instance;
EXPORT_SYMBOL(kvm_mips_instance);
/* These function pointers are initialized once the KVM module is loaded */
-pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn);
+pfn_t (*kvm_mips_gfn_to_pfn)(struct kvm *kvm, gfn_t gfn);
EXPORT_SYMBOL(kvm_mips_gfn_to_pfn);
-void (*kvm_mips_release_pfn_clean) (pfn_t pfn);
+void (*kvm_mips_release_pfn_clean)(pfn_t pfn);
EXPORT_SYMBOL(kvm_mips_release_pfn_clean);
-bool(*kvm_mips_is_error_pfn) (pfn_t pfn);
+bool (*kvm_mips_is_error_pfn)(pfn_t pfn);
EXPORT_SYMBOL(kvm_mips_is_error_pfn);
uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
@@ -53,21 +52,17 @@ uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
}
-
uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
{
return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
}
-inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
+inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu)
{
return vcpu->kvm->arch.commpage_tlb;
}
-
-/*
- * Structure defining an tlb entry data set.
- */
+/* Structure defining an tlb entry data set. */
void kvm_mips_dump_host_tlbs(void)
{
@@ -82,8 +77,8 @@ void kvm_mips_dump_host_tlbs(void)
old_entryhi = read_c0_entryhi();
old_pagemask = read_c0_pagemask();
- printk("HOST TLBs:\n");
- printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
+ kvm_info("HOST TLBs:\n");
+ kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
for (i = 0; i < current_cpu_data.tlbsize; i++) {
write_c0_index(i);
@@ -97,25 +92,26 @@ void kvm_mips_dump_host_tlbs(void)
tlb.tlb_lo1 = read_c0_entrylo1();
tlb.tlb_mask = read_c0_pagemask();
- printk("TLB%c%3d Hi 0x%08lx ",
- (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
- i, tlb.tlb_hi);
- printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
- (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo0 >> 3) & 7);
- printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
- (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+ kvm_info("TLB%c%3d Hi 0x%08lx ",
+ (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+ i, tlb.tlb_hi);
+ kvm_info("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+ (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+ (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+ (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+ (tlb.tlb_lo0 >> 3) & 7);
+ kvm_info("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+ (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+ (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+ (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+ (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
}
write_c0_entryhi(old_entryhi);
write_c0_pagemask(old_pagemask);
mtc0_tlbw_hazard();
local_irq_restore(flags);
}
+EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
{
@@ -123,26 +119,27 @@ void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
struct kvm_mips_tlb tlb;
int i;
- printk("Guest TLBs:\n");
- printk("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
+ kvm_info("Guest TLBs:\n");
+ kvm_info("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0));
for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
tlb = vcpu->arch.guest_tlb[i];
- printk("TLB%c%3d Hi 0x%08lx ",
- (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
- i, tlb.tlb_hi);
- printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
- (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo0 >> 3) & 7);
- printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
- (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
- (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
- (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
- (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
+ kvm_info("TLB%c%3d Hi 0x%08lx ",
+ (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
+ i, tlb.tlb_hi);
+ kvm_info("Lo0=0x%09" PRIx64 " %c%c attr %lx ",
+ (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0),
+ (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
+ (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
+ (tlb.tlb_lo0 >> 3) & 7);
+ kvm_info("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n",
+ (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1),
+ (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
+ (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
+ (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
}
}
+EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
{
@@ -152,7 +149,7 @@ static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)
return 0;
- srcu_idx = srcu_read_lock(&kvm->srcu);
+ srcu_idx = srcu_read_lock(&kvm->srcu);
pfn = kvm_mips_gfn_to_pfn(kvm, gfn);
if (kvm_mips_is_error_pfn(pfn)) {
@@ -169,7 +166,7 @@ out:
/* Translate guest KSEG0 addresses to Host PA */
unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
- unsigned long gva)
+ unsigned long gva)
{
gfn_t gfn;
uint32_t offset = gva & ~PAGE_MASK;
@@ -194,20 +191,20 @@ unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
}
+EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
/* XXXKYMA: Must be called with interrupts disabled */
/* set flush_dcache_mask == 0 if no dcache flush required */
-int
-kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
- unsigned long entrylo0, unsigned long entrylo1, int flush_dcache_mask)
+int kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
+ unsigned long entrylo0, unsigned long entrylo1,
+ int flush_dcache_mask)
{
unsigned long flags;
unsigned long old_entryhi;
- volatile int idx;
+ int idx;
local_irq_save(flags);
-
old_entryhi = read_c0_entryhi();
write_c0_entryhi(entryhi);
mtc0_tlbw_hazard();
@@ -240,12 +237,14 @@ kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
if (flush_dcache_mask) {
if (entrylo0 & MIPS3_PG_V) {
++vcpu->stat.flush_dcache_exits;
- flush_data_cache_page((entryhi & VPN2_MASK) & ~flush_dcache_mask);
+ flush_data_cache_page((entryhi & VPN2_MASK) &
+ ~flush_dcache_mask);
}
if (entrylo1 & MIPS3_PG_V) {
++vcpu->stat.flush_dcache_exits;
- flush_data_cache_page(((entryhi & VPN2_MASK) & ~flush_dcache_mask) |
- (0x1 << PAGE_SHIFT));
+ flush_data_cache_page(((entryhi & VPN2_MASK) &
+ ~flush_dcache_mask) |
+ (0x1 << PAGE_SHIFT));
}
}
@@ -257,10 +256,9 @@ kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi,
return 0;
}
-
/* XXXKYMA: Must be called with interrupts disabled */
int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
- struct kvm_vcpu *vcpu)
+ struct kvm_vcpu *vcpu)
{
gfn_t gfn;
pfn_t pfn0, pfn1;
@@ -270,7 +268,6 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
struct kvm *kvm = vcpu->kvm;
const int flush_dcache_mask = 0;
-
if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) {
kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr);
kvm_mips_dump_host_tlbs();
@@ -302,14 +299,15 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
}
entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
- entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
- (0x1 << 1);
- entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
- (0x1 << 1);
+ entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+ (1 << 2) | (0x1 << 1);
+ entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
+ (1 << 2) | (0x1 << 1);
return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
flush_dcache_mask);
}
+EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
struct kvm_vcpu *vcpu)
@@ -318,11 +316,10 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
unsigned long flags, old_entryhi = 0, vaddr = 0;
unsigned long entrylo0 = 0, entrylo1 = 0;
-
pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
pfn1 = 0;
- entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) |
- (0x1 << 1);
+ entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
+ (1 << 2) | (0x1 << 1);
entrylo1 = 0;
local_irq_save(flags);
@@ -341,9 +338,9 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
mtc0_tlbw_hazard();
tlbw_use_hazard();
- kvm_debug ("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
- vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
- read_c0_entrylo0(), read_c0_entrylo1());
+ kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n",
+ vcpu->arch.pc, read_c0_index(), read_c0_entryhi(),
+ read_c0_entrylo0(), read_c0_entrylo1());
/* Restore old ASID */
write_c0_entryhi(old_entryhi);
@@ -353,28 +350,33 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
return 0;
}
+EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
-int
-kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
- struct kvm_mips_tlb *tlb, unsigned long *hpa0, unsigned long *hpa1)
+int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
+ struct kvm_mips_tlb *tlb,
+ unsigned long *hpa0,
+ unsigned long *hpa1)
{
unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
struct kvm *kvm = vcpu->kvm;
pfn_t pfn0, pfn1;
-
if ((tlb->tlb_hi & VPN2_MASK) == 0) {
pfn0 = 0;
pfn1 = 0;
} else {
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT) < 0)
+ if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
+ >> PAGE_SHIFT) < 0)
return -1;
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT) < 0)
+ if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
+ >> PAGE_SHIFT) < 0)
return -1;
- pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT];
- pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT];
+ pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
+ >> PAGE_SHIFT];
+ pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
+ >> PAGE_SHIFT];
}
if (hpa0)
@@ -385,11 +387,12 @@ kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
/* Get attributes from the Guest TLB */
entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
- kvm_mips_get_kernel_asid(vcpu) : kvm_mips_get_user_asid(vcpu));
+ kvm_mips_get_kernel_asid(vcpu) :
+ kvm_mips_get_user_asid(vcpu));
entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
- (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
+ (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
- (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
+ (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
tlb->tlb_lo0, tlb->tlb_lo1);
@@ -397,6 +400,7 @@ kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
tlb->tlb_mask);
}
+EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
{
@@ -404,10 +408,9 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
int index = -1;
struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb;
-
for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
- if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
- (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) {
+ if (TLB_HI_VPN2_HIT(tlb[i], entryhi) &&
+ TLB_HI_ASID_HIT(tlb[i], entryhi)) {
index = i;
break;
}
@@ -418,21 +421,23 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
return index;
}
+EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
{
unsigned long old_entryhi, flags;
- volatile int idx;
-
+ int idx;
local_irq_save(flags);
old_entryhi = read_c0_entryhi();
if (KVM_GUEST_KERNEL_MODE(vcpu))
- write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_kernel_asid(vcpu));
+ write_c0_entryhi((vaddr & VPN2_MASK) |
+ kvm_mips_get_kernel_asid(vcpu));
else {
- write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
+ write_c0_entryhi((vaddr & VPN2_MASK) |
+ kvm_mips_get_user_asid(vcpu));
}
mtc0_tlbw_hazard();
@@ -452,6 +457,7 @@ int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
return idx;
}
+EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
{
@@ -460,7 +466,6 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
local_irq_save(flags);
-
old_entryhi = read_c0_entryhi();
write_c0_entryhi((va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu));
@@ -499,8 +504,9 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
return 0;
}
+EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
-/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID*/
+/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID */
int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
{
unsigned long flags, old_entryhi;
@@ -510,7 +516,6 @@ int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
local_irq_save(flags);
-
old_entryhi = read_c0_entryhi();
write_c0_entryhi(UNIQUE_ENTRYHI(index));
@@ -546,7 +551,6 @@ void kvm_mips_flush_host_tlb(int skip_kseg0)
int entry = 0;
int maxentry = current_cpu_data.tlbsize;
-
local_irq_save(flags);
old_entryhi = read_c0_entryhi();
@@ -554,7 +558,6 @@ void kvm_mips_flush_host_tlb(int skip_kseg0)
/* Blast 'em all away. */
for (entry = 0; entry < maxentry; entry++) {
-
write_c0_index(entry);
mtc0_tlbw_hazard();
@@ -565,9 +568,8 @@ void kvm_mips_flush_host_tlb(int skip_kseg0)
entryhi = read_c0_entryhi();
/* Don't blow away guest kernel entries */
- if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0) {
+ if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0)
continue;
- }
}
/* Make sure all entries differ. */
@@ -591,17 +593,17 @@ void kvm_mips_flush_host_tlb(int skip_kseg0)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
-void
-kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
- struct kvm_vcpu *vcpu)
+void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
+ struct kvm_vcpu *vcpu)
{
unsigned long asid = asid_cache(cpu);
- if (!((asid += ASID_INC) & ASID_MASK)) {
- if (cpu_has_vtag_icache) {
+ asid += ASID_INC;
+ if (!(asid & ASID_MASK)) {
+ if (cpu_has_vtag_icache)
flush_icache_all();
- }
kvm_local_flush_tlb_all(); /* start new asid cycle */
@@ -639,6 +641,7 @@ void kvm_local_flush_tlb_all(void)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(kvm_local_flush_tlb_all);
/**
* kvm_mips_migrate_count() - Migrate timer.
@@ -699,7 +702,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
}
if (!newasid) {
- /* If we preempted while the guest was executing, then reload the pre-empted ASID */
+ /*
+ * If we preempted while the guest was executing, then reload
+ * the pre-empted ASID
+ */
if (current->flags & PF_VCPU) {
write_c0_entryhi(vcpu->arch.
preempt_entryhi & ASID_MASK);
@@ -708,9 +714,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
} else {
/* New ASIDs were allocated for the VM */
- /* Were we in guest context? If so then the pre-empted ASID is no longer
- * valid, we need to set it to what it should be based on the mode of
- * the Guest (Kernel/User)
+ /*
+ * Were we in guest context? If so then the pre-empted ASID is
+ * no longer valid, we need to set it to what it should be based
+ * on the mode of the Guest (Kernel/User)
*/
if (current->flags & PF_VCPU) {
if (KVM_GUEST_KERNEL_MODE(vcpu))
@@ -728,6 +735,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(kvm_arch_vcpu_load);
/* ASID can change if another task is scheduled during preemption */
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -739,7 +747,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
cpu = smp_processor_id();
-
vcpu->arch.preempt_entryhi = read_c0_entryhi();
vcpu->arch.last_sched_cpu = cpu;
@@ -754,11 +761,12 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
local_irq_restore(flags);
}
+EXPORT_SYMBOL(kvm_arch_vcpu_put);
uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
- unsigned long paddr, flags;
+ unsigned long paddr, flags, vpn2, asid;
uint32_t inst;
int index;
@@ -769,16 +777,12 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
if (index >= 0) {
inst = *(opc);
} else {
- index =
- kvm_mips_guest_tlb_lookup(vcpu,
- ((unsigned long) opc & VPN2_MASK)
- |
- (kvm_read_c0_guest_entryhi
- (cop0) & ASID_MASK));
+ vpn2 = (unsigned long) opc & VPN2_MASK;
+ asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK;
+ index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
if (index < 0) {
- kvm_err
- ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
- __func__, opc, vcpu, read_c0_entryhi());
+ kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
+ __func__, opc, vcpu, read_c0_entryhi());
kvm_mips_dump_host_tlbs();
local_irq_restore(flags);
return KVM_INVALID_INST;
@@ -793,7 +797,7 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
} else if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
paddr =
kvm_mips_translate_guest_kseg0_to_hpa(vcpu,
- (unsigned long) opc);
+ (unsigned long) opc);
inst = *(uint32_t *) CKSEG0ADDR(paddr);
} else {
kvm_err("%s: illegal address: %p\n", __func__, opc);
@@ -802,18 +806,4 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
return inst;
}
-
-EXPORT_SYMBOL(kvm_local_flush_tlb_all);
-EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
-EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
-EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
-EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
-EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
-EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
-EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
-EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
EXPORT_SYMBOL(kvm_get_inst);
-EXPORT_SYMBOL(kvm_arch_vcpu_load);
-EXPORT_SYMBOL(kvm_arch_vcpu_put);
diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h
index bc9e0f406c08..c1388d40663b 100644
--- a/arch/mips/kvm/trace.h
+++ b/arch/mips/kvm/trace.h
@@ -1,11 +1,11 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_KVM_H
@@ -17,9 +17,7 @@
#define TRACE_INCLUDE_PATH .
#define TRACE_INCLUDE_FILE trace
-/*
- * Tracepoints for VM eists
- */
+/* Tracepoints for VM eists */
extern char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES];
TRACE_EVENT(kvm_exit,
diff --git a/arch/mips/kvm/kvm_trap_emul.c b/arch/mips/kvm/trap_emul.c
index 693f952b2fbb..fd7257b70e65 100644
--- a/arch/mips/kvm/kvm_trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -1,13 +1,13 @@
/*
-* This file is subject to the terms and conditions of the GNU General Public
-* License. See the file "COPYING" in the main directory of this archive
-* for more details.
-*
-* KVM/MIPS: Deliver/Emulate exceptions to the guest kernel
-*
-* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
-* Authors: Sanjay Lal <sanjayl@kymasys.com>
-*/
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * KVM/MIPS: Deliver/Emulate exceptions to the guest kernel
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Authors: Sanjay Lal <sanjayl@kymasys.com>
+ */
#include <linux/errno.h>
#include <linux/err.h>
@@ -16,8 +16,8 @@
#include <linux/kvm_host.h>
-#include "kvm_mips_opcode.h"
-#include "kvm_mips_int.h"
+#include "opcode.h"
+#include "interrupt.h"
static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
{
@@ -27,7 +27,7 @@ static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
if ((kseg == CKSEG0) || (kseg == CKSEG1))
gpa = CPHYSADDR(gva);
else {
- printk("%s: cannot find GPA for GVA: %#lx\n", __func__, gva);
+ kvm_err("%s: cannot find GPA for GVA: %#lx\n", __func__, gva);
kvm_mips_dump_host_tlbs();
gpa = KVM_INVALID_ADDR;
}
@@ -37,7 +37,6 @@ static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
return gpa;
}
-
static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
{
struct kvm_run *run = vcpu->run;
@@ -46,9 +45,9 @@ static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu)
enum emulation_result er = EMULATE_DONE;
int ret = RESUME_GUEST;
- if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) {
+ if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1)
er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu);
- } else
+ else
er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
switch (er) {
@@ -83,9 +82,8 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
|| KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
- kvm_debug
- ("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_debug("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu);
if (er == EMULATE_DONE)
@@ -95,20 +93,20 @@ static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
- /* XXXKYMA: The guest kernel does not expect to get this fault when we are not
- * using HIGHMEM. Need to address this in a HIGHMEM kernel
+ /*
+ * XXXKYMA: The guest kernel does not expect to get this fault
+ * when we are not using HIGHMEM. Need to address this in a
+ * HIGHMEM kernel
*/
- printk
- ("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
kvm_mips_dump_host_tlbs();
kvm_arch_vcpu_dump_regs(vcpu);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
} else {
- printk
- ("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
kvm_mips_dump_host_tlbs();
kvm_arch_vcpu_dump_regs(vcpu);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -134,9 +132,8 @@ static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
}
} else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0
|| KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) {
- kvm_debug
- ("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_debug("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
if (er == EMULATE_DONE)
ret = RESUME_GUEST;
@@ -145,8 +142,9 @@ static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) {
- /* All KSEG0 faults are handled by KVM, as the guest kernel does not
- * expect to ever get them
+ /*
+ * All KSEG0 faults are handled by KVM, as the guest kernel does
+ * not expect to ever get them
*/
if (kvm_mips_handle_kseg0_tlb_fault
(vcpu->arch.host_cp0_badvaddr, vcpu) < 0) {
@@ -154,9 +152,8 @@ static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else {
- kvm_err
- ("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
kvm_mips_dump_host_tlbs();
kvm_arch_vcpu_dump_regs(vcpu);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -185,11 +182,14 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n",
vcpu->arch.pc, badvaddr);
- /* User Address (UA) fault, this could happen if
- * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this
- * case we pass on the fault to the guest kernel and let it handle it.
- * (2) TLB entry is present in the Guest TLB but not in the shadow, in this
- * case we inject the TLB from the Guest TLB into the shadow host TLB
+ /*
+ * User Address (UA) fault, this could happen if
+ * (1) TLB entry not present/valid in both Guest and shadow host
+ * TLBs, in this case we pass on the fault to the guest
+ * kernel and let it handle it.
+ * (2) TLB entry is present in the Guest TLB but not in the
+ * shadow, in this case we inject the TLB from the Guest TLB
+ * into the shadow host TLB
*/
er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu);
@@ -206,9 +206,8 @@ static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else {
- printk
- ("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
kvm_mips_dump_host_tlbs();
kvm_arch_vcpu_dump_regs(vcpu);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -231,7 +230,7 @@ static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
kvm_debug("Emulate Store to MMIO space\n");
er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
if (er == EMULATE_FAIL) {
- printk("Emulate Store to MMIO space failed\n");
+ kvm_err("Emulate Store to MMIO space failed\n");
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
} else {
@@ -239,9 +238,8 @@ static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else {
- printk
- ("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
}
@@ -261,7 +259,7 @@ static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr);
er = kvm_mips_emulate_inst(cause, opc, run, vcpu);
if (er == EMULATE_FAIL) {
- printk("Emulate Load from MMIO space failed\n");
+ kvm_err("Emulate Load from MMIO space failed\n");
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
} else {
@@ -269,9 +267,8 @@ static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
}
} else {
- printk
- ("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n",
- cause, opc, badvaddr);
+ kvm_err("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n",
+ cause, opc, badvaddr);
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
ret = RESUME_HOST;
er = EMULATE_FAIL;
@@ -349,9 +346,9 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
uint32_t config1;
int vcpu_id = vcpu->vcpu_id;
- /* Arch specific stuff, set up config registers properly so that the
- * guest will come up as expected, for now we simulate a
- * MIPS 24kc
+ /*
+ * Arch specific stuff, set up config registers properly so that the
+ * guest will come up as expected, for now we simulate a MIPS 24kc
*/
kvm_write_c0_guest_prid(cop0, 0x00019300);
kvm_write_c0_guest_config(cop0,
@@ -373,14 +370,15 @@ static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu)
kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2);
/* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */
- kvm_write_c0_guest_config3(cop0,
- MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 <<
- CP0C3_ULRI));
+ kvm_write_c0_guest_config3(cop0, MIPS_CONFIG3 | (0 << CP0C3_VInt) |
+ (1 << CP0C3_ULRI));
/* Set Wait IE/IXMT Ignore in Config7, IAR, AR */
kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10));
- /* Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5) */
+ /*
+ * Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5)
+ */
kvm_write_c0_guest_intctl(cop0, 0xFC000000);
/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index e6a86ccc4421..1b91fc6a921b 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -60,8 +60,8 @@ config LEMOTE_MACH2F
These family machines include fuloong2f mini PC, yeeloong2f notebook,
LingLoong allinone PC and so forth.
-config LEMOTE_MACH3A
- bool "Lemote Loongson 3A family machines"
+config LOONGSON_MACH3X
+ bool "Generic Loongson 3 family machines"
select ARCH_SPARSEMEM_ENABLE
select GENERIC_ISA_DMA_SUPPORT_BROKEN
select BOOT_ELF32
@@ -79,6 +79,7 @@ config LEMOTE_MACH3A
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_HOTPLUG_CPU
+ select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -86,8 +87,8 @@ config LEMOTE_MACH3A
select ZONE_DMA32
select LEFI_FIRMWARE_INTERFACE
help
- Lemote Loongson 3A family machines utilize the 3A revision of
- Loongson processor and RS780/SBX00 chipset.
+ Generic Loongson 3 family machines utilize the 3A/3B revision
+ of Loongson processor and RS780/SBX00 chipset.
endchoice
config CS5536
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
index 6205372b6c2d..0ac20eb84ecc 100644
--- a/arch/mips/loongson/Platform
+++ b/arch/mips/loongson/Platform
@@ -30,4 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index 0c543eae49bf..f15228550a22 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -27,6 +27,12 @@ EXPORT_SYMBOL(cpu_clock_freq);
struct efi_memory_map_loongson *loongson_memmap;
struct loongson_system_configuration loongson_sysconf;
+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
+u64 loongson_freqctrl[MAX_PACKAGES];
+
+unsigned long long smp_group[4];
+int cpuhotplug_workaround = 0;
+
#define parse_even_earlier(res, option, p) \
do { \
unsigned int tmp __maybe_unused; \
@@ -77,9 +83,47 @@ void __init prom_init_env(void)
cpu_clock_freq = ecpu->cpu_clock_freq;
loongson_sysconf.cputype = ecpu->cputype;
+ if (ecpu->cputype == Loongson_3A) {
+ loongson_sysconf.cores_per_node = 4;
+ loongson_sysconf.cores_per_package = 4;
+ smp_group[0] = 0x900000003ff01000;
+ smp_group[1] = 0x900010003ff01000;
+ smp_group[2] = 0x900020003ff01000;
+ smp_group[3] = 0x900030003ff01000;
+ loongson_chipcfg[0] = 0x900000001fe00180;
+ loongson_chipcfg[1] = 0x900010001fe00180;
+ loongson_chipcfg[2] = 0x900020001fe00180;
+ loongson_chipcfg[3] = 0x900030001fe00180;
+ loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+ } else if (ecpu->cputype == Loongson_3B) {
+ loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
+ loongson_sysconf.cores_per_package = 8;
+ smp_group[0] = 0x900000003ff01000;
+ smp_group[1] = 0x900010003ff05000;
+ smp_group[2] = 0x900020003ff09000;
+ smp_group[3] = 0x900030003ff0d000;
+ loongson_chipcfg[0] = 0x900000001fe00180;
+ loongson_chipcfg[1] = 0x900020001fe00180;
+ loongson_chipcfg[2] = 0x900040001fe00180;
+ loongson_chipcfg[3] = 0x900060001fe00180;
+ loongson_freqctrl[0] = 0x900000001fe001d0;
+ loongson_freqctrl[1] = 0x900020001fe001d0;
+ loongson_freqctrl[2] = 0x900040001fe001d0;
+ loongson_freqctrl[3] = 0x900060001fe001d0;
+ loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
+ cpuhotplug_workaround = 1;
+ } else {
+ loongson_sysconf.cores_per_node = 1;
+ loongson_sysconf.cores_per_package = 1;
+ loongson_chipcfg[0] = 0x900000001fe00180;
+ }
+
loongson_sysconf.nr_cpus = ecpu->nr_cpus;
if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
loongson_sysconf.nr_cpus = NR_CPUS;
+ loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
+ loongson_sysconf.cores_per_node - 1) /
+ loongson_sysconf.cores_per_node;
loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -93,7 +137,6 @@ void __init prom_init_env(void)
loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
- loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
@@ -111,6 +154,10 @@ void __init prom_init_env(void)
case PRID_REV_LOONGSON3A:
cpu_clock_freq = 900000000;
break;
+ case PRID_REV_LOONGSON3B_R1:
+ case PRID_REV_LOONGSON3B_R2:
+ cpu_clock_freq = 1000000000;
+ break;
default:
cpu_clock_freq = 100000000;
break;
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index f37fe5413b73..f6af3aba4c86 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -30,7 +30,11 @@ void __init prom_init(void)
set_io_port_base((unsigned long)
ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+#ifdef CONFIG_NUMA
+ prom_init_numa_memory();
+#else
prom_init_memory();
+#endif
/*init the uart base address */
prom_init_uart_base();
diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c
index f55e07aee071..a6b67ccfc811 100644
--- a/arch/mips/loongson/common/pm.c
+++ b/arch/mips/loongson/common/pm.c
@@ -79,7 +79,7 @@ int __weak wakeup_loongson(void)
static void wait_for_wakeup_events(void)
{
while (!wakeup_loongson())
- LOONGSON_CHIPCFG0 &= ~0x7;
+ LOONGSON_CHIPCFG(0) &= ~0x7;
}
/*
@@ -102,15 +102,15 @@ static void loongson_suspend_enter(void)
stop_perf_counters();
- cached_cpu_freq = LOONGSON_CHIPCFG0;
+ cached_cpu_freq = LOONGSON_CHIPCFG(0);
/* Put CPU into wait mode */
- LOONGSON_CHIPCFG0 &= ~0x7;
+ LOONGSON_CHIPCFG(0) &= ~0x7;
/* wait for the given events to wakeup cpu from wait mode */
wait_for_wakeup_events();
- LOONGSON_CHIPCFG0 = cached_cpu_freq;
+ LOONGSON_CHIPCFG(0) = cached_cpu_freq;
mmiowb();
}
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
index 1eed38e28b1e..a217061beee3 100644
--- a/arch/mips/loongson/lemote-2f/clock.c
+++ b/arch/mips/loongson/lemote-2f/clock.c
@@ -114,9 +114,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
clk->rate = rate;
- regval = LOONGSON_CHIPCFG0;
+ regval = LOONGSON_CHIPCFG(0);
regval = (regval & ~0x7) | (pos->driver_data - 1);
- LOONGSON_CHIPCFG0 = regval;
+ LOONGSON_CHIPCFG(0) = regval;
return ret;
}
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c
index 90962a3a1731..79ac694fe744 100644
--- a/arch/mips/loongson/lemote-2f/reset.c
+++ b/arch/mips/loongson/lemote-2f/reset.c
@@ -28,7 +28,7 @@ static void reset_cpu(void)
* reset cpu to full speed, this is needed when enabling cpu frequency
* scalling
*/
- LOONGSON_CHIPCFG0 |= 0x7;
+ LOONGSON_CHIPCFG(0) |= 0x7;
}
/* reset support for fuloong2f */
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index 70152b252ddc..b4df775b9f30 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -1,6 +1,8 @@
#
# Makefile for Loongson-3 family machines
#
-obj-y += irq.o
+obj-y += irq.o cop2-ex.o
obj-$(CONFIG_SMP) += smp.o
+
+obj-$(CONFIG_NUMA) += numa.o
diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c
new file mode 100644
index 000000000000..9182e8d2967c
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/cop2-ex.c
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Lemote Corporation.
+ * written by Huacai Chen <chenhc@lemote.com>
+ *
+ * based on arch/mips/cavium-octeon/cpu.c
+ * Copyright (C) 2009 Wind River Systems,
+ * written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+
+#include <asm/fpu.h>
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+
+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
+ void *data)
+{
+ int fpu_enabled;
+ int fr = !test_thread_flag(TIF_32BIT_FPREGS);
+
+ switch (action) {
+ case CU2_EXCEPTION:
+ preempt_disable();
+ fpu_enabled = read_c0_status() & ST0_CU1;
+ if (!fr)
+ set_c0_status(ST0_CU1 | ST0_CU2);
+ else
+ set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR);
+ enable_fpu_hazard();
+ KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2);
+ if (fr)
+ KSTK_STATUS(current) |= ST0_FR;
+ else
+ KSTK_STATUS(current) &= ~ST0_FR;
+ /* If FPU is enabled, we needn't init or restore fp */
+ if(!fpu_enabled) {
+ set_thread_flag(TIF_USEDFPU);
+ if (!used_math()) {
+ _init_fpu();
+ set_used_math();
+ } else
+ _restore_fp(current);
+ }
+ preempt_enable();
+
+ return NOTIFY_STOP; /* Don't call default notifier */
+ }
+
+ return NOTIFY_OK; /* Let default notifier send signals */
+}
+
+static int __init loongson_cu2_setup(void)
+{
+ return cu2_notifier(loongson_cu2_call, 0);
+}
+early_initcall(loongson_cu2_setup);
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
index f240828181ff..ca1c62af5188 100644
--- a/arch/mips/loongson/loongson-3/irq.c
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -7,6 +7,8 @@
#include <asm/i8259.h>
#include <asm/mipsregs.h>
+#include "smp.h"
+
unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
static void ht_irqdispatch(void)
@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(struct irq_data *d)
/* Workaround: UART IRQ may deliver to any core */
if (d->irq == LOONGSON_UART_IRQ) {
int cpu = smp_processor_id();
-
- LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+ int node_id = cpu / loongson_sysconf.cores_per_node;
+ int core_id = cpu % loongson_sysconf.cores_per_node;
+ u64 intenclr_addr = smp_group[node_id] |
+ (u64)(&LOONGSON_INT_ROUTER_INTENCLR);
+ u64 introuter_lpc_addr = smp_group[node_id] |
+ (u64)(&LOONGSON_INT_ROUTER_LPC);
+
+ *(volatile u32 *)intenclr_addr = 1 << 10;
+ *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
}
}
@@ -64,9 +72,15 @@ static inline void unmask_loongson_irq(struct irq_data *d)
/* Workaround: UART IRQ may deliver to any core */
if (d->irq == LOONGSON_UART_IRQ) {
int cpu = smp_processor_id();
-
- LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+ int node_id = cpu / loongson_sysconf.cores_per_node;
+ int core_id = cpu % loongson_sysconf.cores_per_node;
+ u64 intenset_addr = smp_group[node_id] |
+ (u64)(&LOONGSON_INT_ROUTER_INTENSET);
+ u64 introuter_lpc_addr = smp_group[node_id] |
+ (u64)(&LOONGSON_INT_ROUTER_LPC);
+
+ *(volatile u32 *)intenset_addr = 1 << 10;
+ *(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
}
set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
new file mode 100644
index 000000000000..ca025a6ba559
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/numa.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ * Insititute of Computing Technology
+ * Author: Xiang Gao, gaoxiang@ict.ac.cn
+ * Huacai Chen, chenhc@lemote.com
+ * Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+#include <boot_param.h>
+
+static struct node_data prealloc__node_data[MAX_NUMNODES];
+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+struct node_data *__node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(__node_data);
+
+static void enable_lpa(void)
+{
+ unsigned long value;
+
+ value = __read_32bit_c0_register($16, 3);
+ value |= 0x00000080;
+ __write_32bit_c0_register($16, 3, value);
+ value = __read_32bit_c0_register($16, 3);
+ pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
+
+ value = __read_32bit_c0_register($5, 1);
+ value |= 0x20000000;
+ __write_32bit_c0_register($5, 1, value);
+ value = __read_32bit_c0_register($5, 1);
+ pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
+}
+
+static void cpu_node_probe(void)
+{
+ int i;
+
+ nodes_clear(node_possible_map);
+ nodes_clear(node_online_map);
+ for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
+ node_set_state(num_online_nodes(), N_POSSIBLE);
+ node_set_online(num_online_nodes());
+ }
+
+ pr_info("NUMA: Discovered %d cpus on %d nodes\n",
+ loongson_sysconf.nr_cpus, num_online_nodes());
+}
+
+static int __init compute_node_distance(int row, int col)
+{
+ int package_row = row * loongson_sysconf.cores_per_node /
+ loongson_sysconf.cores_per_package;
+ int package_col = col * loongson_sysconf.cores_per_node /
+ loongson_sysconf.cores_per_package;
+
+ if (col == row)
+ return 0;
+ else if (package_row == package_col)
+ return 40;
+ else
+ return 100;
+}
+
+static void __init init_topology_matrix(void)
+{
+ int row, col;
+
+ for (row = 0; row < MAX_NUMNODES; row++)
+ for (col = 0; col < MAX_NUMNODES; col++)
+ __node_distances[row][col] = -1;
+
+ for_each_online_node(row) {
+ for_each_online_node(col) {
+ __node_distances[row][col] =
+ compute_node_distance(row, col);
+ }
+ }
+}
+
+static unsigned long nid_to_addroffset(unsigned int nid)
+{
+ unsigned long result;
+ switch (nid) {
+ case 0:
+ default:
+ result = NODE0_ADDRSPACE_OFFSET;
+ break;
+ case 1:
+ result = NODE1_ADDRSPACE_OFFSET;
+ break;
+ case 2:
+ result = NODE2_ADDRSPACE_OFFSET;
+ break;
+ case 3:
+ result = NODE3_ADDRSPACE_OFFSET;
+ break;
+ }
+ return result;
+}
+
+static void __init szmem(unsigned int node)
+{
+ u32 i, mem_type;
+ static unsigned long num_physpages = 0;
+ u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+
+ /* Parse memory information and activate */
+ for (i = 0; i < loongson_memmap->nr_map; i++) {
+ node_id = loongson_memmap->map[i].node_id;
+ if (node_id != node)
+ continue;
+
+ mem_type = loongson_memmap->map[i].mem_type;
+ mem_size = loongson_memmap->map[i].mem_size;
+ mem_start = loongson_memmap->map[i].mem_start;
+
+ switch (mem_type) {
+ case SYSTEM_RAM_LOW:
+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+ node_psize = (mem_size << 20) >> PAGE_SHIFT;
+ end_pfn = start_pfn + node_psize;
+ num_physpages += node_psize;
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+ (u32)node_id, mem_type, mem_start, mem_size);
+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+ start_pfn, end_pfn, num_physpages);
+ add_memory_region((node_id << 44) + mem_start,
+ (u64)mem_size << 20, BOOT_MEM_RAM);
+ memblock_add_node(PFN_PHYS(start_pfn),
+ PFN_PHYS(end_pfn - start_pfn), node);
+ break;
+ case SYSTEM_RAM_HIGH:
+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+ node_psize = (mem_size << 20) >> PAGE_SHIFT;
+ end_pfn = start_pfn + node_psize;
+ num_physpages += node_psize;
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+ (u32)node_id, mem_type, mem_start, mem_size);
+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+ start_pfn, end_pfn, num_physpages);
+ add_memory_region((node_id << 44) + mem_start,
+ (u64)mem_size << 20, BOOT_MEM_RAM);
+ memblock_add_node(PFN_PHYS(start_pfn),
+ PFN_PHYS(end_pfn - start_pfn), node);
+ break;
+ case MEM_RESERVED:
+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+ (u32)node_id, mem_type, mem_start, mem_size);
+ add_memory_region((node_id << 44) + mem_start,
+ (u64)mem_size << 20, BOOT_MEM_RESERVED);
+ memblock_reserve(((node_id << 44) + mem_start),
+ mem_size << 20);
+ break;
+ }
+ }
+}
+
+static void __init node_mem_init(unsigned int node)
+{
+ unsigned long bootmap_size;
+ unsigned long node_addrspace_offset;
+ unsigned long start_pfn, end_pfn, freepfn;
+
+ node_addrspace_offset = nid_to_addroffset(node);
+ pr_info("Node%d's addrspace_offset is 0x%lx\n",
+ node, node_addrspace_offset);
+
+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+ freepfn = start_pfn;
+ if (node == 0)
+ freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
+ pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
+ node, start_pfn, end_pfn, freepfn);
+
+ __node_data[node] = prealloc__node_data + node;
+
+ NODE_DATA(node)->bdata = &bootmem_node_data[node];
+ NODE_DATA(node)->node_start_pfn = start_pfn;
+ NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
+
+ bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
+ start_pfn, end_pfn);
+ free_bootmem_with_active_regions(node, end_pfn);
+ if (node == 0) /* used by finalize_initrd() */
+ max_low_pfn = end_pfn;
+
+ /* This is reserved for the kernel and bdata->node_bootmem_map */
+ reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
+ ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
+ BOOTMEM_DEFAULT);
+
+ if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
+ /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+ reserve_bootmem_node(NODE_DATA(node),
+ (node_addrspace_offset | 0xff800000),
+ 8 << 20, BOOTMEM_DEFAULT);
+ }
+
+ sparse_memory_present_with_active_regions(node);
+}
+
+static __init void prom_meminit(void)
+{
+ unsigned int node, cpu;
+
+ cpu_node_probe();
+ init_topology_matrix();
+
+ for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
+ if (node_online(node)) {
+ szmem(node);
+ node_mem_init(node);
+ cpus_clear(__node_data[(node)]->cpumask);
+ }
+ }
+ for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
+ node = cpu / loongson_sysconf.cores_per_node;
+ if (node >= num_online_nodes())
+ node = 0;
+ pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
+ cpu_set(cpu, __node_data[(node)]->cpumask);
+ }
+}
+
+void __init paging_init(void)
+{
+ unsigned node;
+ unsigned long zones_size[MAX_NR_ZONES] = {0, };
+
+ pagetable_init();
+
+ for_each_online_node(node) {
+ unsigned long start_pfn, end_pfn;
+
+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+
+ if (end_pfn > max_low_pfn)
+ max_low_pfn = end_pfn;
+ }
+#ifdef CONFIG_ZONE_DMA32
+ zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
+#endif
+ zones_size[ZONE_NORMAL] = max_low_pfn;
+ free_area_init_nodes(zones_size);
+}
+
+void __init mem_init(void)
+{
+ high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
+ free_all_bootmem();
+ setup_zero_pages(); /* This comes from node 0 */
+ mem_init_print_info(NULL);
+}
+
+/* All PCI device belongs to logical Node-0 */
+int pcibus_to_node(struct pci_bus *bus)
+{
+ return 0;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+
+void __init prom_init_numa_memory(void)
+{
+ enable_lpa();
+ prom_meminit();
+}
+EXPORT_SYMBOL(prom_init_numa_memory);
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index 1e8894020ea5..74e827b4ec8f 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -31,6 +31,12 @@
DEFINE_PER_CPU(int, cpu_state);
DEFINE_PER_CPU(uint32_t, core0_c0count);
+static void *ipi_set0_regs[16];
+static void *ipi_clear0_regs[16];
+static void *ipi_status0_regs[16];
+static void *ipi_en0_regs[16];
+static void *ipi_mailbox_buf[16];
+
/* read a 32bit value from ipi register */
#define loongson3_ipi_read32(addr) readl(addr)
/* read a 64bit value from ipi register */
@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count);
__wbflush(); \
} while (0)
-static void *ipi_set0_regs[] = {
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
-};
+static void ipi_set0_regs_init(void)
+{
+ ipi_set0_regs[0] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
+ ipi_set0_regs[1] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
+ ipi_set0_regs[2] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
+ ipi_set0_regs[3] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
+ ipi_set0_regs[4] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
+ ipi_set0_regs[5] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
+ ipi_set0_regs[6] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
+ ipi_set0_regs[7] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
+ ipi_set0_regs[8] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
+ ipi_set0_regs[9] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
+ ipi_set0_regs[10] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
+ ipi_set0_regs[11] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
+ ipi_set0_regs[12] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
+ ipi_set0_regs[13] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
+ ipi_set0_regs[14] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
+ ipi_set0_regs[15] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
+}
-static void *ipi_clear0_regs[] = {
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
-};
+static void ipi_clear0_regs_init(void)
+{
+ ipi_clear0_regs[0] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
+ ipi_clear0_regs[1] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
+ ipi_clear0_regs[2] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
+ ipi_clear0_regs[3] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
+ ipi_clear0_regs[4] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
+ ipi_clear0_regs[5] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
+ ipi_clear0_regs[6] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
+ ipi_clear0_regs[7] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
+ ipi_clear0_regs[8] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
+ ipi_clear0_regs[9] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
+ ipi_clear0_regs[10] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
+ ipi_clear0_regs[11] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
+ ipi_clear0_regs[12] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
+ ipi_clear0_regs[13] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
+ ipi_clear0_regs[14] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
+ ipi_clear0_regs[15] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
+}
-static void *ipi_status0_regs[] = {
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
-};
+static void ipi_status0_regs_init(void)
+{
+ ipi_status0_regs[0] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
+ ipi_status0_regs[1] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
+ ipi_status0_regs[2] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
+ ipi_status0_regs[3] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
+ ipi_status0_regs[4] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
+ ipi_status0_regs[5] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
+ ipi_status0_regs[6] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
+ ipi_status0_regs[7] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
+ ipi_status0_regs[8] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
+ ipi_status0_regs[9] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
+ ipi_status0_regs[10] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
+ ipi_status0_regs[11] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
+ ipi_status0_regs[12] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
+ ipi_status0_regs[13] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
+ ipi_status0_regs[14] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
+ ipi_status0_regs[15] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
+}
-static void *ipi_en0_regs[] = {
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
-};
+static void ipi_en0_regs_init(void)
+{
+ ipi_en0_regs[0] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
+ ipi_en0_regs[1] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
+ ipi_en0_regs[2] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
+ ipi_en0_regs[3] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
+ ipi_en0_regs[4] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
+ ipi_en0_regs[5] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
+ ipi_en0_regs[6] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
+ ipi_en0_regs[7] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
+ ipi_en0_regs[8] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
+ ipi_en0_regs[9] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
+ ipi_en0_regs[10] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
+ ipi_en0_regs[11] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
+ ipi_en0_regs[12] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
+ ipi_en0_regs[13] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
+ ipi_en0_regs[14] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
+ ipi_en0_regs[15] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
+}
-static void *ipi_mailbox_buf[] = {
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
-};
+static void ipi_mailbox_buf_init(void)
+{
+ ipi_mailbox_buf[0] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
+ ipi_mailbox_buf[1] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
+ ipi_mailbox_buf[2] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
+ ipi_mailbox_buf[3] = (void *)
+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
+ ipi_mailbox_buf[4] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
+ ipi_mailbox_buf[5] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
+ ipi_mailbox_buf[6] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
+ ipi_mailbox_buf[7] = (void *)
+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
+ ipi_mailbox_buf[8] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
+ ipi_mailbox_buf[9] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
+ ipi_mailbox_buf[10] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
+ ipi_mailbox_buf[11] = (void *)
+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
+ ipi_mailbox_buf[12] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
+ ipi_mailbox_buf[13] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
+ ipi_mailbox_buf[14] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
+ ipi_mailbox_buf[15] = (void *)
+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
+}
/*
* Simple enough, just poke the appropriate ipi register
@@ -203,6 +294,8 @@ static void loongson3_init_secondary(void)
for (i = 0; i < loongson_sysconf.nr_cpus; i++)
loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
+ cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
+ cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
per_cpu(cpu_state, cpu) = CPU_ONLINE;
i = 0;
@@ -246,6 +339,11 @@ static void __init loongson3_smp_setup(void)
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
+ ipi_set0_regs_init();
+ ipi_clear0_regs_init();
+ ipi_status0_regs_init();
+ ipi_en0_regs_init();
+ ipi_mailbox_buf_init();
pr_info("Detected %i available secondary CPU(s)\n", num);
}
@@ -313,7 +411,7 @@ static void loongson3_cpu_die(unsigned int cpu)
* flush all L1 entries at first. Then, another core (usually Core 0) can
* safely disable the clock of the target core. loongson3_play_dead() is
* called via CKSEG1 (uncached and unmmaped) */
-static void loongson3_play_dead(int *state_addr)
+static void loongson3a_play_dead(int *state_addr)
{
register int val;
register long cpuid, core, node, count;
@@ -375,6 +473,70 @@ static void loongson3_play_dead(int *state_addr)
: "a1");
}
+static void loongson3b_play_dead(int *state_addr)
+{
+ register int val;
+ register long cpuid, core, node, count;
+ register void *addr, *base, *initfunc;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " li %[addr], 0x80000000 \n" /* KSEG0 */
+ "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */
+ " cache 0, 1(%[addr]) \n"
+ " cache 0, 2(%[addr]) \n"
+ " cache 0, 3(%[addr]) \n"
+ " cache 1, 0(%[addr]) \n" /* flush L1 DCache */
+ " cache 1, 1(%[addr]) \n"
+ " cache 1, 2(%[addr]) \n"
+ " cache 1, 3(%[addr]) \n"
+ " addiu %[sets], %[sets], -1 \n"
+ " bnez %[sets], 1b \n"
+ " addiu %[addr], %[addr], 0x20 \n"
+ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */
+ " sw %[val], (%[state_addr]) \n"
+ " sync \n"
+ " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */
+ " .set pop \n"
+ : [addr] "=&r" (addr), [val] "=&r" (val)
+ : [state_addr] "r" (state_addr),
+ [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set mips64 \n"
+ " mfc0 %[cpuid], $15, 1 \n"
+ " andi %[cpuid], 0x3ff \n"
+ " dli %[base], 0x900000003ff01000 \n"
+ " andi %[core], %[cpuid], 0x3 \n"
+ " sll %[core], 8 \n" /* get core id */
+ " or %[base], %[base], %[core] \n"
+ " andi %[node], %[cpuid], 0xc \n"
+ " dsll %[node], 42 \n" /* get node id */
+ " or %[base], %[base], %[node] \n"
+ " dsrl %[node], 30 \n" /* 15:14 */
+ " or %[base], %[base], %[node] \n"
+ "1: li %[count], 0x100 \n" /* wait for init loop */
+ "2: bnez %[count], 2b \n" /* limit mailbox access */
+ " addiu %[count], -1 \n"
+ " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */
+ " beqz %[initfunc], 1b \n"
+ " nop \n"
+ " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */
+ " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */
+ " ld $a1, 0x38(%[base]) \n"
+ " jr %[initfunc] \n" /* jump to initial PC */
+ " nop \n"
+ " .set pop \n"
+ : [core] "=&r" (core), [node] "=&r" (node),
+ [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+ [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+ : /* No Input */
+ : "a1");
+}
+
void play_dead(void)
{
int *state_addr;
@@ -382,13 +544,48 @@ void play_dead(void)
void (*play_dead_at_ckseg1)(int *);
idle_task_exit();
- play_dead_at_ckseg1 =
- (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+ switch (loongson_sysconf.cputype) {
+ case Loongson_3A:
+ default:
+ play_dead_at_ckseg1 =
+ (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+ break;
+ case Loongson_3B:
+ play_dead_at_ckseg1 =
+ (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
+ break;
+ }
state_addr = &per_cpu(cpu_state, cpu);
mb();
play_dead_at_ckseg1(state_addr);
}
+void loongson3_disable_clock(int cpu)
+{
+ uint64_t core_id = cpu_data[cpu].core;
+ uint64_t package_id = cpu_data[cpu].package;
+
+ if (loongson_sysconf.cputype == Loongson_3A) {
+ LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
+ } else if (loongson_sysconf.cputype == Loongson_3B) {
+ if (!cpuhotplug_workaround)
+ LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
+ }
+}
+
+void loongson3_enable_clock(int cpu)
+{
+ uint64_t core_id = cpu_data[cpu].core;
+ uint64_t package_id = cpu_data[cpu].package;
+
+ if (loongson_sysconf.cputype == Loongson_3A) {
+ LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
+ } else if (loongson_sysconf.cputype == Loongson_3B) {
+ if (!cpuhotplug_workaround)
+ LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
+ }
+}
+
#define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN)
static int loongson3_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
@@ -399,12 +596,12 @@ static int loongson3_cpu_callback(struct notifier_block *nfb,
case CPU_POST_DEAD:
case CPU_POST_DEAD_FROZEN:
pr_info("Disable clock for CPU#%d\n", cpu);
- LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+ loongson3_disable_clock(cpu);
break;
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
pr_info("Enable clock for CPU#%d\n", cpu);
- LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+ loongson3_enable_clock(cpu);
break;
}
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
index 3453e8c4f2f0..d98ff654b7d7 100644
--- a/arch/mips/loongson/loongson-3/smp.h
+++ b/arch/mips/loongson/loongson-3/smp.h
@@ -1,29 +1,30 @@
#ifndef __LOONGSON_SMP_H_
#define __LOONGSON_SMP_H_
-/* for Loongson-3A smp support */
+/* for Loongson-3 smp support */
+extern unsigned long long smp_group[4];
/* 4 groups(nodes) in maximum in numa case */
-#define SMP_CORE_GROUP0_BASE 0x900000003ff01000
-#define SMP_CORE_GROUP1_BASE 0x900010003ff01000
-#define SMP_CORE_GROUP2_BASE 0x900020003ff01000
-#define SMP_CORE_GROUP3_BASE 0x900030003ff01000
+#define SMP_CORE_GROUP0_BASE (smp_group[0])
+#define SMP_CORE_GROUP1_BASE (smp_group[1])
+#define SMP_CORE_GROUP2_BASE (smp_group[2])
+#define SMP_CORE_GROUP3_BASE (smp_group[3])
/* 4 cores in each group(node) */
-#define SMP_CORE0_OFFSET 0x000
-#define SMP_CORE1_OFFSET 0x100
-#define SMP_CORE2_OFFSET 0x200
-#define SMP_CORE3_OFFSET 0x300
+#define SMP_CORE0_OFFSET 0x000
+#define SMP_CORE1_OFFSET 0x100
+#define SMP_CORE2_OFFSET 0x200
+#define SMP_CORE3_OFFSET 0x300
/* ipi registers offsets */
-#define STATUS0 0x00
-#define EN0 0x04
-#define SET0 0x08
-#define CLEAR0 0x0c
-#define STATUS1 0x10
-#define MASK1 0x14
-#define SET1 0x18
-#define CLEAR1 0x1c
-#define BUF 0x20
+#define STATUS0 0x00
+#define EN0 0x04
+#define SET0 0x08
+#define CLEAR0 0x0c
+#define STATUS1 0x10
+#define MASK1 0x14
+#define SET1 0x18
+#define CLEAR1 0x1c
+#define BUF 0x20
#endif
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 736c17a226e9..bf0fc6b16ad9 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1827,7 +1827,7 @@ dcopuop:
case -1:
if (cpu_has_mips_4_5_r)
- cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
+ cbit = fpucondbit[MIPSInst_FD(ir) >> 2];
else
cbit = FPU_CSR_COND;
if (rv.w)
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index f2e8302fa70f..fbcd8674ff1d 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1230,19 +1230,19 @@ static void probe_pcache(void)
case CPU_R14000:
break;
+ case CPU_74K:
+ case CPU_1074K:
+ alias_74k_erratum(c);
+ /* Fall through. */
case CPU_M14KC:
case CPU_M14KEC:
case CPU_24K:
case CPU_34K:
- case CPU_74K:
case CPU_1004K:
- case CPU_1074K:
case CPU_INTERAPTIV:
case CPU_P5600:
case CPU_PROAPTIV:
case CPU_M5150:
- if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
- alias_74k_erratum(c);
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
(c->icache.waysize > PAGE_SIZE))
c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 6e4413330e36..571aab064936 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -325,6 +325,38 @@ static inline void mem_init_free_highmem(void)
#endif
}
+unsigned __weak platform_maar_init(unsigned num_maars)
+{
+ return 0;
+}
+
+static void maar_init(void)
+{
+ unsigned num_maars, used, i;
+
+ if (!cpu_has_maar)
+ return;
+
+ /* Detect the number of MAARs */
+ write_c0_maari(~0);
+ back_to_back_c0_hazard();
+ num_maars = read_c0_maari() + 1;
+
+ /* MAARs should be in pairs */
+ WARN_ON(num_maars % 2);
+
+ /* Configure the required MAARs */
+ used = platform_maar_init(num_maars / 2);
+
+ /* Disable any further MAARs */
+ for (i = (used * 2); i < num_maars; i++) {
+ write_c0_maari(i);
+ back_to_back_c0_hazard();
+ write_c0_maar(0);
+ back_to_back_c0_hazard();
+ }
+}
+
void __init mem_init(void)
{
#ifdef CONFIG_HIGHMEM
@@ -337,6 +369,7 @@ void __init mem_init(void)
#endif
high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
+ maar_init();
free_all_bootmem();
setup_zero_pages(); /* Setup zeroed pages. */
mem_init_free_highmem();
diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
index d657493ef561..4094bbd42adf 100644
--- a/arch/mips/mm/tlb-r3k.c
+++ b/arch/mips/mm/tlb-r3k.c
@@ -158,7 +158,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
{
int cpu = smp_processor_id();
- if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+ if (cpu_context(cpu, vma->vm_mm) != 0) {
unsigned long flags;
int oldpid, newpid, idx;
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 3914e27456f2..fa6ebd4bc9e9 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -57,6 +57,7 @@ void local_flush_tlb_all(void)
local_irq_save(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
+ htw_stop();
write_c0_entrylo0(0);
write_c0_entrylo1(0);
@@ -90,6 +91,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
+ htw_start();
flush_itlb();
local_irq_restore(flags);
}
@@ -131,6 +133,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
int oldpid = read_c0_entryhi();
int newpid = cpu_asid(cpu, mm);
+ htw_stop();
while (start < end) {
int idx;
@@ -151,6 +154,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
}
tlbw_use_hazard();
write_c0_entryhi(oldpid);
+ htw_start();
} else {
drop_mmu_context(mm, cpu);
}
@@ -174,6 +178,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
start &= (PAGE_MASK << 1);
end += ((PAGE_SIZE << 1) - 1);
end &= (PAGE_MASK << 1);
+ htw_stop();
while (start < end) {
int idx;
@@ -195,6 +200,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
}
tlbw_use_hazard();
write_c0_entryhi(pid);
+ htw_start();
} else {
local_flush_tlb_all();
}
@@ -214,6 +220,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
page &= (PAGE_MASK << 1);
local_irq_save(flags);
oldpid = read_c0_entryhi();
+ htw_stop();
write_c0_entryhi(page | newpid);
mtc0_tlbw_hazard();
tlb_probe();
@@ -231,6 +238,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
+ htw_start();
flush_itlb_vm(vma);
local_irq_restore(flags);
}
@@ -247,6 +255,7 @@ void local_flush_tlb_one(unsigned long page)
local_irq_save(flags);
oldpid = read_c0_entryhi();
+ htw_stop();
page &= (PAGE_MASK << 1);
write_c0_entryhi(page);
mtc0_tlbw_hazard();
@@ -263,6 +272,7 @@ void local_flush_tlb_one(unsigned long page)
tlbw_use_hazard();
}
write_c0_entryhi(oldpid);
+ htw_start();
flush_itlb();
local_irq_restore(flags);
}
@@ -351,6 +361,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
local_irq_save(flags);
/* Save old context and create impossible VPN2 value */
old_ctx = read_c0_entryhi();
+ htw_stop();
old_pagemask = read_c0_pagemask();
wired = read_c0_wired();
write_c0_wired(wired + 1);
@@ -366,6 +377,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
write_c0_entryhi(old_ctx);
tlbw_use_hazard(); /* What is the hazard here? */
+ htw_start();
write_c0_pagemask(old_pagemask);
local_flush_tlb_all();
local_irq_restore(flags);
@@ -391,6 +403,51 @@ int __init has_transparent_hugepage(void)
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+/*
+ * Used for loading TLB entries before trap_init() has started, when we
+ * don't actually want to add a wired entry which remains throughout the
+ * lifetime of the system
+ */
+
+int temp_tlb_entry __cpuinitdata;
+
+__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask)
+{
+ int ret = 0;
+ unsigned long flags;
+ unsigned long wired;
+ unsigned long old_pagemask;
+ unsigned long old_ctx;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ old_pagemask = read_c0_pagemask();
+ wired = read_c0_wired();
+ if (--temp_tlb_entry < wired) {
+ printk(KERN_WARNING
+ "No TLB space left for add_temporary_entry\n");
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ write_c0_index(temp_tlb_entry);
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+ write_c0_pagemask(old_pagemask);
+out:
+ local_irq_restore(flags);
+ return ret;
+}
+
static int ntlb;
static int __init set_ntlb(char *str)
{
@@ -431,6 +488,8 @@ static void r4k_tlb_configure(void)
write_c0_pagegrain(pg);
}
+ temp_tlb_entry = current_cpu_data.tlbsize - 1;
+
/* From this point on the ARC firmware is dead. */
local_flush_tlb_all();
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e80e10bafc83..a08dd53a1cc5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -429,6 +429,7 @@ static void build_r3000_tlb_refill_handler(void)
(unsigned int)(p - tlb_handler));
memcpy((void *)ebase, tlb_handler, 0x80);
+ local_flush_icache_range(ebase, ebase + 0x80);
dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
}
@@ -1299,6 +1300,7 @@ static void build_r4000_tlb_refill_handler(void)
}
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
uasm_l_tlb_huge_update(&l, p);
+ UASM_i_LW(&p, K0, 0, K1);
build_huge_update_entries(&p, htlb_info.huge_pte, K1);
build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
htlb_info.restore_scratch);
@@ -1415,6 +1417,7 @@ static void build_r4000_tlb_refill_handler(void)
final_len);
memcpy((void *)ebase, final_handler, 0x100);
+ local_flush_icache_range(ebase, ebase + 0x100);
dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
}
@@ -1919,7 +1922,7 @@ static void build_r4000_tlb_load_handler(void)
if (m4kc_tlbp_war())
build_tlb_probe_entry(&p);
- if (cpu_has_rixi) {
+ if (cpu_has_rixi && !cpu_has_rixiex) {
/*
* If the page is not _PAGE_VALID, RI or XI could not
* have triggered it. Skip the expensive test..
@@ -1986,7 +1989,7 @@ static void build_r4000_tlb_load_handler(void)
build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
build_tlb_probe_entry(&p);
- if (cpu_has_rixi) {
+ if (cpu_has_rixi && !cpu_has_rixiex) {
/*
* If the page is not _PAGE_VALID, RI or XI could not
* have triggered it. Skip the expensive test..
@@ -2194,6 +2197,94 @@ static void flush_tlb_handlers(void)
(unsigned long)tlbmiss_handler_setup_pgd_end);
}
+static void print_htw_config(void)
+{
+ unsigned long config;
+ unsigned int pwctl;
+ const int field = 2 * sizeof(unsigned long);
+
+ config = read_c0_pwfield();
+ pr_debug("PWField (0x%0*lx): GDI: 0x%02lx UDI: 0x%02lx MDI: 0x%02lx PTI: 0x%02lx PTEI: 0x%02lx\n",
+ field, config,
+ (config & MIPS_PWFIELD_GDI_MASK) >> MIPS_PWFIELD_GDI_SHIFT,
+ (config & MIPS_PWFIELD_UDI_MASK) >> MIPS_PWFIELD_UDI_SHIFT,
+ (config & MIPS_PWFIELD_MDI_MASK) >> MIPS_PWFIELD_MDI_SHIFT,
+ (config & MIPS_PWFIELD_PTI_MASK) >> MIPS_PWFIELD_PTI_SHIFT,
+ (config & MIPS_PWFIELD_PTEI_MASK) >> MIPS_PWFIELD_PTEI_SHIFT);
+
+ config = read_c0_pwsize();
+ pr_debug("PWSize (0x%0*lx): GDW: 0x%02lx UDW: 0x%02lx MDW: 0x%02lx PTW: 0x%02lx PTEW: 0x%02lx\n",
+ field, config,
+ (config & MIPS_PWSIZE_GDW_MASK) >> MIPS_PWSIZE_GDW_SHIFT,
+ (config & MIPS_PWSIZE_UDW_MASK) >> MIPS_PWSIZE_UDW_SHIFT,
+ (config & MIPS_PWSIZE_MDW_MASK) >> MIPS_PWSIZE_MDW_SHIFT,
+ (config & MIPS_PWSIZE_PTW_MASK) >> MIPS_PWSIZE_PTW_SHIFT,
+ (config & MIPS_PWSIZE_PTEW_MASK) >> MIPS_PWSIZE_PTEW_SHIFT);
+
+ pwctl = read_c0_pwctl();
+ pr_debug("PWCtl (0x%x): PWEn: 0x%x DPH: 0x%x HugePg: 0x%x Psn: 0x%x\n",
+ pwctl,
+ (pwctl & MIPS_PWCTL_PWEN_MASK) >> MIPS_PWCTL_PWEN_SHIFT,
+ (pwctl & MIPS_PWCTL_DPH_MASK) >> MIPS_PWCTL_DPH_SHIFT,
+ (pwctl & MIPS_PWCTL_HUGEPG_MASK) >> MIPS_PWCTL_HUGEPG_SHIFT,
+ (pwctl & MIPS_PWCTL_PSN_MASK) >> MIPS_PWCTL_PSN_SHIFT);
+}
+
+static void config_htw_params(void)
+{
+ unsigned long pwfield, pwsize, ptei;
+ unsigned int config;
+
+ /*
+ * We are using 2-level page tables, so we only need to
+ * setup GDW and PTW appropriately. UDW and MDW will remain 0.
+ * The default value of GDI/UDI/MDI/PTI is 0xc. It is illegal to
+ * write values less than 0xc in these fields because the entire
+ * write will be dropped. As a result of which, we must preserve
+ * the original reset values and overwrite only what we really want.
+ */
+
+ pwfield = read_c0_pwfield();
+ /* re-initialize the GDI field */
+ pwfield &= ~MIPS_PWFIELD_GDI_MASK;
+ pwfield |= PGDIR_SHIFT << MIPS_PWFIELD_GDI_SHIFT;
+ /* re-initialize the PTI field including the even/odd bit */
+ pwfield &= ~MIPS_PWFIELD_PTI_MASK;
+ pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+ /* Set the PTEI right shift */
+ ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
+ pwfield |= ptei;
+ write_c0_pwfield(pwfield);
+ /* Check whether the PTEI value is supported */
+ back_to_back_c0_hazard();
+ pwfield = read_c0_pwfield();
+ if (((pwfield & MIPS_PWFIELD_PTEI_MASK) << MIPS_PWFIELD_PTEI_SHIFT)
+ != ptei) {
+ pr_warn("Unsupported PTEI field value: 0x%lx. HTW will not be enabled",
+ ptei);
+ /*
+ * Drop option to avoid HTW being enabled via another path
+ * (eg htw_reset())
+ */
+ current_cpu_data.options &= ~MIPS_CPU_HTW;
+ return;
+ }
+
+ pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
+ pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+ write_c0_pwsize(pwsize);
+
+ /* Make sure everything is set before we enable the HTW */
+ back_to_back_c0_hazard();
+
+ /* Enable HTW and disable the rest of the pwctl fields */
+ config = 1 << MIPS_PWCTL_PWEN_SHIFT;
+ write_c0_pwctl(config);
+ pr_info("Hardware Page Table Walker enabled\n");
+
+ print_htw_config();
+}
+
void build_tlb_refill_handler(void)
{
/*
@@ -2258,5 +2349,8 @@ void build_tlb_refill_handler(void)
}
if (cpu_has_local_ebase)
build_r4000_tlb_refill_handler();
+ if (cpu_has_htw)
+ config_htw_params();
+
}
}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index ecc2785f7858..e4f43baa8f67 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -42,6 +42,10 @@ static unsigned int ipi_map[NR_CPUS];
static DEFINE_RAW_SPINLOCK(mips_irq_lock);
+#ifdef CONFIG_MIPS_GIC_IPI
+DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS);
+#endif
+
static inline int mips_pcibios_iack(void)
{
int irq;
@@ -125,16 +129,22 @@ static void malta_hw0_irqdispatch(void)
static void malta_ipi_irqdispatch(void)
{
- int irq;
+#ifdef CONFIG_MIPS_GIC_IPI
+ unsigned long irq;
+ DECLARE_BITMAP(pending, GIC_NUM_INTRS);
- if (gic_compare_int())
- do_IRQ(MIPS_GIC_IRQ_BASE);
+ gic_get_int_mask(pending, ipi_ints);
+
+ irq = find_first_bit(pending, GIC_NUM_INTRS);
- irq = gic_get_int();
- if (irq < 0)
- return; /* interrupt has already been cleared */
+ while (irq < GIC_NUM_INTRS) {
+ do_IRQ(MIPS_GIC_IRQ_BASE + irq);
- do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+ irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1);
+ }
+#endif
+ if (gic_compare_int())
+ do_IRQ(MIPS_GIC_IRQ_BASE);
}
static void corehi_irqdispatch(void)
@@ -427,8 +437,9 @@ static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
gic_intr_map[intr].pin = cpupin;
gic_intr_map[intr].polarity = GIC_POL_POS;
gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
- gic_intr_map[intr].flags = GIC_FLAG_IPI;
+ gic_intr_map[intr].flags = 0;
ipi_map[cpu] |= (1 << (cpupin + 2));
+ bitmap_set(ipi_ints, intr, 1);
}
static void __init fill_ipi_map(void)
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 6d9773096750..0c35dee0a215 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/maar.h>
#include <asm/sections.h>
#include <asm/fw/fw.h>
@@ -164,3 +165,28 @@ void __init prom_free_prom_memory(void)
addr, addr + boot_mem_map.map[i].size);
}
}
+
+unsigned platform_maar_init(unsigned num_pairs)
+{
+ phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
+ struct maar_config cfg[] = {
+ /* DRAM preceding I/O */
+ { 0x00000000, 0x0fffffff, MIPS_MAAR_S },
+
+ /* DRAM following I/O */
+ { 0x20000000, mem_end, MIPS_MAAR_S },
+
+ /* DRAM alias in upper half of physical */
+ { 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
+ };
+ unsigned i, num_cfg = ARRAY_SIZE(cfg);
+
+ /* If DRAM fits before I/O, drop the region following it */
+ if (physical_memsize <= 0x10000000) {
+ num_cfg--;
+ for (i = 1; i < num_cfg; i++)
+ cfg[i] = cfg[i + 1];
+ }
+
+ return maar_config(cfg, num_cfg, num_pairs);
+}
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index b87390a56a2f..05a56619ece2 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -131,7 +131,7 @@
* @target: Memory location for the compiled filter
*/
struct jit_ctx {
- const struct sk_filter *skf;
+ const struct bpf_prog *skf;
unsigned int prologue_bytes;
u32 idx;
u32 flags;
@@ -789,7 +789,7 @@ static int pkt_type_offset(void)
static int build_body(struct jit_ctx *ctx)
{
void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
- const struct sk_filter *prog = ctx->skf;
+ const struct bpf_prog *prog = ctx->skf;
const struct sock_filter *inst;
unsigned int i, off, load_order, condt;
u32 k, b_off __maybe_unused;
@@ -1369,7 +1369,7 @@ jmp_cmp:
int bpf_jit_enable __read_mostly;
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct jit_ctx ctx;
unsigned int alloc_size, tmp_idx;
@@ -1423,7 +1423,7 @@ out:
kfree(ctx.offsets);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index ff8a5539b363..6523d558ff5a 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_LEMOTE_MACH3A) += fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_LOONGSON_MACH3X) += fixup-loongson3.o ops-loongson3.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 0e046d82e4e3..d54ea93651ac 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -199,8 +199,6 @@ static struct {
char *tx4927_pcibios_setup(char *str)
{
- unsigned long val;
-
if (!strncmp(str, "trdyto=", 7)) {
u8 val = 0;
if (kstrtou8(str + 7, 0, &val) == 0)
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index 563d1f61d6ee..c19600a03460 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -7,6 +7,7 @@
* Support for all devices (greater than 16) added by David Gathright.
*/
+#include <linux/clk.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -364,6 +365,7 @@ static int alchemy_pci_probe(struct platform_device *pdev)
void __iomem *virt_io;
unsigned long val;
struct resource *r;
+ struct clk *c;
int ret;
/* need at least PCI IRQ mapping table */
@@ -393,11 +395,24 @@ static int alchemy_pci_probe(struct platform_device *pdev)
goto out1;
}
+ c = clk_get(&pdev->dev, "pci_clko");
+ if (IS_ERR(c)) {
+ dev_err(&pdev->dev, "unable to find PCI clock\n");
+ ret = PTR_ERR(c);
+ goto out2;
+ }
+
+ ret = clk_prepare_enable(c);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot enable PCI clock\n");
+ goto out6;
+ }
+
ctx->regs = ioremap_nocache(r->start, resource_size(r));
if (!ctx->regs) {
dev_err(&pdev->dev, "cannot map pci regs\n");
ret = -ENODEV;
- goto out2;
+ goto out5;
}
/* map parts of the PCI IO area */
@@ -465,12 +480,19 @@ static int alchemy_pci_probe(struct platform_device *pdev)
register_syscore_ops(&alchemy_pci_pmops);
register_pci_controller(&ctx->alchemy_pci_ctrl);
+ dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
+ clk_get_rate(c) / 1000000);
+
return 0;
out4:
iounmap(virt_io);
out3:
iounmap(ctx->regs);
+out5:
+ clk_disable_unprepare(c);
+out6:
+ clk_put(c);
out2:
release_mem_region(r->start, resource_size(r));
out1:
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index 251395210e23..7c4598cb6de8 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -81,7 +81,7 @@ static int __init plat_of_setup(void)
panic("device tree not present");
strlcpy(of_ids[0].compatible, soc_info.compatible, len);
- strncpy(of_ids[1].compatible, "palmbus", len);
+ strlcpy(of_ids[1].compatible, "palmbus", len);
if (of_platform_populate(NULL, of_ids, NULL, NULL))
panic("failed to populate DT");
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 3af00b2a26ee..e31e8cdcb296 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -223,6 +223,7 @@ static struct platform_device rb532_wdt = {
static struct plat_serial8250_port rb532_uart_res[] = {
{
+ .type = PORT_16550A,
.membase = (char *)KSEG1ADDR(REGBASE + UART0BASE),
.irq = UART0_IRQ,
.regshift = 2,
@@ -250,28 +251,6 @@ static struct platform_device *rb532_devs[] = {
&rb532_wdt
};
-static void __init parse_mac_addr(char *macstr)
-{
- int i, h, l;
-
- for (i = 0; i < 6; i++) {
- if (i != 5 && *(macstr + 2) != ':')
- return;
-
- h = hex_to_bin(*macstr++);
- if (h == -1)
- return;
-
- l = hex_to_bin(*macstr++);
- if (l == -1)
- return;
-
- macstr++;
- korina_dev0_data.mac[i] = (h << 4) + l;
- }
-}
-
-
/* NAND definitions */
#define NAND_CHIP_DELAY 25
@@ -333,7 +312,10 @@ static int __init plat_setup_devices(void)
static int __init setup_kmac(char *s)
{
printk(KERN_INFO "korina mac = %s\n", s);
- parse_mac_addr(s);
+ if (!mac_pton(s, korina_dev0_data.mac)) {
+ printk(KERN_ERR "Invalid mac\n");
+ return -EINVAL;
+ }
return 0;
}
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index 8e52446286ca..8f1b86d4da84 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -27,8 +27,14 @@ static struct {
{ .name = "SGI GR2/GR3", .id = 0x7f },
};
+static void gio_bus_release(struct device *dev)
+{
+ kfree(dev);
+}
+
static struct device gio_bus = {
.init_name = "gio",
+ .release = &gio_bus_release,
};
/**
@@ -413,8 +419,10 @@ int __init ip22_gio_init(void)
int ret;
ret = device_register(&gio_bus);
- if (ret)
+ if (ret) {
+ put_device(&gio_bus);
return ret;
+ }
ret = bus_register(&gio_bus_type);
if (!ret) {
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c
index 4642f56e70e5..566c58bd44d0 100644
--- a/arch/mips/txx9/generic/7segled.c
+++ b/arch/mips/txx9/generic/7segled.c
@@ -83,6 +83,11 @@ static struct bus_type tx_7segled_subsys = {
.dev_name = "7segled",
};
+static void tx_7segled_release(struct device *dev)
+{
+ kfree(dev);
+}
+
static int __init tx_7segled_init_sysfs(void)
{
int error, i;
@@ -103,11 +108,14 @@ static int __init tx_7segled_init_sysfs(void)
}
dev->id = i;
dev->bus = &tx_7segled_subsys;
+ dev->release = &tx_7segled_release;
error = device_register(dev);
- if (!error) {
- device_create_file(dev, &dev_attr_ascii);
- device_create_file(dev, &dev_attr_raw);
+ if (error) {
+ put_device(dev);
+ return error;
}
+ device_create_file(dev, &dev_attr_ascii);
+ device_create_file(dev, &dev_attr_raw);
}
return error;
}
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 28713274e0cc..a77698ff2b6f 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -268,7 +268,7 @@ static int txx9_i8259_irq_setup(int irq)
return err;
}
-static void quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __init_refok quirk_slc90e66_bridge(struct pci_dev *dev)
{
int irq; /* PCI/ISA Bridge interrupt */
u8 reg_64;
@@ -331,7 +331,7 @@ static void quirk_slc90e66_ide(struct pci_dev *dev)
* !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
*/
dat |= 0x01;
- pci_write_config_byte(dev, regs[i], dat);
+ pci_write_config_byte(dev, 0x5c, dat);
pci_read_config_byte(dev, 0x5c, &dat);
printk(KERN_CONT " REG5C %02x", dat);
printk(KERN_CONT "\n");
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index dd2cf25b5ae5..9ff200ae1c9a 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -937,6 +937,14 @@ static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj,
return size;
}
+static void txx9_device_release(struct device *dev)
+{
+ struct txx9_sramc_dev *tdev;
+
+ tdev = container_of(dev, struct txx9_sramc_dev, dev);
+ kfree(tdev);
+}
+
void __init txx9_sramc_init(struct resource *r)
{
struct txx9_sramc_dev *dev;
@@ -951,8 +959,11 @@ void __init txx9_sramc_init(struct resource *r)
return;
size = resource_size(r);
dev->base = ioremap(r->start, size);
- if (!dev->base)
- goto exit;
+ if (!dev->base) {
+ kfree(dev);
+ return;
+ }
+ dev->dev.release = &txx9_device_release;
dev->dev.bus = &txx9_sramc_subsys;
sysfs_bin_attr_init(&dev->bindata_attr);
dev->bindata_attr.attr.name = "bindata";
@@ -963,17 +974,15 @@ void __init txx9_sramc_init(struct resource *r)
dev->bindata_attr.private = dev;
err = device_register(&dev->dev);
if (err)
- goto exit;
+ goto exit_put;
err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
if (err) {
device_unregister(&dev->dev);
- goto exit;
- }
- return;
-exit:
- if (dev) {
- if (dev->base)
- iounmap(dev->base);
+ iounmap(dev->base);
kfree(dev);
}
+ return;
+exit_put:
+ put_device(&dev->dev);
+ return;
}
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 654d5ba6e310..ecbd6676bd33 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -6,4 +6,5 @@ generic-y += exec.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index 8b80b19d0c8a..769d5ed8e992 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -68,7 +68,9 @@ extern struct mn10300_cpuinfo cpu_data[];
extern void identify_cpu(struct mn10300_cpuinfo *);
extern void print_cpu_info(struct mn10300_cpuinfo *);
extern void dodgy_tsc(void);
+
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
/*
* User space process size: 1.75GB (default).
diff --git a/arch/mn10300/include/asm/scatterlist.h b/arch/mn10300/include/asm/scatterlist.h
deleted file mode 100644
index 7baa4006008a..000000000000
--- a/arch/mn10300/include/asm/scatterlist.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* MN10300 Scatterlist definitions
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_SCATTERLIST_H
-#define _ASM_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCATTERLIST_H */
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index 9dfac5cd16e6..a6c0858592c3 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigcontext __user *sc,
/*
* determine which stack to use..
*/
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
size_t frame_size)
{
- unsigned long sp;
-
- /* default to using normal stack */
- sp = regs->sp;
-
- /* this is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (sas_ss_flags(sp) == 0)
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
+ unsigned long sp = sigsp(regs->sp, ksig);
return (void __user *) ((sp - frame_size) & ~7UL);
}
@@ -207,16 +198,16 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
/*
* set up a normal signal frame
*/
-static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
struct sigframe __user *frame;
- int rsig;
+ int rsig, sig = ksig->sig;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
rsig = sig;
if (sig < 32 &&
@@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
if (__put_user(rsig, &frame->sig) < 0 ||
__put_user(&frame->sc, &frame->psc) < 0)
- goto give_sigsegv;
+ return -EFAULT;
if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
- goto give_sigsegv;
+ return -EFAULT;
if (_NSIG_WORDS > 1) {
if (__copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* set up to return from userspace. If provided, use a stub already in
* userspace */
- if (ka->sa.sa_flags & SA_RESTORER) {
- if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
- goto give_sigsegv;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+ return -EFAULT;
} else {
if (__put_user((void (*)(void))frame->retcode,
&frame->pretcode))
- goto give_sigsegv;
+ return -EFAULT;
/* this is mov $,d0; syscall 0 */
if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
__put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
__put_user(0x00, (char *)(frame->retcode + 2)) ||
__put_user(0xf0, (char *)(frame->retcode + 3)) ||
__put_user(0xe0, (char *)(frame->retcode + 4)))
- goto give_sigsegv;
+ return -EFAULT;
flush_icache_range((unsigned long) frame->retcode,
(unsigned long) frame->retcode + 5);
}
/* set up registers for signal handler */
regs->sp = (unsigned long) frame;
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->d0 = sig;
regs->d1 = (unsigned long) &frame->sc;
@@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/*
* set up a realtime signal frame
*/
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
- int rsig;
+ int rsig, sig = ksig->sig;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
rsig = sig;
if (sig < 32 &&
@@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user(rsig, &frame->sig) ||
__put_user(&frame->info, &frame->pinfo) ||
__put_user(&frame->uc, &frame->puc) ||
- copy_siginfo_to_user(&frame->info, info))
- goto give_sigsegv;
+ copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
/* create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) ||
@@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
setup_sigcontext(&frame->uc.uc_mcontext,
&frame->fpuctx, regs, set->sig[0]) ||
__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
- goto give_sigsegv;
+ return -EFAULT;
/* set up to return from userspace. If provided, use a stub already in
* userspace */
- if (ka->sa.sa_flags & SA_RESTORER) {
- if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
- goto give_sigsegv;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
+ return -EFAULT;
+
} else {
if (__put_user((void(*)(void))frame->retcode,
&frame->pretcode) ||
@@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
__put_user(0x00, (char *)(frame->retcode + 2)) ||
__put_user(0xf0, (char *)(frame->retcode + 3)) ||
__put_user(0xe0, (char *)(frame->retcode + 4)))
- goto give_sigsegv;
+ return -EFAULT;
flush_icache_range((u_long) frame->retcode,
(u_long) frame->retcode + 5);
@@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
regs->sp = (unsigned long) frame;
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->d0 = sig;
regs->d1 = (long) &frame->info;
@@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
static inline void stepback(struct pt_regs *regs)
@@ -360,9 +344,7 @@ static inline void stepback(struct pt_regs *regs)
/*
* handle the actual delivery of a signal to userspace
*/
-static int handle_signal(int sig,
- siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs)
+static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -377,7 +359,7 @@ static int handle_signal(int sig,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->d0 = -EINTR;
break;
}
@@ -390,15 +372,12 @@ static int handle_signal(int sig,
}
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
- if (ret)
- return ret;
+ ret = setup_frame(ksig, oldset, regs);
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
return 0;
}
@@ -407,15 +386,10 @@ static int handle_signal(int sig,
*/
static void do_signal(struct pt_regs *regs)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- if (handle_signal(signr, &info, &ka, regs) == 0) {
- }
+ struct ksignal ksig;
+ if (get_signal(&ksig)) {
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index e71d712afb79..88e83368bbf5 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -22,6 +22,7 @@ config OPENRISC
select GENERIC_STRNLEN_USER
select MODULES_USE_ELF_RELA
select HAVE_DEBUG_STACKOVERFLOW
+ select OR1K_PIC
config MMU
def_bool y
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h
index eb612b1865d2..b84634cc95eb 100644
--- a/arch/openrisc/include/asm/irq.h
+++ b/arch/openrisc/include/asm/irq.h
@@ -24,4 +24,7 @@
#define NO_IRQ (-1)
+void handle_IRQ(unsigned int, struct pt_regs *);
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
+
#endif /* __ASM_OPENRISC_IRQ_H__ */
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index cab746fa9e87..4d235e3d2534 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -101,6 +101,7 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
#define init_stack (init_thread_union.stack)
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#endif /* __ASSEMBLY__ */
#endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
index 8ec77bc9f1e7..967eb1430203 100644
--- a/arch/openrisc/kernel/irq.c
+++ b/arch/openrisc/kernel/irq.c
@@ -16,11 +16,10 @@
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/of.h>
#include <linux/ftrace.h>
#include <linux/irq.h>
+#include <linux/irqchip.h>
#include <linux/export.h>
-#include <linux/irqdomain.h>
#include <linux/irqflags.h>
/* read interrupt enabled status */
@@ -37,150 +36,31 @@ void arch_local_irq_restore(unsigned long flags)
}
EXPORT_SYMBOL(arch_local_irq_restore);
-
-/* OR1K PIC implementation */
-
-/* We're a couple of cycles faster than the generic implementations with
- * these 'fast' versions.
- */
-
-static void or1k_pic_mask(struct irq_data *data)
-{
- mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
-}
-
-static void or1k_pic_unmask(struct irq_data *data)
-{
- mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
-}
-
-static void or1k_pic_ack(struct irq_data *data)
-{
- /* EDGE-triggered interrupts need to be ack'ed in order to clear
- * the latch.
- * LEVEL-triggered interrupts do not need to be ack'ed; however,
- * ack'ing the interrupt has no ill-effect and is quicker than
- * trying to figure out what type it is...
- */
-
- /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
- * interrupt, but the OR1200 does this backwards and requires a 0
- * to be written...
- */
-
-#ifdef CONFIG_OR1K_1200
- /* There are two oddities with the OR1200 PIC implementation:
- * i) LEVEL-triggered interrupts are latched and need to be cleared
- * ii) the interrupt latch is cleared by writing a 0 to the bit,
- * as opposed to a 1 as mandated by the spec
- */
-
- mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
-#else
- WARN(1, "Interrupt handling possibly broken\n");
- mtspr(SPR_PICSR, (1UL << data->hwirq));
-#endif
-}
-
-static void or1k_pic_mask_ack(struct irq_data *data)
-{
- /* Comments for pic_ack apply here, too */
-
-#ifdef CONFIG_OR1K_1200
- mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
- mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
-#else
- WARN(1, "Interrupt handling possibly broken\n");
- mtspr(SPR_PICMR, (1UL << data->hwirq));
- mtspr(SPR_PICSR, (1UL << data->hwirq));
-#endif
-}
-
-#if 0
-static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
-{
- /* There's nothing to do in the PIC configuration when changing
- * flow type. Level and edge-triggered interrupts are both
- * supported, but it's PIC-implementation specific which type
- * is handled. */
-
- return irq_setup_alt_chip(data, flow_type);
-}
-#endif
-
-static struct irq_chip or1k_dev = {
- .name = "or1k-PIC",
- .irq_unmask = or1k_pic_unmask,
- .irq_mask = or1k_pic_mask,
- .irq_ack = or1k_pic_ack,
- .irq_mask_ack = or1k_pic_mask_ack,
-};
-
-static struct irq_domain *root_domain;
-
-static inline int pic_get_irq(int first)
-{
- int hwirq;
-
- hwirq = ffs(mfspr(SPR_PICSR) >> first);
- if (!hwirq)
- return NO_IRQ;
- else
- hwirq = hwirq + first -1;
-
- return irq_find_mapping(root_domain, hwirq);
-}
-
-
-static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+void __init init_IRQ(void)
{
- irq_set_chip_and_handler_name(irq, &or1k_dev,
- handle_level_irq, "level");
- irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE);
-
- return 0;
+ irqchip_init();
}
-static const struct irq_domain_ops or1k_irq_domain_ops = {
- .xlate = irq_domain_xlate_onecell,
- .map = or1k_map,
-};
-
-/*
- * This sets up the IRQ domain for the PIC built in to the OpenRISC
- * 1000 CPU. This is the "root" domain as these are the interrupts
- * that directly trigger an exception in the CPU.
- */
-static void __init or1k_irq_init(void)
-{
- struct device_node *intc = NULL;
-
- /* The interrupt controller device node is mandatory */
- intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic");
- BUG_ON(!intc);
-
- /* Disable all interrupts until explicitly requested */
- mtspr(SPR_PICMR, (0UL));
-
- root_domain = irq_domain_add_linear(intc, 32,
- &or1k_irq_domain_ops, NULL);
-}
+static void (*handle_arch_irq)(struct pt_regs *);
-void __init init_IRQ(void)
+void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
{
- or1k_irq_init();
+ handle_arch_irq = handle_irq;
}
-void __irq_entry do_IRQ(struct pt_regs *regs)
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{
- int irq = -1;
struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
- while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
- generic_handle_irq(irq);
+ generic_handle_irq(irq);
irq_exit();
set_irq_regs(old_regs);
}
+
+void __irq_entry do_IRQ(struct pt_regs *regs)
+{
+ handle_arch_irq(regs);
+}
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 66775bc07a8e..7d1b8235bf90 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -132,30 +132,16 @@ static inline unsigned long align_sigframe(unsigned long sp)
* or the alternate stack.
*/
-static inline void __user *get_sigframe(struct k_sigaction *ka,
+static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, size_t frame_size)
{
unsigned long sp = regs->sp;
- int onsigstack = on_sig_stack(sp);
/* redzone */
sp -= STACK_FRAME_OVERHEAD;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
- if (current->sas_ss_size)
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
-
+ sp = sigsp(sp, ksig);
sp = align_sigframe(sp - frame_size);
- /*
- * If we are on the alternate signal stack and would overflow it, don't.
- * Return an always-bogus address instead so we will die with SIGSEGV.
- */
- if (onsigstack && !likely(on_sig_stack(sp)))
- return (void __user *)-1L;
-
return (void __user *)sp;
}
@@ -173,7 +159,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
unsigned long return_ip;
int err = 0;
- frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT;
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 108d48e652af..6e75e2030927 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -6,7 +6,6 @@ config PARISC
select HAVE_OPROFILE
select HAVE_FUNCTION_TRACER if 64BIT
select HAVE_FUNCTION_GRAPH_TRACER if 64BIT
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST if 64BIT
select ARCH_WANT_FRAME_POINTERS
select RTC_CLASS
select RTC_DRV_GENERIC
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
index dc0d7ce71ea7..e945c08892fa 100644
--- a/arch/parisc/configs/generic-64bit_defconfig
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -241,7 +241,6 @@ CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_STAGING=y
-# CONFIG_NET_VENDOR_SILICOM is not set
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index d951c9681ab3..689a8ade3606 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -338,6 +338,7 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30])
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
/* Used as a macro to identify the combined VIPT/PIPT cached
* CPUs which require a guarantee of coherency (no inequivalent
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index 5beb97bafbb1..559d400f9385 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -112,6 +112,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
unsigned long long calltime;
struct ftrace_graph_ent trace;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
@@ -152,9 +155,6 @@ void ftrace_function_trampoline(unsigned long parent,
{
extern ftrace_func_t ftrace_trace_function;
- if (function_trace_stop)
- return;
-
if (ftrace_trace_function != ftrace_stub) {
ftrace_trace_function(parent, self_addr);
return;
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 1cba8f29bb49..012d4fa63d97 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -227,8 +227,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc
}
static long
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs, int in_syscall)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
+ int in_syscall)
{
struct rt_sigframe __user *frame;
unsigned long rp, usp;
@@ -241,10 +241,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
usp = (regs->gr[30] & ~(0x01UL));
/*FIXME: frame_size parameter is unused, remove it. */
- frame = get_sigframe(ka, usp, sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
DBG(1,"SETUP_RT_FRAME: START\n");
- DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
+ DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
#ifdef CONFIG_64BIT
@@ -253,7 +253,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (is_compat_task()) {
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
- err |= copy_siginfo_to_user32(&compat_frame->info, info);
+ err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
@@ -265,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
{
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
@@ -275,7 +275,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. The first words of tramp are used to
@@ -312,9 +312,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
if (err)
- goto give_sigsegv;
+ return -EFAULT;
- haddr = A(ka->sa.sa_handler);
+ haddr = A(ksig->ka.sa.sa_handler);
/* The sa_handler may be a pointer to a function descriptor */
#ifdef CONFIG_64BIT
if (is_compat_task()) {
@@ -326,7 +326,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
haddr = fdesc.addr;
regs->gr[19] = fdesc.gp;
@@ -339,7 +339,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
haddr = fdesc.addr;
regs->gr[19] = fdesc.gp;
@@ -386,7 +386,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
regs->gr[2] = rp; /* userland return pointer */
- regs->gr[26] = sig; /* signal number */
+ regs->gr[26] = ksig->sig; /* signal number */
#ifdef CONFIG_64BIT
if (is_compat_task()) {
@@ -410,11 +410,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->gr[30],
regs->iaoq[0], regs->iaoq[1], rp);
- return 1;
-
-give_sigsegv:
- DBG(1,"setup_rt_frame: sending SIGSEGV\n");
- force_sigsegv(sig, current);
return 0;
}
@@ -423,20 +418,19 @@ give_sigsegv:
*/
static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs *regs, int in_syscall)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
{
+ int ret;
sigset_t *oldset = sigmask_to_save();
+
DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
- sig, ka, info, oldset, regs);
+ ksig->sig, ksig->ka, ksig->info, oldset, regs);
/* Set up the stack frame */
- if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
- return;
+ ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP) ||
- test_thread_flag(TIF_BLOCKSTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
+ test_thread_flag(TIF_BLOCKSTEP));
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
@@ -544,22 +538,18 @@ insert_restart_trampoline(struct pt_regs *regs)
asmlinkage void
do_signal(struct pt_regs *regs, long in_syscall)
{
- siginfo_t info;
- struct k_sigaction ka;
- int signr;
+ struct ksignal ksig;
DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
regs, regs->sr[7], in_syscall);
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
-
- if (signr > 0) {
+ if (get_signal(&ksig)) {
+ DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
/* Restart a system call if necessary. */
if (in_syscall)
- syscall_restart(regs, &ka);
+ syscall_restart(regs, &ksig.ka);
- handle_signal(signr, &info, &ka, regs, in_syscall);
+ handle_signal(&ksig, regs, in_syscall);
return;
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 80b94b0add1f..a577609f8ed6 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -111,6 +111,7 @@ config PPC
select HAVE_DMA_API_DEBUG
select HAVE_OPROFILE
select HAVE_DEBUG_KMEMLEAK
+ select ARCH_HAS_SG_CHAIN
select GENERIC_ATOMIC64 if PPC32
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_PERF_EVENTS
@@ -398,6 +399,8 @@ config PPC64_SUPPORTS_MEMORY_FAILURE
config KEXEC
bool "kexec system call"
depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 35d16bd2760b..ec2e40f2cc11 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -202,9 +202,7 @@ config PPC_EARLY_DEBUG_BEAT
config PPC_EARLY_DEBUG_44x
bool "Early serial debugging for IBM/AMCC 44x CPUs"
- # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water
- # mark, which doesn't work with current 440 KVM.
- depends on 44x && !KVM
+ depends on 44x
help
Select this to enable early debugging for IBM 44x chips via the
inbuilt serial port. If you enable this, ensure you set
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
index 5290df83ff30..69ce1026c948 100644
--- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
@@ -359,6 +359,7 @@
compatible = "fsl,qoriq-core-mux-1.0";
clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>;
clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2";
+ clock-output-names = "cmux2";
};
mux3: mux3@60 {
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi
index f75b4f820c3c..7d4a6a2354f4 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-sec6.0-0.dtsi
@@ -32,7 +32,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
- compatible = "fsl,sec-v6.0";
+ compatible = "fsl,sec-v6.0", "fsl,sec-v5.0",
+ "fsl,sec-v4.0";
fsl,sec-era = <6>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi
new file mode 100644
index 000000000000..082ec2044060
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi
@@ -0,0 +1,69 @@
+/*
+ * T2080 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t2081si-post.dtsi"
+
+&soc {
+/include/ "qoriq-sata2-0.dtsi"
+ sata@220000 {
+ fsl,iommu-parent = <&pamu1>;
+ fsl,liodn-reg = <&guts 0x550>; /* SATA1LIODNR */
+ };
+
+/include/ "qoriq-sata2-1.dtsi"
+ sata@221000 {
+ fsl,iommu-parent = <&pamu1>;
+ fsl,liodn-reg = <&guts 0x554>; /* SATA2LIODNR */
+ };
+};
+
+&rio {
+ compatible = "fsl,srio";
+ interrupts = <16 2 1 11>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ port1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <1>;
+ };
+
+ port2 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <2>;
+ };
+};
diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
new file mode 100644
index 000000000000..97479f0ce630
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
@@ -0,0 +1,435 @@
+/*
+ * T2081 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc", "simple-bus";
+ interrupts = <25 2 0 0>;
+};
+
+/* controller at 0x240000 */
+&pci0 {
+ compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ interrupts = <20 2 0 0>;
+ fsl,iommu-parent = <&pamu0>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <20 2 0 0>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x250000 */
+&pci1 {
+ compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ interrupts = <21 2 0 0>;
+ fsl,iommu-parent = <&pamu0>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <21 2 0 0>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x260000 */
+&pci2 {
+ compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ interrupts = <22 2 0 0>;
+ fsl,iommu-parent = <&pamu0>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <22 2 0 0>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x270000 */
+&pci3 {
+ compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ interrupts = <23 2 0 0>;
+ fsl,iommu-parent = <&pamu0>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <23 2 0 0>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+};
+
+&dcsr {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,dcsr", "simple-bus";
+
+ dcsr-epu@0 {
+ compatible = "fsl,t2080-dcsr-epu", "fsl,dcsr-epu";
+ interrupts = <52 2 0 0
+ 84 2 0 0
+ 85 2 0 0
+ 94 2 0 0
+ 95 2 0 0>;
+ reg = <0x0 0x1000>;
+ };
+ dcsr-npc {
+ compatible = "fsl,t2080-dcsr-cnpc", "fsl,dcsr-cnpc";
+ reg = <0x1000 0x1000 0x1002000 0x10000>;
+ };
+ dcsr-nxc@2000 {
+ compatible = "fsl,dcsr-nxc";
+ reg = <0x2000 0x1000>;
+ };
+ dcsr-corenet {
+ compatible = "fsl,dcsr-corenet";
+ reg = <0x8000 0x1000 0x1A000 0x1000>;
+ };
+ dcsr-ocn@11000 {
+ compatible = "fsl,t2080-dcsr-ocn", "fsl,dcsr-ocn";
+ reg = <0x11000 0x1000>;
+ };
+ dcsr-ddr@12000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr1>;
+ reg = <0x12000 0x1000>;
+ };
+ dcsr-nal@18000 {
+ compatible = "fsl,t2080-dcsr-nal", "fsl,dcsr-nal";
+ reg = <0x18000 0x1000>;
+ };
+ dcsr-rcpm@22000 {
+ compatible = "fsl,t2080-dcsr-rcpm", "fsl,dcsr-rcpm";
+ reg = <0x22000 0x1000>;
+ };
+ dcsr-snpc@30000 {
+ compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+ reg = <0x30000 0x1000 0x1022000 0x10000>;
+ };
+ dcsr-snpc@31000 {
+ compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+ reg = <0x31000 0x1000 0x1042000 0x10000>;
+ };
+ dcsr-snpc@32000 {
+ compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc";
+ reg = <0x32000 0x1000 0x1062000 0x10000>;
+ };
+ dcsr-cpu-sb-proxy@100000 {
+ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu0>;
+ reg = <0x100000 0x1000 0x101000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy@108000 {
+ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu1>;
+ reg = <0x108000 0x1000 0x109000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy@110000 {
+ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu2>;
+ reg = <0x110000 0x1000 0x111000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy@118000 {
+ compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu3>;
+ reg = <0x118000 0x1000 0x119000 0x1000>;
+ };
+};
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ ddr1: memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.7",
+ "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,t2080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000
+ 0x11000 0x1000
+ 0x12000 0x1000>;
+ interrupts = <16 2 1 27
+ 16 2 1 26
+ 16 2 1 25>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet2-cf", "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x3000>;
+ fsl,portid-mapping = <0x8000>;
+ ranges = <0 0x20000 0x3000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+
+ pamu0: pamu@0 {
+ reg = <0 0x1000>;
+ fsl,primary-cache-geometry = <32 1>;
+ fsl,secondary-cache-geometry = <128 2>;
+ };
+
+ pamu1: pamu@1000 {
+ reg = <0x1000 0x1000>;
+ fsl,primary-cache-geometry = <32 1>;
+ fsl,secondary-cache-geometry = <128 2>;
+ };
+
+ pamu2: pamu@2000 {
+ reg = <0x2000 0x1000>;
+ fsl,primary-cache-geometry = <32 1>;
+ fsl,secondary-cache-geometry = <128 2>;
+ };
+ };
+
+/include/ "qoriq-mpic4.3.dtsi"
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,t2080-device-config", "fsl,qoriq-device-config-2.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ fsl,liodn-bits = <12>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0";
+ ranges = <0x0 0xe1000 0x1000>;
+ reg = <0xe1000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sysclk: sysclk {
+ #clock-cells = <0>;
+ compatible = "fsl,qoriq-sysclk-2.0";
+ clock-output-names = "sysclk", "fixed-clock";
+ };
+
+ pll0: pll0@800 {
+ #clock-cells = <1>;
+ reg = <0x800 4>;
+ compatible = "fsl,qoriq-core-pll-2.0";
+ clocks = <&sysclk>;
+ clock-output-names = "pll0", "pll0-div2", "pll0-div4";
+ };
+
+ pll1: pll1@820 {
+ #clock-cells = <1>;
+ reg = <0x820 4>;
+ compatible = "fsl,qoriq-core-pll-2.0";
+ clocks = <&sysclk>;
+ clock-output-names = "pll1", "pll1-div2", "pll1-div4";
+ };
+
+ mux0: mux0@0 {
+ #clock-cells = <0>;
+ reg = <0x0 4>;
+ compatible = "fsl,qoriq-core-mux-2.0";
+ clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>,
+ <&pll1 0>, <&pll1 1>, <&pll1 2>;
+ clock-names = "pll0", "pll0-div2", "pll1-div4",
+ "pll1", "pll1-div2", "pll1-div4";
+ clock-output-names = "cmux0";
+ };
+
+ mux1: mux1@20 {
+ #clock-cells = <0>;
+ reg = <0x20 4>;
+ compatible = "fsl,qoriq-core-mux-2.0";
+ clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>,
+ <&pll1 0>, <&pll1 1>, <&pll1 2>;
+ clock-names = "pll0", "pll0-div2", "pll1-div4",
+ "pll1", "pll1-div2", "pll1-div4";
+ clock-output-names = "cmux1";
+ };
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,t2080-rcpm", "fsl,qoriq-rcpm-2.0";
+ reg = <0xe2000 0x1000>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,t2080-sfp";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,t2080-serdes";
+ reg = <0xea000 0x4000>;
+ };
+
+/include/ "elo3-dma-0.dtsi"
+ dma@100300 {
+ fsl,iommu-parent = <&pamu0>;
+ fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */
+ };
+/include/ "elo3-dma-1.dtsi"
+ dma@101300 {
+ fsl,iommu-parent = <&pamu0>;
+ fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */
+ };
+/include/ "elo3-dma-2.dtsi"
+ dma@102300 {
+ fsl,iommu-parent = <&pamu0>;
+ fsl,liodn-reg = <&guts 0x588>; /* DMA3LIODNR */
+ };
+
+/include/ "qoriq-espi-0.dtsi"
+ spi@110000 {
+ fsl,espi-num-chipselects = <4>;
+ };
+
+/include/ "qoriq-esdhc-0.dtsi"
+ sdhc@114000 {
+ compatible = "fsl,t2080-esdhc", "fsl,esdhc";
+ fsl,iommu-parent = <&pamu1>;
+ fsl,liodn-reg = <&guts 0x530>; /* SDMMCLIODNR */
+ sdhci,auto-cmd12;
+ };
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-gpio-1.dtsi"
+/include/ "qoriq-gpio-2.dtsi"
+/include/ "qoriq-gpio-3.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+ usb0: usb@210000 {
+ compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph";
+ fsl,iommu-parent = <&pamu1>;
+ fsl,liodn-reg = <&guts 0x520>; /* USB1LIODNR */
+ phy_type = "utmi";
+ port0;
+ };
+/include/ "qoriq-usb2-dr-0.dtsi"
+ usb1: usb@211000 {
+ compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr";
+ fsl,iommu-parent = <&pamu1>;
+ fsl,liodn-reg = <&guts 0x524>; /* USB1LIODNR */
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+/include/ "qoriq-sec5.2-0.dtsi"
+
+ L2_1: l2-cache-controller@c20000 {
+ /* Cluster 0 L2 cache */
+ compatible = "fsl,t2080-l2-cache-controller";
+ reg = <0xc20000 0x40000>;
+ next-level-cache = <&cpc>;
+ };
+};
diff --git a/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi
new file mode 100644
index 000000000000..e71ceb0e1100
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi
@@ -0,0 +1,99 @@
+/*
+ * T2080/T2081 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+
+ crypto = &crypto;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ dma2 = &dma2;
+ sdhc = &sdhc;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e6500@0 {
+ device_type = "cpu";
+ reg = <0 1>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ fsl,portid-mapping = <0x80000000>;
+ };
+ cpu1: PowerPC,e6500@2 {
+ device_type = "cpu";
+ reg = <2 3>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ fsl,portid-mapping = <0x80000000>;
+ };
+ cpu2: PowerPC,e6500@4 {
+ device_type = "cpu";
+ reg = <4 5>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ fsl,portid-mapping = <0x80000000>;
+ };
+ cpu3: PowerPC,e6500@6 {
+ device_type = "cpu";
+ reg = <6 7>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ fsl,portid-mapping = <0x80000000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
index 793669baa13e..a3d582e0361a 100644
--- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
@@ -476,6 +476,7 @@
/include/ "elo3-dma-0.dtsi"
/include/ "elo3-dma-1.dtsi"
+/include/ "elo3-dma-2.dtsi"
/include/ "qoriq-espi-0.dtsi"
spi@110000 {
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
index d2f157edbe81..261a3abb1a55 100644
--- a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi
@@ -57,6 +57,7 @@
pci3 = &pci3;
dma0 = &dma0;
dma1 = &dma1;
+ dma2 = &dma2;
sdhc = &sdhc;
};
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 2c0e1552d20b..7f9d14f5c4da 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -498,6 +498,7 @@
compatible = "fsl,mpc5121-dma";
reg = <0x14000 0x1800>;
interrupts = <65 0x8>;
+ #dma-cells = <1>;
};
};
diff --git a/arch/powerpc/boot/dts/t2080qds.dts b/arch/powerpc/boot/dts/t2080qds.dts
new file mode 100644
index 000000000000..aa1d6d8c169b
--- /dev/null
+++ b/arch/powerpc/boot/dts/t2080qds.dts
@@ -0,0 +1,57 @@
+/*
+ * T2080QDS Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xqds.dtsi"
+
+/ {
+ model = "fsl,T2080QDS";
+ compatible = "fsl,T2080QDS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ rio: rapidio@ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+ };
+ };
+};
+
+/include/ "fsl/t2080si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/t2080rdb.dts b/arch/powerpc/boot/dts/t2080rdb.dts
new file mode 100644
index 000000000000..e8891047600c
--- /dev/null
+++ b/arch/powerpc/boot/dts/t2080rdb.dts
@@ -0,0 +1,57 @@
+/*
+ * T2080PCIe-RDB Board Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xrdb.dtsi"
+
+/ {
+ model = "fsl,T2080RDB";
+ compatible = "fsl,T2080RDB";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ rio: rapidio@ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+ };
+ };
+};
+
+/include/ "fsl/t2080si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/t2081qds.dts b/arch/powerpc/boot/dts/t2081qds.dts
new file mode 100644
index 000000000000..8ec80a71e102
--- /dev/null
+++ b/arch/powerpc/boot/dts/t2081qds.dts
@@ -0,0 +1,46 @@
+/*
+ * T2081QDS Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/t208xsi-pre.dtsi"
+/include/ "t208xqds.dtsi"
+
+/ {
+ model = "fsl,T2081QDS";
+ compatible = "fsl,T2081QDS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+};
+
+/include/ "fsl/t2081si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/t208xqds.dtsi b/arch/powerpc/boot/dts/t208xqds.dtsi
new file mode 100644
index 000000000000..555dc6e03d89
--- /dev/null
+++ b/arch/powerpc/boot/dts/t208xqds.dtsi
@@ -0,0 +1,239 @@
+/*
+ * T2080/T2081 QDS Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+ model = "fsl,T2080QDS";
+ compatible = "fsl,T2080QDS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ ifc: localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x2000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000
+ 2 0 0xf 0xff800000 0x00010000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ nand@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc-nand";
+ reg = <0x2 0x0 0x10000>;
+ };
+
+ boardctrl: board-control@3,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,fpga-qixis";
+ reg = <3 0 0x300>;
+ ranges = <0 3 0 0x300>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ dcsr: dcsr@f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+ };
+
+ soc: soc@ffe000000 {
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q128a11"; /* 16MB */
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ };
+
+ flash@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "sst,sst25wf040";
+ reg = <1>;
+ spi-max-frequency = <35000000>;
+ };
+
+ flash@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "eon,en25s64";
+ reg = <2>;
+ spi-max-frequency = <35000000>;
+ };
+ };
+
+ i2c@118000 {
+ pca9547@77 {
+ compatible = "nxp,pca9547";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+
+ eeprom@50 {
+ compatible = "at24,24c512";
+ reg = <0x50>;
+ };
+
+ eeprom@51 {
+ compatible = "at24,24c02";
+ reg = <0x51>;
+ };
+
+ eeprom@57 {
+ compatible = "at24,24c02";
+ reg = <0x57>;
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds3232";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+ };
+
+ i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1>;
+
+ eeprom@55 {
+ compatible = "at24,24c02";
+ reg = <0x55>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+
+ ina220@40 {
+ compatible = "ti,ina220";
+ reg = <0x40>;
+ shunt-resistor = <1000>;
+ };
+
+ ina220@41 {
+ compatible = "ti,ina220";
+ reg = <0x41>;
+ shunt-resistor = <1000>;
+ };
+ };
+ };
+ };
+
+ sdhc@114000 {
+ voltage-ranges = <1800 1800 3300 3300>;
+ };
+ };
+
+ pci0: pcie@ffe240000 {
+ reg = <0xf 0xfe240000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe250000 {
+ reg = <0xf 0xfe250000 0 0x10000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe260000 {
+ reg = <0xf 0xfe260000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie@ffe270000 {
+ reg = <0xf 0xfe270000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/t208xrdb.dtsi b/arch/powerpc/boot/dts/t208xrdb.dtsi
new file mode 100644
index 000000000000..1481e192e783
--- /dev/null
+++ b/arch/powerpc/boot/dts/t208xrdb.dtsi
@@ -0,0 +1,184 @@
+/*
+ * T2080PCIe-RDB Board Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+ model = "fsl,T2080RDB";
+ compatible = "fsl,T2080RDB";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ ifc: localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x2000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000
+ 2 0 0xf 0xff800000 0x00010000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ nand@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc-nand";
+ reg = <0x2 0x0 0x10000>;
+ };
+
+ boardctrl: board-control@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,t2080-cpld";
+ reg = <3 0 0x300>;
+ ranges = <0 3 0 0x300>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ dcsr: dcsr@f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+ };
+
+ soc: soc@ffe000000 {
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q512a";
+ reg = <0>;
+ spi-max-frequency = <10000000>; /* input clock */
+ };
+ };
+
+ i2c@118000 {
+ adt7481@4c {
+ compatible = "adi,adt7481";
+ reg = <0x4c>;
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c256";
+ reg = <0x50>;
+ };
+ };
+
+ i2c@118100 {
+ pca9546@77 {
+ compatible = "nxp,pca9546";
+ reg = <0x77>;
+ };
+ };
+
+ sdhc@114000 {
+ voltage-ranges = <1800 1800 3300 3300>;
+ };
+ };
+
+ pci0: pcie@ffe240000 {
+ reg = <0xf 0xfe240000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe250000 {
+ reg = <0xf 0xfe250000 0 0x10000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe260000 {
+ reg = <0xf 0xfe260000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie@ffe270000 {
+ reg = <0xf 0xfe270000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+};
diff --git a/arch/powerpc/boot/dts/t4240rdb.dts b/arch/powerpc/boot/dts/t4240rdb.dts
new file mode 100644
index 000000000000..53761d4e8c51
--- /dev/null
+++ b/arch/powerpc/boot/dts/t4240rdb.dts
@@ -0,0 +1,186 @@
+/*
+ * T4240RDB Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/t4240si-pre.dtsi"
+
+/ {
+ model = "fsl,T4240RDB";
+ compatible = "fsl,T4240RDB";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ ifc: localbus@ffe124000 {
+ reg = <0xf 0xfe124000 0 0x2000>;
+ ranges = <0 0 0xf 0xe8000000 0x08000000
+ 2 0 0xf 0xff800000 0x00010000
+ 3 0 0xf 0xffdf0000 0x00008000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ nand@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,ifc-nand";
+ reg = <0x2 0x0 0x10000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ };
+
+ dcsr: dcsr@f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01072000>;
+ };
+
+ soc: soc@ffe000000 {
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+ spi@110000 {
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "sst,sst25wf040";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ };
+ };
+
+ i2c@118000 {
+ eeprom@52 {
+ compatible = "at24,24c256";
+ reg = <0x52>;
+ };
+ eeprom@54 {
+ compatible = "at24,24c256";
+ reg = <0x54>;
+ };
+ eeprom@56 {
+ compatible = "at24,24c256";
+ reg = <0x56>;
+ };
+ rtc@68 {
+ compatible = "dallas,ds1374";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+ };
+
+ sdhc@114000 {
+ voltage-ranges = <1800 1800 3300 3300>;
+ };
+ };
+
+ pci0: pcie@ffe240000 {
+ reg = <0xf 0xfe240000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie@ffe250000 {
+ reg = <0xf 0xfe250000 0 0x10000>;
+ ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie@ffe260000 {
+ reg = <0xf 0xfe260000 0 0x1000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie@ffe270000 {
+ reg = <0xf 0xfe270000 0 0x10000>;
+ ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
+ 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
+ pcie@0 {
+ ranges = <0x02000000 0 0xe0000000
+ 0x02000000 0 0xe0000000
+ 0 0x20000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0x00000000
+ 0 0x00010000>;
+ };
+ };
+
+ rio: rapidio@ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+ };
+ };
+};
+
+/include/ "fsl/t4240si-post.dtsi"
diff --git a/arch/powerpc/boot/gunzip_util.c b/arch/powerpc/boot/gunzip_util.c
index ef2aed0f63ca..9dc52501de83 100644
--- a/arch/powerpc/boot/gunzip_util.c
+++ b/arch/powerpc/boot/gunzip_util.c
@@ -112,10 +112,10 @@ int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen)
r = zlib_inflate(&state->s, Z_FULL_FLUSH);
if (r != Z_OK && r != Z_STREAM_END)
fatal("inflate returned %d msg: %s\n\r", r, state->s.msg);
- len = state->s.next_out - (unsigned char *)dst;
+ len = state->s.next_out - (Byte *)dst;
} else {
/* uncompressed image */
- len = min(state->s.avail_in, (unsigned)dstlen);
+ len = min(state->s.avail_in, (uLong)dstlen);
memcpy(dst, state->s.next_in, len);
state->s.next_in += len;
state->s.avail_in -= len;
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
index 7c09f4861fe1..394da5500466 100644
--- a/arch/powerpc/boot/io.h
+++ b/arch/powerpc/boot/io.h
@@ -1,5 +1,5 @@
#ifndef _IO_H
-#define __IO_H
+#define _IO_H
#include "types.h"
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
index c05310a913be..c936fab9ec4a 100644
--- a/arch/powerpc/configs/52xx/motionpro_defconfig
+++ b/arch/powerpc/configs/52xx/motionpro_defconfig
@@ -43,7 +43,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_LEGACY=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
diff --git a/arch/powerpc/configs/85xx/kmp204x_defconfig b/arch/powerpc/configs/85xx/kmp204x_defconfig
index e9a81e5ba273..e362d588dfbf 100644
--- a/arch/powerpc/configs/85xx/kmp204x_defconfig
+++ b/arch/powerpc/configs/85xx/kmp204x_defconfig
@@ -192,7 +192,6 @@ CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_UIO=y
CONFIG_STAGING=y
-# CONFIG_NET_VENDOR_SILICOM is not set
CONFIG_CLK_PPC_CORENET=y
CONFIG_EXT2_FS=y
CONFIG_NTFS_FS=y
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index bcbe74716689..9b192bb6bd3d 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -54,7 +54,6 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_IDE=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index c19ff057d0f9..6a3c58adf253 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -139,8 +139,9 @@ CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_MPC85XX=y
CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
CONFIG_RTC_DRV_DS3232=y
-CONFIG_RTC_DRV_CMOS=y
CONFIG_UIO=y
CONFIG_STAGING=y
CONFIG_VIRT_DRIVERS=y
@@ -179,3 +180,4 @@ CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_FSL_CORENET_CF=y
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 5c7fa19ae4ef..4b07bade1ba9 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -123,6 +123,10 @@ CONFIG_USB_EHCI_FSL=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_DMADEVICES=y
@@ -175,3 +179,4 @@ CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_FSL_CAAM=y
+CONFIG_FSL_CORENET_CF=y
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 530601e8ccfe..69fd8adf9f5e 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -47,7 +47,6 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_EEPROM_AT24=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 55765c8cb08f..fa1bfd37f1ec 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -209,6 +209,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_DMADEVICES=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 5c6ecdc0f70e..0b452ebd8b3d 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -210,6 +210,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_CMOS=y
CONFIG_RTC_DRV_DS1307=y
CONFIG_DMADEVICES=y
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index ccf66b9060a6..924e10df1844 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -127,4 +127,3 @@ CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
CONFIG_VIRTUALIZATION=y
-CONFIG_KVM_440=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index c91066944842..fec5870f1818 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -425,10 +425,8 @@ CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_SCSI_MESH=m
CONFIG_SCSI_MAC53C94=m
-CONFIG_SCSI_SRP=m
CONFIG_SCSI_LOWLEVEL_PCMCIA=y
CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 3fb1bc432f4f..7f23f162ce9c 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -4,5 +4,6 @@ generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
generic-y += rwsem.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
generic-y += vtime.h
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
index 4b237aa35660..21be8ae8f809 100644
--- a/arch/powerpc/include/asm/asm-compat.h
+++ b/arch/powerpc/include/asm/asm-compat.h
@@ -34,10 +34,14 @@
#define PPC_MIN_STKFRM 112
#ifdef __BIG_ENDIAN__
+#define LWZX_BE stringify_in_c(lwzx)
#define LDX_BE stringify_in_c(ldx)
+#define STWX_BE stringify_in_c(stwx)
#define STDX_BE stringify_in_c(stdx)
#else
+#define LWZX_BE stringify_in_c(lwbrx)
#define LDX_BE stringify_in_c(ldbrx)
+#define STWX_BE stringify_in_c(stwbrx)
#define STDX_BE stringify_in_c(stdbrx)
#endif
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index ed0afc1e44a4..34a05a1a990b 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -3,6 +3,7 @@
#ifdef __KERNEL__
+#include <asm/reg.h>
/* bytes per L1 cache line */
#if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -39,6 +40,12 @@ struct ppc64_caches {
};
extern struct ppc64_caches ppc64_caches;
+
+static inline void logmpp(u64 x)
+{
+ asm volatile(PPC_LOGMPP(R1) : : "r" (x));
+}
+
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
#if defined(__ASSEMBLY__)
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 0fdd7eece6d9..daa5af91163c 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -195,8 +195,7 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN)
-#define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_SLB | MMU_FTR_TLBIEL | \
- MMU_FTR_16M_PAGE)
+#define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE)
/* We only set the altivec features if the kernel was compiled with altivec
* support
@@ -268,10 +267,6 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_MAYBE_CAN_NAP 0
#endif
-#define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \
- !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \
- !defined(CONFIG_BOOKE))
-
#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE)
#define CPU_FTRS_603 (CPU_FTR_COMMON | \
@@ -396,15 +391,10 @@ extern const char *powerpc_base_platform;
CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \
- CPU_FTR_CELL_TB_BUG)
+ CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT)
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
/* 64-bit CPUs */
-#define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \
- CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \
- CPU_FTR_IABR | \
- CPU_FTR_MMCRA | CPU_FTR_CTRL)
#define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \
@@ -467,15 +457,15 @@ extern const char *powerpc_base_platform;
#define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2)
#else
#define CPU_FTRS_POSSIBLE \
- (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
- CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \
- CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \
- CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX)
+ (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
+ CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \
+ CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \
+ CPU_FTRS_PA6T | CPU_FTR_VSX)
#endif
#else
enum {
CPU_FTRS_POSSIBLE =
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX |
@@ -518,14 +508,15 @@ enum {
#define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2)
#else
#define CPU_FTRS_ALWAYS \
- (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
- CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \
- CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE)
+ (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \
+ CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \
+ CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \
+ CPU_FTRS_POWER8_DD1 & CPU_FTRS_POSSIBLE)
#endif
#else
enum {
CPU_FTRS_ALWAYS =
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX &
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index fab7743c2640..9983c3d26bca 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -25,6 +25,7 @@
#include <linux/list.h>
#include <linux/string.h>
#include <linux/time.h>
+#include <linux/atomic.h>
struct pci_dev;
struct pci_bus;
@@ -33,10 +34,11 @@ struct device_node;
#ifdef CONFIG_EEH
/* EEH subsystem flags */
-#define EEH_ENABLED 0x1 /* EEH enabled */
-#define EEH_FORCE_DISABLED 0x2 /* EEH disabled */
-#define EEH_PROBE_MODE_DEV 0x4 /* From PCI device */
-#define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */
+#define EEH_ENABLED 0x01 /* EEH enabled */
+#define EEH_FORCE_DISABLED 0x02 /* EEH disabled */
+#define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */
+#define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */
+#define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */
/*
* Delay for PE reset, all in ms
@@ -84,7 +86,9 @@ struct eeh_pe {
int freeze_count; /* Times of froze up */
struct timeval tstamp; /* Time on first-time freeze */
int false_positives; /* Times of reported #ff's */
+ atomic_t pass_dev_cnt; /* Count of passed through devs */
struct eeh_pe *parent; /* Parent PE */
+ void *data; /* PE auxillary data */
struct list_head child_list; /* Link PE to the child list */
struct list_head edevs; /* Link list of EEH devices */
struct list_head child; /* Child PEs */
@@ -93,6 +97,11 @@ struct eeh_pe {
#define eeh_pe_for_each_dev(pe, edev, tmp) \
list_for_each_entry_safe(edev, tmp, &pe->edevs, list)
+static inline bool eeh_pe_passed(struct eeh_pe *pe)
+{
+ return pe ? !!atomic_read(&pe->pass_dev_cnt) : false;
+}
+
/*
* The struct is used to trace EEH state for the associated
* PCI device node or PCI device. In future, it might
@@ -165,6 +174,11 @@ enum {
#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */
#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */
#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */
+#define EEH_PE_STATE_NORMAL 0 /* Normal state */
+#define EEH_PE_STATE_RESET 1 /* PE reset asserted */
+#define EEH_PE_STATE_STOPPED_IO_DMA 2 /* Frozen PE */
+#define EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA, Enabled IO */
+#define EEH_PE_STATE_UNAVAIL 5 /* Unavailable */
#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */
#define EEH_RESET_HOT 1 /* Hot reset */
#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */
@@ -194,36 +208,28 @@ extern int eeh_subsystem_flags;
extern struct eeh_ops *eeh_ops;
extern raw_spinlock_t confirm_error_lock;
-static inline bool eeh_enabled(void)
+static inline void eeh_add_flag(int flag)
{
- if ((eeh_subsystem_flags & EEH_FORCE_DISABLED) ||
- !(eeh_subsystem_flags & EEH_ENABLED))
- return false;
-
- return true;
+ eeh_subsystem_flags |= flag;
}
-static inline void eeh_set_enable(bool mode)
+static inline void eeh_clear_flag(int flag)
{
- if (mode)
- eeh_subsystem_flags |= EEH_ENABLED;
- else
- eeh_subsystem_flags &= ~EEH_ENABLED;
+ eeh_subsystem_flags &= ~flag;
}
-static inline void eeh_probe_mode_set(int flag)
+static inline bool eeh_has_flag(int flag)
{
- eeh_subsystem_flags |= flag;
+ return !!(eeh_subsystem_flags & flag);
}
-static inline int eeh_probe_mode_devtree(void)
+static inline bool eeh_enabled(void)
{
- return (eeh_subsystem_flags & EEH_PROBE_MODE_DEVTREE);
-}
+ if (eeh_has_flag(EEH_FORCE_DISABLED) ||
+ !eeh_has_flag(EEH_ENABLED))
+ return false;
-static inline int eeh_probe_mode_dev(void)
-{
- return (eeh_subsystem_flags & EEH_PROBE_MODE_DEV);
+ return true;
}
static inline void eeh_serialize_lock(unsigned long *flags)
@@ -243,6 +249,7 @@ static inline void eeh_serialize_unlock(unsigned long flags)
#define EEH_MAX_ALLOWED_FREEZES 5
typedef void *(*eeh_traverse_func)(void *data, void *flag);
+void eeh_set_pe_aux_size(int size);
int eeh_phb_pe_create(struct pci_controller *phb);
struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
@@ -272,6 +279,13 @@ void eeh_add_device_late(struct pci_dev *);
void eeh_add_device_tree_late(struct pci_bus *);
void eeh_add_sysfs_files(struct pci_bus *);
void eeh_remove_device(struct pci_dev *);
+int eeh_dev_open(struct pci_dev *pdev);
+void eeh_dev_release(struct pci_dev *pdev);
+struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group);
+int eeh_pe_set_option(struct eeh_pe *pe, int option);
+int eeh_pe_get_state(struct eeh_pe *pe);
+int eeh_pe_reset(struct eeh_pe *pe, int option);
+int eeh_pe_configure(struct eeh_pe *pe);
/**
* EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -295,8 +309,6 @@ static inline bool eeh_enabled(void)
return false;
}
-static inline void eeh_set_enable(bool mode) { }
-
static inline int eeh_init(void)
{
return 0;
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 8f35cd7d59cc..77f52b26dad6 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -425,6 +425,8 @@ label##_relon_hv: \
#define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL
#define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL
#define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL
+#define SOFTEN_VALUE_0xe60 PACA_IRQ_HMI
+#define SOFTEN_VALUE_0xe62 PACA_IRQ_HMI
#define __SOFTEN_TEST(h, vec) \
lbz r10,PACASOFTIRQEN(r13); \
@@ -513,8 +515,11 @@ label##_relon_hv: \
* runlatch, etc...
*/
-/* Exception addition: Hard disable interrupts */
-#define DISABLE_INTS RECONCILE_IRQ_STATE(r10,r11)
+/*
+ * This addition reconciles our actual IRQ state with the various software
+ * flags that track it. This may call C code.
+ */
+#define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11)
#define ADD_NVGPRS \
bl save_nvgprs
@@ -532,6 +537,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
.globl label##_common; \
label##_common: \
EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
+ /* Volatile regs are potentially clobbered here */ \
additions; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
bl hdlr; \
@@ -539,7 +545,7 @@ label##_common: \
#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \
- ADD_NVGPRS;DISABLE_INTS)
+ ADD_NVGPRS;ADD_RECONCILE)
/*
* Like STD_EXCEPTION_COMMON, but for exceptions that can occur
@@ -548,7 +554,7 @@ label##_common: \
*/
#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \
EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
- FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)
+ FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON)
/*
* When the idle code in power4_idle puts the CPU into NAP mode,
diff --git a/arch/powerpc/include/asm/fs_pd.h b/arch/powerpc/include/asm/fs_pd.h
index 9361cd5342cc..f79d6c74eb2a 100644
--- a/arch/powerpc/include/asm/fs_pd.h
+++ b/arch/powerpc/include/asm/fs_pd.h
@@ -28,7 +28,6 @@
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
extern immap_t __iomem *mpc8xx_immr;
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h
index 418fb654370d..1bbb3013d6aa 100644
--- a/arch/powerpc/include/asm/hardirq.h
+++ b/arch/powerpc/include/asm/hardirq.h
@@ -11,6 +11,7 @@ typedef struct {
unsigned int pmu_irqs;
unsigned int mce_exceptions;
unsigned int spurious_irqs;
+ unsigned int hmi_exceptions;
#ifdef CONFIG_PPC_DOORBELL
unsigned int doorbell_irqs;
#endif
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 5dbbb29f5c3e..85bc8c0d257b 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -279,6 +279,12 @@
#define H_GET_24X7_DATA 0xF07C
#define H_GET_PERF_COUNTER_INFO 0xF080
+/* Values for 2nd argument to H_SET_MODE */
+#define H_SET_MODE_RESOURCE_SET_CIABR 1
+#define H_SET_MODE_RESOURCE_SET_DAWR 2
+#define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3
+#define H_SET_MODE_RESOURCE_LE 4
+
#ifndef __ASSEMBLY__
/**
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 10be1dd01c6b..b59ac27a6b7d 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -25,6 +25,7 @@
#define PACA_IRQ_EE 0x04
#define PACA_IRQ_DEC 0x08 /* Or FIT */
#define PACA_IRQ_EE_EDGE 0x10 /* BookE only */
+#define PACA_IRQ_HMI 0x20
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index e20eb95429a8..f2149066fe5d 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -32,9 +32,8 @@
#endif
/*
- * Most of the CPU's IRQ-state tracing is done from assembly code; we
- * have to call a C function so call a wrapper that saves all the
- * C-clobbered registers.
+ * These are calls to C code, so the caller must be prepared for volatiles to
+ * be clobbered.
*/
#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on)
#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off)
@@ -42,6 +41,9 @@
/*
* This is used by assembly code to soft-disable interrupts first and
* reconcile irq state.
+ *
+ * NB: This may call C code, so the caller must be prepared for volatiles to
+ * be clobbered.
*/
#define RECONCILE_IRQ_STATE(__rA, __rB) \
lbz __rA,PACASOFTIRQEN(r13); \
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index f016bb699b5f..efbf9a322a23 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <asm/feature-fixups.h>
@@ -42,4 +43,12 @@ struct jump_entry {
jump_label_t key;
};
+#else
+#define ARCH_STATIC_BRANCH(LABEL, KEY) \
+1098: nop; \
+ .pushsection __jump_table, "aw"; \
+ FTR_ENTRY_LONG 1098b, LABEL, KEY; \
+ .popsection
+#endif
+
#endif /* _ASM_POWERPC_JUMP_LABEL_H */
diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h
deleted file mode 100644
index a0e57618ff33..000000000000
--- a/arch/powerpc/include/asm/kvm_44x.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#ifndef __ASM_44X_H__
-#define __ASM_44X_H__
-
-#include <linux/kvm_host.h>
-
-#define PPC44x_TLB_SIZE 64
-
-/* If the guest is expecting it, this can be as large as we like; we'd just
- * need to find some way of advertising it. */
-#define KVM44x_GUEST_TLB_SIZE 64
-
-struct kvmppc_44x_tlbe {
- u32 tid; /* Only the low 8 bits are used. */
- u32 word0;
- u32 word1;
- u32 word2;
-};
-
-struct kvmppc_44x_shadow_ref {
- struct page *page;
- u16 gtlb_index;
- u8 writeable;
- u8 tid;
-};
-
-struct kvmppc_vcpu_44x {
- /* Unmodified copy of the guest's TLB. */
- struct kvmppc_44x_tlbe guest_tlb[KVM44x_GUEST_TLB_SIZE];
-
- /* References to guest pages in the hardware TLB. */
- struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE];
-
- /* State of the shadow TLB at guest context switch time. */
- struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE];
- u8 shadow_tlb_mod[PPC44x_TLB_SIZE];
-
- struct kvm_vcpu vcpu;
-};
-
-static inline struct kvmppc_vcpu_44x *to_44x(struct kvm_vcpu *vcpu)
-{
- return container_of(vcpu, struct kvmppc_vcpu_44x, vcpu);
-}
-
-void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu);
-void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu);
-
-#endif /* __ASM_44X_H__ */
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index 9601741080e5..465dfcb82c92 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -33,7 +33,6 @@
/* IVPR must be 64KiB-aligned. */
#define VCPU_SIZE_ORDER 4
#define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12)
-#define VCPU_TLB_PGSZ PPC44x_TLB_64K
#define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG)
#define BOOKE_INTERRUPT_CRITICAL 0
@@ -98,6 +97,7 @@
#define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00
#define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20
#define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40
+#define BOOK3S_INTERRUPT_HMI 0xe60
#define BOOK3S_INTERRUPT_H_DOORBELL 0xe80
#define BOOK3S_INTERRUPT_PERFMON 0xf00
#define BOOK3S_INTERRUPT_ALTIVEC 0xf20
@@ -131,6 +131,7 @@
#define BOOK3S_HFLAG_NATIVE_PS 0x8
#define BOOK3S_HFLAG_MULTI_PGSIZE 0x10
#define BOOK3S_HFLAG_NEW_TLBIE 0x20
+#define BOOK3S_HFLAG_SPLIT_HACK 0x40
#define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index f52f65694527..6acf0c2a0f99 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -83,8 +83,6 @@ struct kvmppc_vcpu_book3s {
u64 sdr1;
u64 hior;
u64 msr_mask;
- u64 purr_offset;
- u64 spurr_offset;
#ifdef CONFIG_PPC_BOOK3S_32
u32 vsid_pool[VSID_POOL_SIZE];
u32 vsid_next;
@@ -148,9 +146,10 @@ extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *
extern int kvmppc_mmu_hpte_sysinit(void);
extern void kvmppc_mmu_hpte_sysexit(void);
extern int kvmppc_mmu_hv_init(void);
+extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc);
+/* XXX remove this export when load_last_inst() is generic */
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
-extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data);
extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec);
extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
unsigned int vec);
@@ -159,13 +158,13 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
bool upper, u32 val);
extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu);
-extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
+extern pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
bool *writable);
extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev,
unsigned long *rmap, long pte_index, int realmode);
-extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+extern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
unsigned long pte_index);
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
unsigned long pte_index);
extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
unsigned long *nb_ret);
@@ -183,12 +182,16 @@ extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
struct kvm_memory_slot *memslot, unsigned long *map);
extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr,
unsigned long mask);
+extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr);
extern void kvmppc_entry_trampoline(void);
extern void kvmppc_hv_entry_trampoline(void);
extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm);
+extern int kvmppc_hcall_impl_pr(unsigned long cmd);
+extern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd);
extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
struct kvm_vcpu *vcpu);
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
@@ -274,32 +277,6 @@ static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE);
}
-static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
-{
- /* Load the instruction manually if it failed to do so in the
- * exit path */
- if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
- kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false);
-
- return kvmppc_need_byteswap(vcpu) ? swab32(vcpu->arch.last_inst) :
- vcpu->arch.last_inst;
-}
-
-static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
-{
- return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu));
-}
-
-/*
- * Like kvmppc_get_last_inst(), but for fetching a sc instruction.
- * Because the sc instruction sets SRR0 to point to the following
- * instruction, we have to fetch from pc - 4.
- */
-static inline u32 kvmppc_get_last_sc(struct kvm_vcpu *vcpu)
-{
- return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu) - 4);
-}
-
static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
{
return vcpu->arch.fault_dar;
@@ -310,6 +287,13 @@ static inline bool is_kvmppc_resume_guest(int r)
return (r == RESUME_GUEST || r == RESUME_GUEST_NV);
}
+static inline bool is_kvmppc_hv_enabled(struct kvm *kvm);
+static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
+{
+ /* Only PR KVM supports the magic page */
+ return !is_kvmppc_hv_enabled(vcpu->kvm);
+}
+
/* Magic register values loaded into r3 and r4 before the 'sc' assembly
* instruction for the OSI hypercalls */
#define OSI_SC_MAGIC_R3 0x113724FA
@@ -322,4 +306,7 @@ static inline bool is_kvmppc_resume_guest(int r)
/* LPIDs we support with this build -- runtime limit may be lower */
#define KVMPPC_NR_LPIDS (LPID_RSVD + 1)
+#define SPLIT_HACK_MASK 0xff000000
+#define SPLIT_HACK_OFFS 0xfb000000
+
#endif /* __ASM_KVM_BOOK3S_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index d645428a65a4..0aa817933e6a 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -59,20 +59,29 @@ extern unsigned long kvm_rma_pages;
/* These bits are reserved in the guest view of the HPTE */
#define HPTE_GR_RESERVED HPTE_GR_MODIFIED
-static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
+static inline long try_lock_hpte(__be64 *hpte, unsigned long bits)
{
unsigned long tmp, old;
+ __be64 be_lockbit, be_bits;
+
+ /*
+ * We load/store in native endian, but the HTAB is in big endian. If
+ * we byte swap all data we apply on the PTE we're implicitly correct
+ * again.
+ */
+ be_lockbit = cpu_to_be64(HPTE_V_HVLOCK);
+ be_bits = cpu_to_be64(bits);
asm volatile(" ldarx %0,0,%2\n"
" and. %1,%0,%3\n"
" bne 2f\n"
- " ori %0,%0,%4\n"
+ " or %0,%0,%4\n"
" stdcx. %0,0,%2\n"
" beq+ 2f\n"
" mr %1,%3\n"
"2: isync"
: "=&r" (tmp), "=&r" (old)
- : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
+ : "r" (hpte), "r" (be_bits), "r" (be_lockbit)
: "cc", "memory");
return old == 0;
}
@@ -110,16 +119,12 @@ static inline int __hpte_actual_psize(unsigned int lp, int psize)
static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
unsigned long pte_index)
{
- int b_psize, a_psize;
+ int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K;
unsigned int penc;
unsigned long rb = 0, va_low, sllp;
unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
- if (!(v & HPTE_V_LARGE)) {
- /* both base and actual psize is 4k */
- b_psize = MMU_PAGE_4K;
- a_psize = MMU_PAGE_4K;
- } else {
+ if (v & HPTE_V_LARGE) {
for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) {
/* valid entries have a shift value */
@@ -142,6 +147,8 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
*/
/* This covers 14..54 bits of va*/
rb = (v & ~0x7fUL) << 16; /* AVA field */
+
+ rb |= v >> (62 - 8); /* B field */
/*
* AVA in v had cleared lower 23 bits. We need to derive
* that from pteg index
@@ -172,10 +179,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
{
int aval_shift;
/*
- * remaining 7bits of AVA/LP fields
+ * remaining bits of AVA/LP fields
* Also contain the rr bits of LP
*/
- rb |= (va_low & 0x7f) << 16;
+ rb |= (va_low << mmu_psize_defs[b_psize].shift) & 0x7ff000;
/*
* Now clear not needed LP bits based on actual psize
*/
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index c7aed6105ff9..f7aa5cc395c4 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -69,11 +69,6 @@ static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
return false;
}
-static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.last_inst;
-}
-
static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
{
vcpu->arch.ctr = val;
@@ -108,4 +103,14 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
{
return vcpu->arch.fault_dear;
}
+
+static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
+{
+ /* Magic page is only supported on e500v2 */
+#ifdef CONFIG_KVM_E500V2
+ return true;
+#else
+ return false;
+#endif
+}
#endif /* __ASM_KVM_BOOKE_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index bb66d8b8efdf..98d9dd50d063 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -34,6 +34,7 @@
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
+#include <asm/hvcall.h>
#define KVM_MAX_VCPUS NR_CPUS
#define KVM_MAX_VCORES NR_CPUS
@@ -48,7 +49,6 @@
#define KVM_NR_IRQCHIPS 1
#define KVM_IRQCHIP_NUM_PINS 256
-#if !defined(CONFIG_KVM_440)
#include <linux/mmu_notifier.h>
#define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -61,8 +61,6 @@ extern int kvm_age_hva(struct kvm *kvm, unsigned long hva);
extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
-#endif
-
#define HPTEG_CACHE_NUM (1 << 15)
#define HPTEG_HASH_BITS_PTE 13
#define HPTEG_HASH_BITS_PTE_LONG 12
@@ -96,7 +94,6 @@ struct kvm_vm_stat {
struct kvm_vcpu_stat {
u32 sum_exits;
u32 mmio_exits;
- u32 dcr_exits;
u32 signal_exits;
u32 light_exits;
/* Account for special types of light exits: */
@@ -113,22 +110,21 @@ struct kvm_vcpu_stat {
u32 halt_wakeup;
u32 dbell_exits;
u32 gdbell_exits;
+ u32 ld;
+ u32 st;
#ifdef CONFIG_PPC_BOOK3S
u32 pf_storage;
u32 pf_instruc;
u32 sp_storage;
u32 sp_instruc;
u32 queue_intr;
- u32 ld;
u32 ld_slow;
- u32 st;
u32 st_slow;
#endif
};
enum kvm_exit_types {
MMIO_EXITS,
- DCR_EXITS,
SIGNAL_EXITS,
ITLB_REAL_MISS_EXITS,
ITLB_VIRT_MISS_EXITS,
@@ -254,7 +250,6 @@ struct kvm_arch {
atomic_t hpte_mod_interest;
spinlock_t slot_phys_lock;
cpumask_t need_tlb_flush;
- struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
int hpt_cma_alloc;
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
@@ -263,6 +258,7 @@ struct kvm_arch {
#ifdef CONFIG_PPC_BOOK3S_64
struct list_head spapr_tce_tables;
struct list_head rtas_tokens;
+ DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
#endif
#ifdef CONFIG_KVM_MPIC
struct openpic *mpic;
@@ -271,6 +267,10 @@ struct kvm_arch {
struct kvmppc_xics *xics;
#endif
struct kvmppc_ops *kvm_ops;
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ /* This array can grow quite large, keep it at the end */
+ struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+#endif
};
/*
@@ -305,6 +305,8 @@ struct kvmppc_vcore {
u32 arch_compat;
ulong pcr;
ulong dpdes; /* doorbell state (POWER8) */
+ void *mpp_buffer; /* Micro Partition Prefetch buffer */
+ bool mpp_buffer_is_valid;
};
#define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff)
@@ -503,8 +505,10 @@ struct kvm_vcpu_arch {
#ifdef CONFIG_BOOKE
u32 decar;
#endif
- u32 tbl;
- u32 tbu;
+ /* Time base value when we entered the guest */
+ u64 entry_tb;
+ u64 entry_vtb;
+ u64 entry_ic;
u32 tcr;
ulong tsr; /* we need to perform set/clr_bits() which requires ulong */
u32 ivor[64];
@@ -580,6 +584,8 @@ struct kvm_vcpu_arch {
u32 mmucfg;
u32 eptcfg;
u32 epr;
+ u64 sprg9;
+ u32 pwrmgtcr0;
u32 crit_save;
/* guest debug registers*/
struct debug_reg dbg_reg;
@@ -593,8 +599,6 @@ struct kvm_vcpu_arch {
u8 io_gpr; /* GPR used as IO source/target */
u8 mmio_is_bigendian;
u8 mmio_sign_extend;
- u8 dcr_needed;
- u8 dcr_is_write;
u8 osi_needed;
u8 osi_enabled;
u8 papr_enabled;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 9c89cdd067a6..fb86a2299d8a 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -41,12 +41,26 @@
enum emulation_result {
EMULATE_DONE, /* no further processing */
EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */
- EMULATE_DO_DCR, /* kvm_run filled with DCR request */
EMULATE_FAIL, /* can't emulate this instruction */
EMULATE_AGAIN, /* something went wrong. go again */
EMULATE_EXIT_USER, /* emulation requires exit to user-space */
};
+enum instruction_type {
+ INST_GENERIC,
+ INST_SC, /* system call */
+};
+
+enum xlate_instdata {
+ XLATE_INST, /* translate instruction address */
+ XLATE_DATA /* translate data address */
+};
+
+enum xlate_readwrite {
+ XLATE_READ, /* check for read permissions */
+ XLATE_WRITE /* check for write permissions */
+};
+
extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern void kvmppc_handler_highmem(void);
@@ -62,8 +76,16 @@ extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
u64 val, unsigned int bytes,
int is_default_endian);
+extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
+ enum instruction_type type, u32 *inst);
+
+extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+ bool data);
+extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+ bool data);
extern int kvmppc_emulate_instruction(struct kvm_run *run,
struct kvm_vcpu *vcpu);
+extern int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu);
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
@@ -86,6 +108,9 @@ extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
gva_t eaddr);
extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu);
extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu);
+extern int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr,
+ enum xlate_instdata xlid, enum xlate_readwrite xlrw,
+ struct kvmppc_pte *pte);
extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
unsigned int id);
@@ -106,6 +131,14 @@ extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
struct kvm_interrupt *irq);
extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, ulong dear_flags,
+ ulong esr_flags);
+extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
+ ulong dear_flags,
+ ulong esr_flags);
+extern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
+ ulong esr_flags);
extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
@@ -228,12 +261,35 @@ struct kvmppc_ops {
void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu);
long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl,
unsigned long arg);
-
+ int (*hcall_implemented)(unsigned long hcall);
};
extern struct kvmppc_ops *kvmppc_hv_ops;
extern struct kvmppc_ops *kvmppc_pr_ops;
+static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
+ enum instruction_type type, u32 *inst)
+{
+ int ret = EMULATE_DONE;
+ u32 fetched_inst;
+
+ /* Load the instruction manually if it failed to do so in the
+ * exit path */
+ if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
+ ret = kvmppc_load_last_inst(vcpu, type, &vcpu->arch.last_inst);
+
+ /* Write fetch_failed unswapped if the fetch failed */
+ if (ret == EMULATE_DONE)
+ fetched_inst = kvmppc_need_byteswap(vcpu) ?
+ swab32(vcpu->arch.last_inst) :
+ vcpu->arch.last_inst;
+ else
+ fetched_inst = vcpu->arch.last_inst;
+
+ *inst = fetched_inst;
+ return ret;
+}
+
static inline bool is_kvmppc_hv_enabled(struct kvm *kvm)
{
return kvm->arch.kvm_ops == kvmppc_hv_ops;
@@ -392,6 +448,17 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
{ return 0; }
#endif
+static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_KVM_BOOKE_HV
+ return mfspr(SPRN_GEPR);
+#elif defined(CONFIG_BOOKE)
+ return vcpu->arch.epr;
+#else
+ return 0;
+#endif
+}
+
static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
{
#ifdef CONFIG_KVM_BOOKE_HV
@@ -472,8 +539,20 @@ static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu)
#endif
}
+#define SPRNG_WRAPPER_GET(reg, bookehv_spr) \
+static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
+{ \
+ return mfspr(bookehv_spr); \
+} \
+
+#define SPRNG_WRAPPER_SET(reg, bookehv_spr) \
+static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val) \
+{ \
+ mtspr(bookehv_spr, val); \
+} \
+
#define SHARED_WRAPPER_GET(reg, size) \
-static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
+static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
{ \
if (kvmppc_shared_big_endian(vcpu)) \
return be##size##_to_cpu(vcpu->arch.shared->reg); \
@@ -494,14 +573,31 @@ static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \
SHARED_WRAPPER_GET(reg, size) \
SHARED_WRAPPER_SET(reg, size) \
+#define SPRNG_WRAPPER(reg, bookehv_spr) \
+ SPRNG_WRAPPER_GET(reg, bookehv_spr) \
+ SPRNG_WRAPPER_SET(reg, bookehv_spr) \
+
+#ifdef CONFIG_KVM_BOOKE_HV
+
+#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \
+ SPRNG_WRAPPER(reg, bookehv_spr) \
+
+#else
+
+#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \
+ SHARED_WRAPPER(reg, size) \
+
+#endif
+
SHARED_WRAPPER(critical, 64)
-SHARED_WRAPPER(sprg0, 64)
-SHARED_WRAPPER(sprg1, 64)
-SHARED_WRAPPER(sprg2, 64)
-SHARED_WRAPPER(sprg3, 64)
-SHARED_WRAPPER(srr0, 64)
-SHARED_WRAPPER(srr1, 64)
-SHARED_WRAPPER(dar, 64)
+SHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0)
+SHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1)
+SHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2)
+SHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3)
+SHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0)
+SHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1)
+SHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR)
+SHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR)
SHARED_WRAPPER_GET(msr, 64)
static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
{
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index f92b0b54e921..b125ceab149c 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -57,10 +57,10 @@ struct machdep_calls {
void (*hpte_removebolted)(unsigned long ea,
int psize, int ssize);
void (*flush_hash_range)(unsigned long number, int local);
- void (*hugepage_invalidate)(struct mm_struct *mm,
+ void (*hugepage_invalidate)(unsigned long vsid,
+ unsigned long addr,
unsigned char *hpte_slot_array,
- unsigned long addr, int psize);
-
+ int psize, int ssize);
/* special for kexec, to be called in real mode, linear mapping is
* destroyed as well */
void (*hpte_clear_all)(void);
@@ -174,6 +174,10 @@ struct machdep_calls {
/* Exception handlers */
int (*system_reset_exception)(struct pt_regs *regs);
int (*machine_check_exception)(struct pt_regs *regs);
+ int (*handle_hmi_exception)(struct pt_regs *regs);
+
+ /* Early exception handlers called in realmode */
+ int (*hmi_exception_early)(struct pt_regs *regs);
/* Called during machine check exception to retrive fixup address. */
bool (*mce_check_early_recovery)(struct pt_regs *regs);
@@ -366,6 +370,7 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
} \
__define_initcall(__machine_initcall_##mach##_##fn, id);
+#define machine_early_initcall(mach, fn) __define_machine_initcall(mach, fn, early)
#define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1)
#define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s)
#define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2)
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
index d0918e09557f..cd4f04a74802 100644
--- a/arch/powerpc/include/asm/mmu-book3e.h
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -40,7 +40,11 @@
/* MAS registers bit definitions */
-#define MAS0_TLBSEL(x) (((x) << 28) & 0x30000000)
+#define MAS0_TLBSEL_MASK 0x30000000
+#define MAS0_TLBSEL_SHIFT 28
+#define MAS0_TLBSEL(x) (((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK)
+#define MAS0_GET_TLBSEL(mas0) (((mas0) & MAS0_TLBSEL_MASK) >> \
+ MAS0_TLBSEL_SHIFT)
#define MAS0_ESEL_MASK 0x0FFF0000
#define MAS0_ESEL_SHIFT 16
#define MAS0_ESEL(x) (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK)
@@ -58,6 +62,7 @@
#define MAS1_TSIZE_MASK 0x00000f80
#define MAS1_TSIZE_SHIFT 7
#define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
+#define MAS1_GET_TSIZE(mas1) (((mas1) & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT)
#define MAS2_EPN (~0xFFFUL)
#define MAS2_X0 0x00000040
@@ -86,6 +91,7 @@
#define MAS3_SPSIZE 0x0000003e
#define MAS3_SPSIZE_SHIFT 1
+#define MAS4_TLBSEL_MASK MAS0_TLBSEL_MASK
#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
#define MAS4_INDD 0x00008000 /* Default IND */
#define MAS4_TSIZED(x) MAS1_TSIZE(x)
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index c2b4dcf23d03..d76514487d6f 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -25,26 +25,6 @@
#include <asm/processor.h>
/*
- * Segment table
- */
-
-#define STE_ESID_V 0x80
-#define STE_ESID_KS 0x20
-#define STE_ESID_KP 0x10
-#define STE_ESID_N 0x08
-
-#define STE_VSID_SHIFT 12
-
-/* Location of cpu0's segment table */
-#define STAB0_PAGE 0x8
-#define STAB0_OFFSET (STAB0_PAGE << 12)
-#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START)
-
-#ifndef __ASSEMBLY__
-extern char initial_stab[];
-#endif /* ! __ASSEMBLY */
-
-/*
* SLB
*/
@@ -370,10 +350,8 @@ extern void hpte_init_lpar(void);
extern void hpte_init_beat(void);
extern void hpte_init_beat_v3(void);
-extern void stabs_alloc(void);
extern void slb_initialize(void);
extern void slb_flush_and_rebolt(void);
-extern void stab_initialize(unsigned long stab);
extern void slb_vmalloc_update(void);
extern void slb_set_size(u16 size);
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index e61f24ed4e65..3d5abfe6ba67 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -64,9 +64,9 @@
*/
#define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000)
-/* MMU is SLB-based
+/* Doesn't support the B bit (1T segment) in SLBIE
*/
-#define MMU_FTR_SLB ASM_CONST(0x02000000)
+#define MMU_FTR_NO_SLBIE_B ASM_CONST(0x02000000)
/* Support 16M large pages
*/
@@ -88,10 +88,6 @@
*/
#define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000)
-/* Doesn't support the B bit (1T segment) in SLBIE
- */
-#define MMU_FTR_NO_SLBIE_B ASM_CONST(0x80000000)
-
/* MMU feature bit sets for various CPUs */
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \
MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index b467530e2485..73382eba02dc 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -18,7 +18,6 @@ extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
extern void destroy_context(struct mm_struct *mm);
extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
-extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
extern void set_context(unsigned long id, pgd_t *pgd);
@@ -77,10 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* sub architectures.
*/
#ifdef CONFIG_PPC_STD_MMU_64
- if (mmu_has_feature(MMU_FTR_SLB))
- switch_slb(tsk, next);
- else
- switch_stab(tsk, next);
+ switch_slb(tsk, next);
#else
/* Out of line for now */
switch_mmu_context(prev, next);
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h
index 736d4acc05a8..3bef74a9914b 100644
--- a/arch/powerpc/include/asm/mpc85xx.h
+++ b/arch/powerpc/include/asm/mpc85xx.h
@@ -77,6 +77,8 @@
#define SVR_T1020 0x852100
#define SVR_T1021 0x852101
#define SVR_T1022 0x852102
+#define SVR_T2080 0x853000
+#define SVR_T2081 0x853100
#define SVR_8610 0x80A000
#define SVR_8641 0x809000
diff --git a/arch/powerpc/include/asm/mpc8xx.h b/arch/powerpc/include/asm/mpc8xx.h
deleted file mode 100644
index 98f3c4f17328..000000000000
--- a/arch/powerpc/include/asm/mpc8xx.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* This is the single file included by all MPC8xx build options.
- * Since there are many different boards and no standard configuration,
- * we have a unique include file for each. Rather than change every
- * file that has to include MPC8xx configuration, they all include
- * this one and the configuration switching is done here.
- */
-#ifndef __CONFIG_8xx_DEFS
-#define __CONFIG_8xx_DEFS
-
-extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
-
-#endif /* __CONFIG_8xx_DEFS */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 0da1dbd42e02..86055e598269 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -147,6 +147,10 @@ struct opal_sg_list {
#define OPAL_SET_PARAM 90
#define OPAL_DUMP_RESEND 91
#define OPAL_DUMP_INFO2 94
+#define OPAL_PCI_EEH_FREEZE_SET 97
+#define OPAL_HANDLE_HMI 98
+#define OPAL_REGISTER_DUMP_REGION 101
+#define OPAL_UNREGISTER_DUMP_REGION 102
#ifndef __ASSEMBLY__
@@ -170,7 +174,11 @@ enum OpalFreezeState {
enum OpalEehFreezeActionToken {
OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1,
OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2,
- OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3
+ OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3,
+
+ OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1,
+ OPAL_EEH_ACTION_SET_FREEZE_DMA = 2,
+ OPAL_EEH_ACTION_SET_FREEZE_ALL = 3
};
enum OpalPciStatusToken {
@@ -240,6 +248,7 @@ enum OpalMessageType {
OPAL_MSG_MEM_ERR,
OPAL_MSG_EPOW,
OPAL_MSG_SHUTDOWN,
+ OPAL_MSG_HMI_EVT,
OPAL_MSG_TYPE_MAX,
};
@@ -340,6 +349,12 @@ enum OpalMveEnableAction {
OPAL_ENABLE_MVE = 1
};
+enum OpalM64EnableAction {
+ OPAL_DISABLE_M64 = 0,
+ OPAL_ENABLE_M64_SPLIT = 1,
+ OPAL_ENABLE_M64_NON_SPLIT = 2
+};
+
enum OpalPciResetScope {
OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
@@ -502,6 +517,50 @@ struct OpalMemoryErrorData {
} u;
};
+/* HMI interrupt event */
+enum OpalHMI_Version {
+ OpalHMIEvt_V1 = 1,
+};
+
+enum OpalHMI_Severity {
+ OpalHMI_SEV_NO_ERROR = 0,
+ OpalHMI_SEV_WARNING = 1,
+ OpalHMI_SEV_ERROR_SYNC = 2,
+ OpalHMI_SEV_FATAL = 3,
+};
+
+enum OpalHMI_Disposition {
+ OpalHMI_DISPOSITION_RECOVERED = 0,
+ OpalHMI_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum OpalHMI_ErrType {
+ OpalHMI_ERROR_MALFUNC_ALERT = 0,
+ OpalHMI_ERROR_PROC_RECOV_DONE,
+ OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN,
+ OpalHMI_ERROR_PROC_RECOV_MASKED,
+ OpalHMI_ERROR_TFAC,
+ OpalHMI_ERROR_TFMR_PARITY,
+ OpalHMI_ERROR_HA_OVERFLOW_WARN,
+ OpalHMI_ERROR_XSCOM_FAIL,
+ OpalHMI_ERROR_XSCOM_DONE,
+ OpalHMI_ERROR_SCOM_FIR,
+ OpalHMI_ERROR_DEBUG_TRIG_FIR,
+ OpalHMI_ERROR_HYP_RESOURCE,
+};
+
+struct OpalHMIEvent {
+ uint8_t version; /* 0x00 */
+ uint8_t severity; /* 0x01 */
+ uint8_t type; /* 0x02 */
+ uint8_t disposition; /* 0x03 */
+ uint8_t reserved_1[4]; /* 0x04 */
+
+ __be64 hmer;
+ /* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */
+ __be64 tfmr;
+};
+
enum {
OPAL_P7IOC_DIAG_TYPE_NONE = 0,
OPAL_P7IOC_DIAG_TYPE_RGC = 1,
@@ -513,40 +572,40 @@ enum {
};
struct OpalIoP7IOCErrorData {
- uint16_t type;
+ __be16 type;
/* GEM */
- uint64_t gemXfir;
- uint64_t gemRfir;
- uint64_t gemRirqfir;
- uint64_t gemMask;
- uint64_t gemRwof;
+ __be64 gemXfir;
+ __be64 gemRfir;
+ __be64 gemRirqfir;
+ __be64 gemMask;
+ __be64 gemRwof;
/* LEM */
- uint64_t lemFir;
- uint64_t lemErrMask;
- uint64_t lemAction0;
- uint64_t lemAction1;
- uint64_t lemWof;
+ __be64 lemFir;
+ __be64 lemErrMask;
+ __be64 lemAction0;
+ __be64 lemAction1;
+ __be64 lemWof;
union {
struct OpalIoP7IOCRgcErrorData {
- uint64_t rgcStatus; /* 3E1C10 */
- uint64_t rgcLdcp; /* 3E1C18 */
+ __be64 rgcStatus; /* 3E1C10 */
+ __be64 rgcLdcp; /* 3E1C18 */
}rgc;
struct OpalIoP7IOCBiErrorData {
- uint64_t biLdcp0; /* 3C0100, 3C0118 */
- uint64_t biLdcp1; /* 3C0108, 3C0120 */
- uint64_t biLdcp2; /* 3C0110, 3C0128 */
- uint64_t biFenceStatus; /* 3C0130, 3C0130 */
+ __be64 biLdcp0; /* 3C0100, 3C0118 */
+ __be64 biLdcp1; /* 3C0108, 3C0120 */
+ __be64 biLdcp2; /* 3C0110, 3C0128 */
+ __be64 biFenceStatus; /* 3C0130, 3C0130 */
- uint8_t biDownbound; /* BI Downbound or Upbound */
+ u8 biDownbound; /* BI Downbound or Upbound */
}bi;
struct OpalIoP7IOCCiErrorData {
- uint64_t ciPortStatus; /* 3Dn008 */
- uint64_t ciPortLdcp; /* 3Dn010 */
+ __be64 ciPortStatus; /* 3Dn008 */
+ __be64 ciPortLdcp; /* 3Dn010 */
- uint8_t ciPort; /* Index of CI port: 0/1 */
+ u8 ciPort; /* Index of CI port: 0/1 */
}ci;
};
};
@@ -578,60 +637,60 @@ struct OpalIoPhbErrorCommon {
struct OpalIoP7IOCPhbErrorData {
struct OpalIoPhbErrorCommon common;
- uint32_t brdgCtl;
+ __be32 brdgCtl;
// P7IOC utl regs
- uint32_t portStatusReg;
- uint32_t rootCmplxStatus;
- uint32_t busAgentStatus;
+ __be32 portStatusReg;
+ __be32 rootCmplxStatus;
+ __be32 busAgentStatus;
// P7IOC cfg regs
- uint32_t deviceStatus;
- uint32_t slotStatus;
- uint32_t linkStatus;
- uint32_t devCmdStatus;
- uint32_t devSecStatus;
+ __be32 deviceStatus;
+ __be32 slotStatus;
+ __be32 linkStatus;
+ __be32 devCmdStatus;
+ __be32 devSecStatus;
// cfg AER regs
- uint32_t rootErrorStatus;
- uint32_t uncorrErrorStatus;
- uint32_t corrErrorStatus;
- uint32_t tlpHdr1;
- uint32_t tlpHdr2;
- uint32_t tlpHdr3;
- uint32_t tlpHdr4;
- uint32_t sourceId;
+ __be32 rootErrorStatus;
+ __be32 uncorrErrorStatus;
+ __be32 corrErrorStatus;
+ __be32 tlpHdr1;
+ __be32 tlpHdr2;
+ __be32 tlpHdr3;
+ __be32 tlpHdr4;
+ __be32 sourceId;
- uint32_t rsv3;
+ __be32 rsv3;
// Record data about the call to allocate a buffer.
- uint64_t errorClass;
- uint64_t correlator;
+ __be64 errorClass;
+ __be64 correlator;
//P7IOC MMIO Error Regs
- uint64_t p7iocPlssr; // n120
- uint64_t p7iocCsr; // n110
- uint64_t lemFir; // nC00
- uint64_t lemErrorMask; // nC18
- uint64_t lemWOF; // nC40
- uint64_t phbErrorStatus; // nC80
- uint64_t phbFirstErrorStatus; // nC88
- uint64_t phbErrorLog0; // nCC0
- uint64_t phbErrorLog1; // nCC8
- uint64_t mmioErrorStatus; // nD00
- uint64_t mmioFirstErrorStatus; // nD08
- uint64_t mmioErrorLog0; // nD40
- uint64_t mmioErrorLog1; // nD48
- uint64_t dma0ErrorStatus; // nD80
- uint64_t dma0FirstErrorStatus; // nD88
- uint64_t dma0ErrorLog0; // nDC0
- uint64_t dma0ErrorLog1; // nDC8
- uint64_t dma1ErrorStatus; // nE00
- uint64_t dma1FirstErrorStatus; // nE08
- uint64_t dma1ErrorLog0; // nE40
- uint64_t dma1ErrorLog1; // nE48
- uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS];
- uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
+ __be64 p7iocPlssr; // n120
+ __be64 p7iocCsr; // n110
+ __be64 lemFir; // nC00
+ __be64 lemErrorMask; // nC18
+ __be64 lemWOF; // nC40
+ __be64 phbErrorStatus; // nC80
+ __be64 phbFirstErrorStatus; // nC88
+ __be64 phbErrorLog0; // nCC0
+ __be64 phbErrorLog1; // nCC8
+ __be64 mmioErrorStatus; // nD00
+ __be64 mmioFirstErrorStatus; // nD08
+ __be64 mmioErrorLog0; // nD40
+ __be64 mmioErrorLog1; // nD48
+ __be64 dma0ErrorStatus; // nD80
+ __be64 dma0FirstErrorStatus; // nD88
+ __be64 dma0ErrorLog0; // nDC0
+ __be64 dma0ErrorLog1; // nDC8
+ __be64 dma1ErrorStatus; // nE00
+ __be64 dma1FirstErrorStatus; // nE08
+ __be64 dma1ErrorLog0; // nE40
+ __be64 dma1ErrorLog1; // nE48
+ __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS];
+ __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS];
};
struct OpalIoPhb3ErrorData {
@@ -758,6 +817,8 @@ int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
__be64 *phb_status);
int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
uint64_t eeh_action_token);
+int64_t opal_pci_eeh_freeze_set(uint64_t phb_id, uint64_t pe_number,
+ uint64_t eeh_action_token);
int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
@@ -768,7 +829,7 @@ int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type,
uint16_t window_num,
uint64_t starting_real_address,
uint64_t starting_pci_address,
- uint16_t segment_size);
+ uint64_t size);
int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number,
uint16_t window_type, uint16_t window_num,
uint16_t segment_num);
@@ -860,6 +921,9 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer,
int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
uint64_t length);
int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data);
+int64_t opal_handle_hmi(void);
+int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
+int64_t opal_unregister_dump_region(uint32_t id);
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
@@ -902,6 +966,8 @@ extern void opal_msglog_init(void);
extern int opal_machine_check(struct pt_regs *regs);
extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
+extern int opal_hmi_exception_early(struct pt_regs *regs);
+extern int opal_handle_hmi_exception(struct pt_regs *regs);
extern void opal_shutdown(void);
extern int opal_resync_timebase(void);
@@ -912,6 +978,13 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
unsigned long vmalloc_size);
void opal_free_sg_list(struct opal_sg_list *sg);
+/*
+ * Dump region ID range usable by the OS
+ */
+#define OPAL_DUMP_REGION_HOST_START 0x80
+#define OPAL_DUMP_REGION_LOG_BUF 0x80
+#define OPAL_DUMP_REGION_HOST_END 0xFF
+
#endif /* __ASSEMBLY__ */
#endif /* __OPAL_H */
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h
index d697b08994c9..61fe5d6f18e1 100644
--- a/arch/powerpc/include/asm/oprofile_impl.h
+++ b/arch/powerpc/include/asm/oprofile_impl.h
@@ -61,7 +61,6 @@ struct op_powerpc_model {
};
extern struct op_powerpc_model op_model_fsl_emb;
-extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
extern struct op_powerpc_model op_model_7450;
extern struct op_powerpc_model op_model_cell;
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index bb0bd25f20d0..a5139ea6910b 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -78,10 +78,6 @@ struct paca_struct {
u64 kernel_toc; /* Kernel TOC address */
u64 kernelbase; /* Base address of kernel */
u64 kernel_msr; /* MSR while running in kernel */
-#ifdef CONFIG_PPC_STD_MMU_64
- u64 stab_real; /* Absolute address of segment table */
- u64 stab_addr; /* Virtual address of segment table */
-#endif /* CONFIG_PPC_STD_MMU_64 */
void *emergency_sp; /* pointer to emergency stack */
u64 data_offset; /* per cpu data offset */
s16 hw_cpu_id; /* Physical processor number */
@@ -171,6 +167,7 @@ struct paca_struct {
* and already using emergency stack.
*/
u16 in_mce;
+ u8 hmi_event_available; /* HMI event is available */
#endif
/* Stuff for accurate time accounting */
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 32e4e212b9c1..26fe1ae15212 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -48,9 +48,6 @@ extern unsigned int HPAGE_SHIFT;
#define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1)
#endif
-/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
-#define __HAVE_ARCH_GATE_AREA 1
-
/*
* Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we
* assign PAGE_MASK to a larger type it gets extended the way we want
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index b3e936027b26..814622146d5a 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -19,6 +19,8 @@
#define MAX_EVENT_ALTERNATIVES 8
#define MAX_LIMITED_HWCOUNTERS 2
+struct perf_event;
+
/*
* This struct provides the constants and functions needed to
* describe the PMU on a particular POWER-family CPU.
@@ -30,7 +32,8 @@ struct power_pmu {
unsigned long add_fields;
unsigned long test_adder;
int (*compute_mmcr)(u64 events[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[]);
+ unsigned int hwc[], unsigned long mmcr[],
+ struct perf_event *pevents[]);
int (*get_constraint)(u64 event_id, unsigned long *mskp,
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index eb9261024f51..7b3d54fae46f 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -413,7 +413,7 @@ static inline char *get_hpte_slot_array(pmd_t *pmdp)
}
extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
- pmd_t *pmdp);
+ pmd_t *pmdp, unsigned long old_pmd);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot);
extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 3132bb9365f3..6f8536208049 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -139,6 +139,7 @@
#define PPC_INST_ISEL 0x7c00001e
#define PPC_INST_ISEL_MASK 0xfc00003e
#define PPC_INST_LDARX 0x7c0000a8
+#define PPC_INST_LOGMPP 0x7c0007e4
#define PPC_INST_LSWI 0x7c0004aa
#define PPC_INST_LSWX 0x7c00042a
#define PPC_INST_LWARX 0x7c000028
@@ -150,8 +151,10 @@
#define PPC_INST_MCRXR_MASK 0xfc0007fe
#define PPC_INST_MFSPR_PVR 0x7c1f42a6
#define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff
+#define PPC_INST_MFTMR 0x7c0002dc
#define PPC_INST_MSGSND 0x7c00019c
#define PPC_INST_MSGSNDP 0x7c00011c
+#define PPC_INST_MTTMR 0x7c0003dc
#define PPC_INST_NOP 0x60000000
#define PPC_INST_POPCNTB 0x7c0000f4
#define PPC_INST_POPCNTB_MASK 0xfc0007fe
@@ -275,6 +278,20 @@
#define __PPC_EH(eh) 0
#endif
+/* POWER8 Micro Partition Prefetch (MPP) parameters */
+/* Address mask is common for LOGMPP instruction and MPPR SPR */
+#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000
+
+/* Bits 60 and 61 of MPP SPR should be set to one of the following */
+/* Aborting the fetch is indeed setting 00 in the table size bits */
+#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
+#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
+
+/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
+#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
+#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
+#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
+
/* Deal with instructions that older assemblers aren't aware of */
#define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \
__PPC_RA(a) | __PPC_RB(b))
@@ -283,6 +300,8 @@
#define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
+#define PPC_LOGMPP(b) stringify_in_c(.long PPC_INST_LOGMPP | \
+ __PPC_RB(b))
#define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
@@ -369,4 +388,11 @@
#define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \
| __PPC_RA(r))
+/* book3e thread control instructions */
+#define TMRN(x) ((((x) & 0x1f) << 16) | (((x) & 0x3e0) << 6))
+#define MTTMR(tmr, r) stringify_in_c(.long PPC_INST_MTTMR | \
+ TMRN(tmr) | ___PPC_RS(r))
+#define MFTMR(tmr, r) stringify_in_c(.long PPC_INST_MFTMR | \
+ TMRN(tmr) | ___PPC_RT(r))
+
#endif /* _ASM_POWERPC_PPC_OPCODE_H */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 6d59072e13a7..dda7ac4c80bd 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -400,6 +400,8 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
#define cpu_relax() barrier()
#endif
+#define cpu_relax_lowlatency() cpu_relax()
+
/* Check that a certain kernel stack pointer is valid in task_struct p */
int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes);
diff --git a/arch/powerpc/include/asm/pte-fsl-booke.h b/arch/powerpc/include/asm/pte-fsl-booke.h
index 2c12be5f677a..e84dd7ed505e 100644
--- a/arch/powerpc/include/asm/pte-fsl-booke.h
+++ b/arch/powerpc/include/asm/pte-fsl-booke.h
@@ -37,5 +37,7 @@
#define _PMD_PRESENT_MASK (PAGE_MASK)
#define _PMD_BAD (~PAGE_MASK)
+#define PTE_WIMGE_SHIFT (6)
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h
index d836d945068d..4f4ec2ab45c9 100644
--- a/arch/powerpc/include/asm/pte-hash64-64k.h
+++ b/arch/powerpc/include/asm/pte-hash64-64k.h
@@ -46,11 +46,31 @@
* in order to deal with 64K made of 4K HW pages. Thus we override the
* generic accessors and iterators here
*/
-#define __real_pte(e,p) ((real_pte_t) { \
- (e), (pte_val(e) & _PAGE_COMBO) ? \
- (pte_val(*((p) + PTRS_PER_PTE))) : 0 })
-#define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \
- (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
+#define __real_pte __real_pte
+static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep)
+{
+ real_pte_t rpte;
+
+ rpte.pte = pte;
+ rpte.hidx = 0;
+ if (pte_val(pte) & _PAGE_COMBO) {
+ /*
+ * Make sure we order the hidx load against the _PAGE_COMBO
+ * check. The store side ordering is done in __hash_page_4K
+ */
+ smp_rmb();
+ rpte.hidx = pte_val(*((ptep) + PTRS_PER_PTE));
+ }
+ return rpte;
+}
+
+static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
+{
+ if ((pte_val(rpte.pte) & _PAGE_COMBO))
+ return (rpte.hidx >> (index<<2)) & 0xf;
+ return (pte_val(rpte.pte) >> 12) & 0xf;
+}
+
#define __rpte_to_pte(r) ((r).pte)
#define __rpte_sub_valid(rpte, index) \
(pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index)))
@@ -75,7 +95,8 @@
(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
#define remap_4k_pfn(vma, addr, pfn, prot) \
- remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \
- __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
+ (WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL : \
+ remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \
+ __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)))
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index bffd89d27301..0c0505956a29 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -213,9 +213,8 @@
#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
#define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */
-#define TEXASR_FS __MASK(63-36) /* Transaction Failure Summary */
#define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */
-#define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */
+#define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */
#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
@@ -225,6 +224,7 @@
#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DAWR 0xB4
+#define SPRN_MPPR 0xB8 /* Micro Partition Prefetch Register */
#define SPRN_RPR 0xBA /* Relative Priority Register */
#define SPRN_CIABR 0xBB
#define CIABR_PRIV 0x3
@@ -254,7 +254,7 @@
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
#define DSISR_ISSTORE 0x02000000 /* access was a store */
#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
-#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
+#define DSISR_NOSEGMENT 0x00200000 /* SLB miss */
#define DSISR_KEYFAULT 0x00200000 /* Key fault */
#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */
#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */
@@ -944,9 +944,6 @@
* readable variant for reads, which can avoid a fault
* with KVM type virtualization.
*
- * (*) Under KVM, the host SPRG1 is used to point to
- * the current VCPU data structure
- *
* 32-bit 8xx:
* - SPRG0 scratch for exception vectors
* - SPRG1 scratch for exception vectors
@@ -1203,6 +1200,15 @@
: "r" ((unsigned long)(v)) \
: "memory")
+static inline unsigned long mfvtb (void)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ return mfspr(SPRN_VTB);
+#endif
+ return 0;
+}
+
#ifdef __powerpc64__
#if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E)
#define mftb() ({unsigned long rval; \
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 464f1089b532..1d653308a33c 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -15,16 +15,28 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__
+#include <asm/ppc-opcode.h>
+
/* Machine State Register (MSR) Fields */
-#define MSR_GS (1<<28) /* Guest state */
-#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
-#define MSR_SPE (1<<25) /* Enable SPE */
-#define MSR_DWE (1<<10) /* Debug Wait Enable */
-#define MSR_UBLE (1<<10) /* BTB lock enable (e500) */
-#define MSR_IS MSR_IR /* Instruction Space */
-#define MSR_DS MSR_DR /* Data Space */
-#define MSR_PMM (1<<2) /* Performance monitor mark bit */
-#define MSR_CM (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */
+#define MSR_GS_LG 28 /* Guest state */
+#define MSR_UCLE_LG 26 /* User-mode cache lock enable */
+#define MSR_SPE_LG 25 /* Enable SPE */
+#define MSR_DWE_LG 10 /* Debug Wait Enable */
+#define MSR_UBLE_LG 10 /* BTB lock enable (e500) */
+#define MSR_IS_LG MSR_IR_LG /* Instruction Space */
+#define MSR_DS_LG MSR_DR_LG /* Data Space */
+#define MSR_PMM_LG 2 /* Performance monitor mark bit */
+#define MSR_CM_LG 31 /* Computation Mode (0=32-bit, 1=64-bit) */
+
+#define MSR_GS __MASK(MSR_GS_LG)
+#define MSR_UCLE __MASK(MSR_UCLE_LG)
+#define MSR_SPE __MASK(MSR_SPE_LG)
+#define MSR_DWE __MASK(MSR_DWE_LG)
+#define MSR_UBLE __MASK(MSR_UBLE_LG)
+#define MSR_IS __MASK(MSR_IS_LG)
+#define MSR_DS __MASK(MSR_DS_LG)
+#define MSR_PMM __MASK(MSR_PMM_LG)
+#define MSR_CM __MASK(MSR_CM_LG)
#if defined(CONFIG_PPC_BOOK3E_64)
#define MSR_64BIT MSR_CM
@@ -260,7 +272,7 @@
/* e500mc */
#define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */
-#define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */
+#define MCSR_L2MMU_MHIT 0x08000000UL /* Hit on multiple TLB entries */
#define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */
#define MCSR_MAV 0x00080000UL /* MCAR address valid */
#define MCSR_MEA 0x00040000UL /* MCAR is effective address */
@@ -598,6 +610,13 @@
/* Bit definitions for L1CSR2. */
#define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */
+/* Bit definitions for BUCSR. */
+#define BUCSR_STAC_EN 0x01000000 /* Segment Target Address Cache */
+#define BUCSR_LS_EN 0x00400000 /* Link Stack */
+#define BUCSR_BBFI 0x00000200 /* Branch Buffer flash invalidate */
+#define BUCSR_BPEN 0x00000001 /* Branch prediction enable */
+#define BUCSR_INIT (BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN)
+
/* Bit definitions for L2CSR0. */
#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */
#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */
@@ -721,5 +740,23 @@
#define MMUBE1_VBE4 0x00000002
#define MMUBE1_VBE5 0x00000001
+#define TMRN_IMSR0 0x120 /* Initial MSR Register 0 (e6500) */
+#define TMRN_IMSR1 0x121 /* Initial MSR Register 1 (e6500) */
+#define TMRN_INIA0 0x140 /* Next Instruction Address Register 0 */
+#define TMRN_INIA1 0x141 /* Next Instruction Address Register 1 */
+#define SPRN_TENSR 0x1b5 /* Thread Enable Status Register */
+#define SPRN_TENS 0x1b6 /* Thread Enable Set Register */
+#define SPRN_TENC 0x1b7 /* Thread Enable Clear Register */
+
+#define TEN_THREAD(x) (1 << (x))
+
+#ifndef __ASSEMBLY__
+#define mftmr(rn) ({unsigned long rval; \
+ asm volatile(MFTMR(rn, %0) : "=r" (rval)); rval;})
+#define mttmr(rn, v) asm volatile(MTTMR(rn, %0) : \
+ : "r" ((unsigned long)(v)) \
+ : "memory")
+#endif /* !__ASSEMBLY__ */
+
#endif /* __ASM_POWERPC_REG_BOOKE_H__ */
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/scatterlist.h b/arch/powerpc/include/asm/scatterlist.h
deleted file mode 100644
index de1f620bd5c9..000000000000
--- a/arch/powerpc/include/asm/scatterlist.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_POWERPC_SCATTERLIST_H
-#define _ASM_POWERPC_SCATTERLIST_H
-/*
- * Copyright (C) 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/dma.h>
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_POWERPC_SCATTERLIST_H */
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
index 35aa339410bd..4dbe072eecbe 100644
--- a/arch/powerpc/include/asm/spinlock.h
+++ b/arch/powerpc/include/asm/spinlock.h
@@ -61,6 +61,7 @@ static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
static inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
+ smp_mb();
return !arch_spin_value_unlocked(*lock);
}
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index babbeca6850f..542bc0f0673f 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -77,10 +77,10 @@ SYSCALL_SPU(setreuid)
SYSCALL_SPU(setregid)
#define compat_sys_sigsuspend sys_sigsuspend
SYS32ONLY(sigsuspend)
-COMPAT_SYS(sigpending)
+SYSX(sys_ni_syscall,compat_sys_sigpending,sys_sigpending)
SYSCALL_SPU(sethostname)
COMPAT_SYS_SPU(setrlimit)
-COMPAT_SYS(old_getrlimit)
+SYSX(sys_ni_syscall,compat_sys_old_getrlimit,sys_old_getrlimit)
COMPAT_SYS_SPU(getrusage)
COMPAT_SYS_SPU(gettimeofday)
COMPAT_SYS_SPU(settimeofday)
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index 1d428e6007ca..03cbada59d3a 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -102,6 +102,15 @@ static inline u64 get_rtc(void)
return (u64)hi * 1000000000 + lo;
}
+static inline u64 get_vtb(void)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ return mfvtb();
+#endif
+ return 0;
+}
+
#ifdef CONFIG_PPC64
static inline u64 get_tb(void)
{
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h
index 5712f06905a9..c15da6073cb8 100644
--- a/arch/powerpc/include/asm/trace.h
+++ b/arch/powerpc/include/asm/trace.h
@@ -99,6 +99,51 @@ TRACE_EVENT_FN(hcall_exit,
);
#endif
+#ifdef CONFIG_PPC_POWERNV
+extern void opal_tracepoint_regfunc(void);
+extern void opal_tracepoint_unregfunc(void);
+
+TRACE_EVENT_FN(opal_entry,
+
+ TP_PROTO(unsigned long opcode, unsigned long *args),
+
+ TP_ARGS(opcode, args),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, opcode)
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ ),
+
+ TP_printk("opcode=%lu", __entry->opcode),
+
+ opal_tracepoint_regfunc, opal_tracepoint_unregfunc
+);
+
+TRACE_EVENT_FN(opal_exit,
+
+ TP_PROTO(unsigned long opcode, unsigned long retval),
+
+ TP_ARGS(opcode, retval),
+
+ TP_STRUCT__entry(
+ __field(unsigned long, opcode)
+ __field(unsigned long, retval)
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->retval = retval;
+ ),
+
+ TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval),
+
+ opal_tracepoint_regfunc, opal_tracepoint_unregfunc
+);
+#endif
+
#endif /* _TRACE_POWERPC_H */
#undef TRACE_INCLUDE_PATH
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 2bc4a9409a93..e0e49dbb145d 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -548,6 +548,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
+#define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
#define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
/* Architecture compatibility level */
@@ -555,6 +556,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
+#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index f5995a912213..9d7dede2847c 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -216,8 +216,6 @@ int main(void)
#endif /* CONFIG_PPC_BOOK3E */
#ifdef CONFIG_PPC_STD_MMU_64
- DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real));
- DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr));
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
@@ -493,6 +491,7 @@ int main(void)
DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1));
DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock));
DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
+ DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
@@ -667,6 +666,7 @@ int main(void)
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
+ DEFINE(VCPU_SPRG9, offsetof(struct kvm_vcpu, arch.sprg9));
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 0c157642c2a1..9b6dcaaec1a3 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -123,96 +123,6 @@ extern void __restore_cpu_e6500(void);
static struct cpu_spec __initdata cpu_specs[] = {
#ifdef CONFIG_PPC_BOOK3S_64
- { /* Power3 */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00400000,
- .cpu_name = "POWER3 (630)",
- .cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power3",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "power3",
- },
- { /* Power3+ */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00410000,
- .cpu_name = "POWER3 (630+)",
- .cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power3",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "power3",
- },
- { /* Northstar */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00330000,
- .cpu_name = "RS64-II (northstar)",
- .cpu_features = CPU_FTRS_RS64,
- .cpu_user_features = COMMON_USER_PPC64,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/rs64",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "rs64",
- },
- { /* Pulsar */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00340000,
- .cpu_name = "RS64-III (pulsar)",
- .cpu_features = CPU_FTRS_RS64,
- .cpu_user_features = COMMON_USER_PPC64,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/rs64",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "rs64",
- },
- { /* I-star */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00360000,
- .cpu_name = "RS64-III (icestar)",
- .cpu_features = CPU_FTRS_RS64,
- .cpu_user_features = COMMON_USER_PPC64,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/rs64",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "rs64",
- },
- { /* S-star */
- .pvr_mask = 0xffff0000,
- .pvr_value = 0x00370000,
- .cpu_name = "RS64-IV (sstar)",
- .cpu_features = CPU_FTRS_RS64,
- .cpu_user_features = COMMON_USER_PPC64,
- .mmu_features = MMU_FTR_HPTE_TABLE,
- .icache_bsize = 128,
- .dcache_bsize = 128,
- .num_pmcs = 8,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/rs64",
- .oprofile_type = PPC_OPROFILE_RS64,
- .platform = "rs64",
- },
{ /* Power4 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00350000,
@@ -617,7 +527,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
#endif /* CONFIG_PPC_BOOK3S_64 */
#ifdef CONFIG_PPC32
-#if CLASSIC_PPC
+#ifdef CONFIG_PPC_BOOK3S_32
{ /* 601 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00010000,
@@ -1257,7 +1167,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_generic,
.platform = "ppc603",
},
-#endif /* CLASSIC_PPC */
+#endif /* CONFIG_PPC_BOOK3S_32 */
#ifdef CONFIG_8xx
{ /* 8xx */
.pvr_mask = 0xffff0000,
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 86e25702aaca..59a64f8dc85f 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/iommu.h>
#include <linux/proc_fs.h>
#include <linux/rbtree.h>
#include <linux/reboot.h>
@@ -40,6 +41,7 @@
#include <asm/eeh.h>
#include <asm/eeh_event.h>
#include <asm/io.h>
+#include <asm/iommu.h>
#include <asm/machdep.h>
#include <asm/ppc-pci.h>
#include <asm/rtas.h>
@@ -108,6 +110,9 @@ struct eeh_ops *eeh_ops = NULL;
/* Lock to avoid races due to multiple reports of an error */
DEFINE_RAW_SPINLOCK(confirm_error_lock);
+/* Lock to protect passed flags */
+static DEFINE_MUTEX(eeh_dev_mutex);
+
/* Buffer for reporting pci register dumps. Its here in BSS, and
* not dynamically alloced, so that it ends up in RMO where RTAS
* can access it.
@@ -137,7 +142,7 @@ static struct eeh_stats eeh_stats;
static int __init eeh_setup(char *str)
{
if (!strcmp(str, "off"))
- eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+ eeh_add_flag(EEH_FORCE_DISABLED);
return 1;
}
@@ -152,12 +157,13 @@ __setup("eeh=", eeh_setup);
* This routine captures assorted PCI configuration space data,
* and puts them into a buffer for RTAS error logging.
*/
-static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
+static size_t eeh_gather_pci_data(struct eeh_dev *edev, char *buf, size_t len)
{
struct device_node *dn = eeh_dev_to_of_node(edev);
u32 cfg;
int cap, i;
- int n = 0;
+ int n = 0, l = 0;
+ char buffer[128];
n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
pr_warn("EEH: of node=%s\n", dn->full_name);
@@ -202,8 +208,22 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
for (i=0; i<=8; i++) {
eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
- pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg);
+
+ if ((i % 4) == 0) {
+ if (i != 0)
+ pr_warn("%s\n", buffer);
+
+ l = scnprintf(buffer, sizeof(buffer),
+ "EEH: PCI-E %02x: %08x ",
+ 4*i, cfg);
+ } else {
+ l += scnprintf(buffer+l, sizeof(buffer)-l,
+ "%08x ", cfg);
+ }
+
}
+
+ pr_warn("%s\n", buffer);
}
/* If AER capable, dump it */
@@ -212,11 +232,24 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
n += scnprintf(buf+n, len-n, "pci-e AER:\n");
pr_warn("EEH: PCI-E AER capability register set follows:\n");
- for (i=0; i<14; i++) {
+ for (i=0; i<=13; i++) {
eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
- pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg);
+
+ if ((i % 4) == 0) {
+ if (i != 0)
+ pr_warn("%s\n", buffer);
+
+ l = scnprintf(buffer, sizeof(buffer),
+ "EEH: PCI-E AER %02x: %08x ",
+ 4*i, cfg);
+ } else {
+ l += scnprintf(buffer+l, sizeof(buffer)-l,
+ "%08x ", cfg);
+ }
}
+
+ pr_warn("%s\n", buffer);
}
return n;
@@ -247,7 +280,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
* 0xFF's is always returned from PCI config space.
*/
if (!(pe->type & EEH_PE_PHB)) {
- if (eeh_probe_mode_devtree())
+ if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
eeh_ops->configure_bridge(pe);
eeh_pe_restore_bars(pe);
@@ -298,14 +331,14 @@ static int eeh_phb_check_failure(struct eeh_pe *pe)
unsigned long flags;
int ret;
- if (!eeh_probe_mode_dev())
+ if (!eeh_has_flag(EEH_PROBE_MODE_DEV))
return -EPERM;
/* Find the PHB PE */
phb_pe = eeh_phb_pe_get(pe->phb);
if (!phb_pe) {
- pr_warning("%s Can't find PE for PHB#%d\n",
- __func__, pe->phb->global_number);
+ pr_warn("%s Can't find PE for PHB#%d\n",
+ __func__, pe->phb->global_number);
return -EEXIST;
}
@@ -400,6 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
if (ret > 0)
return ret;
+ /*
+ * If the PE isn't owned by us, we shouldn't check the
+ * state. Instead, let the owner handle it if the PE has
+ * been frozen.
+ */
+ if (eeh_pe_passed(pe))
+ return 0;
+
/* If we already have a pending isolation event for this
* slot, we know it's bad already, we don't need to check.
* Do this checking under a lock; as multiple PCI devices
@@ -746,13 +787,13 @@ void eeh_save_bars(struct eeh_dev *edev)
int __init eeh_ops_register(struct eeh_ops *ops)
{
if (!ops->name) {
- pr_warning("%s: Invalid EEH ops name for %p\n",
+ pr_warn("%s: Invalid EEH ops name for %p\n",
__func__, ops);
return -EINVAL;
}
if (eeh_ops && eeh_ops != ops) {
- pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
+ pr_warn("%s: EEH ops of platform %s already existing (%s)\n",
__func__, eeh_ops->name, ops->name);
return -EEXIST;
}
@@ -772,7 +813,7 @@ int __init eeh_ops_register(struct eeh_ops *ops)
int __exit eeh_ops_unregister(const char *name)
{
if (!name || !strlen(name)) {
- pr_warning("%s: Invalid EEH ops name\n",
+ pr_warn("%s: Invalid EEH ops name\n",
__func__);
return -EINVAL;
}
@@ -788,7 +829,7 @@ int __exit eeh_ops_unregister(const char *name)
static int eeh_reboot_notifier(struct notifier_block *nb,
unsigned long action, void *unused)
{
- eeh_set_enable(false);
+ eeh_clear_flag(EEH_ENABLED);
return NOTIFY_DONE;
}
@@ -837,11 +878,11 @@ int eeh_init(void)
/* call platform initialization function */
if (!eeh_ops) {
- pr_warning("%s: Platform EEH operation not found\n",
+ pr_warn("%s: Platform EEH operation not found\n",
__func__);
return -EEXIST;
} else if ((ret = eeh_ops->init())) {
- pr_warning("%s: Failed to call platform init function (%d)\n",
+ pr_warn("%s: Failed to call platform init function (%d)\n",
__func__, ret);
return ret;
}
@@ -852,13 +893,13 @@ int eeh_init(void)
return ret;
/* Enable EEH for all adapters */
- if (eeh_probe_mode_devtree()) {
+ if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) {
list_for_each_entry_safe(hose, tmp,
&hose_list, list_node) {
phb = hose->dn;
traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
}
- } else if (eeh_probe_mode_dev()) {
+ } else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) {
list_for_each_entry_safe(hose, tmp,
&hose_list, list_node)
pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL);
@@ -882,7 +923,7 @@ int eeh_init(void)
if (eeh_enabled())
pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
else
- pr_warning("EEH: No capable adapters found\n");
+ pr_warn("EEH: No capable adapters found\n");
return ret;
}
@@ -910,7 +951,7 @@ void eeh_add_device_early(struct device_node *dn)
* would delay the probe until late stage because
* the PCI device isn't available this moment.
*/
- if (!eeh_probe_mode_devtree())
+ if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
return;
if (!of_node_to_eeh_dev(dn))
@@ -996,7 +1037,7 @@ void eeh_add_device_late(struct pci_dev *dev)
* We have to do the EEH probe here because the PCI device
* hasn't been created yet in the early stage.
*/
- if (eeh_probe_mode_dev())
+ if (eeh_has_flag(EEH_PROBE_MODE_DEV))
eeh_ops->dev_probe(dev, NULL);
eeh_addr_cache_insert_dev(dev);
@@ -1100,6 +1141,285 @@ void eeh_remove_device(struct pci_dev *dev)
edev->mode &= ~EEH_DEV_SYSFS;
}
+/**
+ * eeh_dev_open - Increase count of pass through devices for PE
+ * @pdev: PCI device
+ *
+ * Increase count of passed through devices for the indicated
+ * PE. In the result, the EEH errors detected on the PE won't be
+ * reported. The PE owner will be responsible for detection
+ * and recovery.
+ */
+int eeh_dev_open(struct pci_dev *pdev)
+{
+ struct eeh_dev *edev;
+
+ mutex_lock(&eeh_dev_mutex);
+
+ /* No PCI device ? */
+ if (!pdev)
+ goto out;
+
+ /* No EEH device or PE ? */
+ edev = pci_dev_to_eeh_dev(pdev);
+ if (!edev || !edev->pe)
+ goto out;
+
+ /* Increase PE's pass through count */
+ atomic_inc(&edev->pe->pass_dev_cnt);
+ mutex_unlock(&eeh_dev_mutex);
+
+ return 0;
+out:
+ mutex_unlock(&eeh_dev_mutex);
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(eeh_dev_open);
+
+/**
+ * eeh_dev_release - Decrease count of pass through devices for PE
+ * @pdev: PCI device
+ *
+ * Decrease count of pass through devices for the indicated PE. If
+ * there is no passed through device in PE, the EEH errors detected
+ * on the PE will be reported and handled as usual.
+ */
+void eeh_dev_release(struct pci_dev *pdev)
+{
+ struct eeh_dev *edev;
+
+ mutex_lock(&eeh_dev_mutex);
+
+ /* No PCI device ? */
+ if (!pdev)
+ goto out;
+
+ /* No EEH device ? */
+ edev = pci_dev_to_eeh_dev(pdev);
+ if (!edev || !edev->pe || !eeh_pe_passed(edev->pe))
+ goto out;
+
+ /* Decrease PE's pass through count */
+ atomic_dec(&edev->pe->pass_dev_cnt);
+ WARN_ON(atomic_read(&edev->pe->pass_dev_cnt) < 0);
+out:
+ mutex_unlock(&eeh_dev_mutex);
+}
+EXPORT_SYMBOL(eeh_dev_release);
+
+#ifdef CONFIG_IOMMU_API
+
+static int dev_has_iommu_table(struct device *dev, void *data)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_dev **ppdev = data;
+ struct iommu_table *tbl;
+
+ if (!dev)
+ return 0;
+
+ tbl = get_iommu_table_base(dev);
+ if (tbl && tbl->it_group) {
+ *ppdev = pdev;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * eeh_iommu_group_to_pe - Convert IOMMU group to EEH PE
+ * @group: IOMMU group
+ *
+ * The routine is called to convert IOMMU group to EEH PE.
+ */
+struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group)
+{
+ struct pci_dev *pdev = NULL;
+ struct eeh_dev *edev;
+ int ret;
+
+ /* No IOMMU group ? */
+ if (!group)
+ return NULL;
+
+ ret = iommu_group_for_each_dev(group, &pdev, dev_has_iommu_table);
+ if (!ret || !pdev)
+ return NULL;
+
+ /* No EEH device or PE ? */
+ edev = pci_dev_to_eeh_dev(pdev);
+ if (!edev || !edev->pe)
+ return NULL;
+
+ return edev->pe;
+}
+EXPORT_SYMBOL_GPL(eeh_iommu_group_to_pe);
+
+#endif /* CONFIG_IOMMU_API */
+
+/**
+ * eeh_pe_set_option - Set options for the indicated PE
+ * @pe: EEH PE
+ * @option: requested option
+ *
+ * The routine is called to enable or disable EEH functionality
+ * on the indicated PE, to enable IO or DMA for the frozen PE.
+ */
+int eeh_pe_set_option(struct eeh_pe *pe, int option)
+{
+ int ret = 0;
+
+ /* Invalid PE ? */
+ if (!pe)
+ return -ENODEV;
+
+ /*
+ * EEH functionality could possibly be disabled, just
+ * return error for the case. And the EEH functinality
+ * isn't expected to be disabled on one specific PE.
+ */
+ switch (option) {
+ case EEH_OPT_ENABLE:
+ if (eeh_enabled())
+ break;
+ ret = -EIO;
+ break;
+ case EEH_OPT_DISABLE:
+ break;
+ case EEH_OPT_THAW_MMIO:
+ case EEH_OPT_THAW_DMA:
+ if (!eeh_ops || !eeh_ops->set_option) {
+ ret = -ENOENT;
+ break;
+ }
+
+ ret = eeh_ops->set_option(pe, option);
+ break;
+ default:
+ pr_debug("%s: Option %d out of range (%d, %d)\n",
+ __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_set_option);
+
+/**
+ * eeh_pe_get_state - Retrieve PE's state
+ * @pe: EEH PE
+ *
+ * Retrieve the PE's state, which includes 3 aspects: enabled
+ * DMA, enabled IO and asserted reset.
+ */
+int eeh_pe_get_state(struct eeh_pe *pe)
+{
+ int result, ret = 0;
+ bool rst_active, dma_en, mmio_en;
+
+ /* Existing PE ? */
+ if (!pe)
+ return -ENODEV;
+
+ if (!eeh_ops || !eeh_ops->get_state)
+ return -ENOENT;
+
+ result = eeh_ops->get_state(pe, NULL);
+ rst_active = !!(result & EEH_STATE_RESET_ACTIVE);
+ dma_en = !!(result & EEH_STATE_DMA_ENABLED);
+ mmio_en = !!(result & EEH_STATE_MMIO_ENABLED);
+
+ if (rst_active)
+ ret = EEH_PE_STATE_RESET;
+ else if (dma_en && mmio_en)
+ ret = EEH_PE_STATE_NORMAL;
+ else if (!dma_en && !mmio_en)
+ ret = EEH_PE_STATE_STOPPED_IO_DMA;
+ else if (!dma_en && mmio_en)
+ ret = EEH_PE_STATE_STOPPED_DMA;
+ else
+ ret = EEH_PE_STATE_UNAVAIL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_get_state);
+
+/**
+ * eeh_pe_reset - Issue PE reset according to specified type
+ * @pe: EEH PE
+ * @option: reset type
+ *
+ * The routine is called to reset the specified PE with the
+ * indicated type, either fundamental reset or hot reset.
+ * PE reset is the most important part for error recovery.
+ */
+int eeh_pe_reset(struct eeh_pe *pe, int option)
+{
+ int ret = 0;
+
+ /* Invalid PE ? */
+ if (!pe)
+ return -ENODEV;
+
+ if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset)
+ return -ENOENT;
+
+ switch (option) {
+ case EEH_RESET_DEACTIVATE:
+ ret = eeh_ops->reset(pe, option);
+ if (ret)
+ break;
+
+ /*
+ * The PE is still in frozen state and we need to clear
+ * that. It's good to clear frozen state after deassert
+ * to avoid messy IO access during reset, which might
+ * cause recursive frozen PE.
+ */
+ ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
+ if (!ret)
+ ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
+ if (!ret)
+ eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
+ break;
+ case EEH_RESET_HOT:
+ case EEH_RESET_FUNDAMENTAL:
+ ret = eeh_ops->reset(pe, option);
+ break;
+ default:
+ pr_debug("%s: Unsupported option %d\n",
+ __func__, option);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_reset);
+
+/**
+ * eeh_pe_configure - Configure PCI bridges after PE reset
+ * @pe: EEH PE
+ *
+ * The routine is called to restore the PCI config space for
+ * those PCI devices, especially PCI bridges affected by PE
+ * reset issued previously.
+ */
+int eeh_pe_configure(struct eeh_pe *pe)
+{
+ int ret = 0;
+
+ /* Invalid PE ? */
+ if (!pe)
+ return -ENODEV;
+
+ /* Restore config space for the affected devices */
+ eeh_pe_restore_bars(pe);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(eeh_pe_configure);
+
static int proc_eeh_show(struct seq_file *m, void *v)
{
if (!eeh_enabled()) {
@@ -1143,9 +1463,9 @@ static const struct file_operations proc_eeh_operations = {
static int eeh_enable_dbgfs_set(void *data, u64 val)
{
if (val)
- eeh_subsystem_flags &= ~EEH_FORCE_DISABLED;
+ eeh_clear_flag(EEH_FORCE_DISABLED);
else
- eeh_subsystem_flags |= EEH_FORCE_DISABLED;
+ eeh_add_flag(EEH_FORCE_DISABLED);
/* Notify the backend */
if (eeh_ops->post_init)
diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c
index e8c9fd546a5c..07d8a2423a61 100644
--- a/arch/powerpc/kernel/eeh_cache.c
+++ b/arch/powerpc/kernel/eeh_cache.c
@@ -143,7 +143,7 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
} else {
if (dev != piar->pcidev ||
alo != piar->addr_lo || ahi != piar->addr_hi) {
- pr_warning("PIAR: overlapping address range\n");
+ pr_warn("PIAR: overlapping address range\n");
}
return piar;
}
@@ -177,19 +177,20 @@ static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
dn = pci_device_to_OF_node(dev);
if (!dn) {
- pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev));
+ pr_warn("PCI: no pci dn found for dev=%s\n",
+ pci_name(dev));
return;
}
edev = of_node_to_eeh_dev(dn);
if (!edev) {
- pr_warning("PCI: no EEH dev found for dn=%s\n",
+ pr_warn("PCI: no EEH dev found for dn=%s\n",
dn->full_name);
return;
}
/* Skip any devices for which EEH is not enabled. */
- if (!eeh_probe_mode_dev() && !edev->pe) {
+ if (!edev->pe) {
#ifdef DEBUG
pr_info("PCI: skip building address cache for=%s - %s\n",
pci_name(dev), dn->full_name);
diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c
index 1efa28f5fc54..e5274ee9a75f 100644
--- a/arch/powerpc/kernel/eeh_dev.c
+++ b/arch/powerpc/kernel/eeh_dev.c
@@ -57,7 +57,8 @@ void *eeh_dev_init(struct device_node *dn, void *data)
/* Allocate EEH device */
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev) {
- pr_warning("%s: out of memory\n", __func__);
+ pr_warn("%s: out of memory\n",
+ __func__);
return NULL;
}
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 420da61d4ce0..6a0dcee8e931 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -599,7 +599,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
pe->freeze_count++;
if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES)
goto excess_failures;
- pr_warning("EEH: This PCI device has failed %d times in the last hour\n",
+ pr_warn("EEH: This PCI device has failed %d times in the last hour\n",
pe->freeze_count);
/* Walk the various device drivers attached to this slot through
@@ -616,7 +616,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
*/
rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000);
if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {
- pr_warning("EEH: Permanent failure\n");
+ pr_warn("EEH: Permanent failure\n");
goto hard_fail;
}
@@ -635,8 +635,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
pr_info("EEH: Reset with hotplug activity\n");
rc = eeh_reset_device(pe, frozen_bus);
if (rc) {
- pr_warning("%s: Unable to reset, err=%d\n",
- __func__, rc);
+ pr_warn("%s: Unable to reset, err=%d\n",
+ __func__, rc);
goto hard_fail;
}
}
@@ -678,7 +678,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
/* If any device has a hard failure, then shut off everything. */
if (result == PCI_ERS_RESULT_DISCONNECT) {
- pr_warning("EEH: Device driver gave up\n");
+ pr_warn("EEH: Device driver gave up\n");
goto hard_fail;
}
@@ -687,8 +687,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
pr_info("EEH: Reset without hotplug activity\n");
rc = eeh_reset_device(pe, NULL);
if (rc) {
- pr_warning("%s: Cannot reset, err=%d\n",
- __func__, rc);
+ pr_warn("%s: Cannot reset, err=%d\n",
+ __func__, rc);
goto hard_fail;
}
@@ -701,7 +701,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
/* All devices should claim they have recovered by now. */
if ((result != PCI_ERS_RESULT_RECOVERED) &&
(result != PCI_ERS_RESULT_NONE)) {
- pr_warning("EEH: Not recovered\n");
+ pr_warn("EEH: Not recovered\n");
goto hard_fail;
}
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index fbd01eba4473..00e3844525a6 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -32,9 +32,24 @@
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
+static int eeh_pe_aux_size = 0;
static LIST_HEAD(eeh_phb_pe);
/**
+ * eeh_set_pe_aux_size - Set PE auxillary data size
+ * @size: PE auxillary data size
+ *
+ * Set PE auxillary data size
+ */
+void eeh_set_pe_aux_size(int size)
+{
+ if (size < 0)
+ return;
+
+ eeh_pe_aux_size = size;
+}
+
+/**
* eeh_pe_alloc - Allocate PE
* @phb: PCI controller
* @type: PE type
@@ -44,9 +59,16 @@ static LIST_HEAD(eeh_phb_pe);
static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
{
struct eeh_pe *pe;
+ size_t alloc_size;
+
+ alloc_size = sizeof(struct eeh_pe);
+ if (eeh_pe_aux_size) {
+ alloc_size = ALIGN(alloc_size, cache_line_size());
+ alloc_size += eeh_pe_aux_size;
+ }
/* Allocate PHB PE */
- pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
+ pe = kzalloc(alloc_size, GFP_KERNEL);
if (!pe) return NULL;
/* Initialize PHB PE */
@@ -56,6 +78,8 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
INIT_LIST_HEAD(&pe->child);
INIT_LIST_HEAD(&pe->edevs);
+ pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe),
+ cache_line_size());
return pe;
}
@@ -179,7 +203,8 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
void *ret;
if (!root) {
- pr_warning("%s: Invalid PE %p\n", __func__, root);
+ pr_warn("%s: Invalid PE %p\n",
+ __func__, root);
return NULL;
}
@@ -351,17 +376,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
pe->config_addr = edev->config_addr;
/*
- * While doing PE reset, we probably hot-reset the
- * upstream bridge. However, the PCI devices including
- * the associated EEH devices might be removed when EEH
- * core is doing recovery. So that won't safe to retrieve
- * the bridge through downstream EEH device. We have to
- * trace the parent PCI bus, then the upstream bridge.
- */
- if (eeh_probe_mode_dev())
- pe->bus = eeh_dev_to_pci_dev(edev)->bus;
-
- /*
* Put the new EEH PE into hierarchy tree. If the parent
* can't be found, the newly created PE will be attached
* to PHB directly. Otherwise, we have to associate the
@@ -802,53 +816,33 @@ void eeh_pe_restore_bars(struct eeh_pe *pe)
*/
const char *eeh_pe_loc_get(struct eeh_pe *pe)
{
- struct pci_controller *hose;
struct pci_bus *bus = eeh_pe_bus_get(pe);
- struct pci_dev *pdev;
- struct device_node *dn;
- const char *loc;
+ struct device_node *dn = pci_bus_to_OF_node(bus);
+ const char *loc = NULL;
- if (!bus)
- return "N/A";
+ if (!dn)
+ goto out;
/* PHB PE or root PE ? */
if (pci_is_root_bus(bus)) {
- hose = pci_bus_to_host(bus);
- loc = of_get_property(hose->dn,
- "ibm,loc-code", NULL);
+ loc = of_get_property(dn, "ibm,loc-code", NULL);
+ if (!loc)
+ loc = of_get_property(dn, "ibm,io-base-loc-code", NULL);
if (loc)
- return loc;
- loc = of_get_property(hose->dn,
- "ibm,io-base-loc-code", NULL);
- if (loc)
- return loc;
-
- pdev = pci_get_slot(bus, 0x0);
- } else {
- pdev = bus->self;
- }
-
- if (!pdev) {
- loc = "N/A";
- goto out;
- }
+ goto out;
- dn = pci_device_to_OF_node(pdev);
- if (!dn) {
- loc = "N/A";
- goto out;
+ /* Check the root port */
+ dn = dn->child;
+ if (!dn)
+ goto out;
}
loc = of_get_property(dn, "ibm,loc-code", NULL);
if (!loc)
loc = of_get_property(dn, "ibm,slot-location-code", NULL);
- if (!loc)
- loc = "N/A";
out:
- if (pci_is_root_bus(bus) && pdev)
- pci_dev_put(pdev);
- return loc;
+ return loc ? loc : "N/A";
}
/**
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 6528c5e2cc44..5bbd1bc8c3b0 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -482,16 +482,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
ld r8,KSP(r4) /* new stack pointer */
#ifdef CONFIG_PPC_BOOK3S
BEGIN_FTR_SECTION
- BEGIN_FTR_SECTION_NESTED(95)
clrrdi r6,r8,28 /* get its ESID */
clrrdi r9,r1,28 /* get current sp ESID */
- FTR_SECTION_ELSE_NESTED(95)
+FTR_SECTION_ELSE
clrrdi r6,r8,40 /* get its 1T ESID */
clrrdi r9,r1,40 /* get current sp 1T ESID */
- ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(MMU_FTR_1T_SEGMENT, 95)
-FTR_SECTION_ELSE
- b 2f
-ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_SLB)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_1T_SEGMENT)
clrldi. r0,r6,2 /* is new ESID c00000000? */
cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */
cror eq,4*cr1+eq,eq
@@ -919,6 +915,11 @@ restore_check_irq_replay:
addi r3,r1,STACK_FRAME_OVERHEAD;
bl do_IRQ
b ret_from_except
+1: cmpwi cr0,r3,0xe60
+ bne 1f
+ addi r3,r1,STACK_FRAME_OVERHEAD;
+ bl handle_hmi_exception
+ b ret_from_except
1: cmpwi cr0,r3,0x900
bne 1f
addi r3,r1,STACK_FRAME_OVERHEAD;
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a7d36b19221d..050f79a4a168 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -188,10 +188,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
data_access_pSeries:
HMT_MEDIUM_PPR_DISCARD
SET_SCRATCH0(r13)
-BEGIN_FTR_SECTION
- b data_access_check_stab
-data_access_not_stab:
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
KVMTEST, 0x300)
@@ -339,7 +335,7 @@ emulation_assist_trampoline:
hv_exception_trampoline:
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXGEN)
- b hmi_exception_hv
+ b hmi_exception_early
. = 0xe80
hv_doorbell_trampoline:
@@ -514,34 +510,6 @@ machine_check_pSeries_0:
EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200)
EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD)
KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
-
- /* moved from 0x300 */
-data_access_check_stab:
- GET_PACA(r13)
- std r9,PACA_EXSLB+EX_R9(r13)
- std r10,PACA_EXSLB+EX_R10(r13)
- mfspr r10,SPRN_DAR
- mfspr r9,SPRN_DSISR
- srdi r10,r10,60
- rlwimi r10,r9,16,0x20
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
- lbz r9,HSTATE_IN_GUEST(r13)
- rlwimi r10,r9,8,0x300
-#endif
- mfcr r9
- cmpwi r10,0x2c
- beq do_stab_bolted_pSeries
- mtcrf 0x80,r9
- ld r9,PACA_EXSLB+EX_R9(r13)
- ld r10,PACA_EXSLB+EX_R10(r13)
- b data_access_not_stab
-do_stab_bolted_pSeries:
- std r11,PACA_EXSLB+EX_R11(r13)
- std r12,PACA_EXSLB+EX_R12(r13)
- GET_SCRATCH0(r10)
- std r10,PACA_EXSLB+EX_R13(r13)
- EXCEPTION_PROLOG_PSERIES_1(do_stab_bolted, EXC_STD)
-
KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400)
@@ -621,8 +589,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22)
STD_EXCEPTION_HV_OOL(0xe42, emulation_assist)
KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42)
- STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */
+ MASKABLE_EXCEPTION_HV_OOL(0xe62, hmi_exception)
KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62)
+
MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell)
KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82)
@@ -643,6 +612,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
* - If it was a decrementer interrupt, we bump the dec to max and and return.
* - If it was a doorbell we return immediately since doorbells are edge
* triggered and won't automatically refire.
+ * - If it was a HMI we return immediately since we handled it in realmode
+ * and it won't refire.
* - else we hard disable and return.
* This is called with r10 containing the value to OR to the paca field.
*/
@@ -660,6 +631,8 @@ masked_##_H##interrupt: \
b 2f; \
1: cmpwi r10,PACA_IRQ_DBELL; \
beq 2f; \
+ cmpwi r10,PACA_IRQ_HMI; \
+ beq 2f; \
mfspr r10,SPRN_##_H##SRR1; \
rldicl r10,r10,48,1; /* clear MSR_EE */ \
rotldi r10,r10,16; \
@@ -799,7 +772,7 @@ kvmppc_skip_Hinterrupt:
STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception)
STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception)
STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt)
- STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception)
+ STD_EXCEPTION_COMMON_ASYNC(0xe60, hmi_exception, handle_hmi_exception)
#ifdef CONFIG_PPC_DOORBELL
STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception)
#else
@@ -985,66 +958,6 @@ ppc64_runlatch_on_trampoline:
b __ppc64_runlatch_on
/*
- * Here we have detected that the kernel stack pointer is bad.
- * R9 contains the saved CR, r13 points to the paca,
- * r10 contains the (bad) kernel stack pointer,
- * r11 and r12 contain the saved SRR0 and SRR1.
- * We switch to using an emergency stack, save the registers there,
- * and call kernel_bad_stack(), which panics.
- */
-bad_stack:
- ld r1,PACAEMERGSP(r13)
- subi r1,r1,64+INT_FRAME_SIZE
- std r9,_CCR(r1)
- std r10,GPR1(r1)
- std r11,_NIP(r1)
- std r12,_MSR(r1)
- mfspr r11,SPRN_DAR
- mfspr r12,SPRN_DSISR
- std r11,_DAR(r1)
- std r12,_DSISR(r1)
- mflr r10
- mfctr r11
- mfxer r12
- std r10,_LINK(r1)
- std r11,_CTR(r1)
- std r12,_XER(r1)
- SAVE_GPR(0,r1)
- SAVE_GPR(2,r1)
- ld r10,EX_R3(r3)
- std r10,GPR3(r1)
- SAVE_GPR(4,r1)
- SAVE_4GPRS(5,r1)
- ld r9,EX_R9(r3)
- ld r10,EX_R10(r3)
- SAVE_2GPRS(9,r1)
- ld r9,EX_R11(r3)
- ld r10,EX_R12(r3)
- ld r11,EX_R13(r3)
- std r9,GPR11(r1)
- std r10,GPR12(r1)
- std r11,GPR13(r1)
-BEGIN_FTR_SECTION
- ld r10,EX_CFAR(r3)
- std r10,ORIG_GPR3(r1)
-END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
- SAVE_8GPRS(14,r1)
- SAVE_10GPRS(22,r1)
- lhz r12,PACA_TRAP_SAVE(r13)
- std r12,_TRAP(r1)
- addi r11,r1,INT_FRAME_SIZE
- std r11,0(r1)
- li r12,0
- std r12,0(r11)
- ld r2,PACATOC(r13)
- ld r11,exception_marker@toc(r2)
- std r12,RESULT(r1)
- std r11,STACK_FRAME_OVERHEAD-16(r1)
-1: addi r3,r1,STACK_FRAME_OVERHEAD
- bl kernel_bad_stack
- b 1b
-
-/*
* Here r13 points to the paca, r9 contains the saved CR,
* SRR0 and SRR1 are saved in r11 and r12,
* r9 - r13 are saved in paca->exgen.
@@ -1057,7 +970,7 @@ data_access_common:
mfspr r10,SPRN_DSISR
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r12,_MSR(r1)
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
@@ -1073,7 +986,7 @@ h_data_storage_common:
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl unknown_exception
b ret_from_except
@@ -1082,7 +995,7 @@ h_data_storage_common:
.globl instruction_access_common
instruction_access_common:
EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r12,_MSR(r1)
ld r3,_NIP(r1)
andis. r4,r12,0x5820
@@ -1146,7 +1059,7 @@ slb_miss_fault:
unrecov_user_slb:
EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
bl save_nvgprs
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
@@ -1169,7 +1082,7 @@ machine_check_common:
stw r10,PACA_EXGEN+EX_DSISR(r13)
EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
FINISH_NAP
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
ld r3,PACA_EXGEN+EX_DAR(r13)
lwz r4,PACA_EXGEN+EX_DSISR(r13)
std r3,_DAR(r1)
@@ -1192,7 +1105,7 @@ alignment_common:
std r3,_DAR(r1)
std r4,_DSISR(r1)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl alignment_exception
b ret_from_except
@@ -1202,7 +1115,7 @@ alignment_common:
program_check_common:
EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl program_check_exception
b ret_from_except
@@ -1213,7 +1126,7 @@ fp_unavailable_common:
EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
bne 1f /* if from user, just load it up */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl kernel_fp_unavailable_exception
BUG_OPCODE
@@ -1232,7 +1145,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl fp_unavailable_tm
b ret_from_except
@@ -1258,7 +1171,7 @@ BEGIN_FTR_SECTION
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl altivec_unavailable_tm
b ret_from_except
@@ -1267,7 +1180,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl altivec_unavailable_exception
b ret_from_except
@@ -1292,7 +1205,7 @@ BEGIN_FTR_SECTION
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
2: /* User process was in a transaction */
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl vsx_unavailable_tm
b ret_from_except
@@ -1301,7 +1214,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
#endif
bl save_nvgprs
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
addi r3,r1,STACK_FRAME_OVERHEAD
bl vsx_unavailable_exception
b ret_from_except
@@ -1338,11 +1251,60 @@ fwnmi_data_area:
. = 0x8000
#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
-/* Space for CPU0's segment table */
- .balign 4096
- .globl initial_stab
-initial_stab:
- .space 4096
+ .globl hmi_exception_early
+hmi_exception_early:
+ EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60)
+ mr r10,r1 /* Save r1 */
+ ld r1,PACAEMERGSP(r13) /* Use emergency stack */
+ subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */
+ std r9,_CCR(r1) /* save CR in stackframe */
+ mfspr r11,SPRN_HSRR0 /* Save HSRR0 */
+ std r11,_NIP(r1) /* save HSRR0 in stackframe */
+ mfspr r12,SPRN_HSRR1 /* Save SRR1 */
+ std r12,_MSR(r1) /* save SRR1 in stackframe */
+ std r10,0(r1) /* make stack chain pointer */
+ std r0,GPR0(r1) /* save r0 in stackframe */
+ std r10,GPR1(r1) /* save r1 in stackframe */
+ EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN)
+ EXCEPTION_PROLOG_COMMON_3(0xe60)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl hmi_exception_realmode
+ /* Windup the stack. */
+ /* Clear MSR_RI before setting SRR0 and SRR1. */
+ li r0,MSR_RI
+ mfmsr r9 /* get MSR value */
+ andc r9,r9,r0
+ mtmsrd r9,1 /* Clear MSR_RI */
+ /* Move original HSRR0 and HSRR1 into the respective regs */
+ ld r9,_MSR(r1)
+ mtspr SPRN_HSRR1,r9
+ ld r3,_NIP(r1)
+ mtspr SPRN_HSRR0,r3
+ ld r9,_CTR(r1)
+ mtctr r9
+ ld r9,_XER(r1)
+ mtxer r9
+ ld r9,_LINK(r1)
+ mtlr r9
+ REST_GPR(0, r1)
+ REST_8GPRS(2, r1)
+ REST_GPR(10, r1)
+ ld r11,_CCR(r1)
+ mtcr r11
+ REST_GPR(11, r1)
+ REST_2GPRS(12, r1)
+ /* restore original r1. */
+ ld r1,GPR1(r1)
+
+ /*
+ * Go to virtual mode and pull the HMI event information from
+ * firmware.
+ */
+ .globl hmi_exception_after_realmode
+hmi_exception_after_realmode:
+ SET_SCRATCH0(r13)
+ EXCEPTION_PROLOG_0(PACA_EXGEN)
+ b hmi_exception_hv
#ifdef CONFIG_PPC_POWERNV
_GLOBAL(opal_mc_secondary_handler)
@@ -1566,7 +1528,7 @@ slb_miss_realmode:
unrecov_slb:
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
- DISABLE_INTS
+ RECONCILE_IRQ_STATE(r10, r11)
bl save_nvgprs
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
@@ -1594,12 +1556,6 @@ do_hash_page:
bne- handle_page_fault /* if not, try to insert a HPTE */
andis. r0,r4,DSISR_DABRMATCH@h
bne- handle_dabr_fault
-
-BEGIN_FTR_SECTION
- andis. r0,r4,0x0020 /* Is it a segment table fault? */
- bne- do_ste_alloc /* If so handle it */
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
-
CURRENT_THREAD_INFO(r11, r1)
lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */
andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */
@@ -1681,113 +1637,62 @@ handle_dabr_fault:
bl bad_page_fault
b ret_from_except
- /* here we have a segment miss */
-do_ste_alloc:
- bl ste_allocate /* try to insert stab entry */
- cmpdi r3,0
- bne- handle_page_fault
- b fast_exception_return
-
/*
- * r13 points to the PACA, r9 contains the saved CR,
+ * Here we have detected that the kernel stack pointer is bad.
+ * R9 contains the saved CR, r13 points to the paca,
+ * r10 contains the (bad) kernel stack pointer,
* r11 and r12 contain the saved SRR0 and SRR1.
- * r9 - r13 are saved in paca->exslb.
- * We assume we aren't going to take any exceptions during this procedure.
- * We assume (DAR >> 60) == 0xc.
+ * We switch to using an emergency stack, save the registers there,
+ * and call kernel_bad_stack(), which panics.
*/
- .align 7
-do_stab_bolted:
- stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
- std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */
- mfspr r11,SPRN_DAR /* ea */
-
- /*
- * check for bad kernel/user address
- * (ea & ~REGION_MASK) >= PGTABLE_RANGE
- */
- rldicr. r9,r11,4,(63 - 46 - 4)
- li r9,0 /* VSID = 0 for bad address */
- bne- 0f
-
- /*
- * Calculate VSID:
- * This is the kernel vsid, we take the top for context from
- * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
- * Here we know that (ea >> 60) == 0xc
- */
- lis r9,(MAX_USER_CONTEXT + 1)@ha
- addi r9,r9,(MAX_USER_CONTEXT + 1)@l
-
- srdi r10,r11,SID_SHIFT
- rldimi r10,r9,ESID_BITS,0 /* proto vsid */
- ASM_VSID_SCRAMBLE(r10, r9, 256M)
- rldic r9,r10,12,16 /* r9 = vsid << 12 */
-
-0:
- /* Hash to the primary group */
- ld r10,PACASTABVIRT(r13)
- srdi r11,r11,SID_SHIFT
- rldimi r10,r11,7,52 /* r10 = first ste of the group */
-
- /* Search the primary group for a free entry */
-1: ld r11,0(r10) /* Test valid bit of the current ste */
- andi. r11,r11,0x80
- beq 2f
- addi r10,r10,16
- andi. r11,r10,0x70
- bne 1b
-
- /* Stick for only searching the primary group for now. */
- /* At least for now, we use a very simple random castout scheme */
- /* Use the TB as a random number ; OR in 1 to avoid entry 0 */
- mftb r11
- rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */
- ori r11,r11,0x10
-
- /* r10 currently points to an ste one past the group of interest */
- /* make it point to the randomly selected entry */
- subi r10,r10,128
- or r10,r10,r11 /* r10 is the entry to invalidate */
-
- isync /* mark the entry invalid */
- ld r11,0(r10)
- rldicl r11,r11,56,1 /* clear the valid bit */
- rotldi r11,r11,8
- std r11,0(r10)
- sync
-
- clrrdi r11,r11,28 /* Get the esid part of the ste */
- slbie r11
-
-2: std r9,8(r10) /* Store the vsid part of the ste */
- eieio
-
- mfspr r11,SPRN_DAR /* Get the new esid */
- clrrdi r11,r11,28 /* Permits a full 32b of ESID */
- ori r11,r11,0x90 /* Turn on valid and kp */
- std r11,0(r10) /* Put new entry back into the stab */
-
- sync
-
- /* All done -- return from exception. */
- lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
- ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */
-
- andi. r10,r12,MSR_RI
- beq- unrecov_slb
-
- mtcrf 0x80,r9 /* restore CR */
-
- mfmsr r10
- clrrdi r10,r10,2
- mtmsrd r10,1
-
- mtspr SPRN_SRR0,r11
- mtspr SPRN_SRR1,r12
- ld r9,PACA_EXSLB+EX_R9(r13)
- ld r10,PACA_EXSLB+EX_R10(r13)
- ld r11,PACA_EXSLB+EX_R11(r13)
- ld r12,PACA_EXSLB+EX_R12(r13)
- ld r13,PACA_EXSLB+EX_R13(r13)
- rfid
- b . /* prevent speculative execution */
+bad_stack:
+ ld r1,PACAEMERGSP(r13)
+ subi r1,r1,64+INT_FRAME_SIZE
+ std r9,_CCR(r1)
+ std r10,GPR1(r1)
+ std r11,_NIP(r1)
+ std r12,_MSR(r1)
+ mfspr r11,SPRN_DAR
+ mfspr r12,SPRN_DSISR
+ std r11,_DAR(r1)
+ std r12,_DSISR(r1)
+ mflr r10
+ mfctr r11
+ mfxer r12
+ std r10,_LINK(r1)
+ std r11,_CTR(r1)
+ std r12,_XER(r1)
+ SAVE_GPR(0,r1)
+ SAVE_GPR(2,r1)
+ ld r10,EX_R3(r3)
+ std r10,GPR3(r1)
+ SAVE_GPR(4,r1)
+ SAVE_4GPRS(5,r1)
+ ld r9,EX_R9(r3)
+ ld r10,EX_R10(r3)
+ SAVE_2GPRS(9,r1)
+ ld r9,EX_R11(r3)
+ ld r10,EX_R12(r3)
+ ld r11,EX_R13(r3)
+ std r9,GPR11(r1)
+ std r10,GPR12(r1)
+ std r11,GPR13(r1)
+BEGIN_FTR_SECTION
+ ld r10,EX_CFAR(r3)
+ std r10,ORIG_GPR3(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
+ SAVE_8GPRS(14,r1)
+ SAVE_10GPRS(22,r1)
+ lhz r12,PACA_TRAP_SAVE(r13)
+ std r12,_TRAP(r1)
+ addi r11,r1,INT_FRAME_SIZE
+ std r11,0(r1)
+ li r12,0
+ std r12,0(r11)
+ ld r2,PACATOC(r13)
+ ld r11,exception_marker@toc(r2)
+ std r12,RESULT(r1)
+ std r11,STACK_FRAME_OVERHEAD-16(r1)
+1: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl kernel_bad_stack
+ b 1b
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index d178834fe508..390311c0f03d 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -525,6 +525,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)&return_to_handler;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index c334f53453f7..b5061abbd2e0 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -1210,10 +1210,12 @@ clear_utlb_entry:
/* We configure icbi to invalidate 128 bytes at a time since the
* current 32-bit kernel code isn't too happy with icache != dcache
- * block size
+ * block size. We also disable the BTAC as this can cause errors
+ * in some circumstances (see IBM Erratum 47).
*/
mfspr r3,SPRN_CCR0
oris r3,r3,0x0020
+ ori r3,r3,0x0040
mtspr SPRN_CCR0,r3
isync
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index a95145d7f61b..d48125d0c048 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -180,6 +180,28 @@ exception_marker:
#include "exceptions-64s.S"
#endif
+#ifdef CONFIG_PPC_BOOK3E
+_GLOBAL(fsl_secondary_thread_init)
+ /* Enable branch prediction */
+ lis r3,BUCSR_INIT@h
+ ori r3,r3,BUCSR_INIT@l
+ mtspr SPRN_BUCSR,r3
+ isync
+
+ /*
+ * Fix PIR to match the linear numbering in the device tree.
+ *
+ * On e6500, the reset value of PIR uses the low three bits for
+ * the thread within a core, and the upper bits for the core
+ * number. There are two threads per core, so shift everything
+ * but the low bit right by two bits so that the cpu numbering is
+ * continuous.
+ */
+ mfspr r3, SPRN_PIR
+ rlwimi r3, r3, 30, 2, 30
+ mtspr SPRN_PIR, r3
+#endif
+
_GLOBAL(generic_secondary_thread_init)
mr r24,r3
@@ -618,7 +640,7 @@ __secondary_start:
addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD
std r14,PACAKSAVE(r13)
- /* Do early setup for that CPU (stab, slb, hash table pointer) */
+ /* Do early setup for that CPU (SLB and hash table pointer) */
bl early_setup_secondary
/*
@@ -771,8 +793,10 @@ start_here_multiplatform:
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
- /* Do very early kernel initializations, including initial hash table,
- * stab and slb setup before we turn on relocation. */
+ /*
+ * Do very early kernel initializations, including initial hash table
+ * and SLB setup before we turn on relocation.
+ */
/* Restore parameters passed from prom_init/kexec */
mr r3,r31
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 5cf3d367190d..be05841396cf 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -135,17 +135,68 @@ _GLOBAL(power7_sleep)
b power7_powersave_common
/* No return */
+/*
+ * Make opal call in realmode. This is a generic function to be called
+ * from realmode from reset vector. It handles endianess.
+ *
+ * r13 - paca pointer
+ * r1 - stack pointer
+ * r3 - opal token
+ */
+opal_call_realmode:
+ mflr r12
+ std r12,_LINK(r1)
+ ld r2,PACATOC(r13)
+ /* Set opal return address */
+ LOAD_REG_ADDR(r0,return_from_opal_call)
+ mtlr r0
+ /* Handle endian-ness */
+ li r0,MSR_LE
+ mfmsr r12
+ andc r12,r12,r0
+ mtspr SPRN_HSRR1,r12
+ mr r0,r3 /* Move opal token to r0 */
+ LOAD_REG_ADDR(r11,opal)
+ ld r12,8(r11)
+ ld r2,0(r11)
+ mtspr SPRN_HSRR0,r12
+ hrfid
+
+return_from_opal_call:
+ FIXUP_ENDIAN
+ ld r0,_LINK(r1)
+ mtlr r0
+ blr
+
+#define CHECK_HMI_INTERRUPT \
+ mfspr r0,SPRN_SRR1; \
+BEGIN_FTR_SECTION_NESTED(66); \
+ rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \
+FTR_SECTION_ELSE_NESTED(66); \
+ rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \
+ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
+ cmpwi r0,0xa; /* Hypervisor maintenance ? */ \
+ bne 20f; \
+ /* Invoke opal call to handle hmi */ \
+ ld r2,PACATOC(r13); \
+ ld r1,PACAR1(r13); \
+ std r3,ORIG_GPR3(r1); /* Save original r3 */ \
+ li r3,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \
+ bl opal_call_realmode; \
+ ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \
+20: nop;
+
+
_GLOBAL(power7_wakeup_tb_loss)
ld r2,PACATOC(r13);
ld r1,PACAR1(r13)
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
/* Time base re-sync */
- li r0,OPAL_RESYNC_TIMEBASE
- LOAD_REG_ADDR(r11,opal);
- ld r12,8(r11);
- ld r2,0(r11);
- mtctr r12
- bctrl
+ li r3,OPAL_RESYNC_TIMEBASE
+ bl opal_call_realmode;
/* TODO: Check r3 for failure */
@@ -163,6 +214,9 @@ _GLOBAL(power7_wakeup_tb_loss)
_GLOBAL(power7_wakeup_loss)
ld r1,PACAR1(r13)
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
REST_NVGPRS(r1)
REST_GPR(2, r1)
ld r3,_CCR(r1)
@@ -178,6 +232,9 @@ _GLOBAL(power7_wakeup_noloss)
lbz r0,PACA_NAPSTATELOST(r13)
cmpwi r0,0
bne power7_wakeup_loss
+BEGIN_FTR_SECTION
+ CHECK_HMI_INTERRUPT
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
ld r1,PACAR1(r13)
ld r4,_MSR(r1)
ld r5,_NIP(r1)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 88e3ec6e1d96..a10642a0d861 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *tbl, unsigned long entry,
/* if (unlikely(ret))
pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n",
- __func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl),
+ __func__, hwaddr, entry << tbl->it_page_shift,
hwaddr, ret); */
return ret;
@@ -1056,7 +1056,7 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry,
direction != DMA_TO_DEVICE, &page);
if (unlikely(ret != 1)) {
/* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n",
- tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */
+ tce, entry << tbl->it_page_shift, ret); */
return -EFAULT;
}
hwaddr = (unsigned long) page_address(page) + offset;
@@ -1120,37 +1120,41 @@ EXPORT_SYMBOL_GPL(iommu_release_ownership);
int iommu_add_device(struct device *dev)
{
struct iommu_table *tbl;
- int ret = 0;
- if (WARN_ON(dev->iommu_group)) {
- pr_warn("iommu_tce: device %s is already in iommu group %d, skipping\n",
- dev_name(dev),
- iommu_group_id(dev->iommu_group));
+ /*
+ * The sysfs entries should be populated before
+ * binding IOMMU group. If sysfs entries isn't
+ * ready, we simply bail.
+ */
+ if (!device_is_registered(dev))
+ return -ENOENT;
+
+ if (dev->iommu_group) {
+ pr_debug("%s: Skipping device %s with iommu group %d\n",
+ __func__, dev_name(dev),
+ iommu_group_id(dev->iommu_group));
return -EBUSY;
}
tbl = get_iommu_table_base(dev);
if (!tbl || !tbl->it_group) {
- pr_debug("iommu_tce: skipping device %s with no tbl\n",
- dev_name(dev));
+ pr_debug("%s: Skipping device %s with no tbl\n",
+ __func__, dev_name(dev));
return 0;
}
- pr_debug("iommu_tce: adding %s to iommu group %d\n",
- dev_name(dev), iommu_group_id(tbl->it_group));
+ pr_debug("%s: Adding %s to iommu group %d\n",
+ __func__, dev_name(dev),
+ iommu_group_id(tbl->it_group));
if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
- pr_err("iommu_tce: unsupported iommu page size.");
- pr_err("%s has not been added\n", dev_name(dev));
+ pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n",
+ __func__, IOMMU_PAGE_SIZE(tbl),
+ PAGE_SIZE, dev_name(dev));
return -EINVAL;
}
- ret = iommu_group_add_device(tbl->it_group, dev);
- if (ret < 0)
- pr_err("iommu_tce: %s has not been added, ret=%d\n",
- dev_name(dev), ret);
-
- return ret;
+ return iommu_group_add_device(tbl->it_group, dev);
}
EXPORT_SYMBOL_GPL(iommu_add_device);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 248ee7e5bebd..4c5891de162e 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -189,6 +189,11 @@ notrace unsigned int __check_irq_replay(void)
}
#endif /* CONFIG_PPC_BOOK3E */
+ /* Check if an hypervisor Maintenance interrupt happened */
+ local_paca->irq_happened &= ~PACA_IRQ_HMI;
+ if (happened & PACA_IRQ_HMI)
+ return 0xe60;
+
/* There should be nothing left ! */
BUG_ON(local_paca->irq_happened != 0);
@@ -377,6 +382,14 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions);
seq_printf(p, " Machine check exceptions\n");
+ if (cpu_has_feature(CPU_FTR_HVMODE)) {
+ seq_printf(p, "%*s: ", prec, "HMI");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat, j).hmi_exceptions);
+ seq_printf(p, " Hypervisor Maintenance Interrupts\n");
+ }
+
#ifdef CONFIG_PPC_DOORBELL
if (cpu_has_feature(CPU_FTR_DBELL)) {
seq_printf(p, "%*s: ", prec, "DBL");
@@ -400,6 +413,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += per_cpu(irq_stat, cpu).mce_exceptions;
sum += per_cpu(irq_stat, cpu).spurious_irqs;
sum += per_cpu(irq_stat, cpu).timer_irqs_others;
+ sum += per_cpu(irq_stat, cpu).hmi_exceptions;
#ifdef CONFIG_PPC_DOORBELL
sum += per_cpu(irq_stat, cpu).doorbell_irqs;
#endif
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index b49c72fd7f16..b2814e23e1ed 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -123,21 +123,12 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus,
void pcibios_reset_secondary_bus(struct pci_dev *dev)
{
- u16 ctrl;
-
if (ppc_md.pcibios_reset_secondary_bus) {
ppc_md.pcibios_reset_secondary_bus(dev);
return;
}
- pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl);
- ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
- pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
- msleep(2);
-
- ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
- pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
- ssleep(1);
+ pci_reset_secondary_bus(dev);
}
static resource_size_t pcibios_io_size(const struct pci_controller *hose)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index be99774d3f44..bf44ae962ab8 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1095,6 +1095,23 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
return 0;
}
+static void setup_ksp_vsid(struct task_struct *p, unsigned long sp)
+{
+#ifdef CONFIG_PPC_STD_MMU_64
+ unsigned long sp_vsid;
+ unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
+
+ if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
+ sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
+ << SLB_VSID_SHIFT_1T;
+ else
+ sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M)
+ << SLB_VSID_SHIFT;
+ sp_vsid |= SLB_VSID_KERNEL | llp;
+ p->thread.ksp_vsid = sp_vsid;
+#endif
+}
+
/*
* Copy a thread..
*/
@@ -1174,21 +1191,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->thread.vr_save_area = NULL;
#endif
-#ifdef CONFIG_PPC_STD_MMU_64
- if (mmu_has_feature(MMU_FTR_SLB)) {
- unsigned long sp_vsid;
- unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
+ setup_ksp_vsid(p, sp);
- if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
- sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
- << SLB_VSID_SHIFT_1T;
- else
- sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M)
- << SLB_VSID_SHIFT;
- sp_vsid |= SLB_VSID_KERNEL | llp;
- p->thread.ksp_vsid = sp_vsid;
- }
-#endif /* CONFIG_PPC_STD_MMU_64 */
#ifdef CONFIG_PPC64
if (cpu_has_feature(CPU_FTR_DSCR)) {
p->thread.dscr_inherit = current->thread.dscr_inherit;
@@ -1577,7 +1581,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
struct pt_regs *regs = (struct pt_regs *)
(sp + STACK_FRAME_OVERHEAD);
lr = regs->link;
- printk("--- Exception: %lx at %pS\n LR = %pS\n",
+ printk("--- interrupt: %lx at %pS\n LR = %pS\n",
regs->trap, (void *)regs->nip, (void *)lr);
firstframe = 1;
}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index b694b0730971..4e139f8a69ef 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -155,7 +155,6 @@ static struct ibm_pa_feature {
} ibm_pa_features[] __initdata = {
{0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0},
{0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0},
- {0, MMU_FTR_SLB, 0, 0, 2, 0},
{CPU_FTR_CTRL, 0, 0, 0, 3, 0},
{CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0},
{CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1},
@@ -309,12 +308,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
/* Get physical cpuid */
intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
- if (intserv) {
- nthreads = len / sizeof(int);
- } else {
- intserv = of_get_flat_dt_prop(node, "reg", NULL);
- nthreads = 1;
- }
+ if (!intserv)
+ intserv = of_get_flat_dt_prop(node, "reg", &len);
+
+ nthreads = len / sizeof(int);
/*
* Now see if any of these threads match our boot cpu.
@@ -821,76 +818,6 @@ int cpu_to_chip_id(int cpu)
}
EXPORT_SYMBOL(cpu_to_chip_id);
-#ifdef CONFIG_PPC_PSERIES
-/*
- * Fix up the uninitialized fields in a new device node:
- * name, type and pci-specific fields
- */
-
-static int of_finish_dynamic_node(struct device_node *node)
-{
- struct device_node *parent = of_get_parent(node);
- int err = 0;
- const phandle *ibm_phandle;
-
- node->name = of_get_property(node, "name", NULL);
- node->type = of_get_property(node, "device_type", NULL);
-
- if (!node->name)
- node->name = "<NULL>";
- if (!node->type)
- node->type = "<NULL>";
-
- if (!parent) {
- err = -ENODEV;
- goto out;
- }
-
- /* We don't support that function on PowerMac, at least
- * not yet
- */
- if (machine_is(powermac))
- return -ENODEV;
-
- /* fix up new node's phandle field */
- if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
- node->phandle = *ibm_phandle;
-
-out:
- of_node_put(parent);
- return err;
-}
-
-static int prom_reconfig_notifier(struct notifier_block *nb,
- unsigned long action, void *node)
-{
- int err;
-
- switch (action) {
- case OF_RECONFIG_ATTACH_NODE:
- err = of_finish_dynamic_node(node);
- if (err < 0)
- printk(KERN_ERR "finish_node returned %d\n", err);
- break;
- default:
- err = 0;
- break;
- }
- return notifier_from_errno(err);
-}
-
-static struct notifier_block prom_reconfig_nb = {
- .notifier_call = prom_reconfig_notifier,
- .priority = 10, /* This one needs to run first */
-};
-
-static int __init prom_reconfig_setup(void)
-{
- return of_reconfig_notifier_register(&prom_reconfig_nb);
-}
-__initcall(prom_reconfig_setup);
-#endif
-
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
{
return (int)phys_id == get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index e5b022c55ccd..1b0e26013a62 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -456,18 +456,20 @@ void __init smp_setup_cpu_maps(void)
intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
&len);
if (intserv) {
- nthreads = len / sizeof(int);
DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
nthreads);
} else {
DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
- intserv = of_get_property(dn, "reg", NULL);
+ intserv = of_get_property(dn, "reg", &len);
if (!intserv) {
cpu_be = cpu_to_be32(cpu);
intserv = &cpu_be; /* assume logical == phys */
+ len = 4;
}
}
+ nthreads = len / sizeof(int);
+
for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
bool avail;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index ee082d771178..75d62d63fe68 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -149,13 +149,13 @@ static void check_smt_enabled(void)
else if (!strcmp(smt_enabled_cmdline, "off"))
smt_enabled_at_boot = 0;
else {
- long smt;
+ int smt;
int rc;
- rc = strict_strtol(smt_enabled_cmdline, 10, &smt);
+ rc = kstrtoint(smt_enabled_cmdline, 10, &smt);
if (!rc)
smt_enabled_at_boot =
- min(threads_per_core, (int)smt);
+ min(threads_per_core, smt);
}
} else {
dn = of_find_node_by_path("/options");
@@ -201,7 +201,11 @@ static void cpu_ready_for_interrupts(void)
/* Set IR and DR in PACA MSR */
get_paca()->kernel_msr = MSR_KERNEL;
- /* Enable AIL if supported */
+ /*
+ * Enable AIL if supported, and we are in hypervisor mode. If we are
+ * not in hypervisor mode, we enable relocation-on interrupts later
+ * in pSeries_setup_arch() using the H_SET_MODE hcall.
+ */
if (cpu_has_feature(CPU_FTR_HVMODE) &&
cpu_has_feature(CPU_FTR_ARCH_207S)) {
unsigned long lpcr = mfspr(SPRN_LPCR);
@@ -507,7 +511,11 @@ void __init setup_system(void)
check_smt_enabled();
setup_tlb_core_data();
-#ifdef CONFIG_SMP
+ /*
+ * Freescale Book3e parts spin in a loop provided by firmware,
+ * so smp_release_cpus() does nothing for them
+ */
+#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_FSL_BOOK3E)
/* Release secondary cpus out of their spinloops at 0x60 now that
* we can map physical -> logical CPU ids
*/
@@ -673,9 +681,6 @@ void __init setup_arch(char **cmdline_p)
exc_lvl_early_init();
emergency_stack_init();
-#ifdef CONFIG_PPC_STD_MMU_64
- stabs_alloc();
-#endif
/* set up the bootmem stuff with available memory */
do_init_bootmem();
sparse_init();
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 1c794cef2883..cf8c7e4e0b21 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -31,20 +31,14 @@ int show_unhandled_signals = 1;
/*
* Allocate space for the signal frame
*/
-void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
+void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
size_t frame_size, int is_32)
{
unsigned long oldsp, newsp;
/* Default to using normal stack */
oldsp = get_clean_sp(sp, is_32);
-
- /* Check for alt stack */
- if ((ka->sa.sa_flags & SA_ONSTACK) &&
- current->sas_ss_size && !on_sig_stack(oldsp))
- oldsp = (current->sas_ss_sp + current->sas_ss_size);
-
- /* Get aligned frame */
+ oldsp = sigsp(oldsp, ksig);
newsp = (oldsp - frame_size) & ~0xFUL;
/* Check access */
@@ -105,25 +99,23 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
}
}
-static int do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
int ret;
int is32 = is_32bit_task();
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ get_signal(&ksig);
/* Is there any syscall restart business here ? */
- check_syscall_restart(regs, &ka, signr > 0);
+ check_syscall_restart(regs, &ksig.ka, ksig.sig > 0);
- if (signr <= 0) {
+ if (ksig.sig <= 0) {
/* No signal to deliver -- put the saved sigmask back */
restore_saved_sigmask();
regs->trap = 0;
- return 0; /* no signals delivered */
+ return; /* no signals delivered */
}
#ifndef CONFIG_PPC_ADV_DEBUG_REGS
@@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *regs)
thread_change_pc(current, regs);
if (is32) {
- if (ka.sa.sa_flags & SA_SIGINFO)
- ret = handle_rt_signal32(signr, &ka, &info, oldset,
- regs);
+ if (ksig.ka.sa.sa_flags & SA_SIGINFO)
+ ret = handle_rt_signal32(&ksig, oldset, regs);
else
- ret = handle_signal32(signr, &ka, &info, oldset,
- regs);
+ ret = handle_signal32(&ksig, oldset, regs);
} else {
- ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+ ret = handle_rt_signal64(&ksig, oldset, regs);
}
regs->trap = 0;
- if (ret) {
- signal_delivered(signr, &info, &ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
- }
-
- return ret;
+ signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
}
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index c69b9aeb9f23..51b274199dd9 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -12,15 +12,13 @@
extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
-extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
+extern void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
size_t frame_size, int is_32);
-extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
+extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
struct pt_regs *regs);
-extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
+extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
struct pt_regs *regs);
extern unsigned long copy_fpr_to_user(void __user *to,
@@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_from_user(struct task_struct *task,
#ifdef CONFIG_PPC64
-extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *set,
+extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);
#else /* CONFIG_PPC64 */
-static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *set,
+static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
return -EFAULT;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 1bc5a1755ed4..b171001698ff 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
* Set up a signal frame for a "real-time" signal handler
* (one which gets siginfo).
*/
-int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
- struct pt_regs *regs)
+int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *rt_sf;
struct mcontext __user *frame;
@@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Set up Signal Frame */
/* Put a Real Time Context onto stack */
- rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
+ rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
addr = rt_sf;
if (unlikely(rt_sf == NULL))
goto badframe;
/* Put the siginfo & fill in most of the ucontext */
- if (copy_siginfo_to_user(&rt_sf->info, info)
+ if (copy_siginfo_to_user(&rt_sf->info, &ksig->info)
|| __put_user(0, &rt_sf->uc.uc_flags)
|| __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])
|| __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
@@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Fill registers for signal handler */
regs->gpr[1] = newsp;
- regs->gpr[3] = sig;
+ regs->gpr[3] = ksig->sig;
regs->gpr[4] = (unsigned long) &rt_sf->info;
regs->gpr[5] = (unsigned long) &rt_sf->uc;
regs->gpr[6] = (unsigned long) rt_sf;
- regs->nip = (unsigned long) ka->sa.sa_handler;
+ regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
/* enter the signal handler in native-endian mode */
regs->msr &= ~MSR_LE;
regs->msr |= (MSR_KERNEL & MSR_LE);
- return 1;
+ return 0;
badframe:
if (show_unhandled_signals)
@@ -1069,8 +1068,7 @@ badframe:
current->comm, current->pid,
addr, regs->nip, regs->link);
- force_sigsegv(sig, current);
- return 0;
+ return 1;
}
static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
@@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
/*
* OK, we're invoking a handler
*/
-int handle_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs)
{
struct sigcontext __user *sc;
struct sigframe __user *frame;
@@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
unsigned long tramp;
/* Set up Signal Frame */
- frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
+ frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1);
if (unlikely(frame == NULL))
goto badframe;
sc = (struct sigcontext __user *) &frame->sctx;
@@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
#if _NSIG != 64
#error "Please adjust handle_signal()"
#endif
- if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler)
+ if (__put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler)
|| __put_user(oldset->sig[0], &sc->oldmask)
#ifdef CONFIG_PPC64
|| __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
@@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|| __put_user(oldset->sig[1], &sc->_unused[3])
#endif
|| __put_user(to_user_ptr(&frame->mctx), &sc->regs)
- || __put_user(sig, &sc->signal))
+ || __put_user(ksig->sig, &sc->signal))
goto badframe;
if (vdso32_sigtramp && current->mm->context.vdso_base) {
@@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
goto badframe;
regs->gpr[1] = newsp;
- regs->gpr[3] = sig;
+ regs->gpr[3] = ksig->sig;
regs->gpr[4] = (unsigned long) sc;
- regs->nip = (unsigned long) ka->sa.sa_handler;
+ regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;
/* enter the signal handler in big-endian mode */
regs->msr &= ~MSR_LE;
- return 1;
+ return 0;
badframe:
if (show_unhandled_signals)
@@ -1486,8 +1483,7 @@ badframe:
current->comm, current->pid,
frame, regs->nip, regs->link);
- force_sigsegv(sig, current);
- return 0;
+ return 1;
}
/*
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 97c1e4b683fc..2cb0c94cafa5 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -708,20 +708,19 @@ badframe:
return 0;
}
-int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
unsigned long newsp = 0;
long err = 0;
- frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
+ frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0);
if (unlikely(frame == NULL))
goto badframe;
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err)
goto badframe;
@@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
&frame->uc_transact.uc_mcontext,
- regs, signr,
+ regs, ksig->sig,
NULL,
- (unsigned long)ka->sa.sa_handler);
+ (unsigned long)ksig->ka.sa.sa_handler);
} else
#endif
{
err |= __put_user(0, &frame->uc.uc_link);
- err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr,
- NULL, (unsigned long)ka->sa.sa_handler,
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig,
+ NULL, (unsigned long)ksig->ka.sa.sa_handler,
1);
}
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
@@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Set up "regs" so we "return" to the signal handler. */
if (is_elf2_task()) {
- regs->nip = (unsigned long) ka->sa.sa_handler;
+ regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
regs->gpr[12] = regs->nip;
} else {
/* Handler is *really* a pointer to the function descriptor for
@@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
* entry is the TOC value we need to use.
*/
func_descr_t __user *funct_desc_ptr =
- (func_descr_t __user *) ka->sa.sa_handler;
+ (func_descr_t __user *) ksig->ka.sa.sa_handler;
err |= get_user(regs->nip, &funct_desc_ptr->entry);
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
@@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
regs->msr &= ~MSR_LE;
regs->msr |= (MSR_KERNEL & MSR_LE);
regs->gpr[1] = newsp;
- regs->gpr[3] = signr;
+ regs->gpr[3] = ksig->sig;
regs->result = 0;
- if (ka->sa.sa_flags & SA_SIGINFO) {
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo);
err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc);
regs->gpr[6] = (unsigned long) frame;
@@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
if (err)
goto badframe;
- return 1;
+ return 0;
badframe:
if (show_unhandled_signals)
@@ -809,6 +808,5 @@ badframe:
current->comm, current->pid, "setup_rt_frame",
(long)frame, regs->nip, regs->link);
- force_sigsegv(signr, current);
- return 0;
+ return 1;
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 1007fb802e6b..a0738af4aba6 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -376,6 +376,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
GFP_KERNEL, cpu_to_node(cpu));
zalloc_cpumask_var_node(&per_cpu(cpu_core_map, cpu),
GFP_KERNEL, cpu_to_node(cpu));
+ /*
+ * numa_node_id() works after this.
+ */
+ set_cpu_numa_node(cpu, numa_cpu_lookup_table[cpu]);
+ set_cpu_numa_mem(cpu, local_memory_node(numa_cpu_lookup_table[cpu]));
}
cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid));
@@ -723,12 +728,6 @@ void start_secondary(void *unused)
}
traverse_core_siblings(cpu, true);
- /*
- * numa_node_id() works after this.
- */
- set_numa_node(numa_cpu_lookup_table[cpu]);
- set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
-
smp_wmb();
notify_cpu_starting(cpu);
set_cpu_online(cpu, true);
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 895c50ca943c..7ab5d434e2ee 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -39,9 +39,6 @@
.section .rodata,"a"
#ifdef CONFIG_PPC64
-#define sys_sigpending sys_ni_syscall
-#define sys_old_getrlimit sys_ni_syscall
-
.p2align 3
#endif
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 9fff9cdcc519..368ab374d33c 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -741,7 +741,7 @@ static cycle_t timebase_read(struct clocksource *cs)
}
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
- struct clocksource *clock, u32 mult)
+ struct clocksource *clock, u32 mult, cycle_t cycle_last)
{
u64 new_tb_to_xs, new_stamp_xsec;
u32 frac_sec;
@@ -774,7 +774,7 @@ void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
* We expect the caller to have done the first increment of
* vdso_data->tb_update_count already.
*/
- vdso_data->tb_orig_stamp = clock->cycle_last;
+ vdso_data->tb_orig_stamp = cycle_last;
vdso_data->stamp_xsec = new_stamp_xsec;
vdso_data->tb_to_xs = new_tb_to_xs;
vdso_data->wtom_clock_sec = wtm->tv_sec;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 239f1cde3fff..0dc43f9932cf 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -302,6 +302,16 @@ long machine_check_early(struct pt_regs *regs)
return handled;
}
+long hmi_exception_realmode(struct pt_regs *regs)
+{
+ __get_cpu_var(irq_stat).hmi_exceptions++;
+
+ if (ppc_md.hmi_exception_early)
+ ppc_md.hmi_exception_early(regs);
+
+ return 0;
+}
+
#endif
/*
@@ -609,7 +619,7 @@ int machine_check_e500(struct pt_regs *regs)
if (reason & MCSR_BUS_RBERR)
printk("Bus - Read Data Bus Error\n");
if (reason & MCSR_BUS_WBERR)
- printk("Bus - Read Data Bus Error\n");
+ printk("Bus - Write Data Bus Error\n");
if (reason & MCSR_BUS_IPERR)
printk("Bus - Instruction Parity Error\n");
if (reason & MCSR_BUS_RPERR)
@@ -738,6 +748,20 @@ void SMIException(struct pt_regs *regs)
die("System Management Interrupt", regs, SIGABRT);
}
+void handle_hmi_exception(struct pt_regs *regs)
+{
+ struct pt_regs *old_regs;
+
+ old_regs = set_irq_regs(regs);
+ irq_enter();
+
+ if (ppc_md.handle_hmi_exception)
+ ppc_md.handle_hmi_exception(regs);
+
+ irq_exit();
+ set_irq_regs(old_regs);
+}
+
void unknown_exception(struct pt_regs *regs)
{
enum ctx_state prev_state = exception_enter();
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ce74c335a6a4..f174351842cf 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -840,19 +840,3 @@ static int __init vdso_init(void)
return 0;
}
arch_initcall(vdso_init);
-
-int in_gate_area_no_mm(unsigned long addr)
-{
- return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
- return 0;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
-
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 904c66128fae..5bfdab9047be 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -977,7 +977,7 @@ static ssize_t viodev_cmo_desired_set(struct device *dev,
size_t new_desired;
int ret;
- ret = strict_strtoul(buf, 10, &new_desired);
+ ret = kstrtoul(buf, 10, &new_desired);
if (ret)
return ret;
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
deleted file mode 100644
index 9cb4b0a36031..000000000000
--- a/arch/powerpc/kvm/44x.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <linux/kvm_host.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-
-#include <asm/reg.h>
-#include <asm/cputable.h>
-#include <asm/tlbflush.h>
-#include <asm/kvm_44x.h>
-#include <asm/kvm_ppc.h>
-
-#include "44x_tlb.h"
-#include "booke.h"
-
-static void kvmppc_core_vcpu_load_44x(struct kvm_vcpu *vcpu, int cpu)
-{
- kvmppc_booke_vcpu_load(vcpu, cpu);
- kvmppc_44x_tlb_load(vcpu);
-}
-
-static void kvmppc_core_vcpu_put_44x(struct kvm_vcpu *vcpu)
-{
- kvmppc_44x_tlb_put(vcpu);
- kvmppc_booke_vcpu_put(vcpu);
-}
-
-int kvmppc_core_check_processor_compat(void)
-{
- int r;
-
- if (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 0)
- r = 0;
- else
- r = -ENOTSUPP;
-
- return r;
-}
-
-int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0];
- int i;
-
- tlbe->tid = 0;
- tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
- tlbe->word1 = 0;
- tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
-
- tlbe++;
- tlbe->tid = 0;
- tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
- tlbe->word1 = 0xef600000;
- tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
- | PPC44x_TLB_I | PPC44x_TLB_G;
-
- /* Since the guest can directly access the timebase, it must know the
- * real timebase frequency. Accordingly, it must see the state of
- * CCR1[TCS]. */
- /* XXX CCR1 doesn't exist on all 440 SoCs. */
- vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
-
- for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
- vcpu_44x->shadow_refs[i].gtlb_index = -1;
-
- vcpu->arch.cpu_type = KVM_CPU_440;
- vcpu->arch.pvr = mfspr(SPRN_PVR);
-
- return 0;
-}
-
-/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
-int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
- struct kvm_translation *tr)
-{
- int index;
- gva_t eaddr;
- u8 pid;
- u8 as;
-
- eaddr = tr->linear_address;
- pid = (tr->linear_address >> 32) & 0xff;
- as = (tr->linear_address >> 40) & 0x1;
-
- index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
- if (index == -1) {
- tr->valid = 0;
- return 0;
- }
-
- tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr);
- /* XXX what does "writeable" and "usermode" even mean? */
- tr->valid = 1;
-
- return 0;
-}
-
-static int kvmppc_core_get_sregs_44x(struct kvm_vcpu *vcpu,
- struct kvm_sregs *sregs)
-{
- return kvmppc_get_sregs_ivor(vcpu, sregs);
-}
-
-static int kvmppc_core_set_sregs_44x(struct kvm_vcpu *vcpu,
- struct kvm_sregs *sregs)
-{
- return kvmppc_set_sregs_ivor(vcpu, sregs);
-}
-
-static int kvmppc_get_one_reg_44x(struct kvm_vcpu *vcpu, u64 id,
- union kvmppc_one_reg *val)
-{
- return -EINVAL;
-}
-
-static int kvmppc_set_one_reg_44x(struct kvm_vcpu *vcpu, u64 id,
- union kvmppc_one_reg *val)
-{
- return -EINVAL;
-}
-
-static struct kvm_vcpu *kvmppc_core_vcpu_create_44x(struct kvm *kvm,
- unsigned int id)
-{
- struct kvmppc_vcpu_44x *vcpu_44x;
- struct kvm_vcpu *vcpu;
- int err;
-
- vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
- if (!vcpu_44x) {
- err = -ENOMEM;
- goto out;
- }
-
- vcpu = &vcpu_44x->vcpu;
- err = kvm_vcpu_init(vcpu, kvm, id);
- if (err)
- goto free_vcpu;
-
- vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
- if (!vcpu->arch.shared)
- goto uninit_vcpu;
-
- return vcpu;
-
-uninit_vcpu:
- kvm_vcpu_uninit(vcpu);
-free_vcpu:
- kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
-out:
- return ERR_PTR(err);
-}
-
-static void kvmppc_core_vcpu_free_44x(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
-
- free_page((unsigned long)vcpu->arch.shared);
- kvm_vcpu_uninit(vcpu);
- kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
-}
-
-static int kvmppc_core_init_vm_44x(struct kvm *kvm)
-{
- return 0;
-}
-
-static void kvmppc_core_destroy_vm_44x(struct kvm *kvm)
-{
-}
-
-static struct kvmppc_ops kvm_ops_44x = {
- .get_sregs = kvmppc_core_get_sregs_44x,
- .set_sregs = kvmppc_core_set_sregs_44x,
- .get_one_reg = kvmppc_get_one_reg_44x,
- .set_one_reg = kvmppc_set_one_reg_44x,
- .vcpu_load = kvmppc_core_vcpu_load_44x,
- .vcpu_put = kvmppc_core_vcpu_put_44x,
- .vcpu_create = kvmppc_core_vcpu_create_44x,
- .vcpu_free = kvmppc_core_vcpu_free_44x,
- .mmu_destroy = kvmppc_mmu_destroy_44x,
- .init_vm = kvmppc_core_init_vm_44x,
- .destroy_vm = kvmppc_core_destroy_vm_44x,
- .emulate_op = kvmppc_core_emulate_op_44x,
- .emulate_mtspr = kvmppc_core_emulate_mtspr_44x,
- .emulate_mfspr = kvmppc_core_emulate_mfspr_44x,
-};
-
-static int __init kvmppc_44x_init(void)
-{
- int r;
-
- r = kvmppc_booke_init();
- if (r)
- goto err_out;
-
- r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE);
- if (r)
- goto err_out;
- kvm_ops_44x.owner = THIS_MODULE;
- kvmppc_pr_ops = &kvm_ops_44x;
-
-err_out:
- return r;
-}
-
-static void __exit kvmppc_44x_exit(void)
-{
- kvmppc_pr_ops = NULL;
- kvmppc_booke_exit();
-}
-
-module_init(kvmppc_44x_init);
-module_exit(kvmppc_44x_exit);
-MODULE_ALIAS_MISCDEV(KVM_MINOR);
-MODULE_ALIAS("devname:kvm");
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
deleted file mode 100644
index 92c9ab4bcfec..000000000000
--- a/arch/powerpc/kvm/44x_emulate.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <asm/kvm_ppc.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
-#include <asm/disassemble.h>
-#include <asm/kvm_44x.h>
-#include "timing.h"
-
-#include "booke.h"
-#include "44x_tlb.h"
-
-#define XOP_MFDCRX 259
-#define XOP_MFDCR 323
-#define XOP_MTDCRX 387
-#define XOP_MTDCR 451
-#define XOP_TLBSX 914
-#define XOP_ICCCI 966
-#define XOP_TLBWE 978
-
-static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
-{
- /* emulate some access in kernel */
- switch (dcrn) {
- case DCRN_CPR0_CONFIG_ADDR:
- vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
- return EMULATE_DONE;
- default:
- vcpu->run->dcr.dcrn = dcrn;
- vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
- vcpu->run->dcr.is_write = 1;
- vcpu->arch.dcr_is_write = 1;
- vcpu->arch.dcr_needed = 1;
- kvmppc_account_exit(vcpu, DCR_EXITS);
- return EMULATE_DO_DCR;
- }
-}
-
-static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
-{
- /* The guest may access CPR0 registers to determine the timebase
- * frequency, and it must know the real host frequency because it
- * can directly access the timebase registers.
- *
- * It would be possible to emulate those accesses in userspace,
- * but userspace can really only figure out the end frequency.
- * We could decompose that into the factors that compute it, but
- * that's tricky math, and it's easier to just report the real
- * CPR0 values.
- */
- switch (dcrn) {
- case DCRN_CPR0_CONFIG_ADDR:
- kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
- break;
- case DCRN_CPR0_CONFIG_DATA:
- local_irq_disable();
- mtdcr(DCRN_CPR0_CONFIG_ADDR,
- vcpu->arch.cpr0_cfgaddr);
- kvmppc_set_gpr(vcpu, rt,
- mfdcr(DCRN_CPR0_CONFIG_DATA));
- local_irq_enable();
- break;
- default:
- vcpu->run->dcr.dcrn = dcrn;
- vcpu->run->dcr.data = 0;
- vcpu->run->dcr.is_write = 0;
- vcpu->arch.dcr_is_write = 0;
- vcpu->arch.io_gpr = rt;
- vcpu->arch.dcr_needed = 1;
- kvmppc_account_exit(vcpu, DCR_EXITS);
- return EMULATE_DO_DCR;
- }
-
- return EMULATE_DONE;
-}
-
-int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu,
- unsigned int inst, int *advance)
-{
- int emulated = EMULATE_DONE;
- int dcrn = get_dcrn(inst);
- int ra = get_ra(inst);
- int rb = get_rb(inst);
- int rc = get_rc(inst);
- int rs = get_rs(inst);
- int rt = get_rt(inst);
- int ws = get_ws(inst);
-
- switch (get_op(inst)) {
- case 31:
- switch (get_xop(inst)) {
-
- case XOP_MFDCR:
- emulated = emulate_mfdcr(vcpu, rt, dcrn);
- break;
-
- case XOP_MFDCRX:
- emulated = emulate_mfdcr(vcpu, rt,
- kvmppc_get_gpr(vcpu, ra));
- break;
-
- case XOP_MTDCR:
- emulated = emulate_mtdcr(vcpu, rs, dcrn);
- break;
-
- case XOP_MTDCRX:
- emulated = emulate_mtdcr(vcpu, rs,
- kvmppc_get_gpr(vcpu, ra));
- break;
-
- case XOP_TLBWE:
- emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws);
- break;
-
- case XOP_TLBSX:
- emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc);
- break;
-
- case XOP_ICCCI:
- break;
-
- default:
- emulated = EMULATE_FAIL;
- }
-
- break;
-
- default:
- emulated = EMULATE_FAIL;
- }
-
- if (emulated == EMULATE_FAIL)
- emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
-
- return emulated;
-}
-
-int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
-{
- int emulated = EMULATE_DONE;
-
- switch (sprn) {
- case SPRN_PID:
- kvmppc_set_pid(vcpu, spr_val); break;
- case SPRN_MMUCR:
- vcpu->arch.mmucr = spr_val; break;
- case SPRN_CCR0:
- vcpu->arch.ccr0 = spr_val; break;
- case SPRN_CCR1:
- vcpu->arch.ccr1 = spr_val; break;
- default:
- emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val);
- }
-
- return emulated;
-}
-
-int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
-{
- int emulated = EMULATE_DONE;
-
- switch (sprn) {
- case SPRN_PID:
- *spr_val = vcpu->arch.pid; break;
- case SPRN_MMUCR:
- *spr_val = vcpu->arch.mmucr; break;
- case SPRN_CCR0:
- *spr_val = vcpu->arch.ccr0; break;
- case SPRN_CCR1:
- *spr_val = vcpu->arch.ccr1; break;
- default:
- emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val);
- }
-
- return emulated;
-}
-
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
deleted file mode 100644
index 0deef1082e02..000000000000
--- a/arch/powerpc/kvm/44x_tlb.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2007
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kvm.h>
-#include <linux/kvm_host.h>
-#include <linux/highmem.h>
-
-#include <asm/tlbflush.h>
-#include <asm/mmu-44x.h>
-#include <asm/kvm_ppc.h>
-#include <asm/kvm_44x.h>
-#include "timing.h"
-
-#include "44x_tlb.h"
-#include "trace.h"
-
-#ifndef PPC44x_TLBE_SIZE
-#define PPC44x_TLBE_SIZE PPC44x_TLB_4K
-#endif
-
-#define PAGE_SIZE_4K (1<<12)
-#define PAGE_MASK_4K (~(PAGE_SIZE_4K - 1))
-
-#define PPC44x_TLB_UATTR_MASK \
- (PPC44x_TLB_U0|PPC44x_TLB_U1|PPC44x_TLB_U2|PPC44x_TLB_U3)
-#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
-#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
-
-#ifdef DEBUG
-void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- struct kvmppc_44x_tlbe *tlbe;
- int i;
-
- printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
- printk("| %2s | %3s | %8s | %8s | %8s |\n",
- "nr", "tid", "word0", "word1", "word2");
-
- for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
- tlbe = &vcpu_44x->guest_tlb[i];
- if (tlbe->word0 & PPC44x_TLB_VALID)
- printk(" G%2d | %02X | %08X | %08X | %08X |\n",
- i, tlbe->tid, tlbe->word0, tlbe->word1,
- tlbe->word2);
- }
-}
-#endif
-
-static inline void kvmppc_44x_tlbie(unsigned int index)
-{
- /* 0 <= index < 64, so the V bit is clear and we can use the index as
- * word0. */
- asm volatile(
- "tlbwe %[index], %[index], 0\n"
- :
- : [index] "r"(index)
- );
-}
-
-static inline void kvmppc_44x_tlbre(unsigned int index,
- struct kvmppc_44x_tlbe *tlbe)
-{
- asm volatile(
- "tlbre %[word0], %[index], 0\n"
- "mfspr %[tid], %[sprn_mmucr]\n"
- "andi. %[tid], %[tid], 0xff\n"
- "tlbre %[word1], %[index], 1\n"
- "tlbre %[word2], %[index], 2\n"
- : [word0] "=r"(tlbe->word0),
- [word1] "=r"(tlbe->word1),
- [word2] "=r"(tlbe->word2),
- [tid] "=r"(tlbe->tid)
- : [index] "r"(index),
- [sprn_mmucr] "i"(SPRN_MMUCR)
- : "cc"
- );
-}
-
-static inline void kvmppc_44x_tlbwe(unsigned int index,
- struct kvmppc_44x_tlbe *stlbe)
-{
- unsigned long tmp;
-
- asm volatile(
- "mfspr %[tmp], %[sprn_mmucr]\n"
- "rlwimi %[tmp], %[tid], 0, 0xff\n"
- "mtspr %[sprn_mmucr], %[tmp]\n"
- "tlbwe %[word0], %[index], 0\n"
- "tlbwe %[word1], %[index], 1\n"
- "tlbwe %[word2], %[index], 2\n"
- : [tmp] "=&r"(tmp)
- : [word0] "r"(stlbe->word0),
- [word1] "r"(stlbe->word1),
- [word2] "r"(stlbe->word2),
- [tid] "r"(stlbe->tid),
- [index] "r"(index),
- [sprn_mmucr] "i"(SPRN_MMUCR)
- );
-}
-
-static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
-{
- /* We only care about the guest's permission and user bits. */
- attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_UATTR_MASK;
-
- if (!usermode) {
- /* Guest is in supervisor mode, so we need to translate guest
- * supervisor permissions into user permissions. */
- attrib &= ~PPC44x_TLB_USER_PERM_MASK;
- attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3;
- }
-
- /* Make sure host can always access this memory. */
- attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW;
-
- /* WIMGE = 0b00100 */
- attrib |= PPC44x_TLB_M;
-
- return attrib;
-}
-
-/* Load shadow TLB back into hardware. */
-void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- for (i = 0; i <= tlb_44x_hwater; i++) {
- struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
-
- if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
- kvmppc_44x_tlbwe(i, stlbe);
- }
-}
-
-static void kvmppc_44x_tlbe_set_modified(struct kvmppc_vcpu_44x *vcpu_44x,
- unsigned int i)
-{
- vcpu_44x->shadow_tlb_mod[i] = 1;
-}
-
-/* Save hardware TLB to the vcpu, and invalidate all guest mappings. */
-void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- for (i = 0; i <= tlb_44x_hwater; i++) {
- struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
-
- if (vcpu_44x->shadow_tlb_mod[i])
- kvmppc_44x_tlbre(i, stlbe);
-
- if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
- kvmppc_44x_tlbie(i);
- }
-}
-
-
-/* Search the guest TLB for a matching entry. */
-int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
- unsigned int as)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
- struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[i];
- unsigned int tid;
-
- if (eaddr < get_tlb_eaddr(tlbe))
- continue;
-
- if (eaddr > get_tlb_end(tlbe))
- continue;
-
- tid = get_tlb_tid(tlbe);
- if (tid && (tid != pid))
- continue;
-
- if (!get_tlb_v(tlbe))
- continue;
-
- if (get_tlb_ts(tlbe) != as)
- continue;
-
- return i;
- }
-
- return -1;
-}
-
-gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
- gva_t eaddr)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
- unsigned int pgmask = get_tlb_bytes(gtlbe) - 1;
-
- return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
-}
-
-int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
-{
- unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
-
- return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-}
-
-int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
-{
- unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
-
- return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
-}
-
-void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
-{
-}
-
-void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
-{
-}
-
-static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x,
- unsigned int stlb_index)
-{
- struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[stlb_index];
-
- if (!ref->page)
- return;
-
- /* Discard from the TLB. */
- /* Note: we could actually invalidate a host mapping, if the host overwrote
- * this TLB entry since we inserted a guest mapping. */
- kvmppc_44x_tlbie(stlb_index);
-
- /* Now release the page. */
- if (ref->writeable)
- kvm_release_page_dirty(ref->page);
- else
- kvm_release_page_clean(ref->page);
-
- ref->page = NULL;
-
- /* XXX set tlb_44x_index to stlb_index? */
-
- trace_kvm_stlb_inval(stlb_index);
-}
-
-void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- for (i = 0; i <= tlb_44x_hwater; i++)
- kvmppc_44x_shadow_release(vcpu_44x, i);
-}
-
-/**
- * kvmppc_mmu_map -- create a host mapping for guest memory
- *
- * If the guest wanted a larger page than the host supports, only the first
- * host page is mapped here and the rest are demand faulted.
- *
- * If the guest wanted a smaller page than the host page size, we map only the
- * guest-size page (i.e. not a full host page mapping).
- *
- * Caller must ensure that the specified guest TLB entry is safe to insert into
- * the shadow TLB.
- */
-void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
- unsigned int gtlb_index)
-{
- struct kvmppc_44x_tlbe stlbe;
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
- struct kvmppc_44x_shadow_ref *ref;
- struct page *new_page;
- hpa_t hpaddr;
- gfn_t gfn;
- u32 asid = gtlbe->tid;
- u32 flags = gtlbe->word2;
- u32 max_bytes = get_tlb_bytes(gtlbe);
- unsigned int victim;
-
- /* Select TLB entry to clobber. Indirectly guard against races with the TLB
- * miss handler by disabling interrupts. */
- local_irq_disable();
- victim = ++tlb_44x_index;
- if (victim > tlb_44x_hwater)
- victim = 0;
- tlb_44x_index = victim;
- local_irq_enable();
-
- /* Get reference to new page. */
- gfn = gpaddr >> PAGE_SHIFT;
- new_page = gfn_to_page(vcpu->kvm, gfn);
- if (is_error_page(new_page)) {
- printk(KERN_ERR "Couldn't get guest page for gfn %llx!\n",
- (unsigned long long)gfn);
- return;
- }
- hpaddr = page_to_phys(new_page);
-
- /* Invalidate any previous shadow mappings. */
- kvmppc_44x_shadow_release(vcpu_44x, victim);
-
- /* XXX Make sure (va, size) doesn't overlap any other
- * entries. 440x6 user manual says the result would be
- * "undefined." */
-
- /* XXX what about AS? */
-
- /* Force TS=1 for all guest mappings. */
- stlbe.word0 = PPC44x_TLB_VALID | PPC44x_TLB_TS;
-
- if (max_bytes >= PAGE_SIZE) {
- /* Guest mapping is larger than or equal to host page size. We can use
- * a "native" host mapping. */
- stlbe.word0 |= (gvaddr & PAGE_MASK) | PPC44x_TLBE_SIZE;
- } else {
- /* Guest mapping is smaller than host page size. We must restrict the
- * size of the mapping to be at most the smaller of the two, but for
- * simplicity we fall back to a 4K mapping (this is probably what the
- * guest is using anyways). */
- stlbe.word0 |= (gvaddr & PAGE_MASK_4K) | PPC44x_TLB_4K;
-
- /* 'hpaddr' is a host page, which is larger than the mapping we're
- * inserting here. To compensate, we must add the in-page offset to the
- * sub-page. */
- hpaddr |= gpaddr & (PAGE_MASK ^ PAGE_MASK_4K);
- }
-
- stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
- stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
- vcpu->arch.shared->msr & MSR_PR);
- stlbe.tid = !(asid & 0xff);
-
- /* Keep track of the reference so we can properly release it later. */
- ref = &vcpu_44x->shadow_refs[victim];
- ref->page = new_page;
- ref->gtlb_index = gtlb_index;
- ref->writeable = !!(stlbe.word2 & PPC44x_TLB_UW);
- ref->tid = stlbe.tid;
-
- /* Insert shadow mapping into hardware TLB. */
- kvmppc_44x_tlbe_set_modified(vcpu_44x, victim);
- kvmppc_44x_tlbwe(victim, &stlbe);
- trace_kvm_stlb_write(victim, stlbe.tid, stlbe.word0, stlbe.word1,
- stlbe.word2);
-}
-
-/* For a particular guest TLB entry, invalidate the corresponding host TLB
- * mappings and release the host pages. */
-static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
- unsigned int gtlb_index)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
- struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
- if (ref->gtlb_index == gtlb_index)
- kvmppc_44x_shadow_release(vcpu_44x, i);
- }
-}
-
-void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
-{
- int usermode = vcpu->arch.shared->msr & MSR_PR;
-
- vcpu->arch.shadow_pid = !usermode;
-}
-
-void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- int i;
-
- if (unlikely(vcpu->arch.pid == new_pid))
- return;
-
- vcpu->arch.pid = new_pid;
-
- /* Guest userspace runs with TID=0 mappings and PID=0, to make sure it
- * can't access guest kernel mappings (TID=1). When we switch to a new
- * guest PID, which will also use host PID=0, we must discard the old guest
- * userspace mappings. */
- for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
- struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
-
- if (ref->tid == 0)
- kvmppc_44x_shadow_release(vcpu_44x, i);
- }
-}
-
-static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
- const struct kvmppc_44x_tlbe *tlbe)
-{
- gpa_t gpa;
-
- if (!get_tlb_v(tlbe))
- return 0;
-
- /* Does it match current guest AS? */
- /* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS))
- return 0;
-
- gpa = get_tlb_raddr(tlbe);
- if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
- /* Mapping is not for RAM. */
- return 0;
-
- return 1;
-}
-
-int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
-{
- struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
- struct kvmppc_44x_tlbe *tlbe;
- unsigned int gtlb_index;
- int idx;
-
- gtlb_index = kvmppc_get_gpr(vcpu, ra);
- if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) {
- printk("%s: index %d\n", __func__, gtlb_index);
- kvmppc_dump_vcpu(vcpu);
- return EMULATE_FAIL;
- }
-
- tlbe = &vcpu_44x->guest_tlb[gtlb_index];
-
- /* Invalidate shadow mappings for the about-to-be-clobbered TLB entry. */
- if (tlbe->word0 & PPC44x_TLB_VALID)
- kvmppc_44x_invalidate(vcpu, gtlb_index);
-
- switch (ws) {
- case PPC44x_TLB_PAGEID:
- tlbe->tid = get_mmucr_stid(vcpu);
- tlbe->word0 = kvmppc_get_gpr(vcpu, rs);
- break;
-
- case PPC44x_TLB_XLAT:
- tlbe->word1 = kvmppc_get_gpr(vcpu, rs);
- break;
-
- case PPC44x_TLB_ATTRIB:
- tlbe->word2 = kvmppc_get_gpr(vcpu, rs);
- break;
-
- default:
- return EMULATE_FAIL;
- }
-
- idx = srcu_read_lock(&vcpu->kvm->srcu);
-
- if (tlbe_is_host_safe(vcpu, tlbe)) {
- gva_t eaddr;
- gpa_t gpaddr;
- u32 bytes;
-
- eaddr = get_tlb_eaddr(tlbe);
- gpaddr = get_tlb_raddr(tlbe);
-
- /* Use the advertised page size to mask effective and real addrs. */
- bytes = get_tlb_bytes(tlbe);
- eaddr &= ~(bytes - 1);
- gpaddr &= ~(bytes - 1);
-
- kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index);
- }
-
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
-
- trace_kvm_gtlb_write(gtlb_index, tlbe->tid, tlbe->word0, tlbe->word1,
- tlbe->word2);
-
- kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
- return EMULATE_DONE;
-}
-
-int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8 rc)
-{
- u32 ea;
- int gtlb_index;
- unsigned int as = get_mmucr_sts(vcpu);
- unsigned int pid = get_mmucr_stid(vcpu);
-
- ea = kvmppc_get_gpr(vcpu, rb);
- if (ra)
- ea += kvmppc_get_gpr(vcpu, ra);
-
- gtlb_index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
- if (rc) {
- u32 cr = kvmppc_get_cr(vcpu);
-
- if (gtlb_index < 0)
- kvmppc_set_cr(vcpu, cr & ~0x20000000);
- else
- kvmppc_set_cr(vcpu, cr | 0x20000000);
- }
- kvmppc_set_gpr(vcpu, rt, gtlb_index);
-
- kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
- return EMULATE_DONE;
-}
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
deleted file mode 100644
index a9ff80e51526..000000000000
--- a/arch/powerpc/kvm/44x_tlb.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2007
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#ifndef __KVM_POWERPC_TLB_H__
-#define __KVM_POWERPC_TLB_H__
-
-#include <linux/kvm_host.h>
-#include <asm/mmu-44x.h>
-
-extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
- unsigned int pid, unsigned int as);
-
-extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb,
- u8 rc);
-extern int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws);
-
-/* TLB helper functions */
-static inline unsigned int get_tlb_size(const struct kvmppc_44x_tlbe *tlbe)
-{
- return (tlbe->word0 >> 4) & 0xf;
-}
-
-static inline gva_t get_tlb_eaddr(const struct kvmppc_44x_tlbe *tlbe)
-{
- return tlbe->word0 & 0xfffffc00;
-}
-
-static inline gva_t get_tlb_bytes(const struct kvmppc_44x_tlbe *tlbe)
-{
- unsigned int pgsize = get_tlb_size(tlbe);
- return 1 << 10 << (pgsize << 1);
-}
-
-static inline gva_t get_tlb_end(const struct kvmppc_44x_tlbe *tlbe)
-{
- return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1;
-}
-
-static inline u64 get_tlb_raddr(const struct kvmppc_44x_tlbe *tlbe)
-{
- u64 word1 = tlbe->word1;
- return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00);
-}
-
-static inline unsigned int get_tlb_tid(const struct kvmppc_44x_tlbe *tlbe)
-{
- return tlbe->tid & 0xff;
-}
-
-static inline unsigned int get_tlb_ts(const struct kvmppc_44x_tlbe *tlbe)
-{
- return (tlbe->word0 >> 8) & 0x1;
-}
-
-static inline unsigned int get_tlb_v(const struct kvmppc_44x_tlbe *tlbe)
-{
- return (tlbe->word0 >> 9) & 0x1;
-}
-
-static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.mmucr & 0xff;
-}
-
-static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu)
-{
- return (vcpu->arch.mmucr >> 16) & 0x1;
-}
-
-#endif /* __KVM_POWERPC_TLB_H__ */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index d6a53b95de94..602eb51d20bc 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -75,7 +75,6 @@ config KVM_BOOK3S_64
config KVM_BOOK3S_64_HV
tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
depends on KVM_BOOK3S_64
- depends on !CPU_LITTLE_ENDIAN
select KVM_BOOK3S_HV_POSSIBLE
select MMU_NOTIFIER
select CMA
@@ -113,23 +112,9 @@ config KVM_BOOK3S_64_PR
config KVM_BOOKE_HV
bool
-config KVM_440
- bool "KVM support for PowerPC 440 processors"
- depends on 44x
- select KVM
- select KVM_MMIO
- ---help---
- Support running unmodified 440 guest kernels in virtual machines on
- 440 host processors.
-
- This module provides access to the hardware capabilities through
- a character device node named /dev/kvm.
-
- If unsure, say N.
-
config KVM_EXIT_TIMING
bool "Detailed exit timing"
- depends on KVM_440 || KVM_E500V2 || KVM_E500MC
+ depends on KVM_E500V2 || KVM_E500MC
---help---
Calculate elapsed time for every exit/enter cycle. A per-vcpu
report is available in debugfs kvm/vm#_vcpu#_timing.
@@ -173,6 +158,7 @@ config KVM_MPIC
bool "KVM in-kernel MPIC emulation"
depends on KVM && E500
select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_MSI
help
@@ -184,6 +170,8 @@ config KVM_MPIC
config KVM_XICS
bool "KVM in-kernel XICS emulation"
depends on KVM_BOOK3S_64 && !KVM_MPIC
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
---help---
Include support for the XICS (eXternal Interrupt Controller
Specification) interrupt controller architecture used on
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index ce569b6bf4d8..0570eef83fba 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -10,27 +10,17 @@ KVM := ../../../virt/kvm
common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
$(KVM)/eventfd.o
-CFLAGS_44x_tlb.o := -I.
CFLAGS_e500_mmu.o := -I.
CFLAGS_e500_mmu_host.o := -I.
CFLAGS_emulate.o := -I.
+CFLAGS_emulate_loadstore.o := -I.
-common-objs-y += powerpc.o emulate.o
+common-objs-y += powerpc.o emulate.o emulate_loadstore.o
obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o
AFLAGS_booke_interrupts.o := -I$(obj)
-kvm-440-objs := \
- $(common-objs-y) \
- booke.o \
- booke_emulate.o \
- booke_interrupts.o \
- 44x.o \
- 44x_tlb.o \
- 44x_emulate.o
-kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs)
-
kvm-e500-objs := \
$(common-objs-y) \
booke.o \
@@ -58,6 +48,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
kvm-pr-y := \
fpu.o \
+ emulate.o \
book3s_paired_singles.o \
book3s_pr.o \
book3s_pr_papr.o \
@@ -90,7 +81,6 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
book3s_hv_rm_mmu.o \
book3s_hv_ras.o \
book3s_hv_builtin.o \
- book3s_hv_cma.o \
$(kvm-book3s_64-builtin-xics-objs-y)
endif
@@ -101,7 +91,7 @@ kvm-book3s_64-module-objs += \
$(KVM)/kvm_main.o \
$(KVM)/eventfd.o \
powerpc.o \
- emulate.o \
+ emulate_loadstore.o \
book3s.o \
book3s_64_vio.o \
book3s_rtas.o \
@@ -127,7 +117,6 @@ kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
kvm-objs := $(kvm-objs-m) $(kvm-objs-y)
-obj-$(CONFIG_KVM_440) += kvm.o
obj-$(CONFIG_KVM_E500V2) += kvm.o
obj-$(CONFIG_KVM_E500MC) += kvm.o
obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index c254c27f240e..dd03f6b299ba 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -72,6 +72,17 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
{
}
+void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) {
+ ulong pc = kvmppc_get_pc(vcpu);
+ if ((pc & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)
+ kvmppc_set_pc(vcpu, pc & ~SPLIT_HACK_MASK);
+ vcpu->arch.hflags &= ~BOOK3S_HFLAG_SPLIT_HACK;
+ }
+}
+EXPORT_SYMBOL_GPL(kvmppc_unfixup_split_real);
+
static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu)
{
if (!is_kvmppc_hv_enabled(vcpu->kvm))
@@ -118,6 +129,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
+ kvmppc_unfixup_split_real(vcpu);
kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags);
kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
@@ -218,6 +230,23 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
}
+void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar,
+ ulong flags)
+{
+ kvmppc_set_dar(vcpu, dar);
+ kvmppc_set_dsisr(vcpu, flags);
+ kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
+}
+
+void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong flags)
+{
+ u64 msr = kvmppc_get_msr(vcpu);
+ msr &= ~(SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
+ msr |= flags & (SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
+ kvmppc_set_msr_fast(vcpu, msr);
+ kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+}
+
int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
{
int deliver = 1;
@@ -342,18 +371,18 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter);
-pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
+pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
bool *writable)
{
- ulong mp_pa = vcpu->arch.magic_page_pa;
+ ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM;
+ gfn_t gfn = gpa >> PAGE_SHIFT;
if (!(kvmppc_get_msr(vcpu) & MSR_SF))
mp_pa = (uint32_t)mp_pa;
/* Magic page override */
- if (unlikely(mp_pa) &&
- unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) ==
- ((mp_pa & PAGE_MASK) & KVM_PAM))) {
+ gpa &= ~0xFFFULL;
+ if (unlikely(mp_pa) && unlikely((gpa & KVM_PAM) == mp_pa)) {
ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
pfn_t pfn;
@@ -366,11 +395,13 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable);
}
-EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn);
+EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn);
-static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
- bool iswrite, struct kvmppc_pte *pte)
+int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
+ enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
{
+ bool data = (xlid == XLATE_DATA);
+ bool iswrite = (xlrw == XLATE_WRITE);
int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
int r;
@@ -384,88 +415,34 @@ static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
pte->may_write = true;
pte->may_execute = true;
r = 0;
+
+ if ((kvmppc_get_msr(vcpu) & (MSR_IR | MSR_DR)) == MSR_DR &&
+ !data) {
+ if ((vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) &&
+ ((eaddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS))
+ pte->raddr &= ~SPLIT_HACK_MASK;
+ }
}
return r;
}
-static hva_t kvmppc_bad_hva(void)
-{
- return PAGE_OFFSET;
-}
-
-static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte,
- bool read)
-{
- hva_t hpage;
-
- if (read && !pte->may_read)
- goto err;
-
- if (!read && !pte->may_write)
- goto err;
-
- hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
- if (kvm_is_error_hva(hpage))
- goto err;
-
- return hpage | (pte->raddr & ~PAGE_MASK);
-err:
- return kvmppc_bad_hva();
-}
-
-int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
- bool data)
-{
- struct kvmppc_pte pte;
-
- vcpu->stat.st++;
-
- if (kvmppc_xlate(vcpu, *eaddr, data, true, &pte))
- return -ENOENT;
-
- *eaddr = pte.raddr;
-
- if (!pte.may_write)
- return -EPERM;
-
- if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
- return EMULATE_DO_MMIO;
-
- return EMULATE_DONE;
-}
-EXPORT_SYMBOL_GPL(kvmppc_st);
-
-int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
- bool data)
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+ u32 *inst)
{
- struct kvmppc_pte pte;
- hva_t hva = *eaddr;
-
- vcpu->stat.ld++;
-
- if (kvmppc_xlate(vcpu, *eaddr, data, false, &pte))
- goto nopte;
-
- *eaddr = pte.raddr;
-
- hva = kvmppc_pte_to_hva(vcpu, &pte, true);
- if (kvm_is_error_hva(hva))
- goto mmio;
-
- if (copy_from_user(ptr, (void __user *)hva, size)) {
- printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
- goto mmio;
- }
+ ulong pc = kvmppc_get_pc(vcpu);
+ int r;
- return EMULATE_DONE;
+ if (type == INST_SC)
+ pc -= 4;
-nopte:
- return -ENOENT;
-mmio:
- return EMULATE_DO_MMIO;
+ r = kvmppc_ld(vcpu, &pc, sizeof(u32), inst, false);
+ if (r == EMULATE_DONE)
+ return r;
+ else
+ return EMULATE_AGAIN;
}
-EXPORT_SYMBOL_GPL(kvmppc_ld);
+EXPORT_SYMBOL_GPL(kvmppc_load_last_inst);
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
@@ -646,6 +623,12 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
case KVM_REG_PPC_BESCR:
val = get_reg_val(reg->id, vcpu->arch.bescr);
break;
+ case KVM_REG_PPC_VTB:
+ val = get_reg_val(reg->id, vcpu->arch.vtb);
+ break;
+ case KVM_REG_PPC_IC:
+ val = get_reg_val(reg->id, vcpu->arch.ic);
+ break;
default:
r = -EINVAL;
break;
@@ -750,6 +733,12 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
case KVM_REG_PPC_BESCR:
vcpu->arch.bescr = set_reg_val(reg->id, val);
break;
+ case KVM_REG_PPC_VTB:
+ vcpu->arch.vtb = set_reg_val(reg->id, val);
+ break;
+ case KVM_REG_PPC_IC:
+ vcpu->arch.ic = set_reg_val(reg->id, val);
+ break;
default:
r = -EINVAL;
break;
@@ -913,6 +902,11 @@ int kvmppc_core_check_processor_compat(void)
return 0;
}
+int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall)
+{
+ return kvm->arch.kvm_ops->hcall_implemented(hcall);
+}
+
static int kvmppc_book3s_init(void)
{
int r;
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 93503bbdae43..cd0b0730e29e 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -335,7 +335,7 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
if (r < 0)
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte,
data, iswrite, true);
- if (r < 0)
+ if (r == -ENOENT)
r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte,
data, iswrite, false);
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 678e75370495..2035d16a9262 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -156,11 +156,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
bool writable;
/* Get host physical address for gpa */
- hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT,
- iswrite, &writable);
+ hpaddr = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
if (is_error_noslot_pfn(hpaddr)) {
- printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
- orig_pte->eaddr);
+ printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
+ orig_pte->raddr);
r = -EINVAL;
goto out;
}
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 0ac98392f363..b982d925c710 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -104,9 +104,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte,
smp_rmb();
/* Get host physical address for gpa */
- pfn = kvmppc_gfn_to_pfn(vcpu, gfn, iswrite, &writable);
+ pfn = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable);
if (is_error_noslot_pfn(pfn)) {
- printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", gfn);
+ printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n",
+ orig_pte->raddr);
r = -EINVAL;
goto out;
}
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 68468d695f12..72c20bb16d26 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -37,8 +37,6 @@
#include <asm/ppc-opcode.h>
#include <asm/cputable.h>
-#include "book3s_hv_cma.h"
-
/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
#define MAX_LPID_970 63
@@ -64,10 +62,10 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
}
kvm->arch.hpt_cma_alloc = 0;
- VM_BUG_ON(order < KVM_CMA_CHUNK_ORDER);
page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
if (page) {
hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+ memset((void *)hpt, 0, (1 << order));
kvm->arch.hpt_cma_alloc = 1;
}
@@ -450,7 +448,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
unsigned long slb_v;
unsigned long pp, key;
unsigned long v, gr;
- unsigned long *hptep;
+ __be64 *hptep;
int index;
int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
@@ -473,13 +471,13 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
preempt_enable();
return -ENOENT;
}
- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
- v = hptep[0] & ~HPTE_V_HVLOCK;
+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
+ v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
gr = kvm->arch.revmap[index].guest_rpte;
/* Unlock the HPTE */
asm volatile("lwsync" : : : "memory");
- hptep[0] = v;
+ hptep[0] = cpu_to_be64(v);
preempt_enable();
gpte->eaddr = eaddr;
@@ -530,21 +528,14 @@ static int instruction_is_store(unsigned int instr)
static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned long gpa, gva_t ea, int is_store)
{
- int ret;
u32 last_inst;
- unsigned long srr0 = kvmppc_get_pc(vcpu);
- /* We try to load the last instruction. We don't let
- * emulate_instruction do it as it doesn't check what
- * kvmppc_ld returns.
+ /*
* If we fail, we just return to the guest and try executing it again.
*/
- if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) {
- ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
- if (ret != EMULATE_DONE || last_inst == KVM_INST_FETCH_FAILED)
- return RESUME_GUEST;
- vcpu->arch.last_inst = last_inst;
- }
+ if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) !=
+ EMULATE_DONE)
+ return RESUME_GUEST;
/*
* WARNING: We do not know for sure whether the instruction we just
@@ -558,7 +549,7 @@ static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu,
* we just return and retry the instruction.
*/
- if (instruction_is_store(kvmppc_get_last_inst(vcpu)) != !!is_store)
+ if (instruction_is_store(last_inst) != !!is_store)
return RESUME_GUEST;
/*
@@ -583,7 +574,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned long ea, unsigned long dsisr)
{
struct kvm *kvm = vcpu->kvm;
- unsigned long *hptep, hpte[3], r;
+ unsigned long hpte[3], r;
+ __be64 *hptep;
unsigned long mmu_seq, psize, pte_size;
unsigned long gpa_base, gfn_base;
unsigned long gpa, gfn, hva, pfn;
@@ -606,16 +598,16 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (ea != vcpu->arch.pgfault_addr)
return RESUME_GUEST;
index = vcpu->arch.pgfault_index;
- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
rev = &kvm->arch.revmap[index];
preempt_disable();
while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
cpu_relax();
- hpte[0] = hptep[0] & ~HPTE_V_HVLOCK;
- hpte[1] = hptep[1];
+ hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
+ hpte[1] = be64_to_cpu(hptep[1]);
hpte[2] = r = rev->guest_rpte;
asm volatile("lwsync" : : : "memory");
- hptep[0] = hpte[0];
+ hptep[0] = cpu_to_be64(hpte[0]);
preempt_enable();
if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
@@ -731,8 +723,9 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
preempt_disable();
while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
cpu_relax();
- if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] ||
- rev->guest_rpte != hpte[2])
+ if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] ||
+ be64_to_cpu(hptep[1]) != hpte[1] ||
+ rev->guest_rpte != hpte[2])
/* HPTE has been changed under us; let the guest retry */
goto out_unlock;
hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
@@ -752,20 +745,20 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
r &= rcbits | ~(HPTE_R_R | HPTE_R_C);
- if (hptep[0] & HPTE_V_VALID) {
+ if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) {
/* HPTE was previously valid, so we need to invalidate it */
unlock_rmap(rmap);
- hptep[0] |= HPTE_V_ABSENT;
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
kvmppc_invalidate_hpte(kvm, hptep, index);
/* don't lose previous R and C bits */
- r |= hptep[1] & (HPTE_R_R | HPTE_R_C);
+ r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
} else {
kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
}
- hptep[1] = r;
+ hptep[1] = cpu_to_be64(r);
eieio();
- hptep[0] = hpte[0];
+ hptep[0] = cpu_to_be64(hpte[0]);
asm volatile("ptesync" : : : "memory");
preempt_enable();
if (page && hpte_is_writable(r))
@@ -784,7 +777,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
return ret;
out_unlock:
- hptep[0] &= ~HPTE_V_HVLOCK;
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
preempt_enable();
goto out_put;
}
@@ -860,7 +853,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
{
struct revmap_entry *rev = kvm->arch.revmap;
unsigned long h, i, j;
- unsigned long *hptep;
+ __be64 *hptep;
unsigned long ptel, psize, rcbits;
for (;;) {
@@ -876,11 +869,11 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
* rmap chain lock.
*/
i = *rmapp & KVMPPC_RMAP_INDEX;
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
/* unlock rmap before spinning on the HPTE lock */
unlock_rmap(rmapp);
- while (hptep[0] & HPTE_V_HVLOCK)
+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
cpu_relax();
continue;
}
@@ -899,14 +892,14 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
/* Now check and modify the HPTE */
ptel = rev[i].guest_rpte;
- psize = hpte_page_size(hptep[0], ptel);
- if ((hptep[0] & HPTE_V_VALID) &&
+ psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel);
+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
hpte_rpn(ptel, psize) == gfn) {
if (kvm->arch.using_mmu_notifiers)
- hptep[0] |= HPTE_V_ABSENT;
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
kvmppc_invalidate_hpte(kvm, hptep, i);
/* Harvest R and C */
- rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
+ rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
if (rcbits & ~rev[i].guest_rpte) {
rev[i].guest_rpte = ptel | rcbits;
@@ -914,7 +907,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
}
}
unlock_rmap(rmapp);
- hptep[0] &= ~HPTE_V_HVLOCK;
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
}
return 0;
}
@@ -961,7 +954,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
{
struct revmap_entry *rev = kvm->arch.revmap;
unsigned long head, i, j;
- unsigned long *hptep;
+ __be64 *hptep;
int ret = 0;
retry:
@@ -977,23 +970,24 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
i = head = *rmapp & KVMPPC_RMAP_INDEX;
do {
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
j = rev[i].forw;
/* If this HPTE isn't referenced, ignore it */
- if (!(hptep[1] & HPTE_R_R))
+ if (!(be64_to_cpu(hptep[1]) & HPTE_R_R))
continue;
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
/* unlock rmap before spinning on the HPTE lock */
unlock_rmap(rmapp);
- while (hptep[0] & HPTE_V_HVLOCK)
+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
cpu_relax();
goto retry;
}
/* Now check and modify the HPTE */
- if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) {
+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) &&
+ (be64_to_cpu(hptep[1]) & HPTE_R_R)) {
kvmppc_clear_ref_hpte(kvm, hptep, i);
if (!(rev[i].guest_rpte & HPTE_R_R)) {
rev[i].guest_rpte |= HPTE_R_R;
@@ -1001,7 +995,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
}
ret = 1;
}
- hptep[0] &= ~HPTE_V_HVLOCK;
+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
} while ((i = j) != head);
unlock_rmap(rmapp);
@@ -1035,7 +1029,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
do {
hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4));
j = rev[i].forw;
- if (hp[1] & HPTE_R_R)
+ if (be64_to_cpu(hp[1]) & HPTE_R_R)
goto out;
} while ((i = j) != head);
}
@@ -1075,7 +1069,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
unsigned long head, i, j;
unsigned long n;
unsigned long v, r;
- unsigned long *hptep;
+ __be64 *hptep;
int npages_dirty = 0;
retry:
@@ -1091,7 +1085,8 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
i = head = *rmapp & KVMPPC_RMAP_INDEX;
do {
- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
+ unsigned long hptep1;
+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4));
j = rev[i].forw;
/*
@@ -1108,29 +1103,30 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
* Otherwise we need to do the tlbie even if C==0 in
* order to pick up any delayed writeback of C.
*/
- if (!(hptep[1] & HPTE_R_C) &&
- (!hpte_is_writable(hptep[1]) || vcpus_running(kvm)))
+ hptep1 = be64_to_cpu(hptep[1]);
+ if (!(hptep1 & HPTE_R_C) &&
+ (!hpte_is_writable(hptep1) || vcpus_running(kvm)))
continue;
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
/* unlock rmap before spinning on the HPTE lock */
unlock_rmap(rmapp);
- while (hptep[0] & HPTE_V_HVLOCK)
+ while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK))
cpu_relax();
goto retry;
}
/* Now check and modify the HPTE */
- if (!(hptep[0] & HPTE_V_VALID))
+ if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID)))
continue;
/* need to make it temporarily absent so C is stable */
- hptep[0] |= HPTE_V_ABSENT;
+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
kvmppc_invalidate_hpte(kvm, hptep, i);
- v = hptep[0];
- r = hptep[1];
+ v = be64_to_cpu(hptep[0]);
+ r = be64_to_cpu(hptep[1]);
if (r & HPTE_R_C) {
- hptep[1] = r & ~HPTE_R_C;
+ hptep[1] = cpu_to_be64(r & ~HPTE_R_C);
if (!(rev[i].guest_rpte & HPTE_R_C)) {
rev[i].guest_rpte |= HPTE_R_C;
note_hpte_modification(kvm, &rev[i]);
@@ -1143,7 +1139,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
}
v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
v |= HPTE_V_VALID;
- hptep[0] = v;
+ hptep[0] = cpu_to_be64(v);
} while ((i = j) != head);
unlock_rmap(rmapp);
@@ -1307,7 +1303,7 @@ struct kvm_htab_ctx {
* Returns 1 if this HPT entry has been modified or has pending
* R/C bit changes.
*/
-static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp)
+static int hpte_dirty(struct revmap_entry *revp, __be64 *hptp)
{
unsigned long rcbits_unset;
@@ -1316,13 +1312,14 @@ static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp)
/* Also need to consider changes in reference and changed bits */
rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
- if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset))
+ if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) &&
+ (be64_to_cpu(hptp[1]) & rcbits_unset))
return 1;
return 0;
}
-static long record_hpte(unsigned long flags, unsigned long *hptp,
+static long record_hpte(unsigned long flags, __be64 *hptp,
unsigned long *hpte, struct revmap_entry *revp,
int want_valid, int first_pass)
{
@@ -1337,10 +1334,10 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
return 0;
valid = 0;
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) {
valid = 1;
if ((flags & KVM_GET_HTAB_BOLTED_ONLY) &&
- !(hptp[0] & HPTE_V_BOLTED))
+ !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED))
valid = 0;
}
if (valid != want_valid)
@@ -1352,7 +1349,7 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
preempt_disable();
while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
cpu_relax();
- v = hptp[0];
+ v = be64_to_cpu(hptp[0]);
/* re-evaluate valid and dirty from synchronized HPTE value */
valid = !!(v & HPTE_V_VALID);
@@ -1360,9 +1357,9 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
/* Harvest R and C into guest view if necessary */
rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
- if (valid && (rcbits_unset & hptp[1])) {
- revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) |
- HPTE_GR_MODIFIED;
+ if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) {
+ revp->guest_rpte |= (be64_to_cpu(hptp[1]) &
+ (HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED;
dirty = 1;
}
@@ -1381,13 +1378,13 @@ static long record_hpte(unsigned long flags, unsigned long *hptp,
revp->guest_rpte = r;
}
asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
- hptp[0] &= ~HPTE_V_HVLOCK;
+ hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
preempt_enable();
if (!(valid == want_valid && (first_pass || dirty)))
ok = 0;
}
- hpte[0] = v;
- hpte[1] = r;
+ hpte[0] = cpu_to_be64(v);
+ hpte[1] = cpu_to_be64(r);
return ok;
}
@@ -1397,7 +1394,7 @@ static ssize_t kvm_htab_read(struct file *file, char __user *buf,
struct kvm_htab_ctx *ctx = file->private_data;
struct kvm *kvm = ctx->kvm;
struct kvm_get_htab_header hdr;
- unsigned long *hptp;
+ __be64 *hptp;
struct revmap_entry *revp;
unsigned long i, nb, nw;
unsigned long __user *lbuf;
@@ -1413,7 +1410,7 @@ static ssize_t kvm_htab_read(struct file *file, char __user *buf,
flags = ctx->flags;
i = ctx->index;
- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
revp = kvm->arch.revmap + i;
lbuf = (unsigned long __user *)buf;
@@ -1497,7 +1494,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
unsigned long i, j;
unsigned long v, r;
unsigned long __user *lbuf;
- unsigned long *hptp;
+ __be64 *hptp;
unsigned long tmp[2];
ssize_t nb;
long int err, ret;
@@ -1539,7 +1536,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte)
break;
- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
lbuf = (unsigned long __user *)buf;
for (j = 0; j < hdr.n_valid; ++j) {
err = -EFAULT;
@@ -1551,7 +1548,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
lbuf += 2;
nb += HPTE_SIZE;
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
err = -EIO;
ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r,
@@ -1577,7 +1574,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
}
for (j = 0; j < hdr.n_invalid; ++j) {
- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT))
+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT))
kvmppc_do_h_remove(kvm, 0, i, 0, tmp);
++i;
hptp += 2;
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 3f295269af37..5a2bc4b0dfe5 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -439,12 +439,6 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
(mfmsr() & MSR_HV))
vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
break;
- case SPRN_PURR:
- to_book3s(vcpu)->purr_offset = spr_val - get_tb();
- break;
- case SPRN_SPURR:
- to_book3s(vcpu)->spurr_offset = spr_val - get_tb();
- break;
case SPRN_GQR0:
case SPRN_GQR1:
case SPRN_GQR2:
@@ -455,10 +449,10 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
case SPRN_GQR7:
to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val;
break;
+#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_FSCR:
- vcpu->arch.fscr = spr_val;
+ kvmppc_set_fscr(vcpu, spr_val);
break;
-#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_BESCR:
vcpu->arch.bescr = spr_val;
break;
@@ -572,10 +566,22 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
*spr_val = 0;
break;
case SPRN_PURR:
- *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+ /*
+ * On exit we would have updated purr
+ */
+ *spr_val = vcpu->arch.purr;
break;
case SPRN_SPURR:
- *spr_val = get_tb() + to_book3s(vcpu)->purr_offset;
+ /*
+ * On exit we would have updated spurr
+ */
+ *spr_val = vcpu->arch.spurr;
+ break;
+ case SPRN_VTB:
+ *spr_val = vcpu->arch.vtb;
+ break;
+ case SPRN_IC:
+ *spr_val = vcpu->arch.ic;
break;
case SPRN_GQR0:
case SPRN_GQR1:
@@ -587,10 +593,10 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
case SPRN_GQR7:
*spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0];
break;
+#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_FSCR:
*spr_val = vcpu->arch.fscr;
break;
-#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_BESCR:
*spr_val = vcpu->arch.bescr;
break;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 7a12edbb61e7..27cced9c7249 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -35,6 +35,7 @@
#include <asm/reg.h>
#include <asm/cputable.h>
+#include <asm/cache.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
@@ -67,6 +68,15 @@
/* Used as a "null" value for timebase values */
#define TB_NIL (~(u64)0)
+static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
+
+#if defined(CONFIG_PPC_64K_PAGES)
+#define MPP_BUFFER_ORDER 0
+#elif defined(CONFIG_PPC_4K_PAGES)
+#define MPP_BUFFER_ORDER 3
+#endif
+
+
static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
@@ -270,7 +280,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
{
vpa->__old_status |= LPPACA_OLD_SHARED_PROC;
- vpa->yield_count = 1;
+ vpa->yield_count = cpu_to_be32(1);
}
static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
@@ -293,8 +303,8 @@ static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
struct reg_vpa {
u32 dummy;
union {
- u16 hword;
- u32 word;
+ __be16 hword;
+ __be32 word;
} length;
};
@@ -333,9 +343,9 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
if (va == NULL)
return H_PARAMETER;
if (subfunc == H_VPA_REG_VPA)
- len = ((struct reg_vpa *)va)->length.hword;
+ len = be16_to_cpu(((struct reg_vpa *)va)->length.hword);
else
- len = ((struct reg_vpa *)va)->length.word;
+ len = be32_to_cpu(((struct reg_vpa *)va)->length.word);
kvmppc_unpin_guest_page(kvm, va, vpa, false);
/* Check length */
@@ -540,21 +550,63 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
return;
memset(dt, 0, sizeof(struct dtl_entry));
dt->dispatch_reason = 7;
- dt->processor_id = vc->pcpu + vcpu->arch.ptid;
- dt->timebase = now + vc->tb_offset;
- dt->enqueue_to_dispatch_time = stolen;
- dt->srr0 = kvmppc_get_pc(vcpu);
- dt->srr1 = vcpu->arch.shregs.msr;
+ dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid);
+ dt->timebase = cpu_to_be64(now + vc->tb_offset);
+ dt->enqueue_to_dispatch_time = cpu_to_be32(stolen);
+ dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu));
+ dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr);
++dt;
if (dt == vcpu->arch.dtl.pinned_end)
dt = vcpu->arch.dtl.pinned_addr;
vcpu->arch.dtl_ptr = dt;
/* order writing *dt vs. writing vpa->dtl_idx */
smp_wmb();
- vpa->dtl_idx = ++vcpu->arch.dtl_index;
+ vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index);
vcpu->arch.dtl.dirty = true;
}
+static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
+ return true;
+ if ((!vcpu->arch.vcore->arch_compat) &&
+ cpu_has_feature(CPU_FTR_ARCH_207S))
+ return true;
+ return false;
+}
+
+static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
+ unsigned long resource, unsigned long value1,
+ unsigned long value2)
+{
+ switch (resource) {
+ case H_SET_MODE_RESOURCE_SET_CIABR:
+ if (!kvmppc_power8_compatible(vcpu))
+ return H_P2;
+ if (value2)
+ return H_P4;
+ if (mflags)
+ return H_UNSUPPORTED_FLAG_START;
+ /* Guests can't breakpoint the hypervisor */
+ if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER)
+ return H_P3;
+ vcpu->arch.ciabr = value1;
+ return H_SUCCESS;
+ case H_SET_MODE_RESOURCE_SET_DAWR:
+ if (!kvmppc_power8_compatible(vcpu))
+ return H_P2;
+ if (mflags)
+ return H_UNSUPPORTED_FLAG_START;
+ if (value2 & DABRX_HYP)
+ return H_P4;
+ vcpu->arch.dawr = value1;
+ vcpu->arch.dawrx = value2;
+ return H_SUCCESS;
+ default:
+ return H_TOO_HARD;
+ }
+}
+
int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
{
unsigned long req = kvmppc_get_gpr(vcpu, 3);
@@ -562,6 +614,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
struct kvm_vcpu *tvcpu;
int idx, rc;
+ if (req <= MAX_HCALL_OPCODE &&
+ !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls))
+ return RESUME_HOST;
+
switch (req) {
case H_ENTER:
idx = srcu_read_lock(&vcpu->kvm->srcu);
@@ -620,7 +676,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
/* Send the error out to userspace via KVM_RUN */
return rc;
-
+ case H_SET_MODE:
+ ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4),
+ kvmppc_get_gpr(vcpu, 5),
+ kvmppc_get_gpr(vcpu, 6),
+ kvmppc_get_gpr(vcpu, 7));
+ if (ret == H_TOO_HARD)
+ return RESUME_HOST;
+ break;
case H_XIRR:
case H_CPPR:
case H_EOI:
@@ -639,6 +702,29 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
return RESUME_GUEST;
}
+static int kvmppc_hcall_impl_hv(unsigned long cmd)
+{
+ switch (cmd) {
+ case H_CEDE:
+ case H_PROD:
+ case H_CONFER:
+ case H_REGISTER_VPA:
+ case H_SET_MODE:
+#ifdef CONFIG_KVM_XICS
+ case H_XIRR:
+ case H_CPPR:
+ case H_EOI:
+ case H_IPI:
+ case H_IPOLL:
+ case H_XIRR_X:
+#endif
+ return 1;
+ }
+
+ /* See if it's in the real-mode table */
+ return kvmppc_hcall_impl_hv_realmode(cmd);
+}
+
static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
struct task_struct *tsk)
{
@@ -785,7 +871,8 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu,
return 0;
}
-static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
+static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
+ bool preserve_top32)
{
struct kvmppc_vcore *vc = vcpu->arch.vcore;
u64 mask;
@@ -820,6 +907,10 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr)
mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
if (cpu_has_feature(CPU_FTR_ARCH_207S))
mask |= LPCR_AIL;
+
+ /* Broken 32-bit version of LPCR must not clear top bits */
+ if (preserve_top32)
+ mask &= 0xFFFFFFFF;
vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask);
spin_unlock(&vc->lock);
}
@@ -894,12 +985,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_CIABR:
*val = get_reg_val(id, vcpu->arch.ciabr);
break;
- case KVM_REG_PPC_IC:
- *val = get_reg_val(id, vcpu->arch.ic);
- break;
- case KVM_REG_PPC_VTB:
- *val = get_reg_val(id, vcpu->arch.vtb);
- break;
case KVM_REG_PPC_CSIGR:
*val = get_reg_val(id, vcpu->arch.csigr);
break;
@@ -939,6 +1024,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.vcore->tb_offset);
break;
case KVM_REG_PPC_LPCR:
+ case KVM_REG_PPC_LPCR_64:
*val = get_reg_val(id, vcpu->arch.vcore->lpcr);
break;
case KVM_REG_PPC_PPR:
@@ -1094,12 +1180,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER)
vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */
break;
- case KVM_REG_PPC_IC:
- vcpu->arch.ic = set_reg_val(id, *val);
- break;
- case KVM_REG_PPC_VTB:
- vcpu->arch.vtb = set_reg_val(id, *val);
- break;
case KVM_REG_PPC_CSIGR:
vcpu->arch.csigr = set_reg_val(id, *val);
break;
@@ -1150,7 +1230,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
ALIGN(set_reg_val(id, *val), 1UL << 24);
break;
case KVM_REG_PPC_LPCR:
- kvmppc_set_lpcr(vcpu, set_reg_val(id, *val));
+ kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true);
+ break;
+ case KVM_REG_PPC_LPCR_64:
+ kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false);
break;
case KVM_REG_PPC_PPR:
vcpu->arch.ppr = set_reg_val(id, *val);
@@ -1228,6 +1311,33 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
return r;
}
+static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
+{
+ struct kvmppc_vcore *vcore;
+
+ vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
+
+ if (vcore == NULL)
+ return NULL;
+
+ INIT_LIST_HEAD(&vcore->runnable_threads);
+ spin_lock_init(&vcore->lock);
+ init_waitqueue_head(&vcore->wq);
+ vcore->preempt_tb = TB_NIL;
+ vcore->lpcr = kvm->arch.lpcr;
+ vcore->first_vcpuid = core * threads_per_subcore;
+ vcore->kvm = kvm;
+
+ vcore->mpp_buffer_is_valid = false;
+
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ vcore->mpp_buffer = (void *)__get_free_pages(
+ GFP_KERNEL|__GFP_ZERO,
+ MPP_BUFFER_ORDER);
+
+ return vcore;
+}
+
static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
unsigned int id)
{
@@ -1279,16 +1389,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
mutex_lock(&kvm->lock);
vcore = kvm->arch.vcores[core];
if (!vcore) {
- vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL);
- if (vcore) {
- INIT_LIST_HEAD(&vcore->runnable_threads);
- spin_lock_init(&vcore->lock);
- init_waitqueue_head(&vcore->wq);
- vcore->preempt_tb = TB_NIL;
- vcore->lpcr = kvm->arch.lpcr;
- vcore->first_vcpuid = core * threads_per_subcore;
- vcore->kvm = kvm;
- }
+ vcore = kvmppc_vcore_create(kvm, core);
kvm->arch.vcores[core] = vcore;
kvm->arch.online_vcores++;
}
@@ -1500,6 +1601,33 @@ static int on_primary_thread(void)
return 1;
}
+static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
+{
+ phys_addr_t phy_addr, mpp_addr;
+
+ phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
+ mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+ mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
+ logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
+
+ vc->mpp_buffer_is_valid = true;
+}
+
+static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
+{
+ phys_addr_t phy_addr, mpp_addr;
+
+ phy_addr = virt_to_phys(vc->mpp_buffer);
+ mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
+
+ /* We must abort any in-progress save operations to ensure
+ * the table is valid so that prefetch engine knows when to
+ * stop prefetching. */
+ logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
+ mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
+}
+
/*
* Run a set of guest threads on a physical core.
* Called with vc->lock held.
@@ -1577,9 +1705,16 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
+ if (vc->mpp_buffer_is_valid)
+ kvmppc_start_restoring_l2_cache(vc);
+
__kvmppc_vcore_entry();
spin_lock(&vc->lock);
+
+ if (vc->mpp_buffer)
+ kvmppc_start_saving_l2_cache(vc);
+
/* disable sending of IPIs on virtual external irqs */
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
vcpu->cpu = -1;
@@ -1929,12 +2064,6 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps,
(*sps)->page_shift = def->shift;
(*sps)->slb_enc = def->sllp;
(*sps)->enc[0].page_shift = def->shift;
- /*
- * Only return base page encoding. We don't want to return
- * all the supporting pte_enc, because our H_ENTER doesn't
- * support MPSS yet. Once they do, we can start passing all
- * support pte_enc here
- */
(*sps)->enc[0].pte_enc = def->penc[linux_psize];
/*
* Add 16MB MPSS support if host supports it
@@ -2281,6 +2410,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
*/
cpumask_setall(&kvm->arch.need_tlb_flush);
+ /* Start out with the default set of hcalls enabled */
+ memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls,
+ sizeof(kvm->arch.enabled_hcalls));
+
kvm->arch.rma = NULL;
kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
@@ -2323,8 +2456,14 @@ static void kvmppc_free_vcores(struct kvm *kvm)
{
long int i;
- for (i = 0; i < KVM_MAX_VCORES; ++i)
+ for (i = 0; i < KVM_MAX_VCORES; ++i) {
+ if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
+ struct kvmppc_vcore *vc = kvm->arch.vcores[i];
+ free_pages((unsigned long)vc->mpp_buffer,
+ MPP_BUFFER_ORDER);
+ }
kfree(kvm->arch.vcores[i]);
+ }
kvm->arch.online_vcores = 0;
}
@@ -2419,6 +2558,49 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,
return r;
}
+/*
+ * List of hcall numbers to enable by default.
+ * For compatibility with old userspace, we enable by default
+ * all hcalls that were implemented before the hcall-enabling
+ * facility was added. Note this list should not include H_RTAS.
+ */
+static unsigned int default_hcall_list[] = {
+ H_REMOVE,
+ H_ENTER,
+ H_READ,
+ H_PROTECT,
+ H_BULK_REMOVE,
+ H_GET_TCE,
+ H_PUT_TCE,
+ H_SET_DABR,
+ H_SET_XDABR,
+ H_CEDE,
+ H_PROD,
+ H_CONFER,
+ H_REGISTER_VPA,
+#ifdef CONFIG_KVM_XICS
+ H_EOI,
+ H_CPPR,
+ H_IPI,
+ H_IPOLL,
+ H_XIRR,
+ H_XIRR_X,
+#endif
+ 0
+};
+
+static void init_default_hcalls(void)
+{
+ int i;
+ unsigned int hcall;
+
+ for (i = 0; default_hcall_list[i]; ++i) {
+ hcall = default_hcall_list[i];
+ WARN_ON(!kvmppc_hcall_impl_hv(hcall));
+ __set_bit(hcall / 4, default_enabled_hcalls);
+ }
+}
+
static struct kvmppc_ops kvm_ops_hv = {
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
@@ -2451,6 +2633,7 @@ static struct kvmppc_ops kvm_ops_hv = {
.emulate_mfspr = kvmppc_core_emulate_mfspr_hv,
.fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv,
.arch_vm_ioctl = kvm_arch_vm_ioctl_hv,
+ .hcall_implemented = kvmppc_hcall_impl_hv,
};
static int kvmppc_book3s_init_hv(void)
@@ -2466,6 +2649,8 @@ static int kvmppc_book3s_init_hv(void)
kvm_ops_hv.owner = THIS_MODULE;
kvmppc_hv_ops = &kvm_ops_hv;
+ init_default_hcalls();
+
r = kvmppc_mmu_hv_init();
return r;
}
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 7cde8a665205..329d7fdd0a6a 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -16,12 +16,14 @@
#include <linux/init.h>
#include <linux/memblock.h>
#include <linux/sizes.h>
+#include <linux/cma.h>
#include <asm/cputable.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
-#include "book3s_hv_cma.h"
+#define KVM_CMA_CHUNK_ORDER 18
+
/*
* Hash page table alignment on newer cpus(CPU_FTR_ARCH_206)
* should be power of 2.
@@ -43,6 +45,8 @@ static unsigned long kvm_cma_resv_ratio = 5;
unsigned long kvm_rma_pages = (1 << 27) >> PAGE_SHIFT; /* 128MB */
EXPORT_SYMBOL_GPL(kvm_rma_pages);
+static struct cma *kvm_cma;
+
/* Work out RMLS (real mode limit selector) field value for a given RMA size.
Assumes POWER7 or PPC970. */
static inline int lpcr_rmls(unsigned long rma_size)
@@ -97,7 +101,7 @@ struct kvm_rma_info *kvm_alloc_rma()
ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL);
if (!ri)
return NULL;
- page = kvm_alloc_cma(kvm_rma_pages, kvm_rma_pages);
+ page = cma_alloc(kvm_cma, kvm_rma_pages, get_order(kvm_rma_pages));
if (!page)
goto err_out;
atomic_set(&ri->use_count, 1);
@@ -112,7 +116,7 @@ EXPORT_SYMBOL_GPL(kvm_alloc_rma);
void kvm_release_rma(struct kvm_rma_info *ri)
{
if (atomic_dec_and_test(&ri->use_count)) {
- kvm_release_cma(pfn_to_page(ri->base_pfn), kvm_rma_pages);
+ cma_release(kvm_cma, pfn_to_page(ri->base_pfn), kvm_rma_pages);
kfree(ri);
}
}
@@ -131,16 +135,18 @@ struct page *kvm_alloc_hpt(unsigned long nr_pages)
{
unsigned long align_pages = HPT_ALIGN_PAGES;
+ VM_BUG_ON(get_order(nr_pages) < KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
+
/* Old CPUs require HPT aligned on a multiple of its size */
if (!cpu_has_feature(CPU_FTR_ARCH_206))
align_pages = nr_pages;
- return kvm_alloc_cma(nr_pages, align_pages);
+ return cma_alloc(kvm_cma, nr_pages, get_order(align_pages));
}
EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
void kvm_release_hpt(struct page *page, unsigned long nr_pages)
{
- kvm_release_cma(page, nr_pages);
+ cma_release(kvm_cma, page, nr_pages);
}
EXPORT_SYMBOL_GPL(kvm_release_hpt);
@@ -179,7 +185,8 @@ void __init kvm_cma_reserve(void)
align_size = HPT_ALIGN_PAGES << PAGE_SHIFT;
align_size = max(kvm_rma_pages << PAGE_SHIFT, align_size);
- kvm_cma_declare_contiguous(selected_size, align_size);
+ cma_declare_contiguous(0, selected_size, 0, align_size,
+ KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma);
}
}
@@ -212,3 +219,16 @@ bool kvm_hv_mode_active(void)
{
return atomic_read(&hv_vm_count) != 0;
}
+
+extern int hcall_real_table[], hcall_real_table_end[];
+
+int kvmppc_hcall_impl_hv_realmode(unsigned long cmd)
+{
+ cmd /= 4;
+ if (cmd < hcall_real_table_end - hcall_real_table &&
+ hcall_real_table[cmd])
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
diff --git a/arch/powerpc/kvm/book3s_hv_cma.c b/arch/powerpc/kvm/book3s_hv_cma.c
deleted file mode 100644
index d9d3d8553d51..000000000000
--- a/arch/powerpc/kvm/book3s_hv_cma.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA
- * for DMA mapping framework
- *
- * Copyright IBM Corporation, 2013
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.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 optional) any later version of the license.
- *
- */
-#define pr_fmt(fmt) "kvm_cma: " fmt
-
-#ifdef CONFIG_CMA_DEBUG
-#ifndef DEBUG
-# define DEBUG
-#endif
-#endif
-
-#include <linux/memblock.h>
-#include <linux/mutex.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-
-#include "book3s_hv_cma.h"
-
-struct kvm_cma {
- unsigned long base_pfn;
- unsigned long count;
- unsigned long *bitmap;
-};
-
-static DEFINE_MUTEX(kvm_cma_mutex);
-static struct kvm_cma kvm_cma_area;
-
-/**
- * kvm_cma_declare_contiguous() - reserve area for contiguous memory handling
- * for kvm hash pagetable
- * @size: Size of the reserved memory.
- * @alignment: Alignment for the contiguous memory area
- *
- * This function reserves memory for kvm cma area. It should be
- * called by arch code when early allocator (memblock or bootmem)
- * is still activate.
- */
-long __init kvm_cma_declare_contiguous(phys_addr_t size, phys_addr_t alignment)
-{
- long base_pfn;
- phys_addr_t addr;
- struct kvm_cma *cma = &kvm_cma_area;
-
- pr_debug("%s(size %lx)\n", __func__, (unsigned long)size);
-
- if (!size)
- return -EINVAL;
- /*
- * Sanitise input arguments.
- * We should be pageblock aligned for CMA.
- */
- alignment = max(alignment, (phys_addr_t)(PAGE_SIZE << pageblock_order));
- size = ALIGN(size, alignment);
- /*
- * Reserve memory
- * Use __memblock_alloc_base() since
- * memblock_alloc_base() panic()s.
- */
- addr = __memblock_alloc_base(size, alignment, 0);
- if (!addr) {
- base_pfn = -ENOMEM;
- goto err;
- } else
- base_pfn = PFN_DOWN(addr);
-
- /*
- * Each reserved area must be initialised later, when more kernel
- * subsystems (like slab allocator) are available.
- */
- cma->base_pfn = base_pfn;
- cma->count = size >> PAGE_SHIFT;
- pr_info("CMA: reserved %ld MiB\n", (unsigned long)size / SZ_1M);
- return 0;
-err:
- pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
- return base_pfn;
-}
-
-/**
- * kvm_alloc_cma() - allocate pages from contiguous area
- * @nr_pages: Requested number of pages.
- * @align_pages: Requested alignment in number of pages
- *
- * This function allocates memory buffer for hash pagetable.
- */
-struct page *kvm_alloc_cma(unsigned long nr_pages, unsigned long align_pages)
-{
- int ret;
- struct page *page = NULL;
- struct kvm_cma *cma = &kvm_cma_area;
- unsigned long chunk_count, nr_chunk;
- unsigned long mask, pfn, pageno, start = 0;
-
-
- if (!cma || !cma->count)
- return NULL;
-
- pr_debug("%s(cma %p, count %lu, align pages %lu)\n", __func__,
- (void *)cma, nr_pages, align_pages);
-
- if (!nr_pages)
- return NULL;
- /*
- * align mask with chunk size. The bit tracks pages in chunk size
- */
- VM_BUG_ON(!is_power_of_2(align_pages));
- mask = (align_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT)) - 1;
- BUILD_BUG_ON(PAGE_SHIFT > KVM_CMA_CHUNK_ORDER);
-
- chunk_count = cma->count >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
- nr_chunk = nr_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-
- mutex_lock(&kvm_cma_mutex);
- for (;;) {
- pageno = bitmap_find_next_zero_area(cma->bitmap, chunk_count,
- start, nr_chunk, mask);
- if (pageno >= chunk_count)
- break;
-
- pfn = cma->base_pfn + (pageno << (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT));
- ret = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_CMA);
- if (ret == 0) {
- bitmap_set(cma->bitmap, pageno, nr_chunk);
- page = pfn_to_page(pfn);
- memset(pfn_to_kaddr(pfn), 0, nr_pages << PAGE_SHIFT);
- break;
- } else if (ret != -EBUSY) {
- break;
- }
- pr_debug("%s(): memory range at %p is busy, retrying\n",
- __func__, pfn_to_page(pfn));
- /* try again with a bit different memory target */
- start = pageno + mask + 1;
- }
- mutex_unlock(&kvm_cma_mutex);
- pr_debug("%s(): returned %p\n", __func__, page);
- return page;
-}
-
-/**
- * kvm_release_cma() - release allocated pages for hash pagetable
- * @pages: Allocated pages.
- * @nr_pages: Number of allocated pages.
- *
- * This function releases memory allocated by kvm_alloc_cma().
- * It returns false when provided pages do not belong to contiguous area and
- * true otherwise.
- */
-bool kvm_release_cma(struct page *pages, unsigned long nr_pages)
-{
- unsigned long pfn;
- unsigned long nr_chunk;
- struct kvm_cma *cma = &kvm_cma_area;
-
- if (!cma || !pages)
- return false;
-
- pr_debug("%s(page %p count %lu)\n", __func__, (void *)pages, nr_pages);
-
- pfn = page_to_pfn(pages);
-
- if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
- return false;
-
- VM_BUG_ON(pfn + nr_pages > cma->base_pfn + cma->count);
- nr_chunk = nr_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
-
- mutex_lock(&kvm_cma_mutex);
- bitmap_clear(cma->bitmap,
- (pfn - cma->base_pfn) >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT),
- nr_chunk);
- free_contig_range(pfn, nr_pages);
- mutex_unlock(&kvm_cma_mutex);
-
- return true;
-}
-
-static int __init kvm_cma_activate_area(unsigned long base_pfn,
- unsigned long count)
-{
- unsigned long pfn = base_pfn;
- unsigned i = count >> pageblock_order;
- struct zone *zone;
-
- WARN_ON_ONCE(!pfn_valid(pfn));
- zone = page_zone(pfn_to_page(pfn));
- do {
- unsigned j;
- base_pfn = pfn;
- for (j = pageblock_nr_pages; j; --j, pfn++) {
- WARN_ON_ONCE(!pfn_valid(pfn));
- /*
- * alloc_contig_range requires the pfn range
- * specified to be in the same zone. Make this
- * simple by forcing the entire CMA resv range
- * to be in the same zone.
- */
- if (page_zone(pfn_to_page(pfn)) != zone)
- return -EINVAL;
- }
- init_cma_reserved_pageblock(pfn_to_page(base_pfn));
- } while (--i);
- return 0;
-}
-
-static int __init kvm_cma_init_reserved_areas(void)
-{
- int bitmap_size, ret;
- unsigned long chunk_count;
- struct kvm_cma *cma = &kvm_cma_area;
-
- pr_debug("%s()\n", __func__);
- if (!cma->count)
- return 0;
- chunk_count = cma->count >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT);
- bitmap_size = BITS_TO_LONGS(chunk_count) * sizeof(long);
- cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!cma->bitmap)
- return -ENOMEM;
-
- ret = kvm_cma_activate_area(cma->base_pfn, cma->count);
- if (ret)
- goto error;
- return 0;
-
-error:
- kfree(cma->bitmap);
- return ret;
-}
-core_initcall(kvm_cma_init_reserved_areas);
diff --git a/arch/powerpc/kvm/book3s_hv_cma.h b/arch/powerpc/kvm/book3s_hv_cma.h
deleted file mode 100644
index 655144f75fa5..000000000000
--- a/arch/powerpc/kvm/book3s_hv_cma.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA
- * for DMA mapping framework
- *
- * Copyright IBM Corporation, 2013
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.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 optional) any later version of the license.
- *
- */
-
-#ifndef __POWERPC_KVM_CMA_ALLOC_H__
-#define __POWERPC_KVM_CMA_ALLOC_H__
-/*
- * Both RMA and Hash page allocation will be multiple of 256K.
- */
-#define KVM_CMA_CHUNK_ORDER 18
-
-extern struct page *kvm_alloc_cma(unsigned long nr_pages,
- unsigned long align_pages);
-extern bool kvm_release_cma(struct page *pages, unsigned long nr_pages);
-extern long kvm_cma_declare_contiguous(phys_addr_t size,
- phys_addr_t alignment) __init;
-#endif
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index 3a5c568b1e89..d562c8e2bc30 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *vcpu)
return;
/* Sanity check */
- n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+ n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end)
return;
/* Load up the SLB from that */
for (i = 0; i < n; ++i) {
- unsigned long rb = slb->save_area[i].esid;
- unsigned long rs = slb->save_area[i].vsid;
+ unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
+ unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
rb = (rb & ~0xFFFul) | i; /* insert entry number */
asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 5a24d3c2b6b8..084ad54c73cd 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -154,10 +154,10 @@ static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva,
return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift);
}
-static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v)
+static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v)
{
asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
- hpte[0] = hpte_v;
+ hpte[0] = cpu_to_be64(hpte_v);
}
long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
@@ -166,7 +166,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
{
unsigned long i, pa, gpa, gfn, psize;
unsigned long slot_fn, hva;
- unsigned long *hpte;
+ __be64 *hpte;
struct revmap_entry *rev;
unsigned long g_ptel;
struct kvm_memory_slot *memslot;
@@ -275,9 +275,9 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
return H_PARAMETER;
if (likely((flags & H_EXACT) == 0)) {
pte_index &= ~7UL;
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
for (i = 0; i < 8; ++i) {
- if ((*hpte & HPTE_V_VALID) == 0 &&
+ if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 &&
try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
HPTE_V_ABSENT))
break;
@@ -292,11 +292,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
*/
hpte -= 16;
for (i = 0; i < 8; ++i) {
+ u64 pte;
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
cpu_relax();
- if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)))
+ pte = be64_to_cpu(*hpte);
+ if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT)))
break;
- *hpte &= ~HPTE_V_HVLOCK;
+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
hpte += 2;
}
if (i == 8)
@@ -304,14 +306,17 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
}
pte_index += i;
} else {
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID |
HPTE_V_ABSENT)) {
/* Lock the slot and check again */
+ u64 pte;
+
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
cpu_relax();
- if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
- *hpte &= ~HPTE_V_HVLOCK;
+ pte = be64_to_cpu(*hpte);
+ if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
return H_PTEG_FULL;
}
}
@@ -347,11 +352,11 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
}
}
- hpte[1] = ptel;
+ hpte[1] = cpu_to_be64(ptel);
/* Write the first HPTE dword, unlocking the HPTE and making it valid */
eieio();
- hpte[0] = pteh;
+ hpte[0] = cpu_to_be64(pteh);
asm volatile("ptesync" : : : "memory");
*pte_idx_ret = pte_index;
@@ -468,30 +473,35 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
unsigned long pte_index, unsigned long avpn,
unsigned long *hpret)
{
- unsigned long *hpte;
+ __be64 *hpte;
unsigned long v, r, rb;
struct revmap_entry *rev;
+ u64 pte;
if (pte_index >= kvm->arch.hpt_npte)
return H_PARAMETER;
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
cpu_relax();
- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
- ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
- hpte[0] &= ~HPTE_V_HVLOCK;
+ pte = be64_to_cpu(hpte[0]);
+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
+ ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
return H_NOT_FOUND;
}
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
- v = hpte[0] & ~HPTE_V_HVLOCK;
+ v = pte & ~HPTE_V_HVLOCK;
if (v & HPTE_V_VALID) {
- hpte[0] &= ~HPTE_V_VALID;
- rb = compute_tlbie_rb(v, hpte[1], pte_index);
+ u64 pte1;
+
+ pte1 = be64_to_cpu(hpte[1]);
+ hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
+ rb = compute_tlbie_rb(v, pte1, pte_index);
do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
/* Read PTE low word after tlbie to get final R/C values */
- remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
+ remove_revmap_chain(kvm, pte_index, rev, v, pte1);
}
r = rev->guest_rpte & ~HPTE_GR_RESERVED;
note_hpte_modification(kvm, rev);
@@ -514,12 +524,14 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
unsigned long *args = &vcpu->arch.gpr[4];
- unsigned long *hp, *hptes[4], tlbrb[4];
+ __be64 *hp, *hptes[4];
+ unsigned long tlbrb[4];
long int i, j, k, n, found, indexes[4];
unsigned long flags, req, pte_index, rcbits;
int global;
long int ret = H_SUCCESS;
struct revmap_entry *rev, *revs[4];
+ u64 hp0;
global = global_invalidates(kvm, 0);
for (i = 0; i < 4 && ret == H_SUCCESS; ) {
@@ -542,8 +554,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
ret = H_PARAMETER;
break;
}
- hp = (unsigned long *)
- (kvm->arch.hpt_virt + (pte_index << 4));
+ hp = (__be64 *) (kvm->arch.hpt_virt + (pte_index << 4));
/* to avoid deadlock, don't spin except for first */
if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) {
if (n)
@@ -552,23 +563,24 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
cpu_relax();
}
found = 0;
- if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) {
+ hp0 = be64_to_cpu(hp[0]);
+ if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) {
switch (flags & 3) {
case 0: /* absolute */
found = 1;
break;
case 1: /* andcond */
- if (!(hp[0] & args[j + 1]))
+ if (!(hp0 & args[j + 1]))
found = 1;
break;
case 2: /* AVPN */
- if ((hp[0] & ~0x7fUL) == args[j + 1])
+ if ((hp0 & ~0x7fUL) == args[j + 1])
found = 1;
break;
}
}
if (!found) {
- hp[0] &= ~HPTE_V_HVLOCK;
+ hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
args[j] = ((0x90 | flags) << 56) + pte_index;
continue;
}
@@ -577,7 +589,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
note_hpte_modification(kvm, rev);
- if (!(hp[0] & HPTE_V_VALID)) {
+ if (!(hp0 & HPTE_V_VALID)) {
/* insert R and C bits from PTE */
rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
args[j] |= rcbits << (56 - 5);
@@ -585,8 +597,10 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
continue;
}
- hp[0] &= ~HPTE_V_VALID; /* leave it locked */
- tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
+ /* leave it locked */
+ hp[0] &= ~cpu_to_be64(HPTE_V_VALID);
+ tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]),
+ be64_to_cpu(hp[1]), pte_index);
indexes[n] = j;
hptes[n] = hp;
revs[n] = rev;
@@ -605,7 +619,8 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
pte_index = args[j] & ((1ul << 56) - 1);
hp = hptes[k];
rev = revs[k];
- remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
+ remove_revmap_chain(kvm, pte_index, rev,
+ be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
args[j] |= rcbits << (56 - 5);
hp[0] = 0;
@@ -620,23 +635,25 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long va)
{
struct kvm *kvm = vcpu->kvm;
- unsigned long *hpte;
+ __be64 *hpte;
struct revmap_entry *rev;
unsigned long v, r, rb, mask, bits;
+ u64 pte;
if (pte_index >= kvm->arch.hpt_npte)
return H_PARAMETER;
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
cpu_relax();
- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
- hpte[0] &= ~HPTE_V_HVLOCK;
+ pte = be64_to_cpu(hpte[0]);
+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
return H_NOT_FOUND;
}
- v = hpte[0];
+ v = pte;
bits = (flags << 55) & HPTE_R_PP0;
bits |= (flags << 48) & HPTE_R_KEY_HI;
bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
@@ -650,12 +667,12 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
rev->guest_rpte = r;
note_hpte_modification(kvm, rev);
}
- r = (hpte[1] & ~mask) | bits;
+ r = (be64_to_cpu(hpte[1]) & ~mask) | bits;
/* Update HPTE */
if (v & HPTE_V_VALID) {
rb = compute_tlbie_rb(v, r, pte_index);
- hpte[0] = v & ~HPTE_V_VALID;
+ hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID);
do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
/*
* If the host has this page as readonly but the guest
@@ -681,9 +698,9 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
}
}
}
- hpte[1] = r;
+ hpte[1] = cpu_to_be64(r);
eieio();
- hpte[0] = v & ~HPTE_V_HVLOCK;
+ hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK);
asm volatile("ptesync" : : : "memory");
return H_SUCCESS;
}
@@ -692,7 +709,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long pte_index)
{
struct kvm *kvm = vcpu->kvm;
- unsigned long *hpte, v, r;
+ __be64 *hpte;
+ unsigned long v, r;
int i, n = 1;
struct revmap_entry *rev = NULL;
@@ -704,9 +722,9 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
}
rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
for (i = 0; i < n; ++i, ++pte_index) {
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
- v = hpte[0] & ~HPTE_V_HVLOCK;
- r = hpte[1];
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
+ r = be64_to_cpu(hpte[1]);
if (v & HPTE_V_ABSENT) {
v &= ~HPTE_V_ABSENT;
v |= HPTE_V_VALID;
@@ -721,25 +739,27 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
return H_SUCCESS;
}
-void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep,
unsigned long pte_index)
{
unsigned long rb;
- hptep[0] &= ~HPTE_V_VALID;
- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
+ hptep[0] &= ~cpu_to_be64(HPTE_V_VALID);
+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+ pte_index);
do_tlbies(kvm, &rb, 1, 1, true);
}
EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
-void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep,
+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep,
unsigned long pte_index)
{
unsigned long rb;
unsigned char rbyte;
- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index);
- rbyte = (hptep[1] & ~HPTE_R_R) >> 8;
+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
+ pte_index);
+ rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8;
/* modify only the second-last byte, which contains the ref bit */
*((char *)hptep + 14) = rbyte;
do_tlbies(kvm, &rb, 1, 1, false);
@@ -765,7 +785,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
unsigned long somask;
unsigned long vsid, hash;
unsigned long avpn;
- unsigned long *hpte;
+ __be64 *hpte;
unsigned long mask, val;
unsigned long v, r;
@@ -797,11 +817,11 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
val |= avpn;
for (;;) {
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7));
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (hash << 7));
for (i = 0; i < 16; i += 2) {
/* Read the PTE racily */
- v = hpte[i] & ~HPTE_V_HVLOCK;
+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
/* Check valid/absent, hash, segment size and AVPN */
if (!(v & valid) || (v & mask) != val)
@@ -810,8 +830,8 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
/* Lock the PTE and read it under the lock */
while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
cpu_relax();
- v = hpte[i] & ~HPTE_V_HVLOCK;
- r = hpte[i+1];
+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
+ r = be64_to_cpu(hpte[i+1]);
/*
* Check the HPTE again, including base page size
@@ -822,7 +842,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
return (hash << 3) + (i >> 1);
/* Unlock and move on */
- hpte[i] = v;
+ hpte[i] = cpu_to_be64(v);
}
if (val & HPTE_V_SECONDARY)
@@ -851,7 +871,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
struct kvm *kvm = vcpu->kvm;
long int index;
unsigned long v, r, gr;
- unsigned long *hpte;
+ __be64 *hpte;
unsigned long valid;
struct revmap_entry *rev;
unsigned long pp, key;
@@ -867,9 +887,9 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
return status; /* there really was no HPTE */
return 0; /* for prot fault, HPTE disappeared */
}
- hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
- v = hpte[0] & ~HPTE_V_HVLOCK;
- r = hpte[1];
+ hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
+ r = be64_to_cpu(hpte[1]);
rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
gr = rev->guest_rpte;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index b4b0082f761c..3ee38e6e884f 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
@@ -401,6 +401,11 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
icp->rm_action |= XICS_RM_REJECT;
icp->rm_reject = irq;
}
+
+ if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) {
+ icp->rm_action |= XICS_RM_NOTIFY_EOI;
+ icp->rm_eoied_irq = irq;
+ }
bail:
return check_too_hard(xics, icp);
}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 558a67df8126..f0c4db7704c3 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -32,10 +32,6 @@
#define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
-#ifdef __LITTLE_ENDIAN__
-#error Need to fix lppaca and SLB shadow accesses in little endian mode
-#endif
-
/* Values in HSTATE_NAPPING(r13) */
#define NAPPING_CEDE 1
#define NAPPING_NOVCPU 2
@@ -159,6 +155,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
BEGIN_FTR_SECTION
beq 11f
+ cmpwi cr2, r12, BOOK3S_INTERRUPT_HMI
+ beq cr2, 14f /* HMI check */
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
/* RFI into the highmem handler, or branch to interrupt handler */
@@ -179,6 +177,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
13: b machine_check_fwnmi
+14: mtspr SPRN_HSRR0, r8
+ mtspr SPRN_HSRR1, r7
+ b hmi_exception_after_realmode
+
kvmppc_primary_no_guest:
/* We handle this much like a ceded vcpu */
/* set our bit in napping_threads */
@@ -595,9 +597,10 @@ kvmppc_got_guest:
ld r3, VCPU_VPA(r4)
cmpdi r3, 0
beq 25f
- lwz r5, LPPACA_YIELDCOUNT(r3)
+ li r6, LPPACA_YIELDCOUNT
+ LWZX_BE r5, r3, r6
addi r5, r5, 1
- stw r5, LPPACA_YIELDCOUNT(r3)
+ STWX_BE r5, r3, r6
li r6, 1
stb r6, VCPU_VPA_DIRTY(r4)
25:
@@ -671,9 +674,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
mr r31, r4
addi r3, r31, VCPU_FPRS_TM
- bl .load_fp_state
+ bl load_fp_state
addi r3, r31, VCPU_VRS_TM
- bl .load_vr_state
+ bl load_vr_state
mr r4, r31
lwz r7, VCPU_VRSAVE_TM(r4)
mtspr SPRN_VRSAVE, r7
@@ -1417,9 +1420,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
/* Save FP/VSX. */
addi r3, r9, VCPU_FPRS_TM
- bl .store_fp_state
+ bl store_fp_state
addi r3, r9, VCPU_VRS_TM
- bl .store_vr_state
+ bl store_vr_state
mfspr r6, SPRN_VRSAVE
stw r6, VCPU_VRSAVE_TM(r9)
1:
@@ -1442,9 +1445,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM)
ld r8, VCPU_VPA(r9) /* do they have a VPA? */
cmpdi r8, 0
beq 25f
- lwz r3, LPPACA_YIELDCOUNT(r8)
+ li r4, LPPACA_YIELDCOUNT
+ LWZX_BE r3, r8, r4
addi r3, r3, 1
- stw r3, LPPACA_YIELDCOUNT(r8)
+ STWX_BE r3, r8, r4
li r3, 1
stb r3, VCPU_VPA_DIRTY(r9)
25:
@@ -1757,8 +1761,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
33: ld r8,PACA_SLBSHADOWPTR(r13)
.rept SLB_NUM_BOLTED
- ld r5,SLBSHADOW_SAVEAREA(r8)
- ld r6,SLBSHADOW_SAVEAREA+8(r8)
+ li r3, SLBSHADOW_SAVEAREA
+ LDX_BE r5, r8, r3
+ addi r3, r3, 8
+ LDX_BE r6, r8, r3
andis. r7,r5,SLB_ESID_V@h
beq 1f
slbmte r6,r5
@@ -1909,12 +1915,23 @@ hcall_try_real_mode:
clrrdi r3,r3,2
cmpldi r3,hcall_real_table_end - hcall_real_table
bge guest_exit_cont
+ /* See if this hcall is enabled for in-kernel handling */
+ ld r4, VCPU_KVM(r9)
+ srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */
+ sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */
+ add r4, r4, r0
+ ld r0, KVM_ENABLED_HCALLS(r4)
+ rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */
+ srd r0, r0, r4
+ andi. r0, r0, 1
+ beq guest_exit_cont
+ /* Get pointer to handler, if any, and call it */
LOAD_REG_ADDR(r4, hcall_real_table)
lwax r3,r3,r4
cmpwi r3,0
beq guest_exit_cont
- add r3,r3,r4
- mtctr r3
+ add r12,r3,r4
+ mtctr r12
mr r3,r9 /* get vcpu pointer */
ld r4,VCPU_GPR(R4)(r9)
bctrl
@@ -2031,6 +2048,7 @@ hcall_real_table:
.long 0 /* 0x12c */
.long 0 /* 0x130 */
.long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
+ .globl hcall_real_table_end
hcall_real_table_end:
ignore_hdec:
@@ -2338,7 +2356,18 @@ kvmppc_read_intr:
cmpdi r6, 0
beq- 1f
lwzcix r0, r6, r7
- rlwinm. r3, r0, 0, 0xffffff
+ /*
+ * Save XIRR for later. Since we get in in reverse endian on LE
+ * systems, save it byte reversed and fetch it back in host endian.
+ */
+ li r3, HSTATE_SAVED_XIRR
+ STWX_BE r0, r3, r13
+#ifdef __LITTLE_ENDIAN__
+ lwz r3, HSTATE_SAVED_XIRR(r13)
+#else
+ mr r3, r0
+#endif
+ rlwinm. r3, r3, 0, 0xffffff
sync
beq 1f /* if nothing pending in the ICP */
@@ -2370,10 +2399,9 @@ kvmppc_read_intr:
li r3, -1
1: blr
-42: /* It's not an IPI and it's for the host, stash it in the PACA
- * before exit, it will be picked up by the host ICP driver
+42: /* It's not an IPI and it's for the host. We saved a copy of XIRR in
+ * the PACA earlier, it will be picked up by the host ICP driver
*/
- stw r0, HSTATE_SAVED_XIRR(r13)
li r3, 1
b 1b
@@ -2408,11 +2436,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
mtmsrd r8
isync
addi r3,r3,VCPU_FPRS
- bl .store_fp_state
+ bl store_fp_state
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
addi r3,r31,VCPU_VRS
- bl .store_vr_state
+ bl store_vr_state
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
mfspr r6,SPRN_VRSAVE
@@ -2444,11 +2472,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
mtmsrd r8
isync
addi r3,r4,VCPU_FPRS
- bl .load_fp_state
+ bl load_fp_state
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
addi r3,r31,VCPU_VRS
- bl .load_vr_state
+ bl load_vr_state
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif
lwz r7,VCPU_VRSAVE(r31)
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index 6c8011fd57e6..bfb8035314e3 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -639,26 +639,36 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
- u32 inst = kvmppc_get_last_inst(vcpu);
+ u32 inst;
enum emulation_result emulated = EMULATE_DONE;
+ int ax_rd, ax_ra, ax_rb, ax_rc;
+ short full_d;
+ u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c;
- int ax_rd = inst_get_field(inst, 6, 10);
- int ax_ra = inst_get_field(inst, 11, 15);
- int ax_rb = inst_get_field(inst, 16, 20);
- int ax_rc = inst_get_field(inst, 21, 25);
- short full_d = inst_get_field(inst, 16, 31);
-
- u64 *fpr_d = &VCPU_FPR(vcpu, ax_rd);
- u64 *fpr_a = &VCPU_FPR(vcpu, ax_ra);
- u64 *fpr_b = &VCPU_FPR(vcpu, ax_rb);
- u64 *fpr_c = &VCPU_FPR(vcpu, ax_rc);
-
- bool rcomp = (inst & 1) ? true : false;
- u32 cr = kvmppc_get_cr(vcpu);
+ bool rcomp;
+ u32 cr;
#ifdef DEBUG
int i;
#endif
+ emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst);
+ if (emulated != EMULATE_DONE)
+ return emulated;
+
+ ax_rd = inst_get_field(inst, 6, 10);
+ ax_ra = inst_get_field(inst, 11, 15);
+ ax_rb = inst_get_field(inst, 16, 20);
+ ax_rc = inst_get_field(inst, 21, 25);
+ full_d = inst_get_field(inst, 16, 31);
+
+ fpr_d = &VCPU_FPR(vcpu, ax_rd);
+ fpr_a = &VCPU_FPR(vcpu, ax_ra);
+ fpr_b = &VCPU_FPR(vcpu, ax_rb);
+ fpr_c = &VCPU_FPR(vcpu, ax_rc);
+
+ rcomp = (inst & 1) ? true : false;
+ cr = kvmppc_get_cr(vcpu);
+
if (!kvmppc_inst_is_paired_single(vcpu, inst))
return EMULATE_FAIL;
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 8eef1e519077..faffb27badd9 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -62,6 +62,35 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
#define HW_PAGE_SIZE PAGE_SIZE
#endif
+static bool kvmppc_is_split_real(struct kvm_vcpu *vcpu)
+{
+ ulong msr = kvmppc_get_msr(vcpu);
+ return (msr & (MSR_IR|MSR_DR)) == MSR_DR;
+}
+
+static void kvmppc_fixup_split_real(struct kvm_vcpu *vcpu)
+{
+ ulong msr = kvmppc_get_msr(vcpu);
+ ulong pc = kvmppc_get_pc(vcpu);
+
+ /* We are in DR only split real mode */
+ if ((msr & (MSR_IR|MSR_DR)) != MSR_DR)
+ return;
+
+ /* We have not fixed up the guest already */
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK)
+ return;
+
+ /* The code is in fixupable address space */
+ if (pc & SPLIT_HACK_MASK)
+ return;
+
+ vcpu->arch.hflags |= BOOK3S_HFLAG_SPLIT_HACK;
+ kvmppc_set_pc(vcpu, pc | SPLIT_HACK_OFFS);
+}
+
+void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu);
+
static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
{
#ifdef CONFIG_PPC_BOOK3S_64
@@ -71,10 +100,19 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
svcpu->in_use = 0;
svcpu_put(svcpu);
#endif
+
+ /* Disable AIL if supported */
+ if (cpu_has_feature(CPU_FTR_HVMODE) &&
+ cpu_has_feature(CPU_FTR_ARCH_207S))
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
+
vcpu->cpu = smp_processor_id();
#ifdef CONFIG_PPC_BOOK3S_32
current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu;
#endif
+
+ if (kvmppc_is_split_real(vcpu))
+ kvmppc_fixup_split_real(vcpu);
}
static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
@@ -89,8 +127,17 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
svcpu_put(svcpu);
#endif
+ if (kvmppc_is_split_real(vcpu))
+ kvmppc_unfixup_split_real(vcpu);
+
kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+
+ /* Enable AIL if supported */
+ if (cpu_has_feature(CPU_FTR_HVMODE) &&
+ cpu_has_feature(CPU_FTR_ARCH_207S))
+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
+
vcpu->cpu = -1;
}
@@ -120,6 +167,14 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
#ifdef CONFIG_PPC_BOOK3S_64
svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
#endif
+ /*
+ * Now also save the current time base value. We use this
+ * to find the guest purr and spurr value.
+ */
+ vcpu->arch.entry_tb = get_tb();
+ vcpu->arch.entry_vtb = get_vtb();
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ vcpu->arch.entry_ic = mfspr(SPRN_IC);
svcpu->in_use = true;
}
@@ -166,6 +221,14 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
#ifdef CONFIG_PPC_BOOK3S_64
vcpu->arch.shadow_fscr = svcpu->shadow_fscr;
#endif
+ /*
+ * Update purr and spurr using time base on exit.
+ */
+ vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb;
+ vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb;
+ vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb;
+ if (cpu_has_feature(CPU_FTR_ARCH_207S))
+ vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic;
svcpu->in_use = false;
out:
@@ -294,6 +357,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
}
}
+ if (kvmppc_is_split_real(vcpu))
+ kvmppc_fixup_split_real(vcpu);
+ else
+ kvmppc_unfixup_split_real(vcpu);
+
if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) !=
(old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
kvmppc_mmu_flush_segments(vcpu);
@@ -443,19 +511,19 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
put_page(hpage);
}
-static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
+static int kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
{
ulong mp_pa = vcpu->arch.magic_page_pa;
if (!(kvmppc_get_msr(vcpu) & MSR_SF))
mp_pa = (uint32_t)mp_pa;
- if (unlikely(mp_pa) &&
- unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) {
+ gpa &= ~0xFFFULL;
+ if (unlikely(mp_pa) && unlikely((mp_pa & KVM_PAM) == (gpa & KVM_PAM))) {
return 1;
}
- return kvm_is_visible_gfn(vcpu->kvm, gfn);
+ return kvm_is_visible_gfn(vcpu->kvm, gpa >> PAGE_SHIFT);
}
int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -494,6 +562,11 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
break;
case MSR_DR:
+ if (!data &&
+ (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) &&
+ ((pte.raddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS))
+ pte.raddr &= ~SPLIT_HACK_MASK;
+ /* fall through */
case MSR_IR:
vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
@@ -541,7 +614,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio &&
- kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
+ kvmppc_visible_gpa(vcpu, pte.raddr)) {
if (data && !(vcpu->arch.fault_dsisr & DSISR_NOHPTE)) {
/*
* There is already a host HPTE there, presumably
@@ -637,42 +710,6 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
#endif
}
-static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
-{
- ulong srr0 = kvmppc_get_pc(vcpu);
- u32 last_inst = kvmppc_get_last_inst(vcpu);
- int ret;
-
- ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
- if (ret == -ENOENT) {
- ulong msr = kvmppc_get_msr(vcpu);
-
- msr = kvmppc_set_field(msr, 33, 33, 1);
- msr = kvmppc_set_field(msr, 34, 36, 0);
- msr = kvmppc_set_field(msr, 42, 47, 0);
- kvmppc_set_msr_fast(vcpu, msr);
- kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
- return EMULATE_AGAIN;
- }
-
- return EMULATE_DONE;
-}
-
-static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr)
-{
-
- /* Need to do paired single emulation? */
- if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE))
- return EMULATE_DONE;
-
- /* Read out the instruction */
- if (kvmppc_read_inst(vcpu) == EMULATE_DONE)
- /* Need to emulate */
- return EMULATE_FAIL;
-
- return EMULATE_AGAIN;
-}
-
/* Handle external providers (FPU, Altivec, VSX) */
static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
ulong msr)
@@ -834,6 +871,15 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
return RESUME_GUEST;
}
+
+void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr)
+{
+ if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) {
+ /* TAR got dropped, drop it in shadow too */
+ kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+ }
+ vcpu->arch.fscr = fscr;
+}
#endif
int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
@@ -858,6 +904,9 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
ulong shadow_srr1 = vcpu->arch.shadow_srr1;
vcpu->stat.pf_instruc++;
+ if (kvmppc_is_split_real(vcpu))
+ kvmppc_fixup_split_real(vcpu);
+
#ifdef CONFIG_PPC_BOOK3S_32
/* We set segments as unused segments when invalidating them. So
* treat the respective fault as segment fault. */
@@ -960,6 +1009,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
case BOOK3S_INTERRUPT_DECREMENTER:
case BOOK3S_INTERRUPT_HV_DECREMENTER:
case BOOK3S_INTERRUPT_DOORBELL:
+ case BOOK3S_INTERRUPT_H_DOORBELL:
vcpu->stat.dec_exits++;
r = RESUME_GUEST;
break;
@@ -977,15 +1027,24 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
{
enum emulation_result er;
ulong flags;
+ u32 last_inst;
+ int emul;
program_interrupt:
flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
+ emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
+ if (emul != EMULATE_DONE) {
+ r = RESUME_GUEST;
+ break;
+ }
+
if (kvmppc_get_msr(vcpu) & MSR_PR) {
#ifdef EXIT_DEBUG
- printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+ pr_info("Userspace triggered 0x700 exception at\n 0x%lx (0x%x)\n",
+ kvmppc_get_pc(vcpu), last_inst);
#endif
- if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) !=
+ if ((last_inst & 0xff0007ff) !=
(INS_DCBZ & 0xfffffff7)) {
kvmppc_core_queue_program(vcpu, flags);
r = RESUME_GUEST;
@@ -1004,7 +1063,7 @@ program_interrupt:
break;
case EMULATE_FAIL:
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
- __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
+ __func__, kvmppc_get_pc(vcpu), last_inst);
kvmppc_core_queue_program(vcpu, flags);
r = RESUME_GUEST;
break;
@@ -1021,8 +1080,23 @@ program_interrupt:
break;
}
case BOOK3S_INTERRUPT_SYSCALL:
+ {
+ u32 last_sc;
+ int emul;
+
+ /* Get last sc for papr */
+ if (vcpu->arch.papr_enabled) {
+ /* The sc instuction points SRR0 to the next inst */
+ emul = kvmppc_get_last_inst(vcpu, INST_SC, &last_sc);
+ if (emul != EMULATE_DONE) {
+ kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) - 4);
+ r = RESUME_GUEST;
+ break;
+ }
+ }
+
if (vcpu->arch.papr_enabled &&
- (kvmppc_get_last_sc(vcpu) == 0x44000022) &&
+ (last_sc == 0x44000022) &&
!(kvmppc_get_msr(vcpu) & MSR_PR)) {
/* SC 1 papr hypercalls */
ulong cmd = kvmppc_get_gpr(vcpu, 3);
@@ -1067,36 +1141,51 @@ program_interrupt:
r = RESUME_GUEST;
}
break;
+ }
case BOOK3S_INTERRUPT_FP_UNAVAIL:
case BOOK3S_INTERRUPT_ALTIVEC:
case BOOK3S_INTERRUPT_VSX:
{
int ext_msr = 0;
+ int emul;
+ u32 last_inst;
+
+ if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) {
+ /* Do paired single instruction emulation */
+ emul = kvmppc_get_last_inst(vcpu, INST_GENERIC,
+ &last_inst);
+ if (emul == EMULATE_DONE)
+ goto program_interrupt;
+ else
+ r = RESUME_GUEST;
- switch (exit_nr) {
- case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break;
- case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break;
- case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break;
+ break;
}
- switch (kvmppc_check_ext(vcpu, exit_nr)) {
- case EMULATE_DONE:
- /* everything ok - let's enable the ext */
- r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
+ /* Enable external provider */
+ switch (exit_nr) {
+ case BOOK3S_INTERRUPT_FP_UNAVAIL:
+ ext_msr = MSR_FP;
break;
- case EMULATE_FAIL:
- /* we need to emulate this instruction */
- goto program_interrupt;
+
+ case BOOK3S_INTERRUPT_ALTIVEC:
+ ext_msr = MSR_VEC;
break;
- default:
- /* nothing to worry about - go again */
+
+ case BOOK3S_INTERRUPT_VSX:
+ ext_msr = MSR_VSX;
break;
}
+
+ r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr);
break;
}
case BOOK3S_INTERRUPT_ALIGNMENT:
- if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
- u32 last_inst = kvmppc_get_last_inst(vcpu);
+ {
+ u32 last_inst;
+ int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
+
+ if (emul == EMULATE_DONE) {
u32 dsisr;
u64 dar;
@@ -1110,6 +1199,7 @@ program_interrupt:
}
r = RESUME_GUEST;
break;
+ }
#ifdef CONFIG_PPC_BOOK3S_64
case BOOK3S_INTERRUPT_FAC_UNAVAIL:
kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
@@ -1233,6 +1323,7 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, to_book3s(vcpu)->hior);
break;
case KVM_REG_PPC_LPCR:
+ case KVM_REG_PPC_LPCR_64:
/*
* We are only interested in the LPCR_ILE bit
*/
@@ -1268,6 +1359,7 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
to_book3s(vcpu)->hior_explicit = true;
break;
case KVM_REG_PPC_LPCR:
+ case KVM_REG_PPC_LPCR_64:
kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
break;
default:
@@ -1310,8 +1402,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
p = __get_free_page(GFP_KERNEL|__GFP_ZERO);
if (!p)
goto uninit_vcpu;
- /* the real shared page fills the last 4k of our page */
- vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096);
+ vcpu->arch.shared = (void *)p;
#ifdef CONFIG_PPC_BOOK3S_64
/* Always start the shared struct in native endian mode */
#ifdef __BIG_ENDIAN__
@@ -1568,6 +1659,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm)
{
mutex_init(&kvm->arch.hpt_mutex);
+#ifdef CONFIG_PPC_BOOK3S_64
+ /* Start out with the default set of hcalls enabled */
+ kvmppc_pr_init_default_hcalls(kvm);
+#endif
+
if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
spin_lock(&kvm_global_user_count_lock);
if (++kvm_global_user_count == 1)
@@ -1636,6 +1732,9 @@ static struct kvmppc_ops kvm_ops_pr = {
.emulate_mfspr = kvmppc_core_emulate_mfspr_pr,
.fast_vcpu_kick = kvm_vcpu_kick,
.arch_vm_ioctl = kvm_arch_vm_ioctl_pr,
+#ifdef CONFIG_PPC_BOOK3S_64
+ .hcall_implemented = kvmppc_hcall_impl_pr,
+#endif
};
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c
index 52a63bfe3f07..ce3c893d509b 100644
--- a/arch/powerpc/kvm/book3s_pr_papr.c
+++ b/arch/powerpc/kvm/book3s_pr_papr.c
@@ -40,8 +40,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
{
long flags = kvmppc_get_gpr(vcpu, 4);
long pte_index = kvmppc_get_gpr(vcpu, 5);
- unsigned long pteg[2 * 8];
- unsigned long pteg_addr, i, *hpte;
+ __be64 pteg[2 * 8];
+ __be64 *hpte;
+ unsigned long pteg_addr, i;
long int ret;
i = pte_index & 7;
@@ -93,8 +94,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
- pte[0] = be64_to_cpu(pte[0]);
- pte[1] = be64_to_cpu(pte[1]);
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
ret = H_NOT_FOUND;
if ((pte[0] & HPTE_V_VALID) == 0 ||
@@ -171,8 +172,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
- pte[0] = be64_to_cpu(pte[0]);
- pte[1] = be64_to_cpu(pte[1]);
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
/* tsl = AVPN */
flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
@@ -211,8 +212,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
- pte[0] = be64_to_cpu(pte[0]);
- pte[1] = be64_to_cpu(pte[1]);
+ pte[0] = be64_to_cpu((__force __be64)pte[0]);
+ pte[1] = be64_to_cpu((__force __be64)pte[1]);
ret = H_NOT_FOUND;
if ((pte[0] & HPTE_V_VALID) == 0 ||
@@ -231,8 +232,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
rb = compute_tlbie_rb(v, r, pte_index);
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
- pte[0] = cpu_to_be64(pte[0]);
- pte[1] = cpu_to_be64(pte[1]);
+ pte[0] = (__force u64)cpu_to_be64(pte[0]);
+ pte[1] = (__force u64)cpu_to_be64(pte[1]);
copy_to_user((void __user *)pteg, pte, sizeof(pte));
ret = H_SUCCESS;
@@ -266,6 +267,12 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
{
+ int rc, idx;
+
+ if (cmd <= MAX_HCALL_OPCODE &&
+ !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls))
+ return EMULATE_FAIL;
+
switch (cmd) {
case H_ENTER:
return kvmppc_h_pr_enter(vcpu);
@@ -294,8 +301,11 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
break;
case H_RTAS:
if (list_empty(&vcpu->kvm->arch.rtas_tokens))
- return RESUME_HOST;
- if (kvmppc_rtas_hcall(vcpu))
+ break;
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+ rc = kvmppc_rtas_hcall(vcpu);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+ if (rc)
break;
kvmppc_set_gpr(vcpu, 3, 0);
return EMULATE_DONE;
@@ -303,3 +313,61 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
return EMULATE_FAIL;
}
+
+int kvmppc_hcall_impl_pr(unsigned long cmd)
+{
+ switch (cmd) {
+ case H_ENTER:
+ case H_REMOVE:
+ case H_PROTECT:
+ case H_BULK_REMOVE:
+ case H_PUT_TCE:
+ case H_CEDE:
+#ifdef CONFIG_KVM_XICS
+ case H_XIRR:
+ case H_CPPR:
+ case H_EOI:
+ case H_IPI:
+ case H_IPOLL:
+ case H_XIRR_X:
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * List of hcall numbers to enable by default.
+ * For compatibility with old userspace, we enable by default
+ * all hcalls that were implemented before the hcall-enabling
+ * facility was added. Note this list should not include H_RTAS.
+ */
+static unsigned int default_hcall_list[] = {
+ H_ENTER,
+ H_REMOVE,
+ H_PROTECT,
+ H_BULK_REMOVE,
+ H_PUT_TCE,
+ H_CEDE,
+#ifdef CONFIG_KVM_XICS
+ H_XIRR,
+ H_CPPR,
+ H_EOI,
+ H_IPI,
+ H_IPOLL,
+ H_XIRR_X,
+#endif
+ 0
+};
+
+void kvmppc_pr_init_default_hcalls(struct kvm *kvm)
+{
+ int i;
+ unsigned int hcall;
+
+ for (i = 0; default_hcall_list[i]; ++i) {
+ hcall = default_hcall_list[i];
+ WARN_ON(!kvmppc_hcall_impl_pr(hcall));
+ __set_bit(hcall / 4, kvm->arch.enabled_hcalls);
+ }
+}
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index d1acd32a64c0..eaeb78047fb8 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -64,8 +64,12 @@
static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
u32 new_irq);
-static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
- bool report_status)
+/*
+ * Return value ideally indicates how the interrupt was handled, but no
+ * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS),
+ * so just return 0.
+ */
+static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
{
struct ics_irq_state *state;
struct kvmppc_ics *ics;
@@ -82,17 +86,14 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
if (!state->exists)
return -EINVAL;
- if (report_status)
- return state->asserted;
-
/*
* We set state->asserted locklessly. This should be fine as
* we are the only setter, thus concurrent access is undefined
* to begin with.
*/
- if (level == KVM_INTERRUPT_SET_LEVEL)
+ if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL)
state->asserted = 1;
- else if (level == KVM_INTERRUPT_UNSET) {
+ else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
state->asserted = 0;
return 0;
}
@@ -100,7 +101,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
/* Attempt delivery */
icp_deliver_irq(xics, NULL, irq);
- return state->asserted;
+ return 0;
}
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
@@ -772,6 +773,8 @@ static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
if (state->asserted)
icp_deliver_irq(xics, icp, irq);
+ kvm_notify_acked_irq(vcpu->kvm, 0, irq);
+
return H_SUCCESS;
}
@@ -789,6 +792,8 @@ static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall)
icp_check_resend(xics, icp);
if (icp->rm_action & XICS_RM_REJECT)
icp_deliver_irq(xics, icp, icp->rm_reject);
+ if (icp->rm_action & XICS_RM_NOTIFY_EOI)
+ kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq);
icp->rm_action = 0;
@@ -1170,7 +1175,16 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
{
struct kvmppc_xics *xics = kvm->arch.xics;
- return ics_deliver_irq(xics, irq, level, line_status);
+ return ics_deliver_irq(xics, irq, level);
+}
+
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
+ int irq_source_id, int level, bool line_status)
+{
+ if (!level)
+ return -1;
+ return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
+ level, line_status);
}
static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
@@ -1301,3 +1315,26 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
vcpu->arch.icp = NULL;
vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
}
+
+static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id, int level,
+ bool line_status)
+{
+ return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
+}
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *entries, int gsi)
+{
+ entries->gsi = gsi;
+ entries->type = KVM_IRQ_ROUTING_IRQCHIP;
+ entries->set = xics_set_irq;
+ entries->irqchip.irqchip = 0;
+ entries->irqchip.pin = gsi;
+ return 1;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+ return pin;
+}
diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h
index dd9326c5c19b..e8aaa7a3f209 100644
--- a/arch/powerpc/kvm/book3s_xics.h
+++ b/arch/powerpc/kvm/book3s_xics.h
@@ -71,9 +71,11 @@ struct kvmppc_icp {
#define XICS_RM_KICK_VCPU 0x1
#define XICS_RM_CHECK_RESEND 0x2
#define XICS_RM_REJECT 0x4
+#define XICS_RM_NOTIFY_EOI 0x8
u32 rm_action;
struct kvm_vcpu *rm_kick_target;
u32 rm_reject;
+ u32 rm_eoied_irq;
/* Debug stuff for real mode */
union kvmppc_icp_state rm_dbgstate;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index ab62109fdfa3..b4c89fa6f109 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -51,7 +51,6 @@ unsigned long kvmppc_booke_handlers;
struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "mmio", VCPU_STAT(mmio_exits) },
- { "dcr", VCPU_STAT(dcr_exits) },
{ "sig", VCPU_STAT(signal_exits) },
{ "itlb_r", VCPU_STAT(itlb_real_miss_exits) },
{ "itlb_v", VCPU_STAT(itlb_virt_miss_exits) },
@@ -185,24 +184,28 @@ static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
set_bit(priority, &vcpu->arch.pending_exceptions);
}
-static void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
- ulong dear_flags, ulong esr_flags)
+void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
+ ulong dear_flags, ulong esr_flags)
{
vcpu->arch.queued_dear = dear_flags;
vcpu->arch.queued_esr = esr_flags;
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
}
-static void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
- ulong dear_flags, ulong esr_flags)
+void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
+ ulong dear_flags, ulong esr_flags)
{
vcpu->arch.queued_dear = dear_flags;
vcpu->arch.queued_esr = esr_flags;
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
}
-static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
- ulong esr_flags)
+void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu)
+{
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
+}
+
+void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong esr_flags)
{
vcpu->arch.queued_esr = esr_flags;
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
@@ -266,13 +269,8 @@ static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
{
-#ifdef CONFIG_KVM_BOOKE_HV
- mtspr(SPRN_GSRR0, srr0);
- mtspr(SPRN_GSRR1, srr1);
-#else
- vcpu->arch.shared->srr0 = srr0;
- vcpu->arch.shared->srr1 = srr1;
-#endif
+ kvmppc_set_srr0(vcpu, srr0);
+ kvmppc_set_srr1(vcpu, srr1);
}
static void set_guest_csrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
@@ -297,51 +295,6 @@ static void set_guest_mcsrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
vcpu->arch.mcsrr1 = srr1;
}
-static unsigned long get_guest_dear(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
- return mfspr(SPRN_GDEAR);
-#else
- return vcpu->arch.shared->dar;
-#endif
-}
-
-static void set_guest_dear(struct kvm_vcpu *vcpu, unsigned long dear)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
- mtspr(SPRN_GDEAR, dear);
-#else
- vcpu->arch.shared->dar = dear;
-#endif
-}
-
-static unsigned long get_guest_esr(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
- return mfspr(SPRN_GESR);
-#else
- return vcpu->arch.shared->esr;
-#endif
-}
-
-static void set_guest_esr(struct kvm_vcpu *vcpu, u32 esr)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
- mtspr(SPRN_GESR, esr);
-#else
- vcpu->arch.shared->esr = esr;
-#endif
-}
-
-static unsigned long get_guest_epr(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_KVM_BOOKE_HV
- return mfspr(SPRN_GEPR);
-#else
- return vcpu->arch.epr;
-#endif
-}
-
/* Deliver the interrupt of the corresponding priority, if possible. */
static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
unsigned int priority)
@@ -450,9 +403,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
if (update_esr == true)
- set_guest_esr(vcpu, vcpu->arch.queued_esr);
+ kvmppc_set_esr(vcpu, vcpu->arch.queued_esr);
if (update_dear == true)
- set_guest_dear(vcpu, vcpu->arch.queued_dear);
+ kvmppc_set_dar(vcpu, vcpu->arch.queued_dear);
if (update_epr == true) {
if (vcpu->arch.epr_flags & KVMPPC_EPR_USER)
kvm_make_request(KVM_REQ_EPR_EXIT, vcpu);
@@ -752,9 +705,8 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
* they were actually modified by emulation. */
return RESUME_GUEST_NV;
- case EMULATE_DO_DCR:
- run->exit_reason = KVM_EXIT_DCR;
- return RESUME_HOST;
+ case EMULATE_AGAIN:
+ return RESUME_GUEST;
case EMULATE_FAIL:
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
@@ -866,6 +818,28 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu,
}
}
+static int kvmppc_resume_inst_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ enum emulation_result emulated, u32 last_inst)
+{
+ switch (emulated) {
+ case EMULATE_AGAIN:
+ return RESUME_GUEST;
+
+ case EMULATE_FAIL:
+ pr_debug("%s: load instruction from guest address %lx failed\n",
+ __func__, vcpu->arch.pc);
+ /* For debugging, encode the failing instruction and
+ * report it to userspace. */
+ run->hw.hardware_exit_reason = ~0ULL << 32;
+ run->hw.hardware_exit_reason |= last_inst;
+ kvmppc_core_queue_program(vcpu, ESR_PIL);
+ return RESUME_HOST;
+
+ default:
+ BUG();
+ }
+}
+
/**
* kvmppc_handle_exit
*
@@ -877,6 +851,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
int r = RESUME_HOST;
int s;
int idx;
+ u32 last_inst = KVM_INST_FETCH_FAILED;
+ enum emulation_result emulated = EMULATE_DONE;
/* update before a new last_exit_type is rewritten */
kvmppc_update_timing_stats(vcpu);
@@ -884,6 +860,20 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* restart interrupts if they were meant for the host */
kvmppc_restart_interrupt(vcpu, exit_nr);
+ /*
+ * get last instruction before beeing preempted
+ * TODO: for e6500 check also BOOKE_INTERRUPT_LRAT_ERROR & ESR_DATA
+ */
+ switch (exit_nr) {
+ case BOOKE_INTERRUPT_DATA_STORAGE:
+ case BOOKE_INTERRUPT_DTLB_MISS:
+ case BOOKE_INTERRUPT_HV_PRIV:
+ emulated = kvmppc_get_last_inst(vcpu, false, &last_inst);
+ break;
+ default:
+ break;
+ }
+
local_irq_enable();
trace_kvm_exit(exit_nr, vcpu);
@@ -892,6 +882,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
run->exit_reason = KVM_EXIT_UNKNOWN;
run->ready_for_interrupt_injection = 1;
+ if (emulated != EMULATE_DONE) {
+ r = kvmppc_resume_inst_load(run, vcpu, emulated, last_inst);
+ goto out;
+ }
+
switch (exit_nr) {
case BOOKE_INTERRUPT_MACHINE_CHECK:
printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR));
@@ -1181,6 +1176,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
BUG();
}
+out:
/*
* To avoid clobbering exit_reason, only check for signals if we
* aren't already exiting to userspace for some other reason.
@@ -1265,17 +1261,17 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->lr = vcpu->arch.lr;
regs->xer = kvmppc_get_xer(vcpu);
regs->msr = vcpu->arch.shared->msr;
- regs->srr0 = vcpu->arch.shared->srr0;
- regs->srr1 = vcpu->arch.shared->srr1;
+ regs->srr0 = kvmppc_get_srr0(vcpu);
+ regs->srr1 = kvmppc_get_srr1(vcpu);
regs->pid = vcpu->arch.pid;
- regs->sprg0 = vcpu->arch.shared->sprg0;
- regs->sprg1 = vcpu->arch.shared->sprg1;
- regs->sprg2 = vcpu->arch.shared->sprg2;
- regs->sprg3 = vcpu->arch.shared->sprg3;
- regs->sprg4 = vcpu->arch.shared->sprg4;
- regs->sprg5 = vcpu->arch.shared->sprg5;
- regs->sprg6 = vcpu->arch.shared->sprg6;
- regs->sprg7 = vcpu->arch.shared->sprg7;
+ regs->sprg0 = kvmppc_get_sprg0(vcpu);
+ regs->sprg1 = kvmppc_get_sprg1(vcpu);
+ regs->sprg2 = kvmppc_get_sprg2(vcpu);
+ regs->sprg3 = kvmppc_get_sprg3(vcpu);
+ regs->sprg4 = kvmppc_get_sprg4(vcpu);
+ regs->sprg5 = kvmppc_get_sprg5(vcpu);
+ regs->sprg6 = kvmppc_get_sprg6(vcpu);
+ regs->sprg7 = kvmppc_get_sprg7(vcpu);
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -1293,17 +1289,17 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu->arch.lr = regs->lr;
kvmppc_set_xer(vcpu, regs->xer);
kvmppc_set_msr(vcpu, regs->msr);
- vcpu->arch.shared->srr0 = regs->srr0;
- vcpu->arch.shared->srr1 = regs->srr1;
+ kvmppc_set_srr0(vcpu, regs->srr0);
+ kvmppc_set_srr1(vcpu, regs->srr1);
kvmppc_set_pid(vcpu, regs->pid);
- vcpu->arch.shared->sprg0 = regs->sprg0;
- vcpu->arch.shared->sprg1 = regs->sprg1;
- vcpu->arch.shared->sprg2 = regs->sprg2;
- vcpu->arch.shared->sprg3 = regs->sprg3;
- vcpu->arch.shared->sprg4 = regs->sprg4;
- vcpu->arch.shared->sprg5 = regs->sprg5;
- vcpu->arch.shared->sprg6 = regs->sprg6;
- vcpu->arch.shared->sprg7 = regs->sprg7;
+ kvmppc_set_sprg0(vcpu, regs->sprg0);
+ kvmppc_set_sprg1(vcpu, regs->sprg1);
+ kvmppc_set_sprg2(vcpu, regs->sprg2);
+ kvmppc_set_sprg3(vcpu, regs->sprg3);
+ kvmppc_set_sprg4(vcpu, regs->sprg4);
+ kvmppc_set_sprg5(vcpu, regs->sprg5);
+ kvmppc_set_sprg6(vcpu, regs->sprg6);
+ kvmppc_set_sprg7(vcpu, regs->sprg7);
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
@@ -1321,8 +1317,8 @@ static void get_sregs_base(struct kvm_vcpu *vcpu,
sregs->u.e.csrr0 = vcpu->arch.csrr0;
sregs->u.e.csrr1 = vcpu->arch.csrr1;
sregs->u.e.mcsr = vcpu->arch.mcsr;
- sregs->u.e.esr = get_guest_esr(vcpu);
- sregs->u.e.dear = get_guest_dear(vcpu);
+ sregs->u.e.esr = kvmppc_get_esr(vcpu);
+ sregs->u.e.dear = kvmppc_get_dar(vcpu);
sregs->u.e.tsr = vcpu->arch.tsr;
sregs->u.e.tcr = vcpu->arch.tcr;
sregs->u.e.dec = kvmppc_get_dec(vcpu, tb);
@@ -1339,8 +1335,8 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
vcpu->arch.csrr0 = sregs->u.e.csrr0;
vcpu->arch.csrr1 = sregs->u.e.csrr1;
vcpu->arch.mcsr = sregs->u.e.mcsr;
- set_guest_esr(vcpu, sregs->u.e.esr);
- set_guest_dear(vcpu, sregs->u.e.dear);
+ kvmppc_set_esr(vcpu, sregs->u.e.esr);
+ kvmppc_set_dar(vcpu, sregs->u.e.dear);
vcpu->arch.vrsave = sregs->u.e.vrsave;
kvmppc_set_tcr(vcpu, sregs->u.e.tcr);
@@ -1493,7 +1489,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2);
break;
case KVM_REG_PPC_EPR: {
- u32 epr = get_guest_epr(vcpu);
+ u32 epr = kvmppc_get_epr(vcpu);
val = get_reg_val(reg->id, epr);
break;
}
@@ -1788,6 +1784,57 @@ void kvm_guest_protect_msr(struct kvm_vcpu *vcpu, ulong prot_bitmap, bool set)
#endif
}
+int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
+ enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
+{
+ int gtlb_index;
+ gpa_t gpaddr;
+
+#ifdef CONFIG_KVM_E500V2
+ if (!(vcpu->arch.shared->msr & MSR_PR) &&
+ (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
+ pte->eaddr = eaddr;
+ pte->raddr = (vcpu->arch.magic_page_pa & PAGE_MASK) |
+ (eaddr & ~PAGE_MASK);
+ pte->vpage = eaddr >> PAGE_SHIFT;
+ pte->may_read = true;
+ pte->may_write = true;
+ pte->may_execute = true;
+
+ return 0;
+ }
+#endif
+
+ /* Check the guest TLB. */
+ switch (xlid) {
+ case XLATE_INST:
+ gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr);
+ break;
+ case XLATE_DATA:
+ gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
+ break;
+ default:
+ BUG();
+ }
+
+ /* Do we have a TLB entry at all? */
+ if (gtlb_index < 0)
+ return -ENOENT;
+
+ gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
+
+ pte->eaddr = eaddr;
+ pte->raddr = (gpaddr & PAGE_MASK) | (eaddr & ~PAGE_MASK);
+ pte->vpage = eaddr >> PAGE_SHIFT;
+
+ /* XXX read permissions from the guest TLB */
+ pte->may_read = true;
+ pte->may_write = true;
+ pte->may_execute = true;
+
+ return 0;
+}
+
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg)
{
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index b632cd35919b..f753543c56fa 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -99,13 +99,6 @@ enum int_class {
void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type);
-extern void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu);
-extern int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu,
- unsigned int inst, int *advance);
-extern int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn,
- ulong spr_val);
-extern int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn,
- ulong *spr_val);
extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu);
extern int kvmppc_core_emulate_op_e500(struct kvm_run *run,
struct kvm_vcpu *vcpu,
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index 27a4b2877c10..28c158881d23 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -165,16 +165,16 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
* guest (PR-mode only).
*/
case SPRN_SPRG4:
- vcpu->arch.shared->sprg4 = spr_val;
+ kvmppc_set_sprg4(vcpu, spr_val);
break;
case SPRN_SPRG5:
- vcpu->arch.shared->sprg5 = spr_val;
+ kvmppc_set_sprg5(vcpu, spr_val);
break;
case SPRN_SPRG6:
- vcpu->arch.shared->sprg6 = spr_val;
+ kvmppc_set_sprg6(vcpu, spr_val);
break;
case SPRN_SPRG7:
- vcpu->arch.shared->sprg7 = spr_val;
+ kvmppc_set_sprg7(vcpu, spr_val);
break;
case SPRN_IVPR:
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 2c6deb5ef2fe..84c308a9a371 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -21,7 +21,6 @@
#include <asm/ppc_asm.h>
#include <asm/kvm_asm.h>
#include <asm/reg.h>
-#include <asm/mmu-44x.h>
#include <asm/page.h>
#include <asm/asm-offsets.h>
@@ -424,10 +423,6 @@ lightweight_exit:
mtspr SPRN_PID1, r3
#endif
-#ifdef CONFIG_44x
- iccci 0, 0 /* XXX hack */
-#endif
-
/* Load some guest volatiles. */
lwz r0, VCPU_GPR(R0)(r4)
lwz r2, VCPU_GPR(R2)(r4)
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index a1712b818a5f..e9fa56a911fd 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -24,12 +24,10 @@
#include <asm/ppc_asm.h>
#include <asm/kvm_asm.h>
#include <asm/reg.h>
-#include <asm/mmu-44x.h>
#include <asm/page.h>
#include <asm/asm-compat.h>
#include <asm/asm-offsets.h>
#include <asm/bitsperlong.h>
-#include <asm/thread_info.h>
#ifdef CONFIG_64BIT
#include <asm/exception-64e.h>
@@ -122,38 +120,14 @@
1:
.if \flags & NEED_EMU
- /*
- * This assumes you have external PID support.
- * To support a bookehv CPU without external PID, you'll
- * need to look up the TLB entry and create a temporary mapping.
- *
- * FIXME: we don't currently handle if the lwepx faults. PR-mode
- * booke doesn't handle it either. Since Linux doesn't use
- * broadcast tlbivax anymore, the only way this should happen is
- * if the guest maps its memory execute-but-not-read, or if we
- * somehow take a TLB miss in the middle of this entry code and
- * evict the relevant entry. On e500mc, all kernel lowmem is
- * bolted into TLB1 large page mappings, and we don't use
- * broadcast invalidates, so we should not take a TLB miss here.
- *
- * Later we'll need to deal with faults here. Disallowing guest
- * mappings that are execute-but-not-read could be an option on
- * e500mc, but not on chips with an LRAT if it is used.
- */
-
- mfspr r3, SPRN_EPLC /* will already have correct ELPID and EGS */
PPC_STL r15, VCPU_GPR(R15)(r4)
PPC_STL r16, VCPU_GPR(R16)(r4)
PPC_STL r17, VCPU_GPR(R17)(r4)
PPC_STL r18, VCPU_GPR(R18)(r4)
PPC_STL r19, VCPU_GPR(R19)(r4)
- mr r8, r3
PPC_STL r20, VCPU_GPR(R20)(r4)
- rlwimi r8, r6, EPC_EAS_SHIFT - MSR_IR_LG, EPC_EAS
PPC_STL r21, VCPU_GPR(R21)(r4)
- rlwimi r8, r6, EPC_EPR_SHIFT - MSR_PR_LG, EPC_EPR
PPC_STL r22, VCPU_GPR(R22)(r4)
- rlwimi r8, r10, EPC_EPID_SHIFT, EPC_EPID
PPC_STL r23, VCPU_GPR(R23)(r4)
PPC_STL r24, VCPU_GPR(R24)(r4)
PPC_STL r25, VCPU_GPR(R25)(r4)
@@ -163,33 +137,15 @@
PPC_STL r29, VCPU_GPR(R29)(r4)
PPC_STL r30, VCPU_GPR(R30)(r4)
PPC_STL r31, VCPU_GPR(R31)(r4)
- mtspr SPRN_EPLC, r8
-
- /* disable preemption, so we are sure we hit the fixup handler */
- CURRENT_THREAD_INFO(r8, r1)
- li r7, 1
- stw r7, TI_PREEMPT(r8)
-
- isync
/*
- * In case the read goes wrong, we catch it and write an invalid value
- * in LAST_INST instead.
+ * We don't use external PID support. lwepx faults would need to be
+ * handled by KVM and this implies aditional code in DO_KVM (for
+ * DTB_MISS, DSI and LRAT) to check ESR[EPID] and EPLC[EGS] which
+ * is too intrusive for the host. Get last instuction in
+ * kvmppc_get_last_inst().
*/
-1: lwepx r9, 0, r5
-2:
-.section .fixup, "ax"
-3: li r9, KVM_INST_FETCH_FAILED
- b 2b
-.previous
-.section __ex_table,"a"
- PPC_LONG_ALIGN
- PPC_LONG 1b,3b
-.previous
-
- mtspr SPRN_EPLC, r3
- li r7, 0
- stw r7, TI_PREEMPT(r8)
+ li r9, KVM_INST_FETCH_FAILED
stw r9, VCPU_LAST_INST(r4)
.endif
@@ -441,6 +397,7 @@ _GLOBAL(kvmppc_resume_host)
#ifdef CONFIG_64BIT
PPC_LL r3, PACA_SPRG_VDSO(r13)
#endif
+ mfspr r5, SPRN_SPRG9
PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
mfspr r8, SPRN_SPRG6
PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
@@ -448,6 +405,7 @@ _GLOBAL(kvmppc_resume_host)
#ifdef CONFIG_64BIT
mtspr SPRN_SPRG_VDSO_WRITE, r3
#endif
+ PPC_STD(r5, VCPU_SPRG9, r4)
PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
mfxer r3
PPC_STD(r9, VCPU_SHARED_SPRG7, r11)
@@ -682,7 +640,9 @@ lightweight_exit:
mtspr SPRN_SPRG5W, r6
PPC_LD(r8, VCPU_SHARED_SPRG7, r11)
mtspr SPRN_SPRG6W, r7
+ PPC_LD(r5, VCPU_SPRG9, r4)
mtspr SPRN_SPRG7W, r8
+ mtspr SPRN_SPRG9, r5
/* Load some guest volatiles. */
PPC_LL r3, VCPU_LR(r4)
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 002d51764143..c99c40e9182a 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -250,6 +250,14 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
spr_val);
break;
+ case SPRN_PWRMGTCR0:
+ /*
+ * Guest relies on host power management configurations
+ * Treat the request as a general store
+ */
+ vcpu->arch.pwrmgtcr0 = spr_val;
+ break;
+
/* extra exceptions */
case SPRN_IVOR32:
vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
@@ -368,6 +376,10 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v
*spr_val = vcpu->arch.eptcfg;
break;
+ case SPRN_PWRMGTCR0:
+ *spr_val = vcpu->arch.pwrmgtcr0;
+ break;
+
/* extra exceptions */
case SPRN_IVOR32:
*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 86903d3f5a03..08f14bb57897 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -107,11 +107,15 @@ static u32 get_host_mas0(unsigned long eaddr)
{
unsigned long flags;
u32 mas0;
+ u32 mas4;
local_irq_save(flags);
mtspr(SPRN_MAS6, 0);
+ mas4 = mfspr(SPRN_MAS4);
+ mtspr(SPRN_MAS4, mas4 & ~MAS4_TLBSEL_MASK);
asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET));
mas0 = mfspr(SPRN_MAS0);
+ mtspr(SPRN_MAS4, mas4);
local_irq_restore(flags);
return mas0;
@@ -607,6 +611,104 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
}
}
+#ifdef CONFIG_KVM_BOOKE_HV
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+ u32 *instr)
+{
+ gva_t geaddr;
+ hpa_t addr;
+ hfn_t pfn;
+ hva_t eaddr;
+ u32 mas1, mas2, mas3;
+ u64 mas7_mas3;
+ struct page *page;
+ unsigned int addr_space, psize_shift;
+ bool pr;
+ unsigned long flags;
+
+ /* Search TLB for guest pc to get the real address */
+ geaddr = kvmppc_get_pc(vcpu);
+
+ addr_space = (vcpu->arch.shared->msr & MSR_IS) >> MSR_IR_LG;
+
+ local_irq_save(flags);
+ mtspr(SPRN_MAS6, (vcpu->arch.pid << MAS6_SPID_SHIFT) | addr_space);
+ mtspr(SPRN_MAS5, MAS5_SGS | vcpu->kvm->arch.lpid);
+ asm volatile("tlbsx 0, %[geaddr]\n" : :
+ [geaddr] "r" (geaddr));
+ mtspr(SPRN_MAS5, 0);
+ mtspr(SPRN_MAS8, 0);
+ mas1 = mfspr(SPRN_MAS1);
+ mas2 = mfspr(SPRN_MAS2);
+ mas3 = mfspr(SPRN_MAS3);
+#ifdef CONFIG_64BIT
+ mas7_mas3 = mfspr(SPRN_MAS7_MAS3);
+#else
+ mas7_mas3 = ((u64)mfspr(SPRN_MAS7) << 32) | mas3;
+#endif
+ local_irq_restore(flags);
+
+ /*
+ * If the TLB entry for guest pc was evicted, return to the guest.
+ * There are high chances to find a valid TLB entry next time.
+ */
+ if (!(mas1 & MAS1_VALID))
+ return EMULATE_AGAIN;
+
+ /*
+ * Another thread may rewrite the TLB entry in parallel, don't
+ * execute from the address if the execute permission is not set
+ */
+ pr = vcpu->arch.shared->msr & MSR_PR;
+ if (unlikely((pr && !(mas3 & MAS3_UX)) ||
+ (!pr && !(mas3 & MAS3_SX)))) {
+ pr_err_ratelimited(
+ "%s: Instuction emulation from guest addres %08lx without execute permission\n",
+ __func__, geaddr);
+ return EMULATE_AGAIN;
+ }
+
+ /*
+ * The real address will be mapped by a cacheable, memory coherent,
+ * write-back page. Check for mismatches when LRAT is used.
+ */
+ if (has_feature(vcpu, VCPU_FTR_MMU_V2) &&
+ unlikely((mas2 & MAS2_I) || (mas2 & MAS2_W) || !(mas2 & MAS2_M))) {
+ pr_err_ratelimited(
+ "%s: Instuction emulation from guest addres %08lx mismatches storage attributes\n",
+ __func__, geaddr);
+ return EMULATE_AGAIN;
+ }
+
+ /* Get pfn */
+ psize_shift = MAS1_GET_TSIZE(mas1) + 10;
+ addr = (mas7_mas3 & (~0ULL << psize_shift)) |
+ (geaddr & ((1ULL << psize_shift) - 1ULL));
+ pfn = addr >> PAGE_SHIFT;
+
+ /* Guard against emulation from devices area */
+ if (unlikely(!page_is_ram(pfn))) {
+ pr_err_ratelimited("%s: Instruction emulation from non-RAM host addres %08llx is not supported\n",
+ __func__, addr);
+ return EMULATE_AGAIN;
+ }
+
+ /* Map a page and get guest's instruction */
+ page = pfn_to_page(pfn);
+ eaddr = (unsigned long)kmap_atomic(page);
+ *instr = *(u32 *)(eaddr | (unsigned long)(addr & ~PAGE_MASK));
+ kunmap_atomic((u32 *)eaddr);
+
+ return EMULATE_DONE;
+}
+#else
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
+ u32 *instr)
+{
+ return EMULATE_AGAIN;
+}
+#endif
+
/************* MMU Notifiers *************/
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 17e456279224..164bad2a19bf 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -110,7 +110,7 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
{
}
-static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
+static DEFINE_PER_CPU(struct kvm_vcpu *[KVMPPC_NR_LPIDS], last_vcpu_of_lpid);
static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
{
@@ -141,9 +141,9 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu)
mtspr(SPRN_GESR, vcpu->arch.shared->esr);
if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
- __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
+ __get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] != vcpu) {
kvmppc_e500_tlbil_all(vcpu_e500);
- __get_cpu_var(last_vcpu_on_cpu) = vcpu;
+ __get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] = vcpu;
}
kvmppc_load_guest_fp(vcpu);
@@ -267,14 +267,32 @@ static int kvmppc_core_set_sregs_e500mc(struct kvm_vcpu *vcpu,
static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ int r = 0;
+
+ switch (id) {
+ case KVM_REG_PPC_SPRG9:
+ *val = get_reg_val(id, vcpu->arch.sprg9);
+ break;
+ default:
+ r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
+ }
+
return r;
}
static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val)
{
- int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val);
+ int r = 0;
+
+ switch (id) {
+ case KVM_REG_PPC_SPRG9:
+ vcpu->arch.sprg9 = set_reg_val(id, *val);
+ break;
+ default:
+ r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val);
+ }
+
return r;
}
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index da86d9ba3476..e96b50d0bdab 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -207,36 +207,28 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
return emulated;
}
-/* XXX to do:
- * lhax
- * lhaux
- * lswx
- * lswi
- * stswx
- * stswi
- * lha
- * lhau
- * lmw
- * stmw
- *
- */
/* XXX Should probably auto-generate instruction decoding for a particular core
* from opcode tables in the future. */
int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
- u32 inst = kvmppc_get_last_inst(vcpu);
- int ra = get_ra(inst);
- int rs = get_rs(inst);
- int rt = get_rt(inst);
- int sprn = get_sprn(inst);
- enum emulation_result emulated = EMULATE_DONE;
+ u32 inst;
+ int rs, rt, sprn;
+ enum emulation_result emulated;
int advance = 1;
/* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
+ emulated = kvmppc_get_last_inst(vcpu, false, &inst);
+ if (emulated != EMULATE_DONE)
+ return emulated;
+
pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
+ rs = get_rs(inst);
+ rt = get_rt(inst);
+ sprn = get_sprn(inst);
+
switch (get_op(inst)) {
case OP_TRAP:
#ifdef CONFIG_PPC_BOOK3S
@@ -264,200 +256,24 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
#endif
advance = 0;
break;
- case OP_31_XOP_LWZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- break;
-
- case OP_31_XOP_LBZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- break;
-
- case OP_31_XOP_LBZUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_STWX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 4, 1);
- break;
-
- case OP_31_XOP_STBX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 1, 1);
- break;
-
- case OP_31_XOP_STBUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_LHAX:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- break;
-
- case OP_31_XOP_LHZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- break;
-
- case OP_31_XOP_LHZUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
case OP_31_XOP_MFSPR:
emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
break;
- case OP_31_XOP_STHX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 2, 1);
- break;
-
- case OP_31_XOP_STHUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
case OP_31_XOP_MTSPR:
emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
break;
- case OP_31_XOP_DCBST:
- case OP_31_XOP_DCBF:
- case OP_31_XOP_DCBI:
- /* Do nothing. The guest is performing dcbi because
- * hardware DMA is not snooped by the dcache, but
- * emulated DMA either goes through the dcache as
- * normal writes, or the host kernel has handled dcache
- * coherence. */
- break;
-
- case OP_31_XOP_LWBRX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
- break;
-
case OP_31_XOP_TLBSYNC:
break;
- case OP_31_XOP_STWBRX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 4, 0);
- break;
-
- case OP_31_XOP_LHBRX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
- break;
-
- case OP_31_XOP_STHBRX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 2, 0);
- break;
-
default:
/* Attempt core-specific emulation below. */
emulated = EMULATE_FAIL;
}
break;
- case OP_LWZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- break;
-
- /* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */
- case OP_LD:
- rt = get_rt(inst);
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
- break;
-
- case OP_LWZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LBZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- break;
-
- case OP_LBZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STW:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 4, 1);
- break;
-
- /* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */
- case OP_STD:
- rs = get_rs(inst);
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 8, 1);
- break;
-
- case OP_STWU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STB:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 1, 1);
- break;
-
- case OP_STBU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LHZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- break;
-
- case OP_LHZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LHA:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- break;
-
- case OP_LHAU:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STH:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 2, 1);
- break;
-
- case OP_STHU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
default:
emulated = EMULATE_FAIL;
}
diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c
new file mode 100644
index 000000000000..0de4ffa175a9
--- /dev/null
+++ b/arch/powerpc/kvm/emulate_loadstore.c
@@ -0,0 +1,272 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/jiffies.h>
+#include <linux/hrtimer.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kvm_host.h>
+#include <linux/clockchips.h>
+
+#include <asm/reg.h>
+#include <asm/time.h>
+#include <asm/byteorder.h>
+#include <asm/kvm_ppc.h>
+#include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
+#include "timing.h"
+#include "trace.h"
+
+/* XXX to do:
+ * lhax
+ * lhaux
+ * lswx
+ * lswi
+ * stswx
+ * stswi
+ * lha
+ * lhau
+ * lmw
+ * stmw
+ *
+ */
+int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
+{
+ struct kvm_run *run = vcpu->run;
+ u32 inst;
+ int ra, rs, rt;
+ enum emulation_result emulated;
+ int advance = 1;
+
+ /* this default type might be overwritten by subcategories */
+ kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
+
+ emulated = kvmppc_get_last_inst(vcpu, false, &inst);
+ if (emulated != EMULATE_DONE)
+ return emulated;
+
+ ra = get_ra(inst);
+ rs = get_rs(inst);
+ rt = get_rt(inst);
+
+ switch (get_op(inst)) {
+ case 31:
+ switch (get_xop(inst)) {
+ case OP_31_XOP_LWZX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+ break;
+
+ case OP_31_XOP_LBZX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+ break;
+
+ case OP_31_XOP_LBZUX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_31_XOP_STWX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 4, 1);
+ break;
+
+ case OP_31_XOP_STBX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 1, 1);
+ break;
+
+ case OP_31_XOP_STBUX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 1, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_31_XOP_LHAX:
+ emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+ break;
+
+ case OP_31_XOP_LHZX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+ break;
+
+ case OP_31_XOP_LHZUX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_31_XOP_STHX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 2, 1);
+ break;
+
+ case OP_31_XOP_STHUX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 2, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_31_XOP_DCBST:
+ case OP_31_XOP_DCBF:
+ case OP_31_XOP_DCBI:
+ /* Do nothing. The guest is performing dcbi because
+ * hardware DMA is not snooped by the dcache, but
+ * emulated DMA either goes through the dcache as
+ * normal writes, or the host kernel has handled dcache
+ * coherence. */
+ break;
+
+ case OP_31_XOP_LWBRX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
+ break;
+
+ case OP_31_XOP_STWBRX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 4, 0);
+ break;
+
+ case OP_31_XOP_LHBRX:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
+ break;
+
+ case OP_31_XOP_STHBRX:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 2, 0);
+ break;
+
+ default:
+ emulated = EMULATE_FAIL;
+ break;
+ }
+ break;
+
+ case OP_LWZ:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+ break;
+
+ /* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */
+ case OP_LD:
+ rt = get_rt(inst);
+ emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
+ break;
+
+ case OP_LWZU:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_LBZ:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+ break;
+
+ case OP_LBZU:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_STW:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 4, 1);
+ break;
+
+ /* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */
+ case OP_STD:
+ rs = get_rs(inst);
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 8, 1);
+ break;
+
+ case OP_STWU:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 4, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_STB:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 1, 1);
+ break;
+
+ case OP_STBU:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 1, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_LHZ:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+ break;
+
+ case OP_LHZU:
+ emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_LHA:
+ emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+ break;
+
+ case OP_LHAU:
+ emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ case OP_STH:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 2, 1);
+ break;
+
+ case OP_STHU:
+ emulated = kvmppc_handle_store(run, vcpu,
+ kvmppc_get_gpr(vcpu, rs),
+ 2, 1);
+ kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+ break;
+
+ default:
+ emulated = EMULATE_FAIL;
+ break;
+ }
+
+ if (emulated == EMULATE_FAIL) {
+ advance = 0;
+ kvmppc_core_queue_program(vcpu, 0);
+ }
+
+ trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated);
+
+ /* Advance past emulated instruction. */
+ if (advance)
+ kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
+
+ return emulated;
+}
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
index b68d0dc9479a..39b3a8f816f2 100644
--- a/arch/powerpc/kvm/mpic.c
+++ b/arch/powerpc/kvm/mpic.c
@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
return 0;
}
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
- struct kvm_kernel_irq_routing_entry *e,
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
{
int r = -EINVAL;
@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
e->irqchip.pin = ue->u.irqchip.pin;
if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
goto out;
- rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
break;
case KVM_IRQ_ROUTING_MSI:
e->set = kvm_set_msi;
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 61c738ab1283..4c79284b58be 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -190,6 +190,25 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
vcpu->arch.magic_page_pa = param1 & ~0xfffULL;
vcpu->arch.magic_page_ea = param2 & ~0xfffULL;
+#ifdef CONFIG_PPC_64K_PAGES
+ /*
+ * Make sure our 4k magic page is in the same window of a 64k
+ * page within the guest and within the host's page.
+ */
+ if ((vcpu->arch.magic_page_pa & 0xf000) !=
+ ((ulong)vcpu->arch.shared & 0xf000)) {
+ void *old_shared = vcpu->arch.shared;
+ ulong shared = (ulong)vcpu->arch.shared;
+ void *new_shared;
+
+ shared &= PAGE_MASK;
+ shared |= vcpu->arch.magic_page_pa & 0xf000;
+ new_shared = (void*)shared;
+ memcpy(new_shared, old_shared, 0x1000);
+ vcpu->arch.shared = new_shared;
+ }
+#endif
+
r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
r = EV_SUCCESS;
@@ -198,7 +217,6 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
r = EV_SUCCESS;
#if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
- /* XXX Missing magic page on 44x */
r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
#endif
@@ -254,13 +272,16 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
enum emulation_result er;
int r;
- er = kvmppc_emulate_instruction(run, vcpu);
+ er = kvmppc_emulate_loadstore(vcpu);
switch (er) {
case EMULATE_DONE:
/* Future optimization: only reload non-volatiles if they were
* actually modified. */
r = RESUME_GUEST_NV;
break;
+ case EMULATE_AGAIN:
+ r = RESUME_GUEST;
+ break;
case EMULATE_DO_MMIO:
run->exit_reason = KVM_EXIT_MMIO;
/* We must reload nonvolatiles because "update" load/store
@@ -270,11 +291,15 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
r = RESUME_HOST_NV;
break;
case EMULATE_FAIL:
+ {
+ u32 last_inst;
+
+ kvmppc_get_last_inst(vcpu, false, &last_inst);
/* XXX Deliver Program interrupt to guest. */
- printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__,
- kvmppc_get_last_inst(vcpu));
+ pr_emerg("%s: emulation failed (%08x)\n", __func__, last_inst);
r = RESUME_HOST;
break;
+ }
default:
WARN_ON(1);
r = RESUME_GUEST;
@@ -284,6 +309,81 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio);
+int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+ bool data)
+{
+ ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
+ struct kvmppc_pte pte;
+ int r;
+
+ vcpu->stat.st++;
+
+ r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
+ XLATE_WRITE, &pte);
+ if (r < 0)
+ return r;
+
+ *eaddr = pte.raddr;
+
+ if (!pte.may_write)
+ return -EPERM;
+
+ /* Magic page override */
+ if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+ ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+ !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+ void *magic = vcpu->arch.shared;
+ magic += pte.eaddr & 0xfff;
+ memcpy(magic, ptr, size);
+ return EMULATE_DONE;
+ }
+
+ if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
+ return EMULATE_DO_MMIO;
+
+ return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvmppc_st);
+
+int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
+ bool data)
+{
+ ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
+ struct kvmppc_pte pte;
+ int rc;
+
+ vcpu->stat.ld++;
+
+ rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
+ XLATE_READ, &pte);
+ if (rc)
+ return rc;
+
+ *eaddr = pte.raddr;
+
+ if (!pte.may_read)
+ return -EPERM;
+
+ if (!data && !pte.may_execute)
+ return -ENOEXEC;
+
+ /* Magic page override */
+ if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+ ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+ !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+ void *magic = vcpu->arch.shared;
+ magic += pte.eaddr & 0xfff;
+ memcpy(ptr, magic, size);
+ return EMULATE_DONE;
+ }
+
+ if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size))
+ return EMULATE_DO_MMIO;
+
+ return EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvmppc_ld);
+
int kvm_arch_hardware_enable(void *garbage)
{
return 0;
@@ -366,14 +466,20 @@ void kvm_arch_sync_events(struct kvm *kvm)
{
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
- /* FIXME!!
- * Should some of this be vm ioctl ? is it possible now ?
- */
+ /* Assume we're using HV mode when the HV module is loaded */
int hv_enabled = kvmppc_hv_ops ? 1 : 0;
+ if (kvm) {
+ /*
+ * Hooray - we know which VM type we're running on. Depend on
+ * that rather than the guess above.
+ */
+ hv_enabled = is_kvmppc_hv_enabled(kvm);
+ }
+
switch (ext) {
#ifdef CONFIG_BOOKE
case KVM_CAP_PPC_BOOKE_SREGS:
@@ -387,6 +493,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_PPC_UNSET_IRQ:
case KVM_CAP_PPC_IRQ_LEVEL:
case KVM_CAP_ENABLE_CAP:
+ case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_ONE_REG:
case KVM_CAP_IOEVENTFD:
case KVM_CAP_DEVICE_CTRL:
@@ -417,6 +524,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_PPC_ALLOC_HTAB:
case KVM_CAP_PPC_RTAS:
case KVM_CAP_PPC_FIXUP_HCALL:
+ case KVM_CAP_PPC_ENABLE_HCALL:
#ifdef CONFIG_KVM_XICS
case KVM_CAP_IRQ_XICS:
#endif
@@ -635,12 +743,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
#endif
}
-static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
- struct kvm_run *run)
-{
- kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, run->dcr.data);
-}
-
static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
struct kvm_run *run)
{
@@ -837,10 +939,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
if (!vcpu->mmio_is_write)
kvmppc_complete_mmio_load(vcpu, run);
vcpu->mmio_needed = 0;
- } else if (vcpu->arch.dcr_needed) {
- if (!vcpu->arch.dcr_is_write)
- kvmppc_complete_dcr_load(vcpu, run);
- vcpu->arch.dcr_needed = 0;
} else if (vcpu->arch.osi_needed) {
u64 *gprs = run->osi.gprs;
int i;
@@ -1099,6 +1197,42 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event,
return 0;
}
+
+static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
+ struct kvm_enable_cap *cap)
+{
+ int r;
+
+ if (cap->flags)
+ return -EINVAL;
+
+ switch (cap->cap) {
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+ case KVM_CAP_PPC_ENABLE_HCALL: {
+ unsigned long hcall = cap->args[0];
+
+ r = -EINVAL;
+ if (hcall > MAX_HCALL_OPCODE || (hcall & 3) ||
+ cap->args[1] > 1)
+ break;
+ if (!kvmppc_book3s_hcall_implemented(kvm, hcall))
+ break;
+ if (cap->args[1])
+ set_bit(hcall / 4, kvm->arch.enabled_hcalls);
+ else
+ clear_bit(hcall / 4, kvm->arch.enabled_hcalls);
+ r = 0;
+ break;
+ }
+#endif
+ default:
+ r = -EINVAL;
+ break;
+ }
+
+ return r;
+}
+
long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -1118,6 +1252,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
break;
}
+ case KVM_ENABLE_CAP:
+ {
+ struct kvm_enable_cap cap;
+ r = -EFAULT;
+ if (copy_from_user(&cap, argp, sizeof(cap)))
+ goto out;
+ r = kvm_vm_ioctl_enable_cap(kvm, &cap);
+ break;
+ }
#ifdef CONFIG_PPC_BOOK3S_64
case KVM_CREATE_SPAPR_TCE: {
struct kvm_create_spapr_tce create_tce;
@@ -1204,3 +1347,5 @@ void kvm_arch_exit(void)
{
}
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ppc_instr);
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c
index 07b6110a4bb7..e44d2b2ea97e 100644
--- a/arch/powerpc/kvm/timing.c
+++ b/arch/powerpc/kvm/timing.c
@@ -110,7 +110,6 @@ void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu)
static const char *kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = {
[MMIO_EXITS] = "MMIO",
- [DCR_EXITS] = "DCR",
[SIGNAL_EXITS] = "SIGNAL",
[ITLB_REAL_MISS_EXITS] = "ITLBREAL",
[ITLB_VIRT_MISS_EXITS] = "ITLBVIRT",
diff --git a/arch/powerpc/kvm/timing.h b/arch/powerpc/kvm/timing.h
index bf191e72b2d8..3123690c82dc 100644
--- a/arch/powerpc/kvm/timing.h
+++ b/arch/powerpc/kvm/timing.h
@@ -63,9 +63,6 @@ static inline void kvmppc_account_exit_stat(struct kvm_vcpu *vcpu, int type)
case EMULATED_INST_EXITS:
vcpu->stat.emulated_inst_exits++;
break;
- case DCR_EXITS:
- vcpu->stat.dcr_exits++;
- break;
case DSI_EXITS:
vcpu->stat.dsi_exits++;
break;
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
index 0860ee46013c..f09899e35991 100644
--- a/arch/powerpc/lib/copyuser_64.S
+++ b/arch/powerpc/lib/copyuser_64.S
@@ -461,8 +461,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
/*
* Routine to copy a whole page of data, optimized for POWER4.
* On POWER4 it is more than 50% faster than the simple loop
- * above (following the .Ldst_aligned label) but it runs slightly
- * slower on POWER3.
+ * above (following the .Ldst_aligned label).
*/
.Lcopy_page_4K:
std r31,-32(1)
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index 0c9c8d7d0734..170a0346f756 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -70,12 +70,16 @@ void __rw_yield(arch_rwlock_t *rw)
void arch_spin_unlock_wait(arch_spinlock_t *lock)
{
+ smp_mb();
+
while (lock->slock) {
HMT_low();
if (SHARED_PROCESSOR)
__spin_yield(lock);
}
HMT_medium();
+
+ smp_mb();
}
EXPORT_SYMBOL(arch_spin_unlock_wait);
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 51230ee6a407..d0130fff20e5 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -13,9 +13,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \
tlb_nohash_low.o
obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(CONFIG_WORD_SIZE)e.o
hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o
-obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o \
- slb_low.o slb.o stab.o \
- $(hash64-y)
+obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o slb_low.o slb.o $(hash64-y)
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o
obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \
tlb_hash$(CONFIG_WORD_SIZE).o \
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
index 7b6c10750179..d85e86aac7fb 100644
--- a/arch/powerpc/mm/dma-noncoherent.c
+++ b/arch/powerpc/mm/dma-noncoherent.c
@@ -33,6 +33,7 @@
#include <linux/export.h>
#include <asm/tlbflush.h>
+#include <asm/dma.h>
#include "mmu_decl.h"
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index cf1d325eae8b..afc0a8295f84 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -412,18 +412,18 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
local_irq_restore(flags);
}
-static void native_hugepage_invalidate(struct mm_struct *mm,
+static void native_hugepage_invalidate(unsigned long vsid,
+ unsigned long addr,
unsigned char *hpte_slot_array,
- unsigned long addr, int psize)
+ int psize, int ssize)
{
- int ssize = 0, i;
- int lock_tlbie;
+ int i;
struct hash_pte *hptep;
int actual_psize = MMU_PAGE_16M;
unsigned int max_hpte_count, valid;
unsigned long flags, s_addr = addr;
unsigned long hpte_v, want_v, shift;
- unsigned long hidx, vpn = 0, vsid, hash, slot;
+ unsigned long hidx, vpn = 0, hash, slot;
shift = mmu_psize_defs[psize].shift;
max_hpte_count = 1U << (PMD_SHIFT - shift);
@@ -437,15 +437,6 @@ static void native_hugepage_invalidate(struct mm_struct *mm,
/* get the vpn */
addr = s_addr + (i * (1ul << shift));
- if (!is_kernel_addr(addr)) {
- ssize = user_segment_size(addr);
- vsid = get_vsid(mm->context.id, addr, ssize);
- WARN_ON(vsid == 0);
- } else {
- vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
- ssize = mmu_kernel_ssize;
- }
-
vpn = hpt_vpn(addr, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
if (hidx & _PTEIDX_SECONDARY)
@@ -465,22 +456,13 @@ static void native_hugepage_invalidate(struct mm_struct *mm,
else
/* Invalidate the hpte. NOTE: this also unlocks it */
hptep->v = 0;
+ /*
+ * We need to do tlb invalidate for all the address, tlbie
+ * instruction compares entry_VA in tlb with the VA specified
+ * here
+ */
+ tlbie(vpn, psize, actual_psize, ssize, 0);
}
- /*
- * Since this is a hugepage, we just need a single tlbie.
- * use the last vpn.
- */
- lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
- if (lock_tlbie)
- raw_spin_lock(&native_tlbie_lock);
-
- asm volatile("ptesync":::"memory");
- __tlbie(vpn, psize, actual_psize, ssize);
- asm volatile("eieio; tlbsync; ptesync":::"memory");
-
- if (lock_tlbie)
- raw_spin_unlock(&native_tlbie_lock);
-
local_irq_restore(flags);
}
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 88fdd9d25077..daee7f4e5a14 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -243,7 +243,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
}
#ifdef CONFIG_MEMORY_HOTPLUG
-static int htab_remove_mapping(unsigned long vstart, unsigned long vend,
+int htab_remove_mapping(unsigned long vstart, unsigned long vend,
int psize, int ssize)
{
unsigned long vaddr;
@@ -821,21 +821,14 @@ static void __init htab_initialize(void)
void __init early_init_mmu(void)
{
- /* Setup initial STAB address in the PACA */
- get_paca()->stab_real = __pa((u64)&initial_stab);
- get_paca()->stab_addr = (u64)&initial_stab;
-
/* Initialize the MMU Hash table and create the linear mapping
- * of memory. Has to be done before stab/slb initialization as
- * this is currently where the page size encoding is obtained
+ * of memory. Has to be done before SLB initialization as this is
+ * currently where the page size encoding is obtained.
*/
htab_initialize();
- /* Initialize stab / SLB management */
- if (mmu_has_feature(MMU_FTR_SLB))
- slb_initialize();
- else
- stab_initialize(get_paca()->stab_real);
+ /* Initialize SLB management */
+ slb_initialize();
}
#ifdef CONFIG_SMP
@@ -845,13 +838,8 @@ void early_init_mmu_secondary(void)
if (!firmware_has_feature(FW_FEATURE_LPAR))
mtspr(SPRN_SDR1, _SDR1);
- /* Initialize STAB/SLB. We use a virtual address as it works
- * in real mode on pSeries.
- */
- if (mmu_has_feature(MMU_FTR_SLB))
- slb_initialize();
- else
- stab_initialize(get_paca()->stab_addr);
+ /* Initialize SLB */
+ slb_initialize();
}
#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c
index 826893fcb3a7..5f5e6328c21c 100644
--- a/arch/powerpc/mm/hugepage-hash64.c
+++ b/arch/powerpc/mm/hugepage-hash64.c
@@ -18,6 +18,57 @@
#include <linux/mm.h>
#include <asm/machdep.h>
+static void invalidate_old_hpte(unsigned long vsid, unsigned long addr,
+ pmd_t *pmdp, unsigned int psize, int ssize)
+{
+ int i, max_hpte_count, valid;
+ unsigned long s_addr;
+ unsigned char *hpte_slot_array;
+ unsigned long hidx, shift, vpn, hash, slot;
+
+ s_addr = addr & HPAGE_PMD_MASK;
+ hpte_slot_array = get_hpte_slot_array(pmdp);
+ /*
+ * IF we try to do a HUGE PTE update after a withdraw is done.
+ * we will find the below NULL. This happens when we do
+ * split_huge_page_pmd
+ */
+ if (!hpte_slot_array)
+ return;
+
+ if (ppc_md.hugepage_invalidate)
+ return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array,
+ psize, ssize);
+ /*
+ * No bluk hpte removal support, invalidate each entry
+ */
+ shift = mmu_psize_defs[psize].shift;
+ max_hpte_count = HPAGE_PMD_SIZE >> shift;
+ for (i = 0; i < max_hpte_count; i++) {
+ /*
+ * 8 bits per each hpte entries
+ * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit]
+ */
+ valid = hpte_valid(hpte_slot_array, i);
+ if (!valid)
+ continue;
+ hidx = hpte_hash_index(hpte_slot_array, i);
+
+ /* get the vpn */
+ addr = s_addr + (i * (1ul << shift));
+ vpn = hpt_vpn(addr, vsid, ssize);
+ hash = hpt_hash(vpn, shift, ssize);
+ if (hidx & _PTEIDX_SECONDARY)
+ hash = ~hash;
+
+ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+ slot += hidx & _PTEIDX_GROUP_IX;
+ ppc_md.hpte_invalidate(slot, vpn, psize,
+ MMU_PAGE_16M, ssize, 0);
+ }
+}
+
+
int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
pmd_t *pmdp, unsigned long trap, int local, int ssize,
unsigned int psize)
@@ -33,7 +84,9 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
* atomically mark the linux large page PMD busy and dirty
*/
do {
- old_pmd = pmd_val(*pmdp);
+ pmd_t pmd = ACCESS_ONCE(*pmdp);
+
+ old_pmd = pmd_val(pmd);
/* If PMD busy, retry the access */
if (unlikely(old_pmd & _PAGE_BUSY))
return 0;
@@ -85,6 +138,15 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
vpn = hpt_vpn(ea, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
hpte_slot_array = get_hpte_slot_array(pmdp);
+ if (psize == MMU_PAGE_4K) {
+ /*
+ * invalidate the old hpte entry if we have that mapped via 64K
+ * base page size. This is because demote_segment won't flush
+ * hash page table entries.
+ */
+ if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO))
+ invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize);
+ }
valid = hpte_valid(hpte_slot_array, index);
if (valid) {
@@ -107,11 +169,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
* safely update this here.
*/
valid = 0;
- new_pmd &= ~_PAGE_HPTEFLAGS;
hpte_slot_array[index] = 0;
- } else
- /* clear the busy bits and set the hash pte bits */
- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
+ }
}
if (!valid) {
@@ -119,11 +178,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
/* insert new entry */
pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT;
-repeat:
- hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
-
- /* clear the busy bits and set the hash pte bits */
- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
+ new_pmd |= _PAGE_HASHPTE;
/* Add in WIMG bits */
rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
@@ -132,6 +187,8 @@ repeat:
* enable the memory coherence always
*/
rflags |= HPTE_R_M;
+repeat:
+ hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
/* Insert into the hash table, primary slot */
slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
@@ -172,8 +229,17 @@ repeat:
mark_hpte_slot_valid(hpte_slot_array, index, slot);
}
/*
- * No need to use ldarx/stdcx here
+ * Mark the pte with _PAGE_COMBO, if we are trying to hash it with
+ * base page size 4k.
+ */
+ if (psize == MMU_PAGE_4K)
+ new_pmd |= _PAGE_COMBO;
+ /*
+ * The hpte valid is stored in the pgtable whose address is in the
+ * second half of the PMD. Order this against clearing of the busy bit in
+ * huge pmd.
*/
+ smp_wmb();
*pmdp = __pmd(new_pmd & ~_PAGE_BUSY);
return 0;
}
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index e3734edffa69..253b4b971c8a 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -175,9 +175,10 @@ static unsigned long __meminit vmemmap_section_start(unsigned long page)
static int __meminit vmemmap_populated(unsigned long start, int page_size)
{
unsigned long end = start + page_size;
+ start = (unsigned long)(pfn_to_page(vmemmap_section_start(start)));
for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page)))
- if (pfn_valid(vmemmap_section_start(start)))
+ if (pfn_valid(page_to_pfn((struct page *)start)))
return 1;
return 0;
@@ -212,6 +213,13 @@ static void __meminit vmemmap_create_mapping(unsigned long start,
for (i = 0; i < page_size; i += PAGE_SIZE)
BUG_ON(map_kernel_page(start + i, phys, flags));
}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static void vmemmap_remove_mapping(unsigned long start,
+ unsigned long page_size)
+{
+}
+#endif
#else /* CONFIG_PPC_BOOK3E */
static void __meminit vmemmap_create_mapping(unsigned long start,
unsigned long page_size,
@@ -223,17 +231,42 @@ static void __meminit vmemmap_create_mapping(unsigned long start,
mmu_kernel_ssize);
BUG_ON(mapped < 0);
}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+extern int htab_remove_mapping(unsigned long vstart, unsigned long vend,
+ int psize, int ssize);
+
+static void vmemmap_remove_mapping(unsigned long start,
+ unsigned long page_size)
+{
+ int mapped = htab_remove_mapping(start, start + page_size,
+ mmu_vmemmap_psize,
+ mmu_kernel_ssize);
+ BUG_ON(mapped < 0);
+}
+#endif
+
#endif /* CONFIG_PPC_BOOK3E */
struct vmemmap_backing *vmemmap_list;
+static struct vmemmap_backing *next;
+static int num_left;
+static int num_freed;
static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node)
{
- static struct vmemmap_backing *next;
- static int num_left;
+ struct vmemmap_backing *vmem_back;
+ /* get from freed entries first */
+ if (num_freed) {
+ num_freed--;
+ vmem_back = next;
+ next = next->list;
+
+ return vmem_back;
+ }
/* allocate a page when required and hand out chunks */
- if (!next || !num_left) {
+ if (!num_left) {
next = vmemmap_alloc_block(PAGE_SIZE, node);
if (unlikely(!next)) {
WARN_ON(1);
@@ -296,10 +329,85 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
return 0;
}
-void vmemmap_free(unsigned long start, unsigned long end)
+#ifdef CONFIG_MEMORY_HOTPLUG
+static unsigned long vmemmap_list_free(unsigned long start)
{
+ struct vmemmap_backing *vmem_back, *vmem_back_prev;
+
+ vmem_back_prev = vmem_back = vmemmap_list;
+
+ /* look for it with prev pointer recorded */
+ for (; vmem_back; vmem_back = vmem_back->list) {
+ if (vmem_back->virt_addr == start)
+ break;
+ vmem_back_prev = vmem_back;
+ }
+
+ if (unlikely(!vmem_back)) {
+ WARN_ON(1);
+ return 0;
+ }
+
+ /* remove it from vmemmap_list */
+ if (vmem_back == vmemmap_list) /* remove head */
+ vmemmap_list = vmem_back->list;
+ else
+ vmem_back_prev->list = vmem_back->list;
+
+ /* next point to this freed entry */
+ vmem_back->list = next;
+ next = vmem_back;
+ num_freed++;
+
+ return vmem_back->phys;
}
+void __ref vmemmap_free(unsigned long start, unsigned long end)
+{
+ unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
+
+ start = _ALIGN_DOWN(start, page_size);
+
+ pr_debug("vmemmap_free %lx...%lx\n", start, end);
+
+ for (; start < end; start += page_size) {
+ unsigned long addr;
+
+ /*
+ * the section has already be marked as invalid, so
+ * vmemmap_populated() true means some other sections still
+ * in this page, so skip it.
+ */
+ if (vmemmap_populated(start, page_size))
+ continue;
+
+ addr = vmemmap_list_free(start);
+ if (addr) {
+ struct page *page = pfn_to_page(addr >> PAGE_SHIFT);
+
+ if (PageReserved(page)) {
+ /* allocated from bootmem */
+ if (page_size < PAGE_SIZE) {
+ /*
+ * this shouldn't happen, but if it is
+ * the case, leave the memory there
+ */
+ WARN_ON_ONCE(1);
+ } else {
+ unsigned int nr_pages =
+ 1 << get_order(page_size);
+ while (nr_pages--)
+ free_reserved_page(page++);
+ }
+ } else
+ free_pages((unsigned long)(__va(addr)),
+ get_order(page_size));
+
+ vmemmap_remove_mapping(start, page_size);
+ }
+ }
+}
+#endif
void register_page_bootmem_memmap(unsigned long section_nr,
struct page *start_page, unsigned long size)
{
@@ -331,16 +439,16 @@ struct page *realmode_pfn_to_page(unsigned long pfn)
if (pg_va < vmem_back->virt_addr)
continue;
- /* Check that page struct is not split between real pages */
- if ((pg_va + sizeof(struct page)) >
- (vmem_back->virt_addr + page_size))
- return NULL;
-
- page = (struct page *) (vmem_back->phys + pg_va -
+ /* After vmemmap_list entry free is possible, need check all */
+ if ((pg_va + sizeof(struct page)) <=
+ (vmem_back->virt_addr + page_size)) {
+ page = (struct page *) (vmem_back->phys + pg_va -
vmem_back->virt_addr);
- return page;
+ return page;
+ }
}
+ /* Probably that page struct is split between real pages */
return NULL;
}
EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 2c8e90f5789e..e0f7a189c48e 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -128,7 +128,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
return -EINVAL;
/* this should work for most non-highmem platforms */
- zone = pgdata->node_zones;
+ zone = pgdata->node_zones +
+ zone_for_memory(nid, start, size, 0);
return __add_pages(nid, zone, start_pfn, nr_pages);
}
diff --git a/arch/powerpc/mm/mmu_context_hash32.c b/arch/powerpc/mm/mmu_context_hash32.c
index 78fef6726e10..aa5a7fd89461 100644
--- a/arch/powerpc/mm/mmu_context_hash32.c
+++ b/arch/powerpc/mm/mmu_context_hash32.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * and 8260 implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 3b181b22cd46..d7737a542fd7 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -611,8 +611,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action,
case CPU_UP_CANCELED:
case CPU_UP_CANCELED_FROZEN:
unmap_cpu_from_node(lcpu);
- break;
ret = NOTIFY_OK;
+ break;
#endif
}
return ret;
@@ -1049,7 +1049,7 @@ static void __init mark_reserved_regions_for_nid(int nid)
void __init do_init_bootmem(void)
{
- int nid;
+ int nid, cpu;
min_low_pfn = 0;
max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
@@ -1122,8 +1122,15 @@ void __init do_init_bootmem(void)
reset_numa_cpu_lookup_table();
register_cpu_notifier(&ppc64_numa_nb);
- cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
- (void *)(unsigned long)boot_cpuid);
+ /*
+ * We need the numa_cpu_lookup_table to be accurate for all CPUs,
+ * even before we online them, so that we can use cpu_to_{node,mem}
+ * early in boot, cf. smp_prepare_cpus().
+ */
+ for_each_possible_cpu(cpu) {
+ cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
+ (void *)(unsigned long)cpu);
+ }
}
void __init paging_init(void)
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 343a87fa78b5..cf11342bf519 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -41,7 +41,7 @@ unsigned long ioremap_base;
unsigned long ioremap_bot;
EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
+#ifdef CONFIG_6xx
#define HAVE_BATS 1
#endif
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index f6ce1f111f5b..c8d709ab489d 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -54,6 +54,9 @@
#include "mmu_decl.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/thp.h>
+
/* Some sanity checking */
#if TASK_SIZE_USER64 > PGTABLE_RANGE
#error TASK_SIZE_USER64 exceeds pagetable range
@@ -68,7 +71,7 @@
unsigned long ioremap_bot = IOREMAP_BASE;
#ifdef CONFIG_PPC_MMU_NOHASH
-static void *early_alloc_pgtable(unsigned long size)
+static __ref void *early_alloc_pgtable(unsigned long size)
{
void *pt;
@@ -537,8 +540,9 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
old = pmd_val(*pmdp);
*pmdp = __pmd((old & ~clr) | set);
#endif
+ trace_hugepage_update(addr, old, clr, set);
if (old & _PAGE_HASHPTE)
- hpte_do_hugepage_flush(mm, addr, pmdp);
+ hpte_do_hugepage_flush(mm, addr, pmdp, old);
return old;
}
@@ -642,10 +646,11 @@ void pmdp_splitting_flush(struct vm_area_struct *vma,
* If we didn't had the splitting flag set, go and flush the
* HPTE entries.
*/
+ trace_hugepage_splitting(address, old);
if (!(old & _PAGE_SPLITTING)) {
/* We need to flush the hpte */
if (old & _PAGE_HASHPTE)
- hpte_do_hugepage_flush(vma->vm_mm, address, pmdp);
+ hpte_do_hugepage_flush(vma->vm_mm, address, pmdp, old);
}
/*
* This ensures that generic code that rely on IRQ disabling
@@ -709,6 +714,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
assert_spin_locked(&mm->page_table_lock);
WARN_ON(!pmd_trans_huge(pmd));
#endif
+ trace_hugepage_set_pmd(addr, pmd);
return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
}
@@ -723,7 +729,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
* neesd to be flushed.
*/
void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
- pmd_t *pmdp)
+ pmd_t *pmdp, unsigned long old_pmd)
{
int ssize, i;
unsigned long s_addr;
@@ -745,12 +751,29 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
if (!hpte_slot_array)
return;
- /* get the base page size */
+ /* get the base page size,vsid and segment size */
+#ifdef CONFIG_DEBUG_VM
psize = get_slice_psize(mm, s_addr);
+ BUG_ON(psize == MMU_PAGE_16M);
+#endif
+ if (old_pmd & _PAGE_COMBO)
+ psize = MMU_PAGE_4K;
+ else
+ psize = MMU_PAGE_64K;
+
+ if (!is_kernel_addr(s_addr)) {
+ ssize = user_segment_size(s_addr);
+ vsid = get_vsid(mm->context.id, s_addr, ssize);
+ WARN_ON(vsid == 0);
+ } else {
+ vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize);
+ ssize = mmu_kernel_ssize;
+ }
if (ppc_md.hugepage_invalidate)
- return ppc_md.hugepage_invalidate(mm, hpte_slot_array,
- s_addr, psize);
+ return ppc_md.hugepage_invalidate(vsid, s_addr,
+ hpte_slot_array,
+ psize, ssize);
/*
* No bluk hpte removal support, invalidate each entry
*/
@@ -768,15 +791,6 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
/* get the vpn */
addr = s_addr + (i * (1ul << shift));
- if (!is_kernel_addr(addr)) {
- ssize = user_segment_size(addr);
- vsid = get_vsid(mm->context.id, addr, ssize);
- WARN_ON(vsid == 0);
- } else {
- vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
- ssize = mmu_kernel_ssize;
- }
-
vpn = hpt_vpn(addr, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
if (hidx & _PTEIDX_SECONDARY)
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 11571e118831..5029dc19b517 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -2,7 +2,7 @@
* This file contains the routines for handling the MMU on those
* PowerPC implementations where the MMU substantially follows the
* architecture specification. This includes the 6xx, 7xx, 7xxx,
- * 8260, and POWER3 implementations but excludes the 8xx and 4xx.
+ * and 8260 implementations but excludes the 8xx and 4xx.
* -- paulus
*
* Derived from arch/ppc/mm/init.c:
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
deleted file mode 100644
index 3f8efa6f2997..000000000000
--- a/arch/powerpc/mm/stab.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * PowerPC64 Segment Translation Support.
- *
- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
- * Copyright (c) 2001 Dave Engebretsen
- *
- * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
- *
- * 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/memblock.h>
-
-#include <asm/pgtable.h>
-#include <asm/mmu.h>
-#include <asm/mmu_context.h>
-#include <asm/paca.h>
-#include <asm/cputable.h>
-#include <asm/prom.h>
-
-struct stab_entry {
- unsigned long esid_data;
- unsigned long vsid_data;
-};
-
-#define NR_STAB_CACHE_ENTRIES 8
-static DEFINE_PER_CPU(long, stab_cache_ptr);
-static DEFINE_PER_CPU(long [NR_STAB_CACHE_ENTRIES], stab_cache);
-
-/*
- * Create a segment table entry for the given esid/vsid pair.
- */
-static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
-{
- unsigned long esid_data, vsid_data;
- unsigned long entry, group, old_esid, castout_entry, i;
- unsigned int global_entry;
- struct stab_entry *ste, *castout_ste;
- unsigned long kernel_segment = (esid << SID_SHIFT) >= PAGE_OFFSET;
-
- vsid_data = vsid << STE_VSID_SHIFT;
- esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
- if (! kernel_segment)
- esid_data |= STE_ESID_KS;
-
- /* Search the primary group first. */
- global_entry = (esid & 0x1f) << 3;
- ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
-
- /* Find an empty entry, if one exists. */
- for (group = 0; group < 2; group++) {
- for (entry = 0; entry < 8; entry++, ste++) {
- if (!(ste->esid_data & STE_ESID_V)) {
- ste->vsid_data = vsid_data;
- eieio();
- ste->esid_data = esid_data;
- return (global_entry | entry);
- }
- }
- /* Now search the secondary group. */
- global_entry = ((~esid) & 0x1f) << 3;
- ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
- }
-
- /*
- * Could not find empty entry, pick one with a round robin selection.
- * Search all entries in the two groups.
- */
- castout_entry = get_paca()->stab_rr;
- for (i = 0; i < 16; i++) {
- if (castout_entry < 8) {
- global_entry = (esid & 0x1f) << 3;
- ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
- castout_ste = ste + castout_entry;
- } else {
- global_entry = ((~esid) & 0x1f) << 3;
- ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
- castout_ste = ste + (castout_entry - 8);
- }
-
- /* Dont cast out the first kernel segment */
- if ((castout_ste->esid_data & ESID_MASK) != PAGE_OFFSET)
- break;
-
- castout_entry = (castout_entry + 1) & 0xf;
- }
-
- get_paca()->stab_rr = (castout_entry + 1) & 0xf;
-
- /* Modify the old entry to the new value. */
-
- /* Force previous translations to complete. DRENG */
- asm volatile("isync" : : : "memory");
-
- old_esid = castout_ste->esid_data >> SID_SHIFT;
- castout_ste->esid_data = 0; /* Invalidate old entry */
-
- asm volatile("sync" : : : "memory"); /* Order update */
-
- castout_ste->vsid_data = vsid_data;
- eieio(); /* Order update */
- castout_ste->esid_data = esid_data;
-
- asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT));
- /* Ensure completion of slbie */
- asm volatile("sync" : : : "memory");
-
- return (global_entry | (castout_entry & 0x7));
-}
-
-/*
- * Allocate a segment table entry for the given ea and mm
- */
-static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
-{
- unsigned long vsid;
- unsigned char stab_entry;
- unsigned long offset;
-
- /* Kernel or user address? */
- if (is_kernel_addr(ea)) {
- vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
- } else {
- if ((ea >= TASK_SIZE_USER64) || (! mm))
- return 1;
-
- vsid = get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M);
- }
-
- stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
-
- if (!is_kernel_addr(ea)) {
- offset = __get_cpu_var(stab_cache_ptr);
- if (offset < NR_STAB_CACHE_ENTRIES)
- __get_cpu_var(stab_cache[offset++]) = stab_entry;
- else
- offset = NR_STAB_CACHE_ENTRIES+1;
- __get_cpu_var(stab_cache_ptr) = offset;
-
- /* Order update */
- asm volatile("sync":::"memory");
- }
-
- return 0;
-}
-
-int ste_allocate(unsigned long ea)
-{
- return __ste_allocate(ea, current->mm);
-}
-
-/*
- * Do the segment table work for a context switch: flush all user
- * entries from the table, then preload some probably useful entries
- * for the new task
- */
-void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
-{
- struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
- struct stab_entry *ste;
- unsigned long offset;
- unsigned long pc = KSTK_EIP(tsk);
- unsigned long stack = KSTK_ESP(tsk);
- unsigned long unmapped_base;
-
- /* Force previous translations to complete. DRENG */
- asm volatile("isync" : : : "memory");
-
- /*
- * We need interrupts hard-disabled here, not just soft-disabled,
- * so that a PMU interrupt can't occur, which might try to access
- * user memory (to get a stack trace) and possible cause an STAB miss
- * which would update the stab_cache/stab_cache_ptr per-cpu variables.
- */
- hard_irq_disable();
-
- offset = __get_cpu_var(stab_cache_ptr);
- if (offset <= NR_STAB_CACHE_ENTRIES) {
- int i;
-
- for (i = 0; i < offset; i++) {
- ste = stab + __get_cpu_var(stab_cache[i]);
- ste->esid_data = 0; /* invalidate entry */
- }
- } else {
- unsigned long entry;
-
- /* Invalidate all entries. */
- ste = stab;
-
- /* Never flush the first entry. */
- ste += 1;
- for (entry = 1;
- entry < (HW_PAGE_SIZE / sizeof(struct stab_entry));
- entry++, ste++) {
- unsigned long ea;
- ea = ste->esid_data & ESID_MASK;
- if (!is_kernel_addr(ea)) {
- ste->esid_data = 0;
- }
- }
- }
-
- asm volatile("sync; slbia; sync":::"memory");
-
- __get_cpu_var(stab_cache_ptr) = 0;
-
- /* Now preload some entries for the new task */
- if (test_tsk_thread_flag(tsk, TIF_32BIT))
- unmapped_base = TASK_UNMAPPED_BASE_USER32;
- else
- unmapped_base = TASK_UNMAPPED_BASE_USER64;
-
- __ste_allocate(pc, mm);
-
- if (GET_ESID(pc) == GET_ESID(stack))
- return;
-
- __ste_allocate(stack, mm);
-
- if ((GET_ESID(pc) == GET_ESID(unmapped_base))
- || (GET_ESID(stack) == GET_ESID(unmapped_base)))
- return;
-
- __ste_allocate(unmapped_base, mm);
-
- /* Order update */
- asm volatile("sync" : : : "memory");
-}
-
-/*
- * Allocate segment tables for secondary CPUs. These must all go in
- * the first (bolted) segment, so that do_stab_bolted won't get a
- * recursive segment miss on the segment table itself.
- */
-void __init stabs_alloc(void)
-{
- int cpu;
-
- if (mmu_has_feature(MMU_FTR_SLB))
- return;
-
- for_each_possible_cpu(cpu) {
- unsigned long newstab;
-
- if (cpu == 0)
- continue; /* stab for CPU 0 is statically allocated */
-
- newstab = memblock_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE,
- 1<<SID_SHIFT);
- newstab = (unsigned long)__va(newstab);
-
- memset((void *)newstab, 0, HW_PAGE_SIZE);
-
- paca[cpu].stab_addr = newstab;
- paca[cpu].stab_real = __pa(newstab);
- printk(KERN_INFO "Segment table for CPU %d at 0x%llx "
- "virtual, 0x%llx absolute\n",
- cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
- }
-}
-
-/*
- * Build an entry for the base kernel segment and put it into
- * the segment table or SLB. All other segment table or SLB
- * entries are faulted in.
- */
-void stab_initialize(unsigned long stab)
-{
- unsigned long vsid = get_kernel_vsid(PAGE_OFFSET, MMU_SEGSIZE_256M);
- unsigned long stabreal;
-
- asm volatile("isync; slbia; isync":::"memory");
- make_ste(stab, GET_ESID(PAGE_OFFSET), vsid);
-
- /* Order update */
- asm volatile("sync":::"memory");
-
- /* Set ASR */
- stabreal = get_paca()->stab_real | 0x1ul;
-
- mtspr(SPRN_ASR, stabreal);
-}
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index c99f6510a0b2..d2a94b85dbc2 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -30,6 +30,8 @@
#include <asm/tlb.h>
#include <asm/bug.h>
+#include <trace/events/thp.h>
+
DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
/*
@@ -213,10 +215,12 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
if (ptep == NULL)
continue;
pte = pte_val(*ptep);
+ if (hugepage_shift)
+ trace_hugepage_invalidate(start, pte_val(pte));
if (!(pte & _PAGE_HASHPTE))
continue;
if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte)))
- hpte_do_hugepage_flush(mm, start, (pmd_t *)pte);
+ hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte);
else
hpte_need_flush(mm, start, ptep, pte, 0);
}
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index 356e8b41fb09..89bf95bd63b1 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -296,9 +296,12 @@ itlb_miss_fault_bolted:
* r14 = page table base
* r13 = PACA
* r11 = tlb_per_core ptr
- * r10 = cpu number
+ * r10 = crap (free to use)
*/
tlb_miss_common_e6500:
+ crmove cr2*4+2,cr0*4+2 /* cr2.eq != 0 if kernel address */
+
+BEGIN_FTR_SECTION /* CPU_FTR_SMT */
/*
* Search if we already have an indirect entry for that virtual
* address, and if we do, bail out.
@@ -309,6 +312,7 @@ tlb_miss_common_e6500:
lhz r10,PACAPACAINDEX(r13)
cmpdi r15,0
cmpdi cr1,r15,1 /* set cr1.eq = 0 for non-recursive */
+ addi r10,r10,1
bne 2f
stbcx. r10,0,r11
bne 1b
@@ -322,18 +326,62 @@ tlb_miss_common_e6500:
b 1b
.previous
+ /*
+ * Erratum A-008139 says that we can't use tlbwe to change
+ * an indirect entry in any way (including replacing or
+ * invalidating) if the other thread could be in the process
+ * of a lookup. The workaround is to invalidate the entry
+ * with tlbilx before overwriting.
+ */
+
+ lbz r15,TCD_ESEL_NEXT(r11)
+ rlwinm r10,r15,16,0xff0000
+ oris r10,r10,MAS0_TLBSEL(1)@h
+ mtspr SPRN_MAS0,r10
+ isync
+ tlbre
+ mfspr r15,SPRN_MAS1
+ andis. r15,r15,MAS1_VALID@h
+ beq 5f
+
+BEGIN_FTR_SECTION_NESTED(532)
+ mfspr r10,SPRN_MAS8
+ rlwinm r10,r10,0,0x80000fff /* tgs,tlpid -> sgs,slpid */
+ mtspr SPRN_MAS5,r10
+END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
+
+ mfspr r10,SPRN_MAS1
+ rlwinm r15,r10,0,0x3fff0000 /* tid -> spid */
+ rlwimi r15,r10,20,0x00000003 /* ind,ts -> sind,sas */
+ mfspr r10,SPRN_MAS6
+ mtspr SPRN_MAS6,r15
+
mfspr r15,SPRN_MAS2
+ isync
+ tlbilxva 0,r15
+ isync
+
+ mtspr SPRN_MAS6,r10
+
+5:
+BEGIN_FTR_SECTION_NESTED(532)
+ li r10,0
+ mtspr SPRN_MAS8,r10
+ mtspr SPRN_MAS5,r10
+END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
tlbsx 0,r16
mfspr r10,SPRN_MAS1
- andis. r10,r10,MAS1_VALID@h
+ andis. r15,r10,MAS1_VALID@h
bne tlb_miss_done_e6500
-
- /* Undo MAS-damage from the tlbsx */
+FTR_SECTION_ELSE
mfspr r10,SPRN_MAS1
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT)
+
oris r10,r10,MAS1_VALID@h
- mtspr SPRN_MAS1,r10
- mtspr SPRN_MAS2,r15
+ beq cr2,4f
+ rlwinm r10,r10,0,16,1 /* Clear TID */
+4: mtspr SPRN_MAS1,r10
/* Now, we need to walk the page tables. First check if we are in
* range.
@@ -394,11 +442,13 @@ tlb_miss_common_e6500:
tlb_miss_done_e6500:
.macro tlb_unlock_e6500
+BEGIN_FTR_SECTION
beq cr1,1f /* no unlock if lock was recursively grabbed */
li r15,0
isync
stb r15,0(r11)
1:
+END_FTR_SECTION_IFSET(CPU_FTR_SMT)
.endm
tlb_unlock_e6500
@@ -407,12 +457,9 @@ tlb_miss_done_e6500:
rfi
tlb_miss_kernel_e6500:
- mfspr r10,SPRN_MAS1
ld r14,PACA_KERNELPGD(r13)
- cmpldi cr0,r15,8 /* Check for vmalloc region */
- rlwinm r10,r10,0,16,1 /* Clear TID */
- mtspr SPRN_MAS1,r10
- beq+ tlb_miss_common_e6500
+ cmpldi cr1,r15,8 /* Check for vmalloc region */
+ beq+ cr1,tlb_miss_common_e6500
tlb_miss_fault_e6500:
tlb_unlock_e6500
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 92cb18d52ea8..f38ea4df6a85 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -581,42 +581,10 @@ static void setup_mmu_htw(void)
/*
* Early initialization of the MMU TLB code
*/
-static void __early_init_mmu(int boot_cpu)
+static void early_init_this_mmu(void)
{
unsigned int mas4;
- /* XXX This will have to be decided at runtime, but right
- * now our boot and TLB miss code hard wires it. Ideally
- * we should find out a suitable page size and patch the
- * TLB miss code (either that or use the PACA to store
- * the value we want)
- */
- mmu_linear_psize = MMU_PAGE_1G;
-
- /* XXX This should be decided at runtime based on supported
- * page sizes in the TLB, but for now let's assume 16M is
- * always there and a good fit (which it probably is)
- *
- * Freescale booke only supports 4K pages in TLB0, so use that.
- */
- if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
- mmu_vmemmap_psize = MMU_PAGE_4K;
- else
- mmu_vmemmap_psize = MMU_PAGE_16M;
-
- /* XXX This code only checks for TLB 0 capabilities and doesn't
- * check what page size combos are supported by the HW. It
- * also doesn't handle the case where a separate array holds
- * the IND entries from the array loaded by the PT.
- */
- if (boot_cpu) {
- /* Look for supported page sizes */
- setup_page_sizes();
-
- /* Look for HW tablewalk support */
- setup_mmu_htw();
- }
-
/* Set MAS4 based on page table setting */
mas4 = 0x4 << MAS4_WIMGED_SHIFT;
@@ -650,11 +618,6 @@ static void __early_init_mmu(int boot_cpu)
}
mtspr(SPRN_MAS4, mas4);
- /* Set the global containing the top of the linear mapping
- * for use by the TLB miss code
- */
- linear_map_top = memblock_end_of_DRAM();
-
#ifdef CONFIG_PPC_FSL_BOOK3E
if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
unsigned int num_cams;
@@ -662,10 +625,49 @@ static void __early_init_mmu(int boot_cpu)
/* use a quarter of the TLBCAM for bolted linear map */
num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
linear_map_top = map_mem_in_cams(linear_map_top, num_cams);
+ }
+#endif
- /* limit memory so we dont have linear faults */
- memblock_enforce_memory_limit(linear_map_top);
+ /* A sync won't hurt us after mucking around with
+ * the MMU configuration
+ */
+ mb();
+}
+static void __init early_init_mmu_global(void)
+{
+ /* XXX This will have to be decided at runtime, but right
+ * now our boot and TLB miss code hard wires it. Ideally
+ * we should find out a suitable page size and patch the
+ * TLB miss code (either that or use the PACA to store
+ * the value we want)
+ */
+ mmu_linear_psize = MMU_PAGE_1G;
+
+ /* XXX This should be decided at runtime based on supported
+ * page sizes in the TLB, but for now let's assume 16M is
+ * always there and a good fit (which it probably is)
+ *
+ * Freescale booke only supports 4K pages in TLB0, so use that.
+ */
+ if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
+ mmu_vmemmap_psize = MMU_PAGE_4K;
+ else
+ mmu_vmemmap_psize = MMU_PAGE_16M;
+
+ /* XXX This code only checks for TLB 0 capabilities and doesn't
+ * check what page size combos are supported by the HW. It
+ * also doesn't handle the case where a separate array holds
+ * the IND entries from the array loaded by the PT.
+ */
+ /* Look for supported page sizes */
+ setup_page_sizes();
+
+ /* Look for HW tablewalk support */
+ setup_mmu_htw();
+
+#ifdef CONFIG_PPC_FSL_BOOK3E
+ if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
if (book3e_htw_mode == PPC_HTW_NONE) {
extlb_level_exc = EX_TLB_SIZE;
patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
@@ -675,22 +677,41 @@ static void __early_init_mmu(int boot_cpu)
}
#endif
- /* A sync won't hurt us after mucking around with
- * the MMU configuration
+ /* Set the global containing the top of the linear mapping
+ * for use by the TLB miss code
*/
- mb();
+ linear_map_top = memblock_end_of_DRAM();
+}
+
+static void __init early_mmu_set_memory_limit(void)
+{
+#ifdef CONFIG_PPC_FSL_BOOK3E
+ if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) {
+ /*
+ * Limit memory so we dont have linear faults.
+ * Unlike memblock_set_current_limit, which limits
+ * memory available during early boot, this permanently
+ * reduces the memory available to Linux. We need to
+ * do this because highmem is not supported on 64-bit.
+ */
+ memblock_enforce_memory_limit(linear_map_top);
+ }
+#endif
memblock_set_current_limit(linear_map_top);
}
+/* boot cpu only */
void __init early_init_mmu(void)
{
- __early_init_mmu(1);
+ early_init_mmu_global();
+ early_init_this_mmu();
+ early_mmu_set_memory_limit();
}
void early_init_mmu_secondary(void)
{
- __early_init_mmu(0);
+ early_init_this_mmu();
}
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 82e82cadcde5..3afa6f4c1957 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -25,7 +25,7 @@ static inline void bpf_flush_icache(void *start, void *end)
flush_icache_range((unsigned long)start, (unsigned long)end);
}
-static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image,
struct codegen_context *ctx)
{
int i;
@@ -121,7 +121,7 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
/* Assemble the body code between the prologue & epilogue. */
-static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
struct codegen_context *ctx,
unsigned int *addrs)
{
@@ -569,7 +569,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
return 0;
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
unsigned int proglen;
unsigned int alloclen;
@@ -693,7 +693,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 751ec7bd5018..cedbbeced632 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -14,6 +14,6 @@ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o
oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \
cell/spu_profiler.o cell/vma_map.o \
cell/spu_task_sync.o
-oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o
+oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_power4.o op_model_pa6t.o
oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o
oprofile-$(CONFIG_6xx) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index c77348c5d463..bf094c5a4bd9 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -205,9 +205,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->sync_stop = model->sync_stop;
break;
#endif
- case PPC_OPROFILE_RS64:
- model = &op_model_rs64;
- break;
case PPC_OPROFILE_POWER4:
model = &op_model_power4;
break;
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
deleted file mode 100644
index 7e5b8ed3a1b7..000000000000
--- a/arch/powerpc/oprofile/op_model_rs64.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- *
- * 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/oprofile.h>
-#include <linux/smp.h>
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/cputable.h>
-#include <asm/oprofile_impl.h>
-
-#define dbg(args...)
-
-static void ctrl_write(unsigned int i, unsigned int val)
-{
- unsigned int tmp = 0;
- unsigned long shift = 0, mask = 0;
-
- dbg("ctrl_write %d %x\n", i, val);
-
- switch(i) {
- case 0:
- tmp = mfspr(SPRN_MMCR0);
- shift = 6;
- mask = 0x7F;
- break;
- case 1:
- tmp = mfspr(SPRN_MMCR0);
- shift = 0;
- mask = 0x3F;
- break;
- case 2:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 4;
- mask = 0x1F;
- break;
- case 3:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 9;
- mask = 0x1F;
- break;
- case 4:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 14;
- mask = 0x1F;
- break;
- case 5:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 19;
- mask = 0x1F;
- break;
- case 6:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 24;
- mask = 0x1F;
- break;
- case 7:
- tmp = mfspr(SPRN_MMCR1);
- shift = 31 - 28;
- mask = 0xF;
- break;
- }
-
- tmp = tmp & ~(mask << shift);
- tmp |= val << shift;
-
- switch(i) {
- case 0:
- case 1:
- mtspr(SPRN_MMCR0, tmp);
- break;
- default:
- mtspr(SPRN_MMCR1, tmp);
- }
-
- dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0),
- mfspr(SPRN_MMCR1));
-}
-
-static unsigned long reset_value[OP_MAX_COUNTER];
-
-static int num_counters;
-
-static int rs64_reg_setup(struct op_counter_config *ctr,
- struct op_system_config *sys,
- int num_ctrs)
-{
- int i;
-
- num_counters = num_ctrs;
-
- for (i = 0; i < num_counters; ++i)
- reset_value[i] = 0x80000000UL - ctr[i].count;
-
- /* XXX setup user and kernel profiling */
- return 0;
-}
-
-static int rs64_cpu_setup(struct op_counter_config *ctr)
-{
- unsigned int mmcr0;
-
- /* reset MMCR0 and set the freeze bit */
- mmcr0 = MMCR0_FC;
- mtspr(SPRN_MMCR0, mmcr0);
-
- /* reset MMCR1, MMCRA */
- mtspr(SPRN_MMCR1, 0);
-
- if (cpu_has_feature(CPU_FTR_MMCRA))
- mtspr(SPRN_MMCRA, 0);
-
- mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
- /* Only applies to POWER3, but should be safe on RS64 */
- mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE;
- mtspr(SPRN_MMCR0, mmcr0);
-
- dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(),
- mfspr(SPRN_MMCR0));
- dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(),
- mfspr(SPRN_MMCR1));
-
- return 0;
-}
-
-static int rs64_start(struct op_counter_config *ctr)
-{
- int i;
- unsigned int mmcr0;
-
- /* set the PMM bit (see comment below) */
- mtmsrd(mfmsr() | MSR_PMM);
-
- for (i = 0; i < num_counters; ++i) {
- if (ctr[i].enabled) {
- classic_ctr_write(i, reset_value[i]);
- ctrl_write(i, ctr[i].event);
- } else {
- classic_ctr_write(i, 0);
- }
- }
-
- mmcr0 = mfspr(SPRN_MMCR0);
-
- /*
- * now clear the freeze bit, counting will not start until we
- * rfid from this excetion, because only at that point will
- * the PMM bit be cleared
- */
- mmcr0 &= ~MMCR0_FC;
- mtspr(SPRN_MMCR0, mmcr0);
-
- dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
- return 0;
-}
-
-static void rs64_stop(void)
-{
- unsigned int mmcr0;
-
- /* freeze counters */
- mmcr0 = mfspr(SPRN_MMCR0);
- mmcr0 |= MMCR0_FC;
- mtspr(SPRN_MMCR0, mmcr0);
-
- dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0);
-
- mb();
-}
-
-static void rs64_handle_interrupt(struct pt_regs *regs,
- struct op_counter_config *ctr)
-{
- unsigned int mmcr0;
- int is_kernel;
- int val;
- int i;
- unsigned long pc = mfspr(SPRN_SIAR);
-
- is_kernel = is_kernel_addr(pc);
-
- /* set the PMM bit (see comment below) */
- mtmsrd(mfmsr() | MSR_PMM);
-
- for (i = 0; i < num_counters; ++i) {
- val = classic_ctr_read(i);
- if (val < 0) {
- if (ctr[i].enabled) {
- oprofile_add_ext_sample(pc, regs, i, is_kernel);
- classic_ctr_write(i, reset_value[i]);
- } else {
- classic_ctr_write(i, 0);
- }
- }
- }
-
- mmcr0 = mfspr(SPRN_MMCR0);
-
- /* reset the perfmon trigger */
- mmcr0 |= MMCR0_PMXE;
-
- /*
- * now clear the freeze bit, counting will not start until we
- * rfid from this exception, because only at that point will
- * the PMM bit be cleared
- */
- mmcr0 &= ~MMCR0_FC;
- mtspr(SPRN_MMCR0, mmcr0);
-}
-
-struct op_powerpc_model op_model_rs64 = {
- .reg_setup = rs64_reg_setup,
- .cpu_setup = rs64_cpu_setup,
- .start = rs64_start,
- .stop = rs64_stop,
- .handle_interrupt = rs64_handle_interrupt,
-};
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index fe52db2eea6a..b7cd00b0171e 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -36,7 +36,12 @@ struct cpu_hw_events {
struct perf_event *event[MAX_HWEVENTS];
u64 events[MAX_HWEVENTS];
unsigned int flags[MAX_HWEVENTS];
- unsigned long mmcr[3];
+ /*
+ * The order of the MMCR array is:
+ * - 64-bit, MMCR0, MMCR1, MMCRA, MMCR2
+ * - 32-bit, MMCR0, MMCR1, MMCR2
+ */
+ unsigned long mmcr[4];
struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS];
u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS];
u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES];
@@ -112,9 +117,9 @@ static bool is_ebb_event(struct perf_event *event) { return false; }
static int ebb_event_check(struct perf_event *event) { return 0; }
static void ebb_event_add(struct perf_event *event) { }
static void ebb_switch_out(unsigned long mmcr0) { }
-static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
+static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
{
- return mmcr0;
+ return cpuhw->mmcr[0];
}
static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
@@ -542,8 +547,10 @@ static void ebb_switch_out(unsigned long mmcr0)
current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK;
}
-static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
+static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
{
+ unsigned long mmcr0 = cpuhw->mmcr[0];
+
if (!ebb)
goto out;
@@ -568,7 +575,15 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0)
mtspr(SPRN_SIAR, current->thread.siar);
mtspr(SPRN_SIER, current->thread.sier);
mtspr(SPRN_SDAR, current->thread.sdar);
- mtspr(SPRN_MMCR2, current->thread.mmcr2);
+
+ /*
+ * Merge the kernel & user values of MMCR2. The semantics we implement
+ * are that the user MMCR2 can set bits, ie. cause counters to freeze,
+ * but not clear bits. If a task wants to be able to clear bits, ie.
+ * unfreeze counters, it should not set exclude_xxx in its events and
+ * instead manage the MMCR2 entirely by itself.
+ */
+ mtspr(SPRN_MMCR2, cpuhw->mmcr[3] | current->thread.mmcr2);
out:
return mmcr0;
}
@@ -915,6 +930,14 @@ static int check_excludes(struct perf_event **ctrs, unsigned int cflags[],
int i, n, first;
struct perf_event *event;
+ /*
+ * If the PMU we're on supports per event exclude settings then we
+ * don't need to do any of this logic. NB. This assumes no PMU has both
+ * per event exclude and limited PMCs.
+ */
+ if (ppmu->flags & PPMU_ARCH_207S)
+ return 0;
+
n = n_prev + n_new;
if (n <= 1)
return 0;
@@ -1219,28 +1242,31 @@ static void power_pmu_enable(struct pmu *pmu)
}
/*
- * Compute MMCR* values for the new set of events
+ * Clear all MMCR settings and recompute them for the new set of events.
*/
+ memset(cpuhw->mmcr, 0, sizeof(cpuhw->mmcr));
+
if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index,
- cpuhw->mmcr)) {
+ cpuhw->mmcr, cpuhw->event)) {
/* shouldn't ever get here */
printk(KERN_ERR "oops compute_mmcr failed\n");
goto out;
}
- /*
- * Add in MMCR0 freeze bits corresponding to the
- * attr.exclude_* bits for the first event.
- * We have already checked that all events have the
- * same values for these bits as the first event.
- */
- event = cpuhw->event[0];
- if (event->attr.exclude_user)
- cpuhw->mmcr[0] |= MMCR0_FCP;
- if (event->attr.exclude_kernel)
- cpuhw->mmcr[0] |= freeze_events_kernel;
- if (event->attr.exclude_hv)
- cpuhw->mmcr[0] |= MMCR0_FCHV;
+ if (!(ppmu->flags & PPMU_ARCH_207S)) {
+ /*
+ * Add in MMCR0 freeze bits corresponding to the attr.exclude_*
+ * bits for the first event. We have already checked that all
+ * events have the same value for these bits as the first event.
+ */
+ event = cpuhw->event[0];
+ if (event->attr.exclude_user)
+ cpuhw->mmcr[0] |= MMCR0_FCP;
+ if (event->attr.exclude_kernel)
+ cpuhw->mmcr[0] |= freeze_events_kernel;
+ if (event->attr.exclude_hv)
+ cpuhw->mmcr[0] |= MMCR0_FCHV;
+ }
/*
* Write the new configuration to MMCR* with the freeze
@@ -1252,6 +1278,8 @@ static void power_pmu_enable(struct pmu *pmu)
mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
| MMCR0_FC);
+ if (ppmu->flags & PPMU_ARCH_207S)
+ mtspr(SPRN_MMCR2, cpuhw->mmcr[3]);
/*
* Read off any pre-existing events that need to move
@@ -1307,10 +1335,7 @@ static void power_pmu_enable(struct pmu *pmu)
out_enable:
pmao_restore_workaround(ebb);
- if (ppmu->flags & PPMU_ARCH_207S)
- mtspr(SPRN_MMCR2, 0);
-
- mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]);
+ mmcr0 = ebb_switch_in(ebb, cpuhw);
mb();
if (cpuhw->bhrb_users)
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index e0766b82e165..70d4f748b54b 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -223,7 +223,7 @@ e_free:
pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
" rc=%ld\n",
catalog_version_num, page_offset, hret);
- kfree(page);
+ kmem_cache_free(hv_page_cache, page);
pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n",
offset, page_offset, count, page_count, catalog_len,
@@ -387,8 +387,7 @@ static int h_24x7_event_init(struct perf_event *event)
event->attr.exclude_hv ||
event->attr.exclude_idle ||
event->attr.exclude_host ||
- event->attr.exclude_guest ||
- is_sampling_event(event)) /* no sampling */
+ event->attr.exclude_guest)
return -EINVAL;
/* no branch sampling */
@@ -513,6 +512,9 @@ static int hv_24x7_init(void)
if (!hv_page_cache)
return -ENOMEM;
+ /* sampling not supported */
+ h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
if (r)
return r;
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index c9d399a2df82..15fc76c93022 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -210,8 +210,7 @@ static int h_gpci_event_init(struct perf_event *event)
event->attr.exclude_hv ||
event->attr.exclude_idle ||
event->attr.exclude_host ||
- event->attr.exclude_guest ||
- is_sampling_event(event)) /* no sampling */
+ event->attr.exclude_guest)
return -EINVAL;
/* no branch sampling */
@@ -284,6 +283,9 @@ static int hv_gpci_init(void)
return -ENODEV;
}
+ /* sampling not supported */
+ h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1);
if (r)
return r;
diff --git a/arch/powerpc/perf/mpc7450-pmu.c b/arch/powerpc/perf/mpc7450-pmu.c
index fe21b515ca44..d115c5635bf3 100644
--- a/arch/powerpc/perf/mpc7450-pmu.c
+++ b/arch/powerpc/perf/mpc7450-pmu.c
@@ -260,8 +260,9 @@ static const u32 pmcsel_mask[N_COUNTER] = {
/*
* Compute MMCR0/1/2 values for a set of events.
*/
-static int mpc7450_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+static int mpc7450_compute_mmcr(u64 event[], int n_ev, unsigned int hwc[],
+ unsigned long mmcr[],
+ struct perf_event *pevents[])
{
u8 event_index[N_CLASSES][N_COUNTER];
int n_classevent[N_CLASSES];
diff --git a/arch/powerpc/perf/power4-pmu.c b/arch/powerpc/perf/power4-pmu.c
index 9103a1de864d..ce6072fa481b 100644
--- a/arch/powerpc/perf/power4-pmu.c
+++ b/arch/powerpc/perf/power4-pmu.c
@@ -356,7 +356,7 @@ static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[])
}
static int p4_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
unsigned int pmc, unit, byte, psel, lower;
diff --git a/arch/powerpc/perf/power5+-pmu.c b/arch/powerpc/perf/power5+-pmu.c
index b03b6dc0172d..0526dac66007 100644
--- a/arch/powerpc/perf/power5+-pmu.c
+++ b/arch/powerpc/perf/power5+-pmu.c
@@ -452,7 +452,7 @@ static int power5p_marked_instr_event(u64 event)
}
static int power5p_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr1 = 0;
unsigned long mmcra = 0;
diff --git a/arch/powerpc/perf/power5-pmu.c b/arch/powerpc/perf/power5-pmu.c
index 1e8ce423c3af..4dc99f9f7962 100644
--- a/arch/powerpc/perf/power5-pmu.c
+++ b/arch/powerpc/perf/power5-pmu.c
@@ -383,7 +383,7 @@ static int power5_marked_instr_event(u64 event)
}
static int power5_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr1 = 0;
unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff --git a/arch/powerpc/perf/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c
index 31128e086fed..9c9d646b68a1 100644
--- a/arch/powerpc/perf/power6-pmu.c
+++ b/arch/powerpc/perf/power6-pmu.c
@@ -175,7 +175,7 @@ static int power6_marked_instr_event(u64 event)
* Assign PMC numbers and compute MMCR1 value for a set of events
*/
static int p6_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr1 = 0;
unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index 56c67bca2f75..5b62f2389290 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -245,7 +245,7 @@ static int power7_marked_instr_event(u64 event)
}
static int power7_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr1 = 0;
unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 639cd9156585..396351db601b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/perf_event.h>
#include <asm/firmware.h>
+#include <asm/cputable.h>
/*
@@ -266,6 +267,11 @@
#define MMCRA_SDAR_MODE_TLB (1ull << 42)
#define MMCRA_IFM_SHIFT 30
+/* Bits in MMCR2 for POWER8 */
+#define MMCR2_FCS(pmc) (1ull << (63 - (((pmc) - 1) * 9)))
+#define MMCR2_FCP(pmc) (1ull << (62 - (((pmc) - 1) * 9)))
+#define MMCR2_FCH(pmc) (1ull << (57 - (((pmc) - 1) * 9)))
+
static inline bool event_is_fab_match(u64 event)
{
@@ -393,9 +399,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long
}
static int power8_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[],
+ struct perf_event *pevents[])
{
- unsigned long mmcra, mmcr1, unit, combine, psel, cache, val;
+ unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val;
unsigned int pmc, pmc_inuse;
int i;
@@ -410,7 +417,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
/* In continous sampling mode, update SDAR on TLB miss */
mmcra = MMCRA_SDAR_MODE_TLB;
- mmcr1 = 0;
+ mmcr1 = mmcr2 = 0;
/* Second pass: assign PMCs, set all MMCR1 fields */
for (i = 0; i < n_ev; ++i) {
@@ -472,6 +479,19 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
mmcra |= val << MMCRA_IFM_SHIFT;
}
+ if (pevents[i]->attr.exclude_user)
+ mmcr2 |= MMCR2_FCP(pmc);
+
+ if (pevents[i]->attr.exclude_hv)
+ mmcr2 |= MMCR2_FCH(pmc);
+
+ if (pevents[i]->attr.exclude_kernel) {
+ if (cpu_has_feature(CPU_FTR_HVMODE))
+ mmcr2 |= MMCR2_FCH(pmc);
+ else
+ mmcr2 |= MMCR2_FCS(pmc);
+ }
+
hwc[i] = pmc - 1;
}
@@ -491,6 +511,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
mmcr[1] = mmcr1;
mmcr[2] = mmcra;
+ mmcr[3] = mmcr2;
return 0;
}
diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c
index 20139ceeacf6..8b6a8a36fa38 100644
--- a/arch/powerpc/perf/ppc970-pmu.c
+++ b/arch/powerpc/perf/ppc970-pmu.c
@@ -257,7 +257,7 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
}
static int p970_compute_mmcr(u64 event[], int n_ev,
- unsigned int hwc[], unsigned long mmcr[])
+ unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
{
unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
unsigned int pmc, unit, byte, psel;
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 534574a97ec9..3a104284b338 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -25,6 +25,7 @@
#include <asm/time.h>
#include <asm/uic.h>
#include <asm/ppc4xx.h>
+#include <asm/dma.h>
static __initdata struct of_device_id warp_of_bus[] = {
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 6e19b0ad5d26..3feffde9128d 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -13,6 +13,7 @@
#include <generated/utsrelease.h>
#include <linux/pci.h>
#include <linux/of.h>
+#include <asm/dma.h>
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index f442120e0033..0c1e6903597e 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -274,7 +274,7 @@ config CORENET_GENERIC
For 32bit kernel, the following boards are supported:
P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080
For 64bit kernel, the following boards are supported:
- T4240 QDS and B4 QDS
+ T208x QDS/RDB, T4240 QDS/RDB and B4 QDS
The following boards are supported for both 32bit and 64bit kernel:
P5020 DS, P5040 DS and T104xQDS
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index 5db1e117fdde..d22dd85e50bf 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -119,7 +119,11 @@ static const char * const boards[] __initconst = {
"fsl,P4080DS",
"fsl,P5020DS",
"fsl,P5040DS",
+ "fsl,T2080QDS",
+ "fsl,T2080RDB",
+ "fsl,T2081QDS",
"fsl,T4240QDS",
+ "fsl,T4240RDB",
"fsl,B4860QDS",
"fsl,B4420QDS",
"fsl,B4220QDS",
@@ -129,28 +133,14 @@ static const char * const boards[] __initconst = {
NULL
};
-static const char * const hv_boards[] __initconst = {
- "fsl,P2041RDB-hv",
- "fsl,P3041DS-hv",
- "fsl,OCA4080-hv",
- "fsl,P4080DS-hv",
- "fsl,P5020DS-hv",
- "fsl,P5040DS-hv",
- "fsl,T4240QDS-hv",
- "fsl,B4860QDS-hv",
- "fsl,B4420QDS-hv",
- "fsl,B4220QDS-hv",
- "fsl,T1040QDS-hv",
- "fsl,T1042QDS-hv",
- NULL
-};
-
/*
* Called very early, device-tree isn't unflattened
*/
static int __init corenet_generic_probe(void)
{
unsigned long root = of_get_flat_dt_root();
+ char hv_compat[24];
+ int i;
#ifdef CONFIG_SMP
extern struct smp_ops_t smp_85xx_ops;
#endif
@@ -159,21 +149,26 @@ static int __init corenet_generic_probe(void)
return 1;
/* Check if we're running under the Freescale hypervisor */
- if (of_flat_dt_match(root, hv_boards)) {
- ppc_md.init_IRQ = ehv_pic_init;
- ppc_md.get_irq = ehv_pic_get_irq;
- ppc_md.restart = fsl_hv_restart;
- ppc_md.power_off = fsl_hv_halt;
- ppc_md.halt = fsl_hv_halt;
+ for (i = 0; boards[i]; i++) {
+ snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
+ if (of_flat_dt_is_compatible(root, hv_compat)) {
+ ppc_md.init_IRQ = ehv_pic_init;
+
+ ppc_md.get_irq = ehv_pic_get_irq;
+ ppc_md.restart = fsl_hv_restart;
+ ppc_md.power_off = fsl_hv_halt;
+ ppc_md.halt = fsl_hv_halt;
#ifdef CONFIG_SMP
- /*
- * Disable the timebase sync operations because we can't write
- * to the timebase registers under the hypervisor.
- */
- smp_85xx_ops.give_timebase = NULL;
- smp_85xx_ops.take_timebase = NULL;
+ /*
+ * Disable the timebase sync operations because we
+ * can't write to the timebase registers under the
+ * hypervisor.
+ */
+ smp_85xx_ops.give_timebase = NULL;
+ smp_85xx_ops.take_timebase = NULL;
#endif
- return 1;
+ return 1;
+ }
}
return 0;
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index ba093f553678..d7c1e69f3070 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -28,6 +28,7 @@
#include <asm/dbell.h>
#include <asm/fsl_guts.h>
#include <asm/code-patching.h>
+#include <asm/cputhreads.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
@@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l(void *spin_table)
return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
}
+#ifdef CONFIG_PPC64
+static void wake_hw_thread(void *info)
+{
+ void fsl_secondary_thread_init(void);
+ unsigned long imsr1, inia1;
+ int nr = *(const int *)info;
+
+ imsr1 = MSR_KERNEL;
+ inia1 = *(unsigned long *)fsl_secondary_thread_init;
+
+ mttmr(TMRN_IMSR1, imsr1);
+ mttmr(TMRN_INIA1, inia1);
+ mtspr(SPRN_TENS, TEN_THREAD(1));
+
+ smp_generic_kick_cpu(nr);
+}
+#endif
+
static int smp_85xx_kick_cpu(int nr)
{
unsigned long flags;
@@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr)
pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
+#ifdef CONFIG_PPC64
+ /* Threads don't use the spin table */
+ if (cpu_thread_in_core(nr) != 0) {
+ int primary = cpu_first_thread_sibling(nr);
+
+ if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
+ return -ENOENT;
+
+ if (cpu_thread_in_core(nr) != 1) {
+ pr_err("%s: cpu %d: invalid hw thread %d\n",
+ __func__, nr, cpu_thread_in_core(nr));
+ return -ENOENT;
+ }
+
+ if (!cpu_online(primary)) {
+ pr_err("%s: cpu %d: primary %d not online\n",
+ __func__, nr, primary);
+ return -ENOENT;
+ }
+
+ smp_call_function_single(primary, wake_hw_thread, &nr, 0);
+ return 0;
+ }
+#endif
+
np = of_get_cpu_node(nr, NULL);
cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 587a2828b06c..d3037747031d 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -18,7 +18,6 @@
#include <linux/fsl_devices.h>
#include <asm/io.h>
-#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/prom.h>
#include <asm/fs_pd.h>
@@ -28,8 +27,6 @@
#include "mpc8xx.h"
-struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
-
extern int cpm_pic_init(void);
extern int cpm_get_irq(void);
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c1262581b63c..5921dcb498fd 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -35,7 +35,6 @@
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/time.h>
-#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/cpm1.h>
#include <asm/fs_pd.h>
@@ -46,61 +45,6 @@
static u32 __iomem *bcsr, *bcsr5;
-#ifdef CONFIG_PCMCIA_M8XX
-static void pcmcia_hw_setup(int slot, int enable)
-{
- if (enable)
- clrbits32(&bcsr[1], BCSR1_PCCEN);
- else
- setbits32(&bcsr[1], BCSR1_PCCEN);
-}
-
-static int pcmcia_set_voltage(int slot, int vcc, int vpp)
-{
- u32 reg = 0;
-
- switch (vcc) {
- case 0:
- break;
- case 33:
- reg |= BCSR1_PCCVCC0;
- break;
- case 50:
- reg |= BCSR1_PCCVCC1;
- break;
- default:
- return 1;
- }
-
- switch (vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if (vcc == vpp)
- reg |= BCSR1_PCCVPP1;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= BCSR1_PCCVPP0;
- else
- return 1;
- default:
- return 1;
- }
-
- /* first, turn off all power */
- clrbits32(&bcsr[1], 0x00610000);
-
- /* enable new powersettings */
- setbits32(&bcsr[1], reg);
-
- return 0;
-}
-#endif
-
struct cpm_pin {
int port, pin, flags;
};
@@ -245,12 +189,6 @@ static void __init mpc885ads_setup_arch(void)
of_detach_node(np);
of_node_put(np);
}
-
-#ifdef CONFIG_PCMCIA_M8XX
- /* Set up board specific hook-ups.*/
- m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
- m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
-#endif
}
static int __init mpc885ads_probe(void)
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
index 251aba8759e4..dda607807def 100644
--- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
@@ -37,7 +37,6 @@
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/time.h>
-#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/cpm1.h>
#include <asm/fs_pd.h>
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index a41bd023647a..e8bc40869cbd 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -61,7 +61,7 @@ choice
help
There are two families of 64 bit PowerPC chips supported.
The most common ones are the desktop and server CPUs
- (POWER3, RS64, POWER4, POWER5, POWER5+, POWER6, ...)
+ (POWER4, POWER5, 970, POWER5+, POWER6, POWER7, POWER8 ...)
The other are the "embedded" processors compliant with the
"Book 3E" variant of the architecture
@@ -140,14 +140,6 @@ config 6xx
depends on PPC32 && PPC_BOOK3S
select PPC_HAVE_PMU_SUPPORT
-config POWER3
- depends on PPC64 && PPC_BOOK3S
- def_bool y
-
-config POWER4
- depends on PPC64 && PPC_BOOK3S
- def_bool y
-
config TUNE_CELL
bool "Optimize for Cell Broadband Engine"
depends on PPC64 && PPC_BOOK3S
@@ -244,7 +236,7 @@ config PHYS_64BIT
config ALTIVEC
bool "AltiVec Support"
- depends on 6xx || POWER4 || (PPC_E500MC && PPC64)
+ depends on 6xx || PPC_BOOK3S_64 || (PPC_E500MC && PPC64)
---help---
This option enables kernel support for the Altivec extensions to the
PowerPC processor. The kernel currently supports saving and restoring
@@ -260,7 +252,7 @@ config ALTIVEC
config VSX
bool "VSX Support"
- depends on POWER4 && ALTIVEC && PPC_FPU
+ depends on PPC_BOOK3S_64 && ALTIVEC && PPC_FPU
---help---
This option enables kernel support for the Vector Scaler extensions
@@ -276,7 +268,7 @@ config VSX
config PPC_ICSWX
bool "Support for PowerPC icswx coprocessor instruction"
- depends on POWER4
+ depends on PPC_BOOK3S_64
default n
---help---
@@ -294,7 +286,7 @@ config PPC_ICSWX
config PPC_ICSWX_PID
bool "icswx requires direct PID management"
- depends on PPC_ICSWX && POWER4
+ depends on PPC_ICSWX
default y
---help---
The PID register in server is used explicitly for ICSWX. In
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
index 03aabc0e16ac..2fe12046279e 100644
--- a/arch/powerpc/platforms/amigaone/setup.c
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -24,6 +24,7 @@
#include <asm/i8259.h>
#include <asm/time.h>
#include <asm/udbg.h>
+#include <asm/dma.h>
extern void __flush_disable_L1(void);
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index f85db3a69b4a..2930d1e81a05 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -611,7 +611,6 @@ static int __init create_spu(void *data)
int ret;
static int number;
unsigned long flags;
- struct timespec ts;
ret = -ENOMEM;
spu = kzalloc(sizeof (*spu), GFP_KERNEL);
@@ -652,8 +651,7 @@ static int __init create_spu(void *data)
mutex_unlock(&spu_full_list_mutex);
spu->stats.util_state = SPU_UTIL_IDLE_LOADED;
- ktime_get_ts(&ts);
- spu->stats.tstamp = timespec_to_ns(&ts);
+ spu->stats.tstamp = ktime_get_ns();
INIT_LIST_HEAD(&spu->aff_list);
@@ -676,7 +674,6 @@ static const char *spu_state_names[] = {
static unsigned long long spu_acct_time(struct spu *spu,
enum spu_utilization_state state)
{
- struct timespec ts;
unsigned long long time = spu->stats.times[state];
/*
@@ -684,10 +681,8 @@ static unsigned long long spu_acct_time(struct spu *spu,
* statistics are not updated. Apply the time delta from the
* last recorded state of the spu.
*/
- if (spu->stats.util_state == state) {
- ktime_get_ts(&ts);
- time += timespec_to_ns(&ts) - spu->stats.tstamp;
- }
+ if (spu->stats.util_state == state)
+ time += ktime_get_ns() - spu->stats.tstamp;
return time / NSEC_PER_MSEC;
}
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 9c6790d17eda..3b4152faeb1f 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -36,7 +36,6 @@ atomic_t nr_spu_contexts = ATOMIC_INIT(0);
struct spu_context *alloc_spu_context(struct spu_gang *gang)
{
struct spu_context *ctx;
- struct timespec ts;
ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
if (!ctx)
@@ -67,8 +66,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
__spu_update_sched_info(ctx);
spu_set_timeslice(ctx);
ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
- ktime_get_ts(&ts);
- ctx->stats.tstamp = timespec_to_ns(&ts);
+ ctx->stats.tstamp = ktime_get_ns();
atomic_inc(&nr_spu_contexts);
goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 90986923a53a..d966bbe58b8f 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2338,7 +2338,6 @@ static const char *ctx_state_names[] = {
static unsigned long long spufs_acct_time(struct spu_context *ctx,
enum spu_utilization_state state)
{
- struct timespec ts;
unsigned long long time = ctx->stats.times[state];
/*
@@ -2351,8 +2350,7 @@ static unsigned long long spufs_acct_time(struct spu_context *ctx,
* of the spu context.
*/
if (ctx->spu && ctx->stats.util_state == state) {
- ktime_get_ts(&ts);
- time += timespec_to_ns(&ts) - ctx->stats.tstamp;
+ time += ktime_get_ns() - ctx->stats.tstamp;
}
return time / NSEC_PER_MSEC;
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 4a0a64fe25df..998f632e7cce 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -1039,13 +1039,11 @@ void spuctx_switch_state(struct spu_context *ctx,
{
unsigned long long curtime;
signed long long delta;
- struct timespec ts;
struct spu *spu;
enum spu_utilization_state old_state;
int node;
- ktime_get_ts(&ts);
- curtime = timespec_to_ns(&ts);
+ curtime = ktime_get_ns();
delta = curtime - ctx->stats.tstamp;
WARN_ON(!mutex_is_locked(&ctx->state_mutex));
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 1afd10f67858..607124bae2e7 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -10,7 +10,7 @@ config PPC_PMAC
config PPC_PMAC64
bool
- depends on PPC_PMAC && POWER4
+ depends on PPC_PMAC && PPC64
select MPIC
select U3_DART
select MPIC_U3_HT_IRQS
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 63d82bbc05e9..4882bfd90e27 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -158,7 +158,7 @@ static inline int simple_feature_tweak(struct device_node *node, int type,
return 0;
}
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
static long ohare_htw_scc_enable(struct device_node *node, long param,
long value)
@@ -1318,7 +1318,7 @@ intrepid_aack_delay_enable(struct device_node *node, long param, long value)
}
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
static long
core99_read_gpio(struct device_node *node, long param, long value)
@@ -1338,7 +1338,7 @@ core99_write_gpio(struct device_node *node, long param, long value)
return 0;
}
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
static long g5_gmac_enable(struct device_node *node, long param, long value)
{
struct macio_chip *macio = &macio_chips[0];
@@ -1550,9 +1550,9 @@ void g5_phy_disable_cpu1(void)
if (uninorth_maj == 3)
UN_OUT(U3_API_PHY_CONFIG_1, 0);
}
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
#ifdef CONFIG_PM
@@ -1864,7 +1864,7 @@ core99_sleep_state(struct device_node *node, long param, long value)
return 0;
}
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
static long
generic_dev_can_wake(struct device_node *node, long param, long value)
@@ -1906,7 +1906,7 @@ static struct feature_table_entry any_features[] = {
{ 0, NULL }
};
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
/* OHare based motherboards. Currently, we only use these on the
* 2400,3400 and 3500 series powerbooks. Some older desktops seem
@@ -2056,7 +2056,7 @@ static struct feature_table_entry intrepid_features[] = {
{ 0, NULL }
};
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
/* G5 features
*/
@@ -2074,10 +2074,10 @@ static struct feature_table_entry g5_features[] = {
{ 0, NULL }
};
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
static struct pmac_mb_def pmac_mb_defs[] = {
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
/*
* Desktops
*/
@@ -2342,7 +2342,7 @@ static struct pmac_mb_def pmac_mb_defs[] = {
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
},
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
{ "PowerMac7,2", "PowerMac G5",
PMAC_TYPE_POWERMAC_G5, g5_features,
0,
@@ -2373,7 +2373,7 @@ static struct pmac_mb_def pmac_mb_defs[] = {
0,
},
#endif /* CONFIG_PPC64 */
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
};
/*
@@ -2441,7 +2441,7 @@ static int __init probe_motherboard(void)
/* Fallback to selection depending on mac-io chip type */
switch(macio->type) {
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
case macio_grand_central:
pmac_mb.model_id = PMAC_TYPE_PSURGE;
pmac_mb.model_name = "Unknown PowerSurge";
@@ -2475,7 +2475,7 @@ static int __init probe_motherboard(void)
pmac_mb.model_name = "Unknown Intrepid-based";
pmac_mb.features = intrepid_features;
break;
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
case macio_keylargo2:
pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
pmac_mb.model_name = "Unknown K2-based";
@@ -2486,13 +2486,13 @@ static int __init probe_motherboard(void)
pmac_mb.model_name = "Unknown Shasta-based";
pmac_mb.features = g5_features;
break;
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
default:
ret = -ENODEV;
goto done;
}
found:
-#ifndef CONFIG_POWER4
+#ifndef CONFIG_PPC64
/* Fixup Hooper vs. Comet */
if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
@@ -2546,9 +2546,9 @@ found:
*/
powersave_lowspeed = 1;
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
powersave_nap = 1;
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
/* Check for "mobile" machine */
if (model && (strncmp(model, "PowerBook", 9) == 0
@@ -2786,7 +2786,7 @@ set_initial_features(void)
MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
}
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
if (macio_chips[0].type == macio_keylargo2 ||
macio_chips[0].type == macio_shasta) {
#ifndef CONFIG_SMP
@@ -2805,28 +2805,23 @@ set_initial_features(void)
/* Enable GMAC for now for PCI probing. It will be disabled
* later on after PCI probe
*/
- np = of_find_node_by_name(NULL, "ethernet");
- while(np) {
+ for_each_node_by_name(np, "ethernet")
if (of_device_is_compatible(np, "K2-GMAC"))
g5_gmac_enable(np, 0, 1);
- np = of_find_node_by_name(np, "ethernet");
- }
/* Enable FW before PCI probe. Will be disabled later on
* Note: We should have a batter way to check that we are
* dealing with uninorth internal cell and not a PCI cell
* on the external PCI. The code below works though.
*/
- np = of_find_node_by_name(NULL, "firewire");
- while(np) {
+ for_each_node_by_name(np, "firewire") {
if (of_device_is_compatible(np, "pci106b,5811")) {
macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
g5_fw_enable(np, 0, 1);
}
- np = of_find_node_by_name(np, "firewire");
}
}
-#else /* CONFIG_POWER4 */
+#else /* CONFIG_PPC64 */
if (macio_chips[0].type == macio_keylargo ||
macio_chips[0].type == macio_pangea ||
@@ -2834,13 +2829,11 @@ set_initial_features(void)
/* Enable GMAC for now for PCI probing. It will be disabled
* later on after PCI probe
*/
- np = of_find_node_by_name(NULL, "ethernet");
- while(np) {
+ for_each_node_by_name(np, "ethernet") {
if (np->parent
&& of_device_is_compatible(np->parent, "uni-north")
&& of_device_is_compatible(np, "gmac"))
core99_gmac_enable(np, 0, 1);
- np = of_find_node_by_name(np, "ethernet");
}
/* Enable FW before PCI probe. Will be disabled later on
@@ -2848,8 +2841,7 @@ set_initial_features(void)
* dealing with uninorth internal cell and not a PCI cell
* on the external PCI. The code below works though.
*/
- np = of_find_node_by_name(NULL, "firewire");
- while(np) {
+ for_each_node_by_name(np, "firewire") {
if (np->parent
&& of_device_is_compatible(np->parent, "uni-north")
&& (of_device_is_compatible(np, "pci106b,18") ||
@@ -2858,18 +2850,16 @@ set_initial_features(void)
macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
core99_firewire_enable(np, 0, 1);
}
- np = of_find_node_by_name(np, "firewire");
}
/* Enable ATA-100 before PCI probe. */
np = of_find_node_by_name(NULL, "ata-6");
- while(np) {
+ for_each_node_by_name(np, "ata-6") {
if (np->parent
&& of_device_is_compatible(np->parent, "uni-north")
&& of_device_is_compatible(np, "kauai-ata")) {
core99_ata100_enable(np, 1);
}
- np = of_find_node_by_name(np, "ata-6");
}
/* Switch airport off */
@@ -2895,7 +2885,7 @@ set_initial_features(void)
MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
}
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64 */
/* On all machines, switch modem & serial ports off */
for_each_node_by_name(np, "ch-a")
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index cf7009b8c7b6..7e868ccf3b0d 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -698,7 +698,7 @@ static void __init fixup_nec_usb2(void)
{
struct device_node *nec;
- for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
+ for_each_node_by_name(nec, "usb") {
struct pci_controller *hose;
u32 data;
const u32 *prop;
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 5cbd4d67d5c4..af094ae03dbb 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -577,7 +577,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
int ok;
/* Look for the clock chip */
- while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
+ for_each_node_by_name(cc, "i2c-hwclock") {
p = of_get_parent(cc);
ok = p && of_device_is_compatible(p, "uni-n-i2c");
of_node_put(p);
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c
index 44e0b55a2a02..366bd221edec 100644
--- a/arch/powerpc/platforms/powermac/udbg_adb.c
+++ b/arch/powerpc/platforms/powermac/udbg_adb.c
@@ -191,7 +191,7 @@ int __init udbg_adb_init(int force_btext)
* of type "adb". If not, we return a failure, but we keep the
* bext output set for now
*/
- for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) {
+ for_each_node_by_name(np, "keyboard") {
struct device_node *parent = of_get_parent(np);
int found = (parent && strcmp(parent->type, "adb") == 0);
of_node_put(parent);
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 4ad227d04c1a..f241accc053d 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,10 +1,11 @@
obj-y += setup.o opal-wrappers.o opal.o opal-async.o
obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
-obj-y += opal-msglog.o
+obj-y += opal-msglog.o opal-hmi.o
obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o
obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o
+obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 8ad0c5b891f4..c945bed4dc9e 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -187,10 +187,10 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
*/
static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
{
- s64 ret;
- u32 pe_no;
struct pci_controller *hose = pe->phb;
struct pnv_phb *phb = hose->private_data;
+ int enable, ret = 0;
+ s64 rc;
/* Check on PE number */
if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
@@ -201,184 +201,214 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
return -EINVAL;
}
- pe_no = pe->addr;
switch (option) {
case EEH_OPT_DISABLE:
- ret = -EEXIST;
- break;
+ return -EPERM;
case EEH_OPT_ENABLE:
- ret = 0;
- break;
+ return 0;
case EEH_OPT_THAW_MMIO:
- ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
- OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO);
- if (ret) {
- pr_warning("%s: Failed to enable MMIO for "
- "PHB#%x-PE#%x, err=%lld\n",
- __func__, hose->global_number, pe_no, ret);
- return -EIO;
- }
-
+ enable = OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO;
break;
case EEH_OPT_THAW_DMA:
- ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
- OPAL_EEH_ACTION_CLEAR_FREEZE_DMA);
- if (ret) {
- pr_warning("%s: Failed to enable DMA for "
- "PHB#%x-PE#%x, err=%lld\n",
- __func__, hose->global_number, pe_no, ret);
- return -EIO;
- }
-
+ enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA;
break;
default:
- pr_warning("%s: Invalid option %d\n", __func__, option);
+ pr_warn("%s: Invalid option %d\n",
+ __func__, option);
return -EINVAL;
}
+ /* If PHB supports compound PE, to handle it */
+ if (phb->unfreeze_pe) {
+ ret = phb->unfreeze_pe(phb, pe->addr, enable);
+ } else {
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+ pe->addr,
+ enable);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n",
+ __func__, rc, option, phb->hose->global_number,
+ pe->addr);
+ ret = -EIO;
+ }
+ }
+
return ret;
}
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
+static void ioda_eeh_phb_diag(struct eeh_pe *pe)
{
- struct pnv_phb *phb = hose->private_data;
+ struct pnv_phb *phb = pe->phb->private_data;
long rc;
- rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+ rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data,
PNV_PCI_DIAG_BUF_SIZE);
- if (rc != OPAL_SUCCESS) {
- pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
- __func__, hose->global_number, rc);
- return;
- }
-
- pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+ __func__, pe->phb->global_number, rc);
}
-/**
- * ioda_eeh_get_state - Retrieve the state of PE
- * @pe: EEH PE
- *
- * The PE's state should be retrieved from the PEEV, PEST
- * IODA tables. Since the OPAL has exported the function
- * to do it, it'd better to use that.
- */
-static int ioda_eeh_get_state(struct eeh_pe *pe)
+static int ioda_eeh_get_phb_state(struct eeh_pe *pe)
{
- s64 ret = 0;
+ struct pnv_phb *phb = pe->phb->private_data;
u8 fstate;
__be16 pcierr;
- u32 pe_no;
- int result;
- struct pci_controller *hose = pe->phb;
- struct pnv_phb *phb = hose->private_data;
+ s64 rc;
+ int result = 0;
+
+ rc = opal_pci_eeh_freeze_status(phb->opal_id,
+ pe->addr,
+ &fstate,
+ &pcierr,
+ NULL);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld getting PHB#%x state\n",
+ __func__, rc, phb->hose->global_number);
+ return EEH_STATE_NOT_SUPPORT;
+ }
/*
- * Sanity check on PE address. The PHB PE address should
- * be zero.
+ * Check PHB state. If the PHB is frozen for the
+ * first time, to dump the PHB diag-data.
*/
- if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) {
- pr_err("%s: PE address %x out of range [0, %x] "
- "on PHB#%x\n",
- __func__, pe->addr, phb->ioda.total_pe,
- hose->global_number);
- return EEH_STATE_NOT_SUPPORT;
+ if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
+ result = (EEH_STATE_MMIO_ACTIVE |
+ EEH_STATE_DMA_ACTIVE |
+ EEH_STATE_MMIO_ENABLED |
+ EEH_STATE_DMA_ENABLED);
+ } else if (!(pe->state & EEH_PE_ISOLATED)) {
+ eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+ ioda_eeh_phb_diag(pe);
}
+ return result;
+}
+
+static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
+{
+ struct pnv_phb *phb = pe->phb->private_data;
+ u8 fstate;
+ __be16 pcierr;
+ s64 rc;
+ int result;
+
/*
- * If we're in middle of PE reset, return normal
- * state to keep EEH core going. For PHB reset, we
- * still expect to have fenced PHB cleared with
- * PHB reset.
+ * We don't clobber hardware frozen state until PE
+ * reset is completed. In order to keep EEH core
+ * moving forward, we have to return operational
+ * state during PE reset.
*/
- if (!(pe->type & EEH_PE_PHB) &&
- (pe->state & EEH_PE_RESET)) {
- result = (EEH_STATE_MMIO_ACTIVE |
- EEH_STATE_DMA_ACTIVE |
+ if (pe->state & EEH_PE_RESET) {
+ result = (EEH_STATE_MMIO_ACTIVE |
+ EEH_STATE_DMA_ACTIVE |
EEH_STATE_MMIO_ENABLED |
EEH_STATE_DMA_ENABLED);
return result;
}
- /* Retrieve PE status through OPAL */
- pe_no = pe->addr;
- ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no,
- &fstate, &pcierr, NULL);
- if (ret) {
- pr_err("%s: Failed to get EEH status on "
- "PHB#%x-PE#%x\n, err=%lld\n",
- __func__, hose->global_number, pe_no, ret);
- return EEH_STATE_NOT_SUPPORT;
- }
-
- /* Check PHB status */
- if (pe->type & EEH_PE_PHB) {
- result = 0;
- result &= ~EEH_STATE_RESET_ACTIVE;
-
- if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) {
- result |= EEH_STATE_MMIO_ACTIVE;
- result |= EEH_STATE_DMA_ACTIVE;
- result |= EEH_STATE_MMIO_ENABLED;
- result |= EEH_STATE_DMA_ENABLED;
- } else if (!(pe->state & EEH_PE_ISOLATED)) {
- eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
- ioda_eeh_phb_diag(hose);
+ /*
+ * Fetch PE state from hardware. If the PHB
+ * supports compound PE, let it handle that.
+ */
+ if (phb->get_pe_state) {
+ fstate = phb->get_pe_state(phb, pe->addr);
+ } else {
+ rc = opal_pci_eeh_freeze_status(phb->opal_id,
+ pe->addr,
+ &fstate,
+ &pcierr,
+ NULL);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n",
+ __func__, rc, phb->hose->global_number, pe->addr);
+ return EEH_STATE_NOT_SUPPORT;
}
-
- return result;
}
- /* Parse result out */
- result = 0;
+ /* Figure out state */
switch (fstate) {
case OPAL_EEH_STOPPED_NOT_FROZEN:
- result &= ~EEH_STATE_RESET_ACTIVE;
- result |= EEH_STATE_MMIO_ACTIVE;
- result |= EEH_STATE_DMA_ACTIVE;
- result |= EEH_STATE_MMIO_ENABLED;
- result |= EEH_STATE_DMA_ENABLED;
+ result = (EEH_STATE_MMIO_ACTIVE |
+ EEH_STATE_DMA_ACTIVE |
+ EEH_STATE_MMIO_ENABLED |
+ EEH_STATE_DMA_ENABLED);
break;
case OPAL_EEH_STOPPED_MMIO_FREEZE:
- result &= ~EEH_STATE_RESET_ACTIVE;
- result |= EEH_STATE_DMA_ACTIVE;
- result |= EEH_STATE_DMA_ENABLED;
+ result = (EEH_STATE_DMA_ACTIVE |
+ EEH_STATE_DMA_ENABLED);
break;
case OPAL_EEH_STOPPED_DMA_FREEZE:
- result &= ~EEH_STATE_RESET_ACTIVE;
- result |= EEH_STATE_MMIO_ACTIVE;
- result |= EEH_STATE_MMIO_ENABLED;
+ result = (EEH_STATE_MMIO_ACTIVE |
+ EEH_STATE_MMIO_ENABLED);
break;
case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE:
- result &= ~EEH_STATE_RESET_ACTIVE;
+ result = 0;
break;
case OPAL_EEH_STOPPED_RESET:
- result |= EEH_STATE_RESET_ACTIVE;
+ result = EEH_STATE_RESET_ACTIVE;
break;
case OPAL_EEH_STOPPED_TEMP_UNAVAIL:
- result |= EEH_STATE_UNAVAILABLE;
+ result = EEH_STATE_UNAVAILABLE;
break;
case OPAL_EEH_STOPPED_PERM_UNAVAIL:
- result |= EEH_STATE_NOT_SUPPORT;
+ result = EEH_STATE_NOT_SUPPORT;
break;
default:
- pr_warning("%s: Unexpected EEH status 0x%x "
- "on PHB#%x-PE#%x\n",
- __func__, fstate, hose->global_number, pe_no);
+ result = EEH_STATE_NOT_SUPPORT;
+ pr_warn("%s: Invalid PHB#%x-PE#%x state %x\n",
+ __func__, phb->hose->global_number,
+ pe->addr, fstate);
}
- /* Dump PHB diag-data for frozen PE */
- if (result != EEH_STATE_NOT_SUPPORT &&
- (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
- (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
+ /*
+ * If PHB supports compound PE, to freeze all
+ * slave PEs for consistency.
+ *
+ * If the PE is switching to frozen state for the
+ * first time, to dump the PHB diag-data.
+ */
+ if (!(result & EEH_STATE_NOT_SUPPORT) &&
+ !(result & EEH_STATE_UNAVAILABLE) &&
+ !(result & EEH_STATE_MMIO_ACTIVE) &&
+ !(result & EEH_STATE_DMA_ACTIVE) &&
!(pe->state & EEH_PE_ISOLATED)) {
+ if (phb->freeze_pe)
+ phb->freeze_pe(phb, pe->addr);
+
eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
- ioda_eeh_phb_diag(hose);
+ ioda_eeh_phb_diag(pe);
}
return result;
}
+/**
+ * ioda_eeh_get_state - Retrieve the state of PE
+ * @pe: EEH PE
+ *
+ * The PE's state should be retrieved from the PEEV, PEST
+ * IODA tables. Since the OPAL has exported the function
+ * to do it, it'd better to use that.
+ */
+static int ioda_eeh_get_state(struct eeh_pe *pe)
+{
+ struct pnv_phb *phb = pe->phb->private_data;
+
+ /* Sanity check on PE number. PHB PE should have 0 */
+ if (pe->addr < 0 ||
+ pe->addr >= phb->ioda.total_pe) {
+ pr_warn("%s: PHB#%x-PE#%x out of range [0, %x]\n",
+ __func__, phb->hose->global_number,
+ pe->addr, phb->ioda.total_pe);
+ return EEH_STATE_NOT_SUPPORT;
+ }
+
+ if (pe->type & EEH_PE_PHB)
+ return ioda_eeh_get_phb_state(pe);
+
+ return ioda_eeh_get_pe_state(pe);
+}
+
static s64 ioda_eeh_phb_poll(struct pnv_phb *phb)
{
s64 rc = OPAL_HARDWARE;
@@ -589,6 +619,24 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
}
/**
+ * ioda_eeh_get_log - Retrieve error log
+ * @pe: frozen PE
+ * @severity: permanent or temporary error
+ * @drv_log: device driver log
+ * @len: length of device driver log
+ *
+ * Retrieve error log, which contains log from device driver
+ * and firmware.
+ */
+int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
+ char *drv_log, unsigned long len)
+{
+ pnv_pci_dump_phb_diag_data(pe->phb, pe->data);
+
+ return 0;
+}
+
+/**
* ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
* @pe: EEH PE
*
@@ -605,18 +653,24 @@ static int ioda_eeh_configure_bridge(struct eeh_pe *pe)
static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
{
/* GEM */
- pr_info(" GEM XFIR: %016llx\n", data->gemXfir);
- pr_info(" GEM RFIR: %016llx\n", data->gemRfir);
- pr_info(" GEM RIRQFIR: %016llx\n", data->gemRirqfir);
- pr_info(" GEM Mask: %016llx\n", data->gemMask);
- pr_info(" GEM RWOF: %016llx\n", data->gemRwof);
+ if (data->gemXfir || data->gemRfir ||
+ data->gemRirqfir || data->gemMask || data->gemRwof)
+ pr_info(" GEM: %016llx %016llx %016llx %016llx %016llx\n",
+ be64_to_cpu(data->gemXfir),
+ be64_to_cpu(data->gemRfir),
+ be64_to_cpu(data->gemRirqfir),
+ be64_to_cpu(data->gemMask),
+ be64_to_cpu(data->gemRwof));
/* LEM */
- pr_info(" LEM FIR: %016llx\n", data->lemFir);
- pr_info(" LEM Error Mask: %016llx\n", data->lemErrMask);
- pr_info(" LEM Action 0: %016llx\n", data->lemAction0);
- pr_info(" LEM Action 1: %016llx\n", data->lemAction1);
- pr_info(" LEM WOF: %016llx\n", data->lemWof);
+ if (data->lemFir || data->lemErrMask ||
+ data->lemAction0 || data->lemAction1 || data->lemWof)
+ pr_info(" LEM: %016llx %016llx %016llx %016llx %016llx\n",
+ be64_to_cpu(data->lemFir),
+ be64_to_cpu(data->lemErrMask),
+ be64_to_cpu(data->lemAction0),
+ be64_to_cpu(data->lemAction1),
+ be64_to_cpu(data->lemWof));
}
static void ioda_eeh_hub_diag(struct pci_controller *hose)
@@ -627,8 +681,8 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
if (rc != OPAL_SUCCESS) {
- pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
- __func__, phb->hub_id, rc);
+ pr_warn("%s: Failed to get HUB#%llx diag-data (%ld)\n",
+ __func__, phb->hub_id, rc);
return;
}
@@ -636,24 +690,31 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
case OPAL_P7IOC_DIAG_TYPE_RGC:
pr_info("P7IOC diag-data for RGC\n\n");
ioda_eeh_hub_diag_common(data);
- pr_info(" RGC Status: %016llx\n", data->rgc.rgcStatus);
- pr_info(" RGC LDCP: %016llx\n", data->rgc.rgcLdcp);
+ if (data->rgc.rgcStatus || data->rgc.rgcLdcp)
+ pr_info(" RGC: %016llx %016llx\n",
+ be64_to_cpu(data->rgc.rgcStatus),
+ be64_to_cpu(data->rgc.rgcLdcp));
break;
case OPAL_P7IOC_DIAG_TYPE_BI:
pr_info("P7IOC diag-data for BI %s\n\n",
data->bi.biDownbound ? "Downbound" : "Upbound");
ioda_eeh_hub_diag_common(data);
- pr_info(" BI LDCP 0: %016llx\n", data->bi.biLdcp0);
- pr_info(" BI LDCP 1: %016llx\n", data->bi.biLdcp1);
- pr_info(" BI LDCP 2: %016llx\n", data->bi.biLdcp2);
- pr_info(" BI Fence Status: %016llx\n", data->bi.biFenceStatus);
+ if (data->bi.biLdcp0 || data->bi.biLdcp1 ||
+ data->bi.biLdcp2 || data->bi.biFenceStatus)
+ pr_info(" BI: %016llx %016llx %016llx %016llx\n",
+ be64_to_cpu(data->bi.biLdcp0),
+ be64_to_cpu(data->bi.biLdcp1),
+ be64_to_cpu(data->bi.biLdcp2),
+ be64_to_cpu(data->bi.biFenceStatus));
break;
case OPAL_P7IOC_DIAG_TYPE_CI:
- pr_info("P7IOC diag-data for CI Port %d\\nn",
+ pr_info("P7IOC diag-data for CI Port %d\n\n",
data->ci.ciPort);
ioda_eeh_hub_diag_common(data);
- pr_info(" CI Port Status: %016llx\n", data->ci.ciPortStatus);
- pr_info(" CI Port LDCP: %016llx\n", data->ci.ciPortLdcp);
+ if (data->ci.ciPortStatus || data->ci.ciPortLdcp)
+ pr_info(" CI: %016llx %016llx\n",
+ be64_to_cpu(data->ci.ciPortStatus),
+ be64_to_cpu(data->ci.ciPortLdcp));
break;
case OPAL_P7IOC_DIAG_TYPE_MISC:
pr_info("P7IOC diag-data for MISC\n\n");
@@ -664,30 +725,51 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
ioda_eeh_hub_diag_common(data);
break;
default:
- pr_warning("%s: Invalid type of HUB#%llx diag-data (%d)\n",
- __func__, phb->hub_id, data->type);
+ pr_warn("%s: Invalid type of HUB#%llx diag-data (%d)\n",
+ __func__, phb->hub_id, data->type);
}
}
static int ioda_eeh_get_pe(struct pci_controller *hose,
u16 pe_no, struct eeh_pe **pe)
{
- struct eeh_pe *phb_pe, *dev_pe;
- struct eeh_dev dev;
+ struct pnv_phb *phb = hose->private_data;
+ struct pnv_ioda_pe *pnv_pe;
+ struct eeh_pe *dev_pe;
+ struct eeh_dev edev;
- /* Find the PHB PE */
- phb_pe = eeh_phb_pe_get(hose);
- if (!phb_pe)
- return -EEXIST;
+ /*
+ * If PHB supports compound PE, to fetch
+ * the master PE because slave PE is invisible
+ * to EEH core.
+ */
+ if (phb->get_pe_state) {
+ pnv_pe = &phb->ioda.pe_array[pe_no];
+ if (pnv_pe->flags & PNV_IODA_PE_SLAVE) {
+ pnv_pe = pnv_pe->master;
+ WARN_ON(!pnv_pe ||
+ !(pnv_pe->flags & PNV_IODA_PE_MASTER));
+ pe_no = pnv_pe->pe_number;
+ }
+ }
/* Find the PE according to PE# */
- memset(&dev, 0, sizeof(struct eeh_dev));
- dev.phb = hose;
- dev.pe_config_addr = pe_no;
- dev_pe = eeh_pe_get(&dev);
- if (!dev_pe) return -EEXIST;
+ memset(&edev, 0, sizeof(struct eeh_dev));
+ edev.phb = hose;
+ edev.pe_config_addr = pe_no;
+ dev_pe = eeh_pe_get(&edev);
+ if (!dev_pe)
+ return -EEXIST;
+ /*
+ * At this point, we're sure the compound PE should
+ * be put into frozen state.
+ */
*pe = dev_pe;
+ if (phb->freeze_pe &&
+ !(dev_pe->state & EEH_PE_ISOLATED))
+ phb->freeze_pe(phb, pe_no);
+
return 0;
}
@@ -792,7 +874,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
"detected, location: %s\n",
hose->global_number,
eeh_pe_loc_get(phb_pe));
- ioda_eeh_phb_diag(hose);
+ ioda_eeh_phb_diag(phb_pe);
+ pnv_pci_dump_phb_diag_data(hose, phb_pe->data);
ret = EEH_NEXT_ERR_NONE;
}
@@ -812,7 +895,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no,
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
ret = EEH_NEXT_ERR_NONE;
- } else if ((*pe)->state & EEH_PE_ISOLATED) {
+ } else if ((*pe)->state & EEH_PE_ISOLATED ||
+ eeh_pe_passed(*pe)) {
ret = EEH_NEXT_ERR_NONE;
} else {
pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
@@ -839,7 +923,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
ret == EEH_NEXT_ERR_FENCED_PHB) &&
!((*pe)->state & EEH_PE_ISOLATED)) {
eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
- ioda_eeh_phb_diag(hose);
+ ioda_eeh_phb_diag(*pe);
}
/*
@@ -885,6 +969,7 @@ struct pnv_eeh_ops ioda_eeh_ops = {
.set_option = ioda_eeh_set_option,
.get_state = ioda_eeh_get_state,
.reset = ioda_eeh_reset,
+ .get_log = ioda_eeh_get_log,
.configure_bridge = ioda_eeh_configure_bridge,
.next_error = ioda_eeh_next_error
};
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 56a206f32f77..fd7a16f855ed 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -45,14 +45,31 @@
*/
static int powernv_eeh_init(void)
{
+ struct pci_controller *hose;
+ struct pnv_phb *phb;
+
/* We require OPALv3 */
if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
- pr_warning("%s: OPALv3 is required !\n", __func__);
+ pr_warn("%s: OPALv3 is required !\n",
+ __func__);
return -EINVAL;
}
- /* Set EEH probe mode */
- eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
+ /* Set probe mode */
+ eeh_add_flag(EEH_PROBE_MODE_DEV);
+
+ /*
+ * P7IOC blocks PCI config access to frozen PE, but PHB3
+ * doesn't do that. So we have to selectively enable I/O
+ * prior to collecting error log.
+ */
+ list_for_each_entry(hose, &hose_list, list_node) {
+ phb = hose->private_data;
+
+ if (phb->model == PNV_PHB_MODEL_P7IOC)
+ eeh_add_flag(EEH_ENABLE_IO_FOR_LOG);
+ break;
+ }
return 0;
}
@@ -107,6 +124,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
struct pnv_phb *phb = hose->private_data;
struct device_node *dn = pci_device_to_OF_node(dev);
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+ int ret;
/*
* When probing the root bridge, which doesn't have any
@@ -143,13 +161,27 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff);
/* Create PE */
- eeh_add_to_parent_pe(edev);
+ ret = eeh_add_to_parent_pe(edev);
+ if (ret) {
+ pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n",
+ __func__, pci_name(dev), ret);
+ return ret;
+ }
+
+ /*
+ * Cache the PE primary bus, which can't be fetched when
+ * full hotplug is in progress. In that case, all child
+ * PCI devices of the PE are expected to be removed prior
+ * to PE reset.
+ */
+ if (!edev->pe->bus)
+ edev->pe->bus = dev->bus;
/*
* Enable EEH explicitly so that we will do EEH check
* while accessing I/O stuff
*/
- eeh_set_enable(true);
+ eeh_add_flag(EEH_ENABLED);
/* Save memory bars */
eeh_save_bars(edev);
@@ -273,8 +305,8 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait)
max_wait -= mwait;
if (max_wait <= 0) {
- pr_warning("%s: Timeout getting PE#%x's state (%d)\n",
- __func__, pe->addr, max_wait);
+ pr_warn("%s: Timeout getting PE#%x's state (%d)\n",
+ __func__, pe->addr, max_wait);
return EEH_STATE_NOT_SUPPORT;
}
@@ -294,7 +326,7 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait)
* Retrieve the temporary or permanent error from the PE.
*/
static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
- char *drv_log, unsigned long len)
+ char *drv_log, unsigned long len)
{
struct pci_controller *hose = pe->phb;
struct pnv_phb *phb = hose->private_data;
@@ -398,9 +430,7 @@ static int __init eeh_powernv_init(void)
{
int ret = -EINVAL;
- if (!machine_is(powernv))
- return ret;
-
+ eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE);
ret = eeh_ops_register(&powernv_eeh_ops);
if (!ret)
pr_info("EEH: PowerNV platform initialized\n");
@@ -409,5 +439,4 @@ static int __init eeh_powernv_init(void)
return ret;
}
-
-early_initcall(eeh_powernv_init);
+machine_early_initcall(powernv, eeh_powernv_init);
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c
index 32e2adfa5320..e462ab947d16 100644
--- a/arch/powerpc/platforms/powernv/opal-async.c
+++ b/arch/powerpc/platforms/powernv/opal-async.c
@@ -20,6 +20,7 @@
#include <linux/wait.h>
#include <linux/gfp.h>
#include <linux/of.h>
+#include <asm/machdep.h>
#include <asm/opal.h>
#define N_ASYNC_COMPLETIONS 64
@@ -201,4 +202,4 @@ out_opal_node:
out:
return err;
}
-subsys_initcall(opal_async_comp_init);
+machine_subsys_initcall(powernv, opal_async_comp_init);
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index 788a1977b9a5..85bb8fff7947 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -102,9 +102,9 @@ static ssize_t dump_ack_store(struct dump_obj *dump_obj,
* due to the dynamic size of the dump
*/
static struct dump_attribute id_attribute =
- __ATTR(id, 0666, dump_id_show, NULL);
+ __ATTR(id, S_IRUGO, dump_id_show, NULL);
static struct dump_attribute type_attribute =
- __ATTR(type, 0666, dump_type_show, NULL);
+ __ATTR(type, S_IRUGO, dump_type_show, NULL);
static struct dump_attribute ack_attribute =
__ATTR(acknowledge, 0660, dump_ack_show, dump_ack_store);
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
index 0ad533b617f7..bbdb3ffaab98 100644
--- a/arch/powerpc/platforms/powernv/opal-elog.c
+++ b/arch/powerpc/platforms/powernv/opal-elog.c
@@ -82,9 +82,9 @@ static ssize_t elog_ack_store(struct elog_obj *elog_obj,
}
static struct elog_attribute id_attribute =
- __ATTR(id, 0666, elog_id_show, NULL);
+ __ATTR(id, S_IRUGO, elog_id_show, NULL);
static struct elog_attribute type_attribute =
- __ATTR(type, 0666, elog_type_show, NULL);
+ __ATTR(type, S_IRUGO, elog_type_show, NULL);
static struct elog_attribute ack_attribute =
__ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store);
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c
new file mode 100644
index 000000000000..97ac8dc33667
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-hmi.c
@@ -0,0 +1,188 @@
+/*
+ * OPAL hypervisor Maintenance interrupt handling support in PowreNV.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2014 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/opal.h>
+#include <asm/cputable.h>
+
+static int opal_hmi_handler_nb_init;
+struct OpalHmiEvtNode {
+ struct list_head list;
+ struct OpalHMIEvent hmi_evt;
+};
+static LIST_HEAD(opal_hmi_evt_list);
+static DEFINE_SPINLOCK(opal_hmi_evt_lock);
+
+static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt)
+{
+ const char *level, *sevstr, *error_info;
+ static const char *hmi_error_types[] = {
+ "Malfunction Alert",
+ "Processor Recovery done",
+ "Processor recovery occurred again",
+ "Processor recovery occurred for masked error",
+ "Timer facility experienced an error",
+ "TFMR SPR is corrupted",
+ "UPS (Uniterrupted Power System) Overflow indication",
+ "An XSCOM operation failure",
+ "An XSCOM operation completed",
+ "SCOM has set a reserved FIR bit to cause recovery",
+ "Debug trigger has set a reserved FIR bit to cause recovery",
+ "A hypervisor resource error occurred"
+ };
+
+ /* Print things out */
+ if (hmi_evt->version != OpalHMIEvt_V1) {
+ pr_err("HMI Interrupt, Unknown event version %d !\n",
+ hmi_evt->version);
+ return;
+ }
+ switch (hmi_evt->severity) {
+ case OpalHMI_SEV_NO_ERROR:
+ level = KERN_INFO;
+ sevstr = "Harmless";
+ break;
+ case OpalHMI_SEV_WARNING:
+ level = KERN_WARNING;
+ sevstr = "";
+ break;
+ case OpalHMI_SEV_ERROR_SYNC:
+ level = KERN_ERR;
+ sevstr = "Severe";
+ break;
+ case OpalHMI_SEV_FATAL:
+ default:
+ level = KERN_ERR;
+ sevstr = "Fatal";
+ break;
+ }
+
+ printk("%s%s Hypervisor Maintenance interrupt [%s]\n",
+ level, sevstr,
+ hmi_evt->disposition == OpalHMI_DISPOSITION_RECOVERED ?
+ "Recovered" : "Not recovered");
+ error_info = hmi_evt->type < ARRAY_SIZE(hmi_error_types) ?
+ hmi_error_types[hmi_evt->type]
+ : "Unknown";
+ printk("%s Error detail: %s\n", level, error_info);
+ printk("%s HMER: %016llx\n", level, be64_to_cpu(hmi_evt->hmer));
+ if ((hmi_evt->type == OpalHMI_ERROR_TFAC) ||
+ (hmi_evt->type == OpalHMI_ERROR_TFMR_PARITY))
+ printk("%s TFMR: %016llx\n", level,
+ be64_to_cpu(hmi_evt->tfmr));
+}
+
+static void hmi_event_handler(struct work_struct *work)
+{
+ unsigned long flags;
+ struct OpalHMIEvent *hmi_evt;
+ struct OpalHmiEvtNode *msg_node;
+ uint8_t disposition;
+
+ spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+ while (!list_empty(&opal_hmi_evt_list)) {
+ msg_node = list_entry(opal_hmi_evt_list.next,
+ struct OpalHmiEvtNode, list);
+ list_del(&msg_node->list);
+ spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+
+ hmi_evt = (struct OpalHMIEvent *) &msg_node->hmi_evt;
+ print_hmi_event_info(hmi_evt);
+ disposition = hmi_evt->disposition;
+ kfree(msg_node);
+
+ /*
+ * Check if HMI event has been recovered or not. If not
+ * then we can't continue, invoke panic.
+ */
+ if (disposition != OpalHMI_DISPOSITION_RECOVERED)
+ panic("Unrecoverable HMI exception");
+
+ spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+ }
+ spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+}
+
+static DECLARE_WORK(hmi_event_work, hmi_event_handler);
+/*
+ * opal_handle_hmi_event - notifier handler that queues up HMI events
+ * to be preocessed later.
+ */
+static int opal_handle_hmi_event(struct notifier_block *nb,
+ unsigned long msg_type, void *msg)
+{
+ unsigned long flags;
+ struct OpalHMIEvent *hmi_evt;
+ struct opal_msg *hmi_msg = msg;
+ struct OpalHmiEvtNode *msg_node;
+
+ /* Sanity Checks */
+ if (msg_type != OPAL_MSG_HMI_EVT)
+ return 0;
+
+ /* HMI event info starts from param[0] */
+ hmi_evt = (struct OpalHMIEvent *)&hmi_msg->params[0];
+
+ /* Delay the logging of HMI events to workqueue. */
+ msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC);
+ if (!msg_node) {
+ pr_err("HMI: out of memory, Opal message event not handled\n");
+ return -ENOMEM;
+ }
+ memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(struct OpalHMIEvent));
+
+ spin_lock_irqsave(&opal_hmi_evt_lock, flags);
+ list_add(&msg_node->list, &opal_hmi_evt_list);
+ spin_unlock_irqrestore(&opal_hmi_evt_lock, flags);
+
+ schedule_work(&hmi_event_work);
+ return 0;
+}
+
+static struct notifier_block opal_hmi_handler_nb = {
+ .notifier_call = opal_handle_hmi_event,
+ .next = NULL,
+ .priority = 0,
+};
+
+static int __init opal_hmi_handler_init(void)
+{
+ int ret;
+
+ if (!opal_hmi_handler_nb_init) {
+ ret = opal_message_notifier_register(
+ OPAL_MSG_HMI_EVT, &opal_hmi_handler_nb);
+ if (ret) {
+ pr_err("%s: Can't register OPAL event notifier (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+ opal_hmi_handler_nb_init = 1;
+ }
+ return 0;
+}
+subsys_initcall(opal_hmi_handler_init);
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c
index f04b4d8aca5a..ad4b31df779a 100644
--- a/arch/powerpc/platforms/powernv/opal-lpc.c
+++ b/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -324,7 +324,7 @@ static int opal_lpc_init_debugfs(void)
rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW);
return rc;
}
-device_initcall(opal_lpc_init_debugfs);
+machine_device_initcall(powernv, opal_lpc_init_debugfs);
#endif /* CONFIG_DEBUG_FS */
void opal_lpc_init(void)
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c
index b17a34b695ef..43db2136dbff 100644
--- a/arch/powerpc/platforms/powernv/opal-memory-errors.c
+++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
+#include <asm/machdep.h>
#include <asm/opal.h>
#include <asm/cputable.h>
@@ -143,4 +144,4 @@ static int __init opal_mem_err_init(void)
}
return 0;
}
-subsys_initcall(opal_mem_err_init);
+machine_subsys_initcall(powernv, opal_mem_err_init);
diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c
new file mode 100644
index 000000000000..d8a000a9988b
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c
@@ -0,0 +1,84 @@
+#include <linux/percpu.h>
+#include <linux/jump_label.h>
+#include <asm/trace.h>
+
+#ifdef CONFIG_JUMP_LABEL
+struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
+
+void opal_tracepoint_regfunc(void)
+{
+ static_key_slow_inc(&opal_tracepoint_key);
+}
+
+void opal_tracepoint_unregfunc(void)
+{
+ static_key_slow_dec(&opal_tracepoint_key);
+}
+#else
+/*
+ * We optimise OPAL calls by placing opal_tracepoint_refcount
+ * directly in the TOC so we can check if the opal tracepoints are
+ * enabled via a single load.
+ */
+
+/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
+extern long opal_tracepoint_refcount;
+
+void opal_tracepoint_regfunc(void)
+{
+ opal_tracepoint_refcount++;
+}
+
+void opal_tracepoint_unregfunc(void)
+{
+ opal_tracepoint_refcount--;
+}
+#endif
+
+/*
+ * Since the tracing code might execute OPAL calls we need to guard against
+ * recursion.
+ */
+static DEFINE_PER_CPU(unsigned int, opal_trace_depth);
+
+void __trace_opal_entry(unsigned long opcode, unsigned long *args)
+{
+ unsigned long flags;
+ unsigned int *depth;
+
+ local_irq_save(flags);
+
+ depth = &__get_cpu_var(opal_trace_depth);
+
+ if (*depth)
+ goto out;
+
+ (*depth)++;
+ preempt_disable();
+ trace_opal_entry(opcode, args);
+ (*depth)--;
+
+out:
+ local_irq_restore(flags);
+}
+
+void __trace_opal_exit(long opcode, unsigned long retval)
+{
+ unsigned long flags;
+ unsigned int *depth;
+
+ local_irq_save(flags);
+
+ depth = &__get_cpu_var(opal_trace_depth);
+
+ if (*depth)
+ goto out;
+
+ (*depth)++;
+ trace_opal_exit(opcode, retval);
+ preempt_enable();
+ (*depth)--;
+
+out:
+ local_irq_restore(flags);
+}
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 4abbff22a61f..2e6ce1b8dc8f 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -13,30 +13,69 @@
#include <asm/hvcall.h>
#include <asm/asm-offsets.h>
#include <asm/opal.h>
+#include <asm/jump_label.h>
+
+ .section ".text"
+
+#ifdef CONFIG_TRACEPOINTS
+#ifdef CONFIG_JUMP_LABEL
+#define OPAL_BRANCH(LABEL) \
+ ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key)
+#else
+
+ .section ".toc","aw"
+
+ .globl opal_tracepoint_refcount
+opal_tracepoint_refcount:
+ .llong 0
+
+ .section ".text"
+
+/*
+ * We branch around this in early init by using an unconditional cpu
+ * feature.
+ */
+#define OPAL_BRANCH(LABEL) \
+BEGIN_FTR_SECTION; \
+ b 1f; \
+END_FTR_SECTION(0, 1); \
+ ld r12,opal_tracepoint_refcount@toc(r2); \
+ std r12,32(r1); \
+ cmpdi r12,0; \
+ bne- LABEL; \
+1:
+
+#endif
+
+#else
+#define OPAL_BRANCH(LABEL)
+#endif
/* TODO:
*
* - Trace irqs in/off (needs saving/restoring all args, argh...)
* - Get r11 feed up by Dave so I can have better register usage
*/
+
#define OPAL_CALL(name, token) \
_GLOBAL(name); \
mflr r0; \
- mfcr r12; \
std r0,16(r1); \
+ li r0,token; \
+ OPAL_BRANCH(opal_tracepoint_entry) \
+ mfcr r12; \
stw r12,8(r1); \
std r1,PACAR1(r13); \
- li r0,0; \
+ li r11,0; \
mfmsr r12; \
- ori r0,r0,MSR_EE; \
+ ori r11,r11,MSR_EE; \
std r12,PACASAVEDMSR(r13); \
- andc r12,r12,r0; \
+ andc r12,r12,r11; \
mtmsrd r12,1; \
- LOAD_REG_ADDR(r0,opal_return); \
- mtlr r0; \
- li r0,MSR_DR|MSR_IR|MSR_LE;\
- andc r12,r12,r0; \
- li r0,token; \
+ LOAD_REG_ADDR(r11,opal_return); \
+ mtlr r11; \
+ li r11,MSR_DR|MSR_IR|MSR_LE;\
+ andc r12,r12,r11; \
mtspr SPRN_HSRR1,r12; \
LOAD_REG_ADDR(r11,opal); \
ld r12,8(r11); \
@@ -61,6 +100,64 @@ opal_return:
mtcr r4;
rfid
+#ifdef CONFIG_TRACEPOINTS
+opal_tracepoint_entry:
+ stdu r1,-STACKFRAMESIZE(r1)
+ std r0,STK_REG(R23)(r1)
+ std r3,STK_REG(R24)(r1)
+ std r4,STK_REG(R25)(r1)
+ std r5,STK_REG(R26)(r1)
+ std r6,STK_REG(R27)(r1)
+ std r7,STK_REG(R28)(r1)
+ std r8,STK_REG(R29)(r1)
+ std r9,STK_REG(R30)(r1)
+ std r10,STK_REG(R31)(r1)
+ mr r3,r0
+ addi r4,r1,STK_REG(R24)
+ bl __trace_opal_entry
+ ld r0,STK_REG(R23)(r1)
+ ld r3,STK_REG(R24)(r1)
+ ld r4,STK_REG(R25)(r1)
+ ld r5,STK_REG(R26)(r1)
+ ld r6,STK_REG(R27)(r1)
+ ld r7,STK_REG(R28)(r1)
+ ld r8,STK_REG(R29)(r1)
+ ld r9,STK_REG(R30)(r1)
+ ld r10,STK_REG(R31)(r1)
+ LOAD_REG_ADDR(r11,opal_tracepoint_return)
+ mfcr r12
+ std r11,16(r1)
+ stw r12,8(r1)
+ std r1,PACAR1(r13)
+ li r11,0
+ mfmsr r12
+ ori r11,r11,MSR_EE
+ std r12,PACASAVEDMSR(r13)
+ andc r12,r12,r11
+ mtmsrd r12,1
+ LOAD_REG_ADDR(r11,opal_return)
+ mtlr r11
+ li r11,MSR_DR|MSR_IR|MSR_LE
+ andc r12,r12,r11
+ mtspr SPRN_HSRR1,r12
+ LOAD_REG_ADDR(r11,opal)
+ ld r12,8(r11)
+ ld r2,0(r11)
+ mtspr SPRN_HSRR0,r12
+ hrfid
+
+opal_tracepoint_return:
+ std r3,STK_REG(R31)(r1)
+ mr r4,r3
+ ld r0,STK_REG(R23)(r1)
+ bl __trace_opal_exit
+ ld r3,STK_REG(R31)(r1)
+ addi r1,r1,STACKFRAMESIZE
+ ld r0,16(r1)
+ mtlr r0
+ blr
+#endif
+
OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL);
OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE);
OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ);
@@ -86,6 +183,7 @@ OPAL_CALL(opal_get_xive, OPAL_GET_XIVE);
OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS);
OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR);
+OPAL_CALL(opal_pci_eeh_freeze_set, OPAL_PCI_EEH_FREEZE_SET);
OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC);
OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE);
OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW);
@@ -146,3 +244,6 @@ OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ);
OPAL_CALL(opal_get_param, OPAL_GET_PARAM);
OPAL_CALL(opal_set_param, OPAL_SET_PARAM);
+OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI);
+OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION);
+OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
index 4cd2ea6c0dbe..7634d1c62299 100644
--- a/arch/powerpc/platforms/powernv/opal-xscom.c
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -130,4 +130,4 @@ static int opal_xscom_init(void)
scom_init(&opal_scom_controller);
return 0;
}
-arch_initcall(opal_xscom_init);
+machine_arch_initcall(powernv, opal_xscom_init);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 199975613fe9..b44eec3e8dbd 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -22,6 +22,8 @@
#include <linux/kobject.h>
#include <linux/delay.h>
#include <linux/memblock.h>
+
+#include <asm/machdep.h>
#include <asm/opal.h>
#include <asm/firmware.h>
#include <asm/mce.h>
@@ -192,16 +194,12 @@ static int __init opal_register_exception_handlers(void)
* fwnmi area at 0x7000 to provide the glue space to OPAL
*/
glue = 0x7000;
- opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
- 0, glue);
- glue += 128;
opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
#endif
return 0;
}
-
-early_initcall(opal_register_exception_handlers);
+machine_early_initcall(powernv, opal_register_exception_handlers);
int opal_notifier_register(struct notifier_block *nb)
{
@@ -368,7 +366,7 @@ static int __init opal_message_init(void)
}
return 0;
}
-early_initcall(opal_message_init);
+machine_early_initcall(powernv, opal_message_init);
int opal_get_chars(uint32_t vtermno, char *buf, int count)
{
@@ -513,6 +511,46 @@ int opal_machine_check(struct pt_regs *regs)
return 0;
}
+/* Early hmi handler called in real mode. */
+int opal_hmi_exception_early(struct pt_regs *regs)
+{
+ s64 rc;
+
+ /*
+ * call opal hmi handler. Pass paca address as token.
+ * The return value OPAL_SUCCESS is an indication that there is
+ * an HMI event generated waiting to pull by Linux.
+ */
+ rc = opal_handle_hmi();
+ if (rc == OPAL_SUCCESS) {
+ local_paca->hmi_event_available = 1;
+ return 1;
+ }
+ return 0;
+}
+
+/* HMI exception handler called in virtual mode during check_irq_replay. */
+int opal_handle_hmi_exception(struct pt_regs *regs)
+{
+ s64 rc;
+ __be64 evt = 0;
+
+ /*
+ * Check if HMI event is available.
+ * if Yes, then call opal_poll_events to pull opal messages and
+ * process them.
+ */
+ if (!local_paca->hmi_event_available)
+ return 0;
+
+ local_paca->hmi_event_available = 0;
+ rc = opal_poll_events(&evt);
+ if (rc == OPAL_SUCCESS && evt)
+ opal_do_notifier(be64_to_cpu(evt));
+
+ return 1;
+}
+
static uint64_t find_recovery_address(uint64_t nip)
{
int i;
@@ -567,6 +605,24 @@ static int opal_sysfs_init(void)
return 0;
}
+static void __init opal_dump_region_init(void)
+{
+ void *addr;
+ uint64_t size;
+ int rc;
+
+ /* Register kernel log buffer */
+ addr = log_buf_addr_get();
+ size = log_buf_len_get();
+ rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF,
+ __pa(addr), size);
+ /* Don't warn if this is just an older OPAL that doesn't
+ * know about that call
+ */
+ if (rc && rc != OPAL_UNSUPPORTED)
+ pr_warn("DUMP: Failed to register kernel log buffer. "
+ "rc = %d\n", rc);
+}
static int __init opal_init(void)
{
struct device_node *np, *consoles;
@@ -616,6 +672,8 @@ static int __init opal_init(void)
/* Create "opal" kobject under /sys/firmware */
rc = opal_sysfs_init();
if (rc == 0) {
+ /* Setup dump region interface */
+ opal_dump_region_init();
/* Setup error log interface */
rc = opal_elog_init();
/* Setup code update interface */
@@ -630,7 +688,7 @@ static int __init opal_init(void)
return 0;
}
-subsys_initcall(opal_init);
+machine_subsys_initcall(powernv, opal_init);
void opal_shutdown(void)
{
@@ -656,6 +714,9 @@ void opal_shutdown(void)
else
mdelay(10);
}
+
+ /* Unregister memory dump region */
+ opal_unregister_dump_region(OPAL_DUMP_REGION_LOG_BUF);
}
/* Export this so that test modules can use it */
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index de19edeaa7a7..df241b11d4f7 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -36,6 +36,7 @@
#include <asm/tce.h>
#include <asm/xics.h>
#include <asm/debug.h>
+#include <asm/firmware.h>
#include "powernv.h"
#include "pci.h"
@@ -82,6 +83,12 @@ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
: : "r" (val), "r" (paddr) : "memory");
}
+static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
+{
+ return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
+ (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
+}
+
static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
{
unsigned long pe;
@@ -106,6 +113,380 @@ static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
clear_bit(pe, phb->ioda.pe_alloc);
}
+/* The default M64 BAR is shared by all PEs */
+static int pnv_ioda2_init_m64(struct pnv_phb *phb)
+{
+ const char *desc;
+ struct resource *r;
+ s64 rc;
+
+ /* Configure the default M64 BAR */
+ rc = opal_pci_set_phb_mem_window(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE,
+ phb->ioda.m64_bar_idx,
+ phb->ioda.m64_base,
+ 0, /* unused */
+ phb->ioda.m64_size);
+ if (rc != OPAL_SUCCESS) {
+ desc = "configuring";
+ goto fail;
+ }
+
+ /* Enable the default M64 BAR */
+ rc = opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE,
+ phb->ioda.m64_bar_idx,
+ OPAL_ENABLE_M64_SPLIT);
+ if (rc != OPAL_SUCCESS) {
+ desc = "enabling";
+ goto fail;
+ }
+
+ /* Mark the M64 BAR assigned */
+ set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc);
+
+ /*
+ * Strip off the segment used by the reserved PE, which is
+ * expected to be 0 or last one of PE capabicity.
+ */
+ r = &phb->hose->mem_resources[1];
+ if (phb->ioda.reserved_pe == 0)
+ r->start += phb->ioda.m64_segsize;
+ else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1))
+ r->end -= phb->ioda.m64_segsize;
+ else
+ pr_warn(" Cannot strip M64 segment for reserved PE#%d\n",
+ phb->ioda.reserved_pe);
+
+ return 0;
+
+fail:
+ pr_warn(" Failure %lld %s M64 BAR#%d\n",
+ rc, desc, phb->ioda.m64_bar_idx);
+ opal_pci_phb_mmio_enable(phb->opal_id,
+ OPAL_M64_WINDOW_TYPE,
+ phb->ioda.m64_bar_idx,
+ OPAL_DISABLE_M64);
+ return -EIO;
+}
+
+static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb)
+{
+ resource_size_t sgsz = phb->ioda.m64_segsize;
+ struct pci_dev *pdev;
+ struct resource *r;
+ int base, step, i;
+
+ /*
+ * Root bus always has full M64 range and root port has
+ * M64 range used in reality. So we're checking root port
+ * instead of root bus.
+ */
+ list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) {
+ for (i = PCI_BRIDGE_RESOURCES;
+ i <= PCI_BRIDGE_RESOURCE_END; i++) {
+ r = &pdev->resource[i];
+ if (!r->parent ||
+ !pnv_pci_is_mem_pref_64(r->flags))
+ continue;
+
+ base = (r->start - phb->ioda.m64_base) / sgsz;
+ for (step = 0; step < resource_size(r) / sgsz; step++)
+ set_bit(base + step, phb->ioda.pe_alloc);
+ }
+ }
+}
+
+static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb,
+ struct pci_bus *bus, int all)
+{
+ resource_size_t segsz = phb->ioda.m64_segsize;
+ struct pci_dev *pdev;
+ struct resource *r;
+ struct pnv_ioda_pe *master_pe, *pe;
+ unsigned long size, *pe_alloc;
+ bool found;
+ int start, i, j;
+
+ /* Root bus shouldn't use M64 */
+ if (pci_is_root_bus(bus))
+ return IODA_INVALID_PE;
+
+ /* We support only one M64 window on each bus */
+ found = false;
+ pci_bus_for_each_resource(bus, r, i) {
+ if (r && r->parent &&
+ pnv_pci_is_mem_pref_64(r->flags)) {
+ found = true;
+ break;
+ }
+ }
+
+ /* No M64 window found ? */
+ if (!found)
+ return IODA_INVALID_PE;
+
+ /* Allocate bitmap */
+ size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
+ pe_alloc = kzalloc(size, GFP_KERNEL);
+ if (!pe_alloc) {
+ pr_warn("%s: Out of memory !\n",
+ __func__);
+ return IODA_INVALID_PE;
+ }
+
+ /*
+ * Figure out reserved PE numbers by the PE
+ * the its child PEs.
+ */
+ start = (r->start - phb->ioda.m64_base) / segsz;
+ for (i = 0; i < resource_size(r) / segsz; i++)
+ set_bit(start + i, pe_alloc);
+
+ if (all)
+ goto done;
+
+ /*
+ * If the PE doesn't cover all subordinate buses,
+ * we need subtract from reserved PEs for children.
+ */
+ list_for_each_entry(pdev, &bus->devices, bus_list) {
+ if (!pdev->subordinate)
+ continue;
+
+ pci_bus_for_each_resource(pdev->subordinate, r, i) {
+ if (!r || !r->parent ||
+ !pnv_pci_is_mem_pref_64(r->flags))
+ continue;
+
+ start = (r->start - phb->ioda.m64_base) / segsz;
+ for (j = 0; j < resource_size(r) / segsz ; j++)
+ clear_bit(start + j, pe_alloc);
+ }
+ }
+
+ /*
+ * the current bus might not own M64 window and that's all
+ * contributed by its child buses. For the case, we needn't
+ * pick M64 dependent PE#.
+ */
+ if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) {
+ kfree(pe_alloc);
+ return IODA_INVALID_PE;
+ }
+
+ /*
+ * Figure out the master PE and put all slave PEs to master
+ * PE's list to form compound PE.
+ */
+done:
+ master_pe = NULL;
+ i = -1;
+ while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) <
+ phb->ioda.total_pe) {
+ pe = &phb->ioda.pe_array[i];
+ pe->phb = phb;
+ pe->pe_number = i;
+
+ if (!master_pe) {
+ pe->flags |= PNV_IODA_PE_MASTER;
+ INIT_LIST_HEAD(&pe->slaves);
+ master_pe = pe;
+ } else {
+ pe->flags |= PNV_IODA_PE_SLAVE;
+ pe->master = master_pe;
+ list_add_tail(&pe->list, &master_pe->slaves);
+ }
+ }
+
+ kfree(pe_alloc);
+ return master_pe->pe_number;
+}
+
+static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
+{
+ struct pci_controller *hose = phb->hose;
+ struct device_node *dn = hose->dn;
+ struct resource *res;
+ const u32 *r;
+ u64 pci_addr;
+
+ if (!firmware_has_feature(FW_FEATURE_OPALv3)) {
+ pr_info(" Firmware too old to support M64 window\n");
+ return;
+ }
+
+ r = of_get_property(dn, "ibm,opal-m64-window", NULL);
+ if (!r) {
+ pr_info(" No <ibm,opal-m64-window> on %s\n",
+ dn->full_name);
+ return;
+ }
+
+ /* FIXME: Support M64 for P7IOC */
+ if (phb->type != PNV_PHB_IODA2) {
+ pr_info(" Not support M64 window\n");
+ return;
+ }
+
+ res = &hose->mem_resources[1];
+ res->start = of_translate_address(dn, r + 2);
+ res->end = res->start + of_read_number(r + 4, 2) - 1;
+ res->flags = (IORESOURCE_MEM | IORESOURCE_MEM_64 | IORESOURCE_PREFETCH);
+ pci_addr = of_read_number(r, 2);
+ hose->mem_offset[1] = res->start - pci_addr;
+
+ phb->ioda.m64_size = resource_size(res);
+ phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe;
+ phb->ioda.m64_base = pci_addr;
+
+ /* Use last M64 BAR to cover M64 window */
+ phb->ioda.m64_bar_idx = 15;
+ phb->init_m64 = pnv_ioda2_init_m64;
+ phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe;
+ phb->pick_m64_pe = pnv_ioda2_pick_m64_pe;
+}
+
+static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no)
+{
+ struct pnv_ioda_pe *pe = &phb->ioda.pe_array[pe_no];
+ struct pnv_ioda_pe *slave;
+ s64 rc;
+
+ /* Fetch master PE */
+ if (pe->flags & PNV_IODA_PE_SLAVE) {
+ pe = pe->master;
+ WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+ pe_no = pe->pe_number;
+ }
+
+ /* Freeze master PE */
+ rc = opal_pci_eeh_freeze_set(phb->opal_id,
+ pe_no,
+ OPAL_EEH_ACTION_SET_FREEZE_ALL);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n",
+ __func__, rc, phb->hose->global_number, pe_no);
+ return;
+ }
+
+ /* Freeze slave PEs */
+ if (!(pe->flags & PNV_IODA_PE_MASTER))
+ return;
+
+ list_for_each_entry(slave, &pe->slaves, list) {
+ rc = opal_pci_eeh_freeze_set(phb->opal_id,
+ slave->pe_number,
+ OPAL_EEH_ACTION_SET_FREEZE_ALL);
+ if (rc != OPAL_SUCCESS)
+ pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n",
+ __func__, rc, phb->hose->global_number,
+ slave->pe_number);
+ }
+}
+
+int pnv_ioda_unfreeze_pe(struct pnv_phb *phb, int pe_no, int opt)
+{
+ struct pnv_ioda_pe *pe, *slave;
+ s64 rc;
+
+ /* Find master PE */
+ pe = &phb->ioda.pe_array[pe_no];
+ if (pe->flags & PNV_IODA_PE_SLAVE) {
+ pe = pe->master;
+ WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+ pe_no = pe->pe_number;
+ }
+
+ /* Clear frozen state for master PE */
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, opt);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n",
+ __func__, rc, opt, phb->hose->global_number, pe_no);
+ return -EIO;
+ }
+
+ if (!(pe->flags & PNV_IODA_PE_MASTER))
+ return 0;
+
+ /* Clear frozen state for slave PEs */
+ list_for_each_entry(slave, &pe->slaves, list) {
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+ slave->pe_number,
+ opt);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n",
+ __func__, rc, opt, phb->hose->global_number,
+ slave->pe_number);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no)
+{
+ struct pnv_ioda_pe *slave, *pe;
+ u8 fstate, state;
+ __be16 pcierr;
+ s64 rc;
+
+ /* Sanity check on PE number */
+ if (pe_no < 0 || pe_no >= phb->ioda.total_pe)
+ return OPAL_EEH_STOPPED_PERM_UNAVAIL;
+
+ /*
+ * Fetch the master PE and the PE instance might be
+ * not initialized yet.
+ */
+ pe = &phb->ioda.pe_array[pe_no];
+ if (pe->flags & PNV_IODA_PE_SLAVE) {
+ pe = pe->master;
+ WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER));
+ pe_no = pe->pe_number;
+ }
+
+ /* Check the master PE */
+ rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no,
+ &state, &pcierr, NULL);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld getting "
+ "PHB#%x-PE#%x state\n",
+ __func__, rc,
+ phb->hose->global_number, pe_no);
+ return OPAL_EEH_STOPPED_TEMP_UNAVAIL;
+ }
+
+ /* Check the slave PE */
+ if (!(pe->flags & PNV_IODA_PE_MASTER))
+ return state;
+
+ list_for_each_entry(slave, &pe->slaves, list) {
+ rc = opal_pci_eeh_freeze_status(phb->opal_id,
+ slave->pe_number,
+ &fstate,
+ &pcierr,
+ NULL);
+ if (rc != OPAL_SUCCESS) {
+ pr_warn("%s: Failure %lld getting "
+ "PHB#%x-PE#%x state\n",
+ __func__, rc,
+ phb->hose->global_number, slave->pe_number);
+ return OPAL_EEH_STOPPED_TEMP_UNAVAIL;
+ }
+
+ /*
+ * Override the result based on the ascending
+ * priority.
+ */
+ if (fstate > state)
+ state = fstate;
+ }
+
+ return state;
+}
+
/* Currently those 2 are only used when MSIs are enabled, this will change
* but in the meantime, we need to protect them to avoid warnings
*/
@@ -363,9 +744,16 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
struct pci_controller *hose = pci_bus_to_host(bus);
struct pnv_phb *phb = hose->private_data;
struct pnv_ioda_pe *pe;
- int pe_num;
+ int pe_num = IODA_INVALID_PE;
+
+ /* Check if PE is determined by M64 */
+ if (phb->pick_m64_pe)
+ pe_num = phb->pick_m64_pe(phb, bus, all);
+
+ /* The PE number isn't pinned by M64 */
+ if (pe_num == IODA_INVALID_PE)
+ pe_num = pnv_ioda_alloc_pe(phb);
- pe_num = pnv_ioda_alloc_pe(phb);
if (pe_num == IODA_INVALID_PE) {
pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
__func__, pci_domain_nr(bus), bus->number);
@@ -373,7 +761,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
}
pe = &phb->ioda.pe_array[pe_num];
- pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
+ pe->flags |= (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
pe->pbus = bus;
pe->pdev = NULL;
pe->tce32_seg = -1;
@@ -441,8 +829,15 @@ static void pnv_ioda_setup_PEs(struct pci_bus *bus)
static void pnv_pci_ioda_setup_PEs(void)
{
struct pci_controller *hose, *tmp;
+ struct pnv_phb *phb;
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+ phb = hose->private_data;
+
+ /* M64 layout might affect PE allocation */
+ if (phb->alloc_m64_pe)
+ phb->alloc_m64_pe(phb);
+
pnv_ioda_setup_PEs(hose->bus);
}
}
@@ -462,7 +857,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
pe = &phb->ioda.pe_array[pdn->pe_number];
WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops);
- set_iommu_table_base(&pdev->dev, &pe->tce32_table);
+ set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
}
static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb,
@@ -491,17 +886,26 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb,
set_dma_ops(&pdev->dev, &dma_iommu_ops);
set_iommu_table_base(&pdev->dev, &pe->tce32_table);
}
+ *pdev->dev.dma_mask = dma_mask;
return 0;
}
-static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
+static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe,
+ struct pci_bus *bus,
+ bool add_to_iommu_group)
{
struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) {
- set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table);
+ if (add_to_iommu_group)
+ set_iommu_table_base_and_group(&dev->dev,
+ &pe->tce32_table);
+ else
+ set_iommu_table_base(&dev->dev, &pe->tce32_table);
+
if (dev->subordinate)
- pnv_ioda_setup_bus_dma(pe, dev->subordinate);
+ pnv_ioda_setup_bus_dma(pe, dev->subordinate,
+ add_to_iommu_group);
}
}
@@ -513,15 +917,16 @@ static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe,
(__be64 __iomem *)pe->tce_inval_reg_phys :
(__be64 __iomem *)tbl->it_index;
unsigned long start, end, inc;
+ const unsigned shift = tbl->it_page_shift;
start = __pa(startp);
end = __pa(endp);
/* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */
if (tbl->it_busno) {
- start <<= 12;
- end <<= 12;
- inc = 128 << 12;
+ start <<= shift;
+ end <<= shift;
+ inc = 128ull << shift;
start |= tbl->it_busno;
end |= tbl->it_busno;
} else if (tbl->it_type & TCE_PCI_SWINV_PAIR) {
@@ -559,18 +964,19 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe,
__be64 __iomem *invalidate = rm ?
(__be64 __iomem *)pe->tce_inval_reg_phys :
(__be64 __iomem *)tbl->it_index;
+ const unsigned shift = tbl->it_page_shift;
/* We'll invalidate DMA address in PE scope */
- start = 0x2ul << 60;
+ start = 0x2ull << 60;
start |= (pe->pe_number & 0xFF);
end = start;
/* Figure out the start, end and step */
inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64));
- start |= (inc << 12);
+ start |= (inc << shift);
inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64));
- end |= (inc << 12);
- inc = (0x1ul << 12);
+ end |= (inc << shift);
+ inc = (0x1ull << shift);
mb();
while (start <= end) {
@@ -654,7 +1060,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
/* Setup linux iommu table */
tbl = &pe->tce32_table;
pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs,
- base << 28);
+ base << 28, IOMMU_PAGE_SHIFT_4K);
/* OPAL variant of P7IOC SW invalidated TCEs */
swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
@@ -677,7 +1083,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
if (pe->pdev)
set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
else
- pnv_ioda_setup_bus_dma(pe, pe->pbus);
+ pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
return;
fail:
@@ -713,11 +1119,15 @@ static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable)
0);
/*
- * We might want to reset the DMA ops of all devices on
- * this PE. However in theory, that shouldn't be necessary
- * as this is used for VFIO/KVM pass-through and the device
- * hasn't yet been returned to its kernel driver
+ * EEH needs the mapping between IOMMU table and group
+ * of those VFIO/KVM pass-through devices. We can postpone
+ * resetting DMA ops until the DMA mask is configured in
+ * host side.
*/
+ if (pe->pdev)
+ set_iommu_table_base(&pe->pdev->dev, tbl);
+ else
+ pnv_ioda_setup_bus_dma(pe, pe->pbus, false);
}
if (rc)
pe_err(pe, "OPAL error %lld configuring bypass window\n", rc);
@@ -784,7 +1194,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
/* Setup linux iommu table */
tbl = &pe->tce32_table;
- pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0);
+ pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0,
+ IOMMU_PAGE_SHIFT_4K);
/* OPAL variant of PHB3 invalidated TCEs */
swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL);
@@ -805,7 +1216,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
if (pe->pdev)
set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
else
- pnv_ioda_setup_bus_dma(pe, pe->pbus);
+ pnv_ioda_setup_bus_dma(pe, pe->pbus, true);
/* Also create a bypass window */
pnv_pci_ioda2_setup_bypass_pe(phb, pe);
@@ -1055,9 +1466,6 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
index++;
}
} else if (res->flags & IORESOURCE_MEM) {
- /* WARNING: Assumes M32 is mem region 0 in PHB. We need to
- * harden that algorithm when we start supporting M64
- */
region.start = res->start -
hose->mem_offset[0] -
phb->ioda.m32_pci_base;
@@ -1141,9 +1549,8 @@ static void pnv_pci_ioda_fixup(void)
pnv_pci_ioda_create_dbgfs();
#ifdef CONFIG_EEH
- eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
- eeh_addr_cache_build();
eeh_init();
+ eeh_addr_cache_build();
#endif
}
@@ -1178,7 +1585,10 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
bridge = bridge->bus->self;
}
- /* We need support prefetchable memory window later */
+ /* We fail back to M32 if M64 isn't supported */
+ if (phb->ioda.m64_segsize &&
+ pnv_pci_is_mem_pref_64(type))
+ return phb->ioda.m64_segsize;
if (type & IORESOURCE_MEM)
return phb->ioda.m32_segsize;
@@ -1299,6 +1709,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL);
if (prop32)
phb->ioda.reserved_pe = be32_to_cpup(prop32);
+
+ /* Parse 64-bit MMIO range */
+ pnv_ioda_parse_m64_window(phb);
+
phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
/* FW Has already off top 64k of M32 space (MSI space) */
phb->ioda.m32_size += 0x10000;
@@ -1334,14 +1748,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
/* Calculate how many 32-bit TCE segments we have */
phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28;
- /* Clear unusable m64 */
- hose->mem_resources[1].flags = 0;
- hose->mem_resources[1].start = 0;
- hose->mem_resources[1].end = 0;
- hose->mem_resources[2].flags = 0;
- hose->mem_resources[2].start = 0;
- hose->mem_resources[2].end = 0;
-
#if 0 /* We should really do that ... */
rc = opal_pci_set_phb_mem_window(opal->phb_id,
window_type,
@@ -1351,14 +1757,21 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
segment_size);
#endif
- pr_info(" %d (%d) PE's M32: 0x%x [segment=0x%x]"
- " IO: 0x%x [segment=0x%x]\n",
- phb->ioda.total_pe,
- phb->ioda.reserved_pe,
- phb->ioda.m32_size, phb->ioda.m32_segsize,
- phb->ioda.io_size, phb->ioda.io_segsize);
+ pr_info(" %03d (%03d) PE's M32: 0x%x [segment=0x%x]\n",
+ phb->ioda.total_pe, phb->ioda.reserved_pe,
+ phb->ioda.m32_size, phb->ioda.m32_segsize);
+ if (phb->ioda.m64_size)
+ pr_info(" M64: 0x%lx [segment=0x%lx]\n",
+ phb->ioda.m64_size, phb->ioda.m64_segsize);
+ if (phb->ioda.io_size)
+ pr_info(" IO: 0x%x [segment=0x%x]\n",
+ phb->ioda.io_size, phb->ioda.io_segsize);
+
phb->hose->ops = &pnv_pci_ops;
+ phb->get_pe_state = pnv_ioda_get_pe_state;
+ phb->freeze_pe = pnv_ioda_freeze_pe;
+ phb->unfreeze_pe = pnv_ioda_unfreeze_pe;
#ifdef CONFIG_EEH
phb->eeh_ops = &ioda_eeh_ops;
#endif
@@ -1404,6 +1817,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
}
+
+ /* Configure M64 window */
+ if (phb->init_m64 && phb->init_m64(phb))
+ hose->mem_resources[1].flags = 0;
}
void __init pnv_pci_init_ioda2_phb(struct device_node *np)
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index e3807d69393e..94ce3481490b 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -172,7 +172,8 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id,
/* Setup TCEs */
phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
- tce_mem, tce_size, 0);
+ tce_mem, tce_size, 0,
+ IOMMU_PAGE_SHIFT_4K);
}
void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index f91a4e5d872e..b854b57ed5e1 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -132,61 +132,78 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
data = (struct OpalIoP7IOCPhbErrorData *)common;
pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n",
- hose->global_number, common->version);
+ hose->global_number, be32_to_cpu(common->version));
if (data->brdgCtl)
pr_info("brdgCtl: %08x\n",
- data->brdgCtl);
+ be32_to_cpu(data->brdgCtl));
if (data->portStatusReg || data->rootCmplxStatus ||
data->busAgentStatus)
pr_info("UtlSts: %08x %08x %08x\n",
- data->portStatusReg, data->rootCmplxStatus,
- data->busAgentStatus);
+ be32_to_cpu(data->portStatusReg),
+ be32_to_cpu(data->rootCmplxStatus),
+ be32_to_cpu(data->busAgentStatus));
if (data->deviceStatus || data->slotStatus ||
data->linkStatus || data->devCmdStatus ||
data->devSecStatus)
pr_info("RootSts: %08x %08x %08x %08x %08x\n",
- data->deviceStatus, data->slotStatus,
- data->linkStatus, data->devCmdStatus,
- data->devSecStatus);
+ be32_to_cpu(data->deviceStatus),
+ be32_to_cpu(data->slotStatus),
+ be32_to_cpu(data->linkStatus),
+ be32_to_cpu(data->devCmdStatus),
+ be32_to_cpu(data->devSecStatus));
if (data->rootErrorStatus || data->uncorrErrorStatus ||
data->corrErrorStatus)
pr_info("RootErrSts: %08x %08x %08x\n",
- data->rootErrorStatus, data->uncorrErrorStatus,
- data->corrErrorStatus);
+ be32_to_cpu(data->rootErrorStatus),
+ be32_to_cpu(data->uncorrErrorStatus),
+ be32_to_cpu(data->corrErrorStatus));
if (data->tlpHdr1 || data->tlpHdr2 ||
data->tlpHdr3 || data->tlpHdr4)
pr_info("RootErrLog: %08x %08x %08x %08x\n",
- data->tlpHdr1, data->tlpHdr2,
- data->tlpHdr3, data->tlpHdr4);
+ be32_to_cpu(data->tlpHdr1),
+ be32_to_cpu(data->tlpHdr2),
+ be32_to_cpu(data->tlpHdr3),
+ be32_to_cpu(data->tlpHdr4));
if (data->sourceId || data->errorClass ||
data->correlator)
pr_info("RootErrLog1: %08x %016llx %016llx\n",
- data->sourceId, data->errorClass,
- data->correlator);
+ be32_to_cpu(data->sourceId),
+ be64_to_cpu(data->errorClass),
+ be64_to_cpu(data->correlator));
if (data->p7iocPlssr || data->p7iocCsr)
pr_info("PhbSts: %016llx %016llx\n",
- data->p7iocPlssr, data->p7iocCsr);
+ be64_to_cpu(data->p7iocPlssr),
+ be64_to_cpu(data->p7iocCsr));
if (data->lemFir)
pr_info("Lem: %016llx %016llx %016llx\n",
- data->lemFir, data->lemErrorMask,
- data->lemWOF);
+ be64_to_cpu(data->lemFir),
+ be64_to_cpu(data->lemErrorMask),
+ be64_to_cpu(data->lemWOF));
if (data->phbErrorStatus)
pr_info("PhbErr: %016llx %016llx %016llx %016llx\n",
- data->phbErrorStatus, data->phbFirstErrorStatus,
- data->phbErrorLog0, data->phbErrorLog1);
+ be64_to_cpu(data->phbErrorStatus),
+ be64_to_cpu(data->phbFirstErrorStatus),
+ be64_to_cpu(data->phbErrorLog0),
+ be64_to_cpu(data->phbErrorLog1));
if (data->mmioErrorStatus)
pr_info("OutErr: %016llx %016llx %016llx %016llx\n",
- data->mmioErrorStatus, data->mmioFirstErrorStatus,
- data->mmioErrorLog0, data->mmioErrorLog1);
+ be64_to_cpu(data->mmioErrorStatus),
+ be64_to_cpu(data->mmioFirstErrorStatus),
+ be64_to_cpu(data->mmioErrorLog0),
+ be64_to_cpu(data->mmioErrorLog1));
if (data->dma0ErrorStatus)
pr_info("InAErr: %016llx %016llx %016llx %016llx\n",
- data->dma0ErrorStatus, data->dma0FirstErrorStatus,
- data->dma0ErrorLog0, data->dma0ErrorLog1);
+ be64_to_cpu(data->dma0ErrorStatus),
+ be64_to_cpu(data->dma0FirstErrorStatus),
+ be64_to_cpu(data->dma0ErrorLog0),
+ be64_to_cpu(data->dma0ErrorLog1));
if (data->dma1ErrorStatus)
pr_info("InBErr: %016llx %016llx %016llx %016llx\n",
- data->dma1ErrorStatus, data->dma1FirstErrorStatus,
- data->dma1ErrorLog0, data->dma1ErrorLog1);
+ be64_to_cpu(data->dma1ErrorStatus),
+ be64_to_cpu(data->dma1FirstErrorStatus),
+ be64_to_cpu(data->dma1ErrorLog0),
+ be64_to_cpu(data->dma1ErrorLog1));
for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
if ((data->pestA[i] >> 63) == 0 &&
@@ -194,7 +211,8 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
continue;
pr_info("PE[%3d] A/B: %016llx %016llx\n",
- i, data->pestA[i], data->pestB[i]);
+ i, be64_to_cpu(data->pestA[i]),
+ be64_to_cpu(data->pestB[i]));
}
}
@@ -319,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
{
unsigned long flags, rc;
- int has_diag;
+ int has_diag, ret = 0;
spin_lock_irqsave(&phb->lock, flags);
+ /* Fetch PHB diag-data */
rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
PNV_PCI_DIAG_BUF_SIZE);
has_diag = (rc == OPAL_SUCCESS);
- rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+ /* If PHB supports compound PE, to handle it */
+ if (phb->unfreeze_pe) {
+ ret = phb->unfreeze_pe(phb,
+ pe_no,
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
- if (rc) {
- pr_warning("PCI %d: Failed to clear EEH freeze state"
- " for PE#%d, err %ld\n",
- phb->hose->global_number, pe_no, rc);
-
- /* For now, let's only display the diag buffer when we fail to clear
- * the EEH status. We'll do more sensible things later when we have
- * proper EEH support. We need to make sure we don't pollute ourselves
- * with the normal errors generated when probing empty slots
- */
- if (has_diag)
- pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
- else
- pr_warning("PCI %d: No diag data available\n",
- phb->hose->global_number);
+ } else {
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id,
+ pe_no,
+ OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+ if (rc) {
+ pr_warn("%s: Failure %ld clearing frozen "
+ "PHB#%x-PE#%x\n",
+ __func__, rc, phb->hose->global_number,
+ pe_no);
+ ret = -EIO;
+ }
}
+ /*
+ * For now, let's only display the diag buffer when we fail to clear
+ * the EEH status. We'll do more sensible things later when we have
+ * proper EEH support. We need to make sure we don't pollute ourselves
+ * with the normal errors generated when probing empty slots
+ */
+ if (has_diag && ret)
+ pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
+
spin_unlock_irqrestore(&phb->lock, flags);
}
static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
struct device_node *dn)
{
- s64 rc;
u8 fstate;
__be16 pcierr;
- u32 pe_no;
+ int pe_no;
+ s64 rc;
/*
* Get the PE#. During the PCI probe stage, we might not
@@ -370,20 +397,42 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
pe_no = phb->ioda.reserved_pe;
}
- /* Read freeze status */
- rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
- NULL);
- if (rc) {
- pr_warning("%s: Can't read EEH status (PE#%d) for "
- "%s, err %lld\n",
- __func__, pe_no, dn->full_name, rc);
- return;
+ /*
+ * Fetch frozen state. If the PHB support compound PE,
+ * we need handle that case.
+ */
+ if (phb->get_pe_state) {
+ fstate = phb->get_pe_state(phb, pe_no);
+ } else {
+ rc = opal_pci_eeh_freeze_status(phb->opal_id,
+ pe_no,
+ &fstate,
+ &pcierr,
+ NULL);
+ if (rc) {
+ pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n",
+ __func__, rc, phb->hose->global_number, pe_no);
+ return;
+ }
}
+
cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
(PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn),
pe_no, fstate);
- if (fstate != 0)
+
+ /* Clear the frozen state if applicable */
+ if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
+ fstate == OPAL_EEH_STOPPED_DMA_FREEZE ||
+ fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) {
+ /*
+ * If PHB supports compound PE, freeze it for
+ * consistency.
+ */
+ if (phb->freeze_pe)
+ phb->freeze_pe(phb, pe_no);
+
pnv_pci_handle_eeh_config(phb, pe_no);
+ }
}
int pnv_pci_cfg_read(struct device_node *dn,
@@ -564,10 +613,11 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
proto_tce |= TCE_PCI_WRITE;
tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
- rpn = __pa(uaddr) >> TCE_SHIFT;
+ rpn = __pa(uaddr) >> tbl->it_page_shift;
while (npages--)
- *(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT));
+ *(tcep++) = cpu_to_be64(proto_tce |
+ (rpn++ << tbl->it_page_shift));
/* Some implementations won't cache invalid TCEs and thus may not
* need that flush. We'll probably turn it_type into a bit mask
@@ -627,11 +677,11 @@ static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages)
void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
void *tce_mem, u64 tce_size,
- u64 dma_offset)
+ u64 dma_offset, unsigned page_shift)
{
tbl->it_blocksize = 16;
tbl->it_base = (unsigned long)tce_mem;
- tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
+ tbl->it_page_shift = page_shift;
tbl->it_offset = dma_offset >> tbl->it_page_shift;
tbl->it_index = 0;
tbl->it_size = tce_size >> 3;
@@ -656,7 +706,7 @@ static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose)
if (WARN_ON(!tbl))
return NULL;
pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)),
- be32_to_cpup(sizep), 0);
+ be32_to_cpup(sizep), 0, IOMMU_PAGE_SHIFT_4K);
iommu_init_table(tbl, hose->node);
iommu_register_group(tbl, pci_domain_nr(hose->bus), 0);
@@ -842,5 +892,4 @@ static int __init tce_iommu_bus_notifier_init(void)
bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
return 0;
}
-
-subsys_initcall_sync(tce_iommu_bus_notifier_init);
+machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init);
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 676232c34328..48494d4b6058 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -21,6 +21,8 @@ enum pnv_phb_model {
#define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */
#define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */
#define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */
+#define PNV_IODA_PE_MASTER (1 << 3) /* Master PE in compound case */
+#define PNV_IODA_PE_SLAVE (1 << 4) /* Slave PE in compound case */
/* Data associated with a PE, including IOMMU tracking etc.. */
struct pnv_phb;
@@ -64,6 +66,10 @@ struct pnv_ioda_pe {
*/
int mve_number;
+ /* PEs in compound case */
+ struct pnv_ioda_pe *master;
+ struct list_head slaves;
+
/* Link in list of PE#s */
struct list_head dma_link;
struct list_head list;
@@ -119,6 +125,12 @@ struct pnv_phb {
void (*fixup_phb)(struct pci_controller *hose);
u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
void (*shutdown)(struct pnv_phb *phb);
+ int (*init_m64)(struct pnv_phb *phb);
+ void (*alloc_m64_pe)(struct pnv_phb *phb);
+ int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all);
+ int (*get_pe_state)(struct pnv_phb *phb, int pe_no);
+ void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
+ int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt);
union {
struct {
@@ -129,9 +141,20 @@ struct pnv_phb {
/* Global bridge info */
unsigned int total_pe;
unsigned int reserved_pe;
+
+ /* 32-bit MMIO window */
unsigned int m32_size;
unsigned int m32_segsize;
unsigned int m32_pci_base;
+
+ /* 64-bit MMIO window */
+ unsigned int m64_bar_idx;
+ unsigned long m64_size;
+ unsigned long m64_segsize;
+ unsigned long m64_base;
+ unsigned long m64_bar_alloc;
+
+ /* IO ports */
unsigned int io_size;
unsigned int io_segsize;
unsigned int io_pci_base;
@@ -198,7 +221,7 @@ int pnv_pci_cfg_write(struct device_node *dn,
int where, int size, u32 val);
extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
void *tce_mem, u64 tce_size,
- u64 dma_offset);
+ u64 dma_offset, unsigned page_shift);
extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
extern void pnv_pci_init_ioda_hub(struct device_node *np);
extern void pnv_pci_init_ioda2_phb(struct device_node *np);
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
index 1cb160dc1609..80db43944afe 100644
--- a/arch/powerpc/platforms/powernv/rng.c
+++ b/arch/powerpc/platforms/powernv/rng.c
@@ -123,4 +123,4 @@ static __init int rng_init(void)
return 0;
}
-subsys_initcall(rng_init);
+machine_subsys_initcall(powernv, rng_init);
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index d9b88fa7c5a3..5a0e2dc6de5f 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -264,6 +264,8 @@ static void __init pnv_setup_machdep_opal(void)
ppc_md.halt = pnv_halt;
ppc_md.machine_check_exception = opal_machine_check;
ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
+ ppc_md.hmi_exception_early = opal_hmi_exception_early;
+ ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
}
#ifdef CONFIG_PPC_POWERNV_RTAS
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 2d0b4d68a40a..a2450b8a50a5 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -400,10 +400,10 @@ out:
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
struct device_node *dn, *parent;
- unsigned long drc_index;
+ u32 drc_index;
int rc;
- rc = strict_strtoul(buf, 0, &drc_index);
+ rc = kstrtou32(buf, 0, &drc_index);
if (rc)
return -EINVAL;
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
index 7d61498e45c0..1062f71f5a85 100644
--- a/arch/powerpc/platforms/pseries/dtl.c
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -29,6 +29,7 @@
#include <asm/lppaca.h>
#include <asm/debug.h>
#include <asm/plpar_wrappers.h>
+#include <asm/machdep.h>
struct dtl {
struct dtl_entry *buf;
@@ -391,4 +392,4 @@ err_remove_dir:
err:
return rc;
}
-arch_initcall(dtl_init);
+machine_arch_initcall(pseries, dtl_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 0bec0c02c5e7..b08053819d99 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -89,26 +89,26 @@ static int pseries_eeh_init(void)
* of domain/bus/slot/function for EEH RTAS operations.
*/
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",
+ pr_warn("%s: RTAS service <ibm,set-eeh-option> invalid\n",
__func__);
return -EINVAL;
} else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n",
+ pr_warn("%s: RTAS service <ibm,set-slot-reset> invalid\n",
__func__);
return -EINVAL;
} else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and "
+ pr_warn("%s: RTAS service <ibm,read-slot-reset-state2> and "
"<ibm,read-slot-reset-state> invalid\n",
__func__);
return -EINVAL;
} else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",
+ pr_warn("%s: RTAS service <ibm,slot-error-detail> invalid\n",
__func__);
return -EINVAL;
} else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: RTAS service <ibm,configure-pe> and "
+ pr_warn("%s: RTAS service <ibm,configure-pe> and "
"<ibm,configure-bridge> invalid\n",
__func__);
return -EINVAL;
@@ -118,17 +118,17 @@ static int pseries_eeh_init(void)
spin_lock_init(&slot_errbuf_lock);
eeh_error_buf_size = rtas_token("rtas-error-log-max");
if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {
- pr_warning("%s: unknown EEH error log size\n",
+ pr_warn("%s: unknown EEH error log size\n",
__func__);
eeh_error_buf_size = 1024;
} else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
- pr_warning("%s: EEH error log size %d exceeds the maximal %d\n",
+ pr_warn("%s: EEH error log size %d exceeds the maximal %d\n",
__func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX);
eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
}
/* Set EEH probe mode */
- eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE);
+ eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG);
return 0;
}
@@ -270,7 +270,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
/* Retrieve the device address */
regs = of_get_property(dn, "reg", NULL);
if (!regs) {
- pr_warning("%s: OF node property %s::reg not found\n",
+ pr_warn("%s: OF node property %s::reg not found\n",
__func__, dn->full_name);
return NULL;
}
@@ -297,7 +297,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
enable = 1;
if (enable) {
- eeh_set_enable(true);
+ eeh_add_flag(EEH_ENABLED);
eeh_add_to_parent_pe(edev);
pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
@@ -398,7 +398,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe)
pe->config_addr, BUID_HI(pe->phb->buid),
BUID_LO(pe->phb->buid), 0);
if (ret) {
- pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+ pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
__func__, pe->phb->global_number, pe->config_addr);
return 0;
}
@@ -411,7 +411,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe)
pe->config_addr, BUID_HI(pe->phb->buid),
BUID_LO(pe->phb->buid), 0);
if (ret) {
- pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+ pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
__func__, pe->phb->global_number, pe->config_addr);
return 0;
}
@@ -584,17 +584,17 @@ static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait)
return ret;
if (max_wait <= 0) {
- pr_warning("%s: Timeout when getting PE's state (%d)\n",
+ pr_warn("%s: Timeout when getting PE's state (%d)\n",
__func__, max_wait);
return EEH_STATE_NOT_SUPPORT;
}
if (mwait <= 0) {
- pr_warning("%s: Firmware returned bad wait value %d\n",
+ pr_warn("%s: Firmware returned bad wait value %d\n",
__func__, mwait);
mwait = EEH_STATE_MIN_WAIT_TIME;
} else if (mwait > EEH_STATE_MAX_WAIT_TIME) {
- pr_warning("%s: Firmware returned too long wait value %d\n",
+ pr_warn("%s: Firmware returned too long wait value %d\n",
__func__, mwait);
mwait = EEH_STATE_MAX_WAIT_TIME;
}
@@ -675,7 +675,7 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
}
if (ret)
- pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+ pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
__func__, pe->phb->global_number, pe->addr, ret);
return ret;
@@ -743,10 +743,7 @@ static struct eeh_ops pseries_eeh_ops = {
*/
static int __init eeh_pseries_init(void)
{
- int ret = -EINVAL;
-
- if (!machine_is(pseries))
- return ret;
+ int ret;
ret = eeh_ops_register(&pseries_eeh_ops);
if (!ret)
@@ -757,5 +754,4 @@ static int __init eeh_pseries_init(void)
return ret;
}
-
-early_initcall(eeh_pseries_init);
+machine_early_initcall(pseries, eeh_pseries_init);
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 7995135170a3..c904583baf4b 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -146,7 +146,7 @@ static inline int pseries_remove_memblock(unsigned long base,
}
static inline int pseries_remove_mem_node(struct device_node *np)
{
- return -EOPNOTSUPP;
+ return 0;
}
#endif /* CONFIG_MEMORY_HOTREMOVE */
@@ -194,7 +194,7 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
if (!memblock_size)
return -EINVAL;
- p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
+ p = (u32 *) pr->old_prop->value;
if (!p)
return -EINVAL;
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index 99ecf0a5a929..3fda3f17b84e 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -12,9 +12,13 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
+#include <asm/jump_label.h>
+
+ .section ".text"
#ifdef CONFIG_TRACEPOINTS
+#ifndef CONFIG_JUMP_LABEL
.section ".toc","aw"
.globl hcall_tracepoint_refcount
@@ -22,21 +26,13 @@ hcall_tracepoint_refcount:
.llong 0
.section ".text"
+#endif
/*
* precall must preserve all registers. use unused STK_PARAM()
- * areas to save snapshots and opcode. We branch around this
- * in early init (eg when populating the MMU hashtable) by using an
- * unconditional cpu feature.
+ * areas to save snapshots and opcode.
*/
#define HCALL_INST_PRECALL(FIRST_REG) \
-BEGIN_FTR_SECTION; \
- b 1f; \
-END_FTR_SECTION(0, 1); \
- ld r12,hcall_tracepoint_refcount@toc(r2); \
- std r12,32(r1); \
- cmpdi r12,0; \
- beq+ 1f; \
mflr r0; \
std r3,STK_PARAM(R3)(r1); \
std r4,STK_PARAM(R4)(r1); \
@@ -50,45 +46,29 @@ END_FTR_SECTION(0, 1); \
addi r4,r1,STK_PARAM(FIRST_REG); \
stdu r1,-STACK_FRAME_OVERHEAD(r1); \
bl __trace_hcall_entry; \
- addi r1,r1,STACK_FRAME_OVERHEAD; \
- ld r0,16(r1); \
- ld r3,STK_PARAM(R3)(r1); \
- ld r4,STK_PARAM(R4)(r1); \
- ld r5,STK_PARAM(R5)(r1); \
- ld r6,STK_PARAM(R6)(r1); \
- ld r7,STK_PARAM(R7)(r1); \
- ld r8,STK_PARAM(R8)(r1); \
- ld r9,STK_PARAM(R9)(r1); \
- ld r10,STK_PARAM(R10)(r1); \
- mtlr r0; \
-1:
+ ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
+ ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \
+ ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \
+ ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \
+ ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \
+ ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \
+ ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \
+ ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
/*
* postcall is performed immediately before function return which
- * allows liberal use of volatile registers. We branch around this
- * in early init (eg when populating the MMU hashtable) by using an
- * unconditional cpu feature.
+ * allows liberal use of volatile registers.
*/
#define __HCALL_INST_POSTCALL \
-BEGIN_FTR_SECTION; \
- b 1f; \
-END_FTR_SECTION(0, 1); \
- ld r12,32(r1); \
- cmpdi r12,0; \
- beq+ 1f; \
- mflr r0; \
- ld r6,STK_PARAM(R3)(r1); \
- std r3,STK_PARAM(R3)(r1); \
+ ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
+ std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
mr r4,r3; \
- mr r3,r6; \
- std r0,16(r1); \
- stdu r1,-STACK_FRAME_OVERHEAD(r1); \
+ mr r3,r0; \
bl __trace_hcall_exit; \
+ ld r0,STACK_FRAME_OVERHEAD+16(r1); \
addi r1,r1,STACK_FRAME_OVERHEAD; \
- ld r0,16(r1); \
ld r3,STK_PARAM(R3)(r1); \
- mtlr r0; \
-1:
+ mtlr r0
#define HCALL_INST_POSTCALL_NORETS \
li r5,0; \
@@ -98,37 +78,62 @@ END_FTR_SECTION(0, 1); \
mr r5,BUFREG; \
__HCALL_INST_POSTCALL
+#ifdef CONFIG_JUMP_LABEL
+#define HCALL_BRANCH(LABEL) \
+ ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
+#else
+
+/*
+ * We branch around this in early init (eg when populating the MMU
+ * hashtable) by using an unconditional cpu feature.
+ */
+#define HCALL_BRANCH(LABEL) \
+BEGIN_FTR_SECTION; \
+ b 1f; \
+END_FTR_SECTION(0, 1); \
+ ld r12,hcall_tracepoint_refcount@toc(r2); \
+ std r12,32(r1); \
+ cmpdi r12,0; \
+ bne- LABEL; \
+1:
+#endif
+
#else
#define HCALL_INST_PRECALL(FIRST_ARG)
#define HCALL_INST_POSTCALL_NORETS
#define HCALL_INST_POSTCALL(BUFREG)
+#define HCALL_BRANCH(LABEL)
#endif
- .text
-
_GLOBAL_TOC(plpar_hcall_norets)
HMT_MEDIUM
mfcr r0
stw r0,8(r1)
-
- HCALL_INST_PRECALL(R4)
-
+ HCALL_BRANCH(plpar_hcall_norets_trace)
HVSC /* invoke the hypervisor */
- HCALL_INST_POSTCALL_NORETS
-
lwz r0,8(r1)
mtcrf 0xff,r0
blr /* return r3 = status */
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall_norets_trace:
+ HCALL_INST_PRECALL(R4)
+ HVSC
+ HCALL_INST_POSTCALL_NORETS
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+ blr
+#endif
+
_GLOBAL_TOC(plpar_hcall)
HMT_MEDIUM
mfcr r0
stw r0,8(r1)
- HCALL_INST_PRECALL(R5)
+ HCALL_BRANCH(plpar_hcall_trace)
std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
@@ -147,12 +152,40 @@ _GLOBAL_TOC(plpar_hcall)
std r6, 16(r12)
std r7, 24(r12)
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
+
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall_trace:
+ HCALL_INST_PRECALL(R5)
+
+ std r4,STK_PARAM(R4)(r1)
+ mr r0,r4
+
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
+
+ HVSC
+
+ ld r12,STK_PARAM(R4)(r1)
+ std r4,0(r12)
+ std r5,8(r12)
+ std r6,16(r12)
+ std r7,24(r12)
+
HCALL_INST_POSTCALL(r12)
lwz r0,8(r1)
mtcrf 0xff,r0
- blr /* return r3 = status */
+ blr
+#endif
/*
* plpar_hcall_raw can be called in real mode. kexec/kdump need some
@@ -194,7 +227,7 @@ _GLOBAL_TOC(plpar_hcall9)
mfcr r0
stw r0,8(r1)
- HCALL_INST_PRECALL(R5)
+ HCALL_BRANCH(plpar_hcall9_trace)
std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
@@ -222,12 +255,49 @@ _GLOBAL_TOC(plpar_hcall9)
std r11,56(r12)
std r0, 64(r12)
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+
+ blr /* return r3 = status */
+
+#ifdef CONFIG_TRACEPOINTS
+plpar_hcall9_trace:
+ HCALL_INST_PRECALL(R5)
+
+ std r4,STK_PARAM(R4)(r1)
+ mr r0,r4
+
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
+ ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
+ ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
+ ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
+
+ HVSC
+
+ mr r0,r12
+ ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
+ std r4,0(r12)
+ std r5,8(r12)
+ std r6,16(r12)
+ std r7,24(r12)
+ std r8,32(r12)
+ std r9,40(r12)
+ std r10,48(r12)
+ std r11,56(r12)
+ std r0,64(r12)
+
HCALL_INST_POSTCALL(r12)
lwz r0,8(r1)
mtcrf 0xff,r0
- blr /* return r3 = status */
+ blr
+#endif
/* See plpar_hcall_raw to see why this is needed */
_GLOBAL(plpar_hcall9_raw)
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index cf4e7736e4f1..4575f0c9e521 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -27,6 +27,7 @@
#include <asm/firmware.h>
#include <asm/cputable.h>
#include <asm/trace.h>
+#include <asm/machdep.h>
DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats);
@@ -162,4 +163,4 @@ static int __init hcall_inst_init(void)
return 0;
}
-__initcall(hcall_inst_init);
+machine_device_initcall(pseries, hcall_inst_init);
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 4557e91626c4..eedb64594dc5 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -163,8 +163,8 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
return retval;
}
- last_p_partition_ID = pi_buff[0];
- last_p_unit_address = pi_buff[1];
+ last_p_partition_ID = be64_to_cpu(pi_buff[0]);
+ last_p_unit_address = be64_to_cpu(pi_buff[1]);
/* This indicates that there are no further partners */
if (last_p_partition_ID == ~0UL
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 33b552ffbe57..4642d6a4d356 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -721,13 +721,13 @@ static int __init disable_ddw_setup(char *str)
early_param("disable_ddw", disable_ddw_setup);
-static void remove_ddw(struct device_node *np)
+static void remove_ddw(struct device_node *np, bool remove_prop)
{
struct dynamic_dma_window_prop *dwp;
struct property *win64;
const u32 *ddw_avail;
u64 liobn;
- int len, ret;
+ int len, ret = 0;
ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len);
win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
@@ -761,7 +761,8 @@ static void remove_ddw(struct device_node *np)
np->full_name, ret, ddw_avail[2], liobn);
delprop:
- ret = of_remove_property(np, win64);
+ if (remove_prop)
+ ret = of_remove_property(np, win64);
if (ret)
pr_warning("%s: failed to remove direct window property: %d\n",
np->full_name, ret);
@@ -805,7 +806,7 @@ static int find_existing_ddw_windows(void)
window = kzalloc(sizeof(*window), GFP_KERNEL);
if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
kfree(window);
- remove_ddw(pdn);
+ remove_ddw(pdn, true);
continue;
}
@@ -1045,7 +1046,7 @@ out_free_window:
kfree(window);
out_clear_window:
- remove_ddw(pdn);
+ remove_ddw(pdn, true);
out_free_prop:
kfree(win64->name);
@@ -1255,7 +1256,14 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
switch (action) {
case OF_RECONFIG_DETACH_NODE:
- remove_ddw(np);
+ /*
+ * Removing the property will invoke the reconfig
+ * notifier again, which causes dead-lock on the
+ * read-write semaphore of the notifier chain. So
+ * we have to remove the property when releasing
+ * the device node.
+ */
+ remove_ddw(np, false);
if (pci && pci->iommu_table)
iommu_free_table(pci->iommu_table, np->full_name);
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index b02af9ef3ff6..34e64237fff9 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -26,6 +26,7 @@
#include <linux/dma-mapping.h>
#include <linux/console.h>
#include <linux/export.h>
+#include <linux/static_key.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/page.h>
@@ -430,16 +431,17 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot,
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
}
-static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm,
- unsigned char *hpte_slot_array,
- unsigned long addr, int psize)
+static void pSeries_lpar_hugepage_invalidate(unsigned long vsid,
+ unsigned long addr,
+ unsigned char *hpte_slot_array,
+ int psize, int ssize)
{
- int ssize = 0, i, index = 0;
+ int i, index = 0;
unsigned long s_addr = addr;
unsigned int max_hpte_count, valid;
unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH];
unsigned long slot_array[PPC64_HUGE_HPTE_BATCH];
- unsigned long shift, hidx, vpn = 0, vsid, hash, slot;
+ unsigned long shift, hidx, vpn = 0, hash, slot;
shift = mmu_psize_defs[psize].shift;
max_hpte_count = 1U << (PMD_SHIFT - shift);
@@ -452,15 +454,6 @@ static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm,
/* get the vpn */
addr = s_addr + (i * (1ul << shift));
- if (!is_kernel_addr(addr)) {
- ssize = user_segment_size(addr);
- vsid = get_vsid(mm->context.id, addr, ssize);
- WARN_ON(vsid == 0);
- } else {
- vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
- ssize = mmu_kernel_ssize;
- }
-
vpn = hpt_vpn(addr, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
if (hidx & _PTEIDX_SECONDARY)
@@ -649,6 +642,19 @@ EXPORT_SYMBOL(arch_free_page);
#endif
#ifdef CONFIG_TRACEPOINTS
+#ifdef CONFIG_JUMP_LABEL
+struct static_key hcall_tracepoint_key = STATIC_KEY_INIT;
+
+void hcall_tracepoint_regfunc(void)
+{
+ static_key_slow_inc(&hcall_tracepoint_key);
+}
+
+void hcall_tracepoint_unregfunc(void)
+{
+ static_key_slow_dec(&hcall_tracepoint_key);
+}
+#else
/*
* We optimise our hcall path by placing hcall_tracepoint_refcount
* directly in the TOC so we can check if the hcall tracepoints are
@@ -658,13 +664,6 @@ EXPORT_SYMBOL(arch_free_page);
/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
extern long hcall_tracepoint_refcount;
-/*
- * Since the tracing code might execute hcalls we need to guard against
- * recursion. One example of this are spinlocks calling H_YIELD on
- * shared processor partitions.
- */
-static DEFINE_PER_CPU(unsigned int, hcall_trace_depth);
-
void hcall_tracepoint_regfunc(void)
{
hcall_tracepoint_refcount++;
@@ -674,6 +673,15 @@ void hcall_tracepoint_unregfunc(void)
{
hcall_tracepoint_refcount--;
}
+#endif
+
+/*
+ * Since the tracing code might execute hcalls we need to guard against
+ * recursion. One example of this are spinlocks calling H_YIELD on
+ * shared processor partitions.
+ */
+static DEFINE_PER_CPU(unsigned int, hcall_trace_depth);
+
void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
{
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index bde7ebad3949..e7cb6d4a871a 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
+#include <asm/machdep.h>
#include <asm/rtas.h>
#include "pseries.h"
@@ -319,7 +320,7 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr,
u64 streamid;
int rc;
- rc = strict_strtoull(buf, 0, &streamid);
+ rc = kstrtou64(buf, 0, &streamid);
if (rc)
return rc;
@@ -362,4 +363,4 @@ static int __init mobility_sysfs_init(void)
return rc;
}
-device_initcall(mobility_sysfs_init);
+machine_device_initcall(pseries, mobility_sysfs_init);
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 0c882e83c4ce..18ff4626d74e 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -16,6 +16,7 @@
#include <asm/rtas.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
+#include <asm/machdep.h>
static int query_token, change_token;
@@ -532,5 +533,4 @@ static int rtas_msi_init(void)
return 0;
}
-arch_initcall(rtas_msi_init);
-
+machine_arch_initcall(pseries, rtas_msi_init);
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 203cbf0dc101..89e23811199c 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_controller *phb)
}
}
- /* Unregister the bridge device from sysfs and remove the PCI bus */
- device_unregister(b->bridge);
+ /* Remove the PCI bus and unregister the bridge device from sysfs */
phb->bus = NULL;
pci_remove_bus(b);
+ device_unregister(b->bridge);
/* Now release the IO resource */
if (res->flags & IORESOURCE_IO)
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
index 6d6266236446..c26eadde434c 100644
--- a/arch/powerpc/platforms/pseries/power.c
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <asm/machdep.h>
unsigned long rtas_poweron_auto; /* default and normal state is 0 */
@@ -71,11 +72,11 @@ static int __init pm_init(void)
return -ENOMEM;
return sysfs_create_group(power_kobj, &attr_group);
}
-core_initcall(pm_init);
+machine_core_initcall(pseries, pm_init);
#else
static int __init apo_pm_init(void)
{
return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr));
}
-__initcall(apo_pm_init);
+machine_device_initcall(pseries, apo_pm_init);
#endif
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 9c5778e6ed4b..dff05b9eb946 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -71,7 +71,7 @@ static int __init init_ras_IRQ(void)
return 0;
}
-subsys_initcall(init_ras_IRQ);
+machine_subsys_initcall(pseries, init_ras_IRQ);
#define EPOW_SHUTDOWN_NORMAL 1
#define EPOW_SHUTDOWN_ON_UPS 2
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1c0a60d98867..0f319521e002 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -446,13 +446,10 @@ static int proc_ppc64_create_ofdt(void)
{
struct proc_dir_entry *ent;
- if (!machine_is(pseries))
- return 0;
-
ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops);
if (ent)
proc_set_size(ent, 0);
return 0;
}
-__initcall(proc_ppc64_create_ofdt);
+machine_device_initcall(pseries, proc_ppc64_create_ofdt);
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c
index 72a102758d4e..e09608770909 100644
--- a/arch/powerpc/platforms/pseries/rng.c
+++ b/arch/powerpc/platforms/pseries/rng.c
@@ -42,4 +42,4 @@ static __init int rng_init(void)
return 0;
}
-subsys_initcall(rng_init);
+machine_subsys_initcall(pseries, rng_init);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f2f40e64658f..e724d3186e73 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -232,8 +232,7 @@ static void __init pseries_discover_pic(void)
struct device_node *np;
const char *typep;
- for (np = NULL; (np = of_find_node_by_name(np,
- "interrupt-controller"));) {
+ for_each_node_by_name(np, "interrupt-controller") {
typep = of_get_property(np, "compatible", NULL);
if (strstr(typep, "open-pic")) {
pSeries_mpic_node = of_node_get(np);
@@ -351,7 +350,7 @@ static int alloc_dispatch_log_kmem_cache(void)
return alloc_dispatch_logs();
}
-early_initcall(alloc_dispatch_log_kmem_cache);
+machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache);
static void pseries_lpar_idle(void)
{
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
index b87b97849d4c..e76aefae2aa2 100644
--- a/arch/powerpc/platforms/pseries/suspend.c
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -265,7 +265,7 @@ static int __init pseries_suspend_init(void)
{
int rc;
- if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR))
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
return 0;
suspend_data.token = rtas_token("ibm,suspend-me");
@@ -280,5 +280,4 @@ static int __init pseries_suspend_init(void)
suspend_set_ops(&pseries_suspend_ops);
return 0;
}
-
-__initcall(pseries_suspend_init);
+machine_device_initcall(pseries, pseries_suspend_init);
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 4bd091a05583..c5077673bd94 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -853,8 +853,8 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
in = pcie->cfg_type0 + PEX_RC_INWIN_BASE;
for (i = 0; i < 4; i++) {
/* not enabled, skip */
- if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN)
- continue;
+ if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN))
+ continue;
if (get_immrbase() == in_le32(&in[i].tar))
return (u64)in_le32(&in[i].barh) << 32 |
diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c
index c0bb76ef7242..6727dc54d549 100644
--- a/arch/powerpc/sysdev/micropatch.c
+++ b/arch/powerpc/sysdev/micropatch.c
@@ -13,7 +13,6 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
-#include <asm/mpc8xx.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/8xx_immap.h>
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index 2c9b52aa266c..7bdf3cc741e4 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -184,7 +184,7 @@ static int mpic_msgr_probe(struct platform_device *dev)
dev_info(&dev->dev, "Found %d message registers\n",
mpic_msgr_count);
- mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
+ mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs),
GFP_KERNEL);
if (!mpic_msgrs) {
dev_err(&dev->dev,
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index d199bfa2f1fa..b988b5addf86 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/bug.h>
+#include <linux/nmi.h>
#include <asm/ptrace.h>
#include <asm/string.h>
@@ -374,6 +375,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
#endif
local_irq_save(flags);
+ hard_irq_disable();
bp = in_breakpoint_table(regs->nip, &offset);
if (bp != NULL) {
@@ -558,6 +560,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
#endif
insert_cpu_bpts();
+ touch_nmi_watchdog();
local_irq_restore(flags);
return cmd != 'X' && cmd != EOF;
@@ -2058,10 +2061,6 @@ static void dump_one_paca(int cpu)
DUMP(p, kernel_toc, "lx");
DUMP(p, kernelbase, "lx");
DUMP(p, kernel_msr, "lx");
-#ifdef CONFIG_PPC_STD_MMU_64
- DUMP(p, stab_real, "lx");
- DUMP(p, stab_addr, "lx");
-#endif
DUMP(p, emergency_sp, "p");
#ifdef CONFIG_PPC_BOOK3S_64
DUMP(p, mc_emergency_sp, "p");
@@ -2694,7 +2693,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
}
#ifdef CONFIG_PPC_BOOK3S_64
-static void dump_slb(void)
+void dump_segments(void)
{
int i;
unsigned long esid,vsid,valid;
@@ -2726,34 +2725,6 @@ static void dump_slb(void)
}
}
}
-
-static void dump_stab(void)
-{
- int i;
- unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
-
- printf("Segment table contents of cpu 0x%x\n", smp_processor_id());
-
- for (i = 0; i < PAGE_SIZE/16; i++) {
- unsigned long a, b;
-
- a = *tmp++;
- b = *tmp++;
-
- if (a || b) {
- printf("%03d %016lx ", i, a);
- printf("%016lx\n", b);
- }
- }
-}
-
-void dump_segments(void)
-{
- if (mmu_has_feature(MMU_FTR_SLB))
- dump_slb();
- else
- dump_stab();
-}
#endif
#ifdef CONFIG_PPC_STD_MMU_32
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index bb63499fc5d3..ab39ceb89ecf 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -48,6 +48,8 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
config KEXEC
def_bool y
+ select CRYPTO
+ select CRYPTO_SHA256
config AUDIT_ARCH
def_bool y
@@ -92,6 +94,7 @@ config S390
select ARCH_INLINE_WRITE_UNLOCK_IRQ
select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
select ARCH_SAVE_PAGE_KEYS if HIBERNATION
+ select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_EXTABLE_SORT
@@ -116,7 +119,6 @@ config S390
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP
@@ -137,7 +139,6 @@ config S390
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UID16 if 32BIT
select HAVE_VIRT_CPU_ACCOUNTING
- select KTIME_SCALAR if 32BIT
select MODULES_USE_ELF_RELA
select NO_BOOTMEM
select OLD_SIGACTION
@@ -146,6 +147,7 @@ config S390
select TTY
select VIRT_CPU_ACCOUNTING
select VIRT_TO_BUS
+ select ARCH_HAS_SG_CHAIN
config SCHED_OMIT_FRAME_POINTER
def_bool y
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
index fd09a10a2b53..3ca1894ade09 100644
--- a/arch/s390/configs/default_defconfig
+++ b/arch/s390/configs/default_defconfig
@@ -366,7 +366,6 @@ CONFIG_VIRTIO_BLK=y
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
@@ -380,7 +379,6 @@ CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_ISCSI_TCP=m
CONFIG_LIBFCOE=m
CONFIG_SCSI_DEBUG=m
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig
index b061180d3544..4830aa6e6f53 100644
--- a/arch/s390/configs/gcov_defconfig
+++ b/arch/s390/configs/gcov_defconfig
@@ -363,7 +363,6 @@ CONFIG_VIRTIO_BLK=y
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
@@ -377,7 +376,6 @@ CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_ISCSI_TCP=m
CONFIG_LIBFCOE=m
CONFIG_SCSI_DEBUG=m
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
index d279baa08014..61db449bf309 100644
--- a/arch/s390/configs/performance_defconfig
+++ b/arch/s390/configs/performance_defconfig
@@ -361,7 +361,6 @@ CONFIG_VIRTIO_BLK=y
CONFIG_ENCLOSURE_SERVICES=m
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=m
CONFIG_CHR_DEV_OSST=m
@@ -375,7 +374,6 @@ CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SPI_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
-CONFIG_SCSI_SRP_TGT_ATTRS=y
CONFIG_ISCSI_TCP=m
CONFIG_LIBFCOE=m
CONFIG_SCSI_DEBUG=m
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 57892a8a9055..b3fea0722ff1 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -4,4 +4,5 @@ generic-y += clkdev.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 4181d7baabba..773bef7614d8 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -305,7 +305,6 @@ struct kvm_s390_local_interrupt {
struct list_head list;
atomic_t active;
struct kvm_s390_float_interrupt *float_int;
- int timer_due; /* event indicator for waitqueue below */
wait_queue_head_t *wq;
atomic_t *cpuflags;
unsigned int action_bits;
@@ -367,7 +366,6 @@ struct kvm_vcpu_arch {
s390_fp_regs guest_fpregs;
struct kvm_s390_local_interrupt local_int;
struct hrtimer ckc_timer;
- struct tasklet_struct tasklet;
struct kvm_s390_pgm_info pgm;
union {
struct cpuid cpu_id;
@@ -418,6 +416,7 @@ struct kvm_arch{
int css_support;
int use_irqchip;
int use_cmma;
+ int user_cpu_state_ctrl;
struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
wait_queue_head_t ipte_wq;
spinlock_t start_stop_lock;
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 114258eeaacd..7b2ac6e44166 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -162,6 +162,4 @@ static inline int devmem_is_allowed(unsigned long pfn)
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
-#define __HAVE_ARCH_GATE_AREA 1
-
#endif /* _S390_PAGE_H */
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index fcba5e03839f..b76317c1f3eb 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -287,7 +287,14 @@ extern unsigned long MODULES_END;
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
#define _SEGMENT_ENTRY_COMMON 0x10 /* common segment bit */
#define _SEGMENT_ENTRY_PTL 0x0f /* page table length */
-#define _SEGMENT_ENTRY_NONE _SEGMENT_ENTRY_PROTECT
+
+#define _SEGMENT_ENTRY_DIRTY 0 /* No sw dirty bit for 31-bit */
+#define _SEGMENT_ENTRY_YOUNG 0 /* No sw young bit for 31-bit */
+#define _SEGMENT_ENTRY_READ 0 /* No sw read bit for 31-bit */
+#define _SEGMENT_ENTRY_WRITE 0 /* No sw write bit for 31-bit */
+#define _SEGMENT_ENTRY_LARGE 0 /* No large pages for 31-bit */
+#define _SEGMENT_ENTRY_BITS_LARGE 0
+#define _SEGMENT_ENTRY_ORIGIN_LARGE 0
#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PTL)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID)
@@ -350,7 +357,7 @@ extern unsigned long MODULES_END;
/* Bits in the segment table entry */
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL
-#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff1ff33UL
+#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address */
#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
#define _SEGMENT_ENTRY_PROTECT 0x200 /* page protection bit */
@@ -359,30 +366,34 @@ extern unsigned long MODULES_END;
#define _SEGMENT_ENTRY (0)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID)
-#define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */
-#define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */
-#define _SEGMENT_ENTRY_SPLIT 0x001 /* THP splitting bit */
-#define _SEGMENT_ENTRY_YOUNG 0x002 /* SW segment young bit */
-#define _SEGMENT_ENTRY_NONE _SEGMENT_ENTRY_YOUNG
+#define _SEGMENT_ENTRY_DIRTY 0x2000 /* SW segment dirty bit */
+#define _SEGMENT_ENTRY_YOUNG 0x1000 /* SW segment young bit */
+#define _SEGMENT_ENTRY_SPLIT 0x0800 /* THP splitting bit */
+#define _SEGMENT_ENTRY_LARGE 0x0400 /* STE-format control, large page */
+#define _SEGMENT_ENTRY_CO 0x0100 /* change-recording override */
+#define _SEGMENT_ENTRY_READ 0x0002 /* SW segment read bit */
+#define _SEGMENT_ENTRY_WRITE 0x0001 /* SW segment write bit */
/*
* Segment table entry encoding (R = read-only, I = invalid, y = young bit):
- * ..R...I...y.
- * prot-none, old ..0...1...1.
- * prot-none, young ..1...1...1.
- * read-only, old ..1...1...0.
- * read-only, young ..1...0...1.
- * read-write, old ..0...1...0.
- * read-write, young ..0...0...1.
+ * dy..R...I...wr
+ * prot-none, clean, old 00..1...1...00
+ * prot-none, clean, young 01..1...1...00
+ * prot-none, dirty, old 10..1...1...00
+ * prot-none, dirty, young 11..1...1...00
+ * read-only, clean, old 00..1...1...01
+ * read-only, clean, young 01..1...0...01
+ * read-only, dirty, old 10..1...1...01
+ * read-only, dirty, young 11..1...0...01
+ * read-write, clean, old 00..1...1...11
+ * read-write, clean, young 01..1...0...11
+ * read-write, dirty, old 10..0...1...11
+ * read-write, dirty, young 11..0...0...11
* The segment table origin is used to distinguish empty (origin==0) from
* read-write, old segment table entries (origin!=0)
*/
-#define _SEGMENT_ENTRY_SPLIT_BIT 0 /* THP splitting bit number */
-
-/* Set of bits not changed in pmd_modify */
-#define _SEGMENT_CHG_MASK (_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \
- | _SEGMENT_ENTRY_SPLIT | _SEGMENT_ENTRY_CO)
+#define _SEGMENT_ENTRY_SPLIT_BIT 11 /* THP splitting bit number */
/* Page status table bits for virtualization */
#define PGSTE_ACC_BITS 0xf000000000000000UL
@@ -455,10 +466,11 @@ extern unsigned long MODULES_END;
* Segment entry (large page) protection definitions.
*/
#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
- _SEGMENT_ENTRY_NONE)
-#define SEGMENT_READ __pgprot(_SEGMENT_ENTRY_INVALID | \
_SEGMENT_ENTRY_PROTECT)
-#define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_INVALID)
+#define SEGMENT_READ __pgprot(_SEGMENT_ENTRY_PROTECT | \
+ _SEGMENT_ENTRY_READ)
+#define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_READ | \
+ _SEGMENT_ENTRY_WRITE)
static inline int mm_has_pgste(struct mm_struct *mm)
{
@@ -569,25 +581,23 @@ static inline int pmd_none(pmd_t pmd)
static inline int pmd_large(pmd_t pmd)
{
-#ifdef CONFIG_64BIT
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
-#else
- return 0;
-#endif
}
-static inline int pmd_prot_none(pmd_t pmd)
+static inline int pmd_pfn(pmd_t pmd)
{
- return (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) &&
- (pmd_val(pmd) & _SEGMENT_ENTRY_NONE);
+ unsigned long origin_mask;
+
+ origin_mask = _SEGMENT_ENTRY_ORIGIN;
+ if (pmd_large(pmd))
+ origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE;
+ return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT;
}
static inline int pmd_bad(pmd_t pmd)
{
-#ifdef CONFIG_64BIT
if (pmd_large(pmd))
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
-#endif
return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
}
@@ -607,20 +617,22 @@ extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
#define __HAVE_ARCH_PMD_WRITE
static inline int pmd_write(pmd_t pmd)
{
- if (pmd_prot_none(pmd))
- return 0;
- return (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) == 0;
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0;
+}
+
+static inline int pmd_dirty(pmd_t pmd)
+{
+ int dirty = 1;
+ if (pmd_large(pmd))
+ dirty = (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
+ return dirty;
}
static inline int pmd_young(pmd_t pmd)
{
- int young = 0;
-#ifdef CONFIG_64BIT
- if (pmd_prot_none(pmd))
- young = (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) != 0;
- else
+ int young = 1;
+ if (pmd_large(pmd))
young = (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0;
-#endif
return young;
}
@@ -1391,7 +1403,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))
/* Find an entry in the lowest level page table.. */
#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
@@ -1413,41 +1425,75 @@ static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
return pgprot_val(SEGMENT_WRITE);
}
-static inline pmd_t pmd_mkyoung(pmd_t pmd)
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
{
-#ifdef CONFIG_64BIT
- if (pmd_prot_none(pmd)) {
+ pmd_val(pmd) &= ~_SEGMENT_ENTRY_WRITE;
+ pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+ return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+ pmd_val(pmd) |= _SEGMENT_ENTRY_WRITE;
+ if (pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
+ return pmd;
+ pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
+ return pmd;
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+ if (pmd_large(pmd)) {
+ pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY;
pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
- } else {
+ }
+ return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+ if (pmd_large(pmd)) {
+ pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY;
+ if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE)
+ pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
+ }
+ return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+ if (pmd_large(pmd)) {
pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
- pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID;
+ if (pmd_val(pmd) & _SEGMENT_ENTRY_READ)
+ pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID;
}
-#endif
return pmd;
}
static inline pmd_t pmd_mkold(pmd_t pmd)
{
-#ifdef CONFIG_64BIT
- if (pmd_prot_none(pmd)) {
- pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
- } else {
+ if (pmd_large(pmd)) {
pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG;
pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
}
-#endif
return pmd;
}
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
- int young;
-
- young = pmd_young(pmd);
- pmd_val(pmd) &= _SEGMENT_CHG_MASK;
+ if (pmd_large(pmd)) {
+ pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE |
+ _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG |
+ _SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SPLIT;
+ pmd_val(pmd) |= massage_pgprot_pmd(newprot);
+ if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY))
+ pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+ if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG))
+ pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
+ return pmd;
+ }
+ pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN;
pmd_val(pmd) |= massage_pgprot_pmd(newprot);
- if (young)
- pmd = pmd_mkyoung(pmd);
return pmd;
}
@@ -1455,16 +1501,9 @@ static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
{
pmd_t __pmd;
pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
- return pmd_mkyoung(__pmd);
+ return __pmd;
}
-static inline pmd_t pmd_mkwrite(pmd_t pmd)
-{
- /* Do not clobber PROT_NONE segments! */
- if (!pmd_prot_none(pmd))
- pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT;
- return pmd;
-}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */
static inline void __pmdp_csp(pmd_t *pmdp)
@@ -1555,34 +1594,21 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
static inline int pmd_trans_splitting(pmd_t pmd)
{
- return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) &&
+ (pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT);
}
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t entry)
{
- if (!(pmd_val(entry) & _SEGMENT_ENTRY_INVALID) && MACHINE_HAS_EDAT1)
- pmd_val(entry) |= _SEGMENT_ENTRY_CO;
*pmdp = entry;
}
static inline pmd_t pmd_mkhuge(pmd_t pmd)
{
pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
- return pmd;
-}
-
-static inline pmd_t pmd_wrprotect(pmd_t pmd)
-{
- /* Do not clobber PROT_NONE segments! */
- if (!pmd_prot_none(pmd))
- pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
- return pmd;
-}
-
-static inline pmd_t pmd_mkdirty(pmd_t pmd)
-{
- /* No dirty bit in the segment table entry. */
+ pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
+ pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
return pmd;
}
@@ -1647,11 +1673,6 @@ static inline int has_transparent_hugepage(void)
{
return MACHINE_HAS_HPAGE ? 1 : 0;
}
-
-static inline unsigned long pmd_pfn(pmd_t pmd)
-{
- return pmd_val(pmd) >> PAGE_SHIFT;
-}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
/*
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 6f02d452bbee..e568fc8a7250 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -217,7 +217,7 @@ static inline void cpu_relax(void)
barrier();
}
-#define arch_mutex_cpu_relax() barrier()
+#define cpu_relax_lowlatency() barrier()
static inline void psw_set_key(unsigned int key)
{
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index d786c634e052..06f3034605a1 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -415,6 +415,10 @@ struct qdio_brinfo_entry_l2 {
#define QDIO_FLAG_SYNC_OUTPUT 0x02
#define QDIO_FLAG_PCI_OUT 0x10
+int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count);
+void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count);
+void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count);
+
extern int qdio_allocate(struct qdio_initialize *);
extern int qdio_establish(struct qdio_initialize *);
extern int qdio_activate(struct ccw_device *);
diff --git a/arch/s390/include/asm/scatterlist.h b/arch/s390/include/asm/scatterlist.h
deleted file mode 100644
index 6d45ef6c12a7..000000000000
--- a/arch/s390/include/asm/scatterlist.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index abad78d5b10c..5bc12598ae9e 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -54,7 +54,7 @@ static inline void syscall_set_return_value(struct task_struct *task,
struct pt_regs *regs,
int error, long val)
{
- regs->gprs[2] = error ? -error : val;
+ regs->gprs[2] = error ? error : val;
}
static inline void syscall_get_arguments(struct task_struct *task,
diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild
index 736637363d31..08fe6dad9026 100644
--- a/arch/s390/include/uapi/asm/Kbuild
+++ b/arch/s390/include/uapi/asm/Kbuild
@@ -16,6 +16,7 @@ header-y += ioctls.h
header-y += ipcbuf.h
header-y += kvm.h
header-y += kvm_para.h
+header-y += kvm_perf.h
header-y += kvm_virtio.h
header-y += mman.h
header-y += monwriter.h
diff --git a/arch/s390/include/uapi/asm/kvm_perf.h b/arch/s390/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..397282727e21
--- /dev/null
+++ b/arch/s390/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,25 @@
+/*
+ * Definitions for perf-kvm on s390
+ *
+ * Copyright 2014 IBM Corp.
+ * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.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 only)
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_KVM_PERF_S390_H
+#define __LINUX_KVM_PERF_S390_H
+
+#include <asm/sie.h>
+
+#define DECODE_STR_LEN 40
+
+#define VCPU_ID "id"
+
+#define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter"
+#define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit"
+#define KVM_EXIT_REASON "icptcode"
+
+#endif
diff --git a/arch/s390/include/uapi/asm/sie.h b/arch/s390/include/uapi/asm/sie.h
index 5d9cc19462c4..d4096fdfc6ab 100644
--- a/arch/s390/include/uapi/asm/sie.h
+++ b/arch/s390/include/uapi/asm/sie.h
@@ -108,6 +108,7 @@
exit_code_ipa0(0xB2, 0x17, "STETR"), \
exit_code_ipa0(0xB2, 0x18, "PC"), \
exit_code_ipa0(0xB2, 0x20, "SERVC"), \
+ exit_code_ipa0(0xB2, 0x21, "IPTE"), \
exit_code_ipa0(0xB2, 0x28, "PT"), \
exit_code_ipa0(0xB2, 0x29, "ISKE"), \
exit_code_ipa0(0xB2, 0x2a, "RRBE"), \
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index f204d6920368..598b0b42668b 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -320,38 +320,39 @@ static inline int map_signal(int sig)
return sig;
}
-static int setup_frame32(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
+static int setup_frame32(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
- sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
+ int sig = ksig->sig;
+ sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
if (frame == (void __user *) -1UL)
- goto give_sigsegv;
+ return -EFAULT;
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
- goto give_sigsegv;
+ return -EFAULT;
if (save_sigregs32(regs, &frame->sregs))
- goto give_sigsegv;
+ return -EFAULT;
if (save_sigregs_gprs_high(regs, frame->gprs_high))
- goto give_sigsegv;
+ return -EFAULT;
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
} else {
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 __force __user *)(frame->retcode)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
@@ -359,7 +360,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
regs->psw.mask = PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
- regs->psw.addr = (__force __u64) ka->sa.sa_handler;
+ regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (__force __u64) &frame->sc;
@@ -376,25 +377,21 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
- goto give_sigsegv;
+ return -EFAULT;
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
int err = 0;
- rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
+ rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
if (frame == (void __user *) -1UL)
- goto give_sigsegv;
+ return -EFAULT;
- if (copy_siginfo_to_user32(&frame->info, info))
- goto give_sigsegv;
+ if (copy_siginfo_to_user32(&frame->info, &ksig->info))
+ return -EFAULT;
/* Create the ucontext. */
err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
@@ -404,22 +401,22 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= save_sigregs_gprs_high(regs, frame->gprs_high);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
} else {
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 __force __user *)(frame->retcode)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
@@ -427,36 +424,30 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->psw.mask = PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
- regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
+ regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;
- regs->gprs[2] = map_signal(sig);
+ regs->gprs[2] = map_signal(ksig->sig);
regs->gprs[3] = (__force __u64) &frame->info;
regs->gprs[4] = (__force __u64) &frame->uc;
regs->gprs[5] = task_thread_info(current)->last_break;
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
-void handle_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
+ struct pt_regs *regs)
{
int ret;
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame32(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame32(ksig, oldset, regs);
else
- ret = setup_frame32(sig, ka, oldset, regs);
- if (ret)
- return;
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLE_STEP));
+ ret = setup_frame32(ksig, oldset, regs);
+
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
}
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 6ac78192455f..1aad48398d06 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -48,8 +48,8 @@ void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit);
void kernel_stack_overflow(struct pt_regs * regs);
void do_signal(struct pt_regs *regs);
-void handle_signal32(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
+void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
+ struct pt_regs *regs);
void do_notify_resume(struct pt_regs *regs);
void __init init_IRQ(void);
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 99b0b09646ca..8eb82443cfbd 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -30,6 +30,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
struct irq_class {
+ int irq;
char *name;
char *desc;
};
@@ -45,9 +46,9 @@ struct irq_class {
* up with having a sum which accounts each interrupt twice.
*/
static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
- [EXT_INTERRUPT] = {.name = "EXT"},
- [IO_INTERRUPT] = {.name = "I/O"},
- [THIN_INTERRUPT] = {.name = "AIO"},
+ {.irq = EXT_INTERRUPT, .name = "EXT"},
+ {.irq = IO_INTERRUPT, .name = "I/O"},
+ {.irq = THIN_INTERRUPT, .name = "AIO"},
};
/*
@@ -56,38 +57,38 @@ static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
* In addition this list contains non external / I/O events like NMIs.
*/
static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
- [IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
- [IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
- [IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
- [IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
- [IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
- [IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
- [IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
- [IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
- [IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
- [IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
- [IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
- [IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
- [IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
- [IRQIO_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
- [IRQIO_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
- [IRQIO_DAS] = {.name = "DAS", .desc = "[I/O] DASD"},
- [IRQIO_C15] = {.name = "C15", .desc = "[I/O] 3215"},
- [IRQIO_C70] = {.name = "C70", .desc = "[I/O] 3270"},
- [IRQIO_TAP] = {.name = "TAP", .desc = "[I/O] Tape"},
- [IRQIO_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
- [IRQIO_LCS] = {.name = "LCS", .desc = "[I/O] LCS"},
- [IRQIO_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"},
- [IRQIO_CTC] = {.name = "CTC", .desc = "[I/O] CTC"},
- [IRQIO_APB] = {.name = "APB", .desc = "[I/O] AP Bus"},
- [IRQIO_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
- [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
- [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
- [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
- [IRQIO_VIR] = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
- [IRQIO_VAI] = {.name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
- [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"},
- [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"},
+ {.irq = IRQEXT_CLK, .name = "CLK", .desc = "[EXT] Clock Comparator"},
+ {.irq = IRQEXT_EXC, .name = "EXC", .desc = "[EXT] External Call"},
+ {.irq = IRQEXT_EMS, .name = "EMS", .desc = "[EXT] Emergency Signal"},
+ {.irq = IRQEXT_TMR, .name = "TMR", .desc = "[EXT] CPU Timer"},
+ {.irq = IRQEXT_TLA, .name = "TAL", .desc = "[EXT] Timing Alert"},
+ {.irq = IRQEXT_PFL, .name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
+ {.irq = IRQEXT_DSD, .name = "DSD", .desc = "[EXT] DASD Diag"},
+ {.irq = IRQEXT_VRT, .name = "VRT", .desc = "[EXT] Virtio"},
+ {.irq = IRQEXT_SCP, .name = "SCP", .desc = "[EXT] Service Call"},
+ {.irq = IRQEXT_IUC, .name = "IUC", .desc = "[EXT] IUCV"},
+ {.irq = IRQEXT_CMS, .name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
+ {.irq = IRQEXT_CMC, .name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
+ {.irq = IRQEXT_CMR, .name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+ {.irq = IRQIO_CIO, .name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
+ {.irq = IRQIO_QAI, .name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
+ {.irq = IRQIO_DAS, .name = "DAS", .desc = "[I/O] DASD"},
+ {.irq = IRQIO_C15, .name = "C15", .desc = "[I/O] 3215"},
+ {.irq = IRQIO_C70, .name = "C70", .desc = "[I/O] 3270"},
+ {.irq = IRQIO_TAP, .name = "TAP", .desc = "[I/O] Tape"},
+ {.irq = IRQIO_VMR, .name = "VMR", .desc = "[I/O] Unit Record Devices"},
+ {.irq = IRQIO_LCS, .name = "LCS", .desc = "[I/O] LCS"},
+ {.irq = IRQIO_CLW, .name = "CLW", .desc = "[I/O] CLAW"},
+ {.irq = IRQIO_CTC, .name = "CTC", .desc = "[I/O] CTC"},
+ {.irq = IRQIO_APB, .name = "APB", .desc = "[I/O] AP Bus"},
+ {.irq = IRQIO_ADM, .name = "ADM", .desc = "[I/O] EADM Subchannel"},
+ {.irq = IRQIO_CSC, .name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+ {.irq = IRQIO_PCI, .name = "PCI", .desc = "[I/O] PCI Interrupt" },
+ {.irq = IRQIO_MSI, .name = "MSI", .desc = "[I/O] MSI Interrupt" },
+ {.irq = IRQIO_VIR, .name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
+ {.irq = IRQIO_VAI, .name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
+ {.irq = NMI_NMI, .name = "NMI", .desc = "[NMI] Machine Check"},
+ {.irq = CPU_RST, .name = "RST", .desc = "[CPU] CPU Restart"},
};
void __init init_IRQ(void)
@@ -116,33 +117,37 @@ void do_IRQ(struct pt_regs *regs, int irq)
*/
int show_interrupts(struct seq_file *p, void *v)
{
- int irq = *(loff_t *) v;
- int cpu;
+ int index = *(loff_t *) v;
+ int cpu, irq;
get_online_cpus();
- if (irq == 0) {
+ if (index == 0) {
seq_puts(p, " ");
for_each_online_cpu(cpu)
seq_printf(p, "CPU%d ", cpu);
seq_putc(p, '\n');
goto out;
}
- if (irq < NR_IRQS) {
- if (irq >= NR_IRQS_BASE)
+ if (index < NR_IRQS) {
+ if (index >= NR_IRQS_BASE)
goto out;
- seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
+ /* Adjust index to process irqclass_main_desc array entries */
+ index--;
+ seq_printf(p, "%s: ", irqclass_main_desc[index].name);
+ irq = irqclass_main_desc[index].irq;
for_each_online_cpu(cpu)
seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
seq_putc(p, '\n');
goto out;
}
- for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
- seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
+ for (index = 0; index < NR_ARCH_IRQS; index++) {
+ seq_printf(p, "%s: ", irqclass_sub_desc[index].name);
+ irq = irqclass_sub_desc[index].irq;
for_each_online_cpu(cpu)
seq_printf(p, "%10u ",
per_cpu(irq_stat, cpu).irqs[irq]);
- if (irqclass_sub_desc[irq].desc)
- seq_printf(p, " %s", irqclass_sub_desc[irq].desc);
+ if (irqclass_sub_desc[index].desc)
+ seq_printf(p, " %s", irqclass_sub_desc[index].desc);
seq_putc(p, '\n');
}
out:
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 08dcf21cb8df..433c6dbfa442 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -21,13 +21,9 @@ ENTRY(_mcount)
ENTRY(ftrace_caller)
#endif
stm %r2,%r5,16(%r15)
- bras %r1,2f
+ bras %r1,1f
0: .long ftrace_trace_function
-1: .long function_trace_stop
-2: l %r2,1b-0b(%r1)
- icm %r2,0xf,0(%r2)
- jnz 3f
- st %r14,56(%r15)
+1: st %r14,56(%r15)
lr %r0,%r15
ahi %r15,-96
l %r3,100(%r15)
@@ -50,7 +46,7 @@ ENTRY(ftrace_graph_caller)
#endif
ahi %r15,96
l %r14,56(%r15)
-3: lm %r2,%r5,16(%r15)
+ lm %r2,%r5,16(%r15)
br %r14
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/arch/s390/kernel/mcount64.S b/arch/s390/kernel/mcount64.S
index 1c52eae3396a..c67a8bf0fd9a 100644
--- a/arch/s390/kernel/mcount64.S
+++ b/arch/s390/kernel/mcount64.S
@@ -20,9 +20,6 @@ ENTRY(_mcount)
ENTRY(ftrace_caller)
#endif
- larl %r1,function_trace_stop
- icm %r1,0xf,0(%r1)
- bnzr %r14
stmg %r2,%r5,32(%r15)
stg %r14,112(%r15)
lgr %r1,%r15
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index ea75d011a6fc..d3194de7ae1e 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -411,12 +411,6 @@ static int cpumf_pmu_event_init(struct perf_event *event)
case PERF_TYPE_HARDWARE:
case PERF_TYPE_HW_CACHE:
case PERF_TYPE_RAW:
- /* The CPU measurement counter facility does not have overflow
- * interrupts to do sampling. Sampling must be provided by
- * external means, for example, by timers.
- */
- if (is_sampling_event(event))
- return -ENOENT;
err = __hw_perf_event_init(event);
break;
default:
@@ -681,6 +675,12 @@ static int __init cpumf_pmu_init(void)
goto out;
}
+ /* The CPU measurement counter facility does not have overflow
+ * interrupts to do sampling. Sampling must be provided by
+ * external means, for example, by timers.
+ */
+ cpumf_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
cpumf_pmu.attr_groups = cpumf_cf_event_group();
rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
if (rc) {
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 1e2264b46e4c..ae1d5be7dd88 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -501,6 +501,8 @@ static int kdump_mem_notifier(struct notifier_block *nb,
{
struct memory_notify *arg = data;
+ if (action != MEM_GOING_OFFLINE)
+ return NOTIFY_OK;
if (arg->start_pfn < PFN_DOWN(resource_size(&crashk_res)))
return NOTIFY_BAD;
if (arg->start_pfn > PFN_DOWN(crashk_res.end))
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 42b49f9e19bf..469c4c6d9182 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
frame = get_sigframe(ka, regs, sizeof(sigframe));
if (frame == (void __user *) -1UL)
- goto give_sigsegv;
+ return -EFAULT;
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
- goto give_sigsegv;
+ return -EFAULT;
if (save_sigregs(regs, &frame->sregs))
- goto give_sigsegv;
+ return -EFAULT;
if (__put_user(&frame->sregs, &frame->sc.sregs))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka,
frame->retcode | PSW_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 __user *)(frame->retcode)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t __user *) frame))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
- goto give_sigsegv;
+ return -EFAULT;
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
int err = 0;
rt_sigframe __user *frame;
- frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
+ frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
if (frame == (void __user *) -1UL)
- goto give_sigsegv;
+ return -EFAULT;
- if (copy_siginfo_to_user(&frame->info, info))
- goto give_sigsegv;
+ if (copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= save_sigregs(regs, &frame->uc.uc_mcontext);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = (unsigned long)
- ka->sa.sa_restorer | PSW_ADDR_AMODE;
+ ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
} else {
regs->gprs[14] = (unsigned long)
frame->retcode | PSW_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 __user *)(frame->retcode)))
- goto give_sigsegv;
+ return -EFAULT;
}
/* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t __user *) frame))
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
- regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
+ regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE;
- regs->gprs[2] = map_signal(sig);
+ regs->gprs[2] = map_signal(ksig->sig);
regs->gprs[3] = (unsigned long) &frame->info;
regs->gprs[4] = (unsigned long) &frame->uc;
regs->gprs[5] = task_thread_info(current)->last_break;
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *oldset,
- struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, sigset_t *oldset,
+ struct pt_regs *regs)
{
int ret;
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
- if (ret)
- return;
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLE_STEP));
+ ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs);
+
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
}
/*
@@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
sigset_t *oldset = sigmask_to_save();
/*
@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs)
*/
current_thread_info()->system_call =
test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
if (current_thread_info()->system_call) {
regs->int_code = current_thread_info()->system_call;
@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs)
regs->gprs[2] = -EINTR;
break;
case -ERESTARTSYS:
- if (!(ka.sa.sa_flags & SA_RESTART)) {
+ if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->gprs[2] = -EINTR;
break;
}
@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs)
clear_pt_regs_flag(regs, PIF_SYSCALL);
if (is_compat_task())
- handle_signal32(signr, &ka, &info, oldset, regs);
+ handle_signal32(&ksig, oldset, regs);
else
- handle_signal(signr, &ka, &info, oldset, regs);
+ handle_signal(&ksig, oldset, regs);
return;
}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 0931b110c826..4cef607f3711 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -214,26 +214,26 @@ void update_vsyscall(struct timekeeper *tk)
{
u64 nsecps;
- if (tk->clock != &clocksource_tod)
+ if (tk->tkr.clock != &clocksource_tod)
return;
/* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count;
smp_wmb();
- vdso_data->xtime_tod_stamp = tk->clock->cycle_last;
+ vdso_data->xtime_tod_stamp = tk->tkr.cycle_last;
vdso_data->xtime_clock_sec = tk->xtime_sec;
- vdso_data->xtime_clock_nsec = tk->xtime_nsec;
+ vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
vdso_data->wtom_clock_sec =
tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
- vdso_data->wtom_clock_nsec = tk->xtime_nsec +
- + ((u64) tk->wall_to_monotonic.tv_nsec << tk->shift);
- nsecps = (u64) NSEC_PER_SEC << tk->shift;
+ vdso_data->wtom_clock_nsec = tk->tkr.xtime_nsec +
+ + ((u64) tk->wall_to_monotonic.tv_nsec << tk->tkr.shift);
+ nsecps = (u64) NSEC_PER_SEC << tk->tkr.shift;
while (vdso_data->wtom_clock_nsec >= nsecps) {
vdso_data->wtom_clock_nsec -= nsecps;
vdso_data->wtom_clock_sec++;
}
- vdso_data->tk_mult = tk->mult;
- vdso_data->tk_shift = tk->shift;
+ vdso_data->tk_mult = tk->tkr.mult;
+ vdso_data->tk_shift = tk->tkr.shift;
smp_wmb();
++vdso_data->tb_update_count;
}
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 613649096783..0bbb7e027c5a 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -316,18 +316,3 @@ static int __init vdso_init(void)
return 0;
}
early_initcall(vdso_init);
-
-int in_gate_area_no_mm(unsigned long addr)
-{
- return 0;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
- return 0;
-}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 10d529ac9821..646db9c467d1 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -26,6 +26,7 @@ config KVM
select KVM_ASYNC_PF
select KVM_ASYNC_PF_SYNC
select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
select HAVE_KVM_IRQ_ROUTING
---help---
Support hosting paravirtualized guest machines using the SIE
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 0161675878a2..59bd8f991b98 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -176,7 +176,8 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
return -EOPNOTSUPP;
}
- kvm_s390_vcpu_stop(vcpu);
+ if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+ kvm_s390_vcpu_stop(vcpu);
vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index a0b586c1913c..eaf46291d361 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -56,32 +56,26 @@ static int handle_noop(struct kvm_vcpu *vcpu)
static int handle_stop(struct kvm_vcpu *vcpu)
{
int rc = 0;
+ unsigned int action_bits;
vcpu->stat.exit_stop_request++;
- spin_lock_bh(&vcpu->arch.local_int.lock);
-
trace_kvm_s390_stop_request(vcpu->arch.local_int.action_bits);
- if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
- kvm_s390_vcpu_stop(vcpu);
- vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
- VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
- rc = -EOPNOTSUPP;
- }
+ action_bits = vcpu->arch.local_int.action_bits;
- if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
- vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
- /* store status must be called unlocked. Since local_int.lock
- * only protects local_int.* and not guest memory we can give
- * up the lock here */
- spin_unlock_bh(&vcpu->arch.local_int.lock);
+ if (!(action_bits & ACTION_STOP_ON_STOP))
+ return 0;
+
+ if (action_bits & ACTION_STORE_ON_STOP) {
rc = kvm_s390_vcpu_store_status(vcpu,
KVM_S390_STORE_STATUS_NOADDR);
- if (rc >= 0)
- rc = -EOPNOTSUPP;
- } else
- spin_unlock_bh(&vcpu->arch.local_int.lock);
- return rc;
+ if (rc)
+ return rc;
+ }
+
+ if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+ kvm_s390_vcpu_stop(vcpu);
+ return -EOPNOTSUPP;
}
static int handle_validity(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 90c8de22a2a0..f4c819bfc193 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -158,6 +158,9 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
LCTL_CR10 | LCTL_CR11);
vcpu->arch.sie_block->ictl |= (ICTL_STCTL | ICTL_PINT);
}
+
+ if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP)
+ atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
}
static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
@@ -544,13 +547,13 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
int rc = 0;
if (atomic_read(&li->active)) {
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_for_each_entry(inti, &li->list, list)
if (__interrupt_is_deliverable(vcpu, inti)) {
rc = 1;
break;
}
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
}
if ((!rc) && atomic_read(&fi->active)) {
@@ -585,88 +588,56 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
{
u64 now, sltime;
- DECLARE_WAITQUEUE(wait, current);
vcpu->stat.exit_wait_state++;
- if (kvm_cpu_has_interrupt(vcpu))
- return 0;
- __set_cpu_idle(vcpu);
- spin_lock_bh(&vcpu->arch.local_int.lock);
- vcpu->arch.local_int.timer_due = 0;
- spin_unlock_bh(&vcpu->arch.local_int.lock);
+ /* fast path */
+ if (kvm_cpu_has_pending_timer(vcpu) || kvm_arch_vcpu_runnable(vcpu))
+ return 0;
if (psw_interrupts_disabled(vcpu)) {
VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
- __unset_cpu_idle(vcpu);
return -EOPNOTSUPP; /* disabled wait */
}
+ __set_cpu_idle(vcpu);
if (!ckc_interrupts_enabled(vcpu)) {
VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
goto no_timer;
}
now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
- if (vcpu->arch.sie_block->ckc < now) {
- __unset_cpu_idle(vcpu);
- return 0;
- }
-
sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
-
hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
no_timer:
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
- spin_lock(&vcpu->arch.local_int.float_int->lock);
- spin_lock_bh(&vcpu->arch.local_int.lock);
- add_wait_queue(&vcpu->wq, &wait);
- while (list_empty(&vcpu->arch.local_int.list) &&
- list_empty(&vcpu->arch.local_int.float_int->list) &&
- (!vcpu->arch.local_int.timer_due) &&
- !signal_pending(current) &&
- !kvm_s390_si_ext_call_pending(vcpu)) {
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_bh(&vcpu->arch.local_int.lock);
- spin_unlock(&vcpu->arch.local_int.float_int->lock);
- schedule();
- spin_lock(&vcpu->arch.local_int.float_int->lock);
- spin_lock_bh(&vcpu->arch.local_int.lock);
- }
+ kvm_vcpu_block(vcpu);
__unset_cpu_idle(vcpu);
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&vcpu->wq, &wait);
- spin_unlock_bh(&vcpu->arch.local_int.lock);
- spin_unlock(&vcpu->arch.local_int.float_int->lock);
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
return 0;
}
-void kvm_s390_tasklet(unsigned long parm)
+void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
{
- struct kvm_vcpu *vcpu = (struct kvm_vcpu *) parm;
-
- spin_lock(&vcpu->arch.local_int.lock);
- vcpu->arch.local_int.timer_due = 1;
- if (waitqueue_active(&vcpu->wq))
+ if (waitqueue_active(&vcpu->wq)) {
+ /*
+ * The vcpu gave up the cpu voluntarily, mark it as a good
+ * yield-candidate.
+ */
+ vcpu->preempted = true;
wake_up_interruptible(&vcpu->wq);
- spin_unlock(&vcpu->arch.local_int.lock);
+ }
}
-/*
- * low level hrtimer wake routine. Because this runs in hardirq context
- * we schedule a tasklet to do the real work.
- */
enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
{
struct kvm_vcpu *vcpu;
vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
- vcpu->preempted = true;
- tasklet_schedule(&vcpu->arch.tasklet);
+ kvm_s390_vcpu_wakeup(vcpu);
return HRTIMER_NORESTART;
}
@@ -676,13 +647,13 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
struct kvm_s390_interrupt_info *n, *inti = NULL;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_for_each_entry_safe(inti, n, &li->list, list) {
list_del(&inti->list);
kfree(inti);
}
atomic_set(&li->active, 0);
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
/* clear pending external calls set by sigp interpretation facility */
atomic_clear_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags);
@@ -701,7 +672,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
if (atomic_read(&li->active)) {
do {
deliver = 0;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_for_each_entry_safe(inti, n, &li->list, list) {
if (__interrupt_is_deliverable(vcpu, inti)) {
list_del(&inti->list);
@@ -712,7 +683,7 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
}
if (list_empty(&li->list))
atomic_set(&li->active, 0);
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
if (deliver) {
__do_deliver_interrupt(vcpu, inti);
kfree(inti);
@@ -758,7 +729,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
if (atomic_read(&li->active)) {
do {
deliver = 0;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_for_each_entry_safe(inti, n, &li->list, list) {
if ((inti->type == KVM_S390_MCHK) &&
__interrupt_is_deliverable(vcpu, inti)) {
@@ -770,7 +741,7 @@ void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu)
}
if (list_empty(&li->list))
atomic_set(&li->active, 0);
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
if (deliver) {
__do_deliver_interrupt(vcpu, inti);
kfree(inti);
@@ -817,11 +788,11 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1);
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_add(&inti->list, &li->list);
atomic_set(&li->active, 1);
BUG_ON(waitqueue_active(li->wq));
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
return 0;
}
@@ -842,11 +813,11 @@ int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
inti->type = KVM_S390_PROGRAM_INT;
memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm));
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
list_add(&inti->list, &li->list);
atomic_set(&li->active, 1);
BUG_ON(waitqueue_active(li->wq));
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
return 0;
}
@@ -934,12 +905,10 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
}
dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
li = &dst_vcpu->arch.local_int;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
- if (waitqueue_active(li->wq))
- wake_up_interruptible(li->wq);
- kvm_get_vcpu(kvm, sigcpu)->preempted = true;
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
+ kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu));
unlock_fi:
spin_unlock(&fi->lock);
mutex_unlock(&kvm->lock);
@@ -1081,7 +1050,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
mutex_lock(&vcpu->kvm->lock);
li = &vcpu->arch.local_int;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
if (inti->type == KVM_S390_PROGRAM_INT)
list_add(&inti->list, &li->list);
else
@@ -1090,11 +1059,9 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
if (inti->type == KVM_S390_SIGP_STOP)
li->action_bits |= ACTION_STOP_ON_STOP;
atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
- if (waitqueue_active(&vcpu->wq))
- wake_up_interruptible(&vcpu->wq);
- vcpu->preempted = true;
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
mutex_unlock(&vcpu->kvm->lock);
+ kvm_s390_vcpu_wakeup(vcpu);
return 0;
}
@@ -1589,8 +1556,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
return ret;
}
-int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
- struct kvm_kernel_irq_routing_entry *e,
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
{
int ret;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2f3e14fe91a4..ce81eb2ab76a 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -146,7 +146,7 @@ long kvm_arch_dev_ioctl(struct file *filp,
return -EINVAL;
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
@@ -166,7 +166,9 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_IOEVENTFD:
case KVM_CAP_DEVICE_CTRL:
case KVM_CAP_ENABLE_CAP_VM:
+ case KVM_CAP_S390_IRQCHIP:
case KVM_CAP_VM_ATTRIBUTES:
+ case KVM_CAP_MP_STATE:
r = 1;
break;
case KVM_CAP_NR_VCPUS:
@@ -595,7 +597,8 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->pp = 0;
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
kvm_clear_async_pf_completion_queue(vcpu);
- kvm_s390_vcpu_stop(vcpu);
+ if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+ kvm_s390_vcpu_stop(vcpu);
kvm_s390_clear_local_irqs(vcpu);
}
@@ -647,8 +650,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
return rc;
}
hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
- tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
- (unsigned long) vcpu);
vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
get_cpu_id(&vcpu->arch.cpu_id);
vcpu->arch.cpu_id.version = 0xff;
@@ -926,7 +927,7 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
{
int rc = 0;
- if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
+ if (!is_vcpu_stopped(vcpu))
rc = -EBUSY;
else {
vcpu->run->psw_mask = psw.mask;
@@ -980,13 +981,34 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
struct kvm_mp_state *mp_state)
{
- return -EINVAL; /* not implemented yet */
+ /* CHECK_STOP and LOAD are not supported yet */
+ return is_vcpu_stopped(vcpu) ? KVM_MP_STATE_STOPPED :
+ KVM_MP_STATE_OPERATING;
}
int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
struct kvm_mp_state *mp_state)
{
- return -EINVAL; /* not implemented yet */
+ int rc = 0;
+
+ /* user space knows about this interface - let it control the state */
+ vcpu->kvm->arch.user_cpu_state_ctrl = 1;
+
+ switch (mp_state->mp_state) {
+ case KVM_MP_STATE_STOPPED:
+ kvm_s390_vcpu_stop(vcpu);
+ break;
+ case KVM_MP_STATE_OPERATING:
+ kvm_s390_vcpu_start(vcpu);
+ break;
+ case KVM_MP_STATE_LOAD:
+ case KVM_MP_STATE_CHECK_STOP:
+ /* fall through - CHECK_STOP and LOAD are not supported yet */
+ default:
+ rc = -ENXIO;
+ }
+
+ return rc;
}
bool kvm_s390_cmma_enabled(struct kvm *kvm)
@@ -1045,6 +1067,9 @@ retry:
goto retry;
}
+ /* nothing to do, just clear the request */
+ clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+
return 0;
}
@@ -1284,7 +1309,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
- kvm_s390_vcpu_start(vcpu);
+ if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) {
+ kvm_s390_vcpu_start(vcpu);
+ } else if (is_vcpu_stopped(vcpu)) {
+ pr_err_ratelimited("kvm-s390: can't run stopped vcpu %d\n",
+ vcpu->vcpu_id);
+ return -EINVAL;
+ }
switch (kvm_run->exit_reason) {
case KVM_EXIT_S390_SIEIC:
@@ -1413,11 +1444,6 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
return kvm_s390_store_status_unloaded(vcpu, addr);
}
-static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
-{
- return atomic_read(&(vcpu)->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
-}
-
static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
{
kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);
@@ -1451,7 +1477,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1);
/* Only one cpu at a time may enter/leave the STOPPED state. */
- spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
+ spin_lock(&vcpu->kvm->arch.start_stop_lock);
online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
for (i = 0; i < online_vcpus; i++) {
@@ -1477,7 +1503,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
* Let's play safe and flush the VCPU at startup.
*/
vcpu->arch.sie_block->ihcpu = 0xffff;
- spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
+ spin_unlock(&vcpu->kvm->arch.start_stop_lock);
return;
}
@@ -1491,10 +1517,18 @@ void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0);
/* Only one cpu at a time may enter/leave the STOPPED state. */
- spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
+ spin_lock(&vcpu->kvm->arch.start_stop_lock);
online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
+ /* Need to lock access to action_bits to avoid a SIGP race condition */
+ spin_lock(&vcpu->arch.local_int.lock);
atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
+
+ /* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */
+ vcpu->arch.local_int.action_bits &=
+ ~(ACTION_STOP_ON_STOP | ACTION_STORE_ON_STOP);
+ spin_unlock(&vcpu->arch.local_int.lock);
+
__disable_ibs_on_vcpu(vcpu);
for (i = 0; i < online_vcpus; i++) {
@@ -1512,7 +1546,7 @@ void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
__enable_ibs_on_vcpu(started_vcpu);
}
- spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
+ spin_unlock(&vcpu->kvm->arch.start_stop_lock);
return;
}
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index a8655ed31616..3862fa2cefe0 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -45,9 +45,9 @@ do { \
d_args); \
} while (0)
-static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
+static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
{
- return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
+ return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
}
static inline int kvm_is_ucontrol(struct kvm *kvm)
@@ -129,9 +129,15 @@ static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
vcpu->arch.sie_block->gpsw.mask |= cc << 44;
}
+/* are cpu states controlled by user space */
+static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
+{
+ return kvm->arch.user_cpu_state_ctrl != 0;
+}
+
int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
+void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);
enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
-void kvm_s390_tasklet(unsigned long parm);
void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu);
void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 43079a48cc98..cf243ba3d50f 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -125,8 +125,9 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr)
return rc ? rc : SIGP_CC_ORDER_CODE_ACCEPTED;
}
-static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
+static int __inject_sigp_stop(struct kvm_vcpu *dst_vcpu, int action)
{
+ struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int;
struct kvm_s390_interrupt_info *inti;
int rc = SIGP_CC_ORDER_CODE_ACCEPTED;
@@ -135,7 +136,13 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
return -ENOMEM;
inti->type = KVM_S390_SIGP_STOP;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
+ if (li->action_bits & ACTION_STOP_ON_STOP) {
+ /* another SIGP STOP is pending */
+ kfree(inti);
+ rc = SIGP_CC_BUSY;
+ goto out;
+ }
if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
kfree(inti);
if ((action & ACTION_STORE_ON_STOP) != 0)
@@ -144,19 +151,17 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action)
}
list_add_tail(&inti->list, &li->list);
atomic_set(&li->active, 1);
- atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
li->action_bits |= action;
- if (waitqueue_active(li->wq))
- wake_up_interruptible(li->wq);
+ atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
+ kvm_s390_vcpu_wakeup(dst_vcpu);
out:
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
return rc;
}
static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
{
- struct kvm_s390_local_interrupt *li;
struct kvm_vcpu *dst_vcpu = NULL;
int rc;
@@ -166,9 +171,8 @@ static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action)
dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
if (!dst_vcpu)
return SIGP_CC_NOT_OPERATIONAL;
- li = &dst_vcpu->arch.local_int;
- rc = __inject_sigp_stop(li, action);
+ rc = __inject_sigp_stop(dst_vcpu, action);
VCPU_EVENT(vcpu, 4, "sent sigp stop to cpu %x", cpu_addr);
@@ -238,7 +242,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
if (!inti)
return SIGP_CC_BUSY;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
/* cpu must be in stopped state */
if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
*reg &= 0xffffffff00000000UL;
@@ -253,13 +257,12 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
list_add_tail(&inti->list, &li->list);
atomic_set(&li->active, 1);
- if (waitqueue_active(li->wq))
- wake_up_interruptible(li->wq);
+ kvm_s390_vcpu_wakeup(dst_vcpu);
rc = SIGP_CC_ORDER_CODE_ACCEPTED;
VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address);
out_li:
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
return rc;
}
@@ -275,9 +278,9 @@ static int __sigp_store_status_at_addr(struct kvm_vcpu *vcpu, u16 cpu_id,
if (!dst_vcpu)
return SIGP_CC_NOT_OPERATIONAL;
- spin_lock_bh(&dst_vcpu->arch.local_int.lock);
+ spin_lock(&dst_vcpu->arch.local_int.lock);
flags = atomic_read(dst_vcpu->arch.local_int.cpuflags);
- spin_unlock_bh(&dst_vcpu->arch.local_int.lock);
+ spin_unlock(&dst_vcpu->arch.local_int.lock);
if (!(flags & CPUSTAT_STOPPED)) {
*reg &= 0xffffffff00000000UL;
*reg |= SIGP_STATUS_INCORRECT_STATE;
@@ -338,10 +341,10 @@ static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr)
if (!dst_vcpu)
return SIGP_CC_NOT_OPERATIONAL;
li = &dst_vcpu->arch.local_int;
- spin_lock_bh(&li->lock);
+ spin_lock(&li->lock);
if (li->action_bits & ACTION_STOP_ON_STOP)
rc = SIGP_CC_BUSY;
- spin_unlock_bh(&li->lock);
+ spin_unlock(&li->lock);
return rc;
}
@@ -461,12 +464,7 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu)
dest_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
BUG_ON(dest_vcpu == NULL);
- spin_lock_bh(&dest_vcpu->arch.local_int.lock);
- if (waitqueue_active(&dest_vcpu->wq))
- wake_up_interruptible(&dest_vcpu->wq);
- dest_vcpu->preempted = true;
- spin_unlock_bh(&dest_vcpu->arch.local_int.lock);
-
+ kvm_s390_vcpu_wakeup(dest_vcpu);
kvm_s390_set_psw_cc(vcpu, SIGP_CC_ORDER_CODE_ACCEPTED);
return 0;
}
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 0ff66a7e29bb..389bc17934b7 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -10,42 +10,33 @@
static inline pmd_t __pte_to_pmd(pte_t pte)
{
- int none, young, prot;
pmd_t pmd;
/*
- * Convert encoding pte bits pmd bits
- * .IR...wrdytp ..R...I...y.
- * empty .10...000000 -> ..0...1...0.
- * prot-none, clean, old .11...000001 -> ..0...1...1.
- * prot-none, clean, young .11...000101 -> ..1...1...1.
- * prot-none, dirty, old .10...001001 -> ..0...1...1.
- * prot-none, dirty, young .10...001101 -> ..1...1...1.
- * read-only, clean, old .11...010001 -> ..1...1...0.
- * read-only, clean, young .01...010101 -> ..1...0...1.
- * read-only, dirty, old .11...011001 -> ..1...1...0.
- * read-only, dirty, young .01...011101 -> ..1...0...1.
- * read-write, clean, old .11...110001 -> ..0...1...0.
- * read-write, clean, young .01...110101 -> ..0...0...1.
- * read-write, dirty, old .10...111001 -> ..0...1...0.
- * read-write, dirty, young .00...111101 -> ..0...0...1.
- * Huge ptes are dirty by definition, a clean pte is made dirty
- * by the conversion.
+ * Convert encoding pte bits pmd bits
+ * .IR...wrdytp dy..R...I...wr
+ * empty .10...000000 -> 00..0...1...00
+ * prot-none, clean, old .11...000001 -> 00..1...1...00
+ * prot-none, clean, young .11...000101 -> 01..1...1...00
+ * prot-none, dirty, old .10...001001 -> 10..1...1...00
+ * prot-none, dirty, young .10...001101 -> 11..1...1...00
+ * read-only, clean, old .11...010001 -> 00..1...1...01
+ * read-only, clean, young .01...010101 -> 01..1...0...01
+ * read-only, dirty, old .11...011001 -> 10..1...1...01
+ * read-only, dirty, young .01...011101 -> 11..1...0...01
+ * read-write, clean, old .11...110001 -> 00..0...1...11
+ * read-write, clean, young .01...110101 -> 01..0...0...11
+ * read-write, dirty, old .10...111001 -> 10..0...1...11
+ * read-write, dirty, young .00...111101 -> 11..0...0...11
*/
if (pte_present(pte)) {
pmd_val(pmd) = pte_val(pte) & PAGE_MASK;
- if (pte_val(pte) & _PAGE_INVALID)
- pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID;
- none = (pte_val(pte) & _PAGE_PRESENT) &&
- !(pte_val(pte) & _PAGE_READ) &&
- !(pte_val(pte) & _PAGE_WRITE);
- prot = (pte_val(pte) & _PAGE_PROTECT) &&
- !(pte_val(pte) & _PAGE_WRITE);
- young = pte_val(pte) & _PAGE_YOUNG;
- if (none || young)
- pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG;
- if (prot || (none && young))
- pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_READ) >> 4;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_WRITE) >> 4;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_INVALID) >> 5;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_PROTECT);
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
} else
pmd_val(pmd) = _SEGMENT_ENTRY_INVALID;
return pmd;
@@ -56,34 +47,31 @@ static inline pte_t __pmd_to_pte(pmd_t pmd)
pte_t pte;
/*
- * Convert encoding pmd bits pte bits
- * ..R...I...y. .IR...wrdytp
- * empty ..0...1...0. -> .10...000000
- * prot-none, old ..0...1...1. -> .10...001001
- * prot-none, young ..1...1...1. -> .10...001101
- * read-only, old ..1...1...0. -> .11...011001
- * read-only, young ..1...0...1. -> .01...011101
- * read-write, old ..0...1...0. -> .10...111001
- * read-write, young ..0...0...1. -> .00...111101
- * Huge ptes are dirty by definition
+ * Convert encoding pmd bits pte bits
+ * dy..R...I...wr .IR...wrdytp
+ * empty 00..0...1...00 -> .10...001100
+ * prot-none, clean, old 00..0...1...00 -> .10...000001
+ * prot-none, clean, young 01..0...1...00 -> .10...000101
+ * prot-none, dirty, old 10..0...1...00 -> .10...001001
+ * prot-none, dirty, young 11..0...1...00 -> .10...001101
+ * read-only, clean, old 00..1...1...01 -> .11...010001
+ * read-only, clean, young 01..1...1...01 -> .11...010101
+ * read-only, dirty, old 10..1...1...01 -> .11...011001
+ * read-only, dirty, young 11..1...1...01 -> .11...011101
+ * read-write, clean, old 00..0...1...11 -> .10...110001
+ * read-write, clean, young 01..0...1...11 -> .10...110101
+ * read-write, dirty, old 10..0...1...11 -> .10...111001
+ * read-write, dirty, young 11..0...1...11 -> .10...111101
*/
if (pmd_present(pmd)) {
- pte_val(pte) = _PAGE_PRESENT | _PAGE_LARGE | _PAGE_DIRTY |
- (pmd_val(pmd) & PAGE_MASK);
- if (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID)
- pte_val(pte) |= _PAGE_INVALID;
- if (pmd_prot_none(pmd)) {
- if (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT)
- pte_val(pte) |= _PAGE_YOUNG;
- } else {
- pte_val(pte) |= _PAGE_READ;
- if (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT)
- pte_val(pte) |= _PAGE_PROTECT;
- else
- pte_val(pte) |= _PAGE_WRITE;
- if (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG)
- pte_val(pte) |= _PAGE_YOUNG;
- }
+ pte_val(pte) = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN_LARGE;
+ pte_val(pte) |= _PAGE_LARGE | _PAGE_PRESENT;
+ pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_READ) << 4;
+ pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) << 4;
+ pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) << 5;
+ pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT);
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
+ pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
} else
pte_val(pte) = _PAGE_INVALID;
return pte;
@@ -96,6 +84,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pmd = __pte_to_pmd(pte);
if (!MACHINE_HAS_HPAGE) {
+ /* Emulated huge ptes loose the dirty and young bit */
pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
pmd_val(pmd) |= pte_page(pte)[1].index;
} else
@@ -113,6 +102,8 @@ pte_t huge_ptep_get(pte_t *ptep)
origin = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN;
pmd_val(pmd) &= ~_SEGMENT_ENTRY_ORIGIN;
pmd_val(pmd) |= *(unsigned long *) origin;
+ /* Emulated huge ptes are young and dirty by definition */
+ pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG | _SEGMENT_ENTRY_DIRTY;
}
return __pmd_to_pte(pmd);
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 37b8241ec784..19daa53a3da4 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -1279,6 +1279,7 @@ static unsigned long page_table_realloc_pmd(struct mmu_gather *tlb,
{
unsigned long next, *table, *new;
struct page *page;
+ spinlock_t *ptl;
pmd_t *pmd;
pmd = pmd_offset(pud, addr);
@@ -1296,7 +1297,7 @@ again:
if (!new)
return -ENOMEM;
- spin_lock(&mm->page_table_lock);
+ ptl = pmd_lock(mm, pmd);
if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
/* Nuke pmd entry pointing to the "short" page table */
pmdp_flush_lazy(mm, addr, pmd);
@@ -1310,7 +1311,7 @@ again:
page_table_free_rcu(tlb, table);
new = NULL;
}
- spin_unlock(&mm->page_table_lock);
+ spin_unlock(ptl);
if (new) {
page_table_free_pgste(new);
goto again;
@@ -1432,6 +1433,9 @@ int pmdp_set_access_flags(struct vm_area_struct *vma,
{
VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+ entry = pmd_mkyoung(entry);
+ if (dirty)
+ entry = pmd_mkdirty(entry);
if (pmd_same(*pmdp, entry))
return 0;
pmdp_invalidate(vma, address, pmdp);
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index a2cbd875543a..61e45b7c04d7 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -812,7 +812,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
return header;
}
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
struct bpf_binary_header *header = NULL;
unsigned long size, prg_len, lit_len;
@@ -875,7 +875,7 @@ out:
kfree(addrs);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 30de42730b2f..2fa7b14b9c08 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -15,8 +15,8 @@
* Thomas Klein
*/
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index 96545d7659fd..6e22a247de9b 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -5,8 +5,8 @@
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c
index c5c66840ac00..eec598c5939f 100644
--- a/arch/s390/pci/pci_debug.c
+++ b/arch/s390/pci/pci_debug.c
@@ -5,8 +5,8 @@
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/seq_file.h>
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index f91c03119804..4cbb29a4d615 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -16,6 +16,13 @@
static struct kmem_cache *dma_region_table_cache;
static struct kmem_cache *dma_page_table_cache;
+static int s390_iommu_strict;
+
+static int zpci_refresh_global(struct zpci_dev *zdev)
+{
+ return zpci_refresh_trans((u64) zdev->fh << 32, zdev->start_dma,
+ zdev->iommu_pages * PAGE_SIZE);
+}
static unsigned long *dma_alloc_cpu_table(void)
{
@@ -155,18 +162,15 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
}
/*
- * rpcit is not required to establish new translations when previously
- * invalid translation-table entries are validated, however it is
- * required when altering previously valid entries.
+ * With zdev->tlb_refresh == 0, rpcit is not required to establish new
+ * translations when previously invalid translation-table entries are
+ * validated. With lazy unmap, it also is skipped for previously valid
+ * entries, but a global rpcit is then required before any address can
+ * be re-used, i.e. after each iommu bitmap wrap-around.
*/
if (!zdev->tlb_refresh &&
- ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID))
- /*
- * TODO: also need to check that the old entry is indeed INVALID
- * and not only for one page but for the whole range...
- * -> now we WARN_ON in that case but with lazy unmap that
- * needs to be redone!
- */
+ (!s390_iommu_strict ||
+ ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)))
goto no_refresh;
rc = zpci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
@@ -220,16 +224,21 @@ static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size)
{
unsigned long offset, flags;
+ int wrap = 0;
spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
offset = __dma_alloc_iommu(zdev, zdev->next_bit, size);
- if (offset == -1)
+ if (offset == -1) {
+ /* wrap-around */
offset = __dma_alloc_iommu(zdev, 0, size);
+ wrap = 1;
+ }
if (offset != -1) {
zdev->next_bit = offset + size;
- if (zdev->next_bit >= zdev->iommu_pages)
- zdev->next_bit = 0;
+ if (!zdev->tlb_refresh && !s390_iommu_strict && wrap)
+ /* global flush after wrap-around with lazy unmap */
+ zpci_refresh_global(zdev);
}
spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
return offset;
@@ -243,7 +252,11 @@ static void dma_free_iommu(struct zpci_dev *zdev, unsigned long offset, int size
if (!zdev->iommu_bitmap)
goto out;
bitmap_clear(zdev->iommu_bitmap, offset, size);
- if (offset >= zdev->next_bit)
+ /*
+ * Lazy flush for unmap: need to move next_bit to avoid address re-use
+ * until wrap-around.
+ */
+ if (!s390_iommu_strict && offset >= zdev->next_bit)
zdev->next_bit = offset + size;
out:
spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
@@ -504,3 +517,12 @@ struct dma_map_ops s390_dma_ops = {
/* dma_supported is unconditionally true without a callback */
};
EXPORT_SYMBOL_GPL(s390_dma_ops);
+
+static int __init s390_iommu_setup(char *str)
+{
+ if (!strncmp(str, "strict", 6))
+ s390_iommu_strict = 1;
+ return 0;
+}
+
+__setup("s390_iommu=", s390_iommu_setup);
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 6d7f5a3016ca..460fdb21cf61 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -5,8 +5,8 @@
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/pci.h>
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
index 9190214b8702..fa3ce891e597 100644
--- a/arch/s390/pci/pci_sysfs.c
+++ b/arch/s390/pci/pci_sysfs.c
@@ -5,8 +5,8 @@
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
-#define COMPONENT "zPCI"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/kernel.h>
#include <linux/stat.h>
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 2f947aba4bd4..aad209199f7e 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -8,5 +8,6 @@ generic-y += cputime.h
generic-y += hash.h
generic-y += mcs_spinlock.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += trace_clock.h
generic-y += xor.h
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h
index d9a922d8711b..851f441991d2 100644
--- a/arch/score/include/asm/processor.h
+++ b/arch/score/include/asm/processor.h
@@ -24,6 +24,7 @@ extern unsigned long get_wchan(struct task_struct *p);
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#define release_thread(thread) do {} while (0)
/*
diff --git a/arch/score/include/asm/scatterlist.h b/arch/score/include/asm/scatterlist.h
deleted file mode 100644
index 9f533b8362c7..000000000000
--- a/arch/score/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_SCATTERLIST_H
-#define _ASM_SCORE_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _ASM_SCORE_SCATTERLIST_H */
diff --git a/arch/score/include/uapi/asm/ptrace.h b/arch/score/include/uapi/asm/ptrace.h
index f59771a3f127..5c5e794058be 100644
--- a/arch/score/include/uapi/asm/ptrace.h
+++ b/arch/score/include/uapi/asm/ptrace.h
@@ -4,17 +4,6 @@
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
-#define PC 32
-#define CONDITION 33
-#define ECR 34
-#define EMA 35
-#define CEH 36
-#define CEL 37
-#define COUNTER 38
-#define LDCR 39
-#define STCR 40
-#define PSR 41
-
#define SINGLESTEP16_INSN 0x7006
#define SINGLESTEP32_INSN 0x840C8000
#define BREAKPOINT16_INSN 0x7002 /* work on SPG300 */
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c
index a00fba32b0eb..1651807774ad 100644
--- a/arch/score/kernel/signal.c
+++ b/arch/score/kernel/signal.c
@@ -173,15 +173,15 @@ badframe:
return 0;
}
-static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
- int signr, sigset_t *set, siginfo_t *info)
+static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
+ sigset_t *set)
{
struct rt_sigframe __user *frame;
int err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
/*
* Set up the return code ...
@@ -194,7 +194,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(0x80008002, frame->rs_code + 1);
flush_cache_sigtramp((unsigned long) frame->rs_code);
- err |= copy_siginfo_to_user(&frame->rs_info, info);
+ err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
err |= __put_user(0, &frame->rs_uc.uc_flags);
err |= __put_user(NULL, &frame->rs_uc.uc_link);
err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]);
@@ -202,26 +202,23 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ return -EFAULT;
regs->regs[0] = (unsigned long) frame;
regs->regs[3] = (unsigned long) frame->rs_code;
- regs->regs[4] = signr;
+ regs->regs[4] = ksig->sig;
regs->regs[5] = (unsigned long) &frame->rs_info;
regs->regs[6] = (unsigned long) &frame->rs_uc;
- regs->regs[29] = (unsigned long) ka->sa.sa_handler;
- regs->cp0_epc = (unsigned long) ka->sa.sa_handler;
+ regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler;
+ regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler;
return 0;
-
-give_sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
+ int ret;
+
if (regs->is_syscall) {
switch (regs->regs[4]) {
case ERESTART_RESTARTBLOCK:
@@ -229,7 +226,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[4] = EINTR;
break;
case ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[4] = EINTR;
break;
}
@@ -245,17 +242,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
/*
* Set up the stack frame
*/
- if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
- return;
+ ret = setup_rt_frame(ksig, regs, sigmask_to_save());
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
static void do_signal(struct pt_regs *regs)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which is why we may in certain
@@ -265,10 +259,9 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
return;
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 834b67c4db5a..453fa5c09550 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -57,7 +57,6 @@ config SUPERH32
select HAVE_FUNCTION_TRACER
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
select ARCH_WANT_IPC_PARSE_VERSION
select HAVE_FUNCTION_GRAPH_TRACER
@@ -596,6 +595,8 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on SUPERH32 && MMU
+ select CRYPTO
+ select CRYPTO_SHA256
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index e331e5373b8e..89963d13f930 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -371,7 +371,7 @@ if SH_MAGIC_PANEL_R2
menu "Magic Panel R2 options"
config SH_MAGIC_PANEL_R2_VERSION
- int SH_MAGIC_PANEL_R2_VERSION
+ int "Magic Panel R2 Version"
default "3"
help
Set the version of the Magic Panel R2
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 85d5255d259f..0d3049244cd3 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
.name = "asoc-simple-card",
.dev = {
.platform_data = &fsi_da7210_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
},
};
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig
index 0c08d9244c97..e741b1e36acd 100644
--- a/arch/sh/configs/sh2007_defconfig
+++ b/arch/sh/configs/sh2007_defconfig
@@ -52,7 +52,6 @@ CONFIG_CDROM_PKTCDVD=y
# CONFIG_MISC_DEVICES is not set
CONFIG_RAID_ATTRS=y
CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig
index cfd5b90a8628..78bc97b1d027 100644
--- a/arch/sh/drivers/dma/Kconfig
+++ b/arch/sh/drivers/dma/Kconfig
@@ -12,9 +12,8 @@ config SH_DMA_IRQ_MULTI
default y if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || \
CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || \
CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7091 || \
- CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \
- CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 || \
- CPU_SUBTYPE_SH7760
+ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7780 || \
+ CPU_SUBTYPE_SH7785 || CPU_SUBTYPE_SH7760
config SH_DMA_API
depends on SH_DMA
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index b22565623142..afde2a7d3eb3 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -25,7 +25,7 @@
* Define the default configuration for dual address memory-memory transfer.
* The 0x400 value represents auto-request, external->external.
*/
-#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_INDEX2VAL(XMIT_SZ_32BIT))
+#define RS_DUAL (DM_INC | SM_INC | RS_AUTO | TS_INDEX2VAL(XMIT_SZ_32BIT))
static unsigned long dma_find_base(unsigned int chan)
{
diff --git a/arch/sh/include/asm/dma-register.h b/arch/sh/include/asm/dma-register.h
index 51cd78feacff..c757b47e6b64 100644
--- a/arch/sh/include/asm/dma-register.h
+++ b/arch/sh/include/asm/dma-register.h
@@ -13,17 +13,17 @@
#ifndef DMA_REGISTER_H
#define DMA_REGISTER_H
-/* DMA register */
-#define SAR 0x00
-#define DAR 0x04
-#define TCR 0x08
-#define CHCR 0x0C
-#define DMAOR 0x40
+/* DMA registers */
+#define SAR 0x00 /* Source Address Register */
+#define DAR 0x04 /* Destination Address Register */
+#define TCR 0x08 /* Transfer Count Register */
+#define CHCR 0x0C /* Channel Control Register */
+#define DMAOR 0x40 /* DMA Operation Register */
/* DMAOR definitions */
-#define DMAOR_AE 0x00000004
+#define DMAOR_AE 0x00000004 /* Address Error Flag */
#define DMAOR_NMIF 0x00000002
-#define DMAOR_DME 0x00000001
+#define DMAOR_DME 0x00000001 /* DMA Master Enable */
/* Definitions for the SuperH DMAC */
#define REQ_L 0x00000000
@@ -34,18 +34,20 @@
#define ACK_W 0x00020000
#define ACK_H 0x00000000
#define ACK_L 0x00010000
-#define DM_INC 0x00004000
-#define DM_DEC 0x00008000
-#define DM_FIX 0x0000c000
-#define SM_INC 0x00001000
-#define SM_DEC 0x00002000
-#define SM_FIX 0x00003000
+#define DM_INC 0x00004000 /* Destination addresses are incremented */
+#define DM_DEC 0x00008000 /* Destination addresses are decremented */
+#define DM_FIX 0x0000c000 /* Destination address is fixed */
+#define SM_INC 0x00001000 /* Source addresses are incremented */
+#define SM_DEC 0x00002000 /* Source addresses are decremented */
+#define SM_FIX 0x00003000 /* Source address is fixed */
#define RS_IN 0x00000200
#define RS_OUT 0x00000300
+#define RS_AUTO 0x00000400 /* Auto Request */
+#define RS_ERS 0x00000800 /* DMA extended resource selector */
#define TS_BLK 0x00000040
#define TM_BUR 0x00000020
-#define CHCR_DE 0x00000001
-#define CHCR_TE 0x00000002
-#define CHCR_IE 0x00000004
+#define CHCR_DE 0x00000001 /* DMA Enable */
+#define CHCR_TE 0x00000002 /* Transfer End Flag */
+#define CHCR_IE 0x00000004 /* Interrupt Enable */
#endif
diff --git a/arch/sh/include/asm/io_noioport.h b/arch/sh/include/asm/io_noioport.h
index 4d48f1436a63..c727e6ddf69e 100644
--- a/arch/sh/include/asm/io_noioport.h
+++ b/arch/sh/include/asm/io_noioport.h
@@ -34,6 +34,17 @@ static inline void outl(unsigned int x, unsigned long port)
BUG();
}
+static inline void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+ BUG();
+ return NULL;
+}
+
+static inline void ioport_unmap(void __iomem *addr)
+{
+ BUG();
+}
+
#define inb_p(addr) inb(addr)
#define inw_p(addr) inw(addr)
#define inl_p(addr) inl(addr)
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index 15d970328f71..fe20d14ae051 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -186,11 +186,6 @@ typedef struct page *pgtable_t;
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
-/* vDSO support */
-#ifdef CONFIG_VSYSCALL
-#define __HAVE_ARCH_GATE_AREA
-#endif
-
/*
* Some drivers need to perform DMA into kmalloc'ed buffers
* and so we have to increase the kmalloc minalign for this.
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 5448f9bbf4ab..1506897648aa 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -97,6 +97,7 @@ extern struct sh_cpuinfo cpu_data[];
#define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory")
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
void default_idle(void);
void stop_this_cpu(void *);
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h
index 02788b6a03b7..9cd81e54056a 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-register.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h
@@ -32,7 +32,6 @@
#define CHCR_TS_HIGH_SHIFT (20 - 2) /* 2 bits for shifted low TS */
#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
defined(CONFIG_CPU_SUBTYPE_SH7763) || \
- defined(CONFIG_CPU_SUBTYPE_SH7764) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
#define CHCR_TS_LOW_MASK 0x00000018
diff --git a/arch/sh/include/cpu-sh4a/cpu/dma.h b/arch/sh/include/cpu-sh4a/cpu/dma.h
index 89afb650ce25..8ceccceae844 100644
--- a/arch/sh/include/cpu-sh4a/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4a/cpu/dma.h
@@ -14,8 +14,7 @@
#define DMTE4_IRQ evt2irq(0xb80)
#define DMAE0_IRQ evt2irq(0xbc0) /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
- defined(CONFIG_CPU_SUBTYPE_SH7764)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
#define DMTE0_IRQ evt2irq(0x640)
#define DMTE4_IRQ evt2irq(0x780)
#define DMAE0_IRQ evt2irq(0x6c0)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index f579dd528198..c187b9579c21 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -307,7 +307,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]),
CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]),
- CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[HWBLK_CMT]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
@@ -332,6 +332,8 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]),
CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[HWBLK_USB1]),
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[HWBLK_USB0]),
+ CLKDEV_CON_ID("usb1", &mstp_clks[HWBLK_USB1]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB0]),
CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]),
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]),
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 57f83a92a505..7aa733307afc 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -30,62 +30,62 @@ static const struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SCIF0_TX,
.addr = 0xffe0000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
}, {
.slave_id = SHDMA_SLAVE_SCIF0_RX,
.addr = 0xffe00014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_TX,
.addr = 0xffe1000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x25,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_RX,
.addr = 0xffe10014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x26,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_TX,
.addr = 0xffe2000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_RX,
.addr = 0xffe20014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
}, {
.slave_id = SHDMA_SLAVE_SIUA_TX,
.addr = 0xa454c098,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xb1,
}, {
.slave_id = SHDMA_SLAVE_SIUA_RX,
.addr = 0xa454c090,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xb2,
}, {
.slave_id = SHDMA_SLAVE_SIUB_TX,
.addr = 0xa454c09c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xb5,
}, {
.slave_id = SHDMA_SLAVE_SIUB_RX,
.addr = 0xa454c094,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xb6,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_TX,
.addr = 0x04ce0030,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc1,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_RX,
.addr = 0x04ce0030,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc2,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index b9e84b1d3aa7..ea5780b3c7f6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -36,122 +36,122 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SCIF0_TX,
.addr = 0xffe0000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
}, {
.slave_id = SHDMA_SLAVE_SCIF0_RX,
.addr = 0xffe00014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_TX,
.addr = 0xffe1000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x25,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_RX,
.addr = 0xffe10014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x26,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_TX,
.addr = 0xffe2000c,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_RX,
.addr = 0xffe20014,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
}, {
.slave_id = SHDMA_SLAVE_SCIF3_TX,
.addr = 0xa4e30020,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2d,
}, {
.slave_id = SHDMA_SLAVE_SCIF3_RX,
.addr = 0xa4e30024,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2e,
}, {
.slave_id = SHDMA_SLAVE_SCIF4_TX,
.addr = 0xa4e40020,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x31,
}, {
.slave_id = SHDMA_SLAVE_SCIF4_RX,
.addr = 0xa4e40024,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x32,
}, {
.slave_id = SHDMA_SLAVE_SCIF5_TX,
.addr = 0xa4e50020,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x35,
}, {
.slave_id = SHDMA_SLAVE_SCIF5_RX,
.addr = 0xa4e50024,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x36,
}, {
.slave_id = SHDMA_SLAVE_USB0D0_TX,
.addr = 0xA4D80100,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0x73,
}, {
.slave_id = SHDMA_SLAVE_USB0D0_RX,
.addr = 0xA4D80100,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0x73,
}, {
.slave_id = SHDMA_SLAVE_USB0D1_TX,
.addr = 0xA4D80120,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0x77,
}, {
.slave_id = SHDMA_SLAVE_USB0D1_RX,
.addr = 0xA4D80120,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0x77,
}, {
.slave_id = SHDMA_SLAVE_USB1D0_TX,
.addr = 0xA4D90100,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xab,
}, {
.slave_id = SHDMA_SLAVE_USB1D0_RX,
.addr = 0xA4D90100,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xab,
}, {
.slave_id = SHDMA_SLAVE_USB1D1_TX,
.addr = 0xA4D90120,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xaf,
}, {
.slave_id = SHDMA_SLAVE_USB1D1_RX,
.addr = 0xA4D90120,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xaf,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_TX,
.addr = 0x04ce0030,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc1,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_RX,
.addr = 0x04ce0030,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc2,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_TX,
.addr = 0x04cf0030,
- .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc9,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_RX,
.addr = 0x04cf0030,
- .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .chcr = DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xca,
},
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 7b24ec4b409a..18bcd70cd813 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -123,28 +123,28 @@ static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SDHI_TX,
.addr = 0x1fe50030,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc5,
},
{
.slave_id = SHDMA_SLAVE_SDHI_RX,
.addr = 0x1fe50030,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc6,
},
{
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0x1fcb0034,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xd3,
},
{
.slave_id = SHDMA_SLAVE_MMCIF_RX,
.addr = 0x1fcb0034,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xd7,
},
@@ -154,56 +154,56 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SCIF2_TX,
.addr = 0x1f4b000c,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_SCIF2_RX,
.addr = 0x1f4b0014,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_SCIF3_TX,
.addr = 0x1f4c000c,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_SCIF3_RX,
.addr = 0x1f4c0014,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_SCIF4_TX,
.addr = 0x1f4d000c,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x41,
},
{
.slave_id = SHDMA_SLAVE_SCIF4_RX,
.addr = 0x1f4d0014,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x42,
},
{
.slave_id = SHDMA_SLAVE_RSPI_TX,
.addr = 0xfe480004,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc1,
},
{
.slave_id = SHDMA_SLAVE_RSPI_RX,
.addr = 0xfe480004,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc2,
},
@@ -213,70 +213,70 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
{
.slave_id = SHDMA_SLAVE_RIIC0_TX,
.addr = 0x1e500012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_RIIC0_RX,
.addr = 0x1e500013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_RIIC1_TX,
.addr = 0x1e510012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_RIIC1_RX,
.addr = 0x1e510013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_RIIC2_TX,
.addr = 0x1e520012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xa1,
},
{
.slave_id = SHDMA_SLAVE_RIIC2_RX,
.addr = 0x1e520013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xa2,
},
{
.slave_id = SHDMA_SLAVE_RIIC3_TX,
.addr = 0x1e530012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xa9,
},
{
.slave_id = SHDMA_SLAVE_RIIC3_RX,
.addr = 0x1e530013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xaf,
},
{
.slave_id = SHDMA_SLAVE_RIIC4_TX,
.addr = 0x1e540012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xc5,
},
{
.slave_id = SHDMA_SLAVE_RIIC4_RX,
.addr = 0x1e540013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xc6,
},
@@ -286,70 +286,70 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
{
.slave_id = SHDMA_SLAVE_RIIC5_TX,
.addr = 0x1e550012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_RIIC5_RX,
.addr = 0x1e550013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_RIIC6_TX,
.addr = 0x1e560012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_RIIC6_RX,
.addr = 0x1e560013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_RIIC7_TX,
.addr = 0x1e570012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x41,
},
{
.slave_id = SHDMA_SLAVE_RIIC7_RX,
.addr = 0x1e570013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x42,
},
{
.slave_id = SHDMA_SLAVE_RIIC8_TX,
.addr = 0x1e580012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x45,
},
{
.slave_id = SHDMA_SLAVE_RIIC8_RX,
.addr = 0x1e580013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x46,
},
{
.slave_id = SHDMA_SLAVE_RIIC9_TX,
.addr = 0x1e590012,
- .chcr = SM_INC | 0x800 | 0x40000000 |
+ .chcr = SM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x51,
},
{
.slave_id = SHDMA_SLAVE_RIIC9_RX,
.addr = 0x1e590013,
- .chcr = DM_INC | 0x800 | 0x40000000 |
+ .chcr = DM_INC | RS_ERS | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x52,
},
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c
index 3c74f53db6db..079d70e6d74b 100644
--- a/arch/sh/kernel/ftrace.c
+++ b/arch/sh/kernel/ftrace.c
@@ -344,6 +344,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)&return_to_handler;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c
index 02331672b6db..7cfd7f153966 100644
--- a/arch/sh/kernel/perf_event.c
+++ b/arch/sh/kernel/perf_event.c
@@ -129,14 +129,6 @@ static int __hw_perf_event_init(struct perf_event *event)
return -ENODEV;
/*
- * All of the on-chip counters are "limited", in that they have
- * no interrupts, and are therefore unable to do sampling without
- * further work and timer assistance.
- */
- if (hwc->sample_period)
- return -EINVAL;
-
- /*
* See if we need to reserve the counter.
*
* If no events are currently in use, then we have to take a
@@ -392,6 +384,13 @@ int register_sh_pmu(struct sh_pmu *_pmu)
pr_info("Performance Events: %s support registered\n", _pmu->name);
+ /*
+ * All of the on-chip counters are "limited", in that they have
+ * no interrupts, and are therefore unable to do sampling without
+ * further work and timer assistance.
+ */
+ pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
WARN_ON(_pmu->num_events > MAX_HWEVENTS);
perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 594cd371aa28..2f002b24fb92 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
extern void __kernel_sigreturn(void);
extern void __kernel_rt_sigreturn(void);
-static int setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
- frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->pr = (unsigned long) ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
#ifdef CONFIG_VSYSCALL
} else if (likely(current->mm->context.vdso)) {
regs->pr = VDSO_SYM(&__kernel_sigreturn);
@@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->regs[15] = (unsigned long) frame;
@@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+ (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
err |= __get_user(regs->pc, &funcptr->text);
err |= __get_user(regs->regs[12], &funcptr->GOT);
} else
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
if (err)
- goto give_sigsegv;
+ return -EFAULT;
set_fs(USER_DS);
@@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
- frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -371,8 +367,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->pr = (unsigned long) ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
#ifdef CONFIG_VSYSCALL
} else if (likely(current->mm->context.vdso)) {
regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
@@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->regs[15] = (unsigned long) frame;
@@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
- (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
+ (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
err |= __get_user(regs->pc, &funcptr->text);
err |= __get_user(regs->regs[12], &funcptr->GOT);
} else
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
if (err)
- goto give_sigsegv;
+ return -EFAULT;
set_fs(USER_DS);
@@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
static inline void
@@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
* OK, we're invoking a handler
*/
static void
-handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- struct pt_regs *regs, unsigned int save_r0)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs, unsigned int save_r0)
{
sigset_t *oldset = sigmask_to_save();
int ret;
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(ksig, oldset, regs);
- if (ret)
- return;
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/
static void do_signal(struct pt_regs *regs, unsigned int save_r0)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which
@@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- handle_syscall_restart(save_r0, regs, &ka.sa);
+ if (get_signal(&ksig)) {
+ handle_syscall_restart(save_r0, regs, &ksig.ka.sa);
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &ka, &info, regs, save_r0);
+ handle_signal(&ksig, regs, save_r0);
return;
}
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 23d4c71c91af..897abe7b871e 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -41,8 +41,7 @@
#define DEBUG_SIG 0
static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs * regs);
+handle_signal(struct ksignal *ksig, struct pt_regs *regs);
static inline void
handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
@@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
*/
static void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which
@@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, 0);
- if (signr > 0) {
- handle_syscall_restart(regs, &ka.sa);
+ if (get_signal(&ksig)) {
+ handle_syscall_restart(regs, &ksig.ka.sa);
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
return;
}
@@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
void sa_default_restorer(void); /* See comments below */
void sa_default_rt_restorer(void); /* See comments below */
-static int setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
struct sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
- frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Give up earlier as i386, in case */
if (err)
- goto give_sigsegv;
+ return -EFAULT;
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
@@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Give up earlier as i386, in case */
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
/*
* On SH5 all edited pointers are subject to NEFF
*/
DEREF_REG_PR = neff_sign_extend((unsigned long)
- ka->sa.sa_restorer | 0x1);
+ ksig->ka->sa.sa_restorer | 0x1);
} else {
/*
* Different approach on SH5.
@@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
if (__copy_to_user(frame->retcode,
(void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
- goto give_sigsegv;
+ return -EFAULT;
/* Cohere the trampoline with the I-cache. */
flush_cache_sigtramp(DEREF_REG_PR-1);
@@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
- regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
+ regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
set_fs(USER_DS);
@@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *kig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
- frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ return -EFAULT;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Give up earlier as i386, in case */
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Give up earlier as i386, in case */
if (err)
- goto give_sigsegv;
+ return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
- if (ka->sa.sa_flags & SA_RESTORER) {
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
/*
* On SH5 all edited pointers are subject to NEFF
*/
DEREF_REG_PR = neff_sign_extend((unsigned long)
- ka->sa.sa_restorer | 0x1);
+ ksig->ka.sa.sa_restorer | 0x1);
} else {
/*
* Different approach on SH5.
@@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__copy_to_user(frame->retcode,
(void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
- goto give_sigsegv;
+ return -EFAULT;
/* Cohere the trampoline with the I-cache. */
flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
@@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
- regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
+ regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
set_fs(USER_DS);
@@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs * regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
/* Set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(sig, ka, oldset, regs);
-
- if (ret)
- return;
+ ret = setup_frame(ksig, oldset, regs);
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 552c8fcf9416..d6d0a986c6e9 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -80,10 +80,8 @@ static int __init rtc_generic_init(void)
return -ENODEV;
pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
module_init(rtc_generic_init);
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index 5ca579720a09..ea2aa1393b87 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -92,18 +92,3 @@ const char *arch_vma_name(struct vm_area_struct *vma)
return NULL;
}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long address)
-{
- return 0;
-}
-
-int in_gate_area_no_mm(unsigned long address)
-{
- return 0;
-}
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S
index 52aa2011d753..7a8572f9d58b 100644
--- a/arch/sh/lib/mcount.S
+++ b/arch/sh/lib/mcount.S
@@ -92,13 +92,6 @@ mcount:
rts
nop
#else
-#ifndef CONFIG_DYNAMIC_FTRACE
- mov.l .Lfunction_trace_stop, r0
- mov.l @r0, r0
- tst r0, r0
- bf ftrace_stub
-#endif
-
MCOUNT_ENTER()
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -174,11 +167,6 @@ ftrace_graph_call:
.globl ftrace_caller
ftrace_caller:
- mov.l .Lfunction_trace_stop, r0
- mov.l @r0, r0
- tst r0, r0
- bf ftrace_stub
-
MCOUNT_ENTER()
.globl ftrace_call
@@ -196,8 +184,6 @@ ftrace_call:
#endif /* CONFIG_DYNAMIC_FTRACE */
.align 2
-.Lfunction_trace_stop:
- .long function_trace_stop
/*
* NOTE: From here on the locations of the .Lftrace_stub label and
@@ -217,12 +203,7 @@ ftrace_stub:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.globl ftrace_graph_caller
ftrace_graph_caller:
- mov.l 2f, r0
- mov.l @r0, r0
- tst r0, r0
- bt 1f
-
- mov.l 3f, r1
+ mov.l 2f, r1
jmp @r1
nop
1:
@@ -242,8 +223,7 @@ ftrace_graph_caller:
MCOUNT_LEAVE()
.align 2
-2: .long function_trace_stop
-3: .long skip_trace
+2: .long skip_trace
.Lprepare_ftrace_return:
.long prepare_ftrace_return
diff --git a/arch/sh/mm/asids-debugfs.c b/arch/sh/mm/asids-debugfs.c
index 74c03ecc4871..ecfc6b0c1da1 100644
--- a/arch/sh/mm/asids-debugfs.c
+++ b/arch/sh/mm/asids-debugfs.c
@@ -67,10 +67,8 @@ static int __init asids_debugfs_init(void)
NULL, &asids_debugfs_fops);
if (!asids_dentry)
return -ENOMEM;
- if (IS_ERR(asids_dentry))
- return PTR_ERR(asids_dentry);
- return 0;
+ return PTR_ERR_OR_ZERO(asids_dentry);
}
module_init(asids_debugfs_init);
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 2d089fe2cba9..2790b6a64157 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -495,8 +495,9 @@ int arch_add_memory(int nid, u64 start, u64 size)
pgdat = NODE_DATA(nid);
/* We only have ZONE_NORMAL, so this is easy.. */
- ret = __add_pages(nid, pgdat->node_zones + ZONE_NORMAL,
- start_pfn, nr_pages);
+ ret = __add_pages(nid, pgdat->node_zones +
+ zone_for_memory(nid, start, size, ZONE_NORMAL),
+ start_pfn, nr_pages);
if (unlikely(ret))
printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 407c87d9879a..a537816613f9 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -42,6 +42,7 @@ config SPARC
select MODULES_USE_ELF_RELA
select ODD_RT_SIGACTION
select OLD_SIGSUSPEND
+ select ARCH_HAS_SG_CHAIN
config SPARC32
def_bool !64BIT
@@ -55,7 +56,6 @@ config SPARC64
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_GRAPH_FP_TEST
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES
select HAVE_KPROBES
select HAVE_RCU_TABLE_FREE if SMP
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 9ff423678cbc..eaee14637d93 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -68,6 +68,9 @@ all: zImage
image zImage uImage tftpboot.img vmlinux.aout: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+install:
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index 6e63afb128d9..6a4ceae5ec67 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -69,3 +69,7 @@ $(obj)/image: vmlinux FORCE
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
$(call if_changed,elftoaout)
$(call if_changed,piggy)
+
+install:
+ sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/zImage \
+ System.map "$(INSTALL_PATH)"
diff --git a/arch/sparc/boot/install.sh b/arch/sparc/boot/install.sh
new file mode 100644
index 000000000000..b32851eae693
--- /dev/null
+++ b/arch/sparc/boot/install.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for SPARC architecture
+#
+# Arguments:
+# $1 - kernel version
+# $2 - kernel image file
+# $3 - kernel map file
+# $4 - default install path (blank if root directory)
+#
+
+verify () {
+ if [ ! -f "$1" ]; then
+ echo "" 1>&2
+ echo " *** Missing file: $1" 1>&2
+ echo ' *** You need to run "make" before "make install".' 1>&2
+ echo "" 1>&2
+ exit 1
+ fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+# Default install - same as make zlilo
+
+if [ -f $4/vmlinuz ]; then
+ mv $4/vmlinuz $4/vmlinuz.old
+fi
+
+if [ -f $4/System.map ]; then
+ mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinuz
+cp $3 $4/System.map
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index a45821818003..cdd1b447bb6c 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -15,6 +15,7 @@ generic-y += mcs_spinlock.h
generic-y += module.h
generic-y += mutex.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += serial.h
generic-y += trace_clock.h
generic-y += types.h
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h
index 05381c3a4228..80b54b326d49 100644
--- a/arch/sparc/include/asm/io_64.h
+++ b/arch/sparc/include/asm/io_64.h
@@ -9,125 +9,99 @@
#include <asm/asi.h>
#include <asm-generic/pci_iomap.h>
-/* PC crapola... */
-#define __SLOW_DOWN_IO do { } while (0)
-#define SLOW_DOWN_IO do { } while (0)
-
/* BIO layer definitions. */
extern unsigned long kern_base, kern_size;
-static inline u8 _inb(unsigned long addr)
+/* __raw_{read,write}{b,w,l,q} uses direct access.
+ * Access the memory as big endian bypassing the cache
+ * by using ASI_PHYS_BYPASS_EC_E
+ */
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 ret;
- __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
: "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
return ret;
}
-static inline u16 _inw(unsigned long addr)
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 ret;
- __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
: "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
return ret;
}
-static inline u32 _inl(unsigned long addr)
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 ret;
- __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
: "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
return ret;
}
-static inline void _outb(u8 b, unsigned long addr)
-{
- __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
- : /* no outputs */
- : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
-}
-
-static inline void _outw(u16 w, unsigned long addr)
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
{
- __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
- : /* no outputs */
- : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
-}
-
-static inline void _outl(u32 l, unsigned long addr)
-{
- __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
- : /* no outputs */
- : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
- : "memory");
-}
-
-#define inb(__addr) (_inb((unsigned long)(__addr)))
-#define inw(__addr) (_inw((unsigned long)(__addr)))
-#define inl(__addr) (_inl((unsigned long)(__addr)))
-#define outb(__b, __addr) (_outb((u8)(__b), (unsigned long)(__addr)))
-#define outw(__w, __addr) (_outw((u16)(__w), (unsigned long)(__addr)))
-#define outl(__l, __addr) (_outl((u32)(__l), (unsigned long)(__addr)))
-
-#define inb_p(__addr) inb(__addr)
-#define outb_p(__b, __addr) outb(__b, __addr)
-#define inw_p(__addr) inw(__addr)
-#define outw_p(__w, __addr) outw(__w, __addr)
-#define inl_p(__addr) inl(__addr)
-#define outl_p(__l, __addr) outl(__l, __addr)
+ u64 ret;
-void outsb(unsigned long, const void *, unsigned long);
-void outsw(unsigned long, const void *, unsigned long);
-void outsl(unsigned long, const void *, unsigned long);
-void insb(unsigned long, void *, unsigned long);
-void insw(unsigned long, void *, unsigned long);
-void insl(unsigned long, void *, unsigned long);
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
-{
- insb((unsigned long __force)port, buf, count);
-}
-static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
-{
- insw((unsigned long __force)port, buf, count);
+ return ret;
}
-static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 b, const volatile void __iomem *addr)
{
- insl((unsigned long __force)port, buf, count);
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 w, const volatile void __iomem *addr)
{
- outsb((unsigned long __force)port, buf, count);
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 l, const volatile void __iomem *addr)
{
- outsw((unsigned long __force)port, buf, count);
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 q, const volatile void __iomem *addr)
{
- outsl((unsigned long __force)port, buf, count);
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
+ : /* no outputs */
+ : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-/* Memory functions, same as I/O accesses on Ultra. */
-static inline u8 _readb(const volatile void __iomem *addr)
+/* Memory functions, same as I/O accesses on Ultra.
+ * Access memory as little endian bypassing
+ * the cache by using ASI_PHYS_BYPASS_EC_E_L
+ */
+#define readb readb
+static inline u8 readb(const volatile void __iomem *addr)
{ u8 ret;
__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
@@ -137,7 +111,8 @@ static inline u8 _readb(const volatile void __iomem *addr)
return ret;
}
-static inline u16 _readw(const volatile void __iomem *addr)
+#define readw readw
+static inline u16 readw(const volatile void __iomem *addr)
{ u16 ret;
__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
@@ -148,7 +123,8 @@ static inline u16 _readw(const volatile void __iomem *addr)
return ret;
}
-static inline u32 _readl(const volatile void __iomem *addr)
+#define readl readl
+static inline u32 readl(const volatile void __iomem *addr)
{ u32 ret;
__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
@@ -159,7 +135,8 @@ static inline u32 _readl(const volatile void __iomem *addr)
return ret;
}
-static inline u64 _readq(const volatile void __iomem *addr)
+#define readq readq
+static inline u64 readq(const volatile void __iomem *addr)
{ u64 ret;
__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
@@ -170,7 +147,8 @@ static inline u64 _readq(const volatile void __iomem *addr)
return ret;
}
-static inline void _writeb(u8 b, volatile void __iomem *addr)
+#define writeb writeb
+static inline void writeb(u8 b, volatile void __iomem *addr)
{
__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
: /* no outputs */
@@ -178,7 +156,8 @@ static inline void _writeb(u8 b, volatile void __iomem *addr)
: "memory");
}
-static inline void _writew(u16 w, volatile void __iomem *addr)
+#define writew writew
+static inline void writew(u16 w, volatile void __iomem *addr)
{
__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
: /* no outputs */
@@ -186,7 +165,8 @@ static inline void _writew(u16 w, volatile void __iomem *addr)
: "memory");
}
-static inline void _writel(u32 l, volatile void __iomem *addr)
+#define writel writel
+static inline void writel(u32 l, volatile void __iomem *addr)
{
__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
: /* no outputs */
@@ -194,7 +174,8 @@ static inline void _writel(u32 l, volatile void __iomem *addr)
: "memory");
}
-static inline void _writeq(u64 q, volatile void __iomem *addr)
+#define writeq writeq
+static inline void writeq(u64 q, volatile void __iomem *addr)
{
__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
: /* no outputs */
@@ -202,100 +183,91 @@ static inline void _writeq(u64 q, volatile void __iomem *addr)
: "memory");
}
-#define readb(__addr) _readb(__addr)
-#define readw(__addr) _readw(__addr)
-#define readl(__addr) _readl(__addr)
-#define readq(__addr) _readq(__addr)
-#define readb_relaxed(__addr) _readb(__addr)
-#define readw_relaxed(__addr) _readw(__addr)
-#define readl_relaxed(__addr) _readl(__addr)
-#define readq_relaxed(__addr) _readq(__addr)
-#define writeb(__b, __addr) _writeb(__b, __addr)
-#define writew(__w, __addr) _writew(__w, __addr)
-#define writel(__l, __addr) _writel(__l, __addr)
-#define writeq(__q, __addr) _writeq(__q, __addr)
-/* Now versions without byte-swapping. */
-static inline u8 _raw_readb(unsigned long addr)
+#define inb inb
+static inline u8 inb(unsigned long addr)
{
- u8 ret;
-
- __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
- return ret;
+ return readb((volatile void __iomem *)addr);
}
-static inline u16 _raw_readw(unsigned long addr)
+#define inw inw
+static inline u16 inw(unsigned long addr)
{
- u16 ret;
-
- __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
- return ret;
+ return readw((volatile void __iomem *)addr);
}
-static inline u32 _raw_readl(unsigned long addr)
+#define inl inl
+static inline u32 inl(unsigned long addr)
{
- u32 ret;
+ return readl((volatile void __iomem *)addr);
+}
- __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+#define outb outb
+static inline void outb(u8 b, unsigned long addr)
+{
+ writeb(b, (volatile void __iomem *)addr);
+}
- return ret;
+#define outw outw
+static inline void outw(u16 w, unsigned long addr)
+{
+ writew(w, (volatile void __iomem *)addr);
}
-static inline u64 _raw_readq(unsigned long addr)
+#define outl outl
+static inline void outl(u32 l, unsigned long addr)
{
- u64 ret;
+ writel(l, (volatile void __iomem *)addr);
+}
- __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
- return ret;
+#define inb_p(__addr) inb(__addr)
+#define outb_p(__b, __addr) outb(__b, __addr)
+#define inw_p(__addr) inw(__addr)
+#define outw_p(__w, __addr) outw(__w, __addr)
+#define inl_p(__addr) inl(__addr)
+#define outl_p(__l, __addr) outl(__l, __addr)
+
+void outsb(unsigned long, const void *, unsigned long);
+void outsw(unsigned long, const void *, unsigned long);
+void outsl(unsigned long, const void *, unsigned long);
+void insb(unsigned long, void *, unsigned long);
+void insw(unsigned long, void *, unsigned long);
+void insl(unsigned long, void *, unsigned long);
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+ insw((unsigned long __force)port, buf, count);
}
-static inline void _raw_writeb(u8 b, unsigned long addr)
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
{
- __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
- : /* no outputs */
- : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+ insl((unsigned long __force)port, buf, count);
}
-static inline void _raw_writew(u16 w, unsigned long addr)
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
{
- __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
- : /* no outputs */
- : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+ outsb((unsigned long __force)port, buf, count);
}
-static inline void _raw_writel(u32 l, unsigned long addr)
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
{
- __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
- : /* no outputs */
- : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+ outsw((unsigned long __force)port, buf, count);
}
-static inline void _raw_writeq(u64 q, unsigned long addr)
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
{
- __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
- : /* no outputs */
- : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+ outsl((unsigned long __force)port, buf, count);
}
-#define __raw_readb(__addr) (_raw_readb((unsigned long)(__addr)))
-#define __raw_readw(__addr) (_raw_readw((unsigned long)(__addr)))
-#define __raw_readl(__addr) (_raw_readl((unsigned long)(__addr)))
-#define __raw_readq(__addr) (_raw_readq((unsigned long)(__addr)))
-#define __raw_writeb(__b, __addr) (_raw_writeb((u8)(__b), (unsigned long)(__addr)))
-#define __raw_writew(__w, __addr) (_raw_writew((u16)(__w), (unsigned long)(__addr)))
-#define __raw_writel(__l, __addr) (_raw_writel((u32)(__l), (unsigned long)(__addr)))
-#define __raw_writeq(__q, __addr) (_raw_writeq((u64)(__q), (unsigned long)(__addr)))
+#define readb_relaxed(__addr) readb(__addr)
+#define readw_relaxed(__addr) readw(__addr)
+#define readl_relaxed(__addr) readl(__addr)
+#define readq_relaxed(__addr) readq(__addr)
/* Valid I/O Space regions are anywhere, because each PCI bus supported
* can live in an arbitrary area of the physical address range.
@@ -305,96 +277,47 @@ static inline void _raw_writeq(u64 q, unsigned long addr)
/* Now, SBUS variants, only difference from PCI is that we do
* not use little-endian ASIs.
*/
-static inline u8 _sbus_readb(const volatile void __iomem *addr)
+static inline u8 sbus_readb(const volatile void __iomem *addr)
{
- u8 ret;
-
- __asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
-
- return ret;
+ return __raw_readb(addr);
}
-static inline u16 _sbus_readw(const volatile void __iomem *addr)
+static inline u16 sbus_readw(const volatile void __iomem *addr)
{
- u16 ret;
-
- __asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
-
- return ret;
+ return __raw_readw(addr);
}
-static inline u32 _sbus_readl(const volatile void __iomem *addr)
+static inline u32 sbus_readl(const volatile void __iomem *addr)
{
- u32 ret;
-
- __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
-
- return ret;
+ return __raw_readl(addr);
}
-static inline u64 _sbus_readq(const volatile void __iomem *addr)
+static inline u64 sbus_readq(const volatile void __iomem *addr)
{
- u64 ret;
-
- __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* sbus_readq */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
-
- return ret;
+ return __raw_readq(addr);
}
-static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
+static inline void sbus_writeb(u8 b, volatile void __iomem *addr)
{
- __asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
- : /* no outputs */
- : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
+ __raw_writeb(b, addr);
}
-static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
+static inline void sbus_writew(u16 w, volatile void __iomem *addr)
{
- __asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
- : /* no outputs */
- : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
+ __raw_writew(w, addr);
}
-static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
+static inline void sbus_writel(u32 l, volatile void __iomem *addr)
{
- __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
- : /* no outputs */
- : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
+ __raw_writel(l, addr);
}
-static inline void _sbus_writeq(u64 l, volatile void __iomem *addr)
+static inline void sbus_writeq(u64 q, volatile void __iomem *addr)
{
- __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
- : /* no outputs */
- : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
- : "memory");
+ __raw_writeq(q, addr);
}
-#define sbus_readb(__addr) _sbus_readb(__addr)
-#define sbus_readw(__addr) _sbus_readw(__addr)
-#define sbus_readl(__addr) _sbus_readl(__addr)
-#define sbus_readq(__addr) _sbus_readq(__addr)
-#define sbus_writeb(__b, __addr) _sbus_writeb(__b, __addr)
-#define sbus_writew(__w, __addr) _sbus_writew(__w, __addr)
-#define sbus_writel(__l, __addr) _sbus_writel(__l, __addr)
-#define sbus_writeq(__l, __addr) _sbus_writeq(__l, __addr)
-
-static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+static inline void sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
{
while(n--) {
sbus_writeb(c, dst);
@@ -402,10 +325,7 @@ static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_s
}
}
-#define sbus_memset_io(d,c,sz) _sbus_memset_io(d,c,sz)
-
-static inline void
-_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+static inline void memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
{
volatile void __iomem *d = dst;
@@ -415,11 +335,8 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
}
}
-#define memset_io(d,c,sz) _memset_io(d,c,sz)
-
-static inline void
-_sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
- __kernel_size_t n)
+static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
{
char *d = dst;
@@ -430,10 +347,9 @@ _sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
}
}
-#define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz)
-static inline void
-_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
{
char *d = dst;
@@ -444,11 +360,8 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
}
}
-#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
-
-static inline void
-_sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
- __kernel_size_t n)
+static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
{
const char *s = src;
volatile void __iomem *d = dst;
@@ -460,10 +373,8 @@ _sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
}
}
-#define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz)
-
-static inline void
-_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
{
const char *s = src;
volatile void __iomem *d = dst;
@@ -475,8 +386,6 @@ _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
}
}
-#define memcpy_toio(d,s,sz) _memcpy_toio(d,s,sz)
-
#define mmiowb()
#ifdef __KERNEL__
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index a564817bbc2e..812fd08f3e62 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -119,6 +119,8 @@ extern struct task_struct *last_task_used_math;
int do_mathemu(struct pt_regs *regs, struct task_struct *fpt);
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
+
extern void (*sparc_idle)(void);
#endif
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 7028fe1a7c04..6924bdefe148 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -216,6 +216,7 @@ unsigned long get_wchan(struct task_struct *task);
"nop\n\t" \
".previous" \
::: "memory")
+#define cpu_relax_lowlatency() cpu_relax()
/* Prefetch support. This is tuned for UltraSPARC-III and later.
* UltraSPARC-I will treat these as nops, and UltraSPARC-II has
diff --git a/arch/sparc/include/asm/scatterlist.h b/arch/sparc/include/asm/scatterlist.h
deleted file mode 100644
index 92bb638313f8..000000000000
--- a/arch/sparc/include/asm/scatterlist.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _SPARC_SCATTERLIST_H
-#define _SPARC_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* !(_SPARC_SCATTERLIST_H) */
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
index 816d8202fa0a..dea1cfa2122b 100644
--- a/arch/sparc/include/asm/tlbflush_64.h
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -34,6 +34,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
{
}
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
void flush_tlb_pending(void);
@@ -48,11 +50,6 @@ void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifndef CONFIG_SMP
-#define flush_tlb_kernel_range(start,end) \
-do { flush_tsb_kernel_range(start,end); \
- __flush_tlb_kernel_range(start,end); \
-} while (0)
-
static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
{
__flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
@@ -63,11 +60,6 @@ static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vad
void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
-#define flush_tlb_kernel_range(start, end) \
-do { flush_tsb_kernel_range(start,end); \
- smp_flush_tlb_kernel_range(start, end); \
-} while (0)
-
#define global_flush_tlb_page(mm, vaddr) \
smp_flush_tlb_page(mm, vaddr)
diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h
index 42f2bca1d338..c842a89b1190 100644
--- a/arch/sparc/include/uapi/asm/unistd.h
+++ b/arch/sparc/include/uapi/asm/unistd.h
@@ -411,8 +411,11 @@
#define __NR_sched_setattr 343
#define __NR_sched_getattr 344
#define __NR_renameat2 345
+#define __NR_seccomp 346
+#define __NR_getrandom 347
+#define __NR_memfd_create 348
-#define NR_syscalls 346
+#define NR_syscalls 349
/* Bitmask values returned from kern_features system call. */
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index e01d75d40329..66dacd56bb10 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -1336,7 +1336,7 @@ int ldc_connect(struct ldc_channel *lp)
if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) ||
!(lp->flags & LDC_FLAG_REGISTERED_QUEUES) ||
lp->hs_state != LDC_HS_OPEN)
- err = -EINVAL;
+ err = ((lp->hs_state > LDC_HS_OPEN) ? 0 : -EINVAL);
else
err = start_handshake(lp);
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index a1a4400d4025..99632a87e697 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -906,29 +906,85 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
smp_fill_in_sib_core_maps();
}
-static ssize_t mdesc_read(struct file *file, char __user *buf,
- size_t len, loff_t *offp)
+/* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
+ * opened. Hold this reference until /dev/mdesc is closed to ensure
+ * mdesc data structure is not released underneath us. Store the
+ * pointer to mdesc structure in private_data for read and seek to use
+ */
+static int mdesc_open(struct inode *inode, struct file *file)
{
struct mdesc_handle *hp = mdesc_grab();
- int err;
if (!hp)
return -ENODEV;
- err = hp->handle_size;
- if (len < hp->handle_size)
- err = -EMSGSIZE;
- else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
- err = -EFAULT;
- mdesc_release(hp);
+ file->private_data = hp;
+
+ return 0;
+}
+
+static ssize_t mdesc_read(struct file *file, char __user *buf,
+ size_t len, loff_t *offp)
+{
+ struct mdesc_handle *hp = file->private_data;
+ unsigned char *mdesc;
+ int bytes_left, count = len;
+
+ if (*offp >= hp->handle_size)
+ return 0;
+
+ bytes_left = hp->handle_size - *offp;
+ if (count > bytes_left)
+ count = bytes_left;
+
+ mdesc = (unsigned char *)&hp->mdesc;
+ mdesc += *offp;
+ if (!copy_to_user(buf, mdesc, count)) {
+ *offp += count;
+ return count;
+ } else {
+ return -EFAULT;
+ }
+}
- return err;
+static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct mdesc_handle *hp;
+
+ switch (whence) {
+ case SEEK_CUR:
+ offset += file->f_pos;
+ break;
+ case SEEK_SET:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ hp = file->private_data;
+ if (offset > hp->handle_size)
+ return -EINVAL;
+ else
+ file->f_pos = offset;
+
+ return offset;
+}
+
+/* mdesc_close() - /dev/mdesc is being closed, release the reference to
+ * mdesc structure.
+ */
+static int mdesc_close(struct inode *inode, struct file *file)
+{
+ mdesc_release(file->private_data);
+ return 0;
}
static const struct file_operations mdesc_fops = {
- .read = mdesc_read,
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
+ .open = mdesc_open,
+ .read = mdesc_read,
+ .llseek = mdesc_llseek,
+ .release = mdesc_close,
+ .owner = THIS_MODULE,
};
static struct miscdevice mdesc_misc = {
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index 337094556916..5b1151dcba13 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -130,7 +130,6 @@ static inline unsigned int get_nmi_count(int cpu)
static __init void nmi_cpu_busy(void *data)
{
- local_irq_enable_in_hardirq();
while (endflag == 0)
mb();
}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 539babf00bb2..b36365f49478 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -432,6 +432,11 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
node->full_name);
return;
}
+
+ if (ofpci_verbose)
+ printk(" Bridge bus range [%u --> %u]\n",
+ busrange[0], busrange[1]);
+
ranges = of_get_property(node, "ranges", &len);
simba = 0;
if (ranges == NULL) {
@@ -451,6 +456,10 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
bus->bridge_ctl = 0;
+ if (ofpci_verbose)
+ printk(" Bridge ranges[%p] simba[%d]\n",
+ ranges, simba);
+
/* parse ranges property, or cook one up by hand for Simba */
/* PCI #address-cells == 3 and #size-cells == 2 always */
res = &dev->resource[PCI_BRIDGE_RESOURCES];
@@ -468,10 +477,29 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
+ u64 start;
+
+ if (ofpci_verbose)
+ printk(" RAW Range[%08x:%08x:%08x:%08x:%08x:%08x:"
+ "%08x:%08x]\n",
+ ranges[0], ranges[1], ranges[2], ranges[3],
+ ranges[4], ranges[5], ranges[6], ranges[7]);
+
flags = pci_parse_of_flags(ranges[0]);
size = GET_64BIT(ranges, 6);
if (flags == 0 || size == 0)
continue;
+
+ /* On PCI-Express systems, PCI bridges that have no devices downstream
+ * have a bogus size value where the first 32-bit cell is 0xffffffff.
+ * This results in a bogus range where start + size overflows.
+ *
+ * Just skip these otherwise the kernel will complain when the resource
+ * tries to be claimed.
+ */
+ if (size >> 32 == 0xffffffff)
+ continue;
+
if (flags & IORESOURCE_IO) {
res = bus->resource[0];
if (res->flags) {
@@ -490,8 +518,13 @@ static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
res->flags = flags;
- region.start = GET_64BIT(ranges, 1);
+ region.start = start = GET_64BIT(ranges, 1);
region.end = region.start + size - 1;
+
+ if (ofpci_verbose)
+ printk(" Using flags[%08x] start[%016llx] size[%016llx]\n",
+ flags, start, size);
+
pcibios_bus_to_resource(dev->bus, res, &region);
}
after_ranges:
@@ -584,6 +617,36 @@ static void pci_bus_register_of_sysfs(struct pci_bus *bus)
pci_bus_register_of_sysfs(child_bus);
}
+static void pci_claim_bus_resources(struct pci_bus *bus)
+{
+ struct pci_bus *child_bus;
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if (r->parent || !r->start || !r->flags)
+ continue;
+
+ if (ofpci_verbose)
+ printk("PCI: Claiming %s: "
+ "Resource %d: %016llx..%016llx [%x]\n",
+ pci_name(dev), i,
+ (unsigned long long)r->start,
+ (unsigned long long)r->end,
+ (unsigned int)r->flags);
+
+ pci_claim_resource(dev, i);
+ }
+ }
+
+ list_for_each_entry(child_bus, &bus->children, node)
+ pci_claim_bus_resources(child_bus);
+}
+
struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
struct device *parent)
{
@@ -614,6 +677,8 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
pci_bus_add_devices(bus);
pci_bus_register_of_sysfs(bus);
+ pci_claim_bus_resources(bus);
+
return bus;
}
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 8efd33753ad3..d35c490a91cb 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1671,9 +1671,12 @@ static bool __init supported_pmu(void)
static int __init init_hw_perf_events(void)
{
+ int err;
+
pr_info("Performance events: ");
- if (!supported_pmu()) {
+ err = pcr_arch_init();
+ if (err || !supported_pmu()) {
pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
return 0;
}
@@ -1685,7 +1688,7 @@ static int __init init_hw_perf_events(void)
return 0;
}
-early_initcall(init_hw_perf_events);
+pure_initcall(init_hw_perf_events);
void perf_callchain_kernel(struct perf_callchain_entry *entry,
struct pt_regs *regs)
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index 027e09986194..0be7bf978cb1 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -312,6 +312,9 @@ static void __global_pmu_self(int this_cpu)
struct global_pmu_snapshot *pp;
int i, num;
+ if (!pcr_ops)
+ return;
+
pp = &global_cpu_snapshot[this_cpu].pmu;
num = 1;
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 7958242d63c5..b3a5d81b20f0 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -68,7 +68,7 @@ void smp_store_cpu_info(int id)
mid = cpu_get_hwmid(cpu_node);
if (mid < 0) {
- printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node);
+ printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08x", id, cpu_node);
mid = 0;
}
cpu_data(id).mid = mid;
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 41aa2478f3ca..f7ba87543e5f 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1383,7 +1383,6 @@ void __cpu_die(unsigned int cpu)
void __init smp_cpus_done(unsigned int max_cpus)
{
- pcr_arch_init();
}
void smp_send_reschedule(int cpu)
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index 85fe9b1087cd..6a873c344bc0 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -86,4 +86,4 @@ sys_call_table:
/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
/*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
/*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-/*345*/ .long sys_renameat2
+/*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 33ecba2826ea..d9151b6490d8 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -87,7 +87,7 @@ sys_call_table32:
/*330*/ .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
- .word sys32_renameat2
+ .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
#endif /* CONFIG_COMPAT */
@@ -166,4 +166,4 @@ sys_call_table:
/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
- .word sys_renameat2
+ .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index c5c61b3c6b56..32b61d1b6379 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -166,7 +166,7 @@ unsigned long safe_compute_effective_address(struct pt_regs *regs,
/* This is just to make gcc think panic does return... */
static void unaligned_panic(char *str)
{
- panic(str);
+ panic("%s", str);
}
/* una_asm.S */
diff --git a/arch/sparc/lib/PeeCeeI.c b/arch/sparc/lib/PeeCeeI.c
index 6529f8657597..e6d183675990 100644
--- a/arch/sparc/lib/PeeCeeI.c
+++ b/arch/sparc/lib/PeeCeeI.c
@@ -15,7 +15,7 @@ void outsb(unsigned long __addr, const void *src, unsigned long count)
const u8 *p = src;
while (count--)
- outb(*p++, addr);
+ __raw_writeb(*p++, addr);
}
EXPORT_SYMBOL(outsb);
@@ -93,21 +93,21 @@ void insb(unsigned long __addr, void *dst, unsigned long count)
u8 *pb = dst;
while ((((unsigned long)pb) & 0x3) && count--)
- *pb++ = inb(addr);
+ *pb++ = __raw_readb(addr);
pi = (u32 *)pb;
while (count >= 4) {
u32 w;
- w = (inb(addr) << 24);
- w |= (inb(addr) << 16);
- w |= (inb(addr) << 8);
- w |= (inb(addr) << 0);
+ w = (__raw_readb(addr) << 24);
+ w |= (__raw_readb(addr) << 16);
+ w |= (__raw_readb(addr) << 8);
+ w |= (__raw_readb(addr) << 0);
*pi++ = w;
count -= 4;
}
pb = (u8 *)pi;
while (count--)
- *pb++ = inb(addr);
+ *pb++ = __raw_readb(addr);
}
}
EXPORT_SYMBOL(insb);
@@ -121,21 +121,21 @@ void insw(unsigned long __addr, void *dst, unsigned long count)
u32 *pi;
if (((unsigned long)ps) & 0x2) {
- *ps++ = le16_to_cpu(inw(addr));
+ *ps++ = __raw_readw(addr);
count--;
}
pi = (u32 *)ps;
while (count >= 2) {
u32 w;
- w = (le16_to_cpu(inw(addr)) << 16);
- w |= (le16_to_cpu(inw(addr)) << 0);
+ w = __raw_readw(addr) << 16;
+ w |= __raw_readw(addr) << 0;
*pi++ = w;
count -= 2;
}
ps = (u16 *)pi;
if (count)
- *ps = le16_to_cpu(inw(addr));
+ *ps = __raw_readw(addr);
}
}
EXPORT_SYMBOL(insw);
@@ -148,7 +148,7 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
if ((((unsigned long)dst) & 0x3) == 0) {
u32 *pi = dst;
while (count--)
- *pi++ = le32_to_cpu(inl(addr));
+ *pi++ = __raw_readl(addr);
} else {
u32 l = 0, l2, *pi;
u16 *ps;
@@ -158,11 +158,11 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x2:
ps = dst;
count -= 1;
- l = le32_to_cpu(inl(addr));
+ l = __raw_readl(addr);
*ps++ = l;
pi = (u32 *)ps;
while (count--) {
- l2 = le32_to_cpu(inl(addr));
+ l2 = __raw_readl(addr);
*pi++ = (l << 16) | (l2 >> 16);
l = l2;
}
@@ -173,13 +173,13 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x1:
pb = dst;
count -= 1;
- l = le32_to_cpu(inl(addr));
+ l = __raw_readl(addr);
*pb++ = l >> 24;
ps = (u16 *)pb;
*ps++ = ((l >> 8) & 0xffff);
pi = (u32 *)ps;
while (count--) {
- l2 = le32_to_cpu(inl(addr));
+ l2 = __raw_readl(addr);
*pi++ = (l << 24) | (l2 >> 8);
l = l2;
}
@@ -190,11 +190,11 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
case 0x3:
pb = (u8 *)dst;
count -= 1;
- l = le32_to_cpu(inl(addr));
+ l = __raw_readl(addr);
*pb++ = l >> 24;
pi = (u32 *)pb;
while (count--) {
- l2 = le32_to_cpu(inl(addr));
+ l2 = __raw_readl(addr);
*pi++ = (l << 8) | (l2 >> 24);
l = l2;
}
diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S
index 3ad6cbdc2163..0b0ed4d34219 100644
--- a/arch/sparc/lib/mcount.S
+++ b/arch/sparc/lib/mcount.S
@@ -24,10 +24,7 @@ mcount:
#ifdef CONFIG_DYNAMIC_FTRACE
/* Do nothing, the retl/nop below is all we need. */
#else
- sethi %hi(function_trace_stop), %g1
- lduw [%g1 + %lo(function_trace_stop)], %g2
- brnz,pn %g2, 2f
- sethi %hi(ftrace_trace_function), %g1
+ sethi %hi(ftrace_trace_function), %g1
sethi %hi(ftrace_stub), %g2
ldx [%g1 + %lo(ftrace_trace_function)], %g1
or %g2, %lo(ftrace_stub), %g2
@@ -80,11 +77,8 @@ ftrace_stub:
.globl ftrace_caller
.type ftrace_caller,#function
ftrace_caller:
- sethi %hi(function_trace_stop), %g1
mov %i7, %g2
- lduw [%g1 + %lo(function_trace_stop)], %g1
- brnz,pn %g1, ftrace_stub
- mov %fp, %g3
+ mov %fp, %g3
save %sp, -176, %sp
mov %g2, %o1
mov %g2, %l0
diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c
index aa4d55b0bdf0..5ce8f2f64604 100644
--- a/arch/sparc/math-emu/math_32.c
+++ b/arch/sparc/math-emu/math_32.c
@@ -499,7 +499,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs)
case 0: fsr = *pfsr;
if (IR == -1) IR = 2;
/* fcc is always fcc0 */
- fsr &= ~0xc00; fsr |= (IR << 10); break;
+ fsr &= ~0xc00; fsr |= (IR << 10);
*pfsr = fsr;
break;
case 1: rd->s = IR; break;
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 16b58ff11e65..98ac8e80adae 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -22,6 +22,7 @@
#include <linux/kprobes.h>
#include <linux/cache.h>
#include <linux/sort.h>
+#include <linux/ioport.h>
#include <linux/percpu.h>
#include <linux/memblock.h>
#include <linux/mmzone.h>
@@ -351,6 +352,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *
mm = vma->vm_mm;
+ /* Don't insert a non-valid PTE into the TSB, we'll deadlock. */
+ if (!pte_accessible(mm, pte))
+ return;
+
spin_lock_irqsave(&mm->context.lock, flags);
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
@@ -2619,6 +2624,10 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
pte = pmd_val(entry);
+ /* Don't insert a non-valid PMD into the TSB, we'll deadlock. */
+ if (!(pte & _PAGE_VALID))
+ return;
+
/* We are fabricating 8MB pages using 4MB real hw pages. */
pte |= (addr & (1UL << REAL_HPAGE_SHIFT));
@@ -2699,3 +2708,90 @@ void hugetlb_setup(struct pt_regs *regs)
}
}
#endif
+
+static struct resource code_resource = {
+ .name = "Kernel code",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource data_resource = {
+ .name = "Kernel data",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource bss_resource = {
+ .name = "Kernel bss",
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static inline resource_size_t compute_kern_paddr(void *addr)
+{
+ return (resource_size_t) (addr - KERNBASE + kern_base);
+}
+
+static void __init kernel_lds_init(void)
+{
+ code_resource.start = compute_kern_paddr(_text);
+ code_resource.end = compute_kern_paddr(_etext - 1);
+ data_resource.start = compute_kern_paddr(_etext);
+ data_resource.end = compute_kern_paddr(_edata - 1);
+ bss_resource.start = compute_kern_paddr(__bss_start);
+ bss_resource.end = compute_kern_paddr(_end - 1);
+}
+
+static int __init report_memory(void)
+{
+ int i;
+ struct resource *res;
+
+ kernel_lds_init();
+
+ for (i = 0; i < pavail_ents; i++) {
+ res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+
+ if (!res) {
+ pr_warn("Failed to allocate source.\n");
+ break;
+ }
+
+ res->name = "System RAM";
+ res->start = pavail[i].phys_addr;
+ res->end = pavail[i].phys_addr + pavail[i].reg_size - 1;
+ res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+
+ if (insert_resource(&iomem_resource, res) < 0) {
+ pr_warn("Resource insertion failed.\n");
+ break;
+ }
+
+ insert_resource(res, &code_resource);
+ insert_resource(res, &data_resource);
+ insert_resource(res, &bss_resource);
+ }
+
+ return 0;
+}
+device_initcall(report_memory);
+
+#ifdef CONFIG_SMP
+#define do_flush_tlb_kernel_range smp_flush_tlb_kernel_range
+#else
+#define do_flush_tlb_kernel_range __flush_tlb_kernel_range
+#endif
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) {
+ if (start < LOW_OBP_ADDRESS) {
+ flush_tsb_kernel_range(start, LOW_OBP_ADDRESS);
+ do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS);
+ }
+ if (end > HI_OBP_ADDRESS) {
+ flush_tsb_kernel_range(end, HI_OBP_ADDRESS);
+ do_flush_tlb_kernel_range(end, HI_OBP_ADDRESS);
+ }
+ } else {
+ flush_tsb_kernel_range(start, end);
+ do_flush_tlb_kernel_range(start, end);
+ }
+}
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 892a102671ad..1f76c22a6a75 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -354,7 +354,7 @@ do { *prog++ = BR_OPC | WDISP22(OFF); \
* emit_jump() calls with adjusted offsets.
*/
-void bpf_jit_compile(struct sk_filter *fp)
+void bpf_jit_compile(struct bpf_prog *fp)
{
unsigned int cleanup_addr, proglen, oldproglen = 0;
u32 temp[8], *prog, *func, seen = 0, pass;
@@ -808,7 +808,7 @@ out:
return;
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited)
module_free(NULL, fp->bpf_func);
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 4f3006b600e3..a3ffe2dd4832 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -128,7 +128,6 @@ config TILEGX
select SPARSE_IRQ
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
select HAVE_FUNCTION_TRACER
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_DYNAMIC_FTRACE
select HAVE_FTRACE_MCOUNT_RECORD
@@ -192,6 +191,8 @@ source "kernel/Kconfig.hz"
config KEXEC
bool "kexec system call"
+ select CRYPTO
+ select CRYPTO_SHA256
---help---
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 730e40d9cf62..91de7dd7427f 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -170,7 +170,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_ATA_OVER_ETH=m
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig
index 80fc32ed0491..c7702b7ab7a5 100644
--- a/arch/tile/configs/tilepro_defconfig
+++ b/arch/tile/configs/tilepro_defconfig
@@ -301,7 +301,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_ATA_OVER_ETH=m
CONFIG_RAID_ATTRS=m
-CONFIG_SCSI_TGT=m
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index ffd4493efc78..c14e36f008c8 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -267,8 +267,7 @@ static inline int is_compat_task(void)
return current_thread_info()->status & TS_COMPAT;
}
-extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
- siginfo_t *info, sigset_t *set,
+extern int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);
/* Compat syscalls. */
diff --git a/arch/tile/include/asm/hardwall.h b/arch/tile/include/asm/hardwall.h
index 2f572b6b7bc2..44d2765bde2b 100644
--- a/arch/tile/include/asm/hardwall.h
+++ b/arch/tile/include/asm/hardwall.h
@@ -23,7 +23,7 @@
struct proc_dir_entry;
#ifdef CONFIG_HARDWALL
void proc_tile_hardwall_init(struct proc_dir_entry *root);
-int proc_pid_hardwall(struct task_struct *task, char *buffer);
+int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task);
#else
static inline void proc_tile_hardwall_init(struct proc_dir_entry *root) {}
#endif
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index 672768008618..a213a8d84a95 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -39,12 +39,6 @@
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
/*
- * We do define AT_SYSINFO_EHDR to support vDSO,
- * but don't use the gate mechanism.
- */
-#define __HAVE_ARCH_GATE_AREA 1
-
-/*
* If the Kconfig doesn't specify, set a maximum zone order that
* is enough so that we can create huge pages from small pages given
* the respective sizes of the two page types. See <linux/mmzone.h>.
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 42323636c459..dd4f9f17e30a 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -266,6 +266,8 @@ static inline void cpu_relax(void)
barrier();
}
+#define cpu_relax_lowlatency() cpu_relax()
+
/* Info on this processor (see fs/proc/cpuinfo.c) */
struct seq_operations;
extern const struct seq_operations cpuinfo_op;
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index 19c04b5ce408..8c5abf2e4794 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -190,18 +190,18 @@ static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
return (void __user *) sp;
}
-int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
unsigned long restorer;
struct compat_rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int usig;
- frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+ frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ goto err;
usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -210,12 +210,12 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
: sig;
/* Always write at least the signal number for the stack backtracer. */
- if (ka->sa.sa_flags & SA_SIGINFO) {
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
/* At sigreturn time, restore the callee-save registers too. */
- err |= copy_siginfo_to_user32(&frame->info, info);
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
regs->flags |= PT_FLAGS_RESTORE_REGS;
} else {
- err |= __put_user(info->si_signo, &frame->info.si_signo);
+ err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
}
/* Create the ucontext. */
@@ -226,11 +226,11 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ goto err;
restorer = VDSO_SYM(&__vdso_rt_sigreturn);
- if (ka->sa.sa_flags & SA_RESTORER)
- restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
/*
* Set up registers for signal handler.
@@ -239,7 +239,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c).
*/
- regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
+ regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer;
@@ -249,7 +249,8 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->flags |= PT_FLAGS_CALLER_SAVES;
return 0;
-give_sigsegv:
- signal_fault("bad setup frame", regs, frame, sig);
+err:
+ trace_unhandled_signal("bad sigreturn frame", regs,
+ (unsigned long)frame, SIGSEGV);
return -EFAULT;
}
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 531f4c365351..aca6000bca75 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -947,15 +947,15 @@ static void hardwall_remove_proc(struct hardwall_info *info)
remove_proc_entry(buf, info->type->proc_dir);
}
-int proc_pid_hardwall(struct task_struct *task, char *buffer)
+int proc_pid_hardwall(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
{
int i;
int n = 0;
for (i = 0; i < HARDWALL_TYPES; ++i) {
struct hardwall_info *info = task->thread.hardwall[i].info;
if (info)
- n += sprintf(&buffer[n], "%s: %d\n",
- info->type->name, info->id);
+ seq_printf(m, "%s: %d\n", info->type->name, info->id);
}
return n;
}
diff --git a/arch/tile/kernel/mcount_64.S b/arch/tile/kernel/mcount_64.S
index 70d7bb0c4d8f..3c2b8d5e1d1a 100644
--- a/arch/tile/kernel/mcount_64.S
+++ b/arch/tile/kernel/mcount_64.S
@@ -77,15 +77,6 @@ STD_ENDPROC(__mcount)
.align 64
STD_ENTRY(ftrace_caller)
- moveli r11, hw2_last(function_trace_stop)
- { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr }
- { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 }
- ld r11, r11
- beqz r11, 1f
- jrp r12
-
-1:
- { move r10, lr; move lr, r12 }
MCOUNT_SAVE_REGS
/* arg1: self return address */
@@ -119,15 +110,6 @@ STD_ENDPROC(ftrace_caller)
.align 64
STD_ENTRY(__mcount)
- moveli r11, hw2_last(function_trace_stop)
- { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr }
- { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 }
- ld r11, r11
- beqz r11, 1f
- jrp r12
-
-1:
- { move r10, lr; move lr, r12 }
{
moveli r11, hw2_last(ftrace_trace_function)
moveli r13, hw2_last(ftrace_stub)
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index 4918d91bc3a6..d19b13e3a59f 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -58,7 +58,7 @@ void *module_alloc(unsigned long size)
area->nr_pages = npages;
area->pages = pages;
- if (map_vm_area(area, prot_rwx, &pages)) {
+ if (map_vm_area(area, prot_rwx, pages)) {
vunmap(area->addr);
goto error;
}
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index d1d026f01267..7c2fecc52177 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -153,18 +153,18 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
return (void __user *) sp;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
unsigned long restorer;
struct rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int usig;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
+ goto err;
usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -173,12 +173,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
: sig;
/* Always write at least the signal number for the stack backtracer. */
- if (ka->sa.sa_flags & SA_SIGINFO) {
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
/* At sigreturn time, restore the callee-save registers too. */
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->flags |= PT_FLAGS_RESTORE_REGS;
} else {
- err |= __put_user(info->si_signo, &frame->info.si_signo);
+ err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
}
/* Create the ucontext. */
@@ -189,11 +189,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto give_sigsegv;
+ goto err;
restorer = VDSO_SYM(&__vdso_rt_sigreturn);
- if (ka->sa.sa_flags & SA_RESTORER)
- restorer = (unsigned long) ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ restorer = (unsigned long) ksig->ka.sa.sa_restorer;
/*
* Set up registers for signal handler.
@@ -202,7 +202,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c).
*/
- regs->pc = (unsigned long) ka->sa.sa_handler;
+ regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = (unsigned long) frame;
regs->lr = restorer;
@@ -212,8 +212,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->flags |= PT_FLAGS_CALLER_SAVES;
return 0;
-give_sigsegv:
- signal_fault("bad setup frame", regs, frame, sig);
+err:
+ trace_unhandled_signal("bad sigreturn frame", regs,
+ (unsigned long)frame, SIGSEGV);
return -EFAULT;
}
@@ -221,9 +222,7 @@ give_sigsegv:
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka,
- struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int ret;
@@ -238,7 +237,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[0] = -EINTR;
break;
}
@@ -254,14 +253,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
/* Set up the stack frame */
#ifdef CONFIG_COMPAT
if (is_compat_task())
- ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = compat_setup_rt_frame(ksig, oldset, regs);
else
#endif
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret)
- return;
- signal_delivered(sig, info, ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ ret = setup_rt_frame(ksig, oldset, regs);
+
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -271,9 +268,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
*/
void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
/*
* i386 will check if we're coming from kernel mode and bail out
@@ -282,10 +277,9 @@ void do_signal(struct pt_regs *regs)
* helpful, we can reinstate the check on "!user_mode(regs)".
*/
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
+ if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
goto done;
}
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index 462dcd0c1700..d8fbc289e680 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -260,9 +260,8 @@ void update_vsyscall_tz(void)
void update_vsyscall(struct timekeeper *tk)
{
- struct timespec wall_time = tk_xtime(tk);
struct timespec *wtm = &tk->wall_to_monotonic;
- struct clocksource *clock = tk->clock;
+ struct clocksource *clock = tk->tkr.clock;
if (clock != &cycle_counter_cs)
return;
@@ -270,13 +269,13 @@ void update_vsyscall(struct timekeeper *tk)
/* Userspace gettimeofday will spin while this value is odd. */
++vdso_data->tb_update_count;
smp_wmb();
- vdso_data->xtime_tod_stamp = clock->cycle_last;
- vdso_data->xtime_clock_sec = wall_time.tv_sec;
- vdso_data->xtime_clock_nsec = wall_time.tv_nsec;
+ vdso_data->xtime_tod_stamp = tk->tkr.cycle_last;
+ vdso_data->xtime_clock_sec = tk->xtime_sec;
+ vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec;
vdso_data->wtom_clock_sec = wtm->tv_sec;
vdso_data->wtom_clock_nsec = wtm->tv_nsec;
- vdso_data->mult = clock->mult;
- vdso_data->shift = clock->shift;
+ vdso_data->mult = tk->tkr.mult;
+ vdso_data->shift = tk->tkr.shift;
smp_wmb();
++vdso_data->tb_update_count;
}
diff --git a/arch/tile/kernel/vdso.c b/arch/tile/kernel/vdso.c
index 1533af24106e..5bc51d7dfdcb 100644
--- a/arch/tile/kernel/vdso.c
+++ b/arch/tile/kernel/vdso.c
@@ -121,21 +121,6 @@ const char *arch_vma_name(struct vm_area_struct *vma)
return NULL;
}
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long address)
-{
- return 0;
-}
-
-int in_gate_area_no_mm(unsigned long address)
-{
- return 0;
-}
-
int setup_vdso_pages(void)
{
struct page **pagelist;
diff --git a/arch/tile/kernel/vdso/vgettimeofday.c b/arch/tile/kernel/vdso/vgettimeofday.c
index 51ec8e46f5f9..e933fb9fbf5c 100644
--- a/arch/tile/kernel/vdso/vgettimeofday.c
+++ b/arch/tile/kernel/vdso/vgettimeofday.c
@@ -83,10 +83,11 @@ int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
if (count & 1)
continue;
- cycles = (get_cycles() - vdso_data->xtime_tod_stamp);
- ns = (cycles * vdso_data->mult) >> vdso_data->shift;
sec = vdso_data->xtime_clock_sec;
- ns += vdso_data->xtime_clock_nsec;
+ cycles = get_cycles() - vdso_data->xtime_tod_stamp;
+ ns = (cycles * vdso_data->mult) + vdso_data->xtime_clock_nsec;
+ ns >>= vdso_data->shift;
+
if (ns >= NSEC_PER_SEC) {
ns -= NSEC_PER_SEC;
sec += 1;
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index a5e4b6068213..7bd64aa2e94a 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -21,6 +21,7 @@ generic-y += param.h
generic-y += pci.h
generic-y += percpu.h
generic-y += preempt.h
+generic-y += scatterlist.h
generic-y += sections.h
generic-y += switch_to.h
generic-y += topology.h
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h
index 5ff53d9185f7..71c5d132062a 100644
--- a/arch/um/include/asm/page.h
+++ b/arch/um/include/asm/page.h
@@ -119,4 +119,9 @@ extern unsigned long uml_physmem;
#include <asm-generic/getorder.h>
#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_X86_32
+#define __HAVE_ARCH_GATE_AREA 1
+#endif
+
#endif /* __UM_PAGE_H */
diff --git a/arch/um/include/shared/frame_kern.h b/arch/um/include/shared/frame_kern.h
index f2ca5702a4e2..a5cde5c433b4 100644
--- a/arch/um/include/shared/frame_kern.h
+++ b/arch/um/include/shared/frame_kern.h
@@ -6,14 +6,10 @@
#ifndef __FRAME_KERN_H_
#define __FRAME_KERN_H_
-extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
- struct k_sigaction *ka,
- struct pt_regs *regs,
- sigset_t *mask);
-extern int setup_signal_stack_si(unsigned long stack_top, int sig,
- struct k_sigaction *ka,
- struct pt_regs *regs, struct siginfo *info,
- sigset_t *mask);
+extern int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *mask);
+extern int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *mask);
#endif
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index f57e02e7910f..4f60e4aad790 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -18,8 +18,7 @@ EXPORT_SYMBOL(unblock_signals);
/*
* OK, we're invoking a handler
*/
-static void handle_signal(struct pt_regs *regs, unsigned long signr,
- struct k_sigaction *ka, struct siginfo *info)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
int singlestep = 0;
@@ -39,7 +38,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
PT_REGS_SYSCALL_RET(regs) = -EINTR;
break;
}
@@ -52,32 +51,28 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
}
sp = PT_REGS_SP(regs);
- if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
+ if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
- if (!(ka->sa.sa_flags & SA_SIGINFO))
- err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
+ if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
+ err = setup_signal_stack_sc(sp, ksig, regs, oldset);
else
#endif
- err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
+ err = setup_signal_stack_si(sp, ksig, regs, oldset);
- if (err)
- force_sigsegv(signr, current);
- else
- signal_delivered(signr, info, ka, regs, singlestep);
+ signal_setup_done(err, ksig, singlestep);
}
static int kern_do_signal(struct pt_regs *regs)
{
- struct k_sigaction ka_copy;
- struct siginfo info;
- int sig, handled_sig = 0;
+ struct ksignal ksig;
+ int handled_sig = 0;
- while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
+ while (get_signal(&ksig)) {
handled_sig = 1;
/* Whee! Actually deliver the signal. */
- handle_signal(regs, sig, &ka_copy, &info);
+ handle_signal(&ksig, regs);
}
/* Did we come from a system call? */
diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h
index 4eaa42167667..8d21b7adf26b 100644
--- a/arch/unicore32/include/asm/processor.h
+++ b/arch/unicore32/include/asm/processor.h
@@ -71,6 +71,7 @@ extern void release_thread(struct task_struct *);
unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 254adeecc61a..438dd2edba4f 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -272,7 +272,7 @@ void __init puv3_core_init(void)
platform_device_register_simple("PKUnity-v3-UART", 1,
puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
- platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+ platform_device_register_resndata(NULL, "musb_hdrc", -1,
puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
&puv3_usb_plat, sizeof(puv3_usb_plat));
}
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
index 0c6618e71897..46ebfdccbc31 100644
--- a/arch/unicore32/kernel/puv3-nb0916.c
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -112,13 +112,13 @@ int __init mach_nb0916_init(void)
platform_device_register_simple("PKUnity-v3-I2C", -1,
puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
- platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+ platform_device_register_data(NULL, "pwm-backlight", -1,
&nb0916_backlight_data, sizeof(nb0916_backlight_data));
- platform_device_register_data(&platform_bus, "gpio-keys", -1,
+ platform_device_register_data(NULL, "gpio-keys", -1,
&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
- platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+ platform_device_register_resndata(NULL, "physmap-flash", -1,
&physmap_flash_resource, 1,
&physmap_flash_data, sizeof(physmap_flash_data));
diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c
index 6905f0ebdc77..780d77388dec 100644
--- a/arch/unicore32/kernel/signal.c
+++ b/arch/unicore32/kernel/signal.c
@@ -238,10 +238,10 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
return 0;
}
-static int setup_frame(int usig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
- struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
+ struct sigframe __user *frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
int err = 0;
if (!frame)
@@ -254,29 +254,29 @@ static int setup_frame(int usig, struct k_sigaction *ka,
err |= setup_sigframe(frame, regs, set);
if (err == 0)
- err |= setup_return(regs, ka, frame->retcode, frame, usig);
+ err |= setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
return err;
}
-static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame =
- get_sigframe(ka, regs, sizeof(*frame));
+ get_sigframe(&ksig->ka, regs, sizeof(*frame));
int err = 0;
if (!frame)
return 1;
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= __put_user(0, &frame->sig.uc.uc_flags);
err |= __put_user(NULL, &frame->sig.uc.uc_link);
err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp);
err |= setup_sigframe(&frame->sig, regs, set);
if (err == 0)
- err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
+ err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
if (err == 0) {
/*
@@ -299,13 +299,13 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
/*
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, struct k_sigaction *ka,
- siginfo_t *info, struct pt_regs *regs, int syscall)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
+ int syscall)
{
struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save();
- int usig = sig;
+ int usig = ksig->sig;
int ret;
/*
@@ -318,7 +318,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
regs->UCreg_00 = -EINTR;
break;
case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
+ if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->UCreg_00 = -EINTR;
break;
}
@@ -338,22 +338,17 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
/*
* Set up the stack frame
*/
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(usig, ka, info, oldset, regs);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ ret = setup_rt_frame(ksig, oldset, regs);
else
- ret = setup_frame(usig, ka, oldset, regs);
+ ret = setup_frame(ksig, oldset, regs);
/*
* Check that the resulting registers are actually sane.
*/
ret |= !valid_user_regs(regs);
- if (ret != 0) {
- force_sigsegv(sig, tsk);
- return;
- }
-
- signal_delivered(sig, info, ka, regs, 0);
+ signal_setup_done(ret, ksig, 0);
}
/*
@@ -367,9 +362,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/
static void do_signal(struct pt_regs *regs, int syscall)
{
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
+ struct ksignal ksig;
/*
* We want the common case to go fast, which
@@ -380,9 +373,8 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs))
return;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- handle_signal(signr, &ka, &info, regs, syscall);
+ if (get_signsl(&ksig)) {
+ handle_signal(&ksig, regs, syscall);
return;
}
diff --git a/arch/x86/Kbuild b/arch/x86/Kbuild
index e5287d8517aa..61b6d51866f8 100644
--- a/arch/x86/Kbuild
+++ b/arch/x86/Kbuild
@@ -16,3 +16,7 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/
obj-y += platform/
obj-y += net/
+
+ifeq ($(CONFIG_X86_64),y)
+obj-$(CONFIG_KEXEC) += purgatory/
+endif
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d24887b645dc..5d0bf1aa9dcb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -21,6 +21,7 @@ config X86_64
### Arch settings
config X86
def_bool y
+ select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
@@ -54,7 +55,6 @@ config X86
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_GRAPH_FP_TEST
- select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_SYSCALL_TRACEPOINTS
select SYSCTL_EXCEPTION_TRACE
select HAVE_KVM
@@ -96,6 +96,7 @@ config X86
select IRQ_FORCED_THREADING
select HAVE_BPF_JIT if X86_64
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select ARCH_HAS_SG_CHAIN
select CLKEVT_I8253
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_IOMAP
@@ -109,9 +110,9 @@ config X86
select CLOCKSOURCE_WATCHDOG
select GENERIC_CLOCKEVENTS
select ARCH_CLOCKSOURCE_DATA
+ select CLOCKSOURCE_VALIDATE_LAST_CYCLE
select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
select GENERIC_TIME_VSYSCALL
- select KTIME_SCALAR if X86_32
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select HAVE_CONTEXT_TRACKING if X86_64
@@ -132,6 +133,9 @@ config X86
select GENERIC_CPU_AUTOPROBE
select HAVE_ARCH_AUDITSYSCALL
select ARCH_SUPPORTS_ATOMIC_RMW
+ select HAVE_ACPI_APEI if ACPI
+ select HAVE_ACPI_APEI_NMI if ACPI
+ select ACPI_LEGACY_TABLES_LOOKUP if ACPI
config INSTRUCTION_DECODER
def_bool y
@@ -430,6 +434,7 @@ config X86_INTEL_CE
bool "CE4100 TV platform"
depends on PCI
depends on PCI_GODIRECT
+ depends on X86_IO_APIC
depends on X86_32
depends on X86_EXTENDED_PLATFORM
select X86_REBOOTFIXUPS
@@ -836,6 +841,7 @@ config X86_IO_APIC
def_bool y
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+ select IRQ_DOMAIN
config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
bool "Reroute for broken boot IRQs"
@@ -1523,6 +1529,7 @@ config EFI
bool "EFI runtime service support"
depends on ACPI
select UCS2_STRING
+ select EFI_RUNTIME_WRAPPERS
---help---
This enables the kernel to use EFI runtime services that are
available (such as the EFI variable services).
@@ -1536,7 +1543,8 @@ config EFI
config EFI_STUB
bool "EFI stub support"
- depends on EFI
+ depends on EFI && !X86_USE_3DNOW
+ select RELOCATABLE
---help---
This kernel feature allows a bzImage to be loaded directly
by EFI firmware without the use of a bootloader.
@@ -1577,6 +1585,9 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call"
+ select BUILD_BIN2C
+ select CRYPTO
+ select CRYPTO_SHA256
---help---
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -1591,6 +1602,28 @@ config KEXEC
interface is strongly in flux, so no good recommendation can be
made.
+config KEXEC_VERIFY_SIG
+ bool "Verify kernel signature during kexec_file_load() syscall"
+ depends on KEXEC
+ ---help---
+ This option makes kernel signature verification mandatory for
+ kexec_file_load() syscall. If kernel is signature can not be
+ verified, kexec_file_load() will fail.
+
+ This option enforces signature verification at generic level.
+ One needs to enable signature verification for type of kernel
+ image being loaded to make sure it works. For example, enable
+ bzImage signature verification option to be able to load and
+ verify signatures of bzImage. Otherwise kernel loading will fail.
+
+config KEXEC_BZIMAGE_VERIFY_SIG
+ bool "Enable bzImage signature verification support"
+ depends on KEXEC_VERIFY_SIG
+ depends on SIGNED_PE_FILE_VERIFICATION
+ select SYSTEM_TRUSTED_KEYRING
+ ---help---
+ Enable bzImage signature verification support.
+
config CRASH_DUMP
bool "kernel crash dumps"
depends on X86_64 || (X86_32 && HIGHMEM)
@@ -2404,6 +2437,10 @@ config IOSF_MBI
default m
depends on PCI
+config PMC_ATOM
+ def_bool y
+ depends on PCI
+
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 33f71b01fd22..c1aa36887843 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -15,12 +15,9 @@ endif
# that way we can complain to the user if the CPU is insufficient.
#
# The -m16 option is supported by GCC >= 4.9 and clang >= 3.5. For
-# older versions of GCC, we need to play evil and unreliable tricks to
-# attempt to ensure that our asm(".code16gcc") is first in the asm
-# output.
-CODE16GCC_CFLAGS := -m32 -include $(srctree)/arch/x86/boot/code16gcc.h \
- $(call cc-option, -fno-toplevel-reorder,\
- $(call cc-option, -fno-unit-at-a-time))
+# older versions of GCC, include an *assembly* header to make sure that
+# gcc doesn't play any games behind our back.
+CODE16GCC_CFLAGS := -m32 -Wa,$(srctree)/arch/x86/boot/code16gcc.h
M16_CFLAGS := $(call cc-option, -m16, $(CODE16GCC_CFLAGS))
REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -D__KERNEL__ \
@@ -186,6 +183,14 @@ archscripts: scripts_basic
archheaders:
$(Q)$(MAKE) $(build)=arch/x86/syscalls all
+archprepare:
+ifeq ($(CONFIG_KEXEC),y)
+# Build only for 64bit. No loaders for 32bit yet.
+ ifeq ($(CONFIG_X86_64),y)
+ $(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
+ endif
+endif
+
###
# Kernel objects
diff --git a/arch/x86/boot/code16gcc.h b/arch/x86/boot/code16gcc.h
index d93e48010b61..5ff426535397 100644
--- a/arch/x86/boot/code16gcc.h
+++ b/arch/x86/boot/code16gcc.h
@@ -1,15 +1,11 @@
-/*
- * code16gcc.h
- *
- * This file is -include'd when compiling 16-bit C code.
- * Note: this asm() needs to be emitted before gcc emits any code.
- * Depending on gcc version, this requires -fno-unit-at-a-time or
- * -fno-toplevel-reorder.
- *
- * Hopefully gcc will eventually have a real -m16 option so we can
- * drop this hack long term.
- */
+#
+# code16gcc.h
+#
+# This file is added to the assembler via -Wa when compiling 16-bit C code.
+# This is done this way instead via asm() to make sure gcc does not reorder
+# things around us.
+#
+# gcc 4.9+ has a real -m16 option so we can drop this hack long term.
+#
-#ifndef __ASSEMBLY__
-asm(".code16gcc");
-#endif
+ .code16gcc
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 0fcd9133790c..7a801a310e37 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -33,7 +33,8 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
ifeq ($(CONFIG_EFI_STUB), y)
- VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
+ VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
+ $(objtree)/drivers/firmware/efi/libstub/lib.a
endif
$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 0331d765c2bb..f277184e2ac1 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -19,10 +19,7 @@
static efi_system_table_t *sys_table;
-static struct efi_config *efi_early;
-
-#define efi_call_early(f, ...) \
- efi_early->call(efi_early->f, __VA_ARGS__);
+struct efi_config *efi_early;
#define BOOT_SERVICES(bits) \
static void setup_boot_services##bits(struct efi_config *c) \
@@ -48,8 +45,7 @@ static void setup_boot_services##bits(struct efi_config *c) \
BOOT_SERVICES(32);
BOOT_SERVICES(64);
-static void efi_printk(efi_system_table_t *, char *);
-static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
static efi_status_t
__file_size32(void *__fh, efi_char16_t *filename_16,
@@ -156,7 +152,7 @@ grow:
return status;
}
-static efi_status_t
+efi_status_t
efi_file_size(efi_system_table_t *sys_table, void *__fh,
efi_char16_t *filename_16, void **handle, u64 *file_sz)
{
@@ -166,7 +162,7 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh,
return __file_size32(__fh, filename_16, handle, file_sz);
}
-static inline efi_status_t
+efi_status_t
efi_file_read(void *handle, unsigned long *size, void *addr)
{
unsigned long func;
@@ -184,7 +180,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr)
}
}
-static inline efi_status_t efi_file_close(void *handle)
+efi_status_t efi_file_close(void *handle)
{
if (efi_early->is64) {
efi_file_handle_64_t *fh = handle;
@@ -249,7 +245,7 @@ static inline efi_status_t __open_volume64(void *__image, void **__fh)
return status;
}
-static inline efi_status_t
+efi_status_t
efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
{
if (efi_early->is64)
@@ -258,7 +254,7 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
return __open_volume32(__image, __fh);
}
-static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
{
unsigned long output_string;
size_t offset;
@@ -284,8 +280,6 @@ static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
}
}
-#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
-
static void find_bits(unsigned long mask, u8 *pos, u8 *size)
{
u8 first, len;
@@ -1038,6 +1032,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
int i;
unsigned long ramdisk_addr;
unsigned long ramdisk_size;
+ unsigned long initrd_addr_max;
efi_early = c;
sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
@@ -1100,14 +1095,21 @@ struct boot_params *make_boot_params(struct efi_config *c)
memset(sdt, 0, sizeof(*sdt));
+ if (hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)
+ initrd_addr_max = -1UL;
+ else
+ initrd_addr_max = hdr->initrd_addr_max;
+
status = handle_cmdline_files(sys_table, image,
(char *)(unsigned long)hdr->cmd_line_ptr,
- "initrd=", hdr->initrd_addr_max,
+ "initrd=", initrd_addr_max,
&ramdisk_addr, &ramdisk_size);
if (status != EFI_SUCCESS)
goto fail2;
- hdr->ramdisk_image = ramdisk_addr;
- hdr->ramdisk_size = ramdisk_size;
+ hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
+ hdr->ramdisk_size = ramdisk_size & 0xffffffff;
+ boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
+ boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;
return boot_params;
fail2:
@@ -1374,7 +1376,10 @@ struct boot_params *efi_main(struct efi_config *c,
setup_graphics(boot_params);
- setup_efi_pci(boot_params);
+ status = setup_efi_pci(boot_params);
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "setup_efi_pci() failed!\n");
+ }
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
sizeof(*gdt), (void **)&gdt);
@@ -1401,16 +1406,20 @@ struct boot_params *efi_main(struct efi_config *c,
hdr->init_size, hdr->init_size,
hdr->pref_address,
hdr->kernel_alignment);
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
goto fail;
+ }
hdr->pref_address = hdr->code32_start;
hdr->code32_start = bzimage_addr;
}
status = exit_boot(boot_params, handle, is64);
- if (status != EFI_SUCCESS)
+ if (status != EFI_SUCCESS) {
+ efi_printk(sys_table, "exit_boot() failed!\n");
goto fail;
+ }
memset((char *)gdt->address, 0x0, gdt->size);
desc = (struct desc_struct *)gdt->address;
@@ -1470,5 +1479,6 @@ struct boot_params *efi_main(struct efi_config *c,
return boot_params;
fail:
+ efi_printk(sys_table, "efi_main() failed!\n");
return NULL;
}
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index c88c31ecad12..d487e727f1ec 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -103,20 +103,4 @@ struct efi_uga_draw_protocol {
void *blt;
};
-struct efi_config {
- u64 image_handle;
- u64 table;
- u64 allocate_pool;
- u64 allocate_pages;
- u64 get_memory_map;
- u64 free_pool;
- u64 free_pages;
- u64 locate_handle;
- u64 handle_protocol;
- u64 exit_boot_services;
- u64 text_output;
- efi_status_t (*call)(unsigned long, ...);
- bool is64;
-} __packed;
-
#endif /* BOOT_COMPRESSED_EBOOT_H */
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 7a6d43a554d7..16ef02596db2 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -154,7 +154,7 @@ extra_header_fields:
#else
.quad 0 # ImageBase
#endif
- .long 0x20 # SectionAlignment
+ .long CONFIG_PHYSICAL_ALIGN # SectionAlignment
.long 0x20 # FileAlignment
.word 0 # MajorOperatingSystemVersion
.word 0 # MinorOperatingSystemVersion
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 61d6e281898b..d551165a3159 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+obj-$(CONFIG_CRYPTO_DES3_EDE_X86_64) += des3_ede-x86_64.o
obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
@@ -52,6 +53,7 @@ salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+des3_ede-x86_64-y := des3_ede-asm_64.o des3_ede_glue.o
camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
@@ -76,7 +78,7 @@ ifeq ($(avx2_supported),yes)
endif
aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
-aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o
+aesni-intel-$(CONFIG_64BIT) += aesni-intel_avx-x86_64.o aes_ctrby8_avx-x86_64.o
ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
ifeq ($(avx2_supported),yes)
diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
new file mode 100644
index 000000000000..f091f122ed24
--- /dev/null
+++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
@@ -0,0 +1,546 @@
+/*
+ * Implement AES CTR mode by8 optimization with AVX instructions. (x86_64)
+ *
+ * This is AES128/192/256 CTR mode optimization implementation. It requires
+ * the support of Intel(R) AESNI and AVX instructions.
+ *
+ * This work was inspired by the AES CTR mode optimization published
+ * in Intel Optimized IPSEC Cryptograhpic library.
+ * Additional information on it can be found at:
+ * http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=22972
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Contact Information:
+ * James Guilford <james.guilford@intel.com>
+ * Sean Gulley <sean.m.gulley@intel.com>
+ * Chandramouli Narayanan <mouli@linux.intel.com>
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/inst.h>
+
+#define CONCAT(a,b) a##b
+#define VMOVDQ vmovdqu
+
+#define xdata0 %xmm0
+#define xdata1 %xmm1
+#define xdata2 %xmm2
+#define xdata3 %xmm3
+#define xdata4 %xmm4
+#define xdata5 %xmm5
+#define xdata6 %xmm6
+#define xdata7 %xmm7
+#define xcounter %xmm8
+#define xbyteswap %xmm9
+#define xkey0 %xmm10
+#define xkey3 %xmm11
+#define xkey6 %xmm12
+#define xkey9 %xmm13
+#define xkey4 %xmm11
+#define xkey8 %xmm12
+#define xkey12 %xmm13
+#define xkeyA %xmm14
+#define xkeyB %xmm15
+
+#define p_in %rdi
+#define p_iv %rsi
+#define p_keys %rdx
+#define p_out %rcx
+#define num_bytes %r8
+
+#define tmp %r10
+#define DDQ(i) CONCAT(ddq_add_,i)
+#define XMM(i) CONCAT(%xmm, i)
+#define DDQ_DATA 0
+#define XDATA 1
+#define KEY_128 1
+#define KEY_192 2
+#define KEY_256 3
+
+.section .rodata
+.align 16
+
+byteswap_const:
+ .octa 0x000102030405060708090A0B0C0D0E0F
+ddq_add_1:
+ .octa 0x00000000000000000000000000000001
+ddq_add_2:
+ .octa 0x00000000000000000000000000000002
+ddq_add_3:
+ .octa 0x00000000000000000000000000000003
+ddq_add_4:
+ .octa 0x00000000000000000000000000000004
+ddq_add_5:
+ .octa 0x00000000000000000000000000000005
+ddq_add_6:
+ .octa 0x00000000000000000000000000000006
+ddq_add_7:
+ .octa 0x00000000000000000000000000000007
+ddq_add_8:
+ .octa 0x00000000000000000000000000000008
+
+.text
+
+/* generate a unique variable for ddq_add_x */
+
+.macro setddq n
+ var_ddq_add = DDQ(\n)
+.endm
+
+/* generate a unique variable for xmm register */
+.macro setxdata n
+ var_xdata = XMM(\n)
+.endm
+
+/* club the numeric 'id' to the symbol 'name' */
+
+.macro club name, id
+.altmacro
+ .if \name == DDQ_DATA
+ setddq %\id
+ .elseif \name == XDATA
+ setxdata %\id
+ .endif
+.noaltmacro
+.endm
+
+/*
+ * do_aes num_in_par load_keys key_len
+ * This increments p_in, but not p_out
+ */
+.macro do_aes b, k, key_len
+ .set by, \b
+ .set load_keys, \k
+ .set klen, \key_len
+
+ .if (load_keys)
+ vmovdqa 0*16(p_keys), xkey0
+ .endif
+
+ vpshufb xbyteswap, xcounter, xdata0
+
+ .set i, 1
+ .rept (by - 1)
+ club DDQ_DATA, i
+ club XDATA, i
+ vpaddd var_ddq_add(%rip), xcounter, var_xdata
+ vpshufb xbyteswap, var_xdata, var_xdata
+ .set i, (i +1)
+ .endr
+
+ vmovdqa 1*16(p_keys), xkeyA
+
+ vpxor xkey0, xdata0, xdata0
+ club DDQ_DATA, by
+ vpaddd var_ddq_add(%rip), xcounter, xcounter
+
+ .set i, 1
+ .rept (by - 1)
+ club XDATA, i
+ vpxor xkey0, var_xdata, var_xdata
+ .set i, (i +1)
+ .endr
+
+ vmovdqa 2*16(p_keys), xkeyB
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 1 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_128)
+ .if (load_keys)
+ vmovdqa 3*16(p_keys), xkeyA
+ .endif
+ .else
+ vmovdqa 3*16(p_keys), xkeyA
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyB, var_xdata, var_xdata /* key 2 */
+ .set i, (i +1)
+ .endr
+
+ add $(16*by), p_in
+
+ .if (klen == KEY_128)
+ vmovdqa 4*16(p_keys), xkey4
+ .else
+ .if (load_keys)
+ vmovdqa 4*16(p_keys), xkey4
+ .endif
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 3 */
+ .set i, (i +1)
+ .endr
+
+ vmovdqa 5*16(p_keys), xkeyA
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkey4, var_xdata, var_xdata /* key 4 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_128)
+ .if (load_keys)
+ vmovdqa 6*16(p_keys), xkeyB
+ .endif
+ .else
+ vmovdqa 6*16(p_keys), xkeyB
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 5 */
+ .set i, (i +1)
+ .endr
+
+ vmovdqa 7*16(p_keys), xkeyA
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyB, var_xdata, var_xdata /* key 6 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_128)
+ vmovdqa 8*16(p_keys), xkey8
+ .else
+ .if (load_keys)
+ vmovdqa 8*16(p_keys), xkey8
+ .endif
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 7 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_128)
+ .if (load_keys)
+ vmovdqa 9*16(p_keys), xkeyA
+ .endif
+ .else
+ vmovdqa 9*16(p_keys), xkeyA
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkey8, var_xdata, var_xdata /* key 8 */
+ .set i, (i +1)
+ .endr
+
+ vmovdqa 10*16(p_keys), xkeyB
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 9 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen != KEY_128)
+ vmovdqa 11*16(p_keys), xkeyA
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ /* key 10 */
+ .if (klen == KEY_128)
+ vaesenclast xkeyB, var_xdata, var_xdata
+ .else
+ vaesenc xkeyB, var_xdata, var_xdata
+ .endif
+ .set i, (i +1)
+ .endr
+
+ .if (klen != KEY_128)
+ .if (load_keys)
+ vmovdqa 12*16(p_keys), xkey12
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ vaesenc xkeyA, var_xdata, var_xdata /* key 11 */
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_256)
+ vmovdqa 13*16(p_keys), xkeyA
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ .if (klen == KEY_256)
+ /* key 12 */
+ vaesenc xkey12, var_xdata, var_xdata
+ .else
+ vaesenclast xkey12, var_xdata, var_xdata
+ .endif
+ .set i, (i +1)
+ .endr
+
+ .if (klen == KEY_256)
+ vmovdqa 14*16(p_keys), xkeyB
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ /* key 13 */
+ vaesenc xkeyA, var_xdata, var_xdata
+ .set i, (i +1)
+ .endr
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ /* key 14 */
+ vaesenclast xkeyB, var_xdata, var_xdata
+ .set i, (i +1)
+ .endr
+ .endif
+ .endif
+
+ .set i, 0
+ .rept (by / 2)
+ .set j, (i+1)
+ VMOVDQ (i*16 - 16*by)(p_in), xkeyA
+ VMOVDQ (j*16 - 16*by)(p_in), xkeyB
+ club XDATA, i
+ vpxor xkeyA, var_xdata, var_xdata
+ club XDATA, j
+ vpxor xkeyB, var_xdata, var_xdata
+ .set i, (i+2)
+ .endr
+
+ .if (i < by)
+ VMOVDQ (i*16 - 16*by)(p_in), xkeyA
+ club XDATA, i
+ vpxor xkeyA, var_xdata, var_xdata
+ .endif
+
+ .set i, 0
+ .rept by
+ club XDATA, i
+ VMOVDQ var_xdata, i*16(p_out)
+ .set i, (i+1)
+ .endr
+.endm
+
+.macro do_aes_load val, key_len
+ do_aes \val, 1, \key_len
+.endm
+
+.macro do_aes_noload val, key_len
+ do_aes \val, 0, \key_len
+.endm
+
+/* main body of aes ctr load */
+
+.macro do_aes_ctrmain key_len
+
+ cmp $16, num_bytes
+ jb .Ldo_return2\key_len
+
+ vmovdqa byteswap_const(%rip), xbyteswap
+ vmovdqu (p_iv), xcounter
+ vpshufb xbyteswap, xcounter, xcounter
+
+ mov num_bytes, tmp
+ and $(7*16), tmp
+ jz .Lmult_of_8_blks\key_len
+
+ /* 1 <= tmp <= 7 */
+ cmp $(4*16), tmp
+ jg .Lgt4\key_len
+ je .Leq4\key_len
+
+.Llt4\key_len:
+ cmp $(2*16), tmp
+ jg .Leq3\key_len
+ je .Leq2\key_len
+
+.Leq1\key_len:
+ do_aes_load 1, \key_len
+ add $(1*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Leq2\key_len:
+ do_aes_load 2, \key_len
+ add $(2*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+
+.Leq3\key_len:
+ do_aes_load 3, \key_len
+ add $(3*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Leq4\key_len:
+ do_aes_load 4, \key_len
+ add $(4*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Lgt4\key_len:
+ cmp $(6*16), tmp
+ jg .Leq7\key_len
+ je .Leq6\key_len
+
+.Leq5\key_len:
+ do_aes_load 5, \key_len
+ add $(5*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Leq6\key_len:
+ do_aes_load 6, \key_len
+ add $(6*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Leq7\key_len:
+ do_aes_load 7, \key_len
+ add $(7*16), p_out
+ and $(~7*16), num_bytes
+ jz .Ldo_return2\key_len
+ jmp .Lmain_loop2\key_len
+
+.Lmult_of_8_blks\key_len:
+ .if (\key_len != KEY_128)
+ vmovdqa 0*16(p_keys), xkey0
+ vmovdqa 4*16(p_keys), xkey4
+ vmovdqa 8*16(p_keys), xkey8
+ vmovdqa 12*16(p_keys), xkey12
+ .else
+ vmovdqa 0*16(p_keys), xkey0
+ vmovdqa 3*16(p_keys), xkey4
+ vmovdqa 6*16(p_keys), xkey8
+ vmovdqa 9*16(p_keys), xkey12
+ .endif
+.align 16
+.Lmain_loop2\key_len:
+ /* num_bytes is a multiple of 8 and >0 */
+ do_aes_noload 8, \key_len
+ add $(8*16), p_out
+ sub $(8*16), num_bytes
+ jne .Lmain_loop2\key_len
+
+.Ldo_return2\key_len:
+ /* return updated IV */
+ vpshufb xbyteswap, xcounter, xcounter
+ vmovdqu xcounter, (p_iv)
+ ret
+.endm
+
+/*
+ * routine to do AES128 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_128_avx_by8(void *in, void *iv, void *keys, void *out,
+ * unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_128_avx_by8)
+ /* call the aes main loop */
+ do_aes_ctrmain KEY_128
+
+ENDPROC(aes_ctr_enc_128_avx_by8)
+
+/*
+ * routine to do AES192 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_192_avx_by8(void *in, void *iv, void *keys, void *out,
+ * unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_192_avx_by8)
+ /* call the aes main loop */
+ do_aes_ctrmain KEY_192
+
+ENDPROC(aes_ctr_enc_192_avx_by8)
+
+/*
+ * routine to do AES256 CTR enc/decrypt "by8"
+ * XMM registers are clobbered.
+ * Saving/restoring must be done at a higher level
+ * aes_ctr_enc_256_avx_by8(void *in, void *iv, void *keys, void *out,
+ * unsigned int num_bytes)
+ */
+ENTRY(aes_ctr_enc_256_avx_by8)
+ /* call the aes main loop */
+ do_aes_ctrmain KEY_256
+
+ENDPROC(aes_ctr_enc_256_avx_by8)
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 948ad0e77741..888950f29fd9 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -105,6 +105,9 @@ void crypto_fpu_exit(void);
#define AVX_GEN4_OPTSIZE 4096
#ifdef CONFIG_X86_64
+
+static void (*aesni_ctr_enc_tfm)(struct crypto_aes_ctx *ctx, u8 *out,
+ const u8 *in, unsigned int len, u8 *iv);
asmlinkage void aesni_ctr_enc(struct crypto_aes_ctx *ctx, u8 *out,
const u8 *in, unsigned int len, u8 *iv);
@@ -155,6 +158,12 @@ asmlinkage void aesni_gcm_dec(void *ctx, u8 *out,
#ifdef CONFIG_AS_AVX
+asmlinkage void aes_ctr_enc_128_avx_by8(const u8 *in, u8 *iv,
+ void *keys, u8 *out, unsigned int num_bytes);
+asmlinkage void aes_ctr_enc_192_avx_by8(const u8 *in, u8 *iv,
+ void *keys, u8 *out, unsigned int num_bytes);
+asmlinkage void aes_ctr_enc_256_avx_by8(const u8 *in, u8 *iv,
+ void *keys, u8 *out, unsigned int num_bytes);
/*
* asmlinkage void aesni_gcm_precomp_avx_gen2()
* gcm_data *my_ctx_data, context data
@@ -472,6 +481,25 @@ static void ctr_crypt_final(struct crypto_aes_ctx *ctx,
crypto_inc(ctrblk, AES_BLOCK_SIZE);
}
+#ifdef CONFIG_AS_AVX
+static void aesni_ctr_enc_avx_tfm(struct crypto_aes_ctx *ctx, u8 *out,
+ const u8 *in, unsigned int len, u8 *iv)
+{
+ /*
+ * based on key length, override with the by8 version
+ * of ctr mode encryption/decryption for improved performance
+ * aes_set_key_common() ensures that key length is one of
+ * {128,192,256}
+ */
+ if (ctx->key_length == AES_KEYSIZE_128)
+ aes_ctr_enc_128_avx_by8(in, iv, (void *)ctx, out, len);
+ else if (ctx->key_length == AES_KEYSIZE_192)
+ aes_ctr_enc_192_avx_by8(in, iv, (void *)ctx, out, len);
+ else
+ aes_ctr_enc_256_avx_by8(in, iv, (void *)ctx, out, len);
+}
+#endif
+
static int ctr_crypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
@@ -486,8 +514,8 @@ static int ctr_crypt(struct blkcipher_desc *desc,
kernel_fpu_begin();
while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
- aesni_ctr_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
- nbytes & AES_BLOCK_MASK, walk.iv);
+ aesni_ctr_enc_tfm(ctx, walk.dst.virt.addr, walk.src.virt.addr,
+ nbytes & AES_BLOCK_MASK, walk.iv);
nbytes &= AES_BLOCK_SIZE - 1;
err = blkcipher_walk_done(desc, &walk, nbytes);
}
@@ -1493,6 +1521,14 @@ static int __init aesni_init(void)
aesni_gcm_enc_tfm = aesni_gcm_enc;
aesni_gcm_dec_tfm = aesni_gcm_dec;
}
+ aesni_ctr_enc_tfm = aesni_ctr_enc;
+#ifdef CONFIG_AS_AVX
+ if (cpu_has_avx) {
+ /* optimize performance of ctr mode encryption transform */
+ aesni_ctr_enc_tfm = aesni_ctr_enc_avx_tfm;
+ pr_info("AES CTR mode by8 optimization enabled\n");
+ }
+#endif
#endif
err = crypto_fpu_init();
diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
index dbc4339b5417..26d49ebae040 100644
--- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -72,6 +72,7 @@
# unsigned int crc_pcl(u8 *buffer, int len, unsigned int crc_init);
+.text
ENTRY(crc_pcl)
#define bufp %rdi
#define bufp_dw %edi
@@ -216,15 +217,11 @@ LABEL crc_ %i
## 4) Combine three results:
################################################################
- lea (K_table-16)(%rip), bufp # first entry is for idx 1
+ lea (K_table-8)(%rip), bufp # first entry is for idx 1
shlq $3, %rax # rax *= 8
- subq %rax, tmp # tmp -= rax*8
- shlq $1, %rax
- subq %rax, tmp # tmp -= rax*16
- # (total tmp -= rax*24)
- addq %rax, bufp
-
- movdqa (bufp), %xmm0 # 2 consts: K1:K2
+ pmovzxdq (bufp,%rax), %xmm0 # 2 consts: K1:K2
+ leal (%eax,%eax,2), %eax # rax *= 3 (total *24)
+ subq %rax, tmp # tmp -= rax*24
movq crc_init, %xmm1 # CRC for block 1
PCLMULQDQ 0x00,%xmm0,%xmm1 # Multiply by K2
@@ -238,9 +235,9 @@ LABEL crc_ %i
mov crc2, crc_init
crc32 %rax, crc_init
-################################################################
-## 5) Check for end:
-################################################################
+ ################################################################
+ ## 5) Check for end:
+ ################################################################
LABEL crc_ 0
mov tmp, len
@@ -331,136 +328,136 @@ ENDPROC(crc_pcl)
################################################################
## PCLMULQDQ tables
- ## Table is 128 entries x 2 quad words each
+ ## Table is 128 entries x 2 words (8 bytes) each
################################################################
-.data
-.align 64
+.section .rotata, "a", %progbits
+.align 8
K_table:
- .quad 0x14cd00bd6,0x105ec76f0
- .quad 0x0ba4fc28e,0x14cd00bd6
- .quad 0x1d82c63da,0x0f20c0dfe
- .quad 0x09e4addf8,0x0ba4fc28e
- .quad 0x039d3b296,0x1384aa63a
- .quad 0x102f9b8a2,0x1d82c63da
- .quad 0x14237f5e6,0x01c291d04
- .quad 0x00d3b6092,0x09e4addf8
- .quad 0x0c96cfdc0,0x0740eef02
- .quad 0x18266e456,0x039d3b296
- .quad 0x0daece73e,0x0083a6eec
- .quad 0x0ab7aff2a,0x102f9b8a2
- .quad 0x1248ea574,0x1c1733996
- .quad 0x083348832,0x14237f5e6
- .quad 0x12c743124,0x02ad91c30
- .quad 0x0b9e02b86,0x00d3b6092
- .quad 0x018b33a4e,0x06992cea2
- .quad 0x1b331e26a,0x0c96cfdc0
- .quad 0x17d35ba46,0x07e908048
- .quad 0x1bf2e8b8a,0x18266e456
- .quad 0x1a3e0968a,0x11ed1f9d8
- .quad 0x0ce7f39f4,0x0daece73e
- .quad 0x061d82e56,0x0f1d0f55e
- .quad 0x0d270f1a2,0x0ab7aff2a
- .quad 0x1c3f5f66c,0x0a87ab8a8
- .quad 0x12ed0daac,0x1248ea574
- .quad 0x065863b64,0x08462d800
- .quad 0x11eef4f8e,0x083348832
- .quad 0x1ee54f54c,0x071d111a8
- .quad 0x0b3e32c28,0x12c743124
- .quad 0x0064f7f26,0x0ffd852c6
- .quad 0x0dd7e3b0c,0x0b9e02b86
- .quad 0x0f285651c,0x0dcb17aa4
- .quad 0x010746f3c,0x018b33a4e
- .quad 0x1c24afea4,0x0f37c5aee
- .quad 0x0271d9844,0x1b331e26a
- .quad 0x08e766a0c,0x06051d5a2
- .quad 0x093a5f730,0x17d35ba46
- .quad 0x06cb08e5c,0x11d5ca20e
- .quad 0x06b749fb2,0x1bf2e8b8a
- .quad 0x1167f94f2,0x021f3d99c
- .quad 0x0cec3662e,0x1a3e0968a
- .quad 0x19329634a,0x08f158014
- .quad 0x0e6fc4e6a,0x0ce7f39f4
- .quad 0x08227bb8a,0x1a5e82106
- .quad 0x0b0cd4768,0x061d82e56
- .quad 0x13c2b89c4,0x188815ab2
- .quad 0x0d7a4825c,0x0d270f1a2
- .quad 0x10f5ff2ba,0x105405f3e
- .quad 0x00167d312,0x1c3f5f66c
- .quad 0x0f6076544,0x0e9adf796
- .quad 0x026f6a60a,0x12ed0daac
- .quad 0x1a2adb74e,0x096638b34
- .quad 0x19d34af3a,0x065863b64
- .quad 0x049c3cc9c,0x1e50585a0
- .quad 0x068bce87a,0x11eef4f8e
- .quad 0x1524fa6c6,0x19f1c69dc
- .quad 0x16cba8aca,0x1ee54f54c
- .quad 0x042d98888,0x12913343e
- .quad 0x1329d9f7e,0x0b3e32c28
- .quad 0x1b1c69528,0x088f25a3a
- .quad 0x02178513a,0x0064f7f26
- .quad 0x0e0ac139e,0x04e36f0b0
- .quad 0x0170076fa,0x0dd7e3b0c
- .quad 0x141a1a2e2,0x0bd6f81f8
- .quad 0x16ad828b4,0x0f285651c
- .quad 0x041d17b64,0x19425cbba
- .quad 0x1fae1cc66,0x010746f3c
- .quad 0x1a75b4b00,0x18db37e8a
- .quad 0x0f872e54c,0x1c24afea4
- .quad 0x01e41e9fc,0x04c144932
- .quad 0x086d8e4d2,0x0271d9844
- .quad 0x160f7af7a,0x052148f02
- .quad 0x05bb8f1bc,0x08e766a0c
- .quad 0x0a90fd27a,0x0a3c6f37a
- .quad 0x0b3af077a,0x093a5f730
- .quad 0x04984d782,0x1d22c238e
- .quad 0x0ca6ef3ac,0x06cb08e5c
- .quad 0x0234e0b26,0x063ded06a
- .quad 0x1d88abd4a,0x06b749fb2
- .quad 0x04597456a,0x04d56973c
- .quad 0x0e9e28eb4,0x1167f94f2
- .quad 0x07b3ff57a,0x19385bf2e
- .quad 0x0c9c8b782,0x0cec3662e
- .quad 0x13a9cba9e,0x0e417f38a
- .quad 0x093e106a4,0x19329634a
- .quad 0x167001a9c,0x14e727980
- .quad 0x1ddffc5d4,0x0e6fc4e6a
- .quad 0x00df04680,0x0d104b8fc
- .quad 0x02342001e,0x08227bb8a
- .quad 0x00a2a8d7e,0x05b397730
- .quad 0x168763fa6,0x0b0cd4768
- .quad 0x1ed5a407a,0x0e78eb416
- .quad 0x0d2c3ed1a,0x13c2b89c4
- .quad 0x0995a5724,0x1641378f0
- .quad 0x19b1afbc4,0x0d7a4825c
- .quad 0x109ffedc0,0x08d96551c
- .quad 0x0f2271e60,0x10f5ff2ba
- .quad 0x00b0bf8ca,0x00bf80dd2
- .quad 0x123888b7a,0x00167d312
- .quad 0x1e888f7dc,0x18dcddd1c
- .quad 0x002ee03b2,0x0f6076544
- .quad 0x183e8d8fe,0x06a45d2b2
- .quad 0x133d7a042,0x026f6a60a
- .quad 0x116b0f50c,0x1dd3e10e8
- .quad 0x05fabe670,0x1a2adb74e
- .quad 0x130004488,0x0de87806c
- .quad 0x000bcf5f6,0x19d34af3a
- .quad 0x18f0c7078,0x014338754
- .quad 0x017f27698,0x049c3cc9c
- .quad 0x058ca5f00,0x15e3e77ee
- .quad 0x1af900c24,0x068bce87a
- .quad 0x0b5cfca28,0x0dd07448e
- .quad 0x0ded288f8,0x1524fa6c6
- .quad 0x059f229bc,0x1d8048348
- .quad 0x06d390dec,0x16cba8aca
- .quad 0x037170390,0x0a3e3e02c
- .quad 0x06353c1cc,0x042d98888
- .quad 0x0c4584f5c,0x0d73c7bea
- .quad 0x1f16a3418,0x1329d9f7e
- .quad 0x0531377e2,0x185137662
- .quad 0x1d8d9ca7c,0x1b1c69528
- .quad 0x0b25b29f2,0x18a08b5bc
- .quad 0x19fb2a8b0,0x02178513a
- .quad 0x1a08fe6ac,0x1da758ae0
- .quad 0x045cddf4e,0x0e0ac139e
- .quad 0x1a91647f2,0x169cf9eb0
- .quad 0x1a0f717c4,0x0170076fa
+ .long 0x493c7d27, 0x00000001
+ .long 0xba4fc28e, 0x493c7d27
+ .long 0xddc0152b, 0xf20c0dfe
+ .long 0x9e4addf8, 0xba4fc28e
+ .long 0x39d3b296, 0x3da6d0cb
+ .long 0x0715ce53, 0xddc0152b
+ .long 0x47db8317, 0x1c291d04
+ .long 0x0d3b6092, 0x9e4addf8
+ .long 0xc96cfdc0, 0x740eef02
+ .long 0x878a92a7, 0x39d3b296
+ .long 0xdaece73e, 0x083a6eec
+ .long 0xab7aff2a, 0x0715ce53
+ .long 0x2162d385, 0xc49f4f67
+ .long 0x83348832, 0x47db8317
+ .long 0x299847d5, 0x2ad91c30
+ .long 0xb9e02b86, 0x0d3b6092
+ .long 0x18b33a4e, 0x6992cea2
+ .long 0xb6dd949b, 0xc96cfdc0
+ .long 0x78d9ccb7, 0x7e908048
+ .long 0xbac2fd7b, 0x878a92a7
+ .long 0xa60ce07b, 0x1b3d8f29
+ .long 0xce7f39f4, 0xdaece73e
+ .long 0x61d82e56, 0xf1d0f55e
+ .long 0xd270f1a2, 0xab7aff2a
+ .long 0xc619809d, 0xa87ab8a8
+ .long 0x2b3cac5d, 0x2162d385
+ .long 0x65863b64, 0x8462d800
+ .long 0x1b03397f, 0x83348832
+ .long 0xebb883bd, 0x71d111a8
+ .long 0xb3e32c28, 0x299847d5
+ .long 0x064f7f26, 0xffd852c6
+ .long 0xdd7e3b0c, 0xb9e02b86
+ .long 0xf285651c, 0xdcb17aa4
+ .long 0x10746f3c, 0x18b33a4e
+ .long 0xc7a68855, 0xf37c5aee
+ .long 0x271d9844, 0xb6dd949b
+ .long 0x8e766a0c, 0x6051d5a2
+ .long 0x93a5f730, 0x78d9ccb7
+ .long 0x6cb08e5c, 0x18b0d4ff
+ .long 0x6b749fb2, 0xbac2fd7b
+ .long 0x1393e203, 0x21f3d99c
+ .long 0xcec3662e, 0xa60ce07b
+ .long 0x96c515bb, 0x8f158014
+ .long 0xe6fc4e6a, 0xce7f39f4
+ .long 0x8227bb8a, 0xa00457f7
+ .long 0xb0cd4768, 0x61d82e56
+ .long 0x39c7ff35, 0x8d6d2c43
+ .long 0xd7a4825c, 0xd270f1a2
+ .long 0x0ab3844b, 0x00ac29cf
+ .long 0x0167d312, 0xc619809d
+ .long 0xf6076544, 0xe9adf796
+ .long 0x26f6a60a, 0x2b3cac5d
+ .long 0xa741c1bf, 0x96638b34
+ .long 0x98d8d9cb, 0x65863b64
+ .long 0x49c3cc9c, 0xe0e9f351
+ .long 0x68bce87a, 0x1b03397f
+ .long 0x57a3d037, 0x9af01f2d
+ .long 0x6956fc3b, 0xebb883bd
+ .long 0x42d98888, 0x2cff42cf
+ .long 0x3771e98f, 0xb3e32c28
+ .long 0xb42ae3d9, 0x88f25a3a
+ .long 0x2178513a, 0x064f7f26
+ .long 0xe0ac139e, 0x4e36f0b0
+ .long 0x170076fa, 0xdd7e3b0c
+ .long 0x444dd413, 0xbd6f81f8
+ .long 0x6f345e45, 0xf285651c
+ .long 0x41d17b64, 0x91c9bd4b
+ .long 0xff0dba97, 0x10746f3c
+ .long 0xa2b73df1, 0x885f087b
+ .long 0xf872e54c, 0xc7a68855
+ .long 0x1e41e9fc, 0x4c144932
+ .long 0x86d8e4d2, 0x271d9844
+ .long 0x651bd98b, 0x52148f02
+ .long 0x5bb8f1bc, 0x8e766a0c
+ .long 0xa90fd27a, 0xa3c6f37a
+ .long 0xb3af077a, 0x93a5f730
+ .long 0x4984d782, 0xd7c0557f
+ .long 0xca6ef3ac, 0x6cb08e5c
+ .long 0x234e0b26, 0x63ded06a
+ .long 0xdd66cbbb, 0x6b749fb2
+ .long 0x4597456a, 0x4d56973c
+ .long 0xe9e28eb4, 0x1393e203
+ .long 0x7b3ff57a, 0x9669c9df
+ .long 0xc9c8b782, 0xcec3662e
+ .long 0x3f70cc6f, 0xe417f38a
+ .long 0x93e106a4, 0x96c515bb
+ .long 0x62ec6c6d, 0x4b9e0f71
+ .long 0xd813b325, 0xe6fc4e6a
+ .long 0x0df04680, 0xd104b8fc
+ .long 0x2342001e, 0x8227bb8a
+ .long 0x0a2a8d7e, 0x5b397730
+ .long 0x6d9a4957, 0xb0cd4768
+ .long 0xe8b6368b, 0xe78eb416
+ .long 0xd2c3ed1a, 0x39c7ff35
+ .long 0x995a5724, 0x61ff0e01
+ .long 0x9ef68d35, 0xd7a4825c
+ .long 0x0c139b31, 0x8d96551c
+ .long 0xf2271e60, 0x0ab3844b
+ .long 0x0b0bf8ca, 0x0bf80dd2
+ .long 0x2664fd8b, 0x0167d312
+ .long 0xed64812d, 0x8821abed
+ .long 0x02ee03b2, 0xf6076544
+ .long 0x8604ae0f, 0x6a45d2b2
+ .long 0x363bd6b3, 0x26f6a60a
+ .long 0x135c83fd, 0xd8d26619
+ .long 0x5fabe670, 0xa741c1bf
+ .long 0x35ec3279, 0xde87806c
+ .long 0x00bcf5f6, 0x98d8d9cb
+ .long 0x8ae00689, 0x14338754
+ .long 0x17f27698, 0x49c3cc9c
+ .long 0x58ca5f00, 0x5bd2011f
+ .long 0xaa7c7ad5, 0x68bce87a
+ .long 0xb5cfca28, 0xdd07448e
+ .long 0xded288f8, 0x57a3d037
+ .long 0x59f229bc, 0xdde8f5b9
+ .long 0x6d390dec, 0x6956fc3b
+ .long 0x37170390, 0xa3e3e02c
+ .long 0x6353c1cc, 0x42d98888
+ .long 0xc4584f5c, 0xd73c7bea
+ .long 0xf48642e9, 0x3771e98f
+ .long 0x531377e2, 0x80ff0093
+ .long 0xdd35bc8d, 0xb42ae3d9
+ .long 0xb25b29f2, 0x8fe4c34d
+ .long 0x9a5ede41, 0x2178513a
+ .long 0xa563905d, 0xdf99fc11
+ .long 0x45cddf4e, 0xe0ac139e
+ .long 0xacfa3103, 0x6c23e841
+ .long 0xa51b6135, 0x170076fa
diff --git a/arch/x86/crypto/des3_ede-asm_64.S b/arch/x86/crypto/des3_ede-asm_64.S
new file mode 100644
index 000000000000..038f6ae87c5e
--- /dev/null
+++ b/arch/x86/crypto/des3_ede-asm_64.S
@@ -0,0 +1,805 @@
+/*
+ * des3_ede-asm_64.S - x86-64 assembly implementation of 3DES cipher
+ *
+ * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+
+.file "des3_ede-asm_64.S"
+.text
+
+#define s1 .L_s1
+#define s2 ((s1) + (64*8))
+#define s3 ((s2) + (64*8))
+#define s4 ((s3) + (64*8))
+#define s5 ((s4) + (64*8))
+#define s6 ((s5) + (64*8))
+#define s7 ((s6) + (64*8))
+#define s8 ((s7) + (64*8))
+
+/* register macros */
+#define CTX %rdi
+
+#define RL0 %r8
+#define RL1 %r9
+#define RL2 %r10
+
+#define RL0d %r8d
+#define RL1d %r9d
+#define RL2d %r10d
+
+#define RR0 %r11
+#define RR1 %r12
+#define RR2 %r13
+
+#define RR0d %r11d
+#define RR1d %r12d
+#define RR2d %r13d
+
+#define RW0 %rax
+#define RW1 %rbx
+#define RW2 %rcx
+
+#define RW0d %eax
+#define RW1d %ebx
+#define RW2d %ecx
+
+#define RW0bl %al
+#define RW1bl %bl
+#define RW2bl %cl
+
+#define RW0bh %ah
+#define RW1bh %bh
+#define RW2bh %ch
+
+#define RT0 %r15
+#define RT1 %rbp
+#define RT2 %r14
+#define RT3 %rdx
+
+#define RT0d %r15d
+#define RT1d %ebp
+#define RT2d %r14d
+#define RT3d %edx
+
+/***********************************************************************
+ * 1-way 3DES
+ ***********************************************************************/
+#define do_permutation(a, b, offset, mask) \
+ movl a, RT0d; \
+ shrl $(offset), RT0d; \
+ xorl b, RT0d; \
+ andl $(mask), RT0d; \
+ xorl RT0d, b; \
+ shll $(offset), RT0d; \
+ xorl RT0d, a;
+
+#define expand_to_64bits(val, mask) \
+ movl val##d, RT0d; \
+ rorl $4, RT0d; \
+ shlq $32, RT0; \
+ orq RT0, val; \
+ andq mask, val;
+
+#define compress_to_64bits(val) \
+ movq val, RT0; \
+ shrq $32, RT0; \
+ roll $4, RT0d; \
+ orl RT0d, val##d;
+
+#define initial_permutation(left, right) \
+ do_permutation(left##d, right##d, 4, 0x0f0f0f0f); \
+ do_permutation(left##d, right##d, 16, 0x0000ffff); \
+ do_permutation(right##d, left##d, 2, 0x33333333); \
+ do_permutation(right##d, left##d, 8, 0x00ff00ff); \
+ movabs $0x3f3f3f3f3f3f3f3f, RT3; \
+ movl left##d, RW0d; \
+ roll $1, right##d; \
+ xorl right##d, RW0d; \
+ andl $0xaaaaaaaa, RW0d; \
+ xorl RW0d, left##d; \
+ xorl RW0d, right##d; \
+ roll $1, left##d; \
+ expand_to_64bits(right, RT3); \
+ expand_to_64bits(left, RT3);
+
+#define final_permutation(left, right) \
+ compress_to_64bits(right); \
+ compress_to_64bits(left); \
+ movl right##d, RW0d; \
+ rorl $1, left##d; \
+ xorl left##d, RW0d; \
+ andl $0xaaaaaaaa, RW0d; \
+ xorl RW0d, right##d; \
+ xorl RW0d, left##d; \
+ rorl $1, right##d; \
+ do_permutation(right##d, left##d, 8, 0x00ff00ff); \
+ do_permutation(right##d, left##d, 2, 0x33333333); \
+ do_permutation(left##d, right##d, 16, 0x0000ffff); \
+ do_permutation(left##d, right##d, 4, 0x0f0f0f0f);
+
+#define round1(n, from, to, load_next_key) \
+ xorq from, RW0; \
+ \
+ movzbl RW0bl, RT0d; \
+ movzbl RW0bh, RT1d; \
+ shrq $16, RW0; \
+ movzbl RW0bl, RT2d; \
+ movzbl RW0bh, RT3d; \
+ shrq $16, RW0; \
+ movq s8(, RT0, 8), RT0; \
+ xorq s6(, RT1, 8), to; \
+ movzbl RW0bl, RL1d; \
+ movzbl RW0bh, RT1d; \
+ shrl $16, RW0d; \
+ xorq s4(, RT2, 8), RT0; \
+ xorq s2(, RT3, 8), to; \
+ movzbl RW0bl, RT2d; \
+ movzbl RW0bh, RT3d; \
+ xorq s7(, RL1, 8), RT0; \
+ xorq s5(, RT1, 8), to; \
+ xorq s3(, RT2, 8), RT0; \
+ load_next_key(n, RW0); \
+ xorq RT0, to; \
+ xorq s1(, RT3, 8), to; \
+
+#define load_next_key(n, RWx) \
+ movq (((n) + 1) * 8)(CTX), RWx;
+
+#define dummy2(a, b) /*_*/
+
+#define read_block(io, left, right) \
+ movl (io), left##d; \
+ movl 4(io), right##d; \
+ bswapl left##d; \
+ bswapl right##d;
+
+#define write_block(io, left, right) \
+ bswapl left##d; \
+ bswapl right##d; \
+ movl left##d, (io); \
+ movl right##d, 4(io);
+
+ENTRY(des3_ede_x86_64_crypt_blk)
+ /* input:
+ * %rdi: round keys, CTX
+ * %rsi: dst
+ * %rdx: src
+ */
+ pushq %rbp;
+ pushq %rbx;
+ pushq %r12;
+ pushq %r13;
+ pushq %r14;
+ pushq %r15;
+
+ read_block(%rdx, RL0, RR0);
+ initial_permutation(RL0, RR0);
+
+ movq (CTX), RW0;
+
+ round1(0, RR0, RL0, load_next_key);
+ round1(1, RL0, RR0, load_next_key);
+ round1(2, RR0, RL0, load_next_key);
+ round1(3, RL0, RR0, load_next_key);
+ round1(4, RR0, RL0, load_next_key);
+ round1(5, RL0, RR0, load_next_key);
+ round1(6, RR0, RL0, load_next_key);
+ round1(7, RL0, RR0, load_next_key);
+ round1(8, RR0, RL0, load_next_key);
+ round1(9, RL0, RR0, load_next_key);
+ round1(10, RR0, RL0, load_next_key);
+ round1(11, RL0, RR0, load_next_key);
+ round1(12, RR0, RL0, load_next_key);
+ round1(13, RL0, RR0, load_next_key);
+ round1(14, RR0, RL0, load_next_key);
+ round1(15, RL0, RR0, load_next_key);
+
+ round1(16+0, RL0, RR0, load_next_key);
+ round1(16+1, RR0, RL0, load_next_key);
+ round1(16+2, RL0, RR0, load_next_key);
+ round1(16+3, RR0, RL0, load_next_key);
+ round1(16+4, RL0, RR0, load_next_key);
+ round1(16+5, RR0, RL0, load_next_key);
+ round1(16+6, RL0, RR0, load_next_key);
+ round1(16+7, RR0, RL0, load_next_key);
+ round1(16+8, RL0, RR0, load_next_key);
+ round1(16+9, RR0, RL0, load_next_key);
+ round1(16+10, RL0, RR0, load_next_key);
+ round1(16+11, RR0, RL0, load_next_key);
+ round1(16+12, RL0, RR0, load_next_key);
+ round1(16+13, RR0, RL0, load_next_key);
+ round1(16+14, RL0, RR0, load_next_key);
+ round1(16+15, RR0, RL0, load_next_key);
+
+ round1(32+0, RR0, RL0, load_next_key);
+ round1(32+1, RL0, RR0, load_next_key);
+ round1(32+2, RR0, RL0, load_next_key);
+ round1(32+3, RL0, RR0, load_next_key);
+ round1(32+4, RR0, RL0, load_next_key);
+ round1(32+5, RL0, RR0, load_next_key);
+ round1(32+6, RR0, RL0, load_next_key);
+ round1(32+7, RL0, RR0, load_next_key);
+ round1(32+8, RR0, RL0, load_next_key);
+ round1(32+9, RL0, RR0, load_next_key);
+ round1(32+10, RR0, RL0, load_next_key);
+ round1(32+11, RL0, RR0, load_next_key);
+ round1(32+12, RR0, RL0, load_next_key);
+ round1(32+13, RL0, RR0, load_next_key);
+ round1(32+14, RR0, RL0, load_next_key);
+ round1(32+15, RL0, RR0, dummy2);
+
+ final_permutation(RR0, RL0);
+ write_block(%rsi, RR0, RL0);
+
+ popq %r15;
+ popq %r14;
+ popq %r13;
+ popq %r12;
+ popq %rbx;
+ popq %rbp;
+
+ ret;
+ENDPROC(des3_ede_x86_64_crypt_blk)
+
+/***********************************************************************
+ * 3-way 3DES
+ ***********************************************************************/
+#define expand_to_64bits(val, mask) \
+ movl val##d, RT0d; \
+ rorl $4, RT0d; \
+ shlq $32, RT0; \
+ orq RT0, val; \
+ andq mask, val;
+
+#define compress_to_64bits(val) \
+ movq val, RT0; \
+ shrq $32, RT0; \
+ roll $4, RT0d; \
+ orl RT0d, val##d;
+
+#define initial_permutation3(left, right) \
+ do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \
+ do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
+ do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \
+ do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
+ do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f); \
+ do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
+ \
+ do_permutation(right##0d, left##0d, 2, 0x33333333); \
+ do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \
+ do_permutation(right##1d, left##1d, 2, 0x33333333); \
+ do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \
+ do_permutation(right##2d, left##2d, 2, 0x33333333); \
+ do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \
+ \
+ movabs $0x3f3f3f3f3f3f3f3f, RT3; \
+ \
+ movl left##0d, RW0d; \
+ roll $1, right##0d; \
+ xorl right##0d, RW0d; \
+ andl $0xaaaaaaaa, RW0d; \
+ xorl RW0d, left##0d; \
+ xorl RW0d, right##0d; \
+ roll $1, left##0d; \
+ expand_to_64bits(right##0, RT3); \
+ expand_to_64bits(left##0, RT3); \
+ movl left##1d, RW1d; \
+ roll $1, right##1d; \
+ xorl right##1d, RW1d; \
+ andl $0xaaaaaaaa, RW1d; \
+ xorl RW1d, left##1d; \
+ xorl RW1d, right##1d; \
+ roll $1, left##1d; \
+ expand_to_64bits(right##1, RT3); \
+ expand_to_64bits(left##1, RT3); \
+ movl left##2d, RW2d; \
+ roll $1, right##2d; \
+ xorl right##2d, RW2d; \
+ andl $0xaaaaaaaa, RW2d; \
+ xorl RW2d, left##2d; \
+ xorl RW2d, right##2d; \
+ roll $1, left##2d; \
+ expand_to_64bits(right##2, RT3); \
+ expand_to_64bits(left##2, RT3);
+
+#define final_permutation3(left, right) \
+ compress_to_64bits(right##0); \
+ compress_to_64bits(left##0); \
+ movl right##0d, RW0d; \
+ rorl $1, left##0d; \
+ xorl left##0d, RW0d; \
+ andl $0xaaaaaaaa, RW0d; \
+ xorl RW0d, right##0d; \
+ xorl RW0d, left##0d; \
+ rorl $1, right##0d; \
+ compress_to_64bits(right##1); \
+ compress_to_64bits(left##1); \
+ movl right##1d, RW1d; \
+ rorl $1, left##1d; \
+ xorl left##1d, RW1d; \
+ andl $0xaaaaaaaa, RW1d; \
+ xorl RW1d, right##1d; \
+ xorl RW1d, left##1d; \
+ rorl $1, right##1d; \
+ compress_to_64bits(right##2); \
+ compress_to_64bits(left##2); \
+ movl right##2d, RW2d; \
+ rorl $1, left##2d; \
+ xorl left##2d, RW2d; \
+ andl $0xaaaaaaaa, RW2d; \
+ xorl RW2d, right##2d; \
+ xorl RW2d, left##2d; \
+ rorl $1, right##2d; \
+ \
+ do_permutation(right##0d, left##0d, 8, 0x00ff00ff); \
+ do_permutation(right##0d, left##0d, 2, 0x33333333); \
+ do_permutation(right##1d, left##1d, 8, 0x00ff00ff); \
+ do_permutation(right##1d, left##1d, 2, 0x33333333); \
+ do_permutation(right##2d, left##2d, 8, 0x00ff00ff); \
+ do_permutation(right##2d, left##2d, 2, 0x33333333); \
+ \
+ do_permutation(left##0d, right##0d, 16, 0x0000ffff); \
+ do_permutation(left##0d, right##0d, 4, 0x0f0f0f0f); \
+ do_permutation(left##1d, right##1d, 16, 0x0000ffff); \
+ do_permutation(left##1d, right##1d, 4, 0x0f0f0f0f); \
+ do_permutation(left##2d, right##2d, 16, 0x0000ffff); \
+ do_permutation(left##2d, right##2d, 4, 0x0f0f0f0f);
+
+#define round3(n, from, to, load_next_key, do_movq) \
+ xorq from##0, RW0; \
+ movzbl RW0bl, RT3d; \
+ movzbl RW0bh, RT1d; \
+ shrq $16, RW0; \
+ xorq s8(, RT3, 8), to##0; \
+ xorq s6(, RT1, 8), to##0; \
+ movzbl RW0bl, RT3d; \
+ movzbl RW0bh, RT1d; \
+ shrq $16, RW0; \
+ xorq s4(, RT3, 8), to##0; \
+ xorq s2(, RT1, 8), to##0; \
+ movzbl RW0bl, RT3d; \
+ movzbl RW0bh, RT1d; \
+ shrl $16, RW0d; \
+ xorq s7(, RT3, 8), to##0; \
+ xorq s5(, RT1, 8), to##0; \
+ movzbl RW0bl, RT3d; \
+ movzbl RW0bh, RT1d; \
+ load_next_key(n, RW0); \
+ xorq s3(, RT3, 8), to##0; \
+ xorq s1(, RT1, 8), to##0; \
+ xorq from##1, RW1; \
+ movzbl RW1bl, RT3d; \
+ movzbl RW1bh, RT1d; \
+ shrq $16, RW1; \
+ xorq s8(, RT3, 8), to##1; \
+ xorq s6(, RT1, 8), to##1; \
+ movzbl RW1bl, RT3d; \
+ movzbl RW1bh, RT1d; \
+ shrq $16, RW1; \
+ xorq s4(, RT3, 8), to##1; \
+ xorq s2(, RT1, 8), to##1; \
+ movzbl RW1bl, RT3d; \
+ movzbl RW1bh, RT1d; \
+ shrl $16, RW1d; \
+ xorq s7(, RT3, 8), to##1; \
+ xorq s5(, RT1, 8), to##1; \
+ movzbl RW1bl, RT3d; \
+ movzbl RW1bh, RT1d; \
+ do_movq(RW0, RW1); \
+ xorq s3(, RT3, 8), to##1; \
+ xorq s1(, RT1, 8), to##1; \
+ xorq from##2, RW2; \
+ movzbl RW2bl, RT3d; \
+ movzbl RW2bh, RT1d; \
+ shrq $16, RW2; \
+ xorq s8(, RT3, 8), to##2; \
+ xorq s6(, RT1, 8), to##2; \
+ movzbl RW2bl, RT3d; \
+ movzbl RW2bh, RT1d; \
+ shrq $16, RW2; \
+ xorq s4(, RT3, 8), to##2; \
+ xorq s2(, RT1, 8), to##2; \
+ movzbl RW2bl, RT3d; \
+ movzbl RW2bh, RT1d; \
+ shrl $16, RW2d; \
+ xorq s7(, RT3, 8), to##2; \
+ xorq s5(, RT1, 8), to##2; \
+ movzbl RW2bl, RT3d; \
+ movzbl RW2bh, RT1d; \
+ do_movq(RW0, RW2); \
+ xorq s3(, RT3, 8), to##2; \
+ xorq s1(, RT1, 8), to##2;
+
+#define __movq(src, dst) \
+ movq src, dst;
+
+ENTRY(des3_ede_x86_64_crypt_blk_3way)
+ /* input:
+ * %rdi: ctx, round keys
+ * %rsi: dst (3 blocks)
+ * %rdx: src (3 blocks)
+ */
+
+ pushq %rbp;
+ pushq %rbx;
+ pushq %r12;
+ pushq %r13;
+ pushq %r14;
+ pushq %r15;
+
+ /* load input */
+ movl 0 * 4(%rdx), RL0d;
+ movl 1 * 4(%rdx), RR0d;
+ movl 2 * 4(%rdx), RL1d;
+ movl 3 * 4(%rdx), RR1d;
+ movl 4 * 4(%rdx), RL2d;
+ movl 5 * 4(%rdx), RR2d;
+
+ bswapl RL0d;
+ bswapl RR0d;
+ bswapl RL1d;
+ bswapl RR1d;
+ bswapl RL2d;
+ bswapl RR2d;
+
+ initial_permutation3(RL, RR);
+
+ movq 0(CTX), RW0;
+ movq RW0, RW1;
+ movq RW0, RW2;
+
+ round3(0, RR, RL, load_next_key, __movq);
+ round3(1, RL, RR, load_next_key, __movq);
+ round3(2, RR, RL, load_next_key, __movq);
+ round3(3, RL, RR, load_next_key, __movq);
+ round3(4, RR, RL, load_next_key, __movq);
+ round3(5, RL, RR, load_next_key, __movq);
+ round3(6, RR, RL, load_next_key, __movq);
+ round3(7, RL, RR, load_next_key, __movq);
+ round3(8, RR, RL, load_next_key, __movq);
+ round3(9, RL, RR, load_next_key, __movq);
+ round3(10, RR, RL, load_next_key, __movq);
+ round3(11, RL, RR, load_next_key, __movq);
+ round3(12, RR, RL, load_next_key, __movq);
+ round3(13, RL, RR, load_next_key, __movq);
+ round3(14, RR, RL, load_next_key, __movq);
+ round3(15, RL, RR, load_next_key, __movq);
+
+ round3(16+0, RL, RR, load_next_key, __movq);
+ round3(16+1, RR, RL, load_next_key, __movq);
+ round3(16+2, RL, RR, load_next_key, __movq);
+ round3(16+3, RR, RL, load_next_key, __movq);
+ round3(16+4, RL, RR, load_next_key, __movq);
+ round3(16+5, RR, RL, load_next_key, __movq);
+ round3(16+6, RL, RR, load_next_key, __movq);
+ round3(16+7, RR, RL, load_next_key, __movq);
+ round3(16+8, RL, RR, load_next_key, __movq);
+ round3(16+9, RR, RL, load_next_key, __movq);
+ round3(16+10, RL, RR, load_next_key, __movq);
+ round3(16+11, RR, RL, load_next_key, __movq);
+ round3(16+12, RL, RR, load_next_key, __movq);
+ round3(16+13, RR, RL, load_next_key, __movq);
+ round3(16+14, RL, RR, load_next_key, __movq);
+ round3(16+15, RR, RL, load_next_key, __movq);
+
+ round3(32+0, RR, RL, load_next_key, __movq);
+ round3(32+1, RL, RR, load_next_key, __movq);
+ round3(32+2, RR, RL, load_next_key, __movq);
+ round3(32+3, RL, RR, load_next_key, __movq);
+ round3(32+4, RR, RL, load_next_key, __movq);
+ round3(32+5, RL, RR, load_next_key, __movq);
+ round3(32+6, RR, RL, load_next_key, __movq);
+ round3(32+7, RL, RR, load_next_key, __movq);
+ round3(32+8, RR, RL, load_next_key, __movq);
+ round3(32+9, RL, RR, load_next_key, __movq);
+ round3(32+10, RR, RL, load_next_key, __movq);
+ round3(32+11, RL, RR, load_next_key, __movq);
+ round3(32+12, RR, RL, load_next_key, __movq);
+ round3(32+13, RL, RR, load_next_key, __movq);
+ round3(32+14, RR, RL, load_next_key, __movq);
+ round3(32+15, RL, RR, dummy2, dummy2);
+
+ final_permutation3(RR, RL);
+
+ bswapl RR0d;
+ bswapl RL0d;
+ bswapl RR1d;
+ bswapl RL1d;
+ bswapl RR2d;
+ bswapl RL2d;
+
+ movl RR0d, 0 * 4(%rsi);
+ movl RL0d, 1 * 4(%rsi);
+ movl RR1d, 2 * 4(%rsi);
+ movl RL1d, 3 * 4(%rsi);
+ movl RR2d, 4 * 4(%rsi);
+ movl RL2d, 5 * 4(%rsi);
+
+ popq %r15;
+ popq %r14;
+ popq %r13;
+ popq %r12;
+ popq %rbx;
+ popq %rbp;
+
+ ret;
+ENDPROC(des3_ede_x86_64_crypt_blk_3way)
+
+.data
+.align 16
+.L_s1:
+ .quad 0x0010100001010400, 0x0000000000000000
+ .quad 0x0000100000010000, 0x0010100001010404
+ .quad 0x0010100001010004, 0x0000100000010404
+ .quad 0x0000000000000004, 0x0000100000010000
+ .quad 0x0000000000000400, 0x0010100001010400
+ .quad 0x0010100001010404, 0x0000000000000400
+ .quad 0x0010000001000404, 0x0010100001010004
+ .quad 0x0010000001000000, 0x0000000000000004
+ .quad 0x0000000000000404, 0x0010000001000400
+ .quad 0x0010000001000400, 0x0000100000010400
+ .quad 0x0000100000010400, 0x0010100001010000
+ .quad 0x0010100001010000, 0x0010000001000404
+ .quad 0x0000100000010004, 0x0010000001000004
+ .quad 0x0010000001000004, 0x0000100000010004
+ .quad 0x0000000000000000, 0x0000000000000404
+ .quad 0x0000100000010404, 0x0010000001000000
+ .quad 0x0000100000010000, 0x0010100001010404
+ .quad 0x0000000000000004, 0x0010100001010000
+ .quad 0x0010100001010400, 0x0010000001000000
+ .quad 0x0010000001000000, 0x0000000000000400
+ .quad 0x0010100001010004, 0x0000100000010000
+ .quad 0x0000100000010400, 0x0010000001000004
+ .quad 0x0000000000000400, 0x0000000000000004
+ .quad 0x0010000001000404, 0x0000100000010404
+ .quad 0x0010100001010404, 0x0000100000010004
+ .quad 0x0010100001010000, 0x0010000001000404
+ .quad 0x0010000001000004, 0x0000000000000404
+ .quad 0x0000100000010404, 0x0010100001010400
+ .quad 0x0000000000000404, 0x0010000001000400
+ .quad 0x0010000001000400, 0x0000000000000000
+ .quad 0x0000100000010004, 0x0000100000010400
+ .quad 0x0000000000000000, 0x0010100001010004
+.L_s2:
+ .quad 0x0801080200100020, 0x0800080000000000
+ .quad 0x0000080000000000, 0x0001080200100020
+ .quad 0x0001000000100000, 0x0000000200000020
+ .quad 0x0801000200100020, 0x0800080200000020
+ .quad 0x0800000200000020, 0x0801080200100020
+ .quad 0x0801080000100000, 0x0800000000000000
+ .quad 0x0800080000000000, 0x0001000000100000
+ .quad 0x0000000200000020, 0x0801000200100020
+ .quad 0x0001080000100000, 0x0001000200100020
+ .quad 0x0800080200000020, 0x0000000000000000
+ .quad 0x0800000000000000, 0x0000080000000000
+ .quad 0x0001080200100020, 0x0801000000100000
+ .quad 0x0001000200100020, 0x0800000200000020
+ .quad 0x0000000000000000, 0x0001080000100000
+ .quad 0x0000080200000020, 0x0801080000100000
+ .quad 0x0801000000100000, 0x0000080200000020
+ .quad 0x0000000000000000, 0x0001080200100020
+ .quad 0x0801000200100020, 0x0001000000100000
+ .quad 0x0800080200000020, 0x0801000000100000
+ .quad 0x0801080000100000, 0x0000080000000000
+ .quad 0x0801000000100000, 0x0800080000000000
+ .quad 0x0000000200000020, 0x0801080200100020
+ .quad 0x0001080200100020, 0x0000000200000020
+ .quad 0x0000080000000000, 0x0800000000000000
+ .quad 0x0000080200000020, 0x0801080000100000
+ .quad 0x0001000000100000, 0x0800000200000020
+ .quad 0x0001000200100020, 0x0800080200000020
+ .quad 0x0800000200000020, 0x0001000200100020
+ .quad 0x0001080000100000, 0x0000000000000000
+ .quad 0x0800080000000000, 0x0000080200000020
+ .quad 0x0800000000000000, 0x0801000200100020
+ .quad 0x0801080200100020, 0x0001080000100000
+.L_s3:
+ .quad 0x0000002000000208, 0x0000202008020200
+ .quad 0x0000000000000000, 0x0000200008020008
+ .quad 0x0000002008000200, 0x0000000000000000
+ .quad 0x0000202000020208, 0x0000002008000200
+ .quad 0x0000200000020008, 0x0000000008000008
+ .quad 0x0000000008000008, 0x0000200000020000
+ .quad 0x0000202008020208, 0x0000200000020008
+ .quad 0x0000200008020000, 0x0000002000000208
+ .quad 0x0000000008000000, 0x0000000000000008
+ .quad 0x0000202008020200, 0x0000002000000200
+ .quad 0x0000202000020200, 0x0000200008020000
+ .quad 0x0000200008020008, 0x0000202000020208
+ .quad 0x0000002008000208, 0x0000202000020200
+ .quad 0x0000200000020000, 0x0000002008000208
+ .quad 0x0000000000000008, 0x0000202008020208
+ .quad 0x0000002000000200, 0x0000000008000000
+ .quad 0x0000202008020200, 0x0000000008000000
+ .quad 0x0000200000020008, 0x0000002000000208
+ .quad 0x0000200000020000, 0x0000202008020200
+ .quad 0x0000002008000200, 0x0000000000000000
+ .quad 0x0000002000000200, 0x0000200000020008
+ .quad 0x0000202008020208, 0x0000002008000200
+ .quad 0x0000000008000008, 0x0000002000000200
+ .quad 0x0000000000000000, 0x0000200008020008
+ .quad 0x0000002008000208, 0x0000200000020000
+ .quad 0x0000000008000000, 0x0000202008020208
+ .quad 0x0000000000000008, 0x0000202000020208
+ .quad 0x0000202000020200, 0x0000000008000008
+ .quad 0x0000200008020000, 0x0000002008000208
+ .quad 0x0000002000000208, 0x0000200008020000
+ .quad 0x0000202000020208, 0x0000000000000008
+ .quad 0x0000200008020008, 0x0000202000020200
+.L_s4:
+ .quad 0x1008020000002001, 0x1000020800002001
+ .quad 0x1000020800002001, 0x0000000800000000
+ .quad 0x0008020800002000, 0x1008000800000001
+ .quad 0x1008000000000001, 0x1000020000002001
+ .quad 0x0000000000000000, 0x0008020000002000
+ .quad 0x0008020000002000, 0x1008020800002001
+ .quad 0x1000000800000001, 0x0000000000000000
+ .quad 0x0008000800000000, 0x1008000000000001
+ .quad 0x1000000000000001, 0x0000020000002000
+ .quad 0x0008000000000000, 0x1008020000002001
+ .quad 0x0000000800000000, 0x0008000000000000
+ .quad 0x1000020000002001, 0x0000020800002000
+ .quad 0x1008000800000001, 0x1000000000000001
+ .quad 0x0000020800002000, 0x0008000800000000
+ .quad 0x0000020000002000, 0x0008020800002000
+ .quad 0x1008020800002001, 0x1000000800000001
+ .quad 0x0008000800000000, 0x1008000000000001
+ .quad 0x0008020000002000, 0x1008020800002001
+ .quad 0x1000000800000001, 0x0000000000000000
+ .quad 0x0000000000000000, 0x0008020000002000
+ .quad 0x0000020800002000, 0x0008000800000000
+ .quad 0x1008000800000001, 0x1000000000000001
+ .quad 0x1008020000002001, 0x1000020800002001
+ .quad 0x1000020800002001, 0x0000000800000000
+ .quad 0x1008020800002001, 0x1000000800000001
+ .quad 0x1000000000000001, 0x0000020000002000
+ .quad 0x1008000000000001, 0x1000020000002001
+ .quad 0x0008020800002000, 0x1008000800000001
+ .quad 0x1000020000002001, 0x0000020800002000
+ .quad 0x0008000000000000, 0x1008020000002001
+ .quad 0x0000000800000000, 0x0008000000000000
+ .quad 0x0000020000002000, 0x0008020800002000
+.L_s5:
+ .quad 0x0000001000000100, 0x0020001002080100
+ .quad 0x0020000002080000, 0x0420001002000100
+ .quad 0x0000000000080000, 0x0000001000000100
+ .quad 0x0400000000000000, 0x0020000002080000
+ .quad 0x0400001000080100, 0x0000000000080000
+ .quad 0x0020001002000100, 0x0400001000080100
+ .quad 0x0420001002000100, 0x0420000002080000
+ .quad 0x0000001000080100, 0x0400000000000000
+ .quad 0x0020000002000000, 0x0400000000080000
+ .quad 0x0400000000080000, 0x0000000000000000
+ .quad 0x0400001000000100, 0x0420001002080100
+ .quad 0x0420001002080100, 0x0020001002000100
+ .quad 0x0420000002080000, 0x0400001000000100
+ .quad 0x0000000000000000, 0x0420000002000000
+ .quad 0x0020001002080100, 0x0020000002000000
+ .quad 0x0420000002000000, 0x0000001000080100
+ .quad 0x0000000000080000, 0x0420001002000100
+ .quad 0x0000001000000100, 0x0020000002000000
+ .quad 0x0400000000000000, 0x0020000002080000
+ .quad 0x0420001002000100, 0x0400001000080100
+ .quad 0x0020001002000100, 0x0400000000000000
+ .quad 0x0420000002080000, 0x0020001002080100
+ .quad 0x0400001000080100, 0x0000001000000100
+ .quad 0x0020000002000000, 0x0420000002080000
+ .quad 0x0420001002080100, 0x0000001000080100
+ .quad 0x0420000002000000, 0x0420001002080100
+ .quad 0x0020000002080000, 0x0000000000000000
+ .quad 0x0400000000080000, 0x0420000002000000
+ .quad 0x0000001000080100, 0x0020001002000100
+ .quad 0x0400001000000100, 0x0000000000080000
+ .quad 0x0000000000000000, 0x0400000000080000
+ .quad 0x0020001002080100, 0x0400001000000100
+.L_s6:
+ .quad 0x0200000120000010, 0x0204000020000000
+ .quad 0x0000040000000000, 0x0204040120000010
+ .quad 0x0204000020000000, 0x0000000100000010
+ .quad 0x0204040120000010, 0x0004000000000000
+ .quad 0x0200040020000000, 0x0004040100000010
+ .quad 0x0004000000000000, 0x0200000120000010
+ .quad 0x0004000100000010, 0x0200040020000000
+ .quad 0x0200000020000000, 0x0000040100000010
+ .quad 0x0000000000000000, 0x0004000100000010
+ .quad 0x0200040120000010, 0x0000040000000000
+ .quad 0x0004040000000000, 0x0200040120000010
+ .quad 0x0000000100000010, 0x0204000120000010
+ .quad 0x0204000120000010, 0x0000000000000000
+ .quad 0x0004040100000010, 0x0204040020000000
+ .quad 0x0000040100000010, 0x0004040000000000
+ .quad 0x0204040020000000, 0x0200000020000000
+ .quad 0x0200040020000000, 0x0000000100000010
+ .quad 0x0204000120000010, 0x0004040000000000
+ .quad 0x0204040120000010, 0x0004000000000000
+ .quad 0x0000040100000010, 0x0200000120000010
+ .quad 0x0004000000000000, 0x0200040020000000
+ .quad 0x0200000020000000, 0x0000040100000010
+ .quad 0x0200000120000010, 0x0204040120000010
+ .quad 0x0004040000000000, 0x0204000020000000
+ .quad 0x0004040100000010, 0x0204040020000000
+ .quad 0x0000000000000000, 0x0204000120000010
+ .quad 0x0000000100000010, 0x0000040000000000
+ .quad 0x0204000020000000, 0x0004040100000010
+ .quad 0x0000040000000000, 0x0004000100000010
+ .quad 0x0200040120000010, 0x0000000000000000
+ .quad 0x0204040020000000, 0x0200000020000000
+ .quad 0x0004000100000010, 0x0200040120000010
+.L_s7:
+ .quad 0x0002000000200000, 0x2002000004200002
+ .quad 0x2000000004000802, 0x0000000000000000
+ .quad 0x0000000000000800, 0x2000000004000802
+ .quad 0x2002000000200802, 0x0002000004200800
+ .quad 0x2002000004200802, 0x0002000000200000
+ .quad 0x0000000000000000, 0x2000000004000002
+ .quad 0x2000000000000002, 0x0000000004000000
+ .quad 0x2002000004200002, 0x2000000000000802
+ .quad 0x0000000004000800, 0x2002000000200802
+ .quad 0x2002000000200002, 0x0000000004000800
+ .quad 0x2000000004000002, 0x0002000004200000
+ .quad 0x0002000004200800, 0x2002000000200002
+ .quad 0x0002000004200000, 0x0000000000000800
+ .quad 0x2000000000000802, 0x2002000004200802
+ .quad 0x0002000000200800, 0x2000000000000002
+ .quad 0x0000000004000000, 0x0002000000200800
+ .quad 0x0000000004000000, 0x0002000000200800
+ .quad 0x0002000000200000, 0x2000000004000802
+ .quad 0x2000000004000802, 0x2002000004200002
+ .quad 0x2002000004200002, 0x2000000000000002
+ .quad 0x2002000000200002, 0x0000000004000000
+ .quad 0x0000000004000800, 0x0002000000200000
+ .quad 0x0002000004200800, 0x2000000000000802
+ .quad 0x2002000000200802, 0x0002000004200800
+ .quad 0x2000000000000802, 0x2000000004000002
+ .quad 0x2002000004200802, 0x0002000004200000
+ .quad 0x0002000000200800, 0x0000000000000000
+ .quad 0x2000000000000002, 0x2002000004200802
+ .quad 0x0000000000000000, 0x2002000000200802
+ .quad 0x0002000004200000, 0x0000000000000800
+ .quad 0x2000000004000002, 0x0000000004000800
+ .quad 0x0000000000000800, 0x2002000000200002
+.L_s8:
+ .quad 0x0100010410001000, 0x0000010000001000
+ .quad 0x0000000000040000, 0x0100010410041000
+ .quad 0x0100000010000000, 0x0100010410001000
+ .quad 0x0000000400000000, 0x0100000010000000
+ .quad 0x0000000400040000, 0x0100000010040000
+ .quad 0x0100010410041000, 0x0000010000041000
+ .quad 0x0100010010041000, 0x0000010400041000
+ .quad 0x0000010000001000, 0x0000000400000000
+ .quad 0x0100000010040000, 0x0100000410000000
+ .quad 0x0100010010001000, 0x0000010400001000
+ .quad 0x0000010000041000, 0x0000000400040000
+ .quad 0x0100000410040000, 0x0100010010041000
+ .quad 0x0000010400001000, 0x0000000000000000
+ .quad 0x0000000000000000, 0x0100000410040000
+ .quad 0x0100000410000000, 0x0100010010001000
+ .quad 0x0000010400041000, 0x0000000000040000
+ .quad 0x0000010400041000, 0x0000000000040000
+ .quad 0x0100010010041000, 0x0000010000001000
+ .quad 0x0000000400000000, 0x0100000410040000
+ .quad 0x0000010000001000, 0x0000010400041000
+ .quad 0x0100010010001000, 0x0000000400000000
+ .quad 0x0100000410000000, 0x0100000010040000
+ .quad 0x0100000410040000, 0x0100000010000000
+ .quad 0x0000000000040000, 0x0100010410001000
+ .quad 0x0000000000000000, 0x0100010410041000
+ .quad 0x0000000400040000, 0x0100000410000000
+ .quad 0x0100000010040000, 0x0100010010001000
+ .quad 0x0100010410001000, 0x0000000000000000
+ .quad 0x0100010410041000, 0x0000010000041000
+ .quad 0x0000010000041000, 0x0000010400001000
+ .quad 0x0000010400001000, 0x0000000400040000
+ .quad 0x0100000010000000, 0x0100010010041000
diff --git a/arch/x86/crypto/des3_ede_glue.c b/arch/x86/crypto/des3_ede_glue.c
new file mode 100644
index 000000000000..0e9c0668fe4e
--- /dev/null
+++ b/arch/x86/crypto/des3_ede_glue.c
@@ -0,0 +1,509 @@
+/*
+ * Glue Code for assembler optimized version of 3DES
+ *
+ * Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ *
+ * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * CTR part based on code (crypto/ctr.c) by:
+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/processor.h>
+#include <crypto/des.h>
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+struct des3_ede_x86_ctx {
+ u32 enc_expkey[DES3_EDE_EXPKEY_WORDS];
+ u32 dec_expkey[DES3_EDE_EXPKEY_WORDS];
+};
+
+/* regular block cipher functions */
+asmlinkage void des3_ede_x86_64_crypt_blk(const u32 *expkey, u8 *dst,
+ const u8 *src);
+
+/* 3-way parallel cipher functions */
+asmlinkage void des3_ede_x86_64_crypt_blk_3way(const u32 *expkey, u8 *dst,
+ const u8 *src);
+
+static inline void des3_ede_enc_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ u32 *enc_ctx = ctx->enc_expkey;
+
+ des3_ede_x86_64_crypt_blk(enc_ctx, dst, src);
+}
+
+static inline void des3_ede_dec_blk(struct des3_ede_x86_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ u32 *dec_ctx = ctx->dec_expkey;
+
+ des3_ede_x86_64_crypt_blk(dec_ctx, dst, src);
+}
+
+static inline void des3_ede_enc_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ u32 *enc_ctx = ctx->enc_expkey;
+
+ des3_ede_x86_64_crypt_blk_3way(enc_ctx, dst, src);
+}
+
+static inline void des3_ede_dec_blk_3way(struct des3_ede_x86_ctx *ctx, u8 *dst,
+ const u8 *src)
+{
+ u32 *dec_ctx = ctx->dec_expkey;
+
+ des3_ede_x86_64_crypt_blk_3way(dec_ctx, dst, src);
+}
+
+static void des3_ede_x86_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ des3_ede_enc_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static void des3_ede_x86_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+ des3_ede_dec_blk(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+ const u32 *expkey)
+{
+ unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+ unsigned int nbytes;
+ int err;
+
+ err = blkcipher_walk_virt(desc, walk);
+
+ while ((nbytes = walk->nbytes)) {
+ u8 *wsrc = walk->src.virt.addr;
+ u8 *wdst = walk->dst.virt.addr;
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ des3_ede_x86_64_crypt_blk_3way(expkey, wdst,
+ wsrc);
+
+ wsrc += bsize * 3;
+ wdst += bsize * 3;
+ nbytes -= bsize * 3;
+ } while (nbytes >= bsize * 3);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ des3_ede_x86_64_crypt_blk(expkey, wdst, wsrc);
+
+ wsrc += bsize;
+ wdst += bsize;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+done:
+ err = blkcipher_walk_done(desc, walk, nbytes);
+ }
+
+ return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, ctx->enc_expkey);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_crypt(desc, &walk, ctx->dec_expkey);
+}
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u64 *src = (u64 *)walk->src.virt.addr;
+ u64 *dst = (u64 *)walk->dst.virt.addr;
+ u64 *iv = (u64 *)walk->iv;
+
+ do {
+ *dst = *src ^ *iv;
+ des3_ede_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
+ iv = dst;
+
+ src += 1;
+ dst += 1;
+ nbytes -= bsize;
+ } while (nbytes >= bsize);
+
+ *(u64 *)walk->iv = *iv;
+ return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_encrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ u64 *src = (u64 *)walk->src.virt.addr;
+ u64 *dst = (u64 *)walk->dst.virt.addr;
+ u64 ivs[3 - 1];
+ u64 last_iv;
+
+ /* Start of the last block. */
+ src += nbytes / bsize - 1;
+ dst += nbytes / bsize - 1;
+
+ last_iv = *src;
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ nbytes -= bsize * 3 - bsize;
+ src -= 3 - 1;
+ dst -= 3 - 1;
+
+ ivs[0] = src[0];
+ ivs[1] = src[1];
+
+ des3_ede_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
+
+ dst[1] ^= ivs[0];
+ dst[2] ^= ivs[1];
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ goto done;
+
+ *dst ^= *(src - 1);
+ src -= 1;
+ dst -= 1;
+ } while (nbytes >= bsize * 3);
+ }
+
+ /* Handle leftovers */
+ for (;;) {
+ des3_ede_dec_blk(ctx, (u8 *)dst, (u8 *)src);
+
+ nbytes -= bsize;
+ if (nbytes < bsize)
+ break;
+
+ *dst ^= *(src - 1);
+ src -= 1;
+ dst -= 1;
+ }
+
+done:
+ *dst ^= *(u64 *)walk->iv;
+ *(u64 *)walk->iv = last_iv;
+
+ return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt(desc, &walk);
+
+ while ((nbytes = walk.nbytes)) {
+ nbytes = __cbc_decrypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ return err;
+}
+
+static void ctr_crypt_final(struct des3_ede_x86_ctx *ctx,
+ struct blkcipher_walk *walk)
+{
+ u8 *ctrblk = walk->iv;
+ u8 keystream[DES3_EDE_BLOCK_SIZE];
+ u8 *src = walk->src.virt.addr;
+ u8 *dst = walk->dst.virt.addr;
+ unsigned int nbytes = walk->nbytes;
+
+ des3_ede_enc_blk(ctx, keystream, ctrblk);
+ crypto_xor(keystream, src, nbytes);
+ memcpy(dst, keystream, nbytes);
+
+ crypto_inc(ctrblk, DES3_EDE_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+ struct blkcipher_walk *walk)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ unsigned int bsize = DES3_EDE_BLOCK_SIZE;
+ unsigned int nbytes = walk->nbytes;
+ __be64 *src = (__be64 *)walk->src.virt.addr;
+ __be64 *dst = (__be64 *)walk->dst.virt.addr;
+ u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+ __be64 ctrblocks[3];
+
+ /* Process four block batch */
+ if (nbytes >= bsize * 3) {
+ do {
+ /* create ctrblks for parallel encrypt */
+ ctrblocks[0] = cpu_to_be64(ctrblk++);
+ ctrblocks[1] = cpu_to_be64(ctrblk++);
+ ctrblocks[2] = cpu_to_be64(ctrblk++);
+
+ des3_ede_enc_blk_3way(ctx, (u8 *)ctrblocks,
+ (u8 *)ctrblocks);
+
+ dst[0] = src[0] ^ ctrblocks[0];
+ dst[1] = src[1] ^ ctrblocks[1];
+ dst[2] = src[2] ^ ctrblocks[2];
+
+ src += 3;
+ dst += 3;
+ } while ((nbytes -= bsize * 3) >= bsize * 3);
+
+ if (nbytes < bsize)
+ goto done;
+ }
+
+ /* Handle leftovers */
+ do {
+ ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+ des3_ede_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+
+ dst[0] = src[0] ^ ctrblocks[0];
+
+ src += 1;
+ dst += 1;
+ } while ((nbytes -= bsize) >= bsize);
+
+done:
+ *(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+ return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+ struct scatterlist *src, unsigned int nbytes)
+{
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, DES3_EDE_BLOCK_SIZE);
+
+ while ((nbytes = walk.nbytes) >= DES3_EDE_BLOCK_SIZE) {
+ nbytes = __ctr_crypt(desc, &walk);
+ err = blkcipher_walk_done(desc, &walk, nbytes);
+ }
+
+ if (walk.nbytes) {
+ ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
+ err = blkcipher_walk_done(desc, &walk, 0);
+ }
+
+ return err;
+}
+
+static int des3_ede_x86_setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct des3_ede_x86_ctx *ctx = crypto_tfm_ctx(tfm);
+ u32 i, j, tmp;
+ int err;
+
+ /* Generate encryption context using generic implementation. */
+ err = __des3_ede_setkey(ctx->enc_expkey, &tfm->crt_flags, key, keylen);
+ if (err < 0)
+ return err;
+
+ /* Fix encryption context for this implementation and form decryption
+ * context. */
+ j = DES3_EDE_EXPKEY_WORDS - 2;
+ for (i = 0; i < DES3_EDE_EXPKEY_WORDS; i += 2, j -= 2) {
+ tmp = ror32(ctx->enc_expkey[i + 1], 4);
+ ctx->enc_expkey[i + 1] = tmp;
+
+ ctx->dec_expkey[j + 0] = ctx->enc_expkey[i + 0];
+ ctx->dec_expkey[j + 1] = tmp;
+ }
+
+ return 0;
+}
+
+static struct crypto_alg des3_ede_algs[4] = { {
+ .cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-asm",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_x86_ctx),
+ .cra_alignmask = 0,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_EDE_KEY_SIZE,
+ .cia_max_keysize = DES3_EDE_KEY_SIZE,
+ .cia_setkey = des3_ede_x86_setkey,
+ .cia_encrypt = des3_ede_x86_encrypt,
+ .cia_decrypt = des3_ede_x86_decrypt,
+ }
+ }
+}, {
+ .cra_name = "ecb(des3_ede)",
+ .cra_driver_name = "ecb-des3_ede-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_x86_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = des3_ede_x86_setkey,
+ .encrypt = ecb_encrypt,
+ .decrypt = ecb_decrypt,
+ },
+ },
+}, {
+ .cra_name = "cbc(des3_ede)",
+ .cra_driver_name = "cbc-des3_ede-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct des3_ede_x86_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = des3_ede_x86_setkey,
+ .encrypt = cbc_encrypt,
+ .decrypt = cbc_decrypt,
+ },
+ },
+}, {
+ .cra_name = "ctr(des3_ede)",
+ .cra_driver_name = "ctr-des3_ede-asm",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct des3_ede_x86_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = des3_ede_x86_setkey,
+ .encrypt = ctr_crypt,
+ .decrypt = ctr_crypt,
+ },
+ },
+} };
+
+static bool is_blacklisted_cpu(void)
+{
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ return false;
+
+ if (boot_cpu_data.x86 == 0x0f) {
+ /*
+ * On Pentium 4, des3_ede-x86_64 is slower than generic C
+ * implementation because use of 64bit rotates (which are really
+ * slow on P4). Therefore blacklist P4s.
+ */
+ return true;
+ }
+
+ return false;
+}
+
+static int force;
+module_param(force, int, 0);
+MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
+
+static int __init des3_ede_x86_init(void)
+{
+ if (!force && is_blacklisted_cpu()) {
+ pr_info("des3_ede-x86_64: performance on this CPU would be suboptimal: disabling des3_ede-x86_64.\n");
+ return -ENODEV;
+ }
+
+ return crypto_register_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs));
+}
+
+static void __exit des3_ede_x86_fini(void)
+{
+ crypto_unregister_algs(des3_ede_algs, ARRAY_SIZE(des3_ede_algs));
+}
+
+module_init(des3_ede_x86_init);
+module_exit(des3_ede_x86_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized");
+MODULE_ALIAS("des3_ede");
+MODULE_ALIAS("des3_ede-asm");
+MODULE_ALIAS("des");
+MODULE_ALIAS("des-asm");
+MODULE_AUTHOR("Jussi Kivilinna <jussi.kivilinna@iki.fi>");
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 3ca9762e1649..3bf000fab0ae 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -5,6 +5,7 @@ genhdr-y += unistd_64.h
genhdr-y += unistd_x32.h
generic-y += clkdev.h
-generic-y += early_ioremap.h
generic-y += cputime.h
+generic-y += early_ioremap.h
generic-y += mcs_spinlock.h
+generic-y += scatterlist.h
diff --git a/arch/x86/include/asm/acenv.h b/arch/x86/include/asm/acenv.h
index 66873297e9f5..1b010a859b8b 100644
--- a/arch/x86/include/asm/acenv.h
+++ b/arch/x86/include/asm/acenv.h
@@ -18,8 +18,6 @@
#define ACPI_FLUSH_CPU_CACHE() wbinvd()
-#ifdef CONFIG_ACPI
-
int __acpi_acquire_global_lock(unsigned int *lock);
int __acpi_release_global_lock(unsigned int *lock);
@@ -44,6 +42,4 @@ int __acpi_release_global_lock(unsigned int *lock);
: "=r"(n_hi), "=r"(n_lo) \
: "0"(n_hi), "1"(n_lo))
-#endif
-
#endif /* _ASM_X86_ACENV_H */
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index e06225eda635..0ab4f9fd2687 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -121,6 +121,11 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
}
+static inline bool acpi_has_cpu_in_madt(void)
+{
+ return !!acpi_lapic;
+}
+
#else /* !CONFIG_ACPI */
#define acpi_lapic 0
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 0a3f9c9f98d5..473bdbee378a 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -161,6 +161,20 @@ static inline int alternatives_text_reserved(void *start, void *end)
asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
: : "i" (0), ## input)
+/*
+ * This is similar to alternative_input. But it has two features and
+ * respective instructions.
+ *
+ * If CPU has feature2, newinstr2 is used.
+ * Otherwise, if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+#define alternative_input_2(oldinstr, newinstr1, feature1, newinstr2, \
+ feature2, input...) \
+ asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, \
+ newinstr2, feature2) \
+ : : "i" (0), ## input)
+
/* Like alternative_input, but with a single output argument */
#define alternative_io(oldinstr, newinstr, feature, output, input...) \
asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 19b0ebafcd3e..465b309af254 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -85,21 +85,13 @@ static inline bool apic_from_smp_config(void)
#include <asm/paravirt.h>
#endif
-#ifdef CONFIG_X86_64
-extern int is_vsmp_box(void);
-#else
-static inline int is_vsmp_box(void)
-{
- return 0;
-}
-#endif
extern int setup_profiling_timer(unsigned int);
static inline void native_apic_mem_write(u32 reg, u32 v)
{
volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
- alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
+ alternative_io("movl %0, %1", "xchgl %0, %1", X86_BUG_11AP,
ASM_OUTPUT2("=r" (v), "=m" (*addr)),
ASM_OUTPUT2("0" (v), "m" (*addr)));
}
@@ -300,7 +292,6 @@ struct apic {
int dest_logical;
unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
- unsigned long (*check_apicid_present)(int apicid);
void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
const struct cpumask *mask);
@@ -309,21 +300,11 @@ struct apic {
void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
void (*setup_apic_routing)(void);
- int (*multi_timer_check)(int apic, int irq);
int (*cpu_present_to_apicid)(int mps_cpu);
void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
- void (*setup_portio_remap)(void);
int (*check_phys_apicid_present)(int phys_apicid);
- void (*enable_apic_mode)(void);
int (*phys_pkg_id)(int cpuid_apic, int index_msb);
- /*
- * When one of the next two hooks returns 1 the apic
- * is switched to this. Essentially they are additional
- * probe functions:
- */
- int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
-
unsigned int (*get_apic_id)(unsigned long x);
unsigned long (*set_apic_id)(unsigned int id);
unsigned long apic_id_mask;
@@ -343,11 +324,7 @@ struct apic {
/* wakeup_secondary_cpu */
int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
- int trampoline_phys_low;
- int trampoline_phys_high;
-
bool wait_for_init_deassert;
- void (*smp_callin_clear_local_apic)(void);
void (*inquire_remote_apic)(int apicid);
/* apic ops */
@@ -378,14 +355,6 @@ struct apic {
* won't be applied properly during early boot in this case.
*/
int (*x86_32_early_logical_apicid)(int cpu);
-
- /*
- * Optional method called from setup_local_APIC() after logical
- * apicid is guaranteed to be known to initialize apicid -> node
- * mapping if NUMA initialization hasn't done so already. Don't
- * add new users.
- */
- int (*x86_32_numa_cpu_node)(int cpu);
#endif
};
@@ -496,14 +465,12 @@ static inline unsigned default_get_apic_id(unsigned long x)
}
/*
- * Warm reset vector default position:
+ * Warm reset vector position:
*/
-#define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467
-#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469
+#define TRAMPOLINE_PHYS_LOW 0x467
+#define TRAMPOLINE_PHYS_HIGH 0x469
#ifdef CONFIG_X86_64
-extern int default_acpi_madt_oem_check(char *, char *);
-
extern void apic_send_IPI_self(int vector);
DECLARE_PER_CPU(int, x2apic_extra_bits);
@@ -552,6 +519,8 @@ static inline int default_apic_id_valid(int apicid)
return (apicid < 255);
}
+extern int default_acpi_madt_oem_check(char *, char *);
+
extern void default_setup_apic_routing(void);
extern struct apic apic_noop;
@@ -635,11 +604,6 @@ static inline unsigned long default_check_apicid_used(physid_mask_t *map, int ap
return physid_isset(apicid, *map);
}
-static inline unsigned long default_check_apicid_present(int bit)
-{
- return physid_isset(bit, phys_cpu_present_map);
-}
-
static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
{
*retmap = *phys_map;
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 5c7198cca5ed..0f4460b5636d 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -99,7 +99,7 @@
#if defined(CONFIG_X86_PPRO_FENCE)
/*
- * For either of these options x86 doesn't have a strong TSO memory
+ * For this option x86 doesn't have a strong TSO memory
* model and we should fall back to full barriers.
*/
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index d47786acb016..99c105d78b7e 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -4,6 +4,8 @@
#include <linux/compiler.h>
#include <asm/alternative.h> /* Provides LOCK_PREFIX */
+#define __HAVE_ARCH_CMPXCHG 1
+
/*
* Non-existant functions to indicate usage errors at link time
* (or compile-time if the compiler implements __compiletime_error().
@@ -143,7 +145,6 @@ extern void __add_wrong_size(void)
# include <asm/cmpxchg_64.h>
#endif
-#ifdef __HAVE_ARCH_CMPXCHG
#define cmpxchg(ptr, old, new) \
__cmpxchg(ptr, old, new, sizeof(*(ptr)))
@@ -152,7 +153,6 @@ extern void __add_wrong_size(void)
#define cmpxchg_local(ptr, old, new) \
__cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
-#endif
/*
* xadd() adds "inc" to "*ptr" and atomically returns the previous
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index f8bf2eecab86..f7e142926481 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -34,8 +34,6 @@ static inline void set_64bit(volatile u64 *ptr, u64 value)
: "memory");
}
-#define __HAVE_ARCH_CMPXCHG 1
-
#ifdef CONFIG_X86_CMPXCHG64
#define cmpxchg64(ptr, o, n) \
((__typeof__(*(ptr)))__cmpxchg64((ptr), (unsigned long long)(o), \
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
index 614be87f1a9b..1af94697aae5 100644
--- a/arch/x86/include/asm/cmpxchg_64.h
+++ b/arch/x86/include/asm/cmpxchg_64.h
@@ -6,8 +6,6 @@ static inline void set_64bit(volatile u64 *ptr, u64 val)
*ptr = val;
}
-#define __HAVE_ARCH_CMPXCHG 1
-
#define cmpxchg64(ptr, o, n) \
({ \
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index e265ff95d16d..bb9b258d60e7 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -8,7 +8,7 @@
#include <asm/required-features.h>
#endif
-#define NCAPINTS 10 /* N 32-bit words worth of info */
+#define NCAPINTS 11 /* N 32-bit words worth of info */
#define NBUGINTS 1 /* N 32-bit bug flags */
/*
@@ -18,213 +18,218 @@
*/
/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
-#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */
-#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Exception */
-#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV (0*32+15) /* CMOV instructions */
+#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */
+#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */
+#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */
+#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */
+#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */
+#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */
+#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */
+#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */
+#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */
+#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */
+#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */
+#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */
+#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */
+#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */
+#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */
/* (plus FCMOVcc, FCOMI with FPU) */
-#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN (0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLUSH (0*32+19) /* CLFLUSH instruction */
-#define X86_FEATURE_DS (0*32+21) /* "dts" Debug Store */
-#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
-#define X86_FEATURE_XMM (0*32+25) /* "sse" */
-#define X86_FEATURE_XMM2 (0*32+26) /* "sse2" */
-#define X86_FEATURE_SELFSNOOP (0*32+27) /* "ss" CPU self snoop */
-#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC (0*32+29) /* "tm" Automatic clock control */
-#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */
-#define X86_FEATURE_PBE (0*32+31) /* Pending Break Enable */
+#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */
+#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */
+#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */
+#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */
+#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */
+#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */
+#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */
+#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
+#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */
+#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */
+#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */
+#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */
+#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */
+#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */
+#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */
/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MP (1*32+19) /* MP Capable. */
-#define X86_FEATURE_NX (1*32+20) /* Execute Disable */
-#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT (1*32+25) /* FXSAVE/FXRSTOR optimizations */
-#define X86_FEATURE_GBPAGES (1*32+26) /* "pdpe1gb" GB pages */
-#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */
+#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */
+#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */
+#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */
+#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */
+#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
+#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */
+#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */
+#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */
+#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */
+#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */
/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */
+#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */
+#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */
+#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */
/* Other features, Linux-defined mapping, word 3 */
/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */
+#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */
+#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
+#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
+#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
/* cpu types for specific tunings: */
-#define X86_FEATURE_K8 (3*32+ 4) /* "" Opteron, Athlon64 */
-#define X86_FEATURE_K7 (3*32+ 5) /* "" Athlon */
-#define X86_FEATURE_P3 (3*32+ 6) /* "" P3 */
-#define X86_FEATURE_P4 (3*32+ 7) /* "" P4 */
-#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
-#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
-#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* "" FXSAVE leaks FOP/FIP/FOP */
-#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32 (3*32+14) /* "" syscall in ia32 userspace */
-#define X86_FEATURE_SYSENTER32 (3*32+15) /* "" sysenter in ia32 userspace */
-#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well */
-#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* "" Mfence synchronizes RDTSC */
-#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* "" Lfence synchronizes RDTSC */
-#define X86_FEATURE_11AP (3*32+19) /* "" Bad local APIC aka 11AP */
-#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */
-#define X86_FEATURE_ALWAYS (3*32+21) /* "" Always-present feature */
-#define X86_FEATURE_XTOPOLOGY (3*32+22) /* cpu topology enum extensions */
-#define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */
-#define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */
-#define X86_FEATURE_CLFLUSH_MONITOR (3*32+25) /* "" clflush reqd with monitor */
-#define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */
-#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */
-#define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */
-#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */
-#define X86_FEATURE_NONSTOP_TSC_S3 (3*32+30) /* TSC doesn't stop in S3 state */
+#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */
+#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */
+#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */
+#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */
+#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
+#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */
+/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */
+#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */
+#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */
+#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */
+#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */
+#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */
+/* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */
+#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */
+#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */
+#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
+#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
+#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
+/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
+#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
+#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
+#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
+#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */
-#define X86_FEATURE_PCLMULQDQ (4*32+ 1) /* PCLMULQDQ instruction */
-#define X86_FEATURE_DTES64 (4*32+ 2) /* 64-bit Debug Store */
-#define X86_FEATURE_MWAIT (4*32+ 3) /* "monitor" Monitor/Mwait support */
-#define X86_FEATURE_DSCPL (4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
-#define X86_FEATURE_VMX (4*32+ 5) /* Hardware virtualization */
-#define X86_FEATURE_SMX (4*32+ 6) /* Safer mode */
-#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental SSE-3 */
-#define X86_FEATURE_CID (4*32+10) /* Context ID */
-#define X86_FEATURE_FMA (4*32+12) /* Fused multiply-add */
-#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
-#define X86_FEATURE_PDCM (4*32+15) /* Performance Capabilities */
-#define X86_FEATURE_PCID (4*32+17) /* Process Context Identifiers */
-#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */
-#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */
-#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */
-#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */
-#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */
-#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
-#define X86_FEATURE_TSC_DEADLINE_TIMER (4*32+24) /* Tsc deadline timer */
-#define X86_FEATURE_AES (4*32+25) /* AES instructions */
-#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
-#define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */
-#define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */
-#define X86_FEATURE_F16C (4*32+29) /* 16-bit fp conversions */
-#define X86_FEATURE_RDRAND (4*32+30) /* The RDRAND instruction */
-#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running on a hypervisor */
+#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
+#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */
+#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */
+#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */
+#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
+#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */
+#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */
+#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */
+#define X86_FEATURE_CID ( 4*32+10) /* Context ID */
+#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */
+#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */
+#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */
+#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */
+#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */
+#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */
+#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */
+#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */
+#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */
+#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */
+#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
+#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */
+#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */
+#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */
+#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */
+#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE (5*32+ 2) /* "rng" RNG present (xstore) */
-#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* "rng_en" RNG enabled */
-#define X86_FEATURE_XCRYPT (5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
-#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* "ace_en" on-CPU crypto enabled */
-#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */
-#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */
-#define X86_FEATURE_PHE (5*32+10) /* PadLock Hash Engine */
-#define X86_FEATURE_PHE_EN (5*32+11) /* PHE enabled */
-#define X86_FEATURE_PMM (5*32+12) /* PadLock Montgomery Multiplier */
-#define X86_FEATURE_PMM_EN (5*32+13) /* PMM enabled */
+#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */
+#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */
+#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
+#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
+#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */
+#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */
+#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */
+#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */
+#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */
+#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */
/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
-#define X86_FEATURE_SVM (6*32+ 2) /* Secure virtual machine */
-#define X86_FEATURE_EXTAPIC (6*32+ 3) /* Extended APIC space */
-#define X86_FEATURE_CR8_LEGACY (6*32+ 4) /* CR8 in 32-bit mode */
-#define X86_FEATURE_ABM (6*32+ 5) /* Advanced bit manipulation */
-#define X86_FEATURE_SSE4A (6*32+ 6) /* SSE-4A */
-#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE mode */
-#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
-#define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */
-#define X86_FEATURE_IBS (6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_XOP (6*32+11) /* extended AVX instructions */
-#define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */
-#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */
-#define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */
-#define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */
-#define X86_FEATURE_TCE (6*32+17) /* translation cache extension */
-#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
-#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
-#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
-#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
-#define X86_FEATURE_PERFCTR_NB (6*32+24) /* NB performance counter extensions */
-#define X86_FEATURE_PERFCTR_L2 (6*32+28) /* L2 performance counter extensions */
+#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */
+#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */
+#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */
+#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */
+#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */
+#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */
+#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
+#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
+#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */
+#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */
+#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */
+#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */
+#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */
+#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */
+#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */
+#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
+#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
/*
* Auxiliary flags: Linux defined - For features scattered in various
* CPUID levels like 0x6, 0xA etc, word 7
*/
-#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */
-#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */
-#define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */
-#define X86_FEATURE_EPB (7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
-#define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */
-#define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */
-#define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */
-#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */
-#define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */
-#define X86_FEATURE_PROC_FEEDBACK (7*32+ 9) /* AMD ProcFeedbackInterface */
+#define X86_FEATURE_IDA ( 7*32+ 0) /* Intel Dynamic Acceleration */
+#define X86_FEATURE_ARAT ( 7*32+ 1) /* Always Running APIC Timer */
+#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
+#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
+#define X86_FEATURE_PLN ( 7*32+ 5) /* Intel Power Limit Notification */
+#define X86_FEATURE_PTS ( 7*32+ 6) /* Intel Package Thermal Status */
+#define X86_FEATURE_DTHERM ( 7*32+ 7) /* Digital Thermal Sensor */
+#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
+#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
/* Virtualization flags: Linux defined, word 8 */
-#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
-#define X86_FEATURE_VNMI (8*32+ 1) /* Intel Virtual NMI */
-#define X86_FEATURE_FLEXPRIORITY (8*32+ 2) /* Intel FlexPriority */
-#define X86_FEATURE_EPT (8*32+ 3) /* Intel Extended Page Table */
-#define X86_FEATURE_VPID (8*32+ 4) /* Intel Virtual Processor ID */
-#define X86_FEATURE_NPT (8*32+ 5) /* AMD Nested Page Table support */
-#define X86_FEATURE_LBRV (8*32+ 6) /* AMD LBR Virtualization support */
-#define X86_FEATURE_SVML (8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
-#define X86_FEATURE_NRIPS (8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
-#define X86_FEATURE_TSCRATEMSR (8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
-#define X86_FEATURE_VMCBCLEAN (8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
-#define X86_FEATURE_FLUSHBYASID (8*32+11) /* AMD flush-by-ASID support */
-#define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */
-#define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */
-#define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */
+#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
+#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */
+#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */
+#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */
+#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */
+#define X86_FEATURE_NPT ( 8*32+ 5) /* AMD Nested Page Table support */
+#define X86_FEATURE_LBRV ( 8*32+ 6) /* AMD LBR Virtualization support */
+#define X86_FEATURE_SVML ( 8*32+ 7) /* "svm_lock" AMD SVM locking MSR */
+#define X86_FEATURE_NRIPS ( 8*32+ 8) /* "nrip_save" AMD SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR ( 8*32+ 9) /* "tsc_scale" AMD TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN ( 8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID ( 8*32+11) /* AMD flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS ( 8*32+12) /* AMD Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
-#define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
-#define X86_FEATURE_TSC_ADJUST (9*32+ 1) /* TSC adjustment MSR 0x3b */
-#define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */
-#define X86_FEATURE_HLE (9*32+ 4) /* Hardware Lock Elision */
-#define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */
-#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */
-#define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */
-#define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
-#define X86_FEATURE_INVPCID (9*32+10) /* Invalidate Processor Context ID */
-#define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */
-#define X86_FEATURE_MPX (9*32+14) /* Memory Protection Extension */
-#define X86_FEATURE_AVX512F (9*32+16) /* AVX-512 Foundation */
-#define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */
-#define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */
-#define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */
-#define X86_FEATURE_CLFLUSHOPT (9*32+23) /* CLFLUSHOPT instruction */
-#define X86_FEATURE_AVX512PF (9*32+26) /* AVX-512 Prefetch */
-#define X86_FEATURE_AVX512ER (9*32+27) /* AVX-512 Exponential and Reciprocal */
-#define X86_FEATURE_AVX512CD (9*32+28) /* AVX-512 Conflict Detection */
+#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
+#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */
+#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */
+#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */
+#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */
+#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */
+#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */
+#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
+#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */
+#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
+#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
+#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
+#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
+#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */
+
+/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
+#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */
+#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */
+#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */
+#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */
/*
* BUG word(s)
@@ -234,8 +239,11 @@
#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */
#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */
#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */
-#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* AMD Erratum 383 */
-#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* AMD Erratum 400 */
+#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
+#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
+#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */
+#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
+#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
@@ -245,6 +253,12 @@
extern const char * const x86_cap_flags[NCAPINTS*32];
extern const char * const x86_power_flags[32];
+/*
+ * In order to save room, we index into this array by doing
+ * X86_BUG_<name> - NCAPINTS*32.
+ */
+extern const char * const x86_bug_flags[NBUGINTS*32];
+
#define test_cpu_cap(c, bit) \
test_bit(bit, (unsigned long *)((c)->x86_capability))
@@ -301,7 +315,6 @@ extern const char * const x86_power_flags[32];
#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX)
#define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2)
#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT)
-#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP)
#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)
#define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR)
#define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR)
@@ -328,6 +341,7 @@ extern const char * const x86_power_flags[32];
#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC)
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
#define cpu_has_xsaveopt boot_cpu_has(X86_FEATURE_XSAVEOPT)
+#define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES)
#define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE)
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ)
@@ -347,9 +361,6 @@ extern const char * const x86_power_flags[32];
#undef cpu_has_pae
#define cpu_has_pae ___BUG___
-#undef cpu_has_mp
-#define cpu_has_mp 1
-
#undef cpu_has_k6_mtrr
#define cpu_has_k6_mtrr 0
@@ -539,20 +550,20 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
#define static_cpu_has_safe(bit) boot_cpu_has(bit)
#endif
-#define cpu_has_bug(c, bit) cpu_has(c, (bit))
-#define set_cpu_bug(c, bit) set_cpu_cap(c, (bit))
-#define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit));
+#define cpu_has_bug(c, bit) cpu_has(c, (bit))
+#define set_cpu_bug(c, bit) set_cpu_cap(c, (bit))
+#define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit))
-#define static_cpu_has_bug(bit) static_cpu_has((bit))
-#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
+#define static_cpu_has_bug(bit) static_cpu_has((bit))
+#define static_cpu_has_bug_safe(bit) static_cpu_has_safe((bit))
+#define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit))
-#define MAX_CPU_FEATURES (NCAPINTS * 32)
-#define cpu_have_feature boot_cpu_has
+#define MAX_CPU_FEATURES (NCAPINTS * 32)
+#define cpu_have_feature boot_cpu_has
-#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X"
-#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
- boot_cpu_data.x86_model
+#define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X"
+#define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \
+ boot_cpu_data.x86_model
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
-
#endif /* _ASM_X86_CPUFEATURE_H */
diff --git a/arch/x86/include/asm/crash.h b/arch/x86/include/asm/crash.h
new file mode 100644
index 000000000000..f498411f2500
--- /dev/null
+++ b/arch/x86/include/asm/crash.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_X86_CRASH_H
+#define _ASM_X86_CRASH_H
+
+int crash_load_segments(struct kimage *image);
+int crash_copy_backup_region(struct kimage *image);
+int crash_setup_memmap_entries(struct kimage *image,
+ struct boot_params *params);
+
+#endif /* _ASM_X86_CRASH_H */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 1eb5f6433ad8..044a2fd3c5fe 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -104,6 +104,8 @@ extern void __init runtime_code_page_mkexec(void);
extern void __init efi_runtime_mkexec(void);
extern void __init efi_dump_pagetable(void);
extern void __init efi_apply_memmap_quirks(void);
+extern int __init efi_reuse_config(u64 tables, int nr_tables);
+extern void efi_delete_dummy_variable(void);
struct efi_setup_data {
u64 fw_vendor;
@@ -156,6 +158,33 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
return EFI_SUCCESS;
}
#endif /* CONFIG_EFI_MIXED */
+
+
+/* arch specific definitions used by the stub code */
+
+struct efi_config {
+ u64 image_handle;
+ u64 table;
+ u64 allocate_pool;
+ u64 allocate_pages;
+ u64 get_memory_map;
+ u64 free_pool;
+ u64 free_pages;
+ u64 locate_handle;
+ u64 handle_protocol;
+ u64 exit_boot_services;
+ u64 text_output;
+ efi_status_t (*call)(unsigned long, ...);
+ bool is64;
+} __packed;
+
+extern struct efi_config *efi_early;
+
+#define efi_call_early(f, ...) \
+ efi_early->call(efi_early->f, __VA_ARGS__);
+
+extern bool efi_reboot_required(void);
+
#else
/*
* IF EFI is not configured, have the EFI calls return -ENOSYS.
@@ -168,6 +197,10 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS)
#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS)
static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
+static inline bool efi_reboot_required(void)
+{
+ return false;
+}
#endif /* CONFIG_EFI */
#endif /* _ASM_X86_EFI_H */
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 115e3689cd53..412ececa00b9 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -293,7 +293,7 @@ static inline int restore_fpu_checking(struct task_struct *tsk)
/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
is pending. Clear the x87 state here by setting it to fixed
values. "m" is a random variable that should be in L1 */
- if (unlikely(static_cpu_has_safe(X86_FEATURE_FXSAVE_LEAK))) {
+ if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) {
asm volatile(
"fnclex\n\t"
"emms\n\t"
@@ -508,9 +508,12 @@ static inline void user_fpu_begin(void)
static inline void __save_fpu(struct task_struct *tsk)
{
- if (use_xsave())
- xsave_state(&tsk->thread.fpu.state->xsave, -1);
- else
+ if (use_xsave()) {
+ if (unlikely(system_state == SYSTEM_BOOTING))
+ xsave_state_booting(&tsk->thread.fpu.state->xsave, -1);
+ else
+ xsave_state(&tsk->thread.fpu.state->xsave, -1);
+ } else
fpu_fxsave(&tsk->thread.fpu);
}
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 0525a8bdf65d..e1f7fecaa7d6 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -68,6 +68,8 @@ struct dyn_arch_ftrace {
int ftrace_int3_handler(struct pt_regs *regs);
+#define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR
+
#endif /* CONFIG_DYNAMIC_FTRACE */
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 230853da4ec0..0f5fb6b6567e 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -40,9 +40,6 @@ typedef struct {
DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
-/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
-#define MAX_HARDIRQS_PER_CPU NR_VECTORS
-
#define __ARCH_IRQ_STAT
#define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index a20365953bf8..ccffa53750a8 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -67,4 +67,9 @@ struct legacy_pic {
extern struct legacy_pic *legacy_pic;
extern struct legacy_pic null_legacy_pic;
+static inline int nr_legacy_irqs(void)
+{
+ return legacy_pic->nr_legacy_irqs;
+}
+
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 90f97b4b9347..0aeed5ca356e 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
#define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
+#define IOAPIC_MAP_ALLOC 0x1
+#define IOAPIC_MAP_CHECK 0x2
#ifdef CONFIG_X86_IO_APIC
@@ -118,9 +120,6 @@ extern int mp_irq_entries;
/* MP IRQ source entries */
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
/* Older SiS APIC requires we rewrite the index register */
extern int sis_apic_bug;
@@ -133,9 +132,6 @@ extern int noioapicquirk;
/* -1 if "noapic" boot option passed */
extern int noioapicreroute;
-/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
-extern int timer_through_8259;
-
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
@@ -145,24 +141,17 @@ extern int timer_through_8259;
struct io_apic_irq_attr;
struct irq_cfg;
-extern int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr);
-void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_insert_resources(void);
extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
unsigned int, int,
struct io_apic_irq_attr *);
-extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
- unsigned int, int,
- struct io_apic_irq_attr *);
extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg);
extern void native_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
-int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
extern int save_ioapic_entries(void);
extern void mask_ioapic_entries(void);
@@ -171,15 +160,40 @@ extern int restore_ioapic_entries(void);
extern void setup_ioapic_ids_from_mpc(void);
extern void setup_ioapic_ids_from_mpc_nocheck(void);
+enum ioapic_domain_type {
+ IOAPIC_DOMAIN_INVALID,
+ IOAPIC_DOMAIN_LEGACY,
+ IOAPIC_DOMAIN_STRICT,
+ IOAPIC_DOMAIN_DYNAMIC,
+};
+
+struct device_node;
+struct irq_domain;
+struct irq_domain_ops;
+
+struct ioapic_domain_cfg {
+ enum ioapic_domain_type type;
+ const struct irq_domain_ops *ops;
+ struct device_node *dev;
+};
+
struct mp_ioapic_gsi{
u32 gsi_base;
u32 gsi_end;
};
-extern struct mp_ioapic_gsi mp_gsi_routing[];
extern u32 gsi_top;
-int mp_find_ioapic(u32 gsi);
-int mp_find_ioapic_pin(int ioapic, u32 gsi);
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+
+extern int mp_find_ioapic(u32 gsi);
+extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern u32 mp_pin_to_gsi(int ioapic, int pin);
+extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
+extern void mp_unmap_irq(int irq);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg);
+extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq);
+extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
+extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
extern void __init pre_init_apic_IRQ0(void);
extern void mp_save_irq(struct mpc_intsrc *m);
@@ -217,14 +231,12 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
#define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop
-static const int timer_through_8259 = 0;
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
-
-struct io_apic_irq_attr;
-static inline int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr) { return 0; }
+static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
+static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
+static inline void mp_unmap_irq(int irq) { }
static inline int save_ioapic_entries(void)
{
diff --git a/arch/x86/include/asm/kexec-bzimage64.h b/arch/x86/include/asm/kexec-bzimage64.h
new file mode 100644
index 000000000000..d1b5d194e31d
--- /dev/null
+++ b/arch/x86/include/asm/kexec-bzimage64.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_KEXEC_BZIMAGE64_H
+#define _ASM_KEXEC_BZIMAGE64_H
+
+extern struct kexec_file_ops kexec_bzImage64_ops;
+
+#endif /* _ASM_KEXE_BZIMAGE64_H */
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index 17483a492f18..d2434c1cad05 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -23,6 +23,9 @@
#include <asm/page.h>
#include <asm/ptrace.h>
+#include <asm/bootparam.h>
+
+struct kimage;
/*
* KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -61,6 +64,10 @@
# define KEXEC_ARCH KEXEC_ARCH_X86_64
#endif
+/* Memory to backup during crash kdump */
+#define KEXEC_BACKUP_SRC_START (0UL)
+#define KEXEC_BACKUP_SRC_END (640 * 1024UL) /* 640K */
+
/*
* CPU does not save ss and sp on stack if execution is already
* running in kernel mode at the time of NMI occurrence. This code
@@ -160,6 +167,44 @@ struct kimage_arch {
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
+ /* Details of backup region */
+ unsigned long backup_src_start;
+ unsigned long backup_src_sz;
+
+ /* Physical address of backup segment */
+ unsigned long backup_load_addr;
+
+ /* Core ELF header buffer */
+ void *elf_headers;
+ unsigned long elf_headers_sz;
+ unsigned long elf_load_addr;
+};
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_X86_64
+/*
+ * Number of elements and order of elements in this structure should match
+ * with the ones in arch/x86/purgatory/entry64.S. If you make a change here
+ * make an appropriate change in purgatory too.
+ */
+struct kexec_entry64_regs {
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
};
#endif
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index a04fe4eb237d..eb181178fe0b 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -37,6 +37,7 @@ struct x86_instruction_info {
u8 modrm_reg; /* index of register used */
u8 modrm_rm; /* rm part of modrm */
u64 src_val; /* value of source operand */
+ u64 dst_val; /* value of destination operand */
u8 src_bytes; /* size of source operand */
u8 dst_bytes; /* size of destination operand */
u8 ad_bytes; /* size of src/dst address */
@@ -194,6 +195,7 @@ struct x86_emulate_ops {
int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
int (*set_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data);
int (*get_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata);
+ int (*check_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc);
int (*read_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc, u64 *pdata);
void (*halt)(struct x86_emulate_ctxt *ctxt);
void (*wbinvd)(struct x86_emulate_ctxt *ctxt);
@@ -231,7 +233,7 @@ struct operand {
union {
unsigned long val;
u64 val64;
- char valptr[sizeof(unsigned long) + 2];
+ char valptr[sizeof(sse128_t)];
sse128_t vec_val;
u64 mm_val;
void *data;
@@ -240,8 +242,8 @@ struct operand {
struct fetch_cache {
u8 data[15];
- unsigned long start;
- unsigned long end;
+ u8 *ptr;
+ u8 *end;
};
struct read_cache {
@@ -286,30 +288,36 @@ struct x86_emulate_ctxt {
u8 opcode_len;
u8 b;
u8 intercept;
- u8 lock_prefix;
- u8 rep_prefix;
u8 op_bytes;
u8 ad_bytes;
- u8 rex_prefix;
struct operand src;
struct operand src2;
struct operand dst;
- bool has_seg_override;
- u8 seg_override;
- u64 d;
int (*execute)(struct x86_emulate_ctxt *ctxt);
int (*check_perm)(struct x86_emulate_ctxt *ctxt);
+ /*
+ * The following six fields are cleared together,
+ * the rest are initialized unconditionally in x86_decode_insn
+ * or elsewhere
+ */
+ bool rip_relative;
+ u8 rex_prefix;
+ u8 lock_prefix;
+ u8 rep_prefix;
+ /* bitmaps of registers in _regs[] that can be read */
+ u32 regs_valid;
+ /* bitmaps of registers in _regs[] that have been written */
+ u32 regs_dirty;
/* modrm */
u8 modrm;
u8 modrm_mod;
u8 modrm_reg;
u8 modrm_rm;
u8 modrm_seg;
- bool rip_relative;
+ u8 seg_override;
+ u64 d;
unsigned long _eip;
struct operand memop;
- u32 regs_valid; /* bitmaps of registers in _regs[] that can be read */
- u32 regs_dirty; /* bitmaps of registers in _regs[] that have been written */
/* Fields above regs are cleared together. */
unsigned long _regs[NR_VCPU_REGS];
struct operand *memopp;
@@ -407,6 +415,7 @@ bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt);
#define EMULATION_OK 0
#define EMULATION_RESTART 1
#define EMULATION_INTERCEPTED 2
+void init_decode_cache(struct x86_emulate_ctxt *ctxt);
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt);
int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, int idt_index, int reason,
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 49205d01b9ad..572460175ba5 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -152,14 +152,16 @@ enum {
#define DR6_BD (1 << 13)
#define DR6_BS (1 << 14)
-#define DR6_FIXED_1 0xffff0ff0
-#define DR6_VOLATILE 0x0000e00f
+#define DR6_RTM (1 << 16)
+#define DR6_FIXED_1 0xfffe0ff0
+#define DR6_INIT 0xffff0ff0
+#define DR6_VOLATILE 0x0001e00f
#define DR7_BP_EN_MASK 0x000000ff
#define DR7_GE (1 << 9)
#define DR7_GD (1 << 13)
#define DR7_FIXED_1 0x00000400
-#define DR7_VOLATILE 0xffff23ff
+#define DR7_VOLATILE 0xffff2bff
/* apic attention bits */
#define KVM_APIC_CHECK_VAPIC 0
@@ -448,7 +450,7 @@ struct kvm_vcpu_arch {
u64 tsc_offset_adjustment;
u64 this_tsc_nsec;
u64 this_tsc_write;
- u8 this_tsc_generation;
+ u64 this_tsc_generation;
bool tsc_catchup;
bool tsc_always_catchup;
s8 virtual_tsc_shift;
@@ -591,7 +593,7 @@ struct kvm_arch {
u64 cur_tsc_nsec;
u64 cur_tsc_write;
u64 cur_tsc_offset;
- u8 cur_tsc_generation;
+ u64 cur_tsc_generation;
int nr_vcpus_matched_tsc;
spinlock_t pvclock_gtod_sync_lock;
@@ -717,7 +719,7 @@ struct kvm_x86_ops {
int (*handle_exit)(struct kvm_vcpu *vcpu);
void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
- u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
+ u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
void (*patch_hypercall)(struct kvm_vcpu *vcpu,
unsigned char *hypercall_addr);
void (*set_irq)(struct kvm_vcpu *vcpu);
@@ -1070,6 +1072,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu);
bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr);
int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
+int kvm_pmu_check_pmc(struct kvm_vcpu *vcpu, unsigned pmc);
int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data);
void kvm_handle_pmu_event(struct kvm_vcpu *vcpu);
void kvm_deliver_pmi(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h
index a55c7efcc4ed..0f555cc31984 100644
--- a/arch/x86/include/asm/mc146818rtc.h
+++ b/arch/x86/include/asm/mc146818rtc.h
@@ -13,7 +13,7 @@
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
#endif
-#if defined(CONFIG_X86_32) && defined(__HAVE_ARCH_CMPXCHG)
+#if defined(CONFIG_X86_32)
/*
* This lock provides nmi access to the CMOS/RTC registers. It has some
* special properties. It is owned by a CPU and stores the index register
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index be12c534fd59..166af2a8e865 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -3,6 +3,10 @@
#include <asm/desc.h>
#include <linux/atomic.h>
+#include <linux/mm_types.h>
+
+#include <trace/events/tlb.h>
+
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/paravirt.h>
@@ -44,6 +48,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
/* Re-load page tables */
load_cr3(next->pgd);
+ trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
/* Stop flush ipis for the previous mm */
cpumask_clear_cpu(cpu, mm_cpumask(prev));
@@ -71,6 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* to make sure to use no freed page tables.
*/
load_cr3(next->pgd);
+ trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
load_LDT_nolock(&next->context);
}
}
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index f5a617956735..b07233b64578 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
extern unsigned int boot_cpu_physical_apicid;
-extern unsigned int max_physical_apicid;
-extern int mpc_default_type;
extern unsigned long mp_lapic_addr;
#ifdef CONFIG_X86_LOCAL_APIC
@@ -88,15 +86,6 @@ static inline void early_reserve_e820_mpc_new(void) { }
#endif
int generic_processor_info(int apicid, int version);
-#ifdef CONFIG_ACPI
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
-extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
-extern void mp_config_acpi_legacy_irqs(void);
-struct device;
-extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
- int active_high_low);
-#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)
@@ -161,8 +150,4 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map)
extern physid_mask_t phys_cpu_present_map;
-extern int generic_mps_oem_check(struct mpc_table *, char *, char *);
-
-extern int default_acpi_madt_oem_check(char *, char *);
-
#endif /* _ASM_X86_MPSPEC_H */
diff --git a/arch/x86/include/asm/mutex_32.h b/arch/x86/include/asm/mutex_32.h
index 0208c3c2cbc6..85e6cda45a02 100644
--- a/arch/x86/include/asm/mutex_32.h
+++ b/arch/x86/include/asm/mutex_32.h
@@ -100,23 +100,11 @@ do { \
static inline int __mutex_fastpath_trylock(atomic_t *count,
int (*fail_fn)(atomic_t *))
{
- /*
- * We have two variants here. The cmpxchg based one is the best one
- * because it never induce a false contention state. It is included
- * here because architectures using the inc/dec algorithms over the
- * xchg ones are much more likely to support cmpxchg natively.
- *
- * If not we fall back to the spinlock based variant - that is
- * just as efficient (and simpler) as a 'destructive' probing of
- * the mutex state would be.
- */
-#ifdef __HAVE_ARCH_CMPXCHG
+ /* cmpxchg because it never induces a false contention state. */
if (likely(atomic_cmpxchg(count, 1, 0) == 1))
return 1;
+
return 0;
-#else
- return fail_fn(count);
-#endif
}
#endif /* _ASM_X86_MUTEX_32_H */
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h
index 1da25a5f96f9..a1410db38a1a 100644
--- a/arch/x86/include/asm/mwait.h
+++ b/arch/x86/include/asm/mwait.h
@@ -43,7 +43,7 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
{
if (!current_set_polling_and_test()) {
- if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
+ if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) {
mb();
clflush((void *)&current_thread_info()->flags);
mb();
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 775873d3be55..802dde30c928 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -70,7 +70,6 @@ extern bool __virt_addr_valid(unsigned long kaddr);
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
-#define __HAVE_ARCH_GATE_AREA 1
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/page_64.h b/arch/x86/include/asm/page_64.h
index 0f1ddee6a0ce..f408caf73430 100644
--- a/arch/x86/include/asm/page_64.h
+++ b/arch/x86/include/asm/page_64.h
@@ -39,4 +39,6 @@ void copy_page(void *to, void *from);
#endif /* !__ASSEMBLY__ */
+#define __HAVE_ARCH_GATE_AREA 1
+
#endif /* _ASM_X86_PAGE_64_H */
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 851bcdc5db04..fd472181a1d0 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -52,10 +52,9 @@
* Compared to the generic __my_cpu_offset version, the following
* saves one instruction and avoids clobbering a temp register.
*/
-#define raw_cpu_ptr(ptr) \
+#define arch_raw_cpu_ptr(ptr) \
({ \
unsigned long tcp_ptr__; \
- __verify_pcpu_ptr(ptr); \
asm volatile("add " __percpu_arg(1) ", %0" \
: "=r" (tcp_ptr__) \
: "m" (this_cpu_off), "0" (ptr)); \
diff --git a/arch/x86/include/asm/platform_sst_audio.h b/arch/x86/include/asm/platform_sst_audio.h
new file mode 100644
index 000000000000..0a4e140315b6
--- /dev/null
+++ b/arch/x86/include/asm/platform_sst_audio.h
@@ -0,0 +1,78 @@
+/*
+ * platform_sst_audio.h: sst audio platform data header file
+ *
+ * Copyright (C) 2012-14 Intel Corporation
+ * Author: Jeeja KP <jeeja.kp@intel.com>
+ * Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ * Vinod Koul ,vinod.koul@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _PLATFORM_SST_AUDIO_H_
+#define _PLATFORM_SST_AUDIO_H_
+
+#include <linux/sfi.h>
+
+enum sst_audio_task_id_mrfld {
+ SST_TASK_ID_NONE = 0,
+ SST_TASK_ID_SBA = 1,
+ SST_TASK_ID_MEDIA = 3,
+ SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
+};
+
+/* Device IDs for Merrifield are Pipe IDs,
+ * ref: DSP spec v0.75 */
+enum sst_audio_device_id_mrfld {
+ /* Output pipeline IDs */
+ PIPE_ID_OUT_START = 0x0,
+ PIPE_CODEC_OUT0 = 0x2,
+ PIPE_CODEC_OUT1 = 0x3,
+ PIPE_SPROT_LOOP_OUT = 0x4,
+ PIPE_MEDIA_LOOP1_OUT = 0x5,
+ PIPE_MEDIA_LOOP2_OUT = 0x6,
+ PIPE_VOIP_OUT = 0xC,
+ PIPE_PCM0_OUT = 0xD,
+ PIPE_PCM1_OUT = 0xE,
+ PIPE_PCM2_OUT = 0xF,
+ PIPE_MEDIA0_OUT = 0x12,
+ PIPE_MEDIA1_OUT = 0x13,
+/* Input Pipeline IDs */
+ PIPE_ID_IN_START = 0x80,
+ PIPE_CODEC_IN0 = 0x82,
+ PIPE_CODEC_IN1 = 0x83,
+ PIPE_SPROT_LOOP_IN = 0x84,
+ PIPE_MEDIA_LOOP1_IN = 0x85,
+ PIPE_MEDIA_LOOP2_IN = 0x86,
+ PIPE_VOIP_IN = 0x8C,
+ PIPE_PCM0_IN = 0x8D,
+ PIPE_PCM1_IN = 0x8E,
+ PIPE_MEDIA0_IN = 0x8F,
+ PIPE_MEDIA1_IN = 0x90,
+ PIPE_MEDIA2_IN = 0x91,
+ PIPE_RSVD = 0xFF,
+};
+
+/* The stream map for each platform consists of an array of the below
+ * stream map structure.
+ */
+struct sst_dev_stream_map {
+ u8 dev_num; /* device id */
+ u8 subdev_num; /* substream */
+ u8 direction;
+ u8 device_id; /* fw id */
+ u8 task_id; /* fw task */
+ u8 status;
+};
+
+struct sst_platform_data {
+ /* Intel software platform id*/
+ struct sst_dev_stream_map *pdev_strm_map;
+ unsigned int strm_map_size;
+};
+
+int add_sst_platform_device(void);
+#endif
+
diff --git a/arch/x86/include/asm/pmc_atom.h b/arch/x86/include/asm/pmc_atom.h
new file mode 100644
index 000000000000..fc7a17c05d35
--- /dev/null
+++ b/arch/x86/include/asm/pmc_atom.h
@@ -0,0 +1,107 @@
+/*
+ * Intel Atom SOC Power Management Controller Header File
+ * Copyright (c) 2014, 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.
+ *
+ */
+
+#ifndef PMC_ATOM_H
+#define PMC_ATOM_H
+
+/* ValleyView Power Control Unit PCI Device ID */
+#define PCI_DEVICE_ID_VLV_PMC 0x0F1C
+
+/* PMC Memory mapped IO registers */
+#define PMC_BASE_ADDR_OFFSET 0x44
+#define PMC_BASE_ADDR_MASK 0xFFFFFE00
+#define PMC_MMIO_REG_LEN 0x100
+#define PMC_REG_BIT_WIDTH 32
+
+/* BIOS uses FUNC_DIS to disable specific function */
+#define PMC_FUNC_DIS 0x34
+#define PMC_FUNC_DIS_2 0x38
+
+/* S0ix wake event control */
+#define PMC_S0IX_WAKE_EN 0x3C
+
+#define BIT_LPC_CLOCK_RUN BIT(4)
+#define BIT_SHARED_IRQ_GPSC BIT(5)
+#define BIT_ORED_DEDICATED_IRQ_GPSS BIT(18)
+#define BIT_ORED_DEDICATED_IRQ_GPSC BIT(19)
+#define BIT_SHARED_IRQ_GPSS BIT(20)
+
+#define PMC_WAKE_EN_SETTING ~(BIT_LPC_CLOCK_RUN | \
+ BIT_SHARED_IRQ_GPSC | \
+ BIT_ORED_DEDICATED_IRQ_GPSS | \
+ BIT_ORED_DEDICATED_IRQ_GPSC | \
+ BIT_SHARED_IRQ_GPSS)
+
+/* The timers acumulate time spent in sleep state */
+#define PMC_S0IR_TMR 0x80
+#define PMC_S0I1_TMR 0x84
+#define PMC_S0I2_TMR 0x88
+#define PMC_S0I3_TMR 0x8C
+#define PMC_S0_TMR 0x90
+/* Sleep state counter is in units of of 32us */
+#define PMC_TMR_SHIFT 5
+
+/* These registers reflect D3 status of functions */
+#define PMC_D3_STS_0 0xA0
+
+#define BIT_LPSS1_F0_DMA BIT(0)
+#define BIT_LPSS1_F1_PWM1 BIT(1)
+#define BIT_LPSS1_F2_PWM2 BIT(2)
+#define BIT_LPSS1_F3_HSUART1 BIT(3)
+#define BIT_LPSS1_F4_HSUART2 BIT(4)
+#define BIT_LPSS1_F5_SPI BIT(5)
+#define BIT_LPSS1_F6_XXX BIT(6)
+#define BIT_LPSS1_F7_XXX BIT(7)
+#define BIT_SCC_EMMC BIT(8)
+#define BIT_SCC_SDIO BIT(9)
+#define BIT_SCC_SDCARD BIT(10)
+#define BIT_SCC_MIPI BIT(11)
+#define BIT_HDA BIT(12)
+#define BIT_LPE BIT(13)
+#define BIT_OTG BIT(14)
+#define BIT_USH BIT(15)
+#define BIT_GBE BIT(16)
+#define BIT_SATA BIT(17)
+#define BIT_USB_EHCI BIT(18)
+#define BIT_SEC BIT(19)
+#define BIT_PCIE_PORT0 BIT(20)
+#define BIT_PCIE_PORT1 BIT(21)
+#define BIT_PCIE_PORT2 BIT(22)
+#define BIT_PCIE_PORT3 BIT(23)
+#define BIT_LPSS2_F0_DMA BIT(24)
+#define BIT_LPSS2_F1_I2C1 BIT(25)
+#define BIT_LPSS2_F2_I2C2 BIT(26)
+#define BIT_LPSS2_F3_I2C3 BIT(27)
+#define BIT_LPSS2_F4_I2C4 BIT(28)
+#define BIT_LPSS2_F5_I2C5 BIT(29)
+#define BIT_LPSS2_F6_I2C6 BIT(30)
+#define BIT_LPSS2_F7_I2C7 BIT(31)
+
+#define PMC_D3_STS_1 0xA4
+#define BIT_SMB BIT(0)
+#define BIT_OTG_SS_PHY BIT(1)
+#define BIT_USH_SS_PHY BIT(2)
+#define BIT_DFX BIT(3)
+
+/* PMC I/O Registers */
+#define ACPI_BASE_ADDR_OFFSET 0x40
+#define ACPI_BASE_ADDR_MASK 0xFFFFFE00
+#define ACPI_MMIO_REG_LEN 0x100
+
+#define PM1_CNT 0x4
+#define SLEEP_TYPE_MASK 0xFFFFECFF
+#define SLEEP_TYPE_S5 0x1C00
+#define SLEEP_ENABLE 0x2000
+#endif /* PMC_ATOM_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a4ea02351f4d..eb71ec794732 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -72,7 +72,6 @@ extern u16 __read_mostly tlb_lld_4k[NR_INFO];
extern u16 __read_mostly tlb_lld_2m[NR_INFO];
extern u16 __read_mostly tlb_lld_4m[NR_INFO];
extern u16 __read_mostly tlb_lld_1g[NR_INFO];
-extern s8 __read_mostly tlb_flushall_shift;
/*
* CPU type and hardware bug flags. Kept separately for each CPU.
@@ -386,8 +385,8 @@ struct bndcsr_struct {
struct xsave_hdr_struct {
u64 xstate_bv;
- u64 reserved1[2];
- u64 reserved2[5];
+ u64 xcomp_bv;
+ u64 reserved[6];
} __attribute__((packed));
struct xsave_struct {
@@ -696,6 +695,8 @@ static inline void cpu_relax(void)
rep_nop();
}
+#define cpu_relax_lowlatency() cpu_relax()
+
/* Stop speculative execution and prefetching of modified code. */
static inline void sync_core(void)
{
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index fbeb06ed0eaa..1d081ac1cd69 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -26,12 +26,10 @@
extern int of_ioapic;
extern u64 initial_dtb;
extern void add_dtb(u64 data);
-extern void x86_add_irq_domains(void);
void x86_of_pci_init(void);
void x86_dtb_init(void);
#else
static inline void add_dtb(u64 data) { }
-static inline void x86_add_irq_domains(void) { }
static inline void x86_of_pci_init(void) { }
static inline void x86_dtb_init(void) { }
#define of_ioapic 0
diff --git a/arch/x86/include/asm/qrwlock.h b/arch/x86/include/asm/qrwlock.h
index 70f46f07f94e..ae0e241e228b 100644
--- a/arch/x86/include/asm/qrwlock.h
+++ b/arch/x86/include/asm/qrwlock.h
@@ -3,7 +3,7 @@
#include <asm-generic/qrwlock_types.h>
-#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
+#ifndef CONFIG_X86_PPRO_FENCE
#define queue_write_unlock queue_write_unlock
static inline void queue_write_unlock(struct qrwlock *lock)
{
diff --git a/arch/x86/include/asm/scatterlist.h b/arch/x86/include/asm/scatterlist.h
deleted file mode 100644
index 4240878b9d76..000000000000
--- a/arch/x86/include/asm/scatterlist.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _ASM_X86_SCATTERLIST_H
-#define _ASM_X86_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* _ASM_X86_SCATTERLIST_H */
diff --git a/arch/x86/include/asm/smpboot_hooks.h b/arch/x86/include/asm/smpboot_hooks.h
index 49adfd7bb4a4..0da7409f0bec 100644
--- a/arch/x86/include/asm/smpboot_hooks.h
+++ b/arch/x86/include/asm/smpboot_hooks.h
@@ -17,11 +17,11 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
spin_unlock_irqrestore(&rtc_lock, flags);
local_flush_tlb();
pr_debug("1.\n");
- *((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) =
- start_eip >> 4;
+ *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
+ start_eip >> 4;
pr_debug("2.\n");
- *((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_low)) =
- start_eip & 0xf;
+ *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
+ start_eip & 0xf;
pr_debug("3.\n");
}
@@ -42,7 +42,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
CMOS_WRITE(0, 0xf);
spin_unlock_irqrestore(&rtc_lock, flags);
- *((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
+ *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
}
static inline void __init smpboot_setup_io_apic(void)
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index 0b46ef261c77..2d60a7813dfe 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -73,6 +73,7 @@
#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \
UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \
UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD)
+/* assuming UV3 is the same */
#define BAU_MISC_CONTROL_MULT_MASK 3
@@ -93,6 +94,8 @@
#define SOFTACK_MSHIFT UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT
#define SOFTACK_PSHIFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
#define SOFTACK_TIMEOUT_PERIOD UV_INTD_SOFT_ACK_TIMEOUT_PERIOD
+#define PREFETCH_HINT_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_PREFETCH_HINT_SHFT
+#define SB_STATUS_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
#define write_gmmr uv_write_global_mmr64
#define write_lmmr uv_write_local_mmr
#define read_lmmr uv_read_local_mmr
@@ -322,8 +325,9 @@ struct uv1_bau_msg_header {
/*
* UV2 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
* see figure 9-2 of harp_sys.pdf
+ * assuming UV3 is the same
*/
-struct uv2_bau_msg_header {
+struct uv2_3_bau_msg_header {
unsigned int base_dest_nasid:15; /* nasid of the first bit */
/* bits 14:0 */ /* in uvhub map */
unsigned int dest_subnodeid:5; /* must be 0x10, for the LB */
@@ -395,7 +399,7 @@ struct bau_desc {
*/
union bau_msg_header {
struct uv1_bau_msg_header uv1_hdr;
- struct uv2_bau_msg_header uv2_hdr;
+ struct uv2_3_bau_msg_header uv2_3_hdr;
} header;
struct bau_msg_payload payload;
@@ -631,11 +635,6 @@ struct bau_control {
struct hub_and_pnode *thp;
};
-static inline unsigned long read_mmr_uv2_status(void)
-{
- return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
-}
-
static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
@@ -760,7 +759,11 @@ static inline int atomic_read_short(const struct atomic_short *v)
*/
static inline int atom_asr(short i, struct atomic_short *v)
{
- return i + xadd(&v->counter, i);
+ short __i = i;
+ asm volatile(LOCK_PREFIX "xaddw %0, %1"
+ : "+r" (i), "+m" (v->counter)
+ : : "memory");
+ return i + __i;
}
/*
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 30be253dd283..8021bd28c0f1 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -18,15 +18,15 @@ struct vdso_image {
unsigned long alt, alt_len;
- unsigned long sym_end_mapping; /* Total size of the mapping */
-
- unsigned long sym_vvar_page;
- unsigned long sym_hpet_page;
- unsigned long sym_VDSO32_NOTE_MASK;
- unsigned long sym___kernel_sigreturn;
- unsigned long sym___kernel_rt_sigreturn;
- unsigned long sym___kernel_vsyscall;
- unsigned long sym_VDSO32_SYSENTER_RETURN;
+ long sym_vvar_start; /* Negative offset to the vvar area */
+
+ long sym_vvar_page;
+ long sym_hpet_page;
+ long sym_VDSO32_NOTE_MASK;
+ long sym___kernel_sigreturn;
+ long sym___kernel_rt_sigreturn;
+ long sym___kernel_vsyscall;
+ long sym_VDSO32_SYSENTER_RETURN;
};
#ifdef CONFIG_X86_64
diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h
index 44282fbf7bf9..c4b9dc2f67c5 100644
--- a/arch/x86/include/asm/vga.h
+++ b/arch/x86/include/asm/vga.h
@@ -17,10 +17,4 @@
#define vga_readb(x) (*(x))
#define vga_writeb(x, y) (*(y) = (x))
-#ifdef CONFIG_FB_EFI
-#define __ARCH_HAS_VGA_DEFAULT_DEVICE
-extern struct pci_dev *vga_default_device(void);
-extern void vga_set_default_device(struct pci_dev *pdev);
-#endif
-
#endif /* _ASM_X86_VGA_H */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 7004d21e6219..bcbfade26d8d 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -51,6 +51,9 @@
#define CPU_BASED_MONITOR_EXITING 0x20000000
#define CPU_BASED_PAUSE_EXITING 0x40000000
#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000
+
+#define CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x0401e172
+
/*
* Definitions of Secondary Processor-Based VM-Execution Controls.
*/
@@ -76,7 +79,7 @@
#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
-#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000002
+#define VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004
#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200
#define VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000
#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
@@ -89,7 +92,7 @@
#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff
-#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000002
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004
#define VM_ENTRY_IA32E_MODE 0x00000200
#define VM_ENTRY_SMM 0x00000400
#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index d949ef28c48b..7e7a79ada658 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -52,24 +52,170 @@ extern void xsave_init(void);
extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
extern int init_fpu(struct task_struct *child);
-static inline int fpu_xrstor_checking(struct xsave_struct *fx)
+/* These macros all use (%edi)/(%rdi) as the single memory argument. */
+#define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27"
+#define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37"
+#define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
+#define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f"
+#define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
+
+#define xstate_fault ".section .fixup,\"ax\"\n" \
+ "3: movl $-1,%[err]\n" \
+ " jmp 2b\n" \
+ ".previous\n" \
+ _ASM_EXTABLE(1b, 3b) \
+ : [err] "=r" (err)
+
+/*
+ * This function is called only during boot time when x86 caps are not set
+ * up and alternative can not be used yet.
+ */
+static inline int xsave_state_booting(struct xsave_struct *fx, u64 mask)
{
- int err;
+ u32 lmask = mask;
+ u32 hmask = mask >> 32;
+ int err = 0;
+
+ WARN_ON(system_state != SYSTEM_BOOTING);
+
+ if (boot_cpu_has(X86_FEATURE_XSAVES))
+ asm volatile("1:"XSAVES"\n\t"
+ "2:\n\t"
+ : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+ : "memory");
+ else
+ asm volatile("1:"XSAVE"\n\t"
+ "2:\n\t"
+ : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+ : "memory");
+
+ asm volatile(xstate_fault
+ : "0" (0)
+ : "memory");
+
+ return err;
+}
+
+/*
+ * This function is called only during boot time when x86 caps are not set
+ * up and alternative can not be used yet.
+ */
+static inline int xrstor_state_booting(struct xsave_struct *fx, u64 mask)
+{
+ u32 lmask = mask;
+ u32 hmask = mask >> 32;
+ int err = 0;
+
+ WARN_ON(system_state != SYSTEM_BOOTING);
- asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
- "2:\n"
- ".section .fixup,\"ax\"\n"
- "3: movl $-1,%[err]\n"
- " jmp 2b\n"
- ".previous\n"
- _ASM_EXTABLE(1b, 3b)
- : [err] "=r" (err)
- : "D" (fx), "m" (*fx), "a" (-1), "d" (-1), "0" (0)
+ if (boot_cpu_has(X86_FEATURE_XSAVES))
+ asm volatile("1:"XRSTORS"\n\t"
+ "2:\n\t"
+ : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+ : "memory");
+ else
+ asm volatile("1:"XRSTOR"\n\t"
+ "2:\n\t"
+ : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+ : "memory");
+
+ asm volatile(xstate_fault
+ : "0" (0)
+ : "memory");
+
+ return err;
+}
+
+/*
+ * Save processor xstate to xsave area.
+ */
+static inline int xsave_state(struct xsave_struct *fx, u64 mask)
+{
+ u32 lmask = mask;
+ u32 hmask = mask >> 32;
+ int err = 0;
+
+ /*
+ * If xsaves is enabled, xsaves replaces xsaveopt because
+ * it supports compact format and supervisor states in addition to
+ * modified optimization in xsaveopt.
+ *
+ * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
+ * because xsaveopt supports modified optimization which is not
+ * supported by xsave.
+ *
+ * If none of xsaves and xsaveopt is enabled, use xsave.
+ */
+ alternative_input_2(
+ "1:"XSAVE,
+ "1:"XSAVEOPT,
+ X86_FEATURE_XSAVEOPT,
+ "1:"XSAVES,
+ X86_FEATURE_XSAVES,
+ [fx] "D" (fx), "a" (lmask), "d" (hmask) :
+ "memory");
+ asm volatile("2:\n\t"
+ xstate_fault
+ : "0" (0)
: "memory");
return err;
}
+/*
+ * Restore processor xstate from xsave area.
+ */
+static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
+{
+ int err = 0;
+ u32 lmask = mask;
+ u32 hmask = mask >> 32;
+
+ /*
+ * Use xrstors to restore context if it is enabled. xrstors supports
+ * compacted format of xsave area which is not supported by xrstor.
+ */
+ alternative_input(
+ "1: " XRSTOR,
+ "1: " XRSTORS,
+ X86_FEATURE_XSAVES,
+ "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
+ : "memory");
+
+ asm volatile("2:\n"
+ xstate_fault
+ : "0" (0)
+ : "memory");
+
+ return err;
+}
+
+/*
+ * Save xstate context for old process during context switch.
+ */
+static inline void fpu_xsave(struct fpu *fpu)
+{
+ xsave_state(&fpu->state->xsave, -1);
+}
+
+/*
+ * Restore xstate context for new process during context switch.
+ */
+static inline int fpu_xrstor_checking(struct xsave_struct *fx)
+{
+ return xrstor_state(fx, -1);
+}
+
+/*
+ * Save xstate to user space xsave area.
+ *
+ * We don't use modified optimization because xrstor/xrstors might track
+ * a different application.
+ *
+ * We don't use compacted format xsave area for
+ * backward compatibility for old applications which don't understand
+ * compacted format of xsave area.
+ */
static inline int xsave_user(struct xsave_struct __user *buf)
{
int err;
@@ -83,69 +229,34 @@ static inline int xsave_user(struct xsave_struct __user *buf)
return -EFAULT;
__asm__ __volatile__(ASM_STAC "\n"
- "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
+ "1:"XSAVE"\n"
"2: " ASM_CLAC "\n"
- ".section .fixup,\"ax\"\n"
- "3: movl $-1,%[err]\n"
- " jmp 2b\n"
- ".previous\n"
- _ASM_EXTABLE(1b,3b)
- : [err] "=r" (err)
+ xstate_fault
: "D" (buf), "a" (-1), "d" (-1), "0" (0)
: "memory");
return err;
}
+/*
+ * Restore xstate from user space xsave area.
+ */
static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
{
- int err;
+ int err = 0;
struct xsave_struct *xstate = ((__force struct xsave_struct *)buf);
u32 lmask = mask;
u32 hmask = mask >> 32;
__asm__ __volatile__(ASM_STAC "\n"
- "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
+ "1:"XRSTOR"\n"
"2: " ASM_CLAC "\n"
- ".section .fixup,\"ax\"\n"
- "3: movl $-1,%[err]\n"
- " jmp 2b\n"
- ".previous\n"
- _ASM_EXTABLE(1b,3b)
- : [err] "=r" (err)
+ xstate_fault
: "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
: "memory"); /* memory required? */
return err;
}
-static inline void xrstor_state(struct xsave_struct *fx, u64 mask)
-{
- u32 lmask = mask;
- u32 hmask = mask >> 32;
-
- asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
- : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
- : "memory");
-}
-
-static inline void xsave_state(struct xsave_struct *fx, u64 mask)
-{
- u32 lmask = mask;
- u32 hmask = mask >> 32;
+void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
+void setup_xstate_comp(void);
- asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
- : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
- : "memory");
-}
-
-static inline void fpu_xsave(struct fpu *fpu)
-{
- /* This, however, we can work around by forcing the compiler to select
- an addressing mode that doesn't require extended registers. */
- alternative_input(
- ".byte " REX_PREFIX "0x0f,0xae,0x27",
- ".byte " REX_PREFIX "0x0f,0xae,0x37",
- X86_FEATURE_XSAVEOPT,
- [fx] "D" (&fpu->state->xsave), "a" (-1), "d" (-1) :
- "memory");
-}
#endif
diff --git a/arch/x86/include/uapi/asm/Kbuild b/arch/x86/include/uapi/asm/Kbuild
index 09409c44f9a5..3dec769cadf7 100644
--- a/arch/x86/include/uapi/asm/Kbuild
+++ b/arch/x86/include/uapi/asm/Kbuild
@@ -22,6 +22,7 @@ header-y += ipcbuf.h
header-y += ist.h
header-y += kvm.h
header-y += kvm_para.h
+header-y += kvm_perf.h
header-y += ldt.h
header-y += mce.h
header-y += mman.h
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index d3a87780c70b..d7dcef58aefa 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -23,7 +23,10 @@
#define GP_VECTOR 13
#define PF_VECTOR 14
#define MF_VECTOR 16
+#define AC_VECTOR 17
#define MC_VECTOR 18
+#define XM_VECTOR 19
+#define VE_VECTOR 20
/* Select x86 specific features in <linux/kvm.h> */
#define __KVM_HAVE_PIT
diff --git a/arch/x86/include/uapi/asm/kvm_perf.h b/arch/x86/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..3bb964f88aa1
--- /dev/null
+++ b/arch/x86/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_X86_KVM_PERF_H
+#define _ASM_X86_KVM_PERF_H
+
+#include <asm/svm.h>
+#include <asm/vmx.h>
+#include <asm/kvm.h>
+
+#define DECODE_STR_LEN 20
+
+#define VCPU_ID "vcpu_id"
+
+#define KVM_ENTRY_TRACE "kvm:kvm_entry"
+#define KVM_EXIT_TRACE "kvm:kvm_exit"
+#define KVM_EXIT_REASON "exit_reason"
+
+#endif /* _ASM_X86_KVM_PERF_H */
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index 4a7aecd2ea13..e21331ce368f 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -300,6 +300,8 @@
#define MSR_IA32_TSC_ADJUST 0x0000003b
#define MSR_IA32_BNDCFGS 0x00000d90
+#define MSR_IA32_XSS 0x00000da0
+
#define FEATURE_CONTROL_LOCKED (1<<0)
#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1)
#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
@@ -561,6 +563,7 @@
/* VMX_BASIC bits and bitmasks */
#define VMX_BASIC_VMCS_SIZE_SHIFT 32
+#define VMX_BASIC_TRUE_CTLS (1ULL << 55)
#define VMX_BASIC_64 0x0001000000000000LLU
#define VMX_BASIC_MEM_TYPE_SHIFT 50
#define VMX_BASIC_MEM_TYPE_MASK 0x003c000000000000LLU
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 047f9ff2e36c..b5ea75c4a4b4 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_EFI) += sysfb_efi.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
obj-$(CONFIG_TRACING) += tracepoint.o
obj-$(CONFIG_IOSF_MBI) += iosf_mbi.o
+obj-$(CONFIG_PMC_ATOM) += pmc_atom.o
###
# 64 bit specific files
@@ -117,4 +118,5 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
obj-y += vsmp_64.o
+ obj-$(CONFIG_KEXEC) += kexec-bzimage64.o
endif
diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile
index 163b22581472..3242e591fa82 100644
--- a/arch/x86/kernel/acpi/Makefile
+++ b/arch/x86/kernel/acpi/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_ACPI) += boot.o
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
+obj-$(CONFIG_ACPI_APEI) += apei.o
ifneq ($(CONFIG_ACPI_PROCESSOR),)
obj-y += cstate.o
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
new file mode 100644
index 000000000000..c280df6b2aa2
--- /dev/null
+++ b/arch/x86/kernel/acpi/apei.c
@@ -0,0 +1,62 @@
+/*
+ * Arch-specific APEI-related functions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <acpi/apei.h>
+
+#include <asm/mce.h>
+#include <asm/tlbflush.h>
+
+int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data)
+{
+#ifdef CONFIG_X86_MCE
+ int i;
+ struct acpi_hest_ia_corrected *cmc;
+ struct acpi_hest_ia_error_bank *mc_bank;
+
+ if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
+ return 0;
+
+ cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
+ if (!cmc->enabled)
+ return 0;
+
+ /*
+ * We expect HEST to provide a list of MC banks that report errors
+ * in firmware first mode. Otherwise, return non-zero value to
+ * indicate that we are done parsing HEST.
+ */
+ if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) ||
+ !cmc->num_hardware_banks)
+ return 1;
+
+ pr_info("HEST: Enabling Firmware First mode for corrected errors.\n");
+
+ mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1);
+ for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++)
+ mce_disable_bank(mc_bank->bank_number);
+#endif
+ return 1;
+}
+
+void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
+{
+#ifdef CONFIG_X86_MCE
+ apei_mce_report_mem_error(sev, mem_err);
+#endif
+}
+
+void arch_apei_flush_tlb_one(unsigned long addr)
+{
+ __flush_tlb_one(addr);
+}
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 86281ffb96d6..b436fc735aa4 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <linux/ioport.h>
@@ -43,6 +44,7 @@
#include <asm/io.h>
#include <asm/mpspec.h>
#include <asm/smp.h>
+#include <asm/i8259.h>
#include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
static int __initdata acpi_force = 0;
@@ -74,10 +76,6 @@ int acpi_fix_pin2_polarity __initdata;
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#endif
-#ifndef __HAVE_ARCH_CMPXCHG
-#warning ACPI uses CMPXCHG, i486 and later hardware
-#endif
-
/* --------------------------------------------------------------------------
Boot-time Configuration
-------------------------------------------------------------------------- */
@@ -97,44 +95,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
-static unsigned int gsi_to_irq(unsigned int gsi)
-{
- unsigned int irq = gsi + NR_IRQS_LEGACY;
- unsigned int i;
-
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
- if (isa_irq_to_gsi[i] == gsi) {
- return i;
- }
- }
-
- /* Provide an identity mapping of gsi == irq
- * except on truly weird platforms that have
- * non isa irqs in the first 16 gsis.
- */
- if (gsi >= NR_IRQS_LEGACY)
- irq = gsi;
- else
- irq = gsi_top + gsi;
-
- return irq;
-}
-
-static u32 irq_to_gsi(int irq)
-{
- unsigned int gsi;
-
- if (irq < NR_IRQS_LEGACY)
- gsi = isa_irq_to_gsi[irq];
- else if (irq < gsi_top)
- gsi = irq;
- else if (irq < (gsi_top + NR_IRQS_LEGACY))
- gsi = irq - gsi_top;
- else
- gsi = 0xffffffff;
-
- return gsi;
-}
+#define ACPI_INVALID_GSI INT_MIN
/*
* This is just a simple wrapper around early_ioremap(),
@@ -345,11 +306,145 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
+#define MP_ISA_BUS 0
+
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
+{
+ int ioapic;
+ int pin;
+ struct mpc_intsrc mp_irq;
+
+ /*
+ * Convert 'gsi' to 'ioapic.pin'.
+ */
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return;
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+
+ /*
+ * TBD: This check is for faulty timer entries, where the override
+ * erroneously sets the trigger to level, resulting in a HUGE
+ * increase of timer interrupts!
+ */
+ if ((bus_irq == 0) && (trigger == 3))
+ trigger = 1;
+
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger << 2) | polarity;
+ mp_irq.srcbus = MP_ISA_BUS;
+ mp_irq.srcbusirq = bus_irq; /* IRQ */
+ mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
+ mp_irq.dstirq = pin; /* INTIN# */
+
+ mp_save_irq(&mp_irq);
+
+ /*
+ * Reset default identity mapping if gsi is also an legacy IRQ,
+ * otherwise there will be more than one entry with the same GSI
+ * and acpi_isa_irq_to_gsi() may give wrong result.
+ */
+ if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
+ isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
+ isa_irq_to_gsi[bus_irq] = gsi;
+}
+
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
+{
+#ifdef CONFIG_X86_MPPARSE
+ struct mpc_intsrc mp_irq;
+ struct pci_dev *pdev;
+ unsigned char number;
+ unsigned int devfn;
+ int ioapic;
+ u8 pin;
+
+ if (!acpi_ioapic)
+ return 0;
+ if (!dev || !dev_is_pci(dev))
+ return 0;
+
+ pdev = to_pci_dev(dev);
+ number = pdev->bus->number;
+ devfn = pdev->devfn;
+ pin = pdev->pin;
+ /* print the entry should happen on mptable identically */
+ mp_irq.type = MP_INTSRC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ mp_irq.srcbus = number;
+ mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ mp_irq.dstapic = mpc_ioapic_id(ioapic);
+ mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+
+ mp_save_irq(&mp_irq);
+#endif
+ return 0;
+}
+
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
+{
+ int irq, node;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return gsi;
+
+ /* Don't set up the ACPI SCI because it's already set up */
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return gsi;
+
+ trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
+ polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
+ node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+ if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
+ pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+ return -1;
+ }
+
+ irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+ if (irq < 0)
+ return irq;
+
+ if (enable_update_mptable)
+ mp_config_acpi_gsi(dev, gsi, trigger, polarity);
+
+ return irq;
+}
+
+static void mp_unregister_gsi(u32 gsi)
+{
+ int irq;
+
+ if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ return;
+
+ if (acpi_gbl_FADT.sci_interrupt == gsi)
+ return;
+
+ irq = mp_map_gsi_to_irq(gsi, 0);
+ if (irq > 0)
+ mp_unmap_irq(irq);
+}
+
+static struct irq_domain_ops acpi_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
+};
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
struct acpi_madt_io_apic *ioapic = NULL;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &acpi_irqdomain_ops,
+ };
ioapic = (struct acpi_madt_io_apic *)header;
@@ -358,8 +453,12 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
acpi_table_print_madt_entry(header);
- mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base);
+ /* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
+ if (ioapic->global_irq_base < nr_legacy_irqs())
+ cfg.type = IOAPIC_DOMAIN_LEGACY;
+
+ mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
+ &cfg);
return 0;
}
@@ -382,11 +481,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
- /*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
- * If GSI is < 16, this will update its flags,
- * else it will create a new mp_irqs[] entry.
- */
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
/*
@@ -508,25 +602,28 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}
-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- *irq = gsi_to_irq(gsi);
+ int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
-#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
-#endif
+ if (irq >= 0) {
+ *irqp = irq;
+ return 0;
+ }
- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq >= 16)
- return -1;
- *gsi = irq_to_gsi(isa_irq);
- return 0;
+ if (isa_irq < nr_legacy_irqs() &&
+ isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
+ *gsi = isa_irq_to_gsi[isa_irq];
+ return 0;
+ }
+
+ return -1;
}
static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
@@ -546,15 +643,25 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
{
+ int irq = gsi;
+
#ifdef CONFIG_X86_IO_APIC
- gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+ irq = mp_register_gsi(dev, gsi, trigger, polarity);
#endif
- return gsi;
+ return irq;
+}
+
+static void acpi_unregister_gsi_ioapic(u32 gsi)
+{
+#ifdef CONFIG_X86_IO_APIC
+ mp_unregister_gsi(gsi);
+#endif
}
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity) = acpi_register_gsi_pic;
+void (*__acpi_unregister_gsi)(u32 gsi) = NULL;
#ifdef CONFIG_ACPI_SLEEP
int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@ -568,32 +675,22 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int irq;
- unsigned int plat_gsi = gsi;
-
- plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
-
- return irq;
+ return __acpi_register_gsi(dev, gsi, trigger, polarity);
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
void acpi_unregister_gsi(u32 gsi)
{
+ if (__acpi_unregister_gsi)
+ __acpi_unregister_gsi(gsi);
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
-void __init acpi_set_irq_model_pic(void)
-{
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
- __acpi_register_gsi = acpi_register_gsi_pic;
- acpi_ioapic = 0;
-}
-
-void __init acpi_set_irq_model_ioapic(void)
+static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
+ __acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
acpi_ioapic = 1;
}
@@ -829,9 +926,8 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -856,9 +952,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -886,11 +981,10 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count;
}
- x2count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
- acpi_parse_x2apic_nmi, 0);
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+ x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+ acpi_parse_x2apic_nmi, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+ acpi_parse_lapic_nmi, 0);
if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -901,44 +995,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
-#define MP_ISA_BUS 0
-
-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
-{
- int ioapic;
- int pin;
- struct mpc_intsrc mp_irq;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0)
- return;
- pin = mp_find_ioapic_pin(ioapic, gsi);
-
- /*
- * TBD: This check is for faulty timer entries, where the override
- * erroneously sets the trigger to level, resulting in a HUGE
- * increase of timer interrupts!
- */
- if ((bus_irq == 0) && (trigger == 3))
- trigger = 1;
-
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger << 2) | polarity;
- mp_irq.srcbus = MP_ISA_BUS;
- mp_irq.srcbusirq = bus_irq; /* IRQ */
- mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
- mp_irq.dstirq = pin; /* INTIN# */
-
- mp_save_irq(&mp_irq);
-
- isa_irq_to_gsi[bus_irq] = gsi;
-}
-
-void __init mp_config_acpi_legacy_irqs(void)
+static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
struct mpc_intsrc mp_irq;
@@ -956,7 +1013,7 @@ void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < nr_legacy_irqs(); i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
@@ -1004,84 +1061,6 @@ void __init mp_config_acpi_legacy_irqs(void)
}
}
-static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
- int polarity)
-{
-#ifdef CONFIG_X86_MPPARSE
- struct mpc_intsrc mp_irq;
- struct pci_dev *pdev;
- unsigned char number;
- unsigned int devfn;
- int ioapic;
- u8 pin;
-
- if (!acpi_ioapic)
- return 0;
- if (!dev || !dev_is_pci(dev))
- return 0;
-
- pdev = to_pci_dev(dev);
- number = pdev->bus->number;
- devfn = pdev->devfn;
- pin = pdev->pin;
- /* print the entry should happen on mptable identically */
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
- (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
- mp_irq.srcbus = number;
- mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
- ioapic = mp_find_ioapic(gsi);
- mp_irq.dstapic = mpc_ioapic_id(ioapic);
- mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-
- mp_save_irq(&mp_irq);
-#endif
- return 0;
-}
-
-int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
-{
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
-
- if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
- return gsi;
-
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_gbl_FADT.sci_interrupt == gsi)
- return gsi;
-
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
- }
-
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
- }
-
- if (enable_update_mptable)
- mp_config_acpi_gsi(dev, gsi, trigger, polarity);
-
- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
- if (ret < 0)
- gsi = INT_MIN;
-
- return gsi;
-}
-
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
@@ -1111,9 +1090,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
- MAX_IO_APICS);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
@@ -1122,9 +1100,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return count;
}
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_parse_int_src_ovr, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
@@ -1143,9 +1120,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
/* Fill in identity legacy mappings where no override */
mp_config_acpi_legacy_irqs();
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+ acpi_parse_nmi_src, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad28db7e6bde..67760275544b 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
/*
* The highest APIC ID seen during enumeration.
*/
-unsigned int max_physical_apicid;
+static unsigned int max_physical_apicid;
/*
* Bitmask of physically existing CPUs:
@@ -1342,17 +1342,6 @@ void setup_local_APIC(void)
/* always use the value from LDR */
early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
logical_smp_processor_id();
-
- /*
- * Some NUMA implementations (NUMAQ) don't initialize apicid to
- * node mapping during NUMA init. Now that logical apicid is
- * guaranteed to be known, give it another chance. This is already
- * a bit too late - percpu allocation has already happened without
- * proper NUMA affinity.
- */
- if (apic->x86_32_numa_cpu_node)
- set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu),
- apic->x86_32_numa_cpu_node(cpu));
#endif
/*
@@ -2053,8 +2042,6 @@ void __init connect_bsp_APIC(void)
imcr_pic_to_apic();
}
#endif
- if (apic->enable_apic_mode)
- apic->enable_apic_mode();
}
/**
@@ -2451,51 +2438,6 @@ static void apic_pm_activate(void) { }
#ifdef CONFIG_X86_64
-static int apic_cluster_num(void)
-{
- int i, clusters, zeros;
- unsigned id;
- u16 *bios_cpu_apicid;
- DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
-
- bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
- bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
-
- for (i = 0; i < nr_cpu_ids; i++) {
- /* are we being called early in kernel startup? */
- if (bios_cpu_apicid) {
- id = bios_cpu_apicid[i];
- } else if (i < nr_cpu_ids) {
- if (cpu_present(i))
- id = per_cpu(x86_bios_cpu_apicid, i);
- else
- continue;
- } else
- break;
-
- if (id != BAD_APICID)
- __set_bit(APIC_CLUSTERID(id), clustermap);
- }
-
- /* Problem: Partially populated chassis may not have CPUs in some of
- * the APIC clusters they have been allocated. Only present CPUs have
- * x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap.
- * Since clusters are allocated sequentially, count zeros only if
- * they are bounded by ones.
- */
- clusters = 0;
- zeros = 0;
- for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
- if (test_bit(i, clustermap)) {
- clusters += 1 + zeros;
- zeros = 0;
- } else
- ++zeros;
- }
-
- return clusters;
-}
-
static int multi_checked;
static int multi;
@@ -2540,20 +2482,7 @@ static void dmi_check_multi(void)
int apic_is_clustered_box(void)
{
dmi_check_multi();
- if (multi)
- return 1;
-
- if (!is_vsmp_box())
- return 0;
-
- /*
- * ScaleMP vSMPowered boxes have one cluster per board and TSCs are
- * not guaranteed to be synced between boards
- */
- if (apic_cluster_num() > 1)
- return 1;
-
- return 0;
+ return multi;
}
#endif
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 7c1b29479513..de918c410eae 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -168,21 +168,16 @@ static struct apic apic_flat = {
.disable_esr = 0,
.dest_logical = APIC_DEST_LOGICAL,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = flat_vector_allocation_domain,
.init_apic_ldr = flat_init_apic_ldr,
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = flat_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = flat_get_apic_id,
.set_apic_id = set_apic_id,
@@ -196,10 +191,7 @@ static struct apic apic_flat = {
.send_IPI_all = flat_send_IPI_all,
.send_IPI_self = apic_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
.read = native_apic_mem_read,
@@ -283,7 +275,6 @@ static struct apic apic_physflat = {
.disable_esr = 0,
.dest_logical = 0,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = default_vector_allocation_domain,
/* not needed, but shouldn't hurt: */
@@ -291,14 +282,10 @@ static struct apic apic_physflat = {
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = flat_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = flat_get_apic_id,
.set_apic_id = set_apic_id,
@@ -312,10 +299,7 @@ static struct apic apic_physflat = {
.send_IPI_all = physflat_send_IPI_all,
.send_IPI_self = apic_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
.read = native_apic_mem_read,
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index 8c7c98249c20..b205cdbdbe6a 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -89,16 +89,6 @@ static const struct cpumask *noop_target_cpus(void)
return cpumask_of(0);
}
-static unsigned long noop_check_apicid_used(physid_mask_t *map, int apicid)
-{
- return physid_isset(apicid, *map);
-}
-
-static unsigned long noop_check_apicid_present(int bit)
-{
- return physid_isset(bit, phys_cpu_present_map);
-}
-
static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
const struct cpumask *mask)
{
@@ -133,27 +123,21 @@ struct apic apic_noop = {
.target_cpus = noop_target_cpus,
.disable_esr = 0,
.dest_logical = APIC_DEST_LOGICAL,
- .check_apicid_used = noop_check_apicid_used,
- .check_apicid_present = noop_check_apicid_present,
+ .check_apicid_used = default_check_apicid_used,
.vector_allocation_domain = noop_vector_allocation_domain,
.init_apic_ldr = noop_init_apic_ldr,
.ioapic_phys_id_map = default_ioapic_phys_id_map,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = physid_set_mask_of_physid,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = noop_phys_pkg_id,
- .mps_oem_check = NULL,
-
.get_apic_id = noop_get_apic_id,
.set_apic_id = NULL,
.apic_id_mask = 0x0F << 24,
@@ -168,12 +152,7 @@ struct apic apic_noop = {
.wakeup_secondary_cpu = noop_wakeup_secondary_cpu,
- /* should be safe */
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = NULL,
.read = noop_apic_read,
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index a5b45df8bc88..ae915391ebec 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -217,21 +217,16 @@ static const struct apic apic_numachip __refconst = {
.disable_esr = 0,
.dest_logical = 0,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = default_vector_allocation_domain,
.init_apic_ldr = flat_init_apic_ldr,
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = numachip_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
@@ -246,10 +241,7 @@ static const struct apic apic_numachip __refconst = {
.send_IPI_self = numachip_send_IPI_self,
.wakeup_secondary_cpu = numachip_wakeup_secondary,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = NULL, /* REMRD not supported */
.read = native_apic_mem_read,
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index e4840aa7a255..c4a8d63f8220 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -31,11 +31,6 @@ static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
return 0;
}
-static unsigned long bigsmp_check_apicid_present(int bit)
-{
- return 1;
-}
-
static int bigsmp_early_logical_apicid(int cpu)
{
/* on bigsmp, logical apicid is the same as physical */
@@ -168,21 +163,16 @@ static struct apic apic_bigsmp = {
.disable_esr = 1,
.dest_logical = 0,
.check_apicid_used = bigsmp_check_apicid_used,
- .check_apicid_present = bigsmp_check_apicid_present,
.vector_allocation_domain = default_vector_allocation_domain,
.init_apic_ldr = bigsmp_init_apic_ldr,
.ioapic_phys_id_map = bigsmp_ioapic_phys_id_map,
.setup_apic_routing = bigsmp_setup_apic_routing,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = bigsmp_cpu_present_to_apicid,
.apicid_to_cpu_present = physid_set_mask_of_physid,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = bigsmp_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = bigsmp_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = bigsmp_get_apic_id,
.set_apic_id = NULL,
@@ -196,11 +186,7 @@ static struct apic apic_bigsmp = {
.send_IPI_all = bigsmp_send_IPI_all,
.send_IPI_self = default_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
.wait_for_init_deassert = true,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
.read = native_apic_mem_read,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 81e08eff05ee..29290f554e79 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
#include <linux/msi.h>
#include <linux/htirq.h>
#include <linux/freezer.h>
@@ -62,6 +63,16 @@
#define __apicdebuginit(type) static type __init
+#define for_each_ioapic(idx) \
+ for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
+#define for_each_ioapic_reverse(idx) \
+ for ((idx) = nr_ioapics - 1; (idx) >= 0; (idx)--)
+#define for_each_pin(idx, pin) \
+ for ((pin) = 0; (pin) < ioapics[(idx)].nr_registers; (pin)++)
+#define for_each_ioapic_pin(idx, pin) \
+ for_each_ioapic((idx)) \
+ for_each_pin((idx), (pin))
+
#define for_each_irq_pin(entry, head) \
for (entry = head; entry; entry = entry->next)
@@ -73,6 +84,17 @@ int sis_apic_bug = -1;
static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
+static DEFINE_MUTEX(ioapic_mutex);
+static unsigned int ioapic_dynirq_base;
+static int ioapic_initialized;
+
+struct mp_pin_info {
+ int trigger;
+ int polarity;
+ int node;
+ int set;
+ u32 count;
+};
static struct ioapic {
/*
@@ -87,7 +109,9 @@ static struct ioapic {
struct mpc_ioapic mp_config;
/* IO APIC gsi routing info */
struct mp_ioapic_gsi gsi_config;
- DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+ struct ioapic_domain_cfg irqdomain_cfg;
+ struct irq_domain *irqdomain;
+ struct mp_pin_info *pin_info;
} ioapics[MAX_IO_APICS];
#define mpc_ioapic_ver(ioapic_idx) ioapics[ioapic_idx].mp_config.apicver
@@ -107,6 +131,41 @@ struct mp_ioapic_gsi *mp_ioapic_gsi_routing(int ioapic_idx)
return &ioapics[ioapic_idx].gsi_config;
}
+static inline int mp_ioapic_pin_count(int ioapic)
+{
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ return gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
+}
+
+u32 mp_pin_to_gsi(int ioapic, int pin)
+{
+ return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
+}
+
+/*
+ * Initialize all legacy IRQs and all pins on the first IOAPIC
+ * if we have legacy interrupt controller. Kernel boot option "pirq="
+ * may rely on non-legacy pins on the first IOAPIC.
+ */
+static inline int mp_init_irq_at_boot(int ioapic, int irq)
+{
+ if (!nr_legacy_irqs())
+ return 0;
+
+ return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
+}
+
+static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin)
+{
+ return ioapics[ioapic_idx].pin_info + pin;
+}
+
+static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
+{
+ return ioapics[ioapic].irqdomain;
+}
+
int nr_ioapics;
/* The one past the highest gsi number used */
@@ -118,9 +177,6 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* # of MP IRQ source entries */
int mp_irq_entries;
-/* GSI interrupts */
-static int nr_irqs_gsi = NR_IRQS_LEGACY;
-
#ifdef CONFIG_EISA
int mp_bus_id_to_type[MAX_MP_BUSSES];
#endif
@@ -149,8 +205,7 @@ static int __init parse_noapic(char *str)
}
early_param("noapic", parse_noapic);
-static int io_apic_setup_irq_pin(unsigned int irq, int node,
- struct io_apic_irq_attr *attr);
+static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node);
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
void mp_save_irq(struct mpc_intsrc *m)
@@ -182,19 +237,15 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
}
-
-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
-
int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
- int count, node, i;
+ int i, node = cpu_to_node(0);
- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
io_apic_irqs = ~0UL;
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
ioapics[i].saved_registers =
kzalloc(sizeof(struct IO_APIC_route_entry) *
ioapics[i].nr_registers, GFP_KERNEL);
@@ -202,28 +253,20 @@ int __init arch_early_irq_init(void)
pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
}
- cfg = irq_cfgx;
- count = ARRAY_SIZE(irq_cfgx);
- node = cpu_to_node(0);
-
- for (i = 0; i < count; i++) {
- irq_set_chip_data(i, &cfg[i]);
- zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
- zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
- /*
- * For legacy IRQ's, start with assigning irq0 to irq15 to
- * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
- */
- if (i < legacy_pic->nr_legacy_irqs) {
- cfg[i].vector = IRQ0_VECTOR + i;
- cpumask_setall(cfg[i].domain);
- }
+ /*
+ * For legacy IRQ's, start with assigning irq0 to irq15 to
+ * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+ */
+ for (i = 0; i < nr_legacy_irqs(); i++) {
+ cfg = alloc_irq_and_cfg_at(i, node);
+ cfg->vector = IRQ0_VECTOR + i;
+ cpumask_setall(cfg->domain);
}
return 0;
}
-static struct irq_cfg *irq_cfg(unsigned int irq)
+static inline struct irq_cfg *irq_cfg(unsigned int irq)
{
return irq_get_chip_data(irq);
}
@@ -265,7 +308,7 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
if (res < 0) {
if (res != -EEXIST)
return NULL;
- cfg = irq_get_chip_data(at);
+ cfg = irq_cfg(at);
if (cfg)
return cfg;
}
@@ -425,6 +468,21 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi
return 0;
}
+static void __remove_pin_from_irq(struct irq_cfg *cfg, int apic, int pin)
+{
+ struct irq_pin_list **last, *entry;
+
+ last = &cfg->irq_2_pin;
+ for_each_irq_pin(entry, cfg->irq_2_pin)
+ if (entry->apic == apic && entry->pin == pin) {
+ *last = entry->next;
+ kfree(entry);
+ return;
+ } else {
+ last = &entry->next;
+ }
+}
+
static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
{
if (__add_pin_to_irq_node(cfg, node, apic, pin))
@@ -627,9 +685,8 @@ static void clear_IO_APIC (void)
{
int apic, pin;
- for (apic = 0; apic < nr_ioapics; apic++)
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
- clear_IO_APIC_pin(apic, pin);
+ for_each_ioapic_pin(apic, pin)
+ clear_IO_APIC_pin(apic, pin);
}
#ifdef CONFIG_X86_32
@@ -678,13 +735,13 @@ int save_ioapic_entries(void)
int apic, pin;
int err = 0;
- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers) {
err = -ENOMEM;
continue;
}
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapics[apic].saved_registers[pin] =
ioapic_read_entry(apic, pin);
}
@@ -699,11 +756,11 @@ void mask_ioapic_entries(void)
{
int apic, pin;
- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
+ for_each_pin(apic, pin) {
struct IO_APIC_route_entry entry;
entry = ioapics[apic].saved_registers[pin];
@@ -722,11 +779,11 @@ int restore_ioapic_entries(void)
{
int apic, pin;
- for (apic = 0; apic < nr_ioapics; apic++) {
+ for_each_ioapic(apic) {
if (!ioapics[apic].saved_registers)
continue;
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++)
+ for_each_pin(apic, pin)
ioapic_write_entry(apic, pin,
ioapics[apic].saved_registers[pin]);
}
@@ -785,7 +842,7 @@ static int __init find_isa_irq_apic(int irq, int type)
if (i < mp_irq_entries) {
int ioapic_idx;
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic)
return ioapic_idx;
}
@@ -799,7 +856,7 @@ static int __init find_isa_irq_apic(int irq, int type)
*/
static int EISA_ELCR(unsigned int irq)
{
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
@@ -939,29 +996,101 @@ static int irq_trigger(int idx)
return trigger;
}
-static int pin_2_irq(int idx, int apic, int pin)
+static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
+{
+ int irq = -1;
+ int ioapic = (int)(long)domain->host_data;
+ int type = ioapics[ioapic].irqdomain_cfg.type;
+
+ switch (type) {
+ case IOAPIC_DOMAIN_LEGACY:
+ /*
+ * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
+ * GSIs on some weird platforms.
+ */
+ if (gsi < nr_legacy_irqs())
+ irq = irq_create_mapping(domain, pin);
+ else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_STRICT:
+ if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ break;
+ case IOAPIC_DOMAIN_DYNAMIC:
+ irq = irq_create_mapping(domain, pin);
+ break;
+ default:
+ WARN(1, "ioapic: unknown irqdomain type %d\n", type);
+ break;
+ }
+
+ return irq > 0 ? irq : -1;
+}
+
+static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
+ unsigned int flags)
{
int irq;
- int bus = mp_irqs[idx].srcbus;
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
+ struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+ struct mp_pin_info *info = mp_pin_info(ioapic, pin);
+
+ if (!domain)
+ return -1;
+
+ mutex_lock(&ioapic_mutex);
/*
- * Debugging check, we are in big trouble if this message pops up!
+ * Don't use irqdomain to manage ISA IRQs because there may be
+ * multiple IOAPIC pins sharing the same ISA IRQ number and
+ * irqdomain only supports 1:1 mapping between IOAPIC pin and
+ * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
+ * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
+ * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
+ * available, and some BIOSes may use MP Interrupt Source records
+ * to override IRQ numbers for PIRQs instead of reprogramming
+ * the interrupt routing logic. Thus there may be multiple pins
+ * sharing the same legacy IRQ number when ACPI is disabled.
*/
- if (mp_irqs[idx].dstirq != pin)
- pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
-
- if (test_bit(bus, mp_bus_not_pci)) {
+ if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
irq = mp_irqs[idx].srcbusirq;
+ if (flags & IOAPIC_MAP_ALLOC) {
+ if (info->count == 0 &&
+ mp_irqdomain_map(domain, irq, pin) != 0)
+ irq = -1;
+
+ /* special handling for timer IRQ0 */
+ if (irq == 0)
+ info->count++;
+ }
} else {
- u32 gsi = gsi_cfg->gsi_base + pin;
+ irq = irq_find_mapping(domain, pin);
+ if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
+ irq = alloc_irq_from_domain(domain, gsi, pin);
+ }
- if (gsi >= NR_IRQS_LEGACY)
- irq = gsi;
- else
- irq = gsi_top + gsi;
+ if (flags & IOAPIC_MAP_ALLOC) {
+ if (irq > 0)
+ info->count++;
+ else if (info->count == 0)
+ info->set = 0;
}
+ mutex_unlock(&ioapic_mutex);
+
+ return irq > 0 ? irq : -1;
+}
+
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
+{
+ u32 gsi = mp_pin_to_gsi(ioapic, pin);
+
+ /*
+ * Debugging check, we are in big trouble if this message pops up!
+ */
+ if (mp_irqs[idx].dstirq != pin)
+ pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
+
#ifdef CONFIG_X86_32
/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -972,16 +1101,58 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"disabling PIRQ%d\n", pin-16);
} else {
- irq = pirq_entries[pin-16];
+ int irq = pirq_entries[pin-16];
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
+ return irq;
}
}
}
#endif
- return irq;
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}
+
+int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
+{
+ int ioapic, pin, idx;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -1;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
+ return -1;
+
+ return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
+}
+
+void mp_unmap_irq(int irq)
+{
+ struct irq_data *data = irq_get_irq_data(irq);
+ struct mp_pin_info *info;
+ int ioapic, pin;
+
+ if (!data || !data->domain)
+ return;
+
+ ioapic = (int)(long)data->domain->host_data;
+ pin = (int)data->hwirq;
+ info = mp_pin_info(ioapic, pin);
+
+ mutex_lock(&ioapic_mutex);
+ if (--info->count == 0) {
+ info->set = 0;
+ if (irq < nr_legacy_irqs() &&
+ ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY)
+ mp_irqdomain_unmap(data->domain, irq);
+ else
+ irq_dispose_mapping(irq);
+ }
+ mutex_unlock(&ioapic_mutex);
}
/*
@@ -991,7 +1162,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int ioapic_idx, i, best_guess = -1;
+ int irq, i, best_ioapic = -1, best_idx = -1;
apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1001,44 +1172,56 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
"PCI BIOS passed nonexistent PCI bus %d!\n", bus);
return -1;
}
+
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;
+ int ioapic_idx, found = 0;
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ if (bus != lbus || mp_irqs[i].irqtype != mp_INT ||
+ slot != ((mp_irqs[i].srcbusirq >> 2) & 0x1f))
+ continue;
+
+ for_each_ioapic(ioapic_idx)
if (mpc_ioapic_id(ioapic_idx) == mp_irqs[i].dstapic ||
- mp_irqs[i].dstapic == MP_APIC_ALL)
+ mp_irqs[i].dstapic == MP_APIC_ALL) {
+ found = 1;
break;
+ }
+ if (!found)
+ continue;
- if (!test_bit(lbus, mp_bus_not_pci) &&
- !mp_irqs[i].irqtype &&
- (bus == lbus) &&
- (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
- int irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
+ /* Skip ISA IRQs */
+ irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq, 0);
+ if (irq > 0 && !IO_APIC_IRQ(irq))
+ continue;
- if (!(ioapic_idx || IO_APIC_IRQ(irq)))
- continue;
+ if (pin == (mp_irqs[i].srcbusirq & 3)) {
+ best_idx = i;
+ best_ioapic = ioapic_idx;
+ goto out;
+ }
- if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
- }
- /*
- * Use the first all-but-pin matching entry as a
- * best-guess fuzzy result for broken mptables.
- */
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
- }
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_idx < 0) {
+ best_idx = i;
+ best_ioapic = ioapic_idx;
}
}
- return best_guess;
+ if (best_idx < 0)
+ return -1;
+
+out:
+ irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq,
+ IOAPIC_MAP_ALLOC);
+ if (irq > 0)
+ set_io_apic_irq_attr(irq_attr, best_ioapic,
+ mp_irqs[best_idx].dstirq,
+ irq_trigger(best_idx),
+ irq_polarity(best_idx));
+ return irq;
}
EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
@@ -1198,7 +1381,7 @@ void __setup_vector_irq(int cpu)
raw_spin_lock(&vector_lock);
/* Mark the inuse vectors */
for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;
@@ -1227,12 +1410,10 @@ static inline int IO_APIC_irq_trigger(int irq)
{
int apic, idx, pin;
- for (apic = 0; apic < nr_ioapics; apic++) {
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
- return irq_trigger(idx);
- }
+ for_each_ioapic_pin(apic, pin) {
+ idx = find_irq_entry(apic, pin, mp_INT);
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
+ return irq_trigger(idx);
}
/*
* nonexistent IRQs are edge default
@@ -1330,95 +1511,29 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
}
ioapic_register_intr(irq, cfg, attr->trigger);
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->mask(irq);
ioapic_write_entry(attr->ioapic, attr->ioapic_pin, entry);
}
-static bool __init io_apic_pin_not_connected(int idx, int ioapic_idx, int pin)
-{
- if (idx != -1)
- return false;
-
- apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
- mpc_ioapic_id(ioapic_idx), pin);
- return true;
-}
-
-static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
-{
- int idx, node = cpu_to_node(0);
- struct io_apic_irq_attr attr;
- unsigned int pin, irq;
-
- for (pin = 0; pin < ioapics[ioapic_idx].nr_registers; pin++) {
- idx = find_irq_entry(ioapic_idx, pin, mp_INT);
- if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
- continue;
-
- irq = pin_2_irq(idx, ioapic_idx, pin);
-
- if ((ioapic_idx > 0) && (irq > 16))
- continue;
-
- /*
- * Skip the timer IRQ if there's a quirk handler
- * installed and if it returns 1:
- */
- if (apic->multi_timer_check &&
- apic->multi_timer_check(ioapic_idx, irq))
- continue;
-
- set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
- irq_polarity(idx));
-
- io_apic_setup_irq_pin(irq, node, &attr);
- }
-}
-
static void __init setup_IO_APIC_irqs(void)
{
- unsigned int ioapic_idx;
+ unsigned int ioapic, pin;
+ int idx;
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
- __io_apic_setup_irqs(ioapic_idx);
-}
-
-/*
- * for the gsit that is not in first ioapic
- * but could not use acpi_register_gsi()
- * like some special sci in IBM x3330
- */
-void setup_IO_APIC_irq_extra(u32 gsi)
-{
- int ioapic_idx = 0, pin, idx, irq, node = cpu_to_node(0);
- struct io_apic_irq_attr attr;
-
- /*
- * Convert 'gsi' to 'ioapic.pin'.
- */
- ioapic_idx = mp_find_ioapic(gsi);
- if (ioapic_idx < 0)
- return;
-
- pin = mp_find_ioapic_pin(ioapic_idx, gsi);
- idx = find_irq_entry(ioapic_idx, pin, mp_INT);
- if (idx == -1)
- return;
-
- irq = pin_2_irq(idx, ioapic_idx, pin);
-
- /* Only handle the non legacy irqs on secondary ioapics */
- if (ioapic_idx == 0 || irq < NR_IRQS_LEGACY)
- return;
-
- set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
- irq_polarity(idx));
-
- io_apic_setup_irq_pin_once(irq, node, &attr);
+ for_each_ioapic_pin(ioapic, pin) {
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if (idx < 0)
+ apic_printk(APIC_VERBOSE,
+ KERN_DEBUG " apic %d pin %d not connected\n",
+ mpc_ioapic_id(ioapic), pin);
+ else
+ pin_2_irq(idx, ioapic, pin,
+ ioapic ? 0 : IOAPIC_MAP_ALLOC);
+ }
}
/*
@@ -1586,7 +1701,7 @@ __apicdebuginit(void) print_IO_APICs(void)
struct irq_chip *chip;
printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
mpc_ioapic_id(ioapic_idx),
ioapics[ioapic_idx].nr_registers);
@@ -1597,7 +1712,7 @@ __apicdebuginit(void) print_IO_APICs(void)
*/
printk(KERN_INFO "testing the IO APIC.......................\n");
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
+ for_each_ioapic(ioapic_idx)
print_IO_APIC(ioapic_idx);
printk(KERN_DEBUG "IRQ to pin mappings:\n");
@@ -1608,7 +1723,7 @@ __apicdebuginit(void) print_IO_APICs(void)
if (chip != &ioapic_chip)
continue;
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (!cfg)
continue;
entry = cfg->irq_2_pin;
@@ -1758,7 +1873,7 @@ __apicdebuginit(void) print_PIC(void)
unsigned int v;
unsigned long flags;
- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;
printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1828,26 +1943,22 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
void __init enable_IO_APIC(void)
{
int i8259_apic, i8259_pin;
- int apic;
+ int apic, pin;
- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;
- for(apic = 0; apic < nr_ioapics; apic++) {
- int pin;
+ for_each_ioapic_pin(apic, pin) {
/* See if any of the pins is in ExtINT mode */
- for (pin = 0; pin < ioapics[apic].nr_registers; pin++) {
- struct IO_APIC_route_entry entry;
- entry = ioapic_read_entry(apic, pin);
+ struct IO_APIC_route_entry entry = ioapic_read_entry(apic, pin);
- /* If the interrupt line is enabled and in ExtInt mode
- * I have found the pin where the i8259 is connected.
- */
- if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
- ioapic_i8259.apic = apic;
- ioapic_i8259.pin = pin;
- goto found_i8259;
- }
+ /* If the interrupt line is enabled and in ExtInt mode
+ * I have found the pin where the i8259 is connected.
+ */
+ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+ ioapic_i8259.apic = apic;
+ ioapic_i8259.pin = pin;
+ goto found_i8259;
}
}
found_i8259:
@@ -1919,7 +2030,7 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();
- if (!legacy_pic->nr_legacy_irqs)
+ if (!nr_legacy_irqs())
return;
x86_io_apic_ops.disable();
@@ -1950,7 +2061,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
/*
* Set the IOAPIC ID to the value stored in the MPC table.
*/
- for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) {
+ for_each_ioapic(ioapic_idx) {
/* Read the register 0 value */
raw_spin_lock_irqsave(&ioapic_lock, flags);
reg_00.raw = io_apic_read(ioapic_idx, 0);
@@ -2123,7 +2234,7 @@ static unsigned int startup_ioapic_irq(struct irq_data *data)
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
- if (irq < legacy_pic->nr_legacy_irqs) {
+ if (irq < nr_legacy_irqs()) {
legacy_pic->mask(irq);
if (legacy_pic->irq_pending(irq))
was_pending = 1;
@@ -2225,7 +2336,7 @@ asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
goto unlock;
}
- __this_cpu_write(vector_irq[vector], -1);
+ __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
unlock:
raw_spin_unlock(&desc->lock);
}
@@ -2253,7 +2364,7 @@ static void irq_complete_move(struct irq_cfg *cfg)
void irq_force_complete_move(int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);
if (!cfg)
return;
@@ -2514,26 +2625,15 @@ static inline void init_IO_APIC_traps(void)
struct irq_cfg *cfg;
unsigned int irq;
- /*
- * NOTE! The local APIC isn't very good at handling
- * multiple interrupts at the same interrupt level.
- * As the interrupt level is determined by taking the
- * vector number and shifting that right by 4, we
- * want to spread these out a bit so that they don't
- * all fall in the same interrupt level.
- *
- * Also, we've got to be careful not to trash gate
- * 0x80, because int 0x80 is hm, kind of importantish. ;)
- */
for_each_active_irq(irq) {
- cfg = irq_get_chip_data(irq);
+ cfg = irq_cfg(irq);
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
/*
* Hmm.. We don't have an entry for this,
* so default to an old-fashioned 8259
* interrupt if we can..
*/
- if (irq < legacy_pic->nr_legacy_irqs)
+ if (irq < nr_legacy_irqs())
legacy_pic->make_irq(irq);
else
/* Strange. Oh, well.. */
@@ -2649,8 +2749,6 @@ static int __init disable_timer_pin_setup(char *arg)
}
early_param("disable_timer_pin_1", disable_timer_pin_setup);
-int timer_through_8259 __initdata;
-
/*
* This code may look a bit paranoid, but it's supposed to cooperate with
* a wide range of boards and BIOS bugs. Fortunately only the timer IRQ
@@ -2661,7 +2759,7 @@ int timer_through_8259 __initdata;
*/
static inline void __init check_timer(void)
{
- struct irq_cfg *cfg = irq_get_chip_data(0);
+ struct irq_cfg *cfg = irq_cfg(0);
int node = cpu_to_node(0);
int apic1, pin1, apic2, pin2;
unsigned long flags;
@@ -2755,7 +2853,6 @@ static inline void __init check_timer(void)
legacy_pic->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
- timer_through_8259 = 1;
goto out;
}
/*
@@ -2827,15 +2924,54 @@ out:
*/
#define PIC_IRQS (1UL << PIC_CASCADE_IR)
+static int mp_irqdomain_create(int ioapic)
+{
+ size_t size;
+ int hwirqs = mp_ioapic_pin_count(ioapic);
+ struct ioapic *ip = &ioapics[ioapic];
+ struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+
+ size = sizeof(struct mp_pin_info) * mp_ioapic_pin_count(ioapic);
+ ip->pin_info = kzalloc(size, GFP_KERNEL);
+ if (!ip->pin_info)
+ return -ENOMEM;
+
+ if (cfg->type == IOAPIC_DOMAIN_INVALID)
+ return 0;
+
+ ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
+ (void *)(long)ioapic);
+ if(!ip->irqdomain) {
+ kfree(ip->pin_info);
+ ip->pin_info = NULL;
+ return -ENOMEM;
+ }
+
+ if (cfg->type == IOAPIC_DOMAIN_LEGACY ||
+ cfg->type == IOAPIC_DOMAIN_STRICT)
+ ioapic_dynirq_base = max(ioapic_dynirq_base,
+ gsi_cfg->gsi_end + 1);
+
+ if (gsi_cfg->gsi_base == 0)
+ irq_set_default_host(ip->irqdomain);
+
+ return 0;
+}
+
void __init setup_IO_APIC(void)
{
+ int ioapic;
/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/
- io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+ io_apic_irqs = nr_legacy_irqs() ? ~PIC_IRQS : ~0UL;
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ for_each_ioapic(ioapic)
+ BUG_ON(mp_irqdomain_create(ioapic));
+
/*
* Set up IO-APIC IRQ routing.
*/
@@ -2844,8 +2980,10 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
- if (legacy_pic->nr_legacy_irqs)
+ if (nr_legacy_irqs())
check_timer();
+
+ ioapic_initialized = 1;
}
/*
@@ -2880,7 +3018,7 @@ static void ioapic_resume(void)
{
int ioapic_idx;
- for (ioapic_idx = nr_ioapics - 1; ioapic_idx >= 0; ioapic_idx--)
+ for_each_ioapic_reverse(ioapic_idx)
resume_ioapic_id(ioapic_idx);
restore_ioapic_entries();
@@ -2926,7 +3064,7 @@ int arch_setup_hwirq(unsigned int irq, int node)
void arch_teardown_hwirq(unsigned int irq)
{
- struct irq_cfg *cfg = irq_get_chip_data(irq);
+ struct irq_cfg *cfg = irq_cfg(irq);
unsigned long flags;
free_remapped_irq(irq);
@@ -3053,7 +3191,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
if (!irq_offset)
write_msi_msg(irq, &msg);
- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
@@ -3192,7 +3330,7 @@ int default_setup_hpet_msi(unsigned int irq, unsigned int id)
hpet_msi_write(irq_get_handler_data(irq), &msg);
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
- setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
+ setup_remapped_irq(irq, irq_cfg(irq), chip);
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
return 0;
@@ -3303,27 +3441,6 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
return ret;
}
-int io_apic_setup_irq_pin_once(unsigned int irq, int node,
- struct io_apic_irq_attr *attr)
-{
- unsigned int ioapic_idx = attr->ioapic, pin = attr->ioapic_pin;
- int ret;
- struct IO_APIC_route_entry orig_entry;
-
- /* Avoid redundant programming */
- if (test_bit(pin, ioapics[ioapic_idx].pin_programmed)) {
- pr_debug("Pin %d-%d already programmed\n", mpc_ioapic_id(ioapic_idx), pin);
- orig_entry = ioapic_read_entry(attr->ioapic, pin);
- if (attr->trigger == orig_entry.trigger && attr->polarity == orig_entry.polarity)
- return 0;
- return -EBUSY;
- }
- ret = io_apic_setup_irq_pin(irq, node, attr);
- if (!ret)
- set_bit(pin, ioapics[ioapic_idx].pin_programmed);
- return ret;
-}
-
static int __init io_apic_get_redir_entries(int ioapic)
{
union IO_APIC_reg_01 reg_01;
@@ -3340,20 +3457,13 @@ static int __init io_apic_get_redir_entries(int ioapic)
return reg_01.bits.entries + 1;
}
-static void __init probe_nr_irqs_gsi(void)
-{
- int nr;
-
- nr = gsi_top + NR_IRQS_LEGACY;
- if (nr > nr_irqs_gsi)
- nr_irqs_gsi = nr;
-
- printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
-}
-
unsigned int arch_dynirq_lower_bound(unsigned int from)
{
- return from < nr_irqs_gsi ? nr_irqs_gsi : from;
+ /*
+ * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
+ * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
+ */
+ return ioapic_initialized ? ioapic_dynirq_base : gsi_top;
}
int __init arch_probe_nr_irqs(void)
@@ -3363,33 +3473,17 @@ int __init arch_probe_nr_irqs(void)
if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
nr_irqs = NR_VECTORS * nr_cpu_ids;
- nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+ nr = (gsi_top + nr_legacy_irqs()) + 8 * nr_cpu_ids;
#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
/*
* for MSI and HT dyn irq
*/
- nr += nr_irqs_gsi * 16;
+ nr += gsi_top * 16;
#endif
if (nr < nr_irqs)
nr_irqs = nr;
- return NR_IRQS_LEGACY;
-}
-
-int io_apic_set_pci_routing(struct device *dev, int irq,
- struct io_apic_irq_attr *irq_attr)
-{
- int node;
-
- if (!IO_APIC_IRQ(irq)) {
- apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
- irq_attr->ioapic);
- return -EINVAL;
- }
-
- node = dev ? dev_to_node(dev) : cpu_to_node(0);
-
- return io_apic_setup_irq_pin_once(irq, node, irq_attr);
+ return 0;
}
#ifdef CONFIG_X86_32
@@ -3483,9 +3577,8 @@ static u8 __init io_apic_unique_id(u8 id)
DECLARE_BITMAP(used, 256);
bitmap_zero(used, 256);
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i)
__set_bit(mpc_ioapic_id(i), used);
- }
if (!test_bit(id, used))
return id;
return find_first_zero_bit(used, 256);
@@ -3543,14 +3636,13 @@ void __init setup_ioapic_dest(void)
if (skip_ioapic_setup == 1)
return;
- for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
- for (pin = 0; pin < ioapics[ioapic].nr_registers; pin++) {
+ for_each_ioapic_pin(ioapic, pin) {
irq_entry = find_irq_entry(ioapic, pin, mp_INT);
if (irq_entry == -1)
continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);
- if ((ioapic > 0) && (irq > 16))
+ irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
continue;
idata = irq_get_irq_data(irq);
@@ -3573,29 +3665,33 @@ void __init setup_ioapic_dest(void)
static struct resource *ioapic_resources;
-static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+static struct resource * __init ioapic_setup_resources(void)
{
unsigned long n;
struct resource *res;
char *mem;
- int i;
+ int i, num = 0;
- if (nr_ioapics <= 0)
+ for_each_ioapic(i)
+ num++;
+ if (num == 0)
return NULL;
n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
- n *= nr_ioapics;
+ n *= num;
mem = alloc_bootmem(n);
res = (void *)mem;
- mem += sizeof(struct resource) * nr_ioapics;
+ mem += sizeof(struct resource) * num;
- for (i = 0; i < nr_ioapics; i++) {
- res[i].name = mem;
- res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ num = 0;
+ for_each_ioapic(i) {
+ res[num].name = mem;
+ res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
mem += IOAPIC_RESOURCE_NAME_SIZE;
+ num++;
}
ioapic_resources = res;
@@ -3609,8 +3705,8 @@ void __init native_io_apic_init_mappings(void)
struct resource *ioapic_res;
int i;
- ioapic_res = ioapic_setup_resources(nr_ioapics);
- for (i = 0; i < nr_ioapics; i++) {
+ ioapic_res = ioapic_setup_resources();
+ for_each_ioapic(i) {
if (smp_found_config) {
ioapic_phys = mpc_ioapic_addr(i);
#ifdef CONFIG_X86_32
@@ -3641,8 +3737,6 @@ fake_ioapic_page:
ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
ioapic_res++;
}
-
- probe_nr_irqs_gsi();
}
void __init ioapic_insert_resources(void)
@@ -3657,7 +3751,7 @@ void __init ioapic_insert_resources(void)
return;
}
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
insert_resource(&iomem_resource, r);
r++;
}
@@ -3665,16 +3759,15 @@ void __init ioapic_insert_resources(void)
int mp_find_ioapic(u32 gsi)
{
- int i = 0;
+ int i;
if (nr_ioapics == 0)
return -1;
/* Find the IOAPIC that manages this GSI. */
- for (i = 0; i < nr_ioapics; i++) {
+ for_each_ioapic(i) {
struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(i);
- if ((gsi >= gsi_cfg->gsi_base)
- && (gsi <= gsi_cfg->gsi_end))
+ if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
return i;
}
@@ -3686,7 +3779,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
{
struct mp_ioapic_gsi *gsi_cfg;
- if (WARN_ON(ioapic == -1))
+ if (WARN_ON(ioapic < 0))
return -1;
gsi_cfg = mp_ioapic_gsi_routing(ioapic);
@@ -3729,7 +3822,8 @@ static __init int bad_ioapic_register(int idx)
return 0;
}
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ struct ioapic_domain_cfg *cfg)
{
int idx = 0;
int entries;
@@ -3743,6 +3837,8 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
ioapics[idx].mp_config.type = MP_IOAPIC;
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
+ ioapics[idx].irqdomain = NULL;
+ ioapics[idx].irqdomain_cfg = *cfg;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
@@ -3779,6 +3875,77 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++;
}
+int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ int ioapic = (int)(long)domain->host_data;
+ struct mp_pin_info *info = mp_pin_info(ioapic, hwirq);
+ struct io_apic_irq_attr attr;
+
+ /* Get default attribute if not set by caller yet */
+ if (!info->set) {
+ u32 gsi = mp_pin_to_gsi(ioapic, hwirq);
+
+ if (acpi_get_override_irq(gsi, &info->trigger,
+ &info->polarity) < 0) {
+ /*
+ * PCI interrupts are always polarity one level
+ * triggered.
+ */
+ info->trigger = 1;
+ info->polarity = 1;
+ }
+ info->node = NUMA_NO_NODE;
+ info->set = 1;
+ }
+ set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
+ info->polarity);
+
+ return io_apic_setup_irq_pin(virq, info->node, &attr);
+}
+
+void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq)
+{
+ struct irq_data *data = irq_get_irq_data(virq);
+ struct irq_cfg *cfg = irq_cfg(virq);
+ int ioapic = (int)(long)domain->host_data;
+ int pin = (int)data->hwirq;
+
+ ioapic_mask_entry(ioapic, pin);
+ __remove_pin_from_irq(cfg, ioapic, pin);
+ WARN_ON(cfg->irq_2_pin != NULL);
+ arch_teardown_hwirq(virq);
+}
+
+int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
+{
+ int ret = 0;
+ int ioapic, pin;
+ struct mp_pin_info *info;
+
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ return -ENODEV;
+
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ info = mp_pin_info(ioapic, pin);
+ trigger = trigger ? 1 : 0;
+ polarity = polarity ? 1 : 0;
+
+ mutex_lock(&ioapic_mutex);
+ if (!info->set) {
+ info->trigger = trigger;
+ info->polarity = polarity;
+ info->node = node;
+ info->set = 1;
+ } else if (info->trigger != trigger || info->polarity != polarity) {
+ ret = -EBUSY;
+ }
+ mutex_unlock(&ioapic_mutex);
+
+ return ret;
+}
+
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index cceb352c968c..bda488680dbc 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -88,21 +88,16 @@ static struct apic apic_default = {
.disable_esr = 0,
.dest_logical = APIC_DEST_LOGICAL,
.check_apicid_used = default_check_apicid_used,
- .check_apicid_present = default_check_apicid_present,
.vector_allocation_domain = flat_vector_allocation_domain,
.init_apic_ldr = default_init_apic_ldr,
.ioapic_phys_id_map = default_ioapic_phys_id_map,
.setup_apic_routing = setup_apic_flat_routing,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = physid_set_mask_of_physid,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = default_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = default_get_apic_id,
.set_apic_id = NULL,
@@ -116,11 +111,7 @@ static struct apic apic_default = {
.send_IPI_all = default_send_IPI_all,
.send_IPI_self = default_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-
.wait_for_init_deassert = true,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
.read = native_apic_mem_read,
@@ -214,29 +205,7 @@ void __init generic_apic_probe(void)
printk(KERN_INFO "Using APIC driver %s\n", apic->name);
}
-/* These functions can switch the APIC even after the initial ->probe() */
-
-int __init
-generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
-{
- struct apic **drv;
-
- for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
- if (!((*drv)->mps_oem_check))
- continue;
- if (!(*drv)->mps_oem_check(mpc, oem, productid))
- continue;
-
- if (!cmdline_apic) {
- apic = *drv;
- printk(KERN_INFO "Switched to APIC driver `%s'.\n",
- apic->name);
- }
- return 1;
- }
- return 0;
-}
-
+/* This function can switch the APIC even after the initial ->probe() */
int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
struct apic **drv;
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index e66766bf1641..6ce600f9bc78 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -249,21 +249,16 @@ static struct apic apic_x2apic_cluster = {
.disable_esr = 0,
.dest_logical = APIC_DEST_LOGICAL,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = cluster_vector_allocation_domain,
.init_apic_ldr = init_x2apic_ldr,
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = x2apic_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = x2apic_get_apic_id,
.set_apic_id = x2apic_set_apic_id,
@@ -277,10 +272,7 @@ static struct apic apic_x2apic_cluster = {
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_self = x2apic_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = NULL,
.read = native_apic_msr_read,
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 6d600ebf6c12..6fae733e9194 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -103,21 +103,16 @@ static struct apic apic_x2apic_phys = {
.disable_esr = 0,
.dest_logical = 0,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = default_vector_allocation_domain,
.init_apic_ldr = init_x2apic_ldr,
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = x2apic_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = x2apic_get_apic_id,
.set_apic_id = x2apic_set_apic_id,
@@ -131,10 +126,7 @@ static struct apic apic_x2apic_phys = {
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_self = x2apic_send_IPI_self,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = NULL,
.read = native_apic_msr_read,
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 293b41df54ef..004f017aa7b9 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -365,21 +365,16 @@ static struct apic __refdata apic_x2apic_uv_x = {
.disable_esr = 0,
.dest_logical = APIC_DEST_LOGICAL,
.check_apicid_used = NULL,
- .check_apicid_present = NULL,
.vector_allocation_domain = default_vector_allocation_domain,
.init_apic_ldr = uv_init_apic_ldr,
.ioapic_phys_id_map = NULL,
.setup_apic_routing = NULL,
- .multi_timer_check = NULL,
.cpu_present_to_apicid = default_cpu_present_to_apicid,
.apicid_to_cpu_present = NULL,
- .setup_portio_remap = NULL,
.check_phys_apicid_present = default_check_phys_apicid_present,
- .enable_apic_mode = NULL,
.phys_pkg_id = uv_phys_pkg_id,
- .mps_oem_check = NULL,
.get_apic_id = x2apic_get_apic_id,
.set_apic_id = set_apic_id,
@@ -394,10 +389,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
.send_IPI_self = uv_send_IPI_self,
.wakeup_secondary_cpu = uv_wakeup_secondary,
- .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
- .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = false,
- .smp_callin_clear_local_apic = NULL,
.inquire_remote_apic = NULL,
.read = native_apic_msr_read,
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index ce8b8ff0e0ef..60e5497681f5 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -8,6 +8,7 @@
#include <asm/processor.h>
#include <asm/apic.h>
#include <asm/cpu.h>
+#include <asm/smp.h>
#include <asm/pci-direct.h>
#ifdef CONFIG_X86_64
@@ -50,7 +51,6 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
return wrmsr_safe_regs(gprs);
}
-#ifdef CONFIG_X86_32
/*
* B step AMD K6 before B 9730xxxx have hardware bugs that can cause
* misexecution of code under Linux. Owners of such processors should
@@ -70,6 +70,7 @@ __asm__(".globl vide\n\t.align 4\nvide: ret");
static void init_amd_k5(struct cpuinfo_x86 *c)
{
+#ifdef CONFIG_X86_32
/*
* General Systems BIOSen alias the cpu frequency registers
* of the Elan at 0x000df000. Unfortuantly, one of the Linux
@@ -83,11 +84,12 @@ static void init_amd_k5(struct cpuinfo_x86 *c)
if (inl(CBAR) & CBAR_ENB)
outl(0 | CBAR_KEY, CBAR);
}
+#endif
}
-
static void init_amd_k6(struct cpuinfo_x86 *c)
{
+#ifdef CONFIG_X86_32
u32 l, h;
int mbytes = get_num_physpages() >> (20-PAGE_SHIFT);
@@ -176,10 +178,44 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
/* placeholder for any needed mods */
return;
}
+#endif
}
-static void amd_k7_smp_check(struct cpuinfo_x86 *c)
+static void init_amd_k7(struct cpuinfo_x86 *c)
{
+#ifdef CONFIG_X86_32
+ u32 l, h;
+
+ /*
+ * Bit 15 of Athlon specific MSR 15, needs to be 0
+ * to enable SSE on Palomino/Morgan/Barton CPU's.
+ * If the BIOS didn't enable it already, enable it here.
+ */
+ if (c->x86_model >= 6 && c->x86_model <= 10) {
+ if (!cpu_has(c, X86_FEATURE_XMM)) {
+ printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
+ msr_clear_bit(MSR_K7_HWCR, 15);
+ set_cpu_cap(c, X86_FEATURE_XMM);
+ }
+ }
+
+ /*
+ * It's been determined by AMD that Athlons since model 8 stepping 1
+ * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
+ * As per AMD technical note 27212 0.2
+ */
+ if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
+ rdmsr(MSR_K7_CLK_CTL, l, h);
+ if ((l & 0xfff00000) != 0x20000000) {
+ printk(KERN_INFO
+ "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
+ l, ((l & 0x000fffff)|0x20000000));
+ wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
+ }
+ }
+
+ set_cpu_cap(c, X86_FEATURE_K7);
+
/* calling is from identify_secondary_cpu() ? */
if (!c->cpu_index)
return;
@@ -207,7 +243,7 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
((c->x86_model == 7) && (c->x86_mask >= 1)) ||
(c->x86_model > 7))
- if (cpu_has_mp)
+ if (cpu_has(c, X86_FEATURE_MP))
return;
/* If we get here, not a certified SMP capable AMD system. */
@@ -219,45 +255,8 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: This combination of AMD"
" processors is not suitable for SMP.\n");
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
-}
-
-static void init_amd_k7(struct cpuinfo_x86 *c)
-{
- u32 l, h;
-
- /*
- * Bit 15 of Athlon specific MSR 15, needs to be 0
- * to enable SSE on Palomino/Morgan/Barton CPU's.
- * If the BIOS didn't enable it already, enable it here.
- */
- if (c->x86_model >= 6 && c->x86_model <= 10) {
- if (!cpu_has(c, X86_FEATURE_XMM)) {
- printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
- msr_clear_bit(MSR_K7_HWCR, 15);
- set_cpu_cap(c, X86_FEATURE_XMM);
- }
- }
-
- /*
- * It's been determined by AMD that Athlons since model 8 stepping 1
- * are more robust with CLK_CTL set to 200xxxxx instead of 600xxxxx
- * As per AMD technical note 27212 0.2
- */
- if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
- rdmsr(MSR_K7_CLK_CTL, l, h);
- if ((l & 0xfff00000) != 0x20000000) {
- printk(KERN_INFO
- "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
- l, ((l & 0x000fffff)|0x20000000));
- wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
- }
- }
-
- set_cpu_cap(c, X86_FEATURE_K7);
-
- amd_k7_smp_check(c);
-}
#endif
+}
#ifdef CONFIG_NUMA
/*
@@ -446,6 +445,26 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
static void bsp_init_amd(struct cpuinfo_x86 *c)
{
+
+#ifdef CONFIG_X86_64
+ if (c->x86 >= 0xf) {
+ unsigned long long tseg;
+
+ /*
+ * Split up direct mapping around the TSEG SMM area.
+ * Don't do it for gbpages because there seems very little
+ * benefit in doing so.
+ */
+ if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
+ unsigned long pfn = tseg >> PAGE_SHIFT;
+
+ printk(KERN_DEBUG "tseg: %010llx\n", tseg);
+ if (pfn_range_is_mapped(pfn, pfn + 1))
+ set_memory_4k((unsigned long)__va(tseg), 1);
+ }
+ }
+#endif
+
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
if (c->x86 > 0x10 ||
@@ -515,101 +534,74 @@ static const int amd_erratum_383[];
static const int amd_erratum_400[];
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
-static void init_amd(struct cpuinfo_x86 *c)
+static void init_amd_k8(struct cpuinfo_x86 *c)
{
- u32 dummy;
- unsigned long long value;
+ u32 level;
+ u64 value;
-#ifdef CONFIG_SMP
- /*
- * Disable TLB flush filter by setting HWCR.FFDIS on K8
- * bit 6 of msr C001_0015
- *
- * Errata 63 for SH-B3 steppings
- * Errata 122 for all steppings (F+ have it disabled by default)
- */
- if (c->x86 == 0xf)
- msr_set_bit(MSR_K7_HWCR, 6);
-#endif
-
- early_init_amd(c);
+ /* On C+ stepping K8 rep microcode works well for copy/memset */
+ level = cpuid_eax(1);
+ if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
+ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
/*
- * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
- * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+ * Some BIOSes incorrectly force this feature, but only K8 revision D
+ * (model = 0x14) and later actually support it.
+ * (AMD Erratum #110, docId: 25759).
*/
- clear_cpu_cap(c, 0*32+31);
-
-#ifdef CONFIG_X86_64
- /* On C+ stepping K8 rep microcode works well for copy/memset */
- if (c->x86 == 0xf) {
- u32 level;
-
- level = cpuid_eax(1);
- if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-
- /*
- * Some BIOSes incorrectly force this feature, but only K8
- * revision D (model = 0x14) and later actually support it.
- * (AMD Erratum #110, docId: 25759).
- */
- if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
- clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
- if (!rdmsrl_amd_safe(0xc001100d, &value)) {
- value &= ~(1ULL << 32);
- wrmsrl_amd_safe(0xc001100d, value);
- }
+ if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) {
+ clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
+ if (!rdmsrl_amd_safe(0xc001100d, &value)) {
+ value &= ~BIT_64(32);
+ wrmsrl_amd_safe(0xc001100d, value);
}
-
}
- if (c->x86 >= 0x10)
- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
- /* get apicid instead of initial apic id from cpuid */
- c->apicid = hard_smp_processor_id();
-#else
+ if (!c->x86_model_id[0])
+ strcpy(c->x86_model_id, "Hammer");
+}
+
+static void init_amd_gh(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+ /* do this for boot cpu */
+ if (c == &boot_cpu_data)
+ check_enable_amd_mmconf_dmi();
+
+ fam10h_check_enable_mmcfg();
+#endif
/*
- * FIXME: We should handle the K5 here. Set up the write
- * range and also turn on MSR 83 bits 4 and 31 (write alloc,
- * no bus pipeline)
+ * Disable GART TLB Walk Errors on Fam10h. We do this here because this
+ * is always needed when GART is enabled, even in a kernel which has no
+ * MCE support built in. BIOS should disable GartTlbWlk Errors already.
+ * If it doesn't, we do it here as suggested by the BKDG.
+ *
+ * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
*/
+ msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
- switch (c->x86) {
- case 4:
- init_amd_k5(c);
- break;
- case 5:
- init_amd_k6(c);
- break;
- case 6: /* An Athlon/Duron */
- init_amd_k7(c);
- break;
- }
+ /*
+ * On family 10h BIOS may not have properly enabled WC+ support, causing
+ * it to be converted to CD memtype. This may result in performance
+ * degradation for certain nested-paging guests. Prevent this conversion
+ * by clearing bit 24 in MSR_AMD64_BU_CFG2.
+ *
+ * NOTE: we want to use the _safe accessors so as not to #GP kvm
+ * guests on older kvm hosts.
+ */
+ msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
- /* K6s reports MCEs but don't actually have all the MSRs */
- if (c->x86 < 6)
- clear_cpu_cap(c, X86_FEATURE_MCE);
-#endif
+ if (cpu_has_amd_erratum(c, amd_erratum_383))
+ set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
+}
- /* Enable workaround for FXSAVE leak */
- if (c->x86 >= 6)
- set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
-
- if (!c->x86_model_id[0]) {
- switch (c->x86) {
- case 0xf:
- /* Should distinguish Models here, but this is only
- a fallback anyways. */
- strcpy(c->x86_model_id, "Hammer");
- break;
- }
- }
+static void init_amd_bd(struct cpuinfo_x86 *c)
+{
+ u64 value;
/* re-enable TopologyExtensions if switched off by BIOS */
- if ((c->x86 == 0x15) &&
- (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+ if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
!cpu_has(c, X86_FEATURE_TOPOEXT)) {
if (msr_set_bit(0xc0011005, 54) > 0) {
@@ -625,14 +617,60 @@ static void 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)) {
-
+ if ((c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
if (!rdmsrl_safe(0xc0011021, &value) && !(value & 0x1E)) {
value |= 0x1E;
wrmsrl_safe(0xc0011021, value);
}
}
+}
+
+static void init_amd(struct cpuinfo_x86 *c)
+{
+ u32 dummy;
+
+#ifdef CONFIG_SMP
+ /*
+ * Disable TLB flush filter by setting HWCR.FFDIS on K8
+ * bit 6 of msr C001_0015
+ *
+ * Errata 63 for SH-B3 steppings
+ * Errata 122 for all steppings (F+ have it disabled by default)
+ */
+ if (c->x86 == 0xf)
+ msr_set_bit(MSR_K7_HWCR, 6);
+#endif
+
+ early_init_amd(c);
+
+ /*
+ * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
+ */
+ clear_cpu_cap(c, 0*32+31);
+
+ if (c->x86 >= 0x10)
+ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+
+ /* get apicid instead of initial apic id from cpuid */
+ c->apicid = hard_smp_processor_id();
+
+ /* K6s reports MCEs but don't actually have all the MSRs */
+ if (c->x86 < 6)
+ clear_cpu_cap(c, X86_FEATURE_MCE);
+
+ switch (c->x86) {
+ case 4: init_amd_k5(c); break;
+ case 5: init_amd_k6(c); break;
+ case 6: init_amd_k7(c); break;
+ case 0xf: init_amd_k8(c); break;
+ case 0x10: init_amd_gh(c); break;
+ case 0x15: init_amd_bd(c); break;
+ }
+
+ /* Enable workaround for FXSAVE leak */
+ if (c->x86 >= 6)
+ set_cpu_bug(c, X86_BUG_FXSAVE_LEAK);
cpu_detect_cache_sizes(c);
@@ -656,33 +694,6 @@ static void init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
}
-#ifdef CONFIG_X86_64
- if (c->x86 == 0x10) {
- /* do this for boot cpu */
- if (c == &boot_cpu_data)
- check_enable_amd_mmconf_dmi();
-
- fam10h_check_enable_mmcfg();
- }
-
- if (c == &boot_cpu_data && c->x86 >= 0xf) {
- unsigned long long tseg;
-
- /*
- * Split up direct mapping around the TSEG SMM area.
- * Don't do it for gbpages because there seems very little
- * benefit in doing so.
- */
- if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
- unsigned long pfn = tseg >> PAGE_SHIFT;
-
- printk(KERN_DEBUG "tseg: %010llx\n", tseg);
- if (pfn_range_is_mapped(pfn, pfn + 1))
- set_memory_4k((unsigned long)__va(tseg), 1);
- }
- }
-#endif
-
/*
* Family 0x12 and above processors have APIC timer
* running in deep C states.
@@ -690,34 +701,6 @@ static void init_amd(struct cpuinfo_x86 *c)
if (c->x86 > 0x11)
set_cpu_cap(c, X86_FEATURE_ARAT);
- if (c->x86 == 0x10) {
- /*
- * Disable GART TLB Walk Errors on Fam10h. We do this here
- * because this is always needed when GART is enabled, even in a
- * kernel which has no MCE support built in.
- * BIOS should disable GartTlbWlk Errors already. If
- * it doesn't, do it here as suggested by the BKDG.
- *
- * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
- */
- msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
-
- /*
- * On family 10h BIOS may not have properly enabled WC+ support,
- * causing it to be converted to CD memtype. This may result in
- * performance degradation for certain nested-paging guests.
- * Prevent this conversion by clearing bit 24 in
- * MSR_AMD64_BU_CFG2.
- *
- * NOTE: we want to use the _safe accessors so as not to #GP kvm
- * guests on older kvm hosts.
- */
- msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
-
- if (cpu_has_amd_erratum(c, amd_erratum_383))
- set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
- }
-
if (cpu_has_amd_erratum(c, amd_erratum_400))
set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
@@ -741,11 +724,6 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
}
#endif
-static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c)
-{
- tlb_flushall_shift = 6;
-}
-
static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
{
u32 ebx, eax, ecx, edx;
@@ -793,8 +771,6 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
tlb_lli_2m[ENTRIES] = eax & mask;
tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1;
-
- cpu_set_tlb_flushall_shift(c);
}
static const struct cpu_dev amd_cpu_dev = {
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ef1b93f18ed1..e4ab2b42bd6f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -148,6 +148,7 @@ static int __init x86_xsave_setup(char *s)
{
setup_clear_cpu_cap(X86_FEATURE_XSAVE);
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
+ setup_clear_cpu_cap(X86_FEATURE_XSAVES);
setup_clear_cpu_cap(X86_FEATURE_AVX);
setup_clear_cpu_cap(X86_FEATURE_AVX2);
return 1;
@@ -161,6 +162,13 @@ static int __init x86_xsaveopt_setup(char *s)
}
__setup("noxsaveopt", x86_xsaveopt_setup);
+static int __init x86_xsaves_setup(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_XSAVES);
+ return 1;
+}
+__setup("noxsaves", x86_xsaves_setup);
+
#ifdef CONFIG_X86_32
static int cachesize_override = -1;
static int disable_x86_serial_nr = 1;
@@ -481,26 +489,17 @@ u16 __read_mostly tlb_lld_2m[NR_INFO];
u16 __read_mostly tlb_lld_4m[NR_INFO];
u16 __read_mostly tlb_lld_1g[NR_INFO];
-/*
- * tlb_flushall_shift shows the balance point in replacing cr3 write
- * with multiple 'invlpg'. It will do this replacement when
- * flush_tlb_lines <= active_lines/2^tlb_flushall_shift.
- * If tlb_flushall_shift is -1, means the replacement will be disabled.
- */
-s8 __read_mostly tlb_flushall_shift = -1;
-
void cpu_detect_tlb(struct cpuinfo_x86 *c)
{
if (this_cpu->c_detect_tlb)
this_cpu->c_detect_tlb(c);
printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n"
- "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n"
- "tlb_flushall_shift: %d\n",
+ "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n",
tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES],
tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES],
tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES],
- tlb_lld_1g[ENTRIES], tlb_flushall_shift);
+ tlb_lld_1g[ENTRIES]);
}
void detect_ht(struct cpuinfo_x86 *c)
@@ -634,6 +633,15 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
c->x86_capability[9] = ebx;
}
+ /* Extended state features: level 0x0000000d */
+ if (c->cpuid_level >= 0x0000000d) {
+ u32 eax, ebx, ecx, edx;
+
+ cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx);
+
+ c->x86_capability[10] = eax;
+ }
+
/* AMD-defined flags: level 0x80000001 */
xlvl = cpuid_eax(0x80000000);
c->extended_cpuid_level = xlvl;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f9e4fdd3b877..74e804ddc5c7 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -253,7 +253,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
*/
if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
(c->x86_mask < 0x6 || c->x86_mask == 0xb))
- set_cpu_cap(c, X86_FEATURE_11AP);
+ set_cpu_bug(c, X86_BUG_11AP);
#ifdef CONFIG_X86_INTEL_USERCOPY
@@ -402,7 +402,7 @@ static void init_intel(struct cpuinfo_x86 *c)
if (c->x86 == 6 && cpu_has_clflush &&
(c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
- set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
+ set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
#ifdef CONFIG_X86_64
if (c->x86 == 15)
@@ -634,31 +634,6 @@ static void intel_tlb_lookup(const unsigned char desc)
}
}
-static void intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c)
-{
- switch ((c->x86 << 8) + c->x86_model) {
- case 0x60f: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
- case 0x616: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
- case 0x617: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
- case 0x61d: /* six-core 45 nm xeon "Dunnington" */
- tlb_flushall_shift = -1;
- break;
- case 0x63a: /* Ivybridge */
- tlb_flushall_shift = 2;
- break;
- case 0x61a: /* 45 nm nehalem, "Bloomfield" */
- case 0x61e: /* 45 nm nehalem, "Lynnfield" */
- case 0x625: /* 32 nm nehalem, "Clarkdale" */
- case 0x62c: /* 32 nm nehalem, "Gulftown" */
- case 0x62e: /* 45 nm nehalem-ex, "Beckton" */
- case 0x62f: /* 32 nm Xeon E7 */
- case 0x62a: /* SandyBridge */
- case 0x62d: /* SandyBridge, "Romely-EP" */
- default:
- tlb_flushall_shift = 6;
- }
-}
-
static void intel_detect_tlb(struct cpuinfo_x86 *c)
{
int i, j, n;
@@ -683,7 +658,6 @@ static void intel_detect_tlb(struct cpuinfo_x86 *c)
for (j = 1 ; j < 16 ; j++)
intel_tlb_lookup(desc[j]);
}
- intel_tlb_flushall_shift_set(c);
}
static const struct cpu_dev intel_cpu_dev = {
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 9c8f7394c612..c7035073dfc1 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -461,7 +461,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
- if (strict_strtoul(buf, 10, &val) < 0)
+ if (kstrtoul(buf, 10, &val) < 0)
return -EINVAL;
err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
@@ -511,7 +511,7 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
if (!this_leaf->base.nb || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL;
- if (strict_strtoul(buf, 16, &val) < 0)
+ if (kstrtoul(buf, 16, &val) < 0)
return -EINVAL;
if (amd_set_subcaches(cpu, val))
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 9a79c8dbd8e8..bd9ccda8087f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2136,7 +2136,7 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr,
{
u64 new;
- if (strict_strtoull(buf, 0, &new) < 0)
+ if (kstrtou64(buf, 0, &new) < 0)
return -EINVAL;
attr_to_bank(attr)->ctl = new;
@@ -2174,7 +2174,7 @@ static ssize_t set_ignore_ce(struct device *s,
{
u64 new;
- if (strict_strtoull(buf, 0, &new) < 0)
+ if (kstrtou64(buf, 0, &new) < 0)
return -EINVAL;
if (mca_cfg.ignore_ce ^ !!new) {
@@ -2198,7 +2198,7 @@ static ssize_t set_cmci_disabled(struct device *s,
{
u64 new;
- if (strict_strtoull(buf, 0, &new) < 0)
+ if (kstrtou64(buf, 0, &new) < 0)
return -EINVAL;
if (mca_cfg.cmci_disabled ^ !!new) {
@@ -2385,6 +2385,10 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
threshold_cpu_callback(action, cpu);
mce_device_remove(cpu);
mce_intel_hcpu_update(cpu);
+
+ /* intentionally ignoring frozen here */
+ if (!(action & CPU_TASKS_FROZEN))
+ cmci_rediscover();
break;
case CPU_DOWN_PREPARE:
smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
@@ -2396,11 +2400,6 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
break;
}
- if (action == CPU_POST_DEAD) {
- /* intentionally ignoring frozen here */
- cmci_rediscover();
- }
-
return NOTIFY_OK;
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 603df4f74640..1e49f8f41276 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -353,7 +353,7 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
if (!b->interrupt_capable)
return -EINVAL;
- if (strict_strtoul(buf, 0, &new) < 0)
+ if (kstrtoul(buf, 0, &new) < 0)
return -EINVAL;
b->interrupt_enable = !!new;
@@ -372,7 +372,7 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
struct thresh_restart tr;
unsigned long new;
- if (strict_strtoul(buf, 0, &new) < 0)
+ if (kstrtoul(buf, 0, &new) < 0)
return -EINVAL;
if (new > THRESHOLD_MAX)
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 9a316b21df8b..3bdb95ae8c43 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
* cmci_discover_lock protects against parallel discovery attempts
* which could race against each other.
*/
-static DEFINE_SPINLOCK(cmci_discover_lock);
+static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
#define CMCI_THRESHOLD 1
#define CMCI_POLL_INTERVAL (30 * HZ)
@@ -144,14 +144,14 @@ static void cmci_storm_disable_banks(void)
int bank;
u64 val;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
owned = __get_cpu_var(mce_banks_owned);
for_each_set_bit(bank, owned, MAX_NR_BANKS) {
rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
val &= ~MCI_CTL2_CMCI_EN;
wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
}
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static bool cmci_storm_detect(void)
@@ -211,7 +211,7 @@ static void cmci_discover(int banks)
int i;
int bios_wrong_thresh = 0;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++) {
u64 val;
int bios_zero_thresh = 0;
@@ -266,7 +266,7 @@ static void cmci_discover(int banks)
WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
}
}
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) {
pr_info_once(
"bios_cmci_threshold: Some banks do not have valid thresholds set\n");
@@ -316,10 +316,10 @@ void cmci_clear(void)
if (!cmci_supported(&banks))
return;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
for (i = 0; i < banks; i++)
__cmci_disable_bank(i);
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static void cmci_rediscover_work_func(void *arg)
@@ -360,9 +360,9 @@ void cmci_disable_bank(int bank)
if (!cmci_supported(&banks))
return;
- spin_lock_irqsave(&cmci_discover_lock, flags);
+ raw_spin_lock_irqsave(&cmci_discover_lock, flags);
__cmci_disable_bank(bank);
- spin_unlock_irqrestore(&cmci_discover_lock, flags);
+ raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
static void intel_init_cmci(void)
diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh
index 2bf616505499..e2b22df964cd 100644
--- a/arch/x86/kernel/cpu/mkcapflags.sh
+++ b/arch/x86/kernel/cpu/mkcapflags.sh
@@ -1,23 +1,25 @@
#!/bin/sh
#
-# Generate the x86_cap_flags[] array from include/asm/cpufeature.h
+# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h
#
IN=$1
OUT=$2
-TABS="$(printf '\t\t\t\t\t')"
-trap 'rm "$OUT"' EXIT
+function dump_array()
+{
+ ARRAY=$1
+ SIZE=$2
+ PFX=$3
+ POSTFIX=$4
-(
- echo "#ifndef _ASM_X86_CPUFEATURE_H"
- echo "#include <asm/cpufeature.h>"
- echo "#endif"
- echo ""
- echo "const char * const x86_cap_flags[NCAPINTS*32] = {"
+ PFX_SZ=$(echo $PFX | wc -c)
+ TABS="$(printf '\t\t\t\t\t')"
+
+ echo "const char * const $ARRAY[$SIZE] = {"
- # Iterate through any input lines starting with #define X86_FEATURE_
- sed -n -e 's/\t/ /g' -e 's/^ *# *define *X86_FEATURE_//p' $IN |
+ # Iterate through any input lines starting with #define $PFX
+ sed -n -e 's/\t/ /g' -e "s/^ *# *define *$PFX//p" $IN |
while read i
do
# Name is everything up to the first whitespace
@@ -31,11 +33,32 @@ trap 'rm "$OUT"' EXIT
# Name is uppercase, VALUE is all lowercase
VALUE="$(echo "$VALUE" | tr A-Z a-z)"
- TABCOUNT=$(( ( 5*8 - 14 - $(echo "$NAME" | wc -c) ) / 8 ))
- printf "\t[%s]%.*s = %s,\n" \
- "X86_FEATURE_$NAME" "$TABCOUNT" "$TABS" "$VALUE"
+ if [ -n "$POSTFIX" ]; then
+ T=$(( $PFX_SZ + $(echo $POSTFIX | wc -c) + 2 ))
+ TABS="$(printf '\t\t\t\t\t\t')"
+ TABCOUNT=$(( ( 6*8 - ($T + 1) - $(echo "$NAME" | wc -c) ) / 8 ))
+ printf "\t[%s - %s]%.*s = %s,\n" "$PFX$NAME" "$POSTFIX" "$TABCOUNT" "$TABS" "$VALUE"
+ else
+ TABCOUNT=$(( ( 5*8 - ($PFX_SZ + 1) - $(echo "$NAME" | wc -c) ) / 8 ))
+ printf "\t[%s]%.*s = %s,\n" "$PFX$NAME" "$TABCOUNT" "$TABS" "$VALUE"
+ fi
done
echo "};"
+}
+
+trap 'rm "$OUT"' EXIT
+
+(
+ echo "#ifndef _ASM_X86_CPUFEATURE_H"
+ echo "#include <asm/cpufeature.h>"
+ echo "#endif"
+ echo ""
+
+ dump_array "x86_cap_flags" "NCAPINTS*32" "X86_FEATURE_" ""
+ echo ""
+
+ dump_array "x86_bug_flags" "NBUGINTS*32" "X86_BUG_" "NCAPINTS*32"
+
) > $OUT
trap - EXIT
diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c
index 3bbdf4cd38b9..30790d798e6b 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_uncore.c
@@ -294,31 +294,41 @@ static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
cpu_to_node(cpu));
}
-static void amd_uncore_cpu_up_prepare(unsigned int cpu)
+static int amd_uncore_cpu_up_prepare(unsigned int cpu)
{
- struct amd_uncore *uncore;
+ struct amd_uncore *uncore_nb = NULL, *uncore_l2;
if (amd_uncore_nb) {
- uncore = amd_uncore_alloc(cpu);
- uncore->cpu = cpu;
- uncore->num_counters = NUM_COUNTERS_NB;
- uncore->rdpmc_base = RDPMC_BASE_NB;
- uncore->msr_base = MSR_F15H_NB_PERF_CTL;
- uncore->active_mask = &amd_nb_active_mask;
- uncore->pmu = &amd_nb_pmu;
- *per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
+ uncore_nb = amd_uncore_alloc(cpu);
+ if (!uncore_nb)
+ goto fail;
+ uncore_nb->cpu = cpu;
+ uncore_nb->num_counters = NUM_COUNTERS_NB;
+ uncore_nb->rdpmc_base = RDPMC_BASE_NB;
+ uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
+ uncore_nb->active_mask = &amd_nb_active_mask;
+ uncore_nb->pmu = &amd_nb_pmu;
+ *per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
}
if (amd_uncore_l2) {
- uncore = amd_uncore_alloc(cpu);
- uncore->cpu = cpu;
- uncore->num_counters = NUM_COUNTERS_L2;
- uncore->rdpmc_base = RDPMC_BASE_L2;
- uncore->msr_base = MSR_F16H_L2I_PERF_CTL;
- uncore->active_mask = &amd_l2_active_mask;
- uncore->pmu = &amd_l2_pmu;
- *per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
+ uncore_l2 = amd_uncore_alloc(cpu);
+ if (!uncore_l2)
+ goto fail;
+ uncore_l2->cpu = cpu;
+ uncore_l2->num_counters = NUM_COUNTERS_L2;
+ uncore_l2->rdpmc_base = RDPMC_BASE_L2;
+ uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
+ uncore_l2->active_mask = &amd_l2_active_mask;
+ uncore_l2->pmu = &amd_l2_pmu;
+ *per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
}
+
+ return 0;
+
+fail:
+ kfree(uncore_nb);
+ return -ENOMEM;
}
static struct amd_uncore *
@@ -441,7 +451,7 @@ static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
if (!--uncore->refcnt)
kfree(uncore);
- *per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
+ *per_cpu_ptr(uncores, cpu) = NULL;
}
static void amd_uncore_cpu_dead(unsigned int cpu)
@@ -461,7 +471,8 @@ amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action,
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
- amd_uncore_cpu_up_prepare(cpu);
+ if (amd_uncore_cpu_up_prepare(cpu))
+ return notifier_from_errno(-ENOMEM);
break;
case CPU_STARTING:
@@ -501,20 +512,33 @@ static void __init init_cpu_already_online(void *dummy)
amd_uncore_cpu_online(cpu);
}
+static void cleanup_cpu_online(void *dummy)
+{
+ unsigned int cpu = smp_processor_id();
+
+ amd_uncore_cpu_dead(cpu);
+}
+
static int __init amd_uncore_init(void)
{
- unsigned int cpu;
+ unsigned int cpu, cpu2;
int ret = -ENODEV;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
- return -ENODEV;
+ goto fail_nodev;
if (!cpu_has_topoext)
- return -ENODEV;
+ goto fail_nodev;
if (cpu_has_perfctr_nb) {
amd_uncore_nb = alloc_percpu(struct amd_uncore *);
- perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
+ if (!amd_uncore_nb) {
+ ret = -ENOMEM;
+ goto fail_nb;
+ }
+ ret = perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
+ if (ret)
+ goto fail_nb;
printk(KERN_INFO "perf: AMD NB counters detected\n");
ret = 0;
@@ -522,20 +546,28 @@ static int __init amd_uncore_init(void)
if (cpu_has_perfctr_l2) {
amd_uncore_l2 = alloc_percpu(struct amd_uncore *);
- perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
+ if (!amd_uncore_l2) {
+ ret = -ENOMEM;
+ goto fail_l2;
+ }
+ ret = perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
+ if (ret)
+ goto fail_l2;
printk(KERN_INFO "perf: AMD L2I counters detected\n");
ret = 0;
}
if (ret)
- return -ENODEV;
+ goto fail_nodev;
cpu_notifier_register_begin();
/* init cpus already online before registering for hotplug notifier */
for_each_online_cpu(cpu) {
- amd_uncore_cpu_up_prepare(cpu);
+ ret = amd_uncore_cpu_up_prepare(cpu);
+ if (ret)
+ goto fail_online;
smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
}
@@ -543,5 +575,30 @@ static int __init amd_uncore_init(void)
cpu_notifier_register_done();
return 0;
+
+
+fail_online:
+ for_each_online_cpu(cpu2) {
+ if (cpu2 == cpu)
+ break;
+ smp_call_function_single(cpu, cleanup_cpu_online, NULL, 1);
+ }
+ cpu_notifier_register_done();
+
+ /* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */
+ amd_uncore_nb = amd_uncore_l2 = NULL;
+ if (cpu_has_perfctr_l2)
+ perf_pmu_unregister(&amd_l2_pmu);
+fail_l2:
+ if (cpu_has_perfctr_nb)
+ perf_pmu_unregister(&amd_nb_pmu);
+ if (amd_uncore_l2)
+ free_percpu(amd_uncore_l2);
+fail_nb:
+ if (amd_uncore_nb)
+ free_percpu(amd_uncore_nb);
+
+fail_nodev:
+ return ret;
}
device_initcall(amd_uncore_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index ae6552a0701f..0939f86f543d 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -945,7 +945,7 @@ static struct intel_uncore_type *snbep_pci_uncores[] = {
NULL,
};
-static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = {
+static const struct pci_device_id snbep_uncore_pci_ids[] = {
{ /* Home Agent */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
.driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
@@ -1510,7 +1510,7 @@ static struct intel_uncore_type *ivt_pci_uncores[] = {
NULL,
};
-static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = {
+static const struct pci_device_id ivt_uncore_pci_ids[] = {
{ /* Home Agent 0 */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_HA, 0),
@@ -1985,7 +1985,7 @@ static struct intel_uncore_type *snb_pci_uncores[] = {
NULL,
};
-static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = {
+static const struct pci_device_id snb_uncore_pci_ids[] = {
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -1993,7 +1993,7 @@ static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = {
{ /* end: all zeroes */ },
};
-static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = {
+static const struct pci_device_id ivb_uncore_pci_ids[] = {
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -2001,7 +2001,7 @@ static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = {
{ /* end: all zeroes */ },
};
-static DEFINE_PCI_DEVICE_TABLE(hsw_uncore_pci_ids) = {
+static const struct pci_device_id hsw_uncore_pci_ids[] = {
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
@@ -2947,10 +2947,7 @@ again:
* extra registers. If we failed to take an extra
* register, try the alternative.
*/
- if (idx % 2)
- idx--;
- else
- idx++;
+ idx ^= 1;
if (idx != reg1->idx % 6) {
if (idx == 2)
config1 >>= 8;
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 06fe3ed8b851..5433658e598d 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -97,6 +97,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
seq_printf(m, " %s", x86_cap_flags[i]);
+ seq_printf(m, "\nbugs\t\t:");
+ for (i = 0; i < 32*NBUGINTS; i++) {
+ unsigned int bug_bit = 32*NCAPINTS + i;
+
+ if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i])
+ seq_printf(m, " %s", x86_bug_flags[i]);
+ }
+
seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
c->loops_per_jiffy/(500000/HZ),
(c->loops_per_jiffy/(5000/HZ)) % 100);
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index b6f794aa1693..4a8013d55947 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -38,7 +38,6 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
{ X86_FEATURE_PTS, CR_EAX, 6, 0x00000006, 0 },
{ X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 },
{ X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 },
- { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 },
{ X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 },
{ X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 },
{ X86_FEATURE_PROC_FEEDBACK, CR_EDX,11, 0x80000007, 0 },
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 507de8066594..0553a34fa0df 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -4,9 +4,14 @@
* Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
*
* Copyright (C) IBM Corporation, 2004. All rights reserved.
+ * Copyright (C) Red Hat Inc., 2014. All rights reserved.
+ * Authors:
+ * Vivek Goyal <vgoyal@redhat.com>
*
*/
+#define pr_fmt(fmt) "kexec: " fmt
+
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
@@ -16,6 +21,7 @@
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/processor.h>
#include <asm/hardirq.h>
@@ -28,6 +34,45 @@
#include <asm/reboot.h>
#include <asm/virtext.h>
+/* Alignment required for elf header segment */
+#define ELF_CORE_HEADER_ALIGN 4096
+
+/* This primarily represents number of split ranges due to exclusion */
+#define CRASH_MAX_RANGES 16
+
+struct crash_mem_range {
+ u64 start, end;
+};
+
+struct crash_mem {
+ unsigned int nr_ranges;
+ struct crash_mem_range ranges[CRASH_MAX_RANGES];
+};
+
+/* Misc data about ram ranges needed to prepare elf headers */
+struct crash_elf_data {
+ struct kimage *image;
+ /*
+ * Total number of ram ranges we have after various adjustments for
+ * GART, crash reserved region etc.
+ */
+ unsigned int max_nr_ranges;
+ unsigned long gart_start, gart_end;
+
+ /* Pointer to elf header */
+ void *ehdr;
+ /* Pointer to next phdr */
+ void *bufp;
+ struct crash_mem mem;
+};
+
+/* Used while preparing memory map entries for second kernel */
+struct crash_memmap_data {
+ struct boot_params *params;
+ /* Type of memory */
+ unsigned int type;
+};
+
int in_crash_kexec;
/*
@@ -39,6 +84,7 @@ int in_crash_kexec;
*/
crash_vmclear_fn __rcu *crash_vmclear_loaded_vmcss = NULL;
EXPORT_SYMBOL_GPL(crash_vmclear_loaded_vmcss);
+unsigned long crash_zero_bytes;
static inline void cpu_crash_vmclear_loaded_vmcss(void)
{
@@ -135,3 +181,520 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
#endif
crash_save_cpu(regs, safe_smp_processor_id());
}
+
+#ifdef CONFIG_X86_64
+
+static int get_nr_ram_ranges_callback(unsigned long start_pfn,
+ unsigned long nr_pfn, void *arg)
+{
+ int *nr_ranges = arg;
+
+ (*nr_ranges)++;
+ return 0;
+}
+
+static int get_gart_ranges_callback(u64 start, u64 end, void *arg)
+{
+ struct crash_elf_data *ced = arg;
+
+ ced->gart_start = start;
+ ced->gart_end = end;
+
+ /* Not expecting more than 1 gart aperture */
+ return 1;
+}
+
+
+/* Gather all the required information to prepare elf headers for ram regions */
+static void fill_up_crash_elf_data(struct crash_elf_data *ced,
+ struct kimage *image)
+{
+ unsigned int nr_ranges = 0;
+
+ ced->image = image;
+
+ walk_system_ram_range(0, -1, &nr_ranges,
+ get_nr_ram_ranges_callback);
+
+ ced->max_nr_ranges = nr_ranges;
+
+ /*
+ * We don't create ELF headers for GART aperture as an attempt
+ * to dump this memory in second kernel leads to hang/crash.
+ * If gart aperture is present, one needs to exclude that region
+ * and that could lead to need of extra phdr.
+ */
+ walk_iomem_res("GART", IORESOURCE_MEM, 0, -1,
+ ced, get_gart_ranges_callback);
+
+ /*
+ * If we have gart region, excluding that could potentially split
+ * a memory range, resulting in extra header. Account for that.
+ */
+ if (ced->gart_end)
+ ced->max_nr_ranges++;
+
+ /* Exclusion of crash region could split memory ranges */
+ ced->max_nr_ranges++;
+
+ /* If crashk_low_res is not 0, another range split possible */
+ if (crashk_low_res.end != 0)
+ ced->max_nr_ranges++;
+}
+
+static int exclude_mem_range(struct crash_mem *mem,
+ unsigned long long mstart, unsigned long long mend)
+{
+ int i, j;
+ unsigned long long start, end;
+ struct crash_mem_range temp_range = {0, 0};
+
+ for (i = 0; i < mem->nr_ranges; i++) {
+ start = mem->ranges[i].start;
+ end = mem->ranges[i].end;
+
+ if (mstart > end || mend < start)
+ continue;
+
+ /* Truncate any area outside of range */
+ if (mstart < start)
+ mstart = start;
+ if (mend > end)
+ mend = end;
+
+ /* Found completely overlapping range */
+ if (mstart == start && mend == end) {
+ mem->ranges[i].start = 0;
+ mem->ranges[i].end = 0;
+ if (i < mem->nr_ranges - 1) {
+ /* Shift rest of the ranges to left */
+ for (j = i; j < mem->nr_ranges - 1; j++) {
+ mem->ranges[j].start =
+ mem->ranges[j+1].start;
+ mem->ranges[j].end =
+ mem->ranges[j+1].end;
+ }
+ }
+ mem->nr_ranges--;
+ return 0;
+ }
+
+ if (mstart > start && mend < end) {
+ /* Split original range */
+ mem->ranges[i].end = mstart - 1;
+ temp_range.start = mend + 1;
+ temp_range.end = end;
+ } else if (mstart != start)
+ mem->ranges[i].end = mstart - 1;
+ else
+ mem->ranges[i].start = mend + 1;
+ break;
+ }
+
+ /* If a split happend, add the split to array */
+ if (!temp_range.end)
+ return 0;
+
+ /* Split happened */
+ if (i == CRASH_MAX_RANGES - 1) {
+ pr_err("Too many crash ranges after split\n");
+ return -ENOMEM;
+ }
+
+ /* Location where new range should go */
+ j = i + 1;
+ if (j < mem->nr_ranges) {
+ /* Move over all ranges one slot towards the end */
+ for (i = mem->nr_ranges - 1; i >= j; i--)
+ mem->ranges[i + 1] = mem->ranges[i];
+ }
+
+ mem->ranges[j].start = temp_range.start;
+ mem->ranges[j].end = temp_range.end;
+ mem->nr_ranges++;
+ return 0;
+}
+
+/*
+ * Look for any unwanted ranges between mstart, mend and remove them. This
+ * might lead to split and split ranges are put in ced->mem.ranges[] array
+ */
+static int elf_header_exclude_ranges(struct crash_elf_data *ced,
+ unsigned long long mstart, unsigned long long mend)
+{
+ struct crash_mem *cmem = &ced->mem;
+ int ret = 0;
+
+ memset(cmem->ranges, 0, sizeof(cmem->ranges));
+
+ cmem->ranges[0].start = mstart;
+ cmem->ranges[0].end = mend;
+ cmem->nr_ranges = 1;
+
+ /* Exclude crashkernel region */
+ ret = exclude_mem_range(cmem, crashk_res.start, crashk_res.end);
+ if (ret)
+ return ret;
+
+ ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
+ if (ret)
+ return ret;
+
+ /* Exclude GART region */
+ if (ced->gart_end) {
+ ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int prepare_elf64_ram_headers_callback(u64 start, u64 end, void *arg)
+{
+ struct crash_elf_data *ced = arg;
+ Elf64_Ehdr *ehdr;
+ Elf64_Phdr *phdr;
+ unsigned long mstart, mend;
+ struct kimage *image = ced->image;
+ struct crash_mem *cmem;
+ int ret, i;
+
+ ehdr = ced->ehdr;
+
+ /* Exclude unwanted mem ranges */
+ ret = elf_header_exclude_ranges(ced, start, end);
+ if (ret)
+ return ret;
+
+ /* Go through all the ranges in ced->mem.ranges[] and prepare phdr */
+ cmem = &ced->mem;
+
+ for (i = 0; i < cmem->nr_ranges; i++) {
+ mstart = cmem->ranges[i].start;
+ mend = cmem->ranges[i].end;
+
+ phdr = ced->bufp;
+ ced->bufp += sizeof(Elf64_Phdr);
+
+ phdr->p_type = PT_LOAD;
+ phdr->p_flags = PF_R|PF_W|PF_X;
+ phdr->p_offset = mstart;
+
+ /*
+ * If a range matches backup region, adjust offset to backup
+ * segment.
+ */
+ if (mstart == image->arch.backup_src_start &&
+ (mend - mstart + 1) == image->arch.backup_src_sz)
+ phdr->p_offset = image->arch.backup_load_addr;
+
+ phdr->p_paddr = mstart;
+ phdr->p_vaddr = (unsigned long long) __va(mstart);
+ phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
+ phdr->p_align = 0;
+ ehdr->e_phnum++;
+ pr_debug("Crash PT_LOAD elf header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx\n",
+ phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
+ ehdr->e_phnum, phdr->p_offset);
+ }
+
+ return ret;
+}
+
+static int prepare_elf64_headers(struct crash_elf_data *ced,
+ void **addr, unsigned long *sz)
+{
+ Elf64_Ehdr *ehdr;
+ Elf64_Phdr *phdr;
+ unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
+ unsigned char *buf, *bufp;
+ unsigned int cpu;
+ unsigned long long notes_addr;
+ int ret;
+
+ /* extra phdr for vmcoreinfo elf note */
+ nr_phdr = nr_cpus + 1;
+ nr_phdr += ced->max_nr_ranges;
+
+ /*
+ * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
+ * area on x86_64 (ffffffff80000000 - ffffffffa0000000).
+ * I think this is required by tools like gdb. So same physical
+ * memory will be mapped in two elf headers. One will contain kernel
+ * text virtual addresses and other will have __va(physical) addresses.
+ */
+
+ nr_phdr++;
+ elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
+ elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
+
+ buf = vzalloc(elf_sz);
+ if (!buf)
+ return -ENOMEM;
+
+ bufp = buf;
+ ehdr = (Elf64_Ehdr *)bufp;
+ bufp += sizeof(Elf64_Ehdr);
+ memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
+ ehdr->e_ident[EI_CLASS] = ELFCLASS64;
+ ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELF_OSABI;
+ memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
+ ehdr->e_type = ET_CORE;
+ ehdr->e_machine = ELF_ARCH;
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_phoff = sizeof(Elf64_Ehdr);
+ ehdr->e_ehsize = sizeof(Elf64_Ehdr);
+ ehdr->e_phentsize = sizeof(Elf64_Phdr);
+
+ /* Prepare one phdr of type PT_NOTE for each present cpu */
+ for_each_present_cpu(cpu) {
+ phdr = (Elf64_Phdr *)bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_NOTE;
+ notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
+ phdr->p_offset = phdr->p_paddr = notes_addr;
+ phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
+ (ehdr->e_phnum)++;
+ }
+
+ /* Prepare one PT_NOTE header for vmcoreinfo */
+ phdr = (Elf64_Phdr *)bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_NOTE;
+ phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
+ phdr->p_filesz = phdr->p_memsz = sizeof(vmcoreinfo_note);
+ (ehdr->e_phnum)++;
+
+#ifdef CONFIG_X86_64
+ /* Prepare PT_LOAD type program header for kernel text region */
+ phdr = (Elf64_Phdr *)bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_LOAD;
+ phdr->p_flags = PF_R|PF_W|PF_X;
+ phdr->p_vaddr = (Elf64_Addr)_text;
+ phdr->p_filesz = phdr->p_memsz = _end - _text;
+ phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
+ (ehdr->e_phnum)++;
+#endif
+
+ /* Prepare PT_LOAD headers for system ram chunks. */
+ ced->ehdr = ehdr;
+ ced->bufp = bufp;
+ ret = walk_system_ram_res(0, -1, ced,
+ prepare_elf64_ram_headers_callback);
+ if (ret < 0)
+ return ret;
+
+ *addr = buf;
+ *sz = elf_sz;
+ return 0;
+}
+
+/* Prepare elf headers. Return addr and size */
+static int prepare_elf_headers(struct kimage *image, void **addr,
+ unsigned long *sz)
+{
+ struct crash_elf_data *ced;
+ int ret;
+
+ ced = kzalloc(sizeof(*ced), GFP_KERNEL);
+ if (!ced)
+ return -ENOMEM;
+
+ fill_up_crash_elf_data(ced, image);
+
+ /* By default prepare 64bit headers */
+ ret = prepare_elf64_headers(ced, addr, sz);
+ kfree(ced);
+ return ret;
+}
+
+static int add_e820_entry(struct boot_params *params, struct e820entry *entry)
+{
+ unsigned int nr_e820_entries;
+
+ nr_e820_entries = params->e820_entries;
+ if (nr_e820_entries >= E820MAX)
+ return 1;
+
+ memcpy(&params->e820_map[nr_e820_entries], entry,
+ sizeof(struct e820entry));
+ params->e820_entries++;
+ return 0;
+}
+
+static int memmap_entry_callback(u64 start, u64 end, void *arg)
+{
+ struct crash_memmap_data *cmd = arg;
+ struct boot_params *params = cmd->params;
+ struct e820entry ei;
+
+ ei.addr = start;
+ ei.size = end - start + 1;
+ ei.type = cmd->type;
+ add_e820_entry(params, &ei);
+
+ return 0;
+}
+
+static int memmap_exclude_ranges(struct kimage *image, struct crash_mem *cmem,
+ unsigned long long mstart,
+ unsigned long long mend)
+{
+ unsigned long start, end;
+ int ret = 0;
+
+ cmem->ranges[0].start = mstart;
+ cmem->ranges[0].end = mend;
+ cmem->nr_ranges = 1;
+
+ /* Exclude Backup region */
+ start = image->arch.backup_load_addr;
+ end = start + image->arch.backup_src_sz - 1;
+ ret = exclude_mem_range(cmem, start, end);
+ if (ret)
+ return ret;
+
+ /* Exclude elf header region */
+ start = image->arch.elf_load_addr;
+ end = start + image->arch.elf_headers_sz - 1;
+ return exclude_mem_range(cmem, start, end);
+}
+
+/* Prepare memory map for crash dump kernel */
+int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
+{
+ int i, ret = 0;
+ unsigned long flags;
+ struct e820entry ei;
+ struct crash_memmap_data cmd;
+ struct crash_mem *cmem;
+
+ cmem = vzalloc(sizeof(struct crash_mem));
+ if (!cmem)
+ return -ENOMEM;
+
+ memset(&cmd, 0, sizeof(struct crash_memmap_data));
+ cmd.params = params;
+
+ /* Add first 640K segment */
+ ei.addr = image->arch.backup_src_start;
+ ei.size = image->arch.backup_src_sz;
+ ei.type = E820_RAM;
+ add_e820_entry(params, &ei);
+
+ /* Add ACPI tables */
+ cmd.type = E820_ACPI;
+ flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd,
+ memmap_entry_callback);
+
+ /* Add ACPI Non-volatile Storage */
+ cmd.type = E820_NVS;
+ walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd,
+ memmap_entry_callback);
+
+ /* Add crashk_low_res region */
+ if (crashk_low_res.end) {
+ ei.addr = crashk_low_res.start;
+ ei.size = crashk_low_res.end - crashk_low_res.start + 1;
+ ei.type = E820_RAM;
+ add_e820_entry(params, &ei);
+ }
+
+ /* Exclude some ranges from crashk_res and add rest to memmap */
+ ret = memmap_exclude_ranges(image, cmem, crashk_res.start,
+ crashk_res.end);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < cmem->nr_ranges; i++) {
+ ei.size = cmem->ranges[i].end - cmem->ranges[i].start + 1;
+
+ /* If entry is less than a page, skip it */
+ if (ei.size < PAGE_SIZE)
+ continue;
+ ei.addr = cmem->ranges[i].start;
+ ei.type = E820_RAM;
+ add_e820_entry(params, &ei);
+ }
+
+out:
+ vfree(cmem);
+ return ret;
+}
+
+static int determine_backup_region(u64 start, u64 end, void *arg)
+{
+ struct kimage *image = arg;
+
+ image->arch.backup_src_start = start;
+ image->arch.backup_src_sz = end - start + 1;
+
+ /* Expecting only one range for backup region */
+ return 1;
+}
+
+int crash_load_segments(struct kimage *image)
+{
+ unsigned long src_start, src_sz, elf_sz;
+ void *elf_addr;
+ int ret;
+
+ /*
+ * Determine and load a segment for backup area. First 640K RAM
+ * region is backup source
+ */
+
+ ret = walk_system_ram_res(KEXEC_BACKUP_SRC_START, KEXEC_BACKUP_SRC_END,
+ image, determine_backup_region);
+
+ /* Zero or postive return values are ok */
+ if (ret < 0)
+ return ret;
+
+ src_start = image->arch.backup_src_start;
+ src_sz = image->arch.backup_src_sz;
+
+ /* Add backup segment. */
+ if (src_sz) {
+ /*
+ * Ideally there is no source for backup segment. This is
+ * copied in purgatory after crash. Just add a zero filled
+ * segment for now to make sure checksum logic works fine.
+ */
+ ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
+ sizeof(crash_zero_bytes), src_sz,
+ PAGE_SIZE, 0, -1, 0,
+ &image->arch.backup_load_addr);
+ if (ret)
+ return ret;
+ pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n",
+ image->arch.backup_load_addr, src_start, src_sz);
+ }
+
+ /* Prepare elf headers and add a segment */
+ ret = prepare_elf_headers(image, &elf_addr, &elf_sz);
+ if (ret)
+ return ret;
+
+ image->arch.elf_headers = elf_addr;
+ image->arch.elf_headers_sz = elf_sz;
+
+ ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
+ ELF_CORE_HEADER_ALIGN, 0, -1, 0,
+ &image->arch.elf_load_addr);
+ if (ret) {
+ vfree((void *)image->arch.elf_headers);
+ return ret;
+ }
+ pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ image->arch.elf_load_addr, elf_sz, elf_sz);
+
+ return ret;
+}
+
+#endif /* CONFIG_X86_64 */
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 7db54b5d5f86..3d3503351242 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -21,6 +21,7 @@
#include <asm/apic.h>
#include <asm/pci_x86.h>
#include <asm/setup.h>
+#include <asm/i8259.h>
__initdata u64 initial_dtb;
char __initdata cmd_line[COMMAND_LINE_SIZE];
@@ -165,82 +166,6 @@ static void __init dtb_lapic_setup(void)
#ifdef CONFIG_X86_IO_APIC
static unsigned int ioapic_id;
-static void __init dtb_add_ioapic(struct device_node *dn)
-{
- struct resource r;
- int ret;
-
- ret = of_address_to_resource(dn, 0, &r);
- if (ret) {
- printk(KERN_ERR "Can't obtain address from node %s.\n",
- dn->full_name);
- return;
- }
- mp_register_ioapic(++ioapic_id, r.start, gsi_top);
-}
-
-static void __init dtb_ioapic_setup(void)
-{
- struct device_node *dn;
-
- for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
- dtb_add_ioapic(dn);
-
- if (nr_ioapics) {
- of_ioapic = 1;
- return;
- }
- printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
-}
-#else
-static void __init dtb_ioapic_setup(void) {}
-#endif
-
-static void __init dtb_apic_setup(void)
-{
- dtb_lapic_setup();
- dtb_ioapic_setup();
-}
-
-#ifdef CONFIG_OF_FLATTREE
-static void __init x86_flattree_get_config(void)
-{
- u32 size, map_len;
- void *dt;
-
- if (!initial_dtb)
- return;
-
- map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
-
- initial_boot_params = dt = early_memremap(initial_dtb, map_len);
- size = of_get_flat_dt_size();
- if (map_len < size) {
- early_iounmap(dt, map_len);
- initial_boot_params = dt = early_memremap(initial_dtb, size);
- map_len = size;
- }
-
- unflatten_and_copy_device_tree();
- early_iounmap(dt, map_len);
-}
-#else
-static inline void x86_flattree_get_config(void) { }
-#endif
-
-void __init x86_dtb_init(void)
-{
- x86_flattree_get_config();
-
- if (!of_have_populated_dt())
- return;
-
- dtb_setup_hpet();
- dtb_apic_setup();
-}
-
-#ifdef CONFIG_X86_IO_APIC
-
struct of_ioapic_type {
u32 out_type;
u32 trigger;
@@ -276,10 +201,8 @@ static int ioapic_xlate(struct irq_domain *domain,
const u32 *intspec, u32 intsize,
irq_hw_number_t *out_hwirq, u32 *out_type)
{
- struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
- u32 line, idx;
- int rc;
+ u32 line, idx, gsi;
if (WARN_ON(intsize < 2))
return -EINVAL;
@@ -291,13 +214,10 @@ static int ioapic_xlate(struct irq_domain *domain,
it = &of_ioapic_type[intspec[1]];
- idx = (u32) domain->host_data;
- set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
-
- rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
- cpu_to_node(0), &attr);
- if (rc)
- return rc;
+ idx = (u32)(long)domain->host_data;
+ gsi = mp_pin_to_gsi(idx, line);
+ if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
+ return -EBUSY;
*out_hwirq = line;
*out_type = it->out_type;
@@ -305,81 +225,86 @@ static int ioapic_xlate(struct irq_domain *domain,
}
const struct irq_domain_ops ioapic_irq_domain_ops = {
+ .map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
.xlate = ioapic_xlate,
};
-static void dt_add_ioapic_domain(unsigned int ioapic_num,
- struct device_node *np)
+static void __init dtb_add_ioapic(struct device_node *dn)
{
- struct irq_domain *id;
- struct mp_ioapic_gsi *gsi_cfg;
+ struct resource r;
int ret;
- int num;
-
- gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
- num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
-
- id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
- (void *)ioapic_num);
- BUG_ON(!id);
- if (gsi_cfg->gsi_base == 0) {
- /*
- * The first NR_IRQS_LEGACY irq descs are allocated in
- * early_irq_init() and need just a mapping. The
- * remaining irqs need both. All of them are preallocated
- * and assigned so we can keep the 1:1 mapping which the ioapic
- * is having.
- */
- irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
-
- if (num > NR_IRQS_LEGACY) {
- ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
- NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
- if (ret)
- pr_err("Error creating mapping for the "
- "remaining IRQs: %d\n", ret);
- }
- irq_set_default_host(id);
- } else {
- ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
- if (ret)
- pr_err("Error creating IRQ mapping: %d\n", ret);
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_DYNAMIC,
+ .ops = &ioapic_irq_domain_ops,
+ .dev = dn,
+ };
+
+ ret = of_address_to_resource(dn, 0, &r);
+ if (ret) {
+ printk(KERN_ERR "Can't obtain address from node %s.\n",
+ dn->full_name);
+ return;
}
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
}
-static void __init ioapic_add_ofnode(struct device_node *np)
+static void __init dtb_ioapic_setup(void)
{
- struct resource r;
- int i, ret;
+ struct device_node *dn;
- ret = of_address_to_resource(np, 0, &r);
- if (ret) {
- printk(KERN_ERR "Failed to obtain address for %s\n",
- np->full_name);
+ for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+ dtb_add_ioapic(dn);
+
+ if (nr_ioapics) {
+ of_ioapic = 1;
return;
}
+ printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
- for (i = 0; i < nr_ioapics; i++) {
- if (r.start == mpc_ioapic_addr(i)) {
- dt_add_ioapic_domain(i, np);
- return;
- }
- }
- printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+static void __init dtb_apic_setup(void)
+{
+ dtb_lapic_setup();
+ dtb_ioapic_setup();
}
-void __init x86_add_irq_domains(void)
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
{
- struct device_node *dp;
+ u32 size, map_len;
+ void *dt;
- if (!of_have_populated_dt())
+ if (!initial_dtb)
return;
- for_each_node_with_property(dp, "interrupt-controller") {
- if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
- ioapic_add_ofnode(dp);
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
+
+ initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+ size = of_get_flat_dt_size();
+ if (map_len < size) {
+ early_iounmap(dt, map_len);
+ initial_boot_params = dt = early_memremap(initial_dtb, size);
+ map_len = size;
}
+
+ unflatten_and_copy_device_tree();
+ early_iounmap(dt, map_len);
}
#else
-void __init x86_add_irq_domains(void) { }
+static inline void x86_flattree_get_config(void) { }
#endif
+
+void __init x86_dtb_init(void)
+{
+ x86_flattree_get_config();
+
+ if (!of_have_populated_dt())
+ return;
+
+ dtb_setup_hpet();
+ dtb_apic_setup();
+}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 0d0c9d4ab6d5..47c410d99f5d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1059,9 +1059,6 @@ ENTRY(mcount)
END(mcount)
ENTRY(ftrace_caller)
- cmpl $0, function_trace_stop
- jne ftrace_stub
-
pushl %eax
pushl %ecx
pushl %edx
@@ -1093,8 +1090,6 @@ END(ftrace_caller)
ENTRY(ftrace_regs_caller)
pushf /* push flags before compare (in cs location) */
- cmpl $0, function_trace_stop
- jne ftrace_restore_flags
/*
* i386 does not save SS and ESP when coming from kernel.
@@ -1153,7 +1148,6 @@ GLOBAL(ftrace_regs_call)
popf /* Pop flags at end (no addl to corrupt flags) */
jmp ftrace_ret
-ftrace_restore_flags:
popf
jmp ftrace_stub
#else /* ! CONFIG_DYNAMIC_FTRACE */
@@ -1162,9 +1156,6 @@ ENTRY(mcount)
cmpl $__PAGE_OFFSET, %esp
jb ftrace_stub /* Paging not enabled yet? */
- cmpl $0, function_trace_stop
- jne ftrace_stub
-
cmpl $ftrace_stub, ftrace_trace_function
jnz trace
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index c844f0816ab8..2fac1343a90b 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -207,7 +207,6 @@ ENDPROC(native_usergs_sysret64)
*/
.macro XCPT_FRAME start=1 offset=0
INTR_FRAME \start, RIP+\offset-ORIG_RAX
- /*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
.endm
/*
@@ -287,21 +286,21 @@ ENDPROC(native_usergs_sysret64)
ENTRY(save_paranoid)
XCPT_FRAME 1 RDI+8
cld
- movq_cfi rdi, RDI+8
- movq_cfi rsi, RSI+8
+ movq %rdi, RDI+8(%rsp)
+ movq %rsi, RSI+8(%rsp)
movq_cfi rdx, RDX+8
movq_cfi rcx, RCX+8
movq_cfi rax, RAX+8
- movq_cfi r8, R8+8
- movq_cfi r9, R9+8
- movq_cfi r10, R10+8
- movq_cfi r11, R11+8
+ movq %r8, R8+8(%rsp)
+ movq %r9, R9+8(%rsp)
+ movq %r10, R10+8(%rsp)
+ movq %r11, R11+8(%rsp)
movq_cfi rbx, RBX+8
- movq_cfi rbp, RBP+8
- movq_cfi r12, R12+8
- movq_cfi r13, R13+8
- movq_cfi r14, R14+8
- movq_cfi r15, R15+8
+ movq %rbp, RBP+8(%rsp)
+ movq %r12, R12+8(%rsp)
+ movq %r13, R13+8(%rsp)
+ movq %r14, R14+8(%rsp)
+ movq %r15, R15+8(%rsp)
movl $1,%ebx
movl $MSR_GS_BASE,%ecx
rdmsr
@@ -1387,21 +1386,21 @@ ENTRY(error_entry)
CFI_ADJUST_CFA_OFFSET 15*8
/* oldrax contains error code */
cld
- movq_cfi rdi, RDI+8
- movq_cfi rsi, RSI+8
- movq_cfi rdx, RDX+8
- movq_cfi rcx, RCX+8
- movq_cfi rax, RAX+8
- movq_cfi r8, R8+8
- movq_cfi r9, R9+8
- movq_cfi r10, R10+8
- movq_cfi r11, R11+8
+ movq %rdi, RDI+8(%rsp)
+ movq %rsi, RSI+8(%rsp)
+ movq %rdx, RDX+8(%rsp)
+ movq %rcx, RCX+8(%rsp)
+ movq %rax, RAX+8(%rsp)
+ movq %r8, R8+8(%rsp)
+ movq %r9, R9+8(%rsp)
+ movq %r10, R10+8(%rsp)
+ movq %r11, R11+8(%rsp)
movq_cfi rbx, RBX+8
- movq_cfi rbp, RBP+8
- movq_cfi r12, R12+8
- movq_cfi r13, R13+8
- movq_cfi r14, R14+8
- movq_cfi r15, R15+8
+ movq %rbp, RBP+8(%rsp)
+ movq %r12, R12+8(%rsp)
+ movq %r13, R13+8(%rsp)
+ movq %r14, R14+8(%rsp)
+ movq %r15, R15+8(%rsp)
xorl %ebx,%ebx
testl $3,CS+8(%rsp)
je error_kernelspace
@@ -1419,6 +1418,7 @@ error_sti:
* compat mode. Check for these here too.
*/
error_kernelspace:
+ CFI_REL_OFFSET rcx, RCX+8
incl %ebx
leaq native_irq_return_iret(%rip),%rcx
cmpq %rcx,RIP+8(%rsp)
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index cbc4a91b131e..3386dc9aa333 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -703,6 +703,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
unsigned long return_hooker = (unsigned long)
&return_to_handler;
+ if (unlikely(ftrace_graph_is_dead()))
+ return;
+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index d5dd80814419..a9a4229f6161 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -375,7 +375,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
/*
* These bits must be zero.
*/
- xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+ memset(xsave_hdr->reserved, 0, 48);
return ret;
}
diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c
index d30acdc1229d..9030e83db6ee 100644
--- a/arch/x86/kernel/iosf_mbi.c
+++ b/arch/x86/kernel/iosf_mbi.c
@@ -202,7 +202,7 @@ static int iosf_mbi_probe(struct pci_dev *pdev,
return 0;
}
-static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
+static const struct pci_device_id iosf_mbi_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) },
{ 0, },
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 7f50156542fb..1e6cff5814fa 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -78,7 +78,7 @@ void __init init_ISA_irqs(void)
#endif
legacy_pic->init(0);
- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
}
@@ -87,12 +87,6 @@ void __init init_IRQ(void)
int i;
/*
- * We probably need a better place for this, but it works for
- * now ...
- */
- x86_add_irq_domains();
-
- /*
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
* then this configuration will likely be static after the boot. If
@@ -100,7 +94,7 @@ void __init init_IRQ(void)
* then this vector space can be freed and re-used dynamically as the
* irq's migrate etc.
*/
- for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+ for (i = 0; i < nr_legacy_irqs(); i++)
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
x86_init.irqs.intr_init();
@@ -121,7 +115,7 @@ void setup_vector_irq(int cpu)
* legacy PIC, for the new cpu that is coming online, setup the static
* legacy vector to irq mapping:
*/
- for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
#endif
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
new file mode 100644
index 000000000000..9642b9b33655
--- /dev/null
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -0,0 +1,553 @@
+/*
+ * Kexec bzImage loader
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ * Authors:
+ * Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#define pr_fmt(fmt) "kexec-bzImage64: " fmt
+
+#include <linux/string.h>
+#include <linux/printk.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/efi.h>
+#include <linux/verify_pefile.h>
+#include <keys/system_keyring.h>
+
+#include <asm/bootparam.h>
+#include <asm/setup.h>
+#include <asm/crash.h>
+#include <asm/efi.h>
+
+#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
+
+/*
+ * Defines lowest physical address for various segments. Not sure where
+ * exactly these limits came from. Current bzimage64 loader in kexec-tools
+ * uses these so I am retaining it. It can be changed over time as we gain
+ * more insight.
+ */
+#define MIN_PURGATORY_ADDR 0x3000
+#define MIN_BOOTPARAM_ADDR 0x3000
+#define MIN_KERNEL_LOAD_ADDR 0x100000
+#define MIN_INITRD_LOAD_ADDR 0x1000000
+
+/*
+ * This is a place holder for all boot loader specific data structure which
+ * gets allocated in one call but gets freed much later during cleanup
+ * time. Right now there is only one field but it can grow as need be.
+ */
+struct bzimage64_data {
+ /*
+ * Temporary buffer to hold bootparams buffer. This should be
+ * freed once the bootparam segment has been loaded.
+ */
+ void *bootparams_buf;
+};
+
+static int setup_initrd(struct boot_params *params,
+ unsigned long initrd_load_addr, unsigned long initrd_len)
+{
+ params->hdr.ramdisk_image = initrd_load_addr & 0xffffffffUL;
+ params->hdr.ramdisk_size = initrd_len & 0xffffffffUL;
+
+ params->ext_ramdisk_image = initrd_load_addr >> 32;
+ params->ext_ramdisk_size = initrd_len >> 32;
+
+ return 0;
+}
+
+static int setup_cmdline(struct kimage *image, struct boot_params *params,
+ unsigned long bootparams_load_addr,
+ unsigned long cmdline_offset, char *cmdline,
+ unsigned long cmdline_len)
+{
+ char *cmdline_ptr = ((char *)params) + cmdline_offset;
+ unsigned long cmdline_ptr_phys, len;
+ uint32_t cmdline_low_32, cmdline_ext_32;
+
+ memcpy(cmdline_ptr, cmdline, cmdline_len);
+ if (image->type == KEXEC_TYPE_CRASH) {
+ len = sprintf(cmdline_ptr + cmdline_len - 1,
+ " elfcorehdr=0x%lx", image->arch.elf_load_addr);
+ cmdline_len += len;
+ }
+ cmdline_ptr[cmdline_len - 1] = '\0';
+
+ pr_debug("Final command line is: %s\n", cmdline_ptr);
+ cmdline_ptr_phys = bootparams_load_addr + cmdline_offset;
+ cmdline_low_32 = cmdline_ptr_phys & 0xffffffffUL;
+ cmdline_ext_32 = cmdline_ptr_phys >> 32;
+
+ params->hdr.cmd_line_ptr = cmdline_low_32;
+ if (cmdline_ext_32)
+ params->ext_cmd_line_ptr = cmdline_ext_32;
+
+ return 0;
+}
+
+static int setup_e820_entries(struct boot_params *params)
+{
+ unsigned int nr_e820_entries;
+
+ nr_e820_entries = e820_saved.nr_map;
+
+ /* TODO: Pass entries more than E820MAX in bootparams setup data */
+ if (nr_e820_entries > E820MAX)
+ nr_e820_entries = E820MAX;
+
+ params->e820_entries = nr_e820_entries;
+ memcpy(&params->e820_map, &e820_saved.map,
+ nr_e820_entries * sizeof(struct e820entry));
+
+ return 0;
+}
+
+#ifdef CONFIG_EFI
+static int setup_efi_info_memmap(struct boot_params *params,
+ unsigned long params_load_addr,
+ unsigned int efi_map_offset,
+ unsigned int efi_map_sz)
+{
+ void *efi_map = (void *)params + efi_map_offset;
+ unsigned long efi_map_phys_addr = params_load_addr + efi_map_offset;
+ struct efi_info *ei = &params->efi_info;
+
+ if (!efi_map_sz)
+ return 0;
+
+ efi_runtime_map_copy(efi_map, efi_map_sz);
+
+ ei->efi_memmap = efi_map_phys_addr & 0xffffffff;
+ ei->efi_memmap_hi = efi_map_phys_addr >> 32;
+ ei->efi_memmap_size = efi_map_sz;
+
+ return 0;
+}
+
+static int
+prepare_add_efi_setup_data(struct boot_params *params,
+ unsigned long params_load_addr,
+ unsigned int efi_setup_data_offset)
+{
+ unsigned long setup_data_phys;
+ struct setup_data *sd = (void *)params + efi_setup_data_offset;
+ struct efi_setup_data *esd = (void *)sd + sizeof(struct setup_data);
+
+ esd->fw_vendor = efi.fw_vendor;
+ esd->runtime = efi.runtime;
+ esd->tables = efi.config_table;
+ esd->smbios = efi.smbios;
+
+ sd->type = SETUP_EFI;
+ sd->len = sizeof(struct efi_setup_data);
+
+ /* Add setup data */
+ setup_data_phys = params_load_addr + efi_setup_data_offset;
+ sd->next = params->hdr.setup_data;
+ params->hdr.setup_data = setup_data_phys;
+
+ return 0;
+}
+
+static int
+setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
+ unsigned int efi_map_offset, unsigned int efi_map_sz,
+ unsigned int efi_setup_data_offset)
+{
+ struct efi_info *current_ei = &boot_params.efi_info;
+ struct efi_info *ei = &params->efi_info;
+
+ if (!current_ei->efi_memmap_size)
+ return 0;
+
+ /*
+ * If 1:1 mapping is not enabled, second kernel can not setup EFI
+ * and use EFI run time services. User space will have to pass
+ * acpi_rsdp=<addr> on kernel command line to make second kernel boot
+ * without efi.
+ */
+ if (efi_enabled(EFI_OLD_MEMMAP))
+ return 0;
+
+ ei->efi_loader_signature = current_ei->efi_loader_signature;
+ ei->efi_systab = current_ei->efi_systab;
+ ei->efi_systab_hi = current_ei->efi_systab_hi;
+
+ ei->efi_memdesc_version = current_ei->efi_memdesc_version;
+ ei->efi_memdesc_size = efi_get_runtime_map_desc_size();
+
+ setup_efi_info_memmap(params, params_load_addr, efi_map_offset,
+ efi_map_sz);
+ prepare_add_efi_setup_data(params, params_load_addr,
+ efi_setup_data_offset);
+ return 0;
+}
+#endif /* CONFIG_EFI */
+
+static int
+setup_boot_parameters(struct kimage *image, struct boot_params *params,
+ unsigned long params_load_addr,
+ unsigned int efi_map_offset, unsigned int efi_map_sz,
+ unsigned int efi_setup_data_offset)
+{
+ unsigned int nr_e820_entries;
+ unsigned long long mem_k, start, end;
+ int i, ret = 0;
+
+ /* Get subarch from existing bootparams */
+ params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch;
+
+ /* Copying screen_info will do? */
+ memcpy(&params->screen_info, &boot_params.screen_info,
+ sizeof(struct screen_info));
+
+ /* Fill in memsize later */
+ params->screen_info.ext_mem_k = 0;
+ params->alt_mem_k = 0;
+
+ /* Default APM info */
+ memset(&params->apm_bios_info, 0, sizeof(params->apm_bios_info));
+
+ /* Default drive info */
+ memset(&params->hd0_info, 0, sizeof(params->hd0_info));
+ memset(&params->hd1_info, 0, sizeof(params->hd1_info));
+
+ /* Default sysdesc table */
+ params->sys_desc_table.length = 0;
+
+ if (image->type == KEXEC_TYPE_CRASH) {
+ ret = crash_setup_memmap_entries(image, params);
+ if (ret)
+ return ret;
+ } else
+ setup_e820_entries(params);
+
+ nr_e820_entries = params->e820_entries;
+
+ for (i = 0; i < nr_e820_entries; i++) {
+ if (params->e820_map[i].type != E820_RAM)
+ continue;
+ start = params->e820_map[i].addr;
+ end = params->e820_map[i].addr + params->e820_map[i].size - 1;
+
+ if ((start <= 0x100000) && end > 0x100000) {
+ mem_k = (end >> 10) - (0x100000 >> 10);
+ params->screen_info.ext_mem_k = mem_k;
+ params->alt_mem_k = mem_k;
+ if (mem_k > 0xfc00)
+ params->screen_info.ext_mem_k = 0xfc00; /* 64M*/
+ if (mem_k > 0xffffffff)
+ params->alt_mem_k = 0xffffffff;
+ }
+ }
+
+#ifdef CONFIG_EFI
+ /* Setup EFI state */
+ setup_efi_state(params, params_load_addr, efi_map_offset, efi_map_sz,
+ efi_setup_data_offset);
+#endif
+
+ /* Setup EDD info */
+ memcpy(params->eddbuf, boot_params.eddbuf,
+ EDDMAXNR * sizeof(struct edd_info));
+ params->eddbuf_entries = boot_params.eddbuf_entries;
+
+ memcpy(params->edd_mbr_sig_buffer, boot_params.edd_mbr_sig_buffer,
+ EDD_MBR_SIG_MAX * sizeof(unsigned int));
+
+ return ret;
+}
+
+int bzImage64_probe(const char *buf, unsigned long len)
+{
+ int ret = -ENOEXEC;
+ struct setup_header *header;
+
+ /* kernel should be atleast two sectors long */
+ if (len < 2 * 512) {
+ pr_err("File is too short to be a bzImage\n");
+ return ret;
+ }
+
+ header = (struct setup_header *)(buf + offsetof(struct boot_params, hdr));
+ if (memcmp((char *)&header->header, "HdrS", 4) != 0) {
+ pr_err("Not a bzImage\n");
+ return ret;
+ }
+
+ if (header->boot_flag != 0xAA55) {
+ pr_err("No x86 boot sector present\n");
+ return ret;
+ }
+
+ if (header->version < 0x020C) {
+ pr_err("Must be at least protocol version 2.12\n");
+ return ret;
+ }
+
+ if (!(header->loadflags & LOADED_HIGH)) {
+ pr_err("zImage not a bzImage\n");
+ return ret;
+ }
+
+ if (!(header->xloadflags & XLF_KERNEL_64)) {
+ pr_err("Not a bzImage64. XLF_KERNEL_64 is not set.\n");
+ return ret;
+ }
+
+ if (!(header->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)) {
+ pr_err("XLF_CAN_BE_LOADED_ABOVE_4G is not set.\n");
+ return ret;
+ }
+
+ /*
+ * Can't handle 32bit EFI as it does not allow loading kernel
+ * above 4G. This should be handled by 32bit bzImage loader
+ */
+ if (efi_enabled(EFI_RUNTIME_SERVICES) && !efi_enabled(EFI_64BIT)) {
+ pr_debug("EFI is 32 bit. Can't load kernel above 4G.\n");
+ return ret;
+ }
+
+ /* I've got a bzImage */
+ pr_debug("It's a relocatable bzImage64\n");
+ ret = 0;
+
+ return ret;
+}
+
+void *bzImage64_load(struct kimage *image, char *kernel,
+ unsigned long kernel_len, char *initrd,
+ unsigned long initrd_len, char *cmdline,
+ unsigned long cmdline_len)
+{
+
+ struct setup_header *header;
+ int setup_sects, kern16_size, ret = 0;
+ unsigned long setup_header_size, params_cmdline_sz, params_misc_sz;
+ struct boot_params *params;
+ unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
+ unsigned long purgatory_load_addr;
+ unsigned long kernel_bufsz, kernel_memsz, kernel_align;
+ char *kernel_buf;
+ struct bzimage64_data *ldata;
+ struct kexec_entry64_regs regs64;
+ void *stack;
+ unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr);
+ unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
+
+ header = (struct setup_header *)(kernel + setup_hdr_offset);
+ setup_sects = header->setup_sects;
+ if (setup_sects == 0)
+ setup_sects = 4;
+
+ kern16_size = (setup_sects + 1) * 512;
+ if (kernel_len < kern16_size) {
+ pr_err("bzImage truncated\n");
+ return ERR_PTR(-ENOEXEC);
+ }
+
+ if (cmdline_len > header->cmdline_size) {
+ pr_err("Kernel command line too long\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+ * In case of crash dump, we will append elfcorehdr=<addr> to
+ * command line. Make sure it does not overflow
+ */
+ if (cmdline_len + MAX_ELFCOREHDR_STR_LEN > header->cmdline_size) {
+ pr_debug("Appending elfcorehdr=<addr> to command line exceeds maximum allowed length\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Allocate and load backup region */
+ if (image->type == KEXEC_TYPE_CRASH) {
+ ret = crash_load_segments(image);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ /*
+ * Load purgatory. For 64bit entry point, purgatory code can be
+ * anywhere.
+ */
+ ret = kexec_load_purgatory(image, MIN_PURGATORY_ADDR, ULONG_MAX, 1,
+ &purgatory_load_addr);
+ if (ret) {
+ pr_err("Loading purgatory failed\n");
+ return ERR_PTR(ret);
+ }
+
+ pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+
+
+ /*
+ * Load Bootparams and cmdline and space for efi stuff.
+ *
+ * Allocate memory together for multiple data structures so
+ * that they all can go in single area/segment and we don't
+ * have to create separate segment for each. Keeps things
+ * little bit simple
+ */
+ efi_map_sz = efi_get_runtime_map_size();
+ efi_map_sz = ALIGN(efi_map_sz, 16);
+ params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
+ MAX_ELFCOREHDR_STR_LEN;
+ params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
+ params_misc_sz = params_cmdline_sz + efi_map_sz +
+ sizeof(struct setup_data) +
+ sizeof(struct efi_setup_data);
+
+ params = kzalloc(params_misc_sz, GFP_KERNEL);
+ if (!params)
+ return ERR_PTR(-ENOMEM);
+ efi_map_offset = params_cmdline_sz;
+ efi_setup_data_offset = efi_map_offset + efi_map_sz;
+
+ /* Copy setup header onto bootparams. Documentation/x86/boot.txt */
+ setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset;
+
+ /* Is there a limit on setup header size? */
+ memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size);
+
+ ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
+ params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
+ ULONG_MAX, 1, &bootparam_load_addr);
+ if (ret)
+ goto out_free_params;
+ pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ bootparam_load_addr, params_misc_sz, params_misc_sz);
+
+ /* Load kernel */
+ kernel_buf = kernel + kern16_size;
+ kernel_bufsz = kernel_len - kern16_size;
+ kernel_memsz = PAGE_ALIGN(header->init_size);
+ kernel_align = header->kernel_alignment;
+
+ ret = kexec_add_buffer(image, kernel_buf,
+ kernel_bufsz, kernel_memsz, kernel_align,
+ MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
+ &kernel_load_addr);
+ if (ret)
+ goto out_free_params;
+
+ pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ kernel_load_addr, kernel_memsz, kernel_memsz);
+
+ /* Load initrd high */
+ if (initrd) {
+ ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
+ PAGE_SIZE, MIN_INITRD_LOAD_ADDR,
+ ULONG_MAX, 1, &initrd_load_addr);
+ if (ret)
+ goto out_free_params;
+
+ pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+ initrd_load_addr, initrd_len, initrd_len);
+
+ setup_initrd(params, initrd_load_addr, initrd_len);
+ }
+
+ setup_cmdline(image, params, bootparam_load_addr,
+ sizeof(struct boot_params), cmdline, cmdline_len);
+
+ /* bootloader info. Do we need a separate ID for kexec kernel loader? */
+ params->hdr.type_of_loader = 0x0D << 4;
+ params->hdr.loadflags = 0;
+
+ /* Setup purgatory regs for entry */
+ ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", &regs64,
+ sizeof(regs64), 1);
+ if (ret)
+ goto out_free_params;
+
+ regs64.rbx = 0; /* Bootstrap Processor */
+ regs64.rsi = bootparam_load_addr;
+ regs64.rip = kernel_load_addr + 0x200;
+ stack = kexec_purgatory_get_symbol_addr(image, "stack_end");
+ if (IS_ERR(stack)) {
+ pr_err("Could not find address of symbol stack_end\n");
+ ret = -EINVAL;
+ goto out_free_params;
+ }
+
+ regs64.rsp = (unsigned long)stack;
+ ret = kexec_purgatory_get_set_symbol(image, "entry64_regs", &regs64,
+ sizeof(regs64), 0);
+ if (ret)
+ goto out_free_params;
+
+ ret = setup_boot_parameters(image, params, bootparam_load_addr,
+ efi_map_offset, efi_map_sz,
+ efi_setup_data_offset);
+ if (ret)
+ goto out_free_params;
+
+ /* Allocate loader specific data */
+ ldata = kzalloc(sizeof(struct bzimage64_data), GFP_KERNEL);
+ if (!ldata) {
+ ret = -ENOMEM;
+ goto out_free_params;
+ }
+
+ /*
+ * Store pointer to params so that it could be freed after loading
+ * params segment has been loaded and contents have been copied
+ * somewhere else.
+ */
+ ldata->bootparams_buf = params;
+ return ldata;
+
+out_free_params:
+ kfree(params);
+ return ERR_PTR(ret);
+}
+
+/* This cleanup function is called after various segments have been loaded */
+int bzImage64_cleanup(void *loader_data)
+{
+ struct bzimage64_data *ldata = loader_data;
+
+ if (!ldata)
+ return 0;
+
+ kfree(ldata->bootparams_buf);
+ ldata->bootparams_buf = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
+int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
+{
+ bool trusted;
+ int ret;
+
+ ret = verify_pefile_signature(kernel, kernel_len,
+ system_trusted_keyring, &trusted);
+ if (ret < 0)
+ return ret;
+ if (!trusted)
+ return -EKEYREJECTED;
+ return 0;
+}
+#endif
+
+struct kexec_file_ops kexec_bzImage64_ops = {
+ .probe = bzImage64_probe,
+ .load = bzImage64_load,
+ .cleanup = bzImage64_cleanup,
+#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
+ .verify_sig = bzImage64_verify_sig,
+#endif
+};
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 679cef0791cd..8b04018e5d1f 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -6,6 +6,8 @@
* Version 2. See the file COPYING for more details.
*/
+#define pr_fmt(fmt) "kexec: " fmt
+
#include <linux/mm.h>
#include <linux/kexec.h>
#include <linux/string.h>
@@ -21,6 +23,11 @@
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/debugreg.h>
+#include <asm/kexec-bzimage64.h>
+
+static struct kexec_file_ops *kexec_file_loaders[] = {
+ &kexec_bzImage64_ops,
+};
static void free_transition_pgtable(struct kimage *image)
{
@@ -171,6 +178,38 @@ static void load_segments(void)
);
}
+/* Update purgatory as needed after various image segments have been prepared */
+static int arch_update_purgatory(struct kimage *image)
+{
+ int ret = 0;
+
+ if (!image->file_mode)
+ return 0;
+
+ /* Setup copying of backup region */
+ if (image->type == KEXEC_TYPE_CRASH) {
+ ret = kexec_purgatory_get_set_symbol(image, "backup_dest",
+ &image->arch.backup_load_addr,
+ sizeof(image->arch.backup_load_addr), 0);
+ if (ret)
+ return ret;
+
+ ret = kexec_purgatory_get_set_symbol(image, "backup_src",
+ &image->arch.backup_src_start,
+ sizeof(image->arch.backup_src_start), 0);
+ if (ret)
+ return ret;
+
+ ret = kexec_purgatory_get_set_symbol(image, "backup_sz",
+ &image->arch.backup_src_sz,
+ sizeof(image->arch.backup_src_sz), 0);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
int machine_kexec_prepare(struct kimage *image)
{
unsigned long start_pgtable;
@@ -184,6 +223,11 @@ int machine_kexec_prepare(struct kimage *image)
if (result)
return result;
+ /* update purgatory as needed */
+ result = arch_update_purgatory(image);
+ if (result)
+ return result;
+
return 0;
}
@@ -283,3 +327,198 @@ void arch_crash_save_vmcoreinfo(void)
(unsigned long)&_text - __START_KERNEL);
}
+/* arch-dependent functionality related to kexec file-based syscall */
+
+int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
+ unsigned long buf_len)
+{
+ int i, ret = -ENOEXEC;
+ struct kexec_file_ops *fops;
+
+ for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) {
+ fops = kexec_file_loaders[i];
+ if (!fops || !fops->probe)
+ continue;
+
+ ret = fops->probe(buf, buf_len);
+ if (!ret) {
+ image->fops = fops;
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+void *arch_kexec_kernel_image_load(struct kimage *image)
+{
+ vfree(image->arch.elf_headers);
+ image->arch.elf_headers = NULL;
+
+ if (!image->fops || !image->fops->load)
+ return ERR_PTR(-ENOEXEC);
+
+ return image->fops->load(image, image->kernel_buf,
+ image->kernel_buf_len, image->initrd_buf,
+ image->initrd_buf_len, image->cmdline_buf,
+ image->cmdline_buf_len);
+}
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+ if (!image->fops || !image->fops->cleanup)
+ return 0;
+
+ return image->fops->cleanup(image->image_loader_data);
+}
+
+int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel,
+ unsigned long kernel_len)
+{
+ if (!image->fops || !image->fops->verify_sig) {
+ pr_debug("kernel loader does not support signature verification.");
+ return -EKEYREJECTED;
+ }
+
+ return image->fops->verify_sig(kernel, kernel_len);
+}
+
+/*
+ * Apply purgatory relocations.
+ *
+ * ehdr: Pointer to elf headers
+ * sechdrs: Pointer to section headers.
+ * relsec: section index of SHT_RELA section.
+ *
+ * TODO: Some of the code belongs to generic code. Move that in kexec.c.
+ */
+int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
+ Elf64_Shdr *sechdrs, unsigned int relsec)
+{
+ unsigned int i;
+ Elf64_Rela *rel;
+ Elf64_Sym *sym;
+ void *location;
+ Elf64_Shdr *section, *symtabsec;
+ unsigned long address, sec_base, value;
+ const char *strtab, *name, *shstrtab;
+
+ /*
+ * ->sh_offset has been modified to keep the pointer to section
+ * contents in memory
+ */
+ rel = (void *)sechdrs[relsec].sh_offset;
+
+ /* Section to which relocations apply */
+ section = &sechdrs[sechdrs[relsec].sh_info];
+
+ pr_debug("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+
+ /* Associated symbol table */
+ symtabsec = &sechdrs[sechdrs[relsec].sh_link];
+
+ /* String table */
+ if (symtabsec->sh_link >= ehdr->e_shnum) {
+ /* Invalid strtab section number */
+ pr_err("Invalid string table section index %d\n",
+ symtabsec->sh_link);
+ return -ENOEXEC;
+ }
+
+ strtab = (char *)sechdrs[symtabsec->sh_link].sh_offset;
+
+ /* section header string table */
+ shstrtab = (char *)sechdrs[ehdr->e_shstrndx].sh_offset;
+
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+
+ /*
+ * rel[i].r_offset contains byte offset from beginning
+ * of section to the storage unit affected.
+ *
+ * This is location to update (->sh_offset). This is temporary
+ * buffer where section is currently loaded. This will finally
+ * be loaded to a different address later, pointed to by
+ * ->sh_addr. kexec takes care of moving it
+ * (kexec_load_segment()).
+ */
+ location = (void *)(section->sh_offset + rel[i].r_offset);
+
+ /* Final address of the location */
+ address = section->sh_addr + rel[i].r_offset;
+
+ /*
+ * rel[i].r_info contains information about symbol table index
+ * w.r.t which relocation must be made and type of relocation
+ * to apply. ELF64_R_SYM() and ELF64_R_TYPE() macros get
+ * these respectively.
+ */
+ sym = (Elf64_Sym *)symtabsec->sh_offset +
+ ELF64_R_SYM(rel[i].r_info);
+
+ if (sym->st_name)
+ name = strtab + sym->st_name;
+ else
+ name = shstrtab + sechdrs[sym->st_shndx].sh_name;
+
+ pr_debug("Symbol: %s info: %02x shndx: %02x value=%llx size: %llx\n",
+ name, sym->st_info, sym->st_shndx, sym->st_value,
+ sym->st_size);
+
+ if (sym->st_shndx == SHN_UNDEF) {
+ pr_err("Undefined symbol: %s\n", name);
+ return -ENOEXEC;
+ }
+
+ if (sym->st_shndx == SHN_COMMON) {
+ pr_err("symbol '%s' in common section\n", name);
+ return -ENOEXEC;
+ }
+
+ if (sym->st_shndx == SHN_ABS)
+ sec_base = 0;
+ else if (sym->st_shndx >= ehdr->e_shnum) {
+ pr_err("Invalid section %d for symbol %s\n",
+ sym->st_shndx, name);
+ return -ENOEXEC;
+ } else
+ sec_base = sechdrs[sym->st_shndx].sh_addr;
+
+ value = sym->st_value;
+ value += sec_base;
+ value += rel[i].r_addend;
+
+ switch (ELF64_R_TYPE(rel[i].r_info)) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_64:
+ *(u64 *)location = value;
+ break;
+ case R_X86_64_32:
+ *(u32 *)location = value;
+ if (value != *(u32 *)location)
+ goto overflow;
+ break;
+ case R_X86_64_32S:
+ *(s32 *)location = value;
+ if ((s64)value != *(s32 *)location)
+ goto overflow;
+ break;
+ case R_X86_64_PC32:
+ value -= (u64)address;
+ *(u32 *)location = value;
+ break;
+ default:
+ pr_err("Unknown rela relocation: %llu\n",
+ ELF64_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+
+overflow:
+ pr_err("Overflow in relocation type %d value 0x%lx\n",
+ (int)ELF64_R_TYPE(rel[i].r_info), value);
+ return -ENOEXEC;
+}
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S
index c050a0153168..c73aecf10d34 100644
--- a/arch/x86/kernel/mcount_64.S
+++ b/arch/x86/kernel/mcount_64.S
@@ -46,10 +46,6 @@ END(function_hook)
.endm
ENTRY(ftrace_caller)
- /* Check if tracing was disabled (quick check) */
- cmpl $0, function_trace_stop
- jne ftrace_stub
-
ftrace_caller_setup
/* regs go into 4th parameter (but make it NULL) */
movq $0, %rcx
@@ -73,10 +69,6 @@ ENTRY(ftrace_regs_caller)
/* Save the current flags before compare (in SS location)*/
pushfq
- /* Check if tracing was disabled (quick check) */
- cmpl $0, function_trace_stop
- jne ftrace_restore_flags
-
/* skip=8 to skip flags saved in SS */
ftrace_caller_setup 8
@@ -131,7 +123,7 @@ GLOBAL(ftrace_regs_call)
popfq
jmp ftrace_return
-ftrace_restore_flags:
+
popfq
jmp ftrace_stub
@@ -141,9 +133,6 @@ END(ftrace_regs_caller)
#else /* ! CONFIG_DYNAMIC_FTRACE */
ENTRY(function_hook)
- cmpl $0, function_trace_stop
- jne ftrace_stub
-
cmpq $ftrace_stub, ftrace_trace_function
jnz trace
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index d2b56489d70f..2d2a237f2c73 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/pci.h>
+#include <linux/irqdomain.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
@@ -67,7 +68,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)
boot_cpu_physical_apicid = m->apicid;
}
- printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+ pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
generic_processor_info(apicid, m->apicver);
}
@@ -87,9 +88,8 @@ static void __init MP_bus_info(struct mpc_bus *m)
#if MAX_MP_BUSSES < 256
if (m->busid >= MAX_MP_BUSSES) {
- printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
- " is too large, max. supported is %d\n",
- m->busid, str, MAX_MP_BUSSES - 1);
+ pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",
+ m->busid, str, MAX_MP_BUSSES - 1);
return;
}
#endif
@@ -110,19 +110,29 @@ static void __init MP_bus_info(struct mpc_bus *m)
mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
#endif
} else
- printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ pr_warn("Unknown bustype %s - ignoring\n", str);
}
+static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+ .unmap = mp_irqdomain_unmap,
+};
+
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_LEGACY,
+ .ops = &mp_ioapic_irqdomain_ops,
+ };
+
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);
}
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
{
- apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",
mp_irq->irqtype, mp_irq->irqflag & 3,
(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
@@ -135,8 +145,8 @@ static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
{
- apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
- " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+ apic_printk(APIC_VERBOSE,
+ "Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
m->srcbusirq, m->destapic, m->destapiclint);
}
@@ -148,34 +158,33 @@ static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
{
if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
- printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+ pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",
mpc->signature[0], mpc->signature[1],
mpc->signature[2], mpc->signature[3]);
return 0;
}
if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
- printk(KERN_ERR "MPTABLE: checksum error!\n");
+ pr_err("MPTABLE: checksum error!\n");
return 0;
}
if (mpc->spec != 0x01 && mpc->spec != 0x04) {
- printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
- mpc->spec);
+ pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);
return 0;
}
if (!mpc->lapic) {
- printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+ pr_err("MPTABLE: null local APIC address!\n");
return 0;
}
memcpy(oem, mpc->oem, 8);
oem[8] = 0;
- printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+ pr_info("MPTABLE: OEM ID: %s\n", oem);
memcpy(str, mpc->productid, 12);
str[12] = 0;
- printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ pr_info("MPTABLE: Product ID: %s\n", str);
- printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+ pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic);
return 1;
}
@@ -188,8 +197,8 @@ static void skip_entry(unsigned char **ptr, int *count, int size)
static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
{
- printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
- "type %x\n", *mpt);
+ pr_err("Your mptable is wrong, contact your HW vendor!\n");
+ pr_cont("type %x\n", *mpt);
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
1, mpc, mpc->length, 1);
}
@@ -207,9 +216,6 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
if (!smp_check_mpc(mpc, oem, str))
return 0;
-#ifdef CONFIG_X86_32
- generic_mps_oem_check(mpc, oem, str);
-#endif
/* Initialize the lapic mapping */
if (!acpi_lapic)
register_lapic_address(mpc->lapic);
@@ -259,7 +265,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
}
if (!num_processors)
- printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ pr_err("MPTABLE: no processors registered!\n");
return num_processors;
}
@@ -295,16 +301,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
* If it does, we assume it's valid.
*/
if (mpc_default_type == 5) {
- printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
- "falling back to ELCR\n");
+ pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
ELCR_trigger(13))
- printk(KERN_ERR "ELCR contains invalid data... "
- "not using ELCR\n");
+ pr_err("ELCR contains invalid data... not using ELCR\n");
else {
- printk(KERN_INFO
- "Using ELCR to identify PCI interrupts\n");
+ pr_info("Using ELCR to identify PCI interrupts\n");
ELCR_fallback = 1;
}
}
@@ -353,7 +356,7 @@ static void __init construct_ioapic_table(int mpc_default_type)
bus.busid = 0;
switch (mpc_default_type) {
default:
- printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+ pr_err("???\nUnknown standard configuration %d\n",
mpc_default_type);
/* fall through */
case 1:
@@ -462,8 +465,8 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
#ifdef CONFIG_X86_LOCAL_APIC
smp_found_config = 0;
#endif
- printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
- "... disabling SMP support. (tell your hw vendor)\n");
+ pr_err("BIOS bug, MP table errors detected!...\n");
+ pr_cont("... disabling SMP support. (tell your hw vendor)\n");
early_iounmap(mpc, size);
return -1;
}
@@ -481,8 +484,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
if (!mp_irq_entries) {
struct mpc_bus bus;
- printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
- "using default mptable. (tell your hw vendor)\n");
+ pr_err("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
bus.type = MP_BUS;
bus.busid = 0;
@@ -516,14 +518,14 @@ void __init default_get_smp_config(unsigned int early)
if (acpi_lapic && acpi_ioapic)
return;
- printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
- mpf->specification);
+ pr_info("Intel MultiProcessor Specification v1.%d\n",
+ mpf->specification);
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
if (mpf->feature2 & (1 << 7)) {
- printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
+ pr_info(" IMCR and PIC compatibility mode.\n");
pic_mode = 1;
} else {
- printk(KERN_INFO " Virtual Wire compatibility mode.\n");
+ pr_info(" Virtual Wire compatibility mode.\n");
pic_mode = 0;
}
#endif
@@ -539,8 +541,7 @@ void __init default_get_smp_config(unsigned int early)
return;
}
- printk(KERN_INFO "Default MP configuration #%d\n",
- mpf->feature1);
+ pr_info("Default MP configuration #%d\n", mpf->feature1);
construct_default_ISA_mptable(mpf->feature1);
} else if (mpf->physptr) {
@@ -550,7 +551,7 @@ void __init default_get_smp_config(unsigned int early)
BUG();
if (!early)
- printk(KERN_INFO "Processors: %d\n", num_processors);
+ pr_info("Processors: %d\n", num_processors);
/*
* Only use the first configuration found.
*/
@@ -583,10 +584,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
#endif
mpf_found = mpf;
- printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
- (unsigned long long) virt_to_phys(mpf),
- (unsigned long long) virt_to_phys(mpf) +
- sizeof(*mpf) - 1, mpf);
+ pr_info("found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
+ (unsigned long long) virt_to_phys(mpf),
+ (unsigned long long) virt_to_phys(mpf) +
+ sizeof(*mpf) - 1, mpf);
mem = virt_to_phys(mpf);
memblock_reserve(mem, sizeof(*mpf));
@@ -735,7 +736,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
int nr_m_spare = 0;
unsigned char *mpt = ((unsigned char *)mpc) + count;
- printk(KERN_INFO "mpc_length %x\n", mpc->length);
+ pr_info("mpc_length %x\n", mpc->length);
while (count < mpc->length) {
switch (*mpt) {
case MP_PROCESSOR:
@@ -862,13 +863,13 @@ static int __init update_mp_table(void)
if (!smp_check_mpc(mpc, oem, str))
return 0;
- printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
- printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+ pr_info("mpf: %llx\n", (u64)virt_to_phys(mpf));
+ pr_info("physptr: %x\n", mpf->physptr);
if (mpc_new_phys && mpc->length > mpc_new_length) {
mpc_new_phys = 0;
- printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
- mpc_new_length);
+ pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
}
if (!mpc_new_phys) {
@@ -879,10 +880,10 @@ static int __init update_mp_table(void)
mpc->checksum = 0xff;
new = mpf_checksum((unsigned char *)mpc, mpc->length);
if (old == new) {
- printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ pr_info("mpc is readonly, please try alloc_mptable instead\n");
return 0;
}
- printk(KERN_INFO "use in-position replacing\n");
+ pr_info("use in-position replacing\n");
} else {
mpf->physptr = mpc_new_phys;
mpc_new = phys_to_virt(mpc_new_phys);
@@ -892,7 +893,7 @@ static int __init update_mp_table(void)
if (mpc_new_phys - mpf->physptr) {
struct mpf_intel *mpf_new;
/* steal 16 bytes from [0, 1k) */
- printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ pr_info("mpf new: %x\n", 0x400 - 16);
mpf_new = phys_to_virt(0x400 - 16);
memcpy(mpf_new, mpf, 16);
mpf = mpf_new;
@@ -900,7 +901,7 @@ static int __init update_mp_table(void)
}
mpf->checksum = 0;
mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
- printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+ pr_info("physptr new: %x\n", mpf->physptr);
}
/*
diff --git a/arch/x86/kernel/pmc_atom.c b/arch/x86/kernel/pmc_atom.c
new file mode 100644
index 000000000000..0c424a67985d
--- /dev/null
+++ b/arch/x86/kernel/pmc_atom.c
@@ -0,0 +1,321 @@
+/*
+ * Intel Atom SOC Power Management Controller Driver
+ * Copyright (c) 2014, 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.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/io.h>
+
+#include <asm/pmc_atom.h>
+
+#define DRIVER_NAME KBUILD_MODNAME
+
+struct pmc_dev {
+ u32 base_addr;
+ void __iomem *regmap;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dbgfs_dir;
+#endif /* CONFIG_DEBUG_FS */
+};
+
+static struct pmc_dev pmc_device;
+static u32 acpi_base_addr;
+
+struct pmc_dev_map {
+ const char *name;
+ u32 bit_mask;
+};
+
+static const struct pmc_dev_map dev_map[] = {
+ {"0 - LPSS1_F0_DMA", BIT_LPSS1_F0_DMA},
+ {"1 - LPSS1_F1_PWM1", BIT_LPSS1_F1_PWM1},
+ {"2 - LPSS1_F2_PWM2", BIT_LPSS1_F2_PWM2},
+ {"3 - LPSS1_F3_HSUART1", BIT_LPSS1_F3_HSUART1},
+ {"4 - LPSS1_F4_HSUART2", BIT_LPSS1_F4_HSUART2},
+ {"5 - LPSS1_F5_SPI", BIT_LPSS1_F5_SPI},
+ {"6 - LPSS1_F6_Reserved", BIT_LPSS1_F6_XXX},
+ {"7 - LPSS1_F7_Reserved", BIT_LPSS1_F7_XXX},
+ {"8 - SCC_EMMC", BIT_SCC_EMMC},
+ {"9 - SCC_SDIO", BIT_SCC_SDIO},
+ {"10 - SCC_SDCARD", BIT_SCC_SDCARD},
+ {"11 - SCC_MIPI", BIT_SCC_MIPI},
+ {"12 - HDA", BIT_HDA},
+ {"13 - LPE", BIT_LPE},
+ {"14 - OTG", BIT_OTG},
+ {"15 - USH", BIT_USH},
+ {"16 - GBE", BIT_GBE},
+ {"17 - SATA", BIT_SATA},
+ {"18 - USB_EHCI", BIT_USB_EHCI},
+ {"19 - SEC", BIT_SEC},
+ {"20 - PCIE_PORT0", BIT_PCIE_PORT0},
+ {"21 - PCIE_PORT1", BIT_PCIE_PORT1},
+ {"22 - PCIE_PORT2", BIT_PCIE_PORT2},
+ {"23 - PCIE_PORT3", BIT_PCIE_PORT3},
+ {"24 - LPSS2_F0_DMA", BIT_LPSS2_F0_DMA},
+ {"25 - LPSS2_F1_I2C1", BIT_LPSS2_F1_I2C1},
+ {"26 - LPSS2_F2_I2C2", BIT_LPSS2_F2_I2C2},
+ {"27 - LPSS2_F3_I2C3", BIT_LPSS2_F3_I2C3},
+ {"28 - LPSS2_F3_I2C4", BIT_LPSS2_F4_I2C4},
+ {"29 - LPSS2_F5_I2C5", BIT_LPSS2_F5_I2C5},
+ {"30 - LPSS2_F6_I2C6", BIT_LPSS2_F6_I2C6},
+ {"31 - LPSS2_F7_I2C7", BIT_LPSS2_F7_I2C7},
+ {"32 - SMB", BIT_SMB},
+ {"33 - OTG_SS_PHY", BIT_OTG_SS_PHY},
+ {"34 - USH_SS_PHY", BIT_USH_SS_PHY},
+ {"35 - DFX", BIT_DFX},
+};
+
+static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)
+{
+ return readl(pmc->regmap + reg_offset);
+}
+
+static inline void pmc_reg_write(struct pmc_dev *pmc, int reg_offset, u32 val)
+{
+ writel(val, pmc->regmap + reg_offset);
+}
+
+static void pmc_power_off(void)
+{
+ u16 pm1_cnt_port;
+ u32 pm1_cnt_value;
+
+ pr_info("Preparing to enter system sleep state S5\n");
+
+ pm1_cnt_port = acpi_base_addr + PM1_CNT;
+
+ pm1_cnt_value = inl(pm1_cnt_port);
+ pm1_cnt_value &= SLEEP_TYPE_MASK;
+ pm1_cnt_value |= SLEEP_TYPE_S5;
+ pm1_cnt_value |= SLEEP_ENABLE;
+
+ outl(pm1_cnt_value, pm1_cnt_port);
+}
+
+static void pmc_hw_reg_setup(struct pmc_dev *pmc)
+{
+ /*
+ * Disable PMC S0IX_WAKE_EN events coming from:
+ * - LPC clock run
+ * - GPIO_SUS ored dedicated IRQs
+ * - GPIO_SCORE ored dedicated IRQs
+ * - GPIO_SUS shared IRQ
+ * - GPIO_SCORE shared IRQ
+ */
+ pmc_reg_write(pmc, PMC_S0IX_WAKE_EN, (u32)PMC_WAKE_EN_SETTING);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int pmc_dev_state_show(struct seq_file *s, void *unused)
+{
+ struct pmc_dev *pmc = s->private;
+ u32 func_dis, func_dis_2, func_dis_index;
+ u32 d3_sts_0, d3_sts_1, d3_sts_index;
+ int dev_num, dev_index, reg_index;
+
+ func_dis = pmc_reg_read(pmc, PMC_FUNC_DIS);
+ func_dis_2 = pmc_reg_read(pmc, PMC_FUNC_DIS_2);
+ d3_sts_0 = pmc_reg_read(pmc, PMC_D3_STS_0);
+ d3_sts_1 = pmc_reg_read(pmc, PMC_D3_STS_1);
+
+ dev_num = ARRAY_SIZE(dev_map);
+
+ for (dev_index = 0; dev_index < dev_num; dev_index++) {
+ reg_index = dev_index / PMC_REG_BIT_WIDTH;
+ if (reg_index) {
+ func_dis_index = func_dis_2;
+ d3_sts_index = d3_sts_1;
+ } else {
+ func_dis_index = func_dis;
+ d3_sts_index = d3_sts_0;
+ }
+
+ seq_printf(s, "Dev: %-32s\tState: %s [%s]\n",
+ dev_map[dev_index].name,
+ dev_map[dev_index].bit_mask & func_dis_index ?
+ "Disabled" : "Enabled ",
+ dev_map[dev_index].bit_mask & d3_sts_index ?
+ "D3" : "D0");
+ }
+ return 0;
+}
+
+static int pmc_dev_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pmc_dev_state_show, inode->i_private);
+}
+
+static const struct file_operations pmc_dev_state_ops = {
+ .open = pmc_dev_state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int pmc_sleep_tmr_show(struct seq_file *s, void *unused)
+{
+ struct pmc_dev *pmc = s->private;
+ u64 s0ir_tmr, s0i1_tmr, s0i2_tmr, s0i3_tmr, s0_tmr;
+
+ s0ir_tmr = (u64)pmc_reg_read(pmc, PMC_S0IR_TMR) << PMC_TMR_SHIFT;
+ s0i1_tmr = (u64)pmc_reg_read(pmc, PMC_S0I1_TMR) << PMC_TMR_SHIFT;
+ s0i2_tmr = (u64)pmc_reg_read(pmc, PMC_S0I2_TMR) << PMC_TMR_SHIFT;
+ s0i3_tmr = (u64)pmc_reg_read(pmc, PMC_S0I3_TMR) << PMC_TMR_SHIFT;
+ s0_tmr = (u64)pmc_reg_read(pmc, PMC_S0_TMR) << PMC_TMR_SHIFT;
+
+ seq_printf(s, "S0IR Residency:\t%lldus\n", s0ir_tmr);
+ seq_printf(s, "S0I1 Residency:\t%lldus\n", s0i1_tmr);
+ seq_printf(s, "S0I2 Residency:\t%lldus\n", s0i2_tmr);
+ seq_printf(s, "S0I3 Residency:\t%lldus\n", s0i3_tmr);
+ seq_printf(s, "S0 Residency:\t%lldus\n", s0_tmr);
+ return 0;
+}
+
+static int pmc_sleep_tmr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pmc_sleep_tmr_show, inode->i_private);
+}
+
+static const struct file_operations pmc_sleep_tmr_ops = {
+ .open = pmc_sleep_tmr_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void pmc_dbgfs_unregister(struct pmc_dev *pmc)
+{
+ if (!pmc->dbgfs_dir)
+ return;
+
+ debugfs_remove_recursive(pmc->dbgfs_dir);
+ pmc->dbgfs_dir = NULL;
+}
+
+static int pmc_dbgfs_register(struct pmc_dev *pmc, struct pci_dev *pdev)
+{
+ struct dentry *dir, *f;
+
+ dir = debugfs_create_dir("pmc_atom", NULL);
+ if (!dir)
+ return -ENOMEM;
+
+ f = debugfs_create_file("dev_state", S_IFREG | S_IRUGO,
+ dir, pmc, &pmc_dev_state_ops);
+ if (!f) {
+ dev_err(&pdev->dev, "dev_states register failed\n");
+ goto err;
+ }
+ f = debugfs_create_file("sleep_state", S_IFREG | S_IRUGO,
+ dir, pmc, &pmc_sleep_tmr_ops);
+ if (!f) {
+ dev_err(&pdev->dev, "sleep_state register failed\n");
+ goto err;
+ }
+ pmc->dbgfs_dir = dir;
+ return 0;
+err:
+ pmc_dbgfs_unregister(pmc);
+ return -ENODEV;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static int pmc_setup_dev(struct pci_dev *pdev)
+{
+ struct pmc_dev *pmc = &pmc_device;
+ int ret;
+
+ /* Obtain ACPI base address */
+ pci_read_config_dword(pdev, ACPI_BASE_ADDR_OFFSET, &acpi_base_addr);
+ acpi_base_addr &= ACPI_BASE_ADDR_MASK;
+
+ /* Install power off function */
+ if (acpi_base_addr != 0 && pm_power_off == NULL)
+ pm_power_off = pmc_power_off;
+
+ pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr);
+ pmc->base_addr &= PMC_BASE_ADDR_MASK;
+
+ pmc->regmap = ioremap_nocache(pmc->base_addr, PMC_MMIO_REG_LEN);
+ if (!pmc->regmap) {
+ dev_err(&pdev->dev, "error: ioremap failed\n");
+ return -ENOMEM;
+ }
+
+ /* PMC hardware registers setup */
+ pmc_hw_reg_setup(pmc);
+
+#ifdef CONFIG_DEBUG_FS
+ ret = pmc_dbgfs_register(pmc, pdev);
+ if (ret) {
+ iounmap(pmc->regmap);
+ return ret;
+ }
+#endif /* CONFIG_DEBUG_FS */
+ return 0;
+}
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because lpc_ich will register
+ * a driver on the same PCI id.
+ */
+static const struct pci_device_id pmc_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VLV_PMC) },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, pmc_pci_ids);
+
+static int __init pmc_atom_init(void)
+{
+ int err = -ENODEV;
+ struct pci_dev *pdev = NULL;
+ const struct pci_device_id *ent;
+
+ /* We look for our device - PCU PMC
+ * we assume that there is max. one device.
+ *
+ * We can't use plain pci_driver mechanism,
+ * as the device is really a multiple function device,
+ * main driver that binds to the pci_device is lpc_ich
+ * and have to find & bind to the device this way.
+ */
+ for_each_pci_dev(pdev) {
+ ent = pci_match_id(pmc_pci_ids, pdev);
+ if (ent) {
+ err = pmc_setup_dev(pdev);
+ goto out;
+ }
+ }
+ /* Device not found. */
+out:
+ return err;
+}
+
+module_init(pmc_atom_init);
+/* no module_exit, this driver shouldn't be unloaded */
+
+MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>");
+MODULE_DESCRIPTION("Intel Atom SOC Power Management Controller Interface");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 4505e2a950d8..f804dc935d2a 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -93,6 +93,7 @@ void arch_task_cache_init(void)
kmem_cache_create("task_xstate", xstate_size,
__alignof__(union thread_xstate),
SLAB_PANIC | SLAB_NOTRACK, NULL);
+ setup_xstate_comp();
}
/*
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 52b1157c53eb..17962e667a91 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -28,6 +28,7 @@
#include <linux/mc146818rtc.h>
#include <asm/realmode.h>
#include <asm/x86_init.h>
+#include <asm/efi.h>
/*
* Power off function, if any
@@ -401,12 +402,25 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
static int __init reboot_init(void)
{
+ int rv;
+
/*
* Only do the DMI check if reboot_type hasn't been overridden
* on the command line
*/
- if (reboot_default)
- dmi_check_system(reboot_dmi_table);
+ if (!reboot_default)
+ return 0;
+
+ /*
+ * The DMI quirks table takes precedence. If no quirks entry
+ * matches and the ACPI Hardware Reduced bit is set, force EFI
+ * reboot.
+ */
+ rv = dmi_check_system(reboot_dmi_table);
+
+ if (!rv && efi_reboot_required())
+ reboot_type = BOOT_EFI;
+
return 0;
}
core_initcall(reboot_init);
@@ -528,11 +542,7 @@ static void native_machine_emergency_restart(void)
break;
case BOOT_EFI:
- if (efi_enabled(EFI_RUNTIME_SERVICES))
- efi.reset_system(reboot_mode == REBOOT_WARM ?
- EFI_RESET_WARM :
- EFI_RESET_COLD,
- EFI_SUCCESS, 0, NULL);
+ efi_reboot(reboot_mode, NULL);
reboot_type = BOOT_BIOS;
break;
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
index 2a26819bb6a8..80eab01c1a68 100644
--- a/arch/x86/kernel/resource.c
+++ b/arch/x86/kernel/resource.c
@@ -37,10 +37,12 @@ static void remove_e820_regions(struct resource *avail)
void arch_remove_reservations(struct resource *avail)
{
- /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+ /*
+ * Trim out BIOS area (high 2MB) and E820 regions. We do not remove
+ * the low 1MB unconditionally, as this area is needed for some ISA
+ * cards requiring a memory range, e.g. the i82365 PCMCIA controller.
+ */
if (avail->flags & IORESOURCE_MEM) {
- if (avail->start < BIOS_END)
- avail->start = BIOS_END;
resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
remove_e820_regions(avail);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 78a0e6298922..41ead8d3bc0b 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -924,10 +924,10 @@ void __init setup_arch(char **cmdline_p)
#endif
#ifdef CONFIG_EFI
if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
- "EL32", 4)) {
+ EFI32_LOADER_SIGNATURE, 4)) {
set_bit(EFI_BOOT, &efi.flags);
} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
- "EL64", 4)) {
+ EFI64_LOADER_SIGNATURE, 4)) {
set_bit(EFI_BOOT, &efi.flags);
set_bit(EFI_64BIT, &efi.flags);
}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 5492798930ef..2d872e08fab9 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -168,10 +168,6 @@ static void smp_callin(void)
* CPU, first the APIC. (this is probably redundant on most
* boards)
*/
-
- pr_debug("CALLIN, before setup_local_APIC()\n");
- if (apic->smp_callin_clear_local_apic)
- apic->smp_callin_clear_local_apic();
setup_local_APIC();
end_local_APIC_setup();
@@ -1143,10 +1139,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
enable_IO_APIC();
bsp_end_local_APIC_setup();
-
- if (apic->setup_portio_remap)
- apic->setup_portio_remap();
-
smpboot_setup_io_apic();
/*
* Set up local APIC timer on boot CPU.
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ea030319b321..b6025f9e36c6 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -234,9 +234,6 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
return ns;
}
-/* XXX surely we already have this someplace in the kernel?! */
-#define DIV_ROUND(n, d) (((n) + ((d) / 2)) / (d))
-
static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
{
unsigned long long tsc_now, ns_now;
@@ -259,7 +256,9 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
* time function is continuous; see the comment near struct
* cyc2ns_data.
*/
- data->cyc2ns_mul = DIV_ROUND(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR, cpu_khz);
+ data->cyc2ns_mul =
+ DIV_ROUND_CLOSEST(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR,
+ cpu_khz);
data->cyc2ns_shift = CYC2NS_SCALE_FACTOR;
data->cyc2ns_offset = ns_now -
mul_u64_u32_shr(tsc_now, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR);
@@ -951,7 +950,7 @@ core_initcall(cpufreq_tsc);
static struct clocksource clocksource_tsc;
/*
- * We compare the TSC to the cycle_last value in the clocksource
+ * We used to compare the TSC to the cycle_last value in the clocksource
* structure to avoid a nasty time-warp. This can be observed in a
* very small window right after one CPU updated cycle_last under
* xtime/vsyscall_gtod lock and the other CPU reads a TSC value which
@@ -961,26 +960,23 @@ static struct clocksource clocksource_tsc;
* due to the unsigned delta calculation of the time keeping core
* code, which is necessary to support wrapping clocksources like pm
* timer.
+ *
+ * This sanity check is now done in the core timekeeping code.
+ * checking the result of read_tsc() - cycle_last for being negative.
+ * That works because CLOCKSOURCE_MASK(64) does not mask out any bit.
*/
static cycle_t read_tsc(struct clocksource *cs)
{
- cycle_t ret = (cycle_t)get_cycles();
-
- return ret >= clocksource_tsc.cycle_last ?
- ret : clocksource_tsc.cycle_last;
-}
-
-static void resume_tsc(struct clocksource *cs)
-{
- if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
- clocksource_tsc.cycle_last = 0;
+ return (cycle_t)get_cycles();
}
+/*
+ * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc()
+ */
static struct clocksource clocksource_tsc = {
.name = "tsc",
.rating = 300,
.read = read_tsc,
- .resume = resume_tsc,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
CLOCK_SOURCE_MUST_VERIFY,
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index b99b9ad8540c..ee22c1d93ae5 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -152,7 +152,7 @@ static void __init detect_vsmp_box(void)
is_vsmp = 1;
}
-int is_vsmp_box(void)
+static int is_vsmp_box(void)
{
if (is_vsmp != -1)
return is_vsmp;
@@ -166,7 +166,7 @@ int is_vsmp_box(void)
static void __init detect_vsmp_box(void)
{
}
-int is_vsmp_box(void)
+static int is_vsmp_box(void)
{
return 0;
}
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index ea5b5709aa76..e1e1e80fc6a6 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -81,10 +81,10 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
if (!show_unhandled_signals)
return;
- pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
- level, current->comm, task_pid_nr(current),
- message, regs->ip, regs->cs,
- regs->sp, regs->ax, regs->si, regs->di);
+ printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+ level, current->comm, task_pid_nr(current),
+ message, regs->ip, regs->cs,
+ regs->sp, regs->ax, regs->si, regs->di);
}
static int addr_to_vsyscall_nr(unsigned long addr)
diff --git a/arch/x86/kernel/vsyscall_gtod.c b/arch/x86/kernel/vsyscall_gtod.c
index 9531fbb123ba..c7d791f32b98 100644
--- a/arch/x86/kernel/vsyscall_gtod.c
+++ b/arch/x86/kernel/vsyscall_gtod.c
@@ -31,29 +31,30 @@ void update_vsyscall(struct timekeeper *tk)
gtod_write_begin(vdata);
/* copy vsyscall data */
- vdata->vclock_mode = tk->clock->archdata.vclock_mode;
- vdata->cycle_last = tk->clock->cycle_last;
- vdata->mask = tk->clock->mask;
- vdata->mult = tk->mult;
- vdata->shift = tk->shift;
+ vdata->vclock_mode = tk->tkr.clock->archdata.vclock_mode;
+ vdata->cycle_last = tk->tkr.cycle_last;
+ vdata->mask = tk->tkr.mask;
+ vdata->mult = tk->tkr.mult;
+ vdata->shift = tk->tkr.shift;
vdata->wall_time_sec = tk->xtime_sec;
- vdata->wall_time_snsec = tk->xtime_nsec;
+ vdata->wall_time_snsec = tk->tkr.xtime_nsec;
vdata->monotonic_time_sec = tk->xtime_sec
+ tk->wall_to_monotonic.tv_sec;
- vdata->monotonic_time_snsec = tk->xtime_nsec
+ vdata->monotonic_time_snsec = tk->tkr.xtime_nsec
+ ((u64)tk->wall_to_monotonic.tv_nsec
- << tk->shift);
+ << tk->tkr.shift);
while (vdata->monotonic_time_snsec >=
- (((u64)NSEC_PER_SEC) << tk->shift)) {
+ (((u64)NSEC_PER_SEC) << tk->tkr.shift)) {
vdata->monotonic_time_snsec -=
- ((u64)NSEC_PER_SEC) << tk->shift;
+ ((u64)NSEC_PER_SEC) << tk->tkr.shift;
vdata->monotonic_time_sec++;
}
vdata->wall_time_coarse_sec = tk->xtime_sec;
- vdata->wall_time_coarse_nsec = (long)(tk->xtime_nsec >> tk->shift);
+ vdata->wall_time_coarse_nsec = (long)(tk->tkr.xtime_nsec >>
+ tk->tkr.shift);
vdata->monotonic_time_coarse_sec =
vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index a4b451c6addf..940b142cc11f 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -8,6 +8,7 @@
#include <linux/bootmem.h>
#include <linux/compat.h>
+#include <linux/cpu.h>
#include <asm/i387.h>
#include <asm/fpu-internal.h>
#include <asm/sigframe.h>
@@ -24,7 +25,9 @@ u64 pcntxt_mask;
struct xsave_struct *init_xstate_buf;
static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
-static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
+static unsigned int *xstate_offsets, *xstate_sizes;
+static unsigned int xstate_comp_offsets[sizeof(pcntxt_mask)*8];
+static unsigned int xstate_features;
/*
* If a processor implementation discern that a processor state component is
@@ -283,7 +286,7 @@ sanitize_restored_xstate(struct task_struct *tsk,
if (use_xsave()) {
/* These bits must be zero. */
- xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+ memset(xsave_hdr->reserved, 0, 48);
/*
* Init the state that is not present in the memory
@@ -479,6 +482,52 @@ static void __init setup_xstate_features(void)
}
/*
+ * This function sets up offsets and sizes of all extended states in
+ * xsave area. This supports both standard format and compacted format
+ * of the xsave aread.
+ *
+ * Input: void
+ * Output: void
+ */
+void setup_xstate_comp(void)
+{
+ unsigned int xstate_comp_sizes[sizeof(pcntxt_mask)*8];
+ int i;
+
+ /*
+ * The FP xstates and SSE xstates are legacy states. They are always
+ * in the fixed offsets in the xsave area in either compacted form
+ * or standard form.
+ */
+ xstate_comp_offsets[0] = 0;
+ xstate_comp_offsets[1] = offsetof(struct i387_fxsave_struct, xmm_space);
+
+ if (!cpu_has_xsaves) {
+ for (i = 2; i < xstate_features; i++) {
+ if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
+ xstate_comp_offsets[i] = xstate_offsets[i];
+ xstate_comp_sizes[i] = xstate_sizes[i];
+ }
+ }
+ return;
+ }
+
+ xstate_comp_offsets[2] = FXSAVE_SIZE + XSAVE_HDR_SIZE;
+
+ for (i = 2; i < xstate_features; i++) {
+ if (test_bit(i, (unsigned long *)&pcntxt_mask))
+ xstate_comp_sizes[i] = xstate_sizes[i];
+ else
+ xstate_comp_sizes[i] = 0;
+
+ if (i > 2)
+ xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
+ + xstate_comp_sizes[i-1];
+
+ }
+}
+
+/*
* setup the xstate image representing the init state
*/
static void __init setup_init_fpu_buf(void)
@@ -496,15 +545,21 @@ static void __init setup_init_fpu_buf(void)
setup_xstate_features();
+ if (cpu_has_xsaves) {
+ init_xstate_buf->xsave_hdr.xcomp_bv =
+ (u64)1 << 63 | pcntxt_mask;
+ init_xstate_buf->xsave_hdr.xstate_bv = pcntxt_mask;
+ }
+
/*
* Init all the features state with header_bv being 0x0
*/
- xrstor_state(init_xstate_buf, -1);
+ xrstor_state_booting(init_xstate_buf, -1);
/*
* Dump the init state again. This is to identify the init state
* of any feature which is not represented by all zero's.
*/
- xsave_state(init_xstate_buf, -1);
+ xsave_state_booting(init_xstate_buf, -1);
}
static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO;
@@ -520,6 +575,30 @@ static int __init eager_fpu_setup(char *s)
}
__setup("eagerfpu=", eager_fpu_setup);
+
+/*
+ * Calculate total size of enabled xstates in XCR0/pcntxt_mask.
+ */
+static void __init init_xstate_size(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ int i;
+
+ if (!cpu_has_xsaves) {
+ cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
+ xstate_size = ebx;
+ return;
+ }
+
+ xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
+ for (i = 2; i < 64; i++) {
+ if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
+ cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
+ xstate_size += eax;
+ }
+ }
+}
+
/*
* Enable and initialize the xsave feature.
*/
@@ -551,8 +630,7 @@ static void __init xstate_enable_boot_cpu(void)
/*
* Recompute the context size for enabled features
*/
- cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
- xstate_size = ebx;
+ init_xstate_size();
update_regset_xstate_info(xstate_size, pcntxt_mask);
prepare_fx_sw_frame();
@@ -572,8 +650,9 @@ static void __init xstate_enable_boot_cpu(void)
}
}
- pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
- pcntxt_mask, xstate_size);
+ pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x using %s\n",
+ pcntxt_mask, xstate_size,
+ cpu_has_xsaves ? "compacted form" : "standard form");
}
/*
@@ -635,3 +714,26 @@ void eager_fpu_init(void)
else
fxrstor_checking(&init_xstate_buf->i387);
}
+
+/*
+ * Given the xsave area and a state inside, this function returns the
+ * address of the state.
+ *
+ * This is the API that is called to get xstate address in either
+ * standard format or compacted format of xsave area.
+ *
+ * Inputs:
+ * xsave: base address of the xsave area;
+ * xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
+ * etc.)
+ * Output:
+ * address of the state in the xsave area.
+ */
+void *get_xsave_addr(struct xsave_struct *xsave, int xstate)
+{
+ int feature = fls64(xstate) - 1;
+ if (!test_bit(feature, (unsigned long *)&pcntxt_mask))
+ return NULL;
+
+ return (void *)xsave + xstate_comp_offsets[feature];
+}
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 287e4c85fff9..f9d16ff56c6b 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -27,6 +27,7 @@ config KVM
select MMU_NOTIFIER
select ANON_INODES
select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_EVENTFD
select KVM_APIC_ARCHITECTURE
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index f9087315e0cd..a5380590ab0e 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -95,4 +95,12 @@ static inline bool guest_cpuid_has_gbpages(struct kvm_vcpu *vcpu)
best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
return best && (best->edx & bit(X86_FEATURE_GBPAGES));
}
+
+static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 7, 0);
+ return best && (best->ebx & bit(X86_FEATURE_RTM));
+}
#endif
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e4e833d3d7d7..56657b0bb3bb 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -162,6 +162,10 @@
#define NoWrite ((u64)1 << 45) /* No writeback */
#define SrcWrite ((u64)1 << 46) /* Write back src operand */
#define NoMod ((u64)1 << 47) /* Mod field is ignored */
+#define Intercept ((u64)1 << 48) /* Has valid intercept field */
+#define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */
+#define NoBigReal ((u64)1 << 50) /* No big real mode */
+#define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */
#define DstXacc (DstAccLo | SrcAccHi | SrcWrite)
@@ -426,6 +430,7 @@ static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
.modrm_reg = ctxt->modrm_reg,
.modrm_rm = ctxt->modrm_rm,
.src_val = ctxt->src.val64,
+ .dst_val = ctxt->dst.val64,
.src_bytes = ctxt->src.bytes,
.dst_bytes = ctxt->dst.bytes,
.ad_bytes = ctxt->ad_bytes,
@@ -511,12 +516,6 @@ static u32 desc_limit_scaled(struct desc_struct *desc)
return desc->g ? (limit << 12) | 0xfff : limit;
}
-static void set_seg_override(struct x86_emulate_ctxt *ctxt, int seg)
-{
- ctxt->has_seg_override = true;
- ctxt->seg_override = seg;
-}
-
static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg)
{
if (ctxt->mode == X86EMUL_MODE_PROT64 && seg < VCPU_SREG_FS)
@@ -525,14 +524,6 @@ static unsigned long seg_base(struct x86_emulate_ctxt *ctxt, int seg)
return ctxt->ops->get_cached_segment_base(ctxt, seg);
}
-static unsigned seg_override(struct x86_emulate_ctxt *ctxt)
-{
- if (!ctxt->has_seg_override)
- return 0;
-
- return ctxt->seg_override;
-}
-
static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec,
u32 error, bool valid)
{
@@ -651,7 +642,12 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
if (!fetch && (desc.type & 8) && !(desc.type & 2))
goto bad;
lim = desc_limit_scaled(&desc);
- if ((desc.type & 8) || !(desc.type & 4)) {
+ if ((ctxt->mode == X86EMUL_MODE_REAL) && !fetch &&
+ (ctxt->d & NoBigReal)) {
+ /* la is between zero and 0xffff */
+ if (la > 0xffff || (u32)(la + size - 1) > 0xffff)
+ goto bad;
+ } else if ((desc.type & 8) || !(desc.type & 4)) {
/* expand-up segment */
if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
goto bad;
@@ -716,68 +712,71 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
}
/*
- * Fetch the next byte of the instruction being emulated which is pointed to
- * by ctxt->_eip, then increment ctxt->_eip.
- *
- * Also prefetch the remaining bytes of the instruction without crossing page
+ * Prefetch the remaining bytes of the instruction without crossing page
* boundary if they are not in fetch_cache yet.
*/
-static int do_insn_fetch_byte(struct x86_emulate_ctxt *ctxt, u8 *dest)
+static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
{
- struct fetch_cache *fc = &ctxt->fetch;
int rc;
- int size, cur_size;
-
- if (ctxt->_eip == fc->end) {
- unsigned long linear;
- struct segmented_address addr = { .seg = VCPU_SREG_CS,
- .ea = ctxt->_eip };
- cur_size = fc->end - fc->start;
- size = min(15UL - cur_size,
- PAGE_SIZE - offset_in_page(ctxt->_eip));
- rc = __linearize(ctxt, addr, size, false, true, &linear);
- if (unlikely(rc != X86EMUL_CONTINUE))
- return rc;
- rc = ctxt->ops->fetch(ctxt, linear, fc->data + cur_size,
- size, &ctxt->exception);
- if (unlikely(rc != X86EMUL_CONTINUE))
- return rc;
- fc->end += size;
- }
- *dest = fc->data[ctxt->_eip - fc->start];
- ctxt->_eip++;
- return X86EMUL_CONTINUE;
-}
+ unsigned size;
+ unsigned long linear;
+ int cur_size = ctxt->fetch.end - ctxt->fetch.data;
+ struct segmented_address addr = { .seg = VCPU_SREG_CS,
+ .ea = ctxt->eip + cur_size };
+
+ size = 15UL ^ cur_size;
+ rc = __linearize(ctxt, addr, size, false, true, &linear);
+ if (unlikely(rc != X86EMUL_CONTINUE))
+ return rc;
-static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
- void *dest, unsigned size)
-{
- int rc;
+ size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
- /* x86 instructions are limited to 15 bytes. */
- if (unlikely(ctxt->_eip + size - ctxt->eip > 15))
+ /*
+ * One instruction can only straddle two pages,
+ * and one has been loaded at the beginning of
+ * x86_decode_insn. So, if not enough bytes
+ * still, we must have hit the 15-byte boundary.
+ */
+ if (unlikely(size < op_size))
return X86EMUL_UNHANDLEABLE;
- while (size--) {
- rc = do_insn_fetch_byte(ctxt, dest++);
- if (rc != X86EMUL_CONTINUE)
- return rc;
- }
+ rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end,
+ size, &ctxt->exception);
+ if (unlikely(rc != X86EMUL_CONTINUE))
+ return rc;
+ ctxt->fetch.end += size;
return X86EMUL_CONTINUE;
}
+static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
+ unsigned size)
+{
+ if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
+ return __do_insn_fetch_bytes(ctxt, size);
+ else
+ return X86EMUL_CONTINUE;
+}
+
/* Fetch next part of the instruction being emulated. */
#define insn_fetch(_type, _ctxt) \
-({ unsigned long _x; \
- rc = do_insn_fetch(_ctxt, &_x, sizeof(_type)); \
+({ _type _x; \
+ \
+ rc = do_insn_fetch_bytes(_ctxt, sizeof(_type)); \
if (rc != X86EMUL_CONTINUE) \
goto done; \
- (_type)_x; \
+ ctxt->_eip += sizeof(_type); \
+ _x = *(_type __aligned(1) *) ctxt->fetch.ptr; \
+ ctxt->fetch.ptr += sizeof(_type); \
+ _x; \
})
#define insn_fetch_arr(_arr, _size, _ctxt) \
-({ rc = do_insn_fetch(_ctxt, _arr, (_size)); \
+({ \
+ rc = do_insn_fetch_bytes(_ctxt, _size); \
if (rc != X86EMUL_CONTINUE) \
goto done; \
+ ctxt->_eip += (_size); \
+ memcpy(_arr, ctxt->fetch.ptr, _size); \
+ ctxt->fetch.ptr += (_size); \
})
/*
@@ -1063,19 +1062,17 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
struct operand *op)
{
u8 sib;
- int index_reg = 0, base_reg = 0, scale;
+ int index_reg, base_reg, scale;
int rc = X86EMUL_CONTINUE;
ulong modrm_ea = 0;
- if (ctxt->rex_prefix) {
- ctxt->modrm_reg = (ctxt->rex_prefix & 4) << 1; /* REX.R */
- index_reg = (ctxt->rex_prefix & 2) << 2; /* REX.X */
- ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
- }
+ ctxt->modrm_reg = ((ctxt->rex_prefix << 1) & 8); /* REX.R */
+ index_reg = (ctxt->rex_prefix << 2) & 8; /* REX.X */
+ base_reg = (ctxt->rex_prefix << 3) & 8; /* REX.B */
- ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
+ ctxt->modrm_mod = (ctxt->modrm & 0xc0) >> 6;
ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
- ctxt->modrm_rm |= (ctxt->modrm & 0x07);
+ ctxt->modrm_rm = base_reg | (ctxt->modrm & 0x07);
ctxt->modrm_seg = VCPU_SREG_DS;
if (ctxt->modrm_mod == 3 || (ctxt->d & NoMod)) {
@@ -1093,7 +1090,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
if (ctxt->d & Mmx) {
op->type = OP_MM;
op->bytes = 8;
- op->addr.xmm = ctxt->modrm_rm & 7;
+ op->addr.mm = ctxt->modrm_rm & 7;
return rc;
}
fetch_register_operand(op);
@@ -1190,6 +1187,9 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
}
}
op->addr.mem.ea = modrm_ea;
+ if (ctxt->ad_bytes != 8)
+ ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
+
done:
return rc;
}
@@ -1220,12 +1220,14 @@ static void fetch_bit_operand(struct x86_emulate_ctxt *ctxt)
long sv = 0, mask;
if (ctxt->dst.type == OP_MEM && ctxt->src.type == OP_REG) {
- mask = ~(ctxt->dst.bytes * 8 - 1);
+ mask = ~((long)ctxt->dst.bytes * 8 - 1);
if (ctxt->src.bytes == 2)
sv = (s16)ctxt->src.val & (s16)mask;
else if (ctxt->src.bytes == 4)
sv = (s32)ctxt->src.val & (s32)mask;
+ else
+ sv = (s64)ctxt->src.val & (s64)mask;
ctxt->dst.addr.mem.ea += (sv >> 3);
}
@@ -1315,8 +1317,7 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
in_page = (ctxt->eflags & EFLG_DF) ?
offset_in_page(reg_read(ctxt, VCPU_REGS_RDI)) :
PAGE_SIZE - offset_in_page(reg_read(ctxt, VCPU_REGS_RDI));
- n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
- count);
+ n = min3(in_page, (unsigned int)sizeof(rc->data) / size, count);
if (n == 0)
n = 1;
rc->pos = rc->end = 0;
@@ -1358,17 +1359,19 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
u16 selector, struct desc_ptr *dt)
{
const struct x86_emulate_ops *ops = ctxt->ops;
+ u32 base3 = 0;
if (selector & 1 << 2) {
struct desc_struct desc;
u16 sel;
memset (dt, 0, sizeof *dt);
- if (!ops->get_segment(ctxt, &sel, &desc, NULL, VCPU_SREG_LDTR))
+ if (!ops->get_segment(ctxt, &sel, &desc, &base3,
+ VCPU_SREG_LDTR))
return;
dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
- dt->address = get_desc_base(&desc);
+ dt->address = get_desc_base(&desc) | ((u64)base3 << 32);
} else
ops->get_gdt(ctxt, dt);
}
@@ -1422,6 +1425,7 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
ulong desc_addr;
int ret;
u16 dummy;
+ u32 base3 = 0;
memset(&seg_desc, 0, sizeof seg_desc);
@@ -1538,9 +1542,14 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
ret = write_segment_descriptor(ctxt, selector, &seg_desc);
if (ret != X86EMUL_CONTINUE)
return ret;
+ } else if (ctxt->mode == X86EMUL_MODE_PROT64) {
+ ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3,
+ sizeof(base3), &ctxt->exception);
+ if (ret != X86EMUL_CONTINUE)
+ return ret;
}
load:
- ctxt->ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
+ ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
return X86EMUL_CONTINUE;
exception:
emulate_exception(ctxt, err_vec, err_code, true);
@@ -1575,34 +1584,28 @@ static void write_register_operand(struct operand *op)
static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
{
- int rc;
-
switch (op->type) {
case OP_REG:
write_register_operand(op);
break;
case OP_MEM:
if (ctxt->lock_prefix)
- rc = segmented_cmpxchg(ctxt,
+ return segmented_cmpxchg(ctxt,
+ op->addr.mem,
+ &op->orig_val,
+ &op->val,
+ op->bytes);
+ else
+ return segmented_write(ctxt,
op->addr.mem,
- &op->orig_val,
&op->val,
op->bytes);
- else
- rc = segmented_write(ctxt,
- op->addr.mem,
- &op->val,
- op->bytes);
- if (rc != X86EMUL_CONTINUE)
- return rc;
break;
case OP_MEM_STR:
- rc = segmented_write(ctxt,
- op->addr.mem,
- op->data,
- op->bytes * op->count);
- if (rc != X86EMUL_CONTINUE)
- return rc;
+ return segmented_write(ctxt,
+ op->addr.mem,
+ op->data,
+ op->bytes * op->count);
break;
case OP_XMM:
write_sse_reg(ctxt, &op->vec_val, op->addr.xmm);
@@ -1671,7 +1674,7 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt,
return rc;
change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
- | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
+ | EFLG_TF | EFLG_DF | EFLG_NT | EFLG_AC | EFLG_ID;
switch(ctxt->mode) {
case X86EMUL_MODE_PROT64:
@@ -1754,6 +1757,9 @@ static int em_pop_sreg(struct x86_emulate_ctxt *ctxt)
if (rc != X86EMUL_CONTINUE)
return rc;
+ if (ctxt->modrm_reg == VCPU_SREG_SS)
+ ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
+
rc = load_segment_descriptor(ctxt, (u16)selector, seg);
return rc;
}
@@ -1991,6 +1997,9 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
{
u64 old = ctxt->dst.orig_val64;
+ if (ctxt->dst.bytes == 16)
+ return X86EMUL_UNHANDLEABLE;
+
if (((u32) (old >> 0) != (u32) reg_read(ctxt, VCPU_REGS_RAX)) ||
((u32) (old >> 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {
*reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old >> 0);
@@ -2017,6 +2026,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
{
int rc;
unsigned long cs;
+ int cpl = ctxt->ops->cpl(ctxt);
rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
@@ -2026,6 +2036,9 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
+ /* Outer-privilege level return is not implemented */
+ if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
+ return X86EMUL_UNHANDLEABLE;
rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
return rc;
}
@@ -2044,8 +2057,10 @@ static int em_ret_far_imm(struct x86_emulate_ctxt *ctxt)
static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
{
/* Save real source value, then compare EAX against destination. */
+ ctxt->dst.orig_val = ctxt->dst.val;
+ ctxt->dst.val = reg_read(ctxt, VCPU_REGS_RAX);
ctxt->src.orig_val = ctxt->src.val;
- ctxt->src.val = reg_read(ctxt, VCPU_REGS_RAX);
+ ctxt->src.val = ctxt->dst.orig_val;
fastop(ctxt, em_cmp);
if (ctxt->eflags & EFLG_ZF) {
@@ -2055,6 +2070,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
/* Failure: write the value we saw to EAX. */
ctxt->dst.type = OP_REG;
ctxt->dst.addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
+ ctxt->dst.val = ctxt->dst.orig_val;
}
return X86EMUL_CONTINUE;
}
@@ -2194,7 +2210,7 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
*reg_write(ctxt, VCPU_REGS_RCX) = ctxt->_eip;
if (efer & EFER_LMA) {
#ifdef CONFIG_X86_64
- *reg_write(ctxt, VCPU_REGS_R11) = ctxt->eflags & ~EFLG_RF;
+ *reg_write(ctxt, VCPU_REGS_R11) = ctxt->eflags;
ops->get_msr(ctxt,
ctxt->mode == X86EMUL_MODE_PROT64 ?
@@ -2202,14 +2218,14 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
ctxt->_eip = msr_data;
ops->get_msr(ctxt, MSR_SYSCALL_MASK, &msr_data);
- ctxt->eflags &= ~(msr_data | EFLG_RF);
+ ctxt->eflags &= ~msr_data;
#endif
} else {
/* legacy mode */
ops->get_msr(ctxt, MSR_STAR, &msr_data);
ctxt->_eip = (u32)msr_data;
- ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+ ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
}
return X86EMUL_CONTINUE;
@@ -2258,7 +2274,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
break;
}
- ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
+ ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
cs_sel = (u16)msr_data;
cs_sel &= ~SELECTOR_RPL_MASK;
ss_sel = cs_sel + 8;
@@ -2964,7 +2980,7 @@ static int em_rdpmc(struct x86_emulate_ctxt *ctxt)
static int em_mov(struct x86_emulate_ctxt *ctxt)
{
- memcpy(ctxt->dst.valptr, ctxt->src.valptr, ctxt->op_bytes);
+ memcpy(ctxt->dst.valptr, ctxt->src.valptr, sizeof(ctxt->src.valptr));
return X86EMUL_CONTINUE;
}
@@ -3221,7 +3237,8 @@ static int em_lidt(struct x86_emulate_ctxt *ctxt)
static int em_smsw(struct x86_emulate_ctxt *ctxt)
{
- ctxt->dst.bytes = 2;
+ if (ctxt->dst.type == OP_MEM)
+ ctxt->dst.bytes = 2;
ctxt->dst.val = ctxt->ops->get_cr(ctxt, 0);
return X86EMUL_CONTINUE;
}
@@ -3496,7 +3513,7 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
u64 rcx = reg_read(ctxt, VCPU_REGS_RCX);
if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt)) ||
- (rcx > 3))
+ ctxt->ops->check_pmc(ctxt, rcx))
return emulate_gp(ctxt, 0);
return X86EMUL_CONTINUE;
@@ -3521,9 +3538,9 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
}
#define D(_y) { .flags = (_y) }
-#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i }
-#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \
- .check_perm = (_p) }
+#define DI(_y, _i) { .flags = (_y)|Intercept, .intercept = x86_intercept_##_i }
+#define DIP(_y, _i, _p) { .flags = (_y)|Intercept|CheckPerm, \
+ .intercept = x86_intercept_##_i, .check_perm = (_p) }
#define N D(NotImpl)
#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
#define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) }
@@ -3532,10 +3549,10 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) }
#define II(_f, _e, _i) \
- { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i }
+ { .flags = (_f)|Intercept, .u.execute = (_e), .intercept = x86_intercept_##_i }
#define IIP(_f, _e, _i, _p) \
- { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i, \
- .check_perm = (_p) }
+ { .flags = (_f)|Intercept|CheckPerm, .u.execute = (_e), \
+ .intercept = x86_intercept_##_i, .check_perm = (_p) }
#define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) }
#define D2bv(_f) D((_f) | ByteOp), D(_f)
@@ -3634,8 +3651,8 @@ static const struct opcode group6[] = {
};
static const struct group_dual group7 = { {
- II(Mov | DstMem | Priv, em_sgdt, sgdt),
- II(Mov | DstMem | Priv, em_sidt, sidt),
+ II(Mov | DstMem, em_sgdt, sgdt),
+ II(Mov | DstMem, em_sidt, sidt),
II(SrcMem | Priv, em_lgdt, lgdt),
II(SrcMem | Priv, em_lidt, lidt),
II(SrcNone | DstMem | Mov, em_smsw, smsw), N,
@@ -3899,7 +3916,7 @@ static const struct opcode twobyte_table[256] = {
N, N,
N, N, N, N, N, N, N, N,
/* 0x40 - 0x4F */
- X16(D(DstReg | SrcMem | ModRM | Mov)),
+ X16(D(DstReg | SrcMem | ModRM)),
/* 0x50 - 0x5F */
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
/* 0x60 - 0x6F */
@@ -4061,12 +4078,12 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
mem_common:
*op = ctxt->memop;
ctxt->memopp = op;
- if ((ctxt->d & BitOp) && op == &ctxt->dst)
+ if (ctxt->d & BitOp)
fetch_bit_operand(ctxt);
op->orig_val = op->val;
break;
case OpMem64:
- ctxt->memop.bytes = 8;
+ ctxt->memop.bytes = (ctxt->op_bytes == 8) ? 16 : 8;
goto mem_common;
case OpAcc:
op->type = OP_REG;
@@ -4150,7 +4167,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.mem.ea =
register_address(ctxt, reg_read(ctxt, VCPU_REGS_RSI));
- op->addr.mem.seg = seg_override(ctxt);
+ op->addr.mem.seg = ctxt->seg_override;
op->val = 0;
op->count = 1;
break;
@@ -4161,7 +4178,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
register_address(ctxt,
reg_read(ctxt, VCPU_REGS_RBX) +
(reg_read(ctxt, VCPU_REGS_RAX) & 0xff));
- op->addr.mem.seg = seg_override(ctxt);
+ op->addr.mem.seg = ctxt->seg_override;
op->val = 0;
break;
case OpImmFAddr:
@@ -4208,16 +4225,22 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
int mode = ctxt->mode;
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
bool op_prefix = false;
+ bool has_seg_override = false;
struct opcode opcode;
ctxt->memop.type = OP_NONE;
ctxt->memopp = NULL;
ctxt->_eip = ctxt->eip;
- ctxt->fetch.start = ctxt->_eip;
- ctxt->fetch.end = ctxt->fetch.start + insn_len;
+ ctxt->fetch.ptr = ctxt->fetch.data;
+ ctxt->fetch.end = ctxt->fetch.data + insn_len;
ctxt->opcode_len = 1;
if (insn_len > 0)
memcpy(ctxt->fetch.data, insn, insn_len);
+ else {
+ rc = __do_insn_fetch_bytes(ctxt, 1);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+ }
switch (mode) {
case X86EMUL_MODE_REAL:
@@ -4261,11 +4284,13 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
case 0x2e: /* CS override */
case 0x36: /* SS override */
case 0x3e: /* DS override */
- set_seg_override(ctxt, (ctxt->b >> 3) & 3);
+ has_seg_override = true;
+ ctxt->seg_override = (ctxt->b >> 3) & 3;
break;
case 0x64: /* FS override */
case 0x65: /* GS override */
- set_seg_override(ctxt, ctxt->b & 7);
+ has_seg_override = true;
+ ctxt->seg_override = ctxt->b & 7;
break;
case 0x40 ... 0x4f: /* REX */
if (mode != X86EMUL_MODE_PROT64)
@@ -4314,6 +4339,13 @@ done_prefixes:
if (ctxt->d & ModRM)
ctxt->modrm = insn_fetch(u8, ctxt);
+ /* vex-prefix instructions are not implemented */
+ if (ctxt->opcode_len == 1 && (ctxt->b == 0xc5 || ctxt->b == 0xc4) &&
+ (mode == X86EMUL_MODE_PROT64 ||
+ (mode >= X86EMUL_MODE_PROT16 && (ctxt->modrm & 0x80)))) {
+ ctxt->d = NotImpl;
+ }
+
while (ctxt->d & GroupMask) {
switch (ctxt->d & GroupMask) {
case Group:
@@ -4356,49 +4388,59 @@ done_prefixes:
ctxt->d |= opcode.flags;
}
- ctxt->execute = opcode.u.execute;
- ctxt->check_perm = opcode.check_perm;
- ctxt->intercept = opcode.intercept;
-
/* Unrecognised? */
- if (ctxt->d == 0 || (ctxt->d & NotImpl))
+ if (ctxt->d == 0)
return EMULATION_FAILED;
- if (!(ctxt->d & EmulateOnUD) && ctxt->ud)
- return EMULATION_FAILED;
+ ctxt->execute = opcode.u.execute;
- if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
- ctxt->op_bytes = 8;
+ if (unlikely(ctxt->d &
+ (NotImpl|EmulateOnUD|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) {
+ /*
+ * These are copied unconditionally here, and checked unconditionally
+ * in x86_emulate_insn.
+ */
+ ctxt->check_perm = opcode.check_perm;
+ ctxt->intercept = opcode.intercept;
+
+ if (ctxt->d & NotImpl)
+ return EMULATION_FAILED;
+
+ if (!(ctxt->d & EmulateOnUD) && ctxt->ud)
+ return EMULATION_FAILED;
- if (ctxt->d & Op3264) {
- if (mode == X86EMUL_MODE_PROT64)
+ if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
ctxt->op_bytes = 8;
- else
- ctxt->op_bytes = 4;
- }
- if (ctxt->d & Sse)
- ctxt->op_bytes = 16;
- else if (ctxt->d & Mmx)
- ctxt->op_bytes = 8;
+ if (ctxt->d & Op3264) {
+ if (mode == X86EMUL_MODE_PROT64)
+ ctxt->op_bytes = 8;
+ else
+ ctxt->op_bytes = 4;
+ }
+
+ if (ctxt->d & Sse)
+ ctxt->op_bytes = 16;
+ else if (ctxt->d & Mmx)
+ ctxt->op_bytes = 8;
+ }
/* ModRM and SIB bytes. */
if (ctxt->d & ModRM) {
rc = decode_modrm(ctxt, &ctxt->memop);
- if (!ctxt->has_seg_override)
- set_seg_override(ctxt, ctxt->modrm_seg);
+ if (!has_seg_override) {
+ has_seg_override = true;
+ ctxt->seg_override = ctxt->modrm_seg;
+ }
} else if (ctxt->d & MemAbs)
rc = decode_abs(ctxt, &ctxt->memop);
if (rc != X86EMUL_CONTINUE)
goto done;
- if (!ctxt->has_seg_override)
- set_seg_override(ctxt, VCPU_SREG_DS);
-
- ctxt->memop.addr.mem.seg = seg_override(ctxt);
+ if (!has_seg_override)
+ ctxt->seg_override = VCPU_SREG_DS;
- if (ctxt->memop.type == OP_MEM && ctxt->ad_bytes != 8)
- ctxt->memop.addr.mem.ea = (u32)ctxt->memop.addr.mem.ea;
+ ctxt->memop.addr.mem.seg = ctxt->seg_override;
/*
* Decode and fetch the source operand: register, memory
@@ -4420,7 +4462,7 @@ done_prefixes:
rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
done:
- if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)
+ if (ctxt->rip_relative)
ctxt->memopp->addr.mem.ea += ctxt->_eip;
return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
@@ -4495,6 +4537,16 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *))
return X86EMUL_CONTINUE;
}
+void init_decode_cache(struct x86_emulate_ctxt *ctxt)
+{
+ memset(&ctxt->rip_relative, 0,
+ (void *)&ctxt->modrm - (void *)&ctxt->rip_relative);
+
+ ctxt->io_read.pos = 0;
+ ctxt->io_read.end = 0;
+ ctxt->mem_read.end = 0;
+}
+
int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
{
const struct x86_emulate_ops *ops = ctxt->ops;
@@ -4503,12 +4555,6 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
ctxt->mem_read.pos = 0;
- if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
- (ctxt->d & Undefined)) {
- rc = emulate_ud(ctxt);
- goto done;
- }
-
/* LOCK prefix is allowed only with some instructions */
if (ctxt->lock_prefix && (!(ctxt->d & Lock) || ctxt->dst.type != OP_MEM)) {
rc = emulate_ud(ctxt);
@@ -4520,69 +4566,82 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
goto done;
}
- if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
- || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
- rc = emulate_ud(ctxt);
- goto done;
- }
-
- if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
- rc = emulate_nm(ctxt);
- goto done;
- }
+ if (unlikely(ctxt->d &
+ (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
+ if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
+ (ctxt->d & Undefined)) {
+ rc = emulate_ud(ctxt);
+ goto done;
+ }
- if (ctxt->d & Mmx) {
- rc = flush_pending_x87_faults(ctxt);
- if (rc != X86EMUL_CONTINUE)
+ if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
+ || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
+ rc = emulate_ud(ctxt);
goto done;
- /*
- * Now that we know the fpu is exception safe, we can fetch
- * operands from it.
- */
- fetch_possible_mmx_operand(ctxt, &ctxt->src);
- fetch_possible_mmx_operand(ctxt, &ctxt->src2);
- if (!(ctxt->d & Mov))
- fetch_possible_mmx_operand(ctxt, &ctxt->dst);
- }
+ }
- if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
- rc = emulator_check_intercept(ctxt, ctxt->intercept,
- X86_ICPT_PRE_EXCEPT);
- if (rc != X86EMUL_CONTINUE)
+ if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
+ rc = emulate_nm(ctxt);
goto done;
- }
+ }
- /* Privileged instruction can be executed only in CPL=0 */
- if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
- rc = emulate_gp(ctxt, 0);
- goto done;
- }
+ if (ctxt->d & Mmx) {
+ rc = flush_pending_x87_faults(ctxt);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ /*
+ * Now that we know the fpu is exception safe, we can fetch
+ * operands from it.
+ */
+ fetch_possible_mmx_operand(ctxt, &ctxt->src);
+ fetch_possible_mmx_operand(ctxt, &ctxt->src2);
+ if (!(ctxt->d & Mov))
+ fetch_possible_mmx_operand(ctxt, &ctxt->dst);
+ }
- /* Instruction can only be executed in protected mode */
- if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
- rc = emulate_ud(ctxt);
- goto done;
- }
+ if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
+ rc = emulator_check_intercept(ctxt, ctxt->intercept,
+ X86_ICPT_PRE_EXCEPT);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ }
- /* Do instruction specific permission checks */
- if (ctxt->check_perm) {
- rc = ctxt->check_perm(ctxt);
- if (rc != X86EMUL_CONTINUE)
+ /* Privileged instruction can be executed only in CPL=0 */
+ if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
+ if (ctxt->d & PrivUD)
+ rc = emulate_ud(ctxt);
+ else
+ rc = emulate_gp(ctxt, 0);
goto done;
- }
+ }
- if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
- rc = emulator_check_intercept(ctxt, ctxt->intercept,
- X86_ICPT_POST_EXCEPT);
- if (rc != X86EMUL_CONTINUE)
+ /* Instruction can only be executed in protected mode */
+ if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
+ rc = emulate_ud(ctxt);
goto done;
- }
+ }
- if (ctxt->rep_prefix && (ctxt->d & String)) {
- /* All REP prefixes have the same first termination condition */
- if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
- ctxt->eip = ctxt->_eip;
- goto done;
+ /* Do instruction specific permission checks */
+ if (ctxt->d & CheckPerm) {
+ rc = ctxt->check_perm(ctxt);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ }
+
+ if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
+ rc = emulator_check_intercept(ctxt, ctxt->intercept,
+ X86_ICPT_POST_EXCEPT);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ }
+
+ if (ctxt->rep_prefix && (ctxt->d & String)) {
+ /* All REP prefixes have the same first termination condition */
+ if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
+ ctxt->eip = ctxt->_eip;
+ ctxt->eflags &= ~EFLG_RF;
+ goto done;
+ }
}
}
@@ -4616,13 +4675,18 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
special_insn:
- if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
+ if (unlikely(ctxt->guest_mode) && (ctxt->d & Intercept)) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_MEMACCESS);
if (rc != X86EMUL_CONTINUE)
goto done;
}
+ if (ctxt->rep_prefix && (ctxt->d & String))
+ ctxt->eflags |= EFLG_RF;
+ else
+ ctxt->eflags &= ~EFLG_RF;
+
if (ctxt->execute) {
if (ctxt->d & Fastop) {
void (*fop)(struct fastop *) = (void *)ctxt->execute;
@@ -4657,8 +4721,9 @@ special_insn:
break;
case 0x90 ... 0x97: /* nop / xchg reg, rax */
if (ctxt->dst.addr.reg == reg_rmw(ctxt, VCPU_REGS_RAX))
- break;
- rc = em_xchg(ctxt);
+ ctxt->dst.type = OP_NONE;
+ else
+ rc = em_xchg(ctxt);
break;
case 0x98: /* cbw/cwde/cdqe */
switch (ctxt->op_bytes) {
@@ -4709,17 +4774,17 @@ special_insn:
goto done;
writeback:
- if (!(ctxt->d & NoWrite)) {
- rc = writeback(ctxt, &ctxt->dst);
- if (rc != X86EMUL_CONTINUE)
- goto done;
- }
if (ctxt->d & SrcWrite) {
BUG_ON(ctxt->src.type == OP_MEM || ctxt->src.type == OP_MEM_STR);
rc = writeback(ctxt, &ctxt->src);
if (rc != X86EMUL_CONTINUE)
goto done;
}
+ if (!(ctxt->d & NoWrite)) {
+ rc = writeback(ctxt, &ctxt->dst);
+ if (rc != X86EMUL_CONTINUE)
+ goto done;
+ }
/*
* restore dst type in case the decoding will be reused
@@ -4761,6 +4826,7 @@ writeback:
}
goto done; /* skip rip writeback */
}
+ ctxt->eflags &= ~EFLG_RF;
}
ctxt->eip = ctxt->_eip;
@@ -4793,8 +4859,10 @@ twobyte_insn:
ops->get_dr(ctxt, ctxt->modrm_reg, &ctxt->dst.val);
break;
case 0x40 ... 0x4f: /* cmov */
- ctxt->dst.val = ctxt->dst.orig_val = ctxt->src.val;
- if (!test_cc(ctxt->b, ctxt->eflags))
+ if (test_cc(ctxt->b, ctxt->eflags))
+ ctxt->dst.val = ctxt->src.val;
+ else if (ctxt->mode != X86EMUL_MODE_PROT64 ||
+ ctxt->op_bytes != 4)
ctxt->dst.type = OP_NONE; /* no writeback */
break;
case 0x80 ... 0x8f: /* jnz rel, etc*/
@@ -4818,8 +4886,8 @@ twobyte_insn:
break;
case 0xc3: /* movnti */
ctxt->dst.bytes = ctxt->op_bytes;
- ctxt->dst.val = (ctxt->op_bytes == 4) ? (u32) ctxt->src.val :
- (u64) ctxt->src.val;
+ ctxt->dst.val = (ctxt->op_bytes == 8) ? (u64) ctxt->src.val :
+ (u32) ctxt->src.val;
break;
default:
goto cannot_emulate;
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index bd0da433e6d7..a1ec6a50a05a 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -108,7 +108,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
vector = kvm_cpu_get_extint(v);
- if (kvm_apic_vid_enabled(v->kvm) || vector != -1)
+ if (vector != -1)
return vector; /* PIC */
return kvm_get_apic_interrupt(v); /* APIC */
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 006911858174..08e8a899e005 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -352,25 +352,46 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic)
static inline void apic_clear_irr(int vec, struct kvm_lapic *apic)
{
- apic->irr_pending = false;
+ struct kvm_vcpu *vcpu;
+
+ vcpu = apic->vcpu;
+
apic_clear_vector(vec, apic->regs + APIC_IRR);
- if (apic_search_irr(apic) != -1)
- apic->irr_pending = true;
+ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm)))
+ /* try to update RVI */
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+ else {
+ vec = apic_search_irr(apic);
+ apic->irr_pending = (vec != -1);
+ }
}
static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
{
- /* Note that we never get here with APIC virtualization enabled. */
+ struct kvm_vcpu *vcpu;
+
+ if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
+ return;
+
+ vcpu = apic->vcpu;
- if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
- ++apic->isr_count;
- BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
/*
- * ISR (in service register) bit is set when injecting an interrupt.
- * The highest vector is injected. Thus the latest bit set matches
- * the highest bit in ISR.
+ * With APIC virtualization enabled, all caching is disabled
+ * because the processor can modify ISR under the hood. Instead
+ * just set SVI.
*/
- apic->highest_isr_cache = vec;
+ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm)))
+ kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec);
+ else {
+ ++apic->isr_count;
+ BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
+ /*
+ * ISR (in service register) bit is set when injecting an interrupt.
+ * The highest vector is injected. Thus the latest bit set matches
+ * the highest bit in ISR.
+ */
+ apic->highest_isr_cache = vec;
+ }
}
static inline int apic_find_highest_isr(struct kvm_lapic *apic)
@@ -1451,7 +1472,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
vcpu->arch.apic_arb_prio = 0;
vcpu->arch.apic_attention = 0;
- apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr="
+ apic_debug("%s: vcpu=%p, id=%d, base_msr="
"0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
vcpu, kvm_apic_id(apic),
vcpu->arch.apic_base, apic->base_address);
@@ -1627,11 +1648,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
int vector = kvm_apic_has_interrupt(vcpu);
struct kvm_lapic *apic = vcpu->arch.apic;
- /* Note that we never get here with APIC virtualization enabled. */
-
if (vector == -1)
return -1;
+ /*
+ * We get here even with APIC virtualization enabled, if doing
+ * nested virtualization and L1 runs with the "acknowledge interrupt
+ * on exit" mode. Then we cannot inject the interrupt via RVI,
+ * because the process would deliver it through the IDT.
+ */
+
apic_set_isr(vector, apic);
apic_update_ppr(apic);
apic_clear_irr(vector, apic);
@@ -1895,7 +1921,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
/* evaluate pending_events before reading the vector */
smp_rmb();
sipi_vector = apic->sipi_vector;
- pr_debug("vcpu %d received sipi with vector # %x\n",
+ apic_debug("vcpu %d received sipi with vector # %x\n",
vcpu->vcpu_id, sipi_vector);
kvm_vcpu_deliver_sipi_vector(vcpu, sipi_vector);
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
index 1185fe7a7f47..9ade5cfb5a4c 100644
--- a/arch/x86/kvm/mmu_audit.c
+++ b/arch/x86/kvm/mmu_audit.c
@@ -273,7 +273,7 @@ static int mmu_audit_set(const char *val, const struct kernel_param *kp)
int ret;
unsigned long enable;
- ret = strict_strtoul(val, 10, &enable);
+ ret = kstrtoul(val, 10, &enable);
if (ret < 0)
return -EINVAL;
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index 9d2e0ffcb190..5aaf35641768 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -22,7 +22,7 @@
__entry->unsync = sp->unsync;
#define KVM_MMU_PAGE_PRINTK() ({ \
- const char *ret = p->buffer + p->len; \
+ const u32 saved_len = p->len; \
static const char *access_str[] = { \
"---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" \
}; \
@@ -41,7 +41,7 @@
role.nxe ? "" : "!", \
__entry->root_count, \
__entry->unsync ? "unsync" : "sync", 0); \
- ret; \
+ p->buffer + saved_len; \
})
#define kvm_mmu_trace_pferr_flags \
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index cbecaa90399c..3dd6accb64ec 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -428,6 +428,15 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
return 1;
}
+int kvm_pmu_check_pmc(struct kvm_vcpu *vcpu, unsigned pmc)
+{
+ struct kvm_pmu *pmu = &vcpu->arch.pmu;
+ bool fixed = pmc & (1u << 30);
+ pmc &= ~(3u << 30);
+ return (!fixed && pmc >= pmu->nr_arch_gp_counters) ||
+ (fixed && pmc >= pmu->nr_arch_fixed_counters);
+}
+
int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data)
{
struct kvm_pmu *pmu = &vcpu->arch.pmu;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index b5e994ad0135..ddf742768ecf 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -486,14 +486,14 @@ static int is_external_interrupt(u32 info)
return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
}
-static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
u32 ret = 0;
if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
- ret |= KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
- return ret & mask;
+ ret = KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
+ return ret;
}
static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
@@ -1415,7 +1415,16 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
- var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+
+ /*
+ * AMD CPUs circa 2014 track the G bit for all segments except CS.
+ * However, the SVM spec states that the G bit is not observed by the
+ * CPU, and some VMware virtual CPUs drop the G bit for all segments.
+ * So let's synthesize a legal G bit for all segments, this helps
+ * running KVM nested. It also helps cross-vendor migration, because
+ * Intel's vmentry has a check on the 'G' bit.
+ */
+ var->g = s->limit > 0xfffff;
/*
* AMD's VMCB does not have an explicit unusable field, so emulate it
@@ -1424,14 +1433,6 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
var->unusable = !var->present || (var->type == 0);
switch (seg) {
- case VCPU_SREG_CS:
- /*
- * SVM always stores 0 for the 'G' bit in the CS selector in
- * the VMCB on a VMEXIT. This hurts cross-vendor migration:
- * Intel's VMENTRY has a check on the 'G' bit.
- */
- var->g = s->limit > 0xfffff;
- break;
case VCPU_SREG_TR:
/*
* Work around a bug where the busy flag in the tr selector
@@ -2116,22 +2117,27 @@ static void nested_svm_unmap(struct page *page)
static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
{
- unsigned port;
- u8 val, bit;
+ unsigned port, size, iopm_len;
+ u16 val, mask;
+ u8 start_bit;
u64 gpa;
if (!(svm->nested.intercept & (1ULL << INTERCEPT_IOIO_PROT)))
return NESTED_EXIT_HOST;
port = svm->vmcb->control.exit_info_1 >> 16;
+ size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >>
+ SVM_IOIO_SIZE_SHIFT;
gpa = svm->nested.vmcb_iopm + (port / 8);
- bit = port % 8;
- val = 0;
+ start_bit = port % 8;
+ iopm_len = (start_bit + size > 8) ? 2 : 1;
+ mask = (0xf >> (4 - size)) << start_bit;
+ val = 0;
- if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, 1))
- val &= (1 << bit);
+ if (kvm_read_guest(svm->vcpu.kvm, gpa, &val, iopm_len))
+ return NESTED_EXIT_DONE;
- return val ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
+ return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
}
static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
@@ -4205,7 +4211,8 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
if (info->intercept == x86_intercept_cr_write)
icpt_info.exit_code += info->modrm_reg;
- if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0)
+ if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0 ||
+ info->intercept == x86_intercept_clts)
break;
intercept = svm->nested.intercept;
@@ -4250,14 +4257,14 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
u64 exit_info;
u32 bytes;
- exit_info = (vcpu->arch.regs[VCPU_REGS_RDX] & 0xffff) << 16;
-
if (info->intercept == x86_intercept_in ||
info->intercept == x86_intercept_ins) {
- exit_info |= SVM_IOIO_TYPE_MASK;
- bytes = info->src_bytes;
- } else {
+ exit_info = ((info->src_val & 0xffff) << 16) |
+ SVM_IOIO_TYPE_MASK;
bytes = info->dst_bytes;
+ } else {
+ exit_info = (info->dst_val & 0xffff) << 16;
+ bytes = info->src_bytes;
}
if (info->intercept == x86_intercept_outs ||
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 33574c95220d..e850a7d332be 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -721,10 +721,10 @@ TRACE_EVENT(kvm_emulate_insn,
),
TP_fast_assign(
- __entry->rip = vcpu->arch.emulate_ctxt.fetch.start;
__entry->csbase = kvm_x86_ops->get_segment_base(vcpu, VCPU_SREG_CS);
- __entry->len = vcpu->arch.emulate_ctxt._eip
- - vcpu->arch.emulate_ctxt.fetch.start;
+ __entry->len = vcpu->arch.emulate_ctxt.fetch.ptr
+ - vcpu->arch.emulate_ctxt.fetch.data;
+ __entry->rip = vcpu->arch.emulate_ctxt._eip - __entry->len;
memcpy(__entry->insn,
vcpu->arch.emulate_ctxt.fetch.data,
15);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 801332edefc3..bfe11cf124a1 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -383,6 +383,9 @@ struct nested_vmx {
struct hrtimer preemption_timer;
bool preemption_timer_expired;
+
+ /* to migrate it to L2 if VM_ENTRY_LOAD_DEBUG_CONTROLS is off */
+ u64 vmcs01_debugctl;
};
#define POSTED_INTR_ON 0
@@ -740,7 +743,6 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var);
static void vmx_sync_pir_to_irr_dummy(struct kvm_vcpu *vcpu);
static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx);
static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx);
-static bool vmx_mpx_supported(void);
static DEFINE_PER_CPU(struct vmcs *, vmxarea);
static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -820,7 +822,6 @@ static const u32 vmx_msr_index[] = {
#endif
MSR_EFER, MSR_TSC_AUX, MSR_STAR,
};
-#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
static inline bool is_page_fault(u32 intr_info)
{
@@ -1940,7 +1941,7 @@ static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
vmcs_writel(GUEST_RFLAGS, rflags);
}
-static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu)
{
u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
int ret = 0;
@@ -1950,7 +1951,7 @@ static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
if (interruptibility & GUEST_INTR_STATE_MOV_SS)
ret |= KVM_X86_SHADOW_INT_MOV_SS;
- return ret & mask;
+ return ret;
}
static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
@@ -2239,10 +2240,13 @@ static inline bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
* or other means.
*/
static u32 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high;
+static u32 nested_vmx_true_procbased_ctls_low;
static u32 nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high;
static u32 nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high;
static u32 nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high;
+static u32 nested_vmx_true_exit_ctls_low;
static u32 nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high;
+static u32 nested_vmx_true_entry_ctls_low;
static u32 nested_vmx_misc_low, nested_vmx_misc_high;
static u32 nested_vmx_ept_caps;
static __init void nested_vmx_setup_ctls_msrs(void)
@@ -2265,21 +2269,13 @@ static __init void nested_vmx_setup_ctls_msrs(void)
/* pin-based controls */
rdmsr(MSR_IA32_VMX_PINBASED_CTLS,
nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high);
- /*
- * According to the Intel spec, if bit 55 of VMX_BASIC is off (as it is
- * in our case), bits 1, 2 and 4 (i.e., 0x16) must be 1 in this MSR.
- */
nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK |
PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS;
nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
PIN_BASED_VMX_PREEMPTION_TIMER;
- /*
- * Exit controls
- * If bit 55 of VMX_BASIC is off, bits 0-8 and 10, 11, 13, 14, 16 and
- * 17 must be 1.
- */
+ /* exit controls */
rdmsr(MSR_IA32_VMX_EXIT_CTLS,
nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high);
nested_vmx_exit_ctls_low = VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
@@ -2296,10 +2292,13 @@ static __init void nested_vmx_setup_ctls_msrs(void)
if (vmx_mpx_supported())
nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
+ /* We support free control of debug control saving. */
+ nested_vmx_true_exit_ctls_low = nested_vmx_exit_ctls_low &
+ ~VM_EXIT_SAVE_DEBUG_CONTROLS;
+
/* entry controls */
rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high);
- /* If bit 55 of VMX_BASIC is off, bits 0-8 and 12 must be 1. */
nested_vmx_entry_ctls_low = VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
nested_vmx_entry_ctls_high &=
#ifdef CONFIG_X86_64
@@ -2311,10 +2310,14 @@ static __init void nested_vmx_setup_ctls_msrs(void)
if (vmx_mpx_supported())
nested_vmx_entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
+ /* We support free control of debug control loading. */
+ nested_vmx_true_entry_ctls_low = nested_vmx_entry_ctls_low &
+ ~VM_ENTRY_LOAD_DEBUG_CONTROLS;
+
/* cpu-based controls */
rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high);
- nested_vmx_procbased_ctls_low = 0;
+ nested_vmx_procbased_ctls_low = CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
nested_vmx_procbased_ctls_high &=
CPU_BASED_VIRTUAL_INTR_PENDING |
CPU_BASED_VIRTUAL_NMI_PENDING | CPU_BASED_USE_TSC_OFFSETING |
@@ -2335,7 +2338,12 @@ static __init void nested_vmx_setup_ctls_msrs(void)
* can use it to avoid exits to L1 - even when L0 runs L2
* without MSR bitmaps.
*/
- nested_vmx_procbased_ctls_high |= CPU_BASED_USE_MSR_BITMAPS;
+ nested_vmx_procbased_ctls_high |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
+ CPU_BASED_USE_MSR_BITMAPS;
+
+ /* We support free control of CR3 access interception. */
+ nested_vmx_true_procbased_ctls_low = nested_vmx_procbased_ctls_low &
+ ~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
/* secondary cpu-based controls */
rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
@@ -2394,7 +2402,7 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
* guest, and the VMCS structure we give it - not about the
* VMX support of the underlying hardware.
*/
- *pdata = VMCS12_REVISION |
+ *pdata = VMCS12_REVISION | VMX_BASIC_TRUE_CTLS |
((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
(VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
break;
@@ -2404,16 +2412,25 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
nested_vmx_pinbased_ctls_high);
break;
case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_true_procbased_ctls_low,
+ nested_vmx_procbased_ctls_high);
+ break;
case MSR_IA32_VMX_PROCBASED_CTLS:
*pdata = vmx_control_msr(nested_vmx_procbased_ctls_low,
nested_vmx_procbased_ctls_high);
break;
case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_true_exit_ctls_low,
+ nested_vmx_exit_ctls_high);
+ break;
case MSR_IA32_VMX_EXIT_CTLS:
*pdata = vmx_control_msr(nested_vmx_exit_ctls_low,
nested_vmx_exit_ctls_high);
break;
case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+ *pdata = vmx_control_msr(nested_vmx_true_entry_ctls_low,
+ nested_vmx_entry_ctls_high);
+ break;
case MSR_IA32_VMX_ENTRY_CTLS:
*pdata = vmx_control_msr(nested_vmx_entry_ctls_low,
nested_vmx_entry_ctls_high);
@@ -2442,7 +2459,7 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
*pdata = -1ULL;
break;
case MSR_IA32_VMX_VMCS_ENUM:
- *pdata = 0x1f;
+ *pdata = 0x2e; /* highest index: VMX_PREEMPTION_TIMER_VALUE */
break;
case MSR_IA32_VMX_PROCBASED_CTLS2:
*pdata = vmx_control_msr(nested_vmx_secondary_ctls_low,
@@ -3653,7 +3670,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
out:
- vmx->emulation_required |= emulation_required(vcpu);
+ vmx->emulation_required = emulation_required(vcpu);
}
static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
@@ -4422,7 +4439,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmx->vcpu.arch.pat = host_pat;
}
- for (i = 0; i < NR_VMX_MSR; ++i) {
+ for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) {
u32 index = vmx_msr_index[i];
u32 data_low, data_high;
int j = vmx->nmsrs;
@@ -4873,7 +4890,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
if (!(vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
vcpu->arch.dr6 &= ~15;
- vcpu->arch.dr6 |= dr6;
+ vcpu->arch.dr6 |= dr6 | DR6_RTM;
if (!(dr6 & ~DR6_RESERVED)) /* icebp */
skip_emulated_instruction(vcpu);
@@ -5039,7 +5056,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
reg = (exit_qualification >> 8) & 15;
switch ((exit_qualification >> 4) & 3) {
case 0: /* mov to cr */
- val = kvm_register_read(vcpu, reg);
+ val = kvm_register_readl(vcpu, reg);
trace_kvm_cr_write(cr, val);
switch (cr) {
case 0:
@@ -5056,7 +5073,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
return 1;
case 8: {
u8 cr8_prev = kvm_get_cr8(vcpu);
- u8 cr8 = kvm_register_read(vcpu, reg);
+ u8 cr8 = (u8)val;
err = kvm_set_cr8(vcpu, cr8);
kvm_complete_insn_gp(vcpu, err);
if (irqchip_in_kernel(vcpu->kvm))
@@ -5132,7 +5149,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
return 0;
} else {
vcpu->arch.dr7 &= ~DR7_GD;
- vcpu->arch.dr6 |= DR6_BD;
+ vcpu->arch.dr6 |= DR6_BD | DR6_RTM;
vmcs_writel(GUEST_DR7, vcpu->arch.dr7);
kvm_queue_exception(vcpu, DB_VECTOR);
return 1;
@@ -5165,7 +5182,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
return 1;
kvm_register_write(vcpu, reg, val);
} else
- if (kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)))
+ if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
return 1;
skip_emulated_instruction(vcpu);
@@ -5621,7 +5638,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
- while (!guest_state_valid(vcpu) && count-- != 0) {
+ while (vmx->emulation_required && count-- != 0) {
if (intr_window_requested && vmx_interrupt_allowed(vcpu))
return handle_interrupt_window(&vmx->vcpu);
@@ -5655,7 +5672,6 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
schedule();
}
- vmx->emulation_required = emulation_required(vcpu);
out:
return ret;
}
@@ -5754,22 +5770,27 @@ static void nested_free_vmcs02(struct vcpu_vmx *vmx, gpa_t vmptr)
/*
* Free all VMCSs saved for this vcpu, except the one pointed by
- * vmx->loaded_vmcs. These include the VMCSs in vmcs02_pool (except the one
- * currently used, if running L2), and vmcs01 when running L2.
+ * vmx->loaded_vmcs. We must be running L1, so vmx->loaded_vmcs
+ * must be &vmx->vmcs01.
*/
static void nested_free_all_saved_vmcss(struct vcpu_vmx *vmx)
{
struct vmcs02_list *item, *n;
+
+ WARN_ON(vmx->loaded_vmcs != &vmx->vmcs01);
list_for_each_entry_safe(item, n, &vmx->nested.vmcs02_pool, list) {
- if (vmx->loaded_vmcs != &item->vmcs02)
- free_loaded_vmcs(&item->vmcs02);
+ /*
+ * Something will leak if the above WARN triggers. Better than
+ * a use-after-free.
+ */
+ if (vmx->loaded_vmcs == &item->vmcs02)
+ continue;
+
+ free_loaded_vmcs(&item->vmcs02);
list_del(&item->list);
kfree(item);
+ vmx->nested.vmcs02_num--;
}
- vmx->nested.vmcs02_num = 0;
-
- if (vmx->loaded_vmcs != &vmx->vmcs01)
- free_loaded_vmcs(&vmx->vmcs01);
}
/*
@@ -5918,7 +5939,7 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
* which replaces physical address width with 32
*
*/
- if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
nested_vmx_failInvalid(vcpu);
skip_emulated_instruction(vcpu);
return 1;
@@ -5936,7 +5957,7 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
vmx->nested.vmxon_ptr = vmptr;
break;
case EXIT_REASON_VMCLEAR:
- if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
nested_vmx_failValid(vcpu,
VMXERR_VMCLEAR_INVALID_ADDRESS);
skip_emulated_instruction(vcpu);
@@ -5951,7 +5972,7 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
}
break;
case EXIT_REASON_VMPTRLD:
- if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
+ if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
nested_vmx_failValid(vcpu,
VMXERR_VMPTRLD_INVALID_ADDRESS);
skip_emulated_instruction(vcpu);
@@ -6086,20 +6107,27 @@ static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
static inline void nested_release_vmcs12(struct vcpu_vmx *vmx)
{
u32 exec_control;
+ if (vmx->nested.current_vmptr == -1ull)
+ return;
+
+ /* current_vmptr and current_vmcs12 are always set/reset together */
+ if (WARN_ON(vmx->nested.current_vmcs12 == NULL))
+ return;
+
if (enable_shadow_vmcs) {
- if (vmx->nested.current_vmcs12 != NULL) {
- /* copy to memory all shadowed fields in case
- they were modified */
- copy_shadow_to_vmcs12(vmx);
- vmx->nested.sync_shadow_vmcs = false;
- exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
- exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
- vmcs_write64(VMCS_LINK_POINTER, -1ull);
- }
+ /* copy to memory all shadowed fields in case
+ they were modified */
+ copy_shadow_to_vmcs12(vmx);
+ vmx->nested.sync_shadow_vmcs = false;
+ exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+ exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS;
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ vmcs_write64(VMCS_LINK_POINTER, -1ull);
}
kunmap(vmx->nested.current_vmcs12_page);
nested_release_page(vmx->nested.current_vmcs12_page);
+ vmx->nested.current_vmptr = -1ull;
+ vmx->nested.current_vmcs12 = NULL;
}
/*
@@ -6110,12 +6138,9 @@ static void free_nested(struct vcpu_vmx *vmx)
{
if (!vmx->nested.vmxon)
return;
+
vmx->nested.vmxon = false;
- if (vmx->nested.current_vmptr != -1ull) {
- nested_release_vmcs12(vmx);
- vmx->nested.current_vmptr = -1ull;
- vmx->nested.current_vmcs12 = NULL;
- }
+ nested_release_vmcs12(vmx);
if (enable_shadow_vmcs)
free_vmcs(vmx->nested.current_shadow_vmcs);
/* Unpin physical memory we referred to in current vmcs02 */
@@ -6152,11 +6177,8 @@ static int handle_vmclear(struct kvm_vcpu *vcpu)
if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr))
return 1;
- if (vmptr == vmx->nested.current_vmptr) {
+ if (vmptr == vmx->nested.current_vmptr)
nested_release_vmcs12(vmx);
- vmx->nested.current_vmptr = -1ull;
- vmx->nested.current_vmcs12 = NULL;
- }
page = nested_get_page(vcpu, vmptr);
if (page == NULL) {
@@ -6384,7 +6406,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
return 1;
/* Decode instruction info and find the field to read */
- field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
/* Read the field, zero-extended to a u64 field_value */
if (!vmcs12_read_any(vcpu, field, &field_value)) {
nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
@@ -6397,7 +6419,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
* on the guest's mode (32 or 64 bit), not on the given field's length.
*/
if (vmx_instruction_info & (1u << 10)) {
- kvm_register_write(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+ kvm_register_writel(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
field_value);
} else {
if (get_vmx_mem_address(vcpu, exit_qualification,
@@ -6434,21 +6456,21 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
return 1;
if (vmx_instruction_info & (1u << 10))
- field_value = kvm_register_read(vcpu,
+ field_value = kvm_register_readl(vcpu,
(((vmx_instruction_info) >> 3) & 0xf));
else {
if (get_vmx_mem_address(vcpu, exit_qualification,
vmx_instruction_info, &gva))
return 1;
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
- &field_value, (is_long_mode(vcpu) ? 8 : 4), &e)) {
+ &field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
}
- field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
if (vmcs_field_readonly(field)) {
nested_vmx_failValid(vcpu,
VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
@@ -6498,9 +6520,8 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
skip_emulated_instruction(vcpu);
return 1;
}
- if (vmx->nested.current_vmptr != -1ull)
- nested_release_vmcs12(vmx);
+ nested_release_vmcs12(vmx);
vmx->nested.current_vmptr = vmptr;
vmx->nested.current_vmcs12 = new_vmcs12;
vmx->nested.current_vmcs12_page = page;
@@ -6571,7 +6592,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
}
vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
- type = kvm_register_read(vcpu, (vmx_instruction_info >> 28) & 0xf);
+ type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
types = (nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6;
@@ -6751,7 +6772,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
int cr = exit_qualification & 15;
int reg = (exit_qualification >> 8) & 15;
- unsigned long val = kvm_register_read(vcpu, reg);
+ unsigned long val = kvm_register_readl(vcpu, reg);
switch ((exit_qualification >> 4) & 3) {
case 0: /* mov to cr */
@@ -7112,7 +7133,26 @@ static void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
if (max_irr == -1)
return;
- vmx_set_rvi(max_irr);
+ /*
+ * If a vmexit is needed, vmx_check_nested_events handles it.
+ */
+ if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+ return;
+
+ if (!is_guest_mode(vcpu)) {
+ vmx_set_rvi(max_irr);
+ return;
+ }
+
+ /*
+ * Fall back to pre-APICv interrupt injection since L2
+ * is run without virtual interrupt delivery.
+ */
+ if (!kvm_event_needs_reinjection(vcpu) &&
+ vmx_interrupt_allowed(vcpu)) {
+ kvm_queue_interrupt(vcpu, max_irr, false);
+ vmx_inject_irq(vcpu);
+ }
}
static void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
@@ -7520,13 +7560,31 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmx_complete_interrupts(vmx);
}
+static void vmx_load_vmcs01(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ int cpu;
+
+ if (vmx->loaded_vmcs == &vmx->vmcs01)
+ return;
+
+ cpu = get_cpu();
+ vmx->loaded_vmcs = &vmx->vmcs01;
+ vmx_vcpu_put(vcpu);
+ vmx_vcpu_load(vcpu, cpu);
+ vcpu->cpu = cpu;
+ put_cpu();
+}
+
static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
free_vpid(vmx);
- free_loaded_vmcs(vmx->loaded_vmcs);
+ leave_guest_mode(vcpu);
+ vmx_load_vmcs01(vcpu);
free_nested(vmx);
+ free_loaded_vmcs(vmx->loaded_vmcs);
kfree(vmx->guest_msrs);
kvm_vcpu_uninit(vcpu);
kmem_cache_free(kvm_vcpu_cache, vmx);
@@ -7548,6 +7606,9 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
goto free_vcpu;
vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
+ > PAGE_SIZE);
+
err = -ENOMEM;
if (!vmx->guest_msrs) {
goto uninit_vcpu;
@@ -7836,7 +7897,13 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
- vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+ if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) {
+ kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
+ } else {
+ kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
+ vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl);
+ }
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
vmcs12->vm_entry_intr_info_field);
vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
@@ -7846,7 +7913,6 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
vmcs12->guest_interruptibility_info);
vmcs_write32(GUEST_SYSENTER_CS, vmcs12->guest_sysenter_cs);
- kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
vmx_set_rflags(vcpu, vmcs12->guest_rflags);
vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS,
vmcs12->guest_pending_dbg_exceptions);
@@ -8113,14 +8179,14 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
}
if ((vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_MSR_BITMAPS) &&
- !IS_ALIGNED(vmcs12->msr_bitmap, PAGE_SIZE)) {
+ !PAGE_ALIGNED(vmcs12->msr_bitmap)) {
/*TODO: Also verify bits beyond physical address width are 0*/
nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
return 1;
}
if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES) &&
- !IS_ALIGNED(vmcs12->apic_access_addr, PAGE_SIZE)) {
+ !PAGE_ALIGNED(vmcs12->apic_access_addr)) {
/*TODO: Also verify bits beyond physical address width are 0*/
nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
return 1;
@@ -8136,15 +8202,18 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
}
if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
- nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high) ||
+ nested_vmx_true_procbased_ctls_low,
+ nested_vmx_procbased_ctls_high) ||
!vmx_control_verify(vmcs12->secondary_vm_exec_control,
nested_vmx_secondary_ctls_low, nested_vmx_secondary_ctls_high) ||
!vmx_control_verify(vmcs12->pin_based_vm_exec_control,
nested_vmx_pinbased_ctls_low, nested_vmx_pinbased_ctls_high) ||
!vmx_control_verify(vmcs12->vm_exit_controls,
- nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high) ||
+ nested_vmx_true_exit_ctls_low,
+ nested_vmx_exit_ctls_high) ||
!vmx_control_verify(vmcs12->vm_entry_controls,
- nested_vmx_entry_ctls_low, nested_vmx_entry_ctls_high))
+ nested_vmx_true_entry_ctls_low,
+ nested_vmx_entry_ctls_high))
{
nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
return 1;
@@ -8221,6 +8290,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET);
+ if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
+ vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+
cpu = get_cpu();
vmx->loaded_vmcs = vmcs02;
vmx_vcpu_put(vcpu);
@@ -8398,7 +8470,6 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
vmcs12->guest_cr0 = vmcs12_guest_cr0(vcpu, vmcs12);
vmcs12->guest_cr4 = vmcs12_guest_cr4(vcpu, vmcs12);
- kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
vmcs12->guest_rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
vmcs12->guest_rip = kvm_register_read(vcpu, VCPU_REGS_RIP);
vmcs12->guest_rflags = vmcs_readl(GUEST_RFLAGS);
@@ -8477,9 +8548,13 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
(vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
(vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
+ if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS) {
+ kvm_get_dr(vcpu, 7, (unsigned long *)&vmcs12->guest_dr7);
+ vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+ }
+
/* TODO: These cannot have changed unless we have MSR bitmaps and
* the relevant bit asks not to trap the change */
- vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT)
vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
@@ -8670,7 +8745,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
unsigned long exit_qualification)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- int cpu;
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
/* trying to cancel vmlaunch/vmresume is a bug */
@@ -8680,6 +8754,8 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
exit_qualification);
+ vmx_load_vmcs01(vcpu);
+
if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
&& nested_exit_intr_ack_set(vcpu)) {
int irq = kvm_cpu_get_interrupt(vcpu);
@@ -8695,13 +8771,6 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
vmcs12->vm_exit_intr_error_code,
KVM_ISA_VMX);
- cpu = get_cpu();
- vmx->loaded_vmcs = &vmx->vmcs01;
- vmx_vcpu_put(vcpu);
- vmx_vcpu_load(vcpu, cpu);
- vcpu->cpu = cpu;
- put_cpu();
-
vm_entry_controls_init(vmx, vmcs_read32(VM_ENTRY_CONTROLS));
vm_exit_controls_init(vmx, vmcs_read32(VM_EXIT_CONTROLS));
vmx_segment_cache_clear(vmx);
@@ -8890,7 +8959,7 @@ static int __init vmx_init(void)
rdmsrl_safe(MSR_EFER, &host_efer);
- for (i = 0; i < NR_VMX_MSR; ++i)
+ for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i)
kvm_define_shared_msr(i, vmx_msr_index[i]);
vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ef432f891d30..8f1e22d3b286 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -87,6 +87,7 @@ static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
static void update_cr8_intercept(struct kvm_vcpu *vcpu);
static void process_nmi(struct kvm_vcpu *vcpu);
+static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
struct kvm_x86_ops *kvm_x86_ops;
EXPORT_SYMBOL_GPL(kvm_x86_ops);
@@ -211,6 +212,7 @@ static void shared_msr_update(unsigned slot, u32 msr)
void kvm_define_shared_msr(unsigned slot, u32 msr)
{
+ BUG_ON(slot >= KVM_NR_SHARED_MSRS);
if (slot >= shared_msrs_global.nr)
shared_msrs_global.nr = slot + 1;
shared_msrs_global.msrs[slot] = msr;
@@ -310,6 +312,31 @@ static int exception_class(int vector)
return EXCPT_BENIGN;
}
+#define EXCPT_FAULT 0
+#define EXCPT_TRAP 1
+#define EXCPT_ABORT 2
+#define EXCPT_INTERRUPT 3
+
+static int exception_type(int vector)
+{
+ unsigned int mask;
+
+ if (WARN_ON(vector > 31 || vector == NMI_VECTOR))
+ return EXCPT_INTERRUPT;
+
+ mask = 1 << vector;
+
+ /* #DB is trap, as instruction watchpoints are handled elsewhere */
+ if (mask & ((1 << DB_VECTOR) | (1 << BP_VECTOR) | (1 << OF_VECTOR)))
+ return EXCPT_TRAP;
+
+ if (mask & ((1 << DF_VECTOR) | (1 << MC_VECTOR)))
+ return EXCPT_ABORT;
+
+ /* Reserved exceptions will result in fault */
+ return EXCPT_FAULT;
+}
+
static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
unsigned nr, bool has_error, u32 error_code,
bool reinject)
@@ -758,6 +785,15 @@ static void kvm_update_dr7(struct kvm_vcpu *vcpu)
vcpu->arch.switch_db_regs |= KVM_DEBUGREG_BP_ENABLED;
}
+static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu)
+{
+ u64 fixed = DR6_FIXED_1;
+
+ if (!guest_cpuid_has_rtm(vcpu))
+ fixed |= DR6_RTM;
+ return fixed;
+}
+
static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
{
switch (dr) {
@@ -773,7 +809,7 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
case 6:
if (val & 0xffffffff00000000ULL)
return -1; /* #GP */
- vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
+ vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu);
kvm_update_dr6(vcpu);
break;
case 5:
@@ -984,9 +1020,8 @@ struct pvclock_gtod_data {
u32 shift;
} clock;
- /* open coded 'struct timespec' */
- u64 monotonic_time_snsec;
- time_t monotonic_time_sec;
+ u64 boot_ns;
+ u64 nsec_base;
};
static struct pvclock_gtod_data pvclock_gtod_data;
@@ -994,27 +1029,21 @@ static struct pvclock_gtod_data pvclock_gtod_data;
static void update_pvclock_gtod(struct timekeeper *tk)
{
struct pvclock_gtod_data *vdata = &pvclock_gtod_data;
+ u64 boot_ns;
+
+ boot_ns = ktime_to_ns(ktime_add(tk->tkr.base_mono, tk->offs_boot));
write_seqcount_begin(&vdata->seq);
/* copy pvclock gtod data */
- vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
- vdata->clock.cycle_last = tk->clock->cycle_last;
- vdata->clock.mask = tk->clock->mask;
- vdata->clock.mult = tk->mult;
- vdata->clock.shift = tk->shift;
-
- vdata->monotonic_time_sec = tk->xtime_sec
- + tk->wall_to_monotonic.tv_sec;
- vdata->monotonic_time_snsec = tk->xtime_nsec
- + (tk->wall_to_monotonic.tv_nsec
- << tk->shift);
- while (vdata->monotonic_time_snsec >=
- (((u64)NSEC_PER_SEC) << tk->shift)) {
- vdata->monotonic_time_snsec -=
- ((u64)NSEC_PER_SEC) << tk->shift;
- vdata->monotonic_time_sec++;
- }
+ vdata->clock.vclock_mode = tk->tkr.clock->archdata.vclock_mode;
+ vdata->clock.cycle_last = tk->tkr.cycle_last;
+ vdata->clock.mask = tk->tkr.mask;
+ vdata->clock.mult = tk->tkr.mult;
+ vdata->clock.shift = tk->tkr.shift;
+
+ vdata->boot_ns = boot_ns;
+ vdata->nsec_base = tk->tkr.xtime_nsec;
write_seqcount_end(&vdata->seq);
}
@@ -1109,11 +1138,7 @@ static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
static inline u64 get_kernel_ns(void)
{
- struct timespec ts;
-
- ktime_get_ts(&ts);
- monotonic_to_bootbased(&ts);
- return timespec_to_ns(&ts);
+ return ktime_get_boot_ns();
}
#ifdef CONFIG_X86_64
@@ -1215,6 +1240,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
unsigned long flags;
s64 usdiff;
bool matched;
+ bool already_matched;
u64 data = msr->data;
raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
@@ -1279,6 +1305,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
}
matched = true;
+ already_matched = (vcpu->arch.this_tsc_generation == kvm->arch.cur_tsc_generation);
} else {
/*
* We split periods of matched TSC writes into generations.
@@ -1294,7 +1321,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
kvm->arch.cur_tsc_write = data;
kvm->arch.cur_tsc_offset = offset;
matched = false;
- pr_debug("kvm: new tsc generation %u, clock %llu\n",
+ pr_debug("kvm: new tsc generation %llu, clock %llu\n",
kvm->arch.cur_tsc_generation, data);
}
@@ -1319,10 +1346,11 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
spin_lock(&kvm->arch.pvclock_gtod_sync_lock);
- if (matched)
- kvm->arch.nr_vcpus_matched_tsc++;
- else
+ if (!matched) {
kvm->arch.nr_vcpus_matched_tsc = 0;
+ } else if (!already_matched) {
+ kvm->arch.nr_vcpus_matched_tsc++;
+ }
kvm_track_tsc_matching(vcpu);
spin_unlock(&kvm->arch.pvclock_gtod_sync_lock);
@@ -1375,23 +1403,22 @@ static inline u64 vgettsc(cycle_t *cycle_now)
return v * gtod->clock.mult;
}
-static int do_monotonic(struct timespec *ts, cycle_t *cycle_now)
+static int do_monotonic_boot(s64 *t, cycle_t *cycle_now)
{
+ struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
unsigned long seq;
- u64 ns;
int mode;
- struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+ u64 ns;
- ts->tv_nsec = 0;
do {
seq = read_seqcount_begin(&gtod->seq);
mode = gtod->clock.vclock_mode;
- ts->tv_sec = gtod->monotonic_time_sec;
- ns = gtod->monotonic_time_snsec;
+ ns = gtod->nsec_base;
ns += vgettsc(cycle_now);
ns >>= gtod->clock.shift;
+ ns += gtod->boot_ns;
} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
- timespec_add_ns(ts, ns);
+ *t = ns;
return mode;
}
@@ -1399,19 +1426,11 @@ static int do_monotonic(struct timespec *ts, cycle_t *cycle_now)
/* returns true if host is using tsc clocksource */
static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
{
- struct timespec ts;
-
/* checked again under seqlock below */
if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
return false;
- if (do_monotonic(&ts, cycle_now) != VCLOCK_TSC)
- return false;
-
- monotonic_to_bootbased(&ts);
- *kernel_ns = timespec_to_ns(&ts);
-
- return true;
+ return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
}
#endif
@@ -2032,6 +2051,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
data &= ~(u64)0x40; /* ignore flush filter disable */
data &= ~(u64)0x100; /* ignore ignne emulation enable */
data &= ~(u64)0x8; /* ignore TLB cache disable */
+ data &= ~(u64)0x40000; /* ignore Mc status write enable */
if (data != 0) {
vcpu_unimpl(vcpu, "unimplemented HWCR wrmsr: 0x%llx\n",
data);
@@ -2616,7 +2636,7 @@ out:
return r;
}
-int kvm_dev_ioctl_check_extension(long ext)
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
@@ -2974,9 +2994,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft;
events->interrupt.nr = vcpu->arch.interrupt.nr;
events->interrupt.soft = 0;
- events->interrupt.shadow =
- kvm_x86_ops->get_interrupt_shadow(vcpu,
- KVM_X86_SHADOW_INT_MOV_SS | KVM_X86_SHADOW_INT_STI);
+ events->interrupt.shadow = kvm_x86_ops->get_interrupt_shadow(vcpu);
events->nmi.injected = vcpu->arch.nmi_injected;
events->nmi.pending = vcpu->arch.nmi_pending != 0;
@@ -4082,7 +4100,8 @@ static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
if (gpa == UNMAPPED_GVA)
return X86EMUL_PROPAGATE_FAULT;
- ret = kvm_read_guest(vcpu->kvm, gpa, data, toread);
+ ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, data,
+ offset, toread);
if (ret < 0) {
r = X86EMUL_IO_NEEDED;
goto out;
@@ -4103,10 +4122,24 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+ unsigned offset;
+ int ret;
- return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
- access | PFERR_FETCH_MASK,
- exception);
+ /* Inline kvm_read_guest_virt_helper for speed. */
+ gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr, access|PFERR_FETCH_MASK,
+ exception);
+ if (unlikely(gpa == UNMAPPED_GVA))
+ return X86EMUL_PROPAGATE_FAULT;
+
+ offset = addr & (PAGE_SIZE-1);
+ if (WARN_ON(offset + bytes > PAGE_SIZE))
+ bytes = (unsigned)PAGE_SIZE - offset;
+ ret = kvm_read_guest_page(vcpu->kvm, gpa >> PAGE_SHIFT, val,
+ offset, bytes);
+ if (unlikely(ret < 0))
+ return X86EMUL_IO_NEEDED;
+
+ return X86EMUL_CONTINUE;
}
int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
@@ -4730,7 +4763,6 @@ static void emulator_set_segment(struct x86_emulate_ctxt *ctxt, u16 selector,
if (desc->g)
var.limit = (var.limit << 12) | 0xfff;
var.type = desc->type;
- var.present = desc->p;
var.dpl = desc->dpl;
var.db = desc->d;
var.s = desc->s;
@@ -4762,6 +4794,12 @@ static int emulator_set_msr(struct x86_emulate_ctxt *ctxt,
return kvm_set_msr(emul_to_vcpu(ctxt), &msr);
}
+static int emulator_check_pmc(struct x86_emulate_ctxt *ctxt,
+ u32 pmc)
+{
+ return kvm_pmu_check_pmc(emul_to_vcpu(ctxt), pmc);
+}
+
static int emulator_read_pmc(struct x86_emulate_ctxt *ctxt,
u32 pmc, u64 *pdata)
{
@@ -4838,6 +4876,7 @@ static const struct x86_emulate_ops emulate_ops = {
.set_dr = emulator_set_dr,
.set_msr = emulator_set_msr,
.get_msr = emulator_get_msr,
+ .check_pmc = emulator_check_pmc,
.read_pmc = emulator_read_pmc,
.halt = emulator_halt,
.wbinvd = emulator_wbinvd,
@@ -4850,7 +4889,7 @@ static const struct x86_emulate_ops emulate_ops = {
static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
{
- u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu, mask);
+ u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu);
/*
* an sti; sti; sequence only disable interrupts for the first
* instruction. So, if the last instruction, be it emulated or
@@ -4858,8 +4897,13 @@ static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
* means that the last instruction is an sti. We should not
* leave the flag on in this case. The same goes for mov ss
*/
- if (!(int_shadow & mask))
+ if (int_shadow & mask)
+ mask = 0;
+ if (unlikely(int_shadow || mask)) {
kvm_x86_ops->set_interrupt_shadow(vcpu, mask);
+ if (!mask)
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
+ }
}
static void inject_emulated_exception(struct kvm_vcpu *vcpu)
@@ -4874,19 +4918,6 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
kvm_queue_exception(vcpu, ctxt->exception.vector);
}
-static void init_decode_cache(struct x86_emulate_ctxt *ctxt)
-{
- memset(&ctxt->opcode_len, 0,
- (void *)&ctxt->_regs - (void *)&ctxt->opcode_len);
-
- ctxt->fetch.start = 0;
- ctxt->fetch.end = 0;
- ctxt->io_read.pos = 0;
- ctxt->io_read.end = 0;
- ctxt->mem_read.pos = 0;
- ctxt->mem_read.end = 0;
-}
-
static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
{
struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
@@ -5085,23 +5116,22 @@ static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7,
return dr6;
}
-static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, int *r)
+static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r)
{
struct kvm_run *kvm_run = vcpu->run;
/*
- * Use the "raw" value to see if TF was passed to the processor.
- * Note that the new value of the flags has not been saved yet.
+ * rflags is the old, "raw" value of the flags. The new value has
+ * not been saved yet.
*
* This is correct even for TF set by the guest, because "the
* processor will not generate this exception after the instruction
* that sets the TF flag".
*/
- unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
-
if (unlikely(rflags & X86_EFLAGS_TF)) {
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
- kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1;
+ kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 |
+ DR6_RTM;
kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG;
@@ -5114,7 +5144,7 @@ static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, int *r)
* cleared by the processor".
*/
vcpu->arch.dr6 &= ~15;
- vcpu->arch.dr6 |= DR6_BS;
+ vcpu->arch.dr6 |= DR6_BS | DR6_RTM;
kvm_queue_exception(vcpu, DB_VECTOR);
}
}
@@ -5133,7 +5163,7 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
vcpu->arch.eff_db);
if (dr6 != 0) {
- kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1;
+ kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM;
kvm_run->debug.arch.pc = kvm_rip_read(vcpu) +
get_segment_base(vcpu, VCPU_SREG_CS);
@@ -5144,14 +5174,15 @@ static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
}
}
- if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK)) {
+ if (unlikely(vcpu->arch.dr7 & DR7_BP_EN_MASK) &&
+ !(kvm_get_rflags(vcpu) & X86_EFLAGS_RF)) {
dr6 = kvm_vcpu_check_hw_bp(eip, 0,
vcpu->arch.dr7,
vcpu->arch.db);
if (dr6 != 0) {
vcpu->arch.dr6 &= ~15;
- vcpu->arch.dr6 |= dr6;
+ vcpu->arch.dr6 |= dr6 | DR6_RTM;
kvm_queue_exception(vcpu, DB_VECTOR);
*r = EMULATE_DONE;
return true;
@@ -5215,6 +5246,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
if (emulation_type & EMULTYPE_SKIP) {
kvm_rip_write(vcpu, ctxt->_eip);
+ if (ctxt->eflags & X86_EFLAGS_RF)
+ kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
return EMULATE_DONE;
}
@@ -5265,13 +5298,22 @@ restart:
r = EMULATE_DONE;
if (writeback) {
+ unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
toggle_interruptibility(vcpu, ctxt->interruptibility);
- kvm_make_request(KVM_REQ_EVENT, vcpu);
vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
kvm_rip_write(vcpu, ctxt->eip);
if (r == EMULATE_DONE)
- kvm_vcpu_check_singlestep(vcpu, &r);
- kvm_set_rflags(vcpu, ctxt->eflags);
+ kvm_vcpu_check_singlestep(vcpu, rflags, &r);
+ __kvm_set_rflags(vcpu, ctxt->eflags);
+
+ /*
+ * For STI, interrupts are shadowed; so KVM_REQ_EVENT will
+ * do nothing, and it will be requested again as soon as
+ * the shadow expires. But we still need to check here,
+ * because POPF has no interrupt shadow.
+ */
+ if (unlikely((ctxt->eflags & ~rflags) & X86_EFLAGS_IF))
+ kvm_make_request(KVM_REQ_EVENT, vcpu);
} else
vcpu->arch.emulate_regs_need_sync_to_vcpu = true;
@@ -5662,7 +5704,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
u64 param, ingpa, outgpa, ret;
uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
bool fast, longmode;
- int cs_db, cs_l;
/*
* hypercall generates UD from non zero cpl and real mode
@@ -5673,8 +5714,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 0;
}
- kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
- longmode = is_long_mode(vcpu) && cs_l == 1;
+ longmode = is_64_bit_mode(vcpu);
if (!longmode) {
param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
@@ -5739,7 +5779,7 @@ static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
- int r = 1;
+ int op_64_bit, r = 1;
if (kvm_hv_hypercall_enabled(vcpu->kvm))
return kvm_hv_hypercall(vcpu);
@@ -5752,7 +5792,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
trace_kvm_hypercall(nr, a0, a1, a2, a3);
- if (!is_long_mode(vcpu)) {
+ op_64_bit = is_64_bit_mode(vcpu);
+ if (!op_64_bit) {
nr &= 0xFFFFFFFF;
a0 &= 0xFFFFFFFF;
a1 &= 0xFFFFFFFF;
@@ -5778,6 +5819,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
break;
}
out:
+ if (!op_64_bit)
+ ret = (u32)ret;
kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
++vcpu->stat.hypercalls;
return r;
@@ -5856,6 +5899,11 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
trace_kvm_inj_exception(vcpu->arch.exception.nr,
vcpu->arch.exception.has_error_code,
vcpu->arch.exception.error_code);
+
+ if (exception_type(vcpu->arch.exception.nr) == EXCPT_FAULT)
+ __kvm_set_rflags(vcpu, kvm_get_rflags(vcpu) |
+ X86_EFLAGS_RF);
+
kvm_x86_ops->queue_exception(vcpu, vcpu->arch.exception.nr,
vcpu->arch.exception.has_error_code,
vcpu->arch.exception.error_code,
@@ -6847,9 +6895,11 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu)
atomic_set(&vcpu->arch.nmi_queued, 0);
vcpu->arch.nmi_pending = 0;
vcpu->arch.nmi_injected = false;
+ kvm_clear_interrupt_queue(vcpu);
+ kvm_clear_exception_queue(vcpu);
memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
- vcpu->arch.dr6 = DR6_FIXED_1;
+ vcpu->arch.dr6 = DR6_INIT;
kvm_update_dr6(vcpu);
vcpu->arch.dr7 = DR7_FIXED_1;
kvm_update_dr7(vcpu);
@@ -7405,12 +7455,17 @@ unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_get_rflags);
-void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
{
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP &&
kvm_is_linear_rip(vcpu, vcpu->arch.singlestep_rip))
rflags |= X86_EFLAGS_TF;
kvm_x86_ops->set_rflags(vcpu, rflags);
+}
+
+void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
+{
+ __kvm_set_rflags(vcpu, rflags);
kvm_make_request(KVM_REQ_EVENT, vcpu);
}
EXPORT_SYMBOL_GPL(kvm_set_rflags);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 8c97bac9a895..306a1b77581f 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -47,6 +47,16 @@ static inline int is_long_mode(struct kvm_vcpu *vcpu)
#endif
}
+static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu)
+{
+ int cs_db, cs_l;
+
+ if (!is_long_mode(vcpu))
+ return false;
+ kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+ return cs_l;
+}
+
static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
{
return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu;
@@ -108,6 +118,23 @@ static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
return false;
}
+static inline unsigned long kvm_register_readl(struct kvm_vcpu *vcpu,
+ enum kvm_reg reg)
+{
+ unsigned long val = kvm_register_read(vcpu, reg);
+
+ return is_64_bit_mode(vcpu) ? val : (u32)val;
+}
+
+static inline void kvm_register_writel(struct kvm_vcpu *vcpu,
+ enum kvm_reg reg,
+ unsigned long val)
+{
+ if (!is_64_bit_mode(vcpu))
+ val = (u32)val;
+ return kvm_register_write(vcpu, reg, val);
+}
+
void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 36642793e315..a24194681513 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -577,6 +577,8 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
static const char nx_warning[] = KERN_CRIT
"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
+static const char smep_warning[] = KERN_CRIT
+"unable to execute userspace code (SMEP?) (uid: %d)\n";
static void
show_fault_oops(struct pt_regs *regs, unsigned long error_code,
@@ -597,6 +599,10 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
if (pte && pte_present(*pte) && !pte_exec(*pte))
printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
+ if (pte && pte_present(*pte) && pte_exec(*pte) &&
+ (pgd_flags(*pgd) & _PAGE_USER) &&
+ (read_cr4() & X86_CR4_SMEP))
+ printk(smep_warning, from_kuid(&init_user_ns, current_uid()));
}
printk(KERN_ALERT "BUG: unable to handle kernel ");
@@ -1212,7 +1218,8 @@ good_area:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
- * the fault:
+ * the fault. Since we never set FAULT_FLAG_RETRY_NOWAIT, if
+ * we get VM_FAULT_RETRY back, the mmap_sem has been unlocked.
*/
fault = handle_mm_fault(mm, vma, address, flags);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index f97130618113..66dba36f2343 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -18,6 +18,13 @@
#include <asm/dma.h> /* for MAX_DMA_PFN */
#include <asm/microcode.h>
+/*
+ * We need to define the tracepoints somewhere, and tlb.c
+ * is only compied when SMP=y.
+ */
+#define CREATE_TRACE_POINTS
+#include <trace/events/tlb.h>
+
#include "mm_internal.h"
static unsigned long __initdata pgt_buf_start;
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index e39504878aec..7d05565ba781 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -825,7 +825,8 @@ void __init mem_init(void)
int arch_add_memory(int nid, u64 start, u64 size)
{
struct pglist_data *pgdata = NODE_DATA(nid);
- struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
+ struct zone *zone = pgdata->node_zones +
+ zone_for_memory(nid, start, size, ZONE_HIGHMEM);
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index df1a9927ad29..5621c47d7a1a 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -691,7 +691,8 @@ static void update_end_of_memory_vars(u64 start, u64 size)
int arch_add_memory(int nid, u64 start, u64 size)
{
struct pglist_data *pgdat = NODE_DATA(nid);
- struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+ struct zone *zone = pgdat->node_zones +
+ zone_for_memory(nid, start, size, ZONE_NORMAL);
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
int ret;
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index dd8dda167a24..1fe33987de02 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -49,6 +49,7 @@ void leave_mm(int cpu)
if (cpumask_test_cpu(cpu, mm_cpumask(active_mm))) {
cpumask_clear_cpu(cpu, mm_cpumask(active_mm));
load_cr3(swapper_pg_dir);
+ trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
}
}
EXPORT_SYMBOL_GPL(leave_mm);
@@ -102,20 +103,24 @@ static void flush_tlb_func(void *info)
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
return;
+ if (!f->flush_end)
+ f->flush_end = f->flush_start + PAGE_SIZE;
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
- if (f->flush_end == TLB_FLUSH_ALL)
+ if (f->flush_end == TLB_FLUSH_ALL) {
local_flush_tlb();
- else if (!f->flush_end)
- __flush_tlb_single(f->flush_start);
- else {
+ trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, TLB_FLUSH_ALL);
+ } else {
unsigned long addr;
+ unsigned long nr_pages =
+ f->flush_end - f->flush_start / PAGE_SIZE;
addr = f->flush_start;
while (addr < f->flush_end) {
__flush_tlb_single(addr);
addr += PAGE_SIZE;
}
+ trace_tlb_flush(TLB_REMOTE_SHOOTDOWN, nr_pages);
}
} else
leave_mm(smp_processor_id());
@@ -153,46 +158,45 @@ void flush_tlb_current_task(void)
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
+ trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
preempt_enable();
}
+/*
+ * See Documentation/x86/tlb.txt for details. We choose 33
+ * because it is large enough to cover the vast majority (at
+ * least 95%) of allocations, and is small enough that we are
+ * confident it will not cause too much overhead. Each single
+ * flush is about 100 ns, so this caps the maximum overhead at
+ * _about_ 3,000 ns.
+ *
+ * This is in units of pages.
+ */
+unsigned long tlb_single_page_flush_ceiling = 33;
+
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned long vmflag)
{
unsigned long addr;
- unsigned act_entries, tlb_entries = 0;
- unsigned long nr_base_pages;
+ /* do a global flush by default */
+ unsigned long base_pages_to_flush = TLB_FLUSH_ALL;
preempt_disable();
if (current->active_mm != mm)
- goto flush_all;
+ goto out;
if (!current->mm) {
leave_mm(smp_processor_id());
- goto flush_all;
+ goto out;
}
- if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
- || vmflag & VM_HUGETLB) {
- local_flush_tlb();
- goto flush_all;
- }
-
- /* In modern CPU, last level tlb used for both data/ins */
- if (vmflag & VM_EXEC)
- tlb_entries = tlb_lli_4k[ENTRIES];
- else
- tlb_entries = tlb_lld_4k[ENTRIES];
+ if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB))
+ base_pages_to_flush = (end - start) >> PAGE_SHIFT;
- /* Assume all of TLB entries was occupied by this task */
- act_entries = tlb_entries >> tlb_flushall_shift;
- act_entries = mm->total_vm > act_entries ? act_entries : mm->total_vm;
- nr_base_pages = (end - start) >> PAGE_SHIFT;
-
- /* tlb_flushall_shift is on balance point, details in commit log */
- if (nr_base_pages > act_entries) {
+ if (base_pages_to_flush > tlb_single_page_flush_ceiling) {
+ base_pages_to_flush = TLB_FLUSH_ALL;
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
local_flush_tlb();
} else {
@@ -201,17 +205,15 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
__flush_tlb_single(addr);
}
-
- if (cpumask_any_but(mm_cpumask(mm),
- smp_processor_id()) < nr_cpu_ids)
- flush_tlb_others(mm_cpumask(mm), mm, start, end);
- preempt_enable();
- return;
}
-
-flush_all:
+ trace_tlb_flush(TLB_LOCAL_MM_SHOOTDOWN, base_pages_to_flush);
+out:
+ if (base_pages_to_flush == TLB_FLUSH_ALL) {
+ start = 0UL;
+ end = TLB_FLUSH_ALL;
+ }
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
- flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
+ flush_tlb_others(mm_cpumask(mm), mm, start, end);
preempt_enable();
}
@@ -260,32 +262,26 @@ static void do_kernel_range_flush(void *info)
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- unsigned act_entries;
- struct flush_tlb_info info;
-
- /* In modern CPU, last level tlb used for both data/ins */
- act_entries = tlb_lld_4k[ENTRIES];
/* Balance as user space task's flush, a bit conservative */
- if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 ||
- (end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift)
-
+ if (end == TLB_FLUSH_ALL ||
+ (end - start) > tlb_single_page_flush_ceiling * PAGE_SIZE) {
on_each_cpu(do_flush_tlb_all, NULL, 1);
- else {
+ } else {
+ struct flush_tlb_info info;
info.flush_start = start;
info.flush_end = end;
on_each_cpu(do_kernel_range_flush, &info, 1);
}
}
-#ifdef CONFIG_DEBUG_TLBFLUSH
static ssize_t tlbflush_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
unsigned int len;
- len = sprintf(buf, "%hd\n", tlb_flushall_shift);
+ len = sprintf(buf, "%ld\n", tlb_single_page_flush_ceiling);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -294,20 +290,20 @@ static ssize_t tlbflush_write_file(struct file *file,
{
char buf[32];
ssize_t len;
- s8 shift;
+ int ceiling;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
- if (kstrtos8(buf, 0, &shift))
+ if (kstrtoint(buf, 0, &ceiling))
return -EINVAL;
- if (shift < -1 || shift >= BITS_PER_LONG)
+ if (ceiling < 0)
return -EINVAL;
- tlb_flushall_shift = shift;
+ tlb_single_page_flush_ceiling = ceiling;
return count;
}
@@ -317,11 +313,10 @@ static const struct file_operations fops_tlbflush = {
.llseek = default_llseek,
};
-static int __init create_tlb_flushall_shift(void)
+static int __init create_tlb_single_page_flush_ceiling(void)
{
- debugfs_create_file("tlb_flushall_shift", S_IRUSR | S_IWUSR,
+ debugfs_create_file("tlb_single_page_flush_ceiling", S_IRUSR | S_IWUSR,
arch_debugfs_dir, NULL, &fops_tlbflush);
return 0;
}
-late_initcall(create_tlb_flushall_shift);
-#endif
+late_initcall(create_tlb_single_page_flush_ceiling);
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 99bef86ed6df..5c8cb8043c5a 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -211,10 +211,10 @@ struct jit_context {
bool seen_ld_abs;
};
-static int do_jit(struct sk_filter *bpf_prog, int *addrs, u8 *image,
+static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
int oldproglen, struct jit_context *ctx)
{
- struct sock_filter_int *insn = bpf_prog->insnsi;
+ struct bpf_insn *insn = bpf_prog->insnsi;
int insn_cnt = bpf_prog->len;
u8 temp[64];
int i;
@@ -235,7 +235,7 @@ static int do_jit(struct sk_filter *bpf_prog, int *addrs, u8 *image,
/* mov qword ptr [rbp-X],rbx */
EMIT3_off32(0x48, 0x89, 0x9D, -stacksize);
- /* sk_convert_filter() maps classic BPF register X to R7 and uses R8
+ /* bpf_convert_filter() maps classic BPF register X to R7 and uses R8
* as temporary, so all tcpdump filters need to spill/fill R7(r13) and
* R8(r14). R9(r15) spill could be made conditional, but there is only
* one 'bpf_error' return path out of helper functions inside bpf_jit.S
@@ -841,7 +841,7 @@ common_load: ctx->seen_ld_abs = true;
/* By design x64 JIT should support all BPF instructions
* This error will be seen if new instruction was added
* to interpreter, but not to JIT
- * or if there is junk in sk_filter
+ * or if there is junk in bpf_prog
*/
pr_err("bpf_jit: unknown opcode %02x\n", insn->code);
return -EINVAL;
@@ -862,11 +862,11 @@ common_load: ctx->seen_ld_abs = true;
return proglen;
}
-void bpf_jit_compile(struct sk_filter *prog)
+void bpf_jit_compile(struct bpf_prog *prog)
{
}
-void bpf_int_jit_compile(struct sk_filter *prog)
+void bpf_int_jit_compile(struct bpf_prog *prog)
{
struct bpf_binary_header *header = NULL;
int proglen, oldproglen = 0;
@@ -932,7 +932,7 @@ out:
static void bpf_jit_free_deferred(struct work_struct *work)
{
- struct sk_filter *fp = container_of(work, struct sk_filter, work);
+ struct bpf_prog *fp = container_of(work, struct bpf_prog, work);
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;
@@ -941,7 +941,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)
kfree(fp);
}
-void bpf_jit_free(struct sk_filter *fp)
+void bpf_jit_free(struct bpf_prog *fp)
{
if (fp->jited) {
INIT_WORK(&fp->work, bpf_jit_free_deferred);
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5075371ab593..cfd1b132b8e3 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -448,7 +448,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
return;
size = sizeof(*info->res) * info->res_num;
- info->res = kzalloc(size, GFP_KERNEL);
+ info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res) {
info->res_num = 0;
return;
@@ -456,7 +456,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
size = sizeof(*info->res_offset) * info->res_num;
info->res_num = 0;
- info->res_offset = kzalloc(size, GFP_KERNEL);
+ info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
if (!info->res_offset) {
kfree(info->res);
info->res = NULL;
@@ -499,7 +499,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != NUMA_NO_NODE && !node_online(node))
node = NUMA_NO_NODE;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index b5e60268d93f..c61ea57d1ba1 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -326,6 +326,27 @@ static void pci_fixup_video(struct pci_dev *pdev)
struct pci_bus *bus;
u16 config;
+ if (!vga_default_device()) {
+ resource_size_t start, end;
+ int i;
+
+ /* Does firmware framebuffer belong to us? */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+ continue;
+
+ start = pci_resource_start(pdev, i);
+ end = pci_resource_end(pdev, i);
+
+ if (!start || !end)
+ continue;
+
+ if (screen_info.lfb_base >= start &&
+ (screen_info.lfb_base + screen_info.lfb_size) < end)
+ vga_set_default_device(pdev);
+ }
+ }
+
/* Is VGA routed to us? */
bus = pdev->bus;
while (bus) {
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index a19ed92e74e4..2ae525e0d8ba 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -162,6 +162,10 @@ pcibios_align_resource(void *data, const struct resource *res,
return start;
if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* The low 1MB range is reserved for ISA cards */
+ if (start < BIOS_END)
+ start = BIOS_END;
}
return start;
}
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 84b9d672843d..3865116c51fb 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -208,27 +208,31 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
static int intel_mid_pci_irq_enable(struct pci_dev *dev)
{
- u8 pin;
- struct io_apic_irq_attr irq_attr;
+ int polarity;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
+ polarity = 0; /* active high */
+ else
+ polarity = 1; /* active low */
/*
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
* IOAPIC RTE entries, so we just enable RTE for the device.
*/
- irq_attr.ioapic = mp_find_ioapic(dev->irq);
- irq_attr.ioapic_pin = dev->irq;
- irq_attr.trigger = 1; /* level */
- if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
- irq_attr.polarity = 0; /* active high */
- else
- irq_attr.polarity = 1; /* active low */
- io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
+ if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
+ return -EBUSY;
+ if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
+ return -EBUSY;
return 0;
}
+static void intel_mid_pci_irq_disable(struct pci_dev *dev)
+{
+ if (!dev->dev.power.is_prepared && dev->irq > 0)
+ mp_unmap_irq(dev->irq);
+}
+
struct pci_ops intel_mid_pci_ops = {
.read = pci_read,
.write = pci_write,
@@ -245,6 +249,7 @@ int __init intel_mid_pci_init(void)
pr_info("Intel MID platform detected, using MID PCI ops\n");
pci_mmcfg_late_init();
pcibios_enable_irq = intel_mid_pci_irq_enable;
+ pcibios_disable_irq = intel_mid_pci_irq_disable;
pci_root_ops = intel_mid_pci_ops;
pci_soc_mode = 1;
/* Continue with standard init */
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 84112f55dd7a..bc1a2c341891 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -26,6 +26,7 @@ static int acer_tm360_irqrouting;
static struct irq_routing_table *pirq_table;
static int pirq_enable_irq(struct pci_dev *dev);
+static void pirq_disable_irq(struct pci_dev *dev);
/*
* Never use: 0, 1, 2 (timer, keyboard, and cascade)
@@ -53,7 +54,7 @@ struct irq_router_handler {
};
int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
-void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;
/*
* Check passed address for the PCI IRQ Routing Table signature
@@ -1186,7 +1187,7 @@ void pcibios_penalize_isa_irq(int irq, int active)
static int pirq_enable_irq(struct pci_dev *dev)
{
- u8 pin;
+ u8 pin = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin && !pcibios_lookup_irq(dev, 1)) {
@@ -1227,8 +1228,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
dev = temp_dev;
if (irq >= 0) {
- io_apic_set_pci_routing(&dev->dev, irq,
- &irq_attr);
dev->irq = irq;
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
@@ -1254,3 +1253,12 @@ static int pirq_enable_irq(struct pci_dev *dev)
}
return 0;
}
+
+static void pirq_disable_irq(struct pci_dev *dev)
+{
+ if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared &&
+ dev->irq) {
+ mp_unmap_irq(dev->irq);
+ dev->irq = 0;
+ }
+}
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 905956f16465..093f5f4272d3 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -23,6 +23,7 @@
#include <xen/features.h>
#include <xen/events.h>
#include <asm/xen/pci.h>
+#include <asm/i8259.h>
static int xen_pcifront_enable_irq(struct pci_dev *dev)
{
@@ -40,7 +41,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
pirq = gsi;
- if (gsi < NR_IRQS_LEGACY)
+ if (gsi < nr_legacy_irqs())
share = 0;
rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
@@ -511,7 +512,7 @@ int __init pci_xen_initial_domain(void)
xen_setup_acpi_sci();
__acpi_register_gsi = acpi_register_gsi_xen;
/* Pre-allocate legacy irqs */
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+ for (irq = 0; irq < nr_legacy_irqs(); irq++) {
int trigger, polarity;
if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
@@ -522,7 +523,7 @@ int __init pci_xen_initial_domain(void)
true /* Map GSI to PIRQ */);
}
if (0 == nr_ioapics) {
- for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
+ for (irq = 0; irq < nr_legacy_irqs(); irq++)
xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
}
return 0;
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 8244f5ec2f4c..701fd5843c87 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -135,14 +135,10 @@ static void __init sdv_arch_setup(void)
sdv_serial_fixup();
}
-#ifdef CONFIG_X86_IO_APIC
static void sdv_pci_init(void)
{
x86_of_pci_init();
- /* We can't set this earlier, because we need to calibrate the timer */
- legacy_pic = &null_legacy_pic;
}
-#endif
/*
* CE4100 specific x86_init function overrides and early setup
@@ -155,7 +151,9 @@ void __init x86_ce4100_early_setup(void)
x86_init.resources.probe_roms = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
x86_init.pci.init = ce4100_pci_init;
+ x86_init.pci.init_irq = sdv_pci_init;
/*
* By default, the reboot method is ACPI which is supported by the
@@ -166,10 +164,5 @@ void __init x86_ce4100_early_setup(void)
*/
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/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index d51045afcaaf..2846aaab5103 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
+obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 87fc96bcc13c..850da94fef30 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -56,13 +56,6 @@
#define EFI_DEBUG
-#define EFI_MIN_RESERVE 5120
-
-#define EFI_DUMMY_GUID \
- EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
-
-static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
-
struct efi_memory_map memmap;
static struct efi efi_phys __initdata;
@@ -95,139 +88,6 @@ static int __init setup_add_efi_memmap(char *arg)
}
early_param("add_efi_memmap", setup_add_efi_memmap);
-static bool efi_no_storage_paranoia;
-
-static int __init setup_storage_paranoia(char *arg)
-{
- efi_no_storage_paranoia = true;
- return 0;
-}
-early_param("efi_no_storage_paranoia", setup_storage_paranoia);
-
-static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
-{
- unsigned long flags;
- efi_status_t status;
-
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_call_virt(get_time, tm, tc);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return status;
-}
-
-static efi_status_t virt_efi_set_time(efi_time_t *tm)
-{
- unsigned long flags;
- efi_status_t status;
-
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_call_virt(set_time, tm);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return status;
-}
-
-static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
- efi_bool_t *pending,
- efi_time_t *tm)
-{
- unsigned long flags;
- efi_status_t status;
-
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return status;
-}
-
-static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
-{
- unsigned long flags;
- efi_status_t status;
-
- spin_lock_irqsave(&rtc_lock, flags);
- status = efi_call_virt(set_wakeup_time, enabled, tm);
- spin_unlock_irqrestore(&rtc_lock, flags);
- return status;
-}
-
-static efi_status_t virt_efi_get_variable(efi_char16_t *name,
- efi_guid_t *vendor,
- u32 *attr,
- unsigned long *data_size,
- void *data)
-{
- return efi_call_virt(get_variable,
- name, vendor, attr,
- data_size, data);
-}
-
-static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
- efi_char16_t *name,
- efi_guid_t *vendor)
-{
- return efi_call_virt(get_next_variable,
- name_size, name, vendor);
-}
-
-static efi_status_t virt_efi_set_variable(efi_char16_t *name,
- efi_guid_t *vendor,
- u32 attr,
- unsigned long data_size,
- void *data)
-{
- return efi_call_virt(set_variable,
- name, vendor, attr,
- data_size, data);
-}
-
-static efi_status_t virt_efi_query_variable_info(u32 attr,
- u64 *storage_space,
- u64 *remaining_space,
- u64 *max_variable_size)
-{
- if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
- return EFI_UNSUPPORTED;
-
- return efi_call_virt(query_variable_info, attr, storage_space,
- remaining_space, max_variable_size);
-}
-
-static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
-{
- return efi_call_virt(get_next_high_mono_count, count);
-}
-
-static void virt_efi_reset_system(int reset_type,
- efi_status_t status,
- unsigned long data_size,
- efi_char16_t *data)
-{
- __efi_call_virt(reset_system, reset_type, status,
- data_size, data);
-}
-
-static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
- unsigned long count,
- unsigned long sg_list)
-{
- if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
- return EFI_UNSUPPORTED;
-
- return efi_call_virt(update_capsule, capsules, count, sg_list);
-}
-
-static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
- unsigned long count,
- u64 *max_size,
- int *reset_type)
-{
- if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
- return EFI_UNSUPPORTED;
-
- return efi_call_virt(query_capsule_caps, capsules, count, max_size,
- reset_type);
-}
-
static efi_status_t __init phys_efi_set_virtual_address_map(
unsigned long memory_map_size,
unsigned long descriptor_size,
@@ -244,42 +104,6 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
return status;
}
-int efi_set_rtc_mmss(const struct timespec *now)
-{
- unsigned long nowtime = now->tv_sec;
- efi_status_t status;
- efi_time_t eft;
- efi_time_cap_t cap;
- struct rtc_time tm;
-
- status = efi.get_time(&eft, &cap);
- if (status != EFI_SUCCESS) {
- pr_err("Oops: efitime: can't read time!\n");
- return -1;
- }
-
- rtc_time_to_tm(nowtime, &tm);
- if (!rtc_valid_tm(&tm)) {
- eft.year = tm.tm_year + 1900;
- eft.month = tm.tm_mon + 1;
- eft.day = tm.tm_mday;
- eft.minute = tm.tm_min;
- eft.second = tm.tm_sec;
- eft.nanosecond = 0;
- } else {
- pr_err("%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
- __func__, nowtime);
- return -1;
- }
-
- status = efi.set_time(&eft);
- if (status != EFI_SUCCESS) {
- pr_err("Oops: efitime: can't write time!\n");
- return -1;
- }
- return 0;
-}
-
void efi_get_time(struct timespec *now)
{
efi_status_t status;
@@ -350,6 +174,9 @@ int __init efi_memblock_x86_reserve_range(void)
struct efi_info *e = &boot_params.efi_info;
unsigned long pmap;
+ if (efi_enabled(EFI_PARAVIRT))
+ return 0;
+
#ifdef CONFIG_X86_32
/* Can't handle data above 4GB at this time */
if (e->efi_memmap_hi) {
@@ -392,69 +219,15 @@ static void __init print_efi_memmap(void)
#endif /* EFI_DEBUG */
}
-void __init efi_reserve_boot_services(void)
-{
- void *p;
-
- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
- efi_memory_desc_t *md = p;
- u64 start = md->phys_addr;
- u64 size = md->num_pages << EFI_PAGE_SHIFT;
-
- if (md->type != EFI_BOOT_SERVICES_CODE &&
- md->type != EFI_BOOT_SERVICES_DATA)
- continue;
- /* Only reserve where possible:
- * - Not within any already allocated areas
- * - Not over any memory area (really needed, if above?)
- * - Not within any part of the kernel
- * - Not the bios reserved area
- */
- if ((start + size > __pa_symbol(_text)
- && start <= __pa_symbol(_end)) ||
- !e820_all_mapped(start, start+size, E820_RAM) ||
- memblock_is_region_reserved(start, size)) {
- /* Could not reserve, skip it */
- md->num_pages = 0;
- memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
- start, start+size-1);
- } else
- memblock_reserve(start, size);
- }
-}
-
void __init efi_unmap_memmap(void)
{
clear_bit(EFI_MEMMAP, &efi.flags);
if (memmap.map) {
- early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
+ early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
}
}
-void __init efi_free_boot_services(void)
-{
- void *p;
-
- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
- efi_memory_desc_t *md = p;
- unsigned long long start = md->phys_addr;
- unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
-
- if (md->type != EFI_BOOT_SERVICES_CODE &&
- md->type != EFI_BOOT_SERVICES_DATA)
- continue;
-
- /* Could not reserve boot area */
- if (!size)
- continue;
-
- free_bootmem_late(start, size);
- }
-
- efi_unmap_memmap();
-}
-
static int __init efi_systab_init(void *phys)
{
if (efi_enabled(EFI_64BIT)) {
@@ -467,12 +240,12 @@ static int __init efi_systab_init(void *phys)
if (!data)
return -ENOMEM;
}
- systab64 = early_ioremap((unsigned long)phys,
+ systab64 = early_memremap((unsigned long)phys,
sizeof(*systab64));
if (systab64 == NULL) {
pr_err("Couldn't map the system table!\n");
if (data)
- early_iounmap(data, sizeof(*data));
+ early_memunmap(data, sizeof(*data));
return -ENOMEM;
}
@@ -504,9 +277,9 @@ static int __init efi_systab_init(void *phys)
systab64->tables;
tmp |= data ? data->tables : systab64->tables;
- early_iounmap(systab64, sizeof(*systab64));
+ early_memunmap(systab64, sizeof(*systab64));
if (data)
- early_iounmap(data, sizeof(*data));
+ early_memunmap(data, sizeof(*data));
#ifdef CONFIG_X86_32
if (tmp >> 32) {
pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -516,7 +289,7 @@ static int __init efi_systab_init(void *phys)
} else {
efi_system_table_32_t *systab32;
- systab32 = early_ioremap((unsigned long)phys,
+ systab32 = early_memremap((unsigned long)phys,
sizeof(*systab32));
if (systab32 == NULL) {
pr_err("Couldn't map the system table!\n");
@@ -537,7 +310,7 @@ static int __init efi_systab_init(void *phys)
efi_systab.nr_tables = systab32->nr_tables;
efi_systab.tables = systab32->tables;
- early_iounmap(systab32, sizeof(*systab32));
+ early_memunmap(systab32, sizeof(*systab32));
}
efi.systab = &efi_systab;
@@ -563,7 +336,7 @@ static int __init efi_runtime_init32(void)
{
efi_runtime_services_32_t *runtime;
- runtime = early_ioremap((unsigned long)efi.systab->runtime,
+ runtime = early_memremap((unsigned long)efi.systab->runtime,
sizeof(efi_runtime_services_32_t));
if (!runtime) {
pr_err("Could not map the runtime service table!\n");
@@ -578,7 +351,7 @@ static int __init efi_runtime_init32(void)
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
(unsigned long)runtime->set_virtual_address_map;
- early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
+ early_memunmap(runtime, sizeof(efi_runtime_services_32_t));
return 0;
}
@@ -587,7 +360,7 @@ static int __init efi_runtime_init64(void)
{
efi_runtime_services_64_t *runtime;
- runtime = early_ioremap((unsigned long)efi.systab->runtime,
+ runtime = early_memremap((unsigned long)efi.systab->runtime,
sizeof(efi_runtime_services_64_t));
if (!runtime) {
pr_err("Could not map the runtime service table!\n");
@@ -602,7 +375,7 @@ static int __init efi_runtime_init64(void)
efi_phys.set_virtual_address_map =
(efi_set_virtual_address_map_t *)
(unsigned long)runtime->set_virtual_address_map;
- early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
+ early_memunmap(runtime, sizeof(efi_runtime_services_64_t));
return 0;
}
@@ -616,14 +389,24 @@ static int __init efi_runtime_init(void)
* the runtime services table so that we can grab the physical
* address of several of the EFI runtime functions, needed to
* set the firmware into virtual mode.
+ *
+ * When EFI_PARAVIRT is in force then we could not map runtime
+ * service memory region because we do not have direct access to it.
+ * However, runtime services are available through proxy functions
+ * (e.g. in case of Xen dom0 EFI implementation they call special
+ * hypercall which executes relevant EFI functions) and that is why
+ * they are always enabled.
*/
- if (efi_enabled(EFI_64BIT))
- rv = efi_runtime_init64();
- else
- rv = efi_runtime_init32();
- if (rv)
- return rv;
+ if (!efi_enabled(EFI_PARAVIRT)) {
+ if (efi_enabled(EFI_64BIT))
+ rv = efi_runtime_init64();
+ else
+ rv = efi_runtime_init32();
+
+ if (rv)
+ return rv;
+ }
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
@@ -632,8 +415,11 @@ static int __init efi_runtime_init(void)
static int __init efi_memmap_init(void)
{
+ if (efi_enabled(EFI_PARAVIRT))
+ return 0;
+
/* Map the EFI memory map */
- memmap.map = early_ioremap((unsigned long)memmap.phys_map,
+ memmap.map = early_memremap((unsigned long)memmap.phys_map,
memmap.nr_map * memmap.desc_size);
if (memmap.map == NULL) {
pr_err("Could not map the memory map!\n");
@@ -649,62 +435,6 @@ static int __init efi_memmap_init(void)
return 0;
}
-/*
- * A number of config table entries get remapped to virtual addresses
- * after entering EFI virtual mode. However, the kexec kernel requires
- * their physical addresses therefore we pass them via setup_data and
- * correct those entries to their respective physical addresses here.
- *
- * Currently only handles smbios which is necessary for some firmware
- * implementation.
- */
-static int __init efi_reuse_config(u64 tables, int nr_tables)
-{
- int i, sz, ret = 0;
- void *p, *tablep;
- struct efi_setup_data *data;
-
- if (!efi_setup)
- return 0;
-
- if (!efi_enabled(EFI_64BIT))
- return 0;
-
- data = early_memremap(efi_setup, sizeof(*data));
- if (!data) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (!data->smbios)
- goto out_memremap;
-
- sz = sizeof(efi_config_table_64_t);
-
- p = tablep = early_memremap(tables, nr_tables * sz);
- if (!p) {
- pr_err("Could not map Configuration table!\n");
- ret = -ENOMEM;
- goto out_memremap;
- }
-
- for (i = 0; i < efi.systab->nr_tables; i++) {
- efi_guid_t guid;
-
- guid = ((efi_config_table_64_t *)p)->guid;
-
- if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
- ((efi_config_table_64_t *)p)->table = data->smbios;
- p += sz;
- }
- early_iounmap(tablep, nr_tables * sz);
-
-out_memremap:
- early_iounmap(data, sizeof(*data));
-out:
- return ret;
-}
-
void __init efi_init(void)
{
efi_char16_t *c16;
@@ -728,8 +458,6 @@ void __init efi_init(void)
if (efi_systab_init(efi_phys.systab))
return;
- set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
efi.config_table = (unsigned long)efi.systab->tables;
efi.fw_vendor = (unsigned long)efi.systab->fw_vendor;
efi.runtime = (unsigned long)efi.systab->runtime;
@@ -737,14 +465,14 @@ void __init efi_init(void)
/*
* Show what we know for posterity
*/
- c16 = tmp = early_ioremap(efi.systab->fw_vendor, 2);
+ c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
if (c16) {
for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
vendor[i] = *c16++;
vendor[i] = '\0';
} else
pr_err("Could not map the firmware vendor!\n");
- early_iounmap(tmp, 2);
+ early_memunmap(tmp, 2);
pr_info("EFI v%u.%.02u by %s\n",
efi.systab->hdr.revision >> 16,
@@ -770,8 +498,6 @@ void __init efi_init(void)
if (efi_memmap_init())
return;
- set_bit(EFI_MEMMAP, &efi.flags);
-
print_efi_memmap();
}
@@ -847,22 +573,6 @@ void __init old_map_region(efi_memory_desc_t *md)
(unsigned long long)md->phys_addr);
}
-static void native_runtime_setup(void)
-{
- efi.get_time = virt_efi_get_time;
- efi.set_time = virt_efi_set_time;
- efi.get_wakeup_time = virt_efi_get_wakeup_time;
- efi.set_wakeup_time = virt_efi_set_wakeup_time;
- efi.get_variable = virt_efi_get_variable;
- efi.get_next_variable = virt_efi_get_next_variable;
- efi.set_variable = virt_efi_set_variable;
- efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
- efi.reset_system = virt_efi_reset_system;
- efi.query_variable_info = virt_efi_query_variable_info;
- efi.update_capsule = virt_efi_update_capsule;
- efi.query_capsule_caps = virt_efi_query_capsule_caps;
-}
-
/* Merge contiguous regions of the same type and attribute */
static void __init efi_merge_regions(void)
{
@@ -1049,7 +759,7 @@ static void __init kexec_enter_virtual_mode(void)
*/
efi.runtime_version = efi_systab.hdr.revision;
- native_runtime_setup();
+ efi_native_runtime_setup();
efi.set_virtual_address_map = NULL;
@@ -1057,11 +767,7 @@ static void __init kexec_enter_virtual_mode(void)
runtime_code_page_mkexec();
/* clean DUMMY object */
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 0, NULL);
+ efi_delete_dummy_variable();
#endif
}
@@ -1142,7 +848,7 @@ static void __init __efi_enter_virtual_mode(void)
efi.runtime_version = efi_systab.hdr.revision;
if (efi_is_native())
- native_runtime_setup();
+ efi_native_runtime_setup();
else
efi_thunk_runtime_setup();
@@ -1179,15 +885,14 @@ static void __init __efi_enter_virtual_mode(void)
free_pages((unsigned long)new_memmap, pg_shift);
/* clean DUMMY object */
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 0, NULL);
+ efi_delete_dummy_variable();
}
void __init efi_enter_virtual_mode(void)
{
+ if (efi_enabled(EFI_PARAVIRT))
+ return;
+
if (efi_setup)
kexec_enter_virtual_mode();
else
@@ -1220,6 +925,9 @@ u64 efi_mem_attributes(unsigned long phys_addr)
efi_memory_desc_t *md;
void *p;
+ if (!efi_enabled(EFI_MEMMAP))
+ return 0;
+
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
md = p;
if ((md->phys_addr <= phys_addr) &&
@@ -1230,86 +938,6 @@ u64 efi_mem_attributes(unsigned long phys_addr)
return 0;
}
-/*
- * Some firmware implementations refuse to boot if there's insufficient space
- * in the variable store. Ensure that we never use more than a safe limit.
- *
- * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
- * store.
- */
-efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
-{
- efi_status_t status;
- u64 storage_size, remaining_size, max_size;
-
- if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
- return 0;
-
- status = efi.query_variable_info(attributes, &storage_size,
- &remaining_size, &max_size);
- if (status != EFI_SUCCESS)
- return status;
-
- /*
- * We account for that by refusing the write if permitting it would
- * reduce the available space to under 5KB. This figure was provided by
- * Samsung, so should be safe.
- */
- if ((remaining_size - size < EFI_MIN_RESERVE) &&
- !efi_no_storage_paranoia) {
-
- /*
- * Triggering garbage collection may require that the firmware
- * generate a real EFI_OUT_OF_RESOURCES error. We can force
- * that by attempting to use more space than is available.
- */
- unsigned long dummy_size = remaining_size + 1024;
- void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
-
- if (!dummy)
- return EFI_OUT_OF_RESOURCES;
-
- status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- dummy_size, dummy);
-
- if (status == EFI_SUCCESS) {
- /*
- * This should have failed, so if it didn't make sure
- * that we delete it...
- */
- efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- 0, dummy);
- }
-
- kfree(dummy);
-
- /*
- * The runtime code may now have triggered a garbage collection
- * run, so check the variable info again
- */
- status = efi.query_variable_info(attributes, &storage_size,
- &remaining_size, &max_size);
-
- if (status != EFI_SUCCESS)
- return status;
-
- /*
- * There still isn't enough room, so return an error
- */
- if (remaining_size - size < EFI_MIN_RESERVE)
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-EXPORT_SYMBOL_GPL(efi_query_variable_store);
-
static int __init parse_efi_cmdline(char *str)
{
if (*str == '=')
@@ -1321,22 +949,3 @@ static int __init parse_efi_cmdline(char *str)
return 0;
}
early_param("efi", parse_efi_cmdline);
-
-void __init efi_apply_memmap_quirks(void)
-{
- /*
- * Once setup is done earlier, unmap the EFI memory map on mismatched
- * firmware/kernel architectures since there is no support for runtime
- * services.
- */
- if (!efi_runtime_supported()) {
- pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
- efi_unmap_memmap();
- }
-
- /*
- * UV doesn't support the new EFI pagetable mapping yet.
- */
- if (is_uv_system())
- set_bit(EFI_OLD_MEMMAP, &efi.flags);
-}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
new file mode 100644
index 000000000000..1c7380da65ff
--- /dev/null
+++ b/arch/x86/platform/efi/quirks.c
@@ -0,0 +1,290 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/acpi.h>
+#include <asm/efi.h>
+#include <asm/uv/uv.h>
+
+#define EFI_MIN_RESERVE 5120
+
+#define EFI_DUMMY_GUID \
+ EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
+
+static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
+
+static bool efi_no_storage_paranoia;
+
+/*
+ * Some firmware implementations refuse to boot if there's insufficient
+ * space in the variable store. The implementation of garbage collection
+ * in some FW versions causes stale (deleted) variables to take up space
+ * longer than intended and space is only freed once the store becomes
+ * almost completely full.
+ *
+ * Enabling this option disables the space checks in
+ * efi_query_variable_store() and forces garbage collection.
+ *
+ * Only enable this option if deleting EFI variables does not free up
+ * space in your variable store, e.g. if despite deleting variables
+ * you're unable to create new ones.
+ */
+static int __init setup_storage_paranoia(char *arg)
+{
+ efi_no_storage_paranoia = true;
+ return 0;
+}
+early_param("efi_no_storage_paranoia", setup_storage_paranoia);
+
+/*
+ * Deleting the dummy variable which kicks off garbage collection
+*/
+void efi_delete_dummy_variable(void)
+{
+ efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ 0, NULL);
+}
+
+/*
+ * Some firmware implementations refuse to boot if there's insufficient space
+ * in the variable store. Ensure that we never use more than a safe limit.
+ *
+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
+ * store.
+ */
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+ efi_status_t status;
+ u64 storage_size, remaining_size, max_size;
+
+ if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
+ return 0;
+
+ status = efi.query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ /*
+ * We account for that by refusing the write if permitting it would
+ * reduce the available space to under 5KB. This figure was provided by
+ * Samsung, so should be safe.
+ */
+ if ((remaining_size - size < EFI_MIN_RESERVE) &&
+ !efi_no_storage_paranoia) {
+
+ /*
+ * Triggering garbage collection may require that the firmware
+ * generate a real EFI_OUT_OF_RESOURCES error. We can force
+ * that by attempting to use more space than is available.
+ */
+ unsigned long dummy_size = remaining_size + 1024;
+ void *dummy = kzalloc(dummy_size, GFP_ATOMIC);
+
+ if (!dummy)
+ return EFI_OUT_OF_RESOURCES;
+
+ status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ dummy_size, dummy);
+
+ if (status == EFI_SUCCESS) {
+ /*
+ * This should have failed, so if it didn't make sure
+ * that we delete it...
+ */
+ efi_delete_dummy_variable();
+ }
+
+ kfree(dummy);
+
+ /*
+ * The runtime code may now have triggered a garbage collection
+ * run, so check the variable info again
+ */
+ status = efi.query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ /*
+ * There still isn't enough room, so return an error
+ */
+ if (remaining_size - size < EFI_MIN_RESERVE)
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(efi_query_variable_store);
+
+/*
+ * The UEFI specification makes it clear that the operating system is free to do
+ * whatever it wants with boot services code after ExitBootServices() has been
+ * called. Ignoring this recommendation a significant bunch of EFI implementations
+ * continue calling into boot services code (SetVirtualAddressMap). In order to
+ * work around such buggy implementations we reserve boot services region during
+ * EFI init and make sure it stays executable. Then, after SetVirtualAddressMap(), it
+* is discarded.
+*/
+void __init efi_reserve_boot_services(void)
+{
+ void *p;
+
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ efi_memory_desc_t *md = p;
+ u64 start = md->phys_addr;
+ u64 size = md->num_pages << EFI_PAGE_SHIFT;
+
+ if (md->type != EFI_BOOT_SERVICES_CODE &&
+ md->type != EFI_BOOT_SERVICES_DATA)
+ continue;
+ /* Only reserve where possible:
+ * - Not within any already allocated areas
+ * - Not over any memory area (really needed, if above?)
+ * - Not within any part of the kernel
+ * - Not the bios reserved area
+ */
+ if ((start + size > __pa_symbol(_text)
+ && start <= __pa_symbol(_end)) ||
+ !e820_all_mapped(start, start+size, E820_RAM) ||
+ memblock_is_region_reserved(start, size)) {
+ /* Could not reserve, skip it */
+ md->num_pages = 0;
+ memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
+ start, start+size-1);
+ } else
+ memblock_reserve(start, size);
+ }
+}
+
+void __init efi_free_boot_services(void)
+{
+ void *p;
+
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ efi_memory_desc_t *md = p;
+ unsigned long long start = md->phys_addr;
+ unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+
+ if (md->type != EFI_BOOT_SERVICES_CODE &&
+ md->type != EFI_BOOT_SERVICES_DATA)
+ continue;
+
+ /* Could not reserve boot area */
+ if (!size)
+ continue;
+
+ free_bootmem_late(start, size);
+ }
+
+ efi_unmap_memmap();
+}
+
+/*
+ * A number of config table entries get remapped to virtual addresses
+ * after entering EFI virtual mode. However, the kexec kernel requires
+ * their physical addresses therefore we pass them via setup_data and
+ * correct those entries to their respective physical addresses here.
+ *
+ * Currently only handles smbios which is necessary for some firmware
+ * implementation.
+ */
+int __init efi_reuse_config(u64 tables, int nr_tables)
+{
+ int i, sz, ret = 0;
+ void *p, *tablep;
+ struct efi_setup_data *data;
+
+ if (!efi_setup)
+ return 0;
+
+ if (!efi_enabled(EFI_64BIT))
+ return 0;
+
+ data = early_memremap(efi_setup, sizeof(*data));
+ if (!data) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!data->smbios)
+ goto out_memremap;
+
+ sz = sizeof(efi_config_table_64_t);
+
+ p = tablep = early_memremap(tables, nr_tables * sz);
+ if (!p) {
+ pr_err("Could not map Configuration table!\n");
+ ret = -ENOMEM;
+ goto out_memremap;
+ }
+
+ for (i = 0; i < efi.systab->nr_tables; i++) {
+ efi_guid_t guid;
+
+ guid = ((efi_config_table_64_t *)p)->guid;
+
+ if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
+ ((efi_config_table_64_t *)p)->table = data->smbios;
+ p += sz;
+ }
+ early_memunmap(tablep, nr_tables * sz);
+
+out_memremap:
+ early_memunmap(data, sizeof(*data));
+out:
+ return ret;
+}
+
+void __init efi_apply_memmap_quirks(void)
+{
+ /*
+ * Once setup is done earlier, unmap the EFI memory map on mismatched
+ * firmware/kernel architectures since there is no support for runtime
+ * services.
+ */
+ if (!efi_runtime_supported()) {
+ pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+ efi_unmap_memmap();
+ }
+
+ /*
+ * UV doesn't support the new EFI pagetable mapping yet.
+ */
+ if (is_uv_system())
+ set_bit(EFI_OLD_MEMMAP, &efi.flags);
+}
+
+/*
+ * For most modern platforms the preferred method of powering off is via
+ * ACPI. However, there are some that are known to require the use of
+ * EFI runtime services and for which ACPI does not work at all.
+ *
+ * Using EFI is a last resort, to be used only if no other option
+ * exists.
+ */
+bool efi_reboot_required(void)
+{
+ if (!acpi_gbl_reduced_hardware)
+ return false;
+
+ efi_reboot_quirk_mode = EFI_RESET_WARM;
+ return true;
+}
+
+bool efi_poweroff_required(void)
+{
+ return !!acpi_gbl_reduced_hardware;
+}
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
index 973cf3bfa9fd..0b283d4d0ad7 100644
--- a/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
+++ b/arch/x86/platform/intel-mid/device_libs/platform_wdt.c
@@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {
static int tangier_probe(struct platform_device *pdev)
{
- int ioapic;
- int irq;
+ int gsi;
struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
- struct io_apic_irq_attr irq_attr = { 0 };
if (!pdata)
return -EINVAL;
- irq = pdata->irq;
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- int ret;
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- /* irq_attr.polarity = 0; -> Active high */
- ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
- if (ret)
- return ret;
- } else {
+ /* IOAPIC builds identity mapping between GSI and IRQ on MID */
+ gsi = pdata->irq;
+ if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
+ mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
- irq);
+ gsi);
return -EINVAL;
}
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
index 994c40bd7cb7..3c53a90fdb18 100644
--- a/arch/x86/platform/intel-mid/sfi.c
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -432,9 +432,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
struct sfi_table_simple *sb;
struct sfi_device_table_entry *pentry;
struct devs_id *dev = NULL;
- int num, i;
- int ioapic;
- struct io_apic_irq_attr irq_attr;
+ int num, i, ret;
+ int polarity;
sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
@@ -448,35 +447,30 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
* devices, but they have separate RTE entry in IOAPIC
* so we have to enable them one by one here
*/
- ioapic = mp_find_ioapic(irq);
- if (ioapic >= 0) {
- irq_attr.ioapic = ioapic;
- irq_attr.ioapic_pin = irq;
- irq_attr.trigger = 1;
- if (intel_mid_identify_cpu() ==
- INTEL_MID_CPU_CHIP_TANGIER) {
- if (!strncmp(pentry->name,
- "r69001-ts-i2c", 13))
- /* active low */
- irq_attr.polarity = 1;
- else if (!strncmp(pentry->name,
- "synaptics_3202", 14))
- /* active low */
- irq_attr.polarity = 1;
- else if (irq == 41)
- /* fast_int_1 */
- irq_attr.polarity = 1;
- else
- /* active high */
- irq_attr.polarity = 0;
- } else {
- /* PNW and CLV go with active low */
- irq_attr.polarity = 1;
- }
- io_apic_set_pci_routing(NULL, irq, &irq_attr);
+ if (intel_mid_identify_cpu() ==
+ INTEL_MID_CPU_CHIP_TANGIER) {
+ if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
+ /* active low */
+ polarity = 1;
+ else if (!strncmp(pentry->name,
+ "synaptics_3202", 14))
+ /* active low */
+ polarity = 1;
+ else if (irq == 41)
+ /* fast_int_1 */
+ polarity = 1;
+ else
+ /* active high */
+ polarity = 0;
+ } else {
+ /* PNW and CLV go with active low */
+ polarity = 1;
}
- } else {
- irq = 0; /* No irq */
+
+ ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
+ if (ret == 0)
+ ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
+ WARN_ON(ret < 0);
}
dev = get_device_id(pentry->type, pentry->name);
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index bcd1a703e3e6..2a8a74f3bd76 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/io.h>
+#include <linux/irqdomain.h>
#include <asm/io_apic.h>
#include <asm/mpspec.h>
@@ -70,19 +71,26 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
+static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};
static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
struct sfi_table_simple *sb;
struct sfi_apic_table_entry *pentry;
int i, num;
+ struct ioapic_domain_cfg cfg = {
+ .type = IOAPIC_DOMAIN_STRICT,
+ .ops = &sfi_ioapic_irqdomain_ops,
+ };
sb = (struct sfi_table_simple *)table;
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
pentry = (struct sfi_apic_table_entry *)sb->pentry;
for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
pentry++;
}
diff --git a/arch/x86/platform/ts5500/ts5500.c b/arch/x86/platform/ts5500/ts5500.c
index 9471b9456f25..baf16e72e668 100644
--- a/arch/x86/platform/ts5500/ts5500.c
+++ b/arch/x86/platform/ts5500/ts5500.c
@@ -1,7 +1,7 @@
/*
* Technologic Systems TS-5500 Single Board Computer support
*
- * Copyright (C) 2013 Savoir-faire Linux Inc.
+ * Copyright (C) 2013-2014 Savoir-faire Linux Inc.
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify it under
@@ -15,8 +15,8 @@
* state or available options. For further information about sysfs entries, see
* Documentation/ABI/testing/sysfs-platform-ts5500.
*
- * This code actually supports the TS-5500 platform, but it may be extended to
- * support similar Technologic Systems x86-based platforms, such as the TS-5600.
+ * This code may be extended to support similar x86-based platforms.
+ * Actually, the TS-5500 and TS-5400 are supported.
*/
#include <linux/delay.h>
@@ -32,6 +32,7 @@
/* Product code register */
#define TS5500_PRODUCT_CODE_ADDR 0x74
#define TS5500_PRODUCT_CODE 0x60 /* TS-5500 product code */
+#define TS5400_PRODUCT_CODE 0x40 /* TS-5400 product code */
/* SRAM/RS-485/ADC options, and RS-485 RTS/Automatic RS-485 flags register */
#define TS5500_SRAM_RS485_ADC_ADDR 0x75
@@ -66,6 +67,7 @@
/**
* struct ts5500_sbc - TS-5500 board description
+ * @name: Board model name.
* @id: Board product ID.
* @sram: Flag for SRAM option.
* @rs485: Flag for RS-485 option.
@@ -75,6 +77,7 @@
* @jumpers: Bitfield for jumpers' state.
*/
struct ts5500_sbc {
+ const char *name;
int id;
bool sram;
bool rs485;
@@ -122,13 +125,16 @@ static int __init ts5500_detect_config(struct ts5500_sbc *sbc)
if (!request_region(TS5500_PRODUCT_CODE_ADDR, 4, "ts5500"))
return -EBUSY;
- tmp = inb(TS5500_PRODUCT_CODE_ADDR);
- if (tmp != TS5500_PRODUCT_CODE) {
- pr_err("This platform is not a TS-5500 (found ID 0x%x)\n", tmp);
+ sbc->id = inb(TS5500_PRODUCT_CODE_ADDR);
+ if (sbc->id == TS5500_PRODUCT_CODE) {
+ sbc->name = "TS-5500";
+ } else if (sbc->id == TS5400_PRODUCT_CODE) {
+ sbc->name = "TS-5400";
+ } else {
+ pr_err("ts5500: unknown product code 0x%x\n", sbc->id);
ret = -ENODEV;
goto cleanup;
}
- sbc->id = tmp;
tmp = inb(TS5500_SRAM_RS485_ADC_ADDR);
sbc->sram = tmp & TS5500_SRAM;
@@ -147,48 +153,52 @@ cleanup:
return ret;
}
-static ssize_t ts5500_show_id(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct ts5500_sbc *sbc = dev_get_drvdata(dev);
- return sprintf(buf, "0x%.2x\n", sbc->id);
+ return sprintf(buf, "%s\n", sbc->name);
}
+static DEVICE_ATTR_RO(name);
-static ssize_t ts5500_show_jumpers(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct ts5500_sbc *sbc = dev_get_drvdata(dev);
- return sprintf(buf, "0x%.2x\n", sbc->jumpers >> 1);
+ return sprintf(buf, "0x%.2x\n", sbc->id);
}
+static DEVICE_ATTR_RO(id);
-#define TS5500_SHOW(field) \
- static ssize_t ts5500_show_##field(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
- { \
- struct ts5500_sbc *sbc = dev_get_drvdata(dev); \
- return sprintf(buf, "%d\n", sbc->field); \
- }
-
-TS5500_SHOW(sram)
-TS5500_SHOW(rs485)
-TS5500_SHOW(adc)
-TS5500_SHOW(ereset)
-TS5500_SHOW(itr)
+static ssize_t jumpers_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ts5500_sbc *sbc = dev_get_drvdata(dev);
-static DEVICE_ATTR(id, S_IRUGO, ts5500_show_id, NULL);
-static DEVICE_ATTR(jumpers, S_IRUGO, ts5500_show_jumpers, NULL);
-static DEVICE_ATTR(sram, S_IRUGO, ts5500_show_sram, NULL);
-static DEVICE_ATTR(rs485, S_IRUGO, ts5500_show_rs485, NULL);
-static DEVICE_ATTR(adc, S_IRUGO, ts5500_show_adc, NULL);
-static DEVICE_ATTR(ereset, S_IRUGO, ts5500_show_ereset, NULL);
-static DEVICE_ATTR(itr, S_IRUGO, ts5500_show_itr, NULL);
+ return sprintf(buf, "0x%.2x\n", sbc->jumpers >> 1);
+}
+static DEVICE_ATTR_RO(jumpers);
+
+#define TS5500_ATTR_BOOL(_field) \
+ static ssize_t _field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+ { \
+ struct ts5500_sbc *sbc = dev_get_drvdata(dev); \
+ \
+ return sprintf(buf, "%d\n", sbc->_field); \
+ } \
+ static DEVICE_ATTR_RO(_field)
+
+TS5500_ATTR_BOOL(sram);
+TS5500_ATTR_BOOL(rs485);
+TS5500_ATTR_BOOL(adc);
+TS5500_ATTR_BOOL(ereset);
+TS5500_ATTR_BOOL(itr);
static struct attribute *ts5500_attributes[] = {
&dev_attr_id.attr,
+ &dev_attr_name.attr,
&dev_attr_jumpers.attr,
&dev_attr_sram.attr,
&dev_attr_rs485.attr,
@@ -311,12 +321,14 @@ static int __init ts5500_init(void)
if (err)
goto error;
- ts5500_dio1_pdev.dev.parent = &pdev->dev;
- if (platform_device_register(&ts5500_dio1_pdev))
- dev_warn(&pdev->dev, "DIO1 block registration failed\n");
- ts5500_dio2_pdev.dev.parent = &pdev->dev;
- if (platform_device_register(&ts5500_dio2_pdev))
- dev_warn(&pdev->dev, "DIO2 block registration failed\n");
+ if (sbc->id == TS5500_PRODUCT_CODE) {
+ ts5500_dio1_pdev.dev.parent = &pdev->dev;
+ if (platform_device_register(&ts5500_dio1_pdev))
+ dev_warn(&pdev->dev, "DIO1 block registration failed\n");
+ ts5500_dio2_pdev.dev.parent = &pdev->dev;
+ if (platform_device_register(&ts5500_dio2_pdev))
+ dev_warn(&pdev->dev, "DIO2 block registration failed\n");
+ }
if (led_classdev_register(&pdev->dev, &ts5500_led_cdev))
dev_warn(&pdev->dev, "LED registration failed\n");
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index dfe605ac1bcd..3968d67d366b 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1,7 +1,7 @@
/*
* SGI UltraViolet TLB flush routines.
*
- * (c) 2008-2012 Cliff Wickman <cpw@sgi.com>, SGI.
+ * (c) 2008-2014 Cliff Wickman <cpw@sgi.com>, SGI.
*
* This code is released under the GNU General Public License version 2 or
* later.
@@ -451,7 +451,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
/*
* The reverse of the above; converts a duration in ns to a duration in cycles.
- */
+ */
static inline unsigned long long ns_2_cycles(unsigned long long ns)
{
struct cyc2ns_data *data = cyc2ns_read_begin();
@@ -563,7 +563,7 @@ static int uv1_wait_completion(struct bau_desc *bau_desc,
* UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register.
* But not currently used.
*/
-static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc)
+static unsigned long uv2_3_read_status(unsigned long offset, int rshft, int desc)
{
unsigned long descriptor_status;
@@ -606,7 +606,7 @@ int handle_uv2_busy(struct bau_control *bcp)
return FLUSH_GIVEUP;
}
-static int uv2_wait_completion(struct bau_desc *bau_desc,
+static int uv2_3_wait_completion(struct bau_desc *bau_desc,
unsigned long mmr_offset, int right_shift,
struct bau_control *bcp, long try)
{
@@ -616,7 +616,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
long busy_reps = 0;
struct ptc_stats *stat = bcp->statp;
- descriptor_stat = uv2_read_status(mmr_offset, right_shift, desc);
+ descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
/* spin on the status MMR, waiting for it to go idle */
while (descriptor_stat != UV2H_DESC_IDLE) {
@@ -658,8 +658,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
/* not to hammer on the clock */
busy_reps = 0;
ttm = get_cycles();
- if ((ttm - bcp->send_message) >
- bcp->timeout_interval)
+ if ((ttm - bcp->send_message) > bcp->timeout_interval)
return handle_uv2_busy(bcp);
}
/*
@@ -667,8 +666,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
*/
cpu_relax();
}
- descriptor_stat = uv2_read_status(mmr_offset, right_shift,
- desc);
+ descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
}
bcp->conseccompletes++;
return FLUSH_COMPLETE;
@@ -679,8 +677,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
* which register to read and position in that register based on cpu in
* current hub.
*/
-static int wait_completion(struct bau_desc *bau_desc,
- struct bau_control *bcp, long try)
+static int wait_completion(struct bau_desc *bau_desc, struct bau_control *bcp, long try)
{
int right_shift;
unsigned long mmr_offset;
@@ -695,11 +692,9 @@ static int wait_completion(struct bau_desc *bau_desc,
}
if (bcp->uvhub_version == 1)
- return uv1_wait_completion(bau_desc, mmr_offset, right_shift,
- bcp, try);
+ return uv1_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try);
else
- return uv2_wait_completion(bau_desc, mmr_offset, right_shift,
- bcp, try);
+ return uv2_3_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try);
}
/*
@@ -888,7 +883,7 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp,
struct ptc_stats *stat = bcp->statp;
struct bau_control *hmaster = bcp->uvhub_master;
struct uv1_bau_msg_header *uv1_hdr = NULL;
- struct uv2_bau_msg_header *uv2_hdr = NULL;
+ struct uv2_3_bau_msg_header *uv2_3_hdr = NULL;
if (bcp->uvhub_version == 1) {
uv1 = 1;
@@ -902,27 +897,28 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp,
if (uv1)
uv1_hdr = &bau_desc->header.uv1_hdr;
else
- uv2_hdr = &bau_desc->header.uv2_hdr;
+ /* uv2 and uv3 */
+ uv2_3_hdr = &bau_desc->header.uv2_3_hdr;
do {
if (try == 0) {
if (uv1)
uv1_hdr->msg_type = MSG_REGULAR;
else
- uv2_hdr->msg_type = MSG_REGULAR;
+ uv2_3_hdr->msg_type = MSG_REGULAR;
seq_number = bcp->message_number++;
} else {
if (uv1)
uv1_hdr->msg_type = MSG_RETRY;
else
- uv2_hdr->msg_type = MSG_RETRY;
+ uv2_3_hdr->msg_type = MSG_RETRY;
stat->s_retry_messages++;
}
if (uv1)
uv1_hdr->sequence = seq_number;
else
- uv2_hdr->sequence = seq_number;
+ uv2_3_hdr->sequence = seq_number;
index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu;
bcp->send_message = get_cycles();
@@ -1080,8 +1076,10 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
* done. The returned pointer is valid till preemption is re-enabled.
*/
const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
- struct mm_struct *mm, unsigned long start,
- unsigned long end, unsigned int cpu)
+ struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end,
+ unsigned int cpu)
{
int locals = 0;
int remotes = 0;
@@ -1268,6 +1266,7 @@ void uv_bau_message_interrupt(struct pt_regs *regs)
if (bcp->uvhub_version == 2)
process_uv2_message(&msgdesc, bcp);
else
+ /* no error workaround for uv1 or uv3 */
bau_process_message(&msgdesc, bcp, 1);
msg++;
@@ -1325,8 +1324,12 @@ static void __init enable_timeouts(void)
*/
mmr_image |= (1L << SOFTACK_MSHIFT);
if (is_uv2_hub()) {
+ /* do not touch the legacy mode bit */
/* hw bug workaround; do not use extended status */
mmr_image &= ~(1L << UV2_EXT_SHFT);
+ } else if (is_uv3_hub()) {
+ mmr_image &= ~(1L << PREFETCH_HINT_SHFT);
+ mmr_image |= (1L << SB_STATUS_SHFT);
}
write_mmr_misc_control(pnode, mmr_image);
}
@@ -1476,7 +1479,7 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,
return count;
}
- if (strict_strtol(optstr, 10, &input_arg) < 0) {
+ if (kstrtol(optstr, 10, &input_arg) < 0) {
printk(KERN_DEBUG "%s is invalid\n", optstr);
return -EINVAL;
}
@@ -1692,7 +1695,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
struct bau_desc *bau_desc;
struct bau_desc *bd2;
struct uv1_bau_msg_header *uv1_hdr;
- struct uv2_bau_msg_header *uv2_hdr;
+ struct uv2_3_bau_msg_header *uv2_3_hdr;
struct bau_control *bcp;
/*
@@ -1739,15 +1742,15 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
*/
} else {
/*
- * BIOS uses legacy mode, but UV2 hardware always
+ * BIOS uses legacy mode, but uv2 and uv3 hardware always
* uses native mode for selective broadcasts.
*/
- uv2_hdr = &bd2->header.uv2_hdr;
- uv2_hdr->swack_flag = 1;
- uv2_hdr->base_dest_nasid =
+ uv2_3_hdr = &bd2->header.uv2_3_hdr;
+ uv2_3_hdr->swack_flag = 1;
+ uv2_3_hdr->base_dest_nasid =
UV_PNODE_TO_NASID(base_pnode);
- uv2_hdr->dest_subnodeid = UV_LB_SUBNODEID;
- uv2_hdr->command = UV_NET_ENDPOINT_INTD;
+ uv2_3_hdr->dest_subnodeid = UV_LB_SUBNODEID;
+ uv2_3_hdr->command = UV_NET_ENDPOINT_INTD;
}
}
for_each_present_cpu(cpu) {
@@ -1858,6 +1861,7 @@ static int calculate_destination_timeout(void)
ts_ns *= (mult1 * mult2);
ret = ts_ns / 1000;
} else {
+ /* same destination timeout for uv2 and uv3 */
/* 4 bits 0/1 for 10/80us base, 3 bits of multiplier */
mmr_image = uv_read_local_mmr(UVH_LB_BAU_MISC_CONTROL);
mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT;
@@ -2012,8 +2016,10 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp,
bcp->uvhub_version = 1;
else if (is_uv2_hub())
bcp->uvhub_version = 2;
+ else if (is_uv3_hub())
+ bcp->uvhub_version = 3;
else {
- printk(KERN_EMERG "uvhub version not 1 or 2\n");
+ printk(KERN_EMERG "uvhub version not 1, 2 or 3\n");
return 1;
}
bcp->uvhub_master = *hmasterp;
@@ -2138,9 +2144,10 @@ static int __init uv_bau_init(void)
}
vector = UV_BAU_MESSAGE;
- for_each_possible_blade(uvhub)
+ for_each_possible_blade(uvhub) {
if (uv_blade_nr_possible_cpus(uvhub))
init_uvhub(uvhub, vector, uv_base_pnode);
+ }
alloc_intr_gate(vector, uv_bau_message_intr1);
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 424f4c97a44d..6ec7910f59bf 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -165,7 +165,7 @@ static void fix_processor_context(void)
* by __save_processor_state()
* @ctxt - structure to load the registers contents from
*/
-static void __restore_processor_state(struct saved_context *ctxt)
+static void notrace __restore_processor_state(struct saved_context *ctxt)
{
if (ctxt->misc_enable_saved)
wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
@@ -239,7 +239,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
}
/* Needed by apm.c */
-void restore_processor_state(void)
+void notrace restore_processor_state(void)
{
__restore_processor_state(&saved_context);
}
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
new file mode 100644
index 000000000000..7fde9ee438a4
--- /dev/null
+++ b/arch/x86/purgatory/Makefile
@@ -0,0 +1,30 @@
+purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
+
+targets += $(purgatory-y)
+PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+
+LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
+targets += purgatory.ro
+
+# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
+# in turn leaves some undefined symbols like __fentry__ in purgatory and not
+# sure how to relocate those. Like kexec-tools, use custom flags.
+
+KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
+
+$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
+ $(call if_changed,ld)
+
+targets += kexec-purgatory.c
+
+quiet_cmd_bin2c = BIN2C $@
+ cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c
+
+$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
+ $(call if_changed,bin2c)
+
+
+# No loaders for 32bits yet.
+ifeq ($(CONFIG_X86_64),y)
+ obj-$(CONFIG_KEXEC) += kexec-purgatory.o
+endif
diff --git a/arch/x86/purgatory/entry64.S b/arch/x86/purgatory/entry64.S
new file mode 100644
index 000000000000..d1a4291d3568
--- /dev/null
+++ b/arch/x86/purgatory/entry64.S
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2014 Red Hat Inc.
+
+ * Author(s): Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This code has been taken from kexec-tools.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+ .text
+ .balign 16
+ .code64
+ .globl entry64, entry64_regs
+
+
+entry64:
+ /* Setup a gdt that should be preserved */
+ lgdt gdt(%rip)
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Setup new stack */
+ leaq stack_init(%rip), %rsp
+ pushq $0x10 /* CS */
+ leaq new_cs_exit(%rip), %rax
+ pushq %rax
+ lretq
+new_cs_exit:
+
+ /* Load the registers */
+ movq rax(%rip), %rax
+ movq rbx(%rip), %rbx
+ movq rcx(%rip), %rcx
+ movq rdx(%rip), %rdx
+ movq rsi(%rip), %rsi
+ movq rdi(%rip), %rdi
+ movq rsp(%rip), %rsp
+ movq rbp(%rip), %rbp
+ movq r8(%rip), %r8
+ movq r9(%rip), %r9
+ movq r10(%rip), %r10
+ movq r11(%rip), %r11
+ movq r12(%rip), %r12
+ movq r13(%rip), %r13
+ movq r14(%rip), %r14
+ movq r15(%rip), %r15
+
+ /* Jump to the new code... */
+ jmpq *rip(%rip)
+
+ .section ".rodata"
+ .balign 4
+entry64_regs:
+rax: .quad 0x0
+rcx: .quad 0x0
+rdx: .quad 0x0
+rbx: .quad 0x0
+rsp: .quad 0x0
+rbp: .quad 0x0
+rsi: .quad 0x0
+rdi: .quad 0x0
+r8: .quad 0x0
+r9: .quad 0x0
+r10: .quad 0x0
+r11: .quad 0x0
+r12: .quad 0x0
+r13: .quad 0x0
+r14: .quad 0x0
+r15: .quad 0x0
+rip: .quad 0x0
+ .size entry64_regs, . - entry64_regs
+
+ /* GDT */
+ .section ".rodata"
+ .balign 16
+gdt:
+ /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ .quad gdt
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00AF
+
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+stack: .quad 0, 0
+stack_init:
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c
new file mode 100644
index 000000000000..25e068ba3382
--- /dev/null
+++ b/arch/x86/purgatory/purgatory.c
@@ -0,0 +1,72 @@
+/*
+ * purgatory: Runs between two kernels
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * Author:
+ * Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include "sha256.h"
+#include "../boot/string.h"
+
+struct sha_region {
+ unsigned long start;
+ unsigned long len;
+};
+
+unsigned long backup_dest = 0;
+unsigned long backup_src = 0;
+unsigned long backup_sz = 0;
+
+u8 sha256_digest[SHA256_DIGEST_SIZE] = { 0 };
+
+struct sha_region sha_regions[16] = {};
+
+/*
+ * On x86, second kernel requries first 640K of memory to boot. Copy
+ * first 640K to a backup region in reserved memory range so that second
+ * kernel can use first 640K.
+ */
+static int copy_backup_region(void)
+{
+ if (backup_dest)
+ memcpy((void *)backup_dest, (void *)backup_src, backup_sz);
+
+ return 0;
+}
+
+int verify_sha256_digest(void)
+{
+ struct sha_region *ptr, *end;
+ u8 digest[SHA256_DIGEST_SIZE];
+ struct sha256_state sctx;
+
+ sha256_init(&sctx);
+ end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])];
+ for (ptr = sha_regions; ptr < end; ptr++)
+ sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
+
+ sha256_final(&sctx, digest);
+
+ if (memcmp(digest, sha256_digest, sizeof(digest)))
+ return 1;
+
+ return 0;
+}
+
+void purgatory(void)
+{
+ int ret;
+
+ ret = verify_sha256_digest();
+ if (ret) {
+ /* loop forever */
+ for (;;)
+ ;
+ }
+ copy_backup_region();
+}
diff --git a/arch/x86/purgatory/setup-x86_64.S b/arch/x86/purgatory/setup-x86_64.S
new file mode 100644
index 000000000000..fe3c91ba1bd0
--- /dev/null
+++ b/arch/x86/purgatory/setup-x86_64.S
@@ -0,0 +1,58 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com)
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This code has been taken from kexec-tools.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+ .text
+ .globl purgatory_start
+ .balign 16
+purgatory_start:
+ .code64
+
+ /* Load a gdt so I know what the segment registers are */
+ lgdt gdt(%rip)
+
+ /* load the data segments */
+ movl $0x18, %eax /* data segment */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %ss
+ movl %eax, %fs
+ movl %eax, %gs
+
+ /* Setup a stack */
+ leaq lstack_end(%rip), %rsp
+
+ /* Call the C code */
+ call purgatory
+ jmp entry64
+
+ .section ".rodata"
+ .balign 16
+gdt: /* 0x00 unusable segment
+ * 0x08 unused
+ * so use them as the gdt ptr
+ */
+ .word gdt_end - gdt - 1
+ .quad gdt
+ .word 0, 0, 0
+
+ /* 0x10 4GB flat code segment */
+ .word 0xFFFF, 0x0000, 0x9A00, 0x00AF
+
+ /* 0x18 4GB flat data segment */
+ .word 0xFFFF, 0x0000, 0x9200, 0x00CF
+gdt_end:
+
+ .bss
+ .balign 4096
+lstack:
+ .skip 4096
+lstack_end:
diff --git a/arch/x86/purgatory/sha256.c b/arch/x86/purgatory/sha256.c
new file mode 100644
index 000000000000..548ca675a14a
--- /dev/null
+++ b/arch/x86/purgatory/sha256.c
@@ -0,0 +1,283 @@
+/*
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include "sha256.h"
+#include "../boot/string.h"
+
+static inline u32 Ch(u32 x, u32 y, u32 z)
+{
+ return z ^ (x & (y ^ z));
+}
+
+static inline u32 Maj(u32 x, u32 y, u32 z)
+{
+ return (x & y) | (z & (x | y));
+}
+
+#define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
+#define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
+#define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
+#define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+ W[I] = __be32_to_cpu(((__be32 *)(input))[I]);
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+ W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha256_transform(u32 *state, const u8 *input)
+{
+ u32 a, b, c, d, e, f, g, h, t1, t2;
+ u32 W[64];
+ int i;
+
+ /* load the input */
+ for (i = 0; i < 16; i++)
+ LOAD_OP(i, W, input);
+
+ /* now blend */
+ for (i = 16; i < 64; i++)
+ BLEND_OP(i, W);
+
+ /* load the state into our registers */
+ a = state[0]; b = state[1]; c = state[2]; d = state[3];
+ e = state[4]; f = state[5]; g = state[6]; h = state[7];
+
+ /* now iterate */
+ t1 = h + e1(e) + Ch(e, f, g) + 0x428a2f98 + W[0];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0x71374491 + W[1];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0xb5c0fbcf + W[2];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0xe9b5dba5 + W[3];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x3956c25b + W[4];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0x59f111f1 + W[5];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x923f82a4 + W[6];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0xab1c5ed5 + W[7];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0xd807aa98 + W[8];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0x12835b01 + W[9];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0x243185be + W[10];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0x550c7dc3 + W[11];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x72be5d74 + W[12];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0x80deb1fe + W[13];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x9bdc06a7 + W[14];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0xc19bf174 + W[15];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0xe49b69c1 + W[16];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0xefbe4786 + W[17];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0x0fc19dc6 + W[18];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0x240ca1cc + W[19];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x2de92c6f + W[20];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0x4a7484aa + W[21];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x5cb0a9dc + W[22];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0x76f988da + W[23];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0x983e5152 + W[24];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0xa831c66d + W[25];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0xb00327c8 + W[26];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0xbf597fc7 + W[27];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0xc6e00bf3 + W[28];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0xd5a79147 + W[29];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x06ca6351 + W[30];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0x14292967 + W[31];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0x27b70a85 + W[32];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0x2e1b2138 + W[33];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0x4d2c6dfc + W[34];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0x53380d13 + W[35];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x650a7354 + W[36];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0x766a0abb + W[37];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x81c2c92e + W[38];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0x92722c85 + W[39];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0xa2bfe8a1 + W[40];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0xa81a664b + W[41];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0xc24b8b70 + W[42];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0xc76c51a3 + W[43];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0xd192e819 + W[44];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0xd6990624 + W[45];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0xf40e3585 + W[46];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0x106aa070 + W[47];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0x19a4c116 + W[48];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0x1e376c08 + W[49];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0x2748774c + W[50];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0x34b0bcb5 + W[51];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x391c0cb3 + W[52];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0x4ed8aa4a + W[53];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0x5b9cca4f + W[54];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0x682e6ff3 + W[55];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ t1 = h + e1(e) + Ch(e, f, g) + 0x748f82ee + W[56];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1+t2;
+ t1 = g + e1(d) + Ch(d, e, f) + 0x78a5636f + W[57];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1+t2;
+ t1 = f + e1(c) + Ch(c, d, e) + 0x84c87814 + W[58];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1+t2;
+ t1 = e + e1(b) + Ch(b, c, d) + 0x8cc70208 + W[59];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1+t2;
+ t1 = d + e1(a) + Ch(a, b, c) + 0x90befffa + W[60];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1+t2;
+ t1 = c + e1(h) + Ch(h, a, b) + 0xa4506ceb + W[61];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1+t2;
+ t1 = b + e1(g) + Ch(g, h, a) + 0xbef9a3f7 + W[62];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1+t2;
+ t1 = a + e1(f) + Ch(f, g, h) + 0xc67178f2 + W[63];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1+t2;
+
+ state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+ state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+ /* clear any sensitive info... */
+ a = b = c = d = e = f = g = h = t1 = t2 = 0;
+ memset(W, 0, 64 * sizeof(u32));
+}
+
+int sha256_init(struct sha256_state *sctx)
+{
+ sctx->state[0] = SHA256_H0;
+ sctx->state[1] = SHA256_H1;
+ sctx->state[2] = SHA256_H2;
+ sctx->state[3] = SHA256_H3;
+ sctx->state[4] = SHA256_H4;
+ sctx->state[5] = SHA256_H5;
+ sctx->state[6] = SHA256_H6;
+ sctx->state[7] = SHA256_H7;
+ sctx->count = 0;
+
+ return 0;
+}
+
+int sha256_update(struct sha256_state *sctx, const u8 *data, unsigned int len)
+{
+ unsigned int partial, done;
+ const u8 *src;
+
+ partial = sctx->count & 0x3f;
+ sctx->count += len;
+ done = 0;
+ src = data;
+
+ if ((partial + len) > 63) {
+ if (partial) {
+ done = -partial;
+ memcpy(sctx->buf + partial, data, done + 64);
+ src = sctx->buf;
+ }
+
+ do {
+ sha256_transform(sctx->state, src);
+ done += 64;
+ src = data + done;
+ } while (done + 63 < len);
+
+ partial = 0;
+ }
+ memcpy(sctx->buf + partial, src, len - done);
+
+ return 0;
+}
+
+int sha256_final(struct sha256_state *sctx, u8 *out)
+{
+ __be32 *dst = (__be32 *)out;
+ __be64 bits;
+ unsigned int index, pad_len;
+ int i;
+ static const u8 padding[64] = { 0x80, };
+
+ /* Save number of bits */
+ bits = cpu_to_be64(sctx->count << 3);
+
+ /* Pad out to 56 mod 64. */
+ index = sctx->count & 0x3f;
+ pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
+ sha256_update(sctx, padding, pad_len);
+
+ /* Append length (before padding) */
+ sha256_update(sctx, (const u8 *)&bits, sizeof(bits));
+
+ /* Store state in digest */
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
+
+ /* Zeroize sensitive information. */
+ memset(sctx, 0, sizeof(*sctx));
+
+ return 0;
+}
diff --git a/arch/x86/purgatory/sha256.h b/arch/x86/purgatory/sha256.h
new file mode 100644
index 000000000000..bd15a4127735
--- /dev/null
+++ b/arch/x86/purgatory/sha256.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * Author: Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef SHA256_H
+#define SHA256_H
+
+
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+extern int sha256_init(struct sha256_state *sctx);
+extern int sha256_update(struct sha256_state *sctx, const u8 *input,
+ unsigned int length);
+extern int sha256_final(struct sha256_state *sctx, u8 *hash);
+
+#endif /* SHA256_H */
diff --git a/arch/x86/purgatory/stack.S b/arch/x86/purgatory/stack.S
new file mode 100644
index 000000000000..3cefba1fefc8
--- /dev/null
+++ b/arch/x86/purgatory/stack.S
@@ -0,0 +1,19 @@
+/*
+ * purgatory: stack
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+ /* A stack for the loaded kernel.
+ * Seperate and in the data section so it can be prepopulated.
+ */
+ .data
+ .balign 4096
+ .globl stack, stack_end
+
+stack:
+ .skip 4096
+stack_end:
diff --git a/arch/x86/purgatory/string.c b/arch/x86/purgatory/string.c
new file mode 100644
index 000000000000..d886b1fa36f0
--- /dev/null
+++ b/arch/x86/purgatory/string.c
@@ -0,0 +1,13 @@
+/*
+ * Simple string functions.
+ *
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * Author:
+ * Vivek Goyal <vgoyal@redhat.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include "../boot/string.c"
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index d6b867921612..028b78168d85 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -360,3 +360,6 @@
351 i386 sched_setattr sys_sched_setattr
352 i386 sched_getattr sys_sched_getattr
353 i386 renameat2 sys_renameat2
+354 i386 seccomp sys_seccomp
+355 i386 getrandom sys_getrandom
+356 i386 memfd_create sys_memfd_create
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index ec255a1646d2..35dd922727b9 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -323,6 +323,10 @@
314 common sched_setattr sys_sched_setattr
315 common sched_getattr sys_sched_getattr
316 common renameat2 sys_renameat2
+317 common seccomp sys_seccomp
+318 common getrandom sys_getrandom
+319 common memfd_create sys_memfd_create
+320 common kexec_file_load sys_kexec_file_load
#
# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index 0feee2fd5077..25a1022dd793 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -216,6 +216,5 @@ extern long elf_aux_hwcap;
#define ELF_HWCAP (elf_aux_hwcap)
#define SET_PERSONALITY(ex) do ; while(0)
-#define __HAVE_ARCH_GATE_AREA 1
#endif
diff --git a/arch/x86/um/asm/processor.h b/arch/x86/um/asm/processor.h
index 04f82e020f2b..2a206d2b14ab 100644
--- a/arch/x86/um/asm/processor.h
+++ b/arch/x86/um/asm/processor.h
@@ -25,7 +25,8 @@ static inline void rep_nop(void)
__asm__ __volatile__("rep;nop": : :"memory");
}
-#define cpu_relax() rep_nop()
+#define cpu_relax() rep_nop()
+#define cpu_relax_lowlatency() cpu_relax()
#include <asm/processor-generic.h>
diff --git a/arch/x86/um/mem_64.c b/arch/x86/um/mem_64.c
index c6492e75797b..f8fecaddcc0d 100644
--- a/arch/x86/um/mem_64.c
+++ b/arch/x86/um/mem_64.c
@@ -9,18 +9,3 @@ const char *arch_vma_name(struct vm_area_struct *vma)
return NULL;
}
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
- return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
- return 0;
-}
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 5e04a1c899fa..79d824551c1a 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -370,13 +370,12 @@ struct rt_sigframe
char retcode[8];
};
-int setup_signal_stack_sc(unsigned long stack_top, int sig,
- struct k_sigaction *ka, struct pt_regs *regs,
- sigset_t *mask)
+int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *mask)
{
struct sigframe __user *frame;
void __user *restorer;
- int err = 0;
+ int err = 0, sig = ksig->sig;
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
stack_top = ((stack_top + 4) & -16UL) - 4;
@@ -385,8 +384,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
return 1;
restorer = frame->retcode;
- if (ka->sa.sa_flags & SA_RESTORER)
- restorer = ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ restorer = ksig->ka.sa.sa_restorer;
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
@@ -410,20 +409,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
return err;
PT_REGS_SP(regs) = (unsigned long) frame;
- PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+ PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) 0;
PT_REGS_CX(regs) = (unsigned long) 0;
return 0;
}
-int setup_signal_stack_si(unsigned long stack_top, int sig,
- struct k_sigaction *ka, struct pt_regs *regs,
- siginfo_t *info, sigset_t *mask)
+int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *mask)
{
struct rt_sigframe __user *frame;
void __user *restorer;
- int err = 0;
+ int err = 0, sig = ksig->sig;
stack_top &= -8UL;
frame = (struct rt_sigframe __user *) stack_top - 1;
@@ -431,14 +429,14 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
return 1;
restorer = frame->retcode;
- if (ka->sa.sa_flags & SA_RESTORER)
- restorer = ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ restorer = ksig->ka.sa.sa_restorer;
err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
PT_REGS_SP(regs));
@@ -457,7 +455,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
return err;
PT_REGS_SP(regs) = (unsigned long) frame;
- PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+ PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) &frame->info;
PT_REGS_CX(regs) = (unsigned long) &frame->uc;
@@ -502,12 +500,11 @@ struct rt_sigframe
struct _fpstate fpstate;
};
-int setup_signal_stack_si(unsigned long stack_top, int sig,
- struct k_sigaction *ka, struct pt_regs * regs,
- siginfo_t *info, sigset_t *set)
+int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
{
struct rt_sigframe __user *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16);
@@ -517,8 +514,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto out;
- if (ka->sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, info);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err)
goto out;
}
@@ -543,8 +540,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
* already in userspace.
*/
/* x86-64 should always use SA_RESTORER. */
- if (ka->sa.sa_flags & SA_RESTORER)
- err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ err |= __put_user(ksig->ka.sa.sa_restorer, &frame->pretcode);
else
/* could use a vstub here */
return err;
@@ -570,7 +567,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
*/
PT_REGS_SI(regs) = (unsigned long) &frame->info;
PT_REGS_DX(regs) = (unsigned long) &frame->uc;
- PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
+ PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
out:
return err;
}
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index 61b04fe36e66..5a4affe025e8 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -10,7 +10,7 @@ VDSO32-$(CONFIG_X86_32) := y
VDSO32-$(CONFIG_COMPAT) := y
# files to link into the vdso
-vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vdso-fakesections.o
+vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
# files to link into kernel
obj-y += vma.o
@@ -37,7 +37,8 @@ vdso_img_sodbg := $(vdso_img-y:%=vdso%.so.dbg)
obj-y += $(vdso_img_objs)
targets += $(vdso_img_cfiles)
targets += $(vdso_img_sodbg)
-.SECONDARY: $(vdso_img-y:%=$(obj)/vdso-image-%.c)
+.SECONDARY: $(vdso_img-y:%=$(obj)/vdso-image-%.c) \
+ $(vdso_img-y:%=$(obj)/vdso%.so)
export CPPFLAGS_vdso.lds += -P -C
@@ -54,10 +55,10 @@ hostprogs-y += vdso2c
quiet_cmd_vdso2c = VDSO2C $@
define cmd_vdso2c
- $(obj)/vdso2c $< $@
+ $(obj)/vdso2c $< $(<:%.dbg=%) $@
endef
-$(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso2c FORCE
+$(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE
$(call if_changed,vdso2c)
#
@@ -113,6 +114,10 @@ $(obj)/%-x32.o: $(obj)/%.o FORCE
targets += vdsox32.lds $(vobjx32s-y)
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg
+ $(call if_changed,objcopy)
+
$(obj)/vdsox32.so.dbg: $(src)/vdsox32.lds $(vobjx32s) FORCE
$(call if_changed,vdso)
@@ -134,7 +139,7 @@ override obj-dirs = $(dir $(obj)) $(obj)/vdso32/
targets += vdso32/vdso32.lds
targets += vdso32/note.o vdso32/vclock_gettime.o $(vdso32.so-y:%=vdso32/%.o)
-targets += vdso32/vclock_gettime.o vdso32/vdso-fakesections.o
+targets += vdso32/vclock_gettime.o
$(obj)/vdso32.o: $(vdso32-images:%=$(obj)/%)
@@ -156,7 +161,6 @@ $(vdso32-images:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
$(vdso32-images:%=$(obj)/%.dbg): $(obj)/vdso32-%.so.dbg: FORCE \
$(obj)/vdso32/vdso32.lds \
$(obj)/vdso32/vclock_gettime.o \
- $(obj)/vdso32/vdso-fakesections.o \
$(obj)/vdso32/note.o \
$(obj)/vdso32/%.o
$(call if_changed,vdso)
diff --git a/arch/x86/vdso/vdso-fakesections.c b/arch/x86/vdso/vdso-fakesections.c
deleted file mode 100644
index aa5fbfab20a5..000000000000
--- a/arch/x86/vdso/vdso-fakesections.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2014 Andy Lutomirski
- * Subject to the GNU Public License, v.2
- *
- * String table for loadable section headers. See vdso2c.h for why
- * this exists.
- */
-
-const char fake_shstrtab[] __attribute__((section(".fake_shstrtab"))) =
- ".hash\0"
- ".dynsym\0"
- ".dynstr\0"
- ".gnu.version\0"
- ".gnu.version_d\0"
- ".dynamic\0"
- ".rodata\0"
- ".fake_shstrtab\0" /* Yay, self-referential code. */
- ".note\0"
- ".eh_frame_hdr\0"
- ".eh_frame\0"
- ".text";
diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S
index 9197544eea9a..de2c921025f5 100644
--- a/arch/x86/vdso/vdso-layout.lds.S
+++ b/arch/x86/vdso/vdso-layout.lds.S
@@ -18,6 +18,25 @@
SECTIONS
{
+ /*
+ * User/kernel shared data is before the vDSO. This may be a little
+ * uglier than putting it after the vDSO, but it avoids issues with
+ * non-allocatable things that dangle past the end of the PT_LOAD
+ * segment.
+ */
+
+ vvar_start = . - 2 * PAGE_SIZE;
+ vvar_page = vvar_start;
+
+ /* Place all vvars at the offsets in asm/vvar.h. */
+#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
+#define __VVAR_KERNEL_LDS
+#include <asm/vvar.h>
+#undef __VVAR_KERNEL_LDS
+#undef EMIT_VVAR
+
+ hpet_page = vvar_start + PAGE_SIZE;
+
. = SIZEOF_HEADERS;
.hash : { *(.hash) } :text
@@ -74,31 +93,6 @@ SECTIONS
.altinstructions : { *(.altinstructions) } :text
.altinstr_replacement : { *(.altinstr_replacement) } :text
- /*
- * The remainder of the vDSO consists of special pages that are
- * shared between the kernel and userspace. It needs to be at the
- * end so that it doesn't overlap the mapping of the actual
- * vDSO image.
- */
-
- . = ALIGN(PAGE_SIZE);
- vvar_page = .;
-
- /* Place all vvars at the offsets in asm/vvar.h. */
-#define EMIT_VVAR(name, offset) vvar_ ## name = vvar_page + offset;
-#define __VVAR_KERNEL_LDS
-#include <asm/vvar.h>
-#undef __VVAR_KERNEL_LDS
-#undef EMIT_VVAR
-
- . = vvar_page + PAGE_SIZE;
-
- hpet_page = .;
- . = . + PAGE_SIZE;
-
- . = ALIGN(PAGE_SIZE);
- end_mapping = .;
-
/DISCARD/ : {
*(.discard)
*(.discard.*)
diff --git a/arch/x86/vdso/vdso2c.c b/arch/x86/vdso/vdso2c.c
index 238dbe82776e..8627db24a7f6 100644
--- a/arch/x86/vdso/vdso2c.c
+++ b/arch/x86/vdso/vdso2c.c
@@ -1,3 +1,53 @@
+/*
+ * vdso2c - A vdso image preparation tool
+ * Copyright (c) 2014 Andy Lutomirski and others
+ * Licensed under the GPL v2
+ *
+ * vdso2c requires stripped and unstripped input. It would be trivial
+ * to fully strip the input in here, but, for reasons described below,
+ * we need to write a section table. Doing this is more or less
+ * equivalent to dropping all non-allocatable sections, but it's
+ * easier to let objcopy handle that instead of doing it ourselves.
+ * If we ever need to do something fancier than what objcopy provides,
+ * it would be straightforward to add here.
+ *
+ * We're keep a section table for a few reasons:
+ *
+ * The Go runtime had a couple of bugs: it would read the section
+ * table to try to figure out how many dynamic symbols there were (it
+ * shouldn't have looked at the section table at all) and, if there
+ * were no SHT_SYNDYM section table entry, it would use an
+ * uninitialized value for the number of symbols. An empty DYNSYM
+ * table would work, but I see no reason not to write a valid one (and
+ * keep full performance for old Go programs). This hack is only
+ * needed on x86_64.
+ *
+ * The bug was introduced on 2012-08-31 by:
+ * https://code.google.com/p/go/source/detail?r=56ea40aac72b
+ * and was fixed on 2014-06-13 by:
+ * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
+ *
+ * Binutils has issues debugging the vDSO: it reads the section table to
+ * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
+ * would break build-id if we removed the section table. Binutils
+ * also requires that shstrndx != 0. See:
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
+ *
+ * elfutils might not look for PT_NOTE if there is a section table at
+ * all. I don't know whether this matters for any practical purpose.
+ *
+ * For simplicity, rather than hacking up a partial section table, we
+ * just write a mostly complete one. We omit non-dynamic symbols,
+ * though, since they're rather large.
+ *
+ * Once binutils gets fixed, we might be able to drop this for all but
+ * the 64-bit vdso, since build-id only works in kernel RPMs, and
+ * systems that update to new enough kernel RPMs will likely update
+ * binutils in sync. build-id has never worked for home-built kernel
+ * RPMs without manual symlinking, and I suspect that no one ever does
+ * that.
+ */
+
#include <inttypes.h>
#include <stdint.h>
#include <unistd.h>
@@ -20,9 +70,9 @@ const char *outfilename;
/* Symbols that we need in vdso2c. */
enum {
+ sym_vvar_start,
sym_vvar_page,
sym_hpet_page,
- sym_end_mapping,
sym_VDSO_FAKE_SECTION_TABLE_START,
sym_VDSO_FAKE_SECTION_TABLE_END,
};
@@ -38,9 +88,9 @@ struct vdso_sym {
};
struct vdso_sym required_syms[] = {
+ [sym_vvar_start] = {"vvar_start", true},
[sym_vvar_page] = {"vvar_page", true},
[sym_hpet_page] = {"hpet_page", true},
- [sym_end_mapping] = {"end_mapping", true},
[sym_VDSO_FAKE_SECTION_TABLE_START] = {
"VDSO_FAKE_SECTION_TABLE_START", false
},
@@ -61,7 +111,8 @@ static void fail(const char *format, ...)
va_start(ap, format);
fprintf(stderr, "Error: ");
vfprintf(stderr, format, ap);
- unlink(outfilename);
+ if (outfilename)
+ unlink(outfilename);
exit(1);
va_end(ap);
}
@@ -96,9 +147,11 @@ extern void bad_put_le(void);
#define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
-#define BITSFUNC3(name, bits) name##bits
-#define BITSFUNC2(name, bits) BITSFUNC3(name, bits)
-#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS)
+#define BITSFUNC3(name, bits, suffix) name##bits##suffix
+#define BITSFUNC2(name, bits, suffix) BITSFUNC3(name, bits, suffix)
+#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS, )
+
+#define INT_BITS BITSFUNC2(int, ELF_BITS, _t)
#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
@@ -112,30 +165,53 @@ extern void bad_put_le(void);
#include "vdso2c.h"
#undef ELF_BITS
-static void go(void *addr, size_t len, FILE *outfile, const char *name)
+static void go(void *raw_addr, size_t raw_len,
+ void *stripped_addr, size_t stripped_len,
+ FILE *outfile, const char *name)
{
- Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr;
+ Elf64_Ehdr *hdr = (Elf64_Ehdr *)raw_addr;
if (hdr->e_ident[EI_CLASS] == ELFCLASS64) {
- go64(addr, len, outfile, name);
+ go64(raw_addr, raw_len, stripped_addr, stripped_len,
+ outfile, name);
} else if (hdr->e_ident[EI_CLASS] == ELFCLASS32) {
- go32(addr, len, outfile, name);
+ go32(raw_addr, raw_len, stripped_addr, stripped_len,
+ outfile, name);
} else {
fail("unknown ELF class\n");
}
}
+static void map_input(const char *name, void **addr, size_t *len, int prot)
+{
+ off_t tmp_len;
+
+ int fd = open(name, O_RDONLY);
+ if (fd == -1)
+ err(1, "%s", name);
+
+ tmp_len = lseek(fd, 0, SEEK_END);
+ if (tmp_len == (off_t)-1)
+ err(1, "lseek");
+ *len = (size_t)tmp_len;
+
+ *addr = mmap(NULL, tmp_len, prot, MAP_PRIVATE, fd, 0);
+ if (*addr == MAP_FAILED)
+ err(1, "mmap");
+
+ close(fd);
+}
+
int main(int argc, char **argv)
{
- int fd;
- off_t len;
- void *addr;
+ size_t raw_len, stripped_len;
+ void *raw_addr, *stripped_addr;
FILE *outfile;
char *name, *tmp;
int namelen;
- if (argc != 3) {
- printf("Usage: vdso2c INPUT OUTPUT\n");
+ if (argc != 4) {
+ printf("Usage: vdso2c RAW_INPUT STRIPPED_INPUT OUTPUT\n");
return 1;
}
@@ -143,7 +219,7 @@ int main(int argc, char **argv)
* Figure out the struct name. If we're writing to a .so file,
* generate raw output insted.
*/
- name = strdup(argv[2]);
+ name = strdup(argv[3]);
namelen = strlen(name);
if (namelen >= 3 && !strcmp(name + namelen - 3, ".so")) {
name = NULL;
@@ -159,26 +235,18 @@ int main(int argc, char **argv)
*tmp = '_';
}
- fd = open(argv[1], O_RDONLY);
- if (fd == -1)
- err(1, "%s", argv[1]);
-
- len = lseek(fd, 0, SEEK_END);
- if (len == (off_t)-1)
- err(1, "lseek");
-
- addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (addr == MAP_FAILED)
- err(1, "mmap");
+ map_input(argv[1], &raw_addr, &raw_len, PROT_READ);
+ map_input(argv[2], &stripped_addr, &stripped_len, PROT_READ);
- outfilename = argv[2];
+ outfilename = argv[3];
outfile = fopen(outfilename, "w");
if (!outfile)
err(1, "%s", argv[2]);
- go(addr, (size_t)len, outfile, name);
+ go(raw_addr, raw_len, stripped_addr, stripped_len, outfile, name);
- munmap(addr, len);
+ munmap(raw_addr, raw_len);
+ munmap(stripped_addr, stripped_len);
fclose(outfile);
return 0;
diff --git a/arch/x86/vdso/vdso2c.h b/arch/x86/vdso/vdso2c.h
index 11b65d4f9414..fd57829b30d8 100644
--- a/arch/x86/vdso/vdso2c.h
+++ b/arch/x86/vdso/vdso2c.h
@@ -4,139 +4,23 @@
* are built for 32-bit userspace.
*/
-/*
- * We're writing a section table for a few reasons:
- *
- * The Go runtime had a couple of bugs: it would read the section
- * table to try to figure out how many dynamic symbols there were (it
- * shouldn't have looked at the section table at all) and, if there
- * were no SHT_SYNDYM section table entry, it would use an
- * uninitialized value for the number of symbols. An empty DYNSYM
- * table would work, but I see no reason not to write a valid one (and
- * keep full performance for old Go programs). This hack is only
- * needed on x86_64.
- *
- * The bug was introduced on 2012-08-31 by:
- * https://code.google.com/p/go/source/detail?r=56ea40aac72b
- * and was fixed on 2014-06-13 by:
- * https://code.google.com/p/go/source/detail?r=fc1cd5e12595
- *
- * Binutils has issues debugging the vDSO: it reads the section table to
- * find SHT_NOTE; it won't look at PT_NOTE for the in-memory vDSO, which
- * would break build-id if we removed the section table. Binutils
- * also requires that shstrndx != 0. See:
- * https://sourceware.org/bugzilla/show_bug.cgi?id=17064
- *
- * elfutils might not look for PT_NOTE if there is a section table at
- * all. I don't know whether this matters for any practical purpose.
- *
- * For simplicity, rather than hacking up a partial section table, we
- * just write a mostly complete one. We omit non-dynamic symbols,
- * though, since they're rather large.
- *
- * Once binutils gets fixed, we might be able to drop this for all but
- * the 64-bit vdso, since build-id only works in kernel RPMs, and
- * systems that update to new enough kernel RPMs will likely update
- * binutils in sync. build-id has never worked for home-built kernel
- * RPMs without manual symlinking, and I suspect that no one ever does
- * that.
- */
-struct BITSFUNC(fake_sections)
-{
- ELF(Shdr) *table;
- unsigned long table_offset;
- int count, max_count;
-
- int in_shstrndx;
- unsigned long shstr_offset;
- const char *shstrtab;
- size_t shstrtab_len;
-
- int out_shstrndx;
-};
-
-static unsigned int BITSFUNC(find_shname)(struct BITSFUNC(fake_sections) *out,
- const char *name)
-{
- const char *outname = out->shstrtab;
- while (outname - out->shstrtab < out->shstrtab_len) {
- if (!strcmp(name, outname))
- return (outname - out->shstrtab) + out->shstr_offset;
- outname += strlen(outname) + 1;
- }
-
- if (*name)
- printf("Warning: could not find output name \"%s\"\n", name);
- return out->shstr_offset + out->shstrtab_len - 1; /* Use a null. */
-}
-
-static void BITSFUNC(init_sections)(struct BITSFUNC(fake_sections) *out)
-{
- if (!out->in_shstrndx)
- fail("didn't find the fake shstrndx\n");
-
- memset(out->table, 0, out->max_count * sizeof(ELF(Shdr)));
-
- if (out->max_count < 1)
- fail("we need at least two fake output sections\n");
-
- PUT_LE(&out->table[0].sh_type, SHT_NULL);
- PUT_LE(&out->table[0].sh_name, BITSFUNC(find_shname)(out, ""));
-
- out->count = 1;
-}
-
-static void BITSFUNC(copy_section)(struct BITSFUNC(fake_sections) *out,
- int in_idx, const ELF(Shdr) *in,
- const char *name)
-{
- uint64_t flags = GET_LE(&in->sh_flags);
-
- bool copy = flags & SHF_ALLOC &&
- (GET_LE(&in->sh_size) ||
- (GET_LE(&in->sh_type) != SHT_RELA &&
- GET_LE(&in->sh_type) != SHT_REL)) &&
- strcmp(name, ".altinstructions") &&
- strcmp(name, ".altinstr_replacement");
-
- if (!copy)
- return;
-
- if (out->count >= out->max_count)
- fail("too many copied sections (max = %d)\n", out->max_count);
-
- if (in_idx == out->in_shstrndx)
- out->out_shstrndx = out->count;
-
- out->table[out->count] = *in;
- PUT_LE(&out->table[out->count].sh_name,
- BITSFUNC(find_shname)(out, name));
-
- /* elfutils requires that a strtab have the correct type. */
- if (!strcmp(name, ".fake_shstrtab"))
- PUT_LE(&out->table[out->count].sh_type, SHT_STRTAB);
-
- out->count++;
-}
-
-static void BITSFUNC(go)(void *addr, size_t len,
+static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
+ void *stripped_addr, size_t stripped_len,
FILE *outfile, const char *name)
{
int found_load = 0;
unsigned long load_size = -1; /* Work around bogus warning */
- unsigned long data_size;
- ELF(Ehdr) *hdr = (ELF(Ehdr) *)addr;
+ unsigned long mapping_size;
+ ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
int i;
unsigned long j;
ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
*alt_sec = NULL;
ELF(Dyn) *dyn = 0, *dyn_end = 0;
const char *secstrings;
- uint64_t syms[NSYMS] = {};
-
- struct BITSFUNC(fake_sections) fake_sections = {};
+ INT_BITS syms[NSYMS] = {};
- ELF(Phdr) *pt = (ELF(Phdr) *)(addr + GET_LE(&hdr->e_phoff));
+ ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_LE(&hdr->e_phoff));
/* Walk the segment table. */
for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
@@ -154,14 +38,16 @@ static void BITSFUNC(go)(void *addr, size_t len,
load_size = GET_LE(&pt[i].p_memsz);
found_load = 1;
} else if (GET_LE(&pt[i].p_type) == PT_DYNAMIC) {
- dyn = addr + GET_LE(&pt[i].p_offset);
- dyn_end = addr + GET_LE(&pt[i].p_offset) +
+ dyn = raw_addr + GET_LE(&pt[i].p_offset);
+ dyn_end = raw_addr + GET_LE(&pt[i].p_offset) +
GET_LE(&pt[i].p_memsz);
}
}
if (!found_load)
fail("no PT_LOAD seg\n");
- data_size = (load_size + 4095) / 4096 * 4096;
+
+ if (stripped_len < load_size)
+ fail("stripped input is too short\n");
/* Walk the dynamic table */
for (i = 0; dyn + i < dyn_end &&
@@ -173,11 +59,11 @@ static void BITSFUNC(go)(void *addr, size_t len,
}
/* Walk the section table */
- secstrings_hdr = addr + GET_LE(&hdr->e_shoff) +
+ secstrings_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx);
- secstrings = addr + GET_LE(&secstrings_hdr->sh_offset);
+ secstrings = raw_addr + GET_LE(&secstrings_hdr->sh_offset);
for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
- ELF(Shdr) *sh = addr + GET_LE(&hdr->e_shoff) +
+ ELF(Shdr) *sh = raw_addr + GET_LE(&hdr->e_shoff) +
GET_LE(&hdr->e_shentsize) * i;
if (GET_LE(&sh->sh_type) == SHT_SYMTAB)
symtab_hdr = sh;
@@ -190,7 +76,7 @@ static void BITSFUNC(go)(void *addr, size_t len,
if (!symtab_hdr)
fail("no symbol table\n");
- strtab_hdr = addr + GET_LE(&hdr->e_shoff) +
+ strtab_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
GET_LE(&hdr->e_shentsize) * GET_LE(&symtab_hdr->sh_link);
/* Walk the symbol table */
@@ -198,9 +84,9 @@ static void BITSFUNC(go)(void *addr, size_t len,
i < GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize);
i++) {
int k;
- ELF(Sym) *sym = addr + GET_LE(&symtab_hdr->sh_offset) +
+ ELF(Sym) *sym = raw_addr + GET_LE(&symtab_hdr->sh_offset) +
GET_LE(&symtab_hdr->sh_entsize) * i;
- const char *name = addr + GET_LE(&strtab_hdr->sh_offset) +
+ const char *name = raw_addr + GET_LE(&strtab_hdr->sh_offset) +
GET_LE(&sym->st_name);
for (k = 0; k < NSYMS; k++) {
@@ -209,51 +95,17 @@ static void BITSFUNC(go)(void *addr, size_t len,
fail("duplicate symbol %s\n",
required_syms[k].name);
}
+
+ /*
+ * Careful: we use negative addresses, but
+ * st_value is unsigned, so we rely
+ * on syms[k] being a signed type of the
+ * correct width.
+ */
syms[k] = GET_LE(&sym->st_value);
}
}
-
- if (!strcmp(name, "fake_shstrtab")) {
- ELF(Shdr) *sh;
-
- fake_sections.in_shstrndx = GET_LE(&sym->st_shndx);
- fake_sections.shstrtab = addr + GET_LE(&sym->st_value);
- fake_sections.shstrtab_len = GET_LE(&sym->st_size);
- sh = addr + GET_LE(&hdr->e_shoff) +
- GET_LE(&hdr->e_shentsize) *
- fake_sections.in_shstrndx;
- fake_sections.shstr_offset = GET_LE(&sym->st_value) -
- GET_LE(&sh->sh_addr);
- }
- }
-
- /* Build the output section table. */
- if (!syms[sym_VDSO_FAKE_SECTION_TABLE_START] ||
- !syms[sym_VDSO_FAKE_SECTION_TABLE_END])
- fail("couldn't find fake section table\n");
- if ((syms[sym_VDSO_FAKE_SECTION_TABLE_END] -
- syms[sym_VDSO_FAKE_SECTION_TABLE_START]) % sizeof(ELF(Shdr)))
- fail("fake section table size isn't a multiple of sizeof(Shdr)\n");
- fake_sections.table = addr + syms[sym_VDSO_FAKE_SECTION_TABLE_START];
- fake_sections.table_offset = syms[sym_VDSO_FAKE_SECTION_TABLE_START];
- fake_sections.max_count = (syms[sym_VDSO_FAKE_SECTION_TABLE_END] -
- syms[sym_VDSO_FAKE_SECTION_TABLE_START]) /
- sizeof(ELF(Shdr));
-
- BITSFUNC(init_sections)(&fake_sections);
- for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
- ELF(Shdr) *sh = addr + GET_LE(&hdr->e_shoff) +
- GET_LE(&hdr->e_shentsize) * i;
- BITSFUNC(copy_section)(&fake_sections, i, sh,
- secstrings + GET_LE(&sh->sh_name));
}
- if (!fake_sections.out_shstrndx)
- fail("didn't generate shstrndx?!?\n");
-
- PUT_LE(&hdr->e_shoff, fake_sections.table_offset);
- PUT_LE(&hdr->e_shentsize, sizeof(ELF(Shdr)));
- PUT_LE(&hdr->e_shnum, fake_sections.count);
- PUT_LE(&hdr->e_shstrndx, fake_sections.out_shstrndx);
/* Validate mapping addresses. */
for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) {
@@ -263,21 +115,23 @@ static void BITSFUNC(go)(void *addr, size_t len,
if (syms[i] % 4096)
fail("%s must be a multiple of 4096\n",
required_syms[i].name);
- if (syms[i] < data_size)
- fail("%s must be after the text mapping\n",
+ if (syms[sym_vvar_start] > syms[i] + 4096)
+ fail("%s underruns begin_vvar\n",
required_syms[i].name);
- if (syms[sym_end_mapping] < syms[i] + 4096)
- fail("%s overruns end_mapping\n",
+ if (syms[i] + 4096 > 0)
+ fail("%s is on the wrong side of the vdso text\n",
required_syms[i].name);
}
- if (syms[sym_end_mapping] % 4096)
- fail("end_mapping must be a multiple of 4096\n");
+ if (syms[sym_vvar_start] % 4096)
+ fail("vvar_begin must be a multiple of 4096\n");
if (!name) {
- fwrite(addr, load_size, 1, outfile);
+ fwrite(stripped_addr, stripped_len, 1, outfile);
return;
}
+ mapping_size = (stripped_len + 4095) / 4096 * 4096;
+
fprintf(outfile, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
fprintf(outfile, "#include <linux/linkage.h>\n");
fprintf(outfile, "#include <asm/page_types.h>\n");
@@ -285,20 +139,21 @@ static void BITSFUNC(go)(void *addr, size_t len,
fprintf(outfile, "\n");
fprintf(outfile,
"static unsigned char raw_data[%lu] __page_aligned_data = {",
- data_size);
- for (j = 0; j < load_size; j++) {
+ mapping_size);
+ for (j = 0; j < stripped_len; j++) {
if (j % 10 == 0)
fprintf(outfile, "\n\t");
- fprintf(outfile, "0x%02X, ", (int)((unsigned char *)addr)[j]);
+ fprintf(outfile, "0x%02X, ",
+ (int)((unsigned char *)stripped_addr)[j]);
}
fprintf(outfile, "\n};\n\n");
fprintf(outfile, "static struct page *pages[%lu];\n\n",
- data_size / 4096);
+ mapping_size / 4096);
fprintf(outfile, "const struct vdso_image %s = {\n", name);
fprintf(outfile, "\t.data = raw_data,\n");
- fprintf(outfile, "\t.size = %lu,\n", data_size);
+ fprintf(outfile, "\t.size = %lu,\n", mapping_size);
fprintf(outfile, "\t.text_mapping = {\n");
fprintf(outfile, "\t\t.name = \"[vdso]\",\n");
fprintf(outfile, "\t\t.pages = pages,\n");
@@ -311,8 +166,8 @@ static void BITSFUNC(go)(void *addr, size_t len,
}
for (i = 0; i < NSYMS; i++) {
if (required_syms[i].export && syms[i])
- fprintf(outfile, "\t.sym_%s = 0x%" PRIx64 ",\n",
- required_syms[i].name, syms[i]);
+ fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
+ required_syms[i].name, (int64_t)syms[i]);
}
fprintf(outfile, "};\n");
}
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index e4f7781ee162..e904c270573b 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -115,23 +115,6 @@ static __init int ia32_binfmt_init(void)
return 0;
}
__initcall(ia32_binfmt_init);
-#endif
-
-#else /* CONFIG_X86_32 */
-
-struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
-{
- return NULL;
-}
-
-int in_gate_area(struct mm_struct *mm, unsigned long addr)
-{
- return 0;
-}
-
-int in_gate_area_no_mm(unsigned long addr)
-{
- return 0;
-}
+#endif /* CONFIG_SYSCTL */
#endif /* CONFIG_X86_64 */
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 5a5176de8d0a..970463b566cf 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -93,7 +93,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
- unsigned long addr;
+ unsigned long addr, text_start;
int ret = 0;
static struct page *no_pages[] = {NULL};
static struct vm_special_mapping vvar_mapping = {
@@ -103,26 +103,28 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
if (calculate_addr) {
addr = vdso_addr(current->mm->start_stack,
- image->sym_end_mapping);
+ image->size - image->sym_vvar_start);
} else {
addr = 0;
}
down_write(&mm->mmap_sem);
- addr = get_unmapped_area(NULL, addr, image->sym_end_mapping, 0, 0);
+ addr = get_unmapped_area(NULL, addr,
+ image->size - image->sym_vvar_start, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
}
- current->mm->context.vdso = (void __user *)addr;
+ text_start = addr - image->sym_vvar_start;
+ current->mm->context.vdso = (void __user *)text_start;
/*
* MAYWRITE to allow gdb to COW and set breakpoints
*/
vma = _install_special_mapping(mm,
- addr,
+ text_start,
image->size,
VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
@@ -134,9 +136,9 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
}
vma = _install_special_mapping(mm,
- addr + image->size,
- image->sym_end_mapping - image->size,
- VM_READ,
+ addr,
+ -image->sym_vvar_start,
+ VM_READ|VM_MAYREAD,
&vvar_mapping);
if (IS_ERR(vma)) {
@@ -146,7 +148,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
if (image->sym_vvar_page)
ret = remap_pfn_range(vma,
- addr + image->sym_vvar_page,
+ text_start + image->sym_vvar_page,
__pa_symbol(&__vvar_page) >> PAGE_SHIFT,
PAGE_SIZE,
PAGE_READONLY);
@@ -157,7 +159,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
#ifdef CONFIG_HPET_TIMER
if (hpet_address && image->sym_hpet_page) {
ret = io_remap_pfn_range(vma,
- addr + image->sym_hpet_page,
+ text_start + image->sym_hpet_page,
hpet_address >> PAGE_SHIFT,
PAGE_SIZE,
pgprot_noncached(PAGE_READONLY));
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 96ab2c09cb68..7322755f337a 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
+obj-$(CONFIG_XEN_EFI) += efi.o
diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
new file mode 100644
index 000000000000..a02e09e18f57
--- /dev/null
+++ b/arch/x86/xen/efi.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Oracle Co., Daniel Kiper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <xen/xen-ops.h>
+
+#include <asm/setup.h>
+
+void __init xen_efi_init(void)
+{
+ efi_system_table_t *efi_systab_xen;
+
+ efi_systab_xen = xen_efi_probe();
+
+ if (efi_systab_xen == NULL)
+ return;
+
+ strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen",
+ sizeof(boot_params.efi_info.efi_loader_signature));
+ boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen);
+ boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32);
+
+ set_bit(EFI_BOOT, &efi.flags);
+ set_bit(EFI_PARAVIRT, &efi.flags);
+ set_bit(EFI_64BIT, &efi.flags);
+}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index ffb101e45731..c0cb11fb5008 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1718,6 +1718,8 @@ asmlinkage __visible void __init xen_start_kernel(void)
xen_setup_runstate_info(0);
+ xen_efi_init();
+
/* Start the world */
#ifdef CONFIG_X86_32
i386_start_kernel();
@@ -1826,8 +1828,19 @@ static void __init xen_hvm_guest_init(void)
xen_hvm_init_mmu_ops();
}
+static bool xen_nopv = false;
+static __init int xen_parse_nopv(char *arg)
+{
+ xen_nopv = true;
+ return 0;
+}
+early_param("xen_nopv", xen_parse_nopv);
+
static uint32_t __init xen_hvm_platform(void)
{
+ if (xen_nopv)
+ return 0;
+
if (xen_pv_domain())
return 0;
@@ -1836,6 +1849,8 @@ static uint32_t __init xen_hvm_platform(void)
bool xen_hvm_need_lapic(void)
{
+ if (xen_nopv)
+ return false;
if (xen_pv_domain())
return false;
if (!xen_hvm_domain())
diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c
index ebfa9b2c871d..1580e7a5a4cf 100644
--- a/arch/x86/xen/grant-table.c
+++ b/arch/x86/xen/grant-table.c
@@ -49,7 +49,7 @@
static struct gnttab_vm_area {
struct vm_struct *area;
pte_t **ptes;
-} gnttab_shared_vm_area, gnttab_status_vm_area;
+} gnttab_shared_vm_area;
int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
unsigned long max_nr_gframes,
@@ -73,43 +73,16 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
return 0;
}
-int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
- unsigned long max_nr_gframes,
- grant_status_t **__shared)
-{
- grant_status_t *shared = *__shared;
- unsigned long addr;
- unsigned long i;
-
- if (shared == NULL)
- *__shared = shared = gnttab_status_vm_area.area->addr;
-
- addr = (unsigned long)shared;
-
- for (i = 0; i < nr_gframes; i++) {
- set_pte_at(&init_mm, addr, gnttab_status_vm_area.ptes[i],
- mfn_pte(frames[i], PAGE_KERNEL));
- addr += PAGE_SIZE;
- }
-
- return 0;
-}
-
void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
{
- pte_t **ptes;
unsigned long addr;
unsigned long i;
- if (shared == gnttab_status_vm_area.area->addr)
- ptes = gnttab_status_vm_area.ptes;
- else
- ptes = gnttab_shared_vm_area.ptes;
-
addr = (unsigned long)shared;
for (i = 0; i < nr_gframes; i++) {
- set_pte_at(&init_mm, addr, ptes[i], __pte(0));
+ set_pte_at(&init_mm, addr, gnttab_shared_vm_area.ptes[i],
+ __pte(0));
addr += PAGE_SIZE;
}
}
@@ -129,35 +102,12 @@ static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames)
return 0;
}
-static void arch_gnttab_vfree(struct gnttab_vm_area *area)
+int arch_gnttab_init(unsigned long nr_shared)
{
- free_vm_area(area->area);
- kfree(area->ptes);
-}
-
-int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status)
-{
- int ret;
-
if (!xen_pv_domain())
return 0;
- ret = arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
- if (ret < 0)
- return ret;
-
- /*
- * Always allocate the space for the status frames in case
- * we're migrated to a host with V2 support.
- */
- ret = arch_gnttab_valloc(&gnttab_status_vm_area, nr_status);
- if (ret < 0)
- goto err;
-
- return 0;
- err:
- arch_gnttab_vfree(&gnttab_shared_vm_area);
- return -ENOMEM;
+ return arch_gnttab_valloc(&gnttab_shared_vm_area, nr_shared);
}
#ifdef CONFIG_XEN_PVH
@@ -168,6 +118,7 @@ static int __init xlated_setup_gnttab_pages(void)
{
struct page **pages;
xen_pfn_t *pfns;
+ void *vaddr;
int rc;
unsigned int i;
unsigned long nr_grant_frames = gnttab_max_grant_frames();
@@ -193,21 +144,20 @@ static int __init xlated_setup_gnttab_pages(void)
for (i = 0; i < nr_grant_frames; i++)
pfns[i] = page_to_pfn(pages[i]);
- rc = arch_gnttab_map_shared(pfns, nr_grant_frames, nr_grant_frames,
- &xen_auto_xlat_grant_frames.vaddr);
-
- if (rc) {
+ vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL);
+ if (!vaddr) {
pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__,
nr_grant_frames, rc);
free_xenballooned_pages(nr_grant_frames, pages);
kfree(pages);
kfree(pfns);
- return rc;
+ return -ENOMEM;
}
kfree(pages);
xen_auto_xlat_grant_frames.pfn = pfns;
xen_auto_xlat_grant_frames.count = nr_grant_frames;
+ xen_auto_xlat_grant_frames.vaddr = vaddr;
return 0;
}
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 9bb3d82ffec8..3172692381ae 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -841,10 +841,9 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
pfn = ALIGN(pfn, P2M_PER_PAGE);
}
- if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
+ WARN((pfn - pfn_s) != (pfn_e - pfn_s),
"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
- (pfn_e - pfn_s) - (pfn - pfn_s)))
- printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
+ (pfn_e - pfn_s) - (pfn - pfn_s));
return pfn - pfn_s;
}
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 7b78f88c1707..5718b0b58b60 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -444,7 +444,7 @@ void xen_setup_timer(int cpu)
irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER|
- IRQF_FORCE_RESUME,
+ IRQF_FORCE_RESUME|IRQF_EARLY_RESUME,
name, NULL);
(void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX);
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 97d87659f779..28c7e0be56e4 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -105,6 +105,14 @@ static inline void __init xen_init_apic(void)
}
#endif
+#ifdef CONFIG_XEN_EFI
+extern void xen_efi_init(void);
+#else
+static inline void __init xen_efi_init(void)
+{
+}
+#endif
+
/* Declare an asm function, along with symbols needed to make it
inlineable */
#define DECL_ASM(ret, name, ...) \
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index abb59708a3b7..b61bdf0eea25 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -182,6 +182,7 @@ extern unsigned long get_wchan(struct task_struct *p);
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1])
#define cpu_relax() barrier()
+#define cpu_relax_lowlatency() cpu_relax()
/* Special register access. */
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 98b67d5f1514..4612321c73cc 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -331,17 +331,17 @@ gen_return_code(unsigned char *codemem)
}
-static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe *frame;
- int err = 0;
+ int err = 0, sig = ksig->sig;
int signal;
unsigned long sp, ra, tp;
sp = regs->areg[1];
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
+ if ((ksig->ka.sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
sp = current->sas_ss_sp + current->sas_ss_size;
}
@@ -351,7 +351,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
panic ("Double exception sys_sigreturn\n");
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
- goto give_sigsegv;
+ return -EFAULT;
}
signal = current_thread_info()->exec_domain
@@ -360,8 +360,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- if (ka->sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, info);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
}
/* Create the user context. */
@@ -372,8 +372,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(frame, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- if (ka->sa.sa_flags & SA_RESTORER) {
- ra = (unsigned long)ka->sa.sa_restorer;
+ if (ksig->ka.sa.sa_flags & SA_RESTORER) {
+ ra = (unsigned long)ksig->ka.sa.sa_restorer;
} else {
/* Create sys_rt_sigreturn syscall in stack frame */
@@ -381,7 +381,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= gen_return_code(frame->retcode);
if (err) {
- goto give_sigsegv;
+ return -EFAULT;
}
ra = (unsigned long) frame->retcode;
}
@@ -393,7 +393,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler; preserve the threadptr */
tp = regs->threadptr;
- start_thread(regs, (unsigned long) ka->sa.sa_handler,
+ start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
(unsigned long) frame);
/* Set up a stack frame for a call4
@@ -416,10 +416,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
}
/*
@@ -433,15 +429,11 @@ give_sigsegv:
*/
static void do_signal(struct pt_regs *regs)
{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
+ struct ksignal ksig;
task_pt_regs(current)->icountlevel = 0;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
- if (signr > 0) {
+ if (get_signal(&ksig)) {
int ret;
/* Are we from a system call? */
@@ -457,7 +449,7 @@ static void do_signal(struct pt_regs *regs)
break;
case -ERESTARTSYS:
- if (!(ka.sa.sa_flags & SA_RESTART)) {
+ if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->areg[2] = -EINTR;
break;
}
@@ -476,11 +468,8 @@ static void do_signal(struct pt_regs *regs)
/* Whee! Actually deliver the signal. */
/* Set up the stack frame */
- ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs);
- if (ret)
- return;
-
- signal_delivered(signr, &info, &ka, regs, 0);
+ ret = setup_frame(&ksig, sigmask_to_save(), regs);
+ signal_setup_done(ret, &ksig, 0);
if (current->ptrace & PT_SINGLESTEP)
task_pt_regs(current)->icountlevel = 1;
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 9e241063a616..bc423f7b02da 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -70,8 +70,10 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
bs->bvec_integrity_pool);
if (!bip->bip_vec)
goto err;
+ bip->bip_max_vcnt = bvec_nr_vecs(idx);
} else {
bip->bip_vec = bip->bip_inline_vecs;
+ bip->bip_max_vcnt = inline_vecs;
}
bip->bip_slab = idx;
@@ -114,14 +116,6 @@ void bio_integrity_free(struct bio *bio)
}
EXPORT_SYMBOL(bio_integrity_free);
-static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip)
-{
- if (bip->bip_slab == BIO_POOL_NONE)
- return BIP_INLINE_VECS;
-
- return bvec_nr_vecs(bip->bip_slab);
-}
-
/**
* bio_integrity_add_page - Attach integrity metadata
* @bio: bio to update
@@ -137,7 +131,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
struct bio_integrity_payload *bip = bio->bi_integrity;
struct bio_vec *iv;
- if (bip->bip_vcnt >= bip_integrity_vecs(bip)) {
+ if (bip->bip_vcnt >= bip->bip_max_vcnt) {
printk(KERN_ERR "%s: bip_vec full\n", __func__);
return 0;
}
diff --git a/block/bio.c b/block/bio.c
index 0ec61c9e536c..3e6331d25d90 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -112,7 +112,8 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
bslab = &bio_slabs[entry];
snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry);
- slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL);
+ slab = kmem_cache_create(bslab->name, sz, ARCH_KMALLOC_MINALIGN,
+ SLAB_HWCACHE_ALIGN, NULL);
if (!slab)
goto out_unlock;
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 28d227c5ca77..e17da947f6bd 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -928,7 +928,15 @@ struct cgroup_subsys blkio_cgrp_subsys = {
.css_offline = blkcg_css_offline,
.css_free = blkcg_css_free,
.can_attach = blkcg_can_attach,
- .base_cftypes = blkcg_files,
+ .legacy_cftypes = blkcg_files,
+#ifdef CONFIG_MEMCG
+ /*
+ * This ensures that, if available, memcg is automatically enabled
+ * together on the default hierarchy so that the owner cgroup can
+ * be retrieved from writeback pages.
+ */
+ .depends_on = 1 << memory_cgrp_id,
+#endif
};
EXPORT_SYMBOL_GPL(blkio_cgrp_subsys);
@@ -1120,7 +1128,8 @@ int blkcg_policy_register(struct blkcg_policy *pol)
/* everything is in place, add intf files for the new policy */
if (pol->cftypes)
- WARN_ON(cgroup_add_cftypes(&blkio_cgrp_subsys, pol->cftypes));
+ WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
+ pol->cftypes));
ret = 0;
out_unlock:
mutex_unlock(&blkcg_pol_mutex);
diff --git a/block/blk-core.c b/block/blk-core.c
index 6f8dba161bfe..c359d72e9d76 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -438,14 +438,17 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all)
*/
void blk_queue_bypass_start(struct request_queue *q)
{
- bool drain;
-
spin_lock_irq(q->queue_lock);
- drain = !q->bypass_depth++;
+ q->bypass_depth++;
queue_flag_set(QUEUE_FLAG_BYPASS, q);
spin_unlock_irq(q->queue_lock);
- if (drain) {
+ /*
+ * Queues start drained. Skip actual draining till init is
+ * complete. This avoids lenghty delays during queue init which
+ * can happen many times during boot.
+ */
+ if (blk_queue_init_done(q)) {
spin_lock_irq(q->queue_lock);
__blk_drain_queue(q, false);
spin_unlock_irq(q->queue_lock);
@@ -511,7 +514,7 @@ void blk_cleanup_queue(struct request_queue *q)
* prevent that q->request_fn() gets invoked after draining finished.
*/
if (q->mq_ops) {
- blk_mq_drain_queue(q);
+ blk_mq_freeze_queue(q);
spin_lock_irq(lock);
} else {
spin_lock_irq(lock);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ad69ef657e85..5189cb1e478a 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -78,68 +78,47 @@ static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx,
static int blk_mq_queue_enter(struct request_queue *q)
{
- int ret;
-
- __percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
- smp_wmb();
-
- /* we have problems freezing the queue if it's initializing */
- if (!blk_queue_dying(q) &&
- (!blk_queue_bypass(q) || !blk_queue_init_done(q)))
- return 0;
-
- __percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
+ while (true) {
+ int ret;
- spin_lock_irq(q->queue_lock);
- ret = wait_event_interruptible_lock_irq(q->mq_freeze_wq,
- !blk_queue_bypass(q) || blk_queue_dying(q),
- *q->queue_lock);
- /* inc usage with lock hold to avoid freeze_queue runs here */
- if (!ret && !blk_queue_dying(q))
- __percpu_counter_add(&q->mq_usage_counter, 1, 1000000);
- else if (blk_queue_dying(q))
- ret = -ENODEV;
- spin_unlock_irq(q->queue_lock);
+ if (percpu_ref_tryget_live(&q->mq_usage_counter))
+ return 0;
- return ret;
+ ret = wait_event_interruptible(q->mq_freeze_wq,
+ !q->mq_freeze_depth || blk_queue_dying(q));
+ if (blk_queue_dying(q))
+ return -ENODEV;
+ if (ret)
+ return ret;
+ }
}
static void blk_mq_queue_exit(struct request_queue *q)
{
- __percpu_counter_add(&q->mq_usage_counter, -1, 1000000);
+ percpu_ref_put(&q->mq_usage_counter);
}
-void blk_mq_drain_queue(struct request_queue *q)
+static void blk_mq_usage_counter_release(struct percpu_ref *ref)
{
- while (true) {
- s64 count;
-
- spin_lock_irq(q->queue_lock);
- count = percpu_counter_sum(&q->mq_usage_counter);
- spin_unlock_irq(q->queue_lock);
+ struct request_queue *q =
+ container_of(ref, struct request_queue, mq_usage_counter);
- if (count == 0)
- break;
- blk_mq_start_hw_queues(q);
- msleep(10);
- }
+ wake_up_all(&q->mq_freeze_wq);
}
/*
* Guarantee no request is in use, so we can change any data structure of
* the queue afterward.
*/
-static void blk_mq_freeze_queue(struct request_queue *q)
+void blk_mq_freeze_queue(struct request_queue *q)
{
- bool drain;
-
spin_lock_irq(q->queue_lock);
- drain = !q->bypass_depth++;
- queue_flag_set(QUEUE_FLAG_BYPASS, q);
+ q->mq_freeze_depth++;
spin_unlock_irq(q->queue_lock);
- if (drain)
- blk_mq_drain_queue(q);
+ percpu_ref_kill(&q->mq_usage_counter);
+ blk_mq_run_queues(q, false);
+ wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
}
static void blk_mq_unfreeze_queue(struct request_queue *q)
@@ -147,14 +126,13 @@ static void blk_mq_unfreeze_queue(struct request_queue *q)
bool wake = false;
spin_lock_irq(q->queue_lock);
- if (!--q->bypass_depth) {
- queue_flag_clear(QUEUE_FLAG_BYPASS, q);
- wake = true;
- }
- WARN_ON_ONCE(q->bypass_depth < 0);
+ wake = !--q->mq_freeze_depth;
+ WARN_ON_ONCE(q->mq_freeze_depth < 0);
spin_unlock_irq(q->queue_lock);
- if (wake)
+ if (wake) {
+ percpu_ref_reinit(&q->mq_usage_counter);
wake_up_all(&q->mq_freeze_wq);
+ }
}
bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx)
@@ -1798,7 +1776,7 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
if (!q)
goto err_hctxs;
- if (percpu_counter_init(&q->mq_usage_counter, 0))
+ if (percpu_ref_init(&q->mq_usage_counter, blk_mq_usage_counter_release))
goto err_map;
setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
@@ -1891,7 +1869,7 @@ void blk_mq_free_queue(struct request_queue *q)
blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
blk_mq_free_hw_queues(q, set);
- percpu_counter_destroy(&q->mq_usage_counter);
+ percpu_ref_exit(&q->mq_usage_counter);
free_percpu(q->queue_ctx);
kfree(q->queue_hw_ctx);
@@ -2050,8 +2028,7 @@ static int __init blk_mq_init(void)
{
blk_mq_cpu_init();
- /* Must be called after percpu_counter_hotcpu_callback() */
- hotcpu_notifier(blk_mq_queue_reinit_notify, -10);
+ hotcpu_notifier(blk_mq_queue_reinit_notify, 0);
return 0;
}
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 26460884c6cd..ca4964a6295d 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -28,7 +28,7 @@ struct blk_mq_ctx {
void __blk_mq_complete_request(struct request *rq);
void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
void blk_mq_init_flush(struct request_queue *q);
-void blk_mq_drain_queue(struct request_queue *q);
+void blk_mq_freeze_queue(struct request_queue *q);
void blk_mq_free_queue(struct request_queue *q);
void blk_mq_clone_flush_request(struct request *flush_rq,
struct request *orig_rq);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 23321fbab293..4db5abf96b9e 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -554,8 +554,8 @@ int blk_register_queue(struct gendisk *disk)
* Initialization must be complete by now. Finish the initial
* bypass from queue allocation.
*/
- blk_queue_bypass_end(q);
queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
+ blk_queue_bypass_end(q);
ret = blk_trace_init_sysfs(dev);
if (ret)
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 3fdb21a390c1..9273d0969ebd 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -412,13 +412,13 @@ static void throtl_pd_init(struct blkcg_gq *blkg)
int rw;
/*
- * If sane_hierarchy is enabled, we switch to properly hierarchical
+ * If on the default hierarchy, we switch to properly hierarchical
* behavior where limits on a given throtl_grp are applied to the
* whole subtree rather than just the group itself. e.g. If 16M
* read_bps limit is set on the root group, the whole system can't
* exceed 16M for the device.
*
- * If sane_hierarchy is not enabled, the broken flat hierarchy
+ * If not on the default hierarchy, the broken flat hierarchy
* behavior is retained where all throtl_grps are treated as if
* they're all separate root groups right below throtl_data.
* Limits of a group don't interact with limits of other groups
@@ -426,7 +426,7 @@ static void throtl_pd_init(struct blkcg_gq *blkg)
*/
parent_sq = &td->service_queue;
- if (cgroup_sane_behavior(blkg->blkcg->css.cgroup) && blkg->parent)
+ if (cgroup_on_dfl(blkg->blkcg->css.cgroup) && blkg->parent)
parent_sq = &blkg_to_tg(blkg->parent)->service_queue;
throtl_service_queue_init(&tg->service_queue, parent_sq);
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index a0926a6094b2..18b282ce361e 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -663,6 +663,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
fmode_t mode = file->f_mode;
struct backing_dev_info *bdi;
loff_t size;
+ unsigned int max_sectors;
/*
* O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
@@ -719,8 +720,9 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case BLKSSZGET: /* get block device hardware sector size */
return compat_put_int(arg, bdev_logical_block_size(bdev));
case BLKSECTGET:
- return compat_put_ushort(arg,
- queue_max_sectors(bdev_get_queue(bdev)));
+ max_sectors = min_t(unsigned int, USHRT_MAX,
+ queue_max_sectors(bdev_get_queue(bdev)));
+ return compat_put_ushort(arg, max_sectors);
case BLKROTATIONAL:
return compat_put_ushort(arg,
!blk_queue_nonrot(bdev_get_queue(bdev)));
diff --git a/block/ioctl.c b/block/ioctl.c
index 7d5c3b20af45..d6cda8147c91 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -278,6 +278,7 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
struct backing_dev_info *bdi;
loff_t size;
int ret, n;
+ unsigned int max_sectors;
switch(cmd) {
case BLKFLSBUF:
@@ -375,7 +376,9 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
case BLKDISCARDZEROES:
return put_uint(arg, bdev_discard_zeroes_data(bdev));
case BLKSECTGET:
- return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev)));
+ max_sectors = min_t(unsigned int, USHRT_MAX,
+ queue_max_sectors(bdev_get_queue(bdev)));
+ return put_ushort(arg, max_sectors);
case BLKROTATIONAL:
return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev)));
case BLKRASET:
diff --git a/block/partitions/aix.c b/block/partitions/aix.c
index 43be471d9b1d..f3ed7b2d89bf 100644
--- a/block/partitions/aix.c
+++ b/block/partitions/aix.c
@@ -215,7 +215,7 @@ int aix_partition(struct parsed_partitions *state)
numlvs = be16_to_cpu(p->numlvs);
put_dev_sector(sect);
}
- lvip = kzalloc(sizeof(struct lv_info) * state->limit, GFP_KERNEL);
+ lvip = kcalloc(state->limit, sizeof(struct lv_info), GFP_KERNEL);
if (!lvip)
return 0;
if (numlvs && (d = read_part_sector(state, vgda_sector + 1, &sect))) {
@@ -253,7 +253,7 @@ int aix_partition(struct parsed_partitions *state)
continue;
}
lv_ix = be16_to_cpu(p->lv_ix) - 1;
- if (lv_ix > state->limit) {
+ if (lv_ix >= state->limit) {
cur_lv_ix = -1;
continue;
}
diff --git a/block/partitions/amiga.c b/block/partitions/amiga.c
index 70cbf44a1560..2b13533d60a2 100644
--- a/block/partitions/amiga.c
+++ b/block/partitions/amiga.c
@@ -7,6 +7,8 @@
* Re-organised Feb 1998 Russell King
*/
+#define pr_fmt(fmt) fmt
+
#include <linux/types.h>
#include <linux/affs_hardblocks.h>
@@ -40,7 +42,7 @@ int amiga_partition(struct parsed_partitions *state)
data = read_part_sector(state, blk, &sect);
if (!data) {
if (warn_no_part)
- printk("Dev %s: unable to read RDB block %d\n",
+ pr_err("Dev %s: unable to read RDB block %d\n",
bdevname(state->bdev, b), blk);
res = -1;
goto rdb_done;
@@ -57,12 +59,12 @@ int amiga_partition(struct parsed_partitions *state)
*(__be32 *)(data+0xdc) = 0;
if (checksum_block((__be32 *)data,
be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
- printk("Warning: Trashed word at 0xd0 in block %d "
- "ignored in checksum calculation\n",blk);
+ pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n",
+ blk);
break;
}
- printk("Dev %s: RDB in block %d has bad checksum\n",
+ pr_err("Dev %s: RDB in block %d has bad checksum\n",
bdevname(state->bdev, b), blk);
}
@@ -83,7 +85,7 @@ int amiga_partition(struct parsed_partitions *state)
data = read_part_sector(state, blk, &sect);
if (!data) {
if (warn_no_part)
- printk("Dev %s: unable to read partition block %d\n",
+ pr_err("Dev %s: unable to read partition block %d\n",
bdevname(state->bdev, b), blk);
res = -1;
goto rdb_done;
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index dc51f467a560..56d08fd75b1a 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -121,7 +121,7 @@ __setup("gpt", force_gpt_fn);
/**
* efi_crc32() - EFI version of crc32 function
* @buf: buffer to calculate crc32 of
- * @len - length of buf
+ * @len: length of buf
*
* Description: Returns EFI-style CRC32 value for @buf
*
@@ -240,10 +240,10 @@ done:
/**
* read_lba(): Read bytes from disk, starting at given LBA
- * @state
- * @lba
- * @buffer
- * @size_t
+ * @state: disk parsed partitions
+ * @lba: the Logical Block Address of the partition table
+ * @buffer: destination buffer
+ * @count: bytes to read
*
* Description: Reads @count bytes from @state->bdev into @buffer.
* Returns number of bytes read on success, 0 on error.
@@ -277,8 +277,8 @@ static size_t read_lba(struct parsed_partitions *state,
/**
* alloc_read_gpt_entries(): reads partition entries from disk
- * @state
- * @gpt - GPT header
+ * @state: disk parsed partitions
+ * @gpt: GPT header
*
* Description: Returns ptes on success, NULL on error.
* Allocates space for PTEs based on information found in @gpt.
@@ -312,8 +312,8 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
/**
* alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
- * @state
- * @lba is the Logical Block Address of the partition table
+ * @state: disk parsed partitions
+ * @lba: the Logical Block Address of the partition table
*
* Description: returns GPT header on success, NULL on error. Allocates
* and fills a GPT header starting at @ from @state->bdev.
@@ -340,10 +340,10 @@ static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state,
/**
* is_gpt_valid() - tests one GPT header and PTEs for validity
- * @state
- * @lba is the logical block address of the GPT header to test
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
+ * @state: disk parsed partitions
+ * @lba: logical block address of the GPT header to test
+ * @gpt: GPT header ptr, filled on return.
+ * @ptes: PTEs ptr, filled on return.
*
* Description: returns 1 if valid, 0 on error.
* If valid, returns pointers to newly allocated GPT header and PTEs.
@@ -461,8 +461,8 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
/**
* is_pte_valid() - tests one PTE for validity
- * @pte is the pte to check
- * @lastlba is last lba of the disk
+ * @pte:pte to check
+ * @lastlba: last lba of the disk
*
* Description: returns 1 if valid, 0 on error.
*/
@@ -478,9 +478,10 @@ is_pte_valid(const gpt_entry *pte, const u64 lastlba)
/**
* compare_gpts() - Search disk for valid GPT headers and PTEs
- * @pgpt is the primary GPT header
- * @agpt is the alternate GPT header
- * @lastlba is the last LBA number
+ * @pgpt: primary GPT header
+ * @agpt: alternate GPT header
+ * @lastlba: last LBA number
+ *
* Description: Returns nothing. Sanity checks pgpt and agpt fields
* and prints warnings on discrepancies.
*
@@ -572,9 +573,10 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
/**
* find_valid_gpt() - Search disk for valid GPT headers and PTEs
- * @state
- * @gpt is a GPT header ptr, filled on return.
- * @ptes is a PTEs ptr, filled on return.
+ * @state: disk parsed partitions
+ * @gpt: GPT header ptr, filled on return.
+ * @ptes: PTEs ptr, filled on return.
+ *
* Description: Returns 1 if valid, 0 on error.
* If valid, returns pointers to newly allocated GPT header and PTEs.
* Validity depends on PMBR being valid (or being overridden by the
@@ -663,7 +665,7 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
/**
* efi_partition(struct parsed_partitions *state)
- * @state
+ * @state: disk parsed partitions
*
* Description: called from check.c, if the disk contains GPT
* partitions, sets up partition entries in the kernel.
diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c
index 9123f250b425..93e7c1b32edd 100644
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -159,8 +159,9 @@ static void parse_extended(struct parsed_partitions *state,
/*
* First process the data partition(s)
*/
- for (i=0; i<4; i++, p++) {
+ for (i = 0; i < 4; i++, p++) {
sector_t offs, size, next;
+
if (!nr_sects(p) || is_extended_partition(p))
continue;
@@ -194,7 +195,7 @@ static void parse_extended(struct parsed_partitions *state,
* It should be a link to the next logical partition.
*/
p -= 4;
- for (i=0; i<4; i++, p++)
+ for (i = 0; i < 4; i++, p++)
if (nr_sects(p) && is_extended_partition(p))
break;
if (i == 4)
@@ -243,8 +244,8 @@ static void parse_solaris_x86(struct parsed_partitions *state,
return;
}
/* Ensure we can handle previous case of VTOC with 8 entries gracefully */
- max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
- for (i=0; i<max_nparts && state->next<state->limit; i++) {
+ max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
+ for (i = 0; i < max_nparts && state->next < state->limit; i++) {
struct solaris_x86_slice *s = &v->v_slice[i];
char tmp[3 + 10 + 1 + 1];
@@ -409,7 +410,7 @@ static void parse_minix(struct parsed_partitions *state,
/* The first sector of a Minix partition can have either
* a secondary MBR describing its subpartitions, or
* the normal boot sector. */
- if (msdos_magic_present (data + 510) &&
+ if (msdos_magic_present(data + 510) &&
SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];
@@ -527,6 +528,7 @@ int msdos_partition(struct parsed_partitions *state)
for (slot = 1 ; slot <= 4 ; slot++, p++) {
sector_t start = start_sect(p)*sector_size;
sector_t size = nr_sects(p)*sector_size;
+
if (!size)
continue;
if (is_extended_partition(p)) {
@@ -537,6 +539,7 @@ int msdos_partition(struct parsed_partitions *state)
* sector, although it may not be enough/proper.
*/
sector_t n = 2;
+
n = min(size, max(sector_size, n));
put_partition(state, slot, start, n);
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 14695c6221c8..51bf5155ee75 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -82,9 +82,18 @@ static int sg_set_timeout(struct request_queue *q, int __user *p)
return err;
}
+static int max_sectors_bytes(struct request_queue *q)
+{
+ unsigned int max_sectors = queue_max_sectors(q);
+
+ max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9);
+
+ return max_sectors << 9;
+}
+
static int sg_get_reserved_size(struct request_queue *q, int __user *p)
{
- unsigned val = min(q->sg_reserved_size, queue_max_sectors(q) << 9);
+ int val = min_t(int, q->sg_reserved_size, max_sectors_bytes(q));
return put_user(val, p);
}
@@ -98,10 +107,8 @@ static int sg_set_reserved_size(struct request_queue *q, int __user *p)
if (size < 0)
return -EINVAL;
- if (size > (queue_max_sectors(q) << 9))
- size = queue_max_sectors(q) << 9;
- q->sg_reserved_size = size;
+ q->sg_reserved_size = min(size, max_sectors_bytes(q));
return 0;
}
@@ -283,6 +290,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
unsigned long start_time;
ssize_t ret = 0;
int writing = 0;
+ int at_head = 0;
struct request *rq;
char sense[SCSI_SENSE_BUFFERSIZE];
struct bio *bio;
@@ -306,6 +314,8 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
case SG_DXFER_FROM_DEV:
break;
}
+ if (hdr->flags & SG_FLAG_Q_AT_HEAD)
+ at_head = 1;
rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
if (!rq)
@@ -362,7 +372,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
* (if he doesn't check that is his problem).
* N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
- blk_execute_rq(q, bd_disk, rq, 0);
+ blk_execute_rq(q, bd_disk, rq, at_head);
hdr->duration = jiffies_to_msecs(jiffies - start_time);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ce4012a58781..00b5906f57b7 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -23,7 +23,8 @@ comment "Crypto core or helper"
config CRYPTO_FIPS
bool "FIPS 200 compliance"
- depends on CRYPTO_ANSI_CPRNG && !CRYPTO_MANAGER_DISABLE_TESTS
+ depends on (CRYPTO_ANSI_CPRNG || CRYPTO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
+ depends on MODULE_SIG
help
This options enables the fips boot option which is
required if you want to system to operate in a FIPS 200
@@ -540,6 +541,17 @@ config CRYPTO_SHA1_ARM
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
using optimized ARM assembler.
+config CRYPTO_SHA1_ARM_NEON
+ tristate "SHA1 digest algorithm (ARM NEON)"
+ depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+ select CRYPTO_SHA1_ARM
+ select CRYPTO_SHA1
+ select CRYPTO_HASH
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+ using optimized ARM NEON assembly, when NEON instructions are
+ available.
+
config CRYPTO_SHA1_PPC
tristate "SHA1 digest algorithm (powerpc)"
depends on PPC
@@ -589,6 +601,21 @@ config CRYPTO_SHA512_SPARC64
SHA-512 secure hash standard (DFIPS 180-2) implemented
using sparc64 crypto instructions, when available.
+config CRYPTO_SHA512_ARM_NEON
+ tristate "SHA384 and SHA512 digest algorithm (ARM NEON)"
+ depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+ select CRYPTO_SHA512
+ select CRYPTO_HASH
+ help
+ SHA-512 secure hash standard (DFIPS 180-2) implemented
+ using ARM NEON instructions, when available.
+
+ This version of SHA implements a 512 bit hash with 256 bits of
+ security against collision attacks.
+
+ This code also includes SHA-384, a 384 bit hash with 192 bits
+ of security against collision attacks.
+
config CRYPTO_TGR192
tristate "Tiger digest algorithms"
select CRYPTO_HASH
@@ -1019,6 +1046,19 @@ config CRYPTO_DES_SPARC64
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3),
optimized using SPARC64 crypto opcodes.
+config CRYPTO_DES3_EDE_X86_64
+ tristate "Triple DES EDE cipher algorithm (x86-64)"
+ depends on X86 && 64BIT
+ select CRYPTO_ALGAPI
+ select CRYPTO_DES
+ help
+ Triple DES EDE (FIPS 46-3) algorithm.
+
+ This module provides implementation of the Triple DES EDE cipher
+ algorithm that is optimized for x86-64 processors. Two versions of
+ algorithm are provided; regular processing one input block and
+ one that processes three blocks parallel.
+
config CRYPTO_FCRYPT
tristate "FCrypt cipher algorithm"
select CRYPTO_ALGAPI
@@ -1380,6 +1420,40 @@ config CRYPTO_ANSI_CPRNG
ANSI X9.31 A.2.4. Note that this option must be enabled if
CRYPTO_FIPS is selected
+menuconfig CRYPTO_DRBG_MENU
+ tristate "NIST SP800-90A DRBG"
+ help
+ NIST SP800-90A compliant DRBG. In the following submenu, one or
+ more of the DRBG types must be selected.
+
+if CRYPTO_DRBG_MENU
+
+config CRYPTO_DRBG_HMAC
+ bool "Enable HMAC DRBG"
+ default y
+ select CRYPTO_HMAC
+ help
+ Enable the HMAC DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_HASH
+ bool "Enable Hash DRBG"
+ select CRYPTO_HASH
+ help
+ Enable the Hash DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG_CTR
+ bool "Enable CTR DRBG"
+ select CRYPTO_AES
+ help
+ Enable the CTR DRBG variant as defined in NIST SP800-90A.
+
+config CRYPTO_DRBG
+ tristate
+ default CRYPTO_DRBG_MENU if (CRYPTO_DRBG_HMAC || CRYPTO_DRBG_HASH || CRYPTO_DRBG_CTR)
+ select CRYPTO_RNG
+
+endif # if CRYPTO_DRBG_MENU
+
config CRYPTO_USER_API
tristate
diff --git a/crypto/Makefile b/crypto/Makefile
index 38e64231dcd3..cfa57b3f5a4d 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_CRYPTO_842) += 842.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
obj-$(CONFIG_CRYPTO_RNG2) += krng.o
obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
+obj-$(CONFIG_CRYPTO_DRBG) += drbg.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 7a1ae87f1683..e8d3a7dca8c4 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -41,8 +41,20 @@ static inline int crypto_set_driver_name(struct crypto_alg *alg)
return 0;
}
+static inline void crypto_check_module_sig(struct module *mod)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ if (fips_enabled && mod && !mod->sig_ok)
+ panic("Module %s signature verification failed in FIPS mode\n",
+ mod->name);
+#endif
+ return;
+}
+
static int crypto_check_alg(struct crypto_alg *alg)
{
+ crypto_check_module_sig(alg->cra_module);
+
if (alg->cra_alignmask & (alg->cra_alignmask + 1))
return -EINVAL;
@@ -430,6 +442,8 @@ int crypto_register_template(struct crypto_template *tmpl)
down_write(&crypto_alg_sem);
+ crypto_check_module_sig(tmpl->module);
+
list_for_each_entry(q, &crypto_template_list, list) {
if (q == tmpl)
goto out;
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 03a6eb95ab50..4870f28403f5 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -22,7 +22,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
config PUBLIC_KEY_ALGO_RSA
tristate "RSA public-key algorithm"
- select MPILIB_EXTRA
select MPILIB
help
This option enables support for the RSA algorithm (PKCS#1, RFC3447).
@@ -33,8 +32,39 @@ config X509_CERTIFICATE_PARSER
select ASN1
select OID_REGISTRY
help
- This option procides support for parsing X.509 format blobs for key
+ This option provides support for parsing X.509 format blobs for key
data and provides the ability to instantiate a crypto key from a
public key packet found inside the certificate.
+config PKCS7_MESSAGE_PARSER
+ tristate "PKCS#7 message parser"
+ depends on X509_CERTIFICATE_PARSER
+ select ASN1
+ select OID_REGISTRY
+ help
+ This option provides support for parsing PKCS#7 format messages for
+ signature data and provides the ability to verify the signature.
+
+config PKCS7_TEST_KEY
+ tristate "PKCS#7 testing key type"
+ depends on PKCS7_MESSAGE_PARSER
+ select SYSTEM_TRUSTED_KEYRING
+ help
+ This option provides a type of key that can be loaded up from a
+ PKCS#7 message - provided the message is signed by a trusted key. If
+ it is, the PKCS#7 wrapper is discarded and reading the key returns
+ just the payload. If it isn't, adding the key will fail with an
+ error.
+
+ This is intended for testing the PKCS#7 parser.
+
+config SIGNED_PE_FILE_VERIFICATION
+ bool "Support for PE file signature verification"
+ depends on PKCS7_MESSAGE_PARSER=y
+ select ASN1
+ select OID_REGISTRY
+ help
+ This option provides support for verifying the signature(s) on a
+ signed PE binary.
+
endif # ASYMMETRIC_KEY_TYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 0727204aab68..e47fcd9ac5e8 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -25,3 +25,40 @@ $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
clean-files += x509-asn1.c x509-asn1.h
clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h
+
+#
+# PKCS#7 message handling
+#
+obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
+pkcs7_message-y := \
+ pkcs7-asn1.o \
+ pkcs7_parser.o \
+ pkcs7_trust.o \
+ pkcs7_verify.o
+
+$(obj)/pkcs7_parser.o: $(obj)/pkcs7-asn1.h
+$(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h
+
+clean-files += pkcs7-asn1.c pkcs7-asn1.h
+
+#
+# PKCS#7 parser testing key
+#
+obj-$(CONFIG_PKCS7_TEST_KEY) += pkcs7_test_key.o
+pkcs7_test_key-y := \
+ pkcs7_key_type.o
+
+#
+# Signed PE binary-wrapped key handling
+#
+obj-$(CONFIG_SIGNED_PE_FILE_VERIFICATION) += verify_signed_pefile.o
+
+verify_signed_pefile-y := \
+ verify_pefile.o \
+ mscode_parser.o \
+ mscode-asn1.o
+
+$(obj)/mscode_parser.o: $(obj)/mscode-asn1.h $(obj)/mscode-asn1.h
+$(obj)/mscode-asn1.o: $(obj)/mscode-asn1.c $(obj)/mscode-asn1.h
+
+clean-files += mscode-asn1.c mscode-asn1.h
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h
index 515b63430812..a63c551c6557 100644
--- a/crypto/asymmetric_keys/asymmetric_keys.h
+++ b/crypto/asymmetric_keys/asymmetric_keys.h
@@ -9,6 +9,8 @@
* 2 of the Licence, or (at your option) any later version.
*/
+int asymmetric_keyid_match(const char *kid, const char *id);
+
static inline const char *asymmetric_key_id(const struct key *key)
{
return key->type_data.p[1];
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index b77eb5304788..eb8cd46961a5 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -23,6 +23,35 @@ static LIST_HEAD(asymmetric_key_parsers);
static DECLARE_RWSEM(asymmetric_key_parsers_sem);
/*
+ * Match asymmetric key id with partial match
+ * @id: key id to match in a form "id:<id>"
+ */
+int asymmetric_keyid_match(const char *kid, const char *id)
+{
+ size_t idlen, kidlen;
+
+ if (!kid || !id)
+ return 0;
+
+ /* make it possible to use id as in the request: "id:<id>" */
+ if (strncmp(id, "id:", 3) == 0)
+ id += 3;
+
+ /* Anything after here requires a partial match on the ID string */
+ idlen = strlen(id);
+ kidlen = strlen(kid);
+ if (idlen > kidlen)
+ return 0;
+
+ kid += kidlen - idlen;
+ if (strcasecmp(id, kid) != 0)
+ return 0;
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
+
+/*
* Match asymmetric keys on (part of) their name
* We have some shorthand methods for matching keys. We allow:
*
@@ -34,9 +63,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
{
const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
const char *spec = description;
- const char *id, *kid;
+ const char *id;
ptrdiff_t speclen;
- size_t idlen, kidlen;
if (!subtype || !spec || !*spec)
return 0;
@@ -55,23 +83,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
speclen = id - spec;
id++;
- /* Anything after here requires a partial match on the ID string */
- kid = asymmetric_key_id(key);
- if (!kid)
- return 0;
-
- idlen = strlen(id);
- kidlen = strlen(kid);
- if (idlen > kidlen)
- return 0;
-
- kid += kidlen - idlen;
- if (strcasecmp(id, kid) != 0)
- return 0;
-
- if (speclen == 2 &&
- memcmp(spec, "id", 2) == 0)
- return 1;
+ if (speclen == 2 && memcmp(spec, "id", 2) == 0)
+ return asymmetric_keyid_match(asymmetric_key_id(key), id);
if (speclen == subtype->name_len &&
memcmp(spec, subtype->name, speclen) == 0)
@@ -156,7 +169,7 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
pr_devel("==>%s()\n", __func__);
if (subtype) {
- subtype->destroy(prep->payload);
+ subtype->destroy(prep->payload[0]);
module_put(subtype->owner);
}
kfree(prep->type_data[1]);
@@ -164,29 +177,6 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
}
/*
- * Instantiate a asymmetric_key defined key. The key was preparsed, so we just
- * have to transfer the data here.
- */
-static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-{
- int ret;
-
- pr_devel("==>%s()\n", __func__);
-
- ret = key_payload_reserve(key, prep->quotalen);
- if (ret == 0) {
- key->type_data.p[0] = prep->type_data[0];
- key->type_data.p[1] = prep->type_data[1];
- key->payload.data = prep->payload;
- prep->type_data[0] = NULL;
- prep->type_data[1] = NULL;
- prep->payload = NULL;
- }
- pr_devel("<==%s() = %d\n", __func__, ret);
- return ret;
-}
-
-/*
* dispose of the data dangling from the corpse of a asymmetric key
*/
static void asymmetric_key_destroy(struct key *key)
@@ -205,7 +195,7 @@ struct key_type key_type_asymmetric = {
.name = "asymmetric",
.preparse = asymmetric_key_preparse,
.free_preparse = asymmetric_key_free_preparse,
- .instantiate = asymmetric_key_instantiate,
+ .instantiate = generic_key_instantiate,
.match = asymmetric_key_match,
.destroy = asymmetric_key_destroy,
.describe = asymmetric_key_describe,
diff --git a/crypto/asymmetric_keys/mscode.asn1 b/crypto/asymmetric_keys/mscode.asn1
new file mode 100644
index 000000000000..6d09ba48c41c
--- /dev/null
+++ b/crypto/asymmetric_keys/mscode.asn1
@@ -0,0 +1,28 @@
+--- Microsoft individual code signing data blob parser
+---
+--- Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+--- Written by David Howells (dhowells@redhat.com)
+---
+--- This program is free software; you can redistribute it and/or
+--- modify it under the terms of the GNU General Public Licence
+--- as published by the Free Software Foundation; either version
+--- 2 of the Licence, or (at your option) any later version.
+---
+
+MSCode ::= SEQUENCE {
+ type SEQUENCE {
+ contentType ContentType,
+ parameters ANY
+ },
+ content SEQUENCE {
+ digestAlgorithm DigestAlgorithmIdentifier,
+ digest OCTET STRING ({ mscode_note_digest })
+ }
+}
+
+ContentType ::= OBJECT IDENTIFIER ({ mscode_note_content_type })
+
+DigestAlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ mscode_note_digest_algo }),
+ parameters ANY OPTIONAL
+}
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
new file mode 100644
index 000000000000..214a992123cd
--- /dev/null
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -0,0 +1,126 @@
+/* Parse a Microsoft Individual Code Signing blob
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "MSCODE: "fmt
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#include <crypto/pkcs7.h>
+#include "verify_pefile.h"
+#include "mscode-asn1.h"
+
+/*
+ * Parse a Microsoft Individual Code Signing blob
+ */
+int mscode_parse(struct pefile_context *ctx)
+{
+ const void *content_data;
+ size_t data_len;
+ int ret;
+
+ ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
+
+ if (ret) {
+ pr_debug("PKCS#7 message does not contain data\n");
+ return ret;
+ }
+
+ pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
+ content_data);
+
+ return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len);
+}
+
+/*
+ * Check the content type OID
+ */
+int mscode_note_content_type(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ if (oid == OID__NR) {
+ char buffer[50];
+
+ sprint_oid(value, vlen, buffer, sizeof(buffer));
+ pr_err("Unknown OID: %s\n", buffer);
+ return -EBADMSG;
+ }
+
+ /*
+ * pesign utility had a bug where it was putting
+ * OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
+ * So allow both OIDs.
+ */
+ if (oid != OID_msPeImageDataObjId &&
+ oid != OID_msIndividualSPKeyPurpose) {
+ pr_err("Unexpected content type OID %u\n", oid);
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+/*
+ * Note the digest algorithm OID
+ */
+int mscode_note_digest_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pefile_context *ctx = context;
+ char buffer[50];
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ switch (oid) {
+ case OID_md4:
+ ctx->digest_algo = HASH_ALGO_MD4;
+ break;
+ case OID_md5:
+ ctx->digest_algo = HASH_ALGO_MD5;
+ break;
+ case OID_sha1:
+ ctx->digest_algo = HASH_ALGO_SHA1;
+ break;
+ case OID_sha256:
+ ctx->digest_algo = HASH_ALGO_SHA256;
+ break;
+
+ case OID__NR:
+ sprint_oid(value, vlen, buffer, sizeof(buffer));
+ pr_err("Unknown OID: %s\n", buffer);
+ return -EBADMSG;
+
+ default:
+ pr_err("Unsupported content type: %u\n", oid);
+ return -ENOPKG;
+ }
+
+ return 0;
+}
+
+/*
+ * Note the digest we're guaranteeing with this certificate
+ */
+int mscode_note_digest(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pefile_context *ctx = context;
+
+ ctx->digest = value;
+ ctx->digest_len = vlen;
+ return 0;
+}
diff --git a/crypto/asymmetric_keys/pkcs7.asn1 b/crypto/asymmetric_keys/pkcs7.asn1
new file mode 100644
index 000000000000..a5a14ef28c86
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7.asn1
@@ -0,0 +1,127 @@
+PKCS7ContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ content [0] EXPLICIT SignedData OPTIONAL
+}
+
+ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID })
+
+SignedData ::= SEQUENCE {
+ version INTEGER,
+ digestAlgorithms DigestAlgorithmIdentifiers,
+ contentInfo ContentInfo,
+ certificates CHOICE {
+ certSet [0] IMPLICIT ExtendedCertificatesAndCertificates,
+ certSequence [2] IMPLICIT Certificates
+ } OPTIONAL ({ pkcs7_note_certificate_list }),
+ crls CHOICE {
+ crlSet [1] IMPLICIT CertificateRevocationLists,
+ crlSequence [3] IMPLICIT CRLSequence
+ } OPTIONAL,
+ signerInfos SignerInfos
+}
+
+ContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ content [0] EXPLICIT Data OPTIONAL
+}
+
+Data ::= ANY ({ pkcs7_note_data })
+
+DigestAlgorithmIdentifiers ::= CHOICE {
+ daSet SET OF DigestAlgorithmIdentifier,
+ daSequence SEQUENCE OF DigestAlgorithmIdentifier
+}
+
+DigestAlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ parameters ANY OPTIONAL
+}
+
+--
+-- Certificates and certificate lists
+--
+ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate
+
+ExtendedCertificateOrCertificate ::= CHOICE {
+ certificate Certificate, -- X.509
+ extendedCertificate [0] IMPLICIT ExtendedCertificate -- PKCS#6
+}
+
+ExtendedCertificate ::= Certificate -- cheating
+
+Certificates ::= SEQUENCE OF Certificate
+
+CertificateRevocationLists ::= SET OF CertificateList
+
+CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly
+
+CRLSequence ::= SEQUENCE OF CertificateList
+
+Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509
+
+--
+-- Signer information
+--
+SignerInfos ::= CHOICE {
+ siSet SET OF SignerInfo,
+ siSequence SEQUENCE OF SignerInfo
+}
+
+SignerInfo ::= SEQUENCE {
+ version INTEGER,
+ issuerAndSerialNumber IssuerAndSerialNumber,
+ digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
+ authenticatedAttributes CHOICE {
+ aaSet [0] IMPLICIT SetOfAuthenticatedAttribute
+ ({ pkcs7_sig_note_set_of_authattrs }),
+ aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
+ -- Explicit because easier to compute digest on
+ -- sequence of attributes and then reuse encoded
+ -- sequence in aaSequence.
+ } OPTIONAL,
+ digestEncryptionAlgorithm
+ DigestEncryptionAlgorithmIdentifier ({ pkcs7_sig_note_pkey_algo }),
+ encryptedDigest EncryptedDigest,
+ unauthenticatedAttributes CHOICE {
+ uaSet [1] IMPLICIT SET OF UnauthenticatedAttribute,
+ uaSequence [3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute
+ } OPTIONAL
+} ({ pkcs7_note_signed_info })
+
+IssuerAndSerialNumber ::= SEQUENCE {
+ issuer Name ({ pkcs7_sig_note_issuer }),
+ serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial })
+}
+
+CertificateSerialNumber ::= INTEGER
+
+SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
+
+AuthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ values SET OF ANY ({ pkcs7_sig_note_authenticated_attr })
+}
+
+UnauthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ values SET OF ANY
+}
+
+DigestEncryptionAlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ parameters ANY OPTIONAL
+}
+
+EncryptedDigest ::= OCTET STRING ({ pkcs7_sig_note_signature })
+
+---
+--- X.500 Name
+---
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeType OBJECT IDENTIFIER ({ pkcs7_note_OID }),
+ attributeValue ANY
+}
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
new file mode 100644
index 000000000000..3de5fb011de0
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -0,0 +1,100 @@
+/* Testing module to load key from trusted PKCS#7 message
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "PKCS7key: "fmt
+#include <linux/key.h>
+#include <linux/err.h>
+#include <linux/key-type.h>
+#include <crypto/pkcs7.h>
+#include <keys/user-type.h>
+#include <keys/system_keyring.h>
+#include "pkcs7_parser.h"
+
+/*
+ * Preparse a PKCS#7 wrapped and validated data blob.
+ */
+static int pkcs7_preparse(struct key_preparsed_payload *prep)
+{
+ struct pkcs7_message *pkcs7;
+ const void *data, *saved_prep_data;
+ size_t datalen, saved_prep_datalen;
+ bool trusted;
+ int ret;
+
+ kenter("");
+
+ saved_prep_data = prep->data;
+ saved_prep_datalen = prep->datalen;
+ pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
+ if (IS_ERR(pkcs7)) {
+ ret = PTR_ERR(pkcs7);
+ goto error;
+ }
+
+ ret = pkcs7_verify(pkcs7);
+ if (ret < 0)
+ goto error_free;
+
+ ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
+ if (ret < 0)
+ goto error_free;
+ if (!trusted)
+ pr_warn("PKCS#7 message doesn't chain back to a trusted key\n");
+
+ ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false);
+ if (ret < 0)
+ goto error_free;
+
+ prep->data = data;
+ prep->datalen = datalen;
+ ret = user_preparse(prep);
+ prep->data = saved_prep_data;
+ prep->datalen = saved_prep_datalen;
+
+error_free:
+ pkcs7_free_message(pkcs7);
+error:
+ kleave(" = %d", ret);
+ return ret;
+}
+
+/*
+ * user defined keys take an arbitrary string as the description and an
+ * arbitrary blob of data as the payload
+ */
+static struct key_type key_type_pkcs7 = {
+ .name = "pkcs7_test",
+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
+ .preparse = pkcs7_preparse,
+ .free_preparse = user_free_preparse,
+ .instantiate = generic_key_instantiate,
+ .match = user_match,
+ .revoke = user_revoke,
+ .destroy = user_destroy,
+ .describe = user_describe,
+ .read = user_read,
+};
+
+/*
+ * Module stuff
+ */
+static int __init pkcs7_key_init(void)
+{
+ return register_key_type(&key_type_pkcs7);
+}
+
+static void __exit pkcs7_key_cleanup(void)
+{
+ unregister_key_type(&key_type_pkcs7);
+}
+
+module_init(pkcs7_key_init);
+module_exit(pkcs7_key_cleanup);
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
new file mode 100644
index 000000000000..42e56aa7d277
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -0,0 +1,396 @@
+/* PKCS#7 parser
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/oid_registry.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+#include "pkcs7-asn1.h"
+
+struct pkcs7_parse_context {
+ struct pkcs7_message *msg; /* Message being constructed */
+ struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */
+ struct pkcs7_signed_info **ppsinfo;
+ struct x509_certificate *certs; /* Certificate cache */
+ struct x509_certificate **ppcerts;
+ unsigned long data; /* Start of data */
+ enum OID last_oid; /* Last OID encountered */
+ unsigned x509_index;
+ unsigned sinfo_index;
+};
+
+/**
+ * pkcs7_free_message - Free a PKCS#7 message
+ * @pkcs7: The PKCS#7 message to free
+ */
+void pkcs7_free_message(struct pkcs7_message *pkcs7)
+{
+ struct x509_certificate *cert;
+ struct pkcs7_signed_info *sinfo;
+
+ if (pkcs7) {
+ while (pkcs7->certs) {
+ cert = pkcs7->certs;
+ pkcs7->certs = cert->next;
+ x509_free_certificate(cert);
+ }
+ while (pkcs7->crl) {
+ cert = pkcs7->crl;
+ pkcs7->crl = cert->next;
+ x509_free_certificate(cert);
+ }
+ while (pkcs7->signed_infos) {
+ sinfo = pkcs7->signed_infos;
+ pkcs7->signed_infos = sinfo->next;
+ mpi_free(sinfo->sig.mpi[0]);
+ kfree(sinfo->sig.digest);
+ kfree(sinfo);
+ }
+ kfree(pkcs7);
+ }
+}
+EXPORT_SYMBOL_GPL(pkcs7_free_message);
+
+/**
+ * pkcs7_parse_message - Parse a PKCS#7 message
+ * @data: The raw binary ASN.1 encoded message to be parsed
+ * @datalen: The size of the encoded message
+ */
+struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
+{
+ struct pkcs7_parse_context *ctx;
+ struct pkcs7_message *msg;
+ long ret;
+
+ ret = -ENOMEM;
+ msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
+ if (!msg)
+ goto error_no_sig;
+ ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
+ if (!ctx)
+ goto error_no_ctx;
+ ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+ if (!ctx->sinfo)
+ goto error_no_sinfo;
+
+ ctx->msg = msg;
+ ctx->data = (unsigned long)data;
+ ctx->ppcerts = &ctx->certs;
+ ctx->ppsinfo = &ctx->msg->signed_infos;
+
+ /* Attempt to decode the signature */
+ ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
+ if (ret < 0)
+ goto error_decode;
+
+ while (ctx->certs) {
+ struct x509_certificate *cert = ctx->certs;
+ ctx->certs = cert->next;
+ x509_free_certificate(cert);
+ }
+ mpi_free(ctx->sinfo->sig.mpi[0]);
+ kfree(ctx->sinfo->sig.digest);
+ kfree(ctx->sinfo);
+ kfree(ctx);
+ return msg;
+
+error_decode:
+ mpi_free(ctx->sinfo->sig.mpi[0]);
+ kfree(ctx->sinfo->sig.digest);
+ kfree(ctx->sinfo);
+error_no_sinfo:
+ kfree(ctx);
+error_no_ctx:
+ pkcs7_free_message(msg);
+error_no_sig:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pkcs7_parse_message);
+
+/**
+ * pkcs7_get_content_data - Get access to the PKCS#7 content
+ * @pkcs7: The preparsed PKCS#7 message to access
+ * @_data: Place to return a pointer to the data
+ * @_data_len: Place to return the data length
+ * @want_wrapper: True if the ASN.1 object header should be included in the data
+ *
+ * Get access to the data content of the PKCS#7 message, including, optionally,
+ * the header of the ASN.1 object that contains it. Returns -ENODATA if the
+ * data object was missing from the message.
+ */
+int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
+ const void **_data, size_t *_data_len,
+ bool want_wrapper)
+{
+ size_t wrapper;
+
+ if (!pkcs7->data)
+ return -ENODATA;
+
+ wrapper = want_wrapper ? pkcs7->data_hdrlen : 0;
+ *_data = pkcs7->data - wrapper;
+ *_data_len = pkcs7->data_len + wrapper;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
+
+/*
+ * Note an OID when we find one for later processing when we know how
+ * to interpret it.
+ */
+int pkcs7_note_OID(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ ctx->last_oid = look_up_OID(value, vlen);
+ if (ctx->last_oid == OID__NR) {
+ char buffer[50];
+ sprint_oid(value, vlen, buffer, sizeof(buffer));
+ printk("PKCS7: Unknown OID: [%lu] %s\n",
+ (unsigned long)value - ctx->data, buffer);
+ }
+ return 0;
+}
+
+/*
+ * Note the digest algorithm for the signature.
+ */
+int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
+ case OID_md4:
+ ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
+ break;
+ case OID_md5:
+ ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
+ break;
+ case OID_sha1:
+ ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
+ break;
+ case OID_sha256:
+ ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
+ break;
+ default:
+ printk("Unsupported digest algo: %u\n", ctx->last_oid);
+ return -ENOPKG;
+ }
+ return 0;
+}
+
+/*
+ * Note the public key algorithm for the signature.
+ */
+int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
+ case OID_rsaEncryption:
+ ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
+ break;
+ default:
+ printk("Unsupported pkey algo: %u\n", ctx->last_oid);
+ return -ENOPKG;
+ }
+ return 0;
+}
+
+/*
+ * Extract a certificate and store it in the context.
+ */
+int pkcs7_extract_cert(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ struct x509_certificate *x509;
+
+ if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
+ pr_debug("Cert began with tag %02x at %lu\n",
+ tag, (unsigned long)ctx - ctx->data);
+ return -EBADMSG;
+ }
+
+ /* We have to correct for the header so that the X.509 parser can start
+ * from the beginning. Note that since X.509 stipulates DER, there
+ * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which
+ * stipulates BER).
+ */
+ value -= hdrlen;
+ vlen += hdrlen;
+
+ if (((u8*)value)[1] == 0x80)
+ vlen += 2; /* Indefinite length - there should be an EOC */
+
+ x509 = x509_cert_parse(value, vlen);
+ if (IS_ERR(x509))
+ return PTR_ERR(x509);
+
+ pr_debug("Got cert for %s\n", x509->subject);
+ pr_debug("- fingerprint %s\n", x509->fingerprint);
+
+ x509->index = ++ctx->x509_index;
+ *ctx->ppcerts = x509;
+ ctx->ppcerts = &x509->next;
+ return 0;
+}
+
+/*
+ * Save the certificate list
+ */
+int pkcs7_note_certificate_list(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_devel("Got cert list (%02x)\n", tag);
+
+ *ctx->ppcerts = ctx->msg->certs;
+ ctx->msg->certs = ctx->certs;
+ ctx->certs = NULL;
+ ctx->ppcerts = &ctx->certs;
+ return 0;
+}
+
+/*
+ * Extract the data from the message and store that and its content type OID in
+ * the context.
+ */
+int pkcs7_note_data(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_debug("Got data\n");
+
+ ctx->msg->data = value;
+ ctx->msg->data_len = vlen;
+ ctx->msg->data_hdrlen = hdrlen;
+ ctx->msg->data_type = ctx->last_oid;
+ return 0;
+}
+
+/*
+ * Parse authenticated attributes
+ */
+int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
+
+ switch (ctx->last_oid) {
+ case OID_messageDigest:
+ if (tag != ASN1_OTS)
+ return -EBADMSG;
+ ctx->sinfo->msgdigest = value;
+ ctx->sinfo->msgdigest_len = vlen;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Note the set of auth attributes for digestion purposes [RFC2315 9.3]
+ */
+int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
+ ctx->sinfo->authattrs = value - (hdrlen - 1);
+ ctx->sinfo->authattrs_len = vlen + (hdrlen - 1);
+ return 0;
+}
+
+/*
+ * Note the issuing certificate serial number
+ */
+int pkcs7_sig_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ ctx->sinfo->raw_serial = value;
+ ctx->sinfo->raw_serial_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the issuer's name
+ */
+int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ ctx->sinfo->raw_issuer = value;
+ ctx->sinfo->raw_issuer_size = vlen;
+ return 0;
+}
+
+/*
+ * Note the signature data
+ */
+int pkcs7_sig_note_signature(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+ MPI mpi;
+
+ BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
+
+ mpi = mpi_read_raw_data(value, vlen);
+ if (!mpi)
+ return -ENOMEM;
+
+ ctx->sinfo->sig.mpi[0] = mpi;
+ ctx->sinfo->sig.nr_mpi = 1;
+ return 0;
+}
+
+/*
+ * Note a signature information block
+ */
+int pkcs7_note_signed_info(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_parse_context *ctx = context;
+
+ ctx->sinfo->index = ++ctx->sinfo_index;
+ *ctx->ppsinfo = ctx->sinfo;
+ ctx->ppsinfo = &ctx->sinfo->next;
+ ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
+ if (!ctx->sinfo)
+ return -ENOMEM;
+ return 0;
+}
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
new file mode 100644
index 000000000000..d25f4d15370f
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -0,0 +1,61 @@
+/* PKCS#7 crypto data parser internal definitions
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/oid_registry.h>
+#include <crypto/pkcs7.h>
+#include "x509_parser.h"
+
+#define kenter(FMT, ...) \
+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+struct pkcs7_signed_info {
+ struct pkcs7_signed_info *next;
+ struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
+ unsigned index;
+ bool trusted;
+
+ /* Message digest - the digest of the Content Data (or NULL) */
+ const void *msgdigest;
+ unsigned msgdigest_len;
+
+ /* Authenticated Attribute data (or NULL) */
+ unsigned authattrs_len;
+ const void *authattrs;
+
+ /* Issuing cert serial number and issuer's name */
+ const void *raw_serial;
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer;
+
+ /* Message signature.
+ *
+ * This contains the generated digest of _either_ the Content Data or
+ * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of
+ * the attributes contains the digest of the the Content Data within
+ * it.
+ */
+ struct public_key_signature sig;
+};
+
+struct pkcs7_message {
+ struct x509_certificate *certs; /* Certificate list */
+ struct x509_certificate *crl; /* Revocation list */
+ struct pkcs7_signed_info *signed_infos;
+
+ /* Content Data (or NULL) */
+ enum OID data_type; /* Type of Data */
+ size_t data_len; /* Length of Data */
+ size_t data_hdrlen; /* Length of Data ASN.1 header */
+ const void *data; /* Content Data (or 0) */
+};
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
new file mode 100644
index 000000000000..e666eb011a85
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -0,0 +1,166 @@
+/* Validate the trust chain of a PKCS#7 message.
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/asn1.h>
+#include <linux/key.h>
+#include <keys/asymmetric-type.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+
+/**
+ * Check the trust on one PKCS#7 SignedInfo block.
+ */
+int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo,
+ struct key *trust_keyring)
+{
+ struct public_key_signature *sig = &sinfo->sig;
+ struct x509_certificate *x509, *last = NULL, *p;
+ struct key *key;
+ bool trusted;
+ int ret;
+
+ kenter(",%u,", sinfo->index);
+
+ for (x509 = sinfo->signer; x509; x509 = x509->signer) {
+ if (x509->seen) {
+ if (x509->verified) {
+ trusted = x509->trusted;
+ goto verified;
+ }
+ kleave(" = -ENOKEY [cached]");
+ return -ENOKEY;
+ }
+ x509->seen = true;
+
+ /* Look to see if this certificate is present in the trusted
+ * keys.
+ */
+ key = x509_request_asymmetric_key(trust_keyring, x509->subject,
+ x509->fingerprint);
+ if (!IS_ERR(key))
+ /* One of the X.509 certificates in the PKCS#7 message
+ * is apparently the same as one we already trust.
+ * Verify that the trusted variant can also validate
+ * the signature on the descendant.
+ */
+ goto matched;
+ if (key == ERR_PTR(-ENOMEM))
+ return -ENOMEM;
+
+ /* Self-signed certificates form roots of their own, and if we
+ * don't know them, then we can't accept them.
+ */
+ if (x509->next == x509) {
+ kleave(" = -ENOKEY [unknown self-signed]");
+ return -ENOKEY;
+ }
+
+ might_sleep();
+ last = x509;
+ sig = &last->sig;
+ }
+
+ /* No match - see if the root certificate has a signer amongst the
+ * trusted keys.
+ */
+ if (!last || !last->issuer || !last->authority) {
+ kleave(" = -ENOKEY [no backref]");
+ return -ENOKEY;
+ }
+
+ key = x509_request_asymmetric_key(trust_keyring, last->issuer,
+ last->authority);
+ if (IS_ERR(key))
+ return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY;
+ x509 = last;
+
+matched:
+ ret = verify_signature(key, sig);
+ trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags);
+ key_put(key);
+ if (ret < 0) {
+ if (ret == -ENOMEM)
+ return ret;
+ kleave(" = -EKEYREJECTED [verify %d]", ret);
+ return -EKEYREJECTED;
+ }
+
+verified:
+ x509->verified = true;
+ for (p = sinfo->signer; p != x509; p = p->signer) {
+ p->verified = true;
+ p->trusted = trusted;
+ }
+ sinfo->trusted = trusted;
+ kleave(" = 0");
+ return 0;
+}
+
+/**
+ * pkcs7_validate_trust - Validate PKCS#7 trust chain
+ * @pkcs7: The PKCS#7 certificate to validate
+ * @trust_keyring: Signing certificates to use as starting points
+ * @_trusted: Set to true if trustworth, false otherwise
+ *
+ * Validate that the certificate chain inside the PKCS#7 message intersects
+ * keys we already know and trust.
+ *
+ * Returns, in order of descending priority:
+ *
+ * (*) -EKEYREJECTED if a signature failed to match for which we have a valid
+ * key, or:
+ *
+ * (*) 0 if at least one signature chain intersects with the keys in the trust
+ * keyring, or:
+ *
+ * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
+ * chain.
+ *
+ * (*) -ENOKEY if we couldn't find a match for any of the signature chains in
+ * the message.
+ *
+ * May also return -ENOMEM.
+ */
+int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
+ struct key *trust_keyring,
+ bool *_trusted)
+{
+ struct pkcs7_signed_info *sinfo;
+ struct x509_certificate *p;
+ int cached_ret = 0, ret;
+
+ for (p = pkcs7->certs; p; p = p->next)
+ p->seen = false;
+
+ for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
+ ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring);
+ if (ret < 0) {
+ if (ret == -ENOPKG) {
+ cached_ret = -ENOPKG;
+ } else if (ret == -ENOKEY) {
+ if (cached_ret == 0)
+ cached_ret = -ENOKEY;
+ } else {
+ return ret;
+ }
+ }
+ *_trusted |= sinfo->trusted;
+ }
+
+ return cached_ret;
+}
+EXPORT_SYMBOL_GPL(pkcs7_validate_trust);
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
new file mode 100644
index 000000000000..c62cf8006e1f
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -0,0 +1,321 @@
+/* Verify the signature on a PKCS#7 message.
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "PKCS7: "fmt
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/asn1.h>
+#include <crypto/hash.h>
+#include "public_key.h"
+#include "pkcs7_parser.h"
+
+/*
+ * Digest the relevant parts of the PKCS#7 data
+ */
+static int pkcs7_digest(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo)
+{
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ size_t digest_size, desc_size;
+ void *digest;
+ int ret;
+
+ kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo);
+
+ if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
+ !hash_algo_name[sinfo->sig.pkey_hash_algo])
+ return -ENOPKG;
+
+ /* Allocate the hashing algorithm we're going to need and find out how
+ * big the hash operational data will be.
+ */
+ tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo],
+ 0, 0);
+ if (IS_ERR(tfm))
+ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
+
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm);
+
+ ret = -ENOMEM;
+ digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
+ if (!digest)
+ goto error_no_desc;
+
+ desc = digest + digest_size;
+ desc->tfm = tfm;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ /* Digest the message [RFC2315 9.3] */
+ ret = crypto_shash_init(desc);
+ if (ret < 0)
+ goto error;
+ ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest);
+ if (ret < 0)
+ goto error;
+ pr_devel("MsgDigest = [%*ph]\n", 8, digest);
+
+ /* However, if there are authenticated attributes, there must be a
+ * message digest attribute amongst them which corresponds to the
+ * digest we just calculated.
+ */
+ if (sinfo->msgdigest) {
+ u8 tag;
+
+ if (sinfo->msgdigest_len != sinfo->sig.digest_size) {
+ pr_debug("Sig %u: Invalid digest size (%u)\n",
+ sinfo->index, sinfo->msgdigest_len);
+ ret = -EBADMSG;
+ goto error;
+ }
+
+ if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) {
+ pr_debug("Sig %u: Message digest doesn't match\n",
+ sinfo->index);
+ ret = -EKEYREJECTED;
+ goto error;
+ }
+
+ /* We then calculate anew, using the authenticated attributes
+ * as the contents of the digest instead. Note that we need to
+ * convert the attributes from a CONT.0 into a SET before we
+ * hash it.
+ */
+ memset(digest, 0, sinfo->sig.digest_size);
+
+ ret = crypto_shash_init(desc);
+ if (ret < 0)
+ goto error;
+ tag = ASN1_CONS_BIT | ASN1_SET;
+ ret = crypto_shash_update(desc, &tag, 1);
+ if (ret < 0)
+ goto error;
+ ret = crypto_shash_finup(desc, sinfo->authattrs,
+ sinfo->authattrs_len, digest);
+ if (ret < 0)
+ goto error;
+ pr_devel("AADigest = [%*ph]\n", 8, digest);
+ }
+
+ sinfo->sig.digest = digest;
+ digest = NULL;
+
+error:
+ kfree(digest);
+error_no_desc:
+ crypto_free_shash(tfm);
+ kleave(" = %d", ret);
+ return ret;
+}
+
+/*
+ * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7
+ * uses the issuer's name and the issuing certificate serial number for
+ * matching purposes. These must match the certificate issuer's name (not
+ * subject's name) and the certificate serial number [RFC 2315 6.7].
+ */
+static int pkcs7_find_key(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo)
+{
+ struct x509_certificate *x509;
+ unsigned certix = 1;
+
+ kenter("%u,%u,%u",
+ sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size);
+
+ for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
+ /* I'm _assuming_ that the generator of the PKCS#7 message will
+ * encode the fields from the X.509 cert in the same way in the
+ * PKCS#7 message - but I can't be 100% sure of that. It's
+ * possible this will need element-by-element comparison.
+ */
+ if (x509->raw_serial_size != sinfo->raw_serial_size ||
+ memcmp(x509->raw_serial, sinfo->raw_serial,
+ sinfo->raw_serial_size) != 0)
+ continue;
+ pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
+ sinfo->index, certix);
+
+ if (x509->raw_issuer_size != sinfo->raw_issuer_size ||
+ memcmp(x509->raw_issuer, sinfo->raw_issuer,
+ sinfo->raw_issuer_size) != 0) {
+ pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n",
+ sinfo->index);
+ continue;
+ }
+
+ if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
+ pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
+ sinfo->index);
+ continue;
+ }
+
+ sinfo->signer = x509;
+ return 0;
+ }
+ pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n",
+ sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial);
+ return -ENOKEY;
+}
+
+/*
+ * Verify the internal certificate chain as best we can.
+ */
+static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo)
+{
+ struct x509_certificate *x509 = sinfo->signer, *p;
+ int ret;
+
+ kenter("");
+
+ for (p = pkcs7->certs; p; p = p->next)
+ p->seen = false;
+
+ for (;;) {
+ pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
+ x509->seen = true;
+ ret = x509_get_sig_params(x509);
+ if (ret < 0)
+ return ret;
+
+ pr_debug("- issuer %s\n", x509->issuer);
+ if (x509->authority)
+ pr_debug("- authkeyid %s\n", x509->authority);
+
+ if (!x509->authority ||
+ strcmp(x509->subject, x509->issuer) == 0) {
+ /* If there's no authority certificate specified, then
+ * the certificate must be self-signed and is the root
+ * of the chain. Likewise if the cert is its own
+ * authority.
+ */
+ pr_debug("- no auth?\n");
+ if (x509->raw_subject_size != x509->raw_issuer_size ||
+ memcmp(x509->raw_subject, x509->raw_issuer,
+ x509->raw_issuer_size) != 0)
+ return 0;
+
+ ret = x509_check_signature(x509->pub, x509);
+ if (ret < 0)
+ return ret;
+ x509->signer = x509;
+ pr_debug("- self-signed\n");
+ return 0;
+ }
+
+ /* Look through the X.509 certificates in the PKCS#7 message's
+ * list to see if the next one is there.
+ */
+ pr_debug("- want %s\n", x509->authority);
+ for (p = pkcs7->certs; p; p = p->next) {
+ pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint);
+ if (p->raw_subject_size == x509->raw_issuer_size &&
+ strcmp(p->fingerprint, x509->authority) == 0 &&
+ memcmp(p->raw_subject, x509->raw_issuer,
+ x509->raw_issuer_size) == 0)
+ goto found_issuer;
+ }
+
+ /* We didn't find the root of this chain */
+ pr_debug("- top\n");
+ return 0;
+
+ found_issuer:
+ pr_debug("- issuer %s\n", p->subject);
+ if (p->seen) {
+ pr_warn("Sig %u: X.509 chain contains loop\n",
+ sinfo->index);
+ return 0;
+ }
+ ret = x509_check_signature(p->pub, x509);
+ if (ret < 0)
+ return ret;
+ x509->signer = p;
+ if (x509 == p) {
+ pr_debug("- self-signed\n");
+ return 0;
+ }
+ x509 = p;
+ might_sleep();
+ }
+}
+
+/*
+ * Verify one signed information block from a PKCS#7 message.
+ */
+static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo)
+{
+ int ret;
+
+ kenter(",%u", sinfo->index);
+
+ /* First of all, digest the data in the PKCS#7 message and the
+ * signed information block
+ */
+ ret = pkcs7_digest(pkcs7, sinfo);
+ if (ret < 0)
+ return ret;
+
+ /* Find the key for the signature */
+ ret = pkcs7_find_key(pkcs7, sinfo);
+ if (ret < 0)
+ return ret;
+
+ pr_devel("Using X.509[%u] for sig %u\n",
+ sinfo->signer->index, sinfo->index);
+
+ /* Verify the PKCS#7 binary against the key */
+ ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
+ if (ret < 0)
+ return ret;
+
+ pr_devel("Verified signature %u\n", sinfo->index);
+
+ /* Verify the internal certificate chain */
+ return pkcs7_verify_sig_chain(pkcs7, sinfo);
+}
+
+/**
+ * pkcs7_verify - Verify a PKCS#7 message
+ * @pkcs7: The PKCS#7 message to be verified
+ */
+int pkcs7_verify(struct pkcs7_message *pkcs7)
+{
+ struct pkcs7_signed_info *sinfo;
+ struct x509_certificate *x509;
+ int ret, n;
+
+ kenter("");
+
+ for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) {
+ ret = x509_get_sig_params(x509);
+ if (ret < 0)
+ return ret;
+ pr_debug("X.509[%u] %s\n", n, x509->authority);
+ }
+
+ for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
+ ret = pkcs7_verify_one(pkcs7, sinfo);
+ if (ret < 0) {
+ kleave(" = %d", ret);
+ return ret;
+ }
+ }
+
+ kleave(" = 0");
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_verify);
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
new file mode 100644
index 000000000000..79175e6ea0b2
--- /dev/null
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -0,0 +1,457 @@
+/* Parse a signed PE binary
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "PEFILE: "fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pe.h>
+#include <linux/asn1.h>
+#include <crypto/pkcs7.h>
+#include <crypto/hash.h>
+#include "verify_pefile.h"
+
+/*
+ * Parse a PE binary.
+ */
+static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
+ struct pefile_context *ctx)
+{
+ const struct mz_hdr *mz = pebuf;
+ const struct pe_hdr *pe;
+ const struct pe32_opt_hdr *pe32;
+ const struct pe32plus_opt_hdr *pe64;
+ const struct data_directory *ddir;
+ const struct data_dirent *dde;
+ const struct section_header *secs, *sec;
+ size_t cursor, datalen = pelen;
+
+ kenter("");
+
+#define chkaddr(base, x, s) \
+ do { \
+ if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \
+ return -ELIBBAD; \
+ } while (0)
+
+ chkaddr(0, 0, sizeof(*mz));
+ if (mz->magic != MZ_MAGIC)
+ return -ELIBBAD;
+ cursor = sizeof(*mz);
+
+ chkaddr(cursor, mz->peaddr, sizeof(*pe));
+ pe = pebuf + mz->peaddr;
+ if (pe->magic != PE_MAGIC)
+ return -ELIBBAD;
+ cursor = mz->peaddr + sizeof(*pe);
+
+ chkaddr(0, cursor, sizeof(pe32->magic));
+ pe32 = pebuf + cursor;
+ pe64 = pebuf + cursor;
+
+ switch (pe32->magic) {
+ case PE_OPT_MAGIC_PE32:
+ chkaddr(0, cursor, sizeof(*pe32));
+ ctx->image_checksum_offset =
+ (unsigned long)&pe32->csum - (unsigned long)pebuf;
+ ctx->header_size = pe32->header_size;
+ cursor += sizeof(*pe32);
+ ctx->n_data_dirents = pe32->data_dirs;
+ break;
+
+ case PE_OPT_MAGIC_PE32PLUS:
+ chkaddr(0, cursor, sizeof(*pe64));
+ ctx->image_checksum_offset =
+ (unsigned long)&pe64->csum - (unsigned long)pebuf;
+ ctx->header_size = pe64->header_size;
+ cursor += sizeof(*pe64);
+ ctx->n_data_dirents = pe64->data_dirs;
+ break;
+
+ default:
+ pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
+ return -ELIBBAD;
+ }
+
+ pr_debug("checksum @ %x\n", ctx->image_checksum_offset);
+ pr_debug("header size = %x\n", ctx->header_size);
+
+ if (cursor >= ctx->header_size || ctx->header_size >= datalen)
+ return -ELIBBAD;
+
+ if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde))
+ return -ELIBBAD;
+
+ ddir = pebuf + cursor;
+ cursor += sizeof(*dde) * ctx->n_data_dirents;
+
+ ctx->cert_dirent_offset =
+ (unsigned long)&ddir->certs - (unsigned long)pebuf;
+ ctx->certs_size = ddir->certs.size;
+
+ if (!ddir->certs.virtual_address || !ddir->certs.size) {
+ pr_debug("Unsigned PE binary\n");
+ return -EKEYREJECTED;
+ }
+
+ chkaddr(ctx->header_size, ddir->certs.virtual_address,
+ ddir->certs.size);
+ ctx->sig_offset = ddir->certs.virtual_address;
+ ctx->sig_len = ddir->certs.size;
+ pr_debug("cert = %x @%x [%*ph]\n",
+ ctx->sig_len, ctx->sig_offset,
+ ctx->sig_len, pebuf + ctx->sig_offset);
+
+ ctx->n_sections = pe->sections;
+ if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec))
+ return -ELIBBAD;
+ ctx->secs = secs = pebuf + cursor;
+
+ return 0;
+}
+
+/*
+ * Check and strip the PE wrapper from around the signature and check that the
+ * remnant looks something like PKCS#7.
+ */
+static int pefile_strip_sig_wrapper(const void *pebuf,
+ struct pefile_context *ctx)
+{
+ struct win_certificate wrapper;
+ const u8 *pkcs7;
+
+ if (ctx->sig_len < sizeof(wrapper)) {
+ pr_debug("Signature wrapper too short\n");
+ return -ELIBBAD;
+ }
+
+ memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper));
+ pr_debug("sig wrapper = { %x, %x, %x }\n",
+ wrapper.length, wrapper.revision, wrapper.cert_type);
+
+ /* Both pesign and sbsign round up the length of certificate table
+ * (in optional header data directories) to 8 byte alignment.
+ */
+ if (round_up(wrapper.length, 8) != ctx->sig_len) {
+ pr_debug("Signature wrapper len wrong\n");
+ return -ELIBBAD;
+ }
+ if (wrapper.revision != WIN_CERT_REVISION_2_0) {
+ pr_debug("Signature is not revision 2.0\n");
+ return -ENOTSUPP;
+ }
+ if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+ pr_debug("Signature certificate type is not PKCS\n");
+ return -ENOTSUPP;
+ }
+
+ /* Looks like actual pkcs signature length is in wrapper->length.
+ * size obtained from data dir entries lists the total size of
+ * certificate table which is also aligned to octawrod boundary.
+ *
+ * So set signature length field appropriately.
+ */
+ ctx->sig_len = wrapper.length;
+ ctx->sig_offset += sizeof(wrapper);
+ ctx->sig_len -= sizeof(wrapper);
+ if (ctx->sig_len == 0) {
+ pr_debug("Signature data missing\n");
+ return -EKEYREJECTED;
+ }
+
+ /* What's left should a PKCS#7 cert */
+ pkcs7 = pebuf + ctx->sig_offset;
+ if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) {
+ if (pkcs7[1] == 0x82 &&
+ pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) &&
+ pkcs7[3] == ((ctx->sig_len - 4) & 0xff))
+ return 0;
+ if (pkcs7[1] == 0x80)
+ return 0;
+ if (pkcs7[1] > 0x82)
+ return -EMSGSIZE;
+ }
+
+ pr_debug("Signature data not PKCS#7\n");
+ return -ELIBBAD;
+}
+
+/*
+ * Compare two sections for canonicalisation.
+ */
+static int pefile_compare_shdrs(const void *a, const void *b)
+{
+ const struct section_header *shdra = a;
+ const struct section_header *shdrb = b;
+ int rc;
+
+ if (shdra->data_addr > shdrb->data_addr)
+ return 1;
+ if (shdrb->data_addr > shdra->data_addr)
+ return -1;
+
+ if (shdra->virtual_address > shdrb->virtual_address)
+ return 1;
+ if (shdrb->virtual_address > shdra->virtual_address)
+ return -1;
+
+ rc = strcmp(shdra->name, shdrb->name);
+ if (rc != 0)
+ return rc;
+
+ if (shdra->virtual_size > shdrb->virtual_size)
+ return 1;
+ if (shdrb->virtual_size > shdra->virtual_size)
+ return -1;
+
+ if (shdra->raw_data_size > shdrb->raw_data_size)
+ return 1;
+ if (shdrb->raw_data_size > shdra->raw_data_size)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Load the contents of the PE binary into the digest, leaving out the image
+ * checksum and the certificate data block.
+ */
+static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,
+ struct pefile_context *ctx,
+ struct shash_desc *desc)
+{
+ unsigned *canon, tmp, loop, i, hashed_bytes;
+ int ret;
+
+ /* Digest the header and data directory, but leave out the image
+ * checksum and the data dirent for the signature.
+ */
+ ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset);
+ if (ret < 0)
+ return ret;
+
+ tmp = ctx->image_checksum_offset + sizeof(uint32_t);
+ ret = crypto_shash_update(desc, pebuf + tmp,
+ ctx->cert_dirent_offset - tmp);
+ if (ret < 0)
+ return ret;
+
+ tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent);
+ ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp);
+ if (ret < 0)
+ return ret;
+
+ canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL);
+ if (!canon)
+ return -ENOMEM;
+
+ /* We have to canonicalise the section table, so we perform an
+ * insertion sort.
+ */
+ canon[0] = 0;
+ for (loop = 1; loop < ctx->n_sections; loop++) {
+ for (i = 0; i < loop; i++) {
+ if (pefile_compare_shdrs(&ctx->secs[canon[i]],
+ &ctx->secs[loop]) > 0) {
+ memmove(&canon[i + 1], &canon[i],
+ (loop - i) * sizeof(canon[0]));
+ break;
+ }
+ }
+ canon[i] = loop;
+ }
+
+ hashed_bytes = ctx->header_size;
+ for (loop = 0; loop < ctx->n_sections; loop++) {
+ i = canon[loop];
+ if (ctx->secs[i].raw_data_size == 0)
+ continue;
+ ret = crypto_shash_update(desc,
+ pebuf + ctx->secs[i].data_addr,
+ ctx->secs[i].raw_data_size);
+ if (ret < 0) {
+ kfree(canon);
+ return ret;
+ }
+ hashed_bytes += ctx->secs[i].raw_data_size;
+ }
+ kfree(canon);
+
+ if (pelen > hashed_bytes) {
+ tmp = hashed_bytes + ctx->certs_size;
+ ret = crypto_shash_update(desc,
+ pebuf + hashed_bytes,
+ pelen - tmp);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Digest the contents of the PE binary, leaving out the image checksum and the
+ * certificate data block.
+ */
+static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
+ struct pefile_context *ctx)
+{
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ size_t digest_size, desc_size;
+ void *digest;
+ int ret;
+
+ kenter(",%u", ctx->digest_algo);
+
+ /* Allocate the hashing algorithm we're going to need and find out how
+ * big the hash operational data will be.
+ */
+ tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0);
+ if (IS_ERR(tfm))
+ return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
+
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ digest_size = crypto_shash_digestsize(tfm);
+
+ if (digest_size != ctx->digest_len) {
+ pr_debug("Digest size mismatch (%zx != %x)\n",
+ digest_size, ctx->digest_len);
+ ret = -EBADMSG;
+ goto error_no_desc;
+ }
+ pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size);
+
+ ret = -ENOMEM;
+ desc = kzalloc(desc_size + digest_size, GFP_KERNEL);
+ if (!desc)
+ goto error_no_desc;
+
+ desc->tfm = tfm;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ ret = crypto_shash_init(desc);
+ if (ret < 0)
+ goto error;
+
+ ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc);
+ if (ret < 0)
+ goto error;
+
+ digest = (void *)desc + desc_size;
+ ret = crypto_shash_final(desc, digest);
+ if (ret < 0)
+ goto error;
+
+ pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest);
+
+ /* Check that the PE file digest matches that in the MSCODE part of the
+ * PKCS#7 certificate.
+ */
+ if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
+ pr_debug("Digest mismatch\n");
+ ret = -EKEYREJECTED;
+ } else {
+ pr_debug("The digests match!\n");
+ }
+
+error:
+ kfree(desc);
+error_no_desc:
+ crypto_free_shash(tfm);
+ kleave(" = %d", ret);
+ return ret;
+}
+
+/**
+ * verify_pefile_signature - Verify the signature on a PE binary image
+ * @pebuf: Buffer containing the PE binary image
+ * @pelen: Length of the binary image
+ * @trust_keyring: Signing certificates to use as starting points
+ * @_trusted: Set to true if trustworth, false otherwise
+ *
+ * Validate that the certificate chain inside the PKCS#7 message inside the PE
+ * binary image intersects keys we already know and trust.
+ *
+ * Returns, in order of descending priority:
+ *
+ * (*) -ELIBBAD if the image cannot be parsed, or:
+ *
+ * (*) -EKEYREJECTED if a signature failed to match for which we have a valid
+ * key, or:
+ *
+ * (*) 0 if at least one signature chain intersects with the keys in the trust
+ * keyring, or:
+ *
+ * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
+ * chain.
+ *
+ * (*) -ENOKEY if we couldn't find a match for any of the signature chains in
+ * the message.
+ *
+ * May also return -ENOMEM.
+ */
+int verify_pefile_signature(const void *pebuf, unsigned pelen,
+ struct key *trusted_keyring, bool *_trusted)
+{
+ struct pkcs7_message *pkcs7;
+ struct pefile_context ctx;
+ const void *data;
+ size_t datalen;
+ int ret;
+
+ kenter("");
+
+ memset(&ctx, 0, sizeof(ctx));
+ ret = pefile_parse_binary(pebuf, pelen, &ctx);
+ if (ret < 0)
+ return ret;
+
+ ret = pefile_strip_sig_wrapper(pebuf, &ctx);
+ if (ret < 0)
+ return ret;
+
+ pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len);
+ if (IS_ERR(pkcs7))
+ return PTR_ERR(pkcs7);
+ ctx.pkcs7 = pkcs7;
+
+ ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false);
+ if (ret < 0 || datalen == 0) {
+ pr_devel("PKCS#7 message does not contain data\n");
+ ret = -EBADMSG;
+ goto error;
+ }
+
+ ret = mscode_parse(&ctx);
+ if (ret < 0)
+ goto error;
+
+ pr_debug("Digest: %u [%*ph]\n",
+ ctx.digest_len, ctx.digest_len, ctx.digest);
+
+ /* Generate the digest and check against the PKCS7 certificate
+ * contents.
+ */
+ ret = pefile_digest_pe(pebuf, pelen, &ctx);
+ if (ret < 0)
+ goto error;
+
+ ret = pkcs7_verify(pkcs7);
+ if (ret < 0)
+ goto error;
+
+ ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted);
+
+error:
+ pkcs7_free_message(ctx.pkcs7);
+ return ret;
+}
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h
new file mode 100644
index 000000000000..55d5f7ebc45a
--- /dev/null
+++ b/crypto/asymmetric_keys/verify_pefile.h
@@ -0,0 +1,42 @@
+/* PE Binary parser bits
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/verify_pefile.h>
+#include <crypto/pkcs7.h>
+#include <crypto/hash_info.h>
+
+struct pefile_context {
+ unsigned header_size;
+ unsigned image_checksum_offset;
+ unsigned cert_dirent_offset;
+ unsigned n_data_dirents;
+ unsigned n_sections;
+ unsigned certs_size;
+ unsigned sig_offset;
+ unsigned sig_len;
+ const struct section_header *secs;
+ struct pkcs7_message *pkcs7;
+
+ /* PKCS#7 MS Individual Code Signing content */
+ const void *digest; /* Digest */
+ unsigned digest_len; /* Digest length */
+ enum hash_algo digest_algo; /* Digest algorithm */
+};
+
+#define kenter(FMT, ...) \
+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+/*
+ * mscode_parser.c
+ */
+extern int mscode_parse(struct pefile_context *ctx);
diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1
index bf32b3dff088..aae0cde414e2 100644
--- a/crypto/asymmetric_keys/x509.asn1
+++ b/crypto/asymmetric_keys/x509.asn1
@@ -6,7 +6,7 @@ Certificate ::= SEQUENCE {
TBSCertificate ::= SEQUENCE {
version [ 0 ] Version DEFAULT,
- serialNumber CertificateSerialNumber,
+ serialNumber CertificateSerialNumber ({ x509_note_serial }),
signature AlgorithmIdentifier ({ x509_note_pkey_algo }),
issuer Name ({ x509_note_issuer }),
validity Validity,
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 29893162497c..ac72348c186a 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -11,6 +11,7 @@
#define pr_fmt(fmt) "X.509: "fmt
#include <linux/kernel.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/oid_registry.h>
@@ -52,6 +53,7 @@ void x509_free_certificate(struct x509_certificate *cert)
kfree(cert);
}
}
+EXPORT_SYMBOL_GPL(x509_free_certificate);
/*
* Parse an X.509 certificate
@@ -97,6 +99,7 @@ error_no_ctx:
error_no_cert:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(x509_cert_parse);
/*
* Note an OID when we find one for later processing when we know how
@@ -211,6 +214,19 @@ int x509_note_signature(void *context, size_t hdrlen,
}
/*
+ * Note the certificate serial number
+ */
+int x509_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ ctx->cert->raw_serial = value;
+ ctx->cert->raw_serial_size = vlen;
+ return 0;
+}
+
+/*
* Note some of the name segments from which we'll fabricate a name.
*/
int x509_extract_name_segment(void *context, size_t hdrlen,
@@ -322,6 +338,8 @@ int x509_note_issuer(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
+ ctx->cert->raw_issuer = value;
+ ctx->cert->raw_issuer_size = vlen;
return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen);
}
@@ -330,6 +348,8 @@ int x509_note_subject(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
+ ctx->cert->raw_subject = value;
+ ctx->cert->raw_subject_size = vlen;
return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen);
}
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 87d9cc26f630..1b76f207c1f3 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -14,7 +14,9 @@
struct x509_certificate {
struct x509_certificate *next;
+ struct x509_certificate *signer; /* Certificate that signed this one */
struct public_key *pub; /* Public key details */
+ struct public_key_signature sig; /* Signature parameters */
char *issuer; /* Name of certificate issuer */
char *subject; /* Name of certificate subject */
char *fingerprint; /* Key fingerprint as hex */
@@ -25,7 +27,16 @@ struct x509_certificate {
unsigned tbs_size; /* Size of signed data */
unsigned raw_sig_size; /* Size of sigature */
const void *raw_sig; /* Signature data */
- struct public_key_signature sig; /* Signature parameters */
+ const void *raw_serial; /* Raw serial number in ASN.1 */
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer; /* Raw issuer name in ASN.1 */
+ const void *raw_subject; /* Raw subject name in ASN.1 */
+ unsigned raw_subject_size;
+ unsigned index;
+ bool seen; /* Infinite recursion prevention */
+ bool verified;
+ bool trusted;
};
/*
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 382ef0d2ff2e..f3d62307e6ee 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,11 +18,86 @@
#include <linux/asn1_decoder.h>
#include <keys/asymmetric-subtype.h>
#include <keys/asymmetric-parser.h>
+#include <keys/system_keyring.h>
#include <crypto/hash.h>
#include "asymmetric_keys.h"
#include "public_key.h"
#include "x509_parser.h"
+static bool use_builtin_keys;
+static char *ca_keyid;
+
+#ifndef MODULE
+static int __init ca_keys_setup(char *str)
+{
+ if (!str) /* default system keyring */
+ return 1;
+
+ if (strncmp(str, "id:", 3) == 0)
+ ca_keyid = str; /* owner key 'id:xxxxxx' */
+ else if (strcmp(str, "builtin") == 0)
+ use_builtin_keys = true;
+
+ return 1;
+}
+__setup("ca_keys=", ca_keys_setup);
+#endif
+
+/**
+ * x509_request_asymmetric_key - Request a key by X.509 certificate params.
+ * @keyring: The keys to search.
+ * @subject: The name of the subject to whom the key belongs.
+ * @key_id: The subject key ID as a hex string.
+ *
+ * Find a key in the given keyring by subject name and key ID. These might,
+ * for instance, be the issuer name and the authority key ID of an X.509
+ * certificate that needs to be verified.
+ */
+struct key *x509_request_asymmetric_key(struct key *keyring,
+ const char *subject,
+ const char *key_id)
+{
+ key_ref_t key;
+ size_t subject_len = strlen(subject), key_id_len = strlen(key_id);
+ char *id;
+
+ /* Construct an identifier "<subjname>:<keyid>". */
+ id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL);
+ if (!id)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(id, subject, subject_len);
+ id[subject_len + 0] = ':';
+ id[subject_len + 1] = ' ';
+ memcpy(id + subject_len + 2, key_id, key_id_len);
+ id[subject_len + 2 + key_id_len] = 0;
+
+ pr_debug("Look up: \"%s\"\n", id);
+
+ key = keyring_search(make_key_ref(keyring, 1),
+ &key_type_asymmetric, id);
+ if (IS_ERR(key))
+ pr_debug("Request for key '%s' err %ld\n", id, PTR_ERR(key));
+ kfree(id);
+
+ if (IS_ERR(key)) {
+ switch (PTR_ERR(key)) {
+ /* Hide some search errors */
+ case -EACCES:
+ case -ENOTDIR:
+ case -EAGAIN:
+ return ERR_PTR(-ENOKEY);
+ default:
+ return ERR_CAST(key);
+ }
+ }
+
+ pr_devel("<==%s() = 0 [%x]\n", __func__,
+ key_serial(key_ref_to_ptr(key)));
+ return key_ref_to_ptr(key);
+}
+EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
+
/*
* Set up the signature parameters in an X.509 certificate. This involves
* digesting the signed data and extracting the signature.
@@ -103,6 +178,38 @@ int x509_check_signature(const struct public_key *pub,
EXPORT_SYMBOL_GPL(x509_check_signature);
/*
+ * Check the new certificate against the ones in the trust keyring. If one of
+ * those is the signing key and validates the new certificate, then mark the
+ * new certificate as being trusted.
+ *
+ * Return 0 if the new certificate was successfully validated, 1 if we couldn't
+ * find a matching parent certificate in the trusted list and an error if there
+ * is a matching certificate but the signature check fails.
+ */
+static int x509_validate_trust(struct x509_certificate *cert,
+ struct key *trust_keyring)
+{
+ struct key *key;
+ int ret = 1;
+
+ if (!trust_keyring)
+ return -EOPNOTSUPP;
+
+ if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid))
+ return -EPERM;
+
+ key = x509_request_asymmetric_key(trust_keyring,
+ cert->issuer, cert->authority);
+ if (!IS_ERR(key)) {
+ if (!use_builtin_keys
+ || test_bit(KEY_FLAG_BUILTIN, &key->flags))
+ ret = x509_check_signature(key->payload.data, cert);
+ key_put(key);
+ }
+ return ret;
+}
+
+/*
* Attempt to parse a data blob for a key as an X509 certificate.
*/
static int x509_key_preparse(struct key_preparsed_payload *prep)
@@ -155,9 +262,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
/* Check the signature on the key if it appears to be self-signed */
if (!cert->authority ||
strcmp(cert->fingerprint, cert->authority) == 0) {
- ret = x509_check_signature(cert->pub, cert);
+ ret = x509_check_signature(cert->pub, cert); /* self-signed */
if (ret < 0)
goto error_free_cert;
+ } else if (!prep->trusted) {
+ ret = x509_validate_trust(cert, get_system_trusted_keyring());
+ if (!ret)
+ prep->trusted = 1;
}
/* Propose a description */
@@ -177,7 +288,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
__module_get(public_key_subtype.owner);
prep->type_data[0] = &public_key_subtype;
prep->type_data[1] = cert->fingerprint;
- prep->payload = cert->pub;
+ prep->payload[0] = cert->pub;
prep->description = desc;
prep->quotalen = 100;
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 7bdd61b867c8..e592c90abebb 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -233,7 +233,7 @@ static void cryptd_blkcipher_decrypt(struct crypto_async_request *req, int err)
}
static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
@@ -241,7 +241,7 @@ static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
queue = cryptd_get_queue(crypto_ablkcipher_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
@@ -414,7 +414,7 @@ static int cryptd_hash_setkey(struct crypto_ahash *parent,
}
static int cryptd_hash_enqueue(struct ahash_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -422,7 +422,7 @@ static int cryptd_hash_enqueue(struct ahash_request *req,
cryptd_get_queue(crypto_ahash_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
@@ -667,14 +667,14 @@ static void cryptd_aead_decrypt(struct crypto_async_request *areq, int err)
}
static int cryptd_aead_enqueue(struct aead_request *req,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct cryptd_aead_request_ctx *rctx = aead_request_ctx(req);
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct cryptd_queue *queue = cryptd_get_queue(crypto_aead_tfm(tfm));
rctx->complete = req->base.complete;
- req->base.complete = complete;
+ req->base.complete = compl;
return cryptd_enqueue_request(queue, &req->base);
}
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index f6cf63f88468..298d464ab7d2 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -859,13 +859,10 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
* property.
*
*/
-static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen)
+int __des3_ede_setkey(u32 *expkey, u32 *flags, const u8 *key,
+ unsigned int keylen)
{
const u32 *K = (const u32 *)key;
- struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
- u32 *expkey = dctx->expkey;
- u32 *flags = &tfm->crt_flags;
if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
!((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
@@ -880,6 +877,17 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
return 0;
}
+EXPORT_SYMBOL_GPL(__des3_ede_setkey);
+
+static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+ u32 *expkey = dctx->expkey;
+
+ return __des3_ede_setkey(expkey, flags, key, keylen);
+}
static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
@@ -945,6 +953,8 @@ static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
static struct crypto_alg des_algs[2] = { {
.cra_name = "des",
+ .cra_driver_name = "des-generic",
+ .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des_ctx),
@@ -958,6 +968,8 @@ static struct crypto_alg des_algs[2] = { {
.cia_decrypt = des_decrypt } }
}, {
.cra_name = "des3_ede",
+ .cra_driver_name = "des3_ede-generic",
+ .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des3_ede_ctx),
diff --git a/crypto/drbg.c b/crypto/drbg.c
new file mode 100644
index 000000000000..7894db9ca90b
--- /dev/null
+++ b/crypto/drbg.c
@@ -0,0 +1,2044 @@
+/*
+ * DRBG: Deterministic Random Bits Generator
+ * Based on NIST Recommended DRBG from NIST SP800-90A with the following
+ * properties:
+ * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
+ * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
+ * * with and without prediction resistance
+ *
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ *
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * DRBG Usage
+ * ==========
+ * The SP 800-90A DRBG allows the user to specify a personalization string
+ * for initialization as well as an additional information string for each
+ * random number request. The following code fragments show how a caller
+ * uses the kernel crypto API to use the full functionality of the DRBG.
+ *
+ * Usage without any additional data
+ * ---------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ *
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization string during initialization
+ * -------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * struct drbg_string pers;
+ * char personalization[11] = "some-string";
+ *
+ * drbg_string_fill(&pers, personalization, strlen(personalization));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset completely re-initializes the DRBG with the provided
+ * // personalization string
+ * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with additional information string during random number request
+ * ---------------------------------------------------------------------
+ * struct crypto_rng *drng;
+ * int err;
+ * char data[DATALEN];
+ * char addtl_string[11] = "some-string";
+ * string drbg_string addtl;
+ *
+ * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
+ * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The following call is a wrapper to crypto_rng_get_bytes() and returns
+ * // the same error codes.
+ * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * crypto_free_rng(drng);
+ *
+ *
+ * Usage with personalization and additional information strings
+ * -------------------------------------------------------------
+ * Just mix both scenarios above.
+ */
+
+#include <crypto/drbg.h>
+
+/***************************************************************
+ * Backend cipher definitions available to DRBG
+ ***************************************************************/
+
+/*
+ * The order of the DRBG definitions here matter: every DRBG is registered
+ * as stdrng. Each DRBG receives an increasing cra_priority values the later
+ * they are defined in this array (see drbg_fill_array).
+ *
+ * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and
+ * the SHA256 / AES 256 over other ciphers. Thus, the favored
+ * DRBGs are the latest entries in this array.
+ */
+static const struct drbg_core drbg_cores[] = {
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ {
+ .flags = DRBG_CTR | DRBG_STRENGTH128,
+ .statelen = 32, /* 256 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes128",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ .flags = DRBG_CTR | DRBG_STRENGTH192,
+ .statelen = 40, /* 320 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes192",
+ .backend_cra_name = "ecb(aes)",
+ }, {
+ .flags = DRBG_CTR | DRBG_STRENGTH256,
+ .statelen = 48, /* 384 bits as defined in 10.2.1 */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 16,
+ .cra_name = "ctr_aes256",
+ .backend_cra_name = "ecb(aes)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ {
+ .flags = DRBG_HASH | DRBG_STRENGTH128,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "sha1",
+ .backend_cra_name = "sha1",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "sha384",
+ .backend_cra_name = "sha384",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 111, /* 888 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "sha512",
+ .backend_cra_name = "sha512",
+ }, {
+ .flags = DRBG_HASH | DRBG_STRENGTH256,
+ .statelen = 55, /* 440 bits */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "sha256",
+ .backend_cra_name = "sha256",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ {
+ .flags = DRBG_HMAC | DRBG_STRENGTH128,
+ .statelen = 20, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 20,
+ .cra_name = "hmac_sha1",
+ .backend_cra_name = "hmac(sha1)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 48, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 48,
+ .cra_name = "hmac_sha384",
+ .backend_cra_name = "hmac(sha384)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 64, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 64,
+ .cra_name = "hmac_sha512",
+ .backend_cra_name = "hmac(sha512)",
+ }, {
+ .flags = DRBG_HMAC | DRBG_STRENGTH256,
+ .statelen = 32, /* block length of cipher */
+ .max_addtllen = 35,
+ .max_bits = 19,
+ .max_req = 48,
+ .blocklen_bytes = 32,
+ .cra_name = "hmac_sha256",
+ .backend_cra_name = "hmac(sha256)",
+ },
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+};
+
+/******************************************************************
+ * Generic helper functions
+ ******************************************************************/
+
+/*
+ * Return strength of DRBG according to SP800-90A section 8.4
+ *
+ * @flags DRBG flags reference
+ *
+ * Return: normalized strength in *bytes* value or 32 as default
+ * to counter programming errors
+ */
+static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
+{
+ switch (flags & DRBG_STRENGTH_MASK) {
+ case DRBG_STRENGTH128:
+ return 16;
+ case DRBG_STRENGTH192:
+ return 24;
+ case DRBG_STRENGTH256:
+ return 32;
+ default:
+ return 32;
+ }
+}
+
+/*
+ * FIPS 140-2 continuous self test
+ * The test is performed on the result of one round of the output
+ * function. Thus, the function implicitly knows the size of the
+ * buffer.
+ *
+ * The FIPS test can be called in an endless loop until it returns
+ * true. Although the code looks like a potential for a deadlock, it
+ * is not the case, because returning a false cannot mathematically
+ * occur (except once when a reseed took place and the updated state
+ * would is now set up such that the generation of new value returns
+ * an identical one -- this is most unlikely and would happen only once).
+ * Thus, if this function repeatedly returns false and thus would cause
+ * a deadlock, the integrity of the entire kernel is lost.
+ *
+ * @drbg DRBG handle
+ * @buf output buffer of random data to be checked
+ *
+ * return:
+ * true on success
+ * false on error
+ */
+static bool drbg_fips_continuous_test(struct drbg_state *drbg,
+ const unsigned char *buf)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int ret = 0;
+ /* skip test if we test the overall system */
+ if (drbg->test_data)
+ return true;
+ /* only perform test in FIPS mode */
+ if (0 == fips_enabled)
+ return true;
+ if (!drbg->fips_primed) {
+ /* Priming of FIPS test */
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ drbg->fips_primed = true;
+ /* return false due to priming, i.e. another round is needed */
+ return false;
+ }
+ ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg));
+ memcpy(drbg->prev, buf, drbg_blocklen(drbg));
+ /* the test shall pass when the two compared values are not equal */
+ return ret != 0;
+#else
+ return true;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @buf buffer holding the converted integer
+ * @val value to be converted
+ * @buflen length of buffer
+ */
+#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
+static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
+ size_t buflen)
+{
+ unsigned char *byte;
+ uint64_t i;
+
+ byte = buf + (buflen - 1);
+ for (i = 0; i < buflen; i++)
+ *(byte--) = val >> (i * 8) & 0xff;
+}
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ const unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr;
+ const unsigned char *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
+
+/******************************************************************
+ * CTR DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+#define CRYPTO_DRBG_CTR_STRING "CTR "
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in);
+static int drbg_init_sym_kernel(struct drbg_state *drbg);
+static int drbg_fini_sym_kernel(struct drbg_state *drbg);
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+static int drbg_ctr_bcc(struct drbg_state *drbg,
+ unsigned char *out, const unsigned char *key,
+ struct list_head *in)
+{
+ int ret = 0;
+ struct drbg_string *curr = NULL;
+ struct drbg_string data;
+ short cnt = 0;
+
+ drbg_string_fill(&data, out, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 1 */
+ memset(out, 0, drbg_blocklen(drbg));
+
+ /* 10.4.3 step 2 / 4 */
+ list_for_each_entry(curr, in, list) {
+ const unsigned char *pos = curr->buf;
+ size_t len = curr->len;
+ /* 10.4.3 step 4.1 */
+ while (len) {
+ /* 10.4.3 step 4.2 */
+ if (drbg_blocklen(drbg) == cnt) {
+ cnt = 0;
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+ if (ret)
+ return ret;
+ }
+ out[cnt] ^= *pos;
+ pos++;
+ cnt++;
+ len--;
+ }
+ }
+ /* 10.4.3 step 4.2 for last block */
+ if (cnt)
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
+
+ return ret;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
+ * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
+ * the scratchpad is used as follows:
+ * drbg_ctr_update:
+ * temp
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg) + drbg_blocklen(drbg)
+ * note: the cipher writing into this variable works
+ * blocklen-wise. Now, when the statelen is not a multiple
+ * of blocklen, the generateion loop below "spills over"
+ * by at most blocklen. Thus, we need to give sufficient
+ * memory.
+ * df_data
+ * start: drbg->scratchpad +
+ * drbg_statelen(drbg) + drbg_blocklen(drbg)
+ * length: drbg_statelen(drbg)
+ *
+ * drbg_ctr_df:
+ * pad
+ * start: df_data + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ * iv
+ * start: pad + drbg_blocklen(drbg)
+ * length: drbg_blocklen(drbg)
+ * temp
+ * start: iv + drbg_blocklen(drbg)
+ * length: drbg_satelen(drbg) + drbg_blocklen(drbg)
+ * note: temp is the buffer that the BCC function operates
+ * on. BCC operates blockwise. drbg_statelen(drbg)
+ * is sufficient when the DRBG state length is a multiple
+ * of the block size. For AES192 (and maybe other ciphers)
+ * this is not correct and the length for temp is
+ * insufficient (yes, that also means for such ciphers,
+ * the final output of all BCC rounds are truncated).
+ * Therefore, add drbg_blocklen(drbg) to cover all
+ * possibilities.
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+static int drbg_ctr_df(struct drbg_state *drbg,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct list_head *seedlist)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ LIST_HEAD(bcc_list);
+ unsigned char *pad = df_data + drbg_statelen(drbg);
+ unsigned char *iv = pad + drbg_blocklen(drbg);
+ unsigned char *temp = iv + drbg_blocklen(drbg);
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ const unsigned char *K = (unsigned char *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+ unsigned char *X;
+ size_t generated_len = 0;
+ size_t inputlen = 0;
+ struct drbg_string *seed = NULL;
+
+ memset(pad, 0, drbg_blocklen(drbg));
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+
+ /* 10.4.2 step 1 is implicit as we work byte-wise */
+
+ /* 10.4.2 step 2 */
+ if ((512/8) < bytes_to_return)
+ return -EINVAL;
+
+ /* 10.4.2 step 2 -- calculate the entire length of all input data */
+ list_for_each_entry(seed, seedlist, list)
+ inputlen += seed->len;
+ drbg_int2byte(&L_N[0], inputlen, 4);
+
+ /* 10.4.2 step 3 */
+ drbg_int2byte(&L_N[4], bytes_to_return, 4);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = drbg_blocklen(drbg) - padlen;
+ /*
+ * pad / padlen contains the 0x80 byte and the following zero bytes.
+ * As the calculated padlen value only covers the number of zero
+ * bytes, this value has to be incremented by one for the 0x80 byte.
+ */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
+ list_add_tail(&S1.list, &bcc_list);
+ drbg_string_fill(&S2, L_N, sizeof(L_N));
+ list_add_tail(&S2.list, &bcc_list);
+ list_splice_tail(seedlist, &bcc_list);
+ drbg_string_fill(&S4, pad, padlen);
+ list_add_tail(&S4.list, &bcc_list);
+
+ /* 10.4.2 step 9 */
+ while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
+ /*
+ * 10.4.2 step 9.1 - the padding is implicit as the buffer
+ * holds zeros after allocation -- even the increment of i
+ * is irrelevant as the increment remains within length of i
+ */
+ drbg_int2byte(iv, i, 4);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += drbg_blocklen(drbg);
+ }
+
+ /* 10.4.2 step 11 */
+ X = temp + (drbg_keylen(drbg));
+ drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
+
+ /* 10.4.2 step 12: overwriting of outval is implemented in next step */
+
+ /* 10.4.2 step 13 */
+ while (generated_len < bytes_to_return) {
+ short blocklen = 0;
+ /*
+ * 10.4.2 step 13.1: the truncation of the key length is
+ * implicit as the key is only drbg_blocklen in size based on
+ * the implementation of the cipher function callback
+ */
+ ret = drbg_kcapi_sym(drbg, temp, X, &cipherin);
+ if (ret)
+ goto out;
+ blocklen = (drbg_blocklen(drbg) <
+ (bytes_to_return - generated_len)) ?
+ drbg_blocklen(drbg) :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, drbg_blocklen(drbg));
+ memset(temp, 0, drbg_statelen(drbg));
+ memset(pad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/*
+ * update function of CTR DRBG as defined in 10.2.1.2
+ *
+ * The reseed variable has an enhanced meaning compared to the update
+ * functions of the other DRBGs as follows:
+ * 0 => initial seed from initialization
+ * 1 => reseed via drbg_seed
+ * 2 => first invocation from drbg_ctr_update when addtl is present. In
+ * this case, the df_data scratchpad is not deleted so that it is
+ * available for another calls to prevent calling the DF function
+ * again.
+ * 3 => second invocation from drbg_ctr_update. When the update function
+ * was called with addtl, the df_data memory already contains the
+ * DFed addtl information and we do not need to call DF again.
+ */
+static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ /* 10.2.1.2 step 1 */
+ unsigned char *temp = drbg->scratchpad;
+ unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
+ drbg_blocklen(drbg);
+ unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
+ unsigned int len = 0;
+ struct drbg_string cipherin;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ if (3 > reseed)
+ memset(df_data, 0, drbg_statelen(drbg));
+
+ /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
+ if (seed) {
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
+ if (ret)
+ goto out;
+ }
+
+ drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg));
+ /*
+ * 10.2.1.3.2 steps 2 and 3 are already covered as the allocation
+ * zeroizes all memory during initialization
+ */
+ while (len < (drbg_statelen(drbg))) {
+ /* 10.2.1.2 step 2.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ /*
+ * 10.2.1.2 step 2.2 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
+ if (ret)
+ goto out;
+ /* 10.2.1.2 step 2.3 and 3 */
+ len += drbg_blocklen(drbg);
+ }
+
+ /* 10.2.1.2 step 4 */
+ temp_p = temp;
+ df_data_p = df_data;
+ for (len = 0; len < drbg_statelen(drbg); len++) {
+ *temp_p ^= *df_data_p;
+ df_data_p++; temp_p++;
+ }
+
+ /* 10.2.1.2 step 5 */
+ memcpy(drbg->C, temp, drbg_keylen(drbg));
+ /* 10.2.1.2 step 6 */
+ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
+ ret = 0;
+
+out:
+ memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ if (2 != reseed)
+ memset(df_data, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/*
+ * scratchpad use: drbg_ctr_update is called independently from
+ * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
+ */
+/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
+static int drbg_ctr_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct list_head *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.2.1.5.2 step 2 */
+ if (addtl && !list_empty(addtl)) {
+ ret = drbg_ctr_update(drbg, addtl, 2);
+ if (ret)
+ return 0;
+ }
+
+ /* 10.2.1.5.2 step 4.1 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
+ while (len < buflen) {
+ int outlen = 0;
+ /* 10.2.1.5.2 step 4.2 */
+ ret = drbg_kcapi_sym(drbg, drbg->C, drbg->scratchpad, &data);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
+ /* 10.2.1.5.2 step 6 */
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.2.1.5.2 step 4.3 */
+ memcpy(buf + len, drbg->scratchpad, outlen);
+ len += outlen;
+ /* 10.2.1.5.2 step 6 */
+ if (len < buflen)
+ drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ }
+
+ /* 10.2.1.5.2 step 6 */
+ ret = drbg_ctr_update(drbg, NULL, 3);
+ if (ret)
+ len = ret;
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+static struct drbg_state_ops drbg_ctr_ops = {
+ .update = drbg_ctr_update,
+ .generate = drbg_ctr_generate,
+ .crypto_init = drbg_init_sym_kernel,
+ .crypto_fini = drbg_fini_sym_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/******************************************************************
+ * HMAC DRBG callback functions
+ ******************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct list_head *in);
+static int drbg_init_hash_kernel(struct drbg_state *drbg);
+static int drbg_fini_hash_kernel(struct drbg_state *drbg);
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+#define CRYPTO_DRBG_HMAC_STRING "HMAC "
+/* update function of HMAC DRBG as defined in 10.1.2.2 */
+static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
+ int reseed)
+{
+ int ret = -EFAULT;
+ int i = 0;
+ struct drbg_string seed1, seed2, vdata;
+ LIST_HEAD(seedlist);
+ LIST_HEAD(vdatalist);
+
+ if (!reseed) {
+ /* 10.1.2.3 step 2 */
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ memset(drbg->V, 1, drbg_statelen(drbg));
+ }
+
+ drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&seed1.list, &seedlist);
+ /* buffer of seed2 will be filled in for loop below with one byte */
+ drbg_string_fill(&seed2, NULL, 1);
+ list_add_tail(&seed2.list, &seedlist);
+ /* input data of seed is allowed to be NULL at this point */
+ if (seed)
+ list_splice_tail(seed, &seedlist);
+
+ drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&vdata.list, &vdatalist);
+ for (i = 2; 0 < i; i--) {
+ /* first round uses 0x0, second 0x1 */
+ unsigned char prefix = DRBG_PREFIX0;
+ if (1 == i)
+ prefix = DRBG_PREFIX1;
+ /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
+ seed2.buf = &prefix;
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 2 and 5 -- HMAC for V */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
+ if (ret)
+ return ret;
+
+ /* 10.1.2.2 step 3 */
+ if (!seed)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* generate function of HMAC DRBG as defined in 10.1.2.5 */
+static int drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct list_head *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ struct drbg_string data;
+ LIST_HEAD(datalist);
+
+ /* 10.1.2.5 step 2 */
+ if (addtl && !list_empty(addtl)) {
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ if (ret)
+ return ret;
+ }
+
+ drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data.list, &datalist);
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.2.5 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
+ if (ret)
+ return ret;
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, drbg->V))
+ continue;
+
+ /* 10.1.2.5 step 4.2 */
+ memcpy(buf + len, drbg->V, outlen);
+ len += outlen;
+ }
+
+ /* 10.1.2.5 step 6 */
+ if (addtl && !list_empty(addtl))
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ else
+ ret = drbg_hmac_update(drbg, NULL, 1);
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static struct drbg_state_ops drbg_hmac_ops = {
+ .update = drbg_hmac_update,
+ .generate = drbg_hmac_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+
+};
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+
+/******************************************************************
+ * Hash DRBG callback functions
+ ******************************************************************/
+
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+#define CRYPTO_DRBG_HASH_STRING "HASH "
+/*
+ * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
+ * interlinked, the scratchpad is used as follows:
+ * drbg_hash_update
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg)
+ * drbg_hash_df:
+ * start: drbg->scratchpad + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ *
+ * drbg_hash_process_addtl uses the scratchpad, but fully completes
+ * before either of the functions mentioned before are invoked. Therefore,
+ * drbg_hash_process_addtl does not need to be specifically considered.
+ */
+
+/* Derivation Function for Hash DRBG as defined in 10.4.1 */
+static int drbg_hash_df(struct drbg_state *drbg,
+ unsigned char *outval, size_t outlen,
+ struct list_head *entropylist)
+{
+ int ret = 0;
+ size_t len = 0;
+ unsigned char input[5];
+ unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+
+ memset(tmp, 0, drbg_blocklen(drbg));
+
+ /* 10.4.1 step 3 */
+ input[0] = 1;
+ drbg_int2byte(&input[1], (outlen * 8), 4);
+
+ /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
+ drbg_string_fill(&data, input, 5);
+ list_add(&data.list, entropylist);
+
+ /* 10.4.1 step 4 */
+ while (len < outlen) {
+ short blocklen = 0;
+ /* 10.4.1 step 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
+ if (ret)
+ goto out;
+ /* 10.4.1 step 4.2 */
+ input[0]++;
+ blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
+ drbg_blocklen(drbg) : (outlen - len);
+ memcpy(outval + len, tmp, blocklen);
+ len += blocklen;
+ }
+
+out:
+ memset(tmp, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
+static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
+ int reseed)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+ LIST_HEAD(datalist2);
+ unsigned char *V = drbg->scratchpad;
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ if (!seed)
+ return -EINVAL;
+
+ if (reseed) {
+ /* 10.1.1.3 step 1 */
+ memcpy(V, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data1, &prefix, 1);
+ list_add_tail(&data1.list, &datalist);
+ drbg_string_fill(&data2, V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist);
+ }
+ list_splice_tail(seed, &datalist);
+
+ /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.2 / 10.1.1.3 step 4 */
+ prefix = DRBG_PREFIX0;
+ drbg_string_fill(&data1, &prefix, 1);
+ list_add_tail(&data1.list, &datalist2);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist2);
+ /* 10.1.1.2 / 10.1.1.3 step 4 */
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ return ret;
+}
+
+/* processing of additional information string for Hash DRBG */
+static int drbg_hash_process_addtl(struct drbg_state *drbg,
+ struct list_head *addtl)
+{
+ int ret = 0;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+ unsigned char prefix = DRBG_PREFIX2;
+
+ /* this is value w as per documentation */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step 2 */
+ if (!addtl || list_empty(addtl))
+ return 0;
+
+ /* 10.1.1.4 step 2a */
+ drbg_string_fill(&data1, &prefix, 1);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data1.list, &datalist);
+ list_add_tail(&data2.list, &datalist);
+ list_splice_tail(addtl, &datalist);
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+ if (ret)
+ goto out;
+
+ /* 10.1.1.4 step 2b */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return ret;
+}
+
+/* Hashgen defined in 10.1.1.4 */
+static int drbg_hash_hashgen(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char *src = drbg->scratchpad;
+ unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
+ struct drbg_string data;
+ LIST_HEAD(datalist);
+ unsigned char prefix = DRBG_PREFIX1;
+
+ memset(src, 0, drbg_statelen(drbg));
+ memset(dst, 0, drbg_blocklen(drbg));
+
+ /* 10.1.1.4 step hashgen 2 */
+ memcpy(src, drbg->V, drbg_statelen(drbg));
+
+ drbg_string_fill(&data, src, drbg_statelen(drbg));
+ list_add_tail(&data.list, &datalist);
+ while (len < buflen) {
+ unsigned int outlen = 0;
+ /* 10.1.1.4 step hashgen 4.1 */
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+ outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
+ drbg_blocklen(drbg) : (buflen - len);
+ if (!drbg_fips_continuous_test(drbg, dst)) {
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ continue;
+ }
+ /* 10.1.1.4 step hashgen 4.2 */
+ memcpy(buf + len, dst, outlen);
+ len += outlen;
+ /* 10.1.1.4 hashgen step 4.3 */
+ if (len < buflen)
+ drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ }
+
+out:
+ memset(drbg->scratchpad, 0,
+ (drbg_statelen(drbg) + drbg_blocklen(drbg)));
+ return len;
+}
+
+/* generate function for Hash DRBG as defined in 10.1.1.4 */
+static int drbg_hash_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct list_head *addtl)
+{
+ int len = 0;
+ int ret = 0;
+ unsigned char req[8];
+ unsigned char prefix = DRBG_PREFIX3;
+ struct drbg_string data1, data2;
+ LIST_HEAD(datalist);
+
+ /* 10.1.1.4 step 2 */
+ ret = drbg_hash_process_addtl(drbg, addtl);
+ if (ret)
+ return ret;
+ /* 10.1.1.4 step 3 */
+ len = drbg_hash_hashgen(drbg, buf, buflen);
+
+ /* this is the value H as documented in 10.1.1.4 */
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ /* 10.1.1.4 step 4 */
+ drbg_string_fill(&data1, &prefix, 1);
+ list_add_tail(&data1.list, &datalist);
+ drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
+ list_add_tail(&data2.list, &datalist);
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+ if (ret) {
+ len = ret;
+ goto out;
+ }
+
+ /* 10.1.1.4 step 5 */
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->scratchpad, drbg_blocklen(drbg));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg),
+ drbg->C, drbg_statelen(drbg));
+ drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+
+out:
+ memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ return len;
+}
+
+/*
+ * scratchpad usage: as update and generate are used isolated, both
+ * can use the scratchpad
+ */
+static struct drbg_state_ops drbg_hash_ops = {
+ .update = drbg_hash_update,
+ .generate = drbg_hash_generate,
+ .crypto_init = drbg_init_hash_kernel,
+ .crypto_fini = drbg_fini_hash_kernel,
+};
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+
+/******************************************************************
+ * Functions common for DRBG implementations
+ ******************************************************************/
+
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+ bool reseed)
+{
+ int ret = 0;
+ unsigned char *entropy = NULL;
+ size_t entropylen = 0;
+ struct drbg_string data1;
+ LIST_HEAD(seedlist);
+
+ /* 9.1 / 9.2 / 9.3.1 step 3 */
+ if (pers && pers->len > (drbg_max_addtl(drbg))) {
+ pr_devel("DRBG: personalization string too long %zu\n",
+ pers->len);
+ return -EINVAL;
+ }
+
+ if (drbg->test_data && drbg->test_data->testentropy) {
+ drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
+ drbg->test_data->testentropy->len);
+ pr_devel("DRBG: using test entropy\n");
+ } else {
+ /*
+ * Gather entropy equal to the security strength of the DRBG.
+ * With a derivation function, a nonce is required in addition
+ * to the entropy. A nonce must be at least 1/2 of the security
+ * strength of the DRBG in size. Thus, entropy * nonce is 3/2
+ * of the strength. The consideration of a nonce is only
+ * applicable during initial seeding.
+ */
+ entropylen = drbg_sec_strength(drbg->core->flags);
+ if (!entropylen)
+ return -EFAULT;
+ if (!reseed)
+ entropylen = ((entropylen + 1) / 2) * 3;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
+ entropy = kzalloc(entropylen, GFP_KERNEL);
+ if (!entropy)
+ return -ENOMEM;
+ get_random_bytes(entropy, entropylen);
+ drbg_string_fill(&data1, entropy, entropylen);
+ }
+ list_add_tail(&data1.list, &seedlist);
+
+ /*
+ * concatenation of entropy with personalization str / addtl input)
+ * the variable pers is directly handed in by the caller, so check its
+ * contents whether it is appropriate
+ */
+ if (pers && pers->buf && 0 < pers->len) {
+ list_add_tail(&pers->list, &seedlist);
+ pr_devel("DRBG: using personalization string\n");
+ }
+
+ ret = drbg->d_ops->update(drbg, &seedlist, reseed);
+ if (ret)
+ goto out;
+
+ drbg->seeded = true;
+ /* 10.1.1.2 / 10.1.1.3 step 5 */
+ drbg->reseed_ctr = 1;
+
+out:
+ if (entropy)
+ kzfree(entropy);
+ return ret;
+}
+
+/* Free all substructures in a DRBG state without the DRBG state structure */
+static inline void drbg_dealloc_state(struct drbg_state *drbg)
+{
+ if (!drbg)
+ return;
+ if (drbg->V)
+ kzfree(drbg->V);
+ drbg->V = NULL;
+ if (drbg->C)
+ kzfree(drbg->C);
+ drbg->C = NULL;
+ if (drbg->scratchpad)
+ kzfree(drbg->scratchpad);
+ drbg->scratchpad = NULL;
+ drbg->reseed_ctr = 0;
+#ifdef CONFIG_CRYPTO_FIPS
+ if (drbg->prev)
+ kzfree(drbg->prev);
+ drbg->prev = NULL;
+ drbg->fips_primed = false;
+#endif
+}
+
+/*
+ * Allocate all sub-structures for a DRBG state.
+ * The DRBG state structure must already be allocated.
+ */
+static inline int drbg_alloc_state(struct drbg_state *drbg)
+{
+ int ret = -ENOMEM;
+ unsigned int sb_size = 0;
+
+ if (!drbg)
+ return -EINVAL;
+
+ drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->V)
+ goto err;
+ drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ if (!drbg->C)
+ goto err;
+#ifdef CONFIG_CRYPTO_FIPS
+ drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ if (!drbg->prev)
+ goto err;
+ drbg->fips_primed = false;
+#endif
+ /* scratchpad is only generated for CTR and Hash */
+ if (drbg->core->flags & DRBG_HMAC)
+ sb_size = 0;
+ else if (drbg->core->flags & DRBG_CTR)
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
+ drbg_statelen(drbg) + /* df_data */
+ drbg_blocklen(drbg) + /* pad */
+ drbg_blocklen(drbg) + /* iv */
+ drbg_statelen(drbg) + drbg_blocklen(drbg); /* temp */
+ else
+ sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
+
+ if (0 < sb_size) {
+ drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL);
+ if (!drbg->scratchpad)
+ goto err;
+ }
+ spin_lock_init(&drbg->drbg_lock);
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * Strategy to avoid holding long term locks: generate a shadow copy of DRBG
+ * and perform all operations on this shadow copy. After finishing, restore
+ * the updated state of the shadow copy into original drbg state. This way,
+ * only the read and write operations of the original drbg state must be
+ * locked
+ */
+static inline void drbg_copy_drbg(struct drbg_state *src,
+ struct drbg_state *dst)
+{
+ if (!src || !dst)
+ return;
+ memcpy(dst->V, src->V, drbg_statelen(src));
+ memcpy(dst->C, src->C, drbg_statelen(src));
+ dst->reseed_ctr = src->reseed_ctr;
+ dst->seeded = src->seeded;
+ dst->pr = src->pr;
+#ifdef CONFIG_CRYPTO_FIPS
+ dst->fips_primed = src->fips_primed;
+ memcpy(dst->prev, src->prev, drbg_blocklen(src));
+#endif
+ /*
+ * Not copied:
+ * scratchpad is initialized drbg_alloc_state;
+ * priv_data is initialized with call to crypto_init;
+ * d_ops and core are set outside, as these parameters are const;
+ * test_data is set outside to prevent it being copied back.
+ */
+}
+
+static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
+{
+ int ret = -ENOMEM;
+ struct drbg_state *tmp = NULL;
+
+ if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
+ pr_devel("DRBG: attempt to generate shadow copy for "
+ "uninitialized DRBG state rejected\n");
+ return -EINVAL;
+ }
+ /* HMAC does not have a scratchpad */
+ if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
+ return -EINVAL;
+
+ tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* read-only data as they are defined as const, no lock needed */
+ tmp->core = drbg->core;
+ tmp->d_ops = drbg->d_ops;
+
+ ret = drbg_alloc_state(tmp);
+ if (ret)
+ goto err;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(drbg, tmp);
+ /* only make a link to the test buffer, as we only read that data */
+ tmp->test_data = drbg->test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+ *shadow = tmp;
+ return 0;
+
+err:
+ if (tmp)
+ kzfree(tmp);
+ return ret;
+}
+
+static void drbg_restore_shadow(struct drbg_state *drbg,
+ struct drbg_state **shadow)
+{
+ struct drbg_state *tmp = *shadow;
+
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_copy_drbg(tmp, drbg);
+ spin_unlock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(tmp);
+ kzfree(tmp);
+ *shadow = NULL;
+}
+
+/*************************************************************************
+ * DRBG interface functions
+ *************************************************************************/
+
+/*
+ * DRBG generate function as required by SP800-90A - this function
+ * generates random numbers
+ *
+ * @drbg DRBG state handle
+ * @buf Buffer where to store the random numbers -- the buffer must already
+ * be pre-allocated by caller
+ * @buflen Length of output buffer - this value defines the number of random
+ * bytes pulled from DRBG
+ * @addtl Additional input that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ *
+ * return: generated number of bytes
+ */
+static int drbg_generate(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ struct drbg_state *shadow = NULL;
+ LIST_HEAD(addtllist);
+ struct drbg_string timestamp;
+ union {
+ cycles_t cycles;
+ unsigned char char_cycles[sizeof(cycles_t)];
+ } now;
+
+ if (0 == buflen || !buf) {
+ pr_devel("DRBG: no output buffer provided\n");
+ return -EINVAL;
+ }
+ if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ pr_devel("DRBG: wrong format of additional information\n");
+ return -EINVAL;
+ }
+
+ len = drbg_make_shadow(drbg, &shadow);
+ if (len) {
+ pr_devel("DRBG: shadow copy cannot be generated\n");
+ return len;
+ }
+
+ /* 9.3.1 step 2 */
+ len = -EINVAL;
+ if (buflen > (drbg_max_request_bytes(shadow))) {
+ pr_devel("DRBG: requested random numbers too large %u\n",
+ buflen);
+ goto err;
+ }
+
+ /* 9.3.1 step 3 is implicit with the chosen DRBG */
+
+ /* 9.3.1 step 4 */
+ if (addtl && addtl->len > (drbg_max_addtl(shadow))) {
+ pr_devel("DRBG: additional information string too long %zu\n",
+ addtl->len);
+ goto err;
+ }
+ /* 9.3.1 step 5 is implicit with the chosen DRBG */
+
+ /*
+ * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented
+ * here. The spec is a bit convoluted here, we make it simpler.
+ */
+ if ((drbg_max_requests(shadow)) < shadow->reseed_ctr)
+ shadow->seeded = false;
+
+ /* allocate cipher handle */
+ if (shadow->d_ops->crypto_init) {
+ len = shadow->d_ops->crypto_init(shadow);
+ if (len)
+ goto err;
+ }
+
+ if (shadow->pr || !shadow->seeded) {
+ pr_devel("DRBG: reseeding before generation (prediction "
+ "resistance: %s, state %s)\n",
+ drbg->pr ? "true" : "false",
+ drbg->seeded ? "seeded" : "unseeded");
+ /* 9.3.1 steps 7.1 through 7.3 */
+ len = drbg_seed(shadow, addtl, true);
+ if (len)
+ goto err;
+ /* 9.3.1 step 7.4 */
+ addtl = NULL;
+ }
+
+ /*
+ * Mix the time stamp into the DRBG state if the DRBG is not in
+ * test mode. If there are two callers invoking the DRBG at the same
+ * time, i.e. before the first caller merges its shadow state back,
+ * both callers would obtain the same random number stream without
+ * changing the state here.
+ */
+ if (!drbg->test_data) {
+ now.cycles = random_get_entropy();
+ drbg_string_fill(&timestamp, now.char_cycles, sizeof(cycles_t));
+ list_add_tail(&timestamp.list, &addtllist);
+ }
+ if (addtl && 0 < addtl->len)
+ list_add_tail(&addtl->list, &addtllist);
+ /* 9.3.1 step 8 and 10 */
+ len = shadow->d_ops->generate(shadow, buf, buflen, &addtllist);
+
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
+ shadow->reseed_ctr++;
+ if (0 >= len)
+ goto err;
+
+ /*
+ * Section 11.3.3 requires to re-perform self tests after some
+ * generated random numbers. The chosen value after which self
+ * test is performed is arbitrary, but it should be reasonable.
+ * However, we do not perform the self tests because of the following
+ * reasons: it is mathematically impossible that the initial self tests
+ * were successfully and the following are not. If the initial would
+ * pass and the following would not, the kernel integrity is violated.
+ * In this case, the entire kernel operation is questionable and it
+ * is unlikely that the integrity violation only affects the
+ * correct operation of the DRBG.
+ *
+ * Albeit the following code is commented out, it is provided in
+ * case somebody has a need to implement the test of 11.3.3.
+ */
+#if 0
+ if (shadow->reseed_ctr && !(shadow->reseed_ctr % 4096)) {
+ int err = 0;
+ pr_devel("DRBG: start to perform self test\n");
+ if (drbg->core->flags & DRBG_HMAC)
+ err = alg_test("drbg_pr_hmac_sha256",
+ "drbg_pr_hmac_sha256", 0, 0);
+ else if (drbg->core->flags & DRBG_CTR)
+ err = alg_test("drbg_pr_ctr_aes128",
+ "drbg_pr_ctr_aes128", 0, 0);
+ else
+ err = alg_test("drbg_pr_sha256",
+ "drbg_pr_sha256", 0, 0);
+ if (err) {
+ pr_err("DRBG: periodical self test failed\n");
+ /*
+ * uninstantiate implies that from now on, only errors
+ * are returned when reusing this DRBG cipher handle
+ */
+ drbg_uninstantiate(drbg);
+ drbg_dealloc_state(shadow);
+ kzfree(shadow);
+ return 0;
+ } else {
+ pr_devel("DRBG: self test successful\n");
+ }
+ }
+#endif
+
+err:
+ if (shadow->d_ops->crypto_fini)
+ shadow->d_ops->crypto_fini(shadow);
+ drbg_restore_shadow(drbg, &shadow);
+ return len;
+}
+
+/*
+ * Wrapper around drbg_generate which can pull arbitrary long strings
+ * from the DRBG without hitting the maximum request limitation.
+ *
+ * Parameters: see drbg_generate
+ * Return codes: see drbg_generate -- if one drbg_generate request fails,
+ * the entire drbg_generate_long request fails
+ */
+static int drbg_generate_long(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct drbg_string *addtl)
+{
+ int len = 0;
+ unsigned int slice = 0;
+ do {
+ int tmplen = 0;
+ unsigned int chunk = 0;
+ slice = ((buflen - len) / drbg_max_request_bytes(drbg));
+ chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ tmplen = drbg_generate(drbg, buf + len, chunk, addtl);
+ if (0 >= tmplen)
+ return tmplen;
+ len += tmplen;
+ } while (slice > 0 && (len < buflen));
+ return len;
+}
+
+/*
+ * DRBG instantiation function as required by SP800-90A - this function
+ * sets up the DRBG handle, performs the initial seeding and all sanity
+ * checks required by SP800-90A
+ *
+ * @drbg memory of state -- if NULL, new memory is allocated
+ * @pers Personalization string that is mixed into state, may be NULL -- note
+ * the entropy is pulled by the DRBG internally unconditionally
+ * as defined in SP800-90A. The additional input is mixed into
+ * the state in addition to the pulled entropy.
+ * @coreref reference to core
+ * @pr prediction resistance enabled
+ *
+ * return
+ * 0 on success
+ * error value otherwise
+ */
+static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
+ int coreref, bool pr)
+{
+ int ret = -ENOMEM;
+
+ pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
+ "%s\n", coreref, pr ? "enabled" : "disabled");
+ drbg->core = &drbg_cores[coreref];
+ drbg->pr = pr;
+ drbg->seeded = false;
+ switch (drbg->core->flags & DRBG_TYPE_MASK) {
+#ifdef CONFIG_CRYPTO_DRBG_HMAC
+ case DRBG_HMAC:
+ drbg->d_ops = &drbg_hmac_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HMAC */
+#ifdef CONFIG_CRYPTO_DRBG_HASH
+ case DRBG_HASH:
+ drbg->d_ops = &drbg_hash_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_HASH */
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ case DRBG_CTR:
+ drbg->d_ops = &drbg_ctr_ops;
+ break;
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* 9.1 step 1 is implicit with the selected DRBG type */
+
+ /*
+ * 9.1 step 2 is implicit as caller can select prediction resistance
+ * and the flag is copied into drbg->flags --
+ * all DRBG types support prediction resistance
+ */
+
+ /* 9.1 step 4 is implicit in drbg_sec_strength */
+
+ ret = drbg_alloc_state(drbg);
+ if (ret)
+ return ret;
+
+ ret = -EFAULT;
+ if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ goto err;
+ ret = drbg_seed(drbg, pers, false);
+ if (drbg->d_ops->crypto_fini)
+ drbg->d_ops->crypto_fini(drbg);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ drbg_dealloc_state(drbg);
+ return ret;
+}
+
+/*
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
+ *
+ * @drbg DRBG state handle
+ *
+ * return
+ * 0 on success
+ */
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ spin_unlock_bh(&drbg->drbg_lock);
+ return 0;
+}
+
+/*
+ * Helper function for setting the test data in the DRBG
+ *
+ * @drbg DRBG state handle
+ * @test_data test data to sets
+ */
+static inline void drbg_set_testdata(struct drbg_state *drbg,
+ struct drbg_test_data *test_data)
+{
+ if (!test_data || !test_data->testentropy)
+ return;
+ spin_lock_bh(&drbg->drbg_lock);
+ drbg->test_data = test_data;
+ spin_unlock_bh(&drbg->drbg_lock);
+}
+
+/***************************************************************
+ * Kernel crypto API cipher invocations requested by DRBG
+ ***************************************************************/
+
+#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
+struct sdesc {
+ struct shash_desc shash;
+ char ctx[];
+};
+
+static int drbg_init_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate digest TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
+ GFP_KERNEL);
+ if (!sdesc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+
+ sdesc->shash.tfm = tfm;
+ sdesc->shash.flags = 0;
+ drbg->priv_data = sdesc;
+ return 0;
+}
+
+static int drbg_fini_hash_kernel(struct drbg_state *drbg)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ if (sdesc) {
+ crypto_free_shash(sdesc->shash.tfm);
+ kzfree(sdesc);
+ }
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct list_head *in)
+{
+ struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+ struct drbg_string *input = NULL;
+
+ if (key)
+ crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_init(&sdesc->shash);
+ list_for_each_entry(input, in, list)
+ crypto_shash_update(&sdesc->shash, input->buf, input->len);
+ return crypto_shash_final(&sdesc->shash, outval);
+}
+#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+static int drbg_init_sym_kernel(struct drbg_state *drbg)
+{
+ int ret = 0;
+ struct crypto_blkcipher *tfm;
+
+ tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0);
+ if (IS_ERR(tfm)) {
+ pr_info("DRBG: could not allocate cipher TFM handle\n");
+ return PTR_ERR(tfm);
+ }
+ BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm));
+ drbg->priv_data = tfm;
+ return ret;
+}
+
+static int drbg_fini_sym_kernel(struct drbg_state *drbg)
+{
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+ if (tfm)
+ crypto_free_blkcipher(tfm);
+ drbg->priv_data = NULL;
+ return 0;
+}
+
+static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
+ unsigned char *outval, const struct drbg_string *in)
+{
+ int ret = 0;
+ struct scatterlist sg_in, sg_out;
+ struct blkcipher_desc desc;
+ struct crypto_blkcipher *tfm =
+ (struct crypto_blkcipher *)drbg->priv_data;
+
+ desc.tfm = tfm;
+ desc.flags = 0;
+ crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
+ /* there is only component in *in */
+ sg_init_one(&sg_in, in->buf, in->len);
+ sg_init_one(&sg_out, outval, drbg_blocklen(drbg));
+ ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len);
+
+ return ret;
+}
+#endif /* CONFIG_CRYPTO_DRBG_CTR */
+
+/***************************************************************
+ * Kernel crypto API interface to register DRBG
+ ***************************************************************/
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the drbg_cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ * the applicable core
+ * @pr reference for setting prediction resistance
+ *
+ * return: flags
+ */
+static inline void drbg_convert_tfm_core(const char *cra_driver_name,
+ int *coreref, bool *pr)
+{
+ int i = 0;
+ size_t start = 0;
+ int len = 0;
+
+ *pr = true;
+ /* disassemble the names */
+ if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
+ start = 10;
+ *pr = false;
+ } else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
+ start = 8;
+ } else {
+ return;
+ }
+
+ /* remove the first part */
+ len = strlen(cra_driver_name) - start;
+ for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
+ if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
+ len)) {
+ *coreref = i;
+ return;
+ }
+ }
+}
+
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ bool pr = false;
+ int coreref = 0;
+
+ drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm), &coreref, &pr);
+ /*
+ * when personalization string is needed, the caller must call reset
+ * and provide the personalization string as seed information
+ */
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+}
+
+static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+{
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
+}
+
+/*
+ * Generate random numbers invoked by the kernel crypto API:
+ * The API of the kernel crypto API is extended as follows:
+ *
+ * If dlen is larger than zero, rdata is interpreted as the output buffer
+ * where random data is to be stored.
+ *
+ * If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
+ * which holds the additional information string that is used for the
+ * DRBG generation process. The output buffer that is to be used to store
+ * data is also pointed to by struct drbg_gen.
+ */
+static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
+ unsigned int dlen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ if (0 < dlen) {
+ return drbg_generate_long(drbg, rdata, dlen, NULL);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)rdata;
+ struct drbg_string addtl;
+ /* catch NULL pointer */
+ if (!data)
+ return 0;
+ drbg_set_testdata(drbg, data->test_data);
+ /* linked list variable is now local to allow modification */
+ drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len);
+ return drbg_generate_long(drbg, data->outbuf, data->outlen,
+ &addtl);
+ }
+}
+
+/*
+ * Reset the DRBG invoked by the kernel crypto API
+ * The reset implies a full re-initialization of the DRBG. Similar to the
+ * generate function of drbg_kcapi_random, this function extends the
+ * kernel crypto API interface with struct drbg_gen
+ */
+static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
+{
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+ bool pr = false;
+ struct drbg_string seed_string;
+ int coreref = 0;
+
+ drbg_uninstantiate(drbg);
+ drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
+ &pr);
+ if (0 < slen) {
+ drbg_string_fill(&seed_string, seed, slen);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ } else {
+ struct drbg_gen *data = (struct drbg_gen *)seed;
+ /* allow invocation of API call with NULL, 0 */
+ if (!data)
+ return drbg_instantiate(drbg, NULL, coreref, pr);
+ drbg_set_testdata(drbg, data->test_data);
+ /* linked list variable is now local to allow modification */
+ drbg_string_fill(&seed_string, data->addtl->buf,
+ data->addtl->len);
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
+ }
+}
+
+/***************************************************************
+ * Kernel module: code to load the module
+ ***************************************************************/
+
+/*
+ * Tests as defined in 11.3.2 in addition to the cipher tests: testing
+ * of the error handling.
+ *
+ * Note: testing of failing seed source as defined in 11.3.2 is not applicable
+ * as seed source of get_random_bytes does not fail.
+ *
+ * Note 2: There is no sensible way of testing the reseed counter
+ * enforcement, so skip it.
+ */
+static inline int __init drbg_healthcheck_sanity(void)
+{
+#ifdef CONFIG_CRYPTO_FIPS
+ int len = 0;
+#define OUTBUFLEN 16
+ unsigned char buf[OUTBUFLEN];
+ struct drbg_state *drbg = NULL;
+ int ret = -EFAULT;
+ int rc = -EFAULT;
+ bool pr = false;
+ int coreref = 0;
+ struct drbg_string addtl;
+ size_t max_addtllen, max_request_bytes;
+
+ /* only perform test in FIPS mode */
+ if (!fips_enabled)
+ return 0;
+
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+ drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+ drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
+#else
+ drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref, &pr);
+#endif
+
+ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
+ if (!drbg)
+ return -ENOMEM;
+
+ /*
+ * if the following tests fail, it is likely that there is a buffer
+ * overflow as buf is much smaller than the requested or provided
+ * string lengths -- in case the error handling does not succeed
+ * we may get an OOPS. And we want to get an OOPS as this is a
+ * grave bug.
+ */
+
+ /* get a valid instance of DRBG for following tests */
+ ret = drbg_instantiate(drbg, NULL, coreref, pr);
+ if (ret) {
+ rc = ret;
+ goto outbuf;
+ }
+ max_addtllen = drbg_max_addtl(drbg);
+ max_request_bytes = drbg_max_request_bytes(drbg);
+ drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ /* overflow addtllen with additonal info string */
+ len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ BUG_ON(0 < len);
+ /* overflow max_bits */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ drbg_uninstantiate(drbg);
+
+ /* overflow max addtllen with personalization string */
+ ret = drbg_instantiate(drbg, &addtl, coreref, pr);
+ BUG_ON(0 == ret);
+ /* test uninstantated DRBG */
+ len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
+ BUG_ON(0 < len);
+ /* all tests passed */
+ rc = 0;
+
+ pr_devel("DRBG: Sanity tests for failure code paths successfully "
+ "completed\n");
+
+ drbg_uninstantiate(drbg);
+outbuf:
+ kzfree(drbg);
+ return rc;
+#else /* CONFIG_CRYPTO_FIPS */
+ return 0;
+#endif /* CONFIG_CRYPTO_FIPS */
+}
+
+static struct crypto_alg drbg_algs[22];
+
+/*
+ * Fill the array drbg_algs used to register the different DRBGs
+ * with the kernel crypto API. To fill the array, the information
+ * from drbg_cores[] is used.
+ */
+static inline void __init drbg_fill_array(struct crypto_alg *alg,
+ const struct drbg_core *core, int pr)
+{
+ int pos = 0;
+ static int priority = 100;
+
+ memset(alg, 0, sizeof(struct crypto_alg));
+ memcpy(alg->cra_name, "stdrng", 6);
+ if (pr) {
+ memcpy(alg->cra_driver_name, "drbg_pr_", 8);
+ pos = 8;
+ } else {
+ memcpy(alg->cra_driver_name, "drbg_nopr_", 10);
+ pos = 10;
+ }
+ memcpy(alg->cra_driver_name + pos, core->cra_name,
+ strlen(core->cra_name));
+
+ alg->cra_priority = priority;
+ priority++;
+ /*
+ * If FIPS mode enabled, the selected DRBG shall have the
+ * highest cra_priority over other stdrng instances to ensure
+ * it is selected.
+ */
+ if (fips_enabled)
+ alg->cra_priority += 200;
+
+ alg->cra_flags = CRYPTO_ALG_TYPE_RNG;
+ alg->cra_ctxsize = sizeof(struct drbg_state);
+ alg->cra_type = &crypto_rng_type;
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = drbg_kcapi_init;
+ alg->cra_exit = drbg_kcapi_cleanup;
+ alg->cra_u.rng.rng_make_random = drbg_kcapi_random;
+ alg->cra_u.rng.rng_reset = drbg_kcapi_reset;
+ alg->cra_u.rng.seedsize = 0;
+}
+
+static int __init drbg_init(void)
+{
+ unsigned int i = 0; /* pointer to drbg_algs */
+ unsigned int j = 0; /* pointer to drbg_cores */
+ int ret = -EFAULT;
+
+ ret = drbg_healthcheck_sanity();
+ if (ret)
+ return ret;
+
+ if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
+ pr_info("DRBG: Cannot register all DRBG types"
+ "(slots needed: %zu, slots available: %zu)\n",
+ ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
+ return ret;
+ }
+
+ /*
+ * each DRBG definition can be used with PR and without PR, thus
+ * we instantiate each DRBG in drbg_cores[] twice.
+ *
+ * As the order of placing them into the drbg_algs array matters
+ * (the later DRBGs receive a higher cra_priority) we register the
+ * prediction resistance DRBGs first as the should not be too
+ * interesting.
+ */
+ for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+ drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
+ for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
+ drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
+ return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+static void __exit drbg_exit(void)
+{
+ crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+}
+
+module_init(drbg_init);
+module_exit(drbg_exit);
+#ifndef CRYPTO_DRBG_HASH_STRING
+#define CRYPTO_DRBG_HASH_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_HMAC_STRING
+#define CRYPTO_DRBG_HMAC_STRING ""
+#endif
+#ifndef CRYPTO_DRBG_CTR_STRING
+#define CRYPTO_DRBG_CTR_STRING ""
+#endif
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
+ "using following cores: "
+ CRYPTO_DRBG_HASH_STRING
+ CRYPTO_DRBG_HMAC_STRING
+ CRYPTO_DRBG_CTR_STRING);
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index 42ce9f570aec..bf7ab4a89493 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -68,7 +68,7 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
struct ablkcipher_request *subreq;
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
struct scatterlist *osrc, *odst;
struct scatterlist *dst;
@@ -86,7 +86,7 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
giv = req->giv;
- complete = req->creq.base.complete;
+ compl = req->creq.base.complete;
data = req->creq.base.data;
osrc = req->creq.src;
@@ -101,11 +101,11 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
if (vsrc != giv + ivsize && vdst != giv + ivsize) {
giv = PTR_ALIGN((u8 *)reqctx->tail,
crypto_ablkcipher_alignmask(geniv) + 1);
- complete = eseqiv_complete;
+ compl = eseqiv_complete;
data = req;
}
- ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
data);
sg_init_table(reqctx->src, 2);
diff --git a/crypto/gcm.c b/crypto/gcm.c
index b4f017939004..276cdac567b6 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -228,14 +228,14 @@ static void gcm_hash_final_done(struct crypto_async_request *areq, int err);
static int gcm_hash_update(struct aead_request *req,
struct crypto_gcm_req_priv_ctx *pctx,
- crypto_completion_t complete,
+ crypto_completion_t compl,
struct scatterlist *src,
unsigned int len)
{
struct ahash_request *ahreq = &pctx->u.ahreq;
ahash_request_set_callback(ahreq, aead_request_flags(req),
- complete, req);
+ compl, req);
ahash_request_set_crypt(ahreq, src, NULL, len);
return crypto_ahash_update(ahreq);
@@ -244,12 +244,12 @@ static int gcm_hash_update(struct aead_request *req,
static int gcm_hash_remain(struct aead_request *req,
struct crypto_gcm_req_priv_ctx *pctx,
unsigned int remain,
- crypto_completion_t complete)
+ crypto_completion_t compl)
{
struct ahash_request *ahreq = &pctx->u.ahreq;
ahash_request_set_callback(ahreq, aead_request_flags(req),
- complete, req);
+ compl, req);
sg_init_one(pctx->src, gcm_zeroes, remain);
ahash_request_set_crypt(ahreq, pctx->src, NULL, remain);
@@ -375,14 +375,14 @@ static void __gcm_hash_assoc_remain_done(struct aead_request *req, int err)
{
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
- crypto_completion_t complete;
+ crypto_completion_t compl;
unsigned int remain = 0;
if (!err && gctx->cryptlen) {
remain = gcm_remain(gctx->cryptlen);
- complete = remain ? gcm_hash_crypt_done :
+ compl = remain ? gcm_hash_crypt_done :
gcm_hash_crypt_remain_done;
- err = gcm_hash_update(req, pctx, complete,
+ err = gcm_hash_update(req, pctx, compl,
gctx->src, gctx->cryptlen);
if (err == -EINPROGRESS || err == -EBUSY)
return;
@@ -429,14 +429,14 @@ static void gcm_hash_assoc_done(struct crypto_async_request *areq, int err)
static void __gcm_hash_init_done(struct aead_request *req, int err)
{
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
unsigned int remain = 0;
if (!err && req->assoclen) {
remain = gcm_remain(req->assoclen);
- complete = remain ? gcm_hash_assoc_done :
+ compl = remain ? gcm_hash_assoc_done :
gcm_hash_assoc_remain_done;
- err = gcm_hash_update(req, pctx, complete,
+ err = gcm_hash_update(req, pctx, compl,
req->assoc, req->assoclen);
if (err == -EINPROGRESS || err == -EBUSY)
return;
@@ -462,7 +462,7 @@ static int gcm_hash(struct aead_request *req,
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
unsigned int remain;
- crypto_completion_t complete;
+ crypto_completion_t compl;
int err;
ahash_request_set_tfm(ahreq, ctx->ghash);
@@ -473,8 +473,8 @@ static int gcm_hash(struct aead_request *req,
if (err)
return err;
remain = gcm_remain(req->assoclen);
- complete = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
- err = gcm_hash_update(req, pctx, complete, req->assoc, req->assoclen);
+ compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
+ err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen);
if (err)
return err;
if (remain) {
@@ -484,8 +484,8 @@ static int gcm_hash(struct aead_request *req,
return err;
}
remain = gcm_remain(gctx->cryptlen);
- complete = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
- err = gcm_hash_update(req, pctx, complete, gctx->src, gctx->cryptlen);
+ compl = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
+ err = gcm_hash_update(req, pctx, compl, gctx->src, gctx->cryptlen);
if (err)
return err;
if (remain) {
diff --git a/crypto/lzo.c b/crypto/lzo.c
index 1c2aa69c54b8..a8ff2f778dc4 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include <linux/lzo.h>
struct lzo_ctx {
@@ -30,7 +31,10 @@ static int lzo_init(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
+ ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
+ GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+ if (!ctx->lzo_comp_mem)
+ ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
if (!ctx->lzo_comp_mem)
return -ENOMEM;
@@ -41,7 +45,7 @@ static void lzo_exit(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- vfree(ctx->lzo_comp_mem);
+ kvfree(ctx->lzo_comp_mem);
}
static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index f2cba4ed6f25..ee190fcedcd2 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -100,7 +100,7 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
u8 *info;
unsigned int ivsize;
@@ -108,7 +108,7 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
- complete = req->creq.base.complete;
+ compl = req->creq.base.complete;
data = req->creq.base.data;
info = req->creq.info;
@@ -122,11 +122,11 @@ static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
if (!info)
return -ENOMEM;
- complete = seqiv_complete;
+ compl = seqiv_complete;
data = req;
}
- ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
+ ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
data);
ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
req->creq.nbytes, info);
@@ -146,7 +146,7 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
struct aead_request *areq = &req->areq;
struct aead_request *subreq = aead_givcrypt_reqctx(req);
- crypto_completion_t complete;
+ crypto_completion_t compl;
void *data;
u8 *info;
unsigned int ivsize;
@@ -154,7 +154,7 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
aead_request_set_tfm(subreq, aead_geniv_base(geniv));
- complete = areq->base.complete;
+ compl = areq->base.complete;
data = areq->base.data;
info = areq->iv;
@@ -168,11 +168,11 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
if (!info)
return -ENOMEM;
- complete = seqiv_aead_complete;
+ compl = seqiv_aead_complete;
data = req;
}
- aead_request_set_callback(subreq, areq->base.flags, complete, data);
+ aead_request_set_callback(subreq, areq->base.flags, compl, data);
aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
info);
aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index ba247cf30858..890449e6e7ef 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -48,6 +48,11 @@
#define DECRYPT 0
/*
+ * return a string with the driver name
+ */
+#define get_driver_name(tfm_type, tfm) crypto_tfm_alg_driver_name(tfm_type ## _tfm(tfm))
+
+/*
* Used by test_cipher_speed()
*/
static unsigned int sec;
@@ -68,13 +73,13 @@ static char *check[] = {
};
static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
- struct scatterlist *sg, int blen, int sec)
+ struct scatterlist *sg, int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = crypto_blkcipher_encrypt(desc, sg, sg, blen);
@@ -86,7 +91,7 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
}
printk("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -138,13 +143,13 @@ out:
}
static int test_aead_jiffies(struct aead_request *req, int enc,
- int blen, int sec)
+ int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = crypto_aead_encrypt(req);
@@ -156,7 +161,7 @@ static int test_aead_jiffies(struct aead_request *req, int enc,
}
printk("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -260,7 +265,7 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE],
}
}
-static void test_aead_speed(const char *algo, int enc, unsigned int sec,
+static void test_aead_speed(const char *algo, int enc, unsigned int secs,
struct aead_speed_template *template,
unsigned int tcount, u8 authsize,
unsigned int aad_size, u8 *keysize)
@@ -305,9 +310,6 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
asg = &sg[8];
sgout = &asg[8];
-
- printk(KERN_INFO "\ntesting speed of %s %s\n", algo, e);
-
tfm = crypto_alloc_aead(algo, 0, 0);
if (IS_ERR(tfm)) {
@@ -316,6 +318,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
goto out_notfm;
}
+ printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+ get_driver_name(crypto_aead, tfm), e);
+
req = aead_request_alloc(tfm, GFP_KERNEL);
if (!req) {
pr_err("alg: aead: Failed to allocate request for %s\n",
@@ -374,8 +379,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int sec,
aead_request_set_crypt(req, sg, sgout, *b_size, iv);
aead_request_set_assoc(req, asg, aad_size);
- if (sec)
- ret = test_aead_jiffies(req, enc, *b_size, sec);
+ if (secs)
+ ret = test_aead_jiffies(req, enc, *b_size,
+ secs);
else
ret = test_aead_cycles(req, enc, *b_size);
@@ -405,7 +411,7 @@ out_noxbuf:
return;
}
-static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_cipher_speed(const char *algo, int enc, unsigned int secs,
struct cipher_speed_template *template,
unsigned int tcount, u8 *keysize)
{
@@ -422,8 +428,6 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
else
e = "decryption";
- printk("\ntesting speed of %s %s\n", algo, e);
-
tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
@@ -434,6 +438,9 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
desc.tfm = tfm;
desc.flags = 0;
+ printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
+ get_driver_name(crypto_blkcipher, tfm), e);
+
i = 0;
do {
@@ -483,9 +490,9 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
crypto_blkcipher_set_iv(tfm, iv, iv_len);
}
- if (sec)
+ if (secs)
ret = test_cipher_jiffies(&desc, enc, sg,
- *b_size, sec);
+ *b_size, secs);
else
ret = test_cipher_cycles(&desc, enc, sg,
*b_size);
@@ -506,13 +513,13 @@ out:
static int test_hash_jiffies_digest(struct hash_desc *desc,
struct scatterlist *sg, int blen,
- char *out, int sec)
+ char *out, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_hash_digest(desc, sg, blen, out);
if (ret)
@@ -520,22 +527,22 @@ static int test_hash_jiffies_digest(struct hash_desc *desc,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
- int blen, int plen, char *out, int sec)
+ int blen, int plen, char *out, int secs)
{
unsigned long start, end;
int bcount, pcount;
int ret;
if (plen == blen)
- return test_hash_jiffies_digest(desc, sg, blen, out, sec);
+ return test_hash_jiffies_digest(desc, sg, blen, out, secs);
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_hash_init(desc);
if (ret)
@@ -552,7 +559,7 @@ static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
@@ -673,7 +680,7 @@ static void test_hash_sg_init(struct scatterlist *sg)
}
}
-static void test_hash_speed(const char *algo, unsigned int sec,
+static void test_hash_speed(const char *algo, unsigned int secs,
struct hash_speed *speed)
{
struct scatterlist sg[TVMEMSIZE];
@@ -683,8 +690,6 @@ static void test_hash_speed(const char *algo, unsigned int sec,
int i;
int ret;
- printk(KERN_INFO "\ntesting speed of %s\n", algo);
-
tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
@@ -693,6 +698,9 @@ static void test_hash_speed(const char *algo, unsigned int sec,
return;
}
+ printk(KERN_INFO "\ntesting speed of %s (%s)\n", algo,
+ get_driver_name(crypto_hash, tfm));
+
desc.tfm = tfm;
desc.flags = 0;
@@ -718,9 +726,9 @@ static void test_hash_speed(const char *algo, unsigned int sec,
"(%5u byte blocks,%5u bytes per update,%4u updates): ",
i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
- if (sec)
+ if (secs)
ret = test_hash_jiffies(&desc, sg, speed[i].blen,
- speed[i].plen, output, sec);
+ speed[i].plen, output, secs);
else
ret = test_hash_cycles(&desc, sg, speed[i].blen,
speed[i].plen, output);
@@ -765,13 +773,13 @@ static inline int do_one_ahash_op(struct ahash_request *req, int ret)
}
static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
- char *out, int sec)
+ char *out, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = do_one_ahash_op(req, crypto_ahash_digest(req));
if (ret)
@@ -779,22 +787,22 @@ static int test_ahash_jiffies_digest(struct ahash_request *req, int blen,
}
printk("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
static int test_ahash_jiffies(struct ahash_request *req, int blen,
- int plen, char *out, int sec)
+ int plen, char *out, int secs)
{
unsigned long start, end;
int bcount, pcount;
int ret;
if (plen == blen)
- return test_ahash_jiffies_digest(req, blen, out, sec);
+ return test_ahash_jiffies_digest(req, blen, out, secs);
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
ret = crypto_ahash_init(req);
if (ret)
@@ -811,7 +819,7 @@ static int test_ahash_jiffies(struct ahash_request *req, int blen,
}
pr_cont("%6u opers/sec, %9lu bytes/sec\n",
- bcount / sec, ((long)bcount * blen) / sec);
+ bcount / secs, ((long)bcount * blen) / secs);
return 0;
}
@@ -911,7 +919,7 @@ out:
return 0;
}
-static void test_ahash_speed(const char *algo, unsigned int sec,
+static void test_ahash_speed(const char *algo, unsigned int secs,
struct hash_speed *speed)
{
struct scatterlist sg[TVMEMSIZE];
@@ -921,8 +929,6 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
static char output[1024];
int i, ret;
- printk(KERN_INFO "\ntesting speed of async %s\n", algo);
-
tfm = crypto_alloc_ahash(algo, 0, 0);
if (IS_ERR(tfm)) {
pr_err("failed to load transform for %s: %ld\n",
@@ -930,6 +936,9 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
return;
}
+ printk(KERN_INFO "\ntesting speed of async %s (%s)\n", algo,
+ get_driver_name(crypto_ahash, tfm));
+
if (crypto_ahash_digestsize(tfm) > sizeof(output)) {
pr_err("digestsize(%u) > outputbuffer(%zu)\n",
crypto_ahash_digestsize(tfm), sizeof(output));
@@ -960,9 +969,9 @@ static void test_ahash_speed(const char *algo, unsigned int sec,
ahash_request_set_crypt(req, sg, output, speed[i].plen);
- if (sec)
+ if (secs)
ret = test_ahash_jiffies(req, speed[i].blen,
- speed[i].plen, output, sec);
+ speed[i].plen, output, secs);
else
ret = test_ahash_cycles(req, speed[i].blen,
speed[i].plen, output);
@@ -994,13 +1003,13 @@ static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
}
static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
- int blen, int sec)
+ int blen, int secs)
{
unsigned long start, end;
int bcount;
int ret;
- for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ for (start = jiffies, end = start + secs * HZ, bcount = 0;
time_before(jiffies, end); bcount++) {
if (enc)
ret = do_one_acipher_op(req,
@@ -1014,7 +1023,7 @@ static int test_acipher_jiffies(struct ablkcipher_request *req, int enc,
}
pr_cont("%d operations in %d seconds (%ld bytes)\n",
- bcount, sec, (long)bcount * blen);
+ bcount, secs, (long)bcount * blen);
return 0;
}
@@ -1065,7 +1074,7 @@ out:
return ret;
}
-static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
+static void test_acipher_speed(const char *algo, int enc, unsigned int secs,
struct cipher_speed_template *template,
unsigned int tcount, u8 *keysize)
{
@@ -1083,8 +1092,6 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
else
e = "decryption";
- pr_info("\ntesting speed of async %s %s\n", algo, e);
-
init_completion(&tresult.completion);
tfm = crypto_alloc_ablkcipher(algo, 0, 0);
@@ -1095,6 +1102,9 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
return;
}
+ pr_info("\ntesting speed of async %s (%s) %s\n", algo,
+ get_driver_name(crypto_ablkcipher, tfm), e);
+
req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) {
pr_err("tcrypt: skcipher: Failed to allocate request for %s\n",
@@ -1168,9 +1178,9 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int sec,
ablkcipher_request_set_crypt(req, sg, sg, *b_size, iv);
- if (sec)
+ if (secs)
ret = test_acipher_jiffies(req, enc,
- *b_size, sec);
+ *b_size, secs);
else
ret = test_acipher_cycles(req, enc,
*b_size);
@@ -1585,6 +1595,12 @@ static int do_test(int m)
test_cipher_speed("cbc(des3_ede)", DECRYPT, sec,
des3_speed_template, DES3_SPEED_VECTORS,
speed_template_24);
+ test_cipher_speed("ctr(des3_ede)", ENCRYPT, sec,
+ des3_speed_template, DES3_SPEED_VECTORS,
+ speed_template_24);
+ test_cipher_speed("ctr(des3_ede)", DECRYPT, sec,
+ des3_speed_template, DES3_SPEED_VECTORS,
+ speed_template_24);
break;
case 202:
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 498649ac1953..ac2b63105afc 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/rng.h>
+#include <crypto/drbg.h>
#include "internal.h"
@@ -108,6 +109,11 @@ struct cprng_test_suite {
unsigned int count;
};
+struct drbg_test_suite {
+ struct drbg_testvec *vecs;
+ unsigned int count;
+};
+
struct alg_test_desc {
const char *alg;
int (*test)(const struct alg_test_desc *desc, const char *driver,
@@ -121,6 +127,7 @@ struct alg_test_desc {
struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
struct cprng_test_suite cprng;
+ struct drbg_test_suite drbg;
} suite;
};
@@ -191,13 +198,20 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
const char *algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm));
unsigned int i, j, k, temp;
struct scatterlist sg[8];
- char result[64];
+ char *result;
+ char *key;
struct ahash_request *req;
struct tcrypt_result tresult;
void *hash_buff;
char *xbuf[XBUFSIZE];
int ret = -ENOMEM;
+ result = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
+ if (!result)
+ return ret;
+ key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+ if (!key)
+ goto out_nobuf;
if (testmgr_alloc_buf(xbuf))
goto out_nobuf;
@@ -222,7 +236,7 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
goto out;
j++;
- memset(result, 0, 64);
+ memset(result, 0, MAX_DIGEST_SIZE);
hash_buff = xbuf[0];
hash_buff += align_offset;
@@ -232,8 +246,14 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (template[i].ksize) {
crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
- template[i].ksize);
+ if (template[i].ksize > MAX_KEYLEN) {
+ pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+ j, algo, template[i].ksize, MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].ksize);
+ ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
if (ret) {
printk(KERN_ERR "alg: hash: setkey failed on "
"test %d for %s: ret=%d\n", j, algo,
@@ -293,7 +313,7 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (template[i].np) {
j++;
- memset(result, 0, 64);
+ memset(result, 0, MAX_DIGEST_SIZE);
temp = 0;
sg_init_table(sg, template[i].np);
@@ -312,8 +332,16 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
}
if (template[i].ksize) {
+ if (template[i].ksize > MAX_KEYLEN) {
+ pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+ j, algo, template[i].ksize,
+ MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
crypto_ahash_clear_flags(tfm, ~0);
- ret = crypto_ahash_setkey(tfm, template[i].key,
+ memcpy(key, template[i].key, template[i].ksize);
+ ret = crypto_ahash_setkey(tfm, key,
template[i].ksize);
if (ret) {
@@ -365,6 +393,8 @@ out:
out_noreq:
testmgr_free_buf(xbuf);
out_nobuf:
+ kfree(key);
+ kfree(result);
return ret;
}
@@ -422,6 +452,9 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
iv = kzalloc(MAX_IVLEN, GFP_KERNEL);
if (!iv)
return ret;
+ key = kmalloc(MAX_KEYLEN, GFP_KERNEL);
+ if (!key)
+ goto out_noxbuf;
if (testmgr_alloc_buf(xbuf))
goto out_noxbuf;
if (testmgr_alloc_buf(axbuf))
@@ -486,7 +519,14 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
crypto_aead_set_flags(
tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = template[i].key;
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen,
+ MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
ret = crypto_aead_setkey(tfm, key,
template[i].klen);
@@ -587,7 +627,14 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
if (template[i].wk)
crypto_aead_set_flags(
tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- key = template[i].key;
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen,
+ MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
ret = crypto_aead_setkey(tfm, key, template[i].klen);
if (!ret == template[i].fail) {
@@ -769,6 +816,7 @@ out_nooutbuf:
out_noaxbuf:
testmgr_free_buf(xbuf);
out_noxbuf:
+ kfree(key);
kfree(iv);
return ret;
}
@@ -1715,6 +1763,100 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
return err;
}
+
+static int drbg_cavs_test(struct drbg_testvec *test, int pr,
+ const char *driver, u32 type, u32 mask)
+{
+ int ret = -EAGAIN;
+ struct crypto_rng *drng;
+ struct drbg_test_data test_data;
+ struct drbg_string addtl, pers, testentropy;
+ unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ drng = crypto_alloc_rng(driver, type, mask);
+ if (IS_ERR(drng)) {
+ printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
+ "%s\n", driver);
+ kzfree(buf);
+ return -ENOMEM;
+ }
+
+ test_data.testentropy = &testentropy;
+ drbg_string_fill(&testentropy, test->entropy, test->entropylen);
+ drbg_string_fill(&pers, test->pers, test->perslen);
+ ret = crypto_drbg_reset_test(drng, &pers, &test_data);
+ if (ret) {
+ printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
+ goto outbuf;
+ }
+
+ drbg_string_fill(&addtl, test->addtla, test->addtllen);
+ if (pr) {
+ drbg_string_fill(&testentropy, test->entpra, test->entprlen);
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen, &addtl, &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen, &addtl);
+ }
+ if (ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data for "
+ "driver %s\n", driver);
+ goto outbuf;
+ }
+
+ drbg_string_fill(&addtl, test->addtlb, test->addtllen);
+ if (pr) {
+ drbg_string_fill(&testentropy, test->entprb, test->entprlen);
+ ret = crypto_drbg_get_bytes_addtl_test(drng,
+ buf, test->expectedlen, &addtl, &test_data);
+ } else {
+ ret = crypto_drbg_get_bytes_addtl(drng,
+ buf, test->expectedlen, &addtl);
+ }
+ if (ret <= 0) {
+ printk(KERN_ERR "alg: drbg: could not obtain random data for "
+ "driver %s\n", driver);
+ goto outbuf;
+ }
+
+ ret = memcmp(test->expected, buf, test->expectedlen);
+
+outbuf:
+ crypto_free_rng(drng);
+ kzfree(buf);
+ return ret;
+}
+
+
+static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ int err = 0;
+ int pr = 0;
+ int i = 0;
+ struct drbg_testvec *template = desc->suite.drbg.vecs;
+ unsigned int tcount = desc->suite.drbg.count;
+
+ if (0 == memcmp(driver, "drbg_pr_", 8))
+ pr = 1;
+
+ for (i = 0; i < tcount; i++) {
+ err = drbg_cavs_test(&template[i], pr, driver, type, mask);
+ if (err) {
+ printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
+ i, driver);
+ err = -EINVAL;
+ break;
+ }
+ }
+ return err;
+
+}
+
static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
{
@@ -2458,6 +2600,152 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "digest_null",
.test = alg_test_null,
}, {
+ .alg = "drbg_nopr_ctr_aes128",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg_nopr_ctr_aes192",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes192_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes192_tv_template)
+ }
+ }
+ }, {
+ .alg = "drbg_nopr_ctr_aes256",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_ctr_aes256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_ctr_aes256_tv_template)
+ }
+ }
+ }, {
+ /*
+ * There is no need to specifically test the DRBG with every
+ * backend cipher -- covered by drbg_nopr_hmac_sha256 test
+ */
+ .alg = "drbg_nopr_hmac_sha1",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_nopr_hmac_sha256",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_hmac_sha256_tv_template,
+ .count =
+ ARRAY_SIZE(drbg_nopr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* covered by drbg_nopr_hmac_sha256 test */
+ .alg = "drbg_nopr_hmac_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_nopr_hmac_sha512",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "drbg_nopr_sha1",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_nopr_sha256",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_nopr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_nopr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* covered by drbg_nopr_sha256 test */
+ .alg = "drbg_nopr_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_nopr_sha512",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_ctr_aes128",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_ctr_aes128_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_ctr_aes128_tv_template)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_ctr_aes128 test */
+ .alg = "drbg_pr_ctr_aes192",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_ctr_aes256",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_hmac_sha1",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_hmac_sha256",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_hmac_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_hmac_sha256_tv_template)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_hmac_sha256 test */
+ .alg = "drbg_pr_hmac_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_hmac_sha512",
+ .test = alg_test_null,
+ .fips_allowed = 1,
+ }, {
+ .alg = "drbg_pr_sha1",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_sha256",
+ .test = alg_test_drbg,
+ .fips_allowed = 1,
+ .suite = {
+ .drbg = {
+ .vecs = drbg_pr_sha256_tv_template,
+ .count = ARRAY_SIZE(drbg_pr_sha256_tv_template)
+ }
+ }
+ }, {
+ /* covered by drbg_pr_sha256 test */
+ .alg = "drbg_pr_sha384",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
+ .alg = "drbg_pr_sha512",
+ .fips_allowed = 1,
+ .test = alg_test_null,
+ }, {
.alg = "ecb(__aes-aesni)",
.test = alg_test_null,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 69d0dd8ef27e..6597203eccfa 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -32,7 +32,7 @@
#define MAX_DIGEST_SIZE 64
#define MAX_TAP 8
-#define MAX_KEYLEN 56
+#define MAX_KEYLEN 160
#define MAX_IVLEN 32
struct hash_testvec {
@@ -92,6 +92,21 @@ struct cprng_testvec {
unsigned short loops;
};
+struct drbg_testvec {
+ unsigned char *entropy;
+ size_t entropylen;
+ unsigned char *entpra;
+ unsigned char *entprb;
+ size_t entprlen;
+ unsigned char *addtla;
+ unsigned char *addtlb;
+ size_t addtllen;
+ unsigned char *pers;
+ size_t perslen;
+ unsigned char *expected;
+ size_t expectedlen;
+};
+
static char zeroed_string[48];
/*
@@ -1807,18 +1822,59 @@ static struct hash_testvec tgr128_tv_template[] = {
},
};
-#define GHASH_TEST_VECTORS 1
+#define GHASH_TEST_VECTORS 5
static struct hash_testvec ghash_tv_template[] =
{
{
-
- .key = "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03\xff\xca\xff\x95\xf8\x30\xf0\x61",
+ .key = "\xdf\xa6\xbf\x4d\xed\x81\xdb\x03"
+ "\xff\xca\xff\x95\xf8\x30\xf0\x61",
.ksize = 16,
- .plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+ .plaintext = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+ "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
.psize = 16,
.digest = "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
"\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+ }, {
+ .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ksize = 16,
+ .plaintext = "what do ya want for nothing?",
+ .psize = 28,
+ .digest = "\x3e\x1f\x5c\x4d\x65\xf0\xef\xce"
+ "\x0d\x61\x06\x27\x66\x51\xd5\xe2",
+ .np = 2,
+ .tap = {14, 14}
+ }, {
+ .key = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ .ksize = 16,
+ .plaintext = "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+ .psize = 50,
+ .digest = "\xfb\x49\x8a\x36\xe1\x96\xe1\x96"
+ "\xe1\x96\xe1\x96\xe1\x96\xe1\x96",
+ }, {
+ .key = "\xda\x53\xeb\x0a\xd2\xc5\x5b\xb6"
+ "\x4f\xc4\x80\x2c\xc3\xfe\xda\x60",
+ .ksize = 16,
+ .plaintext = "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+ .psize = 50,
+ .digest = "\x2b\x5c\x0c\x7f\x52\xd1\x60\xc2"
+ "\x49\xed\x6e\x32\x7a\xa9\xbe\x08",
+ }, {
+ .key = "\x95\x2b\x2a\x56\xa5\x60\x04a\xc0"
+ "\xb3\x2b\x66\x56\xa0\x5b\x40\xb6",
+ .ksize = 16,
+ .plaintext = "Test With Truncation",
+ .psize = 20,
+ .digest = "\xf8\x94\x87\x2a\x4b\x63\x99\x28"
+ "\x23\xf7\x93\xf7\x19\xf5\x96\xd9",
},
};
@@ -3097,8 +3153,8 @@ static struct cipher_testvec des_enc_tv_template[] = {
"\x5F\x62\xC7\x72\xD9\xFC\xCB\x9A",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3207,8 +3263,8 @@ static struct cipher_testvec des_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3333,8 +3389,8 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
"\xC6\x4A\xF3\x55\xC7\x29\x2E\x63",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3442,8 +3498,8 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
},
};
@@ -3517,8 +3573,8 @@ static struct cipher_testvec des_ctr_enc_tv_template[] = {
"\x69\x74\xA1\x06\x46\x0F\x4E\x75",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
.klen = 8,
@@ -3663,8 +3719,8 @@ static struct cipher_testvec des_ctr_dec_tv_template[] = {
"\xC6\x2F\xBB\x24\x8D\x19\x82\xEB",
.rlen = 248,
.also_non_np = 1,
- .np = 2,
- .tap = { 248 - 8, 8 },
+ .np = 3,
+ .tap = { 248 - 10, 2, 8 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55",
.klen = 8,
@@ -3899,8 +3955,8 @@ static struct cipher_testvec des3_ede_enc_tv_template[] = {
"\xD8\x45\xFF\x33\xBA\xBB\x2B\x63",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4064,8 +4120,8 @@ static struct cipher_testvec des3_ede_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4244,8 +4300,8 @@ static struct cipher_testvec des3_ede_cbc_enc_tv_template[] = {
"\x95\x63\x73\xA2\x44\xAC\xF8\xA5",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4424,8 +4480,8 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -4564,8 +4620,8 @@ static struct cipher_testvec des3_ede_ctr_enc_tv_template[] = {
"\x5C\xEE\xFC\xCF\xC4\x70\x00\x34",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
"\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -4842,8 +4898,8 @@ static struct cipher_testvec des3_ede_ctr_dec_tv_template[] = {
"\xB8\x03\xEA\x7D\xE1\x48\xD3\x47",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\x9C\xD6\xF3\x9C\xB9\x5A\x67\x00"
"\x5A\x67\x00\x2D\xCE\xEB\x2D\xCE"
@@ -5182,8 +5238,8 @@ static struct cipher_testvec bf_enc_tv_template[] = {
"\xC9\x1A\xFB\x5D\xDE\xBB\x43\xF4",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5374,8 +5430,8 @@ static struct cipher_testvec bf_dec_tv_template[] = {
"\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5531,8 +5587,8 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
"\xB4\x98\xD8\x6B\x74\xE7\x65\xF4",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -5688,8 +5744,8 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
"\x2B\xC2\x59\xF0\x64\xFB\x92\x06",
.rlen = 504,
.also_non_np = 1,
- .np = 2,
- .tap = { 504 - 8, 8 },
+ .np = 3,
+ .tap = { 504 - 10, 2, 8 },
},
};
@@ -6694,8 +6750,8 @@ static struct cipher_testvec tf_enc_tv_template[] = {
"\x2C\x75\x64\xC4\xCA\xC1\x7E\xD5",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -6862,8 +6918,8 @@ static struct cipher_testvec tf_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -7045,8 +7101,8 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
"\x0A\xA3\x30\x10\x26\x25\x41\x2C",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -7228,8 +7284,8 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -8302,8 +8358,8 @@ static struct cipher_testvec tf_lrw_enc_tv_template[] = {
"\x11\xd7\xb8\x6e\xea\xe1\x80\x30",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -8555,8 +8611,8 @@ static struct cipher_testvec tf_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -8897,8 +8953,8 @@ static struct cipher_testvec tf_xts_enc_tv_template[] = {
"\x37\x30\xe1\x91\x8d\xb3\x2a\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -9240,8 +9296,8 @@ static struct cipher_testvec tf_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -9438,8 +9494,8 @@ static struct cipher_testvec serpent_enc_tv_template[] = {
"\xF4\x46\x2E\xEB\xAC\xF3\xD2\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9664,8 +9720,8 @@ static struct cipher_testvec serpent_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9846,8 +9902,8 @@ static struct cipher_testvec serpent_cbc_enc_tv_template[] = {
"\xBC\x08\x3A\xA2\x29\xB3\xDF\xD1",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -9987,8 +10043,8 @@ static struct cipher_testvec serpent_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -11061,8 +11117,8 @@ static struct cipher_testvec serpent_lrw_enc_tv_template[] = {
"\xd9\x51\x0f\xd7\x94\x2f\xc5\xa7",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11314,8 +11370,8 @@ static struct cipher_testvec serpent_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11656,8 +11712,8 @@ static struct cipher_testvec serpent_xts_enc_tv_template[] = {
"\xd4\xa0\x91\x98\x11\x5f\x4d\xb1",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -11999,8 +12055,8 @@ static struct cipher_testvec serpent_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -12182,8 +12238,8 @@ static struct cipher_testvec cast6_enc_tv_template[] = {
"\x11\x74\x93\x57\xB4\x7E\xC6\x00",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12353,8 +12409,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12494,8 +12550,8 @@ static struct cipher_testvec cast6_cbc_enc_tv_template[] = {
"\x22\x46\x89\x2D\x0F\x2B\x08\x24",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12635,8 +12691,8 @@ static struct cipher_testvec cast6_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12792,8 +12848,8 @@ static struct cipher_testvec cast6_ctr_enc_tv_template[] = {
"\xF9\xC5\xDD\x27\xB3\x39\xCB\xCB",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -12949,8 +13005,8 @@ static struct cipher_testvec cast6_ctr_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -13096,8 +13152,8 @@ static struct cipher_testvec cast6_lrw_enc_tv_template[] = {
"\xC4\xF5\x99\x61\xBC\xBB\x5B\x46",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13243,8 +13299,8 @@ static struct cipher_testvec cast6_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13392,8 +13448,8 @@ static struct cipher_testvec cast6_xts_enc_tv_template[] = {
"\x22\x60\x4E\xE8\xA4\x5D\x85\xB9",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13541,8 +13597,8 @@ static struct cipher_testvec cast6_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -13749,8 +13805,8 @@ static struct cipher_testvec aes_enc_tv_template[] = {
"\x17\xBB\xC0\x6B\x62\x3F\x56\xE9",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -13921,8 +13977,8 @@ static struct cipher_testvec aes_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -14140,8 +14196,8 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
"\xA3\xAA\x13\xCC\x50\xFF\x7B\x02",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -14359,8 +14415,8 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -16265,8 +16321,8 @@ static struct cipher_testvec aes_lrw_enc_tv_template[] = {
"\x74\x3f\x7d\x58\x88\x75\xde\x3e",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -16519,8 +16575,8 @@ static struct cipher_testvec aes_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -16861,8 +16917,8 @@ static struct cipher_testvec aes_xts_enc_tv_template[] = {
"\xb9\xc6\xe6\x93\xe1\x48\xc1\x51",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -17203,8 +17259,8 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
}
};
@@ -17420,8 +17476,8 @@ static struct cipher_testvec aes_ctr_enc_tv_template[] = {
"\xF1\x4C\xE5\xB2\x91\x64\x0C\x51",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
"\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -17775,8 +17831,8 @@ static struct cipher_testvec aes_ctr_dec_tv_template[] = {
"\xED\x56\xBF\x28\xB4\x1D\x86\x12",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
}, { /* Generated with Crypto++ */
.key = "\xC9\x83\xA6\xC9\xEC\x0F\x32\x55"
"\x0F\x32\x55\x78\x9B\xBE\x78\x9B"
@@ -20743,6 +20799,834 @@ static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
},
};
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG with prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_pr_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86"
+ "\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf"
+ "\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6"
+ "\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62"
+ "\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f"
+ "\x67\xb0\x67\x7a\x5e\x9e\x0c\x62",
+ .entprb = (unsigned char *)
+ "\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf"
+ "\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0"
+ "\x8c\xee\xeb\x9c\xf5\x31\x98\x31",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7"
+ "\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49"
+ "\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d"
+ "\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe"
+ "\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1"
+ "\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5"
+ "\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf"
+ "\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6"
+ "\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5"
+ "\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce"
+ "\x30\x81\xa6\x8f\x27\x14\xf8\x1c",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
+ "\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
+ "\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
+ "\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
+ "\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
+ "\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
+ .entprb = (unsigned char *)
+ "\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
+ "\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
+ "\x76\xaa\x55\x04\x8b\x0a\x72\x95",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
+ "\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
+ "\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
+ "\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
+ "\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
+ "\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
+ "\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
+ "\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
+ "\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
+ "\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
+ "\x50\x47\xa3\x63\x81\x16\xaf\x19",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
+ "\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
+ "\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
+ .addtlb = (unsigned char *)
+ "\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
+ "\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
+ "\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85"
+ "\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72"
+ "\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8"
+ "\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9"
+ "\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60"
+ "\xba\x0a\xde\x57\x5b\x4b\x9f\x29",
+ .entprb = (unsigned char *)
+ "\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd"
+ "\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4"
+ "\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25"
+ "\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde"
+ "\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5"
+ "\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9"
+ "\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c"
+ "\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e"
+ "\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c"
+ "\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae"
+ "\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c"
+ "\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe"
+ "\x90\x35\x0d\x4c\x4d\x85\xe7\x13",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7"
+ "\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90"
+ "\xa4\x1b\xe1\xe2\x53\xcc\x61\x47",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6"
+ "\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4"
+ "\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87"
+ "\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c"
+ "\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12"
+ "\x19\xaf\x97\x2d\x5f\xf9\xff\xfc",
+ .entprb = (unsigned char *)
+ "\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73"
+ "\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6"
+ "\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31"
+ "\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65"
+ "\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18"
+ "\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42"
+ "\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50"
+ "\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b"
+ "\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f"
+ "\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0"
+ "\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda"
+ "\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44"
+ "\x63\x4a\x68\x72\xe9\xf5\x55\xfe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c"
+ "\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff"
+ "\x4a\x85\xca\x80\xfe\x0d\x1c\xd0",
+ .addtlb = (unsigned char *)
+ "\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2"
+ "\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89"
+ "\x42\x58\x9e\xd6\xcc\xad\x7b\x1e",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1"
+ "\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52"
+ "\x82\x4c\xdc\x19\xb8\xf8\x92\x5c",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a"
+ "\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96"
+ "\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46"
+ "\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92"
+ "\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46"
+ "\xe2\x9a\x29\x51\x81\x56\x9f\x54",
+ .entprb = (unsigned char *)
+ "\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc"
+ "\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65"
+ "\x8a\x2a\x77\xa8\x69\x90\x89\xf4",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2"
+ "\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1"
+ "\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4"
+ "\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf"
+ "\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc"
+ "\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8"
+ "\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b"
+ "\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e"
+ "\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22"
+ "\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc"
+ "\xb1\xcd\x09\xd6\x92\xd0\x28\x3f",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f"
+ "\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f"
+ "\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05"
+ "\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4"
+ "\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26"
+ "\x46\xd9\x26\xa2\x19\xd4\x94\x43",
+ .entprb = (unsigned char *)
+ "\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79"
+ "\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98"
+ "\x51\x78\x72\xb2\x79\xfd\x2c\xff",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7"
+ "\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda"
+ "\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa"
+ "\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40"
+ "\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda"
+ "\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37"
+ "\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70"
+ "\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b"
+ "\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5"
+ "\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd"
+ "\xcd\x66\xb5\x01\x69\x66\xa0\x3c",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3"
+ "\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56"
+ "\x6d\x99\x3b\xc6\x58\xda\x03\xf6",
+ .addtlb = (unsigned char *)
+ "\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c"
+ "\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44"
+ "\xc6\x03\xa2\xfb\x13\x20\x19\xb7",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
+ "\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
+ "\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
+ "\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
+ "\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
+ "\x20\x28\xad\xf2\x60\xd7\xcd\x45",
+ .entprb = (unsigned char *)
+ "\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
+ "\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
+ "\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
+ "\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
+ "\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
+ "\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
+ "\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
+ "\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
+ "\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
+ "\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
+ "\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
+ "\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
+ "\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
+ "\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
+ "\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd"
+ "\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01"
+ "\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15"
+ "\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb",
+ .entropylen = 48,
+ .entpra = (unsigned char *)
+ "\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a"
+ "\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96"
+ "\xbb\x81\x6a\xcc\xb5\xae\x55\xb6",
+ .entprb = (unsigned char *)
+ "\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2"
+ "\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e"
+ "\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1",
+ .entprlen = 32,
+ .expected = (unsigned char *)
+ "\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14"
+ "\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6"
+ "\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7"
+ "\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77"
+ "\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5"
+ "\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6"
+ "\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1"
+ "\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40"
+ "\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8"
+ "\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72"
+ "\xda\x3f\xad\x2b\xba\x00\x6b\xd1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03"
+ "\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6"
+ "\x86\x88\x55\x28\xc1\x69\xdd\x76",
+ .addtlb = (unsigned char *)
+ "\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7"
+ "\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa"
+ "\x00\x99\x2a\xdd\x0a\x00\x50\x82",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8"
+ "\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda"
+ "\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42"
+ "\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15"
+ "\xb4\xec\x80\xb1",
+ .entprb = (unsigned char *)
+ "\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9"
+ "\x28\x07\xeb\xc2",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe"
+ "\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc"
+ "\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18"
+ "\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce"
+ "\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b"
+ "\x8a\xf1\x23\xa8",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77"
+ "\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73"
+ "\x67\xd1\x08\xf8",
+ .entprb = (unsigned char *)
+ "\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc"
+ "\xd4\xba\x04\x58",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d"
+ "\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc"
+ "\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7"
+ "\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc"
+ "\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c"
+ "\xc1\x02\x41\x82",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8"
+ "\xeb\xb3\x01\x76",
+ .addtlb = (unsigned char *)
+ "\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25"
+ "\xd0\x7f\xcc\x43",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b"
+ "\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66"
+ "\xc3\x0f\xe3\xb0",
+ .entprb = (unsigned char *)
+ "\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8"
+ "\xd6\x9c\x9d\xe8",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b"
+ "\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10"
+ "\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69"
+ "\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc"
+ "\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f"
+ "\x72\x82\x0c\xcf",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed"
+ "\x21\x52\xb3\xad",
+ .perslen = 16,
+ }, {
+ .entropy = (unsigned char *)
+ "\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
+ "\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
+ .entropylen = 24,
+ .entpra = (unsigned char *)
+ "\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
+ "\xc4\x2c\xe8\x10",
+ .entprb = (unsigned char *)
+ "\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
+ "\x08\xf7\xa5\x01",
+ .entprlen = 16,
+ .expected = (unsigned char *)
+ "\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
+ "\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
+ "\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
+ "\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
+ "\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
+ "\x23\xc5\x1f\x68",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
+ "\x23\x6d\xad\x1d",
+ .addtlb = (unsigned char *)
+ "\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
+ "\xbc\x59\x31\x8c",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
+ "\x37\x3c\x5c\x0b",
+ .perslen = 16,
+ },
+};
+
+/*
+ * SP800-90A DRBG Test vectors from
+ * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
+ *
+ * Test vectors for DRBG without prediction resistance. All types of DRBGs
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
+ * w/o personalization string, w/ and w/o additional input string).
+ */
+static struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3"
+ "\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19"
+ "\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31"
+ "\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64"
+ "\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5"
+ "\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3"
+ "\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11"
+ "\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81"
+ "\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63"
+ "\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7"
+ "\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c"
+ "\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91"
+ "\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d"
+ "\xd4\x31\xf4\xc9\xf7\x04\x27\xdf",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
+ "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
+ "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
+ "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
+ "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
+ "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
+ "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
+ "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
+ "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
+ "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
+ "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
+ "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
+ "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
+ "\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
+ "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
+ "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
+ .addtlb = (unsigned char *)
+ "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
+ "\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
+ "\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb"
+ "\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4"
+ "\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1"
+ "\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28"
+ "\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b"
+ "\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46"
+ "\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6"
+ "\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72"
+ "\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1"
+ "\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77"
+ "\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9"
+ "\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e"
+ "\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16"
+ "\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1"
+ "\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda"
+ "\x57\x6b\xce\xa4\x1c\x66\x3d\xbc",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a"
+ "\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74"
+ "\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc"
+ "\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb"
+ "\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13"
+ "\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6"
+ "\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36"
+ "\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64"
+ "\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea"
+ "\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95"
+ "\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e"
+ "\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd"
+ "\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06"
+ "\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2"
+ "\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e"
+ "\x77\xc5\x3d\x9e\x03\xe3\xa5\x78",
+ .addtlb = (unsigned char *)
+ "\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a"
+ "\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b"
+ "\x74\x7f\xa6\xf6\x80\xcd\x9b\x21",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20"
+ "\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73"
+ "\xa9\x65\xb1\x10\xc1\xdc\x77\x7c",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
+ "\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
+ "\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c"
+ "\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75"
+ "\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6"
+ "\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97"
+ "\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60"
+ "\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf"
+ "\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99"
+ "\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19"
+ "\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68"
+ "\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0"
+ "\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd"
+ "\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94"
+ "\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15"
+ "\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4"
+ "\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5"
+ "\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf"
+ "\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d"
+ "\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6"
+ "\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16"
+ "\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62"
+ "\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d"
+ "\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4"
+ "\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec"
+ "\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f"
+ "\x50\x9a\x8c\x85\x90\x87\x03\x9c",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d"
+ "\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf"
+ "\x2f\xf3\x00\x34\xd8\x26\x8e\x3b",
+ .addtlb = (unsigned char *)
+ "\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9"
+ "\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14"
+ "\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0",
+ .addtllen = 32,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
+ "\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
+ "\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
+ "\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
+ "\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
+ "\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
+ "\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
+ "\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
+ "\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
+ "\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
+ "\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
+ "\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
+ "\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
+ "\x10\x37\x41\x03\x0c\xcc\x3a\x56",
+ .expectedlen = 128,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
+ "\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
+ "\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
+ .perslen = 32,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78"
+ "\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11"
+ "\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb"
+ "\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0"
+ "\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37"
+ "\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae"
+ "\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0"
+ "\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad"
+ "\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82"
+ "\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7"
+ "\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4"
+ "\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49"
+ "\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30"
+ "\x35\x24\xcc\x9c\xc5\xea\x54\xa1",
+ .expectedlen = 128,
+ .addtla = (unsigned char *)
+ "\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96"
+ "\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62"
+ "\xd3\x13\x3b\x83\xe4\x9c\x82\x0b",
+ .addtlb = (unsigned char *)
+ "\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2"
+ "\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25"
+ "\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1",
+ .addtllen = 32,
+ .pers = (unsigned char *)
+ "\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8"
+ "\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15"
+ "\x36\x60\x3b\xca\x37\xc9\xee\x29",
+ .perslen = 32,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9"
+ "\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40"
+ "\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9"
+ "\xac\x9b\xbb\x00",
+ .entropylen = 40,
+ .expected = (unsigned char *)
+ "\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17"
+ "\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33"
+ "\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48"
+ "\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79"
+ "\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf"
+ "\x9a\x9d\xf1\x0d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f"
+ "\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec"
+ "\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0"
+ "\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb",
+ .entropylen = 48,
+ .expected = (unsigned char *)
+ "\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6"
+ "\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3"
+ "\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf"
+ "\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16"
+ "\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f"
+ "\xb4\xf0\x7e\x1d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ },
+};
+
+static struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
+ {
+ .entropy = (unsigned char *)
+ "\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8"
+ "\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1"
+ "\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a"
+ "\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3"
+ "\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e"
+ "\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8"
+ "\xcb\x2d\xd6\xb0",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74"
+ "\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34"
+ "\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21"
+ "\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e"
+ "\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1"
+ "\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc"
+ "\xc3\xdf\xb3\x81",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6"
+ "\x91\x4d\x81\x56",
+ .addtlb = (unsigned char *)
+ "\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb"
+ "\x4a\x55\xd1\xc6",
+ .addtllen = 16,
+ .pers = NULL,
+ .perslen = 0,
+ }, {
+ .entropy = (unsigned char *)
+ "\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9"
+ "\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e"
+ "\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75"
+ "\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee"
+ "\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb"
+ "\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45"
+ "\x34\x30\x0c\x3d",
+ .expectedlen = 64,
+ .addtla = NULL,
+ .addtlb = NULL,
+ .addtllen = 0,
+ .pers = (unsigned char *)
+ "\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a"
+ "\x0b\xc6\x97\x54",
+ .perslen = 16,
+ }, {
+ .entropy = (unsigned char *)
+ "\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
+ "\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
+ .entropylen = 24,
+ .expected = (unsigned char *)
+ "\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
+ "\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
+ "\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
+ "\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
+ "\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
+ "\x2b\x49\x1e\x5c",
+ .expectedlen = 64,
+ .addtla = (unsigned char *)
+ "\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
+ "\x44\x85\xe7\xfe",
+ .addtlb = (unsigned char *)
+ "\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
+ "\x82\x16\x62\x7f",
+ .addtllen = 16,
+ .pers = (unsigned char *)
+ "\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
+ "\x8e\xcf\xe0\x02",
+ .perslen = 16,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 4
#define CAST5_DEC_TEST_VECTORS 4
@@ -20907,8 +21791,8 @@ static struct cipher_testvec cast5_enc_tv_template[] = {
"\xF5\xBC\x25\xD6\x02\x56\x57\x1C",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21068,8 +21952,8 @@ static struct cipher_testvec cast5_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21206,8 +22090,8 @@ static struct cipher_testvec cast5_cbc_enc_tv_template[] = {
"\x1D\x18\x66\x44\x5B\x8F\x14\xEB",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21344,8 +22228,8 @@ static struct cipher_testvec cast5_cbc_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21495,8 +22379,8 @@ static struct cipher_testvec cast5_ctr_enc_tv_template[] = {
"\xC0\x0D\x96\xAA\x23\xF8\xFE\x13",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -21646,8 +22530,8 @@ static struct cipher_testvec cast5_ctr_dec_tv_template[] = {
"\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
.rlen = 496,
.also_non_np = 1,
- .np = 2,
- .tap = { 496 - 16, 16 },
+ .np = 3,
+ .tap = { 496 - 20, 4, 16 },
},
};
@@ -22805,8 +23689,8 @@ static struct cipher_testvec camellia_enc_tv_template[] = {
"\x33\x1A\xBB\xD3\xA2\x7E\x97\x66",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23105,8 +23989,8 @@ static struct cipher_testvec camellia_dec_tv_template[] = {
"\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23401,8 +24285,8 @@ static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
"\x70\xC5\xB9\x0B\x3B\x7A\x6E\x6C",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -23697,8 +24581,8 @@ static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
"\x72\x09\xA0\x14\xAB\x42\xD9\x4D",
.rlen = 1008,
.also_non_np = 1,
- .np = 2,
- .tap = { 1008 - 16, 16 },
+ .np = 3,
+ .tap = { 1008 - 20, 4, 16 },
},
};
@@ -25283,8 +26167,8 @@ static struct cipher_testvec camellia_lrw_enc_tv_template[] = {
"\x5a\xa8\x92\x7f\xba\xe6\x0c\x95",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -25536,8 +26420,8 @@ static struct cipher_testvec camellia_lrw_dec_tv_template[] = {
"\x21\xc4\xc2\x75\x67\x89\x37\x0a",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -25878,8 +26762,8 @@ static struct cipher_testvec camellia_xts_enc_tv_template[] = {
"\xd5\xc6\x99\xcc\x4e\x6c\x94\x95",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
@@ -26221,8 +27105,8 @@ static struct cipher_testvec camellia_xts_dec_tv_template[] = {
"\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
.rlen = 512,
.also_non_np = 1,
- .np = 2,
- .tap = { 512 - 16, 16 },
+ .np = 3,
+ .tap = { 512 - 20, 4, 16 },
},
};
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 06b62e5cdcc7..c9ee681d57fd 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -168,7 +168,7 @@ static int zlib_compress_update(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -198,7 +198,7 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -283,7 +283,7 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
@@ -331,7 +331,7 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
}
ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n",
stream->avail_in, stream->avail_out,
req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 0e87a34b6472..622fa266b29e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -176,4 +176,8 @@ source "drivers/powercap/Kconfig"
source "drivers/mcb/Kconfig"
+source "drivers/ras/Kconfig"
+
+source "drivers/thunderbolt/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f98b50d8251d..ebee55537a05 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/
obj-$(CONFIG_PARPORT) += parport/
obj-y += base/ block/ misc/ mfd/ nfc/
+obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
@@ -158,3 +159,5 @@ obj-$(CONFIG_NTB) += ntb/
obj-$(CONFIG_FMC) += fmc/
obj-$(CONFIG_POWERCAP) += powercap/
obj-$(CONFIG_MCB) += mcb/
+obj-$(CONFIG_RAS) += ras/
+obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index a34a22841002..d0f3265fb85d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -42,6 +42,12 @@ menuconfig ACPI
if ACPI
+config ACPI_LEGACY_TABLES_LOOKUP
+ bool
+
+config ARCH_MIGHT_HAVE_ACPI_PDC
+ bool
+
config ACPI_SLEEP
bool
depends on SUSPEND || HIBERNATION
@@ -370,6 +376,7 @@ config ACPI_EXTLOG
tristate "Extended Error Log support"
depends on X86_MCE && X86_LOCAL_APIC
select UEFI_CPER
+ select RAS
default n
help
Certain usages such as Predictive Failure Analysis (PFA) require
@@ -384,6 +391,7 @@ config ACPI_EXTLOG
Enhanced MCA Logging allows firmware to provide additional error
information to system software, synchronous with MCE or CMCI. This
- driver adds support for that functionality.
+ driver adds support for that functionality with corresponding
+ tracepoint which carries that information to userspace.
endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index ea55e0179f81..505d4d79fe3e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -36,6 +36,7 @@ acpi-y += scan.o
acpi-y += resource.o
acpi-y += acpi_processor.o
acpi-y += processor_core.o
+acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
acpi-y += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-y += pci_root.o pci_link.o pci_irq.o
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 185334114d71..b3842ffc19ba 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -12,10 +12,12 @@
#include <linux/cper.h>
#include <linux/ratelimit.h>
#include <linux/edac.h>
+#include <linux/ras.h>
#include <asm/cpu.h>
#include <asm/mce.h>
#include "apei/apei-internal.h"
+#include <ras/ras_event.h>
#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */
@@ -69,11 +71,11 @@ static u32 l1_percpu_entry;
#define ELOG_ENTRY_ADDR(phyaddr) \
(phyaddr - elog_base + (u8 *)elog_addr)
-static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank)
+static struct acpi_hest_generic_status *extlog_elog_entry_check(int cpu, int bank)
{
int idx;
u64 data;
- struct acpi_generic_status *estatus;
+ struct acpi_hest_generic_status *estatus;
WARN_ON(cpu < 0);
idx = ELOG_IDX(cpu, bank);
@@ -82,7 +84,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank)
return NULL;
data &= EXT_ELOG_ENTRY_MASK;
- estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data);
+ estatus = (struct acpi_hest_generic_status *)ELOG_ENTRY_ADDR(data);
/* if no valid data in elog entry, just return */
if (estatus->block_status == 0)
@@ -92,7 +94,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank)
}
static void __print_extlog_rcd(const char *pfx,
- struct acpi_generic_status *estatus, int cpu)
+ struct acpi_hest_generic_status *estatus, int cpu)
{
static atomic_t seqno;
unsigned int curr_seqno;
@@ -111,7 +113,7 @@ static void __print_extlog_rcd(const char *pfx,
}
static int print_extlog_rcd(const char *pfx,
- struct acpi_generic_status *estatus, int cpu)
+ struct acpi_hest_generic_status *estatus, int cpu)
{
/* Not more than 2 messages every 5 seconds */
static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -137,8 +139,12 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
struct mce *mce = (struct mce *)data;
int bank = mce->bank;
int cpu = mce->extcpu;
- struct acpi_generic_status *estatus;
- int rc;
+ struct acpi_hest_generic_status *estatus, *tmp;
+ struct acpi_hest_generic_data *gdata;
+ const uuid_le *fru_id = &NULL_UUID_LE;
+ char *fru_text = "";
+ uuid_le *sec_type;
+ static u32 err_seq;
estatus = extlog_elog_entry_check(cpu, bank);
if (estatus == NULL)
@@ -148,8 +154,29 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
/* clear record status to enable BIOS to update it again */
estatus->block_status = 0;
- rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu);
+ tmp = (struct acpi_hest_generic_status *)elog_buf;
+
+ if (!ras_userspace_consumers()) {
+ print_extlog_rcd(NULL, tmp, cpu);
+ goto out;
+ }
+
+ /* log event via trace */
+ err_seq++;
+ gdata = (struct acpi_hest_generic_data *)(tmp + 1);
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+ fru_id = (uuid_le *)gdata->fru_id;
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+ fru_text = gdata->fru_text;
+ sec_type = (uuid_le *)gdata->section_type;
+ if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
+ struct cper_sec_mem_err *mem = (void *)(gdata + 1);
+ if (gdata->error_data_length >= sizeof(*mem))
+ trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
+ (u8)gdata->error_severity);
+ }
+out:
return NOTIFY_STOP;
}
@@ -196,19 +223,16 @@ static int __init extlog_init(void)
u64 cap;
int rc;
+ rdmsrl(MSR_IA32_MCG_CAP, cap);
+
+ if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr())
+ return -ENODEV;
+
if (get_edac_report_status() == EDAC_REPORTING_FORCE) {
pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n");
return -EPERM;
}
- rc = -ENODEV;
- rdmsrl(MSR_IA32_MCG_CAP, cap);
- if (!(cap & MCG_ELOG_P))
- return rc;
-
- if (!extlog_get_l1addr())
- return rc;
-
rc = -EINVAL;
/* get L1 header to fetch necessary information */
l1_hdr_size = sizeof(struct extlog_l1_head);
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 9cb65b0e7597..ce06149088c5 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -113,6 +113,14 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata)
writel(val, pdata->mmio_base + offset);
}
+static struct lpss_device_desc wpt_dev_desc = {
+ .clk_required = true,
+ .prv_offset = 0x800,
+ .ltr_required = true,
+ .clk_divider = true,
+ .clk_gate = true,
+};
+
static struct lpss_device_desc lpt_dev_desc = {
.clk_required = true,
.prv_offset = 0x800,
@@ -226,6 +234,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
{ "INT3437", },
+ { "INT3438", LPSS_ADDR(wpt_dev_desc) },
+
{ }
};
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index 4ddb0dca56f6..996fa1959eea 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -12,6 +12,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
+#include <linux/ctype.h>
static const struct acpi_device_id acpi_pnp_device_ids[] = {
/* soc_button_array */
@@ -320,11 +321,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
{""},
};
-static bool is_hex_digit(char c)
-{
- return (c >= 0 && c <= '9') || (c >= 'A' && c <= 'F');
-}
-
static bool matching_id(char *idstr, char *list_id)
{
int i;
@@ -335,7 +331,7 @@ static bool matching_id(char *idstr, char *list_id)
for (i = 3; i < 7; i++) {
char c = toupper(idstr[i]);
- if (!is_hex_digit(c)
+ if (!isxdigit(c)
|| (list_id[i] != 'X' && c != toupper(list_id[i])))
return false;
}
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 1c085742644f..1fdf5e07a1c7 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -268,7 +268,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
pr->apic_id = apic_id;
cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
- if (!cpu0_initialized && !acpi_lapic) {
+ if (!cpu0_initialized && !acpi_has_cpu_in_madt()) {
cpu0_initialized = 1;
/* Handle UP system running SMP kernel, with no LAPIC in MADT */
if ((cpu_index == -1) && (num_online_cpus() == 1))
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 8bb43f06e11f..c1a963581dc0 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -2,7 +2,7 @@
# Makefile for ACPICA Core interpreter
#
-ccflags-y := -Os
+ccflags-y := -Os -DBUILDING_ACPICA
ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
# use acpi.o to put all files here into acpi.o modparam namespace
@@ -157,6 +157,7 @@ acpi-y += \
uterror.o \
uteval.o \
utglobal.o \
+ uthex.o \
utids.o \
utinit.o \
utlock.o \
@@ -175,5 +176,10 @@ acpi-y += \
utxferror.o \
utxfmutex.o
-acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o
+acpi-$(ACPI_FUTURE_USAGE) += \
+ utcache.o \
+ utfileio.o \
+ utprint.o \
+ uttrack.o \
+ utuuid.o
diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h
index 8698ffba6f39..3d2c88289da9 100644
--- a/drivers/acpi/acpica/acapps.h
+++ b/drivers/acpi/acpica/acapps.h
@@ -79,10 +79,13 @@
/* Macros for usage messages */
#define ACPI_USAGE_HEADER(usage) \
- printf ("Usage: %s\nOptions:\n", usage);
+ acpi_os_printf ("Usage: %s\nOptions:\n", usage);
+
+#define ACPI_USAGE_TEXT(description) \
+ acpi_os_printf (description);
#define ACPI_OPTION(name, description) \
- printf (" %-18s%s\n", name, description);
+ acpi_os_printf (" %-18s%s\n", name, description);
#define FILE_SUFFIX_DISASSEMBLY "dsl"
#define ACPI_TABLE_FILE_SUFFIX ".dat"
@@ -102,7 +105,7 @@ extern char *acpi_gbl_optarg;
/*
* cmfsize - Common get file size function
*/
-u32 cm_get_file_size(FILE * file);
+u32 cm_get_file_size(ACPI_FILE file);
#ifndef ACPI_DUMP_APP
/*
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 68a91eb0fa48..1d026ff1683f 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -233,9 +233,6 @@ acpi_status acpi_db_load_acpi_table(char *filename);
acpi_status
acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table);
-acpi_status
-acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table);
-
/*
* dbhistry - debugger HISTORY command
*/
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 115eedcade1e..ebf02cc10a43 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -297,7 +297,7 @@ ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer);
*
****************************************************************************/
-ACPI_GLOBAL(u8, acpi_gbl_db_output_flags);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT);
#ifdef ACPI_DISASSEMBLER
@@ -362,6 +362,12 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects);
#ifdef ACPI_APPLICATION
ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
+ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL);
+
+/* Print buffer */
+
+ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */
+ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]);
#endif /* ACPI_APPLICATION */
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 91f801a2e689..1f9aba5fb81f 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -730,12 +730,13 @@ union acpi_parse_value {
#define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */
#define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */
#define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */
-#define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */
-#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */
-#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */
-#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */
-#define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */
-#define ACPI_DASM_IGNORE 0x0A /* Not used at this time */
+#define ACPI_DASM_UUID 0x05 /* Buffer is a UUID/GUID */
+#define ACPI_DASM_EISAID 0x06 /* Integer is an EISAID */
+#define ACPI_DASM_MATCHOP 0x07 /* Parent opcode is a Match() operator */
+#define ACPI_DASM_LNOT_PREFIX 0x08 /* Start of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_LNOT_SUFFIX 0x09 /* End of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_HID_STRING 0x0A /* String is a _HID or _CID */
+#define ACPI_DASM_IGNORE 0x0B /* Not used at this time */
/*
* Generic operation (for example: If, While, Store)
@@ -1154,4 +1155,9 @@ struct ah_device_id {
char *description;
};
+struct ah_uuid {
+ char *description;
+ char *string;
+};
+
#endif /* __ACLOCAL_H__ */
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index bd08817cafd8..bd3908d26c4f 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -105,6 +105,11 @@
* count = 0 (optional)
* (Used for _DLM)
*
+ * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID
+ * defines the format of the package. Zero-length parent package is
+ * allowed.
+ * (Used for _DSD)
+ *
*****************************************************************************/
enum acpi_return_package_types {
@@ -117,7 +122,8 @@ enum acpi_return_package_types {
ACPI_PTYPE2_FIXED = 7,
ACPI_PTYPE2_MIN = 8,
ACPI_PTYPE2_REV_FIXED = 9,
- ACPI_PTYPE2_FIX_VAR = 10
+ ACPI_PTYPE2_FIX_VAR = 10,
+ ACPI_PTYPE2_UUID_PAIR = 11
};
/* Support macros for users of the predefined info table */
@@ -364,6 +370,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_CBA", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */
+ {{"_CCA", METHOD_0ARGS,
+ METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 5.1 */
+
{{"_CDM", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
@@ -436,6 +445,11 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER),
METHOD_NO_RETURN_VALUE}},
+ {{"_DSD", METHOD_0ARGS,
+ METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */
+ PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1,
+ ACPI_RTYPE_PACKAGE, 1, 0),
+
{{"_DSM",
METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER,
ACPI_TYPE_PACKAGE),
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 1e256c5bda20..486d342e74b6 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -95,7 +95,6 @@ extern const char *acpi_gbl_pt_decode[];
#ifdef ACPI_ASL_COMPILER
#include <stdio.h>
-extern FILE *acpi_gbl_output_file;
#define ACPI_MSG_REDIRECT_BEGIN \
FILE *output_file = acpi_gbl_output_file; \
@@ -195,6 +194,8 @@ char *acpi_ut_get_event_name(u32 event_id);
char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
+u8 acpi_ut_ascii_char_to_hex(int hex_char);
+
u8 acpi_ut_valid_object_type(acpi_object_type type);
/*
@@ -211,6 +212,8 @@ void acpi_ut_subsystem_shutdown(void);
acpi_size acpi_ut_strlen(const char *string);
+char *acpi_ut_strchr(const char *string, int ch);
+
char *acpi_ut_strcpy(char *dst_string, const char *src_string);
char *acpi_ut_strncpy(char *dst_string,
@@ -257,7 +260,7 @@ extern const u8 _acpi_ctype[];
#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP))
#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
-#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
+#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU))
#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
#endif /* !ACPI_USE_SYSTEM_CLIBRARY */
@@ -352,6 +355,13 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id);
void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
+#ifdef ACPI_APPLICATION
+void
+acpi_ut_dump_buffer_to_file(ACPI_FILE file,
+ u8 *buffer,
+ u32 count, u32 display, u32 base_offset);
+#endif
+
void acpi_ut_report_error(char *module_name, u32 line_number);
void acpi_ut_report_info(char *module_name, u32 line_number);
@@ -394,6 +404,14 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
u8 method_count, u8 *out_values);
/*
+ * utfileio - file operations
+ */
+#ifdef ACPI_APPLICATION
+acpi_status
+acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table);
+#endif
+
+/*
* utids - device ID support
*/
acpi_status
@@ -743,4 +761,30 @@ const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg);
const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
+const char *acpi_ah_match_uuid(u8 *data);
+
+/*
+ * utprint - printf/vprintf output functions
+ */
+const char *acpi_ut_scan_number(const char *string, u64 *number_ptr);
+
+const char *acpi_ut_print_number(char *string, u64 number);
+
+int
+acpi_ut_vsnprintf(char *string,
+ acpi_size size, const char *format, va_list args);
+
+int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...);
+
+#ifdef ACPI_APPLICATION
+int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args);
+
+int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...);
+#endif
+
+/*
+ * utuuid -- UUID support functions
+ */
+void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer);
+
#endif /* _ACUTILS_H */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 48f70013b488..e4ba4dec86af 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -698,21 +698,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
}
/*
- * If edge-triggered, clear the GPE status bit now. Note that
- * level-triggered events are cleared after the GPE is serviced.
- */
- if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
- ACPI_GPE_EDGE_TRIGGERED) {
- status = acpi_hw_clear_gpe(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "Unable to clear GPE %02X",
- gpe_number));
- return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
- }
- }
-
- /*
* Always disable the GPE so that it does not keep firing before
* any asynchronous activity completes (either from the execution
* of a GPE method or an asynchronous GPE handler.)
@@ -729,6 +714,23 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
}
/*
+ * If edge-triggered, clear the GPE status bit now. Note that
+ * level-triggered events are cleared after the GPE is serviced.
+ */
+ if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
+ ACPI_GPE_EDGE_TRIGGERED) {
+ status = acpi_hw_clear_gpe(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "Unable to clear GPE %02X",
+ gpe_number));
+ (void)acpi_hw_low_set_gpe(gpe_event_info,
+ ACPI_GPE_CONDITIONAL_ENABLE);
+ return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
+ }
+ }
+
+ /*
* Dispatch the GPE to either an installed handler or the control
* method associated with this GPE (_Lxx or _Exx). If a handler
* exists, we invoke it and do not attempt to run the method.
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index cb534faf5369..0cf159cc6e6d 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -126,11 +126,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
- /* Ensure that we have a valid GPE number */
-
+ /*
+ * Ensure that we have a valid GPE number and that there is some way
+ * of handling the GPE (handler or a GPE method). In other words, we
+ * won't allow a valid GPE to be enabled if there is no way to handle it.
+ */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (gpe_event_info) {
- status = acpi_ev_add_gpe_reference(gpe_event_info);
+ if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
+ ACPI_GPE_DISPATCH_NONE) {
+ status = acpi_ev_add_gpe_reference(gpe_event_info);
+ } else {
+ status = AE_NO_HANDLER;
+ }
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
@@ -179,6 +187,53 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
/*******************************************************************************
*
+ * FUNCTION: acpi_mark_gpe_for_wake
+ *
+ * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
+ * gpe_number - GPE level within the GPE block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
+ * sets the ACPI_GPE_CAN_WAKE flag.
+ *
+ * Some potential callers of acpi_setup_gpe_for_wake may know in advance that
+ * there won't be any notify handlers installed for device wake notifications
+ * from the given GPE (one example is a button GPE in Linux). For these cases,
+ * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
+ * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
+ * setup implicit wake notification for it (since there's no handler method).
+ *
+ ******************************************************************************/
+acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
+{
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_status status = AE_BAD_PARAMETER;
+ acpi_cpu_flags flags;
+
+ ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /* Ensure that we have a valid GPE number */
+
+ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
+ if (gpe_event_info) {
+
+ /* Mark the GPE as a possible wake event */
+
+ gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+ status = AE_OK;
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_setup_gpe_for_wake
*
* PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index 4cfc3d3b5c97..6fbfad47518c 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -75,6 +75,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
u32 level, u32 index)
{
u32 i;
+ u32 timer;
ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
@@ -86,11 +87,19 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
}
/*
+ * We will emit the current timer value (in microseconds) with each
+ * debug output. Only need the lower 26 bits. This allows for 67
+ * million microseconds or 67 seconds before rollover.
+ */
+ timer = ((u32)acpi_os_get_timer() / 10); /* (100 nanoseconds to microseconds) */
+ timer &= 0x03FFFFFF;
+
+ /*
* Print line header as long as we are not in the middle of an
* object display
*/
if (!((level > 0) && index == 0)) {
- acpi_os_printf("[ACPI Debug] %*s", level, " ");
+ acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " ");
}
/* Display the index for package output only */
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 925202acc3e4..0f23c3f2678e 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -494,7 +494,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
}
}
- acpi_os_printf("\n", next);
+ acpi_os_printf("\n");
break;
case ACPI_EXD_HDLR_LIST:
@@ -528,7 +528,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
}
}
- acpi_os_printf("\n", next);
+ acpi_os_printf("\n");
break;
case ACPI_EXD_RGN_LIST:
@@ -562,7 +562,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
}
}
- acpi_os_printf("\n", next);
+ acpi_os_printf("\n");
break;
case ACPI_EXD_NODE:
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 12878e1982f7..6907ce0c704c 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -56,7 +56,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
/*******************************************************************************
*
- * FUNCTION: acpi_get_serial_access_bytes
+ * FUNCTION: acpi_ex_get_serial_access_length
*
* PARAMETERS: accessor_type - The type of the protocol indicated by region
* field access attributes
@@ -103,7 +103,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
case AML_FIELD_ATTRIB_BLOCK_CALL:
default:
- length = ACPI_GSBUS_BUFFER_SIZE;
+ length = ACPI_GSBUS_BUFFER_SIZE - 2;
break;
}
@@ -186,12 +186,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
access_length);
/*
- * Add additional 2 bytes for modeled generic_serial_bus data buffer:
- * typedef struct {
- * BYTEStatus; // Byte 0 of the data buffer
- * BYTELength; // Byte 1 of the data buffer
- * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
- * }
+ * Add additional 2 bytes for the generic_serial_bus data buffer:
+ *
+ * Status; (Byte 0 of the data buffer)
+ * Length; (Byte 1 of the data buffer)
+ * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_READ | (accessor_type << 16);
@@ -368,12 +367,11 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
access_length);
/*
- * Add additional 2 bytes for modeled generic_serial_bus data buffer:
- * typedef struct {
- * BYTEStatus; // Byte 0 of the data buffer
- * BYTELength; // Byte 1 of the data buffer
- * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
- * }
+ * Add additional 2 bytes for the generic_serial_bus data buffer:
+ *
+ * Status; (Byte 0 of the data buffer)
+ * Length; (Byte 1 of the data buffer)
+ * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_WRITE | (accessor_type << 16);
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index e0fd9b4978cd..a4c34d2c556b 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -278,8 +278,9 @@ acpi_status acpi_hw_clear_acpi_status(void)
acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
goto exit;
+ }
/* Clear the GPE Bits in all GPE registers in all GPE blocks */
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c
index fe54a8c73b8c..a42ee9d6970d 100644
--- a/drivers/acpi/acpica/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -237,6 +237,16 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node)
(node->object->common.type != ACPI_TYPE_LOCAL_DATA)) {
node->object = node->object->common.next_object;
}
+
+ /*
+ * Detach the object from any data objects (which are still held by
+ * the namespace node)
+ */
+ if (obj_desc->common.next_object &&
+ ((obj_desc->common.next_object)->common.type ==
+ ACPI_TYPE_LOCAL_DATA)) {
+ obj_desc->common.next_object = NULL;
+ }
}
/* Reset the node type to untyped */
diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c
index 3c1699740653..038ea887f562 100644
--- a/drivers/acpi/acpica/utbuffer.c
+++ b/drivers/acpi/acpica/utbuffer.c
@@ -199,3 +199,131 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id)
acpi_ut_dump_buffer(buffer, count, display, 0);
}
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_dump_buffer_to_file
+ *
+ * PARAMETERS: file - File descriptor
+ * buffer - Buffer to dump
+ * count - Amount to dump, in bytes
+ * display - BYTE, WORD, DWORD, or QWORD display:
+ * DB_BYTE_DISPLAY
+ * DB_WORD_DISPLAY
+ * DB_DWORD_DISPLAY
+ * DB_QWORD_DISPLAY
+ * base_offset - Beginning buffer offset (display only)
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Generic dump buffer in both hex and ascii to a file.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_dump_buffer_to_file(ACPI_FILE file,
+ u8 *buffer, u32 count, u32 display, u32 base_offset)
+{
+ u32 i = 0;
+ u32 j;
+ u32 temp32;
+ u8 buf_char;
+
+ if (!buffer) {
+ acpi_ut_file_printf(file,
+ "Null Buffer Pointer in DumpBuffer!\n");
+ return;
+ }
+
+ if ((count < 4) || (count & 0x01)) {
+ display = DB_BYTE_DISPLAY;
+ }
+
+ /* Nasty little dump buffer routine! */
+
+ while (i < count) {
+
+ /* Print current offset */
+
+ acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i));
+
+ /* Print 16 hex chars */
+
+ for (j = 0; j < 16;) {
+ if (i + j >= count) {
+
+ /* Dump fill spaces */
+
+ acpi_ut_file_printf(file, "%*s",
+ ((display * 2) + 1), " ");
+ j += display;
+ continue;
+ }
+
+ switch (display) {
+ case DB_BYTE_DISPLAY:
+ default: /* Default is BYTE display */
+
+ acpi_ut_file_printf(file, "%02X ",
+ buffer[(acpi_size) i + j]);
+ break;
+
+ case DB_WORD_DISPLAY:
+
+ ACPI_MOVE_16_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
+ acpi_ut_file_printf(file, "%04X ", temp32);
+ break;
+
+ case DB_DWORD_DISPLAY:
+
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
+ acpi_ut_file_printf(file, "%08X ", temp32);
+ break;
+
+ case DB_QWORD_DISPLAY:
+
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j]);
+ acpi_ut_file_printf(file, "%08X", temp32);
+
+ ACPI_MOVE_32_TO_32(&temp32,
+ &buffer[(acpi_size) i + j +
+ 4]);
+ acpi_ut_file_printf(file, "%08X ", temp32);
+ break;
+ }
+
+ j += display;
+ }
+
+ /*
+ * Print the ASCII equivalent characters but watch out for the bad
+ * unprintable ones (printable chars are 0x20 through 0x7E)
+ */
+ acpi_ut_file_printf(file, " ");
+ for (j = 0; j < 16; j++) {
+ if (i + j >= count) {
+ acpi_ut_file_printf(file, "\n");
+ return;
+ }
+
+ buf_char = buffer[(acpi_size) i + j];
+ if (ACPI_IS_PRINT(buf_char)) {
+ acpi_ut_file_printf(file, "%c", buf_char);
+ } else {
+ acpi_ut_file_printf(file, ".");
+ }
+ }
+
+ /* Done with that line. */
+
+ acpi_ut_file_printf(file, "\n");
+ i += 16;
+ }
+
+ return;
+}
+#endif
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 270c16464dd9..ff601c0f7c7a 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
}
+ /* Delete the allocated object if copy failed */
+
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_remove_reference(*dest_desc);
+ }
+
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 21a20ac5b1e1..e516254c63b2 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -561,3 +561,29 @@ acpi_ut_ptr_exit(u32 line_number,
}
#endif
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_log_error
+ *
+ * PARAMETERS: format - Printf format field
+ * ... - Optional printf arguments
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Print error message to the console, used by applications.
+ *
+ ******************************************************************************/
+
+void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ (void)acpi_ut_file_vprintf(ACPI_FILE_ERR, format, args);
+ va_end(args);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_log_error)
+#endif
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index 90ec37c473c6..40e923e675fc 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -88,33 +88,6 @@ const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = {
/*******************************************************************************
*
- * FUNCTION: acpi_ut_hex_to_ascii_char
- *
- * PARAMETERS: integer - Contains the hex digit
- * position - bit position of the digit within the
- * integer (multiple of 4)
- *
- * RETURN: The converted Ascii character
- *
- * DESCRIPTION: Convert a hex digit to an Ascii character
- *
- ******************************************************************************/
-
-/* Hex to ASCII conversion table */
-
-static const char acpi_gbl_hex_to_ascii[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
-{
-
- return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
-}
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ut_get_region_name
*
* PARAMETERS: Space ID - ID for the region
@@ -475,7 +448,8 @@ static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
/* 09 */ "Device PLD Check",
/* 0A */ "Reserved",
/* 0B */ "System Locality Update",
- /* 0C */ "Shutdown Request"
+ /* 0C */ "Shutdown Request",
+ /* 0D */ "System Resource Affinity Update"
};
static const char *acpi_gbl_device_notify[4] = {
@@ -502,7 +476,7 @@ static const char *acpi_gbl_thermal_notify[4] = {
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
{
- /* 00 - 0C are common to all object types */
+ /* 00 - 0D are common to all object types */
if (notify_value <= ACPI_NOTIFY_MAX) {
return (acpi_gbl_generic_notify[notify_value]);
diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c
new file mode 100644
index 000000000000..4e263a8cc6f0
--- /dev/null
+++ b/drivers/acpi/acpica/utfileio.c
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ *
+ * Module Name: utfileio - simple file I/O routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, 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"
+#include "actables.h"
+#include "acapps.h"
+
+#ifdef ACPI_ASL_COMPILER
+#include "aslcompiler.h"
+#endif
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ACPI_MODULE_NAME("utfileio")
+
+#ifdef ACPI_APPLICATION
+/* Local prototypes */
+static acpi_status
+acpi_ut_check_text_mode_corruption(u8 *table,
+ u32 table_length, u32 file_length);
+
+static acpi_status
+acpi_ut_read_table(FILE * fp,
+ struct acpi_table_header **table, u32 *table_length);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_check_text_mode_corruption
+ *
+ * PARAMETERS: table - Table buffer
+ * table_length - Length of table from the table header
+ * file_length - Length of the file that contains the table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check table for text mode file corruption where all linefeed
+ * characters (LF) have been replaced by carriage return linefeed
+ * pairs (CR/LF).
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length)
+{
+ u32 i;
+ u32 pairs = 0;
+
+ if (table_length != file_length) {
+ ACPI_WARNING((AE_INFO,
+ "File length (0x%X) is not the same as the table length (0x%X)",
+ file_length, table_length));
+ }
+
+ /* Scan entire table to determine if each LF has been prefixed with a CR */
+
+ for (i = 1; i < file_length; i++) {
+ if (table[i] == 0x0A) {
+ if (table[i - 1] != 0x0D) {
+
+ /* The LF does not have a preceding CR, table not corrupted */
+
+ return (AE_OK);
+ } else {
+ /* Found a CR/LF pair */
+
+ pairs++;
+ }
+ i++;
+ }
+ }
+
+ if (!pairs) {
+ return (AE_OK);
+ }
+
+ /*
+ * Entire table scanned, each CR is part of a CR/LF pair --
+ * meaning that the table was treated as a text file somewhere.
+ *
+ * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
+ * original table are left untouched by the text conversion process --
+ * meaning that we cannot simply replace CR/LF pairs with LFs.
+ */
+ acpi_os_printf("Table has been corrupted by text mode conversion\n");
+ acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs);
+ acpi_os_printf("Table cannot be repaired!\n");
+ return (AE_BAD_VALUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_read_table
+ *
+ * PARAMETERS: fp - File that contains table
+ * table - Return value, buffer with table
+ * table_length - Return value, length of table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load the DSDT from the file pointer
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_read_table(FILE * fp,
+ struct acpi_table_header **table, u32 *table_length)
+{
+ struct acpi_table_header table_header;
+ u32 actual;
+ acpi_status status;
+ u32 file_size;
+ u8 standard_header = TRUE;
+ s32 count;
+
+ /* Get the file size */
+
+ file_size = cm_get_file_size(fp);
+ if (file_size == ACPI_UINT32_MAX) {
+ return (AE_ERROR);
+ }
+
+ if (file_size < 4) {
+ return (AE_BAD_HEADER);
+ }
+
+ /* Read the signature */
+
+ fseek(fp, 0, SEEK_SET);
+
+ count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
+ if (count != sizeof(struct acpi_table_header)) {
+ acpi_os_printf("Could not read the table header\n");
+ return (AE_BAD_HEADER);
+ }
+
+ /* The RSDP table does not have standard ACPI header */
+
+ if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) {
+ *table_length = file_size;
+ standard_header = FALSE;
+ } else {
+
+#if 0
+ /* Validate the table header/length */
+
+ status = acpi_tb_validate_table_header(&table_header);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Table header is invalid!\n");
+ return (status);
+ }
+#endif
+
+ /* File size must be at least as long as the Header-specified length */
+
+ if (table_header.length > file_size) {
+ acpi_os_printf
+ ("TableHeader length [0x%X] greater than the input file size [0x%X]\n",
+ table_header.length, file_size);
+
+#ifdef ACPI_ASL_COMPILER
+ status = fl_check_for_ascii(fp, NULL, FALSE);
+ if (ACPI_SUCCESS(status)) {
+ acpi_os_printf
+ ("File appears to be ASCII only, must be binary\n");
+ }
+#endif
+ return (AE_BAD_HEADER);
+ }
+#ifdef ACPI_OBSOLETE_CODE
+ /* We only support a limited number of table types */
+
+ if (!ACPI_COMPARE_NAME
+ ((char *)table_header.signature, ACPI_SIG_DSDT)
+ && !ACPI_COMPARE_NAME((char *)table_header.signature,
+ ACPI_SIG_PSDT)
+ && !ACPI_COMPARE_NAME((char *)table_header.signature,
+ ACPI_SIG_SSDT)) {
+ acpi_os_printf
+ ("Table signature [%4.4s] is invalid or not supported\n",
+ (char *)table_header.signature);
+ ACPI_DUMP_BUFFER(&table_header,
+ sizeof(struct acpi_table_header));
+ return (AE_ERROR);
+ }
+#endif
+
+ *table_length = table_header.length;
+ }
+
+ /* Allocate a buffer for the table */
+
+ *table = acpi_os_allocate((size_t) file_size);
+ if (!*table) {
+ acpi_os_printf
+ ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
+ table_header.signature, *table_length);
+ return (AE_NO_MEMORY);
+ }
+
+ /* Get the rest of the table */
+
+ fseek(fp, 0, SEEK_SET);
+ actual = fread(*table, 1, (size_t) file_size, fp);
+ if (actual == file_size) {
+ if (standard_header) {
+
+ /* Now validate the checksum */
+
+ status = acpi_tb_verify_checksum((void *)*table,
+ ACPI_CAST_PTR(struct
+ acpi_table_header,
+ *table)->
+ length);
+
+ if (status == AE_BAD_CHECKSUM) {
+ status =
+ acpi_ut_check_text_mode_corruption((u8 *)
+ *table,
+ file_size,
+ (*table)->
+ length);
+ return (status);
+ }
+ }
+ return (AE_OK);
+ }
+
+ if (actual > 0) {
+ acpi_os_printf("Warning - reading table, asked for %X got %X\n",
+ file_size, actual);
+ return (AE_OK);
+ }
+
+ acpi_os_printf("Error - could not read the table file\n");
+ acpi_os_free(*table);
+ *table = NULL;
+ *table_length = 0;
+ return (AE_ERROR);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_read_table_from_file
+ *
+ * PARAMETERS: filename - File where table is located
+ * table - Where a pointer to the table is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get an ACPI table from a file
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
+{
+ FILE *file;
+ u32 file_size;
+ u32 table_length;
+ acpi_status status = AE_ERROR;
+
+ /* Open the file, get current size */
+
+ file = fopen(filename, "rb");
+ if (!file) {
+ perror("Could not open input file");
+ return (status);
+ }
+
+ file_size = cm_get_file_size(file);
+ if (file_size == ACPI_UINT32_MAX) {
+ goto exit;
+ }
+
+ /* Get the entire file */
+
+ fprintf(stderr,
+ "Loading Acpi table from file %10s - Length %.8u (%06X)\n",
+ filename, file_size, file_size);
+
+ status = acpi_ut_read_table(file, table, &table_length);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not get table from the file\n");
+ }
+
+exit:
+ fclose(file);
+ return (status);
+}
+
+#endif
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index d69be3cb3fae..77ceac715f28 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -214,152 +214,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
};
#endif /* !ACPI_REDUCED_HARDWARE */
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_init_globals
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Initialize ACPICA globals. All globals that require specific
- * initialization should be initialized here. This allows for
- * a warm restart.
- *
- ******************************************************************************/
-
-acpi_status acpi_ut_init_globals(void)
-{
- acpi_status status;
- u32 i;
-
- ACPI_FUNCTION_TRACE(ut_init_globals);
-
- /* Create all memory caches */
-
- status = acpi_ut_create_caches();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Address Range lists */
-
- for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
- acpi_gbl_address_range_list[i] = NULL;
- }
-
- /* Mutex locked flags */
-
- for (i = 0; i < ACPI_NUM_MUTEX; i++) {
- acpi_gbl_mutex_info[i].mutex = NULL;
- acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
- acpi_gbl_mutex_info[i].use_count = 0;
- }
-
- for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
- acpi_gbl_owner_id_mask[i] = 0;
- }
-
- /* Last owner_ID is never valid */
-
- acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
-
- /* Event counters */
-
- acpi_method_count = 0;
- acpi_sci_count = 0;
- acpi_gpe_count = 0;
-
- for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
- acpi_fixed_event_count[i] = 0;
- }
-
-#if (!ACPI_REDUCED_HARDWARE)
-
- /* GPE/SCI support */
-
- acpi_gbl_all_gpes_initialized = FALSE;
- acpi_gbl_gpe_xrupt_list_head = NULL;
- acpi_gbl_gpe_fadt_blocks[0] = NULL;
- acpi_gbl_gpe_fadt_blocks[1] = NULL;
- acpi_current_gpe_count = 0;
-
- acpi_gbl_global_event_handler = NULL;
- acpi_gbl_sci_handler_list = NULL;
-
-#endif /* !ACPI_REDUCED_HARDWARE */
-
- /* Global handlers */
-
- acpi_gbl_global_notify[0].handler = NULL;
- acpi_gbl_global_notify[1].handler = NULL;
- acpi_gbl_exception_handler = NULL;
- acpi_gbl_init_handler = NULL;
- acpi_gbl_table_handler = NULL;
- acpi_gbl_interface_handler = NULL;
-
- /* Global Lock support */
-
- acpi_gbl_global_lock_semaphore = NULL;
- acpi_gbl_global_lock_mutex = NULL;
- acpi_gbl_global_lock_acquired = FALSE;
- acpi_gbl_global_lock_handle = 0;
- acpi_gbl_global_lock_present = FALSE;
-
- /* Miscellaneous variables */
-
- acpi_gbl_DSDT = NULL;
- acpi_gbl_cm_single_step = FALSE;
- acpi_gbl_shutdown = FALSE;
- acpi_gbl_ns_lookup_count = 0;
- acpi_gbl_ps_find_count = 0;
- acpi_gbl_acpi_hardware_present = TRUE;
- acpi_gbl_last_owner_id_index = 0;
- acpi_gbl_next_owner_id_offset = 0;
- acpi_gbl_trace_dbg_level = 0;
- acpi_gbl_trace_dbg_layer = 0;
- acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
- acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
- acpi_gbl_osi_mutex = NULL;
- acpi_gbl_reg_methods_executed = FALSE;
-
- /* Hardware oriented */
-
- acpi_gbl_events_initialized = FALSE;
- acpi_gbl_system_awake_and_running = TRUE;
-
- /* Namespace */
-
- acpi_gbl_module_code_list = NULL;
- acpi_gbl_root_node = NULL;
- acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
- acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
- acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
- acpi_gbl_root_node_struct.parent = NULL;
- acpi_gbl_root_node_struct.child = NULL;
- acpi_gbl_root_node_struct.peer = NULL;
- acpi_gbl_root_node_struct.object = NULL;
-
-#ifdef ACPI_DISASSEMBLER
- acpi_gbl_external_list = NULL;
- acpi_gbl_num_external_methods = 0;
- acpi_gbl_resolved_external_methods = 0;
-#endif
-
-#ifdef ACPI_DEBUG_OUTPUT
- acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX);
-#endif
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- acpi_gbl_display_final_mem_stats = FALSE;
- acpi_gbl_disable_mem_tracking = FALSE;
-#endif
-
- ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
-
- return_ACPI_STATUS(AE_OK);
-}
-
/* Public globals */
ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c
new file mode 100644
index 000000000000..9afa9441b183
--- /dev/null
+++ b/drivers/acpi/acpica/uthex.c
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * Module Name: uthex -- Hex/ASCII support functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, 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_COMPILER
+ACPI_MODULE_NAME("uthex")
+
+/* Hex to ASCII conversion table */
+static char acpi_gbl_hex_to_ascii[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+ 'E', 'F'
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_hex_to_ascii_char
+ *
+ * PARAMETERS: integer - Contains the hex digit
+ * position - bit position of the digit within the
+ * integer (multiple of 4)
+ *
+ * RETURN: The converted Ascii character
+ *
+ * DESCRIPTION: Convert a hex digit to an Ascii character
+ *
+ ******************************************************************************/
+
+char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
+{
+
+ return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_hex_char_to_value
+ *
+ * PARAMETERS: ascii_char - Hex character in Ascii
+ *
+ * RETURN: The binary value of the ascii/hex character
+ *
+ * DESCRIPTION: Perform ascii-to-hex translation
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_ascii_char_to_hex(int hex_char)
+{
+
+ if (hex_char <= 0x39) {
+ return ((u8)(hex_char - 0x30));
+ }
+
+ if (hex_char <= 0x46) {
+ return ((u8)(hex_char - 0x37));
+ }
+
+ return ((u8)(hex_char - 0x57));
+}
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 5f56fc49021e..77120ec9ea86 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -102,6 +102,151 @@ static void acpi_ut_free_gpe_lists(void)
}
#endif /* !ACPI_REDUCED_HARDWARE */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_init_globals
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize ACPICA globals. All globals that require specific
+ * initialization should be initialized here. This allows for
+ * a warm restart.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_init_globals(void)
+{
+ acpi_status status;
+ u32 i;
+
+ ACPI_FUNCTION_TRACE(ut_init_globals);
+
+ /* Create all memory caches */
+
+ status = acpi_ut_create_caches();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Address Range lists */
+
+ for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+ acpi_gbl_address_range_list[i] = NULL;
+ }
+
+ /* Mutex locked flags */
+
+ for (i = 0; i < ACPI_NUM_MUTEX; i++) {
+ acpi_gbl_mutex_info[i].mutex = NULL;
+ acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+ acpi_gbl_mutex_info[i].use_count = 0;
+ }
+
+ for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) {
+ acpi_gbl_owner_id_mask[i] = 0;
+ }
+
+ /* Last owner_ID is never valid */
+
+ acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
+
+ /* Event counters */
+
+ acpi_method_count = 0;
+ acpi_sci_count = 0;
+ acpi_gpe_count = 0;
+
+ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+ acpi_fixed_event_count[i] = 0;
+ }
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+ /* GPE/SCI support */
+
+ acpi_gbl_all_gpes_initialized = FALSE;
+ acpi_gbl_gpe_xrupt_list_head = NULL;
+ acpi_gbl_gpe_fadt_blocks[0] = NULL;
+ acpi_gbl_gpe_fadt_blocks[1] = NULL;
+ acpi_current_gpe_count = 0;
+
+ acpi_gbl_global_event_handler = NULL;
+ acpi_gbl_sci_handler_list = NULL;
+
+#endif /* !ACPI_REDUCED_HARDWARE */
+
+ /* Global handlers */
+
+ acpi_gbl_global_notify[0].handler = NULL;
+ acpi_gbl_global_notify[1].handler = NULL;
+ acpi_gbl_exception_handler = NULL;
+ acpi_gbl_init_handler = NULL;
+ acpi_gbl_table_handler = NULL;
+ acpi_gbl_interface_handler = NULL;
+
+ /* Global Lock support */
+
+ acpi_gbl_global_lock_semaphore = NULL;
+ acpi_gbl_global_lock_mutex = NULL;
+ acpi_gbl_global_lock_acquired = FALSE;
+ acpi_gbl_global_lock_handle = 0;
+ acpi_gbl_global_lock_present = FALSE;
+
+ /* Miscellaneous variables */
+
+ acpi_gbl_DSDT = NULL;
+ acpi_gbl_cm_single_step = FALSE;
+ acpi_gbl_shutdown = FALSE;
+ acpi_gbl_ns_lookup_count = 0;
+ acpi_gbl_ps_find_count = 0;
+ acpi_gbl_acpi_hardware_present = TRUE;
+ acpi_gbl_last_owner_id_index = 0;
+ acpi_gbl_next_owner_id_offset = 0;
+ acpi_gbl_trace_dbg_level = 0;
+ acpi_gbl_trace_dbg_layer = 0;
+ acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
+ acpi_gbl_osi_mutex = NULL;
+ acpi_gbl_reg_methods_executed = FALSE;
+
+ /* Hardware oriented */
+
+ acpi_gbl_events_initialized = FALSE;
+ acpi_gbl_system_awake_and_running = TRUE;
+
+ /* Namespace */
+
+ acpi_gbl_module_code_list = NULL;
+ acpi_gbl_root_node = NULL;
+ acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
+ acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
+ acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
+ acpi_gbl_root_node_struct.parent = NULL;
+ acpi_gbl_root_node_struct.child = NULL;
+ acpi_gbl_root_node_struct.peer = NULL;
+ acpi_gbl_root_node_struct.object = NULL;
+
+#ifdef ACPI_DISASSEMBLER
+ acpi_gbl_external_list = NULL;
+ acpi_gbl_num_external_methods = 0;
+ acpi_gbl_resolved_external_methods = 0;
+#endif
+
+#ifdef ACPI_DEBUG_OUTPUT
+ acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX);
+#endif
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ acpi_gbl_display_final_mem_stats = FALSE;
+ acpi_gbl_disable_mem_tracking = FALSE;
+#endif
+
+ ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
+
+ return_ACPI_STATUS(AE_OK);
+}
+
/******************************************************************************
*
* FUNCTION: acpi_ut_terminate
diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c
new file mode 100644
index 000000000000..0ce3f5a0dd67
--- /dev/null
+++ b/drivers/acpi/acpica/utprint.c
@@ -0,0 +1,664 @@
+/******************************************************************************
+ *
+ * Module Name: utprint - Formatted printing routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, 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("utprint")
+
+#define ACPI_FORMAT_SIGN 0x01
+#define ACPI_FORMAT_SIGN_PLUS 0x02
+#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
+#define ACPI_FORMAT_ZERO 0x08
+#define ACPI_FORMAT_LEFT 0x10
+#define ACPI_FORMAT_UPPER 0x20
+#define ACPI_FORMAT_PREFIX 0x40
+/* Local prototypes */
+static acpi_size
+acpi_ut_bound_string_length(const char *string, acpi_size count);
+
+static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
+
+static char *acpi_ut_format_number(char *string,
+ char *end,
+ u64 number,
+ u8 base, s32 width, s32 precision, u8 type);
+
+static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
+
+/* Module globals */
+
+static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
+static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_bound_string_length
+ *
+ * PARAMETERS: string - String with boundary
+ * count - Boundary of the string
+ *
+ * RETURN: Length of the string. Less than or equal to Count.
+ *
+ * DESCRIPTION: Calculate the length of a string with boundary.
+ *
+ ******************************************************************************/
+
+static acpi_size
+acpi_ut_bound_string_length(const char *string, acpi_size count)
+{
+ u32 length = 0;
+
+ while (*string && count) {
+ length++;
+ string++;
+ count--;
+ }
+
+ return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_bound_string_output
+ *
+ * PARAMETERS: string - String with boundary
+ * end - Boundary of the string
+ * c - Character to be output to the string
+ *
+ * RETURN: Updated position for next valid character
+ *
+ * DESCRIPTION: Output a character into a string with boundary check.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
+{
+
+ if (string < end) {
+ *string = c;
+ }
+
+ ++string;
+ return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_put_number
+ *
+ * PARAMETERS: string - Buffer to hold reverse-ordered string
+ * number - Integer to be converted
+ * base - Base of the integer
+ * upper - Whether or not using upper cased digits
+ *
+ * RETURN: Updated position for next valid character
+ *
+ * DESCRIPTION: Convert an integer into a string, note that, the string holds a
+ * reversed ordered number without the trailing zero.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
+{
+ const char *digits;
+ u64 digit_index;
+ char *pos;
+
+ pos = string;
+ digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
+
+ if (number == 0) {
+ *(pos++) = '0';
+ } else {
+ while (number) {
+ (void)acpi_ut_divide(number, base, &number,
+ &digit_index);
+ *(pos++) = digits[digit_index];
+ }
+ }
+
+ /* *(Pos++) = '0'; */
+ return (pos);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_scan_number
+ *
+ * PARAMETERS: string - String buffer
+ * number_ptr - Where the number is returned
+ *
+ * RETURN: Updated position for next valid character
+ *
+ * DESCRIPTION: Scan a string for a decimal integer.
+ *
+ ******************************************************************************/
+
+const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
+{
+ u64 number = 0;
+
+ while (ACPI_IS_DIGIT(*string)) {
+ number *= 10;
+ number += *(string++) - '0';
+ }
+
+ *number_ptr = number;
+ return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_print_number
+ *
+ * PARAMETERS: string - String buffer
+ * number - The number to be converted
+ *
+ * RETURN: Updated position for next valid character
+ *
+ * DESCRIPTION: Print a decimal integer into a string.
+ *
+ ******************************************************************************/
+
+const char *acpi_ut_print_number(char *string, u64 number)
+{
+ char ascii_string[20];
+ const char *pos1;
+ char *pos2;
+
+ pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
+ pos2 = string;
+
+ while (pos1 != ascii_string) {
+ *(pos2++) = *(--pos1);
+ }
+
+ *pos2 = 0;
+ return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_format_number
+ *
+ * PARAMETERS: string - String buffer with boundary
+ * end - Boundary of the string
+ * number - The number to be converted
+ * base - Base of the integer
+ * width - Field width
+ * precision - Precision of the integer
+ * type - Special printing flags
+ *
+ * RETURN: Updated position for next valid character
+ *
+ * DESCRIPTION: Print an integer into a string with any base and any precision.
+ *
+ ******************************************************************************/
+
+static char *acpi_ut_format_number(char *string,
+ char *end,
+ u64 number,
+ u8 base, s32 width, s32 precision, u8 type)
+{
+ char *pos;
+ char sign;
+ char zero;
+ u8 need_prefix;
+ u8 upper;
+ s32 i;
+ char reversed_string[66];
+
+ /* Parameter validation */
+
+ if (base < 2 || base > 16) {
+ return (NULL);
+ }
+
+ if (type & ACPI_FORMAT_LEFT) {
+ type &= ~ACPI_FORMAT_ZERO;
+ }
+
+ need_prefix = ((type & ACPI_FORMAT_PREFIX)
+ && base != 10) ? TRUE : FALSE;
+ upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
+ zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
+
+ /* Calculate size according to sign and prefix */
+
+ sign = '\0';
+ if (type & ACPI_FORMAT_SIGN) {
+ if ((s64) number < 0) {
+ sign = '-';
+ number = -(s64) number;
+ width--;
+ } else if (type & ACPI_FORMAT_SIGN_PLUS) {
+ sign = '+';
+ width--;
+ } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
+ sign = ' ';
+ width--;
+ }
+ }
+ if (need_prefix) {
+ width--;
+ if (base == 16) {
+ width--;
+ }
+ }
+
+ /* Generate full string in reverse order */
+
+ pos = acpi_ut_put_number(reversed_string, number, base, upper);
+ i = ACPI_PTR_DIFF(pos, reversed_string);
+
+ /* Printing 100 using %2d gives "100", not "00" */
+
+ if (i > precision) {
+ precision = i;
+ }
+
+ width -= precision;
+
+ /* Output the string */
+
+ if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
+ while (--width >= 0) {
+ string = acpi_ut_bound_string_output(string, end, ' ');
+ }
+ }
+ if (sign) {
+ string = acpi_ut_bound_string_output(string, end, sign);
+ }
+ if (need_prefix) {
+ string = acpi_ut_bound_string_output(string, end, '0');
+ if (base == 16) {
+ string = acpi_ut_bound_string_output(string, end,
+ upper ? 'X' : 'x');
+ }
+ }
+ if (!(type & ACPI_FORMAT_LEFT)) {
+ while (--width >= 0) {
+ string = acpi_ut_bound_string_output(string, end, zero);
+ }
+ }
+
+ while (i <= --precision) {
+ string = acpi_ut_bound_string_output(string, end, '0');
+ }
+ while (--i >= 0) {
+ string = acpi_ut_bound_string_output(string, end,
+ reversed_string[i]);
+ }
+ while (--width >= 0) {
+ string = acpi_ut_bound_string_output(string, end, ' ');
+ }
+
+ return (string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_vsnprintf
+ *
+ * PARAMETERS: string - String with boundary
+ * size - Boundary of the string
+ * format - Standard printf format
+ * args - Argument list
+ *
+ * RETURN: Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a string using argument list pointer.
+ *
+ ******************************************************************************/
+
+int
+acpi_ut_vsnprintf(char *string,
+ acpi_size size, const char *format, va_list args)
+{
+ u8 base = 10;
+ u8 type = 0;
+ s32 width = -1;
+ s32 precision = -1;
+ char qualifier = 0;
+ u64 number;
+ char *pos;
+ char *end;
+ char c;
+ const char *s;
+ const void *p;
+ s32 length;
+ int i;
+
+ pos = string;
+ end = string + size;
+
+ for (; *format; ++format) {
+ if (*format != '%') {
+ pos = acpi_ut_bound_string_output(pos, end, *format);
+ continue;
+ }
+
+ /* Process sign */
+
+ do {
+ ++format;
+ if (*format == '#') {
+ type |= ACPI_FORMAT_PREFIX;
+ } else if (*format == '0') {
+ type |= ACPI_FORMAT_ZERO;
+ } else if (*format == '+') {
+ type |= ACPI_FORMAT_SIGN_PLUS;
+ } else if (*format == ' ') {
+ type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
+ } else if (*format == '-') {
+ type |= ACPI_FORMAT_LEFT;
+ } else {
+ break;
+ }
+ } while (1);
+
+ /* Process width */
+
+ width = -1;
+ if (ACPI_IS_DIGIT(*format)) {
+ format = acpi_ut_scan_number(format, &number);
+ width = (s32) number;
+ } else if (*format == '*') {
+ ++format;
+ width = va_arg(args, int);
+ if (width < 0) {
+ width = -width;
+ type |= ACPI_FORMAT_LEFT;
+ }
+ }
+
+ /* Process precision */
+
+ precision = -1;
+ if (*format == '.') {
+ ++format;
+ if (ACPI_IS_DIGIT(*format)) {
+ format = acpi_ut_scan_number(format, &number);
+ precision = (s32) number;
+ } else if (*format == '*') {
+ ++format;
+ precision = va_arg(args, int);
+ }
+ if (precision < 0) {
+ precision = 0;
+ }
+ }
+
+ /* Process qualifier */
+
+ qualifier = -1;
+ if (*format == 'h' || *format == 'l' || *format == 'L') {
+ qualifier = *format;
+ ++format;
+
+ if (qualifier == 'l' && *format == 'l') {
+ qualifier = 'L';
+ ++format;
+ }
+ }
+
+ switch (*format) {
+ case '%':
+
+ pos = acpi_ut_bound_string_output(pos, end, '%');
+ continue;
+
+ case 'c':
+
+ if (!(type & ACPI_FORMAT_LEFT)) {
+ while (--width > 0) {
+ pos =
+ acpi_ut_bound_string_output(pos,
+ end,
+ ' ');
+ }
+ }
+
+ c = (char)va_arg(args, int);
+ pos = acpi_ut_bound_string_output(pos, end, c);
+
+ while (--width > 0) {
+ pos =
+ acpi_ut_bound_string_output(pos, end, ' ');
+ }
+ continue;
+
+ case 's':
+
+ s = va_arg(args, char *);
+ if (!s) {
+ s = "<NULL>";
+ }
+ length = acpi_ut_bound_string_length(s, precision);
+ if (!(type & ACPI_FORMAT_LEFT)) {
+ while (length < width--) {
+ pos =
+ acpi_ut_bound_string_output(pos,
+ end,
+ ' ');
+ }
+ }
+ for (i = 0; i < length; ++i) {
+ pos = acpi_ut_bound_string_output(pos, end, *s);
+ ++s;
+ }
+ while (length < width--) {
+ pos =
+ acpi_ut_bound_string_output(pos, end, ' ');
+ }
+ continue;
+
+ case 'o':
+
+ base = 8;
+ break;
+
+ case 'X':
+
+ type |= ACPI_FORMAT_UPPER;
+
+ case 'x':
+
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+
+ type |= ACPI_FORMAT_SIGN;
+
+ case 'u':
+
+ break;
+
+ case 'p':
+
+ if (width == -1) {
+ width = 2 * sizeof(void *);
+ type |= ACPI_FORMAT_ZERO;
+ }
+
+ p = va_arg(args, void *);
+ pos = acpi_ut_format_number(pos, end,
+ ACPI_TO_INTEGER(p), 16,
+ width, precision, type);
+ continue;
+
+ default:
+
+ pos = acpi_ut_bound_string_output(pos, end, '%');
+ if (*format) {
+ pos =
+ acpi_ut_bound_string_output(pos, end,
+ *format);
+ } else {
+ --format;
+ }
+ continue;
+ }
+
+ if (qualifier == 'L') {
+ number = va_arg(args, u64);
+ if (type & ACPI_FORMAT_SIGN) {
+ number = (s64) number;
+ }
+ } else if (qualifier == 'l') {
+ number = va_arg(args, unsigned long);
+ if (type & ACPI_FORMAT_SIGN) {
+ number = (s32) number;
+ }
+ } else if (qualifier == 'h') {
+ number = (u16)va_arg(args, int);
+ if (type & ACPI_FORMAT_SIGN) {
+ number = (s16) number;
+ }
+ } else {
+ number = va_arg(args, unsigned int);
+ if (type & ACPI_FORMAT_SIGN) {
+ number = (signed int)number;
+ }
+ }
+
+ pos = acpi_ut_format_number(pos, end, number, base,
+ width, precision, type);
+ }
+
+ if (size > 0) {
+ if (pos < end) {
+ *pos = '\0';
+ } else {
+ end[-1] = '\0';
+ }
+ }
+
+ return (ACPI_PTR_DIFF(pos, string));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_snprintf
+ *
+ * PARAMETERS: string - String with boundary
+ * size - Boundary of the string
+ * Format, ... - Standard printf format
+ *
+ * RETURN: Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a string.
+ *
+ ******************************************************************************/
+
+int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
+{
+ va_list args;
+ int length;
+
+ va_start(args, format);
+ length = acpi_ut_vsnprintf(string, size, format, args);
+ va_end(args);
+
+ return (length);
+}
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_file_vprintf
+ *
+ * PARAMETERS: file - File descriptor
+ * format - Standard printf format
+ * args - Argument list
+ *
+ * RETURN: Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a file using argument list pointer.
+ *
+ ******************************************************************************/
+
+int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
+{
+ acpi_cpu_flags flags;
+ int length;
+
+ flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
+ length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
+ sizeof(acpi_gbl_print_buffer), format, args);
+
+ (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
+ acpi_os_release_lock(acpi_gbl_print_lock, flags);
+
+ return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_file_printf
+ *
+ * PARAMETERS: file - File descriptor
+ * Format, ... - Standard printf format
+ *
+ * RETURN: Number of bytes actually written.
+ *
+ * DESCRIPTION: Formatted output to a file.
+ *
+ ******************************************************************************/
+
+int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
+{
+ va_list args;
+ int length;
+
+ va_start(args, format);
+ length = acpi_ut_file_vprintf(file, format, args);
+ va_end(args);
+
+ return (length);
+}
+#endif
diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c
new file mode 100644
index 000000000000..4dc33130f134
--- /dev/null
+++ b/drivers/acpi/acpica/utuuid.c
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Module Name: utuuid -- UUID support functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2014, 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_COMPILER
+ACPI_MODULE_NAME("utuuid")
+
+/*
+ * UUID support functions.
+ *
+ * This table is used to convert an input UUID ascii string to a 16 byte
+ * buffer and the reverse. The table maps a UUID buffer index 0-15 to
+ * the index within the 36-byte UUID string where the associated 2-byte
+ * hex value can be found.
+ *
+ * 36-byte UUID strings are of the form:
+ * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
+ * Where aa-pp are one byte hex numbers, made up of two hex digits
+ *
+ * Note: This table is basically the inverse of the string-to-offset table
+ * found in the ACPI spec in the description of the to_UUID macro.
+ */
+const u8 acpi_gbl_map_to_uuid_offset[UUID_BUFFER_LENGTH] = {
+ 6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_convert_string_to_uuid
+ *
+ * PARAMETERS: in_string - 36-byte formatted UUID string
+ * uuid_buffer - Where the 16-byte UUID buffer is returned
+ *
+ * RETURN: None. Output data is returned in the uuid_buffer
+ *
+ * DESCRIPTION: Convert a 36-byte formatted UUID string to 16-byte UUID buffer
+ *
+ ******************************************************************************/
+
+void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer)
+{
+ u32 i;
+
+ for (i = 0; i < UUID_BUFFER_LENGTH; i++) {
+ uuid_buffer[i] =
+ (acpi_ut_ascii_char_to_hex
+ (in_string[acpi_gbl_map_to_uuid_offset[i]]) << 4);
+
+ uuid_buffer[i] |=
+ acpi_ut_ascii_char_to_hex(in_string
+ [acpi_gbl_map_to_uuid_offset[i] +
+ 1]);
+ }
+}
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index c4dac7150960..b0140c8fc733 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -1,9 +1,15 @@
+config HAVE_ACPI_APEI
+ bool
+
+config HAVE_ACPI_APEI_NMI
+ bool
+
config ACPI_APEI
bool "ACPI Platform Error Interface (APEI)"
select MISC_FILESYSTEMS
select PSTORE
select UEFI_CPER
- depends on X86
+ depends on HAVE_ACPI_APEI
help
APEI allows to report errors (for example from the chipset)
to the operating system. This improves NMI handling
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 8678dfe5366b..2cd7bdd6c8b3 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -745,6 +745,19 @@ struct dentry *apei_get_debugfs_dir(void)
}
EXPORT_SYMBOL_GPL(apei_get_debugfs_dir);
+int __weak arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr,
+ void *data)
+{
+ return 1;
+}
+EXPORT_SYMBOL_GPL(arch_apei_enable_cmcff);
+
+void __weak arch_apei_report_mem_error(int sev,
+ struct cper_sec_mem_err *mem_err)
+{
+}
+EXPORT_SYMBOL_GPL(arch_apei_report_mem_error);
+
int apei_osc_setup(void)
{
static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c";
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index e5bcd919d4e6..16129c78b489 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -121,11 +121,11 @@ struct dentry;
struct dentry *apei_get_debugfs_dir(void);
#define apei_estatus_for_each_section(estatus, section) \
- for (section = (struct acpi_generic_data *)(estatus + 1); \
+ for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
(void *)section - (void *)estatus < estatus->data_length; \
section = (void *)(section+1) + section->error_data_length)
-static inline u32 cper_estatus_len(struct acpi_generic_status *estatus)
+static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus)
{
if (estatus->raw_data_length)
return estatus->raw_data_offset + \
@@ -135,9 +135,9 @@ static inline u32 cper_estatus_len(struct acpi_generic_status *estatus)
}
void cper_estatus_print(const char *pfx,
- const struct acpi_generic_status *estatus);
-int cper_estatus_check_header(const struct acpi_generic_status *estatus);
-int cper_estatus_check(const struct acpi_generic_status *estatus);
+ const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus);
+int cper_estatus_check(const struct acpi_hest_generic_status *estatus);
int apei_osc_setup(void);
#endif
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index dab7cb7349df..fc5f780bb61d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -47,11 +47,11 @@
#include <linux/genalloc.h>
#include <linux/pci.h>
#include <linux/aer.h>
+#include <linux/nmi.h>
#include <acpi/ghes.h>
-#include <asm/mce.h>
+#include <acpi/apei.h>
#include <asm/tlbflush.h>
-#include <asm/nmi.h>
#include "apei-internal.h"
@@ -74,20 +74,18 @@
#define GHES_ESTATUS_CACHE_LEN(estatus_len) \
(sizeof(struct ghes_estatus_cache) + (estatus_len))
#define GHES_ESTATUS_FROM_CACHE(estatus_cache) \
- ((struct acpi_generic_status *) \
+ ((struct acpi_hest_generic_status *) \
((struct ghes_estatus_cache *)(estatus_cache) + 1))
#define GHES_ESTATUS_NODE_LEN(estatus_len) \
(sizeof(struct ghes_estatus_node) + (estatus_len))
#define GHES_ESTATUS_FROM_NODE(estatus_node) \
- ((struct acpi_generic_status *) \
+ ((struct acpi_hest_generic_status *) \
((struct ghes_estatus_node *)(estatus_node) + 1))
bool ghes_disable;
module_param_named(disable, ghes_disable, bool, 0);
-static int ghes_panic_timeout __read_mostly = 30;
-
/*
* All error sources notified with SCI shares one notifier function,
* so they need to be linked and checked one by one. This is applied
@@ -97,16 +95,9 @@ static int ghes_panic_timeout __read_mostly = 30;
* list changing, not for traversing.
*/
static LIST_HEAD(ghes_sci);
-static LIST_HEAD(ghes_nmi);
static DEFINE_MUTEX(ghes_list_mutex);
/*
- * NMI may be triggered on any CPU, so ghes_nmi_lock is used for
- * mutual exclusion.
- */
-static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
-
-/*
* Because the memory area used to transfer hardware error information
* from BIOS to Linux can be determined only in NMI, IRQ or timer
* handler, but general ioremap can not be used in atomic context, so
@@ -114,12 +105,16 @@ static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
*/
/*
- * Two virtual pages are used, one for NMI context, the other for
- * IRQ/PROCESS context
+ * Two virtual pages are used, one for IRQ/PROCESS context, the other for
+ * NMI context (optionally).
*/
-#define GHES_IOREMAP_PAGES 2
-#define GHES_IOREMAP_NMI_PAGE(base) (base)
-#define GHES_IOREMAP_IRQ_PAGE(base) ((base) + PAGE_SIZE)
+#ifdef CONFIG_HAVE_ACPI_APEI_NMI
+#define GHES_IOREMAP_PAGES 2
+#else
+#define GHES_IOREMAP_PAGES 1
+#endif
+#define GHES_IOREMAP_IRQ_PAGE(base) (base)
+#define GHES_IOREMAP_NMI_PAGE(base) ((base) + PAGE_SIZE)
/* virtual memory area for atomic ioremap */
static struct vm_struct *ghes_ioremap_area;
@@ -130,18 +125,8 @@ static struct vm_struct *ghes_ioremap_area;
static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
-/*
- * printk is not safe in NMI context. So in NMI handler, we allocate
- * required memory from lock-less memory allocator
- * (ghes_estatus_pool), save estatus into it, put them into lock-less
- * list (ghes_estatus_llist), then delay printk into IRQ context via
- * irq_work (ghes_proc_irq_work). ghes_estatus_size_request record
- * required pool size by all NMI error source.
- */
static struct gen_pool *ghes_estatus_pool;
static unsigned long ghes_estatus_pool_size_request;
-static struct llist_head ghes_estatus_llist;
-static struct irq_work ghes_proc_irq_work;
struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
@@ -192,7 +177,7 @@ static void ghes_iounmap_nmi(void __iomem *vaddr_ptr)
BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
- __flush_tlb_one(vaddr);
+ arch_apei_flush_tlb_one(vaddr);
}
static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
@@ -202,7 +187,7 @@ static void ghes_iounmap_irq(void __iomem *vaddr_ptr)
BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
- __flush_tlb_one(vaddr);
+ arch_apei_flush_tlb_one(vaddr);
}
static int ghes_estatus_pool_init(void)
@@ -249,11 +234,6 @@ static int ghes_estatus_pool_expand(unsigned long len)
return 0;
}
-static void ghes_estatus_pool_shrink(unsigned long len)
-{
- ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
-}
-
static struct ghes *ghes_new(struct acpi_hest_generic *generic)
{
struct ghes *ghes;
@@ -408,7 +388,7 @@ static void ghes_clear_estatus(struct ghes *ghes)
ghes->flags &= ~GHES_TO_CLEAR;
}
-static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
+static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
{
#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
unsigned long pfn;
@@ -441,10 +421,10 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
}
static void ghes_do_proc(struct ghes *ghes,
- const struct acpi_generic_status *estatus)
+ const struct acpi_hest_generic_status *estatus)
{
int sev, sec_sev;
- struct acpi_generic_data *gdata;
+ struct acpi_hest_generic_data *gdata;
sev = ghes_severity(estatus->error_severity);
apei_estatus_for_each_section(estatus, gdata) {
@@ -455,9 +435,7 @@ static void ghes_do_proc(struct ghes *ghes,
mem_err = (struct cper_sec_mem_err *)(gdata+1);
ghes_edac_report_mem_error(ghes, sev, mem_err);
-#ifdef CONFIG_X86_MCE
- apei_mce_report_mem_error(sev, mem_err);
-#endif
+ arch_apei_report_mem_error(sev, mem_err);
ghes_handle_memory_failure(gdata, sev);
}
#ifdef CONFIG_ACPI_APEI_PCIEAER
@@ -498,7 +476,7 @@ static void ghes_do_proc(struct ghes *ghes,
static void __ghes_print_estatus(const char *pfx,
const struct acpi_hest_generic *generic,
- const struct acpi_generic_status *estatus)
+ const struct acpi_hest_generic_status *estatus)
{
static atomic_t seqno;
unsigned int curr_seqno;
@@ -520,7 +498,7 @@ static void __ghes_print_estatus(const char *pfx,
static int ghes_print_estatus(const char *pfx,
const struct acpi_hest_generic *generic,
- const struct acpi_generic_status *estatus)
+ const struct acpi_hest_generic_status *estatus)
{
/* Not more than 2 messages every 5 seconds */
static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -542,13 +520,13 @@ static int ghes_print_estatus(const char *pfx,
* GHES error status reporting throttle, to report more kinds of
* errors, instead of just most frequently occurred errors.
*/
-static int ghes_estatus_cached(struct acpi_generic_status *estatus)
+static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus)
{
u32 len;
int i, cached = 0;
unsigned long long now;
struct ghes_estatus_cache *cache;
- struct acpi_generic_status *cache_estatus;
+ struct acpi_hest_generic_status *cache_estatus;
len = cper_estatus_len(estatus);
rcu_read_lock();
@@ -573,12 +551,12 @@ static int ghes_estatus_cached(struct acpi_generic_status *estatus)
static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
struct acpi_hest_generic *generic,
- struct acpi_generic_status *estatus)
+ struct acpi_hest_generic_status *estatus)
{
int alloced;
u32 len, cache_len;
struct ghes_estatus_cache *cache;
- struct acpi_generic_status *cache_estatus;
+ struct acpi_hest_generic_status *cache_estatus;
alloced = atomic_add_return(1, &ghes_estatus_cache_alloced);
if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) {
@@ -621,7 +599,7 @@ static void ghes_estatus_cache_rcu_free(struct rcu_head *head)
static void ghes_estatus_cache_add(
struct acpi_hest_generic *generic,
- struct acpi_generic_status *estatus)
+ struct acpi_hest_generic_status *estatus)
{
int i, slot = -1, count;
unsigned long long now, duration, period, max_period = 0;
@@ -734,6 +712,32 @@ static int ghes_notify_sci(struct notifier_block *this,
return ret;
}
+static struct notifier_block ghes_notifier_sci = {
+ .notifier_call = ghes_notify_sci,
+};
+
+#ifdef CONFIG_HAVE_ACPI_APEI_NMI
+/*
+ * printk is not safe in NMI context. So in NMI handler, we allocate
+ * required memory from lock-less memory allocator
+ * (ghes_estatus_pool), save estatus into it, put them into lock-less
+ * list (ghes_estatus_llist), then delay printk into IRQ context via
+ * irq_work (ghes_proc_irq_work). ghes_estatus_size_request record
+ * required pool size by all NMI error source.
+ */
+static struct llist_head ghes_estatus_llist;
+static struct irq_work ghes_proc_irq_work;
+
+/*
+ * NMI may be triggered on any CPU, so ghes_nmi_lock is used for
+ * mutual exclusion.
+ */
+static DEFINE_RAW_SPINLOCK(ghes_nmi_lock);
+
+static LIST_HEAD(ghes_nmi);
+
+static int ghes_panic_timeout __read_mostly = 30;
+
static struct llist_node *llist_nodes_reverse(struct llist_node *llnode)
{
struct llist_node *next, *tail = NULL;
@@ -753,7 +757,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
struct llist_node *llnode, *next;
struct ghes_estatus_node *estatus_node;
struct acpi_hest_generic *generic;
- struct acpi_generic_status *estatus;
+ struct acpi_hest_generic_status *estatus;
u32 len, node_len;
llnode = llist_del_all(&ghes_estatus_llist);
@@ -786,7 +790,7 @@ static void ghes_print_queued_estatus(void)
struct llist_node *llnode;
struct ghes_estatus_node *estatus_node;
struct acpi_hest_generic *generic;
- struct acpi_generic_status *estatus;
+ struct acpi_hest_generic_status *estatus;
u32 len, node_len;
llnode = llist_del_all(&ghes_estatus_llist);
@@ -845,7 +849,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
u32 len, node_len;
struct ghes_estatus_node *estatus_node;
- struct acpi_generic_status *estatus;
+ struct acpi_hest_generic_status *estatus;
#endif
if (!(ghes->flags & GHES_TO_CLEAR))
continue;
@@ -877,10 +881,6 @@ out:
return ret;
}
-static struct notifier_block ghes_notifier_sci = {
- .notifier_call = ghes_notify_sci,
-};
-
static unsigned long ghes_esource_prealloc_size(
const struct acpi_hest_generic *generic)
{
@@ -896,11 +896,71 @@ static unsigned long ghes_esource_prealloc_size(
return prealloc_size;
}
+static void ghes_estatus_pool_shrink(unsigned long len)
+{
+ ghes_estatus_pool_size_request -= PAGE_ALIGN(len);
+}
+
+static void ghes_nmi_add(struct ghes *ghes)
+{
+ unsigned long len;
+
+ len = ghes_esource_prealloc_size(ghes->generic);
+ ghes_estatus_pool_expand(len);
+ mutex_lock(&ghes_list_mutex);
+ if (list_empty(&ghes_nmi))
+ register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, "ghes");
+ list_add_rcu(&ghes->list, &ghes_nmi);
+ mutex_unlock(&ghes_list_mutex);
+}
+
+static void ghes_nmi_remove(struct ghes *ghes)
+{
+ unsigned long len;
+
+ mutex_lock(&ghes_list_mutex);
+ list_del_rcu(&ghes->list);
+ if (list_empty(&ghes_nmi))
+ unregister_nmi_handler(NMI_LOCAL, "ghes");
+ mutex_unlock(&ghes_list_mutex);
+ /*
+ * To synchronize with NMI handler, ghes can only be
+ * freed after NMI handler finishes.
+ */
+ synchronize_rcu();
+ len = ghes_esource_prealloc_size(ghes->generic);
+ ghes_estatus_pool_shrink(len);
+}
+
+static void ghes_nmi_init_cxt(void)
+{
+ init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
+}
+#else /* CONFIG_HAVE_ACPI_APEI_NMI */
+static inline void ghes_nmi_add(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to add NMI notification which is not supported!\n",
+ ghes->generic->header.source_id);
+ BUG();
+}
+
+static inline void ghes_nmi_remove(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to remove NMI notification which is not supported!\n",
+ ghes->generic->header.source_id);
+ BUG();
+}
+
+static inline void ghes_nmi_init_cxt(void)
+{
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_NMI */
+
static int ghes_probe(struct platform_device *ghes_dev)
{
struct acpi_hest_generic *generic;
struct ghes *ghes = NULL;
- unsigned long len;
+
int rc = -EINVAL;
generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data;
@@ -911,7 +971,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_POLLED:
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
+ break;
case ACPI_HEST_NOTIFY_NMI:
+ if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
+ generic->header.source_id);
+ goto err;
+ }
break;
case ACPI_HEST_NOTIFY_LOCAL:
pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
@@ -925,7 +991,7 @@ static int ghes_probe(struct platform_device *ghes_dev)
rc = -EIO;
if (generic->error_block_length <
- sizeof(struct acpi_generic_status)) {
+ sizeof(struct acpi_hest_generic_status)) {
pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n",
generic->error_block_length,
generic->header.source_id);
@@ -972,14 +1038,7 @@ static int ghes_probe(struct platform_device *ghes_dev)
mutex_unlock(&ghes_list_mutex);
break;
case ACPI_HEST_NOTIFY_NMI:
- len = ghes_esource_prealloc_size(generic);
- ghes_estatus_pool_expand(len);
- mutex_lock(&ghes_list_mutex);
- if (list_empty(&ghes_nmi))
- register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
- "ghes");
- list_add_rcu(&ghes->list, &ghes_nmi);
- mutex_unlock(&ghes_list_mutex);
+ ghes_nmi_add(ghes);
break;
default:
BUG();
@@ -1001,7 +1060,6 @@ static int ghes_remove(struct platform_device *ghes_dev)
{
struct ghes *ghes;
struct acpi_hest_generic *generic;
- unsigned long len;
ghes = platform_get_drvdata(ghes_dev);
generic = ghes->generic;
@@ -1022,18 +1080,7 @@ static int ghes_remove(struct platform_device *ghes_dev)
mutex_unlock(&ghes_list_mutex);
break;
case ACPI_HEST_NOTIFY_NMI:
- mutex_lock(&ghes_list_mutex);
- list_del_rcu(&ghes->list);
- if (list_empty(&ghes_nmi))
- unregister_nmi_handler(NMI_LOCAL, "ghes");
- mutex_unlock(&ghes_list_mutex);
- /*
- * To synchronize with NMI handler, ghes can only be
- * freed after NMI handler finishes.
- */
- synchronize_rcu();
- len = ghes_esource_prealloc_size(generic);
- ghes_estatus_pool_shrink(len);
+ ghes_nmi_remove(ghes);
break;
default:
BUG();
@@ -1077,7 +1124,7 @@ static int __init ghes_init(void)
return -EINVAL;
}
- init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
+ ghes_nmi_init_cxt();
rc = ghes_ioremap_init();
if (rc)
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index f5e37f32c71f..06e9b411a0a2 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -36,7 +36,6 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <acpi/apei.h>
-#include <asm/mce.h>
#include "apei-internal.h"
@@ -128,33 +127,7 @@ EXPORT_SYMBOL_GPL(apei_hest_parse);
*/
static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
{
-#ifdef CONFIG_X86_MCE
- int i;
- struct acpi_hest_ia_corrected *cmc;
- struct acpi_hest_ia_error_bank *mc_bank;
-
- if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
- return 0;
-
- cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
- if (!cmc->enabled)
- return 0;
-
- /*
- * We expect HEST to provide a list of MC banks that report errors
- * in firmware first mode. Otherwise, return non-zero value to
- * indicate that we are done parsing HEST.
- */
- if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) || !cmc->num_hardware_banks)
- return 1;
-
- pr_info(HEST_PFX "Enabling Firmware First mode for corrected errors.\n");
-
- mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1);
- for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++)
- mce_disable_bank(mc_bank->bank_number);
-#endif
- return 1;
+ return arch_apei_enable_cmcff(hest_hdr, data);
}
struct ghes_arr {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 130f513e08c9..1c162e7be045 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -35,7 +35,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/suspend.h>
-#include <linux/delay.h>
#include <asm/unaligned.h>
#ifdef CONFIG_ACPI_PROCFS_POWER
@@ -541,12 +540,12 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
*/
if (battery->capacity_now > battery->full_charge_capacity
&& battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) {
- battery->capacity_now = battery->full_charge_capacity;
if (battery->capacity_now != battery->design_capacity)
printk_once(KERN_WARNING FW_BUG
"battery: reported current charge level (%d) "
"is higher than reported maximum charge level (%d).\n",
battery->capacity_now, battery->full_charge_capacity);
+ battery->capacity_now = battery->full_charge_capacity;
}
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 3d8413d02a97..36eb42e3b0bb 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -247,75 +247,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
/*
- * The following machines have broken backlight support when reporting
- * the Windows 2012 OSI, so disable it until their support is fixed.
+ * These machines will power on immediately after shutdown when
+ * reporting the Windows 2012 OSI.
*/
{
.callback = dmi_disable_osi_win8,
- .ident = "ASUS Zenbook Prime UX31A",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "ThinkPad Edge E530",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "Acer Aspire V5-573G",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "Acer Aspire V5-572G",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "ThinkPad T431s",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
- .ident = "ThinkPad T430",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
- },
- },
- {
- .callback = dmi_disable_osi_win8,
.ident = "Dell Inspiron 7737",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index c5bc8cfe09fa..8581f5b84f48 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -477,9 +477,6 @@ static int __init acpi_bus_init_irq(void)
return 0;
}
-u8 acpi_gbl_permanent_mmap;
-
-
void __init acpi_early_init(void)
{
acpi_status status;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index db35594d4df7..6d5d1832a588 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device);
static void acpi_button_notify(struct acpi_device *device, u32 event);
#ifdef CONFIG_PM_SLEEP
+static int acpi_button_suspend(struct device *dev);
static int acpi_button_resume(struct device *dev);
#else
+#define acpi_button_suspend NULL
#define acpi_button_resume NULL
#endif
-static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
+static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume);
static struct acpi_driver acpi_button_driver = {
.name = "button",
@@ -102,6 +104,7 @@ struct acpi_button {
struct input_dev *input;
char phys[32]; /* for input device */
unsigned long pushed;
+ bool suspended;
};
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
if (button->type == ACPI_BUTTON_TYPE_LID) {
acpi_lid_send_state(device);
} else {
- int keycode = test_bit(KEY_SLEEP, input->keybit) ?
- KEY_SLEEP : KEY_POWER;
+ int keycode;
+
+ pm_wakeup_event(&device->dev, 0);
+ if (button->suspended)
+ break;
+ keycode = test_bit(KEY_SLEEP, input->keybit) ?
+ KEY_SLEEP : KEY_POWER;
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
input_sync(input);
- pm_wakeup_event(&device->dev, 0);
acpi_bus_generate_netlink_event(
device->pnp.device_class,
dev_name(&device->dev),
@@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
}
#ifdef CONFIG_PM_SLEEP
+static int acpi_button_suspend(struct device *dev)
+{
+ struct acpi_device *device = to_acpi_device(dev);
+ struct acpi_button *button = acpi_driver_data(device);
+
+ button->suspended = true;
+ return 0;
+}
+
static int acpi_button_resume(struct device *dev)
{
struct acpi_device *device = to_acpi_device(dev);
struct acpi_button *button = acpi_driver_data(device);
+ button->suspended = false;
if (button->type == ACPI_BUTTON_TYPE_LID)
return acpi_lid_send_state(device);
return 0;
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 49a51277f81d..67075f800e34 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
#ifdef CONFIG_PM
static DEFINE_MUTEX(acpi_pm_notifier_lock);
+static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
+{
+ struct acpi_device *adev;
+
+ if (val != ACPI_NOTIFY_DEVICE_WAKE)
+ return;
+
+ adev = acpi_bus_get_acpi_device(handle);
+ if (!adev)
+ return;
+
+ mutex_lock(&acpi_pm_notifier_lock);
+
+ if (adev->wakeup.flags.notifier_present) {
+ __pm_wakeup_event(adev->wakeup.ws, 0);
+ if (adev->wakeup.context.work.func)
+ queue_pm_work(&adev->wakeup.context.work);
+ }
+
+ mutex_unlock(&acpi_pm_notifier_lock);
+
+ acpi_bus_put_acpi_device(adev);
+}
+
/**
- * 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.
+ * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
+ * @adev: ACPI device to add the notify handler for.
+ * @dev: Device to generate a wakeup event for while handling the notification.
+ * @work_func: Work function to execute when handling the notification.
*
* 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 acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
+ void (*work_func)(struct work_struct *work))
{
acpi_status status = AE_ALREADY_EXISTS;
+ if (!dev && !work_func)
+ return AE_BAD_PARAMETER;
+
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);
+ adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
+ adev->wakeup.context.dev = dev;
+ if (work_func)
+ INIT_WORK(&adev->wakeup.context.work, work_func);
+
+ status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
+ acpi_pm_notify_handler, NULL);
if (ACPI_FAILURE(status))
goto out;
@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
* 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 acpi_remove_pm_notifier(struct acpi_device *adev)
{
acpi_status status = AE_BAD_PARAMETER;
@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
status = acpi_remove_notify_handler(adev->handle,
ACPI_SYSTEM_NOTIFY,
- handler);
+ acpi_pm_notify_handler);
if (ACPI_FAILURE(status))
goto out;
+ if (adev->wakeup.context.work.func) {
+ cancel_work_sync(&adev->wakeup.context.work);
+ adev->wakeup.context.work.func = NULL;
+ }
+ adev->wakeup.context.dev = NULL;
+ wakeup_source_unregister(adev->wakeup.ws);
+
adev->wakeup.flags.notifier_present = false;
out:
@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
*/
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
{
- acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev;
int ret, d_min, d_max;
@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
d_max_in = ACPI_STATE_D3_HOT;
}
- if (!handle || acpi_bus_get_device(handle, &adev)) {
- dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+ adev = ACPI_COMPANION(dev);
+ if (!adev) {
+ dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
return -ENODEV;
}
@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
}
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.
+ * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
+ * @work: Work item to handle.
*/
-static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
+static void acpi_pm_notify_work_func(struct work_struct *work)
{
- struct device *dev = context;
+ struct device *dev;
- if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) {
+ dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
+ if (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.
+ * acpi_device_wakeup - Enable/disable wakeup functionality for device.
+ * @adev: ACPI device to enable/disable wakeup functionality for.
+ * @target_state: State the system is transitioning into.
* @enable: Whether to enable or disable the wakeup functionality.
*
* Enable/disable the GPE associated with @adev so that it can generate
@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
* 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)
+static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state,
+ bool enable)
{
struct acpi_device_wakeup *wakeup = &adev->wakeup;
@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
acpi_status res;
int error;
- error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
+ error = acpi_enable_wakeup_device_power(adev, target_state);
if (error)
return error;
@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
/**
* acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
* @dev: Device to enable/disable the platform to wake up.
@@ -661,63 +700,42 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
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 = ACPI_HANDLE(phys_dev);
- if (!handle || acpi_bus_get_device(handle, &adev)) {
- dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
- __func__);
+ adev = ACPI_COMPANION(phys_dev);
+ if (!adev) {
+ dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__);
return -ENODEV;
}
- return __acpi_device_run_wake(adev, enable);
+ return acpi_device_wakeup(adev, enable, ACPI_STATE_S0);
}
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 = ACPI_HANDLE(dev);
- if (!handle || acpi_bus_get_device(handle, &adev)) {
- dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+ adev = ACPI_COMPANION(dev);
+ if (!adev) {
+ dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
return -ENODEV;
}
- error = __acpi_device_sleep_wake(adev, acpi_target_system_state(),
- enable);
+ error = acpi_device_wakeup(adev, acpi_target_system_state(), enable);
if (!error)
dev_info(dev, "System wakeup %s by ACPI\n",
enable ? "enabled" : "disabled");
@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev)
remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
PM_QOS_FLAGS_NONE;
- error = __acpi_device_run_wake(adev, remote_wakeup);
+ error = acpi_device_wakeup(adev, ACPI_STATE_S0, 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);
+ acpi_device_wakeup(adev, ACPI_STATE_S0, false);
return error;
}
@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev)
return 0;
error = acpi_dev_pm_full_power(adev);
- __acpi_device_run_wake(adev, false);
+ acpi_device_wakeup(adev, ACPI_STATE_S0, false);
return error;
}
EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev)
target_state = acpi_target_system_state();
wakeup = device_may_wakeup(dev);
- error = __acpi_device_sleep_wake(adev, target_state, wakeup);
+ error = acpi_device_wakeup(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);
+ acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
return error;
}
@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev)
return 0;
error = acpi_dev_pm_full_power(adev);
- __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+ acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false);
return error;
}
EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
if (dev->pm_domain)
return -EEXIST;
- acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
+ acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
dev->pm_domain = &acpi_general_pm_domain;
if (power_on) {
acpi_dev_pm_full_power(adev);
- __acpi_device_run_wake(adev, false);
+ acpi_device_wakeup(adev, ACPI_STATE_S0, false);
}
return 0;
}
@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
if (adev && dev->pm_domain == &acpi_general_pm_domain) {
dev->pm_domain = NULL;
- acpi_remove_pm_notifier(adev, acpi_wakeup_device);
+ acpi_remove_pm_notifier(adev);
if (power_off) {
/*
* If the device's PM QoS resume latency limit or flags
@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
*/
dev_pm_qos_hide_latency_limit(dev);
dev_pm_qos_hide_flags(dev);
- __acpi_device_run_wake(adev, false);
+ acpi_device_wakeup(adev, ACPI_STATE_S0, false);
acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
}
}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 7de5b603f272..4c5cf77e7576 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -84,8 +84,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
int type, unsigned long long sta);
void acpi_device_add_finalize(struct acpi_device *device);
void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
-int acpi_bind_one(struct device *dev, struct acpi_device *adev);
-int acpi_unbind_one(struct device *dev);
bool acpi_device_is_present(struct acpi_device *adev);
bool acpi_device_is_battery(struct acpi_device *adev);
@@ -108,7 +106,12 @@ int acpi_power_transition(struct acpi_device *device, int state);
int acpi_device_update_power(struct acpi_device *device, int *state_p);
int acpi_wakeup_device_init(void);
+
+#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
void acpi_early_processor_set_pdc(void);
+#else
+static inline void acpi_early_processor_set_pdc(void) {}
+#endif
/* --------------------------------------------------------------------------
Embedded Controller
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index bad25b070fe0..3abe9b223ba7 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -259,12 +259,14 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
"System description tables not found\n");
return 0;
}
- } else {
+ } else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) {
acpi_physical_address pa = 0;
acpi_find_root_pointer(&pa);
return pa;
}
+
+ return 0;
}
/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9c62340c2360..c96887d5289e 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -481,6 +481,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (!pin)
return;
+ /* Keep IOAPIC pin configuration when suspending */
+ if (dev->dev.power.is_prepared)
+ return;
+
entry = acpi_pci_irq_lookup(dev, pin);
if (!entry)
return;
@@ -498,5 +502,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
*/
dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
- acpi_unregister_gsi(gsi);
+ if (gsi >= 0 && dev->irq > 0)
+ acpi_unregister_gsi(gsi);
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d388f13d48b4..e6ae603ed1a1 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (no_aspm)
pcie_no_aspm();
- pci_acpi_add_bus_pm_notifier(device, root->bus);
+ pci_acpi_add_bus_pm_notifier(device);
if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 71e2065639a6..e32321ce9a5c 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -4,17 +4,11 @@
*
* Alex Chiang <achiang@hp.com>
* - Unified x86/ia64 implementations
- * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- * - Added _PDC for platforms with Intel CPUs
*/
#include <linux/export.h>
-#include <linux/dmi.h>
-#include <linux/slab.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
-#include "internal.h"
-
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_core");
@@ -135,6 +129,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
map_lapic_id(header, acpi_id, &apic_id);
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
map_lsapic_id(header, type, acpi_id, &apic_id);
+ } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+ map_x2apic_id(header, type, acpi_id, &apic_id);
}
exit:
@@ -208,195 +204,3 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
return acpi_map_cpuid(apic_id, acpi_id);
}
EXPORT_SYMBOL_GPL(acpi_get_cpuid);
-
-static bool __init processor_physically_present(acpi_handle handle)
-{
- int cpuid, type;
- u32 acpi_id;
- acpi_status status;
- acpi_object_type acpi_type;
- unsigned long long tmp;
- union acpi_object object = { 0 };
- struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-
- status = acpi_get_type(handle, &acpi_type);
- if (ACPI_FAILURE(status))
- return false;
-
- switch (acpi_type) {
- case ACPI_TYPE_PROCESSOR:
- status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
- if (ACPI_FAILURE(status))
- return false;
- acpi_id = object.processor.proc_id;
- break;
- case ACPI_TYPE_DEVICE:
- status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
- if (ACPI_FAILURE(status))
- return false;
- acpi_id = tmp;
- break;
- default:
- return false;
- }
-
- type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
- cpuid = acpi_get_cpuid(handle, type, acpi_id);
-
- if (cpuid == -1)
- return false;
-
- return true;
-}
-
-static void acpi_set_pdc_bits(u32 *buf)
-{
- buf[0] = ACPI_PDC_REVISION_ID;
- buf[1] = 1;
-
- /* Enable coordination with firmware's _TSD info */
- buf[2] = ACPI_PDC_SMP_T_SWCOORD;
-
- /* Twiddle arch-specific bits needed for _PDC */
- arch_acpi_set_pdc_bits(buf);
-}
-
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
-{
- struct acpi_object_list *obj_list;
- union acpi_object *obj;
- u32 *buf;
-
- /* allocate and initialize pdc. It will be used later. */
- obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
- if (!obj_list) {
- printk(KERN_ERR "Memory allocation error\n");
- return NULL;
- }
-
- obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
- if (!obj) {
- printk(KERN_ERR "Memory allocation error\n");
- kfree(obj_list);
- return NULL;
- }
-
- buf = kmalloc(12, GFP_KERNEL);
- if (!buf) {
- printk(KERN_ERR "Memory allocation error\n");
- kfree(obj);
- kfree(obj_list);
- return NULL;
- }
-
- acpi_set_pdc_bits(buf);
-
- obj->type = ACPI_TYPE_BUFFER;
- obj->buffer.length = 12;
- obj->buffer.pointer = (u8 *) buf;
- obj_list->count = 1;
- obj_list->pointer = obj;
-
- return obj_list;
-}
-
-/*
- * _PDC is required for a BIOS-OS handshake for most of the newer
- * ACPI processor features.
- */
-static acpi_status
-acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
-{
- acpi_status status = AE_OK;
-
- if (boot_option_idle_override == IDLE_NOMWAIT) {
- /*
- * If mwait is disabled for CPU C-states, the C2C3_FFH access
- * mode will be disabled in the parameter of _PDC object.
- * Of course C1_FFH access mode will also be disabled.
- */
- union acpi_object *obj;
- u32 *buffer = NULL;
-
- obj = pdc_in->pointer;
- buffer = (u32 *)(obj->buffer.pointer);
- buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
- }
- status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
-
- if (ACPI_FAILURE(status))
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Could not evaluate _PDC, using legacy perf. control.\n"));
-
- return status;
-}
-
-void acpi_processor_set_pdc(acpi_handle handle)
-{
- struct acpi_object_list *obj_list;
-
- if (arch_has_acpi_pdc() == false)
- return;
-
- obj_list = acpi_processor_alloc_pdc();
- if (!obj_list)
- return;
-
- acpi_processor_eval_pdc(handle, obj_list);
-
- kfree(obj_list->pointer->buffer.pointer);
- kfree(obj_list->pointer);
- kfree(obj_list);
-}
-
-static acpi_status __init
-early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- if (processor_physically_present(handle) == false)
- return AE_OK;
-
- acpi_processor_set_pdc(handle);
- return AE_OK;
-}
-
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
-static int __init set_no_mwait(const struct dmi_system_id *id)
-{
- pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n",
- id->ident);
- boot_option_idle_override = IDLE_NOMWAIT;
- return 0;
-}
-
-static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
- {
- set_no_mwait, "Extensa 5220", {
- DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
- DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
- {},
-};
-
-static void __init processor_dmi_check(void)
-{
- /*
- * Check whether the system is DMI table. If yes, OSPM
- * should not use mwait for CPU-states.
- */
- dmi_check_system(processor_idle_dmi_table);
-}
-#else
-static inline void processor_dmi_check(void) {}
-#endif
-
-void __init acpi_early_processor_set_pdc(void)
-{
- processor_dmi_check();
-
- acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- early_init_pdc, NULL, NULL, NULL);
- acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
-}
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 4fcbd670415c..d9f71581b79b 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -120,6 +120,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
unsigned int cpu = (unsigned long)hcpu;
struct acpi_processor *pr = per_cpu(processors, cpu);
struct acpi_device *device;
+ action &= ~CPU_TASKS_FROZEN;
/*
* CPU_STARTING and CPU_DYING must not sleep. Return here since
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c
new file mode 100644
index 000000000000..e5dd80800930
--- /dev/null
+++ b/drivers/acpi/processor_pdc.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2005 Intel Corporation
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * - Added _PDC for platforms with Intel CPUs
+ */
+
+#define pr_fmt(fmt) "ACPI: " fmt
+
+#include <linux/dmi.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+
+#include "internal.h"
+
+#define _COMPONENT ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME("processor_pdc");
+
+static bool __init processor_physically_present(acpi_handle handle)
+{
+ int cpuid, type;
+ u32 acpi_id;
+ acpi_status status;
+ acpi_object_type acpi_type;
+ unsigned long long tmp;
+ union acpi_object object = { 0 };
+ struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
+
+ status = acpi_get_type(handle, &acpi_type);
+ if (ACPI_FAILURE(status))
+ return false;
+
+ switch (acpi_type) {
+ case ACPI_TYPE_PROCESSOR:
+ status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ return false;
+ acpi_id = object.processor.proc_id;
+ break;
+ case ACPI_TYPE_DEVICE:
+ status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return false;
+ acpi_id = tmp;
+ break;
+ default:
+ return false;
+ }
+
+ type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
+ cpuid = acpi_get_cpuid(handle, type, acpi_id);
+
+ if (cpuid == -1)
+ return false;
+
+ return true;
+}
+
+static void acpi_set_pdc_bits(u32 *buf)
+{
+ buf[0] = ACPI_PDC_REVISION_ID;
+ buf[1] = 1;
+
+ /* Enable coordination with firmware's _TSD info */
+ buf[2] = ACPI_PDC_SMP_T_SWCOORD;
+
+ /* Twiddle arch-specific bits needed for _PDC */
+ arch_acpi_set_pdc_bits(buf);
+}
+
+static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+{
+ struct acpi_object_list *obj_list;
+ union acpi_object *obj;
+ u32 *buf;
+
+ /* allocate and initialize pdc. It will be used later. */
+ obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
+ if (!obj_list)
+ goto out;
+
+ obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+ if (!obj) {
+ kfree(obj_list);
+ goto out;
+ }
+
+ buf = kmalloc(12, GFP_KERNEL);
+ if (!buf) {
+ kfree(obj);
+ kfree(obj_list);
+ goto out;
+ }
+
+ acpi_set_pdc_bits(buf);
+
+ obj->type = ACPI_TYPE_BUFFER;
+ obj->buffer.length = 12;
+ obj->buffer.pointer = (u8 *) buf;
+ obj_list->count = 1;
+ obj_list->pointer = obj;
+
+ return obj_list;
+out:
+ pr_err("Memory allocation error\n");
+ return NULL;
+}
+
+/*
+ * _PDC is required for a BIOS-OS handshake for most of the newer
+ * ACPI processor features.
+ */
+static acpi_status
+acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
+{
+ acpi_status status = AE_OK;
+
+ if (boot_option_idle_override == IDLE_NOMWAIT) {
+ /*
+ * If mwait is disabled for CPU C-states, the C2C3_FFH access
+ * mode will be disabled in the parameter of _PDC object.
+ * Of course C1_FFH access mode will also be disabled.
+ */
+ union acpi_object *obj;
+ u32 *buffer = NULL;
+
+ obj = pdc_in->pointer;
+ buffer = (u32 *)(obj->buffer.pointer);
+ buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
+
+ }
+ status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
+
+ if (ACPI_FAILURE(status))
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Could not evaluate _PDC, using legacy perf. control.\n"));
+
+ return status;
+}
+
+void acpi_processor_set_pdc(acpi_handle handle)
+{
+ struct acpi_object_list *obj_list;
+
+ if (arch_has_acpi_pdc() == false)
+ return;
+
+ obj_list = acpi_processor_alloc_pdc();
+ if (!obj_list)
+ return;
+
+ acpi_processor_eval_pdc(handle, obj_list);
+
+ kfree(obj_list->pointer->buffer.pointer);
+ kfree(obj_list->pointer);
+ kfree(obj_list);
+}
+
+static acpi_status __init
+early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ if (processor_physically_present(handle) == false)
+ return AE_OK;
+
+ acpi_processor_set_pdc(handle);
+ return AE_OK;
+}
+
+static int __init set_no_mwait(const struct dmi_system_id *id)
+{
+ pr_notice("%s detected - disabling mwait for CPU C-states\n",
+ id->ident);
+ boot_option_idle_override = IDLE_NOMWAIT;
+ return 0;
+}
+
+static struct dmi_system_id processor_idle_dmi_table[] __initdata = {
+ {
+ set_no_mwait, "Extensa 5220", {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+ DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
+ {},
+};
+
+static void __init processor_dmi_check(void)
+{
+ /*
+ * Check whether the system is DMI table. If yes, OSPM
+ * should not use mwait for CPU-states.
+ */
+ dmi_check_system(processor_idle_dmi_table);
+}
+
+void __init acpi_early_processor_set_pdc(void)
+{
+ processor_dmi_check();
+
+ acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ early_init_pdc, NULL, NULL, NULL);
+ acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL);
+}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f775fa0d850f..0a817ad24f16 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -77,7 +77,9 @@ void acpi_initialize_hp_context(struct acpi_device *adev,
void (*uevent)(struct acpi_device *, u32))
{
acpi_lock_hp_context();
- acpi_set_hp_context(adev, hp, notify, uevent, NULL);
+ hp->notify = notify;
+ hp->uevent = uevent;
+ acpi_set_hp_context(adev, hp);
acpi_unlock_hp_context();
}
EXPORT_SYMBOL_GPL(acpi_initialize_hp_context);
@@ -351,7 +353,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
unsigned long long sta;
acpi_status status;
- if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) {
+ if (device->handler && device->handler->hotplug.demand_offline
+ && !acpi_force_hot_remove) {
if (!acpi_scan_is_offline(device, true))
return -EBUSY;
} else {
@@ -1421,14 +1424,13 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
wakeup->sleep_state = sleep_state;
}
}
- acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
out:
kfree(buffer.pointer);
return err;
}
-static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
+static void acpi_wakeup_gpe_init(struct acpi_device *device)
{
struct acpi_device_id button_device_ids[] = {
{"PNP0C0C", 0},
@@ -1436,29 +1438,33 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
{"PNP0C0E", 0},
{"", 0},
};
+ struct acpi_device_wakeup *wakeup = &device->wakeup;
acpi_status status;
acpi_event_status event_status;
- device->wakeup.flags.notifier_present = 0;
+ wakeup->flags.notifier_present = 0;
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids)) {
- device->wakeup.flags.run_wake = 1;
+ 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;
+ if (wakeup->sleep_state == ACPI_STATE_S5)
+ wakeup->sleep_state = ACPI_STATE_S4;
}
+ acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
device_set_wakeup_capable(&device->dev, true);
return;
}
- status = acpi_get_gpe_status(device->wakeup.gpe_device,
- device->wakeup.gpe_number,
- &event_status);
- if (status == AE_OK)
- device->wakeup.flags.run_wake =
- !!(event_status & ACPI_EVENT_FLAG_HANDLE);
+ acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device,
+ wakeup->gpe_number);
+ status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number,
+ &event_status);
+ if (ACPI_FAILURE(status))
+ return;
+
+ wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE);
}
static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
@@ -1478,7 +1484,7 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
device->wakeup.flags.valid = 1;
device->wakeup.prepare_count = 0;
- acpi_bus_set_run_wake_flags(device);
+ acpi_wakeup_gpe_init(device);
/* Call _PSW/_DSW object to disable its ability to wake the sleeping
* system for the ACPI device with the _PRW object.
* The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index b3e3cc73ba79..54da4a3fe65e 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = {
static void acpi_sleep_dmi_check(void)
{
+ int year;
+
+ if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012)
+ acpi_nvs_nosave_s3();
+
dmi_check_system(acpisleep_dmi_table);
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 350d52a8f781..826884392e6b 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -204,6 +204,8 @@ struct acpi_video_device {
struct acpi_video_device_flags flags;
struct acpi_video_device_cap cap;
struct list_head entry;
+ struct delayed_work switch_brightness_work;
+ int switch_brightness_event;
struct acpi_video_bus *video;
struct acpi_device *dev;
struct acpi_video_device_brightness *brightness;
@@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current(
unsigned long long *level, bool raw);
static int acpi_video_get_next_level(struct acpi_video_device *device,
u32 level_current, u32 event);
-static int acpi_video_switch_brightness(struct acpi_video_device *device,
- int event);
+static void acpi_video_switch_brightness(struct work_struct *work);
static bool acpi_video_use_native_backlight(void)
{
@@ -275,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd)
int request_level = bd->props.brightness + 2;
struct acpi_video_device *vd = bl_get_data(bd);
+ cancel_delayed_work(&vd->switch_brightness_work);
return acpi_video_device_lcd_set_level(vd,
vd->brightness->levels[request_level]);
}
@@ -461,6 +463,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
{
.callback = video_set_use_native_backlight,
+ .ident = "ThinkPad X230",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
.ident = "ThinkPad T430 and T430s",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -469,10 +479,42 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
{
.callback = video_set_use_native_backlight,
- .ident = "ThinkPad X230",
+ .ident = "ThinkPad T430",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "ThinkPad T431s",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "ThinkPad Edge E530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "ThinkPad Edge E530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "ThinkPad Edge E530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
},
},
{
@@ -572,6 +614,30 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
},
{
+ .callback = video_set_use_native_backlight,
+ .ident = "Acer Aspire V5-572G",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "Acer Aspire V5-573G",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
+ .ident = "ASUS Zenbook Prime UX31A",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"),
+ },
+ },
+ {
.callback = video_set_use_native_backlight,
.ident = "HP ProBook 4340s",
.matches = {
@@ -607,6 +673,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
},
{
.callback = video_set_use_native_backlight,
+ .ident = "HP EliteBook 2014 models",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+ DMI_MATCH(DMI_PRODUCT_NAME, " G2"),
+ },
+ },
+ {
+ .callback = video_set_use_native_backlight,
.ident = "HP ZBook 14",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -1188,6 +1263,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
data->device_id = device_id;
data->video = video;
data->dev = device;
+ INIT_DELAYED_WORK(&data->switch_brightness_work,
+ acpi_video_switch_brightness);
attribute = acpi_video_get_device_attr(video, device_id);
@@ -1410,15 +1487,18 @@ acpi_video_get_next_level(struct acpi_video_device *device,
}
}
-static int
-acpi_video_switch_brightness(struct acpi_video_device *device, int event)
+static void
+acpi_video_switch_brightness(struct work_struct *work)
{
+ struct acpi_video_device *device = container_of(to_delayed_work(work),
+ struct acpi_video_device, switch_brightness_work);
unsigned long long level_current, level_next;
+ int event = device->switch_brightness_event;
int result = -EINVAL;
/* no warning message if acpi_backlight=vendor or a quirk is used */
if (!acpi_video_verify_backlight_support())
- return 0;
+ return;
if (!device->brightness)
goto out;
@@ -1440,8 +1520,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
out:
if (result)
printk(KERN_ERR PREFIX "Failed to switch the brightness\n");
-
- return result;
}
int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
@@ -1609,6 +1687,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
return;
}
+static void brightness_switch_event(struct acpi_video_device *video_device,
+ u32 event)
+{
+ if (!brightness_switch_enabled)
+ return;
+
+ video_device->switch_brightness_event = event;
+ schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10);
+}
+
static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_video_device *video_device = data;
@@ -1626,28 +1714,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */
- if (brightness_switch_enabled)
- acpi_video_switch_brightness(video_device, event);
+ brightness_switch_event(video_device, event);
keycode = KEY_BRIGHTNESS_CYCLE;
break;
case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */
- if (brightness_switch_enabled)
- acpi_video_switch_brightness(video_device, event);
+ brightness_switch_event(video_device, event);
keycode = KEY_BRIGHTNESSUP;
break;
case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */
- if (brightness_switch_enabled)
- acpi_video_switch_brightness(video_device, event);
+ brightness_switch_event(video_device, event);
keycode = KEY_BRIGHTNESSDOWN;
break;
case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */
- if (brightness_switch_enabled)
- acpi_video_switch_brightness(video_device, event);
+ brightness_switch_event(video_device, event);
keycode = KEY_BRIGHTNESS_ZERO;
break;
case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */
- if (brightness_switch_enabled)
- acpi_video_switch_brightness(video_device, event);
+ brightness_switch_event(video_device, event);
keycode = KEY_DISPLAY_OFF;
break;
default:
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 558a239954e8..d8961ef4d2e7 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -25,7 +25,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/tegra-ahb.h>
+
+#include <soc/tegra/ahb.h>
#define DRV_NAME "tegra-ahb"
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 7671dbac6015..e1b92788c225 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -16,6 +16,7 @@ menuconfig ATA
depends on BLOCK
depends on !(M32R || M68K || S390) || BROKEN
select SCSI
+ select GLOB
---help---
If you want to use an ATA hard disk, ATA tape drive, ATA CD-ROM or
any other ATA device under Linux, say Y and make sure that you know
@@ -141,6 +142,15 @@ config AHCI_SUNXI
If unsure, say N.
+config AHCI_TEGRA
+ tristate "NVIDIA Tegra124 AHCI SATA support"
+ depends on ARCH_TEGRA
+ help
+ This option enables support for the NVIDIA Tegra124 SoC's
+ onboard AHCI SATA.
+
+ If unsure, say N.
+
config AHCI_XGENE
tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
depends on PHY_XGENE
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 5a02aeecef5b..ae41107afc1f 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o
obj-$(CONFIG_AHCI_XGENE) += ahci_xgene.o libahci.o libahci_platform.o
# SFF w/ custom DMA
diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index 0cd7c7a39e5b..25d0ac32e721 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -441,7 +441,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
/* save initial config */
- ahci_save_initial_config(&pdev->dev, hpriv, 0, 0);
+ ahci_save_initial_config(&pdev->dev, hpriv);
/* prepare host */
if (hpriv->cap & HOST_CAP_NCQ)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 4cd52a4541a9..a29f8012fb08 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -526,8 +526,7 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
"Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
}
- ahci_save_initial_config(&pdev->dev, hpriv, force_port_map,
- mask_port_map);
+ ahci_save_initial_config(&pdev->dev, hpriv);
}
static int ahci_pci_reset_controller(struct ata_host *host)
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 5513296e5e2e..59ae0ee00149 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -53,7 +53,7 @@
enum {
AHCI_MAX_PORTS = 32,
- AHCI_MAX_CLKS = 3,
+ AHCI_MAX_CLKS = 4,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
AHCI_MAX_CMDS = 32,
@@ -316,8 +316,12 @@ struct ahci_port_priv {
};
struct ahci_host_priv {
- void __iomem * mmio; /* bus-independent mem map */
+ /* Input fields */
unsigned int flags; /* AHCI_HFLAG_* */
+ u32 force_port_map; /* force port map */
+ u32 mask_port_map; /* mask out particular bits */
+
+ void __iomem * mmio; /* bus-independent mem map */
u32 cap; /* cap to use */
u32 cap2; /* cap2 to use */
u32 port_map; /* port map to use */
@@ -330,7 +334,12 @@ struct ahci_host_priv {
bool got_runtime_pm; /* Did we do pm_runtime_get? */
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
struct regulator *target_pwr; /* Optional */
- struct phy *phy; /* If platform uses phy */
+ /*
+ * If platform uses PHYs. There is a 1:1 relation between the port number and
+ * the PHY position in this array.
+ */
+ struct phy **phys;
+ unsigned nports; /* Number of ports */
void *plat_data; /* Other platform data */
/*
* Optional ahci_start_engine override, if not set this gets set to the
@@ -361,9 +370,7 @@ unsigned int ahci_dev_classify(struct ata_port *ap);
void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
u32 opts);
void ahci_save_initial_config(struct device *dev,
- struct ahci_host_priv *hpriv,
- unsigned int force_port_map,
- unsigned int mask_port_map);
+ struct ahci_host_priv *hpriv);
void ahci_init_controller(struct ata_host *host);
int ahci_reset_controller(struct ata_host *host);
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 2b77d53bccf8..ad1e71ec10cf 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -85,8 +85,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
da850_sata_init(dev, pwrdn_reg, hpriv->mmio);
- rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
- 0, 0, 0);
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info);
if (rc)
goto disable_resources;
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index cac4360f272a..f3970b4ed889 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -64,6 +64,7 @@ struct imx_ahci_priv {
struct regmap *gpr;
bool no_device;
bool first_time;
+ u32 phy_params;
};
static int ahci_imx_hotplug;
@@ -248,14 +249,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
IMX6Q_GPR13_SATA_TX_LVL_MASK |
IMX6Q_GPR13_SATA_MPLL_CLK_EN |
IMX6Q_GPR13_SATA_TX_EDGE_RATE,
- IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
- IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
- IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
- IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
- IMX6Q_GPR13_SATA_MPLL_SS_EN |
- IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
- IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
- IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
+ imxpriv->phy_params);
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
IMX6Q_GPR13_SATA_MPLL_CLK_EN,
IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -265,7 +259,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
ret = imx_sata_phy_reset(hpriv);
if (ret) {
dev_err(dev, "failed to reset phy: %d\n", ret);
- goto disable_regulator;
+ goto disable_clk;
}
}
@@ -273,6 +267,8 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
return 0;
+disable_clk:
+ clk_disable_unprepare(imxpriv->sata_ref_clk);
disable_regulator:
if (hpriv->target_pwr)
regulator_disable(hpriv->target_pwr);
@@ -369,6 +365,165 @@ static const struct of_device_id imx_ahci_of_match[] = {
};
MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
+struct reg_value {
+ u32 of_value;
+ u32 reg_value;
+};
+
+struct reg_property {
+ const char *name;
+ const struct reg_value *values;
+ size_t num_values;
+ u32 def_value;
+ u32 set_value;
+};
+
+static const struct reg_value gpr13_tx_level[] = {
+ { 937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
+ { 947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
+ { 957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
+ { 966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
+ { 976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
+ { 986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
+ { 996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
+ { 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
+ { 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
+ { 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
+ { 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
+ { 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
+ { 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
+ { 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
+ { 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
+ { 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
+ { 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
+ { 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
+ { 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
+ { 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
+ { 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
+ { 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
+ { 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
+ { 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
+ { 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
+ { 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
+ { 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
+ { 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
+ { 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
+ { 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
+ { 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
+ { 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
+};
+
+static const struct reg_value gpr13_tx_boost[] = {
+ { 0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
+ { 370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
+ { 740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
+ { 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
+ { 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
+ { 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
+ { 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
+ { 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
+ { 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
+ { 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
+ { 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
+ { 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
+ { 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
+ { 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
+ { 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
+ { 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
+};
+
+static const struct reg_value gpr13_tx_atten[] = {
+ { 8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
+ { 9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
+ { 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
+ { 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
+ { 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
+ { 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
+};
+
+static const struct reg_value gpr13_rx_eq[] = {
+ { 500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
+ { 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
+ { 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
+ { 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
+ { 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
+ { 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
+ { 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
+ { 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
+};
+
+static const struct reg_property gpr13_props[] = {
+ {
+ .name = "fsl,transmit-level-mV",
+ .values = gpr13_tx_level,
+ .num_values = ARRAY_SIZE(gpr13_tx_level),
+ .def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
+ }, {
+ .name = "fsl,transmit-boost-mdB",
+ .values = gpr13_tx_boost,
+ .num_values = ARRAY_SIZE(gpr13_tx_boost),
+ .def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
+ }, {
+ .name = "fsl,transmit-atten-16ths",
+ .values = gpr13_tx_atten,
+ .num_values = ARRAY_SIZE(gpr13_tx_atten),
+ .def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
+ }, {
+ .name = "fsl,receive-eq-mdB",
+ .values = gpr13_rx_eq,
+ .num_values = ARRAY_SIZE(gpr13_rx_eq),
+ .def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
+ }, {
+ .name = "fsl,no-spread-spectrum",
+ .def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
+ .set_value = 0,
+ },
+};
+
+static u32 imx_ahci_parse_props(struct device *dev,
+ const struct reg_property *prop, size_t num)
+{
+ struct device_node *np = dev->of_node;
+ u32 reg_value = 0;
+ int i, j;
+
+ for (i = 0; i < num; i++, prop++) {
+ u32 of_val;
+
+ if (prop->num_values == 0) {
+ if (of_property_read_bool(np, prop->name))
+ reg_value |= prop->set_value;
+ else
+ reg_value |= prop->def_value;
+ continue;
+ }
+
+ if (of_property_read_u32(np, prop->name, &of_val)) {
+ dev_info(dev, "%s not specified, using %08x\n",
+ prop->name, prop->def_value);
+ reg_value |= prop->def_value;
+ continue;
+ }
+
+ for (j = 0; j < prop->num_values; j++) {
+ if (prop->values[j].of_value == of_val) {
+ dev_info(dev, "%s value %u, using %08x\n",
+ prop->name, of_val, prop->values[j].reg_value);
+ reg_value |= prop->values[j].reg_value;
+ break;
+ }
+ }
+
+ if (j == prop->num_values) {
+ dev_err(dev, "DT property %s is not a valid value\n",
+ prop->name);
+ reg_value |= prop->def_value;
+ }
+ }
+
+ return reg_value;
+}
+
static int imx_ahci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -410,6 +565,8 @@ static int imx_ahci_probe(struct platform_device *pdev)
}
if (imxpriv->type == AHCI_IMX6Q) {
+ u32 reg_value;
+
imxpriv->gpr = syscon_regmap_lookup_by_compatible(
"fsl,imx6q-iomuxc-gpr");
if (IS_ERR(imxpriv->gpr)) {
@@ -417,6 +574,15 @@ static int imx_ahci_probe(struct platform_device *pdev)
"failed to find fsl,imx6q-iomux-gpr regmap\n");
return PTR_ERR(imxpriv->gpr);
}
+
+ reg_value = imx_ahci_parse_props(dev, gpr13_props,
+ ARRAY_SIZE(gpr13_props));
+
+ imxpriv->phy_params =
+ IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+ IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+ IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+ reg_value;
}
hpriv = ahci_platform_get_resources(pdev);
@@ -454,8 +620,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
- ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info,
- 0, 0, 0);
+ ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info);
if (ret)
goto disable_sata;
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index fd3dfd733b84..68672d2692ee 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -88,8 +88,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
ahci_mvebu_mbus_config(hpriv, dram);
ahci_mvebu_regret_option(hpriv);
- rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
- 0, 0, 0);
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info);
if (rc)
goto disable_resources;
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index b10d81ddb528..f61ddb9146d6 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -34,7 +34,6 @@ static int ahci_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ahci_platform_data *pdata = dev_get_platdata(dev);
struct ahci_host_priv *hpriv;
- unsigned long hflags = 0;
int rc;
hpriv = ahci_platform_get_resources(pdev);
@@ -58,10 +57,9 @@ static int ahci_probe(struct platform_device *pdev)
}
if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
- hflags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
+ hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
- rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
- hflags, 0, 0);
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info);
if (rc)
goto pdata_exit;
@@ -78,6 +76,8 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
ahci_platform_resume);
static const struct of_device_id ahci_of_match[] = {
+ { .compatible = "generic-ahci", },
+ /* Keep the following compatibles for device tree compatibility */
{ .compatible = "snps,spear-ahci", },
{ .compatible = "snps,exynos5440-ahci", },
{ .compatible = "ibm,476gtr-ahci", },
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 2595598df9ce..835d6eea84fd 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -166,7 +166,7 @@ static int st_ahci_probe(struct platform_device *pdev)
if (err)
return err;
- err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0, 0, 0);
+ err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info);
if (err) {
ahci_platform_disable_resources(hpriv);
return err;
@@ -221,7 +221,7 @@ static int st_ahci_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(st_ahci_pm_ops, st_ahci_suspend, st_ahci_resume);
-static struct of_device_id st_ahci_match[] = {
+static const struct of_device_id st_ahci_match[] = {
{ .compatible = "st,ahci", },
{},
};
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 02002f125bd4..e44d675a30ec 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -167,7 +167,6 @@ static int ahci_sunxi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
- unsigned long hflags;
int rc;
hpriv = ahci_platform_get_resources(pdev);
@@ -184,11 +183,10 @@ static int ahci_sunxi_probe(struct platform_device *pdev)
if (rc)
goto disable_resources;
- hflags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
- AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
+ hpriv->flags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
- rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info,
- hflags, 0, 0);
+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info);
if (rc)
goto disable_resources;
diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c
new file mode 100644
index 000000000000..fc3df47fca35
--- /dev/null
+++ b/drivers/ata/ahci_tegra.c
@@ -0,0 +1,376 @@
+/*
+ * drivers/ata/ahci_tegra.c
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author:
+ * Mikko Perttunen <mperttunen@nvidia.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/reset.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/tegra-powergate.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define SATA_CONFIGURATION_0 0x180
+#define SATA_CONFIGURATION_EN_FPCI BIT(0)
+
+#define SCFG_OFFSET 0x1000
+
+#define T_SATA0_CFG_1 0x04
+#define T_SATA0_CFG_1_IO_SPACE BIT(0)
+#define T_SATA0_CFG_1_MEMORY_SPACE BIT(1)
+#define T_SATA0_CFG_1_BUS_MASTER BIT(2)
+#define T_SATA0_CFG_1_SERR BIT(8)
+
+#define T_SATA0_CFG_9 0x24
+#define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13
+
+#define SATA_FPCI_BAR5 0x94
+#define SATA_FPCI_BAR5_START_SHIFT 4
+
+#define SATA_INTR_MASK 0x188
+#define SATA_INTR_MASK_IP_INT_MASK BIT(16)
+
+#define T_SATA0_AHCI_HBA_CAP_BKDR 0x300
+
+#define T_SATA0_BKDOOR_CC 0x4a4
+
+#define T_SATA0_CFG_SATA 0x54c
+#define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN BIT(12)
+
+#define T_SATA0_CFG_MISC 0x550
+
+#define T_SATA0_INDEX 0x680
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK (0xff << 8)
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK (0xff << 12)
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12
+
+#define T_SATA0_CHX_PHY_CTRL2 0x69c
+#define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23
+
+#define T_SATA0_CHX_PHY_CTRL11 0x6d0
+#define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16)
+
+#define FUSE_SATA_CALIB 0x124
+#define FUSE_SATA_CALIB_MASK 0x3
+
+struct sata_pad_calibration {
+ u8 gen1_tx_amp;
+ u8 gen1_tx_peak;
+ u8 gen2_tx_amp;
+ u8 gen2_tx_peak;
+};
+
+static const struct sata_pad_calibration tegra124_pad_calibration[] = {
+ {0x18, 0x04, 0x18, 0x0a},
+ {0x0e, 0x04, 0x14, 0x0a},
+ {0x0e, 0x07, 0x1a, 0x0e},
+ {0x14, 0x0e, 0x1a, 0x0e},
+};
+
+struct tegra_ahci_priv {
+ struct platform_device *pdev;
+ void __iomem *sata_regs;
+ struct reset_control *sata_rst;
+ struct reset_control *sata_oob_rst;
+ struct reset_control *sata_cold_rst;
+ /* Needs special handling, cannot use ahci_platform */
+ struct clk *sata_clk;
+ struct regulator_bulk_data supplies[5];
+};
+
+static int tegra_ahci_power_on(struct ahci_host_priv *hpriv)
+{
+ struct tegra_ahci_priv *tegra = hpriv->plat_data;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies),
+ tegra->supplies);
+ if (ret)
+ return ret;
+
+ ret = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SATA,
+ tegra->sata_clk,
+ tegra->sata_rst);
+ if (ret)
+ goto disable_regulators;
+
+ reset_control_assert(tegra->sata_oob_rst);
+ reset_control_assert(tegra->sata_cold_rst);
+
+ ret = ahci_platform_enable_resources(hpriv);
+ if (ret)
+ goto disable_power;
+
+ reset_control_deassert(tegra->sata_cold_rst);
+ reset_control_deassert(tegra->sata_oob_rst);
+
+ return 0;
+
+disable_power:
+ clk_disable_unprepare(tegra->sata_clk);
+
+ tegra_powergate_power_off(TEGRA_POWERGATE_SATA);
+
+disable_regulators:
+ regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+
+ return ret;
+}
+
+static void tegra_ahci_power_off(struct ahci_host_priv *hpriv)
+{
+ struct tegra_ahci_priv *tegra = hpriv->plat_data;
+
+ ahci_platform_disable_resources(hpriv);
+
+ reset_control_assert(tegra->sata_rst);
+ reset_control_assert(tegra->sata_oob_rst);
+ reset_control_assert(tegra->sata_cold_rst);
+
+ clk_disable_unprepare(tegra->sata_clk);
+ tegra_powergate_power_off(TEGRA_POWERGATE_SATA);
+
+ regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+}
+
+static int tegra_ahci_controller_init(struct ahci_host_priv *hpriv)
+{
+ struct tegra_ahci_priv *tegra = hpriv->plat_data;
+ int ret;
+ unsigned int val;
+ struct sata_pad_calibration calib;
+
+ ret = tegra_ahci_power_on(hpriv);
+ if (ret) {
+ dev_err(&tegra->pdev->dev,
+ "failed to power on AHCI controller: %d\n", ret);
+ return ret;
+ }
+
+ val = readl(tegra->sata_regs + SATA_CONFIGURATION_0);
+ val |= SATA_CONFIGURATION_EN_FPCI;
+ writel(val, tegra->sata_regs + SATA_CONFIGURATION_0);
+
+ /* Pad calibration */
+
+ /* FIXME Always use calibration 0. Change this to read the calibration
+ * fuse once the fuse driver has landed. */
+ val = 0;
+
+ calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK];
+
+ writel(BIT(0), tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX);
+
+ val = readl(tegra->sata_regs +
+ SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1);
+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK;
+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK;
+ val |= calib.gen1_tx_amp <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT;
+ val |= calib.gen1_tx_peak <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT;
+ writel(val, tegra->sata_regs + SCFG_OFFSET +
+ T_SATA0_CHX_PHY_CTRL1_GEN1);
+
+ val = readl(tegra->sata_regs +
+ SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2);
+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK;
+ val &= ~T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK;
+ val |= calib.gen2_tx_amp <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT;
+ val |= calib.gen2_tx_peak <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT;
+ writel(val, tegra->sata_regs + SCFG_OFFSET +
+ T_SATA0_CHX_PHY_CTRL1_GEN2);
+
+ writel(T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ,
+ tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11);
+ writel(T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1,
+ tegra->sata_regs + SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2);
+
+ writel(0, tegra->sata_regs + SCFG_OFFSET + T_SATA0_INDEX);
+
+ /* Program controller device ID */
+
+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+ val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+
+ writel(0x01060100, tegra->sata_regs + SCFG_OFFSET + T_SATA0_BKDOOR_CC);
+
+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+ val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_SATA);
+
+ /* Enable IO & memory access, bus master mode */
+
+ val = readl(tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1);
+ val |= T_SATA0_CFG_1_IO_SPACE | T_SATA0_CFG_1_MEMORY_SPACE |
+ T_SATA0_CFG_1_BUS_MASTER | T_SATA0_CFG_1_SERR;
+ writel(val, tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_1);
+
+ /* Program SATA MMIO */
+
+ writel(0x10000 << SATA_FPCI_BAR5_START_SHIFT,
+ tegra->sata_regs + SATA_FPCI_BAR5);
+
+ writel(0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT,
+ tegra->sata_regs + SCFG_OFFSET + T_SATA0_CFG_9);
+
+ /* Unmask SATA interrupts */
+
+ val = readl(tegra->sata_regs + SATA_INTR_MASK);
+ val |= SATA_INTR_MASK_IP_INT_MASK;
+ writel(val, tegra->sata_regs + SATA_INTR_MASK);
+
+ return 0;
+}
+
+static void tegra_ahci_controller_deinit(struct ahci_host_priv *hpriv)
+{
+ tegra_ahci_power_off(hpriv);
+}
+
+static void tegra_ahci_host_stop(struct ata_host *host)
+{
+ struct ahci_host_priv *hpriv = host->private_data;
+
+ tegra_ahci_controller_deinit(hpriv);
+}
+
+static struct ata_port_operations ahci_tegra_port_ops = {
+ .inherits = &ahci_ops,
+ .host_stop = tegra_ahci_host_stop,
+};
+
+static const struct ata_port_info ahci_tegra_port_info = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_tegra_port_ops,
+};
+
+static const struct of_device_id tegra_ahci_of_match[] = {
+ { .compatible = "nvidia,tegra124-ahci" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, tegra_ahci_of_match);
+
+static int tegra_ahci_probe(struct platform_device *pdev)
+{
+ struct ahci_host_priv *hpriv;
+ struct tegra_ahci_priv *tegra;
+ struct resource *res;
+ int ret;
+
+ hpriv = ahci_platform_get_resources(pdev);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+ tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+ if (!tegra)
+ return -ENOMEM;
+
+ hpriv->plat_data = tegra;
+
+ tegra->pdev = pdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ tegra->sata_regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(tegra->sata_regs))
+ return PTR_ERR(tegra->sata_regs);
+
+ tegra->sata_rst = devm_reset_control_get(&pdev->dev, "sata");
+ if (IS_ERR(tegra->sata_rst)) {
+ dev_err(&pdev->dev, "Failed to get sata reset\n");
+ return PTR_ERR(tegra->sata_rst);
+ }
+
+ tegra->sata_oob_rst = devm_reset_control_get(&pdev->dev, "sata-oob");
+ if (IS_ERR(tegra->sata_oob_rst)) {
+ dev_err(&pdev->dev, "Failed to get sata-oob reset\n");
+ return PTR_ERR(tegra->sata_oob_rst);
+ }
+
+ tegra->sata_cold_rst = devm_reset_control_get(&pdev->dev, "sata-cold");
+ if (IS_ERR(tegra->sata_cold_rst)) {
+ dev_err(&pdev->dev, "Failed to get sata-cold reset\n");
+ return PTR_ERR(tegra->sata_cold_rst);
+ }
+
+ tegra->sata_clk = devm_clk_get(&pdev->dev, "sata");
+ if (IS_ERR(tegra->sata_clk)) {
+ dev_err(&pdev->dev, "Failed to get sata clock\n");
+ return PTR_ERR(tegra->sata_clk);
+ }
+
+ tegra->supplies[0].supply = "avdd";
+ tegra->supplies[1].supply = "hvdd";
+ tegra->supplies[2].supply = "vddio";
+ tegra->supplies[3].supply = "target-5v";
+ tegra->supplies[4].supply = "target-12v";
+
+ ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies),
+ tegra->supplies);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to get regulators\n");
+ return ret;
+ }
+
+ ret = tegra_ahci_controller_init(hpriv);
+ if (ret)
+ return ret;
+
+ ret = ahci_platform_init_host(pdev, hpriv, &ahci_tegra_port_info);
+ if (ret)
+ goto deinit_controller;
+
+ return 0;
+
+deinit_controller:
+ tegra_ahci_controller_deinit(hpriv);
+
+ return ret;
+};
+
+static struct platform_driver tegra_ahci_driver = {
+ .probe = tegra_ahci_probe,
+ .remove = ata_platform_remove_one,
+ .driver = {
+ .name = "tegra-ahci",
+ .of_match_table = tegra_ahci_of_match,
+ },
+ /* LP0 suspend support not implemented */
+};
+module_platform_driver(tegra_ahci_driver);
+
+MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
+MODULE_DESCRIPTION("Tegra124 AHCI SATA driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index ee3a3659bd9e..bc281115490b 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -67,6 +67,9 @@
#define PORTAXICFG 0x000000bc
#define PORTAXICFG_OUTTRANS_SET(dst, src) \
(((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000))
+#define PORTRANSCFG 0x000000c8
+#define PORTRANSCFG_RXWM_SET(dst, src) \
+ (((dst) & ~0x0000007f) | (((u32)(src)) & 0x0000007f))
/* SATA host controller AXI CSR */
#define INT_SLV_TMOMASK 0x00000010
@@ -193,11 +196,11 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
/* Disable fix rate */
writel(0x0001fffe, mmio + PORTPHY1CFG);
readl(mmio + PORTPHY1CFG); /* Force a barrier */
- writel(0x5018461c, mmio + PORTPHY2CFG);
+ writel(0x28183219, mmio + PORTPHY2CFG);
readl(mmio + PORTPHY2CFG); /* Force a barrier */
- writel(0x1c081907, mmio + PORTPHY3CFG);
+ writel(0x13081008, mmio + PORTPHY3CFG);
readl(mmio + PORTPHY3CFG); /* Force a barrier */
- writel(0x1c080815, mmio + PORTPHY4CFG);
+ writel(0x00480815, mmio + PORTPHY4CFG);
readl(mmio + PORTPHY4CFG); /* Force a barrier */
/* Set window negotiation */
val = readl(mmio + PORTPHY5CFG);
@@ -209,6 +212,10 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
val = PORTAXICFG_OUTTRANS_SET(val, 0xe); /* Set outstanding */
writel(val, mmio + PORTAXICFG);
readl(mmio + PORTAXICFG); /* Force a barrier */
+ /* Set the watermark threshold of the receive FIFO */
+ val = readl(mmio + PORTRANSCFG);
+ val = PORTRANSCFG_RXWM_SET(val, 0x30);
+ writel(val, mmio + PORTRANSCFG);
}
/**
@@ -415,7 +422,6 @@ static int xgene_ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
struct xgene_ahci_context *ctx;
struct resource *res;
- unsigned long hflags;
int rc;
hpriv = ahci_platform_get_resources(pdev);
@@ -474,20 +480,9 @@ static int xgene_ahci_probe(struct platform_device *pdev)
/* Configure the host controller */
xgene_ahci_hw_init(hpriv);
- /*
- * Setup DMA mask. This is preliminary until the DMA range is sorted
- * out.
- */
- rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
- if (rc) {
- dev_err(dev, "Unable to set dma mask\n");
- goto disable_resources;
- }
-
- hflags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
+ hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ;
- rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info,
- hflags, 0, 0);
+ rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info);
if (rc)
goto disable_resources;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index d72ce0470309..b784e9de426a 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -382,8 +382,6 @@ static ssize_t ahci_show_em_supported(struct device *dev,
* ahci_save_initial_config - Save and fixup initial config values
* @dev: target AHCI device
* @hpriv: host private area to store config values
- * @force_port_map: force port map to a specified value
- * @mask_port_map: mask out particular bits from port map
*
* Some registers containing configuration info might be setup by
* BIOS and might be cleared on reset. This function saves the
@@ -398,10 +396,7 @@ static ssize_t ahci_show_em_supported(struct device *dev,
* LOCKING:
* None.
*/
-void ahci_save_initial_config(struct device *dev,
- struct ahci_host_priv *hpriv,
- unsigned int force_port_map,
- unsigned int mask_port_map)
+void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
{
void __iomem *mmio = hpriv->mmio;
u32 cap, cap2, vers, port_map;
@@ -468,17 +463,17 @@ void ahci_save_initial_config(struct device *dev,
cap &= ~HOST_CAP_FBS;
}
- if (force_port_map && port_map != force_port_map) {
+ if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
- port_map, force_port_map);
- port_map = force_port_map;
+ port_map, hpriv->force_port_map);
+ port_map = hpriv->force_port_map;
}
- if (mask_port_map) {
+ if (hpriv->mask_port_map) {
dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
port_map,
- port_map & mask_port_map);
- port_map &= mask_port_map;
+ port_map & hpriv->mask_port_map);
+ port_map &= hpriv->mask_port_map;
}
/* cross check port_map and cap.n_ports */
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index b0077589f065..5b92c290e6c6 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -39,6 +39,67 @@ static struct scsi_host_template ahci_platform_sht = {
};
/**
+ * ahci_platform_enable_phys - Enable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the PHYs found in hpriv->phys, if any.
+ * If a PHY fails to be enabled, it disables all the PHYs already
+ * enabled in reverse order and returns an error.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
+{
+ int rc, i;
+
+ for (i = 0; i < hpriv->nports; i++) {
+ if (!hpriv->phys[i])
+ continue;
+
+ rc = phy_init(hpriv->phys[i]);
+ if (rc)
+ goto disable_phys;
+
+ rc = phy_power_on(hpriv->phys[i]);
+ if (rc) {
+ phy_exit(hpriv->phys[i]);
+ goto disable_phys;
+ }
+ }
+
+ return 0;
+
+disable_phys:
+ while (--i >= 0) {
+ phy_power_off(hpriv->phys[i]);
+ phy_exit(hpriv->phys[i]);
+ }
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
+
+/**
+ * ahci_platform_disable_phys - Disable PHYs
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all PHYs found in hpriv->phys.
+ */
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
+{
+ int i;
+
+ for (i = 0; i < hpriv->nports; i++) {
+ if (!hpriv->phys[i])
+ continue;
+
+ phy_power_off(hpriv->phys[i]);
+ phy_exit(hpriv->phys[i]);
+ }
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
+
+/**
* ahci_platform_enable_clks - Enable platform clocks
* @hpriv: host private area to store config values
*
@@ -92,7 +153,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
* following order:
* 1) Regulator
* 2) Clocks (through ahci_platform_enable_clks)
- * 3) Phy
+ * 3) Phys
*
* If resource enabling fails at any point the previous enabled resources
* are disabled in reverse order.
@@ -114,17 +175,9 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
if (rc)
goto disable_regulator;
- if (hpriv->phy) {
- rc = phy_init(hpriv->phy);
- if (rc)
- goto disable_clks;
-
- rc = phy_power_on(hpriv->phy);
- if (rc) {
- phy_exit(hpriv->phy);
- goto disable_clks;
- }
- }
+ rc = ahci_platform_enable_phys(hpriv);
+ if (rc)
+ goto disable_clks;
return 0;
@@ -144,16 +197,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
*
* This function disables all ahci_platform managed resources in the
* following order:
- * 1) Phy
+ * 1) Phys
* 2) Clocks (through ahci_platform_disable_clks)
* 3) Regulator
*/
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
{
- if (hpriv->phy) {
- phy_power_off(hpriv->phy);
- phy_exit(hpriv->phy);
- }
+ ahci_platform_disable_phys(hpriv);
ahci_platform_disable_clks(hpriv);
@@ -187,7 +237,7 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
* 2) regulator for controlling the targets power (optional)
* 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
* or for non devicetree enabled platforms a single clock
- * 4) phy (optional)
+ * 4) phys (optional)
*
* RETURNS:
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -197,7 +247,9 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
struct clk *clk;
- int i, rc = -ENOMEM;
+ struct device_node *child;
+ int i, enabled_ports = 0, rc = -ENOMEM;
+ u32 mask_port_map = 0;
if (!devres_open_group(dev, NULL, GFP_KERNEL))
return ERR_PTR(-ENOMEM);
@@ -246,28 +298,89 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
hpriv->clks[i] = clk;
}
- hpriv->phy = devm_phy_get(dev, "sata-phy");
- if (IS_ERR(hpriv->phy)) {
- rc = PTR_ERR(hpriv->phy);
- switch (rc) {
- case -ENOSYS:
- /* No PHY support. Check if PHY is required. */
- if (of_find_property(dev->of_node, "phys", NULL)) {
- dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+ hpriv->nports = of_get_child_count(dev->of_node);
+
+ if (hpriv->nports) {
+ hpriv->phys = devm_kzalloc(dev,
+ hpriv->nports * sizeof(*hpriv->phys),
+ GFP_KERNEL);
+ if (!hpriv->phys) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ for_each_child_of_node(dev->of_node, child) {
+ u32 port;
+
+ if (!of_device_is_available(child))
+ continue;
+
+ if (of_property_read_u32(child, "reg", &port)) {
+ rc = -EINVAL;
goto err_out;
}
- case -ENODEV:
- /* continue normally */
- hpriv->phy = NULL;
- break;
- case -EPROBE_DEFER:
- goto err_out;
+ if (port >= hpriv->nports) {
+ dev_warn(dev, "invalid port number %d\n", port);
+ continue;
+ }
+
+ mask_port_map |= BIT(port);
- default:
- dev_err(dev, "couldn't get sata-phy\n");
+ hpriv->phys[port] = devm_of_phy_get(dev, child, NULL);
+ if (IS_ERR(hpriv->phys[port])) {
+ rc = PTR_ERR(hpriv->phys[port]);
+ dev_err(dev,
+ "couldn't get PHY in node %s: %d\n",
+ child->name, rc);
+ goto err_out;
+ }
+
+ enabled_ports++;
+ }
+ if (!enabled_ports) {
+ dev_warn(dev, "No port enabled\n");
+ rc = -ENODEV;
goto err_out;
}
+
+ if (!hpriv->mask_port_map)
+ hpriv->mask_port_map = mask_port_map;
+ } else {
+ /*
+ * If no sub-node was found, keep this for device tree
+ * compatibility
+ */
+ struct phy *phy = devm_phy_get(dev, "sata-phy");
+ if (!IS_ERR(phy)) {
+ hpriv->phys = devm_kzalloc(dev, sizeof(*hpriv->phys),
+ GFP_KERNEL);
+ if (!hpriv->phys) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ hpriv->phys[0] = phy;
+ hpriv->nports = 1;
+ } else {
+ rc = PTR_ERR(phy);
+ switch (rc) {
+ case -ENOSYS:
+ /* No PHY support. Check if PHY is required. */
+ if (of_find_property(dev->of_node, "phys", NULL)) {
+ dev_err(dev, "couldn't get sata-phy: ENOSYS\n");
+ goto err_out;
+ }
+ case -ENODEV:
+ /* continue normally */
+ hpriv->phys = NULL;
+ break;
+
+ default:
+ goto err_out;
+
+ }
+ }
}
pm_runtime_enable(dev);
@@ -288,12 +401,9 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
* @pdev: platform device pointer for the host
* @hpriv: ahci-host private data for the host
* @pi_template: template for the ata_port_info to use
- * @host_flags: ahci host flags used in ahci_host_priv
- * @force_port_map: param passed to ahci_save_initial_config
- * @mask_port_map: param passed to ahci_save_initial_config
*
* This function does all the usual steps needed to bring up an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
* must be initialized / enabled before calling this.
*
* RETURNS:
@@ -301,10 +411,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
*/
int ahci_platform_init_host(struct platform_device *pdev,
struct ahci_host_priv *hpriv,
- const struct ata_port_info *pi_template,
- unsigned long host_flags,
- unsigned int force_port_map,
- unsigned int mask_port_map)
+ const struct ata_port_info *pi_template)
{
struct device *dev = &pdev->dev;
struct ata_port_info pi = *pi_template;
@@ -319,10 +426,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
}
/* prepare host */
- pi.private_data = (void *)host_flags;
- hpriv->flags |= host_flags;
+ pi.private_data = (void *)(unsigned long)hpriv->flags;
- ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+ ahci_save_initial_config(dev, hpriv);
if (hpriv->cap & HOST_CAP_NCQ)
pi.flags |= ATA_FLAG_NCQ;
@@ -369,6 +475,19 @@ int ahci_platform_init_host(struct platform_device *pdev,
ap->ops = &ata_dummy_port_ops;
}
+ if (hpriv->cap & HOST_CAP_64) {
+ rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (rc) {
+ rc = dma_coerce_mask_and_coherent(dev,
+ DMA_BIT_MASK(32));
+ if (rc) {
+ dev_err(dev, "Failed to enable 64-bit DMA.\n");
+ return rc;
+ }
+ dev_warn(dev, "Enable 32-bit DMA instead of 64-bit.\n");
+ }
+ }
+
rc = ahci_reset_controller(host);
if (rc)
return rc;
@@ -399,7 +518,7 @@ static void ahci_host_stop(struct ata_host *host)
* @dev: device pointer for the host
*
* This function does all the usual steps needed to suspend an
- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * ahci-platform host, note any necessary resources (ie clks, phys, etc.)
* must be disabled after calling this.
*
* RETURNS:
@@ -436,7 +555,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
* @dev: device pointer for the host
*
* This function does all the usual steps needed to resume an ahci-platform
- * host, note any necessary resources (ie clks, phy, etc.) must be
+ * host, note any necessary resources (ie clks, phys, etc.) must be
* initialized / enabled before calling this.
*
* RETURNS:
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 677c0c1b03bd..dbdc5d32343f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -59,6 +59,7 @@
#include <linux/async.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/glob.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
@@ -4250,73 +4251,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ }
};
-/**
- * glob_match - match a text string against a glob-style pattern
- * @text: the string to be examined
- * @pattern: the glob-style pattern to be matched against
- *
- * Either/both of text and pattern can be empty strings.
- *
- * Match text against a glob-style pattern, with wildcards and simple sets:
- *
- * ? matches any single character.
- * * matches any run of characters.
- * [xyz] matches a single character from the set: x, y, or z.
- * [a-d] matches a single character from the range: a, b, c, or d.
- * [a-d0-9] matches a single character from either range.
- *
- * The special characters ?, [, -, or *, can be matched using a set, eg. [*]
- * Behaviour with malformed patterns is undefined, though generally reasonable.
- *
- * Sample patterns: "SD1?", "SD1[0-5]", "*R0", "SD*1?[012]*xx"
- *
- * This function uses one level of recursion per '*' in pattern.
- * Since it calls _nothing_ else, and has _no_ explicit local variables,
- * this will not cause stack problems for any reasonable use here.
- *
- * RETURNS:
- * 0 on match, 1 otherwise.
- */
-static int glob_match (const char *text, const char *pattern)
-{
- do {
- /* Match single character or a '?' wildcard */
- if (*text == *pattern || *pattern == '?') {
- if (!*pattern++)
- return 0; /* End of both strings: match */
- } else {
- /* Match single char against a '[' bracketed ']' pattern set */
- if (!*text || *pattern != '[')
- break; /* Not a pattern set */
- while (*++pattern && *pattern != ']' && *text != *pattern) {
- if (*pattern == '-' && *(pattern - 1) != '[')
- if (*text > *(pattern - 1) && *text < *(pattern + 1)) {
- ++pattern;
- break;
- }
- }
- if (!*pattern || *pattern == ']')
- return 1; /* No match */
- while (*pattern && *pattern++ != ']');
- }
- } while (*++text && *pattern);
-
- /* Match any run of chars against a '*' wildcard */
- if (*pattern == '*') {
- if (!*++pattern)
- return 0; /* Match: avoid recursion at end of pattern */
- /* Loop to handle additional pattern chars after the wildcard */
- while (*text) {
- if (glob_match(text, pattern) == 0)
- return 0; /* Remainder matched */
- ++text; /* Absorb (match) this char and try again */
- }
- }
- if (!*text && !*pattern)
- return 0; /* End of both strings: match */
- return 1; /* No match */
-}
-
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -4327,10 +4261,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
while (ad->model_num) {
- if (!glob_match(model_num, ad->model_num)) {
+ if (glob_match(model_num, ad->model_num)) {
if (ad->model_rev == NULL)
return ad->horkage;
- if (!glob_match(model_rev, ad->model_rev))
+ if (glob_match(model_rev, ad->model_rev))
return ad->horkage;
}
ad++;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 72691fd93948..0586f66d70fa 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3945,7 +3945,7 @@ void ata_scsi_hotplug(struct work_struct *work)
* Zero.
*/
int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
- unsigned int id, unsigned int lun)
+ unsigned int id, u64 lun)
{
struct ata_port *ap = ata_shost_to_port(shost);
unsigned long flags;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 45b5ab3a95d5..5f4e0cca56ec 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -144,7 +144,7 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap);
extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
- unsigned int id, unsigned int lun);
+ unsigned int id, u64 lun);
/* libata-eh.c */
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index fb528831fb92..2578fc16960a 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -54,7 +54,6 @@
enum s3c_cpu_type {
TYPE_S3C64XX,
- TYPE_S5PC100,
TYPE_S5PV210,
};
@@ -476,10 +475,6 @@ static void pata_s3c_hwinit(struct s3c_ide_info *info,
writel(0x1b, info->ide_addr + S3C_ATA_IRQ_MSK);
break;
- case TYPE_S5PC100:
- pata_s3c_cfg_mode(info->sfr_addr);
- /* FALLTHROUGH */
-
case TYPE_S5PV210:
/* Configure as little endian */
pata_s3c_set_endian(info->ide_addr, 0);
@@ -549,11 +544,6 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
info->sfr_addr = info->ide_addr + 0x1800;
info->ide_addr += 0x1900;
info->fifo_status_reg = 0x94;
- } else if (cpu_type == TYPE_S5PC100) {
- ap->ops = &pata_s5p_port_ops;
- info->sfr_addr = info->ide_addr + 0x1800;
- info->ide_addr += 0x1900;
- info->fifo_status_reg = 0x84;
} else {
ap->ops = &pata_s5p_port_ops;
info->fifo_status_reg = 0x84;
@@ -653,9 +643,6 @@ static struct platform_device_id pata_s3c_driver_ids[] = {
.name = "s3c64xx-pata",
.driver_data = TYPE_S3C64XX,
}, {
- .name = "s5pc100-pata",
- .driver_data = TYPE_S5PC100,
- }, {
.name = "s5pv210-pata",
.driver_data = TYPE_S5PV210,
},
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 616a6d2ac20c..07bc7e4dbd04 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -734,13 +734,12 @@ static int sata_fsl_port_start(struct ata_port *ap)
if (!pp)
return -ENOMEM;
- mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
- GFP_KERNEL);
+ mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+ GFP_KERNEL);
if (!mem) {
kfree(pp);
return -ENOMEM;
}
- memset(mem, 0, SATA_FSL_PORT_PRIV_DMA_SZ);
pp->cmdslot = mem;
pp->cmdslot_paddr = mem_dma;
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 65965cf5af06..da3bc2709c63 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -512,7 +512,7 @@ static int ahci_highbank_probe(struct platform_device *pdev)
return rc;
- ahci_save_initial_config(dev, hpriv, 0, 0);
+ ahci_save_initial_config(dev, hpriv);
/* prepare host */
if (hpriv->cap & HOST_CAP_NCQ)
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 0534890f118a..d81b20ddb527 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -1154,8 +1154,8 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
status = readl(host_base + HOST_IRQ_STAT);
if (status == 0xffffffff) {
- printk(KERN_ERR DRV_NAME ": IRQ status == 0xffffffff, "
- "PCI fault or device removal?\n");
+ dev_err(host->dev, "IRQ status == 0xffffffff, "
+ "PCI fault or device removal?\n");
goto out;
}
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index 0e3f8f9dcd29..480fa6ffbc09 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -299,6 +299,7 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
out_vcc = find_vcc(dev, ntohs(hdr->vpi), ntohs(hdr->vci));
read_unlock(&vcc_sklist_lock);
if (!out_vcc) {
+ result = -EUNATCH;
atomic_inc(&vcc->stats->tx_err);
goto done;
}
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index b1955ba40d63..d65975aba4ec 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -2155,7 +2155,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
if (!tx->send) continue;
if (!--left) {
- return sprintf(page,"tx[%d]: 0x%ld-0x%ld "
+ return sprintf(page, "tx[%d]: 0x%lx-0x%lx "
"(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
(unsigned long) (tx->send - eni_dev->ram),
tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
@@ -2181,7 +2181,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
if (--left) continue;
length = sprintf(page,"vcc %4d: ",vcc->vci);
if (eni_vcc->rx) {
- length += sprintf(page+length,"0x%ld-0x%ld "
+ length += sprintf(page+length, "0x%lx-0x%lx "
"(%6ld bytes)",
(unsigned long) (eni_vcc->recv - eni_dev->ram),
eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index aa6be2698669..c39702bc279d 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -533,14 +533,13 @@ static void he_init_tx_lbfp(struct he_dev *he_dev)
static int he_init_tpdrq(struct he_dev *he_dev)
{
- he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev,
- CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys);
+ he_dev->tpdrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+ CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
+ &he_dev->tpdrq_phys);
if (he_dev->tpdrq_base == NULL) {
hprintk("failed to alloc tpdrq\n");
return -ENOMEM;
}
- memset(he_dev->tpdrq_base, 0,
- CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq));
he_dev->tpdrq_tail = he_dev->tpdrq_base;
he_dev->tpdrq_head = he_dev->tpdrq_base;
@@ -804,13 +803,13 @@ static int he_init_group(struct he_dev *he_dev, int group)
goto out_free_rbpl_virt;
}
- he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
- CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
+ he_dev->rbpl_base = pci_zalloc_consistent(he_dev->pci_dev,
+ CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+ &he_dev->rbpl_phys);
if (he_dev->rbpl_base == NULL) {
hprintk("failed to alloc rbpl_base\n");
goto out_destroy_rbpl_pool;
}
- memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
INIT_LIST_HEAD(&he_dev->rbpl_outstanding);
@@ -843,13 +842,13 @@ static int he_init_group(struct he_dev *he_dev, int group)
/* rx buffer ready queue */
- he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev,
- CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
+ he_dev->rbrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+ CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+ &he_dev->rbrq_phys);
if (he_dev->rbrq_base == NULL) {
hprintk("failed to allocate rbrq\n");
goto out_free_rbpl;
}
- memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
he_dev->rbrq_head = he_dev->rbrq_base;
he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16));
@@ -867,13 +866,13 @@ static int he_init_group(struct he_dev *he_dev, int group)
/* tx buffer ready queue */
- he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev,
- CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
+ he_dev->tbrq_base = pci_zalloc_consistent(he_dev->pci_dev,
+ CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+ &he_dev->tbrq_phys);
if (he_dev->tbrq_base == NULL) {
hprintk("failed to allocate tbrq\n");
goto out_free_rbpq_base;
}
- memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
he_dev->tbrq_head = he_dev->tbrq_base;
@@ -1460,13 +1459,13 @@ static int he_start(struct atm_dev *dev)
/* host status page */
- he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev,
- sizeof(struct he_hsp), &he_dev->hsp_phys);
+ he_dev->hsp = pci_zalloc_consistent(he_dev->pci_dev,
+ sizeof(struct he_hsp),
+ &he_dev->hsp_phys);
if (he_dev->hsp == NULL) {
hprintk("failed to allocate host status page\n");
return -ENOMEM;
}
- memset(he_dev->hsp, 0, sizeof(struct he_hsp));
he_writel(he_dev, he_dev->hsp_phys, HSP_BA);
/* initialize framer */
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index b621f56a36be..2b24ed056728 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -641,13 +641,11 @@ alloc_scq(struct idt77252_dev *card, int class)
scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
if (!scq)
return NULL;
- scq->base = pci_alloc_consistent(card->pcidev, SCQ_SIZE,
- &scq->paddr);
+ scq->base = pci_zalloc_consistent(card->pcidev, SCQ_SIZE, &scq->paddr);
if (scq->base == NULL) {
kfree(scq);
return NULL;
}
- memset(scq->base, 0, SCQ_SIZE);
scq->next = scq->base;
scq->last = scq->base + (SCQ_ENTRIES - 1);
@@ -972,13 +970,12 @@ init_rsq(struct idt77252_dev *card)
{
struct rsq_entry *rsqe;
- card->rsq.base = pci_alloc_consistent(card->pcidev, RSQSIZE,
- &card->rsq.paddr);
+ card->rsq.base = pci_zalloc_consistent(card->pcidev, RSQSIZE,
+ &card->rsq.paddr);
if (card->rsq.base == NULL) {
printk("%s: can't allocate RSQ.\n", card->name);
return -1;
}
- memset(card->rsq.base, 0, RSQSIZE);
card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;
card->rsq.next = card->rsq.last;
@@ -3400,14 +3397,14 @@ static int init_card(struct atm_dev *dev)
writel(0, SAR_REG_GP);
/* Initialize RAW Cell Handle Register */
- card->raw_cell_hnd = pci_alloc_consistent(card->pcidev, 2 * sizeof(u32),
- &card->raw_cell_paddr);
+ card->raw_cell_hnd = pci_zalloc_consistent(card->pcidev,
+ 2 * sizeof(u32),
+ &card->raw_cell_paddr);
if (!card->raw_cell_hnd) {
printk("%s: memory allocation failure.\n", card->name);
deinit_card(card);
return -1;
}
- memset(card->raw_cell_hnd, 0, 2 * sizeof(u32));
writel(card->raw_cell_paddr, SAR_REG_RAWHND);
IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name,
card->raw_cell_hnd);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 943cf0d6abaf..7652e8dc188f 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -1278,6 +1278,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
if (!card->dma_bounce) {
dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
+ err = -ENOMEM;
/* Fallback to MMIO doesn't work */
goto out_unmap_both;
}
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 23b8726962af..4e7f0ff83ae7 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -149,15 +149,21 @@ config EXTRA_FIRMWARE_DIR
some other directory containing the firmware files.
config FW_LOADER_USER_HELPER
+ bool
+
+config FW_LOADER_USER_HELPER_FALLBACK
bool "Fallback user-helper invocation for firmware loading"
depends on FW_LOADER
- default y
+ select FW_LOADER_USER_HELPER
help
This option enables / disables the invocation of user-helper
(e.g. udev) for loading firmware files as a fallback after the
direct file loading in kernel fails. The user-mode helper is
no longer required unless you have a special firmware file that
- resides in a non-standard path.
+ resides in a non-standard path. Moreover, the udev support has
+ been deprecated upstream.
+
+ If you are unsure about this, say N here.
config DEBUG_DRIVER
bool "Driver Core verbose debug messages"
@@ -208,6 +214,15 @@ config DMA_SHARED_BUFFER
APIs extension; the file's descriptor can then be passed on to other
driver.
+config FENCE_TRACE
+ bool "Enable verbose FENCE_TRACE messages"
+ depends on DMA_SHARED_BUFFER
+ help
+ Enable the FENCE_TRACE printks. This will add extra
+ spam to the console log, but will make it easier to diagnose
+ lockup related problems for dma-buffers shared across multiple
+ devices.
+
config DMA_CMA
bool "DMA Contiguous Memory Allocator"
depends on HAVE_DMA_CONTIGUOUS && CMA
@@ -274,16 +289,6 @@ config CMA_ALIGNMENT
If unsure, leave the default value "8".
-config CMA_AREAS
- int "Maximum count of the CMA device-private areas"
- default 7
- help
- CMA allows to create CMA areas for particular devices. This parameter
- sets the maximum number of such device private CMA areas in the
- system.
-
- If unsure, leave the default value "7".
-
endif
endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 04b314e0fa51..4aab26ec0292 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
obj-y += power/
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o reservation.o
obj-$(CONFIG_ISA) += isa.o
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
diff --git a/drivers/base/component.c b/drivers/base/component.c
index c4778995cd72..f748430bb654 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -18,6 +18,15 @@
#include <linux/mutex.h>
#include <linux/slab.h>
+struct component_match {
+ size_t alloc;
+ size_t num;
+ struct {
+ void *data;
+ int (*fn)(struct device *, void *);
+ } compare[0];
+};
+
struct master {
struct list_head node;
struct list_head components;
@@ -25,6 +34,7 @@ struct master {
const struct component_master_ops *ops;
struct device *dev;
+ struct component_match *match;
};
struct component {
@@ -69,6 +79,11 @@ static void component_detach_master(struct master *master, struct component *c)
c->master = NULL;
}
+/*
+ * Add a component to a master, finding the component via the compare
+ * function and compare data. This is safe to call for duplicate matches
+ * and will not result in the same component being added multiple times.
+ */
int component_master_add_child(struct master *master,
int (*compare)(struct device *, void *), void *compare_data)
{
@@ -76,11 +91,12 @@ int component_master_add_child(struct master *master,
int ret = -ENXIO;
list_for_each_entry(c, &component_list, node) {
- if (c->master)
+ if (c->master && c->master != master)
continue;
if (compare(c->dev, compare_data)) {
- component_attach_master(master, c);
+ if (!c->master)
+ component_attach_master(master, c);
ret = 0;
break;
}
@@ -90,6 +106,34 @@ int component_master_add_child(struct master *master,
}
EXPORT_SYMBOL_GPL(component_master_add_child);
+static int find_components(struct master *master)
+{
+ struct component_match *match = master->match;
+ size_t i;
+ int ret = 0;
+
+ if (!match) {
+ /*
+ * Search the list of components, looking for components that
+ * belong to this master, and attach them to the master.
+ */
+ return master->ops->add_components(master->dev, master);
+ }
+
+ /*
+ * Scan the array of match functions and attach
+ * any components which are found to this master.
+ */
+ for (i = 0; i < match->num; i++) {
+ ret = component_master_add_child(master,
+ match->compare[i].fn,
+ match->compare[i].data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
/* Detach all attached components from this master */
static void master_remove_components(struct master *master)
{
@@ -113,44 +157,44 @@ static void master_remove_components(struct master *master)
static int try_to_bring_up_master(struct master *master,
struct component *component)
{
- int ret = 0;
+ int ret;
- if (!master->bound) {
- /*
- * Search the list of components, looking for components that
- * belong to this master, and attach them to the master.
- */
- if (master->ops->add_components(master->dev, master)) {
- /* Failed to find all components */
- master_remove_components(master);
- ret = 0;
- goto out;
- }
+ if (master->bound)
+ return 0;
- if (component && component->master != master) {
- master_remove_components(master);
- ret = 0;
- goto out;
- }
+ /*
+ * Search the list of components, looking for components that
+ * belong to this master, and attach them to the master.
+ */
+ if (find_components(master)) {
+ /* Failed to find all components */
+ ret = 0;
+ goto out;
+ }
- if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
- ret = -ENOMEM;
- goto out;
- }
+ if (component && component->master != master) {
+ ret = 0;
+ goto out;
+ }
- /* Found all components */
- ret = master->ops->bind(master->dev);
- if (ret < 0) {
- devres_release_group(master->dev, NULL);
- dev_info(master->dev, "master bind failed: %d\n", ret);
- master_remove_components(master);
- goto out;
- }
+ if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto out;
+ }
- master->bound = true;
- ret = 1;
+ /* Found all components */
+ ret = master->ops->bind(master->dev);
+ if (ret < 0) {
+ devres_release_group(master->dev, NULL);
+ dev_info(master->dev, "master bind failed: %d\n", ret);
+ goto out;
}
+
+ master->bound = true;
+ return 1;
+
out:
+ master_remove_components(master);
return ret;
}
@@ -180,18 +224,89 @@ static void take_down_master(struct master *master)
master_remove_components(master);
}
-int component_master_add(struct device *dev,
- const struct component_master_ops *ops)
+static size_t component_match_size(size_t num)
+{
+ return offsetof(struct component_match, compare[num]);
+}
+
+static struct component_match *component_match_realloc(struct device *dev,
+ struct component_match *match, size_t num)
+{
+ struct component_match *new;
+
+ if (match && match->alloc == num)
+ return match;
+
+ new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);
+ if (!new)
+ return ERR_PTR(-ENOMEM);
+
+ if (match) {
+ memcpy(new, match, component_match_size(min(match->num, num)));
+ devm_kfree(dev, match);
+ } else {
+ new->num = 0;
+ }
+
+ new->alloc = num;
+
+ return new;
+}
+
+/*
+ * Add a component to be matched.
+ *
+ * The match array is first created or extended if necessary.
+ */
+void component_match_add(struct device *dev, struct component_match **matchptr,
+ int (*compare)(struct device *, void *), void *compare_data)
+{
+ struct component_match *match = *matchptr;
+
+ if (IS_ERR(match))
+ return;
+
+ if (!match || match->num == match->alloc) {
+ size_t new_size = match ? match->alloc + 16 : 15;
+
+ match = component_match_realloc(dev, match, new_size);
+
+ *matchptr = match;
+
+ if (IS_ERR(match))
+ return;
+ }
+
+ match->compare[match->num].fn = compare;
+ match->compare[match->num].data = compare_data;
+ match->num++;
+}
+EXPORT_SYMBOL(component_match_add);
+
+int component_master_add_with_match(struct device *dev,
+ const struct component_master_ops *ops,
+ struct component_match *match)
{
struct master *master;
int ret;
+ if (ops->add_components && match)
+ return -EINVAL;
+
+ if (match) {
+ /* Reallocate the match array for its true size */
+ match = component_match_realloc(dev, match, match->num);
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+ }
+
master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master)
return -ENOMEM;
master->dev = dev;
master->ops = ops;
+ master->match = match;
INIT_LIST_HEAD(&master->components);
/* Add to the list of available masters. */
@@ -209,6 +324,13 @@ int component_master_add(struct device *dev,
return ret < 0 ? ret : 0;
}
+EXPORT_SYMBOL_GPL(component_master_add_with_match);
+
+int component_master_add(struct device *dev,
+ const struct component_master_ops *ops)
+{
+ return component_master_add_with_match(dev, ops, NULL);
+}
EXPORT_SYMBOL_GPL(component_master_add);
void component_master_del(struct device *dev,
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 52302946770f..69d9b0c89a01 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -817,6 +817,61 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
EXPORT_SYMBOL_GPL(devm_kstrdup);
/**
+ * devm_kvasprintf - Allocate resource managed space
+ * for the formatted string.
+ * @dev: Device to allocate memory for
+ * @gfp: the GFP mask used in the devm_kmalloc() call when
+ * allocating memory
+ * @fmt: the formatted string to duplicate
+ * @ap: the list of tokens to be placed in the formatted string
+ * RETURNS:
+ * Pointer to allocated string on success, NULL on failure.
+ */
+char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
+ va_list ap)
+{
+ unsigned int len;
+ char *p;
+ va_list aq;
+
+ va_copy(aq, ap);
+ len = vsnprintf(NULL, 0, fmt, aq);
+ va_end(aq);
+
+ p = devm_kmalloc(dev, len+1, gfp);
+ if (!p)
+ return NULL;
+
+ vsnprintf(p, len+1, fmt, ap);
+
+ return p;
+}
+EXPORT_SYMBOL(devm_kvasprintf);
+
+/**
+ * devm_kasprintf - Allocate resource managed space
+ * and copy an existing formatted string into that
+ * @dev: Device to allocate memory for
+ * @gfp: the GFP mask used in the devm_kmalloc() call when
+ * allocating memory
+ * @fmt: the string to duplicate
+ * RETURNS:
+ * Pointer to allocated string on success, NULL on failure.
+ */
+char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...)
+{
+ va_list ap;
+ char *p;
+
+ va_start(ap, fmt);
+ p = devm_kvasprintf(dev, gfp, fmt, ap);
+ va_end(ap);
+
+ return p;
+}
+EXPORT_SYMBOL_GPL(devm_kasprintf);
+
+/**
* devm_kfree - Resource-managed kfree
* @dev: Device this memory belongs to
* @p: Memory to free
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 6467c919c509..6606abdf880c 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -24,23 +24,9 @@
#include <linux/memblock.h>
#include <linux/err.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/page-isolation.h>
#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/swap.h>
-#include <linux/mm_types.h>
#include <linux/dma-contiguous.h>
-
-struct cma {
- unsigned long base_pfn;
- unsigned long count;
- unsigned long *bitmap;
- struct mutex lock;
-};
-
-struct cma *dma_contiguous_default_area;
+#include <linux/cma.h>
#ifdef CONFIG_CMA_SIZE_MBYTES
#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
@@ -48,6 +34,8 @@ struct cma *dma_contiguous_default_area;
#define CMA_SIZE_MBYTES 0
#endif
+struct cma *dma_contiguous_default_area;
+
/*
* Default global CMA area size can be defined in kernel's .config.
* This is useful mainly for distro maintainers to create a kernel
@@ -154,65 +142,6 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
}
}
-static DEFINE_MUTEX(cma_mutex);
-
-static int __init cma_activate_area(struct cma *cma)
-{
- int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long);
- unsigned long base_pfn = cma->base_pfn, pfn = base_pfn;
- unsigned i = cma->count >> pageblock_order;
- struct zone *zone;
-
- cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-
- if (!cma->bitmap)
- return -ENOMEM;
-
- WARN_ON_ONCE(!pfn_valid(pfn));
- zone = page_zone(pfn_to_page(pfn));
-
- do {
- unsigned j;
- base_pfn = pfn;
- for (j = pageblock_nr_pages; j; --j, pfn++) {
- WARN_ON_ONCE(!pfn_valid(pfn));
- /*
- * alloc_contig_range requires the pfn range
- * specified to be in the same zone. Make this
- * simple by forcing the entire CMA resv range
- * to be in the same zone.
- */
- if (page_zone(pfn_to_page(pfn)) != zone)
- goto err;
- }
- init_cma_reserved_pageblock(pfn_to_page(base_pfn));
- } while (--i);
-
- mutex_init(&cma->lock);
- return 0;
-
-err:
- kfree(cma->bitmap);
- return -EINVAL;
-}
-
-static struct cma cma_areas[MAX_CMA_AREAS];
-static unsigned cma_area_count;
-
-static int __init cma_init_reserved_areas(void)
-{
- int i;
-
- for (i = 0; i < cma_area_count; i++) {
- int ret = cma_activate_area(&cma_areas[i]);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-core_initcall(cma_init_reserved_areas);
-
/**
* dma_contiguous_reserve_area() - reserve custom contiguous area
* @size: Size of the reserved area (in bytes),
@@ -234,72 +163,17 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
phys_addr_t limit, struct cma **res_cma,
bool fixed)
{
- struct cma *cma = &cma_areas[cma_area_count];
- phys_addr_t alignment;
- int ret = 0;
-
- pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
- (unsigned long)size, (unsigned long)base,
- (unsigned long)limit);
-
- /* Sanity checks */
- if (cma_area_count == ARRAY_SIZE(cma_areas)) {
- pr_err("Not enough slots for CMA reserved regions!\n");
- return -ENOSPC;
- }
-
- if (!size)
- return -EINVAL;
-
- /* Sanitise input arguments */
- alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
- base = ALIGN(base, alignment);
- size = ALIGN(size, alignment);
- limit &= ~(alignment - 1);
-
- /* Reserve memory */
- if (base && fixed) {
- if (memblock_is_region_reserved(base, size) ||
- memblock_reserve(base, size) < 0) {
- ret = -EBUSY;
- goto err;
- }
- } else {
- phys_addr_t addr = memblock_alloc_range(size, alignment, base,
- limit);
- if (!addr) {
- ret = -ENOMEM;
- goto err;
- } else {
- base = addr;
- }
- }
-
- /*
- * Each reserved area must be initialised later, when more kernel
- * subsystems (like slab allocator) are available.
- */
- cma->base_pfn = PFN_DOWN(base);
- cma->count = size >> PAGE_SHIFT;
- *res_cma = cma;
- cma_area_count++;
+ int ret;
- pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
- (unsigned long)base);
+ ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma);
+ if (ret)
+ return ret;
/* Architecture specific contiguous memory fixup. */
- dma_contiguous_early_fixup(base, size);
- return 0;
-err:
- pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
- return ret;
-}
+ dma_contiguous_early_fixup(cma_get_base(*res_cma),
+ cma_get_size(*res_cma));
-static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count)
-{
- mutex_lock(&cma->lock);
- bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count);
- mutex_unlock(&cma->lock);
+ return 0;
}
/**
@@ -316,62 +190,10 @@ static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count)
struct page *dma_alloc_from_contiguous(struct device *dev, int count,
unsigned int align)
{
- unsigned long mask, pfn, pageno, start = 0;
- struct cma *cma = dev_get_cma_area(dev);
- struct page *page = NULL;
- int ret;
-
- if (!cma || !cma->count)
- return NULL;
-
if (align > CONFIG_CMA_ALIGNMENT)
align = CONFIG_CMA_ALIGNMENT;
- pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
- count, align);
-
- if (!count)
- return NULL;
-
- mask = (1 << align) - 1;
-
-
- for (;;) {
- mutex_lock(&cma->lock);
- pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
- start, count, mask);
- if (pageno >= cma->count) {
- mutex_unlock(&cma->lock);
- break;
- }
- bitmap_set(cma->bitmap, pageno, count);
- /*
- * It's safe to drop the lock here. We've marked this region for
- * our exclusive use. If the migration fails we will take the
- * lock again and unmark it.
- */
- mutex_unlock(&cma->lock);
-
- pfn = cma->base_pfn + pageno;
- mutex_lock(&cma_mutex);
- ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
- mutex_unlock(&cma_mutex);
- if (ret == 0) {
- page = pfn_to_page(pfn);
- break;
- } else if (ret != -EBUSY) {
- clear_cma_bitmap(cma, pfn, count);
- break;
- }
- clear_cma_bitmap(cma, pfn, count);
- pr_debug("%s(): memory range at %p is busy, retrying\n",
- __func__, pfn_to_page(pfn));
- /* try again with a bit different memory target */
- start = pageno + mask + 1;
- }
-
- pr_debug("%s(): returned %p\n", __func__, page);
- return page;
+ return cma_alloc(dev_get_cma_area(dev), count, align);
}
/**
@@ -387,23 +209,5 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count,
bool dma_release_from_contiguous(struct device *dev, struct page *pages,
int count)
{
- struct cma *cma = dev_get_cma_area(dev);
- unsigned long pfn;
-
- if (!cma || !pages)
- return false;
-
- pr_debug("%s(page %p)\n", __func__, (void *)pages);
-
- pfn = page_to_pfn(pages);
-
- if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count)
- return false;
-
- VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
-
- free_contig_range(pfn, count);
- clear_cma_bitmap(cma, pfn, count);
-
- return true;
+ return cma_release(dev_get_cma_area(dev), pages, count);
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index d276e33880be..bf424305f3dc 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -28,6 +28,7 @@
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
+#include <linux/security.h>
#include <generated/utsrelease.h>
@@ -100,10 +101,16 @@ static inline long firmware_loading_timeout(void)
#define FW_OPT_UEVENT (1U << 0)
#define FW_OPT_NOWAIT (1U << 1)
#ifdef CONFIG_FW_LOADER_USER_HELPER
-#define FW_OPT_FALLBACK (1U << 2)
+#define FW_OPT_USERHELPER (1U << 2)
#else
-#define FW_OPT_FALLBACK 0
+#define FW_OPT_USERHELPER 0
#endif
+#ifdef CONFIG_FW_LOADER_USER_HELPER_FALLBACK
+#define FW_OPT_FALLBACK FW_OPT_USERHELPER
+#else
+#define FW_OPT_FALLBACK 0
+#endif
+#define FW_OPT_NO_WARN (1U << 3)
struct firmware_cache {
/* firmware_buf instance will be added into the below list */
@@ -279,26 +286,15 @@ static const char * const fw_path[] = {
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_for_stack int fw_file_size(struct file *file)
-{
- struct kstat st;
- if (vfs_getattr(&file->f_path, &st))
- return -1;
- if (!S_ISREG(st.mode))
- return -1;
- if (st.size != (int)st.size)
- return -1;
- return st.size;
-}
-
static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
{
int size;
char *buf;
int rc;
- size = fw_file_size(file);
+ if (!S_ISREG(file_inode(file)->i_mode))
+ return -EINVAL;
+ size = i_size_read(file_inode(file));
if (size <= 0)
return -EINVAL;
buf = vmalloc(size);
@@ -308,12 +304,17 @@ static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
if (rc != size) {
if (rc > 0)
rc = -EIO;
- vfree(buf);
- return rc;
+ goto fail;
}
+ rc = security_kernel_fw_from_file(file, buf, size);
+ if (rc)
+ goto fail;
fw_buf->data = buf;
fw_buf->size = size;
return 0;
+fail:
+ vfree(buf);
+ return rc;
}
static int fw_get_filesystem_firmware(struct device *device,
@@ -617,6 +618,7 @@ static ssize_t firmware_loading_store(struct device *dev,
{
struct firmware_priv *fw_priv = to_firmware_priv(dev);
struct firmware_buf *fw_buf;
+ ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10);
int i;
@@ -640,6 +642,8 @@ static ssize_t firmware_loading_store(struct device *dev,
break;
case 0:
if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+ int rc;
+
set_bit(FW_STATUS_DONE, &fw_buf->status);
clear_bit(FW_STATUS_LOADING, &fw_buf->status);
@@ -649,10 +653,23 @@ static ssize_t firmware_loading_store(struct device *dev,
* see the mapped 'buf->data' once the loading
* is completed.
* */
- if (fw_map_pages_buf(fw_buf))
+ rc = fw_map_pages_buf(fw_buf);
+ if (rc)
dev_err(dev, "%s: map pages failed\n",
__func__);
+ else
+ rc = security_kernel_fw_from_file(NULL,
+ fw_buf->data, fw_buf->size);
+
+ /*
+ * Same logic as fw_load_abort, only the DONE bit
+ * is ignored and we set ABORT only on failure.
+ */
list_del_init(&fw_buf->pending_list);
+ if (rc) {
+ set_bit(FW_STATUS_ABORT, &fw_buf->status);
+ written = rc;
+ }
complete_all(&fw_buf->completion);
break;
}
@@ -666,7 +683,7 @@ static ssize_t firmware_loading_store(struct device *dev,
}
out:
mutex_unlock(&fw_lock);
- return count;
+ return written;
}
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
@@ -718,7 +735,7 @@ out:
static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
{
struct firmware_buf *buf = fw_priv->buf;
- int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
+ int pages_needed = PAGE_ALIGN(min_size) >> PAGE_SHIFT;
/* If the array of pages is too small, grow it... */
if (buf->page_array_size < pages_needed) {
@@ -911,7 +928,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
wait_for_completion(&buf->completion);
cancel_delayed_work_sync(&fw_priv->timeout_work);
- if (!buf->data)
+ if (is_fw_load_aborted(buf))
+ retval = -EAGAIN;
+ else if (!buf->data)
retval = -ENOMEM;
device_remove_file(f_dev, &dev_attr_loading);
@@ -1111,10 +1130,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
ret = fw_get_filesystem_firmware(device, fw->priv);
if (ret) {
- if (opt_flags & FW_OPT_FALLBACK) {
+ if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,
- "Direct firmware load failed with error %d\n",
- ret);
+ "Direct firmware load for %s failed with error %d\n",
+ name, ret);
+ if (opt_flags & FW_OPT_USERHELPER) {
dev_warn(device, "Falling back to user helper\n");
ret = fw_load_from_user_helper(fw, name, device,
opt_flags, timeout);
@@ -1171,7 +1191,6 @@ request_firmware(const struct firmware **firmware_p, const char *name,
}
EXPORT_SYMBOL(request_firmware);
-#ifdef CONFIG_FW_LOADER_USER_HELPER
/**
* request_firmware: - load firmware directly without usermode helper
* @firmware_p: pointer to firmware image
@@ -1188,12 +1207,12 @@ int request_firmware_direct(const struct firmware **firmware_p,
{
int ret;
__module_get(THIS_MODULE);
- ret = _request_firmware(firmware_p, name, device, FW_OPT_UEVENT);
+ ret = _request_firmware(firmware_p, name, device,
+ FW_OPT_UEVENT | FW_OPT_NO_WARN);
module_put(THIS_MODULE);
return ret;
}
EXPORT_SYMBOL_GPL(request_firmware_direct);
-#endif
/**
* release_firmware: - release the resource associated with a firmware image
@@ -1277,7 +1296,7 @@ request_firmware_nowait(
fw_work->context = context;
fw_work->cont = cont;
fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_FALLBACK |
- (uevent ? FW_OPT_UEVENT : 0);
+ (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
if (!try_module_get(module)) {
kfree(fw_work);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 89f752dd8465..a2e13e250bba 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -284,7 +284,7 @@ static int memory_subsys_online(struct device *dev)
* attribute and need to set the online_type.
*/
if (mem->online_type < 0)
- mem->online_type = ONLINE_KEEP;
+ mem->online_type = MMOP_ONLINE_KEEP;
ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
@@ -315,23 +315,23 @@ store_mem_state(struct device *dev,
if (ret)
return ret;
- if (!strncmp(buf, "online_kernel", min_t(int, count, 13)))
- online_type = ONLINE_KERNEL;
- else if (!strncmp(buf, "online_movable", min_t(int, count, 14)))
- online_type = ONLINE_MOVABLE;
- else if (!strncmp(buf, "online", min_t(int, count, 6)))
- online_type = ONLINE_KEEP;
- else if (!strncmp(buf, "offline", min_t(int, count, 7)))
- online_type = -1;
+ if (sysfs_streq(buf, "online_kernel"))
+ online_type = MMOP_ONLINE_KERNEL;
+ else if (sysfs_streq(buf, "online_movable"))
+ online_type = MMOP_ONLINE_MOVABLE;
+ else if (sysfs_streq(buf, "online"))
+ online_type = MMOP_ONLINE_KEEP;
+ else if (sysfs_streq(buf, "offline"))
+ online_type = MMOP_OFFLINE;
else {
ret = -EINVAL;
goto err;
}
switch (online_type) {
- case ONLINE_KERNEL:
- case ONLINE_MOVABLE:
- case ONLINE_KEEP:
+ case MMOP_ONLINE_KERNEL:
+ case MMOP_ONLINE_MOVABLE:
+ case MMOP_ONLINE_KEEP:
/*
* mem->online_type is not protected so there can be a
* race here. However, when racing online, the first
@@ -342,7 +342,7 @@ store_mem_state(struct device *dev,
mem->online_type = online_type;
ret = device_online(&mem->dev);
break;
- case -1:
+ case MMOP_OFFLINE:
ret = device_offline(&mem->dev);
break;
default:
@@ -406,7 +406,9 @@ memory_probe_store(struct device *dev, struct device_attribute *attr,
int i, ret;
unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
- phys_addr = simple_strtoull(buf, NULL, 0);
+ ret = kstrtoull(buf, 0, &phys_addr);
+ if (ret)
+ return ret;
if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
return -EINVAL;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 8f7ed9933a7c..c6d3ae05f1ca 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -126,7 +126,7 @@ static ssize_t node_read_meminfo(struct device *dev,
nid, K(node_page_state(nid, NR_FILE_PAGES)),
nid, K(node_page_state(nid, NR_FILE_MAPPED)),
nid, K(node_page_state(nid, NR_ANON_PAGES)),
- nid, K(node_page_state(nid, NR_SHMEM)),
+ nid, K(i.sharedram),
nid, node_page_state(nid, NR_KERNEL_STACK) *
THREAD_SIZE / 1024,
nid, K(node_page_state(nid, NR_PAGETABLE)),
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index eee48c49f5de..ab4f4ce02722 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -23,6 +23,8 @@
#include <linux/pm_runtime.h>
#include <linux/idr.h>
#include <linux/acpi.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/limits.h>
#include "base.h"
#include "power/power.h"
@@ -175,7 +177,7 @@ EXPORT_SYMBOL_GPL(platform_add_devices);
struct platform_object {
struct platform_device pdev;
- char name[1];
+ char name[];
};
/**
@@ -201,6 +203,7 @@ static void platform_device_release(struct device *dev)
kfree(pa->pdev.dev.platform_data);
kfree(pa->pdev.mfd_cell);
kfree(pa->pdev.resource);
+ kfree(pa->pdev.driver_override);
kfree(pa);
}
@@ -216,7 +219,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;
- pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
+ pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name;
@@ -499,6 +502,10 @@ static int platform_drv_probe(struct device *_dev)
struct platform_device *dev = to_platform_device(_dev);
int ret;
+ ret = of_clk_set_defaults(_dev->of_node, false);
+ if (ret < 0)
+ return ret;
+
acpi_dev_pm_attach(_dev, true);
ret = drv->probe(dev);
@@ -708,8 +715,49 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
}
static DEVICE_ATTR_RO(modalias);
+static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ char *driver_override, *old = pdev->driver_override, *cp;
+
+ if (count > PATH_MAX)
+ return -EINVAL;
+
+ driver_override = kstrndup(buf, count, GFP_KERNEL);
+ if (!driver_override)
+ return -ENOMEM;
+
+ cp = strchr(driver_override, '\n');
+ if (cp)
+ *cp = '\0';
+
+ if (strlen(driver_override)) {
+ pdev->driver_override = driver_override;
+ } else {
+ kfree(driver_override);
+ pdev->driver_override = NULL;
+ }
+
+ kfree(old);
+
+ return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return sprintf(buf, "%s\n", pdev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
+
static struct attribute *platform_dev_attrs[] = {
&dev_attr_modalias.attr,
+ &dev_attr_driver_override.attr,
NULL,
};
ATTRIBUTE_GROUPS(platform_dev);
@@ -765,6 +813,10 @@ static int platform_match(struct device *dev, struct device_driver *drv)
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
+ /* When driver_override is set, only bind to the matching driver */
+ if (pdev->driver_override)
+ return !strcmp(pdev->driver_override, drv->name);
+
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index bf412961a934..b67d9aef9fe4 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -465,6 +465,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
* device_resume_noirq - Execute an "early resume" callback for given device.
* @dev: Device to handle.
* @state: PM transition of the system being carried out.
+ * @async: If true, the device is being resumed asynchronously.
*
* The driver of @dev will not receive interrupts while this function is being
* executed.
@@ -594,6 +595,7 @@ static void dpm_resume_noirq(pm_message_t state)
* device_resume_early - Execute an "early resume" callback for given device.
* @dev: Device to handle.
* @state: PM transition of the system being carried out.
+ * @async: If true, the device is being resumed asynchronously.
*
* Runtime PM is disabled for @dev while this function is being executed.
*/
@@ -1004,6 +1006,7 @@ static pm_message_t resume_event(pm_message_t sleep_state)
* device_suspend_noirq - Execute a "late suspend" callback for given device.
* @dev: Device to handle.
* @state: PM transition of the system being carried out.
+ * @async: If true, the device is being suspended asynchronously.
*
* The driver of @dev will not receive interrupts while this function is being
* executed.
@@ -1144,6 +1147,7 @@ static int dpm_suspend_noirq(pm_message_t state)
* device_suspend_late - Execute a "late suspend" callback for given device.
* @dev: Device to handle.
* @state: PM transition of the system being carried out.
+ * @async: If true, the device is being suspended asynchronously.
*
* Runtime PM is disabled for @dev while this function is being executed.
*/
@@ -1298,6 +1302,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
* @dev: Device to suspend.
* @state: PM transition of the system being carried out.
* @cb: Suspend callback to execute.
+ * @info: string description of caller.
*/
static int legacy_suspend(struct device *dev, pm_message_t state,
int (*cb)(struct device *dev, pm_message_t state),
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 74d8c0672cf6..78f43fb2fe84 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1073,6 +1073,19 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
}
EXPORT_SYMBOL_GPL(dev_get_regmap);
+/**
+ * regmap_get_device(): Obtain the device from a regmap
+ *
+ * @map: Register map to operate on.
+ *
+ * Returns the underlying device that the regmap has been created for.
+ */
+struct device *regmap_get_device(struct regmap *map)
+{
+ return map->dev;
+}
+EXPORT_SYMBOL_GPL(regmap_get_device);
+
static int _regmap_select_page(struct regmap *map, unsigned int *reg,
struct regmap_range_node *range,
unsigned int val_num)
diff --git a/drivers/base/reservation.c b/drivers/base/reservation.c
deleted file mode 100644
index a73fbf3b8e56..000000000000
--- a/drivers/base/reservation.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Canonical Ltd
- *
- * Based on bo.c which bears the following copyright notice,
- * but is dual licensed:
- *
- * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-/*
- * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
- */
-
-#include <linux/reservation.h>
-#include <linux/export.h>
-
-DEFINE_WW_CLASS(reservation_ww_class);
-EXPORT_SYMBOL(reservation_ww_class);
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 734b32f09c0a..91290f7f61b8 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
bcma-y += driver_pci.o
+bcma-y += driver_pcie2.o
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 5081a8c439cc..fe0d48cb1778 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -603,6 +603,8 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
break;
+ case BCMA_CHIP_ID_BCM43131:
+ case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428:
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index d7f81ad56b8a..aec9f850b4a8 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -220,6 +220,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
#endif
switch (cc->core->bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM5357:
+ case BCMA_CHIP_ID_BCM53572:
chip->ngpio = 32;
break;
default:
diff --git a/drivers/bcma/driver_pcie2.c b/drivers/bcma/driver_pcie2.c
new file mode 100644
index 000000000000..e4be537b0c66
--- /dev/null
+++ b/drivers/bcma/driver_pcie2.c
@@ -0,0 +1,175 @@
+/*
+ * Broadcom specific AMBA
+ * PCIe Gen 2 Core
+ *
+ * Copyright 2014, Broadcom Corporation
+ * Copyright 2014, Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+#if 0
+static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr)
+{
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
+ pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR);
+ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
+}
+#endif
+
+static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr,
+ u32 val)
+{
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val);
+}
+
+/**************************************************
+ * Init.
+ **************************************************/
+
+static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2,
+ bool enable)
+{
+ u32 val;
+
+ /* restore back to default */
+ val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
+ val |= PCIE2_CLKC_DLYPERST;
+ val &= ~PCIE2_CLKC_DISSPROMLD;
+ if (enable) {
+ val &= ~PCIE2_CLKC_DLYPERST;
+ val |= PCIE2_CLKC_DISSPROMLD;
+ }
+ pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val);
+ /* flush */
+ return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
+}
+
+static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2)
+{
+ /* LTR0 */
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c);
+ /* LTR1 */
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864);
+ /* LTR2 */
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003);
+}
+
+static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2)
+{
+ u8 core_rev = pcie2->core->id.rev;
+ u32 devstsctr2;
+
+ if (core_rev < 2 || core_rev == 10 || core_rev > 13)
+ return;
+
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+ PCIE2_CAP_DEVSTSCTRL2_OFFSET);
+ devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
+ if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) {
+ /* force the right LTR values */
+ bcma_core_pcie2_set_ltr_vals(pcie2);
+
+ /* TODO:
+ si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */
+
+ /* enable the LTR */
+ devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB;
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+ PCIE2_CAP_DEVSTSCTRL2_OFFSET);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2);
+
+ /* set the LTR state to be active */
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
+ PCIE2_LTR_ACTIVE);
+ usleep_range(1000, 2000);
+
+ /* set the LTR state to be sleep */
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
+ PCIE2_LTR_SLEEP);
+ usleep_range(1000, 2000);
+ }
+}
+
+static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2)
+{
+ u8 core_rev = pcie2->core->id.rev;
+ bool pciewar160, pciewar162;
+
+ pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11;
+ pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 ||
+ core_rev == 9 || core_rev == 11;
+
+ if (!pciewar160 && !pciewar162)
+ return;
+
+/* TODO */
+#if 0
+ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL,
+ PCIE_DISABLE_L1CLK_GATING);
+#if 0
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+ PCIEGEN2_COE_PVT_TL_CTRL_0);
+ pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA,
+ ~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT));
+#endif
+#endif
+}
+
+static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2)
+{
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP);
+ pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f);
+}
+
+static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2)
+{
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0);
+}
+
+static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2)
+{
+ struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc;
+ u8 core_rev = pcie2->core->id.rev;
+ u32 alp_khz, pm_value;
+
+ if (core_rev <= 13) {
+ alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000;
+ pm_value = (1000000 * 2) / alp_khz;
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
+ PCIE2_PVT_REG_PM_CLK_PERIOD);
+ pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value);
+ }
+}
+
+void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2)
+{
+ struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo;
+ u32 tmp;
+
+ tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54));
+ if ((tmp & 0xe) >> 1 == 2)
+ bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17);
+
+ /* TODO: Do we need pcie_reqsize? */
+
+ if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3)
+ bcma_core_pcie2_war_delay_perst_enab(pcie2, true);
+ bcma_core_pcie2_hw_ltr_war(pcie2);
+ pciedev_crwlpciegen2(pcie2);
+ pciedev_reg_pm_clk_period(pcie2);
+ pciedev_crwlpciegen2_180(pcie2);
+ pciedev_crwlpciegen2_182(pcie2);
+}
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index e333305363aa..294a7dd25190 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -279,6 +279,8 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, },
};
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 34ea4c588d36..0ff8d58831ef 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
case BCMA_CORE_CHIPCOMMON:
case BCMA_CORE_PCI:
case BCMA_CORE_PCIE:
+ case BCMA_CORE_PCIE2:
case BCMA_CORE_MIPS_74K:
case BCMA_CORE_4706_MAC_GBIT_COMMON:
continue;
@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_pci_init(&bus->drv_pci[1]);
}
+ /* Init PCIe Gen 2 core */
+ core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0);
+ if (core) {
+ bus->drv_pcie2.core = core;
+ bcma_core_pcie2_init(&bus->drv_pcie2);
+ }
+
/* Init GBIT MAC COMMON core */
core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
if (core) {
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 37768401d113..b4764c6bcf17 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -32,17 +32,17 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
- { BCMA_CORE_PCIEG2, "PCIe Gen 2" },
- { BCMA_CORE_DMA, "DMA" },
- { BCMA_CORE_SDIO3, "SDIO3" },
- { BCMA_CORE_USB20, "USB 2.0" },
- { BCMA_CORE_USB30, "USB 3.0" },
- { BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" },
- { BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" },
- { BCMA_CORE_ROM, "ROM" },
- { BCMA_CORE_NAND, "NAND flash controller" },
- { BCMA_CORE_QSPI, "SPI flash controller" },
- { BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" },
+ { BCMA_CORE_NS_PCIEG2, "PCIe Gen 2" },
+ { BCMA_CORE_NS_DMA, "DMA" },
+ { BCMA_CORE_NS_SDIO3, "SDIO3" },
+ { BCMA_CORE_NS_USB20, "USB 2.0" },
+ { BCMA_CORE_NS_USB30, "USB 3.0" },
+ { BCMA_CORE_NS_A9JTAG, "ARM Cortex A9 JTAG" },
+ { BCMA_CORE_NS_DDR23, "Denali DDR2/DDR3 memory controller" },
+ { BCMA_CORE_NS_ROM, "ROM" },
+ { BCMA_CORE_NS_NAND, "NAND flash controller" },
+ { BCMA_CORE_NS_QSPI, "SPI flash controller" },
+ { BCMA_CORE_NS_CHIPCOMMON_B, "Chipcommon B" },
{ BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 72bf4540f565..efb037f9c98a 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
SPEX(_field[7], _offset + 14, _mask, _shift); \
} while (0)
+static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift)
+{
+ u16 v;
+ u8 gain;
+
+ v = in[SPOFF(offset)];
+ gain = (v & mask) >> shift;
+ if (gain == 0xFF) {
+ gain = 8; /* If unset use 2dBm */
+ } else {
+ /* Q5.2 Fractional part is stored in 0xC0 */
+ gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
+ }
+
+ return (s8)gain;
+}
+
static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
{
u16 v, o;
@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
/* Extract the antenna gain values. */
- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+ bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom,
+ SSB_SPROM8_AGAIN01,
+ SSB_SPROM8_AGAIN0,
+ SSB_SPROM8_AGAIN0_SHIFT);
+ bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom,
+ SSB_SPROM8_AGAIN01,
+ SSB_SPROM8_AGAIN1,
+ SSB_SPROM8_AGAIN1_SHIFT);
+ bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom,
+ SSB_SPROM8_AGAIN23,
+ SSB_SPROM8_AGAIN2,
+ SSB_SPROM8_AGAIN2_SHIFT);
+ bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom,
+ SSB_SPROM8_AGAIN23,
+ SSB_SPROM8_AGAIN3,
+ SSB_SPROM8_AGAIN3_SHIFT);
SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
SSB_SPROM8_LEDDC_ON_SHIFT);
@@ -509,6 +534,8 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
/* for these chips OTP is always available */
present = true;
break;
+ case BCMA_CHIP_ID_BCM43131:
+ case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428:
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 125d84505738..811e11c82f32 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -6741,11 +6741,11 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
ErrorCode = -ENOMEM;
if (DataTransferLength > 0)
{
- DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
- DataTransferLength, &DataTransferBufferDMA);
+ DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+ DataTransferLength,
+ &DataTransferBufferDMA);
if (DataTransferBuffer == NULL)
break;
- memset(DataTransferBuffer, 0, DataTransferLength);
}
else if (DataTransferLength < 0)
{
@@ -6877,11 +6877,11 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
ErrorCode = -ENOMEM;
if (DataTransferLength > 0)
{
- DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
- DataTransferLength, &DataTransferBufferDMA);
+ DataTransferBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+ DataTransferLength,
+ &DataTransferBufferDMA);
if (DataTransferBuffer == NULL)
break;
- memset(DataTransferBuffer, 0, DataTransferLength);
}
else if (DataTransferLength < 0)
{
@@ -6899,14 +6899,14 @@ static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
RequestSenseLength = UserCommand.RequestSenseLength;
if (RequestSenseLength > 0)
{
- RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
- RequestSenseLength, &RequestSenseBufferDMA);
+ RequestSenseBuffer = pci_zalloc_consistent(Controller->PCIDevice,
+ RequestSenseLength,
+ &RequestSenseBufferDMA);
if (RequestSenseBuffer == NULL)
{
ErrorCode = -ENOMEM;
goto Failure2;
}
- memset(RequestSenseBuffer, 0, RequestSenseLength);
}
spin_lock_irqsave(&Controller->queue_lock, flags);
while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 4595c22f33f7..ff20f192b0f6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1014,24 +1014,21 @@ static CommandList_struct *cmd_special_alloc(ctlr_info_t *h)
u64bit temp64;
dma_addr_t cmd_dma_handle, err_dma_handle;
- c = (CommandList_struct *) pci_alloc_consistent(h->pdev,
- sizeof(CommandList_struct), &cmd_dma_handle);
+ c = pci_zalloc_consistent(h->pdev, sizeof(CommandList_struct),
+ &cmd_dma_handle);
if (c == NULL)
return NULL;
- memset(c, 0, sizeof(CommandList_struct));
c->cmdindex = -1;
- c->err_info = (ErrorInfo_struct *)
- pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
- &err_dma_handle);
+ c->err_info = pci_zalloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
+ &err_dma_handle);
if (c->err_info == NULL) {
pci_free_consistent(h->pdev,
sizeof(CommandList_struct), c, cmd_dma_handle);
return NULL;
}
- memset(c->err_info, 0, sizeof(ErrorInfo_struct));
INIT_LIST_HEAD(&c->list);
c->busaddr = (__u32) cmd_dma_handle;
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
index 8b450338075e..4464e353c1e8 100644
--- a/drivers/block/drbd/Makefile
+++ b/drivers/block/drbd/Makefile
@@ -3,5 +3,6 @@ drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o
drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
drbd-y += drbd_interval.o drbd_state.o
drbd-y += drbd_nla.o
+drbd-$(CONFIG_DEBUG_FS) += drbd_debugfs.o
obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 05a1780ffa85..d26a3fa63688 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -92,34 +92,26 @@ struct __packed al_transaction_on_disk {
__be32 context[AL_CONTEXT_PER_TRANSACTION];
};
-struct update_odbm_work {
- struct drbd_work w;
- struct drbd_device *device;
- unsigned int enr;
-};
-
-struct update_al_work {
- struct drbd_work w;
- struct drbd_device *device;
- struct completion event;
- int err;
-};
-
-
-void *drbd_md_get_buffer(struct drbd_device *device)
+void *drbd_md_get_buffer(struct drbd_device *device, const char *intent)
{
int r;
wait_event(device->misc_wait,
- (r = atomic_cmpxchg(&device->md_io_in_use, 0, 1)) == 0 ||
+ (r = atomic_cmpxchg(&device->md_io.in_use, 0, 1)) == 0 ||
device->state.disk <= D_FAILED);
- return r ? NULL : page_address(device->md_io_page);
+ if (r)
+ return NULL;
+
+ device->md_io.current_use = intent;
+ device->md_io.start_jif = jiffies;
+ device->md_io.submit_jif = device->md_io.start_jif - 1;
+ return page_address(device->md_io.page);
}
void drbd_md_put_buffer(struct drbd_device *device)
{
- if (atomic_dec_and_test(&device->md_io_in_use))
+ if (atomic_dec_and_test(&device->md_io.in_use))
wake_up(&device->misc_wait);
}
@@ -145,10 +137,11 @@ void wait_until_done_or_force_detached(struct drbd_device *device, struct drbd_b
static int _drbd_md_sync_page_io(struct drbd_device *device,
struct drbd_backing_dev *bdev,
- struct page *page, sector_t sector,
- int rw, int size)
+ sector_t sector, int rw)
{
struct bio *bio;
+ /* we do all our meta data IO in aligned 4k blocks. */
+ const int size = 4096;
int err;
device->md_io.done = 0;
@@ -156,15 +149,15 @@ static int _drbd_md_sync_page_io(struct drbd_device *device,
if ((rw & WRITE) && !test_bit(MD_NO_FUA, &device->flags))
rw |= REQ_FUA | REQ_FLUSH;
- rw |= REQ_SYNC;
+ rw |= REQ_SYNC | REQ_NOIDLE;
bio = bio_alloc_drbd(GFP_NOIO);
bio->bi_bdev = bdev->md_bdev;
bio->bi_iter.bi_sector = sector;
err = -EIO;
- if (bio_add_page(bio, page, size, 0) != size)
+ if (bio_add_page(bio, device->md_io.page, size, 0) != size)
goto out;
- bio->bi_private = &device->md_io;
+ bio->bi_private = device;
bio->bi_end_io = drbd_md_io_complete;
bio->bi_rw = rw;
@@ -179,7 +172,8 @@ static int _drbd_md_sync_page_io(struct drbd_device *device,
}
bio_get(bio); /* one bio_put() is in the completion handler */
- atomic_inc(&device->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
+ atomic_inc(&device->md_io.in_use); /* drbd_md_put_buffer() is in the completion handler */
+ device->md_io.submit_jif = jiffies;
if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
bio_endio(bio, -EIO);
else
@@ -197,9 +191,7 @@ int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bd
sector_t sector, int rw)
{
int err;
- struct page *iop = device->md_io_page;
-
- D_ASSERT(device, atomic_read(&device->md_io_in_use) == 1);
+ D_ASSERT(device, atomic_read(&device->md_io.in_use) == 1);
BUG_ON(!bdev->md_bdev);
@@ -214,8 +206,7 @@ int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bd
current->comm, current->pid, __func__,
(unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ");
- /* we do all our meta data IO in aligned 4k blocks. */
- err = _drbd_md_sync_page_io(device, bdev, iop, sector, rw, 4096);
+ err = _drbd_md_sync_page_io(device, bdev, sector, rw);
if (err) {
drbd_err(device, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
(unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err);
@@ -297,26 +288,12 @@ bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval *
return need_transaction;
}
-static int al_write_transaction(struct drbd_device *device, bool delegate);
-
-/* When called through generic_make_request(), we must delegate
- * activity log I/O to the worker thread: a further request
- * submitted via generic_make_request() within the same task
- * would be queued on current->bio_list, and would only start
- * after this function returns (see generic_make_request()).
- *
- * However, if we *are* the worker, we must not delegate to ourselves.
- */
+static int al_write_transaction(struct drbd_device *device);
-/*
- * @delegate: delegate activity log I/O to the worker thread
- */
-void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
+void drbd_al_begin_io_commit(struct drbd_device *device)
{
bool locked = false;
- BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
-
/* Serialize multiple transactions.
* This uses test_and_set_bit, memory barrier is implicit.
*/
@@ -335,7 +312,7 @@ void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
rcu_read_unlock();
if (write_al_updates)
- al_write_transaction(device, delegate);
+ al_write_transaction(device);
spin_lock_irq(&device->al_lock);
/* FIXME
if (err)
@@ -352,12 +329,10 @@ void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
/*
* @delegate: delegate activity log I/O to the worker thread
*/
-void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate)
+void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i)
{
- BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);
-
if (drbd_al_begin_io_prepare(device, i))
- drbd_al_begin_io_commit(device, delegate);
+ drbd_al_begin_io_commit(device);
}
int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
@@ -380,8 +355,19 @@ int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *
/* We want all necessary updates for a given request within the same transaction
* We could first check how many updates are *actually* needed,
* and use that instead of the worst-case nr_al_extents */
- if (available_update_slots < nr_al_extents)
- return -EWOULDBLOCK;
+ if (available_update_slots < nr_al_extents) {
+ /* Too many activity log extents are currently "hot".
+ *
+ * If we have accumulated pending changes already,
+ * we made progress.
+ *
+ * If we cannot get even a single pending change through,
+ * stop the fast path until we made some progress,
+ * or requests to "cold" extents could be starved. */
+ if (!al->pending_changes)
+ __set_bit(__LC_STARVING, &device->act_log->flags);
+ return -ENOBUFS;
+ }
/* Is resync active in this area? */
for (enr = first; enr <= last; enr++) {
@@ -452,15 +438,6 @@ static unsigned int al_extent_to_bm_page(unsigned int al_enr)
(AL_EXTENT_SHIFT - BM_BLOCK_SHIFT));
}
-static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
-{
- return rs_enr >>
- /* bit to page */
- ((PAGE_SHIFT + 3) -
- /* resync extent number to bit */
- (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
-}
-
static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device)
{
const unsigned int stripes = device->ldev->md.al_stripes;
@@ -479,8 +456,7 @@ static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device)
return device->ldev->md.md_offset + device->ldev->md.al_offset + t;
}
-static int
-_al_write_transaction(struct drbd_device *device)
+int al_write_transaction(struct drbd_device *device)
{
struct al_transaction_on_disk *buffer;
struct lc_element *e;
@@ -505,7 +481,8 @@ _al_write_transaction(struct drbd_device *device)
return -EIO;
}
- buffer = drbd_md_get_buffer(device); /* protects md_io_buffer, al_tr_cycle, ... */
+ /* protects md_io_buffer, al_tr_cycle, ... */
+ buffer = drbd_md_get_buffer(device, __func__);
if (!buffer) {
drbd_err(device, "disk failed while waiting for md_io buffer\n");
put_ldev(device);
@@ -590,38 +567,6 @@ _al_write_transaction(struct drbd_device *device)
return err;
}
-
-static int w_al_write_transaction(struct drbd_work *w, int unused)
-{
- struct update_al_work *aw = container_of(w, struct update_al_work, w);
- struct drbd_device *device = aw->device;
- int err;
-
- err = _al_write_transaction(device);
- aw->err = err;
- complete(&aw->event);
-
- return err != -EIO ? err : 0;
-}
-
-/* Calls from worker context (see w_restart_disk_io()) need to write the
- transaction directly. Others came through generic_make_request(),
- those need to delegate it to the worker. */
-static int al_write_transaction(struct drbd_device *device, bool delegate)
-{
- if (delegate) {
- struct update_al_work al_work;
- init_completion(&al_work.event);
- al_work.w.cb = w_al_write_transaction;
- al_work.device = device;
- drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
- &al_work.w);
- wait_for_completion(&al_work.event);
- return al_work.err;
- } else
- return _al_write_transaction(device);
-}
-
static int _try_lc_del(struct drbd_device *device, struct lc_element *al_ext)
{
int rv;
@@ -682,72 +627,56 @@ int drbd_initialize_al(struct drbd_device *device, void *buffer)
return 0;
}
-static int w_update_odbm(struct drbd_work *w, int unused)
-{
- struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w);
- struct drbd_device *device = udw->device;
- struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
-
- if (!get_ldev(device)) {
- if (__ratelimit(&drbd_ratelimit_state))
- drbd_warn(device, "Can not update on disk bitmap, local IO disabled.\n");
- kfree(udw);
- return 0;
- }
-
- drbd_bm_write_page(device, rs_extent_to_bm_page(udw->enr));
- put_ldev(device);
-
- kfree(udw);
-
- if (drbd_bm_total_weight(device) <= device->rs_failed) {
- switch (device->state.conn) {
- case C_SYNC_SOURCE: case C_SYNC_TARGET:
- case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_T:
- drbd_resync_finished(device);
- default:
- /* nothing to do */
- break;
- }
- }
- drbd_bcast_event(device, &sib);
-
- return 0;
-}
-
+static const char *drbd_change_sync_fname[] = {
+ [RECORD_RS_FAILED] = "drbd_rs_failed_io",
+ [SET_IN_SYNC] = "drbd_set_in_sync",
+ [SET_OUT_OF_SYNC] = "drbd_set_out_of_sync"
+};
/* ATTENTION. The AL's extents are 4MB each, while the extents in the
* resync LRU-cache are 16MB each.
* The caller of this function has to hold an get_ldev() reference.
*
+ * Adjusts the caching members ->rs_left (success) or ->rs_failed (!success),
+ * potentially pulling in (and recounting the corresponding bits)
+ * this resync extent into the resync extent lru cache.
+ *
+ * Returns whether all bits have been cleared for this resync extent,
+ * precisely: (rs_left <= rs_failed)
+ *
* TODO will be obsoleted once we have a caching lru of the on disk bitmap
*/
-static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t sector,
- int count, int success)
+static bool update_rs_extent(struct drbd_device *device,
+ unsigned int enr, int count,
+ enum update_sync_bits_mode mode)
{
struct lc_element *e;
- struct update_odbm_work *udw;
-
- unsigned int enr;
D_ASSERT(device, atomic_read(&device->local_cnt));
- /* I simply assume that a sector/size pair never crosses
- * a 16 MB extent border. (Currently this is true...) */
- enr = BM_SECT_TO_EXT(sector);
-
- e = lc_get(device->resync, enr);
+ /* When setting out-of-sync bits,
+ * we don't need it cached (lc_find).
+ * But if it is present in the cache,
+ * we should update the cached bit count.
+ * Otherwise, that extent should be in the resync extent lru cache
+ * already -- or we want to pull it in if necessary -- (lc_get),
+ * then update and check rs_left and rs_failed. */
+ if (mode == SET_OUT_OF_SYNC)
+ e = lc_find(device->resync, enr);
+ else
+ e = lc_get(device->resync, enr);
if (e) {
struct bm_extent *ext = lc_entry(e, struct bm_extent, lce);
if (ext->lce.lc_number == enr) {
- if (success)
+ if (mode == SET_IN_SYNC)
ext->rs_left -= count;
+ else if (mode == SET_OUT_OF_SYNC)
+ ext->rs_left += count;
else
ext->rs_failed += count;
if (ext->rs_left < ext->rs_failed) {
- drbd_warn(device, "BAD! sector=%llus enr=%u rs_left=%d "
+ drbd_warn(device, "BAD! enr=%u rs_left=%d "
"rs_failed=%d count=%d cstate=%s\n",
- (unsigned long long)sector,
ext->lce.lc_number, ext->rs_left,
ext->rs_failed, count,
drbd_conn_str(device->state.conn));
@@ -781,34 +710,27 @@ static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t secto
ext->lce.lc_number, ext->rs_failed);
}
ext->rs_left = rs_left;
- ext->rs_failed = success ? 0 : count;
+ ext->rs_failed = (mode == RECORD_RS_FAILED) ? count : 0;
/* we don't keep a persistent log of the resync lru,
* we can commit any change right away. */
lc_committed(device->resync);
}
- lc_put(device->resync, &ext->lce);
+ if (mode != SET_OUT_OF_SYNC)
+ lc_put(device->resync, &ext->lce);
/* no race, we are within the al_lock! */
- if (ext->rs_left == ext->rs_failed) {
+ if (ext->rs_left <= ext->rs_failed) {
ext->rs_failed = 0;
-
- udw = kmalloc(sizeof(*udw), GFP_ATOMIC);
- if (udw) {
- udw->enr = ext->lce.lc_number;
- udw->w.cb = w_update_odbm;
- udw->device = device;
- drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
- &udw->w);
- } else {
- drbd_warn(device, "Could not kmalloc an udw\n");
- }
+ return true;
}
- } else {
+ } else if (mode != SET_OUT_OF_SYNC) {
+ /* be quiet if lc_find() did not find it. */
drbd_err(device, "lc_get() failed! locked=%d/%d flags=%lu\n",
device->resync_locked,
device->resync->nr_elements,
device->resync->flags);
}
+ return false;
}
void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go)
@@ -827,105 +749,105 @@ void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go
}
}
-/* clear the bit corresponding to the piece of storage in question:
- * size byte of data starting from sector. Only clear a bits of the affected
- * one ore more _aligned_ BM_BLOCK_SIZE blocks.
- *
- * called by worker on C_SYNC_TARGET and receiver on SyncSource.
- *
- */
-void __drbd_set_in_sync(struct drbd_device *device, sector_t sector, int size,
- const char *file, const unsigned int line)
+/* It is called lazy update, so don't do write-out too often. */
+static bool lazy_bitmap_update_due(struct drbd_device *device)
{
- /* Is called from worker and receiver context _only_ */
- unsigned long sbnr, ebnr, lbnr;
- unsigned long count = 0;
- sector_t esector, nr_sectors;
- int wake_up = 0;
- unsigned long flags;
+ return time_after(jiffies, device->rs_last_bcast + 2*HZ);
+}
- if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
- drbd_err(device, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
- (unsigned long long)sector, size);
+static void maybe_schedule_on_disk_bitmap_update(struct drbd_device *device, bool rs_done)
+{
+ if (rs_done)
+ set_bit(RS_DONE, &device->flags);
+ /* and also set RS_PROGRESS below */
+ else if (!lazy_bitmap_update_due(device))
return;
- }
-
- if (!get_ldev(device))
- return; /* no disk, no metadata, no bitmap to clear bits in */
-
- nr_sectors = drbd_get_capacity(device->this_bdev);
- esector = sector + (size >> 9) - 1;
-
- if (!expect(sector < nr_sectors))
- goto out;
- if (!expect(esector < nr_sectors))
- esector = nr_sectors - 1;
-
- lbnr = BM_SECT_TO_BIT(nr_sectors-1);
-
- /* we clear it (in sync).
- * round up start sector, round down end sector. we make sure we only
- * clear full, aligned, BM_BLOCK_SIZE (4K) blocks */
- if (unlikely(esector < BM_SECT_PER_BIT-1))
- goto out;
- if (unlikely(esector == (nr_sectors-1)))
- ebnr = lbnr;
- else
- ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
- sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
- if (sbnr > ebnr)
- goto out;
+ drbd_device_post_work(device, RS_PROGRESS);
+}
+static int update_sync_bits(struct drbd_device *device,
+ unsigned long sbnr, unsigned long ebnr,
+ enum update_sync_bits_mode mode)
+{
/*
- * ok, (capacity & 7) != 0 sometimes, but who cares...
- * we count rs_{total,left} in bits, not sectors.
+ * We keep a count of set bits per resync-extent in the ->rs_left
+ * caching member, so we need to loop and work within the resync extent
+ * alignment. Typically this loop will execute exactly once.
*/
- count = drbd_bm_clear_bits(device, sbnr, ebnr);
- if (count) {
- drbd_advance_rs_marks(device, drbd_bm_total_weight(device));
- spin_lock_irqsave(&device->al_lock, flags);
- drbd_try_clear_on_disk_bm(device, sector, count, true);
- spin_unlock_irqrestore(&device->al_lock, flags);
-
- /* just wake_up unconditional now, various lc_chaged(),
- * lc_put() in drbd_try_clear_on_disk_bm(). */
- wake_up = 1;
+ unsigned long flags;
+ unsigned long count = 0;
+ unsigned int cleared = 0;
+ while (sbnr <= ebnr) {
+ /* set temporary boundary bit number to last bit number within
+ * the resync extent of the current start bit number,
+ * but cap at provided end bit number */
+ unsigned long tbnr = min(ebnr, sbnr | BM_BLOCKS_PER_BM_EXT_MASK);
+ unsigned long c;
+
+ if (mode == RECORD_RS_FAILED)
+ /* Only called from drbd_rs_failed_io(), bits
+ * supposedly still set. Recount, maybe some
+ * of the bits have been successfully cleared
+ * by application IO meanwhile.
+ */
+ c = drbd_bm_count_bits(device, sbnr, tbnr);
+ else if (mode == SET_IN_SYNC)
+ c = drbd_bm_clear_bits(device, sbnr, tbnr);
+ else /* if (mode == SET_OUT_OF_SYNC) */
+ c = drbd_bm_set_bits(device, sbnr, tbnr);
+
+ if (c) {
+ spin_lock_irqsave(&device->al_lock, flags);
+ cleared += update_rs_extent(device, BM_BIT_TO_EXT(sbnr), c, mode);
+ spin_unlock_irqrestore(&device->al_lock, flags);
+ count += c;
+ }
+ sbnr = tbnr + 1;
}
-out:
- put_ldev(device);
- if (wake_up)
+ if (count) {
+ if (mode == SET_IN_SYNC) {
+ unsigned long still_to_go = drbd_bm_total_weight(device);
+ bool rs_is_done = (still_to_go <= device->rs_failed);
+ drbd_advance_rs_marks(device, still_to_go);
+ if (cleared || rs_is_done)
+ maybe_schedule_on_disk_bitmap_update(device, rs_is_done);
+ } else if (mode == RECORD_RS_FAILED)
+ device->rs_failed += count;
wake_up(&device->al_wait);
+ }
+ return count;
}
-/*
- * this is intended to set one request worth of data out of sync.
- * affects at least 1 bit,
- * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits.
+/* clear the bit corresponding to the piece of storage in question:
+ * size byte of data starting from sector. Only clear a bits of the affected
+ * one ore more _aligned_ BM_BLOCK_SIZE blocks.
+ *
+ * called by worker on C_SYNC_TARGET and receiver on SyncSource.
*
- * called by tl_clear and drbd_send_dblock (==drbd_make_request).
- * so this can be _any_ process.
*/
-int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector, int size,
- const char *file, const unsigned int line)
+int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
+ enum update_sync_bits_mode mode,
+ const char *file, const unsigned int line)
{
- unsigned long sbnr, ebnr, flags;
+ /* Is called from worker and receiver context _only_ */
+ unsigned long sbnr, ebnr, lbnr;
+ unsigned long count = 0;
sector_t esector, nr_sectors;
- unsigned int enr, count = 0;
- struct lc_element *e;
- /* this should be an empty REQ_FLUSH */
- if (size == 0)
+ /* This would be an empty REQ_FLUSH, be silent. */
+ if ((mode == SET_OUT_OF_SYNC) && size == 0)
return 0;
- if (size < 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
- drbd_err(device, "sector: %llus, size: %d\n",
- (unsigned long long)sector, size);
+ if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
+ drbd_err(device, "%s: sector=%llus size=%d nonsense!\n",
+ drbd_change_sync_fname[mode],
+ (unsigned long long)sector, size);
return 0;
}
if (!get_ldev(device))
- return 0; /* no disk, no metadata, no bitmap to set bits in */
+ return 0; /* no disk, no metadata, no bitmap to manipulate bits in */
nr_sectors = drbd_get_capacity(device->this_bdev);
esector = sector + (size >> 9) - 1;
@@ -935,25 +857,28 @@ int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector, int size
if (!expect(esector < nr_sectors))
esector = nr_sectors - 1;
- /* we set it out of sync,
- * we do not need to round anything here */
- sbnr = BM_SECT_TO_BIT(sector);
- ebnr = BM_SECT_TO_BIT(esector);
-
- /* ok, (capacity & 7) != 0 sometimes, but who cares...
- * we count rs_{total,left} in bits, not sectors. */
- spin_lock_irqsave(&device->al_lock, flags);
- count = drbd_bm_set_bits(device, sbnr, ebnr);
+ lbnr = BM_SECT_TO_BIT(nr_sectors-1);
- enr = BM_SECT_TO_EXT(sector);
- e = lc_find(device->resync, enr);
- if (e)
- lc_entry(e, struct bm_extent, lce)->rs_left += count;
- spin_unlock_irqrestore(&device->al_lock, flags);
+ if (mode == SET_IN_SYNC) {
+ /* Round up start sector, round down end sector. We make sure
+ * we only clear full, aligned, BM_BLOCK_SIZE blocks. */
+ if (unlikely(esector < BM_SECT_PER_BIT-1))
+ goto out;
+ if (unlikely(esector == (nr_sectors-1)))
+ ebnr = lbnr;
+ else
+ ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
+ sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
+ } else {
+ /* We set it out of sync, or record resync failure.
+ * Should not round anything here. */
+ sbnr = BM_SECT_TO_BIT(sector);
+ ebnr = BM_SECT_TO_BIT(esector);
+ }
+ count = update_sync_bits(device, sbnr, ebnr, mode);
out:
put_ldev(device);
-
return count;
}
@@ -1075,6 +1000,15 @@ int drbd_try_rs_begin_io(struct drbd_device *device, sector_t sector)
struct lc_element *e;
struct bm_extent *bm_ext;
int i;
+ bool throttle = drbd_rs_should_slow_down(device, sector, true);
+
+ /* If we need to throttle, a half-locked (only marked BME_NO_WRITES,
+ * not yet BME_LOCKED) extent needs to be kicked out explicitly if we
+ * need to throttle. There is at most one such half-locked extent,
+ * which is remembered in resync_wenr. */
+
+ if (throttle && device->resync_wenr != enr)
+ return -EAGAIN;
spin_lock_irq(&device->al_lock);
if (device->resync_wenr != LC_FREE && device->resync_wenr != enr) {
@@ -1098,8 +1032,10 @@ int drbd_try_rs_begin_io(struct drbd_device *device, sector_t sector)
D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
clear_bit(BME_NO_WRITES, &bm_ext->flags);
device->resync_wenr = LC_FREE;
- if (lc_put(device->resync, &bm_ext->lce) == 0)
+ if (lc_put(device->resync, &bm_ext->lce) == 0) {
+ bm_ext->flags = 0;
device->resync_locked--;
+ }
wake_up(&device->al_wait);
} else {
drbd_alert(device, "LOGIC BUG\n");
@@ -1161,8 +1097,20 @@ proceed:
return 0;
try_again:
- if (bm_ext)
- device->resync_wenr = enr;
+ if (bm_ext) {
+ if (throttle) {
+ D_ASSERT(device, !test_bit(BME_LOCKED, &bm_ext->flags));
+ D_ASSERT(device, test_bit(BME_NO_WRITES, &bm_ext->flags));
+ clear_bit(BME_NO_WRITES, &bm_ext->flags);
+ device->resync_wenr = LC_FREE;
+ if (lc_put(device->resync, &bm_ext->lce) == 0) {
+ bm_ext->flags = 0;
+ device->resync_locked--;
+ }
+ wake_up(&device->al_wait);
+ } else
+ device->resync_wenr = enr;
+ }
spin_unlock_irq(&device->al_lock);
return -EAGAIN;
}
@@ -1270,69 +1218,3 @@ int drbd_rs_del_all(struct drbd_device *device)
return 0;
}
-
-/**
- * drbd_rs_failed_io() - Record information on a failure to resync the specified blocks
- * @device: DRBD device.
- * @sector: The sector number.
- * @size: Size of failed IO operation, in byte.
- */
-void drbd_rs_failed_io(struct drbd_device *device, sector_t sector, int size)
-{
- /* Is called from worker and receiver context _only_ */
- unsigned long sbnr, ebnr, lbnr;
- unsigned long count;
- sector_t esector, nr_sectors;
- int wake_up = 0;
-
- if (size <= 0 || !IS_ALIGNED(size, 512) || size > DRBD_MAX_DISCARD_SIZE) {
- drbd_err(device, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
- (unsigned long long)sector, size);
- return;
- }
- nr_sectors = drbd_get_capacity(device->this_bdev);
- esector = sector + (size >> 9) - 1;
-
- if (!expect(sector < nr_sectors))
- return;
- if (!expect(esector < nr_sectors))
- esector = nr_sectors - 1;
-
- lbnr = BM_SECT_TO_BIT(nr_sectors-1);
-
- /*
- * round up start sector, round down end sector. we make sure we only
- * handle full, aligned, BM_BLOCK_SIZE (4K) blocks */
- if (unlikely(esector < BM_SECT_PER_BIT-1))
- return;
- if (unlikely(esector == (nr_sectors-1)))
- ebnr = lbnr;
- else
- ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1));
- sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1);
-
- if (sbnr > ebnr)
- return;
-
- /*
- * ok, (capacity & 7) != 0 sometimes, but who cares...
- * we count rs_{total,left} in bits, not sectors.
- */
- spin_lock_irq(&device->al_lock);
- count = drbd_bm_count_bits(device, sbnr, ebnr);
- if (count) {
- device->rs_failed += count;
-
- if (get_ldev(device)) {
- drbd_try_clear_on_disk_bm(device, sector, count, false);
- put_ldev(device);
- }
-
- /* just wake_up unconditional now, various lc_chaged(),
- * lc_put() in drbd_try_clear_on_disk_bm(). */
- wake_up = 1;
- }
- spin_unlock_irq(&device->al_lock);
- if (wake_up)
- wake_up(&device->al_wait);
-}
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 1aa29f8fdfe1..426c97aef900 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -22,6 +22,8 @@
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
@@ -353,9 +355,8 @@ static void bm_free_pages(struct page **pages, unsigned long number)
for (i = 0; i < number; i++) {
if (!pages[i]) {
- printk(KERN_ALERT "drbd: bm_free_pages tried to free "
- "a NULL pointer; i=%lu n=%lu\n",
- i, number);
+ pr_alert("bm_free_pages tried to free a NULL pointer; i=%lu n=%lu\n",
+ i, number);
continue;
}
__free_page(pages[i]);
@@ -592,7 +593,7 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
end = offset + len;
if (end > b->bm_words) {
- printk(KERN_ALERT "drbd: bm_memset end > bm_words\n");
+ pr_alert("bm_memset end > bm_words\n");
return;
}
@@ -602,7 +603,7 @@ static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
p_addr = bm_map_pidx(b, idx);
bm = p_addr + MLPP(offset);
if (bm+do_now > p_addr + LWPP) {
- printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
+ pr_alert("BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
p_addr, bm, (int)do_now);
} else
memset(bm, c, do_now * sizeof(long));
@@ -927,22 +928,14 @@ void drbd_bm_clear_all(struct drbd_device *device)
spin_unlock_irq(&b->bm_lock);
}
-struct bm_aio_ctx {
- struct drbd_device *device;
- atomic_t in_flight;
- unsigned int done;
- unsigned flags;
-#define BM_AIO_COPY_PAGES 1
-#define BM_AIO_WRITE_HINTED 2
-#define BM_WRITE_ALL_PAGES 4
- int error;
- struct kref kref;
-};
-
-static void bm_aio_ctx_destroy(struct kref *kref)
+static void drbd_bm_aio_ctx_destroy(struct kref *kref)
{
- struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref);
+ struct drbd_bm_aio_ctx *ctx = container_of(kref, struct drbd_bm_aio_ctx, kref);
+ unsigned long flags;
+ spin_lock_irqsave(&ctx->device->resource->req_lock, flags);
+ list_del(&ctx->list);
+ spin_unlock_irqrestore(&ctx->device->resource->req_lock, flags);
put_ldev(ctx->device);
kfree(ctx);
}
@@ -950,7 +943,7 @@ static void bm_aio_ctx_destroy(struct kref *kref)
/* bv_page may be a copy, or may be the original */
static void bm_async_io_complete(struct bio *bio, int error)
{
- struct bm_aio_ctx *ctx = bio->bi_private;
+ struct drbd_bm_aio_ctx *ctx = bio->bi_private;
struct drbd_device *device = ctx->device;
struct drbd_bitmap *b = device->bitmap;
unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page);
@@ -993,17 +986,18 @@ static void bm_async_io_complete(struct bio *bio, int error)
if (atomic_dec_and_test(&ctx->in_flight)) {
ctx->done = 1;
wake_up(&device->misc_wait);
- kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+ kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
}
}
-static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local)
+static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_hold(local)
{
struct bio *bio = bio_alloc_drbd(GFP_NOIO);
struct drbd_device *device = ctx->device;
struct drbd_bitmap *b = device->bitmap;
struct page *page;
unsigned int len;
+ unsigned int rw = (ctx->flags & BM_AIO_READ) ? READ : WRITE;
sector_t on_disk_sector =
device->ldev->md.md_offset + device->ldev->md.bm_offset;
@@ -1049,9 +1043,9 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
/*
* bm_rw: read/write the whole bitmap from/to its on disk location.
*/
-static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
+static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
{
- struct bm_aio_ctx *ctx;
+ struct drbd_bm_aio_ctx *ctx;
struct drbd_bitmap *b = device->bitmap;
int num_pages, i, count = 0;
unsigned long now;
@@ -1067,12 +1061,13 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
* as we submit copies of pages anyways.
*/
- ctx = kmalloc(sizeof(struct bm_aio_ctx), GFP_NOIO);
+ ctx = kmalloc(sizeof(struct drbd_bm_aio_ctx), GFP_NOIO);
if (!ctx)
return -ENOMEM;
- *ctx = (struct bm_aio_ctx) {
+ *ctx = (struct drbd_bm_aio_ctx) {
.device = device,
+ .start_jif = jiffies,
.in_flight = ATOMIC_INIT(1),
.done = 0,
.flags = flags,
@@ -1080,15 +1075,21 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
.kref = { ATOMIC_INIT(2) },
};
- if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in bm_aio_ctx_destroy() */
+ if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in drbd_bm_aio_ctx_destroy() */
drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n");
kfree(ctx);
return -ENODEV;
}
+ /* Here D_ATTACHING is sufficient since drbd_bm_read() is called only from
+ drbd_adm_attach(), after device->ldev was assigned. */
- if (!ctx->flags)
+ if (0 == (ctx->flags & ~BM_AIO_READ))
WARN_ON(!(BM_LOCKED_MASK & b->bm_flags));
+ spin_lock_irq(&device->resource->req_lock);
+ list_add_tail(&ctx->list, &device->pending_bitmap_io);
+ spin_unlock_irq(&device->resource->req_lock);
+
num_pages = b->bm_number_of_pages;
now = jiffies;
@@ -1098,13 +1099,13 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
/* ignore completely unchanged pages */
if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
break;
- if (rw & WRITE) {
+ if (!(flags & BM_AIO_READ)) {
if ((flags & BM_AIO_WRITE_HINTED) &&
!test_and_clear_bit(BM_PAGE_HINT_WRITEOUT,
&page_private(b->bm_pages[i])))
continue;
- if (!(flags & BM_WRITE_ALL_PAGES) &&
+ if (!(flags & BM_AIO_WRITE_ALL_PAGES) &&
bm_test_page_unchanged(b->bm_pages[i])) {
dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i);
continue;
@@ -1118,7 +1119,7 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
}
}
atomic_inc(&ctx->in_flight);
- bm_page_io_async(ctx, i, rw);
+ bm_page_io_async(ctx, i);
++count;
cond_resched();
}
@@ -1134,12 +1135,12 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
if (!atomic_dec_and_test(&ctx->in_flight))
wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
else
- kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+ kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
/* summary for global bitmap IO */
if (flags == 0)
drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n",
- rw == WRITE ? "WRITE" : "READ",
+ (flags & BM_AIO_READ) ? "READ" : "WRITE",
count, jiffies - now);
if (ctx->error) {
@@ -1152,20 +1153,18 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
err = -EIO; /* Disk timeout/force-detach during IO... */
now = jiffies;
- if (rw == WRITE) {
- drbd_md_flush(device);
- } else /* rw == READ */ {
+ if (flags & BM_AIO_READ) {
b->bm_set = bm_count_bits(b);
drbd_info(device, "recounting of set bits took additional %lu jiffies\n",
jiffies - now);
}
now = b->bm_set;
- if (flags == 0)
+ if ((flags & ~BM_AIO_READ) == 0)
drbd_info(device, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n",
ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now);
- kref_put(&ctx->kref, &bm_aio_ctx_destroy);
+ kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy);
return err;
}
@@ -1175,7 +1174,7 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la
*/
int drbd_bm_read(struct drbd_device *device) __must_hold(local)
{
- return bm_rw(device, READ, 0, 0);
+ return bm_rw(device, BM_AIO_READ, 0);
}
/**
@@ -1186,7 +1185,7 @@ int drbd_bm_read(struct drbd_device *device) __must_hold(local)
*/
int drbd_bm_write(struct drbd_device *device) __must_hold(local)
{
- return bm_rw(device, WRITE, 0, 0);
+ return bm_rw(device, 0, 0);
}
/**
@@ -1197,7 +1196,17 @@ int drbd_bm_write(struct drbd_device *device) __must_hold(local)
*/
int drbd_bm_write_all(struct drbd_device *device) __must_hold(local)
{
- return bm_rw(device, WRITE, BM_WRITE_ALL_PAGES, 0);
+ return bm_rw(device, BM_AIO_WRITE_ALL_PAGES, 0);
+}
+
+/**
+ * drbd_bm_write_lazy() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
+ * @device: DRBD device.
+ * @upper_idx: 0: write all changed pages; +ve: page index to stop scanning for changed pages
+ */
+int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local)
+{
+ return bm_rw(device, BM_AIO_COPY_PAGES, upper_idx);
}
/**
@@ -1213,7 +1222,7 @@ int drbd_bm_write_all(struct drbd_device *device) __must_hold(local)
*/
int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local)
{
- return bm_rw(device, WRITE, BM_AIO_COPY_PAGES, 0);
+ return bm_rw(device, BM_AIO_COPY_PAGES, 0);
}
/**
@@ -1222,62 +1231,7 @@ int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local)
*/
int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local)
{
- return bm_rw(device, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
-}
-
-/**
- * drbd_bm_write_page() - Writes a PAGE_SIZE aligned piece of bitmap
- * @device: DRBD device.
- * @idx: bitmap page index
- *
- * We don't want to special case on logical_block_size of the backend device,
- * so we submit PAGE_SIZE aligned pieces.
- * Note that on "most" systems, PAGE_SIZE is 4k.
- *
- * In case this becomes an issue on systems with larger PAGE_SIZE,
- * we may want to change this again to write 4k aligned 4k pieces.
- */
-int drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local)
-{
- struct bm_aio_ctx *ctx;
- int err;
-
- if (bm_test_page_unchanged(device->bitmap->bm_pages[idx])) {
- dynamic_drbd_dbg(device, "skipped bm page write for idx %u\n", idx);
- return 0;
- }
-
- ctx = kmalloc(sizeof(struct bm_aio_ctx), GFP_NOIO);
- if (!ctx)
- return -ENOMEM;
-
- *ctx = (struct bm_aio_ctx) {
- .device = device,
- .in_flight = ATOMIC_INIT(1),
- .done = 0,
- .flags = BM_AIO_COPY_PAGES,
- .error = 0,
- .kref = { ATOMIC_INIT(2) },
- };
-
- if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in bm_aio_ctx_destroy() */
- drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in drbd_bm_write_page()\n");
- kfree(ctx);
- return -ENODEV;
- }
-
- bm_page_io_async(ctx, idx, WRITE_SYNC);
- wait_until_done_or_force_detached(device, device->ldev, &ctx->done);
-
- if (ctx->error)
- drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR);
- /* that causes us to detach, so the in memory bitmap will be
- * gone in a moment as well. */
-
- device->bm_writ_cnt++;
- err = atomic_read(&ctx->in_flight) ? -EIO : ctx->error;
- kref_put(&ctx->kref, &bm_aio_ctx_destroy);
- return err;
+ return bm_rw(device, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
}
/* NOTE
diff --git a/drivers/block/drbd/drbd_debugfs.c b/drivers/block/drbd/drbd_debugfs.c
new file mode 100644
index 000000000000..5c20b18540b8
--- /dev/null
+++ b/drivers/block/drbd/drbd_debugfs.c
@@ -0,0 +1,958 @@
+#define pr_fmt(fmt) "drbd debugfs: " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/stat.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+
+#include "drbd_int.h"
+#include "drbd_req.h"
+#include "drbd_debugfs.h"
+
+
+/**********************************************************************
+ * Whenever you change the file format, remember to bump the version. *
+ **********************************************************************/
+
+static struct dentry *drbd_debugfs_root;
+static struct dentry *drbd_debugfs_version;
+static struct dentry *drbd_debugfs_resources;
+static struct dentry *drbd_debugfs_minors;
+
+static void seq_print_age_or_dash(struct seq_file *m, bool valid, unsigned long dt)
+{
+ if (valid)
+ seq_printf(m, "\t%d", jiffies_to_msecs(dt));
+ else
+ seq_printf(m, "\t-");
+}
+
+static void __seq_print_rq_state_bit(struct seq_file *m,
+ bool is_set, char *sep, const char *set_name, const char *unset_name)
+{
+ if (is_set && set_name) {
+ seq_putc(m, *sep);
+ seq_puts(m, set_name);
+ *sep = '|';
+ } else if (!is_set && unset_name) {
+ seq_putc(m, *sep);
+ seq_puts(m, unset_name);
+ *sep = '|';
+ }
+}
+
+static void seq_print_rq_state_bit(struct seq_file *m,
+ bool is_set, char *sep, const char *set_name)
+{
+ __seq_print_rq_state_bit(m, is_set, sep, set_name, NULL);
+}
+
+/* pretty print enum drbd_req_state_bits req->rq_state */
+static void seq_print_request_state(struct seq_file *m, struct drbd_request *req)
+{
+ unsigned int s = req->rq_state;
+ char sep = ' ';
+ seq_printf(m, "\t0x%08x", s);
+ seq_printf(m, "\tmaster: %s", req->master_bio ? "pending" : "completed");
+
+ /* RQ_WRITE ignored, already reported */
+ seq_puts(m, "\tlocal:");
+ seq_print_rq_state_bit(m, s & RQ_IN_ACT_LOG, &sep, "in-AL");
+ seq_print_rq_state_bit(m, s & RQ_POSTPONED, &sep, "postponed");
+ seq_print_rq_state_bit(m, s & RQ_COMPLETION_SUSP, &sep, "suspended");
+ sep = ' ';
+ seq_print_rq_state_bit(m, s & RQ_LOCAL_PENDING, &sep, "pending");
+ seq_print_rq_state_bit(m, s & RQ_LOCAL_COMPLETED, &sep, "completed");
+ seq_print_rq_state_bit(m, s & RQ_LOCAL_ABORTED, &sep, "aborted");
+ seq_print_rq_state_bit(m, s & RQ_LOCAL_OK, &sep, "ok");
+ if (sep == ' ')
+ seq_puts(m, " -");
+
+ /* for_each_connection ... */
+ seq_printf(m, "\tnet:");
+ sep = ' ';
+ seq_print_rq_state_bit(m, s & RQ_NET_PENDING, &sep, "pending");
+ seq_print_rq_state_bit(m, s & RQ_NET_QUEUED, &sep, "queued");
+ seq_print_rq_state_bit(m, s & RQ_NET_SENT, &sep, "sent");
+ seq_print_rq_state_bit(m, s & RQ_NET_DONE, &sep, "done");
+ seq_print_rq_state_bit(m, s & RQ_NET_SIS, &sep, "sis");
+ seq_print_rq_state_bit(m, s & RQ_NET_OK, &sep, "ok");
+ if (sep == ' ')
+ seq_puts(m, " -");
+
+ seq_printf(m, " :");
+ sep = ' ';
+ seq_print_rq_state_bit(m, s & RQ_EXP_RECEIVE_ACK, &sep, "B");
+ seq_print_rq_state_bit(m, s & RQ_EXP_WRITE_ACK, &sep, "C");
+ seq_print_rq_state_bit(m, s & RQ_EXP_BARR_ACK, &sep, "barr");
+ if (sep == ' ')
+ seq_puts(m, " -");
+ seq_printf(m, "\n");
+}
+
+static void seq_print_one_request(struct seq_file *m, struct drbd_request *req, unsigned long now)
+{
+ /* change anything here, fixup header below! */
+ unsigned int s = req->rq_state;
+
+#define RQ_HDR_1 "epoch\tsector\tsize\trw"
+ seq_printf(m, "0x%x\t%llu\t%u\t%s",
+ req->epoch,
+ (unsigned long long)req->i.sector, req->i.size >> 9,
+ (s & RQ_WRITE) ? "W" : "R");
+
+#define RQ_HDR_2 "\tstart\tin AL\tsubmit"
+ seq_printf(m, "\t%d", jiffies_to_msecs(now - req->start_jif));
+ seq_print_age_or_dash(m, s & RQ_IN_ACT_LOG, now - req->in_actlog_jif);
+ seq_print_age_or_dash(m, s & RQ_LOCAL_PENDING, now - req->pre_submit_jif);
+
+#define RQ_HDR_3 "\tsent\tacked\tdone"
+ seq_print_age_or_dash(m, s & RQ_NET_SENT, now - req->pre_send_jif);
+ seq_print_age_or_dash(m, (s & RQ_NET_SENT) && !(s & RQ_NET_PENDING), now - req->acked_jif);
+ seq_print_age_or_dash(m, s & RQ_NET_DONE, now - req->net_done_jif);
+
+#define RQ_HDR_4 "\tstate\n"
+ seq_print_request_state(m, req);
+}
+#define RQ_HDR RQ_HDR_1 RQ_HDR_2 RQ_HDR_3 RQ_HDR_4
+
+static void seq_print_minor_vnr_req(struct seq_file *m, struct drbd_request *req, unsigned long now)
+{
+ seq_printf(m, "%u\t%u\t", req->device->minor, req->device->vnr);
+ seq_print_one_request(m, req, now);
+}
+
+static void seq_print_resource_pending_meta_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+ struct drbd_device *device;
+ unsigned int i;
+
+ seq_puts(m, "minor\tvnr\tstart\tsubmit\tintent\n");
+ rcu_read_lock();
+ idr_for_each_entry(&resource->devices, device, i) {
+ struct drbd_md_io tmp;
+ /* In theory this is racy,
+ * in the sense that there could have been a
+ * drbd_md_put_buffer(); drbd_md_get_buffer();
+ * between accessing these members here. */
+ tmp = device->md_io;
+ if (atomic_read(&tmp.in_use)) {
+ seq_printf(m, "%u\t%u\t%d\t",
+ device->minor, device->vnr,
+ jiffies_to_msecs(now - tmp.start_jif));
+ if (time_before(tmp.submit_jif, tmp.start_jif))
+ seq_puts(m, "-\t");
+ else
+ seq_printf(m, "%d\t", jiffies_to_msecs(now - tmp.submit_jif));
+ seq_printf(m, "%s\n", tmp.current_use);
+ }
+ }
+ rcu_read_unlock();
+}
+
+static void seq_print_waiting_for_AL(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+ struct drbd_device *device;
+ unsigned int i;
+
+ seq_puts(m, "minor\tvnr\tage\t#waiting\n");
+ rcu_read_lock();
+ idr_for_each_entry(&resource->devices, device, i) {
+ unsigned long jif;
+ struct drbd_request *req;
+ int n = atomic_read(&device->ap_actlog_cnt);
+ if (n) {
+ spin_lock_irq(&device->resource->req_lock);
+ req = list_first_entry_or_null(&device->pending_master_completion[1],
+ struct drbd_request, req_pending_master_completion);
+ /* if the oldest request does not wait for the activity log
+ * it is not interesting for us here */
+ if (req && !(req->rq_state & RQ_IN_ACT_LOG))
+ jif = req->start_jif;
+ else
+ req = NULL;
+ spin_unlock_irq(&device->resource->req_lock);
+ }
+ if (n) {
+ seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
+ if (req)
+ seq_printf(m, "%u\t", jiffies_to_msecs(now - jif));
+ else
+ seq_puts(m, "-\t");
+ seq_printf(m, "%u\n", n);
+ }
+ }
+ rcu_read_unlock();
+}
+
+static void seq_print_device_bitmap_io(struct seq_file *m, struct drbd_device *device, unsigned long now)
+{
+ struct drbd_bm_aio_ctx *ctx;
+ unsigned long start_jif;
+ unsigned int in_flight;
+ unsigned int flags;
+ spin_lock_irq(&device->resource->req_lock);
+ ctx = list_first_entry_or_null(&device->pending_bitmap_io, struct drbd_bm_aio_ctx, list);
+ if (ctx && ctx->done)
+ ctx = NULL;
+ if (ctx) {
+ start_jif = ctx->start_jif;
+ in_flight = atomic_read(&ctx->in_flight);
+ flags = ctx->flags;
+ }
+ spin_unlock_irq(&device->resource->req_lock);
+ if (ctx) {
+ seq_printf(m, "%u\t%u\t%c\t%u\t%u\n",
+ device->minor, device->vnr,
+ (flags & BM_AIO_READ) ? 'R' : 'W',
+ jiffies_to_msecs(now - start_jif),
+ in_flight);
+ }
+}
+
+static void seq_print_resource_pending_bitmap_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
+{
+ struct drbd_device *device;
+ unsigned int i;
+
+ seq_puts(m, "minor\tvnr\trw\tage\t#in-flight\n");
+ rcu_read_lock();
+ idr_for_each_entry(&resource->devices, device, i) {
+ seq_print_device_bitmap_io(m, device, now);
+ }
+ rcu_read_unlock();
+}
+
+/* pretty print enum peer_req->flags */
+static void seq_print_peer_request_flags(struct seq_file *m, struct drbd_peer_request *peer_req)
+{
+ unsigned long f = peer_req->flags;
+ char sep = ' ';
+
+ __seq_print_rq_state_bit(m, f & EE_SUBMITTED, &sep, "submitted", "preparing");
+ __seq_print_rq_state_bit(m, f & EE_APPLICATION, &sep, "application", "internal");
+ seq_print_rq_state_bit(m, f & EE_CALL_AL_COMPLETE_IO, &sep, "in-AL");
+ seq_print_rq_state_bit(m, f & EE_SEND_WRITE_ACK, &sep, "C");
+ seq_print_rq_state_bit(m, f & EE_MAY_SET_IN_SYNC, &sep, "set-in-sync");
+
+ if (f & EE_IS_TRIM) {
+ seq_putc(m, sep);
+ sep = '|';
+ if (f & EE_IS_TRIM_USE_ZEROOUT)
+ seq_puts(m, "zero-out");
+ else
+ seq_puts(m, "trim");
+ }
+ seq_putc(m, '\n');
+}
+
+static void seq_print_peer_request(struct seq_file *m,
+ struct drbd_device *device, struct list_head *lh,
+ unsigned long now)
+{
+ bool reported_preparing = false;
+ struct drbd_peer_request *peer_req;
+ list_for_each_entry(peer_req, lh, w.list) {
+ if (reported_preparing && !(peer_req->flags & EE_SUBMITTED))
+ continue;
+
+ if (device)
+ seq_printf(m, "%u\t%u\t", device->minor, device->vnr);
+
+ seq_printf(m, "%llu\t%u\t%c\t%u\t",
+ (unsigned long long)peer_req->i.sector, peer_req->i.size >> 9,
+ (peer_req->flags & EE_WRITE) ? 'W' : 'R',
+ jiffies_to_msecs(now - peer_req->submit_jif));
+ seq_print_peer_request_flags(m, peer_req);
+ if (peer_req->flags & EE_SUBMITTED)
+ break;
+ else
+ reported_preparing = true;
+ }
+}
+
+static void seq_print_device_peer_requests(struct seq_file *m,
+ struct drbd_device *device, unsigned long now)
+{
+ seq_puts(m, "minor\tvnr\tsector\tsize\trw\tage\tflags\n");
+ spin_lock_irq(&device->resource->req_lock);
+ seq_print_peer_request(m, device, &device->active_ee, now);
+ seq_print_peer_request(m, device, &device->read_ee, now);
+ seq_print_peer_request(m, device, &device->sync_ee, now);
+ spin_unlock_irq(&device->resource->req_lock);
+ if (test_bit(FLUSH_PENDING, &device->flags)) {
+ seq_printf(m, "%u\t%u\t-\t-\tF\t%u\tflush\n",
+ device->minor, device->vnr,
+ jiffies_to_msecs(now - device->flush_jif));
+ }
+}
+
+static void seq_print_resource_pending_peer_requests(struct seq_file *m,
+ struct drbd_resource *resource, unsigned long now)
+{
+ struct drbd_device *device;
+ unsigned int i;
+
+ rcu_read_lock();
+ idr_for_each_entry(&resource->devices, device, i) {
+ seq_print_device_peer_requests(m, device, now);
+ }
+ rcu_read_unlock();
+}
+
+static void seq_print_resource_transfer_log_summary(struct seq_file *m,
+ struct drbd_resource *resource,
+ struct drbd_connection *connection,
+ unsigned long now)
+{
+ struct drbd_request *req;
+ unsigned int count = 0;
+ unsigned int show_state = 0;
+
+ seq_puts(m, "n\tdevice\tvnr\t" RQ_HDR);
+ spin_lock_irq(&resource->req_lock);
+ list_for_each_entry(req, &connection->transfer_log, tl_requests) {
+ unsigned int tmp = 0;
+ unsigned int s;
+ ++count;
+
+ /* don't disable irq "forever" */
+ if (!(count & 0x1ff)) {
+ struct drbd_request *req_next;
+ kref_get(&req->kref);
+ spin_unlock_irq(&resource->req_lock);
+ cond_resched();
+ spin_lock_irq(&resource->req_lock);
+ req_next = list_next_entry(req, tl_requests);
+ if (kref_put(&req->kref, drbd_req_destroy))
+ req = req_next;
+ if (&req->tl_requests == &connection->transfer_log)
+ break;
+ }
+
+ s = req->rq_state;
+
+ /* This is meant to summarize timing issues, to be able to tell
+ * local disk problems from network problems.
+ * Skip requests, if we have shown an even older request with
+ * similar aspects already. */
+ if (req->master_bio == NULL)
+ tmp |= 1;
+ if ((s & RQ_LOCAL_MASK) && (s & RQ_LOCAL_PENDING))
+ tmp |= 2;
+ if (s & RQ_NET_MASK) {
+ if (!(s & RQ_NET_SENT))
+ tmp |= 4;
+ if (s & RQ_NET_PENDING)
+ tmp |= 8;
+ if (!(s & RQ_NET_DONE))
+ tmp |= 16;
+ }
+ if ((tmp & show_state) == tmp)
+ continue;
+ show_state |= tmp;
+ seq_printf(m, "%u\t", count);
+ seq_print_minor_vnr_req(m, req, now);
+ if (show_state == 0x1f)
+ break;
+ }
+ spin_unlock_irq(&resource->req_lock);
+}
+
+/* TODO: transfer_log and friends should be moved to resource */
+static int in_flight_summary_show(struct seq_file *m, void *pos)
+{
+ struct drbd_resource *resource = m->private;
+ struct drbd_connection *connection;
+ unsigned long jif = jiffies;
+
+ connection = first_connection(resource);
+ /* This does not happen, actually.
+ * But be robust and prepare for future code changes. */
+ if (!connection || !kref_get_unless_zero(&connection->kref))
+ return -ESTALE;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ seq_puts(m, "oldest bitmap IO\n");
+ seq_print_resource_pending_bitmap_io(m, resource, jif);
+ seq_putc(m, '\n');
+
+ seq_puts(m, "meta data IO\n");
+ seq_print_resource_pending_meta_io(m, resource, jif);
+ seq_putc(m, '\n');
+
+ seq_puts(m, "socket buffer stats\n");
+ /* for each connection ... once we have more than one */
+ rcu_read_lock();
+ if (connection->data.socket) {
+ /* open coded SIOCINQ, the "relevant" part */
+ struct tcp_sock *tp = tcp_sk(connection->data.socket->sk);
+ int answ = tp->rcv_nxt - tp->copied_seq;
+ seq_printf(m, "unread receive buffer: %u Byte\n", answ);
+ /* open coded SIOCOUTQ, the "relevant" part */
+ answ = tp->write_seq - tp->snd_una;
+ seq_printf(m, "unacked send buffer: %u Byte\n", answ);
+ }
+ rcu_read_unlock();
+ seq_putc(m, '\n');
+
+ seq_puts(m, "oldest peer requests\n");
+ seq_print_resource_pending_peer_requests(m, resource, jif);
+ seq_putc(m, '\n');
+
+ seq_puts(m, "application requests waiting for activity log\n");
+ seq_print_waiting_for_AL(m, resource, jif);
+ seq_putc(m, '\n');
+
+ seq_puts(m, "oldest application requests\n");
+ seq_print_resource_transfer_log_summary(m, resource, connection, jif);
+ seq_putc(m, '\n');
+
+ jif = jiffies - jif;
+ if (jif)
+ seq_printf(m, "generated in %d ms\n", jiffies_to_msecs(jif));
+ kref_put(&connection->kref, drbd_destroy_connection);
+ return 0;
+}
+
+/* simple_positive(file->f_dentry) respectively debugfs_positive(),
+ * but neither is "reachable" from here.
+ * So we have our own inline version of it above. :-( */
+static inline int debugfs_positive(struct dentry *dentry)
+{
+ return dentry->d_inode && !d_unhashed(dentry);
+}
+
+/* make sure at *open* time that the respective object won't go away. */
+static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, void *),
+ void *data, struct kref *kref,
+ void (*release)(struct kref *))
+{
+ struct dentry *parent;
+ int ret = -ESTALE;
+
+ /* Are we still linked,
+ * or has debugfs_remove() already been called? */
+ parent = file->f_dentry->d_parent;
+ /* not sure if this can happen: */
+ if (!parent || !parent->d_inode)
+ goto out;
+ /* serialize with d_delete() */
+ mutex_lock(&parent->d_inode->i_mutex);
+ /* Make sure the object is still alive */
+ if (debugfs_positive(file->f_dentry)
+ && kref_get_unless_zero(kref))
+ ret = 0;
+ mutex_unlock(&parent->d_inode->i_mutex);
+ if (!ret) {
+ ret = single_open(file, show, data);
+ if (ret)
+ kref_put(kref, release);
+ }
+out:
+ return ret;
+}
+
+static int in_flight_summary_open(struct inode *inode, struct file *file)
+{
+ struct drbd_resource *resource = inode->i_private;
+ return drbd_single_open(file, in_flight_summary_show, resource,
+ &resource->kref, drbd_destroy_resource);
+}
+
+static int in_flight_summary_release(struct inode *inode, struct file *file)
+{
+ struct drbd_resource *resource = inode->i_private;
+ kref_put(&resource->kref, drbd_destroy_resource);
+ return single_release(inode, file);
+}
+
+static const struct file_operations in_flight_summary_fops = {
+ .owner = THIS_MODULE,
+ .open = in_flight_summary_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = in_flight_summary_release,
+};
+
+void drbd_debugfs_resource_add(struct drbd_resource *resource)
+{
+ struct dentry *dentry;
+ if (!drbd_debugfs_resources)
+ return;
+
+ dentry = debugfs_create_dir(resource->name, drbd_debugfs_resources);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ resource->debugfs_res = dentry;
+
+ dentry = debugfs_create_dir("volumes", resource->debugfs_res);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ resource->debugfs_res_volumes = dentry;
+
+ dentry = debugfs_create_dir("connections", resource->debugfs_res);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ resource->debugfs_res_connections = dentry;
+
+ dentry = debugfs_create_file("in_flight_summary", S_IRUSR|S_IRGRP,
+ resource->debugfs_res, resource,
+ &in_flight_summary_fops);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ resource->debugfs_res_in_flight_summary = dentry;
+ return;
+
+fail:
+ drbd_debugfs_resource_cleanup(resource);
+ drbd_err(resource, "failed to create debugfs dentry\n");
+}
+
+static void drbd_debugfs_remove(struct dentry **dp)
+{
+ debugfs_remove(*dp);
+ *dp = NULL;
+}
+
+void drbd_debugfs_resource_cleanup(struct drbd_resource *resource)
+{
+ /* it is ok to call debugfs_remove(NULL) */
+ drbd_debugfs_remove(&resource->debugfs_res_in_flight_summary);
+ drbd_debugfs_remove(&resource->debugfs_res_connections);
+ drbd_debugfs_remove(&resource->debugfs_res_volumes);
+ drbd_debugfs_remove(&resource->debugfs_res);
+}
+
+static void seq_print_one_timing_detail(struct seq_file *m,
+ const struct drbd_thread_timing_details *tdp,
+ unsigned long now)
+{
+ struct drbd_thread_timing_details td;
+ /* No locking...
+ * use temporary assignment to get at consistent data. */
+ do {
+ td = *tdp;
+ } while (td.cb_nr != tdp->cb_nr);
+ if (!td.cb_addr)
+ return;
+ seq_printf(m, "%u\t%d\t%s:%u\t%ps\n",
+ td.cb_nr,
+ jiffies_to_msecs(now - td.start_jif),
+ td.caller_fn, td.line,
+ td.cb_addr);
+}
+
+static void seq_print_timing_details(struct seq_file *m,
+ const char *title,
+ unsigned int cb_nr, struct drbd_thread_timing_details *tdp, unsigned long now)
+{
+ unsigned int start_idx;
+ unsigned int i;
+
+ seq_printf(m, "%s\n", title);
+ /* If not much is going on, this will result in natural ordering.
+ * If it is very busy, we will possibly skip events, or even see wrap
+ * arounds, which could only be avoided with locking.
+ */
+ start_idx = cb_nr % DRBD_THREAD_DETAILS_HIST;
+ for (i = start_idx; i < DRBD_THREAD_DETAILS_HIST; i++)
+ seq_print_one_timing_detail(m, tdp+i, now);
+ for (i = 0; i < start_idx; i++)
+ seq_print_one_timing_detail(m, tdp+i, now);
+}
+
+static int callback_history_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_connection *connection = m->private;
+ unsigned long jif = jiffies;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ seq_puts(m, "n\tage\tcallsite\tfn\n");
+ seq_print_timing_details(m, "worker", connection->w_cb_nr, connection->w_timing_details, jif);
+ seq_print_timing_details(m, "receiver", connection->r_cb_nr, connection->r_timing_details, jif);
+ return 0;
+}
+
+static int callback_history_open(struct inode *inode, struct file *file)
+{
+ struct drbd_connection *connection = inode->i_private;
+ return drbd_single_open(file, callback_history_show, connection,
+ &connection->kref, drbd_destroy_connection);
+}
+
+static int callback_history_release(struct inode *inode, struct file *file)
+{
+ struct drbd_connection *connection = inode->i_private;
+ kref_put(&connection->kref, drbd_destroy_connection);
+ return single_release(inode, file);
+}
+
+static const struct file_operations connection_callback_history_fops = {
+ .owner = THIS_MODULE,
+ .open = callback_history_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = callback_history_release,
+};
+
+static int connection_oldest_requests_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_connection *connection = m->private;
+ unsigned long now = jiffies;
+ struct drbd_request *r1, *r2;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ spin_lock_irq(&connection->resource->req_lock);
+ r1 = connection->req_next;
+ if (r1)
+ seq_print_minor_vnr_req(m, r1, now);
+ r2 = connection->req_ack_pending;
+ if (r2 && r2 != r1) {
+ r1 = r2;
+ seq_print_minor_vnr_req(m, r1, now);
+ }
+ r2 = connection->req_not_net_done;
+ if (r2 && r2 != r1)
+ seq_print_minor_vnr_req(m, r2, now);
+ spin_unlock_irq(&connection->resource->req_lock);
+ return 0;
+}
+
+static int connection_oldest_requests_open(struct inode *inode, struct file *file)
+{
+ struct drbd_connection *connection = inode->i_private;
+ return drbd_single_open(file, connection_oldest_requests_show, connection,
+ &connection->kref, drbd_destroy_connection);
+}
+
+static int connection_oldest_requests_release(struct inode *inode, struct file *file)
+{
+ struct drbd_connection *connection = inode->i_private;
+ kref_put(&connection->kref, drbd_destroy_connection);
+ return single_release(inode, file);
+}
+
+static const struct file_operations connection_oldest_requests_fops = {
+ .owner = THIS_MODULE,
+ .open = connection_oldest_requests_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = connection_oldest_requests_release,
+};
+
+void drbd_debugfs_connection_add(struct drbd_connection *connection)
+{
+ struct dentry *conns_dir = connection->resource->debugfs_res_connections;
+ struct dentry *dentry;
+ if (!conns_dir)
+ return;
+
+ /* Once we enable mutliple peers,
+ * these connections will have descriptive names.
+ * For now, it is just the one connection to the (only) "peer". */
+ dentry = debugfs_create_dir("peer", conns_dir);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ connection->debugfs_conn = dentry;
+
+ dentry = debugfs_create_file("callback_history", S_IRUSR|S_IRGRP,
+ connection->debugfs_conn, connection,
+ &connection_callback_history_fops);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ connection->debugfs_conn_callback_history = dentry;
+
+ dentry = debugfs_create_file("oldest_requests", S_IRUSR|S_IRGRP,
+ connection->debugfs_conn, connection,
+ &connection_oldest_requests_fops);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ connection->debugfs_conn_oldest_requests = dentry;
+ return;
+
+fail:
+ drbd_debugfs_connection_cleanup(connection);
+ drbd_err(connection, "failed to create debugfs dentry\n");
+}
+
+void drbd_debugfs_connection_cleanup(struct drbd_connection *connection)
+{
+ drbd_debugfs_remove(&connection->debugfs_conn_callback_history);
+ drbd_debugfs_remove(&connection->debugfs_conn_oldest_requests);
+ drbd_debugfs_remove(&connection->debugfs_conn);
+}
+
+static void resync_dump_detail(struct seq_file *m, struct lc_element *e)
+{
+ struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
+
+ seq_printf(m, "%5d %s %s %s\n", bme->rs_left,
+ test_bit(BME_NO_WRITES, &bme->flags) ? "NO_WRITES" : "---------",
+ test_bit(BME_LOCKED, &bme->flags) ? "LOCKED" : "------",
+ test_bit(BME_PRIORITY, &bme->flags) ? "PRIORITY" : "--------"
+ );
+}
+
+static int device_resync_extents_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_device *device = m->private;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ if (get_ldev_if_state(device, D_FAILED)) {
+ lc_seq_printf_stats(m, device->resync);
+ lc_seq_dump_details(m, device->resync, "rs_left flags", resync_dump_detail);
+ put_ldev(device);
+ }
+ return 0;
+}
+
+static int device_act_log_extents_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_device *device = m->private;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ if (get_ldev_if_state(device, D_FAILED)) {
+ lc_seq_printf_stats(m, device->act_log);
+ lc_seq_dump_details(m, device->act_log, "", NULL);
+ put_ldev(device);
+ }
+ return 0;
+}
+
+static int device_oldest_requests_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_device *device = m->private;
+ struct drbd_resource *resource = device->resource;
+ unsigned long now = jiffies;
+ struct drbd_request *r1, *r2;
+ int i;
+
+ /* BUMP me if you change the file format/content/presentation */
+ seq_printf(m, "v: %u\n\n", 0);
+
+ seq_puts(m, RQ_HDR);
+ spin_lock_irq(&resource->req_lock);
+ /* WRITE, then READ */
+ for (i = 1; i >= 0; --i) {
+ r1 = list_first_entry_or_null(&device->pending_master_completion[i],
+ struct drbd_request, req_pending_master_completion);
+ r2 = list_first_entry_or_null(&device->pending_completion[i],
+ struct drbd_request, req_pending_local);
+ if (r1)
+ seq_print_one_request(m, r1, now);
+ if (r2 && r2 != r1)
+ seq_print_one_request(m, r2, now);
+ }
+ spin_unlock_irq(&resource->req_lock);
+ return 0;
+}
+
+static int device_data_gen_id_show(struct seq_file *m, void *ignored)
+{
+ struct drbd_device *device = m->private;
+ struct drbd_md *md;
+ enum drbd_uuid_index idx;
+
+ if (!get_ldev_if_state(device, D_FAILED))
+ return -ENODEV;
+
+ md = &device->ldev->md;
+ spin_lock_irq(&md->uuid_lock);
+ for (idx = UI_CURRENT; idx <= UI_HISTORY_END; idx++) {
+ seq_printf(m, "0x%016llX\n", md->uuid[idx]);
+ }
+ spin_unlock_irq(&md->uuid_lock);
+ put_ldev(device);
+ return 0;
+}
+
+#define drbd_debugfs_device_attr(name) \
+static int device_ ## name ## _open(struct inode *inode, struct file *file) \
+{ \
+ struct drbd_device *device = inode->i_private; \
+ return drbd_single_open(file, device_ ## name ## _show, device, \
+ &device->kref, drbd_destroy_device); \
+} \
+static int device_ ## name ## _release(struct inode *inode, struct file *file) \
+{ \
+ struct drbd_device *device = inode->i_private; \
+ kref_put(&device->kref, drbd_destroy_device); \
+ return single_release(inode, file); \
+} \
+static const struct file_operations device_ ## name ## _fops = { \
+ .owner = THIS_MODULE, \
+ .open = device_ ## name ## _open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = device_ ## name ## _release, \
+};
+
+drbd_debugfs_device_attr(oldest_requests)
+drbd_debugfs_device_attr(act_log_extents)
+drbd_debugfs_device_attr(resync_extents)
+drbd_debugfs_device_attr(data_gen_id)
+
+void drbd_debugfs_device_add(struct drbd_device *device)
+{
+ struct dentry *vols_dir = device->resource->debugfs_res_volumes;
+ char minor_buf[8]; /* MINORMASK, MINORBITS == 20; */
+ char vnr_buf[8]; /* volume number vnr is even 16 bit only; */
+ char *slink_name = NULL;
+
+ struct dentry *dentry;
+ if (!vols_dir || !drbd_debugfs_minors)
+ return;
+
+ snprintf(vnr_buf, sizeof(vnr_buf), "%u", device->vnr);
+ dentry = debugfs_create_dir(vnr_buf, vols_dir);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ device->debugfs_vol = dentry;
+
+ snprintf(minor_buf, sizeof(minor_buf), "%u", device->minor);
+ slink_name = kasprintf(GFP_KERNEL, "../resources/%s/volumes/%u",
+ device->resource->name, device->vnr);
+ if (!slink_name)
+ goto fail;
+ dentry = debugfs_create_symlink(minor_buf, drbd_debugfs_minors, slink_name);
+ kfree(slink_name);
+ slink_name = NULL;
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ device->debugfs_minor = dentry;
+
+#define DCF(name) do { \
+ dentry = debugfs_create_file(#name, S_IRUSR|S_IRGRP, \
+ device->debugfs_vol, device, \
+ &device_ ## name ## _fops); \
+ if (IS_ERR_OR_NULL(dentry)) \
+ goto fail; \
+ device->debugfs_vol_ ## name = dentry; \
+ } while (0)
+
+ DCF(oldest_requests);
+ DCF(act_log_extents);
+ DCF(resync_extents);
+ DCF(data_gen_id);
+#undef DCF
+ return;
+
+fail:
+ drbd_debugfs_device_cleanup(device);
+ drbd_err(device, "failed to create debugfs entries\n");
+}
+
+void drbd_debugfs_device_cleanup(struct drbd_device *device)
+{
+ drbd_debugfs_remove(&device->debugfs_minor);
+ drbd_debugfs_remove(&device->debugfs_vol_oldest_requests);
+ drbd_debugfs_remove(&device->debugfs_vol_act_log_extents);
+ drbd_debugfs_remove(&device->debugfs_vol_resync_extents);
+ drbd_debugfs_remove(&device->debugfs_vol_data_gen_id);
+ drbd_debugfs_remove(&device->debugfs_vol);
+}
+
+void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device)
+{
+ struct dentry *conn_dir = peer_device->connection->debugfs_conn;
+ struct dentry *dentry;
+ char vnr_buf[8];
+
+ if (!conn_dir)
+ return;
+
+ snprintf(vnr_buf, sizeof(vnr_buf), "%u", peer_device->device->vnr);
+ dentry = debugfs_create_dir(vnr_buf, conn_dir);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ peer_device->debugfs_peer_dev = dentry;
+ return;
+
+fail:
+ drbd_debugfs_peer_device_cleanup(peer_device);
+ drbd_err(peer_device, "failed to create debugfs entries\n");
+}
+
+void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device)
+{
+ drbd_debugfs_remove(&peer_device->debugfs_peer_dev);
+}
+
+static int drbd_version_show(struct seq_file *m, void *ignored)
+{
+ seq_printf(m, "# %s\n", drbd_buildtag());
+ seq_printf(m, "VERSION=%s\n", REL_VERSION);
+ seq_printf(m, "API_VERSION=%u\n", API_VERSION);
+ seq_printf(m, "PRO_VERSION_MIN=%u\n", PRO_VERSION_MIN);
+ seq_printf(m, "PRO_VERSION_MAX=%u\n", PRO_VERSION_MAX);
+ return 0;
+}
+
+static int drbd_version_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, drbd_version_show, NULL);
+}
+
+static struct file_operations drbd_version_fops = {
+ .owner = THIS_MODULE,
+ .open = drbd_version_open,
+ .llseek = seq_lseek,
+ .read = seq_read,
+ .release = single_release,
+};
+
+/* not __exit, may be indirectly called
+ * from the module-load-failure path as well. */
+void drbd_debugfs_cleanup(void)
+{
+ drbd_debugfs_remove(&drbd_debugfs_resources);
+ drbd_debugfs_remove(&drbd_debugfs_minors);
+ drbd_debugfs_remove(&drbd_debugfs_version);
+ drbd_debugfs_remove(&drbd_debugfs_root);
+}
+
+int __init drbd_debugfs_init(void)
+{
+ struct dentry *dentry;
+
+ dentry = debugfs_create_dir("drbd", NULL);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ drbd_debugfs_root = dentry;
+
+ dentry = debugfs_create_file("version", 0444, drbd_debugfs_root, NULL, &drbd_version_fops);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ drbd_debugfs_version = dentry;
+
+ dentry = debugfs_create_dir("resources", drbd_debugfs_root);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ drbd_debugfs_resources = dentry;
+
+ dentry = debugfs_create_dir("minors", drbd_debugfs_root);
+ if (IS_ERR_OR_NULL(dentry))
+ goto fail;
+ drbd_debugfs_minors = dentry;
+ return 0;
+
+fail:
+ drbd_debugfs_cleanup();
+ if (dentry)
+ return PTR_ERR(dentry);
+ else
+ return -EINVAL;
+}
diff --git a/drivers/block/drbd/drbd_debugfs.h b/drivers/block/drbd/drbd_debugfs.h
new file mode 100644
index 000000000000..8bee21340dce
--- /dev/null
+++ b/drivers/block/drbd/drbd_debugfs.h
@@ -0,0 +1,39 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+
+#include "drbd_int.h"
+
+#ifdef CONFIG_DEBUG_FS
+int __init drbd_debugfs_init(void);
+void drbd_debugfs_cleanup(void);
+
+void drbd_debugfs_resource_add(struct drbd_resource *resource);
+void drbd_debugfs_resource_cleanup(struct drbd_resource *resource);
+
+void drbd_debugfs_connection_add(struct drbd_connection *connection);
+void drbd_debugfs_connection_cleanup(struct drbd_connection *connection);
+
+void drbd_debugfs_device_add(struct drbd_device *device);
+void drbd_debugfs_device_cleanup(struct drbd_device *device);
+
+void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device);
+void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device);
+#else
+
+static inline int __init drbd_debugfs_init(void) { return -ENODEV; }
+static inline void drbd_debugfs_cleanup(void) { }
+
+static inline void drbd_debugfs_resource_add(struct drbd_resource *resource) { }
+static inline void drbd_debugfs_resource_cleanup(struct drbd_resource *resource) { }
+
+static inline void drbd_debugfs_connection_add(struct drbd_connection *connection) { }
+static inline void drbd_debugfs_connection_cleanup(struct drbd_connection *connection) { }
+
+static inline void drbd_debugfs_device_add(struct drbd_device *device) { }
+static inline void drbd_debugfs_device_cleanup(struct drbd_device *device) { }
+
+static inline void drbd_debugfs_peer_device_add(struct drbd_peer_device *peer_device) { }
+static inline void drbd_debugfs_peer_device_cleanup(struct drbd_peer_device *peer_device) { }
+
+#endif
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index a76ceb344d64..1a000016ccdf 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -317,7 +317,63 @@ struct drbd_request {
struct list_head tl_requests; /* ring list in the transfer log */
struct bio *master_bio; /* master bio pointer */
- unsigned long start_time;
+
+ /* see struct drbd_device */
+ struct list_head req_pending_master_completion;
+ struct list_head req_pending_local;
+
+ /* for generic IO accounting */
+ unsigned long start_jif;
+
+ /* for DRBD internal statistics */
+
+ /* Minimal set of time stamps to determine if we wait for activity log
+ * transactions, local disk or peer. 32 bit "jiffies" are good enough,
+ * we don't expect a DRBD request to be stalled for several month.
+ */
+
+ /* before actual request processing */
+ unsigned long in_actlog_jif;
+
+ /* local disk */
+ unsigned long pre_submit_jif;
+
+ /* per connection */
+ unsigned long pre_send_jif;
+ unsigned long acked_jif;
+ unsigned long net_done_jif;
+
+ /* Possibly even more detail to track each phase:
+ * master_completion_jif
+ * how long did it take to complete the master bio
+ * (application visible latency)
+ * allocated_jif
+ * how long the master bio was blocked until we finally allocated
+ * a tracking struct
+ * in_actlog_jif
+ * how long did we wait for activity log transactions
+ *
+ * net_queued_jif
+ * when did we finally queue it for sending
+ * pre_send_jif
+ * when did we start sending it
+ * post_send_jif
+ * how long did we block in the network stack trying to send it
+ * acked_jif
+ * when did we receive (or fake, in protocol A) a remote ACK
+ * net_done_jif
+ * when did we receive final acknowledgement (P_BARRIER_ACK),
+ * or decide, e.g. on connection loss, that we do no longer expect
+ * anything from this peer for this request.
+ *
+ * pre_submit_jif
+ * post_sub_jif
+ * when did we start submiting to the lower level device,
+ * and how long did we block in that submit function
+ * local_completion_jif
+ * how long did it take the lower level device to complete this request
+ */
+
/* once it hits 0, we may complete the master_bio */
atomic_t completion_ref;
@@ -366,6 +422,7 @@ struct drbd_peer_request {
struct drbd_interval i;
/* see comments on ee flag bits below */
unsigned long flags;
+ unsigned long submit_jif;
union {
u64 block_id;
struct digest_info *digest;
@@ -408,6 +465,17 @@ enum {
/* Is set when net_conf had two_primaries set while creating this peer_req */
__EE_IN_INTERVAL_TREE,
+
+ /* for debugfs: */
+ /* has this been submitted, or does it still wait for something else? */
+ __EE_SUBMITTED,
+
+ /* this is/was a write request */
+ __EE_WRITE,
+
+ /* this originates from application on peer
+ * (not some resync or verify or other DRBD internal request) */
+ __EE_APPLICATION,
};
#define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
#define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC)
@@ -419,6 +487,9 @@ enum {
#define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS)
#define EE_SEND_WRITE_ACK (1<<__EE_SEND_WRITE_ACK)
#define EE_IN_INTERVAL_TREE (1<<__EE_IN_INTERVAL_TREE)
+#define EE_SUBMITTED (1<<__EE_SUBMITTED)
+#define EE_WRITE (1<<__EE_WRITE)
+#define EE_APPLICATION (1<<__EE_APPLICATION)
/* flag bits per device */
enum {
@@ -433,11 +504,11 @@ enum {
CONSIDER_RESYNC,
MD_NO_FUA, /* Users wants us to not use FUA/FLUSH on meta data dev */
+
SUSPEND_IO, /* suspend application io */
BITMAP_IO, /* suspend application io;
once no more io in flight, start bitmap io */
BITMAP_IO_QUEUED, /* Started bitmap IO */
- GO_DISKLESS, /* Disk is being detached, on io-error or admin request. */
WAS_IO_ERROR, /* Local disk failed, returned IO error */
WAS_READ_ERROR, /* Local disk READ failed (set additionally to the above) */
FORCE_DETACH, /* Force-detach from local disk, aborting any pending local IO */
@@ -450,6 +521,20 @@ enum {
B_RS_H_DONE, /* Before resync handler done (already executed) */
DISCARD_MY_DATA, /* discard_my_data flag per volume */
READ_BALANCE_RR,
+
+ FLUSH_PENDING, /* if set, device->flush_jif is when we submitted that flush
+ * from drbd_flush_after_epoch() */
+
+ /* cleared only after backing device related structures have been destroyed. */
+ GOING_DISKLESS, /* Disk is being detached, because of io-error, or admin request. */
+
+ /* to be used in drbd_device_post_work() */
+ GO_DISKLESS, /* tell worker to schedule cleanup before detach */
+ DESTROY_DISK, /* tell worker to close backing devices and destroy related structures. */
+ MD_SYNC, /* tell worker to call drbd_md_sync() */
+ RS_START, /* tell worker to start resync/OV */
+ RS_PROGRESS, /* tell worker that resync made significant progress */
+ RS_DONE, /* tell worker that resync is done */
};
struct drbd_bitmap; /* opaque for drbd_device */
@@ -531,6 +616,11 @@ struct drbd_backing_dev {
};
struct drbd_md_io {
+ struct page *page;
+ unsigned long start_jif; /* last call to drbd_md_get_buffer */
+ unsigned long submit_jif; /* last _drbd_md_sync_page_io() submit */
+ const char *current_use;
+ atomic_t in_use;
unsigned int done;
int error;
};
@@ -577,10 +667,18 @@ enum {
* and potentially deadlock on, this drbd worker.
*/
DISCONNECT_SENT,
+
+ DEVICE_WORK_PENDING, /* tell worker that some device has pending work */
};
struct drbd_resource {
char *name;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_res;
+ struct dentry *debugfs_res_volumes;
+ struct dentry *debugfs_res_connections;
+ struct dentry *debugfs_res_in_flight_summary;
+#endif
struct kref kref;
struct idr devices; /* volume number to device mapping */
struct list_head connections;
@@ -594,12 +692,28 @@ struct drbd_resource {
unsigned susp_nod:1; /* IO suspended because no data */
unsigned susp_fen:1; /* IO suspended because fence peer handler runs */
+ enum write_ordering_e write_ordering;
+
cpumask_var_t cpu_mask;
};
+struct drbd_thread_timing_details
+{
+ unsigned long start_jif;
+ void *cb_addr;
+ const char *caller_fn;
+ unsigned int line;
+ unsigned int cb_nr;
+};
+
struct drbd_connection {
struct list_head connections;
struct drbd_resource *resource;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_conn;
+ struct dentry *debugfs_conn_callback_history;
+ struct dentry *debugfs_conn_oldest_requests;
+#endif
struct kref kref;
struct idr peer_devices; /* volume number to peer device mapping */
enum drbd_conns cstate; /* Only C_STANDALONE to C_WF_REPORT_PARAMS */
@@ -636,7 +750,6 @@ struct drbd_connection {
struct drbd_epoch *current_epoch;
spinlock_t epoch_lock;
unsigned int epochs;
- enum write_ordering_e write_ordering;
atomic_t current_tle_nr; /* transfer log epoch number */
unsigned current_tle_writes; /* writes seen within this tl epoch */
@@ -645,9 +758,22 @@ struct drbd_connection {
struct drbd_thread worker;
struct drbd_thread asender;
+ /* cached pointers,
+ * so we can look up the oldest pending requests more quickly.
+ * protected by resource->req_lock */
+ struct drbd_request *req_next; /* DRBD 9: todo.req_next */
+ struct drbd_request *req_ack_pending;
+ struct drbd_request *req_not_net_done;
+
/* sender side */
struct drbd_work_queue sender_work;
+#define DRBD_THREAD_DETAILS_HIST 16
+ unsigned int w_cb_nr; /* keeps counting up */
+ unsigned int r_cb_nr; /* keeps counting up */
+ struct drbd_thread_timing_details w_timing_details[DRBD_THREAD_DETAILS_HIST];
+ struct drbd_thread_timing_details r_timing_details[DRBD_THREAD_DETAILS_HIST];
+
struct {
/* whether this sender thread
* has processed a single write yet. */
@@ -663,11 +789,22 @@ struct drbd_connection {
} send;
};
+void __update_timing_details(
+ struct drbd_thread_timing_details *tdp,
+ unsigned int *cb_nr,
+ void *cb,
+ const char *fn, const unsigned int line);
+
+#define update_worker_timing_details(c, cb) \
+ __update_timing_details(c->w_timing_details, &c->w_cb_nr, cb, __func__ , __LINE__ )
+#define update_receiver_timing_details(c, cb) \
+ __update_timing_details(c->r_timing_details, &c->r_cb_nr, cb, __func__ , __LINE__ )
+
struct submit_worker {
struct workqueue_struct *wq;
struct work_struct worker;
- spinlock_t lock;
+ /* protected by ..->resource->req_lock */
struct list_head writes;
};
@@ -675,12 +812,29 @@ struct drbd_peer_device {
struct list_head peer_devices;
struct drbd_device *device;
struct drbd_connection *connection;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_peer_dev;
+#endif
};
struct drbd_device {
struct drbd_resource *resource;
struct list_head peer_devices;
- int vnr; /* volume number within the connection */
+ struct list_head pending_bitmap_io;
+
+ unsigned long flush_jif;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_minor;
+ struct dentry *debugfs_vol;
+ struct dentry *debugfs_vol_oldest_requests;
+ struct dentry *debugfs_vol_act_log_extents;
+ struct dentry *debugfs_vol_resync_extents;
+ struct dentry *debugfs_vol_data_gen_id;
+#endif
+
+ unsigned int vnr; /* volume number within the connection */
+ unsigned int minor; /* device minor number */
+
struct kref kref;
/* things that are stored as / read from meta data on disk */
@@ -697,19 +851,10 @@ struct drbd_device {
unsigned long last_reattach_jif;
struct drbd_work resync_work;
struct drbd_work unplug_work;
- struct drbd_work go_diskless;
- struct drbd_work md_sync_work;
- struct drbd_work start_resync_work;
struct timer_list resync_timer;
struct timer_list md_sync_timer;
struct timer_list start_resync_timer;
struct timer_list request_timer;
-#ifdef DRBD_DEBUG_MD_SYNC
- struct {
- unsigned int line;
- const char* func;
- } last_md_mark_dirty;
-#endif
/* Used after attach while negotiating new disk state. */
union drbd_state new_state_tmp;
@@ -724,6 +869,7 @@ struct drbd_device {
unsigned int al_writ_cnt;
unsigned int bm_writ_cnt;
atomic_t ap_bio_cnt; /* Requests we need to complete */
+ atomic_t ap_actlog_cnt; /* Requests waiting for activity log */
atomic_t ap_pending_cnt; /* AP data packets on the wire, ack expected */
atomic_t rs_pending_cnt; /* RS request/data packets on the wire */
atomic_t unacked_cnt; /* Need to send replies for */
@@ -733,6 +879,13 @@ struct drbd_device {
struct rb_root read_requests;
struct rb_root write_requests;
+ /* for statistics and timeouts */
+ /* [0] read, [1] write */
+ struct list_head pending_master_completion[2];
+ struct list_head pending_completion[2];
+
+ /* use checksums for *this* resync */
+ bool use_csums;
/* blocks to resync in this run [unit BM_BLOCK_SIZE] */
unsigned long rs_total;
/* number of resync blocks that failed in this run */
@@ -788,9 +941,7 @@ struct drbd_device {
atomic_t pp_in_use; /* allocated from page pool */
atomic_t pp_in_use_by_net; /* sendpage()d, still referenced by tcp */
wait_queue_head_t ee_wait;
- struct page *md_io_page; /* one page buffer for md_io */
struct drbd_md_io md_io;
- atomic_t md_io_in_use; /* protects the md_io, md_io_page and md_io_tmpp */
spinlock_t al_lock;
wait_queue_head_t al_wait;
struct lru_cache *act_log; /* activity log */
@@ -800,7 +951,6 @@ struct drbd_device {
atomic_t packet_seq;
unsigned int peer_seq;
spinlock_t peer_seq_lock;
- unsigned int minor;
unsigned long comm_bm_set; /* communicated number of set bits. */
struct bm_io_work bm_io_work;
u64 ed_uuid; /* UUID of the exposed data */
@@ -824,6 +974,21 @@ struct drbd_device {
struct submit_worker submit;
};
+struct drbd_bm_aio_ctx {
+ struct drbd_device *device;
+ struct list_head list; /* on device->pending_bitmap_io */;
+ unsigned long start_jif;
+ atomic_t in_flight;
+ unsigned int done;
+ unsigned flags;
+#define BM_AIO_COPY_PAGES 1
+#define BM_AIO_WRITE_HINTED 2
+#define BM_AIO_WRITE_ALL_PAGES 4
+#define BM_AIO_READ 8
+ int error;
+ struct kref kref;
+};
+
struct drbd_config_context {
/* assigned from drbd_genlmsghdr */
unsigned int minor;
@@ -949,7 +1114,7 @@ extern int drbd_send_ov_request(struct drbd_peer_device *, sector_t sector, int
extern int drbd_send_bitmap(struct drbd_device *device);
extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode);
-extern void drbd_free_bc(struct drbd_backing_dev *ldev);
+extern void drbd_free_ldev(struct drbd_backing_dev *ldev);
extern void drbd_device_cleanup(struct drbd_device *device);
void drbd_print_uuids(struct drbd_device *device, const char *text);
@@ -966,13 +1131,7 @@ extern void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must
extern void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
extern void drbd_md_clear_flag(struct drbd_device *device, int flags)__must_hold(local);
extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
-#ifndef DRBD_DEBUG_MD_SYNC
extern void drbd_md_mark_dirty(struct drbd_device *device);
-#else
-#define drbd_md_mark_dirty(m) drbd_md_mark_dirty_(m, __LINE__ , __func__ )
-extern void drbd_md_mark_dirty_(struct drbd_device *device,
- unsigned int line, const char *func);
-#endif
extern void drbd_queue_bitmap_io(struct drbd_device *device,
int (*io_fn)(struct drbd_device *),
void (*done)(struct drbd_device *, int),
@@ -983,9 +1142,8 @@ extern int drbd_bitmap_io(struct drbd_device *device,
extern int drbd_bitmap_io_from_worker(struct drbd_device *device,
int (*io_fn)(struct drbd_device *),
char *why, enum bm_flag flags);
-extern int drbd_bmio_set_n_write(struct drbd_device *device);
-extern int drbd_bmio_clear_n_write(struct drbd_device *device);
-extern void drbd_ldev_destroy(struct drbd_device *device);
+extern int drbd_bmio_set_n_write(struct drbd_device *device) __must_hold(local);
+extern int drbd_bmio_clear_n_write(struct drbd_device *device) __must_hold(local);
/* Meta data layout
*
@@ -1105,17 +1263,21 @@ struct bm_extent {
/* in which _bitmap_ extent (resp. sector) the bit for a certain
* _storage_ sector is located in */
#define BM_SECT_TO_EXT(x) ((x)>>(BM_EXT_SHIFT-9))
+#define BM_BIT_TO_EXT(x) ((x) >> (BM_EXT_SHIFT - BM_BLOCK_SHIFT))
-/* how much _storage_ sectors we have per bitmap sector */
+/* first storage sector a bitmap extent corresponds to */
#define BM_EXT_TO_SECT(x) ((sector_t)(x) << (BM_EXT_SHIFT-9))
+/* how much _storage_ sectors we have per bitmap extent */
#define BM_SECT_PER_EXT BM_EXT_TO_SECT(1)
+/* how many bits are covered by one bitmap extent (resync extent) */
+#define BM_BITS_PER_EXT (1UL << (BM_EXT_SHIFT - BM_BLOCK_SHIFT))
+
+#define BM_BLOCKS_PER_BM_EXT_MASK (BM_BITS_PER_EXT - 1)
+
/* in one sector of the bitmap, we have this many activity_log extents. */
#define AL_EXT_PER_BM_SECT (1 << (BM_EXT_SHIFT - AL_EXTENT_SHIFT))
-#define BM_BLOCKS_PER_BM_EXT_B (BM_EXT_SHIFT - BM_BLOCK_SHIFT)
-#define BM_BLOCKS_PER_BM_EXT_MASK ((1<<BM_BLOCKS_PER_BM_EXT_B) - 1)
-
/* the extent in "PER_EXTENT" below is an activity log extent
* we need that many (long words/bytes) to store the bitmap
* of one AL_EXTENT_SIZE chunk of storage.
@@ -1195,11 +1357,11 @@ extern void _drbd_bm_set_bits(struct drbd_device *device,
const unsigned long s, const unsigned long e);
extern int drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
extern int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
-extern int drbd_bm_write_page(struct drbd_device *device, unsigned int idx) __must_hold(local);
extern int drbd_bm_read(struct drbd_device *device) __must_hold(local);
extern void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
extern int drbd_bm_write(struct drbd_device *device) __must_hold(local);
extern int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
+extern int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local);
extern int drbd_bm_write_all(struct drbd_device *device) __must_hold(local);
extern int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local);
extern size_t drbd_bm_words(struct drbd_device *device);
@@ -1213,7 +1375,6 @@ extern unsigned long _drbd_bm_find_next(struct drbd_device *device, unsigned lon
extern unsigned long _drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo);
extern unsigned long _drbd_bm_total_weight(struct drbd_device *device);
extern unsigned long drbd_bm_total_weight(struct drbd_device *device);
-extern int drbd_bm_rs_done(struct drbd_device *device);
/* for receive_bitmap */
extern void drbd_bm_merge_lel(struct drbd_device *device, size_t offset,
size_t number, unsigned long *buffer);
@@ -1312,7 +1473,7 @@ enum determine_dev_size {
extern enum determine_dev_size
drbd_determine_dev_size(struct drbd_device *, enum dds_flags, struct resize_parms *) __must_hold(local);
extern void resync_after_online_grow(struct drbd_device *);
-extern void drbd_reconsider_max_bio_size(struct drbd_device *device);
+extern void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backing_dev *bdev);
extern enum drbd_state_rv drbd_set_role(struct drbd_device *device,
enum drbd_role new_role,
int force);
@@ -1333,7 +1494,7 @@ extern void resume_next_sg(struct drbd_device *device);
extern void suspend_other_sg(struct drbd_device *device);
extern int drbd_resync_finished(struct drbd_device *device);
/* maybe rather drbd_main.c ? */
-extern void *drbd_md_get_buffer(struct drbd_device *device);
+extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent);
extern void drbd_md_put_buffer(struct drbd_device *device);
extern int drbd_md_sync_page_io(struct drbd_device *device,
struct drbd_backing_dev *bdev, sector_t sector, int rw);
@@ -1380,7 +1541,8 @@ extern void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req);
extern int drbd_receiver(struct drbd_thread *thi);
extern int drbd_asender(struct drbd_thread *thi);
extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
-extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector);
+extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
+ bool throttle_if_app_is_waiting);
extern int drbd_submit_peer_request(struct drbd_device *,
struct drbd_peer_request *, const unsigned,
const int);
@@ -1464,10 +1626,7 @@ static inline void drbd_generic_make_request(struct drbd_device *device,
{
__release(local);
if (!bio->bi_bdev) {
- printk(KERN_ERR "drbd%d: drbd_generic_make_request: "
- "bio->bi_bdev == NULL\n",
- device_to_minor(device));
- dump_stack();
+ drbd_err(device, "drbd_generic_make_request: bio->bi_bdev == NULL\n");
bio_endio(bio, -ENODEV);
return;
}
@@ -1478,7 +1637,8 @@ static inline void drbd_generic_make_request(struct drbd_device *device,
generic_make_request(bio);
}
-void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
+ enum write_ordering_e wo);
/* drbd_proc.c */
extern struct proc_dir_entry *drbd_proc;
@@ -1489,9 +1649,9 @@ extern const char *drbd_role_str(enum drbd_role s);
/* drbd_actlog.c */
extern bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval *i);
extern int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate);
+extern void drbd_al_begin_io_commit(struct drbd_device *device);
extern bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate);
+extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i);
extern void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i);
extern void drbd_rs_complete_io(struct drbd_device *device, sector_t sector);
extern int drbd_rs_begin_io(struct drbd_device *device, sector_t sector);
@@ -1501,14 +1661,17 @@ extern int drbd_rs_del_all(struct drbd_device *device);
extern void drbd_rs_failed_io(struct drbd_device *device,
sector_t sector, int size);
extern void drbd_advance_rs_marks(struct drbd_device *device, unsigned long still_to_go);
-extern void __drbd_set_in_sync(struct drbd_device *device, sector_t sector,
- int size, const char *file, const unsigned int line);
+
+enum update_sync_bits_mode { RECORD_RS_FAILED, SET_OUT_OF_SYNC, SET_IN_SYNC };
+extern int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
+ enum update_sync_bits_mode mode,
+ const char *file, const unsigned int line);
#define drbd_set_in_sync(device, sector, size) \
- __drbd_set_in_sync(device, sector, size, __FILE__, __LINE__)
-extern int __drbd_set_out_of_sync(struct drbd_device *device, sector_t sector,
- int size, const char *file, const unsigned int line);
+ __drbd_change_sync(device, sector, size, SET_IN_SYNC, __FILE__, __LINE__)
#define drbd_set_out_of_sync(device, sector, size) \
- __drbd_set_out_of_sync(device, sector, size, __FILE__, __LINE__)
+ __drbd_change_sync(device, sector, size, SET_OUT_OF_SYNC, __FILE__, __LINE__)
+#define drbd_rs_failed_io(device, sector, size) \
+ __drbd_change_sync(device, sector, size, RECORD_RS_FAILED, __FILE__, __LINE__)
extern void drbd_al_shrink(struct drbd_device *device);
extern int drbd_initialize_al(struct drbd_device *, void *);
@@ -1764,25 +1927,38 @@ static inline sector_t drbd_md_ss(struct drbd_backing_dev *bdev)
}
static inline void
-drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
+drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
{
unsigned long flags;
spin_lock_irqsave(&q->q_lock, flags);
- list_add(&w->list, &q->q);
+ list_add_tail(&w->list, &q->q);
spin_unlock_irqrestore(&q->q_lock, flags);
wake_up(&q->q_wait);
}
static inline void
-drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
+drbd_queue_work_if_unqueued(struct drbd_work_queue *q, struct drbd_work *w)
{
unsigned long flags;
spin_lock_irqsave(&q->q_lock, flags);
- list_add_tail(&w->list, &q->q);
+ if (list_empty_careful(&w->list))
+ list_add_tail(&w->list, &q->q);
spin_unlock_irqrestore(&q->q_lock, flags);
wake_up(&q->q_wait);
}
+static inline void
+drbd_device_post_work(struct drbd_device *device, int work_bit)
+{
+ if (!test_and_set_bit(work_bit, &device->flags)) {
+ struct drbd_connection *connection =
+ first_peer_device(device)->connection;
+ struct drbd_work_queue *q = &connection->sender_work;
+ if (!test_and_set_bit(DEVICE_WORK_PENDING, &connection->flags))
+ wake_up(&q->q_wait);
+ }
+}
+
extern void drbd_flush_workqueue(struct drbd_work_queue *work_queue);
static inline void wake_asender(struct drbd_connection *connection)
@@ -1859,7 +2035,7 @@ static inline void inc_ap_pending(struct drbd_device *device)
func, line, \
atomic_read(&device->which))
-#define dec_ap_pending(device) _dec_ap_pending(device, __FUNCTION__, __LINE__)
+#define dec_ap_pending(device) _dec_ap_pending(device, __func__, __LINE__)
static inline void _dec_ap_pending(struct drbd_device *device, const char *func, int line)
{
if (atomic_dec_and_test(&device->ap_pending_cnt))
@@ -1878,7 +2054,7 @@ static inline void inc_rs_pending(struct drbd_device *device)
atomic_inc(&device->rs_pending_cnt);
}
-#define dec_rs_pending(device) _dec_rs_pending(device, __FUNCTION__, __LINE__)
+#define dec_rs_pending(device) _dec_rs_pending(device, __func__, __LINE__)
static inline void _dec_rs_pending(struct drbd_device *device, const char *func, int line)
{
atomic_dec(&device->rs_pending_cnt);
@@ -1899,20 +2075,29 @@ static inline void inc_unacked(struct drbd_device *device)
atomic_inc(&device->unacked_cnt);
}
-#define dec_unacked(device) _dec_unacked(device, __FUNCTION__, __LINE__)
+#define dec_unacked(device) _dec_unacked(device, __func__, __LINE__)
static inline void _dec_unacked(struct drbd_device *device, const char *func, int line)
{
atomic_dec(&device->unacked_cnt);
ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
}
-#define sub_unacked(device, n) _sub_unacked(device, n, __FUNCTION__, __LINE__)
+#define sub_unacked(device, n) _sub_unacked(device, n, __func__, __LINE__)
static inline void _sub_unacked(struct drbd_device *device, int n, const char *func, int line)
{
atomic_sub(n, &device->unacked_cnt);
ERR_IF_CNT_IS_NEGATIVE(unacked_cnt, func, line);
}
+static inline bool is_sync_state(enum drbd_conns connection_state)
+{
+ return
+ (connection_state == C_SYNC_SOURCE
+ || connection_state == C_SYNC_TARGET
+ || connection_state == C_PAUSED_SYNC_S
+ || connection_state == C_PAUSED_SYNC_T);
+}
+
/**
* get_ldev() - Increase the ref count on device->ldev. Returns 0 if there is no ldev
* @M: DRBD device.
@@ -1924,6 +2109,11 @@ static inline void _sub_unacked(struct drbd_device *device, int n, const char *f
static inline void put_ldev(struct drbd_device *device)
{
+ enum drbd_disk_state ds = device->state.disk;
+ /* We must check the state *before* the atomic_dec becomes visible,
+ * or we have a theoretical race where someone hitting zero,
+ * while state still D_FAILED, will then see D_DISKLESS in the
+ * condition below and calling into destroy, where he must not, yet. */
int i = atomic_dec_return(&device->local_cnt);
/* This may be called from some endio handler,
@@ -1932,15 +2122,13 @@ static inline void put_ldev(struct drbd_device *device)
__release(local);
D_ASSERT(device, i >= 0);
if (i == 0) {
- if (device->state.disk == D_DISKLESS)
+ if (ds == D_DISKLESS)
/* even internal references gone, safe to destroy */
- drbd_ldev_destroy(device);
- if (device->state.disk == D_FAILED) {
+ drbd_device_post_work(device, DESTROY_DISK);
+ if (ds == D_FAILED)
/* all application IO references gone. */
- if (!test_and_set_bit(GO_DISKLESS, &device->flags))
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
- &device->go_diskless);
- }
+ if (!test_and_set_bit(GOING_DISKLESS, &device->flags))
+ drbd_device_post_work(device, GO_DISKLESS);
wake_up(&device->misc_wait);
}
}
@@ -1964,54 +2152,6 @@ static inline int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_
extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins);
#endif
-/* you must have an "get_ldev" reference */
-static inline void drbd_get_syncer_progress(struct drbd_device *device,
- unsigned long *bits_left, unsigned int *per_mil_done)
-{
- /* this is to break it at compile time when we change that, in case we
- * want to support more than (1<<32) bits on a 32bit arch. */
- typecheck(unsigned long, device->rs_total);
-
- /* note: both rs_total and rs_left are in bits, i.e. in
- * units of BM_BLOCK_SIZE.
- * for the percentage, we don't care. */
-
- if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
- *bits_left = device->ov_left;
- else
- *bits_left = drbd_bm_total_weight(device) - device->rs_failed;
- /* >> 10 to prevent overflow,
- * +1 to prevent division by zero */
- if (*bits_left > device->rs_total) {
- /* doh. maybe a logic bug somewhere.
- * may also be just a race condition
- * between this and a disconnect during sync.
- * for now, just prevent in-kernel buffer overflow.
- */
- smp_rmb();
- drbd_warn(device, "cs:%s rs_left=%lu > rs_total=%lu (rs_failed %lu)\n",
- drbd_conn_str(device->state.conn),
- *bits_left, device->rs_total, device->rs_failed);
- *per_mil_done = 0;
- } else {
- /* Make sure the division happens in long context.
- * We allow up to one petabyte storage right now,
- * at a granularity of 4k per bit that is 2**38 bits.
- * After shift right and multiplication by 1000,
- * this should still fit easily into a 32bit long,
- * so we don't need a 64bit division on 32bit arch.
- * Note: currently we don't support such large bitmaps on 32bit
- * arch anyways, but no harm done to be prepared for it here.
- */
- unsigned int shift = device->rs_total > UINT_MAX ? 16 : 10;
- unsigned long left = *bits_left >> shift;
- unsigned long total = 1UL + (device->rs_total >> shift);
- unsigned long tmp = 1000UL - left * 1000UL/total;
- *per_mil_done = tmp;
- }
-}
-
-
/* this throttles on-the-fly application requests
* according to max_buffers settings;
* maybe re-implement using semaphores? */
@@ -2201,25 +2341,6 @@ static inline int drbd_queue_order_type(struct drbd_device *device)
return QUEUE_ORDERED_NONE;
}
-static inline void drbd_md_flush(struct drbd_device *device)
-{
- int r;
-
- if (device->ldev == NULL) {
- drbd_warn(device, "device->ldev == NULL in drbd_md_flush\n");
- return;
- }
-
- if (test_bit(MD_NO_FUA, &device->flags))
- return;
-
- r = blkdev_issue_flush(device->ldev->md_bdev, GFP_NOIO, NULL);
- if (r) {
- set_bit(MD_NO_FUA, &device->flags);
- drbd_err(device, "meta data flush failed with status %d, disabling md-flushes\n", r);
- }
-}
-
static inline struct drbd_connection *first_connection(struct drbd_resource *resource)
{
return list_first_entry_or_null(&resource->connections,
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h
index f38fcb00c10d..f210543f05f4 100644
--- a/drivers/block/drbd/drbd_interval.h
+++ b/drivers/block/drbd/drbd_interval.h
@@ -10,7 +10,9 @@ struct drbd_interval {
unsigned int size; /* size in bytes */
sector_t end; /* highest interval end in subtree */
int local:1 /* local or remote request? */;
- int waiting:1;
+ int waiting:1; /* someone is waiting for this to complete */
+ int completed:1; /* this has been completed already;
+ * ignore for conflict detection */
};
static inline void drbd_clear_interval(struct drbd_interval *i)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 960645c26e6f..9b465bb68487 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -26,7 +26,10 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
+#include <linux/jiffies.h>
#include <linux/drbd.h>
#include <asm/uaccess.h>
#include <asm/types.h>
@@ -54,16 +57,14 @@
#include "drbd_int.h"
#include "drbd_protocol.h"
#include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */
-
#include "drbd_vli.h"
+#include "drbd_debugfs.h"
static DEFINE_MUTEX(drbd_main_mutex);
static int drbd_open(struct block_device *bdev, fmode_t mode);
static void drbd_release(struct gendisk *gd, fmode_t mode);
-static int w_md_sync(struct drbd_work *w, int unused);
static void md_sync_timer_fn(unsigned long data);
static int w_bitmap_io(struct drbd_work *w, int unused);
-static int w_go_diskless(struct drbd_work *w, int unused);
MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
"Lars Ellenberg <lars@linbit.com>");
@@ -264,7 +265,7 @@ bail:
/**
* _tl_restart() - Walks the transfer log, and applies an action to all requests
- * @device: DRBD device.
+ * @connection: DRBD connection to operate on.
* @what: The action/event to perform with all request objects
*
* @what might be one of CONNECTION_LOST_WHILE_PENDING, RESEND, FAIL_FROZEN_DISK_IO,
@@ -662,6 +663,11 @@ static int __send_command(struct drbd_connection *connection, int vnr,
msg_flags);
if (data && !err)
err = drbd_send_all(connection, sock->socket, data, size, 0);
+ /* DRBD protocol "pings" are latency critical.
+ * This is supposed to trigger tcp_push_pending_frames() */
+ if (!err && (cmd == P_PING || cmd == P_PING_ACK))
+ drbd_tcp_nodelay(sock->socket);
+
return err;
}
@@ -1636,7 +1642,10 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request *
if (peer_device->connection->agreed_pro_version >= 100) {
if (req->rq_state & RQ_EXP_RECEIVE_ACK)
dp_flags |= DP_SEND_RECEIVE_ACK;
- if (req->rq_state & RQ_EXP_WRITE_ACK)
+ /* During resync, request an explicit write ack,
+ * even in protocol != C */
+ if (req->rq_state & RQ_EXP_WRITE_ACK
+ || (dp_flags & DP_MAY_SET_IN_SYNC))
dp_flags |= DP_SEND_WRITE_ACK;
}
p->dp_flags = cpu_to_be32(dp_flags);
@@ -1900,6 +1909,7 @@ void drbd_init_set_defaults(struct drbd_device *device)
drbd_set_defaults(device);
atomic_set(&device->ap_bio_cnt, 0);
+ atomic_set(&device->ap_actlog_cnt, 0);
atomic_set(&device->ap_pending_cnt, 0);
atomic_set(&device->rs_pending_cnt, 0);
atomic_set(&device->unacked_cnt, 0);
@@ -1908,7 +1918,7 @@ void drbd_init_set_defaults(struct drbd_device *device)
atomic_set(&device->rs_sect_in, 0);
atomic_set(&device->rs_sect_ev, 0);
atomic_set(&device->ap_in_flight, 0);
- atomic_set(&device->md_io_in_use, 0);
+ atomic_set(&device->md_io.in_use, 0);
mutex_init(&device->own_state_mutex);
device->state_mutex = &device->own_state_mutex;
@@ -1924,17 +1934,15 @@ void drbd_init_set_defaults(struct drbd_device *device)
INIT_LIST_HEAD(&device->resync_reads);
INIT_LIST_HEAD(&device->resync_work.list);
INIT_LIST_HEAD(&device->unplug_work.list);
- INIT_LIST_HEAD(&device->go_diskless.list);
- INIT_LIST_HEAD(&device->md_sync_work.list);
- INIT_LIST_HEAD(&device->start_resync_work.list);
INIT_LIST_HEAD(&device->bm_io_work.w.list);
+ INIT_LIST_HEAD(&device->pending_master_completion[0]);
+ INIT_LIST_HEAD(&device->pending_master_completion[1]);
+ INIT_LIST_HEAD(&device->pending_completion[0]);
+ INIT_LIST_HEAD(&device->pending_completion[1]);
device->resync_work.cb = w_resync_timer;
device->unplug_work.cb = w_send_write_hint;
- device->go_diskless.cb = w_go_diskless;
- device->md_sync_work.cb = w_md_sync;
device->bm_io_work.w.cb = w_bitmap_io;
- device->start_resync_work.cb = w_start_resync;
init_timer(&device->resync_timer);
init_timer(&device->md_sync_timer);
@@ -1992,7 +2000,7 @@ void drbd_device_cleanup(struct drbd_device *device)
drbd_bm_cleanup(device);
}
- drbd_free_bc(device->ldev);
+ drbd_free_ldev(device->ldev);
device->ldev = NULL;
clear_bit(AL_SUSPENDED, &device->flags);
@@ -2006,7 +2014,6 @@ void drbd_device_cleanup(struct drbd_device *device)
D_ASSERT(device, list_empty(&first_peer_device(device)->connection->sender_work.q));
D_ASSERT(device, list_empty(&device->resync_work.list));
D_ASSERT(device, list_empty(&device->unplug_work.list));
- D_ASSERT(device, list_empty(&device->go_diskless.list));
drbd_set_defaults(device);
}
@@ -2129,20 +2136,6 @@ Enomem:
return -ENOMEM;
}
-static int drbd_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- /* just so we have it. you never know what interesting things we
- * might want to do here some day...
- */
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block drbd_notifier = {
- .notifier_call = drbd_notify_sys,
-};
-
static void drbd_release_all_peer_reqs(struct drbd_device *device)
{
int rr;
@@ -2173,7 +2166,7 @@ void drbd_destroy_device(struct kref *kref)
{
struct drbd_device *device = container_of(kref, struct drbd_device, kref);
struct drbd_resource *resource = device->resource;
- struct drbd_connection *connection;
+ struct drbd_peer_device *peer_device, *tmp_peer_device;
del_timer_sync(&device->request_timer);
@@ -2187,7 +2180,7 @@ void drbd_destroy_device(struct kref *kref)
if (device->this_bdev)
bdput(device->this_bdev);
- drbd_free_bc(device->ldev);
+ drbd_free_ldev(device->ldev);
device->ldev = NULL;
drbd_release_all_peer_reqs(device);
@@ -2200,15 +2193,20 @@ void drbd_destroy_device(struct kref *kref)
if (device->bitmap) /* should no longer be there. */
drbd_bm_cleanup(device);
- __free_page(device->md_io_page);
+ __free_page(device->md_io.page);
put_disk(device->vdisk);
blk_cleanup_queue(device->rq_queue);
kfree(device->rs_plan_s);
- kfree(first_peer_device(device));
- kfree(device);
- for_each_connection(connection, resource)
- kref_put(&connection->kref, drbd_destroy_connection);
+ /* not for_each_connection(connection, resource):
+ * those may have been cleaned up and disassociated already.
+ */
+ for_each_peer_device_safe(peer_device, tmp_peer_device, device) {
+ kref_put(&peer_device->connection->kref, drbd_destroy_connection);
+ kfree(peer_device);
+ }
+ memset(device, 0xfd, sizeof(*device));
+ kfree(device);
kref_put(&resource->kref, drbd_destroy_resource);
}
@@ -2236,7 +2234,7 @@ static void do_retry(struct work_struct *ws)
list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
struct drbd_device *device = req->device;
struct bio *bio = req->master_bio;
- unsigned long start_time = req->start_time;
+ unsigned long start_jif = req->start_jif;
bool expected;
expected =
@@ -2271,10 +2269,12 @@ static void do_retry(struct work_struct *ws)
/* We are not just doing generic_make_request(),
* as we want to keep the start_time information. */
inc_ap_bio(device);
- __drbd_make_request(device, bio, start_time);
+ __drbd_make_request(device, bio, start_jif);
}
}
+/* called via drbd_req_put_completion_ref(),
+ * holds resource->req_lock */
void drbd_restart_request(struct drbd_request *req)
{
unsigned long flags;
@@ -2298,6 +2298,7 @@ void drbd_destroy_resource(struct kref *kref)
idr_destroy(&resource->devices);
free_cpumask_var(resource->cpu_mask);
kfree(resource->name);
+ memset(resource, 0xf2, sizeof(*resource));
kfree(resource);
}
@@ -2307,8 +2308,10 @@ void drbd_free_resource(struct drbd_resource *resource)
for_each_connection_safe(connection, tmp, resource) {
list_del(&connection->connections);
+ drbd_debugfs_connection_cleanup(connection);
kref_put(&connection->kref, drbd_destroy_connection);
}
+ drbd_debugfs_resource_cleanup(resource);
kref_put(&resource->kref, drbd_destroy_resource);
}
@@ -2318,8 +2321,6 @@ static void drbd_cleanup(void)
struct drbd_device *device;
struct drbd_resource *resource, *tmp;
- unregister_reboot_notifier(&drbd_notifier);
-
/* first remove proc,
* drbdsetup uses it's presence to detect
* whether DRBD is loaded.
@@ -2335,6 +2336,7 @@ static void drbd_cleanup(void)
destroy_workqueue(retry.wq);
drbd_genl_unregister();
+ drbd_debugfs_cleanup();
idr_for_each_entry(&drbd_devices, device, i)
drbd_delete_device(device);
@@ -2350,7 +2352,7 @@ static void drbd_cleanup(void)
idr_destroy(&drbd_devices);
- printk(KERN_INFO "drbd: module cleanup done.\n");
+ pr_info("module cleanup done.\n");
}
/**
@@ -2539,6 +2541,20 @@ int set_resource_options(struct drbd_resource *resource, struct res_opts *res_op
if (nr_cpu_ids > 1 && res_opts->cpu_mask[0] != 0) {
err = bitmap_parse(res_opts->cpu_mask, DRBD_CPU_MASK_SIZE,
cpumask_bits(new_cpu_mask), nr_cpu_ids);
+ if (err == -EOVERFLOW) {
+ /* So what. mask it out. */
+ cpumask_var_t tmp_cpu_mask;
+ if (zalloc_cpumask_var(&tmp_cpu_mask, GFP_KERNEL)) {
+ cpumask_setall(tmp_cpu_mask);
+ cpumask_and(new_cpu_mask, new_cpu_mask, tmp_cpu_mask);
+ drbd_warn(resource, "Overflow in bitmap_parse(%.12s%s), truncating to %u bits\n",
+ res_opts->cpu_mask,
+ strlen(res_opts->cpu_mask) > 12 ? "..." : "",
+ nr_cpu_ids);
+ free_cpumask_var(tmp_cpu_mask);
+ err = 0;
+ }
+ }
if (err) {
drbd_warn(resource, "bitmap_parse() failed with %d\n", err);
/* retcode = ERR_CPU_MASK_PARSE; */
@@ -2579,10 +2595,12 @@ struct drbd_resource *drbd_create_resource(const char *name)
kref_init(&resource->kref);
idr_init(&resource->devices);
INIT_LIST_HEAD(&resource->connections);
+ resource->write_ordering = WO_bdev_flush;
list_add_tail_rcu(&resource->resources, &drbd_resources);
mutex_init(&resource->conf_update);
mutex_init(&resource->adm_mutex);
spin_lock_init(&resource->req_lock);
+ drbd_debugfs_resource_add(resource);
return resource;
fail_free_name:
@@ -2593,7 +2611,7 @@ fail:
return NULL;
}
-/* caller must be under genl_lock() */
+/* caller must be under adm_mutex */
struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
{
struct drbd_resource *resource;
@@ -2617,7 +2635,6 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
INIT_LIST_HEAD(&connection->current_epoch->list);
connection->epochs = 1;
spin_lock_init(&connection->epoch_lock);
- connection->write_ordering = WO_bdev_flush;
connection->send.seen_any_write_yet = false;
connection->send.current_epoch_nr = 0;
@@ -2652,6 +2669,7 @@ struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts)
kref_get(&resource->kref);
list_add_tail_rcu(&connection->connections, &resource->connections);
+ drbd_debugfs_connection_add(connection);
return connection;
fail_resource:
@@ -2680,6 +2698,7 @@ void drbd_destroy_connection(struct kref *kref)
drbd_free_socket(&connection->data);
kfree(connection->int_dig_in);
kfree(connection->int_dig_vv);
+ memset(connection, 0xfc, sizeof(*connection));
kfree(connection);
kref_put(&resource->kref, drbd_destroy_resource);
}
@@ -2694,7 +2713,6 @@ static int init_submitter(struct drbd_device *device)
return -ENOMEM;
INIT_WORK(&device->submit.worker, do_submit);
- spin_lock_init(&device->submit.lock);
INIT_LIST_HEAD(&device->submit.writes);
return 0;
}
@@ -2764,8 +2782,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
blk_queue_merge_bvec(q, drbd_merge_bvec);
q->queue_lock = &resource->req_lock;
- device->md_io_page = alloc_page(GFP_KERNEL);
- if (!device->md_io_page)
+ device->md_io.page = alloc_page(GFP_KERNEL);
+ if (!device->md_io.page)
goto out_no_io_page;
if (drbd_bm_init(device))
@@ -2794,6 +2812,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
kref_get(&device->kref);
INIT_LIST_HEAD(&device->peer_devices);
+ INIT_LIST_HEAD(&device->pending_bitmap_io);
for_each_connection(connection, resource) {
peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
if (!peer_device)
@@ -2829,7 +2848,10 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
for_each_peer_device(peer_device, device)
drbd_connected(peer_device);
}
-
+ /* move to create_peer_device() */
+ for_each_peer_device(peer_device, device)
+ drbd_debugfs_peer_device_add(peer_device);
+ drbd_debugfs_device_add(device);
return NO_ERROR;
out_idr_remove_vol:
@@ -2853,7 +2875,7 @@ out_idr_remove_minor:
out_no_minor_idr:
drbd_bm_cleanup(device);
out_no_bitmap:
- __free_page(device->md_io_page);
+ __free_page(device->md_io.page);
out_no_io_page:
put_disk(disk);
out_no_disk:
@@ -2868,8 +2890,13 @@ void drbd_delete_device(struct drbd_device *device)
{
struct drbd_resource *resource = device->resource;
struct drbd_connection *connection;
+ struct drbd_peer_device *peer_device;
int refs = 3;
+ /* move to free_peer_device() */
+ for_each_peer_device(peer_device, device)
+ drbd_debugfs_peer_device_cleanup(peer_device);
+ drbd_debugfs_device_cleanup(device);
for_each_connection(connection, resource) {
idr_remove(&connection->peer_devices, device->vnr);
refs++;
@@ -2881,13 +2908,12 @@ void drbd_delete_device(struct drbd_device *device)
kref_sub(&device->kref, refs, drbd_destroy_device);
}
-int __init drbd_init(void)
+static int __init drbd_init(void)
{
int err;
if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
- printk(KERN_ERR
- "drbd: invalid minor_count (%d)\n", minor_count);
+ pr_err("invalid minor_count (%d)\n", minor_count);
#ifdef MODULE
return -EINVAL;
#else
@@ -2897,14 +2923,11 @@ int __init drbd_init(void)
err = register_blkdev(DRBD_MAJOR, "drbd");
if (err) {
- printk(KERN_ERR
- "drbd: unable to register block device major %d\n",
+ pr_err("unable to register block device major %d\n",
DRBD_MAJOR);
return err;
}
- register_reboot_notifier(&drbd_notifier);
-
/*
* allocate all necessary structs
*/
@@ -2918,7 +2941,7 @@ int __init drbd_init(void)
err = drbd_genl_register();
if (err) {
- printk(KERN_ERR "drbd: unable to register generic netlink family\n");
+ pr_err("unable to register generic netlink family\n");
goto fail;
}
@@ -2929,38 +2952,39 @@ int __init drbd_init(void)
err = -ENOMEM;
drbd_proc = proc_create_data("drbd", S_IFREG | S_IRUGO , NULL, &drbd_proc_fops, NULL);
if (!drbd_proc) {
- printk(KERN_ERR "drbd: unable to register proc file\n");
+ pr_err("unable to register proc file\n");
goto fail;
}
retry.wq = create_singlethread_workqueue("drbd-reissue");
if (!retry.wq) {
- printk(KERN_ERR "drbd: unable to create retry workqueue\n");
+ pr_err("unable to create retry workqueue\n");
goto fail;
}
INIT_WORK(&retry.worker, do_retry);
spin_lock_init(&retry.lock);
INIT_LIST_HEAD(&retry.writes);
- printk(KERN_INFO "drbd: initialized. "
+ if (drbd_debugfs_init())
+ pr_notice("failed to initialize debugfs -- will not be available\n");
+
+ pr_info("initialized. "
"Version: " REL_VERSION " (api:%d/proto:%d-%d)\n",
API_VERSION, PRO_VERSION_MIN, PRO_VERSION_MAX);
- printk(KERN_INFO "drbd: %s\n", drbd_buildtag());
- printk(KERN_INFO "drbd: registered as block device major %d\n",
- DRBD_MAJOR);
-
+ pr_info("%s\n", drbd_buildtag());
+ pr_info("registered as block device major %d\n", DRBD_MAJOR);
return 0; /* Success! */
fail:
drbd_cleanup();
if (err == -ENOMEM)
- printk(KERN_ERR "drbd: ran out of memory\n");
+ pr_err("ran out of memory\n");
else
- printk(KERN_ERR "drbd: initialization failure\n");
+ pr_err("initialization failure\n");
return err;
}
-void drbd_free_bc(struct drbd_backing_dev *ldev)
+void drbd_free_ldev(struct drbd_backing_dev *ldev)
{
if (ldev == NULL)
return;
@@ -2972,24 +2996,29 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
kfree(ldev);
}
-void drbd_free_sock(struct drbd_connection *connection)
+static void drbd_free_one_sock(struct drbd_socket *ds)
{
- if (connection->data.socket) {
- mutex_lock(&connection->data.mutex);
- kernel_sock_shutdown(connection->data.socket, SHUT_RDWR);
- sock_release(connection->data.socket);
- connection->data.socket = NULL;
- mutex_unlock(&connection->data.mutex);
- }
- if (connection->meta.socket) {
- mutex_lock(&connection->meta.mutex);
- kernel_sock_shutdown(connection->meta.socket, SHUT_RDWR);
- sock_release(connection->meta.socket);
- connection->meta.socket = NULL;
- mutex_unlock(&connection->meta.mutex);
+ struct socket *s;
+ mutex_lock(&ds->mutex);
+ s = ds->socket;
+ ds->socket = NULL;
+ mutex_unlock(&ds->mutex);
+ if (s) {
+ /* so debugfs does not need to mutex_lock() */
+ synchronize_rcu();
+ kernel_sock_shutdown(s, SHUT_RDWR);
+ sock_release(s);
}
}
+void drbd_free_sock(struct drbd_connection *connection)
+{
+ if (connection->data.socket)
+ drbd_free_one_sock(&connection->data);
+ if (connection->meta.socket)
+ drbd_free_one_sock(&connection->meta);
+}
+
/* meta data management */
void conn_md_sync(struct drbd_connection *connection)
@@ -3093,7 +3122,7 @@ void drbd_md_sync(struct drbd_device *device)
if (!get_ldev_if_state(device, D_FAILED))
return;
- buffer = drbd_md_get_buffer(device);
+ buffer = drbd_md_get_buffer(device, __func__);
if (!buffer)
goto out;
@@ -3253,7 +3282,7 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev)
if (device->state.disk != D_DISKLESS)
return ERR_DISK_CONFIGURED;
- buffer = drbd_md_get_buffer(device);
+ buffer = drbd_md_get_buffer(device, __func__);
if (!buffer)
return ERR_NOMEM;
@@ -3466,23 +3495,19 @@ void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
*
* Sets all bits in the bitmap and writes the whole bitmap to stable storage.
*/
-int drbd_bmio_set_n_write(struct drbd_device *device)
+int drbd_bmio_set_n_write(struct drbd_device *device) __must_hold(local)
{
int rv = -EIO;
- if (get_ldev_if_state(device, D_ATTACHING)) {
- drbd_md_set_flag(device, MDF_FULL_SYNC);
- drbd_md_sync(device);
- drbd_bm_set_all(device);
-
- rv = drbd_bm_write(device);
+ drbd_md_set_flag(device, MDF_FULL_SYNC);
+ drbd_md_sync(device);
+ drbd_bm_set_all(device);
- if (!rv) {
- drbd_md_clear_flag(device, MDF_FULL_SYNC);
- drbd_md_sync(device);
- }
+ rv = drbd_bm_write(device);
- put_ldev(device);
+ if (!rv) {
+ drbd_md_clear_flag(device, MDF_FULL_SYNC);
+ drbd_md_sync(device);
}
return rv;
@@ -3494,18 +3519,11 @@ int drbd_bmio_set_n_write(struct drbd_device *device)
*
* Clears all bits in the bitmap and writes the whole bitmap to stable storage.
*/
-int drbd_bmio_clear_n_write(struct drbd_device *device)
+int drbd_bmio_clear_n_write(struct drbd_device *device) __must_hold(local)
{
- int rv = -EIO;
-
drbd_resume_al(device);
- if (get_ldev_if_state(device, D_ATTACHING)) {
- drbd_bm_clear_all(device);
- rv = drbd_bm_write(device);
- put_ldev(device);
- }
-
- return rv;
+ drbd_bm_clear_all(device);
+ return drbd_bm_write(device);
}
static int w_bitmap_io(struct drbd_work *w, int unused)
@@ -3537,61 +3555,6 @@ static int w_bitmap_io(struct drbd_work *w, int unused)
return 0;
}
-void drbd_ldev_destroy(struct drbd_device *device)
-{
- lc_destroy(device->resync);
- device->resync = NULL;
- lc_destroy(device->act_log);
- device->act_log = NULL;
- __no_warn(local,
- drbd_free_bc(device->ldev);
- device->ldev = NULL;);
-
- clear_bit(GO_DISKLESS, &device->flags);
-}
-
-static int w_go_diskless(struct drbd_work *w, int unused)
-{
- struct drbd_device *device =
- container_of(w, struct drbd_device, go_diskless);
-
- D_ASSERT(device, device->state.disk == D_FAILED);
- /* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
- * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
- * the protected members anymore, though, so once put_ldev reaches zero
- * again, it will be safe to free them. */
-
- /* Try to write changed bitmap pages, read errors may have just
- * set some bits outside the area covered by the activity log.
- *
- * If we have an IO error during the bitmap writeout,
- * we will want a full sync next time, just in case.
- * (Do we want a specific meta data flag for this?)
- *
- * If that does not make it to stable storage either,
- * we cannot do anything about that anymore.
- *
- * We still need to check if both bitmap and ldev are present, we may
- * end up here after a failed attach, before ldev was even assigned.
- */
- if (device->bitmap && device->ldev) {
- /* An interrupted resync or similar is allowed to recounts bits
- * while we detach.
- * Any modifications would not be expected anymore, though.
- */
- if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
- "detach", BM_LOCKED_TEST_ALLOWED)) {
- if (test_bit(WAS_READ_ERROR, &device->flags)) {
- drbd_md_set_flag(device, MDF_FULL_SYNC);
- drbd_md_sync(device);
- }
- }
- }
-
- drbd_force_state(device, NS(disk, D_DISKLESS));
- return 0;
-}
-
/**
* drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
* @device: DRBD device.
@@ -3603,6 +3566,9 @@ static int w_go_diskless(struct drbd_work *w, int unused)
* that drbd_set_out_of_sync() can not be called. This function MAY ONLY be
* called from worker context. It MUST NOT be used while a previous such
* work is still pending!
+ *
+ * Its worker function encloses the call of io_fn() by get_ldev() and
+ * put_ldev().
*/
void drbd_queue_bitmap_io(struct drbd_device *device,
int (*io_fn)(struct drbd_device *),
@@ -3685,25 +3651,7 @@ int drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag)
static void md_sync_timer_fn(unsigned long data)
{
struct drbd_device *device = (struct drbd_device *) data;
-
- /* must not double-queue! */
- if (list_empty(&device->md_sync_work.list))
- drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
- &device->md_sync_work);
-}
-
-static int w_md_sync(struct drbd_work *w, int unused)
-{
- struct drbd_device *device =
- container_of(w, struct drbd_device, md_sync_work);
-
- drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
-#ifdef DEBUG
- drbd_warn(device, "last md_mark_dirty: %s:%u\n",
- device->last_md_mark_dirty.func, device->last_md_mark_dirty.line);
-#endif
- drbd_md_sync(device);
- return 0;
+ drbd_device_post_work(device, MD_SYNC);
}
const char *cmdname(enum drbd_packet cmd)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 3f2e16738080..1cd47df44bda 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -23,6 +23,8 @@
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/drbd.h>
#include <linux/in.h>
@@ -85,7 +87,7 @@ static void drbd_adm_send_reply(struct sk_buff *skb, struct genl_info *info)
{
genlmsg_end(skb, genlmsg_data(nlmsg_data(nlmsg_hdr(skb))));
if (genlmsg_reply(skb, info))
- printk(KERN_ERR "drbd: error sending genl reply\n");
+ pr_err("error sending genl reply\n");
}
/* Used on a fresh "drbd_adm_prepare"d reply_skb, this cannot fail: The only
@@ -558,8 +560,10 @@ void conn_try_outdate_peer_async(struct drbd_connection *connection)
}
enum drbd_state_rv
-drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
+drbd_set_role(struct drbd_device *const device, enum drbd_role new_role, int force)
{
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
const int max_tries = 4;
enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
struct net_conf *nc;
@@ -607,7 +611,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
device->state.disk == D_CONSISTENT && mask.pdsk == 0) {
D_ASSERT(device, device->state.pdsk == D_UNKNOWN);
- if (conn_try_outdate_peer(first_peer_device(device)->connection)) {
+ if (conn_try_outdate_peer(connection)) {
val.disk = D_UP_TO_DATE;
mask.disk = D_MASK;
}
@@ -617,7 +621,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
if (rv == SS_NOTHING_TO_DO)
goto out;
if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
- if (!conn_try_outdate_peer(first_peer_device(device)->connection) && force) {
+ if (!conn_try_outdate_peer(connection) && force) {
drbd_warn(device, "Forced into split brain situation!\n");
mask.pdsk = D_MASK;
val.pdsk = D_OUTDATED;
@@ -630,7 +634,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
retry at most once more in this case. */
int timeo;
rcu_read_lock();
- nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+ nc = rcu_dereference(connection->net_conf);
timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
rcu_read_unlock();
schedule_timeout_interruptible(timeo);
@@ -659,19 +663,17 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
/* FIXME also wait for all pending P_BARRIER_ACK? */
if (new_role == R_SECONDARY) {
- set_disk_ro(device->vdisk, true);
if (get_ldev(device)) {
device->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
put_ldev(device);
}
} else {
- /* Called from drbd_adm_set_role only.
- * We are still holding the conf_update mutex. */
- nc = first_peer_device(device)->connection->net_conf;
+ mutex_lock(&device->resource->conf_update);
+ nc = connection->net_conf;
if (nc)
nc->discard_my_data = 0; /* without copy; single bit op is atomic */
+ mutex_unlock(&device->resource->conf_update);
- set_disk_ro(device->vdisk, false);
if (get_ldev(device)) {
if (((device->state.conn < C_CONNECTED ||
device->state.pdsk <= D_FAILED)
@@ -689,12 +691,12 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
if (device->state.conn >= C_WF_REPORT_PARAMS) {
/* if this was forced, we should consider sync */
if (forced)
- drbd_send_uuids(first_peer_device(device));
- drbd_send_current_state(first_peer_device(device));
+ drbd_send_uuids(peer_device);
+ drbd_send_current_state(peer_device);
}
drbd_md_sync(device);
-
+ set_disk_ro(device->vdisk, new_role == R_SECONDARY);
kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
out:
mutex_unlock(device->state_mutex);
@@ -891,7 +893,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
* still lock the act_log to not trigger ASSERTs there.
*/
drbd_suspend_io(device);
- buffer = drbd_md_get_buffer(device); /* Lock meta-data IO */
+ buffer = drbd_md_get_buffer(device, __func__); /* Lock meta-data IO */
if (!buffer) {
drbd_resume_io(device);
return DS_ERROR;
@@ -971,6 +973,10 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct
if (la_size_changed || md_moved || rs) {
u32 prev_flags;
+ /* We do some synchronous IO below, which may take some time.
+ * Clear the timer, to avoid scary "timer expired!" messages,
+ * "Superblock" is written out at least twice below, anyways. */
+ del_timer(&device->md_sync_timer);
drbd_al_shrink(device); /* All extents inactive. */
prev_flags = md->flags;
@@ -1116,15 +1122,16 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
return 0;
}
-static void drbd_setup_queue_param(struct drbd_device *device, unsigned int max_bio_size)
+static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
+ unsigned int max_bio_size)
{
struct request_queue * const q = device->rq_queue;
unsigned int max_hw_sectors = max_bio_size >> 9;
unsigned int max_segments = 0;
struct request_queue *b = NULL;
- if (get_ldev_if_state(device, D_ATTACHING)) {
- b = device->ldev->backing_bdev->bd_disk->queue;
+ if (bdev) {
+ b = bdev->backing_bdev->bd_disk->queue;
max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
rcu_read_lock();
@@ -1169,11 +1176,10 @@ static void drbd_setup_queue_param(struct drbd_device *device, unsigned int max_
b->backing_dev_info.ra_pages);
q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
}
- put_ldev(device);
}
}
-void drbd_reconsider_max_bio_size(struct drbd_device *device)
+void drbd_reconsider_max_bio_size(struct drbd_device *device, struct drbd_backing_dev *bdev)
{
unsigned int now, new, local, peer;
@@ -1181,10 +1187,9 @@ void drbd_reconsider_max_bio_size(struct drbd_device *device)
local = device->local_max_bio_size; /* Eventually last known value, from volatile memory */
peer = device->peer_max_bio_size; /* Eventually last known value, from meta data */
- if (get_ldev_if_state(device, D_ATTACHING)) {
- local = queue_max_hw_sectors(device->ldev->backing_bdev->bd_disk->queue) << 9;
+ if (bdev) {
+ local = queue_max_hw_sectors(bdev->backing_bdev->bd_disk->queue) << 9;
device->local_max_bio_size = local;
- put_ldev(device);
}
local = min(local, DRBD_MAX_BIO_SIZE);
@@ -1217,7 +1222,7 @@ void drbd_reconsider_max_bio_size(struct drbd_device *device)
if (new != now)
drbd_info(device, "max BIO size = %u\n", new);
- drbd_setup_queue_param(device, new);
+ drbd_setup_queue_param(device, bdev, new);
}
/* Starts the worker thread */
@@ -1299,6 +1304,13 @@ static unsigned int drbd_al_extents_max(struct drbd_backing_dev *bdev)
return (al_size_4k - 1) * AL_CONTEXT_PER_TRANSACTION;
}
+static bool write_ordering_changed(struct disk_conf *a, struct disk_conf *b)
+{
+ return a->disk_barrier != b->disk_barrier ||
+ a->disk_flushes != b->disk_flushes ||
+ a->disk_drain != b->disk_drain;
+}
+
int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
{
struct drbd_config_context adm_ctx;
@@ -1405,7 +1417,8 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
else
set_bit(MD_NO_FUA, &device->flags);
- drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
+ if (write_ordering_changed(old_disk_conf, new_disk_conf))
+ drbd_bump_write_ordering(device->resource, NULL, WO_bdev_flush);
drbd_md_sync(device);
@@ -1440,6 +1453,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
{
struct drbd_config_context adm_ctx;
struct drbd_device *device;
+ struct drbd_peer_device *peer_device;
+ struct drbd_connection *connection;
int err;
enum drbd_ret_code retcode;
enum determine_dev_size dd;
@@ -1462,7 +1477,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
device = adm_ctx.device;
mutex_lock(&adm_ctx.resource->adm_mutex);
- conn_reconfig_start(first_peer_device(device)->connection);
+ peer_device = first_peer_device(device);
+ connection = peer_device ? peer_device->connection : NULL;
+ conn_reconfig_start(connection);
/* if you want to reconfigure, please tear down first */
if (device->state.disk > D_DISKLESS) {
@@ -1473,7 +1490,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
* drbd_ldev_destroy is done already, we may end up here very fast,
* e.g. if someone calls attach from the on-io-error handler,
* to realize a "hot spare" feature (not that I'd recommend that) */
- wait_event(device->misc_wait, !atomic_read(&device->local_cnt));
+ wait_event(device->misc_wait, !test_bit(GOING_DISKLESS, &device->flags));
/* make sure there is no leftover from previous force-detach attempts */
clear_bit(FORCE_DETACH, &device->flags);
@@ -1529,7 +1546,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
goto fail;
rcu_read_lock();
- nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+ nc = rcu_dereference(connection->net_conf);
if (nc) {
if (new_disk_conf->fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) {
rcu_read_unlock();
@@ -1649,7 +1666,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
*/
wait_event(device->misc_wait, !atomic_read(&device->ap_pending_cnt) || drbd_suspended(device));
/* and for any other previously queued work */
- drbd_flush_workqueue(&first_peer_device(device)->connection->sender_work);
+ drbd_flush_workqueue(&connection->sender_work);
rv = _drbd_request_state(device, NS(disk, D_ATTACHING), CS_VERBOSE);
retcode = rv; /* FIXME: Type mismatch. */
@@ -1710,7 +1727,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
new_disk_conf = NULL;
new_plan = NULL;
- drbd_bump_write_ordering(first_peer_device(device)->connection, WO_bdev_flush);
+ drbd_bump_write_ordering(device->resource, device->ldev, WO_bdev_flush);
if (drbd_md_test_flag(device->ldev, MDF_CRASHED_PRIMARY))
set_bit(CRASHED_PRIMARY, &device->flags);
@@ -1726,7 +1743,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
device->read_cnt = 0;
device->writ_cnt = 0;
- drbd_reconsider_max_bio_size(device);
+ drbd_reconsider_max_bio_size(device, device->ldev);
/* If I am currently not R_PRIMARY,
* but meta data primary indicator is set,
@@ -1845,7 +1862,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
kobject_uevent(&disk_to_dev(device->vdisk)->kobj, KOBJ_CHANGE);
put_ldev(device);
- conn_reconfig_done(first_peer_device(device)->connection);
+ conn_reconfig_done(connection);
mutex_unlock(&adm_ctx.resource->adm_mutex);
drbd_adm_finish(&adm_ctx, info, retcode);
return 0;
@@ -1856,7 +1873,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
drbd_force_state(device, NS(disk, D_DISKLESS));
drbd_md_sync(device);
fail:
- conn_reconfig_done(first_peer_device(device)->connection);
+ conn_reconfig_done(connection);
if (nbc) {
if (nbc->backing_bdev)
blkdev_put(nbc->backing_bdev,
@@ -1888,7 +1905,7 @@ static int adm_detach(struct drbd_device *device, int force)
}
drbd_suspend_io(device); /* so no-one is stuck in drbd_al_begin_io */
- drbd_md_get_buffer(device); /* make sure there is no in-flight meta-data IO */
+ drbd_md_get_buffer(device, __func__); /* make sure there is no in-flight meta-data IO */
retcode = drbd_request_state(device, NS(disk, D_FAILED));
drbd_md_put_buffer(device);
/* D_FAILED will transition to DISKLESS. */
@@ -2654,8 +2671,13 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
if (retcode != NO_ERROR)
goto out;
- mutex_lock(&adm_ctx.resource->adm_mutex);
device = adm_ctx.device;
+ if (!get_ldev(device)) {
+ retcode = ERR_NO_DISK;
+ goto out;
+ }
+
+ mutex_lock(&adm_ctx.resource->adm_mutex);
/* If there is still bitmap IO pending, probably because of a previous
* resync just being finished, wait for it before requesting a new resync.
@@ -2679,6 +2701,7 @@ int drbd_adm_invalidate(struct sk_buff *skb, struct genl_info *info)
retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_T));
drbd_resume_io(device);
mutex_unlock(&adm_ctx.resource->adm_mutex);
+ put_ldev(device);
out:
drbd_adm_finish(&adm_ctx, info, retcode);
return 0;
@@ -2704,7 +2727,7 @@ out:
return 0;
}
-static int drbd_bmio_set_susp_al(struct drbd_device *device)
+static int drbd_bmio_set_susp_al(struct drbd_device *device) __must_hold(local)
{
int rv;
@@ -2725,8 +2748,13 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
if (retcode != NO_ERROR)
goto out;
- mutex_lock(&adm_ctx.resource->adm_mutex);
device = adm_ctx.device;
+ if (!get_ldev(device)) {
+ retcode = ERR_NO_DISK;
+ goto out;
+ }
+
+ mutex_lock(&adm_ctx.resource->adm_mutex);
/* If there is still bitmap IO pending, probably because of a previous
* resync just being finished, wait for it before requesting a new resync.
@@ -2753,6 +2781,7 @@ int drbd_adm_invalidate_peer(struct sk_buff *skb, struct genl_info *info)
retcode = drbd_request_state(device, NS(conn, C_STARTING_SYNC_S));
drbd_resume_io(device);
mutex_unlock(&adm_ctx.resource->adm_mutex);
+ put_ldev(device);
out:
drbd_adm_finish(&adm_ctx, info, retcode);
return 0;
@@ -2892,7 +2921,7 @@ static struct drbd_connection *the_only_connection(struct drbd_resource *resourc
return list_first_entry(&resource->connections, struct drbd_connection, connections);
}
-int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
+static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
const struct sib_info *sib)
{
struct drbd_resource *resource = device->resource;
@@ -3622,13 +3651,6 @@ void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib)
unsigned seq;
int err = -ENOMEM;
- if (sib->sib_reason == SIB_SYNC_PROGRESS) {
- if (time_after(jiffies, device->rs_last_bcast + HZ))
- device->rs_last_bcast = jiffies;
- else
- return;
- }
-
seq = atomic_inc_return(&drbd_genl_seq);
msg = genlmsg_new(NLMSG_GOODSIZE, GFP_NOIO);
if (!msg)
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index 89736bdbbc70..06e6147c7601 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -60,20 +60,65 @@ static void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
seq_printf(seq, "%ld", v);
}
+static void drbd_get_syncer_progress(struct drbd_device *device,
+ union drbd_dev_state state, unsigned long *rs_total,
+ unsigned long *bits_left, unsigned int *per_mil_done)
+{
+ /* this is to break it at compile time when we change that, in case we
+ * want to support more than (1<<32) bits on a 32bit arch. */
+ typecheck(unsigned long, device->rs_total);
+ *rs_total = device->rs_total;
+
+ /* note: both rs_total and rs_left are in bits, i.e. in
+ * units of BM_BLOCK_SIZE.
+ * for the percentage, we don't care. */
+
+ if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
+ *bits_left = device->ov_left;
+ else
+ *bits_left = drbd_bm_total_weight(device) - device->rs_failed;
+ /* >> 10 to prevent overflow,
+ * +1 to prevent division by zero */
+ if (*bits_left > *rs_total) {
+ /* D'oh. Maybe a logic bug somewhere. More likely just a race
+ * between state change and reset of rs_total.
+ */
+ *bits_left = *rs_total;
+ *per_mil_done = *rs_total ? 0 : 1000;
+ } else {
+ /* Make sure the division happens in long context.
+ * We allow up to one petabyte storage right now,
+ * at a granularity of 4k per bit that is 2**38 bits.
+ * After shift right and multiplication by 1000,
+ * this should still fit easily into a 32bit long,
+ * so we don't need a 64bit division on 32bit arch.
+ * Note: currently we don't support such large bitmaps on 32bit
+ * arch anyways, but no harm done to be prepared for it here.
+ */
+ unsigned int shift = *rs_total > UINT_MAX ? 16 : 10;
+ unsigned long left = *bits_left >> shift;
+ unsigned long total = 1UL + (*rs_total >> shift);
+ unsigned long tmp = 1000UL - left * 1000UL/total;
+ *per_mil_done = tmp;
+ }
+}
+
+
/*lge
* progress bars shamelessly adapted from driver/md/md.c
* output looks like
* [=====>..............] 33.5% (23456/123456)
* finish: 2:20:20 speed: 6,345 (6,456) K/sec
*/
-static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq)
+static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *seq,
+ union drbd_dev_state state)
{
- unsigned long db, dt, dbdt, rt, rs_left;
+ unsigned long db, dt, dbdt, rt, rs_total, rs_left;
unsigned int res;
int i, x, y;
int stalled = 0;
- drbd_get_syncer_progress(device, &rs_left, &res);
+ drbd_get_syncer_progress(device, state, &rs_total, &rs_left, &res);
x = res/50;
y = 20-x;
@@ -85,21 +130,21 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se
seq_printf(seq, ".");
seq_printf(seq, "] ");
- if (device->state.conn == C_VERIFY_S || device->state.conn == C_VERIFY_T)
+ if (state.conn == C_VERIFY_S || state.conn == C_VERIFY_T)
seq_printf(seq, "verified:");
else
seq_printf(seq, "sync'ed:");
seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
/* if more than a few GB, display in MB */
- if (device->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
+ if (rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
seq_printf(seq, "(%lu/%lu)M",
(unsigned long) Bit2KB(rs_left >> 10),
- (unsigned long) Bit2KB(device->rs_total >> 10));
+ (unsigned long) Bit2KB(rs_total >> 10));
else
seq_printf(seq, "(%lu/%lu)K\n\t",
(unsigned long) Bit2KB(rs_left),
- (unsigned long) Bit2KB(device->rs_total));
+ (unsigned long) Bit2KB(rs_total));
/* see drivers/md/md.c
* We do not want to overflow, so the order of operands and
@@ -150,13 +195,13 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se
dt = (jiffies - device->rs_start - device->rs_paused) / HZ;
if (dt == 0)
dt = 1;
- db = device->rs_total - rs_left;
+ db = rs_total - rs_left;
dbdt = Bit2KB(db/dt);
seq_printf_with_thousands_grouping(seq, dbdt);
seq_printf(seq, ")");
- if (device->state.conn == C_SYNC_TARGET ||
- device->state.conn == C_VERIFY_S) {
+ if (state.conn == C_SYNC_TARGET ||
+ state.conn == C_VERIFY_S) {
seq_printf(seq, " want: ");
seq_printf_with_thousands_grouping(seq, device->c_sync_rate);
}
@@ -168,8 +213,8 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se
unsigned long bm_bits = drbd_bm_bits(device);
unsigned long bit_pos;
unsigned long long stop_sector = 0;
- if (device->state.conn == C_VERIFY_S ||
- device->state.conn == C_VERIFY_T) {
+ if (state.conn == C_VERIFY_S ||
+ state.conn == C_VERIFY_T) {
bit_pos = bm_bits - device->ov_left;
if (verify_can_do_stop_sector(device))
stop_sector = device->ov_stop_sector;
@@ -188,22 +233,13 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se
}
}
-static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
-{
- struct bm_extent *bme = lc_entry(e, struct bm_extent, lce);
-
- seq_printf(seq, "%5d %s %s\n", bme->rs_left,
- bme->flags & BME_NO_WRITES ? "NO_WRITES" : "---------",
- bme->flags & BME_LOCKED ? "LOCKED" : "------"
- );
-}
-
static int drbd_seq_show(struct seq_file *seq, void *v)
{
int i, prev_i = -1;
const char *sn;
struct drbd_device *device;
struct net_conf *nc;
+ union drbd_dev_state state;
char wp;
static char write_ordering_chars[] = {
@@ -241,11 +277,12 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "\n");
prev_i = i;
- sn = drbd_conn_str(device->state.conn);
+ state = device->state;
+ sn = drbd_conn_str(state.conn);
- if (device->state.conn == C_STANDALONE &&
- device->state.disk == D_DISKLESS &&
- device->state.role == R_SECONDARY) {
+ if (state.conn == C_STANDALONE &&
+ state.disk == D_DISKLESS &&
+ state.role == R_SECONDARY) {
seq_printf(seq, "%2d: cs:Unconfigured\n", i);
} else {
/* reset device->congestion_reason */
@@ -258,15 +295,15 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
" ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
"lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
i, sn,
- drbd_role_str(device->state.role),
- drbd_role_str(device->state.peer),
- drbd_disk_str(device->state.disk),
- drbd_disk_str(device->state.pdsk),
+ drbd_role_str(state.role),
+ drbd_role_str(state.peer),
+ drbd_disk_str(state.disk),
+ drbd_disk_str(state.pdsk),
wp,
drbd_suspended(device) ? 's' : 'r',
- device->state.aftr_isp ? 'a' : '-',
- device->state.peer_isp ? 'p' : '-',
- device->state.user_isp ? 'u' : '-',
+ state.aftr_isp ? 'a' : '-',
+ state.peer_isp ? 'p' : '-',
+ state.user_isp ? 'u' : '-',
device->congestion_reason ?: '-',
test_bit(AL_SUSPENDED, &device->flags) ? 's' : '-',
device->send_cnt/2,
@@ -281,17 +318,17 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
atomic_read(&device->unacked_cnt),
atomic_read(&device->ap_bio_cnt),
first_peer_device(device)->connection->epochs,
- write_ordering_chars[first_peer_device(device)->connection->write_ordering]
+ write_ordering_chars[device->resource->write_ordering]
);
seq_printf(seq, " oos:%llu\n",
Bit2KB((unsigned long long)
drbd_bm_total_weight(device)));
}
- if (device->state.conn == C_SYNC_SOURCE ||
- device->state.conn == C_SYNC_TARGET ||
- device->state.conn == C_VERIFY_S ||
- device->state.conn == C_VERIFY_T)
- drbd_syncer_progress(device, seq);
+ if (state.conn == C_SYNC_SOURCE ||
+ state.conn == C_SYNC_TARGET ||
+ state.conn == C_VERIFY_S ||
+ state.conn == C_VERIFY_T)
+ drbd_syncer_progress(device, seq, state);
if (proc_details >= 1 && get_ldev_if_state(device, D_FAILED)) {
lc_seq_printf_stats(seq, device->resync);
@@ -299,12 +336,8 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
put_ldev(device);
}
- if (proc_details >= 2) {
- if (device->resync) {
- lc_seq_dump_details(seq, device->resync, "rs_left",
- resync_dump_detail);
- }
- }
+ if (proc_details >= 2)
+ seq_printf(seq, "\tblocked on activity log: %d\n", atomic_read(&device->ap_actlog_cnt));
}
rcu_read_unlock();
@@ -316,7 +349,7 @@ static int drbd_proc_open(struct inode *inode, struct file *file)
int err;
if (try_module_get(THIS_MODULE)) {
- err = single_open(file, drbd_seq_show, PDE_DATA(inode));
+ err = single_open(file, drbd_seq_show, NULL);
if (err)
module_put(THIS_MODULE);
return err;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 5b17ec88ea05..9342b8da73ab 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -362,17 +362,14 @@ drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t secto
goto fail;
}
+ memset(peer_req, 0, sizeof(*peer_req));
+ INIT_LIST_HEAD(&peer_req->w.list);
drbd_clear_interval(&peer_req->i);
peer_req->i.size = data_size;
peer_req->i.sector = sector;
- peer_req->i.local = false;
- peer_req->i.waiting = false;
-
- peer_req->epoch = NULL;
+ peer_req->submit_jif = jiffies;
peer_req->peer_device = peer_device;
peer_req->pages = page;
- atomic_set(&peer_req->pending_bios, 0);
- peer_req->flags = 0;
/*
* The block_id is opaque to the receiver. It is not endianness
* converted, and sent back to the sender unchanged.
@@ -389,11 +386,16 @@ drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t secto
void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *peer_req,
int is_net)
{
+ might_sleep();
if (peer_req->flags & EE_HAS_DIGEST)
kfree(peer_req->digest);
drbd_free_pages(device, peer_req->pages, is_net);
D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0);
D_ASSERT(device, drbd_interval_empty(&peer_req->i));
+ if (!expect(!(peer_req->flags & EE_CALL_AL_COMPLETE_IO))) {
+ peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
+ drbd_al_complete_io(device, &peer_req->i);
+ }
mempool_free(peer_req, drbd_ee_mempool);
}
@@ -791,8 +793,18 @@ static int receive_first_packet(struct drbd_connection *connection, struct socke
{
unsigned int header_size = drbd_header_size(connection);
struct packet_info pi;
+ struct net_conf *nc;
int err;
+ rcu_read_lock();
+ nc = rcu_dereference(connection->net_conf);
+ if (!nc) {
+ rcu_read_unlock();
+ return -EIO;
+ }
+ sock->sk->sk_rcvtimeo = nc->ping_timeo * 4 * HZ / 10;
+ rcu_read_unlock();
+
err = drbd_recv_short(sock, connection->data.rbuf, header_size, 0);
if (err != header_size) {
if (err >= 0)
@@ -809,7 +821,7 @@ static int receive_first_packet(struct drbd_connection *connection, struct socke
* drbd_socket_okay() - Free the socket if its connection is not okay
* @sock: pointer to the pointer to the socket.
*/
-static int drbd_socket_okay(struct socket **sock)
+static bool drbd_socket_okay(struct socket **sock)
{
int rr;
char tb[4];
@@ -827,6 +839,30 @@ static int drbd_socket_okay(struct socket **sock)
return false;
}
}
+
+static bool connection_established(struct drbd_connection *connection,
+ struct socket **sock1,
+ struct socket **sock2)
+{
+ struct net_conf *nc;
+ int timeout;
+ bool ok;
+
+ if (!*sock1 || !*sock2)
+ return false;
+
+ rcu_read_lock();
+ nc = rcu_dereference(connection->net_conf);
+ timeout = (nc->sock_check_timeo ?: nc->ping_timeo) * HZ / 10;
+ rcu_read_unlock();
+ schedule_timeout_interruptible(timeout);
+
+ ok = drbd_socket_okay(sock1);
+ ok = drbd_socket_okay(sock2) && ok;
+
+ return ok;
+}
+
/* Gets called if a connection is established, or if a new minor gets created
in a connection */
int drbd_connected(struct drbd_peer_device *peer_device)
@@ -868,8 +904,8 @@ static int conn_connect(struct drbd_connection *connection)
struct drbd_socket sock, msock;
struct drbd_peer_device *peer_device;
struct net_conf *nc;
- int vnr, timeout, h, ok;
- bool discard_my_data;
+ int vnr, timeout, h;
+ bool discard_my_data, ok;
enum drbd_state_rv rv;
struct accept_wait_data ad = {
.connection = connection,
@@ -913,17 +949,8 @@ static int conn_connect(struct drbd_connection *connection)
}
}
- if (sock.socket && msock.socket) {
- rcu_read_lock();
- nc = rcu_dereference(connection->net_conf);
- timeout = nc->ping_timeo * HZ / 10;
- rcu_read_unlock();
- schedule_timeout_interruptible(timeout);
- ok = drbd_socket_okay(&sock.socket);
- ok = drbd_socket_okay(&msock.socket) && ok;
- if (ok)
- break;
- }
+ if (connection_established(connection, &sock.socket, &msock.socket))
+ break;
retry:
s = drbd_wait_for_connect(connection, &ad);
@@ -969,8 +996,7 @@ randomize:
goto out_release_sockets;
}
- ok = drbd_socket_okay(&sock.socket);
- ok = drbd_socket_okay(&msock.socket) && ok;
+ ok = connection_established(connection, &sock.socket, &msock.socket);
} while (!ok);
if (ad.s_listen)
@@ -1151,7 +1177,7 @@ static void drbd_flush(struct drbd_connection *connection)
struct drbd_peer_device *peer_device;
int vnr;
- if (connection->write_ordering >= WO_bdev_flush) {
+ if (connection->resource->write_ordering >= WO_bdev_flush) {
rcu_read_lock();
idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
struct drbd_device *device = peer_device->device;
@@ -1161,14 +1187,22 @@ static void drbd_flush(struct drbd_connection *connection)
kref_get(&device->kref);
rcu_read_unlock();
+ /* Right now, we have only this one synchronous code path
+ * for flushes between request epochs.
+ * We may want to make those asynchronous,
+ * or at least parallelize the flushes to the volume devices.
+ */
+ device->flush_jif = jiffies;
+ set_bit(FLUSH_PENDING, &device->flags);
rv = blkdev_issue_flush(device->ldev->backing_bdev,
GFP_NOIO, NULL);
+ clear_bit(FLUSH_PENDING, &device->flags);
if (rv) {
drbd_info(device, "local disk flush failed with status %d\n", rv);
/* would rather check on EOPNOTSUPP, but that is not reliable.
* don't try again for ANY return value != 0
* if (rv == -EOPNOTSUPP) */
- drbd_bump_write_ordering(connection, WO_drain_io);
+ drbd_bump_write_ordering(connection->resource, NULL, WO_drain_io);
}
put_ldev(device);
kref_put(&device->kref, drbd_destroy_device);
@@ -1257,15 +1291,30 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_connection *connectio
return rv;
}
+static enum write_ordering_e
+max_allowed_wo(struct drbd_backing_dev *bdev, enum write_ordering_e wo)
+{
+ struct disk_conf *dc;
+
+ dc = rcu_dereference(bdev->disk_conf);
+
+ if (wo == WO_bdev_flush && !dc->disk_flushes)
+ wo = WO_drain_io;
+ if (wo == WO_drain_io && !dc->disk_drain)
+ wo = WO_none;
+
+ return wo;
+}
+
/**
* drbd_bump_write_ordering() - Fall back to an other write ordering method
* @connection: DRBD connection.
* @wo: Write ordering method to try.
*/
-void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ordering_e wo)
+void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backing_dev *bdev,
+ enum write_ordering_e wo)
{
- struct disk_conf *dc;
- struct drbd_peer_device *peer_device;
+ struct drbd_device *device;
enum write_ordering_e pwo;
int vnr;
static char *write_ordering_str[] = {
@@ -1274,26 +1323,27 @@ void drbd_bump_write_ordering(struct drbd_connection *connection, enum write_ord
[WO_bdev_flush] = "flush",
};
- pwo = connection->write_ordering;
- wo = min(pwo, wo);
+ pwo = resource->write_ordering;
+ if (wo != WO_bdev_flush)
+ wo = min(pwo, wo);
rcu_read_lock();
- idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
- struct drbd_device *device = peer_device->device;
+ idr_for_each_entry(&resource->devices, device, vnr) {
+ if (get_ldev(device)) {
+ wo = max_allowed_wo(device->ldev, wo);
+ if (device->ldev == bdev)
+ bdev = NULL;
+ put_ldev(device);
+ }
+ }
- if (!get_ldev_if_state(device, D_ATTACHING))
- continue;
- dc = rcu_dereference(device->ldev->disk_conf);
+ if (bdev)
+ wo = max_allowed_wo(bdev, wo);
- if (wo == WO_bdev_flush && !dc->disk_flushes)
- wo = WO_drain_io;
- if (wo == WO_drain_io && !dc->disk_drain)
- wo = WO_none;
- put_ldev(device);
- }
rcu_read_unlock();
- connection->write_ordering = wo;
- if (pwo != connection->write_ordering || wo == WO_bdev_flush)
- drbd_info(connection, "Method to ensure write ordering: %s\n", write_ordering_str[connection->write_ordering]);
+
+ resource->write_ordering = wo;
+ if (pwo != resource->write_ordering || wo == WO_bdev_flush)
+ drbd_info(resource, "Method to ensure write ordering: %s\n", write_ordering_str[resource->write_ordering]);
}
/**
@@ -1330,6 +1380,13 @@ int drbd_submit_peer_request(struct drbd_device *device,
/* wait for all pending IO completions, before we start
* zeroing things out. */
conn_wait_active_ee_empty(first_peer_device(device)->connection);
+ /* add it to the active list now,
+ * so we can find it to present it in debugfs */
+ peer_req->submit_jif = jiffies;
+ peer_req->flags |= EE_SUBMITTED;
+ spin_lock_irq(&device->resource->req_lock);
+ list_add_tail(&peer_req->w.list, &device->active_ee);
+ spin_unlock_irq(&device->resource->req_lock);
if (blkdev_issue_zeroout(device->ldev->backing_bdev,
sector, ds >> 9, GFP_NOIO))
peer_req->flags |= EE_WAS_ERROR;
@@ -1398,6 +1455,9 @@ submit:
D_ASSERT(device, page == NULL);
atomic_set(&peer_req->pending_bios, n_bios);
+ /* for debugfs: update timestamp, mark as submitted */
+ peer_req->submit_jif = jiffies;
+ peer_req->flags |= EE_SUBMITTED;
do {
bio = bios;
bios = bios->bi_next;
@@ -1471,7 +1531,7 @@ static int receive_Barrier(struct drbd_connection *connection, struct packet_inf
* R_PRIMARY crashes now.
* Therefore we must send the barrier_ack after the barrier request was
* completed. */
- switch (connection->write_ordering) {
+ switch (connection->resource->write_ordering) {
case WO_none:
if (rv == FE_RECYCLED)
return 0;
@@ -1498,7 +1558,8 @@ static int receive_Barrier(struct drbd_connection *connection, struct packet_inf
return 0;
default:
- drbd_err(connection, "Strangeness in connection->write_ordering %d\n", connection->write_ordering);
+ drbd_err(connection, "Strangeness in connection->write_ordering %d\n",
+ connection->resource->write_ordering);
return -EIO;
}
@@ -1531,7 +1592,7 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
struct drbd_peer_request *peer_req;
struct page *page;
int dgs, ds, err;
- int data_size = pi->size;
+ unsigned int data_size = pi->size;
void *dig_in = peer_device->connection->int_dig_in;
void *dig_vv = peer_device->connection->int_dig_vv;
unsigned long *data;
@@ -1578,6 +1639,7 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
if (!peer_req)
return NULL;
+ peer_req->flags |= EE_WRITE;
if (trim)
return peer_req;
@@ -1734,9 +1796,10 @@ static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
* respective _drbd_clear_done_ee */
peer_req->w.cb = e_end_resync_block;
+ peer_req->submit_jif = jiffies;
spin_lock_irq(&device->resource->req_lock);
- list_add(&peer_req->w.list, &device->sync_ee);
+ list_add_tail(&peer_req->w.list, &device->sync_ee);
spin_unlock_irq(&device->resource->req_lock);
atomic_add(pi->size >> 9, &device->rs_sect_ev);
@@ -1889,6 +1952,7 @@ static int e_end_block(struct drbd_work *w, int cancel)
}
dec_unacked(device);
}
+
/* we delete from the conflict detection hash _after_ we sent out the
* P_WRITE_ACK / P_NEG_ACK, to get the sequence number right. */
if (peer_req->flags & EE_IN_INTERVAL_TREE) {
@@ -2115,6 +2179,8 @@ static int handle_write_conflicts(struct drbd_device *device,
drbd_for_each_overlap(i, &device->write_requests, sector, size) {
if (i == &peer_req->i)
continue;
+ if (i->completed)
+ continue;
if (!i->local) {
/*
@@ -2147,7 +2213,6 @@ static int handle_write_conflicts(struct drbd_device *device,
(unsigned long long)sector, size,
superseded ? "local" : "remote");
- inc_unacked(device);
peer_req->w.cb = superseded ? e_send_superseded :
e_send_retry_write;
list_add_tail(&peer_req->w.list, &device->done_ee);
@@ -2206,6 +2271,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
{
struct drbd_peer_device *peer_device;
struct drbd_device *device;
+ struct net_conf *nc;
sector_t sector;
struct drbd_peer_request *peer_req;
struct p_data *p = pi->data;
@@ -2245,6 +2311,8 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
}
peer_req->w.cb = e_end_block;
+ peer_req->submit_jif = jiffies;
+ peer_req->flags |= EE_APPLICATION;
dp_flags = be32_to_cpu(p->dp_flags);
rw |= wire_flags_to_bio(dp_flags);
@@ -2271,9 +2339,36 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
spin_unlock(&connection->epoch_lock);
rcu_read_lock();
- tp = rcu_dereference(peer_device->connection->net_conf)->two_primaries;
+ nc = rcu_dereference(peer_device->connection->net_conf);
+ tp = nc->two_primaries;
+ if (peer_device->connection->agreed_pro_version < 100) {
+ switch (nc->wire_protocol) {
+ case DRBD_PROT_C:
+ dp_flags |= DP_SEND_WRITE_ACK;
+ break;
+ case DRBD_PROT_B:
+ dp_flags |= DP_SEND_RECEIVE_ACK;
+ break;
+ }
+ }
rcu_read_unlock();
+
+ if (dp_flags & DP_SEND_WRITE_ACK) {
+ peer_req->flags |= EE_SEND_WRITE_ACK;
+ inc_unacked(device);
+ /* corresponding dec_unacked() in e_end_block()
+ * respective _drbd_clear_done_ee */
+ }
+
+ if (dp_flags & DP_SEND_RECEIVE_ACK) {
+ /* I really don't like it that the receiver thread
+ * sends on the msock, but anyways */
+ drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
+ }
+
if (tp) {
+ /* two primaries implies protocol C */
+ D_ASSERT(device, dp_flags & DP_SEND_WRITE_ACK);
peer_req->flags |= EE_IN_INTERVAL_TREE;
err = wait_for_and_update_peer_seq(peer_device, peer_seq);
if (err)
@@ -2297,44 +2392,18 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
* active_ee to become empty in drbd_submit_peer_request();
* better not add ourselves here. */
if ((peer_req->flags & EE_IS_TRIM_USE_ZEROOUT) == 0)
- list_add(&peer_req->w.list, &device->active_ee);
+ list_add_tail(&peer_req->w.list, &device->active_ee);
spin_unlock_irq(&device->resource->req_lock);
if (device->state.conn == C_SYNC_TARGET)
wait_event(device->ee_wait, !overlapping_resync_write(device, peer_req));
- if (peer_device->connection->agreed_pro_version < 100) {
- rcu_read_lock();
- switch (rcu_dereference(peer_device->connection->net_conf)->wire_protocol) {
- case DRBD_PROT_C:
- dp_flags |= DP_SEND_WRITE_ACK;
- break;
- case DRBD_PROT_B:
- dp_flags |= DP_SEND_RECEIVE_ACK;
- break;
- }
- rcu_read_unlock();
- }
-
- if (dp_flags & DP_SEND_WRITE_ACK) {
- peer_req->flags |= EE_SEND_WRITE_ACK;
- inc_unacked(device);
- /* corresponding dec_unacked() in e_end_block()
- * respective _drbd_clear_done_ee */
- }
-
- if (dp_flags & DP_SEND_RECEIVE_ACK) {
- /* I really don't like it that the receiver thread
- * sends on the msock, but anyways */
- drbd_send_ack(first_peer_device(device), P_RECV_ACK, peer_req);
- }
-
if (device->state.pdsk < D_INCONSISTENT) {
/* In case we have the only disk of the cluster, */
drbd_set_out_of_sync(device, peer_req->i.sector, peer_req->i.size);
- peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
peer_req->flags &= ~EE_MAY_SET_IN_SYNC;
- drbd_al_begin_io(device, &peer_req->i, true);
+ drbd_al_begin_io(device, &peer_req->i);
+ peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
}
err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR);
@@ -2347,8 +2416,10 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
list_del(&peer_req->w.list);
drbd_remove_epoch_entry_interval(device, peer_req);
spin_unlock_irq(&device->resource->req_lock);
- if (peer_req->flags & EE_CALL_AL_COMPLETE_IO)
+ if (peer_req->flags & EE_CALL_AL_COMPLETE_IO) {
+ peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
drbd_al_complete_io(device, &peer_req->i);
+ }
out_interrupted:
drbd_may_finish_epoch(connection, peer_req->epoch, EV_PUT + EV_CLEANUP);
@@ -2368,13 +2439,14 @@ out_interrupted:
* The current sync rate used here uses only the most recent two step marks,
* to have a short time average so we can react faster.
*/
-bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector)
+bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
+ bool throttle_if_app_is_waiting)
{
struct lc_element *tmp;
- bool throttle = true;
+ bool throttle = drbd_rs_c_min_rate_throttle(device);
- if (!drbd_rs_c_min_rate_throttle(device))
- return false;
+ if (!throttle || throttle_if_app_is_waiting)
+ return throttle;
spin_lock_irq(&device->al_lock);
tmp = lc_find(device->resync, BM_SECT_TO_EXT(sector));
@@ -2382,7 +2454,8 @@ bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector)
struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce);
if (test_bit(BME_PRIORITY, &bm_ext->flags))
throttle = false;
- /* Do not slow down if app IO is already waiting for this extent */
+ /* Do not slow down if app IO is already waiting for this extent,
+ * and our progress is necessary for application IO to complete. */
}
spin_unlock_irq(&device->al_lock);
@@ -2407,7 +2480,9 @@ bool drbd_rs_c_min_rate_throttle(struct drbd_device *device)
curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
(int)part_stat_read(&disk->part0, sectors[1]) -
atomic_read(&device->rs_sect_ev);
- if (!device->rs_last_events || curr_events - device->rs_last_events > 64) {
+
+ if (atomic_read(&device->ap_actlog_cnt)
+ || !device->rs_last_events || curr_events - device->rs_last_events > 64) {
unsigned long rs_left;
int i;
@@ -2508,6 +2583,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
peer_req->w.cb = w_e_end_data_req;
fault_type = DRBD_FAULT_DT_RD;
/* application IO, don't drbd_rs_begin_io */
+ peer_req->flags |= EE_APPLICATION;
goto submit;
case P_RS_DATA_REQUEST:
@@ -2538,6 +2614,8 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
peer_req->w.cb = w_e_end_csum_rs_req;
/* used in the sector offset progress display */
device->bm_resync_fo = BM_SECT_TO_BIT(sector);
+ /* remember to report stats in drbd_resync_finished */
+ device->use_csums = true;
} else if (pi->cmd == P_OV_REPLY) {
/* track progress, we may need to throttle */
atomic_add(size >> 9, &device->rs_sect_in);
@@ -2595,8 +2673,20 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
* we would also throttle its application reads.
* In that case, throttling is done on the SyncTarget only.
*/
- if (device->state.peer != R_PRIMARY && drbd_rs_should_slow_down(device, sector))
+
+ /* Even though this may be a resync request, we do add to "read_ee";
+ * "sync_ee" is only used for resync WRITEs.
+ * Add to list early, so debugfs can find this request
+ * even if we have to sleep below. */
+ spin_lock_irq(&device->resource->req_lock);
+ list_add_tail(&peer_req->w.list, &device->read_ee);
+ spin_unlock_irq(&device->resource->req_lock);
+
+ update_receiver_timing_details(connection, drbd_rs_should_slow_down);
+ if (device->state.peer != R_PRIMARY
+ && drbd_rs_should_slow_down(device, sector, false))
schedule_timeout_uninterruptible(HZ/10);
+ update_receiver_timing_details(connection, drbd_rs_begin_io);
if (drbd_rs_begin_io(device, sector))
goto out_free_e;
@@ -2604,22 +2694,20 @@ submit_for_resync:
atomic_add(size >> 9, &device->rs_sect_ev);
submit:
+ update_receiver_timing_details(connection, drbd_submit_peer_request);
inc_unacked(device);
- spin_lock_irq(&device->resource->req_lock);
- list_add_tail(&peer_req->w.list, &device->read_ee);
- spin_unlock_irq(&device->resource->req_lock);
-
if (drbd_submit_peer_request(device, peer_req, READ, fault_type) == 0)
return 0;
/* don't care for the reason here */
drbd_err(device, "submit failed, triggering re-connect\n");
+
+out_free_e:
spin_lock_irq(&device->resource->req_lock);
list_del(&peer_req->w.list);
spin_unlock_irq(&device->resource->req_lock);
/* no drbd_rs_complete_io(), we are dropping the connection anyways */
-out_free_e:
put_ldev(device);
drbd_free_peer_req(device, peer_req);
return -EIO;
@@ -2842,8 +2930,10 @@ static void drbd_uuid_dump(struct drbd_device *device, char *text, u64 *uuid,
-1091 requires proto 91
-1096 requires proto 96
*/
-static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_hold(local)
+static int drbd_uuid_compare(struct drbd_device *const device, int *rule_nr) __must_hold(local)
{
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
u64 self, peer;
int i, j;
@@ -2869,7 +2959,7 @@ static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_ho
if (device->p_uuid[UI_BITMAP] == (u64)0 && device->ldev->md.uuid[UI_BITMAP] != (u64)0) {
- if (first_peer_device(device)->connection->agreed_pro_version < 91)
+ if (connection->agreed_pro_version < 91)
return -1091;
if ((device->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (device->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
@@ -2892,7 +2982,7 @@ static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_ho
if (device->ldev->md.uuid[UI_BITMAP] == (u64)0 && device->p_uuid[UI_BITMAP] != (u64)0) {
- if (first_peer_device(device)->connection->agreed_pro_version < 91)
+ if (connection->agreed_pro_version < 91)
return -1091;
if ((device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (device->p_uuid[UI_BITMAP] & ~((u64)1)) &&
@@ -2925,7 +3015,7 @@ static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_ho
case 1: /* self_pri && !peer_pri */ return 1;
case 2: /* !self_pri && peer_pri */ return -1;
case 3: /* self_pri && peer_pri */
- dc = test_bit(RESOLVE_CONFLICTS, &first_peer_device(device)->connection->flags);
+ dc = test_bit(RESOLVE_CONFLICTS, &connection->flags);
return dc ? -1 : 1;
}
}
@@ -2938,14 +3028,14 @@ static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_ho
*rule_nr = 51;
peer = device->p_uuid[UI_HISTORY_START] & ~((u64)1);
if (self == peer) {
- if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+ if (connection->agreed_pro_version < 96 ?
(device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
(device->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
peer + UUID_NEW_BM_OFFSET == (device->p_uuid[UI_BITMAP] & ~((u64)1))) {
/* The last P_SYNC_UUID did not get though. Undo the last start of
resync as sync source modifications of the peer's UUIDs. */
- if (first_peer_device(device)->connection->agreed_pro_version < 91)
+ if (connection->agreed_pro_version < 91)
return -1091;
device->p_uuid[UI_BITMAP] = device->p_uuid[UI_HISTORY_START];
@@ -2975,14 +3065,14 @@ static int drbd_uuid_compare(struct drbd_device *device, int *rule_nr) __must_ho
*rule_nr = 71;
self = device->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
if (self == peer) {
- if (first_peer_device(device)->connection->agreed_pro_version < 96 ?
+ if (connection->agreed_pro_version < 96 ?
(device->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
(device->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
self + UUID_NEW_BM_OFFSET == (device->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
/* The last P_SYNC_UUID did not get though. Undo the last start of
resync as sync source modifications of our UUIDs. */
- if (first_peer_device(device)->connection->agreed_pro_version < 91)
+ if (connection->agreed_pro_version < 91)
return -1091;
__drbd_uuid_set(device, UI_BITMAP, device->ldev->md.uuid[UI_HISTORY_START]);
@@ -3352,8 +3442,7 @@ disconnect:
* return: NULL (alg name was "")
* ERR_PTR(error) if something goes wrong
* or the crypto hash ptr, if it worked out ok. */
-static
-struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device,
+static struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device,
const char *alg, const char *name)
{
struct crypto_hash *tfm;
@@ -3639,7 +3728,7 @@ static int receive_sizes(struct drbd_connection *connection, struct packet_info
struct drbd_device *device;
struct p_sizes *p = pi->data;
enum determine_dev_size dd = DS_UNCHANGED;
- sector_t p_size, p_usize, my_usize;
+ sector_t p_size, p_usize, p_csize, my_usize;
int ldsc = 0; /* local disk size changed */
enum dds_flags ddsf;
@@ -3650,6 +3739,7 @@ static int receive_sizes(struct drbd_connection *connection, struct packet_info
p_size = be64_to_cpu(p->d_size);
p_usize = be64_to_cpu(p->u_size);
+ p_csize = be64_to_cpu(p->c_size);
/* just store the peer's disk size for now.
* we still need to figure out whether we accept that. */
@@ -3710,7 +3800,6 @@ static int receive_sizes(struct drbd_connection *connection, struct packet_info
}
device->peer_max_bio_size = be32_to_cpu(p->max_bio_size);
- drbd_reconsider_max_bio_size(device);
/* Leave drbd_reconsider_max_bio_size() before drbd_determine_dev_size().
In case we cleared the QUEUE_FLAG_DISCARD from our queue in
drbd_reconsider_max_bio_size(), we can be sure that after
@@ -3718,14 +3807,28 @@ static int receive_sizes(struct drbd_connection *connection, struct packet_info
ddsf = be16_to_cpu(p->dds_flags);
if (get_ldev(device)) {
+ drbd_reconsider_max_bio_size(device, device->ldev);
dd = drbd_determine_dev_size(device, ddsf, NULL);
put_ldev(device);
if (dd == DS_ERROR)
return -EIO;
drbd_md_sync(device);
} else {
- /* I am diskless, need to accept the peer's size. */
- drbd_set_my_capacity(device, p_size);
+ /*
+ * I am diskless, need to accept the peer's *current* size.
+ * I must NOT accept the peers backing disk size,
+ * it may have been larger than mine all along...
+ *
+ * At this point, the peer knows more about my disk, or at
+ * least about what we last agreed upon, than myself.
+ * So if his c_size is less than his d_size, the most likely
+ * reason is that *my* d_size was smaller last time we checked.
+ *
+ * However, if he sends a zero current size,
+ * take his (user-capped or) backing disk size anyways.
+ */
+ drbd_reconsider_max_bio_size(device, NULL);
+ drbd_set_my_capacity(device, p_csize ?: p_usize ?: p_size);
}
if (get_ldev(device)) {
@@ -4501,6 +4604,7 @@ static void drbdd(struct drbd_connection *connection)
struct data_cmd *cmd;
drbd_thread_current_set_cpu(&connection->receiver);
+ update_receiver_timing_details(connection, drbd_recv_header);
if (drbd_recv_header(connection, &pi))
goto err_out;
@@ -4519,12 +4623,14 @@ static void drbdd(struct drbd_connection *connection)
}
if (shs) {
+ update_receiver_timing_details(connection, drbd_recv_all_warn);
err = drbd_recv_all_warn(connection, pi.data, shs);
if (err)
goto err_out;
pi.size -= shs;
}
+ update_receiver_timing_details(connection, cmd->fn);
err = cmd->fn(connection, &pi);
if (err) {
drbd_err(connection, "error receiving %s, e: %d l: %d!\n",
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 09803d0d5207..c67717d572d1 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -52,7 +52,7 @@ static void _drbd_start_io_acct(struct drbd_device *device, struct drbd_request
static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req)
{
int rw = bio_data_dir(req->master_bio);
- unsigned long duration = jiffies - req->start_time;
+ unsigned long duration = jiffies - req->start_jif;
int cpu;
cpu = part_stat_lock();
part_stat_add(cpu, &device->vdisk->part0, ticks[rw], duration);
@@ -66,7 +66,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device,
{
struct drbd_request *req;
- req = mempool_alloc(drbd_request_mempool, GFP_NOIO);
+ req = mempool_alloc(drbd_request_mempool, GFP_NOIO | __GFP_ZERO);
if (!req)
return NULL;
@@ -84,6 +84,8 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device,
INIT_LIST_HEAD(&req->tl_requests);
INIT_LIST_HEAD(&req->w.list);
+ INIT_LIST_HEAD(&req->req_pending_master_completion);
+ INIT_LIST_HEAD(&req->req_pending_local);
/* one reference to be put by __drbd_make_request */
atomic_set(&req->completion_ref, 1);
@@ -92,6 +94,19 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device,
return req;
}
+static void drbd_remove_request_interval(struct rb_root *root,
+ struct drbd_request *req)
+{
+ struct drbd_device *device = req->device;
+ struct drbd_interval *i = &req->i;
+
+ drbd_remove_interval(root, i);
+
+ /* Wake up any processes waiting for this request to complete. */
+ if (i->waiting)
+ wake_up(&device->misc_wait);
+}
+
void drbd_req_destroy(struct kref *kref)
{
struct drbd_request *req = container_of(kref, struct drbd_request, kref);
@@ -107,14 +122,30 @@ void drbd_req_destroy(struct kref *kref)
return;
}
- /* remove it from the transfer log.
- * well, only if it had been there in the first
- * place... if it had not (local only or conflicting
- * and never sent), it should still be "empty" as
- * initialized in drbd_req_new(), so we can list_del() it
- * here unconditionally */
+ /* If called from mod_rq_state (expected normal case) or
+ * drbd_send_and_submit (the less likely normal path), this holds the
+ * req_lock, and req->tl_requests will typicaly be on ->transfer_log,
+ * though it may be still empty (never added to the transfer log).
+ *
+ * If called from do_retry(), we do NOT hold the req_lock, but we are
+ * still allowed to unconditionally list_del(&req->tl_requests),
+ * because it will be on a local on-stack list only. */
list_del_init(&req->tl_requests);
+ /* finally remove the request from the conflict detection
+ * respective block_id verification interval tree. */
+ if (!drbd_interval_empty(&req->i)) {
+ struct rb_root *root;
+
+ if (s & RQ_WRITE)
+ root = &device->write_requests;
+ else
+ root = &device->read_requests;
+ drbd_remove_request_interval(root, req);
+ } else if (s & (RQ_NET_MASK & ~RQ_NET_DONE) && req->i.size != 0)
+ drbd_err(device, "drbd_req_destroy: Logic BUG: interval empty, but: rq_state=0x%x, sect=%llu, size=%u\n",
+ s, (unsigned long long)req->i.sector, req->i.size);
+
/* if it was a write, we may have to set the corresponding
* bit(s) out-of-sync first. If it had a local part, we need to
* release the reference to the activity log. */
@@ -188,19 +219,6 @@ void complete_master_bio(struct drbd_device *device,
}
-static void drbd_remove_request_interval(struct rb_root *root,
- struct drbd_request *req)
-{
- struct drbd_device *device = req->device;
- struct drbd_interval *i = &req->i;
-
- drbd_remove_interval(root, i);
-
- /* Wake up any processes waiting for this request to complete. */
- if (i->waiting)
- wake_up(&device->misc_wait);
-}
-
/* Helper for __req_mod().
* Set m->bio to the master bio, if it is fit to be completed,
* or leave it alone (it is initialized to NULL in __req_mod),
@@ -254,18 +272,6 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
ok = (s & RQ_LOCAL_OK) || (s & RQ_NET_OK);
error = PTR_ERR(req->private_bio);
- /* remove the request from the conflict detection
- * respective block_id verification hash */
- if (!drbd_interval_empty(&req->i)) {
- struct rb_root *root;
-
- if (rw == WRITE)
- root = &device->write_requests;
- else
- root = &device->read_requests;
- drbd_remove_request_interval(root, req);
- }
-
/* Before we can signal completion to the upper layers,
* we may need to close the current transfer log epoch.
* We are within the request lock, so we can simply compare
@@ -301,9 +307,24 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
m->error = ok ? 0 : (error ?: -EIO);
m->bio = req->master_bio;
req->master_bio = NULL;
+ /* We leave it in the tree, to be able to verify later
+ * write-acks in protocol != C during resync.
+ * But we mark it as "complete", so it won't be counted as
+ * conflict in a multi-primary setup. */
+ req->i.completed = true;
}
+
+ if (req->i.waiting)
+ wake_up(&device->misc_wait);
+
+ /* Either we are about to complete to upper layers,
+ * or we will restart this request.
+ * In either case, the request object will be destroyed soon,
+ * so better remove it from all lists. */
+ list_del_init(&req->req_pending_master_completion);
}
+/* still holds resource->req_lock */
static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
{
struct drbd_device *device = req->device;
@@ -324,12 +345,91 @@ static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_
return 1;
}
+static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_next == NULL)
+ connection->req_next = req;
+}
+
+static void advance_conn_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_next != req)
+ return;
+ list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+ const unsigned s = req->rq_state;
+ if (s & RQ_NET_QUEUED)
+ break;
+ }
+ if (&req->tl_requests == &connection->transfer_log)
+ req = NULL;
+ connection->req_next = req;
+}
+
+static void set_if_null_req_ack_pending(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_ack_pending == NULL)
+ connection->req_ack_pending = req;
+}
+
+static void advance_conn_req_ack_pending(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_ack_pending != req)
+ return;
+ list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+ const unsigned s = req->rq_state;
+ if ((s & RQ_NET_SENT) && (s & RQ_NET_PENDING))
+ break;
+ }
+ if (&req->tl_requests == &connection->transfer_log)
+ req = NULL;
+ connection->req_ack_pending = req;
+}
+
+static void set_if_null_req_not_net_done(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_not_net_done == NULL)
+ connection->req_not_net_done = req;
+}
+
+static void advance_conn_req_not_net_done(struct drbd_peer_device *peer_device, struct drbd_request *req)
+{
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
+ if (!connection)
+ return;
+ if (connection->req_not_net_done != req)
+ return;
+ list_for_each_entry_continue(req, &connection->transfer_log, tl_requests) {
+ const unsigned s = req->rq_state;
+ if ((s & RQ_NET_SENT) && !(s & RQ_NET_DONE))
+ break;
+ }
+ if (&req->tl_requests == &connection->transfer_log)
+ req = NULL;
+ connection->req_not_net_done = req;
+}
+
/* I'd like this to be the only place that manipulates
* req->completion_ref and req->kref. */
static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
int clear, int set)
{
struct drbd_device *device = req->device;
+ struct drbd_peer_device *peer_device = first_peer_device(device);
unsigned s = req->rq_state;
int c_put = 0;
int k_put = 0;
@@ -356,14 +456,23 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
atomic_inc(&req->completion_ref);
}
- if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED))
+ if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED)) {
atomic_inc(&req->completion_ref);
+ set_if_null_req_next(peer_device, req);
+ }
if (!(s & RQ_EXP_BARR_ACK) && (set & RQ_EXP_BARR_ACK))
kref_get(&req->kref); /* wait for the DONE */
- if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT))
- atomic_add(req->i.size >> 9, &device->ap_in_flight);
+ if (!(s & RQ_NET_SENT) && (set & RQ_NET_SENT)) {
+ /* potentially already completed in the asender thread */
+ if (!(s & RQ_NET_DONE)) {
+ atomic_add(req->i.size >> 9, &device->ap_in_flight);
+ set_if_null_req_not_net_done(peer_device, req);
+ }
+ if (s & RQ_NET_PENDING)
+ set_if_null_req_ack_pending(peer_device, req);
+ }
if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
atomic_inc(&req->completion_ref);
@@ -386,20 +495,34 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
++k_put;
else
++c_put;
+ list_del_init(&req->req_pending_local);
}
if ((s & RQ_NET_PENDING) && (clear & RQ_NET_PENDING)) {
dec_ap_pending(device);
++c_put;
+ req->acked_jif = jiffies;
+ advance_conn_req_ack_pending(peer_device, req);
}
- if ((s & RQ_NET_QUEUED) && (clear & RQ_NET_QUEUED))
+ if ((s & RQ_NET_QUEUED) && (clear & RQ_NET_QUEUED)) {
++c_put;
+ advance_conn_req_next(peer_device, req);
+ }
- if ((s & RQ_EXP_BARR_ACK) && !(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
- if (req->rq_state & RQ_NET_SENT)
+ if (!(s & RQ_NET_DONE) && (set & RQ_NET_DONE)) {
+ if (s & RQ_NET_SENT)
atomic_sub(req->i.size >> 9, &device->ap_in_flight);
- ++k_put;
+ if (s & RQ_EXP_BARR_ACK)
+ ++k_put;
+ req->net_done_jif = jiffies;
+
+ /* in ahead/behind mode, or just in case,
+ * before we finally destroy this request,
+ * the caching pointers must not reference it anymore */
+ advance_conn_req_next(peer_device, req);
+ advance_conn_req_ack_pending(peer_device, req);
+ advance_conn_req_not_net_done(peer_device, req);
}
/* potentially complete and destroy */
@@ -439,6 +562,19 @@ static void drbd_report_io_error(struct drbd_device *device, struct drbd_request
bdevname(device->ldev->backing_bdev, b));
}
+/* Helper for HANDED_OVER_TO_NETWORK.
+ * Is this a protocol A write (neither WRITE_ACK nor RECEIVE_ACK expected)?
+ * Is it also still "PENDING"?
+ * --> If so, clear PENDING and set NET_OK below.
+ * If it is a protocol A write, but not RQ_PENDING anymore, neg-ack was faster
+ * (and we must not set RQ_NET_OK) */
+static inline bool is_pending_write_protocol_A(struct drbd_request *req)
+{
+ return (req->rq_state &
+ (RQ_WRITE|RQ_NET_PENDING|RQ_EXP_WRITE_ACK|RQ_EXP_RECEIVE_ACK))
+ == (RQ_WRITE|RQ_NET_PENDING);
+}
+
/* obviously this could be coded as many single functions
* instead of one huge switch,
* or by putting the code directly in the respective locations
@@ -454,7 +590,9 @@ static void drbd_report_io_error(struct drbd_device *device, struct drbd_request
int __req_mod(struct drbd_request *req, enum drbd_req_event what,
struct bio_and_error *m)
{
- struct drbd_device *device = req->device;
+ struct drbd_device *const device = req->device;
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
struct net_conf *nc;
int p, rv = 0;
@@ -477,7 +615,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
* and from w_read_retry_remote */
D_ASSERT(device, !(req->rq_state & RQ_NET_MASK));
rcu_read_lock();
- nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+ nc = rcu_dereference(connection->net_conf);
p = nc->wire_protocol;
rcu_read_unlock();
req->rq_state |=
@@ -549,7 +687,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(device, (req->rq_state & RQ_LOCAL_MASK) == 0);
mod_rq_state(req, m, 0, RQ_NET_QUEUED);
req->w.cb = w_send_read_req;
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ drbd_queue_work(&connection->sender_work,
&req->w);
break;
@@ -585,23 +723,23 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
mod_rq_state(req, m, 0, RQ_NET_QUEUED|RQ_EXP_BARR_ACK);
req->w.cb = w_send_dblock;
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ drbd_queue_work(&connection->sender_work,
&req->w);
/* close the epoch, in case it outgrew the limit */
rcu_read_lock();
- nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+ nc = rcu_dereference(connection->net_conf);
p = nc->max_epoch_size;
rcu_read_unlock();
- if (first_peer_device(device)->connection->current_tle_writes >= p)
- start_new_tl_epoch(first_peer_device(device)->connection);
+ if (connection->current_tle_writes >= p)
+ start_new_tl_epoch(connection);
break;
case QUEUE_FOR_SEND_OOS:
mod_rq_state(req, m, 0, RQ_NET_QUEUED);
req->w.cb = w_send_out_of_sync;
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ drbd_queue_work(&connection->sender_work,
&req->w);
break;
@@ -615,18 +753,16 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
case HANDED_OVER_TO_NETWORK:
/* assert something? */
- if (bio_data_dir(req->master_bio) == WRITE &&
- !(req->rq_state & (RQ_EXP_RECEIVE_ACK | RQ_EXP_WRITE_ACK))) {
+ if (is_pending_write_protocol_A(req))
/* this is what is dangerous about protocol A:
* pretend it was successfully written on the peer. */
- if (req->rq_state & RQ_NET_PENDING)
- mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
- /* else: neg-ack was faster... */
- /* it is still not yet RQ_NET_DONE until the
- * corresponding epoch barrier got acked as well,
- * so we know what to dirty on connection loss */
- }
- mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_SENT);
+ mod_rq_state(req, m, RQ_NET_QUEUED|RQ_NET_PENDING,
+ RQ_NET_SENT|RQ_NET_OK);
+ else
+ mod_rq_state(req, m, RQ_NET_QUEUED, RQ_NET_SENT);
+ /* It is still not yet RQ_NET_DONE until the
+ * corresponding epoch barrier got acked as well,
+ * so we know what to dirty on connection loss. */
break;
case OOS_HANDED_TO_NETWORK:
@@ -658,12 +794,13 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
case WRITE_ACKED_BY_PEER_AND_SIS:
req->rq_state |= RQ_NET_SIS;
case WRITE_ACKED_BY_PEER:
- D_ASSERT(device, req->rq_state & RQ_EXP_WRITE_ACK);
- /* protocol C; successfully written on peer.
+ /* Normal operation protocol C: successfully written on peer.
+ * During resync, even in protocol != C,
+ * we requested an explicit write ack anyways.
+ * Which means we cannot even assert anything here.
* Nothing more to do here.
* We want to keep the tl in place for all protocols, to cater
* for volatile write-back caches on lower level devices. */
-
goto ack_common;
case RECV_ACKED_BY_PEER:
D_ASSERT(device, req->rq_state & RQ_EXP_RECEIVE_ACK);
@@ -671,7 +808,6 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
* see also notes above in HANDED_OVER_TO_NETWORK about
* protocol != C */
ack_common:
- D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
mod_rq_state(req, m, RQ_NET_PENDING, RQ_NET_OK);
break;
@@ -714,7 +850,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
get_ldev(device); /* always succeeds in this call path */
req->w.cb = w_restart_disk_io;
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ drbd_queue_work(&connection->sender_work,
&req->w);
break;
@@ -736,7 +872,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
mod_rq_state(req, m, RQ_COMPLETION_SUSP, RQ_NET_QUEUED|RQ_NET_PENDING);
if (req->w.cb) {
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ /* w.cb expected to be w_send_dblock, or w_send_read_req */
+ drbd_queue_work(&connection->sender_work,
&req->w);
rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
} /* else: FIXME can this happen? */
@@ -769,7 +906,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
break;
case QUEUE_AS_DRBD_BARRIER:
- start_new_tl_epoch(first_peer_device(device)->connection);
+ start_new_tl_epoch(connection);
mod_rq_state(req, m, 0, RQ_NET_OK|RQ_NET_DONE);
break;
};
@@ -886,6 +1023,9 @@ static void maybe_pull_ahead(struct drbd_device *device)
connection->agreed_pro_version < 96)
return;
+ if (on_congestion == OC_PULL_AHEAD && device->state.conn == C_AHEAD)
+ return; /* nothing to do ... */
+
/* If I don't even have good local storage, we can not reasonably try
* to pull ahead of the peer. We also need the local reference to make
* sure device->act_log is there.
@@ -1021,6 +1161,7 @@ drbd_submit_req_private_bio(struct drbd_request *req)
* stable storage, and this is a WRITE, we may not even submit
* this bio. */
if (get_ldev(device)) {
+ req->pre_submit_jif = jiffies;
if (drbd_insert_fault(device,
rw == WRITE ? DRBD_FAULT_DT_WR
: rw == READ ? DRBD_FAULT_DT_RD
@@ -1035,10 +1176,14 @@ drbd_submit_req_private_bio(struct drbd_request *req)
static void drbd_queue_write(struct drbd_device *device, struct drbd_request *req)
{
- spin_lock(&device->submit.lock);
+ spin_lock_irq(&device->resource->req_lock);
list_add_tail(&req->tl_requests, &device->submit.writes);
- spin_unlock(&device->submit.lock);
+ list_add_tail(&req->req_pending_master_completion,
+ &device->pending_master_completion[1 /* WRITE */]);
+ spin_unlock_irq(&device->resource->req_lock);
queue_work(device->submit.wq, &device->submit.worker);
+ /* do_submit() may sleep internally on al_wait, too */
+ wake_up(&device->al_wait);
}
/* returns the new drbd_request pointer, if the caller is expected to
@@ -1047,7 +1192,7 @@ static void drbd_queue_write(struct drbd_device *device, struct drbd_request *re
* Returns ERR_PTR(-ENOMEM) if we cannot allocate a drbd_request.
*/
static struct drbd_request *
-drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long start_time)
+drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long start_jif)
{
const int rw = bio_data_dir(bio);
struct drbd_request *req;
@@ -1062,7 +1207,7 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
bio_endio(bio, -ENOMEM);
return ERR_PTR(-ENOMEM);
}
- req->start_time = start_time;
+ req->start_jif = start_jif;
if (!get_ldev(device)) {
bio_put(req->private_bio);
@@ -1075,10 +1220,12 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
if (rw == WRITE && req->private_bio && req->i.size
&& !test_bit(AL_SUSPENDED, &device->flags)) {
if (!drbd_al_begin_io_fastpath(device, &req->i)) {
+ atomic_inc(&device->ap_actlog_cnt);
drbd_queue_write(device, req);
return NULL;
}
req->rq_state |= RQ_IN_ACT_LOG;
+ req->in_actlog_jif = jiffies;
}
return req;
@@ -1086,11 +1233,13 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req)
{
+ struct drbd_resource *resource = device->resource;
const int rw = bio_rw(req->master_bio);
struct bio_and_error m = { NULL, };
bool no_remote = false;
+ bool submit_private_bio = false;
- spin_lock_irq(&device->resource->req_lock);
+ spin_lock_irq(&resource->req_lock);
if (rw == WRITE) {
/* This may temporarily give up the req_lock,
* but will re-aquire it before it returns here.
@@ -1148,13 +1297,18 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request
no_remote = true;
}
+ /* If it took the fast path in drbd_request_prepare, add it here.
+ * The slow path has added it already. */
+ if (list_empty(&req->req_pending_master_completion))
+ list_add_tail(&req->req_pending_master_completion,
+ &device->pending_master_completion[rw == WRITE]);
if (req->private_bio) {
/* needs to be marked within the same spinlock */
+ list_add_tail(&req->req_pending_local,
+ &device->pending_completion[rw == WRITE]);
_req_mod(req, TO_BE_SUBMITTED);
/* but we need to give up the spinlock to submit */
- spin_unlock_irq(&device->resource->req_lock);
- drbd_submit_req_private_bio(req);
- spin_lock_irq(&device->resource->req_lock);
+ submit_private_bio = true;
} else if (no_remote) {
nodata:
if (__ratelimit(&drbd_ratelimit_state))
@@ -1167,15 +1321,23 @@ nodata:
out:
if (drbd_req_put_completion_ref(req, &m, 1))
kref_put(&req->kref, drbd_req_destroy);
- spin_unlock_irq(&device->resource->req_lock);
-
+ spin_unlock_irq(&resource->req_lock);
+
+ /* Even though above is a kref_put(), this is safe.
+ * As long as we still need to submit our private bio,
+ * we hold a completion ref, and the request cannot disappear.
+ * If however this request did not even have a private bio to submit
+ * (e.g. remote read), req may already be invalid now.
+ * That's why we cannot check on req->private_bio. */
+ if (submit_private_bio)
+ drbd_submit_req_private_bio(req);
if (m.bio)
complete_master_bio(device, &m);
}
-void __drbd_make_request(struct drbd_device *device, struct bio *bio, unsigned long start_time)
+void __drbd_make_request(struct drbd_device *device, struct bio *bio, unsigned long start_jif)
{
- struct drbd_request *req = drbd_request_prepare(device, bio, start_time);
+ struct drbd_request *req = drbd_request_prepare(device, bio, start_jif);
if (IS_ERR_OR_NULL(req))
return;
drbd_send_and_submit(device, req);
@@ -1194,6 +1356,8 @@ static void submit_fast_path(struct drbd_device *device, struct list_head *incom
continue;
req->rq_state |= RQ_IN_ACT_LOG;
+ req->in_actlog_jif = jiffies;
+ atomic_dec(&device->ap_actlog_cnt);
}
list_del_init(&req->tl_requests);
@@ -1203,7 +1367,8 @@ static void submit_fast_path(struct drbd_device *device, struct list_head *incom
static bool prepare_al_transaction_nonblock(struct drbd_device *device,
struct list_head *incoming,
- struct list_head *pending)
+ struct list_head *pending,
+ struct list_head *later)
{
struct drbd_request *req, *tmp;
int wake = 0;
@@ -1212,45 +1377,105 @@ static bool prepare_al_transaction_nonblock(struct drbd_device *device,
spin_lock_irq(&device->al_lock);
list_for_each_entry_safe(req, tmp, incoming, tl_requests) {
err = drbd_al_begin_io_nonblock(device, &req->i);
+ if (err == -ENOBUFS)
+ break;
if (err == -EBUSY)
wake = 1;
if (err)
- continue;
- req->rq_state |= RQ_IN_ACT_LOG;
- list_move_tail(&req->tl_requests, pending);
+ list_move_tail(&req->tl_requests, later);
+ else
+ list_move_tail(&req->tl_requests, pending);
}
spin_unlock_irq(&device->al_lock);
if (wake)
wake_up(&device->al_wait);
-
return !list_empty(pending);
}
+void send_and_submit_pending(struct drbd_device *device, struct list_head *pending)
+{
+ struct drbd_request *req, *tmp;
+
+ list_for_each_entry_safe(req, tmp, pending, tl_requests) {
+ req->rq_state |= RQ_IN_ACT_LOG;
+ req->in_actlog_jif = jiffies;
+ atomic_dec(&device->ap_actlog_cnt);
+ list_del_init(&req->tl_requests);
+ drbd_send_and_submit(device, req);
+ }
+}
+
void do_submit(struct work_struct *ws)
{
struct drbd_device *device = container_of(ws, struct drbd_device, submit.worker);
- LIST_HEAD(incoming);
- LIST_HEAD(pending);
- struct drbd_request *req, *tmp;
+ LIST_HEAD(incoming); /* from drbd_make_request() */
+ LIST_HEAD(pending); /* to be submitted after next AL-transaction commit */
+ LIST_HEAD(busy); /* blocked by resync requests */
+
+ /* grab new incoming requests */
+ spin_lock_irq(&device->resource->req_lock);
+ list_splice_tail_init(&device->submit.writes, &incoming);
+ spin_unlock_irq(&device->resource->req_lock);
for (;;) {
- spin_lock(&device->submit.lock);
- list_splice_tail_init(&device->submit.writes, &incoming);
- spin_unlock(&device->submit.lock);
+ DEFINE_WAIT(wait);
+ /* move used-to-be-busy back to front of incoming */
+ list_splice_init(&busy, &incoming);
submit_fast_path(device, &incoming);
if (list_empty(&incoming))
break;
-skip_fast_path:
- wait_event(device->al_wait, prepare_al_transaction_nonblock(device, &incoming, &pending));
- /* Maybe more was queued, while we prepared the transaction?
- * Try to stuff them into this transaction as well.
- * Be strictly non-blocking here, no wait_event, we already
- * have something to commit.
- * Stop if we don't make any more progres.
- */
for (;;) {
+ prepare_to_wait(&device->al_wait, &wait, TASK_UNINTERRUPTIBLE);
+
+ list_splice_init(&busy, &incoming);
+ prepare_al_transaction_nonblock(device, &incoming, &pending, &busy);
+ if (!list_empty(&pending))
+ break;
+
+ schedule();
+
+ /* If all currently "hot" activity log extents are kept busy by
+ * incoming requests, we still must not totally starve new
+ * requests to "cold" extents.
+ * Something left on &incoming means there had not been
+ * enough update slots available, and the activity log
+ * has been marked as "starving".
+ *
+ * Try again now, without looking for new requests,
+ * effectively blocking all new requests until we made
+ * at least _some_ progress with what we currently have.
+ */
+ if (!list_empty(&incoming))
+ continue;
+
+ /* Nothing moved to pending, but nothing left
+ * on incoming: all moved to busy!
+ * Grab new and iterate. */
+ spin_lock_irq(&device->resource->req_lock);
+ list_splice_tail_init(&device->submit.writes, &incoming);
+ spin_unlock_irq(&device->resource->req_lock);
+ }
+ finish_wait(&device->al_wait, &wait);
+
+ /* If the transaction was full, before all incoming requests
+ * had been processed, skip ahead to commit, and iterate
+ * without splicing in more incoming requests from upper layers.
+ *
+ * Else, if all incoming have been processed,
+ * they have become either "pending" (to be submitted after
+ * next transaction commit) or "busy" (blocked by resync).
+ *
+ * Maybe more was queued, while we prepared the transaction?
+ * Try to stuff those into this transaction as well.
+ * Be strictly non-blocking here,
+ * we already have something to commit.
+ *
+ * Commit if we don't make any more progres.
+ */
+
+ while (list_empty(&incoming)) {
LIST_HEAD(more_pending);
LIST_HEAD(more_incoming);
bool made_progress;
@@ -1260,55 +1485,32 @@ skip_fast_path:
if (list_empty(&device->submit.writes))
break;
- spin_lock(&device->submit.lock);
+ spin_lock_irq(&device->resource->req_lock);
list_splice_tail_init(&device->submit.writes, &more_incoming);
- spin_unlock(&device->submit.lock);
+ spin_unlock_irq(&device->resource->req_lock);
if (list_empty(&more_incoming))
break;
- made_progress = prepare_al_transaction_nonblock(device, &more_incoming, &more_pending);
+ made_progress = prepare_al_transaction_nonblock(device, &more_incoming, &more_pending, &busy);
list_splice_tail_init(&more_pending, &pending);
list_splice_tail_init(&more_incoming, &incoming);
-
if (!made_progress)
break;
}
- drbd_al_begin_io_commit(device, false);
-
- list_for_each_entry_safe(req, tmp, &pending, tl_requests) {
- list_del_init(&req->tl_requests);
- drbd_send_and_submit(device, req);
- }
- /* If all currently hot activity log extents are kept busy by
- * incoming requests, we still must not totally starve new
- * requests to cold extents. In that case, prepare one request
- * in blocking mode. */
- list_for_each_entry_safe(req, tmp, &incoming, tl_requests) {
- list_del_init(&req->tl_requests);
- req->rq_state |= RQ_IN_ACT_LOG;
- if (!drbd_al_begin_io_prepare(device, &req->i)) {
- /* Corresponding extent was hot after all? */
- drbd_send_and_submit(device, req);
- } else {
- /* Found a request to a cold extent.
- * Put on "pending" list,
- * and try to cumulate with more. */
- list_add(&req->tl_requests, &pending);
- goto skip_fast_path;
- }
- }
+ drbd_al_begin_io_commit(device);
+ send_and_submit_pending(device, &pending);
}
}
void drbd_make_request(struct request_queue *q, struct bio *bio)
{
struct drbd_device *device = (struct drbd_device *) q->queuedata;
- unsigned long start_time;
+ unsigned long start_jif;
- start_time = jiffies;
+ start_jif = jiffies;
/*
* what we "blindly" assume:
@@ -1316,7 +1518,7 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
D_ASSERT(device, IS_ALIGNED(bio->bi_iter.bi_size, 512));
inc_ap_bio(device);
- __drbd_make_request(device, bio, start_time);
+ __drbd_make_request(device, bio, start_jif);
}
/* This is called by bio_add_page().
@@ -1353,36 +1555,13 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
return limit;
}
-static void find_oldest_requests(
- struct drbd_connection *connection,
- struct drbd_device *device,
- struct drbd_request **oldest_req_waiting_for_peer,
- struct drbd_request **oldest_req_waiting_for_disk)
-{
- struct drbd_request *r;
- *oldest_req_waiting_for_peer = NULL;
- *oldest_req_waiting_for_disk = NULL;
- list_for_each_entry(r, &connection->transfer_log, tl_requests) {
- const unsigned s = r->rq_state;
- if (!*oldest_req_waiting_for_peer
- && ((s & RQ_NET_MASK) && !(s & RQ_NET_DONE)))
- *oldest_req_waiting_for_peer = r;
-
- if (!*oldest_req_waiting_for_disk
- && (s & RQ_LOCAL_PENDING) && r->device == device)
- *oldest_req_waiting_for_disk = r;
-
- if (*oldest_req_waiting_for_peer && *oldest_req_waiting_for_disk)
- break;
- }
-}
-
void request_timer_fn(unsigned long data)
{
struct drbd_device *device = (struct drbd_device *) data;
struct drbd_connection *connection = first_peer_device(device)->connection;
- struct drbd_request *req_disk, *req_peer; /* oldest request */
+ struct drbd_request *req_read, *req_write, *req_peer; /* oldest request */
struct net_conf *nc;
+ unsigned long oldest_submit_jif;
unsigned long ent = 0, dt = 0, et, nt; /* effective timeout = ko_count * timeout */
unsigned long now;
@@ -1403,14 +1582,31 @@ void request_timer_fn(unsigned long data)
return; /* Recurring timer stopped */
now = jiffies;
+ nt = now + et;
spin_lock_irq(&device->resource->req_lock);
- find_oldest_requests(connection, device, &req_peer, &req_disk);
- if (req_peer == NULL && req_disk == NULL) {
- spin_unlock_irq(&device->resource->req_lock);
- mod_timer(&device->request_timer, now + et);
- return;
- }
+ req_read = list_first_entry_or_null(&device->pending_completion[0], struct drbd_request, req_pending_local);
+ req_write = list_first_entry_or_null(&device->pending_completion[1], struct drbd_request, req_pending_local);
+ req_peer = connection->req_not_net_done;
+ /* maybe the oldest request waiting for the peer is in fact still
+ * blocking in tcp sendmsg */
+ if (!req_peer && connection->req_next && connection->req_next->pre_send_jif)
+ req_peer = connection->req_next;
+
+ /* evaluate the oldest peer request only in one timer! */
+ if (req_peer && req_peer->device != device)
+ req_peer = NULL;
+
+ /* do we have something to evaluate? */
+ if (req_peer == NULL && req_write == NULL && req_read == NULL)
+ goto out;
+
+ oldest_submit_jif =
+ (req_write && req_read)
+ ? ( time_before(req_write->pre_submit_jif, req_read->pre_submit_jif)
+ ? req_write->pre_submit_jif : req_read->pre_submit_jif )
+ : req_write ? req_write->pre_submit_jif
+ : req_read ? req_read->pre_submit_jif : now;
/* The request is considered timed out, if
* - we have some effective timeout from the configuration,
@@ -1429,13 +1625,13 @@ void request_timer_fn(unsigned long data)
* to expire twice (worst case) to become effective. Good enough.
*/
if (ent && req_peer &&
- time_after(now, req_peer->start_time + ent) &&
+ time_after(now, req_peer->pre_send_jif + ent) &&
!time_in_range(now, connection->last_reconnect_jif, connection->last_reconnect_jif + ent)) {
drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
_drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
}
- if (dt && req_disk &&
- time_after(now, req_disk->start_time + dt) &&
+ if (dt && oldest_submit_jif != now &&
+ time_after(now, oldest_submit_jif + dt) &&
!time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) {
drbd_warn(device, "Local backing device failed to meet the disk-timeout\n");
__drbd_chk_io_error(device, DRBD_FORCE_DETACH);
@@ -1443,11 +1639,12 @@ void request_timer_fn(unsigned long data)
/* Reschedule timer for the nearest not already expired timeout.
* Fallback to now + min(effective network timeout, disk timeout). */
- ent = (ent && req_peer && time_before(now, req_peer->start_time + ent))
- ? req_peer->start_time + ent : now + et;
- dt = (dt && req_disk && time_before(now, req_disk->start_time + dt))
- ? req_disk->start_time + dt : now + et;
+ ent = (ent && req_peer && time_before(now, req_peer->pre_send_jif + ent))
+ ? req_peer->pre_send_jif + ent : now + et;
+ dt = (dt && oldest_submit_jif != now && time_before(now, oldest_submit_jif + dt))
+ ? oldest_submit_jif + dt : now + et;
nt = time_before(ent, dt) ? ent : dt;
+out:
spin_unlock_irq(&connection->resource->req_lock);
mod_timer(&device->request_timer, nt);
}
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 8566cd5866b4..9f6a04080e9f 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -288,6 +288,7 @@ extern void complete_master_bio(struct drbd_device *device,
extern void request_timer_fn(unsigned long data);
extern void tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
extern void _tl_restart(struct drbd_connection *connection, enum drbd_req_event what);
+extern void tl_abort_disk_io(struct drbd_device *device);
/* this is in drbd_main.c */
extern void drbd_restart_request(struct drbd_request *req);
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index a5d8aae00e04..c35c0f001bb7 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -410,7 +410,7 @@ _drbd_request_state(struct drbd_device *device, union drbd_state mask,
return rv;
}
-static void print_st(struct drbd_device *device, char *name, union drbd_state ns)
+static void print_st(struct drbd_device *device, const char *name, union drbd_state ns)
{
drbd_err(device, " %s = { cs:%s ro:%s/%s ds:%s/%s %c%c%c%c%c%c }\n",
name,
@@ -952,11 +952,12 @@ enum drbd_state_rv
__drbd_set_state(struct drbd_device *device, union drbd_state ns,
enum chg_state_flags flags, struct completion *done)
{
+ struct drbd_peer_device *peer_device = first_peer_device(device);
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
union drbd_state os;
enum drbd_state_rv rv = SS_SUCCESS;
enum sanitize_state_warnings ssw;
struct after_state_chg_work *ascw;
- bool did_remote, should_do_remote;
os = drbd_read_state(device);
@@ -978,9 +979,9 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
this happen...*/
if (is_valid_state(device, os) == rv)
- rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
+ rv = is_valid_soft_transition(os, ns, connection);
} else
- rv = is_valid_soft_transition(os, ns, first_peer_device(device)->connection);
+ rv = is_valid_soft_transition(os, ns, connection);
}
if (rv < SS_SUCCESS) {
@@ -997,7 +998,7 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
sanitize_state(). Only display it here if we where not called from
_conn_request_state() */
if (!(flags & CS_DC_SUSP))
- conn_pr_state_change(first_peer_device(device)->connection, os, ns,
+ conn_pr_state_change(connection, os, ns,
(flags & ~CS_DC_MASK) | CS_DC_SUSP);
/* if we are going -> D_FAILED or D_DISKLESS, grab one extra reference
@@ -1008,28 +1009,35 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
(os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
atomic_inc(&device->local_cnt);
- did_remote = drbd_should_do_remote(device->state);
+ if (!is_sync_state(os.conn) && is_sync_state(ns.conn))
+ clear_bit(RS_DONE, &device->flags);
+
+ /* changes to local_cnt and device flags should be visible before
+ * changes to state, which again should be visible before anything else
+ * depending on that change happens. */
+ smp_wmb();
device->state.i = ns.i;
- should_do_remote = drbd_should_do_remote(device->state);
device->resource->susp = ns.susp;
device->resource->susp_nod = ns.susp_nod;
device->resource->susp_fen = ns.susp_fen;
+ smp_wmb();
/* put replicated vs not-replicated requests in seperate epochs */
- if (did_remote != should_do_remote)
- start_new_tl_epoch(first_peer_device(device)->connection);
+ if (drbd_should_do_remote((union drbd_dev_state)os.i) !=
+ drbd_should_do_remote((union drbd_dev_state)ns.i))
+ start_new_tl_epoch(connection);
if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
drbd_print_uuids(device, "attached to UUIDs");
/* Wake up role changes, that were delayed because of connection establishing */
if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS &&
- no_peer_wf_report_params(first_peer_device(device)->connection))
- clear_bit(STATE_SENT, &first_peer_device(device)->connection->flags);
+ no_peer_wf_report_params(connection))
+ clear_bit(STATE_SENT, &connection->flags);
wake_up(&device->misc_wait);
wake_up(&device->state_wait);
- wake_up(&first_peer_device(device)->connection->ping_wait);
+ wake_up(&connection->ping_wait);
/* Aborted verify run, or we reached the stop sector.
* Log the last position, unless end-of-device. */
@@ -1118,21 +1126,21 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
/* Receiver should clean up itself */
if (os.conn != C_DISCONNECTING && ns.conn == C_DISCONNECTING)
- drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
+ drbd_thread_stop_nowait(&connection->receiver);
/* Now the receiver finished cleaning up itself, it should die */
if (os.conn != C_STANDALONE && ns.conn == C_STANDALONE)
- drbd_thread_stop_nowait(&first_peer_device(device)->connection->receiver);
+ drbd_thread_stop_nowait(&connection->receiver);
/* Upon network failure, we need to restart the receiver. */
if (os.conn > C_WF_CONNECTION &&
ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
- drbd_thread_restart_nowait(&first_peer_device(device)->connection->receiver);
+ drbd_thread_restart_nowait(&connection->receiver);
/* Resume AL writing if we get a connection */
if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
drbd_resume_al(device);
- first_peer_device(device)->connection->connect_cnt++;
+ connection->connect_cnt++;
}
/* remember last attach time so request_timer_fn() won't
@@ -1150,7 +1158,7 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
ascw->w.cb = w_after_state_ch;
ascw->device = device;
ascw->done = done;
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
+ drbd_queue_work(&connection->sender_work,
&ascw->w);
} else {
drbd_err(device, "Could not kmalloc an ascw\n");
@@ -1222,13 +1230,16 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
union drbd_state ns, enum chg_state_flags flags)
{
struct drbd_resource *resource = device->resource;
+ struct drbd_peer_device *peer_device = first_peer_device(device);
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
struct sib_info sib;
sib.sib_reason = SIB_STATE_CHANGE;
sib.os = os;
sib.ns = ns;
- if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
+ if ((os.disk != D_UP_TO_DATE || os.pdsk != D_UP_TO_DATE)
+ && (ns.disk == D_UP_TO_DATE && ns.pdsk == D_UP_TO_DATE)) {
clear_bit(CRASHED_PRIMARY, &device->flags);
if (device->p_uuid)
device->p_uuid[UI_FLAGS] &= ~((u64)2);
@@ -1245,7 +1256,6 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
state change. This function might sleep */
if (ns.susp_nod) {
- struct drbd_connection *connection = first_peer_device(device)->connection;
enum drbd_req_event what = NOTHING;
spin_lock_irq(&device->resource->req_lock);
@@ -1267,8 +1277,6 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
}
if (ns.susp_fen) {
- struct drbd_connection *connection = first_peer_device(device)->connection;
-
spin_lock_irq(&device->resource->req_lock);
if (resource->susp_fen && conn_lowest_conn(connection) >= C_CONNECTED) {
/* case2: The connection was established again: */
@@ -1294,8 +1302,8 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
* which is unexpected. */
if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
(ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
- first_peer_device(device)->connection->agreed_pro_version >= 96 && get_ldev(device)) {
- drbd_gen_and_send_sync_uuid(first_peer_device(device));
+ connection->agreed_pro_version >= 96 && get_ldev(device)) {
+ drbd_gen_and_send_sync_uuid(peer_device);
put_ldev(device);
}
@@ -1309,8 +1317,8 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
atomic_set(&device->rs_pending_cnt, 0);
drbd_rs_cancel_all(device);
- drbd_send_uuids(first_peer_device(device));
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_uuids(peer_device);
+ drbd_send_state(peer_device, ns);
}
/* No point in queuing send_bitmap if we don't have a connection
* anymore, so check also the _current_ state, not only the new state
@@ -1335,7 +1343,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
set_bit(NEW_CUR_UUID, &device->flags);
} else {
drbd_uuid_new_current(device);
- drbd_send_uuids(first_peer_device(device));
+ drbd_send_uuids(peer_device);
}
}
put_ldev(device);
@@ -1346,7 +1354,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
if (os.peer == R_SECONDARY && ns.peer == R_PRIMARY &&
device->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
drbd_uuid_new_current(device);
- drbd_send_uuids(first_peer_device(device));
+ drbd_send_uuids(peer_device);
}
/* D_DISKLESS Peer becomes secondary */
if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1373,16 +1381,16 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
/* Last part of the attaching process ... */
if (ns.conn >= C_CONNECTED &&
os.disk == D_ATTACHING && ns.disk == D_NEGOTIATING) {
- drbd_send_sizes(first_peer_device(device), 0, 0); /* to start sync... */
- drbd_send_uuids(first_peer_device(device));
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_sizes(peer_device, 0, 0); /* to start sync... */
+ drbd_send_uuids(peer_device);
+ drbd_send_state(peer_device, ns);
}
/* We want to pause/continue resync, tell peer. */
if (ns.conn >= C_CONNECTED &&
((os.aftr_isp != ns.aftr_isp) ||
(os.user_isp != ns.user_isp)))
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* In case one of the isp bits got set, suspend other devices. */
if ((!os.aftr_isp && !os.peer_isp && !os.user_isp) &&
@@ -1392,10 +1400,10 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
/* Make sure the peer gets informed about eventual state
changes (ISP bits) while we were in WFReportParams. */
if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* We are in the progress to start a full sync... */
if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
@@ -1449,7 +1457,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
drbd_disk_str(device->state.disk));
if (ns.conn >= C_CONNECTED)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
drbd_rs_cancel_all(device);
@@ -1473,7 +1481,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
drbd_disk_str(device->state.disk));
if (ns.conn >= C_CONNECTED)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* corresponding get_ldev in __drbd_set_state
* this may finally trigger drbd_ldev_destroy. */
put_ldev(device);
@@ -1481,7 +1489,7 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
/* Notify peer that I had a local IO error, and did not detached.. */
if (os.disk == D_UP_TO_DATE && ns.disk == D_INCONSISTENT && ns.conn >= C_CONNECTED)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* Disks got bigger while they were detached */
if (ns.disk > D_NEGOTIATING && ns.pdsk > D_NEGOTIATING &&
@@ -1499,14 +1507,14 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
/* sync target done with resync. Explicitly notify peer, even though
* it should (at least for non-empty resyncs) already know itself. */
if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* Verify finished, or reached stop sector. Peer did not know about
* the stop sector, and we may even have changed the stop sector during
* verify to interrupt/stop early. Send the new state. */
if (os.conn == C_VERIFY_S && ns.conn == C_CONNECTED
&& verify_can_do_stop_sector(device))
- drbd_send_state(first_peer_device(device), ns);
+ drbd_send_state(peer_device, ns);
/* This triggers bitmap writeout of potentially still unwritten pages
* if the resync finished cleanly, or aborted because of peer disk
@@ -1563,7 +1571,7 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused)
old_conf = connection->net_conf;
connection->my_addr_len = 0;
connection->peer_addr_len = 0;
- rcu_assign_pointer(connection->net_conf, NULL);
+ RCU_INIT_POINTER(connection->net_conf, NULL);
conn_free_crypto(connection);
mutex_unlock(&connection->resource->conf_update);
@@ -1599,7 +1607,7 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused)
return 0;
}
-void conn_old_common_state(struct drbd_connection *connection, union drbd_state *pcs, enum chg_state_flags *pf)
+static void conn_old_common_state(struct drbd_connection *connection, union drbd_state *pcs, enum chg_state_flags *pf)
{
enum chg_state_flags flags = ~0;
struct drbd_peer_device *peer_device;
@@ -1688,7 +1696,7 @@ conn_is_valid_transition(struct drbd_connection *connection, union drbd_state ma
return rv;
}
-void
+static void
conn_set_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
union drbd_state *pns_min, union drbd_state *pns_max, enum chg_state_flags flags)
{
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index d8f57b6305cd..50776b362828 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -67,13 +67,10 @@ rwlock_t global_state_lock;
*/
void drbd_md_io_complete(struct bio *bio, int error)
{
- struct drbd_md_io *md_io;
struct drbd_device *device;
- md_io = (struct drbd_md_io *)bio->bi_private;
- device = container_of(md_io, struct drbd_device, md_io);
-
- md_io->error = error;
+ device = bio->bi_private;
+ device->md_io.error = error;
/* We grabbed an extra reference in _drbd_md_sync_page_io() to be able
* to timeout on the lower level device, and eventually detach from it.
@@ -87,7 +84,7 @@ void drbd_md_io_complete(struct bio *bio, int error)
* ASSERT(atomic_read(&device->md_io_in_use) == 1) there.
*/
drbd_md_put_buffer(device);
- md_io->done = 1;
+ device->md_io.done = 1;
wake_up(&device->misc_wait);
bio_put(bio);
if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */
@@ -135,6 +132,7 @@ void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(l
i = peer_req->i;
do_al_complete_io = peer_req->flags & EE_CALL_AL_COMPLETE_IO;
block_id = peer_req->block_id;
+ peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
spin_lock_irqsave(&device->resource->req_lock, flags);
device->writ_cnt += peer_req->i.size >> 9;
@@ -398,9 +396,6 @@ static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector,
if (!get_ldev(device))
return -EIO;
- if (drbd_rs_should_slow_down(device, sector))
- goto defer;
-
/* GFP_TRY, because if there is no memory available right now, this may
* be rescheduled for later. It is "only" background resync, after all. */
peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER /* unused */, sector,
@@ -410,7 +405,7 @@ static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector,
peer_req->w.cb = w_e_send_csum;
spin_lock_irq(&device->resource->req_lock);
- list_add(&peer_req->w.list, &device->read_ee);
+ list_add_tail(&peer_req->w.list, &device->read_ee);
spin_unlock_irq(&device->resource->req_lock);
atomic_add(size >> 9, &device->rs_sect_ev);
@@ -452,9 +447,9 @@ void resync_timer_fn(unsigned long data)
{
struct drbd_device *device = (struct drbd_device *) data;
- if (list_empty(&device->resync_work.list))
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
- &device->resync_work);
+ drbd_queue_work_if_unqueued(
+ &first_peer_device(device)->connection->sender_work,
+ &device->resync_work);
}
static void fifo_set(struct fifo_buffer *fb, int value)
@@ -504,9 +499,9 @@ struct fifo_buffer *fifo_alloc(int fifo_size)
static int drbd_rs_controller(struct drbd_device *device, unsigned int sect_in)
{
struct disk_conf *dc;
- unsigned int want; /* The number of sectors we want in the proxy */
+ unsigned int want; /* The number of sectors we want in-flight */
int req_sect; /* Number of sectors to request in this turn */
- int correction; /* Number of sectors more we need in the proxy*/
+ int correction; /* Number of sectors more we need in-flight */
int cps; /* correction per invocation of drbd_rs_controller() */
int steps; /* Number of time steps to plan ahead */
int curr_corr;
@@ -577,20 +572,27 @@ static int drbd_rs_number_requests(struct drbd_device *device)
* potentially causing a distributed deadlock on congestion during
* online-verify or (checksum-based) resync, if max-buffers,
* socket buffer sizes and resync rate settings are mis-configured. */
- if (mxb - device->rs_in_flight < number)
- number = mxb - device->rs_in_flight;
+
+ /* note that "number" is in units of "BM_BLOCK_SIZE" (which is 4k),
+ * mxb (as used here, and in drbd_alloc_pages on the peer) is
+ * "number of pages" (typically also 4k),
+ * but "rs_in_flight" is in "sectors" (512 Byte). */
+ if (mxb - device->rs_in_flight/8 < number)
+ number = mxb - device->rs_in_flight/8;
return number;
}
-static int make_resync_request(struct drbd_device *device, int cancel)
+static int make_resync_request(struct drbd_device *const device, int cancel)
{
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *const connection = peer_device ? peer_device->connection : NULL;
unsigned long bit;
sector_t sector;
const sector_t capacity = drbd_get_capacity(device->this_bdev);
int max_bio_size;
int number, rollback_i, size;
- int align, queued, sndbuf;
+ int align, requeue = 0;
int i = 0;
if (unlikely(cancel))
@@ -617,17 +619,22 @@ static int make_resync_request(struct drbd_device *device, int cancel)
goto requeue;
for (i = 0; i < number; i++) {
- /* Stop generating RS requests, when half of the send buffer is filled */
- mutex_lock(&first_peer_device(device)->connection->data.mutex);
- if (first_peer_device(device)->connection->data.socket) {
- queued = first_peer_device(device)->connection->data.socket->sk->sk_wmem_queued;
- sndbuf = first_peer_device(device)->connection->data.socket->sk->sk_sndbuf;
- } else {
- queued = 1;
- sndbuf = 0;
- }
- mutex_unlock(&first_peer_device(device)->connection->data.mutex);
- if (queued > sndbuf / 2)
+ /* Stop generating RS requests when half of the send buffer is filled,
+ * but notify TCP that we'd like to have more space. */
+ mutex_lock(&connection->data.mutex);
+ if (connection->data.socket) {
+ struct sock *sk = connection->data.socket->sk;
+ int queued = sk->sk_wmem_queued;
+ int sndbuf = sk->sk_sndbuf;
+ if (queued > sndbuf / 2) {
+ requeue = 1;
+ if (sk->sk_socket)
+ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ }
+ } else
+ requeue = 1;
+ mutex_unlock(&connection->data.mutex);
+ if (requeue)
goto requeue;
next_sector:
@@ -642,8 +649,7 @@ next_sector:
sector = BM_BIT_TO_SECT(bit);
- if (drbd_rs_should_slow_down(device, sector) ||
- drbd_try_rs_begin_io(device, sector)) {
+ if (drbd_try_rs_begin_io(device, sector)) {
device->bm_resync_fo = bit;
goto requeue;
}
@@ -696,9 +702,9 @@ next_sector:
/* adjust very last sectors, in case we are oddly sized */
if (sector + (size>>9) > capacity)
size = (capacity-sector)<<9;
- if (first_peer_device(device)->connection->agreed_pro_version >= 89 &&
- first_peer_device(device)->connection->csums_tfm) {
- switch (read_for_csum(first_peer_device(device), sector, size)) {
+
+ if (device->use_csums) {
+ switch (read_for_csum(peer_device, sector, size)) {
case -EIO: /* Disk failure */
put_ldev(device);
return -EIO;
@@ -717,7 +723,7 @@ next_sector:
int err;
inc_rs_pending(device);
- err = drbd_send_drequest(first_peer_device(device), P_RS_DATA_REQUEST,
+ err = drbd_send_drequest(peer_device, P_RS_DATA_REQUEST,
sector, size, ID_SYNCER);
if (err) {
drbd_err(device, "drbd_send_drequest() failed, aborting...\n");
@@ -774,8 +780,7 @@ static int make_ov_request(struct drbd_device *device, int cancel)
size = BM_BLOCK_SIZE;
- if (drbd_rs_should_slow_down(device, sector) ||
- drbd_try_rs_begin_io(device, sector)) {
+ if (drbd_try_rs_begin_io(device, sector)) {
device->ov_position = sector;
goto requeue;
}
@@ -911,7 +916,7 @@ int drbd_resync_finished(struct drbd_device *device)
if (os.conn == C_SYNC_TARGET || os.conn == C_PAUSED_SYNC_T)
khelper_cmd = "after-resync-target";
- if (first_peer_device(device)->connection->csums_tfm && device->rs_total) {
+ if (device->use_csums && device->rs_total) {
const unsigned long s = device->rs_same_csum;
const unsigned long t = device->rs_total;
const int ratio =
@@ -1351,13 +1356,15 @@ int w_send_out_of_sync(struct drbd_work *w, int cancel)
{
struct drbd_request *req = container_of(w, struct drbd_request, w);
struct drbd_device *device = req->device;
- struct drbd_connection *connection = first_peer_device(device)->connection;
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *const connection = peer_device->connection;
int err;
if (unlikely(cancel)) {
req_mod(req, SEND_CANCELED);
return 0;
}
+ req->pre_send_jif = jiffies;
/* this time, no connection->send.current_epoch_writes++;
* If it was sent, it was the closing barrier for the last
@@ -1365,7 +1372,7 @@ int w_send_out_of_sync(struct drbd_work *w, int cancel)
* No more barriers will be sent, until we leave AHEAD mode again. */
maybe_send_barrier(connection, req->epoch);
- err = drbd_send_out_of_sync(first_peer_device(device), req);
+ err = drbd_send_out_of_sync(peer_device, req);
req_mod(req, OOS_HANDED_TO_NETWORK);
return err;
@@ -1380,19 +1387,21 @@ int w_send_dblock(struct drbd_work *w, int cancel)
{
struct drbd_request *req = container_of(w, struct drbd_request, w);
struct drbd_device *device = req->device;
- struct drbd_connection *connection = first_peer_device(device)->connection;
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *connection = peer_device->connection;
int err;
if (unlikely(cancel)) {
req_mod(req, SEND_CANCELED);
return 0;
}
+ req->pre_send_jif = jiffies;
re_init_if_first_write(connection, req->epoch);
maybe_send_barrier(connection, req->epoch);
connection->send.current_epoch_writes++;
- err = drbd_send_dblock(first_peer_device(device), req);
+ err = drbd_send_dblock(peer_device, req);
req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
return err;
@@ -1407,19 +1416,21 @@ int w_send_read_req(struct drbd_work *w, int cancel)
{
struct drbd_request *req = container_of(w, struct drbd_request, w);
struct drbd_device *device = req->device;
- struct drbd_connection *connection = first_peer_device(device)->connection;
+ struct drbd_peer_device *const peer_device = first_peer_device(device);
+ struct drbd_connection *connection = peer_device->connection;
int err;
if (unlikely(cancel)) {
req_mod(req, SEND_CANCELED);
return 0;
}
+ req->pre_send_jif = jiffies;
/* Even read requests may close a write epoch,
* if there was any yet. */
maybe_send_barrier(connection, req->epoch);
- err = drbd_send_drequest(first_peer_device(device), P_DATA_REQUEST, req->i.sector, req->i.size,
+ err = drbd_send_drequest(peer_device, P_DATA_REQUEST, req->i.sector, req->i.size,
(unsigned long)req);
req_mod(req, err ? SEND_FAILED : HANDED_OVER_TO_NETWORK);
@@ -1433,7 +1444,7 @@ int w_restart_disk_io(struct drbd_work *w, int cancel)
struct drbd_device *device = req->device;
if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
- drbd_al_begin_io(device, &req->i, false);
+ drbd_al_begin_io(device, &req->i);
drbd_req_make_private_bio(req, req->master_bio);
req->private_bio->bi_bdev = device->ldev->backing_bdev;
@@ -1601,26 +1612,32 @@ void drbd_rs_controller_reset(struct drbd_device *device)
void start_resync_timer_fn(unsigned long data)
{
struct drbd_device *device = (struct drbd_device *) data;
-
- drbd_queue_work(&first_peer_device(device)->connection->sender_work,
- &device->start_resync_work);
+ drbd_device_post_work(device, RS_START);
}
-int w_start_resync(struct drbd_work *w, int cancel)
+static void do_start_resync(struct drbd_device *device)
{
- struct drbd_device *device =
- container_of(w, struct drbd_device, start_resync_work);
-
if (atomic_read(&device->unacked_cnt) || atomic_read(&device->rs_pending_cnt)) {
- drbd_warn(device, "w_start_resync later...\n");
+ drbd_warn(device, "postponing start_resync ...\n");
device->start_resync_timer.expires = jiffies + HZ/10;
add_timer(&device->start_resync_timer);
- return 0;
+ return;
}
drbd_start_resync(device, C_SYNC_SOURCE);
clear_bit(AHEAD_TO_SYNC_SOURCE, &device->flags);
- return 0;
+}
+
+static bool use_checksum_based_resync(struct drbd_connection *connection, struct drbd_device *device)
+{
+ bool csums_after_crash_only;
+ rcu_read_lock();
+ csums_after_crash_only = rcu_dereference(connection->net_conf)->csums_after_crash_only;
+ rcu_read_unlock();
+ return connection->agreed_pro_version >= 89 && /* supported? */
+ connection->csums_tfm && /* configured? */
+ (csums_after_crash_only == 0 /* use for each resync? */
+ || test_bit(CRASHED_PRIMARY, &device->flags)); /* or only after Primary crash? */
}
/**
@@ -1633,6 +1650,8 @@ int w_start_resync(struct drbd_work *w, int cancel)
*/
void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
{
+ struct drbd_peer_device *peer_device = first_peer_device(device);
+ struct drbd_connection *connection = peer_device ? peer_device->connection : NULL;
union drbd_state ns;
int r;
@@ -1651,7 +1670,7 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
if (r > 0) {
drbd_info(device, "before-resync-target handler returned %d, "
"dropping connection.\n", r);
- conn_request_state(first_peer_device(device)->connection, NS(conn, C_DISCONNECTING), CS_HARD);
+ conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD);
return;
}
} else /* C_SYNC_SOURCE */ {
@@ -1664,7 +1683,7 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
} else {
drbd_info(device, "before-resync-source handler returned %d, "
"dropping connection.\n", r);
- conn_request_state(first_peer_device(device)->connection,
+ conn_request_state(connection,
NS(conn, C_DISCONNECTING), CS_HARD);
return;
}
@@ -1672,7 +1691,7 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
}
}
- if (current == first_peer_device(device)->connection->worker.task) {
+ if (current == connection->worker.task) {
/* The worker should not sleep waiting for state_mutex,
that can take long */
if (!mutex_trylock(device->state_mutex)) {
@@ -1733,11 +1752,20 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
device->rs_mark_time[i] = now;
}
_drbd_pause_after(device);
+ /* Forget potentially stale cached per resync extent bit-counts.
+ * Open coded drbd_rs_cancel_all(device), we already have IRQs
+ * disabled, and know the disk state is ok. */
+ spin_lock(&device->al_lock);
+ lc_reset(device->resync);
+ device->resync_locked = 0;
+ device->resync_wenr = LC_FREE;
+ spin_unlock(&device->al_lock);
}
write_unlock(&global_state_lock);
spin_unlock_irq(&device->resource->req_lock);
if (r == SS_SUCCESS) {
+ wake_up(&device->al_wait); /* for lc_reset() above */
/* reset rs_last_bcast when a resync or verify is started,
* to deal with potential jiffies wrap. */
device->rs_last_bcast = jiffies - HZ;
@@ -1746,8 +1774,12 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
drbd_conn_str(ns.conn),
(unsigned long) device->rs_total << (BM_BLOCK_SHIFT-10),
(unsigned long) device->rs_total);
- if (side == C_SYNC_TARGET)
+ if (side == C_SYNC_TARGET) {
device->bm_resync_fo = 0;
+ device->use_csums = use_checksum_based_resync(connection, device);
+ } else {
+ device->use_csums = 0;
+ }
/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
* with w_send_oos, or the sync target will get confused as to
@@ -1756,12 +1788,10 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
* drbd_resync_finished from here in that case.
* We drbd_gen_and_send_sync_uuid here for protocol < 96,
* and from after_state_ch otherwise. */
- if (side == C_SYNC_SOURCE &&
- first_peer_device(device)->connection->agreed_pro_version < 96)
- drbd_gen_and_send_sync_uuid(first_peer_device(device));
+ if (side == C_SYNC_SOURCE && connection->agreed_pro_version < 96)
+ drbd_gen_and_send_sync_uuid(peer_device);
- if (first_peer_device(device)->connection->agreed_pro_version < 95 &&
- device->rs_total == 0) {
+ if (connection->agreed_pro_version < 95 && device->rs_total == 0) {
/* This still has a race (about when exactly the peers
* detect connection loss) that can lead to a full sync
* on next handshake. In 8.3.9 we fixed this with explicit
@@ -1777,7 +1807,7 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
int timeo;
rcu_read_lock();
- nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
+ nc = rcu_dereference(connection->net_conf);
timeo = nc->ping_int * HZ + nc->ping_timeo * HZ / 9;
rcu_read_unlock();
schedule_timeout_interruptible(timeo);
@@ -1799,10 +1829,165 @@ void drbd_start_resync(struct drbd_device *device, enum drbd_conns side)
mutex_unlock(device->state_mutex);
}
+static void update_on_disk_bitmap(struct drbd_device *device, bool resync_done)
+{
+ struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
+ device->rs_last_bcast = jiffies;
+
+ if (!get_ldev(device))
+ return;
+
+ drbd_bm_write_lazy(device, 0);
+ if (resync_done && is_sync_state(device->state.conn))
+ drbd_resync_finished(device);
+
+ drbd_bcast_event(device, &sib);
+ /* update timestamp, in case it took a while to write out stuff */
+ device->rs_last_bcast = jiffies;
+ put_ldev(device);
+}
+
+static void drbd_ldev_destroy(struct drbd_device *device)
+{
+ lc_destroy(device->resync);
+ device->resync = NULL;
+ lc_destroy(device->act_log);
+ device->act_log = NULL;
+ __no_warn(local,
+ drbd_free_ldev(device->ldev);
+ device->ldev = NULL;);
+ clear_bit(GOING_DISKLESS, &device->flags);
+ wake_up(&device->misc_wait);
+}
+
+static void go_diskless(struct drbd_device *device)
+{
+ D_ASSERT(device, device->state.disk == D_FAILED);
+ /* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
+ * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
+ * the protected members anymore, though, so once put_ldev reaches zero
+ * again, it will be safe to free them. */
+
+ /* Try to write changed bitmap pages, read errors may have just
+ * set some bits outside the area covered by the activity log.
+ *
+ * If we have an IO error during the bitmap writeout,
+ * we will want a full sync next time, just in case.
+ * (Do we want a specific meta data flag for this?)
+ *
+ * If that does not make it to stable storage either,
+ * we cannot do anything about that anymore.
+ *
+ * We still need to check if both bitmap and ldev are present, we may
+ * end up here after a failed attach, before ldev was even assigned.
+ */
+ if (device->bitmap && device->ldev) {
+ /* An interrupted resync or similar is allowed to recounts bits
+ * while we detach.
+ * Any modifications would not be expected anymore, though.
+ */
+ if (drbd_bitmap_io_from_worker(device, drbd_bm_write,
+ "detach", BM_LOCKED_TEST_ALLOWED)) {
+ if (test_bit(WAS_READ_ERROR, &device->flags)) {
+ drbd_md_set_flag(device, MDF_FULL_SYNC);
+ drbd_md_sync(device);
+ }
+ }
+ }
+
+ drbd_force_state(device, NS(disk, D_DISKLESS));
+}
+
+static int do_md_sync(struct drbd_device *device)
+{
+ drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+ drbd_md_sync(device);
+ return 0;
+}
+
+/* only called from drbd_worker thread, no locking */
+void __update_timing_details(
+ struct drbd_thread_timing_details *tdp,
+ unsigned int *cb_nr,
+ void *cb,
+ const char *fn, const unsigned int line)
+{
+ unsigned int i = *cb_nr % DRBD_THREAD_DETAILS_HIST;
+ struct drbd_thread_timing_details *td = tdp + i;
+
+ td->start_jif = jiffies;
+ td->cb_addr = cb;
+ td->caller_fn = fn;
+ td->line = line;
+ td->cb_nr = *cb_nr;
+
+ i = (i+1) % DRBD_THREAD_DETAILS_HIST;
+ td = tdp + i;
+ memset(td, 0, sizeof(*td));
+
+ ++(*cb_nr);
+}
+
+#define WORK_PENDING(work_bit, todo) (todo & (1UL << work_bit))
+static void do_device_work(struct drbd_device *device, const unsigned long todo)
+{
+ if (WORK_PENDING(MD_SYNC, todo))
+ do_md_sync(device);
+ if (WORK_PENDING(RS_DONE, todo) ||
+ WORK_PENDING(RS_PROGRESS, todo))
+ update_on_disk_bitmap(device, WORK_PENDING(RS_DONE, todo));
+ if (WORK_PENDING(GO_DISKLESS, todo))
+ go_diskless(device);
+ if (WORK_PENDING(DESTROY_DISK, todo))
+ drbd_ldev_destroy(device);
+ if (WORK_PENDING(RS_START, todo))
+ do_start_resync(device);
+}
+
+#define DRBD_DEVICE_WORK_MASK \
+ ((1UL << GO_DISKLESS) \
+ |(1UL << DESTROY_DISK) \
+ |(1UL << MD_SYNC) \
+ |(1UL << RS_START) \
+ |(1UL << RS_PROGRESS) \
+ |(1UL << RS_DONE) \
+ )
+
+static unsigned long get_work_bits(unsigned long *flags)
+{
+ unsigned long old, new;
+ do {
+ old = *flags;
+ new = old & ~DRBD_DEVICE_WORK_MASK;
+ } while (cmpxchg(flags, old, new) != old);
+ return old & DRBD_DEVICE_WORK_MASK;
+}
+
+static void do_unqueued_work(struct drbd_connection *connection)
+{
+ struct drbd_peer_device *peer_device;
+ int vnr;
+
+ rcu_read_lock();
+ idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
+ struct drbd_device *device = peer_device->device;
+ unsigned long todo = get_work_bits(&device->flags);
+ if (!todo)
+ continue;
+
+ kref_get(&device->kref);
+ rcu_read_unlock();
+ do_device_work(device, todo);
+ kref_put(&device->kref, drbd_destroy_device);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+}
+
static bool dequeue_work_batch(struct drbd_work_queue *queue, struct list_head *work_list)
{
spin_lock_irq(&queue->q_lock);
- list_splice_init(&queue->q, work_list);
+ list_splice_tail_init(&queue->q, work_list);
spin_unlock_irq(&queue->q_lock);
return !list_empty(work_list);
}
@@ -1851,7 +2036,7 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
/* dequeue single item only,
* we still use drbd_queue_work_front() in some places */
if (!list_empty(&connection->sender_work.q))
- list_move(connection->sender_work.q.next, work_list);
+ list_splice_tail_init(&connection->sender_work.q, work_list);
spin_unlock(&connection->sender_work.q_lock); /* FIXME get rid of this one? */
if (!list_empty(work_list) || signal_pending(current)) {
spin_unlock_irq(&connection->resource->req_lock);
@@ -1873,6 +2058,14 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
if (send_barrier)
maybe_send_barrier(connection,
connection->send.current_epoch_nr + 1);
+
+ if (test_bit(DEVICE_WORK_PENDING, &connection->flags))
+ break;
+
+ /* drbd_send() may have called flush_signals() */
+ if (get_t_state(&connection->worker) != RUNNING)
+ break;
+
schedule();
/* may be woken up for other things but new work, too,
* e.g. if the current epoch got closed.
@@ -1906,10 +2099,15 @@ int drbd_worker(struct drbd_thread *thi)
while (get_t_state(thi) == RUNNING) {
drbd_thread_current_set_cpu(thi);
- /* as long as we use drbd_queue_work_front(),
- * we may only dequeue single work items here, not batches. */
- if (list_empty(&work_list))
+ if (list_empty(&work_list)) {
+ update_worker_timing_details(connection, wait_for_work);
wait_for_work(connection, &work_list);
+ }
+
+ if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
+ update_worker_timing_details(connection, do_unqueued_work);
+ do_unqueued_work(connection);
+ }
if (signal_pending(current)) {
flush_signals(current);
@@ -1926,6 +2124,7 @@ int drbd_worker(struct drbd_thread *thi)
while (!list_empty(&work_list)) {
w = list_first_entry(&work_list, struct drbd_work, list);
list_del_init(&w->list);
+ update_worker_timing_details(connection, w->cb);
if (w->cb(w, connection->cstate < C_WF_REPORT_PARAMS) == 0)
continue;
if (connection->cstate >= C_WF_REPORT_PARAMS)
@@ -1934,13 +2133,18 @@ int drbd_worker(struct drbd_thread *thi)
}
do {
+ if (test_and_clear_bit(DEVICE_WORK_PENDING, &connection->flags)) {
+ update_worker_timing_details(connection, do_unqueued_work);
+ do_unqueued_work(connection);
+ }
while (!list_empty(&work_list)) {
w = list_first_entry(&work_list, struct drbd_work, list);
list_del_init(&w->list);
+ update_worker_timing_details(connection, w->cb);
w->cb(w, 1);
}
dequeue_work_batch(&connection->sender_work, &work_list);
- } while (!list_empty(&work_list));
+ } while (!list_empty(&work_list) || test_bit(DEVICE_WORK_PENDING, &connection->flags));
rcu_read_lock();
idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 295f3afbbef5..db1e9560d8a7 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -4632,7 +4632,7 @@ static void mtip_pci_shutdown(struct pci_dev *pdev)
}
/* Table of device ids supported by this driver. */
-static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
+static const struct pci_device_id mtip_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) },
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index b2c98c1bc037..623c84145b79 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -42,6 +42,7 @@
#include <linux/blkdev.h>
#include <linux/slab.h>
#include <linux/idr.h>
+#include <linux/workqueue.h>
#include "rbd_types.h"
@@ -332,7 +333,10 @@ struct rbd_device {
char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */
+ struct list_head rq_queue; /* incoming rq queue */
spinlock_t lock; /* queue, flags, open_count */
+ struct workqueue_struct *rq_wq;
+ struct work_struct rq_work;
struct rbd_image_header header;
unsigned long flags; /* possibly lock protected */
@@ -514,7 +518,8 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
static int rbd_dev_refresh(struct rbd_device *rbd_dev);
static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
-static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev);
+static int rbd_dev_header_info(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
u64 snap_id);
static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -971,12 +976,6 @@ static int rbd_header_from_disk(struct rbd_device *rbd_dev,
header->snap_names = snap_names;
header->snap_sizes = snap_sizes;
- /* Make sure mapping size is consistent with header info */
-
- if (rbd_dev->spec->snap_id == CEPH_NOSNAP || first_time)
- if (rbd_dev->mapping.size != header->image_size)
- rbd_dev->mapping.size = header->image_size;
-
return 0;
out_2big:
ret = -EIO;
@@ -1139,6 +1138,13 @@ static void rbd_dev_mapping_clear(struct rbd_device *rbd_dev)
rbd_dev->mapping.features = 0;
}
+static void rbd_segment_name_free(const char *name)
+{
+ /* The explicit cast here is needed to drop the const qualifier */
+
+ kmem_cache_free(rbd_segment_name_cache, (void *)name);
+}
+
static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
{
char *name;
@@ -1158,20 +1164,13 @@ static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
if (ret < 0 || ret > CEPH_MAX_OID_NAME_LEN) {
pr_err("error formatting segment name for #%llu (%d)\n",
segment, ret);
- kfree(name);
+ rbd_segment_name_free(name);
name = NULL;
}
return name;
}
-static void rbd_segment_name_free(const char *name)
-{
- /* The explicit cast here is needed to drop the const qualifier */
-
- kmem_cache_free(rbd_segment_name_cache, (void *)name);
-}
-
static u64 rbd_segment_offset(struct rbd_device *rbd_dev, u64 offset)
{
u64 segment_size = (u64) 1 << rbd_dev->header.obj_order;
@@ -1371,7 +1370,7 @@ static void obj_request_img_data_set(struct rbd_obj_request *obj_request)
struct rbd_device *rbd_dev;
rbd_dev = obj_request->img_request->rbd_dev;
- rbd_warn(rbd_dev, "obj_request %p already marked img_data\n",
+ rbd_warn(rbd_dev, "obj_request %p already marked img_data",
obj_request);
}
}
@@ -1389,7 +1388,7 @@ static void obj_request_done_set(struct rbd_obj_request *obj_request)
if (obj_request_img_data_test(obj_request))
rbd_dev = obj_request->img_request->rbd_dev;
- rbd_warn(rbd_dev, "obj_request %p already marked done\n",
+ rbd_warn(rbd_dev, "obj_request %p already marked done",
obj_request);
}
}
@@ -1527,11 +1526,37 @@ static bool obj_request_type_valid(enum obj_request_type type)
static int rbd_obj_request_submit(struct ceph_osd_client *osdc,
struct rbd_obj_request *obj_request)
{
- dout("%s: osdc %p obj %p\n", __func__, osdc, obj_request);
-
+ dout("%s %p\n", __func__, obj_request);
return ceph_osdc_start_request(osdc, obj_request->osd_req, false);
}
+static void rbd_obj_request_end(struct rbd_obj_request *obj_request)
+{
+ dout("%s %p\n", __func__, obj_request);
+ ceph_osdc_cancel_request(obj_request->osd_req);
+}
+
+/*
+ * Wait for an object request to complete. If interrupted, cancel the
+ * underlying osd request.
+ */
+static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
+{
+ int ret;
+
+ dout("%s %p\n", __func__, obj_request);
+
+ ret = wait_for_completion_interruptible(&obj_request->completion);
+ if (ret < 0) {
+ dout("%s %p interrupted\n", __func__, obj_request);
+ rbd_obj_request_end(obj_request);
+ return ret;
+ }
+
+ dout("%s %p done\n", __func__, obj_request);
+ return 0;
+}
+
static void rbd_img_request_complete(struct rbd_img_request *img_request)
{
@@ -1558,15 +1583,6 @@ static void rbd_img_request_complete(struct rbd_img_request *img_request)
rbd_img_request_put(img_request);
}
-/* Caller is responsible for rbd_obj_request_destroy(obj_request) */
-
-static int rbd_obj_request_wait(struct rbd_obj_request *obj_request)
-{
- dout("%s: obj %p\n", __func__, obj_request);
-
- return wait_for_completion_interruptible(&obj_request->completion);
-}
-
/*
* The default/initial value for all image request flags is 0. Each
* is conditionally set to 1 at image request initialization time
@@ -1763,7 +1779,7 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
rbd_osd_trivial_callback(obj_request);
break;
default:
- rbd_warn(NULL, "%s: unsupported op %hu\n",
+ rbd_warn(NULL, "%s: unsupported op %hu",
obj_request->object_name, (unsigned short) opcode);
break;
}
@@ -1998,7 +2014,7 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev)
if (!counter)
rbd_dev_unparent(rbd_dev);
else
- rbd_warn(rbd_dev, "parent reference underflow\n");
+ rbd_warn(rbd_dev, "parent reference underflow");
}
/*
@@ -2028,7 +2044,7 @@ static bool rbd_dev_parent_get(struct rbd_device *rbd_dev)
/* Image was flattened, but parent is not yet torn down */
if (counter < 0)
- rbd_warn(rbd_dev, "parent reference overflow\n");
+ rbd_warn(rbd_dev, "parent reference overflow");
return false;
}
@@ -2045,7 +2061,7 @@ static struct rbd_img_request *rbd_img_request_create(
{
struct rbd_img_request *img_request;
- img_request = kmem_cache_alloc(rbd_img_request_cache, GFP_ATOMIC);
+ img_request = kmem_cache_alloc(rbd_img_request_cache, GFP_NOIO);
if (!img_request)
return NULL;
@@ -2161,11 +2177,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
if (result) {
struct rbd_device *rbd_dev = img_request->rbd_dev;
- rbd_warn(rbd_dev, "%s %llx at %llx (%llx)\n",
+ rbd_warn(rbd_dev, "%s %llx at %llx (%llx)",
img_request_write_test(img_request) ? "write" : "read",
obj_request->length, obj_request->img_offset,
obj_request->offset);
- rbd_warn(rbd_dev, " result %d xferred %x\n",
+ rbd_warn(rbd_dev, " result %d xferred %x",
result, xferred);
if (!img_request->result)
img_request->result = result;
@@ -2946,154 +2962,135 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
dout("%s: \"%s\" notify_id %llu opcode %u\n", __func__,
rbd_dev->header_name, (unsigned long long)notify_id,
(unsigned int)opcode);
+
+ /*
+ * Until adequate refresh error handling is in place, there is
+ * not much we can do here, except warn.
+ *
+ * See http://tracker.ceph.com/issues/5040
+ */
ret = rbd_dev_refresh(rbd_dev);
if (ret)
- rbd_warn(rbd_dev, "header refresh error (%d)\n", ret);
+ rbd_warn(rbd_dev, "refresh failed: %d", ret);
- rbd_obj_notify_ack_sync(rbd_dev, notify_id);
+ ret = rbd_obj_notify_ack_sync(rbd_dev, notify_id);
+ if (ret)
+ rbd_warn(rbd_dev, "notify_ack ret %d", ret);
}
/*
- * Initiate a watch request, synchronously.
+ * Send a (un)watch request and wait for the ack. Return a request
+ * with a ref held on success or error.
*/
-static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
+static struct rbd_obj_request *rbd_obj_watch_request_helper(
+ struct rbd_device *rbd_dev,
+ bool watch)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_obj_request *obj_request;
int ret;
- rbd_assert(!rbd_dev->watch_event);
- rbd_assert(!rbd_dev->watch_request);
-
- ret = ceph_osdc_create_event(osdc, rbd_watch_cb, rbd_dev,
- &rbd_dev->watch_event);
- if (ret < 0)
- return ret;
-
- rbd_assert(rbd_dev->watch_event);
-
obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
OBJ_REQUEST_NODATA);
- if (!obj_request) {
- ret = -ENOMEM;
- goto out_cancel;
- }
+ if (!obj_request)
+ return ERR_PTR(-ENOMEM);
obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1,
obj_request);
if (!obj_request->osd_req) {
ret = -ENOMEM;
- goto out_put;
+ goto out;
}
- ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
-
osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
- rbd_dev->watch_event->cookie, 0, 1);
+ rbd_dev->watch_event->cookie, 0, watch);
rbd_osd_req_format_write(obj_request);
+ if (watch)
+ ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
+
ret = rbd_obj_request_submit(osdc, obj_request);
if (ret)
- goto out_linger;
+ goto out;
ret = rbd_obj_request_wait(obj_request);
if (ret)
- goto out_linger;
+ goto out;
ret = obj_request->result;
- if (ret)
- goto out_linger;
-
- /*
- * A watch request is set to linger, so the underlying osd
- * request won't go away until we unregister it. We retain
- * a pointer to the object request during that time (in
- * rbd_dev->watch_request), so we'll keep a reference to
- * it. We'll drop that reference (below) after we've
- * unregistered it.
- */
- rbd_dev->watch_request = obj_request;
+ if (ret) {
+ if (watch)
+ rbd_obj_request_end(obj_request);
+ goto out;
+ }
- return 0;
+ return obj_request;
-out_linger:
- ceph_osdc_unregister_linger_request(osdc, obj_request->osd_req);
-out_put:
+out:
rbd_obj_request_put(obj_request);
-out_cancel:
- ceph_osdc_cancel_event(rbd_dev->watch_event);
- rbd_dev->watch_event = NULL;
-
- return ret;
+ return ERR_PTR(ret);
}
/*
- * Tear down a watch request, synchronously.
+ * Initiate a watch request, synchronously.
*/
-static int __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_obj_request *obj_request;
int ret;
- rbd_assert(rbd_dev->watch_event);
- rbd_assert(rbd_dev->watch_request);
+ rbd_assert(!rbd_dev->watch_event);
+ rbd_assert(!rbd_dev->watch_request);
- obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
- OBJ_REQUEST_NODATA);
- if (!obj_request) {
- ret = -ENOMEM;
- goto out_cancel;
- }
+ ret = ceph_osdc_create_event(osdc, rbd_watch_cb, rbd_dev,
+ &rbd_dev->watch_event);
+ if (ret < 0)
+ return ret;
- obj_request->osd_req = rbd_osd_req_create(rbd_dev, true, 1,
- obj_request);
- if (!obj_request->osd_req) {
- ret = -ENOMEM;
- goto out_put;
+ obj_request = rbd_obj_watch_request_helper(rbd_dev, true);
+ if (IS_ERR(obj_request)) {
+ ceph_osdc_cancel_event(rbd_dev->watch_event);
+ rbd_dev->watch_event = NULL;
+ return PTR_ERR(obj_request);
}
- osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
- rbd_dev->watch_event->cookie, 0, 0);
- rbd_osd_req_format_write(obj_request);
-
- ret = rbd_obj_request_submit(osdc, obj_request);
- if (ret)
- goto out_put;
+ /*
+ * A watch request is set to linger, so the underlying osd
+ * request won't go away until we unregister it. We retain
+ * a pointer to the object request during that time (in
+ * rbd_dev->watch_request), so we'll keep a reference to it.
+ * We'll drop that reference after we've unregistered it in
+ * rbd_dev_header_unwatch_sync().
+ */
+ rbd_dev->watch_request = obj_request;
- ret = rbd_obj_request_wait(obj_request);
- if (ret)
- goto out_put;
+ return 0;
+}
- ret = obj_request->result;
- if (ret)
- goto out_put;
+/*
+ * Tear down a watch request, synchronously.
+ */
+static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+{
+ struct rbd_obj_request *obj_request;
- /* We have successfully torn down the watch request */
+ rbd_assert(rbd_dev->watch_event);
+ rbd_assert(rbd_dev->watch_request);
- ceph_osdc_unregister_linger_request(osdc,
- rbd_dev->watch_request->osd_req);
+ rbd_obj_request_end(rbd_dev->watch_request);
rbd_obj_request_put(rbd_dev->watch_request);
rbd_dev->watch_request = NULL;
-out_put:
- rbd_obj_request_put(obj_request);
-out_cancel:
+ obj_request = rbd_obj_watch_request_helper(rbd_dev, false);
+ if (!IS_ERR(obj_request))
+ rbd_obj_request_put(obj_request);
+ else
+ rbd_warn(rbd_dev, "unable to tear down watch request (%ld)",
+ PTR_ERR(obj_request));
+
ceph_osdc_cancel_event(rbd_dev->watch_event);
rbd_dev->watch_event = NULL;
-
- return ret;
-}
-
-static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
-{
- int ret;
-
- ret = __rbd_dev_header_unwatch_sync(rbd_dev);
- if (ret) {
- rbd_warn(rbd_dev, "unable to tear down watch request: %d\n",
- ret);
- }
}
/*
@@ -3183,102 +3180,129 @@ out:
return ret;
}
-static void rbd_request_fn(struct request_queue *q)
- __releases(q->queue_lock) __acquires(q->queue_lock)
+static void rbd_handle_request(struct rbd_device *rbd_dev, struct request *rq)
{
- struct rbd_device *rbd_dev = q->queuedata;
- struct request *rq;
+ struct rbd_img_request *img_request;
+ u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
+ u64 length = blk_rq_bytes(rq);
+ bool wr = rq_data_dir(rq) == WRITE;
int result;
- while ((rq = blk_fetch_request(q))) {
- bool write_request = rq_data_dir(rq) == WRITE;
- struct rbd_img_request *img_request;
- u64 offset;
- u64 length;
+ /* Ignore/skip any zero-length requests */
- /* Ignore any non-FS requests that filter through. */
+ if (!length) {
+ dout("%s: zero-length request\n", __func__);
+ result = 0;
+ goto err_rq;
+ }
- if (rq->cmd_type != REQ_TYPE_FS) {
- dout("%s: non-fs request type %d\n", __func__,
- (int) rq->cmd_type);
- __blk_end_request_all(rq, 0);
- continue;
+ /* Disallow writes to a read-only device */
+
+ if (wr) {
+ if (rbd_dev->mapping.read_only) {
+ result = -EROFS;
+ goto err_rq;
}
+ rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
+ }
- /* Ignore/skip any zero-length requests */
+ /*
+ * Quit early if the mapped snapshot no longer exists. It's
+ * still possible the snapshot will have disappeared by the
+ * time our request arrives at the osd, but there's no sense in
+ * sending it if we already know.
+ */
+ if (!test_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags)) {
+ dout("request for non-existent snapshot");
+ rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
+ result = -ENXIO;
+ goto err_rq;
+ }
- offset = (u64) blk_rq_pos(rq) << SECTOR_SHIFT;
- length = (u64) blk_rq_bytes(rq);
+ if (offset && length > U64_MAX - offset + 1) {
+ rbd_warn(rbd_dev, "bad request range (%llu~%llu)", offset,
+ length);
+ result = -EINVAL;
+ goto err_rq; /* Shouldn't happen */
+ }
- if (!length) {
- dout("%s: zero-length request\n", __func__);
- __blk_end_request_all(rq, 0);
- continue;
- }
+ if (offset + length > rbd_dev->mapping.size) {
+ rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset,
+ length, rbd_dev->mapping.size);
+ result = -EIO;
+ goto err_rq;
+ }
- spin_unlock_irq(q->queue_lock);
+ img_request = rbd_img_request_create(rbd_dev, offset, length, wr);
+ if (!img_request) {
+ result = -ENOMEM;
+ goto err_rq;
+ }
+ img_request->rq = rq;
- /* Disallow writes to a read-only device */
+ result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO, rq->bio);
+ if (result)
+ goto err_img_request;
- if (write_request) {
- result = -EROFS;
- if (rbd_dev->mapping.read_only)
- goto end_request;
- rbd_assert(rbd_dev->spec->snap_id == CEPH_NOSNAP);
- }
+ result = rbd_img_request_submit(img_request);
+ if (result)
+ goto err_img_request;
- /*
- * Quit early if the mapped snapshot no longer
- * exists. It's still possible the snapshot will
- * have disappeared by the time our request arrives
- * at the osd, but there's no sense in sending it if
- * we already know.
- */
- if (!test_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags)) {
- dout("request for non-existent snapshot");
- rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
- result = -ENXIO;
- goto end_request;
- }
+ return;
- result = -EINVAL;
- if (offset && length > U64_MAX - offset + 1) {
- rbd_warn(rbd_dev, "bad request range (%llu~%llu)\n",
- offset, length);
- goto end_request; /* Shouldn't happen */
- }
+err_img_request:
+ rbd_img_request_put(img_request);
+err_rq:
+ if (result)
+ rbd_warn(rbd_dev, "%s %llx at %llx result %d",
+ wr ? "write" : "read", length, offset, result);
+ blk_end_request_all(rq, result);
+}
- result = -EIO;
- if (offset + length > rbd_dev->mapping.size) {
- rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)\n",
- offset, length, rbd_dev->mapping.size);
- goto end_request;
- }
+static void rbd_request_workfn(struct work_struct *work)
+{
+ struct rbd_device *rbd_dev =
+ container_of(work, struct rbd_device, rq_work);
+ struct request *rq, *next;
+ LIST_HEAD(requests);
- result = -ENOMEM;
- img_request = rbd_img_request_create(rbd_dev, offset, length,
- write_request);
- if (!img_request)
- goto end_request;
+ spin_lock_irq(&rbd_dev->lock); /* rq->q->queue_lock */
+ list_splice_init(&rbd_dev->rq_queue, &requests);
+ spin_unlock_irq(&rbd_dev->lock);
- img_request->rq = rq;
+ list_for_each_entry_safe(rq, next, &requests, queuelist) {
+ list_del_init(&rq->queuelist);
+ rbd_handle_request(rbd_dev, rq);
+ }
+}
- result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
- rq->bio);
- if (!result)
- result = rbd_img_request_submit(img_request);
- if (result)
- rbd_img_request_put(img_request);
-end_request:
- spin_lock_irq(q->queue_lock);
- if (result < 0) {
- rbd_warn(rbd_dev, "%s %llx at %llx result %d\n",
- write_request ? "write" : "read",
- length, offset, result);
-
- __blk_end_request_all(rq, result);
+/*
+ * Called with q->queue_lock held and interrupts disabled, possibly on
+ * the way to schedule(). Do not sleep here!
+ */
+static void rbd_request_fn(struct request_queue *q)
+{
+ struct rbd_device *rbd_dev = q->queuedata;
+ struct request *rq;
+ int queued = 0;
+
+ rbd_assert(rbd_dev);
+
+ while ((rq = blk_fetch_request(q))) {
+ /* Ignore any non-FS requests that filter through. */
+ if (rq->cmd_type != REQ_TYPE_FS) {
+ dout("%s: non-fs request type %d\n", __func__,
+ (int) rq->cmd_type);
+ __blk_end_request_all(rq, 0);
+ continue;
}
+
+ list_add_tail(&rq->queuelist, &rbd_dev->rq_queue);
+ queued++;
}
+
+ if (queued)
+ queue_work(rbd_dev->rq_wq, &rbd_dev->rq_work);
}
/*
@@ -3517,24 +3541,37 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
u64 mapping_size;
int ret;
- rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
down_write(&rbd_dev->header_rwsem);
mapping_size = rbd_dev->mapping.size;
- if (rbd_dev->image_format == 1)
- ret = rbd_dev_v1_header_info(rbd_dev);
- else
- ret = rbd_dev_v2_header_info(rbd_dev);
- /* If it's a mapped snapshot, validate its EXISTS flag */
+ ret = rbd_dev_header_info(rbd_dev);
+ if (ret)
+ return ret;
+
+ /*
+ * If there is a parent, see if it has disappeared due to the
+ * mapped image getting flattened.
+ */
+ if (rbd_dev->parent) {
+ ret = rbd_dev_v2_parent_info(rbd_dev);
+ if (ret)
+ return ret;
+ }
+
+ if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
+ if (rbd_dev->mapping.size != rbd_dev->header.image_size)
+ rbd_dev->mapping.size = rbd_dev->header.image_size;
+ } else {
+ /* validate mapped snapshot's EXISTS flag */
+ rbd_exists_validate(rbd_dev);
+ }
- rbd_exists_validate(rbd_dev);
up_write(&rbd_dev->header_rwsem);
- if (mapping_size != rbd_dev->mapping.size) {
+ if (mapping_size != rbd_dev->mapping.size)
rbd_dev_update_size(rbd_dev);
- }
- return ret;
+ return 0;
}
static int rbd_init_disk(struct rbd_device *rbd_dev)
@@ -3696,46 +3733,36 @@ static ssize_t rbd_snap_show(struct device *dev,
}
/*
- * For an rbd v2 image, shows the pool id, image id, and snapshot id
- * for the parent image. If there is no parent, simply shows
- * "(no parent image)".
+ * For a v2 image, shows the chain of parent images, separated by empty
+ * lines. For v1 images or if there is no parent, shows "(no parent
+ * image)".
*/
static ssize_t rbd_parent_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
- struct rbd_spec *spec = rbd_dev->parent_spec;
- int count;
- char *bufp = buf;
+ ssize_t count = 0;
- if (!spec)
+ if (!rbd_dev->parent)
return sprintf(buf, "(no parent image)\n");
- count = sprintf(bufp, "pool_id %llu\npool_name %s\n",
- (unsigned long long) spec->pool_id, spec->pool_name);
- if (count < 0)
- return count;
- bufp += count;
-
- count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id,
- spec->image_name ? spec->image_name : "(unknown)");
- if (count < 0)
- return count;
- bufp += count;
-
- count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n",
- (unsigned long long) spec->snap_id, spec->snap_name);
- if (count < 0)
- return count;
- bufp += count;
-
- count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap);
- if (count < 0)
- return count;
- bufp += count;
+ for ( ; rbd_dev->parent; rbd_dev = rbd_dev->parent) {
+ struct rbd_spec *spec = rbd_dev->parent_spec;
+
+ count += sprintf(&buf[count], "%s"
+ "pool_id %llu\npool_name %s\n"
+ "image_id %s\nimage_name %s\n"
+ "snap_id %llu\nsnap_name %s\n"
+ "overlap %llu\n",
+ !count ? "" : "\n", /* first? */
+ spec->pool_id, spec->pool_name,
+ spec->image_id, spec->image_name ?: "(unknown)",
+ spec->snap_id, spec->snap_name,
+ rbd_dev->parent_overlap);
+ }
- return (ssize_t) (bufp - buf);
+ return count;
}
static ssize_t rbd_image_refresh(struct device *dev,
@@ -3748,9 +3775,9 @@ static ssize_t rbd_image_refresh(struct device *dev,
ret = rbd_dev_refresh(rbd_dev);
if (ret)
- rbd_warn(rbd_dev, ": manual header refresh error (%d)\n", ret);
+ return ret;
- return ret < 0 ? ret : size;
+ return size;
}
static DEVICE_ATTR(size, S_IRUGO, rbd_size_show, NULL);
@@ -3822,6 +3849,9 @@ static struct rbd_spec *rbd_spec_alloc(void)
spec = kzalloc(sizeof (*spec), GFP_KERNEL);
if (!spec)
return NULL;
+
+ spec->pool_id = CEPH_NOPOOL;
+ spec->snap_id = CEPH_NOSNAP;
kref_init(&spec->kref);
return spec;
@@ -3848,6 +3878,8 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
return NULL;
spin_lock_init(&rbd_dev->lock);
+ INIT_LIST_HEAD(&rbd_dev->rq_queue);
+ INIT_WORK(&rbd_dev->rq_work, rbd_request_workfn);
rbd_dev->flags = 0;
atomic_set(&rbd_dev->parent_ref, 0);
INIT_LIST_HEAD(&rbd_dev->node);
@@ -4021,7 +4053,7 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
goto out_err;
}
- snapid = cpu_to_le64(CEPH_NOSNAP);
+ snapid = cpu_to_le64(rbd_dev->spec->snap_id);
ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
"rbd", "get_parent",
&snapid, sizeof (snapid),
@@ -4059,7 +4091,7 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
ret = -EIO;
if (pool_id > (u64)U32_MAX) {
- rbd_warn(NULL, "parent pool id too large (%llu > %u)\n",
+ rbd_warn(NULL, "parent pool id too large (%llu > %u)",
(unsigned long long)pool_id, U32_MAX);
goto out_err;
}
@@ -4083,6 +4115,8 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
parent_spec->snap_id = snap_id;
rbd_dev->parent_spec = parent_spec;
parent_spec = NULL; /* rbd_dev now owns this */
+ } else {
+ kfree(image_id);
}
/*
@@ -4110,8 +4144,7 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
* overlap is zero we just pretend there was
* no parent image.
*/
- rbd_warn(rbd_dev, "ignoring parent of "
- "clone with overlap 0\n");
+ rbd_warn(rbd_dev, "ignoring parent with overlap 0");
}
}
out:
@@ -4279,18 +4312,38 @@ static u64 rbd_snap_id_by_name(struct rbd_device *rbd_dev, const char *name)
}
/*
- * When an rbd image has a parent image, it is identified by the
- * pool, image, and snapshot ids (not names). This function fills
- * in the names for those ids. (It's OK if we can't figure out the
- * name for an image id, but the pool and snapshot ids should always
- * exist and have names.) All names in an rbd spec are dynamically
- * allocated.
+ * An image being mapped will have everything but the snap id.
+ */
+static int rbd_spec_fill_snap_id(struct rbd_device *rbd_dev)
+{
+ struct rbd_spec *spec = rbd_dev->spec;
+
+ rbd_assert(spec->pool_id != CEPH_NOPOOL && spec->pool_name);
+ rbd_assert(spec->image_id && spec->image_name);
+ rbd_assert(spec->snap_name);
+
+ if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) {
+ u64 snap_id;
+
+ snap_id = rbd_snap_id_by_name(rbd_dev, spec->snap_name);
+ if (snap_id == CEPH_NOSNAP)
+ return -ENOENT;
+
+ spec->snap_id = snap_id;
+ } else {
+ spec->snap_id = CEPH_NOSNAP;
+ }
+
+ return 0;
+}
+
+/*
+ * A parent image will have all ids but none of the names.
*
- * When an image being mapped (not a parent) is probed, we have the
- * pool name and pool id, image name and image id, and the snapshot
- * name. The only thing we're missing is the snapshot id.
+ * All names in an rbd spec are dynamically allocated. It's OK if we
+ * can't figure out the name for an image id.
*/
-static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
+static int rbd_spec_fill_names(struct rbd_device *rbd_dev)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_spec *spec = rbd_dev->spec;
@@ -4299,24 +4352,9 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
const char *snap_name;
int ret;
- /*
- * An image being mapped will have the pool name (etc.), but
- * we need to look up the snapshot id.
- */
- if (spec->pool_name) {
- if (strcmp(spec->snap_name, RBD_SNAP_HEAD_NAME)) {
- u64 snap_id;
-
- snap_id = rbd_snap_id_by_name(rbd_dev, spec->snap_name);
- if (snap_id == CEPH_NOSNAP)
- return -ENOENT;
- spec->snap_id = snap_id;
- } else {
- spec->snap_id = CEPH_NOSNAP;
- }
-
- return 0;
- }
+ rbd_assert(spec->pool_id != CEPH_NOPOOL);
+ rbd_assert(spec->image_id);
+ rbd_assert(spec->snap_id != CEPH_NOSNAP);
/* Get the pool name; we have to make our own copy of this */
@@ -4335,7 +4373,7 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
if (!image_name)
rbd_warn(rbd_dev, "unable to get image name");
- /* Look up the snapshot name, and make a copy */
+ /* Fetch the snapshot name */
snap_name = rbd_snap_name(rbd_dev, spec->snap_id);
if (IS_ERR(snap_name)) {
@@ -4348,10 +4386,10 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
spec->snap_name = snap_name;
return 0;
+
out_err:
kfree(image_name);
kfree(pool_name);
-
return ret;
}
@@ -4483,43 +4521,22 @@ static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
return ret;
}
- /*
- * If the image supports layering, get the parent info. We
- * need to probe the first time regardless. Thereafter we
- * only need to if there's a parent, to see if it has
- * disappeared due to the mapped image getting flattened.
- */
- if (rbd_dev->header.features & RBD_FEATURE_LAYERING &&
- (first_time || rbd_dev->parent_spec)) {
- bool warn;
-
- ret = rbd_dev_v2_parent_info(rbd_dev);
- if (ret)
- return ret;
-
- /*
- * Print a warning if this is the initial probe and
- * the image has a parent. Don't print it if the
- * image now being probed is itself a parent. We
- * can tell at this point because we won't know its
- * pool name yet (just its pool id).
- */
- warn = rbd_dev->parent_spec && rbd_dev->spec->pool_name;
- if (first_time && warn)
- rbd_warn(rbd_dev, "WARNING: kernel layering "
- "is EXPERIMENTAL!");
- }
-
- if (rbd_dev->spec->snap_id == CEPH_NOSNAP)
- if (rbd_dev->mapping.size != rbd_dev->header.image_size)
- rbd_dev->mapping.size = rbd_dev->header.image_size;
-
ret = rbd_dev_v2_snap_context(rbd_dev);
dout("rbd_dev_v2_snap_context returned %d\n", ret);
return ret;
}
+static int rbd_dev_header_info(struct rbd_device *rbd_dev)
+{
+ rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
+
+ if (rbd_dev->image_format == 1)
+ return rbd_dev_v1_header_info(rbd_dev);
+
+ return rbd_dev_v2_header_info(rbd_dev);
+}
+
static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
{
struct device *dev;
@@ -5066,12 +5083,17 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
ret = rbd_dev_mapping_set(rbd_dev);
if (ret)
goto err_out_disk;
+
set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
+ rbd_dev->rq_wq = alloc_workqueue(rbd_dev->disk->disk_name, 0, 0);
+ if (!rbd_dev->rq_wq)
+ goto err_out_mapping;
+
ret = rbd_bus_add_dev(rbd_dev);
if (ret)
- goto err_out_mapping;
+ goto err_out_workqueue;
/* Everything's ready. Announce the disk to the world. */
@@ -5083,6 +5105,9 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
return ret;
+err_out_workqueue:
+ destroy_workqueue(rbd_dev->rq_wq);
+ rbd_dev->rq_wq = NULL;
err_out_mapping:
rbd_dev_mapping_clear(rbd_dev);
err_out_disk:
@@ -5155,8 +5180,6 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
ret = rbd_dev_image_id(rbd_dev);
if (ret)
return ret;
- rbd_assert(rbd_dev->spec->image_id);
- rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
ret = rbd_dev_header_name(rbd_dev);
if (ret)
@@ -5168,25 +5191,45 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
goto out_header_name;
}
- if (rbd_dev->image_format == 1)
- ret = rbd_dev_v1_header_info(rbd_dev);
- else
- ret = rbd_dev_v2_header_info(rbd_dev);
+ ret = rbd_dev_header_info(rbd_dev);
if (ret)
goto err_out_watch;
- ret = rbd_dev_spec_update(rbd_dev);
+ /*
+ * If this image is the one being mapped, we have pool name and
+ * id, image name and id, and snap name - need to fill snap id.
+ * Otherwise this is a parent image, identified by pool, image
+ * and snap ids - need to fill in names for those ids.
+ */
+ if (mapping)
+ ret = rbd_spec_fill_snap_id(rbd_dev);
+ else
+ ret = rbd_spec_fill_names(rbd_dev);
if (ret)
goto err_out_probe;
+ if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
+ ret = rbd_dev_v2_parent_info(rbd_dev);
+ if (ret)
+ goto err_out_probe;
+
+ /*
+ * Need to warn users if this image is the one being
+ * mapped and has a parent.
+ */
+ if (mapping && rbd_dev->parent_spec)
+ rbd_warn(rbd_dev,
+ "WARNING: kernel layering is EXPERIMENTAL!");
+ }
+
ret = rbd_dev_probe_parent(rbd_dev);
if (ret)
goto err_out_probe;
dout("discovered format %u image, header name is %s\n",
rbd_dev->image_format, rbd_dev->header_name);
-
return 0;
+
err_out_probe:
rbd_dev_unprobe(rbd_dev);
err_out_watch:
@@ -5199,9 +5242,6 @@ err_out_format:
rbd_dev->image_format = 0;
kfree(rbd_dev->spec->image_id);
rbd_dev->spec->image_id = NULL;
-
- dout("probe failed, returning %d\n", ret);
-
return ret;
}
@@ -5243,7 +5283,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
/* The ceph file layout needs to fit pool id in 32 bits */
if (spec->pool_id > (u64)U32_MAX) {
- rbd_warn(NULL, "pool id too large (%llu > %u)\n",
+ rbd_warn(NULL, "pool id too large (%llu > %u)",
(unsigned long long)spec->pool_id, U32_MAX);
rc = -EIO;
goto err_out_client;
@@ -5314,6 +5354,7 @@ static void rbd_dev_device_release(struct device *dev)
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+ destroy_workqueue(rbd_dev->rq_wq);
rbd_free_disk(rbd_dev);
clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
rbd_dev_mapping_clear(rbd_dev);
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c
index a8de2eec6ff3..820b4009d5f7 100644
--- a/drivers/block/rsxx/core.c
+++ b/drivers/block/rsxx/core.c
@@ -1137,7 +1137,7 @@ static const struct pci_error_handlers rsxx_err_handler = {
.slot_reset = rsxx_slot_reset,
};
-static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = {
+static const struct pci_device_id rsxx_pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)},
{PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)},
{0,},
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
index 608532d3f8c9..8fcdcfb4b472 100644
--- a/drivers/block/skd_main.c
+++ b/drivers/block/skd_main.c
@@ -4112,16 +4112,14 @@ static int skd_cons_skcomp(struct skd_device *skdev)
skdev->name, __func__, __LINE__,
nbytes, SKD_N_COMPLETION_ENTRY);
- skcomp = pci_alloc_consistent(skdev->pdev, nbytes,
- &skdev->cq_dma_address);
+ skcomp = pci_zalloc_consistent(skdev->pdev, nbytes,
+ &skdev->cq_dma_address);
if (skcomp == NULL) {
rc = -ENOMEM;
goto err_out;
}
- memset(skcomp, 0, nbytes);
-
skdev->skcomp_table = skcomp;
skdev->skerr_table = (struct fit_comp_error_info *)((char *)skcomp +
sizeof(*skcomp) *
@@ -4304,15 +4302,14 @@ static int skd_cons_skspcl(struct skd_device *skdev)
nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
- skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
- &skspcl->mb_dma_address);
+ skspcl->msg_buf =
+ pci_zalloc_consistent(skdev->pdev, nbytes,
+ &skspcl->mb_dma_address);
if (skspcl->msg_buf == NULL) {
rc = -ENOMEM;
goto err_out;
}
- memset(skspcl->msg_buf, 0, nbytes);
-
skspcl->req.sg = kzalloc(sizeof(struct scatterlist) *
SKD_N_SG_PER_SPECIAL, GFP_KERNEL);
if (skspcl->req.sg == NULL) {
@@ -4353,25 +4350,21 @@ static int skd_cons_sksb(struct skd_device *skdev)
nbytes = SKD_N_INTERNAL_BYTES;
- skspcl->data_buf = pci_alloc_consistent(skdev->pdev, nbytes,
- &skspcl->db_dma_address);
+ skspcl->data_buf = pci_zalloc_consistent(skdev->pdev, nbytes,
+ &skspcl->db_dma_address);
if (skspcl->data_buf == NULL) {
rc = -ENOMEM;
goto err_out;
}
- memset(skspcl->data_buf, 0, nbytes);
-
nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
- skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
- &skspcl->mb_dma_address);
+ skspcl->msg_buf = pci_zalloc_consistent(skdev->pdev, nbytes,
+ &skspcl->mb_dma_address);
if (skspcl->msg_buf == NULL) {
rc = -ENOMEM;
goto err_out;
}
- memset(skspcl->msg_buf, 0, nbytes);
-
skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1,
&skspcl->req.sksg_dma_address);
if (skspcl->req.sksg_list == NULL) {
@@ -4773,7 +4766,7 @@ static const struct block_device_operations skd_blockdev_ops = {
*****************************************************************************
*/
-static DEFINE_PCI_DEVICE_TABLE(skd_pci_tbl) = {
+static const struct pci_device_id skd_pci_tbl[] = {
{ PCI_VENDOR_ID_STEC, PCI_DEVICE_ID_S1120,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
{ 0 } /* terminate list */
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index f63d358f3d93..0a581400de0f 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -15,17 +15,22 @@
#include <linux/numa.h>
#define PART_BITS 4
+#define VQ_NAME_LEN 16
static int major;
static DEFINE_IDA(vd_index_ida);
static struct workqueue_struct *virtblk_wq;
+struct virtio_blk_vq {
+ struct virtqueue *vq;
+ spinlock_t lock;
+ char name[VQ_NAME_LEN];
+} ____cacheline_aligned_in_smp;
+
struct virtio_blk
{
struct virtio_device *vdev;
- struct virtqueue *vq;
- spinlock_t vq_lock;
/* The disk structure for the kernel. */
struct gendisk *disk;
@@ -47,6 +52,10 @@ struct virtio_blk
/* Ida index - used to track minor number allocations. */
int index;
+
+ /* num of vqs */
+ int num_vqs;
+ struct virtio_blk_vq *vqs;
};
struct virtblk_req
@@ -133,14 +142,15 @@ static void virtblk_done(struct virtqueue *vq)
{
struct virtio_blk *vblk = vq->vdev->priv;
bool req_done = false;
+ int qid = vq->index;
struct virtblk_req *vbr;
unsigned long flags;
unsigned int len;
- spin_lock_irqsave(&vblk->vq_lock, flags);
+ spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
do {
virtqueue_disable_cb(vq);
- while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
+ while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
blk_mq_complete_request(vbr->req);
req_done = true;
}
@@ -151,7 +161,7 @@ static void virtblk_done(struct virtqueue *vq)
/* In case queue is stopped waiting for more buffers. */
if (req_done)
blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
}
static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
@@ -160,6 +170,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
unsigned long flags;
unsigned int num;
+ int qid = hctx->queue_num;
const bool last = (req->cmd_flags & REQ_END) != 0;
int err;
bool notify = false;
@@ -202,12 +213,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
}
- spin_lock_irqsave(&vblk->vq_lock, flags);
- err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num);
+ spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
+ err = __virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
if (err) {
- virtqueue_kick(vblk->vq);
+ virtqueue_kick(vblk->vqs[qid].vq);
blk_mq_stop_hw_queue(hctx);
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
/* Out of mem doesn't actually happen, since we fall back
* to direct descriptors */
if (err == -ENOMEM || err == -ENOSPC)
@@ -215,12 +226,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
return BLK_MQ_RQ_QUEUE_ERROR;
}
- if (last && virtqueue_kick_prepare(vblk->vq))
+ if (last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
notify = true;
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
if (notify)
- virtqueue_notify(vblk->vq);
+ virtqueue_notify(vblk->vqs[qid].vq);
return BLK_MQ_RQ_QUEUE_OK;
}
@@ -377,12 +388,64 @@ static void virtblk_config_changed(struct virtio_device *vdev)
static int init_vq(struct virtio_blk *vblk)
{
int err = 0;
+ int i;
+ vq_callback_t **callbacks;
+ const char **names;
+ struct virtqueue **vqs;
+ unsigned short num_vqs;
+ struct virtio_device *vdev = vblk->vdev;
+
+ err = virtio_cread_feature(vdev, VIRTIO_BLK_F_MQ,
+ struct virtio_blk_config, num_queues,
+ &num_vqs);
+ if (err)
+ num_vqs = 1;
+
+ vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL);
+ if (!vblk->vqs) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL);
+ if (!names)
+ goto err_names;
+
+ callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL);
+ if (!callbacks)
+ goto err_callbacks;
+
+ vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL);
+ if (!vqs)
+ goto err_vqs;
- /* We expect one virtqueue, for output. */
- vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
- if (IS_ERR(vblk->vq))
- err = PTR_ERR(vblk->vq);
+ for (i = 0; i < num_vqs; i++) {
+ callbacks[i] = virtblk_done;
+ snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req.%d", i);
+ names[i] = vblk->vqs[i].name;
+ }
+
+ /* Discover virtqueues and write information to configuration. */
+ err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names);
+ if (err)
+ goto err_find_vqs;
+ for (i = 0; i < num_vqs; i++) {
+ spin_lock_init(&vblk->vqs[i].lock);
+ vblk->vqs[i].vq = vqs[i];
+ }
+ vblk->num_vqs = num_vqs;
+
+ err_find_vqs:
+ kfree(vqs);
+ err_vqs:
+ kfree(callbacks);
+ err_callbacks:
+ kfree(names);
+ err_names:
+ if (err)
+ kfree(vblk->vqs);
+ out:
return err;
}
@@ -551,7 +614,6 @@ static int virtblk_probe(struct virtio_device *vdev)
err = init_vq(vblk);
if (err)
goto out_free_vblk;
- spin_lock_init(&vblk->vq_lock);
/* FIXME: How many partitions? How long is a piece of string? */
vblk->disk = alloc_disk(1 << PART_BITS);
@@ -562,7 +624,7 @@ static int virtblk_probe(struct virtio_device *vdev)
/* Default queue sizing is to fill the ring. */
if (!virtblk_queue_depth) {
- virtblk_queue_depth = vblk->vq->num_free;
+ virtblk_queue_depth = vblk->vqs[0].vq->num_free;
/* ... but without indirect descs, we use 2 descs per req */
if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
virtblk_queue_depth /= 2;
@@ -570,7 +632,6 @@ static int virtblk_probe(struct virtio_device *vdev)
memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
vblk->tag_set.ops = &virtio_mq_ops;
- vblk->tag_set.nr_hw_queues = 1;
vblk->tag_set.queue_depth = virtblk_queue_depth;
vblk->tag_set.numa_node = NUMA_NO_NODE;
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
@@ -578,6 +639,7 @@ static int virtblk_probe(struct virtio_device *vdev)
sizeof(struct virtblk_req) +
sizeof(struct scatterlist) * sg_elems;
vblk->tag_set.driver_data = vblk;
+ vblk->tag_set.nr_hw_queues = vblk->num_vqs;
err = blk_mq_alloc_tag_set(&vblk->tag_set);
if (err)
@@ -727,6 +789,7 @@ static void virtblk_remove(struct virtio_device *vdev)
refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
put_disk(vblk->disk);
vdev->config->del_vqs(vdev);
+ kfree(vblk->vqs);
kfree(vblk);
/* Only free device id if we don't have any users */
@@ -777,7 +840,8 @@ static const struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
- VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
+ VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
+ VIRTIO_BLK_F_MQ,
};
static struct virtio_driver virtio_blk = {
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 36e54be402df..dfa4024c448a 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -183,19 +183,32 @@ static ssize_t comp_algorithm_store(struct device *dev,
static int zram_test_flag(struct zram_meta *meta, u32 index,
enum zram_pageflags flag)
{
- return meta->table[index].flags & BIT(flag);
+ return meta->table[index].value & BIT(flag);
}
static void zram_set_flag(struct zram_meta *meta, u32 index,
enum zram_pageflags flag)
{
- meta->table[index].flags |= BIT(flag);
+ meta->table[index].value |= BIT(flag);
}
static void zram_clear_flag(struct zram_meta *meta, u32 index,
enum zram_pageflags flag)
{
- meta->table[index].flags &= ~BIT(flag);
+ meta->table[index].value &= ~BIT(flag);
+}
+
+static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
+{
+ return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+}
+
+static void zram_set_obj_size(struct zram_meta *meta,
+ u32 index, size_t size)
+{
+ unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
+
+ meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
}
static inline int is_partial_io(struct bio_vec *bvec)
@@ -255,7 +268,6 @@ static struct zram_meta *zram_meta_alloc(u64 disksize)
goto free_table;
}
- rwlock_init(&meta->tb_lock);
return meta;
free_table:
@@ -304,7 +316,12 @@ static void handle_zero_page(struct bio_vec *bvec)
flush_dcache_page(page);
}
-/* NOTE: caller should hold meta->tb_lock with write-side */
+
+/*
+ * To protect concurrent access to the same index entry,
+ * caller should hold this table index entry's bit_spinlock to
+ * indicate this index entry is accessing.
+ */
static void zram_free_page(struct zram *zram, size_t index)
{
struct zram_meta *meta = zram->meta;
@@ -324,11 +341,12 @@ static void zram_free_page(struct zram *zram, size_t index)
zs_free(meta->mem_pool, handle);
- atomic64_sub(meta->table[index].size, &zram->stats.compr_data_size);
+ atomic64_sub(zram_get_obj_size(meta, index),
+ &zram->stats.compr_data_size);
atomic64_dec(&zram->stats.pages_stored);
meta->table[index].handle = 0;
- meta->table[index].size = 0;
+ zram_set_obj_size(meta, index, 0);
}
static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
@@ -337,14 +355,14 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
unsigned char *cmem;
struct zram_meta *meta = zram->meta;
unsigned long handle;
- u16 size;
+ size_t size;
- read_lock(&meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
handle = meta->table[index].handle;
- size = meta->table[index].size;
+ size = zram_get_obj_size(meta, index);
if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
- read_unlock(&meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
clear_page(mem);
return 0;
}
@@ -355,7 +373,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
else
ret = zcomp_decompress(zram->comp, cmem, size, mem);
zs_unmap_object(meta->mem_pool, handle);
- read_unlock(&meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
/* Should NEVER happen. Return bio error if it does. */
if (unlikely(ret)) {
@@ -376,14 +394,14 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
struct zram_meta *meta = zram->meta;
page = bvec->bv_page;
- read_lock(&meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
if (unlikely(!meta->table[index].handle) ||
zram_test_flag(meta, index, ZRAM_ZERO)) {
- read_unlock(&meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
handle_zero_page(bvec);
return 0;
}
- read_unlock(&meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
if (is_partial_io(bvec))
/* Use a temporary buffer to decompress the page */
@@ -461,10 +479,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
if (page_zero_filled(uncmem)) {
kunmap_atomic(user_mem);
/* Free memory associated with this sector now. */
- write_lock(&zram->meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
zram_free_page(zram, index);
zram_set_flag(meta, index, ZRAM_ZERO);
- write_unlock(&zram->meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
atomic64_inc(&zram->stats.zero_pages);
ret = 0;
@@ -514,12 +532,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
* Free memory associated with this sector
* before overwriting unused sectors.
*/
- write_lock(&zram->meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
zram_free_page(zram, index);
meta->table[index].handle = handle;
- meta->table[index].size = clen;
- write_unlock(&zram->meta->tb_lock);
+ zram_set_obj_size(meta, index, clen);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
/* Update stats */
atomic64_add(clen, &zram->stats.compr_data_size);
@@ -560,6 +578,7 @@ static void zram_bio_discard(struct zram *zram, u32 index,
int offset, struct bio *bio)
{
size_t n = bio->bi_iter.bi_size;
+ struct zram_meta *meta = zram->meta;
/*
* zram manages data in physical block size units. Because logical block
@@ -580,13 +599,9 @@ static void zram_bio_discard(struct zram *zram, u32 index,
}
while (n >= PAGE_SIZE) {
- /*
- * Discard request can be large so the lock hold times could be
- * lengthy. So take the lock once per page.
- */
- write_lock(&zram->meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
zram_free_page(zram, index);
- write_unlock(&zram->meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
index++;
n -= PAGE_SIZE;
}
@@ -821,9 +836,9 @@ static void zram_slot_free_notify(struct block_device *bdev,
zram = bdev->bd_disk->private_data;
meta = zram->meta;
- write_lock(&meta->tb_lock);
+ bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
zram_free_page(zram, index);
- write_unlock(&meta->tb_lock);
+ bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
atomic64_inc(&zram->stats.notify_free);
}
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 7f21c145e317..5b0afde729cd 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -43,7 +43,6 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
/*-- End of configurable params */
#define SECTOR_SHIFT 9
-#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
#define ZRAM_LOGICAL_BLOCK_SHIFT 12
@@ -51,10 +50,24 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
#define ZRAM_SECTOR_PER_LOGICAL_BLOCK \
(1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
-/* Flags for zram pages (table[page_no].flags) */
+
+/*
+ * The lower ZRAM_FLAG_SHIFT bits of table.value is for
+ * object size (excluding header), the higher bits is for
+ * zram_pageflags.
+ *
+ * zram is mainly used for memory efficiency so we want to keep memory
+ * footprint small so we can squeeze size and flags into a field.
+ * The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header),
+ * the higher bits is for zram_pageflags.
+ */
+#define ZRAM_FLAG_SHIFT 24
+
+/* Flags for zram pages (table[page_no].value) */
enum zram_pageflags {
/* Page consists entirely of zeros */
- ZRAM_ZERO,
+ ZRAM_ZERO = ZRAM_FLAG_SHIFT + 1,
+ ZRAM_ACCESS, /* page in now accessed */
__NR_ZRAM_PAGEFLAGS,
};
@@ -62,11 +75,10 @@ enum zram_pageflags {
/*-- Data structures */
/* Allocated for each disk page */
-struct table {
+struct zram_table_entry {
unsigned long handle;
- u16 size; /* object size (excluding header) */
- u8 flags;
-} __aligned(4);
+ unsigned long value;
+};
struct zram_stats {
atomic64_t compr_data_size; /* compressed size of pages stored */
@@ -81,8 +93,7 @@ struct zram_stats {
};
struct zram_meta {
- rwlock_t tb_lock; /* protect table */
- struct table *table;
+ struct zram_table_entry *table;
struct zs_pool *mem_pool;
};
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index f5ce64e03fd7..fa7fd62ddffa 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -30,8 +30,8 @@ config BT_HCIUART
help
Bluetooth HCI UART driver.
This driver is required if you want to use Bluetooth devices with
- serial port interface. You will also need this driver if you have
- UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
+ serial port interface. You will also need this driver if you have
+ UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
adapter and BrainBoxes Bluetooth PC Card.
Say Y here to compile support for Bluetooth UART devices into the
@@ -41,9 +41,9 @@ config BT_HCIUART_H4
bool "UART (H4) protocol support"
depends on BT_HCIUART
help
- UART (H4) is serial protocol for communication between Bluetooth
- device and host. This protocol is required for most Bluetooth devices
- with UART interface, including PCMCIA and CF cards.
+ UART (H4) is serial protocol for communication between Bluetooth
+ device and host. This protocol is required for most Bluetooth devices
+ with UART interface, including PCMCIA and CF cards.
Say Y here to compile support for HCI UART (H4) protocol.
@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP
depends on BT_HCIUART
select BITREVERSE
help
- BCSP (BlueCore Serial Protocol) is serial protocol for communication
+ BCSP (BlueCore Serial Protocol) is serial protocol for communication
between Bluetooth device and host. This protocol is required for non
USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
CF cards.
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index f50dffc0374f..a0d7355ef127 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -27,6 +27,7 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/usb.h>
+#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#define VERSION "1.0"
@@ -50,12 +51,12 @@
#define ATH3K_NAME_LEN 0xFF
struct ath3k_version {
- unsigned int rom_version;
- unsigned int build_version;
- unsigned int ram_version;
- unsigned char ref_clock;
- unsigned char reserved[0x07];
-};
+ __le32 rom_version;
+ __le32 build_version;
+ __le32 ram_version;
+ __u8 ref_clock;
+ __u8 reserved[7];
+} __packed;
static const struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 */
@@ -103,6 +104,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) },
+ { USB_DEVICE(0x13d3, 0x3432) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -152,6 +154,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
@@ -288,10 +291,10 @@ static int ath3k_load_fwfile(struct usb_device *udev,
sent += size;
count -= size;
+ pipe = usb_sndbulkpipe(udev, 0x02);
+
while (count) {
size = min_t(uint, count, BULK_SIZE);
- pipe = usb_sndbulkpipe(udev, 0x02);
-
memcpy(send_buf, firmware->data + sent, size);
err = usb_bulk_msg(udev, pipe, send_buf, size,
@@ -347,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev)
unsigned char fw_state;
char filename[ATH3K_NAME_LEN] = {0};
const struct firmware *firmware;
- struct ath3k_version fw_version, pt_version;
+ struct ath3k_version fw_version;
+ __u32 pt_rom_version, pt_build_version;
int ret;
ret = ath3k_get_state(udev, &fw_state);
@@ -368,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev)
}
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
- le32_to_cpu(fw_version.rom_version));
+ le32_to_cpu(fw_version.rom_version));
ret = request_firmware(&firmware, filename, &udev->dev);
if (ret < 0) {
@@ -376,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev)
return ret;
}
- pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
- pt_version.build_version = *(int *)
- (firmware->data + firmware->size - 4);
+ pt_rom_version = get_unaligned_le32(firmware->data +
+ firmware->size - 8);
+ pt_build_version = get_unaligned_le32(firmware->data +
+ firmware->size - 4);
- if ((pt_version.rom_version != fw_version.rom_version) ||
- (pt_version.build_version <= fw_version.build_version)) {
+ if (pt_rom_version != le32_to_cpu(fw_version.rom_version) ||
+ pt_build_version <= le32_to_cpu(fw_version.build_version)) {
BT_ERR("Patch file version did not match with firmware");
release_firmware(firmware);
return -EINVAL;
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index dc79f88f8717..38ad66289ad6 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -68,6 +68,7 @@ struct btmrvl_adapter {
u8 hs_state;
u8 wakeup_tries;
wait_queue_head_t cmd_wait_q;
+ wait_queue_head_t event_hs_wait_q;
u8 cmd_complete;
bool is_suspended;
};
@@ -89,6 +90,8 @@ struct btmrvl_private {
#define MRVL_VENDOR_PKT 0xFE
/* Vendor specific Bluetooth commands */
+#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03
+#define BT_CMD_SET_BDADDR 0xFC22
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A
@@ -143,6 +146,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);
+int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index e9dbddb0b8f1..1d7db2064889 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
adapter->hs_state = HS_ACTIVATED;
if (adapter->psmode)
adapter->ps_state = PS_SLEEP;
+ wake_up_interruptible(&adapter->event_hs_wait_q);
BT_DBG("HS ACTIVATED!");
} else {
BT_DBG("HS Enable failed");
@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd)
}
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
+int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd)
+{
+ struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
+ int ret;
+
+ if (!card->support_pscan_win_report)
+ return 0;
+
+ ret = btmrvl_send_sync_cmd(priv, BT_CMD_PSCAN_WIN_REPORT_ENABLE,
+ &subcmd, 1);
+ if (ret)
+ BT_ERR("PSCAN_WIN_REPORT_ENABLE command failed: %#x", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(btmrvl_pscan_window_reporting);
+
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
{
int ret;
@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
int btmrvl_enable_hs(struct btmrvl_private *priv)
{
+ struct btmrvl_adapter *adapter = priv->adapter;
int ret;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
- if (ret)
+ if (ret) {
BT_ERR("Host sleep enable command failed\n");
+ return ret;
+ }
+
+ ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
+ adapter->hs_state,
+ msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
+ if (ret < 0) {
+ BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
+ ret, adapter->hs_state, adapter->ps_state,
+ adapter->wakeup_tries);
+ } else if (!ret) {
+ BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state,
+ adapter->ps_state, adapter->wakeup_tries);
+ ret = -ETIMEDOUT;
+ } else {
+ BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state,
+ adapter->ps_state, adapter->wakeup_tries);
+ ret = 0;
+ }
return ret;
}
@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv)
}
init_waitqueue_head(&priv->adapter->cmd_wait_q);
+ init_waitqueue_head(&priv->adapter->event_hs_wait_q);
}
static void btmrvl_free_adapter(struct btmrvl_private *priv)
@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *hdev)
btmrvl_cal_data_dt(priv);
+ btmrvl_pscan_window_reporting(priv, 0x01);
+
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
@@ -498,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *hdev)
return 0;
}
+static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ long ret;
+ u8 buf[8];
+
+ buf[0] = MRVL_VENDOR_PKT;
+ buf[1] = sizeof(bdaddr_t);
+ memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: changing btmrvl device address failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
@@ -591,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
hdev->flush = btmrvl_flush;
hdev->send = btmrvl_send_frame;
hdev->setup = btmrvl_setup;
+ hdev->set_bdaddr = btmrvl_set_bdaddr;
hdev->dev_type = priv->btmrvl_dev.dev_type;
@@ -645,12 +710,17 @@ struct btmrvl_private *btmrvl_add_card(void *card)
init_waitqueue_head(&priv->main_thread.wait_q);
priv->main_thread.task = kthread_run(btmrvl_service_main_thread,
&priv->main_thread, "btmrvl_main_service");
+ if (IS_ERR(priv->main_thread.task))
+ goto err_thread;
priv->btmrvl_dev.card = card;
priv->btmrvl_dev.tx_dnld_rdy = true;
return priv;
+err_thread:
+ btmrvl_free_adapter(priv);
+
err_adapter:
kfree(priv);
@@ -666,6 +736,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
hdev = priv->btmrvl_dev.hcidev;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
+ wake_up_interruptible(&priv->adapter->event_hs_wait_q);
kthread_stop(priv->main_thread.task);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 9dedca516ff5..3e683b153259 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
.reg = &btmrvl_reg_8688,
+ .support_pscan_win_report = false,
.sd_blksz_fw_dl = 64,
};
@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin",
.reg = &btmrvl_reg_87xx,
+ .support_pscan_win_report = false,
.sd_blksz_fw_dl = 256,
};
@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
.reg = &btmrvl_reg_87xx,
+ .support_pscan_win_report = false,
.sd_blksz_fw_dl = 256,
};
@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx,
+ .support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
};
@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
card->firmware = data->firmware;
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
+ card->support_pscan_win_report = data->support_pscan_win_report;
}
if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1164,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
priv = card->priv;
+ hcidev = priv->btmrvl_dev.hcidev;
+ BT_DBG("%s: SDIO suspend", hcidev->name);
+ hci_suspend_dev(hcidev);
+ skb_queue_purge(&priv->adapter->tx_queue);
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
@@ -1171,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev)
return -EBUSY;
}
}
- hcidev = priv->btmrvl_dev.hcidev;
- BT_DBG("%s: SDIO suspend", hcidev->name);
- hci_suspend_dev(hcidev);
- skb_queue_purge(&priv->adapter->tx_queue);
priv->adapter->is_suspended = true;
@@ -1216,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev)
return 0;
}
- priv->adapter->is_suspended = false;
- hcidev = priv->btmrvl_dev.hcidev;
- BT_DBG("%s: SDIO resume", hcidev->name);
- hci_resume_dev(hcidev);
priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED;
+ hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
+ priv->adapter->is_suspended = false;
+ BT_DBG("%s: SDIO resume", hcidev->name);
+ hci_resume_dev(hcidev);
return 0;
}
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index d4dd3b0fa53d..453559f98a75 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -89,6 +89,7 @@ struct btmrvl_sdio_card {
const char *helper;
const char *firmware;
const struct btmrvl_sdio_card_reg *reg;
+ bool support_pscan_win_report;
u16 sd_blksz_fw_dl;
u8 rx_unit;
struct btmrvl_private *priv;
@@ -98,6 +99,7 @@ struct btmrvl_sdio_device {
const char *helper;
const char *firmware;
const struct btmrvl_sdio_card_reg *reg;
+ const bool support_pscan_win_report;
u16 sd_blksz_fw_dl;
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 6250fc2fb93a..292c38e8aa17 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -30,9 +30,6 @@
#define VERSION "0.6"
-static bool ignore_dga;
-static bool ignore_csr;
-static bool ignore_sniffer;
static bool disable_scofix;
static bool force_scofix;
@@ -49,7 +46,9 @@ static struct usb_driver btusb_driver;
#define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80
#define BTUSB_INTEL 0x100
-#define BTUSB_BCM_PATCHRAM 0x200
+#define BTUSB_INTEL_BOOT 0x200
+#define BTUSB_BCM_PATCHRAM 0x400
+#define BTUSB_MARVELL 0x800
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -115,12 +114,19 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
+ /* ASUSTek Computer - Broadcom based */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
+
/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
/* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
+ /* Intel Bluetooth USB Bootloader (RAM module) */
+ { USB_DEVICE(0x8087, 0x0a5a),
+ .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
+
{ } /* Terminating entry */
};
@@ -175,6 +181,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -228,15 +235,21 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
/* CSR BlueCore Bluetooth Sniffer */
- { USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x0a12, 0x0002),
+ .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Frontline ComProbe Bluetooth Sniffer */
- { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
+ { USB_DEVICE(0x16d3, 0x0002),
+ .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Intel Bluetooth device */
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
+ /* Marvell device */
+ { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
+ { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
+
{ } /* Terminating entry */
};
@@ -1182,6 +1195,51 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
return 0;
}
+#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
+
+static int btusb_check_bdaddr_intel(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ struct hci_rp_read_bd_addr *rp;
+
+ skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s reading Intel device address failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+
+ if (skb->len != sizeof(*rp)) {
+ BT_ERR("%s Intel device address length mismatch", hdev->name);
+ kfree_skb(skb);
+ return -EIO;
+ }
+
+ rp = (struct hci_rp_read_bd_addr *) skb->data;
+ if (rp->status) {
+ BT_ERR("%s Intel device address result failed (%02x)",
+ hdev->name, rp->status);
+ kfree_skb(skb);
+ return -bt_to_errno(rp->status);
+ }
+
+ /* For some Intel based controllers, the default Bluetooth device
+ * address 00:03:19:9E:8B:00 can be found. These controllers are
+ * fully operational, but have the danger of duplicate addresses
+ * and that in turn can cause problems with Bluetooth operation.
+ */
+ if (!bacmp(&rp->bdaddr, BDADDR_INTEL)) {
+ BT_ERR("%s found Intel default device address (%pMR)",
+ hdev->name, &rp->bdaddr);
+ set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int btusb_setup_intel(struct hci_dev *hdev)
{
struct sk_buff *skb;
@@ -1254,6 +1312,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num);
kfree_skb(skb);
+ btusb_check_bdaddr_intel(hdev);
return 0;
}
@@ -1266,6 +1325,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) {
kfree_skb(skb);
+ btusb_check_bdaddr_intel(hdev);
return 0;
}
fw_ptr = fw->data;
@@ -1345,6 +1405,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name);
+ btusb_check_bdaddr_intel(hdev);
return 0;
exit_mfg_disable:
@@ -1359,6 +1420,8 @@ exit_mfg_disable:
kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
+
+ btusb_check_bdaddr_intel(hdev);
return 0;
exit_mfg_deactivate:
@@ -1379,9 +1442,52 @@ exit_mfg_deactivate:
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name);
+ btusb_check_bdaddr_intel(hdev);
+ return 0;
+}
+
+static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ long ret;
+
+ skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: changing Intel device address failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
return 0;
}
+static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
+ const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ u8 buf[8];
+ long ret;
+
+ buf[0] = 0xfe;
+ buf[1] = sizeof(bdaddr_t);
+ memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: changing Marvell device address failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
+#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
+
static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
@@ -1395,6 +1501,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
u16 opcode;
struct sk_buff *skb;
struct hci_rp_read_local_version *ver;
+ struct hci_rp_read_bd_addr *bda;
long ret;
snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
@@ -1404,8 +1511,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
ret = request_firmware(&fw, fw_name, &hdev->dev);
if (ret < 0) {
- BT_INFO("%s: BCM: patch %s not found", hdev->name,
- fw_name);
+ BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
return 0;
}
@@ -1524,12 +1630,67 @@ reset_fw:
ver->lmp_ver, ver->lmp_subver);
kfree_skb(skb);
+ /* Read BD Address */
+ skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)",
+ hdev->name, ret);
+ goto done;
+ }
+
+ if (skb->len != sizeof(*bda)) {
+ BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch",
+ hdev->name);
+ kfree_skb(skb);
+ ret = -EIO;
+ goto done;
+ }
+
+ bda = (struct hci_rp_read_bd_addr *) skb->data;
+ if (bda->status) {
+ BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)",
+ hdev->name, bda->status);
+ kfree_skb(skb);
+ ret = -bt_to_errno(bda->status);
+ goto done;
+ }
+
+ /* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
+ * with no configured address.
+ */
+ if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) {
+ BT_INFO("%s: BCM: using default device address (%pMR)",
+ hdev->name, &bda->bdaddr);
+ set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+ }
+
+ kfree_skb(skb);
+
done:
release_firmware(fw);
return ret;
}
+static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ long ret;
+
+ skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ BT_ERR("%s: BCM: Change address command failed (%ld)",
+ hdev->name, ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1554,15 +1715,6 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE)
return -ENODEV;
- if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
- return -ENODEV;
-
- if (ignore_csr && id->driver_info & BTUSB_CSR)
- return -ENODEV;
-
- if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
- return -ENODEV;
-
if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf);
@@ -1635,11 +1787,21 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BCM92035)
hdev->setup = btusb_setup_bcm92035;
- if (id->driver_info & BTUSB_BCM_PATCHRAM)
+ if (id->driver_info & BTUSB_BCM_PATCHRAM) {
hdev->setup = btusb_setup_bcm_patchram;
+ hdev->set_bdaddr = btusb_set_bdaddr_bcm;
+ }
- if (id->driver_info & BTUSB_INTEL)
+ if (id->driver_info & BTUSB_INTEL) {
hdev->setup = btusb_setup_intel;
+ hdev->set_bdaddr = btusb_set_bdaddr_intel;
+ }
+
+ if (id->driver_info & BTUSB_MARVELL)
+ hdev->set_bdaddr = btusb_set_bdaddr_marvell;
+
+ if (id->driver_info & BTUSB_INTEL_BOOT)
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
@@ -1679,8 +1841,18 @@ static int btusb_probe(struct usb_interface *intf,
/* New sniffer firmware has crippled HCI interface */
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+ }
- data->isoc = NULL;
+ if (id->driver_info & BTUSB_INTEL_BOOT) {
+ /* A bug in the bootloader causes that interrupt interface is
+ * only enabled after receiving SetInterface(0, AltSetting=0).
+ */
+ err = usb_set_interface(data->udev, 0, 0);
+ if (err < 0) {
+ BT_ERR("failed to set interface 0, alt 0 %d", err);
+ hci_free_dev(hdev);
+ return err;
+ }
}
if (data->isoc) {
@@ -1845,15 +2017,6 @@ static struct usb_driver btusb_driver = {
module_usb_driver(btusb_driver);
-module_param(ignore_dga, bool, 0644);
-MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
-
-module_param(ignore_csr, bool, 0644);
-MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
-
-module_param(ignore_sniffer, bool, 0644);
-MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
-
module_param(disable_scofix, bool, 0644);
MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index fede8ca7147c..caacb422995d 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
static int h5_rx_crc(struct hci_uart *hu, unsigned char c)
{
- struct h5 *h5 = hu->priv;
-
h5_complete_rx_pkt(hu);
- h5_reset_rx(h5);
return 0;
}
@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart *hu, unsigned char c)
h5->rx_pending = 2;
} else {
h5_complete_rx_pkt(hu);
- h5_reset_rx(h5);
}
return 0;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index e00f8f5b5c8e..dc487b5d1156 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+ if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
+ set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
+
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
@@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
return 0;
}
+static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
+{
+ unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) |
+ BIT(HCI_UART_RESET_ON_INIT) |
+ BIT(HCI_UART_CREATE_AMP) |
+ BIT(HCI_UART_INIT_PENDING) |
+ BIT(HCI_UART_EXT_CONFIG);
+
+ if ((flags & ~valid_flags))
+ return -EINVAL;
+
+ hu->hdev_flags = flags;
+
+ return 0;
+}
+
/* hci_uart_tty_ioctl()
*
* Process IOCTL system call for the tty device.
@@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return -EUNATCH;
case HCIUARTGETDEVICE:
- if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+ if (test_bit(HCI_UART_REGISTERED, &hu->flags))
return hu->hdev->id;
return -EUNATCH;
case HCIUARTSETFLAGS:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return -EBUSY;
- hu->hdev_flags = arg;
+ err = hci_uart_set_flags(hu, arg);
+ if (err)
+ return err;
break;
case HCIUARTGETFLAGS:
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 12df101ca942..247488edcbf9 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -48,6 +48,7 @@
#define HCI_UART_RESET_ON_INIT 1
#define HCI_UART_CREATE_AMP 2
#define HCI_UART_INIT_PENDING 3
+#define HCI_UART_EXT_CONFIG 4
struct hci_uart;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index add1c6a72063..5bb5872ffee6 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#define VERSION "1.4"
+#define VERSION "1.5"
static bool amp;
@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
-static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
+static int vhci_create_device(struct vhci_data *data, __u8 opcode)
{
struct hci_dev *hdev;
struct sk_buff *skb;
+ __u8 dev_type;
+
+ /* bits 0-1 are dev_type (BR/EDR or AMP) */
+ dev_type = opcode & 0x03;
+
+ if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
+ return -EINVAL;
+
+ /* bits 2-5 are reserved (must be zero) */
+ if (opcode & 0x3c)
+ return -EINVAL;
skb = bt_skb_alloc(4, GFP_KERNEL);
if (!skb)
@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
hdev->flush = vhci_flush;
hdev->send = vhci_send_frame;
+ /* bit 6 is for external configuration */
+ if (opcode & 0x40)
+ set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
+
+ /* bit 7 is for raw device */
+ if (opcode & 0x80)
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
*skb_put(skb, 1) = 0xff;
- *skb_put(skb, 1) = dev_type;
+ *skb_put(skb, 1) = opcode;
put_unaligned_le16(hdev->id, skb_put(skb, 2));
skb_queue_tail(&data->readq, skb);
@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
{
size_t len = iov_length(iov, count);
struct sk_buff *skb;
- __u8 pkt_type, dev_type;
+ __u8 pkt_type, opcode;
unsigned long i;
int ret;
@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
cancel_delayed_work_sync(&data->open_timeout);
- dev_type = *((__u8 *) skb->data);
+ opcode = *((__u8 *) skb->data);
skb_pull(skb, 1);
if (skb->len > 0) {
@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
kfree_skb(skb);
- if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
- return -EINVAL;
-
- ret = vhci_create_device(data, dev_type);
+ ret = vhci_create_device(data, opcode);
break;
default:
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 1f37d9870e7a..603eb1be4f6a 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -50,6 +50,14 @@ config ARM_CCI
Driver supporting the CCI cache coherent interconnect for ARM
platforms.
+config ARM_CCN
+ bool "ARM CCN driver support"
+ depends on ARM || ARM64
+ depends on PERF_EVENTS
+ help
+ PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
+ interconnect.
+
config VEXPRESS_CONFIG
bool "Versatile Express configuration bus"
default y if ARCH_VEXPRESS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 6a4ea7e4af1a..2973c18cbcc2 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -9,7 +9,9 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
# Interconnect bus driver for OMAP SoCs.
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
-# CCI cache coherent interconnect for ARM platforms
+
+# Interconnect bus drivers for ARM platforms
obj-$(CONFIG_ARM_CCI) += arm-cci.o
+obj-$(CONFIG_ARM_CCN) += arm-ccn.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 5a86da97a70b..7af78df241f2 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -397,7 +397,8 @@ static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
hw_counter = &event->hw;
/* Did this counter overflow? */
- if (!pmu_read_register(idx, CCI_PMU_OVRFLW) & CCI_PMU_OVRFLW_FLAG)
+ if (!(pmu_read_register(idx, CCI_PMU_OVRFLW) &
+ CCI_PMU_OVRFLW_FLAG))
continue;
pmu_write_register(CCI_PMU_OVRFLW_FLAG, idx, CCI_PMU_OVRFLW);
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
new file mode 100644
index 000000000000..3266f8ff9311
--- /dev/null
+++ b/drivers/bus/arm-ccn.c
@@ -0,0 +1,1391 @@
+/*
+ * 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) 2014 ARM Limited
+ */
+
+#include <linux/ctype.h>
+#include <linux/hrtimer.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define CCN_NUM_XP_PORTS 2
+#define CCN_NUM_VCS 4
+#define CCN_NUM_REGIONS 256
+#define CCN_REGION_SIZE 0x10000
+
+#define CCN_ALL_OLY_ID 0xff00
+#define CCN_ALL_OLY_ID__OLY_ID__SHIFT 0
+#define CCN_ALL_OLY_ID__OLY_ID__MASK 0x1f
+#define CCN_ALL_OLY_ID__NODE_ID__SHIFT 8
+#define CCN_ALL_OLY_ID__NODE_ID__MASK 0x3f
+
+#define CCN_MN_ERRINT_STATUS 0x0008
+#define CCN_MN_ERRINT_STATUS__INTREQ__DESSERT 0x11
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__ENABLE 0x02
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLED 0x20
+#define CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE 0x22
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_ENABLE 0x04
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLED 0x40
+#define CCN_MN_ERRINT_STATUS__CORRECTED_ERRORS_DISABLE 0x44
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE 0x08
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED 0x80
+#define CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE 0x88
+#define CCN_MN_OLY_COMP_LIST_63_0 0x01e0
+#define CCN_MN_ERR_SIG_VAL_63_0 0x0300
+#define CCN_MN_ERR_SIG_VAL_63_0__DT (1 << 1)
+
+#define CCN_DT_ACTIVE_DSM 0x0000
+#define CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(n) ((n) * 8)
+#define CCN_DT_ACTIVE_DSM__DSM_ID__MASK 0xff
+#define CCN_DT_CTL 0x0028
+#define CCN_DT_CTL__DT_EN (1 << 0)
+#define CCN_DT_PMEVCNT(n) (0x0100 + (n) * 0x8)
+#define CCN_DT_PMCCNTR 0x0140
+#define CCN_DT_PMCCNTRSR 0x0190
+#define CCN_DT_PMOVSR 0x0198
+#define CCN_DT_PMOVSR_CLR 0x01a0
+#define CCN_DT_PMCR 0x01a8
+#define CCN_DT_PMCR__OVFL_INTR_EN (1 << 6)
+#define CCN_DT_PMCR__PMU_EN (1 << 0)
+#define CCN_DT_PMSR 0x01b0
+#define CCN_DT_PMSR_REQ 0x01b8
+#define CCN_DT_PMSR_CLR 0x01c0
+
+#define CCN_HNF_PMU_EVENT_SEL 0x0600
+#define CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_HNF_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_XP_DT_CONFIG 0x0300
+#define CCN_XP_DT_CONFIG__DT_CFG__SHIFT(n) ((n) * 4)
+#define CCN_XP_DT_CONFIG__DT_CFG__MASK 0xf
+#define CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH 0x0
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT_0_OR_1 0x1
+#define CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(n) (0x2 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(n) (0x4 + (n))
+#define CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(d, n) (0x8 + (d) * 4 + (n))
+#define CCN_XP_DT_INTERFACE_SEL 0x0308
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(n) (0 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK 0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(n) (1 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK 0x1
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(n) (2 + (n) * 8)
+#define CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK 0x3
+#define CCN_XP_DT_CMP_VAL_L(n) (0x0310 + (n) * 0x40)
+#define CCN_XP_DT_CMP_VAL_H(n) (0x0318 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_L(n) (0x0320 + (n) * 0x40)
+#define CCN_XP_DT_CMP_MASK_H(n) (0x0328 + (n) * 0x40)
+#define CCN_XP_DT_CONTROL 0x0370
+#define CCN_XP_DT_CONTROL__DT_ENABLE (1 << 0)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(n) (12 + (n) * 4)
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__MASK 0xf
+#define CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS 0xf
+#define CCN_XP_PMU_EVENT_SEL 0x0600
+#define CCN_XP_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 7)
+#define CCN_XP_PMU_EVENT_SEL__ID__MASK 0x3f
+
+#define CCN_SBAS_PMU_EVENT_SEL 0x0600
+#define CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_SBAS_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_RNI_PMU_EVENT_SEL 0x0600
+#define CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(n) ((n) * 4)
+#define CCN_RNI_PMU_EVENT_SEL__ID__MASK 0xf
+
+#define CCN_TYPE_MN 0x01
+#define CCN_TYPE_DT 0x02
+#define CCN_TYPE_HNF 0x04
+#define CCN_TYPE_HNI 0x05
+#define CCN_TYPE_XP 0x08
+#define CCN_TYPE_SBSX 0x0c
+#define CCN_TYPE_SBAS 0x10
+#define CCN_TYPE_RNI_1P 0x14
+#define CCN_TYPE_RNI_2P 0x15
+#define CCN_TYPE_RNI_3P 0x16
+#define CCN_TYPE_RND_1P 0x18 /* RN-D = RN-I + DVM */
+#define CCN_TYPE_RND_2P 0x19
+#define CCN_TYPE_RND_3P 0x1a
+#define CCN_TYPE_CYCLES 0xff /* Pseudotype */
+
+#define CCN_EVENT_WATCHPOINT 0xfe /* Pseudoevent */
+
+#define CCN_NUM_PMU_EVENTS 4
+#define CCN_NUM_XP_WATCHPOINTS 2 /* See DT.dbg_id.num_watchpoints */
+#define CCN_NUM_PMU_EVENT_COUNTERS 8 /* See DT.dbg_id.num_pmucntr */
+#define CCN_IDX_PMU_CYCLE_COUNTER CCN_NUM_PMU_EVENT_COUNTERS
+
+#define CCN_NUM_PREDEFINED_MASKS 4
+#define CCN_IDX_MASK_ANY (CCN_NUM_PMU_EVENT_COUNTERS + 0)
+#define CCN_IDX_MASK_EXACT (CCN_NUM_PMU_EVENT_COUNTERS + 1)
+#define CCN_IDX_MASK_ORDER (CCN_NUM_PMU_EVENT_COUNTERS + 2)
+#define CCN_IDX_MASK_OPCODE (CCN_NUM_PMU_EVENT_COUNTERS + 3)
+
+struct arm_ccn_component {
+ void __iomem *base;
+ u32 type;
+
+ DECLARE_BITMAP(pmu_events_mask, CCN_NUM_PMU_EVENTS);
+ union {
+ struct {
+ DECLARE_BITMAP(dt_cmp_mask, CCN_NUM_XP_WATCHPOINTS);
+ } xp;
+ };
+};
+
+#define pmu_to_arm_ccn(_pmu) container_of(container_of(_pmu, \
+ struct arm_ccn_dt, pmu), struct arm_ccn, dt)
+
+struct arm_ccn_dt {
+ int id;
+ void __iomem *base;
+
+ spinlock_t config_lock;
+
+ DECLARE_BITMAP(pmu_counters_mask, CCN_NUM_PMU_EVENT_COUNTERS + 1);
+ struct {
+ struct arm_ccn_component *source;
+ struct perf_event *event;
+ } pmu_counters[CCN_NUM_PMU_EVENT_COUNTERS + 1];
+
+ struct {
+ u64 l, h;
+ } cmp_mask[CCN_NUM_PMU_EVENT_COUNTERS + CCN_NUM_PREDEFINED_MASKS];
+
+ struct hrtimer hrtimer;
+
+ struct pmu pmu;
+};
+
+struct arm_ccn {
+ struct device *dev;
+ void __iomem *base;
+ unsigned irq_used:1;
+ unsigned sbas_present:1;
+ unsigned sbsx_present:1;
+
+ int num_nodes;
+ struct arm_ccn_component *node;
+
+ int num_xps;
+ struct arm_ccn_component *xp;
+
+ struct arm_ccn_dt dt;
+};
+
+
+static int arm_ccn_node_to_xp(int node)
+{
+ return node / CCN_NUM_XP_PORTS;
+}
+
+static int arm_ccn_node_to_xp_port(int node)
+{
+ return node % CCN_NUM_XP_PORTS;
+}
+
+
+/*
+ * Bit shifts and masks in these defines must be kept in sync with
+ * arm_ccn_pmu_config_set() and CCN_FORMAT_ATTRs below!
+ */
+#define CCN_CONFIG_NODE(_config) (((_config) >> 0) & 0xff)
+#define CCN_CONFIG_XP(_config) (((_config) >> 0) & 0xff)
+#define CCN_CONFIG_TYPE(_config) (((_config) >> 8) & 0xff)
+#define CCN_CONFIG_EVENT(_config) (((_config) >> 16) & 0xff)
+#define CCN_CONFIG_PORT(_config) (((_config) >> 24) & 0x3)
+#define CCN_CONFIG_VC(_config) (((_config) >> 26) & 0x7)
+#define CCN_CONFIG_DIR(_config) (((_config) >> 29) & 0x1)
+#define CCN_CONFIG_MASK(_config) (((_config) >> 30) & 0xf)
+
+static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port)
+{
+ *config &= ~((0xff << 0) | (0xff << 8) | (0xff << 24));
+ *config |= (node_xp << 0) | (type << 8) | (port << 24);
+}
+
+static ssize_t arm_ccn_pmu_format_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dev_ext_attribute *ea = container_of(attr,
+ struct dev_ext_attribute, attr);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)ea->var);
+}
+
+#define CCN_FORMAT_ATTR(_name, _config) \
+ struct dev_ext_attribute arm_ccn_pmu_format_attr_##_name = \
+ { __ATTR(_name, S_IRUGO, arm_ccn_pmu_format_show, \
+ NULL), _config }
+
+static CCN_FORMAT_ATTR(node, "config:0-7");
+static CCN_FORMAT_ATTR(xp, "config:0-7");
+static CCN_FORMAT_ATTR(type, "config:8-15");
+static CCN_FORMAT_ATTR(event, "config:16-23");
+static CCN_FORMAT_ATTR(port, "config:24-25");
+static CCN_FORMAT_ATTR(vc, "config:26-28");
+static CCN_FORMAT_ATTR(dir, "config:29-29");
+static CCN_FORMAT_ATTR(mask, "config:30-33");
+static CCN_FORMAT_ATTR(cmp_l, "config1:0-62");
+static CCN_FORMAT_ATTR(cmp_h, "config2:0-59");
+
+static struct attribute *arm_ccn_pmu_format_attrs[] = {
+ &arm_ccn_pmu_format_attr_node.attr.attr,
+ &arm_ccn_pmu_format_attr_xp.attr.attr,
+ &arm_ccn_pmu_format_attr_type.attr.attr,
+ &arm_ccn_pmu_format_attr_event.attr.attr,
+ &arm_ccn_pmu_format_attr_port.attr.attr,
+ &arm_ccn_pmu_format_attr_vc.attr.attr,
+ &arm_ccn_pmu_format_attr_dir.attr.attr,
+ &arm_ccn_pmu_format_attr_mask.attr.attr,
+ &arm_ccn_pmu_format_attr_cmp_l.attr.attr,
+ &arm_ccn_pmu_format_attr_cmp_h.attr.attr,
+ NULL
+};
+
+static struct attribute_group arm_ccn_pmu_format_attr_group = {
+ .name = "format",
+ .attrs = arm_ccn_pmu_format_attrs,
+};
+
+
+struct arm_ccn_pmu_event {
+ struct device_attribute attr;
+ u32 type;
+ u32 event;
+ int num_ports;
+ int num_vcs;
+ const char *def;
+ int mask;
+};
+
+#define CCN_EVENT_ATTR(_name) \
+ __ATTR(_name, S_IRUGO, arm_ccn_pmu_event_show, NULL)
+
+/*
+ * Events defined in TRM for MN, HN-I and SBSX are actually watchpoints set on
+ * their ports in XP they are connected to. For the sake of usability they are
+ * explicitly defined here (and translated into a relevant watchpoint in
+ * arm_ccn_pmu_event_init()) so the user can easily request them without deep
+ * knowledge of the flit format.
+ */
+
+#define CCN_EVENT_MN(_name, _def, _mask) { .attr = CCN_EVENT_ATTR(mn_##_name), \
+ .type = CCN_TYPE_MN, .event = CCN_EVENT_WATCHPOINT, \
+ .num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, \
+ .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNI(_name, _def, _mask) { \
+ .attr = CCN_EVENT_ATTR(hni_##_name), .type = CCN_TYPE_HNI, \
+ .event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+ .num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_SBSX(_name, _def, _mask) { \
+ .attr = CCN_EVENT_ATTR(sbsx_##_name), .type = CCN_TYPE_SBSX, \
+ .event = CCN_EVENT_WATCHPOINT, .num_ports = CCN_NUM_XP_PORTS, \
+ .num_vcs = CCN_NUM_VCS, .def = _def, .mask = _mask, }
+
+#define CCN_EVENT_HNF(_name, _event) { .attr = CCN_EVENT_ATTR(hnf_##_name), \
+ .type = CCN_TYPE_HNF, .event = _event, }
+
+#define CCN_EVENT_XP(_name, _event) { .attr = CCN_EVENT_ATTR(xp_##_name), \
+ .type = CCN_TYPE_XP, .event = _event, \
+ .num_ports = CCN_NUM_XP_PORTS, .num_vcs = CCN_NUM_VCS, }
+
+/*
+ * RN-I & RN-D (RN-D = RN-I + DVM) nodes have different type ID depending
+ * on configuration. One of them is picked to represent the whole group,
+ * as they all share the same event types.
+ */
+#define CCN_EVENT_RNI(_name, _event) { .attr = CCN_EVENT_ATTR(rni_##_name), \
+ .type = CCN_TYPE_RNI_3P, .event = _event, }
+
+#define CCN_EVENT_SBAS(_name, _event) { .attr = CCN_EVENT_ATTR(sbas_##_name), \
+ .type = CCN_TYPE_SBAS, .event = _event, }
+
+#define CCN_EVENT_CYCLES(_name) { .attr = CCN_EVENT_ATTR(_name), \
+ .type = CCN_TYPE_CYCLES }
+
+
+static ssize_t arm_ccn_pmu_event_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct arm_ccn_pmu_event *event = container_of(attr,
+ struct arm_ccn_pmu_event, attr);
+ ssize_t res;
+
+ res = snprintf(buf, PAGE_SIZE, "type=0x%x", event->type);
+ if (event->event)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",event=0x%x",
+ event->event);
+ if (event->def)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",%s",
+ event->def);
+ if (event->mask)
+ res += snprintf(buf + res, PAGE_SIZE - res, ",mask=0x%x",
+ event->mask);
+ res += snprintf(buf + res, PAGE_SIZE - res, "\n");
+
+ return res;
+}
+
+static umode_t arm_ccn_pmu_events_is_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ struct device_attribute *dev_attr = container_of(attr,
+ struct device_attribute, attr);
+ struct arm_ccn_pmu_event *event = container_of(dev_attr,
+ struct arm_ccn_pmu_event, attr);
+
+ if (event->type == CCN_TYPE_SBAS && !ccn->sbas_present)
+ return 0;
+ if (event->type == CCN_TYPE_SBSX && !ccn->sbsx_present)
+ return 0;
+
+ return attr->mode;
+}
+
+static struct arm_ccn_pmu_event arm_ccn_pmu_events[] = {
+ CCN_EVENT_MN(eobarrier, "dir=0,vc=0,cmp_h=0x1c00", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_MN(ecbarrier, "dir=0,vc=0,cmp_h=0x1e00", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_MN(dvmop, "dir=0,vc=0,cmp_h=0x2800", CCN_IDX_MASK_OPCODE),
+ CCN_EVENT_HNI(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_HNI(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+ CCN_IDX_MASK_ORDER),
+ CCN_EVENT_SBSX(txdatflits, "dir=1,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxdatflits, "dir=0,vc=3", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(txreqflits, "dir=1,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxreqflits, "dir=0,vc=0", CCN_IDX_MASK_ANY),
+ CCN_EVENT_SBSX(rxreqflits_order, "dir=0,vc=0,cmp_h=0x8000",
+ CCN_IDX_MASK_ORDER),
+ CCN_EVENT_HNF(cache_miss, 0x1),
+ CCN_EVENT_HNF(l3_sf_cache_access, 0x02),
+ CCN_EVENT_HNF(cache_fill, 0x3),
+ CCN_EVENT_HNF(pocq_retry, 0x4),
+ CCN_EVENT_HNF(pocq_reqs_recvd, 0x5),
+ CCN_EVENT_HNF(sf_hit, 0x6),
+ CCN_EVENT_HNF(sf_evictions, 0x7),
+ CCN_EVENT_HNF(snoops_sent, 0x8),
+ CCN_EVENT_HNF(snoops_broadcast, 0x9),
+ CCN_EVENT_HNF(l3_eviction, 0xa),
+ CCN_EVENT_HNF(l3_fill_invalid_way, 0xb),
+ CCN_EVENT_HNF(mc_retries, 0xc),
+ CCN_EVENT_HNF(mc_reqs, 0xd),
+ CCN_EVENT_HNF(qos_hh_retry, 0xe),
+ CCN_EVENT_RNI(rdata_beats_p0, 0x1),
+ CCN_EVENT_RNI(rdata_beats_p1, 0x2),
+ CCN_EVENT_RNI(rdata_beats_p2, 0x3),
+ CCN_EVENT_RNI(rxdat_flits, 0x4),
+ CCN_EVENT_RNI(txdat_flits, 0x5),
+ CCN_EVENT_RNI(txreq_flits, 0x6),
+ CCN_EVENT_RNI(txreq_flits_retried, 0x7),
+ CCN_EVENT_RNI(rrt_full, 0x8),
+ CCN_EVENT_RNI(wrt_full, 0x9),
+ CCN_EVENT_RNI(txreq_flits_replayed, 0xa),
+ CCN_EVENT_XP(upload_starvation, 0x1),
+ CCN_EVENT_XP(download_starvation, 0x2),
+ CCN_EVENT_XP(respin, 0x3),
+ CCN_EVENT_XP(valid_flit, 0x4),
+ CCN_EVENT_XP(watchpoint, CCN_EVENT_WATCHPOINT),
+ CCN_EVENT_SBAS(rdata_beats_p0, 0x1),
+ CCN_EVENT_SBAS(rxdat_flits, 0x4),
+ CCN_EVENT_SBAS(txdat_flits, 0x5),
+ CCN_EVENT_SBAS(txreq_flits, 0x6),
+ CCN_EVENT_SBAS(txreq_flits_retried, 0x7),
+ CCN_EVENT_SBAS(rrt_full, 0x8),
+ CCN_EVENT_SBAS(wrt_full, 0x9),
+ CCN_EVENT_SBAS(txreq_flits_replayed, 0xa),
+ CCN_EVENT_CYCLES(cycles),
+};
+
+/* Populated in arm_ccn_init() */
+static struct attribute
+ *arm_ccn_pmu_events_attrs[ARRAY_SIZE(arm_ccn_pmu_events) + 1];
+
+static struct attribute_group arm_ccn_pmu_events_attr_group = {
+ .name = "events",
+ .is_visible = arm_ccn_pmu_events_is_visible,
+ .attrs = arm_ccn_pmu_events_attrs,
+};
+
+
+static u64 *arm_ccn_pmu_get_cmp_mask(struct arm_ccn *ccn, const char *name)
+{
+ unsigned long i;
+
+ if (WARN_ON(!name || !name[0] || !isxdigit(name[0]) || !name[1]))
+ return NULL;
+ i = isdigit(name[0]) ? name[0] - '0' : 0xa + tolower(name[0]) - 'a';
+
+ switch (name[1]) {
+ case 'l':
+ return &ccn->dt.cmp_mask[i].l;
+ case 'h':
+ return &ccn->dt.cmp_mask[i].h;
+ default:
+ return NULL;
+ }
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+
+ return mask ? snprintf(buf, PAGE_SIZE, "0x%016llx\n", *mask) : -EINVAL;
+}
+
+static ssize_t arm_ccn_pmu_cmp_mask_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(dev_get_drvdata(dev));
+ u64 *mask = arm_ccn_pmu_get_cmp_mask(ccn, attr->attr.name);
+ int err = -EINVAL;
+
+ if (mask)
+ err = kstrtoull(buf, 0, mask);
+
+ return err ? err : count;
+}
+
+#define CCN_CMP_MASK_ATTR(_name) \
+ struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+ __ATTR(_name, S_IRUGO | S_IWUSR, \
+ arm_ccn_pmu_cmp_mask_show, arm_ccn_pmu_cmp_mask_store)
+
+#define CCN_CMP_MASK_ATTR_RO(_name) \
+ struct device_attribute arm_ccn_pmu_cmp_mask_attr_##_name = \
+ __ATTR(_name, S_IRUGO, arm_ccn_pmu_cmp_mask_show, NULL)
+
+static CCN_CMP_MASK_ATTR(0l);
+static CCN_CMP_MASK_ATTR(0h);
+static CCN_CMP_MASK_ATTR(1l);
+static CCN_CMP_MASK_ATTR(1h);
+static CCN_CMP_MASK_ATTR(2l);
+static CCN_CMP_MASK_ATTR(2h);
+static CCN_CMP_MASK_ATTR(3l);
+static CCN_CMP_MASK_ATTR(3h);
+static CCN_CMP_MASK_ATTR(4l);
+static CCN_CMP_MASK_ATTR(4h);
+static CCN_CMP_MASK_ATTR(5l);
+static CCN_CMP_MASK_ATTR(5h);
+static CCN_CMP_MASK_ATTR(6l);
+static CCN_CMP_MASK_ATTR(6h);
+static CCN_CMP_MASK_ATTR(7l);
+static CCN_CMP_MASK_ATTR(7h);
+static CCN_CMP_MASK_ATTR_RO(8l);
+static CCN_CMP_MASK_ATTR_RO(8h);
+static CCN_CMP_MASK_ATTR_RO(9l);
+static CCN_CMP_MASK_ATTR_RO(9h);
+static CCN_CMP_MASK_ATTR_RO(al);
+static CCN_CMP_MASK_ATTR_RO(ah);
+static CCN_CMP_MASK_ATTR_RO(bl);
+static CCN_CMP_MASK_ATTR_RO(bh);
+
+static struct attribute *arm_ccn_pmu_cmp_mask_attrs[] = {
+ &arm_ccn_pmu_cmp_mask_attr_0l.attr, &arm_ccn_pmu_cmp_mask_attr_0h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_1l.attr, &arm_ccn_pmu_cmp_mask_attr_1h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_2l.attr, &arm_ccn_pmu_cmp_mask_attr_2h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_3l.attr, &arm_ccn_pmu_cmp_mask_attr_3h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_4l.attr, &arm_ccn_pmu_cmp_mask_attr_4h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_5l.attr, &arm_ccn_pmu_cmp_mask_attr_5h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_6l.attr, &arm_ccn_pmu_cmp_mask_attr_6h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_7l.attr, &arm_ccn_pmu_cmp_mask_attr_7h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_8l.attr, &arm_ccn_pmu_cmp_mask_attr_8h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_9l.attr, &arm_ccn_pmu_cmp_mask_attr_9h.attr,
+ &arm_ccn_pmu_cmp_mask_attr_al.attr, &arm_ccn_pmu_cmp_mask_attr_ah.attr,
+ &arm_ccn_pmu_cmp_mask_attr_bl.attr, &arm_ccn_pmu_cmp_mask_attr_bh.attr,
+ NULL
+};
+
+static struct attribute_group arm_ccn_pmu_cmp_mask_attr_group = {
+ .name = "cmp_mask",
+ .attrs = arm_ccn_pmu_cmp_mask_attrs,
+};
+
+
+/*
+ * Default poll period is 10ms, which is way over the top anyway,
+ * as in the worst case scenario (an event every cycle), with 1GHz
+ * clocked bus, the smallest, 32 bit counter will overflow in
+ * more than 4s.
+ */
+static unsigned int arm_ccn_pmu_poll_period_us = 10000;
+module_param_named(pmu_poll_period_us, arm_ccn_pmu_poll_period_us, uint,
+ S_IRUGO | S_IWUSR);
+
+static ktime_t arm_ccn_pmu_timer_period(void)
+{
+ return ns_to_ktime((u64)arm_ccn_pmu_poll_period_us * 1000);
+}
+
+
+static const struct attribute_group *arm_ccn_pmu_attr_groups[] = {
+ &arm_ccn_pmu_events_attr_group,
+ &arm_ccn_pmu_format_attr_group,
+ &arm_ccn_pmu_cmp_mask_attr_group,
+ NULL
+};
+
+
+static int arm_ccn_pmu_alloc_bit(unsigned long *bitmap, unsigned long size)
+{
+ int bit;
+
+ do {
+ bit = find_first_zero_bit(bitmap, size);
+ if (bit >= size)
+ return -EAGAIN;
+ } while (test_and_set_bit(bit, bitmap));
+
+ return bit;
+}
+
+/* All RN-I and RN-D nodes have identical PMUs */
+static int arm_ccn_pmu_type_eq(u32 a, u32 b)
+{
+ if (a == b)
+ return 1;
+
+ switch (a) {
+ case CCN_TYPE_RNI_1P:
+ case CCN_TYPE_RNI_2P:
+ case CCN_TYPE_RNI_3P:
+ case CCN_TYPE_RND_1P:
+ case CCN_TYPE_RND_2P:
+ case CCN_TYPE_RND_3P:
+ switch (b) {
+ case CCN_TYPE_RNI_1P:
+ case CCN_TYPE_RNI_2P:
+ case CCN_TYPE_RNI_3P:
+ case CCN_TYPE_RND_1P:
+ case CCN_TYPE_RND_2P:
+ case CCN_TYPE_RND_3P:
+ return 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int arm_ccn_pmu_event_init(struct perf_event *event)
+{
+ struct arm_ccn *ccn;
+ struct hw_perf_event *hw = &event->hw;
+ u32 node_xp, type, event_id;
+ int valid, bit;
+ struct arm_ccn_component *source;
+ int i;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ ccn = pmu_to_arm_ccn(event->pmu);
+
+ if (hw->sample_period) {
+ dev_warn(ccn->dev, "Sampling not supported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (has_branch_stack(event) || event->attr.exclude_user ||
+ event->attr.exclude_kernel || event->attr.exclude_hv ||
+ event->attr.exclude_idle) {
+ dev_warn(ccn->dev, "Can't exclude execution levels!\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (event->cpu < 0) {
+ dev_warn(ccn->dev, "Can't provide per-task data!\n");
+ return -EOPNOTSUPP;
+ }
+
+ node_xp = CCN_CONFIG_NODE(event->attr.config);
+ type = CCN_CONFIG_TYPE(event->attr.config);
+ event_id = CCN_CONFIG_EVENT(event->attr.config);
+
+ /* Validate node/xp vs topology */
+ switch (type) {
+ case CCN_TYPE_XP:
+ if (node_xp >= ccn->num_xps) {
+ dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp);
+ return -EINVAL;
+ }
+ break;
+ case CCN_TYPE_CYCLES:
+ break;
+ default:
+ if (node_xp >= ccn->num_nodes) {
+ dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp);
+ return -EINVAL;
+ }
+ if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) {
+ dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n",
+ type, node_xp);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ /* Validate event ID vs available for the type */
+ for (i = 0, valid = 0; i < ARRAY_SIZE(arm_ccn_pmu_events) && !valid;
+ i++) {
+ struct arm_ccn_pmu_event *e = &arm_ccn_pmu_events[i];
+ u32 port = CCN_CONFIG_PORT(event->attr.config);
+ u32 vc = CCN_CONFIG_VC(event->attr.config);
+
+ if (!arm_ccn_pmu_type_eq(type, e->type))
+ continue;
+ if (event_id != e->event)
+ continue;
+ if (e->num_ports && port >= e->num_ports) {
+ dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n",
+ port, node_xp);
+ return -EINVAL;
+ }
+ if (e->num_vcs && vc >= e->num_vcs) {
+ dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n",
+ port, node_xp);
+ return -EINVAL;
+ }
+ valid = 1;
+ }
+ if (!valid) {
+ dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n",
+ event_id, node_xp);
+ return -EINVAL;
+ }
+
+ /* Watchpoint-based event for a node is actually set on XP */
+ if (event_id == CCN_EVENT_WATCHPOINT && type != CCN_TYPE_XP) {
+ u32 port;
+
+ type = CCN_TYPE_XP;
+ port = arm_ccn_node_to_xp_port(node_xp);
+ node_xp = arm_ccn_node_to_xp(node_xp);
+
+ arm_ccn_pmu_config_set(&event->attr.config,
+ node_xp, type, port);
+ }
+
+ /* Allocate the cycle counter */
+ if (type == CCN_TYPE_CYCLES) {
+ if (test_and_set_bit(CCN_IDX_PMU_CYCLE_COUNTER,
+ ccn->dt.pmu_counters_mask))
+ return -EAGAIN;
+
+ hw->idx = CCN_IDX_PMU_CYCLE_COUNTER;
+ ccn->dt.pmu_counters[CCN_IDX_PMU_CYCLE_COUNTER].event = event;
+
+ return 0;
+ }
+
+ /* Allocate an event counter */
+ hw->idx = arm_ccn_pmu_alloc_bit(ccn->dt.pmu_counters_mask,
+ CCN_NUM_PMU_EVENT_COUNTERS);
+ if (hw->idx < 0) {
+ dev_warn(ccn->dev, "No more counters available!\n");
+ return -EAGAIN;
+ }
+
+ if (type == CCN_TYPE_XP)
+ source = &ccn->xp[node_xp];
+ else
+ source = &ccn->node[node_xp];
+ ccn->dt.pmu_counters[hw->idx].source = source;
+
+ /* Allocate an event source or a watchpoint */
+ if (type == CCN_TYPE_XP && event_id == CCN_EVENT_WATCHPOINT)
+ bit = arm_ccn_pmu_alloc_bit(source->xp.dt_cmp_mask,
+ CCN_NUM_XP_WATCHPOINTS);
+ else
+ bit = arm_ccn_pmu_alloc_bit(source->pmu_events_mask,
+ CCN_NUM_PMU_EVENTS);
+ if (bit < 0) {
+ dev_warn(ccn->dev, "No more event sources/watchpoints on node/XP %d!\n",
+ node_xp);
+ clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+ return -EAGAIN;
+ }
+ hw->config_base = bit;
+
+ ccn->dt.pmu_counters[hw->idx].event = event;
+
+ return 0;
+}
+
+static void arm_ccn_pmu_event_free(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+
+ if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+ clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask);
+ } else {
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP &&
+ CCN_CONFIG_EVENT(event->attr.config) ==
+ CCN_EVENT_WATCHPOINT)
+ clear_bit(hw->config_base, source->xp.dt_cmp_mask);
+ else
+ clear_bit(hw->config_base, source->pmu_events_mask);
+ clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+ }
+
+ ccn->dt.pmu_counters[hw->idx].source = NULL;
+ ccn->dt.pmu_counters[hw->idx].event = NULL;
+}
+
+static u64 arm_ccn_pmu_read_counter(struct arm_ccn *ccn, int idx)
+{
+ u64 res;
+
+ if (idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+#ifdef readq
+ res = readq(ccn->dt.base + CCN_DT_PMCCNTR);
+#else
+ /* 40 bit counter, can do snapshot and read in two parts */
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_REQ);
+ while (!(readl(ccn->dt.base + CCN_DT_PMSR) & 0x1))
+ ;
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+ res = readl(ccn->dt.base + CCN_DT_PMCCNTRSR + 4) & 0xff;
+ res <<= 32;
+ res |= readl(ccn->dt.base + CCN_DT_PMCCNTRSR);
+#endif
+ } else {
+ res = readl(ccn->dt.base + CCN_DT_PMEVCNT(idx));
+ }
+
+ return res;
+}
+
+static void arm_ccn_pmu_event_update(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u64 prev_count, new_count, mask;
+
+ do {
+ prev_count = local64_read(&hw->prev_count);
+ new_count = arm_ccn_pmu_read_counter(ccn, hw->idx);
+ } while (local64_xchg(&hw->prev_count, new_count) != prev_count);
+
+ mask = (1LLU << (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER ? 40 : 32)) - 1;
+
+ local64_add((new_count - prev_count) & mask, &event->count);
+}
+
+static void arm_ccn_pmu_xp_dt_config(struct perf_event *event, int enable)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *xp;
+ u32 val, dt_cfg;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+ xp = &ccn->xp[CCN_CONFIG_XP(event->attr.config)];
+ else
+ xp = &ccn->xp[arm_ccn_node_to_xp(
+ CCN_CONFIG_NODE(event->attr.config))];
+
+ if (enable)
+ dt_cfg = hw->event_base;
+ else
+ dt_cfg = CCN_XP_DT_CONFIG__DT_CFG__PASS_THROUGH;
+
+ spin_lock(&ccn->dt.config_lock);
+
+ val = readl(xp->base + CCN_XP_DT_CONFIG);
+ val &= ~(CCN_XP_DT_CONFIG__DT_CFG__MASK <<
+ CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx));
+ val |= dt_cfg << CCN_XP_DT_CONFIG__DT_CFG__SHIFT(hw->idx);
+ writel(val, xp->base + CCN_XP_DT_CONFIG);
+
+ spin_unlock(&ccn->dt.config_lock);
+}
+
+static void arm_ccn_pmu_event_start(struct perf_event *event, int flags)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+
+ local64_set(&event->hw.prev_count,
+ arm_ccn_pmu_read_counter(ccn, hw->idx));
+ hw->state = 0;
+
+ if (!ccn->irq_used)
+ hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
+ HRTIMER_MODE_REL);
+
+ /* Set the DT bus input, engaging the counter */
+ arm_ccn_pmu_xp_dt_config(event, 1);
+}
+
+static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u64 timeout;
+
+ /* Disable counting, setting the DT bus to pass-through mode */
+ arm_ccn_pmu_xp_dt_config(event, 0);
+
+ if (!ccn->irq_used)
+ hrtimer_cancel(&ccn->dt.hrtimer);
+
+ /* Let the DT bus drain */
+ timeout = arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) +
+ ccn->num_xps;
+ while (arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) <
+ timeout)
+ cpu_relax();
+
+ if (flags & PERF_EF_UPDATE)
+ arm_ccn_pmu_event_update(event);
+
+ hw->state |= PERF_HES_STOPPED;
+}
+
+static void arm_ccn_pmu_xp_watchpoint_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ unsigned long wp = hw->config_base;
+ u32 val;
+ u64 cmp_l = event->attr.config1;
+ u64 cmp_h = event->attr.config2;
+ u64 mask_l = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].l;
+ u64 mask_h = ccn->dt.cmp_mask[CCN_CONFIG_MASK(event->attr.config)].h;
+
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__WATCHPOINT(wp);
+
+ /* Direction (RX/TX), device (port) & virtual channel */
+ val = readl(source->base + CCN_XP_DT_INTERFACE_SEL);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_DIR(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_IO_SEL__SHIFT(wp);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_PORT(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_DEV_SEL__SHIFT(wp);
+ val &= ~(CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__MASK <<
+ CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp));
+ val |= CCN_CONFIG_VC(event->attr.config) <<
+ CCN_XP_DT_INTERFACE_SEL__DT_VC_SEL__SHIFT(wp);
+ writel(val, source->base + CCN_XP_DT_INTERFACE_SEL);
+
+ /* Comparison values */
+ writel(cmp_l & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_L(wp));
+ writel((cmp_l >> 32) & 0xefffffff,
+ source->base + CCN_XP_DT_CMP_VAL_L(wp) + 4);
+ writel(cmp_h & 0xffffffff, source->base + CCN_XP_DT_CMP_VAL_H(wp));
+ writel((cmp_h >> 32) & 0x0fffffff,
+ source->base + CCN_XP_DT_CMP_VAL_H(wp) + 4);
+
+ /* Mask */
+ writel(mask_l & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_L(wp));
+ writel((mask_l >> 32) & 0xefffffff,
+ source->base + CCN_XP_DT_CMP_MASK_L(wp) + 4);
+ writel(mask_h & 0xffffffff, source->base + CCN_XP_DT_CMP_MASK_H(wp));
+ writel((mask_h >> 32) & 0x0fffffff,
+ source->base + CCN_XP_DT_CMP_MASK_H(wp) + 4);
+}
+
+static void arm_ccn_pmu_xp_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ u32 val, id;
+
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(hw->config_base);
+
+ id = (CCN_CONFIG_VC(event->attr.config) << 4) |
+ (CCN_CONFIG_PORT(event->attr.config) << 3) |
+ (CCN_CONFIG_EVENT(event->attr.config) << 0);
+
+ val = readl(source->base + CCN_XP_PMU_EVENT_SEL);
+ val &= ~(CCN_XP_PMU_EVENT_SEL__ID__MASK <<
+ CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+ val |= id << CCN_XP_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+ writel(val, source->base + CCN_XP_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_node_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn_component *source =
+ ccn->dt.pmu_counters[hw->idx].source;
+ u32 type = CCN_CONFIG_TYPE(event->attr.config);
+ u32 val, port;
+
+ port = arm_ccn_node_to_xp_port(CCN_CONFIG_NODE(event->attr.config));
+ hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__DEVICE_PMU_EVENT(port,
+ hw->config_base);
+
+ /* These *_event_sel regs should be identical, but let's make sure... */
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL != CCN_SBAS_PMU_EVENT_SEL);
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL != CCN_RNI_PMU_EVENT_SEL);
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(1) !=
+ CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1));
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__SHIFT(1) !=
+ CCN_RNI_PMU_EVENT_SEL__ID__SHIFT(1));
+ BUILD_BUG_ON(CCN_HNF_PMU_EVENT_SEL__ID__MASK !=
+ CCN_SBAS_PMU_EVENT_SEL__ID__MASK);
+ BUILD_BUG_ON(CCN_SBAS_PMU_EVENT_SEL__ID__MASK !=
+ CCN_RNI_PMU_EVENT_SEL__ID__MASK);
+ if (WARN_ON(type != CCN_TYPE_HNF && type != CCN_TYPE_SBAS &&
+ !arm_ccn_pmu_type_eq(type, CCN_TYPE_RNI_3P)))
+ return;
+
+ /* Set the event id for the pre-allocated counter */
+ val = readl(source->base + CCN_HNF_PMU_EVENT_SEL);
+ val &= ~(CCN_HNF_PMU_EVENT_SEL__ID__MASK <<
+ CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base));
+ val |= CCN_CONFIG_EVENT(event->attr.config) <<
+ CCN_HNF_PMU_EVENT_SEL__ID__SHIFT(hw->config_base);
+ writel(val, source->base + CCN_HNF_PMU_EVENT_SEL);
+}
+
+static void arm_ccn_pmu_event_config(struct perf_event *event)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+ struct hw_perf_event *hw = &event->hw;
+ u32 xp, offset, val;
+
+ /* Cycle counter requires no setup */
+ if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER)
+ return;
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP)
+ xp = CCN_CONFIG_XP(event->attr.config);
+ else
+ xp = arm_ccn_node_to_xp(CCN_CONFIG_NODE(event->attr.config));
+
+ spin_lock(&ccn->dt.config_lock);
+
+ /* Set the DT bus "distance" register */
+ offset = (hw->idx / 4) * 4;
+ val = readl(ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+ val &= ~(CCN_DT_ACTIVE_DSM__DSM_ID__MASK <<
+ CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4));
+ val |= xp << CCN_DT_ACTIVE_DSM__DSM_ID__SHIFT(hw->idx % 4);
+ writel(val, ccn->dt.base + CCN_DT_ACTIVE_DSM + offset);
+
+ if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP) {
+ if (CCN_CONFIG_EVENT(event->attr.config) ==
+ CCN_EVENT_WATCHPOINT)
+ arm_ccn_pmu_xp_watchpoint_config(event);
+ else
+ arm_ccn_pmu_xp_event_config(event);
+ } else {
+ arm_ccn_pmu_node_event_config(event);
+ }
+
+ spin_unlock(&ccn->dt.config_lock);
+}
+
+static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hw = &event->hw;
+
+ arm_ccn_pmu_event_config(event);
+
+ hw->state = PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ arm_ccn_pmu_event_start(event, PERF_EF_UPDATE);
+
+ return 0;
+}
+
+static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
+{
+ arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
+
+ arm_ccn_pmu_event_free(event);
+}
+
+static void arm_ccn_pmu_event_read(struct perf_event *event)
+{
+ arm_ccn_pmu_event_update(event);
+}
+
+static irqreturn_t arm_ccn_pmu_overflow_handler(struct arm_ccn_dt *dt)
+{
+ u32 pmovsr = readl(dt->base + CCN_DT_PMOVSR);
+ int idx;
+
+ if (!pmovsr)
+ return IRQ_NONE;
+
+ writel(pmovsr, dt->base + CCN_DT_PMOVSR_CLR);
+
+ BUILD_BUG_ON(CCN_IDX_PMU_CYCLE_COUNTER != CCN_NUM_PMU_EVENT_COUNTERS);
+
+ for (idx = 0; idx < CCN_NUM_PMU_EVENT_COUNTERS + 1; idx++) {
+ struct perf_event *event = dt->pmu_counters[idx].event;
+ int overflowed = pmovsr & BIT(idx);
+
+ WARN_ON_ONCE(overflowed && !event);
+
+ if (!event || !overflowed)
+ continue;
+
+ arm_ccn_pmu_event_update(event);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
+{
+ struct arm_ccn_dt *dt = container_of(hrtimer, struct arm_ccn_dt,
+ hrtimer);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ arm_ccn_pmu_overflow_handler(dt);
+ local_irq_restore(flags);
+
+ hrtimer_forward_now(hrtimer, arm_ccn_pmu_timer_period());
+ return HRTIMER_RESTART;
+}
+
+
+static DEFINE_IDA(arm_ccn_pmu_ida);
+
+static int arm_ccn_pmu_init(struct arm_ccn *ccn)
+{
+ int i;
+ char *name;
+
+ /* Initialize DT subsystem */
+ ccn->dt.base = ccn->base + CCN_REGION_SIZE;
+ spin_lock_init(&ccn->dt.config_lock);
+ writel(CCN_DT_CTL__DT_EN, ccn->dt.base + CCN_DT_CTL);
+ writel(CCN_DT_PMCR__OVFL_INTR_EN | CCN_DT_PMCR__PMU_EN,
+ ccn->dt.base + CCN_DT_PMCR);
+ writel(0x1, ccn->dt.base + CCN_DT_PMSR_CLR);
+ for (i = 0; i < ccn->num_xps; i++) {
+ writel(0, ccn->xp[i].base + CCN_XP_DT_CONFIG);
+ writel((CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+ CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(0)) |
+ (CCN_XP_DT_CONTROL__WP_ARM_SEL__ALWAYS <<
+ CCN_XP_DT_CONTROL__WP_ARM_SEL__SHIFT(1)) |
+ CCN_XP_DT_CONTROL__DT_ENABLE,
+ ccn->xp[i].base + CCN_XP_DT_CONTROL);
+ }
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ANY].h = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].l = 0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_EXACT].h = 0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_ORDER].h = ~(0x1 << 15);
+ ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].l = ~0;
+ ccn->dt.cmp_mask[CCN_IDX_MASK_OPCODE].h = ~(0x1f << 9);
+
+ /* Get a convenient /sys/event_source/devices/ name */
+ ccn->dt.id = ida_simple_get(&arm_ccn_pmu_ida, 0, 0, GFP_KERNEL);
+ if (ccn->dt.id == 0) {
+ name = "ccn";
+ } else {
+ int len = snprintf(NULL, 0, "ccn_%d", ccn->dt.id);
+
+ name = devm_kzalloc(ccn->dev, len + 1, GFP_KERNEL);
+ snprintf(name, len + 1, "ccn_%d", ccn->dt.id);
+ }
+
+ /* Perf driver registration */
+ ccn->dt.pmu = (struct pmu) {
+ .attr_groups = arm_ccn_pmu_attr_groups,
+ .task_ctx_nr = perf_invalid_context,
+ .event_init = arm_ccn_pmu_event_init,
+ .add = arm_ccn_pmu_event_add,
+ .del = arm_ccn_pmu_event_del,
+ .start = arm_ccn_pmu_event_start,
+ .stop = arm_ccn_pmu_event_stop,
+ .read = arm_ccn_pmu_event_read,
+ };
+
+ /* No overflow interrupt? Have to use a timer instead. */
+ if (!ccn->irq_used) {
+ dev_info(ccn->dev, "No access to interrupts, using timer.\n");
+ hrtimer_init(&ccn->dt.hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ ccn->dt.hrtimer.function = arm_ccn_pmu_timer_handler;
+ }
+
+ return perf_pmu_register(&ccn->dt.pmu, name, -1);
+}
+
+static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
+{
+ int i;
+
+ for (i = 0; i < ccn->num_xps; i++)
+ writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
+ writel(0, ccn->dt.base + CCN_DT_PMCR);
+ perf_pmu_unregister(&ccn->dt.pmu);
+ ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
+}
+
+
+static int arm_ccn_for_each_valid_region(struct arm_ccn *ccn,
+ int (*callback)(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id))
+{
+ int region;
+
+ for (region = 0; region < CCN_NUM_REGIONS; region++) {
+ u32 val, type, id;
+ void __iomem *base;
+ int err;
+
+ val = readl(ccn->base + CCN_MN_OLY_COMP_LIST_63_0 +
+ 4 * (region / 32));
+ if (!(val & (1 << (region % 32))))
+ continue;
+
+ base = ccn->base + region * CCN_REGION_SIZE;
+ val = readl(base + CCN_ALL_OLY_ID);
+ type = (val >> CCN_ALL_OLY_ID__OLY_ID__SHIFT) &
+ CCN_ALL_OLY_ID__OLY_ID__MASK;
+ id = (val >> CCN_ALL_OLY_ID__NODE_ID__SHIFT) &
+ CCN_ALL_OLY_ID__NODE_ID__MASK;
+
+ err = callback(ccn, region, base, type, id);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int arm_ccn_get_nodes_num(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id)
+{
+
+ if (type == CCN_TYPE_XP && id >= ccn->num_xps)
+ ccn->num_xps = id + 1;
+ else if (id >= ccn->num_nodes)
+ ccn->num_nodes = id + 1;
+
+ return 0;
+}
+
+static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region,
+ void __iomem *base, u32 type, u32 id)
+{
+ struct arm_ccn_component *component;
+
+ dev_dbg(ccn->dev, "Region %d: id=%u, type=0x%02x\n", region, id, type);
+
+ switch (type) {
+ case CCN_TYPE_MN:
+ case CCN_TYPE_DT:
+ return 0;
+ case CCN_TYPE_XP:
+ component = &ccn->xp[id];
+ break;
+ case CCN_TYPE_SBSX:
+ ccn->sbsx_present = 1;
+ component = &ccn->node[id];
+ break;
+ case CCN_TYPE_SBAS:
+ ccn->sbas_present = 1;
+ /* Fall-through */
+ default:
+ component = &ccn->node[id];
+ break;
+ }
+
+ component->base = base;
+ component->type = type;
+
+ return 0;
+}
+
+
+static irqreturn_t arm_ccn_error_handler(struct arm_ccn *ccn,
+ const u32 *err_sig_val)
+{
+ /* This should be really handled by firmware... */
+ dev_err(ccn->dev, "Error reported in %08x%08x%08x%08x%08x%08x.\n",
+ err_sig_val[5], err_sig_val[4], err_sig_val[3],
+ err_sig_val[2], err_sig_val[1], err_sig_val[0]);
+ dev_err(ccn->dev, "Disabling interrupt generation for all errors.\n");
+ writel(CCN_MN_ERRINT_STATUS__ALL_ERRORS__DISABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t arm_ccn_irq_handler(int irq, void *dev_id)
+{
+ irqreturn_t res = IRQ_NONE;
+ struct arm_ccn *ccn = dev_id;
+ u32 err_sig_val[6];
+ u32 err_or;
+ int i;
+
+ /* PMU overflow is a special case */
+ err_or = err_sig_val[0] = readl(ccn->base + CCN_MN_ERR_SIG_VAL_63_0);
+ if (err_or & CCN_MN_ERR_SIG_VAL_63_0__DT) {
+ err_or &= ~CCN_MN_ERR_SIG_VAL_63_0__DT;
+ res = arm_ccn_pmu_overflow_handler(&ccn->dt);
+ }
+
+ /* Have to read all err_sig_vals to clear them */
+ for (i = 1; i < ARRAY_SIZE(err_sig_val); i++) {
+ err_sig_val[i] = readl(ccn->base +
+ CCN_MN_ERR_SIG_VAL_63_0 + i * 4);
+ err_or |= err_sig_val[i];
+ }
+ if (err_or)
+ res |= arm_ccn_error_handler(ccn, err_sig_val);
+
+ if (res != IRQ_NONE)
+ writel(CCN_MN_ERRINT_STATUS__INTREQ__DESSERT,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+
+ return res;
+}
+
+
+static int arm_ccn_probe(struct platform_device *pdev)
+{
+ struct arm_ccn *ccn;
+ struct resource *res;
+ int err;
+
+ ccn = devm_kzalloc(&pdev->dev, sizeof(*ccn), GFP_KERNEL);
+ if (!ccn)
+ return -ENOMEM;
+ ccn->dev = &pdev->dev;
+ platform_set_drvdata(pdev, ccn);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(ccn->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ ccn->base = devm_ioremap(ccn->dev, res->start,
+ resource_size(res));
+ if (!ccn->base)
+ return -EFAULT;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res)
+ return -EINVAL;
+
+ /* Check if we can use the interrupt */
+ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+ if (readl(ccn->base + CCN_MN_ERRINT_STATUS) &
+ CCN_MN_ERRINT_STATUS__PMU_EVENTS__DISABLED) {
+ /* Can set 'disable' bits, so can acknowledge interrupts */
+ writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE,
+ ccn->base + CCN_MN_ERRINT_STATUS);
+ err = devm_request_irq(ccn->dev, res->start,
+ arm_ccn_irq_handler, 0, dev_name(ccn->dev),
+ ccn);
+ if (err)
+ return err;
+
+ ccn->irq_used = 1;
+ }
+
+
+ /* Build topology */
+
+ err = arm_ccn_for_each_valid_region(ccn, arm_ccn_get_nodes_num);
+ if (err)
+ return err;
+
+ ccn->node = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_nodes,
+ GFP_KERNEL);
+ ccn->xp = devm_kzalloc(ccn->dev, sizeof(*ccn->node) * ccn->num_xps,
+ GFP_KERNEL);
+ if (!ccn->node || !ccn->xp)
+ return -ENOMEM;
+
+ err = arm_ccn_for_each_valid_region(ccn, arm_ccn_init_nodes);
+ if (err)
+ return err;
+
+ return arm_ccn_pmu_init(ccn);
+}
+
+static int arm_ccn_remove(struct platform_device *pdev)
+{
+ struct arm_ccn *ccn = platform_get_drvdata(pdev);
+
+ arm_ccn_pmu_cleanup(ccn);
+
+ return 0;
+}
+
+static const struct of_device_id arm_ccn_match[] = {
+ { .compatible = "arm,ccn-504", },
+ {},
+};
+
+static struct platform_driver arm_ccn_driver = {
+ .driver = {
+ .name = "arm-ccn",
+ .of_match_table = arm_ccn_match,
+ },
+ .probe = arm_ccn_probe,
+ .remove = arm_ccn_remove,
+};
+
+static int __init arm_ccn_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(arm_ccn_pmu_events); i++)
+ arm_ccn_pmu_events_attrs[i] = &arm_ccn_pmu_events[i].attr.attr;
+
+ return platform_driver_register(&arm_ccn_driver);
+}
+
+static void __exit arm_ccn_exit(void)
+{
+ platform_driver_unregister(&arm_ccn_driver);
+}
+
+module_init(arm_ccn_init);
+module_exit(arm_ccn_exit);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c
index 6159b7752a64..f2cd6a2d40b4 100644
--- a/drivers/bus/brcmstb_gisb.c
+++ b/drivers/bus/brcmstb_gisb.c
@@ -212,9 +212,9 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
mutex_init(&gdev->lock);
INIT_LIST_HEAD(&gdev->next);
- gdev->base = devm_request_and_ioremap(&pdev->dev, r);
- if (!gdev->base)
- return -ENOMEM;
+ gdev->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(gdev->base))
+ return PTR_ERR(gdev->base);
err = devm_request_irq(&pdev->dev, timeout_irq,
brcmstb_gisb_timeout_handler, 0, pdev->name,
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index f8ee13c7bf7b..75c9681f8021 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -162,7 +162,9 @@ static int __init weim_parse_dt(struct platform_device *pdev,
}
}
- ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ ret = of_platform_populate(pdev->dev.of_node,
+ of_default_bus_match_table,
+ NULL, &pdev->dev);
if (ret)
dev_err(&pdev->dev, "%s fail to create devices.\n",
pdev->dev.of_node->full_name);
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index b29703324e94..09f17eb73486 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -710,19 +710,6 @@ static int agp_open(struct inode *inode, struct file *file)
return 0;
}
-
-static ssize_t agp_read(struct file *file, char __user *buf,
- size_t count, loff_t * ppos)
-{
- return -EINVAL;
-}
-
-static ssize_t agp_write(struct file *file, const char __user *buf,
- size_t count, loff_t * ppos)
-{
- return -EINVAL;
-}
-
static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_info userinfo;
@@ -1047,8 +1034,6 @@ static const struct file_operations agp_fops =
{
.owner = THIS_MODULE,
.llseek = no_llseek,
- .read = agp_read,
- .write = agp_write,
.unlocked_ioctl = agp_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_agp_ioctl,
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 8fedbc250414..a6cef548e01e 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -259,7 +259,7 @@ static int bsr_add_node(struct device_node *bn)
}
cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
- cur, cur->bsr_name);
+ cur, "%s", cur->bsr_name);
if (IS_ERR(cur->bsr_device)) {
printk(KERN_ERR "device_create failed for %s\n",
cur->bsr_name);
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 01a5ca7425d7..8bf70e8c3f79 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -383,7 +383,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
return put_user(status, &hf->status);
}
case DSP56K_HOST_CMD:
- if (arg > 31 || arg < 0)
+ if (arg > 31)
return -EINVAL;
mutex_lock(&dsp56k_mutex);
dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index f953c96efc86..ebc4c73d8ca4 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -49,7 +49,7 @@
#include <asm/uaccess.h>
#include <linux/sysrq.h>
#include <linux/timer.h>
-#include <linux/time.h>
+#include <linux/hrtimer.h>
#define VERSION_STR "0.9.1"
@@ -117,24 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#endif /* not MODULE */
-#if defined(CONFIG_S390)
-# define HAVE_MONOTONIC
-# define TIMER_FREQ 1000000000ULL
-#else
-# define TIMER_FREQ 1000000000ULL
-#endif
-
-#ifdef HAVE_MONOTONIC
-extern unsigned long long monotonic_clock(void);
-#else
-static inline unsigned long long monotonic_clock(void)
-{
- struct timespec ts;
- getrawmonotonic(&ts);
- return timespec_to_ns(&ts);
-}
-#endif /* HAVE_MONOTONIC */
-
+#define TIMER_FREQ 1000000000ULL
/* Last time scheduled */
static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
@@ -143,12 +126,11 @@ static void hangcheck_fire(unsigned long);
static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
-
static void hangcheck_fire(unsigned long data)
{
unsigned long long cur_tsc, tsc_diff;
- cur_tsc = monotonic_clock();
+ cur_tsc = ktime_get_ns();
if (cur_tsc > hangcheck_tsc)
tsc_diff = cur_tsc - hangcheck_tsc;
@@ -177,7 +159,7 @@ static void hangcheck_fire(unsigned long data)
tsc_diff, tsc_diff - hangcheck_tick*TIMER_FREQ);
#endif
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
- hangcheck_tsc = monotonic_clock();
+ hangcheck_tsc = ktime_get_ns();
}
@@ -185,16 +167,11 @@ static int __init hangcheck_init(void)
{
printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
VERSION_STR, hangcheck_tick, hangcheck_margin);
-#if defined (HAVE_MONOTONIC)
- printk("Hangcheck: Using monotonic_clock().\n");
-#else
- printk("Hangcheck: Using getrawmonotonic().\n");
-#endif /* HAVE_MONOTONIC */
hangcheck_tsc_margin =
(unsigned long long)(hangcheck_margin + hangcheck_tick);
hangcheck_tsc_margin *= (unsigned long long)TIMER_FREQ;
- hangcheck_tsc = monotonic_clock();
+ hangcheck_tsc = ktime_get_ns();
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
return 0;
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index c4419ea1ab07..aa30a25c8d49 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -38,6 +38,7 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
+#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/random.h>
@@ -50,10 +51,22 @@
static struct hwrng *current_rng;
+static struct task_struct *hwrng_fill;
static LIST_HEAD(rng_list);
static DEFINE_MUTEX(rng_mutex);
static int data_avail;
-static u8 *rng_buffer;
+static u8 *rng_buffer, *rng_fillbuf;
+static unsigned short current_quality;
+static unsigned short default_quality; /* = 0; default to "off" */
+
+module_param(current_quality, ushort, 0644);
+MODULE_PARM_DESC(current_quality,
+ "current hwrng entropy estimation per mill");
+module_param(default_quality, ushort, 0644);
+MODULE_PARM_DESC(default_quality,
+ "default entropy content of hwrng per mill");
+
+static void start_khwrngd(void);
static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int wait);
@@ -68,12 +81,6 @@ static void add_early_randomness(struct hwrng *rng)
unsigned char bytes[16];
int bytes_read;
- /*
- * Currently only virtio-rng cannot return data during device
- * probe, and that's handled in virtio-rng.c itself. If there
- * are more such devices, this call to rng_get_data can be
- * made conditional here instead of doing it per-device.
- */
bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
if (bytes_read > 0)
add_device_randomness(bytes, bytes_read);
@@ -89,6 +96,15 @@ static inline int hwrng_init(struct hwrng *rng)
return ret;
}
add_early_randomness(rng);
+
+ current_quality = rng->quality ? : default_quality;
+ current_quality &= 1023;
+
+ if (current_quality == 0 && hwrng_fill)
+ kthread_stop(hwrng_fill);
+ if (current_quality > 0 && !hwrng_fill)
+ start_khwrngd();
+
return 0;
}
@@ -325,6 +341,36 @@ err_misc_dereg:
goto out;
}
+static int hwrng_fillfn(void *unused)
+{
+ long rc;
+
+ while (!kthread_should_stop()) {
+ if (!current_rng)
+ break;
+ rc = rng_get_data(current_rng, rng_fillbuf,
+ rng_buffer_size(), 1);
+ if (rc <= 0) {
+ pr_warn("hwrng: no data available\n");
+ msleep_interruptible(10000);
+ continue;
+ }
+ add_hwgenerator_randomness((void *)rng_fillbuf, rc,
+ rc * current_quality * 8 >> 10);
+ }
+ hwrng_fill = NULL;
+ return 0;
+}
+
+static void start_khwrngd(void)
+{
+ hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
+ if (hwrng_fill == ERR_PTR(-ENOMEM)) {
+ pr_err("hwrng_fill thread creation failed");
+ hwrng_fill = NULL;
+ }
+}
+
int hwrng_register(struct hwrng *rng)
{
int err = -EINVAL;
@@ -343,6 +389,13 @@ int hwrng_register(struct hwrng *rng)
if (!rng_buffer)
goto out_unlock;
}
+ if (!rng_fillbuf) {
+ rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL);
+ if (!rng_fillbuf) {
+ kfree(rng_buffer);
+ goto out_unlock;
+ }
+ }
/* Must not register two RNGs with the same name. */
err = -EEXIST;
@@ -406,8 +459,11 @@ void hwrng_unregister(struct hwrng *rng)
current_rng = NULL;
}
}
- if (list_empty(&rng_list))
+ if (list_empty(&rng_list)) {
unregister_miscdev();
+ if (hwrng_fill)
+ kthread_stop(hwrng_fill);
+ }
mutex_unlock(&rng_mutex);
}
@@ -418,6 +474,7 @@ static void __exit hwrng_exit(void)
mutex_lock(&rng_mutex);
BUG_ON(current_rng);
kfree(rng_buffer);
+ kfree(rng_fillbuf);
mutex_unlock(&rng_mutex);
}
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index e9b15bc18b4d..2e3139eda93b 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -28,17 +28,16 @@
static DEFINE_IDA(rng_index_ida);
struct virtrng_info {
- struct virtio_device *vdev;
struct hwrng hwrng;
struct virtqueue *vq;
- unsigned int data_avail;
struct completion have_data;
- bool busy;
char name[25];
+ unsigned int data_avail;
int index;
+ bool busy;
+ bool hwrng_register_done;
};
-static bool probe_done;
static void random_recv_done(struct virtqueue *vq)
{
@@ -69,13 +68,6 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
- /*
- * Don't ask host for data till we're setup. This call can
- * happen during hwrng_register(), after commit d9e7972619.
- */
- if (unlikely(!probe_done))
- return 0;
-
if (!vi->busy) {
vi->busy = true;
init_completion(&vi->have_data);
@@ -124,6 +116,7 @@ static int probe_common(struct virtio_device *vdev)
.cleanup = virtio_cleanup,
.priv = (unsigned long)vi,
.name = vi->name,
+ .quality = 1000,
};
vdev->priv = vi;
@@ -137,25 +130,17 @@ static int probe_common(struct virtio_device *vdev)
return err;
}
- err = hwrng_register(&vi->hwrng);
- if (err) {
- vdev->config->del_vqs(vdev);
- vi->vq = NULL;
- kfree(vi);
- ida_simple_remove(&rng_index_ida, index);
- return err;
- }
-
- probe_done = true;
return 0;
}
static void remove_common(struct virtio_device *vdev)
{
struct virtrng_info *vi = vdev->priv;
+
vdev->config->reset(vdev);
vi->busy = false;
- hwrng_unregister(&vi->hwrng);
+ if (vi->hwrng_register_done)
+ hwrng_unregister(&vi->hwrng);
vdev->config->del_vqs(vdev);
ida_simple_remove(&rng_index_ida, vi->index);
kfree(vi);
@@ -171,6 +156,16 @@ static void virtrng_remove(struct virtio_device *vdev)
remove_common(vdev);
}
+static void virtrng_scan(struct virtio_device *vdev)
+{
+ struct virtrng_info *vi = vdev->priv;
+ int err;
+
+ err = hwrng_register(&vi->hwrng);
+ if (!err)
+ vi->hwrng_register_done = true;
+}
+
#ifdef CONFIG_PM_SLEEP
static int virtrng_freeze(struct virtio_device *vdev)
{
@@ -195,6 +190,7 @@ static struct virtio_driver virtio_rng_driver = {
.id_table = id_table,
.probe = virtrng_probe,
.remove = virtrng_remove,
+ .scan = virtrng_scan,
#ifdef CONFIG_PM_SLEEP
.freeze = virtrng_freeze,
.restore = virtrng_restore,
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 93dcad0c1cbe..65525c7e903c 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -65,6 +65,8 @@ static char bios_version[4];
static struct device *i8k_hwmon_dev;
static u32 i8k_hwmon_flags;
static int i8k_fan_mult;
+static int i8k_pwm_mult;
+static int i8k_fan_max = I8K_FAN_HIGH;
#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
@@ -97,6 +99,10 @@ static int fan_mult = I8K_FAN_MULT;
module_param(fan_mult, int, 0);
MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
+static int fan_max = I8K_FAN_HIGH;
+module_param(fan_max, int, 0);
+MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed");
+
static int i8k_open_fs(struct inode *inode, struct file *file);
static long i8k_ioctl(struct file *, unsigned int, unsigned long);
@@ -276,7 +282,7 @@ static int i8k_set_fan(int fan, int speed)
{
struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
- speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
regs.ebx = (fan & 0xff) | (speed << 8);
return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
@@ -521,7 +527,7 @@ static ssize_t i8k_hwmon_show_pwm(struct device *dev,
status = i8k_get_fan_status(index);
if (status < 0)
return -EIO;
- return sprintf(buf, "%d\n", clamp_val(status * 128, 0, 255));
+ return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
}
static ssize_t i8k_hwmon_set_pwm(struct device *dev,
@@ -535,7 +541,7 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev,
err = kstrtoul(buf, 10, &val);
if (err)
return err;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 128), 0, 2);
+ val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
mutex_lock(&i8k_mutex);
err = i8k_set_fan(index, val);
@@ -544,20 +550,6 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev,
return err < 0 ? -EIO : count;
}
-static ssize_t i8k_hwmon_show_label(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- static const char *labels[3] = {
- "CPU",
- "Left Fan",
- "Right Fan",
- };
- int index = to_sensor_dev_attr(devattr)->index;
-
- return sprintf(buf, "%s\n", labels[index]);
-}
-
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
@@ -570,41 +562,34 @@ static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
I8K_FAN_RIGHT);
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
i8k_hwmon_set_pwm, I8K_FAN_RIGHT);
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2);
static struct attribute *i8k_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */
- &sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */
- &sensor_dev_attr_temp2_input.dev_attr.attr, /* 2 */
- &sensor_dev_attr_temp3_input.dev_attr.attr, /* 3 */
- &sensor_dev_attr_temp4_input.dev_attr.attr, /* 4 */
- &sensor_dev_attr_fan1_input.dev_attr.attr, /* 5 */
- &sensor_dev_attr_pwm1.dev_attr.attr, /* 6 */
- &sensor_dev_attr_fan1_label.dev_attr.attr, /* 7 */
- &sensor_dev_attr_fan2_input.dev_attr.attr, /* 8 */
- &sensor_dev_attr_pwm2.dev_attr.attr, /* 9 */
- &sensor_dev_attr_fan2_label.dev_attr.attr, /* 10 */
+ &sensor_dev_attr_temp2_input.dev_attr.attr, /* 1 */
+ &sensor_dev_attr_temp3_input.dev_attr.attr, /* 2 */
+ &sensor_dev_attr_temp4_input.dev_attr.attr, /* 3 */
+ &sensor_dev_attr_fan1_input.dev_attr.attr, /* 4 */
+ &sensor_dev_attr_pwm1.dev_attr.attr, /* 5 */
+ &sensor_dev_attr_fan2_input.dev_attr.attr, /* 6 */
+ &sensor_dev_attr_pwm2.dev_attr.attr, /* 7 */
NULL
};
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
- if ((index == 0 || index == 1) &&
- !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
+ if (index == 0 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
return 0;
- if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
+ if (index == 1 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
return 0;
- if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
+ if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
return 0;
- if (index == 4 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
+ if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
return 0;
- if (index >= 5 && index <= 7 &&
+ if (index >= 4 && index <= 5 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
return 0;
- if (index >= 8 && index <= 10 &&
+ if (index >= 6 && index <= 7 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
return 0;
@@ -659,6 +644,37 @@ static int __init i8k_init_hwmon(void)
return 0;
}
+struct i8k_config_data {
+ int fan_mult;
+ int fan_max;
+};
+
+enum i8k_configs {
+ DELL_LATITUDE_D520,
+ DELL_PRECISION_490,
+ DELL_STUDIO,
+ DELL_XPS_M140,
+};
+
+static const struct i8k_config_data i8k_config_data[] = {
+ [DELL_LATITUDE_D520] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_TURBO,
+ },
+ [DELL_PRECISION_490] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_TURBO,
+ },
+ [DELL_STUDIO] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_HIGH,
+ },
+ [DELL_XPS_M140] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_HIGH,
+ },
+};
+
static struct dmi_system_id i8k_dmi_table[] __initdata = {
{
.ident = "Dell Inspiron",
@@ -682,6 +698,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
},
},
{
+ .ident = "Dell Latitude D520",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
+ },
+ .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
+ },
+ {
.ident = "Dell Latitude 2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -703,6 +727,15 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
},
},
{
+ .ident = "Dell Precision 490",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME,
+ "Precision WorkStation 490"),
+ },
+ .driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
+ },
+ {
.ident = "Dell Precision",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -729,7 +762,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
},
- .driver_data = (void *)1, /* fan multiplier override */
+ .driver_data = (void *)&i8k_config_data[DELL_STUDIO],
},
{
.ident = "Dell XPS M140",
@@ -737,7 +770,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
},
- .driver_data = (void *)1, /* fan multiplier override */
+ .driver_data = (void *)&i8k_config_data[DELL_XPS_M140],
},
{ }
};
@@ -777,9 +810,17 @@ static int __init i8k_probe(void)
}
i8k_fan_mult = fan_mult;
+ i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */
id = dmi_first_match(i8k_dmi_table);
- if (id && fan_mult == I8K_FAN_MULT && id->driver_data)
- i8k_fan_mult = (unsigned long)id->driver_data;
+ if (id && id->driver_data) {
+ const struct i8k_config_data *conf = id->driver_data;
+
+ if (fan_mult == I8K_FAN_MULT && conf->fan_mult)
+ i8k_fan_mult = conf->fan_mult;
+ if (fan_max == I8K_FAN_HIGH && conf->fan_max)
+ i8k_fan_max = conf->fan_max;
+ }
+ i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
return 0;
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 8320abd1ef14..0ea9986059af 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
__FILE__, __LINE__, info->device_name, port->count);
- WARN_ON(!port->count);
-
if (tty_port_close_start(port, tty, filp) == 0)
goto cleanup;
@@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
__FILE__, __LINE__, tty->driver->name, port->count);
/* If port is closing, signal caller to try again */
- if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
+ if (port->flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 71529e196b84..c18d41db83d8 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -250,6 +250,7 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
+#include <linux/kthread.h>
#include <linux/percpu.h>
#include <linux/cryptohash.h>
#include <linux/fips.h>
@@ -257,6 +258,8 @@
#include <linux/kmemcheck.h>
#include <linux/workqueue.h>
#include <linux/irq.h>
+#include <linux/syscalls.h>
+#include <linux/completion.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
@@ -267,6 +270,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/random.h>
+/* #define ADD_INTERRUPT_BENCH */
+
/*
* Configuration information
*/
@@ -401,6 +406,7 @@ static struct poolinfo {
*/
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(urandom_init_wait);
static struct fasync_struct *fasync;
/**********************************************************************
@@ -481,9 +487,9 @@ static __u32 const twist_table[8] = {
* the entropy is concentrated in the low-order bits.
*/
static void _mix_pool_bytes(struct entropy_store *r, const void *in,
- int nbytes, __u8 out[64])
+ int nbytes)
{
- unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+ unsigned long i, tap1, tap2, tap3, tap4, tap5;
int input_rotate;
int wordmask = r->poolinfo->poolwords - 1;
const char *bytes = in;
@@ -495,9 +501,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
tap4 = r->poolinfo->tap4;
tap5 = r->poolinfo->tap5;
- smp_rmb();
- input_rotate = ACCESS_ONCE(r->input_rotate);
- i = ACCESS_ONCE(r->add_ptr);
+ input_rotate = r->input_rotate;
+ i = r->add_ptr;
/* mix one byte at a time to simplify size handling and churn faster */
while (nbytes--) {
@@ -524,39 +529,33 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
}
- ACCESS_ONCE(r->input_rotate) = input_rotate;
- ACCESS_ONCE(r->add_ptr) = i;
- smp_wmb();
-
- if (out)
- for (j = 0; j < 16; j++)
- ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+ r->input_rotate = input_rotate;
+ r->add_ptr = i;
}
static void __mix_pool_bytes(struct entropy_store *r, const void *in,
- int nbytes, __u8 out[64])
+ int nbytes)
{
trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
- _mix_pool_bytes(r, in, nbytes, out);
+ _mix_pool_bytes(r, in, nbytes);
}
static void mix_pool_bytes(struct entropy_store *r, const void *in,
- int nbytes, __u8 out[64])
+ int nbytes)
{
unsigned long flags;
trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
spin_lock_irqsave(&r->lock, flags);
- _mix_pool_bytes(r, in, nbytes, out);
+ _mix_pool_bytes(r, in, nbytes);
spin_unlock_irqrestore(&r->lock, flags);
}
struct fast_pool {
__u32 pool[4];
unsigned long last;
- unsigned short count;
- unsigned char rotate;
- unsigned char last_timer_intr;
+ unsigned short reg_idx;
+ unsigned char count;
};
/*
@@ -564,25 +563,29 @@ struct fast_pool {
* collector. It's hardcoded for an 128 bit pool and assumes that any
* locks that might be needed are taken by the caller.
*/
-static void fast_mix(struct fast_pool *f, __u32 input[4])
+static void fast_mix(struct fast_pool *f)
{
- __u32 w;
- unsigned input_rotate = f->rotate;
-
- w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
- f->pool[0] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 14) & 31;
- w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
- f->pool[1] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
- w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
- f->pool[2] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
- w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
- f->pool[3] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
-
- f->rotate = input_rotate;
+ __u32 a = f->pool[0], b = f->pool[1];
+ __u32 c = f->pool[2], d = f->pool[3];
+
+ a += b; c += d;
+ b = rol32(a, 6); d = rol32(c, 27);
+ d ^= a; b ^= c;
+
+ a += b; c += d;
+ b = rol32(a, 16); d = rol32(c, 14);
+ d ^= a; b ^= c;
+
+ a += b; c += d;
+ b = rol32(a, 6); d = rol32(c, 27);
+ d ^= a; b ^= c;
+
+ a += b; c += d;
+ b = rol32(a, 16); d = rol32(c, 14);
+ d ^= a; b ^= c;
+
+ f->pool[0] = a; f->pool[1] = b;
+ f->pool[2] = c; f->pool[3] = d;
f->count++;
}
@@ -657,6 +660,7 @@ retry:
r->entropy_total = 0;
if (r == &nonblocking_pool) {
prandom_reseed_late();
+ wake_up_interruptible(&urandom_init_wait);
pr_notice("random: %s pool is initialized\n", r->name);
}
}
@@ -739,13 +743,13 @@ void add_device_randomness(const void *buf, unsigned int size)
trace_add_device_randomness(size, _RET_IP_);
spin_lock_irqsave(&input_pool.lock, flags);
- _mix_pool_bytes(&input_pool, buf, size, NULL);
- _mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+ _mix_pool_bytes(&input_pool, buf, size);
+ _mix_pool_bytes(&input_pool, &time, sizeof(time));
spin_unlock_irqrestore(&input_pool.lock, flags);
spin_lock_irqsave(&nonblocking_pool.lock, flags);
- _mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
- _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
+ _mix_pool_bytes(&nonblocking_pool, buf, size);
+ _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time));
spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
}
EXPORT_SYMBOL(add_device_randomness);
@@ -778,7 +782,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
sample.cycles = random_get_entropy();
sample.num = num;
r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
- mix_pool_bytes(r, &sample, sizeof(sample), NULL);
+ mix_pool_bytes(r, &sample, sizeof(sample));
/*
* Calculate number of bits of randomness we probably added.
@@ -835,6 +839,38 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+#ifdef ADD_INTERRUPT_BENCH
+static unsigned long avg_cycles, avg_deviation;
+
+#define AVG_SHIFT 8 /* Exponential average factor k=1/256 */
+#define FIXED_1_2 (1 << (AVG_SHIFT-1))
+
+static void add_interrupt_bench(cycles_t start)
+{
+ long delta = random_get_entropy() - start;
+
+ /* Use a weighted moving average */
+ delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
+ avg_cycles += delta;
+ /* And average deviation */
+ delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
+ avg_deviation += delta;
+}
+#else
+#define add_interrupt_bench(x)
+#endif
+
+static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
+{
+ __u32 *ptr = (__u32 *) regs;
+
+ if (regs == NULL)
+ return 0;
+ if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
+ f->reg_idx = 0;
+ return *(ptr + f->reg_idx++);
+}
+
void add_interrupt_randomness(int irq, int irq_flags)
{
struct entropy_store *r;
@@ -842,55 +878,52 @@ void add_interrupt_randomness(int irq, int irq_flags)
struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
cycles_t cycles = random_get_entropy();
- __u32 input[4], c_high, j_high;
+ __u32 c_high, j_high;
__u64 ip;
unsigned long seed;
- int credit;
+ int credit = 0;
+ if (cycles == 0)
+ cycles = get_reg(fast_pool, regs);
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
- input[0] = cycles ^ j_high ^ irq;
- input[1] = now ^ c_high;
+ fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
+ fast_pool->pool[1] ^= now ^ c_high;
ip = regs ? instruction_pointer(regs) : _RET_IP_;
- input[2] = ip;
- input[3] = ip >> 32;
+ fast_pool->pool[2] ^= ip;
+ fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
+ get_reg(fast_pool, regs);
- fast_mix(fast_pool, input);
+ fast_mix(fast_pool);
+ add_interrupt_bench(cycles);
- if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+ if ((fast_pool->count < 64) &&
+ !time_after(now, fast_pool->last + HZ))
return;
- fast_pool->last = now;
-
r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
- __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+ if (!spin_trylock(&r->lock))
+ return;
- /*
- * If we don't have a valid cycle counter, and we see
- * back-to-back timer interrupts, then skip giving credit for
- * any entropy, otherwise credit 1 bit.
- */
- credit = 1;
- if (cycles == 0) {
- if (irq_flags & __IRQF_TIMER) {
- if (fast_pool->last_timer_intr)
- credit = 0;
- fast_pool->last_timer_intr = 1;
- } else
- fast_pool->last_timer_intr = 0;
- }
+ fast_pool->last = now;
+ __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
/*
* If we have architectural seed generator, produce a seed and
- * add it to the pool. For the sake of paranoia count it as
- * 50% entropic.
+ * add it to the pool. For the sake of paranoia don't let the
+ * architectural seed generator dominate the input from the
+ * interrupt noise.
*/
if (arch_get_random_seed_long(&seed)) {
- __mix_pool_bytes(r, &seed, sizeof(seed), NULL);
- credit += sizeof(seed) * 4;
+ __mix_pool_bytes(r, &seed, sizeof(seed));
+ credit = 1;
}
+ spin_unlock(&r->lock);
- credit_entropy_bits(r, credit);
+ fast_pool->count = 0;
+
+ /* award one bit for the contents of the fast pool */
+ credit_entropy_bits(r, credit + 1);
}
#ifdef CONFIG_BLOCK
@@ -922,6 +955,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
+ if (!r->pull ||
+ r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
+ r->entropy_count > r->poolinfo->poolfracbits)
+ return;
+
if (r->limit == 0 && random_min_urandom_seed) {
unsigned long now = jiffies;
@@ -930,10 +968,8 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
return;
r->last_pulled = now;
}
- if (r->pull &&
- r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
- r->entropy_count < r->poolinfo->poolfracbits)
- _xfer_secondary_pool(r, nbytes);
+
+ _xfer_secondary_pool(r, nbytes);
}
static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
@@ -953,7 +989,7 @@ static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
bytes = extract_entropy(r->pull, tmp, bytes,
random_read_wakeup_bits / 8, rsvd_bytes);
- mix_pool_bytes(r, tmp, bytes, NULL);
+ mix_pool_bytes(r, tmp, bytes);
credit_entropy_bits(r, bytes*8);
}
@@ -1039,7 +1075,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
unsigned long l[LONGS(20)];
} hash;
__u32 workspace[SHA_WORKSPACE_WORDS];
- __u8 extract[64];
unsigned long flags;
/*
@@ -1068,15 +1103,9 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
* brute-forcing the feedback as hard as brute-forcing the
* hash.
*/
- __mix_pool_bytes(r, hash.w, sizeof(hash.w), extract);
+ __mix_pool_bytes(r, hash.w, sizeof(hash.w));
spin_unlock_irqrestore(&r->lock, flags);
- /*
- * To avoid duplicates, we atomically extract a portion of the
- * pool while mixing, and hash one final time.
- */
- sha_transform(hash.w, extract, workspace);
- memset(extract, 0, sizeof(extract));
memset(workspace, 0, sizeof(workspace));
/*
@@ -1160,13 +1189,14 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
{
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
+ int large_request = (nbytes > 256);
trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
while (nbytes) {
- if (need_resched()) {
+ if (large_request && need_resched()) {
if (signal_pending(current)) {
if (ret == 0)
ret = -ERESTARTSYS;
@@ -1263,14 +1293,14 @@ static void init_std_data(struct entropy_store *r)
unsigned long rv;
r->last_pulled = jiffies;
- mix_pool_bytes(r, &now, sizeof(now), NULL);
+ mix_pool_bytes(r, &now, sizeof(now));
for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
if (!arch_get_random_seed_long(&rv) &&
!arch_get_random_long(&rv))
rv = random_get_entropy();
- mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+ mix_pool_bytes(r, &rv, sizeof(rv));
}
- mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
+ mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
}
/*
@@ -1309,39 +1339,8 @@ void rand_initialize_disk(struct gendisk *disk)
}
#endif
-/*
- * Attempt an emergency refill using arch_get_random_seed_long().
- *
- * As with add_interrupt_randomness() be paranoid and only
- * credit the output as 50% entropic.
- */
-static int arch_random_refill(void)
-{
- const unsigned int nlongs = 64; /* Arbitrary number */
- unsigned int n = 0;
- unsigned int i;
- unsigned long buf[nlongs];
-
- if (!arch_has_random_seed())
- return 0;
-
- for (i = 0; i < nlongs; i++) {
- if (arch_get_random_seed_long(&buf[n]))
- n++;
- }
-
- if (n) {
- unsigned int rand_bytes = n * sizeof(unsigned long);
-
- mix_pool_bytes(&input_pool, buf, rand_bytes, NULL);
- credit_entropy_bits(&input_pool, rand_bytes*4);
- }
-
- return n;
-}
-
static ssize_t
-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+_random_read(int nonblock, char __user *buf, size_t nbytes)
{
ssize_t n;
@@ -1360,12 +1359,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
return n;
/* Pool is (near) empty. Maybe wait and retry. */
-
- /* First try an emergency refill */
- if (arch_random_refill())
- continue;
-
- if (file->f_flags & O_NONBLOCK)
+ if (nonblock)
return -EAGAIN;
wait_event_interruptible(random_read_wait,
@@ -1377,6 +1371,12 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
}
static ssize_t
+random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+{
+ return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
+}
+
+static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
int ret;
@@ -1424,7 +1424,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
count -= bytes;
p += bytes;
- mix_pool_bytes(r, buf, bytes, NULL);
+ mix_pool_bytes(r, buf, bytes);
cond_resched();
}
@@ -1520,6 +1520,29 @@ const struct file_operations urandom_fops = {
.llseek = noop_llseek,
};
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ unsigned int, flags)
+{
+ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+ return -EINVAL;
+
+ if (count > INT_MAX)
+ count = INT_MAX;
+
+ if (flags & GRND_RANDOM)
+ return _random_read(flags & GRND_NONBLOCK, buf, count);
+
+ if (unlikely(nonblocking_pool.initialized == 0)) {
+ if (flags & GRND_NONBLOCK)
+ return -EAGAIN;
+ wait_event_interruptible(urandom_init_wait,
+ nonblocking_pool.initialized);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+ return urandom_read(NULL, buf, count, NULL);
+}
+
/***************************************************************
* Random UUID interface
*
@@ -1663,6 +1686,22 @@ struct ctl_table random_table[] = {
.mode = 0444,
.proc_handler = proc_do_uuid,
},
+#ifdef ADD_INTERRUPT_BENCH
+ {
+ .procname = "add_interrupt_avg_cycles",
+ .data = &avg_cycles,
+ .maxlen = sizeof(avg_cycles),
+ .mode = 0444,
+ .proc_handler = proc_doulongvec_minmax,
+ },
+ {
+ .procname = "add_interrupt_avg_deviation",
+ .data = &avg_deviation,
+ .maxlen = sizeof(avg_deviation),
+ .mode = 0444,
+ .proc_handler = proc_doulongvec_minmax,
+ },
+#endif
{ }
};
#endif /* CONFIG_SYSCTL */
@@ -1719,3 +1758,23 @@ randomize_range(unsigned long start, unsigned long end, unsigned long len)
return 0;
return PAGE_ALIGN(get_random_int() % range + start);
}
+
+/* Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
+ */
+void add_hwgenerator_randomness(const char *buffer, size_t count,
+ size_t entropy)
+{
+ struct entropy_store *poolp = &input_pool;
+
+ /* Suspend writing if we're above the trickle threshold.
+ * We'll be woken up again once below random_write_wakeup_thresh,
+ * or when the calling thread is about to terminate.
+ */
+ wait_event_interruptible(random_write_wait, kthread_should_stop() ||
+ ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+ mix_pool_bytes(poolp, buffer, count);
+ credit_entropy_bits(poolp, entropy);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 62e10fd1e1cb..6af17002a115 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -491,11 +491,10 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
int tpm_get_timeouts(struct tpm_chip *chip)
{
struct tpm_cmd_t tpm_cmd;
- struct timeout_t *timeout_cap;
+ unsigned long new_timeout[4];
+ unsigned long old_timeout[4];
struct duration_t *duration_cap;
ssize_t rc;
- u32 timeout;
- unsigned int scale = 1;
tpm_cmd.header.in = tpm_getcap_header;
tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -529,25 +528,46 @@ int tpm_get_timeouts(struct tpm_chip *chip)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
return -EINVAL;
- timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
- /* Don't overwrite default if value is 0 */
- timeout = be32_to_cpu(timeout_cap->a);
- if (timeout && timeout < 1000) {
- /* timeouts in msec rather usec */
- scale = 1000;
- chip->vendor.timeout_adjusted = true;
+ old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a);
+ old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b);
+ old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c);
+ old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d);
+ memcpy(new_timeout, old_timeout, sizeof(new_timeout));
+
+ /*
+ * Provide ability for vendor overrides of timeout values in case
+ * of misreporting.
+ */
+ if (chip->ops->update_timeouts != NULL)
+ chip->vendor.timeout_adjusted =
+ chip->ops->update_timeouts(chip, new_timeout);
+
+ if (!chip->vendor.timeout_adjusted) {
+ /* Don't overwrite default if value is 0 */
+ if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
+ int i;
+
+ /* timeouts in msec rather usec */
+ for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
+ new_timeout[i] *= 1000;
+ chip->vendor.timeout_adjusted = true;
+ }
+ }
+
+ /* Report adjusted timeouts */
+ if (chip->vendor.timeout_adjusted) {
+ dev_info(chip->dev,
+ HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
+ old_timeout[0], new_timeout[0],
+ old_timeout[1], new_timeout[1],
+ old_timeout[2], new_timeout[2],
+ old_timeout[3], new_timeout[3]);
}
- if (timeout)
- chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
- timeout = be32_to_cpu(timeout_cap->b);
- if (timeout)
- chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
- timeout = be32_to_cpu(timeout_cap->c);
- if (timeout)
- chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
- timeout = be32_to_cpu(timeout_cap->d);
- if (timeout)
- chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
+
+ chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]);
+ chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]);
+ chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]);
+ chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]);
duration:
tpm_cmd.header.in = tpm_getcap_header;
@@ -991,13 +1011,13 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
int err, total = 0, retries = 5;
u8 *dest = out;
+ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+ return -EINVAL;
+
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
return -ENODEV;
- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
- return -EINVAL;
-
do {
tpm_cmd.header.in = tpm_getrandom_header;
tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
@@ -1016,6 +1036,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
num_bytes -= recd;
} while (retries-- && total < max);
+ tpm_chip_put(chip);
return total ? total : -EIO;
}
EXPORT_SYMBOL_GPL(tpm_get_random);
@@ -1095,7 +1116,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
goto del_misc;
if (tpm_add_ppi(&dev->kobj))
- goto del_misc;
+ goto del_sysfs;
chip->bios_dir = tpm_bios_log_setup(chip->devname);
@@ -1106,6 +1127,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
return chip;
+del_sysfs:
+ tpm_sysfs_del_device(chip);
del_misc:
tpm_dev_del_device(chip);
put_device:
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
index 59f7cb28260b..3a56a131586c 100644
--- a/drivers/char/tpm/tpm_eventlog.c
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -235,7 +235,6 @@ static int tpm_bios_measurements_release(struct inode *inode,
static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
{
int len = 0;
- int i;
char *eventname;
struct tcpa_event *event = v;
unsigned char *event_entry =
@@ -251,8 +250,7 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
seq_printf(m, "%2d ", event->pcr_index);
/* 2nd: SHA1 */
- for (i = 0; i < 20; i++)
- seq_printf(m, "%02x", event->pcr_value[i]);
+ seq_printf(m, "%20phN", event->pcr_value);
/* 3rd: event type identifier */
seq_printf(m, " %02x", event->event_type);
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
index 3b7bf2162898..4669e3713428 100644
--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
+++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
@@ -714,6 +714,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
tpm_get_timeouts(chip);
+ tpm_do_selftest(chip);
dev_info(chip->dev, "TPM I2C Initialized\n");
return 0;
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index a9ed2270c25d..2c46734b266d 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -373,6 +373,36 @@ out_err:
return rc;
}
+struct tis_vendor_timeout_override {
+ u32 did_vid;
+ unsigned long timeout_us[4];
+};
+
+static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
+ /* Atmel 3204 */
+ { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000),
+ (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } },
+};
+
+static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
+ unsigned long *timeout_cap)
+{
+ int i;
+ u32 did_vid;
+
+ did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+
+ for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
+ if (vendor_timeout_overrides[i].did_vid != did_vid)
+ continue;
+ memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
+ sizeof(vendor_timeout_overrides[i].timeout_us));
+ return true;
+ }
+
+ return false;
+}
+
/*
* Early probing for iTPM with STS_DATA_EXPECT flaw.
* Try sending command without itpm flag set and if that
@@ -437,6 +467,7 @@ static const struct tpm_class_ops tpm_tis = {
.recv = tpm_tis_recv,
.send = tpm_tis_send,
.cancel = tpm_tis_ready,
+ .update_timeouts = tpm_tis_update_timeouts,
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
.req_canceled = tpm_tis_req_canceled,
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 60aafb8a1f2e..b585b4789822 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -2262,8 +2262,7 @@ static int __init init(void)
unregister:
unregister_virtio_driver(&virtio_console);
free:
- if (pdrvdata.debugfs_dir)
- debugfs_remove_recursive(pdrvdata.debugfs_dir);
+ debugfs_remove_recursive(pdrvdata.debugfs_dir);
class_destroy(pdrvdata.class);
return err;
}
@@ -2276,8 +2275,7 @@ static void __exit fini(void)
unregister_virtio_driver(&virtio_rproc_serial);
class_destroy(pdrvdata.class);
- if (pdrvdata.debugfs_dir)
- debugfs_remove_recursive(pdrvdata.debugfs_dir);
+ debugfs_remove_recursive(pdrvdata.debugfs_dir);
}
module_init(init);
module_exit(fini);
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index f6345f932e46..9b1a5ac4881d 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -661,6 +661,7 @@ static int hwicap_setup(struct device *dev, int id,
drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
if (!drvdata->base_address) {
dev_err(dev, "ioremap() failed\n");
+ retval = -ENOMEM;
goto failed2;
}
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9f9c5ae5359b..cfd3af7b2cbd 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -102,6 +102,13 @@ config COMMON_CLK_KEYSTONE
Supports clock drivers for Keystone based SOCs. These SOCs have local
a power sleep control module that gate the clock to the IPs and PLLs.
+config COMMON_CLK_PALMAS
+ tristate "Clock driver for TI Palmas devices"
+ depends on MFD_PALMAS
+ ---help---
+ This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
+ using common clock framework.
+
source "drivers/clk/qcom/Kconfig"
endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 567f10259029..f537a0b1f798 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -9,12 +9,16 @@ obj-$(CONFIG_COMMON_CLK) += clk-gate.o
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
+ifeq ($(CONFIG_OF), y)
+obj-$(CONFIG_COMMON_CLK) += clk-conf.o
+endif
# hardware specific clock types
# please keep this section sorted lexicographically by file/directory path name
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
+obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
@@ -22,6 +26,7 @@ obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 733306131b99..59fa3cc96c9e 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -388,6 +388,7 @@ static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
if (parent_rate)
return parent_rate;
+ pr_warn("Main crystal frequency not set, using approximate value\n");
tmp = pmc_read(pmc, AT91_CKGR_MCFR);
if (!(tmp & AT91_PMC_MAINRDY))
return 0;
diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c
new file mode 100644
index 000000000000..715eec1a9902
--- /dev/null
+++ b/drivers/clk/clk-clps711x.c
@@ -0,0 +1,192 @@
+/*
+ * Cirrus Logic CLPS711X CLK driver
+ *
+ * Copyright (C) 2014 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/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon/clps711x.h>
+
+#include <dt-bindings/clock/clps711x-clock.h>
+
+#define CLPS711X_SYSCON1 (0x0100)
+#define CLPS711X_SYSCON2 (0x1100)
+#define CLPS711X_SYSFLG2 (CLPS711X_SYSCON2 + SYSFLG_OFFSET)
+#define CLPS711X_PLLR (0xa5a8)
+
+#define CLPS711X_EXT_FREQ (13000000)
+#define CLPS711X_OSC_FREQ (3686400)
+
+static const struct clk_div_table spi_div_table[] = {
+ { .val = 0, .div = 32, },
+ { .val = 1, .div = 8, },
+ { .val = 2, .div = 2, },
+ { .val = 3, .div = 1, },
+};
+
+static const struct clk_div_table timer_div_table[] = {
+ { .val = 0, .div = 256, },
+ { .val = 1, .div = 1, },
+};
+
+struct clps711x_clk {
+ struct clk_onecell_data clk_data;
+ spinlock_t lock;
+ struct clk *clks[CLPS711X_CLK_MAX];
+};
+
+static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
+ u32 fref)
+{
+ u32 tmp, f_cpu, f_pll, f_bus, f_tim, f_pwm, f_spi;
+ struct clps711x_clk *clps711x_clk;
+ unsigned i;
+
+ if (!base)
+ return ERR_PTR(-ENOMEM);
+
+ clps711x_clk = kzalloc(sizeof(*clps711x_clk), GFP_KERNEL);
+ if (!clps711x_clk)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&clps711x_clk->lock);
+
+ /* Read PLL multiplier value and sanity check */
+ tmp = readl(base + CLPS711X_PLLR) >> 24;
+ if (((tmp >= 10) && (tmp <= 50)) || !fref)
+ f_pll = DIV_ROUND_UP(CLPS711X_OSC_FREQ * tmp, 2);
+ else
+ f_pll = fref;
+
+ tmp = readl(base + CLPS711X_SYSFLG2);
+ if (tmp & SYSFLG2_CKMODE) {
+ f_cpu = CLPS711X_EXT_FREQ;
+ f_bus = CLPS711X_EXT_FREQ;
+ f_spi = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 96);
+ f_pll = 0;
+ f_pwm = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 128);
+ } else {
+ f_cpu = f_pll;
+ if (f_cpu > 36864000)
+ f_bus = DIV_ROUND_UP(f_cpu, 2);
+ else
+ f_bus = 36864000 / 2;
+ f_spi = DIV_ROUND_CLOSEST(f_cpu, 576);
+ f_pwm = DIV_ROUND_CLOSEST(f_cpu, 768);
+ }
+
+ if (tmp & SYSFLG2_CKMODE) {
+ if (readl(base + CLPS711X_SYSCON2) & SYSCON2_OSTB)
+ f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 26);
+ else
+ f_tim = DIV_ROUND_CLOSEST(CLPS711X_EXT_FREQ, 24);
+ } else
+ f_tim = DIV_ROUND_CLOSEST(f_cpu, 144);
+
+ tmp = readl(base + CLPS711X_SYSCON1);
+ /* Timer1 in free running mode.
+ * Counter will wrap around to 0xffff when it underflows
+ * and will continue to count down.
+ */
+ tmp &= ~(SYSCON1_TC1M | SYSCON1_TC1S);
+ /* Timer2 in prescale mode.
+ * Value writen is automatically re-loaded when
+ * the counter underflows.
+ */
+ tmp |= SYSCON1_TC2M | SYSCON1_TC2S;
+ writel(tmp, base + CLPS711X_SYSCON1);
+
+ clps711x_clk->clks[CLPS711X_CLK_DUMMY] =
+ clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0);
+ clps711x_clk->clks[CLPS711X_CLK_CPU] =
+ clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu);
+ clps711x_clk->clks[CLPS711X_CLK_BUS] =
+ clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus);
+ clps711x_clk->clks[CLPS711X_CLK_PLL] =
+ clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll);
+ clps711x_clk->clks[CLPS711X_CLK_TIMERREF] =
+ clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT,
+ f_tim);
+ clps711x_clk->clks[CLPS711X_CLK_TIMER1] =
+ clk_register_divider_table(NULL, "timer1", "timer_ref", 0,
+ base + CLPS711X_SYSCON1, 5, 1, 0,
+ timer_div_table, &clps711x_clk->lock);
+ clps711x_clk->clks[CLPS711X_CLK_TIMER2] =
+ clk_register_divider_table(NULL, "timer2", "timer_ref", 0,
+ base + CLPS711X_SYSCON1, 7, 1, 0,
+ timer_div_table, &clps711x_clk->lock);
+ clps711x_clk->clks[CLPS711X_CLK_PWM] =
+ clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm);
+ clps711x_clk->clks[CLPS711X_CLK_SPIREF] =
+ clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT,
+ f_spi);
+ clps711x_clk->clks[CLPS711X_CLK_SPI] =
+ clk_register_divider_table(NULL, "spi", "spi_ref", 0,
+ base + CLPS711X_SYSCON1, 16, 2, 0,
+ spi_div_table, &clps711x_clk->lock);
+ clps711x_clk->clks[CLPS711X_CLK_UART] =
+ clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10);
+ clps711x_clk->clks[CLPS711X_CLK_TICK] =
+ clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64);
+
+ for (i = 0; i < CLPS711X_CLK_MAX; i++)
+ if (IS_ERR(clps711x_clk->clks[i]))
+ pr_err("clk %i: register failed with %ld\n",
+ i, PTR_ERR(clps711x_clk->clks[i]));
+
+ return clps711x_clk;
+}
+
+void __init clps711x_clk_init(void __iomem *base)
+{
+ struct clps711x_clk *clps711x_clk;
+
+ clps711x_clk = _clps711x_clk_init(base, 73728000);
+
+ BUG_ON(IS_ERR(clps711x_clk));
+
+ /* Clocksource */
+ clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER1],
+ NULL, "clps711x-timer.0");
+ clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_TIMER2],
+ NULL, "clps711x-timer.1");
+
+ /* Drivers */
+ clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_PWM],
+ NULL, "clps711x-pwm");
+ clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
+ NULL, "clps711x-uart.0");
+ clk_register_clkdev(clps711x_clk->clks[CLPS711X_CLK_UART],
+ NULL, "clps711x-uart.1");
+}
+
+#ifdef CONFIG_OF
+static void __init clps711x_clk_init_dt(struct device_node *np)
+{
+ void __iomem *base = of_iomap(np, 0);
+ struct clps711x_clk *clps711x_clk;
+ u32 fref = 0;
+
+ WARN_ON(of_property_read_u32(np, "startup-frequency", &fref));
+
+ clps711x_clk = _clps711x_clk_init(base, fref);
+ BUG_ON(IS_ERR(clps711x_clk));
+
+ clps711x_clk->clk_data.clks = clps711x_clk->clks;
+ clps711x_clk->clk_data.clk_num = CLPS711X_CLK_MAX;
+ of_clk_add_provider(np, of_clk_src_onecell_get,
+ &clps711x_clk->clk_data);
+}
+CLK_OF_DECLARE(clps711x, "cirrus,clps711x-clk", clps711x_clk_init_dt);
+#endif
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 57a078e06efe..b9355daf8065 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -64,11 +64,56 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw;
+ struct clk *parent;
+ unsigned long parent_rate;
+ long tmp_rate, best_rate = 0;
+ unsigned long rate_diff;
+ unsigned long best_rate_diff = ULONG_MAX;
+ int i;
if (rate_hw && rate_ops && rate_ops->determine_rate) {
rate_hw->clk = hw->clk;
return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
best_parent_p);
+ } else if (rate_hw && rate_ops && rate_ops->round_rate &&
+ mux_hw && mux_ops && mux_ops->set_parent) {
+ *best_parent_p = NULL;
+
+ if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
+ *best_parent_p = clk_get_parent(mux_hw->clk);
+ *best_parent_rate = __clk_get_rate(*best_parent_p);
+
+ return rate_ops->round_rate(rate_hw, rate,
+ best_parent_rate);
+ }
+
+ for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
+ parent = clk_get_parent_by_index(mux_hw->clk, i);
+ if (!parent)
+ continue;
+
+ parent_rate = __clk_get_rate(parent);
+
+ tmp_rate = rate_ops->round_rate(rate_hw, rate,
+ &parent_rate);
+ if (tmp_rate < 0)
+ continue;
+
+ rate_diff = abs(rate - tmp_rate);
+
+ if (!rate_diff || !*best_parent_p
+ || best_rate_diff > rate_diff) {
+ *best_parent_p = parent;
+ *best_parent_rate = parent_rate;
+ best_rate_diff = rate_diff;
+ best_rate = tmp_rate;
+ }
+
+ if (!rate_diff)
+ return rate;
+ }
+
+ return best_rate;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
mux_hw->clk = hw->clk;
return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
@@ -162,7 +207,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk_composite_ops = &composite->ops;
if (mux_hw && mux_ops) {
- if (!mux_ops->get_parent || !mux_ops->set_parent) {
+ if (!mux_ops->get_parent) {
clk = ERR_PTR(-EINVAL);
goto err;
}
@@ -170,7 +215,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
composite->mux_hw = mux_hw;
composite->mux_ops = mux_ops;
clk_composite_ops->get_parent = clk_composite_get_parent;
- clk_composite_ops->set_parent = clk_composite_set_parent;
+ if (mux_ops->set_parent)
+ clk_composite_ops->set_parent = clk_composite_set_parent;
if (mux_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
}
@@ -180,24 +226,27 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk = ERR_PTR(-EINVAL);
goto err;
}
+ clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
- /* .round_rate is a prerequisite for .set_rate */
- if (rate_ops->round_rate) {
- clk_composite_ops->round_rate = clk_composite_round_rate;
- if (rate_ops->set_rate) {
- clk_composite_ops->set_rate = clk_composite_set_rate;
- }
- } else {
- WARN(rate_ops->set_rate,
- "%s: missing round_rate op is required\n",
- __func__);
+ if (rate_ops->determine_rate)
+ clk_composite_ops->determine_rate =
+ clk_composite_determine_rate;
+ else if (rate_ops->round_rate)
+ clk_composite_ops->round_rate =
+ clk_composite_round_rate;
+
+ /* .set_rate requires either .round_rate or .determine_rate */
+ if (rate_ops->set_rate) {
+ if (rate_ops->determine_rate || rate_ops->round_rate)
+ clk_composite_ops->set_rate =
+ clk_composite_set_rate;
+ else
+ WARN(1, "%s: missing round_rate op is required\n",
+ __func__);
}
composite->rate_hw = rate_hw;
composite->rate_ops = rate_ops;
- clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
- if (rate_ops->determine_rate)
- clk_composite_ops->determine_rate = clk_composite_determine_rate;
}
if (gate_hw && gate_ops) {
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
new file mode 100644
index 000000000000..aad4796aa3ed
--- /dev/null
+++ b/drivers/clk/clk-conf.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/printk.h>
+#include "clk.h"
+
+static int __set_clk_parents(struct device_node *node, bool clk_supplier)
+{
+ struct of_phandle_args clkspec;
+ int index, rc, num_parents;
+ struct clk *clk, *pclk;
+
+ num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells");
+ if (num_parents == -EINVAL)
+ pr_err("clk: invalid value of clock-parents property at %s\n",
+ node->full_name);
+
+ for (index = 0; index < num_parents; index++) {
+ rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return rc;
+ }
+ if (clkspec.np == node && !clk_supplier)
+ return 0;
+ pclk = of_clk_get_by_clkspec(&clkspec);
+ if (IS_ERR(pclk)) {
+ pr_warn("clk: couldn't get parent clock %d for %s\n",
+ index, node->full_name);
+ return PTR_ERR(pclk);
+ }
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0)
+ goto err;
+ if (clkspec.np == node && !clk_supplier) {
+ rc = 0;
+ goto err;
+ }
+ clk = of_clk_get_by_clkspec(&clkspec);
+ if (IS_ERR(clk)) {
+ pr_warn("clk: couldn't get parent clock %d for %s\n",
+ index, node->full_name);
+ rc = PTR_ERR(clk);
+ goto err;
+ }
+
+ rc = clk_set_parent(clk, pclk);
+ if (rc < 0)
+ pr_err("clk: failed to reparent %s to %s: %d\n",
+ __clk_get_name(clk), __clk_get_name(pclk), rc);
+ clk_put(clk);
+ clk_put(pclk);
+ }
+ return 0;
+err:
+ clk_put(pclk);
+ return rc;
+}
+
+static int __set_clk_rates(struct device_node *node, bool clk_supplier)
+{
+ struct of_phandle_args clkspec;
+ struct property *prop;
+ const __be32 *cur;
+ int rc, index = 0;
+ struct clk *clk;
+ u32 rate;
+
+ of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
+ if (rate) {
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return rc;
+ }
+ if (clkspec.np == node && !clk_supplier)
+ return 0;
+
+ clk = of_clk_get_by_clkspec(&clkspec);
+ if (IS_ERR(clk)) {
+ pr_warn("clk: couldn't get clock %d for %s\n",
+ index, node->full_name);
+ return PTR_ERR(clk);
+ }
+
+ rc = clk_set_rate(clk, rate);
+ if (rc < 0)
+ pr_err("clk: couldn't set %s clock rate: %d\n",
+ __clk_get_name(clk), rc);
+ clk_put(clk);
+ }
+ index++;
+ }
+ return 0;
+}
+
+/**
+ * of_clk_set_defaults() - parse and set assigned clocks configuration
+ * @node: device node to apply clock settings for
+ * @clk_supplier: true if clocks supplied by @node should also be considered
+ *
+ * This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
+ * and sets any specified clock parents and rates. The @clk_supplier argument
+ * should be set to true if @node may be also a clock supplier of any clock
+ * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
+ * If @clk_supplier is false the function exits returnning 0 as soon as it
+ * determines the @node is also a supplier of any of the clocks.
+ */
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
+{
+ int rc;
+
+ if (!node)
+ return 0;
+
+ rc = __set_clk_parents(node, clk_supplier);
+ if (rc < 0)
+ return rc;
+
+ return __set_clk_rates(node, clk_supplier);
+}
+EXPORT_SYMBOL_GPL(of_clk_set_defaults);
diff --git a/drivers/clk/clk-palmas.c b/drivers/clk/clk-palmas.c
new file mode 100644
index 000000000000..781630e1372b
--- /dev/null
+++ b/drivers/clk/clk-palmas.c
@@ -0,0 +1,307 @@
+/*
+ * Clock driver for Palmas device.
+ *
+ * Copyright (c) 2013, NVIDIA Corporation.
+ * Copyright (c) 2013-2014 Texas Instruments, Inc.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ * 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 as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/palmas.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1 1
+#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2 2
+#define PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP 3
+
+struct palmas_clk32k_desc {
+ const char *clk_name;
+ unsigned int control_reg;
+ unsigned int enable_mask;
+ unsigned int sleep_mask;
+ unsigned int sleep_reqstr_id;
+ int delay;
+};
+
+struct palmas_clock_info {
+ struct device *dev;
+ struct clk *clk;
+ struct clk_hw hw;
+ struct palmas *palmas;
+ struct palmas_clk32k_desc *clk_desc;
+ int ext_control_pin;
+};
+
+static inline struct palmas_clock_info *to_palmas_clks_info(struct clk_hw *hw)
+{
+ return container_of(hw, struct palmas_clock_info, hw);
+}
+
+static unsigned long palmas_clks_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return 32768;
+}
+
+static int palmas_clks_prepare(struct clk_hw *hw)
+{
+ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+ int ret;
+
+ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+ cinfo->clk_desc->control_reg,
+ cinfo->clk_desc->enable_mask,
+ cinfo->clk_desc->enable_mask);
+ if (ret < 0)
+ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+ cinfo->clk_desc->control_reg, ret);
+ else if (cinfo->clk_desc->delay)
+ udelay(cinfo->clk_desc->delay);
+
+ return ret;
+}
+
+static void palmas_clks_unprepare(struct clk_hw *hw)
+{
+ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+ int ret;
+
+ /*
+ * Clock can be disabled through external pin if it is externally
+ * controlled.
+ */
+ if (cinfo->ext_control_pin)
+ return;
+
+ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+ cinfo->clk_desc->control_reg,
+ cinfo->clk_desc->enable_mask, 0);
+ if (ret < 0)
+ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+ cinfo->clk_desc->control_reg, ret);
+}
+
+static int palmas_clks_is_prepared(struct clk_hw *hw)
+{
+ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw);
+ int ret;
+ u32 val;
+
+ if (cinfo->ext_control_pin)
+ return 1;
+
+ ret = palmas_read(cinfo->palmas, PALMAS_RESOURCE_BASE,
+ cinfo->clk_desc->control_reg, &val);
+ if (ret < 0) {
+ dev_err(cinfo->dev, "Reg 0x%02x read failed, %d\n",
+ cinfo->clk_desc->control_reg, ret);
+ return ret;
+ }
+ return !!(val & cinfo->clk_desc->enable_mask);
+}
+
+static struct clk_ops palmas_clks_ops = {
+ .prepare = palmas_clks_prepare,
+ .unprepare = palmas_clks_unprepare,
+ .is_prepared = palmas_clks_is_prepared,
+ .recalc_rate = palmas_clks_recalc_rate,
+};
+
+struct palmas_clks_of_match_data {
+ struct clk_init_data init;
+ struct palmas_clk32k_desc desc;
+};
+
+static struct palmas_clks_of_match_data palmas_of_clk32kg = {
+ .init = {
+ .name = "clk32kg",
+ .ops = &palmas_clks_ops,
+ .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+ },
+ .desc = {
+ .clk_name = "clk32kg",
+ .control_reg = PALMAS_CLK32KG_CTRL,
+ .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+ .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+ .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KG,
+ .delay = 200,
+ },
+};
+
+static struct palmas_clks_of_match_data palmas_of_clk32kgaudio = {
+ .init = {
+ .name = "clk32kgaudio",
+ .ops = &palmas_clks_ops,
+ .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+ },
+ .desc = {
+ .clk_name = "clk32kgaudio",
+ .control_reg = PALMAS_CLK32KGAUDIO_CTRL,
+ .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE,
+ .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP,
+ .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO,
+ .delay = 200,
+ },
+};
+
+static struct of_device_id palmas_clks_of_match[] = {
+ {
+ .compatible = "ti,palmas-clk32kg",
+ .data = &palmas_of_clk32kg,
+ },
+ {
+ .compatible = "ti,palmas-clk32kgaudio",
+ .data = &palmas_of_clk32kgaudio,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, palmas_clks_of_match);
+
+static void palmas_clks_get_clk_data(struct platform_device *pdev,
+ struct palmas_clock_info *cinfo)
+{
+ struct device_node *node = pdev->dev.of_node;
+ unsigned int prop;
+ int ret;
+
+ ret = of_property_read_u32(node, "ti,external-sleep-control",
+ &prop);
+ if (ret)
+ return;
+
+ switch (prop) {
+ case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1:
+ prop = PALMAS_EXT_CONTROL_ENABLE1;
+ break;
+ case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2:
+ prop = PALMAS_EXT_CONTROL_ENABLE2;
+ break;
+ case PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP:
+ prop = PALMAS_EXT_CONTROL_NSLEEP;
+ break;
+ default:
+ dev_warn(&pdev->dev, "%s: Invalid ext control option: %u\n",
+ node->name, prop);
+ prop = 0;
+ break;
+ }
+ cinfo->ext_control_pin = prop;
+}
+
+static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
+{
+ int ret;
+
+ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE,
+ cinfo->clk_desc->control_reg,
+ cinfo->clk_desc->sleep_mask, 0);
+ if (ret < 0) {
+ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n",
+ cinfo->clk_desc->control_reg, ret);
+ return ret;
+ }
+
+ if (cinfo->ext_control_pin) {
+ ret = clk_prepare(cinfo->clk);
+ if (ret < 0) {
+ dev_err(cinfo->dev, "Clock prep failed, %d\n", ret);
+ return ret;
+ }
+
+ ret = palmas_ext_control_req_config(cinfo->palmas,
+ cinfo->clk_desc->sleep_reqstr_id,
+ cinfo->ext_control_pin, true);
+ if (ret < 0) {
+ dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
+ cinfo->clk_desc->clk_name, ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+static int palmas_clks_probe(struct platform_device *pdev)
+{
+ struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *node = pdev->dev.of_node;
+ struct palmas_clks_of_match_data *match_data;
+ const struct of_device_id *match;
+ struct palmas_clock_info *cinfo;
+ struct clk *clk;
+ int ret;
+
+ match = of_match_device(palmas_clks_of_match, &pdev->dev);
+ match_data = (struct palmas_clks_of_match_data *)match->data;
+
+ cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
+ if (!cinfo)
+ return -ENOMEM;
+
+ palmas_clks_get_clk_data(pdev, cinfo);
+ platform_set_drvdata(pdev, cinfo);
+
+ cinfo->dev = &pdev->dev;
+ cinfo->palmas = palmas;
+
+ cinfo->clk_desc = &match_data->desc;
+ cinfo->hw.init = &match_data->init;
+ clk = devm_clk_register(&pdev->dev, &cinfo->hw);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(&pdev->dev, "Fail to register clock %s, %d\n",
+ match_data->desc.clk_name, ret);
+ return ret;
+ }
+
+ cinfo->clk = clk;
+ ret = palmas_clks_init_configure(cinfo);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Clock config failed, %d\n", ret);
+ return ret;
+ }
+
+ ret = of_clk_add_provider(node, of_clk_src_simple_get, cinfo->clk);
+ if (ret < 0)
+ dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
+ return ret;
+}
+
+static int palmas_clks_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver palmas_clks_driver = {
+ .driver = {
+ .name = "palmas-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = palmas_clks_of_match,
+ },
+ .probe = palmas_clks_probe,
+ .remove = palmas_clks_remove,
+};
+
+module_platform_driver(palmas_clks_driver);
+
+MODULE_DESCRIPTION("Clock driver for Palmas Series Devices");
+MODULE_ALIAS("platform:palmas-clk");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c
index 8b284be4efa4..8e58edfeeb37 100644
--- a/drivers/clk/clk-ppc-corenet.c
+++ b/drivers/clk/clk-ppc-corenet.c
@@ -291,7 +291,7 @@ static const struct of_device_id ppc_clk_ids[] __initconst = {
{}
};
-static struct platform_driver ppc_corenet_clk_driver = {
+static struct platform_driver ppc_corenet_clk_driver __initdata = {
.driver = {
.name = "ppc_corenet_clock",
.owner = THIS_MODULE,
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
index 3757e9e72d37..b7797fb12e12 100644
--- a/drivers/clk/clk-s2mps11.c
+++ b/drivers/clk/clk-s2mps11.c
@@ -46,7 +46,6 @@ struct s2mps11_clk {
struct clk *clk;
struct clk_lookup *lookup;
u32 mask;
- bool enabled;
unsigned int reg;
};
@@ -63,8 +62,6 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
s2mps11->reg,
s2mps11->mask, s2mps11->mask);
- if (!ret)
- s2mps11->enabled = true;
return ret;
}
@@ -76,32 +73,32 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, s2mps11->reg,
s2mps11->mask, ~s2mps11->mask);
-
- if (!ret)
- s2mps11->enabled = false;
}
-static int s2mps11_clk_is_enabled(struct clk_hw *hw)
+static int s2mps11_clk_is_prepared(struct clk_hw *hw)
{
+ int ret;
+ u32 val;
struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
- return s2mps11->enabled;
+ ret = regmap_read(s2mps11->iodev->regmap_pmic,
+ s2mps11->reg, &val);
+ if (ret < 0)
+ return -EINVAL;
+
+ return val & s2mps11->mask;
}
static unsigned long s2mps11_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
- if (s2mps11->enabled)
- return 32768;
- else
- return 0;
+ return 32768;
}
static struct clk_ops s2mps11_clk_ops = {
.prepare = s2mps11_clk_prepare,
.unprepare = s2mps11_clk_unprepare,
- .is_enabled = s2mps11_clk_is_enabled,
+ .is_prepared = s2mps11_clk_is_prepared,
.recalc_rate = s2mps11_clk_recalc_rate,
};
@@ -169,7 +166,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
unsigned int s2mps11_reg;
struct clk_init_data *clks_init;
int i, ret = 0;
- u32 val;
s2mps11_clks = devm_kzalloc(&pdev->dev, sizeof(*s2mps11_clk) *
S2MPS11_CLKS_NUM, GFP_KERNEL);
@@ -214,13 +210,6 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
s2mps11_clk->mask = 1 << i;
s2mps11_clk->reg = s2mps11_reg;
- ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
- s2mps11_clk->reg, &val);
- if (ret < 0)
- goto err_reg;
-
- s2mps11_clk->enabled = val & s2mps11_clk->mask;
-
s2mps11_clk->clk = devm_clk_register(&pdev->dev,
&s2mps11_clk->hw);
if (IS_ERR(s2mps11_clk->clk)) {
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8b73edef151d..b76fa69b44cb 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -10,6 +10,7 @@
*/
#include <linux/clk-private.h>
+#include <linux/clk/clk-conf.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
@@ -98,9 +99,19 @@ static void clk_enable_unlock(unsigned long flags)
#include <linux/debugfs.h>
static struct dentry *rootdir;
-static struct dentry *orphandir;
static int inited = 0;
+static struct hlist_head *all_lists[] = {
+ &clk_root_list,
+ &clk_orphan_list,
+ NULL,
+};
+
+static struct hlist_head *orphan_list[] = {
+ &clk_orphan_list,
+ NULL,
+};
+
static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
{
if (!c)
@@ -130,17 +141,16 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
struct clk *c;
+ struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
seq_puts(s, "--------------------------------------------------------------------------------\n");
clk_prepare_lock();
- hlist_for_each_entry(c, &clk_root_list, child_node)
- clk_summary_show_subtree(s, c, 0);
-
- hlist_for_each_entry(c, &clk_orphan_list, child_node)
- clk_summary_show_subtree(s, c, 0);
+ for (; *lists; lists++)
+ hlist_for_each_entry(c, *lists, child_node)
+ clk_summary_show_subtree(s, c, 0);
clk_prepare_unlock();
@@ -193,21 +203,19 @@ static int clk_dump(struct seq_file *s, void *data)
{
struct clk *c;
bool first_node = true;
+ struct hlist_head **lists = (struct hlist_head **)s->private;
seq_printf(s, "{");
clk_prepare_lock();
- hlist_for_each_entry(c, &clk_root_list, child_node) {
- if (!first_node)
- seq_printf(s, ",");
- first_node = false;
- clk_dump_subtree(s, c, 0);
- }
-
- hlist_for_each_entry(c, &clk_orphan_list, child_node) {
- seq_printf(s, ",");
- clk_dump_subtree(s, c, 0);
+ for (; *lists; lists++) {
+ hlist_for_each_entry(c, *lists, child_node) {
+ if (!first_node)
+ seq_puts(s, ",");
+ first_node = false;
+ clk_dump_subtree(s, c, 0);
+ }
}
clk_prepare_unlock();
@@ -276,9 +284,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
if (!d)
goto err_out;
- if (clk->ops->debug_init)
- if (clk->ops->debug_init(clk->hw, clk->dentry))
+ if (clk->ops->debug_init) {
+ ret = clk->ops->debug_init(clk->hw, clk->dentry);
+ if (ret)
goto err_out;
+ }
ret = 0;
goto out;
@@ -305,7 +315,7 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
goto out;
hlist_for_each_entry(child, &clk->children, child_node)
- clk_debug_create_subtree(child, clk->dentry);
+ clk_debug_create_subtree(child, pdentry);
ret = 0;
out:
@@ -325,31 +335,12 @@ out:
*/
static int clk_debug_register(struct clk *clk)
{
- struct clk *parent;
- struct dentry *pdentry;
int ret = 0;
if (!inited)
goto out;
- parent = clk->parent;
-
- /*
- * Check to see if a clk is a root clk. Also check that it is
- * safe to add this clk to debugfs
- */
- if (!parent)
- if (clk->flags & CLK_IS_ROOT)
- pdentry = rootdir;
- else
- pdentry = orphandir;
- else
- if (parent->dentry)
- pdentry = parent->dentry;
- else
- goto out;
-
- ret = clk_debug_create_subtree(clk, pdentry);
+ ret = clk_debug_create_subtree(clk, rootdir);
out:
return ret;
@@ -370,38 +361,17 @@ static void clk_debug_unregister(struct clk *clk)
debugfs_remove_recursive(clk->dentry);
}
-/**
- * clk_debug_reparent - reparent clk node in the debugfs clk tree
- * @clk: the clk being reparented
- * @new_parent: the new clk parent, may be NULL
- *
- * Rename clk entry in the debugfs clk tree if debugfs has been
- * initialized. Otherwise it bails out early since the debugfs clk tree
- * will be created lazily by clk_debug_init as part of a late_initcall.
- *
- * Caller must hold prepare_lock.
- */
-static void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+ void *data, const struct file_operations *fops)
{
- struct dentry *d;
- struct dentry *new_parent_d;
-
- if (!inited)
- return;
+ struct dentry *d = NULL;
- if (new_parent)
- new_parent_d = new_parent->dentry;
- else
- new_parent_d = orphandir;
+ if (clk->dentry)
+ d = debugfs_create_file(name, mode, clk->dentry, data, fops);
- d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
- new_parent_d, clk->name);
- if (d)
- clk->dentry = d;
- else
- pr_debug("%s: failed to rename debugfs entry for %s\n",
- __func__, clk->name);
+ return d;
}
+EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
/**
* clk_debug_init - lazily create the debugfs clk tree visualization
@@ -425,19 +395,24 @@ static int __init clk_debug_init(void)
if (!rootdir)
return -ENOMEM;
- d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL,
+ d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
&clk_summary_fops);
if (!d)
return -ENOMEM;
- d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL,
+ d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
&clk_dump_fops);
if (!d)
return -ENOMEM;
- orphandir = debugfs_create_dir("orphans", rootdir);
+ d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
+ &orphan_list, &clk_summary_fops);
+ if (!d)
+ return -ENOMEM;
- if (!orphandir)
+ d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
+ &orphan_list, &clk_dump_fops);
+ if (!d)
return -ENOMEM;
clk_prepare_lock();
@@ -446,7 +421,7 @@ static int __init clk_debug_init(void)
clk_debug_create_subtree(clk, rootdir);
hlist_for_each_entry(clk, &clk_orphan_list, child_node)
- clk_debug_create_subtree(clk, orphandir);
+ clk_debug_create_subtree(clk, rootdir);
inited = 1;
@@ -1284,9 +1259,6 @@ static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
clk_disable(old_parent);
__clk_unprepare(old_parent);
}
-
- /* update debugfs with new clk tree topology */
- clk_debug_reparent(clk, parent);
}
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
@@ -1683,7 +1655,6 @@ out:
void __clk_reparent(struct clk *clk, struct clk *new_parent)
{
clk_reparent(clk, new_parent);
- clk_debug_reparent(clk, new_parent);
__clk_recalc_accuracies(clk);
__clk_recalc_rates(clk, POST_RATE_CHANGE);
}
@@ -2414,6 +2385,7 @@ int of_clk_add_provider(struct device_node *np,
void *data)
{
struct of_clk_provider *cp;
+ int ret;
cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
if (!cp)
@@ -2428,7 +2400,11 @@ int of_clk_add_provider(struct device_node *np,
mutex_unlock(&of_clk_mutex);
pr_debug("Added clock from %s\n", np->full_name);
- return 0;
+ ret = of_clk_set_defaults(np, true);
+ if (ret < 0)
+ of_clk_del_provider(np);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(of_clk_add_provider);
@@ -2605,7 +2581,10 @@ void __init of_clk_init(const struct of_device_id *matches)
list_for_each_entry_safe(clk_provider, next,
&clk_provider_list, node) {
if (force || parent_ready(clk_provider->np)) {
+
clk_provider->clk_init_cb(clk_provider->np);
+ of_clk_set_defaults(clk_provider->np, true);
+
list_del(&clk_provider->node);
kfree(clk_provider);
is_init_done = true;
@@ -2620,7 +2599,6 @@ void __init of_clk_init(const struct of_device_id *matches)
*/
if (!is_init_done)
force = true;
-
}
}
#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index f890b901c6bc..da4bda8b7fc7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -101,8 +101,9 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
if (!IS_ERR(clk))
break;
else if (name && index >= 0) {
- pr_err("ERROR: could not get clock %s:%s(%i)\n",
- np->full_name, name ? name : "", index);
+ if (PTR_ERR(clk) != -EPROBE_DEFER)
+ pr_err("ERROR: could not get clock %s:%s(%i)\n",
+ np->full_name, name ? name : "", index);
return clk;
}
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 8ebf757d29e2..3821a88077ea 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -16,10 +16,19 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/delay.h>
+#include <linux/mvebu-pmsu.h>
+#include <asm/smp_plat.h>
-#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
-#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
-#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
+#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
+#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL 0xff
+#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT 8
+#define SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET 0x8
+#define SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT 16
+#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
+#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
+
+#define PMU_DFS_RATIO_SHIFT 16
+#define PMU_DFS_RATIO_MASK 0x3F
#define MAX_CPU 4
struct cpu_clk {
@@ -28,6 +37,7 @@ struct cpu_clk {
const char *clk_name;
const char *parent_name;
void __iomem *reg_base;
+ void __iomem *pmu_dfs;
};
static struct clk **clks;
@@ -62,8 +72,9 @@ static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
return *parent_rate / div;
}
-static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
- unsigned long parent_rate)
+static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
+ unsigned long parent_rate)
+
{
struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
u32 reg, div;
@@ -95,6 +106,58 @@ static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
return 0;
}
+static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ unsigned long fabric_div, target_div, cur_rate;
+ struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
+
+ /*
+ * PMU DFS registers are not mapped, Device Tree does not
+ * describes them. We cannot change the frequency dynamically.
+ */
+ if (!cpuclk->pmu_dfs)
+ return -ENODEV;
+
+ cur_rate = __clk_get_rate(hwclk->clk);
+
+ reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
+ fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
+ SYS_CTRL_CLK_DIVIDER_MASK;
+
+ /* Frequency is going up */
+ if (rate == 2 * cur_rate)
+ target_div = fabric_div / 2;
+ /* Frequency is going down */
+ else
+ target_div = fabric_div;
+
+ if (target_div == 0)
+ target_div = 1;
+
+ reg = readl(cpuclk->pmu_dfs);
+ reg &= ~(PMU_DFS_RATIO_MASK << PMU_DFS_RATIO_SHIFT);
+ reg |= (target_div << PMU_DFS_RATIO_SHIFT);
+ writel(reg, cpuclk->pmu_dfs);
+
+ reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+ reg |= (SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL <<
+ SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT);
+ writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
+
+ return mvebu_pmsu_dfs_request(cpuclk->cpu);
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ if (__clk_is_enabled(hwclk->clk))
+ return clk_cpu_on_set_rate(hwclk, rate, parent_rate);
+ else
+ return clk_cpu_off_set_rate(hwclk, rate, parent_rate);
+}
+
static const struct clk_ops cpu_ops = {
.recalc_rate = clk_cpu_recalc_rate,
.round_rate = clk_cpu_round_rate,
@@ -105,6 +168,7 @@ static void __init of_cpu_clk_setup(struct device_node *node)
{
struct cpu_clk *cpuclk;
void __iomem *clock_complex_base = of_iomap(node, 0);
+ void __iomem *pmu_dfs_base = of_iomap(node, 1);
int ncpus = 0;
struct device_node *dn;
@@ -114,6 +178,10 @@ static void __init of_cpu_clk_setup(struct device_node *node)
return;
}
+ if (pmu_dfs_base == NULL)
+ pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n",
+ __func__);
+
for_each_node_by_type(dn, "cpu")
ncpus++;
@@ -146,6 +214,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
cpuclk[cpu].clk_name = clk_name;
cpuclk[cpu].cpu = cpu;
cpuclk[cpu].reg_base = clock_complex_base;
+ if (pmu_dfs_base)
+ cpuclk[cpu].pmu_dfs = pmu_dfs_base + 4 * cpu;
cpuclk[cpu].hw.init = &init;
init.name = cpuclk[cpu].clk_name;
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7f696b7d4422..1107351ed346 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -4,6 +4,31 @@ config COMMON_CLK_QCOM
select REGMAP_MMIO
select RESET_CONTROLLER
+config APQ_GCC_8084
+ tristate "APQ8084 Global Clock Controller"
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on apq8084 devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2c, USB, SD/eMMC, SATA, PCIe, etc.
+
+config APQ_MMCC_8084
+ tristate "APQ8084 Multimedia Clock Controller"
+ select APQ_GCC_8084
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the multimedia clock controller on apq8084 devices.
+ Say Y if you want to support multimedia devices such as display,
+ graphics, video encode/decode, camera, etc.
+
+config IPQ_GCC_806X
+ tristate "IPQ806x Global Clock Controller"
+ depends on COMMON_CLK_QCOM
+ help
+ Support for the global clock controller on ipq806x devices.
+ Say Y if you want to use peripheral devices such as UART, SPI,
+ i2c, USB, SD/eMMC, etc.
+
config MSM_GCC_8660
tristate "MSM8660 Global Clock Controller"
depends on COMMON_CLK_QCOM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 689e05bf4f95..783cfb24faa4 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -8,6 +8,9 @@ clk-qcom-y += clk-rcg2.o
clk-qcom-y += clk-branch.o
clk-qcom-y += reset.o
+obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
+obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
+obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 0f927c538613..9db03d3b1657 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -166,7 +166,7 @@ const struct clk_ops clk_pll_vote_ops = {
EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
static void
-clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap)
+clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
{
u32 val;
u32 mask;
@@ -175,7 +175,7 @@ clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap)
regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
/* Program bias count and lock count */
- val = 1 << PLL_BIAS_COUNT_SHIFT;
+ val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT;
mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
regmap_update_bits(regmap, pll->mode_reg, mask, val);
@@ -212,11 +212,20 @@ static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
regmap_update_bits(regmap, pll->config_reg, mask, val);
}
+void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
+ const struct pll_config *config, bool fsm_mode)
+{
+ clk_pll_configure(pll, regmap, config);
+ if (fsm_mode)
+ clk_pll_set_fsm_mode(pll, regmap, 8);
+}
+EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
+
void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode)
{
clk_pll_configure(pll, regmap, config);
if (fsm_mode)
- clk_pll_set_fsm_mode(pll, regmap);
+ clk_pll_set_fsm_mode(pll, regmap, 0);
}
EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index 0775a99ca768..3003e9962472 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -60,6 +60,8 @@ struct pll_config {
u32 aux_output_mask;
};
+void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
+ const struct pll_config *config, bool fsm_mode);
void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
const struct pll_config *config, bool fsm_mode);
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index abfc2b675aea..b638c5846dbf 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
}
-static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *p_rate, struct clk **p)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
- const struct freq_tbl *f;
+ const struct freq_tbl *f = rcg->freq_tbl;
+
+ *p = clk_get_parent_by_index(hw->clk, f->src);
+ *p_rate = __clk_round_rate(*p, rate);
+
+ return *p_rate;
+}
+
+static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
+{
u32 ns, md, ctl;
struct mn *mn = &rcg->mn;
u32 mask = 0;
unsigned int reset_reg;
- f = find_freq(rcg->freq_tbl, rate);
- if (!f)
- return -EINVAL;
-
if (rcg->mn.reset_in_cc)
reset_reg = rcg->clkr.enable_reg;
else
@@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ const struct freq_tbl *f;
+
+ f = find_freq(rcg->freq_tbl, rate);
+ if (!f)
+ return -EINVAL;
+
+ return __clk_rcg_set_rate(rcg, f);
+}
+
+static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+
+ return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
+}
+
static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
{
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
@@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg_ops);
+const struct clk_ops clk_rcg_bypass_ops = {
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+ .get_parent = clk_rcg_get_parent,
+ .set_parent = clk_rcg_set_parent,
+ .recalc_rate = clk_rcg_recalc_rate,
+ .determine_rate = clk_rcg_bypass_determine_rate,
+ .set_rate = clk_rcg_bypass_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
+
const struct clk_ops clk_dyn_rcg_ops = {
.enable = clk_enable_regmap,
.is_enabled = clk_is_enabled_regmap,
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index b9ec11dfd1b4..ba0523cefd2e 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -95,6 +95,7 @@ struct clk_rcg {
};
extern const struct clk_ops clk_rcg_ops;
+extern const struct clk_ops clk_rcg_bypass_ops;
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 9b5a1cfc6b91..eeb3eea01f4c 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -27,30 +27,35 @@ struct qcom_cc {
struct clk *clks[];
};
-int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
+struct regmap *
+qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
void __iomem *base;
struct resource *res;
+ struct device *dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return ERR_CAST(base);
+
+ return devm_regmap_init_mmio(dev, base, desc->config);
+}
+EXPORT_SYMBOL_GPL(qcom_cc_map);
+
+int qcom_cc_really_probe(struct platform_device *pdev,
+ const struct qcom_cc_desc *desc, struct regmap *regmap)
+{
int i, ret;
struct device *dev = &pdev->dev;
struct clk *clk;
struct clk_onecell_data *data;
struct clk **clks;
- struct regmap *regmap;
struct qcom_reset_controller *reset;
struct qcom_cc *cc;
size_t num_clks = desc->num_clks;
struct clk_regmap **rclks = desc->clks;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- regmap = devm_regmap_init_mmio(dev, base, desc->config);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
-
cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
GFP_KERNEL);
if (!cc)
@@ -91,6 +96,18 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
return ret;
}
+EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
+
+int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return qcom_cc_really_probe(pdev, desc, regmap);
+}
EXPORT_SYMBOL_GPL(qcom_cc_probe);
void qcom_cc_remove(struct platform_device *pdev)
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 2c3cfc860348..2765e9d3da97 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -17,6 +17,7 @@ struct platform_device;
struct regmap_config;
struct clk_regmap;
struct qcom_reset_map;
+struct regmap;
struct qcom_cc_desc {
const struct regmap_config *config;
@@ -26,6 +27,11 @@ struct qcom_cc_desc {
size_t num_resets;
};
+extern struct regmap *qcom_cc_map(struct platform_device *pdev,
+ const struct qcom_cc_desc *desc);
+extern int qcom_cc_really_probe(struct platform_device *pdev,
+ const struct qcom_cc_desc *desc,
+ struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
diff --git a/drivers/clk/qcom/gcc-apq8084.c b/drivers/clk/qcom/gcc-apq8084.c
new file mode 100644
index 000000000000..ee52eb1c838a
--- /dev/null
+++ b/drivers/clk/qcom/gcc-apq8084.c
@@ -0,0 +1,3611 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-apq8084.h>
+#include <dt-bindings/reset/qcom,gcc-apq8084.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO 0
+#define P_GPLL0 1
+#define P_GPLL1 1
+#define P_GPLL4 2
+#define P_PCIE_0_1_PIPE_CLK 1
+#define P_SATA_ASIC0_CLK 1
+#define P_SATA_RX_CLK 1
+#define P_SLEEP_CLK 1
+
+static const u8 gcc_xo_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_GPLL0] = 1,
+};
+
+static const char *gcc_xo_gpll0[] = {
+ "xo",
+ "gpll0_vote",
+};
+
+static const u8 gcc_xo_gpll0_gpll4_map[] = {
+ [P_XO] = 0,
+ [P_GPLL0] = 1,
+ [P_GPLL4] = 5,
+};
+
+static const char *gcc_xo_gpll0_gpll4[] = {
+ "xo",
+ "gpll0_vote",
+ "gpll4_vote",
+};
+
+static const u8 gcc_xo_sata_asic0_map[] = {
+ [P_XO] = 0,
+ [P_SATA_ASIC0_CLK] = 2,
+};
+
+static const char *gcc_xo_sata_asic0[] = {
+ "xo",
+ "sata_asic0_clk",
+};
+
+static const u8 gcc_xo_sata_rx_map[] = {
+ [P_XO] = 0,
+ [P_SATA_RX_CLK] = 2,
+};
+
+static const char *gcc_xo_sata_rx[] = {
+ "xo",
+ "sata_rx_clk",
+};
+
+static const u8 gcc_xo_pcie_map[] = {
+ [P_XO] = 0,
+ [P_PCIE_0_1_PIPE_CLK] = 2,
+};
+
+static const char *gcc_xo_pcie[] = {
+ "xo",
+ "pcie_pipe",
+};
+
+static const u8 gcc_xo_pcie_sleep_map[] = {
+ [P_XO] = 0,
+ [P_SLEEP_CLK] = 6,
+};
+
+static const char *gcc_xo_pcie_sleep[] = {
+ "xo",
+ "sleep_clk_src",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll gpll0 = {
+ .l_reg = 0x0004,
+ .m_reg = 0x0008,
+ .n_reg = 0x000c,
+ .config_reg = 0x0014,
+ .mode_reg = 0x0000,
+ .status_reg = 0x001c,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll0",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap gpll0_vote = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll0_vote",
+ .parent_names = (const char *[]){ "gpll0" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static struct clk_rcg2 config_noc_clk_src = {
+ .cmd_rcgr = 0x0150,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "config_noc_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 periph_noc_clk_src = {
+ .cmd_rcgr = 0x0190,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "periph_noc_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 system_noc_clk_src = {
+ .cmd_rcgr = 0x0120,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "system_noc_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_pll gpll1 = {
+ .l_reg = 0x0044,
+ .m_reg = 0x0048,
+ .n_reg = 0x004c,
+ .config_reg = 0x0054,
+ .mode_reg = 0x0040,
+ .status_reg = 0x005c,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll1",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap gpll1_vote = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll1_vote",
+ .parent_names = (const char *[]){ "gpll1" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static struct clk_pll gpll4 = {
+ .l_reg = 0x1dc4,
+ .m_reg = 0x1dc8,
+ .n_reg = 0x1dcc,
+ .config_reg = 0x1dd4,
+ .mode_reg = 0x1dc0,
+ .status_reg = 0x1ddc,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll4",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap gpll4_vote = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_vote",
+ .parent_names = (const char *[]){ "gpll4" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_axi_clk[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(240000000, P_GPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+ .cmd_rcgr = 0x1d64,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_ufs_axi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ufs_axi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = {
+ F(125000000, P_GPLL0, 1, 5, 24),
+ { }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+ .cmd_rcgr = 0x03d4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb30_master_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_sec_master_clk[] = {
+ F(125000000, P_GPLL0, 1, 5, 24),
+ { }
+};
+
+static struct clk_rcg2 usb30_sec_master_clk_src = {
+ .cmd_rcgr = 0x1bd4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb30_sec_master_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_sec_master_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_usb30_sec_mock_utmi_clk = {
+ .halt_reg = 0x1bd0,
+ .clkr = {
+ .enable_reg = 0x1bd0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sec_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb30_sec_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sec_sleep_clk = {
+ .halt_reg = 0x1bcc,
+ .clkr = {
+ .enable_reg = 0x1bcc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sec_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0660,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk[] = {
+ F(960000, P_XO, 10, 1, 2),
+ F(4800000, P_XO, 4, 0, 0),
+ F(9600000, P_XO, 2, 0, 0),
+ F(15000000, P_GPLL0, 10, 1, 4),
+ F(19200000, P_XO, 1, 0, 0),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x064c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x06e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x06cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0760,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x074c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x07e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x07cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0860,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+ .cmd_rcgr = 0x084c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x08e0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+ .cmd_rcgr = 0x08cc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = {
+ F(3686400, P_GPLL0, 1, 96, 15625),
+ F(7372800, P_GPLL0, 1, 192, 15625),
+ F(14745600, P_GPLL0, 1, 384, 15625),
+ F(16000000, P_GPLL0, 5, 2, 15),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_GPLL0, 1, 4, 75),
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(46400000, P_GPLL0, 1, 29, 375),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(51200000, P_GPLL0, 1, 32, 375),
+ F(56000000, P_GPLL0, 1, 7, 75),
+ F(58982400, P_GPLL0, 1, 1536, 15625),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(63160000, P_GPLL0, 9.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x068c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x070c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+ .cmd_rcgr = 0x078c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+ .cmd_rcgr = 0x080c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+ .cmd_rcgr = 0x088c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+ .cmd_rcgr = 0x090c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp1_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x09a0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+ .cmd_rcgr = 0x098c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup1_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0a20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0a0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup2_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0aa0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0a8c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup3_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0b20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0b0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup4_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0ba0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0b8c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup5_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+ .cmd_rcgr = 0x0c20,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_i2c_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+ .cmd_rcgr = 0x0c0c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_qup6_spi_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+ .cmd_rcgr = 0x09cc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+ .cmd_rcgr = 0x0a4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+ .cmd_rcgr = 0x0acc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+ .cmd_rcgr = 0x0b4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+ .cmd_rcgr = 0x0bcc,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart5_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+ .cmd_rcgr = 0x0c4c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "blsp2_uart6_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ce1_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ce1_clk_src = {
+ .cmd_rcgr = 0x1050,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_ce1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ce1_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ce2_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ce2_clk_src = {
+ .cmd_rcgr = 0x1090,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_ce2_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ce2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ce3_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(171430000, P_GPLL0, 3.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 ce3_clk_src = {
+ .cmd_rcgr = 0x1d10,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_ce3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ce3_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x1904,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_gp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+ .cmd_rcgr = 0x1944,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_gp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+ .cmd_rcgr = 0x1984,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_gp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_1_aux_clk[] = {
+ F(1010000, P_XO, 1, 1, 19),
+ { }
+};
+
+static struct clk_rcg2 pcie_0_aux_clk_src = {
+ .cmd_rcgr = 0x1b2c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_pcie_sleep_map,
+ .freq_tbl = ftbl_gcc_pcie_0_1_aux_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_0_aux_clk_src",
+ .parent_names = gcc_xo_pcie_sleep,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 pcie_1_aux_clk_src = {
+ .cmd_rcgr = 0x1bac,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_xo_pcie_sleep_map,
+ .freq_tbl = ftbl_gcc_pcie_0_1_aux_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_1_aux_clk_src",
+ .parent_names = gcc_xo_pcie_sleep,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_1_pipe_clk[] = {
+ F(125000000, P_PCIE_0_1_PIPE_CLK, 1, 0, 0),
+ F(250000000, P_PCIE_0_1_PIPE_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pcie_0_pipe_clk_src = {
+ .cmd_rcgr = 0x1b18,
+ .hid_width = 5,
+ .parent_map = gcc_xo_pcie_map,
+ .freq_tbl = ftbl_gcc_pcie_0_1_pipe_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_0_pipe_clk_src",
+ .parent_names = gcc_xo_pcie,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 pcie_1_pipe_clk_src = {
+ .cmd_rcgr = 0x1b98,
+ .hid_width = 5,
+ .parent_map = gcc_xo_pcie_map,
+ .freq_tbl = ftbl_gcc_pcie_0_1_pipe_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pcie_1_pipe_clk_src",
+ .parent_names = gcc_xo_pcie,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+ .cmd_rcgr = 0x0cd0,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_pdm2_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sata_asic0_clk[] = {
+ F(75000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+ F(150000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+ F(300000000, P_SATA_ASIC0_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sata_asic0_clk_src = {
+ .cmd_rcgr = 0x1c94,
+ .hid_width = 5,
+ .parent_map = gcc_xo_sata_asic0_map,
+ .freq_tbl = ftbl_gcc_sata_asic0_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sata_asic0_clk_src",
+ .parent_names = gcc_xo_sata_asic0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sata_pmalive_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sata_pmalive_clk_src = {
+ .cmd_rcgr = 0x1c80,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_sata_pmalive_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sata_pmalive_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sata_rx_clk[] = {
+ F(75000000, P_SATA_RX_CLK, 1, 0, 0),
+ F(150000000, P_SATA_RX_CLK, 1, 0, 0),
+ F(300000000, P_SATA_RX_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sata_rx_clk_src = {
+ .cmd_rcgr = 0x1ca8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_sata_rx_map,
+ .freq_tbl = ftbl_gcc_sata_rx_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sata_rx_clk_src",
+ .parent_names = gcc_xo_sata_rx,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sata_rx_oob_clk[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sata_rx_oob_clk_src = {
+ .cmd_rcgr = 0x1c5c,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_sata_rx_oob_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sata_rx_oob_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
+ F(144000, P_XO, 16, 3, 25),
+ F(400000, P_XO, 12, 1, 4),
+ F(20000000, P_GPLL0, 15, 1, 2),
+ F(25000000, P_GPLL0, 12, 1, 2),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(192000000, P_GPLL4, 4, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(384000000, P_GPLL4, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+ .cmd_rcgr = 0x04d0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_gpll4_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = gcc_xo_gpll0_gpll4,
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x0510,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+ .cmd_rcgr = 0x0550,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc3_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+ .cmd_rcgr = 0x0590,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "sdcc4_apps_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_tsif_ref_clk[] = {
+ F(105000, P_XO, 2, 1, 91),
+ { }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+ .cmd_rcgr = 0x0d90,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_tsif_ref_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x03e8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_sec_mock_utmi_clk[] = {
+ F(125000000, P_GPLL0, 1, 5, 24),
+ { }
+};
+
+static struct clk_rcg2 usb30_sec_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1be8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb30_sec_mock_utmi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb30_sec_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+ .cmd_rcgr = 0x0490,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb_hs_system_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hs_system_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+ F(480000000, P_GPLL1, 1, 0, 0),
+ { }
+};
+
+static u8 usb_hsic_clk_src_map[] = {
+ [P_XO] = 0,
+ [P_GPLL1] = 4,
+};
+
+static struct clk_rcg2 usb_hsic_clk_src = {
+ .cmd_rcgr = 0x0440,
+ .hid_width = 5,
+ .parent_map = usb_hsic_clk_src_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll1_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_ahb_clk_src[] = {
+ F(60000000, P_GPLL1, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hsic_ahb_clk_src = {
+ .cmd_rcgr = 0x046c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = usb_hsic_clk_src_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_ahb_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll1_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
+ F(9600000, P_XO, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hsic_io_cal_clk_src = {
+ .cmd_rcgr = 0x0458,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_io_cal_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_mock_utmi_clk = {
+ .halt_reg = 0x1f14,
+ .clkr = {
+ .enable_reg = 0x1f14,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb_hsic_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_mock_utmi_clk[] = {
+ F(60000000, P_GPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hsic_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x1f00,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_mock_utmi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_mock_utmi_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hsic_system_clk_src = {
+ .cmd_rcgr = 0x041c,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_system_clk_src",
+ .parent_names = gcc_xo_gpll0,
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_bam_dma_ahb_clk = {
+ .halt_reg = 0x0d44,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_bam_dma_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+ .halt_reg = 0x05c4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+ .halt_reg = 0x0648,
+ .clkr = {
+ .enable_reg = 0x0648,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+ .halt_reg = 0x0644,
+ .clkr = {
+ .enable_reg = 0x0644,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+ .halt_reg = 0x06c8,
+ .clkr = {
+ .enable_reg = 0x06c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+ .halt_reg = 0x06c4,
+ .clkr = {
+ .enable_reg = 0x06c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+ .halt_reg = 0x0748,
+ .clkr = {
+ .enable_reg = 0x0748,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+ .halt_reg = 0x0744,
+ .clkr = {
+ .enable_reg = 0x0744,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+ .halt_reg = 0x07c8,
+ .clkr = {
+ .enable_reg = 0x07c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+ .halt_reg = 0x07c4,
+ .clkr = {
+ .enable_reg = 0x07c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+ .halt_reg = 0x0848,
+ .clkr = {
+ .enable_reg = 0x0848,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup5_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup5_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+ .halt_reg = 0x0844,
+ .clkr = {
+ .enable_reg = 0x0844,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup5_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup5_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+ .halt_reg = 0x08c8,
+ .clkr = {
+ .enable_reg = 0x08c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup6_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup6_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+ .halt_reg = 0x08c4,
+ .clkr = {
+ .enable_reg = 0x08c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_qup6_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_qup6_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+ .halt_reg = 0x0684,
+ .clkr = {
+ .enable_reg = 0x0684,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+ .halt_reg = 0x0704,
+ .clkr = {
+ .enable_reg = 0x0704,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+ .halt_reg = 0x0784,
+ .clkr = {
+ .enable_reg = 0x0784,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart3_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+ .halt_reg = 0x0804,
+ .clkr = {
+ .enable_reg = 0x0804,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart4_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+ .halt_reg = 0x0884,
+ .clkr = {
+ .enable_reg = 0x0884,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart5_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart5_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+ .halt_reg = 0x0904,
+ .clkr = {
+ .enable_reg = 0x0904,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp1_uart6_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp1_uart6_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+ .halt_reg = 0x0944,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+ .halt_reg = 0x0988,
+ .clkr = {
+ .enable_reg = 0x0988,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+ .halt_reg = 0x0984,
+ .clkr = {
+ .enable_reg = 0x0984,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup1_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup1_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+ .halt_reg = 0x0a08,
+ .clkr = {
+ .enable_reg = 0x0a08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+ .halt_reg = 0x0a04,
+ .clkr = {
+ .enable_reg = 0x0a04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup2_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup2_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+ .halt_reg = 0x0a88,
+ .clkr = {
+ .enable_reg = 0x0a88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+ .halt_reg = 0x0a84,
+ .clkr = {
+ .enable_reg = 0x0a84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup3_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup3_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+ .halt_reg = 0x0b08,
+ .clkr = {
+ .enable_reg = 0x0b08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+ .halt_reg = 0x0b04,
+ .clkr = {
+ .enable_reg = 0x0b04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup4_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup4_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+ .halt_reg = 0x0b88,
+ .clkr = {
+ .enable_reg = 0x0b88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup5_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup5_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+ .halt_reg = 0x0b84,
+ .clkr = {
+ .enable_reg = 0x0b84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup5_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup5_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+ .halt_reg = 0x0c08,
+ .clkr = {
+ .enable_reg = 0x0c08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup6_i2c_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup6_i2c_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+ .halt_reg = 0x0c04,
+ .clkr = {
+ .enable_reg = 0x0c04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_qup6_spi_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_qup6_spi_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+ .halt_reg = 0x09c4,
+ .clkr = {
+ .enable_reg = 0x09c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart1_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+ .halt_reg = 0x0a44,
+ .clkr = {
+ .enable_reg = 0x0a44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart2_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+ .halt_reg = 0x0ac4,
+ .clkr = {
+ .enable_reg = 0x0ac4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart3_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+ .halt_reg = 0x0b44,
+ .clkr = {
+ .enable_reg = 0x0b44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart4_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+ .halt_reg = 0x0bc4,
+ .clkr = {
+ .enable_reg = 0x0bc4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart5_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart5_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+ .halt_reg = 0x0c44,
+ .clkr = {
+ .enable_reg = 0x0c44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_blsp2_uart6_apps_clk",
+ .parent_names = (const char *[]){
+ "blsp2_uart6_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x0e04,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_ahb_clk = {
+ .halt_reg = 0x104c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_axi_clk = {
+ .halt_reg = 0x1048,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_axi_clk",
+ .parent_names = (const char *[]){
+ "system_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce1_clk = {
+ .halt_reg = 0x1050,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce1_clk",
+ .parent_names = (const char *[]){
+ "ce1_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce2_ahb_clk = {
+ .halt_reg = 0x108c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce2_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce2_axi_clk = {
+ .halt_reg = 0x1088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce2_axi_clk",
+ .parent_names = (const char *[]){
+ "system_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce2_clk = {
+ .halt_reg = 0x1090,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce2_clk",
+ .parent_names = (const char *[]){
+ "ce2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce3_ahb_clk = {
+ .halt_reg = 0x1d0c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1d0c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce3_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce3_axi_clk = {
+ .halt_reg = 0x1088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1d08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce3_axi_clk",
+ .parent_names = (const char *[]){
+ "system_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ce3_clk = {
+ .halt_reg = 0x1090,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1d04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ce3_clk",
+ .parent_names = (const char *[]){
+ "ce3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x1900,
+ .clkr = {
+ .enable_reg = 0x1900,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_names = (const char *[]){
+ "gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+ .halt_reg = 0x1940,
+ .clkr = {
+ .enable_reg = 0x1940,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_names = (const char *[]){
+ "gp2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+ .halt_reg = 0x1980,
+ .clkr = {
+ .enable_reg = 0x1980,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_names = (const char *[]){
+ "gp3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ocmem_noc_cfg_ahb_clk = {
+ .halt_reg = 0x0248,
+ .clkr = {
+ .enable_reg = 0x0248,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ocmem_noc_cfg_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0x1b10,
+ .clkr = {
+ .enable_reg = 0x1b10,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_names = (const char *[]){
+ "pcie_0_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+ .halt_reg = 0x1b0c,
+ .clkr = {
+ .enable_reg = 0x1b0c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_cfg_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+ .halt_reg = 0x1b08,
+ .clkr = {
+ .enable_reg = 0x1b08,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_mstr_axi_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+ .halt_reg = 0x1b14,
+ .clkr = {
+ .enable_reg = 0x1b14,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_names = (const char *[]){
+ "pcie_0_pipe_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+ .halt_reg = 0x1b04,
+ .clkr = {
+ .enable_reg = 0x1b04,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_slv_axi_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+ .halt_reg = 0x1b90,
+ .clkr = {
+ .enable_reg = 0x1b90,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_names = (const char *[]){
+ "pcie_1_aux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
+ .halt_reg = 0x1b8c,
+ .clkr = {
+ .enable_reg = 0x1b8c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .halt_reg = 0x1b88,
+ .clkr = {
+ .enable_reg = 0x1b88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_mstr_axi_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+ .halt_reg = 0x1b94,
+ .clkr = {
+ .enable_reg = 0x1b94,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_names = (const char *[]){
+ "pcie_1_pipe_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_slv_axi_clk = {
+ .halt_reg = 0x1b84,
+ .clkr = {
+ .enable_reg = 0x1b84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_slv_axi_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x0ccc,
+ .clkr = {
+ .enable_reg = 0x0ccc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_names = (const char *[]){
+ "pdm2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+ .halt_reg = 0x0cc4,
+ .clkr = {
+ .enable_reg = 0x0cc4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_periph_noc_usb_hsic_ahb_clk = {
+ .halt_reg = 0x01a4,
+ .clkr = {
+ .enable_reg = 0x01a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_periph_noc_usb_hsic_ahb_clk",
+ .parent_names = (const char *[]){
+ "usb_hsic_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+ .halt_reg = 0x0d04,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1484,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_prng_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_asic0_clk = {
+ .halt_reg = 0x1c54,
+ .clkr = {
+ .enable_reg = 0x1c54,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_asic0_clk",
+ .parent_names = (const char *[]){
+ "sata_asic0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_axi_clk = {
+ .halt_reg = 0x1c44,
+ .clkr = {
+ .enable_reg = 0x1c44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_axi_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_cfg_ahb_clk = {
+ .halt_reg = 0x1c48,
+ .clkr = {
+ .enable_reg = 0x1c48,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_cfg_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_pmalive_clk = {
+ .halt_reg = 0x1c50,
+ .clkr = {
+ .enable_reg = 0x1c50,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_pmalive_clk",
+ .parent_names = (const char *[]){
+ "sata_pmalive_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_rx_clk = {
+ .halt_reg = 0x1c58,
+ .clkr = {
+ .enable_reg = 0x1c58,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_rx_clk",
+ .parent_names = (const char *[]){
+ "sata_rx_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sata_rx_oob_clk = {
+ .halt_reg = 0x1c4c,
+ .clkr = {
+ .enable_reg = 0x1c4c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sata_rx_oob_clk",
+ .parent_names = (const char *[]){
+ "sata_rx_oob_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+ .halt_reg = 0x04c8,
+ .clkr = {
+ .enable_reg = 0x04c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+ .halt_reg = 0x04c4,
+ .clkr = {
+ .enable_reg = 0x04c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc1_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_cdccal_ff_clk = {
+ .halt_reg = 0x04e8,
+ .clkr = {
+ .enable_reg = 0x04e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_cdccal_ff_clk",
+ .parent_names = (const char *[]){
+ "xo"
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = {
+ .halt_reg = 0x04e4,
+ .clkr = {
+ .enable_reg = 0x04e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc1_cdccal_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src"
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x0508,
+ .clkr = {
+ .enable_reg = 0x0508,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x0504,
+ .clkr = {
+ .enable_reg = 0x0504,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc2_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc3_ahb_clk = {
+ .halt_reg = 0x0548,
+ .clkr = {
+ .enable_reg = 0x0548,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc3_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+ .halt_reg = 0x0544,
+ .clkr = {
+ .enable_reg = 0x0544,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc3_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc3_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc4_ahb_clk = {
+ .halt_reg = 0x0588,
+ .clkr = {
+ .enable_reg = 0x0588,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+ .halt_reg = 0x0584,
+ .clkr = {
+ .enable_reg = 0x0584,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_apps_clk",
+ .parent_names = (const char *[]){
+ "sdcc4_apps_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+ .halt_reg = 0x013c,
+ .clkr = {
+ .enable_reg = 0x013c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+ .halt_reg = 0x0108,
+ .clkr = {
+ .enable_reg = 0x0108,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_usb3_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sys_noc_usb3_sec_axi_clk = {
+ .halt_reg = 0x0138,
+ .clkr = {
+ .enable_reg = 0x0138,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sys_noc_usb3_sec_axi_clk",
+ .parent_names = (const char *[]){
+ "usb30_sec_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_tsif_ahb_clk = {
+ .halt_reg = 0x0d84,
+ .clkr = {
+ .enable_reg = 0x0d84,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_tsif_inactivity_timers_clk = {
+ .halt_reg = 0x0d8c,
+ .clkr = {
+ .enable_reg = 0x0d8c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_inactivity_timers_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+ .halt_reg = 0x0d88,
+ .clkr = {
+ .enable_reg = 0x0d88,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_tsif_ref_clk",
+ .parent_names = (const char *[]){
+ "tsif_ref_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_ahb_clk = {
+ .halt_reg = 0x1d48,
+ .clkr = {
+ .enable_reg = 0x1d48,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_ahb_clk",
+ .parent_names = (const char *[]){
+ "config_noc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+ .halt_reg = 0x1d44,
+ .clkr = {
+ .enable_reg = 0x1d44,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_axi_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_cfg_clk = {
+ .halt_reg = 0x1d50,
+ .clkr = {
+ .enable_reg = 0x1d50,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_cfg_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
+ .halt_reg = 0x1d5c,
+ .clkr = {
+ .enable_reg = 0x1d5c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_0_clk",
+ .parent_names = (const char *[]){
+ "ufs_rx_symbol_0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
+ .halt_reg = 0x1d60,
+ .clkr = {
+ .enable_reg = 0x1d60,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_rx_symbol_1_clk",
+ .parent_names = (const char *[]){
+ "ufs_rx_symbol_1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_cfg_clk = {
+ .halt_reg = 0x1d4c,
+ .clkr = {
+ .enable_reg = 0x1d4c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_cfg_clk",
+ .parent_names = (const char *[]){
+ "ufs_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
+ .halt_reg = 0x1d54,
+ .clkr = {
+ .enable_reg = 0x1d54,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_0_clk",
+ .parent_names = (const char *[]){
+ "ufs_tx_symbol_0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_tx_symbol_1_clk = {
+ .halt_reg = 0x1d58,
+ .clkr = {
+ .enable_reg = 0x1d58,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_tx_symbol_1_clk",
+ .parent_names = (const char *[]){
+ "ufs_tx_symbol_1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb2a_phy_sleep_clk = {
+ .halt_reg = 0x04ac,
+ .clkr = {
+ .enable_reg = 0x04ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb2a_phy_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb2b_phy_sleep_clk = {
+ .halt_reg = 0x04b4,
+ .clkr = {
+ .enable_reg = 0x04b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb2b_phy_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+ .halt_reg = 0x03c8,
+ .clkr = {
+ .enable_reg = 0x03c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_master_clk",
+ .parent_names = (const char *[]){
+ "usb30_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sec_master_clk = {
+ .halt_reg = 0x1bc8,
+ .clkr = {
+ .enable_reg = 0x1bc8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sec_master_clk",
+ .parent_names = (const char *[]){
+ "usb30_sec_master_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+ .halt_reg = 0x03d0,
+ .clkr = {
+ .enable_reg = 0x03d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_mock_utmi_clk",
+ .parent_names = (const char *[]){
+ "usb30_mock_utmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+ .halt_reg = 0x03cc,
+ .clkr = {
+ .enable_reg = 0x03cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hs_ahb_clk = {
+ .halt_reg = 0x0488,
+ .clkr = {
+ .enable_reg = 0x0488,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hs_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hs_inactivity_timers_clk = {
+ .halt_reg = 0x048c,
+ .clkr = {
+ .enable_reg = 0x048c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hs_inactivity_timers_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+ .halt_reg = 0x0484,
+ .clkr = {
+ .enable_reg = 0x0484,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hs_system_clk",
+ .parent_names = (const char *[]){
+ "usb_hs_system_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_ahb_clk = {
+ .halt_reg = 0x0408,
+ .clkr = {
+ .enable_reg = 0x0408,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_ahb_clk",
+ .parent_names = (const char *[]){
+ "periph_noc_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_clk = {
+ .halt_reg = 0x0410,
+ .clkr = {
+ .enable_reg = 0x0410,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_clk",
+ .parent_names = (const char *[]){
+ "usb_hsic_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_clk = {
+ .halt_reg = 0x0414,
+ .clkr = {
+ .enable_reg = 0x0414,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_io_cal_clk",
+ .parent_names = (const char *[]){
+ "usb_hsic_io_cal_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_sleep_clk = {
+ .halt_reg = 0x0418,
+ .clkr = {
+ .enable_reg = 0x0418,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_io_cal_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb_hsic_system_clk = {
+ .halt_reg = 0x040c,
+ .clkr = {
+ .enable_reg = 0x040c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb_hsic_system_clk",
+ .parent_names = (const char *[]){
+ "usb_hsic_system_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *gcc_apq8084_clocks[] = {
+ [GPLL0] = &gpll0.clkr,
+ [GPLL0_VOTE] = &gpll0_vote,
+ [GPLL1] = &gpll1.clkr,
+ [GPLL1_VOTE] = &gpll1_vote,
+ [GPLL4] = &gpll4.clkr,
+ [GPLL4_VOTE] = &gpll4_vote,
+ [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr,
+ [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr,
+ [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr,
+ [UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+ [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_SEC_MASTER_CLK_SRC] = &usb30_sec_master_clk_src.clkr,
+ [USB_HSIC_AHB_CLK_SRC] = &usb_hsic_ahb_clk_src.clkr,
+ [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+ [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+ [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+ [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+ [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+ [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+ [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+ [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+ [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+ [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+ [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+ [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+ [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+ [BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+ [BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+ [BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+ [BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+ [BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr,
+ [BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr,
+ [BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr,
+ [BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+ [BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+ [BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr,
+ [BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr,
+ [BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr,
+ [BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr,
+ [CE1_CLK_SRC] = &ce1_clk_src.clkr,
+ [CE2_CLK_SRC] = &ce2_clk_src.clkr,
+ [CE3_CLK_SRC] = &ce3_clk_src.clkr,
+ [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+ [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+ [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+ [PCIE_0_AUX_CLK_SRC] = &pcie_0_aux_clk_src.clkr,
+ [PCIE_0_PIPE_CLK_SRC] = &pcie_0_pipe_clk_src.clkr,
+ [PCIE_1_AUX_CLK_SRC] = &pcie_1_aux_clk_src.clkr,
+ [PCIE_1_PIPE_CLK_SRC] = &pcie_1_pipe_clk_src.clkr,
+ [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+ [SATA_ASIC0_CLK_SRC] = &sata_asic0_clk_src.clkr,
+ [SATA_PMALIVE_CLK_SRC] = &sata_pmalive_clk_src.clkr,
+ [SATA_RX_CLK_SRC] = &sata_rx_clk_src.clkr,
+ [SATA_RX_OOB_CLK_SRC] = &sata_rx_oob_clk_src.clkr,
+ [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+ [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+ [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr,
+ [SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
+ [TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
+ [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+ [USB30_SEC_MOCK_UTMI_CLK_SRC] = &usb30_sec_mock_utmi_clk_src.clkr,
+ [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+ [USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr,
+ [USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr,
+ [USB_HSIC_MOCK_UTMI_CLK_SRC] = &usb_hsic_mock_utmi_clk_src.clkr,
+ [USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr,
+ [GCC_BAM_DMA_AHB_CLK] = &gcc_bam_dma_ahb_clk.clkr,
+ [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+ [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+ [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+ [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+ [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+ [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+ [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+ [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+ [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+ [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+ [GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+ [GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr,
+ [GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr,
+ [GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr,
+ [GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+ [GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+ [GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr,
+ [GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr,
+ [GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr,
+ [GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr,
+ [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr,
+ [GCC_CE1_CLK] = &gcc_ce1_clk.clkr,
+ [GCC_CE2_AHB_CLK] = &gcc_ce2_ahb_clk.clkr,
+ [GCC_CE2_AXI_CLK] = &gcc_ce2_axi_clk.clkr,
+ [GCC_CE2_CLK] = &gcc_ce2_clk.clkr,
+ [GCC_CE3_AHB_CLK] = &gcc_ce3_ahb_clk.clkr,
+ [GCC_CE3_AXI_CLK] = &gcc_ce3_axi_clk.clkr,
+ [GCC_CE3_CLK] = &gcc_ce3_clk.clkr,
+ [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+ [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+ [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+ [GCC_OCMEM_NOC_CFG_AHB_CLK] = &gcc_ocmem_noc_cfg_ahb_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+ [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
+ [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
+ [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+ [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
+ [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+ [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
+ [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
+ [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+ [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
+ [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+ [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+ [GCC_PERIPH_NOC_USB_HSIC_AHB_CLK] = &gcc_periph_noc_usb_hsic_ahb_clk.clkr,
+ [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+ [GCC_SATA_ASIC0_CLK] = &gcc_sata_asic0_clk.clkr,
+ [GCC_SATA_AXI_CLK] = &gcc_sata_axi_clk.clkr,
+ [GCC_SATA_CFG_AHB_CLK] = &gcc_sata_cfg_ahb_clk.clkr,
+ [GCC_SATA_PMALIVE_CLK] = &gcc_sata_pmalive_clk.clkr,
+ [GCC_SATA_RX_CLK] = &gcc_sata_rx_clk.clkr,
+ [GCC_SATA_RX_OOB_CLK] = &gcc_sata_rx_oob_clk.clkr,
+ [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+ [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+ [GCC_SDCC1_CDCCAL_FF_CLK] = &gcc_sdcc1_cdccal_ff_clk.clkr,
+ [GCC_SDCC1_CDCCAL_SLEEP_CLK] = &gcc_sdcc1_cdccal_sleep_clk.clkr,
+ [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+ [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+ [GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr,
+ [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+ [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr,
+ [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+ [GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
+ [GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
+ [GCC_SYS_NOC_USB3_SEC_AXI_CLK] = &gcc_sys_noc_usb3_sec_axi_clk.clkr,
+ [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr,
+ [GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr,
+ [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+ [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
+ [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+ [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
+ [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
+ [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+ [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
+ [GCC_UFS_TX_SYMBOL_1_CLK] = &gcc_ufs_tx_symbol_1_clk.clkr,
+ [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr,
+ [GCC_USB2B_PHY_SLEEP_CLK] = &gcc_usb2b_phy_sleep_clk.clkr,
+ [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+ [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+ [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
+ [GCC_USB30_SEC_MASTER_CLK] = &gcc_usb30_sec_master_clk.clkr,
+ [GCC_USB30_SEC_MOCK_UTMI_CLK] = &gcc_usb30_sec_mock_utmi_clk.clkr,
+ [GCC_USB30_SEC_SLEEP_CLK] = &gcc_usb30_sec_sleep_clk.clkr,
+ [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr,
+ [GCC_USB_HS_INACTIVITY_TIMERS_CLK] = &gcc_usb_hs_inactivity_timers_clk.clkr,
+ [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+ [GCC_USB_HSIC_AHB_CLK] = &gcc_usb_hsic_ahb_clk.clkr,
+ [GCC_USB_HSIC_CLK] = &gcc_usb_hsic_clk.clkr,
+ [GCC_USB_HSIC_IO_CAL_CLK] = &gcc_usb_hsic_io_cal_clk.clkr,
+ [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr,
+ [GCC_USB_HSIC_MOCK_UTMI_CLK] = &gcc_usb_hsic_mock_utmi_clk.clkr,
+ [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_apq8084_resets[] = {
+ [GCC_SYSTEM_NOC_BCR] = { 0x0100 },
+ [GCC_CONFIG_NOC_BCR] = { 0x0140 },
+ [GCC_PERIPH_NOC_BCR] = { 0x0180 },
+ [GCC_IMEM_BCR] = { 0x0200 },
+ [GCC_MMSS_BCR] = { 0x0240 },
+ [GCC_QDSS_BCR] = { 0x0300 },
+ [GCC_USB_30_BCR] = { 0x03c0 },
+ [GCC_USB3_PHY_BCR] = { 0x03fc },
+ [GCC_USB_HS_HSIC_BCR] = { 0x0400 },
+ [GCC_USB_HS_BCR] = { 0x0480 },
+ [GCC_USB2A_PHY_BCR] = { 0x04a8 },
+ [GCC_USB2B_PHY_BCR] = { 0x04b0 },
+ [GCC_SDCC1_BCR] = { 0x04c0 },
+ [GCC_SDCC2_BCR] = { 0x0500 },
+ [GCC_SDCC3_BCR] = { 0x0540 },
+ [GCC_SDCC4_BCR] = { 0x0580 },
+ [GCC_BLSP1_BCR] = { 0x05c0 },
+ [GCC_BLSP1_QUP1_BCR] = { 0x0640 },
+ [GCC_BLSP1_UART1_BCR] = { 0x0680 },
+ [GCC_BLSP1_QUP2_BCR] = { 0x06c0 },
+ [GCC_BLSP1_UART2_BCR] = { 0x0700 },
+ [GCC_BLSP1_QUP3_BCR] = { 0x0740 },
+ [GCC_BLSP1_UART3_BCR] = { 0x0780 },
+ [GCC_BLSP1_QUP4_BCR] = { 0x07c0 },
+ [GCC_BLSP1_UART4_BCR] = { 0x0800 },
+ [GCC_BLSP1_QUP5_BCR] = { 0x0840 },
+ [GCC_BLSP1_UART5_BCR] = { 0x0880 },
+ [GCC_BLSP1_QUP6_BCR] = { 0x08c0 },
+ [GCC_BLSP1_UART6_BCR] = { 0x0900 },
+ [GCC_BLSP2_BCR] = { 0x0940 },
+ [GCC_BLSP2_QUP1_BCR] = { 0x0980 },
+ [GCC_BLSP2_UART1_BCR] = { 0x09c0 },
+ [GCC_BLSP2_QUP2_BCR] = { 0x0a00 },
+ [GCC_BLSP2_UART2_BCR] = { 0x0a40 },
+ [GCC_BLSP2_QUP3_BCR] = { 0x0a80 },
+ [GCC_BLSP2_UART3_BCR] = { 0x0ac0 },
+ [GCC_BLSP2_QUP4_BCR] = { 0x0b00 },
+ [GCC_BLSP2_UART4_BCR] = { 0x0b40 },
+ [GCC_BLSP2_QUP5_BCR] = { 0x0b80 },
+ [GCC_BLSP2_UART5_BCR] = { 0x0bc0 },
+ [GCC_BLSP2_QUP6_BCR] = { 0x0c00 },
+ [GCC_BLSP2_UART6_BCR] = { 0x0c40 },
+ [GCC_PDM_BCR] = { 0x0cc0 },
+ [GCC_PRNG_BCR] = { 0x0d00 },
+ [GCC_BAM_DMA_BCR] = { 0x0d40 },
+ [GCC_TSIF_BCR] = { 0x0d80 },
+ [GCC_TCSR_BCR] = { 0x0dc0 },
+ [GCC_BOOT_ROM_BCR] = { 0x0e00 },
+ [GCC_MSG_RAM_BCR] = { 0x0e40 },
+ [GCC_TLMM_BCR] = { 0x0e80 },
+ [GCC_MPM_BCR] = { 0x0ec0 },
+ [GCC_MPM_AHB_RESET] = { 0x0ec4, 1 },
+ [GCC_MPM_NON_AHB_RESET] = { 0x0ec4, 2 },
+ [GCC_SEC_CTRL_BCR] = { 0x0f40 },
+ [GCC_SPMI_BCR] = { 0x0fc0 },
+ [GCC_SPDM_BCR] = { 0x1000 },
+ [GCC_CE1_BCR] = { 0x1040 },
+ [GCC_CE2_BCR] = { 0x1080 },
+ [GCC_BIMC_BCR] = { 0x1100 },
+ [GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x1240 },
+ [GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x1248 },
+ [GCC_PNOC_BUS_TIMEOUT0_BCR] = { 0x1280 },
+ [GCC_PNOC_BUS_TIMEOUT1_BCR] = { 0x1288 },
+ [GCC_PNOC_BUS_TIMEOUT2_BCR] = { 0x1290 },
+ [GCC_PNOC_BUS_TIMEOUT3_BCR] = { 0x1298 },
+ [GCC_PNOC_BUS_TIMEOUT4_BCR] = { 0x12a0 },
+ [GCC_CNOC_BUS_TIMEOUT0_BCR] = { 0x12c0 },
+ [GCC_CNOC_BUS_TIMEOUT1_BCR] = { 0x12c8 },
+ [GCC_CNOC_BUS_TIMEOUT2_BCR] = { 0x12d0 },
+ [GCC_CNOC_BUS_TIMEOUT3_BCR] = { 0x12d8 },
+ [GCC_CNOC_BUS_TIMEOUT4_BCR] = { 0x12e0 },
+ [GCC_CNOC_BUS_TIMEOUT5_BCR] = { 0x12e8 },
+ [GCC_CNOC_BUS_TIMEOUT6_BCR] = { 0x12f0 },
+ [GCC_DEHR_BCR] = { 0x1300 },
+ [GCC_RBCPR_BCR] = { 0x1380 },
+ [GCC_MSS_RESTART] = { 0x1680 },
+ [GCC_LPASS_RESTART] = { 0x16c0 },
+ [GCC_WCSS_RESTART] = { 0x1700 },
+ [GCC_VENUS_RESTART] = { 0x1740 },
+ [GCC_COPSS_SMMU_BCR] = { 0x1a40 },
+ [GCC_SPSS_BCR] = { 0x1a80 },
+ [GCC_PCIE_0_BCR] = { 0x1ac0 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x1b00 },
+ [GCC_PCIE_1_BCR] = { 0x1b40 },
+ [GCC_PCIE_1_PHY_BCR] = { 0x1b80 },
+ [GCC_USB_30_SEC_BCR] = { 0x1bc0 },
+ [GCC_USB3_SEC_PHY_BCR] = { 0x1bfc },
+ [GCC_SATA_BCR] = { 0x1c40 },
+ [GCC_CE3_BCR] = { 0x1d00 },
+ [GCC_UFS_BCR] = { 0x1d40 },
+ [GCC_USB30_PHY_COM_BCR] = { 0x1e80 },
+};
+
+static const struct regmap_config gcc_apq8084_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1fc0,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_apq8084_desc = {
+ .config = &gcc_apq8084_regmap_config,
+ .clks = gcc_apq8084_clocks,
+ .num_clks = ARRAY_SIZE(gcc_apq8084_clocks),
+ .resets = gcc_apq8084_resets,
+ .num_resets = ARRAY_SIZE(gcc_apq8084_resets),
+};
+
+static const struct of_device_id gcc_apq8084_match_table[] = {
+ { .compatible = "qcom,gcc-apq8084" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_apq8084_match_table);
+
+static int gcc_apq8084_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ struct device *dev = &pdev->dev;
+
+ /* Temporary until RPM clocks supported */
+ clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
+ CLK_IS_ROOT, 32768);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ return qcom_cc_probe(pdev, &gcc_apq8084_desc);
+}
+
+static int gcc_apq8084_remove(struct platform_device *pdev)
+{
+ qcom_cc_remove(pdev);
+ return 0;
+}
+
+static struct platform_driver gcc_apq8084_driver = {
+ .probe = gcc_apq8084_probe,
+ .remove = gcc_apq8084_remove,
+ .driver = {
+ .name = "gcc-apq8084",
+ .owner = THIS_MODULE,
+ .of_match_table = gcc_apq8084_match_table,
+ },
+};
+
+static int __init gcc_apq8084_init(void)
+{
+ return platform_driver_register(&gcc_apq8084_driver);
+}
+core_initcall(gcc_apq8084_init);
+
+static void __exit gcc_apq8084_exit(void)
+{
+ platform_driver_unregister(&gcc_apq8084_driver);
+}
+module_exit(gcc_apq8084_exit);
+
+MODULE_DESCRIPTION("QCOM GCC APQ8084 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-apq8084");
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
new file mode 100644
index 000000000000..4032e510d9aa
--- /dev/null
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -0,0 +1,2424 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
+#include <dt-bindings/reset/qcom,gcc-ipq806x.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+static struct clk_pll pll3 = {
+ .l_reg = 0x3164,
+ .m_reg = 0x3168,
+ .n_reg = 0x316c,
+ .config_reg = 0x3174,
+ .mode_reg = 0x3160,
+ .status_reg = 0x3178,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll3",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_pll pll8 = {
+ .l_reg = 0x3144,
+ .m_reg = 0x3148,
+ .n_reg = 0x314c,
+ .config_reg = 0x3154,
+ .mode_reg = 0x3140,
+ .status_reg = 0x3158,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll8",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap pll8_vote = {
+ .enable_reg = 0x34c0,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "pll8_vote",
+ .parent_names = (const char *[]){ "pll8" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static struct clk_pll pll14 = {
+ .l_reg = 0x31c4,
+ .m_reg = 0x31c8,
+ .n_reg = 0x31cc,
+ .config_reg = 0x31d4,
+ .mode_reg = 0x31c0,
+ .status_reg = 0x31d8,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll14",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap pll14_vote = {
+ .enable_reg = 0x34c0,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "pll14_vote",
+ .parent_names = (const char *[]){ "pll14" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+#define P_PXO 0
+#define P_PLL8 1
+#define P_PLL3 1
+#define P_PLL0 2
+#define P_CXO 2
+
+static const u8 gcc_pxo_pll8_map[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 3,
+};
+
+static const char *gcc_pxo_pll8[] = {
+ "pxo",
+ "pll8_vote",
+};
+
+static const u8 gcc_pxo_pll8_cxo_map[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 3,
+ [P_CXO] = 5,
+};
+
+static const char *gcc_pxo_pll8_cxo[] = {
+ "pxo",
+ "pll8_vote",
+ "cxo",
+};
+
+static const u8 gcc_pxo_pll3_map[] = {
+ [P_PXO] = 0,
+ [P_PLL3] = 1,
+};
+
+static const u8 gcc_pxo_pll3_sata_map[] = {
+ [P_PXO] = 0,
+ [P_PLL3] = 6,
+};
+
+static const char *gcc_pxo_pll3[] = {
+ "pxo",
+ "pll3",
+};
+
+static const u8 gcc_pxo_pll8_pll0[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 3,
+ [P_PLL0] = 2,
+};
+
+static const char *gcc_pxo_pll8_pll0_map[] = {
+ "pxo",
+ "pll8_vote",
+ "pll0",
+};
+
+static struct freq_tbl clk_tbl_gsbi_uart[] = {
+ { 1843200, P_PLL8, 2, 6, 625 },
+ { 3686400, P_PLL8, 2, 12, 625 },
+ { 7372800, P_PLL8, 2, 24, 625 },
+ { 14745600, P_PLL8, 2, 48, 625 },
+ { 16000000, P_PLL8, 4, 1, 6 },
+ { 24000000, P_PLL8, 4, 1, 4 },
+ { 32000000, P_PLL8, 4, 1, 3 },
+ { 40000000, P_PLL8, 1, 5, 48 },
+ { 46400000, P_PLL8, 1, 29, 240 },
+ { 48000000, P_PLL8, 4, 1, 2 },
+ { 51200000, P_PLL8, 1, 2, 15 },
+ { 56000000, P_PLL8, 1, 7, 48 },
+ { 58982400, P_PLL8, 1, 96, 625 },
+ { 64000000, P_PLL8, 2, 1, 3 },
+ { }
+};
+
+static struct clk_rcg gsbi1_uart_src = {
+ .ns_reg = 0x29d4,
+ .md_reg = 0x29d0,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x29d4,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi1_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi1_uart_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x29d4,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi1_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi1_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi2_uart_src = {
+ .ns_reg = 0x29f4,
+ .md_reg = 0x29f0,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x29f4,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi2_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi2_uart_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 8,
+ .clkr = {
+ .enable_reg = 0x29f4,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi2_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi2_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi4_uart_src = {
+ .ns_reg = 0x2a34,
+ .md_reg = 0x2a30,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x2a34,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi4_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi4_uart_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 26,
+ .clkr = {
+ .enable_reg = 0x2a34,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi4_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi4_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi5_uart_src = {
+ .ns_reg = 0x2a54,
+ .md_reg = 0x2a50,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x2a54,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi5_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_uart_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 22,
+ .clkr = {
+ .enable_reg = 0x2a54,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi5_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi5_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi6_uart_src = {
+ .ns_reg = 0x2a74,
+ .md_reg = 0x2a70,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x2a74,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi6_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi6_uart_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 18,
+ .clkr = {
+ .enable_reg = 0x2a74,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi6_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi6_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi7_uart_src = {
+ .ns_reg = 0x2a94,
+ .md_reg = 0x2a90,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_uart,
+ .clkr = {
+ .enable_reg = 0x2a94,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi7_uart_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi7_uart_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 14,
+ .clkr = {
+ .enable_reg = 0x2a94,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi7_uart_clk",
+ .parent_names = (const char *[]){
+ "gsbi7_uart_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct freq_tbl clk_tbl_gsbi_qup[] = {
+ { 1100000, P_PXO, 1, 2, 49 },
+ { 5400000, P_PXO, 1, 1, 5 },
+ { 10800000, P_PXO, 1, 2, 5 },
+ { 15060000, P_PLL8, 1, 2, 51 },
+ { 24000000, P_PLL8, 4, 1, 4 },
+ { 25600000, P_PLL8, 1, 1, 15 },
+ { 27000000, P_PXO, 1, 0, 0 },
+ { 48000000, P_PLL8, 4, 1, 2 },
+ { 51200000, P_PLL8, 1, 2, 15 },
+ { }
+};
+
+static struct clk_rcg gsbi1_qup_src = {
+ .ns_reg = 0x29cc,
+ .md_reg = 0x29c8,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x29cc,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi1_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi1_qup_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 11,
+ .clkr = {
+ .enable_reg = 0x29cc,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi1_qup_clk",
+ .parent_names = (const char *[]){ "gsbi1_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi2_qup_src = {
+ .ns_reg = 0x29ec,
+ .md_reg = 0x29e8,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x29ec,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi2_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi2_qup_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 6,
+ .clkr = {
+ .enable_reg = 0x29ec,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi2_qup_clk",
+ .parent_names = (const char *[]){ "gsbi2_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi4_qup_src = {
+ .ns_reg = 0x2a2c,
+ .md_reg = 0x2a28,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x2a2c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi4_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi4_qup_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 24,
+ .clkr = {
+ .enable_reg = 0x2a2c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi4_qup_clk",
+ .parent_names = (const char *[]){ "gsbi4_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi5_qup_src = {
+ .ns_reg = 0x2a4c,
+ .md_reg = 0x2a48,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x2a4c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi5_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_qup_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 20,
+ .clkr = {
+ .enable_reg = 0x2a4c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi5_qup_clk",
+ .parent_names = (const char *[]){ "gsbi5_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi6_qup_src = {
+ .ns_reg = 0x2a6c,
+ .md_reg = 0x2a68,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x2a6c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi6_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi6_qup_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 16,
+ .clkr = {
+ .enable_reg = 0x2a6c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi6_qup_clk",
+ .parent_names = (const char *[]){ "gsbi6_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gsbi7_qup_src = {
+ .ns_reg = 0x2a8c,
+ .md_reg = 0x2a88,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_gsbi_qup,
+ .clkr = {
+ .enable_reg = 0x2a8c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi7_qup_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ },
+};
+
+static struct clk_branch gsbi7_qup_clk = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x2a8c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi7_qup_clk",
+ .parent_names = (const char *[]){ "gsbi7_qup_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch gsbi1_h_clk = {
+ .hwcg_reg = 0x29c0,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fcc,
+ .halt_bit = 13,
+ .clkr = {
+ .enable_reg = 0x29c0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch gsbi2_h_clk = {
+ .hwcg_reg = 0x29e0,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fcc,
+ .halt_bit = 9,
+ .clkr = {
+ .enable_reg = 0x29e0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi2_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch gsbi4_h_clk = {
+ .hwcg_reg = 0x2a20,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd0,
+ .halt_bit = 27,
+ .clkr = {
+ .enable_reg = 0x2a20,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi4_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_h_clk = {
+ .hwcg_reg = 0x2a40,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd0,
+ .halt_bit = 23,
+ .clkr = {
+ .enable_reg = 0x2a40,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi5_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch gsbi6_h_clk = {
+ .hwcg_reg = 0x2a60,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd0,
+ .halt_bit = 19,
+ .clkr = {
+ .enable_reg = 0x2a60,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi6_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch gsbi7_h_clk = {
+ .hwcg_reg = 0x2a80,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd0,
+ .halt_bit = 15,
+ .clkr = {
+ .enable_reg = 0x2a80,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gsbi7_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_gp[] = {
+ { 12500000, P_PXO, 2, 0, 0 },
+ { 25000000, P_PXO, 1, 0, 0 },
+ { 64000000, P_PLL8, 2, 1, 3 },
+ { 76800000, P_PLL8, 1, 1, 5 },
+ { 96000000, P_PLL8, 4, 0, 0 },
+ { 128000000, P_PLL8, 3, 0, 0 },
+ { 192000000, P_PLL8, 2, 0, 0 },
+ { }
+};
+
+static struct clk_rcg gp0_src = {
+ .ns_reg = 0x2d24,
+ .md_reg = 0x2d00,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_cxo_map,
+ },
+ .freq_tbl = clk_tbl_gp,
+ .clkr = {
+ .enable_reg = 0x2d24,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_src",
+ .parent_names = gcc_pxo_pll8_cxo,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_PARENT_GATE,
+ },
+ }
+};
+
+static struct clk_branch gp0_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_bit = 7,
+ .clkr = {
+ .enable_reg = 0x2d24,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_clk",
+ .parent_names = (const char *[]){ "gp0_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gp1_src = {
+ .ns_reg = 0x2d44,
+ .md_reg = 0x2d40,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_cxo_map,
+ },
+ .freq_tbl = clk_tbl_gp,
+ .clkr = {
+ .enable_reg = 0x2d44,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp1_src",
+ .parent_names = gcc_pxo_pll8_cxo,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch gp1_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_bit = 6,
+ .clkr = {
+ .enable_reg = 0x2d44,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp1_clk",
+ .parent_names = (const char *[]){ "gp1_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg gp2_src = {
+ .ns_reg = 0x2d64,
+ .md_reg = 0x2d60,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_cxo_map,
+ },
+ .freq_tbl = clk_tbl_gp,
+ .clkr = {
+ .enable_reg = 0x2d64,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp2_src",
+ .parent_names = gcc_pxo_pll8_cxo,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch gp2_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_bit = 5,
+ .clkr = {
+ .enable_reg = 0x2d64,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gp2_clk",
+ .parent_names = (const char *[]){ "gp2_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch pmem_clk = {
+ .hwcg_reg = 0x25a0,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fc8,
+ .halt_bit = 20,
+ .clkr = {
+ .enable_reg = 0x25a0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pmem_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_rcg prng_src = {
+ .ns_reg = 0x2e80,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "prng_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch prng_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 10,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "prng_clk",
+ .parent_names = (const char *[]){ "prng_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_sdc[] = {
+ { 144000, P_PXO, 5, 18,625 },
+ { 400000, P_PLL8, 4, 1, 240 },
+ { 16000000, P_PLL8, 4, 1, 6 },
+ { 17070000, P_PLL8, 1, 2, 45 },
+ { 20210000, P_PLL8, 1, 1, 19 },
+ { 24000000, P_PLL8, 4, 1, 4 },
+ { 48000000, P_PLL8, 4, 1, 2 },
+ { 64000000, P_PLL8, 3, 1, 2 },
+ { 96000000, P_PLL8, 4, 0, 0 },
+ { 192000000, P_PLL8, 2, 0, 0 },
+ { }
+};
+
+static struct clk_rcg sdc1_src = {
+ .ns_reg = 0x282c,
+ .md_reg = 0x2828,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_sdc,
+ .clkr = {
+ .enable_reg = 0x282c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc1_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch sdc1_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 6,
+ .clkr = {
+ .enable_reg = 0x282c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc1_clk",
+ .parent_names = (const char *[]){ "sdc1_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg sdc3_src = {
+ .ns_reg = 0x286c,
+ .md_reg = 0x2868,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_sdc,
+ .clkr = {
+ .enable_reg = 0x286c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc3_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch sdc3_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 4,
+ .clkr = {
+ .enable_reg = 0x286c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc3_clk",
+ .parent_names = (const char *[]){ "sdc3_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sdc1_h_clk = {
+ .hwcg_reg = 0x2820,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fc8,
+ .halt_bit = 11,
+ .clkr = {
+ .enable_reg = 0x2820,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sdc3_h_clk = {
+ .hwcg_reg = 0x2860,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fc8,
+ .halt_bit = 9,
+ .clkr = {
+ .enable_reg = 0x2860,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sdc3_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_tsif_ref[] = {
+ { 105000, P_PXO, 1, 1, 256 },
+ { }
+};
+
+static struct clk_rcg tsif_ref_src = {
+ .ns_reg = 0x2710,
+ .md_reg = 0x270c,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 16,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_tsif_ref,
+ .clkr = {
+ .enable_reg = 0x2710,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch tsif_ref_clk = {
+ .halt_reg = 0x2fd4,
+ .halt_bit = 5,
+ .clkr = {
+ .enable_reg = 0x2710,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_clk",
+ .parent_names = (const char *[]){ "tsif_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch tsif_h_clk = {
+ .hwcg_reg = 0x2700,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd4,
+ .halt_bit = 7,
+ .clkr = {
+ .enable_reg = 0x2700,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "tsif_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch dma_bam_h_clk = {
+ .hwcg_reg = 0x25c0,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fc8,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x25c0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "dma_bam_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch adm0_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "adm0_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch adm0_pbus_clk = {
+ .hwcg_reg = 0x2208,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fdc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 11,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "adm0_pbus_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pmic_arb0_h_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 22,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "pmic_arb0_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pmic_arb1_h_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 21,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pmic_arb1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pmic_ssbi2_clk = {
+ .halt_reg = 0x2fd8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 23,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "pmic_ssbi2_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch rpm_msg_ram_h_clk = {
+ .hwcg_reg = 0x27e0,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fd8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x3080,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "rpm_msg_ram_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_pcie_ref[] = {
+ { 100000000, P_PLL3, 12, 0, 0 },
+ { }
+};
+
+static struct clk_rcg pcie_ref_src = {
+ .ns_reg = 0x3860,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll3_map,
+ },
+ .freq_tbl = clk_tbl_pcie_ref,
+ .clkr = {
+ .enable_reg = 0x3860,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_ref_src",
+ .parent_names = gcc_pxo_pll3,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch pcie_ref_src_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 30,
+ .clkr = {
+ .enable_reg = 0x3860,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_ref_src_clk",
+ .parent_names = (const char *[]){ "pcie_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch pcie_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 13,
+ .clkr = {
+ .enable_reg = 0x22c0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_aux_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 31,
+ .clkr = {
+ .enable_reg = 0x22c8,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_aux_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_h_clk = {
+ .halt_reg = 0x2fd4,
+ .halt_bit = 8,
+ .clkr = {
+ .enable_reg = 0x22cc,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_phy_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 29,
+ .clkr = {
+ .enable_reg = 0x22d0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_phy_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_rcg pcie1_ref_src = {
+ .ns_reg = 0x3aa0,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll3_map,
+ },
+ .freq_tbl = clk_tbl_pcie_ref,
+ .clkr = {
+ .enable_reg = 0x3aa0,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_ref_src",
+ .parent_names = gcc_pxo_pll3,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch pcie1_ref_src_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 27,
+ .clkr = {
+ .enable_reg = 0x3aa0,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_ref_src_clk",
+ .parent_names = (const char *[]){ "pcie1_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch pcie1_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 10,
+ .clkr = {
+ .enable_reg = 0x3a80,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie1_aux_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 28,
+ .clkr = {
+ .enable_reg = 0x3a88,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_aux_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie1_h_clk = {
+ .halt_reg = 0x2fd4,
+ .halt_bit = 9,
+ .clkr = {
+ .enable_reg = 0x3a8c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie1_phy_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 26,
+ .clkr = {
+ .enable_reg = 0x3a90,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie1_phy_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_rcg pcie2_ref_src = {
+ .ns_reg = 0x3ae0,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll3_map,
+ },
+ .freq_tbl = clk_tbl_pcie_ref,
+ .clkr = {
+ .enable_reg = 0x3ae0,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_ref_src",
+ .parent_names = gcc_pxo_pll3,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch pcie2_ref_src_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 24,
+ .clkr = {
+ .enable_reg = 0x3ae0,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_ref_src_clk",
+ .parent_names = (const char *[]){ "pcie2_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch pcie2_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 9,
+ .clkr = {
+ .enable_reg = 0x3ac0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie2_aux_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 25,
+ .clkr = {
+ .enable_reg = 0x3ac8,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_aux_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie2_h_clk = {
+ .halt_reg = 0x2fd4,
+ .halt_bit = 10,
+ .clkr = {
+ .enable_reg = 0x3acc,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie2_phy_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 23,
+ .clkr = {
+ .enable_reg = 0x3ad0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie2_phy_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_sata_ref[] = {
+ { 100000000, P_PLL3, 12, 0, 0 },
+ { }
+};
+
+static struct clk_rcg sata_ref_src = {
+ .ns_reg = 0x2c08,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll3_sata_map,
+ },
+ .freq_tbl = clk_tbl_sata_ref,
+ .clkr = {
+ .enable_reg = 0x2c08,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_ref_src",
+ .parent_names = gcc_pxo_pll3,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch sata_rxoob_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 20,
+ .clkr = {
+ .enable_reg = 0x2c0c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_rxoob_clk",
+ .parent_names = (const char *[]){ "sata_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sata_pmalive_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 19,
+ .clkr = {
+ .enable_reg = 0x2c10,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_pmalive_clk",
+ .parent_names = (const char *[]){ "sata_ref_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sata_phy_ref_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 18,
+ .clkr = {
+ .enable_reg = 0x2c14,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_phy_ref_clk",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+static struct clk_branch sata_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x2c20,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sata_h_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 21,
+ .clkr = {
+ .enable_reg = 0x2c00,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sfab_sata_s_h_clk = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 14,
+ .clkr = {
+ .enable_reg = 0x2480,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sfab_sata_s_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sata_phy_cfg_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 14,
+ .clkr = {
+ .enable_reg = 0x2c40,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_phy_cfg_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_usb30_master[] = {
+ { 125000000, P_PLL0, 1, 5, 32 },
+ { }
+};
+
+static struct clk_rcg usb30_master_clk_src = {
+ .ns_reg = 0x3b2c,
+ .md_reg = 0x3b28,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll0,
+ },
+ .freq_tbl = clk_tbl_usb30_master,
+ .clkr = {
+ .enable_reg = 0x3b2c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_master_ref_src",
+ .parent_names = gcc_pxo_pll8_pll0_map,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch usb30_0_branch_clk = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 22,
+ .clkr = {
+ .enable_reg = 0x3b24,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_0_branch_clk",
+ .parent_names = (const char *[]){ "usb30_master_ref_src", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch usb30_1_branch_clk = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 17,
+ .clkr = {
+ .enable_reg = 0x3b34,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_1_branch_clk",
+ .parent_names = (const char *[]){ "usb30_master_ref_src", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_usb30_utmi[] = {
+ { 60000000, P_PLL8, 1, 5, 32 },
+ { }
+};
+
+static struct clk_rcg usb30_utmi_clk = {
+ .ns_reg = 0x3b44,
+ .md_reg = 0x3b40,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll0,
+ },
+ .freq_tbl = clk_tbl_usb30_utmi,
+ .clkr = {
+ .enable_reg = 0x3b44,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_utmi_clk",
+ .parent_names = gcc_pxo_pll8_pll0_map,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch usb30_0_utmi_clk_ctl = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 21,
+ .clkr = {
+ .enable_reg = 0x3b48,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_0_utmi_clk_ctl",
+ .parent_names = (const char *[]){ "usb30_utmi_clk", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch usb30_1_utmi_clk_ctl = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 15,
+ .clkr = {
+ .enable_reg = 0x3b4c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_1_utmi_clk_ctl",
+ .parent_names = (const char *[]){ "usb30_utmi_clk", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_usb[] = {
+ { 60000000, P_PLL8, 1, 5, 32 },
+ { }
+};
+
+static struct clk_rcg usb_hs1_xcvr_clk_src = {
+ .ns_reg = 0x290C,
+ .md_reg = 0x2908,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll0,
+ },
+ .freq_tbl = clk_tbl_usb,
+ .clkr = {
+ .enable_reg = 0x2968,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs1_xcvr_src",
+ .parent_names = gcc_pxo_pll8_pll0_map,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch usb_hs1_xcvr_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 17,
+ .clkr = {
+ .enable_reg = 0x290c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs1_xcvr_clk",
+ .parent_names = (const char *[]){ "usb_hs1_xcvr_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch usb_hs1_h_clk = {
+ .hwcg_reg = 0x2900,
+ .hwcg_bit = 6,
+ .halt_reg = 0x2fc8,
+ .halt_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2900,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_rcg usb_fs1_xcvr_clk_src = {
+ .ns_reg = 0x2968,
+ .md_reg = 0x2964,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll0,
+ },
+ .freq_tbl = clk_tbl_usb,
+ .clkr = {
+ .enable_reg = 0x2968,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_fs1_xcvr_src",
+ .parent_names = gcc_pxo_pll8_pll0_map,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch usb_fs1_xcvr_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 17,
+ .clkr = {
+ .enable_reg = 0x2968,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_fs1_xcvr_clk",
+ .parent_names = (const char *[]){ "usb_fs1_xcvr_src", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch usb_fs1_sys_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 18,
+ .clkr = {
+ .enable_reg = 0x296c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_fs1_sys_clk",
+ .parent_names = (const char *[]){ "usb_fs1_xcvr_src", },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch usb_fs1_h_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 19,
+ .clkr = {
+ .enable_reg = 0x2960,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_fs1_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_regmap *gcc_ipq806x_clks[] = {
+ [PLL3] = &pll3.clkr,
+ [PLL8] = &pll8.clkr,
+ [PLL8_VOTE] = &pll8_vote,
+ [PLL14] = &pll14.clkr,
+ [PLL14_VOTE] = &pll14_vote,
+ [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+ [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+ [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+ [GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr,
+ [GSBI4_UART_SRC] = &gsbi4_uart_src.clkr,
+ [GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr,
+ [GSBI5_UART_SRC] = &gsbi5_uart_src.clkr,
+ [GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr,
+ [GSBI6_UART_SRC] = &gsbi6_uart_src.clkr,
+ [GSBI6_UART_CLK] = &gsbi6_uart_clk.clkr,
+ [GSBI7_UART_SRC] = &gsbi7_uart_src.clkr,
+ [GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr,
+ [GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr,
+ [GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr,
+ [GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr,
+ [GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr,
+ [GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr,
+ [GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr,
+ [GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr,
+ [GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr,
+ [GSBI6_QUP_SRC] = &gsbi6_qup_src.clkr,
+ [GSBI6_QUP_CLK] = &gsbi6_qup_clk.clkr,
+ [GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr,
+ [GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr,
+ [GP0_SRC] = &gp0_src.clkr,
+ [GP0_CLK] = &gp0_clk.clkr,
+ [GP1_SRC] = &gp1_src.clkr,
+ [GP1_CLK] = &gp1_clk.clkr,
+ [GP2_SRC] = &gp2_src.clkr,
+ [GP2_CLK] = &gp2_clk.clkr,
+ [PMEM_A_CLK] = &pmem_clk.clkr,
+ [PRNG_SRC] = &prng_src.clkr,
+ [PRNG_CLK] = &prng_clk.clkr,
+ [SDC1_SRC] = &sdc1_src.clkr,
+ [SDC1_CLK] = &sdc1_clk.clkr,
+ [SDC3_SRC] = &sdc3_src.clkr,
+ [SDC3_CLK] = &sdc3_clk.clkr,
+ [TSIF_REF_SRC] = &tsif_ref_src.clkr,
+ [TSIF_REF_CLK] = &tsif_ref_clk.clkr,
+ [DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr,
+ [GSBI1_H_CLK] = &gsbi1_h_clk.clkr,
+ [GSBI2_H_CLK] = &gsbi2_h_clk.clkr,
+ [GSBI4_H_CLK] = &gsbi4_h_clk.clkr,
+ [GSBI5_H_CLK] = &gsbi5_h_clk.clkr,
+ [GSBI6_H_CLK] = &gsbi6_h_clk.clkr,
+ [GSBI7_H_CLK] = &gsbi7_h_clk.clkr,
+ [TSIF_H_CLK] = &tsif_h_clk.clkr,
+ [SDC1_H_CLK] = &sdc1_h_clk.clkr,
+ [SDC3_H_CLK] = &sdc3_h_clk.clkr,
+ [ADM0_CLK] = &adm0_clk.clkr,
+ [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr,
+ [PCIE_A_CLK] = &pcie_a_clk.clkr,
+ [PCIE_AUX_CLK] = &pcie_aux_clk.clkr,
+ [PCIE_H_CLK] = &pcie_h_clk.clkr,
+ [PCIE_PHY_CLK] = &pcie_phy_clk.clkr,
+ [SFAB_SATA_S_H_CLK] = &sfab_sata_s_h_clk.clkr,
+ [PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr,
+ [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr,
+ [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr,
+ [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr,
+ [SATA_H_CLK] = &sata_h_clk.clkr,
+ [SATA_CLK_SRC] = &sata_ref_src.clkr,
+ [SATA_RXOOB_CLK] = &sata_rxoob_clk.clkr,
+ [SATA_PMALIVE_CLK] = &sata_pmalive_clk.clkr,
+ [SATA_PHY_REF_CLK] = &sata_phy_ref_clk.clkr,
+ [SATA_A_CLK] = &sata_a_clk.clkr,
+ [SATA_PHY_CFG_CLK] = &sata_phy_cfg_clk.clkr,
+ [PCIE_ALT_REF_SRC] = &pcie_ref_src.clkr,
+ [PCIE_ALT_REF_CLK] = &pcie_ref_src_clk.clkr,
+ [PCIE_1_A_CLK] = &pcie1_a_clk.clkr,
+ [PCIE_1_AUX_CLK] = &pcie1_aux_clk.clkr,
+ [PCIE_1_H_CLK] = &pcie1_h_clk.clkr,
+ [PCIE_1_PHY_CLK] = &pcie1_phy_clk.clkr,
+ [PCIE_1_ALT_REF_SRC] = &pcie1_ref_src.clkr,
+ [PCIE_1_ALT_REF_CLK] = &pcie1_ref_src_clk.clkr,
+ [PCIE_2_A_CLK] = &pcie2_a_clk.clkr,
+ [PCIE_2_AUX_CLK] = &pcie2_aux_clk.clkr,
+ [PCIE_2_H_CLK] = &pcie2_h_clk.clkr,
+ [PCIE_2_PHY_CLK] = &pcie2_phy_clk.clkr,
+ [PCIE_2_ALT_REF_SRC] = &pcie2_ref_src.clkr,
+ [PCIE_2_ALT_REF_CLK] = &pcie2_ref_src_clk.clkr,
+ [USB30_MASTER_SRC] = &usb30_master_clk_src.clkr,
+ [USB30_0_MASTER_CLK] = &usb30_0_branch_clk.clkr,
+ [USB30_1_MASTER_CLK] = &usb30_1_branch_clk.clkr,
+ [USB30_UTMI_SRC] = &usb30_utmi_clk.clkr,
+ [USB30_0_UTMI_CLK] = &usb30_0_utmi_clk_ctl.clkr,
+ [USB30_1_UTMI_CLK] = &usb30_1_utmi_clk_ctl.clkr,
+ [USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr,
+ [USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_clk_src.clkr,
+ [USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr,
+ [USB_FS1_H_CLK] = &usb_fs1_h_clk.clkr,
+ [USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr,
+ [USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr,
+ [USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_ipq806x_resets[] = {
+ [QDSS_STM_RESET] = { 0x2060, 6 },
+ [AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+ [AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+ [AFAB_SMPSS_M0_RESET] = { 0x20b8, 0 },
+ [AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 },
+ [AFAB_EBI1_CH1_RESET] = { 0x20c4, 7 },
+ [SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+ [SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+ [SFAB_ADM0_M2_RESET] = { 0x21e8, 7 },
+ [ADM0_C2_RESET] = { 0x220c, 4 },
+ [ADM0_C1_RESET] = { 0x220c, 3 },
+ [ADM0_C0_RESET] = { 0x220c, 2 },
+ [ADM0_PBUS_RESET] = { 0x220c, 1 },
+ [ADM0_RESET] = { 0x220c, 0 },
+ [QDSS_CLKS_SW_RESET] = { 0x2260, 5 },
+ [QDSS_POR_RESET] = { 0x2260, 4 },
+ [QDSS_TSCTR_RESET] = { 0x2260, 3 },
+ [QDSS_HRESET_RESET] = { 0x2260, 2 },
+ [QDSS_AXI_RESET] = { 0x2260, 1 },
+ [QDSS_DBG_RESET] = { 0x2260, 0 },
+ [SFAB_PCIE_M_RESET] = { 0x22d8, 1 },
+ [SFAB_PCIE_S_RESET] = { 0x22d8, 0 },
+ [PCIE_EXT_RESET] = { 0x22dc, 6 },
+ [PCIE_PHY_RESET] = { 0x22dc, 5 },
+ [PCIE_PCI_RESET] = { 0x22dc, 4 },
+ [PCIE_POR_RESET] = { 0x22dc, 3 },
+ [PCIE_HCLK_RESET] = { 0x22dc, 2 },
+ [PCIE_ACLK_RESET] = { 0x22dc, 0 },
+ [SFAB_LPASS_RESET] = { 0x23a0, 7 },
+ [SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+ [AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+ [AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+ [SFAB_SATA_S_RESET] = { 0x2480, 7 },
+ [SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+ [DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+ [DFAB_SWAY0_RESET] = { 0x2540, 7 },
+ [DFAB_SWAY1_RESET] = { 0x2544, 7 },
+ [DFAB_ARB0_RESET] = { 0x2560, 7 },
+ [DFAB_ARB1_RESET] = { 0x2564, 7 },
+ [PPSS_PROC_RESET] = { 0x2594, 1 },
+ [PPSS_RESET] = { 0x2594, 0 },
+ [DMA_BAM_RESET] = { 0x25c0, 7 },
+ [SPS_TIC_H_RESET] = { 0x2600, 7 },
+ [SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+ [SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+ [TSIF_H_RESET] = { 0x2700, 7 },
+ [CE1_H_RESET] = { 0x2720, 7 },
+ [CE1_CORE_RESET] = { 0x2724, 7 },
+ [CE1_SLEEP_RESET] = { 0x2728, 7 },
+ [CE2_H_RESET] = { 0x2740, 7 },
+ [CE2_CORE_RESET] = { 0x2744, 7 },
+ [SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+ [SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+ [RPM_PROC_RESET] = { 0x27c0, 7 },
+ [PMIC_SSBI2_RESET] = { 0x280c, 12 },
+ [SDC1_RESET] = { 0x2830, 0 },
+ [SDC2_RESET] = { 0x2850, 0 },
+ [SDC3_RESET] = { 0x2870, 0 },
+ [SDC4_RESET] = { 0x2890, 0 },
+ [USB_HS1_RESET] = { 0x2910, 0 },
+ [USB_HSIC_RESET] = { 0x2934, 0 },
+ [USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+ [USB_FS1_RESET] = { 0x2974, 0 },
+ [GSBI1_RESET] = { 0x29dc, 0 },
+ [GSBI2_RESET] = { 0x29fc, 0 },
+ [GSBI3_RESET] = { 0x2a1c, 0 },
+ [GSBI4_RESET] = { 0x2a3c, 0 },
+ [GSBI5_RESET] = { 0x2a5c, 0 },
+ [GSBI6_RESET] = { 0x2a7c, 0 },
+ [GSBI7_RESET] = { 0x2a9c, 0 },
+ [SPDM_RESET] = { 0x2b6c, 0 },
+ [SEC_CTRL_RESET] = { 0x2b80, 7 },
+ [TLMM_H_RESET] = { 0x2ba0, 7 },
+ [SFAB_SATA_M_RESET] = { 0x2c18, 0 },
+ [SATA_RESET] = { 0x2c1c, 0 },
+ [TSSC_RESET] = { 0x2ca0, 7 },
+ [PDM_RESET] = { 0x2cc0, 12 },
+ [MPM_H_RESET] = { 0x2da0, 7 },
+ [MPM_RESET] = { 0x2da4, 0 },
+ [SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+ [PRNG_RESET] = { 0x2e80, 12 },
+ [SFAB_CE3_M_RESET] = { 0x36c8, 1 },
+ [SFAB_CE3_S_RESET] = { 0x36c8, 0 },
+ [CE3_SLEEP_RESET] = { 0x36d0, 7 },
+ [PCIE_1_M_RESET] = { 0x3a98, 1 },
+ [PCIE_1_S_RESET] = { 0x3a98, 0 },
+ [PCIE_1_EXT_RESET] = { 0x3a9c, 6 },
+ [PCIE_1_PHY_RESET] = { 0x3a9c, 5 },
+ [PCIE_1_PCI_RESET] = { 0x3a9c, 4 },
+ [PCIE_1_POR_RESET] = { 0x3a9c, 3 },
+ [PCIE_1_HCLK_RESET] = { 0x3a9c, 2 },
+ [PCIE_1_ACLK_RESET] = { 0x3a9c, 0 },
+ [PCIE_2_M_RESET] = { 0x3ad8, 1 },
+ [PCIE_2_S_RESET] = { 0x3ad8, 0 },
+ [PCIE_2_EXT_RESET] = { 0x3adc, 6 },
+ [PCIE_2_PHY_RESET] = { 0x3adc, 5 },
+ [PCIE_2_PCI_RESET] = { 0x3adc, 4 },
+ [PCIE_2_POR_RESET] = { 0x3adc, 3 },
+ [PCIE_2_HCLK_RESET] = { 0x3adc, 2 },
+ [PCIE_2_ACLK_RESET] = { 0x3adc, 0 },
+ [SFAB_USB30_S_RESET] = { 0x3b54, 1 },
+ [SFAB_USB30_M_RESET] = { 0x3b54, 0 },
+ [USB30_0_PORT2_HS_PHY_RESET] = { 0x3b50, 5 },
+ [USB30_0_MASTER_RESET] = { 0x3b50, 4 },
+ [USB30_0_SLEEP_RESET] = { 0x3b50, 3 },
+ [USB30_0_UTMI_PHY_RESET] = { 0x3b50, 2 },
+ [USB30_0_POWERON_RESET] = { 0x3b50, 1 },
+ [USB30_0_PHY_RESET] = { 0x3b50, 0 },
+ [USB30_1_MASTER_RESET] = { 0x3b58, 4 },
+ [USB30_1_SLEEP_RESET] = { 0x3b58, 3 },
+ [USB30_1_UTMI_PHY_RESET] = { 0x3b58, 2 },
+ [USB30_1_POWERON_RESET] = { 0x3b58, 1 },
+ [USB30_1_PHY_RESET] = { 0x3b58, 0 },
+ [NSSFB0_RESET] = { 0x3b60, 6 },
+ [NSSFB1_RESET] = { 0x3b60, 7 },
+};
+
+static const struct regmap_config gcc_ipq806x_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3e40,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_ipq806x_desc = {
+ .config = &gcc_ipq806x_regmap_config,
+ .clks = gcc_ipq806x_clks,
+ .num_clks = ARRAY_SIZE(gcc_ipq806x_clks),
+ .resets = gcc_ipq806x_resets,
+ .num_resets = ARRAY_SIZE(gcc_ipq806x_resets),
+};
+
+static const struct of_device_id gcc_ipq806x_match_table[] = {
+ { .compatible = "qcom,gcc-ipq8064" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table);
+
+static int gcc_ipq806x_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ struct device *dev = &pdev->dev;
+
+ /* Temporary until RPM clocks supported */
+ clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
+}
+
+static int gcc_ipq806x_remove(struct platform_device *pdev)
+{
+ qcom_cc_remove(pdev);
+ return 0;
+}
+
+static struct platform_driver gcc_ipq806x_driver = {
+ .probe = gcc_ipq806x_probe,
+ .remove = gcc_ipq806x_remove,
+ .driver = {
+ .name = "gcc-ipq806x",
+ .owner = THIS_MODULE,
+ .of_match_table = gcc_ipq806x_match_table,
+ },
+};
+
+static int __init gcc_ipq806x_init(void)
+{
+ return platform_driver_register(&gcc_ipq806x_driver);
+}
+core_initcall(gcc_ipq806x_init);
+
+static void __exit gcc_ipq806x_exit(void)
+{
+ platform_driver_unregister(&gcc_ipq806x_driver);
+}
+module_exit(gcc_ipq806x_exit);
+
+MODULE_DESCRIPTION("QCOM GCC IPQ806x Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-ipq806x");
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
index f4ffd91901f8..007534f7a2d7 100644
--- a/drivers/clk/qcom/gcc-msm8960.c
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -104,6 +104,7 @@ static struct clk_regmap pll14_vote = {
#define P_PXO 0
#define P_PLL8 1
+#define P_PLL3 2
#define P_CXO 2
static const u8 gcc_pxo_pll8_map[] = {
@@ -128,6 +129,18 @@ static const char *gcc_pxo_pll8_cxo[] = {
"cxo",
};
+static const u8 gcc_pxo_pll8_pll3_map[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 3,
+ [P_PLL3] = 6,
+};
+
+static const char *gcc_pxo_pll8_pll3[] = {
+ "pxo",
+ "pll8_vote",
+ "pll3",
+};
+
static struct freq_tbl clk_tbl_gsbi_uart[] = {
{ 1843200, P_PLL8, 2, 6, 625 },
{ 3686400, P_PLL8, 2, 12, 625 },
@@ -1928,6 +1941,104 @@ static struct clk_branch usb_hs1_xcvr_clk = {
},
};
+static struct clk_rcg usb_hs3_xcvr_src = {
+ .ns_reg = 0x370c,
+ .md_reg = 0x3708,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_usb,
+ .clkr = {
+ .enable_reg = 0x370c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs3_xcvr_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch usb_hs3_xcvr_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 30,
+ .clkr = {
+ .enable_reg = 0x370c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs3_xcvr_clk",
+ .parent_names = (const char *[]){ "usb_hs3_xcvr_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_rcg usb_hs4_xcvr_src = {
+ .ns_reg = 0x372c,
+ .md_reg = 0x3728,
+ .mn = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 7,
+ .mnctr_mode_shift = 5,
+ .n_val_shift = 16,
+ .m_val_shift = 16,
+ .width = 8,
+ },
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 2,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_map,
+ },
+ .freq_tbl = clk_tbl_usb,
+ .clkr = {
+ .enable_reg = 0x372c,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs4_xcvr_src",
+ .parent_names = gcc_pxo_pll8,
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ }
+};
+
+static struct clk_branch usb_hs4_xcvr_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 2,
+ .clkr = {
+ .enable_reg = 0x372c,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs4_xcvr_clk",
+ .parent_names = (const char *[]){ "usb_hs4_xcvr_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
static struct clk_rcg usb_hsic_xcvr_fs_src = {
.ns_reg = 0x2928,
.md_reg = 0x2924,
@@ -2456,6 +2567,34 @@ static struct clk_branch usb_hs1_h_clk = {
},
};
+static struct clk_branch usb_hs3_h_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 31,
+ .clkr = {
+ .enable_reg = 0x3700,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs3_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch usb_hs4_h_clk = {
+ .halt_reg = 0x2fc8,
+ .halt_bit = 7,
+ .clkr = {
+ .enable_reg = 0x3720,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs4_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
static struct clk_branch usb_hsic_h_clk = {
.halt_reg = 0x2fcc,
.halt_bit = 28,
@@ -2582,6 +2721,244 @@ static struct clk_branch adm0_pbus_clk = {
},
};
+static struct freq_tbl clk_tbl_ce3[] = {
+ { 48000000, P_PLL8, 8 },
+ { 100000000, P_PLL3, 12 },
+ { 120000000, P_PLL3, 10 },
+ { }
+};
+
+static struct clk_rcg ce3_src = {
+ .ns_reg = 0x36c0,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll3_map,
+ },
+ .freq_tbl = clk_tbl_ce3,
+ .clkr = {
+ .enable_reg = 0x2c08,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "ce3_src",
+ .parent_names = gcc_pxo_pll8_pll3,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch ce3_core_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 5,
+ .clkr = {
+ .enable_reg = 0x36c4,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "ce3_core_clk",
+ .parent_names = (const char *[]){ "ce3_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch ce3_h_clk = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 16,
+ .clkr = {
+ .enable_reg = 0x36c4,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "ce3_h_clk",
+ .parent_names = (const char *[]){ "ce3_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static const struct freq_tbl clk_tbl_sata_ref[] = {
+ { 48000000, P_PLL8, 8, 0, 0 },
+ { 100000000, P_PLL3, 12, 0, 0 },
+ { }
+};
+
+static struct clk_rcg sata_clk_src = {
+ .ns_reg = 0x2c08,
+ .p = {
+ .pre_div_shift = 3,
+ .pre_div_width = 4,
+ },
+ .s = {
+ .src_sel_shift = 0,
+ .parent_map = gcc_pxo_pll8_pll3_map,
+ },
+ .freq_tbl = clk_tbl_sata_ref,
+ .clkr = {
+ .enable_reg = 0x2c08,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_clk_src",
+ .parent_names = gcc_pxo_pll8_pll3,
+ .num_parents = 3,
+ .ops = &clk_rcg_ops,
+ .flags = CLK_SET_RATE_GATE,
+ },
+ },
+};
+
+static struct clk_branch sata_rxoob_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 26,
+ .clkr = {
+ .enable_reg = 0x2c0c,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_rxoob_clk",
+ .parent_names = (const char *[]){ "sata_clk_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sata_pmalive_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 25,
+ .clkr = {
+ .enable_reg = 0x2c10,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_pmalive_clk",
+ .parent_names = (const char *[]){ "sata_clk_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch sata_phy_ref_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 24,
+ .clkr = {
+ .enable_reg = 0x2c14,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_phy_ref_clk",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+static struct clk_branch sata_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x2c20,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sata_h_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 27,
+ .clkr = {
+ .enable_reg = 0x2c00,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sfab_sata_s_h_clk = {
+ .halt_reg = 0x2fc4,
+ .halt_bit = 14,
+ .clkr = {
+ .enable_reg = 0x2480,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sfab_sata_s_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch sata_phy_cfg_clk = {
+ .halt_reg = 0x2fcc,
+ .halt_bit = 12,
+ .clkr = {
+ .enable_reg = 0x2c40,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "sata_phy_cfg_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_phy_ref_clk = {
+ .halt_reg = 0x2fdc,
+ .halt_bit = 29,
+ .clkr = {
+ .enable_reg = 0x22d0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_phy_ref_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_h_clk = {
+ .halt_reg = 0x2fd4,
+ .halt_bit = 8,
+ .clkr = {
+ .enable_reg = 0x22cc,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_h_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
+static struct clk_branch pcie_a_clk = {
+ .halt_reg = 0x2fc0,
+ .halt_bit = 13,
+ .clkr = {
+ .enable_reg = 0x22c0,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "pcie_a_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
static struct clk_branch pmic_arb0_h_clk = {
.halt_reg = 0x2fd8,
.halt_check = BRANCH_HALT_VOTED,
@@ -2869,13 +3246,205 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = {
};
static struct clk_regmap *gcc_apq8064_clks[] = {
+ [PLL3] = &pll3.clkr,
[PLL8] = &pll8.clkr,
[PLL8_VOTE] = &pll8_vote,
+ [PLL14] = &pll14.clkr,
+ [PLL14_VOTE] = &pll14_vote,
+ [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+ [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+ [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+ [GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr,
+ [GSBI3_UART_SRC] = &gsbi3_uart_src.clkr,
+ [GSBI3_UART_CLK] = &gsbi3_uart_clk.clkr,
+ [GSBI4_UART_SRC] = &gsbi4_uart_src.clkr,
+ [GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr,
+ [GSBI5_UART_SRC] = &gsbi5_uart_src.clkr,
+ [GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr,
+ [GSBI6_UART_SRC] = &gsbi6_uart_src.clkr,
+ [GSBI6_UART_CLK] = &gsbi6_uart_clk.clkr,
[GSBI7_UART_SRC] = &gsbi7_uart_src.clkr,
[GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr,
+ [GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr,
+ [GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr,
+ [GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr,
+ [GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr,
+ [GSBI3_QUP_SRC] = &gsbi3_qup_src.clkr,
+ [GSBI3_QUP_CLK] = &gsbi3_qup_clk.clkr,
+ [GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr,
+ [GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr,
+ [GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr,
+ [GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr,
+ [GSBI6_QUP_SRC] = &gsbi6_qup_src.clkr,
+ [GSBI6_QUP_CLK] = &gsbi6_qup_clk.clkr,
[GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr,
[GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr,
+ [GP0_SRC] = &gp0_src.clkr,
+ [GP0_CLK] = &gp0_clk.clkr,
+ [GP1_SRC] = &gp1_src.clkr,
+ [GP1_CLK] = &gp1_clk.clkr,
+ [GP2_SRC] = &gp2_src.clkr,
+ [GP2_CLK] = &gp2_clk.clkr,
+ [PMEM_A_CLK] = &pmem_clk.clkr,
+ [PRNG_SRC] = &prng_src.clkr,
+ [PRNG_CLK] = &prng_clk.clkr,
+ [SDC1_SRC] = &sdc1_src.clkr,
+ [SDC1_CLK] = &sdc1_clk.clkr,
+ [SDC2_SRC] = &sdc2_src.clkr,
+ [SDC2_CLK] = &sdc2_clk.clkr,
+ [SDC3_SRC] = &sdc3_src.clkr,
+ [SDC3_CLK] = &sdc3_clk.clkr,
+ [SDC4_SRC] = &sdc4_src.clkr,
+ [SDC4_CLK] = &sdc4_clk.clkr,
+ [TSIF_REF_SRC] = &tsif_ref_src.clkr,
+ [TSIF_REF_CLK] = &tsif_ref_clk.clkr,
+ [USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_src.clkr,
+ [USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr,
+ [USB_HS3_XCVR_SRC] = &usb_hs3_xcvr_src.clkr,
+ [USB_HS3_XCVR_CLK] = &usb_hs3_xcvr_clk.clkr,
+ [USB_HS4_XCVR_SRC] = &usb_hs4_xcvr_src.clkr,
+ [USB_HS4_XCVR_CLK] = &usb_hs4_xcvr_clk.clkr,
+ [USB_HSIC_XCVR_FS_SRC] = &usb_hsic_xcvr_fs_src.clkr,
+ [USB_HSIC_XCVR_FS_CLK] = &usb_hsic_xcvr_fs_clk.clkr,
+ [USB_HSIC_SYSTEM_CLK] = &usb_hsic_system_clk.clkr,
+ [USB_HSIC_HSIC_CLK] = &usb_hsic_hsic_clk.clkr,
+ [USB_HSIC_HSIO_CAL_CLK] = &usb_hsic_hsio_cal_clk.clkr,
+ [USB_FS1_XCVR_FS_SRC] = &usb_fs1_xcvr_fs_src.clkr,
+ [USB_FS1_XCVR_FS_CLK] = &usb_fs1_xcvr_fs_clk.clkr,
+ [USB_FS1_SYSTEM_CLK] = &usb_fs1_system_clk.clkr,
+ [SATA_H_CLK] = &sata_h_clk.clkr,
+ [SATA_CLK_SRC] = &sata_clk_src.clkr,
+ [SATA_RXOOB_CLK] = &sata_rxoob_clk.clkr,
+ [SATA_PMALIVE_CLK] = &sata_pmalive_clk.clkr,
+ [SATA_PHY_REF_CLK] = &sata_phy_ref_clk.clkr,
+ [SATA_PHY_CFG_CLK] = &sata_phy_cfg_clk.clkr,
+ [SATA_A_CLK] = &sata_a_clk.clkr,
+ [SFAB_SATA_S_H_CLK] = &sfab_sata_s_h_clk.clkr,
+ [CE3_SRC] = &ce3_src.clkr,
+ [CE3_CORE_CLK] = &ce3_core_clk.clkr,
+ [CE3_H_CLK] = &ce3_h_clk.clkr,
+ [DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr,
+ [GSBI1_H_CLK] = &gsbi1_h_clk.clkr,
+ [GSBI2_H_CLK] = &gsbi2_h_clk.clkr,
+ [GSBI3_H_CLK] = &gsbi3_h_clk.clkr,
+ [GSBI4_H_CLK] = &gsbi4_h_clk.clkr,
+ [GSBI5_H_CLK] = &gsbi5_h_clk.clkr,
+ [GSBI6_H_CLK] = &gsbi6_h_clk.clkr,
[GSBI7_H_CLK] = &gsbi7_h_clk.clkr,
+ [TSIF_H_CLK] = &tsif_h_clk.clkr,
+ [USB_FS1_H_CLK] = &usb_fs1_h_clk.clkr,
+ [USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr,
+ [USB_HSIC_H_CLK] = &usb_hsic_h_clk.clkr,
+ [USB_HS3_H_CLK] = &usb_hs3_h_clk.clkr,
+ [USB_HS4_H_CLK] = &usb_hs4_h_clk.clkr,
+ [SDC1_H_CLK] = &sdc1_h_clk.clkr,
+ [SDC2_H_CLK] = &sdc2_h_clk.clkr,
+ [SDC3_H_CLK] = &sdc3_h_clk.clkr,
+ [SDC4_H_CLK] = &sdc4_h_clk.clkr,
+ [ADM0_CLK] = &adm0_clk.clkr,
+ [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr,
+ [PCIE_A_CLK] = &pcie_a_clk.clkr,
+ [PCIE_PHY_REF_CLK] = &pcie_phy_ref_clk.clkr,
+ [PCIE_H_CLK] = &pcie_h_clk.clkr,
+ [PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr,
+ [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr,
+ [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr,
+ [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_apq8064_resets[] = {
+ [QDSS_STM_RESET] = { 0x2060, 6 },
+ [AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+ [AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+ [AFAB_SMPSS_M0_RESET] = { 0x20b8 },
+ [AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 },
+ [AFAB_EBI1_CH1_RESET] = { 0x20c4, 7},
+ [SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+ [SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+ [SFAB_ADM0_M2_RESET] = { 0x21e8, 7 },
+ [ADM0_C2_RESET] = { 0x220c, 4},
+ [ADM0_C1_RESET] = { 0x220c, 3},
+ [ADM0_C0_RESET] = { 0x220c, 2},
+ [ADM0_PBUS_RESET] = { 0x220c, 1 },
+ [ADM0_RESET] = { 0x220c },
+ [QDSS_CLKS_SW_RESET] = { 0x2260, 5 },
+ [QDSS_POR_RESET] = { 0x2260, 4 },
+ [QDSS_TSCTR_RESET] = { 0x2260, 3 },
+ [QDSS_HRESET_RESET] = { 0x2260, 2 },
+ [QDSS_AXI_RESET] = { 0x2260, 1 },
+ [QDSS_DBG_RESET] = { 0x2260 },
+ [SFAB_PCIE_M_RESET] = { 0x22d8, 1 },
+ [SFAB_PCIE_S_RESET] = { 0x22d8 },
+ [PCIE_EXT_PCI_RESET] = { 0x22dc, 6 },
+ [PCIE_PHY_RESET] = { 0x22dc, 5 },
+ [PCIE_PCI_RESET] = { 0x22dc, 4 },
+ [PCIE_POR_RESET] = { 0x22dc, 3 },
+ [PCIE_HCLK_RESET] = { 0x22dc, 2 },
+ [PCIE_ACLK_RESET] = { 0x22dc },
+ [SFAB_USB3_M_RESET] = { 0x2360, 7 },
+ [SFAB_RIVA_M_RESET] = { 0x2380, 7 },
+ [SFAB_LPASS_RESET] = { 0x23a0, 7 },
+ [SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+ [AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+ [AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+ [SFAB_SATA_S_RESET] = { 0x2480, 7 },
+ [SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+ [DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+ [DFAB_SWAY0_RESET] = { 0x2540, 7 },
+ [DFAB_SWAY1_RESET] = { 0x2544, 7 },
+ [DFAB_ARB0_RESET] = { 0x2560, 7 },
+ [DFAB_ARB1_RESET] = { 0x2564, 7 },
+ [PPSS_PROC_RESET] = { 0x2594, 1 },
+ [PPSS_RESET] = { 0x2594},
+ [DMA_BAM_RESET] = { 0x25c0, 7 },
+ [SPS_TIC_H_RESET] = { 0x2600, 7 },
+ [SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+ [SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+ [TSIF_H_RESET] = { 0x2700, 7 },
+ [CE1_H_RESET] = { 0x2720, 7 },
+ [CE1_CORE_RESET] = { 0x2724, 7 },
+ [CE1_SLEEP_RESET] = { 0x2728, 7 },
+ [CE2_H_RESET] = { 0x2740, 7 },
+ [CE2_CORE_RESET] = { 0x2744, 7 },
+ [SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+ [SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+ [RPM_PROC_RESET] = { 0x27c0, 7 },
+ [PMIC_SSBI2_RESET] = { 0x280c, 12 },
+ [SDC1_RESET] = { 0x2830 },
+ [SDC2_RESET] = { 0x2850 },
+ [SDC3_RESET] = { 0x2870 },
+ [SDC4_RESET] = { 0x2890 },
+ [USB_HS1_RESET] = { 0x2910 },
+ [USB_HSIC_RESET] = { 0x2934 },
+ [USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+ [USB_FS1_RESET] = { 0x2974 },
+ [GSBI1_RESET] = { 0x29dc },
+ [GSBI2_RESET] = { 0x29fc },
+ [GSBI3_RESET] = { 0x2a1c },
+ [GSBI4_RESET] = { 0x2a3c },
+ [GSBI5_RESET] = { 0x2a5c },
+ [GSBI6_RESET] = { 0x2a7c },
+ [GSBI7_RESET] = { 0x2a9c },
+ [SPDM_RESET] = { 0x2b6c },
+ [TLMM_H_RESET] = { 0x2ba0, 7 },
+ [SATA_SFAB_M_RESET] = { 0x2c18 },
+ [SATA_RESET] = { 0x2c1c },
+ [GSS_SLP_RESET] = { 0x2c60, 7 },
+ [GSS_RESET] = { 0x2c64 },
+ [TSSC_RESET] = { 0x2ca0, 7 },
+ [PDM_RESET] = { 0x2cc0, 12 },
+ [MPM_H_RESET] = { 0x2da0, 7 },
+ [MPM_RESET] = { 0x2da4 },
+ [SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+ [PRNG_RESET] = { 0x2e80, 12 },
+ [RIVA_RESET] = { 0x35e0 },
+ [CE3_H_RESET] = { 0x36c4, 7 },
+ [SFAB_CE3_M_RESET] = { 0x36c8, 1 },
+ [SFAB_CE3_S_RESET] = { 0x36c8 },
+ [CE3_RESET] = { 0x36cc, 7 },
+ [CE3_SLEEP_RESET] = { 0x36d0, 7 },
+ [USB_HS3_RESET] = { 0x3710 },
+ [USB_HS4_RESET] = { 0x3730 },
};
static const struct regmap_config gcc_msm8960_regmap_config = {
@@ -2886,6 +3455,14 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
.fast_io = true,
};
+static const struct regmap_config gcc_apq8064_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3880,
+ .fast_io = true,
+};
+
static const struct qcom_cc_desc gcc_msm8960_desc = {
.config = &gcc_msm8960_regmap_config,
.clks = gcc_msm8960_clks,
@@ -2895,11 +3472,11 @@ static const struct qcom_cc_desc gcc_msm8960_desc = {
};
static const struct qcom_cc_desc gcc_apq8064_desc = {
- .config = &gcc_msm8960_regmap_config,
+ .config = &gcc_apq8064_regmap_config,
.clks = gcc_apq8064_clks,
.num_clks = ARRAY_SIZE(gcc_apq8064_clks),
- .resets = gcc_msm8960_resets,
- .num_resets = ARRAY_SIZE(gcc_msm8960_resets),
+ .resets = gcc_apq8064_resets,
+ .num_resets = ARRAY_SIZE(gcc_apq8064_resets),
};
static const struct of_device_id gcc_msm8960_match_table[] = {
diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
new file mode 100644
index 000000000000..751eea376a2b
--- /dev/null
+++ b/drivers/clk/qcom/mmcc-apq8084.c
@@ -0,0 +1,3352 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,mmcc-apq8084.h>
+#include <dt-bindings/reset/qcom,mmcc-apq8084.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO 0
+#define P_MMPLL0 1
+#define P_EDPLINK 1
+#define P_MMPLL1 2
+#define P_HDMIPLL 2
+#define P_GPLL0 3
+#define P_EDPVCO 3
+#define P_MMPLL4 4
+#define P_DSI0PLL 4
+#define P_DSI0PLL_BYTE 4
+#define P_MMPLL2 4
+#define P_MMPLL3 4
+#define P_GPLL1 5
+#define P_DSI1PLL 5
+#define P_DSI1PLL_BYTE 5
+#define P_MMSLEEP 6
+
+static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_GPLL0] = 5,
+};
+
+static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+ "xo",
+ "mmpll0_vote",
+ "mmpll1_vote",
+ "mmss_gpll0_vote",
+};
+
+static const u8 mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_HDMIPLL] = 4,
+ [P_GPLL0] = 5,
+ [P_DSI0PLL] = 2,
+ [P_DSI1PLL] = 3,
+};
+
+static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+ "xo",
+ "mmpll0_vote",
+ "hdmipll",
+ "mmss_gpll0_vote",
+ "dsi0pll",
+ "dsi1pll",
+};
+
+static const u8 mmcc_xo_mmpll0_1_2_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_GPLL0] = 5,
+ [P_MMPLL2] = 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+ "xo",
+ "mmpll0_vote",
+ "mmpll1_vote",
+ "mmss_gpll0_vote",
+ "mmpll2",
+};
+
+static const u8 mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_GPLL0] = 5,
+ [P_MMPLL3] = 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+ "xo",
+ "mmpll0_vote",
+ "mmpll1_vote",
+ "mmss_gpll0_vote",
+ "mmpll3",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_map[] = {
+ [P_XO] = 0,
+ [P_EDPLINK] = 4,
+ [P_HDMIPLL] = 3,
+ [P_EDPVCO] = 5,
+ [P_DSI0PLL] = 1,
+ [P_DSI1PLL] = 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp[] = {
+ "xo",
+ "edp_link_clk",
+ "hdmipll",
+ "edp_vco_div",
+ "dsi0pll",
+ "dsi1pll",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_EDPLINK] = 4,
+ [P_HDMIPLL] = 3,
+ [P_GPLL0] = 5,
+ [P_DSI0PLL] = 1,
+ [P_DSI1PLL] = 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+ "xo",
+ "edp_link_clk",
+ "hdmipll",
+ "gpll0_vote",
+ "dsi0pll",
+ "dsi1pll",
+};
+
+static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_EDPLINK] = 4,
+ [P_HDMIPLL] = 3,
+ [P_GPLL0] = 5,
+ [P_DSI0PLL_BYTE] = 1,
+ [P_DSI1PLL_BYTE] = 2,
+};
+
+static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+ "xo",
+ "edp_link_clk",
+ "hdmipll",
+ "gpll0_vote",
+ "dsi0pllbyte",
+ "dsi1pllbyte",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_GPLL0] = 5,
+ [P_MMPLL4] = 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
+ "xo",
+ "mmpll0",
+ "mmpll1",
+ "mmpll4",
+ "gpll0",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_MMPLL4] = 3,
+ [P_GPLL0] = 5,
+ [P_GPLL1] = 4,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
+ "xo",
+ "mmpll0",
+ "mmpll1",
+ "mmpll4",
+ "gpll1",
+ "gpll0",
+};
+
+static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
+ [P_XO] = 0,
+ [P_MMPLL0] = 1,
+ [P_MMPLL1] = 2,
+ [P_MMPLL4] = 3,
+ [P_GPLL0] = 5,
+ [P_GPLL1] = 4,
+ [P_MMSLEEP] = 6,
+};
+
+static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
+ "xo",
+ "mmpll0",
+ "mmpll1",
+ "mmpll4",
+ "gpll1",
+ "gpll0",
+ "sleep_clk_src",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll mmpll0 = {
+ .l_reg = 0x0004,
+ .m_reg = 0x0008,
+ .n_reg = 0x000c,
+ .config_reg = 0x0014,
+ .mode_reg = 0x0000,
+ .status_reg = 0x001c,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll0",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap mmpll0_vote = {
+ .enable_reg = 0x0100,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmpll0_vote",
+ .parent_names = (const char *[]){ "mmpll0" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static struct clk_pll mmpll1 = {
+ .l_reg = 0x0044,
+ .m_reg = 0x0048,
+ .n_reg = 0x004c,
+ .config_reg = 0x0050,
+ .mode_reg = 0x0040,
+ .status_reg = 0x005c,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll1",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap mmpll1_vote = {
+ .enable_reg = 0x0100,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmpll1_vote",
+ .parent_names = (const char *[]){ "mmpll1" },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static struct clk_pll mmpll2 = {
+ .l_reg = 0x4104,
+ .m_reg = 0x4108,
+ .n_reg = 0x410c,
+ .config_reg = 0x4110,
+ .mode_reg = 0x4100,
+ .status_reg = 0x411c,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll2",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_pll mmpll3 = {
+ .l_reg = 0x0084,
+ .m_reg = 0x0088,
+ .n_reg = 0x008c,
+ .config_reg = 0x0090,
+ .mode_reg = 0x0080,
+ .status_reg = 0x009c,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll3",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_pll mmpll4 = {
+ .l_reg = 0x00a4,
+ .m_reg = 0x00a8,
+ .n_reg = 0x00ac,
+ .config_reg = 0x00b0,
+ .mode_reg = 0x0080,
+ .status_reg = 0x00bc,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmpll4",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_rcg2 mmss_ahb_clk_src = {
+ .cmd_rcgr = 0x5000,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmss_ahb_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mmss_axi_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(37500000, P_GPLL0, 16, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(333430000, P_MMPLL1, 3.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ F(466800000, P_MMPLL1, 2.5, 0, 0),
+};
+
+static struct clk_rcg2 mmss_axi_clk_src = {
+ .cmd_rcgr = 0x5040,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_mmss_axi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mmss_axi_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_ocmemnoc_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(37500000, P_GPLL0, 16, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(109090000, P_GPLL0, 5.5, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+};
+
+static struct clk_rcg2 ocmemnoc_clk_src = {
+ .cmd_rcgr = 0x5090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_ocmemnoc_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "ocmemnoc_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_csi0_3_clk[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+ .cmd_rcgr = 0x3090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_csi0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+ .cmd_rcgr = 0x3100,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_csi0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi1_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+ .cmd_rcgr = 0x3160,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_csi0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi2_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi3_clk_src = {
+ .cmd_rcgr = 0x31c0,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_csi0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi3_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_vfe_vfe0_1_clk[] = {
+ F(37500000, P_GPLL0, 16, 0, 0),
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(80000000, P_GPLL0, 7.5, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(109090000, P_GPLL0, 5.5, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(465000000, P_MMPLL4, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+ .cmd_rcgr = 0x3600,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vfe0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+ .cmd_rcgr = 0x3620,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vfe1_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_mdp_clk[] = {
+ F(37500000, P_GPLL0, 16, 0, 0),
+ F(60000000, P_GPLL0, 10, 0, 0),
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(85710000, P_GPLL0, 7, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(160000000, P_MMPLL0, 5, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(300000000, P_GPLL0, 2, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+ .cmd_rcgr = 0x2040,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_dsi_hdmi_gpll0_map,
+ .freq_tbl = ftbl_mdss_mdp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mdp_clk_src",
+ .parent_names = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+ .cmd_rcgr = 0x4000,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_2_gpll0_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gfx3d_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_2_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_jpeg_jpeg0_2_clk[] = {
+ F(75000000, P_GPLL0, 8, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(200000000, P_GPLL0, 3, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+ .cmd_rcgr = 0x3500,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 jpeg1_clk_src = {
+ .cmd_rcgr = 0x3520,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg1_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 jpeg2_clk_src = {
+ .cmd_rcgr = 0x3540,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "jpeg2_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl pixel_freq_tbl[] = {
+ { .src = P_DSI0PLL },
+ { }
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+ .cmd_rcgr = 0x2000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+ .freq_tbl = pixel_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pclk0_clk_src",
+ .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+ .cmd_rcgr = 0x2020,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+ .freq_tbl = pixel_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pclk1_clk_src",
+ .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_pixel_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct freq_tbl ftbl_venus0_vcodec0_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(465000000, P_MMPLL3, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+ .cmd_rcgr = 0x1000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_3_gpll0_map,
+ .freq_tbl = ftbl_venus0_vcodec0_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vcodec0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_3_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_avsync_vp_clk[] = {
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vp_clk_src = {
+ .cmd_rcgr = 0x2430,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_avsync_vp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vp_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_cci_cci_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+ .cmd_rcgr = 0x3300,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+ .freq_tbl = ftbl_camss_cci_cci_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "cci_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_gp0_1_clk[] = {
+ F(10000, P_XO, 16, 1, 120),
+ F(24000, P_XO, 16, 1, 50),
+ F(6000000, P_GPLL0, 10, 1, 10),
+ F(12000000, P_GPLL0, 10, 1, 5),
+ F(13000000, P_GPLL0, 4, 13, 150),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ { }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+ .cmd_rcgr = 0x3420,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map,
+ .freq_tbl = ftbl_camss_gp0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "camss_gp0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0_sleep,
+ .num_parents = 7,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+ .cmd_rcgr = 0x3450,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map,
+ .freq_tbl = ftbl_camss_gp0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "camss_gp1_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0_sleep,
+ .num_parents = 7,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_mclk0_3_clk[] = {
+ F(4800000, P_XO, 4, 0, 0),
+ F(6000000, P_GPLL0, 10, 1, 10),
+ F(8000000, P_GPLL0, 15, 1, 5),
+ F(9600000, P_XO, 2, 0, 0),
+ F(16000000, P_MMPLL0, 10, 1, 5),
+ F(19200000, P_XO, 1, 0, 0),
+ F(24000000, P_GPLL0, 5, 1, 5),
+ F(32000000, P_MMPLL0, 5, 1, 5),
+ F(48000000, P_GPLL0, 12.5, 0, 0),
+ F(64000000, P_MMPLL0, 12.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+ .cmd_rcgr = 0x3360,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+ .freq_tbl = ftbl_camss_mclk0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk0_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+ .cmd_rcgr = 0x3390,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+ .freq_tbl = ftbl_camss_mclk0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk1_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+ .cmd_rcgr = 0x33c0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+ .freq_tbl = ftbl_camss_mclk0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk2_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+ .cmd_rcgr = 0x33f0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll1_0_map,
+ .freq_tbl = ftbl_camss_mclk0_3_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "mclk3_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll1_0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_phy0_2_csi0_2phytimer_clk[] = {
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x3000,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi0phytimer_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x3030,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi1phytimer_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x3060,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "csi2phytimer_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_camss_vfe_cpp_clk[] = {
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(372000000, P_MMPLL4, 2.5, 0, 0),
+ F(465000000, P_MMPLL4, 2, 0, 0),
+ F(600000000, P_GPLL0, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+ .cmd_rcgr = 0x3640,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_1_4_gpll0_map,
+ .freq_tbl = ftbl_camss_vfe_cpp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "cpp_clk_src",
+ .parent_names = mmcc_xo_mmpll0_1_4_gpll0,
+ .num_parents = 5,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl byte_freq_tbl[] = {
+ { .src = P_DSI0PLL_BYTE },
+ { }
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+ .cmd_rcgr = 0x2120,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+ .freq_tbl = byte_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "byte0_clk_src",
+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_byte_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+ .cmd_rcgr = 0x2140,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+ .freq_tbl = byte_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "byte1_clk_src",
+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_byte_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_edpaux_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 edpaux_clk_src = {
+ .cmd_rcgr = 0x20e0,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_mdss_edpaux_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "edpaux_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_edplink_clk[] = {
+ F(135000000, P_EDPLINK, 2, 0, 0),
+ F(270000000, P_EDPLINK, 11, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 edplink_clk_src = {
+ .cmd_rcgr = 0x20c0,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+ .freq_tbl = ftbl_mdss_edplink_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "edplink_clk_src",
+ .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct freq_tbl edp_pixel_freq_tbl[] = {
+ { .src = P_EDPVCO },
+ { }
+};
+
+static struct clk_rcg2 edppixel_clk_src = {
+ .cmd_rcgr = 0x20a0,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi_hdmi_edp_map,
+ .freq_tbl = edp_pixel_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "edppixel_clk_src",
+ .parent_names = mmcc_xo_dsi_hdmi_edp,
+ .num_parents = 6,
+ .ops = &clk_edp_pixel_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+ .cmd_rcgr = 0x2160,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+ .freq_tbl = ftbl_mdss_esc0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "esc0_clk_src",
+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+ .cmd_rcgr = 0x2180,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
+ .freq_tbl = ftbl_mdss_esc0_1_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "esc1_clk_src",
+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl extpclk_freq_tbl[] = {
+ { .src = P_HDMIPLL },
+ { }
+};
+
+static struct clk_rcg2 extpclk_clk_src = {
+ .cmd_rcgr = 0x2060,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+ .freq_tbl = extpclk_freq_tbl,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "extpclk_clk_src",
+ .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = 6,
+ .ops = &clk_byte_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_hdmi_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 hdmi_clk_src = {
+ .cmd_rcgr = 0x2100,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_mdss_hdmi_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "hdmi_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mdss_vsync_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+ .cmd_rcgr = 0x2080,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_mdss_vsync_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vsync_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_mmss_rbcpr_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbcpr_clk_src = {
+ .cmd_rcgr = 0x4060,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_mmss_rbcpr_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "rbcpr_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_oxili_rbbmtimer_clk[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 rbbmtimer_clk_src = {
+ .cmd_rcgr = 0x4090,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_oxili_rbbmtimer_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "rbbmtimer_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_vpu_maple_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(133330000, P_GPLL0, 4.5, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(266670000, P_MMPLL0, 3, 0, 0),
+ F(465000000, P_MMPLL3, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 maple_clk_src = {
+ .cmd_rcgr = 0x1320,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_vpu_maple_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "maple_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_vpu_vdp_clk[] = {
+ F(50000000, P_GPLL0, 12, 0, 0),
+ F(100000000, P_GPLL0, 6, 0, 0),
+ F(200000000, P_MMPLL0, 4, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vdp_clk_src = {
+ .cmd_rcgr = 0x1300,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_vpu_vdp_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vdp_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_vpu_bus_clk[] = {
+ F(40000000, P_GPLL0, 15, 0, 0),
+ F(80000000, P_MMPLL0, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 vpu_bus_clk_src = {
+ .cmd_rcgr = 0x1340,
+ .hid_width = 5,
+ .parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+ .freq_tbl = ftbl_vpu_bus_clk,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "vpu_bus_clk_src",
+ .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = 4,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch mmss_cxo_clk = {
+ .halt_reg = 0x5104,
+ .clkr = {
+ .enable_reg = 0x5104,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_cxo_clk",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_sleepclk_clk = {
+ .halt_reg = 0x5100,
+ .clkr = {
+ .enable_reg = 0x5100,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_sleepclk_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_ahb_clk = {
+ .halt_reg = 0x2414,
+ .clkr = {
+ .enable_reg = 0x2414,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_edppixel_clk = {
+ .halt_reg = 0x2418,
+ .clkr = {
+ .enable_reg = 0x2418,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_edppixel_clk",
+ .parent_names = (const char *[]){
+ "edppixel_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_extpclk_clk = {
+ .halt_reg = 0x2410,
+ .clkr = {
+ .enable_reg = 0x2410,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_extpclk_clk",
+ .parent_names = (const char *[]){
+ "extpclk_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_pclk0_clk = {
+ .halt_reg = 0x241c,
+ .clkr = {
+ .enable_reg = 0x241c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_pclk0_clk",
+ .parent_names = (const char *[]){
+ "pclk0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_pclk1_clk = {
+ .halt_reg = 0x2420,
+ .clkr = {
+ .enable_reg = 0x2420,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_pclk1_clk",
+ .parent_names = (const char *[]){
+ "pclk1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch avsync_vp_clk = {
+ .halt_reg = 0x2404,
+ .clkr = {
+ .enable_reg = 0x2404,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "avsync_vp_clk",
+ .parent_names = (const char *[]){
+ "vp_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_ahb_clk = {
+ .halt_reg = 0x348c,
+ .clkr = {
+ .enable_reg = 0x348c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_cci_cci_ahb_clk = {
+ .halt_reg = 0x3348,
+ .clkr = {
+ .enable_reg = 0x3348,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_cci_cci_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_cci_cci_clk = {
+ .halt_reg = 0x3344,
+ .clkr = {
+ .enable_reg = 0x3344,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_cci_cci_clk",
+ .parent_names = (const char *[]){
+ "cci_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0_ahb_clk = {
+ .halt_reg = 0x30bc,
+ .clkr = {
+ .enable_reg = 0x30bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0_clk = {
+ .halt_reg = 0x30b4,
+ .clkr = {
+ .enable_reg = 0x30b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0_clk",
+ .parent_names = (const char *[]){
+ "csi0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0phy_clk = {
+ .halt_reg = 0x30c4,
+ .clkr = {
+ .enable_reg = 0x30c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0phy_clk",
+ .parent_names = (const char *[]){
+ "csi0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0pix_clk = {
+ .halt_reg = 0x30e4,
+ .clkr = {
+ .enable_reg = 0x30e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0pix_clk",
+ .parent_names = (const char *[]){
+ "csi0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi0rdi_clk = {
+ .halt_reg = 0x30d4,
+ .clkr = {
+ .enable_reg = 0x30d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi0rdi_clk",
+ .parent_names = (const char *[]){
+ "csi0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1_ahb_clk = {
+ .halt_reg = 0x3128,
+ .clkr = {
+ .enable_reg = 0x3128,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1_clk = {
+ .halt_reg = 0x3124,
+ .clkr = {
+ .enable_reg = 0x3124,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1_clk",
+ .parent_names = (const char *[]){
+ "csi1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1phy_clk = {
+ .halt_reg = 0x3134,
+ .clkr = {
+ .enable_reg = 0x3134,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1phy_clk",
+ .parent_names = (const char *[]){
+ "csi1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1pix_clk = {
+ .halt_reg = 0x3154,
+ .clkr = {
+ .enable_reg = 0x3154,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1pix_clk",
+ .parent_names = (const char *[]){
+ "csi1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi1rdi_clk = {
+ .halt_reg = 0x3144,
+ .clkr = {
+ .enable_reg = 0x3144,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi1rdi_clk",
+ .parent_names = (const char *[]){
+ "csi1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2_ahb_clk = {
+ .halt_reg = 0x3188,
+ .clkr = {
+ .enable_reg = 0x3188,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2_clk = {
+ .halt_reg = 0x3184,
+ .clkr = {
+ .enable_reg = 0x3184,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2_clk",
+ .parent_names = (const char *[]){
+ "csi2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2phy_clk = {
+ .halt_reg = 0x3194,
+ .clkr = {
+ .enable_reg = 0x3194,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2phy_clk",
+ .parent_names = (const char *[]){
+ "csi2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2pix_clk = {
+ .halt_reg = 0x31b4,
+ .clkr = {
+ .enable_reg = 0x31b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2pix_clk",
+ .parent_names = (const char *[]){
+ "csi2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi2rdi_clk = {
+ .halt_reg = 0x31a4,
+ .clkr = {
+ .enable_reg = 0x31a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi2rdi_clk",
+ .parent_names = (const char *[]){
+ "csi2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3_ahb_clk = {
+ .halt_reg = 0x31e8,
+ .clkr = {
+ .enable_reg = 0x31e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3_clk = {
+ .halt_reg = 0x31e4,
+ .clkr = {
+ .enable_reg = 0x31e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3_clk",
+ .parent_names = (const char *[]){
+ "csi3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3phy_clk = {
+ .halt_reg = 0x31f4,
+ .clkr = {
+ .enable_reg = 0x31f4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3phy_clk",
+ .parent_names = (const char *[]){
+ "csi3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3pix_clk = {
+ .halt_reg = 0x3214,
+ .clkr = {
+ .enable_reg = 0x3214,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3pix_clk",
+ .parent_names = (const char *[]){
+ "csi3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi3rdi_clk = {
+ .halt_reg = 0x3204,
+ .clkr = {
+ .enable_reg = 0x3204,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi3rdi_clk",
+ .parent_names = (const char *[]){
+ "csi3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi_vfe0_clk = {
+ .halt_reg = 0x3704,
+ .clkr = {
+ .enable_reg = 0x3704,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi_vfe0_clk",
+ .parent_names = (const char *[]){
+ "vfe0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_csi_vfe1_clk = {
+ .halt_reg = 0x3714,
+ .clkr = {
+ .enable_reg = 0x3714,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_csi_vfe1_clk",
+ .parent_names = (const char *[]){
+ "vfe1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_gp0_clk = {
+ .halt_reg = 0x3444,
+ .clkr = {
+ .enable_reg = 0x3444,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_gp0_clk",
+ .parent_names = (const char *[]){
+ "camss_gp0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_gp1_clk = {
+ .halt_reg = 0x3474,
+ .clkr = {
+ .enable_reg = 0x3474,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_gp1_clk",
+ .parent_names = (const char *[]){
+ "camss_gp1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_ispif_ahb_clk = {
+ .halt_reg = 0x3224,
+ .clkr = {
+ .enable_reg = 0x3224,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_ispif_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg0_clk = {
+ .halt_reg = 0x35a8,
+ .clkr = {
+ .enable_reg = 0x35a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg0_clk",
+ .parent_names = (const char *[]){
+ "jpeg0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg1_clk = {
+ .halt_reg = 0x35ac,
+ .clkr = {
+ .enable_reg = 0x35ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg1_clk",
+ .parent_names = (const char *[]){
+ "jpeg1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg2_clk = {
+ .halt_reg = 0x35b0,
+ .clkr = {
+ .enable_reg = 0x35b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg2_clk",
+ .parent_names = (const char *[]){
+ "jpeg2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg_ahb_clk = {
+ .halt_reg = 0x35b4,
+ .clkr = {
+ .enable_reg = 0x35b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_jpeg_jpeg_axi_clk = {
+ .halt_reg = 0x35b8,
+ .clkr = {
+ .enable_reg = 0x35b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_jpeg_jpeg_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk0_clk = {
+ .halt_reg = 0x3384,
+ .clkr = {
+ .enable_reg = 0x3384,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk0_clk",
+ .parent_names = (const char *[]){
+ "mclk0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk1_clk = {
+ .halt_reg = 0x33b4,
+ .clkr = {
+ .enable_reg = 0x33b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk1_clk",
+ .parent_names = (const char *[]){
+ "mclk1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk2_clk = {
+ .halt_reg = 0x33e4,
+ .clkr = {
+ .enable_reg = 0x33e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk2_clk",
+ .parent_names = (const char *[]){
+ "mclk2_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_mclk3_clk = {
+ .halt_reg = 0x3414,
+ .clkr = {
+ .enable_reg = 0x3414,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_mclk3_clk",
+ .parent_names = (const char *[]){
+ "mclk3_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_micro_ahb_clk = {
+ .halt_reg = 0x3494,
+ .clkr = {
+ .enable_reg = 0x3494,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_micro_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy0_csi0phytimer_clk = {
+ .halt_reg = 0x3024,
+ .clkr = {
+ .enable_reg = 0x3024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy0_csi0phytimer_clk",
+ .parent_names = (const char *[]){
+ "csi0phytimer_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy1_csi1phytimer_clk = {
+ .halt_reg = 0x3054,
+ .clkr = {
+ .enable_reg = 0x3054,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy1_csi1phytimer_clk",
+ .parent_names = (const char *[]){
+ "csi1phytimer_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_phy2_csi2phytimer_clk = {
+ .halt_reg = 0x3084,
+ .clkr = {
+ .enable_reg = 0x3084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_phy2_csi2phytimer_clk",
+ .parent_names = (const char *[]){
+ "csi2phytimer_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_top_ahb_clk = {
+ .halt_reg = 0x3484,
+ .clkr = {
+ .enable_reg = 0x3484,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_top_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_cpp_ahb_clk = {
+ .halt_reg = 0x36b4,
+ .clkr = {
+ .enable_reg = 0x36b4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_cpp_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_cpp_clk = {
+ .halt_reg = 0x36b0,
+ .clkr = {
+ .enable_reg = 0x36b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_cpp_clk",
+ .parent_names = (const char *[]){
+ "cpp_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe0_clk = {
+ .halt_reg = 0x36a8,
+ .clkr = {
+ .enable_reg = 0x36a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe0_clk",
+ .parent_names = (const char *[]){
+ "vfe0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe1_clk = {
+ .halt_reg = 0x36ac,
+ .clkr = {
+ .enable_reg = 0x36ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe1_clk",
+ .parent_names = (const char *[]){
+ "vfe1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe_ahb_clk = {
+ .halt_reg = 0x36b8,
+ .clkr = {
+ .enable_reg = 0x36b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch camss_vfe_vfe_axi_clk = {
+ .halt_reg = 0x36bc,
+ .clkr = {
+ .enable_reg = 0x36bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "camss_vfe_vfe_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_ahb_clk = {
+ .halt_reg = 0x2308,
+ .clkr = {
+ .enable_reg = 0x2308,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_axi_clk = {
+ .halt_reg = 0x2310,
+ .clkr = {
+ .enable_reg = 0x2310,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_byte0_clk = {
+ .halt_reg = 0x233c,
+ .clkr = {
+ .enable_reg = 0x233c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_byte0_clk",
+ .parent_names = (const char *[]){
+ "byte0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_byte1_clk = {
+ .halt_reg = 0x2340,
+ .clkr = {
+ .enable_reg = 0x2340,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_byte1_clk",
+ .parent_names = (const char *[]){
+ "byte1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_edpaux_clk = {
+ .halt_reg = 0x2334,
+ .clkr = {
+ .enable_reg = 0x2334,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_edpaux_clk",
+ .parent_names = (const char *[]){
+ "edpaux_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_edplink_clk = {
+ .halt_reg = 0x2330,
+ .clkr = {
+ .enable_reg = 0x2330,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_edplink_clk",
+ .parent_names = (const char *[]){
+ "edplink_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_edppixel_clk = {
+ .halt_reg = 0x232c,
+ .clkr = {
+ .enable_reg = 0x232c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_edppixel_clk",
+ .parent_names = (const char *[]){
+ "edppixel_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_esc0_clk = {
+ .halt_reg = 0x2344,
+ .clkr = {
+ .enable_reg = 0x2344,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_esc0_clk",
+ .parent_names = (const char *[]){
+ "esc0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_esc1_clk = {
+ .halt_reg = 0x2348,
+ .clkr = {
+ .enable_reg = 0x2348,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_esc1_clk",
+ .parent_names = (const char *[]){
+ "esc1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_extpclk_clk = {
+ .halt_reg = 0x2324,
+ .clkr = {
+ .enable_reg = 0x2324,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_extpclk_clk",
+ .parent_names = (const char *[]){
+ "extpclk_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_hdmi_ahb_clk = {
+ .halt_reg = 0x230c,
+ .clkr = {
+ .enable_reg = 0x230c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_hdmi_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_hdmi_clk = {
+ .halt_reg = 0x2338,
+ .clkr = {
+ .enable_reg = 0x2338,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_hdmi_clk",
+ .parent_names = (const char *[]){
+ "hdmi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_mdp_clk = {
+ .halt_reg = 0x231c,
+ .clkr = {
+ .enable_reg = 0x231c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_mdp_clk",
+ .parent_names = (const char *[]){
+ "mdp_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_mdp_lut_clk = {
+ .halt_reg = 0x2320,
+ .clkr = {
+ .enable_reg = 0x2320,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_mdp_lut_clk",
+ .parent_names = (const char *[]){
+ "mdp_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_pclk0_clk = {
+ .halt_reg = 0x2314,
+ .clkr = {
+ .enable_reg = 0x2314,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_pclk0_clk",
+ .parent_names = (const char *[]){
+ "pclk0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_pclk1_clk = {
+ .halt_reg = 0x2318,
+ .clkr = {
+ .enable_reg = 0x2318,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_pclk1_clk",
+ .parent_names = (const char *[]){
+ "pclk1_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mdss_vsync_clk = {
+ .halt_reg = 0x2328,
+ .clkr = {
+ .enable_reg = 0x2328,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mdss_vsync_clk",
+ .parent_names = (const char *[]){
+ "vsync_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_rbcpr_ahb_clk = {
+ .halt_reg = 0x4088,
+ .clkr = {
+ .enable_reg = 0x4088,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_rbcpr_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_rbcpr_clk = {
+ .halt_reg = 0x4084,
+ .clkr = {
+ .enable_reg = 0x4084,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_rbcpr_clk",
+ .parent_names = (const char *[]){
+ "rbcpr_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_ahb_clk = {
+ .halt_reg = 0x0230,
+ .clkr = {
+ .enable_reg = 0x0230,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_ahb_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_axi_clk = {
+ .halt_reg = 0x0210,
+ .clkr = {
+ .enable_reg = 0x0210,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_axi_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_csi0_clk = {
+ .halt_reg = 0x023c,
+ .clkr = {
+ .enable_reg = 0x023c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_csi0_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_csi0_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_gfx3d_clk = {
+ .halt_reg = 0x022c,
+ .clkr = {
+ .enable_reg = 0x022c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_gfx3d_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_gfx3d_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_jpeg0_clk = {
+ .halt_reg = 0x0204,
+ .clkr = {
+ .enable_reg = 0x0204,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_jpeg0_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_jpeg0_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_jpeg1_clk = {
+ .halt_reg = 0x0208,
+ .clkr = {
+ .enable_reg = 0x0208,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_jpeg1_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_jpeg1_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_jpeg2_clk = {
+ .halt_reg = 0x0224,
+ .clkr = {
+ .enable_reg = 0x0224,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_jpeg2_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_jpeg2_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_mdp_clk = {
+ .halt_reg = 0x020c,
+ .clkr = {
+ .enable_reg = 0x020c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_mdp_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_mdp_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_pclk0_clk = {
+ .halt_reg = 0x0234,
+ .clkr = {
+ .enable_reg = 0x0234,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_pclk0_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_pclk0_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_pclk1_clk = {
+ .halt_reg = 0x0228,
+ .clkr = {
+ .enable_reg = 0x0228,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_pclk1_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_pclk1_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_vcodec0_clk = {
+ .halt_reg = 0x0214,
+ .clkr = {
+ .enable_reg = 0x0214,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_vcodec0_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_vcodec0_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_vfe0_clk = {
+ .halt_reg = 0x0218,
+ .clkr = {
+ .enable_reg = 0x0218,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_vfe0_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_vfe0_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_vfe1_clk = {
+ .halt_reg = 0x021c,
+ .clkr = {
+ .enable_reg = 0x021c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_vfe1_clk",
+ .parent_names = (const char *[]){
+ "mmss_spdm_vfe1_div_clk",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_rm_axi_clk = {
+ .halt_reg = 0x0304,
+ .clkr = {
+ .enable_reg = 0x0304,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_rm_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_spdm_rm_ocmemnoc_clk = {
+ .halt_reg = 0x0308,
+ .clkr = {
+ .enable_reg = 0x0308,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_spdm_rm_ocmemnoc_clk",
+ .parent_names = (const char *[]){
+ "ocmemnoc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+
+static struct clk_branch mmss_misc_ahb_clk = {
+ .halt_reg = 0x502c,
+ .clkr = {
+ .enable_reg = 0x502c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_misc_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_mmssnoc_ahb_clk = {
+ .halt_reg = 0x5024,
+ .clkr = {
+ .enable_reg = 0x5024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_mmssnoc_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch mmss_mmssnoc_bto_ahb_clk = {
+ .halt_reg = 0x5028,
+ .clkr = {
+ .enable_reg = 0x5028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_mmssnoc_bto_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch mmss_mmssnoc_axi_clk = {
+ .halt_reg = 0x506c,
+ .clkr = {
+ .enable_reg = 0x506c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_mmssnoc_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch mmss_s0_axi_clk = {
+ .halt_reg = 0x5064,
+ .clkr = {
+ .enable_reg = 0x5064,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "mmss_s0_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch2_ops,
+ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ },
+ },
+};
+
+static struct clk_branch ocmemcx_ahb_clk = {
+ .halt_reg = 0x405c,
+ .clkr = {
+ .enable_reg = 0x405c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "ocmemcx_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch ocmemcx_ocmemnoc_clk = {
+ .halt_reg = 0x4058,
+ .clkr = {
+ .enable_reg = 0x4058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "ocmemcx_ocmemnoc_clk",
+ .parent_names = (const char *[]){
+ "ocmemnoc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxili_ocmemgx_clk = {
+ .halt_reg = 0x402c,
+ .clkr = {
+ .enable_reg = 0x402c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxili_ocmemgx_clk",
+ .parent_names = (const char *[]){
+ "gfx3d_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxili_gfx3d_clk = {
+ .halt_reg = 0x4028,
+ .clkr = {
+ .enable_reg = 0x4028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxili_gfx3d_clk",
+ .parent_names = (const char *[]){
+ "gfx3d_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxili_rbbmtimer_clk = {
+ .halt_reg = 0x40b0,
+ .clkr = {
+ .enable_reg = 0x40b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxili_rbbmtimer_clk",
+ .parent_names = (const char *[]){
+ "rbbmtimer_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch oxilicx_ahb_clk = {
+ .halt_reg = 0x403c,
+ .clkr = {
+ .enable_reg = 0x403c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "oxilicx_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_ahb_clk = {
+ .halt_reg = 0x1030,
+ .clkr = {
+ .enable_reg = 0x1030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_axi_clk = {
+ .halt_reg = 0x1034,
+ .clkr = {
+ .enable_reg = 0x1034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_core0_vcodec_clk = {
+ .halt_reg = 0x1048,
+ .clkr = {
+ .enable_reg = 0x1048,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_core0_vcodec_clk",
+ .parent_names = (const char *[]){
+ "vcodec0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_core1_vcodec_clk = {
+ .halt_reg = 0x104c,
+ .clkr = {
+ .enable_reg = 0x104c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_core1_vcodec_clk",
+ .parent_names = (const char *[]){
+ "vcodec0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_ocmemnoc_clk = {
+ .halt_reg = 0x1038,
+ .clkr = {
+ .enable_reg = 0x1038,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_ocmemnoc_clk",
+ .parent_names = (const char *[]){
+ "ocmemnoc_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch venus0_vcodec0_clk = {
+ .halt_reg = 0x1028,
+ .clkr = {
+ .enable_reg = 0x1028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "venus0_vcodec0_clk",
+ .parent_names = (const char *[]){
+ "vcodec0_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_ahb_clk = {
+ .halt_reg = 0x1430,
+ .clkr = {
+ .enable_reg = 0x1430,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_ahb_clk",
+ .parent_names = (const char *[]){
+ "mmss_ahb_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_axi_clk = {
+ .halt_reg = 0x143c,
+ .clkr = {
+ .enable_reg = 0x143c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_axi_clk",
+ .parent_names = (const char *[]){
+ "mmss_axi_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_bus_clk = {
+ .halt_reg = 0x1440,
+ .clkr = {
+ .enable_reg = 0x1440,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_bus_clk",
+ .parent_names = (const char *[]){
+ "vpu_bus_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_cxo_clk = {
+ .halt_reg = 0x1434,
+ .clkr = {
+ .enable_reg = 0x1434,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_cxo_clk",
+ .parent_names = (const char *[]){ "xo" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_maple_clk = {
+ .halt_reg = 0x142c,
+ .clkr = {
+ .enable_reg = 0x142c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_maple_clk",
+ .parent_names = (const char *[]){
+ "maple_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_sleep_clk = {
+ .halt_reg = 0x1438,
+ .clkr = {
+ .enable_reg = 0x1438,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_sleep_clk",
+ .parent_names = (const char *[]){
+ "sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch vpu_vdp_clk = {
+ .halt_reg = 0x1428,
+ .clkr = {
+ .enable_reg = 0x1428,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vpu_vdp_clk",
+ .parent_names = (const char *[]){
+ "vdp_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct pll_config mmpll1_config = {
+ .l = 60,
+ .m = 25,
+ .n = 32,
+ .vco_val = 0x0,
+ .vco_mask = 0x3 << 20,
+ .pre_div_val = 0x0,
+ .pre_div_mask = 0x7 << 12,
+ .post_div_val = 0x0,
+ .post_div_mask = 0x3 << 8,
+ .mn_ena_mask = BIT(24),
+ .main_output_mask = BIT(0),
+};
+
+static const struct pll_config mmpll3_config = {
+ .l = 48,
+ .m = 7,
+ .n = 16,
+ .vco_val = 0x0,
+ .vco_mask = 0x3 << 20,
+ .pre_div_val = 0x0,
+ .pre_div_mask = 0x7 << 12,
+ .post_div_val = 0x0,
+ .post_div_mask = 0x3 << 8,
+ .mn_ena_mask = BIT(24),
+ .main_output_mask = BIT(0),
+ .aux_output_mask = BIT(1),
+};
+
+static struct clk_regmap *mmcc_apq8084_clocks[] = {
+ [MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
+ [MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
+ [MMPLL0] = &mmpll0.clkr,
+ [MMPLL0_VOTE] = &mmpll0_vote,
+ [MMPLL1] = &mmpll1.clkr,
+ [MMPLL1_VOTE] = &mmpll1_vote,
+ [MMPLL2] = &mmpll2.clkr,
+ [MMPLL3] = &mmpll3.clkr,
+ [MMPLL4] = &mmpll4.clkr,
+ [CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+ [CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+ [CSI2_CLK_SRC] = &csi2_clk_src.clkr,
+ [CSI3_CLK_SRC] = &csi3_clk_src.clkr,
+ [VCODEC0_CLK_SRC] = &vcodec0_clk_src.clkr,
+ [VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+ [VFE1_CLK_SRC] = &vfe1_clk_src.clkr,
+ [MDP_CLK_SRC] = &mdp_clk_src.clkr,
+ [PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+ [PCLK1_CLK_SRC] = &pclk1_clk_src.clkr,
+ [OCMEMNOC_CLK_SRC] = &ocmemnoc_clk_src.clkr,
+ [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+ [JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+ [JPEG1_CLK_SRC] = &jpeg1_clk_src.clkr,
+ [JPEG2_CLK_SRC] = &jpeg2_clk_src.clkr,
+ [EDPPIXEL_CLK_SRC] = &edppixel_clk_src.clkr,
+ [EXTPCLK_CLK_SRC] = &extpclk_clk_src.clkr,
+ [VP_CLK_SRC] = &vp_clk_src.clkr,
+ [CCI_CLK_SRC] = &cci_clk_src.clkr,
+ [CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr,
+ [CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr,
+ [MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+ [MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+ [MCLK2_CLK_SRC] = &mclk2_clk_src.clkr,
+ [MCLK3_CLK_SRC] = &mclk3_clk_src.clkr,
+ [CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+ [CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+ [CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.clkr,
+ [CPP_CLK_SRC] = &cpp_clk_src.clkr,
+ [BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+ [BYTE1_CLK_SRC] = &byte1_clk_src.clkr,
+ [EDPAUX_CLK_SRC] = &edpaux_clk_src.clkr,
+ [EDPLINK_CLK_SRC] = &edplink_clk_src.clkr,
+ [ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+ [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
+ [HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
+ [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+ [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+ [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
+ [MAPLE_CLK_SRC] = &maple_clk_src.clkr,
+ [VDP_CLK_SRC] = &vdp_clk_src.clkr,
+ [VPU_BUS_CLK_SRC] = &vpu_bus_clk_src.clkr,
+ [MMSS_CXO_CLK] = &mmss_cxo_clk.clkr,
+ [MMSS_SLEEPCLK_CLK] = &mmss_sleepclk_clk.clkr,
+ [AVSYNC_AHB_CLK] = &avsync_ahb_clk.clkr,
+ [AVSYNC_EDPPIXEL_CLK] = &avsync_edppixel_clk.clkr,
+ [AVSYNC_EXTPCLK_CLK] = &avsync_extpclk_clk.clkr,
+ [AVSYNC_PCLK0_CLK] = &avsync_pclk0_clk.clkr,
+ [AVSYNC_PCLK1_CLK] = &avsync_pclk1_clk.clkr,
+ [AVSYNC_VP_CLK] = &avsync_vp_clk.clkr,
+ [CAMSS_AHB_CLK] = &camss_ahb_clk.clkr,
+ [CAMSS_CCI_CCI_AHB_CLK] = &camss_cci_cci_ahb_clk.clkr,
+ [CAMSS_CCI_CCI_CLK] = &camss_cci_cci_clk.clkr,
+ [CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.clkr,
+ [CAMSS_CSI0_CLK] = &camss_csi0_clk.clkr,
+ [CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.clkr,
+ [CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.clkr,
+ [CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.clkr,
+ [CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.clkr,
+ [CAMSS_CSI1_CLK] = &camss_csi1_clk.clkr,
+ [CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.clkr,
+ [CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.clkr,
+ [CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.clkr,
+ [CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.clkr,
+ [CAMSS_CSI2_CLK] = &camss_csi2_clk.clkr,
+ [CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.clkr,
+ [CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.clkr,
+ [CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.clkr,
+ [CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.clkr,
+ [CAMSS_CSI3_CLK] = &camss_csi3_clk.clkr,
+ [CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.clkr,
+ [CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.clkr,
+ [CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.clkr,
+ [CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.clkr,
+ [CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.clkr,
+ [CAMSS_GP0_CLK] = &camss_gp0_clk.clkr,
+ [CAMSS_GP1_CLK] = &camss_gp1_clk.clkr,
+ [CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.clkr,
+ [CAMSS_JPEG_JPEG0_CLK] = &camss_jpeg_jpeg0_clk.clkr,
+ [CAMSS_JPEG_JPEG1_CLK] = &camss_jpeg_jpeg1_clk.clkr,
+ [CAMSS_JPEG_JPEG2_CLK] = &camss_jpeg_jpeg2_clk.clkr,
+ [CAMSS_JPEG_JPEG_AHB_CLK] = &camss_jpeg_jpeg_ahb_clk.clkr,
+ [CAMSS_JPEG_JPEG_AXI_CLK] = &camss_jpeg_jpeg_axi_clk.clkr,
+ [CAMSS_MCLK0_CLK] = &camss_mclk0_clk.clkr,
+ [CAMSS_MCLK1_CLK] = &camss_mclk1_clk.clkr,
+ [CAMSS_MCLK2_CLK] = &camss_mclk2_clk.clkr,
+ [CAMSS_MCLK3_CLK] = &camss_mclk3_clk.clkr,
+ [CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.clkr,
+ [CAMSS_PHY0_CSI0PHYTIMER_CLK] = &camss_phy0_csi0phytimer_clk.clkr,
+ [CAMSS_PHY1_CSI1PHYTIMER_CLK] = &camss_phy1_csi1phytimer_clk.clkr,
+ [CAMSS_PHY2_CSI2PHYTIMER_CLK] = &camss_phy2_csi2phytimer_clk.clkr,
+ [CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.clkr,
+ [CAMSS_VFE_CPP_AHB_CLK] = &camss_vfe_cpp_ahb_clk.clkr,
+ [CAMSS_VFE_CPP_CLK] = &camss_vfe_cpp_clk.clkr,
+ [CAMSS_VFE_VFE0_CLK] = &camss_vfe_vfe0_clk.clkr,
+ [CAMSS_VFE_VFE1_CLK] = &camss_vfe_vfe1_clk.clkr,
+ [CAMSS_VFE_VFE_AHB_CLK] = &camss_vfe_vfe_ahb_clk.clkr,
+ [CAMSS_VFE_VFE_AXI_CLK] = &camss_vfe_vfe_axi_clk.clkr,
+ [MDSS_AHB_CLK] = &mdss_ahb_clk.clkr,
+ [MDSS_AXI_CLK] = &mdss_axi_clk.clkr,
+ [MDSS_BYTE0_CLK] = &mdss_byte0_clk.clkr,
+ [MDSS_BYTE1_CLK] = &mdss_byte1_clk.clkr,
+ [MDSS_EDPAUX_CLK] = &mdss_edpaux_clk.clkr,
+ [MDSS_EDPLINK_CLK] = &mdss_edplink_clk.clkr,
+ [MDSS_EDPPIXEL_CLK] = &mdss_edppixel_clk.clkr,
+ [MDSS_ESC0_CLK] = &mdss_esc0_clk.clkr,
+ [MDSS_ESC1_CLK] = &mdss_esc1_clk.clkr,
+ [MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.clkr,
+ [MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.clkr,
+ [MDSS_HDMI_CLK] = &mdss_hdmi_clk.clkr,
+ [MDSS_MDP_CLK] = &mdss_mdp_clk.clkr,
+ [MDSS_MDP_LUT_CLK] = &mdss_mdp_lut_clk.clkr,
+ [MDSS_PCLK0_CLK] = &mdss_pclk0_clk.clkr,
+ [MDSS_PCLK1_CLK] = &mdss_pclk1_clk.clkr,
+ [MDSS_VSYNC_CLK] = &mdss_vsync_clk.clkr,
+ [MMSS_RBCPR_AHB_CLK] = &mmss_rbcpr_ahb_clk.clkr,
+ [MMSS_RBCPR_CLK] = &mmss_rbcpr_clk.clkr,
+ [MMSS_SPDM_AHB_CLK] = &mmss_spdm_ahb_clk.clkr,
+ [MMSS_SPDM_AXI_CLK] = &mmss_spdm_axi_clk.clkr,
+ [MMSS_SPDM_CSI0_CLK] = &mmss_spdm_csi0_clk.clkr,
+ [MMSS_SPDM_GFX3D_CLK] = &mmss_spdm_gfx3d_clk.clkr,
+ [MMSS_SPDM_JPEG0_CLK] = &mmss_spdm_jpeg0_clk.clkr,
+ [MMSS_SPDM_JPEG1_CLK] = &mmss_spdm_jpeg1_clk.clkr,
+ [MMSS_SPDM_JPEG2_CLK] = &mmss_spdm_jpeg2_clk.clkr,
+ [MMSS_SPDM_MDP_CLK] = &mmss_spdm_mdp_clk.clkr,
+ [MMSS_SPDM_PCLK0_CLK] = &mmss_spdm_pclk0_clk.clkr,
+ [MMSS_SPDM_PCLK1_CLK] = &mmss_spdm_pclk1_clk.clkr,
+ [MMSS_SPDM_VCODEC0_CLK] = &mmss_spdm_vcodec0_clk.clkr,
+ [MMSS_SPDM_VFE0_CLK] = &mmss_spdm_vfe0_clk.clkr,
+ [MMSS_SPDM_VFE1_CLK] = &mmss_spdm_vfe1_clk.clkr,
+ [MMSS_SPDM_RM_AXI_CLK] = &mmss_spdm_rm_axi_clk.clkr,
+ [MMSS_SPDM_RM_OCMEMNOC_CLK] = &mmss_spdm_rm_ocmemnoc_clk.clkr,
+ [MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr,
+ [MMSS_MMSSNOC_AHB_CLK] = &mmss_mmssnoc_ahb_clk.clkr,
+ [MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr,
+ [MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr,
+ [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr,
+ [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr,
+ [OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr,
+ [OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.clkr,
+ [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr,
+ [OXILI_RBBMTIMER_CLK] = &oxili_rbbmtimer_clk.clkr,
+ [OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr,
+ [VENUS0_AHB_CLK] = &venus0_ahb_clk.clkr,
+ [VENUS0_AXI_CLK] = &venus0_axi_clk.clkr,
+ [VENUS0_CORE0_VCODEC_CLK] = &venus0_core0_vcodec_clk.clkr,
+ [VENUS0_CORE1_VCODEC_CLK] = &venus0_core1_vcodec_clk.clkr,
+ [VENUS0_OCMEMNOC_CLK] = &venus0_ocmemnoc_clk.clkr,
+ [VENUS0_VCODEC0_CLK] = &venus0_vcodec0_clk.clkr,
+ [VPU_AHB_CLK] = &vpu_ahb_clk.clkr,
+ [VPU_AXI_CLK] = &vpu_axi_clk.clkr,
+ [VPU_BUS_CLK] = &vpu_bus_clk.clkr,
+ [VPU_CXO_CLK] = &vpu_cxo_clk.clkr,
+ [VPU_MAPLE_CLK] = &vpu_maple_clk.clkr,
+ [VPU_SLEEP_CLK] = &vpu_sleep_clk.clkr,
+ [VPU_VDP_CLK] = &vpu_vdp_clk.clkr,
+};
+
+static const struct qcom_reset_map mmcc_apq8084_resets[] = {
+ [MMSS_SPDM_RESET] = { 0x0200 },
+ [MMSS_SPDM_RM_RESET] = { 0x0300 },
+ [VENUS0_RESET] = { 0x1020 },
+ [VPU_RESET] = { 0x1400 },
+ [MDSS_RESET] = { 0x2300 },
+ [AVSYNC_RESET] = { 0x2400 },
+ [CAMSS_PHY0_RESET] = { 0x3020 },
+ [CAMSS_PHY1_RESET] = { 0x3050 },
+ [CAMSS_PHY2_RESET] = { 0x3080 },
+ [CAMSS_CSI0_RESET] = { 0x30b0 },
+ [CAMSS_CSI0PHY_RESET] = { 0x30c0 },
+ [CAMSS_CSI0RDI_RESET] = { 0x30d0 },
+ [CAMSS_CSI0PIX_RESET] = { 0x30e0 },
+ [CAMSS_CSI1_RESET] = { 0x3120 },
+ [CAMSS_CSI1PHY_RESET] = { 0x3130 },
+ [CAMSS_CSI1RDI_RESET] = { 0x3140 },
+ [CAMSS_CSI1PIX_RESET] = { 0x3150 },
+ [CAMSS_CSI2_RESET] = { 0x3180 },
+ [CAMSS_CSI2PHY_RESET] = { 0x3190 },
+ [CAMSS_CSI2RDI_RESET] = { 0x31a0 },
+ [CAMSS_CSI2PIX_RESET] = { 0x31b0 },
+ [CAMSS_CSI3_RESET] = { 0x31e0 },
+ [CAMSS_CSI3PHY_RESET] = { 0x31f0 },
+ [CAMSS_CSI3RDI_RESET] = { 0x3200 },
+ [CAMSS_CSI3PIX_RESET] = { 0x3210 },
+ [CAMSS_ISPIF_RESET] = { 0x3220 },
+ [CAMSS_CCI_RESET] = { 0x3340 },
+ [CAMSS_MCLK0_RESET] = { 0x3380 },
+ [CAMSS_MCLK1_RESET] = { 0x33b0 },
+ [CAMSS_MCLK2_RESET] = { 0x33e0 },
+ [CAMSS_MCLK3_RESET] = { 0x3410 },
+ [CAMSS_GP0_RESET] = { 0x3440 },
+ [CAMSS_GP1_RESET] = { 0x3470 },
+ [CAMSS_TOP_RESET] = { 0x3480 },
+ [CAMSS_AHB_RESET] = { 0x3488 },
+ [CAMSS_MICRO_RESET] = { 0x3490 },
+ [CAMSS_JPEG_RESET] = { 0x35a0 },
+ [CAMSS_VFE_RESET] = { 0x36a0 },
+ [CAMSS_CSI_VFE0_RESET] = { 0x3700 },
+ [CAMSS_CSI_VFE1_RESET] = { 0x3710 },
+ [OXILI_RESET] = { 0x4020 },
+ [OXILICX_RESET] = { 0x4030 },
+ [OCMEMCX_RESET] = { 0x4050 },
+ [MMSS_RBCRP_RESET] = { 0x4080 },
+ [MMSSNOCAHB_RESET] = { 0x5020 },
+ [MMSSNOCAXI_RESET] = { 0x5060 },
+};
+
+static const struct regmap_config mmcc_apq8084_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5104,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc mmcc_apq8084_desc = {
+ .config = &mmcc_apq8084_regmap_config,
+ .clks = mmcc_apq8084_clocks,
+ .num_clks = ARRAY_SIZE(mmcc_apq8084_clocks),
+ .resets = mmcc_apq8084_resets,
+ .num_resets = ARRAY_SIZE(mmcc_apq8084_resets),
+};
+
+static const struct of_device_id mmcc_apq8084_match_table[] = {
+ { .compatible = "qcom,mmcc-apq8084" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mmcc_apq8084_match_table);
+
+static int mmcc_apq8084_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct regmap *regmap;
+
+ ret = qcom_cc_probe(pdev, &mmcc_apq8084_desc);
+ if (ret)
+ return ret;
+
+ regmap = dev_get_regmap(&pdev->dev, NULL);
+ clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
+ clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
+
+ return 0;
+}
+
+static int mmcc_apq8084_remove(struct platform_device *pdev)
+{
+ qcom_cc_remove(pdev);
+ return 0;
+}
+
+static struct platform_driver mmcc_apq8084_driver = {
+ .probe = mmcc_apq8084_probe,
+ .remove = mmcc_apq8084_remove,
+ .driver = {
+ .name = "mmcc-apq8084",
+ .owner = THIS_MODULE,
+ .of_match_table = mmcc_apq8084_match_table,
+ },
+};
+module_platform_driver(mmcc_apq8084_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC APQ8084 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-apq8084");
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
index 4c449b3170f6..2e80a219b8ea 100644
--- a/drivers/clk/qcom/mmcc-msm8960.c
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -37,6 +37,9 @@
#define P_PLL8 1
#define P_PLL2 2
#define P_PLL3 3
+#define P_PLL15 3
+
+#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
static u8 mmcc_pxo_pll8_pll2_map[] = {
[P_PXO] = 0,
@@ -57,10 +60,24 @@ static u8 mmcc_pxo_pll8_pll2_pll3_map[] = {
[P_PLL3] = 3,
};
-static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+static const char *mmcc_pxo_pll8_pll2_pll15[] = {
"pxo",
+ "pll8_vote",
"pll2",
+ "pll15",
+};
+
+static u8 mmcc_pxo_pll8_pll2_pll15_map[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 2,
+ [P_PLL2] = 1,
+ [P_PLL15] = 3,
+};
+
+static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+ "pxo",
"pll8_vote",
+ "pll2",
"pll3",
};
@@ -80,6 +97,36 @@ static struct clk_pll pll2 = {
},
};
+static struct clk_pll pll15 = {
+ .l_reg = 0x33c,
+ .m_reg = 0x340,
+ .n_reg = 0x344,
+ .config_reg = 0x348,
+ .mode_reg = 0x338,
+ .status_reg = 0x350,
+ .status_bit = 16,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "pll15",
+ .parent_names = (const char *[]){ "pxo" },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static const struct pll_config pll15_config = {
+ .l = 33,
+ .m = 1,
+ .n = 3,
+ .vco_val = 0x2 << 16,
+ .vco_mask = 0x3 << 16,
+ .pre_div_val = 0x0,
+ .pre_div_mask = BIT(19),
+ .post_div_val = 0x0,
+ .post_div_mask = 0x3 << 20,
+ .mn_ena_mask = BIT(22),
+ .main_output_mask = BIT(23),
+};
+
static struct freq_tbl clk_tbl_cam[] = {
{ 6000000, P_PLL8, 4, 1, 16 },
{ 8000000, P_PLL8, 4, 1, 12 },
@@ -710,18 +757,18 @@ static struct clk_branch csiphy2_timer_clk = {
};
static struct freq_tbl clk_tbl_gfx2d[] = {
- { 27000000, P_PXO, 1, 0 },
- { 48000000, P_PLL8, 1, 8 },
- { 54857000, P_PLL8, 1, 7 },
- { 64000000, P_PLL8, 1, 6 },
- { 76800000, P_PLL8, 1, 5 },
- { 96000000, P_PLL8, 1, 4 },
- { 128000000, P_PLL8, 1, 3 },
- { 145455000, P_PLL2, 2, 11 },
- { 160000000, P_PLL2, 1, 5 },
- { 177778000, P_PLL2, 2, 9 },
- { 200000000, P_PLL2, 1, 4 },
- { 228571000, P_PLL2, 2, 7 },
+ F_MN( 27000000, P_PXO, 1, 0),
+ F_MN( 48000000, P_PLL8, 1, 8),
+ F_MN( 54857000, P_PLL8, 1, 7),
+ F_MN( 64000000, P_PLL8, 1, 6),
+ F_MN( 76800000, P_PLL8, 1, 5),
+ F_MN( 96000000, P_PLL8, 1, 4),
+ F_MN(128000000, P_PLL8, 1, 3),
+ F_MN(145455000, P_PLL2, 2, 11),
+ F_MN(160000000, P_PLL2, 1, 5),
+ F_MN(177778000, P_PLL2, 2, 9),
+ F_MN(200000000, P_PLL2, 1, 4),
+ F_MN(228571000, P_PLL2, 2, 7),
{ }
};
@@ -842,22 +889,43 @@ static struct clk_branch gfx2d1_clk = {
};
static struct freq_tbl clk_tbl_gfx3d[] = {
- { 27000000, P_PXO, 1, 0 },
- { 48000000, P_PLL8, 1, 8 },
- { 54857000, P_PLL8, 1, 7 },
- { 64000000, P_PLL8, 1, 6 },
- { 76800000, P_PLL8, 1, 5 },
- { 96000000, P_PLL8, 1, 4 },
- { 128000000, P_PLL8, 1, 3 },
- { 145455000, P_PLL2, 2, 11 },
- { 160000000, P_PLL2, 1, 5 },
- { 177778000, P_PLL2, 2, 9 },
- { 200000000, P_PLL2, 1, 4 },
- { 228571000, P_PLL2, 2, 7 },
- { 266667000, P_PLL2, 1, 3 },
- { 300000000, P_PLL3, 1, 4 },
- { 320000000, P_PLL2, 2, 5 },
- { 400000000, P_PLL2, 1, 2 },
+ F_MN( 27000000, P_PXO, 1, 0),
+ F_MN( 48000000, P_PLL8, 1, 8),
+ F_MN( 54857000, P_PLL8, 1, 7),
+ F_MN( 64000000, P_PLL8, 1, 6),
+ F_MN( 76800000, P_PLL8, 1, 5),
+ F_MN( 96000000, P_PLL8, 1, 4),
+ F_MN(128000000, P_PLL8, 1, 3),
+ F_MN(145455000, P_PLL2, 2, 11),
+ F_MN(160000000, P_PLL2, 1, 5),
+ F_MN(177778000, P_PLL2, 2, 9),
+ F_MN(200000000, P_PLL2, 1, 4),
+ F_MN(228571000, P_PLL2, 2, 7),
+ F_MN(266667000, P_PLL2, 1, 3),
+ F_MN(300000000, P_PLL3, 1, 4),
+ F_MN(320000000, P_PLL2, 2, 5),
+ F_MN(400000000, P_PLL2, 1, 2),
+ { }
+};
+
+static struct freq_tbl clk_tbl_gfx3d_8064[] = {
+ F_MN( 27000000, P_PXO, 0, 0),
+ F_MN( 48000000, P_PLL8, 1, 8),
+ F_MN( 54857000, P_PLL8, 1, 7),
+ F_MN( 64000000, P_PLL8, 1, 6),
+ F_MN( 76800000, P_PLL8, 1, 5),
+ F_MN( 96000000, P_PLL8, 1, 4),
+ F_MN(128000000, P_PLL8, 1, 3),
+ F_MN(145455000, P_PLL2, 2, 11),
+ F_MN(160000000, P_PLL2, 1, 5),
+ F_MN(177778000, P_PLL2, 2, 9),
+ F_MN(192000000, P_PLL8, 1, 2),
+ F_MN(200000000, P_PLL2, 1, 4),
+ F_MN(228571000, P_PLL2, 2, 7),
+ F_MN(266667000, P_PLL2, 1, 3),
+ F_MN(320000000, P_PLL2, 2, 5),
+ F_MN(400000000, P_PLL2, 1, 2),
+ F_MN(450000000, P_PLL15, 1, 2),
{ }
};
@@ -897,12 +965,19 @@ static struct clk_dyn_rcg gfx3d_src = {
.hw.init = &(struct clk_init_data){
.name = "gfx3d_src",
.parent_names = mmcc_pxo_pll8_pll2_pll3,
- .num_parents = 3,
+ .num_parents = 4,
.ops = &clk_dyn_rcg_ops,
},
},
};
+static const struct clk_init_data gfx3d_8064_init = {
+ .name = "gfx3d_src",
+ .parent_names = mmcc_pxo_pll8_pll2_pll15,
+ .num_parents = 4,
+ .ops = &clk_dyn_rcg_ops,
+};
+
static struct clk_branch gfx3d_clk = {
.halt_reg = 0x01c8,
.halt_bit = 4,
@@ -919,6 +994,91 @@ static struct clk_branch gfx3d_clk = {
},
};
+static struct freq_tbl clk_tbl_vcap[] = {
+ F_MN( 27000000, P_PXO, 0, 0),
+ F_MN( 54860000, P_PLL8, 1, 7),
+ F_MN( 64000000, P_PLL8, 1, 6),
+ F_MN( 76800000, P_PLL8, 1, 5),
+ F_MN(128000000, P_PLL8, 1, 3),
+ F_MN(160000000, P_PLL2, 1, 5),
+ F_MN(200000000, P_PLL2, 1, 4),
+ { }
+};
+
+static struct clk_dyn_rcg vcap_src = {
+ .ns_reg = 0x021c,
+ .md_reg[0] = 0x01ec,
+ .md_reg[1] = 0x0218,
+ .mn[0] = {
+ .mnctr_en_bit = 8,
+ .mnctr_reset_bit = 23,
+ .mnctr_mode_shift = 9,
+ .n_val_shift = 18,
+ .m_val_shift = 4,
+ .width = 4,
+ },
+ .mn[1] = {
+ .mnctr_en_bit = 5,
+ .mnctr_reset_bit = 22,
+ .mnctr_mode_shift = 6,
+ .n_val_shift = 14,
+ .m_val_shift = 4,
+ .width = 4,
+ },
+ .s[0] = {
+ .src_sel_shift = 3,
+ .parent_map = mmcc_pxo_pll8_pll2_map,
+ },
+ .s[1] = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_pll8_pll2_map,
+ },
+ .mux_sel_bit = 11,
+ .freq_tbl = clk_tbl_vcap,
+ .clkr = {
+ .enable_reg = 0x0178,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "vcap_src",
+ .parent_names = mmcc_pxo_pll8_pll2,
+ .num_parents = 3,
+ .ops = &clk_dyn_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch vcap_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 15,
+ .clkr = {
+ .enable_reg = 0x0178,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "vcap_clk",
+ .parent_names = (const char *[]){ "vcap_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch vcap_npl_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 25,
+ .clkr = {
+ .enable_reg = 0x0178,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "vcap_npl_clk",
+ .parent_names = (const char *[]){ "vcap_src" },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
static struct freq_tbl clk_tbl_ijpeg[] = {
{ 27000000, P_PXO, 1, 0, 0 },
{ 36570000, P_PLL8, 1, 2, 21 },
@@ -995,7 +1155,7 @@ static struct clk_rcg jpegd_src = {
.ns_reg = 0x00ac,
.p = {
.pre_div_shift = 12,
- .pre_div_width = 2,
+ .pre_div_width = 4,
},
.s = {
.src_sel_shift = 0,
@@ -1115,7 +1275,7 @@ static struct clk_branch mdp_lut_clk = {
.enable_reg = 0x016c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
- .parent_names = (const char *[]){ "mdp_clk" },
+ .parent_names = (const char *[]){ "mdp_src" },
.num_parents = 1,
.name = "mdp_lut_clk",
.ops = &clk_branch_ops,
@@ -1218,12 +1378,7 @@ static const char *mmcc_pxo_hdmi[] = {
};
static struct freq_tbl clk_tbl_tv[] = {
- { 25200000, P_HDMI_PLL, 1, 0, 0 },
- { 27000000, P_HDMI_PLL, 1, 0, 0 },
- { 27030000, P_HDMI_PLL, 1, 0, 0 },
- { 74250000, P_HDMI_PLL, 1, 0, 0 },
- { 108000000, P_HDMI_PLL, 1, 0, 0 },
- { 148500000, P_HDMI_PLL, 1, 0, 0 },
+ { .src = P_HDMI_PLL, .pre_div = 1 },
{ }
};
@@ -1254,7 +1409,7 @@ static struct clk_rcg tv_src = {
.name = "tv_src",
.parent_names = mmcc_pxo_hdmi,
.num_parents = 2,
- .ops = &clk_rcg_ops,
+ .ops = &clk_rcg_bypass_ops,
.flags = CLK_SET_RATE_PARENT,
},
},
@@ -1326,6 +1481,38 @@ static struct clk_branch hdmi_tv_clk = {
},
};
+static struct clk_branch rgb_tv_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 27,
+ .clkr = {
+ .enable_reg = 0x0124,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .parent_names = tv_src_name,
+ .num_parents = 1,
+ .name = "rgb_tv_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
+static struct clk_branch npl_tv_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 26,
+ .clkr = {
+ .enable_reg = 0x0124,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .parent_names = tv_src_name,
+ .num_parents = 1,
+ .name = "npl_tv_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+ },
+};
+
static struct clk_branch hdmi_app_clk = {
.halt_reg = 0x01cc,
.halt_bit = 25,
@@ -1342,15 +1529,15 @@ static struct clk_branch hdmi_app_clk = {
};
static struct freq_tbl clk_tbl_vcodec[] = {
- { 27000000, P_PXO, 1, 0 },
- { 32000000, P_PLL8, 1, 12 },
- { 48000000, P_PLL8, 1, 8 },
- { 54860000, P_PLL8, 1, 7 },
- { 96000000, P_PLL8, 1, 4 },
- { 133330000, P_PLL2, 1, 6 },
- { 200000000, P_PLL2, 1, 4 },
- { 228570000, P_PLL2, 2, 7 },
- { 266670000, P_PLL2, 1, 3 },
+ F_MN( 27000000, P_PXO, 1, 0),
+ F_MN( 32000000, P_PLL8, 1, 12),
+ F_MN( 48000000, P_PLL8, 1, 8),
+ F_MN( 54860000, P_PLL8, 1, 7),
+ F_MN( 96000000, P_PLL8, 1, 4),
+ F_MN(133330000, P_PLL2, 1, 6),
+ F_MN(200000000, P_PLL2, 1, 4),
+ F_MN(228570000, P_PLL2, 2, 7),
+ F_MN(266670000, P_PLL2, 1, 3),
{ }
};
@@ -1701,6 +1888,22 @@ static struct clk_branch rot_axi_clk = {
},
};
+static struct clk_branch vcap_axi_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 20,
+ .hwcg_reg = 0x0244,
+ .hwcg_bit = 11,
+ .clkr = {
+ .enable_reg = 0x0244,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "vcap_axi_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
static struct clk_branch vpe_axi_clk = {
.hwcg_reg = 0x0020,
.hwcg_bit = 27,
@@ -2003,6 +2206,20 @@ static struct clk_branch tv_enc_ahb_clk = {
},
};
+static struct clk_branch vcap_ahb_clk = {
+ .halt_reg = 0x0240,
+ .halt_bit = 23,
+ .clkr = {
+ .enable_reg = 0x0248,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "vcap_ahb_clk",
+ .ops = &clk_branch_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ },
+};
+
static struct clk_branch vcodec_ahb_clk = {
.hwcg_reg = 0x0038,
.hwcg_bit = 26,
@@ -2215,6 +2432,175 @@ static const struct qcom_reset_map mmcc_msm8960_resets[] = {
[CSI_RDI2_RESET] = { 0x0214 },
};
+static struct clk_regmap *mmcc_apq8064_clks[] = {
+ [AMP_AHB_CLK] = &amp_ahb_clk.clkr,
+ [DSI2_S_AHB_CLK] = &dsi2_s_ahb_clk.clkr,
+ [JPEGD_AHB_CLK] = &jpegd_ahb_clk.clkr,
+ [DSI_S_AHB_CLK] = &dsi_s_ahb_clk.clkr,
+ [DSI2_M_AHB_CLK] = &dsi2_m_ahb_clk.clkr,
+ [VPE_AHB_CLK] = &vpe_ahb_clk.clkr,
+ [SMMU_AHB_CLK] = &smmu_ahb_clk.clkr,
+ [HDMI_M_AHB_CLK] = &hdmi_m_ahb_clk.clkr,
+ [VFE_AHB_CLK] = &vfe_ahb_clk.clkr,
+ [ROT_AHB_CLK] = &rot_ahb_clk.clkr,
+ [VCODEC_AHB_CLK] = &vcodec_ahb_clk.clkr,
+ [MDP_AHB_CLK] = &mdp_ahb_clk.clkr,
+ [DSI_M_AHB_CLK] = &dsi_m_ahb_clk.clkr,
+ [CSI_AHB_CLK] = &csi_ahb_clk.clkr,
+ [MMSS_IMEM_AHB_CLK] = &mmss_imem_ahb_clk.clkr,
+ [IJPEG_AHB_CLK] = &ijpeg_ahb_clk.clkr,
+ [HDMI_S_AHB_CLK] = &hdmi_s_ahb_clk.clkr,
+ [GFX3D_AHB_CLK] = &gfx3d_ahb_clk.clkr,
+ [JPEGD_AXI_CLK] = &jpegd_axi_clk.clkr,
+ [GMEM_AXI_CLK] = &gmem_axi_clk.clkr,
+ [MDP_AXI_CLK] = &mdp_axi_clk.clkr,
+ [MMSS_IMEM_AXI_CLK] = &mmss_imem_axi_clk.clkr,
+ [IJPEG_AXI_CLK] = &ijpeg_axi_clk.clkr,
+ [GFX3D_AXI_CLK] = &gfx3d_axi_clk.clkr,
+ [VCODEC_AXI_CLK] = &vcodec_axi_clk.clkr,
+ [VFE_AXI_CLK] = &vfe_axi_clk.clkr,
+ [VPE_AXI_CLK] = &vpe_axi_clk.clkr,
+ [ROT_AXI_CLK] = &rot_axi_clk.clkr,
+ [VCODEC_AXI_A_CLK] = &vcodec_axi_a_clk.clkr,
+ [VCODEC_AXI_B_CLK] = &vcodec_axi_b_clk.clkr,
+ [CSI0_SRC] = &csi0_src.clkr,
+ [CSI0_CLK] = &csi0_clk.clkr,
+ [CSI0_PHY_CLK] = &csi0_phy_clk.clkr,
+ [CSI1_SRC] = &csi1_src.clkr,
+ [CSI1_CLK] = &csi1_clk.clkr,
+ [CSI1_PHY_CLK] = &csi1_phy_clk.clkr,
+ [CSI2_SRC] = &csi2_src.clkr,
+ [CSI2_CLK] = &csi2_clk.clkr,
+ [CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
+ [CSI_PIX_CLK] = &csi_pix_clk.clkr,
+ [CSI_RDI_CLK] = &csi_rdi_clk.clkr,
+ [MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
+ [HDMI_APP_CLK] = &hdmi_app_clk.clkr,
+ [CSI_PIX1_CLK] = &csi_pix1_clk.clkr,
+ [CSI_RDI2_CLK] = &csi_rdi2_clk.clkr,
+ [CSI_RDI1_CLK] = &csi_rdi1_clk.clkr,
+ [GFX3D_SRC] = &gfx3d_src.clkr,
+ [GFX3D_CLK] = &gfx3d_clk.clkr,
+ [IJPEG_SRC] = &ijpeg_src.clkr,
+ [IJPEG_CLK] = &ijpeg_clk.clkr,
+ [JPEGD_SRC] = &jpegd_src.clkr,
+ [JPEGD_CLK] = &jpegd_clk.clkr,
+ [MDP_SRC] = &mdp_src.clkr,
+ [MDP_CLK] = &mdp_clk.clkr,
+ [MDP_LUT_CLK] = &mdp_lut_clk.clkr,
+ [ROT_SRC] = &rot_src.clkr,
+ [ROT_CLK] = &rot_clk.clkr,
+ [TV_DAC_CLK] = &tv_dac_clk.clkr,
+ [HDMI_TV_CLK] = &hdmi_tv_clk.clkr,
+ [MDP_TV_CLK] = &mdp_tv_clk.clkr,
+ [TV_SRC] = &tv_src.clkr,
+ [VCODEC_SRC] = &vcodec_src.clkr,
+ [VCODEC_CLK] = &vcodec_clk.clkr,
+ [VFE_SRC] = &vfe_src.clkr,
+ [VFE_CLK] = &vfe_clk.clkr,
+ [VFE_CSI_CLK] = &vfe_csi_clk.clkr,
+ [VPE_SRC] = &vpe_src.clkr,
+ [VPE_CLK] = &vpe_clk.clkr,
+ [CAMCLK0_SRC] = &camclk0_src.clkr,
+ [CAMCLK0_CLK] = &camclk0_clk.clkr,
+ [CAMCLK1_SRC] = &camclk1_src.clkr,
+ [CAMCLK1_CLK] = &camclk1_clk.clkr,
+ [CAMCLK2_SRC] = &camclk2_src.clkr,
+ [CAMCLK2_CLK] = &camclk2_clk.clkr,
+ [CSIPHYTIMER_SRC] = &csiphytimer_src.clkr,
+ [CSIPHY2_TIMER_CLK] = &csiphy2_timer_clk.clkr,
+ [CSIPHY1_TIMER_CLK] = &csiphy1_timer_clk.clkr,
+ [CSIPHY0_TIMER_CLK] = &csiphy0_timer_clk.clkr,
+ [PLL2] = &pll2.clkr,
+ [RGB_TV_CLK] = &rgb_tv_clk.clkr,
+ [NPL_TV_CLK] = &npl_tv_clk.clkr,
+ [VCAP_AHB_CLK] = &vcap_ahb_clk.clkr,
+ [VCAP_AXI_CLK] = &vcap_axi_clk.clkr,
+ [VCAP_SRC] = &vcap_src.clkr,
+ [VCAP_CLK] = &vcap_clk.clkr,
+ [VCAP_NPL_CLK] = &vcap_npl_clk.clkr,
+ [PLL15] = &pll15.clkr,
+};
+
+static const struct qcom_reset_map mmcc_apq8064_resets[] = {
+ [GFX3D_AXI_RESET] = { 0x0208, 17 },
+ [VCAP_AXI_RESET] = { 0x0208, 16 },
+ [VPE_AXI_RESET] = { 0x0208, 15 },
+ [IJPEG_AXI_RESET] = { 0x0208, 14 },
+ [MPD_AXI_RESET] = { 0x0208, 13 },
+ [VFE_AXI_RESET] = { 0x0208, 9 },
+ [SP_AXI_RESET] = { 0x0208, 8 },
+ [VCODEC_AXI_RESET] = { 0x0208, 7 },
+ [ROT_AXI_RESET] = { 0x0208, 6 },
+ [VCODEC_AXI_A_RESET] = { 0x0208, 5 },
+ [VCODEC_AXI_B_RESET] = { 0x0208, 4 },
+ [FAB_S3_AXI_RESET] = { 0x0208, 3 },
+ [FAB_S2_AXI_RESET] = { 0x0208, 2 },
+ [FAB_S1_AXI_RESET] = { 0x0208, 1 },
+ [FAB_S0_AXI_RESET] = { 0x0208 },
+ [SMMU_GFX3D_ABH_RESET] = { 0x020c, 31 },
+ [SMMU_VPE_AHB_RESET] = { 0x020c, 30 },
+ [SMMU_VFE_AHB_RESET] = { 0x020c, 29 },
+ [SMMU_ROT_AHB_RESET] = { 0x020c, 28 },
+ [SMMU_VCODEC_B_AHB_RESET] = { 0x020c, 27 },
+ [SMMU_VCODEC_A_AHB_RESET] = { 0x020c, 26 },
+ [SMMU_MDP1_AHB_RESET] = { 0x020c, 25 },
+ [SMMU_MDP0_AHB_RESET] = { 0x020c, 24 },
+ [SMMU_JPEGD_AHB_RESET] = { 0x020c, 23 },
+ [SMMU_IJPEG_AHB_RESET] = { 0x020c, 22 },
+ [APU_AHB_RESET] = { 0x020c, 18 },
+ [CSI_AHB_RESET] = { 0x020c, 17 },
+ [TV_ENC_AHB_RESET] = { 0x020c, 15 },
+ [VPE_AHB_RESET] = { 0x020c, 14 },
+ [FABRIC_AHB_RESET] = { 0x020c, 13 },
+ [GFX3D_AHB_RESET] = { 0x020c, 10 },
+ [HDMI_AHB_RESET] = { 0x020c, 9 },
+ [MSSS_IMEM_AHB_RESET] = { 0x020c, 8 },
+ [IJPEG_AHB_RESET] = { 0x020c, 7 },
+ [DSI_M_AHB_RESET] = { 0x020c, 6 },
+ [DSI_S_AHB_RESET] = { 0x020c, 5 },
+ [JPEGD_AHB_RESET] = { 0x020c, 4 },
+ [MDP_AHB_RESET] = { 0x020c, 3 },
+ [ROT_AHB_RESET] = { 0x020c, 2 },
+ [VCODEC_AHB_RESET] = { 0x020c, 1 },
+ [VFE_AHB_RESET] = { 0x020c, 0 },
+ [SMMU_VCAP_AHB_RESET] = { 0x0200, 3 },
+ [VCAP_AHB_RESET] = { 0x0200, 2 },
+ [DSI2_M_AHB_RESET] = { 0x0200, 1 },
+ [DSI2_S_AHB_RESET] = { 0x0200, 0 },
+ [CSIPHY2_RESET] = { 0x0210, 31 },
+ [CSI_PIX1_RESET] = { 0x0210, 30 },
+ [CSIPHY0_RESET] = { 0x0210, 29 },
+ [CSIPHY1_RESET] = { 0x0210, 28 },
+ [CSI_RDI_RESET] = { 0x0210, 27 },
+ [CSI_PIX_RESET] = { 0x0210, 26 },
+ [DSI2_RESET] = { 0x0210, 25 },
+ [VFE_CSI_RESET] = { 0x0210, 24 },
+ [MDP_RESET] = { 0x0210, 21 },
+ [AMP_RESET] = { 0x0210, 20 },
+ [JPEGD_RESET] = { 0x0210, 19 },
+ [CSI1_RESET] = { 0x0210, 18 },
+ [VPE_RESET] = { 0x0210, 17 },
+ [MMSS_FABRIC_RESET] = { 0x0210, 16 },
+ [VFE_RESET] = { 0x0210, 15 },
+ [GFX3D_RESET] = { 0x0210, 12 },
+ [HDMI_RESET] = { 0x0210, 11 },
+ [MMSS_IMEM_RESET] = { 0x0210, 10 },
+ [IJPEG_RESET] = { 0x0210, 9 },
+ [CSI0_RESET] = { 0x0210, 8 },
+ [DSI_RESET] = { 0x0210, 7 },
+ [VCODEC_RESET] = { 0x0210, 6 },
+ [MDP_TV_RESET] = { 0x0210, 4 },
+ [MDP_VSYNC_RESET] = { 0x0210, 3 },
+ [ROT_RESET] = { 0x0210, 2 },
+ [TV_HDMI_RESET] = { 0x0210, 1 },
+ [VCAP_NPL_RESET] = { 0x0214, 4 },
+ [VCAP_RESET] = { 0x0214, 3 },
+ [CSI2_RESET] = { 0x0214, 2 },
+ [CSI_RDI1_RESET] = { 0x0214, 1 },
+ [CSI_RDI2_RESET] = { 0x0214 },
+};
+
static const struct regmap_config mmcc_msm8960_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -2223,6 +2609,14 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
.fast_io = true,
};
+static const struct regmap_config mmcc_apq8064_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x350,
+ .fast_io = true,
+};
+
static const struct qcom_cc_desc mmcc_msm8960_desc = {
.config = &mmcc_msm8960_regmap_config,
.clks = mmcc_msm8960_clks,
@@ -2231,15 +2625,47 @@ static const struct qcom_cc_desc mmcc_msm8960_desc = {
.num_resets = ARRAY_SIZE(mmcc_msm8960_resets),
};
+static const struct qcom_cc_desc mmcc_apq8064_desc = {
+ .config = &mmcc_apq8064_regmap_config,
+ .clks = mmcc_apq8064_clks,
+ .num_clks = ARRAY_SIZE(mmcc_apq8064_clks),
+ .resets = mmcc_apq8064_resets,
+ .num_resets = ARRAY_SIZE(mmcc_apq8064_resets),
+};
+
static const struct of_device_id mmcc_msm8960_match_table[] = {
- { .compatible = "qcom,mmcc-msm8960" },
+ { .compatible = "qcom,mmcc-msm8960", .data = &mmcc_msm8960_desc },
+ { .compatible = "qcom,mmcc-apq8064", .data = &mmcc_apq8064_desc },
{ }
};
MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
static int mmcc_msm8960_probe(struct platform_device *pdev)
{
- return qcom_cc_probe(pdev, &mmcc_msm8960_desc);
+ const struct of_device_id *match;
+ struct regmap *regmap;
+ bool is_8064;
+ struct device *dev = &pdev->dev;
+
+ match = of_match_device(mmcc_msm8960_match_table, dev);
+ if (!match)
+ return -EINVAL;
+
+ is_8064 = of_device_is_compatible(dev->of_node, "qcom,mmcc-apq8064");
+ if (is_8064) {
+ gfx3d_src.freq_tbl = clk_tbl_gfx3d_8064;
+ gfx3d_src.clkr.hw.init = &gfx3d_8064_init;
+ gfx3d_src.s[0].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
+ gfx3d_src.s[1].parent_map = mmcc_pxo_pll8_pll2_pll15_map;
+ }
+
+ regmap = qcom_cc_map(pdev, match->data);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_pll_configure_sr(&pll15, regmap, &pll15_config, false);
+
+ return qcom_cc_really_probe(pdev, match->data, regmap);
}
static int mmcc_msm8960_remove(struct platform_device *pdev)
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index c65b90515872..bc8f519c47aa 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -2547,18 +2547,16 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
static int mmcc_msm8974_probe(struct platform_device *pdev)
{
- int ret;
struct regmap *regmap;
- ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc);
- if (ret)
- return ret;
+ regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
- regmap = dev_get_regmap(&pdev->dev, NULL);
clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
- return 0;
+ return qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
}
static int mmcc_msm8974_remove(struct platform_device *pdev)
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 8d3aefad2e73..ee6b077381e1 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -3,3 +3,9 @@
#
obj-y += clk-rockchip.o
+obj-y += clk.o
+obj-y += clk-pll.o
+obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
+
+obj-y += clk-rk3188.o
+obj-y += clk-rk3288.o
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
new file mode 100644
index 000000000000..f2a1c7abf4d9
--- /dev/null
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/div64.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include "clk.h"
+
+#define PLL_MODE_MASK 0x3
+#define PLL_MODE_SLOW 0x0
+#define PLL_MODE_NORM 0x1
+#define PLL_MODE_DEEP 0x2
+
+struct rockchip_clk_pll {
+ struct clk_hw hw;
+
+ struct clk_mux pll_mux;
+ const struct clk_ops *pll_mux_ops;
+
+ struct notifier_block clk_nb;
+ bool rate_change_remuxed;
+
+ void __iomem *reg_base;
+ int lock_offset;
+ unsigned int lock_shift;
+ enum rockchip_pll_type type;
+ const struct rockchip_pll_rate_table *rate_table;
+ unsigned int rate_count;
+ spinlock_t *lock;
+};
+
+#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
+#define to_rockchip_clk_pll_nb(nb) \
+ container_of(nb, struct rockchip_clk_pll, clk_nb)
+
+static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
+ struct rockchip_clk_pll *pll, unsigned long rate)
+{
+ const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+ }
+
+ return NULL;
+}
+
+static long rockchip_pll_round_rate(struct clk_hw *hw,
+ unsigned long drate, unsigned long *prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ /* Assumming rate_table is in descending order */
+ for (i = 0; i < pll->rate_count; i++) {
+ if (drate >= rate_table[i].rate)
+ return rate_table[i].rate;
+ }
+
+ /* return minimum supported value */
+ return rate_table[i - 1].rate;
+}
+
+/*
+ * Wait for the pll to reach the locked state.
+ * The calling set_rate function is responsible for making sure the
+ * grf regmap is available.
+ */
+static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+ struct regmap *grf = rockchip_clk_get_grf();
+ unsigned int val;
+ int delay = 24000000, ret;
+
+ while (delay > 0) {
+ ret = regmap_read(grf, pll->lock_offset, &val);
+ if (ret) {
+ pr_err("%s: failed to read pll lock status: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ if (val & BIT(pll->lock_shift))
+ return 0;
+ delay--;
+ }
+
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+ return -ETIMEDOUT;
+}
+
+/**
+ * Set pll mux when changing the pll rate.
+ * This makes sure to move the pll mux away from the actual pll before
+ * changing its rate and back to the original parent after the change.
+ */
+static int rockchip_pll_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb);
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ int cur_parent;
+
+ switch (event) {
+ case PRE_RATE_CHANGE:
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+ if (cur_parent == PLL_MODE_NORM) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+ pll->rate_change_remuxed = 1;
+ }
+ break;
+ case POST_RATE_CHANGE:
+ if (pll->rate_change_remuxed) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+ pll->rate_change_remuxed = 0;
+ }
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+/**
+ * PLL used in RK3066, RK3188 and RK3288
+ */
+
+#define RK3066_PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1)
+
+#define RK3066_PLLCON(i) (i * 0x4)
+#define RK3066_PLLCON0_OD_MASK 0xf
+#define RK3066_PLLCON0_OD_SHIFT 0
+#define RK3066_PLLCON0_NR_MASK 0x3f
+#define RK3066_PLLCON0_NR_SHIFT 8
+#define RK3066_PLLCON1_NF_MASK 0x1fff
+#define RK3066_PLLCON1_NF_SHIFT 0
+#define RK3066_PLLCON2_BWADJ_MASK 0xfff
+#define RK3066_PLLCON2_BWADJ_SHIFT 0
+#define RK3066_PLLCON3_RESET (1 << 5)
+#define RK3066_PLLCON3_PWRDOWN (1 << 1)
+#define RK3066_PLLCON3_BYPASS (1 << 0)
+
+static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u64 nf, nr, no, rate64 = prate;
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
+ if (pllcon & RK3066_PLLCON3_BYPASS) {
+ pr_debug("%s: pll %s is bypassed\n", __func__,
+ __clk_get_name(hw->clk));
+ return prate;
+ }
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+ nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+ nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
+ no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
+
+ rate64 *= (nf + 1);
+ do_div(rate64, nr + 1);
+ do_div(rate64, no + 1);
+
+ return (unsigned long)rate64;
+}
+
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+ unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
+ struct regmap *grf = rockchip_clk_get_grf();
+ int ret;
+
+ if (IS_ERR(grf)) {
+ pr_debug("%s: grf regmap not available, aborting rate change\n",
+ __func__);
+ return PTR_ERR(grf);
+ }
+
+ pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
+ __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, __clk_get_name(hw->clk));
+ return -EINVAL;
+ }
+
+ pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
+ __func__, rate->rate, rate->nr, rate->no, rate->nf);
+
+ /* enter reset mode */
+ writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0),
+ pll->reg_base + RK3066_PLLCON(3));
+
+ /* update pll values */
+ writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK,
+ RK3066_PLLCON0_NR_SHIFT) |
+ HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK,
+ RK3066_PLLCON0_OD_SHIFT),
+ pll->reg_base + RK3066_PLLCON(0));
+
+ writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
+ RK3066_PLLCON1_NF_SHIFT),
+ pll->reg_base + RK3066_PLLCON(1));
+ writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK,
+ RK3066_PLLCON2_BWADJ_SHIFT),
+ pll->reg_base + RK3066_PLLCON(2));
+
+ /* leave reset and wait the reset_delay */
+ writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0),
+ pll->reg_base + RK3066_PLLCON(3));
+ udelay(RK3066_PLL_RESET_DELAY(rate->nr));
+
+ /* wait for the pll to lock */
+ ret = rockchip_pll_wait_lock(pll);
+ if (ret) {
+ pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+ __func__, old_rate);
+ rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+ }
+
+ return ret;
+}
+
+static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3066_PLLCON(3));
+
+ return 0;
+}
+
+static void rockchip_rk3066_pll_disable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN,
+ RK3066_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3066_PLLCON(3));
+}
+
+static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3));
+
+ return !(pllcon & RK3066_PLLCON3_PWRDOWN);
+}
+
+static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
+ .recalc_rate = rockchip_rk3066_pll_recalc_rate,
+ .enable = rockchip_rk3066_pll_enable,
+ .disable = rockchip_rk3066_pll_disable,
+ .is_enabled = rockchip_rk3066_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
+ .recalc_rate = rockchip_rk3066_pll_recalc_rate,
+ .round_rate = rockchip_pll_round_rate,
+ .set_rate = rockchip_rk3066_pll_set_rate,
+ .enable = rockchip_rk3066_pll_enable,
+ .disable = rockchip_rk3066_pll_disable,
+ .is_enabled = rockchip_rk3066_pll_is_enabled,
+};
+
+/*
+ * Common registering of pll clocks
+ */
+
+struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+ const char *name, const char **parent_names, u8 num_parents,
+ void __iomem *base, int con_offset, int grf_lock_offset,
+ int lock_shift, int mode_offset, int mode_shift,
+ struct rockchip_pll_rate_table *rate_table,
+ spinlock_t *lock)
+{
+ const char *pll_parents[3];
+ struct clk_init_data init;
+ struct rockchip_clk_pll *pll;
+ struct clk_mux *pll_mux;
+ struct clk *pll_clk, *mux_clk;
+ char pll_name[20];
+ int ret;
+
+ if (num_parents != 2) {
+ pr_err("%s: needs two parent clocks\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* name the actual pll */
+ snprintf(pll_name, sizeof(pll_name), "pll_%s", name);
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = pll_name;
+
+ /* keep all plls untouched for now */
+ init.flags = CLK_IGNORE_UNUSED;
+
+ init.parent_names = &parent_names[0];
+ init.num_parents = 1;
+
+ if (rate_table) {
+ int len;
+
+ /* find count of rates in rate_table */
+ for (len = 0; rate_table[len].rate != 0; )
+ len++;
+
+ pll->rate_count = len;
+ pll->rate_table = kmemdup(rate_table,
+ pll->rate_count *
+ sizeof(struct rockchip_pll_rate_table),
+ GFP_KERNEL);
+ WARN(!pll->rate_table,
+ "%s: could not allocate rate table for %s\n",
+ __func__, name);
+ }
+
+ switch (pll_type) {
+ case pll_rk3066:
+ if (!pll->rate_table)
+ init.ops = &rockchip_rk3066_pll_clk_norate_ops;
+ else
+ init.ops = &rockchip_rk3066_pll_clk_ops;
+ break;
+ default:
+ pr_warn("%s: Unknown pll type for pll clk %s\n",
+ __func__, name);
+ }
+
+ pll->hw.init = &init;
+ pll->type = pll_type;
+ pll->reg_base = base + con_offset;
+ pll->lock_offset = grf_lock_offset;
+ pll->lock_shift = lock_shift;
+ pll->lock = lock;
+ pll->clk_nb.notifier_call = rockchip_pll_notifier_cb;
+
+ pll_clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(pll_clk)) {
+ pr_err("%s: failed to register pll clock %s : %ld\n",
+ __func__, name, PTR_ERR(pll_clk));
+ mux_clk = pll_clk;
+ goto err_pll;
+ }
+
+ ret = clk_notifier_register(pll_clk, &pll->clk_nb);
+ if (ret) {
+ pr_err("%s: failed to register clock notifier for %s : %d\n",
+ __func__, name, ret);
+ mux_clk = ERR_PTR(ret);
+ goto err_pll_notifier;
+ }
+
+ /* create the mux on top of the real pll */
+ pll->pll_mux_ops = &clk_mux_ops;
+ pll_mux = &pll->pll_mux;
+
+ /* the actual muxing is xin24m, pll-output, xin32k */
+ pll_parents[0] = parent_names[0];
+ pll_parents[1] = pll_name;
+ pll_parents[2] = parent_names[1];
+
+ init.name = name;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.ops = pll->pll_mux_ops;
+ init.parent_names = pll_parents;
+ init.num_parents = ARRAY_SIZE(pll_parents);
+
+ pll_mux->reg = base + mode_offset;
+ pll_mux->shift = mode_shift;
+ pll_mux->mask = PLL_MODE_MASK;
+ pll_mux->flags = 0;
+ pll_mux->lock = lock;
+ pll_mux->hw.init = &init;
+
+ if (pll_type == pll_rk3066)
+ pll_mux->flags |= CLK_MUX_HIWORD_MASK;
+
+ mux_clk = clk_register(NULL, &pll_mux->hw);
+ if (IS_ERR(mux_clk))
+ goto err_mux;
+
+ return mux_clk;
+
+err_mux:
+ ret = clk_notifier_unregister(pll_clk, &pll->clk_nb);
+ if (ret) {
+ pr_err("%s: could not unregister clock notifier in error path : %d\n",
+ __func__, ret);
+ return mux_clk;
+ }
+err_pll_notifier:
+ clk_unregister(pll_clk);
+err_pll:
+ kfree(pll);
+ return mux_clk;
+}
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
new file mode 100644
index 000000000000..a83a6d8d0fb6
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/rk3188-cru-common.h>
+#include "clk.h"
+
+#define RK3188_GRF_SOC_STATUS 0xac
+
+enum rk3188_plls {
+ apll, cpll, dpll, gpll,
+};
+
+struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+ RK3066_PLL_RATE(2208000000, 1, 92, 1),
+ RK3066_PLL_RATE(2184000000, 1, 91, 1),
+ RK3066_PLL_RATE(2160000000, 1, 90, 1),
+ RK3066_PLL_RATE(2136000000, 1, 89, 1),
+ RK3066_PLL_RATE(2112000000, 1, 88, 1),
+ RK3066_PLL_RATE(2088000000, 1, 87, 1),
+ RK3066_PLL_RATE(2064000000, 1, 86, 1),
+ RK3066_PLL_RATE(2040000000, 1, 85, 1),
+ RK3066_PLL_RATE(2016000000, 1, 84, 1),
+ RK3066_PLL_RATE(1992000000, 1, 83, 1),
+ RK3066_PLL_RATE(1968000000, 1, 82, 1),
+ RK3066_PLL_RATE(1944000000, 1, 81, 1),
+ RK3066_PLL_RATE(1920000000, 1, 80, 1),
+ RK3066_PLL_RATE(1896000000, 1, 79, 1),
+ RK3066_PLL_RATE(1872000000, 1, 78, 1),
+ RK3066_PLL_RATE(1848000000, 1, 77, 1),
+ RK3066_PLL_RATE(1824000000, 1, 76, 1),
+ RK3066_PLL_RATE(1800000000, 1, 75, 1),
+ RK3066_PLL_RATE(1776000000, 1, 74, 1),
+ RK3066_PLL_RATE(1752000000, 1, 73, 1),
+ RK3066_PLL_RATE(1728000000, 1, 72, 1),
+ RK3066_PLL_RATE(1704000000, 1, 71, 1),
+ RK3066_PLL_RATE(1680000000, 1, 70, 1),
+ RK3066_PLL_RATE(1656000000, 1, 69, 1),
+ RK3066_PLL_RATE(1632000000, 1, 68, 1),
+ RK3066_PLL_RATE(1608000000, 1, 67, 1),
+ RK3066_PLL_RATE(1560000000, 1, 65, 1),
+ RK3066_PLL_RATE(1512000000, 1, 63, 1),
+ RK3066_PLL_RATE(1488000000, 1, 62, 1),
+ RK3066_PLL_RATE(1464000000, 1, 61, 1),
+ RK3066_PLL_RATE(1440000000, 1, 60, 1),
+ RK3066_PLL_RATE(1416000000, 1, 59, 1),
+ RK3066_PLL_RATE(1392000000, 1, 58, 1),
+ RK3066_PLL_RATE(1368000000, 1, 57, 1),
+ RK3066_PLL_RATE(1344000000, 1, 56, 1),
+ RK3066_PLL_RATE(1320000000, 1, 55, 1),
+ RK3066_PLL_RATE(1296000000, 1, 54, 1),
+ RK3066_PLL_RATE(1272000000, 1, 53, 1),
+ RK3066_PLL_RATE(1248000000, 1, 52, 1),
+ RK3066_PLL_RATE(1224000000, 1, 51, 1),
+ RK3066_PLL_RATE(1200000000, 1, 50, 1),
+ RK3066_PLL_RATE(1188000000, 2, 99, 1),
+ RK3066_PLL_RATE(1176000000, 1, 49, 1),
+ RK3066_PLL_RATE(1128000000, 1, 47, 1),
+ RK3066_PLL_RATE(1104000000, 1, 46, 1),
+ RK3066_PLL_RATE(1008000000, 1, 84, 2),
+ RK3066_PLL_RATE( 912000000, 1, 76, 2),
+ RK3066_PLL_RATE( 891000000, 8, 594, 2),
+ RK3066_PLL_RATE( 888000000, 1, 74, 2),
+ RK3066_PLL_RATE( 816000000, 1, 68, 2),
+ RK3066_PLL_RATE( 798000000, 2, 133, 2),
+ RK3066_PLL_RATE( 792000000, 1, 66, 2),
+ RK3066_PLL_RATE( 768000000, 1, 64, 2),
+ RK3066_PLL_RATE( 742500000, 8, 495, 2),
+ RK3066_PLL_RATE( 696000000, 1, 58, 2),
+ RK3066_PLL_RATE( 600000000, 1, 50, 2),
+ RK3066_PLL_RATE( 594000000, 2, 198, 4),
+ RK3066_PLL_RATE( 552000000, 1, 46, 2),
+ RK3066_PLL_RATE( 504000000, 1, 84, 4),
+ RK3066_PLL_RATE( 456000000, 1, 76, 4),
+ RK3066_PLL_RATE( 408000000, 1, 68, 4),
+ RK3066_PLL_RATE( 384000000, 2, 128, 4),
+ RK3066_PLL_RATE( 360000000, 1, 60, 4),
+ RK3066_PLL_RATE( 312000000, 1, 52, 4),
+ RK3066_PLL_RATE( 300000000, 1, 50, 4),
+ RK3066_PLL_RATE( 297000000, 2, 198, 8),
+ RK3066_PLL_RATE( 252000000, 1, 84, 8),
+ RK3066_PLL_RATE( 216000000, 1, 72, 8),
+ RK3066_PLL_RATE( 148500000, 2, 99, 8),
+ RK3066_PLL_RATE( 126000000, 1, 84, 16),
+ RK3066_PLL_RATE( 48000000, 1, 64, 32),
+ { /* sentinel */ },
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin32k" };
+PNAME(mux_armclk_p) = { "apll", "gpll_armclk" };
+PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" };
+PNAME(mux_pll_src_gpll_cpll_p) = { "gpll", "cpll" };
+PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
+PNAME(mux_aclk_cpu_p) = { "apll", "gpll" };
+PNAME(mux_sclk_cif0_p) = { "cif0_pre", "xin24m" };
+PNAME(mux_sclk_i2s0_p) = { "i2s0_pre", "i2s0_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_sclk_uart0_p) = { "uart0_pre", "uart0_frac", "xin24m" };
+PNAME(mux_sclk_uart1_p) = { "uart1_pre", "uart1_frac", "xin24m" };
+PNAME(mux_sclk_uart2_p) = { "uart2_pre", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_uart3_p) = { "uart3_pre", "uart3_frac", "xin24m" };
+PNAME(mux_sclk_hsadc_p) = { "hsadc_src", "hsadc_frac", "ext_hsadc" };
+PNAME(mux_mac_p) = { "gpll", "dpll" };
+PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" };
+
+static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
+ RK2928_MODE_CON, 0, 6, rk3188_pll_rates),
+ [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
+ RK2928_MODE_CON, 4, 5, NULL),
+ [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8),
+ RK2928_MODE_CON, 8, 7, rk3188_pll_rates),
+ [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
+ RK2928_MODE_CON, 12, 8, rk3188_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+/* 2 ^ (val + 1) */
+static struct clk_div_table div_core_peri_t[] = {
+ { .val = 0, .div = 2 },
+ { .val = 1, .div = 4 },
+ { .val = 2, .div = 8 },
+ { .val = 3, .div = 16 },
+ { /* sentinel */ },
+};
+
+static struct rockchip_clk_branch common_clk_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ GATE(0, "gpll_armclk", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
+
+ /* these two are set by the cpuclk and should not be changed */
+ COMPOSITE_NOMUX_DIVTBL(CORE_PERI, "core_peri", "armclk", 0,
+ RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS),
+
+ COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 9, GFLAGS),
+ GATE(0, "hclk_vepu", "aclk_vepu", 0,
+ RK2928_CLKGATE_CON(3), 10, GFLAGS),
+ COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 11, GFLAGS),
+ GATE(0, "hclk_vdpu", "aclk_vdpu", 0,
+ RK2928_CLKGATE_CON(3), 12, GFLAGS),
+
+ GATE(0, "gpll_ddr", "gpll", 0,
+ RK2928_CLKGATE_CON(1), 7, GFLAGS),
+ COMPOSITE(0, "ddrphy", mux_ddrphy_p, 0,
+ RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK2928_CLKGATE_CON(0), 2, GFLAGS),
+
+ GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+ RK2928_CLKGATE_CON(0), 3, GFLAGS),
+
+ DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0,
+ RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+ GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
+ RK2928_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+ RK2928_CLKGATE_CON(0), 5, GFLAGS),
+ DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0,
+ RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+ COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0,
+ RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK2928_CLKGATE_CON(4), 9, GFLAGS),
+ GATE(0, "hclk_cpu", "hclk_cpu_pre", 0,
+ RK2928_CLKGATE_CON(0), 4, GFLAGS),
+
+ COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 0, GFLAGS),
+ COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK2928_CLKGATE_CON(1), 4, GFLAGS),
+
+ GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+ RK2928_CLKGATE_CON(2), 1, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0,
+ RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK2928_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0,
+ RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK2928_CLKGATE_CON(2), 3, GFLAGS),
+
+ MUX(0, "cif_src", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(29), 0, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "cif0_pre", "cif_src", 0,
+ RK2928_CLKSEL_CON(29), 1, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 7, GFLAGS),
+ MUX(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_p, 0,
+ RK2928_CLKSEL_CON(29), 7, 1, MFLAGS),
+
+ GATE(0, "pclkin_cif0", "ext_cif0", 0,
+ RK2928_CLKGATE_CON(3), 3, GFLAGS),
+
+ /*
+ * the 480m are generated inside the usb block from these clocks,
+ * but they are also a source for the hsicphy clock.
+ */
+ GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0,
+ RK2928_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0,
+ RK2928_CLKGATE_CON(1), 6, GFLAGS),
+
+ COMPOSITE(0, "mac_src", mux_mac_p, 0,
+ RK2928_CLKSEL_CON(21), 0, 1, MFLAGS, 8, 5, DFLAGS,
+ RK2928_CLKGATE_CON(2), 5, GFLAGS),
+ MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(21), 4, 1, MFLAGS),
+ GATE(0, "sclk_mac_lbtest", "sclk_macref",
+ RK2928_CLKGATE_CON(2), 12, 0, GFLAGS),
+
+ COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
+ RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(2), 6, GFLAGS),
+ COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src",
+ RK2928_CLKSEL_CON(23), 0,
+ RK2928_CLKGATE_CON(2), 7, 0, GFLAGS),
+ MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+ RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+ RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(2), 8, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+
+ GATE(SCLK_SMC, "sclk_smc", "hclk_peri",
+ RK2928_CLKGATE_CON(2), 4, 0, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0,
+ RK2928_CLKSEL_CON(25), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(2), 9, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_SPI1, "sclk_spi1", "pclk_peri", 0,
+ RK2928_CLKSEL_CON(25), 8, 7, DFLAGS,
+ RK2928_CLKGATE_CON(2), 10, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_SDMMC, "sclk_sdmmc", "hclk_peri", 0,
+ RK2928_CLKSEL_CON(11), 0, 6, DFLAGS,
+ RK2928_CLKGATE_CON(2), 11, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_SDIO, "sclk_sdio", "hclk_peri", 0,
+ RK2928_CLKSEL_CON(12), 0, 6, DFLAGS,
+ RK2928_CLKGATE_CON(2), 13, GFLAGS),
+ COMPOSITE_NOMUX(SCLK_EMMC, "sclk_emmc", "hclk_peri", 0,
+ RK2928_CLKSEL_CON(12), 8, 6, DFLAGS,
+ RK2928_CLKGATE_CON(2), 14, GFLAGS),
+
+ MUX(0, "uart_src", mux_pll_src_gpll_cpll_p, 0,
+ RK2928_CLKSEL_CON(12), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
+ RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
+ RK2928_CLKSEL_CON(17), 0,
+ RK2928_CLKGATE_CON(1), 9, GFLAGS),
+ MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+ RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
+ RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(1), 10, GFLAGS),
+ COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
+ RK2928_CLKSEL_CON(18), 0,
+ RK2928_CLKGATE_CON(1), 11, GFLAGS),
+ MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+ RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
+ RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
+ RK2928_CLKSEL_CON(19), 0,
+ RK2928_CLKGATE_CON(1), 13, GFLAGS),
+ MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+ RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
+ RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(1), 14, GFLAGS),
+ COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
+ RK2928_CLKSEL_CON(20), 0,
+ RK2928_CLKGATE_CON(1), 15, GFLAGS),
+ MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+ RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
+
+ GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
+
+ GATE(SCLK_TIMER0, "timer0", "xin24m", 0, RK2928_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(SCLK_TIMER1, "timer1", "xin24m", 0, RK2928_CLKGATE_CON(1), 1, GFLAGS),
+
+ /* clk_core_pre gates */
+ GATE(0, "core_dbg", "armclk", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS),
+
+ /* aclk_cpu gates */
+ GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 12, GFLAGS),
+ GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 10, GFLAGS),
+
+ /* hclk_cpu gates */
+ GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+ GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS),
+ /* hclk_ahb2apb is part of a clk branch */
+ GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
+ GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS),
+ GATE(HCLK_LCDC1, "hclk_lcdc1", "aclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS),
+ GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS),
+ GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS),
+ GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS),
+
+ /* hclk_peri gates */
+ GATE(0, "hclk_peri_axi_matrix", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 0, GFLAGS),
+ GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 6, GFLAGS),
+ GATE(0, "hclk_emem_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 7, GFLAGS),
+ GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
+ GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
+ GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 5, GFLAGS),
+ GATE(HCLK_OTG0, "hclk_usbotg0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
+ GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 5, GFLAGS),
+ GATE(HCLK_PIDF, "hclk_pidfilter", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 12, GFLAGS),
+
+ /* aclk_lcdc0_pre gates */
+ GATE(0, "aclk_vio0", "aclk_lcdc0_pre", 0, RK2928_CLKGATE_CON(6), 13, GFLAGS),
+ GATE(ACLK_LCDC0, "aclk_lcdc0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 0, GFLAGS),
+ GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 5, GFLAGS),
+ GATE(ACLK_IPP, "aclk_ipp", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 8, GFLAGS),
+
+ /* aclk_lcdc1_pre gates */
+ GATE(0, "aclk_vio1", "aclk_lcdc1_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
+ GATE(ACLK_LCDC1, "aclk_lcdc1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 3, GFLAGS),
+ GATE(ACLK_RGA, "aclk_rga", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 11, GFLAGS),
+
+ /* atclk_cpu gates */
+ GATE(0, "atclk", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 3, GFLAGS),
+ GATE(0, "trace", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS),
+
+ /* pclk_cpu gates */
+ GATE(PCLK_PWM01, "pclk_pwm01", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
+ GATE(PCLK_TIMER0, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
+ GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS),
+ GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS),
+ GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+ GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+ GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
+ GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 5, GFLAGS),
+
+ /* aclk_peri */
+ GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS),
+ GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 4, GFLAGS),
+ GATE(0, "aclk_cpu_peri", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 2, GFLAGS),
+ GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 3, GFLAGS),
+
+ /* pclk_peri gates */
+ GATE(0, "pclk_peri_axi_matrix", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 1, GFLAGS),
+ GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS),
+ GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 13, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS),
+};
+
+PNAME(mux_rk3066_lcdc0_p) = { "dclk_lcdc0_src", "xin27m" };
+PNAME(mux_rk3066_lcdc1_p) = { "dclk_lcdc1_src", "xin27m" };
+PNAME(mux_sclk_cif1_p) = { "cif1_pre", "xin24m" };
+PNAME(mux_sclk_i2s1_p) = { "i2s1_pre", "i2s1_frac", "xin12m" };
+PNAME(mux_sclk_i2s2_p) = { "i2s2_pre", "i2s2_frac", "xin12m" };
+
+static struct clk_div_table div_aclk_cpu_t[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 3 },
+ { .val = 3, .div = 4 },
+ { .val = 4, .div = 8 },
+ { /* sentinel */ },
+};
+
+static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
+ COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+ RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 0, 5, DFLAGS),
+ DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
+ RK2928_CLKSEL_CON(1), 0, 3, DFLAGS, div_aclk_cpu_t),
+
+ GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0,
+ RK2928_CLKGATE_CON(9), 4, GFLAGS),
+
+ COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0,
+ RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+ COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(3), 1, GFLAGS),
+ MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0,
+ RK2928_CLKSEL_CON(27), 4, 1, MFLAGS),
+ COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(3), 2, GFLAGS),
+ MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0,
+ RK2928_CLKSEL_CON(28), 4, 1, MFLAGS),
+
+ COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0,
+ RK2928_CLKSEL_CON(29), 8, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 8, GFLAGS),
+ MUX(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_p, 0,
+ RK2928_CLKSEL_CON(29), 15, 1, MFLAGS),
+
+ GATE(0, "pclkin_cif1", "ext_cif1", 0,
+ RK2928_CLKGATE_CON(3), 4, GFLAGS),
+
+ COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 13, GFLAGS),
+ GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0,
+ RK2928_CLKGATE_CON(5), 15, GFLAGS),
+
+ GATE(SCLK_TIMER2, "timer2", "xin24m", 0,
+ RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0,
+ RK2928_CLKSEL_CON(34), 0, 16, DFLAGS,
+ RK2928_CLKGATE_CON(2), 15, GFLAGS),
+
+ MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0,
+ RK2928_CLKSEL_CON(2), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(0), 7, GFLAGS),
+ COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+ RK2928_CLKSEL_CON(6), 0,
+ RK2928_CLKGATE_CON(0), 8, GFLAGS),
+ MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+ RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
+ RK2928_CLKSEL_CON(7), 0,
+ RK2928_CLKGATE_CON(0), 10, GFLAGS),
+ MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+ RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(0), 11, GFLAGS),
+ COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
+ RK2928_CLKSEL_CON(8), 0,
+ RK2928_CLKGATE_CON(0), 12, GFLAGS),
+ MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+ RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+ RK2928_CLKSEL_CON(9), 0,
+ RK2928_CLKGATE_CON(0), 14, GFLAGS),
+ MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+ RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+
+ GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+ GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+ GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS),
+ GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
+
+ GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
+
+ GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS),
+
+ GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS),
+ GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS),
+ GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 13, GFLAGS),
+};
+
+static struct clk_div_table div_rk3188_aclk_core_t[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 3 },
+ { .val = 3, .div = 4 },
+ { .val = 4, .div = 8 },
+ { /* sentinel */ },
+};
+
+PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1",
+ "gpll", "cpll" };
+
+static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
+ COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+ RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 9, 5, DFLAGS),
+ COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0,
+ RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS),
+
+ /* do not source aclk_cpu_pre from the apll, to keep complexity down */
+ COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT,
+ RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS),
+
+ GATE(CORE_L2C, "core_l2c", "armclk", 0,
+ RK2928_CLKGATE_CON(9), 4, GFLAGS),
+
+ COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(2), 0, GFLAGS),
+
+ COMPOSITE(DCLK_LCDC0, "dclk_lcdc0", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(3), 1, GFLAGS),
+ COMPOSITE(DCLK_LCDC1, "dclk_lcdc1", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK2928_CLKGATE_CON(3), 2, GFLAGS),
+
+ COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+ RK2928_CLKSEL_CON(34), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK2928_CLKGATE_CON(3), 15, GFLAGS),
+ GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0,
+ RK2928_CLKGATE_CON(9), 7, GFLAGS),
+
+ GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 4, GFLAGS),
+ GATE(SCLK_TIMER3, "timer3", "xin24m", 0, RK2928_CLKGATE_CON(1), 2, GFLAGS),
+ GATE(SCLK_TIMER4, "timer4", "xin24m", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS),
+ GATE(SCLK_TIMER5, "timer5", "xin24m", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
+ GATE(SCLK_TIMER6, "timer6", "xin24m", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_hsicphy_480m", mux_hsicphy_p, 0,
+ RK2928_CLKSEL_CON(30), 0, 2, DFLAGS,
+ RK2928_CLKGATE_CON(3), 6, GFLAGS),
+ DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0,
+ RK2928_CLKGATE_CON(11), 8, 6, DFLAGS),
+
+ MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0,
+ RK2928_CLKSEL_CON(2), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+ RK2928_CLKSEL_CON(7), 0,
+ RK2928_CLKGATE_CON(0), 10, GFLAGS),
+ MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+ RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
+ RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
+ RK2928_CLKGATE_CON(13), 13, GFLAGS),
+ COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+ RK2928_CLKSEL_CON(9), 0,
+ RK2928_CLKGATE_CON(0), 14, GFLAGS),
+ MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
+ RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+
+ GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
+ GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
+
+ GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+ GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+
+ GATE(PCLK_TIMER3, "pclk_timer3", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS),
+
+ GATE(PCLK_UART0, "pclk_uart0", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
+
+ GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
+};
+
+static void __init rk3188_common_clk_init(struct device_node *np)
+{
+ void __iomem *reg_base;
+ struct clk *clk;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+ /* xin12m is created by an cru-internal divider */
+ clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock xin12m: %ld\n",
+ __func__, PTR_ERR(clk));
+
+ clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock usb480m: %ld\n",
+ __func__, PTR_ERR(clk));
+
+ rockchip_clk_register_plls(rk3188_pll_clks,
+ ARRAY_SIZE(rk3188_pll_clks),
+ RK3188_GRF_SOC_STATUS);
+ rockchip_clk_register_branches(common_clk_branches,
+ ARRAY_SIZE(common_clk_branches));
+
+ rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
+
+static void __init rk3066a_clk_init(struct device_node *np)
+{
+ rk3188_common_clk_init(np);
+ rockchip_clk_register_branches(rk3066a_clk_branches,
+ ARRAY_SIZE(rk3066a_clk_branches));
+}
+CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
+
+static void __init rk3188a_clk_init(struct device_node *np)
+{
+ rk3188_common_clk_init(np);
+ rockchip_clk_register_branches(rk3188_clk_branches,
+ ARRAY_SIZE(rk3188_clk_branches));
+}
+CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
+
+static void __init rk3188_clk_init(struct device_node *np)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rk3188_pll_clks); i++) {
+ struct rockchip_pll_clock *pll = &rk3188_pll_clks[i];
+ struct rockchip_pll_rate_table *rate;
+
+ if (!pll->rate_table)
+ continue;
+
+ rate = pll->rate_table;
+ while (rate->rate > 0) {
+ rate->bwadj = 0;
+ rate++;
+ }
+ }
+
+ rk3188a_clk_init(np);
+}
+CLK_OF_DECLARE(rk3188_cru, "rockchip,rk3188-cru", rk3188_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
new file mode 100644
index 000000000000..0d8c6c59a75e
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include "clk.h"
+
+#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
+#define RK3288_GRF_SOC_STATUS 0x280
+
+enum rk3288_plls {
+ apll, dpll, cpll, gpll, npll,
+};
+
+struct rockchip_pll_rate_table rk3288_pll_rates[] = {
+ RK3066_PLL_RATE(2208000000, 1, 92, 1),
+ RK3066_PLL_RATE(2184000000, 1, 91, 1),
+ RK3066_PLL_RATE(2160000000, 1, 90, 1),
+ RK3066_PLL_RATE(2136000000, 1, 89, 1),
+ RK3066_PLL_RATE(2112000000, 1, 88, 1),
+ RK3066_PLL_RATE(2088000000, 1, 87, 1),
+ RK3066_PLL_RATE(2064000000, 1, 86, 1),
+ RK3066_PLL_RATE(2040000000, 1, 85, 1),
+ RK3066_PLL_RATE(2016000000, 1, 84, 1),
+ RK3066_PLL_RATE(1992000000, 1, 83, 1),
+ RK3066_PLL_RATE(1968000000, 1, 82, 1),
+ RK3066_PLL_RATE(1944000000, 1, 81, 1),
+ RK3066_PLL_RATE(1920000000, 1, 80, 1),
+ RK3066_PLL_RATE(1896000000, 1, 79, 1),
+ RK3066_PLL_RATE(1872000000, 1, 78, 1),
+ RK3066_PLL_RATE(1848000000, 1, 77, 1),
+ RK3066_PLL_RATE(1824000000, 1, 76, 1),
+ RK3066_PLL_RATE(1800000000, 1, 75, 1),
+ RK3066_PLL_RATE(1776000000, 1, 74, 1),
+ RK3066_PLL_RATE(1752000000, 1, 73, 1),
+ RK3066_PLL_RATE(1728000000, 1, 72, 1),
+ RK3066_PLL_RATE(1704000000, 1, 71, 1),
+ RK3066_PLL_RATE(1680000000, 1, 70, 1),
+ RK3066_PLL_RATE(1656000000, 1, 69, 1),
+ RK3066_PLL_RATE(1632000000, 1, 68, 1),
+ RK3066_PLL_RATE(1608000000, 1, 67, 1),
+ RK3066_PLL_RATE(1560000000, 1, 65, 1),
+ RK3066_PLL_RATE(1512000000, 1, 63, 1),
+ RK3066_PLL_RATE(1488000000, 1, 62, 1),
+ RK3066_PLL_RATE(1464000000, 1, 61, 1),
+ RK3066_PLL_RATE(1440000000, 1, 60, 1),
+ RK3066_PLL_RATE(1416000000, 1, 59, 1),
+ RK3066_PLL_RATE(1392000000, 1, 58, 1),
+ RK3066_PLL_RATE(1368000000, 1, 57, 1),
+ RK3066_PLL_RATE(1344000000, 1, 56, 1),
+ RK3066_PLL_RATE(1320000000, 1, 55, 1),
+ RK3066_PLL_RATE(1296000000, 1, 54, 1),
+ RK3066_PLL_RATE(1272000000, 1, 53, 1),
+ RK3066_PLL_RATE(1248000000, 1, 52, 1),
+ RK3066_PLL_RATE(1224000000, 1, 51, 1),
+ RK3066_PLL_RATE(1200000000, 1, 50, 1),
+ RK3066_PLL_RATE(1188000000, 2, 99, 1),
+ RK3066_PLL_RATE(1176000000, 1, 49, 1),
+ RK3066_PLL_RATE(1128000000, 1, 47, 1),
+ RK3066_PLL_RATE(1104000000, 1, 46, 1),
+ RK3066_PLL_RATE(1008000000, 1, 84, 2),
+ RK3066_PLL_RATE( 912000000, 1, 76, 2),
+ RK3066_PLL_RATE( 891000000, 8, 594, 2),
+ RK3066_PLL_RATE( 888000000, 1, 74, 2),
+ RK3066_PLL_RATE( 816000000, 1, 68, 2),
+ RK3066_PLL_RATE( 798000000, 2, 133, 2),
+ RK3066_PLL_RATE( 792000000, 1, 66, 2),
+ RK3066_PLL_RATE( 768000000, 1, 64, 2),
+ RK3066_PLL_RATE( 742500000, 8, 495, 2),
+ RK3066_PLL_RATE( 696000000, 1, 58, 2),
+ RK3066_PLL_RATE( 600000000, 1, 50, 2),
+ RK3066_PLL_RATE( 594000000, 2, 198, 4),
+ RK3066_PLL_RATE( 552000000, 1, 46, 2),
+ RK3066_PLL_RATE( 504000000, 1, 84, 4),
+ RK3066_PLL_RATE( 456000000, 1, 76, 4),
+ RK3066_PLL_RATE( 408000000, 1, 68, 4),
+ RK3066_PLL_RATE( 384000000, 2, 128, 4),
+ RK3066_PLL_RATE( 360000000, 1, 60, 4),
+ RK3066_PLL_RATE( 312000000, 1, 52, 4),
+ RK3066_PLL_RATE( 300000000, 1, 50, 4),
+ RK3066_PLL_RATE( 297000000, 2, 198, 8),
+ RK3066_PLL_RATE( 252000000, 1, 84, 8),
+ RK3066_PLL_RATE( 216000000, 1, 72, 8),
+ RK3066_PLL_RATE( 148500000, 2, 99, 8),
+ RK3066_PLL_RATE( 126000000, 1, 84, 16),
+ RK3066_PLL_RATE( 48000000, 1, 64, 32),
+ { /* sentinel */ },
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin32k" };
+PNAME(mux_armclk_p) = { "apll_core", "gpll_core" };
+PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" };
+
+PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" };
+
+PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" };
+PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" };
+PNAME(mux_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" };
+PNAME(mux_spdif_8ch_p) = { "spdif_8ch_pre", "spdif_8ch_frac", "xin12m" };
+PNAME(mux_uart0_pll_p) = { "cpll", "gpll", "usbphy_480m_src", "npll" };
+PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_uart3_p) = { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p) = { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_cif_out_p) = { "cif_src", "xin24m" };
+PNAME(mux_macref_p) = { "mac_src", "ext_gmac" };
+PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" };
+PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" };
+PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" };
+
+PNAME(mux_usbphy480m_p) = { "sclk_otgphy0", "sclk_otgphy1",
+ "sclk_otgphy2" };
+PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" };
+PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
+
+static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0),
+ RK3288_MODE_CON, 0, 6, rk3288_pll_rates),
+ [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4),
+ RK3288_MODE_CON, 4, 5, NULL),
+ [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8),
+ RK3288_MODE_CON, 8, 7, rk3288_pll_rates),
+ [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12),
+ RK3288_MODE_CON, 12, 8, rk3288_pll_rates),
+ [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16),
+ RK3288_MODE_CON, 14, 9, NULL),
+};
+
+static struct clk_div_table div_hclk_cpu_t[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 3, .div = 4 },
+ { /* sentinel */},
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 1
+ */
+
+ GATE(0, "apll_core", "apll", 0,
+ RK3288_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "gpll_core", "gpll", 0,
+ RK3288_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0,
+ RK3288_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
+
+ COMPOSITE_NOMUX(0, "armcore0", "armclk", 0,
+ RK3288_CLKSEL_CON(36), 0, 3, DFLAGS,
+ RK3288_CLKGATE_CON(12), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "armcore1", "armclk", 0,
+ RK3288_CLKSEL_CON(36), 4, 3, DFLAGS,
+ RK3288_CLKGATE_CON(12), 1, GFLAGS),
+ COMPOSITE_NOMUX(0, "armcore2", "armclk", 0,
+ RK3288_CLKSEL_CON(36), 8, 3, DFLAGS,
+ RK3288_CLKGATE_CON(12), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "armcore3", "armclk", 0,
+ RK3288_CLKSEL_CON(36), 12, 3, DFLAGS,
+ RK3288_CLKGATE_CON(12), 3, GFLAGS),
+ COMPOSITE_NOMUX(0, "l2ram", "armclk", 0,
+ RK3288_CLKSEL_CON(37), 0, 3, DFLAGS,
+ RK3288_CLKGATE_CON(12), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0,
+ RK3288_CLKSEL_CON(0), 0, 4, DFLAGS,
+ RK3288_CLKGATE_CON(12), 5, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0,
+ RK3288_CLKSEL_CON(0), 4, 4, DFLAGS,
+ RK3288_CLKGATE_CON(12), 6, GFLAGS),
+ COMPOSITE_NOMUX(0, "atclk", "armclk", 0,
+ RK3288_CLKSEL_CON(37), 4, 5, DFLAGS,
+ RK3288_CLKGATE_CON(12), 7, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0,
+ RK3288_CLKSEL_CON(37), 9, 5, DFLAGS,
+ RK3288_CLKGATE_CON(12), 8, GFLAGS),
+ GATE(0, "pclk_dbg", "pclk_dbg_pre", 0,
+ RK3288_CLKGATE_CON(12), 9, GFLAGS),
+ GATE(0, "cs_dbg", "pclk_dbg_pre", 0,
+ RK3288_CLKGATE_CON(12), 10, GFLAGS),
+ GATE(0, "pclk_core_niu", "pclk_dbg_pre", 0,
+ RK3288_CLKGATE_CON(12), 11, GFLAGS),
+
+ GATE(0, "dpll_ddr", "dpll", 0,
+ RK3288_CLKGATE_CON(0), 8, GFLAGS),
+ GATE(0, "gpll_ddr", "gpll", 0,
+ RK3288_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, 0,
+ RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2,
+ DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
+
+ GATE(0, "gpll_aclk_cpu", "gpll", 0,
+ RK3288_CLKGATE_CON(0), 10, GFLAGS),
+ GATE(0, "cpll_aclk_cpu", "cpll", 0,
+ RK3288_CLKGATE_CON(0), 11, GFLAGS),
+ COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
+ RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS),
+ DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0,
+ RK3288_CLKSEL_CON(1), 0, 3, DFLAGS),
+ GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+ RK3288_CLKGATE_CON(0), 3, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_cpu", "aclk_cpu_pre", 0,
+ RK3288_CLKSEL_CON(1), 12, 3, DFLAGS,
+ RK3288_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NOMUX_DIVTBL(0, "hclk_cpu", "aclk_cpu_pre", 0,
+ RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t,
+ RK3288_CLKGATE_CON(0), 4, GFLAGS),
+ GATE(0, "c2c_host", "aclk_cpu_src", 0,
+ RK3288_CLKGATE_CON(13), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0,
+ RK3288_CLKSEL_CON(26), 6, 2, DFLAGS,
+ RK3288_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", 0,
+ RK3288_CLKGATE_CON(0), 7, GFLAGS),
+
+ COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(4), 1, GFLAGS),
+ COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", 0,
+ RK3288_CLKSEL_CON(8), 0,
+ RK3288_CLKGATE_CON(4), 2, GFLAGS),
+ MUX(0, "i2s_pre", mux_i2s_pre_p, 0,
+ RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
+ COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0,
+ RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
+ RK3288_CLKGATE_CON(4), 0, GFLAGS),
+ GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", 0,
+ RK3288_CLKGATE_CON(4), 3, GFLAGS),
+
+ MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
+ RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(4), 4, GFLAGS),
+ COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+ RK3288_CLKSEL_CON(9), 0,
+ RK3288_CLKGATE_CON(4), 5, GFLAGS),
+ COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
+ RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
+ RK3288_CLKGATE_CON(4), 6, GFLAGS),
+ COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
+ RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(4), 7, GFLAGS),
+ COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", 0,
+ RK3288_CLKSEL_CON(41), 0,
+ RK3288_CLKGATE_CON(4), 8, GFLAGS),
+ COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+ RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
+ RK3288_CLKGATE_CON(4), 9, GFLAGS),
+
+ GATE(0, "sclk_acc_efuse", "xin24m", 0,
+ RK3288_CLKGATE_CON(0), 12, GFLAGS),
+
+ GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 2, GFLAGS),
+ GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 3, GFLAGS),
+ GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 4, GFLAGS),
+ GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
+ RK3288_CLKGATE_CON(1), 5, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 2
+ */
+
+ COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(32), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 9, GFLAGS),
+ COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 11, GFLAGS),
+
+ COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 0, GFLAGS),
+ DIV(0, "hclk_vio", "aclk_vio0", 0,
+ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
+ COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 2, GFLAGS),
+
+ COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 5, GFLAGS),
+ COMPOSITE(0, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(3), 4, GFLAGS),
+
+ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS,
+ RK3288_CLKGATE_CON(3), 1, GFLAGS),
+ COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS,
+ RK3288_CLKGATE_CON(3), 3, GFLAGS),
+
+ COMPOSITE_NODIV(0, "sclk_edp_24m", mux_edp_24m_p, 0,
+ RK3288_CLKSEL_CON(28), 15, 1, MFLAGS,
+ RK3288_CLKGATE_CON(3), 12, GFLAGS),
+ COMPOSITE(0, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3288_CLKGATE_CON(3), 13, GFLAGS),
+
+ COMPOSITE(0, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3288_CLKGATE_CON(3), 14, GFLAGS),
+ COMPOSITE(0, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3288_CLKGATE_CON(3), 15, GFLAGS),
+
+ GATE(0, "sclk_hdmi_hdcp", "xin24m", 0,
+ RK3288_CLKGATE_CON(5), 12, GFLAGS),
+ GATE(0, "sclk_hdmi_cec", "xin32k", 0,
+ RK3288_CLKGATE_CON(5), 11, GFLAGS),
+
+ COMPOSITE(0, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(13), 13, GFLAGS),
+ DIV(0, "hclk_hevc", "aclk_hevc", 0,
+ RK3288_CLKSEL_CON(40), 12, 2, DFLAGS),
+
+ COMPOSITE(0, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(13), 14, GFLAGS),
+ COMPOSITE(0, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(13), 15, GFLAGS),
+
+ COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
+ RK3288_CLKGATE_CON(3), 7, GFLAGS),
+ COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+ RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
+
+ DIV(0, "pclk_pd_alive", "gpll", 0,
+ RK3288_CLKSEL_CON(33), 8, 5, DFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", 0,
+ RK3288_CLKSEL_CON(33), 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(5), 8, GFLAGS),
+
+ COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
+ RK3288_CLKSEL_CON(34), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(5), 7, GFLAGS),
+
+ COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(2), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_src", 0,
+ RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK3288_CLKGATE_CON(2), 3, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_src", 0,
+ RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+ RK3288_CLKGATE_CON(2), 2, GFLAGS),
+ GATE(0, "aclk_peri", "aclk_peri_src", 0,
+ RK3288_CLKGATE_CON(2), 1, GFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 3
+ */
+
+ COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(2), 9, GFLAGS),
+ COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(25), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3288_CLKGATE_CON(2), 10, GFLAGS),
+ COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(39), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(2), 11, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+ RK3288_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3288_CLKGATE_CON(13), 0, GFLAGS),
+ COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+ RK3288_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3288_CLKGATE_CON(13), 1, GFLAGS),
+ COMPOSITE(SCLK_SDIO1, "sclk_sdio1", mux_mmc_src_p, 0,
+ RK3288_CLKSEL_CON(34), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3288_CLKGATE_CON(13), 2, GFLAGS),
+ COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+ RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3288_CLKGATE_CON(13), 3, GFLAGS),
+
+ COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0,
+ RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(4), 11, GFLAGS),
+ COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(4), 10, GFLAGS),
+
+ GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0,
+ RK3288_CLKGATE_CON(13), 4, GFLAGS),
+ GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0,
+ RK3288_CLKGATE_CON(13), 5, GFLAGS),
+ GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", 0,
+ RK3288_CLKGATE_CON(13), 6, GFLAGS),
+ GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", 0,
+ RK3288_CLKGATE_CON(13), 7, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+ RK3288_CLKSEL_CON(2), 0, 6, DFLAGS,
+ RK3288_CLKGATE_CON(2), 7, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+ RK3288_CLKSEL_CON(24), 8, 8, DFLAGS,
+ RK3288_CLKGATE_CON(2), 8, GFLAGS),
+
+ GATE(SCLK_PS2C, "sclk_ps2c", "xin24m", 0,
+ RK3288_CLKGATE_CON(5), 13, GFLAGS),
+
+ COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(38), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3288_CLKGATE_CON(5), 5, GFLAGS),
+ COMPOSITE(SCLK_NANDC1, "sclk_nandc1", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(38), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(5), 6, GFLAGS),
+
+ COMPOSITE(0, "uart0_src", mux_uart0_pll_p, 0,
+ RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0,
+ RK3288_CLKSEL_CON(17), 0,
+ RK3288_CLKGATE_CON(1), 9, GFLAGS),
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, 0,
+ RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
+ MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+ RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(1), 10, GFLAGS),
+ COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", 0,
+ RK3288_CLKSEL_CON(18), 0,
+ RK3288_CLKGATE_CON(1), 11, GFLAGS),
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, 0,
+ RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+ RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", 0,
+ RK3288_CLKSEL_CON(19), 0,
+ RK3288_CLKGATE_CON(1), 13, GFLAGS),
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, 0,
+ RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+ RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(1), 14, GFLAGS),
+ COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", 0,
+ RK3288_CLKSEL_CON(20), 0,
+ RK3288_CLKGATE_CON(1), 15, GFLAGS),
+ MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, 0,
+ RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+ RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
+ RK3288_CLKGATE_CON(2), 12, GFLAGS),
+ COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", 0,
+ RK3288_CLKSEL_CON(7), 0,
+ RK3288_CLKGATE_CON(2), 13, GFLAGS),
+ MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, 0,
+ RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
+
+ COMPOSITE(0, "mac_src", mux_pll_src_npll_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3288_CLKGATE_CON(2), 5, GFLAGS),
+ MUX(0, "macref", mux_macref_p, 0,
+ RK3288_CLKSEL_CON(21), 4, 1, MFLAGS),
+ GATE(0, "sclk_macref_out", "macref", 0,
+ RK3288_CLKGATE_CON(5), 3, GFLAGS),
+ GATE(SCLK_MACREF, "sclk_macref", "macref", 0,
+ RK3288_CLKGATE_CON(5), 2, GFLAGS),
+ GATE(SCLK_MAC_RX, "sclk_mac_rx", "macref", 0,
+ RK3288_CLKGATE_CON(5), 0, GFLAGS),
+ GATE(SCLK_MAC_TX, "sclk_mac_tx", "macref", 0,
+ RK3288_CLKGATE_CON(5), 1, GFLAGS),
+
+ COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
+ RK3288_CLKGATE_CON(2), 6, GFLAGS),
+ MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+ RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+
+ GATE(0, "jtag", "ext_jtag", 0,
+ RK3288_CLKGATE_CON(4), 14, GFLAGS),
+
+ COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0,
+ RK3288_CLKSEL_CON(13), 11, 2, MFLAGS,
+ RK3288_CLKGATE_CON(5), 15, GFLAGS),
+ COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+ RK3288_CLKSEL_CON(29), 0, 2, MFLAGS,
+ RK3288_CLKGATE_CON(3), 6, GFLAGS),
+ GATE(0, "hsicphy12m_xin12m", "xin12m", 0,
+ RK3288_CLKGATE_CON(13), 9, GFLAGS),
+ DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0,
+ RK3288_CLKSEL_CON(11), 8, 6, DFLAGS),
+ MUX(SCLK_HSICPHY12M, "sclk_hsicphy12m", mux_hsicphy12m_p, 0,
+ RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+
+ /*
+ * Clock-Architecture Diagram 4
+ */
+
+ /* aclk_cpu gates */
+ GATE(0, "sclk_intmem0", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(0, "sclk_intmem1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 6, GFLAGS),
+ GATE(0, "sclk_intmem2", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 7, GFLAGS),
+ GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 12, GFLAGS),
+ GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 13, GFLAGS),
+ GATE(0, "aclk_intmem", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 4, GFLAGS),
+ GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 6, GFLAGS),
+ GATE(0, "aclk_ccp", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 8, GFLAGS),
+
+ /* hclk_cpu gates */
+ GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK3288_CLKGATE_CON(11), 7, GFLAGS),
+ GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 8, GFLAGS),
+ GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 9, GFLAGS),
+ GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 10, GFLAGS),
+ GATE(HCLK_SPDIF8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 11, GFLAGS),
+
+ /* pclk_cpu gates */
+ GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS),
+ GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS),
+ GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
+ GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
+ GATE(0, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
+ GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
+ GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
+ GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
+ GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS),
+
+ /* ddrctrl [DDR Controller PHY clock] gates */
+ GATE(0, "nclk_ddrupctl0", "ddrphy", 0, RK3288_CLKGATE_CON(11), 4, GFLAGS),
+ GATE(0, "nclk_ddrupctl1", "ddrphy", 0, RK3288_CLKGATE_CON(11), 5, GFLAGS),
+
+ /* ddrphy gates */
+ GATE(0, "sclk_ddrphy0", "ddrphy", 0, RK3288_CLKGATE_CON(4), 12, GFLAGS),
+ GATE(0, "sclk_ddrphy1", "ddrphy", 0, RK3288_CLKGATE_CON(4), 13, GFLAGS),
+
+ /* aclk_peri gates */
+ GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 2, GFLAGS),
+ GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS),
+ GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS),
+ GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 12, GFLAGS),
+ GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS),
+ GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS),
+
+ /* hclk_peri gates */
+ GATE(0, "hclk_peri_matrix", "hclk_peri", 0, RK3288_CLKGATE_CON(6), 0, GFLAGS),
+ GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 4, GFLAGS),
+ GATE(HCLK_USBHOST0, "hclk_host0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(HCLK_USBHOST1, "hclk_host1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 7, GFLAGS),
+ GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 8, GFLAGS),
+ GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 9, GFLAGS),
+ GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 10, GFLAGS),
+ GATE(0, "hclk_emem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 12, GFLAGS),
+ GATE(0, "hclk_mem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 13, GFLAGS),
+ GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 14, GFLAGS),
+ GATE(HCLK_NANDC1, "hclk_nandc1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 15, GFLAGS),
+ GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 8, GFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 3, GFLAGS),
+ GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 4, GFLAGS),
+ GATE(HCLK_SDIO1, "hclk_sdio1", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 5, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 6, GFLAGS),
+ GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 7, GFLAGS),
+ GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 5, GFLAGS),
+
+ /* pclk_peri gates */
+ GATE(0, "pclk_peri_matrix", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 1, GFLAGS),
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 4, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 5, GFLAGS),
+ GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 6, GFLAGS),
+ GATE(PCLK_PS2C, "pclk_ps2c", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 7, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 8, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 9, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS),
+ GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS),
+ GATE(PCLK_SIM, "pclk_sim", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 3, GFLAGS),
+ GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 0, GFLAGS),
+ GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3288_CLKGATE_CON(8), 1, GFLAGS),
+
+ GATE(SCLK_LCDC_PWM0, "sclk_lcdc_pwm0", "xin24m", 0, RK3288_CLKGATE_CON(13), 10, GFLAGS),
+ GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
+ GATE(0, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
+ GATE(0, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
+ GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
+
+ /* sclk_gpu gates */
+ GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS),
+
+ /* pclk_pd_alive gates */
+ GATE(PCLK_GPIO8, "pclk_gpio8", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 8, GFLAGS),
+ GATE(PCLK_GPIO7, "pclk_gpio7", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 7, GFLAGS),
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 1, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 2, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 3, GFLAGS),
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 4, GFLAGS),
+ GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS),
+ GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS),
+ GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 11, GFLAGS),
+ GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS),
+
+ /* pclk_pd_pmu gates */
+ GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 0, GFLAGS),
+ GATE(0, "pclk_intmem1", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 1, GFLAGS),
+ GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS),
+ GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 3, GFLAGS),
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS),
+
+ /* hclk_vio gates */
+ GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS),
+ GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS),
+ GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(0, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS),
+ GATE(0, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(0, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS),
+ GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS),
+ GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS),
+ GATE(0, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS),
+ GATE(0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS),
+ GATE(0, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS),
+ GATE(0, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS),
+ GATE(0, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS),
+ GATE(0, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS),
+ GATE(0, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS),
+ GATE(0, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS),
+
+ /* aclk_vio0 gates */
+ GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(0, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS),
+ GATE(0, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS),
+ GATE(0, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS),
+
+ /* aclk_vio1 gates */
+ GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS),
+ GATE(0, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(0, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS),
+
+ /* aclk_rga_pre gates */
+ GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS),
+
+ /*
+ * Other ungrouped clocks.
+ */
+
+ GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+};
+
+static void __init rk3288_clk_init(struct device_node *np)
+{
+ void __iomem *reg_base;
+ struct clk *clk;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+ /* xin12m is created by an cru-internal divider */
+ clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock xin12m: %ld\n",
+ __func__, PTR_ERR(clk));
+
+
+ clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
+ if (IS_ERR(clk))
+ pr_warn("%s: could not register clock usb480m: %ld\n",
+ __func__, PTR_ERR(clk));
+
+ rockchip_clk_register_plls(rk3288_pll_clks,
+ ARRAY_SIZE(rk3288_pll_clks),
+ RK3288_GRF_SOC_STATUS);
+ rockchip_clk_register_branches(rk3288_clk_branches,
+ ARRAY_SIZE(rk3288_clk_branches));
+
+ rockchip_register_softrst(np, 9, reg_base + RK3288_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
+CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
new file mode 100644
index 000000000000..278cf9dd1e23
--- /dev/null
+++ b/drivers/clk/rockchip/clk.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on
+ *
+ * samsung/clk.c
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include "clk.h"
+
+/**
+ * Register a clock branch.
+ * Most clock branches have a form like
+ *
+ * src1 --|--\
+ * |M |--[GATE]-[DIV]-
+ * src2 --|--/
+ *
+ * sometimes without one of those components.
+ */
+struct clk *rockchip_clk_register_branch(const char *name,
+ const char **parent_names, u8 num_parents, void __iomem *base,
+ int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
+ u8 div_shift, u8 div_width, u8 div_flags,
+ struct clk_div_table *div_table, int gate_offset,
+ u8 gate_shift, u8 gate_flags, unsigned long flags,
+ spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_mux *mux = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_divider *div = NULL;
+ const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
+ *gate_ops = NULL;
+
+ if (num_parents > 1) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = base + muxdiv_offset;
+ mux->shift = mux_shift;
+ mux->mask = BIT(mux_width) - 1;
+ mux->flags = mux_flags;
+ mux->lock = lock;
+ mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
+ : &clk_mux_ops;
+ }
+
+ if (gate_offset >= 0) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->flags = gate_flags;
+ gate->reg = base + gate_offset;
+ gate->bit_idx = gate_shift;
+ gate->lock = lock;
+ gate_ops = &clk_gate_ops;
+ }
+
+ if (div_width > 0) {
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->flags = div_flags;
+ div->reg = base + muxdiv_offset;
+ div->shift = div_shift;
+ div->width = div_width;
+ div->lock = lock;
+ div->table = div_table;
+ div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
+ ? &clk_divider_ro_ops
+ : &clk_divider_ops;
+ }
+
+ clk = clk_register_composite(NULL, name, parent_names, num_parents,
+ mux ? &mux->hw : NULL, mux_ops,
+ div ? &div->hw : NULL, div_ops,
+ gate ? &gate->hw : NULL, gate_ops,
+ flags);
+
+ return clk;
+}
+
+static DEFINE_SPINLOCK(clk_lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+static struct clk_onecell_data clk_data;
+static struct device_node *cru_node;
+static struct regmap *grf;
+
+void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
+ unsigned long nr_clks)
+{
+ reg_base = base;
+ cru_node = np;
+ grf = ERR_PTR(-EPROBE_DEFER);
+
+ clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
+ if (!clk_table)
+ pr_err("%s: could not allocate clock lookup table\n", __func__);
+
+ clk_data.clks = clk_table;
+ clk_data.clk_num = nr_clks;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+struct regmap *rockchip_clk_get_grf(void)
+{
+ if (IS_ERR(grf))
+ grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf");
+ return grf;
+}
+
+void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+ if (clk_table && id)
+ clk_table[id] = clk;
+}
+
+void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
+ unsigned int nr_pll, int grf_lock_offset)
+{
+ struct clk *clk;
+ int idx;
+
+ for (idx = 0; idx < nr_pll; idx++, list++) {
+ clk = rockchip_clk_register_pll(list->type, list->name,
+ list->parent_names, list->num_parents,
+ reg_base, list->con_offset, grf_lock_offset,
+ list->lock_shift, list->mode_offset,
+ list->mode_shift, list->rate_table, &clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ list->name);
+ continue;
+ }
+
+ rockchip_clk_add_lookup(clk, list->id);
+ }
+}
+
+void __init rockchip_clk_register_branches(
+ struct rockchip_clk_branch *list,
+ unsigned int nr_clk)
+{
+ struct clk *clk = NULL;
+ unsigned int idx;
+ unsigned long flags;
+
+ for (idx = 0; idx < nr_clk; idx++, list++) {
+ flags = list->flags;
+
+ /* catch simple muxes */
+ switch (list->branch_type) {
+ case branch_mux:
+ clk = clk_register_mux(NULL, list->name,
+ list->parent_names, list->num_parents,
+ flags, reg_base + list->muxdiv_offset,
+ list->mux_shift, list->mux_width,
+ list->mux_flags, &clk_lock);
+ break;
+ case branch_divider:
+ if (list->div_table)
+ clk = clk_register_divider_table(NULL,
+ list->name, list->parent_names[0],
+ flags, reg_base + list->muxdiv_offset,
+ list->div_shift, list->div_width,
+ list->div_flags, list->div_table,
+ &clk_lock);
+ else
+ clk = clk_register_divider(NULL, list->name,
+ list->parent_names[0], flags,
+ reg_base + list->muxdiv_offset,
+ list->div_shift, list->div_width,
+ list->div_flags, &clk_lock);
+ break;
+ case branch_fraction_divider:
+ /* unimplemented */
+ continue;
+ break;
+ case branch_gate:
+ flags |= CLK_SET_RATE_PARENT;
+
+ /* keep all gates untouched for now */
+ flags |= CLK_IGNORE_UNUSED;
+
+ clk = clk_register_gate(NULL, list->name,
+ list->parent_names[0], flags,
+ reg_base + list->gate_offset,
+ list->gate_shift, list->gate_flags, &clk_lock);
+ break;
+ case branch_composite:
+ /* keep all gates untouched for now */
+ flags |= CLK_IGNORE_UNUSED;
+
+ clk = rockchip_clk_register_branch(list->name,
+ list->parent_names, list->num_parents,
+ reg_base, list->muxdiv_offset, list->mux_shift,
+ list->mux_width, list->mux_flags,
+ list->div_shift, list->div_width,
+ list->div_flags, list->div_table,
+ list->gate_offset, list->gate_shift,
+ list->gate_flags, flags, &clk_lock);
+ break;
+ }
+
+ /* none of the cases above matched */
+ if (!clk) {
+ pr_err("%s: unknown clock type %d\n",
+ __func__, list->branch_type);
+ continue;
+ }
+
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s: %ld\n",
+ __func__, list->name, PTR_ERR(clk));
+ continue;
+ }
+
+ rockchip_clk_add_lookup(clk, list->id);
+ }
+}
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
new file mode 100644
index 000000000000..887cbdeca2aa
--- /dev/null
+++ b/drivers/clk/rockchip/clk.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on
+ *
+ * samsung/clk.h
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef CLK_ROCKCHIP_CLK_H
+#define CLK_ROCKCHIP_CLK_H
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define HIWORD_UPDATE(val, mask, shift) \
+ ((val) << (shift) | (mask) << ((shift) + 16))
+
+/* register positions shared by RK2928, RK3066 and RK3188 */
+#define RK2928_PLL_CON(x) (x * 0x4)
+#define RK2928_MODE_CON 0x40
+#define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0)
+#define RK2928_GLB_SRST_FST 0x100
+#define RK2928_GLB_SRST_SND 0x104
+#define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110)
+#define RK2928_MISC_CON 0x134
+
+#define RK3288_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3288_MODE_CON 0x50
+#define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160)
+#define RK3288_GLB_SRST_FST 0x1b0
+#define RK3288_GLB_SRST_SND 0x1b4
+#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8)
+#define RK3288_MISC_CON 0x1e8
+
+enum rockchip_pll_type {
+ pll_rk3066,
+};
+
+#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
+{ \
+ .rate = _rate##U, \
+ .nr = _nr, \
+ .nf = _nf, \
+ .no = _no, \
+ .bwadj = (_nf >> 1), \
+}
+
+struct rockchip_pll_rate_table {
+ unsigned long rate;
+ unsigned int nr;
+ unsigned int nf;
+ unsigned int no;
+ unsigned int bwadj;
+};
+
+/**
+ * struct rockchip_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @mode_offset: offset of the register for configuring the PLL-mode.
+ * @mode_shift: offset inside the mode-register for the mode of this pll.
+ * @lock_shift: offset inside the lock register for the lock status.
+ * @type: Type of PLL to be registered.
+ * @rate_table: Table of usable pll rates
+ */
+struct rockchip_pll_clock {
+ unsigned int id;
+ const char *name;
+ const char **parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ int con_offset;
+ int mode_offset;
+ int mode_shift;
+ int lock_shift;
+ enum rockchip_pll_type type;
+ struct rockchip_pll_rate_table *rate_table;
+};
+
+#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \
+ _lshift, _rtable) \
+ { \
+ .id = _id, \
+ .type = _type, \
+ .name = _name, \
+ .parent_names = _pnames, \
+ .num_parents = ARRAY_SIZE(_pnames), \
+ .flags = CLK_GET_RATE_NOCACHE | _flags, \
+ .con_offset = _con, \
+ .mode_offset = _mode, \
+ .mode_shift = _mshift, \
+ .lock_shift = _lshift, \
+ .rate_table = _rtable, \
+ }
+
+struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+ const char *name, const char **parent_names, u8 num_parents,
+ void __iomem *base, int con_offset, int grf_lock_offset,
+ int lock_shift, int reg_mode, int mode_shift,
+ struct rockchip_pll_rate_table *rate_table,
+ spinlock_t *lock);
+
+#define PNAME(x) static const char *x[] __initconst
+
+enum rockchip_clk_branch_type {
+ branch_composite,
+ branch_mux,
+ branch_divider,
+ branch_fraction_divider,
+ branch_gate,
+};
+
+struct rockchip_clk_branch {
+ unsigned int id;
+ enum rockchip_clk_branch_type branch_type;
+ const char *name;
+ const char **parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ int muxdiv_offset;
+ u8 mux_shift;
+ u8 mux_width;
+ u8 mux_flags;
+ u8 div_shift;
+ u8 div_width;
+ u8 div_flags;
+ struct clk_div_table *div_table;
+ int gate_offset;
+ u8 gate_shift;
+ u8 gate_flags;
+};
+
+#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
+ df, go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
+ go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
+ df, dt, go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .div_table = dt, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \
+ go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
+ ds, dw, df) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = -1, \
+ }
+
+#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
+ { \
+ .id = _id, \
+ .branch_type = branch_fraction_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = 16, \
+ .div_width = 16, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+#define MUX(_id, cname, pnames, f, o, s, w, mf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_mux, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .mux_shift = s, \
+ .mux_width = w, \
+ .mux_flags = mf, \
+ .gate_offset = -1, \
+ }
+
+#define DIV(_id, cname, pname, f, o, s, w, df) \
+ { \
+ .id = _id, \
+ .branch_type = branch_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .div_shift = s, \
+ .div_width = w, \
+ .div_flags = df, \
+ .gate_offset = -1, \
+ }
+
+#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \
+ { \
+ .id = _id, \
+ .branch_type = branch_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .div_shift = s, \
+ .div_width = w, \
+ .div_flags = df, \
+ .div_table = dt, \
+ }
+
+#define GATE(_id, cname, pname, f, o, b, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_gate, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .gate_offset = o, \
+ .gate_shift = b, \
+ .gate_flags = gf, \
+ }
+
+
+void rockchip_clk_init(struct device_node *np, void __iomem *base,
+ unsigned long nr_clks);
+struct regmap *rockchip_clk_get_grf(void);
+void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
+void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
+ unsigned int nr_clk);
+void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
+ unsigned int nr_pll, int grf_lock_offset);
+
+#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
+
+#ifdef CONFIG_RESET_CONTROLLER
+void rockchip_register_softrst(struct device_node *np,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags);
+#else
+static inline void rockchip_register_softrst(struct device_node *np,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c
new file mode 100644
index 000000000000..552f7bb15bc5
--- /dev/null
+++ b/drivers/clk/rockchip/softrst.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_softrst {
+ struct reset_controller_dev rcdev;
+ void __iomem *reg_base;
+ int num_regs;
+ int num_per_reg;
+ u8 flags;
+ spinlock_t lock;
+};
+
+static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rockchip_softrst *softrst = container_of(rcdev,
+ struct rockchip_softrst,
+ rcdev);
+ int bank = id / softrst->num_per_reg;
+ int offset = id % softrst->num_per_reg;
+
+ if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+ writel(BIT(offset) | (BIT(offset) << 16),
+ softrst->reg_base + (bank * 4));
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&softrst->lock, flags);
+
+ reg = readl(softrst->reg_base + (bank * 4));
+ writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
+
+ spin_unlock_irqrestore(&softrst->lock, flags);
+ }
+
+ return 0;
+}
+
+static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rockchip_softrst *softrst = container_of(rcdev,
+ struct rockchip_softrst,
+ rcdev);
+ int bank = id / softrst->num_per_reg;
+ int offset = id % softrst->num_per_reg;
+
+ if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+ writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&softrst->lock, flags);
+
+ reg = readl(softrst->reg_base + (bank * 4));
+ writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
+
+ spin_unlock_irqrestore(&softrst->lock, flags);
+ }
+
+ return 0;
+}
+
+static struct reset_control_ops rockchip_softrst_ops = {
+ .assert = rockchip_softrst_assert,
+ .deassert = rockchip_softrst_deassert,
+};
+
+void __init rockchip_register_softrst(struct device_node *np,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+ struct rockchip_softrst *softrst;
+ int ret;
+
+ softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
+ if (!softrst)
+ return;
+
+ spin_lock_init(&softrst->lock);
+
+ softrst->reg_base = base;
+ softrst->flags = flags;
+ softrst->num_regs = num_regs;
+ softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
+ : 32;
+
+ softrst->rcdev.owner = THIS_MODULE;
+ softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
+ softrst->rcdev.ops = &rockchip_softrst_ops;
+ softrst->rcdev.of_node = np;
+ ret = reset_controller_register(&softrst->rcdev);
+ if (ret) {
+ pr_err("%s: could not register reset controller, %d\n",
+ __func__, ret);
+ kfree(softrst);
+ }
+};
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 69e81773164e..6fb4bc602e8a 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -11,8 +11,10 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
+obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
+obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o
diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
new file mode 100644
index 000000000000..3a7cb2506731
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Tomasz Figa <t.figa@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Clock driver for Exynos clock output
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define EXYNOS_CLKOUT_NR_CLKS 1
+#define EXYNOS_CLKOUT_PARENTS 32
+
+#define EXYNOS_PMU_DEBUG_REG 0xa00
+#define EXYNOS_CLKOUT_DISABLE_SHIFT 0
+#define EXYNOS_CLKOUT_MUX_SHIFT 8
+#define EXYNOS4_CLKOUT_MUX_MASK 0xf
+#define EXYNOS5_CLKOUT_MUX_MASK 0x1f
+
+struct exynos_clkout {
+ struct clk_gate gate;
+ struct clk_mux mux;
+ spinlock_t slock;
+ struct clk_onecell_data data;
+ struct clk *clk_table[EXYNOS_CLKOUT_NR_CLKS];
+ void __iomem *reg;
+ u32 pmu_debug_save;
+};
+
+static struct exynos_clkout *clkout;
+
+static int exynos_clkout_suspend(void)
+{
+ clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
+
+ return 0;
+}
+
+static void exynos_clkout_resume(void)
+{
+ writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
+}
+
+static struct syscore_ops exynos_clkout_syscore_ops = {
+ .suspend = exynos_clkout_suspend,
+ .resume = exynos_clkout_resume,
+};
+
+static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
+{
+ const char *parent_names[EXYNOS_CLKOUT_PARENTS];
+ struct clk *parents[EXYNOS_CLKOUT_PARENTS];
+ int parent_count;
+ int ret;
+ int i;
+
+ clkout = kzalloc(sizeof(*clkout), GFP_KERNEL);
+ if (!clkout)
+ return;
+
+ spin_lock_init(&clkout->slock);
+
+ parent_count = 0;
+ for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i) {
+ char name[] = "clkoutXX";
+
+ snprintf(name, sizeof(name), "clkout%d", i);
+ parents[i] = of_clk_get_by_name(node, name);
+ if (IS_ERR(parents[i])) {
+ parent_names[i] = "none";
+ continue;
+ }
+
+ parent_names[i] = __clk_get_name(parents[i]);
+ parent_count = i + 1;
+ }
+
+ if (!parent_count)
+ goto free_clkout;
+
+ clkout->reg = of_iomap(node, 0);
+ if (!clkout->reg)
+ goto clks_put;
+
+ clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
+ clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT;
+ clkout->gate.flags = CLK_GATE_SET_TO_DISABLE;
+ clkout->gate.lock = &clkout->slock;
+
+ clkout->mux.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
+ clkout->mux.mask = mux_mask;
+ clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT;
+ clkout->mux.lock = &clkout->slock;
+
+ clkout->clk_table[0] = clk_register_composite(NULL, "clkout",
+ parent_names, parent_count, &clkout->mux.hw,
+ &clk_mux_ops, NULL, NULL, &clkout->gate.hw,
+ &clk_gate_ops, CLK_SET_RATE_PARENT
+ | CLK_SET_RATE_NO_REPARENT);
+ if (IS_ERR(clkout->clk_table[0]))
+ goto err_unmap;
+
+ clkout->data.clks = clkout->clk_table;
+ clkout->data.clk_num = EXYNOS_CLKOUT_NR_CLKS;
+ ret = of_clk_add_provider(node, of_clk_src_onecell_get, &clkout->data);
+ if (ret)
+ goto err_clk_unreg;
+
+ register_syscore_ops(&exynos_clkout_syscore_ops);
+
+ return;
+
+err_clk_unreg:
+ clk_unregister(clkout->clk_table[0]);
+err_unmap:
+ iounmap(clkout->reg);
+clks_put:
+ for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i)
+ if (!IS_ERR(parents[i]))
+ clk_put(parents[i]);
+free_clkout:
+ kfree(clkout);
+
+ pr_err("%s: failed to register clkout clock\n", __func__);
+}
+
+static void __init exynos4_clkout_init(struct device_node *node)
+{
+ exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK);
+}
+CLK_OF_DECLARE(exynos4210_clkout, "samsung,exynos4210-pmu",
+ exynos4_clkout_init);
+CLK_OF_DECLARE(exynos4212_clkout, "samsung,exynos4212-pmu",
+ exynos4_clkout_init);
+CLK_OF_DECLARE(exynos4412_clkout, "samsung,exynos4412-pmu",
+ exynos4_clkout_init);
+
+static void __init exynos5_clkout_init(struct device_node *node)
+{
+ exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK);
+}
+CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
+ exynos5_clkout_init);
+CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
+ exynos5_clkout_init);
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 7a17bd40d1dd..dc85f8e7a2d7 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -87,6 +87,22 @@
#define SRC_CPU 0x14200
#define DIV_CPU0 0x14500
#define DIV_CPU1 0x14504
+#define PWR_CTRL1 0x15020
+#define PWR_CTRL2 0x15024
+
+/* Below definitions are used for PWR_CTRL settings */
+#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
+#define PWR_CTRL1_USE_CORE3_WFE (1 << 7)
+#define PWR_CTRL1_USE_CORE2_WFE (1 << 6)
+#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
+#define PWR_CTRL1_USE_CORE3_WFI (1 << 3)
+#define PWR_CTRL1_USE_CORE2_WFI (1 << 2)
+#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
/* list of PLLs to be registered */
enum exynos3250_plls {
@@ -168,6 +184,8 @@ static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
SRC_CPU,
DIV_CPU0,
DIV_CPU1,
+ PWR_CTRL1,
+ PWR_CTRL2,
};
static int exynos3250_clk_suspend(void)
@@ -748,6 +766,27 @@ static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = {
UPLL_LOCK, UPLL_CON0, NULL),
};
+static void __init exynos3_core_down_clock(void)
+{
+ unsigned int tmp;
+
+ /*
+ * Enable arm clock down (in idle) and set arm divider
+ * ratios in WFI/WFE state.
+ */
+ tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
+ PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
+ PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
+ PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
+ __raw_writel(tmp, reg_base + PWR_CTRL1);
+
+ /*
+ * Disable the clock up feature on Exynos4x12, in case it was
+ * enabled by bootloader.
+ */
+ __raw_writel(0x0, reg_base + PWR_CTRL2);
+}
+
static void __init exynos3250_cmu_init(struct device_node *np)
{
struct samsung_clk_provider *ctx;
@@ -775,6 +814,10 @@ static void __init exynos3250_cmu_init(struct device_node *np)
samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
+ exynos3_core_down_clock();
+
exynos3250_clk_sleep_init();
+
+ samsung_clk_of_add_provider(np, ctx);
}
CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 7f4a473a7ad7..ac163d7f5bc3 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -25,10 +25,12 @@
#define DIV_LEFTBUS 0x4500
#define GATE_IP_LEFTBUS 0x4800
#define E4X12_GATE_IP_IMAGE 0x4930
+#define CLKOUT_CMU_LEFTBUS 0x4a00
#define SRC_RIGHTBUS 0x8200
#define DIV_RIGHTBUS 0x8500
#define GATE_IP_RIGHTBUS 0x8800
#define E4X12_GATE_IP_PERIR 0x8960
+#define CLKOUT_CMU_RIGHTBUS 0x8a00
#define EPLL_LOCK 0xc010
#define VPLL_LOCK 0xc020
#define EPLL_CON0 0xc110
@@ -98,6 +100,7 @@
#define GATE_IP_PERIL 0xc950
#define E4210_GATE_IP_PERIR 0xc960
#define GATE_BLOCK 0xc970
+#define CLKOUT_CMU_TOP 0xca00
#define E4X12_MPLL_LOCK 0x10008
#define E4X12_MPLL_CON0 0x10108
#define SRC_DMC 0x10200
@@ -105,6 +108,7 @@
#define DIV_DMC0 0x10500
#define DIV_DMC1 0x10504
#define GATE_IP_DMC 0x10900
+#define CLKOUT_CMU_DMC 0x10a00
#define APLL_LOCK 0x14000
#define E4210_MPLL_LOCK 0x14008
#define APLL_CON0 0x14100
@@ -114,11 +118,28 @@
#define DIV_CPU1 0x14504
#define GATE_SCLK_CPU 0x14800
#define GATE_IP_CPU 0x14900
+#define CLKOUT_CMU_CPU 0x14a00
+#define PWR_CTRL1 0x15020
+#define E4X12_PWR_CTRL2 0x15024
#define E4X12_DIV_ISP0 0x18300
#define E4X12_DIV_ISP1 0x18304
#define E4X12_GATE_ISP0 0x18800
#define E4X12_GATE_ISP1 0x18804
+/* Below definitions are used for PWR_CTRL settings */
+#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
+#define PWR_CTRL1_USE_CORE3_WFE (1 << 7)
+#define PWR_CTRL1_USE_CORE2_WFE (1 << 6)
+#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
+#define PWR_CTRL1_USE_CORE3_WFI (1 << 3)
+#define PWR_CTRL1_USE_CORE2_WFI (1 << 2)
+#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
+
/* the exynos4 soc type */
enum exynos4_soc {
EXYNOS4210,
@@ -155,6 +176,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
E4210_GATE_IP_LCD1,
E4210_GATE_IP_PERIR,
E4210_MPLL_CON0,
+ PWR_CTRL1,
};
static unsigned long exynos4x12_clk_save[] __initdata = {
@@ -164,6 +186,8 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
E4X12_DIV_ISP,
E4X12_DIV_CAM1,
E4X12_MPLL_CON0,
+ PWR_CTRL1,
+ E4X12_PWR_CTRL2,
};
static unsigned long exynos4_clk_pll_regs[] __initdata = {
@@ -242,6 +266,11 @@ static unsigned long exynos4_clk_regs[] __initdata = {
DIV_CPU1,
GATE_SCLK_CPU,
GATE_IP_CPU,
+ CLKOUT_CMU_LEFTBUS,
+ CLKOUT_CMU_RIGHTBUS,
+ CLKOUT_CMU_TOP,
+ CLKOUT_CMU_DMC,
+ CLKOUT_CMU_CPU,
};
static const struct samsung_clk_reg_dump src_mask_suspend[] = {
@@ -397,10 +426,32 @@ PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m",
"sclk_epll", "sclk_vpll", };
PNAME(mout_mixer_p4210) = { "sclk_dac", "sclk_hdmi", };
PNAME(mout_dac_p4210) = { "sclk_vpll", "sclk_hdmiphy", };
+PNAME(mout_pwi_p4210) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+ "sclk_usbphy1", "sclk_hdmiphy", "none",
+ "sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+ "div_gdl", "div_gpl" };
+PNAME(clkout_right_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2",
+ "div_gdr", "div_gpr" };
+PNAME(clkout_top_p4210) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+ "sclk_usbphy0", "sclk_usbphy1", "sclk_hdmiphy",
+ "cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+ "aclk160", "aclk133", "aclk200", "aclk100",
+ "sclk_mfc", "sclk_g3d", "sclk_g2d",
+ "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+ "s_rxbyteclkhs0_4l" };
+PNAME(clkout_dmc_p4210) = { "div_dmcd", "div_dmcp", "div_acp_pclk", "div_dmc",
+ "div_dphy", "none", "div_pwi" };
+PNAME(clkout_cpu_p4210) = { "fout_apll_div_2", "none", "fout_mpll_div_2",
+ "none", "arm_clk_div_2", "div_corem0",
+ "div_corem1", "div_corem0", "div_atb",
+ "div_periph", "div_pclk_dbg", "div_hpm" };
/* Exynos 4x12-specific parent groups */
PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", };
PNAME(mout_core_p4x12) = { "mout_apll", "mout_mpll_user_c", };
+PNAME(mout_gdl_p4x12) = { "mout_mpll_user_l", "sclk_apll", };
+PNAME(mout_gdr_p4x12) = { "mout_mpll_user_r", "sclk_apll", };
PNAME(sclk_ampll_p4x12) = { "mout_mpll_user_t", "sclk_apll", };
PNAME(group1_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
"none", "sclk_hdmiphy", "mout_mpll_user_t",
@@ -418,6 +469,32 @@ PNAME(aclk_p4412) = { "mout_mpll_user_t", "sclk_apll", };
PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", };
PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
+PNAME(mout_pwi_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+ "none", "sclk_hdmiphy", "sclk_mpll",
+ "sclk_epll", "sclk_vpll" };
+PNAME(clkout_left_p4x12) = { "sclk_mpll_user_l_div_2", "sclk_apll_div_2",
+ "div_gdl", "div_gpl" };
+PNAME(clkout_right_p4x12) = { "sclk_mpll_user_r_div_2", "sclk_apll_div_2",
+ "div_gdr", "div_gpr" };
+PNAME(clkout_top_p4x12) = { "fout_epll", "fout_vpll", "sclk_hdmi24m",
+ "sclk_usbphy0", "none", "sclk_hdmiphy",
+ "cdclk0", "cdclk1", "cdclk2", "spdif_extclk",
+ "aclk160", "aclk133", "aclk200", "aclk100",
+ "sclk_mfc", "sclk_g3d", "aclk400_mcuisp",
+ "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l",
+ "s_rxbyteclkhs0_4l", "rx_half_byte_clk_csis0",
+ "rx_half_byte_clk_csis1", "div_jpeg",
+ "sclk_pwm_isp", "sclk_spi0_isp",
+ "sclk_spi1_isp", "sclk_uart_isp",
+ "sclk_mipihsi", "sclk_hdmi", "sclk_fimd0",
+ "sclk_pcm0" };
+PNAME(clkout_dmc_p4x12) = { "div_dmcd", "div_dmcp", "aclk_acp", "div_acp_pclk",
+ "div_dmc", "div_dphy", "fout_mpll_div_2",
+ "div_pwi", "none", "div_c2c", "div_c2c_aclk" };
+PNAME(clkout_cpu_p4x12) = { "fout_apll_div_2", "none", "none", "none",
+ "arm_clk_div_2", "div_corem0", "div_corem1",
+ "div_cores", "div_atb", "div_periph",
+ "div_pclk_dbg", "div_hpm" };
/* fixed rate clocks generated outside the soc */
static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
@@ -436,6 +513,24 @@ static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata =
FRATE(0, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
};
+static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = {
+ FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
+ FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
+ FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
+ FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
+ FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0),
+};
+
+static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = {
+ FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0),
+ FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0),
+ FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0),
+ FFACTOR(0, "sclk_mpll_user_c_div_2", "mout_mpll_user_c", 1, 2, 0),
+};
+
/* list of mux clocks supported in all exynos4 soc's */
static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
@@ -451,6 +546,9 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
MUX(0, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
MUX(CLK_SCLK_EPLL, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1),
MUX(0, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
+
+ MUX(0, "mout_dmc_bus", sclk_ampll_p4210, SRC_DMC, 4, 1),
+ MUX(0, "mout_dphy", sclk_ampll_p4210, SRC_DMC, 8, 1),
};
/* list of mux clocks supported in exynos4210 soc */
@@ -459,6 +557,14 @@ static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
};
static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+ MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1),
+ MUX(0, "mout_clkout_leftbus", clkout_left_p4210,
+ CLKOUT_CMU_LEFTBUS, 0, 5),
+
+ MUX(0, "mout_gdr", sclk_ampll_p4210, SRC_RIGHTBUS, 0, 1),
+ MUX(0, "mout_clkout_rightbus", clkout_right_p4210,
+ CLKOUT_CMU_RIGHTBUS, 0, 5),
+
MUX(0, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
@@ -472,6 +578,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1),
MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1),
+ MUX(0, "mout_hpm", mout_core_p4210, SRC_CPU, 20, 1),
MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1),
MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
@@ -503,12 +610,30 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
MUX(0, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4),
MUX(0, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4),
MUX(0, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4),
+ MUX(0, "mout_clkout_top", clkout_top_p4210, CLKOUT_CMU_TOP, 0, 5),
+
+ MUX(0, "mout_pwi", mout_pwi_p4210, SRC_DMC, 16, 4),
+ MUX(0, "mout_clkout_dmc", clkout_dmc_p4210, CLKOUT_CMU_DMC, 0, 5),
+
+ MUX(0, "mout_clkout_cpu", clkout_cpu_p4210, CLKOUT_CMU_CPU, 0, 5),
};
/* list of mux clocks supported in exynos4x12 soc */
static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+ MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1),
+ MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1),
+ MUX(0, "mout_clkout_leftbus", clkout_left_p4x12,
+ CLKOUT_CMU_LEFTBUS, 0, 5),
+
+ MUX(0, "mout_mpll_user_r", mout_mpll_p, SRC_RIGHTBUS, 4, 1),
+ MUX(0, "mout_gdr", mout_gdr_p4x12, SRC_RIGHTBUS, 0, 1),
+ MUX(0, "mout_clkout_rightbus", clkout_right_p4x12,
+ CLKOUT_CMU_RIGHTBUS, 0, 5),
+
MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p4x12,
SRC_CPU, 24, 1),
+ MUX(0, "mout_clkout_cpu", clkout_cpu_p4x12, CLKOUT_CMU_CPU, 0, 5),
+
MUX(0, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
MUX(0, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
MUX(CLK_MOUT_MPLL_USER_T, "mout_mpll_user_t", mout_mpll_user_p4x12,
@@ -531,6 +656,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1),
MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1),
MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
+ MUX(0, "mout_hpm", mout_core_p4x12, SRC_CPU, 20, 1),
MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
@@ -565,15 +691,39 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
MUX(0, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4),
MUX(0, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4),
MUX(0, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4),
+ MUX(0, "mout_clkout_top", clkout_top_p4x12, CLKOUT_CMU_TOP, 0, 5),
+
+ MUX(0, "mout_c2c", sclk_ampll_p4210, SRC_DMC, 0, 1),
+ MUX(0, "mout_pwi", mout_pwi_p4x12, SRC_DMC, 16, 4),
MUX(0, "mout_g2d0", sclk_ampll_p4210, SRC_DMC, 20, 1),
MUX(0, "mout_g2d1", sclk_evpll_p, SRC_DMC, 24, 1),
MUX(0, "mout_g2d", mout_g2d_p, SRC_DMC, 28, 1),
+ MUX(0, "mout_clkout_dmc", clkout_dmc_p4x12, CLKOUT_CMU_DMC, 0, 5),
};
/* list of divider clocks supported in all exynos4 soc's */
static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+ DIV(0, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
+ DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
+ DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
+ CLKOUT_CMU_LEFTBUS, 8, 6),
+
+ DIV(0, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3),
+ DIV(0, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3),
+ DIV(0, "div_clkout_rightbus", "mout_clkout_rightbus",
+ CLKOUT_CMU_RIGHTBUS, 8, 6),
+
DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
+ DIV(0, "div_corem0", "div_core2", DIV_CPU0, 4, 3),
+ DIV(0, "div_corem1", "div_core2", DIV_CPU0, 8, 3),
+ DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3),
+ DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3),
+ DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3),
DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
+ DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
+ DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3),
+ DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6),
+
DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
@@ -631,6 +781,16 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
CLK_SET_RATE_PARENT, 0),
DIV_F(0, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_clkout_top", "mout_clkout_top", CLKOUT_CMU_TOP, 8, 6),
+
+ DIV(0, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3),
+ DIV(0, "div_acp_pclk", "div_acp", DIV_DMC0, 4, 3),
+ DIV(0, "div_dphy", "mout_dphy", DIV_DMC0, 8, 3),
+ DIV(0, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3),
+ DIV(0, "div_dmcd", "div_dmc", DIV_DMC0, 16, 3),
+ DIV(0, "div_dmcp", "div_dmcd", DIV_DMC0, 20, 3),
+ DIV(0, "div_pwi", "mout_pwi", DIV_DMC1, 8, 4),
+ DIV(0, "div_clkout_dmc", "mout_clkout_dmc", CLKOUT_CMU_DMC, 8, 6),
};
/* list of divider clocks supported in exynos4210 soc */
@@ -671,6 +831,8 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
8, 3, CLK_GET_RATE_NOCACHE, 0),
DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
+ DIV(0, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
+ DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
};
/* list of gate clocks supported in all exynos4 soc's */
@@ -680,6 +842,8 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
* the device name and clock alias names specified below for some
* of the clocks can be removed.
*/
+ GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0),
+ GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0),
GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0,
0),
@@ -695,11 +859,13 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0,
CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0),
GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
GATE(CLK_NFCON, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
GATE(CLK_GPS, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0),
GATE(CLK_SMMU_GPS, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0),
+ GATE(CLK_PPMUGPS, "ppmugps", "aclk200", GATE_IP_GPS, 2, 0, 0),
GATE(CLK_SLIMBUS, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0),
GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4,
CLK_SET_RATE_PARENT, 0),
@@ -781,19 +947,24 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
0, 0),
GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11,
0, 0),
+ GATE(CLK_PPMUCAMIF, "ppmucamif", "aclk160", GATE_IP_CAM, 16, 0, 0),
GATE(CLK_PIXELASYNCM0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
GATE(CLK_PIXELASYNCM1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
GATE(CLK_SMMU_TV, "smmu_tv", "aclk160", GATE_IP_TV, 4,
0, 0),
+ GATE(CLK_PPMUTV, "ppmutv", "aclk160", GATE_IP_TV, 5, 0, 0),
GATE(CLK_MFC, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0),
GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1,
0, 0),
GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2,
0, 0),
+ GATE(CLK_PPMUMFC_L, "ppmumfc_l", "aclk100", GATE_IP_MFC, 3, 0, 0),
+ GATE(CLK_PPMUMFC_R, "ppmumfc_r", "aclk100", GATE_IP_MFC, 4, 0, 0),
GATE(CLK_FIMD0, "fimd0", "aclk160", GATE_IP_LCD0, 0,
0, 0),
GATE(CLK_SMMU_FIMD0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4,
0, 0),
+ GATE(CLK_PPMULCD0, "ppmulcd0", "aclk160", GATE_IP_LCD0, 5, 0, 0),
GATE(CLK_PDMA0, "pdma0", "aclk133", GATE_IP_FSYS, 0,
0, 0),
GATE(CLK_PDMA1, "pdma1", "aclk133", GATE_IP_FSYS, 1,
@@ -806,6 +977,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
0, 0),
GATE(CLK_SDMMC3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8,
0, 0),
+ GATE(CLK_PPMUFILE, "ppmufile", "aclk133", GATE_IP_FSYS, 17, 0, 0),
GATE(CLK_UART0, "uart0", "aclk100", GATE_IP_PERIL, 0,
0, 0),
GATE(CLK_UART1, "uart1", "aclk100", GATE_IP_PERIL, 1,
@@ -852,6 +1024,21 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
0, 0),
GATE(CLK_AC97, "ac97", "aclk100", GATE_IP_PERIL, 27,
0, 0),
+ GATE(CLK_PPMUDMC0, "ppmudmc0", "aclk133", GATE_IP_DMC, 8, 0, 0),
+ GATE(CLK_PPMUDMC1, "ppmudmc1", "aclk133", GATE_IP_DMC, 9, 0, 0),
+ GATE(CLK_PPMUCPU, "ppmucpu", "aclk133", GATE_IP_DMC, 10, 0, 0),
+ GATE(CLK_PPMUACP, "ppmuacp", "aclk133", GATE_IP_DMC, 16, 0, 0),
+
+ GATE(CLK_OUT_LEFTBUS, "clkout_leftbus", "div_clkout_leftbus",
+ CLKOUT_CMU_LEFTBUS, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_OUT_RIGHTBUS, "clkout_rightbus", "div_clkout_rightbus",
+ CLKOUT_CMU_RIGHTBUS, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_OUT_TOP, "clkout_top", "div_clkout_top",
+ CLKOUT_CMU_TOP, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_OUT_DMC, "clkout_dmc", "div_clkout_dmc",
+ CLKOUT_CMU_DMC, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_OUT_CPU, "clkout_cpu", "div_clkout_cpu",
+ CLKOUT_CMU_CPU, 16, CLK_SET_RATE_PARENT, 0),
};
/* list of gate clocks supported in exynos4210 soc */
@@ -863,6 +1050,9 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0),
GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0,
0),
+ GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4210_GATE_IP_IMAGE, 9, 0,
+ 0),
+ GATE(CLK_PPMULCD1, "ppmulcd1", "aclk160", E4210_GATE_IP_LCD1, 5, 0, 0),
GATE(CLK_PCIE_PHY, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0),
GATE(CLK_SATA_PHY, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0),
GATE(CLK_SATA, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0),
@@ -906,6 +1096,8 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0,
0),
+ GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0,
+ 0),
GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
@@ -1062,7 +1254,7 @@ static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx)
}
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
{ .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
{},
@@ -1164,6 +1356,32 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
VPLL_LOCK, VPLL_CON0, NULL),
};
+static void __init exynos4_core_down_clock(enum exynos4_soc soc)
+{
+ unsigned int tmp;
+
+ /*
+ * Enable arm clock down (in idle) and set arm divider
+ * ratios in WFI/WFE state.
+ */
+ tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
+ PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
+ PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
+ PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
+ /* On Exynos4412 enable it also on core 2 and 3 */
+ if (num_possible_cpus() == 4)
+ tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
+ PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
+ __raw_writel(tmp, reg_base + PWR_CTRL1);
+
+ /*
+ * Disable the clock up feature on Exynos4x12, in case it was
+ * enabled by bootloader.
+ */
+ if (exynos4_soc == EXYNOS4X12)
+ __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+}
+
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
enum exynos4_soc soc)
@@ -1224,6 +1442,8 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4_div_clks));
samsung_clk_register_gate(ctx, exynos4_gate_clks,
ARRAY_SIZE(exynos4_gate_clks));
+ samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks,
+ ARRAY_SIZE(exynos4_fixed_factor_clks));
if (exynos4_soc == EXYNOS4210) {
samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
@@ -1236,6 +1456,9 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4210_gate_clks));
samsung_clk_register_alias(ctx, exynos4210_aliases,
ARRAY_SIZE(exynos4210_aliases));
+ samsung_clk_register_fixed_factor(ctx,
+ exynos4210_fixed_factor_clks,
+ ARRAY_SIZE(exynos4210_fixed_factor_clks));
} else {
samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
ARRAY_SIZE(exynos4x12_mux_clks));
@@ -1245,13 +1468,19 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4x12_gate_clks));
samsung_clk_register_alias(ctx, exynos4x12_aliases,
ARRAY_SIZE(exynos4x12_aliases));
+ samsung_clk_register_fixed_factor(ctx,
+ exynos4x12_fixed_factor_clks,
+ ARRAY_SIZE(exynos4x12_fixed_factor_clks));
}
samsung_clk_register_alias(ctx, exynos4_aliases,
ARRAY_SIZE(exynos4_aliases));
+ exynos4_core_down_clock(soc);
exynos4_clk_sleep_init();
+ samsung_clk_of_add_provider(np, ctx);
+
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 184f64293b26..70ec3d2608a1 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -748,7 +748,7 @@ static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
VPLL_LOCK, VPLL_CON0, NULL),
};
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
{ },
};
@@ -820,6 +820,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
exynos5250_clk_sleep_init();
+ samsung_clk_of_add_provider(np, ctx);
+
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
_get_rate("div_arm2"));
}
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index 64596ba58df1..ce3de97e5f11 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -206,6 +206,8 @@ void __init exynos5260_cmu_register_one(struct device_node *np,
if (cmu->clk_regs)
exynos5260_clk_sleep_init(reg_base, cmu->clk_regs,
cmu->nr_clk_regs);
+
+ samsung_clk_of_add_provider(np, ctx);
}
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index c9505ab9ee70..231475bc2b99 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -204,6 +204,8 @@ static void __init exynos5410_clk_init(struct device_node *np)
samsung_clk_register_gate(ctx, exynos5410_gate_clks,
ARRAY_SIZE(exynos5410_gate_clks));
+ samsung_clk_of_add_provider(np, ctx);
+
pr_debug("Exynos5410: clock setup completed.\n");
}
CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index a4e6cc782e5c..848d602efc06 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -28,6 +28,7 @@
#define GATE_BUS_CPU 0x700
#define GATE_SCLK_CPU 0x800
#define CLKOUT_CMU_CPU 0xa00
+#define SRC_MASK_CPERI 0x4300
#define GATE_IP_G2D 0x8800
#define CPLL_LOCK 0x10020
#define DPLL_LOCK 0x10030
@@ -70,6 +71,8 @@
#define SRC_TOP11 0x10284
#define SRC_TOP12 0x10288
#define SRC_TOP13 0x1028c /* 5800 specific */
+#define SRC_MASK_TOP0 0x10300
+#define SRC_MASK_TOP1 0x10304
#define SRC_MASK_TOP2 0x10308
#define SRC_MASK_TOP7 0x1031c
#define SRC_MASK_DISP10 0x1032c
@@ -77,6 +80,7 @@
#define SRC_MASK_FSYS 0x10340
#define SRC_MASK_PERIC0 0x10350
#define SRC_MASK_PERIC1 0x10354
+#define SRC_MASK_ISP 0x10370
#define DIV_TOP0 0x10500
#define DIV_TOP1 0x10504
#define DIV_TOP2 0x10508
@@ -98,6 +102,7 @@
#define DIV2_RATIO0 0x10590
#define DIV4_RATIO 0x105a0
#define GATE_BUS_TOP 0x10700
+#define GATE_BUS_DISP1 0x10728
#define GATE_BUS_GEN 0x1073c
#define GATE_BUS_FSYS0 0x10740
#define GATE_BUS_FSYS2 0x10748
@@ -190,6 +195,10 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
SRC_MASK_FSYS,
SRC_MASK_PERIC0,
SRC_MASK_PERIC1,
+ SRC_MASK_TOP0,
+ SRC_MASK_TOP1,
+ SRC_MASK_MAU,
+ SRC_MASK_ISP,
SRC_ISP,
DIV_TOP0,
DIV_TOP1,
@@ -208,6 +217,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
SCLK_DIV_ISP1,
DIV2_RATIO0,
DIV4_RATIO,
+ GATE_BUS_DISP1,
GATE_BUS_TOP,
GATE_BUS_GEN,
GATE_BUS_FSYS0,
@@ -249,6 +259,22 @@ static unsigned long exynos5800_clk_regs[] __initdata = {
GATE_IP_CAM,
};
+static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = {
+ { .offset = SRC_MASK_CPERI, .value = 0xffffffff, },
+ { .offset = SRC_MASK_TOP0, .value = 0x11111111, },
+ { .offset = SRC_MASK_TOP1, .value = 0x11101111, },
+ { .offset = SRC_MASK_TOP2, .value = 0x11111110, },
+ { .offset = SRC_MASK_TOP7, .value = 0x00111100, },
+ { .offset = SRC_MASK_DISP10, .value = 0x11111110, },
+ { .offset = SRC_MASK_MAU, .value = 0x10000000, },
+ { .offset = SRC_MASK_FSYS, .value = 0x11111110, },
+ { .offset = SRC_MASK_PERIC0, .value = 0x11111110, },
+ { .offset = SRC_MASK_PERIC1, .value = 0x11111100, },
+ { .offset = SRC_MASK_ISP, .value = 0x11111000, },
+ { .offset = GATE_BUS_DISP1, .value = 0xffffffff, },
+ { .offset = GATE_IP_PERIC, .value = 0xffffffff, },
+};
+
static int exynos5420_clk_suspend(void)
{
samsung_clk_save(reg_base, exynos5x_save,
@@ -258,6 +284,9 @@ static int exynos5420_clk_suspend(void)
samsung_clk_save(reg_base, exynos5800_save,
ARRAY_SIZE(exynos5800_clk_regs));
+ samsung_clk_restore(reg_base, exynos5420_set_clksrc,
+ ARRAY_SIZE(exynos5420_set_clksrc));
+
return 0;
}
@@ -1169,6 +1198,28 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
};
+static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = {
+ PLL_35XX_RATE(2000000000, 250, 3, 0),
+ PLL_35XX_RATE(1900000000, 475, 6, 0),
+ PLL_35XX_RATE(1800000000, 225, 3, 0),
+ PLL_35XX_RATE(1700000000, 425, 6, 0),
+ PLL_35XX_RATE(1600000000, 200, 3, 0),
+ PLL_35XX_RATE(1500000000, 250, 4, 0),
+ PLL_35XX_RATE(1400000000, 175, 3, 0),
+ PLL_35XX_RATE(1300000000, 325, 6, 0),
+ PLL_35XX_RATE(1200000000, 200, 2, 1),
+ PLL_35XX_RATE(1100000000, 275, 3, 1),
+ PLL_35XX_RATE(1000000000, 250, 3, 1),
+ PLL_35XX_RATE(900000000, 150, 2, 1),
+ PLL_35XX_RATE(800000000, 200, 3, 1),
+ PLL_35XX_RATE(700000000, 175, 3, 1),
+ PLL_35XX_RATE(600000000, 200, 2, 2),
+ PLL_35XX_RATE(500000000, 250, 3, 2),
+ PLL_35XX_RATE(400000000, 200, 3, 2),
+ PLL_35XX_RATE(300000000, 200, 2, 3),
+ PLL_35XX_RATE(200000000, 200, 3, 3),
+};
+
static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
[apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, NULL),
@@ -1194,7 +1245,7 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
KPLL_CON0, NULL),
};
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
{ },
};
@@ -1222,6 +1273,12 @@ static void __init exynos5x_clk_init(struct device_node *np,
samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
ext_clk_match);
+
+ if (_get_rate("fin_pll") == 24 * MHZ) {
+ exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+ exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
+ }
+
samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
reg_base);
samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks,
@@ -1253,6 +1310,8 @@ static void __init exynos5x_clk_init(struct device_node *np,
}
exynos5420_clk_sleep_init();
+
+ samsung_clk_of_add_provider(np, ctx);
}
static void __init exynos5420_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index 647f1440aa6a..00d1d00a41de 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -84,7 +84,7 @@ static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
};
-static struct of_device_id ext_clk_match[] __initdata = {
+static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
{},
};
@@ -123,6 +123,8 @@ static void __init exynos5440_clk_init(struct device_node *np)
samsung_clk_register_gate(ctx, exynos5440_gate_clks,
ARRAY_SIZE(exynos5440_gate_clks));
+ samsung_clk_of_add_provider(np, ctx);
+
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
pr_info("exynos5440 clock initialization complete\n");
}
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
index 140f4733c02e..5d2f03461bc5 100644
--- a/drivers/clk/samsung/clk-s3c2410.c
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -466,6 +466,8 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
}
s3c2410_clk_sleep_init();
+
+ samsung_clk_of_add_provider(np, ctx);
}
static void __init s3c2410_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index 23e4313f625e..34af09f6a155 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -265,6 +265,8 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
ARRAY_SIZE(s3c2412_aliases));
s3c2412_clk_sleep_init();
+
+ samsung_clk_of_add_provider(np, ctx);
}
static void __init s3c2412_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index c4bbdabebaa4..c92f853fca9f 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -445,6 +445,8 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
}
s3c2443_clk_sleep_init();
+
+ samsung_clk_of_add_provider(np, ctx);
}
static void __init s3c2416_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 8889ff1c10fc..0f590e5550cb 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -518,6 +518,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
ARRAY_SIZE(s3c64xx_clock_aliases));
s3c64xx_clk_sleep_init();
+ samsung_clk_of_add_provider(np, ctx);
+
pr_info("%s clocks: apll = %lu, mpll = %lu\n"
"\tepll = %lu, arm_clk = %lu\n",
is_s3c6400 ? "S3C6400" : "S3C6410",
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
new file mode 100644
index 000000000000..a8053b4aca56
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
+ *
+ * Based on Exynos Audio Subsystem Clock Controller driver:
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Padmavathi Venna <padma.v@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
+*/
+
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/s5pv210-audss.h>
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+static struct clk_onecell_data clk_data;
+
+#define ASS_CLK_SRC 0x0
+#define ASS_CLK_DIV 0x4
+#define ASS_CLK_GATE 0x8
+
+#ifdef CONFIG_PM_SLEEP
+static unsigned long reg_save[][2] = {
+ {ASS_CLK_SRC, 0},
+ {ASS_CLK_DIV, 0},
+ {ASS_CLK_GATE, 0},
+};
+
+static int s5pv210_audss_clk_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ reg_save[i][1] = readl(reg_base + reg_save[i][0]);
+
+ return 0;
+}
+
+static void s5pv210_audss_clk_resume(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ writel(reg_save[i][1], reg_base + reg_save[i][0]);
+}
+
+static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
+ .suspend = s5pv210_audss_clk_suspend,
+ .resume = s5pv210_audss_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+/* register s5pv210_audss clocks */
+static int s5pv210_audss_clk_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct resource *res;
+ const char *mout_audss_p[2];
+ const char *mout_i2s_p[3];
+ const char *hclk_p;
+ struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg_base)) {
+ dev_err(&pdev->dev, "failed to map audss registers\n");
+ return PTR_ERR(reg_base);
+ }
+
+ clk_table = devm_kzalloc(&pdev->dev,
+ sizeof(struct clk *) * AUDSS_MAX_CLKS,
+ GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ clk_data.clks = clk_table;
+ clk_data.clk_num = AUDSS_MAX_CLKS;
+
+ hclk = devm_clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk clock\n");
+ return PTR_ERR(hclk);
+ }
+
+ pll_in = devm_clk_get(&pdev->dev, "fout_epll");
+ if (IS_ERR(pll_in)) {
+ dev_err(&pdev->dev, "failed to get fout_epll clock\n");
+ return PTR_ERR(pll_in);
+ }
+
+ sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
+ if (IS_ERR(sclk_audio)) {
+ dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
+ return PTR_ERR(sclk_audio);
+ }
+
+ /* iiscdclk0 is an optional external I2S codec clock */
+ cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
+ pll_ref = devm_clk_get(&pdev->dev, "xxti");
+
+ if (!IS_ERR(pll_ref))
+ mout_audss_p[0] = __clk_get_name(pll_ref);
+ else
+ mout_audss_p[0] = "xxti";
+ mout_audss_p[1] = __clk_get_name(pll_in);
+ clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+ mout_audss_p, ARRAY_SIZE(mout_audss_p),
+ CLK_SET_RATE_NO_REPARENT,
+ reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
+
+ mout_i2s_p[0] = "mout_audss";
+ if (!IS_ERR(cdclk))
+ mout_i2s_p[1] = __clk_get_name(cdclk);
+ else
+ mout_i2s_p[1] = "iiscdclk0";
+ mout_i2s_p[2] = __clk_get_name(sclk_audio);
+ clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
+ mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
+ CLK_SET_RATE_NO_REPARENT,
+ reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
+
+ clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
+ "dout_aud_bus", "mout_audss", 0,
+ reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
+ clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
+ "mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
+ 4, 4, 0, &lock);
+
+ clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
+ "dout_i2s_audss", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 6, 0, &lock);
+
+ hclk_p = __clk_get_name(hclk);
+
+ clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 5, 0, &lock);
+ clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 4, 0, &lock);
+ clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 3, 0, &lock);
+ clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 2, 0, &lock);
+ clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 1, 0, &lock);
+ clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 0, 0, &lock);
+
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (IS_ERR(clk_table[i])) {
+ dev_err(&pdev->dev, "failed to register clock %d\n", i);
+ ret = PTR_ERR(clk_table[i]);
+ goto unregister;
+ }
+ }
+
+ ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ &clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add clock provider\n");
+ goto unregister;
+ }
+
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
+#endif
+
+ return 0;
+
+unregister:
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister(clk_table[i]);
+ }
+
+ return ret;
+}
+
+static int s5pv210_audss_clk_remove(struct platform_device *pdev)
+{
+ int i;
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister(clk_table[i]);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id s5pv210_audss_clk_of_match[] = {
+ { .compatible = "samsung,s5pv210-audss-clock", },
+ {},
+};
+
+static struct platform_driver s5pv210_audss_clk_driver = {
+ .driver = {
+ .name = "s5pv210-audss-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = s5pv210_audss_clk_of_match,
+ },
+ .probe = s5pv210_audss_clk_probe,
+ .remove = s5pv210_audss_clk_remove,
+};
+
+static int __init s5pv210_audss_clk_init(void)
+{
+ return platform_driver_register(&s5pv210_audss_clk_driver);
+}
+core_initcall(s5pv210_audss_clk_init);
+
+static void __exit s5pv210_audss_clk_exit(void)
+{
+ platform_driver_unregister(&s5pv210_audss_clk_driver);
+}
+module_exit(s5pv210_audss_clk_exit);
+
+MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
+MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:s5pv210-audss-clk");
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
new file mode 100644
index 000000000000..d270a2084644
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ *
+ * Based on clock drivers for S3C64xx and Exynos4 SoCs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#include <dt-bindings/clock/s5pv210.h>
+
+/* S5PC110/S5PV210 clock controller register offsets */
+#define APLL_LOCK 0x0000
+#define MPLL_LOCK 0x0008
+#define EPLL_LOCK 0x0010
+#define VPLL_LOCK 0x0020
+#define APLL_CON0 0x0100
+#define APLL_CON1 0x0104
+#define MPLL_CON 0x0108
+#define EPLL_CON0 0x0110
+#define EPLL_CON1 0x0114
+#define VPLL_CON 0x0120
+#define CLK_SRC0 0x0200
+#define CLK_SRC1 0x0204
+#define CLK_SRC2 0x0208
+#define CLK_SRC3 0x020c
+#define CLK_SRC4 0x0210
+#define CLK_SRC5 0x0214
+#define CLK_SRC6 0x0218
+#define CLK_SRC_MASK0 0x0280
+#define CLK_SRC_MASK1 0x0284
+#define CLK_DIV0 0x0300
+#define CLK_DIV1 0x0304
+#define CLK_DIV2 0x0308
+#define CLK_DIV3 0x030c
+#define CLK_DIV4 0x0310
+#define CLK_DIV5 0x0314
+#define CLK_DIV6 0x0318
+#define CLK_DIV7 0x031c
+#define CLK_GATE_MAIN0 0x0400
+#define CLK_GATE_MAIN1 0x0404
+#define CLK_GATE_MAIN2 0x0408
+#define CLK_GATE_PERI0 0x0420
+#define CLK_GATE_PERI1 0x0424
+#define CLK_GATE_SCLK0 0x0440
+#define CLK_GATE_SCLK1 0x0444
+#define CLK_GATE_IP0 0x0460
+#define CLK_GATE_IP1 0x0464
+#define CLK_GATE_IP2 0x0468
+#define CLK_GATE_IP3 0x046c
+#define CLK_GATE_IP4 0x0470
+#define CLK_GATE_BLOCK 0x0480
+#define CLK_GATE_IP5 0x0484
+#define CLK_OUT 0x0500
+#define MISC 0xe000
+#define OM_STAT 0xe100
+
+/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
+enum {
+ apll,
+ mpll,
+ epll,
+ vpll,
+};
+
+/* IDs of external clocks (used for legacy boards) */
+enum {
+ xxti,
+ xusbxti,
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s5pv210_clk_dump;
+
+/* List of registers that need to be preserved across suspend/resume. */
+static unsigned long s5pv210_clk_regs[] __initdata = {
+ CLK_SRC0,
+ CLK_SRC1,
+ CLK_SRC2,
+ CLK_SRC3,
+ CLK_SRC4,
+ CLK_SRC5,
+ CLK_SRC6,
+ CLK_SRC_MASK0,
+ CLK_SRC_MASK1,
+ CLK_DIV0,
+ CLK_DIV1,
+ CLK_DIV2,
+ CLK_DIV3,
+ CLK_DIV4,
+ CLK_DIV5,
+ CLK_DIV6,
+ CLK_DIV7,
+ CLK_GATE_MAIN0,
+ CLK_GATE_MAIN1,
+ CLK_GATE_MAIN2,
+ CLK_GATE_PERI0,
+ CLK_GATE_PERI1,
+ CLK_GATE_SCLK0,
+ CLK_GATE_SCLK1,
+ CLK_GATE_IP0,
+ CLK_GATE_IP1,
+ CLK_GATE_IP2,
+ CLK_GATE_IP3,
+ CLK_GATE_IP4,
+ CLK_GATE_IP5,
+ CLK_GATE_BLOCK,
+ APLL_LOCK,
+ MPLL_LOCK,
+ EPLL_LOCK,
+ VPLL_LOCK,
+ APLL_CON0,
+ APLL_CON1,
+ MPLL_CON,
+ EPLL_CON0,
+ EPLL_CON1,
+ VPLL_CON,
+ CLK_OUT,
+};
+
+static int s5pv210_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, s5pv210_clk_dump,
+ ARRAY_SIZE(s5pv210_clk_regs));
+ return 0;
+}
+
+static void s5pv210_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, s5pv210_clk_dump,
+ ARRAY_SIZE(s5pv210_clk_regs));
+}
+
+static struct syscore_ops s5pv210_clk_syscore_ops = {
+ .suspend = s5pv210_clk_suspend,
+ .resume = s5pv210_clk_resume,
+};
+
+static void s5pv210_clk_sleep_init(void)
+{
+ s5pv210_clk_dump =
+ samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
+ ARRAY_SIZE(s5pv210_clk_regs));
+ if (!s5pv210_clk_dump) {
+ pr_warn("%s: Failed to allocate sleep save data\n", __func__);
+ return;
+ }
+
+ register_syscore_ops(&s5pv210_clk_syscore_ops);
+}
+#else
+static inline void s5pv210_clk_sleep_init(void) { }
+#endif
+
+/* Mux parent lists. */
+static const char *fin_pll_p[] __initconst = {
+ "xxti",
+ "xusbxti"
+};
+
+static const char *mout_apll_p[] __initconst = {
+ "fin_pll",
+ "fout_apll"
+};
+
+static const char *mout_mpll_p[] __initconst = {
+ "fin_pll",
+ "fout_mpll"
+};
+
+static const char *mout_epll_p[] __initconst = {
+ "fin_pll",
+ "fout_epll"
+};
+
+static const char *mout_vpllsrc_p[] __initconst = {
+ "fin_pll",
+ "sclk_hdmi27m"
+};
+
+static const char *mout_vpll_p[] __initconst = {
+ "mout_vpllsrc",
+ "fout_vpll"
+};
+
+static const char *mout_group1_p[] __initconst = {
+ "dout_a2m",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll"
+};
+
+static const char *mout_group2_p[] __initconst = {
+ "xxti",
+ "xusbxti",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio0_p[] __initconst = {
+ "xxti",
+ "pcmcdclk0",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio1_p[] __initconst = {
+ "i2scdclk1",
+ "pcmcdclk1",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio2_p[] __initconst = {
+ "i2scdclk2",
+ "pcmcdclk2",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_spdif_p[] __initconst = {
+ "dout_audio0",
+ "dout_audio1",
+ "dout_audio3",
+};
+
+static const char *mout_group3_p[] __initconst = {
+ "mout_apll",
+ "mout_mpll"
+};
+
+static const char *mout_group4_p[] __initconst = {
+ "mout_mpll",
+ "dout_a2m"
+};
+
+static const char *mout_flash_p[] __initconst = {
+ "dout_hclkd",
+ "dout_hclkp"
+};
+
+static const char *mout_dac_p[] __initconst = {
+ "mout_vpll",
+ "sclk_hdmiphy"
+};
+
+static const char *mout_hdmi_p[] __initconst = {
+ "sclk_hdmiphy",
+ "dout_tblk"
+};
+
+static const char *mout_mixer_p[] __initconst = {
+ "mout_dac",
+ "mout_hdmi"
+};
+
+static const char *mout_vpll_6442_p[] __initconst = {
+ "fin_pll",
+ "fout_vpll"
+};
+
+static const char *mout_mixer_6442_p[] __initconst = {
+ "mout_vpll",
+ "dout_mixer"
+};
+
+static const char *mout_d0sync_6442_p[] __initconst = {
+ "mout_dsys",
+ "div_apll"
+};
+
+static const char *mout_d1sync_6442_p[] __initconst = {
+ "mout_psys",
+ "div_apll"
+};
+
+static const char *mout_group2_6442_p[] __initconst = {
+ "fin_pll",
+ "none",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio0_6442_p[] __initconst = {
+ "fin_pll",
+ "pcmcdclk0",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio1_6442_p[] __initconst = {
+ "i2scdclk1",
+ "pcmcdclk1",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+ "fin_pll",
+};
+
+static const char *mout_clksel_p[] __initconst = {
+ "fout_apll_clkout",
+ "fout_mpll_clkout",
+ "fout_epll",
+ "fout_vpll",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "rtc",
+ "rtc_tick",
+ "dout_hclkm",
+ "dout_pclkm",
+ "dout_hclkd",
+ "dout_pclkd",
+ "dout_hclkp",
+ "dout_pclkp",
+ "dout_apll_clkout",
+ "dout_hpm",
+ "xxti",
+ "xusbxti",
+ "div_dclk"
+};
+
+static const char *mout_clksel_6442_p[] __initconst = {
+ "fout_apll_clkout",
+ "fout_mpll_clkout",
+ "fout_epll",
+ "fout_vpll",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "rtc",
+ "rtc_tick",
+ "none",
+ "none",
+ "dout_hclkd",
+ "dout_pclkd",
+ "dout_hclkp",
+ "dout_pclkp",
+ "dout_apll_clkout",
+ "none",
+ "fin_pll",
+ "none",
+ "div_dclk"
+};
+
+static const char *mout_clkout_p[] __initconst = {
+ "dout_clkout",
+ "none",
+ "xxti",
+ "xusbxti"
+};
+
+/* Common fixed factor clocks. */
+static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+ FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
+ FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
+ FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
+};
+
+/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
+static struct samsung_mux_clock early_mux_clks[] __initdata = {
+ MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
+ CLK_MUX_READ_ONLY, 0),
+};
+
+/* Common clock muxes. */
+static struct samsung_mux_clock mux_clks[] __initdata = {
+ MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
+ MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
+ MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
+ MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
+ MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
+ MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
+ MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
+
+ MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
+};
+
+/* S5PV210-specific clock muxes. */
+static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+ MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
+
+ MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
+ MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
+ MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
+ MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
+ MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
+ MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
+ MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
+ MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
+
+ MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
+ MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
+ MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
+
+ MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
+ MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
+ MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
+
+ MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
+ MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
+ MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
+ MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
+ MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
+ MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
+ MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
+ MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
+
+ MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
+ MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
+ MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
+
+ MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
+ MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
+ MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
+ MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
+ MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
+ MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
+ MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
+
+ MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
+};
+
+/* S5P6442-specific clock muxes. */
+static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+ MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
+
+ MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
+ MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
+ MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
+ MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
+
+ MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
+ MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
+
+ MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
+ MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
+ MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
+
+ MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
+ MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
+ MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
+ MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
+ MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
+ MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
+
+ MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
+ MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
+
+ MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
+ MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
+
+ MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
+};
+
+/* S5PV210-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+ FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+ FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* S5P6442-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+ FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
+};
+
+/* Common clock dividers. */
+static struct samsung_div_clock div_clks[] __initdata = {
+ DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
+ DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
+ DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
+ DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
+
+ DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
+ DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
+ DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
+
+ DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
+ DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
+ DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
+
+ DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
+ DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
+ DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
+ DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
+ DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
+ DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
+
+ DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
+ DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
+
+ DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
+ DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
+ DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
+
+ DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
+};
+
+/* S5PV210-specific clock dividers. */
+static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+ DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
+ DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
+ DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
+ DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
+
+ DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
+ DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
+
+ DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
+ DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
+ DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
+
+ DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
+ DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
+
+ DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
+
+ DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
+ DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
+ DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
+ DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
+ DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
+
+ DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
+ DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
+};
+
+/* S5P6442-specific clock dividers. */
+static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+ DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
+ DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
+
+ DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
+};
+
+/* Common clock gates. */
+static struct samsung_gate_clock gate_clks[] __initdata = {
+ GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
+ GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
+ GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
+ GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
+ GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
+ GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
+
+ GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
+ GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
+ GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
+ GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
+ GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
+ GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
+ GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
+
+ GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
+ GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
+ GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
+ GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
+ GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
+
+ GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
+ GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
+ GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
+ GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
+ GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
+ GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
+ GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
+ GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
+ GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
+ GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
+ GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
+ GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
+ GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
+ GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
+ GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
+ GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
+
+ GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
+ GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
+
+ GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
+ CLK_SET_RATE_PARENT, 0),
+
+ GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5PV210-specific clock gates. */
+static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+ GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
+ GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
+ GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+ GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
+ GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
+ GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
+
+ GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
+ GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
+ GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
+ GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
+ GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
+
+ GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
+ GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
+ GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
+ GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
+ GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
+ GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
+ GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
+ GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
+ GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
+
+ GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
+ GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
+ GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
+ GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
+ CLK_GATE_IP3, 11, 0, 0),
+ GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
+ GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
+ GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
+ GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
+
+ GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
+ GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
+ GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
+ GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
+ GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
+ GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
+
+ GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
+
+ GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5P6442-specific clock gates. */
+static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+ GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
+ GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
+ GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+ GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
+ GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
+
+ GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
+ GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
+
+ GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
+
+ GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/*
+ * Clock aliases for legacy clkdev look-up.
+ * NOTE: Needed only to support legacy board files.
+ */
+static struct samsung_clock_alias s5pv210_aliases[] = {
+ ALIAS(DOUT_APLL, NULL, "armclk"),
+ ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
+ ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
+};
+
+/* S5PV210-specific PLLs. */
+static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+ [apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, NULL),
+ [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ [epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+ [vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
+ VPLL_LOCK, VPLL_CON, NULL),
+};
+
+/* S5P6442-specific PLLs. */
+static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+ [apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, NULL),
+ [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ [epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+ [vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
+ VPLL_LOCK, VPLL_CON, NULL),
+};
+
+static void __init __s5pv210_clk_init(struct device_node *np,
+ unsigned long xxti_f,
+ unsigned long xusbxti_f,
+ bool is_s5p6442)
+{
+ struct samsung_clk_provider *ctx;
+
+ ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+ if (!ctx)
+ panic("%s: unable to allocate context.\n", __func__);
+
+ samsung_clk_register_mux(ctx, early_mux_clks,
+ ARRAY_SIZE(early_mux_clks));
+
+ if (is_s5p6442) {
+ samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
+ ARRAY_SIZE(s5p6442_frate_clks));
+ samsung_clk_register_pll(ctx, s5p6442_pll_clks,
+ ARRAY_SIZE(s5p6442_pll_clks), reg_base);
+ samsung_clk_register_mux(ctx, s5p6442_mux_clks,
+ ARRAY_SIZE(s5p6442_mux_clks));
+ samsung_clk_register_div(ctx, s5p6442_div_clks,
+ ARRAY_SIZE(s5p6442_div_clks));
+ samsung_clk_register_gate(ctx, s5p6442_gate_clks,
+ ARRAY_SIZE(s5p6442_gate_clks));
+ } else {
+ samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
+ ARRAY_SIZE(s5pv210_frate_clks));
+ samsung_clk_register_pll(ctx, s5pv210_pll_clks,
+ ARRAY_SIZE(s5pv210_pll_clks), reg_base);
+ samsung_clk_register_mux(ctx, s5pv210_mux_clks,
+ ARRAY_SIZE(s5pv210_mux_clks));
+ samsung_clk_register_div(ctx, s5pv210_div_clks,
+ ARRAY_SIZE(s5pv210_div_clks));
+ samsung_clk_register_gate(ctx, s5pv210_gate_clks,
+ ARRAY_SIZE(s5pv210_gate_clks));
+ }
+
+ samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
+ samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
+ samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
+
+ samsung_clk_register_fixed_factor(ctx, ffactor_clks,
+ ARRAY_SIZE(ffactor_clks));
+
+ samsung_clk_register_alias(ctx, s5pv210_aliases,
+ ARRAY_SIZE(s5pv210_aliases));
+
+ s5pv210_clk_sleep_init();
+
+ pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
+ "\tmout_epll = %ld, mout_vpll = %ld\n",
+ is_s5p6442 ? "S5P6442" : "S5PV210",
+ _get_rate("mout_apll"), _get_rate("mout_mpll"),
+ _get_rate("mout_epll"), _get_rate("mout_vpll"));
+}
+
+static void __init s5pv210_clk_dt_init(struct device_node *np)
+{
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ __s5pv210_clk_init(np, 0, 0, false);
+}
+CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
+
+static void __init s5p6442_clk_dt_init(struct device_node *np)
+{
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ __s5pv210_clk_init(np, 0, 0, true);
+}
+CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 49629c71c9e7..deab84d9f37d 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -53,7 +53,6 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
{
struct samsung_clk_provider *ctx;
struct clk **clk_table;
- int ret;
int i;
ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL);
@@ -72,17 +71,19 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
ctx->clk_data.clk_num = nr_clks;
spin_lock_init(&ctx->lock);
- if (!np)
- return ctx;
-
- ret = of_clk_add_provider(np, of_clk_src_onecell_get,
- &ctx->clk_data);
- if (ret)
- panic("could not register clock provide\n");
-
return ctx;
}
+void __init samsung_clk_of_add_provider(struct device_node *np,
+ struct samsung_clk_provider *ctx)
+{
+ if (np) {
+ if (of_clk_add_provider(np, of_clk_src_onecell_get,
+ &ctx->clk_data))
+ panic("could not register clk provider\n");
+ }
+}
+
/* add a clock instance to the clock lookup table used for dt based lookup */
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
unsigned int id)
@@ -284,7 +285,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
- struct of_device_id *clk_matches)
+ const struct of_device_id *clk_matches)
{
const struct of_device_id *match;
struct device_node *clk_np;
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 9693b80d924f..66ab36b5cef1 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -327,11 +327,13 @@ struct samsung_pll_clock {
extern struct samsung_clk_provider *__init samsung_clk_init(
struct device_node *np, void __iomem *base,
unsigned long nr_clks);
+extern void __init samsung_clk_of_add_provider(struct device_node *np,
+ struct samsung_clk_provider *ctx);
extern void __init samsung_clk_of_register_fixed_ext(
struct samsung_clk_provider *ctx,
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
- struct of_device_id *clk_matches);
+ const struct of_device_id *clk_matches);
extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
struct clk *clk, unsigned int id);
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 65894f7687ed..4daa5977793a 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -742,19 +742,19 @@ void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
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, "b1000000.pcie");
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, "b1800000.pcie");
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, "b4000000.pcie");
clk_register_clkdev(clk, NULL, "b4000000.ahci");
clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index fe835c1845fe..5a5c6648308d 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -839,7 +839,7 @@ void __init spear1340_clk_init(void __iomem *misc_base)
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, "b1000000.pcie");
clk_register_clkdev(clk, NULL, "b1000000.ahci");
clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
diff --git a/drivers/clk/st/Makefile b/drivers/clk/st/Makefile
index c7455ffdbdf7..ede7b2f13092 100644
--- a/drivers/clk/st/Makefile
+++ b/drivers/clk/st/Makefile
@@ -1 +1 @@
-obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o
+obj-y += clkgen-mux.o clkgen-pll.o clkgen-fsyn.o clk-flexgen.o
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
new file mode 100644
index 000000000000..2282cef9f2ff
--- /dev/null
+++ b/drivers/clk/st/clk-flexgen.c
@@ -0,0 +1,331 @@
+/*
+ * clk-flexgen.c
+ *
+ * Copyright (C) ST-Microelectronics SA 2013
+ * Author: Maxime Coquelin <maxime.coquelin@st.com> for ST-Microelectronics.
+ * License terms: GNU General Public License (GPL), version 2 */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+struct flexgen {
+ struct clk_hw hw;
+
+ /* Crossbar */
+ struct clk_mux mux;
+ /* Pre-divisor's gate */
+ struct clk_gate pgate;
+ /* Pre-divisor */
+ struct clk_divider pdiv;
+ /* Final divisor's gate */
+ struct clk_gate fgate;
+ /* Final divisor */
+ struct clk_divider fdiv;
+};
+
+#define to_flexgen(_hw) container_of(_hw, struct flexgen, hw)
+
+static int flexgen_enable(struct clk_hw *hw)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *pgate_hw = &flexgen->pgate.hw;
+ struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+ pgate_hw->clk = hw->clk;
+ fgate_hw->clk = hw->clk;
+
+ clk_gate_ops.enable(pgate_hw);
+
+ clk_gate_ops.enable(fgate_hw);
+
+ pr_debug("%s: flexgen output enabled\n", __clk_get_name(hw->clk));
+ return 0;
+}
+
+static void flexgen_disable(struct clk_hw *hw)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+ /* disable only the final gate */
+ fgate_hw->clk = hw->clk;
+
+ clk_gate_ops.disable(fgate_hw);
+
+ pr_debug("%s: flexgen output disabled\n", __clk_get_name(hw->clk));
+}
+
+static int flexgen_is_enabled(struct clk_hw *hw)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *fgate_hw = &flexgen->fgate.hw;
+
+ fgate_hw->clk = hw->clk;
+
+ if (!clk_gate_ops.is_enabled(fgate_hw))
+ return 0;
+
+ return 1;
+}
+
+static u8 flexgen_get_parent(struct clk_hw *hw)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *mux_hw = &flexgen->mux.hw;
+
+ mux_hw->clk = hw->clk;
+
+ return clk_mux_ops.get_parent(mux_hw);
+}
+
+static int flexgen_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *mux_hw = &flexgen->mux.hw;
+
+ mux_hw->clk = hw->clk;
+
+ return clk_mux_ops.set_parent(mux_hw, index);
+}
+
+static inline unsigned long
+clk_best_div(unsigned long parent_rate, unsigned long rate)
+{
+ return parent_rate / rate + ((rate > (2*(parent_rate % rate))) ? 0 : 1);
+}
+
+static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ unsigned long div;
+
+ /* Round div according to exact prate and wished rate */
+ div = clk_best_div(*prate, rate);
+
+ if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+ *prate = rate * div;
+ return rate;
+ }
+
+ return *prate / div;
+}
+
+unsigned long flexgen_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
+ struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
+ unsigned long mid_rate;
+
+ pdiv_hw->clk = hw->clk;
+ fdiv_hw->clk = hw->clk;
+
+ mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate);
+
+ return clk_divider_ops.recalc_rate(fdiv_hw, mid_rate);
+}
+
+static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct flexgen *flexgen = to_flexgen(hw);
+ struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
+ struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
+ unsigned long primary_div = 0;
+ int ret = 0;
+
+ pdiv_hw->clk = hw->clk;
+ fdiv_hw->clk = hw->clk;
+
+ primary_div = clk_best_div(parent_rate, rate);
+
+ clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
+ ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * primary_div);
+
+ return ret;
+}
+
+static const struct clk_ops flexgen_ops = {
+ .enable = flexgen_enable,
+ .disable = flexgen_disable,
+ .is_enabled = flexgen_is_enabled,
+ .get_parent = flexgen_get_parent,
+ .set_parent = flexgen_set_parent,
+ .round_rate = flexgen_round_rate,
+ .recalc_rate = flexgen_recalc_rate,
+ .set_rate = flexgen_set_rate,
+};
+
+struct clk *clk_register_flexgen(const char *name,
+ const char **parent_names, u8 num_parents,
+ void __iomem *reg, spinlock_t *lock, u32 idx,
+ unsigned long flexgen_flags) {
+ struct flexgen *fgxbar;
+ struct clk *clk;
+ struct clk_init_data init;
+ u32 xbar_shift;
+ void __iomem *xbar_reg, *fdiv_reg;
+
+ fgxbar = kzalloc(sizeof(struct flexgen), GFP_KERNEL);
+ if (!fgxbar)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &flexgen_ops;
+ init.flags = CLK_IS_BASIC | flexgen_flags;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+
+ xbar_reg = reg + 0x18 + (idx & ~0x3);
+ xbar_shift = (idx % 4) * 0x8;
+ fdiv_reg = reg + 0x164 + idx * 4;
+
+ /* Crossbar element config */
+ fgxbar->mux.lock = lock;
+ fgxbar->mux.mask = BIT(6) - 1;
+ fgxbar->mux.reg = xbar_reg;
+ fgxbar->mux.shift = xbar_shift;
+ fgxbar->mux.table = NULL;
+
+
+ /* Pre-divider's gate config (in xbar register)*/
+ fgxbar->pgate.lock = lock;
+ fgxbar->pgate.reg = xbar_reg;
+ fgxbar->pgate.bit_idx = xbar_shift + 6;
+
+ /* Pre-divider config */
+ fgxbar->pdiv.lock = lock;
+ fgxbar->pdiv.reg = reg + 0x58 + idx * 4;
+ fgxbar->pdiv.width = 10;
+
+ /* Final divider's gate config */
+ fgxbar->fgate.lock = lock;
+ fgxbar->fgate.reg = fdiv_reg;
+ fgxbar->fgate.bit_idx = 6;
+
+ /* Final divider config */
+ fgxbar->fdiv.lock = lock;
+ fgxbar->fdiv.reg = fdiv_reg;
+ fgxbar->fdiv.width = 6;
+
+ fgxbar->hw.init = &init;
+
+ clk = clk_register(NULL, &fgxbar->hw);
+ if (IS_ERR(clk))
+ kfree(fgxbar);
+ else
+ pr_debug("%s: parent %s rate %u\n",
+ __clk_get_name(clk),
+ __clk_get_name(clk_get_parent(clk)),
+ (unsigned int)clk_get_rate(clk));
+ return clk;
+}
+
+static const char ** __init flexgen_get_parents(struct device_node *np,
+ int *num_parents)
+{
+ const char **parents;
+ int nparents, i;
+
+ nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+ if (WARN_ON(nparents <= 0))
+ return NULL;
+
+ parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
+ if (!parents)
+ return NULL;
+
+ for (i = 0; i < nparents; i++)
+ parents[i] = of_clk_get_parent_name(np, i);
+
+ *num_parents = nparents;
+ return parents;
+}
+
+void __init st_of_flexgen_setup(struct device_node *np)
+{
+ struct device_node *pnode;
+ void __iomem *reg;
+ struct clk_onecell_data *clk_data;
+ const char **parents;
+ int num_parents, i;
+ spinlock_t *rlock = NULL;
+ unsigned long flex_flags = 0;
+
+ pnode = of_get_parent(np);
+ if (!pnode)
+ return;
+
+ reg = of_iomap(pnode, 0);
+ if (!reg)
+ return;
+
+ parents = flexgen_get_parents(np, &num_parents);
+ if (!parents)
+ return;
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data)
+ goto err;
+
+ clk_data->clk_num = of_property_count_strings(np ,
+ "clock-output-names");
+ if (clk_data->clk_num <= 0) {
+ pr_err("%s: Failed to get number of output clocks (%d)",
+ __func__, clk_data->clk_num);
+ goto err;
+ }
+
+ clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clk_data->clks)
+ goto err;
+
+ rlock = kzalloc(sizeof(spinlock_t), GFP_KERNEL);
+ if (!rlock)
+ goto err;
+
+ for (i = 0; i < clk_data->clk_num; i++) {
+ struct clk *clk;
+ const char *clk_name;
+
+ if (of_property_read_string_index(np, "clock-output-names",
+ i, &clk_name)) {
+ break;
+ }
+
+ /*
+ * If we read an empty clock name then the output is unused
+ */
+ if (*clk_name == '\0')
+ continue;
+
+ clk = clk_register_flexgen(clk_name, parents, num_parents,
+ reg, rlock, i, flex_flags);
+
+ if (IS_ERR(clk))
+ goto err;
+
+ clk_data->clks[i] = clk;
+ }
+
+ kfree(parents);
+ of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+
+ return;
+
+err:
+ if (clk_data)
+ kfree(clk_data->clks);
+ kfree(clk_data);
+ kfree(parents);
+ kfree(rlock);
+}
+CLK_OF_DECLARE(flexgen, "st,flexgen", st_of_flexgen_setup);
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index 4f53ee0778d9..af94ed82cfcb 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -41,7 +41,7 @@ struct stm_fs {
unsigned long nsdiv;
};
-static struct stm_fs fs216c65_rtbl[] = {
+static const struct stm_fs fs216c65_rtbl[] = {
{ .mdiv = 0x1f, .pe = 0x0, .sdiv = 0x7, .nsdiv = 0 }, /* 312.5 Khz */
{ .mdiv = 0x17, .pe = 0x25ed, .sdiv = 0x1, .nsdiv = 0 }, /* 27 MHz */
{ .mdiv = 0x1a, .pe = 0x7b36, .sdiv = 0x2, .nsdiv = 1 }, /* 36.87 MHz */
@@ -49,31 +49,86 @@ static struct stm_fs fs216c65_rtbl[] = {
{ .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x1, .nsdiv = 1 }, /* 108 MHz */
};
-static struct stm_fs fs432c65_rtbl[] = {
- { .mdiv = 0x1f, .pe = 0x0, .sdiv = 0x7, .nsdiv = 0 }, /* 625 Khz */
- { .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x2, .nsdiv = 1 }, /* 108 MHz */
- { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x0, .nsdiv = 1 }, /* 297 MHz */
+static const struct stm_fs fs432c65_rtbl[] = {
+ { .mdiv = 0x1f, .pe = 0x0, .sdiv = 0x7, .nsdiv = 0 }, /* 625 Khz */
+ { .mdiv = 0x13, .pe = 0x777c, .sdiv = 0x4, .nsdiv = 1 }, /* 25.175 MHz */
+ { .mdiv = 0x19, .pe = 0x4d35, .sdiv = 0x2, .nsdiv = 0 }, /* 25.200 MHz */
+ { .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x4, .nsdiv = 1 }, /* 27.000 MHz */
+ { .mdiv = 0x17, .pe = 0x28f5, .sdiv = 0x2, .nsdiv = 0 }, /* 27.027 MHz */
+ { .mdiv = 0x16, .pe = 0x3359, .sdiv = 0x2, .nsdiv = 0 }, /* 28.320 MHz */
+ { .mdiv = 0x1f, .pe = 0x2083, .sdiv = 0x3, .nsdiv = 1 }, /* 30.240 MHz */
+ { .mdiv = 0x1e, .pe = 0x430d, .sdiv = 0x3, .nsdiv = 1 }, /* 31.500 MHz */
+ { .mdiv = 0x17, .pe = 0x0, .sdiv = 0x3, .nsdiv = 1 }, /* 40.000 MHz */
+ { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x1, .nsdiv = 0 }, /* 49.500 MHz */
+ { .mdiv = 0x13, .pe = 0x6667, .sdiv = 0x3, .nsdiv = 1 }, /* 50.000 MHz */
+ { .mdiv = 0x10, .pe = 0x1ee6, .sdiv = 0x3, .nsdiv = 1 }, /* 57.284 MHz */
+ { .mdiv = 0x1d, .pe = 0x3b14, .sdiv = 0x2, .nsdiv = 1 }, /* 65.000 MHz */
+ { .mdiv = 0x12, .pe = 0x7c65, .sdiv = 0x1, .nsdiv = 0 }, /* 71.000 MHz */
+ { .mdiv = 0x19, .pe = 0xecd, .sdiv = 0x2, .nsdiv = 1 }, /* 74.176 MHz */
+ { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x2, .nsdiv = 1 }, /* 74.250 MHz */
+ { .mdiv = 0x19, .pe = 0x3334, .sdiv = 0x2, .nsdiv = 1 }, /* 75.000 MHz */
+ { .mdiv = 0x18, .pe = 0x5138, .sdiv = 0x2, .nsdiv = 1 }, /* 78.800 MHz */
+ { .mdiv = 0x1d, .pe = 0x77d, .sdiv = 0x0, .nsdiv = 0 }, /* 85.500 MHz */
+ { .mdiv = 0x1c, .pe = 0x13d5, .sdiv = 0x0, .nsdiv = 0 }, /* 88.750 MHz */
+ { .mdiv = 0x11, .pe = 0x1c72, .sdiv = 0x2, .nsdiv = 1 }, /* 108.000 MHz */
+ { .mdiv = 0x17, .pe = 0x28f5, .sdiv = 0x0, .nsdiv = 0 }, /* 108.108 MHz */
+ { .mdiv = 0x10, .pe = 0x6e26, .sdiv = 0x2, .nsdiv = 1 }, /* 118.963 MHz */
+ { .mdiv = 0x15, .pe = 0x3e63, .sdiv = 0x0, .nsdiv = 0 }, /* 119.000 MHz */
+ { .mdiv = 0x1c, .pe = 0x471d, .sdiv = 0x1, .nsdiv = 1 }, /* 135.000 MHz */
+ { .mdiv = 0x19, .pe = 0xecd, .sdiv = 0x1, .nsdiv = 1 }, /* 148.352 MHz */
+ { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x1, .nsdiv = 1 }, /* 148.500 MHz */
+ { .mdiv = 0x19, .pe = 0x121a, .sdiv = 0x0, .nsdiv = 1 }, /* 297 MHz */
};
-static struct stm_fs fs660c32_rtbl[] = {
- { .mdiv = 0x01, .pe = 0x2aaa, .sdiv = 0x8, .nsdiv = 0 }, /* 600 KHz */
- { .mdiv = 0x02, .pe = 0x3d33, .sdiv = 0x0, .nsdiv = 0 }, /* 148.5 Mhz */
- { .mdiv = 0x13, .pe = 0x5bcc, .sdiv = 0x0, .nsdiv = 1 }, /* 297 Mhz */
- { .mdiv = 0x0e, .pe = 0x1025, .sdiv = 0x0, .nsdiv = 1 }, /* 333 Mhz */
- { .mdiv = 0x0b, .pe = 0x715f, .sdiv = 0x0, .nsdiv = 1 }, /* 350 Mhz */
+static const struct stm_fs fs660c32_rtbl[] = {
+ { .mdiv = 0x14, .pe = 0x376b, .sdiv = 0x4, .nsdiv = 1 }, /* 25.175 MHz */
+ { .mdiv = 0x14, .pe = 0x30c3, .sdiv = 0x4, .nsdiv = 1 }, /* 25.200 MHz */
+ { .mdiv = 0x10, .pe = 0x71c7, .sdiv = 0x4, .nsdiv = 1 }, /* 27.000 MHz */
+ { .mdiv = 0x00, .pe = 0x47af, .sdiv = 0x3, .nsdiv = 0 }, /* 27.027 MHz */
+ { .mdiv = 0x0e, .pe = 0x4e1a, .sdiv = 0x4, .nsdiv = 1 }, /* 28.320 MHz */
+ { .mdiv = 0x0b, .pe = 0x534d, .sdiv = 0x4, .nsdiv = 1 }, /* 30.240 MHz */
+ { .mdiv = 0x17, .pe = 0x6fbf, .sdiv = 0x2, .nsdiv = 0 }, /* 31.500 MHz */
+ { .mdiv = 0x01, .pe = 0x0, .sdiv = 0x4, .nsdiv = 1 }, /* 40.000 MHz */
+ { .mdiv = 0x15, .pe = 0x2aab, .sdiv = 0x3, .nsdiv = 1 }, /* 49.500 MHz */
+ { .mdiv = 0x14, .pe = 0x6666, .sdiv = 0x3, .nsdiv = 1 }, /* 50.000 MHz */
+ { .mdiv = 0x1d, .pe = 0x395f, .sdiv = 0x1, .nsdiv = 0 }, /* 57.284 MHz */
+ { .mdiv = 0x08, .pe = 0x4ec5, .sdiv = 0x3, .nsdiv = 1 }, /* 65.000 MHz */
+ { .mdiv = 0x05, .pe = 0x1770, .sdiv = 0x3, .nsdiv = 1 }, /* 71.000 MHz */
+ { .mdiv = 0x03, .pe = 0x4ba7, .sdiv = 0x3, .nsdiv = 1 }, /* 74.176 MHz */
+ { .mdiv = 0x0f, .pe = 0x3426, .sdiv = 0x1, .nsdiv = 0 }, /* 74.250 MHz */
+ { .mdiv = 0x0e, .pe = 0x7777, .sdiv = 0x1, .nsdiv = 0 }, /* 75.000 MHz */
+ { .mdiv = 0x01, .pe = 0x4053, .sdiv = 0x3, .nsdiv = 1 }, /* 78.800 MHz */
+ { .mdiv = 0x09, .pe = 0x15b5, .sdiv = 0x1, .nsdiv = 0 }, /* 85.500 MHz */
+ { .mdiv = 0x1b, .pe = 0x3f19, .sdiv = 0x2, .nsdiv = 1 }, /* 88.750 MHz */
+ { .mdiv = 0x10, .pe = 0x71c7, .sdiv = 0x2, .nsdiv = 1 }, /* 108.000 MHz */
+ { .mdiv = 0x00, .pe = 0x47af, .sdiv = 0x1, .nsdiv = 0 }, /* 108.108 MHz */
+ { .mdiv = 0x0c, .pe = 0x3118, .sdiv = 0x2, .nsdiv = 1 }, /* 118.963 MHz */
+ { .mdiv = 0x0c, .pe = 0x2f54, .sdiv = 0x2, .nsdiv = 1 }, /* 119.000 MHz */
+ { .mdiv = 0x07, .pe = 0xe39, .sdiv = 0x2, .nsdiv = 1 }, /* 135.000 MHz */
+ { .mdiv = 0x03, .pe = 0x4ba7, .sdiv = 0x2, .nsdiv = 1 }, /* 148.352 MHz */
+ { .mdiv = 0x0f, .pe = 0x3426, .sdiv = 0x0, .nsdiv = 0 }, /* 148.500 MHz */
+ { .mdiv = 0x03, .pe = 0x4ba7, .sdiv = 0x1, .nsdiv = 1 }, /* 296.704 MHz */
+ { .mdiv = 0x03, .pe = 0x471c, .sdiv = 0x1, .nsdiv = 1 }, /* 297.000 MHz */
+ { .mdiv = 0x00, .pe = 0x295f, .sdiv = 0x1, .nsdiv = 1 }, /* 326.700 MHz */
+ { .mdiv = 0x1f, .pe = 0x3633, .sdiv = 0x0, .nsdiv = 1 }, /* 333.000 MHz */
+ { .mdiv = 0x1c, .pe = 0x0, .sdiv = 0x0, .nsdiv = 1 }, /* 352.000 Mhz */
};
struct clkgen_quadfs_data {
bool reset_present;
bool bwfilter_present;
bool lockstatus_present;
+ bool powerup_polarity;
+ bool standby_polarity;
bool nsdiv_present;
+ bool nrst_present;
struct clkgen_field ndiv;
struct clkgen_field ref_bw;
struct clkgen_field nreset;
struct clkgen_field npda;
struct clkgen_field lock_status;
+ struct clkgen_field nrst[QUADFS_MAX_CHAN];
struct clkgen_field nsb[QUADFS_MAX_CHAN];
struct clkgen_field en[QUADFS_MAX_CHAN];
struct clkgen_field mdiv[QUADFS_MAX_CHAN];
@@ -82,9 +137,9 @@ struct clkgen_quadfs_data {
struct clkgen_field nsdiv[QUADFS_MAX_CHAN];
const struct clk_ops *pll_ops;
- struct stm_fs *rtbl;
+ const struct stm_fs *rtbl;
u8 rtbl_cnt;
- int (*get_rate)(unsigned long , struct stm_fs *,
+ int (*get_rate)(unsigned long , const struct stm_fs *,
unsigned long *);
};
@@ -94,11 +149,11 @@ static const struct clk_ops st_quadfs_fs216c65_ops;
static const struct clk_ops st_quadfs_fs432c65_ops;
static const struct clk_ops st_quadfs_fs660c32_ops;
-static int clk_fs216c65_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs216c65_get_rate(unsigned long, const struct stm_fs *,
unsigned long *);
-static int clk_fs432c65_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs432c65_get_rate(unsigned long, const struct stm_fs *,
unsigned long *);
-static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *,
+static int clk_fs660c32_dig_get_rate(unsigned long, const struct stm_fs *,
unsigned long *);
/*
* Values for all of the standalone instances of this clock
@@ -106,7 +161,7 @@ static int clk_fs660c32_dig_get_rate(unsigned long, struct stm_fs *,
* that the individual channel standby control bits (nsb) are in the
* first register along with the PLL control bits.
*/
-static struct clkgen_quadfs_data st_fs216c65_416 = {
+static const struct clkgen_quadfs_data st_fs216c65_416 = {
/* 416 specific */
.npda = CLKGEN_FIELD(0x0, 0x1, 14),
.nsb = { CLKGEN_FIELD(0x0, 0x1, 10),
@@ -143,7 +198,7 @@ static struct clkgen_quadfs_data st_fs216c65_416 = {
.get_rate = clk_fs216c65_get_rate,
};
-static struct clkgen_quadfs_data st_fs432c65_416 = {
+static const struct clkgen_quadfs_data st_fs432c65_416 = {
.npda = CLKGEN_FIELD(0x0, 0x1, 14),
.nsb = { CLKGEN_FIELD(0x0, 0x1, 10),
CLKGEN_FIELD(0x0, 0x1, 11),
@@ -179,7 +234,7 @@ static struct clkgen_quadfs_data st_fs432c65_416 = {
.get_rate = clk_fs432c65_get_rate,
};
-static struct clkgen_quadfs_data st_fs660c32_E_416 = {
+static const struct clkgen_quadfs_data st_fs660c32_E_416 = {
.npda = CLKGEN_FIELD(0x0, 0x1, 14),
.nsb = { CLKGEN_FIELD(0x0, 0x1, 10),
CLKGEN_FIELD(0x0, 0x1, 11),
@@ -215,7 +270,7 @@ static struct clkgen_quadfs_data st_fs660c32_E_416 = {
.get_rate = clk_fs660c32_dig_get_rate,
};
-static struct clkgen_quadfs_data st_fs660c32_F_416 = {
+static const struct clkgen_quadfs_data st_fs660c32_F_416 = {
.npda = CLKGEN_FIELD(0x0, 0x1, 14),
.nsb = { CLKGEN_FIELD(0x0, 0x1, 10),
CLKGEN_FIELD(0x0, 0x1, 11),
@@ -251,6 +306,91 @@ static struct clkgen_quadfs_data st_fs660c32_F_416 = {
.get_rate = clk_fs660c32_dig_get_rate,
};
+static const struct clkgen_quadfs_data st_fs660c32_C_407 = {
+ .nrst_present = true,
+ .nrst = { CLKGEN_FIELD(0x2f0, 0x1, 0),
+ CLKGEN_FIELD(0x2f0, 0x1, 1),
+ CLKGEN_FIELD(0x2f0, 0x1, 2),
+ CLKGEN_FIELD(0x2f0, 0x1, 3) },
+ .npda = CLKGEN_FIELD(0x2f0, 0x1, 12),
+ .nsb = { CLKGEN_FIELD(0x2f0, 0x1, 8),
+ CLKGEN_FIELD(0x2f0, 0x1, 9),
+ CLKGEN_FIELD(0x2f0, 0x1, 10),
+ CLKGEN_FIELD(0x2f0, 0x1, 11) },
+ .nsdiv_present = true,
+ .nsdiv = { CLKGEN_FIELD(0x304, 0x1, 24),
+ CLKGEN_FIELD(0x308, 0x1, 24),
+ CLKGEN_FIELD(0x30c, 0x1, 24),
+ CLKGEN_FIELD(0x310, 0x1, 24) },
+ .mdiv = { CLKGEN_FIELD(0x304, 0x1f, 15),
+ CLKGEN_FIELD(0x308, 0x1f, 15),
+ CLKGEN_FIELD(0x30c, 0x1f, 15),
+ CLKGEN_FIELD(0x310, 0x1f, 15) },
+ .en = { CLKGEN_FIELD(0x2fc, 0x1, 0),
+ CLKGEN_FIELD(0x2fc, 0x1, 1),
+ CLKGEN_FIELD(0x2fc, 0x1, 2),
+ CLKGEN_FIELD(0x2fc, 0x1, 3) },
+ .ndiv = CLKGEN_FIELD(0x2f4, 0x7, 16),
+ .pe = { CLKGEN_FIELD(0x304, 0x7fff, 0),
+ CLKGEN_FIELD(0x308, 0x7fff, 0),
+ CLKGEN_FIELD(0x30c, 0x7fff, 0),
+ CLKGEN_FIELD(0x310, 0x7fff, 0) },
+ .sdiv = { CLKGEN_FIELD(0x304, 0xf, 20),
+ CLKGEN_FIELD(0x308, 0xf, 20),
+ CLKGEN_FIELD(0x30c, 0xf, 20),
+ CLKGEN_FIELD(0x310, 0xf, 20) },
+ .lockstatus_present = true,
+ .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
+ .powerup_polarity = 1,
+ .standby_polarity = 1,
+ .pll_ops = &st_quadfs_pll_c32_ops,
+ .rtbl = fs660c32_rtbl,
+ .rtbl_cnt = ARRAY_SIZE(fs660c32_rtbl),
+ .get_rate = clk_fs660c32_dig_get_rate,
+};
+
+static const struct clkgen_quadfs_data st_fs660c32_D_407 = {
+ .nrst_present = true,
+ .nrst = { CLKGEN_FIELD(0x2a0, 0x1, 0),
+ CLKGEN_FIELD(0x2a0, 0x1, 1),
+ CLKGEN_FIELD(0x2a0, 0x1, 2),
+ CLKGEN_FIELD(0x2a0, 0x1, 3) },
+ .ndiv = CLKGEN_FIELD(0x2a4, 0x7, 16),
+ .pe = { CLKGEN_FIELD(0x2b4, 0x7fff, 0),
+ CLKGEN_FIELD(0x2b8, 0x7fff, 0),
+ CLKGEN_FIELD(0x2bc, 0x7fff, 0),
+ CLKGEN_FIELD(0x2c0, 0x7fff, 0) },
+ .sdiv = { CLKGEN_FIELD(0x2b4, 0xf, 20),
+ CLKGEN_FIELD(0x2b8, 0xf, 20),
+ CLKGEN_FIELD(0x2bc, 0xf, 20),
+ CLKGEN_FIELD(0x2c0, 0xf, 20) },
+ .npda = CLKGEN_FIELD(0x2a0, 0x1, 12),
+ .nsb = { CLKGEN_FIELD(0x2a0, 0x1, 8),
+ CLKGEN_FIELD(0x2a0, 0x1, 9),
+ CLKGEN_FIELD(0x2a0, 0x1, 10),
+ CLKGEN_FIELD(0x2a0, 0x1, 11) },
+ .nsdiv_present = true,
+ .nsdiv = { CLKGEN_FIELD(0x2b4, 0x1, 24),
+ CLKGEN_FIELD(0x2b8, 0x1, 24),
+ CLKGEN_FIELD(0x2bc, 0x1, 24),
+ CLKGEN_FIELD(0x2c0, 0x1, 24) },
+ .mdiv = { CLKGEN_FIELD(0x2b4, 0x1f, 15),
+ CLKGEN_FIELD(0x2b8, 0x1f, 15),
+ CLKGEN_FIELD(0x2bc, 0x1f, 15),
+ CLKGEN_FIELD(0x2c0, 0x1f, 15) },
+ .en = { CLKGEN_FIELD(0x2ac, 0x1, 0),
+ CLKGEN_FIELD(0x2ac, 0x1, 1),
+ CLKGEN_FIELD(0x2ac, 0x1, 2),
+ CLKGEN_FIELD(0x2ac, 0x1, 3) },
+ .lockstatus_present = true,
+ .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24),
+ .powerup_polarity = 1,
+ .standby_polarity = 1,
+ .pll_ops = &st_quadfs_pll_c32_ops,
+ .rtbl = fs660c32_rtbl,
+ .rtbl_cnt = ARRAY_SIZE(fs660c32_rtbl),
+ .get_rate = clk_fs660c32_dig_get_rate,};
+
/**
* DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
*
@@ -308,7 +448,7 @@ static int quadfs_pll_enable(struct clk_hw *hw)
/*
* Power up the PLL
*/
- CLKGEN_WRITE(pll, npda, 1);
+ CLKGEN_WRITE(pll, npda, !pll->data->powerup_polarity);
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
@@ -335,7 +475,7 @@ static void quadfs_pll_disable(struct clk_hw *hw)
* Powerdown the PLL and then put block into soft reset if we have
* reset control.
*/
- CLKGEN_WRITE(pll, npda, 0);
+ CLKGEN_WRITE(pll, npda, pll->data->powerup_polarity);
if (pll->data->reset_present)
CLKGEN_WRITE(pll, nreset, 0);
@@ -611,7 +751,10 @@ static int quadfs_fsynth_enable(struct clk_hw *hw)
if (fs->lock)
spin_lock_irqsave(fs->lock, flags);
- CLKGEN_WRITE(fs, nsb[fs->chan], 1);
+ CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
+
+ if (fs->data->nrst_present)
+ CLKGEN_WRITE(fs, nrst[fs->chan], 0);
if (fs->lock)
spin_unlock_irqrestore(fs->lock, flags);
@@ -631,7 +774,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw)
if (fs->lock)
spin_lock_irqsave(fs->lock, flags);
- CLKGEN_WRITE(fs, nsb[fs->chan], 0);
+ CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity);
if (fs->lock)
spin_unlock_irqrestore(fs->lock, flags);
@@ -645,12 +788,12 @@ static int quadfs_fsynth_is_enabled(struct clk_hw *hw)
pr_debug("%s: %s enable bit = 0x%x\n",
__func__, __clk_get_name(hw->clk), nsb);
- return !!nsb;
+ return fs->data->standby_polarity ? !nsb : !!nsb;
}
#define P15 (uint64_t)(1 << 15)
-static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs216c65_get_rate(unsigned long input, const struct stm_fs *fs,
unsigned long *rate)
{
uint64_t res;
@@ -670,7 +813,7 @@ static int clk_fs216c65_get_rate(unsigned long input, struct stm_fs *fs,
return 0;
}
-static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs432c65_get_rate(unsigned long input, const struct stm_fs *fs,
unsigned long *rate)
{
uint64_t res;
@@ -693,7 +836,7 @@ static int clk_fs432c65_get_rate(unsigned long input, struct stm_fs *fs,
#define P20 (uint64_t)(1 << 20)
static int clk_fs660c32_dig_get_rate(unsigned long input,
- struct stm_fs *fs, unsigned long *rate)
+ const struct stm_fs *fs, unsigned long *rate)
{
unsigned long s = (1 << fs->sdiv);
unsigned long ns;
@@ -749,7 +892,7 @@ static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
{
struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
int (*clk_fs_get_rate)(unsigned long ,
- struct stm_fs *, unsigned long *);
+ const struct stm_fs *, unsigned long *);
struct stm_fs prev_params;
unsigned long prev_rate, rate = 0;
unsigned long diff_rate, prev_diff_rate = ~0;
@@ -793,7 +936,7 @@ static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
unsigned long rate = 0;
struct stm_fs params;
int (*clk_fs_get_rate)(unsigned long ,
- struct stm_fs *, unsigned long *);
+ const struct stm_fs *, unsigned long *);
clk_fs_get_rate = fs->data->get_rate;
@@ -917,19 +1060,31 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
static struct of_device_id quadfs_of_match[] = {
{
.compatible = "st,stih416-quadfs216",
- .data = (void *)&st_fs216c65_416
+ .data = &st_fs216c65_416
},
{
.compatible = "st,stih416-quadfs432",
- .data = (void *)&st_fs432c65_416
+ .data = &st_fs432c65_416
},
{
.compatible = "st,stih416-quadfs660-E",
- .data = (void *)&st_fs660c32_E_416
+ .data = &st_fs660c32_E_416
},
{
.compatible = "st,stih416-quadfs660-F",
- .data = (void *)&st_fs660c32_F_416
+ .data = &st_fs660c32_F_416
+ },
+ {
+ .compatible = "st,stih407-quadfs660-C",
+ .data = &st_fs660c32_C_407
+ },
+ {
+ .compatible = "st,stih407-quadfs660-D",
+ .data = &st_fs660c32_D_407
+ },
+ {
+ .compatible = "st,stih407-quadfs660-D",
+ .data = (void *)&st_fs660c32_D_407
},
{}
};
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index a329906d1e81..79dc40b5cc68 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -580,6 +580,11 @@ static struct clkgen_mux_data stih416_a9_mux_data = {
.shift = 0,
.width = 2,
};
+static struct clkgen_mux_data stih407_a9_mux_data = {
+ .offset = 0x1a4,
+ .shift = 1,
+ .width = 2,
+};
static struct of_device_id mux_of_match[] = {
{
@@ -610,6 +615,10 @@ static struct of_device_id mux_of_match[] = {
.compatible = "st,stih416-clkgen-a9-mux",
.data = &stih416_a9_mux_data,
},
+ {
+ .compatible = "st,stih407-clkgen-a9-mux",
+ .data = &stih407_a9_mux_data,
+ },
{}
};
@@ -765,7 +774,8 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
div->reg = reg + VCC_DIV_OFFSET;
div->shift = 2 * i;
div->width = 2;
- div->flags = CLK_DIVIDER_POWER_OF_TWO;
+ div->flags = CLK_DIVIDER_POWER_OF_TWO |
+ CLK_DIVIDER_ROUND_CLOSEST;
mux->reg = reg + VCC_MUX_OFFSET;
mux->shift = 2 * i;
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index d8b9b1a2aeda..29769d79e306 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -59,7 +59,7 @@ static const struct clk_ops st_pll800c65_ops;
static const struct clk_ops stm_pll3200c32_ops;
static const struct clk_ops st_pll1200c32_ops;
-static struct clkgen_pll_data st_pll1600c65_ax = {
+static const struct clkgen_pll_data st_pll1600c65_ax = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 19),
.locked_status = CLKGEN_FIELD(0x0, 0x1, 31),
.mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK, 0),
@@ -67,7 +67,7 @@ static struct clkgen_pll_data st_pll1600c65_ax = {
.ops = &st_pll1600c65_ops
};
-static struct clkgen_pll_data st_pll800c65_ax = {
+static const struct clkgen_pll_data st_pll800c65_ax = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 19),
.locked_status = CLKGEN_FIELD(0x0, 0x1, 31),
.mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL800_MASK, 0),
@@ -76,7 +76,7 @@ static struct clkgen_pll_data st_pll800c65_ax = {
.ops = &st_pll800c65_ops
};
-static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
+static const struct clkgen_pll_data st_pll3200c32_a1x_0 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 31),
.locked_status = CLKGEN_FIELD(0x4, 0x1, 31),
.ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 0x0),
@@ -93,7 +93,7 @@ static struct clkgen_pll_data st_pll3200c32_a1x_0 = {
.ops = &stm_pll3200c32_ops,
};
-static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
+static const struct clkgen_pll_data st_pll3200c32_a1x_1 = {
.pdn_status = CLKGEN_FIELD(0xC, 0x1, 31),
.locked_status = CLKGEN_FIELD(0x10, 0x1, 31),
.ndiv = CLKGEN_FIELD(0xC, C32_NDIV_MASK, 0x0),
@@ -111,7 +111,7 @@ static struct clkgen_pll_data st_pll3200c32_a1x_1 = {
};
/* 415 specific */
-static struct clkgen_pll_data st_pll3200c32_a9_415 = {
+static const struct clkgen_pll_data st_pll3200c32_a9_415 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x6C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 9),
@@ -122,7 +122,7 @@ static struct clkgen_pll_data st_pll3200c32_a9_415 = {
.ops = &stm_pll3200c32_ops,
};
-static struct clkgen_pll_data st_pll3200c32_ddr_415 = {
+static const struct clkgen_pll_data st_pll3200c32_ddr_415 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x100, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
@@ -135,7 +135,7 @@ static struct clkgen_pll_data st_pll3200c32_ddr_415 = {
.ops = &stm_pll3200c32_ops,
};
-static struct clkgen_pll_data st_pll1200c32_gpu_415 = {
+static const struct clkgen_pll_data st_pll1200c32_gpu_415 = {
.pdn_status = CLKGEN_FIELD(0x144, 0x1, 3),
.locked_status = CLKGEN_FIELD(0x168, 0x1, 0),
.ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3),
@@ -146,7 +146,7 @@ static struct clkgen_pll_data st_pll1200c32_gpu_415 = {
};
/* 416 specific */
-static struct clkgen_pll_data st_pll3200c32_a9_416 = {
+static const struct clkgen_pll_data st_pll3200c32_a9_416 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x6C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
@@ -157,7 +157,7 @@ static struct clkgen_pll_data st_pll3200c32_a9_416 = {
.ops = &stm_pll3200c32_ops,
};
-static struct clkgen_pll_data st_pll3200c32_ddr_416 = {
+static const struct clkgen_pll_data st_pll3200c32_ddr_416 = {
.pdn_status = CLKGEN_FIELD(0x0, 0x1, 0),
.locked_status = CLKGEN_FIELD(0x10C, 0x1, 0),
.ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0),
@@ -170,7 +170,7 @@ static struct clkgen_pll_data st_pll3200c32_ddr_416 = {
.ops = &stm_pll3200c32_ops,
};
-static struct clkgen_pll_data st_pll1200c32_gpu_416 = {
+static const struct clkgen_pll_data st_pll1200c32_gpu_416 = {
.pdn_status = CLKGEN_FIELD(0x8E4, 0x1, 3),
.locked_status = CLKGEN_FIELD(0x90C, 0x1, 0),
.ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3),
@@ -180,6 +180,54 @@ static struct clkgen_pll_data st_pll1200c32_gpu_416 = {
.ops = &st_pll1200c32_ops,
};
+static const struct clkgen_pll_data st_pll3200c32_407_a0 = {
+ /* 407 A0 */
+ .pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8),
+ .locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24),
+ .ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16),
+ .idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0),
+ .num_odfs = 1,
+ .odf = { CLKGEN_FIELD(0x2b4, C32_ODF_MASK, 0) },
+ .odf_gate = { CLKGEN_FIELD(0x2b4, 0x1, 6) },
+ .ops = &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_c0_0 = {
+ /* 407 C0 PLL0 */
+ .pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8),
+ .locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24),
+ .ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16),
+ .idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0),
+ .num_odfs = 1,
+ .odf = { CLKGEN_FIELD(0x2b4, C32_ODF_MASK, 0) },
+ .odf_gate = { CLKGEN_FIELD(0x2b4, 0x1, 6) },
+ .ops = &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_c0_1 = {
+ /* 407 C0 PLL1 */
+ .pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8),
+ .locked_status = CLKGEN_FIELD(0x2c8, 0x1, 24),
+ .ndiv = CLKGEN_FIELD(0x2cc, C32_NDIV_MASK, 16),
+ .idf = CLKGEN_FIELD(0x2cc, C32_IDF_MASK, 0x0),
+ .num_odfs = 1,
+ .odf = { CLKGEN_FIELD(0x2dc, C32_ODF_MASK, 0) },
+ .odf_gate = { CLKGEN_FIELD(0x2dc, 0x1, 6) },
+ .ops = &stm_pll3200c32_ops,
+};
+
+static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
+ /* 407 A9 */
+ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
+ .locked_status = CLKGEN_FIELD(0x87c, 0x1, 0),
+ .ndiv = CLKGEN_FIELD(0x1b0, C32_NDIV_MASK, 0),
+ .idf = CLKGEN_FIELD(0x1a8, C32_IDF_MASK, 25),
+ .num_odfs = 1,
+ .odf = { CLKGEN_FIELD(0x1b0, C32_ODF_MASK, 8) },
+ .odf_gate = { CLKGEN_FIELD(0x1ac, 0x1, 28) },
+ .ops = &stm_pll3200c32_ops,
+};
+
/**
* DOC: Clock Generated by PLL, rate set and enabled by bootloader
*
@@ -450,9 +498,8 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
* PLL0 HS (high speed) output
*/
clk_data->clks[0] = clkgen_pll_register(parent_name,
- &st_pll1600c65_ax,
- reg + CLKGENAx_PLL0_OFFSET,
- clk_name);
+ (struct clkgen_pll_data *) &st_pll1600c65_ax,
+ reg + CLKGENAx_PLL0_OFFSET, clk_name);
if (IS_ERR(clk_data->clks[0]))
goto err;
@@ -480,9 +527,8 @@ static void __init clkgena_c65_pll_setup(struct device_node *np)
* PLL1 output
*/
clk_data->clks[2] = clkgen_pll_register(parent_name,
- &st_pll800c65_ax,
- reg + CLKGENAx_PLL1_OFFSET,
- clk_name);
+ (struct clkgen_pll_data *) &st_pll800c65_ax,
+ reg + CLKGENAx_PLL1_OFFSET, clk_name);
if (IS_ERR(clk_data->clks[2]))
goto err;
@@ -572,6 +618,22 @@ static struct of_device_id c32_pll_of_match[] = {
.compatible = "st,stih416-plls-c32-ddr",
.data = &st_pll3200c32_ddr_416,
},
+ {
+ .compatible = "st,stih407-plls-c32-a0",
+ .data = &st_pll3200c32_407_a0,
+ },
+ {
+ .compatible = "st,stih407-plls-c32-c0_0",
+ .data = &st_pll3200c32_407_c0_0,
+ },
+ {
+ .compatible = "st,stih407-plls-c32-c0_1",
+ .data = &st_pll3200c32_407_c0_1,
+ },
+ {
+ .compatible = "st,stih407-plls-c32-a9",
+ .data = &st_pll3200c32_407_a9,
+ },
{}
};
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 762fd64dbd1f..6850cba35871 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -6,4 +6,6 @@ obj-y += clk-sunxi.o clk-factors.o
obj-y += clk-a10-hosc.o
obj-y += clk-a20-gmac.o
-obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o
+obj-$(CONFIG_MFD_SUN6I_PRCM) += \
+ clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
+ clk-sun8i-apb0.o
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c
index 633ddc4389ef..5296fd6dd7b3 100644
--- a/drivers/clk/sunxi/clk-a20-gmac.c
+++ b/drivers/clk/sunxi/clk-a20-gmac.c
@@ -60,7 +60,7 @@ static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
struct clk_gate *gate;
const char *clk_name = node->name;
const char *parents[SUN7I_A20_GMAC_PARENTS];
- void *reg;
+ void __iomem *reg;
if (of_property_read_string(node, "clock-output-names", &clk_name))
return;
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 3806d97e529b..2057c8ac648f 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
p = FACTOR_GET(config->pshift, config->pwidth, reg);
/* Calculate the rate */
- rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1);
return rate;
}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index 02e1a43ebac7..d2d0efa39379 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -15,6 +15,7 @@ struct clk_factors_config {
u8 mwidth;
u8 pshift;
u8 pwidth;
+ u8 n_start;
};
struct clk_factors {
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
index 670f90d629d7..e10d0521ec76 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
@@ -9,23 +9,53 @@
*/
#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#define SUN6I_APB0_GATES_MAX_SIZE 32
+struct gates_data {
+ DECLARE_BITMAP(mask, SUN6I_APB0_GATES_MAX_SIZE);
+};
+
+static const struct gates_data sun6i_a31_apb0_gates __initconst = {
+ .mask = {0x7F},
+};
+
+static const struct gates_data sun8i_a23_apb0_gates __initconst = {
+ .mask = {0x5D},
+};
+
+static const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
+ { .compatible = "allwinner,sun6i-a31-apb0-gates-clk", .data = &sun6i_a31_apb0_gates },
+ { .compatible = "allwinner,sun8i-a23-apb0-gates-clk", .data = &sun8i_a23_apb0_gates },
+ { /* sentinel */ }
+};
+
static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct clk_onecell_data *clk_data;
+ const struct of_device_id *device;
+ const struct gates_data *data;
const char *clk_parent;
const char *clk_name;
struct resource *r;
void __iomem *reg;
- int gate_id;
int ngates;
int i;
+ int j = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ device = of_match_device(sun6i_a31_apb0_gates_clk_dt_ids, &pdev->dev);
+ if (!device)
+ return -ENODEV;
+ data = device->data;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg = devm_ioremap_resource(&pdev->dev, r);
@@ -36,54 +66,36 @@ static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
if (!clk_parent)
return -EINVAL;
- ngates = of_property_count_strings(np, "clock-output-names");
- if (ngates < 0)
- return ngates;
-
- if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE)
- return -EINVAL;
-
clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
- clk_data->clks = devm_kzalloc(&pdev->dev,
- SUN6I_APB0_GATES_MAX_SIZE *
- sizeof(struct clk *),
- GFP_KERNEL);
+ /* Worst-case size approximation and memory allocation */
+ ngates = find_last_bit(data->mask, SUN6I_APB0_GATES_MAX_SIZE);
+ clk_data->clks = devm_kcalloc(&pdev->dev, (ngates + 1),
+ sizeof(struct clk *), GFP_KERNEL);
if (!clk_data->clks)
return -ENOMEM;
- for (i = 0; i < ngates; i++) {
+ for_each_set_bit(i, data->mask, SUN6I_APB0_GATES_MAX_SIZE) {
of_property_read_string_index(np, "clock-output-names",
- i, &clk_name);
+ j, &clk_name);
- gate_id = i;
- of_property_read_u32_index(np, "clock-indices", i, &gate_id);
+ clk_data->clks[i] = clk_register_gate(&pdev->dev, clk_name,
+ clk_parent, 0, reg, i,
+ 0, NULL);
+ WARN_ON(IS_ERR(clk_data->clks[i]));
+ clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
- WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE);
- if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE)
- continue;
-
- clk_data->clks[gate_id] = clk_register_gate(&pdev->dev,
- clk_name,
- clk_parent, 0,
- reg, gate_id,
- 0, NULL);
- WARN_ON(IS_ERR(clk_data->clks[gate_id]));
+ j++;
}
- clk_data->clk_num = ngates;
+ clk_data->clk_num = ngates + 1;
return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
}
-const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
- { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" },
- { /* sentinel */ }
-};
-
static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
.driver = {
.name = "sun6i-a31-apb0-gates-clk",
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
index 11f17c34c2ae..1fa23371c8c6 100644
--- a/drivers/clk/sunxi/clk-sun6i-apb0.c
+++ b/drivers/clk/sunxi/clk-sun6i-apb0.c
@@ -57,7 +57,7 @@ static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev)
return of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
-const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
+static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-apb0-clk" },
{ /* sentinel */ }
};
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index f73cc051f0dd..eca8ca025b6a 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -160,7 +160,7 @@ static int ar100_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-struct clk_ops ar100_ops = {
+static struct clk_ops ar100_ops = {
.recalc_rate = ar100_recalc_rate,
.determine_rate = ar100_determine_rate,
.set_parent = ar100_set_parent,
@@ -213,7 +213,7 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
return of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
-const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
+static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-ar100-clk" },
{ /* sentinel */ }
};
diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c
new file mode 100644
index 000000000000..1f5ba9b4b8cd
--- /dev/null
+++ b/drivers/clk/sunxi/clk-sun8i-apb0.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Chen-Yu Tsai
+ * Author: Chen-Yu Tsai <wens@csie.org>
+ *
+ * Allwinner A23 APB0 clock driver
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Based on clk-sun6i-apb0.c
+ * Allwinner A31 APB0 clock driver
+ *
+ * Copyright (C) 2014 Free Electrons
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const char *clk_name = np->name;
+ const char *clk_parent;
+ struct resource *r;
+ void __iomem *reg;
+ struct clk *clk;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ clk_parent = of_clk_get_parent_name(np, 0);
+ if (!clk_parent)
+ return -EINVAL;
+
+ of_property_read_string(np, "clock-output-names", &clk_name);
+
+ /* The A23 APB0 clock is a standard 2 bit wide divider clock */
+ clk = clk_register_divider(&pdev->dev, clk_name, clk_parent, 0, reg,
+ 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ return of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
+ { .compatible = "allwinner,sun8i-a23-apb0-clk" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun8i_a23_apb0_clk_driver = {
+ .driver = {
+ .name = "sun8i-a23-apb0-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = sun8i_a23_apb0_clk_dt_ids,
+ },
+ .probe = sun8i_a23_apb0_clk_probe,
+};
+module_platform_driver(sun8i_a23_apb0_clk_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_DESCRIPTION("Allwinner A23 APB0 clock Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index fb2ce8440f0e..b654b7b1d137 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -164,6 +164,54 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
}
/**
+ * sun8i_a23_get_pll1_factors() - calculates n, k, m, p factors for PLL1
+ * PLL1 rate is calculated as follows
+ * rate = (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
+ * parent_rate is always 24Mhz
+ */
+
+static void sun8i_a23_get_pll1_factors(u32 *freq, u32 parent_rate,
+ u8 *n, u8 *k, u8 *m, u8 *p)
+{
+ u8 div;
+
+ /* Normalize value to a 6M multiple */
+ div = *freq / 6000000;
+ *freq = 6000000 * div;
+
+ /* we were called to round the frequency, we can now return */
+ if (n == NULL)
+ return;
+
+ /* m is always zero for pll1 */
+ *m = 0;
+
+ /* k is 1 only on these cases */
+ if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000)
+ *k = 1;
+ else
+ *k = 0;
+
+ /* p will be 2 for divs under 20 and odd divs under 32 */
+ if (div < 20 || (div < 32 && (div & 1)))
+ *p = 2;
+
+ /* p will be 1 for even divs under 32, divs under 40 and odd pairs
+ * of divs between 40-62 */
+ else if (div < 40 || (div < 64 && (div & 2)))
+ *p = 1;
+
+ /* any other entries have p = 0 */
+ else
+ *p = 0;
+
+ /* calculate a suitable n based on k and p */
+ div <<= *p;
+ div /= (*k + 1);
+ *n = div / 4 - 1;
+}
+
+/**
* sun4i_get_pll5_factors() - calculates n, k factors for PLL5
* PLL5 rate is calculated as follows
* rate = parent_rate * n * (k + 1)
@@ -422,6 +470,18 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
.mwidth = 2,
};
+static struct clk_factors_config sun8i_a23_pll1_config = {
+ .nshift = 8,
+ .nwidth = 5,
+ .kshift = 4,
+ .kwidth = 2,
+ .mshift = 0,
+ .mwidth = 2,
+ .pshift = 16,
+ .pwidth = 2,
+ .n_start = 1,
+};
+
static struct clk_factors_config sun4i_pll5_config = {
.nshift = 8,
.nwidth = 5,
@@ -471,6 +531,12 @@ static const struct factors_data sun6i_a31_pll1_data __initconst = {
.getter = sun6i_a31_get_pll1_factors,
};
+static const struct factors_data sun8i_a23_pll1_data __initconst = {
+ .enable = 31,
+ .table = &sun8i_a23_pll1_config,
+ .getter = sun8i_a23_get_pll1_factors,
+};
+
static const struct factors_data sun7i_a20_pll4_data __initconst = {
.enable = 31,
.table = &sun4i_pll5_config,
@@ -527,7 +593,7 @@ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
struct clk_hw *mux_hw = NULL;
const char *clk_name = node->name;
const char *parents[SUNXI_MAX_PARENTS];
- void *reg;
+ void __iomem *reg;
int i = 0;
reg = of_iomap(node, 0);
@@ -632,7 +698,7 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
struct clk *clk;
const char *clk_name = node->name;
const char *parents[SUNXI_MAX_PARENTS];
- void *reg;
+ void __iomem *reg;
int i = 0;
reg = of_iomap(node, 0);
@@ -664,6 +730,7 @@ struct div_data {
u8 shift;
u8 pow;
u8 width;
+ const struct clk_div_table *table;
};
static const struct div_data sun4i_axi_data __initconst = {
@@ -672,6 +739,23 @@ static const struct div_data sun4i_axi_data __initconst = {
.width = 2,
};
+static const struct clk_div_table sun8i_a23_axi_table[] __initconst = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 3 },
+ { .val = 3, .div = 4 },
+ { .val = 4, .div = 4 },
+ { .val = 5, .div = 4 },
+ { .val = 6, .div = 4 },
+ { .val = 7, .div = 4 },
+ { } /* sentinel */
+};
+
+static const struct div_data sun8i_a23_axi_data __initconst = {
+ .width = 3,
+ .table = sun8i_a23_axi_table,
+};
+
static const struct div_data sun4i_ahb_data __initconst = {
.shift = 4,
.pow = 1,
@@ -696,7 +780,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
struct clk *clk;
const char *clk_name = node->name;
const char *clk_parent;
- void *reg;
+ void __iomem *reg;
reg = of_iomap(node, 0);
@@ -704,10 +788,10 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
of_property_read_string(node, "clock-output-names", &clk_name);
- clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
- reg, data->shift, data->width,
- data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
- &clk_lock);
+ clk = clk_register_divider_table(NULL, clk_name, clk_parent, 0,
+ reg, data->shift, data->width,
+ data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
+ data->table, &clk_lock);
if (clk) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
@@ -804,6 +888,10 @@ static const struct gates_data sun7i_a20_ahb_gates_data __initconst = {
.mask = { 0x12f77fff, 0x16ff3f },
};
+static const struct gates_data sun8i_a23_ahb1_gates_data __initconst = {
+ .mask = {0x25386742, 0x2505111},
+};
+
static const struct gates_data sun4i_apb0_gates_data __initconst = {
.mask = {0x4EF},
};
@@ -836,6 +924,10 @@ static const struct gates_data sun6i_a31_apb1_gates_data __initconst = {
.mask = {0x3031},
};
+static const struct gates_data sun8i_a23_apb1_gates_data __initconst = {
+ .mask = {0x3021},
+};
+
static const struct gates_data sun6i_a31_apb2_gates_data __initconst = {
.mask = {0x3F000F},
};
@@ -844,6 +936,10 @@ static const struct gates_data sun7i_a20_apb1_gates_data __initconst = {
.mask = { 0xff80ff },
};
+static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
+ .mask = {0x1F0007},
+};
+
static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
.mask = {0x1C0},
.reset_mask = 0x07,
@@ -866,11 +962,10 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_reset_data *reset_data;
const char *clk_parent;
const char *clk_name;
- void *reg;
+ void __iomem *reg;
int qty;
int i = 0;
int j = 0;
- int ignore;
reg = of_iomap(node, 0);
@@ -891,14 +986,12 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
of_property_read_string_index(node, "clock-output-names",
j, &clk_name);
- /* No driver claims this clock, but it should remain gated */
- ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0;
-
clk_data->clks[i] = clk_register_gate(NULL, clk_name,
- clk_parent, ignore,
+ clk_parent, 0,
reg + 4 * (i/32), i % 32,
0, &clk_lock);
WARN_ON(IS_ERR(clk_data->clks[i]));
+ clk_register_clkdev(clk_data->clks[i], clk_name, NULL);
j++;
}
@@ -991,7 +1084,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
struct clk_gate *gate = NULL;
struct clk_fixed_factor *fix_factor;
struct clk_divider *divider;
- void *reg;
+ void __iomem *reg;
int i = 0;
int flags, clkflags;
@@ -1102,6 +1195,7 @@ free_clkdata:
static const struct of_device_id clk_factors_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-pll1-clk", .data = &sun4i_pll1_data,},
{.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+ {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
@@ -1113,6 +1207,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
/* Matches for divider clocks */
static const struct of_device_id clk_div_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-axi-clk", .data = &sun4i_axi_data,},
+ {.compatible = "allwinner,sun8i-a23-axi-clk", .data = &sun8i_a23_axi_data,},
{.compatible = "allwinner,sun4i-a10-ahb-clk", .data = &sun4i_ahb_data,},
{.compatible = "allwinner,sun4i-a10-apb0-clk", .data = &sun4i_apb0_data,},
{.compatible = "allwinner,sun6i-a31-apb2-div-clk", .data = &sun6i_a31_apb2_div_data,},
@@ -1142,6 +1237,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
+ {.compatible = "allwinner,sun8i-a23-ahb1-gates-clk", .data = &sun8i_a23_ahb1_gates_data,},
{.compatible = "allwinner,sun4i-a10-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a10s-apb0-gates-clk", .data = &sun5i_a10s_apb0_gates_data,},
{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
@@ -1151,7 +1247,9 @@ static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb1-gates-clk", .data = &sun6i_a31_apb1_gates_data,},
{.compatible = "allwinner,sun7i-a20-apb1-gates-clk", .data = &sun7i_a20_apb1_gates_data,},
+ {.compatible = "allwinner,sun8i-a23-apb1-gates-clk", .data = &sun8i_a23_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
+ {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
{.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
{.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
{.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
@@ -1202,6 +1300,7 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
static const char *sun4i_a10_critical_clocks[] __initdata = {
"pll5_ddr",
+ "ahb_sdram",
};
static void __init sun4i_a10_init_clocks(struct device_node *node)
@@ -1214,6 +1313,7 @@ CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks)
static const char *sun5i_critical_clocks[] __initdata = {
"mbus",
"pll5_ddr",
+ "ahb_sdram",
};
static void __init sun5i_init_clocks(struct device_node *node)
@@ -1236,3 +1336,4 @@ static void __init sun6i_init_clocks(struct device_node *node)
ARRAY_SIZE(sun6i_critical_clocks));
}
CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index 507015314827..0aa8830ae7cc 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -20,7 +20,8 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/tegra-soc.h>
+
+#include <soc/tegra/fuse.h>
#include "clk.h"
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 637b62ccc91e..c7c6d8fb32fb 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -110,6 +110,12 @@
#define XUSBIO_PLL_CFG0_SEQ_ENABLE BIT(24)
#define XUSBIO_PLL_CFG0_SEQ_START_STATE BIT(25)
+#define SATA_PLL_CFG0 0x490
+#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
+#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2)
+#define SATA_PLL_CFG0_SEQ_ENABLE BIT(24)
+#define SATA_PLL_CFG0_SEQ_START_STATE BIT(25)
+
#define PLLE_MISC_PLLE_PTS BIT(8)
#define PLLE_MISC_IDDQ_SW_VALUE BIT(13)
#define PLLE_MISC_IDDQ_SW_CTRL BIT(14)
@@ -1361,6 +1367,19 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
pll_writel(val, XUSBIO_PLL_CFG0, pll);
+ /* Enable hw control of SATA pll */
+ val = pll_readl(SATA_PLL_CFG0, pll);
+ val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
+ val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET;
+ val |= SATA_PLL_CFG0_SEQ_START_STATE;
+ pll_writel(val, SATA_PLL_CFG0, pll);
+
+ udelay(1);
+
+ val = pll_readl(SATA_PLL_CFG0, pll);
+ val |= SATA_PLL_CFG0_SEQ_ENABLE;
+ pll_writel(val, SATA_PLL_CFG0, pll);
+
out:
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index adf6b814b5bc..37f32c49674e 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -469,7 +469,7 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
- MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+ MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8),
MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8),
MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8),
@@ -487,7 +487,7 @@ static struct tegra_periph_init_data periph_clks[] = {
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
- MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
+ MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy),
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index b9c8ba258ef0..f760f31d05c4 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -151,6 +151,13 @@
/* Tegra CPU clock and reset control regs */
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
+#define MUX8(_name, _parents, _offset, \
+ _clk_num, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
+ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+ _clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
+ NULL)
+
#ifdef CONFIG_PM_SLEEP
static struct cpu_clk_suspend_context {
u32 clk_csite_src;
@@ -777,7 +784,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_spdif_in] = { .dt_id = TEGRA114_CLK_SPDIF_IN, .present = true },
[tegra_clk_spdif_out] = { .dt_id = TEGRA114_CLK_SPDIF_OUT, .present = true },
[tegra_clk_vi_8] = { .dt_id = TEGRA114_CLK_VI, .present = true },
- [tegra_clk_vi_sensor_8] = { .dt_id = TEGRA114_CLK_VI_SENSOR, .present = true },
[tegra_clk_fuse] = { .dt_id = TEGRA114_CLK_FUSE, .present = true },
[tegra_clk_fuse_burn] = { .dt_id = TEGRA114_CLK_FUSE_BURN, .present = true },
[tegra_clk_clk_32k] = { .dt_id = TEGRA114_CLK_CLK_32K, .present = true },
@@ -923,6 +929,13 @@ static struct tegra_devclk devclks[] __initdata = {
{ .dev_id = "timer", .dt_id = TEGRA114_CLK_TIMER },
};
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+ "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+static u32 mux_pllm_pllc2_c_c3_pllp_plla_idx[] = {
+ [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
static struct clk **clks;
static unsigned long osc_freq;
@@ -1178,10 +1191,18 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
clks[TEGRA114_CLK_PLL_E_OUT0] = clk;
}
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+
+static struct tegra_periph_init_data tegra_periph_clk_list[] = {
+ MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, TEGRA114_CLK_VI_SENSOR),
+};
+
static __init void tegra114_periph_clk_init(void __iomem *clk_base,
void __iomem *pmc_base)
{
struct clk *clk;
+ struct tegra_periph_init_data *data;
+ int i;
/* xusb_ss_div2 */
clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
@@ -1209,6 +1230,14 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
clk_base + CLK_SOURCE_EMC,
29, 3, 0, NULL);
+ for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+ data = &tegra_periph_clk_list[i];
+ clk = tegra_clk_register_periph(data->name,
+ data->p.parent_names, data->num_parents,
+ &data->periph, clk_base, data->offset, data->flags);
+ clks[data->clk_id] = clk;
+ }
+
tegra_periph_clk_init(clk_base, pmc_base, tegra114_clks,
&pll_p_params);
}
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 80efe51fdcdf..9525c684d149 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -869,7 +869,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_spdif_in] = { .dt_id = TEGRA124_CLK_SPDIF_IN, .present = true },
[tegra_clk_spdif_out] = { .dt_id = TEGRA124_CLK_SPDIF_OUT, .present = true },
[tegra_clk_vi_9] = { .dt_id = TEGRA124_CLK_VI, .present = true },
- [tegra_clk_vi_sensor] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true },
+ [tegra_clk_vi_sensor_8] = { .dt_id = TEGRA124_CLK_VI_SENSOR, .present = true },
[tegra_clk_fuse] = { .dt_id = TEGRA124_CLK_FUSE, .present = true },
[tegra_clk_fuse_burn] = { .dt_id = TEGRA124_CLK_FUSE_BURN, .present = true },
[tegra_clk_clk_32k] = { .dt_id = TEGRA124_CLK_CLK_32K, .present = true },
@@ -1369,6 +1369,14 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0},
{TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0},
{TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
+ {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
+ {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
+ {TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
+ {TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
+ {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
+ {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
+ {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
+ {TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0},
/* This MUST be the last entry. */
{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
};
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 8b10c38b6e3c..5bbacd01094f 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -22,8 +22,11 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/clk/tegra.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
+
#include <dt-bindings/clock/tegra30-car.h>
+
#include "clk.h"
#include "clk-id.h"
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index c0a7d7723510..f87c609e8f72 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -19,7 +19,8 @@
#include <linux/of.h>
#include <linux/clk/tegra.h>
#include <linux/reset-controller.h>
-#include <linux/tegra-soc.h>
+
+#include <soc/tegra/fuse.h>
#include "clk.h"
@@ -277,6 +278,12 @@ void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
for (i = 0; i < num; i++, dev_clks++)
clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
dev_clks->dev_id);
+
+ for (i = 0; i < clk_num; i++) {
+ if (!IS_ERR_OR_NULL(clks[i]))
+ clk_register_clkdev(clks[i], __clk_get_name(clks[i]),
+ "tegra-clk-debug");
+ }
}
struct clk ** __init tegra_lookup_dt_id(int clk_id,
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index cb8e6f14e880..62ac8f6e480c 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -18,6 +18,7 @@
#define DRA7_DPLL_ABE_DEFFREQ 180633600
#define DRA7_DPLL_GMAC_DEFFREQ 1000000000
+#define DRA7_DPLL_USB_DEFFREQ 960000000
static struct ti_dt_clk dra7xx_clks[] = {
@@ -332,5 +333,15 @@ int __init dra7xx_dt_clk_init(void)
if (rc)
pr_err("%s: failed to configure GMAC DPLL!\n", __func__);
+ dpll_ck = clk_get_sys(NULL, "dpll_usb_ck");
+ rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ);
+ if (rc)
+ pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+ dpll_ck = clk_get_sys(NULL, "dpll_usb_m2_ck");
+ rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ/2);
+ if (rc)
+ pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__);
+
return rc;
}
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index fd449f9b006d..162e519cb0f9 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,6 +1,5 @@
# Makefile for Versatile-specific clocks
-obj-$(CONFIG_ICST) += clk-icst.o
-obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
+obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-versatile.c
index 734c4b8fe6ab..a76981e88cb6 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-versatile.c
@@ -1,5 +1,6 @@
/*
- * Clock driver for the ARM Integrator/AP and Integrator/CP boards
+ * Clock driver for the ARM Integrator/AP, Integrator/CP, Versatile AB and
+ * Versatile PB boards.
* Copyright (C) 2012 Linus Walleij
*
* This program is free software; you can redistribute it and/or modify
@@ -17,6 +18,9 @@
#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
+#define VERSATILE_SYS_OSCCLCD_OFFSET 0x1c
+#define VERSATILE_SYS_LOCK_OFFSET 0x20
+
/* Base offset for the core module */
static void __iomem *cm_base;
@@ -37,11 +41,27 @@ static const struct clk_icst_desc __initdata cm_auxosc_desc = {
.lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
};
-static void __init of_integrator_cm_osc_setup(struct device_node *np)
+static const struct icst_params versatile_auxosc_params = {
+ .vco_max = ICST307_VCO_MAX,
+ .vco_min = ICST307_VCO_MIN,
+ .vd_min = 4 + 8,
+ .vd_max = 511 + 8,
+ .rd_min = 1 + 2,
+ .rd_max = 127 + 2,
+ .s2div = icst307_s2div,
+ .idx2s = icst307_idx2s,
+};
+
+static const struct clk_icst_desc versatile_auxosc_desc __initconst = {
+ .params = &versatile_auxosc_params,
+ .vco_offset = VERSATILE_SYS_OSCCLCD_OFFSET,
+ .lock_offset = VERSATILE_SYS_LOCK_OFFSET,
+};
+static void __init cm_osc_setup(struct device_node *np,
+ const struct clk_icst_desc *desc)
{
struct clk *clk = ERR_PTR(-EINVAL);
const char *clk_name = np->name;
- const struct clk_icst_desc *desc = &cm_auxosc_desc;
const char *parent_name;
if (!cm_base) {
@@ -65,5 +85,17 @@ static void __init of_integrator_cm_osc_setup(struct device_node *np)
if (!IS_ERR(clk))
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
+
+static void __init of_integrator_cm_osc_setup(struct device_node *np)
+{
+ cm_osc_setup(np, &cm_auxosc_desc);
+}
CLK_OF_DECLARE(integrator_cm_auxosc_clk,
"arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
+
+static void __init of_versatile_cm_osc_setup(struct device_node *np)
+{
+ cm_osc_setup(np, &versatile_auxosc_desc);
+}
+CLK_OF_DECLARE(versatile_cm_auxosc_clk,
+ "arm,versatile-cm-auxosc", of_versatile_cm_osc_setup);
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 065131cbfcc0..cfd6519df661 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,3 +1,5 @@
+menu "Clock Source drivers"
+
config CLKSRC_OF
bool
@@ -125,6 +127,7 @@ config CLKSRC_METAG_GENERIC
config CLKSRC_EXYNOS_MCT
def_bool y if ARCH_EXYNOS
+ depends on !ARM64
help
Support for Multi Core Timer controller on Exynos SoCs.
@@ -149,6 +152,11 @@ config VF_PIT_TIMER
config SYS_SUPPORTS_SH_CMT
bool
+config MTK_TIMER
+ select CLKSRC_OF
+ select CLKSRC_MMIO
+ bool
+
config SYS_SUPPORTS_SH_MTU2
bool
@@ -173,7 +181,7 @@ config SH_TIMER_MTU2
default SYS_SUPPORTS_SH_MTU2
help
This enables build of a clockevent driver for the Multi-Function
- Timer Pulse Unit 2 (TMU2) hardware available on SoCs from Renesas.
+ Timer Pulse Unit 2 (MTU2) hardware available on SoCs from Renesas.
This hardware comes with 16 bit-timer registers.
config SH_TIMER_TMU
@@ -187,7 +195,7 @@ config SH_TIMER_TMU
config EM_TIMER_STI
bool "Renesas STI timer driver" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
default SYS_SUPPORTS_EM_STI
help
This enables build of a clocksource and clockevent driver for
@@ -207,3 +215,5 @@ config CLKSRC_VERSATILE
counter available in the "System Registers" block of
ARM Versatile, RealView and Versatile Express reference
platforms.
+
+endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 800b1303c236..7fd9fd1dff42 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -16,9 +16,11 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
obj-$(CONFIG_ORION_TIMER) += time-orion.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
+obj-$(CONFIG_ARCH_CLPS711X) += clps711x-timer.o
obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o
obj-$(CONFIG_ARCH_MXS) += mxs_timer.o
+obj-$(CONFIG_ARCH_PXA) += pxa_timer.o
obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
obj-$(CONFIG_ARCH_U300) += timer-u300.o
obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o
obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o
obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o
+obj-$(CONFIG_MTK_TIMER) += mtk_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 60e5a170c4d2..e6833771a716 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -250,7 +250,7 @@ static void __init global_timer_of_register(struct device_node *np)
* fire when the timer value is greater than or equal to. In previous
* revisions the comparators fired when the timer value was equal to.
*/
- if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9
&& (read_cpuid_id() & 0xf0000f) < 0x200000) {
pr_warn("global-timer: non support for this cpu version.\n");
return;
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c
new file mode 100644
index 000000000000..d83ec1f2fddc
--- /dev/null
+++ b/drivers/clocksource/clps711x-timer.c
@@ -0,0 +1,131 @@
+/*
+ * Cirrus Logic CLPS711X clocksource driver
+ *
+ * Copyright (C) 2014 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/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+
+enum {
+ CLPS711X_CLKSRC_CLOCKSOURCE,
+ CLPS711X_CLKSRC_CLOCKEVENT,
+};
+
+static void __iomem *tcd;
+
+static u64 notrace clps711x_sched_clock_read(void)
+{
+ return ~readw(tcd);
+}
+
+static int __init _clps711x_clksrc_init(struct clk *clock, void __iomem *base)
+{
+ unsigned long rate;
+
+ if (!base)
+ return -ENOMEM;
+ if (IS_ERR(clock))
+ return PTR_ERR(clock);
+
+ rate = clk_get_rate(clock);
+
+ tcd = base;
+
+ clocksource_mmio_init(tcd, "clps711x-clocksource", rate, 300, 16,
+ clocksource_mmio_readw_down);
+
+ sched_clock_register(clps711x_sched_clock_read, 16, rate);
+
+ return 0;
+}
+
+static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = dev_id;
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static void clps711x_clockevent_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+}
+
+static int __init _clps711x_clkevt_init(struct clk *clock, void __iomem *base,
+ unsigned int irq)
+{
+ struct clock_event_device *clkevt;
+ unsigned long rate;
+
+ if (!irq)
+ return -EINVAL;
+ if (!base)
+ return -ENOMEM;
+ if (IS_ERR(clock))
+ return PTR_ERR(clock);
+
+ clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
+ if (!clkevt)
+ return -ENOMEM;
+
+ rate = clk_get_rate(clock);
+
+ /* Set Timer prescaler */
+ writew(DIV_ROUND_CLOSEST(rate, HZ), base);
+
+ clkevt->name = "clps711x-clockevent";
+ clkevt->rating = 300;
+ clkevt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_C3STOP;
+ clkevt->set_mode = clps711x_clockevent_set_mode;
+ clkevt->cpumask = cpumask_of(0);
+ clockevents_config_and_register(clkevt, HZ, 0, 0);
+
+ return request_irq(irq, clps711x_timer_interrupt, IRQF_TIMER,
+ "clps711x-timer", clkevt);
+}
+
+void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base,
+ unsigned int irq)
+{
+ struct clk *tc1 = clk_get_sys("clps711x-timer.0", NULL);
+ struct clk *tc2 = clk_get_sys("clps711x-timer.1", NULL);
+
+ BUG_ON(_clps711x_clksrc_init(tc1, tc1_base));
+ BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq));
+}
+
+#ifdef CONFIG_CLKSRC_OF
+static void __init clps711x_timer_init(struct device_node *np)
+{
+ unsigned int irq = irq_of_parse_and_map(np, 0);
+ struct clk *clock = of_clk_get(np, 0);
+ void __iomem *base = of_iomap(np, 0);
+
+ switch (of_alias_get_id(np, "timer")) {
+ case CLPS711X_CLKSRC_CLOCKSOURCE:
+ BUG_ON(_clps711x_clksrc_init(clock, base));
+ break;
+ case CLPS711X_CLKSRC_CLOCKEVENT:
+ BUG_ON(_clps711x_clkevt_init(clock, base, irq));
+ break;
+ default:
+ break;
+ }
+}
+CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init);
+#endif
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index ab51bf20a3ed..9403061a2acc 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -94,7 +94,7 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset)
u32 mask;
u32 i;
- __raw_writel(value, reg_base + offset);
+ writel_relaxed(value, reg_base + offset);
if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
@@ -144,8 +144,8 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset)
/* Wait maximum 1 ms until written values are applied */
for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
- if (__raw_readl(reg_base + stat_addr) & mask) {
- __raw_writel(mask, reg_base + stat_addr);
+ if (readl_relaxed(reg_base + stat_addr) & mask) {
+ writel_relaxed(mask, reg_base + stat_addr);
return;
}
@@ -157,28 +157,51 @@ static void exynos4_mct_frc_start(void)
{
u32 reg;
- reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+ reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
reg |= MCT_G_TCON_START;
exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
}
-static cycle_t notrace _exynos4_frc_read(void)
+/**
+ * exynos4_read_count_64 - Read all 64-bits of the global counter
+ *
+ * This will read all 64-bits of the global counter taking care to make sure
+ * that the upper and lower half match. Note that reading the MCT can be quite
+ * slow (hundreds of nanoseconds) so you should use the 32-bit (lower half
+ * only) version when possible.
+ *
+ * Returns the number of cycles in the global counter.
+ */
+static u64 exynos4_read_count_64(void)
{
unsigned int lo, hi;
- u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+ u32 hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
do {
hi = hi2;
- lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
- hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
+ lo = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
+ hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
} while (hi != hi2);
return ((cycle_t)hi << 32) | lo;
}
+/**
+ * exynos4_read_count_32 - Read the lower 32-bits of the global counter
+ *
+ * This will read just the lower 32-bits of the global counter. This is marked
+ * as notrace so it can be used by the scheduler clock.
+ *
+ * Returns the number of cycles in the global counter (lower 32 bits).
+ */
+static u32 notrace exynos4_read_count_32(void)
+{
+ return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
+}
+
static cycle_t exynos4_frc_read(struct clocksource *cs)
{
- return _exynos4_frc_read();
+ return exynos4_read_count_32();
}
static void exynos4_frc_resume(struct clocksource *cs)
@@ -190,21 +213,23 @@ struct clocksource mct_frc = {
.name = "mct-frc",
.rating = 400,
.read = exynos4_frc_read,
- .mask = CLOCKSOURCE_MASK(64),
+ .mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.resume = exynos4_frc_resume,
};
static u64 notrace exynos4_read_sched_clock(void)
{
- return _exynos4_frc_read();
+ return exynos4_read_count_32();
}
static struct delay_timer exynos4_delay_timer;
static cycles_t exynos4_read_current_timer(void)
{
- return _exynos4_frc_read();
+ BUILD_BUG_ON_MSG(sizeof(cycles_t) != sizeof(u32),
+ "cycles_t needs to move to 32-bit for ARM64 usage");
+ return exynos4_read_count_32();
}
static void __init exynos4_clocksource_init(void)
@@ -218,14 +243,14 @@ static void __init exynos4_clocksource_init(void)
if (clocksource_register_hz(&mct_frc, clk_rate))
panic("%s: can't register clocksource\n", mct_frc.name);
- sched_clock_register(exynos4_read_sched_clock, 64, clk_rate);
+ sched_clock_register(exynos4_read_sched_clock, 32, clk_rate);
}
static void exynos4_mct_comp0_stop(void)
{
unsigned int tcon;
- tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+ tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -238,14 +263,14 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
unsigned int tcon;
cycle_t comp_cycle;
- tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
+ tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
if (mode == CLOCK_EVT_MODE_PERIODIC) {
tcon |= MCT_G_TCON_COMP0_AUTO_INC;
exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
}
- comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+ comp_cycle = exynos4_read_count_64() + cycles;
exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
@@ -327,7 +352,7 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
- tmp = __raw_readl(reg_base + offset);
+ tmp = readl_relaxed(reg_base + offset);
if (tmp & mask) {
tmp &= ~mask;
exynos4_mct_write(tmp, offset);
@@ -349,7 +374,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
/* enable MCT tick interrupt */
exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
- tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
+ tmp = readl_relaxed(reg_base + mevt->base + MCT_L_TCON_OFFSET);
tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
MCT_L_TCON_INTERVAL_MODE;
exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -401,7 +426,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
exynos4_mct_tick_stop(mevt);
/* Clear the MCT tick interrupt */
- if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+ if (readl_relaxed(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
return 1;
} else {
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
new file mode 100644
index 000000000000..32a3d25795d3
--- /dev/null
+++ b/drivers/clocksource/mtk_timer.c
@@ -0,0 +1,261 @@
+/*
+ * Mediatek SoCs General-Purpose Timer handling.
+ *
+ * Copyright (C) 2014 Matthias Brugger
+ *
+ * Matthias Brugger <matthias.bgg@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#define GPT_IRQ_EN_REG 0x00
+#define GPT_IRQ_ENABLE(val) BIT((val) - 1)
+#define GPT_IRQ_ACK_REG 0x08
+#define GPT_IRQ_ACK(val) BIT((val) - 1)
+
+#define TIMER_CTRL_REG(val) (0x10 * (val))
+#define TIMER_CTRL_OP(val) (((val) & 0x3) << 4)
+#define TIMER_CTRL_OP_ONESHOT (0)
+#define TIMER_CTRL_OP_REPEAT (1)
+#define TIMER_CTRL_OP_FREERUN (3)
+#define TIMER_CTRL_CLEAR (2)
+#define TIMER_CTRL_ENABLE (1)
+#define TIMER_CTRL_DISABLE (0)
+
+#define TIMER_CLK_REG(val) (0x04 + (0x10 * (val)))
+#define TIMER_CLK_SRC(val) (((val) & 0x1) << 4)
+#define TIMER_CLK_SRC_SYS13M (0)
+#define TIMER_CLK_SRC_RTC32K (1)
+#define TIMER_CLK_DIV1 (0x0)
+#define TIMER_CLK_DIV2 (0x1)
+
+#define TIMER_CNT_REG(val) (0x08 + (0x10 * (val)))
+#define TIMER_CMP_REG(val) (0x0C + (0x10 * (val)))
+
+#define GPT_CLK_EVT 1
+#define GPT_CLK_SRC 2
+
+struct mtk_clock_event_device {
+ void __iomem *gpt_base;
+ u32 ticks_per_jiffy;
+ struct clock_event_device dev;
+};
+
+static inline struct mtk_clock_event_device *to_mtk_clk(
+ struct clock_event_device *c)
+{
+ return container_of(c, struct mtk_clock_event_device, dev);
+}
+
+static void mtk_clkevt_time_stop(struct mtk_clock_event_device *evt, u8 timer)
+{
+ u32 val;
+
+ val = readl(evt->gpt_base + TIMER_CTRL_REG(timer));
+ writel(val & ~TIMER_CTRL_ENABLE, evt->gpt_base +
+ TIMER_CTRL_REG(timer));
+}
+
+static void mtk_clkevt_time_setup(struct mtk_clock_event_device *evt,
+ unsigned long delay, u8 timer)
+{
+ writel(delay, evt->gpt_base + TIMER_CMP_REG(timer));
+}
+
+static void mtk_clkevt_time_start(struct mtk_clock_event_device *evt,
+ bool periodic, u8 timer)
+{
+ u32 val;
+
+ /* Acknowledge interrupt */
+ writel(GPT_IRQ_ACK(timer), evt->gpt_base + GPT_IRQ_ACK_REG);
+
+ val = readl(evt->gpt_base + TIMER_CTRL_REG(timer));
+
+ /* Clear 2 bit timer operation mode field */
+ val &= ~TIMER_CTRL_OP(0x3);
+
+ if (periodic)
+ val |= TIMER_CTRL_OP(TIMER_CTRL_OP_REPEAT);
+ else
+ val |= TIMER_CTRL_OP(TIMER_CTRL_OP_ONESHOT);
+
+ writel(val | TIMER_CTRL_ENABLE | TIMER_CTRL_CLEAR,
+ evt->gpt_base + TIMER_CTRL_REG(timer));
+}
+
+static void mtk_clkevt_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ struct mtk_clock_event_device *evt = to_mtk_clk(clk);
+
+ mtk_clkevt_time_stop(evt, GPT_CLK_EVT);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ mtk_clkevt_time_setup(evt, evt->ticks_per_jiffy, GPT_CLK_EVT);
+ mtk_clkevt_time_start(evt, true, GPT_CLK_EVT);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Timer is enabled in set_next_event */
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ /* No more interrupts will occur as source is disabled */
+ break;
+ }
+}
+
+static int mtk_clkevt_next_event(unsigned long event,
+ struct clock_event_device *clk)
+{
+ struct mtk_clock_event_device *evt = to_mtk_clk(clk);
+
+ mtk_clkevt_time_stop(evt, GPT_CLK_EVT);
+ mtk_clkevt_time_setup(evt, event, GPT_CLK_EVT);
+ mtk_clkevt_time_start(evt, false, GPT_CLK_EVT);
+
+ return 0;
+}
+
+static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
+{
+ struct mtk_clock_event_device *evt = dev_id;
+
+ /* Acknowledge timer0 irq */
+ writel(GPT_IRQ_ACK(GPT_CLK_EVT), evt->gpt_base + GPT_IRQ_ACK_REG);
+ evt->dev.event_handler(&evt->dev);
+
+ return IRQ_HANDLED;
+}
+
+static void mtk_timer_global_reset(struct mtk_clock_event_device *evt)
+{
+ /* Disable all interrupts */
+ writel(0x0, evt->gpt_base + GPT_IRQ_EN_REG);
+ /* Acknowledge all interrupts */
+ writel(0x3f, evt->gpt_base + GPT_IRQ_ACK_REG);
+}
+
+static void
+mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
+{
+ writel(TIMER_CTRL_CLEAR | TIMER_CTRL_DISABLE,
+ evt->gpt_base + TIMER_CTRL_REG(timer));
+
+ writel(TIMER_CLK_SRC(TIMER_CLK_SRC_SYS13M) | TIMER_CLK_DIV1,
+ evt->gpt_base + TIMER_CLK_REG(timer));
+
+ writel(0x0, evt->gpt_base + TIMER_CMP_REG(timer));
+
+ writel(TIMER_CTRL_OP(option) | TIMER_CTRL_ENABLE,
+ evt->gpt_base + TIMER_CTRL_REG(timer));
+}
+
+static void mtk_timer_enable_irq(struct mtk_clock_event_device *evt, u8 timer)
+{
+ u32 val;
+
+ val = readl(evt->gpt_base + GPT_IRQ_EN_REG);
+ writel(val | GPT_IRQ_ENABLE(timer),
+ evt->gpt_base + GPT_IRQ_EN_REG);
+}
+
+static void __init mtk_timer_init(struct device_node *node)
+{
+ struct mtk_clock_event_device *evt;
+ struct resource res;
+ unsigned long rate = 0;
+ struct clk *clk;
+
+ evt = kzalloc(sizeof(*evt), GFP_KERNEL);
+ if (!evt) {
+ pr_warn("Can't allocate mtk clock event driver struct");
+ return;
+ }
+
+ evt->dev.name = "mtk_tick";
+ evt->dev.rating = 300;
+ evt->dev.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ evt->dev.set_mode = mtk_clkevt_mode;
+ evt->dev.set_next_event = mtk_clkevt_next_event;
+ evt->dev.cpumask = cpu_possible_mask;
+
+ evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer");
+ if (IS_ERR(evt->gpt_base)) {
+ pr_warn("Can't get resource\n");
+ return;
+ }
+
+ evt->dev.irq = irq_of_parse_and_map(node, 0);
+ if (evt->dev.irq <= 0) {
+ pr_warn("Can't parse IRQ");
+ goto err_mem;
+ }
+
+ clk = of_clk_get(node, 0);
+ if (IS_ERR(clk)) {
+ pr_warn("Can't get timer clock");
+ goto err_irq;
+ }
+
+ if (clk_prepare_enable(clk)) {
+ pr_warn("Can't prepare clock");
+ goto err_clk_put;
+ }
+ rate = clk_get_rate(clk);
+
+ if (request_irq(evt->dev.irq, mtk_timer_interrupt,
+ IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
+ pr_warn("failed to setup irq %d\n", evt->dev.irq);
+ goto err_clk_disable;
+ }
+
+ evt->ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
+
+ mtk_timer_global_reset(evt);
+
+ /* Configure clock source */
+ mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
+ clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
+ node->name, rate, 300, 32, clocksource_mmio_readl_up);
+
+ /* Configure clock event */
+ mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
+ mtk_timer_enable_irq(evt, GPT_CLK_EVT);
+
+ clockevents_config_and_register(&evt->dev, rate, 0x3,
+ 0xffffffff);
+ return;
+
+err_clk_disable:
+ clk_disable_unprepare(clk);
+err_clk_put:
+ clk_put(clk);
+err_irq:
+ irq_dispose_mapping(evt->dev.irq);
+err_mem:
+ iounmap(evt->gpt_base);
+ of_address_to_resource(node, 0, &res);
+ release_mem_region(res.start, resource_size(&res));
+}
+CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c
new file mode 100644
index 000000000000..941f3f344e08
--- /dev/null
+++ b/drivers/clocksource/pxa_timer.c
@@ -0,0 +1,227 @@
+/*
+ * arch/arm/mach-pxa/time.c
+ *
+ * PXA clocksource, clockevents, and OST interrupt handlers.
+ * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
+ *
+ * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
+ * by MontaVista Software, Inc. (Nico, your code rocks!)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <asm/div64.h>
+
+#define OSMR0 0x00 /* OS Timer 0 Match Register */
+#define OSMR1 0x04 /* OS Timer 1 Match Register */
+#define OSMR2 0x08 /* OS Timer 2 Match Register */
+#define OSMR3 0x0C /* OS Timer 3 Match Register */
+
+#define OSCR 0x10 /* OS Timer Counter Register */
+#define OSSR 0x14 /* OS Timer Status Register */
+#define OWER 0x18 /* OS Timer Watchdog Enable Register */
+#define OIER 0x1C /* OS Timer Interrupt Enable Register */
+
+#define OSSR_M3 (1 << 3) /* Match status channel 3 */
+#define OSSR_M2 (1 << 2) /* Match status channel 2 */
+#define OSSR_M1 (1 << 1) /* Match status channel 1 */
+#define OSSR_M0 (1 << 0) /* Match status channel 0 */
+
+#define OIER_E0 (1 << 0) /* Interrupt enable channel 0 */
+
+/*
+ * This is PXA's sched_clock implementation. This has a resolution
+ * of at least 308 ns and a maximum value of 208 days.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to sched_clock() which should always be the case in practice.
+ */
+
+#define timer_readl(reg) readl_relaxed(timer_base + (reg))
+#define timer_writel(val, reg) writel_relaxed((val), timer_base + (reg))
+
+static void __iomem *timer_base;
+
+static u64 notrace pxa_read_sched_clock(void)
+{
+ return timer_readl(OSCR);
+}
+
+
+#define MIN_OSCR_DELTA 16
+
+static irqreturn_t
+pxa_ost0_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *c = dev_id;
+
+ /* Disarm the compare/match, signal the event. */
+ timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+ timer_writel(OSSR_M0, OSSR);
+ c->event_handler(c);
+
+ return IRQ_HANDLED;
+}
+
+static int
+pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+ unsigned long next, oscr;
+
+ timer_writel(timer_readl(OIER) | OIER_E0, OIER);
+ next = timer_readl(OSCR) + delta;
+ timer_writel(next, OSMR0);
+ oscr = timer_readl(OSCR);
+
+ return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
+}
+
+static void
+pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT:
+ timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+ timer_writel(OSSR_M0, OSSR);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* initializing, released, or preparing for suspend */
+ timer_writel(timer_readl(OIER) & ~OIER_E0, OIER);
+ timer_writel(OSSR_M0, OSSR);
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ case CLOCK_EVT_MODE_PERIODIC:
+ break;
+ }
+}
+
+#ifdef CONFIG_PM
+static unsigned long osmr[4], oier, oscr;
+
+static void pxa_timer_suspend(struct clock_event_device *cedev)
+{
+ osmr[0] = timer_readl(OSMR0);
+ osmr[1] = timer_readl(OSMR1);
+ osmr[2] = timer_readl(OSMR2);
+ osmr[3] = timer_readl(OSMR3);
+ oier = timer_readl(OIER);
+ oscr = timer_readl(OSCR);
+}
+
+static void pxa_timer_resume(struct clock_event_device *cedev)
+{
+ /*
+ * Ensure that we have at least MIN_OSCR_DELTA between match
+ * register 0 and the OSCR, to guarantee that we will receive
+ * the one-shot timer interrupt. We adjust OSMR0 in preference
+ * to OSCR to guarantee that OSCR is monotonically incrementing.
+ */
+ if (osmr[0] - oscr < MIN_OSCR_DELTA)
+ osmr[0] += MIN_OSCR_DELTA;
+
+ timer_writel(osmr[0], OSMR0);
+ timer_writel(osmr[1], OSMR1);
+ timer_writel(osmr[2], OSMR2);
+ timer_writel(osmr[3], OSMR3);
+ timer_writel(oier, OIER);
+ timer_writel(oscr, OSCR);
+}
+#else
+#define pxa_timer_suspend NULL
+#define pxa_timer_resume NULL
+#endif
+
+static struct clock_event_device ckevt_pxa_osmr0 = {
+ .name = "osmr0",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .set_next_event = pxa_osmr0_set_next_event,
+ .set_mode = pxa_osmr0_set_mode,
+ .suspend = pxa_timer_suspend,
+ .resume = pxa_timer_resume,
+};
+
+static struct irqaction pxa_ost0_irq = {
+ .name = "ost0",
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = pxa_ost0_interrupt,
+ .dev_id = &ckevt_pxa_osmr0,
+};
+
+static void pxa_timer_common_init(int irq, unsigned long clock_tick_rate)
+{
+ timer_writel(0, OIER);
+ timer_writel(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+ sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
+
+ ckevt_pxa_osmr0.cpumask = cpumask_of(0);
+
+ setup_irq(irq, &pxa_ost0_irq);
+
+ clocksource_mmio_init(timer_base + OSCR, "oscr0", clock_tick_rate, 200,
+ 32, clocksource_mmio_readl_up);
+ clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
+ MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
+
+static void __init pxa_timer_dt_init(struct device_node *np)
+{
+ struct clk *clk;
+ int irq;
+
+ /* timer registers are shared with watchdog timer */
+ timer_base = of_iomap(np, 0);
+ if (!timer_base)
+ panic("%s: unable to map resource\n", np->name);
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ pr_crit("%s: unable to get clk\n", np->name);
+ return;
+ }
+ clk_prepare_enable(clk);
+
+ /* we are only interested in OS-timer0 irq */
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq <= 0) {
+ pr_crit("%s: unable to parse OS-timer0 irq\n", np->name);
+ return;
+ }
+
+ pxa_timer_common_init(irq, clk_get_rate(clk));
+}
+CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
+
+/*
+ * Legacy timer init for non device-tree boards.
+ */
+void __init pxa_timer_nodt_init(int irq, void __iomem *base,
+ unsigned long clock_tick_rate)
+{
+ struct clk *clk;
+
+ timer_base = base;
+ clk = clk_get(NULL, "OSTIMER0");
+ if (clk && !IS_ERR(clk))
+ clk_prepare_enable(clk);
+ else
+ pr_crit("%s: unable to get clk\n", __func__);
+
+ pxa_timer_common_init(irq, clock_tick_rate);
+}
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index dfa780396b91..2bd13b53b727 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
@@ -114,14 +115,15 @@ struct sh_cmt_device {
struct platform_device *pdev;
const struct sh_cmt_info *info;
- bool legacy;
- void __iomem *mapbase_ch;
void __iomem *mapbase;
struct clk *clk;
+ raw_spinlock_t lock; /* Protect the shared start/stop register */
+
struct sh_cmt_channel *channels;
unsigned int num_channels;
+ unsigned int hw_channels;
bool has_clockevent;
bool has_clocksource;
@@ -301,14 +303,12 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
return v2;
}
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
-
static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
{
unsigned long flags, value;
/* start stop register shared by multiple timer channels */
- raw_spin_lock_irqsave(&sh_cmt_lock, flags);
+ raw_spin_lock_irqsave(&ch->cmt->lock, flags);
value = sh_cmt_read_cmstr(ch);
if (start)
@@ -317,7 +317,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
value &= ~(1 << ch->timer_bit);
sh_cmt_write_cmstr(ch, value);
- raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
+ raw_spin_unlock_irqrestore(&ch->cmt->lock, flags);
}
static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
@@ -792,7 +792,7 @@ static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
int irq;
int ret;
- irq = platform_get_irq(ch->cmt->pdev, ch->cmt->legacy ? 0 : ch->index);
+ irq = platform_get_irq(ch->cmt->pdev, ch->index);
if (irq < 0) {
dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n",
ch->index);
@@ -863,33 +863,26 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
* Compute the address of the channel control register block. For the
* timers with a per-channel start/stop register, compute its address
* as well.
- *
- * For legacy configuration the address has been mapped explicitly.
*/
- if (cmt->legacy) {
- ch->ioctrl = cmt->mapbase_ch;
- } else {
- switch (cmt->info->model) {
- case SH_CMT_16BIT:
- ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
- break;
- case SH_CMT_32BIT:
- case SH_CMT_48BIT:
- ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
- break;
- case SH_CMT_32BIT_FAST:
- /*
- * The 32-bit "fast" timer has a single channel at hwidx
- * 5 but is located at offset 0x40 instead of 0x60 for
- * some reason.
- */
- ch->ioctrl = cmt->mapbase + 0x40;
- break;
- case SH_CMT_48BIT_GEN2:
- ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
- ch->ioctrl = ch->iostart + 0x10;
- break;
- }
+ switch (cmt->info->model) {
+ case SH_CMT_16BIT:
+ ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
+ break;
+ case SH_CMT_32BIT:
+ case SH_CMT_48BIT:
+ ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
+ break;
+ case SH_CMT_32BIT_FAST:
+ /*
+ * The 32-bit "fast" timer has a single channel at hwidx 5 but
+ * is located at offset 0x40 instead of 0x60 for some reason.
+ */
+ ch->ioctrl = cmt->mapbase + 0x40;
+ break;
+ case SH_CMT_48BIT_GEN2:
+ ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
+ ch->ioctrl = ch->iostart + 0x10;
+ break;
}
if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
@@ -900,12 +893,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
ch->match_value = ch->max_match_value;
raw_spin_lock_init(&ch->lock);
- if (cmt->legacy) {
- ch->timer_bit = ch->hwidx;
- } else {
- ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2
- ? 0 : ch->hwidx;
- }
+ ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx;
ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
clockevent, clocksource);
@@ -938,75 +926,65 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
return 0;
}
-static int sh_cmt_map_memory_legacy(struct sh_cmt_device *cmt)
-{
- struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
- struct resource *res, *res2;
-
- /* map memory, let mapbase_ch point to our channel */
- res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
- return -ENXIO;
- }
-
- cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res));
- if (cmt->mapbase_ch == NULL) {
- dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
- return -ENXIO;
- }
-
- /* optional resource for the shared timer start/stop register */
- res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
-
- /* map second resource for CMSTR */
- cmt->mapbase = ioremap_nocache(res2 ? res2->start :
- res->start - cfg->channel_offset,
- res2 ? resource_size(res2) : 2);
- if (cmt->mapbase == NULL) {
- dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
- iounmap(cmt->mapbase_ch);
- return -ENXIO;
- }
-
- /* identify the model based on the resources */
- if (resource_size(res) == 6)
- cmt->info = &sh_cmt_info[SH_CMT_16BIT];
- else if (res2 && (resource_size(res2) == 4))
- cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
- else
- cmt->info = &sh_cmt_info[SH_CMT_32BIT];
+static const struct platform_device_id sh_cmt_id_table[] = {
+ { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
+ { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
+ { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
+ { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
+ { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
- return 0;
-}
+static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
+ { .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] },
+ { .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] },
+ { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+ { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
-static void sh_cmt_unmap_memory(struct sh_cmt_device *cmt)
+static int sh_cmt_parse_dt(struct sh_cmt_device *cmt)
{
- iounmap(cmt->mapbase);
- if (cmt->mapbase_ch)
- iounmap(cmt->mapbase_ch);
+ struct device_node *np = cmt->pdev->dev.of_node;
+
+ return of_property_read_u32(np, "renesas,channels-mask",
+ &cmt->hw_channels);
}
static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
{
- struct sh_timer_config *cfg = pdev->dev.platform_data;
- const struct platform_device_id *id = pdev->id_entry;
- unsigned int hw_channels;
+ unsigned int mask;
+ unsigned int i;
int ret;
memset(cmt, 0, sizeof(*cmt));
cmt->pdev = pdev;
+ raw_spin_lock_init(&cmt->lock);
+
+ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+ const struct of_device_id *id;
+
+ id = of_match_node(sh_cmt_of_table, pdev->dev.of_node);
+ cmt->info = id->data;
- if (!cfg) {
+ ret = sh_cmt_parse_dt(cmt);
+ if (ret < 0)
+ return ret;
+ } else if (pdev->dev.platform_data) {
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+ const struct platform_device_id *id = pdev->id_entry;
+
+ cmt->info = (const struct sh_cmt_info *)id->driver_data;
+ cmt->hw_channels = cfg->channels_mask;
+ } else {
dev_err(&cmt->pdev->dev, "missing platform data\n");
return -ENXIO;
}
- cmt->info = (const struct sh_cmt_info *)id->driver_data;
- cmt->legacy = cmt->info ? false : true;
-
/* Get hold of clock. */
- cmt->clk = clk_get(&cmt->pdev->dev, cmt->legacy ? "cmt_fck" : "fck");
+ cmt->clk = clk_get(&cmt->pdev->dev, "fck");
if (IS_ERR(cmt->clk)) {
dev_err(&cmt->pdev->dev, "cannot get clock\n");
return PTR_ERR(cmt->clk);
@@ -1016,28 +994,13 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
if (ret < 0)
goto err_clk_put;
- /*
- * Map the memory resource(s). We need to support both the legacy
- * platform device configuration (with one device per channel) and the
- * new version (with multiple channels per device).
- */
- if (cmt->legacy)
- ret = sh_cmt_map_memory_legacy(cmt);
- else
- ret = sh_cmt_map_memory(cmt);
-
+ /* Map the memory resource(s). */
+ ret = sh_cmt_map_memory(cmt);
if (ret < 0)
goto err_clk_unprepare;
/* Allocate and setup the channels. */
- if (cmt->legacy) {
- cmt->num_channels = 1;
- hw_channels = 0;
- } else {
- cmt->num_channels = hweight8(cfg->channels_mask);
- hw_channels = cfg->channels_mask;
- }
-
+ cmt->num_channels = hweight8(cmt->hw_channels);
cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
GFP_KERNEL);
if (cmt->channels == NULL) {
@@ -1045,35 +1008,21 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
goto err_unmap;
}
- if (cmt->legacy) {
- ret = sh_cmt_setup_channel(&cmt->channels[0],
- cfg->timer_bit, cfg->timer_bit,
- cfg->clockevent_rating != 0,
- cfg->clocksource_rating != 0, cmt);
+ /*
+ * Use the first channel as a clock event device and the second channel
+ * as a clock source. If only one channel is available use it for both.
+ */
+ for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
+ unsigned int hwidx = ffs(mask) - 1;
+ bool clocksource = i == 1 || cmt->num_channels == 1;
+ bool clockevent = i == 0;
+
+ ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
+ clockevent, clocksource, cmt);
if (ret < 0)
goto err_unmap;
- } else {
- unsigned int mask = hw_channels;
- unsigned int i;
- /*
- * Use the first channel as a clock event device and the second
- * channel as a clock source. If only one channel is available
- * use it for both.
- */
- for (i = 0; i < cmt->num_channels; ++i) {
- unsigned int hwidx = ffs(mask) - 1;
- bool clocksource = i == 1 || cmt->num_channels == 1;
- bool clockevent = i == 0;
-
- ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
- clockevent, clocksource,
- cmt);
- if (ret < 0)
- goto err_unmap;
-
- mask &= ~(1 << hwidx);
- }
+ mask &= ~(1 << hwidx);
}
platform_set_drvdata(pdev, cmt);
@@ -1082,7 +1031,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
err_unmap:
kfree(cmt->channels);
- sh_cmt_unmap_memory(cmt);
+ iounmap(cmt->mapbase);
err_clk_unprepare:
clk_unprepare(cmt->clk);
err_clk_put:
@@ -1132,22 +1081,12 @@ static int sh_cmt_remove(struct platform_device *pdev)
return -EBUSY; /* cannot unregister clockevent and clocksource */
}
-static const struct platform_device_id sh_cmt_id_table[] = {
- { "sh_cmt", 0 },
- { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
- { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
- { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
- { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
- { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
- { }
-};
-MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
-
static struct platform_driver sh_cmt_device_driver = {
.probe = sh_cmt_probe,
.remove = sh_cmt_remove,
.driver = {
.name = "sh_cmt",
+ .of_match_table = of_match_ptr(sh_cmt_of_table),
},
.id_table = sh_cmt_id_table,
};
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 188d4e092efc..3d88698cf2b8 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -23,6 +23,7 @@
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
@@ -37,7 +38,6 @@ struct sh_mtu2_channel {
unsigned int index;
void __iomem *base;
- int irq;
struct clock_event_device ced;
};
@@ -48,15 +48,14 @@ struct sh_mtu2_device {
void __iomem *mapbase;
struct clk *clk;
+ raw_spinlock_t lock; /* Protect the shared registers */
+
struct sh_mtu2_channel *channels;
unsigned int num_channels;
- bool legacy;
bool has_clockevent;
};
-static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
-
#define TSTR -1 /* shared register */
#define TCR 0 /* channel register */
#define TMDR 1 /* channel register */
@@ -162,12 +161,8 @@ static inline unsigned long sh_mtu2_read(struct sh_mtu2_channel *ch, int reg_nr)
{
unsigned long offs;
- if (reg_nr == TSTR) {
- if (ch->mtu->legacy)
- return ioread8(ch->mtu->mapbase);
- else
- return ioread8(ch->mtu->mapbase + 0x280);
- }
+ if (reg_nr == TSTR)
+ return ioread8(ch->mtu->mapbase + 0x280);
offs = mtu2_reg_offs[reg_nr];
@@ -182,12 +177,8 @@ static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr,
{
unsigned long offs;
- if (reg_nr == TSTR) {
- if (ch->mtu->legacy)
- return iowrite8(value, ch->mtu->mapbase);
- else
- return iowrite8(value, ch->mtu->mapbase + 0x280);
- }
+ if (reg_nr == TSTR)
+ return iowrite8(value, ch->mtu->mapbase + 0x280);
offs = mtu2_reg_offs[reg_nr];
@@ -202,7 +193,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
unsigned long flags, value;
/* start stop register shared by multiple timer channels */
- raw_spin_lock_irqsave(&sh_mtu2_lock, flags);
+ raw_spin_lock_irqsave(&ch->mtu->lock, flags);
value = sh_mtu2_read(ch, TSTR);
if (start)
@@ -211,7 +202,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
value &= ~(1 << ch->index);
sh_mtu2_write(ch, TSTR, value);
- raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags);
+ raw_spin_unlock_irqrestore(&ch->mtu->lock, flags);
}
static int sh_mtu2_enable(struct sh_mtu2_channel *ch)
@@ -331,7 +322,6 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
const char *name)
{
struct clock_event_device *ced = &ch->ced;
- int ret;
ced->name = name;
ced->features = CLOCK_EVT_FEAT_PERIODIC;
@@ -344,24 +334,12 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
dev_info(&ch->mtu->pdev->dev, "ch%u: used for clock events\n",
ch->index);
clockevents_register_device(ced);
-
- ret = request_irq(ch->irq, sh_mtu2_interrupt,
- IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
- dev_name(&ch->mtu->pdev->dev), ch);
- if (ret) {
- dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n",
- ch->index, ch->irq);
- return;
- }
}
-static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name,
- bool clockevent)
+static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name)
{
- if (clockevent) {
- ch->mtu->has_clockevent = true;
- sh_mtu2_register_clockevent(ch, name);
- }
+ ch->mtu->has_clockevent = true;
+ sh_mtu2_register_clockevent(ch, name);
return 0;
}
@@ -372,40 +350,32 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch, unsigned int index,
static const unsigned int channel_offsets[] = {
0x300, 0x380, 0x000,
};
- bool clockevent;
+ char name[6];
+ int irq;
+ int ret;
ch->mtu = mtu;
- if (mtu->legacy) {
- struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
-
- clockevent = cfg->clockevent_rating != 0;
-
- ch->irq = platform_get_irq(mtu->pdev, 0);
- ch->base = mtu->mapbase - cfg->channel_offset;
- ch->index = cfg->timer_bit;
- } else {
- char name[6];
-
- clockevent = true;
-
- sprintf(name, "tgi%ua", index);
- ch->irq = platform_get_irq_byname(mtu->pdev, name);
- ch->base = mtu->mapbase + channel_offsets[index];
- ch->index = index;
- }
-
- if (ch->irq < 0) {
+ sprintf(name, "tgi%ua", index);
+ irq = platform_get_irq_byname(mtu->pdev, name);
+ if (irq < 0) {
/* Skip channels with no declared interrupt. */
- if (!mtu->legacy)
- return 0;
+ return 0;
+ }
- dev_err(&mtu->pdev->dev, "ch%u: failed to get irq\n",
- ch->index);
- return ch->irq;
+ ret = request_irq(irq, sh_mtu2_interrupt,
+ IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+ dev_name(&ch->mtu->pdev->dev), ch);
+ if (ret) {
+ dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n",
+ index, irq);
+ return ret;
}
- return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev), clockevent);
+ ch->base = mtu->mapbase + channel_offsets[index];
+ ch->index = index;
+
+ return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev));
}
static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu)
@@ -422,46 +392,21 @@ static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu)
if (mtu->mapbase == NULL)
return -ENXIO;
- /*
- * In legacy platform device configuration (with one device per channel)
- * the resource points to the channel base address.
- */
- if (mtu->legacy) {
- struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
- mtu->mapbase += cfg->channel_offset;
- }
-
return 0;
}
-static void sh_mtu2_unmap_memory(struct sh_mtu2_device *mtu)
-{
- if (mtu->legacy) {
- struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
- mtu->mapbase -= cfg->channel_offset;
- }
-
- iounmap(mtu->mapbase);
-}
-
static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
struct platform_device *pdev)
{
- struct sh_timer_config *cfg = pdev->dev.platform_data;
- const struct platform_device_id *id = pdev->id_entry;
unsigned int i;
int ret;
mtu->pdev = pdev;
- mtu->legacy = id->driver_data;
- if (mtu->legacy && !cfg) {
- dev_err(&mtu->pdev->dev, "missing platform data\n");
- return -ENXIO;
- }
+ raw_spin_lock_init(&mtu->lock);
/* Get hold of clock. */
- mtu->clk = clk_get(&mtu->pdev->dev, mtu->legacy ? "mtu2_fck" : "fck");
+ mtu->clk = clk_get(&mtu->pdev->dev, "fck");
if (IS_ERR(mtu->clk)) {
dev_err(&mtu->pdev->dev, "cannot get clock\n");
return PTR_ERR(mtu->clk);
@@ -479,10 +424,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
}
/* Allocate and setup the channels. */
- if (mtu->legacy)
- mtu->num_channels = 1;
- else
- mtu->num_channels = 3;
+ mtu->num_channels = 3;
mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels,
GFP_KERNEL);
@@ -491,16 +433,10 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
goto err_unmap;
}
- if (mtu->legacy) {
- ret = sh_mtu2_setup_channel(&mtu->channels[0], 0, mtu);
+ for (i = 0; i < mtu->num_channels; ++i) {
+ ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu);
if (ret < 0)
goto err_unmap;
- } else {
- for (i = 0; i < mtu->num_channels; ++i) {
- ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu);
- if (ret < 0)
- goto err_unmap;
- }
}
platform_set_drvdata(pdev, mtu);
@@ -509,7 +445,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
err_unmap:
kfree(mtu->channels);
- sh_mtu2_unmap_memory(mtu);
+ iounmap(mtu->mapbase);
err_clk_unprepare:
clk_unprepare(mtu->clk);
err_clk_put:
@@ -560,17 +496,23 @@ static int sh_mtu2_remove(struct platform_device *pdev)
}
static const struct platform_device_id sh_mtu2_id_table[] = {
- { "sh_mtu2", 1 },
{ "sh-mtu2", 0 },
{ },
};
MODULE_DEVICE_TABLE(platform, sh_mtu2_id_table);
+static const struct of_device_id sh_mtu2_of_table[] __maybe_unused = {
+ { .compatible = "renesas,mtu2" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sh_mtu2_of_table);
+
static struct platform_driver sh_mtu2_device_driver = {
.probe = sh_mtu2_probe,
.remove = sh_mtu2_remove,
.driver = {
.name = "sh_mtu2",
+ .of_match_table = of_match_ptr(sh_mtu2_of_table),
},
.id_table = sh_mtu2_id_table,
};
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 6bd17a8f3dd4..0f665b8f2461 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
@@ -32,7 +33,6 @@
#include <linux/spinlock.h>
enum sh_tmu_model {
- SH_TMU_LEGACY,
SH_TMU,
SH_TMU_SH3,
};
@@ -62,6 +62,8 @@ struct sh_tmu_device {
enum sh_tmu_model model;
+ raw_spinlock_t lock; /* Protect the shared start/stop register */
+
struct sh_tmu_channel *channels;
unsigned int num_channels;
@@ -69,8 +71,6 @@ struct sh_tmu_device {
bool has_clocksource;
};
-static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
-
#define TSTR -1 /* shared register */
#define TCOR 0 /* channel register */
#define TCNT 1 /* channel register */
@@ -91,8 +91,6 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
if (reg_nr == TSTR) {
switch (ch->tmu->model) {
- case SH_TMU_LEGACY:
- return ioread8(ch->tmu->mapbase);
case SH_TMU_SH3:
return ioread8(ch->tmu->mapbase + 2);
case SH_TMU:
@@ -115,8 +113,6 @@ static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
if (reg_nr == TSTR) {
switch (ch->tmu->model) {
- case SH_TMU_LEGACY:
- return iowrite8(value, ch->tmu->mapbase);
case SH_TMU_SH3:
return iowrite8(value, ch->tmu->mapbase + 2);
case SH_TMU:
@@ -137,7 +133,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
unsigned long flags, value;
/* start stop register shared by multiple timer channels */
- raw_spin_lock_irqsave(&sh_tmu_lock, flags);
+ raw_spin_lock_irqsave(&ch->tmu->lock, flags);
value = sh_tmu_read(ch, TSTR);
if (start)
@@ -146,7 +142,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
value &= ~(1 << ch->index);
sh_tmu_write(ch, TSTR, value);
- raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
+ raw_spin_unlock_irqrestore(&ch->tmu->lock, flags);
}
static int __sh_tmu_enable(struct sh_tmu_channel *ch)
@@ -476,27 +472,12 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index,
return 0;
ch->tmu = tmu;
+ ch->index = index;
- if (tmu->model == SH_TMU_LEGACY) {
- struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
-
- /*
- * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps
- * channel registers blocks at base + 2 + 12 * index, while all
- * other variants map them at base + 4 + 12 * index. We can
- * compute the index by just dividing by 12, the 2 bytes or 4
- * bytes offset being hidden by the integer division.
- */
- ch->index = cfg->channel_offset / 12;
- ch->base = tmu->mapbase + cfg->channel_offset;
- } else {
- ch->index = index;
-
- if (tmu->model == SH_TMU_SH3)
- ch->base = tmu->mapbase + 4 + ch->index * 12;
- else
- ch->base = tmu->mapbase + 8 + ch->index * 12;
- }
+ if (tmu->model == SH_TMU_SH3)
+ ch->base = tmu->mapbase + 4 + ch->index * 12;
+ else
+ ch->base = tmu->mapbase + 8 + ch->index * 12;
ch->irq = platform_get_irq(tmu->pdev, index);
if (ch->irq < 0) {
@@ -526,46 +507,53 @@ static int sh_tmu_map_memory(struct sh_tmu_device *tmu)
if (tmu->mapbase == NULL)
return -ENXIO;
- /*
- * In legacy platform device configuration (with one device per channel)
- * the resource points to the channel base address.
- */
- if (tmu->model == SH_TMU_LEGACY) {
- struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
- tmu->mapbase -= cfg->channel_offset;
- }
-
return 0;
}
-static void sh_tmu_unmap_memory(struct sh_tmu_device *tmu)
+static int sh_tmu_parse_dt(struct sh_tmu_device *tmu)
{
- if (tmu->model == SH_TMU_LEGACY) {
- struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
- tmu->mapbase += cfg->channel_offset;
+ struct device_node *np = tmu->pdev->dev.of_node;
+
+ tmu->model = SH_TMU;
+ tmu->num_channels = 3;
+
+ of_property_read_u32(np, "#renesas,channels", &tmu->num_channels);
+
+ if (tmu->num_channels != 2 && tmu->num_channels != 3) {
+ dev_err(&tmu->pdev->dev, "invalid number of channels %u\n",
+ tmu->num_channels);
+ return -EINVAL;
}
- iounmap(tmu->mapbase);
+ return 0;
}
static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
{
- struct sh_timer_config *cfg = pdev->dev.platform_data;
- const struct platform_device_id *id = pdev->id_entry;
unsigned int i;
int ret;
- if (!cfg) {
+ tmu->pdev = pdev;
+
+ raw_spin_lock_init(&tmu->lock);
+
+ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+ ret = sh_tmu_parse_dt(tmu);
+ if (ret < 0)
+ return ret;
+ } else if (pdev->dev.platform_data) {
+ const struct platform_device_id *id = pdev->id_entry;
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
+
+ tmu->model = id->driver_data;
+ tmu->num_channels = hweight8(cfg->channels_mask);
+ } else {
dev_err(&tmu->pdev->dev, "missing platform data\n");
return -ENXIO;
}
- tmu->pdev = pdev;
- tmu->model = id->driver_data;
-
/* Get hold of clock. */
- tmu->clk = clk_get(&tmu->pdev->dev,
- tmu->model == SH_TMU_LEGACY ? "tmu_fck" : "fck");
+ tmu->clk = clk_get(&tmu->pdev->dev, "fck");
if (IS_ERR(tmu->clk)) {
dev_err(&tmu->pdev->dev, "cannot get clock\n");
return PTR_ERR(tmu->clk);
@@ -583,11 +571,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
}
/* Allocate and setup the channels. */
- if (tmu->model == SH_TMU_LEGACY)
- tmu->num_channels = 1;
- else
- tmu->num_channels = hweight8(cfg->channels_mask);
-
tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels,
GFP_KERNEL);
if (tmu->channels == NULL) {
@@ -595,23 +578,15 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
goto err_unmap;
}
- if (tmu->model == SH_TMU_LEGACY) {
- ret = sh_tmu_channel_setup(&tmu->channels[0], 0,
- cfg->clockevent_rating != 0,
- cfg->clocksource_rating != 0, tmu);
+ /*
+ * Use the first channel as a clock event device and the second channel
+ * as a clock source.
+ */
+ for (i = 0; i < tmu->num_channels; ++i) {
+ ret = sh_tmu_channel_setup(&tmu->channels[i], i,
+ i == 0, i == 1, tmu);
if (ret < 0)
goto err_unmap;
- } else {
- /*
- * Use the first channel as a clock event device and the second
- * channel as a clock source.
- */
- for (i = 0; i < tmu->num_channels; ++i) {
- ret = sh_tmu_channel_setup(&tmu->channels[i], i,
- i == 0, i == 1, tmu);
- if (ret < 0)
- goto err_unmap;
- }
}
platform_set_drvdata(pdev, tmu);
@@ -620,7 +595,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
err_unmap:
kfree(tmu->channels);
- sh_tmu_unmap_memory(tmu);
+ iounmap(tmu->mapbase);
err_clk_unprepare:
clk_unprepare(tmu->clk);
err_clk_put:
@@ -671,18 +646,24 @@ static int sh_tmu_remove(struct platform_device *pdev)
}
static const struct platform_device_id sh_tmu_id_table[] = {
- { "sh_tmu", SH_TMU_LEGACY },
{ "sh-tmu", SH_TMU },
{ "sh-tmu-sh3", SH_TMU_SH3 },
{ }
};
MODULE_DEVICE_TABLE(platform, sh_tmu_id_table);
+static const struct of_device_id sh_tmu_of_table[] __maybe_unused = {
+ { .compatible = "renesas,tmu" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sh_tmu_of_table);
+
static struct platform_driver sh_tmu_device_driver = {
.probe = sh_tmu_probe,
.remove = sh_tmu_remove,
.driver = {
.name = "sh_tmu",
+ .of_match_table = of_match_ptr(sh_tmu_of_table),
},
.id_table = sh_tmu_id_table,
};
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index d1869f02051c..d2616ef16770 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -27,6 +27,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
+#include <linux/delay.h>
#include <asm/mach/time.h>
#include <asm/smp_twd.h>
@@ -53,6 +54,8 @@ static void __iomem *rtc_base;
static struct timespec persistent_ts;
static u64 persistent_ms, last_persistent_ms;
+static struct delay_timer tegra_delay_timer;
+
#define timer_writel(value, reg) \
__raw_writel(value, timer_reg_base + (reg))
#define timer_readl(reg) \
@@ -139,6 +142,11 @@ static void tegra_read_persistent_clock(struct timespec *ts)
*ts = *tsp;
}
+static unsigned long tegra_delay_timer_read_counter_long(void)
+{
+ return readl(timer_reg_base + TIMERUS_CNTR_1US);
+}
+
static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -206,6 +214,11 @@ static void __init tegra20_init_timer(struct device_node *np)
BUG();
}
+ tegra_delay_timer.read_current_timer =
+ tegra_delay_timer_read_counter_long;
+ tegra_delay_timer.freq = 1000000;
+ register_current_timer_delay(&tegra_delay_timer);
+
ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
if (ret) {
pr_err("Failed to register timer IRQ: %d\n", ret);
diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c
index dbd30398222a..330e93064692 100644
--- a/drivers/clocksource/timer-marco.c
+++ b/drivers/clocksource/timer-marco.c
@@ -260,6 +260,9 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
clk = of_clk_get(np, 0);
BUG_ON(IS_ERR(clk));
+
+ BUG_ON(clk_prepare_enable(clk));
+
rate = clk_get_rate(clk);
BUG_ON(rate < MARCO_CLOCK_FREQ);
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index a722aac7ac02..ce18d570e1cd 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -200,6 +200,9 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np)
clk = of_clk_get(np, 0);
BUG_ON(IS_ERR(clk));
+
+ BUG_ON(clk_prepare_enable(clk));
+
rate = clk_get_rate(clk);
BUG_ON(rate < PRIMA2_CLOCK_FREQ);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index ccdd4c7e748b..15d06fcf0b50 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -69,7 +69,6 @@ void proc_fork_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- struct timespec ts;
struct task_struct *parent;
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -79,8 +78,7 @@ void proc_fork_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_FORK;
rcu_read_lock();
parent = rcu_dereference(task->real_parent);
@@ -102,7 +100,6 @@ void proc_exec_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
- struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -112,8 +109,7 @@ void proc_exec_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -130,7 +126,6 @@ void proc_id_connector(struct task_struct *task, int which_id)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- struct timespec ts;
const struct cred *cred;
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -156,8 +151,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
}
rcu_read_unlock();
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -170,7 +164,6 @@ void proc_sid_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
- struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -180,8 +173,7 @@ void proc_sid_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_SID;
ev->event_data.sid.process_pid = task->pid;
ev->event_data.sid.process_tgid = task->tgid;
@@ -197,7 +189,6 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
{
struct cn_msg *msg;
struct proc_event *ev;
- struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -207,8 +198,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_PTRACE;
ev->event_data.ptrace.process_pid = task->pid;
ev->event_data.ptrace.process_tgid = task->tgid;
@@ -232,7 +222,6 @@ void proc_comm_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
- struct timespec ts;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
@@ -242,8 +231,7 @@ void proc_comm_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_COMM;
ev->event_data.comm.process_pid = task->pid;
ev->event_data.comm.process_tgid = task->tgid;
@@ -261,7 +249,6 @@ void proc_coredump_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -270,8 +257,7 @@ void proc_coredump_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_COREDUMP;
ev->event_data.coredump.process_pid = task->pid;
ev->event_data.coredump.process_tgid = task->tgid;
@@ -288,7 +274,6 @@ void proc_exit_connector(struct task_struct *task)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -297,8 +282,7 @@ void proc_exit_connector(struct task_struct *task)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -325,7 +309,6 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
@@ -334,8 +317,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
msg->seq = rcvd_seq;
- ktime_get_ts(&ts); /* get high res monotonic timestamp */
- ev->timestamp_ns = timespec_to_ns(&ts);
+ ev->timestamp_ns = ktime_get_ns();
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 1f4d4e315057..a46c223c2506 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -24,6 +24,7 @@
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/export.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/pm_opp.h>
@@ -593,3 +594,7 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
arm_bL_ops = NULL;
}
EXPORT_SYMBOL_GPL(bL_cpufreq_unregister);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index 8d9d59108906..4550f6976768 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -114,4 +114,4 @@ module_platform_driver(generic_bL_platdrv);
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 86beda9f950b..0d2172b07765 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -137,7 +137,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
* not yet registered, we should try defering probe.
*/
if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
- dev_err(cpu_dev, "cpu0 regulator not ready, retry\n");
+ dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
ret = -EPROBE_DEFER;
goto out_put_node;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6f024852c6fb..d9fdeddcef96 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
kfree(policy);
}
-static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
+static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu,
+ struct device *cpu_dev)
{
+ int ret;
+
if (WARN_ON(cpu == policy->cpu))
- return;
+ return 0;
+
+ /* Move kobject to the new policy->cpu */
+ ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
+ if (ret) {
+ pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
+ return ret;
+ }
down_write(&policy->rwsem);
@@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_UPDATE_POLICY_CPU, policy);
+
+ return 0;
}
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
@@ -1153,12 +1165,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
* the creation of a brand new one. So we need to perform this update
* by invoking update_policy_cpu().
*/
- if (recover_policy && cpu != policy->cpu) {
- update_policy_cpu(policy, cpu);
- WARN_ON(kobject_move(&policy->kobj, &dev->kobj));
- } else {
+ if (recover_policy && cpu != policy->cpu)
+ WARN_ON(update_policy_cpu(policy, cpu, dev));
+ else
policy->cpu = cpu;
- }
cpumask_copy(policy->cpus, cpumask_of(cpu));
@@ -1309,38 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
return __cpufreq_add_dev(dev, sif);
}
-static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
- unsigned int old_cpu)
-{
- struct device *cpu_dev;
- int ret;
-
- /* first sibling now owns the new sysfs dir */
- cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
-
- sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
- ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
- if (ret) {
- pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
-
- down_write(&policy->rwsem);
- cpumask_set_cpu(old_cpu, policy->cpus);
- up_write(&policy->rwsem);
-
- ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
- "cpufreq");
-
- return -EINVAL;
- }
-
- return cpu_dev->id;
-}
-
static int __cpufreq_remove_dev_prepare(struct device *dev,
struct subsys_interface *sif)
{
unsigned int cpu = dev->id, cpus;
- int new_cpu, ret;
+ int ret;
unsigned long flags;
struct cpufreq_policy *policy;
@@ -1380,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
if (cpu != policy->cpu) {
sysfs_remove_link(&dev->kobj, "cpufreq");
} else if (cpus > 1) {
- new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
- if (new_cpu >= 0) {
- update_policy_cpu(policy, new_cpu);
+ /* Nominate new CPU */
+ int new_cpu = cpumask_any_but(policy->cpus, cpu);
+ struct device *cpu_dev = get_cpu_device(new_cpu);
- if (!cpufreq_suspended)
- pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
- __func__, new_cpu, cpu);
+ sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
+ ret = update_policy_cpu(policy, new_cpu, cpu_dev);
+ if (ret) {
+ if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
+ "cpufreq"))
+ pr_err("%s: Failed to restore kobj link to cpu:%d\n",
+ __func__, cpu_dev->id);
+ return ret;
}
+
+ if (!cpufreq_suspended)
+ pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+ __func__, new_cpu, cpu);
} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
cpufreq_driver->stop_cpu(policy);
}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 18d409189092..ad3f38fd3eb9 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -170,21 +170,24 @@ static void od_check_cpu(int cpu, unsigned int load)
dbs_freq_increase(policy, policy->max);
} else {
/* Calculate the next frequency proportional to load */
- unsigned int freq_next;
- freq_next = load * policy->cpuinfo.max_freq / 100;
+ unsigned int freq_next, min_f, max_f;
+
+ min_f = policy->cpuinfo.min_freq;
+ max_f = policy->cpuinfo.max_freq;
+ freq_next = min_f + load * (max_f - min_f) / 100;
/* No longer fully busy, reset rate_mult */
dbs_info->rate_mult = 1;
if (!od_tuners->powersave_bias) {
__cpufreq_driver_target(policy, freq_next,
- CPUFREQ_RELATION_L);
+ CPUFREQ_RELATION_C);
return;
}
freq_next = od_ops.powersave_bias_target(policy, freq_next,
CPUFREQ_RELATION_L);
- __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
+ __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C);
}
}
diff --git a/drivers/cpufreq/cpufreq_opp.c b/drivers/cpufreq/cpufreq_opp.c
index c0c6f4a4eccf..f7a32d2326c6 100644
--- a/drivers/cpufreq/cpufreq_opp.c
+++ b/drivers/cpufreq/cpufreq_opp.c
@@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
goto out;
}
- freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL);
+ freq_table = kcalloc(sizeof(*freq_table), (max_opps + 1), GFP_ATOMIC);
if (!freq_table) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 1632981c4b25..df14766a8e06 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -117,7 +117,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
.frequency = 0,
};
struct cpufreq_frequency_table *pos;
- unsigned int freq, i = 0;
+ unsigned int freq, diff, i = 0;
pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
target_freq, relation, policy->cpu);
@@ -127,6 +127,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
suboptimal.frequency = ~0;
break;
case CPUFREQ_RELATION_L:
+ case CPUFREQ_RELATION_C:
optimal.frequency = ~0;
break;
}
@@ -168,6 +169,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
}
break;
+ case CPUFREQ_RELATION_C:
+ diff = abs(freq - target_freq);
+ if (diff < optimal.frequency ||
+ (diff == optimal.frequency &&
+ freq > table[optimal.driver_data].frequency)) {
+ optimal.frequency = diff;
+ optimal.driver_data = i;
+ }
+ break;
}
}
if (optimal.driver_data > i) {
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index af366c21d4b4..c2d30765bf3d 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -66,10 +66,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
/* scaling up? scale voltage before frequency */
if (new_freq > old_freq) {
- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- if (ret) {
- dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
- return ret;
+ if (!IS_ERR(pu_reg)) {
+ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
+ if (ret) {
+ dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
+ return ret;
+ }
}
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
if (ret) {
@@ -121,10 +123,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
ret = 0;
}
- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
- if (ret) {
- dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
- ret = 0;
+ if (!IS_ERR(pu_reg)) {
+ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
+ if (ret) {
+ dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
+ ret = 0;
+ }
}
}
@@ -182,9 +186,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
}
arm_reg = regulator_get(cpu_dev, "arm");
- pu_reg = regulator_get(cpu_dev, "pu");
+ pu_reg = regulator_get_optional(cpu_dev, "pu");
soc_reg = regulator_get(cpu_dev, "soc");
- if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
+ if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
dev_err(cpu_dev, "failed to get regulators\n");
ret = -ENOENT;
goto put_reg;
@@ -268,9 +272,11 @@ soc_opp_out:
ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
if (ret > 0)
transition_latency += ret * 1000;
- ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
- if (ret > 0)
- transition_latency += ret * 1000;
+ if (!IS_ERR(pu_reg)) {
+ ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
+ if (ret > 0)
+ transition_latency += ret * 1000;
+ }
/*
* OPP is maintained in order of increasing frequency, and
@@ -327,7 +333,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
regulator_put(arm_reg);
- regulator_put(pu_reg);
+ if (!IS_ERR(pu_reg))
+ regulator_put(pu_reg);
regulator_put(soc_reg);
clk_put(arm_clk);
clk_put(pll1_sys_clk);
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
index e5122f1bfe78..c1320528b9d0 100644
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ b/drivers/cpufreq/integrator-cpufreq.c
@@ -92,7 +92,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
* Bind to the specified CPU. When this call returns,
* we should be running on the right CPU.
*/
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, cpumask_of(cpu));
BUG_ON(cpu != smp_processor_id());
/* get current setting */
@@ -118,7 +118,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
freqs.new = icst_hz(&cclk_params, vco) / 1000;
if (freqs.old == freqs.new) {
- set_cpus_allowed(current, cpus_allowed);
+ set_cpus_allowed_ptr(current, &cpus_allowed);
return 0;
}
@@ -141,7 +141,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
/*
* Restore the CPUs allowed mask.
*/
- set_cpus_allowed(current, cpus_allowed);
+ set_cpus_allowed_ptr(current, &cpus_allowed);
cpufreq_freq_transition_end(policy, &freqs, 0);
@@ -157,7 +157,7 @@ static unsigned int integrator_get(unsigned int cpu)
cpus_allowed = current->cpus_allowed;
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ set_cpus_allowed_ptr(current, cpumask_of(cpu));
BUG_ON(cpu != smp_processor_id());
/* detect memory etc. */
@@ -173,7 +173,7 @@ static unsigned int integrator_get(unsigned int cpu)
current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
- set_cpus_allowed(current, cpus_allowed);
+ set_cpus_allowed_ptr(current, &cpus_allowed);
return current_freq;
}
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 86631cb6f7de..c5eac949760d 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -37,7 +37,6 @@
#define BYT_TURBO_RATIOS 0x66c
#define BYT_TURBO_VIDS 0x66d
-
#define FRAC_BITS 8
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
#define fp_toint(X) ((X) >> FRAC_BITS)
@@ -50,7 +49,7 @@ static inline int32_t mul_fp(int32_t x, int32_t y)
static inline int32_t div_fp(int32_t x, int32_t y)
{
- return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
+ return div_s64((int64_t)x << FRAC_BITS, y);
}
struct sample {
@@ -148,7 +147,7 @@ static struct perf_limits limits = {
};
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
- int deadband, int integral) {
+ int deadband, int integral) {
pid->setpoint = setpoint;
pid->deadband = deadband;
pid->integral = int_tofp(integral);
@@ -167,7 +166,6 @@ static inline void pid_i_gain_set(struct _pid *pid, int percent)
static inline void pid_d_gain_set(struct _pid *pid, int percent)
{
-
pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
}
@@ -207,16 +205,13 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
- pid_reset(&cpu->pid,
- pid_params.setpoint,
- 100,
- pid_params.deadband,
- 0);
+ pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0);
}
static inline void intel_pstate_reset_all_pid(void)
{
unsigned int cpu;
+
for_each_online_cpu(cpu) {
if (all_cpu_data[cpu])
intel_pstate_busy_pid_reset(all_cpu_data[cpu]);
@@ -230,13 +225,13 @@ static int pid_param_set(void *data, u64 val)
intel_pstate_reset_all_pid();
return 0;
}
+
static int pid_param_get(void *data, u64 *val)
{
*val = *(u32 *)data;
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get,
- pid_param_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n");
struct pid_param {
char *name;
@@ -253,9 +248,9 @@ static struct pid_param pid_files[] = {
{NULL, NULL}
};
-static struct dentry *debugfs_parent;
-static void intel_pstate_debug_expose_params(void)
+static void __init intel_pstate_debug_expose_params(void)
{
+ struct dentry *debugfs_parent;
int i = 0;
debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
@@ -263,8 +258,8 @@ static void intel_pstate_debug_expose_params(void)
return;
while (pid_files[i].name) {
debugfs_create_file(pid_files[i].name, 0660,
- debugfs_parent, pid_files[i].value,
- &fops_pid_param);
+ debugfs_parent, pid_files[i].value,
+ &fops_pid_param);
i++;
}
}
@@ -280,10 +275,11 @@ static void intel_pstate_debug_expose_params(void)
}
static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -296,10 +292,11 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
}
static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -307,14 +304,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
+
return count;
}
static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
+ const char *buf, size_t count)
{
unsigned int input;
int ret;
+
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -342,17 +341,16 @@ static struct attribute *intel_pstate_attributes[] = {
static struct attribute_group intel_pstate_attr_group = {
.attrs = intel_pstate_attributes,
};
-static struct kobject *intel_pstate_kobject;
-static void intel_pstate_sysfs_expose_params(void)
+static void __init intel_pstate_sysfs_expose_params(void)
{
+ struct kobject *intel_pstate_kobject;
int rc;
intel_pstate_kobject = kobject_create_and_add("intel_pstate",
&cpu_subsys.dev_root->kobj);
BUG_ON(!intel_pstate_kobject);
- rc = sysfs_create_group(intel_pstate_kobject,
- &intel_pstate_attr_group);
+ rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
BUG_ON(rc);
}
@@ -360,6 +358,7 @@ static void intel_pstate_sysfs_expose_params(void)
static int byt_get_min_pstate(void)
{
u64 value;
+
rdmsrl(BYT_RATIOS, value);
return (value >> 8) & 0x7F;
}
@@ -367,6 +366,7 @@ static int byt_get_min_pstate(void)
static int byt_get_max_pstate(void)
{
u64 value;
+
rdmsrl(BYT_RATIOS, value);
return (value >> 16) & 0x7F;
}
@@ -374,6 +374,7 @@ static int byt_get_max_pstate(void)
static int byt_get_turbo_pstate(void)
{
u64 value;
+
rdmsrl(BYT_TURBO_RATIOS, value);
return value & 0x7F;
}
@@ -407,7 +408,6 @@ static void byt_get_vid(struct cpudata *cpudata)
{
u64 value;
-
rdmsrl(BYT_VIDS, value);
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
@@ -420,10 +420,10 @@ static void byt_get_vid(struct cpudata *cpudata)
cpudata->vid.turbo = value & 0x7f;
}
-
static int core_get_min_pstate(void)
{
u64 value;
+
rdmsrl(MSR_PLATFORM_INFO, value);
return (value >> 40) & 0xFF;
}
@@ -431,6 +431,7 @@ static int core_get_min_pstate(void)
static int core_get_max_pstate(void)
{
u64 value;
+
rdmsrl(MSR_PLATFORM_INFO, value);
return (value >> 8) & 0xFF;
}
@@ -439,9 +440,10 @@ static int core_get_turbo_pstate(void)
{
u64 value;
int nont, ret;
+
rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
nont = core_get_max_pstate();
- ret = ((value) & 255);
+ ret = (value) & 255;
if (ret <= nont)
ret = nont;
return ret;
@@ -493,12 +495,12 @@ static struct cpu_defaults byt_params = {
},
};
-
static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
{
int max_perf = cpu->pstate.turbo_pstate;
int max_perf_adj;
int min_perf;
+
if (limits.no_turbo)
max_perf = cpu->pstate.max_pstate;
@@ -507,8 +509,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
- *min = clamp_t(int, min_perf,
- cpu->pstate.min_pstate, max_perf);
+ *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
}
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
@@ -529,21 +530,6 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
pstate_funcs.set(cpu, pstate);
}
-static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
-{
- int target;
- target = cpu->pstate.current_pstate + steps;
-
- intel_pstate_set_pstate(cpu, target);
-}
-
-static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps)
-{
- int target;
- target = cpu->pstate.current_pstate - steps;
- intel_pstate_set_pstate(cpu, target);
-}
-
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
{
cpu->pstate.min_pstate = pstate_funcs.get_min();
@@ -559,13 +545,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
int64_t core_pct;
- int32_t rem;
core_pct = int_tofp(sample->aperf) * int_tofp(100);
- core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
-
- if ((rem << 1) >= int_tofp(sample->mperf))
- core_pct += 1;
+ core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
sample->freq = fp_toint(
mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
@@ -576,12 +558,12 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
static inline void intel_pstate_sample(struct cpudata *cpu)
{
u64 aperf, mperf;
+ unsigned long flags;
+ local_irq_save(flags);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
-
- aperf = aperf >> FRAC_BITS;
- mperf = mperf >> FRAC_BITS;
+ local_irq_restore(flags);
cpu->last_sample_time = cpu->sample.time;
cpu->sample.time = ktime_get();
@@ -598,10 +580,9 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
{
- int sample_time, delay;
+ int delay;
- sample_time = pid_params.sample_rate_ms;
- delay = msecs_to_jiffies(sample_time);
+ delay = msecs_to_jiffies(pid_params.sample_rate_ms);
mod_timer_pinned(&cpu->timer, jiffies + delay);
}
@@ -616,12 +597,12 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
current_pstate = int_tofp(cpu->pstate.current_pstate);
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
- sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC);
+ sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC;
duration_us = (u32) ktime_us_delta(cpu->sample.time,
- cpu->last_sample_time);
+ cpu->last_sample_time);
if (duration_us > sample_time * 3) {
sample_ratio = div_fp(int_tofp(sample_time),
- int_tofp(duration_us));
+ int_tofp(duration_us));
core_busy = mul_fp(core_busy, sample_ratio);
}
@@ -632,20 +613,15 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
{
int32_t busy_scaled;
struct _pid *pid;
- signed int ctl = 0;
- int steps;
+ signed int ctl;
pid = &cpu->pid;
busy_scaled = intel_pstate_get_scaled_busy(cpu);
ctl = pid_calc(pid, busy_scaled);
- steps = abs(ctl);
-
- if (ctl < 0)
- intel_pstate_pstate_increase(cpu, steps);
- else
- intel_pstate_pstate_decrease(cpu, steps);
+ /* Negative values of ctl increase the pstate and vice versa */
+ intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl);
}
static void intel_pstate_timer_func(unsigned long __data)
@@ -705,8 +681,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
init_timer_deferrable(&cpu->timer);
cpu->timer.function = intel_pstate_timer_func;
- cpu->timer.data =
- (unsigned long)cpu;
+ cpu->timer.data = (unsigned long)cpu;
cpu->timer.expires = jiffies + HZ/100;
intel_pstate_busy_pid_reset(cpu);
intel_pstate_sample(cpu);
@@ -751,7 +726,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
- limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq;
+ limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
@@ -763,8 +738,8 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
{
cpufreq_verify_within_cpu_limits(policy);
- if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
- (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
+ if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
+ policy->policy != CPUFREQ_POLICY_PERFORMANCE)
return -EINVAL;
return 0;
@@ -797,7 +772,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
- cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
+ cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
limits.turbo_disabled = 1;
limits.no_turbo = 1;
}
@@ -839,8 +814,8 @@ static int intel_pstate_msrs_not_valid(void)
rdmsrl(MSR_IA32_MPERF, mperf);
if (!pstate_funcs.get_max() ||
- !pstate_funcs.get_min() ||
- !pstate_funcs.get_turbo())
+ !pstate_funcs.get_min() ||
+ !pstate_funcs.get_turbo())
return -ENODEV;
rdmsrl(MSR_IA32_APERF, tmp);
@@ -922,14 +897,14 @@ static bool intel_pstate_platform_pwr_mgmt_exists(void)
struct acpi_table_header hdr;
struct hw_vendor_info *v_info;
- if (acpi_disabled
- || ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
+ if (acpi_disabled ||
+ ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
return false;
for (v_info = vendor_info; v_info->valid; v_info++) {
- if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
- && !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
- && intel_pstate_no_acpi_pss())
+ if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) &&
+ !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
+ intel_pstate_no_acpi_pss())
return true;
}
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index d4add8621944..9fa177206032 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -148,9 +148,9 @@ static void loongson2_cpu_wait(void)
u32 cpu_freq;
spin_lock_irqsave(&loongson2_wait_lock, flags);
- cpu_freq = LOONGSON_CHIPCFG0;
- LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */
- LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */
+ cpu_freq = LOONGSON_CHIPCFG(0);
+ LOONGSON_CHIPCFG(0) &= ~0x7; /* Put CPU into wait mode */
+ LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */
spin_unlock_irqrestore(&loongson2_wait_lock, flags);
local_irq_enable();
}
diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c
index 8bc422977b5b..4ff86878727f 100644
--- a/drivers/cpufreq/pmac64-cpufreq.c
+++ b/drivers/cpufreq/pmac64-cpufreq.c
@@ -499,8 +499,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode)
}
/* Lookup the i2c hwclock */
- for (hwclock = NULL;
- (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){
+ for_each_node_by_name(hwclock, "i2c-hwclock") {
const char *loc = of_get_property(hwclock,
"hwctrl-location", NULL);
if (loc == NULL)
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index c8012bc86910..f91027259c3c 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -55,6 +55,7 @@ static const struct {
unsigned freq;
unsigned mult;
} usual_frequency_table[] = {
+ { 350000, 35 }, // 100 * 3.5
{ 400000, 40 }, // 100 * 4
{ 450000, 45 }, // 100 * 4.5
{ 475000, 50 }, // 95 * 5
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index bb1d08dc8cc8..379c0837f5a9 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -28,6 +28,7 @@
#include <linux/of.h>
#include <asm/cputhreads.h>
+#include <asm/firmware.h>
#include <asm/reg.h>
#include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */
@@ -98,7 +99,11 @@ static int init_powernv_pstates(void)
return -ENODEV;
}
- WARN_ON(len_ids != len_freqs);
+ if (len_ids != len_freqs) {
+ pr_warn("Entries in ibm,pstate-ids and "
+ "ibm,pstate-frequencies-mhz does not match\n");
+ }
+
nr_pstates = min(len_ids, len_freqs) / sizeof(u32);
if (!nr_pstates) {
pr_warn("No PStates found\n");
@@ -131,7 +136,12 @@ static unsigned int pstate_id_to_freq(int pstate_id)
int i;
i = powernv_pstate_info.max - pstate_id;
- BUG_ON(i >= powernv_pstate_info.nr_pstates || i < 0);
+ if (i >= powernv_pstate_info.nr_pstates || i < 0) {
+ pr_warn("PState id %d outside of PState table, "
+ "reporting nominal id %d instead\n",
+ pstate_id, powernv_pstate_info.nominal);
+ i = powernv_pstate_info.max - powernv_pstate_info.nominal;
+ }
return powernv_freqs[i].frequency;
}
@@ -321,6 +331,10 @@ static int __init powernv_cpufreq_init(void)
{
int rc = 0;
+ /* Don't probe on pseries (guest) platforms */
+ if (!firmware_has_feature(FW_FEATURE_OPALv3))
+ return -ENODEV;
+
/* Discover pstates from device tree and init */
rc = init_powernv_pstates();
if (rc) {
diff --git a/drivers/cpufreq/s3c2410-cpufreq.c b/drivers/cpufreq/s3c2410-cpufreq.c
index cfa0dd8723ec..b8e5da8e188b 100644
--- a/drivers/cpufreq/s3c2410-cpufreq.c
+++ b/drivers/cpufreq/s3c2410-cpufreq.c
@@ -26,7 +26,6 @@
#include <mach/regs-clock.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
@@ -104,7 +103,6 @@ static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
.calc_iotiming = s3c2410_iotiming_calc,
.set_iotiming = s3c2410_iotiming_set,
.get_iotiming = s3c2410_iotiming_get,
- .resume_clocks = s3c2410_setup_clocks,
.set_fvco = s3c2410_set_fvco,
.set_refresh = s3c2410_cpufreq_setrefresh,
diff --git a/drivers/cpufreq/s3c2412-cpufreq.c b/drivers/cpufreq/s3c2412-cpufreq.c
index 4645b4898996..eb262133fef2 100644
--- a/drivers/cpufreq/s3c2412-cpufreq.c
+++ b/drivers/cpufreq/s3c2412-cpufreq.c
@@ -28,7 +28,6 @@
#include <mach/s3c2412.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
/* our clock resources. */
@@ -188,8 +187,6 @@ static struct s3c_cpufreq_info s3c2412_cpufreq_info = {
.set_iotiming = s3c2412_iotiming_set,
.get_iotiming = s3c2412_iotiming_get,
- .resume_clocks = s3c2412_setup_clocks,
-
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
};
diff --git a/drivers/cpufreq/s3c2440-cpufreq.c b/drivers/cpufreq/s3c2440-cpufreq.c
index f84ed10755b5..0129f5c70a61 100644
--- a/drivers/cpufreq/s3c2440-cpufreq.c
+++ b/drivers/cpufreq/s3c2440-cpufreq.c
@@ -29,7 +29,6 @@
#include <plat/cpu.h>
#include <plat/cpu-freq-core.h>
-#include <plat/clock.h>
static struct clk *xtal;
static struct clk *fclk;
@@ -262,8 +261,6 @@ static struct s3c_cpufreq_info s3c2440_cpufreq_info = {
.calc_divs = s3c2440_cpufreq_calcdivs,
.calc_freqtable = s3c2440_cpufreq_calctable,
- .resume_clocks = s3c244x_setup_clocks,
-
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
};
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 227ebf7c1eea..d00f1cee4509 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -27,7 +27,6 @@
#include <asm/mach/map.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
#include <mach/regs-clock.h>
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 19a10b89fef7..9a68225a757e 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -16,11 +16,70 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regulator/consumer.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
+static void __iomem *clk_base;
+static void __iomem *dmc_base[2];
+
+#define S5P_CLKREG(x) (clk_base + (x))
+
+#define S5P_APLL_LOCK S5P_CLKREG(0x00)
+#define S5P_APLL_CON S5P_CLKREG(0x100)
+#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
+#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
+#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
+#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
+#define S5P_CLK_DIV6 S5P_CLKREG(0x318)
+#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000)
+#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004)
+#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100)
+#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104)
+
+#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
+
+/* CLKSRC0 */
+#define S5P_CLKSRC0_MUX200_SHIFT (16)
+#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
+#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
+#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
+
+/* CLKSRC2 */
+#define S5P_CLKSRC2_G3D_SHIFT (0)
+#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT)
+#define S5P_CLKSRC2_MFC_SHIFT (4)
+#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT (0)
+#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT (4)
+#define S5P_CLKDIV0_A2M_MASK (0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_HCLK200_SHIFT (8)
+#define S5P_CLKDIV0_HCLK200_MASK (0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
+#define S5P_CLKDIV0_PCLK100_SHIFT (12)
+#define S5P_CLKDIV0_PCLK100_MASK (0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
+#define S5P_CLKDIV0_HCLK166_SHIFT (16)
+#define S5P_CLKDIV0_HCLK166_MASK (0xF << S5P_CLKDIV0_HCLK166_SHIFT)
+#define S5P_CLKDIV0_PCLK83_SHIFT (20)
+#define S5P_CLKDIV0_PCLK83_MASK (0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
+#define S5P_CLKDIV0_HCLK133_SHIFT (24)
+#define S5P_CLKDIV0_HCLK133_MASK (0xF << S5P_CLKDIV0_HCLK133_SHIFT)
+#define S5P_CLKDIV0_PCLK66_SHIFT (28)
+#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+
+/* CLKDIV2 */
+#define S5P_CLKDIV2_G3D_SHIFT (0)
+#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT)
+#define S5P_CLKDIV2_MFC_SHIFT (4)
+#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT)
+
+/* CLKDIV6 */
+#define S5P_CLKDIV6_ONEDRAM_SHIFT (28)
+#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
static struct clk *dmc0_clk;
static struct clk *dmc1_clk;
@@ -142,9 +201,9 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
void __iomem *reg = NULL;
if (ch == DMC0) {
- reg = (S5P_VA_DMC0 + 0x30);
+ reg = (dmc_base[0] + 0x30);
} else if (ch == DMC1) {
- reg = (S5P_VA_DMC1 + 0x30);
+ reg = (dmc_base[1] + 0x30);
} else {
printk(KERN_ERR "Cannot find DMC port\n");
return;
@@ -472,7 +531,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
* check_mem_type : This driver only support LPDDR & LPDDR2.
* other memory type is not supported.
*/
- mem_type = check_mem_type(S5P_VA_DMC0);
+ mem_type = check_mem_type(dmc_base[0]);
if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
@@ -481,10 +540,10 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
}
/* Find current refresh counter and frequency each DMC */
- s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
+ s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000);
s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
- s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
+ s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000);
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
policy->suspend_freq = SLEEP_FREQ;
@@ -527,8 +586,55 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
};
-static int __init s5pv210_cpufreq_init(void)
+static int s5pv210_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *np;
+ int id;
+
+ /*
+ * HACK: This is a temporary workaround to get access to clock
+ * and DMC controller registers directly and remove static mappings
+ * and dependencies on platform headers. It is necessary to enable
+ * S5PV210 multi-platform support and will be removed together with
+ * this whole driver as soon as S5PV210 gets migrated to use
+ * cpufreq-cpu0 driver.
+ */
+ np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
+ if (!np) {
+ pr_err("%s: failed to find clock controller DT node\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ clk_base = of_iomap(np, 0);
+ if (!clk_base) {
+ pr_err("%s: failed to map clock registers\n", __func__);
+ return -EFAULT;
+ }
+
+ for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {
+ id = of_alias_get_id(np, "dmc");
+ if (id < 0 || id >= ARRAY_SIZE(dmc_base)) {
+ pr_err("%s: failed to get alias of dmc node '%s'\n",
+ __func__, np->name);
+ return id;
+ }
+
+ dmc_base[id] = of_iomap(np, 0);
+ if (!dmc_base[id]) {
+ pr_err("%s: failed to map dmc%d registers\n",
+ __func__, id);
+ return -EFAULT;
+ }
+ }
+
+ for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) {
+ if (!dmc_base[id]) {
+ pr_err("%s: failed to find dmc%d node\n", __func__, id);
+ return -ENODEV;
+ }
+ }
+
arm_regulator = regulator_get(NULL, "vddarm");
if (IS_ERR(arm_regulator)) {
pr_err("failed to get regulator vddarm");
@@ -547,4 +653,11 @@ static int __init s5pv210_cpufreq_init(void)
return cpufreq_register_driver(&s5pv210_driver);
}
-late_initcall(s5pv210_cpufreq_init);
+static struct platform_driver s5pv210_cpufreq_platdrv = {
+ .driver = {
+ .name = "s5pv210-cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5pv210_cpufreq_probe,
+};
+module_platform_driver(s5pv210_cpufreq_platdrv);
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index 8635eec96da5..5fc96d5d656b 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -324,8 +324,8 @@ static int __init speedstep_init(void)
return -ENODEV;
}
- pr_debug("signature:0x%.8ulx, command:0x%.8ulx, "
- "event:0x%.8ulx, perf_level:0x%.8ulx.\n",
+ pr_debug("signature:0x%.8x, command:0x%.8x, "
+ "event:0x%.8x, perf_level:0x%.8x.\n",
ist_info.signature, ist_info.command,
ist_info.event, ist_info.perf_level);
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index 1b96fb91d32c..32748c36c477 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -15,12 +15,7 @@ config CPU_IDLE
if CPU_IDLE
config CPU_IDLE_MULTIPLE_DRIVERS
- bool "Support multiple cpuidle drivers"
- 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.
+ bool
config CPU_IDLE_GOV_LADDER
bool "Ladder governor (for periodic timer tick)"
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index b6d69e899f5d..38cff69ffe06 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -1,15 +1,10 @@
#
# ARM CPU Idle drivers
#
-config ARM_ARMADA_370_XP_CPUIDLE
- bool "CPU Idle Driver for Armada 370/XP family processors"
- depends on ARCH_MVEBU
- help
- Select this to enable cpuidle on Armada 370/XP processors.
-
config ARM_BIG_LITTLE_CPUIDLE
bool "Support for ARM big.LITTLE processors"
- depends on ARCH_VEXPRESS_TC2_PM
+ depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
+ depends on MCPM
select ARM_CPU_SUSPEND
select CPU_IDLE_MULTIPLE_DRIVERS
help
@@ -61,3 +56,9 @@ config ARM_EXYNOS_CPUIDLE
depends on ARCH_EXYNOS
help
Select this to enable cpuidle for Exynos processors
+
+config ARM_MVEBU_V7_CPUIDLE
+ bool "CPU Idle Driver for mvebu v7 family processors"
+ depends on ARCH_MVEBU
+ help
+ Select this to enable cpuidle on Armada 370, 38x and XP processors.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index d8bb1ff72561..11edb31c55e9 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
##################################################################################
# ARM SoC drivers
-obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o
+obj-$(CONFIG_ARM_MVEBU_V7_CPUIDLE) += cpuidle-mvebu-v7.o
obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o
obj-$(CONFIG_ARM_CLPS711X_CPUIDLE) += cpuidle-clps711x.o
obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o
diff --git a/drivers/cpuidle/cpuidle-armada-370-xp.c b/drivers/cpuidle/cpuidle-armada-370-xp.c
deleted file mode 100644
index a5fba0287bfb..000000000000
--- a/drivers/cpuidle/cpuidle-armada-370-xp.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Marvell Armada 370 and Armada XP SoC cpuidle driver
- *
- * Copyright (C) 2014 Marvell
- *
- * Nadav Haklai <nadavh@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
- */
-
-#include <linux/cpu_pm.h>
-#include <linux/cpuidle.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/suspend.h>
-#include <linux/platform_device.h>
-#include <asm/cpuidle.h>
-
-#define ARMADA_370_XP_MAX_STATES 3
-#define ARMADA_370_XP_FLAG_DEEP_IDLE 0x10000
-
-static int (*armada_370_xp_cpu_suspend)(int);
-
-static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- int ret;
- bool deepidle = false;
- cpu_pm_enter();
-
- if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE)
- deepidle = true;
-
- ret = armada_370_xp_cpu_suspend(deepidle);
- if (ret)
- return ret;
-
- cpu_pm_exit();
-
- return index;
-}
-
-static struct cpuidle_driver armada_370_xp_idle_driver = {
- .name = "armada_370_xp_idle",
- .states[0] = ARM_CPUIDLE_WFI_STATE,
- .states[1] = {
- .enter = armada_370_xp_enter_idle,
- .exit_latency = 10,
- .power_usage = 50,
- .target_residency = 100,
- .flags = CPUIDLE_FLAG_TIME_VALID,
- .name = "Idle",
- .desc = "CPU power down",
- },
- .states[2] = {
- .enter = armada_370_xp_enter_idle,
- .exit_latency = 100,
- .power_usage = 5,
- .target_residency = 1000,
- .flags = CPUIDLE_FLAG_TIME_VALID |
- ARMADA_370_XP_FLAG_DEEP_IDLE,
- .name = "Deep idle",
- .desc = "CPU and L2 Fabric power down",
- },
- .state_count = ARMADA_370_XP_MAX_STATES,
-};
-
-static int armada_370_xp_cpuidle_probe(struct platform_device *pdev)
-{
-
- armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data);
- return cpuidle_register(&armada_370_xp_idle_driver, NULL);
-}
-
-static struct platform_driver armada_370_xp_cpuidle_plat_driver = {
- .driver = {
- .name = "cpuidle-armada-370-xp",
- .owner = THIS_MODULE,
- },
- .probe = armada_370_xp_cpuidle_probe,
-};
-
-module_platform_driver(armada_370_xp_cpuidle_plat_driver);
-
-MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
-MODULE_DESCRIPTION("Armada 370/XP cpu idle driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index b45fc6249041..344d79fa3407 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -163,14 +163,24 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
return 0;
}
+static const struct of_device_id compatible_machine_match[] = {
+ { .compatible = "arm,vexpress,v2p-ca15_a7" },
+ { .compatible = "samsung,exynos5420" },
+ {},
+};
+
static int __init bl_idle_init(void)
{
int ret;
+ struct device_node *root = of_find_node_by_path("/");
+
+ if (!root)
+ return -ENODEV;
/*
* Initialize the driver just for a compliant set of machines
*/
- if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7"))
+ if (!of_match_node(compatible_machine_match, root))
return -ENODEV;
/*
* For now the differentiation between little and big cores
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 7c0151263828..ba9b34b579f3 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -20,25 +20,6 @@
static void (*exynos_enter_aftr)(void);
-static int idle_finisher(unsigned long flags)
-{
- exynos_enter_aftr();
- cpu_do_idle();
-
- return 1;
-}
-
-static int exynos_enter_core0_aftr(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- cpu_pm_enter();
- cpu_suspend(0, idle_finisher);
- cpu_pm_exit();
-
- return index;
-}
-
static int exynos_enter_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
@@ -51,8 +32,10 @@ static int exynos_enter_lowpower(struct cpuidle_device *dev,
if (new_index == 0)
return arm_cpuidle_simple_enter(dev, drv, new_index);
- else
- return exynos_enter_core0_aftr(dev, drv, new_index);
+
+ exynos_enter_aftr();
+
+ return new_index;
}
static struct cpuidle_driver exynos_idle_driver = {
diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c
new file mode 100644
index 000000000000..45371bb16214
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-mvebu-v7.c
@@ -0,0 +1,150 @@
+/*
+ * Marvell Armada 370, 38x and XP SoC cpuidle driver
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Nadav Haklai <nadavh@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/suspend.h>
+#include <linux/platform_device.h>
+#include <asm/cpuidle.h>
+
+#define MVEBU_V7_FLAG_DEEP_IDLE 0x10000
+
+static int (*mvebu_v7_cpu_suspend)(int);
+
+static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ int ret;
+ bool deepidle = false;
+ cpu_pm_enter();
+
+ if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
+ deepidle = true;
+
+ ret = mvebu_v7_cpu_suspend(deepidle);
+ if (ret)
+ return ret;
+
+ cpu_pm_exit();
+
+ return index;
+}
+
+static struct cpuidle_driver armadaxp_idle_driver = {
+ .name = "armada_xp_idle",
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = mvebu_v7_enter_idle,
+ .exit_latency = 10,
+ .power_usage = 50,
+ .target_residency = 100,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "MV CPU IDLE",
+ .desc = "CPU power down",
+ },
+ .states[2] = {
+ .enter = mvebu_v7_enter_idle,
+ .exit_latency = 100,
+ .power_usage = 5,
+ .target_residency = 1000,
+ .flags = CPUIDLE_FLAG_TIME_VALID |
+ MVEBU_V7_FLAG_DEEP_IDLE,
+ .name = "MV CPU DEEP IDLE",
+ .desc = "CPU and L2 Fabric power down",
+ },
+ .state_count = 3,
+};
+
+static struct cpuidle_driver armada370_idle_driver = {
+ .name = "armada_370_idle",
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = mvebu_v7_enter_idle,
+ .exit_latency = 100,
+ .power_usage = 5,
+ .target_residency = 1000,
+ .flags = (CPUIDLE_FLAG_TIME_VALID |
+ MVEBU_V7_FLAG_DEEP_IDLE),
+ .name = "Deep Idle",
+ .desc = "CPU and L2 Fabric power down",
+ },
+ .state_count = 2,
+};
+
+static struct cpuidle_driver armada38x_idle_driver = {
+ .name = "armada_38x_idle",
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = mvebu_v7_enter_idle,
+ .exit_latency = 10,
+ .power_usage = 5,
+ .target_residency = 100,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "Idle",
+ .desc = "CPU and SCU power down",
+ },
+ .state_count = 2,
+};
+
+static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
+{
+ mvebu_v7_cpu_suspend = pdev->dev.platform_data;
+
+ if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
+ return cpuidle_register(&armadaxp_idle_driver, NULL);
+ else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
+ return cpuidle_register(&armada370_idle_driver, NULL);
+ else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
+ return cpuidle_register(&armada38x_idle_driver, NULL);
+ else
+ return -EINVAL;
+}
+
+static struct platform_driver armadaxp_cpuidle_plat_driver = {
+ .driver = {
+ .name = "cpuidle-armada-xp",
+ .owner = THIS_MODULE,
+ },
+ .probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armadaxp_cpuidle_plat_driver);
+
+static struct platform_driver armada370_cpuidle_plat_driver = {
+ .driver = {
+ .name = "cpuidle-armada-370",
+ .owner = THIS_MODULE,
+ },
+ .probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada370_cpuidle_plat_driver);
+
+static struct platform_driver armada38x_cpuidle_plat_driver = {
+ .driver = {
+ .name = "cpuidle-armada-38x",
+ .owner = THIS_MODULE,
+ },
+ .probe = mvebu_v7_cpuidle_probe,
+};
+
+module_platform_driver(armada38x_cpuidle_plat_driver);
+
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
index 74f5788d50b1..a64be578dab2 100644
--- a/drivers/cpuidle/cpuidle-powernv.c
+++ b/drivers/cpuidle/cpuidle-powernv.c
@@ -160,10 +160,10 @@ static int powernv_cpuidle_driver_init(void)
static int powernv_add_idle_states(void)
{
struct device_node *power_mgt;
- struct property *prop;
int nr_idle_states = 1; /* Snooze */
int dt_idle_states;
- u32 *flags;
+ const __be32 *idle_state_flags;
+ u32 len_flags, flags;
int i;
/* Currently we have snooze statically defined */
@@ -174,18 +174,18 @@ static int powernv_add_idle_states(void)
return nr_idle_states;
}
- prop = of_find_property(power_mgt, "ibm,cpu-idle-state-flags", NULL);
- if (!prop) {
+ idle_state_flags = of_get_property(power_mgt, "ibm,cpu-idle-state-flags", &len_flags);
+ if (!idle_state_flags) {
pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n");
return nr_idle_states;
}
- dt_idle_states = prop->length / sizeof(u32);
- flags = (u32 *) prop->value;
+ dt_idle_states = len_flags / sizeof(u32);
for (i = 0; i < dt_idle_states; i++) {
- if (flags[i] & IDLE_USE_INST_NAP) {
+ flags = be32_to_cpu(idle_state_flags[i]);
+ if (flags & IDLE_USE_INST_NAP) {
/* Add NAP state */
strcpy(powernv_states[nr_idle_states].name, "Nap");
strcpy(powernv_states[nr_idle_states].desc, "Nap");
@@ -196,7 +196,7 @@ static int powernv_add_idle_states(void)
nr_idle_states++;
}
- if (flags[i] & IDLE_USE_INST_SLEEP) {
+ if (flags & IDLE_USE_INST_SLEEP) {
/* Add FASTSLEEP state */
strcpy(powernv_states[nr_idle_states].name, "FastSleep");
strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index cb7019977c50..ee9df5e3f5eb 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -119,11 +119,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
ktime_t time_start, time_end;
s64 diff;
+ trace_cpu_idle_rcuidle(index, dev->cpu);
time_start = ktime_get();
entered_state = target_state->enter(dev, drv, index);
time_end = ktime_get();
+ trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
if (!cpuidle_state_is_coupled(dev, drv, entered_state))
local_irq_enable();
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 9634f20e3926..e431d11abf8d 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -182,10 +182,6 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
static int poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- ktime_t t1, t2;
- s64 diff;
-
- t1 = ktime_get();
local_irq_enable();
if (!current_set_polling_and_test()) {
while (!need_resched())
@@ -193,13 +189,6 @@ static int poll_idle(struct cpuidle_device *dev,
}
current_clr_polling();
- t2 = ktime_get();
- diff = ktime_to_us(ktime_sub(t2, t1));
- if (diff > INT_MAX)
- diff = INT_MAX;
-
- dev->last_residency = (int) diff;
-
return index;
}
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 9f08e8cce1af..044ee0df5871 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -144,7 +144,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
- for (i = 0; i < drv->state_count; i++) {
+ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
state = &drv->states[i];
lstate = &ldev->states[i];
@@ -156,7 +156,7 @@ static int ladder_enable_device(struct cpuidle_driver *drv,
if (i < drv->state_count - 1)
lstate->threshold.promotion_time = state->exit_latency;
- if (i > 0)
+ if (i > CPUIDLE_DRIVER_STATE_START)
lstate->threshold.demotion_time = state->exit_latency;
}
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index c4f80c15a48d..34db2fb3ef1e 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -31,11 +31,11 @@
* The default values do not overflow.
*/
#define BUCKETS 12
-#define INTERVALS 8
+#define INTERVAL_SHIFT 3
+#define INTERVALS (1UL << INTERVAL_SHIFT)
#define RESOLUTION 1024
#define DECAY 8
#define MAX_INTERESTING 50000
-#define STDDEV_THRESH 400
/*
@@ -134,15 +134,12 @@ struct menu_device {
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
-static int get_loadavg(void)
+static inline int get_loadavg(unsigned long load)
{
- unsigned long this = this_cpu_load();
-
-
- return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10;
+ return LOAD_INT(load) * 10 + LOAD_FRAC(load) / 10;
}
-static inline int which_bucket(unsigned int duration)
+static inline int which_bucket(unsigned int duration, unsigned long nr_iowaiters)
{
int bucket = 0;
@@ -152,7 +149,7 @@ static inline int which_bucket(unsigned int duration)
* This allows us to calculate
* E(duration)|iowait
*/
- if (nr_iowait_cpu(smp_processor_id()))
+ if (nr_iowaiters)
bucket = BUCKETS/2;
if (duration < 10)
@@ -175,16 +172,16 @@ static inline int which_bucket(unsigned int duration)
* to be, the higher this multiplier, and thus the higher
* the barrier to go to an expensive C state.
*/
-static inline int performance_multiplier(void)
+static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned long load)
{
int mult = 1;
/* for higher loadavg, we are more reluctant */
- mult += 2 * get_loadavg();
+ mult += 2 * get_loadavg(load);
/* for IO wait tasks (per cpu!) we add 5x each */
- mult += 10 * nr_iowait_cpu(smp_processor_id());
+ mult += 10 * nr_iowaiters;
return mult;
}
@@ -228,7 +225,10 @@ again:
max = value;
}
}
- do_div(avg, divisor);
+ if (divisor == INTERVALS)
+ avg >>= INTERVAL_SHIFT;
+ else
+ do_div(avg, divisor);
/* Then try to determine standard deviation */
stddev = 0;
@@ -239,7 +239,11 @@ again:
stddev += diff * diff;
}
}
- do_div(stddev, divisor);
+ if (divisor == INTERVALS)
+ stddev >>= INTERVAL_SHIFT;
+ else
+ do_div(stddev, divisor);
+
/*
* The typical interval is obtained when standard deviation is small
* or standard deviation is small compared to the average interval.
@@ -289,7 +293,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
int i;
unsigned int interactivity_req;
- struct timespec t;
+ unsigned long nr_iowaiters, cpu_load;
if (data->needs_update) {
menu_update(drv, dev);
@@ -303,12 +307,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
return 0;
/* determine the expected residency time, round up */
- t = ktime_to_timespec(tick_nohz_get_sleep_length());
- data->next_timer_us =
- t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
-
+ data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length());
- data->bucket = which_bucket(data->next_timer_us);
+ get_iowait_load(&nr_iowaiters, &cpu_load);
+ data->bucket = which_bucket(data->next_timer_us, nr_iowaiters);
/*
* Force the result of multiplication to be 64 bits even if both
@@ -326,7 +328,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
* duration / latency ratio. Adjust the latency limit if
* necessary.
*/
- interactivity_req = data->predicted_us / performance_multiplier();
+ interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
if (latency_req > interactivity_req)
latency_req = interactivity_req;
@@ -399,7 +401,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
*
* Any measured amount of time will include the exit latency.
* Since we are interested in when the wakeup begun, not when it
- * was completed, we must substract the exit latency. However, if
+ * was completed, we must subtract the exit latency. However, if
* the measured amount of time is less than the exit latency,
* assume the state was never reached and the exit latency is 0.
*/
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index efe2f175168f..97c5903b4606 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -445,7 +445,7 @@ static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
#define define_one_driver_ro(_name, show) \
static struct cpuidle_driver_attr attr_driver_##_name = \
- __ATTR(_name, 0644, show, NULL)
+ __ATTR(_name, 0444, show, NULL)
struct cpuidle_driver_kobj {
struct cpuidle_driver *drv;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 02f177aeb16c..2fb0fdfc87df 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -391,7 +391,7 @@ config CRYPTO_DEV_ATMEL_SHA
config CRYPTO_DEV_CCP
bool "Support for AMD Cryptographic Coprocessor"
- depends on X86 && PCI
+ depends on (X86 && PCI) || ARM64
default n
help
The AMD Cryptographic Coprocessor provides hardware support
@@ -418,4 +418,22 @@ config CRYPTO_DEV_MXS_DCP
To compile this driver as a module, choose M here: the module
will be called mxs-dcp.
+source "drivers/crypto/qat/Kconfig"
+
+config CRYPTO_DEV_QCE
+ tristate "Qualcomm crypto engine accelerator"
+ depends on (ARCH_QCOM || COMPILE_TEST) && HAS_DMA && HAS_IOMEM
+ select CRYPTO_AES
+ select CRYPTO_DES
+ select CRYPTO_ECB
+ select CRYPTO_CBC
+ select CRYPTO_XTS
+ select CRYPTO_CTR
+ select CRYPTO_ALGAPI
+ select CRYPTO_BLKCIPHER
+ help
+ This driver supports Qualcomm crypto engine accelerator
+ hardware. To compile this driver as a module, choose M here. The
+ module will be called qcrypto.
+
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 482f090d16d0..3924f93d5774 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -23,3 +23,5 @@ obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
+obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 37f9cc98ba17..e4c6c58fbb03 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1292,7 +1292,7 @@ static struct platform_driver crypto4xx_driver = {
.of_match_table = crypto4xx_match,
},
.probe = crypto4xx_probe,
- .remove = crypto4xx_remove,
+ .remove = __exit_p(crypto4xx_remove),
};
module_platform_driver(crypto4xx_driver);
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 0618be06b9fb..9a4f69eaa5e0 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -1353,7 +1353,6 @@ static struct crypto_platform_data *atmel_sha_of_init(struct platform_device *pd
GFP_KERNEL);
if (!pdata->dma_slave) {
dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
- devm_kfree(&pdev->dev, pdata);
return ERR_PTR(-ENOMEM);
}
@@ -1375,7 +1374,8 @@ static int atmel_sha_probe(struct platform_device *pdev)
unsigned long sha_phys_size;
int err;
- sha_dd = kzalloc(sizeof(struct atmel_sha_dev), GFP_KERNEL);
+ sha_dd = devm_kzalloc(&pdev->dev, sizeof(struct atmel_sha_dev),
+ GFP_KERNEL);
if (sha_dd == NULL) {
dev_err(dev, "unable to alloc data struct.\n");
err = -ENOMEM;
@@ -1490,8 +1490,6 @@ clk_err:
free_irq(sha_dd->irq, sha_dd);
res_err:
tasklet_kill(&sha_dd->done_task);
- kfree(sha_dd);
- sha_dd = NULL;
sha_dd_err:
dev_err(dev, "initialization failed.\n");
@@ -1523,9 +1521,6 @@ static int atmel_sha_remove(struct platform_device *pdev)
if (sha_dd->irq >= 0)
free_irq(sha_dd->irq, sha_dd);
- kfree(sha_dd);
- sha_dd = NULL;
-
return 0;
}
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index 6cde5b530c69..d3a9041938ea 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -1337,7 +1337,6 @@ static struct crypto_platform_data *atmel_tdes_of_init(struct platform_device *p
GFP_KERNEL);
if (!pdata->dma_slave) {
dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
- devm_kfree(&pdev->dev, pdata);
return ERR_PTR(-ENOMEM);
}
@@ -1359,7 +1358,7 @@ static int atmel_tdes_probe(struct platform_device *pdev)
unsigned long tdes_phys_size;
int err;
- tdes_dd = kzalloc(sizeof(struct atmel_tdes_dev), GFP_KERNEL);
+ tdes_dd = devm_kmalloc(&pdev->dev, sizeof(*tdes_dd), GFP_KERNEL);
if (tdes_dd == NULL) {
dev_err(dev, "unable to alloc data struct.\n");
err = -ENOMEM;
@@ -1483,8 +1482,6 @@ tdes_irq_err:
res_err:
tasklet_kill(&tdes_dd->done_task);
tasklet_kill(&tdes_dd->queue_task);
- kfree(tdes_dd);
- tdes_dd = NULL;
tdes_dd_err:
dev_err(dev, "initialization failed.\n");
@@ -1519,9 +1516,6 @@ static int atmel_tdes_remove(struct platform_device *pdev)
if (tdes_dd->irq >= 0)
free_irq(tdes_dd->irq, tdes_dd);
- kfree(tdes_dd);
- tdes_dd = NULL;
-
return 0;
}
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index c09ce1f040d3..a80ea853701d 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -97,6 +97,13 @@ static inline void append_dec_op1(u32 *desc, u32 type)
{
u32 *jump_cmd, *uncond_jump_cmd;
+ /* DK bit is valid only for AES */
+ if ((type & OP_ALG_ALGSEL_MASK) != OP_ALG_ALGSEL_AES) {
+ append_operation(desc, type | OP_ALG_AS_INITFINAL |
+ OP_ALG_DECRYPT);
+ return;
+ }
+
jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
append_operation(desc, type | OP_ALG_AS_INITFINAL |
OP_ALG_DECRYPT);
@@ -786,7 +793,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
desc_bytes(desc),
DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
dev_err(jrdev, "unable to map shared descriptor\n");
return -ENOMEM;
}
@@ -1313,8 +1320,13 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
DMA_FROM_DEVICE, dst_chained);
}
- /* Check if data are contiguous */
iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Check if data are contiguous */
if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
iv_dma || src_nents || iv_dma + ivsize !=
sg_dma_address(req->src)) {
@@ -1345,8 +1357,6 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
desc_bytes;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
*all_contig_ptr = all_contig;
sec4_sg_index = 0;
@@ -1369,6 +1379,12 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
sg_to_sec4_sg_last(req->dst, dst_nents,
edesc->sec4_sg + sec4_sg_index, 0);
}
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return ERR_PTR(-ENOMEM);
+ }
return edesc;
}
@@ -1494,8 +1510,13 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
DMA_FROM_DEVICE, dst_chained);
}
- /* Check if data are contiguous */
iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Check if data are contiguous */
if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
iv_dma || src_nents || iv_dma + ivsize != sg_dma_address(req->src))
contig &= ~GIV_SRC_CONTIG;
@@ -1534,8 +1555,6 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
desc_bytes;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
*contig_ptr = contig;
sec4_sg_index = 0;
@@ -1559,6 +1578,12 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
sg_to_sec4_sg_last(req->dst, dst_nents,
edesc->sec4_sg + sec4_sg_index, 0);
}
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return ERR_PTR(-ENOMEM);
+ }
return edesc;
}
@@ -1650,11 +1675,16 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
DMA_FROM_DEVICE, dst_chained);
}
+ iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, iv_dma)) {
+ dev_err(jrdev, "unable to map IV\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
/*
* Check if iv can be contiguous with source and destination.
* If so, include it. If not, create scatterlist.
*/
- iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
if (!src_nents && iv_dma + ivsize == sg_dma_address(req->src))
iv_contig = true;
else
@@ -1693,6 +1723,11 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
edesc->iv_dma = iv_dma;
#ifdef DEBUG
@@ -2441,8 +2476,37 @@ static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
static int __init caam_algapi_init(void)
{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ void *priv;
int i = 0, err = 0;
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev) {
+ of_node_put(dev_node);
+ return -ENODEV;
+ }
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ of_node_put(dev_node);
+
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
+
INIT_LIST_HEAD(&alg_list);
/* register crypto algorithms the device supports */
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 0d9284ef96a8..b464d03ebf40 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -137,13 +137,20 @@ struct caam_hash_state {
/* Common job descriptor seq in/out ptr routines */
/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
-static inline void map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
- struct caam_hash_state *state,
- int ctx_len)
+static inline int map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
+ struct caam_hash_state *state,
+ int ctx_len)
{
state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
ctx_len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, state->ctx_dma)) {
+ dev_err(jrdev, "unable to map ctx\n");
+ return -ENOMEM;
+ }
+
append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
+
+ return 0;
}
/* Map req->result, and append seq_out_ptr command that points to it */
@@ -201,14 +208,19 @@ try_buf_map_to_sec4_sg(struct device *jrdev, struct sec4_sg_entry *sec4_sg,
}
/* Map state->caam_ctx, and add it to link table */
-static inline void ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
- struct caam_hash_state *state,
- int ctx_len,
- struct sec4_sg_entry *sec4_sg,
- u32 flag)
+static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
+ struct caam_hash_state *state, int ctx_len,
+ struct sec4_sg_entry *sec4_sg, u32 flag)
{
state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
+ if (dma_mapping_error(jrdev, state->ctx_dma)) {
+ dev_err(jrdev, "unable to map ctx\n");
+ return -ENOMEM;
+ }
+
dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
+
+ return 0;
}
/* Common shared descriptor commands */
@@ -487,11 +499,11 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
digestsize, 1);
#endif
}
- *keylen = digestsize;
-
dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
+ *keylen = digestsize;
+
kfree(desc);
return ret;
@@ -706,7 +718,7 @@ static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
- ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_TO_DEVICE);
kfree(edesc);
#ifdef DEBUG
@@ -741,7 +753,7 @@ static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
if (err)
caam_jr_strstatus(jrdev, err);
- ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE);
kfree(edesc);
#ifdef DEBUG
@@ -808,12 +820,11 @@ static int ahash_update_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes,
- DMA_TO_DEVICE);
- ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
- edesc->sec4_sg, DMA_BIDIRECTIONAL);
+ ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+ edesc->sec4_sg, DMA_BIDIRECTIONAL);
+ if (ret)
+ return ret;
state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
edesc->sec4_sg + 1,
@@ -839,6 +850,14 @@ static int ahash_update_ctx(struct ahash_request *req)
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
HDR_REVERSE);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
+
append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
to_hash, LDST_SGF);
@@ -911,23 +930,34 @@ static int ahash_final_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
edesc->src_nents = 0;
- ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
- DMA_TO_DEVICE);
+ ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+ edesc->sec4_sg, DMA_TO_DEVICE);
+ if (ret)
+ return ret;
state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
buf, state->buf_dma, buflen,
last_buflen);
(edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
+
append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
LDST_SGF);
edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
digestsize);
+ if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -989,11 +1019,11 @@ static int ahash_finup_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
- ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
- DMA_TO_DEVICE);
+ ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+ edesc->sec4_sg, DMA_TO_DEVICE);
+ if (ret)
+ return ret;
state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
buf, state->buf_dma, buflen,
@@ -1002,11 +1032,22 @@ static int ahash_finup_ctx(struct ahash_request *req)
src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg +
sec4_sg_src_index, chained);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
+
append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
buflen + req->nbytes, LDST_SGF);
edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
digestsize);
+ if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1056,8 +1097,7 @@ static int ahash_digest(struct ahash_request *req)
}
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->src_nents = src_nents;
edesc->chained = chained;
@@ -1067,6 +1107,12 @@ static int ahash_digest(struct ahash_request *req)
if (src_nents) {
sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
src_dma = edesc->sec4_sg_dma;
options = LDST_SGF;
} else {
@@ -1077,6 +1123,10 @@ static int ahash_digest(struct ahash_request *req)
edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
digestsize);
+ if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1125,11 +1175,19 @@ static int ahash_final_no_ctx(struct ahash_request *req)
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, state->buf_dma)) {
+ dev_err(jrdev, "unable to map src\n");
+ return -ENOMEM;
+ }
append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
digestsize);
+ if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
edesc->src_nents = 0;
#ifdef DEBUG
@@ -1197,9 +1255,7 @@ static int ahash_update_no_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes,
- DMA_TO_DEVICE);
+ edesc->dst_dma = 0;
state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg,
buf, *buflen);
@@ -1216,9 +1272,19 @@ static int ahash_update_no_ctx(struct ahash_request *req)
init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
HDR_REVERSE);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
+
append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
- map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+ ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+ if (ret)
+ return ret;
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1297,8 +1363,6 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes, DMA_TO_DEVICE);
state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, buf,
state->buf_dma, buflen,
@@ -1307,11 +1371,22 @@ static int ahash_finup_no_ctx(struct ahash_request *req)
src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1,
chained);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
+
append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen +
req->nbytes, LDST_SGF);
edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
digestsize);
+ if (dma_mapping_error(jrdev, edesc->dst_dma)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1380,13 +1455,19 @@ static int ahash_update_first(struct ahash_request *req)
edesc->sec4_sg_bytes = sec4_sg_bytes;
edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
DESC_JOB_IO_LEN;
- edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
- sec4_sg_bytes,
- DMA_TO_DEVICE);
+ edesc->dst_dma = 0;
if (src_nents) {
sg_to_sec4_sg_last(req->src, src_nents,
edesc->sec4_sg, 0);
+ edesc->sec4_sg_dma = dma_map_single(jrdev,
+ edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
+ dev_err(jrdev, "unable to map S/G table\n");
+ return -ENOMEM;
+ }
src_dma = edesc->sec4_sg_dma;
options = LDST_SGF;
} else {
@@ -1404,7 +1485,9 @@ static int ahash_update_first(struct ahash_request *req)
append_seq_in_ptr(desc, src_dma, to_hash, options);
- map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+ ret = map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+ if (ret)
+ return ret;
#ifdef DEBUG
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
@@ -1453,6 +1536,7 @@ static int ahash_init(struct ahash_request *req)
state->final = ahash_final_no_ctx;
state->current_buf = 0;
+ state->buf_dma = 0;
return 0;
}
@@ -1787,8 +1871,36 @@ caam_hash_alloc(struct caam_hash_template *template,
static int __init caam_algapi_hash_init(void)
{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ void *priv;
int i = 0, err = 0;
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev) {
+ of_node_put(dev_node);
+ return -ENODEV;
+ }
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ of_node_put(dev_node);
+
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
INIT_LIST_HEAD(&hash_list);
/* register crypto algorithms the device supports */
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 8c07d3153f12..ae31e555793c 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -185,7 +185,7 @@ static int caam_read(struct hwrng *rng, void *data, size_t max, bool wait)
max - copied_idx, false);
}
-static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx)
+static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
{
struct device *jrdev = ctx->jrdev;
u32 *desc = ctx->sh_desc;
@@ -203,13 +203,18 @@ static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx)
ctx->sh_desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
#ifdef DEBUG
print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
desc, desc_bytes(desc), 1);
#endif
+ return 0;
}
-static inline void rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
+static inline int rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
{
struct device *jrdev = ctx->jrdev;
struct buf_data *bd = &ctx->bufs[buf_id];
@@ -220,12 +225,17 @@ static inline void rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
HDR_REVERSE);
bd->addr = dma_map_single(jrdev, bd->buf, RN_BUF_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, bd->addr)) {
+ dev_err(jrdev, "unable to map dst\n");
+ return -ENOMEM;
+ }
append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0);
#ifdef DEBUG
print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
desc, desc_bytes(desc), 1);
#endif
+ return 0;
}
static void caam_cleanup(struct hwrng *rng)
@@ -242,24 +252,44 @@ static void caam_cleanup(struct hwrng *rng)
rng_unmap_ctx(rng_ctx);
}
-static void caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
+static int caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
{
struct buf_data *bd = &ctx->bufs[buf_id];
+ int err;
+
+ err = rng_create_job_desc(ctx, buf_id);
+ if (err)
+ return err;
- rng_create_job_desc(ctx, buf_id);
atomic_set(&bd->empty, BUF_EMPTY);
submit_job(ctx, buf_id == ctx->current_buf);
wait_for_completion(&bd->filled);
+
+ return 0;
}
-static void caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev)
+static int caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev)
{
+ int err;
+
ctx->jrdev = jrdev;
- rng_create_sh_desc(ctx);
+
+ err = rng_create_sh_desc(ctx);
+ if (err)
+ return err;
+
ctx->current_buf = 0;
ctx->cur_buf_idx = 0;
- caam_init_buf(ctx, 0);
- caam_init_buf(ctx, 1);
+
+ err = caam_init_buf(ctx, 0);
+ if (err)
+ return err;
+
+ err = caam_init_buf(ctx, 1);
+ if (err)
+ return err;
+
+ return 0;
}
static struct hwrng caam_rng = {
@@ -278,6 +308,35 @@ static void __exit caam_rng_exit(void)
static int __init caam_rng_init(void)
{
struct device *dev;
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ void *priv;
+ int err;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev) {
+ of_node_put(dev_node);
+ return -ENODEV;
+ }
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ of_node_put(dev_node);
+
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
dev = caam_jr_alloc();
if (IS_ERR(dev)) {
@@ -287,7 +346,9 @@ static int __init caam_rng_init(void)
rng_ctx = kmalloc(sizeof(struct caam_rng_ctx), GFP_DMA);
if (!rng_ctx)
return -ENOMEM;
- caam_init_rng(rng_ctx, dev);
+ err = caam_init_rng(rng_ctx, dev);
+ if (err)
+ return err;
dev_info(dev, "registering rng-caam\n");
return hwrng_register(&caam_rng);
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 1c38f86bf63a..3cade79ea41e 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -5,6 +5,7 @@
* Copyright 2008-2012 Freescale Semiconductor, Inc.
*/
+#include <linux/device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@@ -87,6 +88,17 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
/* Set the bit to request direct access to DECO0 */
topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+
+ if (ctrlpriv->virt_en == 1) {
+ setbits32(&topregs->ctrl.deco_rsr, DECORSR_JR0);
+
+ while (!(rd_reg32(&topregs->ctrl.deco_rsr) & DECORSR_VALID) &&
+ --timeout)
+ cpu_relax();
+
+ timeout = 100000;
+ }
+
setbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
while (!(rd_reg32(&topregs->ctrl.deco_rq) & DECORR_DEN0) &&
@@ -129,6 +141,9 @@ static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
*status = rd_reg32(&topregs->deco.op_status_hi) &
DECO_OP_STATUS_HI_ERR_MASK;
+ if (ctrlpriv->virt_en == 1)
+ clrbits32(&topregs->ctrl.deco_rsr, DECORSR_JR0);
+
/* Mark the DECO as free */
clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
@@ -295,9 +310,6 @@ static int caam_remove(struct platform_device *pdev)
/* Unmap controller region */
iounmap(&topregs->ctrl);
- kfree(ctrlpriv->jrpdev);
- kfree(ctrlpriv);
-
return ret;
}
@@ -380,9 +392,11 @@ static int caam_probe(struct platform_device *pdev)
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
#endif
- u64 cha_vid;
+ u32 scfgr, comp_params;
+ u32 cha_vid_ls;
- ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL);
+ ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(struct caam_drv_private),
+ GFP_KERNEL);
if (!ctrlpriv)
return -ENOMEM;
@@ -413,13 +427,40 @@ static int caam_probe(struct platform_device *pdev)
setbits32(&topregs->ctrl.mcr, MCFGR_WDENABLE |
(sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+ /*
+ * Read the Compile Time paramters and SCFGR to determine
+ * if Virtualization is enabled for this platform
+ */
+ comp_params = rd_reg32(&topregs->ctrl.perfmon.comp_parms_ms);
+ scfgr = rd_reg32(&topregs->ctrl.scfgr);
+
+ ctrlpriv->virt_en = 0;
+ if (comp_params & CTPR_MS_VIRT_EN_INCL) {
+ /* VIRT_EN_INCL = 1 & VIRT_EN_POR = 1 or
+ * VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SCFGR_VIRT_EN = 1
+ */
+ if ((comp_params & CTPR_MS_VIRT_EN_POR) ||
+ (!(comp_params & CTPR_MS_VIRT_EN_POR) &&
+ (scfgr & SCFGR_VIRT_EN)))
+ ctrlpriv->virt_en = 1;
+ } else {
+ /* VIRT_EN_INCL = 0 && VIRT_EN_POR_VALUE = 1 */
+ if (comp_params & CTPR_MS_VIRT_EN_POR)
+ ctrlpriv->virt_en = 1;
+ }
+
+ if (ctrlpriv->virt_en == 1)
+ setbits32(&topregs->ctrl.jrstart, JRSTART_JR0_START |
+ JRSTART_JR1_START | JRSTART_JR2_START |
+ JRSTART_JR3_START);
+
if (sizeof(dma_addr_t) == sizeof(u64))
if (of_device_is_compatible(nprop, "fsl,sec-v5.0"))
- dma_set_mask(dev, DMA_BIT_MASK(40));
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
else
- dma_set_mask(dev, DMA_BIT_MASK(36));
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
else
- dma_set_mask(dev, DMA_BIT_MASK(32));
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
/*
* Detect and enable JobRs
@@ -432,8 +473,9 @@ static int caam_probe(struct platform_device *pdev)
of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
rspec++;
- ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
- GFP_KERNEL);
+ ctrlpriv->jrpdev = devm_kzalloc(&pdev->dev,
+ sizeof(struct platform_device *) * rspec,
+ GFP_KERNEL);
if (ctrlpriv->jrpdev == NULL) {
iounmap(&topregs->ctrl);
return -ENOMEM;
@@ -456,8 +498,9 @@ static int caam_probe(struct platform_device *pdev)
}
/* Check to see if QI present. If so, enable */
- ctrlpriv->qi_present = !!(rd_reg64(&topregs->ctrl.perfmon.comp_parms) &
- CTPR_QI_MASK);
+ ctrlpriv->qi_present =
+ !!(rd_reg32(&topregs->ctrl.perfmon.comp_parms_ms) &
+ CTPR_MS_QI_MASK);
if (ctrlpriv->qi_present) {
ctrlpriv->qi = (struct caam_queue_if __force *)&topregs->qi;
/* This is all that's required to physically enable QI */
@@ -471,13 +514,13 @@ static int caam_probe(struct platform_device *pdev)
return -ENOMEM;
}
- cha_vid = rd_reg64(&topregs->ctrl.perfmon.cha_id);
+ cha_vid_ls = rd_reg32(&topregs->ctrl.perfmon.cha_id_ls);
/*
* If SEC has RNG version >= 4 and RNG state handle has not been
* already instantiated, do RNG instantiation
*/
- if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
+ if ((cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 4) {
ctrlpriv->rng4_sh_init =
rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
/*
@@ -531,7 +574,8 @@ static int caam_probe(struct platform_device *pdev)
/* NOTE: RTIC detection ought to go here, around Si time */
- caam_id = rd_reg64(&topregs->ctrl.perfmon.caam_id);
+ caam_id = (u64)rd_reg32(&topregs->ctrl.perfmon.caam_id_ms) << 32 |
+ (u64)rd_reg32(&topregs->ctrl.perfmon.caam_id_ls);
/* Report "alive" for developer to see */
dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
@@ -547,7 +591,7 @@ static int caam_probe(struct platform_device *pdev)
*/
perfmon = (struct caam_perfmon __force *)&ctrl->perfmon;
- ctrlpriv->dfs_root = debugfs_create_dir("caam", NULL);
+ ctrlpriv->dfs_root = debugfs_create_dir(dev_name(dev), NULL);
ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root);
/* Controller-level - performance monitor counters */
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 7e4500f18df6..d397ff9d56fd 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -321,7 +321,6 @@ struct sec4_sg_entry {
/* Continue - Not the last FIFO store to come */
#define FIFOST_CONT_SHIFT 23
#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
/*
* Extended Length - use 32-bit extended length that
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 6d85fcc5bd0a..97363db4e56e 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -82,6 +82,7 @@ struct caam_drv_private {
u8 total_jobrs; /* Total Job Rings in device */
u8 qi_present; /* Nonzero if QI present in device */
int secvio_irq; /* Security violation interrupt number */
+ int virt_en; /* Virtualization enabled in CAAM */
#define RNG4_MAX_HANDLES 2
/* RNG4 block */
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index b512a4ba7569..4d18e27ffa9e 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -476,11 +476,11 @@ static int caam_jr_probe(struct platform_device *pdev)
if (sizeof(dma_addr_t) == sizeof(u64))
if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring"))
- dma_set_mask(jrdev, DMA_BIT_MASK(40));
+ dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(40));
else
- dma_set_mask(jrdev, DMA_BIT_MASK(36));
+ dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(36));
else
- dma_set_mask(jrdev, DMA_BIT_MASK(32));
+ dma_set_mask_and_coherent(jrdev, DMA_BIT_MASK(32));
/* Identify the interrupt */
jrpriv->irq = irq_of_parse_and_map(nprop, 0);
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index cbde8b95a6f8..f48e344ffc39 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -84,6 +84,7 @@
#endif
#ifndef CONFIG_64BIT
+#ifdef __BIG_ENDIAN
static inline void wr_reg64(u64 __iomem *reg, u64 data)
{
wr_reg32((u32 __iomem *)reg, (data & 0xffffffff00000000ull) >> 32);
@@ -95,6 +96,21 @@ static inline u64 rd_reg64(u64 __iomem *reg)
return (((u64)rd_reg32((u32 __iomem *)reg)) << 32) |
((u64)rd_reg32((u32 __iomem *)reg + 1));
}
+#else
+#ifdef __LITTLE_ENDIAN
+static inline void wr_reg64(u64 __iomem *reg, u64 data)
+{
+ wr_reg32((u32 __iomem *)reg + 1, (data & 0xffffffff00000000ull) >> 32);
+ wr_reg32((u32 __iomem *)reg, data & 0x00000000ffffffffull);
+}
+
+static inline u64 rd_reg64(u64 __iomem *reg)
+{
+ return (((u64)rd_reg32((u32 __iomem *)reg + 1)) << 32) |
+ ((u64)rd_reg32((u32 __iomem *)reg));
+}
+#endif
+#endif
#endif
/*
@@ -114,45 +130,45 @@ struct jr_outentry {
*/
/* Number of DECOs */
-#define CHA_NUM_DECONUM_SHIFT 56
-#define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT)
+#define CHA_NUM_MS_DECONUM_SHIFT 24
+#define CHA_NUM_MS_DECONUM_MASK (0xfull << CHA_NUM_MS_DECONUM_SHIFT)
/* CHA Version IDs */
-#define CHA_ID_AES_SHIFT 0
-#define CHA_ID_AES_MASK (0xfull << CHA_ID_AES_SHIFT)
+#define CHA_ID_LS_AES_SHIFT 0
+#define CHA_ID_LS_AES_MASK (0xfull << CHA_ID_LS_AES_SHIFT)
-#define CHA_ID_DES_SHIFT 4
-#define CHA_ID_DES_MASK (0xfull << CHA_ID_DES_SHIFT)
+#define CHA_ID_LS_DES_SHIFT 4
+#define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT)
-#define CHA_ID_ARC4_SHIFT 8
-#define CHA_ID_ARC4_MASK (0xfull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_LS_ARC4_SHIFT 8
+#define CHA_ID_LS_ARC4_MASK (0xfull << CHA_ID_LS_ARC4_SHIFT)
-#define CHA_ID_MD_SHIFT 12
-#define CHA_ID_MD_MASK (0xfull << CHA_ID_MD_SHIFT)
+#define CHA_ID_LS_MD_SHIFT 12
+#define CHA_ID_LS_MD_MASK (0xfull << CHA_ID_LS_MD_SHIFT)
-#define CHA_ID_RNG_SHIFT 16
-#define CHA_ID_RNG_MASK (0xfull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_LS_RNG_SHIFT 16
+#define CHA_ID_LS_RNG_MASK (0xfull << CHA_ID_LS_RNG_SHIFT)
-#define CHA_ID_SNW8_SHIFT 20
-#define CHA_ID_SNW8_MASK (0xfull << CHA_ID_SNW8_SHIFT)
+#define CHA_ID_LS_SNW8_SHIFT 20
+#define CHA_ID_LS_SNW8_MASK (0xfull << CHA_ID_LS_SNW8_SHIFT)
-#define CHA_ID_KAS_SHIFT 24
-#define CHA_ID_KAS_MASK (0xfull << CHA_ID_KAS_SHIFT)
+#define CHA_ID_LS_KAS_SHIFT 24
+#define CHA_ID_LS_KAS_MASK (0xfull << CHA_ID_LS_KAS_SHIFT)
-#define CHA_ID_PK_SHIFT 28
-#define CHA_ID_PK_MASK (0xfull << CHA_ID_PK_SHIFT)
+#define CHA_ID_LS_PK_SHIFT 28
+#define CHA_ID_LS_PK_MASK (0xfull << CHA_ID_LS_PK_SHIFT)
-#define CHA_ID_CRC_SHIFT 32
-#define CHA_ID_CRC_MASK (0xfull << CHA_ID_CRC_SHIFT)
+#define CHA_ID_MS_CRC_SHIFT 0
+#define CHA_ID_MS_CRC_MASK (0xfull << CHA_ID_MS_CRC_SHIFT)
-#define CHA_ID_SNW9_SHIFT 36
-#define CHA_ID_SNW9_MASK (0xfull << CHA_ID_SNW9_SHIFT)
+#define CHA_ID_MS_SNW9_SHIFT 4
+#define CHA_ID_MS_SNW9_MASK (0xfull << CHA_ID_MS_SNW9_SHIFT)
-#define CHA_ID_DECO_SHIFT 56
-#define CHA_ID_DECO_MASK (0xfull << CHA_ID_DECO_SHIFT)
+#define CHA_ID_MS_DECO_SHIFT 24
+#define CHA_ID_MS_DECO_MASK (0xfull << CHA_ID_MS_DECO_SHIFT)
-#define CHA_ID_JR_SHIFT 60
-#define CHA_ID_JR_MASK (0xfull << CHA_ID_JR_SHIFT)
+#define CHA_ID_MS_JR_SHIFT 28
+#define CHA_ID_MS_JR_MASK (0xfull << CHA_ID_MS_JR_SHIFT)
struct sec_vid {
u16 ip_id;
@@ -172,10 +188,14 @@ struct caam_perfmon {
u64 rsvd[13];
/* CAAM Hardware Instantiation Parameters fa0-fbf */
- u64 cha_rev; /* CRNR - CHA Revision Number */
-#define CTPR_QI_SHIFT 57
-#define CTPR_QI_MASK (0x1ull << CTPR_QI_SHIFT)
- u64 comp_parms; /* CTPR - Compile Parameters Register */
+ u32 cha_rev_ms; /* CRNR - CHA Rev No. Most significant half*/
+ u32 cha_rev_ls; /* CRNR - CHA Rev No. Least significant half*/
+#define CTPR_MS_QI_SHIFT 25
+#define CTPR_MS_QI_MASK (0x1ull << CTPR_MS_QI_SHIFT)
+#define CTPR_MS_VIRT_EN_INCL 0x00000001
+#define CTPR_MS_VIRT_EN_POR 0x00000002
+ u32 comp_parms_ms; /* CTPR - Compile Parameters Register */
+ u32 comp_parms_ls; /* CTPR - Compile Parameters Register */
u64 rsvd1[2];
/* CAAM Global Status fc0-fdf */
@@ -189,9 +209,12 @@ struct caam_perfmon {
/* Component Instantiation Parameters fe0-fff */
u32 rtic_id; /* RVID - RTIC Version ID */
u32 ccb_id; /* CCBVID - CCB Version ID */
- u64 cha_id; /* CHAVID - CHA Version ID */
- u64 cha_num; /* CHANUM - CHA Number */
- u64 caam_id; /* CAAMVID - CAAM Version ID */
+ u32 cha_id_ms; /* CHAVID - CHA Version ID Most Significant*/
+ u32 cha_id_ls; /* CHAVID - CHA Version ID Least Significant*/
+ u32 cha_num_ms; /* CHANUM - CHA Number Most Significant */
+ u32 cha_num_ls; /* CHANUM - CHA Number Least Significant*/
+ u32 caam_id_ms; /* CAAMVID - CAAM Version ID MS */
+ u32 caam_id_ls; /* CAAMVID - CAAM Version ID LS */
};
/* LIODN programming for DMA configuration */
@@ -304,9 +327,12 @@ struct caam_ctrl {
/* Bus Access Configuration Section 010-11f */
/* Read/Writable */
struct masterid jr_mid[4]; /* JRxLIODNR - JobR LIODN setup */
- u32 rsvd3[12];
+ u32 rsvd3[11];
+ u32 jrstart; /* JRSTART - Job Ring Start Register */
struct masterid rtic_mid[4]; /* RTICxLIODNR - RTIC LIODN setup */
- u32 rsvd4[7];
+ u32 rsvd4[5];
+ u32 deco_rsr; /* DECORSR - Deco Request Source */
+ u32 rsvd11;
u32 deco_rq; /* DECORR - DECO Request */
struct partid deco_mid[5]; /* DECOxLIODNR - 1 per DECO */
u32 rsvd5[22];
@@ -347,7 +373,10 @@ struct caam_ctrl {
#define MCFGR_DMA_RESET 0x10000000
#define MCFGR_LONG_PTR 0x00010000 /* Use >32-bit desc addressing */
#define SCFGR_RDBENABLE 0x00000400
+#define SCFGR_VIRT_EN 0x00008000
#define DECORR_RQD0ENABLE 0x00000001 /* Enable DECO0 for direct access */
+#define DECORSR_JR0 0x00000001 /* JR to supply TZ, SDID, ICID */
+#define DECORSR_VALID 0x80000000
#define DECORR_DEN0 0x00010000 /* DECO0 available for access*/
/* AXI read cache control */
@@ -365,6 +394,12 @@ struct caam_ctrl {
#define MCFGR_AXIPRI 0x00000008 /* Assert AXI priority sideband */
#define MCFGR_BURST_64 0x00000001 /* Max burst size */
+/* JRSTART register offsets */
+#define JRSTART_JR0_START 0x00000001 /* Start Job ring 0 */
+#define JRSTART_JR1_START 0x00000002 /* Start Job ring 1 */
+#define JRSTART_JR2_START 0x00000004 /* Start Job ring 2 */
+#define JRSTART_JR3_START 0x00000008 /* Start Job ring 3 */
+
/*
* caam_job_ring - direct job ring setup
* 1-4 possible per instantiation, base + 1000/2000/3000/4000
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index d3505a018720..7f592d8d07bb 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -1,6 +1,11 @@
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
ccp-objs := ccp-dev.o ccp-ops.o
+ifdef CONFIG_X86
ccp-objs += ccp-pci.o
+endif
+ifdef CONFIG_ARM64
+ccp-objs += ccp-platform.o
+endif
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index 2c7816149b01..a7d110652a74 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -20,7 +20,9 @@
#include <linux/delay.h>
#include <linux/hw_random.h>
#include <linux/cpu.h>
+#ifdef CONFIG_X86
#include <asm/cpu_device_id.h>
+#endif
#include <linux/ccp.h>
#include "ccp-dev.h"
@@ -360,6 +362,12 @@ int ccp_init(struct ccp_device *ccp)
/* Build queue interrupt mask (two interrupts per queue) */
qim |= cmd_q->int_ok | cmd_q->int_err;
+#ifdef CONFIG_ARM64
+ /* For arm64 set the recommended queue cache settings */
+ iowrite32(ccp->axcache, ccp->io_regs + CMD_Q_CACHE_BASE +
+ (CMD_Q_CACHE_INC * i));
+#endif
+
dev_dbg(dev, "queue #%u available\n", i);
}
if (ccp->cmd_q_count == 0) {
@@ -558,12 +566,15 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
}
#endif
+#ifdef CONFIG_X86
static const struct x86_cpu_id ccp_support[] = {
{ X86_VENDOR_AMD, 22, },
};
+#endif
static int __init ccp_mod_init(void)
{
+#ifdef CONFIG_X86
struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
int ret;
@@ -589,12 +600,30 @@ static int __init ccp_mod_init(void)
break;
}
+#endif
+
+#ifdef CONFIG_ARM64
+ int ret;
+
+ ret = ccp_platform_init();
+ if (ret)
+ return ret;
+
+ /* Don't leave the driver loaded if init failed */
+ if (!ccp_get_device()) {
+ ccp_platform_exit();
+ return -ENODEV;
+ }
+
+ return 0;
+#endif
return -ENODEV;
}
static void __exit ccp_mod_exit(void)
{
+#ifdef CONFIG_X86
struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
switch (cpuinfo->x86) {
@@ -602,6 +631,11 @@ static void __exit ccp_mod_exit(void)
ccp_pci_exit();
break;
}
+#endif
+
+#ifdef CONFIG_ARM64
+ ccp_platform_exit();
+#endif
}
module_init(ccp_mod_init);
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index 7ec536e702ec..62ff35a6b9ec 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -23,8 +23,6 @@
#include <linux/hw_random.h>
-#define IO_OFFSET 0x20000
-
#define MAX_DMAPOOL_NAME_LEN 32
#define MAX_HW_QUEUES 5
@@ -32,6 +30,9 @@
#define TRNG_RETRIES 10
+#define CACHE_NONE 0x00
+#define CACHE_WB_NO_ALLOC 0xb7
+
/****** Register Mappings ******/
#define Q_MASK_REG 0x000
@@ -50,7 +51,7 @@
#define CMD_Q_INT_STATUS_BASE 0x214
#define CMD_Q_STATUS_INCR 0x20
-#define CMD_Q_CACHE 0x228
+#define CMD_Q_CACHE_BASE 0x228
#define CMD_Q_CACHE_INC 0x20
#define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f);
@@ -194,6 +195,7 @@ struct ccp_device {
void *dev_specific;
int (*get_irq)(struct ccp_device *ccp);
void (*free_irq)(struct ccp_device *ccp);
+ unsigned int irq;
/*
* I/O area used for device communication. The register mapping
@@ -254,12 +256,18 @@ struct ccp_device {
/* Suspend support */
unsigned int suspending;
wait_queue_head_t suspend_queue;
+
+ /* DMA caching attribute support */
+ unsigned int axcache;
};
int ccp_pci_init(void);
void ccp_pci_exit(void);
+int ccp_platform_init(void);
+void ccp_platform_exit(void);
+
struct ccp_device *ccp_alloc_struct(struct device *dev);
int ccp_init(struct ccp_device *ccp);
void ccp_destroy(struct ccp_device *ccp);
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
index 9ae006d69df4..8729364261d7 100644
--- a/drivers/crypto/ccp/ccp-ops.c
+++ b/drivers/crypto/ccp/ccp-ops.c
@@ -1606,7 +1606,7 @@ static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
goto e_ksb;
ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len, CCP_KSB_BYTES,
- true);
+ false);
ret = ccp_copy_to_ksb(cmd_q, &exp, op.jobid, op.ksb_key,
CCP_PASSTHRU_BYTESWAP_NOOP);
if (ret) {
@@ -1623,10 +1623,10 @@ static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
goto e_exp;
ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len, CCP_KSB_BYTES,
- true);
+ false);
src.address += o_len; /* Adjust the address for the copy operation */
ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len, CCP_KSB_BYTES,
- true);
+ false);
src.address -= o_len; /* Reset the address to original value */
/* Prepare the output area for the operation */
@@ -1841,20 +1841,20 @@ static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
/* Copy the ECC modulus */
ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
/* Copy the first operand */
ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1,
ecc->u.mm.operand_1_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) {
/* Copy the second operand */
ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2,
ecc->u.mm.operand_2_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
}
@@ -1960,17 +1960,17 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
/* Copy the ECC modulus */
ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
/* Copy the first point X and Y coordinate */
ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x,
ecc->u.pm.point_1.x_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y,
ecc->u.pm.point_1.y_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
/* Set the first point Z coordianate to 1 */
@@ -1981,11 +1981,11 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
/* Copy the second point X and Y coordinate */
ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x,
ecc->u.pm.point_2.x_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y,
ecc->u.pm.point_2.y_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
/* Set the second point Z coordianate to 1 */
@@ -1995,14 +1995,14 @@ static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
/* Copy the Domain "a" parameter */
ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a,
ecc->u.pm.domain_a_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) {
/* Copy the scalar value */
ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar,
ecc->u.pm.scalar_len,
- CCP_ECC_OPERAND_SIZE, true);
+ CCP_ECC_OPERAND_SIZE, false);
src.address += CCP_ECC_OPERAND_SIZE;
}
}
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 0d746236df5e..7f89c946adfe 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -12,8 +12,10 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/device.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
+#include <linux/dma-mapping.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -24,6 +26,8 @@
#include "ccp-dev.h"
#define IO_BAR 2
+#define IO_OFFSET 0x20000
+
#define MSIX_VECTORS 2
struct ccp_msix {
@@ -89,7 +93,8 @@ static int ccp_get_msi_irq(struct ccp_device *ccp)
if (ret)
return ret;
- ret = request_irq(pdev->irq, ccp_irq_handler, 0, "ccp", dev);
+ ccp->irq = pdev->irq;
+ ret = request_irq(ccp->irq, ccp_irq_handler, 0, "ccp", dev);
if (ret) {
dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
goto e_msi;
@@ -136,7 +141,7 @@ static void ccp_free_irqs(struct ccp_device *ccp)
dev);
pci_disable_msix(pdev);
} else {
- free_irq(pdev->irq, dev);
+ free_irq(ccp->irq, dev);
pci_disable_msi(pdev);
}
}
@@ -147,21 +152,12 @@ static int ccp_find_mmio_area(struct ccp_device *ccp)
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
resource_size_t io_len;
unsigned long io_flags;
- int bar;
io_flags = pci_resource_flags(pdev, IO_BAR);
io_len = pci_resource_len(pdev, IO_BAR);
if ((io_flags & IORESOURCE_MEM) && (io_len >= (IO_OFFSET + 0x800)))
return IO_BAR;
- for (bar = 0; bar < PCI_STD_RESOURCE_END; bar++) {
- io_flags = pci_resource_flags(pdev, bar);
- io_len = pci_resource_len(pdev, bar);
- if ((io_flags & IORESOURCE_MEM) &&
- (io_len >= (IO_OFFSET + 0x800)))
- return bar;
- }
-
return -EIO;
}
@@ -214,20 +210,13 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
ccp->io_regs = ccp->io_map + IO_OFFSET;
- ret = dma_set_mask(dev, DMA_BIT_MASK(48));
- if (ret == 0) {
- ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(48));
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+ if (ret) {
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) {
- dev_err(dev,
- "pci_set_consistent_dma_mask failed (%d)\n",
+ dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
ret);
- goto e_bar0;
- }
- } else {
- ret = dma_set_mask(dev, DMA_BIT_MASK(32));
- if (ret) {
- dev_err(dev, "pci_set_dma_mask failed (%d)\n", ret);
- goto e_bar0;
+ goto e_iomap;
}
}
@@ -235,13 +224,13 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = ccp_init(ccp);
if (ret)
- goto e_bar0;
+ goto e_iomap;
dev_notice(dev, "enabled\n");
return 0;
-e_bar0:
+e_iomap:
pci_iounmap(pdev, ccp->io_map);
e_device:
@@ -331,7 +320,7 @@ static int ccp_pci_resume(struct pci_dev *pdev)
}
#endif
-static DEFINE_PCI_DEVICE_TABLE(ccp_pci_table) = {
+static const struct pci_device_id ccp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1537), },
/* Last entry must be zero */
{ 0, }
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
new file mode 100644
index 000000000000..b0a2806908f1
--- /dev/null
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -0,0 +1,230 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ccp.h>
+#include <linux/of.h>
+
+#include "ccp-dev.h"
+
+
+static int ccp_get_irq(struct ccp_device *ccp)
+{
+ struct device *dev = ccp->dev;
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ int ret;
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+
+ ccp->irq = ret;
+ ret = request_irq(ccp->irq, ccp_irq_handler, 0, "ccp", dev);
+ if (ret) {
+ dev_notice(dev, "unable to allocate IRQ (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ccp_get_irqs(struct ccp_device *ccp)
+{
+ struct device *dev = ccp->dev;
+ int ret;
+
+ ret = ccp_get_irq(ccp);
+ if (!ret)
+ return 0;
+
+ /* Couldn't get an interrupt */
+ dev_notice(dev, "could not enable interrupts (%d)\n", ret);
+
+ return ret;
+}
+
+static void ccp_free_irqs(struct ccp_device *ccp)
+{
+ struct device *dev = ccp->dev;
+
+ free_irq(ccp->irq, dev);
+}
+
+static struct resource *ccp_find_mmio_area(struct ccp_device *ccp)
+{
+ struct device *dev = ccp->dev;
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ struct resource *ior;
+
+ ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (ior && (resource_size(ior) >= 0x800))
+ return ior;
+
+ return NULL;
+}
+
+static int ccp_platform_probe(struct platform_device *pdev)
+{
+ struct ccp_device *ccp;
+ struct device *dev = &pdev->dev;
+ struct resource *ior;
+ int ret;
+
+ ret = -ENOMEM;
+ ccp = ccp_alloc_struct(dev);
+ if (!ccp)
+ goto e_err;
+
+ ccp->dev_specific = NULL;
+ ccp->get_irq = ccp_get_irqs;
+ ccp->free_irq = ccp_free_irqs;
+
+ ior = ccp_find_mmio_area(ccp);
+ ccp->io_map = devm_ioremap_resource(dev, ior);
+ if (IS_ERR(ccp->io_map)) {
+ ret = PTR_ERR(ccp->io_map);
+ goto e_free;
+ }
+ ccp->io_regs = ccp->io_map;
+
+ if (!dev->dma_mask)
+ dev->dma_mask = &dev->coherent_dma_mask;
+ *(dev->dma_mask) = DMA_BIT_MASK(48);
+ dev->coherent_dma_mask = DMA_BIT_MASK(48);
+
+ if (of_property_read_bool(dev->of_node, "dma-coherent"))
+ ccp->axcache = CACHE_WB_NO_ALLOC;
+ else
+ ccp->axcache = CACHE_NONE;
+
+ dev_set_drvdata(dev, ccp);
+
+ ret = ccp_init(ccp);
+ if (ret)
+ goto e_free;
+
+ dev_notice(dev, "enabled\n");
+
+ return 0;
+
+e_free:
+ kfree(ccp);
+
+e_err:
+ dev_notice(dev, "initialization failed\n");
+ return ret;
+}
+
+static int ccp_platform_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+
+ ccp_destroy(ccp);
+
+ kfree(ccp);
+
+ dev_notice(dev, "disabled\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ccp_platform_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct device *dev = &pdev->dev;
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+ ccp->suspending = 1;
+
+ /* Wake all the queue kthreads to prepare for suspend */
+ for (i = 0; i < ccp->cmd_q_count; i++)
+ wake_up_process(ccp->cmd_q[i].kthread);
+
+ spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+ /* Wait for all queue kthreads to say they're done */
+ while (!ccp_queues_suspended(ccp))
+ wait_event_interruptible(ccp->suspend_queue,
+ ccp_queues_suspended(ccp));
+
+ return 0;
+}
+
+static int ccp_platform_resume(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+ ccp->suspending = 0;
+
+ /* Wake up all the kthreads */
+ for (i = 0; i < ccp->cmd_q_count; i++) {
+ ccp->cmd_q[i].suspended = 0;
+ wake_up_process(ccp->cmd_q[i].kthread);
+ }
+
+ spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+ return 0;
+}
+#endif
+
+static const struct of_device_id ccp_platform_ids[] = {
+ { .compatible = "amd,ccp-seattle-v1a" },
+ { },
+};
+
+static struct platform_driver ccp_platform_driver = {
+ .driver = {
+ .name = "AMD Cryptographic Coprocessor",
+ .owner = THIS_MODULE,
+ .of_match_table = ccp_platform_ids,
+ },
+ .probe = ccp_platform_probe,
+ .remove = ccp_platform_remove,
+#ifdef CONFIG_PM
+ .suspend = ccp_platform_suspend,
+ .resume = ccp_platform_resume,
+#endif
+};
+
+int ccp_platform_init(void)
+{
+ return platform_driver_register(&ccp_platform_driver);
+}
+
+void ccp_platform_exit(void)
+{
+ platform_driver_unregister(&ccp_platform_driver);
+}
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index 12fea3e22348..8d2a7728434d 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -2617,14 +2617,13 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
}
- dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma),
- &dev->desc_dma);
+ dev->desc_virt = pci_zalloc_consistent(pdev, sizeof(struct hifn_dma),
+ &dev->desc_dma);
if (!dev->desc_virt) {
dprintk("Failed to allocate descriptor rings.\n");
err = -ENOMEM;
goto err_out_unmap_bars;
}
- memset(dev->desc_virt, 0, sizeof(struct hifn_dma));
dev->pdev = pdev;
dev->irq = pdev->irq;
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c
index 502edf0a2933..061407d59520 100644
--- a/drivers/crypto/nx/nx-842.c
+++ b/drivers/crypto/nx/nx-842.c
@@ -936,28 +936,14 @@ static int nx842_OF_upd(struct property *new_prop)
goto error_out;
}
- /* Set ptr to new property if provided */
- if (new_prop) {
- /* Single property */
- if (!strncmp(new_prop->name, "status", new_prop->length)) {
- status = new_prop;
-
- } else if (!strncmp(new_prop->name, "ibm,max-sg-len",
- new_prop->length)) {
- maxsglen = new_prop;
-
- } else if (!strncmp(new_prop->name, "ibm,max-sync-cop",
- new_prop->length)) {
- maxsyncop = new_prop;
-
- } else {
- /*
- * Skip the update, the property being updated
- * has no impact.
- */
- goto out;
- }
- }
+ /*
+ * If this is a property update, there are only certain properties that
+ * we care about. Bail if it isn't in the below list
+ */
+ if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) ||
+ strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) ||
+ strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length)))
+ goto out;
/* Perform property updates */
ret = nx842_OF_upd_status(new_devdata, status);
@@ -1247,7 +1233,7 @@ static struct vio_device_id nx842_driver_ids[] = {
static struct vio_driver nx842_driver = {
.name = MODULE_NAME,
.probe = nx842_probe,
- .remove = nx842_remove,
+ .remove = __exit_p(nx842_remove),
.get_desired_dma = nx842_get_desired_dma,
.id_table = nx842_driver_ids,
};
diff --git a/drivers/crypto/qat/Kconfig b/drivers/crypto/qat/Kconfig
new file mode 100644
index 000000000000..49bede2a9f77
--- /dev/null
+++ b/drivers/crypto/qat/Kconfig
@@ -0,0 +1,23 @@
+config CRYPTO_DEV_QAT
+ tristate
+ select CRYPTO_AEAD
+ select CRYPTO_AUTHENC
+ select CRYPTO_ALGAPI
+ select CRYPTO_AES
+ select CRYPTO_CBC
+ select CRYPTO_SHA1
+ select CRYPTO_SHA256
+ select CRYPTO_SHA512
+ select FW_LOADER
+
+config CRYPTO_DEV_QAT_DH895xCC
+ tristate "Support for Intel(R) DH895xCC"
+ depends on X86 && PCI
+ default n
+ select CRYPTO_DEV_QAT
+ help
+ Support for Intel(R) DH895xcc with Intel(R) QuickAssist Technology
+ for accelerating crypto and compression workloads.
+
+ To compile this as a module, choose M here: the module
+ will be called qat_dh895xcc.
diff --git a/drivers/crypto/qat/Makefile b/drivers/crypto/qat/Makefile
new file mode 100644
index 000000000000..d11481be225e
--- /dev/null
+++ b/drivers/crypto/qat/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_QAT) += qat_common/
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc/
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
new file mode 100644
index 000000000000..e0424dc382fe
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -0,0 +1,14 @@
+obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
+intel_qat-objs := adf_cfg.o \
+ adf_ctl_drv.o \
+ adf_dev_mgr.o \
+ adf_init.o \
+ adf_accel_engine.o \
+ adf_aer.o \
+ adf_transport.o \
+ qat_crypto.o \
+ qat_algs.o \
+ qat_uclo.o \
+ qat_hal.o
+
+intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o
diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h
new file mode 100644
index 000000000000..9282381b03ce
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h
@@ -0,0 +1,205 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_ACCEL_DEVICES_H_
+#define ADF_ACCEL_DEVICES_H_
+#include <linux/module.h>
+#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/io.h>
+#include "adf_cfg_common.h"
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define ADF_DH895XCC_DEVICE_NAME "dh895xcc"
+#define ADF_DH895XCC_PCI_DEVICE_ID 0x435
+#define ADF_DH895XCC_PMISC_BAR 1
+#define ADF_DH895XCC_ETR_BAR 2
+#define ADF_PCI_MAX_BARS 3
+#define ADF_DEVICE_NAME_LENGTH 32
+#define ADF_ETR_MAX_RINGS_PER_BANK 16
+#define ADF_MAX_MSIX_VECTOR_NAME 16
+#define ADF_DEVICE_NAME_PREFIX "qat_"
+
+enum adf_accel_capabilities {
+ ADF_ACCEL_CAPABILITIES_NULL = 0,
+ ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = 1,
+ ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = 2,
+ ADF_ACCEL_CAPABILITIES_CIPHER = 4,
+ ADF_ACCEL_CAPABILITIES_AUTHENTICATION = 8,
+ ADF_ACCEL_CAPABILITIES_COMPRESSION = 32,
+ ADF_ACCEL_CAPABILITIES_LZS_COMPRESSION = 64,
+ ADF_ACCEL_CAPABILITIES_RANDOM_NUMBER = 128
+};
+
+struct adf_bar {
+ resource_size_t base_addr;
+ void __iomem *virt_addr;
+ resource_size_t size;
+} __packed;
+
+struct adf_accel_msix {
+ struct msix_entry *entries;
+ char **names;
+} __packed;
+
+struct adf_accel_pci {
+ struct pci_dev *pci_dev;
+ struct adf_accel_msix msix_entries;
+ struct adf_bar pci_bars[ADF_PCI_MAX_BARS];
+ uint8_t revid;
+ uint8_t sku;
+} __packed;
+
+enum dev_state {
+ DEV_DOWN = 0,
+ DEV_UP
+};
+
+enum dev_sku_info {
+ DEV_SKU_1 = 0,
+ DEV_SKU_2,
+ DEV_SKU_3,
+ DEV_SKU_4,
+ DEV_SKU_UNKNOWN,
+};
+
+static inline const char *get_sku_info(enum dev_sku_info info)
+{
+ switch (info) {
+ case DEV_SKU_1:
+ return "SKU1";
+ case DEV_SKU_2:
+ return "SKU2";
+ case DEV_SKU_3:
+ return "SKU3";
+ case DEV_SKU_4:
+ return "SKU4";
+ case DEV_SKU_UNKNOWN:
+ default:
+ break;
+ }
+ return "Unknown SKU";
+}
+
+struct adf_hw_device_class {
+ const char *name;
+ const enum adf_device_type type;
+ uint32_t instances;
+} __packed;
+
+struct adf_cfg_device_data;
+struct adf_accel_dev;
+struct adf_etr_data;
+struct adf_etr_ring_data;
+
+struct adf_hw_device_data {
+ struct adf_hw_device_class *dev_class;
+ uint32_t (*get_accel_mask)(uint32_t fuse);
+ uint32_t (*get_ae_mask)(uint32_t fuse);
+ uint32_t (*get_misc_bar_id)(struct adf_hw_device_data *self);
+ uint32_t (*get_etr_bar_id)(struct adf_hw_device_data *self);
+ uint32_t (*get_num_aes)(struct adf_hw_device_data *self);
+ uint32_t (*get_num_accels)(struct adf_hw_device_data *self);
+ enum dev_sku_info (*get_sku)(struct adf_hw_device_data *self);
+ void (*hw_arb_ring_enable)(struct adf_etr_ring_data *ring);
+ void (*hw_arb_ring_disable)(struct adf_etr_ring_data *ring);
+ int (*alloc_irq)(struct adf_accel_dev *accel_dev);
+ void (*free_irq)(struct adf_accel_dev *accel_dev);
+ void (*enable_error_correction)(struct adf_accel_dev *accel_dev);
+ const char *fw_name;
+ uint32_t pci_dev_id;
+ uint32_t fuses;
+ uint32_t accel_capabilities_mask;
+ uint16_t accel_mask;
+ uint16_t ae_mask;
+ uint16_t tx_rings_mask;
+ uint8_t tx_rx_gap;
+ uint8_t instance_id;
+ uint8_t num_banks;
+ uint8_t num_accel;
+ uint8_t num_logical_accel;
+ uint8_t num_engines;
+} __packed;
+
+/* CSR write macro */
+#define ADF_CSR_WR(csr_base, csr_offset, val) \
+ __raw_writel(val, csr_base + csr_offset)
+
+/* CSR read macro */
+#define ADF_CSR_RD(csr_base, csr_offset) __raw_readl(csr_base + csr_offset)
+
+#define GET_DEV(accel_dev) ((accel_dev)->accel_pci_dev.pci_dev->dev)
+#define GET_BARS(accel_dev) ((accel_dev)->accel_pci_dev.pci_bars)
+#define GET_HW_DATA(accel_dev) (accel_dev->hw_device)
+#define GET_MAX_BANKS(accel_dev) (GET_HW_DATA(accel_dev)->num_banks)
+#define GET_MAX_ACCELENGINES(accel_dev) (GET_HW_DATA(accel_dev)->num_engines)
+#define accel_to_pci_dev(accel_ptr) accel_ptr->accel_pci_dev.pci_dev
+
+struct adf_admin_comms;
+struct icp_qat_fw_loader_handle;
+struct adf_fw_loader_data {
+ struct icp_qat_fw_loader_handle *fw_loader;
+ const struct firmware *uof_fw;
+};
+
+struct adf_accel_dev {
+ struct adf_etr_data *transport;
+ struct adf_hw_device_data *hw_device;
+ struct adf_cfg_device_data *cfg;
+ struct adf_fw_loader_data *fw_loader;
+ struct adf_admin_comms *admin;
+ struct list_head crypto_list;
+ unsigned long status;
+ atomic_t ref_count;
+ struct dentry *debugfs_dir;
+ struct list_head list;
+ struct module *owner;
+ uint8_t accel_id;
+ uint8_t numa_node;
+ struct adf_accel_pci accel_pci_dev;
+} __packed;
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_accel_engine.c b/drivers/crypto/qat/qat_common/adf_accel_engine.c
new file mode 100644
index 000000000000..c77453b900a3
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_accel_engine.c
@@ -0,0 +1,168 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include "adf_cfg.h"
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_uclo.h"
+
+int adf_ae_fw_load(struct adf_accel_dev *accel_dev)
+{
+ struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+ struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+ void *uof_addr;
+ uint32_t uof_size;
+
+ if (request_firmware(&loader_data->uof_fw, hw_device->fw_name,
+ &accel_dev->accel_pci_dev.pci_dev->dev)) {
+ pr_err("QAT: Failed to load firmware %s\n", hw_device->fw_name);
+ return -EFAULT;
+ }
+
+ uof_size = loader_data->uof_fw->size;
+ uof_addr = (void *)loader_data->uof_fw->data;
+ if (qat_uclo_map_uof_obj(loader_data->fw_loader, uof_addr, uof_size)) {
+ pr_err("QAT: Failed to map UOF\n");
+ goto out_err;
+ }
+ if (qat_uclo_wr_all_uimage(loader_data->fw_loader)) {
+ pr_err("QAT: Failed to map UOF\n");
+ goto out_err;
+ }
+ return 0;
+
+out_err:
+ release_firmware(loader_data->uof_fw);
+ return -EFAULT;
+}
+
+int adf_ae_fw_release(struct adf_accel_dev *accel_dev)
+{
+ struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+
+ release_firmware(loader_data->uof_fw);
+ qat_uclo_del_uof_obj(loader_data->fw_loader);
+ qat_hal_deinit(loader_data->fw_loader);
+ loader_data->fw_loader = NULL;
+ return 0;
+}
+
+int adf_ae_start(struct adf_accel_dev *accel_dev)
+{
+ struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
+
+ for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
+ if (hw_data->ae_mask & (1 << ae)) {
+ qat_hal_start(loader_data->fw_loader, ae, 0xFF);
+ ae_ctr++;
+ }
+ }
+ pr_info("QAT: qat_dev%d started %d acceleration engines\n",
+ accel_dev->accel_id, ae_ctr);
+ return 0;
+}
+
+int adf_ae_stop(struct adf_accel_dev *accel_dev)
+{
+ struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint32_t ae_ctr, ae, max_aes = GET_MAX_ACCELENGINES(accel_dev);
+
+ for (ae = 0, ae_ctr = 0; ae < max_aes; ae++) {
+ if (hw_data->ae_mask & (1 << ae)) {
+ qat_hal_stop(loader_data->fw_loader, ae, 0xFF);
+ ae_ctr++;
+ }
+ }
+ pr_info("QAT: qat_dev%d stopped %d acceleration engines\n",
+ accel_dev->accel_id, ae_ctr);
+ return 0;
+}
+
+static int adf_ae_reset(struct adf_accel_dev *accel_dev, int ae)
+{
+ struct adf_fw_loader_data *loader_data = accel_dev->fw_loader;
+
+ qat_hal_reset(loader_data->fw_loader);
+ if (qat_hal_clr_reset(loader_data->fw_loader))
+ return -EFAULT;
+
+ return 0;
+}
+
+int adf_ae_init(struct adf_accel_dev *accel_dev)
+{
+ struct adf_fw_loader_data *loader_data;
+
+ loader_data = kzalloc(sizeof(*loader_data), GFP_KERNEL);
+ if (!loader_data)
+ return -ENOMEM;
+
+ accel_dev->fw_loader = loader_data;
+ if (qat_hal_init(accel_dev)) {
+ pr_err("QAT: Failed to init the AEs\n");
+ kfree(loader_data);
+ return -EFAULT;
+ }
+ if (adf_ae_reset(accel_dev, 0)) {
+ pr_err("QAT: Failed to reset the AEs\n");
+ qat_hal_deinit(loader_data->fw_loader);
+ kfree(loader_data);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int adf_ae_shutdown(struct adf_accel_dev *accel_dev)
+{
+ kfree(accel_dev->fw_loader);
+ accel_dev->fw_loader = NULL;
+ return 0;
+}
diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c
new file mode 100644
index 000000000000..c29d4c3926bf
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_aer.c
@@ -0,0 +1,259 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+
+static struct workqueue_struct *device_reset_wq;
+
+static pci_ers_result_t adf_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+ pr_info("QAT: Acceleration driver hardware error detected.\n");
+ if (!accel_dev) {
+ pr_err("QAT: Can't find acceleration device\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ if (state == pci_channel_io_perm_failure) {
+ pr_err("QAT: Can't recover from device error\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/* reset dev data */
+struct adf_reset_dev_data {
+ int mode;
+ struct adf_accel_dev *accel_dev;
+ struct completion compl;
+ struct work_struct reset_work;
+};
+
+#define PPDSTAT_OFFSET 0x7E
+static void adf_dev_restore(struct adf_accel_dev *accel_dev)
+{
+ struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+ struct pci_dev *parent = pdev->bus->self;
+ uint16_t ppdstat = 0, bridge_ctl = 0;
+ int pending = 0;
+
+ pr_info("QAT: Reseting device qat_dev%d\n", accel_dev->accel_id);
+ pci_read_config_word(pdev, PPDSTAT_OFFSET, &ppdstat);
+ pending = ppdstat & PCI_EXP_DEVSTA_TRPND;
+ if (pending) {
+ int ctr = 0;
+
+ do {
+ msleep(100);
+ pci_read_config_word(pdev, PPDSTAT_OFFSET, &ppdstat);
+ pending = ppdstat & PCI_EXP_DEVSTA_TRPND;
+ } while (pending && ctr++ < 10);
+ }
+
+ if (pending)
+ pr_info("QAT: Transaction still in progress. Proceeding\n");
+
+ pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &bridge_ctl);
+ bridge_ctl |= PCI_BRIDGE_CTL_BUS_RESET;
+ pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
+ msleep(100);
+ bridge_ctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+ pci_write_config_word(parent, PCI_BRIDGE_CONTROL, bridge_ctl);
+ msleep(100);
+ pci_restore_state(pdev);
+ pci_save_state(pdev);
+}
+
+static void adf_device_reset_worker(struct work_struct *work)
+{
+ struct adf_reset_dev_data *reset_data =
+ container_of(work, struct adf_reset_dev_data, reset_work);
+ struct adf_accel_dev *accel_dev = reset_data->accel_dev;
+
+ adf_dev_restarting_notify(accel_dev);
+ adf_dev_stop(accel_dev);
+ adf_dev_restore(accel_dev);
+ if (adf_dev_start(accel_dev)) {
+ /* The device hanged and we can't restart it so stop here */
+ dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
+ kfree(reset_data);
+ WARN(1, "QAT: device restart failed. Device is unusable\n");
+ return;
+ }
+ adf_dev_restarted_notify(accel_dev);
+ clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+
+ /* The dev is back alive. Notify the caller if in sync mode */
+ if (reset_data->mode == ADF_DEV_RESET_SYNC)
+ complete(&reset_data->compl);
+ else
+ kfree(reset_data);
+}
+
+static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
+ enum adf_dev_reset_mode mode)
+{
+ struct adf_reset_dev_data *reset_data;
+
+ if (adf_dev_started(accel_dev) &&
+ !test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
+ return 0;
+
+ set_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+ reset_data = kzalloc(sizeof(*reset_data), GFP_ATOMIC);
+ if (!reset_data)
+ return -ENOMEM;
+ reset_data->accel_dev = accel_dev;
+ init_completion(&reset_data->compl);
+ reset_data->mode = mode;
+ INIT_WORK(&reset_data->reset_work, adf_device_reset_worker);
+ queue_work(device_reset_wq, &reset_data->reset_work);
+
+ /* If in sync mode wait for the result */
+ if (mode == ADF_DEV_RESET_SYNC) {
+ int ret = 0;
+ /* Maximum device reset time is 10 seconds */
+ unsigned long wait_jiffies = msecs_to_jiffies(10000);
+ unsigned long timeout = wait_for_completion_timeout(
+ &reset_data->compl, wait_jiffies);
+ if (!timeout) {
+ pr_err("QAT: Reset device timeout expired\n");
+ ret = -EFAULT;
+ }
+ kfree(reset_data);
+ return ret;
+ }
+ return 0;
+}
+
+static pci_ers_result_t adf_slot_reset(struct pci_dev *pdev)
+{
+ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+ if (!accel_dev) {
+ pr_err("QAT: Can't find acceleration device\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (adf_dev_aer_schedule_reset(accel_dev, ADF_DEV_RESET_SYNC))
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void adf_resume(struct pci_dev *pdev)
+{
+ pr_info("QAT: Acceleration driver reset completed\n");
+ pr_info("QAT: Device is up and runnig\n");
+}
+
+static struct pci_error_handlers adf_err_handler = {
+ .error_detected = adf_error_detected,
+ .slot_reset = adf_slot_reset,
+ .resume = adf_resume,
+};
+
+/**
+ * adf_enable_aer() - Enable Advance Error Reporting for acceleration device
+ * @accel_dev: Pointer to acceleration device.
+ * @adf: PCI device driver owning the given acceleration device.
+ *
+ * Function enables PCI Advance Error Reporting for the
+ * QAT acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf)
+{
+ struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+ adf->err_handler = &adf_err_handler;
+ pci_enable_pcie_error_reporting(pdev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_enable_aer);
+
+/**
+ * adf_disable_aer() - Enable Advance Error Reporting for acceleration device
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function disables PCI Advance Error Reporting for the
+ * QAT acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_disable_aer(struct adf_accel_dev *accel_dev)
+{
+ struct pci_dev *pdev = accel_to_pci_dev(accel_dev);
+
+ pci_disable_pcie_error_reporting(pdev);
+}
+EXPORT_SYMBOL_GPL(adf_disable_aer);
+
+int adf_init_aer(void)
+{
+ device_reset_wq = create_workqueue("qat_device_reset_wq");
+ return (device_reset_wq == NULL) ? -EFAULT : 0;
+}
+
+void adf_exit_aer(void)
+{
+ if (device_reset_wq)
+ destroy_workqueue(device_reset_wq);
+ device_reset_wq = NULL;
+}
diff --git a/drivers/crypto/qat/qat_common/adf_cfg.c b/drivers/crypto/qat/qat_common/adf_cfg.c
new file mode 100644
index 000000000000..aba7f1d043fb
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_cfg.c
@@ -0,0 +1,361 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg.h"
+
+static DEFINE_MUTEX(qat_cfg_read_lock);
+
+static void *qat_dev_cfg_start(struct seq_file *sfile, loff_t *pos)
+{
+ struct adf_cfg_device_data *dev_cfg = sfile->private;
+
+ mutex_lock(&qat_cfg_read_lock);
+ return seq_list_start(&dev_cfg->sec_list, *pos);
+}
+
+static int qat_dev_cfg_show(struct seq_file *sfile, void *v)
+{
+ struct list_head *list;
+ struct adf_cfg_section *sec =
+ list_entry(v, struct adf_cfg_section, list);
+
+ seq_printf(sfile, "[%s]\n", sec->name);
+ list_for_each(list, &sec->param_head) {
+ struct adf_cfg_key_val *ptr =
+ list_entry(list, struct adf_cfg_key_val, list);
+ seq_printf(sfile, "%s = %s\n", ptr->key, ptr->val);
+ }
+ return 0;
+}
+
+static void *qat_dev_cfg_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+ struct adf_cfg_device_data *dev_cfg = sfile->private;
+
+ return seq_list_next(v, &dev_cfg->sec_list, pos);
+}
+
+static void qat_dev_cfg_stop(struct seq_file *sfile, void *v)
+{
+ mutex_unlock(&qat_cfg_read_lock);
+}
+
+static const struct seq_operations qat_dev_cfg_sops = {
+ .start = qat_dev_cfg_start,
+ .next = qat_dev_cfg_next,
+ .stop = qat_dev_cfg_stop,
+ .show = qat_dev_cfg_show
+};
+
+static int qat_dev_cfg_open(struct inode *inode, struct file *file)
+{
+ int ret = seq_open(file, &qat_dev_cfg_sops);
+
+ if (!ret) {
+ struct seq_file *seq_f = file->private_data;
+
+ seq_f->private = inode->i_private;
+ }
+ return ret;
+}
+
+static const struct file_operations qat_dev_cfg_fops = {
+ .open = qat_dev_cfg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/**
+ * adf_cfg_dev_add() - Create an acceleration device configuration table.
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function creates a configuration table for the given acceleration device.
+ * The table stores device specific config values.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_dev_add(struct adf_accel_dev *accel_dev)
+{
+ struct adf_cfg_device_data *dev_cfg_data;
+
+ dev_cfg_data = kzalloc(sizeof(*dev_cfg_data), GFP_KERNEL);
+ if (!dev_cfg_data)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&dev_cfg_data->sec_list);
+ init_rwsem(&dev_cfg_data->lock);
+ accel_dev->cfg = dev_cfg_data;
+
+ /* accel_dev->debugfs_dir should always be non-NULL here */
+ dev_cfg_data->debug = debugfs_create_file("dev_cfg", S_IRUSR,
+ accel_dev->debugfs_dir,
+ dev_cfg_data,
+ &qat_dev_cfg_fops);
+ if (!dev_cfg_data->debug) {
+ pr_err("QAT: Failed to create qat cfg debugfs entry.\n");
+ kfree(dev_cfg_data);
+ accel_dev->cfg = NULL;
+ return -EFAULT;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_dev_add);
+
+static void adf_cfg_section_del_all(struct list_head *head);
+
+void adf_cfg_del_all(struct adf_accel_dev *accel_dev)
+{
+ struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+ down_write(&dev_cfg_data->lock);
+ adf_cfg_section_del_all(&dev_cfg_data->sec_list);
+ up_write(&dev_cfg_data->lock);
+}
+
+/**
+ * adf_cfg_dev_remove() - Clears acceleration device configuration table.
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function removes configuration table from the given acceleration device
+ * and frees all allocated memory.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev)
+{
+ struct adf_cfg_device_data *dev_cfg_data = accel_dev->cfg;
+
+ down_write(&dev_cfg_data->lock);
+ adf_cfg_section_del_all(&dev_cfg_data->sec_list);
+ up_write(&dev_cfg_data->lock);
+ debugfs_remove(dev_cfg_data->debug);
+ kfree(dev_cfg_data);
+ accel_dev->cfg = NULL;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_dev_remove);
+
+static void adf_cfg_keyval_add(struct adf_cfg_key_val *new,
+ struct adf_cfg_section *sec)
+{
+ list_add_tail(&new->list, &sec->param_head);
+}
+
+static void adf_cfg_keyval_del_all(struct list_head *head)
+{
+ struct list_head *list_ptr, *tmp;
+
+ list_for_each_prev_safe(list_ptr, tmp, head) {
+ struct adf_cfg_key_val *ptr =
+ list_entry(list_ptr, struct adf_cfg_key_val, list);
+ list_del(list_ptr);
+ kfree(ptr);
+ }
+}
+
+static void adf_cfg_section_del_all(struct list_head *head)
+{
+ struct adf_cfg_section *ptr;
+ struct list_head *list, *tmp;
+
+ list_for_each_prev_safe(list, tmp, head) {
+ ptr = list_entry(list, struct adf_cfg_section, list);
+ adf_cfg_keyval_del_all(&ptr->param_head);
+ list_del(list);
+ kfree(ptr);
+ }
+}
+
+static struct adf_cfg_key_val *adf_cfg_key_value_find(struct adf_cfg_section *s,
+ const char *key)
+{
+ struct list_head *list;
+
+ list_for_each(list, &s->param_head) {
+ struct adf_cfg_key_val *ptr =
+ list_entry(list, struct adf_cfg_key_val, list);
+ if (!strcmp(ptr->key, key))
+ return ptr;
+ }
+ return NULL;
+}
+
+static struct adf_cfg_section *adf_cfg_sec_find(struct adf_accel_dev *accel_dev,
+ const char *sec_name)
+{
+ struct adf_cfg_device_data *cfg = accel_dev->cfg;
+ struct list_head *list;
+
+ list_for_each(list, &cfg->sec_list) {
+ struct adf_cfg_section *ptr =
+ list_entry(list, struct adf_cfg_section, list);
+ if (!strcmp(ptr->name, sec_name))
+ return ptr;
+ }
+ return NULL;
+}
+
+static int adf_cfg_key_val_get(struct adf_accel_dev *accel_dev,
+ const char *sec_name,
+ const char *key_name,
+ char *val)
+{
+ struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, sec_name);
+ struct adf_cfg_key_val *keyval = NULL;
+
+ if (sec)
+ keyval = adf_cfg_key_value_find(sec, key_name);
+ if (keyval) {
+ memcpy(val, keyval->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
+ return 0;
+ }
+ return -1;
+}
+
+/**
+ * adf_cfg_add_key_value_param() - Add key-value config entry to config table.
+ * @accel_dev: Pointer to acceleration device.
+ * @section_name: Name of the section where the param will be added
+ * @key: The key string
+ * @val: Value pain for the given @key
+ * @type: Type - string, int or address
+ *
+ * Function adds configuration key - value entry in the appropriate section
+ * in the given acceleration device
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
+ const char *section_name,
+ const char *key, const void *val,
+ enum adf_cfg_val_type type)
+{
+ struct adf_cfg_device_data *cfg = accel_dev->cfg;
+ struct adf_cfg_key_val *key_val;
+ struct adf_cfg_section *section = adf_cfg_sec_find(accel_dev,
+ section_name);
+ if (!section)
+ return -EFAULT;
+
+ key_val = kzalloc(sizeof(*key_val), GFP_KERNEL);
+ if (!key_val)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&key_val->list);
+ strlcpy(key_val->key, key, sizeof(key_val->key));
+
+ if (type == ADF_DEC) {
+ snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
+ "%ld", (*((long *)val)));
+ } else if (type == ADF_STR) {
+ strlcpy(key_val->val, (char *)val, sizeof(key_val->val));
+ } else if (type == ADF_HEX) {
+ snprintf(key_val->val, ADF_CFG_MAX_VAL_LEN_IN_BYTES,
+ "0x%lx", (unsigned long)val);
+ } else {
+ pr_err("QAT: Unknown type given.\n");
+ kfree(key_val);
+ return -1;
+ }
+ key_val->type = type;
+ down_write(&cfg->lock);
+ adf_cfg_keyval_add(key_val, section);
+ up_write(&cfg->lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_add_key_value_param);
+
+/**
+ * adf_cfg_section_add() - Add config section entry to config table.
+ * @accel_dev: Pointer to acceleration device.
+ * @name: Name of the section
+ *
+ * Function adds configuration section where key - value entries
+ * will be stored.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name)
+{
+ struct adf_cfg_device_data *cfg = accel_dev->cfg;
+ struct adf_cfg_section *sec = adf_cfg_sec_find(accel_dev, name);
+
+ if (sec)
+ return 0;
+
+ sec = kzalloc(sizeof(*sec), GFP_KERNEL);
+ if (!sec)
+ return -ENOMEM;
+
+ strlcpy(sec->name, name, sizeof(sec->name));
+ INIT_LIST_HEAD(&sec->param_head);
+ down_write(&cfg->lock);
+ list_add_tail(&sec->list, &cfg->sec_list);
+ up_write(&cfg->lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_cfg_section_add);
+
+int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
+ const char *section, const char *name,
+ char *value)
+{
+ struct adf_cfg_device_data *cfg = accel_dev->cfg;
+ int ret;
+
+ down_read(&cfg->lock);
+ ret = adf_cfg_key_val_get(accel_dev, section, name, value);
+ up_read(&cfg->lock);
+ return ret;
+}
diff --git a/drivers/crypto/qat/qat_common/adf_cfg.h b/drivers/crypto/qat/qat_common/adf_cfg.h
new file mode 100644
index 000000000000..6a9c6f6b5ec9
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_cfg.h
@@ -0,0 +1,87 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_CFG_H_
+#define ADF_CFG_H_
+
+#include <linux/list.h>
+#include <linux/rwsem.h>
+#include <linux/debugfs.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg_common.h"
+#include "adf_cfg_strings.h"
+
+struct adf_cfg_key_val {
+ char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+ enum adf_cfg_val_type type;
+ struct list_head list;
+};
+
+struct adf_cfg_section {
+ char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
+ struct list_head list;
+ struct list_head param_head;
+};
+
+struct adf_cfg_device_data {
+ struct list_head sec_list;
+ struct dentry *debug;
+ struct rw_semaphore lock;
+};
+
+int adf_cfg_dev_add(struct adf_accel_dev *accel_dev);
+void adf_cfg_dev_remove(struct adf_accel_dev *accel_dev);
+int adf_cfg_section_add(struct adf_accel_dev *accel_dev, const char *name);
+void adf_cfg_del_all(struct adf_accel_dev *accel_dev);
+int adf_cfg_add_key_value_param(struct adf_accel_dev *accel_dev,
+ const char *section_name,
+ const char *key, const void *val,
+ enum adf_cfg_val_type type);
+int adf_cfg_get_param_value(struct adf_accel_dev *accel_dev,
+ const char *section, const char *name, char *value);
+
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_cfg_common.h b/drivers/crypto/qat/qat_common/adf_cfg_common.h
new file mode 100644
index 000000000000..88b82187ac35
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_cfg_common.h
@@ -0,0 +1,100 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_CFG_COMMON_H_
+#define ADF_CFG_COMMON_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define ADF_CFG_MAX_STR_LEN 64
+#define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN
+#define ADF_CFG_BASE_DEC 10
+#define ADF_CFG_BASE_HEX 16
+#define ADF_CFG_ALL_DEVICES 0xFE
+#define ADF_CFG_NO_DEVICE 0xFF
+#define ADF_CFG_AFFINITY_WHATEVER 0xFF
+#define MAX_DEVICE_NAME_SIZE 32
+#define ADF_MAX_DEVICES 32
+
+enum adf_cfg_val_type {
+ ADF_DEC,
+ ADF_HEX,
+ ADF_STR
+};
+
+enum adf_device_type {
+ DEV_UNKNOWN = 0,
+ DEV_DH895XCC,
+};
+
+struct adf_dev_status_info {
+ enum adf_device_type type;
+ uint8_t accel_id;
+ uint8_t instance_id;
+ uint8_t num_ae;
+ uint8_t num_accel;
+ uint8_t num_logical_accel;
+ uint8_t banks_per_accel;
+ uint8_t state;
+ uint8_t bus;
+ uint8_t dev;
+ uint8_t fun;
+ char name[MAX_DEVICE_NAME_SIZE];
+};
+
+#define ADF_CTL_IOC_MAGIC 'a'
+#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \
+ struct adf_user_cfg_ctl_data)
+#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \
+ struct adf_user_cfg_ctl_data)
+#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \
+ struct adf_user_cfg_ctl_data)
+#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, uint32_t)
+#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, int32_t)
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/qat/qat_common/adf_cfg_strings.h
new file mode 100644
index 000000000000..c7ac758ebc90
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_cfg_strings.h
@@ -0,0 +1,83 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_CFG_STRINGS_H_
+#define ADF_CFG_STRINGS_H_
+
+#define ADF_GENERAL_SEC "GENERAL"
+#define ADF_KERNEL_SEC "KERNEL"
+#define ADF_ACCEL_SEC "Accelerator"
+#define ADF_NUM_CY "NumberCyInstances"
+#define ADF_NUM_DC "NumberDcInstances"
+#define ADF_RING_SYM_SIZE "NumConcurrentSymRequests"
+#define ADF_RING_ASYM_SIZE "NumConcurrentAsymRequests"
+#define ADF_RING_DC_SIZE "NumConcurrentRequests"
+#define ADF_RING_ASYM_TX "RingAsymTx"
+#define ADF_RING_SYM_TX "RingSymTx"
+#define ADF_RING_RND_TX "RingNrbgTx"
+#define ADF_RING_ASYM_RX "RingAsymRx"
+#define ADF_RING_SYM_RX "RinSymRx"
+#define ADF_RING_RND_RX "RingNrbgRx"
+#define ADF_RING_DC_TX "RingTx"
+#define ADF_RING_DC_RX "RingRx"
+#define ADF_ETRMGR_BANK "Bank"
+#define ADF_RING_BANK_NUM "BankNumber"
+#define ADF_CY "Cy"
+#define ADF_DC "Dc"
+#define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled"
+#define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \
+ ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCING_ENABLED
+#define ADF_ETRMGR_COALESCE_TIMER "InterruptCoalescingTimerNs"
+#define ADF_ETRMGR_COALESCE_TIMER_FORMAT \
+ ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCE_TIMER
+#define ADF_ETRMGR_COALESCING_MSG_ENABLED "InterruptCoalescingNumResponses"
+#define ADF_ETRMGR_COALESCING_MSG_ENABLED_FORMAT \
+ ADF_ETRMGR_BANK"%d"ADF_ETRMGR_COALESCING_MSG_ENABLED
+#define ADF_ETRMGR_CORE_AFFINITY "CoreAffinity"
+#define ADF_ETRMGR_CORE_AFFINITY_FORMAT \
+ ADF_ETRMGR_BANK"%d"ADF_ETRMGR_CORE_AFFINITY
+#define ADF_ACCEL_STR "Accelerator%d"
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_cfg_user.h b/drivers/crypto/qat/qat_common/adf_cfg_user.h
new file mode 100644
index 000000000000..0c38a155a865
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_cfg_user.h
@@ -0,0 +1,94 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_CFG_USER_H_
+#define ADF_CFG_USER_H_
+
+#include "adf_cfg_common.h"
+#include "adf_cfg_strings.h"
+
+struct adf_user_cfg_key_val {
+ char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+ union {
+ char *user_val_ptr;
+ uint64_t padding1;
+ };
+ union {
+ struct adf_user_cfg_key_val *prev;
+ uint64_t padding2;
+ };
+ union {
+ struct adf_user_cfg_key_val *next;
+ uint64_t padding3;
+ };
+ enum adf_cfg_val_type type;
+};
+
+struct adf_user_cfg_section {
+ char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES];
+ union {
+ struct adf_user_cfg_key_val *params;
+ uint64_t padding1;
+ };
+ union {
+ struct adf_user_cfg_section *prev;
+ uint64_t padding2;
+ };
+ union {
+ struct adf_user_cfg_section *next;
+ uint64_t padding3;
+ };
+};
+
+struct adf_user_cfg_ctl_data {
+ union {
+ struct adf_user_cfg_section *config_section;
+ uint64_t padding;
+ };
+ uint8_t device_id;
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
new file mode 100644
index 000000000000..5e8f9d431e5d
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -0,0 +1,192 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_DRV_H
+#define ADF_DRV_H
+
+#include <linux/list.h>
+#include <linux/pci.h>
+#include "adf_accel_devices.h"
+#include "icp_qat_fw_loader_handle.h"
+#include "icp_qat_hal.h"
+
+#define ADF_STATUS_RESTARTING 0
+#define ADF_STATUS_STARTING 1
+#define ADF_STATUS_CONFIGURED 2
+#define ADF_STATUS_STARTED 3
+#define ADF_STATUS_AE_INITIALISED 4
+#define ADF_STATUS_AE_UCODE_LOADED 5
+#define ADF_STATUS_AE_STARTED 6
+#define ADF_STATUS_ORPHAN_TH_RUNNING 7
+#define ADF_STATUS_IRQ_ALLOCATED 8
+
+enum adf_dev_reset_mode {
+ ADF_DEV_RESET_ASYNC = 0,
+ ADF_DEV_RESET_SYNC
+};
+
+enum adf_event {
+ ADF_EVENT_INIT = 0,
+ ADF_EVENT_START,
+ ADF_EVENT_STOP,
+ ADF_EVENT_SHUTDOWN,
+ ADF_EVENT_RESTARTING,
+ ADF_EVENT_RESTARTED,
+};
+
+struct service_hndl {
+ int (*event_hld)(struct adf_accel_dev *accel_dev,
+ enum adf_event event);
+ unsigned long init_status;
+ unsigned long start_status;
+ char *name;
+ struct list_head list;
+ int admin;
+};
+
+int adf_service_register(struct service_hndl *service);
+int adf_service_unregister(struct service_hndl *service);
+
+int adf_dev_init(struct adf_accel_dev *accel_dev);
+int adf_dev_start(struct adf_accel_dev *accel_dev);
+int adf_dev_stop(struct adf_accel_dev *accel_dev);
+int adf_dev_shutdown(struct adf_accel_dev *accel_dev);
+
+int adf_ctl_dev_register(void);
+void adf_ctl_dev_unregister(void);
+int adf_processes_dev_register(void);
+void adf_processes_dev_unregister(void);
+
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev);
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev);
+struct list_head *adf_devmgr_get_head(void);
+struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id);
+struct adf_accel_dev *adf_devmgr_get_first(void);
+struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev);
+int adf_devmgr_verify_id(uint32_t id);
+void adf_devmgr_get_num_dev(uint32_t *num);
+int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev);
+int adf_dev_started(struct adf_accel_dev *accel_dev);
+int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev);
+int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev);
+int adf_ae_init(struct adf_accel_dev *accel_dev);
+int adf_ae_shutdown(struct adf_accel_dev *accel_dev);
+int adf_ae_fw_load(struct adf_accel_dev *accel_dev);
+int adf_ae_fw_release(struct adf_accel_dev *accel_dev);
+int adf_ae_start(struct adf_accel_dev *accel_dev);
+int adf_ae_stop(struct adf_accel_dev *accel_dev);
+
+int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf);
+void adf_disable_aer(struct adf_accel_dev *accel_dev);
+int adf_init_aer(void);
+void adf_exit_aer(void);
+
+int adf_dev_get(struct adf_accel_dev *accel_dev);
+void adf_dev_put(struct adf_accel_dev *accel_dev);
+int adf_dev_in_use(struct adf_accel_dev *accel_dev);
+int adf_init_etr_data(struct adf_accel_dev *accel_dev);
+void adf_cleanup_etr_data(struct adf_accel_dev *accel_dev);
+int qat_crypto_register(void);
+int qat_crypto_unregister(void);
+struct qat_crypto_instance *qat_crypto_get_instance_node(int node);
+void qat_crypto_put_instance(struct qat_crypto_instance *inst);
+void qat_alg_callback(void *resp);
+int qat_algs_init(void);
+void qat_algs_exit(void);
+int qat_algs_register(void);
+int qat_algs_unregister(void);
+
+int qat_hal_init(struct adf_accel_dev *accel_dev);
+void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle);
+void qat_hal_start(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+ unsigned int ctx_mask);
+void qat_hal_stop(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+ unsigned int ctx_mask);
+void qat_hal_reset(struct icp_qat_fw_loader_handle *handle);
+int qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle);
+void qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask);
+int qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, enum icp_qat_uof_regtype lm_type,
+ unsigned char mode);
+int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char mode);
+int qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char mode);
+void qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask, unsigned int upc);
+void qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int uaddr,
+ unsigned int words_num, uint64_t *uword);
+void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+ unsigned int uword_addr, unsigned int words_num,
+ unsigned int *data);
+int qat_hal_get_ins_num(void);
+int qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae,
+ struct icp_qat_uof_batch_init *lm_init_header);
+int qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata);
+int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ unsigned short reg_num, unsigned int regdata);
+int qat_hal_wr_lm(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned short lm_addr, unsigned int value);
+int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle);
+void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle);
+int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
+ void *addr_ptr, int mem_size);
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
new file mode 100644
index 000000000000..d97069b8a8e4
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c
@@ -0,0 +1,490 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_cfg.h"
+#include "adf_cfg_common.h"
+#include "adf_cfg_user.h"
+
+#define DEVICE_NAME "qat_adf_ctl"
+
+static DEFINE_MUTEX(adf_ctl_lock);
+static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+
+static const struct file_operations adf_ctl_ops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = adf_ctl_ioctl,
+ .compat_ioctl = adf_ctl_ioctl,
+};
+
+struct adf_ctl_drv_info {
+ unsigned int major;
+ struct cdev drv_cdev;
+ struct class *drv_class;
+};
+
+static struct adf_ctl_drv_info adt_ctl_drv;
+
+static void adf_chr_drv_destroy(void)
+{
+ device_destroy(adt_ctl_drv.drv_class, MKDEV(adt_ctl_drv.major, 0));
+ cdev_del(&adt_ctl_drv.drv_cdev);
+ class_destroy(adt_ctl_drv.drv_class);
+ unregister_chrdev_region(MKDEV(adt_ctl_drv.major, 0), 1);
+}
+
+static int adf_chr_drv_create(void)
+{
+ dev_t dev_id;
+ struct device *drv_device;
+
+ if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
+ pr_err("QAT: unable to allocate chrdev region\n");
+ return -EFAULT;
+ }
+
+ adt_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
+ if (IS_ERR(adt_ctl_drv.drv_class)) {
+ pr_err("QAT: class_create failed for adf_ctl\n");
+ goto err_chrdev_unreg;
+ }
+ adt_ctl_drv.major = MAJOR(dev_id);
+ cdev_init(&adt_ctl_drv.drv_cdev, &adf_ctl_ops);
+ if (cdev_add(&adt_ctl_drv.drv_cdev, dev_id, 1)) {
+ pr_err("QAT: cdev add failed\n");
+ goto err_class_destr;
+ }
+
+ drv_device = device_create(adt_ctl_drv.drv_class, NULL,
+ MKDEV(adt_ctl_drv.major, 0),
+ NULL, DEVICE_NAME);
+ if (!drv_device) {
+ pr_err("QAT: failed to create device\n");
+ goto err_cdev_del;
+ }
+ return 0;
+err_cdev_del:
+ cdev_del(&adt_ctl_drv.drv_cdev);
+err_class_destr:
+ class_destroy(adt_ctl_drv.drv_class);
+err_chrdev_unreg:
+ unregister_chrdev_region(dev_id, 1);
+ return -EFAULT;
+}
+
+static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
+ unsigned long arg)
+{
+ struct adf_user_cfg_ctl_data *cfg_data;
+
+ cfg_data = kzalloc(sizeof(*cfg_data), GFP_KERNEL);
+ if (!cfg_data)
+ return -ENOMEM;
+
+ /* Initialize device id to NO DEVICE as 0 is a valid device id */
+ cfg_data->device_id = ADF_CFG_NO_DEVICE;
+
+ if (copy_from_user(cfg_data, (void __user *)arg, sizeof(*cfg_data))) {
+ pr_err("QAT: failed to copy from user cfg_data.\n");
+ kfree(cfg_data);
+ return -EIO;
+ }
+
+ *ctl_data = cfg_data;
+ return 0;
+}
+
+static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
+ const char *section,
+ const struct adf_user_cfg_key_val *key_val)
+{
+ if (key_val->type == ADF_HEX) {
+ long *ptr = (long *)key_val->val;
+ long val = *ptr;
+
+ if (adf_cfg_add_key_value_param(accel_dev, section,
+ key_val->key, (void *)val,
+ key_val->type)) {
+ pr_err("QAT: failed to add keyvalue.\n");
+ return -EFAULT;
+ }
+ } else {
+ if (adf_cfg_add_key_value_param(accel_dev, section,
+ key_val->key, key_val->val,
+ key_val->type)) {
+ pr_err("QAT: failed to add keyvalue.\n");
+ return -EFAULT;
+ }
+ }
+ return 0;
+}
+
+static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
+ struct adf_user_cfg_ctl_data *ctl_data)
+{
+ struct adf_user_cfg_key_val key_val;
+ struct adf_user_cfg_key_val *params_head;
+ struct adf_user_cfg_section section, *section_head;
+
+ section_head = ctl_data->config_section;
+
+ while (section_head) {
+ if (copy_from_user(&section, (void __user *)section_head,
+ sizeof(*section_head))) {
+ pr_err("QAT: failed to copy section info\n");
+ goto out_err;
+ }
+
+ if (adf_cfg_section_add(accel_dev, section.name)) {
+ pr_err("QAT: failed to add section.\n");
+ goto out_err;
+ }
+
+ params_head = section_head->params;
+
+ while (params_head) {
+ if (copy_from_user(&key_val, (void __user *)params_head,
+ sizeof(key_val))) {
+ pr_err("QAT: Failed to copy keyvalue.\n");
+ goto out_err;
+ }
+ if (adf_add_key_value_data(accel_dev, section.name,
+ &key_val)) {
+ goto out_err;
+ }
+ params_head = key_val.next;
+ }
+ section_head = section.next;
+ }
+ return 0;
+out_err:
+ adf_cfg_del_all(accel_dev);
+ return -EFAULT;
+}
+
+static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct adf_user_cfg_ctl_data *ctl_data;
+ struct adf_accel_dev *accel_dev;
+
+ ret = adf_ctl_alloc_resources(&ctl_data, arg);
+ if (ret)
+ return ret;
+
+ accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+ if (!accel_dev) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (adf_dev_started(accel_dev)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (adf_copy_key_value_data(accel_dev, ctl_data)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+out:
+ kfree(ctl_data);
+ return ret;
+}
+
+static int adf_ctl_is_device_in_use(int id)
+{
+ struct list_head *itr, *head = adf_devmgr_get_head();
+
+ list_for_each(itr, head) {
+ struct adf_accel_dev *dev =
+ list_entry(itr, struct adf_accel_dev, list);
+
+ if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+ if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
+ pr_info("QAT: device qat_dev%d is busy\n",
+ dev->accel_id);
+ return -EBUSY;
+ }
+ }
+ }
+ return 0;
+}
+
+static int adf_ctl_stop_devices(uint32_t id)
+{
+ struct list_head *itr, *head = adf_devmgr_get_head();
+ int ret = 0;
+
+ list_for_each(itr, head) {
+ struct adf_accel_dev *accel_dev =
+ list_entry(itr, struct adf_accel_dev, list);
+ if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+ if (!adf_dev_started(accel_dev))
+ continue;
+
+ if (adf_dev_stop(accel_dev)) {
+ pr_err("QAT: Failed to stop qat_dev%d\n", id);
+ ret = -EFAULT;
+ }
+ }
+ }
+ return ret;
+}
+
+static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct adf_user_cfg_ctl_data *ctl_data;
+
+ ret = adf_ctl_alloc_resources(&ctl_data, arg);
+ if (ret)
+ return ret;
+
+ if (adf_devmgr_verify_id(ctl_data->device_id)) {
+ pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = adf_ctl_is_device_in_use(ctl_data->device_id);
+ if (ret)
+ goto out;
+
+ if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
+ pr_info("QAT: Stopping all acceleration devices.\n");
+ else
+ pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
+ ctl_data->device_id);
+
+ ret = adf_ctl_stop_devices(ctl_data->device_id);
+ if (ret)
+ pr_err("QAT: failed to stop device.\n");
+out:
+ kfree(ctl_data);
+ return ret;
+}
+
+static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct adf_user_cfg_ctl_data *ctl_data;
+ struct adf_accel_dev *accel_dev;
+
+ ret = adf_ctl_alloc_resources(&ctl_data, arg);
+ if (ret)
+ return ret;
+
+ accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
+ if (!accel_dev) {
+ pr_err("QAT: Device %d not found\n", ctl_data->device_id);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (!adf_dev_started(accel_dev)) {
+ pr_info("QAT: Starting acceleration device qat_dev%d.\n",
+ ctl_data->device_id);
+ ret = adf_dev_start(accel_dev);
+ } else {
+ pr_info("QAT: Acceleration device qat_dev%d already started.\n",
+ ctl_data->device_id);
+ }
+ if (ret) {
+ pr_err("QAT: Failed to start qat_dev%d\n", ctl_data->device_id);
+ adf_dev_stop(accel_dev);
+ }
+out:
+ kfree(ctl_data);
+ return ret;
+}
+
+static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ uint32_t num_devices = 0;
+
+ adf_devmgr_get_num_dev(&num_devices);
+ if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct adf_hw_device_data *hw_data;
+ struct adf_dev_status_info dev_info;
+ struct adf_accel_dev *accel_dev;
+
+ if (copy_from_user(&dev_info, (void __user *)arg,
+ sizeof(struct adf_dev_status_info))) {
+ pr_err("QAT: failed to copy from user.\n");
+ return -EFAULT;
+ }
+
+ accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
+ if (!accel_dev) {
+ pr_err("QAT: Device %d not found\n", dev_info.accel_id);
+ return -ENODEV;
+ }
+ hw_data = accel_dev->hw_device;
+ dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
+ dev_info.num_ae = hw_data->get_num_aes(hw_data);
+ dev_info.num_accel = hw_data->get_num_accels(hw_data);
+ dev_info.num_logical_accel = hw_data->num_logical_accel;
+ dev_info.banks_per_accel = hw_data->num_banks
+ / hw_data->num_logical_accel;
+ strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
+ dev_info.instance_id = hw_data->instance_id;
+ dev_info.type = hw_data->dev_class->type;
+ dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
+ dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
+ dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
+
+ if (copy_to_user((void __user *)arg, &dev_info,
+ sizeof(struct adf_dev_status_info))) {
+ pr_err("QAT: failed to copy status.\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+
+ if (mutex_lock_interruptible(&adf_ctl_lock))
+ return -EFAULT;
+
+ switch (cmd) {
+ case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
+ ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
+ break;
+
+ case IOCTL_STOP_ACCEL_DEV:
+ ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
+ break;
+
+ case IOCTL_START_ACCEL_DEV:
+ ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
+ break;
+
+ case IOCTL_GET_NUM_DEVICES:
+ ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
+ break;
+
+ case IOCTL_STATUS_ACCEL_DEV:
+ ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
+ break;
+ default:
+ pr_err("QAT: Invalid ioclt\n");
+ ret = -EFAULT;
+ break;
+ }
+ mutex_unlock(&adf_ctl_lock);
+ return ret;
+}
+
+static int __init adf_register_ctl_device_driver(void)
+{
+ mutex_init(&adf_ctl_lock);
+
+ if (qat_algs_init())
+ goto err_algs_init;
+
+ if (adf_chr_drv_create())
+ goto err_chr_dev;
+
+ if (adf_init_aer())
+ goto err_aer;
+
+ if (qat_crypto_register())
+ goto err_crypto_register;
+
+ return 0;
+
+err_crypto_register:
+ adf_exit_aer();
+err_aer:
+ adf_chr_drv_destroy();
+err_chr_dev:
+ qat_algs_exit();
+err_algs_init:
+ mutex_destroy(&adf_ctl_lock);
+ return -EFAULT;
+}
+
+static void __exit adf_unregister_ctl_device_driver(void)
+{
+ adf_chr_drv_destroy();
+ adf_exit_aer();
+ qat_crypto_unregister();
+ qat_algs_exit();
+ mutex_destroy(&adf_ctl_lock);
+}
+
+module_init(adf_register_ctl_device_driver);
+module_exit(adf_unregister_ctl_device_driver);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
+MODULE_ALIAS("intel_qat");
diff --git a/drivers/crypto/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/qat/qat_common/adf_dev_mgr.c
new file mode 100644
index 000000000000..ae71555c0868
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_dev_mgr.c
@@ -0,0 +1,215 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static LIST_HEAD(accel_table);
+static DEFINE_MUTEX(table_lock);
+static uint32_t num_devices;
+
+/**
+ * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function adds acceleration device to the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev)
+{
+ struct list_head *itr;
+
+ if (num_devices == ADF_MAX_DEVICES) {
+ pr_err("QAT: Only support up to %d devices\n", ADF_MAX_DEVICES);
+ return -EFAULT;
+ }
+
+ mutex_lock(&table_lock);
+ list_for_each(itr, &accel_table) {
+ struct adf_accel_dev *ptr =
+ list_entry(itr, struct adf_accel_dev, list);
+
+ if (ptr == accel_dev) {
+ mutex_unlock(&table_lock);
+ return -EEXIST;
+ }
+ }
+ atomic_set(&accel_dev->ref_count, 0);
+ list_add_tail(&accel_dev->list, &accel_table);
+ accel_dev->accel_id = num_devices++;
+ mutex_unlock(&table_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_add_dev);
+
+struct list_head *adf_devmgr_get_head(void)
+{
+ return &accel_table;
+}
+
+/**
+ * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework.
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function removes acceleration device from the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev)
+{
+ mutex_lock(&table_lock);
+ list_del(&accel_dev->list);
+ num_devices--;
+ mutex_unlock(&table_lock);
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev);
+
+struct adf_accel_dev *adf_devmgr_get_first(void)
+{
+ struct adf_accel_dev *dev = NULL;
+
+ if (!list_empty(&accel_table))
+ dev = list_first_entry(&accel_table, struct adf_accel_dev,
+ list);
+ return dev;
+}
+
+/**
+ * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev.
+ * @accel_dev: Pointer to pci device.
+ *
+ * Function returns acceleration device associated with the given pci device.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: pinter to accel_dev or NULL if not found.
+ */
+struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev)
+{
+ struct list_head *itr;
+
+ list_for_each(itr, &accel_table) {
+ struct adf_accel_dev *ptr =
+ list_entry(itr, struct adf_accel_dev, list);
+
+ if (ptr->accel_pci_dev.pci_dev == pci_dev) {
+ mutex_unlock(&table_lock);
+ return ptr;
+ }
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev);
+
+struct adf_accel_dev *adf_devmgr_get_dev_by_id(uint32_t id)
+{
+ struct list_head *itr;
+
+ list_for_each(itr, &accel_table) {
+ struct adf_accel_dev *ptr =
+ list_entry(itr, struct adf_accel_dev, list);
+
+ if (ptr->accel_id == id) {
+ mutex_unlock(&table_lock);
+ return ptr;
+ }
+ }
+ return NULL;
+}
+
+int adf_devmgr_verify_id(uint32_t id)
+{
+ if (id == ADF_CFG_ALL_DEVICES)
+ return 0;
+
+ if (adf_devmgr_get_dev_by_id(id))
+ return 0;
+
+ return -ENODEV;
+}
+
+void adf_devmgr_get_num_dev(uint32_t *num)
+{
+ struct list_head *itr;
+
+ *num = 0;
+ list_for_each(itr, &accel_table) {
+ (*num)++;
+ }
+}
+
+int adf_dev_in_use(struct adf_accel_dev *accel_dev)
+{
+ return atomic_read(&accel_dev->ref_count) != 0;
+}
+
+int adf_dev_get(struct adf_accel_dev *accel_dev)
+{
+ if (atomic_add_return(1, &accel_dev->ref_count) == 1)
+ if (!try_module_get(accel_dev->owner))
+ return -EFAULT;
+ return 0;
+}
+
+void adf_dev_put(struct adf_accel_dev *accel_dev)
+{
+ if (atomic_sub_return(1, &accel_dev->ref_count) == 0)
+ module_put(accel_dev->owner);
+}
+
+int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev)
+{
+ return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+}
+
+int adf_dev_started(struct adf_accel_dev *accel_dev)
+{
+ return test_bit(ADF_STATUS_STARTED, &accel_dev->status);
+}
diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c
new file mode 100644
index 000000000000..5c0e47a00a87
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_init.c
@@ -0,0 +1,388 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static LIST_HEAD(service_table);
+static DEFINE_MUTEX(service_lock);
+
+static void adf_service_add(struct service_hndl *service)
+{
+ mutex_lock(&service_lock);
+ list_add(&service->list, &service_table);
+ mutex_unlock(&service_lock);
+}
+
+/**
+ * adf_service_register() - Register acceleration service in the accel framework
+ * @service: Pointer to the service
+ *
+ * Function adds the acceleration service to the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_service_register(struct service_hndl *service)
+{
+ service->init_status = 0;
+ service->start_status = 0;
+ adf_service_add(service);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_service_register);
+
+static void adf_service_remove(struct service_hndl *service)
+{
+ mutex_lock(&service_lock);
+ list_del(&service->list);
+ mutex_unlock(&service_lock);
+}
+
+/**
+ * adf_service_unregister() - Unregister acceleration service from the framework
+ * @service: Pointer to the service
+ *
+ * Function remove the acceleration service from the acceleration framework.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_service_unregister(struct service_hndl *service)
+{
+ if (service->init_status || service->start_status) {
+ pr_err("QAT: Could not remove active service\n");
+ return -EFAULT;
+ }
+ adf_service_remove(service);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_service_unregister);
+
+/**
+ * adf_dev_start() - Start acceleration service for the given accel device
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function notifies all the registered services that the acceleration device
+ * is ready to be used.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_dev_start(struct adf_accel_dev *accel_dev)
+{
+ struct service_hndl *service;
+ struct list_head *list_itr;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+
+ if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
+ pr_info("QAT: Device not configured\n");
+ return -EFAULT;
+ }
+ set_bit(ADF_STATUS_STARTING, &accel_dev->status);
+
+ if (adf_ae_init(accel_dev)) {
+ pr_err("QAT: Failed to initialise Acceleration Engine\n");
+ return -EFAULT;
+ }
+ set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
+
+ if (adf_ae_fw_load(accel_dev)) {
+ pr_err("QAT: Failed to load acceleration FW\n");
+ adf_ae_fw_release(accel_dev);
+ return -EFAULT;
+ }
+ set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
+
+ if (hw_data->alloc_irq(accel_dev)) {
+ pr_err("QAT: Failed to allocate interrupts\n");
+ return -EFAULT;
+ }
+ set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
+
+ /*
+ * Subservice initialisation is divided into two stages: init and start.
+ * This is to facilitate any ordering dependencies between services
+ * prior to starting any of the accelerators.
+ */
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
+ pr_err("QAT: Failed to initialise service %s\n",
+ service->name);
+ return -EFAULT;
+ }
+ set_bit(accel_dev->accel_id, &service->init_status);
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
+ pr_err("QAT: Failed to initialise service %s\n",
+ service->name);
+ return -EFAULT;
+ }
+ set_bit(accel_dev->accel_id, &service->init_status);
+ }
+
+ hw_data->enable_error_correction(accel_dev);
+
+ if (adf_ae_start(accel_dev)) {
+ pr_err("QAT: AE Start Failed\n");
+ return -EFAULT;
+ }
+ set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
+
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_START)) {
+ pr_err("QAT: Failed to start service %s\n",
+ service->name);
+ return -EFAULT;
+ }
+ set_bit(accel_dev->accel_id, &service->start_status);
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_START)) {
+ pr_err("QAT: Failed to start service %s\n",
+ service->name);
+ return -EFAULT;
+ }
+ set_bit(accel_dev->accel_id, &service->start_status);
+ }
+
+ clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
+ set_bit(ADF_STATUS_STARTED, &accel_dev->status);
+
+ if (qat_algs_register()) {
+ pr_err("QAT: Failed to register crypto algs\n");
+ set_bit(ADF_STATUS_STARTING, &accel_dev->status);
+ clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
+ return -EFAULT;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_dev_start);
+
+/**
+ * adf_dev_stop() - Stop acceleration service for the given accel device
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function notifies all the registered services that the acceleration device
+ * is shuting down.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_dev_stop(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct service_hndl *service;
+ struct list_head *list_itr;
+ int ret, wait = 0;
+
+ if (!adf_dev_started(accel_dev) &&
+ !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
+ return 0;
+ }
+ clear_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+ clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
+ clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
+
+ if (qat_algs_unregister())
+ pr_err("QAT: Failed to unregister crypto algs\n");
+
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (!test_bit(accel_dev->accel_id, &service->start_status))
+ continue;
+ ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
+ if (!ret) {
+ clear_bit(accel_dev->accel_id, &service->start_status);
+ } else if (ret == -EAGAIN) {
+ wait = 1;
+ clear_bit(accel_dev->accel_id, &service->start_status);
+ }
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (!test_bit(accel_dev->accel_id, &service->start_status))
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_STOP))
+ pr_err("QAT: Failed to shutdown service %s\n",
+ service->name);
+ else
+ clear_bit(accel_dev->accel_id, &service->start_status);
+ }
+
+ if (wait)
+ msleep(100);
+
+ if (adf_dev_started(accel_dev)) {
+ if (adf_ae_stop(accel_dev))
+ pr_err("QAT: failed to stop AE\n");
+ else
+ clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
+ }
+
+ if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
+ if (adf_ae_fw_release(accel_dev))
+ pr_err("QAT: Failed to release the ucode\n");
+ else
+ clear_bit(ADF_STATUS_AE_UCODE_LOADED,
+ &accel_dev->status);
+ }
+
+ if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
+ if (adf_ae_shutdown(accel_dev))
+ pr_err("QAT: Failed to shutdown Accel Engine\n");
+ else
+ clear_bit(ADF_STATUS_AE_INITIALISED,
+ &accel_dev->status);
+ }
+
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (!test_bit(accel_dev->accel_id, &service->init_status))
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
+ pr_err("QAT: Failed to shutdown service %s\n",
+ service->name);
+ else
+ clear_bit(accel_dev->accel_id, &service->init_status);
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (!test_bit(accel_dev->accel_id, &service->init_status))
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
+ pr_err("QAT: Failed to shutdown service %s\n",
+ service->name);
+ else
+ clear_bit(accel_dev->accel_id, &service->init_status);
+ }
+
+ if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
+ hw_data->free_irq(accel_dev);
+ clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
+ }
+
+ /* Delete configuration only if not restarting */
+ if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
+ adf_cfg_del_all(accel_dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(adf_dev_stop);
+
+int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
+{
+ struct service_hndl *service;
+ struct list_head *list_itr;
+
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
+ pr_err("QAT: Failed to restart service %s.\n",
+ service->name);
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
+ pr_err("QAT: Failed to restart service %s.\n",
+ service->name);
+ }
+ return 0;
+}
+
+int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
+{
+ struct service_hndl *service;
+ struct list_head *list_itr;
+
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
+ pr_err("QAT: Failed to restart service %s.\n",
+ service->name);
+ }
+ list_for_each(list_itr, &service_table) {
+ service = list_entry(list_itr, struct service_hndl, list);
+ if (!service->admin)
+ continue;
+ if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
+ pr_err("QAT: Failed to restart service %s.\n",
+ service->name);
+ }
+ return 0;
+}
diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c
new file mode 100644
index 000000000000..5f3fa45348b4
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_transport.c
@@ -0,0 +1,567 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/delay.h>
+#include "adf_accel_devices.h"
+#include "adf_transport_internal.h"
+#include "adf_transport_access_macros.h"
+#include "adf_cfg.h"
+#include "adf_common_drv.h"
+
+static inline uint32_t adf_modulo(uint32_t data, uint32_t shift)
+{
+ uint32_t div = data >> shift;
+ uint32_t mult = div << shift;
+
+ return data - mult;
+}
+
+static inline int adf_check_ring_alignment(uint64_t addr, uint64_t size)
+{
+ if (((size - 1) & addr) != 0)
+ return -EFAULT;
+ return 0;
+}
+
+static int adf_verify_ring_size(uint32_t msg_size, uint32_t msg_num)
+{
+ int i = ADF_MIN_RING_SIZE;
+
+ for (; i <= ADF_MAX_RING_SIZE; i++)
+ if ((msg_size * msg_num) == ADF_SIZE_TO_RING_SIZE_IN_BYTES(i))
+ return i;
+
+ return ADF_DEFAULT_RING_SIZE;
+}
+
+static int adf_reserve_ring(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+ spin_lock(&bank->lock);
+ if (bank->ring_mask & (1 << ring)) {
+ spin_unlock(&bank->lock);
+ return -EFAULT;
+ }
+ bank->ring_mask |= (1 << ring);
+ spin_unlock(&bank->lock);
+ return 0;
+}
+
+static void adf_unreserve_ring(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+ spin_lock(&bank->lock);
+ bank->ring_mask &= ~(1 << ring);
+ spin_unlock(&bank->lock);
+}
+
+static void adf_enable_ring_irq(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+ spin_lock_bh(&bank->lock);
+ bank->irq_mask |= (1 << ring);
+ spin_unlock_bh(&bank->lock);
+ WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask);
+ WRITE_CSR_INT_COL_CTL(bank->csr_addr, bank->bank_number,
+ bank->irq_coalesc_timer);
+}
+
+static void adf_disable_ring_irq(struct adf_etr_bank_data *bank, uint32_t ring)
+{
+ spin_lock_bh(&bank->lock);
+ bank->irq_mask &= ~(1 << ring);
+ spin_unlock_bh(&bank->lock);
+ WRITE_CSR_INT_COL_EN(bank->csr_addr, bank->bank_number, bank->irq_mask);
+}
+
+int adf_send_message(struct adf_etr_ring_data *ring, uint32_t *msg)
+{
+ if (atomic_add_return(1, ring->inflights) >
+ ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) {
+ atomic_dec(ring->inflights);
+ return -EAGAIN;
+ }
+ spin_lock_bh(&ring->lock);
+ memcpy(ring->base_addr + ring->tail, msg,
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
+
+ ring->tail = adf_modulo(ring->tail +
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
+ ADF_RING_SIZE_MODULO(ring->ring_size));
+ WRITE_CSR_RING_TAIL(ring->bank->csr_addr, ring->bank->bank_number,
+ ring->ring_number, ring->tail);
+ spin_unlock_bh(&ring->lock);
+ return 0;
+}
+
+static int adf_handle_response(struct adf_etr_ring_data *ring)
+{
+ uint32_t msg_counter = 0;
+ uint32_t *msg = (uint32_t *)(ring->base_addr + ring->head);
+
+ while (*msg != ADF_RING_EMPTY_SIG) {
+ ring->callback((uint32_t *)msg);
+ *msg = ADF_RING_EMPTY_SIG;
+ ring->head = adf_modulo(ring->head +
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
+ ADF_RING_SIZE_MODULO(ring->ring_size));
+ msg_counter++;
+ msg = (uint32_t *)(ring->base_addr + ring->head);
+ }
+ if (msg_counter > 0) {
+ WRITE_CSR_RING_HEAD(ring->bank->csr_addr,
+ ring->bank->bank_number,
+ ring->ring_number, ring->head);
+ atomic_sub(msg_counter, ring->inflights);
+ }
+ return 0;
+}
+
+static void adf_configure_tx_ring(struct adf_etr_ring_data *ring)
+{
+ uint32_t ring_config = BUILD_RING_CONFIG(ring->ring_size);
+
+ WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, ring->bank->bank_number,
+ ring->ring_number, ring_config);
+}
+
+static void adf_configure_rx_ring(struct adf_etr_ring_data *ring)
+{
+ uint32_t ring_config =
+ BUILD_RESP_RING_CONFIG(ring->ring_size,
+ ADF_RING_NEAR_WATERMARK_512,
+ ADF_RING_NEAR_WATERMARK_0);
+
+ WRITE_CSR_RING_CONFIG(ring->bank->csr_addr, ring->bank->bank_number,
+ ring->ring_number, ring_config);
+}
+
+static int adf_init_ring(struct adf_etr_ring_data *ring)
+{
+ struct adf_etr_bank_data *bank = ring->bank;
+ struct adf_accel_dev *accel_dev = bank->accel_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint64_t ring_base;
+ uint32_t ring_size_bytes =
+ ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size);
+
+ ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes);
+ ring->base_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
+ ring_size_bytes, &ring->dma_addr,
+ GFP_KERNEL);
+ if (!ring->base_addr)
+ return -ENOMEM;
+
+ memset(ring->base_addr, 0x7F, ring_size_bytes);
+ /* The base_addr has to be aligned to the size of the buffer */
+ if (adf_check_ring_alignment(ring->dma_addr, ring_size_bytes)) {
+ pr_err("QAT: Ring address not aligned\n");
+ dma_free_coherent(&GET_DEV(accel_dev), ring_size_bytes,
+ ring->base_addr, ring->dma_addr);
+ return -EFAULT;
+ }
+
+ if (hw_data->tx_rings_mask & (1 << ring->ring_number))
+ adf_configure_tx_ring(ring);
+
+ else
+ adf_configure_rx_ring(ring);
+
+ ring_base = BUILD_RING_BASE_ADDR(ring->dma_addr, ring->ring_size);
+ WRITE_CSR_RING_BASE(ring->bank->csr_addr, ring->bank->bank_number,
+ ring->ring_number, ring_base);
+ spin_lock_init(&ring->lock);
+ return 0;
+}
+
+static void adf_cleanup_ring(struct adf_etr_ring_data *ring)
+{
+ uint32_t ring_size_bytes =
+ ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size);
+ ring_size_bytes = ADF_RING_SIZE_BYTES_MIN(ring_size_bytes);
+
+ if (ring->base_addr) {
+ memset(ring->base_addr, 0x7F, ring_size_bytes);
+ dma_free_coherent(&GET_DEV(ring->bank->accel_dev),
+ ring_size_bytes, ring->base_addr,
+ ring->dma_addr);
+ }
+}
+
+int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+ uint32_t bank_num, uint32_t num_msgs,
+ uint32_t msg_size, const char *ring_name,
+ adf_callback_fn callback, int poll_mode,
+ struct adf_etr_ring_data **ring_ptr)
+{
+ struct adf_etr_data *transport_data = accel_dev->transport;
+ struct adf_etr_bank_data *bank;
+ struct adf_etr_ring_data *ring;
+ char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+ uint32_t ring_num;
+ int ret;
+
+ if (bank_num >= GET_MAX_BANKS(accel_dev)) {
+ pr_err("QAT: Invalid bank number\n");
+ return -EFAULT;
+ }
+ if (msg_size > ADF_MSG_SIZE_TO_BYTES(ADF_MAX_MSG_SIZE)) {
+ pr_err("QAT: Invalid msg size\n");
+ return -EFAULT;
+ }
+ if (ADF_MAX_INFLIGHTS(adf_verify_ring_size(msg_size, num_msgs),
+ ADF_BYTES_TO_MSG_SIZE(msg_size)) < 2) {
+ pr_err("QAT: Invalid ring size for given msg size\n");
+ return -EFAULT;
+ }
+ if (adf_cfg_get_param_value(accel_dev, section, ring_name, val)) {
+ pr_err("QAT: Section %s, no such entry : %s\n",
+ section, ring_name);
+ return -EFAULT;
+ }
+ if (kstrtouint(val, 10, &ring_num)) {
+ pr_err("QAT: Can't get ring number\n");
+ return -EFAULT;
+ }
+
+ bank = &transport_data->banks[bank_num];
+ if (adf_reserve_ring(bank, ring_num)) {
+ pr_err("QAT: Ring %d, %s already exists.\n",
+ ring_num, ring_name);
+ return -EFAULT;
+ }
+ ring = &bank->rings[ring_num];
+ ring->ring_number = ring_num;
+ ring->bank = bank;
+ ring->callback = callback;
+ ring->msg_size = ADF_BYTES_TO_MSG_SIZE(msg_size);
+ ring->ring_size = adf_verify_ring_size(msg_size, num_msgs);
+ ring->head = 0;
+ ring->tail = 0;
+ atomic_set(ring->inflights, 0);
+ ret = adf_init_ring(ring);
+ if (ret)
+ goto err;
+
+ /* Enable HW arbitration for the given ring */
+ accel_dev->hw_device->hw_arb_ring_enable(ring);
+
+ if (adf_ring_debugfs_add(ring, ring_name)) {
+ pr_err("QAT: Couldn't add ring debugfs entry\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ /* Enable interrupts if needed */
+ if (callback && (!poll_mode))
+ adf_enable_ring_irq(bank, ring->ring_number);
+ *ring_ptr = ring;
+ return 0;
+err:
+ adf_cleanup_ring(ring);
+ adf_unreserve_ring(bank, ring_num);
+ accel_dev->hw_device->hw_arb_ring_disable(ring);
+ return ret;
+}
+
+void adf_remove_ring(struct adf_etr_ring_data *ring)
+{
+ struct adf_etr_bank_data *bank = ring->bank;
+ struct adf_accel_dev *accel_dev = bank->accel_dev;
+
+ /* Disable interrupts for the given ring */
+ adf_disable_ring_irq(bank, ring->ring_number);
+
+ /* Clear PCI config space */
+ WRITE_CSR_RING_CONFIG(bank->csr_addr, bank->bank_number,
+ ring->ring_number, 0);
+ WRITE_CSR_RING_BASE(bank->csr_addr, bank->bank_number,
+ ring->ring_number, 0);
+ adf_ring_debugfs_rm(ring);
+ adf_unreserve_ring(bank, ring->ring_number);
+ /* Disable HW arbitration for the given ring */
+ accel_dev->hw_device->hw_arb_ring_disable(ring);
+ adf_cleanup_ring(ring);
+}
+
+static void adf_ring_response_handler(struct adf_etr_bank_data *bank)
+{
+ uint32_t empty_rings, i;
+
+ empty_rings = READ_CSR_E_STAT(bank->csr_addr, bank->bank_number);
+ empty_rings = ~empty_rings & bank->irq_mask;
+
+ for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; ++i) {
+ if (empty_rings & (1 << i))
+ adf_handle_response(&bank->rings[i]);
+ }
+}
+
+/**
+ * adf_response_handler() - Bottom half handler response handler
+ * @bank_addr: Address of a ring bank for with the BH was scheduled.
+ *
+ * Function is the bottom half handler for the response from acceleration
+ * device. There is one handler for every ring bank. Function checks all
+ * communication rings in the bank.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_response_handler(unsigned long bank_addr)
+{
+ struct adf_etr_bank_data *bank = (void *)bank_addr;
+
+ /* Handle all the responses nad reenable IRQs */
+ adf_ring_response_handler(bank);
+ WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number,
+ bank->irq_mask);
+}
+EXPORT_SYMBOL_GPL(adf_response_handler);
+
+static inline int adf_get_cfg_int(struct adf_accel_dev *accel_dev,
+ const char *section, const char *format,
+ uint32_t key, uint32_t *value)
+{
+ char key_buf[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ char val_buf[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+
+ snprintf(key_buf, ADF_CFG_MAX_KEY_LEN_IN_BYTES, format, key);
+
+ if (adf_cfg_get_param_value(accel_dev, section, key_buf, val_buf))
+ return -EFAULT;
+
+ if (kstrtouint(val_buf, 10, value))
+ return -EFAULT;
+ return 0;
+}
+
+static void adf_enable_coalesc(struct adf_etr_bank_data *bank,
+ const char *section, uint32_t bank_num_in_accel)
+{
+ if (adf_get_cfg_int(bank->accel_dev, section,
+ ADF_ETRMGR_COALESCE_TIMER_FORMAT,
+ bank_num_in_accel, &bank->irq_coalesc_timer))
+ bank->irq_coalesc_timer = ADF_COALESCING_DEF_TIME;
+
+ if (ADF_COALESCING_MAX_TIME < bank->irq_coalesc_timer ||
+ ADF_COALESCING_MIN_TIME > bank->irq_coalesc_timer)
+ bank->irq_coalesc_timer = ADF_COALESCING_DEF_TIME;
+}
+
+static int adf_init_bank(struct adf_accel_dev *accel_dev,
+ struct adf_etr_bank_data *bank,
+ uint32_t bank_num, void __iomem *csr_addr)
+{
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct adf_etr_ring_data *ring;
+ struct adf_etr_ring_data *tx_ring;
+ uint32_t i, coalesc_enabled;
+
+ memset(bank, 0, sizeof(*bank));
+ bank->bank_number = bank_num;
+ bank->csr_addr = csr_addr;
+ bank->accel_dev = accel_dev;
+ spin_lock_init(&bank->lock);
+
+ /* Enable IRQ coalescing always. This will allow to use
+ * the optimised flag and coalesc register.
+ * If it is disabled in the config file just use min time value */
+ if (adf_get_cfg_int(accel_dev, "Accelerator0",
+ ADF_ETRMGR_COALESCING_ENABLED_FORMAT,
+ bank_num, &coalesc_enabled) && coalesc_enabled)
+ adf_enable_coalesc(bank, "Accelerator0", bank_num);
+ else
+ bank->irq_coalesc_timer = ADF_COALESCING_MIN_TIME;
+
+ for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+ WRITE_CSR_RING_CONFIG(csr_addr, bank_num, i, 0);
+ WRITE_CSR_RING_BASE(csr_addr, bank_num, i, 0);
+ ring = &bank->rings[i];
+ if (hw_data->tx_rings_mask & (1 << i)) {
+ ring->inflights = kzalloc_node(sizeof(atomic_t),
+ GFP_KERNEL,
+ accel_dev->numa_node);
+ if (!ring->inflights)
+ goto err;
+ } else {
+ if (i < hw_data->tx_rx_gap) {
+ pr_err("QAT: Invalid tx rings mask config\n");
+ goto err;
+ }
+ tx_ring = &bank->rings[i - hw_data->tx_rx_gap];
+ ring->inflights = tx_ring->inflights;
+ }
+ }
+ if (adf_bank_debugfs_add(bank)) {
+ pr_err("QAT: Failed to add bank debugfs entry\n");
+ goto err;
+ }
+
+ WRITE_CSR_INT_SRCSEL(csr_addr, bank_num);
+ return 0;
+err:
+ for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+ ring = &bank->rings[i];
+ if (hw_data->tx_rings_mask & (1 << i) && ring->inflights)
+ kfree(ring->inflights);
+ }
+ return -ENOMEM;
+}
+
+/**
+ * adf_init_etr_data() - Initialize transport rings for acceleration device
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function is the initializes the communications channels (rings) to the
+ * acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int adf_init_etr_data(struct adf_accel_dev *accel_dev)
+{
+ struct adf_etr_data *etr_data;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ void __iomem *csr_addr;
+ uint32_t size;
+ uint32_t num_banks = 0;
+ int i, ret;
+
+ etr_data = kzalloc_node(sizeof(*etr_data), GFP_KERNEL,
+ accel_dev->numa_node);
+ if (!etr_data)
+ return -ENOMEM;
+
+ num_banks = GET_MAX_BANKS(accel_dev);
+ size = num_banks * sizeof(struct adf_etr_bank_data);
+ etr_data->banks = kzalloc_node(size, GFP_KERNEL, accel_dev->numa_node);
+ if (!etr_data->banks) {
+ ret = -ENOMEM;
+ goto err_bank;
+ }
+
+ accel_dev->transport = etr_data;
+ i = hw_data->get_etr_bar_id(hw_data);
+ csr_addr = accel_dev->accel_pci_dev.pci_bars[i].virt_addr;
+
+ /* accel_dev->debugfs_dir should always be non-NULL here */
+ etr_data->debug = debugfs_create_dir("transport",
+ accel_dev->debugfs_dir);
+ if (!etr_data->debug) {
+ pr_err("QAT: Unable to create transport debugfs entry\n");
+ ret = -ENOENT;
+ goto err_bank_debug;
+ }
+
+ for (i = 0; i < num_banks; i++) {
+ ret = adf_init_bank(accel_dev, &etr_data->banks[i], i,
+ csr_addr);
+ if (ret)
+ goto err_bank_all;
+ }
+
+ return 0;
+
+err_bank_all:
+ debugfs_remove(etr_data->debug);
+err_bank_debug:
+ kfree(etr_data->banks);
+err_bank:
+ kfree(etr_data);
+ accel_dev->transport = NULL;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(adf_init_etr_data);
+
+static void cleanup_bank(struct adf_etr_bank_data *bank)
+{
+ uint32_t i;
+
+ for (i = 0; i < ADF_ETR_MAX_RINGS_PER_BANK; i++) {
+ struct adf_accel_dev *accel_dev = bank->accel_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct adf_etr_ring_data *ring = &bank->rings[i];
+
+ if (bank->ring_mask & (1 << i))
+ adf_cleanup_ring(ring);
+
+ if (hw_data->tx_rings_mask & (1 << i))
+ kfree(ring->inflights);
+ }
+ adf_bank_debugfs_rm(bank);
+ memset(bank, 0, sizeof(*bank));
+}
+
+static void adf_cleanup_etr_handles(struct adf_accel_dev *accel_dev)
+{
+ struct adf_etr_data *etr_data = accel_dev->transport;
+ uint32_t i, num_banks = GET_MAX_BANKS(accel_dev);
+
+ for (i = 0; i < num_banks; i++)
+ cleanup_bank(&etr_data->banks[i]);
+}
+
+/**
+ * adf_cleanup_etr_data() - Clear transport rings for acceleration device
+ * @accel_dev: Pointer to acceleration device.
+ *
+ * Function is the clears the communications channels (rings) of the
+ * acceleration device accel_dev.
+ * To be used by QAT device specific drivers.
+ *
+ * Return: void
+ */
+void adf_cleanup_etr_data(struct adf_accel_dev *accel_dev)
+{
+ struct adf_etr_data *etr_data = accel_dev->transport;
+
+ if (etr_data) {
+ adf_cleanup_etr_handles(accel_dev);
+ debugfs_remove(etr_data->debug);
+ kfree(etr_data->banks);
+ kfree(etr_data);
+ accel_dev->transport = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(adf_cleanup_etr_data);
diff --git a/drivers/crypto/qat/qat_common/adf_transport.h b/drivers/crypto/qat/qat_common/adf_transport.h
new file mode 100644
index 000000000000..386485bd9c95
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_transport.h
@@ -0,0 +1,63 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_TRANSPORT_H
+#define ADF_TRANSPORT_H
+
+#include "adf_accel_devices.h"
+
+struct adf_etr_ring_data;
+
+typedef void (*adf_callback_fn)(void *resp_msg);
+
+int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section,
+ uint32_t bank_num, uint32_t num_mgs, uint32_t msg_size,
+ const char *ring_name, adf_callback_fn callback,
+ int poll_mode, struct adf_etr_ring_data **ring_ptr);
+
+int adf_send_message(struct adf_etr_ring_data *ring, uint32_t *msg);
+void adf_remove_ring(struct adf_etr_ring_data *ring);
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_transport_access_macros.h b/drivers/crypto/qat/qat_common/adf_transport_access_macros.h
new file mode 100644
index 000000000000..91d88d676580
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_transport_access_macros.h
@@ -0,0 +1,160 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_TRANSPORT_ACCESS_MACROS_H
+#define ADF_TRANSPORT_ACCESS_MACROS_H
+
+#include "adf_accel_devices.h"
+#define ADF_BANK_INT_SRC_SEL_MASK_0 0x4444444CUL
+#define ADF_BANK_INT_SRC_SEL_MASK_X 0x44444444UL
+#define ADF_RING_CSR_RING_CONFIG 0x000
+#define ADF_RING_CSR_RING_LBASE 0x040
+#define ADF_RING_CSR_RING_UBASE 0x080
+#define ADF_RING_CSR_RING_HEAD 0x0C0
+#define ADF_RING_CSR_RING_TAIL 0x100
+#define ADF_RING_CSR_E_STAT 0x14C
+#define ADF_RING_CSR_INT_SRCSEL 0x174
+#define ADF_RING_CSR_INT_SRCSEL_2 0x178
+#define ADF_RING_CSR_INT_COL_EN 0x17C
+#define ADF_RING_CSR_INT_COL_CTL 0x180
+#define ADF_RING_CSR_INT_FLAG_AND_COL 0x184
+#define ADF_RING_CSR_INT_COL_CTL_ENABLE 0x80000000
+#define ADF_RING_BUNDLE_SIZE 0x1000
+#define ADF_RING_CONFIG_NEAR_FULL_WM 0x0A
+#define ADF_RING_CONFIG_NEAR_EMPTY_WM 0x05
+#define ADF_COALESCING_MIN_TIME 0x1FF
+#define ADF_COALESCING_MAX_TIME 0xFFFFF
+#define ADF_COALESCING_DEF_TIME 0x27FF
+#define ADF_RING_NEAR_WATERMARK_512 0x08
+#define ADF_RING_NEAR_WATERMARK_0 0x00
+#define ADF_RING_EMPTY_SIG 0x7F7F7F7F
+
+/* Valid internal ring size values */
+#define ADF_RING_SIZE_128 0x01
+#define ADF_RING_SIZE_256 0x02
+#define ADF_RING_SIZE_512 0x03
+#define ADF_RING_SIZE_4K 0x06
+#define ADF_RING_SIZE_16K 0x08
+#define ADF_RING_SIZE_4M 0x10
+#define ADF_MIN_RING_SIZE ADF_RING_SIZE_128
+#define ADF_MAX_RING_SIZE ADF_RING_SIZE_4M
+#define ADF_DEFAULT_RING_SIZE ADF_RING_SIZE_16K
+
+/* Valid internal msg size values internal */
+#define ADF_MSG_SIZE_32 0x01
+#define ADF_MSG_SIZE_64 0x02
+#define ADF_MSG_SIZE_128 0x04
+#define ADF_MIN_MSG_SIZE ADF_MSG_SIZE_32
+#define ADF_MAX_MSG_SIZE ADF_MSG_SIZE_128
+
+/* Size to bytes conversion macros for ring and msg values */
+#define ADF_MSG_SIZE_TO_BYTES(SIZE) (SIZE << 5)
+#define ADF_BYTES_TO_MSG_SIZE(SIZE) (SIZE >> 5)
+#define ADF_SIZE_TO_RING_SIZE_IN_BYTES(SIZE) ((1 << (SIZE - 1)) << 7)
+#define ADF_RING_SIZE_IN_BYTES_TO_SIZE(SIZE) ((1 << (SIZE - 1)) >> 7)
+
+/* Minimum ring bufer size for memory allocation */
+#define ADF_RING_SIZE_BYTES_MIN(SIZE) ((SIZE < ADF_RING_SIZE_4K) ? \
+ ADF_RING_SIZE_4K : SIZE)
+#define ADF_RING_SIZE_MODULO(SIZE) (SIZE + 0x6)
+#define ADF_MAX_INFLIGHTS(RING_SIZE, MSG_SIZE) \
+ ((((1 << (RING_SIZE - 1)) << 4) >> MSG_SIZE) - 1)
+#define BUILD_RING_CONFIG(size) \
+ ((ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_FULL_WM) \
+ | (ADF_RING_NEAR_WATERMARK_0 << ADF_RING_CONFIG_NEAR_EMPTY_WM) \
+ | size)
+#define BUILD_RESP_RING_CONFIG(size, watermark_nf, watermark_ne) \
+ ((watermark_nf << ADF_RING_CONFIG_NEAR_FULL_WM) \
+ | (watermark_ne << ADF_RING_CONFIG_NEAR_EMPTY_WM) \
+ | size)
+#define BUILD_RING_BASE_ADDR(addr, size) \
+ ((addr >> 6) & (0xFFFFFFFFFFFFFFFFULL << size))
+#define READ_CSR_RING_HEAD(csr_base_addr, bank, ring) \
+ ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_HEAD + (ring << 2))
+#define READ_CSR_RING_TAIL(csr_base_addr, bank, ring) \
+ ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_TAIL + (ring << 2))
+#define READ_CSR_E_STAT(csr_base_addr, bank) \
+ ADF_CSR_RD(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_E_STAT)
+#define WRITE_CSR_RING_CONFIG(csr_base_addr, bank, ring, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_CONFIG + (ring << 2), value)
+#define WRITE_CSR_RING_BASE(csr_base_addr, bank, ring, value) \
+do { \
+ uint32_t l_base = 0, u_base = 0; \
+ l_base = (uint32_t)(value & 0xFFFFFFFF); \
+ u_base = (uint32_t)((value & 0xFFFFFFFF00000000ULL) >> 32); \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_LBASE + (ring << 2), l_base); \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_UBASE + (ring << 2), u_base); \
+} while (0)
+#define WRITE_CSR_RING_HEAD(csr_base_addr, bank, ring, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_HEAD + (ring << 2), value)
+#define WRITE_CSR_RING_TAIL(csr_base_addr, bank, ring, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_RING_TAIL + (ring << 2), value)
+#define WRITE_CSR_INT_SRCSEL(csr_base_addr, bank) \
+do { \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_INT_SRCSEL, ADF_BANK_INT_SRC_SEL_MASK_0); \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_INT_SRCSEL_2, ADF_BANK_INT_SRC_SEL_MASK_X); \
+} while (0)
+#define WRITE_CSR_INT_COL_EN(csr_base_addr, bank, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_INT_COL_EN, value)
+#define WRITE_CSR_INT_COL_CTL(csr_base_addr, bank, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_INT_COL_CTL, \
+ ADF_RING_CSR_INT_COL_CTL_ENABLE | value)
+#define WRITE_CSR_INT_FLAG_AND_COL(csr_base_addr, bank, value) \
+ ADF_CSR_WR(csr_base_addr, (ADF_RING_BUNDLE_SIZE * bank) + \
+ ADF_RING_CSR_INT_FLAG_AND_COL, value)
+#endif
diff --git a/drivers/crypto/qat/qat_common/adf_transport_debug.c b/drivers/crypto/qat/qat_common/adf_transport_debug.c
new file mode 100644
index 000000000000..6b6974553514
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_transport_debug.c
@@ -0,0 +1,304 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include "adf_accel_devices.h"
+#include "adf_transport_internal.h"
+#include "adf_transport_access_macros.h"
+
+static DEFINE_MUTEX(ring_read_lock);
+static DEFINE_MUTEX(bank_read_lock);
+
+static void *adf_ring_start(struct seq_file *sfile, loff_t *pos)
+{
+ struct adf_etr_ring_data *ring = sfile->private;
+
+ mutex_lock(&ring_read_lock);
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
+ return NULL;
+
+ return ring->base_addr +
+ (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
+}
+
+static void *adf_ring_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+ struct adf_etr_ring_data *ring = sfile->private;
+
+ if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
+ return NULL;
+
+ return ring->base_addr +
+ (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
+}
+
+static int adf_ring_show(struct seq_file *sfile, void *v)
+{
+ struct adf_etr_ring_data *ring = sfile->private;
+ struct adf_etr_bank_data *bank = ring->bank;
+ uint32_t *msg = v;
+ void __iomem *csr = ring->bank->csr_addr;
+ int i, x;
+
+ if (v == SEQ_START_TOKEN) {
+ int head, tail, empty;
+
+ head = READ_CSR_RING_HEAD(csr, bank->bank_number,
+ ring->ring_number);
+ tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
+ ring->ring_number);
+ empty = READ_CSR_E_STAT(csr, bank->bank_number);
+
+ seq_puts(sfile, "------- Ring configuration -------\n");
+ seq_printf(sfile, "ring num %d, bank num %d\n",
+ ring->ring_number, ring->bank->bank_number);
+ seq_printf(sfile, "head %x, tail %x, empty: %d\n",
+ head, tail, (empty & 1 << ring->ring_number)
+ >> ring->ring_number);
+ seq_printf(sfile, "ring size %d, msg size %d\n",
+ ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size),
+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
+ seq_puts(sfile, "----------- Ring data ------------\n");
+ return 0;
+ }
+ seq_printf(sfile, "%p:", msg);
+ x = 0;
+ i = 0;
+ for (; i < (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2); i++) {
+ seq_printf(sfile, " %08X", *(msg + i));
+ if ((ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2) != i + 1 &&
+ (++x == 8)) {
+ seq_printf(sfile, "\n%p:", msg + i + 1);
+ x = 0;
+ }
+ }
+ seq_puts(sfile, "\n");
+ return 0;
+}
+
+static void adf_ring_stop(struct seq_file *sfile, void *v)
+{
+ mutex_unlock(&ring_read_lock);
+}
+
+static const struct seq_operations adf_ring_sops = {
+ .start = adf_ring_start,
+ .next = adf_ring_next,
+ .stop = adf_ring_stop,
+ .show = adf_ring_show
+};
+
+static int adf_ring_open(struct inode *inode, struct file *file)
+{
+ int ret = seq_open(file, &adf_ring_sops);
+
+ if (!ret) {
+ struct seq_file *seq_f = file->private_data;
+
+ seq_f->private = inode->i_private;
+ }
+ return ret;
+}
+
+static const struct file_operations adf_ring_debug_fops = {
+ .open = adf_ring_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
+{
+ struct adf_etr_ring_debug_entry *ring_debug;
+ char entry_name[8];
+
+ ring_debug = kzalloc(sizeof(*ring_debug), GFP_KERNEL);
+ if (!ring_debug)
+ return -ENOMEM;
+
+ strlcpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name));
+ snprintf(entry_name, sizeof(entry_name), "ring_%02d",
+ ring->ring_number);
+
+ ring_debug->debug = debugfs_create_file(entry_name, S_IRUSR,
+ ring->bank->bank_debug_dir,
+ ring, &adf_ring_debug_fops);
+ if (!ring_debug->debug) {
+ pr_err("QAT: Failed to create ring debug entry.\n");
+ kfree(ring_debug);
+ return -EFAULT;
+ }
+ ring->ring_debug = ring_debug;
+ return 0;
+}
+
+void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring)
+{
+ if (ring->ring_debug) {
+ debugfs_remove(ring->ring_debug->debug);
+ kfree(ring->ring_debug);
+ ring->ring_debug = NULL;
+ }
+}
+
+static void *adf_bank_start(struct seq_file *sfile, loff_t *pos)
+{
+ mutex_lock(&bank_read_lock);
+ if (*pos == 0)
+ return SEQ_START_TOKEN;
+
+ if (*pos >= ADF_ETR_MAX_RINGS_PER_BANK)
+ return NULL;
+
+ return pos;
+}
+
+static void *adf_bank_next(struct seq_file *sfile, void *v, loff_t *pos)
+{
+ if (++(*pos) >= ADF_ETR_MAX_RINGS_PER_BANK)
+ return NULL;
+
+ return pos;
+}
+
+static int adf_bank_show(struct seq_file *sfile, void *v)
+{
+ struct adf_etr_bank_data *bank = sfile->private;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(sfile, "------- Bank %d configuration -------\n",
+ bank->bank_number);
+ } else {
+ int ring_id = *((int *)v) - 1;
+ struct adf_etr_ring_data *ring = &bank->rings[ring_id];
+ void __iomem *csr = bank->csr_addr;
+ int head, tail, empty;
+
+ if (!(bank->ring_mask & 1 << ring_id))
+ return 0;
+
+ head = READ_CSR_RING_HEAD(csr, bank->bank_number,
+ ring->ring_number);
+ tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
+ ring->ring_number);
+ empty = READ_CSR_E_STAT(csr, bank->bank_number);
+
+ seq_printf(sfile,
+ "ring num %02d, head %04x, tail %04x, empty: %d\n",
+ ring->ring_number, head, tail,
+ (empty & 1 << ring->ring_number) >>
+ ring->ring_number);
+ }
+ return 0;
+}
+
+static void adf_bank_stop(struct seq_file *sfile, void *v)
+{
+ mutex_unlock(&bank_read_lock);
+}
+
+static const struct seq_operations adf_bank_sops = {
+ .start = adf_bank_start,
+ .next = adf_bank_next,
+ .stop = adf_bank_stop,
+ .show = adf_bank_show
+};
+
+static int adf_bank_open(struct inode *inode, struct file *file)
+{
+ int ret = seq_open(file, &adf_bank_sops);
+
+ if (!ret) {
+ struct seq_file *seq_f = file->private_data;
+
+ seq_f->private = inode->i_private;
+ }
+ return ret;
+}
+
+static const struct file_operations adf_bank_debug_fops = {
+ .open = adf_bank_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
+{
+ struct adf_accel_dev *accel_dev = bank->accel_dev;
+ struct dentry *parent = accel_dev->transport->debug;
+ char name[8];
+
+ snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
+ bank->bank_debug_dir = debugfs_create_dir(name, parent);
+ if (!bank->bank_debug_dir) {
+ pr_err("QAT: Failed to create bank debug dir.\n");
+ return -EFAULT;
+ }
+
+ bank->bank_debug_cfg = debugfs_create_file("config", S_IRUSR,
+ bank->bank_debug_dir, bank,
+ &adf_bank_debug_fops);
+ if (!bank->bank_debug_cfg) {
+ pr_err("QAT: Failed to create bank debug entry.\n");
+ debugfs_remove(bank->bank_debug_dir);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank)
+{
+ debugfs_remove(bank->bank_debug_cfg);
+ debugfs_remove(bank->bank_debug_dir);
+}
diff --git a/drivers/crypto/qat/qat_common/adf_transport_internal.h b/drivers/crypto/qat/qat_common/adf_transport_internal.h
new file mode 100644
index 000000000000..f854bac276b0
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/adf_transport_internal.h
@@ -0,0 +1,118 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_TRANSPORT_INTRN_H
+#define ADF_TRANSPORT_INTRN_H
+
+#include <linux/interrupt.h>
+#include <linux/atomic.h>
+#include <linux/spinlock_types.h>
+#include "adf_transport.h"
+
+struct adf_etr_ring_debug_entry {
+ char ring_name[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ struct dentry *debug;
+};
+
+struct adf_etr_ring_data {
+ void *base_addr;
+ atomic_t *inflights;
+ spinlock_t lock; /* protects ring data struct */
+ adf_callback_fn callback;
+ struct adf_etr_bank_data *bank;
+ dma_addr_t dma_addr;
+ uint16_t head;
+ uint16_t tail;
+ uint8_t ring_number;
+ uint8_t ring_size;
+ uint8_t msg_size;
+ uint8_t reserved;
+ struct adf_etr_ring_debug_entry *ring_debug;
+} __packed;
+
+struct adf_etr_bank_data {
+ struct adf_etr_ring_data rings[ADF_ETR_MAX_RINGS_PER_BANK];
+ struct tasklet_struct resp_hanlder;
+ void __iomem *csr_addr;
+ struct adf_accel_dev *accel_dev;
+ uint32_t irq_coalesc_timer;
+ uint16_t ring_mask;
+ uint16_t irq_mask;
+ spinlock_t lock; /* protects bank data struct */
+ struct dentry *bank_debug_dir;
+ struct dentry *bank_debug_cfg;
+ uint32_t bank_number;
+} __packed;
+
+struct adf_etr_data {
+ struct adf_etr_bank_data *banks;
+ struct dentry *debug;
+};
+
+void adf_response_handler(unsigned long bank_addr);
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+int adf_bank_debugfs_add(struct adf_etr_bank_data *bank);
+void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank);
+int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name);
+void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring);
+#else
+static inline int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
+{
+ return 0;
+}
+
+#define adf_bank_debugfs_rm(bank) do {} while (0)
+
+static inline int adf_ring_debugfs_add(struct adf_etr_ring_data *ring,
+ const char *name)
+{
+ return 0;
+}
+
+#define adf_ring_debugfs_rm(ring) do {} while (0)
+#endif
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_fw.h b/drivers/crypto/qat/qat_common/icp_qat_fw.h
new file mode 100644
index 000000000000..f1e30e24a419
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_fw.h
@@ -0,0 +1,316 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _ICP_QAT_FW_H_
+#define _ICP_QAT_FW_H_
+#include <linux/types.h>
+#include "icp_qat_hw.h"
+
+#define QAT_FIELD_SET(flags, val, bitpos, mask) \
+{ (flags) = (((flags) & (~((mask) << (bitpos)))) | \
+ (((val) & (mask)) << (bitpos))) ; }
+
+#define QAT_FIELD_GET(flags, bitpos, mask) \
+ (((flags) >> (bitpos)) & (mask))
+
+#define ICP_QAT_FW_REQ_DEFAULT_SZ 128
+#define ICP_QAT_FW_RESP_DEFAULT_SZ 32
+#define ICP_QAT_FW_COMN_ONE_BYTE_SHIFT 8
+#define ICP_QAT_FW_COMN_SINGLE_BYTE_MASK 0xFF
+#define ICP_QAT_FW_NUM_LONGWORDS_1 1
+#define ICP_QAT_FW_NUM_LONGWORDS_2 2
+#define ICP_QAT_FW_NUM_LONGWORDS_3 3
+#define ICP_QAT_FW_NUM_LONGWORDS_4 4
+#define ICP_QAT_FW_NUM_LONGWORDS_5 5
+#define ICP_QAT_FW_NUM_LONGWORDS_6 6
+#define ICP_QAT_FW_NUM_LONGWORDS_7 7
+#define ICP_QAT_FW_NUM_LONGWORDS_10 10
+#define ICP_QAT_FW_NUM_LONGWORDS_13 13
+#define ICP_QAT_FW_NULL_REQ_SERV_ID 1
+
+enum icp_qat_fw_comn_resp_serv_id {
+ ICP_QAT_FW_COMN_RESP_SERV_NULL,
+ ICP_QAT_FW_COMN_RESP_SERV_CPM_FW,
+ ICP_QAT_FW_COMN_RESP_SERV_DELIMITER
+};
+
+enum icp_qat_fw_comn_request_id {
+ ICP_QAT_FW_COMN_REQ_NULL = 0,
+ ICP_QAT_FW_COMN_REQ_CPM_FW_PKE = 3,
+ ICP_QAT_FW_COMN_REQ_CPM_FW_LA = 4,
+ ICP_QAT_FW_COMN_REQ_CPM_FW_DMA = 7,
+ ICP_QAT_FW_COMN_REQ_CPM_FW_COMP = 9,
+ ICP_QAT_FW_COMN_REQ_DELIMITER
+};
+
+struct icp_qat_fw_comn_req_hdr_cd_pars {
+ union {
+ struct {
+ uint64_t content_desc_addr;
+ uint16_t content_desc_resrvd1;
+ uint8_t content_desc_params_sz;
+ uint8_t content_desc_hdr_resrvd2;
+ uint32_t content_desc_resrvd3;
+ } s;
+ struct {
+ uint32_t serv_specif_fields[4];
+ } s1;
+ } u;
+};
+
+struct icp_qat_fw_comn_req_mid {
+ uint64_t opaque_data;
+ uint64_t src_data_addr;
+ uint64_t dest_data_addr;
+ uint32_t src_length;
+ uint32_t dst_length;
+};
+
+struct icp_qat_fw_comn_req_cd_ctrl {
+ uint32_t content_desc_ctrl_lw[ICP_QAT_FW_NUM_LONGWORDS_5];
+};
+
+struct icp_qat_fw_comn_req_hdr {
+ uint8_t resrvd1;
+ uint8_t service_cmd_id;
+ uint8_t service_type;
+ uint8_t hdr_flags;
+ uint16_t serv_specif_flags;
+ uint16_t comn_req_flags;
+};
+
+struct icp_qat_fw_comn_req_rqpars {
+ uint32_t serv_specif_rqpars_lw[ICP_QAT_FW_NUM_LONGWORDS_13];
+};
+
+struct icp_qat_fw_comn_req {
+ struct icp_qat_fw_comn_req_hdr comn_hdr;
+ struct icp_qat_fw_comn_req_hdr_cd_pars cd_pars;
+ struct icp_qat_fw_comn_req_mid comn_mid;
+ struct icp_qat_fw_comn_req_rqpars serv_specif_rqpars;
+ struct icp_qat_fw_comn_req_cd_ctrl cd_ctrl;
+};
+
+struct icp_qat_fw_comn_error {
+ uint8_t xlat_err_code;
+ uint8_t cmp_err_code;
+};
+
+struct icp_qat_fw_comn_resp_hdr {
+ uint8_t resrvd1;
+ uint8_t service_id;
+ uint8_t response_type;
+ uint8_t hdr_flags;
+ struct icp_qat_fw_comn_error comn_error;
+ uint8_t comn_status;
+ uint8_t cmd_id;
+};
+
+struct icp_qat_fw_comn_resp {
+ struct icp_qat_fw_comn_resp_hdr comn_hdr;
+ uint64_t opaque_data;
+ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4];
+};
+
+#define ICP_QAT_FW_COMN_REQ_FLAG_SET 1
+#define ICP_QAT_FW_COMN_REQ_FLAG_CLR 0
+#define ICP_QAT_FW_COMN_VALID_FLAG_BITPOS 7
+#define ICP_QAT_FW_COMN_VALID_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK 0x7F
+
+#define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \
+ icp_qat_fw_comn_req_hdr_t.service_type
+
+#define ICP_QAT_FW_COMN_OV_SRV_TYPE_SET(icp_qat_fw_comn_req_hdr_t, val) \
+ icp_qat_fw_comn_req_hdr_t.service_type = val
+
+#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_GET(icp_qat_fw_comn_req_hdr_t) \
+ icp_qat_fw_comn_req_hdr_t.service_cmd_id
+
+#define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_SET(icp_qat_fw_comn_req_hdr_t, val) \
+ icp_qat_fw_comn_req_hdr_t.service_cmd_id = val
+
+#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_GET(hdr_t) \
+ ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_t.hdr_flags)
+
+#define ICP_QAT_FW_COMN_HDR_VALID_FLAG_SET(hdr_t, val) \
+ ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val)
+
+#define ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_flags) \
+ QAT_FIELD_GET(hdr_flags, \
+ ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \
+ ICP_QAT_FW_COMN_VALID_FLAG_MASK)
+
+#define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_GET(hdr_flags) \
+ (hdr_flags & ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK)
+
+#define ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) \
+ QAT_FIELD_SET((hdr_t.hdr_flags), (val), \
+ ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \
+ ICP_QAT_FW_COMN_VALID_FLAG_MASK)
+
+#define ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(valid) \
+ (((valid) & ICP_QAT_FW_COMN_VALID_FLAG_MASK) << \
+ ICP_QAT_FW_COMN_VALID_FLAG_BITPOS)
+
+#define QAT_COMN_PTR_TYPE_BITPOS 0
+#define QAT_COMN_PTR_TYPE_MASK 0x1
+#define QAT_COMN_CD_FLD_TYPE_BITPOS 1
+#define QAT_COMN_CD_FLD_TYPE_MASK 0x1
+#define QAT_COMN_PTR_TYPE_FLAT 0x0
+#define QAT_COMN_PTR_TYPE_SGL 0x1
+#define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0
+#define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1
+
+#define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \
+ ((((cdt) & QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) \
+ | (((ptr) & QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS))
+
+#define ICP_QAT_FW_COMN_PTR_TYPE_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_CD_FLD_TYPE_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_COMN_CD_FLD_TYPE_BITPOS, \
+ QAT_COMN_CD_FLD_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_PTR_TYPE_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_COMN_PTR_TYPE_BITPOS, \
+ QAT_COMN_PTR_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_COMN_CD_FLD_TYPE_BITPOS, \
+ QAT_COMN_CD_FLD_TYPE_MASK)
+
+#define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4
+#define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0
+#define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0
+#define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F
+
+#define ICP_QAT_FW_COMN_NEXT_ID_GET(cd_ctrl_hdr_t) \
+ ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) \
+ >> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+ { ((cd_ctrl_hdr_t)->next_curr_id) = ((((cd_ctrl_hdr_t)->next_curr_id) \
+ & ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK)); }
+
+#define ICP_QAT_FW_COMN_CURR_ID_GET(cd_ctrl_hdr_t) \
+ (((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+ { ((cd_ctrl_hdr_t)->next_curr_id) = ((((cd_ctrl_hdr_t)->next_curr_id) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+ ((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)); }
+
+#define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7
+#define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1
+#define QAT_COMN_RESP_CMP_STATUS_BITPOS 5
+#define QAT_COMN_RESP_CMP_STATUS_MASK 0x1
+#define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4
+#define QAT_COMN_RESP_XLAT_STATUS_MASK 0x1
+#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS 3
+#define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK 0x1
+
+#define ICP_QAT_FW_COMN_RESP_STATUS_BUILD(crypto, comp, xlat, eolb) \
+ ((((crypto) & QAT_COMN_RESP_CRYPTO_STATUS_MASK) << \
+ QAT_COMN_RESP_CRYPTO_STATUS_BITPOS) | \
+ (((comp) & QAT_COMN_RESP_CMP_STATUS_MASK) << \
+ QAT_COMN_RESP_CMP_STATUS_BITPOS) | \
+ (((xlat) & QAT_COMN_RESP_XLAT_STATUS_MASK) << \
+ QAT_COMN_RESP_XLAT_STATUS_BITPOS) | \
+ (((eolb) & QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) << \
+ QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS))
+
+#define ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(status) \
+ QAT_FIELD_GET(status, QAT_COMN_RESP_CRYPTO_STATUS_BITPOS, \
+ QAT_COMN_RESP_CRYPTO_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(status) \
+ QAT_FIELD_GET(status, QAT_COMN_RESP_CMP_STATUS_BITPOS, \
+ QAT_COMN_RESP_CMP_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(status) \
+ QAT_FIELD_GET(status, QAT_COMN_RESP_XLAT_STATUS_BITPOS, \
+ QAT_COMN_RESP_XLAT_STATUS_MASK)
+
+#define ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(status) \
+ QAT_FIELD_GET(status, QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS, \
+ QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK)
+
+#define ICP_QAT_FW_COMN_STATUS_FLAG_OK 0
+#define ICP_QAT_FW_COMN_STATUS_FLAG_ERROR 1
+#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_CLR 0
+#define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET 1
+#define ERR_CODE_NO_ERROR 0
+#define ERR_CODE_INVALID_BLOCK_TYPE -1
+#define ERR_CODE_NO_MATCH_ONES_COMP -2
+#define ERR_CODE_TOO_MANY_LEN_OR_DIS -3
+#define ERR_CODE_INCOMPLETE_LEN -4
+#define ERR_CODE_RPT_LEN_NO_FIRST_LEN -5
+#define ERR_CODE_RPT_GT_SPEC_LEN -6
+#define ERR_CODE_INV_LIT_LEN_CODE_LEN -7
+#define ERR_CODE_INV_DIS_CODE_LEN -8
+#define ERR_CODE_INV_LIT_LEN_DIS_IN_BLK -9
+#define ERR_CODE_DIS_TOO_FAR_BACK -10
+#define ERR_CODE_OVERFLOW_ERROR -11
+#define ERR_CODE_SOFT_ERROR -12
+#define ERR_CODE_FATAL_ERROR -13
+#define ERR_CODE_SSM_ERROR -14
+#define ERR_CODE_ENDPOINT_ERROR -15
+
+enum icp_qat_fw_slice {
+ ICP_QAT_FW_SLICE_NULL = 0,
+ ICP_QAT_FW_SLICE_CIPHER = 1,
+ ICP_QAT_FW_SLICE_AUTH = 2,
+ ICP_QAT_FW_SLICE_DRAM_RD = 3,
+ ICP_QAT_FW_SLICE_DRAM_WR = 4,
+ ICP_QAT_FW_SLICE_COMP = 5,
+ ICP_QAT_FW_SLICE_XLAT = 6,
+ ICP_QAT_FW_SLICE_DELIMITER
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h b/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h
new file mode 100644
index 000000000000..72a59faa9005
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_fw_init_admin.h
@@ -0,0 +1,131 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _ICP_QAT_FW_INIT_ADMIN_H_
+#define _ICP_QAT_FW_INIT_ADMIN_H_
+
+#include "icp_qat_fw.h"
+
+enum icp_qat_fw_init_admin_cmd_id {
+ ICP_QAT_FW_INIT_ME = 0,
+ ICP_QAT_FW_TRNG_ENABLE = 1,
+ ICP_QAT_FW_TRNG_DISABLE = 2,
+ ICP_QAT_FW_CONSTANTS_CFG = 3,
+ ICP_QAT_FW_STATUS_GET = 4,
+ ICP_QAT_FW_COUNTERS_GET = 5,
+ ICP_QAT_FW_LOOPBACK = 6,
+ ICP_QAT_FW_HEARTBEAT_SYNC = 7,
+ ICP_QAT_FW_HEARTBEAT_GET = 8
+};
+
+enum icp_qat_fw_init_admin_resp_status {
+ ICP_QAT_FW_INIT_RESP_STATUS_SUCCESS = 0,
+ ICP_QAT_FW_INIT_RESP_STATUS_FAIL
+};
+
+struct icp_qat_fw_init_admin_req {
+ uint16_t init_cfg_sz;
+ uint8_t resrvd1;
+ uint8_t init_admin_cmd_id;
+ uint32_t resrvd2;
+ uint64_t opaque_data;
+ uint64_t init_cfg_ptr;
+ uint64_t resrvd3;
+};
+
+struct icp_qat_fw_init_admin_resp_hdr {
+ uint8_t flags;
+ uint8_t resrvd1;
+ uint8_t status;
+ uint8_t init_admin_cmd_id;
+};
+
+struct icp_qat_fw_init_admin_resp_pars {
+ union {
+ uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_4];
+ struct {
+ uint32_t version_patch_num;
+ uint8_t context_id;
+ uint8_t ae_id;
+ uint16_t resrvd1;
+ uint64_t resrvd2;
+ } s1;
+ struct {
+ uint64_t req_rec_count;
+ uint64_t resp_sent_count;
+ } s2;
+ } u;
+};
+
+struct icp_qat_fw_init_admin_resp {
+ struct icp_qat_fw_init_admin_resp_hdr init_resp_hdr;
+ union {
+ uint32_t resrvd2;
+ struct {
+ uint16_t version_minor_num;
+ uint16_t version_major_num;
+ } s;
+ } u;
+ uint64_t opaque_data;
+ struct icp_qat_fw_init_admin_resp_pars init_resp_pars;
+};
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_OK 0
+#define ICP_QAT_FW_COMN_HEARTBEAT_BLOCKED 1
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS 0
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_STATUS_RESRVD_FLD_MASK 0xFE
+#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_GET(hdr_t) \
+ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(hdr_t.flags)
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_SET(hdr_t, val) \
+ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_SET(hdr_t, val)
+
+#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(flags) \
+ QAT_FIELD_GET(flags, \
+ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS, \
+ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK)
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_fw_la.h b/drivers/crypto/qat/qat_common/icp_qat_fw_la.h
new file mode 100644
index 000000000000..c8d26697e8ea
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_fw_la.h
@@ -0,0 +1,404 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _ICP_QAT_FW_LA_H_
+#define _ICP_QAT_FW_LA_H_
+#include "icp_qat_fw.h"
+
+enum icp_qat_fw_la_cmd_id {
+ ICP_QAT_FW_LA_CMD_CIPHER = 0,
+ ICP_QAT_FW_LA_CMD_AUTH = 1,
+ ICP_QAT_FW_LA_CMD_CIPHER_HASH = 2,
+ ICP_QAT_FW_LA_CMD_HASH_CIPHER = 3,
+ ICP_QAT_FW_LA_CMD_TRNG_GET_RANDOM = 4,
+ ICP_QAT_FW_LA_CMD_TRNG_TEST = 5,
+ ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE = 6,
+ ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE = 7,
+ ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE = 8,
+ ICP_QAT_FW_LA_CMD_MGF1 = 9,
+ ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP = 10,
+ ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP = 11,
+ ICP_QAT_FW_LA_CMD_DELIMITER = 12
+};
+
+#define ICP_QAT_FW_LA_ICV_VER_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK
+#define ICP_QAT_FW_LA_ICV_VER_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR
+#define ICP_QAT_FW_LA_TRNG_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK
+#define ICP_QAT_FW_LA_TRNG_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR
+
+struct icp_qat_fw_la_bulk_req {
+ struct icp_qat_fw_comn_req_hdr comn_hdr;
+ struct icp_qat_fw_comn_req_hdr_cd_pars cd_pars;
+ struct icp_qat_fw_comn_req_mid comn_mid;
+ struct icp_qat_fw_comn_req_rqpars serv_specif_rqpars;
+ struct icp_qat_fw_comn_req_cd_ctrl cd_ctrl;
+};
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS 1
+#define ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS 0
+#define QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS 12
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO 1
+#define QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK 0x1
+#define QAT_LA_GCM_IV_LEN_FLAG_BITPOS 11
+#define QAT_LA_GCM_IV_LEN_FLAG_MASK 0x1
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER 1
+#define ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER 0
+#define QAT_LA_DIGEST_IN_BUFFER_BITPOS 10
+#define QAT_LA_DIGEST_IN_BUFFER_MASK 0x1
+#define ICP_QAT_FW_LA_SNOW_3G_PROTO 4
+#define ICP_QAT_FW_LA_GCM_PROTO 2
+#define ICP_QAT_FW_LA_CCM_PROTO 1
+#define ICP_QAT_FW_LA_NO_PROTO 0
+#define QAT_LA_PROTO_BITPOS 7
+#define QAT_LA_PROTO_MASK 0x7
+#define ICP_QAT_FW_LA_CMP_AUTH_RES 1
+#define ICP_QAT_FW_LA_NO_CMP_AUTH_RES 0
+#define QAT_LA_CMP_AUTH_RES_BITPOS 6
+#define QAT_LA_CMP_AUTH_RES_MASK 0x1
+#define ICP_QAT_FW_LA_RET_AUTH_RES 1
+#define ICP_QAT_FW_LA_NO_RET_AUTH_RES 0
+#define QAT_LA_RET_AUTH_RES_BITPOS 5
+#define QAT_LA_RET_AUTH_RES_MASK 0x1
+#define ICP_QAT_FW_LA_UPDATE_STATE 1
+#define ICP_QAT_FW_LA_NO_UPDATE_STATE 0
+#define QAT_LA_UPDATE_STATE_BITPOS 4
+#define QAT_LA_UPDATE_STATE_MASK 0x1
+#define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP 0
+#define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_SHRAM_CP 1
+#define QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS 3
+#define QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK 0x1
+#define ICP_QAT_FW_CIPH_IV_64BIT_PTR 0
+#define ICP_QAT_FW_CIPH_IV_16BYTE_DATA 1
+#define QAT_LA_CIPH_IV_FLD_BITPOS 2
+#define QAT_LA_CIPH_IV_FLD_MASK 0x1
+#define ICP_QAT_FW_LA_PARTIAL_NONE 0
+#define ICP_QAT_FW_LA_PARTIAL_START 1
+#define ICP_QAT_FW_LA_PARTIAL_MID 3
+#define ICP_QAT_FW_LA_PARTIAL_END 2
+#define QAT_LA_PARTIAL_BITPOS 0
+#define QAT_LA_PARTIAL_MASK 0x3
+#define ICP_QAT_FW_LA_FLAGS_BUILD(zuc_proto, gcm_iv_len, auth_rslt, proto, \
+ cmp_auth, ret_auth, update_state, \
+ ciph_iv, ciphcfg, partial) \
+ (((zuc_proto & QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK) << \
+ QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS) | \
+ ((gcm_iv_len & QAT_LA_GCM_IV_LEN_FLAG_MASK) << \
+ QAT_LA_GCM_IV_LEN_FLAG_BITPOS) | \
+ ((auth_rslt & QAT_LA_DIGEST_IN_BUFFER_MASK) << \
+ QAT_LA_DIGEST_IN_BUFFER_BITPOS) | \
+ ((proto & QAT_LA_PROTO_MASK) << \
+ QAT_LA_PROTO_BITPOS) | \
+ ((cmp_auth & QAT_LA_CMP_AUTH_RES_MASK) << \
+ QAT_LA_CMP_AUTH_RES_BITPOS) | \
+ ((ret_auth & QAT_LA_RET_AUTH_RES_MASK) << \
+ QAT_LA_RET_AUTH_RES_BITPOS) | \
+ ((update_state & QAT_LA_UPDATE_STATE_MASK) << \
+ QAT_LA_UPDATE_STATE_BITPOS) | \
+ ((ciph_iv & QAT_LA_CIPH_IV_FLD_MASK) << \
+ QAT_LA_CIPH_IV_FLD_BITPOS) | \
+ ((ciphcfg & QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK) << \
+ QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS) | \
+ ((partial & QAT_LA_PARTIAL_MASK) << \
+ QAT_LA_PARTIAL_BITPOS))
+
+#define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_CIPH_IV_FLD_BITPOS, \
+ QAT_LA_CIPH_IV_FLD_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \
+ QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK)
+
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \
+ QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_GCM_IV_LEN_FLAG_BITPOS, \
+ QAT_LA_GCM_IV_LEN_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_PROTO_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_PROTO_BITPOS, QAT_LA_PROTO_MASK)
+
+#define ICP_QAT_FW_LA_CMP_AUTH_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_CMP_AUTH_RES_BITPOS, \
+ QAT_LA_CMP_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_RET_AUTH_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_RET_AUTH_RES_BITPOS, \
+ QAT_LA_RET_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_DIGEST_IN_BUFFER_BITPOS, \
+ QAT_LA_DIGEST_IN_BUFFER_MASK)
+
+#define ICP_QAT_FW_LA_UPDATE_STATE_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_UPDATE_STATE_BITPOS, \
+ QAT_LA_UPDATE_STATE_MASK)
+
+#define ICP_QAT_FW_LA_PARTIAL_GET(flags) \
+ QAT_FIELD_GET(flags, QAT_LA_PARTIAL_BITPOS, \
+ QAT_LA_PARTIAL_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_CIPH_IV_FLD_BITPOS, \
+ QAT_LA_CIPH_IV_FLD_MASK)
+
+#define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \
+ QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK)
+
+#define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \
+ QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_GCM_IV_LEN_FLAG_BITPOS, \
+ QAT_LA_GCM_IV_LEN_FLAG_MASK)
+
+#define ICP_QAT_FW_LA_PROTO_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_PROTO_BITPOS, \
+ QAT_LA_PROTO_MASK)
+
+#define ICP_QAT_FW_LA_CMP_AUTH_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_CMP_AUTH_RES_BITPOS, \
+ QAT_LA_CMP_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_RET_AUTH_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_RET_AUTH_RES_BITPOS, \
+ QAT_LA_RET_AUTH_RES_MASK)
+
+#define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_DIGEST_IN_BUFFER_BITPOS, \
+ QAT_LA_DIGEST_IN_BUFFER_MASK)
+
+#define ICP_QAT_FW_LA_UPDATE_STATE_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_UPDATE_STATE_BITPOS, \
+ QAT_LA_UPDATE_STATE_MASK)
+
+#define ICP_QAT_FW_LA_PARTIAL_SET(flags, val) \
+ QAT_FIELD_SET(flags, val, QAT_LA_PARTIAL_BITPOS, \
+ QAT_LA_PARTIAL_MASK)
+
+struct icp_qat_fw_cipher_req_hdr_cd_pars {
+ union {
+ struct {
+ uint64_t content_desc_addr;
+ uint16_t content_desc_resrvd1;
+ uint8_t content_desc_params_sz;
+ uint8_t content_desc_hdr_resrvd2;
+ uint32_t content_desc_resrvd3;
+ } s;
+ struct {
+ uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+ } s1;
+ } u;
+};
+
+struct icp_qat_fw_cipher_auth_req_hdr_cd_pars {
+ union {
+ struct {
+ uint64_t content_desc_addr;
+ uint16_t content_desc_resrvd1;
+ uint8_t content_desc_params_sz;
+ uint8_t content_desc_hdr_resrvd2;
+ uint32_t content_desc_resrvd3;
+ } s;
+ struct {
+ uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+ } sl;
+ } u;
+};
+
+struct icp_qat_fw_cipher_cd_ctrl_hdr {
+ uint8_t cipher_state_sz;
+ uint8_t cipher_key_sz;
+ uint8_t cipher_cfg_offset;
+ uint8_t next_curr_id;
+ uint8_t cipher_padding_sz;
+ uint8_t resrvd1;
+ uint16_t resrvd2;
+ uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_3];
+};
+
+struct icp_qat_fw_auth_cd_ctrl_hdr {
+ uint32_t resrvd1;
+ uint8_t resrvd2;
+ uint8_t hash_flags;
+ uint8_t hash_cfg_offset;
+ uint8_t next_curr_id;
+ uint8_t resrvd3;
+ uint8_t outer_prefix_sz;
+ uint8_t final_sz;
+ uint8_t inner_res_sz;
+ uint8_t resrvd4;
+ uint8_t inner_state1_sz;
+ uint8_t inner_state2_offset;
+ uint8_t inner_state2_sz;
+ uint8_t outer_config_offset;
+ uint8_t outer_state1_sz;
+ uint8_t outer_res_sz;
+ uint8_t outer_prefix_offset;
+};
+
+struct icp_qat_fw_cipher_auth_cd_ctrl_hdr {
+ uint8_t cipher_state_sz;
+ uint8_t cipher_key_sz;
+ uint8_t cipher_cfg_offset;
+ uint8_t next_curr_id_cipher;
+ uint8_t cipher_padding_sz;
+ uint8_t hash_flags;
+ uint8_t hash_cfg_offset;
+ uint8_t next_curr_id_auth;
+ uint8_t resrvd1;
+ uint8_t outer_prefix_sz;
+ uint8_t final_sz;
+ uint8_t inner_res_sz;
+ uint8_t resrvd2;
+ uint8_t inner_state1_sz;
+ uint8_t inner_state2_offset;
+ uint8_t inner_state2_sz;
+ uint8_t outer_config_offset;
+ uint8_t outer_state1_sz;
+ uint8_t outer_res_sz;
+ uint8_t outer_prefix_offset;
+};
+
+#define ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED 1
+#define ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED 0
+#define ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX 240
+#define ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET \
+ (sizeof(struct icp_qat_fw_la_cipher_req_params_t))
+#define ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET (0)
+
+struct icp_qat_fw_la_cipher_req_params {
+ uint32_t cipher_offset;
+ uint32_t cipher_length;
+ union {
+ uint32_t cipher_IV_array[ICP_QAT_FW_NUM_LONGWORDS_4];
+ struct {
+ uint64_t cipher_IV_ptr;
+ uint64_t resrvd1;
+ } s;
+ } u;
+};
+
+struct icp_qat_fw_la_auth_req_params {
+ uint32_t auth_off;
+ uint32_t auth_len;
+ union {
+ uint64_t auth_partial_st_prefix;
+ uint64_t aad_adr;
+ } u1;
+ uint64_t auth_res_addr;
+ union {
+ uint8_t inner_prefix_sz;
+ uint8_t aad_sz;
+ } u2;
+ uint8_t resrvd1;
+ uint8_t hash_state_sz;
+ uint8_t auth_res_sz;
+} __packed;
+
+struct icp_qat_fw_la_auth_req_params_resrvd_flds {
+ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_6];
+ union {
+ uint8_t inner_prefix_sz;
+ uint8_t aad_sz;
+ } u2;
+ uint8_t resrvd1;
+ uint16_t resrvd2;
+};
+
+struct icp_qat_fw_la_resp {
+ struct icp_qat_fw_comn_resp_hdr comn_resp;
+ uint64_t opaque_data;
+ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4];
+};
+
+#define ICP_QAT_FW_CIPHER_NEXT_ID_GET(cd_ctrl_hdr_t) \
+ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \
+ ICP_QAT_FW_COMN_NEXT_ID_MASK) >> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_CIPHER_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_cipher = \
+ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+ & ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK)) }
+
+#define ICP_QAT_FW_CIPHER_CURR_ID_GET(cd_ctrl_hdr_t) \
+ (((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+ & ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_CIPHER_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_cipher = \
+ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+ ((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)) }
+
+#define ICP_QAT_FW_AUTH_NEXT_ID_GET(cd_ctrl_hdr_t) \
+ ((((cd_ctrl_hdr_t)->next_curr_id_auth) & ICP_QAT_FW_COMN_NEXT_ID_MASK) \
+ >> (ICP_QAT_FW_COMN_NEXT_ID_BITPOS))
+
+#define ICP_QAT_FW_AUTH_NEXT_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_auth = \
+ ((((cd_ctrl_hdr_t)->next_curr_id_auth) \
+ & ICP_QAT_FW_COMN_CURR_ID_MASK) | \
+ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK)) }
+
+#define ICP_QAT_FW_AUTH_CURR_ID_GET(cd_ctrl_hdr_t) \
+ (((cd_ctrl_hdr_t)->next_curr_id_auth) \
+ & ICP_QAT_FW_COMN_CURR_ID_MASK)
+
+#define ICP_QAT_FW_AUTH_CURR_ID_SET(cd_ctrl_hdr_t, val) \
+{ (cd_ctrl_hdr_t)->next_curr_id_auth = \
+ ((((cd_ctrl_hdr_t)->next_curr_id_auth) \
+ & ICP_QAT_FW_COMN_NEXT_ID_MASK) | \
+ ((val) & ICP_QAT_FW_COMN_CURR_ID_MASK)) }
+
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h b/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h
new file mode 100644
index 000000000000..5e1aa40c0404
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_fw_loader_handle.h
@@ -0,0 +1,78 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __ICP_QAT_FW_LOADER_HANDLE_H__
+#define __ICP_QAT_FW_LOADER_HANDLE_H__
+#include "icp_qat_uclo.h"
+
+struct icp_qat_fw_loader_ae_data {
+ unsigned int state;
+ unsigned int ustore_size;
+ unsigned int free_addr;
+ unsigned int free_size;
+ unsigned int live_ctx_mask;
+};
+
+struct icp_qat_fw_loader_hal_handle {
+ struct icp_qat_fw_loader_ae_data aes[ICP_QAT_UCLO_MAX_AE];
+ unsigned int ae_mask;
+ unsigned int slice_mask;
+ unsigned int revision_id;
+ unsigned int ae_max_num;
+ unsigned int upc_mask;
+ unsigned int max_ustore;
+};
+
+struct icp_qat_fw_loader_handle {
+ struct icp_qat_fw_loader_hal_handle *hal_handle;
+ void *obj_handle;
+ void __iomem *hal_sram_addr_v;
+ void __iomem *hal_cap_g_ctl_csr_addr_v;
+ void __iomem *hal_cap_ae_xfer_csr_addr_v;
+ void __iomem *hal_cap_ae_local_csr_addr_v;
+ void __iomem *hal_ep_csr_addr_v;
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_hal.h b/drivers/crypto/qat/qat_common/icp_qat_hal.h
new file mode 100644
index 000000000000..85b6d241ea82
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_hal.h
@@ -0,0 +1,125 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __ICP_QAT_HAL_H
+#define __ICP_QAT_HAL_H
+#include "icp_qat_fw_loader_handle.h"
+
+enum hal_global_csr {
+ MISC_CONTROL = 0x04,
+ ICP_RESET = 0x0c,
+ ICP_GLOBAL_CLK_ENABLE = 0x50
+};
+
+enum hal_ae_csr {
+ USTORE_ADDRESS = 0x000,
+ USTORE_DATA_LOWER = 0x004,
+ USTORE_DATA_UPPER = 0x008,
+ ALU_OUT = 0x010,
+ CTX_ARB_CNTL = 0x014,
+ CTX_ENABLES = 0x018,
+ CC_ENABLE = 0x01c,
+ CSR_CTX_POINTER = 0x020,
+ CTX_STS_INDIRECT = 0x040,
+ ACTIVE_CTX_STATUS = 0x044,
+ CTX_SIG_EVENTS_INDIRECT = 0x048,
+ CTX_SIG_EVENTS_ACTIVE = 0x04c,
+ CTX_WAKEUP_EVENTS_INDIRECT = 0x050,
+ LM_ADDR_0_INDIRECT = 0x060,
+ LM_ADDR_1_INDIRECT = 0x068,
+ INDIRECT_LM_ADDR_0_BYTE_INDEX = 0x0e0,
+ INDIRECT_LM_ADDR_1_BYTE_INDEX = 0x0e8,
+ FUTURE_COUNT_SIGNAL_INDIRECT = 0x078,
+ TIMESTAMP_LOW = 0x0c0,
+ TIMESTAMP_HIGH = 0x0c4,
+ PROFILE_COUNT = 0x144,
+ SIGNATURE_ENABLE = 0x150,
+ AE_MISC_CONTROL = 0x160,
+ LOCAL_CSR_STATUS = 0x180,
+};
+
+#define UA_ECS (0x1 << 31)
+#define ACS_ABO_BITPOS 31
+#define ACS_ACNO 0x7
+#define CE_ENABLE_BITPOS 0x8
+#define CE_LMADDR_0_GLOBAL_BITPOS 16
+#define CE_LMADDR_1_GLOBAL_BITPOS 17
+#define CE_NN_MODE_BITPOS 20
+#define CE_REG_PAR_ERR_BITPOS 25
+#define CE_BREAKPOINT_BITPOS 27
+#define CE_CNTL_STORE_PARITY_ERROR_BITPOS 29
+#define CE_INUSE_CONTEXTS_BITPOS 31
+#define CE_NN_MODE (0x1 << CE_NN_MODE_BITPOS)
+#define CE_INUSE_CONTEXTS (0x1 << CE_INUSE_CONTEXTS_BITPOS)
+#define XCWE_VOLUNTARY (0x1)
+#define LCS_STATUS (0x1)
+#define MMC_SHARE_CS_BITPOS 2
+#define GLOBAL_CSR 0xA00
+
+#define SET_CAP_CSR(handle, csr, val) \
+ ADF_CSR_WR(handle->hal_cap_g_ctl_csr_addr_v, csr, val)
+#define GET_CAP_CSR(handle, csr) \
+ ADF_CSR_RD(handle->hal_cap_g_ctl_csr_addr_v, csr)
+#define SET_GLB_CSR(handle, csr, val) SET_CAP_CSR(handle, csr + GLOBAL_CSR, val)
+#define GET_GLB_CSR(handle, csr) GET_CAP_CSR(handle, GLOBAL_CSR + csr)
+#define AE_CSR(handle, ae) \
+ (handle->hal_cap_ae_local_csr_addr_v + \
+ ((ae & handle->hal_handle->ae_mask) << 12))
+#define AE_CSR_ADDR(handle, ae, csr) (AE_CSR(handle, ae) + (0x3ff & csr))
+#define SET_AE_CSR(handle, ae, csr, val) \
+ ADF_CSR_WR(AE_CSR_ADDR(handle, ae, csr), 0, val)
+#define GET_AE_CSR(handle, ae, csr) ADF_CSR_RD(AE_CSR_ADDR(handle, ae, csr), 0)
+#define AE_XFER(handle, ae) \
+ (handle->hal_cap_ae_xfer_csr_addr_v + \
+ ((ae & handle->hal_handle->ae_mask) << 12))
+#define AE_XFER_ADDR(handle, ae, reg) (AE_XFER(handle, ae) + \
+ ((reg & 0xff) << 2))
+#define SET_AE_XFER(handle, ae, reg, val) \
+ ADF_CSR_WR(AE_XFER_ADDR(handle, ae, reg), 0, val)
+#define SRAM_WRITE(handle, addr, val) \
+ ADF_CSR_WR(handle->hal_sram_addr_v, addr, val)
+#define SRAM_READ(handle, addr) ADF_CSR_RD(handle->hal_sram_addr_v, addr)
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_hw.h b/drivers/crypto/qat/qat_common/icp_qat_hw.h
new file mode 100644
index 000000000000..5031f8c10d75
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_hw.h
@@ -0,0 +1,305 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _ICP_QAT_HW_H_
+#define _ICP_QAT_HW_H_
+
+enum icp_qat_hw_ae_id {
+ ICP_QAT_HW_AE_0 = 0,
+ ICP_QAT_HW_AE_1 = 1,
+ ICP_QAT_HW_AE_2 = 2,
+ ICP_QAT_HW_AE_3 = 3,
+ ICP_QAT_HW_AE_4 = 4,
+ ICP_QAT_HW_AE_5 = 5,
+ ICP_QAT_HW_AE_6 = 6,
+ ICP_QAT_HW_AE_7 = 7,
+ ICP_QAT_HW_AE_8 = 8,
+ ICP_QAT_HW_AE_9 = 9,
+ ICP_QAT_HW_AE_10 = 10,
+ ICP_QAT_HW_AE_11 = 11,
+ ICP_QAT_HW_AE_DELIMITER = 12
+};
+
+enum icp_qat_hw_qat_id {
+ ICP_QAT_HW_QAT_0 = 0,
+ ICP_QAT_HW_QAT_1 = 1,
+ ICP_QAT_HW_QAT_2 = 2,
+ ICP_QAT_HW_QAT_3 = 3,
+ ICP_QAT_HW_QAT_4 = 4,
+ ICP_QAT_HW_QAT_5 = 5,
+ ICP_QAT_HW_QAT_DELIMITER = 6
+};
+
+enum icp_qat_hw_auth_algo {
+ ICP_QAT_HW_AUTH_ALGO_NULL = 0,
+ ICP_QAT_HW_AUTH_ALGO_SHA1 = 1,
+ ICP_QAT_HW_AUTH_ALGO_MD5 = 2,
+ ICP_QAT_HW_AUTH_ALGO_SHA224 = 3,
+ ICP_QAT_HW_AUTH_ALGO_SHA256 = 4,
+ ICP_QAT_HW_AUTH_ALGO_SHA384 = 5,
+ ICP_QAT_HW_AUTH_ALGO_SHA512 = 6,
+ ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC = 7,
+ ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC = 8,
+ ICP_QAT_HW_AUTH_ALGO_AES_F9 = 9,
+ ICP_QAT_HW_AUTH_ALGO_GALOIS_128 = 10,
+ ICP_QAT_HW_AUTH_ALGO_GALOIS_64 = 11,
+ ICP_QAT_HW_AUTH_ALGO_KASUMI_F9 = 12,
+ ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 = 13,
+ ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 = 14,
+ ICP_QAT_HW_AUTH_RESERVED_1 = 15,
+ ICP_QAT_HW_AUTH_RESERVED_2 = 16,
+ ICP_QAT_HW_AUTH_ALGO_SHA3_256 = 17,
+ ICP_QAT_HW_AUTH_RESERVED_3 = 18,
+ ICP_QAT_HW_AUTH_ALGO_SHA3_512 = 19,
+ ICP_QAT_HW_AUTH_ALGO_DELIMITER = 20
+};
+
+enum icp_qat_hw_auth_mode {
+ ICP_QAT_HW_AUTH_MODE0 = 0,
+ ICP_QAT_HW_AUTH_MODE1 = 1,
+ ICP_QAT_HW_AUTH_MODE2 = 2,
+ ICP_QAT_HW_AUTH_MODE_DELIMITER = 3
+};
+
+struct icp_qat_hw_auth_config {
+ uint32_t config;
+ uint32_t reserved;
+};
+
+#define QAT_AUTH_MODE_BITPOS 4
+#define QAT_AUTH_MODE_MASK 0xF
+#define QAT_AUTH_ALGO_BITPOS 0
+#define QAT_AUTH_ALGO_MASK 0xF
+#define QAT_AUTH_CMP_BITPOS 8
+#define QAT_AUTH_CMP_MASK 0x7F
+#define QAT_AUTH_SHA3_PADDING_BITPOS 16
+#define QAT_AUTH_SHA3_PADDING_MASK 0x1
+#define QAT_AUTH_ALGO_SHA3_BITPOS 22
+#define QAT_AUTH_ALGO_SHA3_MASK 0x3
+#define ICP_QAT_HW_AUTH_CONFIG_BUILD(mode, algo, cmp_len) \
+ (((mode & QAT_AUTH_MODE_MASK) << QAT_AUTH_MODE_BITPOS) | \
+ ((algo & QAT_AUTH_ALGO_MASK) << QAT_AUTH_ALGO_BITPOS) | \
+ (((algo >> 4) & QAT_AUTH_ALGO_SHA3_MASK) << \
+ QAT_AUTH_ALGO_SHA3_BITPOS) | \
+ (((((algo == ICP_QAT_HW_AUTH_ALGO_SHA3_256) || \
+ (algo == ICP_QAT_HW_AUTH_ALGO_SHA3_512)) ? 1 : 0) \
+ & QAT_AUTH_SHA3_PADDING_MASK) << QAT_AUTH_SHA3_PADDING_BITPOS) | \
+ ((cmp_len & QAT_AUTH_CMP_MASK) << QAT_AUTH_CMP_BITPOS))
+
+struct icp_qat_hw_auth_counter {
+ __be32 counter;
+ uint32_t reserved;
+};
+
+#define QAT_AUTH_COUNT_MASK 0xFFFFFFFF
+#define QAT_AUTH_COUNT_BITPOS 0
+#define ICP_QAT_HW_AUTH_COUNT_BUILD(val) \
+ (((val) & QAT_AUTH_COUNT_MASK) << QAT_AUTH_COUNT_BITPOS)
+
+struct icp_qat_hw_auth_setup {
+ struct icp_qat_hw_auth_config auth_config;
+ struct icp_qat_hw_auth_counter auth_counter;
+};
+
+#define QAT_HW_DEFAULT_ALIGNMENT 8
+#define QAT_HW_ROUND_UP(val, n) (((val) + ((n)-1)) & (~(n-1)))
+#define ICP_QAT_HW_NULL_STATE1_SZ 32
+#define ICP_QAT_HW_MD5_STATE1_SZ 16
+#define ICP_QAT_HW_SHA1_STATE1_SZ 20
+#define ICP_QAT_HW_SHA224_STATE1_SZ 32
+#define ICP_QAT_HW_SHA256_STATE1_SZ 32
+#define ICP_QAT_HW_SHA3_256_STATE1_SZ 32
+#define ICP_QAT_HW_SHA384_STATE1_SZ 64
+#define ICP_QAT_HW_SHA512_STATE1_SZ 64
+#define ICP_QAT_HW_SHA3_512_STATE1_SZ 64
+#define ICP_QAT_HW_SHA3_224_STATE1_SZ 28
+#define ICP_QAT_HW_SHA3_384_STATE1_SZ 48
+#define ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ 16
+#define ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ 16
+#define ICP_QAT_HW_AES_F9_STATE1_SZ 32
+#define ICP_QAT_HW_KASUMI_F9_STATE1_SZ 16
+#define ICP_QAT_HW_GALOIS_128_STATE1_SZ 16
+#define ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ 8
+#define ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ 8
+#define ICP_QAT_HW_NULL_STATE2_SZ 32
+#define ICP_QAT_HW_MD5_STATE2_SZ 16
+#define ICP_QAT_HW_SHA1_STATE2_SZ 20
+#define ICP_QAT_HW_SHA224_STATE2_SZ 32
+#define ICP_QAT_HW_SHA256_STATE2_SZ 32
+#define ICP_QAT_HW_SHA3_256_STATE2_SZ 0
+#define ICP_QAT_HW_SHA384_STATE2_SZ 64
+#define ICP_QAT_HW_SHA512_STATE2_SZ 64
+#define ICP_QAT_HW_SHA3_512_STATE2_SZ 0
+#define ICP_QAT_HW_SHA3_224_STATE2_SZ 0
+#define ICP_QAT_HW_SHA3_384_STATE2_SZ 0
+#define ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ 16
+#define ICP_QAT_HW_AES_CBC_MAC_KEY_SZ 16
+#define ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ 16
+#define ICP_QAT_HW_F9_IK_SZ 16
+#define ICP_QAT_HW_F9_FK_SZ 16
+#define ICP_QAT_HW_KASUMI_F9_STATE2_SZ (ICP_QAT_HW_F9_IK_SZ + \
+ ICP_QAT_HW_F9_FK_SZ)
+#define ICP_QAT_HW_AES_F9_STATE2_SZ ICP_QAT_HW_KASUMI_F9_STATE2_SZ
+#define ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ 24
+#define ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ 32
+#define ICP_QAT_HW_GALOIS_H_SZ 16
+#define ICP_QAT_HW_GALOIS_LEN_A_SZ 8
+#define ICP_QAT_HW_GALOIS_E_CTR0_SZ 16
+
+struct icp_qat_hw_auth_sha512 {
+ struct icp_qat_hw_auth_setup inner_setup;
+ uint8_t state1[ICP_QAT_HW_SHA512_STATE1_SZ];
+ struct icp_qat_hw_auth_setup outer_setup;
+ uint8_t state2[ICP_QAT_HW_SHA512_STATE2_SZ];
+};
+
+struct icp_qat_hw_auth_algo_blk {
+ struct icp_qat_hw_auth_sha512 sha;
+};
+
+#define ICP_QAT_HW_GALOIS_LEN_A_BITPOS 0
+#define ICP_QAT_HW_GALOIS_LEN_A_MASK 0xFFFFFFFF
+
+enum icp_qat_hw_cipher_algo {
+ ICP_QAT_HW_CIPHER_ALGO_NULL = 0,
+ ICP_QAT_HW_CIPHER_ALGO_DES = 1,
+ ICP_QAT_HW_CIPHER_ALGO_3DES = 2,
+ ICP_QAT_HW_CIPHER_ALGO_AES128 = 3,
+ ICP_QAT_HW_CIPHER_ALGO_AES192 = 4,
+ ICP_QAT_HW_CIPHER_ALGO_AES256 = 5,
+ ICP_QAT_HW_CIPHER_ALGO_ARC4 = 6,
+ ICP_QAT_HW_CIPHER_ALGO_KASUMI = 7,
+ ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 = 8,
+ ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3 = 9,
+ ICP_QAT_HW_CIPHER_DELIMITER = 10
+};
+
+enum icp_qat_hw_cipher_mode {
+ ICP_QAT_HW_CIPHER_ECB_MODE = 0,
+ ICP_QAT_HW_CIPHER_CBC_MODE = 1,
+ ICP_QAT_HW_CIPHER_CTR_MODE = 2,
+ ICP_QAT_HW_CIPHER_F8_MODE = 3,
+ ICP_QAT_HW_CIPHER_XTS_MODE = 6,
+ ICP_QAT_HW_CIPHER_MODE_DELIMITER = 7
+};
+
+struct icp_qat_hw_cipher_config {
+ uint32_t val;
+ uint32_t reserved;
+};
+
+enum icp_qat_hw_cipher_dir {
+ ICP_QAT_HW_CIPHER_ENCRYPT = 0,
+ ICP_QAT_HW_CIPHER_DECRYPT = 1,
+};
+
+enum icp_qat_hw_cipher_convert {
+ ICP_QAT_HW_CIPHER_NO_CONVERT = 0,
+ ICP_QAT_HW_CIPHER_KEY_CONVERT = 1,
+};
+
+#define QAT_CIPHER_MODE_BITPOS 4
+#define QAT_CIPHER_MODE_MASK 0xF
+#define QAT_CIPHER_ALGO_BITPOS 0
+#define QAT_CIPHER_ALGO_MASK 0xF
+#define QAT_CIPHER_CONVERT_BITPOS 9
+#define QAT_CIPHER_CONVERT_MASK 0x1
+#define QAT_CIPHER_DIR_BITPOS 8
+#define QAT_CIPHER_DIR_MASK 0x1
+#define QAT_CIPHER_MODE_F8_KEY_SZ_MULT 2
+#define QAT_CIPHER_MODE_XTS_KEY_SZ_MULT 2
+#define ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, algo, convert, dir) \
+ (((mode & QAT_CIPHER_MODE_MASK) << QAT_CIPHER_MODE_BITPOS) | \
+ ((algo & QAT_CIPHER_ALGO_MASK) << QAT_CIPHER_ALGO_BITPOS) | \
+ ((convert & QAT_CIPHER_CONVERT_MASK) << QAT_CIPHER_CONVERT_BITPOS) | \
+ ((dir & QAT_CIPHER_DIR_MASK) << QAT_CIPHER_DIR_BITPOS))
+#define ICP_QAT_HW_DES_BLK_SZ 8
+#define ICP_QAT_HW_3DES_BLK_SZ 8
+#define ICP_QAT_HW_NULL_BLK_SZ 8
+#define ICP_QAT_HW_AES_BLK_SZ 16
+#define ICP_QAT_HW_KASUMI_BLK_SZ 8
+#define ICP_QAT_HW_SNOW_3G_BLK_SZ 8
+#define ICP_QAT_HW_ZUC_3G_BLK_SZ 8
+#define ICP_QAT_HW_NULL_KEY_SZ 256
+#define ICP_QAT_HW_DES_KEY_SZ 8
+#define ICP_QAT_HW_3DES_KEY_SZ 24
+#define ICP_QAT_HW_AES_128_KEY_SZ 16
+#define ICP_QAT_HW_AES_192_KEY_SZ 24
+#define ICP_QAT_HW_AES_256_KEY_SZ 32
+#define ICP_QAT_HW_AES_128_F8_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+ QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_192_F8_KEY_SZ (ICP_QAT_HW_AES_192_KEY_SZ * \
+ QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_F8_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+ QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_128_XTS_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+ QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_XTS_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+ QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_KASUMI_KEY_SZ 16
+#define ICP_QAT_HW_KASUMI_F8_KEY_SZ (ICP_QAT_HW_KASUMI_KEY_SZ * \
+ QAT_CIPHER_MODE_F8_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_128_XTS_KEY_SZ (ICP_QAT_HW_AES_128_KEY_SZ * \
+ QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_AES_256_XTS_KEY_SZ (ICP_QAT_HW_AES_256_KEY_SZ * \
+ QAT_CIPHER_MODE_XTS_KEY_SZ_MULT)
+#define ICP_QAT_HW_ARC4_KEY_SZ 256
+#define ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ 16
+#define ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ 16
+#define ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ 16
+#define ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ 16
+#define ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR 2
+#define INIT_SHRAM_CONSTANTS_TABLE_SZ 1024
+
+struct icp_qat_hw_cipher_aes256_f8 {
+ struct icp_qat_hw_cipher_config cipher_config;
+ uint8_t key[ICP_QAT_HW_AES_256_F8_KEY_SZ];
+};
+
+struct icp_qat_hw_cipher_algo_blk {
+ struct icp_qat_hw_cipher_aes256_f8 aes;
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/icp_qat_uclo.h b/drivers/crypto/qat/qat_common/icp_qat_uclo.h
new file mode 100644
index 000000000000..2132a8cbc4ec
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/icp_qat_uclo.h
@@ -0,0 +1,377 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __ICP_QAT_UCLO_H__
+#define __ICP_QAT_UCLO_H__
+
+#define ICP_QAT_AC_C_CPU_TYPE 0x00400000
+#define ICP_QAT_UCLO_MAX_AE 12
+#define ICP_QAT_UCLO_MAX_CTX 8
+#define ICP_QAT_UCLO_MAX_UIMAGE (ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX)
+#define ICP_QAT_UCLO_MAX_USTORE 0x4000
+#define ICP_QAT_UCLO_MAX_XFER_REG 128
+#define ICP_QAT_UCLO_MAX_GPR_REG 128
+#define ICP_QAT_UCLO_MAX_NN_REG 128
+#define ICP_QAT_UCLO_MAX_LMEM_REG 1024
+#define ICP_QAT_UCLO_AE_ALL_CTX 0xff
+#define ICP_QAT_UOF_OBJID_LEN 8
+#define ICP_QAT_UOF_FID 0xc6c2
+#define ICP_QAT_UOF_MAJVER 0x4
+#define ICP_QAT_UOF_MINVER 0x11
+#define ICP_QAT_UOF_NN_MODE_NOTCARE 0xff
+#define ICP_QAT_UOF_OBJS "UOF_OBJS"
+#define ICP_QAT_UOF_STRT "UOF_STRT"
+#define ICP_QAT_UOF_GTID "UOF_GTID"
+#define ICP_QAT_UOF_IMAG "UOF_IMAG"
+#define ICP_QAT_UOF_IMEM "UOF_IMEM"
+#define ICP_QAT_UOF_MSEG "UOF_MSEG"
+#define ICP_QAT_UOF_LOCAL_SCOPE 1
+#define ICP_QAT_UOF_INIT_EXPR 0
+#define ICP_QAT_UOF_INIT_REG 1
+#define ICP_QAT_UOF_INIT_REG_CTX 2
+#define ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP 3
+
+#define ICP_QAT_CTX_MODE(ae_mode) ((ae_mode) & 0xf)
+#define ICP_QAT_NN_MODE(ae_mode) (((ae_mode) >> 0x4) & 0xf)
+#define ICP_QAT_SHARED_USTORE_MODE(ae_mode) (((ae_mode) >> 0xb) & 0x1)
+#define RELOADABLE_CTX_SHARED_MODE(ae_mode) (((ae_mode) >> 0xc) & 0x1)
+
+#define ICP_QAT_LOC_MEM0_MODE(ae_mode) (((ae_mode) >> 0x8) & 0x1)
+#define ICP_QAT_LOC_MEM1_MODE(ae_mode) (((ae_mode) >> 0x9) & 0x1)
+
+enum icp_qat_uof_mem_region {
+ ICP_QAT_UOF_SRAM_REGION = 0x0,
+ ICP_QAT_UOF_LMEM_REGION = 0x3,
+ ICP_QAT_UOF_UMEM_REGION = 0x5
+};
+
+enum icp_qat_uof_regtype {
+ ICP_NO_DEST,
+ ICP_GPA_REL,
+ ICP_GPA_ABS,
+ ICP_GPB_REL,
+ ICP_GPB_ABS,
+ ICP_SR_REL,
+ ICP_SR_RD_REL,
+ ICP_SR_WR_REL,
+ ICP_SR_ABS,
+ ICP_SR_RD_ABS,
+ ICP_SR_WR_ABS,
+ ICP_DR_REL,
+ ICP_DR_RD_REL,
+ ICP_DR_WR_REL,
+ ICP_DR_ABS,
+ ICP_DR_RD_ABS,
+ ICP_DR_WR_ABS,
+ ICP_LMEM,
+ ICP_LMEM0,
+ ICP_LMEM1,
+ ICP_NEIGH_REL,
+};
+
+struct icp_qat_uclo_page {
+ struct icp_qat_uclo_encap_page *encap_page;
+ struct icp_qat_uclo_region *region;
+ unsigned int flags;
+};
+
+struct icp_qat_uclo_region {
+ struct icp_qat_uclo_page *loaded;
+ struct icp_qat_uclo_page *page;
+};
+
+struct icp_qat_uclo_aeslice {
+ struct icp_qat_uclo_region *region;
+ struct icp_qat_uclo_page *page;
+ struct icp_qat_uclo_page *cur_page[ICP_QAT_UCLO_MAX_CTX];
+ struct icp_qat_uclo_encapme *encap_image;
+ unsigned int ctx_mask_assigned;
+ unsigned int new_uaddr[ICP_QAT_UCLO_MAX_CTX];
+};
+
+struct icp_qat_uclo_aedata {
+ unsigned int slice_num;
+ unsigned int eff_ustore_size;
+ struct icp_qat_uclo_aeslice ae_slices[ICP_QAT_UCLO_MAX_CTX];
+};
+
+struct icp_qat_uof_encap_obj {
+ char *beg_uof;
+ struct icp_qat_uof_objhdr *obj_hdr;
+ struct icp_qat_uof_chunkhdr *chunk_hdr;
+ struct icp_qat_uof_varmem_seg *var_mem_seg;
+};
+
+struct icp_qat_uclo_encap_uwblock {
+ unsigned int start_addr;
+ unsigned int words_num;
+ uint64_t micro_words;
+};
+
+struct icp_qat_uclo_encap_page {
+ unsigned int def_page;
+ unsigned int page_region;
+ unsigned int beg_addr_v;
+ unsigned int beg_addr_p;
+ unsigned int micro_words_num;
+ unsigned int uwblock_num;
+ struct icp_qat_uclo_encap_uwblock *uwblock;
+};
+
+struct icp_qat_uclo_encapme {
+ struct icp_qat_uof_image *img_ptr;
+ struct icp_qat_uclo_encap_page *page;
+ unsigned int ae_reg_num;
+ struct icp_qat_uof_ae_reg *ae_reg;
+ unsigned int init_regsym_num;
+ struct icp_qat_uof_init_regsym *init_regsym;
+ unsigned int sbreak_num;
+ struct icp_qat_uof_sbreak *sbreak;
+ unsigned int uwords_num;
+};
+
+struct icp_qat_uclo_init_mem_table {
+ unsigned int entry_num;
+ struct icp_qat_uof_initmem *init_mem;
+};
+
+struct icp_qat_uclo_objhdr {
+ char *file_buff;
+ unsigned int checksum;
+ unsigned int size;
+};
+
+struct icp_qat_uof_strtable {
+ unsigned int table_len;
+ unsigned int reserved;
+ uint64_t strings;
+};
+
+struct icp_qat_uclo_objhandle {
+ unsigned int prod_type;
+ unsigned int prod_rev;
+ struct icp_qat_uclo_objhdr *obj_hdr;
+ struct icp_qat_uof_encap_obj encap_uof_obj;
+ struct icp_qat_uof_strtable str_table;
+ struct icp_qat_uclo_encapme ae_uimage[ICP_QAT_UCLO_MAX_UIMAGE];
+ struct icp_qat_uclo_aedata ae_data[ICP_QAT_UCLO_MAX_AE];
+ struct icp_qat_uclo_init_mem_table init_mem_tab;
+ struct icp_qat_uof_batch_init *lm_init_tab[ICP_QAT_UCLO_MAX_AE];
+ struct icp_qat_uof_batch_init *umem_init_tab[ICP_QAT_UCLO_MAX_AE];
+ int uimage_num;
+ int uword_in_bytes;
+ int global_inited;
+ unsigned int ae_num;
+ unsigned int ustore_phy_size;
+ void *obj_buf;
+ uint64_t *uword_buf;
+};
+
+struct icp_qat_uof_uword_block {
+ unsigned int start_addr;
+ unsigned int words_num;
+ unsigned int uword_offset;
+ unsigned int reserved;
+};
+
+struct icp_qat_uof_filehdr {
+ unsigned short file_id;
+ unsigned short reserved1;
+ char min_ver;
+ char maj_ver;
+ unsigned short reserved2;
+ unsigned short max_chunks;
+ unsigned short num_chunks;
+};
+
+struct icp_qat_uof_filechunkhdr {
+ char chunk_id[ICP_QAT_UOF_OBJID_LEN];
+ unsigned int checksum;
+ unsigned int offset;
+ unsigned int size;
+};
+
+struct icp_qat_uof_objhdr {
+ unsigned int cpu_type;
+ unsigned short min_cpu_ver;
+ unsigned short max_cpu_ver;
+ short max_chunks;
+ short num_chunks;
+ unsigned int reserved1;
+ unsigned int reserved2;
+};
+
+struct icp_qat_uof_chunkhdr {
+ char chunk_id[ICP_QAT_UOF_OBJID_LEN];
+ unsigned int offset;
+ unsigned int size;
+};
+
+struct icp_qat_uof_memvar_attr {
+ unsigned int offset_in_byte;
+ unsigned int value;
+};
+
+struct icp_qat_uof_initmem {
+ unsigned int sym_name;
+ char region;
+ char scope;
+ unsigned short reserved1;
+ unsigned int addr;
+ unsigned int num_in_bytes;
+ unsigned int val_attr_num;
+};
+
+struct icp_qat_uof_init_regsym {
+ unsigned int sym_name;
+ char init_type;
+ char value_type;
+ char reg_type;
+ unsigned char ctx;
+ unsigned int reg_addr;
+ unsigned int value;
+};
+
+struct icp_qat_uof_varmem_seg {
+ unsigned int sram_base;
+ unsigned int sram_size;
+ unsigned int sram_alignment;
+ unsigned int sdram_base;
+ unsigned int sdram_size;
+ unsigned int sdram_alignment;
+ unsigned int sdram1_base;
+ unsigned int sdram1_size;
+ unsigned int sdram1_alignment;
+ unsigned int scratch_base;
+ unsigned int scratch_size;
+ unsigned int scratch_alignment;
+};
+
+struct icp_qat_uof_gtid {
+ char tool_id[ICP_QAT_UOF_OBJID_LEN];
+ int tool_ver;
+ unsigned int reserved1;
+ unsigned int reserved2;
+};
+
+struct icp_qat_uof_sbreak {
+ unsigned int page_num;
+ unsigned int virt_uaddr;
+ unsigned char sbreak_type;
+ unsigned char reg_type;
+ unsigned short reserved1;
+ unsigned int addr_offset;
+ unsigned int reg_addr;
+};
+
+struct icp_qat_uof_code_page {
+ unsigned int page_region;
+ unsigned int page_num;
+ unsigned char def_page;
+ unsigned char reserved2;
+ unsigned short reserved1;
+ unsigned int beg_addr_v;
+ unsigned int beg_addr_p;
+ unsigned int neigh_reg_tab_offset;
+ unsigned int uc_var_tab_offset;
+ unsigned int imp_var_tab_offset;
+ unsigned int imp_expr_tab_offset;
+ unsigned int code_area_offset;
+};
+
+struct icp_qat_uof_image {
+ unsigned int img_name;
+ unsigned int ae_assigned;
+ unsigned int ctx_assigned;
+ unsigned int cpu_type;
+ unsigned int entry_address;
+ unsigned int fill_pattern[2];
+ unsigned int reloadable_size;
+ unsigned char sensitivity;
+ unsigned char reserved;
+ unsigned short ae_mode;
+ unsigned short max_ver;
+ unsigned short min_ver;
+ unsigned short image_attrib;
+ unsigned short reserved2;
+ unsigned short page_region_num;
+ unsigned short numpages;
+ unsigned int reg_tab_offset;
+ unsigned int init_reg_sym_tab;
+ unsigned int sbreak_tab;
+ unsigned int app_metadata;
+};
+
+struct icp_qat_uof_objtable {
+ unsigned int entry_num;
+};
+
+struct icp_qat_uof_ae_reg {
+ unsigned int name;
+ unsigned int vis_name;
+ unsigned short type;
+ unsigned short addr;
+ unsigned short access_mode;
+ unsigned char visible;
+ unsigned char reserved1;
+ unsigned short ref_count;
+ unsigned short reserved2;
+ unsigned int xo_id;
+};
+
+struct icp_qat_uof_code_area {
+ unsigned int micro_words_num;
+ unsigned int uword_block_tab;
+};
+
+struct icp_qat_uof_batch_init {
+ unsigned int ae;
+ unsigned int addr;
+ unsigned int *value;
+ unsigned int size;
+ struct icp_qat_uof_batch_init *next;
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
new file mode 100644
index 000000000000..59df48872955
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_algs.c
@@ -0,0 +1,1038 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/crypto.h>
+#include <crypto/aead.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/hash.h>
+#include <crypto/algapi.h>
+#include <crypto/authenc.h>
+#include <crypto/rng.h>
+#include <linux/dma-mapping.h>
+#include "adf_accel_devices.h"
+#include "adf_transport.h"
+#include "adf_common_drv.h"
+#include "qat_crypto.h"
+#include "icp_qat_hw.h"
+#include "icp_qat_fw.h"
+#include "icp_qat_fw_la.h"
+
+#define QAT_AES_HW_CONFIG_ENC(alg) \
+ ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+ ICP_QAT_HW_CIPHER_NO_CONVERT, \
+ ICP_QAT_HW_CIPHER_ENCRYPT)
+
+#define QAT_AES_HW_CONFIG_DEC(alg) \
+ ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \
+ ICP_QAT_HW_CIPHER_KEY_CONVERT, \
+ ICP_QAT_HW_CIPHER_DECRYPT)
+
+static atomic_t active_dev;
+
+struct qat_alg_buf {
+ uint32_t len;
+ uint32_t resrvd;
+ uint64_t addr;
+} __packed;
+
+struct qat_alg_buf_list {
+ uint64_t resrvd;
+ uint32_t num_bufs;
+ uint32_t num_mapped_bufs;
+ struct qat_alg_buf bufers[];
+} __packed __aligned(64);
+
+/* Common content descriptor */
+struct qat_alg_cd {
+ union {
+ struct qat_enc { /* Encrypt content desc */
+ struct icp_qat_hw_cipher_algo_blk cipher;
+ struct icp_qat_hw_auth_algo_blk hash;
+ } qat_enc_cd;
+ struct qat_dec { /* Decrytp content desc */
+ struct icp_qat_hw_auth_algo_blk hash;
+ struct icp_qat_hw_cipher_algo_blk cipher;
+ } qat_dec_cd;
+ };
+} __aligned(64);
+
+#define MAX_AUTH_STATE_SIZE sizeof(struct icp_qat_hw_auth_algo_blk)
+
+struct qat_auth_state {
+ uint8_t data[MAX_AUTH_STATE_SIZE];
+} __aligned(64);
+
+struct qat_alg_session_ctx {
+ struct qat_alg_cd *enc_cd;
+ dma_addr_t enc_cd_paddr;
+ struct qat_alg_cd *dec_cd;
+ dma_addr_t dec_cd_paddr;
+ struct qat_auth_state *auth_hw_state_enc;
+ dma_addr_t auth_state_enc_paddr;
+ struct qat_auth_state *auth_hw_state_dec;
+ dma_addr_t auth_state_dec_paddr;
+ struct icp_qat_fw_la_bulk_req enc_fw_req_tmpl;
+ struct icp_qat_fw_la_bulk_req dec_fw_req_tmpl;
+ struct qat_crypto_instance *inst;
+ struct crypto_tfm *tfm;
+ struct crypto_shash *hash_tfm;
+ enum icp_qat_hw_auth_algo qat_hash_alg;
+ uint8_t salt[AES_BLOCK_SIZE];
+ spinlock_t lock; /* protects qat_alg_session_ctx struct */
+};
+
+static int get_current_node(void)
+{
+ return cpu_data(current_thread_info()->cpu).phys_proc_id;
+}
+
+static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg)
+{
+ switch (qat_hash_alg) {
+ case ICP_QAT_HW_AUTH_ALGO_SHA1:
+ return ICP_QAT_HW_SHA1_STATE1_SZ;
+ case ICP_QAT_HW_AUTH_ALGO_SHA256:
+ return ICP_QAT_HW_SHA256_STATE1_SZ;
+ case ICP_QAT_HW_AUTH_ALGO_SHA512:
+ return ICP_QAT_HW_SHA512_STATE1_SZ;
+ default:
+ return -EFAULT;
+ };
+ return -EFAULT;
+}
+
+static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash,
+ struct qat_alg_session_ctx *ctx,
+ const uint8_t *auth_key,
+ unsigned int auth_keylen, uint8_t *auth_state)
+{
+ struct {
+ struct shash_desc shash;
+ char ctx[crypto_shash_descsize(ctx->hash_tfm)];
+ } desc;
+ struct sha1_state sha1;
+ struct sha256_state sha256;
+ struct sha512_state sha512;
+ int block_size = crypto_shash_blocksize(ctx->hash_tfm);
+ int digest_size = crypto_shash_digestsize(ctx->hash_tfm);
+ uint8_t *ipad = auth_state;
+ uint8_t *opad = ipad + block_size;
+ __be32 *hash_state_out;
+ __be64 *hash512_state_out;
+ int i, offset;
+
+ desc.shash.tfm = ctx->hash_tfm;
+ desc.shash.flags = 0x0;
+
+ if (auth_keylen > block_size) {
+ char buff[SHA512_BLOCK_SIZE];
+ int ret = crypto_shash_digest(&desc.shash, auth_key,
+ auth_keylen, buff);
+ if (ret)
+ return ret;
+
+ memcpy(ipad, buff, digest_size);
+ memcpy(opad, buff, digest_size);
+ memset(ipad + digest_size, 0, block_size - digest_size);
+ memset(opad + digest_size, 0, block_size - digest_size);
+ } else {
+ memcpy(ipad, auth_key, auth_keylen);
+ memcpy(opad, auth_key, auth_keylen);
+ memset(ipad + auth_keylen, 0, block_size - auth_keylen);
+ memset(opad + auth_keylen, 0, block_size - auth_keylen);
+ }
+
+ for (i = 0; i < block_size; i++) {
+ char *ipad_ptr = ipad + i;
+ char *opad_ptr = opad + i;
+ *ipad_ptr ^= 0x36;
+ *opad_ptr ^= 0x5C;
+ }
+
+ if (crypto_shash_init(&desc.shash))
+ return -EFAULT;
+
+ if (crypto_shash_update(&desc.shash, ipad, block_size))
+ return -EFAULT;
+
+ hash_state_out = (__be32 *)hash->sha.state1;
+ hash512_state_out = (__be64 *)hash_state_out;
+
+ switch (ctx->qat_hash_alg) {
+ case ICP_QAT_HW_AUTH_ALGO_SHA1:
+ if (crypto_shash_export(&desc.shash, &sha1))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+ *hash_state_out = cpu_to_be32(*(sha1.state + i));
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA256:
+ if (crypto_shash_export(&desc.shash, &sha256))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+ *hash_state_out = cpu_to_be32(*(sha256.state + i));
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA512:
+ if (crypto_shash_export(&desc.shash, &sha512))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 3; i++, hash512_state_out++)
+ *hash512_state_out = cpu_to_be64(*(sha512.state + i));
+ break;
+ default:
+ return -EFAULT;
+ }
+
+ if (crypto_shash_init(&desc.shash))
+ return -EFAULT;
+
+ if (crypto_shash_update(&desc.shash, opad, block_size))
+ return -EFAULT;
+
+ offset = round_up(qat_get_inter_state_size(ctx->qat_hash_alg), 8);
+ hash_state_out = (__be32 *)(hash->sha.state1 + offset);
+ hash512_state_out = (__be64 *)hash_state_out;
+
+ switch (ctx->qat_hash_alg) {
+ case ICP_QAT_HW_AUTH_ALGO_SHA1:
+ if (crypto_shash_export(&desc.shash, &sha1))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+ *hash_state_out = cpu_to_be32(*(sha1.state + i));
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA256:
+ if (crypto_shash_export(&desc.shash, &sha256))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 2; i++, hash_state_out++)
+ *hash_state_out = cpu_to_be32(*(sha256.state + i));
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA512:
+ if (crypto_shash_export(&desc.shash, &sha512))
+ return -EFAULT;
+ for (i = 0; i < digest_size >> 3; i++, hash512_state_out++)
+ *hash512_state_out = cpu_to_be64(*(sha512.state + i));
+ break;
+ default:
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header)
+{
+ header->hdr_flags =
+ ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
+ header->service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_LA;
+ header->comn_req_flags =
+ ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_CD_FLD_TYPE_64BIT_ADR,
+ QAT_COMN_PTR_TYPE_SGL);
+ ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_DIGEST_IN_BUFFER);
+ ICP_QAT_FW_LA_PARTIAL_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_PARTIAL_NONE);
+ ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags,
+ ICP_QAT_FW_CIPH_IV_16BYTE_DATA);
+ ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_NO_PROTO);
+ ICP_QAT_FW_LA_UPDATE_STATE_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_NO_UPDATE_STATE);
+}
+
+static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx,
+ int alg, struct crypto_authenc_keys *keys)
+{
+ struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
+ unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+ struct qat_enc *enc_ctx = &ctx->enc_cd->qat_enc_cd;
+ struct icp_qat_hw_cipher_algo_blk *cipher = &enc_ctx->cipher;
+ struct icp_qat_hw_auth_algo_blk *hash =
+ (struct icp_qat_hw_auth_algo_blk *)((char *)enc_ctx +
+ sizeof(struct icp_qat_hw_auth_setup) + keys->enckeylen);
+ struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->enc_fw_req_tmpl;
+ struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars;
+ struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr;
+ void *ptr = &req_tmpl->cd_ctrl;
+ struct icp_qat_fw_cipher_cd_ctrl_hdr *cipher_cd_ctrl = ptr;
+ struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr;
+ struct icp_qat_fw_la_auth_req_params *auth_param =
+ (struct icp_qat_fw_la_auth_req_params *)
+ ((char *)&req_tmpl->serv_specif_rqpars +
+ sizeof(struct icp_qat_fw_la_cipher_req_params));
+
+ /* CD setup */
+ cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg);
+ memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
+ hash->sha.inner_setup.auth_config.config =
+ ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
+ ctx->qat_hash_alg, digestsize);
+ hash->sha.inner_setup.auth_counter.counter =
+ cpu_to_be32(crypto_shash_blocksize(ctx->hash_tfm));
+
+ if (qat_alg_do_precomputes(hash, ctx, keys->authkey, keys->authkeylen,
+ (uint8_t *)ctx->auth_hw_state_enc))
+ return -EFAULT;
+
+ /* Request setup */
+ qat_alg_init_common_hdr(header);
+ header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER_HASH;
+ ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_RET_AUTH_RES);
+ ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_NO_CMP_AUTH_RES);
+ cd_pars->u.s.content_desc_addr = ctx->enc_cd_paddr;
+ cd_pars->u.s.content_desc_params_sz = sizeof(struct qat_alg_cd) >> 3;
+
+ /* Cipher CD config setup */
+ cipher_cd_ctrl->cipher_key_sz = keys->enckeylen >> 3;
+ cipher_cd_ctrl->cipher_state_sz = AES_BLOCK_SIZE >> 3;
+ cipher_cd_ctrl->cipher_cfg_offset = 0;
+ ICP_QAT_FW_COMN_CURR_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+ ICP_QAT_FW_COMN_NEXT_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+ /* Auth CD config setup */
+ hash_cd_ctrl->hash_cfg_offset = ((char *)hash - (char *)cipher) >> 3;
+ hash_cd_ctrl->hash_flags = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED;
+ hash_cd_ctrl->inner_res_sz = digestsize;
+ hash_cd_ctrl->final_sz = digestsize;
+
+ switch (ctx->qat_hash_alg) {
+ case ICP_QAT_HW_AUTH_ALGO_SHA1:
+ hash_cd_ctrl->inner_state1_sz =
+ round_up(ICP_QAT_HW_SHA1_STATE1_SZ, 8);
+ hash_cd_ctrl->inner_state2_sz =
+ round_up(ICP_QAT_HW_SHA1_STATE2_SZ, 8);
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA256:
+ hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA256_STATE1_SZ;
+ hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA256_STATE2_SZ;
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA512:
+ hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA512_STATE1_SZ;
+ hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA512_STATE2_SZ;
+ break;
+ default:
+ break;
+ }
+ hash_cd_ctrl->inner_state2_offset = hash_cd_ctrl->hash_cfg_offset +
+ ((sizeof(struct icp_qat_hw_auth_setup) +
+ round_up(hash_cd_ctrl->inner_state1_sz, 8)) >> 3);
+ auth_param->u1.auth_partial_st_prefix = ctx->auth_state_enc_paddr +
+ sizeof(struct icp_qat_hw_auth_counter) +
+ round_up(hash_cd_ctrl->inner_state1_sz, 8);
+ ICP_QAT_FW_COMN_CURR_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+ ICP_QAT_FW_COMN_NEXT_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_DRAM_WR);
+ return 0;
+}
+
+static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx,
+ int alg, struct crypto_authenc_keys *keys)
+{
+ struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm);
+ unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize;
+ struct qat_dec *dec_ctx = &ctx->dec_cd->qat_dec_cd;
+ struct icp_qat_hw_auth_algo_blk *hash = &dec_ctx->hash;
+ struct icp_qat_hw_cipher_algo_blk *cipher =
+ (struct icp_qat_hw_cipher_algo_blk *)((char *)dec_ctx +
+ sizeof(struct icp_qat_hw_auth_setup) +
+ roundup(crypto_shash_digestsize(ctx->hash_tfm), 8) * 2);
+ struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->dec_fw_req_tmpl;
+ struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars;
+ struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr;
+ void *ptr = &req_tmpl->cd_ctrl;
+ struct icp_qat_fw_cipher_cd_ctrl_hdr *cipher_cd_ctrl = ptr;
+ struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr;
+ struct icp_qat_fw_la_auth_req_params *auth_param =
+ (struct icp_qat_fw_la_auth_req_params *)
+ ((char *)&req_tmpl->serv_specif_rqpars +
+ sizeof(struct icp_qat_fw_la_cipher_req_params));
+
+ /* CD setup */
+ cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_DEC(alg);
+ memcpy(cipher->aes.key, keys->enckey, keys->enckeylen);
+ hash->sha.inner_setup.auth_config.config =
+ ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
+ ctx->qat_hash_alg,
+ digestsize);
+ hash->sha.inner_setup.auth_counter.counter =
+ cpu_to_be32(crypto_shash_blocksize(ctx->hash_tfm));
+
+ if (qat_alg_do_precomputes(hash, ctx, keys->authkey, keys->authkeylen,
+ (uint8_t *)ctx->auth_hw_state_dec))
+ return -EFAULT;
+
+ /* Request setup */
+ qat_alg_init_common_hdr(header);
+ header->service_cmd_id = ICP_QAT_FW_LA_CMD_HASH_CIPHER;
+ ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_NO_RET_AUTH_RES);
+ ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags,
+ ICP_QAT_FW_LA_CMP_AUTH_RES);
+ cd_pars->u.s.content_desc_addr = ctx->dec_cd_paddr;
+ cd_pars->u.s.content_desc_params_sz = sizeof(struct qat_alg_cd) >> 3;
+
+ /* Cipher CD config setup */
+ cipher_cd_ctrl->cipher_key_sz = keys->enckeylen >> 3;
+ cipher_cd_ctrl->cipher_state_sz = AES_BLOCK_SIZE >> 3;
+ cipher_cd_ctrl->cipher_cfg_offset =
+ (sizeof(struct icp_qat_hw_auth_setup) +
+ roundup(crypto_shash_digestsize(ctx->hash_tfm), 8) * 2) >> 3;
+ ICP_QAT_FW_COMN_CURR_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+ ICP_QAT_FW_COMN_NEXT_ID_SET(cipher_cd_ctrl, ICP_QAT_FW_SLICE_DRAM_WR);
+
+ /* Auth CD config setup */
+ hash_cd_ctrl->hash_cfg_offset = 0;
+ hash_cd_ctrl->hash_flags = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED;
+ hash_cd_ctrl->inner_res_sz = digestsize;
+ hash_cd_ctrl->final_sz = digestsize;
+
+ switch (ctx->qat_hash_alg) {
+ case ICP_QAT_HW_AUTH_ALGO_SHA1:
+ hash_cd_ctrl->inner_state1_sz =
+ round_up(ICP_QAT_HW_SHA1_STATE1_SZ, 8);
+ hash_cd_ctrl->inner_state2_sz =
+ round_up(ICP_QAT_HW_SHA1_STATE2_SZ, 8);
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA256:
+ hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA256_STATE1_SZ;
+ hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA256_STATE2_SZ;
+ break;
+ case ICP_QAT_HW_AUTH_ALGO_SHA512:
+ hash_cd_ctrl->inner_state1_sz = ICP_QAT_HW_SHA512_STATE1_SZ;
+ hash_cd_ctrl->inner_state2_sz = ICP_QAT_HW_SHA512_STATE2_SZ;
+ break;
+ default:
+ break;
+ }
+
+ hash_cd_ctrl->inner_state2_offset = hash_cd_ctrl->hash_cfg_offset +
+ ((sizeof(struct icp_qat_hw_auth_setup) +
+ round_up(hash_cd_ctrl->inner_state1_sz, 8)) >> 3);
+ auth_param->u1.auth_partial_st_prefix = ctx->auth_state_enc_paddr +
+ sizeof(struct icp_qat_hw_auth_counter) +
+ round_up(hash_cd_ctrl->inner_state1_sz, 8);
+ auth_param->auth_res_sz = digestsize;
+ ICP_QAT_FW_COMN_CURR_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_AUTH);
+ ICP_QAT_FW_COMN_NEXT_ID_SET(hash_cd_ctrl, ICP_QAT_FW_SLICE_CIPHER);
+ return 0;
+}
+
+static int qat_alg_init_sessions(struct qat_alg_session_ctx *ctx,
+ const uint8_t *key, unsigned int keylen)
+{
+ struct crypto_authenc_keys keys;
+ int alg;
+
+ if (crypto_rng_get_bytes(crypto_default_rng, ctx->salt, AES_BLOCK_SIZE))
+ return -EFAULT;
+
+ if (crypto_authenc_extractkeys(&keys, key, keylen))
+ goto bad_key;
+
+ switch (keys.enckeylen) {
+ case AES_KEYSIZE_128:
+ alg = ICP_QAT_HW_CIPHER_ALGO_AES128;
+ break;
+ case AES_KEYSIZE_192:
+ alg = ICP_QAT_HW_CIPHER_ALGO_AES192;
+ break;
+ case AES_KEYSIZE_256:
+ alg = ICP_QAT_HW_CIPHER_ALGO_AES256;
+ break;
+ default:
+ goto bad_key;
+ break;
+ }
+
+ if (qat_alg_init_enc_session(ctx, alg, &keys))
+ goto error;
+
+ if (qat_alg_init_dec_session(ctx, alg, &keys))
+ goto error;
+
+ return 0;
+bad_key:
+ crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+error:
+ return -EFAULT;
+}
+
+static int qat_alg_setkey(struct crypto_aead *tfm, const uint8_t *key,
+ unsigned int keylen)
+{
+ struct qat_alg_session_ctx *ctx = crypto_aead_ctx(tfm);
+ struct device *dev;
+
+ spin_lock(&ctx->lock);
+ if (ctx->enc_cd) {
+ /* rekeying */
+ dev = &GET_DEV(ctx->inst->accel_dev);
+ memset(ctx->enc_cd, 0, sizeof(struct qat_alg_cd));
+ memset(ctx->dec_cd, 0, sizeof(struct qat_alg_cd));
+ memset(ctx->auth_hw_state_enc, 0,
+ sizeof(struct qat_auth_state));
+ memset(ctx->auth_hw_state_dec, 0,
+ sizeof(struct qat_auth_state));
+ memset(&ctx->enc_fw_req_tmpl, 0,
+ sizeof(struct icp_qat_fw_la_bulk_req));
+ memset(&ctx->dec_fw_req_tmpl, 0,
+ sizeof(struct icp_qat_fw_la_bulk_req));
+ } else {
+ /* new key */
+ int node = get_current_node();
+ struct qat_crypto_instance *inst =
+ qat_crypto_get_instance_node(node);
+ if (!inst) {
+ spin_unlock(&ctx->lock);
+ return -EINVAL;
+ }
+
+ dev = &GET_DEV(inst->accel_dev);
+ ctx->inst = inst;
+ ctx->enc_cd = dma_zalloc_coherent(dev,
+ sizeof(struct qat_alg_cd),
+ &ctx->enc_cd_paddr,
+ GFP_ATOMIC);
+ if (!ctx->enc_cd) {
+ spin_unlock(&ctx->lock);
+ return -ENOMEM;
+ }
+ ctx->dec_cd = dma_zalloc_coherent(dev,
+ sizeof(struct qat_alg_cd),
+ &ctx->dec_cd_paddr,
+ GFP_ATOMIC);
+ if (!ctx->dec_cd) {
+ spin_unlock(&ctx->lock);
+ goto out_free_enc;
+ }
+ ctx->auth_hw_state_enc =
+ dma_zalloc_coherent(dev, sizeof(struct qat_auth_state),
+ &ctx->auth_state_enc_paddr,
+ GFP_ATOMIC);
+ if (!ctx->auth_hw_state_enc) {
+ spin_unlock(&ctx->lock);
+ goto out_free_dec;
+ }
+ ctx->auth_hw_state_dec =
+ dma_zalloc_coherent(dev, sizeof(struct qat_auth_state),
+ &ctx->auth_state_dec_paddr,
+ GFP_ATOMIC);
+ if (!ctx->auth_hw_state_dec) {
+ spin_unlock(&ctx->lock);
+ goto out_free_auth_enc;
+ }
+ }
+ spin_unlock(&ctx->lock);
+ if (qat_alg_init_sessions(ctx, key, keylen))
+ goto out_free_all;
+
+ return 0;
+
+out_free_all:
+ dma_free_coherent(dev, sizeof(struct qat_auth_state),
+ ctx->auth_hw_state_dec, ctx->auth_state_dec_paddr);
+ ctx->auth_hw_state_dec = NULL;
+out_free_auth_enc:
+ dma_free_coherent(dev, sizeof(struct qat_auth_state),
+ ctx->auth_hw_state_enc, ctx->auth_state_enc_paddr);
+ ctx->auth_hw_state_enc = NULL;
+out_free_dec:
+ dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+ ctx->dec_cd, ctx->dec_cd_paddr);
+ ctx->dec_cd = NULL;
+out_free_enc:
+ dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+ ctx->enc_cd, ctx->enc_cd_paddr);
+ ctx->enc_cd = NULL;
+ return -ENOMEM;
+}
+
+static void qat_alg_free_bufl(struct qat_crypto_instance *inst,
+ struct qat_crypto_request *qat_req)
+{
+ struct device *dev = &GET_DEV(inst->accel_dev);
+ struct qat_alg_buf_list *bl = qat_req->buf.bl;
+ struct qat_alg_buf_list *blout = qat_req->buf.blout;
+ dma_addr_t blp = qat_req->buf.blp;
+ dma_addr_t blpout = qat_req->buf.bloutp;
+ size_t sz = qat_req->buf.sz;
+ int i, bufs = bl->num_bufs;
+
+ for (i = 0; i < bl->num_bufs; i++)
+ dma_unmap_single(dev, bl->bufers[i].addr,
+ bl->bufers[i].len, DMA_BIDIRECTIONAL);
+
+ dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE);
+ kfree(bl);
+ if (blp != blpout) {
+ /* If out of place operation dma unmap only data */
+ int bufless = bufs - blout->num_mapped_bufs;
+
+ for (i = bufless; i < bufs; i++) {
+ dma_unmap_single(dev, blout->bufers[i].addr,
+ blout->bufers[i].len,
+ DMA_BIDIRECTIONAL);
+ }
+ dma_unmap_single(dev, blpout, sz, DMA_TO_DEVICE);
+ kfree(blout);
+ }
+}
+
+static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
+ struct scatterlist *assoc,
+ struct scatterlist *sgl,
+ struct scatterlist *sglout, uint8_t *iv,
+ uint8_t ivlen,
+ struct qat_crypto_request *qat_req)
+{
+ struct device *dev = &GET_DEV(inst->accel_dev);
+ int i, bufs = 0, n = sg_nents(sgl), assoc_n = sg_nents(assoc);
+ struct qat_alg_buf_list *bufl;
+ struct qat_alg_buf_list *buflout = NULL;
+ dma_addr_t blp;
+ dma_addr_t bloutp = 0;
+ struct scatterlist *sg;
+ size_t sz = sizeof(struct qat_alg_buf_list) +
+ ((1 + n + assoc_n) * sizeof(struct qat_alg_buf));
+
+ if (unlikely(!n))
+ return -EINVAL;
+
+ bufl = kmalloc_node(sz, GFP_ATOMIC, inst->accel_dev->numa_node);
+ if (unlikely(!bufl))
+ return -ENOMEM;
+
+ blp = dma_map_single(dev, bufl, sz, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, blp)))
+ goto err;
+
+ for_each_sg(assoc, sg, assoc_n, i) {
+ bufl->bufers[bufs].addr = dma_map_single(dev,
+ sg_virt(sg),
+ sg->length,
+ DMA_BIDIRECTIONAL);
+ bufl->bufers[bufs].len = sg->length;
+ if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
+ goto err;
+ bufs++;
+ }
+ bufl->bufers[bufs].addr = dma_map_single(dev, iv, ivlen,
+ DMA_BIDIRECTIONAL);
+ bufl->bufers[bufs].len = ivlen;
+ if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr)))
+ goto err;
+ bufs++;
+
+ for_each_sg(sgl, sg, n, i) {
+ int y = i + bufs;
+
+ bufl->bufers[y].addr = dma_map_single(dev, sg_virt(sg),
+ sg->length,
+ DMA_BIDIRECTIONAL);
+ bufl->bufers[y].len = sg->length;
+ if (unlikely(dma_mapping_error(dev, bufl->bufers[y].addr)))
+ goto err;
+ }
+ bufl->num_bufs = n + bufs;
+ qat_req->buf.bl = bufl;
+ qat_req->buf.blp = blp;
+ qat_req->buf.sz = sz;
+ /* Handle out of place operation */
+ if (sgl != sglout) {
+ struct qat_alg_buf *bufers;
+
+ buflout = kmalloc_node(sz, GFP_ATOMIC,
+ inst->accel_dev->numa_node);
+ if (unlikely(!buflout))
+ goto err;
+ bloutp = dma_map_single(dev, buflout, sz, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, bloutp)))
+ goto err;
+ bufers = buflout->bufers;
+ /* For out of place operation dma map only data and
+ * reuse assoc mapping and iv */
+ for (i = 0; i < bufs; i++) {
+ bufers[i].len = bufl->bufers[i].len;
+ bufers[i].addr = bufl->bufers[i].addr;
+ }
+ for_each_sg(sglout, sg, n, i) {
+ int y = i + bufs;
+
+ bufers[y].addr = dma_map_single(dev, sg_virt(sg),
+ sg->length,
+ DMA_BIDIRECTIONAL);
+ buflout->bufers[y].len = sg->length;
+ if (unlikely(dma_mapping_error(dev, bufers[y].addr)))
+ goto err;
+ }
+ buflout->num_bufs = n + bufs;
+ buflout->num_mapped_bufs = n;
+ qat_req->buf.blout = buflout;
+ qat_req->buf.bloutp = bloutp;
+ } else {
+ /* Otherwise set the src and dst to the same address */
+ qat_req->buf.bloutp = qat_req->buf.blp;
+ }
+ return 0;
+err:
+ dev_err(dev, "Failed to map buf for dma\n");
+ for_each_sg(sgl, sg, n + bufs, i) {
+ if (!dma_mapping_error(dev, bufl->bufers[i].addr)) {
+ dma_unmap_single(dev, bufl->bufers[i].addr,
+ bufl->bufers[i].len,
+ DMA_BIDIRECTIONAL);
+ }
+ }
+ if (!dma_mapping_error(dev, blp))
+ dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE);
+ kfree(bufl);
+ if (sgl != sglout && buflout) {
+ for_each_sg(sglout, sg, n, i) {
+ int y = i + bufs;
+
+ if (!dma_mapping_error(dev, buflout->bufers[y].addr))
+ dma_unmap_single(dev, buflout->bufers[y].addr,
+ buflout->bufers[y].len,
+ DMA_BIDIRECTIONAL);
+ }
+ if (!dma_mapping_error(dev, bloutp))
+ dma_unmap_single(dev, bloutp, sz, DMA_TO_DEVICE);
+ kfree(buflout);
+ }
+ return -ENOMEM;
+}
+
+void qat_alg_callback(void *resp)
+{
+ struct icp_qat_fw_la_resp *qat_resp = resp;
+ struct qat_crypto_request *qat_req =
+ (void *)(__force long)qat_resp->opaque_data;
+ struct qat_alg_session_ctx *ctx = qat_req->ctx;
+ struct qat_crypto_instance *inst = ctx->inst;
+ struct aead_request *areq = qat_req->areq;
+ uint8_t stat_filed = qat_resp->comn_resp.comn_status;
+ int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed);
+
+ qat_alg_free_bufl(inst, qat_req);
+ if (unlikely(qat_res != ICP_QAT_FW_COMN_STATUS_FLAG_OK))
+ res = -EBADMSG;
+ areq->base.complete(&areq->base, res);
+}
+
+static int qat_alg_dec(struct aead_request *areq)
+{
+ struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
+ struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+ struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct qat_crypto_request *qat_req = aead_request_ctx(areq);
+ struct icp_qat_fw_la_cipher_req_params *cipher_param;
+ struct icp_qat_fw_la_auth_req_params *auth_param;
+ struct icp_qat_fw_la_bulk_req *msg;
+ int digst_size = crypto_aead_crt(aead_tfm)->authsize;
+ int ret, ctr = 0;
+
+ ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->src, areq->dst,
+ areq->iv, AES_BLOCK_SIZE, qat_req);
+ if (unlikely(ret))
+ return ret;
+
+ msg = &qat_req->req;
+ *msg = ctx->dec_fw_req_tmpl;
+ qat_req->ctx = ctx;
+ qat_req->areq = areq;
+ qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req;
+ qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp;
+ qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
+ cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
+ cipher_param->cipher_length = areq->cryptlen - digst_size;
+ cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
+ memcpy(cipher_param->u.cipher_IV_array, areq->iv, AES_BLOCK_SIZE);
+ auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
+ auth_param->auth_off = 0;
+ auth_param->auth_len = areq->assoclen +
+ cipher_param->cipher_length + AES_BLOCK_SIZE;
+ do {
+ ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
+ } while (ret == -EAGAIN && ctr++ < 10);
+
+ if (ret == -EAGAIN) {
+ qat_alg_free_bufl(ctx->inst, qat_req);
+ return -EBUSY;
+ }
+ return -EINPROGRESS;
+}
+
+static int qat_alg_enc_internal(struct aead_request *areq, uint8_t *iv,
+ int enc_iv)
+{
+ struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq);
+ struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+ struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct qat_crypto_request *qat_req = aead_request_ctx(areq);
+ struct icp_qat_fw_la_cipher_req_params *cipher_param;
+ struct icp_qat_fw_la_auth_req_params *auth_param;
+ struct icp_qat_fw_la_bulk_req *msg;
+ int ret, ctr = 0;
+
+ ret = qat_alg_sgl_to_bufl(ctx->inst, areq->assoc, areq->src, areq->dst,
+ iv, AES_BLOCK_SIZE, qat_req);
+ if (unlikely(ret))
+ return ret;
+
+ msg = &qat_req->req;
+ *msg = ctx->enc_fw_req_tmpl;
+ qat_req->ctx = ctx;
+ qat_req->areq = areq;
+ qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req;
+ qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp;
+ qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
+ cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
+ auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
+
+ if (enc_iv) {
+ cipher_param->cipher_length = areq->cryptlen + AES_BLOCK_SIZE;
+ cipher_param->cipher_offset = areq->assoclen;
+ } else {
+ memcpy(cipher_param->u.cipher_IV_array, iv, AES_BLOCK_SIZE);
+ cipher_param->cipher_length = areq->cryptlen;
+ cipher_param->cipher_offset = areq->assoclen + AES_BLOCK_SIZE;
+ }
+ auth_param->auth_off = 0;
+ auth_param->auth_len = areq->assoclen + areq->cryptlen + AES_BLOCK_SIZE;
+
+ do {
+ ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
+ } while (ret == -EAGAIN && ctr++ < 10);
+
+ if (ret == -EAGAIN) {
+ qat_alg_free_bufl(ctx->inst, qat_req);
+ return -EBUSY;
+ }
+ return -EINPROGRESS;
+}
+
+static int qat_alg_enc(struct aead_request *areq)
+{
+ return qat_alg_enc_internal(areq, areq->iv, 0);
+}
+
+static int qat_alg_genivenc(struct aead_givcrypt_request *req)
+{
+ struct crypto_aead *aead_tfm = crypto_aead_reqtfm(&req->areq);
+ struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm);
+ struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+ __be64 seq;
+
+ memcpy(req->giv, ctx->salt, AES_BLOCK_SIZE);
+ seq = cpu_to_be64(req->seq);
+ memcpy(req->giv + AES_BLOCK_SIZE - sizeof(uint64_t),
+ &seq, sizeof(uint64_t));
+ return qat_alg_enc_internal(&req->areq, req->giv, 1);
+}
+
+static int qat_alg_init(struct crypto_tfm *tfm,
+ enum icp_qat_hw_auth_algo hash, const char *hash_name)
+{
+ struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ memset(ctx, '\0', sizeof(*ctx));
+ ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
+ if (IS_ERR(ctx->hash_tfm))
+ return -EFAULT;
+ spin_lock_init(&ctx->lock);
+ ctx->qat_hash_alg = hash;
+ tfm->crt_aead.reqsize = sizeof(struct aead_request) +
+ sizeof(struct qat_crypto_request);
+ ctx->tfm = tfm;
+ return 0;
+}
+
+static int qat_alg_sha1_init(struct crypto_tfm *tfm)
+{
+ return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA1, "sha1");
+}
+
+static int qat_alg_sha256_init(struct crypto_tfm *tfm)
+{
+ return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA256, "sha256");
+}
+
+static int qat_alg_sha512_init(struct crypto_tfm *tfm)
+{
+ return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA512, "sha512");
+}
+
+static void qat_alg_exit(struct crypto_tfm *tfm)
+{
+ struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct qat_crypto_instance *inst = ctx->inst;
+ struct device *dev;
+
+ if (!IS_ERR(ctx->hash_tfm))
+ crypto_free_shash(ctx->hash_tfm);
+
+ if (!inst)
+ return;
+
+ dev = &GET_DEV(inst->accel_dev);
+ if (ctx->enc_cd)
+ dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+ ctx->enc_cd, ctx->enc_cd_paddr);
+ if (ctx->dec_cd)
+ dma_free_coherent(dev, sizeof(struct qat_alg_cd),
+ ctx->dec_cd, ctx->dec_cd_paddr);
+ if (ctx->auth_hw_state_enc)
+ dma_free_coherent(dev, sizeof(struct qat_auth_state),
+ ctx->auth_hw_state_enc,
+ ctx->auth_state_enc_paddr);
+
+ if (ctx->auth_hw_state_dec)
+ dma_free_coherent(dev, sizeof(struct qat_auth_state),
+ ctx->auth_hw_state_dec,
+ ctx->auth_state_dec_paddr);
+
+ qat_crypto_put_instance(inst);
+}
+
+static struct crypto_alg qat_algs[] = { {
+ .cra_name = "authenc(hmac(sha1),cbc(aes))",
+ .cra_driver_name = "qat_aes_cbc_hmac_sha1",
+ .cra_priority = 4001,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = qat_alg_sha1_init,
+ .cra_exit = qat_alg_exit,
+ .cra_u = {
+ .aead = {
+ .setkey = qat_alg_setkey,
+ .decrypt = qat_alg_dec,
+ .encrypt = qat_alg_enc,
+ .givencrypt = qat_alg_genivenc,
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ },
+}, {
+ .cra_name = "authenc(hmac(sha256),cbc(aes))",
+ .cra_driver_name = "qat_aes_cbc_hmac_sha256",
+ .cra_priority = 4001,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = qat_alg_sha256_init,
+ .cra_exit = qat_alg_exit,
+ .cra_u = {
+ .aead = {
+ .setkey = qat_alg_setkey,
+ .decrypt = qat_alg_dec,
+ .encrypt = qat_alg_enc,
+ .givencrypt = qat_alg_genivenc,
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ },
+}, {
+ .cra_name = "authenc(hmac(sha512),cbc(aes))",
+ .cra_driver_name = "qat_aes_cbc_hmac_sha512",
+ .cra_priority = 4001,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct qat_alg_session_ctx),
+ .cra_alignmask = 0,
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = qat_alg_sha512_init,
+ .cra_exit = qat_alg_exit,
+ .cra_u = {
+ .aead = {
+ .setkey = qat_alg_setkey,
+ .decrypt = qat_alg_dec,
+ .encrypt = qat_alg_enc,
+ .givencrypt = qat_alg_genivenc,
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA512_DIGEST_SIZE,
+ },
+ },
+} };
+
+int qat_algs_register(void)
+{
+ if (atomic_add_return(1, &active_dev) == 1) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(qat_algs); i++)
+ qat_algs[i].cra_flags = CRYPTO_ALG_TYPE_AEAD |
+ CRYPTO_ALG_ASYNC;
+ return crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
+ }
+ return 0;
+}
+
+int qat_algs_unregister(void)
+{
+ if (atomic_sub_return(1, &active_dev) == 0)
+ return crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+ return 0;
+}
+
+int qat_algs_init(void)
+{
+ atomic_set(&active_dev, 0);
+ crypto_get_default_rng();
+ return 0;
+}
+
+void qat_algs_exit(void)
+{
+ crypto_put_default_rng();
+}
diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c
new file mode 100644
index 000000000000..0d59bcb50de1
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_crypto.c
@@ -0,0 +1,284 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_transport.h"
+#include "adf_cfg.h"
+#include "adf_cfg_strings.h"
+#include "qat_crypto.h"
+#include "icp_qat_fw.h"
+
+#define SEC ADF_KERNEL_SEC
+
+static struct service_hndl qat_crypto;
+
+void qat_crypto_put_instance(struct qat_crypto_instance *inst)
+{
+ if (atomic_sub_return(1, &inst->refctr) == 0)
+ adf_dev_put(inst->accel_dev);
+}
+
+static int qat_crypto_free_instances(struct adf_accel_dev *accel_dev)
+{
+ struct qat_crypto_instance *inst;
+ struct list_head *list_ptr, *tmp;
+ int i;
+
+ list_for_each_safe(list_ptr, tmp, &accel_dev->crypto_list) {
+ inst = list_entry(list_ptr, struct qat_crypto_instance, list);
+
+ for (i = 0; i < atomic_read(&inst->refctr); i++)
+ qat_crypto_put_instance(inst);
+
+ if (inst->sym_tx)
+ adf_remove_ring(inst->sym_tx);
+
+ if (inst->sym_rx)
+ adf_remove_ring(inst->sym_rx);
+
+ if (inst->pke_tx)
+ adf_remove_ring(inst->pke_tx);
+
+ if (inst->pke_rx)
+ adf_remove_ring(inst->pke_rx);
+
+ if (inst->rnd_tx)
+ adf_remove_ring(inst->rnd_tx);
+
+ if (inst->rnd_rx)
+ adf_remove_ring(inst->rnd_rx);
+
+ list_del(list_ptr);
+ kfree(inst);
+ }
+ return 0;
+}
+
+struct qat_crypto_instance *qat_crypto_get_instance_node(int node)
+{
+ struct adf_accel_dev *accel_dev = NULL;
+ struct qat_crypto_instance *inst_best = NULL;
+ struct list_head *itr;
+ unsigned long best = ~0;
+
+ list_for_each(itr, adf_devmgr_get_head()) {
+ accel_dev = list_entry(itr, struct adf_accel_dev, list);
+ if (accel_dev->numa_node == node && adf_dev_started(accel_dev))
+ break;
+ accel_dev = NULL;
+ }
+ if (!accel_dev) {
+ pr_err("QAT: Could not find device on give node\n");
+ accel_dev = adf_devmgr_get_first();
+ }
+ if (!accel_dev || !adf_dev_started(accel_dev))
+ return NULL;
+
+ list_for_each(itr, &accel_dev->crypto_list) {
+ struct qat_crypto_instance *inst;
+ unsigned long cur;
+
+ inst = list_entry(itr, struct qat_crypto_instance, list);
+ cur = atomic_read(&inst->refctr);
+ if (best > cur) {
+ inst_best = inst;
+ best = cur;
+ }
+ }
+ if (inst_best) {
+ if (atomic_add_return(1, &inst_best->refctr) == 1) {
+ if (adf_dev_get(accel_dev)) {
+ atomic_dec(&inst_best->refctr);
+ pr_err("QAT: Could increment dev refctr\n");
+ return NULL;
+ }
+ }
+ }
+ return inst_best;
+}
+
+static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
+{
+ int i;
+ unsigned long bank;
+ unsigned long num_inst, num_msg_sym, num_msg_asym;
+ int msg_size;
+ struct qat_crypto_instance *inst;
+ char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
+
+ INIT_LIST_HEAD(&accel_dev->crypto_list);
+ strlcpy(key, ADF_NUM_CY, sizeof(key));
+
+ if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+ return -EFAULT;
+
+ if (kstrtoul(val, 0, &num_inst))
+ return -EFAULT;
+
+ for (i = 0; i < num_inst; i++) {
+ inst = kzalloc_node(sizeof(*inst), GFP_KERNEL,
+ accel_dev->numa_node);
+ if (!inst)
+ goto err;
+
+ list_add_tail(&inst->list, &accel_dev->crypto_list);
+ inst->id = i;
+ atomic_set(&inst->refctr, 0);
+ inst->accel_dev = accel_dev;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i);
+ if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+ goto err;
+
+ if (kstrtoul(val, 10, &bank))
+ goto err;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_SIZE, i);
+ if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+ goto err;
+
+ if (kstrtoul(val, 10, &num_msg_sym))
+ goto err;
+ num_msg_sym = num_msg_sym >> 1;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, i);
+ if (adf_cfg_get_param_value(accel_dev, SEC, key, val))
+ goto err;
+
+ if (kstrtoul(val, 10, &num_msg_asym))
+ goto err;
+ num_msg_asym = num_msg_asym >> 1;
+
+ msg_size = ICP_QAT_FW_REQ_DEFAULT_SZ;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_TX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_sym,
+ msg_size, key, NULL, 0, &inst->sym_tx))
+ goto err;
+
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+ msg_size, key, NULL, 0, &inst->rnd_tx))
+ goto err;
+
+ msg_size = msg_size >> 1;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+ msg_size, key, NULL, 0, &inst->pke_tx))
+ goto err;
+
+ msg_size = ICP_QAT_FW_RESP_DEFAULT_SZ;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_RX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_sym,
+ msg_size, key, qat_alg_callback, 0,
+ &inst->sym_rx))
+ goto err;
+
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+ msg_size, key, qat_alg_callback, 0,
+ &inst->rnd_rx))
+ goto err;
+
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
+ if (adf_create_ring(accel_dev, SEC, bank, num_msg_asym,
+ msg_size, key, qat_alg_callback, 0,
+ &inst->pke_rx))
+ goto err;
+ }
+ return 0;
+err:
+ qat_crypto_free_instances(accel_dev);
+ return -ENOMEM;
+}
+
+static int qat_crypto_init(struct adf_accel_dev *accel_dev)
+{
+ if (qat_crypto_create_instances(accel_dev))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int qat_crypto_shutdown(struct adf_accel_dev *accel_dev)
+{
+ return qat_crypto_free_instances(accel_dev);
+}
+
+static int qat_crypto_event_handler(struct adf_accel_dev *accel_dev,
+ enum adf_event event)
+{
+ int ret;
+
+ switch (event) {
+ case ADF_EVENT_INIT:
+ ret = qat_crypto_init(accel_dev);
+ break;
+ case ADF_EVENT_SHUTDOWN:
+ ret = qat_crypto_shutdown(accel_dev);
+ break;
+ case ADF_EVENT_RESTARTING:
+ case ADF_EVENT_RESTARTED:
+ case ADF_EVENT_START:
+ case ADF_EVENT_STOP:
+ default:
+ ret = 0;
+ }
+ return ret;
+}
+
+int qat_crypto_register(void)
+{
+ memset(&qat_crypto, 0, sizeof(qat_crypto));
+ qat_crypto.event_hld = qat_crypto_event_handler;
+ qat_crypto.name = "qat_crypto";
+ return adf_service_register(&qat_crypto);
+}
+
+int qat_crypto_unregister(void)
+{
+ return adf_service_unregister(&qat_crypto);
+}
diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h
new file mode 100644
index 000000000000..ab8468d11ddb
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_crypto.h
@@ -0,0 +1,83 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _QAT_CRYPTO_INSTANCE_H_
+#define _QAT_CRYPTO_INSTANCE_H_
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "adf_accel_devices.h"
+#include "icp_qat_fw_la.h"
+
+struct qat_crypto_instance {
+ struct adf_etr_ring_data *sym_tx;
+ struct adf_etr_ring_data *sym_rx;
+ struct adf_etr_ring_data *pke_tx;
+ struct adf_etr_ring_data *pke_rx;
+ struct adf_etr_ring_data *rnd_tx;
+ struct adf_etr_ring_data *rnd_rx;
+ struct adf_accel_dev *accel_dev;
+ struct list_head list;
+ unsigned long state;
+ int id;
+ atomic_t refctr;
+};
+
+struct qat_crypto_request_buffs {
+ struct qat_alg_buf_list *bl;
+ dma_addr_t blp;
+ struct qat_alg_buf_list *blout;
+ dma_addr_t bloutp;
+ size_t sz;
+};
+
+struct qat_crypto_request {
+ struct icp_qat_fw_la_bulk_req req;
+ struct qat_alg_session_ctx *ctx;
+ struct aead_request *areq;
+ struct qat_crypto_request_buffs buf;
+};
+#endif
diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c
new file mode 100644
index 000000000000..9b8a31521ff3
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_hal.c
@@ -0,0 +1,1393 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/slab.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_hal.h"
+#include "icp_qat_uclo.h"
+
+#define BAD_REGADDR 0xffff
+#define MAX_RETRY_TIMES 10000
+#define INIT_CTX_ARB_VALUE 0x0
+#define INIT_CTX_ENABLE_VALUE 0x0
+#define INIT_PC_VALUE 0x0
+#define INIT_WAKEUP_EVENTS_VALUE 0x1
+#define INIT_SIG_EVENTS_VALUE 0x1
+#define INIT_CCENABLE_VALUE 0x2000
+#define RST_CSR_QAT_LSB 20
+#define RST_CSR_AE_LSB 0
+#define MC_TIMESTAMP_ENABLE (0x1 << 7)
+
+#define IGNORE_W1C_MASK ((~(1 << CE_BREAKPOINT_BITPOS)) & \
+ (~(1 << CE_CNTL_STORE_PARITY_ERROR_BITPOS)) & \
+ (~(1 << CE_REG_PAR_ERR_BITPOS)))
+#define INSERT_IMMED_GPRA_CONST(inst, const_val) \
+ (inst = ((inst & 0xFFFF00C03FFull) | \
+ ((((const_val) << 12) & 0x0FF00000ull) | \
+ (((const_val) << 10) & 0x0003FC00ull))))
+#define INSERT_IMMED_GPRB_CONST(inst, const_val) \
+ (inst = ((inst & 0xFFFF00FFF00ull) | \
+ ((((const_val) << 12) & 0x0FF00000ull) | \
+ (((const_val) << 0) & 0x000000FFull))))
+
+#define AE(handle, ae) handle->hal_handle->aes[ae]
+
+static const uint64_t inst_4b[] = {
+ 0x0F0400C0000ull, 0x0F4400C0000ull, 0x0F040000300ull, 0x0F440000300ull,
+ 0x0FC066C0000ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+ 0x0A021000000ull
+};
+
+static const uint64_t inst[] = {
+ 0x0F0000C0000ull, 0x0F000000380ull, 0x0D805000011ull, 0x0FC082C0300ull,
+ 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+ 0x0A0643C0000ull, 0x0BAC0000301ull, 0x0D802000101ull, 0x0F0000C0001ull,
+ 0x0FC066C0001ull, 0x0F0000C0300ull, 0x0F0000C0300ull, 0x0F0000C0300ull,
+ 0x0F000400300ull, 0x0A0610C0000ull, 0x0BAC0000301ull, 0x0D804400101ull,
+ 0x0A0580C0000ull, 0x0A0581C0000ull, 0x0A0582C0000ull, 0x0A0583C0000ull,
+ 0x0A0584C0000ull, 0x0A0585C0000ull, 0x0A0586C0000ull, 0x0A0587C0000ull,
+ 0x0A0588C0000ull, 0x0A0589C0000ull, 0x0A058AC0000ull, 0x0A058BC0000ull,
+ 0x0A058CC0000ull, 0x0A058DC0000ull, 0x0A058EC0000ull, 0x0A058FC0000ull,
+ 0x0A05C0C0000ull, 0x0A05C1C0000ull, 0x0A05C2C0000ull, 0x0A05C3C0000ull,
+ 0x0A05C4C0000ull, 0x0A05C5C0000ull, 0x0A05C6C0000ull, 0x0A05C7C0000ull,
+ 0x0A05C8C0000ull, 0x0A05C9C0000ull, 0x0A05CAC0000ull, 0x0A05CBC0000ull,
+ 0x0A05CCC0000ull, 0x0A05CDC0000ull, 0x0A05CEC0000ull, 0x0A05CFC0000ull,
+ 0x0A0400C0000ull, 0x0B0400C0000ull, 0x0A0401C0000ull, 0x0B0401C0000ull,
+ 0x0A0402C0000ull, 0x0B0402C0000ull, 0x0A0403C0000ull, 0x0B0403C0000ull,
+ 0x0A0404C0000ull, 0x0B0404C0000ull, 0x0A0405C0000ull, 0x0B0405C0000ull,
+ 0x0A0406C0000ull, 0x0B0406C0000ull, 0x0A0407C0000ull, 0x0B0407C0000ull,
+ 0x0A0408C0000ull, 0x0B0408C0000ull, 0x0A0409C0000ull, 0x0B0409C0000ull,
+ 0x0A040AC0000ull, 0x0B040AC0000ull, 0x0A040BC0000ull, 0x0B040BC0000ull,
+ 0x0A040CC0000ull, 0x0B040CC0000ull, 0x0A040DC0000ull, 0x0B040DC0000ull,
+ 0x0A040EC0000ull, 0x0B040EC0000ull, 0x0A040FC0000ull, 0x0B040FC0000ull,
+ 0x0D81581C010ull, 0x0E000010000ull, 0x0E000010000ull,
+};
+
+void qat_hal_set_live_ctx(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask)
+{
+ AE(handle, ae).live_ctx_mask = ctx_mask;
+}
+
+#define CSR_RETRY_TIMES 500
+static int qat_hal_rd_ae_csr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int csr,
+ unsigned int *value)
+{
+ unsigned int iterations = CSR_RETRY_TIMES;
+
+ do {
+ *value = GET_AE_CSR(handle, ae, csr);
+ if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS))
+ return 0;
+ } while (iterations--);
+
+ pr_err("QAT: Read CSR timeout\n");
+ return -EFAULT;
+}
+
+static int qat_hal_wr_ae_csr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int csr,
+ unsigned int value)
+{
+ unsigned int iterations = CSR_RETRY_TIMES;
+
+ do {
+ SET_AE_CSR(handle, ae, csr, value);
+ if (!(GET_AE_CSR(handle, ae, LOCAL_CSR_STATUS) & LCS_STATUS))
+ return 0;
+ } while (iterations--);
+
+ pr_err("QAT: Write CSR Timeout\n");
+ return -EFAULT;
+}
+
+static void qat_hal_get_wakeup_event(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ unsigned int *events)
+{
+ unsigned int cur_ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+ qat_hal_rd_ae_csr(handle, ae, CTX_WAKEUP_EVENTS_INDIRECT, events);
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static int qat_hal_wait_cycles(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int cycles,
+ int chk_inactive)
+{
+ unsigned int base_cnt = 0, cur_cnt = 0;
+ unsigned int csr = (1 << ACS_ABO_BITPOS);
+ int times = MAX_RETRY_TIMES;
+ int elapsed_cycles = 0;
+
+ qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &base_cnt);
+ base_cnt &= 0xffff;
+ while ((int)cycles > elapsed_cycles && times--) {
+ if (chk_inactive)
+ qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &csr);
+
+ qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT, &cur_cnt);
+ cur_cnt &= 0xffff;
+ elapsed_cycles = cur_cnt - base_cnt;
+
+ if (elapsed_cycles < 0)
+ elapsed_cycles += 0x10000;
+
+ /* ensure at least 8 time cycles elapsed in wait_cycles */
+ if (elapsed_cycles >= 8 && !(csr & (1 << ACS_ABO_BITPOS)))
+ return 0;
+ }
+ if (!times) {
+ pr_err("QAT: wait_num_cycles time out\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+#define CLR_BIT(wrd, bit) (wrd & ~(1 << bit))
+#define SET_BIT(wrd, bit) (wrd | 1 << bit)
+
+int qat_hal_set_ae_ctx_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char mode)
+{
+ unsigned int csr, new_csr;
+
+ if ((mode != 4) && (mode != 8)) {
+ pr_err("QAT: bad ctx mode=%d\n", mode);
+ return -EINVAL;
+ }
+
+ /* Sets the accelaration engine context mode to either four or eight */
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+ csr = IGNORE_W1C_MASK & csr;
+ new_csr = (mode == 4) ?
+ SET_BIT(csr, CE_INUSE_CONTEXTS_BITPOS) :
+ CLR_BIT(csr, CE_INUSE_CONTEXTS_BITPOS);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+ return 0;
+}
+
+int qat_hal_set_ae_nn_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char mode)
+{
+ unsigned int csr, new_csr;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+ csr &= IGNORE_W1C_MASK;
+
+ new_csr = (mode) ?
+ SET_BIT(csr, CE_NN_MODE_BITPOS) :
+ CLR_BIT(csr, CE_NN_MODE_BITPOS);
+
+ if (new_csr != csr)
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+
+ return 0;
+}
+
+int qat_hal_set_ae_lm_mode(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, enum icp_qat_uof_regtype lm_type,
+ unsigned char mode)
+{
+ unsigned int csr, new_csr;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr);
+ csr &= IGNORE_W1C_MASK;
+ switch (lm_type) {
+ case ICP_LMEM0:
+ new_csr = (mode) ?
+ SET_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS) :
+ CLR_BIT(csr, CE_LMADDR_0_GLOBAL_BITPOS);
+ break;
+ case ICP_LMEM1:
+ new_csr = (mode) ?
+ SET_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS) :
+ CLR_BIT(csr, CE_LMADDR_1_GLOBAL_BITPOS);
+ break;
+ default:
+ pr_err("QAT: lmType = 0x%x\n", lm_type);
+ return -EINVAL;
+ }
+
+ if (new_csr != csr)
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, new_csr);
+ return 0;
+}
+
+static unsigned short qat_hal_get_reg_addr(unsigned int type,
+ unsigned short reg_num)
+{
+ unsigned short reg_addr;
+
+ switch (type) {
+ case ICP_GPA_ABS:
+ case ICP_GPB_ABS:
+ reg_addr = 0x80 | (reg_num & 0x7f);
+ break;
+ case ICP_GPA_REL:
+ case ICP_GPB_REL:
+ reg_addr = reg_num & 0x1f;
+ break;
+ case ICP_SR_RD_REL:
+ case ICP_SR_WR_REL:
+ case ICP_SR_REL:
+ reg_addr = 0x180 | (reg_num & 0x1f);
+ break;
+ case ICP_SR_ABS:
+ reg_addr = 0x140 | ((reg_num & 0x3) << 1);
+ break;
+ case ICP_DR_RD_REL:
+ case ICP_DR_WR_REL:
+ case ICP_DR_REL:
+ reg_addr = 0x1c0 | (reg_num & 0x1f);
+ break;
+ case ICP_DR_ABS:
+ reg_addr = 0x100 | ((reg_num & 0x3) << 1);
+ break;
+ case ICP_NEIGH_REL:
+ reg_addr = 0x280 | (reg_num & 0x1f);
+ break;
+ case ICP_LMEM0:
+ reg_addr = 0x200;
+ break;
+ case ICP_LMEM1:
+ reg_addr = 0x220;
+ break;
+ case ICP_NO_DEST:
+ reg_addr = 0x300 | (reg_num & 0xff);
+ break;
+ default:
+ reg_addr = BAD_REGADDR;
+ break;
+ }
+ return reg_addr;
+}
+
+void qat_hal_reset(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned int ae_reset_csr;
+
+ ae_reset_csr = GET_GLB_CSR(handle, ICP_RESET);
+ ae_reset_csr |= handle->hal_handle->ae_mask << RST_CSR_AE_LSB;
+ ae_reset_csr |= handle->hal_handle->slice_mask << RST_CSR_QAT_LSB;
+ SET_GLB_CSR(handle, ICP_RESET, ae_reset_csr);
+}
+
+static void qat_hal_wr_indr_csr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask,
+ unsigned int ae_csr, unsigned int csr_val)
+{
+ unsigned int ctx, cur_ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+
+ for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+ if (!(ctx_mask & (1 << ctx)))
+ continue;
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+ qat_hal_wr_ae_csr(handle, ae, ae_csr, csr_val);
+ }
+
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_rd_indr_csr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ unsigned int ae_csr, unsigned int *csr_val)
+{
+ unsigned int cur_ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+ qat_hal_rd_ae_csr(handle, ae, ae_csr, csr_val);
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_put_sig_event(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask,
+ unsigned int events)
+{
+ unsigned int ctx, cur_ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+ for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+ if (!(ctx_mask & (1 << ctx)))
+ continue;
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+ qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_INDIRECT, events);
+ }
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static void qat_hal_put_wakeup_event(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask,
+ unsigned int events)
+{
+ unsigned int ctx, cur_ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CSR_CTX_POINTER, &cur_ctx);
+ for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+ if (!(ctx_mask & (1 << ctx)))
+ continue;
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, ctx);
+ qat_hal_wr_ae_csr(handle, ae, CTX_WAKEUP_EVENTS_INDIRECT,
+ events);
+ }
+ qat_hal_wr_ae_csr(handle, ae, CSR_CTX_POINTER, cur_ctx);
+}
+
+static int qat_hal_check_ae_alive(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned int base_cnt, cur_cnt;
+ unsigned char ae;
+ unsigned int times = MAX_RETRY_TIMES;
+
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!(handle->hal_handle->ae_mask & (1 << ae)))
+ continue;
+
+ qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT,
+ (unsigned int *)&base_cnt);
+ base_cnt &= 0xffff;
+
+ do {
+ qat_hal_rd_ae_csr(handle, ae, PROFILE_COUNT,
+ (unsigned int *)&cur_cnt);
+ cur_cnt &= 0xffff;
+ } while (times-- && (cur_cnt == base_cnt));
+
+ if (!times) {
+ pr_err("QAT: AE%d is inactive!!\n", ae);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+static void qat_hal_reset_timestamp(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned int misc_ctl;
+ unsigned char ae;
+
+ /* stop the timestamp timers */
+ misc_ctl = GET_GLB_CSR(handle, MISC_CONTROL);
+ if (misc_ctl & MC_TIMESTAMP_ENABLE)
+ SET_GLB_CSR(handle, MISC_CONTROL, misc_ctl &
+ (~MC_TIMESTAMP_ENABLE));
+
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!(handle->hal_handle->ae_mask & (1 << ae)))
+ continue;
+ qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_LOW, 0);
+ qat_hal_wr_ae_csr(handle, ae, TIMESTAMP_HIGH, 0);
+ }
+ /* start timestamp timers */
+ SET_GLB_CSR(handle, MISC_CONTROL, misc_ctl | MC_TIMESTAMP_ENABLE);
+}
+
+#define ESRAM_AUTO_TINIT (1<<2)
+#define ESRAM_AUTO_TINIT_DONE (1<<3)
+#define ESRAM_AUTO_INIT_USED_CYCLES (1640)
+#define ESRAM_AUTO_INIT_CSR_OFFSET 0xC1C
+static int qat_hal_init_esram(struct icp_qat_fw_loader_handle *handle)
+{
+ void __iomem *csr_addr = handle->hal_ep_csr_addr_v +
+ ESRAM_AUTO_INIT_CSR_OFFSET;
+ unsigned int csr_val, times = 30;
+
+ csr_val = ADF_CSR_RD(csr_addr, 0);
+ if ((csr_val & ESRAM_AUTO_TINIT) && (csr_val & ESRAM_AUTO_TINIT_DONE))
+ return 0;
+
+ csr_val = ADF_CSR_RD(csr_addr, 0);
+ csr_val |= ESRAM_AUTO_TINIT;
+ ADF_CSR_WR(csr_addr, 0, csr_val);
+
+ do {
+ qat_hal_wait_cycles(handle, 0, ESRAM_AUTO_INIT_USED_CYCLES, 0);
+ csr_val = ADF_CSR_RD(csr_addr, 0);
+ } while (!(csr_val & ESRAM_AUTO_TINIT_DONE) && times--);
+ if ((!times)) {
+ pr_err("QAT: Fail to init eSram!\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+#define SHRAM_INIT_CYCLES 2060
+int qat_hal_clr_reset(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned int ae_reset_csr;
+ unsigned char ae;
+ unsigned int clk_csr;
+ unsigned int times = 100;
+ unsigned int csr;
+
+ /* write to the reset csr */
+ ae_reset_csr = GET_GLB_CSR(handle, ICP_RESET);
+ ae_reset_csr &= ~(handle->hal_handle->ae_mask << RST_CSR_AE_LSB);
+ ae_reset_csr &= ~(handle->hal_handle->slice_mask << RST_CSR_QAT_LSB);
+ do {
+ SET_GLB_CSR(handle, ICP_RESET, ae_reset_csr);
+ if (!(times--))
+ goto out_err;
+ csr = GET_GLB_CSR(handle, ICP_RESET);
+ } while ((handle->hal_handle->ae_mask |
+ (handle->hal_handle->slice_mask << RST_CSR_QAT_LSB)) & csr);
+ /* enable clock */
+ clk_csr = GET_GLB_CSR(handle, ICP_GLOBAL_CLK_ENABLE);
+ clk_csr |= handle->hal_handle->ae_mask << 0;
+ clk_csr |= handle->hal_handle->slice_mask << 20;
+ SET_GLB_CSR(handle, ICP_GLOBAL_CLK_ENABLE, clk_csr);
+ if (qat_hal_check_ae_alive(handle))
+ goto out_err;
+
+ /* Set undefined power-up/reset states to reasonable default values */
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!(handle->hal_handle->ae_mask & (1 << ae)))
+ continue;
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES,
+ INIT_CTX_ENABLE_VALUE);
+ qat_hal_wr_indr_csr(handle, ae, ICP_QAT_UCLO_AE_ALL_CTX,
+ CTX_STS_INDIRECT,
+ handle->hal_handle->upc_mask &
+ INIT_PC_VALUE);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE);
+ qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE);
+ qat_hal_put_wakeup_event(handle, ae,
+ ICP_QAT_UCLO_AE_ALL_CTX,
+ INIT_WAKEUP_EVENTS_VALUE);
+ qat_hal_put_sig_event(handle, ae,
+ ICP_QAT_UCLO_AE_ALL_CTX,
+ INIT_SIG_EVENTS_VALUE);
+ }
+ if (qat_hal_init_esram(handle))
+ goto out_err;
+ if (qat_hal_wait_cycles(handle, 0, SHRAM_INIT_CYCLES, 0))
+ goto out_err;
+ qat_hal_reset_timestamp(handle);
+
+ return 0;
+out_err:
+ pr_err("QAT: failed to get device out of reset\n");
+ return -EFAULT;
+}
+
+static void qat_hal_disable_ctx(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask)
+{
+ unsigned int ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx);
+ ctx &= IGNORE_W1C_MASK &
+ (~((ctx_mask & ICP_QAT_UCLO_AE_ALL_CTX) << CE_ENABLE_BITPOS));
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
+}
+
+static uint64_t qat_hal_parity_64bit(uint64_t word)
+{
+ word ^= word >> 1;
+ word ^= word >> 2;
+ word ^= word >> 4;
+ word ^= word >> 8;
+ word ^= word >> 16;
+ word ^= word >> 32;
+ return word & 1;
+}
+
+static uint64_t qat_hal_set_uword_ecc(uint64_t uword)
+{
+ uint64_t bit0_mask = 0xff800007fffULL, bit1_mask = 0x1f801ff801fULL,
+ bit2_mask = 0xe387e0781e1ULL, bit3_mask = 0x7cb8e388e22ULL,
+ bit4_mask = 0xaf5b2c93244ULL, bit5_mask = 0xf56d5525488ULL,
+ bit6_mask = 0xdaf69a46910ULL;
+
+ /* clear the ecc bits */
+ uword &= ~(0x7fULL << 0x2C);
+ uword |= qat_hal_parity_64bit(bit0_mask & uword) << 0x2C;
+ uword |= qat_hal_parity_64bit(bit1_mask & uword) << 0x2D;
+ uword |= qat_hal_parity_64bit(bit2_mask & uword) << 0x2E;
+ uword |= qat_hal_parity_64bit(bit3_mask & uword) << 0x2F;
+ uword |= qat_hal_parity_64bit(bit4_mask & uword) << 0x30;
+ uword |= qat_hal_parity_64bit(bit5_mask & uword) << 0x31;
+ uword |= qat_hal_parity_64bit(bit6_mask & uword) << 0x32;
+ return uword;
+}
+
+void qat_hal_wr_uwords(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int uaddr,
+ unsigned int words_num, uint64_t *uword)
+{
+ unsigned int ustore_addr;
+ unsigned int i;
+
+ qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+ uaddr |= UA_ECS;
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+ for (i = 0; i < words_num; i++) {
+ unsigned int uwrd_lo, uwrd_hi;
+ uint64_t tmp;
+
+ tmp = qat_hal_set_uword_ecc(uword[i]);
+ uwrd_lo = (unsigned int)(tmp & 0xffffffff);
+ uwrd_hi = (unsigned int)(tmp >> 0x20);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+ }
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+static void qat_hal_enable_ctx(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask)
+{
+ unsigned int ctx;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx);
+ ctx &= IGNORE_W1C_MASK;
+ ctx_mask &= (ctx & CE_INUSE_CONTEXTS) ? 0x55 : 0xFF;
+ ctx |= (ctx_mask << CE_ENABLE_BITPOS);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
+}
+
+static int qat_hal_clear_gpr(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned char ae;
+ unsigned int ctx_mask = ICP_QAT_UCLO_AE_ALL_CTX;
+ int times = MAX_RETRY_TIMES;
+ unsigned int csr_val = 0;
+ unsigned short reg;
+ unsigned int savctx = 0;
+ int ret = 0;
+
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!(handle->hal_handle->ae_mask & (1 << ae)))
+ continue;
+ for (reg = 0; reg < ICP_QAT_UCLO_MAX_GPR_REG; reg++) {
+ qat_hal_init_rd_xfer(handle, ae, 0, ICP_SR_RD_ABS,
+ reg, 0);
+ qat_hal_init_rd_xfer(handle, ae, 0, ICP_DR_RD_ABS,
+ reg, 0);
+ }
+ qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val);
+ csr_val &= ~(1 << MMC_SHARE_CS_BITPOS);
+ qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, csr_val);
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &csr_val);
+ csr_val &= IGNORE_W1C_MASK;
+ csr_val |= CE_NN_MODE;
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, csr_val);
+ qat_hal_wr_uwords(handle, ae, 0, ARRAY_SIZE(inst),
+ (uint64_t *)inst);
+ qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+ handle->hal_handle->upc_mask &
+ INIT_PC_VALUE);
+ qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, 0);
+ qat_hal_put_wakeup_event(handle, ae, ctx_mask, XCWE_VOLUNTARY);
+ qat_hal_wr_indr_csr(handle, ae, ctx_mask,
+ CTX_SIG_EVENTS_INDIRECT, 0);
+ qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0);
+ qat_hal_enable_ctx(handle, ae, ctx_mask);
+ }
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!(handle->hal_handle->ae_mask & (1 << ae)))
+ continue;
+ /* wait for AE to finish */
+ do {
+ ret = qat_hal_wait_cycles(handle, ae, 20, 1);
+ } while (ret && times--);
+
+ if (!times) {
+ pr_err("QAT: clear GPR of AE %d failed", ae);
+ return -EINVAL;
+ }
+ qat_hal_disable_ctx(handle, ae, ctx_mask);
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+ savctx & ACS_ACNO);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES,
+ INIT_CTX_ENABLE_VALUE);
+ qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+ handle->hal_handle->upc_mask &
+ INIT_PC_VALUE);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, INIT_CTX_ARB_VALUE);
+ qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, INIT_CCENABLE_VALUE);
+ qat_hal_put_wakeup_event(handle, ae, ctx_mask,
+ INIT_WAKEUP_EVENTS_VALUE);
+ qat_hal_put_sig_event(handle, ae, ctx_mask,
+ INIT_SIG_EVENTS_VALUE);
+ }
+ return 0;
+}
+
+#define ICP_DH895XCC_AE_OFFSET 0x20000
+#define ICP_DH895XCC_CAP_OFFSET (ICP_DH895XCC_AE_OFFSET + 0x10000)
+#define LOCAL_TO_XFER_REG_OFFSET 0x800
+#define ICP_DH895XCC_EP_OFFSET 0x3a000
+#define ICP_DH895XCC_PMISC_BAR 1
+int qat_hal_init(struct adf_accel_dev *accel_dev)
+{
+ unsigned char ae;
+ unsigned int max_en_ae_id = 0;
+ struct icp_qat_fw_loader_handle *handle;
+ struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct adf_bar *bar = &pci_info->pci_bars[ADF_DH895XCC_PMISC_BAR];
+
+ handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+ if (!handle)
+ return -ENOMEM;
+
+ handle->hal_cap_g_ctl_csr_addr_v = bar->virt_addr +
+ ICP_DH895XCC_CAP_OFFSET;
+ handle->hal_cap_ae_xfer_csr_addr_v = bar->virt_addr +
+ ICP_DH895XCC_AE_OFFSET;
+ handle->hal_ep_csr_addr_v = bar->virt_addr + ICP_DH895XCC_EP_OFFSET;
+ handle->hal_cap_ae_local_csr_addr_v =
+ handle->hal_cap_ae_xfer_csr_addr_v + LOCAL_TO_XFER_REG_OFFSET;
+
+ handle->hal_handle = kzalloc(sizeof(*handle->hal_handle), GFP_KERNEL);
+ if (!handle->hal_handle)
+ goto out_hal_handle;
+ handle->hal_handle->revision_id = accel_dev->accel_pci_dev.revid;
+ handle->hal_handle->ae_mask = hw_data->ae_mask;
+ handle->hal_handle->slice_mask = hw_data->accel_mask;
+ /* create AE objects */
+ handle->hal_handle->upc_mask = 0x1ffff;
+ handle->hal_handle->max_ustore = 0x4000;
+ for (ae = 0; ae < ICP_QAT_UCLO_MAX_AE; ae++) {
+ if (!(hw_data->ae_mask & (1 << ae)))
+ continue;
+ handle->hal_handle->aes[ae].free_addr = 0;
+ handle->hal_handle->aes[ae].free_size =
+ handle->hal_handle->max_ustore;
+ handle->hal_handle->aes[ae].ustore_size =
+ handle->hal_handle->max_ustore;
+ handle->hal_handle->aes[ae].live_ctx_mask =
+ ICP_QAT_UCLO_AE_ALL_CTX;
+ max_en_ae_id = ae;
+ }
+ handle->hal_handle->ae_max_num = max_en_ae_id + 1;
+ /* take all AEs out of reset */
+ if (qat_hal_clr_reset(handle)) {
+ pr_err("QAT: qat_hal_clr_reset error\n");
+ goto out_err;
+ }
+ if (qat_hal_clear_gpr(handle))
+ goto out_err;
+ /* Set SIGNATURE_ENABLE[0] to 0x1 in order to enable ALU_OUT csr */
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ unsigned int csr_val = 0;
+
+ if (!(hw_data->ae_mask & (1 << ae)))
+ continue;
+ qat_hal_rd_ae_csr(handle, ae, SIGNATURE_ENABLE, &csr_val);
+ csr_val |= 0x1;
+ qat_hal_wr_ae_csr(handle, ae, SIGNATURE_ENABLE, csr_val);
+ }
+ accel_dev->fw_loader->fw_loader = handle;
+ return 0;
+
+out_err:
+ kfree(handle->hal_handle);
+out_hal_handle:
+ kfree(handle);
+ return -EFAULT;
+}
+
+void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle)
+{
+ if (!handle)
+ return;
+ kfree(handle->hal_handle);
+ kfree(handle);
+}
+
+void qat_hal_start(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+ unsigned int ctx_mask)
+{
+ qat_hal_put_wakeup_event(handle, ae, (~ctx_mask) &
+ ICP_QAT_UCLO_AE_ALL_CTX, 0x10000);
+ qat_hal_enable_ctx(handle, ae, ctx_mask);
+}
+
+void qat_hal_stop(struct icp_qat_fw_loader_handle *handle, unsigned char ae,
+ unsigned int ctx_mask)
+{
+ qat_hal_disable_ctx(handle, ae, ctx_mask);
+}
+
+void qat_hal_set_pc(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int ctx_mask, unsigned int upc)
+{
+ qat_hal_wr_indr_csr(handle, ae, ctx_mask, CTX_STS_INDIRECT,
+ handle->hal_handle->upc_mask & upc);
+}
+
+static void qat_hal_get_uwords(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int uaddr,
+ unsigned int words_num, uint64_t *uword)
+{
+ unsigned int i, uwrd_lo, uwrd_hi;
+ unsigned int ustore_addr, misc_control;
+
+ qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &misc_control);
+ qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL,
+ misc_control & 0xfffffffb);
+ qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+ uaddr |= UA_ECS;
+ for (i = 0; i < words_num; i++) {
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+ uaddr++;
+ qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_LOWER, &uwrd_lo);
+ qat_hal_rd_ae_csr(handle, ae, USTORE_DATA_UPPER, &uwrd_hi);
+ uword[i] = uwrd_hi;
+ uword[i] = (uword[i] << 0x20) | uwrd_lo;
+ }
+ qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, misc_control);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int uaddr,
+ unsigned int words_num, unsigned int *data)
+{
+ unsigned int i, ustore_addr;
+
+ qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+ uaddr |= UA_ECS;
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+ for (i = 0; i < words_num; i++) {
+ unsigned int uwrd_lo, uwrd_hi, tmp;
+
+ uwrd_lo = ((data[i] & 0xfff0000) << 4) | (0x3 << 18) |
+ ((data[i] & 0xff00) << 2) |
+ (0x3 << 8) | (data[i] & 0xff);
+ uwrd_hi = (0xf << 4) | ((data[i] & 0xf0000000) >> 28);
+ uwrd_hi |= (hweight32(data[i] & 0xffff) & 0x1) << 8;
+ tmp = ((data[i] >> 0x10) & 0xffff);
+ uwrd_hi |= (hweight32(tmp) & 0x1) << 9;
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+ }
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+}
+
+#define MAX_EXEC_INST 100
+static int qat_hal_exec_micro_inst(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ uint64_t *micro_inst, unsigned int inst_num,
+ int code_off, unsigned int max_cycle,
+ unsigned int *endpc)
+{
+ uint64_t savuwords[MAX_EXEC_INST];
+ unsigned int ind_lm_addr0, ind_lm_addr1;
+ unsigned int ind_lm_addr_byte0, ind_lm_addr_byte1;
+ unsigned int ind_cnt_sig;
+ unsigned int ind_sig, act_sig;
+ unsigned int csr_val = 0, newcsr_val;
+ unsigned int savctx;
+ unsigned int savcc, wakeup_events, savpc;
+ unsigned int ctxarb_ctl, ctx_enables;
+
+ if ((inst_num > handle->hal_handle->max_ustore) || !micro_inst) {
+ pr_err("QAT: invalid instruction num %d\n", inst_num);
+ return -EINVAL;
+ }
+ /* save current context */
+ qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_0_INDIRECT, &ind_lm_addr0);
+ qat_hal_rd_indr_csr(handle, ae, ctx, LM_ADDR_1_INDIRECT, &ind_lm_addr1);
+ qat_hal_rd_indr_csr(handle, ae, ctx, INDIRECT_LM_ADDR_0_BYTE_INDEX,
+ &ind_lm_addr_byte0);
+ qat_hal_rd_indr_csr(handle, ae, ctx, INDIRECT_LM_ADDR_1_BYTE_INDEX,
+ &ind_lm_addr_byte1);
+ if (inst_num <= MAX_EXEC_INST)
+ qat_hal_get_uwords(handle, ae, 0, inst_num, savuwords);
+ qat_hal_get_wakeup_event(handle, ae, ctx, &wakeup_events);
+ qat_hal_rd_indr_csr(handle, ae, ctx, CTX_STS_INDIRECT, &savpc);
+ savpc = (savpc & handle->hal_handle->upc_mask) >> 0;
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ ctx_enables &= IGNORE_W1C_MASK;
+ qat_hal_rd_ae_csr(handle, ae, CC_ENABLE, &savcc);
+ qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+ qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_ctl);
+ qat_hal_rd_indr_csr(handle, ae, ctx, FUTURE_COUNT_SIGNAL_INDIRECT,
+ &ind_cnt_sig);
+ qat_hal_rd_indr_csr(handle, ae, ctx, CTX_SIG_EVENTS_INDIRECT, &ind_sig);
+ qat_hal_rd_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, &act_sig);
+ /* execute micro codes */
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+ qat_hal_wr_uwords(handle, ae, 0, inst_num, micro_inst);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_STS_INDIRECT, 0);
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, ctx & ACS_ACNO);
+ if (code_off)
+ qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc & 0xffffdfff);
+ qat_hal_put_wakeup_event(handle, ae, (1 << ctx), XCWE_VOLUNTARY);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_SIG_EVENTS_INDIRECT, 0);
+ qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, 0);
+ qat_hal_enable_ctx(handle, ae, (1 << ctx));
+ /* wait for micro codes to finish */
+ if (qat_hal_wait_cycles(handle, ae, max_cycle, 1) != 0)
+ return -EFAULT;
+ if (endpc) {
+ unsigned int ctx_status;
+
+ qat_hal_rd_indr_csr(handle, ae, ctx, CTX_STS_INDIRECT,
+ &ctx_status);
+ *endpc = ctx_status & handle->hal_handle->upc_mask;
+ }
+ /* retore to saved context */
+ qat_hal_disable_ctx(handle, ae, (1 << ctx));
+ if (inst_num <= MAX_EXEC_INST)
+ qat_hal_wr_uwords(handle, ae, 0, inst_num, savuwords);
+ qat_hal_put_wakeup_event(handle, ae, (1 << ctx), wakeup_events);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx), CTX_STS_INDIRECT,
+ handle->hal_handle->upc_mask & savpc);
+ qat_hal_rd_ae_csr(handle, ae, AE_MISC_CONTROL, &csr_val);
+ newcsr_val = CLR_BIT(csr_val, MMC_SHARE_CS_BITPOS);
+ qat_hal_wr_ae_csr(handle, ae, AE_MISC_CONTROL, newcsr_val);
+ qat_hal_wr_ae_csr(handle, ae, CC_ENABLE, savcc);
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS, savctx & ACS_ACNO);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_ctl);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ LM_ADDR_0_INDIRECT, ind_lm_addr0);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ LM_ADDR_1_INDIRECT, ind_lm_addr1);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ INDIRECT_LM_ADDR_0_BYTE_INDEX, ind_lm_addr_byte0);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ INDIRECT_LM_ADDR_1_BYTE_INDEX, ind_lm_addr_byte1);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ FUTURE_COUNT_SIGNAL_INDIRECT, ind_cnt_sig);
+ qat_hal_wr_indr_csr(handle, ae, (1 << ctx),
+ CTX_SIG_EVENTS_INDIRECT, ind_sig);
+ qat_hal_wr_ae_csr(handle, ae, CTX_SIG_EVENTS_ACTIVE, act_sig);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+
+ return 0;
+}
+
+static int qat_hal_rd_rel_reg(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int *data)
+{
+ unsigned int savctx, uaddr, uwrd_lo, uwrd_hi;
+ unsigned int ctxarb_cntl, ustore_addr, ctx_enables;
+ unsigned short reg_addr;
+ int status = 0;
+ uint64_t insts, savuword;
+
+ reg_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+ if (reg_addr == BAD_REGADDR) {
+ pr_err("QAT: bad regaddr=0x%x\n", reg_addr);
+ return -EINVAL;
+ }
+ switch (reg_type) {
+ case ICP_GPA_REL:
+ insts = 0xA070000000ull | (reg_addr & 0x3ff);
+ break;
+ default:
+ insts = (uint64_t)0xA030000000ull | ((reg_addr & 0x3ff) << 10);
+ break;
+ }
+ qat_hal_rd_ae_csr(handle, ae, ACTIVE_CTX_STATUS, &savctx);
+ qat_hal_rd_ae_csr(handle, ae, CTX_ARB_CNTL, &ctxarb_cntl);
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ ctx_enables &= IGNORE_W1C_MASK;
+ if (ctx != (savctx & ACS_ACNO))
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+ ctx & ACS_ACNO);
+ qat_hal_get_uwords(handle, ae, 0, 1, &savuword);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+ qat_hal_rd_ae_csr(handle, ae, USTORE_ADDRESS, &ustore_addr);
+ uaddr = UA_ECS;
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+ insts = qat_hal_set_uword_ecc(insts);
+ uwrd_lo = (unsigned int)(insts & 0xffffffff);
+ uwrd_hi = (unsigned int)(insts >> 0x20);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
+ /* delay for at least 8 cycles */
+ qat_hal_wait_cycles(handle, ae, 0x8, 0);
+ /*
+ * read ALU output
+ * the instruction should have been executed
+ * prior to clearing the ECS in putUwords
+ */
+ qat_hal_rd_ae_csr(handle, ae, ALU_OUT, data);
+ qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, ustore_addr);
+ qat_hal_wr_uwords(handle, ae, 0, 1, &savuword);
+ if (ctx != (savctx & ACS_ACNO))
+ qat_hal_wr_ae_csr(handle, ae, ACTIVE_CTX_STATUS,
+ savctx & ACS_ACNO);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ARB_CNTL, ctxarb_cntl);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+
+ return status;
+}
+
+static int qat_hal_wr_rel_reg(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int data)
+{
+ unsigned short src_hiaddr, src_lowaddr, dest_addr, data16hi, data16lo;
+ uint64_t insts[] = {
+ 0x0F440000000ull,
+ 0x0F040000000ull,
+ 0x0F0000C0300ull,
+ 0x0E000010000ull
+ };
+ const int num_inst = ARRAY_SIZE(insts), code_off = 1;
+ const int imm_w1 = 0, imm_w0 = 1;
+
+ dest_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+ if (dest_addr == BAD_REGADDR) {
+ pr_err("QAT: bad destAddr=0x%x\n", dest_addr);
+ return -EINVAL;
+ }
+
+ data16lo = 0xffff & data;
+ data16hi = 0xffff & (data >> 0x10);
+ src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST, (unsigned short)
+ (0xff & data16hi));
+ src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST, (unsigned short)
+ (0xff & data16lo));
+ switch (reg_type) {
+ case ICP_GPA_REL:
+ insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) |
+ ((src_hiaddr & 0x3ff) << 10) | (dest_addr & 0x3ff);
+ insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) |
+ ((src_lowaddr & 0x3ff) << 10) | (dest_addr & 0x3ff);
+ break;
+ default:
+ insts[imm_w1] = insts[imm_w1] | ((data16hi >> 8) << 20) |
+ ((dest_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff);
+
+ insts[imm_w0] = insts[imm_w0] | ((data16lo >> 8) << 20) |
+ ((dest_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff);
+ break;
+ }
+
+ return qat_hal_exec_micro_inst(handle, ae, ctx, insts, num_inst,
+ code_off, num_inst * 0x5, NULL);
+}
+
+int qat_hal_get_ins_num(void)
+{
+ return ARRAY_SIZE(inst_4b);
+}
+
+static int qat_hal_concat_micro_code(uint64_t *micro_inst,
+ unsigned int inst_num, unsigned int size,
+ unsigned int addr, unsigned int *value)
+{
+ int i, val_indx;
+ unsigned int cur_value;
+ const uint64_t *inst_arr;
+ int fixup_offset;
+ int usize = 0;
+ int orig_num;
+
+ orig_num = inst_num;
+ val_indx = 0;
+ cur_value = value[val_indx++];
+ inst_arr = inst_4b;
+ usize = ARRAY_SIZE(inst_4b);
+ fixup_offset = inst_num;
+ for (i = 0; i < usize; i++)
+ micro_inst[inst_num++] = inst_arr[i];
+ INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], (addr));
+ fixup_offset++;
+ INSERT_IMMED_GPRA_CONST(micro_inst[fixup_offset], 0);
+ fixup_offset++;
+ INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0));
+ fixup_offset++;
+ INSERT_IMMED_GPRB_CONST(micro_inst[fixup_offset], (cur_value >> 0x10));
+
+ return inst_num - orig_num;
+}
+
+static int qat_hal_exec_micro_init_lm(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ int *pfirst_exec, uint64_t *micro_inst,
+ unsigned int inst_num)
+{
+ int stat = 0;
+ unsigned int gpra0 = 0, gpra1 = 0, gpra2 = 0;
+ unsigned int gprb0 = 0, gprb1 = 0;
+
+ if (*pfirst_exec) {
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, &gpra0);
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, &gpra1);
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, &gpra2);
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, &gprb0);
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, &gprb1);
+ *pfirst_exec = 0;
+ }
+ stat = qat_hal_exec_micro_inst(handle, ae, ctx, micro_inst, inst_num, 1,
+ inst_num * 0x5, NULL);
+ if (stat != 0)
+ return -EFAULT;
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0, gpra0);
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x1, gpra1);
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPA_REL, 0x2, gpra2);
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0, gprb0);
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, 0x1, gprb1);
+
+ return 0;
+}
+
+int qat_hal_batch_wr_lm(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae,
+ struct icp_qat_uof_batch_init *lm_init_header)
+{
+ struct icp_qat_uof_batch_init *plm_init;
+ uint64_t *micro_inst_arry;
+ int micro_inst_num;
+ int alloc_inst_size;
+ int first_exec = 1;
+ int stat = 0;
+
+ plm_init = lm_init_header->next;
+ alloc_inst_size = lm_init_header->size;
+ if ((unsigned int)alloc_inst_size > handle->hal_handle->max_ustore)
+ alloc_inst_size = handle->hal_handle->max_ustore;
+ micro_inst_arry = kmalloc_array(alloc_inst_size, sizeof(uint64_t),
+ GFP_KERNEL);
+ if (!micro_inst_arry)
+ return -ENOMEM;
+ micro_inst_num = 0;
+ while (plm_init) {
+ unsigned int addr, *value, size;
+
+ ae = plm_init->ae;
+ addr = plm_init->addr;
+ value = plm_init->value;
+ size = plm_init->size;
+ micro_inst_num += qat_hal_concat_micro_code(micro_inst_arry,
+ micro_inst_num,
+ size, addr, value);
+ plm_init = plm_init->next;
+ }
+ /* exec micro codes */
+ if (micro_inst_arry && (micro_inst_num > 0)) {
+ micro_inst_arry[micro_inst_num++] = 0x0E000010000ull;
+ stat = qat_hal_exec_micro_init_lm(handle, ae, 0, &first_exec,
+ micro_inst_arry,
+ micro_inst_num);
+ }
+ kfree(micro_inst_arry);
+ return stat;
+}
+
+static int qat_hal_put_rel_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int val)
+{
+ int status = 0;
+ unsigned int reg_addr;
+ unsigned int ctx_enables;
+ unsigned short mask;
+ unsigned short dr_offset = 0x10;
+
+ status = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ if (CE_INUSE_CONTEXTS & ctx_enables) {
+ if (ctx & 0x1) {
+ pr_err("QAT: bad 4-ctx mode,ctx=0x%x\n", ctx);
+ return -EINVAL;
+ }
+ mask = 0x1f;
+ dr_offset = 0x20;
+ } else {
+ mask = 0x0f;
+ }
+ if (reg_num & ~mask)
+ return -EINVAL;
+ reg_addr = reg_num + (ctx << 0x5);
+ switch (reg_type) {
+ case ICP_SR_RD_REL:
+ case ICP_SR_REL:
+ SET_AE_XFER(handle, ae, reg_addr, val);
+ break;
+ case ICP_DR_RD_REL:
+ case ICP_DR_REL:
+ SET_AE_XFER(handle, ae, (reg_addr + dr_offset), val);
+ break;
+ default:
+ status = -EINVAL;
+ break;
+ }
+ return status;
+}
+
+static int qat_hal_put_rel_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int data)
+{
+ unsigned int gprval, ctx_enables;
+ unsigned short src_hiaddr, src_lowaddr, gpr_addr, xfr_addr, data16hi,
+ data16low;
+ unsigned short reg_mask;
+ int status = 0;
+ uint64_t micro_inst[] = {
+ 0x0F440000000ull,
+ 0x0F040000000ull,
+ 0x0A000000000ull,
+ 0x0F0000C0300ull,
+ 0x0E000010000ull
+ };
+ const int num_inst = ARRAY_SIZE(micro_inst), code_off = 1;
+ const unsigned short gprnum = 0, dly = num_inst * 0x5;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ if (CE_INUSE_CONTEXTS & ctx_enables) {
+ if (ctx & 0x1) {
+ pr_err("QAT: 4-ctx mode,ctx=0x%x\n", ctx);
+ return -EINVAL;
+ }
+ reg_mask = (unsigned short)~0x1f;
+ } else {
+ reg_mask = (unsigned short)~0xf;
+ }
+ if (reg_num & reg_mask)
+ return -EINVAL;
+ xfr_addr = qat_hal_get_reg_addr(reg_type, reg_num);
+ if (xfr_addr == BAD_REGADDR) {
+ pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr);
+ return -EINVAL;
+ }
+ qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
+ gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum);
+ data16low = 0xffff & data;
+ data16hi = 0xffff & (data >> 0x10);
+ src_hiaddr = qat_hal_get_reg_addr(ICP_NO_DEST,
+ (unsigned short)(0xff & data16hi));
+ src_lowaddr = qat_hal_get_reg_addr(ICP_NO_DEST,
+ (unsigned short)(0xff & data16low));
+ micro_inst[0] = micro_inst[0x0] | ((data16hi >> 8) << 20) |
+ ((gpr_addr & 0x3ff) << 10) | (src_hiaddr & 0x3ff);
+ micro_inst[1] = micro_inst[0x1] | ((data16low >> 8) << 20) |
+ ((gpr_addr & 0x3ff) << 10) | (src_lowaddr & 0x3ff);
+ micro_inst[0x2] = micro_inst[0x2] |
+ ((xfr_addr & 0x3ff) << 20) | ((gpr_addr & 0x3ff) << 10);
+ status = qat_hal_exec_micro_inst(handle, ae, ctx, micro_inst, num_inst,
+ code_off, dly, NULL);
+ qat_hal_wr_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, gprval);
+ return status;
+}
+
+static int qat_hal_put_rel_nn(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx,
+ unsigned short nn, unsigned int val)
+{
+ unsigned int ctx_enables;
+ int stat = 0;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ ctx_enables &= IGNORE_W1C_MASK;
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables | CE_NN_MODE);
+
+ stat = qat_hal_put_rel_wr_xfer(handle, ae, ctx, ICP_NEIGH_REL, nn, val);
+ qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx_enables);
+ return stat;
+}
+
+static int qat_hal_convert_abs_to_rel(struct icp_qat_fw_loader_handle
+ *handle, unsigned char ae,
+ unsigned short absreg_num,
+ unsigned short *relreg,
+ unsigned char *ctx)
+{
+ unsigned int ctx_enables;
+
+ qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES, &ctx_enables);
+ if (ctx_enables & CE_INUSE_CONTEXTS) {
+ /* 4-ctx mode */
+ *relreg = absreg_num & 0x1F;
+ *ctx = (absreg_num >> 0x4) & 0x6;
+ } else {
+ /* 8-ctx mode */
+ *relreg = absreg_num & 0x0F;
+ *ctx = (absreg_num >> 0x4) & 0x7;
+ }
+ return 0;
+}
+
+int qat_hal_init_gpr(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata)
+{
+ int stat = 0;
+ unsigned short reg;
+ unsigned char ctx = 0;
+ enum icp_qat_uof_regtype type;
+
+ if (reg_num >= ICP_QAT_UCLO_MAX_GPR_REG)
+ return -EINVAL;
+
+ do {
+ if (ctx_mask == 0) {
+ qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+ &ctx);
+ type = reg_type - 1;
+ } else {
+ reg = reg_num;
+ type = reg_type;
+ if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+ continue;
+ }
+ stat = qat_hal_wr_rel_reg(handle, ae, ctx, type, reg, regdata);
+ if (stat) {
+ pr_err("QAT: write gpr fail\n");
+ return -EINVAL;
+ }
+ } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+ return 0;
+}
+
+int qat_hal_init_wr_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata)
+{
+ int stat = 0;
+ unsigned short reg;
+ unsigned char ctx = 0;
+ enum icp_qat_uof_regtype type;
+
+ if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG)
+ return -EINVAL;
+
+ do {
+ if (ctx_mask == 0) {
+ qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+ &ctx);
+ type = reg_type - 3;
+ } else {
+ reg = reg_num;
+ type = reg_type;
+ if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+ continue;
+ }
+ stat = qat_hal_put_rel_wr_xfer(handle, ae, ctx, type, reg,
+ regdata);
+ if (stat) {
+ pr_err("QAT: write wr xfer fail\n");
+ return -EINVAL;
+ }
+ } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+ return 0;
+}
+
+int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_num, unsigned int regdata)
+{
+ int stat = 0;
+ unsigned short reg;
+ unsigned char ctx = 0;
+ enum icp_qat_uof_regtype type;
+
+ if (reg_num >= ICP_QAT_UCLO_MAX_XFER_REG)
+ return -EINVAL;
+
+ do {
+ if (ctx_mask == 0) {
+ qat_hal_convert_abs_to_rel(handle, ae, reg_num, &reg,
+ &ctx);
+ type = reg_type - 3;
+ } else {
+ reg = reg_num;
+ type = reg_type;
+ if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+ continue;
+ }
+ stat = qat_hal_put_rel_rd_xfer(handle, ae, ctx, type, reg,
+ regdata);
+ if (stat) {
+ pr_err("QAT: write rd xfer fail\n");
+ return -EINVAL;
+ }
+ } while (ctx_mask && (ctx++ < ICP_QAT_UCLO_MAX_CTX));
+
+ return 0;
+}
+
+int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ unsigned short reg_num, unsigned int regdata)
+{
+ int stat = 0;
+ unsigned char ctx;
+
+ if (ctx_mask == 0)
+ return -EINVAL;
+
+ for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++) {
+ if (!test_bit(ctx, (unsigned long *)&ctx_mask))
+ continue;
+ stat = qat_hal_put_rel_nn(handle, ae, ctx, reg_num, regdata);
+ if (stat) {
+ pr_err("QAT: write neigh error\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c
new file mode 100644
index 000000000000..1e27f9f7fddf
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_uclo.c
@@ -0,0 +1,1181 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "icp_qat_uclo.h"
+#include "icp_qat_hal.h"
+#include "icp_qat_fw_loader_handle.h"
+
+#define UWORD_CPYBUF_SIZE 1024
+#define INVLD_UWORD 0xffffffffffull
+#define PID_MINOR_REV 0xf
+#define PID_MAJOR_REV (0xf << 4)
+
+static int qat_uclo_init_ae_data(struct icp_qat_uclo_objhandle *obj_handle,
+ unsigned int ae, unsigned int image_num)
+{
+ struct icp_qat_uclo_aedata *ae_data;
+ struct icp_qat_uclo_encapme *encap_image;
+ struct icp_qat_uclo_page *page = NULL;
+ struct icp_qat_uclo_aeslice *ae_slice = NULL;
+
+ ae_data = &obj_handle->ae_data[ae];
+ encap_image = &obj_handle->ae_uimage[image_num];
+ ae_slice = &ae_data->ae_slices[ae_data->slice_num];
+ ae_slice->encap_image = encap_image;
+
+ if (encap_image->img_ptr) {
+ ae_slice->ctx_mask_assigned =
+ encap_image->img_ptr->ctx_assigned;
+ ae_data->eff_ustore_size = obj_handle->ustore_phy_size;
+ } else {
+ ae_slice->ctx_mask_assigned = 0;
+ }
+ ae_slice->region = kzalloc(sizeof(*ae_slice->region), GFP_KERNEL);
+ if (!ae_slice->region)
+ return -ENOMEM;
+ ae_slice->page = kzalloc(sizeof(*ae_slice->page), GFP_KERNEL);
+ if (!ae_slice->page)
+ goto out_err;
+ page = ae_slice->page;
+ page->encap_page = encap_image->page;
+ ae_slice->page->region = ae_slice->region;
+ ae_data->slice_num++;
+ return 0;
+out_err:
+ kfree(ae_slice->region);
+ ae_slice->region = NULL;
+ return -ENOMEM;
+}
+
+static int qat_uclo_free_ae_data(struct icp_qat_uclo_aedata *ae_data)
+{
+ unsigned int i;
+
+ if (!ae_data) {
+ pr_err("QAT: bad argument, ae_data is NULL\n ");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ae_data->slice_num; i++) {
+ kfree(ae_data->ae_slices[i].region);
+ ae_data->ae_slices[i].region = NULL;
+ kfree(ae_data->ae_slices[i].page);
+ ae_data->ae_slices[i].page = NULL;
+ }
+ return 0;
+}
+
+static char *qat_uclo_get_string(struct icp_qat_uof_strtable *str_table,
+ unsigned int str_offset)
+{
+ if ((!str_table->table_len) || (str_offset > str_table->table_len))
+ return NULL;
+ return (char *)(((unsigned long)(str_table->strings)) + str_offset);
+}
+
+static int qat_uclo_check_format(struct icp_qat_uof_filehdr *hdr)
+{
+ int maj = hdr->maj_ver & 0xff;
+ int min = hdr->min_ver & 0xff;
+
+ if (hdr->file_id != ICP_QAT_UOF_FID) {
+ pr_err("QAT: Invalid header 0x%x\n", hdr->file_id);
+ return -EINVAL;
+ }
+ if (min != ICP_QAT_UOF_MINVER || maj != ICP_QAT_UOF_MAJVER) {
+ pr_err("QAT: bad UOF version, major 0x%x, minor 0x%x\n",
+ maj, min);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void qat_uclo_wr_sram_by_words(struct icp_qat_fw_loader_handle *handle,
+ unsigned int addr, unsigned int *val,
+ unsigned int num_in_bytes)
+{
+ unsigned int outval;
+ unsigned char *ptr = (unsigned char *)val;
+
+ while (num_in_bytes) {
+ memcpy(&outval, ptr, 4);
+ SRAM_WRITE(handle, addr, outval);
+ num_in_bytes -= 4;
+ ptr += 4;
+ addr += 4;
+ }
+}
+
+static void qat_uclo_wr_umem_by_words(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned int addr,
+ unsigned int *val,
+ unsigned int num_in_bytes)
+{
+ unsigned int outval;
+ unsigned char *ptr = (unsigned char *)val;
+
+ addr >>= 0x2; /* convert to uword address */
+
+ while (num_in_bytes) {
+ memcpy(&outval, ptr, 4);
+ qat_hal_wr_umem(handle, ae, addr++, 1, &outval);
+ num_in_bytes -= 4;
+ ptr += 4;
+ }
+}
+
+static void qat_uclo_batch_wr_umem(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae,
+ struct icp_qat_uof_batch_init
+ *umem_init_header)
+{
+ struct icp_qat_uof_batch_init *umem_init;
+
+ if (!umem_init_header)
+ return;
+ umem_init = umem_init_header->next;
+ while (umem_init) {
+ unsigned int addr, *value, size;
+
+ ae = umem_init->ae;
+ addr = umem_init->addr;
+ value = umem_init->value;
+ size = umem_init->size;
+ qat_uclo_wr_umem_by_words(handle, ae, addr, value, size);
+ umem_init = umem_init->next;
+ }
+}
+
+static void
+qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_batch_init **base)
+{
+ struct icp_qat_uof_batch_init *umem_init;
+
+ umem_init = *base;
+ while (umem_init) {
+ struct icp_qat_uof_batch_init *pre;
+
+ pre = umem_init;
+ umem_init = umem_init->next;
+ kfree(pre);
+ }
+ *base = NULL;
+}
+
+static int qat_uclo_parse_num(char *str, unsigned int *num)
+{
+ char buf[16] = {0};
+ unsigned long ae = 0;
+ int i;
+
+ strncpy(buf, str, 15);
+ for (i = 0; i < 16; i++) {
+ if (!isdigit(buf[i])) {
+ buf[i] = '\0';
+ break;
+ }
+ }
+ if ((kstrtoul(buf, 10, &ae)))
+ return -EFAULT;
+
+ *num = (unsigned int)ae;
+ return 0;
+}
+
+static int qat_uclo_fetch_initmem_ae(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_initmem *init_mem,
+ unsigned int size_range, unsigned int *ae)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ char *str;
+
+ if ((init_mem->addr + init_mem->num_in_bytes) > (size_range << 0x2)) {
+ pr_err("QAT: initmem is out of range");
+ return -EINVAL;
+ }
+ if (init_mem->scope != ICP_QAT_UOF_LOCAL_SCOPE) {
+ pr_err("QAT: Memory scope for init_mem error\n");
+ return -EINVAL;
+ }
+ str = qat_uclo_get_string(&obj_handle->str_table, init_mem->sym_name);
+ if (!str) {
+ pr_err("QAT: AE name assigned in UOF init table is NULL\n");
+ return -EINVAL;
+ }
+ if (qat_uclo_parse_num(str, ae)) {
+ pr_err("QAT: Parse num for AE number failed\n");
+ return -EINVAL;
+ }
+ if (*ae >= ICP_QAT_UCLO_MAX_AE) {
+ pr_err("QAT: ae %d out of range\n", *ae);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle
+ *handle, struct icp_qat_uof_initmem
+ *init_mem, unsigned int ae,
+ struct icp_qat_uof_batch_init
+ **init_tab_base)
+{
+ struct icp_qat_uof_batch_init *init_header, *tail;
+ struct icp_qat_uof_batch_init *mem_init, *tail_old;
+ struct icp_qat_uof_memvar_attr *mem_val_attr;
+ unsigned int i, flag = 0;
+
+ mem_val_attr =
+ (struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
+ sizeof(struct icp_qat_uof_initmem));
+
+ init_header = *init_tab_base;
+ if (!init_header) {
+ init_header = kzalloc(sizeof(*init_header), GFP_KERNEL);
+ if (!init_header)
+ return -ENOMEM;
+ init_header->size = 1;
+ *init_tab_base = init_header;
+ flag = 1;
+ }
+ tail_old = init_header;
+ while (tail_old->next)
+ tail_old = tail_old->next;
+ tail = tail_old;
+ for (i = 0; i < init_mem->val_attr_num; i++) {
+ mem_init = kzalloc(sizeof(*mem_init), GFP_KERNEL);
+ if (!mem_init)
+ goto out_err;
+ mem_init->ae = ae;
+ mem_init->addr = init_mem->addr + mem_val_attr->offset_in_byte;
+ mem_init->value = &mem_val_attr->value;
+ mem_init->size = 4;
+ mem_init->next = NULL;
+ tail->next = mem_init;
+ tail = mem_init;
+ init_header->size += qat_hal_get_ins_num();
+ mem_val_attr++;
+ }
+ return 0;
+out_err:
+ while (tail_old) {
+ mem_init = tail_old->next;
+ kfree(tail_old);
+ tail_old = mem_init;
+ }
+ if (flag)
+ kfree(*init_tab_base);
+ return -ENOMEM;
+}
+
+static int qat_uclo_init_lmem_seg(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_initmem *init_mem)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int ae;
+
+ if (qat_uclo_fetch_initmem_ae(handle, init_mem,
+ ICP_QAT_UCLO_MAX_LMEM_REG, &ae))
+ return -EINVAL;
+ if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
+ &obj_handle->lm_init_tab[ae]))
+ return -EINVAL;
+ return 0;
+}
+
+static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_initmem *init_mem)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int ae, ustore_size, uaddr, i;
+
+ ustore_size = obj_handle->ustore_phy_size;
+ if (qat_uclo_fetch_initmem_ae(handle, init_mem, ustore_size, &ae))
+ return -EINVAL;
+ if (qat_uclo_create_batch_init_list(handle, init_mem, ae,
+ &obj_handle->umem_init_tab[ae]))
+ return -EINVAL;
+ /* set the highest ustore address referenced */
+ uaddr = (init_mem->addr + init_mem->num_in_bytes) >> 0x2;
+ for (i = 0; i < obj_handle->ae_data[ae].slice_num; i++) {
+ if (obj_handle->ae_data[ae].ae_slices[i].
+ encap_image->uwords_num < uaddr)
+ obj_handle->ae_data[ae].ae_slices[i].
+ encap_image->uwords_num = uaddr;
+ }
+ return 0;
+}
+
+#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
+static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_initmem *init_mem)
+{
+ unsigned int i;
+ struct icp_qat_uof_memvar_attr *mem_val_attr;
+
+ mem_val_attr =
+ (struct icp_qat_uof_memvar_attr *)((unsigned long)init_mem +
+ sizeof(struct icp_qat_uof_initmem));
+
+ switch (init_mem->region) {
+ case ICP_QAT_UOF_SRAM_REGION:
+ if ((init_mem->addr + init_mem->num_in_bytes) >
+ ICP_DH895XCC_PESRAM_BAR_SIZE) {
+ pr_err("QAT: initmem on SRAM is out of range");
+ return -EINVAL;
+ }
+ for (i = 0; i < init_mem->val_attr_num; i++) {
+ qat_uclo_wr_sram_by_words(handle,
+ init_mem->addr +
+ mem_val_attr->offset_in_byte,
+ &mem_val_attr->value, 4);
+ mem_val_attr++;
+ }
+ break;
+ case ICP_QAT_UOF_LMEM_REGION:
+ if (qat_uclo_init_lmem_seg(handle, init_mem))
+ return -EINVAL;
+ break;
+ case ICP_QAT_UOF_UMEM_REGION:
+ if (qat_uclo_init_umem_seg(handle, init_mem))
+ return -EINVAL;
+ break;
+ default:
+ pr_err("QAT: initmem region error. region type=0x%x\n",
+ init_mem->region);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int qat_uclo_init_ustore(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uclo_encapme *image)
+{
+ unsigned int i;
+ struct icp_qat_uclo_encap_page *page;
+ struct icp_qat_uof_image *uof_image;
+ unsigned char ae;
+ unsigned int ustore_size;
+ unsigned int patt_pos;
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ uint64_t *fill_data;
+
+ uof_image = image->img_ptr;
+ fill_data = kcalloc(ICP_QAT_UCLO_MAX_USTORE, sizeof(uint64_t),
+ GFP_KERNEL);
+ if (!fill_data)
+ return -ENOMEM;
+ for (i = 0; i < ICP_QAT_UCLO_MAX_USTORE; i++)
+ memcpy(&fill_data[i], &uof_image->fill_pattern,
+ sizeof(uint64_t));
+ page = image->page;
+
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!test_bit(ae, (unsigned long *)&uof_image->ae_assigned))
+ continue;
+ ustore_size = obj_handle->ae_data[ae].eff_ustore_size;
+ patt_pos = page->beg_addr_p + page->micro_words_num;
+
+ qat_hal_wr_uwords(handle, (unsigned char)ae, 0,
+ page->beg_addr_p, &fill_data[0]);
+ qat_hal_wr_uwords(handle, (unsigned char)ae, patt_pos,
+ ustore_size - patt_pos + 1,
+ &fill_data[page->beg_addr_p]);
+ }
+ kfree(fill_data);
+ return 0;
+}
+
+static int qat_uclo_init_memory(struct icp_qat_fw_loader_handle *handle)
+{
+ int i, ae;
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ struct icp_qat_uof_initmem *initmem = obj_handle->init_mem_tab.init_mem;
+
+ for (i = 0; i < obj_handle->init_mem_tab.entry_num; i++) {
+ if (initmem->num_in_bytes) {
+ if (qat_uclo_init_ae_memory(handle, initmem))
+ return -EINVAL;
+ }
+ initmem = (struct icp_qat_uof_initmem *)((unsigned long)(
+ (unsigned long)initmem +
+ sizeof(struct icp_qat_uof_initmem)) +
+ (sizeof(struct icp_qat_uof_memvar_attr) *
+ initmem->val_attr_num));
+ }
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (qat_hal_batch_wr_lm(handle, ae,
+ obj_handle->lm_init_tab[ae])) {
+ pr_err("QAT: fail to batch init lmem for AE %d\n", ae);
+ return -EINVAL;
+ }
+ qat_uclo_cleanup_batch_init_list(handle,
+ &obj_handle->lm_init_tab[ae]);
+ qat_uclo_batch_wr_umem(handle, ae,
+ obj_handle->umem_init_tab[ae]);
+ qat_uclo_cleanup_batch_init_list(handle,
+ &obj_handle->
+ umem_init_tab[ae]);
+ }
+ return 0;
+}
+
+static void *qat_uclo_find_chunk(struct icp_qat_uof_objhdr *obj_hdr,
+ char *chunk_id, void *cur)
+{
+ int i;
+ struct icp_qat_uof_chunkhdr *chunk_hdr =
+ (struct icp_qat_uof_chunkhdr *)
+ ((unsigned long)obj_hdr + sizeof(struct icp_qat_uof_objhdr));
+
+ for (i = 0; i < obj_hdr->num_chunks; i++) {
+ if ((cur < (void *)&chunk_hdr[i]) &&
+ !strncmp(chunk_hdr[i].chunk_id, chunk_id,
+ ICP_QAT_UOF_OBJID_LEN)) {
+ return &chunk_hdr[i];
+ }
+ }
+ return NULL;
+}
+
+static unsigned int qat_uclo_calc_checksum(unsigned int reg, int ch)
+{
+ int i;
+ unsigned int topbit = 1 << 0xF;
+ unsigned int inbyte = (unsigned int)((reg >> 0x18) ^ ch);
+
+ reg ^= inbyte << 0x8;
+ for (i = 0; i < 0x8; i++) {
+ if (reg & topbit)
+ reg = (reg << 1) ^ 0x1021;
+ else
+ reg <<= 1;
+ }
+ return reg & 0xFFFF;
+}
+
+static unsigned int qat_uclo_calc_str_checksum(char *ptr, int num)
+{
+ unsigned int chksum = 0;
+
+ if (ptr)
+ while (num--)
+ chksum = qat_uclo_calc_checksum(chksum, *ptr++);
+ return chksum;
+}
+
+static struct icp_qat_uclo_objhdr *
+qat_uclo_map_chunk(char *buf, struct icp_qat_uof_filehdr *file_hdr,
+ char *chunk_id)
+{
+ struct icp_qat_uof_filechunkhdr *file_chunk;
+ struct icp_qat_uclo_objhdr *obj_hdr;
+ char *chunk;
+ int i;
+
+ file_chunk = (struct icp_qat_uof_filechunkhdr *)
+ (buf + sizeof(struct icp_qat_uof_filehdr));
+ for (i = 0; i < file_hdr->num_chunks; i++) {
+ if (!strncmp(file_chunk->chunk_id, chunk_id,
+ ICP_QAT_UOF_OBJID_LEN)) {
+ chunk = buf + file_chunk->offset;
+ if (file_chunk->checksum != qat_uclo_calc_str_checksum(
+ chunk, file_chunk->size))
+ break;
+ obj_hdr = kzalloc(sizeof(*obj_hdr), GFP_KERNEL);
+ if (!obj_hdr)
+ break;
+ obj_hdr->file_buff = chunk;
+ obj_hdr->checksum = file_chunk->checksum;
+ obj_hdr->size = file_chunk->size;
+ return obj_hdr;
+ }
+ file_chunk++;
+ }
+ return NULL;
+}
+
+static unsigned int
+qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj,
+ struct icp_qat_uof_image *image)
+{
+ struct icp_qat_uof_objtable *uc_var_tab, *imp_var_tab, *imp_expr_tab;
+ struct icp_qat_uof_objtable *neigh_reg_tab;
+ struct icp_qat_uof_code_page *code_page;
+
+ code_page = (struct icp_qat_uof_code_page *)
+ ((char *)image + sizeof(struct icp_qat_uof_image));
+ uc_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
+ code_page->uc_var_tab_offset);
+ imp_var_tab = (struct icp_qat_uof_objtable *)(encap_uof_obj->beg_uof +
+ code_page->imp_var_tab_offset);
+ imp_expr_tab = (struct icp_qat_uof_objtable *)
+ (encap_uof_obj->beg_uof +
+ code_page->imp_expr_tab_offset);
+ if (uc_var_tab->entry_num || imp_var_tab->entry_num ||
+ imp_expr_tab->entry_num) {
+ pr_err("QAT: UOF can't contain imported variable to be parsed");
+ return -EINVAL;
+ }
+ neigh_reg_tab = (struct icp_qat_uof_objtable *)
+ (encap_uof_obj->beg_uof +
+ code_page->neigh_reg_tab_offset);
+ if (neigh_reg_tab->entry_num) {
+ pr_err("QAT: UOF can't contain shared control store feature");
+ return -EINVAL;
+ }
+ if (image->numpages > 1) {
+ pr_err("QAT: UOF can't contain multiple pages");
+ return -EINVAL;
+ }
+ if (ICP_QAT_SHARED_USTORE_MODE(image->ae_mode)) {
+ pr_err("QAT: UOF can't use shared control store feature");
+ return -EFAULT;
+ }
+ if (RELOADABLE_CTX_SHARED_MODE(image->ae_mode)) {
+ pr_err("QAT: UOF can't use reloadable feature");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void qat_uclo_map_image_page(struct icp_qat_uof_encap_obj
+ *encap_uof_obj,
+ struct icp_qat_uof_image *img,
+ struct icp_qat_uclo_encap_page *page)
+{
+ struct icp_qat_uof_code_page *code_page;
+ struct icp_qat_uof_code_area *code_area;
+ struct icp_qat_uof_objtable *uword_block_tab;
+ struct icp_qat_uof_uword_block *uwblock;
+ int i;
+
+ code_page = (struct icp_qat_uof_code_page *)
+ ((char *)img + sizeof(struct icp_qat_uof_image));
+ page->def_page = code_page->def_page;
+ page->page_region = code_page->page_region;
+ page->beg_addr_v = code_page->beg_addr_v;
+ page->beg_addr_p = code_page->beg_addr_p;
+ code_area = (struct icp_qat_uof_code_area *)(encap_uof_obj->beg_uof +
+ code_page->code_area_offset);
+ page->micro_words_num = code_area->micro_words_num;
+ uword_block_tab = (struct icp_qat_uof_objtable *)
+ (encap_uof_obj->beg_uof +
+ code_area->uword_block_tab);
+ page->uwblock_num = uword_block_tab->entry_num;
+ uwblock = (struct icp_qat_uof_uword_block *)((char *)uword_block_tab +
+ sizeof(struct icp_qat_uof_objtable));
+ page->uwblock = (struct icp_qat_uclo_encap_uwblock *)uwblock;
+ for (i = 0; i < uword_block_tab->entry_num; i++)
+ page->uwblock[i].micro_words =
+ (unsigned long)encap_uof_obj->beg_uof + uwblock[i].uword_offset;
+}
+
+static int qat_uclo_map_uimage(struct icp_qat_uclo_objhandle *obj_handle,
+ struct icp_qat_uclo_encapme *ae_uimage,
+ int max_image)
+{
+ int i, j;
+ struct icp_qat_uof_chunkhdr *chunk_hdr = NULL;
+ struct icp_qat_uof_image *image;
+ struct icp_qat_uof_objtable *ae_regtab;
+ struct icp_qat_uof_objtable *init_reg_sym_tab;
+ struct icp_qat_uof_objtable *sbreak_tab;
+ struct icp_qat_uof_encap_obj *encap_uof_obj =
+ &obj_handle->encap_uof_obj;
+
+ for (j = 0; j < max_image; j++) {
+ chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
+ ICP_QAT_UOF_IMAG, chunk_hdr);
+ if (!chunk_hdr)
+ break;
+ image = (struct icp_qat_uof_image *)(encap_uof_obj->beg_uof +
+ chunk_hdr->offset);
+ ae_regtab = (struct icp_qat_uof_objtable *)
+ (image->reg_tab_offset +
+ obj_handle->obj_hdr->file_buff);
+ ae_uimage[j].ae_reg_num = ae_regtab->entry_num;
+ ae_uimage[j].ae_reg = (struct icp_qat_uof_ae_reg *)
+ (((char *)ae_regtab) +
+ sizeof(struct icp_qat_uof_objtable));
+ init_reg_sym_tab = (struct icp_qat_uof_objtable *)
+ (image->init_reg_sym_tab +
+ obj_handle->obj_hdr->file_buff);
+ ae_uimage[j].init_regsym_num = init_reg_sym_tab->entry_num;
+ ae_uimage[j].init_regsym = (struct icp_qat_uof_init_regsym *)
+ (((char *)init_reg_sym_tab) +
+ sizeof(struct icp_qat_uof_objtable));
+ sbreak_tab = (struct icp_qat_uof_objtable *)
+ (image->sbreak_tab + obj_handle->obj_hdr->file_buff);
+ ae_uimage[j].sbreak_num = sbreak_tab->entry_num;
+ ae_uimage[j].sbreak = (struct icp_qat_uof_sbreak *)
+ (((char *)sbreak_tab) +
+ sizeof(struct icp_qat_uof_objtable));
+ ae_uimage[j].img_ptr = image;
+ if (qat_uclo_check_image_compat(encap_uof_obj, image))
+ goto out_err;
+ ae_uimage[j].page =
+ kzalloc(sizeof(struct icp_qat_uclo_encap_page),
+ GFP_KERNEL);
+ if (!ae_uimage[j].page)
+ goto out_err;
+ qat_uclo_map_image_page(encap_uof_obj, image,
+ ae_uimage[j].page);
+ }
+ return j;
+out_err:
+ for (i = 0; i < j; i++)
+ kfree(ae_uimage[i].page);
+ return 0;
+}
+
+static int qat_uclo_map_ae(struct icp_qat_fw_loader_handle *handle, int max_ae)
+{
+ int i, ae;
+ int mflag = 0;
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+
+ for (ae = 0; ae <= max_ae; ae++) {
+ if (!test_bit(ae,
+ (unsigned long *)&handle->hal_handle->ae_mask))
+ continue;
+ for (i = 0; i < obj_handle->uimage_num; i++) {
+ if (!test_bit(ae, (unsigned long *)
+ &obj_handle->ae_uimage[i].img_ptr->ae_assigned))
+ continue;
+ mflag = 1;
+ if (qat_uclo_init_ae_data(obj_handle, ae, i))
+ return -EINVAL;
+ }
+ }
+ if (!mflag) {
+ pr_err("QAT: uimage uses AE not set");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static struct icp_qat_uof_strtable *
+qat_uclo_map_str_table(struct icp_qat_uclo_objhdr *obj_hdr,
+ char *tab_name, struct icp_qat_uof_strtable *str_table)
+{
+ struct icp_qat_uof_chunkhdr *chunk_hdr;
+
+ chunk_hdr = qat_uclo_find_chunk((struct icp_qat_uof_objhdr *)
+ obj_hdr->file_buff, tab_name, NULL);
+ if (chunk_hdr) {
+ int hdr_size;
+
+ memcpy(&str_table->table_len, obj_hdr->file_buff +
+ chunk_hdr->offset, sizeof(str_table->table_len));
+ hdr_size = (char *)&str_table->strings - (char *)str_table;
+ str_table->strings = (unsigned long)obj_hdr->file_buff +
+ chunk_hdr->offset + hdr_size;
+ return str_table;
+ }
+ return NULL;
+}
+
+static void
+qat_uclo_map_initmem_table(struct icp_qat_uof_encap_obj *encap_uof_obj,
+ struct icp_qat_uclo_init_mem_table *init_mem_tab)
+{
+ struct icp_qat_uof_chunkhdr *chunk_hdr;
+
+ chunk_hdr = qat_uclo_find_chunk(encap_uof_obj->obj_hdr,
+ ICP_QAT_UOF_IMEM, NULL);
+ if (chunk_hdr) {
+ memmove(&init_mem_tab->entry_num, encap_uof_obj->beg_uof +
+ chunk_hdr->offset, sizeof(unsigned int));
+ init_mem_tab->init_mem = (struct icp_qat_uof_initmem *)
+ (encap_uof_obj->beg_uof + chunk_hdr->offset +
+ sizeof(unsigned int));
+ }
+}
+
+static int qat_uclo_check_uof_compat(struct icp_qat_uclo_objhandle *obj_handle)
+{
+ unsigned int maj_ver, prod_type = obj_handle->prod_type;
+
+ if (!(prod_type & obj_handle->encap_uof_obj.obj_hdr->cpu_type)) {
+ pr_err("QAT: UOF type 0x%x not match with cur platform 0x%x\n",
+ obj_handle->encap_uof_obj.obj_hdr->cpu_type, prod_type);
+ return -EINVAL;
+ }
+ maj_ver = obj_handle->prod_rev & 0xff;
+ if ((obj_handle->encap_uof_obj.obj_hdr->max_cpu_ver < maj_ver) ||
+ (obj_handle->encap_uof_obj.obj_hdr->min_cpu_ver > maj_ver)) {
+ pr_err("QAT: UOF majVer 0x%x out of range\n", maj_ver);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle,
+ unsigned char ae, unsigned char ctx_mask,
+ enum icp_qat_uof_regtype reg_type,
+ unsigned short reg_addr, unsigned int value)
+{
+ switch (reg_type) {
+ case ICP_GPA_ABS:
+ case ICP_GPB_ABS:
+ ctx_mask = 0;
+ case ICP_GPA_REL:
+ case ICP_GPB_REL:
+ return qat_hal_init_gpr(handle, ae, ctx_mask, reg_type,
+ reg_addr, value);
+ case ICP_SR_ABS:
+ case ICP_DR_ABS:
+ case ICP_SR_RD_ABS:
+ case ICP_DR_RD_ABS:
+ ctx_mask = 0;
+ case ICP_SR_REL:
+ case ICP_DR_REL:
+ case ICP_SR_RD_REL:
+ case ICP_DR_RD_REL:
+ return qat_hal_init_rd_xfer(handle, ae, ctx_mask, reg_type,
+ reg_addr, value);
+ case ICP_SR_WR_ABS:
+ case ICP_DR_WR_ABS:
+ ctx_mask = 0;
+ case ICP_SR_WR_REL:
+ case ICP_DR_WR_REL:
+ return qat_hal_init_wr_xfer(handle, ae, ctx_mask, reg_type,
+ reg_addr, value);
+ case ICP_NEIGH_REL:
+ return qat_hal_init_nn(handle, ae, ctx_mask, reg_addr, value);
+ default:
+ pr_err("QAT: UOF uses not supported reg type 0x%x\n", reg_type);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int qat_uclo_init_reg_sym(struct icp_qat_fw_loader_handle *handle,
+ unsigned int ae,
+ struct icp_qat_uclo_encapme *encap_ae)
+{
+ unsigned int i;
+ unsigned char ctx_mask;
+ struct icp_qat_uof_init_regsym *init_regsym;
+
+ if (ICP_QAT_CTX_MODE(encap_ae->img_ptr->ae_mode) ==
+ ICP_QAT_UCLO_MAX_CTX)
+ ctx_mask = 0xff;
+ else
+ ctx_mask = 0x55;
+
+ for (i = 0; i < encap_ae->init_regsym_num; i++) {
+ unsigned int exp_res;
+
+ init_regsym = &encap_ae->init_regsym[i];
+ exp_res = init_regsym->value;
+ switch (init_regsym->init_type) {
+ case ICP_QAT_UOF_INIT_REG:
+ qat_uclo_init_reg(handle, ae, ctx_mask,
+ (enum icp_qat_uof_regtype)
+ init_regsym->reg_type,
+ (unsigned short)init_regsym->reg_addr,
+ exp_res);
+ break;
+ case ICP_QAT_UOF_INIT_REG_CTX:
+ /* check if ctx is appropriate for the ctxMode */
+ if (!((1 << init_regsym->ctx) & ctx_mask)) {
+ pr_err("QAT: invalid ctx num = 0x%x\n",
+ init_regsym->ctx);
+ return -EINVAL;
+ }
+ qat_uclo_init_reg(handle, ae,
+ (unsigned char)
+ (1 << init_regsym->ctx),
+ (enum icp_qat_uof_regtype)
+ init_regsym->reg_type,
+ (unsigned short)init_regsym->reg_addr,
+ exp_res);
+ break;
+ case ICP_QAT_UOF_INIT_EXPR:
+ pr_err("QAT: INIT_EXPR feature not supported\n");
+ return -EINVAL;
+ case ICP_QAT_UOF_INIT_EXPR_ENDIAN_SWAP:
+ pr_err("QAT: INIT_EXPR_ENDIAN_SWAP feature not supported\n");
+ return -EINVAL;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int qat_uclo_init_globals(struct icp_qat_fw_loader_handle *handle)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int s, ae;
+
+ if (obj_handle->global_inited)
+ return 0;
+ if (obj_handle->init_mem_tab.entry_num) {
+ if (qat_uclo_init_memory(handle)) {
+ pr_err("QAT: initialize memory failed\n");
+ return -EINVAL;
+ }
+ }
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
+ if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
+ continue;
+ if (qat_uclo_init_reg_sym(handle, ae,
+ obj_handle->ae_data[ae].
+ ae_slices[s].encap_image))
+ return -EINVAL;
+ }
+ }
+ obj_handle->global_inited = 1;
+ return 0;
+}
+
+static int qat_uclo_set_ae_mode(struct icp_qat_fw_loader_handle *handle)
+{
+ unsigned char ae, nn_mode, s;
+ struct icp_qat_uof_image *uof_image;
+ struct icp_qat_uclo_aedata *ae_data;
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!test_bit(ae,
+ (unsigned long *)&handle->hal_handle->ae_mask))
+ continue;
+ ae_data = &obj_handle->ae_data[ae];
+ for (s = 0; s < min_t(unsigned int, ae_data->slice_num,
+ ICP_QAT_UCLO_MAX_CTX); s++) {
+ if (!obj_handle->ae_data[ae].ae_slices[s].encap_image)
+ continue;
+ uof_image = ae_data->ae_slices[s].encap_image->img_ptr;
+ if (qat_hal_set_ae_ctx_mode(handle, ae,
+ (char)ICP_QAT_CTX_MODE
+ (uof_image->ae_mode))) {
+ pr_err("QAT: qat_hal_set_ae_ctx_mode error\n");
+ return -EFAULT;
+ }
+ nn_mode = ICP_QAT_NN_MODE(uof_image->ae_mode);
+ if (qat_hal_set_ae_nn_mode(handle, ae, nn_mode)) {
+ pr_err("QAT: qat_hal_set_ae_nn_mode error\n");
+ return -EFAULT;
+ }
+ if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM0,
+ (char)ICP_QAT_LOC_MEM0_MODE
+ (uof_image->ae_mode))) {
+ pr_err("QAT: qat_hal_set_ae_lm_mode LMEM0 error\n");
+ return -EFAULT;
+ }
+ if (qat_hal_set_ae_lm_mode(handle, ae, ICP_LMEM1,
+ (char)ICP_QAT_LOC_MEM1_MODE
+ (uof_image->ae_mode))) {
+ pr_err("QAT: qat_hal_set_ae_lm_mode LMEM1 error\n");
+ return -EFAULT;
+ }
+ }
+ }
+ return 0;
+}
+
+static void qat_uclo_init_uword_num(struct icp_qat_fw_loader_handle *handle)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ struct icp_qat_uclo_encapme *image;
+ int a;
+
+ for (a = 0; a < obj_handle->uimage_num; a++) {
+ image = &obj_handle->ae_uimage[a];
+ image->uwords_num = image->page->beg_addr_p +
+ image->page->micro_words_num;
+ }
+}
+
+static int qat_uclo_parse_uof_obj(struct icp_qat_fw_loader_handle *handle)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int ae;
+
+ obj_handle->uword_buf = kcalloc(UWORD_CPYBUF_SIZE, sizeof(uint64_t),
+ GFP_KERNEL);
+ if (!obj_handle->uword_buf)
+ return -ENOMEM;
+ obj_handle->encap_uof_obj.beg_uof = obj_handle->obj_hdr->file_buff;
+ obj_handle->encap_uof_obj.obj_hdr = (struct icp_qat_uof_objhdr *)
+ obj_handle->obj_hdr->file_buff;
+ obj_handle->uword_in_bytes = 6;
+ obj_handle->prod_type = ICP_QAT_AC_C_CPU_TYPE;
+ obj_handle->prod_rev = PID_MAJOR_REV |
+ (PID_MINOR_REV & handle->hal_handle->revision_id);
+ if (qat_uclo_check_uof_compat(obj_handle)) {
+ pr_err("QAT: UOF incompatible\n");
+ return -EINVAL;
+ }
+ obj_handle->ustore_phy_size = ICP_QAT_UCLO_MAX_USTORE;
+ if (!obj_handle->obj_hdr->file_buff ||
+ !qat_uclo_map_str_table(obj_handle->obj_hdr, ICP_QAT_UOF_STRT,
+ &obj_handle->str_table)) {
+ pr_err("QAT: UOF doesn't have effective images\n");
+ goto out_err;
+ }
+ obj_handle->uimage_num =
+ qat_uclo_map_uimage(obj_handle, obj_handle->ae_uimage,
+ ICP_QAT_UCLO_MAX_AE * ICP_QAT_UCLO_MAX_CTX);
+ if (!obj_handle->uimage_num)
+ goto out_err;
+ if (qat_uclo_map_ae(handle, handle->hal_handle->ae_max_num)) {
+ pr_err("QAT: Bad object\n");
+ goto out_check_uof_aemask_err;
+ }
+ qat_uclo_init_uword_num(handle);
+ qat_uclo_map_initmem_table(&obj_handle->encap_uof_obj,
+ &obj_handle->init_mem_tab);
+ if (qat_uclo_set_ae_mode(handle))
+ goto out_check_uof_aemask_err;
+ return 0;
+out_check_uof_aemask_err:
+ for (ae = 0; ae < obj_handle->uimage_num; ae++)
+ kfree(obj_handle->ae_uimage[ae].page);
+out_err:
+ kfree(obj_handle->uword_buf);
+ return -EFAULT;
+}
+
+int qat_uclo_map_uof_obj(struct icp_qat_fw_loader_handle *handle,
+ void *addr_ptr, int mem_size)
+{
+ struct icp_qat_uof_filehdr *filehdr;
+ struct icp_qat_uclo_objhandle *objhdl;
+
+ BUILD_BUG_ON(ICP_QAT_UCLO_MAX_AE >=
+ (sizeof(handle->hal_handle->ae_mask) * 8));
+
+ if (!handle || !addr_ptr || mem_size < 24)
+ return -EINVAL;
+ objhdl = kzalloc(sizeof(*objhdl), GFP_KERNEL);
+ if (!objhdl)
+ return -ENOMEM;
+ objhdl->obj_buf = kmemdup(addr_ptr, mem_size, GFP_KERNEL);
+ if (!objhdl->obj_buf)
+ goto out_objbuf_err;
+ filehdr = (struct icp_qat_uof_filehdr *)objhdl->obj_buf;
+ if (qat_uclo_check_format(filehdr))
+ goto out_objhdr_err;
+ objhdl->obj_hdr = qat_uclo_map_chunk((char *)objhdl->obj_buf, filehdr,
+ ICP_QAT_UOF_OBJS);
+ if (!objhdl->obj_hdr) {
+ pr_err("QAT: object file chunk is null\n");
+ goto out_objhdr_err;
+ }
+ handle->obj_handle = objhdl;
+ if (qat_uclo_parse_uof_obj(handle))
+ goto out_overlay_obj_err;
+ return 0;
+
+out_overlay_obj_err:
+ handle->obj_handle = NULL;
+ kfree(objhdl->obj_hdr);
+out_objhdr_err:
+ kfree(objhdl->obj_buf);
+out_objbuf_err:
+ kfree(objhdl);
+ return -ENOMEM;
+}
+
+void qat_uclo_del_uof_obj(struct icp_qat_fw_loader_handle *handle)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int a;
+
+ if (!obj_handle)
+ return;
+
+ kfree(obj_handle->uword_buf);
+ for (a = 0; a < obj_handle->uimage_num; a++)
+ kfree(obj_handle->ae_uimage[a].page);
+
+ for (a = 0; a < handle->hal_handle->ae_max_num; a++)
+ qat_uclo_free_ae_data(&obj_handle->ae_data[a]);
+
+ kfree(obj_handle->obj_hdr);
+ kfree(obj_handle->obj_buf);
+ kfree(obj_handle);
+ handle->obj_handle = NULL;
+}
+
+static void qat_uclo_fill_uwords(struct icp_qat_uclo_objhandle *obj_handle,
+ struct icp_qat_uclo_encap_page *encap_page,
+ uint64_t *uword, unsigned int addr_p,
+ unsigned int raddr, uint64_t fill)
+{
+ uint64_t uwrd = 0;
+ unsigned int i;
+
+ if (!encap_page) {
+ *uword = fill;
+ return;
+ }
+ for (i = 0; i < encap_page->uwblock_num; i++) {
+ if (raddr >= encap_page->uwblock[i].start_addr &&
+ raddr <= encap_page->uwblock[i].start_addr +
+ encap_page->uwblock[i].words_num - 1) {
+ raddr -= encap_page->uwblock[i].start_addr;
+ raddr *= obj_handle->uword_in_bytes;
+ memcpy(&uwrd, (void *)(((unsigned long)
+ encap_page->uwblock[i].micro_words) + raddr),
+ obj_handle->uword_in_bytes);
+ uwrd = uwrd & 0xbffffffffffull;
+ }
+ }
+ *uword = uwrd;
+ if (*uword == INVLD_UWORD)
+ *uword = fill;
+}
+
+static void qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uclo_encap_page
+ *encap_page, unsigned int ae)
+{
+ unsigned int uw_physical_addr, uw_relative_addr, i, words_num, cpylen;
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ uint64_t fill_pat;
+
+ /* load the page starting at appropriate ustore address */
+ /* get fill-pattern from an image -- they are all the same */
+ memcpy(&fill_pat, obj_handle->ae_uimage[0].img_ptr->fill_pattern,
+ sizeof(uint64_t));
+ uw_physical_addr = encap_page->beg_addr_p;
+ uw_relative_addr = 0;
+ words_num = encap_page->micro_words_num;
+ while (words_num) {
+ if (words_num < UWORD_CPYBUF_SIZE)
+ cpylen = words_num;
+ else
+ cpylen = UWORD_CPYBUF_SIZE;
+
+ /* load the buffer */
+ for (i = 0; i < cpylen; i++)
+ qat_uclo_fill_uwords(obj_handle, encap_page,
+ &obj_handle->uword_buf[i],
+ uw_physical_addr + i,
+ uw_relative_addr + i, fill_pat);
+
+ /* copy the buffer to ustore */
+ qat_hal_wr_uwords(handle, (unsigned char)ae,
+ uw_physical_addr, cpylen,
+ obj_handle->uword_buf);
+
+ uw_physical_addr += cpylen;
+ uw_relative_addr += cpylen;
+ words_num -= cpylen;
+ }
+}
+
+static void qat_uclo_wr_uimage_page(struct icp_qat_fw_loader_handle *handle,
+ struct icp_qat_uof_image *image)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int ctx_mask, s;
+ struct icp_qat_uclo_page *page;
+ unsigned char ae;
+ int ctx;
+
+ if (ICP_QAT_CTX_MODE(image->ae_mode) == ICP_QAT_UCLO_MAX_CTX)
+ ctx_mask = 0xff;
+ else
+ ctx_mask = 0x55;
+ /* load the default page and set assigned CTX PC
+ * to the entrypoint address */
+ for (ae = 0; ae < handle->hal_handle->ae_max_num; ae++) {
+ if (!test_bit(ae, (unsigned long *)&image->ae_assigned))
+ continue;
+ /* find the slice to which this image is assigned */
+ for (s = 0; s < obj_handle->ae_data[ae].slice_num; s++) {
+ if (image->ctx_assigned & obj_handle->ae_data[ae].
+ ae_slices[s].ctx_mask_assigned)
+ break;
+ }
+ if (s >= obj_handle->ae_data[ae].slice_num)
+ continue;
+ page = obj_handle->ae_data[ae].ae_slices[s].page;
+ if (!page->encap_page->def_page)
+ continue;
+ qat_uclo_wr_uimage_raw_page(handle, page->encap_page, ae);
+
+ page = obj_handle->ae_data[ae].ae_slices[s].page;
+ for (ctx = 0; ctx < ICP_QAT_UCLO_MAX_CTX; ctx++)
+ obj_handle->ae_data[ae].ae_slices[s].cur_page[ctx] =
+ (ctx_mask & (1 << ctx)) ? page : NULL;
+ qat_hal_set_live_ctx(handle, (unsigned char)ae,
+ image->ctx_assigned);
+ qat_hal_set_pc(handle, (unsigned char)ae, image->ctx_assigned,
+ image->entry_address);
+ }
+}
+
+int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle)
+{
+ struct icp_qat_uclo_objhandle *obj_handle = handle->obj_handle;
+ unsigned int i;
+
+ if (qat_uclo_init_globals(handle))
+ return -EINVAL;
+ for (i = 0; i < obj_handle->uimage_num; i++) {
+ if (!obj_handle->ae_uimage[i].img_ptr)
+ return -EINVAL;
+ if (qat_uclo_init_ustore(handle, &obj_handle->ae_uimage[i]))
+ return -EINVAL;
+ qat_uclo_wr_uimage_page(handle,
+ obj_handle->ae_uimage[i].img_ptr);
+ }
+ return 0;
+}
diff --git a/drivers/crypto/qat/qat_dh895xcc/Makefile b/drivers/crypto/qat/qat_dh895xcc/Makefile
new file mode 100644
index 000000000000..25171c557043
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/Makefile
@@ -0,0 +1,8 @@
+ccflags-y := -I$(src)/../qat_common
+obj-$(CONFIG_CRYPTO_DEV_QAT_DH895xCC) += qat_dh895xcc.o
+qat_dh895xcc-objs := adf_drv.o \
+ adf_isr.o \
+ adf_dh895xcc_hw_data.o \
+ adf_hw_arbiter.o \
+ qat_admin.o \
+ adf_admin.o
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_admin.c b/drivers/crypto/qat/qat_dh895xcc/adf_admin.c
new file mode 100644
index 000000000000..978d6c56639d
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_admin.c
@@ -0,0 +1,144 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <adf_accel_devices.h>
+#include "adf_drv.h"
+#include "adf_dh895xcc_hw_data.h"
+
+#define ADF_ADMINMSG_LEN 32
+
+struct adf_admin_comms {
+ dma_addr_t phy_addr;
+ void *virt_addr;
+ void __iomem *mailbox_addr;
+ struct mutex lock; /* protects adf_admin_comms struct */
+};
+
+int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
+ uint32_t ae, void *in, void *out)
+{
+ struct adf_admin_comms *admin = accel_dev->admin;
+ int offset = ae * ADF_ADMINMSG_LEN * 2;
+ void __iomem *mailbox = admin->mailbox_addr;
+ int mb_offset = ae * ADF_DH895XCC_MAILBOX_STRIDE;
+ int times, received;
+
+ mutex_lock(&admin->lock);
+
+ if (ADF_CSR_RD(mailbox, mb_offset) == 1) {
+ mutex_unlock(&admin->lock);
+ return -EAGAIN;
+ }
+
+ memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
+ ADF_CSR_WR(mailbox, mb_offset, 1);
+ received = 0;
+ for (times = 0; times < 50; times++) {
+ msleep(20);
+ if (ADF_CSR_RD(mailbox, mb_offset) == 0) {
+ received = 1;
+ break;
+ }
+ }
+ if (received)
+ memcpy(out, admin->virt_addr + offset +
+ ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
+ else
+ pr_err("QAT: Failed to send admin msg to accelerator\n");
+
+ mutex_unlock(&admin->lock);
+ return received ? 0 : -EFAULT;
+}
+
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
+{
+ struct adf_admin_comms *admin;
+ struct adf_bar *pmisc = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
+ void __iomem *csr = pmisc->virt_addr;
+ void __iomem *mailbox = csr + ADF_DH895XCC_MAILBOX_BASE_OFFSET;
+ uint64_t reg_val;
+
+ admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
+ accel_dev->numa_node);
+ if (!admin)
+ return -ENOMEM;
+ admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+ &admin->phy_addr, GFP_KERNEL);
+ if (!admin->virt_addr) {
+ dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
+ kfree(admin);
+ return -ENOMEM;
+ }
+ reg_val = (uint64_t)admin->phy_addr;
+ ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGUR_OFFSET, reg_val >> 32);
+ ADF_CSR_WR(csr, ADF_DH895XCC_ADMINMSGLR_OFFSET, reg_val);
+ mutex_init(&admin->lock);
+ admin->mailbox_addr = mailbox;
+ accel_dev->admin = admin;
+ return 0;
+}
+
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
+{
+ struct adf_admin_comms *admin = accel_dev->admin;
+
+ if (!admin)
+ return;
+
+ if (admin->virt_addr)
+ dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+ admin->virt_addr, admin->phy_addr);
+
+ mutex_destroy(&admin->lock);
+ kfree(admin);
+ accel_dev->admin = NULL;
+}
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
new file mode 100644
index 000000000000..ef05825cc651
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
@@ -0,0 +1,214 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <adf_accel_devices.h>
+#include "adf_dh895xcc_hw_data.h"
+#include "adf_drv.h"
+
+/* Worker thread to service arbiter mappings based on dev SKUs */
+static const uint32_t thrd_to_arb_map_sku4[] = {
+ 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
+ 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+static const uint32_t thrd_to_arb_map_sku6[] = {
+ 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
+ 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
+ 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222
+};
+
+static struct adf_hw_device_class dh895xcc_class = {
+ .name = ADF_DH895XCC_DEVICE_NAME,
+ .type = DEV_DH895XCC,
+ .instances = 0
+};
+
+static uint32_t get_accel_mask(uint32_t fuse)
+{
+ return (~fuse) >> ADF_DH895XCC_ACCELERATORS_REG_OFFSET &
+ ADF_DH895XCC_ACCELERATORS_MASK;
+}
+
+static uint32_t get_ae_mask(uint32_t fuse)
+{
+ return (~fuse) & ADF_DH895XCC_ACCELENGINES_MASK;
+}
+
+static uint32_t get_num_accels(struct adf_hw_device_data *self)
+{
+ uint32_t i, ctr = 0;
+
+ if (!self || !self->accel_mask)
+ return 0;
+
+ for (i = 0; i < ADF_DH895XCC_MAX_ACCELERATORS; i++) {
+ if (self->accel_mask & (1 << i))
+ ctr++;
+ }
+ return ctr;
+}
+
+static uint32_t get_num_aes(struct adf_hw_device_data *self)
+{
+ uint32_t i, ctr = 0;
+
+ if (!self || !self->ae_mask)
+ return 0;
+
+ for (i = 0; i < ADF_DH895XCC_MAX_ACCELENGINES; i++) {
+ if (self->ae_mask & (1 << i))
+ ctr++;
+ }
+ return ctr;
+}
+
+static uint32_t get_misc_bar_id(struct adf_hw_device_data *self)
+{
+ return ADF_DH895XCC_PMISC_BAR;
+}
+
+static uint32_t get_etr_bar_id(struct adf_hw_device_data *self)
+{
+ return ADF_DH895XCC_ETR_BAR;
+}
+
+static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
+{
+ int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK)
+ >> ADF_DH895XCC_FUSECTL_SKU_SHIFT;
+
+ switch (sku) {
+ case ADF_DH895XCC_FUSECTL_SKU_1:
+ return DEV_SKU_1;
+ case ADF_DH895XCC_FUSECTL_SKU_2:
+ return DEV_SKU_2;
+ case ADF_DH895XCC_FUSECTL_SKU_3:
+ return DEV_SKU_3;
+ case ADF_DH895XCC_FUSECTL_SKU_4:
+ return DEV_SKU_4;
+ default:
+ return DEV_SKU_UNKNOWN;
+ }
+ return DEV_SKU_UNKNOWN;
+}
+
+void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
+ uint32_t const **arb_map_config)
+{
+ switch (accel_dev->accel_pci_dev.sku) {
+ case DEV_SKU_1:
+ *arb_map_config = thrd_to_arb_map_sku4;
+ break;
+
+ case DEV_SKU_2:
+ case DEV_SKU_4:
+ *arb_map_config = thrd_to_arb_map_sku6;
+ break;
+ default:
+ pr_err("QAT: The configuration doesn't match any SKU");
+ *arb_map_config = NULL;
+ }
+}
+
+static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+ struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
+ void __iomem *csr = misc_bar->virt_addr;
+ unsigned int val, i;
+
+ /* Enable Accel Engine error detection & correction */
+ for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
+ val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_CTX_ENABLES(i));
+ val |= ADF_DH895XCC_ENABLE_AE_ECC_ERR;
+ ADF_CSR_WR(csr, ADF_DH895XCC_AE_CTX_ENABLES(i), val);
+ val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_MISC_CONTROL(i));
+ val |= ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR;
+ ADF_CSR_WR(csr, ADF_DH895XCC_AE_MISC_CONTROL(i), val);
+ }
+
+ /* Enable shared memory error detection & correction */
+ for (i = 0; i < hw_device->get_num_accels(hw_device); i++) {
+ val = ADF_CSR_RD(csr, ADF_DH895XCC_UERRSSMSH(i));
+ val |= ADF_DH895XCC_ERRSSMSH_EN;
+ ADF_CSR_WR(csr, ADF_DH895XCC_UERRSSMSH(i), val);
+ val = ADF_CSR_RD(csr, ADF_DH895XCC_CERRSSMSH(i));
+ val |= ADF_DH895XCC_ERRSSMSH_EN;
+ ADF_CSR_WR(csr, ADF_DH895XCC_CERRSSMSH(i), val);
+ }
+}
+
+void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
+{
+ hw_data->dev_class = &dh895xcc_class;
+ hw_data->instance_id = dh895xcc_class.instances++;
+ hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS;
+ hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS;
+ hw_data->pci_dev_id = ADF_DH895XCC_PCI_DEVICE_ID;
+ hw_data->num_logical_accel = 1;
+ hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES;
+ hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET;
+ hw_data->tx_rings_mask = ADF_DH895XCC_TX_RINGS_MASK;
+ hw_data->alloc_irq = adf_isr_resource_alloc;
+ hw_data->free_irq = adf_isr_resource_free;
+ hw_data->enable_error_correction = adf_enable_error_correction;
+ hw_data->hw_arb_ring_enable = adf_update_ring_arb_enable;
+ hw_data->hw_arb_ring_disable = adf_update_ring_arb_enable;
+ hw_data->get_accel_mask = get_accel_mask;
+ hw_data->get_ae_mask = get_ae_mask;
+ hw_data->get_num_accels = get_num_accels;
+ hw_data->get_num_aes = get_num_aes;
+ hw_data->get_etr_bar_id = get_etr_bar_id;
+ hw_data->get_misc_bar_id = get_misc_bar_id;
+ hw_data->get_sku = get_sku;
+ hw_data->fw_name = ADF_DH895XCC_FW;
+}
+
+void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
+{
+ hw_data->dev_class->instances--;
+}
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h
new file mode 100644
index 000000000000..b707f292b377
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h
@@ -0,0 +1,86 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_DH895x_HW_DATA_H_
+#define ADF_DH895x_HW_DATA_H_
+
+/* PCIe configuration space */
+#define ADF_DH895XCC_RX_RINGS_OFFSET 8
+#define ADF_DH895XCC_TX_RINGS_MASK 0xFF
+#define ADF_DH895XCC_FUSECTL_OFFSET 0x40
+#define ADF_DH895XCC_FUSECTL_SKU_MASK 0x300000
+#define ADF_DH895XCC_FUSECTL_SKU_SHIFT 20
+#define ADF_DH895XCC_FUSECTL_SKU_1 0x0
+#define ADF_DH895XCC_FUSECTL_SKU_2 0x1
+#define ADF_DH895XCC_FUSECTL_SKU_3 0x2
+#define ADF_DH895XCC_FUSECTL_SKU_4 0x3
+#define ADF_DH895XCC_MAX_ACCELERATORS 6
+#define ADF_DH895XCC_MAX_ACCELENGINES 12
+#define ADF_DH895XCC_ACCELERATORS_REG_OFFSET 13
+#define ADF_DH895XCC_ACCELERATORS_MASK 0x3F
+#define ADF_DH895XCC_ACCELENGINES_MASK 0xFFF
+#define ADF_DH895XCC_LEGFUSE_OFFSET 0x4C
+#define ADF_DH895XCC_ETR_MAX_BANKS 32
+#define ADF_DH895XCC_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28)
+#define ADF_DH895XCC_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30)
+#define ADF_DH895XCC_SMIA0_MASK 0xFFFF
+#define ADF_DH895XCC_SMIA1_MASK 0x1
+/* Error detection and correction */
+#define ADF_DH895XCC_AE_CTX_ENABLES(i) (i * 0x1000 + 0x20818)
+#define ADF_DH895XCC_AE_MISC_CONTROL(i) (i * 0x1000 + 0x20960)
+#define ADF_DH895XCC_ENABLE_AE_ECC_ERR (1 << 28)
+#define ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR (1 << 24 | 1 << 12)
+#define ADF_DH895XCC_UERRSSMSH(i) (i * 0x4000 + 0x18)
+#define ADF_DH895XCC_CERRSSMSH(i) (i * 0x4000 + 0x10)
+#define ADF_DH895XCC_ERRSSMSH_EN (1 << 3)
+
+/* Admin Messages Registers */
+#define ADF_DH895XCC_ADMINMSGUR_OFFSET (0x3A000 + 0x574)
+#define ADF_DH895XCC_ADMINMSGLR_OFFSET (0x3A000 + 0x578)
+#define ADF_DH895XCC_MAILBOX_BASE_OFFSET 0x20970
+#define ADF_DH895XCC_MAILBOX_STRIDE 0x1000
+#define ADF_DH895XCC_FW "qat_895xcc.bin"
+#endif
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
new file mode 100644
index 000000000000..0d0435a41be9
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
@@ -0,0 +1,449 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_transport_access_macros.h>
+#include "adf_dh895xcc_hw_data.h"
+#include "adf_drv.h"
+
+static const char adf_driver_name[] = ADF_DH895XCC_DEVICE_NAME;
+
+#define ADF_SYSTEM_DEVICE(device_id) \
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+
+static const struct pci_device_id adf_pci_tbl[] = {
+ ADF_SYSTEM_DEVICE(ADF_DH895XCC_PCI_DEVICE_ID),
+ {0,}
+};
+MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
+
+static int adf_probe(struct pci_dev *dev, const struct pci_device_id *ent);
+static void adf_remove(struct pci_dev *dev);
+
+static struct pci_driver adf_driver = {
+ .id_table = adf_pci_tbl,
+ .name = adf_driver_name,
+ .probe = adf_probe,
+ .remove = adf_remove
+};
+
+static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
+{
+ struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
+ int i;
+
+ adf_exit_admin_comms(accel_dev);
+ adf_exit_arb(accel_dev);
+ adf_cleanup_etr_data(accel_dev);
+
+ for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
+ struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+
+ if (bar->virt_addr)
+ pci_iounmap(accel_pci_dev->pci_dev, bar->virt_addr);
+ }
+
+ if (accel_dev->hw_device) {
+ switch (accel_dev->hw_device->pci_dev_id) {
+ case ADF_DH895XCC_PCI_DEVICE_ID:
+ adf_clean_hw_data_dh895xcc(accel_dev->hw_device);
+ break;
+ default:
+ break;
+ }
+ kfree(accel_dev->hw_device);
+ }
+ adf_cfg_dev_remove(accel_dev);
+ debugfs_remove(accel_dev->debugfs_dir);
+ adf_devmgr_rm_dev(accel_dev);
+ pci_release_regions(accel_pci_dev->pci_dev);
+ pci_disable_device(accel_pci_dev->pci_dev);
+ kfree(accel_dev);
+}
+
+static uint8_t adf_get_dev_node_id(struct pci_dev *pdev)
+{
+ unsigned int bus_per_cpu = 0;
+ struct cpuinfo_x86 *c = &cpu_data(num_online_cpus() - 1);
+
+ if (!c->phys_proc_id)
+ return 0;
+
+ bus_per_cpu = 256 / (c->phys_proc_id + 1);
+
+ if (bus_per_cpu != 0)
+ return pdev->bus->number / bus_per_cpu;
+ return 0;
+}
+
+static int qat_dev_start(struct adf_accel_dev *accel_dev)
+{
+ int cpus = num_online_cpus();
+ int banks = GET_MAX_BANKS(accel_dev);
+ int instances = min(cpus, banks);
+ char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
+ int i;
+ unsigned long val;
+
+ if (adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC))
+ goto err;
+ if (adf_cfg_section_add(accel_dev, "Accelerator0"))
+ goto err;
+ for (i = 0; i < instances; i++) {
+ val = i;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY,
+ i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_SIZE, i);
+ val = 128;
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 512;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_SIZE, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 0;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_TX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 2;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_TX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 4;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_TX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 8;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_RX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 10;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_SYM_RX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = 12;
+ snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_RND_RX, i);
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ key, (void *)&val, ADF_DEC))
+ goto err;
+
+ val = ADF_COALESCING_DEF_TIME;
+ snprintf(key, sizeof(key), ADF_ETRMGR_COALESCE_TIMER_FORMAT, i);
+ if (adf_cfg_add_key_value_param(accel_dev, "Accelerator0",
+ key, (void *)&val, ADF_DEC))
+ goto err;
+ }
+
+ val = i;
+ if (adf_cfg_add_key_value_param(accel_dev, ADF_KERNEL_SEC,
+ ADF_NUM_CY, (void *)&val, ADF_DEC))
+ goto err;
+
+ set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
+ return adf_dev_start(accel_dev);
+err:
+ dev_err(&GET_DEV(accel_dev), "Failed to start QAT accel dev\n");
+ return -EINVAL;
+}
+
+static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct adf_accel_dev *accel_dev;
+ struct adf_accel_pci *accel_pci_dev;
+ struct adf_hw_device_data *hw_data;
+ void __iomem *pmisc_bar_addr = NULL;
+ char name[ADF_DEVICE_NAME_LENGTH];
+ unsigned int i, bar_nr;
+ uint8_t node;
+ int ret;
+
+ switch (ent->device) {
+ case ADF_DH895XCC_PCI_DEVICE_ID:
+ break;
+ default:
+ dev_err(&pdev->dev, "Invalid device 0x%x.\n", ent->device);
+ return -ENODEV;
+ }
+
+ node = adf_get_dev_node_id(pdev);
+ accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL, node);
+ if (!accel_dev)
+ return -ENOMEM;
+
+ accel_dev->numa_node = node;
+ INIT_LIST_HEAD(&accel_dev->crypto_list);
+
+ /* Add accel device to accel table.
+ * This should be called before adf_cleanup_accel is called */
+ if (adf_devmgr_add_dev(accel_dev)) {
+ dev_err(&pdev->dev, "Failed to add new accelerator device.\n");
+ kfree(accel_dev);
+ return -EFAULT;
+ }
+
+ accel_dev->owner = THIS_MODULE;
+ /* Allocate and configure device configuration structure */
+ hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL, node);
+ if (!hw_data) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ accel_dev->hw_device = hw_data;
+ switch (ent->device) {
+ case ADF_DH895XCC_PCI_DEVICE_ID:
+ adf_init_hw_data_dh895xcc(accel_dev->hw_device);
+ break;
+ default:
+ return -ENODEV;
+ }
+ accel_pci_dev = &accel_dev->accel_pci_dev;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &accel_pci_dev->revid);
+ pci_read_config_dword(pdev, ADF_DH895XCC_FUSECTL_OFFSET,
+ &hw_data->fuses);
+
+ /* Get Accelerators and Accelerators Engines masks */
+ hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses);
+ hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses);
+ accel_pci_dev->sku = hw_data->get_sku(hw_data);
+ accel_pci_dev->pci_dev = pdev;
+ /* If the device has no acceleration engines then ignore it. */
+ if (!hw_data->accel_mask || !hw_data->ae_mask ||
+ ((~hw_data->ae_mask) & 0x01)) {
+ dev_err(&pdev->dev, "No acceleration units found");
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ /* Create dev top level debugfs entry */
+ snprintf(name, sizeof(name), "%s%s_dev%d", ADF_DEVICE_NAME_PREFIX,
+ hw_data->dev_class->name, hw_data->instance_id);
+ accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
+ if (!accel_dev->debugfs_dir) {
+ dev_err(&pdev->dev, "Could not create debugfs dir\n");
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ /* Create device configuration table */
+ ret = adf_cfg_dev_add(accel_dev);
+ if (ret)
+ goto out_err;
+
+ /* enable PCI device */
+ if (pci_enable_device(pdev)) {
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ /* set dma identifier */
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
+ dev_err(&pdev->dev, "No usable DMA configuration\n");
+ ret = -EFAULT;
+ goto out_err;
+ } else {
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ }
+
+ } else {
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ }
+
+ if (pci_request_regions(pdev, adf_driver_name)) {
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ /* Read accelerator capabilities mask */
+ pci_read_config_dword(pdev, ADF_DH895XCC_LEGFUSE_OFFSET,
+ &hw_data->accel_capabilities_mask);
+
+ /* Find and map all the device's BARS */
+ for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
+ struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
+
+ bar_nr = i * 2;
+ bar->base_addr = pci_resource_start(pdev, bar_nr);
+ if (!bar->base_addr)
+ break;
+ bar->size = pci_resource_len(pdev, bar_nr);
+ bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0);
+ if (!bar->virt_addr) {
+ dev_err(&pdev->dev, "Failed to map BAR %d\n", i);
+ ret = -EFAULT;
+ goto out_err;
+ }
+ if (i == ADF_DH895XCC_PMISC_BAR)
+ pmisc_bar_addr = bar->virt_addr;
+ }
+ pci_set_master(pdev);
+
+ if (adf_enable_aer(accel_dev, &adf_driver)) {
+ dev_err(&pdev->dev, "Failed to enable aer\n");
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ if (adf_init_etr_data(accel_dev)) {
+ dev_err(&pdev->dev, "Failed initialize etr\n");
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ if (adf_init_admin_comms(accel_dev)) {
+ dev_err(&pdev->dev, "Failed initialize admin comms\n");
+ ret = -EFAULT;
+ goto out_err;
+ }
+
+ if (adf_init_arb(accel_dev)) {
+ dev_err(&pdev->dev, "Failed initialize hw arbiter\n");
+ ret = -EFAULT;
+ goto out_err;
+ }
+ if (pci_save_state(pdev)) {
+ dev_err(&pdev->dev, "Failed to save pci state\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ /* Enable bundle and misc interrupts */
+ ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCC_SMIAPF0_MASK_OFFSET,
+ ADF_DH895XCC_SMIA0_MASK);
+ ADF_CSR_WR(pmisc_bar_addr, ADF_DH895XCC_SMIAPF1_MASK_OFFSET,
+ ADF_DH895XCC_SMIA1_MASK);
+
+ ret = qat_dev_start(accel_dev);
+ if (ret) {
+ adf_dev_stop(accel_dev);
+ goto out_err;
+ }
+
+ return 0;
+out_err:
+ adf_cleanup_accel(accel_dev);
+ return ret;
+}
+
+static void __exit adf_remove(struct pci_dev *pdev)
+{
+ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
+
+ if (!accel_dev) {
+ pr_err("QAT: Driver removal failed\n");
+ return;
+ }
+ if (adf_dev_stop(accel_dev))
+ dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
+ adf_disable_aer(accel_dev);
+ adf_cleanup_accel(accel_dev);
+}
+
+static int __init adfdrv_init(void)
+{
+ request_module("intel_qat");
+ if (qat_admin_register())
+ return -EFAULT;
+
+ if (pci_register_driver(&adf_driver)) {
+ pr_err("QAT: Driver initialization failed\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void __exit adfdrv_release(void)
+{
+ pci_unregister_driver(&adf_driver);
+ qat_admin_unregister();
+}
+
+module_init(adfdrv_init);
+module_exit(adfdrv_release);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Intel");
+MODULE_FIRMWARE("qat_895xcc.bin");
+MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_drv.h b/drivers/crypto/qat/qat_dh895xcc/adf_drv.h
new file mode 100644
index 000000000000..a2fbb6ce75cd
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_drv.h
@@ -0,0 +1,67 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef ADF_DH895x_DRV_H_
+#define ADF_DH895x_DRV_H_
+#include <adf_accel_devices.h>
+#include <adf_transport.h>
+
+void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
+void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data);
+int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev);
+void adf_isr_resource_free(struct adf_accel_dev *accel_dev);
+void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring);
+void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
+ uint32_t const **arb_map_config);
+int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
+void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
+int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev,
+ uint32_t ae, void *in, void *out);
+int qat_admin_register(void);
+int qat_admin_unregister(void);
+int adf_init_arb(struct adf_accel_dev *accel_dev);
+void adf_exit_arb(struct adf_accel_dev *accel_dev);
+#endif
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c b/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c
new file mode 100644
index 000000000000..1864bdb36f8f
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_hw_arbiter.c
@@ -0,0 +1,159 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <adf_accel_devices.h>
+#include <adf_transport_internal.h>
+#include "adf_drv.h"
+
+#define ADF_ARB_NUM 4
+#define ADF_ARB_REQ_RING_NUM 8
+#define ADF_ARB_REG_SIZE 0x4
+#define ADF_ARB_WTR_SIZE 0x20
+#define ADF_ARB_OFFSET 0x30000
+#define ADF_ARB_REG_SLOT 0x1000
+#define ADF_ARB_WTR_OFFSET 0x010
+#define ADF_ARB_RO_EN_OFFSET 0x090
+#define ADF_ARB_WQCFG_OFFSET 0x100
+#define ADF_ARB_WRK_2_SER_MAP_OFFSET 0x180
+#define ADF_ARB_WRK_2_SER_MAP 10
+#define ADF_ARB_RINGSRVARBEN_OFFSET 0x19C
+
+#define WRITE_CSR_ARB_RINGSRVARBEN(csr_addr, index, value) \
+ ADF_CSR_WR(csr_addr, ADF_ARB_RINGSRVARBEN_OFFSET + \
+ (ADF_ARB_REG_SLOT * index), value)
+
+#define WRITE_CSR_ARB_RESPORDERING(csr_addr, index, value) \
+ ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+ ADF_ARB_RO_EN_OFFSET) + (ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WEIGHT(csr_addr, arb, index, value) \
+ ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+ ADF_ARB_WTR_OFFSET) + (ADF_ARB_WTR_SIZE * arb) + \
+ (ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_SARCONFIG(csr_addr, index, value) \
+ ADF_CSR_WR(csr_addr, ADF_ARB_OFFSET + \
+ (ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WRK_2_SER_MAP(csr_addr, index, value) \
+ ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+ ADF_ARB_WRK_2_SER_MAP_OFFSET) + \
+ (ADF_ARB_REG_SIZE * index), value)
+
+#define WRITE_CSR_ARB_WQCFG(csr_addr, index, value) \
+ ADF_CSR_WR(csr_addr, (ADF_ARB_OFFSET + \
+ ADF_ARB_WQCFG_OFFSET) + (ADF_ARB_REG_SIZE * index), value)
+
+int adf_init_arb(struct adf_accel_dev *accel_dev)
+{
+ void __iomem *csr = accel_dev->transport->banks[0].csr_addr;
+ uint32_t arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1;
+ uint32_t arb, i;
+ const uint32_t *thd_2_arb_cfg;
+
+ /* Service arb configured for 32 bytes responses and
+ * ring flow control check enabled. */
+ for (arb = 0; arb < ADF_ARB_NUM; arb++)
+ WRITE_CSR_ARB_SARCONFIG(csr, arb, arb_cfg);
+
+ /* Setup service weighting */
+ for (arb = 0; arb < ADF_ARB_NUM; arb++)
+ for (i = 0; i < ADF_ARB_REQ_RING_NUM; i++)
+ WRITE_CSR_ARB_WEIGHT(csr, arb, i, 0xFFFFFFFF);
+
+ /* Setup ring response ordering */
+ for (i = 0; i < ADF_ARB_REQ_RING_NUM; i++)
+ WRITE_CSR_ARB_RESPORDERING(csr, i, 0xFFFFFFFF);
+
+ /* Setup worker queue registers */
+ for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+ WRITE_CSR_ARB_WQCFG(csr, i, i);
+
+ /* Map worker threads to service arbiters */
+ adf_get_arbiter_mapping(accel_dev, &thd_2_arb_cfg);
+
+ if (!thd_2_arb_cfg)
+ return -EFAULT;
+
+ for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+ WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, *(thd_2_arb_cfg + i));
+
+ return 0;
+}
+
+void adf_update_ring_arb_enable(struct adf_etr_ring_data *ring)
+{
+ WRITE_CSR_ARB_RINGSRVARBEN(ring->bank->csr_addr,
+ ring->bank->bank_number,
+ ring->bank->ring_mask & 0xFF);
+}
+
+void adf_exit_arb(struct adf_accel_dev *accel_dev)
+{
+ void __iomem *csr;
+ unsigned int i;
+
+ if (!accel_dev->transport)
+ return;
+
+ csr = accel_dev->transport->banks[0].csr_addr;
+
+ /* Reset arbiter configuration */
+ for (i = 0; i < ADF_ARB_NUM; i++)
+ WRITE_CSR_ARB_SARCONFIG(csr, i, 0);
+
+ /* Shutdown work queue */
+ for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+ WRITE_CSR_ARB_WQCFG(csr, i, 0);
+
+ /* Unmap worker threads to service arbiters */
+ for (i = 0; i < ADF_ARB_WRK_2_SER_MAP; i++)
+ WRITE_CSR_ARB_WRK_2_SER_MAP(csr, i, 0);
+
+ /* Disable arbitration on all rings */
+ for (i = 0; i < GET_MAX_BANKS(accel_dev); i++)
+ WRITE_CSR_ARB_RINGSRVARBEN(csr, i, 0);
+}
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_isr.c b/drivers/crypto/qat/qat_dh895xcc/adf_isr.c
new file mode 100644
index 000000000000..d4172dedf775
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_isr.c
@@ -0,0 +1,266 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include <adf_cfg.h>
+#include <adf_cfg_strings.h>
+#include <adf_cfg_common.h>
+#include <adf_transport_access_macros.h>
+#include <adf_transport_internal.h>
+#include "adf_drv.h"
+
+static int adf_enable_msix(struct adf_accel_dev *accel_dev)
+{
+ struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint32_t msix_num_entries = hw_data->num_banks + 1;
+ int i;
+
+ for (i = 0; i < msix_num_entries; i++)
+ pci_dev_info->msix_entries.entries[i].entry = i;
+
+ if (pci_enable_msix(pci_dev_info->pci_dev,
+ pci_dev_info->msix_entries.entries,
+ msix_num_entries)) {
+ pr_err("QAT: Failed to enable MSIX IRQ\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void adf_disable_msix(struct adf_accel_pci *pci_dev_info)
+{
+ pci_disable_msix(pci_dev_info->pci_dev);
+}
+
+static irqreturn_t adf_msix_isr_bundle(int irq, void *bank_ptr)
+{
+ struct adf_etr_bank_data *bank = bank_ptr;
+
+ WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number, 0);
+ tasklet_hi_schedule(&bank->resp_hanlder);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
+{
+ struct adf_accel_dev *accel_dev = dev_ptr;
+
+ pr_info("QAT: qat_dev%d spurious AE interrupt\n", accel_dev->accel_id);
+ return IRQ_HANDLED;
+}
+
+static int adf_request_irqs(struct adf_accel_dev *accel_dev)
+{
+ struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
+ struct adf_etr_data *etr_data = accel_dev->transport;
+ int ret, i;
+ char *name;
+
+ /* Request msix irq for all banks */
+ for (i = 0; i < hw_data->num_banks; i++) {
+ struct adf_etr_bank_data *bank = &etr_data->banks[i];
+ unsigned int cpu, cpus = num_online_cpus();
+
+ name = *(pci_dev_info->msix_entries.names + i);
+ snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
+ "qat%d-bundle%d", accel_dev->accel_id, i);
+ ret = request_irq(msixe[i].vector,
+ adf_msix_isr_bundle, 0, name, bank);
+ if (ret) {
+ pr_err("QAT: failed to enable irq %d for %s\n",
+ msixe[i].vector, name);
+ return ret;
+ }
+
+ cpu = ((accel_dev->accel_id * hw_data->num_banks) + i) % cpus;
+ irq_set_affinity_hint(msixe[i].vector, get_cpu_mask(cpu));
+ }
+
+ /* Request msix irq for AE */
+ name = *(pci_dev_info->msix_entries.names + i);
+ snprintf(name, ADF_MAX_MSIX_VECTOR_NAME,
+ "qat%d-ae-cluster", accel_dev->accel_id);
+ ret = request_irq(msixe[i].vector, adf_msix_isr_ae, 0, name, accel_dev);
+ if (ret) {
+ pr_err("QAT: failed to enable irq %d, for %s\n",
+ msixe[i].vector, name);
+ return ret;
+ }
+ return ret;
+}
+
+static void adf_free_irqs(struct adf_accel_dev *accel_dev)
+{
+ struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ struct msix_entry *msixe = pci_dev_info->msix_entries.entries;
+ struct adf_etr_data *etr_data = accel_dev->transport;
+ int i;
+
+ for (i = 0; i < hw_data->num_banks; i++) {
+ irq_set_affinity_hint(msixe[i].vector, NULL);
+ free_irq(msixe[i].vector, &etr_data->banks[i]);
+ }
+ irq_set_affinity_hint(msixe[i].vector, NULL);
+ free_irq(msixe[i].vector, accel_dev);
+}
+
+static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
+{
+ int i;
+ char **names;
+ struct msix_entry *entries;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint32_t msix_num_entries = hw_data->num_banks + 1;
+
+ entries = kzalloc_node(msix_num_entries * sizeof(*entries),
+ GFP_KERNEL, accel_dev->numa_node);
+ if (!entries)
+ return -ENOMEM;
+
+ names = kcalloc(msix_num_entries, sizeof(char *), GFP_KERNEL);
+ if (!names) {
+ kfree(entries);
+ return -ENOMEM;
+ }
+ for (i = 0; i < msix_num_entries; i++) {
+ *(names + i) = kzalloc(ADF_MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
+ if (!(*(names + i)))
+ goto err;
+ }
+ accel_dev->accel_pci_dev.msix_entries.entries = entries;
+ accel_dev->accel_pci_dev.msix_entries.names = names;
+ return 0;
+err:
+ for (i = 0; i < msix_num_entries; i++) {
+ if (*(names + i))
+ kfree(*(names + i));
+ }
+ kfree(entries);
+ kfree(names);
+ return -ENOMEM;
+}
+
+static void adf_isr_free_msix_entry_table(struct adf_accel_dev *accel_dev)
+{
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ uint32_t msix_num_entries = hw_data->num_banks + 1;
+ char **names = accel_dev->accel_pci_dev.msix_entries.names;
+ int i;
+
+ kfree(accel_dev->accel_pci_dev.msix_entries.entries);
+ for (i = 0; i < msix_num_entries; i++) {
+ if (*(names + i))
+ kfree(*(names + i));
+ }
+ kfree(names);
+}
+
+static int adf_setup_bh(struct adf_accel_dev *accel_dev)
+{
+ struct adf_etr_data *priv_data = accel_dev->transport;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ int i;
+
+ for (i = 0; i < hw_data->num_banks; i++)
+ tasklet_init(&priv_data->banks[i].resp_hanlder,
+ adf_response_handler,
+ (unsigned long)&priv_data->banks[i]);
+ return 0;
+}
+
+static void adf_cleanup_bh(struct adf_accel_dev *accel_dev)
+{
+ struct adf_etr_data *priv_data = accel_dev->transport;
+ struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+ int i;
+
+ for (i = 0; i < hw_data->num_banks; i++) {
+ tasklet_disable(&priv_data->banks[i].resp_hanlder);
+ tasklet_kill(&priv_data->banks[i].resp_hanlder);
+ }
+}
+
+void adf_isr_resource_free(struct adf_accel_dev *accel_dev)
+{
+ adf_free_irqs(accel_dev);
+ adf_cleanup_bh(accel_dev);
+ adf_disable_msix(&accel_dev->accel_pci_dev);
+ adf_isr_free_msix_entry_table(accel_dev);
+}
+
+int adf_isr_resource_alloc(struct adf_accel_dev *accel_dev)
+{
+ int ret;
+
+ ret = adf_isr_alloc_msix_entry_table(accel_dev);
+ if (ret)
+ return ret;
+ if (adf_enable_msix(accel_dev))
+ goto err_out;
+
+ if (adf_setup_bh(accel_dev))
+ goto err_out;
+
+ if (adf_request_irqs(accel_dev))
+ goto err_out;
+
+ return 0;
+err_out:
+ adf_isr_resource_free(accel_dev);
+ return -EFAULT;
+}
diff --git a/drivers/crypto/qat/qat_dh895xcc/qat_admin.c b/drivers/crypto/qat/qat_dh895xcc/qat_admin.c
new file mode 100644
index 000000000000..55b7a8e48bad
--- /dev/null
+++ b/drivers/crypto/qat/qat_dh895xcc/qat_admin.c
@@ -0,0 +1,107 @@
+/*
+ This file is provided under a dual BSD/GPLv2 license. When using or
+ redistributing this file, you may do so under either license.
+
+ GPL LICENSE SUMMARY
+ Copyright(c) 2014 Intel Corporation.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Contact Information:
+ qat-linux@intel.com
+
+ BSD LICENSE
+ Copyright(c) 2014 Intel Corporation.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <icp_qat_fw_init_admin.h>
+#include <adf_accel_devices.h>
+#include <adf_common_drv.h>
+#include "adf_drv.h"
+
+static struct service_hndl qat_admin;
+
+static int qat_send_admin_cmd(struct adf_accel_dev *accel_dev, int cmd)
+{
+ struct adf_hw_device_data *hw_device = accel_dev->hw_device;
+ struct icp_qat_fw_init_admin_req req;
+ struct icp_qat_fw_init_admin_resp resp;
+ int i;
+
+ memset(&req, 0, sizeof(struct icp_qat_fw_init_admin_req));
+ req.init_admin_cmd_id = cmd;
+ for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
+ memset(&resp, 0, sizeof(struct icp_qat_fw_init_admin_resp));
+ if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
+ resp.init_resp_hdr.status)
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int qat_admin_start(struct adf_accel_dev *accel_dev)
+{
+ return qat_send_admin_cmd(accel_dev, ICP_QAT_FW_INIT_ME);
+}
+
+static int qat_admin_event_handler(struct adf_accel_dev *accel_dev,
+ enum adf_event event)
+{
+ int ret;
+
+ switch (event) {
+ case ADF_EVENT_START:
+ ret = qat_admin_start(accel_dev);
+ break;
+ case ADF_EVENT_STOP:
+ case ADF_EVENT_INIT:
+ case ADF_EVENT_SHUTDOWN:
+ default:
+ ret = 0;
+ }
+ return ret;
+}
+
+int qat_admin_register(void)
+{
+ memset(&qat_admin, 0, sizeof(struct service_hndl));
+ qat_admin.event_hld = qat_admin_event_handler;
+ qat_admin.name = "qat_admin";
+ qat_admin.admin = 1;
+ return adf_service_register(&qat_admin);
+}
+
+int qat_admin_unregister(void)
+{
+ return adf_service_unregister(&qat_admin);
+}
diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile
new file mode 100644
index 000000000000..348dc3173afa
--- /dev/null
+++ b/drivers/crypto/qce/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
+qcrypto-objs := core.o \
+ common.o \
+ dma.o \
+ sha.o \
+ ablkcipher.o
diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c
new file mode 100644
index 000000000000..ad592de475a4
--- /dev/null
+++ b/drivers/crypto/qce/ablkcipher.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+#include "cipher.h"
+
+static LIST_HEAD(ablkcipher_algs);
+
+static void qce_ablkcipher_done(void *data)
+{
+ struct crypto_async_request *async_req = data;
+ struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+ struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+ struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ enum dma_data_direction dir_src, dir_dst;
+ u32 status;
+ int error;
+ bool diff_dst;
+
+ diff_dst = (req->src != req->dst) ? true : false;
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
+
+ error = qce_dma_terminate_all(&qce->dma);
+ if (error)
+ dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n",
+ error);
+
+ if (diff_dst)
+ qce_unmapsg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src,
+ rctx->dst_chained);
+ qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+ rctx->dst_chained);
+
+ sg_free_table(&rctx->dst_tbl);
+
+ error = qce_check_status(qce, &status);
+ if (error < 0)
+ dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status);
+
+ qce->async_req_done(tmpl->qce, error);
+}
+
+static int
+qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
+{
+ struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+ struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+ struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+ struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ enum dma_data_direction dir_src, dir_dst;
+ struct scatterlist *sg;
+ bool diff_dst;
+ gfp_t gfp;
+ int ret;
+
+ rctx->iv = req->info;
+ rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ rctx->cryptlen = req->nbytes;
+
+ diff_dst = (req->src != req->dst) ? true : false;
+ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
+ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
+
+ rctx->src_nents = qce_countsg(req->src, req->nbytes,
+ &rctx->src_chained);
+ if (diff_dst) {
+ rctx->dst_nents = qce_countsg(req->dst, req->nbytes,
+ &rctx->dst_chained);
+ } else {
+ rctx->dst_nents = rctx->src_nents;
+ rctx->dst_chained = rctx->src_chained;
+ }
+
+ rctx->dst_nents += 1;
+
+ gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+ GFP_KERNEL : GFP_ATOMIC;
+
+ ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
+ if (ret)
+ return ret;
+
+ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
+
+ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst);
+ if (IS_ERR(sg)) {
+ ret = PTR_ERR(sg);
+ goto error_free;
+ }
+
+ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg);
+ if (IS_ERR(sg)) {
+ ret = PTR_ERR(sg);
+ goto error_free;
+ }
+
+ sg_mark_end(sg);
+ rctx->dst_sg = rctx->dst_tbl.sgl;
+
+ ret = qce_mapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+ rctx->dst_chained);
+ if (ret < 0)
+ goto error_free;
+
+ if (diff_dst) {
+ ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, dir_src,
+ rctx->src_chained);
+ if (ret < 0)
+ goto error_unmap_dst;
+ rctx->src_sg = req->src;
+ } else {
+ rctx->src_sg = rctx->dst_sg;
+ }
+
+ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
+ rctx->dst_sg, rctx->dst_nents,
+ qce_ablkcipher_done, async_req);
+ if (ret)
+ goto error_unmap_src;
+
+ qce_dma_issue_pending(&qce->dma);
+
+ ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0);
+ if (ret)
+ goto error_terminate;
+
+ return 0;
+
+error_terminate:
+ qce_dma_terminate_all(&qce->dma);
+error_unmap_src:
+ if (diff_dst)
+ qce_unmapsg(qce->dev, req->src, rctx->src_nents, dir_src,
+ rctx->src_chained);
+error_unmap_dst:
+ qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst,
+ rctx->dst_chained);
+error_free:
+ sg_free_table(&rctx->dst_tbl);
+ return ret;
+}
+
+static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk);
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ unsigned long flags = to_cipher_tmpl(tfm)->alg_flags;
+ int ret;
+
+ if (!key || !keylen)
+ return -EINVAL;
+
+ if (IS_AES(flags)) {
+ switch (keylen) {
+ case AES_KEYSIZE_128:
+ case AES_KEYSIZE_256:
+ break;
+ default:
+ goto fallback;
+ }
+ } else if (IS_DES(flags)) {
+ u32 tmp[DES_EXPKEY_WORDS];
+
+ ret = des_ekey(tmp, key);
+ if (!ret && crypto_ablkcipher_get_flags(ablk) &
+ CRYPTO_TFM_REQ_WEAK_KEY)
+ goto weakkey;
+ }
+
+ ctx->enc_keylen = keylen;
+ memcpy(ctx->enc_key, key, keylen);
+ return 0;
+fallback:
+ ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen);
+ if (!ret)
+ ctx->enc_keylen = keylen;
+ return ret;
+weakkey:
+ crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY);
+ return -EINVAL;
+}
+
+static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt)
+{
+ struct crypto_tfm *tfm =
+ crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
+ int ret;
+
+ rctx->flags = tmpl->alg_flags;
+ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
+
+ if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 &&
+ ctx->enc_keylen != AES_KEYSIZE_256) {
+ ablkcipher_request_set_tfm(req, ctx->fallback);
+ ret = encrypt ? crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
+ ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+ return ret;
+ }
+
+ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+ return qce_ablkcipher_crypt(req, 1);
+}
+
+static int qce_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+ return qce_ablkcipher_crypt(req, 0);
+}
+
+static int qce_ablkcipher_init(struct crypto_tfm *tfm)
+{
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ memset(ctx, 0, sizeof(*ctx));
+ tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx);
+
+ ctx->fallback = crypto_alloc_ablkcipher(crypto_tfm_alg_name(tfm),
+ CRYPTO_ALG_TYPE_ABLKCIPHER,
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK);
+ if (IS_ERR(ctx->fallback))
+ return PTR_ERR(ctx->fallback);
+
+ return 0;
+}
+
+static void qce_ablkcipher_exit(struct crypto_tfm *tfm)
+{
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_ablkcipher(ctx->fallback);
+}
+
+struct qce_ablkcipher_def {
+ unsigned long flags;
+ const char *name;
+ const char *drv_name;
+ unsigned int blocksize;
+ unsigned int ivsize;
+ unsigned int min_keysize;
+ unsigned int max_keysize;
+};
+
+static const struct qce_ablkcipher_def ablkcipher_def[] = {
+ {
+ .flags = QCE_ALG_AES | QCE_MODE_ECB,
+ .name = "ecb(aes)",
+ .drv_name = "ecb-aes-qce",
+ .blocksize = AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_AES | QCE_MODE_CBC,
+ .name = "cbc(aes)",
+ .drv_name = "cbc-aes-qce",
+ .blocksize = AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_AES | QCE_MODE_CTR,
+ .name = "ctr(aes)",
+ .drv_name = "ctr-aes-qce",
+ .blocksize = AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_AES | QCE_MODE_XTS,
+ .name = "xts(aes)",
+ .drv_name = "xts-aes-qce",
+ .blocksize = AES_BLOCK_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_DES | QCE_MODE_ECB,
+ .name = "ecb(des)",
+ .drv_name = "ecb-des-qce",
+ .blocksize = DES_BLOCK_SIZE,
+ .ivsize = 0,
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_DES | QCE_MODE_CBC,
+ .name = "cbc(des)",
+ .drv_name = "cbc-des-qce",
+ .blocksize = DES_BLOCK_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_3DES | QCE_MODE_ECB,
+ .name = "ecb(des3_ede)",
+ .drv_name = "ecb-3des-qce",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .ivsize = 0,
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ },
+ {
+ .flags = QCE_ALG_3DES | QCE_MODE_CBC,
+ .name = "cbc(des3_ede)",
+ .drv_name = "cbc-3des-qce",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ },
+};
+
+static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def,
+ struct qce_device *qce)
+{
+ struct qce_alg_template *tmpl;
+ struct crypto_alg *alg;
+ int ret;
+
+ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+ if (!tmpl)
+ return -ENOMEM;
+
+ alg = &tmpl->alg.crypto;
+
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ def->drv_name);
+
+ alg->cra_blocksize = def->blocksize;
+ alg->cra_ablkcipher.ivsize = def->ivsize;
+ alg->cra_ablkcipher.min_keysize = def->min_keysize;
+ alg->cra_ablkcipher.max_keysize = def->max_keysize;
+ alg->cra_ablkcipher.setkey = qce_ablkcipher_setkey;
+ alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt;
+ alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt;
+
+ alg->cra_priority = 300;
+ alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK;
+ alg->cra_ctxsize = sizeof(struct qce_cipher_ctx);
+ alg->cra_alignmask = 0;
+ alg->cra_type = &crypto_ablkcipher_type;
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = qce_ablkcipher_init;
+ alg->cra_exit = qce_ablkcipher_exit;
+ INIT_LIST_HEAD(&alg->cra_list);
+
+ INIT_LIST_HEAD(&tmpl->entry);
+ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER;
+ tmpl->alg_flags = def->flags;
+ tmpl->qce = qce;
+
+ ret = crypto_register_alg(alg);
+ if (ret) {
+ kfree(tmpl);
+ dev_err(qce->dev, "%s registration failed\n", alg->cra_name);
+ return ret;
+ }
+
+ list_add_tail(&tmpl->entry, &ablkcipher_algs);
+ dev_dbg(qce->dev, "%s is registered\n", alg->cra_name);
+ return 0;
+}
+
+static void qce_ablkcipher_unregister(struct qce_device *qce)
+{
+ struct qce_alg_template *tmpl, *n;
+
+ list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) {
+ crypto_unregister_alg(&tmpl->alg.crypto);
+ list_del(&tmpl->entry);
+ kfree(tmpl);
+ }
+}
+
+static int qce_ablkcipher_register(struct qce_device *qce)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) {
+ ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ qce_ablkcipher_unregister(qce);
+ return ret;
+}
+
+const struct qce_algo_ops ablkcipher_ops = {
+ .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
+ .register_algs = qce_ablkcipher_register,
+ .unregister_algs = qce_ablkcipher_unregister,
+ .async_req_handle = qce_ablkcipher_async_req_handle,
+};
diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h
new file mode 100644
index 000000000000..d5757cfcda2d
--- /dev/null
+++ b/drivers/crypto/qce/cipher.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CIPHER_H_
+#define _CIPHER_H_
+
+#include "common.h"
+#include "core.h"
+
+#define QCE_MAX_KEY_SIZE 64
+
+struct qce_cipher_ctx {
+ u8 enc_key[QCE_MAX_KEY_SIZE];
+ unsigned int enc_keylen;
+ struct crypto_ablkcipher *fallback;
+};
+
+/**
+ * struct qce_cipher_reqctx - holds private cipher objects per request
+ * @flags: operation flags
+ * @iv: pointer to the IV
+ * @ivsize: IV size
+ * @src_nents: source entries
+ * @dst_nents: destination entries
+ * @src_chained: is source chained
+ * @dst_chained: is destination chained
+ * @result_sg: scatterlist used for result buffer
+ * @dst_tbl: destination sg table
+ * @dst_sg: destination sg pointer table beginning
+ * @src_tbl: source sg table
+ * @src_sg: source sg pointer table beginning;
+ * @cryptlen: crypto length
+ */
+struct qce_cipher_reqctx {
+ unsigned long flags;
+ u8 *iv;
+ unsigned int ivsize;
+ int src_nents;
+ int dst_nents;
+ bool src_chained;
+ bool dst_chained;
+ struct scatterlist result_sg;
+ struct sg_table dst_tbl;
+ struct scatterlist *dst_sg;
+ struct sg_table src_tbl;
+ struct scatterlist *src_sg;
+ unsigned int cryptlen;
+};
+
+static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *alg = tfm->__crt_alg;
+ return container_of(alg, struct qce_alg_template, alg.crypto);
+}
+
+extern const struct qce_algo_ops ablkcipher_ops;
+
+#endif /* _CIPHER_H_ */
diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c
new file mode 100644
index 000000000000..1fb5fde7fc03
--- /dev/null
+++ b/drivers/crypto/qce/common.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/sha.h>
+
+#include "cipher.h"
+#include "common.h"
+#include "core.h"
+#include "regs-v5.h"
+#include "sha.h"
+
+#define QCE_SECTOR_SIZE 512
+
+static inline u32 qce_read(struct qce_device *qce, u32 offset)
+{
+ return readl(qce->base + offset);
+}
+
+static inline void qce_write(struct qce_device *qce, u32 offset, u32 val)
+{
+ writel(val, qce->base + offset);
+}
+
+static inline void qce_write_array(struct qce_device *qce, u32 offset,
+ const u32 *val, unsigned int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ qce_write(qce, offset + i * sizeof(u32), val[i]);
+}
+
+static inline void
+qce_clear_array(struct qce_device *qce, u32 offset, unsigned int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ qce_write(qce, offset + i * sizeof(u32), 0);
+}
+
+static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
+{
+ u32 cfg = 0;
+
+ if (IS_AES(flags)) {
+ if (aes_key_size == AES_KEYSIZE_128)
+ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
+ else if (aes_key_size == AES_KEYSIZE_256)
+ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
+ }
+
+ if (IS_AES(flags))
+ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
+ else if (IS_DES(flags) || IS_3DES(flags))
+ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
+
+ if (IS_DES(flags))
+ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
+
+ if (IS_3DES(flags))
+ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
+
+ switch (flags & QCE_MODE_MASK) {
+ case QCE_MODE_ECB:
+ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
+ break;
+ case QCE_MODE_CBC:
+ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
+ break;
+ case QCE_MODE_CTR:
+ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
+ break;
+ case QCE_MODE_XTS:
+ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
+ break;
+ case QCE_MODE_CCM:
+ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
+ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
+ break;
+ default:
+ return ~0;
+ }
+
+ return cfg;
+}
+
+static u32 qce_auth_cfg(unsigned long flags, u32 key_size)
+{
+ u32 cfg = 0;
+
+ if (IS_AES(flags) && (IS_CCM(flags) || IS_CMAC(flags)))
+ cfg |= AUTH_ALG_AES << AUTH_ALG_SHIFT;
+ else
+ cfg |= AUTH_ALG_SHA << AUTH_ALG_SHIFT;
+
+ if (IS_CCM(flags) || IS_CMAC(flags)) {
+ if (key_size == AES_KEYSIZE_128)
+ cfg |= AUTH_KEY_SZ_AES128 << AUTH_KEY_SIZE_SHIFT;
+ else if (key_size == AES_KEYSIZE_256)
+ cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT;
+ }
+
+ if (IS_SHA1(flags) || IS_SHA1_HMAC(flags))
+ cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT;
+ else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags))
+ cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT;
+ else if (IS_CMAC(flags))
+ cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT;
+
+ if (IS_SHA1(flags) || IS_SHA256(flags))
+ cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT;
+ else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags) ||
+ IS_CBC(flags) || IS_CTR(flags))
+ cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT;
+ else if (IS_AES(flags) && IS_CCM(flags))
+ cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT;
+ else if (IS_AES(flags) && IS_CMAC(flags))
+ cfg |= AUTH_MODE_CMAC << AUTH_MODE_SHIFT;
+
+ if (IS_SHA(flags) || IS_SHA_HMAC(flags))
+ cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT;
+
+ if (IS_CCM(flags))
+ cfg |= QCE_MAX_NONCE_WORDS << AUTH_NONCE_NUM_WORDS_SHIFT;
+
+ if (IS_CBC(flags) || IS_CTR(flags) || IS_CCM(flags) ||
+ IS_CMAC(flags))
+ cfg |= BIT(AUTH_LAST_SHIFT) | BIT(AUTH_FIRST_SHIFT);
+
+ return cfg;
+}
+
+static u32 qce_config_reg(struct qce_device *qce, int little)
+{
+ u32 beats = (qce->burst_size >> 3) - 1;
+ u32 pipe_pair = qce->pipe_pair_id;
+ u32 config;
+
+ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
+ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
+ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
+ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
+ config &= ~HIGH_SPD_EN_N_SHIFT;
+
+ if (little)
+ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
+
+ return config;
+}
+
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
+{
+ __be32 *d = dst;
+ const u8 *s = src;
+ unsigned int n;
+
+ n = len / sizeof(u32);
+ for (; n > 0; n--) {
+ *d = cpu_to_be32p((const __u32 *) s);
+ s += sizeof(__u32);
+ d++;
+ }
+}
+
+static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
+{
+ u8 swap[QCE_AES_IV_LENGTH];
+ u32 i, j;
+
+ if (ivsize > QCE_AES_IV_LENGTH)
+ return;
+
+ memset(swap, 0, QCE_AES_IV_LENGTH);
+
+ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1;
+ i < QCE_AES_IV_LENGTH; i++, j--)
+ swap[i] = src[j];
+
+ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
+}
+
+static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
+ unsigned int enckeylen, unsigned int cryptlen)
+{
+ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
+ unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
+ unsigned int xtsdusize;
+
+ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
+ enckeylen / 2);
+ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
+
+ /* xts du size 512B */
+ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen);
+ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize);
+}
+
+static void qce_setup_config(struct qce_device *qce)
+{
+ u32 config;
+
+ /* get big endianness */
+ config = qce_config_reg(qce, 0);
+
+ /* clear status */
+ qce_write(qce, REG_STATUS, 0);
+ qce_write(qce, REG_CONFIG, config);
+}
+
+static inline void qce_crypto_go(struct qce_device *qce)
+{
+ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
+}
+
+static int qce_setup_regs_ahash(struct crypto_async_request *async_req,
+ u32 totallen, u32 offset)
+{
+ struct ahash_request *req = ahash_request_cast(async_req);
+ struct crypto_ahash *ahash = __crypto_ahash_cast(async_req->tfm);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ unsigned int digestsize = crypto_ahash_digestsize(ahash);
+ unsigned int blocksize = crypto_tfm_alg_blocksize(async_req->tfm);
+ __be32 auth[SHA256_DIGEST_SIZE / sizeof(__be32)] = {0};
+ __be32 mackey[QCE_SHA_HMAC_KEY_SIZE / sizeof(__be32)] = {0};
+ u32 auth_cfg = 0, config;
+ unsigned int iv_words;
+
+ /* if not the last, the size has to be on the block boundary */
+ if (!rctx->last_blk && req->nbytes % blocksize)
+ return -EINVAL;
+
+ qce_setup_config(qce);
+
+ if (IS_CMAC(rctx->flags)) {
+ qce_write(qce, REG_AUTH_SEG_CFG, 0);
+ qce_write(qce, REG_ENCR_SEG_CFG, 0);
+ qce_write(qce, REG_ENCR_SEG_SIZE, 0);
+ qce_clear_array(qce, REG_AUTH_IV0, 16);
+ qce_clear_array(qce, REG_AUTH_KEY0, 16);
+ qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
+
+ auth_cfg = qce_auth_cfg(rctx->flags, rctx->authklen);
+ }
+
+ if (IS_SHA_HMAC(rctx->flags) || IS_CMAC(rctx->flags)) {
+ u32 authkey_words = rctx->authklen / sizeof(u32);
+
+ qce_cpu_to_be32p_array(mackey, rctx->authkey, rctx->authklen);
+ qce_write_array(qce, REG_AUTH_KEY0, (u32 *)mackey,
+ authkey_words);
+ }
+
+ if (IS_CMAC(rctx->flags))
+ goto go_proc;
+
+ if (rctx->first_blk)
+ memcpy(auth, rctx->digest, digestsize);
+ else
+ qce_cpu_to_be32p_array(auth, rctx->digest, digestsize);
+
+ iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8;
+ qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words);
+
+ if (rctx->first_blk)
+ qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
+ else
+ qce_write_array(qce, REG_AUTH_BYTECNT0,
+ (u32 *)rctx->byte_count, 2);
+
+ auth_cfg = qce_auth_cfg(rctx->flags, 0);
+
+ if (rctx->last_blk)
+ auth_cfg |= BIT(AUTH_LAST_SHIFT);
+ else
+ auth_cfg &= ~BIT(AUTH_LAST_SHIFT);
+
+ if (rctx->first_blk)
+ auth_cfg |= BIT(AUTH_FIRST_SHIFT);
+ else
+ auth_cfg &= ~BIT(AUTH_FIRST_SHIFT);
+
+go_proc:
+ qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
+ qce_write(qce, REG_AUTH_SEG_SIZE, req->nbytes);
+ qce_write(qce, REG_AUTH_SEG_START, 0);
+ qce_write(qce, REG_ENCR_SEG_CFG, 0);
+ qce_write(qce, REG_SEG_SIZE, req->nbytes);
+
+ /* get little endianness */
+ config = qce_config_reg(qce, 1);
+ qce_write(qce, REG_CONFIG, config);
+
+ qce_crypto_go(qce);
+
+ return 0;
+}
+
+static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req,
+ u32 totallen, u32 offset)
+{
+ struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+ struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req);
+ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
+ struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0};
+ __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0};
+ unsigned int enckey_words, enciv_words;
+ unsigned int keylen;
+ u32 encr_cfg = 0, auth_cfg = 0, config;
+ unsigned int ivsize = rctx->ivsize;
+ unsigned long flags = rctx->flags;
+
+ qce_setup_config(qce);
+
+ if (IS_XTS(flags))
+ keylen = ctx->enc_keylen / 2;
+ else
+ keylen = ctx->enc_keylen;
+
+ qce_cpu_to_be32p_array(enckey, ctx->enc_key, keylen);
+ enckey_words = keylen / sizeof(u32);
+
+ qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
+
+ encr_cfg = qce_encr_cfg(flags, keylen);
+
+ if (IS_DES(flags)) {
+ enciv_words = 2;
+ enckey_words = 2;
+ } else if (IS_3DES(flags)) {
+ enciv_words = 2;
+ enckey_words = 6;
+ } else if (IS_AES(flags)) {
+ if (IS_XTS(flags))
+ qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen,
+ rctx->cryptlen);
+ enciv_words = 4;
+ } else {
+ return -EINVAL;
+ }
+
+ qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words);
+
+ if (!IS_ECB(flags)) {
+ if (IS_XTS(flags))
+ qce_xts_swapiv(enciv, rctx->iv, ivsize);
+ else
+ qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize);
+
+ qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words);
+ }
+
+ if (IS_ENCRYPT(flags))
+ encr_cfg |= BIT(ENCODE_SHIFT);
+
+ qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg);
+ qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen);
+ qce_write(qce, REG_ENCR_SEG_START, offset & 0xffff);
+
+ if (IS_CTR(flags)) {
+ qce_write(qce, REG_CNTR_MASK, ~0);
+ qce_write(qce, REG_CNTR_MASK0, ~0);
+ qce_write(qce, REG_CNTR_MASK1, ~0);
+ qce_write(qce, REG_CNTR_MASK2, ~0);
+ }
+
+ qce_write(qce, REG_SEG_SIZE, totallen);
+
+ /* get little endianness */
+ config = qce_config_reg(qce, 1);
+ qce_write(qce, REG_CONFIG, config);
+
+ qce_crypto_go(qce);
+
+ return 0;
+}
+
+int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
+ u32 offset)
+{
+ switch (type) {
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ return qce_setup_regs_ablkcipher(async_req, totallen, offset);
+ case CRYPTO_ALG_TYPE_AHASH:
+ return qce_setup_regs_ahash(async_req, totallen, offset);
+ default:
+ return -EINVAL;
+ }
+}
+
+#define STATUS_ERRORS \
+ (BIT(SW_ERR_SHIFT) | BIT(AXI_ERR_SHIFT) | BIT(HSD_ERR_SHIFT))
+
+int qce_check_status(struct qce_device *qce, u32 *status)
+{
+ int ret = 0;
+
+ *status = qce_read(qce, REG_STATUS);
+
+ /*
+ * Don't use result dump status. The operation may not be complete.
+ * Instead, use the status we just read from device. In case, we need to
+ * use result_status from result dump the result_status needs to be byte
+ * swapped, since we set the device to little endian.
+ */
+ if (*status & STATUS_ERRORS || !(*status & BIT(OPERATION_DONE_SHIFT)))
+ ret = -ENXIO;
+
+ return ret;
+}
+
+void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step)
+{
+ u32 val;
+
+ val = qce_read(qce, REG_VERSION);
+ *major = (val & CORE_MAJOR_REV_MASK) >> CORE_MAJOR_REV_SHIFT;
+ *minor = (val & CORE_MINOR_REV_MASK) >> CORE_MINOR_REV_SHIFT;
+ *step = (val & CORE_STEP_REV_MASK) >> CORE_STEP_REV_SHIFT;
+}
diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h
new file mode 100644
index 000000000000..a4addd4f7d6c
--- /dev/null
+++ b/drivers/crypto/qce/common.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <linux/crypto.h>
+#include <linux/types.h>
+#include <crypto/aes.h>
+#include <crypto/hash.h>
+
+/* key size in bytes */
+#define QCE_SHA_HMAC_KEY_SIZE 64
+#define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256
+
+/* IV length in bytes */
+#define QCE_AES_IV_LENGTH AES_BLOCK_SIZE
+/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
+#define QCE_MAX_IV_SIZE AES_BLOCK_SIZE
+
+/* maximum nonce bytes */
+#define QCE_MAX_NONCE 16
+#define QCE_MAX_NONCE_WORDS (QCE_MAX_NONCE / sizeof(u32))
+
+/* burst size alignment requirement */
+#define QCE_MAX_ALIGN_SIZE 64
+
+/* cipher algorithms */
+#define QCE_ALG_DES BIT(0)
+#define QCE_ALG_3DES BIT(1)
+#define QCE_ALG_AES BIT(2)
+
+/* hash and hmac algorithms */
+#define QCE_HASH_SHA1 BIT(3)
+#define QCE_HASH_SHA256 BIT(4)
+#define QCE_HASH_SHA1_HMAC BIT(5)
+#define QCE_HASH_SHA256_HMAC BIT(6)
+#define QCE_HASH_AES_CMAC BIT(7)
+
+/* cipher modes */
+#define QCE_MODE_CBC BIT(8)
+#define QCE_MODE_ECB BIT(9)
+#define QCE_MODE_CTR BIT(10)
+#define QCE_MODE_XTS BIT(11)
+#define QCE_MODE_CCM BIT(12)
+#define QCE_MODE_MASK GENMASK(12, 8)
+
+/* cipher encryption/decryption operations */
+#define QCE_ENCRYPT BIT(13)
+#define QCE_DECRYPT BIT(14)
+
+#define IS_DES(flags) (flags & QCE_ALG_DES)
+#define IS_3DES(flags) (flags & QCE_ALG_3DES)
+#define IS_AES(flags) (flags & QCE_ALG_AES)
+
+#define IS_SHA1(flags) (flags & QCE_HASH_SHA1)
+#define IS_SHA256(flags) (flags & QCE_HASH_SHA256)
+#define IS_SHA1_HMAC(flags) (flags & QCE_HASH_SHA1_HMAC)
+#define IS_SHA256_HMAC(flags) (flags & QCE_HASH_SHA256_HMAC)
+#define IS_CMAC(flags) (flags & QCE_HASH_AES_CMAC)
+#define IS_SHA(flags) (IS_SHA1(flags) || IS_SHA256(flags))
+#define IS_SHA_HMAC(flags) \
+ (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags))
+
+#define IS_CBC(mode) (mode & QCE_MODE_CBC)
+#define IS_ECB(mode) (mode & QCE_MODE_ECB)
+#define IS_CTR(mode) (mode & QCE_MODE_CTR)
+#define IS_XTS(mode) (mode & QCE_MODE_XTS)
+#define IS_CCM(mode) (mode & QCE_MODE_CCM)
+
+#define IS_ENCRYPT(dir) (dir & QCE_ENCRYPT)
+#define IS_DECRYPT(dir) (dir & QCE_DECRYPT)
+
+struct qce_alg_template {
+ struct list_head entry;
+ u32 crypto_alg_type;
+ unsigned long alg_flags;
+ const u32 *std_iv;
+ union {
+ struct crypto_alg crypto;
+ struct ahash_alg ahash;
+ } alg;
+ struct qce_device *qce;
+};
+
+void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len);
+int qce_check_status(struct qce_device *qce, u32 *status);
+void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step);
+int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen,
+ u32 offset);
+
+#endif /* _COMMON_H_ */
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
new file mode 100644
index 000000000000..33ae3545dc48
--- /dev/null
+++ b/drivers/crypto/qce/core.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+
+#include "core.h"
+#include "cipher.h"
+#include "sha.h"
+
+#define QCE_MAJOR_VERSION5 0x05
+#define QCE_QUEUE_LENGTH 1
+
+static const struct qce_algo_ops *qce_ops[] = {
+ &ablkcipher_ops,
+ &ahash_ops,
+};
+
+static void qce_unregister_algs(struct qce_device *qce)
+{
+ const struct qce_algo_ops *ops;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ ops->unregister_algs(qce);
+ }
+}
+
+static int qce_register_algs(struct qce_device *qce)
+{
+ const struct qce_algo_ops *ops;
+ int i, ret = -ENODEV;
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ ret = ops->register_algs(qce);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int qce_handle_request(struct crypto_async_request *async_req)
+{
+ int ret = -EINVAL, i;
+ const struct qce_algo_ops *ops;
+ u32 type = crypto_tfm_alg_type(async_req->tfm);
+
+ for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
+ ops = qce_ops[i];
+ if (type != ops->type)
+ continue;
+ ret = ops->async_req_handle(async_req);
+ break;
+ }
+
+ return ret;
+}
+
+static int qce_handle_queue(struct qce_device *qce,
+ struct crypto_async_request *req)
+{
+ struct crypto_async_request *async_req, *backlog;
+ unsigned long flags;
+ int ret = 0, err;
+
+ spin_lock_irqsave(&qce->lock, flags);
+
+ if (req)
+ ret = crypto_enqueue_request(&qce->queue, req);
+
+ /* busy, do not dequeue request */
+ if (qce->req) {
+ spin_unlock_irqrestore(&qce->lock, flags);
+ return ret;
+ }
+
+ backlog = crypto_get_backlog(&qce->queue);
+ async_req = crypto_dequeue_request(&qce->queue);
+ if (async_req)
+ qce->req = async_req;
+
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ if (!async_req)
+ return ret;
+
+ if (backlog) {
+ spin_lock_bh(&qce->lock);
+ backlog->complete(backlog, -EINPROGRESS);
+ spin_unlock_bh(&qce->lock);
+ }
+
+ err = qce_handle_request(async_req);
+ if (err) {
+ qce->result = err;
+ tasklet_schedule(&qce->done_tasklet);
+ }
+
+ return ret;
+}
+
+static void qce_tasklet_req_done(unsigned long data)
+{
+ struct qce_device *qce = (struct qce_device *)data;
+ struct crypto_async_request *req;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qce->lock, flags);
+ req = qce->req;
+ qce->req = NULL;
+ spin_unlock_irqrestore(&qce->lock, flags);
+
+ if (req)
+ req->complete(req, qce->result);
+
+ qce_handle_queue(qce, NULL);
+}
+
+static int qce_async_request_enqueue(struct qce_device *qce,
+ struct crypto_async_request *req)
+{
+ return qce_handle_queue(qce, req);
+}
+
+static void qce_async_request_done(struct qce_device *qce, int ret)
+{
+ qce->result = ret;
+ tasklet_schedule(&qce->done_tasklet);
+}
+
+static int qce_check_version(struct qce_device *qce)
+{
+ u32 major, minor, step;
+
+ qce_get_version(qce, &major, &minor, &step);
+
+ /*
+ * the driver does not support v5 with minor 0 because it has special
+ * alignment requirements.
+ */
+ if (major != QCE_MAJOR_VERSION5 || minor == 0)
+ return -ENODEV;
+
+ qce->burst_size = QCE_BAM_BURST_SIZE;
+ qce->pipe_pair_id = 1;
+
+ dev_dbg(qce->dev, "Crypto device found, version %d.%d.%d\n",
+ major, minor, step);
+
+ return 0;
+}
+
+static int qce_crypto_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct qce_device *qce;
+ struct resource *res;
+ int ret;
+
+ qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL);
+ if (!qce)
+ return -ENOMEM;
+
+ qce->dev = dev;
+ platform_set_drvdata(pdev, qce);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ qce->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(qce->base))
+ return PTR_ERR(qce->base);
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret < 0)
+ return ret;
+
+ qce->core = devm_clk_get(qce->dev, "core");
+ if (IS_ERR(qce->core))
+ return PTR_ERR(qce->core);
+
+ qce->iface = devm_clk_get(qce->dev, "iface");
+ if (IS_ERR(qce->iface))
+ return PTR_ERR(qce->iface);
+
+ qce->bus = devm_clk_get(qce->dev, "bus");
+ if (IS_ERR(qce->bus))
+ return PTR_ERR(qce->bus);
+
+ ret = clk_prepare_enable(qce->core);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(qce->iface);
+ if (ret)
+ goto err_clks_core;
+
+ ret = clk_prepare_enable(qce->bus);
+ if (ret)
+ goto err_clks_iface;
+
+ ret = qce_dma_request(qce->dev, &qce->dma);
+ if (ret)
+ goto err_clks;
+
+ ret = qce_check_version(qce);
+ if (ret)
+ goto err_clks;
+
+ spin_lock_init(&qce->lock);
+ tasklet_init(&qce->done_tasklet, qce_tasklet_req_done,
+ (unsigned long)qce);
+ crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
+
+ qce->async_req_enqueue = qce_async_request_enqueue;
+ qce->async_req_done = qce_async_request_done;
+
+ ret = qce_register_algs(qce);
+ if (ret)
+ goto err_dma;
+
+ return 0;
+
+err_dma:
+ qce_dma_release(&qce->dma);
+err_clks:
+ clk_disable_unprepare(qce->bus);
+err_clks_iface:
+ clk_disable_unprepare(qce->iface);
+err_clks_core:
+ clk_disable_unprepare(qce->core);
+ return ret;
+}
+
+static int qce_crypto_remove(struct platform_device *pdev)
+{
+ struct qce_device *qce = platform_get_drvdata(pdev);
+
+ tasklet_kill(&qce->done_tasklet);
+ qce_unregister_algs(qce);
+ qce_dma_release(&qce->dma);
+ clk_disable_unprepare(qce->bus);
+ clk_disable_unprepare(qce->iface);
+ clk_disable_unprepare(qce->core);
+ return 0;
+}
+
+static const struct of_device_id qce_crypto_of_match[] = {
+ { .compatible = "qcom,crypto-v5.1", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
+
+static struct platform_driver qce_crypto_driver = {
+ .probe = qce_crypto_probe,
+ .remove = qce_crypto_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .of_match_table = qce_crypto_of_match,
+ },
+};
+module_platform_driver(qce_crypto_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm crypto engine driver");
+MODULE_ALIAS("platform:" KBUILD_MODNAME);
+MODULE_AUTHOR("The Linux Foundation");
diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h
new file mode 100644
index 000000000000..549965d4d91f
--- /dev/null
+++ b/drivers/crypto/qce/core.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CORE_H_
+#define _CORE_H_
+
+#include "dma.h"
+
+/**
+ * struct qce_device - crypto engine device structure
+ * @queue: crypto request queue
+ * @lock: the lock protects queue and req
+ * @done_tasklet: done tasklet object
+ * @req: current active request
+ * @result: result of current transform
+ * @base: virtual IO base
+ * @dev: pointer to device structure
+ * @core: core device clock
+ * @iface: interface clock
+ * @bus: bus clock
+ * @dma: pointer to dma data
+ * @burst_size: the crypto burst size
+ * @pipe_pair_id: which pipe pair id the device using
+ * @async_req_enqueue: invoked by every algorithm to enqueue a request
+ * @async_req_done: invoked by every algorithm to finish its request
+ */
+struct qce_device {
+ struct crypto_queue queue;
+ spinlock_t lock;
+ struct tasklet_struct done_tasklet;
+ struct crypto_async_request *req;
+ int result;
+ void __iomem *base;
+ struct device *dev;
+ struct clk *core, *iface, *bus;
+ struct qce_dma_data dma;
+ int burst_size;
+ unsigned int pipe_pair_id;
+ int (*async_req_enqueue)(struct qce_device *qce,
+ struct crypto_async_request *req);
+ void (*async_req_done)(struct qce_device *qce, int ret);
+};
+
+/**
+ * struct qce_algo_ops - algorithm operations per crypto type
+ * @type: should be CRYPTO_ALG_TYPE_XXX
+ * @register_algs: invoked by core to register the algorithms
+ * @unregister_algs: invoked by core to unregister the algorithms
+ * @async_req_handle: invoked by core to handle enqueued request
+ */
+struct qce_algo_ops {
+ u32 type;
+ int (*register_algs)(struct qce_device *qce);
+ void (*unregister_algs)(struct qce_device *qce);
+ int (*async_req_handle)(struct crypto_async_request *async_req);
+};
+
+#endif /* _CORE_H_ */
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
new file mode 100644
index 000000000000..0fb21e13f247
--- /dev/null
+++ b/drivers/crypto/qce/dma.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/dmaengine.h>
+#include <crypto/scatterwalk.h>
+
+#include "dma.h"
+
+int qce_dma_request(struct device *dev, struct qce_dma_data *dma)
+{
+ int ret;
+
+ dma->txchan = dma_request_slave_channel_reason(dev, "tx");
+ if (IS_ERR(dma->txchan))
+ return PTR_ERR(dma->txchan);
+
+ dma->rxchan = dma_request_slave_channel_reason(dev, "rx");
+ if (IS_ERR(dma->rxchan)) {
+ ret = PTR_ERR(dma->rxchan);
+ goto error_rx;
+ }
+
+ dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ,
+ GFP_KERNEL);
+ if (!dma->result_buf) {
+ ret = -ENOMEM;
+ goto error_nomem;
+ }
+
+ dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ;
+
+ return 0;
+error_nomem:
+ dma_release_channel(dma->rxchan);
+error_rx:
+ dma_release_channel(dma->txchan);
+ return ret;
+}
+
+void qce_dma_release(struct qce_dma_data *dma)
+{
+ dma_release_channel(dma->txchan);
+ dma_release_channel(dma->rxchan);
+ kfree(dma->result_buf);
+}
+
+int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, bool chained)
+{
+ int err;
+
+ if (chained) {
+ while (sg) {
+ err = dma_map_sg(dev, sg, 1, dir);
+ if (!err)
+ return -EFAULT;
+ sg = scatterwalk_sg_next(sg);
+ }
+ } else {
+ err = dma_map_sg(dev, sg, nents, dir);
+ if (!err)
+ return -EFAULT;
+ }
+
+ return nents;
+}
+
+void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, bool chained)
+{
+ if (chained)
+ while (sg) {
+ dma_unmap_sg(dev, sg, 1, dir);
+ sg = scatterwalk_sg_next(sg);
+ }
+ else
+ dma_unmap_sg(dev, sg, nents, dir);
+}
+
+int qce_countsg(struct scatterlist *sglist, int nbytes, bool *chained)
+{
+ struct scatterlist *sg = sglist;
+ int nents = 0;
+
+ if (chained)
+ *chained = false;
+
+ while (nbytes > 0 && sg) {
+ nents++;
+ nbytes -= sg->length;
+ if (!sg_is_last(sg) && (sg + 1)->length == 0 && chained)
+ *chained = true;
+ sg = scatterwalk_sg_next(sg);
+ }
+
+ return nents;
+}
+
+struct scatterlist *
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl)
+{
+ struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
+
+ while (sg) {
+ if (!sg_page(sg))
+ break;
+ sg = sg_next(sg);
+ }
+
+ if (!sg)
+ return ERR_PTR(-EINVAL);
+
+ while (new_sgl && sg) {
+ sg_set_page(sg, sg_page(new_sgl), new_sgl->length,
+ new_sgl->offset);
+ sg_last = sg;
+ sg = sg_next(sg);
+ new_sgl = sg_next(new_sgl);
+ }
+
+ return sg_last;
+}
+
+static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg,
+ int nents, unsigned long flags,
+ enum dma_transfer_direction dir,
+ dma_async_tx_callback cb, void *cb_param)
+{
+ struct dma_async_tx_descriptor *desc;
+ dma_cookie_t cookie;
+
+ if (!sg || !nents)
+ return -EINVAL;
+
+ desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags);
+ if (!desc)
+ return -EINVAL;
+
+ desc->callback = cb;
+ desc->callback_param = cb_param;
+ cookie = dmaengine_submit(desc);
+
+ return dma_submit_error(cookie);
+}
+
+int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg,
+ int rx_nents, struct scatterlist *tx_sg, int tx_nents,
+ dma_async_tx_callback cb, void *cb_param)
+{
+ struct dma_chan *rxchan = dma->rxchan;
+ struct dma_chan *txchan = dma->txchan;
+ unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+ int ret;
+
+ ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV,
+ NULL, NULL);
+ if (ret)
+ return ret;
+
+ return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM,
+ cb, cb_param);
+}
+
+void qce_dma_issue_pending(struct qce_dma_data *dma)
+{
+ dma_async_issue_pending(dma->rxchan);
+ dma_async_issue_pending(dma->txchan);
+}
+
+int qce_dma_terminate_all(struct qce_dma_data *dma)
+{
+ int ret;
+
+ ret = dmaengine_terminate_all(dma->rxchan);
+ return ret ?: dmaengine_terminate_all(dma->txchan);
+}
diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h
new file mode 100644
index 000000000000..805e378d59e9
--- /dev/null
+++ b/drivers/crypto/qce/dma.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DMA_H_
+#define _DMA_H_
+
+/* maximum data transfer block size between BAM and CE */
+#define QCE_BAM_BURST_SIZE 64
+
+#define QCE_AUTHIV_REGS_CNT 16
+#define QCE_AUTH_BYTECOUNT_REGS_CNT 4
+#define QCE_CNTRIV_REGS_CNT 4
+
+struct qce_result_dump {
+ u32 auth_iv[QCE_AUTHIV_REGS_CNT];
+ u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT];
+ u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT];
+ u32 status;
+ u32 status2;
+};
+
+#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
+#define QCE_RESULT_BUF_SZ \
+ ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE)
+
+struct qce_dma_data {
+ struct dma_chan *txchan;
+ struct dma_chan *rxchan;
+ struct qce_result_dump *result_buf;
+ void *ignore_buf;
+};
+
+int qce_dma_request(struct device *dev, struct qce_dma_data *dma);
+void qce_dma_release(struct qce_dma_data *dma);
+int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in,
+ int in_ents, struct scatterlist *sg_out, int out_ents,
+ dma_async_tx_callback cb, void *cb_param);
+void qce_dma_issue_pending(struct qce_dma_data *dma);
+int qce_dma_terminate_all(struct qce_dma_data *dma);
+int qce_countsg(struct scatterlist *sg_list, int nbytes, bool *chained);
+void qce_unmapsg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, bool chained);
+int qce_mapsg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, bool chained);
+struct scatterlist *
+qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add);
+
+#endif /* _DMA_H_ */
diff --git a/drivers/crypto/qce/regs-v5.h b/drivers/crypto/qce/regs-v5.h
new file mode 100644
index 000000000000..f0e19e35664a
--- /dev/null
+++ b/drivers/crypto/qce/regs-v5.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _REGS_V5_H_
+#define _REGS_V5_H_
+
+#include <linux/bitops.h>
+
+#define REG_VERSION 0x000
+#define REG_STATUS 0x100
+#define REG_STATUS2 0x104
+#define REG_ENGINES_AVAIL 0x108
+#define REG_FIFO_SIZES 0x10c
+#define REG_SEG_SIZE 0x110
+#define REG_GOPROC 0x120
+#define REG_ENCR_SEG_CFG 0x200
+#define REG_ENCR_SEG_SIZE 0x204
+#define REG_ENCR_SEG_START 0x208
+#define REG_CNTR0_IV0 0x20c
+#define REG_CNTR1_IV1 0x210
+#define REG_CNTR2_IV2 0x214
+#define REG_CNTR3_IV3 0x218
+#define REG_CNTR_MASK 0x21C
+#define REG_ENCR_CCM_INT_CNTR0 0x220
+#define REG_ENCR_CCM_INT_CNTR1 0x224
+#define REG_ENCR_CCM_INT_CNTR2 0x228
+#define REG_ENCR_CCM_INT_CNTR3 0x22c
+#define REG_ENCR_XTS_DU_SIZE 0x230
+#define REG_CNTR_MASK2 0x234
+#define REG_CNTR_MASK1 0x238
+#define REG_CNTR_MASK0 0x23c
+#define REG_AUTH_SEG_CFG 0x300
+#define REG_AUTH_SEG_SIZE 0x304
+#define REG_AUTH_SEG_START 0x308
+#define REG_AUTH_IV0 0x310
+#define REG_AUTH_IV1 0x314
+#define REG_AUTH_IV2 0x318
+#define REG_AUTH_IV3 0x31c
+#define REG_AUTH_IV4 0x320
+#define REG_AUTH_IV5 0x324
+#define REG_AUTH_IV6 0x328
+#define REG_AUTH_IV7 0x32c
+#define REG_AUTH_IV8 0x330
+#define REG_AUTH_IV9 0x334
+#define REG_AUTH_IV10 0x338
+#define REG_AUTH_IV11 0x33c
+#define REG_AUTH_IV12 0x340
+#define REG_AUTH_IV13 0x344
+#define REG_AUTH_IV14 0x348
+#define REG_AUTH_IV15 0x34c
+#define REG_AUTH_INFO_NONCE0 0x350
+#define REG_AUTH_INFO_NONCE1 0x354
+#define REG_AUTH_INFO_NONCE2 0x358
+#define REG_AUTH_INFO_NONCE3 0x35c
+#define REG_AUTH_BYTECNT0 0x390
+#define REG_AUTH_BYTECNT1 0x394
+#define REG_AUTH_BYTECNT2 0x398
+#define REG_AUTH_BYTECNT3 0x39c
+#define REG_AUTH_EXP_MAC0 0x3a0
+#define REG_AUTH_EXP_MAC1 0x3a4
+#define REG_AUTH_EXP_MAC2 0x3a8
+#define REG_AUTH_EXP_MAC3 0x3ac
+#define REG_AUTH_EXP_MAC4 0x3b0
+#define REG_AUTH_EXP_MAC5 0x3b4
+#define REG_AUTH_EXP_MAC6 0x3b8
+#define REG_AUTH_EXP_MAC7 0x3bc
+#define REG_CONFIG 0x400
+#define REG_GOPROC_QC_KEY 0x1000
+#define REG_GOPROC_OEM_KEY 0x2000
+#define REG_ENCR_KEY0 0x3000
+#define REG_ENCR_KEY1 0x3004
+#define REG_ENCR_KEY2 0x3008
+#define REG_ENCR_KEY3 0x300c
+#define REG_ENCR_KEY4 0x3010
+#define REG_ENCR_KEY5 0x3014
+#define REG_ENCR_KEY6 0x3018
+#define REG_ENCR_KEY7 0x301c
+#define REG_ENCR_XTS_KEY0 0x3020
+#define REG_ENCR_XTS_KEY1 0x3024
+#define REG_ENCR_XTS_KEY2 0x3028
+#define REG_ENCR_XTS_KEY3 0x302c
+#define REG_ENCR_XTS_KEY4 0x3030
+#define REG_ENCR_XTS_KEY5 0x3034
+#define REG_ENCR_XTS_KEY6 0x3038
+#define REG_ENCR_XTS_KEY7 0x303c
+#define REG_AUTH_KEY0 0x3040
+#define REG_AUTH_KEY1 0x3044
+#define REG_AUTH_KEY2 0x3048
+#define REG_AUTH_KEY3 0x304c
+#define REG_AUTH_KEY4 0x3050
+#define REG_AUTH_KEY5 0x3054
+#define REG_AUTH_KEY6 0x3058
+#define REG_AUTH_KEY7 0x305c
+#define REG_AUTH_KEY8 0x3060
+#define REG_AUTH_KEY9 0x3064
+#define REG_AUTH_KEY10 0x3068
+#define REG_AUTH_KEY11 0x306c
+#define REG_AUTH_KEY12 0x3070
+#define REG_AUTH_KEY13 0x3074
+#define REG_AUTH_KEY14 0x3078
+#define REG_AUTH_KEY15 0x307c
+
+/* Register bits - REG_VERSION */
+#define CORE_STEP_REV_SHIFT 0
+#define CORE_STEP_REV_MASK GENMASK(15, 0)
+#define CORE_MINOR_REV_SHIFT 16
+#define CORE_MINOR_REV_MASK GENMASK(23, 16)
+#define CORE_MAJOR_REV_SHIFT 24
+#define CORE_MAJOR_REV_MASK GENMASK(31, 24)
+
+/* Register bits - REG_STATUS */
+#define MAC_FAILED_SHIFT 31
+#define DOUT_SIZE_AVAIL_SHIFT 26
+#define DOUT_SIZE_AVAIL_MASK GENMASK(30, 26)
+#define DIN_SIZE_AVAIL_SHIFT 21
+#define DIN_SIZE_AVAIL_MASK GENMASK(25, 21)
+#define HSD_ERR_SHIFT 20
+#define ACCESS_VIOL_SHIFT 19
+#define PIPE_ACTIVE_ERR_SHIFT 18
+#define CFG_CHNG_ERR_SHIFT 17
+#define DOUT_ERR_SHIFT 16
+#define DIN_ERR_SHIFT 15
+#define AXI_ERR_SHIFT 14
+#define CRYPTO_STATE_SHIFT 10
+#define CRYPTO_STATE_MASK GENMASK(13, 10)
+#define ENCR_BUSY_SHIFT 9
+#define AUTH_BUSY_SHIFT 8
+#define DOUT_INTR_SHIFT 7
+#define DIN_INTR_SHIFT 6
+#define OP_DONE_INTR_SHIFT 5
+#define ERR_INTR_SHIFT 4
+#define DOUT_RDY_SHIFT 3
+#define DIN_RDY_SHIFT 2
+#define OPERATION_DONE_SHIFT 1
+#define SW_ERR_SHIFT 0
+
+/* Register bits - REG_STATUS2 */
+#define AXI_EXTRA_SHIFT 1
+#define LOCKED_SHIFT 2
+
+/* Register bits - REG_CONFIG */
+#define REQ_SIZE_SHIFT 17
+#define REQ_SIZE_MASK GENMASK(20, 17)
+#define REQ_SIZE_ENUM_1_BEAT 0
+#define REQ_SIZE_ENUM_2_BEAT 1
+#define REQ_SIZE_ENUM_3_BEAT 2
+#define REQ_SIZE_ENUM_4_BEAT 3
+#define REQ_SIZE_ENUM_5_BEAT 4
+#define REQ_SIZE_ENUM_6_BEAT 5
+#define REQ_SIZE_ENUM_7_BEAT 6
+#define REQ_SIZE_ENUM_8_BEAT 7
+#define REQ_SIZE_ENUM_9_BEAT 8
+#define REQ_SIZE_ENUM_10_BEAT 9
+#define REQ_SIZE_ENUM_11_BEAT 10
+#define REQ_SIZE_ENUM_12_BEAT 11
+#define REQ_SIZE_ENUM_13_BEAT 12
+#define REQ_SIZE_ENUM_14_BEAT 13
+#define REQ_SIZE_ENUM_15_BEAT 14
+#define REQ_SIZE_ENUM_16_BEAT 15
+
+#define MAX_QUEUED_REQ_SHIFT 14
+#define MAX_QUEUED_REQ_MASK GENMASK(24, 16)
+#define ENUM_1_QUEUED_REQS 0
+#define ENUM_2_QUEUED_REQS 1
+#define ENUM_3_QUEUED_REQS 2
+
+#define IRQ_ENABLES_SHIFT 10
+#define IRQ_ENABLES_MASK GENMASK(13, 10)
+
+#define LITTLE_ENDIAN_MODE_SHIFT 9
+#define PIPE_SET_SELECT_SHIFT 5
+#define PIPE_SET_SELECT_MASK GENMASK(8, 5)
+
+#define HIGH_SPD_EN_N_SHIFT 4
+#define MASK_DOUT_INTR_SHIFT 3
+#define MASK_DIN_INTR_SHIFT 2
+#define MASK_OP_DONE_INTR_SHIFT 1
+#define MASK_ERR_INTR_SHIFT 0
+
+/* Register bits - REG_AUTH_SEG_CFG */
+#define COMP_EXP_MAC_SHIFT 24
+#define COMP_EXP_MAC_DISABLED 0
+#define COMP_EXP_MAC_ENABLED 1
+
+#define F9_DIRECTION_SHIFT 23
+#define F9_DIRECTION_UPLINK 0
+#define F9_DIRECTION_DOWNLINK 1
+
+#define AUTH_NONCE_NUM_WORDS_SHIFT 20
+#define AUTH_NONCE_NUM_WORDS_MASK GENMASK(22, 20)
+
+#define USE_PIPE_KEY_AUTH_SHIFT 19
+#define USE_HW_KEY_AUTH_SHIFT 18
+#define AUTH_FIRST_SHIFT 17
+#define AUTH_LAST_SHIFT 16
+
+#define AUTH_POS_SHIFT 14
+#define AUTH_POS_MASK GENMASK(15, 14)
+#define AUTH_POS_BEFORE 0
+#define AUTH_POS_AFTER 1
+
+#define AUTH_SIZE_SHIFT 9
+#define AUTH_SIZE_MASK GENMASK(13, 9)
+#define AUTH_SIZE_SHA1 0
+#define AUTH_SIZE_SHA256 1
+#define AUTH_SIZE_ENUM_1_BYTES 0
+#define AUTH_SIZE_ENUM_2_BYTES 1
+#define AUTH_SIZE_ENUM_3_BYTES 2
+#define AUTH_SIZE_ENUM_4_BYTES 3
+#define AUTH_SIZE_ENUM_5_BYTES 4
+#define AUTH_SIZE_ENUM_6_BYTES 5
+#define AUTH_SIZE_ENUM_7_BYTES 6
+#define AUTH_SIZE_ENUM_8_BYTES 7
+#define AUTH_SIZE_ENUM_9_BYTES 8
+#define AUTH_SIZE_ENUM_10_BYTES 9
+#define AUTH_SIZE_ENUM_11_BYTES 10
+#define AUTH_SIZE_ENUM_12_BYTES 11
+#define AUTH_SIZE_ENUM_13_BYTES 12
+#define AUTH_SIZE_ENUM_14_BYTES 13
+#define AUTH_SIZE_ENUM_15_BYTES 14
+#define AUTH_SIZE_ENUM_16_BYTES 15
+
+#define AUTH_MODE_SHIFT 6
+#define AUTH_MODE_MASK GENMASK(8, 6)
+#define AUTH_MODE_HASH 0
+#define AUTH_MODE_HMAC 1
+#define AUTH_MODE_CCM 0
+#define AUTH_MODE_CMAC 1
+
+#define AUTH_KEY_SIZE_SHIFT 3
+#define AUTH_KEY_SIZE_MASK GENMASK(5, 3)
+#define AUTH_KEY_SZ_AES128 0
+#define AUTH_KEY_SZ_AES256 2
+
+#define AUTH_ALG_SHIFT 0
+#define AUTH_ALG_MASK GENMASK(2, 0)
+#define AUTH_ALG_NONE 0
+#define AUTH_ALG_SHA 1
+#define AUTH_ALG_AES 2
+#define AUTH_ALG_KASUMI 3
+#define AUTH_ALG_SNOW3G 4
+#define AUTH_ALG_ZUC 5
+
+/* Register bits - REG_ENCR_XTS_DU_SIZE */
+#define ENCR_XTS_DU_SIZE_SHIFT 0
+#define ENCR_XTS_DU_SIZE_MASK GENMASK(19, 0)
+
+/* Register bits - REG_ENCR_SEG_CFG */
+#define F8_KEYSTREAM_ENABLE_SHIFT 17
+#define F8_KEYSTREAM_DISABLED 0
+#define F8_KEYSTREAM_ENABLED 1
+
+#define F8_DIRECTION_SHIFT 16
+#define F8_DIRECTION_UPLINK 0
+#define F8_DIRECTION_DOWNLINK 1
+
+#define USE_PIPE_KEY_ENCR_SHIFT 15
+#define USE_PIPE_KEY_ENCR_ENABLED 1
+#define USE_KEY_REGISTERS 0
+
+#define USE_HW_KEY_ENCR_SHIFT 14
+#define USE_KEY_REG 0
+#define USE_HW_KEY 1
+
+#define LAST_CCM_SHIFT 13
+#define LAST_CCM_XFR 1
+#define INTERM_CCM_XFR 0
+
+#define CNTR_ALG_SHIFT 11
+#define CNTR_ALG_MASK GENMASK(12, 11)
+#define CNTR_ALG_NIST 0
+
+#define ENCODE_SHIFT 10
+
+#define ENCR_MODE_SHIFT 6
+#define ENCR_MODE_MASK GENMASK(9, 6)
+#define ENCR_MODE_ECB 0
+#define ENCR_MODE_CBC 1
+#define ENCR_MODE_CTR 2
+#define ENCR_MODE_XTS 3
+#define ENCR_MODE_CCM 4
+
+#define ENCR_KEY_SZ_SHIFT 3
+#define ENCR_KEY_SZ_MASK GENMASK(5, 3)
+#define ENCR_KEY_SZ_DES 0
+#define ENCR_KEY_SZ_3DES 1
+#define ENCR_KEY_SZ_AES128 0
+#define ENCR_KEY_SZ_AES256 2
+
+#define ENCR_ALG_SHIFT 0
+#define ENCR_ALG_MASK GENMASK(2, 0)
+#define ENCR_ALG_NONE 0
+#define ENCR_ALG_DES 1
+#define ENCR_ALG_AES 2
+#define ENCR_ALG_KASUMI 4
+#define ENCR_ALG_SNOW_3G 5
+#define ENCR_ALG_ZUC 6
+
+/* Register bits - REG_GOPROC */
+#define GO_SHIFT 0
+#define CLR_CNTXT_SHIFT 1
+#define RESULTS_DUMP_SHIFT 2
+
+/* Register bits - REG_ENGINES_AVAIL */
+#define ENCR_AES_SEL_SHIFT 0
+#define DES_SEL_SHIFT 1
+#define ENCR_SNOW3G_SEL_SHIFT 2
+#define ENCR_KASUMI_SEL_SHIFT 3
+#define SHA_SEL_SHIFT 4
+#define SHA512_SEL_SHIFT 5
+#define AUTH_AES_SEL_SHIFT 6
+#define AUTH_SNOW3G_SEL_SHIFT 7
+#define AUTH_KASUMI_SEL_SHIFT 8
+#define BAM_PIPE_SETS_SHIFT 9
+#define BAM_PIPE_SETS_MASK GENMASK(12, 9)
+#define AXI_WR_BEATS_SHIFT 13
+#define AXI_WR_BEATS_MASK GENMASK(18, 13)
+#define AXI_RD_BEATS_SHIFT 19
+#define AXI_RD_BEATS_MASK GENMASK(24, 19)
+#define ENCR_ZUC_SEL_SHIFT 26
+#define AUTH_ZUC_SEL_SHIFT 27
+#define ZUC_ENABLE_SHIFT 28
+
+#endif /* _REGS_V5_H_ */
diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c
new file mode 100644
index 000000000000..f3385934eed2
--- /dev/null
+++ b/drivers/crypto/qce/sha.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <crypto/internal/hash.h>
+
+#include "common.h"
+#include "core.h"
+#include "sha.h"
+
+/* crypto hw padding constant for first operation */
+#define SHA_PADDING 64
+#define SHA_PADDING_MASK (SHA_PADDING - 1)
+
+static LIST_HEAD(ahash_algs);
+
+static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = {
+ SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0
+};
+
+static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = {
+ SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
+ SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7
+};
+
+static void qce_ahash_done(void *data)
+{
+ struct crypto_async_request *async_req = data;
+ struct ahash_request *req = ahash_request_cast(async_req);
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ struct qce_result_dump *result = qce->dma.result_buf;
+ unsigned int digestsize = crypto_ahash_digestsize(ahash);
+ int error;
+ u32 status;
+
+ error = qce_dma_terminate_all(&qce->dma);
+ if (error)
+ dev_dbg(qce->dev, "ahash dma termination error (%d)\n", error);
+
+ qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+ rctx->src_chained);
+ qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+
+ memcpy(rctx->digest, result->auth_iv, digestsize);
+ if (req->result)
+ memcpy(req->result, result->auth_iv, digestsize);
+
+ rctx->byte_count[0] = cpu_to_be32(result->auth_byte_count[0]);
+ rctx->byte_count[1] = cpu_to_be32(result->auth_byte_count[1]);
+
+ error = qce_check_status(qce, &status);
+ if (error < 0)
+ dev_dbg(qce->dev, "ahash operation error (%x)\n", status);
+
+ req->src = rctx->src_orig;
+ req->nbytes = rctx->nbytes_orig;
+ rctx->last_blk = false;
+ rctx->first_blk = false;
+
+ qce->async_req_done(tmpl->qce, error);
+}
+
+static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
+{
+ struct ahash_request *req = ahash_request_cast(async_req);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_sha_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
+ struct qce_device *qce = tmpl->qce;
+ unsigned long flags = rctx->flags;
+ int ret;
+
+ if (IS_SHA_HMAC(flags)) {
+ rctx->authkey = ctx->authkey;
+ rctx->authklen = QCE_SHA_HMAC_KEY_SIZE;
+ } else if (IS_CMAC(flags)) {
+ rctx->authkey = ctx->authkey;
+ rctx->authklen = AES_KEYSIZE_128;
+ }
+
+ rctx->src_nents = qce_countsg(req->src, req->nbytes,
+ &rctx->src_chained);
+ ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+ rctx->src_chained);
+ if (ret < 0)
+ return ret;
+
+ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
+
+ ret = qce_mapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+ if (ret < 0)
+ goto error_unmap_src;
+
+ ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents,
+ &rctx->result_sg, 1, qce_ahash_done, async_req);
+ if (ret)
+ goto error_unmap_dst;
+
+ qce_dma_issue_pending(&qce->dma);
+
+ ret = qce_start(async_req, tmpl->crypto_alg_type, 0, 0);
+ if (ret)
+ goto error_terminate;
+
+ return 0;
+
+error_terminate:
+ qce_dma_terminate_all(&qce->dma);
+error_unmap_dst:
+ qce_unmapsg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE, 0);
+error_unmap_src:
+ qce_unmapsg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE,
+ rctx->src_chained);
+ return ret;
+}
+
+static int qce_ahash_init(struct ahash_request *req)
+{
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+ const u32 *std_iv = tmpl->std_iv;
+
+ memset(rctx, 0, sizeof(*rctx));
+ rctx->first_blk = true;
+ rctx->last_blk = false;
+ rctx->flags = tmpl->alg_flags;
+ memcpy(rctx->digest, std_iv, sizeof(rctx->digest));
+
+ return 0;
+}
+
+static int qce_ahash_export(struct ahash_request *req, void *out)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ unsigned long flags = rctx->flags;
+ unsigned int digestsize = crypto_ahash_digestsize(ahash);
+ unsigned int blocksize =
+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
+
+ if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
+ struct sha1_state *out_state = out;
+
+ out_state->count = rctx->count;
+ qce_cpu_to_be32p_array((__be32 *)out_state->state,
+ rctx->digest, digestsize);
+ memcpy(out_state->buffer, rctx->buf, blocksize);
+ } else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
+ struct sha256_state *out_state = out;
+
+ out_state->count = rctx->count;
+ qce_cpu_to_be32p_array((__be32 *)out_state->state,
+ rctx->digest, digestsize);
+ memcpy(out_state->buf, rctx->buf, blocksize);
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int qce_import_common(struct ahash_request *req, u64 in_count,
+ const u32 *state, const u8 *buffer, bool hmac)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ unsigned int digestsize = crypto_ahash_digestsize(ahash);
+ unsigned int blocksize;
+ u64 count = in_count;
+
+ blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(ahash));
+ rctx->count = in_count;
+ memcpy(rctx->buf, buffer, blocksize);
+
+ if (in_count <= blocksize) {
+ rctx->first_blk = 1;
+ } else {
+ rctx->first_blk = 0;
+ /*
+ * For HMAC, there is a hardware padding done when first block
+ * is set. Therefore the byte_count must be incremened by 64
+ * after the first block operation.
+ */
+ if (hmac)
+ count += SHA_PADDING;
+ }
+
+ rctx->byte_count[0] = (__force __be32)(count & ~SHA_PADDING_MASK);
+ rctx->byte_count[1] = (__force __be32)(count >> 32);
+ qce_cpu_to_be32p_array((__be32 *)rctx->digest, (const u8 *)state,
+ digestsize);
+ rctx->buflen = (unsigned int)(in_count & (blocksize - 1));
+
+ return 0;
+}
+
+static int qce_ahash_import(struct ahash_request *req, const void *in)
+{
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ unsigned long flags = rctx->flags;
+ bool hmac = IS_SHA_HMAC(flags);
+ int ret = -EINVAL;
+
+ if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) {
+ const struct sha1_state *state = in;
+
+ ret = qce_import_common(req, state->count, state->state,
+ state->buffer, hmac);
+ } else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) {
+ const struct sha256_state *state = in;
+
+ ret = qce_import_common(req, state->count, state->state,
+ state->buf, hmac);
+ }
+
+ return ret;
+}
+
+static int qce_ahash_update(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+ struct qce_device *qce = tmpl->qce;
+ struct scatterlist *sg_last, *sg;
+ unsigned int total, len;
+ unsigned int hash_later;
+ unsigned int nbytes;
+ unsigned int blocksize;
+
+ blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+ rctx->count += req->nbytes;
+
+ /* check for buffer from previous updates and append it */
+ total = req->nbytes + rctx->buflen;
+
+ if (total <= blocksize) {
+ scatterwalk_map_and_copy(rctx->buf + rctx->buflen, req->src,
+ 0, req->nbytes, 0);
+ rctx->buflen += req->nbytes;
+ return 0;
+ }
+
+ /* save the original req structure fields */
+ rctx->src_orig = req->src;
+ rctx->nbytes_orig = req->nbytes;
+
+ /*
+ * if we have data from previous update copy them on buffer. The old
+ * data will be combined with current request bytes.
+ */
+ if (rctx->buflen)
+ memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
+
+ /* calculate how many bytes will be hashed later */
+ hash_later = total % blocksize;
+ if (hash_later) {
+ unsigned int src_offset = req->nbytes - hash_later;
+ scatterwalk_map_and_copy(rctx->buf, req->src, src_offset,
+ hash_later, 0);
+ }
+
+ /* here nbytes is multiple of blocksize */
+ nbytes = total - hash_later;
+
+ len = rctx->buflen;
+ sg = sg_last = req->src;
+
+ while (len < nbytes && sg) {
+ if (len + sg_dma_len(sg) > nbytes)
+ break;
+ len += sg_dma_len(sg);
+ sg_last = sg;
+ sg = scatterwalk_sg_next(sg);
+ }
+
+ if (!sg_last)
+ return -EINVAL;
+
+ sg_mark_end(sg_last);
+
+ if (rctx->buflen) {
+ sg_init_table(rctx->sg, 2);
+ sg_set_buf(rctx->sg, rctx->tmpbuf, rctx->buflen);
+ scatterwalk_sg_chain(rctx->sg, 2, req->src);
+ req->src = rctx->sg;
+ }
+
+ req->nbytes = nbytes;
+ rctx->buflen = hash_later;
+
+ return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ahash_final(struct ahash_request *req)
+{
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+ struct qce_device *qce = tmpl->qce;
+
+ if (!rctx->buflen)
+ return 0;
+
+ rctx->last_blk = true;
+
+ rctx->src_orig = req->src;
+ rctx->nbytes_orig = req->nbytes;
+
+ memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
+ sg_init_one(rctx->sg, rctx->tmpbuf, rctx->buflen);
+
+ req->src = rctx->sg;
+ req->nbytes = rctx->buflen;
+
+ return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+static int qce_ahash_digest(struct ahash_request *req)
+{
+ struct qce_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
+ struct qce_device *qce = tmpl->qce;
+ int ret;
+
+ ret = qce_ahash_init(req);
+ if (ret)
+ return ret;
+
+ rctx->src_orig = req->src;
+ rctx->nbytes_orig = req->nbytes;
+ rctx->first_blk = true;
+ rctx->last_blk = true;
+
+ return qce->async_req_enqueue(tmpl->qce, &req->base);
+}
+
+struct qce_ahash_result {
+ struct completion completion;
+ int error;
+};
+
+static void qce_digest_complete(struct crypto_async_request *req, int error)
+{
+ struct qce_ahash_result *result = req->data;
+
+ if (error == -EINPROGRESS)
+ return;
+
+ result->error = error;
+ complete(&result->completion);
+}
+
+static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ unsigned int digestsize = crypto_ahash_digestsize(tfm);
+ struct qce_sha_ctx *ctx = crypto_tfm_ctx(&tfm->base);
+ struct qce_ahash_result result;
+ struct ahash_request *req;
+ struct scatterlist sg;
+ unsigned int blocksize;
+ struct crypto_ahash *ahash_tfm;
+ u8 *buf;
+ int ret;
+ const char *alg_name;
+
+ blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+ memset(ctx->authkey, 0, sizeof(ctx->authkey));
+
+ if (keylen <= blocksize) {
+ memcpy(ctx->authkey, key, keylen);
+ return 0;
+ }
+
+ if (digestsize == SHA1_DIGEST_SIZE)
+ alg_name = "sha1-qce";
+ else if (digestsize == SHA256_DIGEST_SIZE)
+ alg_name = "sha256-qce";
+ else
+ return -EINVAL;
+
+ ahash_tfm = crypto_alloc_ahash(alg_name, CRYPTO_ALG_TYPE_AHASH,
+ CRYPTO_ALG_TYPE_AHASH_MASK);
+ if (IS_ERR(ahash_tfm))
+ return PTR_ERR(ahash_tfm);
+
+ req = ahash_request_alloc(ahash_tfm, GFP_KERNEL);
+ if (!req) {
+ ret = -ENOMEM;
+ goto err_free_ahash;
+ }
+
+ init_completion(&result.completion);
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ qce_digest_complete, &result);
+ crypto_ahash_clear_flags(ahash_tfm, ~0);
+
+ buf = kzalloc(keylen + QCE_MAX_ALIGN_SIZE, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_free_req;
+ }
+
+ memcpy(buf, key, keylen);
+ sg_init_one(&sg, buf, keylen);
+ ahash_request_set_crypt(req, &sg, ctx->authkey, keylen);
+
+ ret = crypto_ahash_digest(req);
+ if (ret == -EINPROGRESS || ret == -EBUSY) {
+ ret = wait_for_completion_interruptible(&result.completion);
+ if (!ret)
+ ret = result.error;
+ }
+
+ if (ret)
+ crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+ kfree(buf);
+err_free_req:
+ ahash_request_free(req);
+err_free_ahash:
+ crypto_free_ahash(ahash_tfm);
+ return ret;
+}
+
+static int qce_ahash_cra_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+ struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_ahash_set_reqsize(ahash, sizeof(struct qce_sha_reqctx));
+ memset(ctx, 0, sizeof(*ctx));
+ return 0;
+}
+
+struct qce_ahash_def {
+ unsigned long flags;
+ const char *name;
+ const char *drv_name;
+ unsigned int digestsize;
+ unsigned int blocksize;
+ unsigned int statesize;
+ const u32 *std_iv;
+};
+
+static const struct qce_ahash_def ahash_def[] = {
+ {
+ .flags = QCE_HASH_SHA1,
+ .name = "sha1",
+ .drv_name = "sha1-qce",
+ .digestsize = SHA1_DIGEST_SIZE,
+ .blocksize = SHA1_BLOCK_SIZE,
+ .statesize = sizeof(struct sha1_state),
+ .std_iv = std_iv_sha1,
+ },
+ {
+ .flags = QCE_HASH_SHA256,
+ .name = "sha256",
+ .drv_name = "sha256-qce",
+ .digestsize = SHA256_DIGEST_SIZE,
+ .blocksize = SHA256_BLOCK_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .std_iv = std_iv_sha256,
+ },
+ {
+ .flags = QCE_HASH_SHA1_HMAC,
+ .name = "hmac(sha1)",
+ .drv_name = "hmac-sha1-qce",
+ .digestsize = SHA1_DIGEST_SIZE,
+ .blocksize = SHA1_BLOCK_SIZE,
+ .statesize = sizeof(struct sha1_state),
+ .std_iv = std_iv_sha1,
+ },
+ {
+ .flags = QCE_HASH_SHA256_HMAC,
+ .name = "hmac(sha256)",
+ .drv_name = "hmac-sha256-qce",
+ .digestsize = SHA256_DIGEST_SIZE,
+ .blocksize = SHA256_BLOCK_SIZE,
+ .statesize = sizeof(struct sha256_state),
+ .std_iv = std_iv_sha256,
+ },
+};
+
+static int qce_ahash_register_one(const struct qce_ahash_def *def,
+ struct qce_device *qce)
+{
+ struct qce_alg_template *tmpl;
+ struct ahash_alg *alg;
+ struct crypto_alg *base;
+ int ret;
+
+ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+ if (!tmpl)
+ return -ENOMEM;
+
+ tmpl->std_iv = def->std_iv;
+
+ alg = &tmpl->alg.ahash;
+ alg->init = qce_ahash_init;
+ alg->update = qce_ahash_update;
+ alg->final = qce_ahash_final;
+ alg->digest = qce_ahash_digest;
+ alg->export = qce_ahash_export;
+ alg->import = qce_ahash_import;
+ if (IS_SHA_HMAC(def->flags))
+ alg->setkey = qce_ahash_hmac_setkey;
+ alg->halg.digestsize = def->digestsize;
+ alg->halg.statesize = def->statesize;
+
+ base = &alg->halg.base;
+ base->cra_blocksize = def->blocksize;
+ base->cra_priority = 300;
+ base->cra_flags = CRYPTO_ALG_ASYNC;
+ base->cra_ctxsize = sizeof(struct qce_sha_ctx);
+ base->cra_alignmask = 0;
+ base->cra_module = THIS_MODULE;
+ base->cra_init = qce_ahash_cra_init;
+ INIT_LIST_HEAD(&base->cra_list);
+
+ snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+ snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ def->drv_name);
+
+ INIT_LIST_HEAD(&tmpl->entry);
+ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_AHASH;
+ tmpl->alg_flags = def->flags;
+ tmpl->qce = qce;
+
+ ret = crypto_register_ahash(alg);
+ if (ret) {
+ kfree(tmpl);
+ dev_err(qce->dev, "%s registration failed\n", base->cra_name);
+ return ret;
+ }
+
+ list_add_tail(&tmpl->entry, &ahash_algs);
+ dev_dbg(qce->dev, "%s is registered\n", base->cra_name);
+ return 0;
+}
+
+static void qce_ahash_unregister(struct qce_device *qce)
+{
+ struct qce_alg_template *tmpl, *n;
+
+ list_for_each_entry_safe(tmpl, n, &ahash_algs, entry) {
+ crypto_unregister_ahash(&tmpl->alg.ahash);
+ list_del(&tmpl->entry);
+ kfree(tmpl);
+ }
+}
+
+static int qce_ahash_register(struct qce_device *qce)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(ahash_def); i++) {
+ ret = qce_ahash_register_one(&ahash_def[i], qce);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+err:
+ qce_ahash_unregister(qce);
+ return ret;
+}
+
+const struct qce_algo_ops ahash_ops = {
+ .type = CRYPTO_ALG_TYPE_AHASH,
+ .register_algs = qce_ahash_register,
+ .unregister_algs = qce_ahash_unregister,
+ .async_req_handle = qce_ahash_async_req_handle,
+};
diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h
new file mode 100644
index 000000000000..286f0d5397f3
--- /dev/null
+++ b/drivers/crypto/qce/sha.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SHA_H_
+#define _SHA_H_
+
+#include <crypto/scatterwalk.h>
+#include <crypto/sha.h>
+
+#include "common.h"
+#include "core.h"
+
+#define QCE_SHA_MAX_BLOCKSIZE SHA256_BLOCK_SIZE
+#define QCE_SHA_MAX_DIGESTSIZE SHA256_DIGEST_SIZE
+
+struct qce_sha_ctx {
+ u8 authkey[QCE_SHA_MAX_BLOCKSIZE];
+};
+
+/**
+ * struct qce_sha_reqctx - holds private ahash objects per request
+ * @buf: used during update, import and export
+ * @tmpbuf: buffer for internal use
+ * @digest: calculated digest buffer
+ * @buflen: length of the buffer
+ * @flags: operation flags
+ * @src_orig: original request sg list
+ * @nbytes_orig: original request number of bytes
+ * @src_chained: is source scatterlist chained
+ * @src_nents: source number of entries
+ * @byte_count: byte count
+ * @count: save count in states during update, import and export
+ * @first_blk: is it the first block
+ * @last_blk: is it the last block
+ * @sg: used to chain sg lists
+ * @authkey: pointer to auth key in sha ctx
+ * @authklen: auth key length
+ * @result_sg: scatterlist used for result buffer
+ */
+struct qce_sha_reqctx {
+ u8 buf[QCE_SHA_MAX_BLOCKSIZE];
+ u8 tmpbuf[QCE_SHA_MAX_BLOCKSIZE];
+ u8 digest[QCE_SHA_MAX_DIGESTSIZE];
+ unsigned int buflen;
+ unsigned long flags;
+ struct scatterlist *src_orig;
+ unsigned int nbytes_orig;
+ bool src_chained;
+ int src_nents;
+ __be32 byte_count[2];
+ u64 count;
+ bool first_blk;
+ bool last_blk;
+ struct scatterlist sg[2];
+ u8 *authkey;
+ unsigned int authklen;
+ struct scatterlist result_sg;
+};
+
+static inline struct qce_alg_template *to_ahash_tmpl(struct crypto_tfm *tfm)
+{
+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+ struct ahash_alg *alg = container_of(crypto_hash_alg_common(ahash),
+ struct ahash_alg, halg);
+
+ return container_of(alg, struct qce_alg_template, alg.ahash);
+}
+
+extern const struct qce_algo_ops ahash_ops;
+
+#endif /* _SHA_H_ */
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index a999f537228f..92105f3dc8e0 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -190,7 +190,7 @@ static void add_session_id(struct cryp_ctx *ctx)
static irqreturn_t cryp_interrupt_handler(int irq, void *param)
{
struct cryp_ctx *ctx;
- int i;
+ int count;
struct cryp_device_data *device_data;
if (param == NULL) {
@@ -215,12 +215,11 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param)
if (cryp_pending_irq_src(device_data,
CRYP_IRQ_SRC_OUTPUT_FIFO)) {
if (ctx->outlen / ctx->blocksize > 0) {
- for (i = 0; i < ctx->blocksize / 4; i++) {
- *(ctx->outdata) = readl_relaxed(
- &device_data->base->dout);
- ctx->outdata += 4;
- ctx->outlen -= 4;
- }
+ count = ctx->blocksize / 4;
+
+ readsl(&device_data->base->dout, ctx->outdata, count);
+ ctx->outdata += count;
+ ctx->outlen -= count;
if (ctx->outlen == 0) {
cryp_disable_irq_src(device_data,
@@ -230,12 +229,12 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param)
} else if (cryp_pending_irq_src(device_data,
CRYP_IRQ_SRC_INPUT_FIFO)) {
if (ctx->datalen / ctx->blocksize > 0) {
- for (i = 0 ; i < ctx->blocksize / 4; i++) {
- writel_relaxed(ctx->indata,
- &device_data->base->din);
- ctx->indata += 4;
- ctx->datalen -= 4;
- }
+ count = ctx->blocksize / 4;
+
+ writesl(&device_data->base->din, ctx->indata, count);
+
+ ctx->indata += count;
+ ctx->datalen -= count;
if (ctx->datalen == 0)
cryp_disable_irq_src(device_data,
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 49e74c1fc639..3dced0a9eae3 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -68,7 +68,6 @@ comment "DEVFREQ Drivers"
config ARM_EXYNOS4_BUS_DEVFREQ
bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver"
depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
- select ARCH_HAS_OPP
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select PM_OPP
help
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
new file mode 100644
index 000000000000..57a675f90cd0
--- /dev/null
+++ b/drivers/dma-buf/Makefile
@@ -0,0 +1 @@
+obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
diff --git a/drivers/base/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 840c7fa80983..f3014c448e1e 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -25,10 +25,13 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/dma-buf.h>
+#include <linux/fence.h>
#include <linux/anon_inodes.h>
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/poll.h>
+#include <linux/reservation.h>
static inline int is_dma_buf_file(struct file *);
@@ -50,12 +53,25 @@ static int dma_buf_release(struct inode *inode, struct file *file)
BUG_ON(dmabuf->vmapping_counter);
+ /*
+ * Any fences that a dma-buf poll can wait on should be signaled
+ * before releasing dma-buf. This is the responsibility of each
+ * driver that uses the reservation objects.
+ *
+ * If you hit this BUG() it means someone dropped their ref to the
+ * dma-buf while still having pending operation to the buffer.
+ */
+ BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
+
dmabuf->ops->release(dmabuf);
mutex_lock(&db_list.lock);
list_del(&dmabuf->list_node);
mutex_unlock(&db_list.lock);
+ if (dmabuf->resv == (struct reservation_object *)&dmabuf[1])
+ reservation_object_fini(dmabuf->resv);
+
kfree(dmabuf);
return 0;
}
@@ -103,10 +119,141 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
return base + offset;
}
+static void dma_buf_poll_cb(struct fence *fence, struct fence_cb *cb)
+{
+ struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dcb->poll->lock, flags);
+ wake_up_locked_poll(dcb->poll, dcb->active);
+ dcb->active = 0;
+ spin_unlock_irqrestore(&dcb->poll->lock, flags);
+}
+
+static unsigned int dma_buf_poll(struct file *file, poll_table *poll)
+{
+ struct dma_buf *dmabuf;
+ struct reservation_object *resv;
+ struct reservation_object_list *fobj;
+ struct fence *fence_excl;
+ unsigned long events;
+ unsigned shared_count, seq;
+
+ dmabuf = file->private_data;
+ if (!dmabuf || !dmabuf->resv)
+ return POLLERR;
+
+ resv = dmabuf->resv;
+
+ poll_wait(file, &dmabuf->poll, poll);
+
+ events = poll_requested_events(poll) & (POLLIN | POLLOUT);
+ if (!events)
+ return 0;
+
+retry:
+ seq = read_seqcount_begin(&resv->seq);
+ rcu_read_lock();
+
+ fobj = rcu_dereference(resv->fence);
+ if (fobj)
+ shared_count = fobj->shared_count;
+ else
+ shared_count = 0;
+ fence_excl = rcu_dereference(resv->fence_excl);
+ if (read_seqcount_retry(&resv->seq, seq)) {
+ rcu_read_unlock();
+ goto retry;
+ }
+
+ if (fence_excl && (!(events & POLLOUT) || shared_count == 0)) {
+ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
+ unsigned long pevents = POLLIN;
+
+ if (shared_count == 0)
+ pevents |= POLLOUT;
+
+ spin_lock_irq(&dmabuf->poll.lock);
+ if (dcb->active) {
+ dcb->active |= pevents;
+ events &= ~pevents;
+ } else
+ dcb->active = pevents;
+ spin_unlock_irq(&dmabuf->poll.lock);
+
+ if (events & pevents) {
+ if (!fence_get_rcu(fence_excl)) {
+ /* force a recheck */
+ events &= ~pevents;
+ dma_buf_poll_cb(NULL, &dcb->cb);
+ } else if (!fence_add_callback(fence_excl, &dcb->cb,
+ dma_buf_poll_cb)) {
+ events &= ~pevents;
+ fence_put(fence_excl);
+ } else {
+ /*
+ * No callback queued, wake up any additional
+ * waiters.
+ */
+ fence_put(fence_excl);
+ dma_buf_poll_cb(NULL, &dcb->cb);
+ }
+ }
+ }
+
+ if ((events & POLLOUT) && shared_count > 0) {
+ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared;
+ int i;
+
+ /* Only queue a new callback if no event has fired yet */
+ spin_lock_irq(&dmabuf->poll.lock);
+ if (dcb->active)
+ events &= ~POLLOUT;
+ else
+ dcb->active = POLLOUT;
+ spin_unlock_irq(&dmabuf->poll.lock);
+
+ if (!(events & POLLOUT))
+ goto out;
+
+ for (i = 0; i < shared_count; ++i) {
+ struct fence *fence = rcu_dereference(fobj->shared[i]);
+
+ if (!fence_get_rcu(fence)) {
+ /*
+ * fence refcount dropped to zero, this means
+ * that fobj has been freed
+ *
+ * call dma_buf_poll_cb and force a recheck!
+ */
+ events &= ~POLLOUT;
+ dma_buf_poll_cb(NULL, &dcb->cb);
+ break;
+ }
+ if (!fence_add_callback(fence, &dcb->cb,
+ dma_buf_poll_cb)) {
+ fence_put(fence);
+ events &= ~POLLOUT;
+ break;
+ }
+ fence_put(fence);
+ }
+
+ /* No callback queued, wake up any additional waiters. */
+ if (i == shared_count)
+ dma_buf_poll_cb(NULL, &dcb->cb);
+ }
+
+out:
+ rcu_read_unlock();
+ return events;
+}
+
static const struct file_operations dma_buf_fops = {
.release = dma_buf_release,
.mmap = dma_buf_mmap_internal,
.llseek = dma_buf_llseek,
+ .poll = dma_buf_poll,
};
/*
@@ -128,6 +275,7 @@ static inline int is_dma_buf_file(struct file *file)
* @size: [in] Size of the buffer
* @flags: [in] mode flags for the file.
* @exp_name: [in] name of the exporting module - useful for debugging.
+ * @resv: [in] reservation-object, NULL to allocate default one.
*
* Returns, on success, a newly created dma_buf object, which wraps the
* supplied private data and operations for dma_buf_ops. On either missing
@@ -135,10 +283,17 @@ static inline int is_dma_buf_file(struct file *file)
*
*/
struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
- size_t size, int flags, const char *exp_name)
+ size_t size, int flags, const char *exp_name,
+ struct reservation_object *resv)
{
struct dma_buf *dmabuf;
struct file *file;
+ size_t alloc_size = sizeof(struct dma_buf);
+ if (!resv)
+ alloc_size += sizeof(struct reservation_object);
+ else
+ /* prevent &dma_buf[1] == dma_buf->resv */
+ alloc_size += 1;
if (WARN_ON(!priv || !ops
|| !ops->map_dma_buf
@@ -150,7 +305,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
return ERR_PTR(-EINVAL);
}
- dmabuf = kzalloc(sizeof(struct dma_buf), GFP_KERNEL);
+ dmabuf = kzalloc(alloc_size, GFP_KERNEL);
if (dmabuf == NULL)
return ERR_PTR(-ENOMEM);
@@ -158,6 +313,15 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
dmabuf->ops = ops;
dmabuf->size = size;
dmabuf->exp_name = exp_name;
+ init_waitqueue_head(&dmabuf->poll);
+ dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
+ dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
+
+ if (!resv) {
+ resv = (struct reservation_object *)&dmabuf[1];
+ reservation_object_init(resv);
+ }
+ dmabuf->resv = resv;
file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
if (IS_ERR(file)) {
diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c
new file mode 100644
index 000000000000..4222cb2aa96a
--- /dev/null
+++ b/drivers/dma-buf/fence.c
@@ -0,0 +1,431 @@
+/*
+ * Fence mechanism for dma-buf and to allow for asynchronous dma access
+ *
+ * Copyright (C) 2012 Canonical Ltd
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Maarten Lankhorst <maarten.lankhorst@canonical.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.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/atomic.h>
+#include <linux/fence.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/fence.h>
+
+EXPORT_TRACEPOINT_SYMBOL(fence_annotate_wait_on);
+EXPORT_TRACEPOINT_SYMBOL(fence_emit);
+
+/**
+ * fence context counter: each execution context should have its own
+ * fence context, this allows checking if fences belong to the same
+ * context or not. One device can have multiple separate contexts,
+ * and they're used if some engine can run independently of another.
+ */
+static atomic_t fence_context_counter = ATOMIC_INIT(0);
+
+/**
+ * fence_context_alloc - allocate an array of fence contexts
+ * @num: [in] amount of contexts to allocate
+ *
+ * This function will return the first index of the number of fences allocated.
+ * The fence context is used for setting fence->context to a unique number.
+ */
+unsigned fence_context_alloc(unsigned num)
+{
+ BUG_ON(!num);
+ return atomic_add_return(num, &fence_context_counter) - num;
+}
+EXPORT_SYMBOL(fence_context_alloc);
+
+/**
+ * fence_signal_locked - signal completion of a fence
+ * @fence: the fence to signal
+ *
+ * Signal completion for software callbacks on a fence, this will unblock
+ * fence_wait() calls and run all the callbacks added with
+ * fence_add_callback(). Can be called multiple times, but since a fence
+ * can only go from unsignaled to signaled state, it will only be effective
+ * the first time.
+ *
+ * Unlike fence_signal, this function must be called with fence->lock held.
+ */
+int fence_signal_locked(struct fence *fence)
+{
+ struct fence_cb *cur, *tmp;
+ int ret = 0;
+
+ if (WARN_ON(!fence))
+ return -EINVAL;
+
+ if (!ktime_to_ns(fence->timestamp)) {
+ fence->timestamp = ktime_get();
+ smp_mb__before_atomic();
+ }
+
+ if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ ret = -EINVAL;
+
+ /*
+ * we might have raced with the unlocked fence_signal,
+ * still run through all callbacks
+ */
+ } else
+ trace_fence_signaled(fence);
+
+ list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+ list_del_init(&cur->node);
+ cur->func(fence, cur);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(fence_signal_locked);
+
+/**
+ * fence_signal - signal completion of a fence
+ * @fence: the fence to signal
+ *
+ * Signal completion for software callbacks on a fence, this will unblock
+ * fence_wait() calls and run all the callbacks added with
+ * fence_add_callback(). Can be called multiple times, but since a fence
+ * can only go from unsignaled to signaled state, it will only be effective
+ * the first time.
+ */
+int fence_signal(struct fence *fence)
+{
+ unsigned long flags;
+
+ if (!fence)
+ return -EINVAL;
+
+ if (!ktime_to_ns(fence->timestamp)) {
+ fence->timestamp = ktime_get();
+ smp_mb__before_atomic();
+ }
+
+ if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return -EINVAL;
+
+ trace_fence_signaled(fence);
+
+ if (test_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
+ struct fence_cb *cur, *tmp;
+
+ spin_lock_irqsave(fence->lock, flags);
+ list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+ list_del_init(&cur->node);
+ cur->func(fence, cur);
+ }
+ spin_unlock_irqrestore(fence->lock, flags);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(fence_signal);
+
+/**
+ * fence_wait_timeout - sleep until the fence gets signaled
+ * or until timeout elapses
+ * @fence: [in] the fence to wait on
+ * @intr: [in] if true, do an interruptible wait
+ * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ *
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
+ * remaining timeout in jiffies on success. Other error values may be
+ * returned on custom implementations.
+ *
+ * Performs a synchronous wait on this fence. It is assumed the caller
+ * directly or indirectly (buf-mgr between reservation and committing)
+ * holds a reference to the fence, otherwise the fence might be
+ * freed before return, resulting in undefined behavior.
+ */
+signed long
+fence_wait_timeout(struct fence *fence, bool intr, signed long timeout)
+{
+ signed long ret;
+
+ if (WARN_ON(timeout < 0))
+ return -EINVAL;
+
+ trace_fence_wait_start(fence);
+ ret = fence->ops->wait(fence, intr, timeout);
+ trace_fence_wait_end(fence);
+ return ret;
+}
+EXPORT_SYMBOL(fence_wait_timeout);
+
+void fence_release(struct kref *kref)
+{
+ struct fence *fence =
+ container_of(kref, struct fence, refcount);
+
+ trace_fence_destroy(fence);
+
+ BUG_ON(!list_empty(&fence->cb_list));
+
+ if (fence->ops->release)
+ fence->ops->release(fence);
+ else
+ fence_free(fence);
+}
+EXPORT_SYMBOL(fence_release);
+
+void fence_free(struct fence *fence)
+{
+ kfree_rcu(fence, rcu);
+}
+EXPORT_SYMBOL(fence_free);
+
+/**
+ * fence_enable_sw_signaling - enable signaling on fence
+ * @fence: [in] the fence to enable
+ *
+ * this will request for sw signaling to be enabled, to make the fence
+ * complete as soon as possible
+ */
+void fence_enable_sw_signaling(struct fence *fence)
+{
+ unsigned long flags;
+
+ if (!test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags) &&
+ !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ trace_fence_enable_signal(fence);
+
+ spin_lock_irqsave(fence->lock, flags);
+
+ if (!fence->ops->enable_signaling(fence))
+ fence_signal_locked(fence);
+
+ spin_unlock_irqrestore(fence->lock, flags);
+ }
+}
+EXPORT_SYMBOL(fence_enable_sw_signaling);
+
+/**
+ * fence_add_callback - add a callback to be called when the fence
+ * is signaled
+ * @fence: [in] the fence to wait on
+ * @cb: [in] the callback to register
+ * @func: [in] the function to call
+ *
+ * cb will be initialized by fence_add_callback, no initialization
+ * by the caller is required. Any number of callbacks can be registered
+ * to a fence, but a callback can only be registered to one fence at a time.
+ *
+ * Note that the callback can be called from an atomic context. If
+ * fence is already signaled, this function will return -ENOENT (and
+ * *not* call the callback)
+ *
+ * Add a software callback to the fence. Same restrictions apply to
+ * refcount as it does to fence_wait, however the caller doesn't need to
+ * keep a refcount to fence afterwards: when software access is enabled,
+ * the creator of the fence is required to keep the fence alive until
+ * after it signals with fence_signal. The callback itself can be called
+ * from irq context.
+ *
+ */
+int fence_add_callback(struct fence *fence, struct fence_cb *cb,
+ fence_func_t func)
+{
+ unsigned long flags;
+ int ret = 0;
+ bool was_set;
+
+ if (WARN_ON(!fence || !func))
+ return -EINVAL;
+
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ INIT_LIST_HEAD(&cb->node);
+ return -ENOENT;
+ }
+
+ spin_lock_irqsave(fence->lock, flags);
+
+ was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
+
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ ret = -ENOENT;
+ else if (!was_set) {
+ trace_fence_enable_signal(fence);
+
+ if (!fence->ops->enable_signaling(fence)) {
+ fence_signal_locked(fence);
+ ret = -ENOENT;
+ }
+ }
+
+ if (!ret) {
+ cb->func = func;
+ list_add_tail(&cb->node, &fence->cb_list);
+ } else
+ INIT_LIST_HEAD(&cb->node);
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(fence_add_callback);
+
+/**
+ * fence_remove_callback - remove a callback from the signaling list
+ * @fence: [in] the fence to wait on
+ * @cb: [in] the callback to remove
+ *
+ * Remove a previously queued callback from the fence. This function returns
+ * true if the callback is succesfully removed, or false if the fence has
+ * already been signaled.
+ *
+ * *WARNING*:
+ * Cancelling a callback should only be done if you really know what you're
+ * doing, since deadlocks and race conditions could occur all too easily. For
+ * this reason, it should only ever be done on hardware lockup recovery,
+ * with a reference held to the fence.
+ */
+bool
+fence_remove_callback(struct fence *fence, struct fence_cb *cb)
+{
+ unsigned long flags;
+ bool ret;
+
+ spin_lock_irqsave(fence->lock, flags);
+
+ ret = !list_empty(&cb->node);
+ if (ret)
+ list_del_init(&cb->node);
+
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(fence_remove_callback);
+
+struct default_wait_cb {
+ struct fence_cb base;
+ struct task_struct *task;
+};
+
+static void
+fence_default_wait_cb(struct fence *fence, struct fence_cb *cb)
+{
+ struct default_wait_cb *wait =
+ container_of(cb, struct default_wait_cb, base);
+
+ wake_up_state(wait->task, TASK_NORMAL);
+}
+
+/**
+ * fence_default_wait - default sleep until the fence gets signaled
+ * or until timeout elapses
+ * @fence: [in] the fence to wait on
+ * @intr: [in] if true, do an interruptible wait
+ * @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ *
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
+ * remaining timeout in jiffies on success.
+ */
+signed long
+fence_default_wait(struct fence *fence, bool intr, signed long timeout)
+{
+ struct default_wait_cb cb;
+ unsigned long flags;
+ signed long ret = timeout;
+ bool was_set;
+
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return timeout;
+
+ spin_lock_irqsave(fence->lock, flags);
+
+ if (intr && signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ goto out;
+ }
+
+ was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
+
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ goto out;
+
+ if (!was_set) {
+ trace_fence_enable_signal(fence);
+
+ if (!fence->ops->enable_signaling(fence)) {
+ fence_signal_locked(fence);
+ goto out;
+ }
+ }
+
+ cb.base.func = fence_default_wait_cb;
+ cb.task = current;
+ list_add(&cb.base.node, &fence->cb_list);
+
+ while (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {
+ if (intr)
+ __set_current_state(TASK_INTERRUPTIBLE);
+ else
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ ret = schedule_timeout(ret);
+
+ spin_lock_irqsave(fence->lock, flags);
+ if (ret > 0 && intr && signal_pending(current))
+ ret = -ERESTARTSYS;
+ }
+
+ if (!list_empty(&cb.base.node))
+ list_del(&cb.base.node);
+ __set_current_state(TASK_RUNNING);
+
+out:
+ spin_unlock_irqrestore(fence->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(fence_default_wait);
+
+/**
+ * fence_init - Initialize a custom fence.
+ * @fence: [in] the fence to initialize
+ * @ops: [in] the fence_ops for operations on this fence
+ * @lock: [in] the irqsafe spinlock to use for locking this fence
+ * @context: [in] the execution context this fence is run on
+ * @seqno: [in] a linear increasing sequence number for this context
+ *
+ * Initializes an allocated fence, the caller doesn't have to keep its
+ * refcount after committing with this fence, but it will need to hold a
+ * refcount again if fence_ops.enable_signaling gets called. This can
+ * be used for other implementing other types of fence.
+ *
+ * context and seqno are used for easy comparison between fences, allowing
+ * to check which fence is later by simply using fence_later.
+ */
+void
+fence_init(struct fence *fence, const struct fence_ops *ops,
+ spinlock_t *lock, unsigned context, unsigned seqno)
+{
+ BUG_ON(!lock);
+ BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
+ !ops->get_driver_name || !ops->get_timeline_name);
+
+ kref_init(&fence->refcount);
+ fence->ops = ops;
+ INIT_LIST_HEAD(&fence->cb_list);
+ fence->lock = lock;
+ fence->context = context;
+ fence->seqno = seqno;
+ fence->flags = 0UL;
+
+ trace_fence_init(fence);
+}
+EXPORT_SYMBOL(fence_init);
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
new file mode 100644
index 000000000000..3c97c8fa8d02
--- /dev/null
+++ b/drivers/dma-buf/reservation.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2012-2014 Canonical Ltd (Maarten Lankhorst)
+ *
+ * Based on bo.c which bears the following copyright notice,
+ * but is dual licensed:
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include <linux/reservation.h>
+#include <linux/export.h>
+
+DEFINE_WW_CLASS(reservation_ww_class);
+EXPORT_SYMBOL(reservation_ww_class);
+
+struct lock_class_key reservation_seqcount_class;
+EXPORT_SYMBOL(reservation_seqcount_class);
+
+const char reservation_seqcount_string[] = "reservation_seqcount";
+EXPORT_SYMBOL(reservation_seqcount_string);
+/*
+ * Reserve space to add a shared fence to a reservation_object,
+ * must be called with obj->lock held.
+ */
+int reservation_object_reserve_shared(struct reservation_object *obj)
+{
+ struct reservation_object_list *fobj, *old;
+ u32 max;
+
+ old = reservation_object_get_list(obj);
+
+ if (old && old->shared_max) {
+ if (old->shared_count < old->shared_max) {
+ /* perform an in-place update */
+ kfree(obj->staged);
+ obj->staged = NULL;
+ return 0;
+ } else
+ max = old->shared_max * 2;
+ } else
+ max = 4;
+
+ /*
+ * resize obj->staged or allocate if it doesn't exist,
+ * noop if already correct size
+ */
+ fobj = krealloc(obj->staged, offsetof(typeof(*fobj), shared[max]),
+ GFP_KERNEL);
+ if (!fobj)
+ return -ENOMEM;
+
+ obj->staged = fobj;
+ fobj->shared_max = max;
+ return 0;
+}
+EXPORT_SYMBOL(reservation_object_reserve_shared);
+
+static void
+reservation_object_add_shared_inplace(struct reservation_object *obj,
+ struct reservation_object_list *fobj,
+ struct fence *fence)
+{
+ u32 i;
+
+ fence_get(fence);
+
+ preempt_disable();
+ write_seqcount_begin(&obj->seq);
+
+ for (i = 0; i < fobj->shared_count; ++i) {
+ struct fence *old_fence;
+
+ old_fence = rcu_dereference_protected(fobj->shared[i],
+ reservation_object_held(obj));
+
+ if (old_fence->context == fence->context) {
+ /* memory barrier is added by write_seqcount_begin */
+ RCU_INIT_POINTER(fobj->shared[i], fence);
+ write_seqcount_end(&obj->seq);
+ preempt_enable();
+
+ fence_put(old_fence);
+ return;
+ }
+ }
+
+ /*
+ * memory barrier is added by write_seqcount_begin,
+ * fobj->shared_count is protected by this lock too
+ */
+ RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+ fobj->shared_count++;
+
+ write_seqcount_end(&obj->seq);
+ preempt_enable();
+}
+
+static void
+reservation_object_add_shared_replace(struct reservation_object *obj,
+ struct reservation_object_list *old,
+ struct reservation_object_list *fobj,
+ struct fence *fence)
+{
+ unsigned i;
+ struct fence *old_fence = NULL;
+
+ fence_get(fence);
+
+ if (!old) {
+ RCU_INIT_POINTER(fobj->shared[0], fence);
+ fobj->shared_count = 1;
+ goto done;
+ }
+
+ /*
+ * no need to bump fence refcounts, rcu_read access
+ * requires the use of kref_get_unless_zero, and the
+ * references from the old struct are carried over to
+ * the new.
+ */
+ fobj->shared_count = old->shared_count;
+
+ for (i = 0; i < old->shared_count; ++i) {
+ struct fence *check;
+
+ check = rcu_dereference_protected(old->shared[i],
+ reservation_object_held(obj));
+
+ if (!old_fence && check->context == fence->context) {
+ old_fence = check;
+ RCU_INIT_POINTER(fobj->shared[i], fence);
+ } else
+ RCU_INIT_POINTER(fobj->shared[i], check);
+ }
+ if (!old_fence) {
+ RCU_INIT_POINTER(fobj->shared[fobj->shared_count], fence);
+ fobj->shared_count++;
+ }
+
+done:
+ preempt_disable();
+ write_seqcount_begin(&obj->seq);
+ /*
+ * RCU_INIT_POINTER can be used here,
+ * seqcount provides the necessary barriers
+ */
+ RCU_INIT_POINTER(obj->fence, fobj);
+ write_seqcount_end(&obj->seq);
+ preempt_enable();
+
+ if (old)
+ kfree_rcu(old, rcu);
+
+ if (old_fence)
+ fence_put(old_fence);
+}
+
+/*
+ * Add a fence to a shared slot, obj->lock must be held, and
+ * reservation_object_reserve_shared_fence has been called.
+ */
+void reservation_object_add_shared_fence(struct reservation_object *obj,
+ struct fence *fence)
+{
+ struct reservation_object_list *old, *fobj = obj->staged;
+
+ old = reservation_object_get_list(obj);
+ obj->staged = NULL;
+
+ if (!fobj) {
+ BUG_ON(old->shared_count >= old->shared_max);
+ reservation_object_add_shared_inplace(obj, old, fence);
+ } else
+ reservation_object_add_shared_replace(obj, old, fobj, fence);
+}
+EXPORT_SYMBOL(reservation_object_add_shared_fence);
+
+void reservation_object_add_excl_fence(struct reservation_object *obj,
+ struct fence *fence)
+{
+ struct fence *old_fence = reservation_object_get_excl(obj);
+ struct reservation_object_list *old;
+ u32 i = 0;
+
+ old = reservation_object_get_list(obj);
+ if (old)
+ i = old->shared_count;
+
+ if (fence)
+ fence_get(fence);
+
+ preempt_disable();
+ write_seqcount_begin(&obj->seq);
+ /* write_seqcount_begin provides the necessary memory barrier */
+ RCU_INIT_POINTER(obj->fence_excl, fence);
+ if (old)
+ old->shared_count = 0;
+ write_seqcount_end(&obj->seq);
+ preempt_enable();
+
+ /* inplace update, no shared fences */
+ while (i--)
+ fence_put(rcu_dereference_protected(old->shared[i],
+ reservation_object_held(obj)));
+
+ if (old_fence)
+ fence_put(old_fence);
+}
+EXPORT_SYMBOL(reservation_object_add_excl_fence);
+
+int reservation_object_get_fences_rcu(struct reservation_object *obj,
+ struct fence **pfence_excl,
+ unsigned *pshared_count,
+ struct fence ***pshared)
+{
+ unsigned shared_count = 0;
+ unsigned retry = 1;
+ struct fence **shared = NULL, *fence_excl = NULL;
+ int ret = 0;
+
+ while (retry) {
+ struct reservation_object_list *fobj;
+ unsigned seq;
+
+ seq = read_seqcount_begin(&obj->seq);
+
+ rcu_read_lock();
+
+ fobj = rcu_dereference(obj->fence);
+ if (fobj) {
+ struct fence **nshared;
+ size_t sz = sizeof(*shared) * fobj->shared_max;
+
+ nshared = krealloc(shared, sz,
+ GFP_NOWAIT | __GFP_NOWARN);
+ if (!nshared) {
+ rcu_read_unlock();
+ nshared = krealloc(shared, sz, GFP_KERNEL);
+ if (nshared) {
+ shared = nshared;
+ continue;
+ }
+
+ ret = -ENOMEM;
+ shared_count = 0;
+ break;
+ }
+ shared = nshared;
+ memcpy(shared, fobj->shared, sz);
+ shared_count = fobj->shared_count;
+ } else
+ shared_count = 0;
+ fence_excl = rcu_dereference(obj->fence_excl);
+
+ retry = read_seqcount_retry(&obj->seq, seq);
+ if (retry)
+ goto unlock;
+
+ if (!fence_excl || fence_get_rcu(fence_excl)) {
+ unsigned i;
+
+ for (i = 0; i < shared_count; ++i) {
+ if (fence_get_rcu(shared[i]))
+ continue;
+
+ /* uh oh, refcount failed, abort and retry */
+ while (i--)
+ fence_put(shared[i]);
+
+ if (fence_excl) {
+ fence_put(fence_excl);
+ fence_excl = NULL;
+ }
+
+ retry = 1;
+ break;
+ }
+ } else
+ retry = 1;
+
+unlock:
+ rcu_read_unlock();
+ }
+ *pshared_count = shared_count;
+ if (shared_count)
+ *pshared = shared;
+ else {
+ *pshared = NULL;
+ kfree(shared);
+ }
+ *pfence_excl = fence_excl;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
+
+long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
+ bool wait_all, bool intr,
+ unsigned long timeout)
+{
+ struct fence *fence;
+ unsigned seq, shared_count, i = 0;
+ long ret = timeout;
+
+retry:
+ fence = NULL;
+ shared_count = 0;
+ seq = read_seqcount_begin(&obj->seq);
+ rcu_read_lock();
+
+ if (wait_all) {
+ struct reservation_object_list *fobj = rcu_dereference(obj->fence);
+
+ if (fobj)
+ shared_count = fobj->shared_count;
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto unlock_retry;
+
+ for (i = 0; i < shared_count; ++i) {
+ struct fence *lfence = rcu_dereference(fobj->shared[i]);
+
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags))
+ continue;
+
+ if (!fence_get_rcu(lfence))
+ goto unlock_retry;
+
+ if (fence_is_signaled(lfence)) {
+ fence_put(lfence);
+ continue;
+ }
+
+ fence = lfence;
+ break;
+ }
+ }
+
+ if (!shared_count) {
+ struct fence *fence_excl = rcu_dereference(obj->fence_excl);
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto unlock_retry;
+
+ if (fence_excl &&
+ !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) {
+ if (!fence_get_rcu(fence_excl))
+ goto unlock_retry;
+
+ if (fence_is_signaled(fence_excl))
+ fence_put(fence_excl);
+ else
+ fence = fence_excl;
+ }
+ }
+
+ rcu_read_unlock();
+ if (fence) {
+ ret = fence_wait_timeout(fence, intr, ret);
+ fence_put(fence);
+ if (ret > 0 && wait_all && (i + 1 < shared_count))
+ goto retry;
+ }
+ return ret;
+
+unlock_retry:
+ rcu_read_unlock();
+ goto retry;
+}
+EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu);
+
+
+static inline int
+reservation_object_test_signaled_single(struct fence *passed_fence)
+{
+ struct fence *fence, *lfence = passed_fence;
+ int ret = 1;
+
+ if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
+ int ret;
+
+ fence = fence_get_rcu(lfence);
+ if (!fence)
+ return -1;
+
+ ret = !!fence_is_signaled(fence);
+ fence_put(fence);
+ }
+ return ret;
+}
+
+bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
+ bool test_all)
+{
+ unsigned seq, shared_count;
+ int ret = true;
+
+retry:
+ shared_count = 0;
+ seq = read_seqcount_begin(&obj->seq);
+ rcu_read_lock();
+
+ if (test_all) {
+ unsigned i;
+
+ struct reservation_object_list *fobj = rcu_dereference(obj->fence);
+
+ if (fobj)
+ shared_count = fobj->shared_count;
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto unlock_retry;
+
+ for (i = 0; i < shared_count; ++i) {
+ struct fence *fence = rcu_dereference(fobj->shared[i]);
+
+ ret = reservation_object_test_signaled_single(fence);
+ if (ret < 0)
+ goto unlock_retry;
+ else if (!ret)
+ break;
+ }
+
+ /*
+ * There could be a read_seqcount_retry here, but nothing cares
+ * about whether it's the old or newer fence pointers that are
+ * signaled. That race could still have happened after checking
+ * read_seqcount_retry. If you care, use ww_mutex_lock.
+ */
+ }
+
+ if (!shared_count) {
+ struct fence *fence_excl = rcu_dereference(obj->fence_excl);
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto unlock_retry;
+
+ if (fence_excl) {
+ ret = reservation_object_test_signaled_single(fence_excl);
+ if (ret < 0)
+ goto unlock_retry;
+ }
+ }
+
+ rcu_read_unlock();
+ return ret;
+
+unlock_retry:
+ rcu_read_unlock();
+ goto retry;
+}
+EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu);
diff --git a/drivers/dma-buf/seqno-fence.c b/drivers/dma-buf/seqno-fence.c
new file mode 100644
index 000000000000..7d12a39a4b57
--- /dev/null
+++ b/drivers/dma-buf/seqno-fence.c
@@ -0,0 +1,73 @@
+/*
+ * seqno-fence, using a dma-buf to synchronize fencing
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Copyright (C) 2012-2014 Canonical Ltd
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Maarten Lankhorst <maarten.lankhorst@canonical.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.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/seqno-fence.h>
+
+static const char *seqno_fence_get_driver_name(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->get_driver_name(fence);
+}
+
+static const char *seqno_fence_get_timeline_name(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->get_timeline_name(fence);
+}
+
+static bool seqno_enable_signaling(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->enable_signaling(fence);
+}
+
+static bool seqno_signaled(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
+}
+
+static void seqno_release(struct fence *fence)
+{
+ struct seqno_fence *f = to_seqno_fence(fence);
+
+ dma_buf_put(f->sync_buf);
+ if (f->ops->release)
+ f->ops->release(fence);
+ else
+ fence_free(&f->base);
+}
+
+static signed long seqno_wait(struct fence *fence, bool intr, signed long timeout)
+{
+ struct seqno_fence *f = to_seqno_fence(fence);
+ return f->ops->wait(fence, intr, timeout);
+}
+
+const struct fence_ops seqno_fence_ops = {
+ .get_driver_name = seqno_fence_get_driver_name,
+ .get_timeline_name = seqno_fence_get_timeline_name,
+ .enable_signaling = seqno_enable_signaling,
+ .signaled = seqno_signaled,
+ .wait = seqno_wait,
+ .release = seqno_release,
+};
+EXPORT_SYMBOL(seqno_fence_ops);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 1eca7b9760e6..9b1ea0ef59af 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -33,6 +33,24 @@ if DMADEVICES
comment "DMA Devices"
+config INTEL_MIC_X100_DMA
+ tristate "Intel MIC X100 DMA Driver"
+ depends on 64BIT && X86 && INTEL_MIC_BUS
+ select DMA_ENGINE
+ help
+ This enables DMA support for the Intel Many Integrated Core
+ (MIC) family of PCIe form factor coprocessor X100 devices that
+ run a 64 bit Linux OS. This driver will be used by both MIC
+ host and card drivers.
+
+ If you are building host kernel with a MIC device or a card
+ kernel for a MIC device, then say M (recommended) or Y, else
+ say N. If unsure say N.
+
+ More information about the Intel MIC family as well as the Linux
+ OS and tools for MIC to use with this driver are available from
+ <http://software.intel.com/en-us/mic-developer>.
+
config INTEL_MID_DMAC
tristate "Intel MID DMA support for Peripheral DMA controllers"
depends on PCI && X86
@@ -375,6 +393,22 @@ config XILINX_VDMA
channels, Memory Mapped to Stream (MM2S) and Stream to
Memory Mapped (S2MM) for the data transfers.
+config DMA_SUN6I
+ tristate "Allwinner A31 SoCs DMA support"
+ depends on MACH_SUN6I || COMPILE_TEST
+ depends on RESET_CONTROLLER
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support for the DMA engine for Allwinner A31 SoCs.
+
+config NBPFAXI_DMA
+ tristate "Renesas Type-AXI NBPF DMA support"
+ select DMA_ENGINE
+ depends on ARM || COMPILE_TEST
+ help
+ Support for "Type-AXI" NBPF DMA IPs from Renesas
+
config DMA_ENGINE
bool
@@ -388,6 +422,7 @@ config DMA_ACPI
config DMA_OF
def_bool y
depends on OF
+ select DMA_ENGINE
comment "DMA Clients"
depends on DMA_ENGINE
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index c779e1eb2db2..c6adb925f0b9 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,5 +1,5 @@
-ccflags-$(CONFIG_DMADEVICES_DEBUG) := -DDEBUG
-ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
+subdir-ccflags-$(CONFIG_DMADEVICES_DEBUG) := -DDEBUG
+subdir-ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o
@@ -47,3 +47,6 @@ obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
obj-y += xilinx/
+obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
+obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o
+obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
diff --git a/drivers/dma/TODO b/drivers/dma/TODO
index 734ed0206cd5..b8045cd42ee1 100644
--- a/drivers/dma/TODO
+++ b/drivers/dma/TODO
@@ -7,7 +7,6 @@ TODO for slave dma
- imx-dma
- imx-sdma
- mxs-dma.c
- - dw_dmac
- intel_mid_dma
4. Check other subsystems for dma drivers and merge/move to dmaengine
5. Remove dma_slave_config's dma direction.
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 8114731a1c62..e34024b000a4 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1040,7 +1040,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
if (early_bytes) {
dev_vdbg(&pl08x->adev->dev,
- "%s byte width LLIs (remain 0x%08x)\n",
+ "%s byte width LLIs (remain 0x%08zx)\n",
__func__, bd.remainder);
prep_byte_width_lli(pl08x, &bd, &cctl, early_bytes,
num_llis++, &total_bytes);
@@ -1653,7 +1653,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
struct pl08x_driver_data *pl08x = plchan->host;
@@ -1662,7 +1662,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
dma_addr_t slave_addr;
dev_dbg(&pl08x->adev->dev,
- "%s prepare cyclic transaction of %d/%d bytes %s %s\n",
+ "%s prepare cyclic transaction of %zd/%zd bytes %s %s\n",
__func__, period_len, buf_len,
direction == DMA_MEM_TO_DEV ? "to" : "from",
plchan->name);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index c13a3bb0f594..ca9dd2613283 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -294,14 +294,16 @@ static int atc_get_bytes_left(struct dma_chan *chan)
ret = -EINVAL;
goto out;
}
- atchan->remain_desc -= (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
- << (desc_first->tx_width);
- if (atchan->remain_desc < 0) {
+
+ count = (desc_cur->lli.ctrla & ATC_BTSIZE_MAX)
+ << desc_first->tx_width;
+ if (atchan->remain_desc < count) {
ret = -EINVAL;
goto out;
- } else {
- ret = atchan->remain_desc;
}
+
+ atchan->remain_desc -= count;
+ ret = atchan->remain_desc;
} else {
/*
* Get residual bytes when current
@@ -893,12 +895,11 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
* @period_len: number of bytes for each period
* @direction: transfer direction, to or from device
* @flags: tx descriptor status flags
- * @context: transfer context (ignored)
*/
static struct dma_async_tx_descriptor *
atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct at_dma_chan *atchan = to_at_dma_chan(chan);
struct at_dma_slave *atslave = chan->private;
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index a03602164e3e..68007974961a 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -335,7 +335,7 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan)
static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
enum dma_slave_buswidth dev_width;
diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c
index 94c380f07538..6a9d89c93b1f 100644
--- a/drivers/dma/dma-jz4740.c
+++ b/drivers/dma/dma-jz4740.c
@@ -433,7 +433,7 @@ static struct dma_async_tx_descriptor *jz4740_dma_prep_slave_sg(
static struct dma_async_tx_descriptor *jz4740_dma_prep_dma_cyclic(
struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct jz4740_dmaengine_chan *chan = to_jz4740_dma_chan(c);
struct jz4740_dma_desc *desc;
@@ -614,4 +614,4 @@ module_platform_driver(jz4740_dma_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("JZ4740 DMA driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index a27ded53ab4f..1af731b83b3f 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -279,6 +279,19 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
channel_set_bit(dw, CH_EN, dwc->mask);
}
+static void dwc_dostart_first_queued(struct dw_dma_chan *dwc)
+{
+ struct dw_desc *desc;
+
+ if (list_empty(&dwc->queue))
+ return;
+
+ list_move(dwc->queue.next, &dwc->active_list);
+ desc = dwc_first_active(dwc);
+ dev_vdbg(chan2dev(&dwc->chan), "%s: started %u\n", __func__, desc->txd.cookie);
+ dwc_dostart(dwc, desc);
+}
+
/*----------------------------------------------------------------------*/
static void
@@ -335,10 +348,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
* the completed ones.
*/
list_splice_init(&dwc->active_list, &list);
- if (!list_empty(&dwc->queue)) {
- list_move(dwc->queue.next, &dwc->active_list);
- dwc_dostart(dwc, dwc_first_active(dwc));
- }
+ dwc_dostart_first_queued(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -467,10 +477,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
/* Try to continue after resetting the channel... */
dwc_chan_disable(dw, dwc);
- if (!list_empty(&dwc->queue)) {
- list_move(dwc->queue.next, &dwc->active_list);
- dwc_dostart(dwc, dwc_first_active(dwc));
- }
+ dwc_dostart_first_queued(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
}
@@ -677,17 +684,9 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
* possible, perhaps even appending to those already submitted
* for DMA. But this is hard to do in a race-free manner.
*/
- if (list_empty(&dwc->active_list)) {
- dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__,
- desc->txd.cookie);
- list_add_tail(&desc->desc_node, &dwc->active_list);
- dwc_dostart(dwc, dwc_first_active(dwc));
- } else {
- dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__,
- desc->txd.cookie);
- list_add_tail(&desc->desc_node, &dwc->queue);
- }
+ dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie);
+ list_add_tail(&desc->desc_node, &dwc->queue);
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1092,9 +1091,12 @@ dwc_tx_status(struct dma_chan *chan,
static void dwc_issue_pending(struct dma_chan *chan)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+ unsigned long flags;
- if (!list_empty(&dwc->queue))
- dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+ spin_lock_irqsave(&dwc->lock, flags);
+ if (list_empty(&dwc->active_list))
+ dwc_dostart_first_queued(dwc);
+ spin_unlock_irqrestore(&dwc->lock, flags);
}
static int dwc_alloc_chan_resources(struct dma_chan *chan)
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index d08c4dedef35..7b65633f495e 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/of.h>
#include <linux/platform_data/edma.h>
@@ -256,8 +257,13 @@ static int edma_terminate_all(struct edma_chan *echan)
* echan->edesc is NULL and exit.)
*/
if (echan->edesc) {
+ int cyclic = echan->edesc->cyclic;
echan->edesc = NULL;
edma_stop(echan->ch_num);
+ /* Move the cyclic channel back to default queue */
+ if (cyclic)
+ edma_assign_channel_eventq(echan->ch_num,
+ EVENTQ_DEFAULT);
}
vchan_get_all_descriptors(&echan->vchan, &head);
@@ -592,7 +598,7 @@ struct dma_async_tx_descriptor *edma_prep_dma_memcpy(
static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long tx_flags, void *context)
+ unsigned long tx_flags)
{
struct edma_chan *echan = to_edma_chan(chan);
struct device *dev = chan->device->dev;
@@ -718,12 +724,15 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
edesc->absync = ret;
/*
- * Enable interrupts for every period because callback
- * has to be called for every period.
+ * Enable period interrupt only if it is requested
*/
- edesc->pset[i].param.opt |= TCINTEN;
+ if (tx_flags & DMA_PREP_INTERRUPT)
+ edesc->pset[i].param.opt |= TCINTEN;
}
+ /* Place the cyclic channel to highest priority queue */
+ edma_assign_channel_eventq(echan->ch_num, EVENTQ_0);
+
return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
}
@@ -982,6 +991,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
#define EDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
static int edma_dma_device_slave_caps(struct dma_chan *dchan,
@@ -992,7 +1002,7 @@ static int edma_dma_device_slave_caps(struct dma_chan *dchan,
caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
caps->cmd_pause = true;
caps->cmd_terminate = true;
- caps->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+ caps->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
return 0;
}
@@ -1039,7 +1049,7 @@ static int edma_probe(struct platform_device *pdev)
ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
if (ecc->dummy_slot < 0) {
dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
- return -EIO;
+ return ecc->dummy_slot;
}
dma_cap_zero(ecc->dma_slave.cap_mask);
@@ -1124,7 +1134,7 @@ static int edma_init(void)
}
}
- if (EDMA_CTLRS == 2) {
+ if (!of_have_populated_dt() && EDMA_CTLRS == 2) {
pdev1 = platform_device_register_full(&edma_dev_info1);
if (IS_ERR(pdev1)) {
platform_driver_unregister(&edma_driver);
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index cb4bf682a708..7650470196c4 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -1092,7 +1092,6 @@ fail:
* @period_len: length of a single period
* @dir: direction of the operation
* @flags: tx descriptor status flags
- * @context: operation context (ignored)
*
* Prepares a descriptor for cyclic DMA operation. This means that once the
* descriptor is submitted, we will be submitting in a @period_len sized
@@ -1105,8 +1104,7 @@ fail:
static struct dma_async_tx_descriptor *
ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
size_t buf_len, size_t period_len,
- enum dma_transfer_direction dir, unsigned long flags,
- void *context)
+ enum dma_transfer_direction dir, unsigned long flags)
{
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
struct ep93xx_dma_desc *desc, *first;
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index b396a7fb53ab..3c5711d5fe97 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -248,11 +248,12 @@ static void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
unsigned int slot, bool enable)
{
u32 ch = fsl_chan->vchan.chan.chan_id;
- void __iomem *muxaddr = fsl_chan->edma->muxbase[ch / DMAMUX_NR];
+ void __iomem *muxaddr;
unsigned chans_per_mux, ch_off;
chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
+ muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
if (enable)
edma_writeb(fsl_chan->edma,
@@ -516,7 +517,7 @@ err:
static struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
struct fsl_edma_desc *fsl_desc;
@@ -724,6 +725,7 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
{
struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
struct dma_chan *chan, *_chan;
+ unsigned long chans_per_mux = fsl_edma->n_chans / DMAMUX_NR;
if (dma_spec->args_count != 2)
return NULL;
@@ -732,7 +734,7 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
list_for_each_entry_safe(chan, _chan, &fsl_edma->dma_dev.channels, device_node) {
if (chan->client_count)
continue;
- if ((chan->chan_id / DMAMUX_NR) == dma_spec->args[0]) {
+ if ((chan->chan_id / chans_per_mux) == dma_spec->args[0]) {
chan = dma_get_slave_channel(chan);
if (chan) {
chan->device->privatecnt++;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index e0fec68aed25..d5d6885ab341 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -396,10 +396,17 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
struct fsldma_chan *chan = to_fsl_chan(tx->chan);
struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
struct fsl_desc_sw *child;
- unsigned long flags;
dma_cookie_t cookie = -EINVAL;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
+
+#ifdef CONFIG_PM
+ if (unlikely(chan->pm_state != RUNNING)) {
+ chan_dbg(chan, "cannot submit due to suspend\n");
+ spin_unlock_bh(&chan->desc_lock);
+ return -1;
+ }
+#endif
/*
* assign cookies to all of the software descriptors
@@ -412,7 +419,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
/* put this transaction onto the tail of the pending queue */
append_ld_queue(chan, desc);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return cookie;
}
@@ -459,6 +466,88 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
}
/**
+ * fsldma_clean_completed_descriptor - free all descriptors which
+ * has been completed and acked
+ * @chan: Freescale DMA channel
+ *
+ * This function is used on all completed and acked descriptors.
+ * All descriptors should only be freed in this function.
+ */
+static void fsldma_clean_completed_descriptor(struct fsldma_chan *chan)
+{
+ struct fsl_desc_sw *desc, *_desc;
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node)
+ if (async_tx_test_ack(&desc->async_tx))
+ fsl_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * fsldma_run_tx_complete_actions - cleanup a single link descriptor
+ * @chan: Freescale DMA channel
+ * @desc: descriptor to cleanup and free
+ * @cookie: Freescale DMA transaction identifier
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies.
+ */
+static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc, dma_cookie_t cookie)
+{
+ struct dma_async_tx_descriptor *txd = &desc->async_tx;
+ dma_cookie_t ret = cookie;
+
+ BUG_ON(txd->cookie < 0);
+
+ if (txd->cookie > 0) {
+ ret = txd->cookie;
+
+ /* Run the link descriptor callback function */
+ if (txd->callback) {
+ chan_dbg(chan, "LD %p callback\n", desc);
+ txd->callback(txd->callback_param);
+ }
+ }
+
+ /* Run any dependencies */
+ dma_run_dependencies(txd);
+
+ return ret;
+}
+
+/**
+ * fsldma_clean_running_descriptor - move the completed descriptor from
+ * ld_running to ld_completed
+ * @chan: Freescale DMA channel
+ * @desc: the descriptor which is completed
+ *
+ * Free the descriptor directly if acked by async_tx api, or move it to
+ * queue ld_completed.
+ */
+static void fsldma_clean_running_descriptor(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc)
+{
+ /* Remove from the list of transactions */
+ list_del(&desc->node);
+
+ /*
+ * the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!async_tx_test_ack(&desc->async_tx)) {
+ /*
+ * Move this descriptor to the list of descriptors which is
+ * completed, but still awaiting the 'ack' bit to be set.
+ */
+ list_add_tail(&desc->node, &chan->ld_completed);
+ return;
+ }
+
+ dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
+/**
* fsl_chan_xfer_ld_queue - transfer any pending transactions
* @chan : Freescale DMA channel
*
@@ -526,31 +615,58 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
}
/**
- * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
+ * fsldma_cleanup_descriptors - cleanup link descriptors which are completed
+ * and move them to ld_completed to free until flag 'ack' is set
* @chan: Freescale DMA channel
- * @desc: descriptor to cleanup and free
*
- * This function is used on a descriptor which has been executed by the DMA
- * controller. It will run any callbacks, submit any dependencies, and then
- * free the descriptor.
+ * This function is used on descriptors which have been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, then
+ * free these descriptors if flag 'ack' is set.
*/
-static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
- struct fsl_desc_sw *desc)
+static void fsldma_cleanup_descriptors(struct fsldma_chan *chan)
{
- struct dma_async_tx_descriptor *txd = &desc->async_tx;
+ struct fsl_desc_sw *desc, *_desc;
+ dma_cookie_t cookie = 0;
+ dma_addr_t curr_phys = get_cdar(chan);
+ int seen_current = 0;
+
+ fsldma_clean_completed_descriptor(chan);
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ /*
+ * do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /*
+ * stop the search if we reach the current descriptor and the
+ * channel is busy
+ */
+ if (desc->async_tx.phys == curr_phys) {
+ seen_current = 1;
+ if (!dma_is_idle(chan))
+ break;
+ }
+
+ cookie = fsldma_run_tx_complete_actions(chan, desc, cookie);
- /* Run the link descriptor callback function */
- if (txd->callback) {
- chan_dbg(chan, "LD %p callback\n", desc);
- txd->callback(txd->callback_param);
+ fsldma_clean_running_descriptor(chan, desc);
}
- /* Run any dependencies */
- dma_run_dependencies(txd);
+ /*
+ * Start any pending transactions automatically
+ *
+ * In the ideal case, we keep the DMA controller busy while we go
+ * ahead and free the descriptors below.
+ */
+ fsl_chan_xfer_ld_queue(chan);
- dma_descriptor_unmap(txd);
- chan_dbg(chan, "LD %p free\n", desc);
- dma_pool_free(chan->desc_pool, desc, txd->phys);
+ if (cookie > 0)
+ chan->common.completed_cookie = cookie;
}
/**
@@ -617,13 +733,14 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
chan_dbg(chan, "free all channel resources\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
+ spin_unlock_bh(&chan->desc_lock);
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
@@ -842,7 +959,6 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
{
struct dma_slave_config *config;
struct fsldma_chan *chan;
- unsigned long flags;
int size;
if (!dchan)
@@ -852,7 +968,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
switch (cmd) {
case DMA_TERMINATE_ALL:
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/* Halt the DMA engine */
dma_halt(chan);
@@ -860,9 +976,10 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
/* Remove and free all of the descriptors in the LD queue */
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
chan->idle = true;
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return 0;
case DMA_SLAVE_CONFIG:
@@ -904,11 +1021,10 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
}
/**
@@ -919,6 +1035,17 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
+ struct fsldma_chan *chan = to_fsl_chan(dchan);
+ enum dma_status ret;
+
+ ret = dma_cookie_status(dchan, cookie, txstate);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
+ spin_unlock_bh(&chan->desc_lock);
+
return dma_cookie_status(dchan, cookie, txstate);
}
@@ -996,52 +1123,18 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
static void dma_do_tasklet(unsigned long data)
{
struct fsldma_chan *chan = (struct fsldma_chan *)data;
- struct fsl_desc_sw *desc, *_desc;
- LIST_HEAD(ld_cleanup);
- unsigned long flags;
chan_dbg(chan, "tasklet entry\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
-
- /* update the cookie if we have some descriptors to cleanup */
- if (!list_empty(&chan->ld_running)) {
- dma_cookie_t cookie;
-
- desc = to_fsl_desc(chan->ld_running.prev);
- cookie = desc->async_tx.cookie;
- dma_cookie_complete(&desc->async_tx);
-
- chan_dbg(chan, "completed_cookie=%d\n", cookie);
- }
-
- /*
- * move the descriptors to a temporary list so we can drop the lock
- * during the entire cleanup operation
- */
- list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+ spin_lock_bh(&chan->desc_lock);
/* the hardware is now idle and ready for more */
chan->idle = true;
- /*
- * Start any pending transactions automatically
- *
- * In the ideal case, we keep the DMA controller busy while we go
- * ahead and free the descriptors below.
- */
- fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
-
- /* Run the callback for each descriptor, in order */
- list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
-
- /* Remove from the list of transactions */
- list_del(&desc->node);
+ /* Run all cleanup for descriptors which have been completed */
+ fsldma_cleanup_descriptors(chan);
- /* Run all cleanup for this descriptor */
- fsldma_cleanup_descriptor(chan, desc);
- }
+ spin_unlock_bh(&chan->desc_lock);
chan_dbg(chan, "tasklet exit\n");
}
@@ -1225,7 +1318,11 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
spin_lock_init(&chan->desc_lock);
INIT_LIST_HEAD(&chan->ld_pending);
INIT_LIST_HEAD(&chan->ld_running);
+ INIT_LIST_HEAD(&chan->ld_completed);
chan->idle = true;
+#ifdef CONFIG_PM
+ chan->pm_state = RUNNING;
+#endif
chan->common.device = &fdev->common;
dma_cookie_init(&chan->common);
@@ -1365,6 +1462,69 @@ static int fsldma_of_remove(struct platform_device *op)
return 0;
}
+#ifdef CONFIG_PM
+static int fsldma_suspend_late(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_chan *chan;
+ int i;
+
+ for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+
+ spin_lock_bh(&chan->desc_lock);
+ if (unlikely(!chan->idle))
+ goto out;
+ chan->regs_save.mr = get_mr(chan);
+ chan->pm_state = SUSPENDED;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+ return 0;
+
+out:
+ for (; i >= 0; i--) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+ chan->pm_state = RUNNING;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+ return -EBUSY;
+}
+
+static int fsldma_resume_early(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_chan *chan;
+ u32 mode;
+ int i;
+
+ for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+
+ spin_lock_bh(&chan->desc_lock);
+ mode = chan->regs_save.mr
+ & ~FSL_DMA_MR_CS & ~FSL_DMA_MR_CC & ~FSL_DMA_MR_CA;
+ set_mr(chan, mode);
+ chan->pm_state = RUNNING;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops fsldma_pm_ops = {
+ .suspend_late = fsldma_suspend_late,
+ .resume_early = fsldma_resume_early,
+};
+#endif
+
static const struct of_device_id fsldma_of_ids[] = {
{ .compatible = "fsl,elo3-dma", },
{ .compatible = "fsl,eloplus-dma", },
@@ -1377,6 +1537,9 @@ static struct platform_driver fsldma_of_driver = {
.name = "fsl-elo-dma",
.owner = THIS_MODULE,
.of_match_table = fsldma_of_ids,
+#ifdef CONFIG_PM
+ .pm = &fsldma_pm_ops,
+#endif
},
.probe = fsldma_of_probe,
.remove = fsldma_of_remove,
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index d56e83599825..239c20c84382 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -134,12 +134,36 @@ struct fsldma_device {
#define FSL_DMA_CHAN_PAUSE_EXT 0x00001000
#define FSL_DMA_CHAN_START_EXT 0x00002000
+#ifdef CONFIG_PM
+struct fsldma_chan_regs_save {
+ u32 mr;
+};
+
+enum fsldma_pm_state {
+ RUNNING = 0,
+ SUSPENDED,
+};
+#endif
+
struct fsldma_chan {
char name[8]; /* Channel name */
struct fsldma_chan_regs __iomem *regs;
spinlock_t desc_lock; /* Descriptor operation lock */
- struct list_head ld_pending; /* Link descriptors queue */
- struct list_head ld_running; /* Link descriptors queue */
+ /*
+ * Descriptors which are queued to run, but have not yet been
+ * submitted to the hardware for execution
+ */
+ struct list_head ld_pending;
+ /*
+ * Descriptors which are currently being executed by the hardware
+ */
+ struct list_head ld_running;
+ /*
+ * Descriptors which have finished execution by the hardware. These
+ * descriptors have already had their cleanup actions run. They are
+ * waiting for the ACK bit to be set by the async_tx API.
+ */
+ struct list_head ld_completed; /* Link descriptors queue */
struct dma_chan common; /* DMA common channel */
struct dma_pool *desc_pool; /* Descriptors pool */
struct device *dev; /* Channel device */
@@ -148,6 +172,10 @@ struct fsldma_chan {
struct tasklet_struct tasklet;
u32 feature;
bool idle; /* DMA controller is idle */
+#ifdef CONFIG_PM
+ struct fsldma_chan_regs_save regs_save;
+ enum fsldma_pm_state pm_state;
+#endif
void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 286660a12cc6..9d2c9e7374dc 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -866,7 +866,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
struct imxdma_engine *imxdma = imxdmac->imxdma;
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 14867e3ac8ff..f7626e37d0b8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -271,6 +271,7 @@ struct sdma_channel {
unsigned int chn_count;
unsigned int chn_real_count;
struct tasklet_struct tasklet;
+ struct imx_dma_data data;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -749,6 +750,11 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
emi_2_per = sdma->script_addrs->asrc_2_mcu_addr;
per_2_per = sdma->script_addrs->per_2_per_addr;
break;
+ case IMX_DMATYPE_ASRC_SP:
+ per_2_emi = sdma->script_addrs->shp_2_mcu_addr;
+ emi_2_per = sdma->script_addrs->mcu_2_shp_addr;
+ per_2_per = sdma->script_addrs->per_2_per_addr;
+ break;
case IMX_DMATYPE_MSHC:
per_2_emi = sdma->script_addrs->mshc_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_mshc_addr;
@@ -911,14 +917,13 @@ static int sdma_request_channel(struct sdma_channel *sdmac)
int channel = sdmac->channel;
int ret = -EBUSY;
- sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL);
+ sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+ GFP_KERNEL);
if (!sdmac->bd) {
ret = -ENOMEM;
goto out;
}
- memset(sdmac->bd, 0, PAGE_SIZE);
-
sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
@@ -1120,7 +1125,7 @@ err_out:
static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
@@ -1414,12 +1419,14 @@ err_dma_alloc:
static bool sdma_filter_fn(struct dma_chan *chan, void *fn_param)
{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
struct imx_dma_data *data = fn_param;
if (!imx_dma_is_general_purpose(chan))
return false;
- chan->private = data;
+ sdmac->data = *data;
+ chan->private = &sdmac->data;
return true;
}
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 128ca143486d..bbf62927bd72 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1532,11 +1532,17 @@ static int idmac_alloc_chan_resources(struct dma_chan *chan)
#ifdef DEBUG
if (chan->chan_id == IDMAC_IC_7) {
ic_sof = ipu_irq_map(69);
- if (ic_sof > 0)
- request_irq(ic_sof, ic_sof_irq, 0, "IC SOF", ichan);
+ if (ic_sof > 0) {
+ ret = request_irq(ic_sof, ic_sof_irq, 0, "IC SOF", ichan);
+ if (ret)
+ dev_err(&chan->dev->device, "request irq failed for IC SOF");
+ }
ic_eof = ipu_irq_map(70);
- if (ic_eof > 0)
- request_irq(ic_eof, ic_eof_irq, 0, "IC EOF", ichan);
+ if (ic_eof > 0) {
+ ret = request_irq(ic_eof, ic_eof_irq, 0, "IC EOF", ichan);
+ if (ret)
+ dev_err(&chan->dev->device, "request irq failed for IC EOF");
+ }
}
#endif
diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
new file mode 100644
index 000000000000..6de2e677be04
--- /dev/null
+++ b/drivers/dma/mic_x100_dma.c
@@ -0,0 +1,774 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC X100 DMA Driver.
+ *
+ * Adapted from IOAT dma driver.
+ */
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+
+#include "mic_x100_dma.h"
+
+#define MIC_DMA_MAX_XFER_SIZE_CARD (1 * 1024 * 1024 -\
+ MIC_DMA_ALIGN_BYTES)
+#define MIC_DMA_MAX_XFER_SIZE_HOST (1 * 1024 * 1024 >> 1)
+#define MIC_DMA_DESC_TYPE_SHIFT 60
+#define MIC_DMA_MEMCPY_LEN_SHIFT 46
+#define MIC_DMA_STAT_INTR_SHIFT 59
+
+/* high-water mark for pushing dma descriptors */
+static int mic_dma_pending_level = 4;
+
+/* Status descriptor is used to write a 64 bit value to a memory location */
+enum mic_dma_desc_format_type {
+ MIC_DMA_MEMCPY = 1,
+ MIC_DMA_STATUS,
+};
+
+static inline u32 mic_dma_hw_ring_inc(u32 val)
+{
+ return (val + 1) % MIC_DMA_DESC_RX_SIZE;
+}
+
+static inline u32 mic_dma_hw_ring_dec(u32 val)
+{
+ return val ? val - 1 : MIC_DMA_DESC_RX_SIZE - 1;
+}
+
+static inline void mic_dma_hw_ring_inc_head(struct mic_dma_chan *ch)
+{
+ ch->head = mic_dma_hw_ring_inc(ch->head);
+}
+
+/* Prepare a memcpy desc */
+static inline void mic_dma_memcpy_desc(struct mic_dma_desc *desc,
+ dma_addr_t src_phys, dma_addr_t dst_phys, u64 size)
+{
+ u64 qw0, qw1;
+
+ qw0 = src_phys;
+ qw0 |= (size >> MIC_DMA_ALIGN_SHIFT) << MIC_DMA_MEMCPY_LEN_SHIFT;
+ qw1 = MIC_DMA_MEMCPY;
+ qw1 <<= MIC_DMA_DESC_TYPE_SHIFT;
+ qw1 |= dst_phys;
+ desc->qw0 = qw0;
+ desc->qw1 = qw1;
+}
+
+/* Prepare a status desc. with @data to be written at @dst_phys */
+static inline void mic_dma_prep_status_desc(struct mic_dma_desc *desc, u64 data,
+ dma_addr_t dst_phys, bool generate_intr)
+{
+ u64 qw0, qw1;
+
+ qw0 = data;
+ qw1 = (u64) MIC_DMA_STATUS << MIC_DMA_DESC_TYPE_SHIFT | dst_phys;
+ if (generate_intr)
+ qw1 |= (1ULL << MIC_DMA_STAT_INTR_SHIFT);
+ desc->qw0 = qw0;
+ desc->qw1 = qw1;
+}
+
+static void mic_dma_cleanup(struct mic_dma_chan *ch)
+{
+ struct dma_async_tx_descriptor *tx;
+ u32 tail;
+ u32 last_tail;
+
+ spin_lock(&ch->cleanup_lock);
+ tail = mic_dma_read_cmp_cnt(ch);
+ /*
+ * This is the barrier pair for smp_wmb() in fn.
+ * mic_dma_tx_submit_unlock. It's required so that we read the
+ * updated cookie value from tx->cookie.
+ */
+ smp_rmb();
+ for (last_tail = ch->last_tail; tail != last_tail;) {
+ tx = &ch->tx_array[last_tail];
+ if (tx->cookie) {
+ dma_cookie_complete(tx);
+ if (tx->callback) {
+ tx->callback(tx->callback_param);
+ tx->callback = NULL;
+ }
+ }
+ last_tail = mic_dma_hw_ring_inc(last_tail);
+ }
+ /* finish all completion callbacks before incrementing tail */
+ smp_mb();
+ ch->last_tail = last_tail;
+ spin_unlock(&ch->cleanup_lock);
+}
+
+static u32 mic_dma_ring_count(u32 head, u32 tail)
+{
+ u32 count;
+
+ if (head >= tail)
+ count = (tail - 0) + (MIC_DMA_DESC_RX_SIZE - head);
+ else
+ count = tail - head;
+ return count - 1;
+}
+
+/* Returns the num. of free descriptors on success, -ENOMEM on failure */
+static int mic_dma_avail_desc_ring_space(struct mic_dma_chan *ch, int required)
+{
+ struct device *dev = mic_dma_ch_to_device(ch);
+ u32 count;
+
+ count = mic_dma_ring_count(ch->head, ch->last_tail);
+ if (count < required) {
+ mic_dma_cleanup(ch);
+ count = mic_dma_ring_count(ch->head, ch->last_tail);
+ }
+
+ if (count < required) {
+ dev_dbg(dev, "Not enough desc space");
+ dev_dbg(dev, "%s %d required=%u, avail=%u\n",
+ __func__, __LINE__, required, count);
+ return -ENOMEM;
+ } else {
+ return count;
+ }
+}
+
+/* Program memcpy descriptors into the descriptor ring and update s/w head ptr*/
+static int mic_dma_prog_memcpy_desc(struct mic_dma_chan *ch, dma_addr_t src,
+ dma_addr_t dst, size_t len)
+{
+ size_t current_transfer_len;
+ size_t max_xfer_size = to_mic_dma_dev(ch)->max_xfer_size;
+ /* 3 is added to make sure we have enough space for status desc */
+ int num_desc = len / max_xfer_size + 3;
+ int ret;
+
+ if (len % max_xfer_size)
+ num_desc++;
+
+ ret = mic_dma_avail_desc_ring_space(ch, num_desc);
+ if (ret < 0)
+ return ret;
+ do {
+ current_transfer_len = min(len, max_xfer_size);
+ mic_dma_memcpy_desc(&ch->desc_ring[ch->head],
+ src, dst, current_transfer_len);
+ mic_dma_hw_ring_inc_head(ch);
+ len -= current_transfer_len;
+ dst = dst + current_transfer_len;
+ src = src + current_transfer_len;
+ } while (len > 0);
+ return 0;
+}
+
+/* It's a h/w quirk and h/w needs 2 status descriptors for every status desc */
+static void mic_dma_prog_intr(struct mic_dma_chan *ch)
+{
+ mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+ ch->status_dest_micpa, false);
+ mic_dma_hw_ring_inc_head(ch);
+ mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+ ch->status_dest_micpa, true);
+ mic_dma_hw_ring_inc_head(ch);
+}
+
+/* Wrapper function to program memcpy descriptors/status descriptors */
+static int mic_dma_do_dma(struct mic_dma_chan *ch, int flags, dma_addr_t src,
+ dma_addr_t dst, size_t len)
+{
+ if (-ENOMEM == mic_dma_prog_memcpy_desc(ch, src, dst, len))
+ return -ENOMEM;
+ /* Above mic_dma_prog_memcpy_desc() makes sure we have enough space */
+ if (flags & DMA_PREP_FENCE) {
+ mic_dma_prep_status_desc(&ch->desc_ring[ch->head], 0,
+ ch->status_dest_micpa, false);
+ mic_dma_hw_ring_inc_head(ch);
+ }
+
+ if (flags & DMA_PREP_INTERRUPT)
+ mic_dma_prog_intr(ch);
+
+ return 0;
+}
+
+static inline void mic_dma_issue_pending(struct dma_chan *ch)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+
+ spin_lock(&mic_ch->issue_lock);
+ /*
+ * Write to head triggers h/w to act on the descriptors.
+ * On MIC, writing the same head value twice causes
+ * a h/w error. On second write, h/w assumes we filled
+ * the entire ring & overwrote some of the descriptors.
+ */
+ if (mic_ch->issued == mic_ch->submitted)
+ goto out;
+ mic_ch->issued = mic_ch->submitted;
+ /*
+ * make descriptor updates visible before advancing head,
+ * this is purposefully not smp_wmb() since we are also
+ * publishing the descriptor updates to a dma device
+ */
+ wmb();
+ mic_dma_write_reg(mic_ch, MIC_DMA_REG_DHPR, mic_ch->issued);
+out:
+ spin_unlock(&mic_ch->issue_lock);
+}
+
+static inline void mic_dma_update_pending(struct mic_dma_chan *ch)
+{
+ if (mic_dma_ring_count(ch->issued, ch->submitted)
+ > mic_dma_pending_level)
+ mic_dma_issue_pending(&ch->api_ch);
+}
+
+static dma_cookie_t mic_dma_tx_submit_unlock(struct dma_async_tx_descriptor *tx)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(tx->chan);
+ dma_cookie_t cookie;
+
+ dma_cookie_assign(tx);
+ cookie = tx->cookie;
+ /*
+ * We need an smp write barrier here because another CPU might see
+ * an update to submitted and update h/w head even before we
+ * assigned a cookie to this tx.
+ */
+ smp_wmb();
+ mic_ch->submitted = mic_ch->head;
+ spin_unlock(&mic_ch->prep_lock);
+ mic_dma_update_pending(mic_ch);
+ return cookie;
+}
+
+static inline struct dma_async_tx_descriptor *
+allocate_tx(struct mic_dma_chan *ch)
+{
+ u32 idx = mic_dma_hw_ring_dec(ch->head);
+ struct dma_async_tx_descriptor *tx = &ch->tx_array[idx];
+
+ dma_async_tx_descriptor_init(tx, &ch->api_ch);
+ tx->tx_submit = mic_dma_tx_submit_unlock;
+ return tx;
+}
+
+/*
+ * Prepare a memcpy descriptor to be added to the ring.
+ * Note that the temporary descriptor adds an extra overhead of copying the
+ * descriptor to ring. So, we copy directly to the descriptor ring
+ */
+static struct dma_async_tx_descriptor *
+mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest,
+ dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+ struct device *dev = mic_dma_ch_to_device(mic_ch);
+ int result;
+
+ if (!len && !flags)
+ return NULL;
+
+ spin_lock(&mic_ch->prep_lock);
+ result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len);
+ if (result >= 0)
+ return allocate_tx(mic_ch);
+ dev_err(dev, "Error enqueueing dma, error=%d\n", result);
+ spin_unlock(&mic_ch->prep_lock);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mic_dma_prep_interrupt_lock(struct dma_chan *ch, unsigned long flags)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+ int ret;
+
+ spin_lock(&mic_ch->prep_lock);
+ ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0);
+ if (!ret)
+ return allocate_tx(mic_ch);
+ spin_unlock(&mic_ch->prep_lock);
+ return NULL;
+}
+
+/* Return the status of the transaction */
+static enum dma_status
+mic_dma_tx_status(struct dma_chan *ch, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+
+ if (DMA_COMPLETE != dma_cookie_status(ch, cookie, txstate))
+ mic_dma_cleanup(mic_ch);
+
+ return dma_cookie_status(ch, cookie, txstate);
+}
+
+static irqreturn_t mic_dma_thread_fn(int irq, void *data)
+{
+ mic_dma_cleanup((struct mic_dma_chan *)data);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mic_dma_intr_handler(int irq, void *data)
+{
+ struct mic_dma_chan *ch = ((struct mic_dma_chan *)data);
+
+ mic_dma_ack_interrupt(ch);
+ return IRQ_WAKE_THREAD;
+}
+
+static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch)
+{
+ u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
+ struct device *dev = &to_mbus_device(ch)->dev;
+
+ desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
+ ch->desc_ring = kzalloc(desc_ring_size, GFP_KERNEL);
+
+ if (!ch->desc_ring)
+ return -ENOMEM;
+
+ ch->desc_ring_micpa = dma_map_single(dev, ch->desc_ring,
+ desc_ring_size, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, ch->desc_ring_micpa))
+ goto map_error;
+
+ ch->tx_array = vzalloc(MIC_DMA_DESC_RX_SIZE * sizeof(*ch->tx_array));
+ if (!ch->tx_array)
+ goto tx_error;
+ return 0;
+tx_error:
+ dma_unmap_single(dev, ch->desc_ring_micpa, desc_ring_size,
+ DMA_BIDIRECTIONAL);
+map_error:
+ kfree(ch->desc_ring);
+ return -ENOMEM;
+}
+
+static void mic_dma_free_desc_ring(struct mic_dma_chan *ch)
+{
+ u64 desc_ring_size = MIC_DMA_DESC_RX_SIZE * sizeof(*ch->desc_ring);
+
+ vfree(ch->tx_array);
+ desc_ring_size = ALIGN(desc_ring_size, MIC_DMA_ALIGN_BYTES);
+ dma_unmap_single(&to_mbus_device(ch)->dev, ch->desc_ring_micpa,
+ desc_ring_size, DMA_BIDIRECTIONAL);
+ kfree(ch->desc_ring);
+ ch->desc_ring = NULL;
+}
+
+static void mic_dma_free_status_dest(struct mic_dma_chan *ch)
+{
+ dma_unmap_single(&to_mbus_device(ch)->dev, ch->status_dest_micpa,
+ L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
+ kfree(ch->status_dest);
+}
+
+static int mic_dma_alloc_status_dest(struct mic_dma_chan *ch)
+{
+ struct device *dev = &to_mbus_device(ch)->dev;
+
+ ch->status_dest = kzalloc(L1_CACHE_BYTES, GFP_KERNEL);
+ if (!ch->status_dest)
+ return -ENOMEM;
+ ch->status_dest_micpa = dma_map_single(dev, ch->status_dest,
+ L1_CACHE_BYTES, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, ch->status_dest_micpa)) {
+ kfree(ch->status_dest);
+ ch->status_dest = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int mic_dma_check_chan(struct mic_dma_chan *ch)
+{
+ if (mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR) ||
+ mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) & MIC_DMA_CHAN_QUIESCE) {
+ mic_dma_disable_chan(ch);
+ mic_dma_chan_mask_intr(ch);
+ dev_err(mic_dma_ch_to_device(ch),
+ "%s %d error setting up mic dma chan %d\n",
+ __func__, __LINE__, ch->ch_num);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int mic_dma_chan_setup(struct mic_dma_chan *ch)
+{
+ if (MIC_DMA_CHAN_MIC == ch->owner)
+ mic_dma_chan_set_owner(ch);
+ mic_dma_disable_chan(ch);
+ mic_dma_chan_mask_intr(ch);
+ mic_dma_write_reg(ch, MIC_DMA_REG_DCHERRMSK, 0);
+ mic_dma_chan_set_desc_ring(ch);
+ ch->last_tail = mic_dma_read_reg(ch, MIC_DMA_REG_DTPR);
+ ch->head = ch->last_tail;
+ ch->issued = 0;
+ mic_dma_chan_unmask_intr(ch);
+ mic_dma_enable_chan(ch);
+ return mic_dma_check_chan(ch);
+}
+
+static void mic_dma_chan_destroy(struct mic_dma_chan *ch)
+{
+ mic_dma_disable_chan(ch);
+ mic_dma_chan_mask_intr(ch);
+}
+
+static void mic_dma_unregister_dma_device(struct mic_dma_device *mic_dma_dev)
+{
+ dma_async_device_unregister(&mic_dma_dev->dma_dev);
+}
+
+static int mic_dma_setup_irq(struct mic_dma_chan *ch)
+{
+ ch->cookie =
+ to_mbus_hw_ops(ch)->request_threaded_irq(to_mbus_device(ch),
+ mic_dma_intr_handler, mic_dma_thread_fn,
+ "mic dma_channel", ch, ch->ch_num);
+ if (IS_ERR(ch->cookie))
+ return IS_ERR(ch->cookie);
+ return 0;
+}
+
+static inline void mic_dma_free_irq(struct mic_dma_chan *ch)
+{
+ to_mbus_hw_ops(ch)->free_irq(to_mbus_device(ch), ch->cookie, ch);
+}
+
+static int mic_dma_chan_init(struct mic_dma_chan *ch)
+{
+ int ret = mic_dma_alloc_desc_ring(ch);
+
+ if (ret)
+ goto ring_error;
+ ret = mic_dma_alloc_status_dest(ch);
+ if (ret)
+ goto status_error;
+ ret = mic_dma_chan_setup(ch);
+ if (ret)
+ goto chan_error;
+ return ret;
+chan_error:
+ mic_dma_free_status_dest(ch);
+status_error:
+ mic_dma_free_desc_ring(ch);
+ring_error:
+ return ret;
+}
+
+static int mic_dma_drain_chan(struct mic_dma_chan *ch)
+{
+ struct dma_async_tx_descriptor *tx;
+ int err = 0;
+ dma_cookie_t cookie;
+
+ tx = mic_dma_prep_memcpy_lock(&ch->api_ch, 0, 0, 0, DMA_PREP_FENCE);
+ if (!tx) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie))
+ err = -ENOMEM;
+ else
+ err = dma_sync_wait(&ch->api_ch, cookie);
+ if (err) {
+ dev_err(mic_dma_ch_to_device(ch), "%s %d TO chan 0x%x\n",
+ __func__, __LINE__, ch->ch_num);
+ err = -EIO;
+ }
+error:
+ mic_dma_cleanup(ch);
+ return err;
+}
+
+static inline void mic_dma_chan_uninit(struct mic_dma_chan *ch)
+{
+ mic_dma_chan_destroy(ch);
+ mic_dma_cleanup(ch);
+ mic_dma_free_status_dest(ch);
+ mic_dma_free_desc_ring(ch);
+}
+
+static int mic_dma_init(struct mic_dma_device *mic_dma_dev,
+ enum mic_dma_chan_owner owner)
+{
+ int i, first_chan = mic_dma_dev->start_ch;
+ struct mic_dma_chan *ch;
+ int ret;
+
+ for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+ unsigned long data;
+ ch = &mic_dma_dev->mic_ch[i];
+ data = (unsigned long)ch;
+ ch->ch_num = i;
+ ch->owner = owner;
+ spin_lock_init(&ch->cleanup_lock);
+ spin_lock_init(&ch->prep_lock);
+ spin_lock_init(&ch->issue_lock);
+ ret = mic_dma_setup_irq(ch);
+ if (ret)
+ goto error;
+ }
+ return 0;
+error:
+ for (i = i - 1; i >= first_chan; i--)
+ mic_dma_free_irq(ch);
+ return ret;
+}
+
+static void mic_dma_uninit(struct mic_dma_device *mic_dma_dev)
+{
+ int i, first_chan = mic_dma_dev->start_ch;
+ struct mic_dma_chan *ch;
+
+ for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+ ch = &mic_dma_dev->mic_ch[i];
+ mic_dma_free_irq(ch);
+ }
+}
+
+static int mic_dma_alloc_chan_resources(struct dma_chan *ch)
+{
+ int ret = mic_dma_chan_init(to_mic_dma_chan(ch));
+ if (ret)
+ return ret;
+ return MIC_DMA_DESC_RX_SIZE;
+}
+
+static void mic_dma_free_chan_resources(struct dma_chan *ch)
+{
+ struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch);
+ mic_dma_drain_chan(mic_ch);
+ mic_dma_chan_uninit(mic_ch);
+}
+
+/* Set the fn. handlers and register the dma device with dma api */
+static int mic_dma_register_dma_device(struct mic_dma_device *mic_dma_dev,
+ enum mic_dma_chan_owner owner)
+{
+ int i, first_chan = mic_dma_dev->start_ch;
+
+ dma_cap_zero(mic_dma_dev->dma_dev.cap_mask);
+ /*
+ * This dma engine is not capable of host memory to host memory
+ * transfers
+ */
+ dma_cap_set(DMA_MEMCPY, mic_dma_dev->dma_dev.cap_mask);
+
+ if (MIC_DMA_CHAN_HOST == owner)
+ dma_cap_set(DMA_PRIVATE, mic_dma_dev->dma_dev.cap_mask);
+ mic_dma_dev->dma_dev.device_alloc_chan_resources =
+ mic_dma_alloc_chan_resources;
+ mic_dma_dev->dma_dev.device_free_chan_resources =
+ mic_dma_free_chan_resources;
+ mic_dma_dev->dma_dev.device_tx_status = mic_dma_tx_status;
+ mic_dma_dev->dma_dev.device_prep_dma_memcpy = mic_dma_prep_memcpy_lock;
+ mic_dma_dev->dma_dev.device_prep_dma_interrupt =
+ mic_dma_prep_interrupt_lock;
+ mic_dma_dev->dma_dev.device_issue_pending = mic_dma_issue_pending;
+ mic_dma_dev->dma_dev.copy_align = MIC_DMA_ALIGN_SHIFT;
+ INIT_LIST_HEAD(&mic_dma_dev->dma_dev.channels);
+ for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+ mic_dma_dev->mic_ch[i].api_ch.device = &mic_dma_dev->dma_dev;
+ dma_cookie_init(&mic_dma_dev->mic_ch[i].api_ch);
+ list_add_tail(&mic_dma_dev->mic_ch[i].api_ch.device_node,
+ &mic_dma_dev->dma_dev.channels);
+ }
+ return dma_async_device_register(&mic_dma_dev->dma_dev);
+}
+
+/*
+ * Initializes dma channels and registers the dma device with the
+ * dma engine api.
+ */
+static struct mic_dma_device *mic_dma_dev_reg(struct mbus_device *mbdev,
+ enum mic_dma_chan_owner owner)
+{
+ struct mic_dma_device *mic_dma_dev;
+ int ret;
+ struct device *dev = &mbdev->dev;
+
+ mic_dma_dev = kzalloc(sizeof(*mic_dma_dev), GFP_KERNEL);
+ if (!mic_dma_dev) {
+ ret = -ENOMEM;
+ goto alloc_error;
+ }
+ mic_dma_dev->mbdev = mbdev;
+ mic_dma_dev->dma_dev.dev = dev;
+ mic_dma_dev->mmio = mbdev->mmio_va;
+ if (MIC_DMA_CHAN_HOST == owner) {
+ mic_dma_dev->start_ch = 0;
+ mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_HOST;
+ } else {
+ mic_dma_dev->start_ch = 4;
+ mic_dma_dev->max_xfer_size = MIC_DMA_MAX_XFER_SIZE_CARD;
+ }
+ ret = mic_dma_init(mic_dma_dev, owner);
+ if (ret)
+ goto init_error;
+ ret = mic_dma_register_dma_device(mic_dma_dev, owner);
+ if (ret)
+ goto reg_error;
+ return mic_dma_dev;
+reg_error:
+ mic_dma_uninit(mic_dma_dev);
+init_error:
+ kfree(mic_dma_dev);
+ mic_dma_dev = NULL;
+alloc_error:
+ dev_err(dev, "Error at %s %d ret=%d\n", __func__, __LINE__, ret);
+ return mic_dma_dev;
+}
+
+static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev)
+{
+ mic_dma_unregister_dma_device(mic_dma_dev);
+ mic_dma_uninit(mic_dma_dev);
+ kfree(mic_dma_dev);
+}
+
+/* DEBUGFS CODE */
+static int mic_dma_reg_seq_show(struct seq_file *s, void *pos)
+{
+ struct mic_dma_device *mic_dma_dev = s->private;
+ int i, chan_num, first_chan = mic_dma_dev->start_ch;
+ struct mic_dma_chan *ch;
+
+ seq_printf(s, "SBOX_DCR: %#x\n",
+ mic_dma_mmio_read(&mic_dma_dev->mic_ch[first_chan],
+ MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR));
+ seq_puts(s, "DMA Channel Registers\n");
+ seq_printf(s, "%-10s| %-10s %-10s %-10s %-10s %-10s",
+ "Channel", "DCAR", "DTPR", "DHPR", "DRAR_HI", "DRAR_LO");
+ seq_printf(s, " %-11s %-14s %-10s\n", "DCHERR", "DCHERRMSK", "DSTAT");
+ for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
+ ch = &mic_dma_dev->mic_ch[i];
+ chan_num = ch->ch_num;
+ seq_printf(s, "%-10i| %-#10x %-#10x %-#10x %-#10x",
+ chan_num,
+ mic_dma_read_reg(ch, MIC_DMA_REG_DCAR),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DTPR),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DHPR),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_HI));
+ seq_printf(s, " %-#10x %-#10x %-#14x %-#10x\n",
+ mic_dma_read_reg(ch, MIC_DMA_REG_DRAR_LO),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DCHERR),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DCHERRMSK),
+ mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT));
+ }
+ return 0;
+}
+
+static int mic_dma_reg_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_dma_reg_seq_show, inode->i_private);
+}
+
+static int mic_dma_reg_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations mic_dma_reg_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_dma_reg_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_dma_reg_debug_release
+};
+
+/* Debugfs parent dir */
+static struct dentry *mic_dma_dbg;
+
+static int mic_dma_driver_probe(struct mbus_device *mbdev)
+{
+ struct mic_dma_device *mic_dma_dev;
+ enum mic_dma_chan_owner owner;
+
+ if (MBUS_DEV_DMA_MIC == mbdev->id.device)
+ owner = MIC_DMA_CHAN_MIC;
+ else
+ owner = MIC_DMA_CHAN_HOST;
+
+ mic_dma_dev = mic_dma_dev_reg(mbdev, owner);
+ dev_set_drvdata(&mbdev->dev, mic_dma_dev);
+
+ if (mic_dma_dbg) {
+ mic_dma_dev->dbg_dir = debugfs_create_dir(dev_name(&mbdev->dev),
+ mic_dma_dbg);
+ if (mic_dma_dev->dbg_dir)
+ debugfs_create_file("mic_dma_reg", 0444,
+ mic_dma_dev->dbg_dir, mic_dma_dev,
+ &mic_dma_reg_ops);
+ }
+ return 0;
+}
+
+static void mic_dma_driver_remove(struct mbus_device *mbdev)
+{
+ struct mic_dma_device *mic_dma_dev;
+
+ mic_dma_dev = dev_get_drvdata(&mbdev->dev);
+ debugfs_remove_recursive(mic_dma_dev->dbg_dir);
+ mic_dma_dev_unreg(mic_dma_dev);
+}
+
+static struct mbus_device_id id_table[] = {
+ {MBUS_DEV_DMA_MIC, MBUS_DEV_ANY_ID},
+ {MBUS_DEV_DMA_HOST, MBUS_DEV_ANY_ID},
+ {0},
+};
+
+static struct mbus_driver mic_dma_driver = {
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = mic_dma_driver_probe,
+ .remove = mic_dma_driver_remove,
+};
+
+static int __init mic_x100_dma_init(void)
+{
+ int rc = mbus_register_driver(&mic_dma_driver);
+ if (rc)
+ return rc;
+ mic_dma_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ return 0;
+}
+
+static void __exit mic_x100_dma_exit(void)
+{
+ debugfs_remove_recursive(mic_dma_dbg);
+ mbus_unregister_driver(&mic_dma_driver);
+}
+
+module_init(mic_x100_dma_init);
+module_exit(mic_x100_dma_exit);
+
+MODULE_DEVICE_TABLE(mbus, id_table);
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 DMA Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/mic_x100_dma.h b/drivers/dma/mic_x100_dma.h
new file mode 100644
index 000000000000..f663b0bdd11d
--- /dev/null
+++ b/drivers/dma/mic_x100_dma.h
@@ -0,0 +1,286 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC X100 DMA Driver.
+ *
+ * Adapted from IOAT dma driver.
+ */
+#ifndef _MIC_X100_DMA_H_
+#define _MIC_X100_DMA_H_
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/mic_bus.h>
+
+#include "dmaengine.h"
+
+/*
+ * MIC has a total of 8 dma channels.
+ * Four channels are assigned for host SW use & the remaining for MIC SW.
+ * MIC DMA transfer size & addresses need to be 64 byte aligned.
+ */
+#define MIC_DMA_MAX_NUM_CHAN 8
+#define MIC_DMA_NUM_CHAN 4
+#define MIC_DMA_ALIGN_SHIFT 6
+#define MIC_DMA_ALIGN_BYTES (1 << MIC_DMA_ALIGN_SHIFT)
+#define MIC_DMA_DESC_RX_SIZE (128 * 1024 - 4)
+
+/*
+ * Register descriptions
+ * All the registers are 32 bit registers.
+ * DCR is a global register and all others are per-channel.
+ * DCR - bits 0, 2, 4, 6, 8, 10, 12, 14 - enable bits for channels 0 to 7
+ * bits 1, 3, 5, 7, 9, 11, 13, 15 - owner bits for channels 0 to 7
+ * DCAR - bit 24 & 25 interrupt masks for mic owned & host owned channels
+ * DHPR - head of the descriptor ring updated by s/w
+ * DTPR - tail of the descriptor ring updated by h/w
+ * DRAR_LO - lower 32 bits of descriptor ring's mic address
+ * DRAR_HI - 3:0 - remaining 4 bits of descriptor ring's mic address
+ * 20:4 descriptor ring size
+ * 25:21 mic smpt entry number
+ * DSTAT - 16:0 h/w completion count; 31:28 dma engine status
+ * DCHERR - this register is non-zero on error
+ * DCHERRMSK - interrupt mask register
+ */
+#define MIC_DMA_HW_CMP_CNT_MASK 0x1ffff
+#define MIC_DMA_CHAN_QUIESCE 0x20000000
+#define MIC_DMA_SBOX_BASE 0x00010000
+#define MIC_DMA_SBOX_DCR 0x0000A280
+#define MIC_DMA_SBOX_CH_BASE 0x0001A000
+#define MIC_DMA_SBOX_CHAN_OFF 0x40
+#define MIC_DMA_SBOX_DCAR_IM0 (0x1 << 24)
+#define MIC_DMA_SBOX_DCAR_IM1 (0x1 << 25)
+#define MIC_DMA_SBOX_DRARHI_SYS_MASK (0x1 << 26)
+#define MIC_DMA_REG_DCAR 0
+#define MIC_DMA_REG_DHPR 4
+#define MIC_DMA_REG_DTPR 8
+#define MIC_DMA_REG_DRAR_LO 20
+#define MIC_DMA_REG_DRAR_HI 24
+#define MIC_DMA_REG_DSTAT 32
+#define MIC_DMA_REG_DCHERR 44
+#define MIC_DMA_REG_DCHERRMSK 48
+
+/* HW dma desc */
+struct mic_dma_desc {
+ u64 qw0;
+ u64 qw1;
+};
+
+enum mic_dma_chan_owner {
+ MIC_DMA_CHAN_MIC = 0,
+ MIC_DMA_CHAN_HOST
+};
+
+/*
+ * mic_dma_chan - channel specific information
+ * @ch_num: channel number
+ * @owner: owner of this channel
+ * @last_tail: cached value of descriptor ring tail
+ * @head: index of next descriptor in desc_ring
+ * @issued: hardware notification point
+ * @submitted: index that will be used to submit descriptors to h/w
+ * @api_ch: dma engine api channel
+ * @desc_ring: dma descriptor ring
+ * @desc_ring_micpa: mic physical address of desc_ring
+ * @status_dest: destination for status (fence) descriptor
+ * @status_dest_micpa: mic address for status_dest,
+ * DMA controller uses this address
+ * @tx_array: array of async_tx
+ * @cleanup_lock: lock held when processing completed tx
+ * @prep_lock: lock held in prep_memcpy & released in tx_submit
+ * @issue_lock: lock used to synchronize writes to head
+ * @cookie: mic_irq cookie used with mic irq request
+ */
+struct mic_dma_chan {
+ int ch_num;
+ enum mic_dma_chan_owner owner;
+ u32 last_tail;
+ u32 head;
+ u32 issued;
+ u32 submitted;
+ struct dma_chan api_ch;
+ struct mic_dma_desc *desc_ring;
+ dma_addr_t desc_ring_micpa;
+ u64 *status_dest;
+ dma_addr_t status_dest_micpa;
+ struct dma_async_tx_descriptor *tx_array;
+ spinlock_t cleanup_lock;
+ spinlock_t prep_lock;
+ spinlock_t issue_lock;
+ struct mic_irq *cookie;
+};
+
+/*
+ * struct mic_dma_device - per mic device
+ * @mic_ch: dma channels
+ * @dma_dev: underlying dma device
+ * @mbdev: mic bus dma device
+ * @mmio: virtual address of the mmio space
+ * @dbg_dir: debugfs directory
+ * @start_ch: first channel number that can be used
+ * @max_xfer_size: maximum transfer size per dma descriptor
+ */
+struct mic_dma_device {
+ struct mic_dma_chan mic_ch[MIC_DMA_MAX_NUM_CHAN];
+ struct dma_device dma_dev;
+ struct mbus_device *mbdev;
+ void __iomem *mmio;
+ struct dentry *dbg_dir;
+ int start_ch;
+ size_t max_xfer_size;
+};
+
+static inline struct mic_dma_chan *to_mic_dma_chan(struct dma_chan *ch)
+{
+ return container_of(ch, struct mic_dma_chan, api_ch);
+}
+
+static inline struct mic_dma_device *to_mic_dma_dev(struct mic_dma_chan *ch)
+{
+ return
+ container_of((const typeof(((struct mic_dma_device *)0)->mic_ch)*)
+ (ch - ch->ch_num), struct mic_dma_device, mic_ch);
+}
+
+static inline struct mbus_device *to_mbus_device(struct mic_dma_chan *ch)
+{
+ return to_mic_dma_dev(ch)->mbdev;
+}
+
+static inline struct mbus_hw_ops *to_mbus_hw_ops(struct mic_dma_chan *ch)
+{
+ return to_mbus_device(ch)->hw_ops;
+}
+
+static inline struct device *mic_dma_ch_to_device(struct mic_dma_chan *ch)
+{
+ return to_mic_dma_dev(ch)->dma_dev.dev;
+}
+
+static inline void __iomem *mic_dma_chan_to_mmio(struct mic_dma_chan *ch)
+{
+ return to_mic_dma_dev(ch)->mmio;
+}
+
+static inline u32 mic_dma_read_reg(struct mic_dma_chan *ch, u32 reg)
+{
+ return ioread32(mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
+ ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
+}
+
+static inline void mic_dma_write_reg(struct mic_dma_chan *ch, u32 reg, u32 val)
+{
+ iowrite32(val, mic_dma_chan_to_mmio(ch) + MIC_DMA_SBOX_CH_BASE +
+ ch->ch_num * MIC_DMA_SBOX_CHAN_OFF + reg);
+}
+
+static inline u32 mic_dma_mmio_read(struct mic_dma_chan *ch, u32 offset)
+{
+ return ioread32(mic_dma_chan_to_mmio(ch) + offset);
+}
+
+static inline void mic_dma_mmio_write(struct mic_dma_chan *ch, u32 val,
+ u32 offset)
+{
+ iowrite32(val, mic_dma_chan_to_mmio(ch) + offset);
+}
+
+static inline u32 mic_dma_read_cmp_cnt(struct mic_dma_chan *ch)
+{
+ return mic_dma_read_reg(ch, MIC_DMA_REG_DSTAT) &
+ MIC_DMA_HW_CMP_CNT_MASK;
+}
+
+static inline void mic_dma_chan_set_owner(struct mic_dma_chan *ch)
+{
+ u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+ u32 chan_num = ch->ch_num;
+
+ dcr = (dcr & ~(0x1 << (chan_num * 2))) | (ch->owner << (chan_num * 2));
+ mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static inline void mic_dma_enable_chan(struct mic_dma_chan *ch)
+{
+ u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+
+ dcr |= 2 << (ch->ch_num << 1);
+ mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static inline void mic_dma_disable_chan(struct mic_dma_chan *ch)
+{
+ u32 dcr = mic_dma_mmio_read(ch, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+
+ dcr &= ~(2 << (ch->ch_num << 1));
+ mic_dma_mmio_write(ch, dcr, MIC_DMA_SBOX_BASE + MIC_DMA_SBOX_DCR);
+}
+
+static void mic_dma_chan_set_desc_ring(struct mic_dma_chan *ch)
+{
+ u32 drar_hi;
+ dma_addr_t desc_ring_micpa = ch->desc_ring_micpa;
+
+ drar_hi = (MIC_DMA_DESC_RX_SIZE & 0x1ffff) << 4;
+ if (MIC_DMA_CHAN_MIC == ch->owner) {
+ drar_hi |= (desc_ring_micpa >> 32) & 0xf;
+ } else {
+ drar_hi |= MIC_DMA_SBOX_DRARHI_SYS_MASK;
+ drar_hi |= ((desc_ring_micpa >> 34)
+ & 0x1f) << 21;
+ drar_hi |= (desc_ring_micpa >> 32) & 0x3;
+ }
+ mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_LO, (u32) desc_ring_micpa);
+ mic_dma_write_reg(ch, MIC_DMA_REG_DRAR_HI, drar_hi);
+}
+
+static inline void mic_dma_chan_mask_intr(struct mic_dma_chan *ch)
+{
+ u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
+
+ if (MIC_DMA_CHAN_MIC == ch->owner)
+ dcar |= MIC_DMA_SBOX_DCAR_IM0;
+ else
+ dcar |= MIC_DMA_SBOX_DCAR_IM1;
+ mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
+}
+
+static inline void mic_dma_chan_unmask_intr(struct mic_dma_chan *ch)
+{
+ u32 dcar = mic_dma_read_reg(ch, MIC_DMA_REG_DCAR);
+
+ if (MIC_DMA_CHAN_MIC == ch->owner)
+ dcar &= ~MIC_DMA_SBOX_DCAR_IM0;
+ else
+ dcar &= ~MIC_DMA_SBOX_DCAR_IM1;
+ mic_dma_write_reg(ch, MIC_DMA_REG_DCAR, dcar);
+}
+
+static void mic_dma_ack_interrupt(struct mic_dma_chan *ch)
+{
+ if (MIC_DMA_CHAN_MIC == ch->owner) {
+ /* HW errata */
+ mic_dma_chan_mask_intr(ch);
+ mic_dma_chan_unmask_intr(ch);
+ }
+ to_mbus_hw_ops(ch)->ack_interrupt(to_mbus_device(ch), ch->ch_num);
+}
+#endif
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index a7b186d536b3..a1a4db5721b8 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -601,7 +601,7 @@ static struct dma_async_tx_descriptor *
mmp_pdma_prep_dma_cyclic(struct dma_chan *dchan,
dma_addr_t buf_addr, size_t len, size_t period_len,
enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct mmp_pdma_chan *chan;
struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index 724f7f4c9720..6ad30e2c5038 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -389,7 +389,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
struct mmp_tdma_desc *desc;
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2ad43738ac8b..881db2bcb48b 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -53,6 +53,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/of_dma.h>
#include <linux/of_platform.h>
#include <linux/random.h>
@@ -1036,7 +1037,15 @@ static int mpc_dma_probe(struct platform_device *op)
if (retval)
goto err_free2;
- return retval;
+ /* Register with OF helpers for DMA lookups (nonfatal) */
+ if (dev->of_node) {
+ retval = of_dma_controller_register(dev->of_node,
+ of_dma_xlate_by_chan_id, mdma);
+ if (retval)
+ dev_warn(dev, "Could not register for OF lookup\n");
+ }
+
+ return 0;
err_free2:
if (mdma->is_mpc8308)
@@ -1057,6 +1066,8 @@ static int mpc_dma_remove(struct platform_device *op)
struct device *dev = &op->dev;
struct mpc_dma *mdma = dev_get_drvdata(dev);
+ if (dev->of_node)
+ of_dma_controller_free(dev->of_node);
dma_async_device_unregister(&mdma->dma);
if (mdma->is_mpc8308) {
free_irq(mdma->irq2, mdma);
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index ead491346da7..5ea61201dbf0 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -413,16 +413,14 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int ret;
- mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
- CCW_BLOCK_SIZE, &mxs_chan->ccw_phys,
- GFP_KERNEL);
+ mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev,
+ CCW_BLOCK_SIZE,
+ &mxs_chan->ccw_phys, GFP_KERNEL);
if (!mxs_chan->ccw) {
ret = -ENOMEM;
goto err_alloc;
}
- memset(mxs_chan->ccw, 0, CCW_BLOCK_SIZE);
-
if (mxs_chan->chan_irq != NO_IRQ) {
ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
0, "mxs-dma", mxs_dma);
@@ -591,7 +589,7 @@ err_out:
static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c
new file mode 100644
index 000000000000..5aeada56a442
--- /dev/null
+++ b/drivers/dma/nbpfaxi.c
@@ -0,0 +1,1517 @@
+/*
+ * Copyright (C) 2013-2014 Renesas Electronics Europe Ltd.
+ * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/dma/nbpfaxi.h>
+
+#include "dmaengine.h"
+
+#define NBPF_REG_CHAN_OFFSET 0
+#define NBPF_REG_CHAN_SIZE 0x40
+
+/* Channel Current Transaction Byte register */
+#define NBPF_CHAN_CUR_TR_BYTE 0x20
+
+/* Channel Status register */
+#define NBPF_CHAN_STAT 0x24
+#define NBPF_CHAN_STAT_EN 1
+#define NBPF_CHAN_STAT_TACT 4
+#define NBPF_CHAN_STAT_ERR 0x10
+#define NBPF_CHAN_STAT_END 0x20
+#define NBPF_CHAN_STAT_TC 0x40
+#define NBPF_CHAN_STAT_DER 0x400
+
+/* Channel Control register */
+#define NBPF_CHAN_CTRL 0x28
+#define NBPF_CHAN_CTRL_SETEN 1
+#define NBPF_CHAN_CTRL_CLREN 2
+#define NBPF_CHAN_CTRL_STG 4
+#define NBPF_CHAN_CTRL_SWRST 8
+#define NBPF_CHAN_CTRL_CLRRQ 0x10
+#define NBPF_CHAN_CTRL_CLREND 0x20
+#define NBPF_CHAN_CTRL_CLRTC 0x40
+#define NBPF_CHAN_CTRL_SETSUS 0x100
+#define NBPF_CHAN_CTRL_CLRSUS 0x200
+
+/* Channel Configuration register */
+#define NBPF_CHAN_CFG 0x2c
+#define NBPF_CHAN_CFG_SEL 7 /* terminal SELect: 0..7 */
+#define NBPF_CHAN_CFG_REQD 8 /* REQuest Direction: DMAREQ is 0: input, 1: output */
+#define NBPF_CHAN_CFG_LOEN 0x10 /* LOw ENable: low DMA request line is: 0: inactive, 1: active */
+#define NBPF_CHAN_CFG_HIEN 0x20 /* HIgh ENable: high DMA request line is: 0: inactive, 1: active */
+#define NBPF_CHAN_CFG_LVL 0x40 /* LeVeL: DMA request line is sensed as 0: edge, 1: level */
+#define NBPF_CHAN_CFG_AM 0x700 /* ACK Mode: 0: Pulse mode, 1: Level mode, b'1x: Bus Cycle */
+#define NBPF_CHAN_CFG_SDS 0xf000 /* Source Data Size: 0: 8 bits,... , 7: 1024 bits */
+#define NBPF_CHAN_CFG_DDS 0xf0000 /* Destination Data Size: as above */
+#define NBPF_CHAN_CFG_SAD 0x100000 /* Source ADdress counting: 0: increment, 1: fixed */
+#define NBPF_CHAN_CFG_DAD 0x200000 /* Destination ADdress counting: 0: increment, 1: fixed */
+#define NBPF_CHAN_CFG_TM 0x400000 /* Transfer Mode: 0: single, 1: block TM */
+#define NBPF_CHAN_CFG_DEM 0x1000000 /* DMAEND interrupt Mask */
+#define NBPF_CHAN_CFG_TCM 0x2000000 /* DMATCO interrupt Mask */
+#define NBPF_CHAN_CFG_SBE 0x8000000 /* Sweep Buffer Enable */
+#define NBPF_CHAN_CFG_RSEL 0x10000000 /* RM: Register Set sELect */
+#define NBPF_CHAN_CFG_RSW 0x20000000 /* RM: Register Select sWitch */
+#define NBPF_CHAN_CFG_REN 0x40000000 /* RM: Register Set Enable */
+#define NBPF_CHAN_CFG_DMS 0x80000000 /* 0: register mode (RM), 1: link mode (LM) */
+
+#define NBPF_CHAN_NXLA 0x38
+#define NBPF_CHAN_CRLA 0x3c
+
+/* Link Header field */
+#define NBPF_HEADER_LV 1
+#define NBPF_HEADER_LE 2
+#define NBPF_HEADER_WBD 4
+#define NBPF_HEADER_DIM 8
+
+#define NBPF_CTRL 0x300
+#define NBPF_CTRL_PR 1 /* 0: fixed priority, 1: round robin */
+#define NBPF_CTRL_LVINT 2 /* DMAEND and DMAERR signalling: 0: pulse, 1: level */
+
+#define NBPF_DSTAT_ER 0x314
+#define NBPF_DSTAT_END 0x318
+
+#define NBPF_DMA_BUSWIDTHS \
+ (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
+ BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES))
+
+struct nbpf_config {
+ int num_channels;
+ int buffer_size;
+};
+
+/*
+ * We've got 3 types of objects, used to describe DMA transfers:
+ * 1. high-level descriptor, containing a struct dma_async_tx_descriptor object
+ * in it, used to communicate with the user
+ * 2. hardware DMA link descriptors, that we pass to DMAC for DMA transfer
+ * queuing, these must be DMAable, using either the streaming DMA API or
+ * allocated from coherent memory - one per SG segment
+ * 3. one per SG segment descriptors, used to manage HW link descriptors from
+ * (2). They do not have to be DMAable. They can either be (a) allocated
+ * together with link descriptors as mixed (DMA / CPU) objects, or (b)
+ * separately. Even if allocated separately it would be best to link them
+ * to link descriptors once during channel resource allocation and always
+ * use them as a single object.
+ * Therefore for both cases (a) and (b) at run-time objects (2) and (3) shall be
+ * treated as a single SG segment descriptor.
+ */
+
+struct nbpf_link_reg {
+ u32 header;
+ u32 src_addr;
+ u32 dst_addr;
+ u32 transaction_size;
+ u32 config;
+ u32 interval;
+ u32 extension;
+ u32 next;
+} __packed;
+
+struct nbpf_device;
+struct nbpf_channel;
+struct nbpf_desc;
+
+struct nbpf_link_desc {
+ struct nbpf_link_reg *hwdesc;
+ dma_addr_t hwdesc_dma_addr;
+ struct nbpf_desc *desc;
+ struct list_head node;
+};
+
+/**
+ * struct nbpf_desc - DMA transfer descriptor
+ * @async_tx: dmaengine object
+ * @user_wait: waiting for a user ack
+ * @length: total transfer length
+ * @sg: list of hardware descriptors, represented by struct nbpf_link_desc
+ * @node: member in channel descriptor lists
+ */
+struct nbpf_desc {
+ struct dma_async_tx_descriptor async_tx;
+ bool user_wait;
+ size_t length;
+ struct nbpf_channel *chan;
+ struct list_head sg;
+ struct list_head node;
+};
+
+/* Take a wild guess: allocate 4 segments per descriptor */
+#define NBPF_SEGMENTS_PER_DESC 4
+#define NBPF_DESCS_PER_PAGE ((PAGE_SIZE - sizeof(struct list_head)) / \
+ (sizeof(struct nbpf_desc) + \
+ NBPF_SEGMENTS_PER_DESC * \
+ (sizeof(struct nbpf_link_desc) + sizeof(struct nbpf_link_reg))))
+#define NBPF_SEGMENTS_PER_PAGE (NBPF_SEGMENTS_PER_DESC * NBPF_DESCS_PER_PAGE)
+
+struct nbpf_desc_page {
+ struct list_head node;
+ struct nbpf_desc desc[NBPF_DESCS_PER_PAGE];
+ struct nbpf_link_desc ldesc[NBPF_SEGMENTS_PER_PAGE];
+ struct nbpf_link_reg hwdesc[NBPF_SEGMENTS_PER_PAGE];
+};
+
+/**
+ * struct nbpf_channel - one DMAC channel
+ * @dma_chan: standard dmaengine channel object
+ * @base: register address base
+ * @nbpf: DMAC
+ * @name: IRQ name
+ * @irq: IRQ number
+ * @slave_addr: address for slave DMA
+ * @slave_width:slave data size in bytes
+ * @slave_burst:maximum slave burst size in bytes
+ * @terminal: DMA terminal, assigned to this channel
+ * @dmarq_cfg: DMA request line configuration - high / low, edge / level for NBPF_CHAN_CFG
+ * @flags: configuration flags from DT
+ * @lock: protect descriptor lists
+ * @free_links: list of free link descriptors
+ * @free: list of free descriptors
+ * @queued: list of queued descriptors
+ * @active: list of descriptors, scheduled for processing
+ * @done: list of completed descriptors, waiting post-processing
+ * @desc_page: list of additionally allocated descriptor pages - if any
+ */
+struct nbpf_channel {
+ struct dma_chan dma_chan;
+ struct tasklet_struct tasklet;
+ void __iomem *base;
+ struct nbpf_device *nbpf;
+ char name[16];
+ int irq;
+ dma_addr_t slave_src_addr;
+ size_t slave_src_width;
+ size_t slave_src_burst;
+ dma_addr_t slave_dst_addr;
+ size_t slave_dst_width;
+ size_t slave_dst_burst;
+ unsigned int terminal;
+ u32 dmarq_cfg;
+ unsigned long flags;
+ spinlock_t lock;
+ struct list_head free_links;
+ struct list_head free;
+ struct list_head queued;
+ struct list_head active;
+ struct list_head done;
+ struct list_head desc_page;
+ struct nbpf_desc *running;
+ bool paused;
+};
+
+struct nbpf_device {
+ struct dma_device dma_dev;
+ void __iomem *base;
+ struct clk *clk;
+ const struct nbpf_config *config;
+ struct nbpf_channel chan[];
+};
+
+enum nbpf_model {
+ NBPF1B4,
+ NBPF1B8,
+ NBPF1B16,
+ NBPF4B4,
+ NBPF4B8,
+ NBPF4B16,
+ NBPF8B4,
+ NBPF8B8,
+ NBPF8B16,
+};
+
+static struct nbpf_config nbpf_cfg[] = {
+ [NBPF1B4] = {
+ .num_channels = 1,
+ .buffer_size = 4,
+ },
+ [NBPF1B8] = {
+ .num_channels = 1,
+ .buffer_size = 8,
+ },
+ [NBPF1B16] = {
+ .num_channels = 1,
+ .buffer_size = 16,
+ },
+ [NBPF4B4] = {
+ .num_channels = 4,
+ .buffer_size = 4,
+ },
+ [NBPF4B8] = {
+ .num_channels = 4,
+ .buffer_size = 8,
+ },
+ [NBPF4B16] = {
+ .num_channels = 4,
+ .buffer_size = 16,
+ },
+ [NBPF8B4] = {
+ .num_channels = 8,
+ .buffer_size = 4,
+ },
+ [NBPF8B8] = {
+ .num_channels = 8,
+ .buffer_size = 8,
+ },
+ [NBPF8B16] = {
+ .num_channels = 8,
+ .buffer_size = 16,
+ },
+};
+
+#define nbpf_to_chan(d) container_of(d, struct nbpf_channel, dma_chan)
+
+/*
+ * dmaengine drivers seem to have a lot in common and instead of sharing more
+ * code, they reimplement those common algorithms independently. In this driver
+ * we try to separate the hardware-specific part from the (largely) generic
+ * part. This improves code readability and makes it possible in the future to
+ * reuse the generic code in form of a helper library. That generic code should
+ * be suitable for various DMA controllers, using transfer descriptors in RAM
+ * and pushing one SG list at a time to the DMA controller.
+ */
+
+/* Hardware-specific part */
+
+static inline u32 nbpf_chan_read(struct nbpf_channel *chan,
+ unsigned int offset)
+{
+ u32 data = ioread32(chan->base + offset);
+ dev_dbg(chan->dma_chan.device->dev, "%s(0x%p + 0x%x) = 0x%x\n",
+ __func__, chan->base, offset, data);
+ return data;
+}
+
+static inline void nbpf_chan_write(struct nbpf_channel *chan,
+ unsigned int offset, u32 data)
+{
+ iowrite32(data, chan->base + offset);
+ dev_dbg(chan->dma_chan.device->dev, "%s(0x%p + 0x%x) = 0x%x\n",
+ __func__, chan->base, offset, data);
+}
+
+static inline u32 nbpf_read(struct nbpf_device *nbpf,
+ unsigned int offset)
+{
+ u32 data = ioread32(nbpf->base + offset);
+ dev_dbg(nbpf->dma_dev.dev, "%s(0x%p + 0x%x) = 0x%x\n",
+ __func__, nbpf->base, offset, data);
+ return data;
+}
+
+static inline void nbpf_write(struct nbpf_device *nbpf,
+ unsigned int offset, u32 data)
+{
+ iowrite32(data, nbpf->base + offset);
+ dev_dbg(nbpf->dma_dev.dev, "%s(0x%p + 0x%x) = 0x%x\n",
+ __func__, nbpf->base, offset, data);
+}
+
+static void nbpf_chan_halt(struct nbpf_channel *chan)
+{
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREN);
+}
+
+static bool nbpf_status_get(struct nbpf_channel *chan)
+{
+ u32 status = nbpf_read(chan->nbpf, NBPF_DSTAT_END);
+
+ return status & BIT(chan - chan->nbpf->chan);
+}
+
+static void nbpf_status_ack(struct nbpf_channel *chan)
+{
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREND);
+}
+
+static u32 nbpf_error_get(struct nbpf_device *nbpf)
+{
+ return nbpf_read(nbpf, NBPF_DSTAT_ER);
+}
+
+static struct nbpf_channel *nbpf_error_get_channel(struct nbpf_device *nbpf, u32 error)
+{
+ return nbpf->chan + __ffs(error);
+}
+
+static void nbpf_error_clear(struct nbpf_channel *chan)
+{
+ u32 status;
+ int i;
+
+ /* Stop the channel, make sure DMA has been aborted */
+ nbpf_chan_halt(chan);
+
+ for (i = 1000; i; i--) {
+ status = nbpf_chan_read(chan, NBPF_CHAN_STAT);
+ if (!(status & NBPF_CHAN_STAT_TACT))
+ break;
+ cpu_relax();
+ }
+
+ if (!i)
+ dev_err(chan->dma_chan.device->dev,
+ "%s(): abort timeout, channel status 0x%x\n", __func__, status);
+
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SWRST);
+}
+
+static int nbpf_start(struct nbpf_desc *desc)
+{
+ struct nbpf_channel *chan = desc->chan;
+ struct nbpf_link_desc *ldesc = list_first_entry(&desc->sg, struct nbpf_link_desc, node);
+
+ nbpf_chan_write(chan, NBPF_CHAN_NXLA, (u32)ldesc->hwdesc_dma_addr);
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SETEN | NBPF_CHAN_CTRL_CLRSUS);
+ chan->paused = false;
+
+ /* Software trigger MEMCPY - only MEMCPY uses the block mode */
+ if (ldesc->hwdesc->config & NBPF_CHAN_CFG_TM)
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_STG);
+
+ dev_dbg(chan->nbpf->dma_dev.dev, "%s(): next 0x%x, cur 0x%x\n", __func__,
+ nbpf_chan_read(chan, NBPF_CHAN_NXLA), nbpf_chan_read(chan, NBPF_CHAN_CRLA));
+
+ return 0;
+}
+
+static void nbpf_chan_prepare(struct nbpf_channel *chan)
+{
+ chan->dmarq_cfg = (chan->flags & NBPF_SLAVE_RQ_HIGH ? NBPF_CHAN_CFG_HIEN : 0) |
+ (chan->flags & NBPF_SLAVE_RQ_LOW ? NBPF_CHAN_CFG_LOEN : 0) |
+ (chan->flags & NBPF_SLAVE_RQ_LEVEL ?
+ NBPF_CHAN_CFG_LVL | (NBPF_CHAN_CFG_AM & 0x200) : 0) |
+ chan->terminal;
+}
+
+static void nbpf_chan_prepare_default(struct nbpf_channel *chan)
+{
+ /* Don't output DMAACK */
+ chan->dmarq_cfg = NBPF_CHAN_CFG_AM & 0x400;
+ chan->terminal = 0;
+ chan->flags = 0;
+}
+
+static void nbpf_chan_configure(struct nbpf_channel *chan)
+{
+ /*
+ * We assume, that only the link mode and DMA request line configuration
+ * have to be set in the configuration register manually. Dynamic
+ * per-transfer configuration will be loaded from transfer descriptors.
+ */
+ nbpf_chan_write(chan, NBPF_CHAN_CFG, NBPF_CHAN_CFG_DMS | chan->dmarq_cfg);
+}
+
+static u32 nbpf_xfer_ds(struct nbpf_device *nbpf, size_t size)
+{
+ /* Maximum supported bursts depend on the buffer size */
+ return min_t(int, __ffs(size), ilog2(nbpf->config->buffer_size * 8));
+}
+
+static size_t nbpf_xfer_size(struct nbpf_device *nbpf,
+ enum dma_slave_buswidth width, u32 burst)
+{
+ size_t size;
+
+ if (!burst)
+ burst = 1;
+
+ switch (width) {
+ case DMA_SLAVE_BUSWIDTH_8_BYTES:
+ size = 8 * burst;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ size = 4 * burst;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ size = 2 * burst;
+ break;
+
+ default:
+ pr_warn("%s(): invalid bus width %u\n", __func__, width);
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ size = burst;
+ }
+
+ return nbpf_xfer_ds(nbpf, size);
+}
+
+/*
+ * We need a way to recognise slaves, whose data is sent "raw" over the bus,
+ * i.e. it isn't known in advance how many bytes will be received. Therefore
+ * the slave driver has to provide a "large enough" buffer and either read the
+ * buffer, when it is full, or detect, that some data has arrived, then wait for
+ * a timeout, if no more data arrives - receive what's already there. We want to
+ * handle such slaves in a special way to allow an optimised mode for other
+ * users, for whom the amount of data is known in advance. So far there's no way
+ * to recognise such slaves. We use a data-width check to distinguish between
+ * the SD host and the PL011 UART.
+ */
+
+static int nbpf_prep_one(struct nbpf_link_desc *ldesc,
+ enum dma_transfer_direction direction,
+ dma_addr_t src, dma_addr_t dst, size_t size, bool last)
+{
+ struct nbpf_link_reg *hwdesc = ldesc->hwdesc;
+ struct nbpf_desc *desc = ldesc->desc;
+ struct nbpf_channel *chan = desc->chan;
+ struct device *dev = chan->dma_chan.device->dev;
+ size_t mem_xfer, slave_xfer;
+ bool can_burst;
+
+ hwdesc->header = NBPF_HEADER_WBD | NBPF_HEADER_LV |
+ (last ? NBPF_HEADER_LE : 0);
+
+ hwdesc->src_addr = src;
+ hwdesc->dst_addr = dst;
+ hwdesc->transaction_size = size;
+
+ /*
+ * set config: SAD, DAD, DDS, SDS, etc.
+ * Note on transfer sizes: the DMAC can perform unaligned DMA transfers,
+ * but it is important to have transaction size a multiple of both
+ * receiver and transmitter transfer sizes. It is also possible to use
+ * different RAM and device transfer sizes, and it does work well with
+ * some devices, e.g. with V08R07S01E SD host controllers, which can use
+ * 128 byte transfers. But this doesn't work with other devices,
+ * especially when the transaction size is unknown. This is the case,
+ * e.g. with serial drivers like amba-pl011.c. For reception it sets up
+ * the transaction size of 4K and if fewer bytes are received, it
+ * pauses DMA and reads out data received via DMA as well as those left
+ * in the Rx FIFO. For this to work with the RAM side using burst
+ * transfers we enable the SBE bit and terminate the transfer in our
+ * DMA_PAUSE handler.
+ */
+ mem_xfer = nbpf_xfer_ds(chan->nbpf, size);
+
+ switch (direction) {
+ case DMA_DEV_TO_MEM:
+ can_burst = chan->slave_src_width >= 3;
+ slave_xfer = min(mem_xfer, can_burst ?
+ chan->slave_src_burst : chan->slave_src_width);
+ /*
+ * Is the slave narrower than 64 bits, i.e. isn't using the full
+ * bus width and cannot use bursts?
+ */
+ if (mem_xfer > chan->slave_src_burst && !can_burst)
+ mem_xfer = chan->slave_src_burst;
+ /* Device-to-RAM DMA is unreliable without REQD set */
+ hwdesc->config = NBPF_CHAN_CFG_SAD | (NBPF_CHAN_CFG_DDS & (mem_xfer << 16)) |
+ (NBPF_CHAN_CFG_SDS & (slave_xfer << 12)) | NBPF_CHAN_CFG_REQD |
+ NBPF_CHAN_CFG_SBE;
+ break;
+
+ case DMA_MEM_TO_DEV:
+ slave_xfer = min(mem_xfer, chan->slave_dst_width >= 3 ?
+ chan->slave_dst_burst : chan->slave_dst_width);
+ hwdesc->config = NBPF_CHAN_CFG_DAD | (NBPF_CHAN_CFG_SDS & (mem_xfer << 12)) |
+ (NBPF_CHAN_CFG_DDS & (slave_xfer << 16)) | NBPF_CHAN_CFG_REQD;
+ break;
+
+ case DMA_MEM_TO_MEM:
+ hwdesc->config = NBPF_CHAN_CFG_TCM | NBPF_CHAN_CFG_TM |
+ (NBPF_CHAN_CFG_SDS & (mem_xfer << 12)) |
+ (NBPF_CHAN_CFG_DDS & (mem_xfer << 16));
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ hwdesc->config |= chan->dmarq_cfg | (last ? 0 : NBPF_CHAN_CFG_DEM) |
+ NBPF_CHAN_CFG_DMS;
+
+ dev_dbg(dev, "%s(): desc @ %pad: hdr 0x%x, cfg 0x%x, %zu @ %pad -> %pad\n",
+ __func__, &ldesc->hwdesc_dma_addr, hwdesc->header,
+ hwdesc->config, size, &src, &dst);
+
+ dma_sync_single_for_device(dev, ldesc->hwdesc_dma_addr, sizeof(*hwdesc),
+ DMA_TO_DEVICE);
+
+ return 0;
+}
+
+static size_t nbpf_bytes_left(struct nbpf_channel *chan)
+{
+ return nbpf_chan_read(chan, NBPF_CHAN_CUR_TR_BYTE);
+}
+
+static void nbpf_configure(struct nbpf_device *nbpf)
+{
+ nbpf_write(nbpf, NBPF_CTRL, NBPF_CTRL_LVINT);
+}
+
+static void nbpf_pause(struct nbpf_channel *chan)
+{
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_SETSUS);
+ /* See comment in nbpf_prep_one() */
+ nbpf_chan_write(chan, NBPF_CHAN_CTRL, NBPF_CHAN_CTRL_CLREN);
+}
+
+/* Generic part */
+
+/* DMA ENGINE functions */
+static void nbpf_issue_pending(struct dma_chan *dchan)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ unsigned long flags;
+
+ dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+ spin_lock_irqsave(&chan->lock, flags);
+ if (list_empty(&chan->queued))
+ goto unlock;
+
+ list_splice_tail_init(&chan->queued, &chan->active);
+
+ if (!chan->running) {
+ struct nbpf_desc *desc = list_first_entry(&chan->active,
+ struct nbpf_desc, node);
+ if (!nbpf_start(desc))
+ chan->running = desc;
+ }
+
+unlock:
+ spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static enum dma_status nbpf_tx_status(struct dma_chan *dchan,
+ dma_cookie_t cookie, struct dma_tx_state *state)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ enum dma_status status = dma_cookie_status(dchan, cookie, state);
+
+ if (state) {
+ dma_cookie_t running;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ running = chan->running ? chan->running->async_tx.cookie : -EINVAL;
+
+ if (cookie == running) {
+ state->residue = nbpf_bytes_left(chan);
+ dev_dbg(dchan->device->dev, "%s(): residue %u\n", __func__,
+ state->residue);
+ } else if (status == DMA_IN_PROGRESS) {
+ struct nbpf_desc *desc;
+ bool found = false;
+
+ list_for_each_entry(desc, &chan->active, node)
+ if (desc->async_tx.cookie == cookie) {
+ found = true;
+ break;
+ }
+
+ if (!found)
+ list_for_each_entry(desc, &chan->queued, node)
+ if (desc->async_tx.cookie == cookie) {
+ found = true;
+ break;
+
+ }
+
+ state->residue = found ? desc->length : 0;
+ }
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+
+ if (chan->paused)
+ status = DMA_PAUSED;
+
+ return status;
+}
+
+static dma_cookie_t nbpf_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct nbpf_desc *desc = container_of(tx, struct nbpf_desc, async_tx);
+ struct nbpf_channel *chan = desc->chan;
+ unsigned long flags;
+ dma_cookie_t cookie;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ cookie = dma_cookie_assign(tx);
+ list_add_tail(&desc->node, &chan->queued);
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ dev_dbg(chan->dma_chan.device->dev, "Entry %s(%d)\n", __func__, cookie);
+
+ return cookie;
+}
+
+static int nbpf_desc_page_alloc(struct nbpf_channel *chan)
+{
+ struct dma_chan *dchan = &chan->dma_chan;
+ struct nbpf_desc_page *dpage = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ struct nbpf_link_desc *ldesc;
+ struct nbpf_link_reg *hwdesc;
+ struct nbpf_desc *desc;
+ LIST_HEAD(head);
+ LIST_HEAD(lhead);
+ int i;
+ struct device *dev = dchan->device->dev;
+
+ if (!dpage)
+ return -ENOMEM;
+
+ dev_dbg(dev, "%s(): alloc %lu descriptors, %lu segments, total alloc %zu\n",
+ __func__, NBPF_DESCS_PER_PAGE, NBPF_SEGMENTS_PER_PAGE, sizeof(*dpage));
+
+ for (i = 0, ldesc = dpage->ldesc, hwdesc = dpage->hwdesc;
+ i < ARRAY_SIZE(dpage->ldesc);
+ i++, ldesc++, hwdesc++) {
+ ldesc->hwdesc = hwdesc;
+ list_add_tail(&ldesc->node, &lhead);
+ ldesc->hwdesc_dma_addr = dma_map_single(dchan->device->dev,
+ hwdesc, sizeof(*hwdesc), DMA_TO_DEVICE);
+
+ dev_dbg(dev, "%s(): mapped 0x%p to %pad\n", __func__,
+ hwdesc, &ldesc->hwdesc_dma_addr);
+ }
+
+ for (i = 0, desc = dpage->desc;
+ i < ARRAY_SIZE(dpage->desc);
+ i++, desc++) {
+ dma_async_tx_descriptor_init(&desc->async_tx, dchan);
+ desc->async_tx.tx_submit = nbpf_tx_submit;
+ desc->chan = chan;
+ INIT_LIST_HEAD(&desc->sg);
+ list_add_tail(&desc->node, &head);
+ }
+
+ /*
+ * This function cannot be called from interrupt context, so, no need to
+ * save flags
+ */
+ spin_lock_irq(&chan->lock);
+ list_splice_tail(&lhead, &chan->free_links);
+ list_splice_tail(&head, &chan->free);
+ list_add(&dpage->node, &chan->desc_page);
+ spin_unlock_irq(&chan->lock);
+
+ return ARRAY_SIZE(dpage->desc);
+}
+
+static void nbpf_desc_put(struct nbpf_desc *desc)
+{
+ struct nbpf_channel *chan = desc->chan;
+ struct nbpf_link_desc *ldesc, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ list_for_each_entry_safe(ldesc, tmp, &desc->sg, node)
+ list_move(&ldesc->node, &chan->free_links);
+
+ list_add(&desc->node, &chan->free);
+ spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static void nbpf_scan_acked(struct nbpf_channel *chan)
+{
+ struct nbpf_desc *desc, *tmp;
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->lock, flags);
+ list_for_each_entry_safe(desc, tmp, &chan->done, node)
+ if (async_tx_test_ack(&desc->async_tx) && desc->user_wait) {
+ list_move(&desc->node, &head);
+ desc->user_wait = false;
+ }
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ list_for_each_entry_safe(desc, tmp, &head, node) {
+ list_del(&desc->node);
+ nbpf_desc_put(desc);
+ }
+}
+
+/*
+ * We have to allocate descriptors with the channel lock dropped. This means,
+ * before we re-acquire the lock buffers can be taken already, so we have to
+ * re-check after re-acquiring the lock and possibly retry, if buffers are gone
+ * again.
+ */
+static struct nbpf_desc *nbpf_desc_get(struct nbpf_channel *chan, size_t len)
+{
+ struct nbpf_desc *desc = NULL;
+ struct nbpf_link_desc *ldesc, *prev = NULL;
+
+ nbpf_scan_acked(chan);
+
+ spin_lock_irq(&chan->lock);
+
+ do {
+ int i = 0, ret;
+
+ if (list_empty(&chan->free)) {
+ /* No more free descriptors */
+ spin_unlock_irq(&chan->lock);
+ ret = nbpf_desc_page_alloc(chan);
+ if (ret < 0)
+ return NULL;
+ spin_lock_irq(&chan->lock);
+ continue;
+ }
+ desc = list_first_entry(&chan->free, struct nbpf_desc, node);
+ list_del(&desc->node);
+
+ do {
+ if (list_empty(&chan->free_links)) {
+ /* No more free link descriptors */
+ spin_unlock_irq(&chan->lock);
+ ret = nbpf_desc_page_alloc(chan);
+ if (ret < 0) {
+ nbpf_desc_put(desc);
+ return NULL;
+ }
+ spin_lock_irq(&chan->lock);
+ continue;
+ }
+
+ ldesc = list_first_entry(&chan->free_links,
+ struct nbpf_link_desc, node);
+ ldesc->desc = desc;
+ if (prev)
+ prev->hwdesc->next = (u32)ldesc->hwdesc_dma_addr;
+
+ prev = ldesc;
+ list_move_tail(&ldesc->node, &desc->sg);
+
+ i++;
+ } while (i < len);
+ } while (!desc);
+
+ prev->hwdesc->next = 0;
+
+ spin_unlock_irq(&chan->lock);
+
+ return desc;
+}
+
+static void nbpf_chan_idle(struct nbpf_channel *chan)
+{
+ struct nbpf_desc *desc, *tmp;
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->lock, flags);
+
+ list_splice_init(&chan->done, &head);
+ list_splice_init(&chan->active, &head);
+ list_splice_init(&chan->queued, &head);
+
+ chan->running = NULL;
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ list_for_each_entry_safe(desc, tmp, &head, node) {
+ dev_dbg(chan->nbpf->dma_dev.dev, "%s(): force-free desc %p cookie %d\n",
+ __func__, desc, desc->async_tx.cookie);
+ list_del(&desc->node);
+ nbpf_desc_put(desc);
+ }
+}
+
+static int nbpf_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ struct dma_slave_config *config;
+
+ dev_dbg(dchan->device->dev, "Entry %s(%d)\n", __func__, cmd);
+
+ switch (cmd) {
+ case DMA_TERMINATE_ALL:
+ dev_dbg(dchan->device->dev, "Terminating\n");
+ nbpf_chan_halt(chan);
+ nbpf_chan_idle(chan);
+ break;
+
+ case DMA_SLAVE_CONFIG:
+ if (!arg)
+ return -EINVAL;
+ config = (struct dma_slave_config *)arg;
+
+ /*
+ * We could check config->slave_id to match chan->terminal here,
+ * but with DT they would be coming from the same source, so
+ * such a check would be superflous
+ */
+
+ chan->slave_dst_addr = config->dst_addr;
+ chan->slave_dst_width = nbpf_xfer_size(chan->nbpf,
+ config->dst_addr_width, 1);
+ chan->slave_dst_burst = nbpf_xfer_size(chan->nbpf,
+ config->dst_addr_width,
+ config->dst_maxburst);
+ chan->slave_src_addr = config->src_addr;
+ chan->slave_src_width = nbpf_xfer_size(chan->nbpf,
+ config->src_addr_width, 1);
+ chan->slave_src_burst = nbpf_xfer_size(chan->nbpf,
+ config->src_addr_width,
+ config->src_maxburst);
+ break;
+
+ case DMA_PAUSE:
+ chan->paused = true;
+ nbpf_pause(chan);
+ break;
+
+ default:
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_sg(struct nbpf_channel *chan,
+ struct scatterlist *src_sg, struct scatterlist *dst_sg,
+ size_t len, enum dma_transfer_direction direction,
+ unsigned long flags)
+{
+ struct nbpf_link_desc *ldesc;
+ struct scatterlist *mem_sg;
+ struct nbpf_desc *desc;
+ bool inc_src, inc_dst;
+ size_t data_len = 0;
+ int i = 0;
+
+ switch (direction) {
+ case DMA_DEV_TO_MEM:
+ mem_sg = dst_sg;
+ inc_src = false;
+ inc_dst = true;
+ break;
+
+ case DMA_MEM_TO_DEV:
+ mem_sg = src_sg;
+ inc_src = true;
+ inc_dst = false;
+ break;
+
+ default:
+ case DMA_MEM_TO_MEM:
+ mem_sg = src_sg;
+ inc_src = true;
+ inc_dst = true;
+ }
+
+ desc = nbpf_desc_get(chan, len);
+ if (!desc)
+ return NULL;
+
+ desc->async_tx.flags = flags;
+ desc->async_tx.cookie = -EBUSY;
+ desc->user_wait = false;
+
+ /*
+ * This is a private descriptor list, and we own the descriptor. No need
+ * to lock.
+ */
+ list_for_each_entry(ldesc, &desc->sg, node) {
+ int ret = nbpf_prep_one(ldesc, direction,
+ sg_dma_address(src_sg),
+ sg_dma_address(dst_sg),
+ sg_dma_len(mem_sg),
+ i == len - 1);
+ if (ret < 0) {
+ nbpf_desc_put(desc);
+ return NULL;
+ }
+ data_len += sg_dma_len(mem_sg);
+ if (inc_src)
+ src_sg = sg_next(src_sg);
+ if (inc_dst)
+ dst_sg = sg_next(dst_sg);
+ mem_sg = direction == DMA_DEV_TO_MEM ? dst_sg : src_sg;
+ i++;
+ }
+
+ desc->length = data_len;
+
+ /* The user has to return the descriptor to us ASAP via .tx_submit() */
+ return &desc->async_tx;
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_memcpy(
+ struct dma_chan *dchan, dma_addr_t dst, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ struct scatterlist dst_sg;
+ struct scatterlist src_sg;
+
+ sg_init_table(&dst_sg, 1);
+ sg_init_table(&src_sg, 1);
+
+ sg_dma_address(&dst_sg) = dst;
+ sg_dma_address(&src_sg) = src;
+
+ sg_dma_len(&dst_sg) = len;
+ sg_dma_len(&src_sg) = len;
+
+ dev_dbg(dchan->device->dev, "%s(): %zu @ %pad -> %pad\n",
+ __func__, len, &src, &dst);
+
+ return nbpf_prep_sg(chan, &src_sg, &dst_sg, 1,
+ DMA_MEM_TO_MEM, flags);
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_memcpy_sg(
+ struct dma_chan *dchan,
+ struct scatterlist *dst_sg, unsigned int dst_nents,
+ struct scatterlist *src_sg, unsigned int src_nents,
+ unsigned long flags)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+
+ if (dst_nents != src_nents)
+ return NULL;
+
+ return nbpf_prep_sg(chan, src_sg, dst_sg, src_nents,
+ DMA_MEM_TO_MEM, flags);
+}
+
+static struct dma_async_tx_descriptor *nbpf_prep_slave_sg(
+ struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+ enum dma_transfer_direction direction, unsigned long flags, void *context)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ struct scatterlist slave_sg;
+
+ dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+ sg_init_table(&slave_sg, 1);
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ sg_dma_address(&slave_sg) = chan->slave_dst_addr;
+ return nbpf_prep_sg(chan, sgl, &slave_sg, sg_len,
+ direction, flags);
+
+ case DMA_DEV_TO_MEM:
+ sg_dma_address(&slave_sg) = chan->slave_src_addr;
+ return nbpf_prep_sg(chan, &slave_sg, sgl, sg_len,
+ direction, flags);
+
+ default:
+ return NULL;
+ }
+}
+
+static int nbpf_alloc_chan_resources(struct dma_chan *dchan)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ int ret;
+
+ INIT_LIST_HEAD(&chan->free);
+ INIT_LIST_HEAD(&chan->free_links);
+ INIT_LIST_HEAD(&chan->queued);
+ INIT_LIST_HEAD(&chan->active);
+ INIT_LIST_HEAD(&chan->done);
+
+ ret = nbpf_desc_page_alloc(chan);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dchan->device->dev, "Entry %s(): terminal %u\n", __func__,
+ chan->terminal);
+
+ nbpf_chan_configure(chan);
+
+ return ret;
+}
+
+static void nbpf_free_chan_resources(struct dma_chan *dchan)
+{
+ struct nbpf_channel *chan = nbpf_to_chan(dchan);
+ struct nbpf_desc_page *dpage, *tmp;
+
+ dev_dbg(dchan->device->dev, "Entry %s()\n", __func__);
+
+ nbpf_chan_halt(chan);
+ nbpf_chan_idle(chan);
+ /* Clean up for if a channel is re-used for MEMCPY after slave DMA */
+ nbpf_chan_prepare_default(chan);
+
+ list_for_each_entry_safe(dpage, tmp, &chan->desc_page, node) {
+ struct nbpf_link_desc *ldesc;
+ int i;
+ list_del(&dpage->node);
+ for (i = 0, ldesc = dpage->ldesc;
+ i < ARRAY_SIZE(dpage->ldesc);
+ i++, ldesc++)
+ dma_unmap_single(dchan->device->dev, ldesc->hwdesc_dma_addr,
+ sizeof(*ldesc->hwdesc), DMA_TO_DEVICE);
+ free_page((unsigned long)dpage);
+ }
+}
+
+static int nbpf_slave_caps(struct dma_chan *dchan,
+ struct dma_slave_caps *caps)
+{
+ caps->src_addr_widths = NBPF_DMA_BUSWIDTHS;
+ caps->dstn_addr_widths = NBPF_DMA_BUSWIDTHS;
+ caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ caps->cmd_pause = false;
+ caps->cmd_terminate = true;
+
+ return 0;
+}
+
+static struct dma_chan *nbpf_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct nbpf_device *nbpf = ofdma->of_dma_data;
+ struct dma_chan *dchan;
+ struct nbpf_channel *chan;
+
+ if (dma_spec->args_count != 2)
+ return NULL;
+
+ dchan = dma_get_any_slave_channel(&nbpf->dma_dev);
+ if (!dchan)
+ return NULL;
+
+ dev_dbg(dchan->device->dev, "Entry %s(%s)\n", __func__,
+ dma_spec->np->name);
+
+ chan = nbpf_to_chan(dchan);
+
+ chan->terminal = dma_spec->args[0];
+ chan->flags = dma_spec->args[1];
+
+ nbpf_chan_prepare(chan);
+ nbpf_chan_configure(chan);
+
+ return dchan;
+}
+
+static void nbpf_chan_tasklet(unsigned long data)
+{
+ struct nbpf_channel *chan = (struct nbpf_channel *)data;
+ struct nbpf_desc *desc, *tmp;
+ dma_async_tx_callback callback;
+ void *param;
+
+ while (!list_empty(&chan->done)) {
+ bool found = false, must_put, recycling = false;
+
+ spin_lock_irq(&chan->lock);
+
+ list_for_each_entry_safe(desc, tmp, &chan->done, node) {
+ if (!desc->user_wait) {
+ /* Newly completed descriptor, have to process */
+ found = true;
+ break;
+ } else if (async_tx_test_ack(&desc->async_tx)) {
+ /*
+ * This descriptor was waiting for a user ACK,
+ * it can be recycled now.
+ */
+ list_del(&desc->node);
+ spin_unlock_irq(&chan->lock);
+ nbpf_desc_put(desc);
+ recycling = true;
+ break;
+ }
+ }
+
+ if (recycling)
+ continue;
+
+ if (!found) {
+ /* This can happen if TERMINATE_ALL has been called */
+ spin_unlock_irq(&chan->lock);
+ break;
+ }
+
+ dma_cookie_complete(&desc->async_tx);
+
+ /*
+ * With released lock we cannot dereference desc, maybe it's
+ * still on the "done" list
+ */
+ if (async_tx_test_ack(&desc->async_tx)) {
+ list_del(&desc->node);
+ must_put = true;
+ } else {
+ desc->user_wait = true;
+ must_put = false;
+ }
+
+ callback = desc->async_tx.callback;
+ param = desc->async_tx.callback_param;
+
+ /* ack and callback completed descriptor */
+ spin_unlock_irq(&chan->lock);
+
+ if (callback)
+ callback(param);
+
+ if (must_put)
+ nbpf_desc_put(desc);
+ }
+}
+
+static irqreturn_t nbpf_chan_irq(int irq, void *dev)
+{
+ struct nbpf_channel *chan = dev;
+ bool done = nbpf_status_get(chan);
+ struct nbpf_desc *desc;
+ irqreturn_t ret;
+ bool bh = false;
+
+ if (!done)
+ return IRQ_NONE;
+
+ nbpf_status_ack(chan);
+
+ dev_dbg(&chan->dma_chan.dev->device, "%s()\n", __func__);
+
+ spin_lock(&chan->lock);
+ desc = chan->running;
+ if (WARN_ON(!desc)) {
+ ret = IRQ_NONE;
+ goto unlock;
+ } else {
+ ret = IRQ_HANDLED;
+ bh = true;
+ }
+
+ list_move_tail(&desc->node, &chan->done);
+ chan->running = NULL;
+
+ if (!list_empty(&chan->active)) {
+ desc = list_first_entry(&chan->active,
+ struct nbpf_desc, node);
+ if (!nbpf_start(desc))
+ chan->running = desc;
+ }
+
+unlock:
+ spin_unlock(&chan->lock);
+
+ if (bh)
+ tasklet_schedule(&chan->tasklet);
+
+ return ret;
+}
+
+static irqreturn_t nbpf_err_irq(int irq, void *dev)
+{
+ struct nbpf_device *nbpf = dev;
+ u32 error = nbpf_error_get(nbpf);
+
+ dev_warn(nbpf->dma_dev.dev, "DMA error IRQ %u\n", irq);
+
+ if (!error)
+ return IRQ_NONE;
+
+ do {
+ struct nbpf_channel *chan = nbpf_error_get_channel(nbpf, error);
+ /* On error: abort all queued transfers, no callback */
+ nbpf_error_clear(chan);
+ nbpf_chan_idle(chan);
+ error = nbpf_error_get(nbpf);
+ } while (error);
+
+ return IRQ_HANDLED;
+}
+
+static int nbpf_chan_probe(struct nbpf_device *nbpf, int n)
+{
+ struct dma_device *dma_dev = &nbpf->dma_dev;
+ struct nbpf_channel *chan = nbpf->chan + n;
+ int ret;
+
+ chan->nbpf = nbpf;
+ chan->base = nbpf->base + NBPF_REG_CHAN_OFFSET + NBPF_REG_CHAN_SIZE * n;
+ INIT_LIST_HEAD(&chan->desc_page);
+ spin_lock_init(&chan->lock);
+ chan->dma_chan.device = dma_dev;
+ dma_cookie_init(&chan->dma_chan);
+ nbpf_chan_prepare_default(chan);
+
+ dev_dbg(dma_dev->dev, "%s(): channel %d: -> %p\n", __func__, n, chan->base);
+
+ snprintf(chan->name, sizeof(chan->name), "nbpf %d", n);
+
+ tasklet_init(&chan->tasklet, nbpf_chan_tasklet, (unsigned long)chan);
+ ret = devm_request_irq(dma_dev->dev, chan->irq,
+ nbpf_chan_irq, IRQF_SHARED,
+ chan->name, chan);
+ if (ret < 0)
+ return ret;
+
+ /* Add the channel to DMA device channel list */
+ list_add_tail(&chan->dma_chan.device_node,
+ &dma_dev->channels);
+
+ return 0;
+}
+
+static const struct of_device_id nbpf_match[] = {
+ {.compatible = "renesas,nbpfaxi64dmac1b4", .data = &nbpf_cfg[NBPF1B4]},
+ {.compatible = "renesas,nbpfaxi64dmac1b8", .data = &nbpf_cfg[NBPF1B8]},
+ {.compatible = "renesas,nbpfaxi64dmac1b16", .data = &nbpf_cfg[NBPF1B16]},
+ {.compatible = "renesas,nbpfaxi64dmac4b4", .data = &nbpf_cfg[NBPF4B4]},
+ {.compatible = "renesas,nbpfaxi64dmac4b8", .data = &nbpf_cfg[NBPF4B8]},
+ {.compatible = "renesas,nbpfaxi64dmac4b16", .data = &nbpf_cfg[NBPF4B16]},
+ {.compatible = "renesas,nbpfaxi64dmac8b4", .data = &nbpf_cfg[NBPF8B4]},
+ {.compatible = "renesas,nbpfaxi64dmac8b8", .data = &nbpf_cfg[NBPF8B8]},
+ {.compatible = "renesas,nbpfaxi64dmac8b16", .data = &nbpf_cfg[NBPF8B16]},
+ {}
+};
+MODULE_DEVICE_TABLE(of, nbpf_match);
+
+static int nbpf_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id = of_match_device(nbpf_match, dev);
+ struct device_node *np = dev->of_node;
+ struct nbpf_device *nbpf;
+ struct dma_device *dma_dev;
+ struct resource *iomem, *irq_res;
+ const struct nbpf_config *cfg;
+ int num_channels;
+ int ret, irq, eirq, i;
+ int irqbuf[9] /* maximum 8 channels + error IRQ */;
+ unsigned int irqs = 0;
+
+ BUILD_BUG_ON(sizeof(struct nbpf_desc_page) > PAGE_SIZE);
+
+ /* DT only */
+ if (!np || !of_id || !of_id->data)
+ return -ENODEV;
+
+ cfg = of_id->data;
+ num_channels = cfg->num_channels;
+
+ nbpf = devm_kzalloc(dev, sizeof(*nbpf) + num_channels *
+ sizeof(nbpf->chan[0]), GFP_KERNEL);
+ if (!nbpf) {
+ dev_err(dev, "Memory allocation failed\n");
+ return -ENOMEM;
+ }
+ dma_dev = &nbpf->dma_dev;
+ dma_dev->dev = dev;
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nbpf->base = devm_ioremap_resource(dev, iomem);
+ if (IS_ERR(nbpf->base))
+ return PTR_ERR(nbpf->base);
+
+ nbpf->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(nbpf->clk))
+ return PTR_ERR(nbpf->clk);
+
+ nbpf->config = cfg;
+
+ for (i = 0; irqs < ARRAY_SIZE(irqbuf); i++) {
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!irq_res)
+ break;
+
+ for (irq = irq_res->start; irq <= irq_res->end;
+ irq++, irqs++)
+ irqbuf[irqs] = irq;
+ }
+
+ /*
+ * 3 IRQ resource schemes are supported:
+ * 1. 1 shared IRQ for error and all channels
+ * 2. 2 IRQs: one for error and one shared for all channels
+ * 3. 1 IRQ for error and an own IRQ for each channel
+ */
+ if (irqs != 1 && irqs != 2 && irqs != num_channels + 1)
+ return -ENXIO;
+
+ if (irqs == 1) {
+ eirq = irqbuf[0];
+
+ for (i = 0; i <= num_channels; i++)
+ nbpf->chan[i].irq = irqbuf[0];
+ } else {
+ eirq = platform_get_irq_byname(pdev, "error");
+ if (eirq < 0)
+ return eirq;
+
+ if (irqs == num_channels + 1) {
+ struct nbpf_channel *chan;
+
+ for (i = 0, chan = nbpf->chan; i <= num_channels;
+ i++, chan++) {
+ /* Skip the error IRQ */
+ if (irqbuf[i] == eirq)
+ i++;
+ chan->irq = irqbuf[i];
+ }
+
+ if (chan != nbpf->chan + num_channels)
+ return -EINVAL;
+ } else {
+ /* 2 IRQs and more than one channel */
+ if (irqbuf[0] == eirq)
+ irq = irqbuf[1];
+ else
+ irq = irqbuf[0];
+
+ for (i = 0; i <= num_channels; i++)
+ nbpf->chan[i].irq = irq;
+ }
+ }
+
+ ret = devm_request_irq(dev, eirq, nbpf_err_irq,
+ IRQF_SHARED, "dma error", nbpf);
+ if (ret < 0)
+ return ret;
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+
+ /* Create DMA Channel */
+ for (i = 0; i < num_channels; i++) {
+ ret = nbpf_chan_probe(nbpf, i);
+ if (ret < 0)
+ return ret;
+ }
+
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
+ dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+ dma_cap_set(DMA_SG, dma_dev->cap_mask);
+
+ /* Common and MEMCPY operations */
+ dma_dev->device_alloc_chan_resources
+ = nbpf_alloc_chan_resources;
+ dma_dev->device_free_chan_resources = nbpf_free_chan_resources;
+ dma_dev->device_prep_dma_sg = nbpf_prep_memcpy_sg;
+ dma_dev->device_prep_dma_memcpy = nbpf_prep_memcpy;
+ dma_dev->device_tx_status = nbpf_tx_status;
+ dma_dev->device_issue_pending = nbpf_issue_pending;
+ dma_dev->device_slave_caps = nbpf_slave_caps;
+
+ /*
+ * If we drop support for unaligned MEMCPY buffer addresses and / or
+ * lengths by setting
+ * dma_dev->copy_align = 4;
+ * then we can set transfer length to 4 bytes in nbpf_prep_one() for
+ * DMA_MEM_TO_MEM
+ */
+
+ /* Compulsory for DMA_SLAVE fields */
+ dma_dev->device_prep_slave_sg = nbpf_prep_slave_sg;
+ dma_dev->device_control = nbpf_control;
+
+ platform_set_drvdata(pdev, nbpf);
+
+ ret = clk_prepare_enable(nbpf->clk);
+ if (ret < 0)
+ return ret;
+
+ nbpf_configure(nbpf);
+
+ ret = dma_async_device_register(dma_dev);
+ if (ret < 0)
+ goto e_clk_off;
+
+ ret = of_dma_controller_register(np, nbpf_of_xlate, nbpf);
+ if (ret < 0)
+ goto e_dma_dev_unreg;
+
+ return 0;
+
+e_dma_dev_unreg:
+ dma_async_device_unregister(dma_dev);
+e_clk_off:
+ clk_disable_unprepare(nbpf->clk);
+
+ return ret;
+}
+
+static int nbpf_remove(struct platform_device *pdev)
+{
+ struct nbpf_device *nbpf = platform_get_drvdata(pdev);
+
+ of_dma_controller_free(pdev->dev.of_node);
+ dma_async_device_unregister(&nbpf->dma_dev);
+ clk_disable_unprepare(nbpf->clk);
+
+ return 0;
+}
+
+static struct platform_device_id nbpf_ids[] = {
+ {"nbpfaxi64dmac1b4", (kernel_ulong_t)&nbpf_cfg[NBPF1B4]},
+ {"nbpfaxi64dmac1b8", (kernel_ulong_t)&nbpf_cfg[NBPF1B8]},
+ {"nbpfaxi64dmac1b16", (kernel_ulong_t)&nbpf_cfg[NBPF1B16]},
+ {"nbpfaxi64dmac4b4", (kernel_ulong_t)&nbpf_cfg[NBPF4B4]},
+ {"nbpfaxi64dmac4b8", (kernel_ulong_t)&nbpf_cfg[NBPF4B8]},
+ {"nbpfaxi64dmac4b16", (kernel_ulong_t)&nbpf_cfg[NBPF4B16]},
+ {"nbpfaxi64dmac8b4", (kernel_ulong_t)&nbpf_cfg[NBPF8B4]},
+ {"nbpfaxi64dmac8b8", (kernel_ulong_t)&nbpf_cfg[NBPF8B8]},
+ {"nbpfaxi64dmac8b16", (kernel_ulong_t)&nbpf_cfg[NBPF8B16]},
+ {},
+};
+MODULE_DEVICE_TABLE(platform, nbpf_ids);
+
+#ifdef CONFIG_PM_RUNTIME
+static int nbpf_runtime_suspend(struct device *dev)
+{
+ struct nbpf_device *nbpf = platform_get_drvdata(to_platform_device(dev));
+ clk_disable_unprepare(nbpf->clk);
+ return 0;
+}
+
+static int nbpf_runtime_resume(struct device *dev)
+{
+ struct nbpf_device *nbpf = platform_get_drvdata(to_platform_device(dev));
+ return clk_prepare_enable(nbpf->clk);
+}
+#endif
+
+static const struct dev_pm_ops nbpf_pm_ops = {
+ SET_RUNTIME_PM_OPS(nbpf_runtime_suspend, nbpf_runtime_resume, NULL)
+};
+
+static struct platform_driver nbpf_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "dma-nbpf",
+ .of_match_table = nbpf_match,
+ .pm = &nbpf_pm_ops,
+ },
+ .id_table = nbpf_ids,
+ .probe = nbpf_probe,
+ .remove = nbpf_remove,
+};
+
+module_platform_driver(nbpf_driver);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("dmaengine driver for NBPFAXI64* DMACs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
index e8fe9dc455f4..d5fbeaa1e7ba 100644
--- a/drivers/dma/of-dma.c
+++ b/drivers/dma/of-dma.c
@@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
&dma_spec->args[0]);
}
EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+
+/**
+ * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
+ * @dma_spec: pointer to DMA specifier as found in the device tree
+ * @of_dma: pointer to DMA controller data
+ *
+ * This function can be used as the of xlate callback for DMA driver which wants
+ * to match the channel based on the channel id. When using this xlate function
+ * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
+ * The data parameter of of_dma_controller_register must be a pointer to the
+ * dma_device struct the function should match upon.
+ *
+ * Returns pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct dma_device *dev = ofdma->of_dma_data;
+ struct dma_chan *chan, *candidate = NULL;
+
+ if (!dev || dma_spec->args_count != 1)
+ return NULL;
+
+ list_for_each_entry(chan, &dev->channels, device_node)
+ if (chan->chan_id == dma_spec->args[0]) {
+ candidate = chan;
+ break;
+ }
+
+ if (!candidate)
+ return NULL;
+
+ return dma_get_slave_channel(candidate);
+}
+EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index b19f04f4390b..4cf7d9a950d7 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -853,8 +853,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
- size_t period_len, enum dma_transfer_direction dir, unsigned long flags,
- void *context)
+ size_t period_len, enum dma_transfer_direction dir, unsigned long flags)
{
struct omap_dmadev *od = to_omap_dma_dev(chan->device);
struct omap_chan *c = to_omap_dma_chan(chan);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 73fa9b7a10ab..d5149aacd2fe 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -33,26 +33,15 @@
#define PL330_MAX_IRQS 32
#define PL330_MAX_PERI 32
-enum pl330_srccachectrl {
- SCCTRL0, /* Noncacheable and nonbufferable */
- SCCTRL1, /* Bufferable only */
- SCCTRL2, /* Cacheable, but do not allocate */
- SCCTRL3, /* Cacheable and bufferable, but do not allocate */
- SINVALID1,
- SINVALID2,
- SCCTRL6, /* Cacheable write-through, allocate on reads only */
- SCCTRL7, /* Cacheable write-back, allocate on reads only */
-};
-
-enum pl330_dstcachectrl {
- DCCTRL0, /* Noncacheable and nonbufferable */
- DCCTRL1, /* Bufferable only */
- DCCTRL2, /* Cacheable, but do not allocate */
- DCCTRL3, /* Cacheable and bufferable, but do not allocate */
- DINVALID1, /* AWCACHE = 0x1000 */
- DINVALID2,
- DCCTRL6, /* Cacheable write-through, allocate on writes only */
- DCCTRL7, /* Cacheable write-back, allocate on writes only */
+enum pl330_cachectrl {
+ CCTRL0, /* Noncacheable and nonbufferable */
+ CCTRL1, /* Bufferable only */
+ CCTRL2, /* Cacheable, but do not allocate */
+ CCTRL3, /* Cacheable and bufferable, but do not allocate */
+ INVALID1, /* AWCACHE = 0x1000 */
+ INVALID2,
+ CCTRL6, /* Cacheable write-through, allocate on writes only */
+ CCTRL7, /* Cacheable write-back, allocate on writes only */
};
enum pl330_byteswap {
@@ -63,13 +52,6 @@ enum pl330_byteswap {
SWAP_16,
};
-enum pl330_reqtype {
- MEMTOMEM,
- MEMTODEV,
- DEVTOMEM,
- DEVTODEV,
-};
-
/* Register and Bit field Definitions */
#define DS 0x0
#define DS_ST_STOP 0x0
@@ -263,9 +245,6 @@ enum pl330_reqtype {
*/
#define MCODE_BUFF_PER_REQ 256
-/* If the _pl330_req is available to the client */
-#define IS_FREE(req) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
-
/* Use this _only_ to wait on transient states */
#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax();
@@ -300,27 +279,6 @@ struct pl330_config {
u32 irq_ns;
};
-/* Handle to the DMAC provided to the PL330 core */
-struct pl330_info {
- /* Owning device */
- struct device *dev;
- /* Size of MicroCode buffers for each channel. */
- unsigned mcbufsz;
- /* ioremap'ed address of PL330 registers. */
- void __iomem *base;
- /* Client can freely use it. */
- void *client_data;
- /* PL330 core data, Client must not touch it. */
- void *pl330_data;
- /* Populated by the PL330 core driver during pl330_add */
- struct pl330_config pcfg;
- /*
- * If the DMAC has some reset mechanism, then the
- * client may want to provide pointer to the method.
- */
- void (*dmac_reset)(struct pl330_info *pi);
-};
-
/**
* Request Configuration.
* The PL330 core does not modify this and uses the last
@@ -344,8 +302,8 @@ struct pl330_reqcfg {
unsigned brst_len:5;
unsigned brst_size:3; /* in power of 2 */
- enum pl330_dstcachectrl dcctl;
- enum pl330_srccachectrl scctl;
+ enum pl330_cachectrl dcctl;
+ enum pl330_cachectrl scctl;
enum pl330_byteswap swap;
struct pl330_config *pcfg;
};
@@ -359,11 +317,6 @@ struct pl330_xfer {
u32 dst_addr;
/* Size to xfer */
u32 bytes;
- /*
- * Pointer to next xfer in the list.
- * The last xfer in the req must point to NULL.
- */
- struct pl330_xfer *next;
};
/* The xfer callbacks are made with one of these arguments. */
@@ -376,67 +329,6 @@ enum pl330_op_err {
PL330_ERR_FAIL,
};
-/* A request defining Scatter-Gather List ending with NULL xfer. */
-struct pl330_req {
- enum pl330_reqtype rqtype;
- /* Index of peripheral for the xfer. */
- unsigned peri:5;
- /* Unique token for this xfer, set by the client. */
- void *token;
- /* Callback to be called after xfer. */
- void (*xfer_cb)(void *token, enum pl330_op_err err);
- /* If NULL, req will be done at last set parameters. */
- struct pl330_reqcfg *cfg;
- /* Pointer to first xfer in the request. */
- struct pl330_xfer *x;
- /* Hook to attach to DMAC's list of reqs with due callback */
- struct list_head rqd;
-};
-
-/*
- * To know the status of the channel and DMAC, the client
- * provides a pointer to this structure. The PL330 core
- * fills it with current information.
- */
-struct pl330_chanstatus {
- /*
- * If the DMAC engine halted due to some error,
- * the client should remove-add DMAC.
- */
- bool dmac_halted;
- /*
- * If channel is halted due to some error,
- * the client should ABORT/FLUSH and START the channel.
- */
- bool faulting;
- /* Location of last load */
- u32 src_addr;
- /* Location of last store */
- u32 dst_addr;
- /*
- * Pointer to the currently active req, NULL if channel is
- * inactive, even though the requests may be present.
- */
- struct pl330_req *top_req;
- /* Pointer to req waiting second in the queue if any. */
- struct pl330_req *wait_req;
-};
-
-enum pl330_chan_op {
- /* Start the channel */
- PL330_OP_START,
- /* Abort the active xfer */
- PL330_OP_ABORT,
- /* Stop xfer and flush queue */
- PL330_OP_FLUSH,
-};
-
-struct _xfer_spec {
- u32 ccr;
- struct pl330_req *r;
- struct pl330_xfer *x;
-};
-
enum dmamov_dst {
SAR = 0,
CCR,
@@ -454,12 +346,12 @@ enum pl330_cond {
ALWAYS,
};
+struct dma_pl330_desc;
+
struct _pl330_req {
u32 mc_bus;
void *mc_cpu;
- /* Number of bytes taken to setup MC for the req */
- u32 mc_len;
- struct pl330_req *r;
+ struct dma_pl330_desc *desc;
};
/* ToBeDone for tasklet */
@@ -491,30 +383,6 @@ enum pl330_dmac_state {
DYING,
};
-/* A DMAC */
-struct pl330_dmac {
- spinlock_t lock;
- /* Holds list of reqs with due callbacks */
- struct list_head req_done;
- /* Pointer to platform specific stuff */
- struct pl330_info *pinfo;
- /* Maximum possible events/irqs */
- int events[32];
- /* BUS address of MicroCode buffer */
- dma_addr_t mcode_bus;
- /* CPU address of MicroCode buffer */
- void *mcode_cpu;
- /* List of all Channel threads */
- struct pl330_thread *channels;
- /* Pointer to the MANAGER thread */
- struct pl330_thread *manager;
- /* To handle bad news in interrupt */
- struct tasklet_struct tasks;
- struct _pl330_tbd dmac_tbd;
- /* State of DMAC operation */
- enum pl330_dmac_state state;
-};
-
enum desc_status {
/* In the DMAC pool */
FREE,
@@ -555,15 +423,16 @@ struct dma_pl330_chan {
* As the parent, this DMAC also provides descriptors
* to the channel.
*/
- struct dma_pl330_dmac *dmac;
+ struct pl330_dmac *dmac;
/* To protect channel manipulation */
spinlock_t lock;
- /* Token of a hardware channel thread of PL330 DMAC
- * NULL if the channel is available to be acquired.
+ /*
+ * Hardware channel thread of PL330 DMAC. NULL if the channel is
+ * available.
*/
- void *pl330_chid;
+ struct pl330_thread *thread;
/* For D-to-M and M-to-D channels */
int burst_sz; /* the peripheral fifo width */
@@ -574,9 +443,7 @@ struct dma_pl330_chan {
bool cyclic;
};
-struct dma_pl330_dmac {
- struct pl330_info pif;
-
+struct pl330_dmac {
/* DMA-Engine Device */
struct dma_device ddma;
@@ -588,6 +455,32 @@ struct dma_pl330_dmac {
/* To protect desc_pool manipulation */
spinlock_t pool_lock;
+ /* Size of MicroCode buffers for each channel. */
+ unsigned mcbufsz;
+ /* ioremap'ed address of PL330 registers. */
+ void __iomem *base;
+ /* Populated by the PL330 core driver during pl330_add */
+ struct pl330_config pcfg;
+
+ spinlock_t lock;
+ /* Maximum possible events/irqs */
+ int events[32];
+ /* BUS address of MicroCode buffer */
+ dma_addr_t mcode_bus;
+ /* CPU address of MicroCode buffer */
+ void *mcode_cpu;
+ /* List of all Channel threads */
+ struct pl330_thread *channels;
+ /* Pointer to the MANAGER thread */
+ struct pl330_thread *manager;
+ /* To handle bad news in interrupt */
+ struct tasklet_struct tasks;
+ struct _pl330_tbd dmac_tbd;
+ /* State of DMAC operation */
+ enum pl330_dmac_state state;
+ /* Holds list of reqs with due callbacks */
+ struct list_head req_done;
+
/* Peripheral channels connected to this DMAC */
unsigned int num_peripherals;
struct dma_pl330_chan *peripherals; /* keep at end */
@@ -604,49 +497,43 @@ struct dma_pl330_desc {
struct pl330_xfer px;
struct pl330_reqcfg rqcfg;
- struct pl330_req req;
enum desc_status status;
/* The channel which currently holds this desc */
struct dma_pl330_chan *pchan;
+
+ enum dma_transfer_direction rqtype;
+ /* Index of peripheral for the xfer. */
+ unsigned peri:5;
+ /* Hook to attach to DMAC's list of reqs with due callback */
+ struct list_head rqd;
};
-static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
-{
- if (r && r->xfer_cb)
- r->xfer_cb(r->token, err);
-}
+struct _xfer_spec {
+ u32 ccr;
+ struct dma_pl330_desc *desc;
+};
static inline bool _queue_empty(struct pl330_thread *thrd)
{
- return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
- ? true : false;
+ return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
}
static inline bool _queue_full(struct pl330_thread *thrd)
{
- return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
- ? false : true;
+ return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
}
static inline bool is_manager(struct pl330_thread *thrd)
{
- struct pl330_dmac *pl330 = thrd->dmac;
-
- /* MANAGER is indexed at the end */
- if (thrd->id == pl330->pinfo->pcfg.num_chan)
- return true;
- else
- return false;
+ return thrd->dmac->manager == thrd;
}
/* If manager of the thread is in Non-Secure mode */
static inline bool _manager_ns(struct pl330_thread *thrd)
{
- struct pl330_dmac *pl330 = thrd->dmac;
-
- return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
+ return (thrd->dmac->pcfg.mode & DMAC_MODE_NS) ? true : false;
}
static inline u32 get_revision(u32 periph_id)
@@ -1004,7 +891,7 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
/* Returns Time-Out */
static bool _until_dmac_idle(struct pl330_thread *thrd)
{
- void __iomem *regs = thrd->dmac->pinfo->base;
+ void __iomem *regs = thrd->dmac->base;
unsigned long loops = msecs_to_loops(5);
do {
@@ -1024,7 +911,7 @@ static bool _until_dmac_idle(struct pl330_thread *thrd)
static inline void _execute_DBGINSN(struct pl330_thread *thrd,
u8 insn[], bool as_manager)
{
- void __iomem *regs = thrd->dmac->pinfo->base;
+ void __iomem *regs = thrd->dmac->base;
u32 val;
val = (insn[0] << 16) | (insn[1] << 24);
@@ -1039,7 +926,7 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
/* If timed out due to halted state-machine */
if (_until_dmac_idle(thrd)) {
- dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
+ dev_err(thrd->dmac->ddma.dev, "DMAC halted!\n");
return;
}
@@ -1047,25 +934,9 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
writel(0, regs + DBGCMD);
}
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-static void mark_free(struct pl330_thread *thrd, int idx)
-{
- struct _pl330_req *req = &thrd->req[idx];
-
- _emit_END(0, req->mc_cpu);
- req->mc_len = 0;
-
- thrd->req_running = -1;
-}
-
static inline u32 _state(struct pl330_thread *thrd)
{
- void __iomem *regs = thrd->dmac->pinfo->base;
+ void __iomem *regs = thrd->dmac->base;
u32 val;
if (is_manager(thrd))
@@ -1123,7 +994,7 @@ static inline u32 _state(struct pl330_thread *thrd)
static void _stop(struct pl330_thread *thrd)
{
- void __iomem *regs = thrd->dmac->pinfo->base;
+ void __iomem *regs = thrd->dmac->base;
u8 insn[6] = {0, 0, 0, 0, 0, 0};
if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
@@ -1146,9 +1017,9 @@ static void _stop(struct pl330_thread *thrd)
/* Start doing req 'idx' of thread 'thrd' */
static bool _trigger(struct pl330_thread *thrd)
{
- void __iomem *regs = thrd->dmac->pinfo->base;
+ void __iomem *regs = thrd->dmac->base;
struct _pl330_req *req;
- struct pl330_req *r;
+ struct dma_pl330_desc *desc;
struct _arg_GO go;
unsigned ns;
u8 insn[6] = {0, 0, 0, 0, 0, 0};
@@ -1159,32 +1030,27 @@ static bool _trigger(struct pl330_thread *thrd)
return true;
idx = 1 - thrd->lstenq;
- if (!IS_FREE(&thrd->req[idx]))
+ if (thrd->req[idx].desc != NULL) {
req = &thrd->req[idx];
- else {
+ } else {
idx = thrd->lstenq;
- if (!IS_FREE(&thrd->req[idx]))
+ if (thrd->req[idx].desc != NULL)
req = &thrd->req[idx];
else
req = NULL;
}
/* Return if no request */
- if (!req || !req->r)
+ if (!req)
return true;
- r = req->r;
+ desc = req->desc;
- if (r->cfg)
- ns = r->cfg->nonsecure ? 1 : 0;
- else if (readl(regs + CS(thrd->id)) & CS_CNS)
- ns = 1;
- else
- ns = 0;
+ ns = desc->rqcfg.nonsecure ? 1 : 0;
/* See 'Abort Sources' point-4 at Page 2-25 */
if (_manager_ns(thrd) && !ns)
- dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
+ dev_info(thrd->dmac->ddma.dev, "%s:%d Recipe for ABORT!\n",
__func__, __LINE__);
go.chan = thrd->id;
@@ -1240,7 +1106,7 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs, int cyc)
{
int off = 0;
- struct pl330_config *pcfg = pxs->r->cfg->pcfg;
+ struct pl330_config *pcfg = pxs->desc->rqcfg.pcfg;
/* check lock-up free version */
if (get_revision(pcfg->periph_id) >= PERIPH_REV_R1P0) {
@@ -1266,10 +1132,10 @@ static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
int off = 0;
while (cyc--) {
- off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
- off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+ off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+ off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
off += _emit_ST(dry_run, &buf[off], ALWAYS);
- off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
}
return off;
@@ -1281,10 +1147,10 @@ static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
int off = 0;
while (cyc--) {
- off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+ off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
off += _emit_LD(dry_run, &buf[off], ALWAYS);
- off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
- off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+ off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->desc->peri);
+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
}
return off;
@@ -1295,14 +1161,14 @@ static int _bursts(unsigned dry_run, u8 buf[],
{
int off = 0;
- switch (pxs->r->rqtype) {
- case MEMTODEV:
+ switch (pxs->desc->rqtype) {
+ case DMA_MEM_TO_DEV:
off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
break;
- case DEVTOMEM:
+ case DMA_DEV_TO_MEM:
off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
break;
- case MEMTOMEM:
+ case DMA_MEM_TO_MEM:
off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
break;
default:
@@ -1395,7 +1261,7 @@ static inline int _loop(unsigned dry_run, u8 buf[],
static inline int _setup_loops(unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs)
{
- struct pl330_xfer *x = pxs->x;
+ struct pl330_xfer *x = &pxs->desc->px;
u32 ccr = pxs->ccr;
unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
int off = 0;
@@ -1412,7 +1278,7 @@ static inline int _setup_loops(unsigned dry_run, u8 buf[],
static inline int _setup_xfer(unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs)
{
- struct pl330_xfer *x = pxs->x;
+ struct pl330_xfer *x = &pxs->desc->px;
int off = 0;
/* DMAMOV SAR, x->src_addr */
@@ -1443,17 +1309,12 @@ static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
/* DMAMOV CCR, ccr */
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
- x = pxs->r->x;
- do {
- /* Error if xfer length is not aligned at burst size */
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
- return -EINVAL;
-
- pxs->x = x;
- off += _setup_xfer(dry_run, &buf[off], pxs);
+ x = &pxs->desc->px;
+ /* Error if xfer length is not aligned at burst size */
+ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
+ return -EINVAL;
- x = x->next;
- } while (x);
+ off += _setup_xfer(dry_run, &buf[off], pxs);
/* DMASEV peripheral/event */
off += _emit_SEV(dry_run, &buf[off], thrd->ev);
@@ -1495,31 +1356,15 @@ static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
return ccr;
}
-static inline bool _is_valid(u32 ccr)
-{
- enum pl330_dstcachectrl dcctl;
- enum pl330_srccachectrl scctl;
-
- dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
- scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
-
- if (dcctl == DINVALID1 || dcctl == DINVALID2
- || scctl == SINVALID1 || scctl == SINVALID2)
- return false;
- else
- return true;
-}
-
/*
* Submit a list of xfers after which the client wants notification.
* Client is not notified after each xfer unit, just once after all
* xfer units are done or some error occurs.
*/
-static int pl330_submit_req(void *ch_id, struct pl330_req *r)
+static int pl330_submit_req(struct pl330_thread *thrd,
+ struct dma_pl330_desc *desc)
{
- struct pl330_thread *thrd = ch_id;
- struct pl330_dmac *pl330;
- struct pl330_info *pi;
+ struct pl330_dmac *pl330 = thrd->dmac;
struct _xfer_spec xs;
unsigned long flags;
void __iomem *regs;
@@ -1528,25 +1373,24 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
int ret = 0;
/* No Req or Unacquired Channel or DMAC */
- if (!r || !thrd || thrd->free)
+ if (!desc || !thrd || thrd->free)
return -EINVAL;
- pl330 = thrd->dmac;
- pi = pl330->pinfo;
- regs = pi->base;
+ regs = thrd->dmac->base;
if (pl330->state == DYING
|| pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
- dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
+ dev_info(thrd->dmac->ddma.dev, "%s:%d\n",
__func__, __LINE__);
return -EAGAIN;
}
/* If request for non-existing peripheral */
- if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
- dev_info(thrd->dmac->pinfo->dev,
+ if (desc->rqtype != DMA_MEM_TO_MEM &&
+ desc->peri >= pl330->pcfg.num_peri) {
+ dev_info(thrd->dmac->ddma.dev,
"%s:%d Invalid peripheral(%u)!\n",
- __func__, __LINE__, r->peri);
+ __func__, __LINE__, desc->peri);
return -EINVAL;
}
@@ -1557,41 +1401,26 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
goto xfer_exit;
}
+ /* Prefer Secure Channel */
+ if (!_manager_ns(thrd))
+ desc->rqcfg.nonsecure = 0;
+ else
+ desc->rqcfg.nonsecure = 1;
- /* Use last settings, if not provided */
- if (r->cfg) {
- /* Prefer Secure Channel */
- if (!_manager_ns(thrd))
- r->cfg->nonsecure = 0;
- else
- r->cfg->nonsecure = 1;
-
- ccr = _prepare_ccr(r->cfg);
- } else {
- ccr = readl(regs + CC(thrd->id));
- }
-
- /* If this req doesn't have valid xfer settings */
- if (!_is_valid(ccr)) {
- ret = -EINVAL;
- dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
- __func__, __LINE__, ccr);
- goto xfer_exit;
- }
+ ccr = _prepare_ccr(&desc->rqcfg);
- idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
+ idx = thrd->req[0].desc == NULL ? 0 : 1;
xs.ccr = ccr;
- xs.r = r;
+ xs.desc = desc;
/* First dry run to check if req is acceptable */
ret = _setup_req(1, thrd, idx, &xs);
if (ret < 0)
goto xfer_exit;
- if (ret > pi->mcbufsz / 2) {
- dev_info(thrd->dmac->pinfo->dev,
- "%s:%d Trying increasing mcbufsz\n",
+ if (ret > pl330->mcbufsz / 2) {
+ dev_info(pl330->ddma.dev, "%s:%d Trying increasing mcbufsz\n",
__func__, __LINE__);
ret = -ENOMEM;
goto xfer_exit;
@@ -1599,8 +1428,8 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
/* Hook the request */
thrd->lstenq = idx;
- thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
- thrd->req[idx].r = r;
+ thrd->req[idx].desc = desc;
+ _setup_req(0, thrd, idx, &xs);
ret = 0;
@@ -1610,10 +1439,32 @@ xfer_exit:
return ret;
}
+static void dma_pl330_rqcb(struct dma_pl330_desc *desc, enum pl330_op_err err)
+{
+ struct dma_pl330_chan *pch;
+ unsigned long flags;
+
+ if (!desc)
+ return;
+
+ pch = desc->pchan;
+
+ /* If desc aborted */
+ if (!pch)
+ return;
+
+ spin_lock_irqsave(&pch->lock, flags);
+
+ desc->status = DONE;
+
+ spin_unlock_irqrestore(&pch->lock, flags);
+
+ tasklet_schedule(&pch->task);
+}
+
static void pl330_dotask(unsigned long data)
{
struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
- struct pl330_info *pi = pl330->pinfo;
unsigned long flags;
int i;
@@ -1631,16 +1482,16 @@ static void pl330_dotask(unsigned long data)
if (pl330->dmac_tbd.reset_mngr) {
_stop(pl330->manager);
/* Reset all channels */
- pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
+ pl330->dmac_tbd.reset_chan = (1 << pl330->pcfg.num_chan) - 1;
/* Clear the reset flag */
pl330->dmac_tbd.reset_mngr = false;
}
- for (i = 0; i < pi->pcfg.num_chan; i++) {
+ for (i = 0; i < pl330->pcfg.num_chan; i++) {
if (pl330->dmac_tbd.reset_chan & (1 << i)) {
struct pl330_thread *thrd = &pl330->channels[i];
- void __iomem *regs = pi->base;
+ void __iomem *regs = pl330->base;
enum pl330_op_err err;
_stop(thrd);
@@ -1651,16 +1502,13 @@ static void pl330_dotask(unsigned long data)
err = PL330_ERR_ABORT;
spin_unlock_irqrestore(&pl330->lock, flags);
-
- _callback(thrd->req[1 - thrd->lstenq].r, err);
- _callback(thrd->req[thrd->lstenq].r, err);
-
+ dma_pl330_rqcb(thrd->req[1 - thrd->lstenq].desc, err);
+ dma_pl330_rqcb(thrd->req[thrd->lstenq].desc, err);
spin_lock_irqsave(&pl330->lock, flags);
- thrd->req[0].r = NULL;
- thrd->req[1].r = NULL;
- mark_free(thrd, 0);
- mark_free(thrd, 1);
+ thrd->req[0].desc = NULL;
+ thrd->req[1].desc = NULL;
+ thrd->req_running = -1;
/* Clear the reset flag */
pl330->dmac_tbd.reset_chan &= ~(1 << i);
@@ -1673,20 +1521,15 @@ static void pl330_dotask(unsigned long data)
}
/* Returns 1 if state was updated, 0 otherwise */
-static int pl330_update(const struct pl330_info *pi)
+static int pl330_update(struct pl330_dmac *pl330)
{
- struct pl330_req *rqdone, *tmp;
- struct pl330_dmac *pl330;
+ struct dma_pl330_desc *descdone, *tmp;
unsigned long flags;
void __iomem *regs;
u32 val;
int id, ev, ret = 0;
- if (!pi || !pi->pl330_data)
- return 0;
-
- regs = pi->base;
- pl330 = pi->pl330_data;
+ regs = pl330->base;
spin_lock_irqsave(&pl330->lock, flags);
@@ -1696,13 +1539,13 @@ static int pl330_update(const struct pl330_info *pi)
else
pl330->dmac_tbd.reset_mngr = false;
- val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
+ val = readl(regs + FSC) & ((1 << pl330->pcfg.num_chan) - 1);
pl330->dmac_tbd.reset_chan |= val;
if (val) {
int i = 0;
- while (i < pi->pcfg.num_chan) {
+ while (i < pl330->pcfg.num_chan) {
if (val & (1 << i)) {
- dev_info(pi->dev,
+ dev_info(pl330->ddma.dev,
"Reset Channel-%d\t CS-%x FTC-%x\n",
i, readl(regs + CS(i)),
readl(regs + FTC(i)));
@@ -1714,15 +1557,16 @@ static int pl330_update(const struct pl330_info *pi)
/* Check which event happened i.e, thread notified */
val = readl(regs + ES);
- if (pi->pcfg.num_events < 32
- && val & ~((1 << pi->pcfg.num_events) - 1)) {
+ if (pl330->pcfg.num_events < 32
+ && val & ~((1 << pl330->pcfg.num_events) - 1)) {
pl330->dmac_tbd.reset_dmac = true;
- dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
+ dev_err(pl330->ddma.dev, "%s:%d Unexpected!\n", __func__,
+ __LINE__);
ret = 1;
goto updt_exit;
}
- for (ev = 0; ev < pi->pcfg.num_events; ev++) {
+ for (ev = 0; ev < pl330->pcfg.num_events; ev++) {
if (val & (1 << ev)) { /* Event occurred */
struct pl330_thread *thrd;
u32 inten = readl(regs + INTEN);
@@ -1743,25 +1587,22 @@ static int pl330_update(const struct pl330_info *pi)
continue;
/* Detach the req */
- rqdone = thrd->req[active].r;
- thrd->req[active].r = NULL;
-
- mark_free(thrd, active);
+ descdone = thrd->req[active].desc;
+ thrd->req[active].desc = NULL;
/* Get going again ASAP */
_start(thrd);
/* For now, just make a list of callbacks to be done */
- list_add_tail(&rqdone->rqd, &pl330->req_done);
+ list_add_tail(&descdone->rqd, &pl330->req_done);
}
}
/* Now that we are in no hurry, do the callbacks */
- list_for_each_entry_safe(rqdone, tmp, &pl330->req_done, rqd) {
- list_del(&rqdone->rqd);
-
+ list_for_each_entry_safe(descdone, tmp, &pl330->req_done, rqd) {
+ list_del(&descdone->rqd);
spin_unlock_irqrestore(&pl330->lock, flags);
- _callback(rqdone, PL330_ERR_NONE);
+ dma_pl330_rqcb(descdone, PL330_ERR_NONE);
spin_lock_irqsave(&pl330->lock, flags);
}
@@ -1778,65 +1619,13 @@ updt_exit:
return ret;
}
-static int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
-{
- struct pl330_thread *thrd = ch_id;
- struct pl330_dmac *pl330;
- unsigned long flags;
- int ret = 0, active;
-
- if (!thrd || thrd->free || thrd->dmac->state == DYING)
- return -EINVAL;
-
- pl330 = thrd->dmac;
- active = thrd->req_running;
-
- spin_lock_irqsave(&pl330->lock, flags);
-
- switch (op) {
- case PL330_OP_FLUSH:
- /* Make sure the channel is stopped */
- _stop(thrd);
-
- thrd->req[0].r = NULL;
- thrd->req[1].r = NULL;
- mark_free(thrd, 0);
- mark_free(thrd, 1);
- break;
-
- case PL330_OP_ABORT:
- /* Make sure the channel is stopped */
- _stop(thrd);
-
- /* ABORT is only for the active req */
- if (active == -1)
- break;
-
- thrd->req[active].r = NULL;
- mark_free(thrd, active);
-
- /* Start the next */
- case PL330_OP_START:
- if ((active == -1) && !_start(thrd))
- ret = -EIO;
- break;
-
- default:
- ret = -EINVAL;
- }
-
- spin_unlock_irqrestore(&pl330->lock, flags);
- return ret;
-}
-
/* Reserve an event */
static inline int _alloc_event(struct pl330_thread *thrd)
{
struct pl330_dmac *pl330 = thrd->dmac;
- struct pl330_info *pi = pl330->pinfo;
int ev;
- for (ev = 0; ev < pi->pcfg.num_events; ev++)
+ for (ev = 0; ev < pl330->pcfg.num_events; ev++)
if (pl330->events[ev] == -1) {
pl330->events[ev] = thrd->id;
return ev;
@@ -1845,45 +1634,38 @@ static inline int _alloc_event(struct pl330_thread *thrd)
return -1;
}
-static bool _chan_ns(const struct pl330_info *pi, int i)
+static bool _chan_ns(const struct pl330_dmac *pl330, int i)
{
- return pi->pcfg.irq_ns & (1 << i);
+ return pl330->pcfg.irq_ns & (1 << i);
}
/* Upon success, returns IdentityToken for the
* allocated channel, NULL otherwise.
*/
-static void *pl330_request_channel(const struct pl330_info *pi)
+static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
{
struct pl330_thread *thrd = NULL;
- struct pl330_dmac *pl330;
unsigned long flags;
int chans, i;
- if (!pi || !pi->pl330_data)
- return NULL;
-
- pl330 = pi->pl330_data;
-
if (pl330->state == DYING)
return NULL;
- chans = pi->pcfg.num_chan;
+ chans = pl330->pcfg.num_chan;
spin_lock_irqsave(&pl330->lock, flags);
for (i = 0; i < chans; i++) {
thrd = &pl330->channels[i];
if ((thrd->free) && (!_manager_ns(thrd) ||
- _chan_ns(pi, i))) {
+ _chan_ns(pl330, i))) {
thrd->ev = _alloc_event(thrd);
if (thrd->ev >= 0) {
thrd->free = false;
thrd->lstenq = 1;
- thrd->req[0].r = NULL;
- mark_free(thrd, 0);
- thrd->req[1].r = NULL;
- mark_free(thrd, 1);
+ thrd->req[0].desc = NULL;
+ thrd->req[1].desc = NULL;
+ thrd->req_running = -1;
break;
}
}
@@ -1899,17 +1681,15 @@ static void *pl330_request_channel(const struct pl330_info *pi)
static inline void _free_event(struct pl330_thread *thrd, int ev)
{
struct pl330_dmac *pl330 = thrd->dmac;
- struct pl330_info *pi = pl330->pinfo;
/* If the event is valid and was held by the thread */
- if (ev >= 0 && ev < pi->pcfg.num_events
+ if (ev >= 0 && ev < pl330->pcfg.num_events
&& pl330->events[ev] == thrd->id)
pl330->events[ev] = -1;
}
-static void pl330_release_channel(void *ch_id)
+static void pl330_release_channel(struct pl330_thread *thrd)
{
- struct pl330_thread *thrd = ch_id;
struct pl330_dmac *pl330;
unsigned long flags;
@@ -1918,8 +1698,8 @@ static void pl330_release_channel(void *ch_id)
_stop(thrd);
- _callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
- _callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
+ dma_pl330_rqcb(thrd->req[1 - thrd->lstenq].desc, PL330_ERR_ABORT);
+ dma_pl330_rqcb(thrd->req[thrd->lstenq].desc, PL330_ERR_ABORT);
pl330 = thrd->dmac;
@@ -1932,72 +1712,70 @@ static void pl330_release_channel(void *ch_id)
/* Initialize the structure for PL330 configuration, that can be used
* by the client driver the make best use of the DMAC
*/
-static void read_dmac_config(struct pl330_info *pi)
+static void read_dmac_config(struct pl330_dmac *pl330)
{
- void __iomem *regs = pi->base;
+ void __iomem *regs = pl330->base;
u32 val;
val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
val &= CRD_DATA_WIDTH_MASK;
- pi->pcfg.data_bus_width = 8 * (1 << val);
+ pl330->pcfg.data_bus_width = 8 * (1 << val);
val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
val &= CRD_DATA_BUFF_MASK;
- pi->pcfg.data_buf_dep = val + 1;
+ pl330->pcfg.data_buf_dep = val + 1;
val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
val &= CR0_NUM_CHANS_MASK;
val += 1;
- pi->pcfg.num_chan = val;
+ pl330->pcfg.num_chan = val;
val = readl(regs + CR0);
if (val & CR0_PERIPH_REQ_SET) {
val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
val += 1;
- pi->pcfg.num_peri = val;
- pi->pcfg.peri_ns = readl(regs + CR4);
+ pl330->pcfg.num_peri = val;
+ pl330->pcfg.peri_ns = readl(regs + CR4);
} else {
- pi->pcfg.num_peri = 0;
+ pl330->pcfg.num_peri = 0;
}
val = readl(regs + CR0);
if (val & CR0_BOOT_MAN_NS)
- pi->pcfg.mode |= DMAC_MODE_NS;
+ pl330->pcfg.mode |= DMAC_MODE_NS;
else
- pi->pcfg.mode &= ~DMAC_MODE_NS;
+ pl330->pcfg.mode &= ~DMAC_MODE_NS;
val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
val &= CR0_NUM_EVENTS_MASK;
val += 1;
- pi->pcfg.num_events = val;
+ pl330->pcfg.num_events = val;
- pi->pcfg.irq_ns = readl(regs + CR3);
+ pl330->pcfg.irq_ns = readl(regs + CR3);
}
static inline void _reset_thread(struct pl330_thread *thrd)
{
struct pl330_dmac *pl330 = thrd->dmac;
- struct pl330_info *pi = pl330->pinfo;
thrd->req[0].mc_cpu = pl330->mcode_cpu
- + (thrd->id * pi->mcbufsz);
+ + (thrd->id * pl330->mcbufsz);
thrd->req[0].mc_bus = pl330->mcode_bus
- + (thrd->id * pi->mcbufsz);
- thrd->req[0].r = NULL;
- mark_free(thrd, 0);
+ + (thrd->id * pl330->mcbufsz);
+ thrd->req[0].desc = NULL;
thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
- + pi->mcbufsz / 2;
+ + pl330->mcbufsz / 2;
thrd->req[1].mc_bus = thrd->req[0].mc_bus
- + pi->mcbufsz / 2;
- thrd->req[1].r = NULL;
- mark_free(thrd, 1);
+ + pl330->mcbufsz / 2;
+ thrd->req[1].desc = NULL;
+
+ thrd->req_running = -1;
}
static int dmac_alloc_threads(struct pl330_dmac *pl330)
{
- struct pl330_info *pi = pl330->pinfo;
- int chans = pi->pcfg.num_chan;
+ int chans = pl330->pcfg.num_chan;
struct pl330_thread *thrd;
int i;
@@ -2028,29 +1806,28 @@ static int dmac_alloc_threads(struct pl330_dmac *pl330)
static int dmac_alloc_resources(struct pl330_dmac *pl330)
{
- struct pl330_info *pi = pl330->pinfo;
- int chans = pi->pcfg.num_chan;
+ int chans = pl330->pcfg.num_chan;
int ret;
/*
* Alloc MicroCode buffer for 'chans' Channel threads.
* A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
*/
- pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
- chans * pi->mcbufsz,
+ pl330->mcode_cpu = dma_alloc_coherent(pl330->ddma.dev,
+ chans * pl330->mcbufsz,
&pl330->mcode_bus, GFP_KERNEL);
if (!pl330->mcode_cpu) {
- dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+ dev_err(pl330->ddma.dev, "%s:%d Can't allocate memory!\n",
__func__, __LINE__);
return -ENOMEM;
}
ret = dmac_alloc_threads(pl330);
if (ret) {
- dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
+ dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n",
__func__, __LINE__);
- dma_free_coherent(pi->dev,
- chans * pi->mcbufsz,
+ dma_free_coherent(pl330->ddma.dev,
+ chans * pl330->mcbufsz,
pl330->mcode_cpu, pl330->mcode_bus);
return ret;
}
@@ -2058,71 +1835,45 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330)
return 0;
}
-static int pl330_add(struct pl330_info *pi)
+static int pl330_add(struct pl330_dmac *pl330)
{
- struct pl330_dmac *pl330;
void __iomem *regs;
int i, ret;
- if (!pi || !pi->dev)
- return -EINVAL;
-
- /* If already added */
- if (pi->pl330_data)
- return -EINVAL;
-
- /*
- * If the SoC can perform reset on the DMAC, then do it
- * before reading its configuration.
- */
- if (pi->dmac_reset)
- pi->dmac_reset(pi);
-
- regs = pi->base;
+ regs = pl330->base;
/* Check if we can handle this DMAC */
- if ((pi->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
- dev_err(pi->dev, "PERIPH_ID 0x%x !\n", pi->pcfg.periph_id);
+ if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
+ dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n",
+ pl330->pcfg.periph_id);
return -EINVAL;
}
/* Read the configuration of the DMAC */
- read_dmac_config(pi);
+ read_dmac_config(pl330);
- if (pi->pcfg.num_events == 0) {
- dev_err(pi->dev, "%s:%d Can't work without events!\n",
+ if (pl330->pcfg.num_events == 0) {
+ dev_err(pl330->ddma.dev, "%s:%d Can't work without events!\n",
__func__, __LINE__);
return -EINVAL;
}
- pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
- if (!pl330) {
- dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
- __func__, __LINE__);
- return -ENOMEM;
- }
-
- /* Assign the info structure and private data */
- pl330->pinfo = pi;
- pi->pl330_data = pl330;
-
spin_lock_init(&pl330->lock);
INIT_LIST_HEAD(&pl330->req_done);
/* Use default MC buffer size if not provided */
- if (!pi->mcbufsz)
- pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
+ if (!pl330->mcbufsz)
+ pl330->mcbufsz = MCODE_BUFF_PER_REQ * 2;
/* Mark all events as free */
- for (i = 0; i < pi->pcfg.num_events; i++)
+ for (i = 0; i < pl330->pcfg.num_events; i++)
pl330->events[i] = -1;
/* Allocate resources needed by the DMAC */
ret = dmac_alloc_resources(pl330);
if (ret) {
- dev_err(pi->dev, "Unable to create channels for DMAC\n");
- kfree(pl330);
+ dev_err(pl330->ddma.dev, "Unable to create channels for DMAC\n");
return ret;
}
@@ -2135,15 +1886,13 @@ static int pl330_add(struct pl330_info *pi)
static int dmac_free_threads(struct pl330_dmac *pl330)
{
- struct pl330_info *pi = pl330->pinfo;
- int chans = pi->pcfg.num_chan;
struct pl330_thread *thrd;
int i;
/* Release Channel threads */
- for (i = 0; i < chans; i++) {
+ for (i = 0; i < pl330->pcfg.num_chan; i++) {
thrd = &pl330->channels[i];
- pl330_release_channel((void *)thrd);
+ pl330_release_channel(thrd);
}
/* Free memory */
@@ -2152,35 +1901,18 @@ static int dmac_free_threads(struct pl330_dmac *pl330)
return 0;
}
-static void dmac_free_resources(struct pl330_dmac *pl330)
+static void pl330_del(struct pl330_dmac *pl330)
{
- struct pl330_info *pi = pl330->pinfo;
- int chans = pi->pcfg.num_chan;
-
- dmac_free_threads(pl330);
-
- dma_free_coherent(pi->dev, chans * pi->mcbufsz,
- pl330->mcode_cpu, pl330->mcode_bus);
-}
-
-static void pl330_del(struct pl330_info *pi)
-{
- struct pl330_dmac *pl330;
-
- if (!pi || !pi->pl330_data)
- return;
-
- pl330 = pi->pl330_data;
-
pl330->state = UNINIT;
tasklet_kill(&pl330->tasks);
/* Free DMAC resources */
- dmac_free_resources(pl330);
+ dmac_free_threads(pl330);
- kfree(pl330);
- pi->pl330_data = NULL;
+ dma_free_coherent(pl330->ddma.dev,
+ pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu,
+ pl330->mcode_bus);
}
/* forward declaration */
@@ -2212,8 +1944,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
if (desc->status == BUSY)
continue;
- ret = pl330_submit_req(pch->pl330_chid,
- &desc->req);
+ ret = pl330_submit_req(pch->thread, desc);
if (!ret) {
desc->status = BUSY;
} else if (ret == -EAGAIN) {
@@ -2222,7 +1953,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
} else {
/* Unacceptable request */
desc->status = DONE;
- dev_err(pch->dmac->pif.dev, "%s:%d Bad Desc(%d)\n",
+ dev_err(pch->dmac->ddma.dev, "%s:%d Bad Desc(%d)\n",
__func__, __LINE__, desc->txd.cookie);
tasklet_schedule(&pch->task);
}
@@ -2249,7 +1980,9 @@ static void pl330_tasklet(unsigned long data)
fill_queue(pch);
/* Make sure the PL330 Channel thread is active */
- pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START);
+ spin_lock(&pch->thread->dmac->lock);
+ _start(pch->thread);
+ spin_unlock(&pch->thread->dmac->lock);
while (!list_empty(&pch->completed_list)) {
dma_async_tx_callback callback;
@@ -2280,25 +2013,6 @@ static void pl330_tasklet(unsigned long data)
spin_unlock_irqrestore(&pch->lock, flags);
}
-static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
-{
- struct dma_pl330_desc *desc = token;
- struct dma_pl330_chan *pch = desc->pchan;
- unsigned long flags;
-
- /* If desc aborted */
- if (!pch)
- return;
-
- spin_lock_irqsave(&pch->lock, flags);
-
- desc->status = DONE;
-
- spin_unlock_irqrestore(&pch->lock, flags);
-
- tasklet_schedule(&pch->task);
-}
-
bool pl330_filter(struct dma_chan *chan, void *param)
{
u8 *peri_id;
@@ -2315,23 +2029,26 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
int count = dma_spec->args_count;
- struct dma_pl330_dmac *pdmac = ofdma->of_dma_data;
+ struct pl330_dmac *pl330 = ofdma->of_dma_data;
unsigned int chan_id;
+ if (!pl330)
+ return NULL;
+
if (count != 1)
return NULL;
chan_id = dma_spec->args[0];
- if (chan_id >= pdmac->num_peripherals)
+ if (chan_id >= pl330->num_peripherals)
return NULL;
- return dma_get_slave_channel(&pdmac->peripherals[chan_id].chan);
+ return dma_get_slave_channel(&pl330->peripherals[chan_id].chan);
}
static int pl330_alloc_chan_resources(struct dma_chan *chan)
{
struct dma_pl330_chan *pch = to_pchan(chan);
- struct dma_pl330_dmac *pdmac = pch->dmac;
+ struct pl330_dmac *pl330 = pch->dmac;
unsigned long flags;
spin_lock_irqsave(&pch->lock, flags);
@@ -2339,8 +2056,8 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
dma_cookie_init(chan);
pch->cyclic = false;
- pch->pl330_chid = pl330_request_channel(&pdmac->pif);
- if (!pch->pl330_chid) {
+ pch->thread = pl330_request_channel(pl330);
+ if (!pch->thread) {
spin_unlock_irqrestore(&pch->lock, flags);
return -ENOMEM;
}
@@ -2357,7 +2074,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
struct dma_pl330_chan *pch = to_pchan(chan);
struct dma_pl330_desc *desc;
unsigned long flags;
- struct dma_pl330_dmac *pdmac = pch->dmac;
+ struct pl330_dmac *pl330 = pch->dmac;
struct dma_slave_config *slave_config;
LIST_HEAD(list);
@@ -2365,8 +2082,13 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
case DMA_TERMINATE_ALL:
spin_lock_irqsave(&pch->lock, flags);
- /* FLUSH the PL330 Channel thread */
- pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
+ spin_lock(&pl330->lock);
+ _stop(pch->thread);
+ spin_unlock(&pl330->lock);
+
+ pch->thread->req[0].desc = NULL;
+ pch->thread->req[1].desc = NULL;
+ pch->thread->req_running = -1;
/* Mark all desc done */
list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2384,9 +2106,9 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
dma_cookie_complete(&desc->txd);
}
- list_splice_tail_init(&pch->submitted_list, &pdmac->desc_pool);
- list_splice_tail_init(&pch->work_list, &pdmac->desc_pool);
- list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool);
+ list_splice_tail_init(&pch->submitted_list, &pl330->desc_pool);
+ list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
+ list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
spin_unlock_irqrestore(&pch->lock, flags);
break;
case DMA_SLAVE_CONFIG:
@@ -2409,7 +2131,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
}
break;
default:
- dev_err(pch->dmac->pif.dev, "Not supported command.\n");
+ dev_err(pch->dmac->ddma.dev, "Not supported command.\n");
return -ENXIO;
}
@@ -2425,8 +2147,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
spin_lock_irqsave(&pch->lock, flags);
- pl330_release_channel(pch->pl330_chid);
- pch->pl330_chid = NULL;
+ pl330_release_channel(pch->thread);
+ pch->thread = NULL;
if (pch->cyclic)
list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
@@ -2489,57 +2211,46 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
static inline void _init_desc(struct dma_pl330_desc *desc)
{
- desc->req.x = &desc->px;
- desc->req.token = desc;
desc->rqcfg.swap = SWAP_NO;
- desc->rqcfg.scctl = SCCTRL0;
- desc->rqcfg.dcctl = DCCTRL0;
- desc->req.cfg = &desc->rqcfg;
- desc->req.xfer_cb = dma_pl330_rqcb;
+ desc->rqcfg.scctl = CCTRL0;
+ desc->rqcfg.dcctl = CCTRL0;
desc->txd.tx_submit = pl330_tx_submit;
INIT_LIST_HEAD(&desc->node);
}
/* Returns the number of descriptors added to the DMAC pool */
-static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
+static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
{
struct dma_pl330_desc *desc;
unsigned long flags;
int i;
- if (!pdmac)
- return 0;
-
desc = kcalloc(count, sizeof(*desc), flg);
if (!desc)
return 0;
- spin_lock_irqsave(&pdmac->pool_lock, flags);
+ spin_lock_irqsave(&pl330->pool_lock, flags);
for (i = 0; i < count; i++) {
_init_desc(&desc[i]);
- list_add_tail(&desc[i].node, &pdmac->desc_pool);
+ list_add_tail(&desc[i].node, &pl330->desc_pool);
}
- spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+ spin_unlock_irqrestore(&pl330->pool_lock, flags);
return count;
}
-static struct dma_pl330_desc *
-pluck_desc(struct dma_pl330_dmac *pdmac)
+static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
{
struct dma_pl330_desc *desc = NULL;
unsigned long flags;
- if (!pdmac)
- return NULL;
-
- spin_lock_irqsave(&pdmac->pool_lock, flags);
+ spin_lock_irqsave(&pl330->pool_lock, flags);
- if (!list_empty(&pdmac->desc_pool)) {
- desc = list_entry(pdmac->desc_pool.next,
+ if (!list_empty(&pl330->desc_pool)) {
+ desc = list_entry(pl330->desc_pool.next,
struct dma_pl330_desc, node);
list_del_init(&desc->node);
@@ -2548,29 +2259,29 @@ pluck_desc(struct dma_pl330_dmac *pdmac)
desc->txd.callback = NULL;
}
- spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+ spin_unlock_irqrestore(&pl330->pool_lock, flags);
return desc;
}
static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
{
- struct dma_pl330_dmac *pdmac = pch->dmac;
+ struct pl330_dmac *pl330 = pch->dmac;
u8 *peri_id = pch->chan.private;
struct dma_pl330_desc *desc;
/* Pluck one desc from the pool of DMAC */
- desc = pluck_desc(pdmac);
+ desc = pluck_desc(pl330);
/* If the DMAC pool is empty, alloc new */
if (!desc) {
- if (!add_desc(pdmac, GFP_ATOMIC, 1))
+ if (!add_desc(pl330, GFP_ATOMIC, 1))
return NULL;
/* Try again */
- desc = pluck_desc(pdmac);
+ desc = pluck_desc(pl330);
if (!desc) {
- dev_err(pch->dmac->pif.dev,
+ dev_err(pch->dmac->ddma.dev,
"%s:%d ALERT!\n", __func__, __LINE__);
return NULL;
}
@@ -2581,8 +2292,8 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
desc->txd.cookie = 0;
async_tx_ack(&desc->txd);
- desc->req.peri = peri_id ? pch->chan.chan_id : 0;
- desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;
+ desc->peri = peri_id ? pch->chan.chan_id : 0;
+ desc->rqcfg.pcfg = &pch->dmac->pcfg;
dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
@@ -2592,7 +2303,6 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
static inline void fill_px(struct pl330_xfer *px,
dma_addr_t dst, dma_addr_t src, size_t len)
{
- px->next = NULL;
px->bytes = len;
px->dst_addr = dst;
px->src_addr = src;
@@ -2605,7 +2315,7 @@ __pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst,
struct dma_pl330_desc *desc = pl330_get_desc(pch);
if (!desc) {
- dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
__func__, __LINE__);
return NULL;
}
@@ -2629,11 +2339,11 @@ __pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst,
static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
{
struct dma_pl330_chan *pch = desc->pchan;
- struct pl330_info *pi = &pch->dmac->pif;
+ struct pl330_dmac *pl330 = pch->dmac;
int burst_len;
- burst_len = pi->pcfg.data_bus_width / 8;
- burst_len *= pi->pcfg.data_buf_dep;
+ burst_len = pl330->pcfg.data_bus_width / 8;
+ burst_len *= pl330->pcfg.data_buf_dep;
burst_len >>= desc->rqcfg.brst_size;
/* src/dst_burst_len can't be more than 16 */
@@ -2652,11 +2362,11 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct dma_pl330_desc *desc = NULL, *first = NULL;
struct dma_pl330_chan *pch = to_pchan(chan);
- struct dma_pl330_dmac *pdmac = pch->dmac;
+ struct pl330_dmac *pl330 = pch->dmac;
unsigned int i;
dma_addr_t dst;
dma_addr_t src;
@@ -2665,7 +2375,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
return NULL;
if (!is_slave_direction(direction)) {
- dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
+ dev_err(pch->dmac->ddma.dev, "%s:%d Invalid dma direction\n",
__func__, __LINE__);
return NULL;
}
@@ -2673,23 +2383,23 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
for (i = 0; i < len / period_len; i++) {
desc = pl330_get_desc(pch);
if (!desc) {
- dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
+ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
__func__, __LINE__);
if (!first)
return NULL;
- spin_lock_irqsave(&pdmac->pool_lock, flags);
+ spin_lock_irqsave(&pl330->pool_lock, flags);
while (!list_empty(&first->node)) {
desc = list_entry(first->node.next,
struct dma_pl330_desc, node);
- list_move_tail(&desc->node, &pdmac->desc_pool);
+ list_move_tail(&desc->node, &pl330->desc_pool);
}
- list_move_tail(&first->node, &pdmac->desc_pool);
+ list_move_tail(&first->node, &pl330->desc_pool);
- spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+ spin_unlock_irqrestore(&pl330->pool_lock, flags);
return NULL;
}
@@ -2698,14 +2408,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
case DMA_MEM_TO_DEV:
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
- desc->req.rqtype = MEMTODEV;
src = dma_addr;
dst = pch->fifo_addr;
break;
case DMA_DEV_TO_MEM:
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
- desc->req.rqtype = DEVTOMEM;
src = pch->fifo_addr;
dst = dma_addr;
break;
@@ -2713,6 +2421,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
break;
}
+ desc->rqtype = direction;
desc->rqcfg.brst_size = pch->burst_sz;
desc->rqcfg.brst_len = 1;
fill_px(&desc->px, dst, src, period_len);
@@ -2740,24 +2449,22 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
{
struct dma_pl330_desc *desc;
struct dma_pl330_chan *pch = to_pchan(chan);
- struct pl330_info *pi;
+ struct pl330_dmac *pl330 = pch->dmac;
int burst;
if (unlikely(!pch || !len))
return NULL;
- pi = &pch->dmac->pif;
-
desc = __pl330_prep_dma_memcpy(pch, dst, src, len);
if (!desc)
return NULL;
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 1;
- desc->req.rqtype = MEMTOMEM;
+ desc->rqtype = DMA_MEM_TO_MEM;
/* Select max possible burst size */
- burst = pi->pcfg.data_bus_width / 8;
+ burst = pl330->pcfg.data_bus_width / 8;
while (burst > 1) {
if (!(len % burst))
@@ -2776,7 +2483,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
return &desc->txd;
}
-static void __pl330_giveback_desc(struct dma_pl330_dmac *pdmac,
+static void __pl330_giveback_desc(struct pl330_dmac *pl330,
struct dma_pl330_desc *first)
{
unsigned long flags;
@@ -2785,17 +2492,17 @@ static void __pl330_giveback_desc(struct dma_pl330_dmac *pdmac,
if (!first)
return;
- spin_lock_irqsave(&pdmac->pool_lock, flags);
+ spin_lock_irqsave(&pl330->pool_lock, flags);
while (!list_empty(&first->node)) {
desc = list_entry(first->node.next,
struct dma_pl330_desc, node);
- list_move_tail(&desc->node, &pdmac->desc_pool);
+ list_move_tail(&desc->node, &pl330->desc_pool);
}
- list_move_tail(&first->node, &pdmac->desc_pool);
+ list_move_tail(&first->node, &pl330->desc_pool);
- spin_unlock_irqrestore(&pdmac->pool_lock, flags);
+ spin_unlock_irqrestore(&pl330->pool_lock, flags);
}
static struct dma_async_tx_descriptor *
@@ -2820,12 +2527,12 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
desc = pl330_get_desc(pch);
if (!desc) {
- struct dma_pl330_dmac *pdmac = pch->dmac;
+ struct pl330_dmac *pl330 = pch->dmac;
- dev_err(pch->dmac->pif.dev,
+ dev_err(pch->dmac->ddma.dev,
"%s:%d Unable to fetch desc\n",
__func__, __LINE__);
- __pl330_giveback_desc(pdmac, first);
+ __pl330_giveback_desc(pl330, first);
return NULL;
}
@@ -2838,19 +2545,18 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (direction == DMA_MEM_TO_DEV) {
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
- desc->req.rqtype = MEMTODEV;
fill_px(&desc->px,
addr, sg_dma_address(sg), sg_dma_len(sg));
} else {
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
- desc->req.rqtype = DEVTOMEM;
fill_px(&desc->px,
sg_dma_address(sg), addr, sg_dma_len(sg));
}
desc->rqcfg.brst_size = pch->burst_sz;
desc->rqcfg.brst_len = 1;
+ desc->rqtype = direction;
}
/* Return the last desc in the chain */
@@ -2890,9 +2596,9 @@ static int
pl330_probe(struct amba_device *adev, const struct amba_id *id)
{
struct dma_pl330_platdata *pdat;
- struct dma_pl330_dmac *pdmac;
+ struct pl330_config *pcfg;
+ struct pl330_dmac *pl330;
struct dma_pl330_chan *pch, *_p;
- struct pl330_info *pi;
struct dma_device *pd;
struct resource *res;
int i, ret, irq;
@@ -2905,30 +2611,27 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
return ret;
/* Allocate a new DMAC and its Channels */
- pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL);
- if (!pdmac) {
+ pl330 = devm_kzalloc(&adev->dev, sizeof(*pl330), GFP_KERNEL);
+ if (!pl330) {
dev_err(&adev->dev, "unable to allocate mem\n");
return -ENOMEM;
}
- pi = &pdmac->pif;
- pi->dev = &adev->dev;
- pi->pl330_data = NULL;
- pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
+ pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
res = &adev->res;
- pi->base = devm_ioremap_resource(&adev->dev, res);
- if (IS_ERR(pi->base))
- return PTR_ERR(pi->base);
+ pl330->base = devm_ioremap_resource(&adev->dev, res);
+ if (IS_ERR(pl330->base))
+ return PTR_ERR(pl330->base);
- amba_set_drvdata(adev, pdmac);
+ amba_set_drvdata(adev, pl330);
for (i = 0; i < AMBA_NR_IRQS; i++) {
irq = adev->irq[i];
if (irq) {
ret = devm_request_irq(&adev->dev, irq,
pl330_irq_handler, 0,
- dev_name(&adev->dev), pi);
+ dev_name(&adev->dev), pl330);
if (ret)
return ret;
} else {
@@ -2936,38 +2639,40 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
}
}
- pi->pcfg.periph_id = adev->periphid;
- ret = pl330_add(pi);
+ pcfg = &pl330->pcfg;
+
+ pcfg->periph_id = adev->periphid;
+ ret = pl330_add(pl330);
if (ret)
return ret;
- INIT_LIST_HEAD(&pdmac->desc_pool);
- spin_lock_init(&pdmac->pool_lock);
+ INIT_LIST_HEAD(&pl330->desc_pool);
+ spin_lock_init(&pl330->pool_lock);
/* Create a descriptor pool of default size */
- if (!add_desc(pdmac, GFP_KERNEL, NR_DEFAULT_DESC))
+ if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
dev_warn(&adev->dev, "unable to allocate desc\n");
- pd = &pdmac->ddma;
+ pd = &pl330->ddma;
INIT_LIST_HEAD(&pd->channels);
/* Initialize channel parameters */
if (pdat)
- num_chan = max_t(int, pdat->nr_valid_peri, pi->pcfg.num_chan);
+ num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan);
else
- num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
+ num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
- pdmac->num_peripherals = num_chan;
+ pl330->num_peripherals = num_chan;
- pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
- if (!pdmac->peripherals) {
+ pl330->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
+ if (!pl330->peripherals) {
ret = -ENOMEM;
- dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
+ dev_err(&adev->dev, "unable to allocate pl330->peripherals\n");
goto probe_err2;
}
for (i = 0; i < num_chan; i++) {
- pch = &pdmac->peripherals[i];
+ pch = &pl330->peripherals[i];
if (!adev->dev.of_node)
pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
else
@@ -2977,9 +2682,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
INIT_LIST_HEAD(&pch->work_list);
INIT_LIST_HEAD(&pch->completed_list);
spin_lock_init(&pch->lock);
- pch->pl330_chid = NULL;
+ pch->thread = NULL;
pch->chan.device = pd;
- pch->dmac = pdmac;
+ pch->dmac = pl330;
/* Add the channel to the DMAC list */
list_add_tail(&pch->chan.device_node, &pd->channels);
@@ -2990,7 +2695,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pd->cap_mask = pdat->cap_mask;
} else {
dma_cap_set(DMA_MEMCPY, pd->cap_mask);
- if (pi->pcfg.num_peri) {
+ if (pcfg->num_peri) {
dma_cap_set(DMA_SLAVE, pd->cap_mask);
dma_cap_set(DMA_CYCLIC, pd->cap_mask);
dma_cap_set(DMA_PRIVATE, pd->cap_mask);
@@ -3015,14 +2720,14 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
if (adev->dev.of_node) {
ret = of_dma_controller_register(adev->dev.of_node,
- of_dma_pl330_xlate, pdmac);
+ of_dma_pl330_xlate, pl330);
if (ret) {
dev_err(&adev->dev,
"unable to register DMA to the generic DT DMA helpers\n");
}
}
- adev->dev.dma_parms = &pdmac->dma_parms;
+ adev->dev.dma_parms = &pl330->dma_parms;
/*
* This is the limit for transfers with a buswidth of 1, larger
@@ -3037,14 +2742,13 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
dev_info(&adev->dev,
"\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
- pi->pcfg.data_buf_dep,
- pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
- pi->pcfg.num_peri, pi->pcfg.num_events);
+ pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
+ pcfg->num_peri, pcfg->num_events);
return 0;
probe_err3:
/* Idle the DMAC */
- list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+ list_for_each_entry_safe(pch, _p, &pl330->ddma.channels,
chan.device_node) {
/* Remove the channel */
@@ -3055,27 +2759,23 @@ probe_err3:
pl330_free_chan_resources(&pch->chan);
}
probe_err2:
- pl330_del(pi);
+ pl330_del(pl330);
return ret;
}
static int pl330_remove(struct amba_device *adev)
{
- struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
+ struct pl330_dmac *pl330 = amba_get_drvdata(adev);
struct dma_pl330_chan *pch, *_p;
- struct pl330_info *pi;
-
- if (!pdmac)
- return 0;
if (adev->dev.of_node)
of_dma_controller_free(adev->dev.of_node);
- dma_async_device_unregister(&pdmac->ddma);
+ dma_async_device_unregister(&pl330->ddma);
/* Idle the DMAC */
- list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+ list_for_each_entry_safe(pch, _p, &pl330->ddma.channels,
chan.device_node) {
/* Remove the channel */
@@ -3086,9 +2786,7 @@ static int pl330_remove(struct amba_device *adev)
pl330_free_chan_resources(&pch->chan);
}
- pi = &pdmac->pif;
-
- pl330_del(pi);
+ pl330_del(pl330);
return 0;
}
diff --git a/drivers/dma/qcom_bam_dma.c b/drivers/dma/qcom_bam_dma.c
index 82c923146e49..7a4bbb0f80a5 100644
--- a/drivers/dma/qcom_bam_dma.c
+++ b/drivers/dma/qcom_bam_dma.c
@@ -61,12 +61,17 @@ struct bam_desc_hw {
#define DESC_FLAG_INT BIT(15)
#define DESC_FLAG_EOT BIT(14)
#define DESC_FLAG_EOB BIT(13)
+#define DESC_FLAG_NWD BIT(12)
struct bam_async_desc {
struct virt_dma_desc vd;
u32 num_desc;
u32 xfer_len;
+
+ /* transaction flags, EOT|EOB|NWD */
+ u16 flags;
+
struct bam_desc_hw *curr_desc;
enum dma_transfer_direction dir;
@@ -490,6 +495,14 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan,
if (!async_desc)
goto err_out;
+ if (flags & DMA_PREP_FENCE)
+ async_desc->flags |= DESC_FLAG_NWD;
+
+ if (flags & DMA_PREP_INTERRUPT)
+ async_desc->flags |= DESC_FLAG_EOT;
+ else
+ async_desc->flags |= DESC_FLAG_INT;
+
async_desc->num_desc = num_alloc;
async_desc->curr_desc = async_desc->desc;
async_desc->dir = direction;
@@ -793,8 +806,11 @@ static void bam_start_dma(struct bam_chan *bchan)
else
async_desc->xfer_len = async_desc->num_desc;
- /* set INT on last descriptor */
- desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT;
+ /* set any special flags on the last descriptor */
+ if (async_desc->num_desc == async_desc->xfer_len)
+ desc[async_desc->xfer_len - 1].flags = async_desc->flags;
+ else
+ desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT;
if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) {
u32 partial = MAX_DESCRIPTORS - bchan->tail;
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
index 012520c9fd79..7416572d1e40 100644
--- a/drivers/dma/s3c24xx-dma.c
+++ b/drivers/dma/s3c24xx-dma.c
@@ -889,8 +889,7 @@ static struct dma_async_tx_descriptor *s3c24xx_dma_prep_memcpy(
static struct dma_async_tx_descriptor *s3c24xx_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period,
- enum dma_transfer_direction direction, unsigned long flags,
- void *context)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 5ebdfbc1051e..4b0ef043729a 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -612,7 +612,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period,
- enum dma_transfer_direction dir, unsigned long flags, void *context)
+ enum dma_transfer_direction dir, unsigned long flags)
{
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
struct sa11x0_dma_desc *txd;
diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig
index 0f719816c91b..0349125a2e20 100644
--- a/drivers/dma/sh/Kconfig
+++ b/drivers/dma/sh/Kconfig
@@ -2,21 +2,39 @@
# DMA engine configuration for sh
#
+#
+# DMA Engine Helpers
+#
+
config SH_DMAE_BASE
bool "Renesas SuperH DMA Engine support"
- depends on (SUPERH && SH_DMA) || ARCH_SHMOBILE || COMPILE_TEST
+ depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+ depends on !SUPERH || SH_DMA
depends on !SH_DMA_API
default y
select DMA_ENGINE
help
Enable support for the Renesas SuperH DMA controllers.
+#
+# DMA Controllers
+#
+
config SH_DMAE
tristate "Renesas SuperH DMAC support"
depends on SH_DMAE_BASE
help
Enable support for the Renesas SuperH DMA controllers.
+if SH_DMAE
+
+config SH_DMAE_R8A73A4
+ def_bool y
+ depends on ARCH_R8A73A4
+ depends on OF
+
+endif
+
config SUDMAC
tristate "Renesas SUDMAC support"
depends on SH_DMAE_BASE
@@ -34,7 +52,3 @@ config RCAR_AUDMAC_PP
depends on SH_DMAE_BASE
help
Enable support for the Renesas R-Car Audio DMAC Peripheral Peripheral controllers.
-
-config SHDMA_R8A73A4
- def_bool y
- depends on ARCH_R8A73A4 && SH_DMAE != n
diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
index 1ce88b28cfc6..0a5cfdb76e45 100644
--- a/drivers/dma/sh/Makefile
+++ b/drivers/dma/sh/Makefile
@@ -1,10 +1,18 @@
+#
+# DMA Engine Helpers
+#
+
obj-$(CONFIG_SH_DMAE_BASE) += shdma-base.o shdma-of.o
-obj-$(CONFIG_SH_DMAE) += shdma.o
+
+#
+# DMA Controllers
+#
+
shdma-y := shdmac.o
-ifeq ($(CONFIG_OF),y)
-shdma-$(CONFIG_SHDMA_R8A73A4) += shdma-r8a73a4.o
-endif
+shdma-$(CONFIG_SH_DMAE_R8A73A4) += shdma-r8a73a4.o
shdma-objs := $(shdma-y)
+obj-$(CONFIG_SH_DMAE) += shdma.o
+
obj-$(CONFIG_SUDMAC) += sudmac.o
obj-$(CONFIG_RCAR_HPB_DMAE) += rcar-hpbdma.o
obj-$(CONFIG_RCAR_AUDMAC_PP) += rcar-audmapp.o
diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c
index 2de77289a2e9..dabbf0aba2e9 100644
--- a/drivers/dma/sh/rcar-audmapp.c
+++ b/drivers/dma/sh/rcar-audmapp.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
+#include <linux/of_dma.h>
#include <linux/platform_data/dma-rcar-audmapp.h>
#include <linux/platform_device.h>
#include <linux/shdma-base.h>
@@ -45,8 +46,9 @@
struct audmapp_chan {
struct shdma_chan shdma_chan;
- struct audmapp_slave_config *config;
void __iomem *base;
+ dma_addr_t slave_addr;
+ u32 chcr;
};
struct audmapp_device {
@@ -56,7 +58,16 @@ struct audmapp_device {
void __iomem *chan_reg;
};
+struct audmapp_desc {
+ struct shdma_desc shdma_desc;
+ dma_addr_t src;
+ dma_addr_t dst;
+};
+
+#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
+
#define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan)
+#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc)
#define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \
struct audmapp_device, shdma_dev.dma_dev)
@@ -90,70 +101,82 @@ static void audmapp_halt(struct shdma_chan *schan)
}
static void audmapp_start_xfer(struct shdma_chan *schan,
- struct shdma_desc *sdecs)
+ struct shdma_desc *sdesc)
{
struct audmapp_chan *auchan = to_chan(schan);
struct audmapp_device *audev = to_dev(auchan);
- struct audmapp_slave_config *cfg = auchan->config;
+ struct audmapp_desc *desc = to_desc(sdesc);
struct device *dev = audev->dev;
- u32 chcr = cfg->chcr | PDMACHCR_DE;
+ u32 chcr = auchan->chcr | PDMACHCR_DE;
- dev_dbg(dev, "src/dst/chcr = %pad/%pad/%x\n",
- &cfg->src, &cfg->dst, cfg->chcr);
+ dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n",
+ &desc->src, &desc->dst, chcr);
- audmapp_write(auchan, cfg->src, PDMASAR);
- audmapp_write(auchan, cfg->dst, PDMADAR);
+ audmapp_write(auchan, desc->src, PDMASAR);
+ audmapp_write(auchan, desc->dst, PDMADAR);
audmapp_write(auchan, chcr, PDMACHCR);
}
-static struct audmapp_slave_config *
-audmapp_find_slave(struct audmapp_chan *auchan, int slave_id)
+static void audmapp_get_config(struct audmapp_chan *auchan, int slave_id,
+ u32 *chcr, dma_addr_t *dst)
{
struct audmapp_device *audev = to_dev(auchan);
struct audmapp_pdata *pdata = audev->pdata;
struct audmapp_slave_config *cfg;
int i;
+ *chcr = 0;
+ *dst = 0;
+
+ if (!pdata) { /* DT */
+ *chcr = ((u32)slave_id) << 16;
+ auchan->shdma_chan.slave_id = (slave_id) >> 8;
+ return;
+ }
+
+ /* non-DT */
+
if (slave_id >= AUDMAPP_SLAVE_NUMBER)
- return NULL;
+ return;
for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
- if (cfg->slave_id == slave_id)
- return cfg;
-
- return NULL;
+ if (cfg->slave_id == slave_id) {
+ *chcr = cfg->chcr;
+ *dst = cfg->dst;
+ break;
+ }
}
static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
dma_addr_t slave_addr, bool try)
{
struct audmapp_chan *auchan = to_chan(schan);
- struct audmapp_slave_config *cfg =
- audmapp_find_slave(auchan, slave_id);
+ u32 chcr;
+ dma_addr_t dst;
+
+ audmapp_get_config(auchan, slave_id, &chcr, &dst);
- if (!cfg)
- return -ENODEV;
if (try)
return 0;
- auchan->config = cfg;
+ auchan->chcr = chcr;
+ auchan->slave_addr = slave_addr ? : dst;
return 0;
}
static int audmapp_desc_setup(struct shdma_chan *schan,
- struct shdma_desc *sdecs,
+ struct shdma_desc *sdesc,
dma_addr_t src, dma_addr_t dst, size_t *len)
{
- struct audmapp_chan *auchan = to_chan(schan);
- struct audmapp_slave_config *cfg = auchan->config;
-
- if (!cfg)
- return -ENODEV;
+ struct audmapp_desc *desc = to_desc(sdesc);
if (*len > (size_t)AUDMAPP_LEN_MAX)
*len = (size_t)AUDMAPP_LEN_MAX;
+ desc->src = src;
+ desc->dst = dst;
+
return 0;
}
@@ -164,7 +187,9 @@ static void audmapp_setup_xfer(struct shdma_chan *schan,
static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan)
{
- return 0; /* always fixed address */
+ struct audmapp_chan *auchan = to_chan(schan);
+
+ return auchan->slave_addr;
}
static bool audmapp_channel_busy(struct shdma_chan *schan)
@@ -183,7 +208,7 @@ static bool audmapp_desc_completed(struct shdma_chan *schan,
static struct shdma_desc *audmapp_embedded_desc(void *buf, int i)
{
- return &((struct shdma_desc *)buf)[i];
+ return &((struct audmapp_desc *)buf)[i].shdma_desc;
}
static const struct shdma_ops audmapp_shdma_ops = {
@@ -234,16 +259,39 @@ static void audmapp_chan_remove(struct audmapp_device *audev)
dma_dev->chancnt = 0;
}
+static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ u32 chcr = dma_spec->args[0];
+
+ if (dma_spec->args_count != 1)
+ return NULL;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ chan = dma_request_channel(mask, shdma_chan_filter, NULL);
+ if (chan)
+ to_shdma_chan(chan)->hw_req = chcr;
+
+ return chan;
+}
+
static int audmapp_probe(struct platform_device *pdev)
{
struct audmapp_pdata *pdata = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
struct audmapp_device *audev;
struct shdma_dev *sdev;
struct dma_device *dma_dev;
struct resource *res;
int err, i;
- if (!pdata)
+ if (np)
+ of_dma_controller_register(np, audmapp_of_xlate, pdev);
+ else if (!pdata)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -260,7 +308,7 @@ static int audmapp_probe(struct platform_device *pdev)
sdev = &audev->shdma_dev;
sdev->ops = &audmapp_shdma_ops;
- sdev->desc_size = sizeof(struct shdma_desc);
+ sdev->desc_size = sizeof(struct audmapp_desc);
dma_dev = &sdev->dma_dev;
dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE;
@@ -305,12 +353,18 @@ static int audmapp_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id audmapp_of_match[] = {
+ { .compatible = "renesas,rcar-audmapp", },
+ {},
+};
+
static struct platform_driver audmapp_driver = {
.probe = audmapp_probe,
.remove = audmapp_remove,
.driver = {
.owner = THIS_MODULE,
.name = "rcar-audmapp-engine",
+ .of_match_table = audmapp_of_match,
},
};
module_platform_driver(audmapp_driver);
diff --git a/drivers/dma/sh/shdma-arm.h b/drivers/dma/sh/shdma-arm.h
index a2b8258426c9..a1b0ef45d6a2 100644
--- a/drivers/dma/sh/shdma-arm.h
+++ b/drivers/dma/sh/shdma-arm.h
@@ -45,7 +45,7 @@ enum {
((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
(((i) & TS_HI_BIT) << TS_HI_SHIFT))
-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz)))
#endif
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index b35007e21e6b..42d497416196 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -206,45 +206,6 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
return 0;
}
-/*
- * This is the standard shdma filter function to be used as a replacement to the
- * "old" method, using the .private pointer. If for some reason you allocate a
- * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
- * parameter. If this filter is used, the slave driver, after calling
- * dma_request_channel(), will also have to call dmaengine_slave_config() with
- * .slave_id, .direction, and either .src_addr or .dst_addr set.
- * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
- * capability! If this becomes a requirement, hardware glue drivers, using this
- * services would have to provide their own filters, which first would check
- * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
- * this, and only then, in case of a match, call this common filter.
- * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
- * In that case the MID-RID value is used for slave channel filtering and is
- * passed to this function in the "arg" parameter.
- */
-bool shdma_chan_filter(struct dma_chan *chan, void *arg)
-{
- struct shdma_chan *schan = to_shdma_chan(chan);
- struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
- const struct shdma_ops *ops = sdev->ops;
- int match = (long)arg;
- int ret;
-
- if (match < 0)
- /* No slave requested - arbitrary channel */
- return true;
-
- if (!schan->dev->of_node && match >= slave_num)
- return false;
-
- ret = ops->set_slave(schan, match, 0, true);
- if (ret < 0)
- return false;
-
- return true;
-}
-EXPORT_SYMBOL(shdma_chan_filter);
-
static int shdma_alloc_chan_resources(struct dma_chan *chan)
{
struct shdma_chan *schan = to_shdma_chan(chan);
@@ -295,6 +256,51 @@ esetslave:
return ret;
}
+/*
+ * This is the standard shdma filter function to be used as a replacement to the
+ * "old" method, using the .private pointer. If for some reason you allocate a
+ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
+ * parameter. If this filter is used, the slave driver, after calling
+ * dma_request_channel(), will also have to call dmaengine_slave_config() with
+ * .slave_id, .direction, and either .src_addr or .dst_addr set.
+ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
+ * capability! If this becomes a requirement, hardware glue drivers, using this
+ * services would have to provide their own filters, which first would check
+ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
+ * this, and only then, in case of a match, call this common filter.
+ * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
+ * In that case the MID-RID value is used for slave channel filtering and is
+ * passed to this function in the "arg" parameter.
+ */
+bool shdma_chan_filter(struct dma_chan *chan, void *arg)
+{
+ struct shdma_chan *schan;
+ struct shdma_dev *sdev;
+ int match = (long)arg;
+ int ret;
+
+ /* Only support channels handled by this driver. */
+ if (chan->device->device_alloc_chan_resources !=
+ shdma_alloc_chan_resources)
+ return false;
+
+ if (match < 0)
+ /* No slave requested - arbitrary channel */
+ return true;
+
+ schan = to_shdma_chan(chan);
+ if (!schan->dev->of_node && match >= slave_num)
+ return false;
+
+ sdev = to_shdma_dev(schan->dma_chan.device);
+ ret = sdev->ops->set_slave(schan, match, 0, true);
+ if (ret < 0)
+ return false;
+
+ return true;
+}
+EXPORT_SYMBOL(shdma_chan_filter);
+
static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all)
{
struct shdma_desc *desc, *_desc;
@@ -662,15 +668,16 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
static struct dma_async_tx_descriptor *shdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct shdma_chan *schan = to_shdma_chan(chan);
struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+ struct dma_async_tx_descriptor *desc;
const struct shdma_ops *ops = sdev->ops;
unsigned int sg_len = buf_len / period_len;
int slave_id = schan->slave_id;
dma_addr_t slave_addr;
- struct scatterlist sgl[SHDMA_MAX_SG_LEN];
+ struct scatterlist *sgl;
int i;
if (!chan)
@@ -694,7 +701,16 @@ static struct dma_async_tx_descriptor *shdma_prep_dma_cyclic(
slave_addr = ops->slave_addr(schan);
+ /*
+ * Allocate the sg list dynamically as it would consumer too much stack
+ * space.
+ */
+ sgl = kcalloc(sg_len, sizeof(*sgl), GFP_KERNEL);
+ if (!sgl)
+ return NULL;
+
sg_init_table(sgl, sg_len);
+
for (i = 0; i < sg_len; i++) {
dma_addr_t src = buf_addr + (period_len * i);
@@ -704,8 +720,11 @@ static struct dma_async_tx_descriptor *shdma_prep_dma_cyclic(
sg_dma_len(&sgl[i]) = period_len;
}
- return shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
+ desc = shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
direction, flags, true);
+
+ kfree(sgl);
+ return desc;
}
static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
index 758a57b51875..2c0a969adc9f 100644
--- a/drivers/dma/sh/shdma.h
+++ b/drivers/dma/sh/shdma.h
@@ -62,7 +62,7 @@ struct sh_dmae_desc {
#define to_sh_dev(chan) container_of(chan->shdma_chan.dma_chan.device,\
struct sh_dmae_device, shdma_dev.dma_dev)
-#ifdef CONFIG_SHDMA_R8A73A4
+#ifdef CONFIG_SH_DMAE_R8A73A4
extern const struct sh_dmae_pdata r8a73a4_dma_pdata;
#define r8a73a4_shdma_devid (&r8a73a4_dma_pdata)
#else
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c
index 146d5df926db..58eb85770eba 100644
--- a/drivers/dma/sh/shdmac.c
+++ b/drivers/dma/sh/shdmac.c
@@ -38,12 +38,12 @@
#include "../dmaengine.h"
#include "shdma.h"
-/* DMA register */
-#define SAR 0x00
-#define DAR 0x04
-#define TCR 0x08
-#define CHCR 0x0C
-#define DMAOR 0x40
+/* DMA registers */
+#define SAR 0x00 /* Source Address Register */
+#define DAR 0x04 /* Destination Address Register */
+#define TCR 0x08 /* Transfer Count Register */
+#define CHCR 0x0C /* Channel Control Register */
+#define DMAOR 0x40 /* DMA Operation Register */
#define TEND 0x18 /* USB-DMAC */
@@ -239,9 +239,8 @@ static void dmae_init(struct sh_dmae_chan *sh_chan)
{
/*
* Default configuration for dual address memory-memory transfer.
- * 0x400 represents auto-request.
*/
- u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
+ u32 chcr = DM_INC | SM_INC | RS_AUTO | log2size_to_chcr(sh_chan,
LOG2_DEFAULT_XFER_SIZE);
sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
chcr_write(sh_chan, chcr);
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 03f7820fa333..aac03ab10c54 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -580,7 +580,7 @@ err_dir:
static struct dma_async_tx_descriptor *
sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
size_t buf_len, size_t period_len,
- enum dma_transfer_direction direction, unsigned long flags, void *context)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
struct sirfsoc_dma_desc *sdesc = NULL;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index c7984459ede7..5fe59335e247 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2531,8 +2531,7 @@ d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
static struct dma_async_tx_descriptor *
dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
size_t buf_len, size_t period_len,
- enum dma_transfer_direction direction, unsigned long flags,
- void *context)
+ enum dma_transfer_direction direction, unsigned long flags)
{
unsigned int periods = buf_len / period_len;
struct dma_async_tx_descriptor *txd;
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
new file mode 100644
index 000000000000..1f92a56fd2b6
--- /dev/null
+++ b/drivers/dma/sun6i-dma.c
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (C) 2013-2014 Allwinner Tech Co., Ltd
+ * Author: Sugar <shuge@allwinnertech.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "virt-dma.h"
+
+/*
+ * There's 16 physical channels that can work in parallel.
+ *
+ * However we have 30 different endpoints for our requests.
+ *
+ * Since the channels are able to handle only an unidirectional
+ * transfer, we need to allocate more virtual channels so that
+ * everyone can grab one channel.
+ *
+ * Some devices can't work in both direction (mostly because it
+ * wouldn't make sense), so we have a bit fewer virtual channels than
+ * 2 channels per endpoints.
+ */
+
+#define NR_MAX_CHANNELS 16
+#define NR_MAX_REQUESTS 30
+#define NR_MAX_VCHANS 53
+
+/*
+ * Common registers
+ */
+#define DMA_IRQ_EN(x) ((x) * 0x04)
+#define DMA_IRQ_HALF BIT(0)
+#define DMA_IRQ_PKG BIT(1)
+#define DMA_IRQ_QUEUE BIT(2)
+
+#define DMA_IRQ_CHAN_NR 8
+#define DMA_IRQ_CHAN_WIDTH 4
+
+
+#define DMA_IRQ_STAT(x) ((x) * 0x04 + 0x10)
+
+#define DMA_STAT 0x30
+
+/*
+ * Channels specific registers
+ */
+#define DMA_CHAN_ENABLE 0x00
+#define DMA_CHAN_ENABLE_START BIT(0)
+#define DMA_CHAN_ENABLE_STOP 0
+
+#define DMA_CHAN_PAUSE 0x04
+#define DMA_CHAN_PAUSE_PAUSE BIT(1)
+#define DMA_CHAN_PAUSE_RESUME 0
+
+#define DMA_CHAN_LLI_ADDR 0x08
+
+#define DMA_CHAN_CUR_CFG 0x0c
+#define DMA_CHAN_CFG_SRC_DRQ(x) ((x) & 0x1f)
+#define DMA_CHAN_CFG_SRC_IO_MODE BIT(5)
+#define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5)
+#define DMA_CHAN_CFG_SRC_BURST(x) (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
+
+#define DMA_CHAN_CFG_DST_DRQ(x) (DMA_CHAN_CFG_SRC_DRQ(x) << 16)
+#define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16)
+#define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
+#define DMA_CHAN_CFG_DST_BURST(x) (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
+
+#define DMA_CHAN_CUR_SRC 0x10
+
+#define DMA_CHAN_CUR_DST 0x14
+
+#define DMA_CHAN_CUR_CNT 0x18
+
+#define DMA_CHAN_CUR_PARA 0x1c
+
+
+/*
+ * Various hardware related defines
+ */
+#define LLI_LAST_ITEM 0xfffff800
+#define NORMAL_WAIT 8
+#define DRQ_SDRAM 1
+
+/*
+ * Hardware representation of the LLI
+ *
+ * The hardware will be fed the physical address of this structure,
+ * and read its content in order to start the transfer.
+ */
+struct sun6i_dma_lli {
+ u32 cfg;
+ u32 src;
+ u32 dst;
+ u32 len;
+ u32 para;
+ u32 p_lli_next;
+
+ /*
+ * This field is not used by the DMA controller, but will be
+ * used by the CPU to go through the list (mostly for dumping
+ * or freeing it).
+ */
+ struct sun6i_dma_lli *v_lli_next;
+};
+
+
+struct sun6i_desc {
+ struct virt_dma_desc vd;
+ dma_addr_t p_lli;
+ struct sun6i_dma_lli *v_lli;
+};
+
+struct sun6i_pchan {
+ u32 idx;
+ void __iomem *base;
+ struct sun6i_vchan *vchan;
+ struct sun6i_desc *desc;
+ struct sun6i_desc *done;
+};
+
+struct sun6i_vchan {
+ struct virt_dma_chan vc;
+ struct list_head node;
+ struct dma_slave_config cfg;
+ struct sun6i_pchan *phy;
+ u8 port;
+};
+
+struct sun6i_dma_dev {
+ struct dma_device slave;
+ void __iomem *base;
+ struct clk *clk;
+ int irq;
+ spinlock_t lock;
+ struct reset_control *rstc;
+ struct tasklet_struct task;
+ atomic_t tasklet_shutdown;
+ struct list_head pending;
+ struct dma_pool *pool;
+ struct sun6i_pchan *pchans;
+ struct sun6i_vchan *vchans;
+};
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+ return &chan->dev->device;
+}
+
+static inline struct sun6i_dma_dev *to_sun6i_dma_dev(struct dma_device *d)
+{
+ return container_of(d, struct sun6i_dma_dev, slave);
+}
+
+static inline struct sun6i_vchan *to_sun6i_vchan(struct dma_chan *chan)
+{
+ return container_of(chan, struct sun6i_vchan, vc.chan);
+}
+
+static inline struct sun6i_desc *
+to_sun6i_desc(struct dma_async_tx_descriptor *tx)
+{
+ return container_of(tx, struct sun6i_desc, vd.tx);
+}
+
+static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev)
+{
+ dev_dbg(sdev->slave.dev, "Common register:\n"
+ "\tmask0(%04x): 0x%08x\n"
+ "\tmask1(%04x): 0x%08x\n"
+ "\tpend0(%04x): 0x%08x\n"
+ "\tpend1(%04x): 0x%08x\n"
+ "\tstats(%04x): 0x%08x\n",
+ DMA_IRQ_EN(0), readl(sdev->base + DMA_IRQ_EN(0)),
+ DMA_IRQ_EN(1), readl(sdev->base + DMA_IRQ_EN(1)),
+ DMA_IRQ_STAT(0), readl(sdev->base + DMA_IRQ_STAT(0)),
+ DMA_IRQ_STAT(1), readl(sdev->base + DMA_IRQ_STAT(1)),
+ DMA_STAT, readl(sdev->base + DMA_STAT));
+}
+
+static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev,
+ struct sun6i_pchan *pchan)
+{
+ phys_addr_t reg = virt_to_phys(pchan->base);
+
+ dev_dbg(sdev->slave.dev, "Chan %d reg: %pa\n"
+ "\t___en(%04x): \t0x%08x\n"
+ "\tpause(%04x): \t0x%08x\n"
+ "\tstart(%04x): \t0x%08x\n"
+ "\t__cfg(%04x): \t0x%08x\n"
+ "\t__src(%04x): \t0x%08x\n"
+ "\t__dst(%04x): \t0x%08x\n"
+ "\tcount(%04x): \t0x%08x\n"
+ "\t_para(%04x): \t0x%08x\n\n",
+ pchan->idx, &reg,
+ DMA_CHAN_ENABLE,
+ readl(pchan->base + DMA_CHAN_ENABLE),
+ DMA_CHAN_PAUSE,
+ readl(pchan->base + DMA_CHAN_PAUSE),
+ DMA_CHAN_LLI_ADDR,
+ readl(pchan->base + DMA_CHAN_LLI_ADDR),
+ DMA_CHAN_CUR_CFG,
+ readl(pchan->base + DMA_CHAN_CUR_CFG),
+ DMA_CHAN_CUR_SRC,
+ readl(pchan->base + DMA_CHAN_CUR_SRC),
+ DMA_CHAN_CUR_DST,
+ readl(pchan->base + DMA_CHAN_CUR_DST),
+ DMA_CHAN_CUR_CNT,
+ readl(pchan->base + DMA_CHAN_CUR_CNT),
+ DMA_CHAN_CUR_PARA,
+ readl(pchan->base + DMA_CHAN_CUR_PARA));
+}
+
+static inline int convert_burst(u32 maxburst, u8 *burst)
+{
+ switch (maxburst) {
+ case 1:
+ *burst = 0;
+ break;
+ case 8:
+ *burst = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int convert_buswidth(enum dma_slave_buswidth addr_width, u8 *width)
+{
+ if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
+ (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
+ return -EINVAL;
+
+ *width = addr_width >> 1;
+ return 0;
+}
+
+static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev,
+ struct sun6i_dma_lli *next,
+ dma_addr_t next_phy,
+ struct sun6i_desc *txd)
+{
+ if ((!prev && !txd) || !next)
+ return NULL;
+
+ if (!prev) {
+ txd->p_lli = next_phy;
+ txd->v_lli = next;
+ } else {
+ prev->p_lli_next = next_phy;
+ prev->v_lli_next = next;
+ }
+
+ next->p_lli_next = LLI_LAST_ITEM;
+ next->v_lli_next = NULL;
+
+ return next;
+}
+
+static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli,
+ dma_addr_t src,
+ dma_addr_t dst, u32 len,
+ struct dma_slave_config *config)
+{
+ u8 src_width, dst_width, src_burst, dst_burst;
+ int ret;
+
+ if (!config)
+ return -EINVAL;
+
+ ret = convert_burst(config->src_maxburst, &src_burst);
+ if (ret)
+ return ret;
+
+ ret = convert_burst(config->dst_maxburst, &dst_burst);
+ if (ret)
+ return ret;
+
+ ret = convert_buswidth(config->src_addr_width, &src_width);
+ if (ret)
+ return ret;
+
+ ret = convert_buswidth(config->dst_addr_width, &dst_width);
+ if (ret)
+ return ret;
+
+ lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
+ DMA_CHAN_CFG_SRC_WIDTH(src_width) |
+ DMA_CHAN_CFG_DST_BURST(dst_burst) |
+ DMA_CHAN_CFG_DST_WIDTH(dst_width);
+
+ lli->src = src;
+ lli->dst = dst;
+ lli->len = len;
+ lli->para = NORMAL_WAIT;
+
+ return 0;
+}
+
+static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan,
+ struct sun6i_dma_lli *lli)
+{
+ phys_addr_t p_lli = virt_to_phys(lli);
+
+ dev_dbg(chan2dev(&vchan->vc.chan),
+ "\n\tdesc: p - %pa v - 0x%p\n"
+ "\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n"
+ "\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n",
+ &p_lli, lli,
+ lli->cfg, lli->src, lli->dst,
+ lli->len, lli->para, lli->p_lli_next);
+}
+
+static void sun6i_dma_free_desc(struct virt_dma_desc *vd)
+{
+ struct sun6i_desc *txd = to_sun6i_desc(&vd->tx);
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vd->tx.chan->device);
+ struct sun6i_dma_lli *v_lli, *v_next;
+ dma_addr_t p_lli, p_next;
+
+ if (unlikely(!txd))
+ return;
+
+ p_lli = txd->p_lli;
+ v_lli = txd->v_lli;
+
+ while (v_lli) {
+ v_next = v_lli->v_lli_next;
+ p_next = v_lli->p_lli_next;
+
+ dma_pool_free(sdev->pool, v_lli, p_lli);
+
+ v_lli = v_next;
+ p_lli = p_next;
+ }
+
+ kfree(txd);
+}
+
+static int sun6i_dma_terminate_all(struct sun6i_vchan *vchan)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
+ struct sun6i_pchan *pchan = vchan->phy;
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock(&sdev->lock);
+ list_del_init(&vchan->node);
+ spin_unlock(&sdev->lock);
+
+ spin_lock_irqsave(&vchan->vc.lock, flags);
+
+ vchan_get_all_descriptors(&vchan->vc, &head);
+
+ if (pchan) {
+ writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE);
+ writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE);
+
+ vchan->phy = NULL;
+ pchan->vchan = NULL;
+ pchan->desc = NULL;
+ pchan->done = NULL;
+ }
+
+ spin_unlock_irqrestore(&vchan->vc.lock, flags);
+
+ vchan_dma_desc_free_list(&vchan->vc, &head);
+
+ return 0;
+}
+
+static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device);
+ struct virt_dma_desc *desc = vchan_next_desc(&vchan->vc);
+ struct sun6i_pchan *pchan = vchan->phy;
+ u32 irq_val, irq_reg, irq_offset;
+
+ if (!pchan)
+ return -EAGAIN;
+
+ if (!desc) {
+ pchan->desc = NULL;
+ pchan->done = NULL;
+ return -EAGAIN;
+ }
+
+ list_del(&desc->node);
+
+ pchan->desc = to_sun6i_desc(&desc->tx);
+ pchan->done = NULL;
+
+ sun6i_dma_dump_lli(vchan, pchan->desc->v_lli);
+
+ irq_reg = pchan->idx / DMA_IRQ_CHAN_NR;
+ irq_offset = pchan->idx % DMA_IRQ_CHAN_NR;
+
+ irq_val = readl(sdev->base + DMA_IRQ_EN(irq_offset));
+ irq_val |= DMA_IRQ_QUEUE << (irq_offset * DMA_IRQ_CHAN_WIDTH);
+ writel(irq_val, sdev->base + DMA_IRQ_EN(irq_offset));
+
+ writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR);
+ writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE);
+
+ sun6i_dma_dump_com_regs(sdev);
+ sun6i_dma_dump_chan_regs(sdev, pchan);
+
+ return 0;
+}
+
+static void sun6i_dma_tasklet(unsigned long data)
+{
+ struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
+ struct sun6i_vchan *vchan;
+ struct sun6i_pchan *pchan;
+ unsigned int pchan_alloc = 0;
+ unsigned int pchan_idx;
+
+ list_for_each_entry(vchan, &sdev->slave.channels, vc.chan.device_node) {
+ spin_lock_irq(&vchan->vc.lock);
+
+ pchan = vchan->phy;
+
+ if (pchan && pchan->done) {
+ if (sun6i_dma_start_desc(vchan)) {
+ /*
+ * No current txd associated with this channel
+ */
+ dev_dbg(sdev->slave.dev, "pchan %u: free\n",
+ pchan->idx);
+
+ /* Mark this channel free */
+ vchan->phy = NULL;
+ pchan->vchan = NULL;
+ }
+ }
+ spin_unlock_irq(&vchan->vc.lock);
+ }
+
+ spin_lock_irq(&sdev->lock);
+ for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+ pchan = &sdev->pchans[pchan_idx];
+
+ if (pchan->vchan || list_empty(&sdev->pending))
+ continue;
+
+ vchan = list_first_entry(&sdev->pending,
+ struct sun6i_vchan, node);
+
+ /* Remove from pending channels */
+ list_del_init(&vchan->node);
+ pchan_alloc |= BIT(pchan_idx);
+
+ /* Mark this channel allocated */
+ pchan->vchan = vchan;
+ vchan->phy = pchan;
+ dev_dbg(sdev->slave.dev, "pchan %u: alloc vchan %p\n",
+ pchan->idx, &vchan->vc);
+ }
+ spin_unlock_irq(&sdev->lock);
+
+ for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+ if (!(pchan_alloc & BIT(pchan_idx)))
+ continue;
+
+ pchan = sdev->pchans + pchan_idx;
+ vchan = pchan->vchan;
+ if (vchan) {
+ spin_lock_irq(&vchan->vc.lock);
+ sun6i_dma_start_desc(vchan);
+ spin_unlock_irq(&vchan->vc.lock);
+ }
+ }
+}
+
+static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
+{
+ struct sun6i_dma_dev *sdev = dev_id;
+ struct sun6i_vchan *vchan;
+ struct sun6i_pchan *pchan;
+ int i, j, ret = IRQ_NONE;
+ u32 status;
+
+ for (i = 0; i < 2; i++) {
+ status = readl(sdev->base + DMA_IRQ_STAT(i));
+ if (!status)
+ continue;
+
+ dev_dbg(sdev->slave.dev, "DMA irq status %s: 0x%x\n",
+ i ? "high" : "low", status);
+
+ writel(status, sdev->base + DMA_IRQ_STAT(i));
+
+ for (j = 0; (j < 8) && status; j++) {
+ if (status & DMA_IRQ_QUEUE) {
+ pchan = sdev->pchans + j;
+ vchan = pchan->vchan;
+
+ if (vchan) {
+ spin_lock(&vchan->vc.lock);
+ vchan_cookie_complete(&pchan->desc->vd);
+ pchan->done = pchan->desc;
+ spin_unlock(&vchan->vc.lock);
+ }
+ }
+
+ status = status >> 4;
+ }
+
+ if (!atomic_read(&sdev->tasklet_shutdown))
+ tasklet_schedule(&sdev->task);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ struct dma_slave_config *sconfig = &vchan->cfg;
+ struct sun6i_dma_lli *v_lli;
+ struct sun6i_desc *txd;
+ dma_addr_t p_lli;
+ int ret;
+
+ dev_dbg(chan2dev(chan),
+ "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n",
+ __func__, vchan->vc.chan.chan_id, &dest, &src, len, flags);
+
+ if (!len)
+ return NULL;
+
+ txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+ if (!txd)
+ return NULL;
+
+ v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
+ if (!v_lli) {
+ dev_err(sdev->slave.dev, "Failed to alloc lli memory\n");
+ goto err_txd_free;
+ }
+
+ ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig);
+ if (ret)
+ goto err_dma_free;
+
+ v_lli->cfg |= DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
+ DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
+ DMA_CHAN_CFG_DST_LINEAR_MODE |
+ DMA_CHAN_CFG_SRC_LINEAR_MODE;
+
+ sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
+
+ sun6i_dma_dump_lli(vchan, v_lli);
+
+ return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
+
+err_dma_free:
+ dma_pool_free(sdev->pool, v_lli, p_lli);
+err_txd_free:
+ kfree(txd);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction dir,
+ unsigned long flags, void *context)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ struct dma_slave_config *sconfig = &vchan->cfg;
+ struct sun6i_dma_lli *v_lli, *prev = NULL;
+ struct sun6i_desc *txd;
+ struct scatterlist *sg;
+ dma_addr_t p_lli;
+ int i, ret;
+
+ if (!sgl)
+ return NULL;
+
+ if (!is_slave_direction(dir)) {
+ dev_err(chan2dev(chan), "Invalid DMA direction\n");
+ return NULL;
+ }
+
+ txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+ if (!txd)
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
+ if (!v_lli)
+ goto err_lli_free;
+
+ if (dir == DMA_MEM_TO_DEV) {
+ ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg),
+ sconfig->dst_addr, sg_dma_len(sg),
+ sconfig);
+ if (ret)
+ goto err_cur_lli_free;
+
+ v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE |
+ DMA_CHAN_CFG_SRC_LINEAR_MODE |
+ DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
+ DMA_CHAN_CFG_DST_DRQ(vchan->port);
+
+ dev_dbg(chan2dev(chan),
+ "%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
+ __func__, vchan->vc.chan.chan_id,
+ &sconfig->dst_addr, &sg_dma_address(sg),
+ sg_dma_len(sg), flags);
+
+ } else {
+ ret = sun6i_dma_cfg_lli(v_lli, sconfig->src_addr,
+ sg_dma_address(sg), sg_dma_len(sg),
+ sconfig);
+ if (ret)
+ goto err_cur_lli_free;
+
+ v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE |
+ DMA_CHAN_CFG_SRC_IO_MODE |
+ DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
+ DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+
+ dev_dbg(chan2dev(chan),
+ "%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
+ __func__, vchan->vc.chan.chan_id,
+ &sg_dma_address(sg), &sconfig->src_addr,
+ sg_dma_len(sg), flags);
+ }
+
+ prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
+ }
+
+ dev_dbg(chan2dev(chan), "First: %pad\n", &txd->p_lli);
+ for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+ sun6i_dma_dump_lli(vchan, prev);
+
+ return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
+
+err_cur_lli_free:
+ dma_pool_free(sdev->pool, v_lli, p_lli);
+err_lli_free:
+ for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+ dma_pool_free(sdev->pool, prev, virt_to_phys(prev));
+ kfree(txd);
+ return NULL;
+}
+
+static int sun6i_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ struct sun6i_pchan *pchan = vchan->phy;
+ unsigned long flags;
+ int ret = 0;
+
+ switch (cmd) {
+ case DMA_RESUME:
+ dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc);
+
+ spin_lock_irqsave(&vchan->vc.lock, flags);
+
+ if (pchan) {
+ writel(DMA_CHAN_PAUSE_RESUME,
+ pchan->base + DMA_CHAN_PAUSE);
+ } else if (!list_empty(&vchan->vc.desc_issued)) {
+ spin_lock(&sdev->lock);
+ list_add_tail(&vchan->node, &sdev->pending);
+ spin_unlock(&sdev->lock);
+ }
+
+ spin_unlock_irqrestore(&vchan->vc.lock, flags);
+ break;
+
+ case DMA_PAUSE:
+ dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc);
+
+ if (pchan) {
+ writel(DMA_CHAN_PAUSE_PAUSE,
+ pchan->base + DMA_CHAN_PAUSE);
+ } else {
+ spin_lock(&sdev->lock);
+ list_del_init(&vchan->node);
+ spin_unlock(&sdev->lock);
+ }
+ break;
+
+ case DMA_TERMINATE_ALL:
+ ret = sun6i_dma_terminate_all(vchan);
+ break;
+ case DMA_SLAVE_CONFIG:
+ memcpy(&vchan->cfg, (void *)arg, sizeof(struct dma_slave_config));
+ break;
+ default:
+ ret = -ENXIO;
+ break;
+ }
+ return ret;
+}
+
+static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *state)
+{
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ struct sun6i_pchan *pchan = vchan->phy;
+ struct sun6i_dma_lli *lli;
+ struct virt_dma_desc *vd;
+ struct sun6i_desc *txd;
+ enum dma_status ret;
+ unsigned long flags;
+ size_t bytes = 0;
+
+ ret = dma_cookie_status(chan, cookie, state);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ spin_lock_irqsave(&vchan->vc.lock, flags);
+
+ vd = vchan_find_desc(&vchan->vc, cookie);
+ txd = to_sun6i_desc(&vd->tx);
+
+ if (vd) {
+ for (lli = txd->v_lli; lli != NULL; lli = lli->v_lli_next)
+ bytes += lli->len;
+ } else if (!pchan || !pchan->desc) {
+ bytes = 0;
+ } else {
+ bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
+ }
+
+ spin_unlock_irqrestore(&vchan->vc.lock, flags);
+
+ dma_set_residue(state, bytes);
+
+ return ret;
+}
+
+static void sun6i_dma_issue_pending(struct dma_chan *chan)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&vchan->vc.lock, flags);
+
+ if (vchan_issue_pending(&vchan->vc)) {
+ spin_lock(&sdev->lock);
+
+ if (!vchan->phy && list_empty(&vchan->node)) {
+ list_add_tail(&vchan->node, &sdev->pending);
+ tasklet_schedule(&sdev->task);
+ dev_dbg(chan2dev(chan), "vchan %p: issued\n",
+ &vchan->vc);
+ }
+
+ spin_unlock(&sdev->lock);
+ } else {
+ dev_dbg(chan2dev(chan), "vchan %p: nothing to issue\n",
+ &vchan->vc);
+ }
+
+ spin_unlock_irqrestore(&vchan->vc.lock, flags);
+}
+
+static int sun6i_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ return 0;
+}
+
+static void sun6i_dma_free_chan_resources(struct dma_chan *chan)
+{
+ struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+ struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdev->lock, flags);
+ list_del_init(&vchan->node);
+ spin_unlock_irqrestore(&sdev->lock, flags);
+
+ vchan_free_chan_resources(&vchan->vc);
+}
+
+static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct sun6i_dma_dev *sdev = ofdma->of_dma_data;
+ struct sun6i_vchan *vchan;
+ struct dma_chan *chan;
+ u8 port = dma_spec->args[0];
+
+ if (port > NR_MAX_REQUESTS)
+ return NULL;
+
+ chan = dma_get_any_slave_channel(&sdev->slave);
+ if (!chan)
+ return NULL;
+
+ vchan = to_sun6i_vchan(chan);
+ vchan->port = port;
+
+ return chan;
+}
+
+static inline void sun6i_kill_tasklet(struct sun6i_dma_dev *sdev)
+{
+ /* Disable all interrupts from DMA */
+ writel(0, sdev->base + DMA_IRQ_EN(0));
+ writel(0, sdev->base + DMA_IRQ_EN(1));
+
+ /* Prevent spurious interrupts from scheduling the tasklet */
+ atomic_inc(&sdev->tasklet_shutdown);
+
+ /* Make sure we won't have any further interrupts */
+ devm_free_irq(sdev->slave.dev, sdev->irq, sdev);
+
+ /* Actually prevent the tasklet from being scheduled */
+ tasklet_kill(&sdev->task);
+}
+
+static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
+{
+ int i;
+
+ for (i = 0; i < NR_MAX_VCHANS; i++) {
+ struct sun6i_vchan *vchan = &sdev->vchans[i];
+
+ list_del(&vchan->vc.chan.device_node);
+ tasklet_kill(&vchan->vc.task);
+ }
+}
+
+static int sun6i_dma_probe(struct platform_device *pdev)
+{
+ struct sun6i_dma_dev *sdc;
+ struct resource *res;
+ struct clk *mux, *pll6;
+ int ret, i;
+
+ sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
+ if (!sdc)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sdc->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(sdc->base))
+ return PTR_ERR(sdc->base);
+
+ sdc->irq = platform_get_irq(pdev, 0);
+ if (sdc->irq < 0) {
+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
+ return sdc->irq;
+ }
+
+ sdc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sdc->clk)) {
+ dev_err(&pdev->dev, "No clock specified\n");
+ return PTR_ERR(sdc->clk);
+ }
+
+ mux = clk_get(NULL, "ahb1_mux");
+ if (IS_ERR(mux)) {
+ dev_err(&pdev->dev, "Couldn't get AHB1 Mux\n");
+ return PTR_ERR(mux);
+ }
+
+ pll6 = clk_get(NULL, "pll6");
+ if (IS_ERR(pll6)) {
+ dev_err(&pdev->dev, "Couldn't get PLL6\n");
+ clk_put(mux);
+ return PTR_ERR(pll6);
+ }
+
+ ret = clk_set_parent(mux, pll6);
+ clk_put(pll6);
+ clk_put(mux);
+
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't reparent AHB1 on PLL6\n");
+ return ret;
+ }
+
+ sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(sdc->rstc)) {
+ dev_err(&pdev->dev, "No reset controller specified\n");
+ return PTR_ERR(sdc->rstc);
+ }
+
+ sdc->pool = dmam_pool_create(dev_name(&pdev->dev), &pdev->dev,
+ sizeof(struct sun6i_dma_lli), 4, 0);
+ if (!sdc->pool) {
+ dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, sdc);
+ INIT_LIST_HEAD(&sdc->pending);
+ spin_lock_init(&sdc->lock);
+
+ dma_cap_set(DMA_PRIVATE, sdc->slave.cap_mask);
+ dma_cap_set(DMA_MEMCPY, sdc->slave.cap_mask);
+ dma_cap_set(DMA_SLAVE, sdc->slave.cap_mask);
+
+ INIT_LIST_HEAD(&sdc->slave.channels);
+ sdc->slave.device_alloc_chan_resources = sun6i_dma_alloc_chan_resources;
+ sdc->slave.device_free_chan_resources = sun6i_dma_free_chan_resources;
+ sdc->slave.device_tx_status = sun6i_dma_tx_status;
+ sdc->slave.device_issue_pending = sun6i_dma_issue_pending;
+ sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg;
+ sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy;
+ sdc->slave.device_control = sun6i_dma_control;
+ sdc->slave.chancnt = NR_MAX_VCHANS;
+
+ sdc->slave.dev = &pdev->dev;
+
+ sdc->pchans = devm_kcalloc(&pdev->dev, NR_MAX_CHANNELS,
+ sizeof(struct sun6i_pchan), GFP_KERNEL);
+ if (!sdc->pchans)
+ return -ENOMEM;
+
+ sdc->vchans = devm_kcalloc(&pdev->dev, NR_MAX_VCHANS,
+ sizeof(struct sun6i_vchan), GFP_KERNEL);
+ if (!sdc->vchans)
+ return -ENOMEM;
+
+ tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
+
+ for (i = 0; i < NR_MAX_CHANNELS; i++) {
+ struct sun6i_pchan *pchan = &sdc->pchans[i];
+
+ pchan->idx = i;
+ pchan->base = sdc->base + 0x100 + i * 0x40;
+ }
+
+ for (i = 0; i < NR_MAX_VCHANS; i++) {
+ struct sun6i_vchan *vchan = &sdc->vchans[i];
+
+ INIT_LIST_HEAD(&vchan->node);
+ vchan->vc.desc_free = sun6i_dma_free_desc;
+ vchan_init(&vchan->vc, &sdc->slave);
+ }
+
+ ret = reset_control_deassert(sdc->rstc);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't deassert the device from reset\n");
+ goto err_chan_free;
+ }
+
+ ret = clk_prepare_enable(sdc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable the clock\n");
+ goto err_reset_assert;
+ }
+
+ ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
+ dev_name(&pdev->dev), sdc);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot request IRQ\n");
+ goto err_clk_disable;
+ }
+
+ ret = dma_async_device_register(&sdc->slave);
+ if (ret) {
+ dev_warn(&pdev->dev, "Failed to register DMA engine device\n");
+ goto err_irq_disable;
+ }
+
+ ret = of_dma_controller_register(pdev->dev.of_node, sun6i_dma_of_xlate,
+ sdc);
+ if (ret) {
+ dev_err(&pdev->dev, "of_dma_controller_register failed\n");
+ goto err_dma_unregister;
+ }
+
+ return 0;
+
+err_dma_unregister:
+ dma_async_device_unregister(&sdc->slave);
+err_irq_disable:
+ sun6i_kill_tasklet(sdc);
+err_clk_disable:
+ clk_disable_unprepare(sdc->clk);
+err_reset_assert:
+ reset_control_assert(sdc->rstc);
+err_chan_free:
+ sun6i_dma_free(sdc);
+ return ret;
+}
+
+static int sun6i_dma_remove(struct platform_device *pdev)
+{
+ struct sun6i_dma_dev *sdc = platform_get_drvdata(pdev);
+
+ of_dma_controller_free(pdev->dev.of_node);
+ dma_async_device_unregister(&sdc->slave);
+
+ sun6i_kill_tasklet(sdc);
+
+ clk_disable_unprepare(sdc->clk);
+ reset_control_assert(sdc->rstc);
+
+ sun6i_dma_free(sdc);
+
+ return 0;
+}
+
+static struct of_device_id sun6i_dma_match[] = {
+ { .compatible = "allwinner,sun6i-a31-dma" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun6i_dma_driver = {
+ .probe = sun6i_dma_probe,
+ .remove = sun6i_dma_remove,
+ .driver = {
+ .name = "sun6i-dma",
+ .of_match_table = sun6i_dma_match,
+ },
+};
+module_platform_driver(sun6i_dma_driver);
+
+MODULE_DESCRIPTION("Allwinner A31 DMA Controller Driver");
+MODULE_AUTHOR("Sugar <shuge@allwinnertech.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 03ad64ecaaf0..16efa603ff65 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1055,7 +1055,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+ unsigned long flags)
{
struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
struct tegra_dma_desc *dma_desc = NULL;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 878f09005fad..fd89ca982748 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -72,6 +72,7 @@ config EDAC_MCE_INJ
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+ select RAS
help
Some systems are able to detect and correct errors in main
memory. EDAC can report statistics on memory error
@@ -186,6 +187,13 @@ config EDAC_I3200
Support for error detection and correction on the Intel
3200 and 3210 server chipsets.
+config EDAC_IE31200
+ tristate "Intel e312xx"
+ depends on EDAC_MM_EDAC && PCI && X86
+ help
+ Support for error detection and correction on the Intel
+ E3-1200 based DRAM controllers.
+
config EDAC_X38
tristate "Intel X38"
depends on EDAC_MM_EDAC && PCI && X86
@@ -245,12 +253,12 @@ config EDAC_I7300
Clarksboro MCH (Intel 7300 chipset).
config EDAC_SBRIDGE
- tristate "Intel Sandy-Bridge Integrated MC"
+ tristate "Intel Sandy-Bridge/Ivy-Bridge/Haswell Integrated MC"
depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL
depends on PCI_MMCONFIG
help
Support for error detection and correction the Intel
- Sandy Bridge Integrated Memory Controller.
+ Sandy Bridge, Ivy Bridge and Haswell Integrated Memory Controllers.
config EDAC_MPC85XX
tristate "Freescale MPC83xx / MPC85xx"
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 4154ed6a02c6..c479a24d8f77 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
obj-$(CONFIG_EDAC_I82975X) += i82975x_edac.o
obj-$(CONFIG_EDAC_I3000) += i3000_edac.o
obj-$(CONFIG_EDAC_I3200) += i3200_edac.o
+obj-$(CONFIG_EDAC_IE31200) += ie31200_edac.o
obj-$(CONFIG_EDAC_X38) += x38_edac.o
obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index 374b57fc596d..a12c8552f6a6 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -134,8 +134,7 @@ static void cell_edac_init_csrows(struct mem_ctl_info *mci)
int j;
u32 nr_pages;
- for (np = NULL;
- (np = of_find_node_by_name(np, "memory")) != NULL;) {
+ for_each_node_by_name(np, "memory") {
struct resource r;
/* We "know" that the Cell firmware only creates one entry
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 2c694b5297cc..9f134823fa75 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -33,9 +33,6 @@
#include <asm/edac.h>
#include "edac_core.h"
#include "edac_module.h"
-
-#define CREATE_TRACE_POINTS
-#define TRACE_INCLUDE_PATH ../../include/ras
#include <ras/ras_event.h>
/* lock to memory controller's control array */
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 01fae8289cf0..a6cd36100663 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -108,7 +108,9 @@ static const char * const mem_types[] = {
[MEM_RDDR2] = "Registered-DDR2",
[MEM_XDR] = "XDR",
[MEM_DDR3] = "Unbuffered-DDR3",
- [MEM_RDDR3] = "Registered-DDR3"
+ [MEM_RDDR3] = "Registered-DDR3",
+ [MEM_DDR4] = "Unbuffered-DDR4",
+ [MEM_RDDR4] = "Registered-DDR4"
};
static const char * const dev_types[] = {
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index a66941fea5a4..e6d1691dfa45 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -28,7 +28,7 @@ static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
if (ret)
return ret;
- if (val < 0 || val > 4)
+ if (val > 4)
return -EINVAL;
return param_set_int(buf, kp);
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
new file mode 100644
index 000000000000..a981dc6fd88e
--- /dev/null
+++ b/drivers/edac/ie31200_edac.c
@@ -0,0 +1,536 @@
+/*
+ * Intel E3-1200
+ * Copyright (C) 2014 Jason Baron <jbaron@akamai.com>
+ *
+ * Support for the E3-1200 processor family. Heavily based on previous
+ * Intel EDAC drivers.
+ *
+ * Since the DRAM controller is on the cpu chip, we can use its PCI device
+ * id to identify these processors.
+ *
+ * PCI DRAM controller device ids (Taken from The PCI ID Repository - http://pci-ids.ucw.cz/)
+ *
+ * 0108: Xeon E3-1200 Processor Family DRAM Controller
+ * 010c: Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller
+ * 0150: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
+ * 0158: Xeon E3-1200 v2/Ivy Bridge DRAM Controller
+ * 015c: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
+ * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
+ * 0c08: Xeon E3-1200 v3 Processor DRAM Controller
+ *
+ * Based on Intel specification:
+ * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
+ * http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
+ *
+ * According to the above datasheet (p.16):
+ * "
+ * 6. Software must not access B0/D0/F0 32-bit memory-mapped registers with
+ * requests that cross a DW boundary.
+ * "
+ *
+ * Thus, we make use of the explicit: lo_hi_readq(), which breaks the readq into
+ * 2 readl() calls. This restriction may be lifted in subsequent chip releases,
+ * but lo_hi_readq() ensures that we are safe across all e3-1200 processors.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/edac.h>
+
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+#include "edac_core.h"
+
+#define IE31200_REVISION "1.0"
+#define EDAC_MOD_STR "ie31200_edac"
+
+#define ie31200_printk(level, fmt, arg...) \
+ edac_printk(level, "ie31200", fmt, ##arg)
+
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_1 0x0108
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_2 0x010c
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_3 0x0150
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_4 0x0158
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_5 0x015c
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08
+
+#define IE31200_DIMMS 4
+#define IE31200_RANKS 8
+#define IE31200_RANKS_PER_CHANNEL 4
+#define IE31200_DIMMS_PER_CHANNEL 2
+#define IE31200_CHANNELS 2
+
+/* Intel IE31200 register addresses - device 0 function 0 - DRAM Controller */
+#define IE31200_MCHBAR_LOW 0x48
+#define IE31200_MCHBAR_HIGH 0x4c
+#define IE31200_MCHBAR_MASK GENMASK_ULL(38, 15)
+#define IE31200_MMR_WINDOW_SIZE BIT(15)
+
+/*
+ * Error Status Register (16b)
+ *
+ * 15 reserved
+ * 14 Isochronous TBWRR Run Behind FIFO Full
+ * (ITCV)
+ * 13 Isochronous TBWRR Run Behind FIFO Put
+ * (ITSTV)
+ * 12 reserved
+ * 11 MCH Thermal Sensor Event
+ * for SMI/SCI/SERR (GTSE)
+ * 10 reserved
+ * 9 LOCK to non-DRAM Memory Flag (LCKF)
+ * 8 reserved
+ * 7 DRAM Throttle Flag (DTF)
+ * 6:2 reserved
+ * 1 Multi-bit DRAM ECC Error Flag (DMERR)
+ * 0 Single-bit DRAM ECC Error Flag (DSERR)
+ */
+#define IE31200_ERRSTS 0xc8
+#define IE31200_ERRSTS_UE BIT(1)
+#define IE31200_ERRSTS_CE BIT(0)
+#define IE31200_ERRSTS_BITS (IE31200_ERRSTS_UE | IE31200_ERRSTS_CE)
+
+/*
+ * Channel 0 ECC Error Log (64b)
+ *
+ * 63:48 Error Column Address (ERRCOL)
+ * 47:32 Error Row Address (ERRROW)
+ * 31:29 Error Bank Address (ERRBANK)
+ * 28:27 Error Rank Address (ERRRANK)
+ * 26:24 reserved
+ * 23:16 Error Syndrome (ERRSYND)
+ * 15: 2 reserved
+ * 1 Multiple Bit Error Status (MERRSTS)
+ * 0 Correctable Error Status (CERRSTS)
+ */
+#define IE31200_C0ECCERRLOG 0x40c8
+#define IE31200_C1ECCERRLOG 0x44c8
+#define IE31200_ECCERRLOG_CE BIT(0)
+#define IE31200_ECCERRLOG_UE BIT(1)
+#define IE31200_ECCERRLOG_RANK_BITS GENMASK_ULL(28, 27)
+#define IE31200_ECCERRLOG_RANK_SHIFT 27
+#define IE31200_ECCERRLOG_SYNDROME_BITS GENMASK_ULL(23, 16)
+#define IE31200_ECCERRLOG_SYNDROME_SHIFT 16
+
+#define IE31200_ECCERRLOG_SYNDROME(log) \
+ ((log & IE31200_ECCERRLOG_SYNDROME_BITS) >> \
+ IE31200_ECCERRLOG_SYNDROME_SHIFT)
+
+#define IE31200_CAPID0 0xe4
+#define IE31200_CAPID0_PDCD BIT(4)
+#define IE31200_CAPID0_DDPCD BIT(6)
+#define IE31200_CAPID0_ECC BIT(1)
+
+#define IE31200_MAD_DIMM_0_OFFSET 0x5004
+#define IE31200_MAD_DIMM_SIZE GENMASK_ULL(7, 0)
+#define IE31200_MAD_DIMM_A_RANK BIT(17)
+#define IE31200_MAD_DIMM_A_WIDTH BIT(19)
+
+#define IE31200_PAGES(n) (n << (28 - PAGE_SHIFT))
+
+static int nr_channels;
+
+struct ie31200_priv {
+ void __iomem *window;
+};
+
+enum ie31200_chips {
+ IE31200 = 0,
+};
+
+struct ie31200_dev_info {
+ const char *ctl_name;
+};
+
+struct ie31200_error_info {
+ u16 errsts;
+ u16 errsts2;
+ u64 eccerrlog[IE31200_CHANNELS];
+};
+
+static const struct ie31200_dev_info ie31200_devs[] = {
+ [IE31200] = {
+ .ctl_name = "IE31200"
+ },
+};
+
+struct dimm_data {
+ u8 size; /* in 256MB multiples */
+ u8 dual_rank : 1,
+ x16_width : 1; /* 0 means x8 width */
+};
+
+static int how_many_channels(struct pci_dev *pdev)
+{
+ int n_channels;
+ unsigned char capid0_2b; /* 2nd byte of CAPID0 */
+
+ pci_read_config_byte(pdev, IE31200_CAPID0 + 1, &capid0_2b);
+
+ /* check PDCD: Dual Channel Disable */
+ if (capid0_2b & IE31200_CAPID0_PDCD) {
+ edac_dbg(0, "In single channel mode\n");
+ n_channels = 1;
+ } else {
+ edac_dbg(0, "In dual channel mode\n");
+ n_channels = 2;
+ }
+
+ /* check DDPCD - check if both channels are filled */
+ if (capid0_2b & IE31200_CAPID0_DDPCD)
+ edac_dbg(0, "2 DIMMS per channel disabled\n");
+ else
+ edac_dbg(0, "2 DIMMS per channel enabled\n");
+
+ return n_channels;
+}
+
+static bool ecc_capable(struct pci_dev *pdev)
+{
+ unsigned char capid0_4b; /* 4th byte of CAPID0 */
+
+ pci_read_config_byte(pdev, IE31200_CAPID0 + 3, &capid0_4b);
+ if (capid0_4b & IE31200_CAPID0_ECC)
+ return false;
+ return true;
+}
+
+static int eccerrlog_row(int channel, u64 log)
+{
+ int rank = ((log & IE31200_ECCERRLOG_RANK_BITS) >>
+ IE31200_ECCERRLOG_RANK_SHIFT);
+ return rank | (channel * IE31200_RANKS_PER_CHANNEL);
+}
+
+static void ie31200_clear_error_info(struct mem_ctl_info *mci)
+{
+ /*
+ * Clear any error bits.
+ * (Yes, we really clear bits by writing 1 to them.)
+ */
+ pci_write_bits16(to_pci_dev(mci->pdev), IE31200_ERRSTS,
+ IE31200_ERRSTS_BITS, IE31200_ERRSTS_BITS);
+}
+
+static void ie31200_get_and_clear_error_info(struct mem_ctl_info *mci,
+ struct ie31200_error_info *info)
+{
+ struct pci_dev *pdev;
+ struct ie31200_priv *priv = mci->pvt_info;
+ void __iomem *window = priv->window;
+
+ pdev = to_pci_dev(mci->pdev);
+
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts);
+ if (!(info->errsts & IE31200_ERRSTS_BITS))
+ return;
+
+ info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+ if (nr_channels == 2)
+ info->eccerrlog[1] = lo_hi_readq(window + IE31200_C1ECCERRLOG);
+
+ pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts2);
+
+ /*
+ * If the error is the same for both reads then the first set
+ * of reads is valid. If there is a change then there is a CE
+ * with no info and the second set of reads is valid and
+ * should be UE info.
+ */
+ if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) {
+ info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+ if (nr_channels == 2)
+ info->eccerrlog[1] =
+ lo_hi_readq(window + IE31200_C1ECCERRLOG);
+ }
+
+ ie31200_clear_error_info(mci);
+}
+
+static void ie31200_process_error_info(struct mem_ctl_info *mci,
+ struct ie31200_error_info *info)
+{
+ int channel;
+ u64 log;
+
+ if (!(info->errsts & IE31200_ERRSTS_BITS))
+ return;
+
+ if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) {
+ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0,
+ -1, -1, -1, "UE overwrote CE", "");
+ info->errsts = info->errsts2;
+ }
+
+ for (channel = 0; channel < nr_channels; channel++) {
+ log = info->eccerrlog[channel];
+ if (log & IE31200_ECCERRLOG_UE) {
+ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
+ 0, 0, 0,
+ eccerrlog_row(channel, log),
+ channel, -1,
+ "ie31200 UE", "");
+ } else if (log & IE31200_ECCERRLOG_CE) {
+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
+ 0, 0,
+ IE31200_ECCERRLOG_SYNDROME(log),
+ eccerrlog_row(channel, log),
+ channel, -1,
+ "ie31200 CE", "");
+ }
+ }
+}
+
+static void ie31200_check(struct mem_ctl_info *mci)
+{
+ struct ie31200_error_info info;
+
+ edac_dbg(1, "MC%d\n", mci->mc_idx);
+ ie31200_get_and_clear_error_info(mci, &info);
+ ie31200_process_error_info(mci, &info);
+}
+
+static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev)
+{
+ union {
+ u64 mchbar;
+ struct {
+ u32 mchbar_low;
+ u32 mchbar_high;
+ };
+ } u;
+ void __iomem *window;
+
+ pci_read_config_dword(pdev, IE31200_MCHBAR_LOW, &u.mchbar_low);
+ pci_read_config_dword(pdev, IE31200_MCHBAR_HIGH, &u.mchbar_high);
+ u.mchbar &= IE31200_MCHBAR_MASK;
+
+ if (u.mchbar != (resource_size_t)u.mchbar) {
+ ie31200_printk(KERN_ERR, "mmio space beyond accessible range (0x%llx)\n",
+ (unsigned long long)u.mchbar);
+ return NULL;
+ }
+
+ window = ioremap_nocache(u.mchbar, IE31200_MMR_WINDOW_SIZE);
+ if (!window)
+ ie31200_printk(KERN_ERR, "Cannot map mmio space at 0x%llx\n",
+ (unsigned long long)u.mchbar);
+
+ return window;
+}
+
+static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int i, j, ret;
+ struct mem_ctl_info *mci = NULL;
+ struct edac_mc_layer layers[2];
+ struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
+ void __iomem *window;
+ struct ie31200_priv *priv;
+ u32 addr_decode;
+
+ edac_dbg(0, "MC:\n");
+
+ if (!ecc_capable(pdev)) {
+ ie31200_printk(KERN_INFO, "No ECC support\n");
+ return -ENODEV;
+ }
+
+ nr_channels = how_many_channels(pdev);
+ layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
+ layers[0].size = IE31200_DIMMS;
+ layers[0].is_virt_csrow = true;
+ layers[1].type = EDAC_MC_LAYER_CHANNEL;
+ layers[1].size = nr_channels;
+ layers[1].is_virt_csrow = false;
+ mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
+ sizeof(struct ie31200_priv));
+ if (!mci)
+ return -ENOMEM;
+
+ window = ie31200_map_mchbar(pdev);
+ if (!window) {
+ ret = -ENODEV;
+ goto fail_free;
+ }
+
+ edac_dbg(3, "MC: init mci\n");
+ mci->pdev = &pdev->dev;
+ mci->mtype_cap = MEM_FLAG_DDR3;
+ mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ mci->mod_name = EDAC_MOD_STR;
+ mci->mod_ver = IE31200_REVISION;
+ mci->ctl_name = ie31200_devs[dev_idx].ctl_name;
+ mci->dev_name = pci_name(pdev);
+ mci->edac_check = ie31200_check;
+ mci->ctl_page_to_phys = NULL;
+ priv = mci->pvt_info;
+ priv->window = window;
+
+ /* populate DIMM info */
+ for (i = 0; i < IE31200_CHANNELS; i++) {
+ addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET +
+ (i * 4));
+ edac_dbg(0, "addr_decode: 0x%x\n", addr_decode);
+ for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) {
+ dimm_info[i][j].size = (addr_decode >> (j * 8)) &
+ IE31200_MAD_DIMM_SIZE;
+ dimm_info[i][j].dual_rank = (addr_decode &
+ (IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0;
+ dimm_info[i][j].x16_width = (addr_decode &
+ (IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0;
+ edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
+ dimm_info[i][j].size,
+ dimm_info[i][j].dual_rank,
+ dimm_info[i][j].x16_width);
+ }
+ }
+
+ /*
+ * The dram rank boundary (DRB) reg values are boundary addresses
+ * for each DRAM rank with a granularity of 64MB. DRB regs are
+ * cumulative; the last one will contain the total memory
+ * contained in all ranks.
+ */
+ for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) {
+ for (j = 0; j < IE31200_CHANNELS; j++) {
+ struct dimm_info *dimm;
+ unsigned long nr_pages;
+
+ nr_pages = IE31200_PAGES(dimm_info[j][i].size);
+ if (nr_pages == 0)
+ continue;
+
+ if (dimm_info[j][i].dual_rank) {
+ nr_pages = nr_pages / 2;
+ dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
+ mci->n_layers, (i * 2) + 1,
+ j, 0);
+ dimm->nr_pages = nr_pages;
+ edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
+ dimm->grain = 8; /* just a guess */
+ dimm->mtype = MEM_DDR3;
+ dimm->dtype = DEV_UNKNOWN;
+ dimm->edac_mode = EDAC_UNKNOWN;
+ }
+ dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
+ mci->n_layers, i * 2, j, 0);
+ dimm->nr_pages = nr_pages;
+ edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
+ dimm->grain = 8; /* same guess */
+ dimm->mtype = MEM_DDR3;
+ dimm->dtype = DEV_UNKNOWN;
+ dimm->edac_mode = EDAC_UNKNOWN;
+ }
+ }
+
+ ie31200_clear_error_info(mci);
+
+ if (edac_mc_add_mc(mci)) {
+ edac_dbg(3, "MC: failed edac_mc_add_mc()\n");
+ ret = -ENODEV;
+ goto fail_unmap;
+ }
+
+ /* get this far and it's successful */
+ edac_dbg(3, "MC: success\n");
+ return 0;
+
+fail_unmap:
+ iounmap(window);
+
+fail_free:
+ edac_mc_free(mci);
+
+ return ret;
+}
+
+static int ie31200_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ edac_dbg(0, "MC:\n");
+
+ if (pci_enable_device(pdev) < 0)
+ return -EIO;
+
+ return ie31200_probe1(pdev, ent->driver_data);
+}
+
+static void ie31200_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct ie31200_priv *priv;
+
+ edac_dbg(0, "\n");
+ mci = edac_mc_del_mc(&pdev->dev);
+ if (!mci)
+ return;
+ priv = mci->pvt_info;
+ iounmap(priv->window);
+ edac_mc_free(mci);
+}
+
+static const struct pci_device_id ie31200_pci_tbl[] = {
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_4), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_5), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_6), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ IE31200},
+ {
+ 0,
+ } /* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, ie31200_pci_tbl);
+
+static struct pci_driver ie31200_driver = {
+ .name = EDAC_MOD_STR,
+ .probe = ie31200_init_one,
+ .remove = ie31200_remove_one,
+ .id_table = ie31200_pci_tbl,
+};
+
+static int __init ie31200_init(void)
+{
+ edac_dbg(3, "MC:\n");
+ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+ opstate_init();
+
+ return pci_register_driver(&ie31200_driver);
+}
+
+static void __exit ie31200_exit(void)
+{
+ edac_dbg(3, "MC:\n");
+ pci_unregister_driver(&ie31200_driver);
+}
+
+module_init(ie31200_init);
+module_exit(ie31200_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
+MODULE_DESCRIPTION("MC support for Intel Processor E31200 memory hub controllers");
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 5f43620d580a..f78c1c54dbd5 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -78,7 +78,8 @@ static const char * const f15h_mc1_mce_desc[] = {
"uop queue",
"insn buffer",
"predecode buffer",
- "fetch address FIFO"
+ "fetch address FIFO",
+ "dispatch uop queue"
};
static const char * const f15h_mc2_mce_desc[] = {
@@ -267,6 +268,12 @@ static bool f15h_mc0_mce(u16 ec, u8 xec)
pr_cont("System Read Data Error.\n");
else
pr_cont(" Internal error condition type %d.\n", xec);
+ } else if (INT_ERROR(ec)) {
+ if (xec <= 0x1f)
+ pr_cont("Hardware Assert.\n");
+ else
+ ret = false;
+
} else
ret = false;
@@ -373,7 +380,7 @@ static bool f15h_mc1_mce(u16 ec, u8 xec)
pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
break;
- case 0x11 ... 0x14:
+ case 0x11 ... 0x15:
pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
break;
@@ -397,10 +404,20 @@ static void decode_mc1_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 (INT_ERROR(ec)) {
+ if (xec <= 0x3f)
+ pr_cont("Hardware Assert.\n");
+ else
+ goto wrong_mc1_mce;
} else if (fam_ops->mc1_mce(ec, xec))
;
else
- pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
+ goto wrong_mc1_mce;
+
+ return;
+
+wrong_mc1_mce:
+ pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
}
static bool k8_mc2_mce(u16 ec, u8 xec)
@@ -468,6 +485,11 @@ static bool f15h_mc2_mce(u16 ec, u8 xec)
default:
ret = false;
}
+ } else if (INT_ERROR(ec)) {
+ if (xec <= 0x3f)
+ pr_cont("Hardware Assert.\n");
+ else
+ ret = false;
}
return ret;
@@ -615,6 +637,7 @@ static void decode_mc4_mce(struct mce *m)
static void decode_mc5_mce(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
+ u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
if (c->x86 == 0xf || c->x86 == 0x11)
@@ -622,6 +645,14 @@ static void decode_mc5_mce(struct mce *m)
pr_emerg(HW_ERR "MC5 Error: ");
+ if (INT_ERROR(ec)) {
+ if (xec <= 0x1f) {
+ pr_cont("Hardware Assert.\n");
+ return;
+ } else
+ goto wrong_mc5_mce;
+ }
+
if (xec == 0x0 || xec == 0xc)
pr_cont("%s.\n", mc5_mce_desc[xec]);
else if (xec <= 0xd)
@@ -642,6 +673,10 @@ static void decode_mc6_mce(struct mce *m)
pr_emerg(HW_ERR "MC6 Error: ");
switch (xec) {
+ case 0x0:
+ pr_cont("Hardware Assertion");
+ break;
+
case 0x1:
pr_cont("Free List");
break;
@@ -857,7 +892,8 @@ static int __init mce_amd_init(void)
break;
case 0x15:
- xec_mask = 0x1f;
+ xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f;
+
fam_ops->mc0_mce = f15h_mc0_mce;
fam_ops->mc1_mce = f15h_mc1_mce;
fam_ops->mc2_mce = f15h_mc2_mce;
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index deea0dc9999b..0034c4844428 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -99,6 +99,7 @@ static const u32 ibridge_dram_rule[] = {
#define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3)
#define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1)
#define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0)
+#define A7MODE(reg) GET_BITFIELD(reg, 26, 26)
static char *get_dram_attr(u32 reg)
{
@@ -164,6 +165,8 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
#define TOLM 0x80
#define TOHM 0x84
+#define HASWELL_TOHM_0 0xd4
+#define HASWELL_TOHM_1 0xd8
#define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff)
#define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
@@ -176,8 +179,6 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
#define SAD_CONTROL 0xf4
-#define NODE_ID(reg) GET_BITFIELD(reg, 0, 2)
-
/* Device 14 function 0 */
static const u32 tad_dram_rule[] = {
@@ -235,7 +236,6 @@ static const u32 rir_way_limit[] = {
#define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31)
#define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29)
-#define RIR_LIMIT(reg) ((GET_BITFIELD(reg, 1, 10) << 29)| 0x1fffffff)
#define MAX_RIR_WAY 8
@@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = {
#define IB_RANK_CFG_A 0x0320
-#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11)
-
/*
* sbridge structs
*/
@@ -291,6 +289,7 @@ static const u32 correrrthrsld[] = {
enum type {
SANDY_BRIDGE,
IVY_BRIDGE,
+ HASWELL,
};
struct sbridge_pvt;
@@ -300,11 +299,15 @@ struct sbridge_info {
u32 rankcfgr;
u64 (*get_tolm)(struct sbridge_pvt *pvt);
u64 (*get_tohm)(struct sbridge_pvt *pvt);
+ u64 (*rir_limit)(u32 reg);
const u32 *dram_rule;
const u32 *interleave_list;
const struct interleave_pkg *interleave_pkg;
u8 max_sad;
u8 max_interleave;
+ u8 (*get_node_id)(struct sbridge_pvt *pvt);
+ enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);
+ struct pci_dev *pci_vtd;
};
struct sbridge_channel {
@@ -313,9 +316,7 @@ struct sbridge_channel {
};
struct pci_id_descr {
- int dev;
- int func;
- int dev_id;
+ int dev_id;
int optional;
};
@@ -338,6 +339,7 @@ struct sbridge_pvt {
struct pci_dev *pci_sad0, *pci_sad1;
struct pci_dev *pci_ha0, *pci_ha1;
struct pci_dev *pci_br0, *pci_br1;
+ struct pci_dev *pci_ha1_ta;
struct pci_dev *pci_tad[NUM_CHANNELS];
struct sbridge_dev *sbridge_dev;
@@ -362,31 +364,29 @@ struct sbridge_pvt {
u64 tolm, tohm;
};
-#define PCI_DESCR(device, function, device_id, opt) \
- .dev = (device), \
- .func = (function), \
- .dev_id = (device_id), \
+#define PCI_DESCR(device_id, opt) \
+ .dev_id = (device_id), \
.optional = opt
static const struct pci_id_descr pci_dev_descr_sbridge[] = {
/* Processor Home Agent */
- { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) },
/* Memory controller */
- { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) },
- { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) },
- { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) },
- { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) },
- { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) },
- { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) },
- { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) },
/* System Address Decoder */
- { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) },
- { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) },
/* Broadcast Registers */
- { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) },
};
#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -423,34 +423,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
static const struct pci_id_descr pci_dev_descr_ibridge[] = {
/* Processor Home Agent */
- { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) },
/* Memory controller */
- { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) },
- { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) },
- { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) },
- { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) },
- { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) },
- { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) },
/* System Address Decoder */
- { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) },
/* Broadcast Registers */
- { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) },
- { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) },
/* Optional, mode 2HA */
- { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) },
#if 0
- { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) },
- { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
#endif
- { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
- { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
- { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
- { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
};
static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
@@ -458,12 +458,80 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
{0,} /* 0 terminated list. */
};
+/* Haswell support */
+/* EN processor:
+ * - 1 IMC
+ * - 3 DDR3 channels, 2 DPC per channel
+ * EP processor:
+ * - 1 or 2 IMC
+ * - 4 DDR4 channels, 3 DPC per channel
+ * EP 4S processor:
+ * - 2 IMC
+ * - 4 DDR4 channels, 3 DPC per channel
+ * EX processor:
+ * - 2 IMC
+ * - each IMC interfaces with a SMI 2 channel
+ * - each SMI channel interfaces with a scalable memory buffer
+ * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
+ */
+#define HASWELL_DDRCRCLKCONTROLS 0xa10
+#define HASWELL_HASYSDEFEATURE2 0x84
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d
+#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd
+static const struct pci_id_descr pci_dev_descr_haswell[] = {
+ /* first item must be the HA */
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) },
+
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) },
+ { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) },
+};
+
+static const struct pci_id_table pci_dev_descr_haswell_table[] = {
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell),
+ {0,} /* 0 terminated list. */
+};
+
/*
* pci_device_id table for which devices we are looking for
*/
static const struct pci_device_id sbridge_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
{0,} /* 0 terminated list. */
};
@@ -472,13 +540,17 @@ static const struct pci_device_id sbridge_pci_tbl[] = {
Ancillary status routines
****************************************************************************/
-static inline int numrank(u32 mtr)
+static inline int numrank(enum type type, u32 mtr)
{
int ranks = (1 << RANK_CNT_BITS(mtr));
+ int max = 4;
- if (ranks > 4) {
- edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n",
- ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr);
+ if (type == HASWELL)
+ max = 8;
+
+ if (ranks > max) {
+ edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)\n",
+ ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr);
return -EINVAL;
}
@@ -588,10 +660,107 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
return GET_TOHM(reg);
}
+static u64 rir_limit(u32 reg)
+{
+ return ((u64)GET_BITFIELD(reg, 1, 10) << 29) | 0x1fffffff;
+}
+
+static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+ enum mem_type mtype;
+
+ if (pvt->pci_ddrio) {
+ pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
+ &reg);
+ if (GET_BITFIELD(reg, 11, 11))
+ /* FIXME: Can also be LRDIMM */
+ mtype = MEM_RDDR3;
+ else
+ mtype = MEM_DDR3;
+ } else
+ mtype = MEM_UNKNOWN;
+
+ return mtype;
+}
+
+static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+ bool registered = false;
+ enum mem_type mtype = MEM_UNKNOWN;
+
+ if (!pvt->pci_ddrio)
+ goto out;
+
+ pci_read_config_dword(pvt->pci_ddrio,
+ HASWELL_DDRCRCLKCONTROLS, &reg);
+ /* Is_Rdimm */
+ if (GET_BITFIELD(reg, 16, 16))
+ registered = true;
+
+ pci_read_config_dword(pvt->pci_ta, MCMTR, &reg);
+ if (GET_BITFIELD(reg, 14, 14)) {
+ if (registered)
+ mtype = MEM_RDDR4;
+ else
+ mtype = MEM_DDR4;
+ } else {
+ if (registered)
+ mtype = MEM_RDDR3;
+ else
+ mtype = MEM_DDR3;
+ }
+
+out:
+ return mtype;
+}
+
+static u8 get_node_id(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+ pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
+ return GET_BITFIELD(reg, 0, 2);
+}
+
+static u8 haswell_get_node_id(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+
+ pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, &reg);
+ return GET_BITFIELD(reg, 0, 3);
+}
+
+static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+
+ pci_read_config_dword(pvt->info.pci_vtd, TOLM, &reg);
+ return (GET_BITFIELD(reg, 26, 31) << 26) | 0x1ffffff;
+}
+
+static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
+{
+ u64 rc;
+ u32 reg;
+
+ pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, &reg);
+ rc = GET_BITFIELD(reg, 26, 31);
+ pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg);
+ rc = ((reg << 6) | rc) << 26;
+
+ return rc | 0x1ffffff;
+}
+
+static u64 haswell_rir_limit(u32 reg)
+{
+ return (((u64)GET_BITFIELD(reg, 1, 11) + 1) << 29) - 1;
+}
+
static inline u8 sad_pkg_socket(u8 pkg)
{
/* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
- return (pkg >> 3) | (pkg & 0x3);
+ return ((pkg >> 3) << 2) | (pkg & 0x3);
}
static inline u8 sad_pkg_ha(u8 pkg)
@@ -602,44 +771,43 @@ static inline u8 sad_pkg_ha(u8 pkg)
/****************************************************************************
Memory check routines
****************************************************************************/
-static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
- unsigned func)
+static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
{
- struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
- int i;
-
- if (!sbridge_dev)
- return NULL;
-
- for (i = 0; i < sbridge_dev->n_devs; i++) {
- if (!sbridge_dev->pdev[i])
- continue;
+ struct pci_dev *pdev = NULL;
- if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
- PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
- edac_dbg(1, "Associated %02x.%02x.%d with %p\n",
- bus, slot, func, sbridge_dev->pdev[i]);
- return sbridge_dev->pdev[i];
- }
- }
+ do {
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
+ if (pdev && pdev->bus->number == bus)
+ break;
+ } while (pdev);
- return NULL;
+ return pdev;
}
/**
* check_if_ecc_is_active() - Checks if ECC is active
- * bus: Device bus
+ * @bus: Device bus
+ * @type: Memory controller type
+ * returns: 0 in case ECC is active, -ENODEV if it can't be determined or
+ * disabled
*/
-static int check_if_ecc_is_active(const u8 bus)
+static int check_if_ecc_is_active(const u8 bus, enum type type)
{
struct pci_dev *pdev = NULL;
- u32 mcmtr;
+ u32 mcmtr, id;
+
+ if (type == IVY_BRIDGE)
+ id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
+ else if (type == HASWELL)
+ id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
+ else
+ id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
- pdev = get_pdev_slot_func(bus, 15, 0);
+ pdev = get_pdev_same_bus(bus, id);
if (!pdev) {
sbridge_printk(KERN_ERR, "Couldn't find PCI device "
- "%2x.%02d.%d!!!\n",
- bus, 15, 0);
+ "%04x:%04x! on bus %02d\n",
+ PCI_VENDOR_ID_INTEL, id, bus);
return -ENODEV;
}
@@ -661,11 +829,14 @@ static int get_dimm_config(struct mem_ctl_info *mci)
enum edac_type mode;
enum mem_type mtype;
- pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
+ if (pvt->info.type == HASWELL)
+ pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
+ else
+ pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
+
pvt->sbridge_dev->source_id = SOURCE_ID(reg);
- pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
- pvt->sbridge_dev->node_id = NODE_ID(reg);
+ pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
pvt->sbridge_dev->mc,
pvt->sbridge_dev->node_id,
@@ -698,24 +869,18 @@ static int get_dimm_config(struct mem_ctl_info *mci)
pvt->is_close_pg = false;
}
- if (pvt->pci_ddrio) {
- pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
- &reg);
- if (IS_RDIMM_ENABLED(reg)) {
- /* FIXME: Can also be LRDIMM */
- edac_dbg(0, "Memory is registered\n");
- mtype = MEM_RDDR3;
- } else {
- edac_dbg(0, "Memory is unregistered\n");
- mtype = MEM_DDR3;
- }
- } else {
+ mtype = pvt->info.get_memory_type(pvt);
+ if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
+ edac_dbg(0, "Memory is registered\n");
+ else if (mtype == MEM_UNKNOWN)
edac_dbg(0, "Cannot determine memory type\n");
- mtype = MEM_UNKNOWN;
- }
+ else
+ edac_dbg(0, "Memory is unregistered\n");
- /* On all supported DDR3 DIMM types, there are 8 banks available */
- banks = 8;
+ if (mtype == MEM_DDR4 || MEM_RDDR4)
+ banks = 16;
+ else
+ banks = 8;
for (i = 0; i < NUM_CHANNELS; i++) {
u32 mtr;
@@ -729,11 +894,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
if (IS_DIMM_PRESENT(mtr)) {
pvt->channel[i].dimms++;
- ranks = numrank(mtr);
+ ranks = numrank(pvt->info.type, mtr);
rows = numrow(mtr);
cols = numcol(mtr);
- /* DDR3 has 8 I/O banks */
size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
npages = MiB_TO_PAGES(size);
@@ -744,7 +908,17 @@ static int get_dimm_config(struct mem_ctl_info *mci)
dimm->nr_pages = npages;
dimm->grain = 32;
- dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4;
+ switch (banks) {
+ case 16:
+ dimm->dtype = DEV_X16;
+ break;
+ case 8:
+ dimm->dtype = DEV_X8;
+ break;
+ case 4:
+ dimm->dtype = DEV_X4;
+ break;
+ }
dimm->mtype = mtype;
dimm->edac_mode = mode;
snprintf(dimm->label, sizeof(dimm->label),
@@ -887,7 +1061,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
if (!IS_RIR_VALID(reg))
continue;
- tmp_mb = RIR_LIMIT(reg) >> 20;
+ tmp_mb = pvt->info.rir_limit(reg) >> 20;
rir_way = 1 << RIR_WAY(reg);
mb = div_u64_rem(tmp_mb, 1000, &kb);
edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
@@ -936,11 +1110,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
struct mem_ctl_info *new_mci;
struct sbridge_pvt *pvt = mci->pvt_info;
struct pci_dev *pci_ha;
- int n_rir, n_sads, n_tads, sad_way, sck_xch;
+ int n_rir, n_sads, n_tads, sad_way, sck_xch;
int sad_interl, idx, base_ch;
- int interleave_mode;
+ int interleave_mode, shiftup = 0;
unsigned sad_interleave[pvt->info.max_interleave];
- u32 reg;
+ u32 reg, dram_rule;
u8 ch_way, sck_way, pkg, sad_ha = 0;
u32 tad_offset;
u32 rir_way;
@@ -987,8 +1161,9 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
sprintf(msg, "Can't discover the memory socket");
return -EINVAL;
}
- *area_type = get_dram_attr(reg);
- interleave_mode = INTERLEAVE_MODE(reg);
+ dram_rule = reg;
+ *area_type = get_dram_attr(dram_rule);
+ interleave_mode = INTERLEAVE_MODE(dram_rule);
pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
&reg);
@@ -1033,6 +1208,36 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
*socket = sad_interleave[idx];
edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
idx, sad_way, *socket);
+ } else if (pvt->info.type == HASWELL) {
+ int bits, a7mode = A7MODE(dram_rule);
+
+ if (a7mode) {
+ /* A7 mode swaps P9 with P6 */
+ bits = GET_BITFIELD(addr, 7, 8) << 1;
+ bits |= GET_BITFIELD(addr, 9, 9);
+ } else
+ bits = GET_BITFIELD(addr, 7, 9);
+
+ if (interleave_mode) {
+ /* interleave mode will XOR {8,7,6} with {18,17,16} */
+ idx = GET_BITFIELD(addr, 16, 18);
+ idx ^= bits;
+ } else
+ idx = bits;
+
+ pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
+ *socket = sad_pkg_socket(pkg);
+ sad_ha = sad_pkg_ha(pkg);
+
+ if (a7mode) {
+ /* MCChanShiftUpEnable */
+ pci_read_config_dword(pvt->pci_ha0,
+ HASWELL_HASYSDEFEATURE2, &reg);
+ shiftup = GET_BITFIELD(reg, 22, 22);
+ }
+
+ edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i\n",
+ idx, *socket, sad_ha, shiftup);
} else {
/* Ivy Bridge's SAD mode doesn't support XOR interleave mode */
idx = (addr >> 6) & 7;
@@ -1090,7 +1295,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
if (ch_way == 3)
idx = addr >> 6;
else
- idx = addr >> (6 + sck_way);
+ idx = (addr >> (6 + sck_way + shiftup)) & 0x3;
idx = idx % ch_way;
/*
@@ -1181,7 +1386,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
if (!IS_RIR_VALID(reg))
continue;
- limit = RIR_LIMIT(reg);
+ limit = pvt->info.rir_limit(reg);
mb = div_u64_rem(limit >> 20, 1000, &kb);
edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
n_rir,
@@ -1197,6 +1402,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
return -EINVAL;
}
rir_way = RIR_WAY(reg);
+
if (pvt->is_close_pg)
idx = (ch_addr >> 6);
else
@@ -1259,13 +1465,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
{
struct sbridge_dev *sbridge_dev;
const struct pci_id_descr *dev_descr = &table->descr[devno];
-
struct pci_dev *pdev = NULL;
u8 bus = 0;
sbridge_printk(KERN_DEBUG,
- "Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
- dev_descr->dev, dev_descr->func,
+ "Seeking for: PCI ID %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1280,12 +1484,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
if (dev_descr->optional)
return 0;
+ /* if the HA wasn't found */
if (devno == 0)
return -ENODEV;
sbridge_printk(KERN_INFO,
- "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
- dev_descr->dev, dev_descr->func,
+ "Device not found: %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
/* End of list, leave */
@@ -1305,9 +1509,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
if (sbridge_dev->pdev[devno]) {
sbridge_printk(KERN_ERR,
- "Duplicated device for "
- "dev %02x:%d.%d PCI ID %04x:%04x\n",
- bus, dev_descr->dev, dev_descr->func,
+ "Duplicated device for %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
pci_dev_put(pdev);
return -ENODEV;
@@ -1315,30 +1517,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
sbridge_dev->pdev[devno] = pdev;
- /* Sanity check */
- if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
- PCI_FUNC(pdev->devfn) != dev_descr->func)) {
- sbridge_printk(KERN_ERR,
- "Device PCI ID %04x:%04x "
- "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
- PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
- bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- bus, dev_descr->dev, dev_descr->func);
- return -ENODEV;
- }
-
/* Be sure that the device is enabled */
if (unlikely(pci_enable_device(pdev) < 0)) {
sbridge_printk(KERN_ERR,
- "Couldn't enable "
- "dev %02x:%d.%d PCI ID %04x:%04x\n",
- bus, dev_descr->dev, dev_descr->func,
+ "Couldn't enable %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
return -ENODEV;
}
- edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
- bus, dev_descr->dev, dev_descr->func,
+ edac_dbg(0, "Detected %04x:%04x\n",
PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
/*
@@ -1355,10 +1542,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
/*
* sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
- * device/functions we want to reference for this driver.
- * Need to 'get' device 16 func 1 and func 2.
+ * devices we want to reference for this driver.
* @num_mc: pointer to the memory controllers count, to be incremented in case
- * of success.
+ * of success.
* @table: model specific table
*
* returns 0 in case of success or error code
@@ -1396,79 +1582,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct pci_dev *pdev;
- int i, func, slot;
+ int i;
for (i = 0; i < sbridge_dev->n_devs; i++) {
pdev = sbridge_dev->pdev[i];
if (!pdev)
continue;
- slot = PCI_SLOT(pdev->devfn);
- func = PCI_FUNC(pdev->devfn);
- switch (slot) {
- case 12:
- switch (func) {
- case 6:
- pvt->pci_sad0 = pdev;
- break;
- case 7:
- pvt->pci_sad1 = pdev;
- break;
- default:
- goto error;
- }
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
+ pvt->pci_sad0 = pdev;
break;
- case 13:
- switch (func) {
- case 6:
- pvt->pci_br0 = pdev;
- break;
- default:
- goto error;
- }
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
+ pvt->pci_sad1 = pdev;
break;
- case 14:
- switch (func) {
- case 0:
- pvt->pci_ha0 = pdev;
- break;
- default:
- goto error;
- }
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
+ pvt->pci_br0 = pdev;
break;
- case 15:
- switch (func) {
- case 0:
- pvt->pci_ta = pdev;
- break;
- case 1:
- pvt->pci_ras = pdev;
- break;
- case 2:
- case 3:
- case 4:
- case 5:
- pvt->pci_tad[func - 2] = pdev;
- break;
- default:
- goto error;
- }
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
+ pvt->pci_ha0 = pdev;
break;
- case 17:
- switch (func) {
- case 0:
- pvt->pci_ddrio = pdev;
- break;
- default:
- goto error;
- }
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
+ pvt->pci_ta = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS:
+ pvt->pci_ras = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0:
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1:
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
+ {
+ int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
+ pvt->pci_tad[id] = pdev;
+ }
+ break;
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
+ pvt->pci_ddrio = pdev;
break;
default:
goto error;
}
- edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
+ edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n",
+ pdev->vendor, pdev->device,
sbridge_dev->bus,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
pdev);
}
@@ -1488,9 +1646,8 @@ enodev:
return -ENODEV;
error:
- sbridge_printk(KERN_ERR, "Device %d, function %d "
- "is out of the expected range\n",
- slot, func);
+ sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n",
+ PCI_VENDOR_ID_INTEL, pdev->device);
return -EINVAL;
}
@@ -1499,7 +1656,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct pci_dev *pdev, *tmp;
- int i, func, slot;
+ int i;
bool mode_2ha = false;
tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1513,79 +1670,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
pdev = sbridge_dev->pdev[i];
if (!pdev)
continue;
- slot = PCI_SLOT(pdev->devfn);
- func = PCI_FUNC(pdev->devfn);
- switch (slot) {
- case 14:
- if (func == 0) {
- pvt->pci_ha0 = pdev;
- break;
- }
- goto error;
- case 15:
- switch (func) {
- case 0:
- pvt->pci_ta = pdev;
- break;
- case 1:
- pvt->pci_ras = pdev;
- break;
- case 4:
- case 5:
- /* if we have 2 HAs active, channels 2 and 3
- * are in other device */
- if (mode_2ha)
- break;
- /* fall through */
- case 2:
- case 3:
- pvt->pci_tad[func - 2] = pdev;
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
+ pvt->pci_ha0 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
+ pvt->pci_ta = pdev;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
+ pvt->pci_ras = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
+ /* if we have 2 HAs active, channels 2 and 3
+ * are in other device */
+ if (mode_2ha)
break;
- default:
- goto error;
- }
+ /* fall through */
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
+ {
+ int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
+ pvt->pci_tad[id] = pdev;
+ }
break;
- case 17:
- if (func == 4) {
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0:
+ pvt->pci_ddrio = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0:
+ if (!mode_2ha)
pvt->pci_ddrio = pdev;
- break;
- } else if (func == 0) {
- if (!mode_2ha)
- pvt->pci_ddrio = pdev;
- break;
- }
- goto error;
- case 22:
- switch (func) {
- case 0:
- pvt->pci_sad0 = pdev;
- break;
- case 1:
- pvt->pci_br0 = pdev;
- break;
- case 2:
- pvt->pci_br1 = pdev;
- break;
- default:
- goto error;
- }
break;
- case 28:
- if (func == 0) {
- pvt->pci_ha1 = pdev;
- break;
- }
- goto error;
- case 29:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD:
+ pvt->pci_sad0 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0:
+ pvt->pci_br0 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
+ pvt->pci_br1 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
+ pvt->pci_ha1 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
+ {
+ int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2;
+
/* we shouldn't have this device if we have just one
* HA present */
WARN_ON(!mode_2ha);
- if (func == 2 || func == 3) {
- pvt->pci_tad[func] = pdev;
- break;
- }
- goto error;
+ pvt->pci_tad[id] = pdev;
+ }
+ break;
default:
goto error;
}
@@ -1614,11 +1752,111 @@ enodev:
error:
sbridge_printk(KERN_ERR,
- "Device %d, function %d is out of the expected range\n",
- slot, func);
+ "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL,
+ pdev->device);
return -EINVAL;
}
+static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
+ struct sbridge_dev *sbridge_dev)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev, *tmp;
+ int i;
+ bool mode_2ha = false;
+
+ tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, NULL);
+ if (tmp) {
+ mode_2ha = true;
+ pci_dev_put(tmp);
+ }
+
+ /* there's only one device per system; not tied to any bus */
+ if (pvt->info.pci_vtd == NULL)
+ /* result will be checked later */
+ pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC,
+ NULL);
+
+ for (i = 0; i < sbridge_dev->n_devs; i++) {
+ pdev = sbridge_dev->pdev[i];
+ if (!pdev)
+ continue;
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0:
+ pvt->pci_sad0 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1:
+ pvt->pci_sad1 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
+ pvt->pci_ha0 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
+ pvt->pci_ta = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL:
+ pvt->pci_ras = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
+ pvt->pci_tad[0] = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
+ pvt->pci_tad[1] = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
+ if (!mode_2ha)
+ pvt->pci_tad[2] = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
+ if (!mode_2ha)
+ pvt->pci_tad[3] = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
+ pvt->pci_ddrio = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
+ pvt->pci_ha1 = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
+ pvt->pci_ha1_ta = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0:
+ if (mode_2ha)
+ pvt->pci_tad[2] = pdev;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1:
+ if (mode_2ha)
+ pvt->pci_tad[3] = pdev;
+ break;
+ default:
+ break;
+ }
+
+ edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
+ sbridge_dev->bus,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ pdev);
+ }
+
+ /* Check if everything were registered */
+ if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
+ !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
+ goto enodev;
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (!pvt->pci_tad[i])
+ goto enodev;
+ }
+ return 0;
+
+enodev:
+ sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+ return -ENODEV;
+}
+
/****************************************************************************
Error check routines
****************************************************************************/
@@ -1736,6 +1974,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
* EDAC core should be handling the channel mask, in order to point
* to the group of dimm's where the error may be happening.
*/
+ if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg)
+ channel = first_channel;
+
snprintf(msg, sizeof(msg),
"%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d",
overflow ? " OVERFLOW" : "",
@@ -1865,10 +2106,6 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
"%u APIC %x\n", mce->cpuvendor, mce->cpuid,
mce->time, mce->socketid, mce->apicid);
- /* Only handle if it is the right mc controller */
- if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc)
- return NOTIFY_DONE;
-
smp_rmb();
if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
smp_wmb();
@@ -1932,7 +2169,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
int rc;
/* Check the number of active and not disabled channels */
- rc = check_if_ecc_is_active(sbridge_dev->bus);
+ rc = check_if_ecc_is_active(sbridge_dev->bus, type);
if (unlikely(rc < 0))
return rc;
@@ -1971,11 +2208,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
mci->edac_check = sbridge_check_error;
pvt->info.type = type;
- if (type == IVY_BRIDGE) {
+ switch (type) {
+ case IVY_BRIDGE:
pvt->info.rankcfgr = IB_RANK_CFG_A;
pvt->info.get_tolm = ibridge_get_tolm;
pvt->info.get_tohm = ibridge_get_tohm;
pvt->info.dram_rule = ibridge_dram_rule;
+ pvt->info.get_memory_type = get_memory_type;
+ pvt->info.get_node_id = get_node_id;
+ pvt->info.rir_limit = rir_limit;
pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
pvt->info.interleave_list = ibridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -1986,11 +2227,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
rc = ibridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
- } else {
+ break;
+ case SANDY_BRIDGE:
pvt->info.rankcfgr = SB_RANK_CFG_A;
pvt->info.get_tolm = sbridge_get_tolm;
pvt->info.get_tohm = sbridge_get_tohm;
pvt->info.dram_rule = sbridge_dram_rule;
+ pvt->info.get_memory_type = get_memory_type;
+ pvt->info.get_node_id = get_node_id;
+ pvt->info.rir_limit = rir_limit;
pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
pvt->info.interleave_list = sbridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
@@ -2001,8 +2246,27 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
rc = sbridge_mci_bind_devs(mci, sbridge_dev);
if (unlikely(rc < 0))
goto fail0;
- }
+ break;
+ case HASWELL:
+ /* rankcfgr isn't used */
+ pvt->info.get_tolm = haswell_get_tolm;
+ pvt->info.get_tohm = haswell_get_tohm;
+ pvt->info.dram_rule = ibridge_dram_rule;
+ pvt->info.get_memory_type = haswell_get_memory_type;
+ pvt->info.get_node_id = haswell_get_node_id;
+ pvt->info.rir_limit = haswell_rir_limit;
+ pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
+ pvt->info.interleave_list = ibridge_interleave_list;
+ pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
+ pvt->info.interleave_pkg = ibridge_interleave_pkg;
+ mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
+ /* Store pci devices at mci for faster access */
+ rc = haswell_mci_bind_devs(mci, sbridge_dev);
+ if (unlikely(rc < 0))
+ goto fail0;
+ break;
+ }
/* Get dimm basic config and the memory layout */
get_dimm_config(mci);
@@ -2037,10 +2301,10 @@ fail0:
static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int rc;
+ int rc = -ENODEV;
u8 mc, num_mc = 0;
struct sbridge_dev *sbridge_dev;
- enum type type;
+ enum type type = SANDY_BRIDGE;
/* get the pci devices we want to reserve for our use */
mutex_lock(&sbridge_edac_lock);
@@ -2054,12 +2318,19 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
probed++;
- if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) {
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table);
type = IVY_BRIDGE;
- } else {
+ break;
+ case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table);
type = SANDY_BRIDGE;
+ break;
+ case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
+ rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
+ type = HASWELL;
+ break;
}
if (unlikely(rc < 0))
goto fail0;
@@ -2068,6 +2339,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
edac_dbg(0, "Registering MC#%d (%d of %d)\n",
mc, mc + 1, num_mc);
+
sbridge_dev->mc = mc++;
rc = sbridge_register_mci(sbridge_dev, type);
if (unlikely(rc < 0))
diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c
index 4891b450830b..e644b52c287c 100644
--- a/drivers/edac/x38_edac.c
+++ b/drivers/edac/x38_edac.c
@@ -14,6 +14,8 @@
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/edac.h>
+
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
#include "edac_core.h"
#define X38_REVISION "1.1"
@@ -161,11 +163,6 @@ static void x38_clear_error_info(struct mem_ctl_info *mci)
X38_ERRSTS_BITS);
}
-static u64 x38_readq(const void __iomem *addr)
-{
- return readl(addr) | (((u64)readl(addr + 4)) << 32);
-}
-
static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
struct x38_error_info *info)
{
@@ -183,9 +180,9 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
if (!(info->errsts & X38_ERRSTS_BITS))
return;
- info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG);
+ info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
if (x38_channel_num == 2)
- info->eccerrlog[1] = x38_readq(window + X38_C1ECCERRLOG);
+ info->eccerrlog[1] = lo_hi_readq(window + X38_C1ECCERRLOG);
pci_read_config_word(pdev, X38_ERRSTS, &info->errsts2);
@@ -196,10 +193,10 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
* should be UE info.
*/
if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) {
- info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG);
+ info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
if (x38_channel_num == 2)
info->eccerrlog[1] =
- x38_readq(window + X38_C1ECCERRLOG);
+ lo_hi_readq(window + X38_C1ECCERRLOG);
}
x38_clear_error_info(mci);
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index aebde489c291..6f2f4727de2c 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -14,6 +14,20 @@ if EXTCON
comment "Extcon Device Drivers"
+config EXTCON_ADC_JACK
+ tristate "ADC Jack extcon support"
+ depends on IIO
+ help
+ Say Y here to enable extcon device driver based on ADC values.
+
+config EXTCON_ARIZONA
+ tristate "Wolfson Arizona EXTCON support"
+ depends on MFD_ARIZONA && INPUT && SND_SOC
+ help
+ Say Y here to enable support for external accessory detection
+ with Wolfson Arizona devices. These are audio CODECs with
+ advanced audio accessory detection support.
+
config EXTCON_GPIO
tristate "GPIO extcon support"
depends on GPIOLIB
@@ -21,12 +35,6 @@ config EXTCON_GPIO
Say Y here to enable GPIO based extcon support. Note that GPIO
extcon supports single state per extcon instance.
-config EXTCON_ADC_JACK
- tristate "ADC Jack extcon support"
- depends on IIO
- help
- Say Y here to enable extcon device driver based on ADC values.
-
config EXTCON_MAX14577
tristate "MAX14577/77836 EXTCON Support"
depends on MFD_MAX14577
@@ -55,14 +63,6 @@ config EXTCON_MAX8997
Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
detector and switch.
-config EXTCON_ARIZONA
- tristate "Wolfson Arizona EXTCON support"
- depends on MFD_ARIZONA && INPUT && SND_SOC
- help
- Say Y here to enable support for external accessory detection
- with Wolfson Arizona devices. These are audio CODECs with
- advanced audio accessory detection support.
-
config EXTCON_PALMAS
tristate "Palmas USB EXTCON support"
depends on MFD_PALMAS
@@ -70,4 +70,14 @@ config EXTCON_PALMAS
Say Y here to enable support for USB peripheral and USB host
detection by palmas usb.
+config EXTCON_SM5502
+ tristate "SM5502 EXTCON support"
+ select IRQ_DOMAIN
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ If you say yes here you get support for the MUIC device of
+ Silicon Mitus SM5502. The SM5502 is a USB port accessory
+ detector and switch.
+
endif # MULTISTATE_SWITCH
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index bf7861ec0906..b38546eb522a 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -1,12 +1,13 @@
-#
+
# Makefile for external connector class (extcon) devices
#
obj-$(CONFIG_EXTCON) += extcon-class.o
-obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o
+obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
+obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o
-obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o
obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o
+obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index e18f95be3733..d860229e4de1 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -112,7 +112,6 @@ static int adc_jack_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- data->edev->dev.parent = &pdev->dev;
data->edev->name = pdata->name;
/* Check the length of array and set num_cables */
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 6c84e3d12043..ba51588cc000 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -39,6 +39,11 @@
#define ARIZONA_ACCDET_MODE_HPL 1
#define ARIZONA_ACCDET_MODE_HPR 2
+#define ARIZONA_MICD_CLAMP_MODE_JDL 0x4
+#define ARIZONA_MICD_CLAMP_MODE_JDH 0x5
+#define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9
+#define ARIZONA_MICD_CLAMP_MODE_JDH_GP5H 0xb
+
#define ARIZONA_HPDET_MAX 10000
#define HPDET_DEBOUNCE 500
@@ -324,14 +329,17 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
}
static struct {
+ unsigned int threshold;
unsigned int factor_a;
unsigned int factor_b;
} arizona_hpdet_b_ranges[] = {
- { 5528, 362464 },
- { 11084, 6186851 },
- { 11065, 65460395 },
+ { 100, 5528, 362464 },
+ { 169, 11084, 6186851 },
+ { 169, 11065, 65460395 },
};
+#define ARIZONA_HPDET_B_RANGE_MAX 0x3fb
+
static struct {
int min;
int max;
@@ -386,7 +394,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
>> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
- (val < 100 || val >= 0x3fb)) {
+ (val < arizona_hpdet_b_ranges[range].threshold ||
+ val >= ARIZONA_HPDET_B_RANGE_MAX)) {
range++;
dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
range);
@@ -399,7 +408,8 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info)
}
/* If we go out of range report top of range */
- if (val < 100 || val >= 0x3fb) {
+ if (val < arizona_hpdet_b_ranges[range].threshold ||
+ val >= ARIZONA_HPDET_B_RANGE_MAX) {
dev_dbg(arizona->dev, "Measurement out of range\n");
return ARIZONA_HPDET_MAX;
}
@@ -664,9 +674,8 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_update_state(info->edev,
- 1 << ARIZONA_CABLE_HEADPHONE,
- 1 << ARIZONA_CABLE_HEADPHONE);
+ ret = extcon_set_cable_state_(info->edev,
+ ARIZONA_CABLE_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -723,9 +732,8 @@ err:
ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
/* Just report headphone */
- ret = extcon_update_state(info->edev,
- 1 << ARIZONA_CABLE_HEADPHONE,
- 1 << ARIZONA_CABLE_HEADPHONE);
+ ret = extcon_set_cable_state_(info->edev,
+ ARIZONA_CABLE_HEADPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
@@ -812,16 +820,15 @@ static void arizona_micd_detect(struct work_struct *work)
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
arizona_identify_headphone(info);
- ret = extcon_update_state(info->edev,
- 1 << ARIZONA_CABLE_MICROPHONE,
- 1 << ARIZONA_CABLE_MICROPHONE);
+ ret = extcon_set_cable_state_(info->edev,
+ ARIZONA_CABLE_MICROPHONE, true);
if (ret != 0)
dev_err(arizona->dev, "Headset report failed: %d\n",
ret);
/* Don't need to regulate for button detection */
- ret = regulator_allow_bypass(info->micvdd, false);
+ ret = regulator_allow_bypass(info->micvdd, true);
if (ret != 0) {
dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n",
ret);
@@ -962,10 +969,16 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
if (arizona->pdata.jd_gpio5) {
mask = ARIZONA_MICD_CLAMP_STS;
- present = 0;
+ if (arizona->pdata.jd_invert)
+ present = ARIZONA_MICD_CLAMP_STS;
+ else
+ present = 0;
} else {
mask = ARIZONA_JD1_STS;
- present = ARIZONA_JD1_STS;
+ if (arizona->pdata.jd_invert)
+ present = 0;
+ else
+ present = ARIZONA_JD1_STS;
}
ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
@@ -1096,6 +1109,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_extcon_info *info;
unsigned int val;
+ unsigned int clamp_mode;
int jack_irq_fall, jack_irq_rise;
int ret, mode, i, j;
@@ -1103,12 +1117,10 @@ static int arizona_extcon_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "Failed to allocate memory\n");
+ if (!info)
return -ENOMEM;
- }
- info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
+ info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
if (IS_ERR(info->micvdd)) {
ret = PTR_ERR(info->micvdd);
dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
@@ -1156,7 +1168,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
}
info->edev->name = "Headset Jack";
- info->edev->dev.parent = arizona->dev;
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret < 0) {
@@ -1174,7 +1185,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
info->input->name = "Headset";
info->input->phys = "arizona/extcon";
- info->input->dev.parent = &pdev->dev;
if (pdata->num_micd_configs) {
info->micd_modes = pdata->micd_configs;
@@ -1305,16 +1315,22 @@ static int arizona_extcon_probe(struct platform_device *pdev)
regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
val);
- regmap_update_bits(arizona->regmap,
- ARIZONA_MICD_CLAMP_CONTROL,
- ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
+ if (arizona->pdata.jd_invert)
+ clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH_GP5H;
+ else
+ clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL_GP5H;
} else {
- regmap_update_bits(arizona->regmap,
- ARIZONA_MICD_CLAMP_CONTROL,
- ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
+ if (arizona->pdata.jd_invert)
+ clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDH;
+ else
+ clamp_mode = ARIZONA_MICD_CLAMP_MODE_JDL;
}
regmap_update_bits(arizona->regmap,
+ ARIZONA_MICD_CLAMP_CONTROL,
+ ARIZONA_MICD_CLAMP_MODE_MASK, clamp_mode);
+
+ regmap_update_bits(arizona->regmap,
ARIZONA_JACK_DETECT_DEBOUNCE,
ARIZONA_MICD_CLAMP_DB,
ARIZONA_MICD_CLAMP_DB);
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 18d42c0e4581..4c2f2c543bb7 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -645,6 +645,8 @@ struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
return edev;
}
+ edev->dev.parent = dev;
+
*ptr = edev;
devres_add(dev, ptr);
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 645b28356819..5b7ec274cb63 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -105,7 +105,6 @@ static int gpio_extcon_probe(struct platform_device *pdev)
return -ENOMEM;
}
extcon_data->edev->name = pdata->name;
- extcon_data->edev->dev.parent = &pdev->dev;
extcon_data->gpio = pdata->gpio;
extcon_data->gpio_active_low = pdata->gpio_active_low;
diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c
index d49e891b5675..7309743d0da1 100644
--- a/drivers/extcon/extcon-max14577.c
+++ b/drivers/extcon/extcon-max14577.c
@@ -692,10 +692,9 @@ static int max14577_muic_probe(struct platform_device *pdev)
u8 id;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ if (!info)
return -ENOMEM;
- }
+
info->dev = &pdev->dev;
info->max14577 = max14577;
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 2c7c3e191591..77460f2c1ca1 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -255,10 +255,10 @@ static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
case ADC_DEBOUNCE_TIME_10MS:
case ADC_DEBOUNCE_TIME_25MS:
case ADC_DEBOUNCE_TIME_38_62MS:
- ret = max77693_update_reg(info->max77693->regmap_muic,
+ ret = regmap_update_bits(info->max77693->regmap_muic,
MAX77693_MUIC_REG_CTRL3,
- time << CONTROL3_ADCDBSET_SHIFT,
- CONTROL3_ADCDBSET_MASK);
+ CONTROL3_ADCDBSET_MASK,
+ time << CONTROL3_ADCDBSET_SHIFT);
if (ret) {
dev_err(info->dev, "failed to set ADC debounce time\n");
return ret;
@@ -286,15 +286,15 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
u8 val, bool attached)
{
int ret = 0;
- u8 ctrl1, ctrl2 = 0;
+ unsigned int ctrl1, ctrl2 = 0;
if (attached)
ctrl1 = val;
else
ctrl1 = CONTROL1_SW_OPEN;
- ret = max77693_update_reg(info->max77693->regmap_muic,
- MAX77693_MUIC_REG_CTRL1, ctrl1, COMP_SW_MASK);
+ ret = regmap_update_bits(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CTRL1, COMP_SW_MASK, ctrl1);
if (ret < 0) {
dev_err(info->dev, "failed to update MUIC register\n");
return ret;
@@ -305,9 +305,9 @@ static int max77693_muic_set_path(struct max77693_muic_info *info,
else
ctrl2 |= CONTROL2_LOWPWR_MASK; /* LowPwr=1, CPEn=0 */
- ret = max77693_update_reg(info->max77693->regmap_muic,
- MAX77693_MUIC_REG_CTRL2, ctrl2,
- CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
+ ret = regmap_update_bits(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_CTRL2,
+ CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
if (ret < 0) {
dev_err(info->dev, "failed to update MUIC register\n");
return ret;
@@ -969,8 +969,8 @@ static void max77693_muic_irq_work(struct work_struct *work)
if (info->irq == muic_irqs[i].virq)
irq_type = muic_irqs[i].irq;
- ret = max77693_bulk_read(info->max77693->regmap_muic,
- MAX77693_MUIC_REG_STATUS1, 2, info->status);
+ ret = regmap_bulk_read(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_STATUS1, info->status, 2);
if (ret) {
dev_err(info->dev, "failed to read MUIC register\n");
mutex_unlock(&info->mutex);
@@ -1042,8 +1042,8 @@ static int max77693_muic_detect_accessory(struct max77693_muic_info *info)
mutex_lock(&info->mutex);
/* Read STATUSx register to detect accessory */
- ret = max77693_bulk_read(info->max77693->regmap_muic,
- MAX77693_MUIC_REG_STATUS1, 2, info->status);
+ ret = regmap_bulk_read(info->max77693->regmap_muic,
+ MAX77693_MUIC_REG_STATUS1, info->status, 2);
if (ret) {
dev_err(info->dev, "failed to read MUIC register\n");
mutex_unlock(&info->mutex);
@@ -1095,14 +1095,13 @@ static int max77693_muic_probe(struct platform_device *pdev)
int delay_jiffies;
int ret;
int i;
- u8 id;
+ unsigned int id;
info = devm_kzalloc(&pdev->dev, sizeof(struct max77693_muic_info),
GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ if (!info)
return -ENOMEM;
- }
+
info->dev = &pdev->dev;
info->max77693 = max77693;
if (info->max77693->regmap_muic) {
@@ -1154,7 +1153,8 @@ static int max77693_muic_probe(struct platform_device *pdev)
struct max77693_muic_irq *muic_irq = &muic_irqs[i];
unsigned int virq = 0;
- virq = irq_create_mapping(max77693->irq_domain, muic_irq->irq);
+ virq = regmap_irq_get_virq(max77693->irq_data_muic,
+ muic_irq->irq);
if (!virq) {
ret = -EINVAL;
goto err_irq;
@@ -1183,7 +1183,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
goto err_irq;
}
info->edev->name = DEV_NAME;
- info->edev->dev.parent = &pdev->dev;
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
@@ -1204,7 +1203,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
enum max77693_irq_source irq_src
= MAX77693_IRQ_GROUP_NR;
- max77693_write_reg(info->max77693->regmap_muic,
+ regmap_write(info->max77693->regmap_muic,
init_data[i].addr,
init_data[i].data);
@@ -1262,7 +1261,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
max77693_muic_set_path(info, info->path_uart, true);
/* Check revision number of MUIC device*/
- ret = max77693_read_reg(info->max77693->regmap_muic,
+ ret = regmap_read(info->max77693->regmap_muic,
MAX77693_MUIC_REG_ID, &id);
if (ret < 0) {
dev_err(&pdev->dev, "failed to read revision number\n");
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index d9f7f1baaa03..75e501c98005 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -661,10 +661,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ if (!info)
return -ENOMEM;
- }
info->dev = &pdev->dev;
info->muic = max8997->muic;
@@ -706,7 +704,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
goto err_irq;
}
info->edev->name = DEV_NAME;
- info->edev->dev.parent = &pdev->dev;
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
if (ret) {
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 7417ce84eb2d..230e1220ce48 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -194,7 +194,6 @@ static int palmas_usb_probe(struct platform_device *pdev)
return -ENOMEM;
}
palmas_usb->edev->name = kstrdup(node->name, GFP_KERNEL);
- palmas_usb->edev->dev.parent = palmas_usb->dev;
palmas_usb->edev->mutually_exclusive = mutually_exclusive;
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
@@ -278,7 +277,7 @@ static int palmas_usb_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_usb_suspend, palmas_usb_resume);
-static struct of_device_id of_palmas_match_tbl[] = {
+static const struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas-usb", },
{ .compatible = "ti,palmas-usb-vid", },
{ .compatible = "ti,twl6035-usb", },
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
new file mode 100644
index 000000000000..560d7dccec7b
--- /dev/null
+++ b/drivers/extcon/extcon-sm5502.c
@@ -0,0 +1,724 @@
+/*
+ * extcon-sm5502.c - Silicon Mitus SM5502 extcon drvier to support USB switches
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/extcon.h>
+#include <linux/extcon/sm5502.h>
+
+#define DELAY_MS_DEFAULT 17000 /* unit: millisecond */
+
+struct muic_irq {
+ unsigned int irq;
+ const char *name;
+ unsigned int virq;
+};
+
+struct reg_data {
+ u8 reg;
+ unsigned int val;
+ bool invert;
+};
+
+struct sm5502_muic_info {
+ struct device *dev;
+ struct extcon_dev *edev;
+
+ struct i2c_client *i2c;
+ struct regmap *regmap;
+
+ struct regmap_irq_chip_data *irq_data;
+ struct muic_irq *muic_irqs;
+ unsigned int num_muic_irqs;
+ int irq;
+ bool irq_attach;
+ bool irq_detach;
+ struct work_struct irq_work;
+
+ struct reg_data *reg_data;
+ unsigned int num_reg_data;
+
+ struct mutex mutex;
+
+ /*
+ * Use delayed workqueue to detect cable state and then
+ * notify cable state to notifiee/platform through uevent.
+ * After completing the booting of platform, the extcon provider
+ * driver should notify cable state to upper layer.
+ */
+ struct delayed_work wq_detcable;
+};
+
+/* Default value of SM5502 register to bring up MUIC device. */
+static struct reg_data sm5502_reg_data[] = {
+ {
+ .reg = SM5502_REG_CONTROL,
+ .val = SM5502_REG_CONTROL_MASK_INT_MASK,
+ .invert = false,
+ }, {
+ .reg = SM5502_REG_INTMASK1,
+ .val = SM5502_REG_INTM1_KP_MASK
+ | SM5502_REG_INTM1_LKP_MASK
+ | SM5502_REG_INTM1_LKR_MASK,
+ .invert = true,
+ }, {
+ .reg = SM5502_REG_INTMASK2,
+ .val = SM5502_REG_INTM2_VBUS_DET_MASK
+ | SM5502_REG_INTM2_REV_ACCE_MASK
+ | SM5502_REG_INTM2_ADC_CHG_MASK
+ | SM5502_REG_INTM2_STUCK_KEY_MASK
+ | SM5502_REG_INTM2_STUCK_KEY_RCV_MASK
+ | SM5502_REG_INTM2_MHL_MASK,
+ .invert = true,
+ },
+ { }
+};
+
+/* List of detectable cables */
+enum {
+ EXTCON_CABLE_USB = 0,
+ EXTCON_CABLE_USB_HOST,
+ EXTCON_CABLE_TA,
+
+ EXTCON_CABLE_END,
+};
+
+static const char *sm5502_extcon_cable[] = {
+ [EXTCON_CABLE_USB] = "USB",
+ [EXTCON_CABLE_USB_HOST] = "USB-Host",
+ [EXTCON_CABLE_TA] = "TA",
+ NULL,
+};
+
+/* Define supported accessory type */
+enum sm5502_muic_acc_type {
+ SM5502_MUIC_ADC_GROUND = 0x0,
+ SM5502_MUIC_ADC_SEND_END_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S1_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S2_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S3_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S4_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S5_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S6_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S7_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S8_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S9_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S10_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S11_BUTTON,
+ SM5502_MUIC_ADC_REMOTE_S12_BUTTON,
+ SM5502_MUIC_ADC_RESERVED_ACC_1,
+ SM5502_MUIC_ADC_RESERVED_ACC_2,
+ SM5502_MUIC_ADC_RESERVED_ACC_3,
+ SM5502_MUIC_ADC_RESERVED_ACC_4,
+ SM5502_MUIC_ADC_RESERVED_ACC_5,
+ SM5502_MUIC_ADC_AUDIO_TYPE2,
+ SM5502_MUIC_ADC_PHONE_POWERED_DEV,
+ SM5502_MUIC_ADC_TTY_CONVERTER,
+ SM5502_MUIC_ADC_UART_CABLE,
+ SM5502_MUIC_ADC_TYPE1_CHARGER,
+ SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB,
+ SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB,
+ SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE,
+ SM5502_MUIC_ADC_TYPE2_CHARGER,
+ SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART,
+ SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART,
+ SM5502_MUIC_ADC_AUDIO_TYPE1,
+ SM5502_MUIC_ADC_OPEN = 0x1f,
+
+ /* The below accessories have same ADC value (0x1f or 0x1e).
+ So, Device type1 is used to separate specific accessory. */
+ /* |---------|--ADC| */
+ /* | [7:5]|[4:0]| */
+ SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */
+ SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e, /* | 010|11110| */
+ /* |Dev Type1|--ADC| */
+ SM5502_MUIC_ADC_OPEN_USB = 0x5f, /* | 010|11111| */
+ SM5502_MUIC_ADC_OPEN_TA = 0xdf, /* | 110|11111| */
+ SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff, /* | 111|11111| */
+};
+
+/* List of supported interrupt for SM5502 */
+static struct muic_irq sm5502_muic_irqs[] = {
+ { SM5502_IRQ_INT1_ATTACH, "muic-attach" },
+ { SM5502_IRQ_INT1_DETACH, "muic-detach" },
+ { SM5502_IRQ_INT1_KP, "muic-kp" },
+ { SM5502_IRQ_INT1_LKP, "muic-lkp" },
+ { SM5502_IRQ_INT1_LKR, "muic-lkr" },
+ { SM5502_IRQ_INT1_OVP_EVENT, "muic-ovp-event" },
+ { SM5502_IRQ_INT1_OCP_EVENT, "muic-ocp-event" },
+ { SM5502_IRQ_INT1_OVP_OCP_DIS, "muic-ovp-ocp-dis" },
+ { SM5502_IRQ_INT2_VBUS_DET, "muic-vbus-det" },
+ { SM5502_IRQ_INT2_REV_ACCE, "muic-rev-acce" },
+ { SM5502_IRQ_INT2_ADC_CHG, "muic-adc-chg" },
+ { SM5502_IRQ_INT2_STUCK_KEY, "muic-stuck-key" },
+ { SM5502_IRQ_INT2_STUCK_KEY_RCV, "muic-stuck-key-rcv" },
+ { SM5502_IRQ_INT2_MHL, "muic-mhl" },
+};
+
+/* Define interrupt list of SM5502 to register regmap_irq */
+static const struct regmap_irq sm5502_irqs[] = {
+ /* INT1 interrupts */
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_ATTACH_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_DETACH_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_KP_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKP_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_LKR_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_EVENT_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OCP_EVENT_MASK, },
+ { .reg_offset = 0, .mask = SM5502_IRQ_INT1_OVP_OCP_DIS_MASK, },
+
+ /* INT2 interrupts */
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_VBUS_DET_MASK,},
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_REV_ACCE_MASK, },
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_ADC_CHG_MASK, },
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_MASK, },
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_STUCK_KEY_RCV_MASK, },
+ { .reg_offset = 1, .mask = SM5502_IRQ_INT2_MHL_MASK, },
+};
+
+static const struct regmap_irq_chip sm5502_muic_irq_chip = {
+ .name = "sm5502",
+ .status_base = SM5502_REG_INT1,
+ .mask_base = SM5502_REG_INTMASK1,
+ .mask_invert = false,
+ .num_regs = 2,
+ .irqs = sm5502_irqs,
+ .num_irqs = ARRAY_SIZE(sm5502_irqs),
+};
+
+/* Define regmap configuration of SM5502 for I2C communication */
+static bool sm5502_muic_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SM5502_REG_INTMASK1:
+ case SM5502_REG_INTMASK2:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static const struct regmap_config sm5502_muic_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_reg = sm5502_muic_volatile_reg,
+ .max_register = SM5502_REG_END,
+};
+
+/* Change DM_CON/DP_CON/VBUSIN switch according to cable type */
+static int sm5502_muic_set_path(struct sm5502_muic_info *info,
+ unsigned int con_sw, unsigned int vbus_sw,
+ bool attached)
+{
+ int ret;
+
+ if (!attached) {
+ con_sw = DM_DP_SWITCH_OPEN;
+ vbus_sw = VBUSIN_SWITCH_OPEN;
+ }
+
+ switch (con_sw) {
+ case DM_DP_SWITCH_OPEN:
+ case DM_DP_SWITCH_USB:
+ case DM_DP_SWITCH_AUDIO:
+ case DM_DP_SWITCH_UART:
+ ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
+ SM5502_REG_MANUAL_SW1_DP_MASK |
+ SM5502_REG_MANUAL_SW1_DM_MASK,
+ con_sw);
+ if (ret < 0) {
+ dev_err(info->dev,
+ "cannot update DM_CON/DP_CON switch\n");
+ return ret;
+ }
+ break;
+ default:
+ dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
+ con_sw);
+ return -EINVAL;
+ };
+
+ switch (vbus_sw) {
+ case VBUSIN_SWITCH_OPEN:
+ case VBUSIN_SWITCH_VBUSOUT:
+ case VBUSIN_SWITCH_MIC:
+ case VBUSIN_SWITCH_VBUSOUT_WITH_USB:
+ ret = regmap_update_bits(info->regmap, SM5502_REG_MANUAL_SW1,
+ SM5502_REG_MANUAL_SW1_VBUSIN_MASK,
+ vbus_sw);
+ if (ret < 0) {
+ dev_err(info->dev,
+ "cannot update VBUSIN switch\n");
+ return ret;
+ }
+ break;
+ default:
+ dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
+ return -EINVAL;
+ };
+
+ return 0;
+}
+
+/* Return cable type of attached or detached accessories */
+static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
+{
+ unsigned int cable_type = -1, adc, dev_type1;
+ int ret;
+
+ /* Read ADC value according to external cable or button */
+ ret = regmap_read(info->regmap, SM5502_REG_ADC, &adc);
+ if (ret) {
+ dev_err(info->dev, "failed to read ADC register\n");
+ return ret;
+ }
+
+ /*
+ * If ADC is SM5502_MUIC_ADC_GROUND(0x0), external cable hasn't
+ * connected with to MUIC device.
+ */
+ cable_type &= SM5502_REG_ADC_MASK;
+ if (cable_type == SM5502_MUIC_ADC_GROUND)
+ return SM5502_MUIC_ADC_GROUND;
+
+ switch (cable_type) {
+ case SM5502_MUIC_ADC_GROUND:
+ case SM5502_MUIC_ADC_SEND_END_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S1_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S2_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S3_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S4_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S5_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S6_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S7_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S8_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S9_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S10_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S11_BUTTON:
+ case SM5502_MUIC_ADC_REMOTE_S12_BUTTON:
+ case SM5502_MUIC_ADC_RESERVED_ACC_1:
+ case SM5502_MUIC_ADC_RESERVED_ACC_2:
+ case SM5502_MUIC_ADC_RESERVED_ACC_3:
+ case SM5502_MUIC_ADC_RESERVED_ACC_4:
+ case SM5502_MUIC_ADC_RESERVED_ACC_5:
+ case SM5502_MUIC_ADC_AUDIO_TYPE2:
+ case SM5502_MUIC_ADC_PHONE_POWERED_DEV:
+ case SM5502_MUIC_ADC_TTY_CONVERTER:
+ case SM5502_MUIC_ADC_UART_CABLE:
+ case SM5502_MUIC_ADC_TYPE1_CHARGER:
+ case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_USB:
+ case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_USB:
+ case SM5502_MUIC_ADC_AUDIO_VIDEO_CABLE:
+ case SM5502_MUIC_ADC_TYPE2_CHARGER:
+ case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_OFF_UART:
+ case SM5502_MUIC_ADC_FACTORY_MODE_BOOT_ON_UART:
+ break;
+ case SM5502_MUIC_ADC_AUDIO_TYPE1:
+ /*
+ * Check whether cable type is
+ * SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE
+ * or SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END
+ * by using Button event.
+ */
+ break;
+ case SM5502_MUIC_ADC_OPEN:
+ ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1,
+ &dev_type1);
+ if (ret) {
+ dev_err(info->dev, "failed to read DEV_TYPE1 reg\n");
+ return ret;
+ }
+
+ switch (dev_type1) {
+ case SM5502_REG_DEV_TYPE1_USB_SDP_MASK:
+ cable_type = SM5502_MUIC_ADC_OPEN_USB;
+ break;
+ case SM5502_REG_DEV_TYPE1_DEDICATED_CHG_MASK:
+ cable_type = SM5502_MUIC_ADC_OPEN_TA;
+ break;
+ case SM5502_REG_DEV_TYPE1_USB_OTG_MASK:
+ cable_type = SM5502_MUIC_ADC_OPEN_USB_OTG;
+ break;
+ default:
+ dev_dbg(info->dev,
+ "cannot identify the cable type: adc(0x%x) "
+ "dev_type1(0x%x)\n", adc, dev_type1);
+ return -EINVAL;
+ };
+ break;
+ default:
+ dev_err(info->dev,
+ "failed to identify the cable type: adc(0x%x)\n", adc);
+ return -EINVAL;
+ };
+
+ return cable_type;
+}
+
+static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
+ bool attached)
+{
+ static unsigned int prev_cable_type = SM5502_MUIC_ADC_GROUND;
+ const char **cable_names = info->edev->supported_cable;
+ unsigned int cable_type = SM5502_MUIC_ADC_GROUND;
+ unsigned int con_sw = DM_DP_SWITCH_OPEN;
+ unsigned int vbus_sw = VBUSIN_SWITCH_OPEN;
+ unsigned int idx = 0;
+ int ret;
+
+ if (!cable_names)
+ return 0;
+
+ /* Get the type of attached or detached cable */
+ if (attached)
+ cable_type = sm5502_muic_get_cable_type(info);
+ else if (!attached)
+ cable_type = prev_cable_type;
+ prev_cable_type = cable_type;
+
+ switch (cable_type) {
+ case SM5502_MUIC_ADC_OPEN_USB:
+ idx = EXTCON_CABLE_USB;
+ con_sw = DM_DP_SWITCH_USB;
+ vbus_sw = VBUSIN_SWITCH_VBUSOUT_WITH_USB;
+ break;
+ case SM5502_MUIC_ADC_OPEN_TA:
+ idx = EXTCON_CABLE_TA;
+ con_sw = DM_DP_SWITCH_OPEN;
+ vbus_sw = VBUSIN_SWITCH_VBUSOUT;
+ break;
+ case SM5502_MUIC_ADC_OPEN_USB_OTG:
+ idx = EXTCON_CABLE_USB_HOST;
+ con_sw = DM_DP_SWITCH_USB;
+ vbus_sw = VBUSIN_SWITCH_OPEN;
+ break;
+ default:
+ dev_dbg(info->dev,
+ "cannot handle this cable_type (0x%x)\n", cable_type);
+ return 0;
+ };
+
+ /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
+ ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
+ if (ret < 0)
+ return ret;
+
+ /* Change the state of external accessory */
+ extcon_set_cable_state(info->edev, cable_names[idx], attached);
+
+ return 0;
+}
+
+static void sm5502_muic_irq_work(struct work_struct *work)
+{
+ struct sm5502_muic_info *info = container_of(work,
+ struct sm5502_muic_info, irq_work);
+ int ret = 0;
+
+ if (!info->edev)
+ return;
+
+ mutex_lock(&info->mutex);
+
+ /* Detect attached or detached cables */
+ if (info->irq_attach) {
+ ret = sm5502_muic_cable_handler(info, true);
+ info->irq_attach = false;
+ }
+ if (info->irq_detach) {
+ ret = sm5502_muic_cable_handler(info, false);
+ info->irq_detach = false;
+ }
+
+ if (ret < 0)
+ dev_err(info->dev, "failed to handle MUIC interrupt\n");
+
+ mutex_unlock(&info->mutex);
+
+ return;
+}
+
+/*
+ * Sets irq_attach or irq_detach in sm5502_muic_info and returns 0.
+ * Returns -ESRCH if irq_type does not match registered IRQ for this dev type.
+ */
+static int sm5502_parse_irq(struct sm5502_muic_info *info, int irq_type)
+{
+ switch (irq_type) {
+ case SM5502_IRQ_INT1_ATTACH:
+ info->irq_attach = true;
+ break;
+ case SM5502_IRQ_INT1_DETACH:
+ info->irq_detach = true;
+ break;
+ case SM5502_IRQ_INT1_KP:
+ case SM5502_IRQ_INT1_LKP:
+ case SM5502_IRQ_INT1_LKR:
+ case SM5502_IRQ_INT1_OVP_EVENT:
+ case SM5502_IRQ_INT1_OCP_EVENT:
+ case SM5502_IRQ_INT1_OVP_OCP_DIS:
+ case SM5502_IRQ_INT2_VBUS_DET:
+ case SM5502_IRQ_INT2_REV_ACCE:
+ case SM5502_IRQ_INT2_ADC_CHG:
+ case SM5502_IRQ_INT2_STUCK_KEY:
+ case SM5502_IRQ_INT2_STUCK_KEY_RCV:
+ case SM5502_IRQ_INT2_MHL:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static irqreturn_t sm5502_muic_irq_handler(int irq, void *data)
+{
+ struct sm5502_muic_info *info = data;
+ int i, irq_type = -1, ret;
+
+ for (i = 0; i < info->num_muic_irqs; i++)
+ if (irq == info->muic_irqs[i].virq)
+ irq_type = info->muic_irqs[i].irq;
+
+ ret = sm5502_parse_irq(info, irq_type);
+ if (ret < 0) {
+ dev_warn(info->dev, "cannot handle is interrupt:%d\n",
+ irq_type);
+ return IRQ_HANDLED;
+ }
+ schedule_work(&info->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void sm5502_muic_detect_cable_wq(struct work_struct *work)
+{
+ struct sm5502_muic_info *info = container_of(to_delayed_work(work),
+ struct sm5502_muic_info, wq_detcable);
+ int ret;
+
+ /* Notify the state of connector cable or not */
+ ret = sm5502_muic_cable_handler(info, true);
+ if (ret < 0)
+ dev_warn(info->dev, "failed to detect cable state\n");
+}
+
+static void sm5502_init_dev_type(struct sm5502_muic_info *info)
+{
+ unsigned int reg_data, vendor_id, version_id;
+ int i, ret;
+
+ /* To test I2C, Print version_id and vendor_id of SM5502 */
+ ret = regmap_read(info->regmap, SM5502_REG_DEVICE_ID, &reg_data);
+ if (ret) {
+ dev_err(info->dev,
+ "failed to read DEVICE_ID register: %d\n", ret);
+ return;
+ }
+
+ vendor_id = ((reg_data & SM5502_REG_DEVICE_ID_VENDOR_MASK) >>
+ SM5502_REG_DEVICE_ID_VENDOR_SHIFT);
+ version_id = ((reg_data & SM5502_REG_DEVICE_ID_VERSION_MASK) >>
+ SM5502_REG_DEVICE_ID_VERSION_SHIFT);
+
+ dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
+ version_id, vendor_id);
+
+ /* Initiazle the register of SM5502 device to bring-up */
+ for (i = 0; i < info->num_reg_data; i++) {
+ unsigned int val = 0;
+
+ if (!info->reg_data[i].invert)
+ val |= ~info->reg_data[i].val;
+ else
+ val = info->reg_data[i].val;
+ regmap_write(info->regmap, info->reg_data[i].reg, val);
+ }
+}
+
+static int sm5022_muic_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct device_node *np = i2c->dev.of_node;
+ struct sm5502_muic_info *info;
+ int i, ret, irq_flags;
+
+ if (!np)
+ return -EINVAL;
+
+ info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ i2c_set_clientdata(i2c, info);
+
+ info->dev = &i2c->dev;
+ info->i2c = i2c;
+ info->irq = i2c->irq;
+ info->muic_irqs = sm5502_muic_irqs;
+ info->num_muic_irqs = ARRAY_SIZE(sm5502_muic_irqs);
+ info->reg_data = sm5502_reg_data;
+ info->num_reg_data = ARRAY_SIZE(sm5502_reg_data);
+
+ mutex_init(&info->mutex);
+
+ INIT_WORK(&info->irq_work, sm5502_muic_irq_work);
+
+ info->regmap = devm_regmap_init_i2c(i2c, &sm5502_muic_regmap_config);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(info->dev, "failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ /* Support irq domain for SM5502 MUIC device */
+ irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED;
+ ret = regmap_add_irq_chip(info->regmap, info->irq, irq_flags, 0,
+ &sm5502_muic_irq_chip, &info->irq_data);
+ if (ret != 0) {
+ dev_err(info->dev, "failed to request IRQ %d: %d\n",
+ info->irq, ret);
+ return ret;
+ }
+
+ for (i = 0; i < info->num_muic_irqs; i++) {
+ struct muic_irq *muic_irq = &info->muic_irqs[i];
+ unsigned int virq = 0;
+
+ virq = regmap_irq_get_virq(info->irq_data, muic_irq->irq);
+ if (virq <= 0)
+ return -EINVAL;
+ muic_irq->virq = virq;
+
+ ret = devm_request_threaded_irq(info->dev, virq, NULL,
+ sm5502_muic_irq_handler,
+ IRQF_NO_SUSPEND,
+ muic_irq->name, info);
+ if (ret) {
+ dev_err(info->dev, "failed: irq request (IRQ: %d,"
+ " error :%d)\n", muic_irq->irq, ret);
+ return ret;
+ }
+ }
+
+ /* Allocate extcon device */
+ info->edev = devm_extcon_dev_allocate(info->dev, sm5502_extcon_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(info->dev, "failed to allocate memory for extcon\n");
+ return -ENOMEM;
+ }
+ info->edev->name = np->name;
+
+ /* Register extcon device */
+ ret = devm_extcon_dev_register(info->dev, info->edev);
+ if (ret) {
+ dev_err(info->dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ /*
+ * Detect accessory after completing the initialization of platform
+ *
+ * - Use delayed workqueue to detect cable state and then
+ * notify cable state to notifiee/platform through uevent.
+ * After completing the booting of platform, the extcon provider
+ * driver should notify cable state to upper layer.
+ */
+ INIT_DELAYED_WORK(&info->wq_detcable, sm5502_muic_detect_cable_wq);
+ queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+ msecs_to_jiffies(DELAY_MS_DEFAULT));
+
+ /* Initialize SM5502 device and print vendor id and version id */
+ sm5502_init_dev_type(info);
+
+ return 0;
+}
+
+static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
+{
+ struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+ regmap_del_irq_chip(info->irq, info->irq_data);
+
+ return 0;
+}
+
+static struct of_device_id sm5502_dt_match[] = {
+ { .compatible = "siliconmitus,sm5502-muic" },
+ { },
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int sm5502_muic_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+ enable_irq_wake(info->irq);
+
+ return 0;
+}
+
+static int sm5502_muic_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct sm5502_muic_info *info = i2c_get_clientdata(i2c);
+
+ disable_irq_wake(info->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sm5502_muic_pm_ops,
+ sm5502_muic_suspend, sm5502_muic_resume);
+
+static const struct i2c_device_id sm5502_i2c_id[] = {
+ { "sm5502", TYPE_SM5502 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sm5502_i2c_id);
+
+static struct i2c_driver sm5502_muic_i2c_driver = {
+ .driver = {
+ .name = "sm5502",
+ .owner = THIS_MODULE,
+ .pm = &sm5502_muic_pm_ops,
+ .of_match_table = sm5502_dt_match,
+ },
+ .probe = sm5022_muic_i2c_probe,
+ .remove = sm5502_muic_i2c_remove,
+ .id_table = sm5502_i2c_id,
+};
+
+static int __init sm5502_muic_i2c_init(void)
+{
+ return i2c_add_driver(&sm5502_muic_i2c_driver);
+}
+subsys_initcall(sm5502_muic_i2c_init);
+
+MODULE_DESCRIPTION("Silicon Mitus SM5502 Extcon driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index d7d5c8af92b9..5d997a33907e 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -1214,9 +1214,9 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
switch (a->clk_id) {
- case CLOCK_REALTIME: getnstimeofday(&ts); break;
- case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break;
- case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break;
+ case CLOCK_REALTIME: getnstimeofday(&ts); break;
+ case CLOCK_MONOTONIC: ktime_get_ts(&ts); break;
+ case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break;
default:
ret = -EINVAL;
}
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index c3986452194d..2c68da1ceeee 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1460,7 +1460,8 @@ static int fwnet_probe(struct fw_unit *unit,
goto have_dev;
}
- net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev);
+ net = alloc_netdev(sizeof(*dev), "firewire%d", NET_NAME_UNKNOWN,
+ fwnet_init_dev);
if (net == NULL) {
mutex_unlock(&fwnet_device_mutex);
return -ENOMEM;
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index d420ae2d3413..f712d47f30d8 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -54,6 +54,12 @@ config EFI_PARAMS_FROM_FDT
the EFI runtime support gets system table address, memory
map address, and other parameters from the device tree.
+config EFI_RUNTIME_WRAPPERS
+ bool
+
+config EFI_ARMSTUB
+ bool
+
endmenu
config UEFI_CPER
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 9553496b0f43..d8be608a9f3b 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -1,8 +1,10 @@
#
# Makefile for linux kernel
#
-obj-$(CONFIG_EFI) += efi.o vars.o
+obj-$(CONFIG_EFI) += efi.o vars.o reboot.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
obj-$(CONFIG_UEFI_CPER) += cper.o
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
+obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
+obj-$(CONFIG_EFI_STUB) += libstub/
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 1491dd4f08f9..5b53d6183b6b 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -34,6 +34,9 @@
#include <linux/aer.h>
#define INDENT_SP " "
+
+static char rcd_decode_str[CPER_REC_LEN];
+
/*
* CPER record ID need to be unique even after reboot, because record
* ID is used as index for ERST storage, while CPER records from
@@ -50,18 +53,19 @@ u64 cper_next_record_id(void)
}
EXPORT_SYMBOL_GPL(cper_next_record_id);
-static const char *cper_severity_strs[] = {
+static const char * const severity_strs[] = {
"recoverable",
"fatal",
"corrected",
"info",
};
-static const char *cper_severity_str(unsigned int severity)
+const char *cper_severity_str(unsigned int severity)
{
- return severity < ARRAY_SIZE(cper_severity_strs) ?
- cper_severity_strs[severity] : "unknown";
+ return severity < ARRAY_SIZE(severity_strs) ?
+ severity_strs[severity] : "unknown";
}
+EXPORT_SYMBOL_GPL(cper_severity_str);
/*
* cper_print_bits - print strings for set bits
@@ -100,32 +104,32 @@ void cper_print_bits(const char *pfx, unsigned int bits,
printk("%s\n", buf);
}
-static const char * const cper_proc_type_strs[] = {
+static const char * const proc_type_strs[] = {
"IA32/X64",
"IA64",
};
-static const char * const cper_proc_isa_strs[] = {
+static const char * const proc_isa_strs[] = {
"IA32",
"IA64",
"X64",
};
-static const char * const cper_proc_error_type_strs[] = {
+static const char * const proc_error_type_strs[] = {
"cache error",
"TLB error",
"bus error",
"micro-architectural error",
};
-static const char * const cper_proc_op_strs[] = {
+static const char * const proc_op_strs[] = {
"unknown or generic",
"data read",
"data write",
"instruction execution",
};
-static const char * const cper_proc_flag_strs[] = {
+static const char * const proc_flag_strs[] = {
"restartable",
"precise IP",
"overflow",
@@ -137,26 +141,26 @@ static void cper_print_proc_generic(const char *pfx,
{
if (proc->validation_bits & CPER_PROC_VALID_TYPE)
printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
- proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ?
- cper_proc_type_strs[proc->proc_type] : "unknown");
+ proc->proc_type < ARRAY_SIZE(proc_type_strs) ?
+ proc_type_strs[proc->proc_type] : "unknown");
if (proc->validation_bits & CPER_PROC_VALID_ISA)
printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
- proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ?
- cper_proc_isa_strs[proc->proc_isa] : "unknown");
+ proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ?
+ proc_isa_strs[proc->proc_isa] : "unknown");
if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
cper_print_bits(pfx, proc->proc_error_type,
- cper_proc_error_type_strs,
- ARRAY_SIZE(cper_proc_error_type_strs));
+ proc_error_type_strs,
+ ARRAY_SIZE(proc_error_type_strs));
}
if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
printk("%s""operation: %d, %s\n", pfx, proc->operation,
- proc->operation < ARRAY_SIZE(cper_proc_op_strs) ?
- cper_proc_op_strs[proc->operation] : "unknown");
+ proc->operation < ARRAY_SIZE(proc_op_strs) ?
+ proc_op_strs[proc->operation] : "unknown");
if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
printk("%s""flags: 0x%02x\n", pfx, proc->flags);
- cper_print_bits(pfx, proc->flags, cper_proc_flag_strs,
- ARRAY_SIZE(cper_proc_flag_strs));
+ cper_print_bits(pfx, proc->flags, proc_flag_strs,
+ ARRAY_SIZE(proc_flag_strs));
}
if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
printk("%s""level: %d\n", pfx, proc->level);
@@ -177,7 +181,7 @@ static void cper_print_proc_generic(const char *pfx,
printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
}
-static const char *cper_mem_err_type_strs[] = {
+static const char * const mem_err_type_strs[] = {
"unknown",
"no error",
"single-bit ECC",
@@ -196,58 +200,136 @@ static const char *cper_mem_err_type_strs[] = {
"physical memory map-out event",
};
-static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+const char *cper_mem_err_type_str(unsigned int etype)
{
- if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
- printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
- if (mem->validation_bits & CPER_MEM_VALID_PA)
- printk("%s""physical_address: 0x%016llx\n",
- pfx, mem->physical_addr);
- if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
- printk("%s""physical_address_mask: 0x%016llx\n",
- pfx, mem->physical_addr_mask);
+ return etype < ARRAY_SIZE(mem_err_type_strs) ?
+ mem_err_type_strs[etype] : "unknown";
+}
+EXPORT_SYMBOL_GPL(cper_mem_err_type_str);
+
+static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
+{
+ u32 len, n;
+
+ if (!msg)
+ return 0;
+
+ n = 0;
+ len = CPER_REC_LEN - 1;
if (mem->validation_bits & CPER_MEM_VALID_NODE)
- pr_debug("node: %d\n", mem->node);
+ n += scnprintf(msg + n, len - n, "node: %d ", mem->node);
if (mem->validation_bits & CPER_MEM_VALID_CARD)
- pr_debug("card: %d\n", mem->card);
+ n += scnprintf(msg + n, len - n, "card: %d ", mem->card);
if (mem->validation_bits & CPER_MEM_VALID_MODULE)
- pr_debug("module: %d\n", mem->module);
+ n += scnprintf(msg + n, len - n, "module: %d ", mem->module);
if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
- pr_debug("rank: %d\n", mem->rank);
+ n += scnprintf(msg + n, len - n, "rank: %d ", mem->rank);
if (mem->validation_bits & CPER_MEM_VALID_BANK)
- pr_debug("bank: %d\n", mem->bank);
+ n += scnprintf(msg + n, len - n, "bank: %d ", mem->bank);
if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
- pr_debug("device: %d\n", mem->device);
+ n += scnprintf(msg + n, len - n, "device: %d ", mem->device);
if (mem->validation_bits & CPER_MEM_VALID_ROW)
- pr_debug("row: %d\n", mem->row);
+ n += scnprintf(msg + n, len - n, "row: %d ", mem->row);
if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
- pr_debug("column: %d\n", mem->column);
+ n += scnprintf(msg + n, len - n, "column: %d ", mem->column);
if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
- pr_debug("bit_position: %d\n", mem->bit_pos);
+ n += scnprintf(msg + n, len - n, "bit_position: %d ",
+ mem->bit_pos);
if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
- pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id);
+ n += scnprintf(msg + n, len - n, "requestor_id: 0x%016llx ",
+ mem->requestor_id);
if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
- pr_debug("responder_id: 0x%016llx\n", mem->responder_id);
+ n += scnprintf(msg + n, len - n, "responder_id: 0x%016llx ",
+ mem->responder_id);
if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
- pr_debug("target_id: 0x%016llx\n", mem->target_id);
+ scnprintf(msg + n, len - n, "target_id: 0x%016llx ",
+ mem->target_id);
+
+ msg[n] = '\0';
+ return n;
+}
+
+static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
+{
+ u32 len, n;
+ const char *bank = NULL, *device = NULL;
+
+ if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
+ return 0;
+
+ n = 0;
+ len = CPER_REC_LEN - 1;
+ dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
+ if (bank && device)
+ n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
+ else
+ n = snprintf(msg, len,
+ "DIMM location: not present. DMI handle: 0x%.4x ",
+ mem->mem_dev_handle);
+
+ msg[n] = '\0';
+ return n;
+}
+
+void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
+ struct cper_mem_err_compact *cmem)
+{
+ cmem->validation_bits = mem->validation_bits;
+ cmem->node = mem->node;
+ cmem->card = mem->card;
+ cmem->module = mem->module;
+ cmem->bank = mem->bank;
+ cmem->device = mem->device;
+ cmem->row = mem->row;
+ cmem->column = mem->column;
+ cmem->bit_pos = mem->bit_pos;
+ cmem->requestor_id = mem->requestor_id;
+ cmem->responder_id = mem->responder_id;
+ cmem->target_id = mem->target_id;
+ cmem->rank = mem->rank;
+ cmem->mem_array_handle = mem->mem_array_handle;
+ cmem->mem_dev_handle = mem->mem_dev_handle;
+}
+
+const char *cper_mem_err_unpack(struct trace_seq *p,
+ struct cper_mem_err_compact *cmem)
+{
+ const char *ret = p->buffer + p->len;
+
+ if (cper_mem_err_location(cmem, rcd_decode_str))
+ trace_seq_printf(p, "%s", rcd_decode_str);
+ if (cper_dimm_err_location(cmem, rcd_decode_str))
+ trace_seq_printf(p, "%s", rcd_decode_str);
+ trace_seq_putc(p, '\0');
+
+ return ret;
+}
+
+static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+{
+ struct cper_mem_err_compact cmem;
+
+ if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
+ printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
+ if (mem->validation_bits & CPER_MEM_VALID_PA)
+ printk("%s""physical_address: 0x%016llx\n",
+ pfx, mem->physical_addr);
+ if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
+ printk("%s""physical_address_mask: 0x%016llx\n",
+ pfx, mem->physical_addr_mask);
+ cper_mem_err_pack(mem, &cmem);
+ if (cper_mem_err_location(&cmem, rcd_decode_str))
+ printk("%s%s\n", pfx, rcd_decode_str);
if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
u8 etype = mem->error_type;
printk("%s""error_type: %d, %s\n", pfx, etype,
- etype < ARRAY_SIZE(cper_mem_err_type_strs) ?
- cper_mem_err_type_strs[etype] : "unknown");
- }
- if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
- const char *bank = NULL, *device = NULL;
- dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
- if (bank != NULL && device != NULL)
- printk("%s""DIMM location: %s %s", pfx, bank, device);
- else
- printk("%s""DIMM DMI handle: 0x%.4x",
- pfx, mem->mem_dev_handle);
+ cper_mem_err_type_str(etype));
}
+ if (cper_dimm_err_location(&cmem, rcd_decode_str))
+ printk("%s%s\n", pfx, rcd_decode_str);
}
-static const char *cper_pcie_port_type_strs[] = {
+static const char * const pcie_port_type_strs[] = {
"PCIe end point",
"legacy PCI end point",
"unknown",
@@ -262,12 +344,12 @@ static const char *cper_pcie_port_type_strs[] = {
};
static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
- const struct acpi_generic_data *gdata)
+ const struct acpi_hest_generic_data *gdata)
{
if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
- pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
- cper_pcie_port_type_strs[pcie->port_type] : "unknown");
+ pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ?
+ pcie_port_type_strs[pcie->port_type] : "unknown");
if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
printk("%s""version: %d.%d\n", pfx,
pcie->version.major, pcie->version.minor);
@@ -298,7 +380,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
}
static void cper_estatus_print_section(
- const char *pfx, const struct acpi_generic_data *gdata, int sec_no)
+ const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
{
uuid_le *sec_type = (uuid_le *)gdata->section_type;
__u16 severity;
@@ -344,9 +426,9 @@ err_section_too_small:
}
void cper_estatus_print(const char *pfx,
- const struct acpi_generic_status *estatus)
+ const struct acpi_hest_generic_status *estatus)
{
- struct acpi_generic_data *gdata;
+ struct acpi_hest_generic_data *gdata;
unsigned int data_len, gedata_len;
int sec_no = 0;
char newpfx[64];
@@ -359,7 +441,7 @@ void cper_estatus_print(const char *pfx,
"and requires no further action");
printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
data_len = estatus->data_length;
- gdata = (struct acpi_generic_data *)(estatus + 1);
+ gdata = (struct acpi_hest_generic_data *)(estatus + 1);
snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
while (data_len >= sizeof(*gdata)) {
gedata_len = gdata->error_data_length;
@@ -371,10 +453,10 @@ void cper_estatus_print(const char *pfx,
}
EXPORT_SYMBOL_GPL(cper_estatus_print);
-int cper_estatus_check_header(const struct acpi_generic_status *estatus)
+int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus)
{
if (estatus->data_length &&
- estatus->data_length < sizeof(struct acpi_generic_data))
+ estatus->data_length < sizeof(struct acpi_hest_generic_data))
return -EINVAL;
if (estatus->raw_data_length &&
estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
@@ -384,9 +466,9 @@ int cper_estatus_check_header(const struct acpi_generic_status *estatus)
}
EXPORT_SYMBOL_GPL(cper_estatus_check_header);
-int cper_estatus_check(const struct acpi_generic_status *estatus)
+int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
{
- struct acpi_generic_data *gdata;
+ struct acpi_hest_generic_data *gdata;
unsigned int data_len, gedata_len;
int rc;
@@ -394,7 +476,7 @@ int cper_estatus_check(const struct acpi_generic_status *estatus)
if (rc)
return rc;
data_len = estatus->data_length;
- gdata = (struct acpi_generic_data *)(estatus + 1);
+ gdata = (struct acpi_hest_generic_data *)(estatus + 1);
while (data_len >= sizeof(*gdata)) {
gedata_len = gdata->error_data_length;
if (gedata_len > data_len - sizeof(*gdata))
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index dc79346689e6..64ecbb501c50 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,6 +23,7 @@
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
struct efi __read_mostly efi = {
.mps = EFI_INVALID_TABLE_ADDR,
@@ -104,16 +105,19 @@ static struct attribute *efi_subsys_attrs[] = {
static umode_t efi_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
- umode_t mode = attr->mode;
-
- if (attr == &efi_attr_fw_vendor.attr)
- return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
- else if (attr == &efi_attr_runtime.attr)
- return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
- else if (attr == &efi_attr_config_table.attr)
- return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
+ if (attr == &efi_attr_fw_vendor.attr) {
+ if (efi_enabled(EFI_PARAVIRT) ||
+ efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
+ return 0;
+ } else if (attr == &efi_attr_runtime.attr) {
+ if (efi.runtime == EFI_INVALID_TABLE_ADDR)
+ return 0;
+ } else if (attr == &efi_attr_config_table.attr) {
+ if (efi.config_table == EFI_INVALID_TABLE_ADDR)
+ return 0;
+ }
- return mode;
+ return attr->mode;
}
static struct attribute_group efi_subsys_attr_group = {
@@ -298,7 +302,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
if (table64 >> 32) {
pr_cont("\n");
pr_err("Table located above 4GB, disabling EFI.\n");
- early_iounmap(config_tables,
+ early_memunmap(config_tables,
efi.systab->nr_tables * sz);
return -EINVAL;
}
@@ -314,13 +318,27 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
tablep += sz;
}
pr_cont("\n");
- early_iounmap(config_tables, efi.systab->nr_tables * sz);
+ early_memunmap(config_tables, efi.systab->nr_tables * sz);
set_bit(EFI_CONFIG_TABLES, &efi.flags);
return 0;
}
+#ifdef CONFIG_EFI_VARS_MODULE
+static int __init efi_load_efivars(void)
+{
+ struct platform_device *pdev;
+
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
+ return 0;
+
+ pdev = platform_device_register_simple("efivars", 0, NULL, 0);
+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+}
+device_initcall(efi_load_efivars);
+#endif
+
#ifdef CONFIG_EFI_PARAMS_FROM_FDT
#define UEFI_PARAM(name, prop, field) \
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index 463c56545ae8..f256ecd8a176 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
MODULE_DESCRIPTION("sysfs interface to EFI Variables");
MODULE_LICENSE("GPL");
MODULE_VERSION(EFIVARS_VERSION);
+MODULE_ALIAS("platform:efivars");
LIST_HEAD(efivar_sysfs_list);
EXPORT_SYMBOL_GPL(efivar_sysfs_list);
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
new file mode 100644
index 000000000000..b14bc2b9fb4d
--- /dev/null
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -0,0 +1,26 @@
+#
+# The stub may be linked into the kernel proper or into a separate boot binary,
+# but in either case, it executes before the kernel does (with MMU disabled) so
+# things like ftrace and stack-protector are likely to cause trouble if left
+# enabled, even if doing so doesn't break the build.
+#
+cflags-$(CONFIG_X86_32) := -march=i386
+cflags-$(CONFIG_X86_64) := -mcmodel=small
+cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+ -fPIC -fno-strict-aliasing -mno-red-zone \
+ -mno-mmx -mno-sse -DDISABLE_BRANCH_PROFILING
+
+cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
+cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \
+ -fno-builtin -fpic -mno-single-pic-base
+
+KBUILD_CFLAGS := $(cflags-y) \
+ $(call cc-option,-ffreestanding) \
+ $(call cc-option,-fno-stack-protector)
+
+GCOV_PROFILE := n
+
+lib-y := efi-stub-helper.o
+lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o
+
+CFLAGS_fdt.o += -I$(srctree)/scripts/dtc/libfdt/
diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 41114ce03b01..480339b6b110 100644
--- a/drivers/firmware/efi/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -12,6 +12,11 @@
*
*/
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
{
static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID;
@@ -36,8 +41,8 @@ static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
}
}
-static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
- void *__image, void **__fh)
+efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
+ void *__image, void **__fh)
{
efi_file_io_interface_t *io;
efi_loaded_image_t *image = __image;
@@ -60,14 +65,15 @@ static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
*__fh = fh;
return status;
}
-static efi_status_t efi_file_close(void *handle)
+
+efi_status_t efi_file_close(void *handle)
{
efi_file_handle_t *fh = handle;
return fh->close(handle);
}
-static efi_status_t
+efi_status_t
efi_file_read(void *handle, unsigned long *size, void *addr)
{
efi_file_handle_t *fh = handle;
@@ -76,7 +82,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr)
}
-static efi_status_t
+efi_status_t
efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
efi_char16_t *filename_16, void **handle, u64 *file_sz)
{
@@ -129,7 +135,7 @@ grow:
-static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+void efi_char16_printk(efi_system_table_t *sys_table_arg,
efi_char16_t *str)
{
struct efi_simple_text_output_protocol *out;
@@ -145,13 +151,13 @@ static void efi_char16_printk(efi_system_table_t *sys_table_arg,
* must be reserved. On failure it is required to free all
* all allocations it has made.
*/
-static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
- unsigned long *image_addr,
- unsigned long *image_size,
- unsigned long *reserve_addr,
- unsigned long *reserve_size,
- unsigned long dram_base,
- efi_loaded_image_t *image);
+efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
+ unsigned long *image_addr,
+ unsigned long *image_size,
+ unsigned long *reserve_addr,
+ unsigned long *reserve_size,
+ unsigned long dram_base,
+ efi_loaded_image_t *image);
/*
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
* that is described in the PE/COFF header. Most of the code is the same
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index eb6d4be9e722..32d5cca30f49 100644
--- a/drivers/firmware/efi/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -9,18 +9,20 @@
* under the terms of the GNU General Public License version 2.
*
*/
-#define EFI_READ_CHUNK_SIZE (1024 * 1024)
-/* error code which can't be mistaken for valid address */
-#define EFI_ERROR (~0UL)
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+#define EFI_READ_CHUNK_SIZE (1024 * 1024)
struct file_info {
efi_file_handle_t *handle;
u64 size;
};
-static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
+void efi_printk(efi_system_table_t *sys_table_arg, char *str)
{
char *s8;
@@ -37,16 +39,12 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
}
}
-#define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg)
-#define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg)
-
-
-static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
- efi_memory_desc_t **map,
- unsigned long *map_size,
- unsigned long *desc_size,
- u32 *desc_ver,
- unsigned long *key_ptr)
+efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
+ efi_memory_desc_t **map,
+ unsigned long *map_size,
+ unsigned long *desc_size,
+ u32 *desc_ver,
+ unsigned long *key_ptr)
{
efi_memory_desc_t *m = NULL;
efi_status_t status;
@@ -88,7 +86,7 @@ fail:
}
-static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg)
+unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg)
{
efi_status_t status;
unsigned long map_size;
@@ -116,9 +114,9 @@ static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg)
/*
* Allocate at the highest possible address that is not above 'max'.
*/
-static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
- unsigned long size, unsigned long align,
- unsigned long *addr, unsigned long max)
+efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
+ unsigned long size, unsigned long align,
+ unsigned long *addr, unsigned long max)
{
unsigned long map_size, desc_size;
efi_memory_desc_t *map;
@@ -202,9 +200,9 @@ fail:
/*
* Allocate at the lowest possible address.
*/
-static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
- unsigned long size, unsigned long align,
- unsigned long *addr)
+efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
+ unsigned long size, unsigned long align,
+ unsigned long *addr)
{
unsigned long map_size, desc_size;
efi_memory_desc_t *map;
@@ -271,8 +269,8 @@ fail:
return status;
}
-static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
- unsigned long addr)
+void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
+ unsigned long addr)
{
unsigned long nr_pages;
@@ -290,12 +288,12 @@ static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
* We only support loading a file from the same filesystem as
* the kernel image.
*/
-static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
- efi_loaded_image_t *image,
- char *cmd_line, char *option_string,
- unsigned long max_addr,
- unsigned long *load_addr,
- unsigned long *load_size)
+efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
+ efi_loaded_image_t *image,
+ char *cmd_line, char *option_string,
+ unsigned long max_addr,
+ unsigned long *load_addr,
+ unsigned long *load_size)
{
struct file_info *files;
unsigned long file_addr;
@@ -477,12 +475,12 @@ fail:
* address is not available the lowest available address will
* be used.
*/
-static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
- unsigned long *image_addr,
- unsigned long image_size,
- unsigned long alloc_size,
- unsigned long preferred_addr,
- unsigned long alignment)
+efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
+ unsigned long *image_addr,
+ unsigned long image_size,
+ unsigned long alloc_size,
+ unsigned long preferred_addr,
+ unsigned long alignment)
{
unsigned long cur_image_addr;
unsigned long new_addr = 0;
@@ -589,9 +587,9 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
* Size of memory allocated return in *cmd_line_len.
* Returns NULL on error.
*/
-static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
- efi_loaded_image_t *image,
- int *cmd_line_len)
+char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
+ efi_loaded_image_t *image,
+ int *cmd_line_len)
{
const u16 *s2;
u8 *s1 = NULL;
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
new file mode 100644
index 000000000000..304ab295ca1a
--- /dev/null
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -0,0 +1,42 @@
+
+#ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
+
+/* error code which can't be mistaken for valid address */
+#define EFI_ERROR (~0UL)
+
+void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+
+efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
+ void **__fh);
+
+efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh,
+ efi_char16_t *filename_16, void **handle,
+ u64 *file_sz);
+
+efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr);
+
+efi_status_t efi_file_close(void *handle);
+
+unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
+
+efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+ unsigned long orig_fdt_size,
+ void *fdt, int new_fdt_size, char *cmdline_ptr,
+ u64 initrd_addr, u64 initrd_size,
+ efi_memory_desc_t *memory_map,
+ unsigned long map_size, unsigned long desc_size,
+ u32 desc_ver);
+
+efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
+ void *handle,
+ unsigned long *new_fdt_addr,
+ unsigned long max_addr,
+ u64 initrd_addr, u64 initrd_size,
+ char *cmdline_ptr,
+ unsigned long fdt_addr,
+ unsigned long fdt_size);
+
+void *get_fdt(efi_system_table_t *sys_table);
+
+#endif
diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 507a3df46a5d..a56bb3528755 100644
--- a/drivers/firmware/efi/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -10,13 +10,17 @@
*
*/
-static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
- unsigned long orig_fdt_size,
- void *fdt, int new_fdt_size, char *cmdline_ptr,
- u64 initrd_addr, u64 initrd_size,
- efi_memory_desc_t *memory_map,
- unsigned long map_size, unsigned long desc_size,
- u32 desc_ver)
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+#include <asm/efi.h>
+
+efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+ unsigned long orig_fdt_size,
+ void *fdt, int new_fdt_size, char *cmdline_ptr,
+ u64 initrd_addr, u64 initrd_size,
+ efi_memory_desc_t *memory_map,
+ unsigned long map_size, unsigned long desc_size,
+ u32 desc_ver)
{
int node, prev;
int status;
@@ -255,7 +259,7 @@ fail:
return EFI_LOAD_ERROR;
}
-static void *get_fdt(efi_system_table_t *sys_table)
+void *get_fdt(efi_system_table_t *sys_table)
{
efi_guid_t fdt_guid = DEVICE_TREE_GUID;
efi_config_table_t *tables;
diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
new file mode 100644
index 000000000000..9c59d1c795d1
--- /dev/null
+++ b/drivers/firmware/efi/reboot.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 Intel Corporation; author Matt Fleming
+ * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com>
+ */
+#include <linux/efi.h>
+#include <linux/reboot.h>
+
+int efi_reboot_quirk_mode = -1;
+
+void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
+{
+ int efi_mode;
+
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
+ return;
+
+ switch (reboot_mode) {
+ case REBOOT_WARM:
+ case REBOOT_SOFT:
+ efi_mode = EFI_RESET_WARM;
+ break;
+ default:
+ efi_mode = EFI_RESET_COLD;
+ break;
+ }
+
+ /*
+ * If a quirk forced an EFI reset mode, always use that.
+ */
+ if (efi_reboot_quirk_mode != -1)
+ efi_mode = efi_reboot_quirk_mode;
+
+ efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);
+}
+
+bool __weak efi_poweroff_required(void)
+{
+ return false;
+}
+
+static void efi_power_off(void)
+{
+ efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
+}
+
+static int __init efi_shutdown_init(void)
+{
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
+ return -ENODEV;
+
+ if (efi_poweroff_required())
+ pm_power_off = efi_power_off;
+
+ return 0;
+}
+late_initcall(efi_shutdown_init);
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
index 97cdd16a2169..018c29a26615 100644
--- a/drivers/firmware/efi/runtime-map.c
+++ b/drivers/firmware/efi/runtime-map.c
@@ -138,6 +138,27 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr)
return entry;
}
+int efi_get_runtime_map_size(void)
+{
+ return nr_efi_runtime_map * efi_memdesc_size;
+}
+
+int efi_get_runtime_map_desc_size(void)
+{
+ return efi_memdesc_size;
+}
+
+int efi_runtime_map_copy(void *buf, size_t bufsz)
+{
+ size_t sz = efi_get_runtime_map_size();
+
+ if (sz > bufsz)
+ sz = bufsz;
+
+ memcpy(buf, efi_runtime_map, sz);
+ return 0;
+}
+
void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size)
{
efi_runtime_map = map;
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
new file mode 100644
index 000000000000..10daa4bbb258
--- /dev/null
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -0,0 +1,161 @@
+/*
+ * runtime-wrappers.c - Runtime Services function call wrappers
+ *
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * Split off from arch/x86/platform/efi/efi.c
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ * Copyright (C) 2005-2008 Intel Co.
+ * Copyright (C) 2013 SuSE Labs
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/efi.h>
+#include <linux/spinlock.h> /* spinlock_t */
+#include <asm/efi.h>
+
+/*
+ * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
+ * the EFI specification requires that callers of the time related runtime
+ * functions serialize with other CMOS accesses in the kernel, as the EFI time
+ * functions may choose to also use the legacy CMOS RTC.
+ */
+__weak DEFINE_SPINLOCK(rtc_lock);
+
+static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt(get_time, tm, tc);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
+}
+
+static efi_status_t virt_efi_set_time(efi_time_t *tm)
+{
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt(set_time, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
+}
+
+static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
+ efi_bool_t *pending,
+ efi_time_t *tm)
+{
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
+}
+
+static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+{
+ unsigned long flags;
+ efi_status_t status;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ status = efi_call_virt(set_wakeup_time, enabled, tm);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ return status;
+}
+
+static efi_status_t virt_efi_get_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 *attr,
+ unsigned long *data_size,
+ void *data)
+{
+ return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
+ efi_char16_t *name,
+ efi_guid_t *vendor)
+{
+ return efi_call_virt(get_next_variable, name_size, name, vendor);
+}
+
+static efi_status_t virt_efi_set_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 attr,
+ unsigned long data_size,
+ void *data)
+{
+ return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_query_variable_info(u32 attr,
+ u64 *storage_space,
+ u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt(query_variable_info, attr, storage_space,
+ remaining_space, max_variable_size);
+}
+
+static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
+{
+ return efi_call_virt(get_next_high_mono_count, count);
+}
+
+static void virt_efi_reset_system(int reset_type,
+ efi_status_t status,
+ unsigned long data_size,
+ efi_char16_t *data)
+{
+ __efi_call_virt(reset_system, reset_type, status, data_size, data);
+}
+
+static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
+ unsigned long count,
+ unsigned long sg_list)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt(update_capsule, capsules, count, sg_list);
+}
+
+static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+ unsigned long count,
+ u64 *max_size,
+ int *reset_type)
+{
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ return efi_call_virt(query_capsule_caps, capsules, count, max_size,
+ reset_type);
+}
+
+void efi_native_runtime_setup(void)
+{
+ efi.get_time = virt_efi_get_time;
+ efi.set_time = virt_efi_set_time;
+ efi.get_wakeup_time = virt_efi_get_wakeup_time;
+ efi.set_wakeup_time = virt_efi_set_wakeup_time;
+ efi.get_variable = virt_efi_get_variable;
+ efi.get_next_variable = virt_efi_get_next_variable;
+ efi.set_variable = virt_efi_set_variable;
+ efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+ efi.reset_system = virt_efi_reset_system;
+ efi.query_variable_info = virt_efi_query_variable_info;
+ efi.update_capsule = virt_efi_update_capsule;
+ efi.query_capsule_caps = virt_efi_query_capsule_caps;
+}
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 17cf96c45f2b..79f18e6d9c4f 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -286,7 +286,11 @@ int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;
- entry = firmware_map_find_entry_bootmem(start, end, type);
+ entry = firmware_map_find_entry(start, end - 1, type);
+ if (entry)
+ return 0;
+
+ entry = firmware_map_find_entry_bootmem(start, end - 1, type);
if (!entry) {
entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
if (!entry)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 4a1b5113e527..9de1515e5808 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -340,6 +340,13 @@ config GPIO_XILINX
help
Say yes here to support the Xilinx FPGA GPIO device
+config GPIO_ZYNQ
+ tristate "Xilinx Zynq GPIO support"
+ depends on ARCH_ZYNQ
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to support Xilinx Zynq GPIO controller.
+
config GPIO_XTENSA
bool "Xtensa GPIO32 support"
depends on XTENSA
@@ -423,7 +430,7 @@ config GPIO_GE_FPGA
config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
- select IRQ_DOMAIN
+ select GPIOLIB_IRQCHIP
help
driver for GPIO functionality on Intel Lynxpoint PCH chipset
Requires ACPI device enumeration code to set up a platform device.
@@ -450,6 +457,19 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
+config GPIO_CRYSTAL_COVE
+ tristate "GPIO support for Crystal Cove PMIC"
+ depends on INTEL_SOC_PMIC
+ select GPIOLIB_IRQCHIP
+ help
+ Support for GPIO pins on Crystal Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Crystal Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-crystalcove.
+
config GPIO_LP3943
tristate "TI/National Semiconductor LP3943 GPIO expander"
depends on MFD_LP3943
@@ -573,6 +593,7 @@ config GPIO_SX150X
config GPIO_STMPE
bool "STMPE GPIOs"
depends on MFD_STMPE
+ select GPIOLIB_IRQCHIP
help
This enables support for the GPIOs found on the STMPE I/O
Expanders.
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d10f6a9d875a..5d024e396622 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,7 +4,9 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIO_DEVRES) += devres.o
obj-$(CONFIG_GPIOLIB) += gpiolib.o
+obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
+obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
@@ -20,6 +22,7 @@ obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.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_CRYSTAL_COVE) += gpio-crystalcove.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
@@ -101,3 +104,4 @@ obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
+obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 65978cf85f79..41b2f40578d5 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -39,47 +39,53 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
* devm_gpiod_get - Resource-managed gpiod_get()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
*
* Managed gpiod_get(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get() for detailed
* information about behavior and return values.
*/
-struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
- const char *con_id)
+struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
+ const char *con_id,
+ enum gpiod_flags flags)
{
- return devm_gpiod_get_index(dev, con_id, 0);
+ return devm_gpiod_get_index(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL(devm_gpiod_get);
+EXPORT_SYMBOL(__devm_gpiod_get);
/**
* devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
*
* Managed gpiod_get_optional(). GPIO descriptors returned from this function
* are automatically disposed on driver detach. See gpiod_get_optional() for
* detailed information about behavior and return values.
*/
-struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
- const char *con_id)
+struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
+ const char *con_id,
+ enum gpiod_flags flags)
{
- return devm_gpiod_get_index_optional(dev, con_id, 0);
+ return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL(devm_gpiod_get_optional);
+EXPORT_SYMBOL(__devm_gpiod_get_optional);
/**
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
*
* Managed gpiod_get_index(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get_index() for detailed
* information about behavior and return values.
*/
-struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
const char *con_id,
- unsigned int idx)
+ unsigned int idx,
+ enum gpiod_flags flags)
{
struct gpio_desc **dr;
struct gpio_desc *desc;
@@ -89,7 +95,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
if (!dr)
return ERR_PTR(-ENOMEM);
- desc = gpiod_get_index(dev, con_id, idx);
+ desc = gpiod_get_index(dev, con_id, idx, flags);
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
@@ -100,26 +106,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_gpiod_get_index);
+EXPORT_SYMBOL(__devm_gpiod_get_index);
/**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
*
* Managed gpiod_get_index_optional(). GPIO descriptors returned from this
* function are automatically disposed on driver detach. See
* gpiod_get_index_optional() for detailed information about behavior and
* return values.
*/
-struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev,
const char *con_id,
- unsigned int index)
+ unsigned int index,
+ enum gpiod_flags flags)
{
struct gpio_desc *desc;
- desc = devm_gpiod_get_index(dev, con_id, index);
+ desc = devm_gpiod_get_index(dev, con_id, index, flags);
if (IS_ERR(desc)) {
if (PTR_ERR(desc) == -ENOENT)
return NULL;
@@ -127,7 +135,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_gpiod_get_index_optional);
+EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
/**
* devm_gpiod_put - Resource-managed gpiod_put()
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index e4ae29824c32..e3d968f751f1 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -167,13 +167,11 @@ exit_destroy:
static int gen_74x164_remove(struct spi_device *spi)
{
struct gen_74x164_chip *chip = spi_get_drvdata(spi);
- int ret;
- ret = gpiochip_remove(&chip->gpio_chip);
- if (!ret)
- mutex_destroy(&chip->lock);
+ gpiochip_remove(&chip->gpio_chip);
+ mutex_destroy(&chip->lock);
- return ret;
+ return 0;
}
static const struct of_device_id gen_74x164_dt_ids[] = {
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index b2239d678d01..416b2200d4f1 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -585,15 +585,8 @@ static int adnp_i2c_remove(struct i2c_client *client)
{
struct adnp *adnp = i2c_get_clientdata(client);
struct device_node *np = client->dev.of_node;
- int err;
-
- err = gpiochip_remove(&adnp->gpio);
- if (err < 0) {
- dev_err(&client->dev, "%s failed: %d\n", "gpiochip_remove()",
- err);
- return err;
- }
+ gpiochip_remove(&adnp->gpio);
if (of_find_property(np, "interrupt-controller", NULL))
adnp_irq_teardown(adnp);
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index f1ade8fa3218..b08bd169e568 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -167,15 +167,9 @@ err:
static int adp5520_gpio_remove(struct platform_device *pdev)
{
struct adp5520_gpio *dev;
- int ret;
dev = platform_get_drvdata(pdev);
- ret = gpiochip_remove(&dev->gpio_chip);
- if (ret) {
- dev_err(&pdev->dev, "%s failed, %d\n",
- "gpiochip_remove()", ret);
- return ret;
- }
+ gpiochip_remove(&dev->gpio_chip);
return 0;
}
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index ef19bc33f2bd..3beed6ea8c65 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -470,11 +470,7 @@ static int adp5588_gpio_remove(struct i2c_client *client)
if (dev->irq_base)
free_irq(dev->client->irq, dev);
- ret = gpiochip_remove(&dev->gpio_chip);
- if (ret) {
- dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
- return ret;
- }
+ gpiochip_remove(&dev->gpio_chip);
kfree(dev);
return 0;
diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c
index 94e9992f8904..3c09f1a6872a 100644
--- a/drivers/gpio/gpio-amd8111.c
+++ b/drivers/gpio/gpio-amd8111.c
@@ -232,8 +232,7 @@ out:
static void __exit amd_gpio_exit(void)
{
- int err = gpiochip_remove(&gp.chip);
- WARN_ON(err);
+ gpiochip_remove(&gp.chip);
ioport_unmap(gp.pm);
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
}
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 29bdff558981..fe369f5c7fa6 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -149,7 +149,8 @@ static int arizona_gpio_remove(struct platform_device *pdev)
{
struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&arizona_gpio->gpio_chip);
+ gpiochip_remove(&arizona_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver arizona_gpio_driver = {
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
new file mode 100644
index 000000000000..934462f5bd22
--- /dev/null
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -0,0 +1,380 @@
+/*
+ * gpio-crystalcove.c - Intel Crystal Cove GPIO Driver
+ *
+ * Copyright (C) 2012, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as 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.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/seq_file.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+
+#define CRYSTALCOVE_GPIO_NUM 16
+
+#define UPDATE_IRQ_TYPE BIT(0)
+#define UPDATE_IRQ_MASK BIT(1)
+
+#define GPIO0IRQ 0x0b
+#define GPIO1IRQ 0x0c
+#define MGPIO0IRQS0 0x19
+#define MGPIO1IRQS0 0x1a
+#define MGPIO0IRQSX 0x1b
+#define MGPIO1IRQSX 0x1c
+#define GPIO0P0CTLO 0x2b
+#define GPIO0P0CTLI 0x33
+#define GPIO1P0CTLO 0x3b
+#define GPIO1P0CTLI 0x43
+
+#define CTLI_INTCNT_DIS (0)
+#define CTLI_INTCNT_NE (1 << 1)
+#define CTLI_INTCNT_PE (2 << 1)
+#define CTLI_INTCNT_BE (3 << 1)
+
+#define CTLO_DIR_IN (0)
+#define CTLO_DIR_OUT (1 << 5)
+
+#define CTLO_DRV_CMOS (0)
+#define CTLO_DRV_OD (1 << 4)
+
+#define CTLO_DRV_REN (1 << 3)
+
+#define CTLO_RVAL_2KDW (0)
+#define CTLO_RVAL_2KUP (1 << 1)
+#define CTLO_RVAL_50KDW (2 << 1)
+#define CTLO_RVAL_50KUP (3 << 1)
+
+#define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP)
+#define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET)
+
+enum ctrl_register {
+ CTRL_IN,
+ CTRL_OUT,
+};
+
+/**
+ * struct crystalcove_gpio - Crystal Cove GPIO controller
+ * @buslock: for bus lock/sync and unlock.
+ * @chip: the abstract gpio_chip structure.
+ * @regmap: the regmap from the parent device.
+ * @update: pending IRQ setting update, to be written to the chip upon unlock.
+ * @intcnt_value: the Interrupt Detect value to be written.
+ * @set_irq_mask: true if the IRQ mask needs to be set, false to clear.
+ */
+struct crystalcove_gpio {
+ struct mutex buslock; /* irq_bus_lock */
+ struct gpio_chip chip;
+ struct regmap *regmap;
+ int update;
+ int intcnt_value;
+ bool set_irq_mask;
+};
+
+static inline struct crystalcove_gpio *to_cg(struct gpio_chip *gc)
+{
+ return container_of(gc, struct crystalcove_gpio, chip);
+}
+
+static inline int to_reg(int gpio, enum ctrl_register reg_type)
+{
+ int reg;
+
+ if (reg_type == CTRL_IN) {
+ if (gpio < 8)
+ reg = GPIO0P0CTLI;
+ else
+ reg = GPIO1P0CTLI;
+ } else {
+ if (gpio < 8)
+ reg = GPIO0P0CTLO;
+ else
+ reg = GPIO1P0CTLO;
+ }
+
+ return reg + gpio % 8;
+}
+
+static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg,
+ int gpio)
+{
+ u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0;
+ int mask = BIT(gpio % 8);
+
+ if (cg->set_irq_mask)
+ regmap_update_bits(cg->regmap, mirqs0, mask, mask);
+ else
+ regmap_update_bits(cg->regmap, mirqs0, mask, 0);
+}
+
+static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
+{
+ int reg = to_reg(gpio, CTRL_IN);
+
+ regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value);
+}
+
+static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+ CTLO_INPUT_SET);
+}
+
+static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
+ int value)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
+ CTLO_OUTPUT_SET | value);
+}
+
+static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+ if (ret)
+ return ret;
+
+ return val & 0x1;
+}
+
+static void crystalcove_gpio_set(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+
+ if (value)
+ regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+ else
+ regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+}
+
+static int crystalcove_irq_type(struct irq_data *data, unsigned type)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ cg->intcnt_value = CTLI_INTCNT_DIS;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ cg->intcnt_value = CTLI_INTCNT_BE;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ cg->intcnt_value = CTLI_INTCNT_PE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ cg->intcnt_value = CTLI_INTCNT_NE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cg->update |= UPDATE_IRQ_TYPE;
+
+ return 0;
+}
+
+static void crystalcove_bus_lock(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ mutex_lock(&cg->buslock);
+}
+
+static void crystalcove_bus_sync_unlock(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+ int gpio = data->hwirq;
+
+ if (cg->update & UPDATE_IRQ_TYPE)
+ crystalcove_update_irq_ctrl(cg, gpio);
+ if (cg->update & UPDATE_IRQ_MASK)
+ crystalcove_update_irq_mask(cg, gpio);
+ cg->update = 0;
+
+ mutex_unlock(&cg->buslock);
+}
+
+static void crystalcove_irq_unmask(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ cg->set_irq_mask = false;
+ cg->update |= UPDATE_IRQ_MASK;
+}
+
+static void crystalcove_irq_mask(struct irq_data *data)
+{
+ struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
+
+ cg->set_irq_mask = true;
+ cg->update |= UPDATE_IRQ_MASK;
+}
+
+static struct irq_chip crystalcove_irqchip = {
+ .name = "Crystal Cove",
+ .irq_mask = crystalcove_irq_mask,
+ .irq_unmask = crystalcove_irq_unmask,
+ .irq_set_type = crystalcove_irq_type,
+ .irq_bus_lock = crystalcove_bus_lock,
+ .irq_bus_sync_unlock = crystalcove_bus_sync_unlock,
+};
+
+static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
+{
+ struct crystalcove_gpio *cg = data;
+ unsigned int p0, p1;
+ int pending;
+ int gpio;
+ unsigned int virq;
+
+ if (regmap_read(cg->regmap, GPIO0IRQ, &p0) ||
+ regmap_read(cg->regmap, GPIO1IRQ, &p1))
+ return IRQ_NONE;
+
+ regmap_write(cg->regmap, GPIO0IRQ, p0);
+ regmap_write(cg->regmap, GPIO1IRQ, p1);
+
+ pending = p0 | p1 << 8;
+
+ for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ if (pending & BIT(gpio)) {
+ virq = irq_find_mapping(cg->chip.irqdomain, gpio);
+ generic_handle_irq(virq);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void crystalcove_gpio_dbg_show(struct seq_file *s,
+ struct gpio_chip *chip)
+{
+ struct crystalcove_gpio *cg = to_cg(chip);
+ int gpio, offset;
+ unsigned int ctlo, ctli, mirqs0, mirqsx, irq;
+
+ for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
+ regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
+ regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli);
+ regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0,
+ &mirqs0);
+ regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQSX : MGPIO1IRQSX,
+ &mirqsx);
+ regmap_read(cg->regmap, gpio < 8 ? GPIO0IRQ : GPIO1IRQ,
+ &irq);
+
+ offset = gpio % 8;
+ seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s %s\n",
+ gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ",
+ ctli & 0x1 ? "hi" : "lo",
+ ctli & CTLI_INTCNT_NE ? "fall" : " ",
+ ctli & CTLI_INTCNT_PE ? "rise" : " ",
+ ctlo,
+ mirqs0 & BIT(offset) ? "s0 mask " : "s0 unmask",
+ mirqsx & BIT(offset) ? "sx mask " : "sx unmask",
+ irq & BIT(offset) ? "pending" : " ");
+ }
+}
+
+static int crystalcove_gpio_probe(struct platform_device *pdev)
+{
+ int irq = platform_get_irq(pdev, 0);
+ struct crystalcove_gpio *cg;
+ int retval;
+ struct device *dev = pdev->dev.parent;
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ if (irq < 0)
+ return irq;
+
+ cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL);
+ if (!cg)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cg);
+
+ mutex_init(&cg->buslock);
+ cg->chip.label = KBUILD_MODNAME;
+ cg->chip.direction_input = crystalcove_gpio_dir_in;
+ cg->chip.direction_output = crystalcove_gpio_dir_out;
+ cg->chip.get = crystalcove_gpio_get;
+ cg->chip.set = crystalcove_gpio_set;
+ cg->chip.base = -1;
+ cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM;
+ cg->chip.can_sleep = true;
+ cg->chip.dev = dev;
+ cg->chip.dbg_show = crystalcove_gpio_dbg_show;
+ cg->regmap = pmic->regmap;
+
+ retval = gpiochip_add(&cg->chip);
+ if (retval) {
+ dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
+ return retval;
+ }
+
+ gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+
+ retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
+ IRQF_ONESHOT, KBUILD_MODNAME, cg);
+
+ if (retval) {
+ dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
+ goto out_remove_gpio;
+ }
+
+ return 0;
+
+out_remove_gpio:
+ WARN_ON(gpiochip_remove(&cg->chip));
+ return retval;
+}
+
+static int crystalcove_gpio_remove(struct platform_device *pdev)
+{
+ struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+ int err;
+
+ err = gpiochip_remove(&cg->chip);
+
+ if (irq >= 0)
+ free_irq(irq, cg);
+
+ return err;
+}
+
+static struct platform_driver crystalcove_gpio_driver = {
+ .probe = crystalcove_gpio_probe,
+ .remove = crystalcove_gpio_remove,
+ .driver = {
+ .name = "crystal_cove_gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(crystalcove_gpio_driver);
+
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_DESCRIPTION("Intel Crystal Cove GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index c0a3aeba6f21..92ec58fa9236 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -358,14 +358,8 @@ done:
static int cs5535_gpio_remove(struct platform_device *pdev)
{
struct resource *r;
- int err;
- err = gpiochip_remove(&cs5535_gpio_chip.chip);
- if (err) {
- /* uhh? */
- dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
- return err;
- }
+ gpiochip_remove(&cs5535_gpio_chip.chip);
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 416cdf786b05..c5bccd4dec96 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -237,7 +237,8 @@ static int da9052_gpio_remove(struct platform_device *pdev)
{
struct da9052_gpio *gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&gpio->gp);
+ gpiochip_remove(&gpio->gp);
+ return 0;
}
static struct platform_driver da9052_gpio_driver = {
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
index f992997bc301..9167c4331081 100644
--- a/drivers/gpio/gpio-da9055.c
+++ b/drivers/gpio/gpio-da9055.c
@@ -174,7 +174,8 @@ static int da9055_gpio_remove(struct platform_device *pdev)
{
struct da9055_gpio *gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&gpio->gp);
+ gpiochip_remove(&gpio->gp);
+ return 0;
}
static struct platform_driver da9055_gpio_driver = {
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index cd3b81435274..d6618a6e2399 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -359,7 +359,7 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio)
for (m = 0; m < gpio->nr_ports; ++m)
if (gpio->ports[m].is_registered)
- WARN_ON(gpiochip_remove(&gpio->ports[m].bgc.gc));
+ gpiochip_remove(&gpio->ports[m].bgc.gc);
}
static int dwapb_gpio_probe(struct platform_device *pdev)
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index cde36054c387..fe49ec3cdb7d 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -409,11 +409,8 @@ err0:
static int em_gio_remove(struct platform_device *pdev)
{
struct em_gio_priv *p = platform_get_drvdata(pdev);
- int ret;
- ret = gpiochip_remove(&p->gpio_chip);
- if (ret)
- return ret;
+ gpiochip_remove(&p->gpio_chip);
irq_domain_remove(p->irq_domain);
return 0;
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
index 8f73ee093739..fd3202f968ff 100644
--- a/drivers/gpio/gpio-f7188x.c
+++ b/drivers/gpio/gpio-f7188x.c
@@ -317,13 +317,7 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
err_gpiochip:
for (i = i - 1; i >= 0; i--) {
struct f7188x_gpio_bank *bank = &data->bank[i];
- int tmp;
-
- tmp = gpiochip_remove(&bank->chip);
- if (tmp < 0)
- dev_err(&pdev->dev,
- "Failed to remove gpiochip %d: %d\n",
- i, tmp);
+ gpiochip_remove(&bank->chip);
}
return err;
@@ -331,20 +325,12 @@ err_gpiochip:
static int f7188x_gpio_remove(struct platform_device *pdev)
{
- int err;
int i;
struct f7188x_gpio_data *data = platform_get_drvdata(pdev);
for (i = 0; i < data->nr_bank; i++) {
struct f7188x_gpio_bank *bank = &data->bank[i];
-
- err = gpiochip_remove(&bank->chip);
- if (err) {
- dev_err(&pdev->dev,
- "Failed to remove GPIO gpiochip %d: %d\n",
- i, err);
- return err;
- }
+ gpiochip_remove(&bank->chip);
}
return 0;
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index fea8c82bb8fc..16f6115e5bdb 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -398,7 +398,8 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
int bgpio_remove(struct bgpio_chip *bgc)
{
- return gpiochip_remove(&bgc->gc);
+ gpiochip_remove(&bgc->gc);
+ return 0;
}
EXPORT_SYMBOL_GPL(bgpio_remove);
diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
index 3c3f515b7916..66ad3df9d9cf 100644
--- a/drivers/gpio/gpio-grgpio.c
+++ b/drivers/gpio/gpio-grgpio.c
@@ -468,9 +468,7 @@ static int grgpio_remove(struct platform_device *ofdev)
}
}
- ret = gpiochip_remove(&priv->bgc.gc);
- if (ret)
- goto out;
+ gpiochip_remove(&priv->bgc.gc);
if (priv->domain)
irq_domain_remove(priv->domain);
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index 70304220a479..3784e81e7762 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -514,14 +514,7 @@ add_err:
static int ichx_gpio_remove(struct platform_device *pdev)
{
- int err;
-
- err = gpiochip_remove(&ichx_priv.chip);
- if (err) {
- dev_err(&pdev->dev, "%s failed, %d\n",
- "gpiochip_remove()", err);
- return err;
- }
+ gpiochip_remove(&ichx_priv.chip);
ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
if (ichx_priv.pm_base)
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
index 118a6bf455d9..aa28c65eb6b4 100644
--- a/drivers/gpio/gpio-intel-mid.c
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -28,12 +28,10 @@
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
-#include <linux/irqdomain.h>
#define INTEL_MID_IRQ_TYPE_EDGE (1 << 0)
#define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1)
@@ -78,10 +76,12 @@ struct intel_mid_gpio {
void __iomem *reg_base;
spinlock_t lock;
struct pci_dev *pdev;
- struct irq_domain *domain;
};
-#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip)
+static inline struct intel_mid_gpio *to_intel_gpio_priv(struct gpio_chip *gc)
+{
+ return container_of(gc, struct intel_mid_gpio, chip);
+}
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type)
@@ -182,15 +182,10 @@ static int intel_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
-static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
- return irq_create_mapping(priv->domain, offset);
-}
-
static int intel_mid_irq_type(struct irq_data *d, unsigned type)
{
- struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
u32 gpio = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
@@ -231,33 +226,11 @@ static void intel_mid_irq_mask(struct irq_data *d)
{
}
-static int intel_mid_irq_reqres(struct irq_data *d)
-{
- struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
-
- if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) {
- dev_err(priv->chip.dev,
- "unable to lock HW IRQ %lu for IRQ\n",
- irqd_to_hwirq(d));
- return -EINVAL;
- }
- return 0;
-}
-
-static void intel_mid_irq_relres(struct irq_data *d)
-{
- struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
-
- gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d));
-}
-
static struct irq_chip intel_mid_irqchip = {
.name = "INTEL_MID-GPIO",
.irq_mask = intel_mid_irq_mask,
.irq_unmask = intel_mid_irq_unmask,
.irq_set_type = intel_mid_irq_type,
- .irq_request_resources = intel_mid_irq_reqres,
- .irq_release_resources = intel_mid_irq_relres,
};
static const struct intel_mid_gpio_ddata gpio_lincroft = {
@@ -330,8 +303,9 @@ MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
struct irq_data *data = irq_desc_get_irq_data(desc);
- struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, gpio, mask;
unsigned long pending;
@@ -345,7 +319,7 @@ static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
mask = BIT(gpio);
/* Clear before handling so we can't lose an edge */
writel(mask, gedr);
- generic_handle_irq(irq_find_mapping(priv->domain,
+ generic_handle_irq(irq_find_mapping(gc->irqdomain,
base + gpio));
}
}
@@ -371,23 +345,6 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
}
}
-static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct intel_mid_gpio *priv = d->host_data;
-
- irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq);
- irq_set_chip_data(irq, priv);
- irq_set_irq_type(irq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static const struct irq_domain_ops intel_gpio_irq_ops = {
- .map = intel_gpio_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
static int intel_gpio_runtime_idle(struct device *dev)
{
int err = pm_schedule_suspend(dev, 500);
@@ -441,7 +398,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
priv->chip.direction_output = intel_gpio_direction_output;
priv->chip.get = intel_gpio_get;
priv->chip.set = intel_gpio_set;
- priv->chip.to_irq = intel_gpio_to_irq;
priv->chip.base = gpio_base;
priv->chip.ngpio = ddata->ngpio;
priv->chip.can_sleep = false;
@@ -449,11 +405,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
spin_lock_init(&priv->lock);
- priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
- irq_base, &intel_gpio_irq_ops, priv);
- if (!priv->domain)
- return -ENOMEM;
-
pci_set_drvdata(pdev, priv);
retval = gpiochip_add(&priv->chip);
if (retval) {
@@ -461,10 +412,23 @@ static int intel_gpio_probe(struct pci_dev *pdev,
return retval;
}
+ retval = gpiochip_irqchip_add(&priv->chip,
+ &intel_mid_irqchip,
+ irq_base,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (retval) {
+ dev_err(&pdev->dev,
+ "could not connect irqchip to gpiochip\n");
+ return retval;
+ }
+
intel_mid_irq_init_hw(priv);
- irq_set_handler_data(pdev->irq, priv);
- irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);
+ gpiochip_set_chained_irqchip(&priv->chip,
+ &intel_mid_irqchip,
+ pdev->irq,
+ intel_mid_irq_handler);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/gpio-it8761e.c
index 278b81317010..dadfc245cf09 100644
--- a/drivers/gpio/gpio-it8761e.c
+++ b/drivers/gpio/gpio-it8761e.c
@@ -217,11 +217,7 @@ gpiochip_add_err:
static void __exit it8761e_gpio_exit(void)
{
if (gpio_ba) {
- int ret = gpiochip_remove(&it8761e_gpio_chip);
-
- WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
- __func__, ret);
-
+ gpiochip_remove(&it8761e_gpio_chip);
release_region(gpio_ba, GPIO_IOSIZE);
gpio_ba = 0;
}
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index 42852eaaf020..29ffe22ad97a 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -194,14 +194,8 @@ static int ttl_probe(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;
- int ret;
- ret = gpiochip_remove(&mod->gpio);
- if (ret) {
- dev_err(dev, "unable to remove GPIO chip\n");
- return ret;
- }
+ gpiochip_remove(&mod->gpio);
return 0;
}
diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c
index 1e5e51987d31..fd150adeebf9 100644
--- a/drivers/gpio/gpio-kempld.c
+++ b/drivers/gpio/gpio-kempld.c
@@ -199,7 +199,8 @@ static int kempld_gpio_remove(struct platform_device *pdev)
{
struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&gpio->chip);
+ gpiochip_remove(&gpio->chip);
+ return 0;
}
static struct platform_driver kempld_gpio_driver = {
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
index a0341c92bcb4..6bbdad805b78 100644
--- a/drivers/gpio/gpio-lp3943.c
+++ b/drivers/gpio/gpio-lp3943.c
@@ -216,7 +216,8 @@ static int lp3943_gpio_remove(struct platform_device *pdev)
{
struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&lp3943_gpio->chip);
+ gpiochip_remove(&lp3943_gpio->chip);
+ return 0;
}
static const struct of_device_id lp3943_gpio_of_match[] = {
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 225344d66404..b9b9799b368b 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -560,7 +560,7 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev)
}
#ifdef CONFIG_OF
-static struct of_device_id lpc32xx_gpio_of_match[] = {
+static const struct of_device_id lpc32xx_gpio_of_match[] = {
{ .compatible = "nxp,lpc3220-gpio", },
{ },
};
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 2bea89b72508..ff9eb911b5e4 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -25,9 +25,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/gpio.h>
-#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
@@ -62,7 +60,6 @@
struct lp_gpio {
struct gpio_chip chip;
- struct irq_domain *domain;
struct platform_device *pdev;
spinlock_t lock;
unsigned long reg_base;
@@ -151,7 +148,8 @@ static void lp_gpio_free(struct gpio_chip *chip, unsigned offset)
static int lp_irq_type(struct irq_data *d, unsigned type)
{
- struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
@@ -236,16 +234,11 @@ static int lp_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
-static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
- return irq_create_mapping(lg->domain, offset);
-}
-
static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
- struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, pin, mask;
unsigned long reg, ena, pending;
@@ -262,7 +255,7 @@ static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
mask = BIT(pin);
/* Clear before handling so we don't lose an edge */
outl(mask, reg);
- irq = irq_find_mapping(lg->domain, base + pin);
+ irq = irq_find_mapping(lg->chip.irqdomain, base + pin);
generic_handle_irq(irq);
}
}
@@ -279,7 +272,8 @@ static void lp_irq_mask(struct irq_data *d)
static void lp_irq_enable(struct irq_data *d)
{
- struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
@@ -291,7 +285,8 @@ static void lp_irq_enable(struct irq_data *d)
static void lp_irq_disable(struct irq_data *d)
{
- struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
@@ -301,26 +296,6 @@ static void lp_irq_disable(struct irq_data *d)
spin_unlock_irqrestore(&lg->lock, flags);
}
-static int lp_irq_reqres(struct irq_data *d)
-{
- struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
-
- if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) {
- dev_err(lg->chip.dev,
- "unable to lock HW IRQ %lu for IRQ\n",
- irqd_to_hwirq(d));
- return -EINVAL;
- }
- return 0;
-}
-
-static void lp_irq_relres(struct irq_data *d)
-{
- struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
-
- gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d));
-}
-
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_mask = lp_irq_mask,
@@ -328,8 +303,6 @@ static struct irq_chip lp_irqchip = {
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_type,
- .irq_request_resources = lp_irq_reqres,
- .irq_release_resources = lp_irq_relres,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
@@ -348,22 +321,6 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
}
}
-static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct lp_gpio *lg = d->host_data;
-
- irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq);
- irq_set_chip_data(irq, lg);
- irq_set_irq_type(irq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static const struct irq_domain_ops lp_gpio_irq_ops = {
- .map = lp_gpio_irq_map,
-};
-
static int lp_gpio_probe(struct platform_device *pdev)
{
struct lp_gpio *lg;
@@ -371,7 +328,6 @@ static int lp_gpio_probe(struct platform_device *pdev)
struct resource *io_rc, *irq_rc;
struct device *dev = &pdev->dev;
unsigned long reg_len;
- unsigned hwirq;
int ret = -ENODEV;
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
@@ -414,27 +370,28 @@ static int lp_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false;
gc->dev = dev;
+ ret = gpiochip_add(gc);
+ if (ret) {
+ dev_err(dev, "failed adding lp-gpio chip\n");
+ return ret;
+ }
+
/* set up interrupts */
if (irq_rc && irq_rc->start) {
- hwirq = irq_rc->start;
- gc->to_irq = lp_gpio_to_irq;
-
- lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO,
- &lp_gpio_irq_ops, lg);
- if (!lg->domain)
- return -ENXIO;
-
lp_gpio_irq_init_hw(lg);
+ ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(dev, "failed to add irqchip\n");
+ gpiochip_remove(gc);
+ return ret;
+ }
- irq_set_handler_data(hwirq, lg);
- irq_set_chained_handler(hwirq, lp_gpio_irq_handler);
+ gpiochip_set_chained_irqchip(gc, &lp_irqchip,
+ (unsigned)irq_rc->start,
+ lp_gpio_irq_handler);
}
- ret = gpiochip_add(gc);
- if (ret) {
- dev_err(dev, "failed adding lp-gpio chip\n");
- return ret;
- }
pm_runtime_enable(dev);
return 0;
@@ -465,11 +422,8 @@ MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
static int lp_gpio_remove(struct platform_device *pdev)
{
struct lp_gpio *lg = platform_get_drvdata(pdev);
- int err;
pm_runtime_disable(&pdev->dev);
- err = gpiochip_remove(&lg->chip);
- if (err)
- dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
+ gpiochip_remove(&lg->chip);
return 0;
}
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 0814584fcdc1..18ab89e20806 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -228,21 +228,16 @@ EXPORT_SYMBOL_GPL(__max730x_probe);
int __max730x_remove(struct device *dev)
{
struct max7301 *ts = dev_get_drvdata(dev);
- int ret;
if (ts == NULL)
return -ENODEV;
/* Power down the chip and disable IRQ output */
ts->write(dev, 0x04, 0x00);
-
- ret = gpiochip_remove(&ts->chip);
- if (!ret)
- mutex_destroy(&ts->lock);
- else
- dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
-
- return ret;
+ gpiochip_remove(&ts->chip);
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ return 0;
}
EXPORT_SYMBOL_GPL(__max730x_remove);
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 7c36f2b0983d..6c676225b886 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -676,12 +676,7 @@ static int max732x_remove(struct i2c_client *client)
}
}
- ret = gpiochip_remove(&chip->gpio_chip);
- if (ret) {
- dev_err(&client->dev, "%s failed, %d\n",
- "gpiochip_remove()", ret);
- return ret;
- }
+ gpiochip_remove(&chip->gpio_chip);
max732x_irq_teardown(chip);
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 553a80a5eaf3..4e3e160e5db2 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -149,20 +149,15 @@ exit_destroy:
static int mc33880_remove(struct spi_device *spi)
{
struct mc33880 *mc;
- int ret;
mc = spi_get_drvdata(spi);
if (mc == NULL)
return -ENODEV;
- ret = gpiochip_remove(&mc->chip);
- if (!ret)
- mutex_destroy(&mc->lock);
- else
- dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
- ret);
+ gpiochip_remove(&mc->chip);
+ mutex_destroy(&mc->lock);
- return ret;
+ return 0;
}
static struct spi_driver mc33880_driver = {
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
index dce35ff00db7..d62b4f8182bf 100644
--- a/drivers/gpio/gpio-mc9s08dz60.c
+++ b/drivers/gpio/gpio-mc9s08dz60.c
@@ -118,7 +118,8 @@ static int mc9s08dz60_remove(struct i2c_client *client)
mc9s = i2c_get_clientdata(client);
- return gpiochip_remove(&mc9s->chip);
+ gpiochip_remove(&mc9s->chip);
+ return 0;
}
static const struct i2c_device_id mc9s08dz60_id[] = {
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 57adbc90fdad..6f183d9b487e 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -812,16 +812,14 @@ fail:
static int mcp230xx_remove(struct i2c_client *client)
{
struct mcp23s08 *mcp = i2c_get_clientdata(client);
- int status;
if (client->irq && mcp->irq_controller)
mcp23s08_irq_teardown(mcp);
- status = gpiochip_remove(&mcp->chip);
- if (status == 0)
- kfree(mcp);
+ gpiochip_remove(&mcp->chip);
+ kfree(mcp);
- return status;
+ return 0;
}
static const struct i2c_device_id mcp230xx_id[] = {
@@ -960,13 +958,10 @@ static int mcp23s08_probe(struct spi_device *spi)
fail:
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
- int tmp;
if (!data->mcp[addr])
continue;
- tmp = gpiochip_remove(&data->mcp[addr]->chip);
- if (tmp < 0)
- dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
+ gpiochip_remove(&data->mcp[addr]->chip);
}
kfree(data);
return status;
@@ -976,23 +971,16 @@ static int mcp23s08_remove(struct spi_device *spi)
{
struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
unsigned addr;
- int status = 0;
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
- int tmp;
if (!data->mcp[addr])
continue;
- tmp = gpiochip_remove(&data->mcp[addr]->chip);
- if (tmp < 0) {
- dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
- status = tmp;
- }
+ gpiochip_remove(&data->mcp[addr]->chip);
}
- if (status == 0)
- kfree(data);
- return status;
+ kfree(data);
+ return 0;
}
static const struct spi_device_id mcp23s08_ids[] = {
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index d51329d23d38..5536108aa9db 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -497,8 +497,7 @@ err_irq_alloc_descs:
err_gpiochip_add:
while (--i >= 0) {
chip--;
- if (gpiochip_remove(&chip->gpio))
- dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
+ gpiochip_remove(&chip->gpio);
}
kfree(chip_save);
@@ -519,7 +518,6 @@ err_pci_enable:
static void ioh_gpio_remove(struct pci_dev *pdev)
{
- int err;
int i;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
void *chip_save;
@@ -530,9 +528,7 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
for (i = 0; i < 8; i++, chip++) {
irq_free_descs(chip->irq_base, num_ports[i]);
- err = gpiochip_remove(&chip->gpio);
- if (err)
- dev_err(&pdev->dev, "Failed gpiochip_remove\n");
+ gpiochip_remove(&chip->gpio);
}
chip = chip_save;
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index a3351acd4963..94f57670df9a 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -438,10 +438,7 @@ MODULE_DEVICE_TABLE(of, msm_gpio_of_match);
static int msm_gpio_remove(struct platform_device *dev)
{
- int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
- if (ret < 0)
- return ret;
+ gpiochip_remove(&msm_gpio.gpio_chip);
irq_set_handler(msm_gpio.summary_irq, NULL);
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index db83b3c0a449..f4e54a92e04a 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -485,7 +485,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
out_irqdesc_free:
irq_free_descs(irq_base, 32);
out_gpiochip_remove:
- WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
+ gpiochip_remove(&port->bgc.gc);
out_bgpio_remove:
bgpio_remove(&port->bgc);
out_bgio:
diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c
index dbb08546b9ec..5c5770c99c80 100644
--- a/drivers/gpio/gpio-octeon.c
+++ b/drivers/gpio/gpio-octeon.c
@@ -129,7 +129,8 @@ out:
static int octeon_gpio_remove(struct platform_device *pdev)
{
struct gpio_chip *chip = pdev->dev.platform_data;
- return gpiochip_remove(chip);
+ gpiochip_remove(chip);
+ return 0;
}
static struct of_device_id octeon_gpio_match[] = {
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 00f29aa1fb9d..174932165fcb 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -24,7 +24,6 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/irqchip/chained_irq.h>
#include <linux/gpio.h>
#include <linux/bitops.h>
#include <linux/platform_data/gpio-omap.h>
@@ -89,18 +88,19 @@ struct gpio_bank {
#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
#define LINE_USED(line, offset) (line & (BIT(offset)))
-static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
+static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
{
return bank->chip.base + gpio_irq;
}
-static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
+static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
return container_of(chip, struct gpio_bank, chip);
}
-static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
+static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
+ int is_input)
{
void __iomem *reg = bank->base;
u32 l;
@@ -117,7 +117,8 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
/* set data out value using dedicate set/clear register */
-static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
+static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, int gpio,
+ int enable)
{
void __iomem *reg = bank->base;
u32 l = GPIO_BIT(bank, gpio);
@@ -134,7 +135,8 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
}
/* set data out value using mask register */
-static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
+static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, int gpio,
+ int enable)
{
void __iomem *reg = bank->base + bank->regs->dataout;
u32 gpio_bit = GPIO_BIT(bank, gpio);
@@ -149,21 +151,21 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
bank->context.dataout = l;
}
-static int _get_gpio_datain(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_datain(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->datain;
return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
-static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
+static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->dataout;
return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
-static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
{
int l = readl_relaxed(base + reg);
@@ -175,7 +177,7 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
writel_relaxed(l, base + reg);
}
-static inline void _gpio_dbck_enable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
{
if (bank->dbck_enable_mask && !bank->dbck_enabled) {
clk_prepare_enable(bank->dbck);
@@ -186,7 +188,7 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank)
}
}
-static inline void _gpio_dbck_disable(struct gpio_bank *bank)
+static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
{
if (bank->dbck_enable_mask && bank->dbck_enabled) {
/*
@@ -202,7 +204,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
}
/**
- * _set_gpio_debounce - low level gpio debounce time
+ * omap2_set_gpio_debounce - low level gpio debounce time
* @bank: the gpio bank we're acting upon
* @gpio: the gpio number on this @gpio
* @debounce: debounce time to use
@@ -210,8 +212,8 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
* OMAP's debounce time is in 31us steps so we need
* to convert and round up to the closest unit.
*/
-static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
- unsigned debounce)
+static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
+ unsigned debounce)
{
void __iomem *reg;
u32 val;
@@ -252,7 +254,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
* used within _gpio_dbck_enable() is still not initialized at
* that point. Therefore we have to enable dbck here.
*/
- _gpio_dbck_enable(bank);
+ omap_gpio_dbck_enable(bank);
if (bank->dbck_enable_mask) {
bank->context.debounce = debounce;
bank->context.debounce_en = val;
@@ -260,7 +262,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
}
/**
- * _clear_gpio_debounce - clear debounce settings for a gpio
+ * omap_clear_gpio_debounce - clear debounce settings for a gpio
* @bank: the gpio bank we're acting upon
* @gpio: the gpio number on this @gpio
*
@@ -269,7 +271,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
* time too. The debounce clock will also be disabled when calling this function
* if this is the only gpio in the bank using debounce.
*/
-static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
{
u32 gpio_bit = GPIO_BIT(bank, gpio);
@@ -293,20 +295,20 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
}
}
-static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
+static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
unsigned trigger)
{
void __iomem *base = bank->base;
u32 gpio_bit = BIT(gpio);
- _gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
- trigger & IRQ_TYPE_LEVEL_LOW);
- _gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
- trigger & IRQ_TYPE_LEVEL_HIGH);
- _gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
- trigger & IRQ_TYPE_EDGE_RISING);
- _gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
- trigger & IRQ_TYPE_EDGE_FALLING);
+ omap_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
+ trigger & IRQ_TYPE_LEVEL_LOW);
+ omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
+ trigger & IRQ_TYPE_LEVEL_HIGH);
+ omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
+ trigger & IRQ_TYPE_EDGE_RISING);
+ omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
+ trigger & IRQ_TYPE_EDGE_FALLING);
bank->context.leveldetect0 =
readl_relaxed(bank->base + bank->regs->leveldetect0);
@@ -318,7 +320,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
readl_relaxed(bank->base + bank->regs->fallingdetect);
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
- _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
+ omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
}
@@ -354,7 +356,7 @@ exit:
* This only applies to chips that can't do both rising and falling edge
* detection at once. For all other chips, this function is a noop.
*/
-static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
{
void __iomem *reg = bank->base;
u32 l = 0;
@@ -373,18 +375,18 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
writel_relaxed(l, reg);
}
#else
-static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
+static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
#endif
-static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
- unsigned trigger)
+static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
+ unsigned trigger)
{
void __iomem *reg = bank->base;
void __iomem *base = bank->base;
u32 l = 0;
if (bank->regs->leveldetect0 && bank->regs->wkup_en) {
- set_gpio_trigger(bank, gpio, trigger);
+ omap_set_gpio_trigger(bank, gpio, trigger);
} else if (bank->regs->irqctrl) {
reg += bank->regs->irqctrl;
@@ -414,7 +416,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
l |= BIT(gpio << 1);
/* Enable wake-up during idle for dynamic tick */
- _gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
+ omap_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
writel_relaxed(l, reg);
@@ -422,7 +424,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
return 0;
}
-static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
{
if (bank->regs->pinctrl) {
void __iomem *reg = bank->base + bank->regs->pinctrl;
@@ -443,7 +445,7 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
}
}
-static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
+static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
{
void __iomem *base = bank->base;
@@ -451,7 +453,7 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
!LINE_USED(bank->mod_usage, offset) &&
!LINE_USED(bank->irq_usage, offset)) {
/* Disable wake-up during idle for dynamic tick */
- _gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
+ omap_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
}
@@ -468,16 +470,16 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
}
}
-static int gpio_is_input(struct gpio_bank *bank, int mask)
+static int omap_gpio_is_input(struct gpio_bank *bank, int mask)
{
void __iomem *reg = bank->base + bank->regs->direction;
return readl_relaxed(reg) & mask;
}
-static int gpio_irq_type(struct irq_data *d, unsigned type)
+static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned gpio = 0;
int retval;
unsigned long flags;
@@ -492,7 +494,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
#endif
if (!gpio)
- gpio = irq_to_gpio(bank, d->hwirq);
+ gpio = omap_irq_to_gpio(bank, d->hwirq);
if (type & ~IRQ_TYPE_SENSE_MASK)
return -EINVAL;
@@ -503,11 +505,11 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
spin_lock_irqsave(&bank->lock, flags);
offset = GPIO_INDEX(bank, gpio);
- retval = _set_gpio_triggering(bank, offset, type);
+ retval = omap_set_gpio_triggering(bank, offset, type);
if (!LINE_USED(bank->mod_usage, offset)) {
- _enable_gpio_module(bank, offset);
- _set_gpio_direction(bank, offset, 1);
- } else if (!gpio_is_input(bank, BIT(offset))) {
+ omap_enable_gpio_module(bank, offset);
+ omap_set_gpio_direction(bank, offset, 1);
+ } else if (!omap_gpio_is_input(bank, BIT(offset))) {
spin_unlock_irqrestore(&bank->lock, flags);
return -EINVAL;
}
@@ -523,7 +525,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
return retval;
}
-static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
@@ -540,12 +542,12 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
readl_relaxed(reg);
}
-static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
+static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
{
- _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+ omap_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
-static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
+static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;
u32 l;
@@ -559,7 +561,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
return l;
}
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
u32 l;
@@ -581,7 +583,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
writel_relaxed(l, reg);
}
-static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
u32 l;
@@ -603,12 +605,13 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
writel_relaxed(l, reg);
}
-static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
+static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, int gpio,
+ int enable)
{
if (enable)
- _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+ omap_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
else
- _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+ omap_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
/*
@@ -619,7 +622,7 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
* enabled. When system is suspended, only selected GPIO interrupts need
* to have wake-up enabled.
*/
-static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
+static int omap_set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
u32 gpio_bit = GPIO_BIT(bank, gpio);
unsigned long flags;
@@ -642,22 +645,22 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
return 0;
}
-static void _reset_gpio(struct gpio_bank *bank, int gpio)
+static void omap_reset_gpio(struct gpio_bank *bank, int gpio)
{
- _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
- _set_gpio_irqenable(bank, gpio, 0);
- _clear_gpio_irqstatus(bank, gpio);
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
- _clear_gpio_debounce(bank, gpio);
+ omap_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
+ omap_set_gpio_irqenable(bank, gpio, 0);
+ omap_clear_gpio_irqstatus(bank, gpio);
+ omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+ omap_clear_gpio_debounce(bank, gpio);
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
-static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
+static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
- unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
- return _set_gpio_wakeup(bank, gpio, enable);
+ return omap_set_gpio_wakeup(bank, gpio, enable);
}
static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -678,8 +681,8 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
* not already been requested.
*/
if (!LINE_USED(bank->irq_usage, offset)) {
- _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
- _enable_gpio_module(bank, offset);
+ omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+ omap_enable_gpio_module(bank, offset);
}
bank->mod_usage |= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags);
@@ -694,8 +697,8 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&bank->lock, flags);
bank->mod_usage &= ~(BIT(offset));
- _disable_gpio_module(bank, offset);
- _reset_gpio(bank, bank->chip.base + offset);
+ omap_disable_gpio_module(bank, offset);
+ omap_reset_gpio(bank, bank->chip.base + offset);
spin_unlock_irqrestore(&bank->lock, flags);
/*
@@ -715,7 +718,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
* line's interrupt handler has been run, we may miss some nested
* interrupts.
*/
-static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
void __iomem *isr_reg = NULL;
u32 isr;
@@ -738,7 +741,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
u32 isr_saved, level_mask = 0;
u32 enabled;
- enabled = _get_gpio_irqbank_mask(bank);
+ enabled = omap_get_gpio_irqbank_mask(bank);
isr_saved = isr = readl_relaxed(isr_reg) & enabled;
if (bank->level_mask)
@@ -747,9 +750,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
/* clear edge sensitive interrupts before handler(s) are
called so that we don't miss any interrupt occurred while
executing them */
- _disable_gpio_irqbank(bank, isr_saved & ~level_mask);
- _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
- _enable_gpio_irqbank(bank, isr_saved & ~level_mask);
+ omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
+ omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+ omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
@@ -773,7 +776,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
* This will be indicated in the bank toggle_mask.
*/
if (bank->toggle_mask & (BIT(bit)))
- _toggle_gpio_edge_triggering(bank, bit);
+ omap_toggle_gpio_edge_triggering(bank, bit);
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit));
@@ -789,18 +792,18 @@ exit:
pm_runtime_put(bank->dev);
}
-static void gpio_irq_shutdown(struct irq_data *d)
+static void omap_gpio_irq_shutdown(struct irq_data *d)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
- unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned long flags;
unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags);
gpio_unlock_as_irq(&bank->chip, offset);
bank->irq_usage &= ~(BIT(offset));
- _disable_gpio_module(bank, offset);
- _reset_gpio(bank, gpio);
+ omap_disable_gpio_module(bank, offset);
+ omap_reset_gpio(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);
/*
@@ -811,57 +814,57 @@ static void gpio_irq_shutdown(struct irq_data *d)
pm_runtime_put(bank->dev);
}
-static void gpio_ack_irq(struct irq_data *d)
+static void omap_gpio_ack_irq(struct irq_data *d)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
- unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
- _clear_gpio_irqstatus(bank, gpio);
+ omap_clear_gpio_irqstatus(bank, gpio);
}
-static void gpio_mask_irq(struct irq_data *d)
+static void omap_gpio_mask_irq(struct irq_data *d)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
- unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
- _set_gpio_irqenable(bank, gpio, 0);
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+ omap_set_gpio_irqenable(bank, gpio, 0);
+ omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
spin_unlock_irqrestore(&bank->lock, flags);
}
-static void gpio_unmask_irq(struct irq_data *d)
+static void omap_gpio_unmask_irq(struct irq_data *d)
{
- struct gpio_bank *bank = _irq_data_get_bank(d);
- unsigned int gpio = irq_to_gpio(bank, d->hwirq);
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned int irq_mask = GPIO_BIT(bank, gpio);
u32 trigger = irqd_get_trigger_type(d);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
if (trigger)
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
+ omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
/* For level-triggered GPIOs, the clearing must be done after
* the HW source is cleared, thus after the handler has run */
if (bank->level_mask & irq_mask) {
- _set_gpio_irqenable(bank, gpio, 0);
- _clear_gpio_irqstatus(bank, gpio);
+ omap_set_gpio_irqenable(bank, gpio, 0);
+ omap_clear_gpio_irqstatus(bank, gpio);
}
- _set_gpio_irqenable(bank, gpio, 1);
+ omap_set_gpio_irqenable(bank, gpio, 1);
spin_unlock_irqrestore(&bank->lock, flags);
}
static struct irq_chip gpio_irq_chip = {
.name = "GPIO",
- .irq_shutdown = gpio_irq_shutdown,
- .irq_ack = gpio_ack_irq,
- .irq_mask = gpio_mask_irq,
- .irq_unmask = gpio_unmask_irq,
- .irq_set_type = gpio_irq_type,
- .irq_set_wake = gpio_wake_enable,
+ .irq_shutdown = omap_gpio_irq_shutdown,
+ .irq_ack = omap_gpio_ack_irq,
+ .irq_mask = omap_gpio_mask_irq,
+ .irq_unmask = omap_gpio_unmask_irq,
+ .irq_set_type = omap_gpio_irq_type,
+ .irq_set_wake = omap_gpio_wake_enable,
};
/*---------------------------------------------------------------------*/
@@ -918,7 +921,7 @@ static struct platform_device omap_mpuio_device = {
/* could list the /proc/iomem resources */
};
-static inline void mpuio_init(struct gpio_bank *bank)
+static inline void omap_mpuio_init(struct gpio_bank *bank)
{
platform_set_drvdata(&omap_mpuio_device, bank);
@@ -928,7 +931,7 @@ static inline void mpuio_init(struct gpio_bank *bank)
/*---------------------------------------------------------------------*/
-static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
unsigned long flags;
@@ -943,19 +946,19 @@ static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
return dir;
}
-static int gpio_input(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- _set_gpio_direction(bank, offset, 1);
+ omap_set_gpio_direction(bank, offset, 1);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
-static int gpio_get(struct gpio_chip *chip, unsigned offset)
+static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
u32 mask;
@@ -963,13 +966,13 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
bank = container_of(chip, struct gpio_bank, chip);
mask = (BIT(offset));
- if (gpio_is_input(bank, mask))
- return _get_gpio_datain(bank, offset);
+ if (omap_gpio_is_input(bank, mask))
+ return omap_get_gpio_datain(bank, offset);
else
- return _get_gpio_dataout(bank, offset);
+ return omap_get_gpio_dataout(bank, offset);
}
-static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
@@ -977,13 +980,13 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
bank->set_dataout(bank, offset, value);
- _set_gpio_direction(bank, offset, 0);
+ omap_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
-static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
- unsigned debounce)
+static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
+ unsigned debounce)
{
struct gpio_bank *bank;
unsigned long flags;
@@ -991,13 +994,13 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- _set_gpio_debounce(bank, offset, debounce);
+ omap2_set_gpio_debounce(bank, offset, debounce);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
-static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
@@ -1025,11 +1028,6 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)
called = true;
}
-/* 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 void omap_gpio_mod_init(struct gpio_bank *bank)
{
void __iomem *base = bank->base;
@@ -1043,8 +1041,10 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
return;
}
- _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv);
- _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv);
+ omap_gpio_rmw(base, bank->regs->irqenable, l,
+ bank->regs->irqenable_inv);
+ omap_gpio_rmw(base, bank->regs->irqstatus, l,
+ !bank->regs->irqenable_inv);
if (bank->regs->debounce_en)
writel_relaxed(0, base + bank->regs->debounce_en);
@@ -1078,10 +1078,10 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
/* NOTE: No ack required, reading IRQ status clears it. */
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = gpio_irq_type;
+ ct->chip.irq_set_type = omap_gpio_irq_type;
if (bank->regs->wkup_en)
- ct->chip.irq_set_wake = gpio_wake_enable;
+ ct->chip.irq_set_wake = omap_gpio_wake_enable;
ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@@ -1101,12 +1101,12 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
*/
bank->chip.request = omap_gpio_request;
bank->chip.free = omap_gpio_free;
- bank->chip.get_direction = gpio_get_direction;
- bank->chip.direction_input = gpio_input;
- bank->chip.get = gpio_get;
- bank->chip.direction_output = gpio_output;
- bank->chip.set_debounce = gpio_debounce;
- bank->chip.set = gpio_set;
+ bank->chip.get_direction = omap_gpio_get_direction;
+ bank->chip.direction_input = omap_gpio_input;
+ bank->chip.get = omap_gpio_get;
+ bank->chip.direction_output = omap_gpio_output;
+ bank->chip.set_debounce = omap_gpio_debounce;
+ bank->chip.set = omap_gpio_set;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
if (bank->regs->wkup_en)
@@ -1138,7 +1138,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
#endif
ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
- irq_base, gpio_irq_handler,
+ irq_base, omap_gpio_irq_handler,
IRQ_TYPE_NONE);
if (ret) {
@@ -1148,11 +1148,10 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
}
gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
- bank->irq, gpio_irq_handler);
+ bank->irq, omap_gpio_irq_handler);
for (j = 0; j < bank->width; j++) {
int irq = irq_find_mapping(bank->chip.irqdomain, j);
- irq_set_lockdep_class(irq, &gpio_lock_class);
if (bank->is_mpuio) {
omap_mpuio_alloc_gc(bank, irq, bank->width);
irq_set_chip_and_handler(irq, NULL, NULL);
@@ -1217,9 +1216,9 @@ static int omap_gpio_probe(struct platform_device *pdev)
}
if (bank->regs->set_dataout && bank->regs->clr_dataout)
- bank->set_dataout = _set_gpio_dataout_reg;
+ bank->set_dataout = omap_set_gpio_dataout_reg;
else
- bank->set_dataout = _set_gpio_dataout_mask;
+ bank->set_dataout = omap_set_gpio_dataout_mask;
spin_lock_init(&bank->lock);
@@ -1238,7 +1237,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
pm_runtime_get_sync(bank->dev);
if (bank->is_mpuio)
- mpuio_init(bank);
+ omap_mpuio_init(bank);
omap_gpio_mod_init(bank);
@@ -1320,7 +1319,7 @@ update_gpio_context_count:
bank->context_loss_count =
bank->get_context_loss_count(bank->dev);
- _gpio_dbck_disable(bank);
+ omap_gpio_dbck_disable(bank);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
@@ -1351,7 +1350,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
bank->get_context_loss_count(bank->dev);
}
- _gpio_dbck_enable(bank);
+ omap_gpio_dbck_enable(bank);
/*
* In ->runtime_suspend(), level-triggered, wakeup-enabled
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index 86bdbe362068..171a6389f9ce 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -210,7 +210,8 @@ static int palmas_gpio_remove(struct platform_device *pdev)
{
struct palmas_gpio *palmas_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&palmas_gpio->gpio_chip);
+ gpiochip_remove(&palmas_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver palmas_gpio_driver = {
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index e721a37c3473..f9961eea2120 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -765,12 +765,7 @@ static int pca953x_remove(struct i2c_client *client)
}
}
- ret = gpiochip_remove(&chip->gpio_chip);
- if (ret) {
- dev_err(&client->dev, "%s failed, %d\n",
- "gpiochip_remove()", ret);
- return ret;
- }
+ gpiochip_remove(&chip->gpio_chip);
return 0;
}
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 27b46751ea7e..236708ad0a5b 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -444,9 +444,7 @@ static int pcf857x_remove(struct i2c_client *client)
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
- status = gpiochip_remove(&gpio->chip);
- if (status)
- dev_err(&client->dev, "%s --> %d\n", "remove", status);
+ gpiochip_remove(&gpio->chip);
return status;
}
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index d6eac9b17db9..e0ac549dccb5 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -426,9 +426,7 @@ end:
err_request_irq:
irq_free_descs(irq_base, gpio_pins[chip->ioh]);
-
- if (gpiochip_remove(&chip->gpio))
- dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+ gpiochip_remove(&chip->gpio);
err_gpiochip_add:
pci_iounmap(pdev, chip->base);
@@ -447,7 +445,6 @@ err_pci_enable:
static void pch_gpio_remove(struct pci_dev *pdev)
{
- int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
if (chip->irq_base != -1) {
@@ -456,10 +453,7 @@ static void pch_gpio_remove(struct pci_dev *pdev)
irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
}
- err = gpiochip_remove(&chip->gpio);
- if (err)
- dev_err(&pdev->dev, "Failed gpiochip_remove\n");
-
+ gpiochip_remove(&chip->gpio);
pci_iounmap(pdev, chip->base);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 42e6e64f2120..ad3feec0075e 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -498,7 +498,7 @@ static int pxa_gpio_nums(struct platform_device *pdev)
}
#ifdef CONFIG_OF
-static struct of_device_id pxa_gpio_dt_ids[] = {
+static const struct of_device_id pxa_gpio_dt_ids[] = {
{ .compatible = "intel,pxa25x-gpio", .data = &pxa25x_id, },
{ .compatible = "intel,pxa26x-gpio", .data = &pxa26x_id, },
{ .compatible = "intel,pxa27x-gpio", .data = &pxa27x_id, },
@@ -649,6 +649,11 @@ static int pxa_gpio_probe(struct platform_device *pdev)
handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
+ } else {
+ if (irq0 > 0)
+ irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
+ if (irq1 > 0)
+ irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
}
irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 562b0c4d9cc8..769233d2da6d 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -148,7 +148,8 @@ static int rc5t583_gpio_remove(struct platform_device *pdev)
{
struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&rc5t583_gpio->gpio_chip);
+ gpiochip_remove(&rc5t583_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver rc5t583_gpio_driver = {
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index b6ae89ea8811..bf6c09450fee 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -240,9 +240,9 @@ static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
/* testing on r8a7790 shows that INDT does not show correct pin state
* when configured as output, so use OUTDT in case of output pins */
if (gpio_rcar_read(gpio_to_priv(chip), INOUTSEL) & bit)
- return (int)(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
+ return !!(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
else
- return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
+ return !!(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
}
static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -472,11 +472,8 @@ err0:
static int gpio_rcar_remove(struct platform_device *pdev)
{
struct gpio_rcar_priv *p = platform_get_drvdata(pdev);
- int ret;
- ret = gpiochip_remove(&p->gpio_chip);
- if (ret)
- return ret;
+ gpiochip_remove(&p->gpio_chip);
irq_domain_remove(p->irq_domain);
pm_runtime_put(&pdev->dev);
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index 9fa7e53331c9..d729bc8a554d 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -199,14 +199,11 @@ static int rdc321x_gpio_probe(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);
- ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
- if (ret)
- dev_err(&pdev->dev, "failed to unregister chip\n");
+ gpiochip_remove(&rdc321x_gpio_dev->chip);
- return ret;
+ return 0;
}
static struct platform_driver rdc321x_gpio_driver = {
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 07105ee5c9ae..3810da47043f 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -32,10 +32,7 @@
#include <mach/map.h>
#include <mach/regs-gpio.h>
-
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
#include <mach/gpio-samsung.h>
-#endif
#include <plat/cpu.h>
#include <plat/gpio-core.h>
@@ -358,47 +355,6 @@ static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
}
#endif
-#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
-static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
- unsigned int off, unsigned int cfg)
-{
- void __iomem *reg = chip->base;
- unsigned int shift;
- u32 con;
-
- switch (off) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- shift = (off & 7) * 4;
- reg -= 4;
- break;
- case 6:
- shift = ((off + 1) & 7) * 4;
- reg -= 4;
- break;
- default:
- shift = ((off + 1) & 7) * 4;
- break;
- }
-
- if (samsung_gpio_is_cfg_special(cfg)) {
- cfg &= 0xf;
- cfg <<= shift;
- }
-
- con = __raw_readl(reg);
- con &= ~(0xf << shift);
- con |= cfg;
- __raw_writel(con, reg);
-
- return 0;
-}
-#endif
-
static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
int nr_chips)
{
@@ -426,16 +382,6 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
};
#endif
-#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
-static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
- .cfg_eint = 0x3,
- .set_config = s5p64x0_gpio_setcfg_rbank,
- .get_config = samsung_gpio_getcfg_4bit,
- .set_pull = samsung_gpio_setpull_updown,
- .get_pull = samsung_gpio_getpull_updown,
-};
-#endif
-
static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
[0] = {
.cfg_eint = 0x0,
@@ -708,91 +654,6 @@ static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
}
#endif
-/* The next set of routines are for the case of s5p64x0 bank r */
-
-static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
- unsigned int offset)
-{
- struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
- void __iomem *base = ourchip->base;
- void __iomem *regcon = base;
- unsigned long con;
- unsigned long flags;
-
- switch (offset) {
- case 6:
- offset += 1;
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- regcon -= 4;
- break;
- default:
- offset -= 7;
- break;
- }
-
- samsung_gpio_lock(ourchip, flags);
-
- con = __raw_readl(regcon);
- con &= ~(0xf << con_4bit_shift(offset));
- __raw_writel(con, regcon);
-
- samsung_gpio_unlock(ourchip, flags);
-
- return 0;
-}
-
-static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
- unsigned int offset, int value)
-{
- struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
- void __iomem *base = ourchip->base;
- void __iomem *regcon = base;
- unsigned long con;
- unsigned long dat;
- unsigned long flags;
- unsigned con_offset = offset;
-
- switch (con_offset) {
- case 6:
- con_offset += 1;
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- regcon -= 4;
- break;
- default:
- con_offset -= 7;
- break;
- }
-
- samsung_gpio_lock(ourchip, flags);
-
- con = __raw_readl(regcon);
- con &= ~(0xf << con_4bit_shift(con_offset));
- con |= 0x1 << con_4bit_shift(con_offset);
-
- dat = __raw_readl(base + GPIODAT_OFF);
- if (value)
- dat |= 1 << offset;
- else
- dat &= ~(1 << offset);
-
- __raw_writel(con, regcon);
- __raw_writel(dat, base + GPIODAT_OFF);
-
- samsung_gpio_unlock(ourchip, flags);
-
- return 0;
-}
-
static void samsung_gpiolib_set(struct gpio_chip *chip,
unsigned offset, int value)
{
@@ -999,20 +860,6 @@ static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chi
}
}
-static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
- int nr_chips)
-{
- for (; nr_chips > 0; nr_chips--, chip++) {
- chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
- chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
-
- if (!chip->pm)
- chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
-
- samsung_gpiolib_add(chip);
- }
-}
-
int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
@@ -1319,773 +1166,9 @@ static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
#endif
};
-/*
- * S5P6440 GPIO bank summary:
- *
- * Bank GPIOs Style SlpCon ExtInt Group
- * A 6 4Bit Yes 1
- * B 7 4Bit Yes 1
- * C 8 4Bit Yes 2
- * F 2 2Bit Yes 4 [1]
- * G 7 4Bit Yes 5
- * H 10 4Bit[2] Yes 6
- * I 16 2Bit Yes None
- * J 12 2Bit Yes None
- * N 16 2Bit No IRQ_EINT
- * P 8 2Bit Yes 8
- * R 15 4Bit[2] Yes 8
- */
-
-static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5P6440
- {
- .chip = {
- .base = S5P6440_GPA(0),
- .ngpio = S5P6440_GPIO_A_NR,
- .label = "GPA",
- },
- }, {
- .chip = {
- .base = S5P6440_GPB(0),
- .ngpio = S5P6440_GPIO_B_NR,
- .label = "GPB",
- },
- }, {
- .chip = {
- .base = S5P6440_GPC(0),
- .ngpio = S5P6440_GPIO_C_NR,
- .label = "GPC",
- },
- }, {
- .base = S5P64X0_GPG_BASE,
- .chip = {
- .base = S5P6440_GPG(0),
- .ngpio = S5P6440_GPIO_G_NR,
- .label = "GPG",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
-#ifdef CONFIG_CPU_S5P6440
- {
- .base = S5P64X0_GPH_BASE + 0x4,
- .chip = {
- .base = S5P6440_GPH(0),
- .ngpio = S5P6440_GPIO_H_NR,
- .label = "GPH",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
-#ifdef CONFIG_CPU_S5P6440
- {
- .base = S5P64X0_GPR_BASE + 0x4,
- .config = &s5p64x0_gpio_cfg_rbank,
- .chip = {
- .base = S5P6440_GPR(0),
- .ngpio = S5P6440_GPIO_R_NR,
- .label = "GPR",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
-#ifdef CONFIG_CPU_S5P6440
- {
- .base = S5P64X0_GPF_BASE,
- .config = &samsung_gpio_cfgs[6],
- .chip = {
- .base = S5P6440_GPF(0),
- .ngpio = S5P6440_GPIO_F_NR,
- .label = "GPF",
- },
- }, {
- .base = S5P64X0_GPI_BASE,
- .config = &samsung_gpio_cfgs[4],
- .chip = {
- .base = S5P6440_GPI(0),
- .ngpio = S5P6440_GPIO_I_NR,
- .label = "GPI",
- },
- }, {
- .base = S5P64X0_GPJ_BASE,
- .config = &samsung_gpio_cfgs[4],
- .chip = {
- .base = S5P6440_GPJ(0),
- .ngpio = S5P6440_GPIO_J_NR,
- .label = "GPJ",
- },
- }, {
- .base = S5P64X0_GPN_BASE,
- .config = &samsung_gpio_cfgs[5],
- .chip = {
- .base = S5P6440_GPN(0),
- .ngpio = S5P6440_GPIO_N_NR,
- .label = "GPN",
- },
- }, {
- .base = S5P64X0_GPP_BASE,
- .config = &samsung_gpio_cfgs[6],
- .chip = {
- .base = S5P6440_GPP(0),
- .ngpio = S5P6440_GPIO_P_NR,
- .label = "GPP",
- },
- },
-#endif
-};
-
-/*
- * S5P6450 GPIO bank summary:
- *
- * Bank GPIOs Style SlpCon ExtInt Group
- * A 6 4Bit Yes 1
- * B 7 4Bit Yes 1
- * C 8 4Bit Yes 2
- * D 8 4Bit Yes None
- * F 2 2Bit Yes None
- * G 14 4Bit[2] Yes 5
- * H 10 4Bit[2] Yes 6
- * I 16 2Bit Yes None
- * J 12 2Bit Yes None
- * K 5 4Bit Yes None
- * N 16 2Bit No IRQ_EINT
- * P 11 2Bit Yes 8
- * Q 14 2Bit Yes None
- * R 15 4Bit[2] Yes None
- * S 8 2Bit Yes None
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5P6450
- {
- .chip = {
- .base = S5P6450_GPA(0),
- .ngpio = S5P6450_GPIO_A_NR,
- .label = "GPA",
- },
- }, {
- .chip = {
- .base = S5P6450_GPB(0),
- .ngpio = S5P6450_GPIO_B_NR,
- .label = "GPB",
- },
- }, {
- .chip = {
- .base = S5P6450_GPC(0),
- .ngpio = S5P6450_GPIO_C_NR,
- .label = "GPC",
- },
- }, {
- .chip = {
- .base = S5P6450_GPD(0),
- .ngpio = S5P6450_GPIO_D_NR,
- .label = "GPD",
- },
- }, {
- .base = S5P6450_GPK_BASE,
- .chip = {
- .base = S5P6450_GPK(0),
- .ngpio = S5P6450_GPIO_K_NR,
- .label = "GPK",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
-#ifdef CONFIG_CPU_S5P6450
- {
- .base = S5P64X0_GPG_BASE + 0x4,
- .chip = {
- .base = S5P6450_GPG(0),
- .ngpio = S5P6450_GPIO_G_NR,
- .label = "GPG",
- },
- }, {
- .base = S5P64X0_GPH_BASE + 0x4,
- .chip = {
- .base = S5P6450_GPH(0),
- .ngpio = S5P6450_GPIO_H_NR,
- .label = "GPH",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
-#ifdef CONFIG_CPU_S5P6450
- {
- .base = S5P64X0_GPR_BASE + 0x4,
- .config = &s5p64x0_gpio_cfg_rbank,
- .chip = {
- .base = S5P6450_GPR(0),
- .ngpio = S5P6450_GPIO_R_NR,
- .label = "GPR",
- },
- },
-#endif
-};
-
-static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
-#ifdef CONFIG_CPU_S5P6450
- {
- .base = S5P64X0_GPF_BASE,
- .config = &samsung_gpio_cfgs[6],
- .chip = {
- .base = S5P6450_GPF(0),
- .ngpio = S5P6450_GPIO_F_NR,
- .label = "GPF",
- },
- }, {
- .base = S5P64X0_GPI_BASE,
- .config = &samsung_gpio_cfgs[4],
- .chip = {
- .base = S5P6450_GPI(0),
- .ngpio = S5P6450_GPIO_I_NR,
- .label = "GPI",
- },
- }, {
- .base = S5P64X0_GPJ_BASE,
- .config = &samsung_gpio_cfgs[4],
- .chip = {
- .base = S5P6450_GPJ(0),
- .ngpio = S5P6450_GPIO_J_NR,
- .label = "GPJ",
- },
- }, {
- .base = S5P64X0_GPN_BASE,
- .config = &samsung_gpio_cfgs[5],
- .chip = {
- .base = S5P6450_GPN(0),
- .ngpio = S5P6450_GPIO_N_NR,
- .label = "GPN",
- },
- }, {
- .base = S5P64X0_GPP_BASE,
- .config = &samsung_gpio_cfgs[6],
- .chip = {
- .base = S5P6450_GPP(0),
- .ngpio = S5P6450_GPIO_P_NR,
- .label = "GPP",
- },
- }, {
- .base = S5P6450_GPQ_BASE,
- .config = &samsung_gpio_cfgs[5],
- .chip = {
- .base = S5P6450_GPQ(0),
- .ngpio = S5P6450_GPIO_Q_NR,
- .label = "GPQ",
- },
- }, {
- .base = S5P6450_GPS_BASE,
- .config = &samsung_gpio_cfgs[6],
- .chip = {
- .base = S5P6450_GPS(0),
- .ngpio = S5P6450_GPIO_S_NR,
- .label = "GPS",
- },
- },
-#endif
-};
-
-/*
- * S5PC100 GPIO bank summary:
- *
- * Bank GPIOs Style INT Type
- * A0 8 4Bit GPIO_INT0
- * A1 5 4Bit GPIO_INT1
- * B 8 4Bit GPIO_INT2
- * C 5 4Bit GPIO_INT3
- * D 7 4Bit GPIO_INT4
- * E0 8 4Bit GPIO_INT5
- * E1 6 4Bit GPIO_INT6
- * F0 8 4Bit GPIO_INT7
- * F1 8 4Bit GPIO_INT8
- * F2 8 4Bit GPIO_INT9
- * F3 4 4Bit GPIO_INT10
- * G0 8 4Bit GPIO_INT11
- * G1 3 4Bit GPIO_INT12
- * G2 7 4Bit GPIO_INT13
- * G3 7 4Bit GPIO_INT14
- * H0 8 4Bit WKUP_INT
- * H1 8 4Bit WKUP_INT
- * H2 8 4Bit WKUP_INT
- * H3 8 4Bit WKUP_INT
- * I 8 4Bit GPIO_INT15
- * J0 8 4Bit GPIO_INT16
- * J1 5 4Bit GPIO_INT17
- * J2 8 4Bit GPIO_INT18
- * J3 8 4Bit GPIO_INT19
- * J4 4 4Bit GPIO_INT20
- * K0 8 4Bit None
- * K1 6 4Bit None
- * K2 8 4Bit None
- * K3 8 4Bit None
- * L0 8 4Bit None
- * L1 8 4Bit None
- * L2 8 4Bit None
- * L3 8 4Bit None
- */
-
-static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5PC100
- {
- .chip = {
- .base = S5PC100_GPA0(0),
- .ngpio = S5PC100_GPIO_A0_NR,
- .label = "GPA0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPA1(0),
- .ngpio = S5PC100_GPIO_A1_NR,
- .label = "GPA1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPB(0),
- .ngpio = S5PC100_GPIO_B_NR,
- .label = "GPB",
- },
- }, {
- .chip = {
- .base = S5PC100_GPC(0),
- .ngpio = S5PC100_GPIO_C_NR,
- .label = "GPC",
- },
- }, {
- .chip = {
- .base = S5PC100_GPD(0),
- .ngpio = S5PC100_GPIO_D_NR,
- .label = "GPD",
- },
- }, {
- .chip = {
- .base = S5PC100_GPE0(0),
- .ngpio = S5PC100_GPIO_E0_NR,
- .label = "GPE0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPE1(0),
- .ngpio = S5PC100_GPIO_E1_NR,
- .label = "GPE1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPF0(0),
- .ngpio = S5PC100_GPIO_F0_NR,
- .label = "GPF0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPF1(0),
- .ngpio = S5PC100_GPIO_F1_NR,
- .label = "GPF1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPF2(0),
- .ngpio = S5PC100_GPIO_F2_NR,
- .label = "GPF2",
- },
- }, {
- .chip = {
- .base = S5PC100_GPF3(0),
- .ngpio = S5PC100_GPIO_F3_NR,
- .label = "GPF3",
- },
- }, {
- .chip = {
- .base = S5PC100_GPG0(0),
- .ngpio = S5PC100_GPIO_G0_NR,
- .label = "GPG0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPG1(0),
- .ngpio = S5PC100_GPIO_G1_NR,
- .label = "GPG1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPG2(0),
- .ngpio = S5PC100_GPIO_G2_NR,
- .label = "GPG2",
- },
- }, {
- .chip = {
- .base = S5PC100_GPG3(0),
- .ngpio = S5PC100_GPIO_G3_NR,
- .label = "GPG3",
- },
- }, {
- .chip = {
- .base = S5PC100_GPI(0),
- .ngpio = S5PC100_GPIO_I_NR,
- .label = "GPI",
- },
- }, {
- .chip = {
- .base = S5PC100_GPJ0(0),
- .ngpio = S5PC100_GPIO_J0_NR,
- .label = "GPJ0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPJ1(0),
- .ngpio = S5PC100_GPIO_J1_NR,
- .label = "GPJ1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPJ2(0),
- .ngpio = S5PC100_GPIO_J2_NR,
- .label = "GPJ2",
- },
- }, {
- .chip = {
- .base = S5PC100_GPJ3(0),
- .ngpio = S5PC100_GPIO_J3_NR,
- .label = "GPJ3",
- },
- }, {
- .chip = {
- .base = S5PC100_GPJ4(0),
- .ngpio = S5PC100_GPIO_J4_NR,
- .label = "GPJ4",
- },
- }, {
- .chip = {
- .base = S5PC100_GPK0(0),
- .ngpio = S5PC100_GPIO_K0_NR,
- .label = "GPK0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPK1(0),
- .ngpio = S5PC100_GPIO_K1_NR,
- .label = "GPK1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPK2(0),
- .ngpio = S5PC100_GPIO_K2_NR,
- .label = "GPK2",
- },
- }, {
- .chip = {
- .base = S5PC100_GPK3(0),
- .ngpio = S5PC100_GPIO_K3_NR,
- .label = "GPK3",
- },
- }, {
- .chip = {
- .base = S5PC100_GPL0(0),
- .ngpio = S5PC100_GPIO_L0_NR,
- .label = "GPL0",
- },
- }, {
- .chip = {
- .base = S5PC100_GPL1(0),
- .ngpio = S5PC100_GPIO_L1_NR,
- .label = "GPL1",
- },
- }, {
- .chip = {
- .base = S5PC100_GPL2(0),
- .ngpio = S5PC100_GPIO_L2_NR,
- .label = "GPL2",
- },
- }, {
- .chip = {
- .base = S5PC100_GPL3(0),
- .ngpio = S5PC100_GPIO_L3_NR,
- .label = "GPL3",
- },
- }, {
- .chip = {
- .base = S5PC100_GPL4(0),
- .ngpio = S5PC100_GPIO_L4_NR,
- .label = "GPL4",
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC00),
- .irq_base = IRQ_EINT(0),
- .chip = {
- .base = S5PC100_GPH0(0),
- .ngpio = S5PC100_GPIO_H0_NR,
- .label = "GPH0",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC20),
- .irq_base = IRQ_EINT(8),
- .chip = {
- .base = S5PC100_GPH1(0),
- .ngpio = S5PC100_GPIO_H1_NR,
- .label = "GPH1",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC40),
- .irq_base = IRQ_EINT(16),
- .chip = {
- .base = S5PC100_GPH2(0),
- .ngpio = S5PC100_GPIO_H2_NR,
- .label = "GPH2",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC60),
- .irq_base = IRQ_EINT(24),
- .chip = {
- .base = S5PC100_GPH3(0),
- .ngpio = S5PC100_GPIO_H3_NR,
- .label = "GPH3",
- .to_irq = samsung_gpiolib_to_irq,
- },
- },
-#endif
-};
-
-/*
- * Followings are the gpio banks in S5PV210/S5PC110
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure samsung_gpio_cfgs[3] in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of samsung_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-
-static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5PV210
- {
- .chip = {
- .base = S5PV210_GPA0(0),
- .ngpio = S5PV210_GPIO_A0_NR,
- .label = "GPA0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPA1(0),
- .ngpio = S5PV210_GPIO_A1_NR,
- .label = "GPA1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPB(0),
- .ngpio = S5PV210_GPIO_B_NR,
- .label = "GPB",
- },
- }, {
- .chip = {
- .base = S5PV210_GPC0(0),
- .ngpio = S5PV210_GPIO_C0_NR,
- .label = "GPC0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPC1(0),
- .ngpio = S5PV210_GPIO_C1_NR,
- .label = "GPC1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPD0(0),
- .ngpio = S5PV210_GPIO_D0_NR,
- .label = "GPD0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPD1(0),
- .ngpio = S5PV210_GPIO_D1_NR,
- .label = "GPD1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPE0(0),
- .ngpio = S5PV210_GPIO_E0_NR,
- .label = "GPE0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPE1(0),
- .ngpio = S5PV210_GPIO_E1_NR,
- .label = "GPE1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF0(0),
- .ngpio = S5PV210_GPIO_F0_NR,
- .label = "GPF0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF1(0),
- .ngpio = S5PV210_GPIO_F1_NR,
- .label = "GPF1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF2(0),
- .ngpio = S5PV210_GPIO_F2_NR,
- .label = "GPF2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF3(0),
- .ngpio = S5PV210_GPIO_F3_NR,
- .label = "GPF3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG0(0),
- .ngpio = S5PV210_GPIO_G0_NR,
- .label = "GPG0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG1(0),
- .ngpio = S5PV210_GPIO_G1_NR,
- .label = "GPG1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG2(0),
- .ngpio = S5PV210_GPIO_G2_NR,
- .label = "GPG2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG3(0),
- .ngpio = S5PV210_GPIO_G3_NR,
- .label = "GPG3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPI(0),
- .ngpio = S5PV210_GPIO_I_NR,
- .label = "GPI",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ0(0),
- .ngpio = S5PV210_GPIO_J0_NR,
- .label = "GPJ0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ1(0),
- .ngpio = S5PV210_GPIO_J1_NR,
- .label = "GPJ1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ2(0),
- .ngpio = S5PV210_GPIO_J2_NR,
- .label = "GPJ2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ3(0),
- .ngpio = S5PV210_GPIO_J3_NR,
- .label = "GPJ3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ4(0),
- .ngpio = S5PV210_GPIO_J4_NR,
- .label = "GPJ4",
- },
- }, {
- .chip = {
- .base = S5PV210_MP01(0),
- .ngpio = S5PV210_GPIO_MP01_NR,
- .label = "MP01",
- },
- }, {
- .chip = {
- .base = S5PV210_MP02(0),
- .ngpio = S5PV210_GPIO_MP02_NR,
- .label = "MP02",
- },
- }, {
- .chip = {
- .base = S5PV210_MP03(0),
- .ngpio = S5PV210_GPIO_MP03_NR,
- .label = "MP03",
- },
- }, {
- .chip = {
- .base = S5PV210_MP04(0),
- .ngpio = S5PV210_GPIO_MP04_NR,
- .label = "MP04",
- },
- }, {
- .chip = {
- .base = S5PV210_MP05(0),
- .ngpio = S5PV210_GPIO_MP05_NR,
- .label = "MP05",
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC00),
- .irq_base = IRQ_EINT(0),
- .chip = {
- .base = S5PV210_GPH0(0),
- .ngpio = S5PV210_GPIO_H0_NR,
- .label = "GPH0",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC20),
- .irq_base = IRQ_EINT(8),
- .chip = {
- .base = S5PV210_GPH1(0),
- .ngpio = S5PV210_GPIO_H1_NR,
- .label = "GPH1",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC40),
- .irq_base = IRQ_EINT(16),
- .chip = {
- .base = S5PV210_GPH2(0),
- .ngpio = S5PV210_GPIO_H2_NR,
- .label = "GPH2",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC60),
- .irq_base = IRQ_EINT(24),
- .chip = {
- .base = S5PV210_GPH3(0),
- .ngpio = S5PV210_GPIO_H3_NR,
- .label = "GPH3",
- .to_irq = samsung_gpiolib_to_irq,
- },
- },
-#endif
-};
-
/* TODO: cleanup soc_is_* */
static __init int samsung_gpiolib_init(void)
{
- struct samsung_gpio_chip *chip;
- int i, nr_chips;
- int group = 0;
-
/*
* Currently there are two drivers that can provide GPIO support for
* Samsung SoCs. For device tree enabled platforms, the new
@@ -2109,54 +1192,6 @@ static __init int samsung_gpiolib_init(void)
S3C64XX_VA_GPIO);
samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
ARRAY_SIZE(s3c64xx_gpios_4bit2));
- } else if (soc_is_s5p6440()) {
- samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
- ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
- samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
- ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
- samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
- ARRAY_SIZE(s5p6440_gpios_4bit2));
- s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
- ARRAY_SIZE(s5p6440_gpios_rbank));
- } else if (soc_is_s5p6450()) {
- samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
- ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
- samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
- ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
- samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
- ARRAY_SIZE(s5p6450_gpios_4bit2));
- s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
- ARRAY_SIZE(s5p6450_gpios_rbank));
- } else if (soc_is_s5pc100()) {
- group = 0;
- chip = s5pc100_gpios_4bit;
- nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
-
- for (i = 0; i < nr_chips; i++, chip++) {
- if (!chip->config) {
- chip->config = &samsung_gpio_cfgs[3];
- chip->group = group++;
- }
- }
- samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
-#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
- s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-#endif
- } else if (soc_is_s5pv210()) {
- group = 0;
- chip = s5pv210_gpios_4bit;
- nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
-
- for (i = 0; i < nr_chips; i++, chip++) {
- if (!chip->config) {
- chip->config = &samsung_gpio_cfgs[3];
- chip->group = group++;
- }
- }
- samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
-#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
- s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-#endif
} else {
WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
return -ENODEV;
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index a9b1cd16c848..41e91d70301e 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -290,8 +290,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
return 0;
err_sch_gpio_resume:
- if (gpiochip_remove(&sch_gpio_core))
- dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+ gpiochip_remove(&sch_gpio_core);
err_sch_gpio_core:
release_region(res->start, resource_size(res));
@@ -304,23 +303,14 @@ static int sch_gpio_remove(struct platform_device *pdev)
{
struct resource *res;
if (gpio_ba) {
- int err;
- err = gpiochip_remove(&sch_gpio_core);
- if (err)
- dev_err(&pdev->dev, "%s failed, %d\n",
- "gpiochip_remove()", err);
- err = gpiochip_remove(&sch_gpio_resume);
- if (err)
- dev_err(&pdev->dev, "%s failed, %d\n",
- "gpiochip_remove()", err);
+ gpiochip_remove(&sch_gpio_core);
+ gpiochip_remove(&sch_gpio_resume);
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(res->start, resource_size(res));
gpio_ba = 0;
-
- return err;
}
return 0;
diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c
index f942b80ee403..0cb11413e814 100644
--- a/drivers/gpio/gpio-sch311x.c
+++ b/drivers/gpio/gpio-sch311x.c
@@ -291,14 +291,12 @@ static int sch311x_gpio_remove(struct platform_device *pdev)
{
struct sch311x_pdev_data *pdata = pdev->dev.platform_data;
struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
- int err, i;
+ int i;
release_region(pdata->runtime_reg + GP1, 6);
for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
- err = gpiochip_remove(&priv->blocks[i].chip);
- if (err)
- return err;
+ gpiochip_remove(&priv->blocks[i].chip);
dev_info(&pdev->dev,
"SMSC SCH311x GPIO block %d unregistered.\n", i);
}
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 7c6c518929bc..d8da36cd8123 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -265,9 +265,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
free_irq(pdev->irq, sd);
irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
- if (gpiochip_remove(&sd->bgpio.gc))
- dev_err(&pdev->dev, "gpiochip_remove() failed.\n");
-
+ gpiochip_remove(&sd->bgpio.gc);
pci_release_region(pdev, GPIO_BAR);
iounmap(sd->gpio_pub_base);
pci_disable_device(pdev);
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 628b58494294..845025a57240 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -10,8 +10,6 @@
#include <linux/platform_device.h>
#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>
@@ -31,9 +29,7 @@ struct stmpe_gpio {
struct stmpe *stmpe;
struct device *dev;
struct mutex irq_lock;
- struct irq_domain *domain;
unsigned norequest_mask;
-
/* Caches of interrupt control registers for bus_lock */
u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -101,13 +97,6 @@ static int stmpe_gpio_direction_input(struct gpio_chip *chip,
return stmpe_set_bits(stmpe, reg, mask, 0);
}
-static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
-
- return irq_create_mapping(stmpe_gpio->domain, offset);
-}
-
static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
{
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
@@ -126,14 +115,14 @@ static struct gpio_chip template_chip = {
.get = stmpe_gpio_get,
.direction_output = stmpe_gpio_direction_output,
.set = stmpe_gpio_set,
- .to_irq = stmpe_gpio_to_irq,
.request = stmpe_gpio_request,
.can_sleep = true,
};
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);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -160,14 +149,16 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static void stmpe_gpio_irq_lock(struct irq_data *d)
{
- struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
mutex_lock(&stmpe_gpio->irq_lock);
}
static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
{
- struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
struct stmpe *stmpe = stmpe_gpio->stmpe;
int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
static const u8 regmap[] = {
@@ -200,7 +191,8 @@ 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);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -210,7 +202,8 @@ 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);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -253,7 +246,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = bank * 8 + bit;
- int child_irq = irq_find_mapping(stmpe_gpio->domain,
+ int child_irq = irq_find_mapping(stmpe_gpio->chip.irqdomain,
line);
handle_nested_irq(child_irq);
@@ -271,56 +264,6 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- struct stmpe_gpio *stmpe_gpio = d->host_data;
-
- if (!stmpe_gpio)
- return -EINVAL;
-
- 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);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
-
- return 0;
-}
-
-static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
-#ifdef CONFIG_ARM
- set_irq_flags(irq, 0);
-#endif
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, 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,
- struct device_node *np)
-{
- stmpe_gpio->domain = irq_domain_add_simple(np,
- stmpe_gpio->chip.ngpio, 0,
- &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 stmpe_gpio_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
@@ -358,30 +301,37 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
if (irq < 0)
dev_info(&pdev->dev,
- "device configured in no-irq mode; "
+ "device configured in no-irq mode: "
"irqs are not available\n");
ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
if (ret)
goto out_free;
- if (irq >= 0) {
- ret = stmpe_gpio_irq_init(stmpe_gpio, np);
- if (ret)
- goto out_disable;
-
- ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq,
- IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
+ if (irq > 0) {
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ stmpe_gpio_irq, IRQF_ONESHOT,
+ "stmpe-gpio", stmpe_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_disable;
}
+ ret = gpiochip_irqchip_add(&stmpe_gpio->chip,
+ &stmpe_gpio_irq_chip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "could not connect irqchip to gpiochip\n");
+ return ret;
+ }
}
ret = gpiochip_add(&stmpe_gpio->chip);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
- goto out_freeirq;
+ goto out_disable;
}
if (pdata && pdata->setup)
@@ -391,9 +341,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
return 0;
-out_freeirq:
- if (irq >= 0)
- free_irq(irq, stmpe_gpio);
out_disable:
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
out_free:
@@ -406,24 +353,14 @@ static int stmpe_gpio_remove(struct platform_device *pdev)
struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
struct stmpe *stmpe = stmpe_gpio->stmpe;
struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
- int irq = platform_get_irq(pdev, 0);
- int ret;
if (pdata && pdata->remove)
pdata->remove(stmpe, stmpe_gpio->chip.base);
- ret = gpiochip_remove(&stmpe_gpio->chip);
- if (ret < 0) {
- dev_err(stmpe_gpio->dev,
- "unable to remove gpiochip: %d\n", ret);
- return ret;
- }
+ gpiochip_remove(&stmpe_gpio->chip);
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
- if (irq >= 0)
- free_irq(irq, stmpe_gpio);
-
kfree(stmpe_gpio);
return 0;
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index b51ca9f5c140..bce6c6108f20 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -615,19 +615,16 @@ static int sx150x_probe(struct i2c_client *client,
return 0;
probe_fail_post_gpiochip_add:
- WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
+ gpiochip_remove(&chip->gpio_chip);
return rc;
}
static int sx150x_remove(struct i2c_client *client)
{
struct sx150x_chip *chip;
- int rc;
chip = i2c_get_clientdata(client);
- rc = gpiochip_remove(&chip->gpio_chip);
- if (rc < 0)
- return rc;
+ gpiochip_remove(&chip->gpio_chip);
if (chip->irq_summary >= 0)
sx150x_remove_irq_chip(chip);
diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c
index b50fe1297748..30884fbc750d 100644
--- a/drivers/gpio/gpio-syscon.c
+++ b/drivers/gpio/gpio-syscon.c
@@ -172,7 +172,8 @@ static int syscon_gpio_remove(struct platform_device *pdev)
{
struct syscon_gpio_priv *priv = platform_get_drvdata(pdev);
- return gpiochip_remove(&priv->chip);
+ gpiochip_remove(&priv->chip);
+ return 0;
}
static struct platform_driver syscon_gpio_driver = {
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
index 07bce97647a6..9e615be8032c 100644
--- a/drivers/gpio/gpio-tb10x.c
+++ b/drivers/gpio/gpio-tb10x.c
@@ -291,7 +291,6 @@ fail_ioremap:
static int __exit tb10x_gpio_remove(struct platform_device *pdev)
{
struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
- int ret;
if (tb10x_gpio->gc.to_irq) {
irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0],
@@ -300,9 +299,7 @@ static int __exit tb10x_gpio_remove(struct platform_device *pdev)
irq_domain_remove(tb10x_gpio->domain);
free_irq(tb10x_gpio->irq, tb10x_gpio);
}
- ret = gpiochip_remove(&tb10x_gpio->gc);
- if (ret)
- return ret;
+ gpiochip_remove(&tb10x_gpio->gc);
return 0;
}
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 51f7cbd9ff71..7324869c38e0 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -313,17 +313,11 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
- int ret;
if (pdata && pdata->remove)
pdata->remove(tc3589x, tc3589x_gpio->chip.base);
- ret = gpiochip_remove(&tc3589x_gpio->chip);
- if (ret < 0) {
- dev_err(tc3589x_gpio->dev,
- "unable to remove gpiochip: %d\n", ret);
- return ret;
- }
+ gpiochip_remove(&tc3589x_gpio->chip);
return 0;
}
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index efc7c129016d..a685a3cbbc81 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -307,7 +307,6 @@ static int timbgpio_probe(struct platform_device *pdev)
static int timbgpio_remove(struct platform_device *pdev)
{
- int err;
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct timbgpio *tgpio = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
@@ -323,9 +322,7 @@ static int timbgpio_remove(struct platform_device *pdev)
irq_set_handler_data(irq, NULL);
}
- err = gpiochip_remove(&tgpio->gpio);
- if (err)
- printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
+ gpiochip_remove(&tgpio->gpio);
return 0;
}
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
index a69fbea41253..9c9238e838a9 100644
--- a/drivers/gpio/gpio-tps6586x.c
+++ b/drivers/gpio/gpio-tps6586x.c
@@ -137,7 +137,8 @@ static int tps6586x_gpio_remove(struct platform_device *pdev)
{
struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&tps6586x_gpio->gpio_chip);
+ gpiochip_remove(&tps6586x_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver tps6586x_gpio_driver = {
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index e2f8cda235ea..88f1f5ff4e96 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -190,7 +190,8 @@ static int tps65910_gpio_remove(struct platform_device *pdev)
{
struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&tps65910_gpio->gpio_chip);
+ gpiochip_remove(&tps65910_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver tps65910_gpio_driver = {
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index 59ee486cb8b9..22052d84c63b 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -117,7 +117,8 @@ static int tps65912_gpio_remove(struct platform_device *pdev)
{
struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&tps65912_gpio->gpio_chip);
+ gpiochip_remove(&tps65912_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver tps65912_gpio_driver = {
diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c
index 3df3ebdb3e52..de18591ff11e 100644
--- a/drivers/gpio/gpio-ts5500.c
+++ b/drivers/gpio/gpio-ts5500.c
@@ -427,8 +427,7 @@ static int ts5500_dio_probe(struct platform_device *pdev)
return 0;
cleanup:
- if (gpiochip_remove(&priv->gpio_chip))
- dev_err(dev, "failed to remove gpio chip\n");
+ gpiochip_remove(&priv->gpio_chip);
return ret;
}
@@ -437,7 +436,8 @@ static int 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);
+ gpiochip_remove(&priv->gpio_chip);
+ return 0;
}
static struct platform_device_id ts5500_dio_ids[] = {
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 3ebb1a5ff22e..118828b3736f 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -554,7 +554,7 @@ no_irqs:
platform_set_drvdata(pdev, priv);
- if (pdata && pdata->setup) {
+ if (pdata->setup) {
int status;
status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
@@ -583,9 +583,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
}
}
- status = gpiochip_remove(&priv->gpio_chip);
- if (status < 0)
- return status;
+ gpiochip_remove(&priv->gpio_chip);
if (is_module())
return 0;
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
index 0caf5cd1b47d..f28e04b88aa9 100644
--- a/drivers/gpio/gpio-twl6040.c
+++ b/drivers/gpio/gpio-twl6040.c
@@ -111,7 +111,8 @@ static int gpo_twl6040_probe(struct platform_device *pdev)
static int gpo_twl6040_remove(struct platform_device *pdev)
{
- return gpiochip_remove(&twl6040gpo_chip);
+ gpiochip_remove(&twl6040gpo_chip);
+ return 0;
}
/* Note: this hardware lives inside an I2C-based multi-function device. */
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c
index 2445fe771179..d502825159b9 100644
--- a/drivers/gpio/gpio-ucb1400.c
+++ b/drivers/gpio/gpio-ucb1400.c
@@ -70,7 +70,7 @@ static int ucb1400_gpio_probe(struct platform_device *dev)
if (err)
goto err;
- if (ucb && ucb->gpio_setup)
+ if (ucb->gpio_setup)
err = ucb->gpio_setup(&dev->dev, ucb->gc.ngpio);
err:
@@ -89,7 +89,7 @@ static int ucb1400_gpio_remove(struct platform_device *dev)
return err;
}
- err = gpiochip_remove(&ucb->gc);
+ gpiochip_remove(&ucb->gc);
return err;
}
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c
index 79e3b5836712..e2a11f27807f 100644
--- a/drivers/gpio/gpio-viperboard.c
+++ b/drivers/gpio/gpio-viperboard.c
@@ -446,8 +446,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
return ret;
err_gpiob:
- if (gpiochip_remove(&vb_gpio->gpioa))
- dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
+ gpiochip_remove(&vb_gpio->gpioa);
err_gpioa:
return ret;
@@ -456,13 +455,10 @@ err_gpioa:
static int vprbrd_gpio_remove(struct platform_device *pdev)
{
struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev);
- int ret;
- ret = gpiochip_remove(&vb_gpio->gpiob);
- if (ret == 0)
- ret = gpiochip_remove(&vb_gpio->gpioa);
+ gpiochip_remove(&vb_gpio->gpiob);
- return ret;
+ return 0;
}
static struct platform_driver vprbrd_gpio_driver = {
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
index 66cbcc108e62..dbf28fa03f67 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -515,7 +515,7 @@ static int giu_probe(struct platform_device *pdev)
struct resource *res;
unsigned int trigger, i, pin;
struct irq_chip *chip;
- int irq, retval;
+ int irq, ret;
switch (pdev->id) {
case GPIO_50PINS_PULLUPDOWN:
@@ -544,7 +544,11 @@ static int giu_probe(struct platform_device *pdev)
vr41xx_gpio_chip.dev = &pdev->dev;
- retval = gpiochip_add(&vr41xx_gpio_chip);
+ ret = gpiochip_add(&vr41xx_gpio_chip);
+ if (!ret) {
+ iounmap(giu_base);
+ return -ENODEV;
+ }
giu_write(GIUINTENL, 0);
giu_write(GIUINTENH, 0);
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 0fd23b6a753d..85971d4e23c1 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -288,8 +288,7 @@ static int vx855gpio_remove(struct platform_device *pdev)
struct vx855_gpio *vg = platform_get_drvdata(pdev);
struct resource *res;
- if (gpiochip_remove(&vg->gpio))
- dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
+ gpiochip_remove(&vg->gpio);
if (vg->gpi_reserved) {
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index b18a1a26425e..58ce75c188b7 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -279,7 +279,8 @@ static int wm831x_gpio_remove(struct platform_device *pdev)
{
struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&wm831x_gpio->gpio_chip);
+ gpiochip_remove(&wm831x_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver wm831x_gpio_driver = {
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index 2487f9d575d3..060b89303bb6 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -145,7 +145,8 @@ static int wm8350_gpio_remove(struct platform_device *pdev)
{
struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&wm8350_gpio->gpio_chip);
+ gpiochip_remove(&wm8350_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver wm8350_gpio_driver = {
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index d93b6b581677..6f5e42db4b9e 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -285,7 +285,8 @@ static int wm8994_gpio_remove(struct platform_device *pdev)
{
struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
- return gpiochip_remove(&wm8994_gpio->gpio_chip);
+ gpiochip_remove(&wm8994_gpio->gpio_chip);
+ return 0;
}
static struct platform_driver wm8994_gpio_driver = {
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c
new file mode 100644
index 000000000000..c3145f91fda3
--- /dev/null
+++ b/drivers/gpio/gpio-zynq.c
@@ -0,0 +1,692 @@
+/*
+ * Xilinx Zynq GPIO device driver
+ *
+ * Copyright (C) 2009 - 2014 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define DRIVER_NAME "zynq-gpio"
+
+/* Maximum banks */
+#define ZYNQ_GPIO_MAX_BANK 4
+
+#define ZYNQ_GPIO_BANK0_NGPIO 32
+#define ZYNQ_GPIO_BANK1_NGPIO 22
+#define ZYNQ_GPIO_BANK2_NGPIO 32
+#define ZYNQ_GPIO_BANK3_NGPIO 32
+
+#define ZYNQ_GPIO_NR_GPIOS (ZYNQ_GPIO_BANK0_NGPIO + \
+ ZYNQ_GPIO_BANK1_NGPIO + \
+ ZYNQ_GPIO_BANK2_NGPIO + \
+ ZYNQ_GPIO_BANK3_NGPIO)
+
+#define ZYNQ_GPIO_BANK0_PIN_MIN 0
+#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \
+ ZYNQ_GPIO_BANK0_NGPIO - 1)
+#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \
+ ZYNQ_GPIO_BANK1_NGPIO - 1)
+#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \
+ ZYNQ_GPIO_BANK2_NGPIO - 1)
+#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1)
+#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \
+ ZYNQ_GPIO_BANK3_NGPIO - 1)
+
+
+/* Register offsets for the GPIO device */
+/* LSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK))
+/* MSW Mask & Data -WO */
+#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK))
+/* Data Register-RW */
+#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK))
+/* Direction mode reg-RW */
+#define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK))
+/* Output enable reg-RW */
+#define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK))
+/* Interrupt mask reg-RO */
+#define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK))
+/* Interrupt enable reg-WO */
+#define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK))
+/* Interrupt disable reg-WO */
+#define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK))
+/* Interrupt status reg-RO */
+#define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK))
+/* Interrupt type reg-RW */
+#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK))
+/* Interrupt polarity reg-RW */
+#define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK))
+/* Interrupt on any, reg-RW */
+#define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK))
+
+/* Disable all interrupts mask */
+#define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF
+
+/* Mid pin number of a bank */
+#define ZYNQ_GPIO_MID_PIN_NUM 16
+
+/* GPIO upper 16 bit mask */
+#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
+
+/**
+ * struct zynq_gpio - gpio device private data structure
+ * @chip: instance of the gpio_chip
+ * @base_addr: base address of the GPIO device
+ * @clk: clock resource for this controller
+ */
+struct zynq_gpio {
+ struct gpio_chip chip;
+ void __iomem *base_addr;
+ struct clk *clk;
+};
+
+/**
+ * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
+ * for a given pin in the GPIO device
+ * @pin_num: gpio pin number within the device
+ * @bank_num: an output parameter used to return the bank number of the gpio
+ * pin
+ * @bank_pin_num: an output parameter used to return pin number within a bank
+ * for the given gpio pin
+ *
+ * Returns the bank number and pin offset within the bank.
+ */
+static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
+ unsigned int *bank_num,
+ unsigned int *bank_pin_num)
+{
+ switch (pin_num) {
+ case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
+ *bank_num = 0;
+ *bank_pin_num = pin_num;
+ break;
+ case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
+ *bank_num = 1;
+ *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
+ break;
+ case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
+ *bank_num = 2;
+ *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
+ break;
+ case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
+ *bank_num = 3;
+ *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
+ break;
+ default:
+ WARN(true, "invalid GPIO pin number: %u", pin_num);
+ *bank_num = 0;
+ *bank_pin_num = 0;
+ break;
+ }
+}
+
+/**
+ * zynq_gpio_get_value - Get the state of the specified pin of GPIO device
+ * @chip: gpio_chip instance to be worked on
+ * @pin: gpio pin number within the device
+ *
+ * This function reads the state of the specified pin of the GPIO device.
+ *
+ * Return: 0 if the pin is low, 1 if pin is high.
+ */
+static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
+{
+ u32 data;
+ unsigned int bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+ zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+ data = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
+
+ return (data >> bank_pin_num) & 1;
+}
+
+/**
+ * zynq_gpio_set_value - Modify the state of the pin with specified value
+ * @chip: gpio_chip instance to be worked on
+ * @pin: gpio pin number within the device
+ * @state: value used to modify the state of the specified pin
+ *
+ * This function calculates the register offset (i.e to lower 16 bits or
+ * upper 16 bits) based on the given pin number and sets the state of a
+ * gpio pin to the specified value. The state is either 0 or non-zero.
+ */
+static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
+ int state)
+{
+ unsigned int reg_offset, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+ zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+ if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
+ /* only 16 data bits in bit maskable reg */
+ bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
+ reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
+ } else {
+ reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
+ }
+
+ /*
+ * get the 32 bit value to be written to the mask/data register where
+ * the upper 16 bits is the mask and lower 16 bits is the data
+ */
+ state = !!state;
+ state = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
+ ((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
+
+ writel_relaxed(state, gpio->base_addr + reg_offset);
+}
+
+/**
+ * zynq_gpio_dir_in - Set the direction of the specified GPIO pin as input
+ * @chip: gpio_chip instance to be worked on
+ * @pin: gpio pin number within the device
+ *
+ * This function uses the read-modify-write sequence to set the direction of
+ * the gpio pin as input.
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
+{
+ u32 reg;
+ unsigned int bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+ zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+ /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
+ if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
+ return -EINVAL;
+
+ /* clear the bit in direction mode reg to set the pin as input */
+ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ reg &= ~BIT(bank_pin_num);
+ writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+ return 0;
+}
+
+/**
+ * zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output
+ * @chip: gpio_chip instance to be worked on
+ * @pin: gpio pin number within the device
+ * @state: value to be written to specified pin
+ *
+ * This function sets the direction of specified GPIO pin as output, configures
+ * the Output Enable register for the pin and uses zynq_gpio_set to set
+ * the state of the pin to the value specified.
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
+ int state)
+{
+ u32 reg;
+ unsigned int bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
+
+ zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
+
+ /* set the GPIO pin as output */
+ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+ reg |= BIT(bank_pin_num);
+ writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+
+ /* configure the output enable reg for the pin */
+ reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+ reg |= BIT(bank_pin_num);
+ writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+
+ /* set the state of the pin */
+ zynq_gpio_set_value(chip, pin, state);
+ return 0;
+}
+
+/**
+ * zynq_gpio_irq_mask - Disable the interrupts for a gpio pin
+ * @irq_data: per irq and chip data passed down to chip functions
+ *
+ * This function calculates gpio pin number from irq number and sets the
+ * bit in the Interrupt Disable register of the corresponding bank to disable
+ * interrupts for that pin.
+ */
+static void zynq_gpio_irq_mask(struct irq_data *irq_data)
+{
+ unsigned int device_pin_num, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+ device_pin_num = irq_data->hwirq;
+ zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+ writel_relaxed(BIT(bank_pin_num),
+ gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_unmask - Enable the interrupts for a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin for the interrupt
+ * to enable
+ *
+ * This function calculates the gpio pin number from irq number and sets the
+ * bit in the Interrupt Enable register of the corresponding bank to enable
+ * interrupts for that pin.
+ */
+static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
+{
+ unsigned int device_pin_num, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+ device_pin_num = irq_data->hwirq;
+ zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+ writel_relaxed(BIT(bank_pin_num),
+ gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin for the interrupt
+ * to ack
+ *
+ * This function calculates gpio pin number from irq number and sets the bit
+ * in the Interrupt Status Register of the corresponding bank, to ACK the irq.
+ */
+static void zynq_gpio_irq_ack(struct irq_data *irq_data)
+{
+ unsigned int device_pin_num, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+ device_pin_num = irq_data->hwirq;
+ zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+ writel_relaxed(BIT(bank_pin_num),
+ gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+}
+
+/**
+ * zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin for the interrupt
+ * to enable
+ *
+ * Clears the INTSTS bit and unmasks the given interrrupt.
+ */
+static void zynq_gpio_irq_enable(struct irq_data *irq_data)
+{
+ /*
+ * The Zynq GPIO controller does not disable interrupt detection when
+ * the interrupt is masked and only disables the propagation of the
+ * interrupt. This means when the controller detects an interrupt
+ * condition while the interrupt is logically disabled it will propagate
+ * that interrupt event once the interrupt is enabled. This will cause
+ * the interrupt consumer to see spurious interrupts to prevent this
+ * first make sure that the interrupt is not asserted and then enable
+ * it.
+ */
+ zynq_gpio_irq_ack(irq_data);
+ zynq_gpio_irq_unmask(irq_data);
+}
+
+/**
+ * zynq_gpio_set_irq_type - Set the irq type for a gpio pin
+ * @irq_data: irq data containing irq number of gpio pin
+ * @type: interrupt type that is to be set for the gpio pin
+ *
+ * This function gets the gpio pin number and its bank from the gpio pin number
+ * and configures the INT_TYPE, INT_POLARITY and INT_ANY registers.
+ *
+ * Return: 0, negative error otherwise.
+ * TYPE-EDGE_RISING, INT_TYPE - 1, INT_POLARITY - 1, INT_ANY - 0;
+ * TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0, INT_ANY - 0;
+ * TYPE-EDGE_BOTH, INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1;
+ * TYPE-LEVEL_HIGH, INT_TYPE - 0, INT_POLARITY - 1, INT_ANY - NA;
+ * TYPE-LEVEL_LOW, INT_TYPE - 0, INT_POLARITY - 0, INT_ANY - NA
+ */
+static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
+{
+ u32 int_type, int_pol, int_any;
+ unsigned int device_pin_num, bank_num, bank_pin_num;
+ struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
+
+ device_pin_num = irq_data->hwirq;
+ zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
+
+ int_type = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+ int_pol = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+ int_any = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+
+ /*
+ * based on the type requested, configure the INT_TYPE, INT_POLARITY
+ * and INT_ANY registers
+ */
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ int_type |= BIT(bank_pin_num);
+ int_pol |= BIT(bank_pin_num);
+ int_any &= ~BIT(bank_pin_num);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ int_type |= BIT(bank_pin_num);
+ int_pol &= ~BIT(bank_pin_num);
+ int_any &= ~BIT(bank_pin_num);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ int_type |= BIT(bank_pin_num);
+ int_any |= BIT(bank_pin_num);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ int_type &= ~BIT(bank_pin_num);
+ int_pol |= BIT(bank_pin_num);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ int_type &= ~BIT(bank_pin_num);
+ int_pol &= ~BIT(bank_pin_num);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ writel_relaxed(int_type,
+ gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
+ writel_relaxed(int_pol,
+ gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
+ writel_relaxed(int_any,
+ gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+ return 0;
+}
+
+static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
+{
+ if (on)
+ zynq_gpio_irq_unmask(data);
+ else
+ zynq_gpio_irq_mask(data);
+
+ return 0;
+}
+
+/* irq chip descriptor */
+static struct irq_chip zynq_gpio_irqchip = {
+ .name = DRIVER_NAME,
+ .irq_enable = zynq_gpio_irq_enable,
+ .irq_mask = zynq_gpio_irq_mask,
+ .irq_unmask = zynq_gpio_irq_unmask,
+ .irq_set_type = zynq_gpio_set_irq_type,
+ .irq_set_wake = zynq_gpio_set_wake,
+};
+
+/**
+ * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
+ * @irq: irq number of the gpio bank where interrupt has occurred
+ * @desc: irq descriptor instance of the 'irq'
+ *
+ * This function reads the Interrupt Status Register of each bank to get the
+ * gpio pin number which has triggered an interrupt. It then acks the triggered
+ * interrupt and calls the pin specific handler set by the higher layer
+ * application for that pin.
+ * Note: A bug is reported if no handler is set for the gpio pin.
+ */
+static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
+{
+ u32 int_sts, int_enb;
+ unsigned int bank_num;
+ struct zynq_gpio *gpio = irq_get_handler_data(irq);
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(irqchip, desc);
+
+ for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++) {
+ int_sts = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+ int_enb = readl_relaxed(gpio->base_addr +
+ ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
+ int_sts &= ~int_enb;
+ if (int_sts) {
+ int offset;
+ unsigned long pending = int_sts;
+
+ for_each_set_bit(offset, &pending, 32) {
+ unsigned int gpio_irq =
+ irq_find_mapping(gpio->chip.irqdomain,
+ offset);
+ generic_handle_irq(gpio_irq);
+ }
+
+ /* clear IRQ in HW */
+ writel_relaxed(int_sts, gpio->base_addr +
+ ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
+ }
+ }
+
+ chained_irq_exit(irqchip, desc);
+}
+
+static int __maybe_unused zynq_gpio_suspend(struct device *dev)
+{
+ if (!device_may_wakeup(dev))
+ return pm_runtime_force_suspend(dev);
+
+ return 0;
+}
+
+static int __maybe_unused zynq_gpio_resume(struct device *dev)
+{
+ if (!device_may_wakeup(dev))
+ return pm_runtime_force_resume(dev);
+
+ return 0;
+}
+
+static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(gpio->clk);
+
+ return 0;
+}
+
+static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+ return clk_prepare_enable(gpio->clk);
+}
+
+static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ int ret;
+
+ ret = pm_runtime_get_sync(chip->dev);
+
+ /*
+ * If the device is already active pm_runtime_get() will return 1 on
+ * success, but gpio_request still needs to return 0.
+ */
+ return ret < 0 ? ret : 0;
+}
+
+static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pm_runtime_put(chip->dev);
+}
+
+static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume)
+ SET_PM_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
+ zynq_gpio_runtime_resume, NULL)
+};
+
+/**
+ * zynq_gpio_probe - Initialization method for a zynq_gpio device
+ * @pdev: platform device instance
+ *
+ * This function allocates memory resources for the gpio device and registers
+ * all the banks of the device. It will also set up interrupts for the gpio
+ * pins.
+ * Note: Interrupts are disabled for all the banks during initialization.
+ *
+ * Return: 0 on success, negative error otherwise.
+ */
+static int zynq_gpio_probe(struct platform_device *pdev)
+{
+ int ret, bank_num, irq;
+ struct zynq_gpio *gpio;
+ struct gpio_chip *chip;
+ struct resource *res;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, gpio);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(gpio->base_addr))
+ return PTR_ERR(gpio->base_addr);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "invalid IRQ\n");
+ return irq;
+ }
+
+ /* configure the gpio chip */
+ chip = &gpio->chip;
+ chip->label = "zynq_gpio";
+ chip->owner = THIS_MODULE;
+ chip->dev = &pdev->dev;
+ chip->get = zynq_gpio_get_value;
+ chip->set = zynq_gpio_set_value;
+ chip->request = zynq_gpio_request;
+ chip->free = zynq_gpio_free;
+ chip->direction_input = zynq_gpio_dir_in;
+ chip->direction_output = zynq_gpio_dir_out;
+ chip->base = -1;
+ chip->ngpio = ZYNQ_GPIO_NR_GPIOS;
+
+ /* Enable GPIO clock */
+ gpio->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(gpio->clk)) {
+ dev_err(&pdev->dev, "input clock not found.\n");
+ return PTR_ERR(gpio->clk);
+ }
+ ret = clk_prepare_enable(gpio->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to enable clock.\n");
+ return ret;
+ }
+
+ /* report a bug if gpio chip registration fails */
+ ret = gpiochip_add(chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add gpio chip\n");
+ goto err_disable_clk;
+ }
+
+ /* disable interrupts for all banks */
+ for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++)
+ writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
+ ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+
+ ret = gpiochip_irqchip_add(chip, &zynq_gpio_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add irq chip\n");
+ goto err_rm_gpiochip;
+ }
+
+ gpiochip_set_chained_irqchip(chip, &zynq_gpio_irqchip, irq,
+ zynq_gpio_irqhandler);
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ device_set_wakeup_capable(&pdev->dev, 1);
+
+ return 0;
+
+err_rm_gpiochip:
+ if (gpiochip_remove(chip))
+ dev_err(&pdev->dev, "Failed to remove gpio chip\n");
+err_disable_clk:
+ clk_disable_unprepare(gpio->clk);
+
+ return ret;
+}
+
+/**
+ * zynq_gpio_remove - Driver removal function
+ * @pdev: platform device instance
+ *
+ * Return: 0 always
+ */
+static int zynq_gpio_remove(struct platform_device *pdev)
+{
+ int ret;
+ struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&pdev->dev);
+
+ ret = gpiochip_remove(&gpio->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to remove gpio chip\n");
+ return ret;
+ }
+ clk_disable_unprepare(gpio->clk);
+ device_set_wakeup_capable(&pdev->dev, 0);
+ return 0;
+}
+
+static struct of_device_id zynq_gpio_of_match[] = {
+ { .compatible = "xlnx,zynq-gpio-1.0", },
+ { /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
+
+static struct platform_driver zynq_gpio_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &zynq_gpio_dev_pm_ops,
+ .of_match_table = zynq_gpio_of_match,
+ },
+ .probe = zynq_gpio_probe,
+ .remove = zynq_gpio_remove,
+};
+
+/**
+ * zynq_gpio_init - Initial driver registration call
+ *
+ * Return: value from platform_driver_register
+ */
+static int __init zynq_gpio_init(void)
+{
+ return platform_driver_register(&zynq_gpio_driver);
+}
+postcore_initcall(zynq_gpio_init);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Zynq GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 4a987917c186..d62eaaa75397 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -157,7 +157,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
gpiod_direction_input(desc);
- ret = gpiod_lock_as_irq(desc);
+ ret = gpio_lock_as_irq(chip, pin);
if (ret) {
dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
goto fail_free_desc;
@@ -212,7 +212,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
fail_free_event:
kfree(event);
fail_unlock_irq:
- gpiod_unlock_as_irq(desc);
+ gpio_unlock_as_irq(chip, pin);
fail_free_desc:
gpiochip_free_own_desc(desc);
@@ -221,7 +221,7 @@ fail_free_desc:
/**
* acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
- * @acpi_gpio: ACPI GPIO chip
+ * @chip: GPIO chip
*
* ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
* handled by ACPI event methods which need to be called from the GPIO
@@ -229,11 +229,21 @@ fail_free_desc:
* gpio pins have acpi event methods and assigns interrupt handlers that calls
* the acpi event methods for those pins.
*/
-static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
- struct gpio_chip *chip = acpi_gpio->chip;
+ struct acpi_gpio_chip *acpi_gpio;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip->dev || !chip->to_irq)
+ return;
- if (!chip->to_irq)
+ handle = ACPI_HANDLE(chip->dev);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
return;
INIT_LIST_HEAD(&acpi_gpio->events);
@@ -243,17 +253,27 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
/**
* acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
- * @acpi_gpio: ACPI GPIO chip
+ * @chip: GPIO chip
*
* Free interrupts associated with GPIO ACPI event method for the given
* GPIO chip.
*/
-static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
{
+ struct acpi_gpio_chip *acpi_gpio;
struct acpi_gpio_event *event, *ep;
- struct gpio_chip *chip = acpi_gpio->chip;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip->dev || !chip->to_irq)
+ return;
- if (!chip->to_irq)
+ handle = ACPI_HANDLE(chip->dev);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
return;
list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@@ -263,7 +283,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
desc = gpiochip_get_desc(chip, event->pin);
if (WARN_ON(IS_ERR(desc)))
continue;
- gpiod_unlock_as_irq(desc);
+ gpio_unlock_as_irq(chip, event->pin);
gpiochip_free_own_desc(desc);
list_del(&event->node);
kfree(event);
@@ -525,7 +545,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
return;
}
- acpi_gpiochip_request_interrupts(acpi_gpio);
acpi_gpiochip_request_regions(acpi_gpio);
}
@@ -549,7 +568,6 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
}
acpi_gpiochip_free_regions(acpi_gpio);
- acpi_gpiochip_free_interrupts(acpi_gpio);
acpi_detach_data(handle, acpi_gpio_chip_dh);
kfree(acpi_gpio);
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
new file mode 100644
index 000000000000..078ae6c2df79
--- /dev/null
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -0,0 +1,102 @@
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+#include <linux/gpio.h>
+
+#include "gpiolib.h"
+
+void gpio_free(unsigned gpio)
+{
+ gpiod_free(gpio_to_desc(gpio));
+}
+EXPORT_SYMBOL_GPL(gpio_free);
+
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ struct gpio_desc *desc;
+ int err;
+
+ desc = gpio_to_desc(gpio);
+
+ err = gpiod_request(desc, label);
+ if (err)
+ return err;
+
+ if (flags & GPIOF_OPEN_DRAIN)
+ set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+
+ if (flags & GPIOF_OPEN_SOURCE)
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
+ if (flags & GPIOF_ACTIVE_LOW)
+ set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+ if (flags & GPIOF_DIR_IN)
+ err = gpiod_direction_input(desc);
+ else
+ err = gpiod_direction_output_raw(desc,
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+ if (err)
+ goto free_gpio;
+
+ if (flags & GPIOF_EXPORT) {
+ err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
+ if (err)
+ goto free_gpio;
+ }
+
+ return 0;
+
+ free_gpio:
+ gpiod_free(desc);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ return gpiod_request(gpio_to_desc(gpio), label);
+}
+EXPORT_SYMBOL_GPL(gpio_request);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+int gpio_request_array(const struct gpio *array, size_t num)
+{
+ int i, err;
+
+ for (i = 0; i < num; i++, array++) {
+ err = gpio_request_one(array->gpio, array->flags, array->label);
+ if (err)
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ while (i--)
+ gpio_free((--array)->gpio);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+void gpio_free_array(const struct gpio *array, size_t num)
+{
+ while (num--)
+ gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index af7e25c9a9ae..7cfdc2278905 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -23,7 +23,7 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
-struct gpio_desc;
+#include "gpiolib.h"
/* Private data structure for of_gpiochip_find_and_xlate */
struct gg_data {
@@ -82,19 +82,19 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
&gg_data.gpiospec);
if (ret) {
- pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
- __func__, np->full_name, index);
+ pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n",
+ __func__, propname, np->full_name, index);
return ERR_PTR(ret);
}
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
of_node_put(gg_data.gpiospec.np);
- pr_debug("%s exited with status %d\n", __func__,
+ pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n",
+ __func__, propname, np->full_name, index,
PTR_ERR_OR_ZERO(gg_data.out_gpio));
return gg_data.out_gpio;
}
-EXPORT_SYMBOL(of_get_named_gpiod_flags);
int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
int index, enum of_gpio_flags *flags)
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
new file mode 100644
index 000000000000..5f2150b619a7
--- /dev/null
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -0,0 +1,827 @@
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+
+#include "gpiolib.h"
+
+static DEFINE_IDR(dirent_idr);
+
+
+/* lock protects against unexport_gpio() being called while
+ * sysfs files are active.
+ */
+static DEFINE_MUTEX(sysfs_lock);
+
+/*
+ * /sys/class/gpio/gpioN... only for GPIOs that are exported
+ * /direction
+ * * MAY BE OMITTED if kernel won't allow direction changes
+ * * is read/write as "in" or "out"
+ * * may also be written as "high" or "low", initializing
+ * output value as specified ("out" implies "low")
+ * /value
+ * * always readable, subject to hardware behavior
+ * * may be writable, as zero/nonzero
+ * /edge
+ * * configures behavior of poll(2) on /value
+ * * available only if pin can generate IRQs on input
+ * * is read/write as "none", "falling", "rising", or "both"
+ * /active_low
+ * * configures polarity of /value
+ * * is read/write as zero/nonzero
+ * * also affects existing and subsequent "falling" and "rising"
+ * /edge configuration
+ */
+
+static ssize_t gpio_direction_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+ status = -EIO;
+ } else {
+ gpiod_get_direction(desc);
+ status = sprintf(buf, "%s\n",
+ test_bit(FLAG_IS_OUT, &desc->flags)
+ ? "out" : "in");
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_direction_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else if (sysfs_streq(buf, "high"))
+ status = gpiod_direction_output_raw(desc, 1);
+ else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
+ status = gpiod_direction_output_raw(desc, 0);
+ else if (sysfs_streq(buf, "in"))
+ status = gpiod_direction_input(desc);
+ else
+ status = -EINVAL;
+
+ mutex_unlock(&sysfs_lock);
+ return status ? : size;
+}
+
+static /* const */ DEVICE_ATTR(direction, 0644,
+ gpio_direction_show, gpio_direction_store);
+
+static ssize_t gpio_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else
+ status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_value_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else if (!test_bit(FLAG_IS_OUT, &desc->flags))
+ status = -EPERM;
+ else {
+ long value;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0) {
+ gpiod_set_value_cansleep(desc, value);
+ status = size;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static const DEVICE_ATTR(value, 0644,
+ gpio_value_show, gpio_value_store);
+
+static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
+{
+ struct kernfs_node *value_sd = priv;
+
+ sysfs_notify_dirent(value_sd);
+ return IRQ_HANDLED;
+}
+
+static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
+ unsigned long gpio_flags)
+{
+ struct kernfs_node *value_sd;
+ unsigned long irq_flags;
+ int ret, irq, id;
+
+ if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
+ return 0;
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0)
+ return -EIO;
+
+ id = desc->flags >> ID_SHIFT;
+ value_sd = idr_find(&dirent_idr, id);
+ if (value_sd)
+ free_irq(irq, value_sd);
+
+ desc->flags &= ~GPIO_TRIGGER_MASK;
+
+ if (!gpio_flags) {
+ gpio_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ ret = 0;
+ goto free_id;
+ }
+
+ irq_flags = IRQF_SHARED;
+ if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
+ irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+ IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
+ if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
+ irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+ IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+
+ if (!value_sd) {
+ value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
+ if (!value_sd) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_sd;
+ id = ret;
+
+ desc->flags &= GPIO_FLAGS_MASK;
+ desc->flags |= (unsigned long)id << ID_SHIFT;
+
+ if (desc->flags >> ID_SHIFT != id) {
+ ret = -ERANGE;
+ goto free_id;
+ }
+ }
+
+ ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
+ "gpiolib", value_sd);
+ if (ret < 0)
+ goto free_id;
+
+ ret = gpio_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
+ if (ret < 0) {
+ gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
+ goto free_id;
+ }
+
+ desc->flags |= gpio_flags;
+ return 0;
+
+free_id:
+ idr_remove(&dirent_idr, id);
+ desc->flags &= GPIO_FLAGS_MASK;
+free_sd:
+ if (value_sd)
+ sysfs_put(value_sd);
+err_out:
+ return ret;
+}
+
+static const struct {
+ const char *name;
+ unsigned long flags;
+} trigger_types[] = {
+ { "none", 0 },
+ { "falling", BIT(FLAG_TRIG_FALL) },
+ { "rising", BIT(FLAG_TRIG_RISE) },
+ { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
+};
+
+static ssize_t gpio_edge_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else {
+ int i;
+
+ status = 0;
+ for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
+ if ((desc->flags & GPIO_TRIGGER_MASK)
+ == trigger_types[i].flags) {
+ status = sprintf(buf, "%s\n",
+ trigger_types[i].name);
+ break;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static ssize_t gpio_edge_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
+ if (sysfs_streq(trigger_types[i].name, buf))
+ goto found;
+ return -EINVAL;
+
+found:
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else {
+ status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
+ if (!status)
+ status = size;
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+ return status;
+}
+
+static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
+
+static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
+ int value)
+{
+ int status = 0;
+
+ if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
+ return 0;
+
+ if (value)
+ set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ else
+ clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+ /* reconfigure poll(2) support if enabled on one edge only */
+ if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
+ !!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
+ unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
+
+ gpio_setup_irq(desc, dev, 0);
+ status = gpio_setup_irq(desc, dev, trigger_flags);
+ }
+
+ return status;
+}
+
+static ssize_t gpio_active_low_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else
+ status = sprintf(buf, "%d\n",
+ !!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
+
+ mutex_unlock(&sysfs_lock);
+
+ return status;
+}
+
+static ssize_t gpio_active_low_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+ status = -EIO;
+ } else {
+ long value;
+
+ status = kstrtol(buf, 0, &value);
+ if (status == 0)
+ status = sysfs_set_active_low(desc, dev, value != 0);
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+ return status ? : size;
+}
+
+static const DEVICE_ATTR(active_low, 0644,
+ gpio_active_low_show, gpio_active_low_store);
+
+static const struct attribute *gpio_attrs[] = {
+ &dev_attr_value.attr,
+ &dev_attr_active_low.attr,
+ NULL,
+};
+
+static const struct attribute_group gpio_attr_group = {
+ .attrs = (struct attribute **) gpio_attrs,
+};
+
+/*
+ * /sys/class/gpio/gpiochipN/
+ * /base ... matching gpio_chip.base (N)
+ * /label ... matching gpio_chip.label
+ * /ngpio ... matching gpio_chip.ngpio
+ */
+
+static ssize_t chip_base_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", chip->base);
+}
+static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
+
+static ssize_t chip_label_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", chip->label ? : "");
+}
+static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
+
+static ssize_t chip_ngpio_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", chip->ngpio);
+}
+static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
+
+static const struct attribute *gpiochip_attrs[] = {
+ &dev_attr_base.attr,
+ &dev_attr_label.attr,
+ &dev_attr_ngpio.attr,
+ NULL,
+};
+
+static const struct attribute_group gpiochip_attr_group = {
+ .attrs = (struct attribute **) gpiochip_attrs,
+};
+
+/*
+ * /sys/class/gpio/export ... write-only
+ * integer N ... number of GPIO to export (full access)
+ * /sys/class/gpio/unexport ... write-only
+ * integer N ... number of GPIO to unexport
+ */
+static ssize_t export_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t len)
+{
+ long gpio;
+ struct gpio_desc *desc;
+ int status;
+
+ status = kstrtol(buf, 0, &gpio);
+ if (status < 0)
+ goto done;
+
+ desc = gpio_to_desc(gpio);
+ /* reject invalid GPIOs */
+ if (!desc) {
+ pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+ return -EINVAL;
+ }
+
+ /* No extra locking here; FLAG_SYSFS just signifies that the
+ * request and export were done by on behalf of userspace, so
+ * they may be undone on its behalf too.
+ */
+
+ status = gpiod_request(desc, "sysfs");
+ if (status < 0) {
+ if (status == -EPROBE_DEFER)
+ status = -ENODEV;
+ goto done;
+ }
+ status = gpiod_export(desc, true);
+ if (status < 0)
+ gpiod_free(desc);
+ else
+ set_bit(FLAG_SYSFS, &desc->flags);
+
+done:
+ if (status)
+ pr_debug("%s: status %d\n", __func__, status);
+ return status ? : len;
+}
+
+static ssize_t unexport_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t len)
+{
+ long gpio;
+ struct gpio_desc *desc;
+ int status;
+
+ status = kstrtol(buf, 0, &gpio);
+ if (status < 0)
+ goto done;
+
+ desc = gpio_to_desc(gpio);
+ /* reject bogus commands (gpio_unexport ignores them) */
+ if (!desc) {
+ pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
+ return -EINVAL;
+ }
+
+ status = -EINVAL;
+
+ /* No extra locking here; FLAG_SYSFS just signifies that the
+ * request and export were done by on behalf of userspace, so
+ * they may be undone on its behalf too.
+ */
+ if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
+ status = 0;
+ gpiod_free(desc);
+ }
+done:
+ if (status)
+ pr_debug("%s: status %d\n", __func__, status);
+ return status ? : len;
+}
+
+static struct class_attribute gpio_class_attrs[] = {
+ __ATTR(export, 0200, NULL, export_store),
+ __ATTR(unexport, 0200, NULL, unexport_store),
+ __ATTR_NULL,
+};
+
+static struct class gpio_class = {
+ .name = "gpio",
+ .owner = THIS_MODULE,
+
+ .class_attrs = gpio_class_attrs,
+};
+
+
+/**
+ * gpiod_export - export a GPIO through sysfs
+ * @gpio: gpio to make available, already requested
+ * @direction_may_change: true if userspace may change gpio direction
+ * Context: arch_initcall or later
+ *
+ * When drivers want to make a GPIO accessible to userspace after they
+ * have requested it -- perhaps while debugging, or as part of their
+ * public interface -- they may use this routine. If the GPIO can
+ * change direction (some can't) and the caller allows it, userspace
+ * will see "direction" sysfs attribute which may be used to change
+ * the gpio's direction. A "value" attribute will always be provided.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+{
+ unsigned long flags;
+ int status;
+ const char *ioname = NULL;
+ struct device *dev;
+ int offset;
+
+ /* can't export until sysfs is available ... */
+ if (!gpio_class.p) {
+ pr_debug("%s: called too early!\n", __func__);
+ return -ENOENT;
+ }
+
+ if (!desc) {
+ pr_debug("%s: invalid gpio descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&sysfs_lock);
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+ test_bit(FLAG_EXPORT, &desc->flags)) {
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
+ __func__,
+ 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);
+
+ offset = gpio_chip_hwgpio(desc);
+ if (desc->chip->names && desc->chip->names[offset])
+ ioname = desc->chip->names[offset];
+
+ dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+ desc, ioname ? ioname : "gpio%u",
+ desc_to_gpio(desc));
+ if (IS_ERR(dev)) {
+ status = PTR_ERR(dev);
+ goto fail_unlock;
+ }
+
+ status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
+ if (status)
+ goto fail_unregister_device;
+
+ if (direction_may_change) {
+ status = device_create_file(dev, &dev_attr_direction);
+ if (status)
+ goto fail_unregister_device;
+ }
+
+ if (gpiod_to_irq(desc) >= 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);
+ gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_export);
+
+static int match_export(struct device *dev, const void *data)
+{
+ return dev_get_drvdata(dev) == data;
+}
+
+/**
+ * gpiod_export_link - create a sysfs link to an exported GPIO node
+ * @dev: device under which to create symlink
+ * @name: name of the symlink
+ * @gpio: gpio to create symlink to, already exported
+ *
+ * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
+ * node. Caller is responsible for unlinking.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_export_link(struct device *dev, const char *name,
+ struct gpio_desc *desc)
+{
+ int status = -EINVAL;
+
+ if (!desc) {
+ pr_warn("%s: invalid GPIO\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&sysfs_lock);
+
+ if (test_bit(FLAG_EXPORT, &desc->flags)) {
+ struct device *tdev;
+
+ tdev = class_find_device(&gpio_class, NULL, desc, match_export);
+ if (tdev != NULL) {
+ status = sysfs_create_link(&dev->kobj, &tdev->kobj,
+ name);
+ } else {
+ status = -ENODEV;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+ if (status)
+ gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_export_link);
+
+/**
+ * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
+ * @gpio: gpio to change
+ * @value: non-zero to use active low, i.e. inverted values
+ *
+ * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
+ * The GPIO does not have to be exported yet. If poll(2) support has
+ * been enabled for either rising or falling edge, it will be
+ * reconfigured to follow the new polarity.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
+{
+ struct device *dev = NULL;
+ int status = -EINVAL;
+
+ if (!desc) {
+ pr_warn("%s: invalid GPIO\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&sysfs_lock);
+
+ if (test_bit(FLAG_EXPORT, &desc->flags)) {
+ dev = class_find_device(&gpio_class, NULL, desc, match_export);
+ if (dev == NULL) {
+ status = -ENODEV;
+ goto unlock;
+ }
+ }
+
+ status = sysfs_set_active_low(desc, dev, value);
+
+unlock:
+ mutex_unlock(&sysfs_lock);
+
+ if (status)
+ gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
+
+/**
+ * gpiod_unexport - reverse effect of gpio_export()
+ * @gpio: gpio to make unavailable
+ *
+ * This is implicit on gpio_free().
+ */
+void gpiod_unexport(struct gpio_desc *desc)
+{
+ int status = 0;
+ struct device *dev = NULL;
+
+ if (!desc) {
+ pr_warn("%s: invalid GPIO\n", __func__);
+ return;
+ }
+
+ mutex_lock(&sysfs_lock);
+
+ if (test_bit(FLAG_EXPORT, &desc->flags)) {
+
+ dev = class_find_device(&gpio_class, NULL, desc, match_export);
+ if (dev) {
+ gpio_setup_irq(desc, dev, 0);
+ clear_bit(FLAG_EXPORT, &desc->flags);
+ } else
+ status = -ENODEV;
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+ if (dev) {
+ device_unregister(dev);
+ put_device(dev);
+ }
+
+ if (status)
+ gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+}
+EXPORT_SYMBOL_GPL(gpiod_unexport);
+
+int gpiochip_export(struct gpio_chip *chip)
+{
+ int status;
+ struct device *dev;
+
+ /* Many systems register gpio chips for SOC support very early,
+ * before driver model support is available. In those cases we
+ * export this later, in gpiolib_sysfs_init() ... here we just
+ * verify that _some_ field of gpio_class got initialized.
+ */
+ if (!gpio_class.p)
+ return 0;
+
+ /* use chip->base for the ID; it's already known to be unique */
+ mutex_lock(&sysfs_lock);
+ dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
+ "gpiochip%d", chip->base);
+ if (!IS_ERR(dev)) {
+ status = sysfs_create_group(&dev->kobj,
+ &gpiochip_attr_group);
+ } else
+ status = PTR_ERR(dev);
+ chip->exported = (status == 0);
+ mutex_unlock(&sysfs_lock);
+
+ if (status)
+ chip_dbg(chip, "%s: status %d\n", __func__, status);
+
+ return status;
+}
+
+void gpiochip_unexport(struct gpio_chip *chip)
+{
+ int status;
+ struct device *dev;
+
+ mutex_lock(&sysfs_lock);
+ dev = class_find_device(&gpio_class, NULL, chip, match_export);
+ if (dev) {
+ put_device(dev);
+ device_unregister(dev);
+ chip->exported = false;
+ status = 0;
+ } else
+ status = -ENODEV;
+ mutex_unlock(&sysfs_lock);
+
+ if (status)
+ chip_dbg(chip, "%s: status %d\n", __func__, status);
+}
+
+static int __init gpiolib_sysfs_init(void)
+{
+ int status;
+ unsigned long flags;
+ struct gpio_chip *chip;
+
+ status = class_register(&gpio_class);
+ if (status < 0)
+ return status;
+
+ /* Scan and register the gpio_chips which registered very
+ * early (e.g. before the class_register above was called).
+ *
+ * We run before arch_initcall() so chip->dev nodes can have
+ * registered, and so arch_initcall() can always gpio_export().
+ */
+ spin_lock_irqsave(&gpio_lock, flags);
+ list_for_each_entry(chip, &gpio_chips, list) {
+ if (chip->exported)
+ continue;
+
+ /*
+ * TODO we yield gpio_lock here because gpiochip_export()
+ * acquires a mutex. This is unsafe and needs to be fixed.
+ *
+ * Also it would be nice to use gpiochip_find() here so we
+ * can keep gpio_chips local to gpiolib.c, but the yield of
+ * gpio_lock prevents us from doing this.
+ */
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ status = gpiochip_export(chip);
+ spin_lock_irqsave(&gpio_lock, flags);
+ }
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+
+ return status;
+}
+postcore_initcall(gpiolib_sysfs_init);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2ebc9071e354..15cc0bb65dda 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include "gpiolib.h"
@@ -44,111 +45,19 @@
* While any GPIO is requested, its gpio_chip is not removable;
* each GPIO's "requested" flag serves as a lock and refcount.
*/
-static DEFINE_SPINLOCK(gpio_lock);
+DEFINE_SPINLOCK(gpio_lock);
-struct gpio_desc {
- struct gpio_chip *chip;
- unsigned long flags;
-/* flag symbols are bit numbers */
-#define FLAG_REQUESTED 0
-#define FLAG_IS_OUT 1
-#define FLAG_EXPORT 2 /* protected by sysfs_lock */
-#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
-#define FLAG_TRIG_FALL 4 /* trigger on falling edge */
-#define FLAG_TRIG_RISE 5 /* trigger on rising edge */
-#define FLAG_ACTIVE_LOW 6 /* value has active low */
-#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
-#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
-#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
-
-#define ID_SHIFT 16 /* add new flags before this one */
-
-#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
-#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
-
-#ifdef CONFIG_DEBUG_FS
- const char *label;
-#endif
-};
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
static DEFINE_MUTEX(gpio_lookup_lock);
static LIST_HEAD(gpio_lookup_list);
-static LIST_HEAD(gpio_chips);
-
-#ifdef CONFIG_GPIO_SYSFS
-static DEFINE_IDR(dirent_idr);
-#endif
-
-static int gpiod_request(struct gpio_desc *desc, const char *label);
-static void gpiod_free(struct gpio_desc *desc);
-
-/* With descriptor prefix */
-
-#ifdef CONFIG_DEBUG_FS
-#define gpiod_emerg(desc, fmt, ...) \
- pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
- ##__VA_ARGS__)
-#define gpiod_crit(desc, fmt, ...) \
- pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_err(desc, fmt, ...) \
- pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_warn(desc, fmt, ...) \
- pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_info(desc, fmt, ...) \
- pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_dbg(desc, fmt, ...) \
- pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
- ##__VA_ARGS__)
-#else
-#define gpiod_emerg(desc, fmt, ...) \
- pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_crit(desc, fmt, ...) \
- pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_err(desc, fmt, ...) \
- pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_warn(desc, fmt, ...) \
- pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_info(desc, fmt, ...) \
- pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#define gpiod_dbg(desc, fmt, ...) \
- pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
-#endif
-
-/* With chip prefix */
-
-#define chip_emerg(chip, fmt, ...) \
- pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_crit(chip, fmt, ...) \
- pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_err(chip, fmt, ...) \
- pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_warn(chip, fmt, ...) \
- pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_info(chip, fmt, ...) \
- pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
-#define chip_dbg(chip, fmt, ...) \
- pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+LIST_HEAD(gpio_chips);
static inline void desc_set_label(struct gpio_desc *d, const char *label)
{
-#ifdef CONFIG_DEBUG_FS
d->label = label;
-#endif
-}
-
-/*
- * Return the GPIO number of the passed descriptor relative to its chip
- */
-static int gpio_chip_hwgpio(const struct gpio_desc *desc)
-{
- return desc - &desc->chip->desc[0];
}
/**
@@ -174,7 +83,6 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
return &chip->desc[hwnum];
}
-EXPORT_SYMBOL_GPL(gpiochip_get_desc);
/**
* Convert a GPIO descriptor to the integer namespace.
@@ -188,39 +96,6 @@ int desc_to_gpio(const struct gpio_desc *desc)
EXPORT_SYMBOL_GPL(desc_to_gpio);
-/* Warn when drivers omit gpio_request() calls -- legal but ill-advised
- * when setting direction, and otherwise illegal. Until board setup code
- * and drivers use explicit requests everywhere (which won't happen when
- * those calls have no teeth) we can't avoid autorequesting. This nag
- * message should motivate switching to explicit requests... so should
- * the weaker cleanup after faults, compared to gpio_request().
- *
- * NOTE: the autorequest mechanism is going away; at this point it's
- * only "legal" in the sense that (old) code using it won't break yet,
- * but instead only triggers a WARN() stack dump.
- */
-static int gpio_ensure_requested(struct gpio_desc *desc)
-{
- const struct gpio_chip *chip = desc->chip;
- const int gpio = desc_to_gpio(desc);
-
- if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0,
- "autorequest GPIO-%d\n", gpio)) {
- if (!try_module_get(chip->owner)) {
- gpiod_err(desc, "%s: module can't be gotten\n",
- __func__);
- clear_bit(FLAG_REQUESTED, &desc->flags);
- /* lose */
- return -EIO;
- }
- desc_set_label(desc, "[auto]");
- /* caller must chip->request() w/o spinlock */
- if (chip->request)
- return 1;
- }
- return 0;
-}
-
/**
* gpiod_to_chip - Return the GPIO chip to which a GPIO descriptor belongs
* @desc: descriptor to return the chip of
@@ -291,836 +166,6 @@ int gpiod_get_direction(const struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiod_get_direction);
-#ifdef CONFIG_GPIO_SYSFS
-
-/* lock protects against unexport_gpio() being called while
- * sysfs files are active.
- */
-static DEFINE_MUTEX(sysfs_lock);
-
-/*
- * /sys/class/gpio/gpioN... only for GPIOs that are exported
- * /direction
- * * MAY BE OMITTED if kernel won't allow direction changes
- * * is read/write as "in" or "out"
- * * may also be written as "high" or "low", initializing
- * output value as specified ("out" implies "low")
- * /value
- * * always readable, subject to hardware behavior
- * * may be writable, as zero/nonzero
- * /edge
- * * configures behavior of poll(2) on /value
- * * available only if pin can generate IRQs on input
- * * is read/write as "none", "falling", "rising", or "both"
- * /active_low
- * * configures polarity of /value
- * * is read/write as zero/nonzero
- * * also affects existing and subsequent "falling" and "rising"
- * /edge configuration
- */
-
-static ssize_t gpio_direction_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags)) {
- status = -EIO;
- } else {
- gpiod_get_direction(desc);
- status = sprintf(buf, "%s\n",
- test_bit(FLAG_IS_OUT, &desc->flags)
- ? "out" : "in");
- }
-
- mutex_unlock(&sysfs_lock);
- return status;
-}
-
-static ssize_t gpio_direction_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else if (sysfs_streq(buf, "high"))
- status = gpiod_direction_output_raw(desc, 1);
- else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
- status = gpiod_direction_output_raw(desc, 0);
- else if (sysfs_streq(buf, "in"))
- status = gpiod_direction_input(desc);
- else
- status = -EINVAL;
-
- mutex_unlock(&sysfs_lock);
- return status ? : size;
-}
-
-static /* const */ DEVICE_ATTR(direction, 0644,
- gpio_direction_show, gpio_direction_store);
-
-static ssize_t gpio_value_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else
- status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
-
- mutex_unlock(&sysfs_lock);
- return status;
-}
-
-static ssize_t gpio_value_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else if (!test_bit(FLAG_IS_OUT, &desc->flags))
- status = -EPERM;
- else {
- long value;
-
- status = kstrtol(buf, 0, &value);
- if (status == 0) {
- gpiod_set_value_cansleep(desc, value);
- status = size;
- }
- }
-
- mutex_unlock(&sysfs_lock);
- return status;
-}
-
-static const DEVICE_ATTR(value, 0644,
- gpio_value_show, gpio_value_store);
-
-static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
-{
- struct kernfs_node *value_sd = priv;
-
- sysfs_notify_dirent(value_sd);
- return IRQ_HANDLED;
-}
-
-static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
- unsigned long gpio_flags)
-{
- struct kernfs_node *value_sd;
- unsigned long irq_flags;
- int ret, irq, id;
-
- if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
- return 0;
-
- irq = gpiod_to_irq(desc);
- if (irq < 0)
- return -EIO;
-
- id = desc->flags >> ID_SHIFT;
- value_sd = idr_find(&dirent_idr, id);
- if (value_sd)
- free_irq(irq, value_sd);
-
- desc->flags &= ~GPIO_TRIGGER_MASK;
-
- if (!gpio_flags) {
- gpiod_unlock_as_irq(desc);
- ret = 0;
- goto free_id;
- }
-
- irq_flags = IRQF_SHARED;
- if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
- irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
- IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
- if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
- irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
- IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
-
- if (!value_sd) {
- value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
- if (!value_sd) {
- ret = -ENODEV;
- goto err_out;
- }
-
- ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
- if (ret < 0)
- goto free_sd;
- id = ret;
-
- desc->flags &= GPIO_FLAGS_MASK;
- desc->flags |= (unsigned long)id << ID_SHIFT;
-
- if (desc->flags >> ID_SHIFT != id) {
- ret = -ERANGE;
- goto free_id;
- }
- }
-
- ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
- "gpiolib", value_sd);
- if (ret < 0)
- goto free_id;
-
- ret = gpiod_lock_as_irq(desc);
- if (ret < 0) {
- gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
- goto free_id;
- }
-
- desc->flags |= gpio_flags;
- return 0;
-
-free_id:
- idr_remove(&dirent_idr, id);
- desc->flags &= GPIO_FLAGS_MASK;
-free_sd:
- if (value_sd)
- sysfs_put(value_sd);
-err_out:
- return ret;
-}
-
-static const struct {
- const char *name;
- unsigned long flags;
-} trigger_types[] = {
- { "none", 0 },
- { "falling", BIT(FLAG_TRIG_FALL) },
- { "rising", BIT(FLAG_TRIG_RISE) },
- { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
-};
-
-static ssize_t gpio_edge_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else {
- int i;
-
- status = 0;
- for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
- if ((desc->flags & GPIO_TRIGGER_MASK)
- == trigger_types[i].flags) {
- status = sprintf(buf, "%s\n",
- trigger_types[i].name);
- break;
- }
- }
-
- mutex_unlock(&sysfs_lock);
- return status;
-}
-
-static ssize_t gpio_edge_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
- if (sysfs_streq(trigger_types[i].name, buf))
- goto found;
- return -EINVAL;
-
-found:
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else {
- status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
- if (!status)
- status = size;
- }
-
- mutex_unlock(&sysfs_lock);
-
- return status;
-}
-
-static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
-
-static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
- int value)
-{
- int status = 0;
-
- if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
- return 0;
-
- if (value)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- else
- clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
- /* reconfigure poll(2) support if enabled on one edge only */
- if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
- !!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
- unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
-
- gpio_setup_irq(desc, dev, 0);
- status = gpio_setup_irq(desc, dev, trigger_flags);
- }
-
- return status;
-}
-
-static ssize_t gpio_active_low_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags))
- status = -EIO;
- else
- status = sprintf(buf, "%d\n",
- !!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
-
- mutex_unlock(&sysfs_lock);
-
- return status;
-}
-
-static ssize_t gpio_active_low_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct gpio_desc *desc = dev_get_drvdata(dev);
- ssize_t status;
-
- mutex_lock(&sysfs_lock);
-
- if (!test_bit(FLAG_EXPORT, &desc->flags)) {
- status = -EIO;
- } else {
- long value;
-
- status = kstrtol(buf, 0, &value);
- if (status == 0)
- status = sysfs_set_active_low(desc, dev, value != 0);
- }
-
- mutex_unlock(&sysfs_lock);
-
- return status ? : size;
-}
-
-static const DEVICE_ATTR(active_low, 0644,
- gpio_active_low_show, gpio_active_low_store);
-
-static const struct attribute *gpio_attrs[] = {
- &dev_attr_value.attr,
- &dev_attr_active_low.attr,
- NULL,
-};
-
-static const struct attribute_group gpio_attr_group = {
- .attrs = (struct attribute **) gpio_attrs,
-};
-
-/*
- * /sys/class/gpio/gpiochipN/
- * /base ... matching gpio_chip.base (N)
- * /label ... matching gpio_chip.label
- * /ngpio ... matching gpio_chip.ngpio
- */
-
-static ssize_t chip_base_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_chip *chip = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", chip->base);
-}
-static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
-
-static ssize_t chip_label_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_chip *chip = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", chip->label ? : "");
-}
-static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
-
-static ssize_t chip_ngpio_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- const struct gpio_chip *chip = dev_get_drvdata(dev);
-
- return sprintf(buf, "%u\n", chip->ngpio);
-}
-static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
-
-static const struct attribute *gpiochip_attrs[] = {
- &dev_attr_base.attr,
- &dev_attr_label.attr,
- &dev_attr_ngpio.attr,
- NULL,
-};
-
-static const struct attribute_group gpiochip_attr_group = {
- .attrs = (struct attribute **) gpiochip_attrs,
-};
-
-/*
- * /sys/class/gpio/export ... write-only
- * integer N ... number of GPIO to export (full access)
- * /sys/class/gpio/unexport ... write-only
- * integer N ... number of GPIO to unexport
- */
-static ssize_t export_store(struct class *class,
- struct class_attribute *attr,
- const char *buf, size_t len)
-{
- long gpio;
- struct gpio_desc *desc;
- int status;
-
- status = kstrtol(buf, 0, &gpio);
- if (status < 0)
- goto done;
-
- desc = gpio_to_desc(gpio);
- /* reject invalid GPIOs */
- if (!desc) {
- pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
- return -EINVAL;
- }
-
- /* No extra locking here; FLAG_SYSFS just signifies that the
- * request and export were done by on behalf of userspace, so
- * they may be undone on its behalf too.
- */
-
- status = gpiod_request(desc, "sysfs");
- if (status < 0) {
- if (status == -EPROBE_DEFER)
- status = -ENODEV;
- goto done;
- }
- status = gpiod_export(desc, true);
- if (status < 0)
- gpiod_free(desc);
- else
- set_bit(FLAG_SYSFS, &desc->flags);
-
-done:
- if (status)
- pr_debug("%s: status %d\n", __func__, status);
- return status ? : len;
-}
-
-static ssize_t unexport_store(struct class *class,
- struct class_attribute *attr,
- const char *buf, size_t len)
-{
- long gpio;
- struct gpio_desc *desc;
- int status;
-
- status = kstrtol(buf, 0, &gpio);
- if (status < 0)
- goto done;
-
- desc = gpio_to_desc(gpio);
- /* reject bogus commands (gpio_unexport ignores them) */
- if (!desc) {
- pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
- return -EINVAL;
- }
-
- status = -EINVAL;
-
- /* No extra locking here; FLAG_SYSFS just signifies that the
- * request and export were done by on behalf of userspace, so
- * they may be undone on its behalf too.
- */
- if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
- status = 0;
- gpiod_free(desc);
- }
-done:
- if (status)
- pr_debug("%s: status %d\n", __func__, status);
- return status ? : len;
-}
-
-static struct class_attribute gpio_class_attrs[] = {
- __ATTR(export, 0200, NULL, export_store),
- __ATTR(unexport, 0200, NULL, unexport_store),
- __ATTR_NULL,
-};
-
-static struct class gpio_class = {
- .name = "gpio",
- .owner = THIS_MODULE,
-
- .class_attrs = gpio_class_attrs,
-};
-
-
-/**
- * gpiod_export - export a GPIO through sysfs
- * @gpio: gpio to make available, already requested
- * @direction_may_change: true if userspace may change gpio direction
- * Context: arch_initcall or later
- *
- * When drivers want to make a GPIO accessible to userspace after they
- * have requested it -- perhaps while debugging, or as part of their
- * public interface -- they may use this routine. If the GPIO can
- * change direction (some can't) and the caller allows it, userspace
- * will see "direction" sysfs attribute which may be used to change
- * the gpio's direction. A "value" attribute will always be provided.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
-{
- unsigned long flags;
- int status;
- const char *ioname = NULL;
- struct device *dev;
- int offset;
-
- /* can't export until sysfs is available ... */
- if (!gpio_class.p) {
- pr_debug("%s: called too early!\n", __func__);
- return -ENOENT;
- }
-
- if (!desc) {
- pr_debug("%s: invalid gpio descriptor\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&sysfs_lock);
-
- spin_lock_irqsave(&gpio_lock, flags);
- if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
- test_bit(FLAG_EXPORT, &desc->flags)) {
- spin_unlock_irqrestore(&gpio_lock, flags);
- gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
- __func__,
- 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);
-
- offset = gpio_chip_hwgpio(desc);
- if (desc->chip->names && desc->chip->names[offset])
- ioname = desc->chip->names[offset];
-
- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
- desc, ioname ? ioname : "gpio%u",
- desc_to_gpio(desc));
- if (IS_ERR(dev)) {
- status = PTR_ERR(dev);
- goto fail_unlock;
- }
-
- status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
- if (status)
- goto fail_unregister_device;
-
- if (direction_may_change) {
- status = device_create_file(dev, &dev_attr_direction);
- if (status)
- goto fail_unregister_device;
- }
-
- if (gpiod_to_irq(desc) >= 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);
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
- return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_export);
-
-static int match_export(struct device *dev, const void *data)
-{
- return dev_get_drvdata(dev) == data;
-}
-
-/**
- * gpiod_export_link - create a sysfs link to an exported GPIO node
- * @dev: device under which to create symlink
- * @name: name of the symlink
- * @gpio: gpio to create symlink to, already exported
- *
- * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
- * node. Caller is responsible for unlinking.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_export_link(struct device *dev, const char *name,
- struct gpio_desc *desc)
-{
- int status = -EINVAL;
-
- if (!desc) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&sysfs_lock);
-
- if (test_bit(FLAG_EXPORT, &desc->flags)) {
- struct device *tdev;
-
- tdev = class_find_device(&gpio_class, NULL, desc, match_export);
- if (tdev != NULL) {
- status = sysfs_create_link(&dev->kobj, &tdev->kobj,
- name);
- } else {
- status = -ENODEV;
- }
- }
-
- mutex_unlock(&sysfs_lock);
-
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_export_link);
-
-/**
- * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
- * @gpio: gpio to change
- * @value: non-zero to use active low, i.e. inverted values
- *
- * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
- * The GPIO does not have to be exported yet. If poll(2) support has
- * been enabled for either rising or falling edge, it will be
- * reconfigured to follow the new polarity.
- *
- * Returns zero on success, else an error.
- */
-int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
-{
- struct device *dev = NULL;
- int status = -EINVAL;
-
- if (!desc) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&sysfs_lock);
-
- if (test_bit(FLAG_EXPORT, &desc->flags)) {
- dev = class_find_device(&gpio_class, NULL, desc, match_export);
- if (dev == NULL) {
- status = -ENODEV;
- goto unlock;
- }
- }
-
- status = sysfs_set_active_low(desc, dev, value);
-
-unlock:
- mutex_unlock(&sysfs_lock);
-
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
-
-/**
- * gpiod_unexport - reverse effect of gpio_export()
- * @gpio: gpio to make unavailable
- *
- * This is implicit on gpio_free().
- */
-void gpiod_unexport(struct gpio_desc *desc)
-{
- int status = 0;
- struct device *dev = NULL;
-
- if (!desc) {
- pr_warn("%s: invalid GPIO\n", __func__);
- return;
- }
-
- mutex_lock(&sysfs_lock);
-
- if (test_bit(FLAG_EXPORT, &desc->flags)) {
-
- dev = class_find_device(&gpio_class, NULL, desc, match_export);
- if (dev) {
- gpio_setup_irq(desc, dev, 0);
- clear_bit(FLAG_EXPORT, &desc->flags);
- } else
- status = -ENODEV;
- }
-
- mutex_unlock(&sysfs_lock);
-
- if (dev) {
- device_unregister(dev);
- put_device(dev);
- }
-
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-}
-EXPORT_SYMBOL_GPL(gpiod_unexport);
-
-static int gpiochip_export(struct gpio_chip *chip)
-{
- int status;
- struct device *dev;
-
- /* Many systems register gpio chips for SOC support very early,
- * before driver model support is available. In those cases we
- * export this later, in gpiolib_sysfs_init() ... here we just
- * verify that _some_ field of gpio_class got initialized.
- */
- if (!gpio_class.p)
- return 0;
-
- /* use chip->base for the ID; it's already known to be unique */
- mutex_lock(&sysfs_lock);
- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
- "gpiochip%d", chip->base);
- if (!IS_ERR(dev)) {
- status = sysfs_create_group(&dev->kobj,
- &gpiochip_attr_group);
- } else
- status = PTR_ERR(dev);
- chip->exported = (status == 0);
- mutex_unlock(&sysfs_lock);
-
- if (status) {
- unsigned long flags;
- unsigned gpio;
-
- spin_lock_irqsave(&gpio_lock, flags);
- gpio = 0;
- while (gpio < chip->ngpio)
- chip->desc[gpio++].chip = NULL;
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- chip_dbg(chip, "%s: status %d\n", __func__, status);
- }
-
- return status;
-}
-
-static void gpiochip_unexport(struct gpio_chip *chip)
-{
- int status;
- struct device *dev;
-
- mutex_lock(&sysfs_lock);
- dev = class_find_device(&gpio_class, NULL, chip, match_export);
- if (dev) {
- put_device(dev);
- device_unregister(dev);
- chip->exported = false;
- status = 0;
- } else
- status = -ENODEV;
- mutex_unlock(&sysfs_lock);
-
- if (status)
- chip_dbg(chip, "%s: status %d\n", __func__, status);
-}
-
-static int __init gpiolib_sysfs_init(void)
-{
- int status;
- unsigned long flags;
- struct gpio_chip *chip;
-
- status = class_register(&gpio_class);
- if (status < 0)
- return status;
-
- /* Scan and register the gpio_chips which registered very
- * early (e.g. before the class_register above was called).
- *
- * We run before arch_initcall() so chip->dev nodes can have
- * registered, and so arch_initcall() can always gpio_export().
- */
- spin_lock_irqsave(&gpio_lock, flags);
- list_for_each_entry(chip, &gpio_chips, list) {
- if (!chip || chip->exported)
- continue;
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- status = gpiochip_export(chip);
- spin_lock_irqsave(&gpio_lock, flags);
- }
- spin_unlock_irqrestore(&gpio_lock, flags);
-
-
- return status;
-}
-postcore_initcall(gpiolib_sysfs_init);
-
-#else
-static inline int gpiochip_export(struct gpio_chip *chip)
-{
- return 0;
-}
-
-static inline void gpiochip_unexport(struct gpio_chip *chip)
-{
-}
-
-#endif /* CONFIG_GPIO_SYSFS */
-
/*
* Add a new chip to the global chips list, keeping the list of chips sorted
* by base order.
@@ -1474,6 +519,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
{
unsigned int offset;
+ acpi_gpiochip_free_interrupts(gpiochip);
+
/* Remove all IRQ mappings and delete the domain */
if (gpiochip->irqdomain) {
for (offset = 0; offset < gpiochip->ngpio; offset++)
@@ -1567,6 +614,8 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
gpiochip->irq_base = irq_base;
}
+ acpi_gpiochip_request_interrupts(gpiochip);
+
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_irqchip_add);
@@ -1740,7 +789,7 @@ done:
return status;
}
-static int gpiod_request(struct gpio_desc *desc, const char *label)
+int gpiod_request(struct gpio_desc *desc, const char *label)
{
int status = -EPROBE_DEFER;
struct gpio_chip *chip;
@@ -1767,12 +816,6 @@ done:
return status;
}
-int gpio_request(unsigned gpio, const char *label)
-{
- return gpiod_request(gpio_to_desc(gpio), label);
-}
-EXPORT_SYMBOL_GPL(gpio_request);
-
static bool __gpiod_free(struct gpio_desc *desc)
{
bool ret = false;
@@ -1805,7 +848,7 @@ static bool __gpiod_free(struct gpio_desc *desc)
return ret;
}
-static void gpiod_free(struct gpio_desc *desc)
+void gpiod_free(struct gpio_desc *desc)
{
if (desc && __gpiod_free(desc))
module_put(desc->chip->owner);
@@ -1813,101 +856,14 @@ static void gpiod_free(struct gpio_desc *desc)
WARN_ON(extra_checks);
}
-void gpio_free(unsigned gpio)
-{
- gpiod_free(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_free);
-
-/**
- * gpio_request_one - request a single GPIO with initial configuration
- * @gpio: the GPIO number
- * @flags: GPIO configuration as specified by GPIOF_*
- * @label: a literal description string of this GPIO
- */
-int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
-{
- struct gpio_desc *desc;
- int err;
-
- desc = gpio_to_desc(gpio);
-
- err = gpiod_request(desc, label);
- if (err)
- return err;
-
- if (flags & GPIOF_OPEN_DRAIN)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-
- if (flags & GPIOF_OPEN_SOURCE)
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-
- if (flags & GPIOF_DIR_IN)
- err = gpiod_direction_input(desc);
- else
- err = gpiod_direction_output_raw(desc,
- (flags & GPIOF_INIT_HIGH) ? 1 : 0);
-
- if (err)
- goto free_gpio;
-
- if (flags & GPIOF_EXPORT) {
- err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
- if (err)
- goto free_gpio;
- }
-
- return 0;
-
- free_gpio:
- gpiod_free(desc);
- return err;
-}
-EXPORT_SYMBOL_GPL(gpio_request_one);
-
-/**
- * gpio_request_array - request multiple GPIOs in a single call
- * @array: array of the 'struct gpio'
- * @num: how many GPIOs in the array
- */
-int gpio_request_array(const struct gpio *array, size_t num)
-{
- int i, err;
-
- for (i = 0; i < num; i++, array++) {
- err = gpio_request_one(array->gpio, array->flags, array->label);
- if (err)
- goto err_free;
- }
- return 0;
-
-err_free:
- while (i--)
- gpio_free((--array)->gpio);
- return err;
-}
-EXPORT_SYMBOL_GPL(gpio_request_array);
-
-/**
- * gpio_free_array - release multiple GPIOs in a single call
- * @array: array of the 'struct gpio'
- * @num: how many GPIOs in the array
- */
-void gpio_free_array(const struct gpio *array, size_t num)
-{
- while (num--)
- gpio_free((array++)->gpio);
-}
-EXPORT_SYMBOL_GPL(gpio_free_array);
-
/**
* gpiochip_is_requested - return string iff signal was requested
* @chip: controller managing the signal
* @offset: of signal within controller's 0..(ngpio - 1) range
*
* Returns NULL if the GPIO is not currently requested, else a string.
- * If debugfs support is enabled, the string returned is the label passed
- * to gpio_request(); otherwise it is a meaningless constant.
+ * The string returned is the label passed to gpio_request(); if none has been
+ * passed it is a meaningless, non-NULL constant.
*
* This function is for use by GPIO controller drivers. The label can
* help with diagnostics, and knowing that the signal is used as a GPIO
@@ -1924,11 +880,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
return NULL;
-#ifdef CONFIG_DEBUG_FS
return desc->label;
-#else
- return "?";
-#endif
}
EXPORT_SYMBOL_GPL(gpiochip_is_requested);
@@ -1950,6 +902,7 @@ int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
return __gpiod_request(desc, label);
}
+EXPORT_SYMBOL_GPL(gpiochip_request_own_desc);
/**
* gpiochip_free_own_desc - Free GPIO requested by the chip driver
@@ -1963,6 +916,7 @@ void gpiochip_free_own_desc(struct gpio_desc *desc)
if (desc)
__gpiod_free(desc);
}
+EXPORT_SYMBOL_GPL(gpiochip_free_own_desc);
/* Drivers MUST set GPIO direction before making get/set calls. In
* some cases this is done in early boot, before IRQs are enabled.
@@ -1984,10 +938,8 @@ void gpiochip_free_own_desc(struct gpio_desc *desc)
*/
int gpiod_direction_input(struct gpio_desc *desc)
{
- unsigned long flags;
struct gpio_chip *chip;
int status = -EINVAL;
- int offset;
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
@@ -2002,52 +954,20 @@ int gpiod_direction_input(struct gpio_desc *desc)
return -EIO;
}
- spin_lock_irqsave(&gpio_lock, flags);
-
- status = gpio_ensure_requested(desc);
- if (status < 0)
- goto fail;
-
- /* now we know the gpio is valid and chip won't vanish */
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- might_sleep_if(chip->can_sleep);
-
- offset = gpio_chip_hwgpio(desc);
- if (status) {
- status = chip->request(chip, offset);
- if (status < 0) {
- gpiod_dbg(desc, "%s: chip request fail, %d\n",
- __func__, status);
- /* and it's not available to anyone else ...
- * gpio_request() is the fully clean solution.
- */
- goto lose;
- }
- }
-
- status = chip->direction_input(chip, offset);
+ status = chip->direction_input(chip, gpio_chip_hwgpio(desc));
if (status == 0)
clear_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_direction(desc_to_gpio(desc), 1, status);
-lose:
- return status;
-fail:
- spin_unlock_irqrestore(&gpio_lock, flags);
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+
return status;
}
EXPORT_SYMBOL_GPL(gpiod_direction_input);
static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
{
- unsigned long flags;
struct gpio_chip *chip;
int status = -EINVAL;
- int offset;
/* GPIOs used for IRQs shall not be set as output */
if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
@@ -2073,42 +993,11 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
return -EIO;
}
- spin_lock_irqsave(&gpio_lock, flags);
-
- status = gpio_ensure_requested(desc);
- if (status < 0)
- goto fail;
-
- /* now we know the gpio is valid and chip won't vanish */
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- might_sleep_if(chip->can_sleep);
-
- offset = gpio_chip_hwgpio(desc);
- if (status) {
- status = chip->request(chip, offset);
- if (status < 0) {
- gpiod_dbg(desc, "%s: chip request fail, %d\n",
- __func__, status);
- /* and it's not available to anyone else ...
- * gpio_request() is the fully clean solution.
- */
- goto lose;
- }
- }
-
- status = chip->direction_output(chip, offset, value);
+ status = chip->direction_output(chip, gpio_chip_hwgpio(desc), value);
if (status == 0)
set_bit(FLAG_IS_OUT, &desc->flags);
trace_gpio_value(desc_to_gpio(desc), 0, value);
trace_gpio_direction(desc_to_gpio(desc), 0, status);
-lose:
- return status;
-fail:
- spin_unlock_irqrestore(&gpio_lock, flags);
- if (status)
- gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
return status;
}
@@ -2167,10 +1056,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output);
*/
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{
- unsigned long flags;
struct gpio_chip *chip;
- int status = -EINVAL;
- int offset;
if (!desc || !desc->chip) {
pr_warn("%s: invalid GPIO\n", __func__);
@@ -2185,27 +1071,7 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
return -ENOTSUPP;
}
- spin_lock_irqsave(&gpio_lock, flags);
-
- status = gpio_ensure_requested(desc);
- if (status < 0)
- goto fail;
-
- /* now we know the gpio is valid and chip won't vanish */
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- might_sleep_if(chip->can_sleep);
-
- offset = gpio_chip_hwgpio(desc);
- return chip->set_debounce(chip, offset, debounce);
-
-fail:
- spin_unlock_irqrestore(&gpio_lock, flags);
- if (status)
- gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-
- return status;
+ return chip->set_debounce(chip, gpio_chip_hwgpio(desc), debounce);
}
EXPORT_SYMBOL_GPL(gpiod_set_debounce);
@@ -2448,54 +1314,44 @@ int gpiod_to_irq(const struct gpio_desc *desc)
EXPORT_SYMBOL_GPL(gpiod_to_irq);
/**
- * gpiod_lock_as_irq() - lock a GPIO to be used as IRQ
- * @gpio: the GPIO line to lock as used for IRQ
+ * gpio_lock_as_irq() - lock a GPIO to be used as IRQ
+ * @chip: the chip the GPIO to lock belongs to
+ * @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to lock down
* a certain GPIO line to be used for IRQs.
*/
-int gpiod_lock_as_irq(struct gpio_desc *desc)
+int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
- if (!desc)
+ if (offset >= chip->ngpio)
return -EINVAL;
- if (test_bit(FLAG_IS_OUT, &desc->flags)) {
- gpiod_err(desc,
+ if (test_bit(FLAG_IS_OUT, &chip->desc[offset].flags)) {
+ chip_err(chip,
"%s: tried to flag a GPIO set as output for IRQ\n",
__func__);
return -EIO;
}
- set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+ set_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
return 0;
}
-EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
-
-int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
-{
- return gpiod_lock_as_irq(gpiochip_get_desc(chip, offset));
-}
EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
/**
- * gpiod_unlock_as_irq() - unlock a GPIO used as IRQ
- * @gpio: the GPIO line to unlock from IRQ usage
+ * gpio_unlock_as_irq() - unlock a GPIO used as IRQ
+ * @chip: the chip the GPIO to lock belongs to
+ * @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to indicate
* that a certain GPIO is no longer used exclusively for IRQ.
*/
-void gpiod_unlock_as_irq(struct gpio_desc *desc)
+void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
- if (!desc)
+ if (offset >= chip->ngpio)
return;
- clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
-}
-EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
-
-void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
-{
- return gpiod_unlock_as_irq(gpiochip_get_desc(chip, offset));
+ clear_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
}
EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
@@ -2726,38 +1582,43 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
* gpiod_get - obtain a GPIO for a given GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
*
* Return the GPIO descriptor corresponding to the function con_id of device
* dev, -ENOENT if no GPIO has been assigned to the requested function, or
* another IS_ERR() code if an error occured while trying to acquire the GPIO.
*/
-struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
+struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id,
+ enum gpiod_flags flags)
{
- return gpiod_get_index(dev, con_id, 0);
+ return gpiod_get_index(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL_GPL(gpiod_get);
+EXPORT_SYMBOL_GPL(__gpiod_get);
/**
* gpiod_get_optional - obtain an optional GPIO for a given GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
+ * @flags: optional GPIO initialization flags
*
* This is equivalent to gpiod_get(), except that when no GPIO was assigned to
* the requested function it will return NULL. This is convenient for drivers
* that need to handle optional GPIOs.
*/
-struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
- const char *con_id)
+struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
+ const char *con_id,
+ enum gpiod_flags flags)
{
- return gpiod_get_index_optional(dev, con_id, 0);
+ return gpiod_get_index_optional(dev, con_id, 0, flags);
}
-EXPORT_SYMBOL_GPL(gpiod_get_optional);
+EXPORT_SYMBOL_GPL(__gpiod_get_optional);
/**
* gpiod_get_index - obtain a GPIO from a multi-index GPIO function
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
*
* This variant of gpiod_get() allows to access GPIOs other than the first
* defined one for functions that define several GPIOs.
@@ -2766,23 +1627,24 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
* requested function and/or index, or another IS_ERR() code if an error
* occured while trying to acquire the GPIO.
*/
-struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
const char *con_id,
- unsigned int idx)
+ unsigned int idx,
+ enum gpiod_flags flags)
{
struct gpio_desc *desc = NULL;
int status;
- enum gpio_lookup_flags flags = 0;
+ enum gpio_lookup_flags lookupflags = 0;
dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
/* Using device tree? */
if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
dev_dbg(dev, "using device tree for GPIO lookup\n");
- desc = of_find_gpio(dev, con_id, idx, &flags);
+ desc = of_find_gpio(dev, con_id, idx, &lookupflags);
} else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
dev_dbg(dev, "using ACPI for GPIO lookup\n");
- desc = acpi_find_gpio(dev, con_id, idx, &flags);
+ desc = acpi_find_gpio(dev, con_id, idx, &lookupflags);
}
/*
@@ -2791,7 +1653,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
*/
if (!desc || desc == ERR_PTR(-ENOENT)) {
dev_dbg(dev, "using lookup tables for GPIO lookup");
- desc = gpiod_find(dev, con_id, idx, &flags);
+ desc = gpiod_find(dev, con_id, idx, &lookupflags);
}
if (IS_ERR(desc)) {
@@ -2804,16 +1666,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
if (status < 0)
return ERR_PTR(status);
- if (flags & GPIO_ACTIVE_LOW)
+ if (lookupflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- if (flags & GPIO_OPEN_DRAIN)
+ if (lookupflags & GPIO_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
- if (flags & GPIO_OPEN_SOURCE)
+ if (lookupflags & GPIO_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+ /* No particular flag request, return here... */
+ if (flags & GPIOD_FLAGS_BIT_DIR_SET)
+ return desc;
+
+ /* Process flags */
+ if (flags & GPIOD_FLAGS_BIT_DIR_OUT)
+ status = gpiod_direction_output(desc,
+ flags & GPIOD_FLAGS_BIT_DIR_VAL);
+ else
+ status = gpiod_direction_input(desc);
+
+ if (status < 0) {
+ dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
+ gpiod_put(desc);
+ return ERR_PTR(status);
+ }
+
return desc;
}
-EXPORT_SYMBOL_GPL(gpiod_get_index);
+EXPORT_SYMBOL_GPL(__gpiod_get_index);
/**
* gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
@@ -2821,18 +1700,20 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
* @dev: GPIO consumer, can be NULL for system-global GPIOs
* @con_id: function within the GPIO consumer
* @index: index of the GPIO to obtain in the consumer
+ * @flags: optional GPIO initialization flags
*
* This is equivalent to gpiod_get_index(), except that when no GPIO with the
* specified index was assigned to the requested function it will return NULL.
* This is convenient for drivers that need to handle optional GPIOs.
*/
-struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
const char *con_id,
- unsigned int index)
+ unsigned int index,
+ enum gpiod_flags flags)
{
struct gpio_desc *desc;
- desc = gpiod_get_index(dev, con_id, index);
+ desc = gpiod_get_index(dev, con_id, index, flags);
if (IS_ERR(desc)) {
if (PTR_ERR(desc) == -ENOENT)
return NULL;
@@ -2840,7 +1721,7 @@ struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
return desc;
}
-EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
+EXPORT_SYMBOL_GPL(__gpiod_get_index_optional);
/**
* gpiod_put - dispose of a GPIO descriptor
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 1a4103dd38df..9db2b6a71c5d 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -31,12 +31,21 @@ struct acpi_gpio_info {
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
+
struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
+static inline void
+acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
+
+static inline void
+acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
+
static inline struct gpio_desc *
acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info)
@@ -45,10 +54,100 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
}
#endif
-int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
-void gpiochip_free_own_desc(struct gpio_desc *desc);
-
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
+struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
+
+extern struct spinlock gpio_lock;
+extern struct list_head gpio_chips;
+
+struct gpio_desc {
+ struct gpio_chip *chip;
+ unsigned long flags;
+/* flag symbols are bit numbers */
+#define FLAG_REQUESTED 0
+#define FLAG_IS_OUT 1
+#define FLAG_EXPORT 2 /* protected by sysfs_lock */
+#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
+#define FLAG_TRIG_FALL 4 /* trigger on falling edge */
+#define FLAG_TRIG_RISE 5 /* trigger on rising edge */
+#define FLAG_ACTIVE_LOW 6 /* value has active low */
+#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
+#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
+#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
+
+#define ID_SHIFT 16 /* add new flags before this one */
+
+#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
+#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
+
+ const char *label;
+};
+
+int gpiod_request(struct gpio_desc *desc, const char *label);
+void gpiod_free(struct gpio_desc *desc);
+
+/*
+ * Return the GPIO number of the passed descriptor relative to its chip
+ */
+static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
+{
+ return desc - &desc->chip->desc[0];
+}
+
+/* With descriptor prefix */
+
+#define gpiod_emerg(desc, fmt, ...) \
+ pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
+ ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...) \
+ pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+ ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...) \
+ pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+ ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...) \
+ pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+ ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...) \
+ pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
+ ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...) \
+ pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
+ ##__VA_ARGS__)
+
+/* With chip prefix */
+
+#define chip_emerg(chip, fmt, ...) \
+ pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_crit(chip, fmt, ...) \
+ pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_err(chip, fmt, ...) \
+ pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_warn(chip, fmt, ...) \
+ pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_info(chip, fmt, ...) \
+ pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+#define chip_dbg(chip, fmt, ...) \
+ pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
+
+#ifdef CONFIG_GPIO_SYSFS
+
+int gpiochip_export(struct gpio_chip *chip);
+void gpiochip_unexport(struct gpio_chip *chip);
+
+#else
+
+static inline int gpiochip_export(struct gpio_chip *chip)
+{
+ return 0;
+}
+
+static inline void gpiochip_unexport(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_GPIO_SYSFS */
+
#endif /* GPIOLIB_H */
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index f5120046ff80..b066bb3ca01a 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -114,6 +114,7 @@ config DRM_RADEON
select POWER_SUPPLY
select HWMON
select BACKLIGHT_CLASS_DEVICE
+ select INTERVAL_TREE
help
Choose this option if you have an ATI Radeon graphics card. There
are both PCI and AGP versions. You don't need to choose this to
@@ -201,3 +202,5 @@ source "drivers/gpu/drm/msm/Kconfig"
source "drivers/gpu/drm/tegra/Kconfig"
source "drivers/gpu/drm/panel/Kconfig"
+
+source "drivers/gpu/drm/sti/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index dd2ba4269740..4a55d59ccd22 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -6,8 +6,8 @@ ccflags-y := -Iinclude/drm
drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_context.o drm_dma.o \
- drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
- drm_lock.o drm_memory.o drm_stub.o drm_vm.o \
+ drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+ drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
drm_agpsupport.o drm_scatter.o drm_pci.o \
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \
@@ -20,11 +20,12 @@ drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_PCI) += ati_pcigart.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
+drm-$(CONFIG_OF) += drm_of.o
drm-usb-y := drm_usb.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
- drm_plane_helper.o
+ drm_plane_helper.o drm_dp_mst_topology.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_DRM_QXL) += qxl/
obj-$(CONFIG_DRM_BOCHS) += bochs/
obj-$(CONFIG_DRM_MSM) += msm/
obj-$(CONFIG_DRM_TEGRA) += tegra/
+obj-$(CONFIG_DRM_STI) += sti/
obj-y += i2c/
obj-y += panel/
obj-y += bridge/
diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index 59948eff6095..ad3d2ebf95c9 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -15,20 +15,19 @@
#include "armada_drm.h"
#include "armada_hw.h"
-static int armada510_init(struct armada_private *priv, struct device *dev)
+static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
{
- priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1");
+ struct clk *clk;
- if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
- priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
+ clk = devm_clk_get(dev, "ext_ref_clk1");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
- return PTR_RET(priv->extclk[0]);
-}
+ dcrtc->extclk[0] = clk;
-static int armada510_crtc_init(struct armada_crtc *dcrtc)
-{
/* Lower the watermark so to eliminate jitter at higher bandwidths */
armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+
return 0;
}
@@ -45,8 +44,7 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc)
static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
const struct drm_display_mode *mode, uint32_t *sclk)
{
- struct armada_private *priv = dcrtc->crtc.dev->dev_private;
- struct clk *clk = priv->extclk[0];
+ struct clk *clk = dcrtc->extclk[0];
int ret;
if (dcrtc->num == 1)
@@ -81,7 +79,6 @@ static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
const struct armada_variant armada510_ops = {
.has_spu_adv_reg = true,
.spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
- .init = armada510_init,
- .crtc_init = armada510_crtc_init,
- .crtc_compute_clock = armada510_crtc_compute_clock,
+ .init = armada510_crtc_init,
+ .compute_clock = armada510_crtc_compute_clock,
};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 81c34f949dfc..9a0cc09e6653 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -7,6 +7,9 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "armada_crtc.h"
@@ -332,24 +335,23 @@ static void armada_drm_crtc_commit(struct drm_crtc *crtc)
static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode, struct drm_display_mode *adj)
{
- struct armada_private *priv = crtc->dev->dev_private;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
int ret;
/* We can't do interlaced modes if we don't have the SPU_ADV_REG */
- if (!priv->variant->has_spu_adv_reg &&
+ if (!dcrtc->variant->has_spu_adv_reg &&
adj->flags & DRM_MODE_FLAG_INTERLACE)
return false;
/* Check whether the display mode is possible */
- ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL);
+ ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
if (ret)
return false;
return true;
}
-void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
+static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
{
struct armada_vbl_event *e, *n;
void __iomem *base = dcrtc->base;
@@ -410,6 +412,27 @@ void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
}
}
+static irqreturn_t armada_drm_irq(int irq, void *arg)
+{
+ struct armada_crtc *dcrtc = arg;
+ u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
+
+ /*
+ * This is rediculous - rather than writing bits to clear, we
+ * have to set the actual status register value. This is racy.
+ */
+ writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
+
+ /* Mask out those interrupts we haven't enabled */
+ v = stat & dcrtc->irq_ena;
+
+ if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
+ armada_drm_crtc_irq(dcrtc, stat);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
/* These are locked by dev->vbl_lock */
void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
{
@@ -470,7 +493,6 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *adj,
int x, int y, struct drm_framebuffer *old_fb)
{
- struct armada_private *priv = crtc->dev->dev_private;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
struct armada_regs regs[17];
uint32_t lm, rm, tm, bm, val, sclk;
@@ -515,7 +537,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
}
/* Now compute the divider for real */
- priv->variant->crtc_compute_clock(dcrtc, adj, &sclk);
+ dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
/* Ensure graphic fifo is enabled */
armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
@@ -537,7 +559,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
dcrtc->v[1].spu_v_porch = tm << 16 | bm;
val = adj->crtc_hsync_start;
dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
- priv->variant->spu_adv_reg;
+ dcrtc->variant->spu_adv_reg;
if (interlaced) {
/* Odd interlaced frame */
@@ -546,7 +568,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
- priv->variant->spu_adv_reg;
+ dcrtc->variant->spu_adv_reg;
} else {
dcrtc->v[0] = dcrtc->v[1];
}
@@ -561,7 +583,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
LCD_SPUT_V_H_TOTAL);
- if (priv->variant->has_spu_adv_reg) {
+ if (dcrtc->variant->has_spu_adv_reg) {
armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
@@ -805,12 +827,11 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
{
struct drm_device *dev = crtc->dev;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
- struct armada_private *priv = crtc->dev->dev_private;
struct armada_gem_object *obj = NULL;
int ret;
/* If no cursor support, replicate drm's return value */
- if (!priv->variant->has_spu_adv_reg)
+ if (!dcrtc->variant->has_spu_adv_reg)
return -ENXIO;
if (handle && w > 0 && h > 0) {
@@ -858,11 +879,10 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{
struct drm_device *dev = crtc->dev;
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
- struct armada_private *priv = crtc->dev->dev_private;
int ret;
/* If no cursor support, replicate drm's return value */
- if (!priv->variant->has_spu_adv_reg)
+ if (!dcrtc->variant->has_spu_adv_reg)
return -EFAULT;
mutex_lock(&dev->struct_mutex);
@@ -888,6 +908,10 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
if (!IS_ERR(dcrtc->clk))
clk_disable_unprepare(dcrtc->clk);
+ writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
+
+ of_node_put(dcrtc->crtc.port);
+
kfree(dcrtc);
}
@@ -1027,23 +1051,22 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev)
return 0;
}
-int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
- struct resource *res)
+int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
+ struct resource *res, int irq, const struct armada_variant *variant,
+ struct device_node *port)
{
- struct armada_private *priv = dev->dev_private;
+ struct armada_private *priv = drm->dev_private;
struct armada_crtc *dcrtc;
void __iomem *base;
int ret;
- ret = armada_drm_crtc_create_properties(dev);
+ ret = armada_drm_crtc_create_properties(drm);
if (ret)
return ret;
- base = devm_request_and_ioremap(dev->dev, res);
- if (!base) {
- DRM_ERROR("failed to ioremap register\n");
- return -ENOMEM;
- }
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
dcrtc = kzalloc(sizeof(*dcrtc), GFP_KERNEL);
if (!dcrtc) {
@@ -1051,8 +1074,12 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
return -ENOMEM;
}
+ if (dev != drm->dev)
+ dev_set_drvdata(dev, dcrtc);
+
+ dcrtc->variant = variant;
dcrtc->base = base;
- dcrtc->num = num;
+ dcrtc->num = drm->mode_config.num_crtc;
dcrtc->clk = ERR_PTR(-EINVAL);
dcrtc->csc_yuv_mode = CSC_AUTO;
dcrtc->csc_rgb_mode = CSC_AUTO;
@@ -1074,9 +1101,18 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
+ writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
+ writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
- if (priv->variant->crtc_init) {
- ret = priv->variant->crtc_init(dcrtc);
+ ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
+ dcrtc);
+ if (ret < 0) {
+ kfree(dcrtc);
+ return ret;
+ }
+
+ if (dcrtc->variant->init) {
+ ret = dcrtc->variant->init(dcrtc, dev);
if (ret) {
kfree(dcrtc);
return ret;
@@ -1088,7 +1124,8 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
priv->dcrtc[dcrtc->num] = dcrtc;
- drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
+ dcrtc->crtc.port = port;
+ drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs);
drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
@@ -1096,5 +1133,107 @@ int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
dcrtc->csc_rgb_mode);
- return armada_overlay_plane_create(dev, 1 << dcrtc->num);
+ return armada_overlay_plane_create(drm, 1 << dcrtc->num);
+}
+
+static int
+armada_lcd_bind(struct device *dev, struct device *master, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = data;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int irq = platform_get_irq(pdev, 0);
+ const struct armada_variant *variant;
+ struct device_node *port = NULL;
+
+ if (irq < 0)
+ return irq;
+
+ if (!dev->of_node) {
+ const struct platform_device_id *id;
+
+ id = platform_get_device_id(pdev);
+ if (!id)
+ return -ENXIO;
+
+ variant = (const struct armada_variant *)id->driver_data;
+ } else {
+ const struct of_device_id *match;
+ struct device_node *np, *parent = dev->of_node;
+
+ match = of_match_device(dev->driver->of_match_table, dev);
+ if (!match)
+ return -ENXIO;
+
+ np = of_get_child_by_name(parent, "ports");
+ if (np)
+ parent = np;
+ port = of_get_child_by_name(parent, "port");
+ of_node_put(np);
+ if (!port) {
+ dev_err(dev, "no port node found in %s\n",
+ parent->full_name);
+ return -ENXIO;
+ }
+
+ variant = match->data;
+ }
+
+ return armada_drm_crtc_create(drm, dev, res, irq, variant, port);
+}
+
+static void
+armada_lcd_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct armada_crtc *dcrtc = dev_get_drvdata(dev);
+
+ armada_drm_crtc_destroy(&dcrtc->crtc);
}
+
+static const struct component_ops armada_lcd_ops = {
+ .bind = armada_lcd_bind,
+ .unbind = armada_lcd_unbind,
+};
+
+static int armada_lcd_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &armada_lcd_ops);
+}
+
+static int armada_lcd_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &armada_lcd_ops);
+ return 0;
+}
+
+static struct of_device_id armada_lcd_of_match[] = {
+ {
+ .compatible = "marvell,dove-lcd",
+ .data = &armada510_ops,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
+
+static const struct platform_device_id armada_lcd_platform_ids[] = {
+ {
+ .name = "armada-lcd",
+ .driver_data = (unsigned long)&armada510_ops,
+ }, {
+ .name = "armada-510-lcd",
+ .driver_data = (unsigned long)&armada510_ops,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
+
+struct platform_driver armada_lcd_platform_driver = {
+ .probe = armada_lcd_probe,
+ .remove = armada_lcd_remove,
+ .driver = {
+ .name = "armada-lcd",
+ .owner = THIS_MODULE,
+ .of_match_table = armada_lcd_of_match,
+ },
+ .id_table = armada_lcd_platform_ids,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 9c10a07e7492..98102a5a9af5 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -32,12 +32,15 @@ struct armada_regs {
armada_reg_queue_mod(_r, _i, 0, 0, ~0)
struct armada_frame_work;
+struct armada_variant;
struct armada_crtc {
struct drm_crtc crtc;
+ const struct armada_variant *variant;
unsigned num;
void __iomem *base;
struct clk *clk;
+ struct clk *extclk[2];
struct {
uint32_t spu_v_h_total;
uint32_t spu_v_porch;
@@ -72,12 +75,16 @@ struct armada_crtc {
};
#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
-int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *);
+struct device_node;
+int armada_drm_crtc_create(struct drm_device *, struct device *,
+ struct resource *, int, const struct armada_variant *,
+ struct device_node *);
void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
-void armada_drm_crtc_irq(struct armada_crtc *, u32);
void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+extern struct platform_driver armada_lcd_platform_driver;
+
#endif
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index a72cae03b99b..ea63c6c7c66f 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -59,26 +59,23 @@ void armada_drm_vbl_event_remove_unlocked(struct armada_crtc *,
struct armada_private;
struct armada_variant {
- bool has_spu_adv_reg;
+ bool has_spu_adv_reg;
uint32_t spu_adv_reg;
- int (*init)(struct armada_private *, struct device *);
- int (*crtc_init)(struct armada_crtc *);
- int (*crtc_compute_clock)(struct armada_crtc *,
- const struct drm_display_mode *,
- uint32_t *);
+ int (*init)(struct armada_crtc *, struct device *);
+ int (*compute_clock)(struct armada_crtc *,
+ const struct drm_display_mode *,
+ uint32_t *);
};
/* Variant ops */
extern const struct armada_variant armada510_ops;
struct armada_private {
- const struct armada_variant *variant;
struct work_struct fb_unref_work;
DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
struct drm_fb_helper *fbdev;
struct armada_crtc *dcrtc[2];
struct drm_mm linear;
- struct clk *extclk[2];
struct drm_property *csc_yuv_prop;
struct drm_property *csc_rgb_prop;
struct drm_property *colorkey_prop;
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 8ab3cd1a8cdb..e2d5792b140f 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -6,7 +6,9 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
+#include <linux/component.h>
#include <linux/module.h>
+#include <linux/of_graph.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "armada_crtc.h"
@@ -52,6 +54,11 @@ static const struct armada_drm_slave_config tda19988_config = {
};
#endif
+static bool is_componentized(struct device *dev)
+{
+ return dev->of_node || dev->platform_data;
+}
+
static void armada_drm_unref_work(struct work_struct *work)
{
struct armada_private *priv =
@@ -85,6 +92,7 @@ void armada_drm_queue_unref_work(struct drm_device *dev,
static int armada_drm_load(struct drm_device *dev, unsigned long flags)
{
const struct platform_device_id *id;
+ const struct armada_variant *variant;
struct armada_private *priv;
struct resource *res[ARRAY_SIZE(priv->dcrtc)];
struct resource *mem = NULL;
@@ -107,7 +115,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
return -EINVAL;
}
- if (!res[0] || !mem)
+ if (!mem)
return -ENXIO;
if (!devm_request_mem_region(dev->dev, mem->start,
@@ -128,11 +136,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
if (!id)
return -ENXIO;
- priv->variant = (struct armada_variant *)id->driver_data;
-
- ret = priv->variant->init(priv, dev->dev);
- if (ret)
- return ret;
+ variant = (const struct armada_variant *)id->driver_data;
INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
INIT_KFIFO(priv->fb_unref);
@@ -155,40 +159,50 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
/* Create all LCD controllers */
for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
+ int irq;
+
if (!res[n])
break;
- ret = armada_drm_crtc_create(dev, n, res[n]);
+ irq = platform_get_irq(dev->platformdev, n);
+ if (irq < 0)
+ goto err_kms;
+
+ ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
+ variant, NULL);
if (ret)
goto err_kms;
}
+ if (is_componentized(dev->dev)) {
+ ret = component_bind_all(dev->dev, dev);
+ if (ret)
+ goto err_kms;
+ } else {
#ifdef CONFIG_DRM_ARMADA_TDA1998X
- ret = armada_drm_connector_slave_create(dev, &tda19988_config);
- if (ret)
- goto err_kms;
+ ret = armada_drm_connector_slave_create(dev, &tda19988_config);
+ if (ret)
+ goto err_kms;
#endif
+ }
- ret = drm_vblank_init(dev, n);
- if (ret)
- goto err_kms;
-
- ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
- goto err_kms;
+ goto err_comp;
dev->vblank_disable_allowed = 1;
ret = armada_fbdev_init(dev);
if (ret)
- goto err_irq;
+ goto err_comp;
drm_kms_helper_poll_init(dev);
return 0;
- err_irq:
- drm_irq_uninstall(dev);
+ err_comp:
+ if (is_componentized(dev->dev))
+ component_unbind_all(dev->dev, dev);
err_kms:
drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear);
@@ -203,7 +217,10 @@ static int armada_drm_unload(struct drm_device *dev)
drm_kms_helper_poll_fini(dev);
armada_fbdev_fini(dev);
- drm_irq_uninstall(dev);
+
+ if (is_componentized(dev->dev))
+ component_unbind_all(dev->dev, dev);
+
drm_mode_config_cleanup(dev);
drm_mm_takedown(&priv->linear);
flush_work(&priv->fb_unref_work);
@@ -259,52 +276,6 @@ static void armada_drm_disable_vblank(struct drm_device *dev, int crtc)
armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
}
-static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
-{
- struct drm_device *dev = arg;
- struct armada_private *priv = dev->dev_private;
- struct armada_crtc *dcrtc = priv->dcrtc[0];
- uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
- irqreturn_t handled = IRQ_NONE;
-
- /*
- * This is rediculous - rather than writing bits to clear, we
- * have to set the actual status register value. This is racy.
- */
- writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
-
- /* Mask out those interrupts we haven't enabled */
- v = stat & dcrtc->irq_ena;
-
- if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
- armada_drm_crtc_irq(dcrtc, stat);
- handled = IRQ_HANDLED;
- }
-
- return handled;
-}
-
-static int armada_drm_irq_postinstall(struct drm_device *dev)
-{
- struct armada_private *priv = dev->dev_private;
- struct armada_crtc *dcrtc = priv->dcrtc[0];
-
- spin_lock_irq(&dev->vbl_lock);
- writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
- writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
- spin_unlock_irq(&dev->vbl_lock);
-
- return 0;
-}
-
-static void armada_drm_irq_uninstall(struct drm_device *dev)
-{
- struct armada_private *priv = dev->dev_private;
- struct armada_crtc *dcrtc = priv->dcrtc[0];
-
- writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
-}
-
static struct drm_ioctl_desc armada_ioctls[] = {
DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
DRM_UNLOCKED),
@@ -340,9 +311,6 @@ static struct drm_driver armada_drm_driver = {
.get_vblank_counter = drm_vblank_count,
.enable_vblank = armada_drm_enable_vblank,
.disable_vblank = armada_drm_disable_vblank,
- .irq_handler = armada_drm_irq_handler,
- .irq_postinstall = armada_drm_irq_postinstall,
- .irq_uninstall = armada_drm_irq_uninstall,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = armada_drm_debugfs_init,
.debugfs_cleanup = armada_drm_debugfs_cleanup,
@@ -362,19 +330,140 @@ static struct drm_driver armada_drm_driver = {
.desc = "Armada SoC DRM",
.date = "20120730",
.driver_features = DRIVER_GEM | DRIVER_MODESET |
- DRIVER_HAVE_IRQ | DRIVER_PRIME,
+ DRIVER_PRIME,
.ioctls = armada_ioctls,
.fops = &armada_drm_fops,
};
+static int armada_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
+}
+
+static void armada_drm_unbind(struct device *dev)
+{
+ drm_put_dev(dev_get_drvdata(dev));
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int compare_dev_name(struct device *dev, void *data)
+{
+ const char *name = data;
+ return !strcmp(dev_name(dev), name);
+}
+
+static void armada_add_endpoints(struct device *dev,
+ struct component_match **match, struct device_node *port)
+{
+ struct device_node *ep, *remote;
+
+ for_each_child_of_node(port, ep) {
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote || !of_device_is_available(remote)) {
+ of_node_put(remote);
+ continue;
+ } else if (!of_device_is_available(remote->parent)) {
+ dev_warn(dev, "parent device of %s is not available\n",
+ remote->full_name);
+ of_node_put(remote);
+ continue;
+ }
+
+ component_match_add(dev, match, compare_of, remote);
+ of_node_put(remote);
+ }
+}
+
+static int armada_drm_find_components(struct device *dev,
+ struct component_match **match)
+{
+ struct device_node *port;
+ int i;
+
+ if (dev->of_node) {
+ struct device_node *np = dev->of_node;
+
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(np, "ports", i);
+ if (!port)
+ break;
+
+ component_match_add(dev, match, compare_of, port);
+ of_node_put(port);
+ }
+
+ if (i == 0) {
+ dev_err(dev, "missing 'ports' property\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(np, "ports", i);
+ if (!port)
+ break;
+
+ armada_add_endpoints(dev, match, port);
+ of_node_put(port);
+ }
+ } else if (dev->platform_data) {
+ char **devices = dev->platform_data;
+ struct device *d;
+
+ for (i = 0; devices[i]; i++)
+ component_match_add(dev, match, compare_dev_name,
+ devices[i]);
+
+ if (i == 0) {
+ dev_err(dev, "missing 'ports' property\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; devices[i]; i++) {
+ d = bus_find_device_by_name(&platform_bus_type, NULL,
+ devices[i]);
+ if (d && d->of_node) {
+ for_each_child_of_node(d->of_node, port)
+ armada_add_endpoints(dev, match, port);
+ }
+ put_device(d);
+ }
+ }
+
+ return 0;
+}
+
+static const struct component_master_ops armada_master_ops = {
+ .bind = armada_drm_bind,
+ .unbind = armada_drm_unbind,
+};
+
static int armada_drm_probe(struct platform_device *pdev)
{
- return drm_platform_init(&armada_drm_driver, pdev);
+ if (is_componentized(&pdev->dev)) {
+ struct component_match *match = NULL;
+ int ret;
+
+ ret = armada_drm_find_components(&pdev->dev, &match);
+ if (ret < 0)
+ return ret;
+
+ return component_master_add_with_match(&pdev->dev,
+ &armada_master_ops, match);
+ } else {
+ return drm_platform_init(&armada_drm_driver, pdev);
+ }
}
static int armada_drm_remove(struct platform_device *pdev)
{
- drm_put_dev(platform_get_drvdata(pdev));
+ if (is_componentized(&pdev->dev))
+ component_master_del(&pdev->dev, &armada_master_ops);
+ else
+ drm_put_dev(platform_get_drvdata(pdev));
return 0;
}
@@ -402,14 +491,24 @@ static struct platform_driver armada_drm_platform_driver = {
static int __init armada_drm_init(void)
{
+ int ret;
+
armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls);
- return platform_driver_register(&armada_drm_platform_driver);
+
+ ret = platform_driver_register(&armada_lcd_platform_driver);
+ if (ret)
+ return ret;
+ ret = platform_driver_register(&armada_drm_platform_driver);
+ if (ret)
+ platform_driver_unregister(&armada_lcd_platform_driver);
+ return ret;
}
module_init(armada_drm_init);
static void __exit armada_drm_exit(void)
{
platform_driver_unregister(&armada_drm_platform_driver);
+ platform_driver_unregister(&armada_lcd_platform_driver);
}
module_exit(armada_drm_exit);
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index fd166f532ab9..7838e731b0de 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -131,7 +131,7 @@ static int armada_fb_probe(struct drm_fb_helper *fbh,
return ret;
}
-static struct drm_fb_helper_funcs armada_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
.gamma_set = armada_drm_crtc_gamma_set,
.gamma_get = armada_drm_crtc_gamma_get,
.fb_probe = armada_fb_probe,
@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device *dev)
priv->fbdev = fbh;
- fbh->funcs = &armada_fb_helper_funcs;
+ drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
ret = drm_fb_helper_init(dev, fbh, 1, 1);
if (ret) {
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index bb9b642d8485..7496f55611a5 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -539,7 +539,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
int flags)
{
return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
- O_RDWR);
+ O_RDWR, NULL);
}
struct drm_gem_object *
diff --git a/drivers/gpu/drm/armada/armada_output.c b/drivers/gpu/drm/armada/armada_output.c
index d685a5421485..abbc309fe539 100644
--- a/drivers/gpu/drm/armada/armada_output.c
+++ b/drivers/gpu/drm/armada/armada_output.c
@@ -48,7 +48,7 @@ static void armada_drm_connector_destroy(struct drm_connector *conn)
{
struct armada_connector *dconn = drm_to_armada_conn(conn);
- drm_sysfs_connector_remove(conn);
+ drm_connector_unregister(conn);
drm_connector_cleanup(conn);
kfree(dconn);
}
@@ -141,7 +141,7 @@ int armada_output_create(struct drm_device *dev,
if (ret)
goto err_conn;
- ret = drm_sysfs_connector_add(&dconn->conn);
+ ret = drm_connector_register(&dconn->conn);
if (ret)
goto err_sysfs;
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 44074fbcf7ff..f19682a93c24 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -51,7 +51,7 @@ static struct drm_driver driver;
.subdevice = PCI_ANY_ID, \
.driver_data = (unsigned long) info }
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL),
AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL),
/* AST_VGA_DEVICE(PCI_CHIP_AST1180, NULL), - don't bind to 1180 for now */
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 5d6a87573c33..957d4fabf1e1 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -362,7 +362,7 @@ static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
{
int ret;
- ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
if (ret) {
if (ret != -ERESTARTSYS && ret != -EBUSY)
DRM_ERROR("reserve failed %p\n", bo);
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index a28640f47c27..cba45c774552 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -287,7 +287,7 @@ static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
*blue = ast_crtc->lut_b[regno] << 8;
}
-static struct drm_fb_helper_funcs ast_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
.gamma_set = ast_fb_gamma_set,
.gamma_get = ast_fb_gamma_get,
.fb_probe = astfb_create,
@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *dev)
return -ENOMEM;
ast->fbdev = afbdev;
- afbdev->helper.funcs = &ast_fb_helper_funcs;
spin_lock_init(&afbdev->dirty_lock);
+
+ drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
+
ret = drm_fb_helper_init(dev, &afbdev->helper,
1, 1);
if (ret) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 114aee941d46..5389350244f2 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -667,17 +667,9 @@ static void ast_encoder_destroy(struct drm_encoder *encoder)
static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
/* pick the encoder ids */
- if (enc_id) {
- obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
@@ -829,7 +821,7 @@ static void ast_connector_destroy(struct drm_connector *connector)
{
struct ast_connector *ast_connector = to_ast_connector(connector);
ast_i2c_destroy(ast_connector->i2c);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -871,7 +863,7 @@ static int ast_connector_init(struct drm_device *dev)
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index 9c13df29fd20..9738e9b14708 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -97,6 +97,7 @@ static struct drm_driver bochs_driver = {
/* ---------------------------------------------------------------------- */
/* pm interface */
+#ifdef CONFIG_PM_SLEEP
static int bochs_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -131,6 +132,7 @@ static int bochs_pm_resume(struct device *dev)
drm_kms_helper_poll_enable(drm_dev);
return 0;
}
+#endif
static const struct dev_pm_ops bochs_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
@@ -175,7 +177,7 @@ static void bochs_pci_remove(struct pci_dev *pdev)
drm_put_dev(dev);
}
-static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = {
+static const struct pci_device_id bochs_pci_tbl[] = {
{
.vendor = 0x1234,
.device = 0x1111,
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 561b84474122..fe95d31cd110 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -72,7 +72,7 @@ static int bochsfb_create(struct drm_fb_helper *helper,
bo = gem_to_bochs_bo(gobj);
- ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret)
return ret;
@@ -179,7 +179,7 @@ void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
*blue = regno;
}
-static struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
.gamma_set = bochs_fb_gamma_set,
.gamma_get = bochs_fb_gamma_get,
.fb_probe = bochsfb_create,
@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device *bochs)
{
int ret;
- bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
+ drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
+ &bochs_fb_helper_funcs);
ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
1, 1);
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index dcf2e55f4ae9..9d7346b92653 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -53,7 +53,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
if (old_fb) {
bochs_fb = to_bochs_framebuffer(old_fb);
bo = gem_to_bochs_bo(bochs_fb->obj);
- ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret) {
DRM_ERROR("failed to reserve old_fb bo\n");
} else {
@@ -67,7 +67,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
bo = gem_to_bochs_bo(bochs_fb->obj);
- ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
if (ret)
return ret;
@@ -216,18 +216,9 @@ static struct drm_encoder *
bochs_connector_best_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
/* pick the encoder ids */
- if (enc_id) {
- obj = drm_mode_object_find(connector->dev, enc_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index b9a695d92792..1728a1b0b813 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -387,7 +387,7 @@ int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
*obj = NULL;
- size = ALIGN(size, PAGE_SIZE);
+ size = PAGE_ALIGN(size);
if (size == 0)
return -EINVAL;
diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c
index 98fd17ae4916..d466696ed5e8 100644
--- a/drivers/gpu/drm/bridge/ptn3460.c
+++ b/drivers/gpu/drm/bridge/ptn3460.c
@@ -328,7 +328,7 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
}
drm_connector_helper_add(&ptn_bridge->connector,
&ptn3460_connector_helper_funcs);
- drm_sysfs_connector_add(&ptn_bridge->connector);
+ drm_connector_register(&ptn_bridge->connector);
drm_mode_connector_attach_encoder(&ptn_bridge->connector, encoder);
return 0;
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
index 08ce520f61a5..919c73b94447 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -29,7 +29,7 @@ module_param_named(modeset, cirrus_modeset, int, 0400);
static struct drm_driver driver;
/* only bind to the cirrus chip in qemu */
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
{ PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
0, 0 },
{0,}
@@ -76,6 +76,7 @@ static void cirrus_pci_remove(struct pci_dev *pdev)
drm_put_dev(dev);
}
+#ifdef CONFIG_PM_SLEEP
static int cirrus_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -110,6 +111,7 @@ static int cirrus_pm_resume(struct device *dev)
drm_kms_helper_poll_enable(drm_dev);
return 0;
}
+#endif
static const struct file_operations cirrus_driver_fops = {
.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 117d3eca5e37..401c890b6c6a 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -241,7 +241,7 @@ static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
{
int ret;
- ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
if (ret) {
if (ret != -ERESTARTSYS && ret != -EBUSY)
DRM_ERROR("reserve failed %p\n", bo);
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index 32bbba0a787b..2a135f253e29 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -288,7 +288,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
return 0;
}
-static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
.gamma_set = cirrus_crtc_fb_gamma_set,
.gamma_get = cirrus_crtc_fb_gamma_get,
.fb_probe = cirrusfb_create,
@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
return -ENOMEM;
cdev->mode_info.gfbdev = gfbdev;
- gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
spin_lock_init(&gfbdev->dirty_lock);
+ drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
+ &cirrus_fb_helper_funcs);
+
ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
if (ret) {
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 49332c5fe35b..e1c5c3222129 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -509,19 +509,9 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
*connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
/* pick the encoder ids */
- if (enc_id) {
- obj =
- drm_mode_object_find(connector->dev, enc_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c
index 0406110f83ed..86a4a4a60afc 100644
--- a/drivers/gpu/drm/drm_buffer.c
+++ b/drivers/gpu/drm/drm_buffer.c
@@ -80,11 +80,7 @@ int drm_buffer_alloc(struct drm_buffer **buf, int size)
error_out:
- /* Only last element can be null pointer so check for it first. */
- if ((*buf)->data[idx])
- kfree((*buf)->data[idx]);
-
- for (--idx; idx >= 0; --idx)
+ for (; idx >= 0; --idx)
kfree((*buf)->data[idx]);
kfree(*buf);
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 68175b54504b..61acb8f6756d 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1217,7 +1217,6 @@ int drm_infobufs(struct drm_device *dev, void *data,
struct drm_buf_desc __user *to =
&request->list[count];
struct drm_buf_entry *from = &dma->bufs[i];
- struct drm_freelist *list = &dma->bufs[i].freelist;
if (copy_to_user(&to->count,
&from->buf_count,
sizeof(from->buf_count)) ||
@@ -1225,19 +1224,19 @@ int drm_infobufs(struct drm_device *dev, void *data,
&from->buf_size,
sizeof(from->buf_size)) ||
copy_to_user(&to->low_mark,
- &list->low_mark,
- sizeof(list->low_mark)) ||
+ &from->low_mark,
+ sizeof(from->low_mark)) ||
copy_to_user(&to->high_mark,
- &list->high_mark,
- sizeof(list->high_mark)))
+ &from->high_mark,
+ sizeof(from->high_mark)))
return -EFAULT;
DRM_DEBUG("%d %d %d %d %d\n",
i,
dma->bufs[i].buf_count,
dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark);
+ dma->bufs[i].low_mark,
+ dma->bufs[i].high_mark);
++count;
}
}
@@ -1290,8 +1289,8 @@ int drm_markbufs(struct drm_device *dev, void *data,
if (request->high_mark < 0 || request->high_mark > entry->buf_count)
return -EINVAL;
- entry->freelist.low_mark = request->low_mark;
- entry->freelist.high_mark = request->high_mark;
+ entry->low_mark = request->low_mark;
+ entry->high_mark = request->high_mark;
return 0;
}
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
index a4b017b6849e..9b23525c0ed0 100644
--- a/drivers/gpu/drm/drm_context.c
+++ b/drivers/gpu/drm/drm_context.c
@@ -1,18 +1,13 @@
-/**
- * \file drm_context.c
- * IOCTLs for generic contexts
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
/*
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ * Legacy: Generic DRM Contexts
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author: Gareth Hughes <gareth@valinux.com>
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@@ -33,14 +28,14 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-/*
- * ChangeLog:
- * 2001-11-16 Torsten Duwe <duwe@caldera.de>
- * added context constructor/destructor hooks,
- * needed by SiS driver's memory management.
- */
-
#include <drm/drmP.h>
+#include "drm_legacy.h"
+
+struct drm_ctx_list {
+ struct list_head head;
+ drm_context_t handle;
+ struct drm_file *tag;
+};
/******************************************************************/
/** \name Context bitmap support */
@@ -56,7 +51,7 @@
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
-void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
+void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
{
mutex_lock(&dev->struct_mutex);
idr_remove(&dev->ctx_idr, ctx_handle);
@@ -72,7 +67,7 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
* Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
-static int drm_ctxbitmap_next(struct drm_device * dev)
+static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
{
int ret;
@@ -90,7 +85,7 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
*
* Initialise the drm_device::ctx_idr
*/
-int drm_ctxbitmap_init(struct drm_device * dev)
+int drm_legacy_ctxbitmap_init(struct drm_device * dev)
{
idr_init(&dev->ctx_idr);
return 0;
@@ -104,13 +99,43 @@ int drm_ctxbitmap_init(struct drm_device * dev)
* Free all idr members using drm_ctx_sarea_free helper function
* while holding the drm_device::struct_mutex lock.
*/
-void drm_ctxbitmap_cleanup(struct drm_device * dev)
+void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
{
mutex_lock(&dev->struct_mutex);
idr_destroy(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
+/**
+ * drm_ctxbitmap_flush() - Flush all contexts owned by a file
+ * @dev: DRM device to operate on
+ * @file: Open file to flush contexts for
+ *
+ * This iterates over all contexts on @dev and drops them if they're owned by
+ * @file. Note that after this call returns, new contexts might be added if
+ * the file is still alive.
+ */
+void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
+{
+ struct drm_ctx_list *pos, *tmp;
+
+ mutex_lock(&dev->ctxlist_mutex);
+
+ list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
+ if (pos->tag == file &&
+ pos->handle != DRM_KERNEL_CONTEXT) {
+ if (dev->driver->context_dtor)
+ dev->driver->context_dtor(dev, pos->handle);
+
+ drm_legacy_ctxbitmap_free(dev, pos->handle);
+ list_del(&pos->head);
+ kfree(pos);
+ }
+ }
+
+ mutex_unlock(&dev->ctxlist_mutex);
+}
+
/*@}*/
/******************************************************************/
@@ -129,8 +154,8 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
* Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
-int drm_getsareactx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_getsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
struct drm_local_map *map;
@@ -173,8 +198,8 @@ int drm_getsareactx(struct drm_device *dev, void *data,
* Searches the mapping specified in \p arg and update the entry in
* drm_device::ctx_idr with it.
*/
-int drm_setsareactx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_setsareactx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
struct drm_local_map *map = NULL;
@@ -273,8 +298,8 @@ static int drm_context_switch_complete(struct drm_device *dev,
* \param arg user argument pointing to a drm_ctx_res structure.
* \return zero on success or a negative number on failure.
*/
-int drm_resctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_resctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx_res *res = data;
struct drm_ctx ctx;
@@ -304,16 +329,16 @@ int drm_resctx(struct drm_device *dev, void *data,
*
* Get a new handle for the context and copy to userspace.
*/
-int drm_addctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_addctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx_list *ctx_entry;
struct drm_ctx *ctx = data;
- ctx->handle = drm_ctxbitmap_next(dev);
+ ctx->handle = drm_legacy_ctxbitmap_next(dev);
if (ctx->handle == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
- ctx->handle = drm_ctxbitmap_next(dev);
+ ctx->handle = drm_legacy_ctxbitmap_next(dev);
}
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle == -1) {
@@ -348,7 +373,8 @@ int drm_addctx(struct drm_device *dev, void *data,
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*/
-int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int drm_legacy_getctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
@@ -369,8 +395,8 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
*
* Calls context_switch().
*/
-int drm_switchctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_switchctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
@@ -389,8 +415,8 @@ int drm_switchctx(struct drm_device *dev, void *data,
*
* Calls context_switch_complete().
*/
-int drm_newctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_newctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
@@ -411,8 +437,8 @@ int drm_newctx(struct drm_device *dev, void *data,
*
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
*/
-int drm_rmctx(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+int drm_legacy_rmctx(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
@@ -420,7 +446,7 @@ int drm_rmctx(struct drm_device *dev, void *data,
if (ctx->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx->handle);
- drm_ctxbitmap_free(dev, ctx->handle);
+ drm_legacy_ctxbitmap_free(dev, ctx->handle);
}
mutex_lock(&dev->ctxlist_mutex);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index fe94cc10cd35..fa2be249999c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -41,6 +41,10 @@
#include "drm_crtc_internal.h"
+static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *r,
+ struct drm_file *file_priv);
+
/**
* drm_modeset_lock_all - take all modeset locks
* @dev: drm device
@@ -178,6 +182,12 @@ static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
};
+static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
+ { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
+ { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
+ { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
+};
+
/*
* Non-global properties, but "required" for certain connectors.
*/
@@ -357,6 +367,32 @@ const char *drm_get_format_name(uint32_t format)
}
EXPORT_SYMBOL(drm_get_format_name);
+/*
+ * Internal function to assign a slot in the object idr and optionally
+ * register the object into the idr.
+ */
+static int drm_mode_object_get_reg(struct drm_device *dev,
+ struct drm_mode_object *obj,
+ uint32_t obj_type,
+ bool register_obj)
+{
+ int ret;
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+ ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
+ if (ret >= 0) {
+ /*
+ * Set up the object linking under the protection of the idr
+ * lock so that other users can't see inconsistent state.
+ */
+ obj->id = ret;
+ obj->type = obj_type;
+ }
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return ret < 0 ? ret : 0;
+}
+
/**
* drm_mode_object_get - allocate a new modeset identifier
* @dev: DRM device
@@ -375,21 +411,15 @@ EXPORT_SYMBOL(drm_get_format_name);
int drm_mode_object_get(struct drm_device *dev,
struct drm_mode_object *obj, uint32_t obj_type)
{
- int ret;
+ return drm_mode_object_get_reg(dev, obj, obj_type, true);
+}
+static void drm_mode_object_register(struct drm_device *dev,
+ struct drm_mode_object *obj)
+{
mutex_lock(&dev->mode_config.idr_mutex);
- ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL);
- if (ret >= 0) {
- /*
- * Set up the object linking under the protection of the idr
- * lock so that other users can't see inconsistent state.
- */
- obj->id = ret;
- obj->type = obj_type;
- }
+ idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
mutex_unlock(&dev->mode_config.idr_mutex);
-
- return ret < 0 ? ret : 0;
}
/**
@@ -416,8 +446,12 @@ static struct drm_mode_object *_object_find(struct drm_device *dev,
mutex_lock(&dev->mode_config.idr_mutex);
obj = idr_find(&dev->mode_config.crtc_idr, id);
- if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
- (obj->id != id))
+ if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
+ obj = NULL;
+ if (obj && obj->id != id)
+ obj = NULL;
+ /* don't leak out unref'd fb's */
+ if (obj && (obj->type == DRM_MODE_OBJECT_FB))
obj = NULL;
mutex_unlock(&dev->mode_config.idr_mutex);
@@ -444,9 +478,6 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
* function.*/
WARN_ON(type == DRM_MODE_OBJECT_FB);
obj = _object_find(dev, id, type);
- /* don't leak out unref'd fb's */
- if (obj && (obj->type == DRM_MODE_OBJECT_FB))
- obj = NULL;
return obj;
}
EXPORT_SYMBOL(drm_mode_object_find);
@@ -723,7 +754,7 @@ DEFINE_WW_CLASS(crtc_ww_class);
*/
int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_plane *primary,
- void *cursor,
+ struct drm_plane *cursor,
const struct drm_crtc_funcs *funcs)
{
struct drm_mode_config *config = &dev->mode_config;
@@ -748,8 +779,11 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
config->num_crtc++;
crtc->primary = primary;
+ crtc->cursor = cursor;
if (primary)
primary->possible_crtcs = 1 << drm_crtc_index(crtc);
+ if (cursor)
+ cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
out:
drm_modeset_unlock_all(dev);
@@ -842,7 +876,7 @@ int drm_connector_init(struct drm_device *dev,
drm_modeset_lock_all(dev);
- ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
+ ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false);
if (ret)
goto out_unlock;
@@ -881,6 +915,8 @@ int drm_connector_init(struct drm_device *dev,
drm_object_attach_property(&connector->base,
dev->mode_config.dpms_property, 0);
+ connector->debugfs_entry = NULL;
+
out_put:
if (ret)
drm_mode_object_put(dev, &connector->base);
@@ -921,6 +957,49 @@ void drm_connector_cleanup(struct drm_connector *connector)
EXPORT_SYMBOL(drm_connector_cleanup);
/**
+ * drm_connector_register - register a connector
+ * @connector: the connector to register
+ *
+ * Register userspace interfaces for a connector
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_register(struct drm_connector *connector)
+{
+ int ret;
+
+ drm_mode_object_register(connector->dev, &connector->base);
+
+ ret = drm_sysfs_connector_add(connector);
+ if (ret)
+ return ret;
+
+ ret = drm_debugfs_connector_add(connector);
+ if (ret) {
+ drm_sysfs_connector_remove(connector);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_register);
+
+/**
+ * drm_connector_unregister - unregister a connector
+ * @connector: the connector to unregister
+ *
+ * Unregister userspace interfaces for a connector
+ */
+void drm_connector_unregister(struct drm_connector *connector)
+{
+ drm_sysfs_connector_remove(connector);
+ drm_debugfs_connector_remove(connector);
+}
+EXPORT_SYMBOL(drm_connector_unregister);
+
+
+/**
* drm_connector_unplug_all - unregister connector userspace interfaces
* @dev: drm device
*
@@ -934,7 +1013,7 @@ void drm_connector_unplug_all(struct drm_device *dev)
/* taking the mode config mutex ends up in a clash with sysfs */
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
}
EXPORT_SYMBOL(drm_connector_unplug_all);
@@ -1214,6 +1293,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
{
struct drm_property *edid;
struct drm_property *dpms;
+ struct drm_property *dev_path;
/*
* Standard properties (apply to all connectors)
@@ -1228,6 +1308,12 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
ARRAY_SIZE(drm_dpms_enum_list));
dev->mode_config.dpms_property = dpms;
+ dev_path = drm_property_create(dev,
+ DRM_MODE_PROP_BLOB |
+ DRM_MODE_PROP_IMMUTABLE,
+ "PATH", 0);
+ dev->mode_config.path_property = dev_path;
+
return 0;
}
@@ -1384,6 +1470,33 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev)
EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
/**
+ * drm_mode_create_aspect_ratio_property - create aspect ratio property
+ * @dev: DRM device
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * connectors.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
+{
+ if (dev->mode_config.aspect_ratio_property)
+ return 0;
+
+ dev->mode_config.aspect_ratio_property =
+ drm_property_create_enum(dev, 0, "aspect ratio",
+ drm_aspect_ratio_enum_list,
+ ARRAY_SIZE(drm_aspect_ratio_enum_list));
+
+ if (dev->mode_config.aspect_ratio_property == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
+
+/**
* drm_mode_create_dirty_property - create dirty property
* @dev: DRM device
*
@@ -1470,6 +1583,15 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
+void drm_reinit_primary_mode_group(struct drm_device *dev)
+{
+ drm_modeset_lock_all(dev);
+ drm_mode_group_destroy(&dev->primary->mode_group);
+ drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
+ drm_modeset_unlock_all(dev);
+}
+EXPORT_SYMBOL(drm_reinit_primary_mode_group);
+
/**
* drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
* @out: drm_mode_modeinfo struct to return to the user
@@ -2118,45 +2240,32 @@ out:
return ret;
}
-/**
- * drm_mode_setplane - configure a plane's configuration
- * @dev: DRM device
- * @data: ioctl data*
- * @file_priv: DRM file info
+/*
+ * setplane_internal - setplane handler for internal callers
*
- * Set plane configuration, including placement, fb, scaling, and other factors.
- * Or pass a NULL fb to disable.
+ * Note that we assume an extra reference has already been taken on fb. If the
+ * update fails, this reference will be dropped before return; if it succeeds,
+ * the previous framebuffer (if any) will be unreferenced instead.
*
- * Returns:
- * Zero on success, errno on failure.
+ * src_{x,y,w,h} are provided in 16.16 fixed point format
*/
-int drm_mode_setplane(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static int setplane_internal(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ int32_t crtc_x, int32_t crtc_y,
+ uint32_t crtc_w, uint32_t crtc_h,
+ /* src_{x,y,w,h} values are 16.16 fixed point */
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
{
- struct drm_mode_set_plane *plane_req = data;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- struct drm_framebuffer *fb = NULL, *old_fb = NULL;
+ struct drm_device *dev = plane->dev;
+ struct drm_framebuffer *old_fb = NULL;
int ret = 0;
unsigned int fb_width, fb_height;
int i;
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return -EINVAL;
-
- /*
- * First, find the plane, crtc, and fb objects. If not available,
- * we don't bother to call the driver.
- */
- plane = drm_plane_find(dev, plane_req->plane_id);
- if (!plane) {
- DRM_DEBUG_KMS("Unknown plane ID %d\n",
- plane_req->plane_id);
- return -ENOENT;
- }
-
/* No fb means shut it down */
- if (!plane_req->fb_id) {
+ if (!fb) {
drm_modeset_lock_all(dev);
old_fb = plane->fb;
ret = plane->funcs->disable_plane(plane);
@@ -2170,14 +2279,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
goto out;
}
- crtc = drm_crtc_find(dev, plane_req->crtc_id);
- if (!crtc) {
- DRM_DEBUG_KMS("Unknown crtc ID %d\n",
- plane_req->crtc_id);
- ret = -ENOENT;
- goto out;
- }
-
/* Check whether this plane is usable on this CRTC */
if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
DRM_DEBUG_KMS("Invalid crtc for plane\n");
@@ -2185,14 +2286,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
goto out;
}
- fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
- if (!fb) {
- DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
- plane_req->fb_id);
- ret = -ENOENT;
- goto out;
- }
-
/* Check whether this plane supports the fb pixel format. */
for (i = 0; i < plane->format_count; i++)
if (fb->pixel_format == plane->format_types[i])
@@ -2208,43 +2301,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
fb_height = fb->height << 16;
/* Make sure source coordinates are inside the fb. */
- if (plane_req->src_w > fb_width ||
- plane_req->src_x > fb_width - plane_req->src_w ||
- plane_req->src_h > fb_height ||
- plane_req->src_y > fb_height - plane_req->src_h) {
+ if (src_w > fb_width ||
+ src_x > fb_width - src_w ||
+ src_h > fb_height ||
+ src_y > fb_height - src_h) {
DRM_DEBUG_KMS("Invalid source coordinates "
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
- plane_req->src_w >> 16,
- ((plane_req->src_w & 0xffff) * 15625) >> 10,
- plane_req->src_h >> 16,
- ((plane_req->src_h & 0xffff) * 15625) >> 10,
- plane_req->src_x >> 16,
- ((plane_req->src_x & 0xffff) * 15625) >> 10,
- plane_req->src_y >> 16,
- ((plane_req->src_y & 0xffff) * 15625) >> 10);
+ src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
+ src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
+ src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
+ src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
ret = -ENOSPC;
goto out;
}
- /* Give drivers some help against integer overflows */
- if (plane_req->crtc_w > INT_MAX ||
- plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
- plane_req->crtc_h > INT_MAX ||
- plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
- DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
- plane_req->crtc_w, plane_req->crtc_h,
- plane_req->crtc_x, plane_req->crtc_y);
- ret = -ERANGE;
- goto out;
- }
-
drm_modeset_lock_all(dev);
old_fb = plane->fb;
ret = plane->funcs->update_plane(plane, crtc, fb,
- plane_req->crtc_x, plane_req->crtc_y,
- plane_req->crtc_w, plane_req->crtc_h,
- plane_req->src_x, plane_req->src_y,
- plane_req->src_w, plane_req->src_h);
+ crtc_x, crtc_y, crtc_w, crtc_h,
+ src_x, src_y, src_w, src_h);
if (!ret) {
plane->crtc = crtc;
plane->fb = fb;
@@ -2261,6 +2336,85 @@ out:
drm_framebuffer_unreference(old_fb);
return ret;
+
+}
+
+/**
+ * drm_mode_setplane - configure a plane's configuration
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_priv: DRM file info
+ *
+ * Set plane configuration, including placement, fb, scaling, and other factors.
+ * Or pass a NULL fb to disable (planes may be disabled without providing a
+ * valid crtc).
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_setplane(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_set_plane *plane_req = data;
+ struct drm_mode_object *obj;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc = NULL;
+ struct drm_framebuffer *fb = NULL;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ /* Give drivers some help against integer overflows */
+ if (plane_req->crtc_w > INT_MAX ||
+ plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
+ plane_req->crtc_h > INT_MAX ||
+ plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
+ DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
+ plane_req->crtc_w, plane_req->crtc_h,
+ plane_req->crtc_x, plane_req->crtc_y);
+ return -ERANGE;
+ }
+
+ /*
+ * First, find the plane, crtc, and fb objects. If not available,
+ * we don't bother to call the driver.
+ */
+ obj = drm_mode_object_find(dev, plane_req->plane_id,
+ DRM_MODE_OBJECT_PLANE);
+ if (!obj) {
+ DRM_DEBUG_KMS("Unknown plane ID %d\n",
+ plane_req->plane_id);
+ return -ENOENT;
+ }
+ plane = obj_to_plane(obj);
+
+ if (plane_req->fb_id) {
+ fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
+ if (!fb) {
+ DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+ plane_req->fb_id);
+ return -ENOENT;
+ }
+
+ obj = drm_mode_object_find(dev, plane_req->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
+ if (!obj) {
+ DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+ plane_req->crtc_id);
+ return -ENOENT;
+ }
+ crtc = obj_to_crtc(obj);
+ }
+
+ /*
+ * setplane_internal will take care of deref'ing either the old or new
+ * framebuffer depending on success.
+ */
+ return setplane_internal(plane, crtc, fb,
+ plane_req->crtc_x, plane_req->crtc_y,
+ plane_req->crtc_w, plane_req->crtc_h,
+ plane_req->src_x, plane_req->src_y,
+ plane_req->src_w, plane_req->src_h);
}
/**
@@ -2509,6 +2663,102 @@ out:
return ret;
}
+/**
+ * drm_mode_cursor_universal - translate legacy cursor ioctl call into a
+ * universal plane handler call
+ * @crtc: crtc to update cursor for
+ * @req: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Legacy cursor ioctl's work directly with driver buffer handles. To
+ * translate legacy ioctl calls into universal plane handler calls, we need to
+ * wrap the native buffer handle in a drm_framebuffer.
+ *
+ * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB
+ * buffer with a pitch of 4*width; the universal plane interface should be used
+ * directly in cases where the hardware can support other buffer settings and
+ * userspace wants to make use of these capabilities.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+static int drm_mode_cursor_universal(struct drm_crtc *crtc,
+ struct drm_mode_cursor2 *req,
+ struct drm_file *file_priv)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_framebuffer *fb = NULL;
+ struct drm_mode_fb_cmd2 fbreq = {
+ .width = req->width,
+ .height = req->height,
+ .pixel_format = DRM_FORMAT_ARGB8888,
+ .pitches = { req->width * 4 },
+ .handles = { req->handle },
+ };
+ int32_t crtc_x, crtc_y;
+ uint32_t crtc_w = 0, crtc_h = 0;
+ uint32_t src_w = 0, src_h = 0;
+ int ret = 0;
+
+ BUG_ON(!crtc->cursor);
+
+ /*
+ * Obtain fb we'll be using (either new or existing) and take an extra
+ * reference to it if fb != null. setplane will take care of dropping
+ * the reference if the plane update fails.
+ */
+ if (req->flags & DRM_MODE_CURSOR_BO) {
+ if (req->handle) {
+ fb = add_framebuffer_internal(dev, &fbreq, file_priv);
+ if (IS_ERR(fb)) {
+ DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
+ return PTR_ERR(fb);
+ }
+
+ drm_framebuffer_reference(fb);
+ } else {
+ fb = NULL;
+ }
+ } else {
+ mutex_lock(&dev->mode_config.mutex);
+ fb = crtc->cursor->fb;
+ if (fb)
+ drm_framebuffer_reference(fb);
+ mutex_unlock(&dev->mode_config.mutex);
+ }
+
+ if (req->flags & DRM_MODE_CURSOR_MOVE) {
+ crtc_x = req->x;
+ crtc_y = req->y;
+ } else {
+ crtc_x = crtc->cursor_x;
+ crtc_y = crtc->cursor_y;
+ }
+
+ if (fb) {
+ crtc_w = fb->width;
+ crtc_h = fb->height;
+ src_w = fb->width << 16;
+ src_h = fb->height << 16;
+ }
+
+ /*
+ * setplane_internal will take care of deref'ing either the old or new
+ * framebuffer depending on success.
+ */
+ ret = setplane_internal(crtc->cursor, crtc, fb,
+ crtc_x, crtc_y, crtc_w, crtc_h,
+ 0, 0, src_w, src_h);
+
+ /* Update successful; save new cursor position, if necessary */
+ if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
+ crtc->cursor_x = req->x;
+ crtc->cursor_y = req->y;
+ }
+
+ return ret;
+}
+
static int drm_mode_cursor_common(struct drm_device *dev,
struct drm_mode_cursor2 *req,
struct drm_file *file_priv)
@@ -2528,6 +2778,13 @@ static int drm_mode_cursor_common(struct drm_device *dev,
return -ENOENT;
}
+ /*
+ * If this crtc has a universal cursor plane, call that plane's update
+ * handler rather than using legacy cursor handlers.
+ */
+ if (crtc->cursor)
+ return drm_mode_cursor_universal(crtc, req, file_priv);
+
drm_modeset_lock(&crtc->mutex, NULL);
if (req->flags & DRM_MODE_CURSOR_BO) {
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
@@ -2827,56 +3084,38 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
return 0;
}
-/**
- * drm_mode_addfb2 - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request with format. This is
- * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
- * and uses fourcc codes as pixel format specifiers.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, errno on failure.
- */
-int drm_mode_addfb2(struct drm_device *dev,
- void *data, struct drm_file *file_priv)
+static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *r,
+ struct drm_file *file_priv)
{
- struct drm_mode_fb_cmd2 *r = data;
struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb;
int ret;
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- return -EINVAL;
-
if (r->flags & ~DRM_MODE_FB_INTERLACED) {
DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
if ((config->min_width > r->width) || (r->width > config->max_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
r->width, config->min_width, config->max_width);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
if ((config->min_height > r->height) || (r->height > config->max_height)) {
DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
r->height, config->min_height, config->max_height);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
ret = framebuffer_check(r);
if (ret)
- return ret;
+ return ERR_PTR(ret);
fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
if (IS_ERR(fb)) {
DRM_DEBUG_KMS("could not create framebuffer\n");
- return PTR_ERR(fb);
+ return fb;
}
mutex_lock(&file_priv->fbs_lock);
@@ -2885,8 +3124,37 @@ int drm_mode_addfb2(struct drm_device *dev,
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
mutex_unlock(&file_priv->fbs_lock);
+ return fb;
+}
- return ret;
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request with format. This is
+ * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
+ * and uses fourcc codes as pixel format specifiers.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_framebuffer *fb;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ fb = add_framebuffer_internal(dev, data, file_priv);
+ if (IS_ERR(fb))
+ return PTR_ERR(fb);
+
+ return 0;
}
/**
@@ -3176,7 +3444,7 @@ fail:
EXPORT_SYMBOL(drm_property_create);
/**
- * drm_property_create - create a new enumeration property type
+ * drm_property_create_enum - create a new enumeration property type
* @dev: drm device
* @flags: flags specifying the property type
* @name: name of the property
@@ -3222,7 +3490,7 @@ struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
EXPORT_SYMBOL(drm_property_create_enum);
/**
- * drm_property_create - create a new bitmask property type
+ * drm_property_create_bitmask - create a new bitmask property type
* @dev: drm device
* @flags: flags specifying the property type
* @name: name of the property
@@ -3242,19 +3510,28 @@ EXPORT_SYMBOL(drm_property_create_enum);
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
int flags, const char *name,
const struct drm_prop_enum_list *props,
- int num_values)
+ int num_props,
+ uint64_t supported_bits)
{
struct drm_property *property;
- int i, ret;
+ int i, ret, index = 0;
+ int num_values = hweight64(supported_bits);
flags |= DRM_MODE_PROP_BITMASK;
property = drm_property_create(dev, flags, name, num_values);
if (!property)
return NULL;
+ for (i = 0; i < num_props; i++) {
+ if (!(supported_bits & (1ULL << props[i].type)))
+ continue;
- for (i = 0; i < num_values; i++) {
- ret = drm_property_add_enum(property, i,
+ if (WARN_ON(index >= num_values)) {
+ drm_property_destroy(dev, property);
+ return NULL;
+ }
+
+ ret = drm_property_add_enum(property, index++,
props[i].type,
props[i].name);
if (ret) {
@@ -3284,7 +3561,7 @@ static struct drm_property *property_create_range(struct drm_device *dev,
}
/**
- * drm_property_create - create a new ranged property type
+ * drm_property_create_range - create a new ranged property type
* @dev: drm device
* @flags: flags specifying the property type
* @name: name of the property
@@ -3703,6 +3980,25 @@ done:
return ret;
}
+int drm_mode_connector_set_path_property(struct drm_connector *connector,
+ char *path)
+{
+ struct drm_device *dev = connector->dev;
+ int ret, size;
+ size = strlen(path) + 1;
+
+ connector->path_blob_ptr = drm_property_create_blob(connector->dev,
+ size, path);
+ if (!connector->path_blob_ptr)
+ return -EINVAL;
+
+ ret = drm_object_property_set_value(&connector->base,
+ dev->mode_config.path_property,
+ connector->path_blob_ptr->base.id);
+ return ret;
+}
+EXPORT_SYMBOL(drm_mode_connector_set_path_property);
+
/**
* drm_mode_connector_update_edid_property - update the edid property of a connector
* @connector: drm connector
@@ -3720,6 +4016,10 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct drm_device *dev = connector->dev;
int ret, size;
+ /* ignore requests to set edid when overridden */
+ if (connector->override_edid)
+ return 0;
+
if (connector->edid_blob_ptr)
drm_property_destroy_blob(dev, connector->edid_blob_ptr);
@@ -4680,6 +4980,36 @@ int drm_format_vert_chroma_subsampling(uint32_t format)
EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
/**
+ * drm_rotation_simplify() - Try to simplify the rotation
+ * @rotation: Rotation to be simplified
+ * @supported_rotations: Supported rotations
+ *
+ * Attempt to simplify the rotation to a form that is supported.
+ * Eg. if the hardware supports everything except DRM_REFLECT_X
+ * one could call this function like this:
+ *
+ * drm_rotation_simplify(rotation, BIT(DRM_ROTATE_0) |
+ * BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) |
+ * BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_Y));
+ *
+ * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
+ * transforms the hardware supports, this function may not
+ * be able to produce a supported transform, so the caller should
+ * check the result afterwards.
+ */
+unsigned int drm_rotation_simplify(unsigned int rotation,
+ unsigned int supported_rotations)
+{
+ if (rotation & ~supported_rotations) {
+ rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y);
+ rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4);
+ }
+
+ return rotation;
+}
+EXPORT_SYMBOL(drm_rotation_simplify);
+
+/**
* drm_mode_config_init - initialize DRM mode_configuration structure
* @dev: DRM device
*
@@ -4797,3 +5127,21 @@ void drm_mode_config_cleanup(struct drm_device *dev)
drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
}
EXPORT_SYMBOL(drm_mode_config_cleanup);
+
+struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
+ unsigned int supported_rotations)
+{
+ static const struct drm_prop_enum_list props[] = {
+ { DRM_ROTATE_0, "rotate-0" },
+ { DRM_ROTATE_90, "rotate-90" },
+ { DRM_ROTATE_180, "rotate-180" },
+ { DRM_ROTATE_270, "rotate-270" },
+ { DRM_REFLECT_X, "reflect-x" },
+ { DRM_REFLECT_Y, "reflect-y" },
+ };
+
+ return drm_property_create_bitmask(dev, 0, "rotation",
+ props, ARRAY_SIZE(props),
+ supported_rotations);
+}
+EXPORT_SYMBOL(drm_mode_create_rotation_property);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 78b37f3febd3..6c65a0a28fbd 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -818,6 +818,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
&fb->bits_per_pixel);
fb->pixel_format = mode_cmd->pixel_format;
+ fb->flags = mode_cmd->flags;
}
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index b4b51d46f339..13bd42923dd4 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/export.h>
#include <drm/drmP.h>
+#include <drm/drm_edid.h>
#if defined(CONFIG_DEBUG_FS)
@@ -237,5 +238,186 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
return 0;
}
+static int connector_show(struct seq_file *m, void *data)
+{
+ struct drm_connector *connector = m->private;
+ const char *status;
+
+ switch (connector->force) {
+ case DRM_FORCE_ON:
+ status = "on\n";
+ break;
+
+ case DRM_FORCE_ON_DIGITAL:
+ status = "digital\n";
+ break;
+
+ case DRM_FORCE_OFF:
+ status = "off\n";
+ break;
+
+ case DRM_FORCE_UNSPECIFIED:
+ status = "unspecified\n";
+ break;
+
+ default:
+ return 0;
+ }
+
+ seq_puts(m, status);
+
+ return 0;
+}
+
+static int connector_open(struct inode *inode, struct file *file)
+{
+ struct drm_connector *dev = inode->i_private;
+
+ return single_open(file, connector_show, dev);
+}
+
+static ssize_t connector_write(struct file *file, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_connector *connector = m->private;
+ char buf[12];
+
+ if (len > sizeof(buf) - 1)
+ return -EINVAL;
+
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+
+ buf[len] = '\0';
+
+ if (!strcmp(buf, "on"))
+ connector->force = DRM_FORCE_ON;
+ else if (!strcmp(buf, "digital"))
+ connector->force = DRM_FORCE_ON_DIGITAL;
+ else if (!strcmp(buf, "off"))
+ connector->force = DRM_FORCE_OFF;
+ else if (!strcmp(buf, "unspecified"))
+ connector->force = DRM_FORCE_UNSPECIFIED;
+ else
+ return -EINVAL;
+
+ return len;
+}
+
+static int edid_show(struct seq_file *m, void *data)
+{
+ struct drm_connector *connector = m->private;
+ struct drm_property_blob *edid = connector->edid_blob_ptr;
+
+ if (connector->override_edid && edid)
+ seq_write(m, edid->data, edid->length);
+
+ return 0;
+}
+
+static int edid_open(struct inode *inode, struct file *file)
+{
+ struct drm_connector *dev = inode->i_private;
+
+ return single_open(file, edid_show, dev);
+}
+
+static ssize_t edid_write(struct file *file, const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_connector *connector = m->private;
+ char *buf;
+ struct edid *edid;
+ int ret;
+
+ buf = memdup_user(ubuf, len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ edid = (struct edid *) buf;
+
+ if (len == 5 && !strncmp(buf, "reset", 5)) {
+ connector->override_edid = false;
+ ret = drm_mode_connector_update_edid_property(connector, NULL);
+ } else if (len < EDID_LENGTH ||
+ EDID_LENGTH * (1 + edid->extensions) > len)
+ ret = -EINVAL;
+ else {
+ connector->override_edid = false;
+ ret = drm_mode_connector_update_edid_property(connector, edid);
+ if (!ret)
+ connector->override_edid = true;
+ }
+
+ kfree(buf);
+
+ return (ret) ? ret : len;
+}
+
+static const struct file_operations drm_edid_fops = {
+ .owner = THIS_MODULE,
+ .open = edid_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = edid_write
+};
+
+
+static const struct file_operations drm_connector_fops = {
+ .owner = THIS_MODULE,
+ .open = connector_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = connector_write
+};
+
+int drm_debugfs_connector_add(struct drm_connector *connector)
+{
+ struct drm_minor *minor = connector->dev->primary;
+ struct dentry *root, *ent;
+
+ if (!minor->debugfs_root)
+ return -1;
+
+ root = debugfs_create_dir(connector->name, minor->debugfs_root);
+ if (!root)
+ return -ENOMEM;
+
+ connector->debugfs_entry = root;
+
+ /* force */
+ ent = debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
+ &drm_connector_fops);
+ if (!ent)
+ goto error;
+
+ /* edid */
+ ent = debugfs_create_file("edid_override", S_IRUGO | S_IWUSR, root,
+ connector, &drm_edid_fops);
+ if (!ent)
+ goto error;
+
+ return 0;
+
+error:
+ debugfs_remove_recursive(connector->debugfs_entry);
+ connector->debugfs_entry = NULL;
+ return -ENOMEM;
+}
+
+void drm_debugfs_connector_remove(struct drm_connector *connector)
+{
+ if (!connector->debugfs_entry)
+ return;
+
+ debugfs_remove_recursive(connector->debugfs_entry);
+
+ connector->debugfs_entry = NULL;
+}
+
#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
new file mode 100644
index 000000000000..ac3c2738db94
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -0,0 +1,2715 @@
+/*
+ * Copyright © 2014 Red Hat
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/i2c.h>
+#include <drm/drm_dp_mst_helper.h>
+#include <drm/drmP.h>
+
+#include <drm/drm_fixed.h>
+
+/**
+ * DOC: dp mst helper
+ *
+ * These functions contain parts of the DisplayPort 1.2a MultiStream Transport
+ * protocol. The helpers contain a topology manager and bandwidth manager.
+ * The helpers encapsulate the sending and received of sideband msgs.
+ */
+static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
+ char *buf);
+static int test_calc_pbn_mode(void);
+
+static void drm_dp_put_port(struct drm_dp_mst_port *port);
+
+static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
+ int id,
+ struct drm_dp_payload *payload);
+
+static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int offset, int size, u8 *bytes);
+
+static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb);
+static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb,
+ struct drm_dp_mst_port *port);
+static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
+ u8 *guid);
+
+static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
+static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
+static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
+/* sideband msg handling */
+static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t num_nibbles)
+{
+ u8 bitmask = 0x80;
+ u8 bitshift = 7;
+ u8 array_index = 0;
+ int number_of_bits = num_nibbles * 4;
+ u8 remainder = 0;
+
+ while (number_of_bits != 0) {
+ number_of_bits--;
+ remainder <<= 1;
+ remainder |= (data[array_index] & bitmask) >> bitshift;
+ bitmask >>= 1;
+ bitshift--;
+ if (bitmask == 0) {
+ bitmask = 0x80;
+ bitshift = 7;
+ array_index++;
+ }
+ if ((remainder & 0x10) == 0x10)
+ remainder ^= 0x13;
+ }
+
+ number_of_bits = 4;
+ while (number_of_bits != 0) {
+ number_of_bits--;
+ remainder <<= 1;
+ if ((remainder & 0x10) != 0)
+ remainder ^= 0x13;
+ }
+
+ return remainder;
+}
+
+static u8 drm_dp_msg_data_crc4(const uint8_t *data, u8 number_of_bytes)
+{
+ u8 bitmask = 0x80;
+ u8 bitshift = 7;
+ u8 array_index = 0;
+ int number_of_bits = number_of_bytes * 8;
+ u16 remainder = 0;
+
+ while (number_of_bits != 0) {
+ number_of_bits--;
+ remainder <<= 1;
+ remainder |= (data[array_index] & bitmask) >> bitshift;
+ bitmask >>= 1;
+ bitshift--;
+ if (bitmask == 0) {
+ bitmask = 0x80;
+ bitshift = 7;
+ array_index++;
+ }
+ if ((remainder & 0x100) == 0x100)
+ remainder ^= 0xd5;
+ }
+
+ number_of_bits = 8;
+ while (number_of_bits != 0) {
+ number_of_bits--;
+ remainder <<= 1;
+ if ((remainder & 0x100) != 0)
+ remainder ^= 0xd5;
+ }
+
+ return remainder & 0xff;
+}
+static inline u8 drm_dp_calc_sb_hdr_size(struct drm_dp_sideband_msg_hdr *hdr)
+{
+ u8 size = 3;
+ size += (hdr->lct / 2);
+ return size;
+}
+
+static void drm_dp_encode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
+ u8 *buf, int *len)
+{
+ int idx = 0;
+ int i;
+ u8 crc4;
+ buf[idx++] = ((hdr->lct & 0xf) << 4) | (hdr->lcr & 0xf);
+ for (i = 0; i < (hdr->lct / 2); i++)
+ buf[idx++] = hdr->rad[i];
+ buf[idx++] = (hdr->broadcast << 7) | (hdr->path_msg << 6) |
+ (hdr->msg_len & 0x3f);
+ buf[idx++] = (hdr->somt << 7) | (hdr->eomt << 6) | (hdr->seqno << 4);
+
+ crc4 = drm_dp_msg_header_crc4(buf, (idx * 2) - 1);
+ buf[idx - 1] |= (crc4 & 0xf);
+
+ *len = idx;
+}
+
+static bool drm_dp_decode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
+ u8 *buf, int buflen, u8 *hdrlen)
+{
+ u8 crc4;
+ u8 len;
+ int i;
+ u8 idx;
+ if (buf[0] == 0)
+ return false;
+ len = 3;
+ len += ((buf[0] & 0xf0) >> 4) / 2;
+ if (len > buflen)
+ return false;
+ crc4 = drm_dp_msg_header_crc4(buf, (len * 2) - 1);
+
+ if ((crc4 & 0xf) != (buf[len - 1] & 0xf)) {
+ DRM_DEBUG_KMS("crc4 mismatch 0x%x 0x%x\n", crc4, buf[len - 1]);
+ return false;
+ }
+
+ hdr->lct = (buf[0] & 0xf0) >> 4;
+ hdr->lcr = (buf[0] & 0xf);
+ idx = 1;
+ for (i = 0; i < (hdr->lct / 2); i++)
+ hdr->rad[i] = buf[idx++];
+ hdr->broadcast = (buf[idx] >> 7) & 0x1;
+ hdr->path_msg = (buf[idx] >> 6) & 0x1;
+ hdr->msg_len = buf[idx] & 0x3f;
+ idx++;
+ hdr->somt = (buf[idx] >> 7) & 0x1;
+ hdr->eomt = (buf[idx] >> 6) & 0x1;
+ hdr->seqno = (buf[idx] >> 4) & 0x1;
+ idx++;
+ *hdrlen = idx;
+ return true;
+}
+
+static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req,
+ struct drm_dp_sideband_msg_tx *raw)
+{
+ int idx = 0;
+ int i;
+ u8 *buf = raw->msg;
+ buf[idx++] = req->req_type & 0x7f;
+
+ switch (req->req_type) {
+ case DP_ENUM_PATH_RESOURCES:
+ buf[idx] = (req->u.port_num.port_number & 0xf) << 4;
+ idx++;
+ break;
+ case DP_ALLOCATE_PAYLOAD:
+ buf[idx] = (req->u.allocate_payload.port_number & 0xf) << 4 |
+ (req->u.allocate_payload.number_sdp_streams & 0xf);
+ idx++;
+ buf[idx] = (req->u.allocate_payload.vcpi & 0x7f);
+ idx++;
+ buf[idx] = (req->u.allocate_payload.pbn >> 8);
+ idx++;
+ buf[idx] = (req->u.allocate_payload.pbn & 0xff);
+ idx++;
+ for (i = 0; i < req->u.allocate_payload.number_sdp_streams / 2; i++) {
+ buf[idx] = ((req->u.allocate_payload.sdp_stream_sink[i * 2] & 0xf) << 4) |
+ (req->u.allocate_payload.sdp_stream_sink[i * 2 + 1] & 0xf);
+ idx++;
+ }
+ if (req->u.allocate_payload.number_sdp_streams & 1) {
+ i = req->u.allocate_payload.number_sdp_streams - 1;
+ buf[idx] = (req->u.allocate_payload.sdp_stream_sink[i] & 0xf) << 4;
+ idx++;
+ }
+ break;
+ case DP_QUERY_PAYLOAD:
+ buf[idx] = (req->u.query_payload.port_number & 0xf) << 4;
+ idx++;
+ buf[idx] = (req->u.query_payload.vcpi & 0x7f);
+ idx++;
+ break;
+ case DP_REMOTE_DPCD_READ:
+ buf[idx] = (req->u.dpcd_read.port_number & 0xf) << 4;
+ buf[idx] |= ((req->u.dpcd_read.dpcd_address & 0xf0000) >> 16) & 0xf;
+ idx++;
+ buf[idx] = (req->u.dpcd_read.dpcd_address & 0xff00) >> 8;
+ idx++;
+ buf[idx] = (req->u.dpcd_read.dpcd_address & 0xff);
+ idx++;
+ buf[idx] = (req->u.dpcd_read.num_bytes);
+ idx++;
+ break;
+
+ case DP_REMOTE_DPCD_WRITE:
+ buf[idx] = (req->u.dpcd_write.port_number & 0xf) << 4;
+ buf[idx] |= ((req->u.dpcd_write.dpcd_address & 0xf0000) >> 16) & 0xf;
+ idx++;
+ buf[idx] = (req->u.dpcd_write.dpcd_address & 0xff00) >> 8;
+ idx++;
+ buf[idx] = (req->u.dpcd_write.dpcd_address & 0xff);
+ idx++;
+ buf[idx] = (req->u.dpcd_write.num_bytes);
+ idx++;
+ memcpy(&buf[idx], req->u.dpcd_write.bytes, req->u.dpcd_write.num_bytes);
+ idx += req->u.dpcd_write.num_bytes;
+ break;
+ case DP_REMOTE_I2C_READ:
+ buf[idx] = (req->u.i2c_read.port_number & 0xf) << 4;
+ buf[idx] |= (req->u.i2c_read.num_transactions & 0x3);
+ idx++;
+ for (i = 0; i < (req->u.i2c_read.num_transactions & 0x3); i++) {
+ buf[idx] = req->u.i2c_read.transactions[i].i2c_dev_id & 0x7f;
+ idx++;
+ buf[idx] = req->u.i2c_read.transactions[i].num_bytes;
+ idx++;
+ memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes);
+ idx += req->u.i2c_read.transactions[i].num_bytes;
+
+ buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5;
+ buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf);
+ idx++;
+ }
+ buf[idx] = (req->u.i2c_read.read_i2c_device_id) & 0x7f;
+ idx++;
+ buf[idx] = (req->u.i2c_read.num_bytes_read);
+ idx++;
+ break;
+
+ case DP_REMOTE_I2C_WRITE:
+ buf[idx] = (req->u.i2c_write.port_number & 0xf) << 4;
+ idx++;
+ buf[idx] = (req->u.i2c_write.write_i2c_device_id) & 0x7f;
+ idx++;
+ buf[idx] = (req->u.i2c_write.num_bytes);
+ idx++;
+ memcpy(&buf[idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes);
+ idx += req->u.i2c_write.num_bytes;
+ break;
+ }
+ raw->cur_len = idx;
+}
+
+static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len)
+{
+ u8 crc4;
+ crc4 = drm_dp_msg_data_crc4(msg, len);
+ msg[len] = crc4;
+}
+
+static void drm_dp_encode_sideband_reply(struct drm_dp_sideband_msg_reply_body *rep,
+ struct drm_dp_sideband_msg_tx *raw)
+{
+ int idx = 0;
+ u8 *buf = raw->msg;
+
+ buf[idx++] = (rep->reply_type & 0x1) << 7 | (rep->req_type & 0x7f);
+
+ raw->cur_len = idx;
+}
+
+/* this adds a chunk of msg to the builder to get the final msg */
+static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
+ u8 *replybuf, u8 replybuflen, bool hdr)
+{
+ int ret;
+ u8 crc4;
+
+ if (hdr) {
+ u8 hdrlen;
+ struct drm_dp_sideband_msg_hdr recv_hdr;
+ ret = drm_dp_decode_sideband_msg_hdr(&recv_hdr, replybuf, replybuflen, &hdrlen);
+ if (ret == false) {
+ print_hex_dump(KERN_DEBUG, "failed hdr", DUMP_PREFIX_NONE, 16, 1, replybuf, replybuflen, false);
+ return false;
+ }
+
+ /* get length contained in this portion */
+ msg->curchunk_len = recv_hdr.msg_len;
+ msg->curchunk_hdrlen = hdrlen;
+
+ /* we have already gotten an somt - don't bother parsing */
+ if (recv_hdr.somt && msg->have_somt)
+ return false;
+
+ if (recv_hdr.somt) {
+ memcpy(&msg->initial_hdr, &recv_hdr, sizeof(struct drm_dp_sideband_msg_hdr));
+ msg->have_somt = true;
+ }
+ if (recv_hdr.eomt)
+ msg->have_eomt = true;
+
+ /* copy the bytes for the remainder of this header chunk */
+ msg->curchunk_idx = min(msg->curchunk_len, (u8)(replybuflen - hdrlen));
+ memcpy(&msg->chunk[0], replybuf + hdrlen, msg->curchunk_idx);
+ } else {
+ memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen);
+ msg->curchunk_idx += replybuflen;
+ }
+
+ if (msg->curchunk_idx >= msg->curchunk_len) {
+ /* do CRC */
+ crc4 = drm_dp_msg_data_crc4(msg->chunk, msg->curchunk_len - 1);
+ /* copy chunk into bigger msg */
+ memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
+ msg->curlen += msg->curchunk_len - 1;
+ }
+ return true;
+}
+
+static bool drm_dp_sideband_parse_link_address(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ int i;
+ memcpy(repmsg->u.link_addr.guid, &raw->msg[idx], 16);
+ idx += 16;
+ repmsg->u.link_addr.nports = raw->msg[idx] & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ for (i = 0; i < repmsg->u.link_addr.nports; i++) {
+ if (raw->msg[idx] & 0x80)
+ repmsg->u.link_addr.ports[i].input_port = 1;
+
+ repmsg->u.link_addr.ports[i].peer_device_type = (raw->msg[idx] >> 4) & 0x7;
+ repmsg->u.link_addr.ports[i].port_number = (raw->msg[idx] & 0xf);
+
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.link_addr.ports[i].mcs = (raw->msg[idx] >> 7) & 0x1;
+ repmsg->u.link_addr.ports[i].ddps = (raw->msg[idx] >> 6) & 0x1;
+ if (repmsg->u.link_addr.ports[i].input_port == 0)
+ repmsg->u.link_addr.ports[i].legacy_device_plug_status = (raw->msg[idx] >> 5) & 0x1;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ if (repmsg->u.link_addr.ports[i].input_port == 0) {
+ repmsg->u.link_addr.ports[i].dpcd_revision = (raw->msg[idx]);
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ memcpy(repmsg->u.link_addr.ports[i].peer_guid, &raw->msg[idx], 16);
+ idx += 16;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.link_addr.ports[i].num_sdp_streams = (raw->msg[idx] >> 4) & 0xf;
+ repmsg->u.link_addr.ports[i].num_sdp_stream_sinks = (raw->msg[idx] & 0xf);
+ idx++;
+
+ }
+ if (idx > raw->curlen)
+ goto fail_len;
+ }
+
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("link address reply parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_remote_dpcd_read(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ repmsg->u.remote_dpcd_read_ack.port_number = raw->msg[idx] & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx];
+ if (idx > raw->curlen)
+ goto fail_len;
+
+ memcpy(repmsg->u.remote_dpcd_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_dpcd_read_ack.num_bytes);
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("link address reply parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_remote_dpcd_write(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ repmsg->u.remote_dpcd_write_ack.port_number = raw->msg[idx] & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_remote_i2c_read_ack(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+
+ repmsg->u.remote_i2c_read_ack.port_number = (raw->msg[idx] & 0xf);
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.remote_i2c_read_ack.num_bytes = raw->msg[idx];
+ idx++;
+ /* TODO check */
+ memcpy(repmsg->u.remote_i2c_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_i2c_read_ack.num_bytes);
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("remote i2c reply parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.path_resources.full_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+ idx += 2;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.path_resources.avail_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+ idx += 2;
+ if (idx > raw->curlen)
+ goto fail_len;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("enum resource parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_allocate_payload_ack(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ repmsg->u.allocate_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.allocate_payload.vcpi = raw->msg[idx];
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.allocate_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
+ idx += 2;
+ if (idx > raw->curlen)
+ goto fail_len;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("allocate payload parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *repmsg)
+{
+ int idx = 1;
+ repmsg->u.query_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+ repmsg->u.query_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
+ idx += 2;
+ if (idx > raw->curlen)
+ goto fail_len;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("query payload parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_reply_body *msg)
+{
+ memset(msg, 0, sizeof(*msg));
+ msg->reply_type = (raw->msg[0] & 0x80) >> 7;
+ msg->req_type = (raw->msg[0] & 0x7f);
+
+ if (msg->reply_type) {
+ memcpy(msg->u.nak.guid, &raw->msg[1], 16);
+ msg->u.nak.reason = raw->msg[17];
+ msg->u.nak.nak_data = raw->msg[18];
+ return false;
+ }
+
+ switch (msg->req_type) {
+ case DP_LINK_ADDRESS:
+ return drm_dp_sideband_parse_link_address(raw, msg);
+ case DP_QUERY_PAYLOAD:
+ return drm_dp_sideband_parse_query_payload_ack(raw, msg);
+ case DP_REMOTE_DPCD_READ:
+ return drm_dp_sideband_parse_remote_dpcd_read(raw, msg);
+ case DP_REMOTE_DPCD_WRITE:
+ return drm_dp_sideband_parse_remote_dpcd_write(raw, msg);
+ case DP_REMOTE_I2C_READ:
+ return drm_dp_sideband_parse_remote_i2c_read_ack(raw, msg);
+ case DP_ENUM_PATH_RESOURCES:
+ return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg);
+ case DP_ALLOCATE_PAYLOAD:
+ return drm_dp_sideband_parse_allocate_payload_ack(raw, msg);
+ default:
+ DRM_ERROR("Got unknown reply 0x%02x\n", msg->req_type);
+ return false;
+ }
+}
+
+static bool drm_dp_sideband_parse_connection_status_notify(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_req_body *msg)
+{
+ int idx = 1;
+
+ msg->u.conn_stat.port_number = (raw->msg[idx] & 0xf0) >> 4;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+
+ memcpy(msg->u.conn_stat.guid, &raw->msg[idx], 16);
+ idx += 16;
+ if (idx > raw->curlen)
+ goto fail_len;
+
+ msg->u.conn_stat.legacy_device_plug_status = (raw->msg[idx] >> 6) & 0x1;
+ msg->u.conn_stat.displayport_device_plug_status = (raw->msg[idx] >> 5) & 0x1;
+ msg->u.conn_stat.message_capability_status = (raw->msg[idx] >> 4) & 0x1;
+ msg->u.conn_stat.input_port = (raw->msg[idx] >> 3) & 0x1;
+ msg->u.conn_stat.peer_device_type = (raw->msg[idx] & 0x7);
+ idx++;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("connection status reply parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_resource_status_notify(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_req_body *msg)
+{
+ int idx = 1;
+
+ msg->u.resource_stat.port_number = (raw->msg[idx] & 0xf0) >> 4;
+ idx++;
+ if (idx > raw->curlen)
+ goto fail_len;
+
+ memcpy(msg->u.resource_stat.guid, &raw->msg[idx], 16);
+ idx += 16;
+ if (idx > raw->curlen)
+ goto fail_len;
+
+ msg->u.resource_stat.available_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
+ idx++;
+ return true;
+fail_len:
+ DRM_DEBUG_KMS("resource status reply parse length fail %d %d\n", idx, raw->curlen);
+ return false;
+}
+
+static bool drm_dp_sideband_parse_req(struct drm_dp_sideband_msg_rx *raw,
+ struct drm_dp_sideband_msg_req_body *msg)
+{
+ memset(msg, 0, sizeof(*msg));
+ msg->req_type = (raw->msg[0] & 0x7f);
+
+ switch (msg->req_type) {
+ case DP_CONNECTION_STATUS_NOTIFY:
+ return drm_dp_sideband_parse_connection_status_notify(raw, msg);
+ case DP_RESOURCE_STATUS_NOTIFY:
+ return drm_dp_sideband_parse_resource_status_notify(raw, msg);
+ default:
+ DRM_ERROR("Got unknown request 0x%02x\n", msg->req_type);
+ return false;
+ }
+}
+
+static int build_dpcd_write(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes, u8 *bytes)
+{
+ struct drm_dp_sideband_msg_req_body req;
+
+ req.req_type = DP_REMOTE_DPCD_WRITE;
+ req.u.dpcd_write.port_number = port_num;
+ req.u.dpcd_write.dpcd_address = offset;
+ req.u.dpcd_write.num_bytes = num_bytes;
+ req.u.dpcd_write.bytes = bytes;
+ drm_dp_encode_sideband_req(&req, msg);
+
+ return 0;
+}
+
+static int build_link_address(struct drm_dp_sideband_msg_tx *msg)
+{
+ struct drm_dp_sideband_msg_req_body req;
+
+ req.req_type = DP_LINK_ADDRESS;
+ drm_dp_encode_sideband_req(&req, msg);
+ return 0;
+}
+
+static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int port_num)
+{
+ struct drm_dp_sideband_msg_req_body req;
+
+ req.req_type = DP_ENUM_PATH_RESOURCES;
+ req.u.port_num.port_number = port_num;
+ drm_dp_encode_sideband_req(&req, msg);
+ msg->path_msg = true;
+ return 0;
+}
+
+static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
+ u8 vcpi, uint16_t pbn)
+{
+ struct drm_dp_sideband_msg_req_body req;
+ memset(&req, 0, sizeof(req));
+ req.req_type = DP_ALLOCATE_PAYLOAD;
+ req.u.allocate_payload.port_number = port_num;
+ req.u.allocate_payload.vcpi = vcpi;
+ req.u.allocate_payload.pbn = pbn;
+ drm_dp_encode_sideband_req(&req, msg);
+ msg->path_msg = true;
+ return 0;
+}
+
+static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_vcpi *vcpi)
+{
+ int ret;
+
+ mutex_lock(&mgr->payload_lock);
+ ret = find_first_zero_bit(&mgr->payload_mask, mgr->max_payloads + 1);
+ if (ret > mgr->max_payloads) {
+ ret = -EINVAL;
+ DRM_DEBUG_KMS("out of payload ids %d\n", ret);
+ goto out_unlock;
+ }
+
+ set_bit(ret, &mgr->payload_mask);
+ vcpi->vcpi = ret;
+ mgr->proposed_vcpis[ret - 1] = vcpi;
+out_unlock:
+ mutex_unlock(&mgr->payload_lock);
+ return ret;
+}
+
+static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
+ int id)
+{
+ if (id == 0)
+ return;
+
+ mutex_lock(&mgr->payload_lock);
+ DRM_DEBUG_KMS("putting payload %d\n", id);
+ clear_bit(id, &mgr->payload_mask);
+ mgr->proposed_vcpis[id - 1] = NULL;
+ mutex_unlock(&mgr->payload_lock);
+}
+
+static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_sideband_msg_tx *txmsg)
+{
+ bool ret;
+ mutex_lock(&mgr->qlock);
+ ret = (txmsg->state == DRM_DP_SIDEBAND_TX_RX ||
+ txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT);
+ mutex_unlock(&mgr->qlock);
+ return ret;
+}
+
+static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
+ struct drm_dp_sideband_msg_tx *txmsg)
+{
+ struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
+ int ret;
+
+ ret = wait_event_timeout(mgr->tx_waitq,
+ check_txmsg_state(mgr, txmsg),
+ (4 * HZ));
+ mutex_lock(&mstb->mgr->qlock);
+ if (ret > 0) {
+ if (txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT) {
+ ret = -EIO;
+ goto out;
+ }
+ } else {
+ DRM_DEBUG_KMS("timedout msg send %p %d %d\n", txmsg, txmsg->state, txmsg->seqno);
+
+ /* dump some state */
+ ret = -EIO;
+
+ /* remove from q */
+ if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED ||
+ txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND) {
+ list_del(&txmsg->next);
+ }
+
+ if (txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
+ txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
+ mstb->tx_slots[txmsg->seqno] = NULL;
+ }
+ }
+out:
+ mutex_unlock(&mgr->qlock);
+
+ return ret;
+}
+
+static struct drm_dp_mst_branch *drm_dp_add_mst_branch_device(u8 lct, u8 *rad)
+{
+ struct drm_dp_mst_branch *mstb;
+
+ mstb = kzalloc(sizeof(*mstb), GFP_KERNEL);
+ if (!mstb)
+ return NULL;
+
+ mstb->lct = lct;
+ if (lct > 1)
+ memcpy(mstb->rad, rad, lct / 2);
+ INIT_LIST_HEAD(&mstb->ports);
+ kref_init(&mstb->kref);
+ return mstb;
+}
+
+static void drm_dp_destroy_mst_branch_device(struct kref *kref)
+{
+ struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+ struct drm_dp_mst_port *port, *tmp;
+ bool wake_tx = false;
+
+ cancel_work_sync(&mstb->mgr->work);
+
+ /*
+ * destroy all ports - don't need lock
+ * as there are no more references to the mst branch
+ * device at this point.
+ */
+ list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
+ list_del(&port->next);
+ drm_dp_put_port(port);
+ }
+
+ /* drop any tx slots msg */
+ mutex_lock(&mstb->mgr->qlock);
+ if (mstb->tx_slots[0]) {
+ mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ mstb->tx_slots[0] = NULL;
+ wake_tx = true;
+ }
+ if (mstb->tx_slots[1]) {
+ mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ mstb->tx_slots[1] = NULL;
+ wake_tx = true;
+ }
+ mutex_unlock(&mstb->mgr->qlock);
+
+ if (wake_tx)
+ wake_up(&mstb->mgr->tx_waitq);
+ kfree(mstb);
+}
+
+static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
+{
+ kref_put(&mstb->kref, drm_dp_destroy_mst_branch_device);
+}
+
+
+static void drm_dp_port_teardown_pdt(struct drm_dp_mst_port *port, int old_pdt)
+{
+ switch (old_pdt) {
+ case DP_PEER_DEVICE_DP_LEGACY_CONV:
+ case DP_PEER_DEVICE_SST_SINK:
+ /* remove i2c over sideband */
+ drm_dp_mst_unregister_i2c_bus(&port->aux);
+ break;
+ case DP_PEER_DEVICE_MST_BRANCHING:
+ drm_dp_put_mst_branch_device(port->mstb);
+ port->mstb = NULL;
+ break;
+ }
+}
+
+static void drm_dp_destroy_port(struct kref *kref)
+{
+ struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
+ struct drm_dp_mst_topology_mgr *mgr = port->mgr;
+ if (!port->input) {
+ port->vcpi.num_slots = 0;
+ if (port->connector)
+ (*port->mgr->cbs->destroy_connector)(mgr, port->connector);
+ drm_dp_port_teardown_pdt(port, port->pdt);
+
+ if (!port->input && port->vcpi.vcpi > 0)
+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+ }
+ kfree(port);
+
+ (*mgr->cbs->hotplug)(mgr);
+}
+
+static void drm_dp_put_port(struct drm_dp_mst_port *port)
+{
+ kref_put(&port->kref, drm_dp_destroy_port);
+}
+
+static struct drm_dp_mst_branch *drm_dp_mst_get_validated_mstb_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_branch *to_find)
+{
+ struct drm_dp_mst_port *port;
+ struct drm_dp_mst_branch *rmstb;
+ if (to_find == mstb) {
+ kref_get(&mstb->kref);
+ return mstb;
+ }
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port->mstb) {
+ rmstb = drm_dp_mst_get_validated_mstb_ref_locked(port->mstb, to_find);
+ if (rmstb)
+ return rmstb;
+ }
+ }
+ return NULL;
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_validated_mstb_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_branch *mstb)
+{
+ struct drm_dp_mst_branch *rmstb = NULL;
+ mutex_lock(&mgr->lock);
+ if (mgr->mst_primary)
+ rmstb = drm_dp_mst_get_validated_mstb_ref_locked(mgr->mst_primary, mstb);
+ mutex_unlock(&mgr->lock);
+ return rmstb;
+}
+
+static struct drm_dp_mst_port *drm_dp_mst_get_port_ref_locked(struct drm_dp_mst_branch *mstb, struct drm_dp_mst_port *to_find)
+{
+ struct drm_dp_mst_port *port, *mport;
+
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port == to_find) {
+ kref_get(&port->kref);
+ return port;
+ }
+ if (port->mstb) {
+ mport = drm_dp_mst_get_port_ref_locked(port->mstb, to_find);
+ if (mport)
+ return mport;
+ }
+ }
+ return NULL;
+}
+
+static struct drm_dp_mst_port *drm_dp_get_validated_port_ref(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+ struct drm_dp_mst_port *rport = NULL;
+ mutex_lock(&mgr->lock);
+ if (mgr->mst_primary)
+ rport = drm_dp_mst_get_port_ref_locked(mgr->mst_primary, port);
+ mutex_unlock(&mgr->lock);
+ return rport;
+}
+
+static struct drm_dp_mst_port *drm_dp_get_port(struct drm_dp_mst_branch *mstb, u8 port_num)
+{
+ struct drm_dp_mst_port *port;
+
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port->port_num == port_num) {
+ kref_get(&port->kref);
+ return port;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * calculate a new RAD for this MST branch device
+ * if parent has an LCT of 2 then it has 1 nibble of RAD,
+ * if parent has an LCT of 3 then it has 2 nibbles of RAD,
+ */
+static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
+ u8 *rad)
+{
+ int lct = port->parent->lct;
+ int shift = 4;
+ int idx = lct / 2;
+ if (lct > 1) {
+ memcpy(rad, port->parent->rad, idx);
+ shift = (lct % 2) ? 4 : 0;
+ } else
+ rad[0] = 0;
+
+ rad[idx] |= port->port_num << shift;
+ return lct + 1;
+}
+
+/*
+ * return sends link address for new mstb
+ */
+static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port)
+{
+ int ret;
+ u8 rad[6], lct;
+ bool send_link = false;
+ switch (port->pdt) {
+ case DP_PEER_DEVICE_DP_LEGACY_CONV:
+ case DP_PEER_DEVICE_SST_SINK:
+ /* add i2c over sideband */
+ ret = drm_dp_mst_register_i2c_bus(&port->aux);
+ break;
+ case DP_PEER_DEVICE_MST_BRANCHING:
+ lct = drm_dp_calculate_rad(port, rad);
+
+ port->mstb = drm_dp_add_mst_branch_device(lct, rad);
+ port->mstb->mgr = port->mgr;
+ port->mstb->port_parent = port;
+
+ send_link = true;
+ break;
+ }
+ return send_link;
+}
+
+static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
+ struct drm_dp_mst_port *port)
+{
+ int ret;
+ if (port->dpcd_rev >= 0x12) {
+ port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid);
+ if (!port->guid_valid) {
+ ret = drm_dp_send_dpcd_write(mstb->mgr,
+ port,
+ DP_GUID,
+ 16, port->guid);
+ port->guid_valid = true;
+ }
+ }
+}
+
+static void build_mst_prop_path(struct drm_dp_mst_port *port,
+ struct drm_dp_mst_branch *mstb,
+ char *proppath)
+{
+ int i;
+ char temp[8];
+ snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id);
+ for (i = 0; i < (mstb->lct - 1); i++) {
+ int shift = (i % 2) ? 0 : 4;
+ int port_num = mstb->rad[i / 2] >> shift;
+ snprintf(temp, 8, "-%d", port_num);
+ strncat(proppath, temp, 255);
+ }
+ snprintf(temp, 8, "-%d", port->port_num);
+ strncat(proppath, temp, 255);
+}
+
+static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
+ struct device *dev,
+ struct drm_dp_link_addr_reply_port *port_msg)
+{
+ struct drm_dp_mst_port *port;
+ bool ret;
+ bool created = false;
+ int old_pdt = 0;
+ int old_ddps = 0;
+ port = drm_dp_get_port(mstb, port_msg->port_number);
+ if (!port) {
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return;
+ kref_init(&port->kref);
+ port->parent = mstb;
+ port->port_num = port_msg->port_number;
+ port->mgr = mstb->mgr;
+ port->aux.name = "DPMST";
+ port->aux.dev = dev;
+ created = true;
+ } else {
+ old_pdt = port->pdt;
+ old_ddps = port->ddps;
+ }
+
+ port->pdt = port_msg->peer_device_type;
+ port->input = port_msg->input_port;
+ port->mcs = port_msg->mcs;
+ port->ddps = port_msg->ddps;
+ port->ldps = port_msg->legacy_device_plug_status;
+ port->dpcd_rev = port_msg->dpcd_revision;
+ port->num_sdp_streams = port_msg->num_sdp_streams;
+ port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
+ memcpy(port->guid, port_msg->peer_guid, 16);
+
+ /* manage mstb port lists with mgr lock - take a reference
+ for this list */
+ if (created) {
+ mutex_lock(&mstb->mgr->lock);
+ kref_get(&port->kref);
+ list_add(&port->next, &mstb->ports);
+ mutex_unlock(&mstb->mgr->lock);
+ }
+
+ if (old_ddps != port->ddps) {
+ if (port->ddps) {
+ drm_dp_check_port_guid(mstb, port);
+ if (!port->input)
+ drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
+ } else {
+ port->guid_valid = false;
+ port->available_pbn = 0;
+ }
+ }
+
+ if (old_pdt != port->pdt && !port->input) {
+ drm_dp_port_teardown_pdt(port, old_pdt);
+
+ ret = drm_dp_port_setup_pdt(port);
+ if (ret == true) {
+ drm_dp_send_link_address(mstb->mgr, port->mstb);
+ port->mstb->link_address_sent = true;
+ }
+ }
+
+ if (created && !port->input) {
+ char proppath[255];
+ build_mst_prop_path(port, mstb, proppath);
+ port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+ }
+
+ /* put reference to this port */
+ drm_dp_put_port(port);
+}
+
+static void drm_dp_update_port(struct drm_dp_mst_branch *mstb,
+ struct drm_dp_connection_status_notify *conn_stat)
+{
+ struct drm_dp_mst_port *port;
+ int old_pdt;
+ int old_ddps;
+ bool dowork = false;
+ port = drm_dp_get_port(mstb, conn_stat->port_number);
+ if (!port)
+ return;
+
+ old_ddps = port->ddps;
+ old_pdt = port->pdt;
+ port->pdt = conn_stat->peer_device_type;
+ port->mcs = conn_stat->message_capability_status;
+ port->ldps = conn_stat->legacy_device_plug_status;
+ port->ddps = conn_stat->displayport_device_plug_status;
+
+ if (old_ddps != port->ddps) {
+ if (port->ddps) {
+ drm_dp_check_port_guid(mstb, port);
+ dowork = true;
+ } else {
+ port->guid_valid = false;
+ port->available_pbn = 0;
+ }
+ }
+ if (old_pdt != port->pdt && !port->input) {
+ drm_dp_port_teardown_pdt(port, old_pdt);
+
+ if (drm_dp_port_setup_pdt(port))
+ dowork = true;
+ }
+
+ drm_dp_put_port(port);
+ if (dowork)
+ queue_work(system_long_wq, &mstb->mgr->work);
+
+}
+
+static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_topology_mgr *mgr,
+ u8 lct, u8 *rad)
+{
+ struct drm_dp_mst_branch *mstb;
+ struct drm_dp_mst_port *port;
+ int i;
+ /* find the port by iterating down */
+ mstb = mgr->mst_primary;
+
+ for (i = 0; i < lct - 1; i++) {
+ int shift = (i % 2) ? 0 : 4;
+ int port_num = rad[i / 2] >> shift;
+
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port->port_num == port_num) {
+ if (!port->mstb) {
+ DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
+ return NULL;
+ }
+
+ mstb = port->mstb;
+ break;
+ }
+ }
+ }
+ kref_get(&mstb->kref);
+ return mstb;
+}
+
+static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb)
+{
+ struct drm_dp_mst_port *port;
+
+ if (!mstb->link_address_sent) {
+ drm_dp_send_link_address(mgr, mstb);
+ mstb->link_address_sent = true;
+ }
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port->input)
+ continue;
+
+ if (!port->ddps)
+ continue;
+
+ if (!port->available_pbn)
+ drm_dp_send_enum_path_resources(mgr, mstb, port);
+
+ if (port->mstb)
+ drm_dp_check_and_send_link_address(mgr, port->mstb);
+ }
+}
+
+static void drm_dp_mst_link_probe_work(struct work_struct *work)
+{
+ struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
+
+ drm_dp_check_and_send_link_address(mgr, mgr->mst_primary);
+
+}
+
+static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
+ u8 *guid)
+{
+ static u8 zero_guid[16];
+
+ if (!memcmp(guid, zero_guid, 16)) {
+ u64 salt = get_jiffies_64();
+ memcpy(&guid[0], &salt, sizeof(u64));
+ memcpy(&guid[8], &salt, sizeof(u64));
+ return false;
+ }
+ return true;
+}
+
+#if 0
+static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes)
+{
+ struct drm_dp_sideband_msg_req_body req;
+
+ req.req_type = DP_REMOTE_DPCD_READ;
+ req.u.dpcd_read.port_number = port_num;
+ req.u.dpcd_read.dpcd_address = offset;
+ req.u.dpcd_read.num_bytes = num_bytes;
+ drm_dp_encode_sideband_req(&req, msg);
+
+ return 0;
+}
+#endif
+
+static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr,
+ bool up, u8 *msg, int len)
+{
+ int ret;
+ int regbase = up ? DP_SIDEBAND_MSG_UP_REP_BASE : DP_SIDEBAND_MSG_DOWN_REQ_BASE;
+ int tosend, total, offset;
+ int retries = 0;
+
+retry:
+ total = len;
+ offset = 0;
+ do {
+ tosend = min3(mgr->max_dpcd_transaction_bytes, 16, total);
+
+ ret = drm_dp_dpcd_write(mgr->aux, regbase + offset,
+ &msg[offset],
+ tosend);
+ if (ret != tosend) {
+ if (ret == -EIO && retries < 5) {
+ retries++;
+ goto retry;
+ }
+ DRM_DEBUG_KMS("failed to dpcd write %d %d\n", tosend, ret);
+ WARN(1, "fail\n");
+
+ return -EIO;
+ }
+ offset += tosend;
+ total -= tosend;
+ } while (total > 0);
+ return 0;
+}
+
+static int set_hdr_from_dst_qlock(struct drm_dp_sideband_msg_hdr *hdr,
+ struct drm_dp_sideband_msg_tx *txmsg)
+{
+ struct drm_dp_mst_branch *mstb = txmsg->dst;
+
+ /* both msg slots are full */
+ if (txmsg->seqno == -1) {
+ if (mstb->tx_slots[0] && mstb->tx_slots[1]) {
+ DRM_DEBUG_KMS("%s: failed to find slot\n", __func__);
+ return -EAGAIN;
+ }
+ if (mstb->tx_slots[0] == NULL && mstb->tx_slots[1] == NULL) {
+ txmsg->seqno = mstb->last_seqno;
+ mstb->last_seqno ^= 1;
+ } else if (mstb->tx_slots[0] == NULL)
+ txmsg->seqno = 0;
+ else
+ txmsg->seqno = 1;
+ mstb->tx_slots[txmsg->seqno] = txmsg;
+ }
+ hdr->broadcast = 0;
+ hdr->path_msg = txmsg->path_msg;
+ hdr->lct = mstb->lct;
+ hdr->lcr = mstb->lct - 1;
+ if (mstb->lct > 1)
+ memcpy(hdr->rad, mstb->rad, mstb->lct / 2);
+ hdr->seqno = txmsg->seqno;
+ return 0;
+}
+/*
+ * process a single block of the next message in the sideband queue
+ */
+static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_sideband_msg_tx *txmsg,
+ bool up)
+{
+ u8 chunk[48];
+ struct drm_dp_sideband_msg_hdr hdr;
+ int len, space, idx, tosend;
+ int ret;
+
+ memset(&hdr, 0, sizeof(struct drm_dp_sideband_msg_hdr));
+
+ if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED) {
+ txmsg->seqno = -1;
+ txmsg->state = DRM_DP_SIDEBAND_TX_START_SEND;
+ }
+
+ /* make hdr from dst mst - for replies use seqno
+ otherwise assign one */
+ ret = set_hdr_from_dst_qlock(&hdr, txmsg);
+ if (ret < 0)
+ return ret;
+
+ /* amount left to send in this message */
+ len = txmsg->cur_len - txmsg->cur_offset;
+
+ /* 48 - sideband msg size - 1 byte for data CRC, x header bytes */
+ space = 48 - 1 - drm_dp_calc_sb_hdr_size(&hdr);
+
+ tosend = min(len, space);
+ if (len == txmsg->cur_len)
+ hdr.somt = 1;
+ if (space >= len)
+ hdr.eomt = 1;
+
+
+ hdr.msg_len = tosend + 1;
+ drm_dp_encode_sideband_msg_hdr(&hdr, chunk, &idx);
+ memcpy(&chunk[idx], &txmsg->msg[txmsg->cur_offset], tosend);
+ /* add crc at end */
+ drm_dp_crc_sideband_chunk_req(&chunk[idx], tosend);
+ idx += tosend + 1;
+
+ ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
+ if (ret) {
+ DRM_DEBUG_KMS("sideband msg failed to send\n");
+ return ret;
+ }
+
+ txmsg->cur_offset += tosend;
+ if (txmsg->cur_offset == txmsg->cur_len) {
+ txmsg->state = DRM_DP_SIDEBAND_TX_SENT;
+ return 1;
+ }
+ return 0;
+}
+
+/* must be called holding qlock */
+static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct drm_dp_sideband_msg_tx *txmsg;
+ int ret;
+
+ /* construct a chunk from the first msg in the tx_msg queue */
+ if (list_empty(&mgr->tx_msg_downq)) {
+ mgr->tx_down_in_progress = false;
+ return;
+ }
+ mgr->tx_down_in_progress = true;
+
+ txmsg = list_first_entry(&mgr->tx_msg_downq, struct drm_dp_sideband_msg_tx, next);
+ ret = process_single_tx_qlock(mgr, txmsg, false);
+ if (ret == 1) {
+ /* txmsg is sent it should be in the slots now */
+ list_del(&txmsg->next);
+ } else if (ret) {
+ DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+ list_del(&txmsg->next);
+ if (txmsg->seqno != -1)
+ txmsg->dst->tx_slots[txmsg->seqno] = NULL;
+ txmsg->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ wake_up(&mgr->tx_waitq);
+ }
+ if (list_empty(&mgr->tx_msg_downq)) {
+ mgr->tx_down_in_progress = false;
+ return;
+ }
+}
+
+/* called holding qlock */
+static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct drm_dp_sideband_msg_tx *txmsg;
+ int ret;
+
+ /* construct a chunk from the first msg in the tx_msg queue */
+ if (list_empty(&mgr->tx_msg_upq)) {
+ mgr->tx_up_in_progress = false;
+ return;
+ }
+
+ txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
+ ret = process_single_tx_qlock(mgr, txmsg, true);
+ if (ret == 1) {
+ /* up txmsgs aren't put in slots - so free after we send it */
+ list_del(&txmsg->next);
+ kfree(txmsg);
+ } else if (ret)
+ DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+ mgr->tx_up_in_progress = true;
+}
+
+static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_sideband_msg_tx *txmsg)
+{
+ mutex_lock(&mgr->qlock);
+ list_add_tail(&txmsg->next, &mgr->tx_msg_downq);
+ if (!mgr->tx_down_in_progress)
+ process_single_down_tx_qlock(mgr);
+ mutex_unlock(&mgr->qlock);
+}
+
+static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb)
+{
+ int len;
+ struct drm_dp_sideband_msg_tx *txmsg;
+ int ret;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg)
+ return -ENOMEM;
+
+ txmsg->dst = mstb;
+ len = build_link_address(txmsg);
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret > 0) {
+ int i;
+
+ if (txmsg->reply.reply_type == 1)
+ DRM_DEBUG_KMS("link address nak received\n");
+ else {
+ DRM_DEBUG_KMS("link address reply: %d\n", txmsg->reply.u.link_addr.nports);
+ for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+ DRM_DEBUG_KMS("port %d: input %d, pdt: %d, pn: %d, dpcd_rev: %02x, mcs: %d, ddps: %d, ldps %d, sdp %d/%d\n", i,
+ txmsg->reply.u.link_addr.ports[i].input_port,
+ txmsg->reply.u.link_addr.ports[i].peer_device_type,
+ txmsg->reply.u.link_addr.ports[i].port_number,
+ txmsg->reply.u.link_addr.ports[i].dpcd_revision,
+ txmsg->reply.u.link_addr.ports[i].mcs,
+ txmsg->reply.u.link_addr.ports[i].ddps,
+ txmsg->reply.u.link_addr.ports[i].legacy_device_plug_status,
+ txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
+ txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
+ }
+ for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+ drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
+ }
+ (*mgr->cbs->hotplug)(mgr);
+ }
+ } else
+ DRM_DEBUG_KMS("link address failed %d\n", ret);
+
+ kfree(txmsg);
+ return 0;
+}
+
+static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb,
+ struct drm_dp_mst_port *port)
+{
+ int len;
+ struct drm_dp_sideband_msg_tx *txmsg;
+ int ret;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg)
+ return -ENOMEM;
+
+ txmsg->dst = mstb;
+ len = build_enum_path_resources(txmsg, port->port_num);
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret > 0) {
+ if (txmsg->reply.reply_type == 1)
+ DRM_DEBUG_KMS("enum path resources nak received\n");
+ else {
+ if (port->port_num != txmsg->reply.u.path_resources.port_number)
+ DRM_ERROR("got incorrect port in response\n");
+ DRM_DEBUG_KMS("enum path resources %d: %d %d\n", txmsg->reply.u.path_resources.port_number, txmsg->reply.u.path_resources.full_payload_bw_number,
+ txmsg->reply.u.path_resources.avail_payload_bw_number);
+ port->available_pbn = txmsg->reply.u.path_resources.avail_payload_bw_number;
+ }
+ }
+
+ kfree(txmsg);
+ return 0;
+}
+
+static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int id,
+ int pbn)
+{
+ struct drm_dp_sideband_msg_tx *txmsg;
+ struct drm_dp_mst_branch *mstb;
+ int len, ret;
+
+ mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+ if (!mstb)
+ return -EINVAL;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg) {
+ ret = -ENOMEM;
+ goto fail_put;
+ }
+
+ txmsg->dst = mstb;
+ len = build_allocate_payload(txmsg, port->port_num,
+ id,
+ pbn);
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret > 0) {
+ if (txmsg->reply.reply_type == 1) {
+ ret = -EINVAL;
+ } else
+ ret = 0;
+ }
+ kfree(txmsg);
+fail_put:
+ drm_dp_put_mst_branch_device(mstb);
+ return ret;
+}
+
+static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
+ int id,
+ struct drm_dp_payload *payload)
+{
+ int ret;
+
+ ret = drm_dp_dpcd_write_payload(mgr, id, payload);
+ if (ret < 0) {
+ payload->payload_state = 0;
+ return ret;
+ }
+ payload->payload_state = DP_PAYLOAD_LOCAL;
+ return 0;
+}
+
+static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int id,
+ struct drm_dp_payload *payload)
+{
+ int ret;
+ ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
+ if (ret < 0)
+ return ret;
+ payload->payload_state = DP_PAYLOAD_REMOTE;
+ return ret;
+}
+
+static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int id,
+ struct drm_dp_payload *payload)
+{
+ DRM_DEBUG_KMS("\n");
+ /* its okay for these to fail */
+ if (port) {
+ drm_dp_payload_send_msg(mgr, port, id, 0);
+ }
+
+ drm_dp_dpcd_write_payload(mgr, id, payload);
+ payload->payload_state = 0;
+ return 0;
+}
+
+static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
+ int id,
+ struct drm_dp_payload *payload)
+{
+ payload->payload_state = 0;
+ return 0;
+}
+
+/**
+ * drm_dp_update_payload_part1() - Execute payload update part 1
+ * @mgr: manager to use.
+ *
+ * This iterates over all proposed virtual channels, and tries to
+ * allocate space in the link for them. For 0->slots transitions,
+ * this step just writes the VCPI to the MST device. For slots->0
+ * transitions, this writes the updated VCPIs and removes the
+ * remote VC payloads.
+ *
+ * after calling this the driver should generate ACT and payload
+ * packets.
+ */
+int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
+{
+ int i;
+ int cur_slots = 1;
+ struct drm_dp_payload req_payload;
+ struct drm_dp_mst_port *port;
+
+ mutex_lock(&mgr->payload_lock);
+ for (i = 0; i < mgr->max_payloads; i++) {
+ /* solve the current payloads - compare to the hw ones
+ - update the hw view */
+ req_payload.start_slot = cur_slots;
+ if (mgr->proposed_vcpis[i]) {
+ port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+ req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots;
+ } else {
+ port = NULL;
+ req_payload.num_slots = 0;
+ }
+ /* work out what is required to happen with this payload */
+ if (mgr->payloads[i].start_slot != req_payload.start_slot ||
+ mgr->payloads[i].num_slots != req_payload.num_slots) {
+
+ /* need to push an update for this payload */
+ if (req_payload.num_slots) {
+ drm_dp_create_payload_step1(mgr, i + 1, &req_payload);
+ mgr->payloads[i].num_slots = req_payload.num_slots;
+ } else if (mgr->payloads[i].num_slots) {
+ mgr->payloads[i].num_slots = 0;
+ drm_dp_destroy_payload_step1(mgr, port, i + 1, &mgr->payloads[i]);
+ req_payload.payload_state = mgr->payloads[i].payload_state;
+ } else
+ req_payload.payload_state = 0;
+
+ mgr->payloads[i].start_slot = req_payload.start_slot;
+ mgr->payloads[i].payload_state = req_payload.payload_state;
+ }
+ cur_slots += req_payload.num_slots;
+ }
+ mutex_unlock(&mgr->payload_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_dp_update_payload_part1);
+
+/**
+ * drm_dp_update_payload_part2() - Execute payload update part 2
+ * @mgr: manager to use.
+ *
+ * This iterates over all proposed virtual channels, and tries to
+ * allocate space in the link for them. For 0->slots transitions,
+ * this step writes the remote VC payload commands. For slots->0
+ * this just resets some internal state.
+ */
+int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct drm_dp_mst_port *port;
+ int i;
+ int ret = 0;
+ mutex_lock(&mgr->payload_lock);
+ for (i = 0; i < mgr->max_payloads; i++) {
+
+ if (!mgr->proposed_vcpis[i])
+ continue;
+
+ port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+
+ DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state);
+ if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) {
+ ret = drm_dp_create_payload_step2(mgr, port, i + 1, &mgr->payloads[i]);
+ } else if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) {
+ ret = drm_dp_destroy_payload_step2(mgr, i + 1, &mgr->payloads[i]);
+ }
+ if (ret) {
+ mutex_unlock(&mgr->payload_lock);
+ return ret;
+ }
+ }
+ mutex_unlock(&mgr->payload_lock);
+ return 0;
+}
+EXPORT_SYMBOL(drm_dp_update_payload_part2);
+
+#if 0 /* unused as of yet */
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int offset, int size)
+{
+ int len;
+ struct drm_dp_sideband_msg_tx *txmsg;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg)
+ return -ENOMEM;
+
+ len = build_dpcd_read(txmsg, port->port_num, 0, 8);
+ txmsg->dst = port->parent;
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ return 0;
+}
+#endif
+
+static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int offset, int size, u8 *bytes)
+{
+ int len;
+ int ret;
+ struct drm_dp_sideband_msg_tx *txmsg;
+ struct drm_dp_mst_branch *mstb;
+
+ mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+ if (!mstb)
+ return -EINVAL;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg) {
+ ret = -ENOMEM;
+ goto fail_put;
+ }
+
+ len = build_dpcd_write(txmsg, port->port_num, offset, size, bytes);
+ txmsg->dst = mstb;
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret > 0) {
+ if (txmsg->reply.reply_type == 1) {
+ ret = -EINVAL;
+ } else
+ ret = 0;
+ }
+ kfree(txmsg);
+fail_put:
+ drm_dp_put_mst_branch_device(mstb);
+ return ret;
+}
+
+static int drm_dp_encode_up_ack_reply(struct drm_dp_sideband_msg_tx *msg, u8 req_type)
+{
+ struct drm_dp_sideband_msg_reply_body reply;
+
+ reply.reply_type = 1;
+ reply.req_type = req_type;
+ drm_dp_encode_sideband_reply(&reply, msg);
+ return 0;
+}
+
+static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb,
+ int req_type, int seqno, bool broadcast)
+{
+ struct drm_dp_sideband_msg_tx *txmsg;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg)
+ return -ENOMEM;
+
+ txmsg->dst = mstb;
+ txmsg->seqno = seqno;
+ drm_dp_encode_up_ack_reply(txmsg, req_type);
+
+ mutex_lock(&mgr->qlock);
+ list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
+ if (!mgr->tx_up_in_progress) {
+ process_single_up_tx_qlock(mgr);
+ }
+ mutex_unlock(&mgr->qlock);
+ return 0;
+}
+
+static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
+{
+ switch (dp_link_bw) {
+ case DP_LINK_BW_1_62:
+ return 3 * dp_link_count;
+ case DP_LINK_BW_2_7:
+ return 5 * dp_link_count;
+ case DP_LINK_BW_5_4:
+ return 10 * dp_link_count;
+ }
+ return 0;
+}
+
+/**
+ * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager
+ * @mgr: manager to set state for
+ * @mst_state: true to enable MST on this connector - false to disable.
+ *
+ * This is called by the driver when it detects an MST capable device plugged
+ * into a DP MST capable port, or when a DP MST capable device is unplugged.
+ */
+int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state)
+{
+ int ret = 0;
+ struct drm_dp_mst_branch *mstb = NULL;
+
+ mutex_lock(&mgr->lock);
+ if (mst_state == mgr->mst_state)
+ goto out_unlock;
+
+ mgr->mst_state = mst_state;
+ /* set the device into MST mode */
+ if (mst_state) {
+ WARN_ON(mgr->mst_primary);
+
+ /* get dpcd info */
+ ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
+ if (ret != DP_RECEIVER_CAP_SIZE) {
+ DRM_DEBUG_KMS("failed to read DPCD\n");
+ goto out_unlock;
+ }
+
+ mgr->pbn_div = drm_dp_get_vc_payload_bw(mgr->dpcd[1], mgr->dpcd[2] & DP_MAX_LANE_COUNT_MASK);
+ mgr->total_pbn = 2560;
+ mgr->total_slots = DIV_ROUND_UP(mgr->total_pbn, mgr->pbn_div);
+ mgr->avail_slots = mgr->total_slots;
+
+ /* add initial branch device at LCT 1 */
+ mstb = drm_dp_add_mst_branch_device(1, NULL);
+ if (mstb == NULL) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+ mstb->mgr = mgr;
+
+ /* give this the main reference */
+ mgr->mst_primary = mstb;
+ kref_get(&mgr->mst_primary->kref);
+
+ {
+ struct drm_dp_payload reset_pay;
+ reset_pay.start_slot = 0;
+ reset_pay.num_slots = 0x3f;
+ drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+ }
+
+ ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+ DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+ if (ret < 0) {
+ goto out_unlock;
+ }
+
+
+ /* sort out guid */
+ ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16);
+ if (ret != 16) {
+ DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret);
+ goto out_unlock;
+ }
+
+ mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid);
+ if (!mgr->guid_valid) {
+ ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16);
+ mgr->guid_valid = true;
+ }
+
+ queue_work(system_long_wq, &mgr->work);
+
+ ret = 0;
+ } else {
+ /* disable MST on the device */
+ mstb = mgr->mst_primary;
+ mgr->mst_primary = NULL;
+ /* this can fail if the device is gone */
+ drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
+ ret = 0;
+ memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload));
+ mgr->payload_mask = 0;
+ set_bit(0, &mgr->payload_mask);
+ }
+
+out_unlock:
+ mutex_unlock(&mgr->lock);
+ if (mstb)
+ drm_dp_put_mst_branch_device(mstb);
+ return ret;
+
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_set_mst);
+
+/**
+ * drm_dp_mst_topology_mgr_suspend() - suspend the MST manager
+ * @mgr: manager to suspend
+ *
+ * This function tells the MST device that we can't handle UP messages
+ * anymore. This should stop it from sending any since we are suspended.
+ */
+void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr)
+{
+ mutex_lock(&mgr->lock);
+ drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+ DP_MST_EN | DP_UPSTREAM_IS_SRC);
+ mutex_unlock(&mgr->lock);
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
+
+/**
+ * drm_dp_mst_topology_mgr_resume() - resume the MST manager
+ * @mgr: manager to resume
+ *
+ * This will fetch DPCD and see if the device is still there,
+ * if it is, it will rewrite the MSTM control bits, and return.
+ *
+ * if the device fails this returns -1, and the driver should do
+ * a full MST reprobe, in case we were undocked.
+ */
+int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)
+{
+ int ret = 0;
+
+ mutex_lock(&mgr->lock);
+
+ if (mgr->mst_primary) {
+ int sret;
+ sret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd, DP_RECEIVER_CAP_SIZE);
+ if (sret != DP_RECEIVER_CAP_SIZE) {
+ DRM_DEBUG_KMS("dpcd read failed - undocked during suspend?\n");
+ ret = -1;
+ goto out_unlock;
+ }
+
+ ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+ DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("mst write failed - undocked during suspend?\n");
+ ret = -1;
+ goto out_unlock;
+ }
+ ret = 0;
+ } else
+ ret = -1;
+
+out_unlock:
+ mutex_unlock(&mgr->lock);
+ return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
+
+static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
+{
+ int len;
+ u8 replyblock[32];
+ int replylen, origlen, curreply;
+ int ret;
+ struct drm_dp_sideband_msg_rx *msg;
+ int basereg = up ? DP_SIDEBAND_MSG_UP_REQ_BASE : DP_SIDEBAND_MSG_DOWN_REP_BASE;
+ msg = up ? &mgr->up_req_recv : &mgr->down_rep_recv;
+
+ len = min(mgr->max_dpcd_transaction_bytes, 16);
+ ret = drm_dp_dpcd_read(mgr->aux, basereg,
+ replyblock, len);
+ if (ret != len) {
+ DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
+ return;
+ }
+ ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
+ if (!ret) {
+ DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
+ return;
+ }
+ replylen = msg->curchunk_len + msg->curchunk_hdrlen;
+
+ origlen = replylen;
+ replylen -= len;
+ curreply = len;
+ while (replylen > 0) {
+ len = min3(replylen, mgr->max_dpcd_transaction_bytes, 16);
+ ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
+ replyblock, len);
+ if (ret != len) {
+ DRM_DEBUG_KMS("failed to read a chunk\n");
+ }
+ ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
+ if (ret == false)
+ DRM_DEBUG_KMS("failed to build sideband msg\n");
+ curreply += len;
+ replylen -= len;
+ }
+}
+
+static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
+{
+ int ret = 0;
+
+ drm_dp_get_one_sb_msg(mgr, false);
+
+ if (mgr->down_rep_recv.have_eomt) {
+ struct drm_dp_sideband_msg_tx *txmsg;
+ struct drm_dp_mst_branch *mstb;
+ int slot = -1;
+ mstb = drm_dp_get_mst_branch_device(mgr,
+ mgr->down_rep_recv.initial_hdr.lct,
+ mgr->down_rep_recv.initial_hdr.rad);
+
+ if (!mstb) {
+ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->down_rep_recv.initial_hdr.lct);
+ memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ return 0;
+ }
+
+ /* find the message */
+ slot = mgr->down_rep_recv.initial_hdr.seqno;
+ mutex_lock(&mgr->qlock);
+ txmsg = mstb->tx_slots[slot];
+ /* remove from slots */
+ mutex_unlock(&mgr->qlock);
+
+ if (!txmsg) {
+ DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
+ mstb,
+ mgr->down_rep_recv.initial_hdr.seqno,
+ mgr->down_rep_recv.initial_hdr.lct,
+ mgr->down_rep_recv.initial_hdr.rad[0],
+ mgr->down_rep_recv.msg[0]);
+ drm_dp_put_mst_branch_device(mstb);
+ memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ return 0;
+ }
+
+ drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply);
+ if (txmsg->reply.reply_type == 1) {
+ DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, reason 0x%02x, nak data 0x%02x\n", txmsg->reply.req_type, txmsg->reply.u.nak.reason, txmsg->reply.u.nak.nak_data);
+ }
+
+ memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ drm_dp_put_mst_branch_device(mstb);
+
+ mutex_lock(&mgr->qlock);
+ txmsg->state = DRM_DP_SIDEBAND_TX_RX;
+ mstb->tx_slots[slot] = NULL;
+ mutex_unlock(&mgr->qlock);
+
+ wake_up(&mgr->tx_waitq);
+ }
+ return ret;
+}
+
+static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
+{
+ int ret = 0;
+ drm_dp_get_one_sb_msg(mgr, true);
+
+ if (mgr->up_req_recv.have_eomt) {
+ struct drm_dp_sideband_msg_req_body msg;
+ struct drm_dp_mst_branch *mstb;
+ bool seqno;
+ mstb = drm_dp_get_mst_branch_device(mgr,
+ mgr->up_req_recv.initial_hdr.lct,
+ mgr->up_req_recv.initial_hdr.rad);
+ if (!mstb) {
+ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ return 0;
+ }
+
+ seqno = mgr->up_req_recv.initial_hdr.seqno;
+ drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
+
+ if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
+ drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+ drm_dp_update_port(mstb, &msg.u.conn_stat);
+ DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+ (*mgr->cbs->hotplug)(mgr);
+
+ } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
+ drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
+ DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
+ }
+
+ drm_dp_put_mst_branch_device(mstb);
+ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ }
+ return ret;
+}
+
+/**
+ * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
+ * @mgr: manager to notify irq for.
+ * @esi: 4 bytes from SINK_COUNT_ESI
+ *
+ * This should be called from the driver when it detects a short IRQ,
+ * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
+ * topology manager will process the sideband messages received as a result
+ * of this.
+ */
+int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled)
+{
+ int ret = 0;
+ int sc;
+ *handled = false;
+ sc = esi[0] & 0x3f;
+
+ if (sc != mgr->sink_count) {
+ mgr->sink_count = sc;
+ *handled = true;
+ }
+
+ if (esi[1] & DP_DOWN_REP_MSG_RDY) {
+ ret = drm_dp_mst_handle_down_rep(mgr);
+ *handled = true;
+ }
+
+ if (esi[1] & DP_UP_REQ_MSG_RDY) {
+ ret |= drm_dp_mst_handle_up_req(mgr);
+ *handled = true;
+ }
+
+ drm_dp_mst_kick_tx(mgr);
+ return ret;
+}
+EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
+
+/**
+ * drm_dp_mst_detect_port() - get connection status for an MST port
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port
+ *
+ * This returns the current connection state for a port. It validates the
+ * port pointer still exists so the caller doesn't require a reference
+ */
+enum drm_connector_status drm_dp_mst_detect_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+ enum drm_connector_status status = connector_status_disconnected;
+
+ /* we need to search for the port in the mgr in case its gone */
+ port = drm_dp_get_validated_port_ref(mgr, port);
+ if (!port)
+ return connector_status_disconnected;
+
+ if (!port->ddps)
+ goto out;
+
+ switch (port->pdt) {
+ case DP_PEER_DEVICE_NONE:
+ case DP_PEER_DEVICE_MST_BRANCHING:
+ break;
+
+ case DP_PEER_DEVICE_SST_SINK:
+ status = connector_status_connected;
+ break;
+ case DP_PEER_DEVICE_DP_LEGACY_CONV:
+ if (port->ldps)
+ status = connector_status_connected;
+ break;
+ }
+out:
+ drm_dp_put_port(port);
+ return status;
+}
+EXPORT_SYMBOL(drm_dp_mst_detect_port);
+
+/**
+ * drm_dp_mst_get_edid() - get EDID for an MST port
+ * @connector: toplevel connector to get EDID for
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This returns an EDID for the port connected to a connector,
+ * It validates the pointer still exists so the caller doesn't require a
+ * reference.
+ */
+struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+ struct edid *edid = NULL;
+
+ /* we need to search for the port in the mgr in case its gone */
+ port = drm_dp_get_validated_port_ref(mgr, port);
+ if (!port)
+ return NULL;
+
+ edid = drm_get_edid(connector, &port->aux.ddc);
+ drm_dp_put_port(port);
+ return edid;
+}
+EXPORT_SYMBOL(drm_dp_mst_get_edid);
+
+/**
+ * drm_dp_find_vcpi_slots() - find slots for this PBN value
+ * @mgr: manager to use
+ * @pbn: payload bandwidth to convert into slots.
+ */
+int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
+ int pbn)
+{
+ int num_slots;
+
+ num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
+
+ if (num_slots > mgr->avail_slots)
+ return -ENOSPC;
+ return num_slots;
+}
+EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
+
+static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_vcpi *vcpi, int pbn)
+{
+ int num_slots;
+ int ret;
+
+ num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
+
+ if (num_slots > mgr->avail_slots)
+ return -ENOSPC;
+
+ vcpi->pbn = pbn;
+ vcpi->aligned_pbn = num_slots * mgr->pbn_div;
+ vcpi->num_slots = num_slots;
+
+ ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+/**
+ * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
+ * @mgr: manager for this port
+ * @port: port to allocate a virtual channel for.
+ * @pbn: payload bandwidth number to request
+ * @slots: returned number of slots for this PBN.
+ */
+bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots)
+{
+ int ret;
+
+ port = drm_dp_get_validated_port_ref(mgr, port);
+ if (!port)
+ return false;
+
+ if (port->vcpi.vcpi > 0) {
+ DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
+ if (pbn == port->vcpi.pbn) {
+ *slots = port->vcpi.num_slots;
+ return true;
+ }
+ }
+
+ ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn);
+ if (ret) {
+ DRM_DEBUG_KMS("failed to init vcpi %d %d %d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), mgr->avail_slots, ret);
+ goto out;
+ }
+ DRM_DEBUG_KMS("initing vcpi for %d %d\n", pbn, port->vcpi.num_slots);
+ *slots = port->vcpi.num_slots;
+
+ drm_dp_put_port(port);
+ return true;
+out:
+ return false;
+}
+EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
+
+/**
+ * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
+ * @mgr: manager for this port
+ * @port: unverified pointer to a port.
+ *
+ * This just resets the number of slots for the ports VCPI for later programming.
+ */
+void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+ port = drm_dp_get_validated_port_ref(mgr, port);
+ if (!port)
+ return;
+ port->vcpi.num_slots = 0;
+ drm_dp_put_port(port);
+}
+EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots);
+
+/**
+ * drm_dp_mst_deallocate_vcpi() - deallocate a VCPI
+ * @mgr: manager for this port
+ * @port: unverified port to deallocate vcpi for
+ */
+void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
+{
+ port = drm_dp_get_validated_port_ref(mgr, port);
+ if (!port)
+ return;
+
+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+ port->vcpi.num_slots = 0;
+ port->vcpi.pbn = 0;
+ port->vcpi.aligned_pbn = 0;
+ port->vcpi.vcpi = 0;
+ drm_dp_put_port(port);
+}
+EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi);
+
+static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr,
+ int id, struct drm_dp_payload *payload)
+{
+ u8 payload_alloc[3], status;
+ int ret;
+ int retries = 0;
+
+ drm_dp_dpcd_writeb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS,
+ DP_PAYLOAD_TABLE_UPDATED);
+
+ payload_alloc[0] = id;
+ payload_alloc[1] = payload->start_slot;
+ payload_alloc[2] = payload->num_slots;
+
+ ret = drm_dp_dpcd_write(mgr->aux, DP_PAYLOAD_ALLOCATE_SET, payload_alloc, 3);
+ if (ret != 3) {
+ DRM_DEBUG_KMS("failed to write payload allocation %d\n", ret);
+ goto fail;
+ }
+
+retry:
+ ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
+ if (ret < 0) {
+ DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
+ goto fail;
+ }
+
+ if (!(status & DP_PAYLOAD_TABLE_UPDATED)) {
+ retries++;
+ if (retries < 20) {
+ usleep_range(10000, 20000);
+ goto retry;
+ }
+ DRM_DEBUG_KMS("status not set after read payload table status %d\n", status);
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = 0;
+fail:
+ return ret;
+}
+
+
+/**
+ * drm_dp_check_act_status() - Check ACT handled status.
+ * @mgr: manager to use
+ *
+ * Check the payload status bits in the DPCD for ACT handled completion.
+ */
+int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr)
+{
+ u8 status;
+ int ret;
+ int count = 0;
+
+ do {
+ ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
+
+ if (ret < 0) {
+ DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
+ goto fail;
+ }
+
+ if (status & DP_PAYLOAD_ACT_HANDLED)
+ break;
+ count++;
+ udelay(100);
+
+ } while (count < 30);
+
+ if (!(status & DP_PAYLOAD_ACT_HANDLED)) {
+ DRM_DEBUG_KMS("failed to get ACT bit %d after %d retries\n", status, count);
+ ret = -EINVAL;
+ goto fail;
+ }
+ return 0;
+fail:
+ return ret;
+}
+EXPORT_SYMBOL(drm_dp_check_act_status);
+
+/**
+ * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode.
+ * @clock: dot clock for the mode
+ * @bpp: bpp for the mode.
+ *
+ * This uses the formula in the spec to calculate the PBN value for a mode.
+ */
+int drm_dp_calc_pbn_mode(int clock, int bpp)
+{
+ fixed20_12 pix_bw;
+ fixed20_12 fbpp;
+ fixed20_12 result;
+ fixed20_12 margin, tmp;
+ u32 res;
+
+ pix_bw.full = dfixed_const(clock);
+ fbpp.full = dfixed_const(bpp);
+ tmp.full = dfixed_const(8);
+ fbpp.full = dfixed_div(fbpp, tmp);
+
+ result.full = dfixed_mul(pix_bw, fbpp);
+ margin.full = dfixed_const(54);
+ tmp.full = dfixed_const(64);
+ margin.full = dfixed_div(margin, tmp);
+ result.full = dfixed_div(result, margin);
+
+ margin.full = dfixed_const(1006);
+ tmp.full = dfixed_const(1000);
+ margin.full = dfixed_div(margin, tmp);
+ result.full = dfixed_mul(result, margin);
+
+ result.full = dfixed_div(result, tmp);
+ result.full = dfixed_ceil(result);
+ res = dfixed_trunc(result);
+ return res;
+}
+EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
+
+static int test_calc_pbn_mode(void)
+{
+ int ret;
+ ret = drm_dp_calc_pbn_mode(154000, 30);
+ if (ret != 689)
+ return -EINVAL;
+ ret = drm_dp_calc_pbn_mode(234000, 30);
+ if (ret != 1047)
+ return -EINVAL;
+ return 0;
+}
+
+/* we want to kick the TX after we've ack the up/down IRQs. */
+static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr)
+{
+ queue_work(system_long_wq, &mgr->tx_work);
+}
+
+static void drm_dp_mst_dump_mstb(struct seq_file *m,
+ struct drm_dp_mst_branch *mstb)
+{
+ struct drm_dp_mst_port *port;
+ int tabs = mstb->lct;
+ char prefix[10];
+ int i;
+
+ for (i = 0; i < tabs; i++)
+ prefix[i] = '\t';
+ prefix[i] = '\0';
+
+ seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
+ list_for_each_entry(port, &mstb->ports, next) {
+ seq_printf(m, "%sport: %d: ddps: %d ldps: %d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port, port->connector);
+ if (port->mstb)
+ drm_dp_mst_dump_mstb(m, port->mstb);
+ }
+}
+
+static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
+ char *buf)
+{
+ int ret;
+ int i;
+ for (i = 0; i < 4; i++) {
+ ret = drm_dp_dpcd_read(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS + (i * 16), &buf[i * 16], 16);
+ if (ret != 16)
+ break;
+ }
+ if (i == 4)
+ return true;
+ return false;
+}
+
+/**
+ * drm_dp_mst_dump_topology(): dump topology to seq file.
+ * @m: seq_file to dump output to
+ * @mgr: manager to dump current topology for.
+ *
+ * helper to dump MST topology to a seq file for debugfs.
+ */
+void drm_dp_mst_dump_topology(struct seq_file *m,
+ struct drm_dp_mst_topology_mgr *mgr)
+{
+ int i;
+ struct drm_dp_mst_port *port;
+ mutex_lock(&mgr->lock);
+ if (mgr->mst_primary)
+ drm_dp_mst_dump_mstb(m, mgr->mst_primary);
+
+ /* dump VCPIs */
+ mutex_unlock(&mgr->lock);
+
+ mutex_lock(&mgr->payload_lock);
+ seq_printf(m, "vcpi: %lx\n", mgr->payload_mask);
+
+ for (i = 0; i < mgr->max_payloads; i++) {
+ if (mgr->proposed_vcpis[i]) {
+ port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
+ seq_printf(m, "vcpi %d: %d %d %d\n", i, port->port_num, port->vcpi.vcpi, port->vcpi.num_slots);
+ } else
+ seq_printf(m, "vcpi %d:unsed\n", i);
+ }
+ for (i = 0; i < mgr->max_payloads; i++) {
+ seq_printf(m, "payload %d: %d, %d, %d\n",
+ i,
+ mgr->payloads[i].payload_state,
+ mgr->payloads[i].start_slot,
+ mgr->payloads[i].num_slots);
+
+
+ }
+ mutex_unlock(&mgr->payload_lock);
+
+ mutex_lock(&mgr->lock);
+ if (mgr->mst_primary) {
+ u8 buf[64];
+ bool bret;
+ int ret;
+ ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
+ seq_printf(m, "dpcd: ");
+ for (i = 0; i < DP_RECEIVER_CAP_SIZE; i++)
+ seq_printf(m, "%02x ", buf[i]);
+ seq_printf(m, "\n");
+ ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
+ seq_printf(m, "faux/mst: ");
+ for (i = 0; i < 2; i++)
+ seq_printf(m, "%02x ", buf[i]);
+ seq_printf(m, "\n");
+ ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
+ seq_printf(m, "mst ctrl: ");
+ for (i = 0; i < 1; i++)
+ seq_printf(m, "%02x ", buf[i]);
+ seq_printf(m, "\n");
+
+ bret = dump_dp_payload_table(mgr, buf);
+ if (bret == true) {
+ seq_printf(m, "payload table: ");
+ for (i = 0; i < 63; i++)
+ seq_printf(m, "%02x ", buf[i]);
+ seq_printf(m, "\n");
+ }
+
+ }
+
+ mutex_unlock(&mgr->lock);
+
+}
+EXPORT_SYMBOL(drm_dp_mst_dump_topology);
+
+static void drm_dp_tx_work(struct work_struct *work)
+{
+ struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
+
+ mutex_lock(&mgr->qlock);
+ if (mgr->tx_down_in_progress)
+ process_single_down_tx_qlock(mgr);
+ mutex_unlock(&mgr->qlock);
+}
+
+/**
+ * drm_dp_mst_topology_mgr_init - initialise a topology manager
+ * @mgr: manager struct to initialise
+ * @dev: device providing this structure - for i2c addition.
+ * @aux: DP helper aux channel to talk to this device
+ * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit
+ * @max_payloads: maximum number of payloads this GPU can source
+ * @conn_base_id: the connector object ID the MST device is connected to.
+ *
+ * Return 0 for success, or negative error code on failure
+ */
+int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
+ struct device *dev, struct drm_dp_aux *aux,
+ int max_dpcd_transaction_bytes,
+ int max_payloads, int conn_base_id)
+{
+ mutex_init(&mgr->lock);
+ mutex_init(&mgr->qlock);
+ mutex_init(&mgr->payload_lock);
+ INIT_LIST_HEAD(&mgr->tx_msg_upq);
+ INIT_LIST_HEAD(&mgr->tx_msg_downq);
+ INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
+ INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
+ init_waitqueue_head(&mgr->tx_waitq);
+ mgr->dev = dev;
+ mgr->aux = aux;
+ mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes;
+ mgr->max_payloads = max_payloads;
+ mgr->conn_base_id = conn_base_id;
+ mgr->payloads = kcalloc(max_payloads, sizeof(struct drm_dp_payload), GFP_KERNEL);
+ if (!mgr->payloads)
+ return -ENOMEM;
+ mgr->proposed_vcpis = kcalloc(max_payloads, sizeof(struct drm_dp_vcpi *), GFP_KERNEL);
+ if (!mgr->proposed_vcpis)
+ return -ENOMEM;
+ set_bit(0, &mgr->payload_mask);
+ test_calc_pbn_mode();
+ return 0;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
+
+/**
+ * drm_dp_mst_topology_mgr_destroy() - destroy topology manager.
+ * @mgr: manager to destroy
+ */
+void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
+{
+ mutex_lock(&mgr->payload_lock);
+ kfree(mgr->payloads);
+ mgr->payloads = NULL;
+ kfree(mgr->proposed_vcpis);
+ mgr->proposed_vcpis = NULL;
+ mutex_unlock(&mgr->payload_lock);
+ mgr->dev = NULL;
+ mgr->aux = NULL;
+}
+EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
+
+/* I2C device */
+static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+ int num)
+{
+ struct drm_dp_aux *aux = adapter->algo_data;
+ struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux);
+ struct drm_dp_mst_branch *mstb;
+ struct drm_dp_mst_topology_mgr *mgr = port->mgr;
+ unsigned int i;
+ bool reading = false;
+ struct drm_dp_sideband_msg_req_body msg;
+ struct drm_dp_sideband_msg_tx *txmsg = NULL;
+ int ret;
+
+ mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+ if (!mstb)
+ return -EREMOTEIO;
+
+ /* construct i2c msg */
+ /* see if last msg is a read */
+ if (msgs[num - 1].flags & I2C_M_RD)
+ reading = true;
+
+ if (!reading) {
+ DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ msg.req_type = DP_REMOTE_I2C_READ;
+ msg.u.i2c_read.num_transactions = num - 1;
+ msg.u.i2c_read.port_number = port->port_num;
+ for (i = 0; i < num - 1; i++) {
+ msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr;
+ msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len;
+ msg.u.i2c_read.transactions[i].bytes = msgs[i].buf;
+ }
+ msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr;
+ msg.u.i2c_read.num_bytes_read = msgs[num - 1].len;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ txmsg->dst = mstb;
+ drm_dp_encode_sideband_req(&msg, txmsg);
+
+ drm_dp_queue_down_tx(mgr, txmsg);
+
+ ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
+ if (ret > 0) {
+
+ if (txmsg->reply.reply_type == 1) { /* got a NAK back */
+ ret = -EREMOTEIO;
+ goto out;
+ }
+ if (txmsg->reply.u.remote_i2c_read_ack.num_bytes != msgs[num - 1].len) {
+ ret = -EIO;
+ goto out;
+ }
+ memcpy(msgs[num - 1].buf, txmsg->reply.u.remote_i2c_read_ack.bytes, msgs[num - 1].len);
+ ret = num;
+ }
+out:
+ kfree(txmsg);
+ drm_dp_put_mst_branch_device(mstb);
+ return ret;
+}
+
+static u32 drm_dp_mst_i2c_functionality(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm drm_dp_mst_i2c_algo = {
+ .functionality = drm_dp_mst_i2c_functionality,
+ .master_xfer = drm_dp_mst_i2c_xfer,
+};
+
+/**
+ * drm_dp_mst_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
+ * @aux: DisplayPort AUX channel
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux)
+{
+ aux->ddc.algo = &drm_dp_mst_i2c_algo;
+ aux->ddc.algo_data = aux;
+ aux->ddc.retries = 3;
+
+ aux->ddc.class = I2C_CLASS_DDC;
+ aux->ddc.owner = THIS_MODULE;
+ aux->ddc.dev.parent = aux->dev;
+ aux->ddc.dev.of_node = aux->dev->of_node;
+
+ strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
+ sizeof(aux->ddc.name));
+
+ return i2c_add_adapter(&aux->ddc);
+}
+
+/**
+ * drm_dp_mst_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
+ * @aux: DisplayPort AUX channel
+ */
+static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux)
+{
+ i2c_del_adapter(&aux->ddc);
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 8218078b6133..3242e208c0d0 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -1,31 +1,11 @@
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR "VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME "mga"
- * #define DRIVER_DESC "Matrox G200/G400"
- * #define DRIVER_DATE "20001127"
- *
- * #define drm_x mga_##x
- * \endcode
- */
-
/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
*
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
+ * Author Rickard E. (Rik) Faith <faith@valinux.com>
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@@ -40,432 +20,906 @@
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*/
#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mount.h>
#include <linux/slab.h>
-#include <linux/export.h>
#include <drm/drmP.h>
#include <drm/drm_core.h>
+#include "drm_legacy.h"
+unsigned int drm_debug = 0; /* 1 to enable debug output */
+EXPORT_SYMBOL(drm_debug);
-static int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
- [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
-
-/** Ioctl table */
-static const struct drm_ioctl_desc drm_ioctls[] = {
- DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
- DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
-
- DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-#if __OS_HAS_AGP
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#endif
-
- DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
-
- DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
-
- DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
-
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-
- DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
-
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-};
+unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
-#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
+unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
- .owner = THIS_MODULE,
- .open = drm_stub_open,
- .llseek = noop_llseek,
-};
+/*
+ * Default to use monotonic timestamps for wait-for-vblank and page-flip
+ * complete events.
+ */
+unsigned int drm_timestamp_monotonic = 1;
-static int __init drm_core_init(void)
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
+MODULE_LICENSE("GPL and additional rights");
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
+MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
+
+module_param_named(debug, drm_debug, int, 0600);
+module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
+module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
+
+static DEFINE_SPINLOCK(drm_minor_lock);
+static struct idr drm_minors_idr;
+
+struct class *drm_class;
+static struct dentry *drm_debugfs_root;
+
+int drm_err(const char *func, const char *format, ...)
{
- int ret = -ENOMEM;
+ struct va_format vaf;
+ va_list args;
+ int r;
- drm_global_init();
- drm_connector_ida_init();
- idr_init(&drm_minors_idr);
+ va_start(args, format);
- if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
- goto err_p1;
+ vaf.fmt = format;
+ vaf.va = &args;
- drm_class = drm_sysfs_create(THIS_MODULE, "drm");
- if (IS_ERR(drm_class)) {
- printk(KERN_ERR "DRM: Error creating drm class.\n");
- ret = PTR_ERR(drm_class);
- goto err_p2;
+ r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
+
+ va_end(args);
+
+ return r;
+}
+EXPORT_SYMBOL(drm_err);
+
+void drm_ut_debug_printk(const char *function_name, const char *format, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, format);
+ vaf.fmt = format;
+ vaf.va = &args;
+
+ printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
+
+ va_end(args);
+}
+EXPORT_SYMBOL(drm_ut_debug_printk);
+
+struct drm_master *drm_master_create(struct drm_minor *minor)
+{
+ struct drm_master *master;
+
+ master = kzalloc(sizeof(*master), GFP_KERNEL);
+ if (!master)
+ return NULL;
+
+ kref_init(&master->refcount);
+ spin_lock_init(&master->lock.spinlock);
+ init_waitqueue_head(&master->lock.lock_queue);
+ if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
+ kfree(master);
+ return NULL;
}
+ INIT_LIST_HEAD(&master->magicfree);
+ master->minor = minor;
- drm_debugfs_root = debugfs_create_dir("dri", NULL);
- if (!drm_debugfs_root) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
- ret = -1;
- goto err_p3;
+ return master;
+}
+
+struct drm_master *drm_master_get(struct drm_master *master)
+{
+ kref_get(&master->refcount);
+ return master;
+}
+EXPORT_SYMBOL(drm_master_get);
+
+static void drm_master_destroy(struct kref *kref)
+{
+ struct drm_master *master = container_of(kref, struct drm_master, refcount);
+ struct drm_magic_entry *pt, *next;
+ struct drm_device *dev = master->minor->dev;
+ struct drm_map_list *r_list, *list_temp;
+
+ mutex_lock(&dev->struct_mutex);
+ if (dev->driver->master_destroy)
+ dev->driver->master_destroy(dev, master);
+
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+ if (r_list->master == master) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
+ }
}
- DRM_INFO("Initialized %s %d.%d.%d %s\n",
- CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
- return 0;
-err_p3:
- drm_sysfs_destroy();
-err_p2:
- unregister_chrdev(DRM_MAJOR, "drm");
+ if (master->unique) {
+ kfree(master->unique);
+ master->unique = NULL;
+ master->unique_len = 0;
+ }
- idr_destroy(&drm_minors_idr);
-err_p1:
- return ret;
+ list_for_each_entry_safe(pt, next, &master->magicfree, head) {
+ list_del(&pt->head);
+ drm_ht_remove_item(&master->magiclist, &pt->hash_item);
+ kfree(pt);
+ }
+
+ drm_ht_remove(&master->magiclist);
+
+ mutex_unlock(&dev->struct_mutex);
+ kfree(master);
}
-static void __exit drm_core_exit(void)
+void drm_master_put(struct drm_master **master)
{
- debugfs_remove(drm_debugfs_root);
- drm_sysfs_destroy();
+ kref_put(&(*master)->refcount, drm_master_destroy);
+ *master = NULL;
+}
+EXPORT_SYMBOL(drm_master_put);
- unregister_chrdev(DRM_MAJOR, "drm");
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret = 0;
- drm_connector_ida_destroy();
- idr_destroy(&drm_minors_idr);
+ mutex_lock(&dev->master_mutex);
+ if (file_priv->is_master)
+ goto out_unlock;
+
+ if (file_priv->minor->master) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ if (!file_priv->master) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ file_priv->minor->master = drm_master_get(file_priv->master);
+ file_priv->is_master = 1;
+ if (dev->driver->master_set) {
+ ret = dev->driver->master_set(dev, file_priv, false);
+ if (unlikely(ret != 0)) {
+ file_priv->is_master = 0;
+ drm_master_put(&file_priv->minor->master);
+ }
+ }
+
+out_unlock:
+ mutex_unlock(&dev->master_mutex);
+ return ret;
}
-module_init(drm_core_init);
-module_exit(drm_core_exit);
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret = -EINVAL;
-/**
- * Copy and IOCTL return string to user space
+ mutex_lock(&dev->master_mutex);
+ if (!file_priv->is_master)
+ goto out_unlock;
+
+ if (!file_priv->minor->master)
+ goto out_unlock;
+
+ ret = 0;
+ if (dev->driver->master_drop)
+ dev->driver->master_drop(dev, file_priv, false);
+ drm_master_put(&file_priv->minor->master);
+ file_priv->is_master = 0;
+
+out_unlock:
+ mutex_unlock(&dev->master_mutex);
+ return ret;
+}
+
+/*
+ * DRM Minors
+ * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
+ * of them is represented by a drm_minor object. Depending on the capabilities
+ * of the device-driver, different interfaces are registered.
+ *
+ * Minors can be accessed via dev->$minor_name. This pointer is either
+ * NULL or a valid drm_minor pointer and stays valid as long as the device is
+ * valid. This means, DRM minors have the same life-time as the underlying
+ * device. However, this doesn't mean that the minor is active. Minors are
+ * registered and unregistered dynamically according to device-state.
*/
-static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
+
+static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
+ unsigned int type)
{
- int len;
+ switch (type) {
+ case DRM_MINOR_LEGACY:
+ return &dev->primary;
+ case DRM_MINOR_RENDER:
+ return &dev->render;
+ case DRM_MINOR_CONTROL:
+ return &dev->control;
+ default:
+ return NULL;
+ }
+}
- /* don't overflow userbuf */
- len = strlen(value);
- if (len > *buf_len)
- len = *buf_len;
+static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
+{
+ struct drm_minor *minor;
+ unsigned long flags;
+ int r;
+
+ minor = kzalloc(sizeof(*minor), GFP_KERNEL);
+ if (!minor)
+ return -ENOMEM;
+
+ minor->type = type;
+ minor->dev = dev;
+
+ idr_preload(GFP_KERNEL);
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ r = idr_alloc(&drm_minors_idr,
+ NULL,
+ 64 * type,
+ 64 * (type + 1),
+ GFP_NOWAIT);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+ idr_preload_end();
+
+ if (r < 0)
+ goto err_free;
+
+ minor->index = r;
+
+ minor->kdev = drm_sysfs_minor_alloc(minor);
+ if (IS_ERR(minor->kdev)) {
+ r = PTR_ERR(minor->kdev);
+ goto err_index;
+ }
- /* let userspace know exact length of driver value (which could be
- * larger than the userspace-supplied buffer) */
- *buf_len = strlen(value);
+ *drm_minor_get_slot(dev, type) = minor;
+ return 0;
+
+err_index:
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_remove(&drm_minors_idr, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+err_free:
+ kfree(minor);
+ return r;
+}
+
+static void drm_minor_free(struct drm_device *dev, unsigned int type)
+{
+ struct drm_minor **slot, *minor;
+ unsigned long flags;
+
+ slot = drm_minor_get_slot(dev, type);
+ minor = *slot;
+ if (!minor)
+ return;
+
+ drm_mode_group_destroy(&minor->mode_group);
+ put_device(minor->kdev);
+
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_remove(&drm_minors_idr, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+ kfree(minor);
+ *slot = NULL;
+}
- /* finally, try filling in the userbuf */
- if (len && buf)
- if (copy_to_user(buf, value, len))
- return -EFAULT;
+static int drm_minor_register(struct drm_device *dev, unsigned int type)
+{
+ struct drm_minor *minor;
+ unsigned long flags;
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ minor = *drm_minor_get_slot(dev, type);
+ if (!minor)
+ return 0;
+
+ ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
+ if (ret) {
+ DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
+ return ret;
+ }
+
+ ret = device_add(minor->kdev);
+ if (ret)
+ goto err_debugfs;
+
+ /* replace NULL with @minor so lookups will succeed from now on */
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_replace(&drm_minors_idr, minor, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+ DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;
+
+err_debugfs:
+ drm_debugfs_cleanup(minor);
+ return ret;
+}
+
+static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
+{
+ struct drm_minor *minor;
+ unsigned long flags;
+
+ minor = *drm_minor_get_slot(dev, type);
+ if (!minor || !device_is_registered(minor->kdev))
+ return;
+
+ /* replace @minor with NULL so lookups will fail from now on */
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_replace(&drm_minors_idr, NULL, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+ device_del(minor->kdev);
+ dev_set_drvdata(minor->kdev, NULL); /* safety belt */
+ drm_debugfs_cleanup(minor);
}
/**
- * Get version information
+ * drm_minor_acquire - Acquire a DRM minor
+ * @minor_id: Minor ID of the DRM-minor
+ *
+ * Looks up the given minor-ID and returns the respective DRM-minor object. The
+ * refence-count of the underlying device is increased so you must release this
+ * object with drm_minor_release().
*
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_version structure.
- * \return zero on success or negative number on failure.
+ * As long as you hold this minor, it is guaranteed that the object and the
+ * minor->dev pointer will stay valid! However, the device may get unplugged and
+ * unregistered while you hold the minor.
*
- * Fills in the version information in \p arg.
+ * Returns:
+ * Pointer to minor-object with increased device-refcount, or PTR_ERR on
+ * failure.
*/
-static int drm_version(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+struct drm_minor *drm_minor_acquire(unsigned int minor_id)
{
- struct drm_version *version = data;
- int err;
+ struct drm_minor *minor;
+ unsigned long flags;
+
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ minor = idr_find(&drm_minors_idr, minor_id);
+ if (minor)
+ drm_dev_ref(minor->dev);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+
+ if (!minor) {
+ return ERR_PTR(-ENODEV);
+ } else if (drm_device_is_unplugged(minor->dev)) {
+ drm_dev_unref(minor->dev);
+ return ERR_PTR(-ENODEV);
+ }
- version->version_major = dev->driver->major;
- version->version_minor = dev->driver->minor;
- version->version_patchlevel = dev->driver->patchlevel;
- err = drm_copy_field(version->name, &version->name_len,
- dev->driver->name);
- if (!err)
- err = drm_copy_field(version->date, &version->date_len,
- dev->driver->date);
- if (!err)
- err = drm_copy_field(version->desc, &version->desc_len,
- dev->driver->desc);
+ return minor;
+}
- return err;
+/**
+ * drm_minor_release - Release DRM minor
+ * @minor: Pointer to DRM minor object
+ *
+ * Release a minor that was previously acquired via drm_minor_acquire().
+ */
+void drm_minor_release(struct drm_minor *minor)
+{
+ drm_dev_unref(minor->dev);
}
/**
- * drm_ioctl_permit - Check ioctl permissions against caller
+ * drm_put_dev - Unregister and release a DRM device
+ * @dev: DRM device
+ *
+ * Called at module unload time or when a PCI device is unplugged.
*
- * @flags: ioctl permission flags.
- * @file_priv: Pointer to struct drm_file identifying the caller.
+ * Use of this function is discouraged. It will eventually go away completely.
+ * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
*
- * Checks whether the caller is allowed to run an ioctl with the
- * indicated permissions. If so, returns zero. Otherwise returns an
- * error code suitable for ioctl return.
+ * Cleans up all DRM device, calling drm_lastclose().
*/
-static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+void drm_put_dev(struct drm_device *dev)
{
- /* ROOT_ONLY is only for CAP_SYS_ADMIN */
- if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
- return -EACCES;
-
- /* AUTH is only for authenticated or render client */
- if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
- !file_priv->authenticated))
- return -EACCES;
-
- /* MASTER is only for master or control clients */
- if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
- !drm_is_control_client(file_priv)))
- return -EACCES;
-
- /* Control clients must be explicitly allowed */
- if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
- drm_is_control_client(file_priv)))
- return -EACCES;
-
- /* Render clients must be explicitly allowed */
- if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
- drm_is_render_client(file_priv)))
- return -EACCES;
+ DRM_DEBUG("\n");
- return 0;
+ if (!dev) {
+ DRM_ERROR("cleanup called no dev\n");
+ return;
+ }
+
+ drm_dev_unregister(dev);
+ drm_dev_unref(dev);
+}
+EXPORT_SYMBOL(drm_put_dev);
+
+void drm_unplug_dev(struct drm_device *dev)
+{
+ /* for a USB device */
+ drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+ drm_minor_unregister(dev, DRM_MINOR_RENDER);
+ drm_minor_unregister(dev, DRM_MINOR_CONTROL);
+
+ mutex_lock(&drm_global_mutex);
+
+ drm_device_set_unplugged(dev);
+
+ if (dev->open_count == 0) {
+ drm_put_dev(dev);
+ }
+ mutex_unlock(&drm_global_mutex);
+}
+EXPORT_SYMBOL(drm_unplug_dev);
+
+/*
+ * DRM internal mount
+ * We want to be able to allocate our own "struct address_space" to control
+ * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow
+ * stand-alone address_space objects, so we need an underlying inode. As there
+ * is no way to allocate an independent inode easily, we need a fake internal
+ * VFS mount-point.
+ *
+ * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free()
+ * frees it again. You are allowed to use iget() and iput() to get references to
+ * the inode. But each drm_fs_inode_new() call must be paired with exactly one
+ * drm_fs_inode_free() call (which does not have to be the last iput()).
+ * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it
+ * between multiple inode-users. You could, technically, call
+ * iget() + drm_fs_inode_free() directly after alloc and sometime later do an
+ * iput(), but this way you'd end up with a new vfsmount for each inode.
+ */
+
+static int drm_fs_cnt;
+static struct vfsmount *drm_fs_mnt;
+
+static const struct dentry_operations drm_fs_dops = {
+ .d_dname = simple_dname,
+};
+
+static const struct super_operations drm_fs_sops = {
+ .statfs = simple_statfs,
+};
+
+static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
+{
+ return mount_pseudo(fs_type,
+ "drm:",
+ &drm_fs_sops,
+ &drm_fs_dops,
+ 0x010203ff);
+}
+
+static struct file_system_type drm_fs_type = {
+ .name = "drm",
+ .owner = THIS_MODULE,
+ .mount = drm_fs_mount,
+ .kill_sb = kill_anon_super,
+};
+
+static struct inode *drm_fs_inode_new(void)
+{
+ struct inode *inode;
+ int r;
+
+ r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
+ if (r < 0) {
+ DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
+ return ERR_PTR(r);
+ }
+
+ inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
+ if (IS_ERR(inode))
+ simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
+
+ return inode;
+}
+
+static void drm_fs_inode_free(struct inode *inode)
+{
+ if (inode) {
+ iput(inode);
+ simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
+ }
}
/**
- * Called whenever a process performs an ioctl on /dev/drm.
+ * drm_dev_alloc - Allocate new DRM device
+ * @driver: DRM driver to allocate device for
+ * @parent: Parent device object
*
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+ * Allocate and initialize a new DRM device. No device registration is done.
+ * Call drm_dev_register() to advertice the device to user space and register it
+ * with other core subsystems.
*
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
+ * The initial ref-count of the object is 1. Use drm_dev_ref() and
+ * drm_dev_unref() to take and drop further ref-counts.
+ *
+ * RETURNS:
+ * Pointer to new DRM device, or NULL if out of memory.
*/
-long drm_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
+struct drm_device *drm_dev_alloc(struct drm_driver *driver,
+ struct device *parent)
{
- struct drm_file *file_priv = filp->private_data;
struct drm_device *dev;
- const struct drm_ioctl_desc *ioctl = NULL;
- drm_ioctl_t *func;
- unsigned int nr = DRM_IOCTL_NR(cmd);
- int retcode = -EINVAL;
- char stack_kdata[128];
- char *kdata = NULL;
- unsigned int usize, asize;
-
- dev = file_priv->minor->dev;
-
- if (drm_device_is_unplugged(dev))
- return -ENODEV;
-
- if ((nr >= DRM_CORE_IOCTL_COUNT) &&
- ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
- goto err_i1;
- if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
- (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
- u32 drv_size;
- ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
- drv_size = _IOC_SIZE(ioctl->cmd_drv);
- usize = asize = _IOC_SIZE(cmd);
- if (drv_size > asize)
- asize = drv_size;
- cmd = ioctl->cmd_drv;
+ int ret;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ kref_init(&dev->ref);
+ dev->dev = parent;
+ dev->driver = driver;
+
+ INIT_LIST_HEAD(&dev->filelist);
+ INIT_LIST_HEAD(&dev->ctxlist);
+ INIT_LIST_HEAD(&dev->vmalist);
+ INIT_LIST_HEAD(&dev->maplist);
+ INIT_LIST_HEAD(&dev->vblank_event_list);
+
+ spin_lock_init(&dev->buf_lock);
+ spin_lock_init(&dev->event_lock);
+ mutex_init(&dev->struct_mutex);
+ mutex_init(&dev->ctxlist_mutex);
+ mutex_init(&dev->master_mutex);
+
+ dev->anon_inode = drm_fs_inode_new();
+ if (IS_ERR(dev->anon_inode)) {
+ ret = PTR_ERR(dev->anon_inode);
+ DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
+ goto err_free;
}
- else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
- u32 drv_size;
-
- ioctl = &drm_ioctls[nr];
- drv_size = _IOC_SIZE(ioctl->cmd);
- usize = asize = _IOC_SIZE(cmd);
- if (drv_size > asize)
- asize = drv_size;
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
+ if (ret)
+ goto err_minors;
+ }
- cmd = ioctl->cmd;
- } else
- goto err_i1;
+ if (drm_core_check_feature(dev, DRIVER_RENDER)) {
+ ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
+ if (ret)
+ goto err_minors;
+ }
- DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
- task_pid_nr(current),
- (long)old_encode_dev(file_priv->minor->kdev->devt),
- file_priv->authenticated, ioctl->name);
+ ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
+ if (ret)
+ goto err_minors;
- /* Do not trust userspace, use our own definition */
- func = ioctl->func;
+ if (drm_ht_create(&dev->map_hash, 12))
+ goto err_minors;
- if (unlikely(!func)) {
- DRM_DEBUG("no function\n");
- retcode = -EINVAL;
- goto err_i1;
+ ret = drm_legacy_ctxbitmap_init(dev);
+ if (ret) {
+ DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+ goto err_ht;
}
- retcode = drm_ioctl_permit(ioctl->flags, file_priv);
- if (unlikely(retcode))
- goto err_i1;
-
- if (cmd & (IOC_IN | IOC_OUT)) {
- if (asize <= sizeof(stack_kdata)) {
- kdata = stack_kdata;
- } else {
- kdata = kmalloc(asize, GFP_KERNEL);
- if (!kdata) {
- retcode = -ENOMEM;
- goto err_i1;
- }
+ if (driver->driver_features & DRIVER_GEM) {
+ ret = drm_gem_init(dev);
+ if (ret) {
+ DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
+ goto err_ctxbitmap;
}
- if (asize > usize)
- memset(kdata + usize, 0, asize - usize);
}
- if (cmd & IOC_IN) {
- if (copy_from_user(kdata, (void __user *)arg,
- usize) != 0) {
- retcode = -EFAULT;
- goto err_i1;
- }
- } else if (cmd & IOC_OUT) {
- memset(kdata, 0, usize);
- }
+ return dev;
+
+err_ctxbitmap:
+ drm_legacy_ctxbitmap_cleanup(dev);
+err_ht:
+ drm_ht_remove(&dev->map_hash);
+err_minors:
+ drm_minor_free(dev, DRM_MINOR_LEGACY);
+ drm_minor_free(dev, DRM_MINOR_RENDER);
+ drm_minor_free(dev, DRM_MINOR_CONTROL);
+ drm_fs_inode_free(dev->anon_inode);
+err_free:
+ mutex_destroy(&dev->master_mutex);
+ kfree(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(drm_dev_alloc);
+
+static void drm_dev_release(struct kref *ref)
+{
+ struct drm_device *dev = container_of(ref, struct drm_device, ref);
+
+ if (dev->driver->driver_features & DRIVER_GEM)
+ drm_gem_destroy(dev);
+
+ drm_legacy_ctxbitmap_cleanup(dev);
+ drm_ht_remove(&dev->map_hash);
+ drm_fs_inode_free(dev->anon_inode);
+
+ drm_minor_free(dev, DRM_MINOR_LEGACY);
+ drm_minor_free(dev, DRM_MINOR_RENDER);
+ drm_minor_free(dev, DRM_MINOR_CONTROL);
+
+ mutex_destroy(&dev->master_mutex);
+ kfree(dev->unique);
+ kfree(dev);
+}
- if (ioctl->flags & DRM_UNLOCKED)
- retcode = func(dev, kdata, file_priv);
- else {
- mutex_lock(&drm_global_mutex);
- retcode = func(dev, kdata, file_priv);
- mutex_unlock(&drm_global_mutex);
+/**
+ * drm_dev_ref - Take reference of a DRM device
+ * @dev: device to take reference of or NULL
+ *
+ * This increases the ref-count of @dev by one. You *must* already own a
+ * reference when calling this. Use drm_dev_unref() to drop this reference
+ * again.
+ *
+ * This function never fails. However, this function does not provide *any*
+ * guarantee whether the device is alive or running. It only provides a
+ * reference to the object and the memory associated with it.
+ */
+void drm_dev_ref(struct drm_device *dev)
+{
+ if (dev)
+ kref_get(&dev->ref);
+}
+EXPORT_SYMBOL(drm_dev_ref);
+
+/**
+ * drm_dev_unref - Drop reference of a DRM device
+ * @dev: device to drop reference of or NULL
+ *
+ * This decreases the ref-count of @dev by one. The device is destroyed if the
+ * ref-count drops to zero.
+ */
+void drm_dev_unref(struct drm_device *dev)
+{
+ if (dev)
+ kref_put(&dev->ref, drm_dev_release);
+}
+EXPORT_SYMBOL(drm_dev_unref);
+
+/**
+ * drm_dev_register - Register DRM device
+ * @dev: Device to register
+ * @flags: Flags passed to the driver's .load() function
+ *
+ * Register the DRM device @dev with the system, advertise device to user-space
+ * and start normal device operation. @dev must be allocated via drm_dev_alloc()
+ * previously.
+ *
+ * Never call this twice on any device!
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int drm_dev_register(struct drm_device *dev, unsigned long flags)
+{
+ int ret;
+
+ mutex_lock(&drm_global_mutex);
+
+ ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
+ if (ret)
+ goto err_minors;
+
+ ret = drm_minor_register(dev, DRM_MINOR_RENDER);
+ if (ret)
+ goto err_minors;
+
+ ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
+ if (ret)
+ goto err_minors;
+
+ if (dev->driver->load) {
+ ret = dev->driver->load(dev, flags);
+ if (ret)
+ goto err_minors;
}
- if (cmd & IOC_OUT) {
- if (copy_to_user((void __user *)arg, kdata,
- usize) != 0)
- retcode = -EFAULT;
+ /* setup grouping for legacy outputs */
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = drm_mode_group_init_legacy_group(dev,
+ &dev->primary->mode_group);
+ if (ret)
+ goto err_unload;
}
- err_i1:
- if (!ioctl)
- DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
- task_pid_nr(current),
- (long)old_encode_dev(file_priv->minor->kdev->devt),
- file_priv->authenticated, cmd, nr);
-
- if (kdata != stack_kdata)
- kfree(kdata);
- if (retcode)
- DRM_DEBUG("ret = %d\n", retcode);
- return retcode;
+ ret = 0;
+ goto out_unlock;
+
+err_unload:
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
+err_minors:
+ drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+ drm_minor_unregister(dev, DRM_MINOR_RENDER);
+ drm_minor_unregister(dev, DRM_MINOR_CONTROL);
+out_unlock:
+ mutex_unlock(&drm_global_mutex);
+ return ret;
}
-EXPORT_SYMBOL(drm_ioctl);
+EXPORT_SYMBOL(drm_dev_register);
/**
- * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ * drm_dev_unregister - Unregister DRM device
+ * @dev: Device to unregister
+ *
+ * Unregister the DRM device from the system. This does the reverse of
+ * drm_dev_register() but does not deallocate the device. The caller must call
+ * drm_dev_unref() to drop their final reference.
+ */
+void drm_dev_unregister(struct drm_device *dev)
+{
+ struct drm_map_list *r_list, *list_temp;
+
+ drm_lastclose(dev);
+
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
+
+ if (dev->agp)
+ drm_pci_agp_destroy(dev);
+
+ drm_vblank_cleanup(dev);
+
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+ drm_rmmap(dev, r_list->map);
+
+ drm_minor_unregister(dev, DRM_MINOR_LEGACY);
+ drm_minor_unregister(dev, DRM_MINOR_RENDER);
+ drm_minor_unregister(dev, DRM_MINOR_CONTROL);
+}
+EXPORT_SYMBOL(drm_dev_unregister);
+
+/**
+ * drm_dev_set_unique - Set the unique name of a DRM device
+ * @dev: device of which to set the unique name
+ * @fmt: format string for unique name
+ *
+ * Sets the unique name of a DRM device using the specified format string and
+ * a variable list of arguments. Drivers can use this at driver probe time if
+ * the unique name of the devices they drive is static.
*
- * @nr: Ioctl number.
- * @flags: Where to return the ioctl permission flags
+ * Return: 0 on success or a negative error code on failure.
*/
-bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...)
{
- if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
- (nr < DRM_COMMAND_BASE)) {
- *flags = drm_ioctls[nr].flags;
- return true;
+ va_list ap;
+
+ kfree(dev->unique);
+
+ va_start(ap, fmt);
+ dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
+ va_end(ap);
+
+ return dev->unique ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(drm_dev_set_unique);
+
+/*
+ * DRM Core
+ * The DRM core module initializes all global DRM objects and makes them
+ * available to drivers. Once setup, drivers can probe their respective
+ * devices.
+ * Currently, core management includes:
+ * - The "DRM-Global" key/value database
+ * - Global ID management for connectors
+ * - DRM major number allocation
+ * - DRM minor management
+ * - DRM sysfs class
+ * - DRM debugfs root
+ *
+ * Furthermore, the DRM core provides dynamic char-dev lookups. For each
+ * interface registered on a DRM device, you can request minor numbers from DRM
+ * core. DRM core takes care of major-number management and char-dev
+ * registration. A stub ->open() callback forwards any open() requests to the
+ * registered minor.
+ */
+
+static int drm_stub_open(struct inode *inode, struct file *filp)
+{
+ const struct file_operations *new_fops;
+ struct drm_minor *minor;
+ int err;
+
+ DRM_DEBUG("\n");
+
+ mutex_lock(&drm_global_mutex);
+ minor = drm_minor_acquire(iminor(inode));
+ if (IS_ERR(minor)) {
+ err = PTR_ERR(minor);
+ goto out_unlock;
+ }
+
+ new_fops = fops_get(minor->dev->driver->fops);
+ if (!new_fops) {
+ err = -ENODEV;
+ goto out_release;
}
- return false;
+ replace_fops(filp, new_fops);
+ if (filp->f_op->open)
+ err = filp->f_op->open(inode, filp);
+ else
+ err = 0;
+
+out_release:
+ drm_minor_release(minor);
+out_unlock:
+ mutex_unlock(&drm_global_mutex);
+ return err;
}
-EXPORT_SYMBOL(drm_ioctl_flags);
+
+static const struct file_operations drm_stub_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_stub_open,
+ .llseek = noop_llseek,
+};
+
+static int __init drm_core_init(void)
+{
+ int ret = -ENOMEM;
+
+ drm_global_init();
+ drm_connector_ida_init();
+ idr_init(&drm_minors_idr);
+
+ if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+ goto err_p1;
+
+ drm_class = drm_sysfs_create(THIS_MODULE, "drm");
+ if (IS_ERR(drm_class)) {
+ printk(KERN_ERR "DRM: Error creating drm class.\n");
+ ret = PTR_ERR(drm_class);
+ goto err_p2;
+ }
+
+ drm_debugfs_root = debugfs_create_dir("dri", NULL);
+ if (!drm_debugfs_root) {
+ DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
+ ret = -1;
+ goto err_p3;
+ }
+
+ DRM_INFO("Initialized %s %d.%d.%d %s\n",
+ CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+ return 0;
+err_p3:
+ drm_sysfs_destroy();
+err_p2:
+ unregister_chrdev(DRM_MAJOR, "drm");
+
+ idr_destroy(&drm_minors_idr);
+err_p1:
+ return ret;
+}
+
+static void __exit drm_core_exit(void)
+{
+ debugfs_remove(drm_debugfs_root);
+ drm_sysfs_destroy();
+
+ unregister_chrdev(DRM_MAJOR, "drm");
+
+ drm_connector_ida_destroy();
+ idr_destroy(&drm_minors_idr);
+}
+
+module_init(drm_core_init);
+module_exit(drm_core_exit);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index dfa9769b26b5..1dbf3bc4c6a3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3305,6 +3305,7 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder && connector->eld[0])
@@ -3775,8 +3776,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
- /* Populate picture aspect ratio from CEA mode list */
- if (frame->video_code > 0)
+ /*
+ * Populate picture aspect ratio from either
+ * user input (if specified) or from the CEA mode list.
+ */
+ if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_4_3 ||
+ mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_16_9)
+ frame->picture_aspect = mode->picture_aspect_ratio;
+ else if (frame->video_code > 0)
frame->picture_aspect = drm_get_cea_aspect_ratio(
frame->video_code);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index f27c883be391..cc0ae047ed3b 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -327,7 +327,7 @@ err_drm_gem_cma_free_object:
return ret;
}
-static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
.fb_probe = drm_fbdev_cma_create,
};
@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
return ERR_PTR(-ENOMEM);
}
- fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
helper = &fbdev_cma->fb_helper;
+ drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
+
ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
if (ret < 0) {
dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d5d8cea1a679..3144db9dc0f1 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list);
* helper functions used by many drivers to implement the kernel mode setting
* interfaces.
*
- * Initialization is done as a three-step process with drm_fb_helper_init(),
- * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config().
- * Drivers with fancier requirements than the default behaviour can override the
- * second step with their own code. Teardown is done with drm_fb_helper_fini().
+ * Initialization is done as a four-step process with drm_fb_helper_prepare(),
+ * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
+ * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
+ * default behaviour can override the third step with their own code.
+ * Teardown is done with drm_fb_helper_fini().
*
* At runtime drivers should restore the fbdev console by calling
* drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
@@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list);
*
* All other functions exported by the fb helper library can be used to
* implement the fbdev driver interface by the driver.
+ *
+ * It is possible, though perhaps somewhat tricky, to implement race-free
+ * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
+ * helper must be called first to initialize the minimum required to make
+ * hotplug detection work. Drivers also need to make sure to properly set up
+ * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
+ * it is safe to enable interrupts and start processing hotplug events. At the
+ * same time, drivers should initialize all modeset objects such as CRTCs,
+ * encoders and connectors. To finish up the fbdev helper initialization, the
+ * drm_fb_helper_init() function is called. To probe for all attached displays
+ * and set up an initial configuration using the detected hardware, drivers
+ * should call drm_fb_helper_single_add_all_connectors() followed by
+ * drm_fb_helper_initial_config().
*/
/**
@@ -105,6 +119,58 @@ fail:
}
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
+int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector)
+{
+ struct drm_fb_helper_connector **temp;
+ struct drm_fb_helper_connector *fb_helper_connector;
+
+ WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
+ if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
+ temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
+ if (!temp)
+ return -ENOMEM;
+
+ fb_helper->connector_info_alloc_count = fb_helper->connector_count + 1;
+ fb_helper->connector_info = temp;
+ }
+
+
+ fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
+ if (!fb_helper_connector)
+ return -ENOMEM;
+
+ fb_helper_connector->connector = connector;
+ fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
+ return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
+
+int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
+ struct drm_connector *connector)
+{
+ struct drm_fb_helper_connector *fb_helper_connector;
+ int i, j;
+
+ WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
+
+ for (i = 0; i < fb_helper->connector_count; i++) {
+ if (fb_helper->connector_info[i]->connector == connector)
+ break;
+ }
+
+ if (i == fb_helper->connector_count)
+ return -EINVAL;
+ fb_helper_connector = fb_helper->connector_info[i];
+
+ for (j = i + 1; j < fb_helper->connector_count; j++) {
+ fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
+ }
+ fb_helper->connector_count--;
+ kfree(fb_helper_connector);
+ return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
+
static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
{
struct drm_fb_helper_connector *fb_helper_conn;
@@ -199,9 +265,6 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
struct drm_crtc_helper_funcs *funcs;
int i;
- if (list_empty(&kernel_fb_helper_list))
- return false;
-
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
for (i = 0; i < helper->crtc_count; i++) {
struct drm_mode_set *mode_set =
@@ -531,6 +594,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
}
/**
+ * drm_fb_helper_prepare - setup a drm_fb_helper structure
+ * @dev: DRM device
+ * @helper: driver-allocated fbdev helper structure to set up
+ * @funcs: pointer to structure of functions associate with this helper
+ *
+ * Sets up the bare minimum to make the framebuffer helper usable. This is
+ * useful to implement race-free initialization of the polling helpers.
+ */
+void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
+ const struct drm_fb_helper_funcs *funcs)
+{
+ INIT_LIST_HEAD(&helper->kernel_fb_list);
+ helper->funcs = funcs;
+ helper->dev = dev;
+}
+EXPORT_SYMBOL(drm_fb_helper_prepare);
+
+/**
* drm_fb_helper_init - initialize a drm_fb_helper structure
* @dev: drm device
* @fb_helper: driver-allocated fbdev helper structure to initialize
@@ -542,8 +623,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
* nor register the fbdev. This is only done in drm_fb_helper_initial_config()
* to allow driver writes more control over the exact init sequence.
*
- * Drivers must set fb_helper->funcs before calling
- * drm_fb_helper_initial_config().
+ * Drivers must call drm_fb_helper_prepare() before calling this function.
*
* RETURNS:
* Zero if everything went ok, nonzero otherwise.
@@ -558,10 +638,6 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!max_conn_count)
return -EINVAL;
- fb_helper->dev = dev;
-
- INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
-
fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
if (!fb_helper->crtc_info)
return -ENOMEM;
@@ -572,6 +648,7 @@ int drm_fb_helper_init(struct drm_device *dev,
kfree(fb_helper->crtc_info);
return -ENOMEM;
}
+ fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
fb_helper->connector_count = 0;
for (i = 0; i < crtc_count; i++) {
@@ -1056,7 +1133,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
info->fix.ypanstep = 1; /* doing it in hw */
info->fix.ywrapstep = 0;
info->fix.accel = FB_ACCEL_NONE;
- info->fix.type_aux = 0;
info->fix.line_length = pitch;
return;
@@ -1613,8 +1689,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
* either the output polling work or a work item launched from the driver's
* hotplug interrupt).
*
- * Note that the driver must ensure that this is only called _after_ the fb has
- * been fully set up, i.e. after the call to drm_fb_helper_initial_config.
+ * Note that drivers may call this even before calling
+ * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
+ * for a race-free fbcon setup and will make sure that the fbdev emulation will
+ * not miss any hotplug events.
*
* RETURNS:
* 0 on success and a non-zero error code otherwise.
@@ -1624,11 +1702,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
struct drm_device *dev = fb_helper->dev;
u32 max_width, max_height;
- if (!fb_helper->fb)
- return 0;
-
mutex_lock(&fb_helper->dev->mode_config.mutex);
- if (!drm_fb_helper_is_bound(fb_helper)) {
+ if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
fb_helper->delayed_hotplug = true;
mutex_unlock(&fb_helper->dev->mode_config.mutex);
return 0;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 021fe5d11df5..79d5221c6e41 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -38,6 +38,7 @@
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include "drm_legacy.h"
/* from BKL pushdown */
DEFINE_MUTEX(drm_global_mutex);
@@ -112,55 +113,12 @@ err_undo:
EXPORT_SYMBOL(drm_open);
/**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
- struct drm_device *dev;
- struct drm_minor *minor;
- int err = -ENODEV;
- const struct file_operations *new_fops;
-
- DRM_DEBUG("\n");
-
- mutex_lock(&drm_global_mutex);
- minor = drm_minor_acquire(iminor(inode));
- if (IS_ERR(minor))
- goto out_unlock;
-
- dev = minor->dev;
- new_fops = fops_get(dev->driver->fops);
- if (!new_fops)
- goto out_release;
-
- replace_fops(filp, new_fops);
- if (filp->f_op->open)
- err = filp->f_op->open(inode, filp);
-
-out_release:
- drm_minor_release(minor);
-out_unlock:
- mutex_unlock(&drm_global_mutex);
- return err;
-}
-
-/**
* Check whether DRI will run on this CPU.
*
* \return non-zero if the DRI will run on this CPU, or zero otherwise.
*/
static int drm_cpu_valid(void)
{
-#if defined(__i386__)
- if (boot_cpu_data.x86 == 3)
- return 0; /* No cmpxchg on a 386 */
-#endif
#if defined(__sparc__) && !defined(__sparc_v9__)
return 0; /* No cmpxchg before v9 sparc. */
#endif
@@ -203,8 +161,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
priv->minor = minor;
/* for compatibility root is always authenticated */
- priv->always_authenticated = capable(CAP_SYS_ADMIN);
- priv->authenticated = priv->always_authenticated;
+ priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
INIT_LIST_HEAD(&priv->lhead);
@@ -429,6 +386,10 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
+ mutex_lock(&dev->struct_mutex);
+ list_del(&file_priv->lhead);
+ mutex_unlock(&dev->struct_mutex);
+
if (dev->driver->preclose)
dev->driver->preclose(dev, file_priv);
@@ -461,44 +422,18 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv);
- mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist)) {
- struct drm_ctx_list *pos, *n;
-
- list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
- if (pos->tag == file_priv &&
- pos->handle != DRM_KERNEL_CONTEXT) {
- if (dev->driver->context_dtor)
- dev->driver->context_dtor(dev,
- pos->handle);
-
- drm_ctxbitmap_free(dev, pos->handle);
-
- list_del(&pos->head);
- kfree(pos);
- }
- }
- }
- mutex_unlock(&dev->ctxlist_mutex);
+ drm_legacy_ctxbitmap_flush(dev, file_priv);
mutex_lock(&dev->master_mutex);
if (file_priv->is_master) {
struct drm_master *master = file_priv->master;
- struct drm_file *temp;
-
- mutex_lock(&dev->struct_mutex);
- list_for_each_entry(temp, &dev->filelist, lhead) {
- if ((temp->master == file_priv->master) &&
- (temp != file_priv))
- temp->authenticated = temp->always_authenticated;
- }
/**
* Since the master is disappearing, so is the
* possibility to lock.
*/
-
+ mutex_lock(&dev->struct_mutex);
if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
@@ -522,10 +457,6 @@ int drm_release(struct inode *inode, struct file *filp)
file_priv->is_master = 0;
mutex_unlock(&dev->master_mutex);
- mutex_lock(&dev->struct_mutex);
- list_del(&file_priv->lhead);
- mutex_unlock(&dev->struct_mutex);
-
if (dev->driver->postclose)
dev->driver->postclose(dev, file_priv);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index f7d71190aad5..6adee4c2afc0 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -441,18 +441,31 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset);
* drm_gem_get_pages - helper to allocate backing pages for a GEM object
* from shmem
* @obj: obj in question
- * @gfpmask: gfp mask of requested pages
+ *
+ * This reads the page-array of the shmem-backing storage of the given gem
+ * object. An array of pages is returned. If a page is not allocated or
+ * swapped-out, this will allocate/swap-in the required pages. Note that the
+ * whole object is covered by the page-array and pinned in memory.
+ *
+ * Use drm_gem_put_pages() to release the array and unpin all pages.
+ *
+ * This uses the GFP-mask set on the shmem-mapping (see mapping_set_gfp_mask()).
+ * If you require other GFP-masks, you have to do those allocations yourself.
+ *
+ * Note that you are not allowed to change gfp-zones during runtime. That is,
+ * shmem_read_mapping_page_gfp() must be called with the same gfp_zone(gfp) as
+ * set during initialization. If you have special zone constraints, set them
+ * after drm_gem_init_object() via mapping_set_gfp_mask(). shmem-core takes care
+ * to keep pages in the required zone during swap-in.
*/
-struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
+struct page **drm_gem_get_pages(struct drm_gem_object *obj)
{
- struct inode *inode;
struct address_space *mapping;
struct page *p, **pages;
int i, npages;
/* This is the shared memory object that backs the GEM resource */
- inode = file_inode(obj->filp);
- mapping = inode->i_mapping;
+ mapping = file_inode(obj->filp)->i_mapping;
/* We already BUG_ON() for non-page-aligned sizes in
* drm_gem_object_init(), so we should never hit this unless
@@ -466,10 +479,8 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
if (pages == NULL)
return ERR_PTR(-ENOMEM);
- gfpmask |= mapping_gfp_mask(mapping);
-
for (i = 0; i < npages; i++) {
- p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
+ p = shmem_read_mapping_page(mapping, i);
if (IS_ERR(p))
goto fail;
pages[i] = p;
@@ -479,7 +490,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
* __GFP_DMA32 to be set in mapping_gfp_mask(inode->i_mapping)
* so shmem can relocate pages during swapin if required.
*/
- BUG_ON((gfpmask & __GFP_DMA32) &&
+ BUG_ON((mapping_gfp_mask(mapping) & __GFP_DMA32) &&
(page_to_pfn(p) >= 0x00100000UL));
}
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 05c97c5350a1..e467e67af6e7 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -327,7 +327,7 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, size_t size,
/* Create a CMA GEM buffer. */
cma_obj = __drm_gem_cma_create(dev, size);
if (IS_ERR(cma_obj))
- return ERR_PTR(PTR_ERR(cma_obj));
+ return ERR_CAST(cma_obj);
cma_obj->paddr = sg_dma_address(sgt->sgl);
cma_obj->sgt = sgt;
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index 7e4bae760e27..c3b80fd65d62 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -125,7 +125,7 @@ int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
parent = &entry->head;
}
if (parent) {
- hlist_add_after_rcu(parent, &item->head);
+ hlist_add_behind_rcu(&item->head, parent);
} else {
hlist_add_head_rcu(&item->head, h_list);
}
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 86feedd5e6f6..ecaf0fa2eec8 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -132,7 +132,7 @@ int drm_bufs_info(struct seq_file *m, void *data)
i,
dma->bufs[i].buf_size,
dma->bufs[i].buf_count,
- atomic_read(&dma->bufs[i].freelist.count),
+ 0,
dma->bufs[i].seg_count,
seg_pages,
seg_pages * PAGE_SIZE / 1024);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 69c61f392e66..40be746b7e68 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -1,11 +1,3 @@
-/**
- * \file drm_ioctl.c
- * IOCTL processing for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
/*
* Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
*
@@ -13,6 +5,9 @@
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
+ * Author Rickard E. (Rik) Faith <faith@valinux.com>
+ * Author Gareth Hughes <gareth@valinux.com>
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@@ -35,6 +30,7 @@
#include <drm/drmP.h>
#include <drm/drm_core.h>
+#include "drm_legacy.h"
#include <linux/pci.h>
#include <linux/export.h>
@@ -42,6 +38,124 @@
#include <asm/mtrr.h>
#endif
+static int drm_version(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+#define DRM_IOCTL_DEF(ioctl, _func, _flags) \
+ [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+
+/** Ioctl table */
+static const struct drm_ioctl_desc drm_ioctls[] = {
+ DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma_ioctl, DRM_AUTH),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+#if __OS_HAS_AGP
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
+
+ DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+ DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+};
+
+#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
+
/**
* Get the bus id.
*
@@ -342,8 +456,6 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
file_priv->stereo_allowed = req->value;
break;
case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
- if (!drm_universal_planes)
- return -EINVAL;
if (req->value > 1)
return -EINVAL;
file_priv->universal_planes = req->value;
@@ -417,3 +529,243 @@ int drm_noop(struct drm_device *dev, void *data,
return 0;
}
EXPORT_SYMBOL(drm_noop);
+
+/**
+ * Copy and IOCTL return string to user space
+ */
+static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
+{
+ int len;
+
+ /* don't overflow userbuf */
+ len = strlen(value);
+ if (len > *buf_len)
+ len = *buf_len;
+
+ /* let userspace know exact length of driver value (which could be
+ * larger than the userspace-supplied buffer) */
+ *buf_len = strlen(value);
+
+ /* finally, try filling in the userbuf */
+ if (len && buf)
+ if (copy_to_user(buf, value, len))
+ return -EFAULT;
+ return 0;
+}
+
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
+static int drm_version(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_version *version = data;
+ int err;
+
+ version->version_major = dev->driver->major;
+ version->version_minor = dev->driver->minor;
+ version->version_patchlevel = dev->driver->patchlevel;
+ err = drm_copy_field(version->name, &version->name_len,
+ dev->driver->name);
+ if (!err)
+ err = drm_copy_field(version->date, &version->date_len,
+ dev->driver->date);
+ if (!err)
+ err = drm_copy_field(version->desc, &version->desc_len,
+ dev->driver->desc);
+
+ return err;
+}
+
+/**
+ * drm_ioctl_permit - Check ioctl permissions against caller
+ *
+ * @flags: ioctl permission flags.
+ * @file_priv: Pointer to struct drm_file identifying the caller.
+ *
+ * Checks whether the caller is allowed to run an ioctl with the
+ * indicated permissions. If so, returns zero. Otherwise returns an
+ * error code suitable for ioctl return.
+ */
+static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv)
+{
+ /* ROOT_ONLY is only for CAP_SYS_ADMIN */
+ if (unlikely((flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)))
+ return -EACCES;
+
+ /* AUTH is only for authenticated or render client */
+ if (unlikely((flags & DRM_AUTH) && !drm_is_render_client(file_priv) &&
+ !file_priv->authenticated))
+ return -EACCES;
+
+ /* MASTER is only for master or control clients */
+ if (unlikely((flags & DRM_MASTER) && !file_priv->is_master &&
+ !drm_is_control_client(file_priv)))
+ return -EACCES;
+
+ /* Control clients must be explicitly allowed */
+ if (unlikely(!(flags & DRM_CONTROL_ALLOW) &&
+ drm_is_control_client(file_priv)))
+ return -EACCES;
+
+ /* Render clients must be explicitly allowed */
+ if (unlikely(!(flags & DRM_RENDER_ALLOW) &&
+ drm_is_render_client(file_priv)))
+ return -EACCES;
+
+ return 0;
+}
+
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
+ */
+long drm_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct drm_device *dev;
+ const struct drm_ioctl_desc *ioctl = NULL;
+ drm_ioctl_t *func;
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ int retcode = -EINVAL;
+ char stack_kdata[128];
+ char *kdata = NULL;
+ unsigned int usize, asize;
+
+ dev = file_priv->minor->dev;
+
+ if (drm_device_is_unplugged(dev))
+ return -ENODEV;
+
+ if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+ ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+ goto err_i1;
+ if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+ (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+ u32 drv_size;
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ drv_size = _IOC_SIZE(ioctl->cmd_drv);
+ usize = asize = _IOC_SIZE(cmd);
+ if (drv_size > asize)
+ asize = drv_size;
+ cmd = ioctl->cmd_drv;
+ }
+ else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+ u32 drv_size;
+
+ ioctl = &drm_ioctls[nr];
+
+ drv_size = _IOC_SIZE(ioctl->cmd);
+ usize = asize = _IOC_SIZE(cmd);
+ if (drv_size > asize)
+ asize = drv_size;
+
+ cmd = ioctl->cmd;
+ } else
+ goto err_i1;
+
+ DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
+ task_pid_nr(current),
+ (long)old_encode_dev(file_priv->minor->kdev->devt),
+ file_priv->authenticated, ioctl->name);
+
+ /* Do not trust userspace, use our own definition */
+ func = ioctl->func;
+
+ if (unlikely(!func)) {
+ DRM_DEBUG("no function\n");
+ retcode = -EINVAL;
+ goto err_i1;
+ }
+
+ retcode = drm_ioctl_permit(ioctl->flags, file_priv);
+ if (unlikely(retcode))
+ goto err_i1;
+
+ if (cmd & (IOC_IN | IOC_OUT)) {
+ if (asize <= sizeof(stack_kdata)) {
+ kdata = stack_kdata;
+ } else {
+ kdata = kmalloc(asize, GFP_KERNEL);
+ if (!kdata) {
+ retcode = -ENOMEM;
+ goto err_i1;
+ }
+ }
+ if (asize > usize)
+ memset(kdata + usize, 0, asize - usize);
+ }
+
+ if (cmd & IOC_IN) {
+ if (copy_from_user(kdata, (void __user *)arg,
+ usize) != 0) {
+ retcode = -EFAULT;
+ goto err_i1;
+ }
+ } else if (cmd & IOC_OUT) {
+ memset(kdata, 0, usize);
+ }
+
+ if (ioctl->flags & DRM_UNLOCKED)
+ retcode = func(dev, kdata, file_priv);
+ else {
+ mutex_lock(&drm_global_mutex);
+ retcode = func(dev, kdata, file_priv);
+ mutex_unlock(&drm_global_mutex);
+ }
+
+ if (cmd & IOC_OUT) {
+ if (copy_to_user((void __user *)arg, kdata,
+ usize) != 0)
+ retcode = -EFAULT;
+ }
+
+ err_i1:
+ if (!ioctl)
+ DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
+ task_pid_nr(current),
+ (long)old_encode_dev(file_priv->minor->kdev->devt),
+ file_priv->authenticated, cmd, nr);
+
+ if (kdata != stack_kdata)
+ kfree(kdata);
+ if (retcode)
+ DRM_DEBUG("ret = %d\n", retcode);
+ return retcode;
+}
+EXPORT_SYMBOL(drm_ioctl);
+
+/**
+ * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ *
+ * @nr: Ioctl number.
+ * @flags: Where to return the ioctl permission flags
+ */
+bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
+{
+ if ((nr >= DRM_COMMAND_END && nr < DRM_CORE_IOCTL_COUNT) ||
+ (nr < DRM_COMMAND_BASE)) {
+ *flags = drm_ioctls[nr].flags;
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(drm_ioctl_flags);
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 0de123afdb34..08ba1209228e 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -542,8 +542,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
const struct drm_crtc *refcrtc,
const struct drm_display_mode *mode)
{
- ktime_t stime, etime, mono_time_offset;
struct timeval tv_etime;
+ ktime_t stime, etime;
int vbl_status;
int vpos, hpos, i;
int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
@@ -588,13 +588,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
&hpos, &stime, &etime);
- /*
- * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if
- * CLOCK_REALTIME is requested.
- */
- if (!drm_timestamp_monotonic)
- mono_time_offset = ktime_get_monotonic_offset();
-
/* Return as no-op if scanout query unsupported or failed. */
if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
@@ -633,7 +626,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
if (!drm_timestamp_monotonic)
- etime = ktime_sub(etime, mono_time_offset);
+ etime = ktime_mono_to_real(etime);
/* save this only for debugging purposes */
tv_etime = ktime_to_timeval(etime);
@@ -664,10 +657,7 @@ static struct timeval get_drm_timestamp(void)
{
ktime_t now;
- now = ktime_get();
- if (!drm_timestamp_monotonic)
- now = ktime_sub(now, ktime_get_monotonic_offset());
-
+ now = drm_timestamp_monotonic ? ktime_get() : ktime_get_real();
return ktime_to_timeval(now);
}
diff --git a/drivers/gpu/drm/drm_legacy.h b/drivers/gpu/drm/drm_legacy.h
new file mode 100644
index 000000000000..d34f20a79b7c
--- /dev/null
+++ b/drivers/gpu/drm/drm_legacy.h
@@ -0,0 +1,51 @@
+#ifndef __DRM_LEGACY_H__
+#define __DRM_LEGACY_H__
+
+/*
+ * Copyright (c) 2014 David Herrmann <dh.herrmann@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+struct drm_device;
+struct drm_file;
+
+/*
+ * Generic DRM Contexts
+ */
+
+#define DRM_KERNEL_CONTEXT 0
+#define DRM_RESERVED_CONTEXTS 1
+
+int drm_legacy_ctxbitmap_init(struct drm_device *dev);
+void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev);
+void drm_legacy_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file);
+
+int drm_legacy_resctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_addctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_getctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_switchctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_newctx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_rmctx(struct drm_device *d, void *v, struct drm_file *f);
+
+int drm_legacy_setsareactx(struct drm_device *d, void *v, struct drm_file *f);
+int drm_legacy_getsareactx(struct drm_device *d, void *v, struct drm_file *f);
+
+#endif /* __DRM_LEGACY_H__ */
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index f6452682141b..e26b59e385ff 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -35,6 +35,7 @@
#include <linux/export.h>
#include <drm/drmP.h>
+#include "drm_legacy.h"
static int drm_notifier(void *priv);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index e633df2f68d8..6aa6a9e95570 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -201,16 +201,15 @@ EXPORT_SYMBOL(mipi_dsi_detach);
/**
* mipi_dsi_dcs_write - send DCS write command
* @dsi: DSI device
- * @channel: virtual channel
* @data: pointer to the command followed by parameters
* @len: length of @data
*/
-int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel,
- const void *data, size_t len)
+ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
+ size_t len)
{
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
struct mipi_dsi_msg msg = {
- .channel = channel,
+ .channel = dsi->channel,
.tx_buf = data,
.tx_len = len
};
@@ -239,19 +238,18 @@ EXPORT_SYMBOL(mipi_dsi_dcs_write);
/**
* mipi_dsi_dcs_read - send DCS read request command
* @dsi: DSI device
- * @channel: virtual channel
* @cmd: DCS read command
* @data: pointer to read buffer
* @len: length of @data
*
* Function returns number of read bytes or error code.
*/
-ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel,
- u8 cmd, void *data, size_t len)
+ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
+ size_t len)
{
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
struct mipi_dsi_msg msg = {
- .channel = channel,
+ .channel = dsi->channel,
.type = MIPI_DSI_DCS_READ,
.tx_buf = &cmd,
.tx_len = 1,
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
new file mode 100644
index 000000000000..16150a00c237
--- /dev/null
+++ b/drivers/gpu/drm/drm_of.c
@@ -0,0 +1,67 @@
+#include <linux/export.h>
+#include <linux/list.h>
+#include <linux/of_graph.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_of.h>
+
+/**
+ * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
+ * @dev: DRM device
+ * @port: port OF node
+ *
+ * Given a port OF node, return the possible mask of the corresponding
+ * CRTC within a device's list of CRTCs. Returns zero if not found.
+ */
+static uint32_t drm_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port)
+{
+ unsigned int index = 0;
+ struct drm_crtc *tmp;
+
+ list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+ if (tmp->port == port)
+ return 1 << index;
+
+ index++;
+ }
+
+ return 0;
+}
+
+/**
+ * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
+ * @dev: DRM device
+ * @port: encoder port to scan for endpoints
+ *
+ * Scan all endpoints attached to a port, locate their attached CRTCs,
+ * and generate the DRM mask of CRTCs which may be attached to this
+ * encoder.
+ *
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ */
+uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
+ struct device_node *port)
+{
+ struct device_node *remote_port, *ep = NULL;
+ uint32_t possible_crtcs = 0;
+
+ do {
+ ep = of_graph_get_next_endpoint(port, ep);
+ if (!ep)
+ break;
+
+ remote_port = of_graph_get_remote_port(ep);
+ if (!remote_port) {
+ of_node_put(ep);
+ return 0;
+ }
+
+ possible_crtcs |= drm_crtc_port_mask(dev, remote_port);
+
+ of_node_put(remote_port);
+ } while (1);
+
+ return possible_crtcs;
+}
+EXPORT_SYMBOL(drm_of_find_possible_crtcs);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 6d133149cc74..827ec1a3040b 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -335,9 +335,10 @@ struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
}
/* possible_crtc's will be filled in later by crtc_init */
- ret = drm_plane_init(dev, primary, 0, &drm_primary_helper_funcs,
- formats, num_formats,
- DRM_PLANE_TYPE_PRIMARY);
+ ret = drm_universal_plane_init(dev, primary, 0,
+ &drm_primary_helper_funcs,
+ formats, num_formats,
+ DRM_PLANE_TYPE_PRIMARY);
if (ret) {
kfree(primary);
primary = NULL;
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 304ca8cacbc4..99d578bad17e 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -336,7 +336,13 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *obj, int flags)
{
- return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags);
+ struct reservation_object *robj = NULL;
+
+ if (dev->driver->gem_prime_res_obj)
+ robj = dev->driver->gem_prime_res_obj(obj);
+
+ return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size,
+ flags, robj);
}
EXPORT_SYMBOL(drm_gem_prime_export);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index d22676b89cbb..db7d250f7ac7 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -130,7 +130,14 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
count = drm_load_edid_firmware(connector);
if (count == 0)
#endif
- count = (*connector_funcs->get_modes)(connector);
+ {
+ if (connector->override_edid) {
+ struct edid *edid = (struct edid *) connector->edid_blob_ptr->data;
+
+ count = drm_add_edid_modes(connector, edid);
+ } else
+ count = (*connector_funcs->get_modes)(connector);
+ }
if (count == 0 && connector->status == connector_status_connected)
count = drm_add_modes_noedid(connector, 1024, 768);
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 7047ca025787..631f5afd451c 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -293,3 +293,143 @@ void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point)
DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
}
EXPORT_SYMBOL(drm_rect_debug_print);
+
+/**
+ * drm_rect_rotate - Rotate the rectangle
+ * @r: rectangle to be rotated
+ * @width: Width of the coordinate space
+ * @height: Height of the coordinate space
+ * @rotation: Transformation to be applied
+ *
+ * Apply @rotation to the coordinates of rectangle @r.
+ *
+ * @width and @height combined with @rotation define
+ * the location of the new origin.
+ *
+ * @width correcsponds to the horizontal and @height
+ * to the vertical axis of the untransformed coordinate
+ * space.
+ */
+void drm_rect_rotate(struct drm_rect *r,
+ int width, int height,
+ unsigned int rotation)
+{
+ struct drm_rect tmp;
+
+ if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) {
+ tmp = *r;
+
+ if (rotation & BIT(DRM_REFLECT_X)) {
+ r->x1 = width - tmp.x2;
+ r->x2 = width - tmp.x1;
+ }
+
+ if (rotation & BIT(DRM_REFLECT_Y)) {
+ r->y1 = height - tmp.y2;
+ r->y2 = height - tmp.y1;
+ }
+ }
+
+ switch (rotation & 0xf) {
+ case BIT(DRM_ROTATE_0):
+ break;
+ case BIT(DRM_ROTATE_90):
+ tmp = *r;
+ r->x1 = tmp.y1;
+ r->x2 = tmp.y2;
+ r->y1 = width - tmp.x2;
+ r->y2 = width - tmp.x1;
+ break;
+ case BIT(DRM_ROTATE_180):
+ tmp = *r;
+ r->x1 = width - tmp.x2;
+ r->x2 = width - tmp.x1;
+ r->y1 = height - tmp.y2;
+ r->y2 = height - tmp.y1;
+ break;
+ case BIT(DRM_ROTATE_270):
+ tmp = *r;
+ r->x1 = height - tmp.y2;
+ r->x2 = height - tmp.y1;
+ r->y1 = tmp.x1;
+ r->y2 = tmp.x2;
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(drm_rect_rotate);
+
+/**
+ * drm_rect_rotate_inv - Inverse rotate the rectangle
+ * @r: rectangle to be rotated
+ * @width: Width of the coordinate space
+ * @height: Height of the coordinate space
+ * @rotation: Transformation whose inverse is to be applied
+ *
+ * Apply the inverse of @rotation to the coordinates
+ * of rectangle @r.
+ *
+ * @width and @height combined with @rotation define
+ * the location of the new origin.
+ *
+ * @width correcsponds to the horizontal and @height
+ * to the vertical axis of the original untransformed
+ * coordinate space, so that you never have to flip
+ * them when doing a rotatation and its inverse.
+ * That is, if you do:
+ *
+ * drm_rotate(&r, width, height, rotation);
+ * drm_rotate_inv(&r, width, height, rotation);
+ *
+ * you will always get back the original rectangle.
+ */
+void drm_rect_rotate_inv(struct drm_rect *r,
+ int width, int height,
+ unsigned int rotation)
+{
+ struct drm_rect tmp;
+
+ switch (rotation & 0xf) {
+ case BIT(DRM_ROTATE_0):
+ break;
+ case BIT(DRM_ROTATE_90):
+ tmp = *r;
+ r->x1 = width - tmp.y2;
+ r->x2 = width - tmp.y1;
+ r->y1 = tmp.x1;
+ r->y2 = tmp.x2;
+ break;
+ case BIT(DRM_ROTATE_180):
+ tmp = *r;
+ r->x1 = width - tmp.x2;
+ r->x2 = width - tmp.x1;
+ r->y1 = height - tmp.y2;
+ r->y2 = height - tmp.y1;
+ break;
+ case BIT(DRM_ROTATE_270):
+ tmp = *r;
+ r->x1 = tmp.y1;
+ r->x2 = tmp.y2;
+ r->y1 = height - tmp.x2;
+ r->y2 = height - tmp.x1;
+ break;
+ default:
+ break;
+ }
+
+ if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) {
+ tmp = *r;
+
+ if (rotation & BIT(DRM_REFLECT_X)) {
+ r->x1 = width - tmp.x2;
+ r->x2 = width - tmp.x1;
+ }
+
+ if (rotation & BIT(DRM_REFLECT_Y)) {
+ r->y1 = height - tmp.y2;
+ r->y2 = height - tmp.y1;
+ }
+ }
+}
+EXPORT_SYMBOL(drm_rect_rotate_inv);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
deleted file mode 100644
index 14d16464000a..000000000000
--- a/drivers/gpu/drm/drm_stub.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
- * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
- *
- * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Author Rickard E. (Rik) Faith <faith@valinux.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mount.h>
-#include <linux/slab.h>
-#include <drm/drmP.h>
-#include <drm/drm_core.h>
-
-unsigned int drm_debug = 0; /* 1 to enable debug output */
-EXPORT_SYMBOL(drm_debug);
-
-unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */
-EXPORT_SYMBOL(drm_rnodes);
-
-/* 1 to allow user space to request universal planes (experimental) */
-unsigned int drm_universal_planes = 0;
-EXPORT_SYMBOL(drm_universal_planes);
-
-unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
-EXPORT_SYMBOL(drm_vblank_offdelay);
-
-unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
-EXPORT_SYMBOL(drm_timestamp_precision);
-
-/*
- * Default to use monotonic timestamps for wait-for-vblank and page-flip
- * complete events.
- */
-unsigned int drm_timestamp_monotonic = 1;
-
-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
-MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output");
-MODULE_PARM_DESC(rnodes, "Enable experimental render nodes API");
-MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
-MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
-MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
-
-module_param_named(debug, drm_debug, int, 0600);
-module_param_named(rnodes, drm_rnodes, int, 0600);
-module_param_named(universal_planes, drm_universal_planes, int, 0600);
-module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
-module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
-module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
-
-static DEFINE_SPINLOCK(drm_minor_lock);
-struct idr drm_minors_idr;
-
-struct class *drm_class;
-struct dentry *drm_debugfs_root;
-
-int drm_err(const char *func, const char *format, ...)
-{
- struct va_format vaf;
- va_list args;
- int r;
-
- va_start(args, format);
-
- vaf.fmt = format;
- vaf.va = &args;
-
- r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
-
- va_end(args);
-
- return r;
-}
-EXPORT_SYMBOL(drm_err);
-
-void drm_ut_debug_printk(const char *function_name, const char *format, ...)
-{
- struct va_format vaf;
- va_list args;
-
- va_start(args, format);
- vaf.fmt = format;
- vaf.va = &args;
-
- printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
-
- va_end(args);
-}
-EXPORT_SYMBOL(drm_ut_debug_printk);
-
-struct drm_master *drm_master_create(struct drm_minor *minor)
-{
- struct drm_master *master;
-
- master = kzalloc(sizeof(*master), GFP_KERNEL);
- if (!master)
- return NULL;
-
- kref_init(&master->refcount);
- spin_lock_init(&master->lock.spinlock);
- init_waitqueue_head(&master->lock.lock_queue);
- if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
- kfree(master);
- return NULL;
- }
- INIT_LIST_HEAD(&master->magicfree);
- master->minor = minor;
-
- return master;
-}
-
-struct drm_master *drm_master_get(struct drm_master *master)
-{
- kref_get(&master->refcount);
- return master;
-}
-EXPORT_SYMBOL(drm_master_get);
-
-static void drm_master_destroy(struct kref *kref)
-{
- struct drm_master *master = container_of(kref, struct drm_master, refcount);
- struct drm_magic_entry *pt, *next;
- struct drm_device *dev = master->minor->dev;
- struct drm_map_list *r_list, *list_temp;
-
- mutex_lock(&dev->struct_mutex);
- if (dev->driver->master_destroy)
- dev->driver->master_destroy(dev, master);
-
- list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
- if (r_list->master == master) {
- drm_rmmap_locked(dev, r_list->map);
- r_list = NULL;
- }
- }
-
- if (master->unique) {
- kfree(master->unique);
- master->unique = NULL;
- master->unique_len = 0;
- }
-
- list_for_each_entry_safe(pt, next, &master->magicfree, head) {
- list_del(&pt->head);
- drm_ht_remove_item(&master->magiclist, &pt->hash_item);
- kfree(pt);
- }
-
- drm_ht_remove(&master->magiclist);
-
- mutex_unlock(&dev->struct_mutex);
- kfree(master);
-}
-
-void drm_master_put(struct drm_master **master)
-{
- kref_put(&(*master)->refcount, drm_master_destroy);
- *master = NULL;
-}
-EXPORT_SYMBOL(drm_master_put);
-
-int drm_setmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- int ret = 0;
-
- mutex_lock(&dev->master_mutex);
- if (file_priv->is_master)
- goto out_unlock;
-
- if (file_priv->minor->master) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- if (!file_priv->master) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- file_priv->minor->master = drm_master_get(file_priv->master);
- file_priv->is_master = 1;
- if (dev->driver->master_set) {
- ret = dev->driver->master_set(dev, file_priv, false);
- if (unlikely(ret != 0)) {
- file_priv->is_master = 0;
- drm_master_put(&file_priv->minor->master);
- }
- }
-
-out_unlock:
- mutex_unlock(&dev->master_mutex);
- return ret;
-}
-
-int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- int ret = -EINVAL;
-
- mutex_lock(&dev->master_mutex);
- if (!file_priv->is_master)
- goto out_unlock;
-
- if (!file_priv->minor->master)
- goto out_unlock;
-
- ret = 0;
- if (dev->driver->master_drop)
- dev->driver->master_drop(dev, file_priv, false);
- drm_master_put(&file_priv->minor->master);
- file_priv->is_master = 0;
-
-out_unlock:
- mutex_unlock(&dev->master_mutex);
- return ret;
-}
-
-/*
- * DRM Minors
- * A DRM device can provide several char-dev interfaces on the DRM-Major. Each
- * of them is represented by a drm_minor object. Depending on the capabilities
- * of the device-driver, different interfaces are registered.
- *
- * Minors can be accessed via dev->$minor_name. This pointer is either
- * NULL or a valid drm_minor pointer and stays valid as long as the device is
- * valid. This means, DRM minors have the same life-time as the underlying
- * device. However, this doesn't mean that the minor is active. Minors are
- * registered and unregistered dynamically according to device-state.
- */
-
-static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
- unsigned int type)
-{
- switch (type) {
- case DRM_MINOR_LEGACY:
- return &dev->primary;
- case DRM_MINOR_RENDER:
- return &dev->render;
- case DRM_MINOR_CONTROL:
- return &dev->control;
- default:
- return NULL;
- }
-}
-
-static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
-{
- struct drm_minor *minor;
-
- minor = kzalloc(sizeof(*minor), GFP_KERNEL);
- if (!minor)
- return -ENOMEM;
-
- minor->type = type;
- minor->dev = dev;
-
- *drm_minor_get_slot(dev, type) = minor;
- return 0;
-}
-
-static void drm_minor_free(struct drm_device *dev, unsigned int type)
-{
- struct drm_minor **slot;
-
- slot = drm_minor_get_slot(dev, type);
- if (*slot) {
- drm_mode_group_destroy(&(*slot)->mode_group);
- kfree(*slot);
- *slot = NULL;
- }
-}
-
-static int drm_minor_register(struct drm_device *dev, unsigned int type)
-{
- struct drm_minor *new_minor;
- unsigned long flags;
- int ret;
- int minor_id;
-
- DRM_DEBUG("\n");
-
- new_minor = *drm_minor_get_slot(dev, type);
- if (!new_minor)
- return 0;
-
- idr_preload(GFP_KERNEL);
- spin_lock_irqsave(&drm_minor_lock, flags);
- minor_id = idr_alloc(&drm_minors_idr,
- NULL,
- 64 * type,
- 64 * (type + 1),
- GFP_NOWAIT);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
- idr_preload_end();
-
- if (minor_id < 0)
- return minor_id;
-
- new_minor->index = minor_id;
-
- ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
- if (ret) {
- DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
- goto err_id;
- }
-
- ret = drm_sysfs_device_add(new_minor);
- if (ret) {
- DRM_ERROR("DRM: Error sysfs_device_add.\n");
- goto err_debugfs;
- }
-
- /* replace NULL with @minor so lookups will succeed from now on */
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_replace(&drm_minors_idr, new_minor, new_minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
-
- DRM_DEBUG("new minor assigned %d\n", minor_id);
- return 0;
-
-err_debugfs:
- drm_debugfs_cleanup(new_minor);
-err_id:
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_remove(&drm_minors_idr, minor_id);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
- new_minor->index = 0;
- return ret;
-}
-
-static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
-{
- struct drm_minor *minor;
- unsigned long flags;
-
- minor = *drm_minor_get_slot(dev, type);
- if (!minor || !minor->kdev)
- return;
-
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_remove(&drm_minors_idr, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
- minor->index = 0;
-
- drm_debugfs_cleanup(minor);
- drm_sysfs_device_remove(minor);
-}
-
-/**
- * drm_minor_acquire - Acquire a DRM minor
- * @minor_id: Minor ID of the DRM-minor
- *
- * Looks up the given minor-ID and returns the respective DRM-minor object. The
- * refence-count of the underlying device is increased so you must release this
- * object with drm_minor_release().
- *
- * As long as you hold this minor, it is guaranteed that the object and the
- * minor->dev pointer will stay valid! However, the device may get unplugged and
- * unregistered while you hold the minor.
- *
- * Returns:
- * Pointer to minor-object with increased device-refcount, or PTR_ERR on
- * failure.
- */
-struct drm_minor *drm_minor_acquire(unsigned int minor_id)
-{
- struct drm_minor *minor;
- unsigned long flags;
-
- spin_lock_irqsave(&drm_minor_lock, flags);
- minor = idr_find(&drm_minors_idr, minor_id);
- if (minor)
- drm_dev_ref(minor->dev);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
-
- if (!minor) {
- return ERR_PTR(-ENODEV);
- } else if (drm_device_is_unplugged(minor->dev)) {
- drm_dev_unref(minor->dev);
- return ERR_PTR(-ENODEV);
- }
-
- return minor;
-}
-
-/**
- * drm_minor_release - Release DRM minor
- * @minor: Pointer to DRM minor object
- *
- * Release a minor that was previously acquired via drm_minor_acquire().
- */
-void drm_minor_release(struct drm_minor *minor)
-{
- drm_dev_unref(minor->dev);
-}
-
-/**
- * drm_put_dev - Unregister and release a DRM device
- * @dev: DRM device
- *
- * Called at module unload time or when a PCI device is unplugged.
- *
- * Use of this function is discouraged. It will eventually go away completely.
- * Please use drm_dev_unregister() and drm_dev_unref() explicitly instead.
- *
- * Cleans up all DRM device, calling drm_lastclose().
- */
-void drm_put_dev(struct drm_device *dev)
-{
- DRM_DEBUG("\n");
-
- if (!dev) {
- DRM_ERROR("cleanup called no dev\n");
- return;
- }
-
- drm_dev_unregister(dev);
- drm_dev_unref(dev);
-}
-EXPORT_SYMBOL(drm_put_dev);
-
-void drm_unplug_dev(struct drm_device *dev)
-{
- /* for a USB device */
- drm_minor_unregister(dev, DRM_MINOR_LEGACY);
- drm_minor_unregister(dev, DRM_MINOR_RENDER);
- drm_minor_unregister(dev, DRM_MINOR_CONTROL);
-
- mutex_lock(&drm_global_mutex);
-
- drm_device_set_unplugged(dev);
-
- if (dev->open_count == 0) {
- drm_put_dev(dev);
- }
- mutex_unlock(&drm_global_mutex);
-}
-EXPORT_SYMBOL(drm_unplug_dev);
-
-/*
- * DRM internal mount
- * We want to be able to allocate our own "struct address_space" to control
- * memory-mappings in VRAM (or stolen RAM, ...). However, core MM does not allow
- * stand-alone address_space objects, so we need an underlying inode. As there
- * is no way to allocate an independent inode easily, we need a fake internal
- * VFS mount-point.
- *
- * The drm_fs_inode_new() function allocates a new inode, drm_fs_inode_free()
- * frees it again. You are allowed to use iget() and iput() to get references to
- * the inode. But each drm_fs_inode_new() call must be paired with exactly one
- * drm_fs_inode_free() call (which does not have to be the last iput()).
- * We use drm_fs_inode_*() to manage our internal VFS mount-point and share it
- * between multiple inode-users. You could, technically, call
- * iget() + drm_fs_inode_free() directly after alloc and sometime later do an
- * iput(), but this way you'd end up with a new vfsmount for each inode.
- */
-
-static int drm_fs_cnt;
-static struct vfsmount *drm_fs_mnt;
-
-static const struct dentry_operations drm_fs_dops = {
- .d_dname = simple_dname,
-};
-
-static const struct super_operations drm_fs_sops = {
- .statfs = simple_statfs,
-};
-
-static struct dentry *drm_fs_mount(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data)
-{
- return mount_pseudo(fs_type,
- "drm:",
- &drm_fs_sops,
- &drm_fs_dops,
- 0x010203ff);
-}
-
-static struct file_system_type drm_fs_type = {
- .name = "drm",
- .owner = THIS_MODULE,
- .mount = drm_fs_mount,
- .kill_sb = kill_anon_super,
-};
-
-static struct inode *drm_fs_inode_new(void)
-{
- struct inode *inode;
- int r;
-
- r = simple_pin_fs(&drm_fs_type, &drm_fs_mnt, &drm_fs_cnt);
- if (r < 0) {
- DRM_ERROR("Cannot mount pseudo fs: %d\n", r);
- return ERR_PTR(r);
- }
-
- inode = alloc_anon_inode(drm_fs_mnt->mnt_sb);
- if (IS_ERR(inode))
- simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
-
- return inode;
-}
-
-static void drm_fs_inode_free(struct inode *inode)
-{
- if (inode) {
- iput(inode);
- simple_release_fs(&drm_fs_mnt, &drm_fs_cnt);
- }
-}
-
-/**
- * drm_dev_alloc - Allocate new DRM device
- * @driver: DRM driver to allocate device for
- * @parent: Parent device object
- *
- * Allocate and initialize a new DRM device. No device registration is done.
- * Call drm_dev_register() to advertice the device to user space and register it
- * with other core subsystems.
- *
- * The initial ref-count of the object is 1. Use drm_dev_ref() and
- * drm_dev_unref() to take and drop further ref-counts.
- *
- * RETURNS:
- * Pointer to new DRM device, or NULL if out of memory.
- */
-struct drm_device *drm_dev_alloc(struct drm_driver *driver,
- struct device *parent)
-{
- struct drm_device *dev;
- int ret;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return NULL;
-
- kref_init(&dev->ref);
- dev->dev = parent;
- dev->driver = driver;
-
- INIT_LIST_HEAD(&dev->filelist);
- INIT_LIST_HEAD(&dev->ctxlist);
- INIT_LIST_HEAD(&dev->vmalist);
- INIT_LIST_HEAD(&dev->maplist);
- INIT_LIST_HEAD(&dev->vblank_event_list);
-
- spin_lock_init(&dev->buf_lock);
- spin_lock_init(&dev->event_lock);
- mutex_init(&dev->struct_mutex);
- mutex_init(&dev->ctxlist_mutex);
- mutex_init(&dev->master_mutex);
-
- dev->anon_inode = drm_fs_inode_new();
- if (IS_ERR(dev->anon_inode)) {
- ret = PTR_ERR(dev->anon_inode);
- DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
- goto err_free;
- }
-
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
- if (ret)
- goto err_minors;
- }
-
- if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
- ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
- if (ret)
- goto err_minors;
- }
-
- ret = drm_minor_alloc(dev, DRM_MINOR_LEGACY);
- if (ret)
- goto err_minors;
-
- if (drm_ht_create(&dev->map_hash, 12))
- goto err_minors;
-
- ret = drm_ctxbitmap_init(dev);
- if (ret) {
- DRM_ERROR("Cannot allocate memory for context bitmap.\n");
- goto err_ht;
- }
-
- if (driver->driver_features & DRIVER_GEM) {
- ret = drm_gem_init(dev);
- if (ret) {
- DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
- goto err_ctxbitmap;
- }
- }
-
- return dev;
-
-err_ctxbitmap:
- drm_ctxbitmap_cleanup(dev);
-err_ht:
- drm_ht_remove(&dev->map_hash);
-err_minors:
- drm_minor_free(dev, DRM_MINOR_LEGACY);
- drm_minor_free(dev, DRM_MINOR_RENDER);
- drm_minor_free(dev, DRM_MINOR_CONTROL);
- drm_fs_inode_free(dev->anon_inode);
-err_free:
- mutex_destroy(&dev->master_mutex);
- kfree(dev);
- return NULL;
-}
-EXPORT_SYMBOL(drm_dev_alloc);
-
-static void drm_dev_release(struct kref *ref)
-{
- struct drm_device *dev = container_of(ref, struct drm_device, ref);
-
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_destroy(dev);
-
- drm_ctxbitmap_cleanup(dev);
- drm_ht_remove(&dev->map_hash);
- drm_fs_inode_free(dev->anon_inode);
-
- drm_minor_free(dev, DRM_MINOR_LEGACY);
- drm_minor_free(dev, DRM_MINOR_RENDER);
- drm_minor_free(dev, DRM_MINOR_CONTROL);
-
- mutex_destroy(&dev->master_mutex);
- kfree(dev->unique);
- kfree(dev);
-}
-
-/**
- * drm_dev_ref - Take reference of a DRM device
- * @dev: device to take reference of or NULL
- *
- * This increases the ref-count of @dev by one. You *must* already own a
- * reference when calling this. Use drm_dev_unref() to drop this reference
- * again.
- *
- * This function never fails. However, this function does not provide *any*
- * guarantee whether the device is alive or running. It only provides a
- * reference to the object and the memory associated with it.
- */
-void drm_dev_ref(struct drm_device *dev)
-{
- if (dev)
- kref_get(&dev->ref);
-}
-EXPORT_SYMBOL(drm_dev_ref);
-
-/**
- * drm_dev_unref - Drop reference of a DRM device
- * @dev: device to drop reference of or NULL
- *
- * This decreases the ref-count of @dev by one. The device is destroyed if the
- * ref-count drops to zero.
- */
-void drm_dev_unref(struct drm_device *dev)
-{
- if (dev)
- kref_put(&dev->ref, drm_dev_release);
-}
-EXPORT_SYMBOL(drm_dev_unref);
-
-/**
- * drm_dev_register - Register DRM device
- * @dev: Device to register
- * @flags: Flags passed to the driver's .load() function
- *
- * Register the DRM device @dev with the system, advertise device to user-space
- * and start normal device operation. @dev must be allocated via drm_dev_alloc()
- * previously.
- *
- * Never call this twice on any device!
- *
- * RETURNS:
- * 0 on success, negative error code on failure.
- */
-int drm_dev_register(struct drm_device *dev, unsigned long flags)
-{
- int ret;
-
- mutex_lock(&drm_global_mutex);
-
- ret = drm_minor_register(dev, DRM_MINOR_CONTROL);
- if (ret)
- goto err_minors;
-
- ret = drm_minor_register(dev, DRM_MINOR_RENDER);
- if (ret)
- goto err_minors;
-
- ret = drm_minor_register(dev, DRM_MINOR_LEGACY);
- if (ret)
- goto err_minors;
-
- if (dev->driver->load) {
- ret = dev->driver->load(dev, flags);
- if (ret)
- goto err_minors;
- }
-
- /* setup grouping for legacy outputs */
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = drm_mode_group_init_legacy_group(dev,
- &dev->primary->mode_group);
- if (ret)
- goto err_unload;
- }
-
- ret = 0;
- goto out_unlock;
-
-err_unload:
- if (dev->driver->unload)
- dev->driver->unload(dev);
-err_minors:
- drm_minor_unregister(dev, DRM_MINOR_LEGACY);
- drm_minor_unregister(dev, DRM_MINOR_RENDER);
- drm_minor_unregister(dev, DRM_MINOR_CONTROL);
-out_unlock:
- mutex_unlock(&drm_global_mutex);
- return ret;
-}
-EXPORT_SYMBOL(drm_dev_register);
-
-/**
- * drm_dev_unregister - Unregister DRM device
- * @dev: Device to unregister
- *
- * Unregister the DRM device from the system. This does the reverse of
- * drm_dev_register() but does not deallocate the device. The caller must call
- * drm_dev_unref() to drop their final reference.
- */
-void drm_dev_unregister(struct drm_device *dev)
-{
- struct drm_map_list *r_list, *list_temp;
-
- drm_lastclose(dev);
-
- if (dev->driver->unload)
- dev->driver->unload(dev);
-
- if (dev->agp)
- drm_pci_agp_destroy(dev);
-
- drm_vblank_cleanup(dev);
-
- list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
- drm_rmmap(dev, r_list->map);
-
- drm_minor_unregister(dev, DRM_MINOR_LEGACY);
- drm_minor_unregister(dev, DRM_MINOR_RENDER);
- drm_minor_unregister(dev, DRM_MINOR_CONTROL);
-}
-EXPORT_SYMBOL(drm_dev_unregister);
-
-/**
- * drm_dev_set_unique - Set the unique name of a DRM device
- * @dev: device of which to set the unique name
- * @fmt: format string for unique name
- *
- * Sets the unique name of a DRM device using the specified format string and
- * a variable list of arguments. Drivers can use this at driver probe time if
- * the unique name of the devices they drive is static.
- *
- * Return: 0 on success or a negative error code on failure.
- */
-int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...)
-{
- va_list ap;
-
- kfree(dev->unique);
-
- va_start(ap, fmt);
- dev->unique = kvasprintf(GFP_KERNEL, fmt, ap);
- va_end(ap);
-
- return dev->unique ? 0 : -ENOMEM;
-}
-EXPORT_SYMBOL(drm_dev_set_unique);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 369b26278e76..ab1a5f6dde8a 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -438,7 +438,6 @@ err_out_files:
out:
return ret;
}
-EXPORT_SYMBOL(drm_sysfs_connector_add);
/**
* drm_sysfs_connector_remove - remove an connector device from sysfs
@@ -468,7 +467,6 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
device_unregister(connector->kdev);
connector->kdev = NULL;
}
-EXPORT_SYMBOL(drm_sysfs_connector_remove);
/**
* drm_sysfs_hotplug_event - generate a DRM uevent
@@ -495,71 +493,55 @@ static void drm_sysfs_release(struct device *dev)
}
/**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
+ * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor
+ * @minor: minor to allocate sysfs device for
*
- * Add a DRM device to the DRM's device model class. We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
+ * This allocates a new sysfs device for @minor and returns it. The device is
+ * not registered nor linked. The caller has to use device_add() and
+ * device_del() to register and unregister it.
+ *
+ * Note that dev_get_drvdata() on the new device will return the minor.
+ * However, the device does not hold a ref-count to the minor nor to the
+ * underlying drm_device. This is unproblematic as long as you access the
+ * private data only in sysfs callbacks. device_del() disables those
+ * synchronously, so they cannot be called after you cleanup a minor.
*/
-int drm_sysfs_device_add(struct drm_minor *minor)
+struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
{
- char *minor_str;
+ const char *minor_str;
+ struct device *kdev;
int r;
if (minor->type == DRM_MINOR_CONTROL)
minor_str = "controlD%d";
- else if (minor->type == DRM_MINOR_RENDER)
- minor_str = "renderD%d";
- else
- minor_str = "card%d";
-
- minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
- if (!minor->kdev) {
- r = -ENOMEM;
- goto error;
- }
-
- device_initialize(minor->kdev);
- minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
- minor->kdev->class = drm_class;
- minor->kdev->type = &drm_sysfs_device_minor;
- minor->kdev->parent = minor->dev->dev;
- minor->kdev->release = drm_sysfs_release;
- dev_set_drvdata(minor->kdev, minor);
-
- r = dev_set_name(minor->kdev, minor_str, minor->index);
+ else if (minor->type == DRM_MINOR_RENDER)
+ minor_str = "renderD%d";
+ else
+ minor_str = "card%d";
+
+ kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+ if (!kdev)
+ return ERR_PTR(-ENOMEM);
+
+ device_initialize(kdev);
+ kdev->devt = MKDEV(DRM_MAJOR, minor->index);
+ kdev->class = drm_class;
+ kdev->type = &drm_sysfs_device_minor;
+ kdev->parent = minor->dev->dev;
+ kdev->release = drm_sysfs_release;
+ dev_set_drvdata(kdev, minor);
+
+ r = dev_set_name(kdev, minor_str, minor->index);
if (r < 0)
- goto error;
-
- r = device_add(minor->kdev);
- if (r < 0)
- goto error;
-
- return 0;
+ goto err_free;
-error:
- DRM_ERROR("device create failed %d\n", r);
- put_device(minor->kdev);
- return r;
-}
+ return kdev;
-/**
- * drm_sysfs_device_remove - remove DRM device
- * @dev: DRM device to remove
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to drm_sysfs_device_add()
- */
-void drm_sysfs_device_remove(struct drm_minor *minor)
-{
- if (minor->kdev)
- device_unregister(minor->kdev);
- minor->kdev = NULL;
+err_free:
+ put_device(kdev);
+ return ERR_PTR(r);
}
-
/**
* drm_class_device_register - Register a struct device in the drm class.
*
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 178d2a9672a8..7f9f6f9e9b7e 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD
bool "Exynos DRM FIMD"
depends on DRM_EXYNOS && !FB_S3C
select FB_MODE_HELPERS
+ select MFD_SYSCON
help
Choose this option if you want to use Exynos FIMD for DRM.
@@ -52,6 +53,7 @@ config DRM_EXYNOS_DP
bool "EXYNOS DRM DP driver support"
depends on DRM_EXYNOS_FIMD && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
default DRM_EXYNOS
+ select DRM_PANEL
help
This enables support for DP device.
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index a8ffc8c1477b..4f3c7eb2d37d 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -16,7 +16,6 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
@@ -28,6 +27,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
#include <drm/bridge/ptn3460.h>
#include "exynos_drm_drv.h"
@@ -41,7 +41,7 @@ struct bridge_init {
struct device_node *node;
};
-static int exynos_dp_init_dp(struct exynos_dp_device *dp)
+static void exynos_dp_init_dp(struct exynos_dp_device *dp)
{
exynos_dp_reset(dp);
@@ -58,8 +58,6 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)
exynos_dp_init_hpd(dp);
exynos_dp_init_aux(dp);
-
- return 0;
}
static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
@@ -875,10 +873,24 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
static void exynos_dp_hotplug(struct work_struct *work)
{
struct exynos_dp_device *dp;
- int ret;
dp = container_of(work, struct exynos_dp_device, hotplug_work);
+ if (dp->drm_dev)
+ drm_helper_hpd_irq_event(dp->drm_dev);
+}
+
+static void exynos_dp_commit(struct exynos_drm_display *display)
+{
+ struct exynos_dp_device *dp = display->ctx;
+ int ret;
+
+ /* Keep the panel disabled while we configure video */
+ if (dp->panel) {
+ if (drm_panel_disable(dp->panel))
+ DRM_ERROR("failed to disable the panel\n");
+ }
+
ret = exynos_dp_detect_hpd(dp);
if (ret) {
/* Cable has been disconnected, we're done */
@@ -909,6 +921,12 @@ static void exynos_dp_hotplug(struct work_struct *work)
ret = exynos_dp_config_video(dp);
if (ret)
dev_err(dp->dev, "unable to config video\n");
+
+ /* Safe to enable the panel now */
+ if (dp->panel) {
+ if (drm_panel_enable(dp->panel))
+ DRM_ERROR("failed to enable the panel\n");
+ }
}
static enum drm_connector_status exynos_dp_detect(
@@ -933,15 +951,18 @@ static int exynos_dp_get_modes(struct drm_connector *connector)
struct exynos_dp_device *dp = ctx_from_connector(connector);
struct drm_display_mode *mode;
+ if (dp->panel)
+ return drm_panel_get_modes(dp->panel);
+
mode = drm_mode_create(connector->dev);
if (!mode) {
DRM_ERROR("failed to create a new display mode.\n");
return 0;
}
- drm_display_mode_from_videomode(&dp->panel.vm, mode);
- mode->width_mm = dp->panel.width_mm;
- mode->height_mm = dp->panel.height_mm;
+ drm_display_mode_from_videomode(&dp->priv.vm, mode);
+ mode->width_mm = dp->priv.width_mm;
+ mode->height_mm = dp->priv.height_mm;
connector->display_info.width_mm = mode->width_mm;
connector->display_info.height_mm = mode->height_mm;
@@ -1018,10 +1039,13 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display,
}
drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
- return 0;
+ if (dp->panel)
+ ret = drm_panel_attach(dp->panel, &dp->connector);
+
+ return ret;
}
static void exynos_dp_phy_init(struct exynos_dp_device *dp)
@@ -1050,26 +1074,50 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
}
}
-static void exynos_dp_poweron(struct exynos_dp_device *dp)
+static void exynos_dp_poweron(struct exynos_drm_display *display)
{
+ struct exynos_dp_device *dp = display->ctx;
+
if (dp->dpms_mode == DRM_MODE_DPMS_ON)
return;
+ if (dp->panel) {
+ if (drm_panel_prepare(dp->panel)) {
+ DRM_ERROR("failed to setup the panel\n");
+ return;
+ }
+ }
+
clk_prepare_enable(dp->clock);
exynos_dp_phy_init(dp);
exynos_dp_init_dp(dp);
enable_irq(dp->irq);
+ exynos_dp_commit(display);
}
-static void exynos_dp_poweroff(struct exynos_dp_device *dp)
+static void exynos_dp_poweroff(struct exynos_drm_display *display)
{
+ struct exynos_dp_device *dp = display->ctx;
+
if (dp->dpms_mode != DRM_MODE_DPMS_ON)
return;
+ if (dp->panel) {
+ if (drm_panel_disable(dp->panel)) {
+ DRM_ERROR("failed to disable the panel\n");
+ return;
+ }
+ }
+
disable_irq(dp->irq);
flush_work(&dp->hotplug_work);
exynos_dp_phy_exit(dp);
clk_disable_unprepare(dp->clock);
+
+ if (dp->panel) {
+ if (drm_panel_unprepare(dp->panel))
+ DRM_ERROR("failed to turnoff the panel\n");
+ }
}
static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
@@ -1078,12 +1126,12 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
switch (mode) {
case DRM_MODE_DPMS_ON:
- exynos_dp_poweron(dp);
+ exynos_dp_poweron(display);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- exynos_dp_poweroff(dp);
+ exynos_dp_poweroff(display);
break;
default:
break;
@@ -1094,6 +1142,7 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode)
static struct exynos_drm_display_ops exynos_dp_display_ops = {
.create_connector = exynos_dp_create_connector,
.dpms = exynos_dp_dpms,
+ .commit = exynos_dp_commit,
};
static struct exynos_drm_display exynos_dp_display = {
@@ -1201,7 +1250,7 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
{
int ret;
- ret = of_get_videomode(dp->dev->of_node, &dp->panel.vm,
+ ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm,
OF_USE_NATIVE_MODE);
if (ret) {
DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
@@ -1215,16 +1264,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm_dev = data;
struct resource *res;
- struct exynos_dp_device *dp;
+ struct exynos_dp_device *dp = exynos_dp_display.ctx;
unsigned int irq_flags;
-
int ret = 0;
- dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
- GFP_KERNEL);
- if (!dp)
- return -ENOMEM;
-
dp->dev = &pdev->dev;
dp->dpms_mode = DRM_MODE_DPMS_OFF;
@@ -1236,9 +1279,11 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
- ret = exynos_dp_dt_parse_panel(dp);
- if (ret)
- return ret;
+ if (!dp->panel) {
+ ret = exynos_dp_dt_parse_panel(dp);
+ if (ret)
+ return ret;
+ }
dp->clock = devm_clk_get(&pdev->dev, "dp");
if (IS_ERR(dp->clock)) {
@@ -1298,7 +1343,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
disable_irq(dp->irq);
dp->drm_dev = drm_dev;
- exynos_dp_display.ctx = dp;
platform_set_drvdata(pdev, &exynos_dp_display);
@@ -1325,6 +1369,9 @@ static const struct component_ops exynos_dp_ops = {
static int exynos_dp_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct device_node *panel_node;
+ struct exynos_dp_device *dp;
int ret;
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CONNECTOR,
@@ -1332,6 +1379,21 @@ static int exynos_dp_probe(struct platform_device *pdev)
if (ret)
return ret;
+ dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+ GFP_KERNEL);
+ if (!dp)
+ return -ENOMEM;
+
+ panel_node = of_parse_phandle(dev->of_node, "panel", 0);
+ if (panel_node) {
+ dp->panel = of_drm_find_panel(panel_node);
+ of_node_put(panel_node);
+ if (!dp->panel)
+ return -EPROBE_DEFER;
+ }
+
+ exynos_dp_display.ctx = dp;
+
ret = component_add(&pdev->dev, &exynos_dp_ops);
if (ret)
exynos_drm_component_del(&pdev->dev,
@@ -1376,6 +1438,7 @@ static const struct of_device_id exynos_dp_match[] = {
{ .compatible = "samsung,exynos5-dp" },
{},
};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
struct platform_driver dp_driver = {
.probe = exynos_dp_probe,
@@ -1390,4 +1453,4 @@ struct platform_driver dp_driver = {
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h
index 02cc4f9ab903..a1aee6931bd7 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.h
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.h
@@ -149,6 +149,7 @@ struct exynos_dp_device {
struct drm_device *drm_dev;
struct drm_connector connector;
struct drm_encoder *encoder;
+ struct drm_panel *panel;
struct clk *clock;
unsigned int irq;
void __iomem *reg_base;
@@ -162,7 +163,7 @@ struct exynos_dp_device {
int dpms_mode;
int hpd_gpio;
- struct exynos_drm_panel_info panel;
+ struct exynos_drm_panel_info priv;
};
/* exynos_dp_reg.c */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 9a16dbe121d1..ba9b3d5ed672 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -117,20 +117,7 @@ static struct drm_encoder *exynos_drm_best_encoder(
struct drm_device *dev = connector->dev;
struct exynos_drm_connector *exynos_connector =
to_exynos_connector(connector);
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
- obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj) {
- DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
- exynos_connector->encoder_id);
- return NULL;
- }
-
- encoder = obj_to_encoder(obj);
-
- return encoder;
+ return drm_encoder_find(dev, exynos_connector->encoder_id);
}
static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
@@ -185,7 +172,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
struct exynos_drm_connector *exynos_connector =
to_exynos_connector(connector);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(exynos_connector);
}
@@ -230,7 +217,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
drm_connector_init(dev, connector, &exynos_connector_funcs, type);
drm_connector_helper_add(connector, &exynos_connector_helper_funcs);
- err = drm_sysfs_connector_add(connector);
+ err = drm_connector_register(connector);
if (err)
goto err_connector;
@@ -250,7 +237,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
return connector;
err_sysfs:
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
err_connector:
drm_connector_cleanup(connector);
kfree(exynos_connector);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 95c9435d0266..b68e58f78cd1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -69,8 +69,10 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
if (mode > DRM_MODE_DPMS_ON) {
/* wait for the completion of page flip. */
- wait_event(exynos_crtc->pending_flip_queue,
- atomic_read(&exynos_crtc->pending_flip) == 0);
+ if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
+ !atomic_read(&exynos_crtc->pending_flip),
+ HZ/20))
+ atomic_set(&exynos_crtc->pending_flip, 0);
drm_vblank_off(crtc->dev, exynos_crtc->pipe);
}
@@ -259,6 +261,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
spin_lock_irq(&dev->event_lock);
drm_vblank_put(dev, exynos_crtc->pipe);
list_del(&event->base.link);
+ atomic_set(&exynos_crtc->pending_flip, 0);
spin_unlock_irq(&dev->event_lock);
goto out;
@@ -508,3 +511,11 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
return -EPERM;
}
+
+void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
+{
+ struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
+
+ if (manager->ops->te_handler)
+ manager->ops->te_handler(manager);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 9f74b10a8a01..690dcddab725 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
unsigned int out_type);
+/*
+ * This function calls the crtc device(manager)'s te_handler() callback
+ * to trigger to transfer video image at the tearing effect synchronization
+ * signal.
+ */
+void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
+
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 2a3ad24276f8..60192ed544f0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -187,7 +187,7 @@ struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
return dma_buf_export(obj, &exynos_dmabuf_ops,
- exynos_gem_obj->base.size, flags);
+ exynos_gem_obj->base.size, flags, NULL);
}
struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 9e530f205ad2..fa08f05e3e34 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -48,7 +48,7 @@ exynos_dpi_detect(struct drm_connector *connector, bool force)
static void exynos_dpi_connector_destroy(struct drm_connector *connector)
{
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
@@ -117,7 +117,7 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display,
}
drm_connector_helper_add(connector, &exynos_dpi_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
@@ -125,14 +125,18 @@ static int exynos_dpi_create_connector(struct exynos_drm_display *display,
static void exynos_dpi_poweron(struct exynos_dpi *ctx)
{
- if (ctx->panel)
+ if (ctx->panel) {
+ drm_panel_prepare(ctx->panel);
drm_panel_enable(ctx->panel);
+ }
}
static void exynos_dpi_poweroff(struct exynos_dpi *ctx)
{
- if (ctx->panel)
+ if (ctx->panel) {
drm_panel_disable(ctx->panel);
+ drm_panel_unprepare(ctx->panel);
+ }
}
static void exynos_dpi_dpms(struct exynos_drm_display *display, int mode)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ab7d182063c3..0d74e9b99c4e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -39,8 +39,6 @@
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
-#define VBLANK_OFF_DELAY 50000
-
static struct platform_device *exynos_drm_pdev;
static DEFINE_MUTEX(drm_component_lock);
@@ -103,8 +101,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
/* setup possible_clones. */
exynos_drm_encoder_setup(dev);
- drm_vblank_offdelay = VBLANK_OFF_DELAY;
-
platform_set_drvdata(dev->platformdev, dev);
/* Try to bind all sub drivers. */
@@ -362,7 +358,7 @@ static int exynos_drm_sys_suspend(struct device *dev)
struct drm_device *drm_dev = dev_get_drvdata(dev);
pm_message_t message;
- if (pm_runtime_suspended(dev))
+ if (pm_runtime_suspended(dev) || !drm_dev)
return 0;
message.event = PM_EVENT_SUSPEND;
@@ -373,7 +369,7 @@ static int exynos_drm_sys_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
- if (pm_runtime_suspended(dev))
+ if (pm_runtime_suspended(dev) || !drm_dev)
return 0;
return exynos_drm_resume(drm_dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 06cde4506278..69a6fa397d75 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -40,8 +40,6 @@ struct drm_device;
struct exynos_drm_overlay;
struct drm_connector;
-extern unsigned int drm_vblank_offdelay;
-
/* This enumerates device type. */
enum exynos_drm_device_type {
EXYNOS_DEVICE_TYPE_NONE,
@@ -188,6 +186,8 @@ struct exynos_drm_display {
* @win_commit: apply hardware specific overlay data to registers.
* @win_enable: enable hardware specific overlay.
* @win_disable: disable hardware specific overlay.
+ * @te_handler: trigger to transfer video image at the tearing effect
+ * synchronization signal if there is a page flip request.
*/
struct exynos_drm_manager;
struct exynos_drm_manager_ops {
@@ -206,6 +206,7 @@ struct exynos_drm_manager_ops {
void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
+ void (*te_handler)(struct exynos_drm_manager *mgr);
};
/*
@@ -236,14 +237,9 @@ struct exynos_drm_g2d_private {
struct list_head userptr_list;
};
-struct exynos_drm_ipp_private {
- struct device *dev;
- struct list_head event_list;
-};
-
struct drm_exynos_file_private {
struct exynos_drm_g2d_private *g2d_priv;
- struct exynos_drm_ipp_private *ipp_priv;
+ struct device *ipp_dev;
struct file *anon_filp;
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 6302aa64f6c1..442aa2d00132 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -16,7 +16,10 @@
#include <drm/drm_panel.h>
#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
#include <linux/irq.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/component.h>
@@ -24,6 +27,7 @@
#include <video/mipi_display.h>
#include <video/videomode.h>
+#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
/* returns true iff both arguments logically differs */
@@ -54,9 +58,12 @@
/* FIFO memory AC characteristic register */
#define DSIM_PLLCTRL_REG 0x4c /* PLL control register */
-#define DSIM_PLLTMR_REG 0x50 /* PLL timer register */
#define DSIM_PHYACCHR_REG 0x54 /* D-PHY AC characteristic register */
#define DSIM_PHYACCHR1_REG 0x58 /* D-PHY AC characteristic register1 */
+#define DSIM_PHYCTRL_REG 0x5c
+#define DSIM_PHYTIMING_REG 0x64
+#define DSIM_PHYTIMING1_REG 0x68
+#define DSIM_PHYTIMING2_REG 0x6c
/* DSIM_STATUS */
#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
@@ -200,6 +207,24 @@
#define DSIM_PLL_M(x) ((x) << 4)
#define DSIM_PLL_S(x) ((x) << 1)
+/* DSIM_PHYCTRL */
+#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0)
+
+/* DSIM_PHYTIMING */
+#define DSIM_PHYTIMING_LPX(x) ((x) << 8)
+#define DSIM_PHYTIMING_HS_EXIT(x) ((x) << 0)
+
+/* DSIM_PHYTIMING1 */
+#define DSIM_PHYTIMING1_CLK_PREPARE(x) ((x) << 24)
+#define DSIM_PHYTIMING1_CLK_ZERO(x) ((x) << 16)
+#define DSIM_PHYTIMING1_CLK_POST(x) ((x) << 8)
+#define DSIM_PHYTIMING1_CLK_TRAIL(x) ((x) << 0)
+
+/* DSIM_PHYTIMING2 */
+#define DSIM_PHYTIMING2_HS_PREPARE(x) ((x) << 16)
+#define DSIM_PHYTIMING2_HS_ZERO(x) ((x) << 8)
+#define DSIM_PHYTIMING2_HS_TRAIL(x) ((x) << 0)
+
#define DSI_MAX_BUS_WIDTH 4
#define DSI_NUM_VIRTUAL_CHANNELS 4
#define DSI_TX_FIFO_SIZE 2048
@@ -233,6 +258,12 @@ struct exynos_dsi_transfer {
#define DSIM_STATE_INITIALIZED BIT(1)
#define DSIM_STATE_CMD_LPM BIT(2)
+struct exynos_dsi_driver_data {
+ unsigned int plltmr_reg;
+
+ unsigned int has_freqband:1;
+};
+
struct exynos_dsi {
struct mipi_dsi_host dsi_host;
struct drm_connector connector;
@@ -247,6 +278,7 @@ struct exynos_dsi {
struct clk *bus_clk;
struct regulator_bulk_data supplies[2];
int irq;
+ int te_gpio;
u32 pll_clk_rate;
u32 burst_clk_rate;
@@ -262,11 +294,39 @@ struct exynos_dsi {
spinlock_t transfer_lock; /* protects transfer_list */
struct list_head transfer_list;
+
+ struct exynos_dsi_driver_data *driver_data;
};
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
+static struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
+ .plltmr_reg = 0x50,
+ .has_freqband = 1,
+};
+
+static struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
+ .plltmr_reg = 0x58,
+};
+
+static struct of_device_id exynos_dsi_of_match[] = {
+ { .compatible = "samsung,exynos4210-mipi-dsi",
+ .data = &exynos4_dsi_driver_data },
+ { .compatible = "samsung,exynos5410-mipi-dsi",
+ .data = &exynos5_dsi_driver_data },
+ { }
+};
+
+static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
+ struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(exynos_dsi_of_match, &pdev->dev);
+
+ return (struct exynos_dsi_driver_data *)of_id->data;
+}
+
static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
{
if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
@@ -340,14 +400,9 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
unsigned long freq)
{
- static const unsigned long freq_bands[] = {
- 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
- 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
- 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
- 770 * MHZ, 870 * MHZ, 950 * MHZ,
- };
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
unsigned long fin, fout;
- int timeout, band;
+ int timeout;
u8 p, s;
u16 m;
u32 reg;
@@ -368,18 +423,30 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
"failed to find PLL PMS for requested frequency\n");
return -EFAULT;
}
+ dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
- for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
- if (fout < freq_bands[band])
- break;
+ writel(500, dsi->reg_base + driver_data->plltmr_reg);
+
+ reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
- dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d), band %d\n", fout,
- p, m, s, band);
+ if (driver_data->has_freqband) {
+ static const unsigned long freq_bands[] = {
+ 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
+ 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
+ 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
+ 770 * MHZ, 870 * MHZ, 950 * MHZ,
+ };
+ int band;
- writel(500, dsi->reg_base + DSIM_PLLTMR_REG);
+ for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
+ if (fout < freq_bands[band])
+ break;
+
+ dev_dbg(dsi->dev, "band %d\n", band);
+
+ reg |= DSIM_FREQ_BAND(band);
+ }
- reg = DSIM_FREQ_BAND(band) | DSIM_PLL_EN
- | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
timeout = 1000;
@@ -433,6 +500,59 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
return 0;
}
+static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
+{
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+ u32 reg;
+
+ if (driver_data->has_freqband)
+ return;
+
+ /* B D-PHY: D-PHY Master & Slave Analog Block control */
+ reg = DSIM_PHYCTRL_ULPS_EXIT(0x0af);
+ writel(reg, dsi->reg_base + DSIM_PHYCTRL_REG);
+
+ /*
+ * T LPX: Transmitted length of any Low-Power state period
+ * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
+ * burst
+ */
+ reg = DSIM_PHYTIMING_LPX(0x06) | DSIM_PHYTIMING_HS_EXIT(0x0b);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING_REG);
+
+ /*
+ * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
+ * Line state immediately before the HS-0 Line state starting the
+ * HS transmission
+ * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
+ * transmitting the Clock.
+ * T CLK_POST: Time that the transmitter continues to send HS clock
+ * after the last associated Data Lane has transitioned to LP Mode
+ * Interval is defined as the period from the end of T HS-TRAIL to
+ * the beginning of T CLK-TRAIL
+ * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
+ * the last payload clock bit of a HS transmission burst
+ */
+ reg = DSIM_PHYTIMING1_CLK_PREPARE(0x07) |
+ DSIM_PHYTIMING1_CLK_ZERO(0x27) |
+ DSIM_PHYTIMING1_CLK_POST(0x0d) |
+ DSIM_PHYTIMING1_CLK_TRAIL(0x08);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING1_REG);
+
+ /*
+ * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
+ * Line state immediately before the HS-0 Line state starting the
+ * HS transmission
+ * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
+ * transmitting the Sync sequence.
+ * T HS-TRAIL: Time that the transmitter drives the flipped differential
+ * state after last payload data bit of a HS transmission burst
+ */
+ reg = DSIM_PHYTIMING2_HS_PREPARE(0x09) | DSIM_PHYTIMING2_HS_ZERO(0x0d) |
+ DSIM_PHYTIMING2_HS_TRAIL(0x0b);
+ writel(reg, dsi->reg_base + DSIM_PHYTIMING2_REG);
+}
+
static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
{
u32 reg;
@@ -468,13 +588,20 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
/* DSI configuration */
reg = 0;
+ /*
+ * The first bit of mode_flags specifies display configuration.
+ * If this bit is set[= MIPI_DSI_MODE_VIDEO], dsi will support video
+ * mode, otherwise it will support command mode.
+ */
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
reg |= DSIM_VIDEO_MODE;
+ /*
+ * The user manual describes that following bits are ignored in
+ * command mode.
+ */
if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
reg |= DSIM_MFLUSH_VS;
- if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
- reg |= DSIM_EOT_DISABLE;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
reg |= DSIM_SYNC_INFORM;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -491,6 +618,9 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
reg |= DSIM_HSA_MODE;
}
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
+ reg |= DSIM_EOT_DISABLE;
+
switch (dsi->format) {
case MIPI_DSI_FMT_RGB888:
reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
@@ -944,17 +1074,90 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
+{
+ struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
+ struct drm_encoder *encoder = dsi->encoder;
+
+ if (dsi->state & DSIM_STATE_ENABLED)
+ exynos_drm_crtc_te_handler(encoder->crtc);
+
+ return IRQ_HANDLED;
+}
+
+static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
+{
+ enable_irq(dsi->irq);
+
+ if (gpio_is_valid(dsi->te_gpio))
+ enable_irq(gpio_to_irq(dsi->te_gpio));
+}
+
+static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
+{
+ if (gpio_is_valid(dsi->te_gpio))
+ disable_irq(gpio_to_irq(dsi->te_gpio));
+
+ disable_irq(dsi->irq);
+}
+
static int exynos_dsi_init(struct exynos_dsi *dsi)
{
- exynos_dsi_enable_clock(dsi);
exynos_dsi_reset(dsi);
- enable_irq(dsi->irq);
+ exynos_dsi_enable_irq(dsi);
+ exynos_dsi_enable_clock(dsi);
exynos_dsi_wait_for_reset(dsi);
+ exynos_dsi_set_phy_ctrl(dsi);
exynos_dsi_init_link(dsi);
return 0;
}
+static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi)
+{
+ int ret;
+
+ dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0);
+ if (!gpio_is_valid(dsi->te_gpio)) {
+ dev_err(dsi->dev, "no te-gpios specified\n");
+ ret = dsi->te_gpio;
+ goto out;
+ }
+
+ ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
+ if (ret) {
+ dev_err(dsi->dev, "gpio request failed with %d\n", ret);
+ goto out;
+ }
+
+ /*
+ * This TE GPIO IRQ should not be set to IRQ_NOAUTOEN, because panel
+ * calls drm_panel_init() first then calls mipi_dsi_attach() in probe().
+ * It means that te_gpio is invalid when exynos_dsi_enable_irq() is
+ * called by drm_panel_init() before panel is attached.
+ */
+ ret = request_threaded_irq(gpio_to_irq(dsi->te_gpio),
+ exynos_dsi_te_irq_handler, NULL,
+ IRQF_TRIGGER_RISING, "TE", dsi);
+ if (ret) {
+ dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
+ gpio_free(dsi->te_gpio);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
+{
+ if (gpio_is_valid(dsi->te_gpio)) {
+ free_irq(gpio_to_irq(dsi->te_gpio), dsi);
+ gpio_free(dsi->te_gpio);
+ dsi->te_gpio = -ENOENT;
+ }
+}
+
static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
@@ -968,6 +1171,19 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
if (dsi->connector.dev)
drm_helper_hpd_irq_event(dsi->connector.dev);
+ /*
+ * This is a temporary solution and should be made by more generic way.
+ *
+ * If attached panel device is for command mode one, dsi should register
+ * TE interrupt handler.
+ */
+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) {
+ int ret = exynos_dsi_register_te_irq(dsi);
+
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -976,6 +1192,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
{
struct exynos_dsi *dsi = host_to_dsi(host);
+ exynos_dsi_unregister_te_irq(dsi);
+
dsi->panel_node = NULL;
if (dsi->connector.dev)
@@ -1089,7 +1307,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
exynos_dsi_disable_clock(dsi);
- disable_irq(dsi->irq);
+ exynos_dsi_disable_irq(dsi);
}
dsi->state &= ~DSIM_STATE_CMD_LPM;
@@ -1115,7 +1333,7 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi)
if (ret < 0)
return ret;
- ret = drm_panel_enable(dsi->panel);
+ ret = drm_panel_prepare(dsi->panel);
if (ret < 0) {
exynos_dsi_poweroff(dsi);
return ret;
@@ -1124,6 +1342,14 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi)
exynos_dsi_set_display_mode(dsi);
exynos_dsi_set_display_enable(dsi, true);
+ ret = drm_panel_enable(dsi->panel);
+ if (ret < 0) {
+ exynos_dsi_set_display_enable(dsi, false);
+ drm_panel_unprepare(dsi->panel);
+ exynos_dsi_poweroff(dsi);
+ return ret;
+ }
+
dsi->state |= DSIM_STATE_ENABLED;
return 0;
@@ -1134,8 +1360,9 @@ static void exynos_dsi_disable(struct exynos_dsi *dsi)
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
- exynos_dsi_set_display_enable(dsi, false);
drm_panel_disable(dsi->panel);
+ exynos_dsi_set_display_enable(dsi, false);
+ drm_panel_unprepare(dsi->panel);
exynos_dsi_poweroff(dsi);
dsi->state &= ~DSIM_STATE_ENABLED;
@@ -1246,7 +1473,7 @@ static int exynos_dsi_create_connector(struct exynos_drm_display *display,
}
drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
@@ -1278,6 +1505,7 @@ static struct exynos_drm_display exynos_dsi_display = {
.type = EXYNOS_DISPLAY_TYPE_LCD,
.ops = &exynos_dsi_display_ops,
};
+MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
/* of_* functions will be removed after merge of of_graph patches */
static struct device_node *
@@ -1435,6 +1663,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
goto err_del_component;
}
+ /* To be checked as invalid one */
+ dsi->te_gpio = -ENOENT;
+
init_completion(&dsi->completed);
spin_lock_init(&dsi->transfer_lock);
INIT_LIST_HEAD(&dsi->transfer_list);
@@ -1443,6 +1674,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->dsi_host.dev = &pdev->dev;
dsi->dev = &pdev->dev;
+ dsi->driver_data = exynos_dsi_get_driver_data(pdev);
ret = exynos_dsi_parse_dt(dsi);
if (ret)
@@ -1525,11 +1757,6 @@ static int exynos_dsi_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id exynos_dsi_of_match[] = {
- { .compatible = "samsung,exynos4210-mipi-dsi" },
- { }
-};
-
struct platform_driver dsi_driver = {
.probe = exynos_dsi_probe,
.remove = exynos_dsi_remove,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index d771b467cf0c..32e63f60e1d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -225,7 +225,7 @@ out:
return ret;
}
-static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
.fb_probe = exynos_drm_fbdev_create,
};
@@ -266,7 +266,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
return -ENOMEM;
private->fb_helper = helper = &fbdev->drm_fb_helper;
- helper->funcs = &exynos_drm_fb_helper_funcs;
+
+ drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs);
num_crtc = dev->mode_config.num_crtc;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 831dde9034c6..ec7cc9ea50df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1887,6 +1887,7 @@ static const struct of_device_id fimc_of_match[] = {
{ .compatible = "samsung,exynos4212-fimc" },
{ },
};
+MODULE_DEVICE_TABLE(of, fimc_of_match);
struct platform_driver fimc_driver = {
.probe = fimc_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 33161ad38201..5d09e33fef87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -20,6 +20,8 @@
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/component.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
@@ -61,6 +63,24 @@
/* color key value register for hardware window 1 ~ 4. */
#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
+/* I80 / RGB trigger control register */
+#define TRIGCON 0x1A4
+#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0)
+#define SWTRGCMD_I80_RGB_ENABLE (1 << 1)
+
+/* display mode change control register except exynos4 */
+#define VIDOUT_CON 0x000
+#define VIDOUT_CON_F_I80_LDI0 (0x2 << 8)
+
+/* I80 interface control for main LDI register */
+#define I80IFCONFAx(x) (0x1B0 + (x) * 4)
+#define I80IFCONFBx(x) (0x1B8 + (x) * 4)
+#define LCD_CS_SETUP(x) ((x) << 16)
+#define LCD_WR_SETUP(x) ((x) << 12)
+#define LCD_WR_ACTIVE(x) ((x) << 8)
+#define LCD_WR_HOLD(x) ((x) << 4)
+#define I80IFEN_ENABLE (1 << 0)
+
/* FIMD has totally five hardware windows. */
#define WINDOWS_NR 5
@@ -68,10 +88,14 @@
struct fimd_driver_data {
unsigned int timing_base;
+ unsigned int lcdblk_offset;
+ unsigned int lcdblk_vt_shift;
+ unsigned int lcdblk_bypass_shift;
unsigned int has_shadowcon:1;
unsigned int has_clksel:1;
unsigned int has_limited_fmt:1;
+ unsigned int has_vidoutcon:1;
};
static struct fimd_driver_data s3c64xx_fimd_driver_data = {
@@ -82,12 +106,19 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
static struct fimd_driver_data exynos4_fimd_driver_data = {
.timing_base = 0x0,
+ .lcdblk_offset = 0x210,
+ .lcdblk_vt_shift = 10,
+ .lcdblk_bypass_shift = 1,
.has_shadowcon = 1,
};
static struct fimd_driver_data exynos5_fimd_driver_data = {
.timing_base = 0x20000,
+ .lcdblk_offset = 0x214,
+ .lcdblk_vt_shift = 24,
+ .lcdblk_bypass_shift = 15,
.has_shadowcon = 1,
+ .has_vidoutcon = 1,
};
struct fimd_win_data {
@@ -112,15 +143,22 @@ struct fimd_context {
struct clk *bus_clk;
struct clk *lcd_clk;
void __iomem *regs;
+ struct regmap *sysreg;
struct drm_display_mode mode;
struct fimd_win_data win_data[WINDOWS_NR];
unsigned int default_win;
unsigned long irq_flags;
+ u32 vidcon0;
u32 vidcon1;
+ u32 vidout_con;
+ u32 i80ifcon;
+ bool i80_if;
bool suspended;
int pipe;
wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event;
+ atomic_t win_updated;
+ atomic_t triggering;
struct exynos_drm_panel_info panel;
struct fimd_driver_data *driver_data;
@@ -136,6 +174,7 @@ static const struct of_device_id fimd_driver_dt_match[] = {
.data = &exynos5_fimd_driver_data },
{},
};
+MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
static inline struct fimd_driver_data *drm_fimd_get_driver_data(
struct platform_device *pdev)
@@ -243,6 +282,14 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
u32 clkdiv;
+ if (ctx->i80_if) {
+ /*
+ * The frame done interrupt should be occurred prior to the
+ * next TE signal.
+ */
+ ideal_clk *= 2;
+ }
+
/* Find the clock divider value that gets us closest to ideal_clk */
clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
@@ -271,11 +318,10 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
{
struct fimd_context *ctx = mgr->ctx;
struct drm_display_mode *mode = &ctx->mode;
- struct fimd_driver_data *driver_data;
- u32 val, clkdiv, vidcon1;
- int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
+ struct fimd_driver_data *driver_data = ctx->driver_data;
+ void *timing_base = ctx->regs + driver_data->timing_base;
+ u32 val, clkdiv;
- driver_data = ctx->driver_data;
if (ctx->suspended)
return;
@@ -283,33 +329,65 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
if (mode->htotal == 0 || mode->vtotal == 0)
return;
- /* setup polarity values */
- vidcon1 = ctx->vidcon1;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- vidcon1 |= VIDCON1_INV_VSYNC;
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- vidcon1 |= VIDCON1_INV_HSYNC;
- writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
-
- /* setup vertical timing values. */
- vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
- vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
- vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
-
- val = VIDTCON0_VBPD(vbpd - 1) |
- VIDTCON0_VFPD(vfpd - 1) |
- VIDTCON0_VSPW(vsync_len - 1);
- writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
-
- /* setup horizontal timing values. */
- hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
- hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
- hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
-
- val = VIDTCON1_HBPD(hbpd - 1) |
- VIDTCON1_HFPD(hfpd - 1) |
- VIDTCON1_HSPW(hsync_len - 1);
- writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+ if (ctx->i80_if) {
+ val = ctx->i80ifcon | I80IFEN_ENABLE;
+ writel(val, timing_base + I80IFCONFAx(0));
+
+ /* disable auto frame rate */
+ writel(0, timing_base + I80IFCONFBx(0));
+
+ /* set video type selection to I80 interface */
+ if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+ driver_data->lcdblk_offset,
+ 0x3 << driver_data->lcdblk_vt_shift,
+ 0x1 << driver_data->lcdblk_vt_shift)) {
+ DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
+ return;
+ }
+ } else {
+ int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
+ u32 vidcon1;
+
+ /* setup polarity values */
+ vidcon1 = ctx->vidcon1;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ vidcon1 |= VIDCON1_INV_VSYNC;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ vidcon1 |= VIDCON1_INV_HSYNC;
+ writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
+
+ /* setup vertical timing values. */
+ vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
+ vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
+
+ val = VIDTCON0_VBPD(vbpd - 1) |
+ VIDTCON0_VFPD(vfpd - 1) |
+ VIDTCON0_VSPW(vsync_len - 1);
+ writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
+
+ /* setup horizontal timing values. */
+ hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+ hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
+ hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
+
+ val = VIDTCON1_HBPD(hbpd - 1) |
+ VIDTCON1_HFPD(hfpd - 1) |
+ VIDTCON1_HSPW(hsync_len - 1);
+ writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
+ }
+
+ if (driver_data->has_vidoutcon)
+ writel(ctx->vidout_con, timing_base + VIDOUT_CON);
+
+ /* set bypass selection */
+ if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
+ driver_data->lcdblk_offset,
+ 0x1 << driver_data->lcdblk_bypass_shift,
+ 0x1 << driver_data->lcdblk_bypass_shift)) {
+ DRM_ERROR("Failed to update sysreg for bypass setting.\n");
+ return;
+ }
/* setup horizontal and vertical display size. */
val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
@@ -322,7 +400,8 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
* fields of register with prefix '_F' would be updated
* at vsync(same as dma start)
*/
- val = VIDCON0_ENVID | VIDCON0_ENVID_F;
+ val = ctx->vidcon0;
+ val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
if (ctx->driver_data->has_clksel)
val |= VIDCON0_CLKSEL_LCD;
@@ -660,6 +739,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
}
win_data->enabled = true;
+
+ if (ctx->i80_if)
+ atomic_set(&ctx->win_updated, 1);
}
static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
@@ -838,6 +920,58 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
}
}
+static void fimd_trigger(struct device *dev)
+{
+ struct exynos_drm_manager *mgr = get_fimd_manager(dev);
+ struct fimd_context *ctx = mgr->ctx;
+ struct fimd_driver_data *driver_data = ctx->driver_data;
+ void *timing_base = ctx->regs + driver_data->timing_base;
+ u32 reg;
+
+ atomic_set(&ctx->triggering, 1);
+
+ reg = readl(ctx->regs + VIDINTCON0);
+ reg |= (VIDINTCON0_INT_ENABLE | VIDINTCON0_INT_I80IFDONE |
+ VIDINTCON0_INT_SYSMAINCON);
+ writel(reg, ctx->regs + VIDINTCON0);
+
+ reg = readl(timing_base + TRIGCON);
+ reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
+ writel(reg, timing_base + TRIGCON);
+}
+
+static void fimd_te_handler(struct exynos_drm_manager *mgr)
+{
+ struct fimd_context *ctx = mgr->ctx;
+
+ /* Checks the crtc is detached already from encoder */
+ if (ctx->pipe < 0 || !ctx->drm_dev)
+ return;
+
+ /*
+ * Skips to trigger if in triggering state, because multiple triggering
+ * requests can cause panel reset.
+ */
+ if (atomic_read(&ctx->triggering))
+ return;
+
+ /*
+ * If there is a page flip request, triggers and handles the page flip
+ * event so that current fb can be updated into panel GRAM.
+ */
+ if (atomic_add_unless(&ctx->win_updated, -1, 0))
+ fimd_trigger(ctx->dev);
+
+ /* Wakes up vsync event queue */
+ if (atomic_read(&ctx->wait_vsync_event)) {
+ atomic_set(&ctx->wait_vsync_event, 0);
+ wake_up(&ctx->wait_vsync_queue);
+
+ if (!atomic_read(&ctx->triggering))
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ }
+}
+
static struct exynos_drm_manager_ops fimd_manager_ops = {
.dpms = fimd_dpms,
.mode_fixup = fimd_mode_fixup,
@@ -849,6 +983,7 @@ static struct exynos_drm_manager_ops fimd_manager_ops = {
.win_mode_set = fimd_win_mode_set,
.win_commit = fimd_win_commit,
.win_disable = fimd_win_disable,
+ .te_handler = fimd_te_handler,
};
static struct exynos_drm_manager fimd_manager = {
@@ -859,26 +994,40 @@ static struct exynos_drm_manager fimd_manager = {
static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
{
struct fimd_context *ctx = (struct fimd_context *)dev_id;
- u32 val;
+ u32 val, clear_bit;
val = readl(ctx->regs + VIDINTCON1);
- if (val & VIDINTCON1_INT_FRAME)
- /* VSYNC interrupt */
- writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
+ clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
+ if (val & clear_bit)
+ writel(clear_bit, ctx->regs + VIDINTCON1);
/* check the crtc is detached already from encoder */
if (ctx->pipe < 0 || !ctx->drm_dev)
goto out;
- drm_handle_vblank(ctx->drm_dev, ctx->pipe);
- exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+ if (ctx->i80_if) {
+ /* unset I80 frame done interrupt */
+ val = readl(ctx->regs + VIDINTCON0);
+ val &= ~(VIDINTCON0_INT_I80IFDONE | VIDINTCON0_INT_SYSMAINCON);
+ writel(val, ctx->regs + VIDINTCON0);
- /* set wait vsync event to zero and wake up queue. */
- if (atomic_read(&ctx->wait_vsync_event)) {
- atomic_set(&ctx->wait_vsync_event, 0);
- wake_up(&ctx->wait_vsync_queue);
+ /* exit triggering mode */
+ atomic_set(&ctx->triggering, 0);
+
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+ } else {
+ drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+ exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
+
+ /* set wait vsync event to zero and wake up queue. */
+ if (atomic_read(&ctx->wait_vsync_event)) {
+ atomic_set(&ctx->wait_vsync_event, 0);
+ wake_up(&ctx->wait_vsync_queue);
+ }
}
+
out:
return IRQ_HANDLED;
}
@@ -923,6 +1072,7 @@ static int fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fimd_context *ctx;
+ struct device_node *i80_if_timings;
struct resource *res;
int ret = -EINVAL;
@@ -944,12 +1094,51 @@ static int fimd_probe(struct platform_device *pdev)
ctx->dev = dev;
ctx->suspended = true;
+ ctx->driver_data = drm_fimd_get_driver_data(pdev);
if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
ctx->vidcon1 |= VIDCON1_INV_VDEN;
if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
ctx->vidcon1 |= VIDCON1_INV_VCLK;
+ i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
+ if (i80_if_timings) {
+ u32 val;
+
+ ctx->i80_if = true;
+
+ if (ctx->driver_data->has_vidoutcon)
+ ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
+ else
+ ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
+ /*
+ * The user manual describes that this "DSI_EN" bit is required
+ * to enable I80 24-bit data interface.
+ */
+ ctx->vidcon0 |= VIDCON0_DSI_EN;
+
+ if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
+ val = 0;
+ ctx->i80ifcon = LCD_CS_SETUP(val);
+ if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
+ val = 0;
+ ctx->i80ifcon |= LCD_WR_SETUP(val);
+ if (of_property_read_u32(i80_if_timings, "wr-active", &val))
+ val = 1;
+ ctx->i80ifcon |= LCD_WR_ACTIVE(val);
+ if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
+ val = 0;
+ ctx->i80ifcon |= LCD_WR_HOLD(val);
+ }
+ of_node_put(i80_if_timings);
+
+ ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,sysreg");
+ if (IS_ERR(ctx->sysreg)) {
+ dev_warn(dev, "failed to get system register.\n");
+ ctx->sysreg = NULL;
+ }
+
ctx->bus_clk = devm_clk_get(dev, "fimd");
if (IS_ERR(ctx->bus_clk)) {
dev_err(dev, "failed to get bus clock\n");
@@ -972,7 +1161,8 @@ static int fimd_probe(struct platform_device *pdev)
goto err_del_component;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync");
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ ctx->i80_if ? "lcd_sys" : "vsync");
if (!res) {
dev_err(dev, "irq request failed.\n");
ret = -ENXIO;
@@ -986,7 +1176,6 @@ static int fimd_probe(struct platform_device *pdev)
goto err_del_component;
}
- ctx->driver_data = drm_fimd_get_driver_data(pdev);
init_waitqueue_head(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 800158714473..df7a77d3eff8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1042,8 +1042,23 @@ err:
int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
struct drm_file *file)
{
+ struct drm_exynos_file_private *file_priv = file->driver_priv;
+ struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
+ struct device *dev;
+ struct g2d_data *g2d;
struct drm_exynos_g2d_get_ver *ver = data;
+ if (!g2d_priv)
+ return -ENODEV;
+
+ dev = g2d_priv->dev;
+ if (!dev)
+ return -ENODEV;
+
+ g2d = dev_get_drvdata(dev);
+ if (!g2d)
+ return -EFAULT;
+
ver->major = G2D_HW_MAJOR_VER;
ver->minor = G2D_HW_MINOR_VER;
@@ -1056,7 +1071,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
+ struct device *dev;
struct g2d_data *g2d;
struct drm_exynos_g2d_set_cmdlist *req = data;
struct drm_exynos_g2d_cmd *cmd;
@@ -1067,6 +1082,10 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
int size;
int ret;
+ if (!g2d_priv)
+ return -ENODEV;
+
+ dev = g2d_priv->dev;
if (!dev)
return -ENODEV;
@@ -1223,13 +1242,17 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
- struct device *dev = g2d_priv->dev;
+ struct device *dev;
struct g2d_data *g2d;
struct drm_exynos_g2d_exec *req = data;
struct g2d_runqueue_node *runqueue_node;
struct list_head *run_cmdlist;
struct list_head *event_list;
+ if (!g2d_priv)
+ return -ENODEV;
+
+ dev = g2d_priv->dev;
if (!dev)
return -ENODEV;
@@ -1544,8 +1567,10 @@ static const struct dev_pm_ops g2d_pm_ops = {
static const struct of_device_id exynos_g2d_match[] = {
{ .compatible = "samsung,exynos5250-g2d" },
+ { .compatible = "samsung,exynos4212-g2d" },
{},
};
+MODULE_DEVICE_TABLE(of, exynos_g2d_match);
struct platform_driver g2d_driver = {
.probe = g2d_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 163a054922cb..15db80138382 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -301,7 +301,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
unsigned int gem_handle,
struct drm_file *filp)
{
- struct exynos_drm_gem_obj *exynos_gem_obj;
struct drm_gem_object *obj;
obj = drm_gem_object_lookup(dev, filp, gem_handle);
@@ -310,8 +309,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
return;
}
- exynos_gem_obj = to_exynos_gem_obj(obj);
-
drm_gem_object_unreference_unlocked(obj);
/*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index a1888e128f1d..c411399070d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -129,9 +129,6 @@ void exynos_platform_device_ipp_unregister(void)
int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
{
- if (!ippdrv)
- return -EINVAL;
-
mutex_lock(&exynos_drm_ippdrv_lock);
list_add_tail(&ippdrv->drv_list, &exynos_drm_ippdrv_list);
mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -141,9 +138,6 @@ int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
{
- if (!ippdrv)
- return -EINVAL;
-
mutex_lock(&exynos_drm_ippdrv_lock);
list_del(&ippdrv->drv_list);
mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -151,20 +145,15 @@ int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
return 0;
}
-static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
- u32 *idp)
+static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj)
{
int ret;
- /* do the allocation under our mutexlock */
mutex_lock(lock);
ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
mutex_unlock(lock);
- if (ret < 0)
- return ret;
- *idp = ret;
- return 0;
+ return ret;
}
static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id)
@@ -178,35 +167,25 @@ static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
{
void *obj;
- DRM_DEBUG_KMS("id[%d]\n", id);
-
mutex_lock(lock);
-
- /* find object using handle */
obj = idr_find(id_idr, id);
- if (!obj) {
- DRM_ERROR("failed to find object.\n");
- mutex_unlock(lock);
- return ERR_PTR(-ENODEV);
- }
-
mutex_unlock(lock);
return obj;
}
-static inline bool ipp_check_dedicated(struct exynos_drm_ippdrv *ippdrv,
- enum drm_exynos_ipp_cmd cmd)
+static int ipp_check_driver(struct exynos_drm_ippdrv *ippdrv,
+ struct drm_exynos_ipp_property *property)
{
- /*
- * check dedicated flag and WB, OUTPUT operation with
- * power on state.
- */
- if (ippdrv->dedicated || (!ipp_is_m2m_cmd(cmd) &&
- !pm_runtime_suspended(ippdrv->dev)))
- return true;
+ if (ippdrv->dedicated || (!ipp_is_m2m_cmd(property->cmd) &&
+ !pm_runtime_suspended(ippdrv->dev)))
+ return -EBUSY;
- return false;
+ if (ippdrv->check_property &&
+ ippdrv->check_property(ippdrv->dev, property))
+ return -EINVAL;
+
+ return 0;
}
static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
@@ -214,62 +193,30 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
{
struct exynos_drm_ippdrv *ippdrv;
u32 ipp_id = property->ipp_id;
-
- DRM_DEBUG_KMS("ipp_id[%d]\n", ipp_id);
+ int ret;
if (ipp_id) {
- /* find ipp driver using idr */
- ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
- ipp_id);
- if (IS_ERR(ippdrv)) {
- DRM_ERROR("not found ipp%d driver.\n", ipp_id);
- return ippdrv;
+ ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, ipp_id);
+ if (!ippdrv) {
+ DRM_DEBUG("ipp%d driver not found\n", ipp_id);
+ return ERR_PTR(-ENODEV);
}
- /*
- * WB, OUTPUT opertion not supported multi-operation.
- * so, make dedicated state at set property ioctl.
- * when ipp driver finished operations, clear dedicated flags.
- */
- if (ipp_check_dedicated(ippdrv, property->cmd)) {
- DRM_ERROR("already used choose device.\n");
- return ERR_PTR(-EBUSY);
- }
-
- /*
- * This is necessary to find correct device in ipp drivers.
- * ipp drivers have different abilities,
- * so need to check property.
- */
- if (ippdrv->check_property &&
- ippdrv->check_property(ippdrv->dev, property)) {
- DRM_ERROR("not support property.\n");
- return ERR_PTR(-EINVAL);
+ ret = ipp_check_driver(ippdrv, property);
+ if (ret < 0) {
+ DRM_DEBUG("ipp%d driver check error %d\n", ipp_id, ret);
+ return ERR_PTR(ret);
}
return ippdrv;
} else {
- /*
- * This case is search all ipp driver for finding.
- * user application don't set ipp_id in this case,
- * so ipp subsystem search correct driver in driver list.
- */
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
- if (ipp_check_dedicated(ippdrv, property->cmd)) {
- DRM_DEBUG_KMS("used device.\n");
- continue;
- }
-
- if (ippdrv->check_property &&
- ippdrv->check_property(ippdrv->dev, property)) {
- DRM_DEBUG_KMS("not support property.\n");
- continue;
- }
-
- return ippdrv;
+ ret = ipp_check_driver(ippdrv, property);
+ if (ret == 0)
+ return ippdrv;
}
- DRM_ERROR("not support ipp driver operations.\n");
+ DRM_DEBUG("cannot find driver suitable for given property.\n");
}
return ERR_PTR(-ENODEV);
@@ -308,8 +255,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
- struct device *dev = priv->dev;
+ struct device *dev = file_priv->ipp_dev;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_prop_list *prop_list = data;
struct exynos_drm_ippdrv *ippdrv;
@@ -346,10 +292,10 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
*/
ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
prop_list->ipp_id);
- if (IS_ERR(ippdrv)) {
+ if (!ippdrv) {
DRM_ERROR("not found ipp%d driver.\n",
prop_list->ipp_id);
- return PTR_ERR(ippdrv);
+ return -ENODEV;
}
*prop_list = ippdrv->prop_list;
@@ -432,7 +378,7 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
if (!event_work)
return ERR_PTR(-ENOMEM);
- INIT_WORK((struct work_struct *)event_work, ipp_sched_event);
+ INIT_WORK(&event_work->work, ipp_sched_event);
return event_work;
}
@@ -441,8 +387,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
- struct device *dev = priv->dev;
+ struct device *dev = file_priv->ipp_dev;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_property *property = data;
struct exynos_drm_ippdrv *ippdrv;
@@ -489,19 +434,18 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
if (!c_node)
return -ENOMEM;
- /* create property id */
- ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node,
- &property->prop_id);
- if (ret) {
+ ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node);
+ if (ret < 0) {
DRM_ERROR("failed to create id.\n");
goto err_clear;
}
+ property->prop_id = ret;
DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
property->prop_id, property->cmd, (int)ippdrv);
/* stored property information and ippdrv in private data */
- c_node->priv = priv;
+ c_node->dev = dev;
c_node->property = *property;
c_node->state = IPP_STATE_IDLE;
@@ -534,7 +478,6 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
INIT_LIST_HEAD(&c_node->mem_list[i]);
INIT_LIST_HEAD(&c_node->event_list);
- list_splice_init(&priv->event_list, &c_node->event_list);
mutex_lock(&ippdrv->cmd_lock);
list_add_tail(&c_node->list, &ippdrv->cmd_list);
mutex_unlock(&ippdrv->cmd_lock);
@@ -577,42 +520,18 @@ static void ipp_clean_cmd_node(struct ipp_context *ctx,
kfree(c_node);
}
-static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
+static bool ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
{
- struct drm_exynos_ipp_property *property = &c_node->property;
- struct drm_exynos_ipp_mem_node *m_node;
- struct list_head *head;
- int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, };
-
- for_each_ipp_ops(i) {
- /* source/destination memory list */
- head = &c_node->mem_list[i];
-
- /* find memory node entry */
- list_for_each_entry(m_node, head, list) {
- DRM_DEBUG_KMS("%s,count[%d]m_node[0x%x]\n",
- i ? "dst" : "src", count[i], (int)m_node);
- count[i]++;
- }
+ switch (c_node->property.cmd) {
+ case IPP_CMD_WB:
+ return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
+ case IPP_CMD_OUTPUT:
+ return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]);
+ case IPP_CMD_M2M:
+ default:
+ return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]) &&
+ !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
}
-
- DRM_DEBUG_KMS("min[%d]max[%d]\n",
- min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
- max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
-
- /*
- * M2M operations should be need paired memory address.
- * so, need to check minimum count about src, dst.
- * other case not use paired memory, so use maximum count
- */
- if (ipp_is_m2m_cmd(property->cmd))
- ret = min(count[EXYNOS_DRM_OPS_SRC],
- count[EXYNOS_DRM_OPS_DST]);
- else
- ret = max(count[EXYNOS_DRM_OPS_SRC],
- count[EXYNOS_DRM_OPS_DST]);
-
- return ret;
}
static struct drm_exynos_ipp_mem_node
@@ -683,16 +602,14 @@ static struct drm_exynos_ipp_mem_node
struct drm_exynos_ipp_queue_buf *qbuf)
{
struct drm_exynos_ipp_mem_node *m_node;
- struct drm_exynos_ipp_buf_info buf_info;
- void *addr;
+ struct drm_exynos_ipp_buf_info *buf_info;
int i;
m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
if (!m_node)
return ERR_PTR(-ENOMEM);
- /* clear base address for error handling */
- memset(&buf_info, 0x0, sizeof(buf_info));
+ buf_info = &m_node->buf_info;
/* operations, buffer id */
m_node->ops_id = qbuf->ops_id;
@@ -707,6 +624,8 @@ static struct drm_exynos_ipp_mem_node
/* get dma address by handle */
if (qbuf->handle[i]) {
+ dma_addr_t *addr;
+
addr = exynos_drm_gem_get_dma_addr(drm_dev,
qbuf->handle[i], file);
if (IS_ERR(addr)) {
@@ -714,15 +633,14 @@ static struct drm_exynos_ipp_mem_node
goto err_clear;
}
- buf_info.handles[i] = qbuf->handle[i];
- buf_info.base[i] = *(dma_addr_t *) addr;
- DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%x]\n",
- i, buf_info.base[i], (int)buf_info.handles[i]);
+ buf_info->handles[i] = qbuf->handle[i];
+ buf_info->base[i] = *addr;
+ DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i,
+ buf_info->base[i], buf_info->handles[i]);
}
}
m_node->filp = file;
- m_node->buf_info = buf_info;
mutex_lock(&c_node->mem_lock);
list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
mutex_unlock(&c_node->mem_lock);
@@ -930,8 +848,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
- struct device *dev = priv->dev;
+ struct device *dev = file_priv->ipp_dev;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_queue_buf *qbuf = data;
struct drm_exynos_ipp_cmd_node *c_node;
@@ -955,9 +872,9 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
/* find command node */
c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
qbuf->prop_id);
- if (IS_ERR(c_node)) {
+ if (!c_node) {
DRM_ERROR("failed to get command node.\n");
- return PTR_ERR(c_node);
+ return -ENODEV;
}
/* buffer control */
@@ -1062,9 +979,8 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
struct exynos_drm_ippdrv *ippdrv = NULL;
- struct device *dev = priv->dev;
+ struct device *dev = file_priv->ipp_dev;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data;
struct drm_exynos_ipp_cmd_work *cmd_work;
@@ -1091,9 +1007,9 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
cmd_ctrl->prop_id);
- if (IS_ERR(c_node)) {
+ if (!c_node) {
DRM_ERROR("invalid command node list.\n");
- return PTR_ERR(c_node);
+ return -ENODEV;
}
if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl,
@@ -1198,7 +1114,6 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
/* reset h/w block */
if (ippdrv->reset &&
ippdrv->reset(ippdrv->dev)) {
- DRM_ERROR("failed to reset.\n");
return -EINVAL;
}
@@ -1216,30 +1131,24 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
/* set format */
if (ops->set_fmt) {
ret = ops->set_fmt(ippdrv->dev, config->fmt);
- if (ret) {
- DRM_ERROR("not support format.\n");
+ if (ret)
return ret;
- }
}
/* set transform for rotation, flip */
if (ops->set_transf) {
ret = ops->set_transf(ippdrv->dev, config->degree,
config->flip, &swap);
- if (ret) {
- DRM_ERROR("not support tranf.\n");
- return -EINVAL;
- }
+ if (ret)
+ return ret;
}
/* set size */
if (ops->set_size) {
ret = ops->set_size(ippdrv->dev, swap, &config->pos,
&config->sz);
- if (ret) {
- DRM_ERROR("not support size.\n");
+ if (ret)
return ret;
- }
}
}
@@ -1283,11 +1192,6 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
m_node = list_first_entry(head,
struct drm_exynos_ipp_mem_node, list);
- if (!m_node) {
- DRM_ERROR("failed to get node.\n");
- ret = -EFAULT;
- goto err_unlock;
- }
DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
@@ -1545,11 +1449,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
m_node = list_first_entry(head,
struct drm_exynos_ipp_mem_node, list);
- if (!m_node) {
- DRM_ERROR("empty memory node.\n");
- ret = -ENOMEM;
- goto err_mem_unlock;
- }
tbuf_id[i] = m_node->buf_id;
DRM_DEBUG_KMS("%s buf_id[%d]\n",
@@ -1586,11 +1485,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
m_node = list_first_entry(head,
struct drm_exynos_ipp_mem_node, list);
- if (!m_node) {
- DRM_ERROR("empty memory node.\n");
- ret = -ENOMEM;
- goto err_mem_unlock;
- }
tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id;
@@ -1704,21 +1598,17 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
/* get ipp driver entry */
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
- u32 ipp_id;
-
ippdrv->drm_dev = drm_dev;
- ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv,
- &ipp_id);
- if (ret || ipp_id == 0) {
+ ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv);
+ if (ret < 0) {
DRM_ERROR("failed to create id.\n");
goto err;
}
+ ippdrv->prop_list.ipp_id = ret;
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
- count++, (int)ippdrv, ipp_id);
-
- ippdrv->prop_list.ipp_id = ipp_id;
+ count++, (int)ippdrv, ret);
/* store parent device for node */
ippdrv->parent_dev = dev;
@@ -1776,17 +1666,10 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->dev = dev;
- file_priv->ipp_priv = priv;
- INIT_LIST_HEAD(&priv->event_list);
+ file_priv->ipp_dev = dev;
- DRM_DEBUG_KMS("done priv[0x%x]\n", (int)priv);
+ DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev);
return 0;
}
@@ -1795,13 +1678,12 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file)
{
struct drm_exynos_file_private *file_priv = file->driver_priv;
- struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
struct exynos_drm_ippdrv *ippdrv = NULL;
struct ipp_context *ctx = get_ipp_context(dev);
struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
int count = 0;
- DRM_DEBUG_KMS("for priv[0x%x]\n", (int)priv);
+ DRM_DEBUG_KMS("for priv[0x%x]\n", (int)file_priv->ipp_dev);
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
mutex_lock(&ippdrv->cmd_lock);
@@ -1810,7 +1692,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
count++, (int)ippdrv);
- if (c_node->priv == priv) {
+ if (c_node->dev == file_priv->ipp_dev) {
/*
* userland goto unnormal state. process killed.
* and close the file.
@@ -1832,7 +1714,6 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
mutex_unlock(&ippdrv->cmd_lock);
}
- kfree(priv);
return;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index 7aaeaae757c2..6f48d62aeb30 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work {
/*
* A structure of command node.
*
- * @priv: IPP private information.
+ * @dev: IPP device.
* @list: list head to command queue information.
* @event_list: list head of event.
* @mem_list: list head to source,destination memory queue information.
@@ -64,7 +64,7 @@ struct drm_exynos_ipp_cmd_work {
* @state: state of command node.
*/
struct drm_exynos_ipp_cmd_node {
- struct exynos_drm_ipp_private *priv;
+ struct device *dev;
struct list_head list;
struct list_head event_list;
struct list_head mem_list[EXYNOS_DRM_OPS_MAX];
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index f01fbb6dc1f0..55af6b41c1df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -691,6 +691,7 @@ static const struct of_device_id exynos_rotator_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, exynos_rotator_match);
static int rotator_probe(struct platform_device *pdev)
{
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 2fb8705d6461..9528d81d8004 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -562,7 +562,7 @@ static int vidi_create_connector(struct exynos_drm_display *display,
}
drm_connector_helper_add(connector, &vidi_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index aa259b0a873a..562966db2aa1 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -84,6 +84,7 @@ struct hdmi_resources {
struct clk *sclk_hdmiphy;
struct clk *mout_hdmi;
struct regulator_bulk_data *regul_bulk;
+ struct regulator *reg_hdmi_en;
int regul_count;
};
@@ -592,6 +593,13 @@ static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
.is_apb_phy = 0,
};
+static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
+ .type = HDMI_TYPE13,
+ .phy_confs = hdmiphy_v13_configs,
+ .phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs),
+ .is_apb_phy = 0,
+};
+
static struct hdmi_driver_data exynos5_hdmi_driver_data = {
.type = HDMI_TYPE14,
.phy_confs = hdmiphy_v13_configs,
@@ -1129,7 +1137,7 @@ static int hdmi_create_connector(struct exynos_drm_display *display,
}
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
@@ -1241,14 +1249,13 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
static void hdmi_audio_init(struct hdmi_context *hdata)
{
- u32 sample_rate, bits_per_sample, frame_size_code;
+ u32 sample_rate, bits_per_sample;
u32 data_num, bit_ch, sample_frq;
u32 val;
u8 acr[7];
sample_rate = 44100;
bits_per_sample = 16;
- frame_size_code = 0;
switch (bits_per_sample) {
case 20:
@@ -2168,7 +2175,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
struct device *dev = hdata->dev;
struct hdmi_resources *res = &hdata->res;
static char *supply[] = {
- "hdmi-en",
"vdd",
"vdd_osc",
"vdd_pll",
@@ -2228,6 +2234,20 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
}
res->regul_count = ARRAY_SIZE(supply);
+ res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
+ if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
+ DRM_ERROR("failed to get hdmi-en regulator\n");
+ return PTR_ERR(res->reg_hdmi_en);
+ }
+ if (!IS_ERR(res->reg_hdmi_en)) {
+ ret = regulator_enable(res->reg_hdmi_en);
+ if (ret) {
+ DRM_ERROR("failed to enable hdmi-en regulator\n");
+ return ret;
+ }
+ } else
+ res->reg_hdmi_en = NULL;
+
return ret;
fail:
DRM_ERROR("HDMI resource init - failed\n");
@@ -2263,6 +2283,9 @@ static struct of_device_id hdmi_match_types[] = {
.compatible = "samsung,exynos5-hdmi",
.data = &exynos5_hdmi_driver_data,
}, {
+ .compatible = "samsung,exynos4210-hdmi",
+ .data = &exynos4210_hdmi_driver_data,
+ }, {
.compatible = "samsung,exynos4212-hdmi",
.data = &exynos4212_hdmi_driver_data,
}, {
@@ -2272,6 +2295,7 @@ static struct of_device_id hdmi_match_types[] = {
/* end node */
}
};
+MODULE_DEVICE_TABLE (of, hdmi_match_types);
static int hdmi_bind(struct device *dev, struct device *master, void *data)
{
@@ -2494,7 +2518,11 @@ static int hdmi_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&hdata->hotplug_work);
- put_device(&hdata->hdmiphy_port->dev);
+ if (hdata->res.reg_hdmi_en)
+ regulator_disable(hdata->res.reg_hdmi_en);
+
+ if (hdata->hdmiphy_port)
+ put_device(&hdata->hdmiphy_port->dev);
put_device(&hdata->ddc_adpt->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7529946d0a74..e8b4ec84b312 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -76,7 +76,7 @@ struct mixer_resources {
struct clk *vp;
struct clk *sclk_mixer;
struct clk *sclk_hdmi;
- struct clk *sclk_dac;
+ struct clk *mout_mixer;
};
enum mixer_version_id {
@@ -93,6 +93,7 @@ struct mixer_context {
bool interlace;
bool powered;
bool vp_enabled;
+ bool has_sclk;
u32 int_en;
struct mutex mixer_mutex;
@@ -106,6 +107,7 @@ struct mixer_context {
struct mixer_drv_data {
enum mixer_version_id version;
bool is_vp_enabled;
+ bool has_sclk;
};
static const u8 filter_y_horiz_tap8[] = {
@@ -363,6 +365,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
mixer_reg_writemask(res, MXR_CFG, val,
MXR_CFG_VP_ENABLE);
+
+ /* control blending of graphic layer 0 */
+ mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
+ MXR_GRP_CFG_BLEND_PRE_MUL |
+ MXR_GRP_CFG_PIXEL_BLEND_EN);
}
break;
}
@@ -809,19 +816,23 @@ static int vp_resources_init(struct mixer_context *mixer_ctx)
dev_err(dev, "failed to get clock 'vp'\n");
return -ENODEV;
}
- mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
- if (IS_ERR(mixer_res->sclk_mixer)) {
- dev_err(dev, "failed to get clock 'sclk_mixer'\n");
- return -ENODEV;
- }
- mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
- if (IS_ERR(mixer_res->sclk_dac)) {
- dev_err(dev, "failed to get clock 'sclk_dac'\n");
- return -ENODEV;
- }
- if (mixer_res->sclk_hdmi)
- clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
+ if (mixer_ctx->has_sclk) {
+ mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
+ if (IS_ERR(mixer_res->sclk_mixer)) {
+ dev_err(dev, "failed to get clock 'sclk_mixer'\n");
+ return -ENODEV;
+ }
+ mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
+ if (IS_ERR(mixer_res->mout_mixer)) {
+ dev_err(dev, "failed to get clock 'mout_mixer'\n");
+ return -ENODEV;
+ }
+
+ if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
+ clk_set_parent(mixer_res->mout_mixer,
+ mixer_res->sclk_hdmi);
+ }
res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
if (res == NULL) {
@@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
clk_prepare_enable(res->mixer);
if (ctx->vp_enabled) {
clk_prepare_enable(res->vp);
- clk_prepare_enable(res->sclk_mixer);
+ if (ctx->has_sclk)
+ clk_prepare_enable(res->sclk_mixer);
}
mutex_lock(&ctx->mixer_mutex);
@@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
clk_disable_unprepare(res->mixer);
if (ctx->vp_enabled) {
clk_disable_unprepare(res->vp);
- clk_disable_unprepare(res->sclk_mixer);
+ if (ctx->has_sclk)
+ clk_disable_unprepare(res->sclk_mixer);
}
pm_runtime_put_sync(ctx->dev);
@@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_mxr_drv_data = {
.is_vp_enabled = 0,
};
+static struct mixer_drv_data exynos4212_mxr_drv_data = {
+ .version = MXR_VER_0_0_0_16,
+ .is_vp_enabled = 1,
+};
+
static struct mixer_drv_data exynos4210_mxr_drv_data = {
.version = MXR_VER_0_0_0_16,
.is_vp_enabled = 1,
+ .has_sclk = 1,
};
static struct platform_device_id mixer_driver_types[] = {
@@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_driver_types[] = {
static struct of_device_id mixer_match_types[] = {
{
+ .compatible = "samsung,exynos4210-mixer",
+ .data = &exynos4210_mxr_drv_data,
+ }, {
+ .compatible = "samsung,exynos4212-mixer",
+ .data = &exynos4212_mxr_drv_data,
+ }, {
.compatible = "samsung,exynos5-mixer",
.data = &exynos5250_mxr_drv_data,
}, {
@@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_types[] = {
/* end node */
}
};
+MODULE_DEVICE_TABLE(of, mixer_match_types);
static int mixer_bind(struct device *dev, struct device *manager, void *data)
{
@@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
ctx->pdev = pdev;
ctx->dev = dev;
ctx->vp_enabled = drv->is_vp_enabled;
+ ctx->has_sclk = drv->has_sclk;
ctx->mxr_ver = drv->version;
init_waitqueue_head(&ctx->wait_vsync_queue);
atomic_set(&ctx->wait_vsync_event, 0);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index c18268cd516e..248c33a35ebf 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -192,7 +192,7 @@ static void cdv_intel_crt_destroy(struct drm_connector *connector)
struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
psb_intel_i2c_destroy(gma_encoder->ddc_bus);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -304,7 +304,7 @@ void cdv_intel_crt_init(struct drm_device *dev,
drm_connector_helper_add(connector,
&cdv_intel_crt_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
failed_ddc:
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 9ff30c2efadb..a4cc0e60a1be 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1713,7 +1713,7 @@ cdv_intel_dp_destroy(struct drm_connector *connector)
}
}
i2c_del_adapter(&intel_dp->adapter);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -1847,7 +1847,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
/* Set up the DDC bus. */
switch (output_reg) {
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index b99084b3f706..4268bf210034 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -248,7 +248,7 @@ static void cdv_hdmi_destroy(struct drm_connector *connector)
if (gma_encoder->i2c_bus)
psb_intel_i2c_destroy(gma_encoder->i2c_bus);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -356,7 +356,7 @@ void cdv_hdmi_init(struct drm_device *dev,
hdmi_priv->hdmi_i2c_adapter = &(gma_encoder->i2c_bus->adapter);
hdmi_priv->dev = dev;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
failed_ddc:
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 8ecc920fc26d..0b770396548c 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -446,7 +446,7 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector)
if (gma_encoder->i2c_bus)
psb_intel_i2c_destroy(gma_encoder->i2c_bus);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -774,7 +774,7 @@ void cdv_intel_lvds_init(struct drm_device *dev,
out:
mutex_unlock(&dev->mode_config.mutex);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
failed_find:
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index e7fcc148f333..d0dd3bea8aa5 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -561,7 +561,7 @@ static int psbfb_probe(struct drm_fb_helper *helper,
return psbfb_create(psb_fbdev, sizes);
}
-static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
.gamma_set = psbfb_gamma_set,
.gamma_get = psbfb_gamma_get,
.fb_probe = psbfb_probe,
@@ -600,7 +600,8 @@ int psb_fbdev_init(struct drm_device *dev)
}
dev_priv->fbdev = fbdev;
- fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+ drm_fb_helper_prepare(dev, &fbdev->psb_fb_helper, &psb_fb_helper_funcs);
drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
INTELFB_CONN_LIMIT);
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 592d205a0089..ce015db59dc6 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -206,7 +206,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
WARN_ON(gt->pages);
- pages = drm_gem_get_pages(&gt->gem, 0);
+ pages = drm_gem_get_pages(&gt->gem);
if (IS_ERR(pages))
return PTR_ERR(pages);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 6e91b20ce2e5..abf2248da61e 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -318,7 +318,7 @@ static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
if (!dsi_connector)
return;
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
sender = dsi_connector->pkg_sender;
mdfld_dsi_pkg_sender_destroy(sender);
@@ -597,7 +597,7 @@ void mdfld_dsi_output_init(struct drm_device *dev,
dsi_config->encoder = encoder;
encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
INTEL_OUTPUT_MIPI2;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
/*TODO: add code to destroy outputs on error*/
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c
index a97e38e284fa..d75ecb3bdee7 100644
--- a/drivers/gpu/drm/gma500/mid_bios.c
+++ b/drivers/gpu/drm/gma500/mid_bios.c
@@ -39,7 +39,6 @@ static void mid_get_fuse_settings(struct drm_device *dev)
#define FB_REG06 0xD0810600
#define FB_MIPI_DISABLE (1 << 11)
#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
#define FB_SKU_MASK 0x7000
#define FB_SKU_SHIFT 12
#define FB_SKU_100 0
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index cf018ddcc5a6..54f73f50571a 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -665,7 +665,7 @@ void oaktrail_hdmi_init(struct drm_device *dev,
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
dev_info(dev->dev, "HDMI initialised.\n");
return;
@@ -674,7 +674,7 @@ failed_connector:
kfree(gma_encoder);
}
-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
+static const struct pci_device_id hdmi_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
{ 0 }
};
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index 9b099468a5db..0d39da6e8b7a 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -404,7 +404,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
out:
mutex_unlock(&dev->mode_config.mutex);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
failed_find:
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 6e8fe9ec02b5..eec993f93b1a 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -54,7 +54,7 @@ static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
* PowerVR SGX545 - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700,
* N2800
*/
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
#if defined(CONFIG_DRM_GMA600)
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index d7778d0472c1..88aad95bde09 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -563,7 +563,7 @@ void psb_intel_lvds_destroy(struct drm_connector *connector)
if (lvds_priv->ddc_bus)
psb_intel_i2c_destroy(lvds_priv->ddc_bus);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -829,7 +829,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
*/
out:
mutex_unlock(&dev->mode_config.mutex);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
failed_find:
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index deeb0829b129..0be96fdb5e28 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1682,7 +1682,7 @@ static void psb_intel_sdvo_destroy(struct drm_connector *connector)
psb_intel_sdvo_connector->tv_format);
psb_intel_sdvo_destroy_enhance_property(connector);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -2071,7 +2071,7 @@ psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector,
connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
gma_connector_attach_encoder(&connector->base, &encoder->base);
- drm_sysfs_connector_add(&connector->base.base);
+ drm_connector_register(&connector->base.base);
}
static void
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index ac357b02bd35..d4762799351d 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -15,8 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
+#include <linux/component.h>
#include <linux/hdmi.h>
#include <linux/module.h>
#include <linux/irq.h>
@@ -730,12 +729,9 @@ tda998x_configure_audio(struct tda998x_priv *priv,
/* DRM encoder functions */
-static void
-tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
+static void tda998x_encoder_set_config(struct tda998x_priv *priv,
+ const struct tda998x_encoder_params *p)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
- struct tda998x_encoder_params *p = params;
-
priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
(p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
VIP_CNTRL_0_SWAP_B(p->swap_b) |
@@ -752,11 +748,8 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
priv->params = *p;
}
-static void
-tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+static void tda998x_encoder_dpms(struct tda998x_priv *priv, int mode)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
/* we only care about on or off: */
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
@@ -806,9 +799,8 @@ tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
return true;
}
-static int
-tda998x_encoder_mode_valid(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+static int tda998x_encoder_mode_valid(struct tda998x_priv *priv,
+ struct drm_display_mode *mode)
{
if (mode->clock > 150000)
return MODE_CLOCK_HIGH;
@@ -820,11 +812,10 @@ tda998x_encoder_mode_valid(struct drm_encoder *encoder,
}
static void
-tda998x_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+tda998x_encoder_mode_set(struct tda998x_priv *priv,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
uint16_t ref_pix, ref_line, n_pix, n_line;
uint16_t hs_pix_s, hs_pix_e;
uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
@@ -1012,20 +1003,16 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
}
static enum drm_connector_status
-tda998x_encoder_detect(struct drm_encoder *encoder,
- struct drm_connector *connector)
+tda998x_encoder_detect(struct tda998x_priv *priv)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV);
return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
connector_status_disconnected;
}
-static int
-read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+static int read_edid_block(struct tda998x_priv *priv, uint8_t *buf, int blk)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
uint8_t offset, segptr;
int ret, i;
@@ -1079,10 +1066,8 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
return 0;
}
-static uint8_t *
-do_get_edid(struct drm_encoder *encoder)
+static uint8_t *do_get_edid(struct tda998x_priv *priv)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
int j, valid_extensions = 0;
uint8_t *block, *new;
bool print_bad_edid = drm_debug & DRM_UT_KMS;
@@ -1094,7 +1079,7 @@ do_get_edid(struct drm_encoder *encoder)
reg_clear(priv, REG_TX4, TX4_PD_RAM);
/* base block fetch */
- if (read_edid_block(encoder, block, 0))
+ if (read_edid_block(priv, block, 0))
goto fail;
if (!drm_edid_block_valid(block, 0, print_bad_edid))
@@ -1111,7 +1096,7 @@ do_get_edid(struct drm_encoder *encoder)
for (j = 1; j <= block[0x7e]; j++) {
uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
- if (read_edid_block(encoder, ext_block, j))
+ if (read_edid_block(priv, ext_block, j))
goto fail;
if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
@@ -1144,11 +1129,10 @@ fail:
}
static int
-tda998x_encoder_get_modes(struct drm_encoder *encoder,
- struct drm_connector *connector)
+tda998x_encoder_get_modes(struct tda998x_priv *priv,
+ struct drm_connector *connector)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
- struct edid *edid = (struct edid *)do_get_edid(encoder);
+ struct edid *edid = (struct edid *)do_get_edid(priv);
int n = 0;
if (edid) {
@@ -1161,18 +1145,14 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder,
return n;
}
-static int
-tda998x_encoder_create_resources(struct drm_encoder *encoder,
- struct drm_connector *connector)
+static void tda998x_encoder_set_polling(struct tda998x_priv *priv,
+ struct drm_connector *connector)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
if (priv->hdmi->irq)
connector->polled = DRM_CONNECTOR_POLL_HPD;
else
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
- return 0;
}
static int
@@ -1185,66 +1165,97 @@ tda998x_encoder_set_property(struct drm_encoder *encoder,
return 0;
}
-static void
-tda998x_encoder_destroy(struct drm_encoder *encoder)
+static void tda998x_destroy(struct tda998x_priv *priv)
{
- struct tda998x_priv *priv = to_tda998x_priv(encoder);
-
/* disable all IRQs and free the IRQ handler */
cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
if (priv->hdmi->irq)
free_irq(priv->hdmi->irq, priv);
- if (priv->cec)
- i2c_unregister_device(priv->cec);
+ i2c_unregister_device(priv->cec);
+}
+
+/* Slave encoder support */
+
+static void
+tda998x_encoder_slave_set_config(struct drm_encoder *encoder, void *params)
+{
+ tda998x_encoder_set_config(to_tda998x_priv(encoder), params);
+}
+
+static void tda998x_encoder_slave_destroy(struct drm_encoder *encoder)
+{
+ struct tda998x_priv *priv = to_tda998x_priv(encoder);
+
+ tda998x_destroy(priv);
drm_i2c_encoder_destroy(encoder);
kfree(priv);
}
-static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
- .set_config = tda998x_encoder_set_config,
- .destroy = tda998x_encoder_destroy,
- .dpms = tda998x_encoder_dpms,
- .save = tda998x_encoder_save,
- .restore = tda998x_encoder_restore,
- .mode_fixup = tda998x_encoder_mode_fixup,
- .mode_valid = tda998x_encoder_mode_valid,
- .mode_set = tda998x_encoder_mode_set,
- .detect = tda998x_encoder_detect,
- .get_modes = tda998x_encoder_get_modes,
- .create_resources = tda998x_encoder_create_resources,
- .set_property = tda998x_encoder_set_property,
-};
+static void tda998x_encoder_slave_dpms(struct drm_encoder *encoder, int mode)
+{
+ tda998x_encoder_dpms(to_tda998x_priv(encoder), mode);
+}
-/* I2C driver functions */
+static int tda998x_encoder_slave_mode_valid(struct drm_encoder *encoder,
+ struct drm_display_mode *mode)
+{
+ return tda998x_encoder_mode_valid(to_tda998x_priv(encoder), mode);
+}
-static int
-tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static void
+tda998x_encoder_slave_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
{
- return 0;
+ tda998x_encoder_mode_set(to_tda998x_priv(encoder), mode, adjusted_mode);
+}
+
+static enum drm_connector_status
+tda998x_encoder_slave_detect(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+{
+ return tda998x_encoder_detect(to_tda998x_priv(encoder));
+}
+
+static int tda998x_encoder_slave_get_modes(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+{
+ return tda998x_encoder_get_modes(to_tda998x_priv(encoder), connector);
}
static int
-tda998x_remove(struct i2c_client *client)
+tda998x_encoder_slave_create_resources(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
+ tda998x_encoder_set_polling(to_tda998x_priv(encoder), connector);
return 0;
}
-static int
-tda998x_encoder_init(struct i2c_client *client,
- struct drm_device *dev,
- struct drm_encoder_slave *encoder_slave)
+static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = {
+ .set_config = tda998x_encoder_slave_set_config,
+ .destroy = tda998x_encoder_slave_destroy,
+ .dpms = tda998x_encoder_slave_dpms,
+ .save = tda998x_encoder_save,
+ .restore = tda998x_encoder_restore,
+ .mode_fixup = tda998x_encoder_mode_fixup,
+ .mode_valid = tda998x_encoder_slave_mode_valid,
+ .mode_set = tda998x_encoder_slave_mode_set,
+ .detect = tda998x_encoder_slave_detect,
+ .get_modes = tda998x_encoder_slave_get_modes,
+ .create_resources = tda998x_encoder_slave_create_resources,
+ .set_property = tda998x_encoder_set_property,
+};
+
+/* I2C driver functions */
+
+static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
{
- struct tda998x_priv *priv;
struct device_node *np = client->dev.of_node;
u32 video;
int rev_lo, rev_hi, ret;
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
@@ -1252,17 +1263,11 @@ tda998x_encoder_init(struct i2c_client *client,
priv->current_page = 0xff;
priv->hdmi = client;
priv->cec = i2c_new_dummy(client->adapter, 0x34);
- if (!priv->cec) {
- kfree(priv);
+ if (!priv->cec)
return -ENODEV;
- }
- priv->encoder = &encoder_slave->base;
priv->dpms = DRM_MODE_DPMS_OFF;
- encoder_slave->slave_priv = priv;
- encoder_slave->slave_funcs = &tda998x_encoder_funcs;
-
/* wake up the device: */
cec_write(priv, REG_CEC_ENAMODS,
CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
@@ -1365,12 +1370,231 @@ fail:
*/
if (priv->cec)
i2c_unregister_device(priv->cec);
- kfree(priv);
- encoder_slave->slave_priv = NULL;
- encoder_slave->slave_funcs = NULL;
return -ENXIO;
}
+static int tda998x_encoder_init(struct i2c_client *client,
+ struct drm_device *dev,
+ struct drm_encoder_slave *encoder_slave)
+{
+ struct tda998x_priv *priv;
+ int ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->encoder = &encoder_slave->base;
+
+ ret = tda998x_create(client, priv);
+ if (ret) {
+ kfree(priv);
+ return ret;
+ }
+
+ encoder_slave->slave_priv = priv;
+ encoder_slave->slave_funcs = &tda998x_encoder_slave_funcs;
+
+ return 0;
+}
+
+struct tda998x_priv2 {
+ struct tda998x_priv base;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+#define conn_to_tda998x_priv2(x) \
+ container_of(x, struct tda998x_priv2, connector);
+
+#define enc_to_tda998x_priv2(x) \
+ container_of(x, struct tda998x_priv2, encoder);
+
+static void tda998x_encoder2_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+ tda998x_encoder_dpms(&priv->base, mode);
+}
+
+static void tda998x_encoder_prepare(struct drm_encoder *encoder)
+{
+ tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void tda998x_encoder_commit(struct drm_encoder *encoder)
+{
+ tda998x_encoder2_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void tda998x_encoder2_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+ tda998x_encoder_mode_set(&priv->base, mode, adjusted_mode);
+}
+
+static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = {
+ .dpms = tda998x_encoder2_dpms,
+ .save = tda998x_encoder_save,
+ .restore = tda998x_encoder_restore,
+ .mode_fixup = tda998x_encoder_mode_fixup,
+ .prepare = tda998x_encoder_prepare,
+ .commit = tda998x_encoder_commit,
+ .mode_set = tda998x_encoder2_mode_set,
+};
+
+static void tda998x_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct tda998x_priv2 *priv = enc_to_tda998x_priv2(encoder);
+
+ tda998x_destroy(&priv->base);
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs tda998x_encoder_funcs = {
+ .destroy = tda998x_encoder_destroy,
+};
+
+static int tda998x_connector_get_modes(struct drm_connector *connector)
+{
+ struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+ return tda998x_encoder_get_modes(&priv->base, connector);
+}
+
+static int tda998x_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+ return tda998x_encoder_mode_valid(&priv->base, mode);
+}
+
+static struct drm_encoder *
+tda998x_connector_best_encoder(struct drm_connector *connector)
+{
+ struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+ return &priv->encoder;
+}
+
+static
+const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
+ .get_modes = tda998x_connector_get_modes,
+ .mode_valid = tda998x_connector_mode_valid,
+ .best_encoder = tda998x_connector_best_encoder,
+};
+
+static enum drm_connector_status
+tda998x_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct tda998x_priv2 *priv = conn_to_tda998x_priv2(connector);
+
+ return tda998x_encoder_detect(&priv->base);
+}
+
+static void tda998x_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs tda998x_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = tda998x_connector_detect,
+ .destroy = tda998x_connector_destroy,
+};
+
+static int tda998x_bind(struct device *dev, struct device *master, void *data)
+{
+ struct tda998x_encoder_params *params = dev->platform_data;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct drm_device *drm = data;
+ struct tda998x_priv2 *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, priv);
+
+ priv->base.encoder = &priv->encoder;
+ priv->connector.interlace_allowed = 1;
+ priv->encoder.possible_crtcs = 1 << 0;
+
+ ret = tda998x_create(client, &priv->base);
+ if (ret)
+ return ret;
+
+ if (!dev->of_node && params)
+ tda998x_encoder_set_config(&priv->base, params);
+
+ tda998x_encoder_set_polling(&priv->base, &priv->connector);
+
+ drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
+ ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ if (ret)
+ goto err_encoder;
+
+ drm_connector_helper_add(&priv->connector,
+ &tda998x_connector_helper_funcs);
+ ret = drm_connector_init(drm, &priv->connector,
+ &tda998x_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA);
+ if (ret)
+ goto err_connector;
+
+ ret = drm_connector_register(&priv->connector);
+ if (ret)
+ goto err_sysfs;
+
+ priv->connector.encoder = &priv->encoder;
+ drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
+
+ return 0;
+
+err_sysfs:
+ drm_connector_cleanup(&priv->connector);
+err_connector:
+ drm_encoder_cleanup(&priv->encoder);
+err_encoder:
+ tda998x_destroy(&priv->base);
+ return ret;
+}
+
+static void tda998x_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct tda998x_priv2 *priv = dev_get_drvdata(dev);
+
+ drm_connector_cleanup(&priv->connector);
+ drm_encoder_cleanup(&priv->encoder);
+ tda998x_destroy(&priv->base);
+}
+
+static const struct component_ops tda998x_ops = {
+ .bind = tda998x_bind,
+ .unbind = tda998x_unbind,
+};
+
+static int
+tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ return component_add(&client->dev, &tda998x_ops);
+}
+
+static int tda998x_remove(struct i2c_client *client)
+{
+ component_del(&client->dev, &tda998x_ops);
+ return 0;
+}
+
#ifdef CONFIG_OF
static const struct of_device_id tda998x_dt_ids[] = {
{ .compatible = "nxp,tda998x", },
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index e88bac1d781f..bae897de9468 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -393,15 +393,14 @@ static int i810_dma_initialize(struct drm_device *dev,
/* Program Hardware Status Page */
dev_priv->hw_status_page =
- pci_alloc_consistent(dev->pdev, PAGE_SIZE,
- &dev_priv->dma_status_page);
+ pci_zalloc_consistent(dev->pdev, PAGE_SIZE,
+ &dev_priv->dma_status_page);
if (!dev_priv->hw_status_page) {
dev->dev_private = (void *)dev_priv;
i810_dma_cleanup(dev);
DRM_ERROR("Can not allocate hardware status page\n");
return -ENOMEM;
}
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
I810_WRITE(0x02080, dev_priv->dma_status_page);
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 437e1824d0bf..4e39ab34eb1c 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -69,15 +69,3 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
option changes the default for that module option.
If in doubt, say "N".
-
-config DRM_I915_UMS
- bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
- depends on DRM_I915 && BROKEN
- default n
- help
- Choose this option if you still need userspace modesetting.
-
- Userspace modesetting is deprecated for quite some time now, so
- enable this only if you have ancient versions of the DDX drivers.
-
- If in doubt, say "N".
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index cad1683d8bb5..91bd167e1cb7 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -59,6 +59,7 @@ i915-y += dvo_ch7017.o \
intel_crt.o \
intel_ddi.o \
intel_dp.o \
+ intel_dp_mst.o \
intel_dsi_cmd.o \
intel_dsi.o \
intel_dsi_pll.o \
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 9d7954366bd2..dea99d92fb4a 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -426,6 +426,9 @@ static const u32 gen7_render_regs[] = {
GEN7_SO_WRITE_OFFSET(1),
GEN7_SO_WRITE_OFFSET(2),
GEN7_SO_WRITE_OFFSET(3),
+ GEN7_L3SQCREG1,
+ GEN7_L3CNTLREG2,
+ GEN7_L3CNTLREG3,
};
static const u32 gen7_blt_regs[] = {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b8c689202c40..9e737b771c40 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -170,11 +170,13 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
}
if (obj->ring != NULL)
seq_printf(m, " (%s)", obj->ring->name);
+ if (obj->frontbuffer_bits)
+ seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
}
static void describe_ctx(struct seq_file *m, struct intel_context *ctx)
{
- seq_putc(m, ctx->is_initialized ? 'I' : 'i');
+ seq_putc(m, ctx->legacy_hw_ctx.initialized ? 'I' : 'i');
seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, ' ');
}
@@ -515,6 +517,11 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
unsigned long flags;
struct intel_crtc *crtc;
+ int ret;
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
for_each_intel_crtc(dev, crtc) {
const char pipe = pipe_name(crtc->pipe);
@@ -556,6 +563,8 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+ mutex_unlock(&dev->struct_mutex);
+
return 0;
}
@@ -985,29 +994,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
i915_next_seqno_get, i915_next_seqno_set,
"0x%llx\n");
-static int i915_rstdby_delays(struct seq_file *m, void *unused)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u16 crstanddelay;
- int ret;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
- intel_runtime_pm_get(dev_priv);
-
- crstanddelay = I915_READ16(CRSTANDVID);
-
- intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
-
- seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
-
- return 0;
-}
-
static int i915_frequency_info(struct seq_file *m, void *unused)
{
struct drm_info_node *node = m->private;
@@ -1029,7 +1015,8 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
MEMSTAT_VID_SHIFT);
seq_printf(m, "Current P-state: %d\n",
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
- } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
+ } else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
+ IS_BROADWELL(dev)) {
u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
@@ -1048,7 +1035,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
reqf = I915_READ(GEN6_RPNSWREQ);
reqf &= ~GEN6_TURBO_DISABLE;
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev))
reqf >>= 24;
else
reqf >>= 25;
@@ -1065,7 +1052,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
- if (IS_HASWELL(dev))
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev))
cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
else
cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
@@ -1121,20 +1108,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
seq_printf(m, "Max overclocked frequency: %dMHz\n",
dev_priv->rps.max_freq * GT_FREQUENCY_MULTIPLIER);
} else if (IS_VALLEYVIEW(dev)) {
- u32 freq_sts, val;
+ u32 freq_sts;
mutex_lock(&dev_priv->rps.hw_lock);
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
- val = valleyview_rps_max_freq(dev_priv);
seq_printf(m, "max GPU freq: %d MHz\n",
- vlv_gpu_freq(dev_priv, val));
+ vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq));
- val = valleyview_rps_min_freq(dev_priv);
seq_printf(m, "min GPU freq: %d MHz\n",
- vlv_gpu_freq(dev_priv, val));
+ vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq));
+
+ seq_printf(m, "efficient (RPe) frequency: %d MHz\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
seq_printf(m, "current GPU freq: %d MHz\n",
vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
@@ -1148,61 +1136,6 @@ out:
return ret;
}
-static int i915_delayfreq_table(struct seq_file *m, void *unused)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 delayfreq;
- int ret, i;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
- intel_runtime_pm_get(dev_priv);
-
- for (i = 0; i < 16; i++) {
- delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
- seq_printf(m, "P%02dVIDFREQ: 0x%08x (VID: %d)\n", i, delayfreq,
- (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
- }
-
- intel_runtime_pm_put(dev_priv);
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-static inline int MAP_TO_MV(int map)
-{
- return 1250 - (map * 25);
-}
-
-static int i915_inttoext_table(struct seq_file *m, void *unused)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- u32 inttoext;
- int ret, i;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
- intel_runtime_pm_get(dev_priv);
-
- for (i = 1; i <= 32; i++) {
- inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
- seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
- }
-
- intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
static int ironlake_drpc_info(struct seq_file *m)
{
struct drm_info_node *node = m->private;
@@ -1513,10 +1446,17 @@ static int i915_ips_status(struct seq_file *m, void *unused)
intel_runtime_pm_get(dev_priv);
- if (IS_BROADWELL(dev) || I915_READ(IPS_CTL) & IPS_ENABLE)
- seq_puts(m, "enabled\n");
- else
- seq_puts(m, "disabled\n");
+ seq_printf(m, "Enabled by kernel parameter: %s\n",
+ yesno(i915.enable_ips));
+
+ if (INTEL_INFO(dev)->gen >= 8) {
+ seq_puts(m, "Currently: unknown\n");
+ } else {
+ if (I915_READ(IPS_CTL) & IPS_ENABLE)
+ seq_puts(m, "Currently: enabled\n");
+ else
+ seq_puts(m, "Currently: disabled\n");
+ }
intel_runtime_pm_put(dev_priv);
@@ -1620,26 +1560,6 @@ out:
return ret;
}
-static int i915_gfxec(struct seq_file *m, void *unused)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- int ret;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
- intel_runtime_pm_get(dev_priv);
-
- seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
- intel_runtime_pm_put(dev_priv);
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
static int i915_opregion(struct seq_file *m, void *unused)
{
struct drm_info_node *node = m->private;
@@ -1677,9 +1597,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
#ifdef CONFIG_DRM_I915_FBDEV
struct drm_i915_private *dev_priv = dev->dev_private;
- int ret = mutex_lock_interruptible(&dev->mode_config.mutex);
- if (ret)
- return ret;
ifbdev = dev_priv->fbdev;
fb = to_intel_framebuffer(ifbdev->helper.fb);
@@ -1692,7 +1609,6 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
atomic_read(&fb->base.refcount.refcount));
describe_obj(m, fb->obj);
seq_putc(m, '\n');
- mutex_unlock(&dev->mode_config.mutex);
#endif
mutex_lock(&dev->mode_config.fb_lock);
@@ -1723,7 +1639,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
struct intel_context *ctx;
int ret, i;
- ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
@@ -1740,7 +1656,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
}
list_for_each_entry(ctx, &dev_priv->context_list, link) {
- if (ctx->obj == NULL)
+ if (ctx->legacy_hw_ctx.rcs_state == NULL)
continue;
seq_puts(m, "HW context ");
@@ -1749,11 +1665,11 @@ static int i915_context_status(struct seq_file *m, void *unused)
if (ring->default_context == ctx)
seq_printf(m, "(default context %s) ", ring->name);
- describe_obj(m, ctx->obj);
+ describe_obj(m, ctx->legacy_hw_ctx.rcs_state);
seq_putc(m, '\n');
}
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -1863,7 +1779,7 @@ static int per_file_ctx(int id, void *ptr, void *data)
if (i915_gem_context_is_default(ctx))
seq_puts(m, " default context:\n");
else
- seq_printf(m, " context %d:\n", ctx->id);
+ seq_printf(m, " context %d:\n", ctx->user_handle);
ppgtt->debug_dump(ppgtt, m);
return 0;
@@ -1976,17 +1892,25 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
intel_runtime_pm_get(dev_priv);
+ mutex_lock(&dev_priv->psr.lock);
seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
+ seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled));
+ seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active));
+ seq_printf(m, "Busy frontbuffer bits: 0x%03x\n",
+ dev_priv->psr.busy_frontbuffer_bits);
+ seq_printf(m, "Re-enable work scheduled: %s\n",
+ yesno(work_busy(&dev_priv->psr.work.work)));
enabled = HAS_PSR(dev) &&
I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
- seq_printf(m, "Enabled: %s\n", yesno(enabled));
+ seq_printf(m, "HW Enabled & Active bit: %s\n", yesno(enabled));
if (HAS_PSR(dev))
psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance_Counter: %u\n", psrperf);
+ mutex_unlock(&dev_priv->psr.lock);
intel_runtime_pm_put(dev_priv);
return 0;
@@ -2072,7 +1996,7 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy));
seq_printf(m, "IRQs disabled: %s\n",
- yesno(dev_priv->pm.irqs_disabled));
+ yesno(!intel_irqs_enabled(dev_priv)));
return 0;
}
@@ -2126,6 +2050,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
return "VGA";
case POWER_DOMAIN_AUDIO:
return "AUDIO";
+ case POWER_DOMAIN_PLLS:
+ return "PLLS";
case POWER_DOMAIN_INIT:
return "INIT";
default:
@@ -2223,9 +2149,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc)
struct drm_crtc *crtc = &intel_crtc->base;
struct intel_encoder *intel_encoder;
- seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
- crtc->primary->fb->base.id, crtc->x, crtc->y,
- crtc->primary->fb->width, crtc->primary->fb->height);
+ if (crtc->primary->fb)
+ seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n",
+ crtc->primary->fb->base.id, crtc->x, crtc->y,
+ crtc->primary->fb->width, crtc->primary->fb->height);
+ else
+ seq_puts(m, "\tprimary plane disabled\n");
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
intel_encoder_info(m, intel_crtc, intel_encoder);
}
@@ -2287,13 +2216,15 @@ static void intel_connector_info(struct seq_file *m,
seq_printf(m, "\tCEA rev: %d\n",
connector->display_info.cea_rev);
}
- if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
- intel_encoder->type == INTEL_OUTPUT_EDP)
- intel_dp_info(m, intel_connector);
- else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
- intel_hdmi_info(m, intel_connector);
- else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
- intel_lvds_info(m, intel_connector);
+ if (intel_encoder) {
+ if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+ intel_encoder->type == INTEL_OUTPUT_EDP)
+ intel_dp_info(m, intel_connector);
+ else if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+ intel_hdmi_info(m, intel_connector);
+ else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
+ intel_lvds_info(m, intel_connector);
+ }
seq_printf(m, "\tmodes:\n");
list_for_each_entry(mode, &connector->modes, head)
@@ -2347,17 +2278,17 @@ static int i915_display_info(struct seq_file *m, void *unused)
bool active;
int x, y;
- seq_printf(m, "CRTC %d: pipe: %c, active: %s\n",
+ seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n",
crtc->base.base.id, pipe_name(crtc->pipe),
- yesno(crtc->active));
+ yesno(crtc->active), crtc->config.pipe_src_w, crtc->config.pipe_src_h);
if (crtc->active) {
intel_crtc_info(m, crtc);
active = cursor_position(dev, crtc->pipe, &x, &y);
- seq_printf(m, "\tcursor visible? %s, position (%d, %d), addr 0x%08x, active? %s\n",
+ seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x, active? %s\n",
yesno(crtc->cursor_base),
- x, y, crtc->cursor_addr,
- yesno(active));
+ x, y, crtc->cursor_width, crtc->cursor_height,
+ crtc->cursor_addr, yesno(active));
}
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
@@ -2377,12 +2308,132 @@ static int i915_display_info(struct seq_file *m, void *unused)
return 0;
}
+static int i915_semaphore_status(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *ring;
+ int num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+ int i, j, ret;
+
+ if (!i915_semaphore_is_enabled(dev)) {
+ seq_puts(m, "Semaphores are disabled\n");
+ return 0;
+ }
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
+ intel_runtime_pm_get(dev_priv);
+
+ if (IS_BROADWELL(dev)) {
+ struct page *page;
+ uint64_t *seqno;
+
+ page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
+
+ seqno = (uint64_t *)kmap_atomic(page);
+ for_each_ring(ring, dev_priv, i) {
+ uint64_t offset;
+
+ seq_printf(m, "%s\n", ring->name);
+
+ seq_puts(m, " Last signal:");
+ for (j = 0; j < num_rings; j++) {
+ offset = i * I915_NUM_RINGS + j;
+ seq_printf(m, "0x%08llx (0x%02llx) ",
+ seqno[offset], offset * 8);
+ }
+ seq_putc(m, '\n');
+
+ seq_puts(m, " Last wait: ");
+ for (j = 0; j < num_rings; j++) {
+ offset = i + (j * I915_NUM_RINGS);
+ seq_printf(m, "0x%08llx (0x%02llx) ",
+ seqno[offset], offset * 8);
+ }
+ seq_putc(m, '\n');
+
+ }
+ kunmap_atomic(seqno);
+ } else {
+ seq_puts(m, " Last signal:");
+ for_each_ring(ring, dev_priv, i)
+ for (j = 0; j < num_rings; j++)
+ seq_printf(m, "0x%08x\n",
+ I915_READ(ring->semaphore.mbox.signal[j]));
+ seq_putc(m, '\n');
+ }
+
+ seq_puts(m, "\nSync seqno:\n");
+ for_each_ring(ring, dev_priv, i) {
+ for (j = 0; j < num_rings; j++) {
+ seq_printf(m, " 0x%08x ", ring->semaphore.sync_seqno[j]);
+ }
+ seq_putc(m, '\n');
+ }
+ seq_putc(m, '\n');
+
+ intel_runtime_pm_put(dev_priv);
+ mutex_unlock(&dev->struct_mutex);
+ return 0;
+}
+
+static int i915_shared_dplls_info(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ drm_modeset_lock_all(dev);
+ for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+ struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+
+ seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id);
+ seq_printf(m, " refcount: %i, active: %i, on: %s\n", pll->refcount,
+ pll->active, yesno(pll->on));
+ seq_printf(m, " tracked hardware state:\n");
+ seq_printf(m, " dpll: 0x%08x\n", pll->hw_state.dpll);
+ seq_printf(m, " dpll_md: 0x%08x\n", pll->hw_state.dpll_md);
+ seq_printf(m, " fp0: 0x%08x\n", pll->hw_state.fp0);
+ seq_printf(m, " fp1: 0x%08x\n", pll->hw_state.fp1);
+ seq_printf(m, " wrpll: 0x%08x\n", pll->hw_state.wrpll);
+ }
+ drm_modeset_unlock_all(dev);
+
+ return 0;
+}
+
struct pipe_crc_info {
const char *name;
struct drm_device *dev;
enum pipe pipe;
};
+static int i915_dp_mst_info(struct seq_file *m, void *unused)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct drm_encoder *encoder;
+ struct intel_encoder *intel_encoder;
+ struct intel_digital_port *intel_dig_port;
+ drm_modeset_lock_all(dev);
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ intel_encoder = to_intel_encoder(encoder);
+ if (intel_encoder->type != INTEL_OUTPUT_DISPLAYPORT)
+ continue;
+ intel_dig_port = enc_to_dig_port(encoder);
+ if (!intel_dig_port->dp.can_mst)
+ continue;
+
+ drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr);
+ }
+ drm_modeset_unlock_all(dev);
+ return 0;
+}
+
static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
{
struct pipe_crc_info *info = inode->i_private;
@@ -2849,7 +2900,60 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
return 0;
}
-static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
+static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc =
+ to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+
+ drm_modeset_lock_all(dev);
+ /*
+ * If we use the eDP transcoder we need to make sure that we don't
+ * bypass the pfit, since otherwise the pipe CRC source won't work. Only
+ * relevant on hsw with pipe A when using the always-on power well
+ * routing.
+ */
+ if (crtc->config.cpu_transcoder == TRANSCODER_EDP &&
+ !crtc->config.pch_pfit.enabled) {
+ crtc->config.pch_pfit.force_thru = true;
+
+ intel_display_power_get(dev_priv,
+ POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
+
+ dev_priv->display.crtc_disable(&crtc->base);
+ dev_priv->display.crtc_enable(&crtc->base);
+ }
+ drm_modeset_unlock_all(dev);
+}
+
+static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc =
+ to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+
+ drm_modeset_lock_all(dev);
+ /*
+ * If we use the eDP transcoder we need to make sure that we don't
+ * bypass the pfit, since otherwise the pipe CRC source won't work. Only
+ * relevant on hsw with pipe A when using the always-on power well
+ * routing.
+ */
+ if (crtc->config.pch_pfit.force_thru) {
+ crtc->config.pch_pfit.force_thru = false;
+
+ dev_priv->display.crtc_disable(&crtc->base);
+ dev_priv->display.crtc_enable(&crtc->base);
+
+ intel_display_power_put(dev_priv,
+ POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
+ }
+ drm_modeset_unlock_all(dev);
+}
+
+static int ivb_pipe_crc_ctl_reg(struct drm_device *dev,
+ enum pipe pipe,
+ enum intel_pipe_crc_source *source,
uint32_t *val)
{
if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
@@ -2863,6 +2967,9 @@ static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
break;
case INTEL_PIPE_CRC_SOURCE_PF:
+ if (IS_HASWELL(dev) && pipe == PIPE_A)
+ hsw_trans_edp_pipe_A_crc_wa(dev);
+
*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
break;
case INTEL_PIPE_CRC_SOURCE_NONE:
@@ -2895,11 +3002,11 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
else if (INTEL_INFO(dev)->gen < 5)
ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
else if (IS_VALLEYVIEW(dev))
- ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val);
+ ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
else if (IS_GEN5(dev) || IS_GEN6(dev))
ret = ilk_pipe_crc_ctl_reg(&source, &val);
else
- ret = ivb_pipe_crc_ctl_reg(&source, &val);
+ ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
if (ret != 0)
return ret;
@@ -2929,11 +3036,16 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
/* real source -> none transition */
if (source == INTEL_PIPE_CRC_SOURCE_NONE) {
struct intel_pipe_crc_entry *entries;
+ struct intel_crtc *crtc =
+ to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
pipe_name(pipe));
- intel_wait_for_vblank(dev, pipe);
+ drm_modeset_lock(&crtc->base.mutex, NULL);
+ if (crtc->active)
+ intel_wait_for_vblank(dev, pipe);
+ drm_modeset_unlock(&crtc->base.mutex);
spin_lock_irq(&pipe_crc->lock);
entries = pipe_crc->entries;
@@ -2946,6 +3058,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
g4x_undo_pipe_scramble_reset(dev, pipe);
else if (IS_VALLEYVIEW(dev))
vlv_undo_pipe_scramble_reset(dev, pipe);
+ else if (IS_HASWELL(dev) && pipe == PIPE_A)
+ hsw_undo_trans_edp_pipe_A_crc_wa(dev);
}
return 0;
@@ -3177,7 +3291,7 @@ static int pri_wm_latency_open(struct inode *inode, struct file *file)
{
struct drm_device *dev = inode->i_private;
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
return -ENODEV;
return single_open(file, pri_wm_latency_show, dev);
@@ -3187,7 +3301,7 @@ static int spr_wm_latency_open(struct inode *inode, struct file *file)
{
struct drm_device *dev = inode->i_private;
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
return -ENODEV;
return single_open(file, spr_wm_latency_show, dev);
@@ -3197,7 +3311,7 @@ static int cur_wm_latency_open(struct inode *inode, struct file *file)
{
struct drm_device *dev = inode->i_private;
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
return -ENODEV;
return single_open(file, cur_wm_latency_show, dev);
@@ -3506,7 +3620,7 @@ i915_max_freq_get(void *data, u64 *val)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+ if (INTEL_INFO(dev)->gen < 6)
return -ENODEV;
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3532,7 +3646,7 @@ i915_max_freq_set(void *data, u64 val)
u32 rp_state_cap, hw_max, hw_min;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+ if (INTEL_INFO(dev)->gen < 6)
return -ENODEV;
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3549,8 +3663,8 @@ i915_max_freq_set(void *data, u64 val)
if (IS_VALLEYVIEW(dev)) {
val = vlv_freq_opcode(dev_priv, val);
- hw_max = valleyview_rps_max_freq(dev_priv);
- hw_min = valleyview_rps_min_freq(dev_priv);
+ hw_max = dev_priv->rps.max_freq;
+ hw_min = dev_priv->rps.min_freq;
} else {
do_div(val, GT_FREQUENCY_MULTIPLIER);
@@ -3587,7 +3701,7 @@ i915_min_freq_get(void *data, u64 *val)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+ if (INTEL_INFO(dev)->gen < 6)
return -ENODEV;
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3613,7 +3727,7 @@ i915_min_freq_set(void *data, u64 val)
u32 rp_state_cap, hw_max, hw_min;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+ if (INTEL_INFO(dev)->gen < 6)
return -ENODEV;
flush_delayed_work(&dev_priv->rps.delayed_resume_work);
@@ -3630,8 +3744,8 @@ i915_min_freq_set(void *data, u64 val)
if (IS_VALLEYVIEW(dev)) {
val = vlv_freq_opcode(dev_priv, val);
- hw_max = valleyview_rps_max_freq(dev_priv);
- hw_min = valleyview_rps_min_freq(dev_priv);
+ hw_max = dev_priv->rps.max_freq;
+ hw_min = dev_priv->rps.min_freq;
} else {
do_div(val, GT_FREQUENCY_MULTIPLIER);
@@ -3799,14 +3913,10 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
- {"i915_rstdby_delays", i915_rstdby_delays, 0},
{"i915_frequency_info", i915_frequency_info, 0},
- {"i915_delayfreq_table", i915_delayfreq_table, 0},
- {"i915_inttoext_table", i915_inttoext_table, 0},
{"i915_drpc_info", i915_drpc_info, 0},
{"i915_emon_status", i915_emon_status, 0},
{"i915_ring_freq_table", i915_ring_freq_table, 0},
- {"i915_gfxec", i915_gfxec, 0},
{"i915_fbc_status", i915_fbc_status, 0},
{"i915_ips_status", i915_ips_status, 0},
{"i915_sr_status", i915_sr_status, 0},
@@ -3823,6 +3933,9 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_pc8_status", i915_pc8_status, 0},
{"i915_power_domain_info", i915_power_domain_info, 0},
{"i915_display_info", i915_display_info, 0},
+ {"i915_semaphore_status", i915_semaphore_status, 0},
+ {"i915_shared_dplls_info", i915_shared_dplls_info, 0},
+ {"i915_dp_mst_info", i915_dp_mst_info, 0},
};
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index d44344140627..2e7f03ad5ee2 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -138,7 +138,7 @@ static void i915_free_hws(struct drm_device *dev)
I915_WRITE(HWS_PGA, 0x1ffff000);
}
-void i915_kernel_lost_context(struct drm_device * dev)
+void i915_kernel_lost_context(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv;
@@ -166,7 +166,7 @@ void i915_kernel_lost_context(struct drm_device * dev)
master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
-static int i915_dma_cleanup(struct drm_device * dev)
+static int i915_dma_cleanup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
@@ -190,7 +190,7 @@ static int i915_dma_cleanup(struct drm_device * dev)
return 0;
}
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
+static int i915_initialize(struct drm_device *dev, drm_i915_init_t *init)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -235,7 +235,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
return 0;
}
-static int i915_dma_resume(struct drm_device * dev)
+static int i915_dma_resume(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = LP_RING(dev_priv);
@@ -359,7 +359,7 @@ static int validate_cmd(int cmd)
return 0;
}
-static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
+static int i915_emit_cmds(struct drm_device *dev, int *buffer, int dwords)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int i, ret;
@@ -369,6 +369,7 @@ static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
for (i = 0; i < dwords;) {
int sz = validate_cmd(buffer[i]);
+
if (sz == 0 || i + sz > dwords)
return -EINVAL;
i += sz;
@@ -453,7 +454,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
}
}
-static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+static int i915_dispatch_cmdbuffer(struct drm_device *dev,
drm_i915_cmdbuffer_t *cmd,
struct drm_clip_rect *cliprects,
void *cmdbuf)
@@ -487,8 +488,8 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
return 0;
}
-static int i915_dispatch_batchbuffer(struct drm_device * dev,
- drm_i915_batchbuffer_t * batch,
+static int i915_dispatch_batchbuffer(struct drm_device *dev,
+ drm_i915_batchbuffer_t *batch,
struct drm_clip_rect *cliprects)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -549,7 +550,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
return 0;
}
-static int i915_dispatch_flip(struct drm_device * dev)
+static int i915_dispatch_flip(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv =
@@ -755,7 +756,7 @@ fail_batch_free:
return ret;
}
-static int i915_emit_irq(struct drm_device * dev)
+static int i915_emit_irq(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -781,7 +782,7 @@ static int i915_emit_irq(struct drm_device * dev)
return dev_priv->dri1.counter;
}
-static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device *dev, int irq_nr)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
@@ -1266,6 +1267,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
{
struct drm_device *dev = pci_get_drvdata(pdev);
pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+
if (state == VGA_SWITCHEROO_ON) {
pr_info("switched on\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -1338,6 +1340,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret)
goto cleanup_gem_stolen;
+ dev_priv->pm._irqs_disabled = false;
+
/* Important: The output setup functions called by modeset_init need
* working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev);
@@ -1375,9 +1379,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
*/
intel_fbdev_initial_config(dev);
- /* Only enable hotplug handling once the fbdev is fully set up. */
- dev_priv->enable_hotplug_processing = true;
-
drm_kms_helper_poll_init(dev);
return 0;
@@ -1425,15 +1426,16 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
}
#if IS_ENABLED(CONFIG_FB)
-static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
+static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
{
struct apertures_struct *ap;
struct pci_dev *pdev = dev_priv->dev->pdev;
bool primary;
+ int ret;
ap = alloc_apertures(1);
if (!ap)
- return;
+ return -ENOMEM;
ap->ranges[0].base = dev_priv->gtt.mappable_base;
ap->ranges[0].size = dev_priv->gtt.mappable_end;
@@ -1441,13 +1443,16 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
primary =
pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
- remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
+ ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
kfree(ap);
+
+ return ret;
}
#else
-static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
+static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
{
+ return 0;
}
#endif
@@ -1492,10 +1497,11 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
#define SEP_EMPTY
#define PRINT_FLAG(name) info->name ? #name "," : ""
#define SEP_COMMA ,
- DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
+ DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
info->gen,
dev_priv->dev->pdev->device,
+ dev_priv->dev->pdev->revision,
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
#undef PRINT_S
#undef SEP_EMPTY
@@ -1594,7 +1600,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (dev_priv == NULL)
return -ENOMEM;
- dev->dev_private = (void *)dev_priv;
+ dev->dev_private = dev_priv;
dev_priv->dev = dev;
/* copy initial configuration to dev_priv->info */
@@ -1606,6 +1612,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
spin_lock_init(&dev_priv->backlight_lock);
spin_lock_init(&dev_priv->uncore.lock);
spin_lock_init(&dev_priv->mm.object_stat_lock);
+ spin_lock_init(&dev_priv->mmio_flip_lock);
mutex_init(&dev_priv->dpio_lock);
mutex_init(&dev_priv->modeset_restore_lock);
@@ -1664,7 +1671,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto out_gtt;
}
- i915_kick_out_firmware_fb(dev_priv);
+ ret = i915_kick_out_firmware_fb(dev_priv);
+ if (ret) {
+ DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
+ goto out_gtt;
+ }
}
pci_set_master(dev->pdev);
@@ -1717,6 +1728,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto out_mtrrfree;
}
+ dev_priv->dp_wq = alloc_ordered_workqueue("i915-dp", 0);
+ if (dev_priv->dp_wq == NULL) {
+ DRM_ERROR("Failed to create our dp workqueue.\n");
+ ret = -ENOMEM;
+ goto out_freewq;
+ }
+
intel_irq_init(dev);
intel_uncore_sanitize(dev);
@@ -1792,6 +1810,8 @@ out_gem_unload:
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
pm_qos_remove_request(&dev_priv->pm_qos);
+ destroy_workqueue(dev_priv->dp_wq);
+out_freewq:
destroy_workqueue(dev_priv->wq);
out_mtrrfree:
arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1892,6 +1912,7 @@ int i915_driver_unload(struct drm_device *dev)
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
+ destroy_workqueue(dev_priv->dp_wq);
destroy_workqueue(dev_priv->wq);
pm_qos_remove_request(&dev_priv->pm_qos);
@@ -1933,7 +1954,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
* and DMA structures, since the kernel won't be using them, and clea
* up any GEM state.
*/
-void i915_driver_lastclose(struct drm_device * dev)
+void i915_driver_lastclose(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1954,11 +1975,11 @@ void i915_driver_lastclose(struct drm_device * dev)
i915_dma_cleanup(dev);
}
-void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
{
mutex_lock(&dev->struct_mutex);
- i915_gem_context_close(dev, file_priv);
- i915_gem_release(dev, file_priv);
+ i915_gem_context_close(dev, file);
+ i915_gem_release(dev, file);
mutex_unlock(&dev->struct_mutex);
}
@@ -2031,7 +2052,7 @@ int i915_max_ioctl = ARRAY_SIZE(i915_ioctls);
* manage the gtt, we need to claim that all intel devices are agp. For
* otherwise the drm core refuses to initialize the agp support code.
*/
-int i915_driver_device_is_agp(struct drm_device * dev)
+int i915_driver_device_is_agp(struct drm_device *dev)
{
return 1;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 651e65e051c0..ec96f9a9724c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -28,6 +28,7 @@
*/
#include <linux/device.h>
+#include <linux/acpi.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
@@ -46,8 +47,6 @@ static struct drm_driver driver;
PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \
.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
TRANSCODER_C_OFFSET, TRANSCODER_EDP_OFFSET }, \
- .dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET }, \
- .dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET }, \
.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET }
#define GEN_CHV_PIPEOFFSETS \
@@ -55,10 +54,6 @@ static struct drm_driver driver;
CHV_PIPE_C_OFFSET }, \
.trans_offsets = { TRANSCODER_A_OFFSET, TRANSCODER_B_OFFSET, \
CHV_TRANSCODER_C_OFFSET, }, \
- .dpll_offsets = { DPLL_A_OFFSET, DPLL_B_OFFSET, \
- CHV_DPLL_C_OFFSET }, \
- .dpll_md_offsets = { DPLL_A_MD_OFFSET, DPLL_B_MD_OFFSET, \
- CHV_DPLL_C_MD_OFFSET }, \
.palette_offsets = { PALETTE_A_OFFSET, PALETTE_B_OFFSET, \
CHV_PALETTE_C_OFFSET }
@@ -308,6 +303,7 @@ static const struct intel_device_info intel_broadwell_d_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -319,6 +315,7 @@ static const struct intel_device_info intel_broadwell_m_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -330,6 +327,7 @@ static const struct intel_device_info intel_broadwell_gt3d_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -341,6 +339,7 @@ static const struct intel_device_info intel_broadwell_gt3m_info = {
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
.has_llc = 1,
.has_ddi = 1,
+ .has_fpga_dbg = 1,
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
@@ -499,8 +498,7 @@ static int i915_drm_freeze(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
-
- intel_runtime_pm_get(dev_priv);
+ pci_power_t opregion_target_state;
/* ignore lid events during suspend */
mutex_lock(&dev_priv->modeset_restore_lock);
@@ -526,21 +524,23 @@ static int i915_drm_freeze(struct drm_device *dev)
return error;
}
- drm_irq_uninstall(dev);
- dev_priv->enable_hotplug_processing = false;
-
- intel_disable_gt_powersave(dev);
-
/*
* Disable CRTCs directly since we want to preserve sw state
- * for _thaw.
+ * for _thaw. Also, power gate the CRTC power wells.
*/
drm_modeset_lock_all(dev);
- for_each_crtc(dev, crtc) {
- dev_priv->display.crtc_disable(crtc);
- }
+ for_each_crtc(dev, crtc)
+ intel_crtc_control(crtc, false);
drm_modeset_unlock_all(dev);
+ intel_dp_mst_suspend(dev);
+
+ flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+ intel_runtime_pm_disable_interrupts(dev);
+
+ intel_suspend_gt_powersave(dev);
+
intel_modeset_suspend_hw(dev);
}
@@ -548,8 +548,15 @@ static int i915_drm_freeze(struct drm_device *dev)
i915_save_state(dev);
+ opregion_target_state = PCI_D3cold;
+#if IS_ENABLED(CONFIG_ACPI_SLEEP)
+ if (acpi_target_system_state() < ACPI_STATE_S3)
+ opregion_target_state = PCI_D1;
+#endif
+ intel_opregion_notify_adapter(dev, opregion_target_state);
+
+ intel_uncore_forcewake_reset(dev, false);
intel_opregion_fini(dev);
- intel_uncore_fini(dev);
console_lock();
intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
@@ -557,6 +564,8 @@ static int i915_drm_freeze(struct drm_device *dev)
dev_priv->suspend_count++;
+ intel_display_set_init_power(dev_priv, false);
+
return 0;
}
@@ -606,7 +615,10 @@ static int i915_drm_thaw_early(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- intel_uncore_early_sanitize(dev);
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+ hsw_disable_pc8(dev_priv);
+
+ intel_uncore_early_sanitize(dev, true);
intel_uncore_sanitize(dev);
intel_power_domains_init_hw(dev_priv);
@@ -639,11 +651,19 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
}
mutex_unlock(&dev->struct_mutex);
- /* We need working interrupts for modeset enabling ... */
- drm_irq_install(dev, dev->pdev->irq);
+ intel_runtime_pm_restore_interrupts(dev);
intel_modeset_init_hw(dev);
+ {
+ unsigned long irqflags;
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ if (dev_priv->display.hpd_irq_setup)
+ dev_priv->display.hpd_irq_setup(dev);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+ }
+
+ intel_dp_mst_resume(dev);
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev, true);
drm_modeset_unlock_all(dev);
@@ -655,7 +675,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
* notifications.
* */
intel_hpd_init(dev);
- dev_priv->enable_hotplug_processing = true;
/* Config may have changed between suspend and resume */
drm_helper_hpd_irq_event(dev);
}
@@ -678,7 +697,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
dev_priv->modeset_restore = MODESET_DONE;
mutex_unlock(&dev_priv->modeset_restore_lock);
- intel_runtime_pm_put(dev_priv);
+ intel_opregion_notify_adapter(dev, PCI_D0);
+
return 0;
}
@@ -887,6 +907,7 @@ static int i915_pm_suspend_late(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct drm_i915_private *dev_priv = drm_dev->dev_private;
/*
* We have a suspedn ordering issue with the snd-hda driver also
@@ -900,6 +921,9 @@ static int i915_pm_suspend_late(struct device *dev)
if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
+ if (IS_HASWELL(drm_dev) || IS_BROADWELL(drm_dev))
+ hsw_enable_pc8(dev_priv);
+
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 374f964323ad..4412f6a4383b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -53,7 +53,7 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20080730"
+#define DRIVER_DATE "20140725"
enum pipe {
INVALID_PIPE = -1,
@@ -129,6 +129,7 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_OTHER,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO,
+ POWER_DOMAIN_PLLS,
POWER_DOMAIN_INIT,
POWER_DOMAIN_NUM,
@@ -178,14 +179,20 @@ enum hpd_pin {
list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
if ((intel_connector)->base.encoder == (__encoder))
+#define for_each_power_domain(domain, mask) \
+ for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
+ if ((1 << (domain)) & (mask))
+
struct drm_i915_private;
struct i915_mmu_object;
enum intel_dpll_id {
DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
/* real shared dpll ids must be >= 0 */
- DPLL_ID_PCH_PLL_A,
- DPLL_ID_PCH_PLL_B,
+ DPLL_ID_PCH_PLL_A = 0,
+ DPLL_ID_PCH_PLL_B = 1,
+ DPLL_ID_WRPLL1 = 0,
+ DPLL_ID_WRPLL2 = 1,
};
#define I915_NUM_PLLS 2
@@ -194,6 +201,7 @@ struct intel_dpll_hw_state {
uint32_t dpll_md;
uint32_t fp0;
uint32_t fp1;
+ uint32_t wrpll;
};
struct intel_shared_dpll {
@@ -204,6 +212,8 @@ struct intel_shared_dpll {
/* should match the index in the dev_priv->shared_dplls array */
enum intel_dpll_id id;
struct intel_dpll_hw_state hw_state;
+ /* The mode_set hook is optional and should be used together with the
+ * intel_prepare_shared_dpll function. */
void (*mode_set)(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll);
void (*enable)(struct drm_i915_private *dev_priv,
@@ -228,12 +238,6 @@ void intel_link_compute_m_n(int bpp, int nlanes,
int pixel_clock, int link_clock,
struct intel_link_m_n *m_n);
-struct intel_ddi_plls {
- int spll_refcount;
- int wrpll1_refcount;
- int wrpll2_refcount;
-};
-
/* Interface history:
*
* 1.1: Original.
@@ -310,6 +314,7 @@ struct drm_i915_error_state {
u32 eir;
u32 pgtbl_er;
u32 ier;
+ u32 gtier[4];
u32 ccid;
u32 derrmr;
u32 forcewake;
@@ -324,6 +329,7 @@ struct drm_i915_error_state {
u64 fence[I915_MAX_NUM_FENCES];
struct intel_overlay_error_state *overlay;
struct intel_display_error_state *display;
+ struct drm_i915_error_object *semaphore_obj;
struct drm_i915_error_ring {
bool valid;
@@ -435,8 +441,8 @@ struct drm_i915_display_funcs {
void (*update_wm)(struct drm_crtc *crtc);
void (*update_sprite_wm)(struct drm_plane *plane,
struct drm_crtc *crtc,
- uint32_t sprite_width, int pixel_size,
- bool enable, bool scaled);
+ uint32_t sprite_width, uint32_t sprite_height,
+ int pixel_size, bool enable, bool scaled);
void (*modeset_global_resources)(struct drm_device *dev);
/* Returns the active state of the crtc, and if the crtc is active,
* fills out the pipe-config with the hw state. */
@@ -552,8 +558,6 @@ struct intel_device_info {
/* Register offsets for the various display pipes and transcoders */
int pipe_offsets[I915_MAX_TRANSCODERS];
int trans_offsets[I915_MAX_TRANSCODERS];
- int dpll_offsets[I915_MAX_PIPES];
- int dpll_md_offsets[I915_MAX_PIPES];
int palette_offsets[I915_MAX_PIPES];
int cursor_offsets[I915_MAX_PIPES];
};
@@ -586,28 +590,48 @@ struct i915_ctx_hang_stats {
};
/* This must match up with the value previously used for execbuf2.rsvd1. */
-#define DEFAULT_CONTEXT_ID 0
+#define DEFAULT_CONTEXT_HANDLE 0
+/**
+ * struct intel_context - as the name implies, represents a context.
+ * @ref: reference count.
+ * @user_handle: userspace tracking identity for this context.
+ * @remap_slice: l3 row remapping information.
+ * @file_priv: filp associated with this context (NULL for global default
+ * context).
+ * @hang_stats: information about the role of this context in possible GPU
+ * hangs.
+ * @vm: virtual memory space used by this context.
+ * @legacy_hw_ctx: render context backing object and whether it is correctly
+ * initialized (legacy ring submission mechanism only).
+ * @link: link in the global list of contexts.
+ *
+ * Contexts are memory images used by the hardware to store copies of their
+ * internal state.
+ */
struct intel_context {
struct kref ref;
- int id;
- bool is_initialized;
+ int user_handle;
uint8_t remap_slice;
struct drm_i915_file_private *file_priv;
- struct intel_engine_cs *last_ring;
- struct drm_i915_gem_object *obj;
struct i915_ctx_hang_stats hang_stats;
struct i915_address_space *vm;
+ struct {
+ struct drm_i915_gem_object *rcs_state;
+ bool initialized;
+ } legacy_hw_ctx;
+
struct list_head link;
};
struct i915_fbc {
unsigned long size;
+ unsigned threshold;
unsigned int fb_id;
enum plane plane;
int y;
- struct drm_mm_node *compressed_fb;
+ struct drm_mm_node compressed_fb;
struct drm_mm_node *compressed_llb;
struct intel_fbc_work {
@@ -635,9 +659,15 @@ struct i915_drrs {
struct intel_connector *connector;
};
+struct intel_dp;
struct i915_psr {
+ struct mutex lock;
bool sink_support;
bool source_ok;
+ struct intel_dp *enabled;
+ bool active;
+ struct delayed_work work;
+ unsigned busy_frontbuffer_bits;
};
enum intel_pch {
@@ -880,6 +910,12 @@ struct vlv_s0ix_state {
u32 clock_gate_dis2;
};
+struct intel_rps_ei {
+ u32 cz_clock;
+ u32 render_c0;
+ u32 media_c0;
+};
+
struct intel_gen6_power_mgmt {
/* work and pm_iir are protected by dev_priv->irq_lock */
struct work_struct work;
@@ -903,6 +939,9 @@ struct intel_gen6_power_mgmt {
u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */
u8 rp1_freq; /* "less than" RP0 power/freqency */
u8 rp0_freq; /* Non-overclocked max frequency. */
+ u32 cz_freq;
+
+ u32 ei_interrupt_count;
int last_adj;
enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
@@ -910,6 +949,9 @@ struct intel_gen6_power_mgmt {
bool enabled;
struct delayed_work delayed_resume_work;
+ /* manual wa residency calculations */
+ struct intel_rps_ei up_ei, down_ei;
+
/*
* Protects RPS/RC6 register access and PCU communication.
* Must be taken after struct_mutex if nested.
@@ -931,7 +973,7 @@ struct intel_ilk_power_mgmt {
unsigned long last_time1;
unsigned long chipset_power;
u64 last_count2;
- struct timespec last_time2;
+ u64 last_time2;
unsigned long gfx_power;
u8 corr;
@@ -1230,6 +1272,7 @@ struct intel_vbt_data {
u16 pwm_freq_hz;
bool present;
bool active_low_pwm;
+ u8 min_brightness; /* min_brightness/255 of max */
} backlight;
/* MIPI DSI */
@@ -1299,7 +1342,7 @@ struct ilk_wm_values {
*/
struct i915_runtime_pm {
bool suspended;
- bool irqs_disabled;
+ bool _irqs_disabled;
};
enum intel_pipe_crc_source {
@@ -1332,6 +1375,17 @@ struct intel_pipe_crc {
wait_queue_head_t wq;
};
+struct i915_frontbuffer_tracking {
+ struct mutex lock;
+
+ /*
+ * Tracking bits for delayed frontbuffer flushing du to gpu activity or
+ * scheduled flips.
+ */
+ unsigned busy_bits;
+ unsigned flip_bits;
+};
+
struct drm_i915_private {
struct drm_device *dev;
struct kmem_cache *slab;
@@ -1363,6 +1417,7 @@ struct drm_i915_private {
struct pci_dev *bridge_dev;
struct intel_engine_cs ring[I915_NUM_RINGS];
+ struct drm_i915_gem_object *semaphore_obj;
uint32_t last_seqno, next_seqno;
drm_dma_handle_t *status_page_dmah;
@@ -1371,6 +1426,9 @@ struct drm_i915_private {
/* protects the irq masks */
spinlock_t irq_lock;
+ /* protects the mmio flip data */
+ spinlock_t mmio_flip_lock;
+
bool display_irqs_enabled;
/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
@@ -1390,7 +1448,6 @@ struct drm_i915_private {
u32 pipestat_irq_mask[I915_MAX_PIPES];
struct work_struct hotplug_work;
- bool enable_hotplug_processing;
struct {
unsigned long hpd_last_jiffies;
int hpd_cnt;
@@ -1467,7 +1524,6 @@ struct drm_i915_private {
int num_shared_dpll;
struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
- struct intel_ddi_plls ddi_plls;
int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
/* Reclocking support */
@@ -1475,6 +1531,9 @@ struct drm_i915_private {
bool lvds_downclock_avail;
/* indicates the reduced downclock for LVDS*/
int lvds_downclock;
+
+ struct i915_frontbuffer_tracking fb_tracking;
+
u16 orig_clock;
bool mchbar_need_disable;
@@ -1541,6 +1600,20 @@ struct drm_i915_private {
struct i915_runtime_pm pm;
+ struct intel_digital_port *hpd_irq_port[I915_MAX_PORTS];
+ u32 long_hpd_port_mask;
+ u32 short_hpd_port_mask;
+ struct work_struct dig_port_work;
+
+ /*
+ * if we get a HPD irq from DP and a HPD irq from non-DP
+ * the non-DP HPD could block the workqueue on a mode config
+ * mutex getting, that userspace may have taken. However
+ * userspace is waiting on the DP workqueue to run which is
+ * blocked behind the non-DP one.
+ */
+ struct workqueue_struct *dp_wq;
+
/* Old dri1 support infrastructure, beware the dragons ya fools entering
* here! */
struct i915_dri1_state dri1;
@@ -1592,6 +1665,28 @@ struct drm_i915_gem_object_ops {
void (*release)(struct drm_i915_gem_object *);
};
+/*
+ * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is
+ * considered to be the frontbuffer for the given plane interface-vise. This
+ * doesn't mean that the hw necessarily already scans it out, but that any
+ * rendering (by the cpu or gpu) will land in the frontbuffer eventually.
+ *
+ * We have one bit per pipe and per scanout plane type.
+ */
+#define INTEL_FRONTBUFFER_BITS_PER_PIPE 4
+#define INTEL_FRONTBUFFER_BITS \
+ (INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES)
+#define INTEL_FRONTBUFFER_PRIMARY(pipe) \
+ (1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
+#define INTEL_FRONTBUFFER_CURSOR(pipe) \
+ (1 << (1 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_SPRITE(pipe) \
+ (1 << (2 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_OVERLAY(pipe) \
+ (1 << (3 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))))
+#define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
+ (0xf << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
+
struct drm_i915_gem_object {
struct drm_gem_object base;
@@ -1662,6 +1757,12 @@ struct drm_i915_gem_object {
unsigned int pin_display:1;
/*
+ * Is the object to be mapped as read-only to the GPU
+ * Only honoured if hardware has relevant pte bit
+ */
+ unsigned long gt_ro:1;
+
+ /*
* Is the GPU currently using a fence to access this buffer,
*/
unsigned int pending_fenced_gpu_access:1;
@@ -1673,6 +1774,8 @@ struct drm_i915_gem_object {
unsigned int has_global_gtt_mapping:1;
unsigned int has_dma_mapping:1;
+ unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;
+
struct sg_table *pages;
int pages_pin_count;
@@ -1719,6 +1822,10 @@ struct drm_i915_gem_object {
};
#define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
+void i915_gem_track_fb(struct drm_i915_gem_object *old,
+ struct drm_i915_gem_object *new,
+ unsigned frontbuffer_bits);
+
/**
* Request queue structure.
*
@@ -1940,10 +2047,8 @@ struct drm_i915_cmd_table {
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6)
-#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6 && \
- (!IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
-#define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 \
- && !IS_GEN8(dev))
+#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >= 6)
+#define HAS_PPGTT(dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))
#define USES_PPGTT(dev) intel_enable_ppgtt(dev, false)
#define USES_FULL_PPGTT(dev) intel_enable_ppgtt(dev, true)
@@ -1998,6 +2103,8 @@ struct drm_i915_cmd_table {
#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
+#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
+
/* DPF == dynamic parity feature */
#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
@@ -2040,6 +2147,8 @@ struct i915_params {
bool reset;
bool disable_display;
bool disable_vtd_wa;
+ int use_mmio_flip;
+ bool mmio_debug;
};
extern struct i915_params i915 __read_mostly;
@@ -2048,12 +2157,12 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev);
extern void i915_kernel_lost_context(struct drm_device * dev);
extern int i915_driver_load(struct drm_device *, unsigned long flags);
extern int i915_driver_unload(struct drm_device *);
-extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
extern void i915_driver_lastclose(struct drm_device * dev);
extern void i915_driver_preclose(struct drm_device *dev,
- struct drm_file *file_priv);
+ struct drm_file *file);
extern void i915_driver_postclose(struct drm_device *dev,
- struct drm_file *file_priv);
+ struct drm_file *file);
extern int i915_driver_device_is_agp(struct drm_device * dev);
#ifdef CONFIG_COMPAT
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
@@ -2084,10 +2193,12 @@ extern void intel_irq_init(struct drm_device *dev);
extern void intel_hpd_init(struct drm_device *dev);
extern void intel_uncore_sanitize(struct drm_device *dev);
-extern void intel_uncore_early_sanitize(struct drm_device *dev);
+extern void intel_uncore_early_sanitize(struct drm_device *dev,
+ bool restore_forcewake);
extern void intel_uncore_init(struct drm_device *dev);
extern void intel_uncore_check_errors(struct drm_device *dev);
extern void intel_uncore_fini(struct drm_device *dev);
+extern void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore);
void
i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
@@ -2235,6 +2346,8 @@ bool i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_requests_ring(struct intel_engine_cs *ring);
int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
bool interruptible);
+int __must_check i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno);
+
static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
{
return unlikely(atomic_read(&error->reset_counter)
@@ -2404,7 +2517,7 @@ static inline void i915_gem_context_unreference(struct intel_context *ctx)
static inline bool i915_gem_context_is_default(const struct intel_context *c)
{
- return c->id == DEFAULT_CONTEXT_ID;
+ return c->user_handle == DEFAULT_CONTEXT_HANDLE;
}
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -2435,7 +2548,7 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev)
/* i915_gem_stolen.c */
int i915_gem_init_stolen(struct drm_device *dev);
-int i915_gem_stolen_setup_compression(struct drm_device *dev, int size);
+int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp);
void i915_gem_stolen_cleanup_compression(struct drm_device *dev);
void i915_gem_cleanup_stolen(struct drm_device *dev);
struct drm_i915_gem_object *
@@ -2445,7 +2558,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
u32 stolen_offset,
u32 gtt_offset,
u32 size);
-void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
/* i915_gem_tiling.c */
static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
@@ -2593,8 +2705,8 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void intel_init_pch_refclk(struct drm_device *dev);
extern void gen6_set_rps(struct drm_device *dev, u8 val);
extern void valleyview_set_rps(struct drm_device *dev, u8 val);
-extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv);
-extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv);
+extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
+ bool enable);
extern void intel_detect_pch(struct drm_device *dev);
extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
extern int intel_enable_rc6(const struct drm_device *dev);
@@ -2605,6 +2717,8 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+void intel_notify_mmio_flip(struct intel_engine_cs *ring);
+
/* overlay */
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
@@ -2700,10 +2814,10 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
{
- if (HAS_PCH_SPLIT(dev))
- return CPU_VGACNTRL;
- else if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev))
return VLV_VGACNTRL;
+ else if (INTEL_INFO(dev)->gen >= 5)
+ return CPU_VGACNTRL;
else
return VGACNTRL;
}
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d893e4da5dce..ba7f5c6bb50d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1095,7 +1095,7 @@ i915_gem_check_wedge(struct i915_gpu_error *error,
* Compare seqno against outstanding lazy request. Emit a request if they are
* equal.
*/
-static int
+int
i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno)
{
int ret;
@@ -1149,26 +1149,26 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv)
static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
unsigned reset_counter,
bool interruptible,
- struct timespec *timeout,
+ s64 *timeout,
struct drm_i915_file_private *file_priv)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
const bool irq_test_in_progress =
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
- struct timespec before, now;
DEFINE_WAIT(wait);
unsigned long timeout_expire;
+ s64 before, now;
int ret;
- WARN(dev_priv->pm.irqs_disabled, "IRQs disabled\n");
+ WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
return 0;
- timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
+ timeout_expire = timeout ? jiffies + nsecs_to_jiffies((u64)*timeout) : 0;
- if (INTEL_INFO(dev)->gen >= 6 && can_wait_boost(file_priv)) {
+ if (INTEL_INFO(dev)->gen >= 6 && ring->id == RCS && can_wait_boost(file_priv)) {
gen6_rps_boost(dev_priv);
if (file_priv)
mod_delayed_work(dev_priv->wq,
@@ -1181,7 +1181,7 @@ static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
/* Record current time in case interrupted by signal, or wedged */
trace_i915_gem_request_wait_begin(ring, seqno);
- getrawmonotonic(&before);
+ before = ktime_get_raw_ns();
for (;;) {
struct timer_list timer;
@@ -1230,7 +1230,7 @@ static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
destroy_timer_on_stack(&timer);
}
}
- getrawmonotonic(&now);
+ now = ktime_get_raw_ns();
trace_i915_gem_request_wait_end(ring, seqno);
if (!irq_test_in_progress)
@@ -1239,10 +1239,9 @@ static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
finish_wait(&ring->irq_queue, &wait);
if (timeout) {
- struct timespec sleep_time = timespec_sub(now, before);
- *timeout = timespec_sub(*timeout, sleep_time);
- if (!timespec_valid(timeout)) /* i.e. negative time remains */
- set_normalized_timespec(timeout, 0, 0);
+ s64 tres = *timeout - (now - before);
+
+ *timeout = tres < 0 ? 0 : tres;
}
return ret;
@@ -1561,14 +1560,29 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (ret)
goto unpin;
- obj->fault_mappable = true;
-
+ /* Finally, remap it using the new GTT offset */
pfn = dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj);
pfn >>= PAGE_SHIFT;
- pfn += page_offset;
- /* Finally, remap it using the new GTT offset */
- ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+ if (!obj->fault_mappable) {
+ unsigned long size = min_t(unsigned long,
+ vma->vm_end - vma->vm_start,
+ obj->base.size);
+ int i;
+
+ for (i = 0; i < size >> PAGE_SHIFT; i++) {
+ ret = vm_insert_pfn(vma,
+ (unsigned long)vma->vm_start + i * PAGE_SIZE,
+ pfn + i);
+ if (ret)
+ break;
+ }
+
+ obj->fault_mappable = true;
+ } else
+ ret = vm_insert_pfn(vma,
+ (unsigned long)vmf->virtual_address,
+ pfn + page_offset);
unpin:
i915_gem_object_ggtt_unpin(obj);
unlock:
@@ -2052,16 +2066,10 @@ 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_NO_KSWAPD);
- gfp |= __GFP_IO | __GFP_WAIT;
-
i915_gem_shrink_all(dev_priv);
- page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+ page = shmem_read_mapping_page(mapping, i);
if (IS_ERR(page))
goto err_pages;
-
- gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
- gfp &= ~(__GFP_IO | __GFP_WAIT);
}
#ifdef CONFIG_SWIOTLB
if (swiotlb_nr_tbl()) {
@@ -2210,6 +2218,8 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
list_move_tail(&vma->mm_list, &vm->inactive_list);
}
+ intel_fb_obj_flush(obj, true);
+
list_del_init(&obj->ring_list);
obj->ring = NULL;
@@ -2319,7 +2329,7 @@ int __i915_add_request(struct intel_engine_cs *ring,
u32 request_ring_position, request_start;
int ret;
- request_start = intel_ring_get_tail(ring);
+ request_start = intel_ring_get_tail(ring->buffer);
/*
* Emit any outstanding flushes - execbuf can fail to emit the flush
* after having emitted the batchbuffer command. Hence we need to fix
@@ -2340,7 +2350,7 @@ int __i915_add_request(struct intel_engine_cs *ring,
* GPU processing the request, we never over-estimate the
* position of the head.
*/
- request_ring_position = intel_ring_get_tail(ring);
+ request_ring_position = intel_ring_get_tail(ring->buffer);
ret = ring->add_request(ring);
if (ret)
@@ -2746,16 +2756,10 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
struct drm_i915_gem_wait *args = data;
struct drm_i915_gem_object *obj;
struct intel_engine_cs *ring = NULL;
- struct timespec timeout_stack, *timeout = NULL;
unsigned reset_counter;
u32 seqno = 0;
int ret = 0;
- if (args->timeout_ns >= 0) {
- timeout_stack = ns_to_timespec(args->timeout_ns);
- timeout = &timeout_stack;
- }
-
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
@@ -2780,9 +2784,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
goto out;
/* Do this after OLR check to make sure we make forward progress polling
- * on this IOCTL with a 0 timeout (like busy ioctl)
+ * on this IOCTL with a timeout <=0 (like busy ioctl)
*/
- if (!args->timeout_ns) {
+ if (args->timeout_ns <= 0) {
ret = -ETIME;
goto out;
}
@@ -2791,10 +2795,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
mutex_unlock(&dev->struct_mutex);
- ret = __wait_seqno(ring, seqno, reset_counter, true, timeout, file->driver_priv);
- if (timeout)
- args->timeout_ns = timespec_to_ns(timeout);
- return ret;
+ return __wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns,
+ file->driver_priv);
out:
drm_gem_object_unreference(&obj->base);
@@ -2831,6 +2833,8 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
idx = intel_ring_sync_index(from, to);
seqno = obj->last_read_seqno;
+ /* Optimization: Avoid semaphore sync when we are sure we already
+ * waited for an object with higher seqno */
if (seqno <= from->semaphore.sync_seqno[idx])
return 0;
@@ -2914,8 +2918,6 @@ int i915_vma_unbind(struct i915_vma *vma)
vma->unbind_vma(vma);
- i915_gem_gtt_finish_object(obj);
-
list_del_init(&vma->mm_list);
/* Avoid an unnecessary call to unbind on rebind. */
if (i915_is_ggtt(vma->vm))
@@ -2926,8 +2928,10 @@ int i915_vma_unbind(struct i915_vma *vma)
/* Since the unbound list is global, only move to that list if
* no more VMAs exist. */
- if (list_empty(&obj->vma_list))
+ if (list_empty(&obj->vma_list)) {
+ i915_gem_gtt_finish_object(obj);
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
+ }
/* And finally now the object is completely decoupled from this vma,
* we can drop its hold on the backing storage and allow it to be
@@ -3539,6 +3543,8 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
old_write_domain = obj->base.write_domain;
obj->base.write_domain = 0;
+ intel_fb_obj_flush(obj, false);
+
trace_i915_gem_object_change_domain(obj,
obj->base.read_domains,
old_write_domain);
@@ -3560,6 +3566,8 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj,
old_write_domain = obj->base.write_domain;
obj->base.write_domain = 0;
+ intel_fb_obj_flush(obj, false);
+
trace_i915_gem_object_change_domain(obj,
obj->base.read_domains,
old_write_domain);
@@ -3613,6 +3621,9 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
obj->dirty = 1;
}
+ if (write)
+ intel_fb_obj_invalidate(obj, NULL);
+
trace_i915_gem_object_change_domain(obj,
old_read_domains,
old_write_domain);
@@ -3949,6 +3960,9 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
obj->base.write_domain = I915_GEM_DOMAIN_CPU;
}
+ if (write)
+ intel_fb_obj_invalidate(obj, NULL);
+
trace_i915_gem_object_change_domain(obj,
old_read_domains,
old_write_domain);
@@ -4437,13 +4451,14 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
if (obj->stolen)
i915_gem_object_unpin_pages(obj);
+ WARN_ON(obj->frontbuffer_bits);
+
if (WARN_ON(obj->pages_pin_count))
obj->pages_pin_count = 0;
if (discard_backing_storage(obj))
obj->madv = I915_MADV_DONTNEED;
i915_gem_object_put_pages(obj);
i915_gem_object_free_mmap_offset(obj);
- i915_gem_object_release_stolen(obj);
BUG_ON(obj->pages);
@@ -4530,7 +4545,7 @@ i915_gem_suspend(struct drm_device *dev)
del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
- cancel_delayed_work_sync(&dev_priv->mm.idle_work);
+ flush_delayed_work(&dev_priv->mm.idle_work);
return 0;
@@ -4921,6 +4936,8 @@ i915_gem_load(struct drm_device *dev)
dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
register_oom_notifier(&dev_priv->mm.oom_notifier);
+
+ mutex_init(&dev_priv->fb_tracking.lock);
}
void i915_gem_release(struct drm_device *dev, struct drm_file *file)
@@ -4982,6 +4999,23 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file)
return ret;
}
+void i915_gem_track_fb(struct drm_i915_gem_object *old,
+ struct drm_i915_gem_object *new,
+ unsigned frontbuffer_bits)
+{
+ if (old) {
+ WARN_ON(!mutex_is_locked(&old->base.dev->struct_mutex));
+ WARN_ON(!(old->frontbuffer_bits & frontbuffer_bits));
+ old->frontbuffer_bits &= ~frontbuffer_bits;
+ }
+
+ if (new) {
+ WARN_ON(!mutex_is_locked(&new->base.dev->struct_mutex));
+ WARN_ON(new->frontbuffer_bits & frontbuffer_bits);
+ new->frontbuffer_bits |= frontbuffer_bits;
+ }
+}
+
static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
{
if (!mutex_is_locked(mutex))
@@ -5064,12 +5098,13 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
vm == &dev_priv->mm.aliasing_ppgtt->base)
vm = &dev_priv->gtt.base;
- BUG_ON(list_empty(&o->vma_list));
list_for_each_entry(vma, &o->vma_list, vma_link) {
if (vma->vm == vm)
return vma->node.start;
}
+ WARN(1, "%s vma for this object not found.\n",
+ i915_is_ggtt(vm) ? "global" : "ppgtt");
return -1;
}
@@ -5150,8 +5185,11 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
bool was_interruptible;
bool unlock;
- while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout)
+ while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout) {
schedule_timeout_killable(1);
+ if (fatal_signal_pending(current))
+ return NOTIFY_DONE;
+ }
if (timeout == 0) {
pr_err("Unable to purge GPU memory due lock contention.\n");
return NOTIFY_DONE;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index a5ddf3bce9c3..3b99390e467a 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -182,22 +182,50 @@ void i915_gem_context_free(struct kref *ctx_ref)
typeof(*ctx), ref);
struct i915_hw_ppgtt *ppgtt = NULL;
- if (ctx->obj) {
+ if (ctx->legacy_hw_ctx.rcs_state) {
/* We refcount even the aliasing PPGTT to keep the code symmetric */
- if (USES_PPGTT(ctx->obj->base.dev))
+ if (USES_PPGTT(ctx->legacy_hw_ctx.rcs_state->base.dev))
ppgtt = ctx_to_ppgtt(ctx);
-
- /* XXX: Free up the object before tearing down the address space, in
- * case we're bound in the PPGTT */
- drm_gem_object_unreference(&ctx->obj->base);
}
if (ppgtt)
kref_put(&ppgtt->ref, ppgtt_release);
+ if (ctx->legacy_hw_ctx.rcs_state)
+ drm_gem_object_unreference(&ctx->legacy_hw_ctx.rcs_state->base);
list_del(&ctx->link);
kfree(ctx);
}
+static struct drm_i915_gem_object *
+i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
+{
+ struct drm_i915_gem_object *obj;
+ int ret;
+
+ obj = i915_gem_alloc_object(dev, size);
+ if (obj == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * Try to make the context utilize L3 as well as LLC.
+ *
+ * On VLV we don't have L3 controls in the PTEs so we
+ * shouldn't touch the cache level, especially as that
+ * would make the object snooped which might have a
+ * negative performance impact.
+ */
+ if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
+ ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
+ /* Failure shouldn't ever happen this early */
+ if (WARN_ON(ret)) {
+ drm_gem_object_unreference(&obj->base);
+ return ERR_PTR(ret);
+ }
+ }
+
+ return obj;
+}
+
static struct i915_hw_ppgtt *
create_vm_for_ctx(struct drm_device *dev, struct intel_context *ctx)
{
@@ -234,40 +262,26 @@ __create_hw_context(struct drm_device *dev,
list_add_tail(&ctx->link, &dev_priv->context_list);
if (dev_priv->hw_context_size) {
- ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
- if (ctx->obj == NULL) {
- ret = -ENOMEM;
+ struct drm_i915_gem_object *obj =
+ i915_gem_alloc_context_obj(dev, dev_priv->hw_context_size);
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
goto err_out;
}
-
- /*
- * Try to make the context utilize L3 as well as LLC.
- *
- * On VLV we don't have L3 controls in the PTEs so we
- * shouldn't touch the cache level, especially as that
- * would make the object snooped which might have a
- * negative performance impact.
- */
- if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
- ret = i915_gem_object_set_cache_level(ctx->obj,
- I915_CACHE_L3_LLC);
- /* Failure shouldn't ever happen this early */
- if (WARN_ON(ret))
- goto err_out;
- }
+ ctx->legacy_hw_ctx.rcs_state = obj;
}
/* Default context will never have a file_priv */
if (file_priv != NULL) {
ret = idr_alloc(&file_priv->context_idr, ctx,
- DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
+ DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL);
if (ret < 0)
goto err_out;
} else
- ret = DEFAULT_CONTEXT_ID;
+ ret = DEFAULT_CONTEXT_HANDLE;
ctx->file_priv = file_priv;
- ctx->id = ret;
+ ctx->user_handle = ret;
/* NB: Mark all slices as needing a remap so that when the context first
* loads it will restore whatever remap state already exists. If there
* is no remap info, it will be a NOP. */
@@ -301,7 +315,7 @@ i915_gem_create_context(struct drm_device *dev,
if (IS_ERR(ctx))
return ctx;
- if (is_global_default_ctx && ctx->obj) {
+ if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state) {
/* We may need to do things with the shrinker which
* require us to immediately switch back to the default
* context. This can cause a problem as pinning the
@@ -309,7 +323,7 @@ i915_gem_create_context(struct drm_device *dev,
* be available. To avoid this we always pin the default
* context.
*/
- ret = i915_gem_obj_ggtt_pin(ctx->obj,
+ ret = i915_gem_obj_ggtt_pin(ctx->legacy_hw_ctx.rcs_state,
get_context_alignment(dev), 0);
if (ret) {
DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
@@ -349,8 +363,8 @@ i915_gem_create_context(struct drm_device *dev,
return ctx;
err_unpin:
- if (is_global_default_ctx && ctx->obj)
- i915_gem_object_ggtt_unpin(ctx->obj);
+ if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state)
+ i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
err_destroy:
i915_gem_context_unreference(ctx);
return ERR_PTR(ret);
@@ -366,23 +380,27 @@ void i915_gem_context_reset(struct drm_device *dev)
for (i = 0; i < I915_NUM_RINGS; i++) {
struct intel_engine_cs *ring = &dev_priv->ring[i];
struct intel_context *dctx = ring->default_context;
+ struct intel_context *lctx = ring->last_context;
/* Do a fake switch to the default context */
- if (ring->last_context == dctx)
+ if (lctx == dctx)
continue;
- if (!ring->last_context)
+ if (!lctx)
continue;
- if (dctx->obj && i == RCS) {
- WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
+ if (dctx->legacy_hw_ctx.rcs_state && i == RCS) {
+ WARN_ON(i915_gem_obj_ggtt_pin(dctx->legacy_hw_ctx.rcs_state,
get_context_alignment(dev), 0));
/* Fake a finish/inactive */
- dctx->obj->base.write_domain = 0;
- dctx->obj->active = 0;
+ dctx->legacy_hw_ctx.rcs_state->base.write_domain = 0;
+ dctx->legacy_hw_ctx.rcs_state->active = 0;
}
- i915_gem_context_unreference(ring->last_context);
+ if (lctx->legacy_hw_ctx.rcs_state && i == RCS)
+ i915_gem_object_ggtt_unpin(lctx->legacy_hw_ctx.rcs_state);
+
+ i915_gem_context_unreference(lctx);
i915_gem_context_reference(dctx);
ring->last_context = dctx;
}
@@ -429,7 +447,7 @@ void i915_gem_context_fini(struct drm_device *dev)
struct intel_context *dctx = dev_priv->ring[RCS].default_context;
int i;
- if (dctx->obj) {
+ if (dctx->legacy_hw_ctx.rcs_state) {
/* The only known way to stop the gpu from accessing the hw context is
* to reset it. Do this as the very last operation to avoid confusing
* other code, leading to spurious errors. */
@@ -444,13 +462,13 @@ void i915_gem_context_fini(struct drm_device *dev)
WARN_ON(!dev_priv->ring[RCS].last_context);
if (dev_priv->ring[RCS].last_context == dctx) {
/* Fake switch to NULL context */
- WARN_ON(dctx->obj->active);
- i915_gem_object_ggtt_unpin(dctx->obj);
+ WARN_ON(dctx->legacy_hw_ctx.rcs_state->active);
+ i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
i915_gem_context_unreference(dctx);
dev_priv->ring[RCS].last_context = NULL;
}
- i915_gem_object_ggtt_unpin(dctx->obj);
+ i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
}
for (i = 0; i < I915_NUM_RINGS; i++) {
@@ -570,7 +588,7 @@ mi_set_context(struct intel_engine_cs *ring,
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_SET_CONTEXT);
- intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->obj) |
+ intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->legacy_hw_ctx.rcs_state) |
MI_MM_SPACE_GTT |
MI_SAVE_EXT_STATE_EN |
MI_RESTORE_EXT_STATE_EN |
@@ -602,16 +620,16 @@ static int do_switch(struct intel_engine_cs *ring,
int ret, i;
if (from != NULL && ring == &dev_priv->ring[RCS]) {
- BUG_ON(from->obj == NULL);
- BUG_ON(!i915_gem_obj_is_pinned(from->obj));
+ BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
+ BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
}
- if (from == to && from->last_ring == ring && !to->remap_slice)
+ if (from == to && !to->remap_slice)
return 0;
/* Trying to pin first makes error handling easier. */
if (ring == &dev_priv->ring[RCS]) {
- ret = i915_gem_obj_ggtt_pin(to->obj,
+ ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
get_context_alignment(ring->dev), 0);
if (ret)
return ret;
@@ -644,17 +662,17 @@ static int do_switch(struct intel_engine_cs *ring,
*
* XXX: We need a real interface to do this instead of trickery.
*/
- ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
+ ret = i915_gem_object_set_to_gtt_domain(to->legacy_hw_ctx.rcs_state, false);
if (ret)
goto unpin_out;
- if (!to->obj->has_global_gtt_mapping) {
- struct i915_vma *vma = i915_gem_obj_to_vma(to->obj,
+ if (!to->legacy_hw_ctx.rcs_state->has_global_gtt_mapping) {
+ struct i915_vma *vma = i915_gem_obj_to_vma(to->legacy_hw_ctx.rcs_state,
&dev_priv->gtt.base);
- vma->bind_vma(vma, to->obj->cache_level, GLOBAL_BIND);
+ vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, GLOBAL_BIND);
}
- if (!to->is_initialized || i915_gem_context_is_default(to))
+ if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
hw_flags |= MI_RESTORE_INHIBIT;
ret = mi_set_context(ring, to, hw_flags);
@@ -680,8 +698,8 @@ static int do_switch(struct intel_engine_cs *ring,
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from != NULL) {
- from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
- i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring);
+ from->legacy_hw_ctx.rcs_state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+ i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), ring);
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be
@@ -689,21 +707,20 @@ static int do_switch(struct intel_engine_cs *ring,
* able to defer doing this until we know the object would be
* swapped, but there is no way to do that yet.
*/
- from->obj->dirty = 1;
- BUG_ON(from->obj->ring != ring);
+ from->legacy_hw_ctx.rcs_state->dirty = 1;
+ BUG_ON(from->legacy_hw_ctx.rcs_state->ring != ring);
/* obj is kept alive until the next request by its active ref */
- i915_gem_object_ggtt_unpin(from->obj);
+ i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
i915_gem_context_unreference(from);
}
- uninitialized = !to->is_initialized && from == NULL;
- to->is_initialized = true;
+ uninitialized = !to->legacy_hw_ctx.initialized && from == NULL;
+ to->legacy_hw_ctx.initialized = true;
done:
i915_gem_context_reference(to);
ring->last_context = to;
- to->last_ring = ring;
if (uninitialized) {
ret = i915_gem_render_state_init(ring);
@@ -715,7 +732,7 @@ done:
unpin_out:
if (ring->id == RCS)
- i915_gem_object_ggtt_unpin(to->obj);
+ i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
return ret;
}
@@ -736,7 +753,7 @@ int i915_switch_context(struct intel_engine_cs *ring,
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
- if (to->obj == NULL) { /* We have the fake context */
+ if (to->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
if (to != ring->last_context) {
i915_gem_context_reference(to);
if (ring->last_context)
@@ -774,7 +791,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (IS_ERR(ctx))
return PTR_ERR(ctx);
- args->ctx_id = ctx->id;
+ args->ctx_id = ctx->user_handle;
DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id);
return 0;
@@ -788,7 +805,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
struct intel_context *ctx;
int ret;
- if (args->ctx_id == DEFAULT_CONTEXT_ID)
+ if (args->ctx_id == DEFAULT_CONTEXT_HANDLE)
return -ENOENT;
ret = i915_mutex_lock_interruptible(dev);
@@ -801,7 +818,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
return PTR_ERR(ctx);
}
- idr_remove(&ctx->file_priv->context_idr, ctx->id);
+ idr_remove(&ctx->file_priv->context_idr, ctx->user_handle);
i915_gem_context_unreference(ctx);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 580aa42443ed..82a1f4b57778 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -237,7 +237,8 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
return ERR_PTR(ret);
}
- return dma_buf_export(gem_obj, &i915_dmabuf_ops, gem_obj->size, flags);
+ return dma_buf_export(gem_obj, &i915_dmabuf_ops, gem_obj->size, flags,
+ NULL);
}
static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3a30133f93e8..60998fc4e5b2 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -938,7 +938,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
struct intel_context *ctx = NULL;
struct i915_ctx_hang_stats *hs;
- if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_ID)
+ if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
return ERR_PTR(-EINVAL);
ctx = i915_gem_context_get(file->driver_priv, ctx_id);
@@ -975,10 +975,8 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
if (obj->base.write_domain) {
obj->dirty = 1;
obj->last_write_seqno = intel_ring_get_seqno(ring);
- /* check for potential scanout */
- if (i915_gem_obj_ggtt_bound(obj) &&
- i915_gem_obj_to_ggtt(obj)->pin_count)
- intel_mark_fb_busy(obj, ring);
+
+ intel_fb_obj_invalidate(obj, ring);
/* update for the implicit flush after a batch */
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
@@ -1028,6 +1026,163 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
return 0;
}
+static int
+legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
+ struct intel_engine_cs *ring,
+ struct intel_context *ctx,
+ struct drm_i915_gem_execbuffer2 *args,
+ struct list_head *vmas,
+ struct drm_i915_gem_object *batch_obj,
+ u64 exec_start, u32 flags)
+{
+ struct drm_clip_rect *cliprects = NULL;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u64 exec_len;
+ int instp_mode;
+ u32 instp_mask;
+ int i, ret = 0;
+
+ if (args->num_cliprects != 0) {
+ if (ring != &dev_priv->ring[RCS]) {
+ DRM_DEBUG("clip rectangles are only valid with the render ring\n");
+ return -EINVAL;
+ }
+
+ if (INTEL_INFO(dev)->gen >= 5) {
+ DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
+ return -EINVAL;
+ }
+
+ if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+ DRM_DEBUG("execbuf with %u cliprects\n",
+ args->num_cliprects);
+ return -EINVAL;
+ }
+
+ cliprects = kcalloc(args->num_cliprects,
+ sizeof(*cliprects),
+ GFP_KERNEL);
+ if (cliprects == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(cliprects,
+ to_user_ptr(args->cliprects_ptr),
+ sizeof(*cliprects)*args->num_cliprects)) {
+ ret = -EFAULT;
+ goto error;
+ }
+ } else {
+ if (args->DR4 == 0xffffffff) {
+ DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
+ args->DR4 = 0;
+ }
+
+ if (args->DR1 || args->DR4 || args->cliprects_ptr) {
+ DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = i915_gem_execbuffer_move_to_gpu(ring, vmas);
+ if (ret)
+ goto error;
+
+ ret = i915_switch_context(ring, ctx);
+ if (ret)
+ goto error;
+
+ instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+ instp_mask = I915_EXEC_CONSTANTS_MASK;
+ switch (instp_mode) {
+ case I915_EXEC_CONSTANTS_REL_GENERAL:
+ case I915_EXEC_CONSTANTS_ABSOLUTE:
+ case I915_EXEC_CONSTANTS_REL_SURFACE:
+ if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+ DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (instp_mode != dev_priv->relative_constants_mode) {
+ if (INTEL_INFO(dev)->gen < 4) {
+ DRM_DEBUG("no rel constants on pre-gen4\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (INTEL_INFO(dev)->gen > 5 &&
+ instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
+ DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* The HW changed the meaning on this bit on gen6 */
+ if (INTEL_INFO(dev)->gen >= 6)
+ instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
+ }
+ break;
+ default:
+ DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (ring == &dev_priv->ring[RCS] &&
+ instp_mode != dev_priv->relative_constants_mode) {
+ ret = intel_ring_begin(ring, 4);
+ if (ret)
+ goto error;
+
+ intel_ring_emit(ring, MI_NOOP);
+ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+ intel_ring_emit(ring, INSTPM);
+ intel_ring_emit(ring, instp_mask << 16 | instp_mode);
+ intel_ring_advance(ring);
+
+ dev_priv->relative_constants_mode = instp_mode;
+ }
+
+ if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
+ ret = i915_reset_gen7_sol_offsets(dev, ring);
+ if (ret)
+ goto error;
+ }
+
+ exec_len = args->batch_len;
+ if (cliprects) {
+ for (i = 0; i < args->num_cliprects; i++) {
+ ret = i915_emit_box(dev, &cliprects[i],
+ args->DR1, args->DR4);
+ if (ret)
+ goto error;
+
+ ret = ring->dispatch_execbuffer(ring,
+ exec_start, exec_len,
+ flags);
+ if (ret)
+ goto error;
+ }
+ } else {
+ ret = ring->dispatch_execbuffer(ring,
+ exec_start, exec_len,
+ flags);
+ if (ret)
+ return ret;
+ }
+
+ trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
+
+ i915_gem_execbuffer_move_to_active(vmas, ring);
+ i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
+
+error:
+ kfree(cliprects);
+ return ret;
+}
+
/**
* Find one BSD ring to dispatch the corresponding BSD command.
* The Ring ID is returned.
@@ -1087,14 +1242,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_i915_private *dev_priv = dev->dev_private;
struct eb_vmas *eb;
struct drm_i915_gem_object *batch_obj;
- struct drm_clip_rect *cliprects = NULL;
struct intel_engine_cs *ring;
struct intel_context *ctx;
struct i915_address_space *vm;
const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
- u64 exec_start = args->batch_start_offset, exec_len;
- u32 mask, flags;
- int ret, mode, i;
+ u64 exec_start = args->batch_start_offset;
+ u32 flags;
+ int ret;
bool need_relocs;
if (!i915_gem_check_execbuffer(args))
@@ -1138,87 +1292,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
- mode = args->flags & I915_EXEC_CONSTANTS_MASK;
- mask = I915_EXEC_CONSTANTS_MASK;
- switch (mode) {
- case I915_EXEC_CONSTANTS_REL_GENERAL:
- case I915_EXEC_CONSTANTS_ABSOLUTE:
- case I915_EXEC_CONSTANTS_REL_SURFACE:
- if (mode != 0 && ring != &dev_priv->ring[RCS]) {
- DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
- return -EINVAL;
- }
-
- if (mode != dev_priv->relative_constants_mode) {
- if (INTEL_INFO(dev)->gen < 4) {
- DRM_DEBUG("no rel constants on pre-gen4\n");
- return -EINVAL;
- }
-
- if (INTEL_INFO(dev)->gen > 5 &&
- mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
- DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
- return -EINVAL;
- }
-
- /* The HW changed the meaning on this bit on gen6 */
- if (INTEL_INFO(dev)->gen >= 6)
- mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
- }
- break;
- default:
- DRM_DEBUG("execbuf with unknown constants: %d\n", mode);
- return -EINVAL;
- }
-
if (args->buffer_count < 1) {
DRM_DEBUG("execbuf with %d buffers\n", args->buffer_count);
return -EINVAL;
}
- if (args->num_cliprects != 0) {
- if (ring != &dev_priv->ring[RCS]) {
- DRM_DEBUG("clip rectangles are only valid with the render ring\n");
- return -EINVAL;
- }
-
- if (INTEL_INFO(dev)->gen >= 5) {
- DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
- return -EINVAL;
- }
-
- if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
- DRM_DEBUG("execbuf with %u cliprects\n",
- args->num_cliprects);
- return -EINVAL;
- }
-
- cliprects = kcalloc(args->num_cliprects,
- sizeof(*cliprects),
- GFP_KERNEL);
- if (cliprects == NULL) {
- ret = -ENOMEM;
- goto pre_mutex_err;
- }
-
- if (copy_from_user(cliprects,
- to_user_ptr(args->cliprects_ptr),
- sizeof(*cliprects)*args->num_cliprects)) {
- ret = -EFAULT;
- goto pre_mutex_err;
- }
- } else {
- if (args->DR4 == 0xffffffff) {
- DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
- args->DR4 = 0;
- }
-
- if (args->DR1 || args->DR4 || args->cliprects_ptr) {
- DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
- return -EINVAL;
- }
- }
-
intel_runtime_pm_get(dev_priv);
ret = i915_mutex_lock_interruptible(dev);
@@ -1322,63 +1400,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
else
exec_start += i915_gem_obj_offset(batch_obj, vm);
- ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas);
+ ret = legacy_ringbuffer_submission(dev, file, ring, ctx,
+ args, &eb->vmas, batch_obj, exec_start, flags);
if (ret)
goto err;
- ret = i915_switch_context(ring, ctx);
- if (ret)
- goto err;
-
- if (ring == &dev_priv->ring[RCS] &&
- mode != dev_priv->relative_constants_mode) {
- ret = intel_ring_begin(ring, 4);
- if (ret)
- goto err;
-
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, INSTPM);
- intel_ring_emit(ring, mask << 16 | mode);
- intel_ring_advance(ring);
-
- dev_priv->relative_constants_mode = mode;
- }
-
- if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
- ret = i915_reset_gen7_sol_offsets(dev, ring);
- if (ret)
- goto err;
- }
-
-
- exec_len = args->batch_len;
- if (cliprects) {
- for (i = 0; i < args->num_cliprects; i++) {
- ret = i915_emit_box(dev, &cliprects[i],
- args->DR1, args->DR4);
- if (ret)
- goto err;
-
- ret = ring->dispatch_execbuffer(ring,
- exec_start, exec_len,
- flags);
- if (ret)
- goto err;
- }
- } else {
- ret = ring->dispatch_execbuffer(ring,
- exec_start, exec_len,
- flags);
- if (ret)
- goto err;
- }
-
- trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
-
- i915_gem_execbuffer_move_to_active(&eb->vmas, ring);
- i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
-
err:
/* the request owns the ref now */
i915_gem_context_unreference(ctx);
@@ -1387,8 +1413,6 @@ err:
mutex_unlock(&dev->struct_mutex);
pre_mutex_err:
- kfree(cliprects);
-
/* intel_gpu_busy should also get a ref, so it will free when the device
* is really idle. */
intel_runtime_pm_put(dev_priv);
@@ -1525,7 +1549,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
if (!ret) {
/* Copy the new buffer offsets back to the user's exec list. */
- struct drm_i915_gem_exec_object2 *user_exec_list =
+ struct drm_i915_gem_exec_object2 __user *user_exec_list =
to_user_ptr(args->buffers_ptr);
int i;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 8b3cde703364..1411613f2174 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -63,6 +63,13 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
}
#endif
+ /* Early VLV doesn't have this */
+ if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+ dev->pdev->revision < 0xb) {
+ DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
+ return 0;
+ }
+
return HAS_ALIASING_PPGTT(dev) ? 1 : 0;
}
@@ -110,7 +117,7 @@ static inline gen8_ppgtt_pde_t gen8_pde_encode(struct drm_device *dev,
static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid)
+ bool valid, u32 unused)
{
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -132,7 +139,7 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid)
+ bool valid, u32 unused)
{
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -156,7 +163,7 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid)
+ bool valid, u32 flags)
{
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
@@ -164,7 +171,8 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
/* Mark the page as writeable. Other platforms don't have a
* setting for read-only/writable, so this matches that behavior.
*/
- pte |= BYT_PTE_WRITEABLE;
+ if (!(flags & PTE_READ_ONLY))
+ pte |= BYT_PTE_WRITEABLE;
if (level != I915_CACHE_NONE)
pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
@@ -174,7 +182,7 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid)
+ bool valid, u32 unused)
{
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr);
@@ -187,7 +195,7 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
- bool valid)
+ bool valid, u32 unused)
{
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr);
@@ -301,7 +309,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
struct sg_table *pages,
uint64_t start,
- enum i915_cache_level cache_level)
+ enum i915_cache_level cache_level, u32 unused)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
@@ -639,7 +647,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
uint32_t pd_entry;
int pte, pde;
- scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+ scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm +
ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
@@ -941,7 +949,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
unsigned last_pte, i;
- scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+ scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true, 0);
while (num_entries) {
last_pte = first_pte + num_entries;
@@ -964,7 +972,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
struct sg_table *pages,
uint64_t start,
- enum i915_cache_level cache_level)
+ enum i915_cache_level cache_level, u32 flags)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
@@ -981,7 +989,8 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
pt_vaddr[act_pte] =
vm->pte_encode(sg_page_iter_dma_address(&sg_iter),
- cache_level, true);
+ cache_level, true, flags);
+
if (++act_pte == I915_PPGTT_PT_ENTRIES) {
kunmap_atomic(pt_vaddr);
pt_vaddr = NULL;
@@ -1218,8 +1227,12 @@ ppgtt_bind_vma(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags)
{
+ /* Currently applicable only to VLV */
+ if (vma->obj->gt_ro)
+ flags |= PTE_READ_ONLY;
+
vma->vm->insert_entries(vma->vm, vma->obj->pages, vma->node.start,
- cache_level);
+ cache_level, flags);
}
static void ppgtt_unbind_vma(struct i915_vma *vma)
@@ -1394,7 +1407,7 @@ static inline void gen8_set_pte(void __iomem *addr, gen8_gtt_pte_t pte)
static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct sg_table *st,
uint64_t start,
- enum i915_cache_level level)
+ enum i915_cache_level level, u32 unused)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
unsigned first_entry = start >> PAGE_SHIFT;
@@ -1402,7 +1415,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
(gen8_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
int i = 0;
struct sg_page_iter sg_iter;
- dma_addr_t addr = 0;
+ dma_addr_t addr = 0; /* shut up gcc */
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
addr = sg_dma_address(sg_iter.sg) +
@@ -1440,7 +1453,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
struct sg_table *st,
uint64_t start,
- enum i915_cache_level level)
+ enum i915_cache_level level, u32 flags)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
unsigned first_entry = start >> PAGE_SHIFT;
@@ -1448,11 +1461,11 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
(gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
int i = 0;
struct sg_page_iter sg_iter;
- dma_addr_t addr;
+ dma_addr_t addr = 0;
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
addr = sg_page_iter_dma_address(&sg_iter);
- iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
+ iowrite32(vm->pte_encode(addr, level, true, flags), &gtt_entries[i]);
i++;
}
@@ -1462,9 +1475,10 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
* of NUMA access patterns. Therefore, even with the way we assume
* hardware should work, we must keep this posting read for paranoia.
*/
- if (i != 0)
- WARN_ON(readl(&gtt_entries[i-1]) !=
- vm->pte_encode(addr, level, true));
+ if (i != 0) {
+ unsigned long gtt = readl(&gtt_entries[i-1]);
+ WARN_ON(gtt != vm->pte_encode(addr, level, true, flags));
+ }
/* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates
@@ -1518,7 +1532,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
first_entry, num_entries, max_entries))
num_entries = max_entries;
- scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
+ scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch, 0);
for (i = 0; i < num_entries; i++)
iowrite32(scratch_pte, &gtt_base[i]);
@@ -1567,6 +1581,10 @@ static void ggtt_bind_vma(struct i915_vma *vma,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = vma->obj;
+ /* Currently applicable only to VLV */
+ if (obj->gt_ro)
+ flags |= PTE_READ_ONLY;
+
/* If there is no aliasing PPGTT, or the caller needs a global mapping,
* or we have a global mapping already but the cacheability flags have
* changed, set the global PTEs.
@@ -1583,7 +1601,7 @@ static void ggtt_bind_vma(struct i915_vma *vma,
(cache_level != obj->cache_level)) {
vma->vm->insert_entries(vma->vm, obj->pages,
vma->node.start,
- cache_level);
+ cache_level, flags);
obj->has_global_gtt_mapping = 1;
}
}
@@ -1595,7 +1613,7 @@ static void ggtt_bind_vma(struct i915_vma *vma,
appgtt->base.insert_entries(&appgtt->base,
vma->obj->pages,
vma->node.start,
- cache_level);
+ cache_level, flags);
vma->obj->has_aliasing_ppgtt_mapping = 1;
}
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 1b96a06be3cb..8d6f7c18c404 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -154,6 +154,7 @@ struct i915_vma {
void (*unbind_vma)(struct i915_vma *vma);
/* Map an object into an address space with the given cache flags. */
#define GLOBAL_BIND (1<<0)
+#define PTE_READ_ONLY (1<<1)
void (*bind_vma)(struct i915_vma *vma,
enum i915_cache_level cache_level,
u32 flags);
@@ -197,7 +198,7 @@ struct i915_address_space {
/* FIXME: Need a more generic return type */
gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
enum i915_cache_level level,
- bool valid); /* Create a valid PTE */
+ bool valid, u32 flags); /* Create a valid PTE */
void (*clear_range)(struct i915_address_space *vm,
uint64_t start,
uint64_t length,
@@ -205,7 +206,7 @@ struct i915_address_space {
void (*insert_entries)(struct i915_address_space *vm,
struct sg_table *st,
uint64_t start,
- enum i915_cache_level cache_level);
+ enum i915_cache_level cache_level, u32 flags);
void (*cleanup)(struct i915_address_space *vm);
};
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index 34894b573064..e60be3f552a6 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -28,64 +28,13 @@
#include "i915_drv.h"
#include "intel_renderstate.h"
-struct i915_render_state {
+struct render_state {
+ const struct intel_renderstate_rodata *rodata;
struct drm_i915_gem_object *obj;
- unsigned long ggtt_offset;
- u32 *batch;
- u32 size;
- u32 len;
+ u64 ggtt_offset;
+ int gen;
};
-static struct i915_render_state *render_state_alloc(struct drm_device *dev)
-{
- struct i915_render_state *so;
- struct page *page;
- int ret;
-
- so = kzalloc(sizeof(*so), GFP_KERNEL);
- if (!so)
- return ERR_PTR(-ENOMEM);
-
- so->obj = i915_gem_alloc_object(dev, 4096);
- if (so->obj == NULL) {
- ret = -ENOMEM;
- goto free;
- }
- so->size = 4096;
-
- ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
- if (ret)
- goto free_gem;
-
- BUG_ON(so->obj->pages->nents != 1);
- page = sg_page(so->obj->pages->sgl);
-
- so->batch = kmap(page);
- if (!so->batch) {
- ret = -ENOMEM;
- goto unpin;
- }
-
- so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
-
- return so;
-unpin:
- i915_gem_object_ggtt_unpin(so->obj);
-free_gem:
- drm_gem_object_unreference(&so->obj->base);
-free:
- kfree(so);
- return ERR_PTR(ret);
-}
-
-static void render_state_free(struct i915_render_state *so)
-{
- kunmap(kmap_to_page(so->batch));
- i915_gem_object_ggtt_unpin(so->obj);
- drm_gem_object_unreference(&so->obj->base);
- kfree(so);
-}
-
static const struct intel_renderstate_rodata *
render_state_get_rodata(struct drm_device *dev, const int gen)
{
@@ -101,98 +50,120 @@ render_state_get_rodata(struct drm_device *dev, const int gen)
return NULL;
}
-static int render_state_setup(const int gen,
- const struct intel_renderstate_rodata *rodata,
- struct i915_render_state *so)
+static int render_state_init(struct render_state *so, struct drm_device *dev)
{
- const u64 goffset = i915_gem_obj_ggtt_offset(so->obj);
- u32 reloc_index = 0;
- u32 * const d = so->batch;
- unsigned int i = 0;
int ret;
- if (!rodata || rodata->batch_items * 4 > so->size)
+ so->gen = INTEL_INFO(dev)->gen;
+ so->rodata = render_state_get_rodata(dev, so->gen);
+ if (so->rodata == NULL)
+ return 0;
+
+ if (so->rodata->batch_items * 4 > 4096)
return -EINVAL;
+ so->obj = i915_gem_alloc_object(dev, 4096);
+ if (so->obj == NULL)
+ return -ENOMEM;
+
+ ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0);
+ if (ret)
+ goto free_gem;
+
+ so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj);
+ return 0;
+
+free_gem:
+ drm_gem_object_unreference(&so->obj->base);
+ return ret;
+}
+
+static int render_state_setup(struct render_state *so)
+{
+ const struct intel_renderstate_rodata *rodata = so->rodata;
+ unsigned int i = 0, reloc_index = 0;
+ struct page *page;
+ u32 *d;
+ int ret;
+
ret = i915_gem_object_set_to_cpu_domain(so->obj, true);
if (ret)
return ret;
+ page = sg_page(so->obj->pages->sgl);
+ d = kmap(page);
+
while (i < rodata->batch_items) {
u32 s = rodata->batch[i];
- if (reloc_index < rodata->reloc_items &&
- i * 4 == rodata->reloc[reloc_index]) {
-
- s += goffset & 0xffffffff;
-
- /* We keep batch offsets max 32bit */
- if (gen >= 8) {
+ if (i * 4 == rodata->reloc[reloc_index]) {
+ u64 r = s + so->ggtt_offset;
+ s = lower_32_bits(r);
+ if (so->gen >= 8) {
if (i + 1 >= rodata->batch_items ||
rodata->batch[i + 1] != 0)
return -EINVAL;
- d[i] = s;
- i++;
- s = (goffset & 0xffffffff00000000ull) >> 32;
+ d[i++] = s;
+ s = upper_32_bits(r);
}
reloc_index++;
}
- d[i] = s;
- i++;
+ d[i++] = s;
}
+ kunmap(page);
ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
if (ret)
return ret;
- if (rodata->reloc_items != reloc_index) {
- DRM_ERROR("not all relocs resolved, %d out of %d\n",
- reloc_index, rodata->reloc_items);
+ if (rodata->reloc[reloc_index] != -1) {
+ DRM_ERROR("only %d relocs resolved\n", reloc_index);
return -EINVAL;
}
- so->len = rodata->batch_items * 4;
-
return 0;
}
+static void render_state_fini(struct render_state *so)
+{
+ i915_gem_object_ggtt_unpin(so->obj);
+ drm_gem_object_unreference(&so->obj->base);
+}
+
int i915_gem_render_state_init(struct intel_engine_cs *ring)
{
- const int gen = INTEL_INFO(ring->dev)->gen;
- struct i915_render_state *so;
- const struct intel_renderstate_rodata *rodata;
+ struct render_state so;
int ret;
if (WARN_ON(ring->id != RCS))
return -ENOENT;
- rodata = render_state_get_rodata(ring->dev, gen);
- if (rodata == NULL)
- return 0;
+ ret = render_state_init(&so, ring->dev);
+ if (ret)
+ return ret;
- so = render_state_alloc(ring->dev);
- if (IS_ERR(so))
- return PTR_ERR(so);
+ if (so.rodata == NULL)
+ return 0;
- ret = render_state_setup(gen, rodata, so);
+ ret = render_state_setup(&so);
if (ret)
goto out;
ret = ring->dispatch_execbuffer(ring,
- i915_gem_obj_ggtt_offset(so->obj),
- so->len,
+ so.ggtt_offset,
+ so.rodata->batch_items * 4,
I915_DISPATCH_SECURE);
if (ret)
goto out;
- i915_vma_move_to_active(i915_gem_obj_to_ggtt(so->obj), ring);
+ i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
- ret = __i915_add_request(ring, NULL, so->obj, NULL);
+ ret = __i915_add_request(ring, NULL, so.obj, NULL);
/* __i915_add_request moves object to inactive if it fails */
out:
- render_state_free(so);
+ render_state_fini(&so);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 7465ab0fd396..21c025a209c0 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -147,30 +147,68 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
return base;
}
-static int i915_setup_compression(struct drm_device *dev, int size)
+static int find_compression_threshold(struct drm_device *dev,
+ struct drm_mm_node *node,
+ int size,
+ int fb_cpp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
+ int compression_threshold = 1;
int ret;
- compressed_fb = kzalloc(sizeof(*compressed_fb), GFP_KERNEL);
- if (!compressed_fb)
- goto err_llb;
+ /* HACK: This code depends on what we will do in *_enable_fbc. If that
+ * code changes, this code needs to change as well.
+ *
+ * The enable_fbc code will attempt to use one of our 2 compression
+ * thresholds, therefore, in that case, we only have 1 resort.
+ */
- /* Try to over-allocate to reduce reallocations and fragmentation */
- ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
+ /* Try to over-allocate to reduce reallocations and fragmentation. */
+ ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
size <<= 1, 4096, DRM_MM_SEARCH_DEFAULT);
- if (ret)
- ret = drm_mm_insert_node(&dev_priv->mm.stolen, compressed_fb,
- size >>= 1, 4096,
- DRM_MM_SEARCH_DEFAULT);
- if (ret)
+ if (ret == 0)
+ return compression_threshold;
+
+again:
+ /* HW's ability to limit the CFB is 1:4 */
+ if (compression_threshold > 4 ||
+ (fb_cpp == 2 && compression_threshold == 2))
+ return 0;
+
+ ret = drm_mm_insert_node(&dev_priv->mm.stolen, node,
+ size >>= 1, 4096,
+ DRM_MM_SEARCH_DEFAULT);
+ if (ret && INTEL_INFO(dev)->gen <= 4) {
+ return 0;
+ } else if (ret) {
+ compression_threshold <<= 1;
+ goto again;
+ } else {
+ return compression_threshold;
+ }
+}
+
+static int i915_setup_compression(struct drm_device *dev, int size, int fb_cpp)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_mm_node *uninitialized_var(compressed_llb);
+ int ret;
+
+ ret = find_compression_threshold(dev, &dev_priv->fbc.compressed_fb,
+ size, fb_cpp);
+ if (!ret)
goto err_llb;
+ else if (ret > 1) {
+ DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
+
+ }
+
+ dev_priv->fbc.threshold = ret;
if (HAS_PCH_SPLIT(dev))
- I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
+ I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
else if (IS_GM45(dev)) {
- I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
+ I915_WRITE(DPFC_CB_BASE, dev_priv->fbc.compressed_fb.start);
} else {
compressed_llb = kzalloc(sizeof(*compressed_llb), GFP_KERNEL);
if (!compressed_llb)
@@ -184,13 +222,12 @@ static int i915_setup_compression(struct drm_device *dev, int size)
dev_priv->fbc.compressed_llb = compressed_llb;
I915_WRITE(FBC_CFB_BASE,
- dev_priv->mm.stolen_base + compressed_fb->start);
+ dev_priv->mm.stolen_base + dev_priv->fbc.compressed_fb.start);
I915_WRITE(FBC_LL_BASE,
dev_priv->mm.stolen_base + compressed_llb->start);
}
- dev_priv->fbc.compressed_fb = compressed_fb;
- dev_priv->fbc.size = size;
+ dev_priv->fbc.size = size / dev_priv->fbc.threshold;
DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
size);
@@ -199,14 +236,13 @@ static int i915_setup_compression(struct drm_device *dev, int size)
err_fb:
kfree(compressed_llb);
- drm_mm_remove_node(compressed_fb);
+ drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
err_llb:
- kfree(compressed_fb);
pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
return -ENOSPC;
}
-int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
+int i915_gem_stolen_setup_compression(struct drm_device *dev, int size, int fb_cpp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -219,7 +255,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
/* Release any current block */
i915_gem_stolen_cleanup_compression(dev);
- return i915_setup_compression(dev, size);
+ return i915_setup_compression(dev, size, fb_cpp);
}
void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
@@ -229,10 +265,7 @@ void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
if (dev_priv->fbc.size == 0)
return;
- if (dev_priv->fbc.compressed_fb) {
- drm_mm_remove_node(dev_priv->fbc.compressed_fb);
- kfree(dev_priv->fbc.compressed_fb);
- }
+ drm_mm_remove_node(&dev_priv->fbc.compressed_fb);
if (dev_priv->fbc.compressed_llb) {
drm_mm_remove_node(dev_priv->fbc.compressed_llb);
@@ -336,9 +369,20 @@ static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj)
kfree(obj->pages);
}
+
+static void
+i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
+{
+ if (obj->stolen) {
+ drm_mm_remove_node(obj->stolen);
+ kfree(obj->stolen);
+ obj->stolen = NULL;
+ }
+}
static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
.get_pages = i915_gem_object_get_pages_stolen,
.put_pages = i915_gem_object_put_pages_stolen,
+ .release = i915_gem_object_release_stolen,
};
static struct drm_i915_gem_object *
@@ -496,13 +540,3 @@ err_out:
drm_gem_object_unreference(&obj->base);
return NULL;
}
-
-void
-i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
-{
- if (obj->stolen) {
- drm_mm_remove_node(obj->stolen);
- kfree(obj->stolen);
- obj->stolen = NULL;
- }
-}
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index 21ea92886a56..fe69fc837d9e 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -40,19 +40,87 @@ struct i915_mmu_notifier {
struct hlist_node node;
struct mmu_notifier mn;
struct rb_root objects;
+ struct list_head linear;
struct drm_device *dev;
struct mm_struct *mm;
struct work_struct work;
unsigned long count;
unsigned long serial;
+ bool has_linear;
};
struct i915_mmu_object {
struct i915_mmu_notifier *mmu;
struct interval_tree_node it;
+ struct list_head link;
struct drm_i915_gem_object *obj;
+ bool is_linear;
};
+static unsigned long cancel_userptr(struct drm_i915_gem_object *obj)
+{
+ struct drm_device *dev = obj->base.dev;
+ unsigned long end;
+
+ mutex_lock(&dev->struct_mutex);
+ /* Cancel any active worker and force us to re-evaluate gup */
+ obj->userptr.work = NULL;
+
+ if (obj->pages != NULL) {
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct i915_vma *vma, *tmp;
+ bool was_interruptible;
+
+ was_interruptible = dev_priv->mm.interruptible;
+ dev_priv->mm.interruptible = false;
+
+ list_for_each_entry_safe(vma, tmp, &obj->vma_list, vma_link) {
+ int ret = i915_vma_unbind(vma);
+ WARN_ON(ret && ret != -EIO);
+ }
+ WARN_ON(i915_gem_object_put_pages(obj));
+
+ dev_priv->mm.interruptible = was_interruptible;
+ }
+
+ end = obj->userptr.ptr + obj->base.size;
+
+ drm_gem_object_unreference(&obj->base);
+ mutex_unlock(&dev->struct_mutex);
+
+ return end;
+}
+
+static void *invalidate_range__linear(struct i915_mmu_notifier *mn,
+ struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+ struct i915_mmu_object *mmu;
+ unsigned long serial;
+
+restart:
+ serial = mn->serial;
+ list_for_each_entry(mmu, &mn->linear, link) {
+ struct drm_i915_gem_object *obj;
+
+ if (mmu->it.last < start || mmu->it.start > end)
+ continue;
+
+ obj = mmu->obj;
+ drm_gem_object_reference(&obj->base);
+ spin_unlock(&mn->lock);
+
+ cancel_userptr(obj);
+
+ spin_lock(&mn->lock);
+ if (serial != mn->serial)
+ goto restart;
+ }
+
+ return NULL;
+}
+
static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
struct mm_struct *mm,
unsigned long start,
@@ -60,16 +128,18 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
{
struct i915_mmu_notifier *mn = container_of(_mn, struct i915_mmu_notifier, mn);
struct interval_tree_node *it = NULL;
+ unsigned long next = start;
unsigned long serial = 0;
end--; /* interval ranges are inclusive, but invalidate range is exclusive */
- while (start < end) {
- struct drm_i915_gem_object *obj;
+ while (next < end) {
+ struct drm_i915_gem_object *obj = NULL;
- obj = NULL;
spin_lock(&mn->lock);
- if (serial == mn->serial)
- it = interval_tree_iter_next(it, start, end);
+ if (mn->has_linear)
+ it = invalidate_range__linear(mn, mm, start, end);
+ else if (serial == mn->serial)
+ it = interval_tree_iter_next(it, next, end);
else
it = interval_tree_iter_first(&mn->objects, start, end);
if (it != NULL) {
@@ -81,31 +151,7 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
if (obj == NULL)
return;
- mutex_lock(&mn->dev->struct_mutex);
- /* Cancel any active worker and force us to re-evaluate gup */
- obj->userptr.work = NULL;
-
- if (obj->pages != NULL) {
- struct drm_i915_private *dev_priv = to_i915(mn->dev);
- struct i915_vma *vma, *tmp;
- bool was_interruptible;
-
- was_interruptible = dev_priv->mm.interruptible;
- dev_priv->mm.interruptible = false;
-
- list_for_each_entry_safe(vma, tmp, &obj->vma_list, vma_link) {
- int ret = i915_vma_unbind(vma);
- WARN_ON(ret && ret != -EIO);
- }
- WARN_ON(i915_gem_object_put_pages(obj));
-
- dev_priv->mm.interruptible = was_interruptible;
- }
-
- start = obj->userptr.ptr + obj->base.size;
-
- drm_gem_object_unreference(&obj->base);
- mutex_unlock(&mn->dev->struct_mutex);
+ next = cancel_userptr(obj);
}
}
@@ -150,7 +196,9 @@ i915_mmu_notifier_get(struct drm_device *dev, struct mm_struct *mm)
mmu->mm = mm;
mmu->objects = RB_ROOT;
mmu->count = 0;
- mmu->serial = 0;
+ mmu->serial = 1;
+ INIT_LIST_HEAD(&mmu->linear);
+ mmu->has_linear = false;
/* Protected by mmap_sem (write-lock) */
ret = __mmu_notifier_register(&mmu->mn, mm);
@@ -197,6 +245,17 @@ static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mmu)
mmu->serial = 1;
}
+static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mmu)
+{
+ struct i915_mmu_object *mn;
+
+ list_for_each_entry(mn, &mmu->linear, link)
+ if (mn->is_linear)
+ return true;
+
+ return false;
+}
+
static void
i915_mmu_notifier_del(struct i915_mmu_notifier *mmu,
struct i915_mmu_object *mn)
@@ -204,7 +263,11 @@ i915_mmu_notifier_del(struct i915_mmu_notifier *mmu,
lockdep_assert_held(&mmu->dev->struct_mutex);
spin_lock(&mmu->lock);
- interval_tree_remove(&mn->it, &mmu->objects);
+ list_del(&mn->link);
+ if (mn->is_linear)
+ mmu->has_linear = i915_mmu_notifier_has_linear(mmu);
+ else
+ interval_tree_remove(&mn->it, &mmu->objects);
__i915_mmu_notifier_update_serial(mmu);
spin_unlock(&mmu->lock);
@@ -230,7 +293,6 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
*/
i915_gem_retire_requests(mmu->dev);
- /* Disallow overlapping userptr objects */
spin_lock(&mmu->lock);
it = interval_tree_iter_first(&mmu->objects,
mn->it.start, mn->it.last);
@@ -243,14 +305,22 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
* to flush their object references upon which the object will
* be removed from the interval-tree, or the the range is
* still in use by another client and the overlap is invalid.
+ *
+ * If we do have an overlap, we cannot use the interval tree
+ * for fast range invalidation.
*/
obj = container_of(it, struct i915_mmu_object, it)->obj;
- ret = obj->userptr.workers ? -EAGAIN : -EINVAL;
- } else {
+ if (!obj->userptr.workers)
+ mmu->has_linear = mn->is_linear = true;
+ else
+ ret = -EAGAIN;
+ } else
interval_tree_insert(&mn->it, &mmu->objects);
+
+ if (ret == 0) {
+ list_add(&mn->link, &mmu->linear);
__i915_mmu_notifier_update_serial(mmu);
- ret = 0;
}
spin_unlock(&mmu->lock);
mutex_unlock(&mmu->dev->struct_mutex);
@@ -611,12 +681,11 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
* We impose several restrictions upon the memory being mapped
* into the GPU.
* 1. It must be page aligned (both start/end addresses, i.e ptr and size).
- * 2. It cannot overlap any other userptr object in the same address space.
- * 3. It must be normal system memory, not a pointer into another map of IO
+ * 2. It must be normal system memory, not a pointer into another map of IO
* space (e.g. it must not be a GTT mmapping of another object).
- * 4. We only allow a bo as large as we could in theory map into the GTT,
+ * 3. We only allow a bo as large as we could in theory map into the GTT,
* that is we limit the size to the total size of the GTT.
- * 5. The bo is marked as being snoopable. The backing pages are left
+ * 4. The bo is marked as being snoopable. The backing pages are left
* accessible directly by the CPU, but reads and writes by the GPU may
* incur the cost of a snoop (unless you have an LLC architecture).
*
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 66cf41765bf9..eab41f9390f8 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -229,6 +229,8 @@ static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a)
return "wait";
case HANGCHECK_ACTIVE:
return "active";
+ case HANGCHECK_ACTIVE_LOOP:
+ return "active (loop)";
case HANGCHECK_KICK:
return "kick";
case HANGCHECK_HUNG:
@@ -327,6 +329,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
struct drm_device *dev = error_priv->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_error_state *error = error_priv->error;
+ struct drm_i915_error_object *obj;
int i, j, offset, elt;
int max_hangcheck_score;
@@ -358,6 +361,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
err_printf(m, "EIR: 0x%08x\n", error->eir);
err_printf(m, "IER: 0x%08x\n", error->ier);
+ if (INTEL_INFO(dev)->gen >= 8) {
+ for (i = 0; i < 4; i++)
+ err_printf(m, "GTIER gt %d: 0x%08x\n", i,
+ error->gtier[i]);
+ } else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev))
+ err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]);
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
@@ -395,8 +404,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
error->pinned_bo_count[0]);
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
- struct drm_i915_error_object *obj;
-
obj = error->ring[i].batchbuffer;
if (obj) {
err_puts(m, dev_priv->ring[i].name);
@@ -459,6 +466,18 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
}
+ if ((obj = error->semaphore_obj)) {
+ err_printf(m, "Semaphore page = 0x%08x\n", obj->gtt_offset);
+ for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
+ err_printf(m, "[%04x] %08x %08x %08x %08x\n",
+ elt * 4,
+ obj->pages[0][elt],
+ obj->pages[0][elt+1],
+ obj->pages[0][elt+2],
+ obj->pages[0][elt+3]);
+ }
+ }
+
if (error->overlay)
intel_overlay_print_error_state(m, error->overlay);
@@ -529,6 +548,7 @@ static void i915_error_state_free(struct kref *error_ref)
kfree(error->ring[i].requests);
}
+ i915_error_object_free(error->semaphore_obj);
kfree(error->active_bo);
kfree(error->overlay);
kfree(error->display);
@@ -746,7 +766,60 @@ static void i915_gem_record_fences(struct drm_device *dev,
}
}
+
+static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error,
+ struct intel_engine_cs *ring,
+ struct drm_i915_error_ring *ering)
+{
+ struct intel_engine_cs *to;
+ int i;
+
+ if (!i915_semaphore_is_enabled(dev_priv->dev))
+ return;
+
+ if (!error->semaphore_obj)
+ error->semaphore_obj =
+ i915_error_object_create(dev_priv,
+ dev_priv->semaphore_obj,
+ &dev_priv->gtt.base);
+
+ for_each_ring(to, dev_priv, i) {
+ int idx;
+ u16 signal_offset;
+ u32 *tmp;
+
+ if (ring == to)
+ continue;
+
+ signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
+ / 4;
+ tmp = error->semaphore_obj->pages[0];
+ idx = intel_ring_sync_index(ring, to);
+
+ ering->semaphore_mboxes[idx] = tmp[signal_offset];
+ ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx];
+ }
+}
+
+static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
+ struct intel_engine_cs *ring,
+ struct drm_i915_error_ring *ering)
+{
+ ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
+ ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
+ ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
+ ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
+
+ if (HAS_VEBOX(dev_priv->dev)) {
+ ering->semaphore_mboxes[2] =
+ I915_READ(RING_SYNC_2(ring->mmio_base));
+ ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+ }
+}
+
static void i915_record_ring_state(struct drm_device *dev,
+ struct drm_i915_error_state *error,
struct intel_engine_cs *ring,
struct drm_i915_error_ring *ering)
{
@@ -755,18 +828,10 @@ static void i915_record_ring_state(struct drm_device *dev,
if (INTEL_INFO(dev)->gen >= 6) {
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
- ering->semaphore_mboxes[0]
- = I915_READ(RING_SYNC_0(ring->mmio_base));
- ering->semaphore_mboxes[1]
- = I915_READ(RING_SYNC_1(ring->mmio_base));
- ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
- ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
- }
-
- if (HAS_VEBOX(dev)) {
- ering->semaphore_mboxes[2] =
- I915_READ(RING_SYNC_2(ring->mmio_base));
- ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+ if (INTEL_INFO(dev)->gen >= 8)
+ gen8_record_semaphore_state(dev_priv, error, ring, ering);
+ else
+ gen6_record_semaphore_state(dev_priv, ring, ering);
}
if (INTEL_INFO(dev)->gen >= 4) {
@@ -871,6 +936,9 @@ static void i915_gem_record_active_context(struct intel_engine_cs *ring,
return;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ if (!i915_gem_obj_ggtt_bound(obj))
+ continue;
+
if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
break;
@@ -895,7 +963,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].valid = true;
- i915_record_ring_state(dev, ring, &error->ring[i]);
+ i915_record_ring_state(dev, error, ring, &error->ring[i]);
request = i915_gem_find_active_request(ring);
if (request) {
@@ -1032,6 +1100,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
struct drm_device *dev = dev_priv->dev;
+ int i;
/* General organization
* 1. Registers specific to a single generation
@@ -1043,7 +1112,8 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
/* 1: Registers specific to a single generation */
if (IS_VALLEYVIEW(dev)) {
- error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+ error->gtier[0] = I915_READ(GTIER);
+ error->ier = I915_READ(VLV_IER);
error->forcewake = I915_READ(FORCEWAKE_VLV);
}
@@ -1076,16 +1146,18 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
if (HAS_HW_CONTEXTS(dev))
error->ccid = I915_READ(CCID);
- if (HAS_PCH_SPLIT(dev))
- error->ier = I915_READ(DEIER) | I915_READ(GTIER);
- else {
- if (IS_GEN2(dev))
- error->ier = I915_READ16(IER);
- else
- error->ier = I915_READ(IER);
+ if (INTEL_INFO(dev)->gen >= 8) {
+ error->ier = I915_READ(GEN8_DE_MISC_IER);
+ for (i = 0; i < 4; i++)
+ error->gtier[i] = I915_READ(GEN8_GT_IER(i));
+ } else if (HAS_PCH_SPLIT(dev)) {
+ error->ier = I915_READ(DEIER);
+ error->gtier[0] = I915_READ(GTIER);
+ } else if (IS_GEN2(dev)) {
+ error->ier = I915_READ16(IER);
+ } else if (!IS_VALLEYVIEW(dev)) {
+ error->ier = I915_READ(IER);
}
-
- /* 4: Everything else */
error->eir = I915_READ(EIR);
error->pgtbl_er = I915_READ(PGTBL_ER);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c05c84f3f091..390ccc2a3096 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -136,7 +136,7 @@ ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
if ((dev_priv->irq_mask & mask) != 0) {
@@ -151,7 +151,7 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
{
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (!intel_irqs_enabled(dev_priv))
return;
if ((dev_priv->irq_mask & mask) != mask) {
@@ -173,7 +173,7 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
{
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
dev_priv->gt_irq_mask &= ~interrupt_mask;
@@ -182,12 +182,12 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
POSTING_READ(GTIMR);
}
-void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
ilk_update_gt_irq(dev_priv, mask, mask);
}
-void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
ilk_update_gt_irq(dev_priv, mask, 0);
}
@@ -206,7 +206,7 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
new_val = dev_priv->pm_irq_mask;
@@ -220,12 +220,12 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
}
}
-void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
snb_update_pm_irq(dev_priv, mask, mask);
}
-void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
snb_update_pm_irq(dev_priv, mask, 0);
}
@@ -264,7 +264,7 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
new_val = dev_priv->pm_irq_mask;
@@ -278,12 +278,12 @@ static void bdw_update_pm_irq(struct drm_i915_private *dev_priv,
}
}
-void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
bdw_update_pm_irq(dev_priv, mask, mask);
}
-void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
{
bdw_update_pm_irq(dev_priv, mask, 0);
}
@@ -420,7 +420,7 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
assert_spin_locked(&dev_priv->irq_lock);
- if (WARN_ON(dev_priv->pm.irqs_disabled))
+ if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
I915_WRITE(SDEIMR, sdeimr);
@@ -1090,6 +1090,53 @@ static bool intel_hpd_irq_event(struct drm_device *dev,
return true;
}
+static void i915_digport_work_func(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, dig_port_work);
+ unsigned long irqflags;
+ u32 long_port_mask, short_port_mask;
+ struct intel_digital_port *intel_dig_port;
+ int i, ret;
+ u32 old_bits = 0;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ long_port_mask = dev_priv->long_hpd_port_mask;
+ dev_priv->long_hpd_port_mask = 0;
+ short_port_mask = dev_priv->short_hpd_port_mask;
+ dev_priv->short_hpd_port_mask = 0;
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+ for (i = 0; i < I915_MAX_PORTS; i++) {
+ bool valid = false;
+ bool long_hpd = false;
+ intel_dig_port = dev_priv->hpd_irq_port[i];
+ if (!intel_dig_port || !intel_dig_port->hpd_pulse)
+ continue;
+
+ if (long_port_mask & (1 << i)) {
+ valid = true;
+ long_hpd = true;
+ } else if (short_port_mask & (1 << i))
+ valid = true;
+
+ if (valid) {
+ ret = intel_dig_port->hpd_pulse(intel_dig_port, long_hpd);
+ if (ret == true) {
+ /* if we get true fallback to old school hpd */
+ old_bits |= (1 << intel_dig_port->base.hpd_pin);
+ }
+ }
+ }
+
+ if (old_bits) {
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ dev_priv->hpd_event_bits |= old_bits;
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+ schedule_work(&dev_priv->hotplug_work);
+ }
+}
+
/*
* Handle hotplug events outside the interrupt handler proper.
*/
@@ -1109,10 +1156,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
bool changed = false;
u32 hpd_event_bits;
- /* HPD irq before everything is fully set up. */
- if (!dev_priv->enable_hotplug_processing)
- return;
-
mutex_lock(&mode_config->mutex);
DRM_DEBUG_KMS("running encoder hotplug functions\n");
@@ -1122,6 +1165,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
dev_priv->hpd_event_bits = 0;
list_for_each_entry(connector, &mode_config->connector_list, head) {
intel_connector = to_intel_connector(connector);
+ if (!intel_connector->encoder)
+ continue;
intel_encoder = intel_connector->encoder;
if (intel_encoder->hpd_pin > HPD_NONE &&
dev_priv->hpd_stats[intel_encoder->hpd_pin].hpd_mark == HPD_MARK_DISABLED &&
@@ -1152,6 +1197,8 @@ static void i915_hotplug_work_func(struct work_struct *work)
list_for_each_entry(connector, &mode_config->connector_list, head) {
intel_connector = to_intel_connector(connector);
+ if (!intel_connector->encoder)
+ continue;
intel_encoder = intel_connector->encoder;
if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
if (intel_encoder->hot_plug)
@@ -1218,10 +1265,138 @@ static void notify_ring(struct drm_device *dev,
trace_i915_gem_request_complete(ring);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ intel_notify_mmio_flip(ring);
+
wake_up_all(&ring->irq_queue);
i915_queue_hangcheck(dev);
}
+static u32 vlv_c0_residency(struct drm_i915_private *dev_priv,
+ struct intel_rps_ei *rps_ei)
+{
+ u32 cz_ts, cz_freq_khz;
+ u32 render_count, media_count;
+ u32 elapsed_render, elapsed_media, elapsed_time;
+ u32 residency = 0;
+
+ cz_ts = vlv_punit_read(dev_priv, PUNIT_REG_CZ_TIMESTAMP);
+ cz_freq_khz = DIV_ROUND_CLOSEST(dev_priv->mem_freq * 1000, 4);
+
+ render_count = I915_READ(VLV_RENDER_C0_COUNT_REG);
+ media_count = I915_READ(VLV_MEDIA_C0_COUNT_REG);
+
+ if (rps_ei->cz_clock == 0) {
+ rps_ei->cz_clock = cz_ts;
+ rps_ei->render_c0 = render_count;
+ rps_ei->media_c0 = media_count;
+
+ return dev_priv->rps.cur_freq;
+ }
+
+ elapsed_time = cz_ts - rps_ei->cz_clock;
+ rps_ei->cz_clock = cz_ts;
+
+ elapsed_render = render_count - rps_ei->render_c0;
+ rps_ei->render_c0 = render_count;
+
+ elapsed_media = media_count - rps_ei->media_c0;
+ rps_ei->media_c0 = media_count;
+
+ /* Convert all the counters into common unit of milli sec */
+ elapsed_time /= VLV_CZ_CLOCK_TO_MILLI_SEC;
+ elapsed_render /= cz_freq_khz;
+ elapsed_media /= cz_freq_khz;
+
+ /*
+ * Calculate overall C0 residency percentage
+ * only if elapsed time is non zero
+ */
+ if (elapsed_time) {
+ residency =
+ ((max(elapsed_render, elapsed_media) * 100)
+ / elapsed_time);
+ }
+
+ return residency;
+}
+
+/**
+ * vlv_calc_delay_from_C0_counters - Increase/Decrease freq based on GPU
+ * busy-ness calculated from C0 counters of render & media power wells
+ * @dev_priv: DRM device private
+ *
+ */
+static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv)
+{
+ u32 residency_C0_up = 0, residency_C0_down = 0;
+ u8 new_delay, adj;
+
+ dev_priv->rps.ei_interrupt_count++;
+
+ WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+
+ if (dev_priv->rps.up_ei.cz_clock == 0) {
+ vlv_c0_residency(dev_priv, &dev_priv->rps.up_ei);
+ vlv_c0_residency(dev_priv, &dev_priv->rps.down_ei);
+ return dev_priv->rps.cur_freq;
+ }
+
+
+ /*
+ * To down throttle, C0 residency should be less than down threshold
+ * for continous EI intervals. So calculate down EI counters
+ * once in VLV_INT_COUNT_FOR_DOWN_EI
+ */
+ if (dev_priv->rps.ei_interrupt_count == VLV_INT_COUNT_FOR_DOWN_EI) {
+
+ dev_priv->rps.ei_interrupt_count = 0;
+
+ residency_C0_down = vlv_c0_residency(dev_priv,
+ &dev_priv->rps.down_ei);
+ } else {
+ residency_C0_up = vlv_c0_residency(dev_priv,
+ &dev_priv->rps.up_ei);
+ }
+
+ new_delay = dev_priv->rps.cur_freq;
+
+ adj = dev_priv->rps.last_adj;
+ /* C0 residency is greater than UP threshold. Increase Frequency */
+ if (residency_C0_up >= VLV_RP_UP_EI_THRESHOLD) {
+ if (adj > 0)
+ adj *= 2;
+ else
+ adj = 1;
+
+ if (dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit)
+ new_delay = dev_priv->rps.cur_freq + adj;
+
+ /*
+ * For better performance, jump directly
+ * to RPe if we're below it.
+ */
+ if (new_delay < dev_priv->rps.efficient_freq)
+ new_delay = dev_priv->rps.efficient_freq;
+
+ } else if (!dev_priv->rps.ei_interrupt_count &&
+ (residency_C0_down < VLV_RP_DOWN_EI_THRESHOLD)) {
+ if (adj < 0)
+ adj *= 2;
+ else
+ adj = -1;
+ /*
+ * This means, C0 residency is less than down threshold over
+ * a period of VLV_INT_COUNT_FOR_DOWN_EI. So, reduce the freq
+ */
+ if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit)
+ new_delay = dev_priv->rps.cur_freq + adj;
+ }
+
+ return new_delay;
+}
+
static void gen6_pm_rps_work(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
@@ -1232,11 +1407,11 @@ static void gen6_pm_rps_work(struct work_struct *work)
spin_lock_irq(&dev_priv->irq_lock);
pm_iir = dev_priv->rps.pm_iir;
dev_priv->rps.pm_iir = 0;
- if (IS_BROADWELL(dev_priv->dev))
- bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+ if (INTEL_INFO(dev_priv->dev)->gen >= 8)
+ gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
else {
/* Make sure not to corrupt PMIMR state used by ringbuffer */
- snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+ gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
}
spin_unlock_irq(&dev_priv->irq_lock);
@@ -1252,8 +1427,10 @@ static void gen6_pm_rps_work(struct work_struct *work)
if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
if (adj > 0)
adj *= 2;
- else
- adj = 1;
+ else {
+ /* CHV needs even encode values */
+ adj = IS_CHERRYVIEW(dev_priv->dev) ? 2 : 1;
+ }
new_delay = dev_priv->rps.cur_freq + adj;
/*
@@ -1268,11 +1445,15 @@ static void gen6_pm_rps_work(struct work_struct *work)
else
new_delay = dev_priv->rps.min_freq_softlimit;
adj = 0;
+ } else if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
+ new_delay = vlv_calc_delay_from_C0_counters(dev_priv);
} else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
if (adj < 0)
adj *= 2;
- else
- adj = -1;
+ else {
+ /* CHV needs even encode values */
+ adj = IS_CHERRYVIEW(dev_priv->dev) ? -2 : -1;
+ }
new_delay = dev_priv->rps.cur_freq + adj;
} else { /* unknown event */
new_delay = dev_priv->rps.cur_freq;
@@ -1372,7 +1553,7 @@ static void ivybridge_parity_work(struct work_struct *work)
out:
WARN_ON(dev_priv->l3_parity.which_slice);
spin_lock_irqsave(&dev_priv->irq_lock, flags);
- ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
+ gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
mutex_unlock(&dev_priv->dev->struct_mutex);
@@ -1386,7 +1567,7 @@ static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir)
return;
spin_lock(&dev_priv->irq_lock);
- ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
+ gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
spin_unlock(&dev_priv->irq_lock);
iir &= GT_PARITY_ERROR(dev);
@@ -1441,7 +1622,7 @@ static void gen8_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
spin_lock(&dev_priv->irq_lock);
dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
- bdw_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+ gen8_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
spin_unlock(&dev_priv->irq_lock);
queue_work(dev_priv->wq, &dev_priv->rps.work);
@@ -1458,6 +1639,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
tmp = I915_READ(GEN8_GT_IIR(0));
if (tmp) {
+ I915_WRITE(GEN8_GT_IIR(0), tmp);
ret = IRQ_HANDLED;
rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
@@ -1465,7 +1647,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
notify_ring(dev, &dev_priv->ring[RCS]);
if (bcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[BCS]);
- I915_WRITE(GEN8_GT_IIR(0), tmp);
} else
DRM_ERROR("The master control interrupt lied (GT0)!\n");
}
@@ -1473,6 +1654,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
tmp = I915_READ(GEN8_GT_IIR(1));
if (tmp) {
+ I915_WRITE(GEN8_GT_IIR(1), tmp);
ret = IRQ_HANDLED;
vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
if (vcs & GT_RENDER_USER_INTERRUPT)
@@ -1480,7 +1662,6 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VCS2]);
- I915_WRITE(GEN8_GT_IIR(1), tmp);
} else
DRM_ERROR("The master control interrupt lied (GT1)!\n");
}
@@ -1488,10 +1669,10 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
if (master_ctl & GEN8_GT_PM_IRQ) {
tmp = I915_READ(GEN8_GT_IIR(2));
if (tmp & dev_priv->pm_rps_events) {
- ret = IRQ_HANDLED;
- gen8_rps_irq_handler(dev_priv, tmp);
I915_WRITE(GEN8_GT_IIR(2),
tmp & dev_priv->pm_rps_events);
+ ret = IRQ_HANDLED;
+ gen8_rps_irq_handler(dev_priv, tmp);
} else
DRM_ERROR("The master control interrupt lied (PM)!\n");
}
@@ -1499,11 +1680,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
if (master_ctl & GEN8_GT_VECS_IRQ) {
tmp = I915_READ(GEN8_GT_IIR(3));
if (tmp) {
+ I915_WRITE(GEN8_GT_IIR(3), tmp);
ret = IRQ_HANDLED;
vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, &dev_priv->ring[VECS]);
- I915_WRITE(GEN8_GT_IIR(3), tmp);
} else
DRM_ERROR("The master control interrupt lied (GT3)!\n");
}
@@ -1514,23 +1695,104 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
#define HPD_STORM_DETECT_PERIOD 1000
#define HPD_STORM_THRESHOLD 5
+static int ilk_port_to_hotplug_shift(enum port port)
+{
+ switch (port) {
+ case PORT_A:
+ case PORT_E:
+ default:
+ return -1;
+ case PORT_B:
+ return 0;
+ case PORT_C:
+ return 8;
+ case PORT_D:
+ return 16;
+ }
+}
+
+static int g4x_port_to_hotplug_shift(enum port port)
+{
+ switch (port) {
+ case PORT_A:
+ case PORT_E:
+ default:
+ return -1;
+ case PORT_B:
+ return 17;
+ case PORT_C:
+ return 19;
+ case PORT_D:
+ return 21;
+ }
+}
+
+static inline enum port get_port_from_pin(enum hpd_pin pin)
+{
+ switch (pin) {
+ case HPD_PORT_B:
+ return PORT_B;
+ case HPD_PORT_C:
+ return PORT_C;
+ case HPD_PORT_D:
+ return PORT_D;
+ default:
+ return PORT_A; /* no hpd */
+ }
+}
+
static inline void intel_hpd_irq_handler(struct drm_device *dev,
u32 hotplug_trigger,
+ u32 dig_hotplug_reg,
const u32 *hpd)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
+ enum port port;
bool storm_detected = false;
+ bool queue_dig = false, queue_hp = false;
+ u32 dig_shift;
+ u32 dig_port_mask = 0;
if (!hotplug_trigger)
return;
- DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
- hotplug_trigger);
+ DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x, dig 0x%08x\n",
+ hotplug_trigger, dig_hotplug_reg);
spin_lock(&dev_priv->irq_lock);
for (i = 1; i < HPD_NUM_PINS; i++) {
+ if (!(hpd[i] & hotplug_trigger))
+ continue;
+
+ port = get_port_from_pin(i);
+ if (port && dev_priv->hpd_irq_port[port]) {
+ bool long_hpd;
+
+ if (IS_G4X(dev)) {
+ dig_shift = g4x_port_to_hotplug_shift(port);
+ long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
+ } else {
+ dig_shift = ilk_port_to_hotplug_shift(port);
+ long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
+ }
+
+ DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port, long_hpd);
+ /* for long HPD pulses we want to have the digital queue happen,
+ but we still want HPD storm detection to function. */
+ if (long_hpd) {
+ dev_priv->long_hpd_port_mask |= (1 << port);
+ dig_port_mask |= hpd[i];
+ } else {
+ /* for short HPD just trigger the digital queue */
+ dev_priv->short_hpd_port_mask |= (1 << port);
+ hotplug_trigger &= ~hpd[i];
+ }
+ queue_dig = true;
+ }
+ }
+ for (i = 1; i < HPD_NUM_PINS; i++) {
if (hpd[i] & hotplug_trigger &&
dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {
/*
@@ -1550,7 +1812,11 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
continue;
- dev_priv->hpd_event_bits |= (1 << i);
+ if (!(dig_port_mask & hpd[i])) {
+ dev_priv->hpd_event_bits |= (1 << i);
+ queue_hp = true;
+ }
+
if (!time_in_range(jiffies, dev_priv->hpd_stats[i].hpd_last_jiffies,
dev_priv->hpd_stats[i].hpd_last_jiffies
+ msecs_to_jiffies(HPD_STORM_DETECT_PERIOD))) {
@@ -1579,7 +1845,10 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
* queue for otherwise the flush_work in the pageflip code will
* deadlock.
*/
- schedule_work(&dev_priv->hotplug_work);
+ if (queue_dig)
+ queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
+ if (queue_hp)
+ schedule_work(&dev_priv->hotplug_work);
}
static void gmbus_irq_handler(struct drm_device *dev)
@@ -1700,7 +1969,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
if (pm_iir & dev_priv->pm_rps_events) {
spin_lock(&dev_priv->irq_lock);
dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
- snb_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+ gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
spin_unlock(&dev_priv->irq_lock);
queue_work(dev_priv->wq, &dev_priv->rps.work);
@@ -1809,26 +2078,28 @@ static void i9xx_hpd_irq_handler(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
- if (IS_G4X(dev)) {
- u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
+ if (hotplug_status) {
+ I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+ /*
+ * Make sure hotplug status is cleared before we clear IIR, or else we
+ * may miss hotplug events.
+ */
+ POSTING_READ(PORT_HOTPLUG_STAT);
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_g4x);
- } else {
- u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
+ if (IS_G4X(dev)) {
+ u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
- }
+ intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_g4x);
+ } else {
+ u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
- if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
- hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
- dp_aux_irq_handler(dev);
+ intel_hpd_irq_handler(dev, hotplug_trigger, 0, hpd_status_i915);
+ }
- I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
- /*
- * Make sure hotplug status is cleared before we clear IIR, or else we
- * may miss hotplug events.
- */
- POSTING_READ(PORT_HOTPLUG_STAT);
+ if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
+ hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+ dp_aux_irq_handler(dev);
+ }
}
static irqreturn_t valleyview_irq_handler(int irq, void *arg)
@@ -1839,29 +2110,36 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
irqreturn_t ret = IRQ_NONE;
while (true) {
- iir = I915_READ(VLV_IIR);
+ /* Find, clear, then process each source of interrupt */
+
gt_iir = I915_READ(GTIIR);
+ if (gt_iir)
+ I915_WRITE(GTIIR, gt_iir);
+
pm_iir = I915_READ(GEN6_PMIIR);
+ if (pm_iir)
+ I915_WRITE(GEN6_PMIIR, pm_iir);
+
+ iir = I915_READ(VLV_IIR);
+ if (iir) {
+ /* Consume port before clearing IIR or we'll miss events */
+ if (iir & I915_DISPLAY_PORT_INTERRUPT)
+ i9xx_hpd_irq_handler(dev);
+ I915_WRITE(VLV_IIR, iir);
+ }
if (gt_iir == 0 && pm_iir == 0 && iir == 0)
goto out;
ret = IRQ_HANDLED;
- snb_gt_irq_handler(dev, dev_priv, gt_iir);
-
- valleyview_pipestat_irq_handler(dev, iir);
-
- /* Consume port. Then clear IIR or we'll miss events */
- if (iir & I915_DISPLAY_PORT_INTERRUPT)
- i9xx_hpd_irq_handler(dev);
-
+ if (gt_iir)
+ snb_gt_irq_handler(dev, dev_priv, gt_iir);
if (pm_iir)
gen6_rps_irq_handler(dev_priv, pm_iir);
-
- I915_WRITE(GTIIR, gt_iir);
- I915_WRITE(GEN6_PMIIR, pm_iir);
- I915_WRITE(VLV_IIR, iir);
+ /* Call regardless, as some status bits might not be
+ * signalled in iir */
+ valleyview_pipestat_irq_handler(dev, iir);
}
out:
@@ -1882,21 +2160,27 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
if (master_ctl == 0 && iir == 0)
break;
+ ret = IRQ_HANDLED;
+
I915_WRITE(GEN8_MASTER_IRQ, 0);
- gen8_gt_irq_handler(dev, dev_priv, master_ctl);
+ /* Find, clear, then process each source of interrupt */
- valleyview_pipestat_irq_handler(dev, iir);
+ if (iir) {
+ /* Consume port before clearing IIR or we'll miss events */
+ if (iir & I915_DISPLAY_PORT_INTERRUPT)
+ i9xx_hpd_irq_handler(dev);
+ I915_WRITE(VLV_IIR, iir);
+ }
- /* Consume port. Then clear IIR or we'll miss events */
- i9xx_hpd_irq_handler(dev);
+ gen8_gt_irq_handler(dev, dev_priv, master_ctl);
- I915_WRITE(VLV_IIR, iir);
+ /* Call regardless, as some status bits might not be
+ * signalled in iir */
+ valleyview_pipestat_irq_handler(dev, iir);
I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
POSTING_READ(GEN8_MASTER_IRQ);
-
- ret = IRQ_HANDLED;
}
return ret;
@@ -1907,8 +2191,12 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK;
+ u32 dig_hotplug_reg;
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+ I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
+
+ intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_ibx);
if (pch_iir & SDE_AUDIO_POWER_MASK) {
int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -2014,8 +2302,12 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe;
u32 hotplug_trigger = pch_iir & SDE_HOTPLUG_MASK_CPT;
+ u32 dig_hotplug_reg;
+
+ dig_hotplug_reg = I915_READ(PCH_PORT_HOTPLUG);
+ I915_WRITE(PCH_PORT_HOTPLUG, dig_hotplug_reg);
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
+ intel_hpd_irq_handler(dev, hotplug_trigger, dig_hotplug_reg, hpd_cpt);
if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) {
int port = ffs((pch_iir & SDE_AUDIO_POWER_MASK_CPT) >>
@@ -2132,6 +2424,14 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir)
}
}
+/*
+ * To handle irqs with the minimum potential races with fresh interrupts, we:
+ * 1 - Disable Master Interrupt Control.
+ * 2 - Find the source(s) of the interrupt.
+ * 3 - Clear the Interrupt Identity bits (IIR).
+ * 4 - Process the interrupt(s) that had bits set in the IIRs.
+ * 5 - Re-enable Master Interrupt Control.
+ */
static irqreturn_t ironlake_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
@@ -2159,32 +2459,34 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
POSTING_READ(SDEIER);
}
+ /* Find, clear, then process each source of interrupt */
+
gt_iir = I915_READ(GTIIR);
if (gt_iir) {
+ I915_WRITE(GTIIR, gt_iir);
+ ret = IRQ_HANDLED;
if (INTEL_INFO(dev)->gen >= 6)
snb_gt_irq_handler(dev, dev_priv, gt_iir);
else
ilk_gt_irq_handler(dev, dev_priv, gt_iir);
- I915_WRITE(GTIIR, gt_iir);
- ret = IRQ_HANDLED;
}
de_iir = I915_READ(DEIIR);
if (de_iir) {
+ I915_WRITE(DEIIR, de_iir);
+ ret = IRQ_HANDLED;
if (INTEL_INFO(dev)->gen >= 7)
ivb_display_irq_handler(dev, de_iir);
else
ilk_display_irq_handler(dev, de_iir);
- I915_WRITE(DEIIR, de_iir);
- ret = IRQ_HANDLED;
}
if (INTEL_INFO(dev)->gen >= 6) {
u32 pm_iir = I915_READ(GEN6_PMIIR);
if (pm_iir) {
- gen6_rps_irq_handler(dev_priv, pm_iir);
I915_WRITE(GEN6_PMIIR, pm_iir);
ret = IRQ_HANDLED;
+ gen6_rps_irq_handler(dev_priv, pm_iir);
}
}
@@ -2215,36 +2517,36 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
I915_WRITE(GEN8_MASTER_IRQ, 0);
POSTING_READ(GEN8_MASTER_IRQ);
+ /* Find, clear, then process each source of interrupt */
+
ret = gen8_gt_irq_handler(dev, dev_priv, master_ctl);
if (master_ctl & GEN8_DE_MISC_IRQ) {
tmp = I915_READ(GEN8_DE_MISC_IIR);
- if (tmp & GEN8_DE_MISC_GSE)
- intel_opregion_asle_intr(dev);
- else if (tmp)
- DRM_ERROR("Unexpected DE Misc interrupt\n");
- else
- DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
-
if (tmp) {
I915_WRITE(GEN8_DE_MISC_IIR, tmp);
ret = IRQ_HANDLED;
+ if (tmp & GEN8_DE_MISC_GSE)
+ intel_opregion_asle_intr(dev);
+ else
+ DRM_ERROR("Unexpected DE Misc interrupt\n");
}
+ else
+ DRM_ERROR("The master control interrupt lied (DE MISC)!\n");
}
if (master_ctl & GEN8_DE_PORT_IRQ) {
tmp = I915_READ(GEN8_DE_PORT_IIR);
- if (tmp & GEN8_AUX_CHANNEL_A)
- dp_aux_irq_handler(dev);
- else if (tmp)
- DRM_ERROR("Unexpected DE Port interrupt\n");
- else
- DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
-
if (tmp) {
I915_WRITE(GEN8_DE_PORT_IIR, tmp);
ret = IRQ_HANDLED;
+ if (tmp & GEN8_AUX_CHANNEL_A)
+ dp_aux_irq_handler(dev);
+ else
+ DRM_ERROR("Unexpected DE Port interrupt\n");
}
+ else
+ DRM_ERROR("The master control interrupt lied (DE PORT)!\n");
}
for_each_pipe(pipe) {
@@ -2254,33 +2556,32 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
continue;
pipe_iir = I915_READ(GEN8_DE_PIPE_IIR(pipe));
- if (pipe_iir & GEN8_PIPE_VBLANK)
- intel_pipe_handle_vblank(dev, pipe);
-
- if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
- intel_prepare_page_flip(dev, pipe);
- intel_finish_page_flip_plane(dev, pipe);
- }
+ if (pipe_iir) {
+ ret = IRQ_HANDLED;
+ I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+ if (pipe_iir & GEN8_PIPE_VBLANK)
+ intel_pipe_handle_vblank(dev, pipe);
- if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
- hsw_pipe_crc_irq_handler(dev, pipe);
+ if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
+ intel_prepare_page_flip(dev, pipe);
+ intel_finish_page_flip_plane(dev, pipe);
+ }
- if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
- if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
- false))
- DRM_ERROR("Pipe %c FIFO underrun\n",
- pipe_name(pipe));
- }
+ if (pipe_iir & GEN8_PIPE_CDCLK_CRC_DONE)
+ hsw_pipe_crc_irq_handler(dev, pipe);
- if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
- DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
- pipe_name(pipe),
- pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
- }
+ if (pipe_iir & GEN8_PIPE_FIFO_UNDERRUN) {
+ if (intel_set_cpu_fifo_underrun_reporting(dev, pipe,
+ false))
+ DRM_ERROR("Pipe %c FIFO underrun\n",
+ pipe_name(pipe));
+ }
- if (pipe_iir) {
- ret = IRQ_HANDLED;
- I915_WRITE(GEN8_DE_PIPE_IIR(pipe), pipe_iir);
+ if (pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS) {
+ DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
+ pipe_name(pipe),
+ pipe_iir & GEN8_DE_PIPE_IRQ_FAULT_ERRORS);
+ }
} else
DRM_ERROR("The master control interrupt lied (DE PIPE)!\n");
}
@@ -2292,13 +2593,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
* on older pch-split platforms. But this needs testing.
*/
u32 pch_iir = I915_READ(SDEIIR);
-
- cpt_irq_handler(dev, pch_iir);
-
if (pch_iir) {
I915_WRITE(SDEIIR, pch_iir);
ret = IRQ_HANDLED;
- }
+ cpt_irq_handler(dev, pch_iir);
+ } else
+ DRM_ERROR("The master control interrupt lied (SDE)!\n");
+
}
I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -2753,12 +3054,7 @@ static bool
ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
{
if (INTEL_INFO(dev)->gen >= 8) {
- /*
- * FIXME: gen8 semaphore support - currently we don't emit
- * semaphores on bdw anyway, but this needs to be addressed when
- * we merge that code.
- */
- return false;
+ return (ipehr >> 23) == 0x1c;
} else {
ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
@@ -2767,19 +3063,20 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
}
static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr)
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr, u64 offset)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct intel_engine_cs *signaller;
int i;
if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
- /*
- * FIXME: gen8 semaphore support - currently we don't emit
- * semaphores on bdw anyway, but this needs to be addressed when
- * we merge that code.
- */
- return NULL;
+ for_each_ring(signaller, dev_priv, i) {
+ if (ring == signaller)
+ continue;
+
+ if (offset == signaller->semaphore.signal_ggtt[ring->id])
+ return signaller;
+ }
} else {
u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
@@ -2792,8 +3089,8 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr)
}
}
- DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x\n",
- ring->id, ipehr);
+ DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n",
+ ring->id, ipehr, offset);
return NULL;
}
@@ -2803,7 +3100,8 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
u32 cmd, ipehr, head;
- int i;
+ u64 offset = 0;
+ int i, backwards;
ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
@@ -2812,13 +3110,15 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
/*
* HEAD is likely pointing to the dword after the actual command,
* so scan backwards until we find the MBOX. But limit it to just 3
- * dwords. Note that we don't care about ACTHD here since that might
+ * or 4 dwords depending on the semaphore wait command size.
+ * Note that we don't care about ACTHD here since that might
* point at at batch, and semaphores are always emitted into the
* ringbuffer itself.
*/
head = I915_READ_HEAD(ring) & HEAD_ADDR;
+ backwards = (INTEL_INFO(ring->dev)->gen >= 8) ? 5 : 4;
- for (i = 4; i; --i) {
+ for (i = backwards; i; --i) {
/*
* Be paranoid and presume the hw has gone off into the wild -
* our ring is smaller than what the hardware (and hence
@@ -2838,7 +3138,12 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
return NULL;
*seqno = ioread32(ring->buffer->virtual_start + head + 4) + 1;
- return semaphore_wait_to_signaller_ring(ring, ipehr);
+ if (INTEL_INFO(ring->dev)->gen >= 8) {
+ offset = ioread32(ring->buffer->virtual_start + head + 12);
+ offset <<= 32;
+ offset = ioread32(ring->buffer->virtual_start + head + 8);
+ }
+ return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
}
static int semaphore_passed(struct intel_engine_cs *ring)
@@ -2884,8 +3189,14 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp;
- if (ring->hangcheck.acthd != acthd)
- return HANGCHECK_ACTIVE;
+ if (acthd != ring->hangcheck.acthd) {
+ if (acthd > ring->hangcheck.max_acthd) {
+ ring->hangcheck.max_acthd = acthd;
+ return HANGCHECK_ACTIVE;
+ }
+
+ return HANGCHECK_ACTIVE_LOOP;
+ }
if (IS_GEN2(dev))
return HANGCHECK_HUNG;
@@ -2996,8 +3307,9 @@ static void i915_hangcheck_elapsed(unsigned long data)
switch (ring->hangcheck.action) {
case HANGCHECK_IDLE:
case HANGCHECK_WAIT:
- break;
case HANGCHECK_ACTIVE:
+ break;
+ case HANGCHECK_ACTIVE_LOOP:
ring->hangcheck.score += BUSY;
break;
case HANGCHECK_KICK:
@@ -3017,6 +3329,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
*/
if (ring->hangcheck.score > 0)
ring->hangcheck.score--;
+
+ ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
}
ring->hangcheck.seqno = seqno;
@@ -3159,7 +3473,9 @@ static void gen8_irq_reset(struct drm_device *dev)
gen8_gt_irq_reset(dev_priv);
for_each_pipe(pipe)
- GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
+ if (intel_display_power_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(pipe)))
+ GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
GEN5_IRQ_RESET(GEN8_DE_PORT_);
GEN5_IRQ_RESET(GEN8_DE_MISC_);
@@ -3168,6 +3484,18 @@ static void gen8_irq_reset(struct drm_device *dev)
ibx_irq_reset(dev);
}
+void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv)
+{
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+ GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_B, dev_priv->de_irq_mask[PIPE_B],
+ ~dev_priv->de_irq_mask[PIPE_B]);
+ GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_C, dev_priv->de_irq_mask[PIPE_C],
+ ~dev_priv->de_irq_mask[PIPE_C]);
+ spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+}
+
static void cherryview_irq_preinstall(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3492,8 +3820,11 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
for_each_pipe(pipe)
- GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe],
- de_pipe_enables);
+ if (intel_display_power_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(pipe)))
+ GEN8_IRQ_INIT_NDX(DE_PIPE, pipe,
+ dev_priv->de_irq_mask[pipe],
+ de_pipe_enables);
GEN5_IRQ_INIT(GEN8_DE_PORT_, ~GEN8_AUX_CHANNEL_A, GEN8_AUX_CHANNEL_A);
}
@@ -4324,12 +4655,17 @@ void intel_irq_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+ INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);
INIT_WORK(&dev_priv->gpu_error.work, i915_error_work_func);
INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
/* Let's track the enabled rps events */
- dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
+ if (IS_VALLEYVIEW(dev))
+ /* WaGsvRC0ResidenncyMethod:VLV */
+ dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
+ else
+ dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
setup_timer(&dev_priv->gpu_error.hangcheck_timer,
i915_hangcheck_elapsed,
@@ -4339,6 +4675,9 @@ void intel_irq_init(struct drm_device *dev)
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
+ /* Haven't installed the IRQ handler yet */
+ dev_priv->pm._irqs_disabled = true;
+
if (IS_GEN2(dev)) {
dev->max_vblank_count = 0;
dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
@@ -4426,7 +4765,9 @@ void intel_hpd_init(struct drm_device *dev)
list_for_each_entry(connector, &mode_config->connector_list, head) {
struct intel_connector *intel_connector = to_intel_connector(connector);
connector->polled = intel_connector->polled;
- if (!connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+ if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ if (intel_connector->mst_port)
connector->polled = DRM_CONNECTOR_POLL_HPD;
}
@@ -4444,7 +4785,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
dev->driver->irq_uninstall(dev);
- dev_priv->pm.irqs_disabled = true;
+ dev_priv->pm._irqs_disabled = true;
}
/* Restore interrupts so we can recover from runtime PM. */
@@ -4452,7 +4793,7 @@ void intel_runtime_pm_restore_interrupts(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- dev_priv->pm.irqs_disabled = false;
+ dev_priv->pm._irqs_disabled = false;
dev->driver->irq_preinstall(dev);
dev->driver->irq_postinstall(dev);
}
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d05a2afa17dc..7f84dd263ee8 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -48,6 +48,8 @@ struct i915_params i915 __read_mostly = {
.disable_display = 0,
.enable_cmd_parser = 1,
.disable_vtd_wa = 0,
+ .use_mmio_flip = 0,
+ .mmio_debug = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -156,3 +158,12 @@ MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled [default], 0=disabled)");
+
+module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600);
+MODULE_PARM_DESC(use_mmio_flip,
+ "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");
+
+module_param_named(mmio_debug, i915.mmio_debug, bool, 0600);
+MODULE_PARM_DESC(mmio_debug,
+ "Enable the MMIO debug code (default: false). This may negatively "
+ "affect performance.");
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a5bab61bfc00..e4d7607da2c4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -29,8 +29,8 @@
#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
#define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
-#define _PIPE3(pipe, a, b, c) (pipe < 2 ? _PIPE(pipe, a, b) : c)
-#define _PORT3(port, a, b, c) (port < 2 ? _PORT(port, a, b) : c)
+#define _PIPE3(pipe, a, b, c) ((pipe) == PIPE_A ? (a) : \
+ (pipe) == PIPE_B ? (b) : (c))
#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a))
#define _MASKED_BIT_DISABLE(a) ((a) << 16)
@@ -240,7 +240,7 @@
#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19)
#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
-#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */
+#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6, gen7 */
#define MI_SEMAPHORE_GLOBAL_GTT (1<<22)
#define MI_SEMAPHORE_UPDATE (1<<21)
#define MI_SEMAPHORE_COMPARE (1<<20)
@@ -266,6 +266,11 @@
#define MI_RESTORE_EXT_STATE_EN (1<<2)
#define MI_FORCE_RESTORE (1<<1)
#define MI_RESTORE_INHIBIT (1<<0)
+#define MI_SEMAPHORE_SIGNAL MI_INSTR(0x1b, 0) /* GEN8+ */
+#define MI_SEMAPHORE_TARGET(engine) ((engine)<<15)
+#define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */
+#define MI_SEMAPHORE_POLL (1<<15)
+#define MI_SEMAPHORE_SAD_GTE_SDD (1<<12)
#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1)
#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
@@ -360,6 +365,7 @@
#define PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE (1<<10) /* GM45+ only */
#define PIPE_CONTROL_INDIRECT_STATE_DISABLE (1<<9)
#define PIPE_CONTROL_NOTIFY (1<<8)
+#define PIPE_CONTROL_FLUSH_ENABLE (1<<7) /* gen7+ */
#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1<<4)
#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1<<3)
#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1<<2)
@@ -525,10 +531,21 @@ enum punit_power_well {
#define PUNIT_REG_GPU_FREQ_STS 0xd8
#define GENFREQSTATUS (1<<0)
#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc
+#define PUNIT_REG_CZ_TIMESTAMP 0xce
#define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */
#define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */
+#define PUNIT_GPU_STATUS_REG 0xdb
+#define PUNIT_GPU_STATUS_MAX_FREQ_SHIFT 16
+#define PUNIT_GPU_STATUS_MAX_FREQ_MASK 0xff
+#define PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT 8
+#define PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK 0xff
+
+#define PUNIT_GPU_DUTYCYCLE_REG 0xdf
+#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT 8
+#define PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK 0xff
+
#define IOSF_NC_FB_GFX_FREQ_FUSE 0x1c
#define FB_GFX_MAX_FREQ_FUSE_SHIFT 3
#define FB_GFX_MAX_FREQ_FUSE_MASK 0x000007f8
@@ -540,6 +557,11 @@ enum punit_power_well {
#define FB_FMAX_VMIN_FREQ_LO_SHIFT 27
#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000
+#define VLV_CZ_CLOCK_TO_MILLI_SEC 100000
+#define VLV_RP_UP_EI_THRESHOLD 90
+#define VLV_RP_DOWN_EI_THRESHOLD 70
+#define VLV_INT_COUNT_FOR_DOWN_EI 5
+
/* vlv2 north clock has */
#define CCK_FUSE_REG 0x8
#define CCK_FUSE_HPLL_FREQ_MASK 0x3
@@ -574,6 +596,11 @@ enum punit_power_well {
#define DSI_PLL_M1_DIV_SHIFT 0
#define DSI_PLL_M1_DIV_MASK (0x1ff << 0)
#define CCK_DISPLAY_CLOCK_CONTROL 0x6b
+#define DISPLAY_TRUNK_FORCE_ON (1 << 17)
+#define DISPLAY_TRUNK_FORCE_OFF (1 << 16)
+#define DISPLAY_FREQUENCY_STATUS (0x1f << 8)
+#define DISPLAY_FREQUENCY_STATUS_SHIFT 8
+#define DISPLAY_FREQUENCY_VALUES (0x1f << 0)
/**
* DOC: DPIO
@@ -761,6 +788,8 @@ enum punit_power_well {
#define _VLV_PCS_DW8_CH0 0x8220
#define _VLV_PCS_DW8_CH1 0x8420
+#define CHV_PCS_USEDCLKCHANNEL_OVRRIDE (1 << 20)
+#define CHV_PCS_USEDCLKCHANNEL (1 << 21)
#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1)
#define _VLV_PCS01_DW8_CH0 0x0220
@@ -869,6 +898,16 @@ enum punit_power_well {
#define DPIO_CHV_PROP_COEFF_SHIFT 0
#define CHV_PLL_DW6(ch) _PIPE(ch, _CHV_PLL_DW6_CH0, _CHV_PLL_DW6_CH1)
+#define _CHV_CMN_DW5_CH0 0x8114
+#define CHV_BUFRIGHTENA1_DISABLE (0 << 20)
+#define CHV_BUFRIGHTENA1_NORMAL (1 << 20)
+#define CHV_BUFRIGHTENA1_FORCE (3 << 20)
+#define CHV_BUFRIGHTENA1_MASK (3 << 20)
+#define CHV_BUFLEFTENA1_DISABLE (0 << 22)
+#define CHV_BUFLEFTENA1_NORMAL (1 << 22)
+#define CHV_BUFLEFTENA1_FORCE (3 << 22)
+#define CHV_BUFLEFTENA1_MASK (3 << 22)
+
#define _CHV_CMN_DW13_CH0 0x8134
#define _CHV_CMN_DW0_CH1 0x8080
#define DPIO_CHV_S1_DIV_SHIFT 21
@@ -883,8 +922,21 @@ enum punit_power_well {
#define _CHV_CMN_DW1_CH1 0x8084
#define DPIO_AFC_RECAL (1 << 14)
#define DPIO_DCLKP_EN (1 << 13)
+#define CHV_BUFLEFTENA2_DISABLE (0 << 17) /* CL2 DW1 only */
+#define CHV_BUFLEFTENA2_NORMAL (1 << 17) /* CL2 DW1 only */
+#define CHV_BUFLEFTENA2_FORCE (3 << 17) /* CL2 DW1 only */
+#define CHV_BUFLEFTENA2_MASK (3 << 17) /* CL2 DW1 only */
+#define CHV_BUFRIGHTENA2_DISABLE (0 << 19) /* CL2 DW1 only */
+#define CHV_BUFRIGHTENA2_NORMAL (1 << 19) /* CL2 DW1 only */
+#define CHV_BUFRIGHTENA2_FORCE (3 << 19) /* CL2 DW1 only */
+#define CHV_BUFRIGHTENA2_MASK (3 << 19) /* CL2 DW1 only */
#define CHV_CMN_DW14(ch) _PIPE(ch, _CHV_CMN_DW14_CH0, _CHV_CMN_DW1_CH1)
+#define _CHV_CMN_DW19_CH0 0x814c
+#define _CHV_CMN_DW6_CH1 0x8098
+#define CHV_CMN_USEDCLKCHANNEL (1 << 13)
+#define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1)
+
#define CHV_CMN_DW30 0x8178
#define DPIO_LRC_BYPASS (1 << 3)
@@ -933,6 +985,7 @@ enum punit_power_well {
#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
#define GEN7_FENCE_MAX_PITCH_VAL 0x0800
+
/* control register for cpu gtt access */
#define TILECTL 0x101000
#define TILECTL_SWZCTL (1 << 0)
@@ -1170,6 +1223,8 @@ enum punit_power_well {
#define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8)
#define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac)
#define VLV_PCBR (VLV_DISPLAY_BASE + 0x2120)
+#define VLV_PCBR_ADDR_SHIFT 12
+
#define DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
#define EIR 0x020b0
#define EMR 0x020b4
@@ -1570,11 +1625,10 @@ enum punit_power_well {
/*
* Clock control & power management
*/
-#define DPLL_A_OFFSET 0x6014
-#define DPLL_B_OFFSET 0x6018
-#define CHV_DPLL_C_OFFSET 0x6030
-#define DPLL(pipe) (dev_priv->info.dpll_offsets[pipe] + \
- dev_priv->info.display_mmio_offset)
+#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
+#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
+#define _CHV_DPLL_C (dev_priv->info.display_mmio_offset + 0x6030)
+#define DPLL(pipe) _PIPE3((pipe), _DPLL_A, _DPLL_B, _CHV_DPLL_C)
#define VGA0 0x6000
#define VGA1 0x6004
@@ -1662,11 +1716,10 @@ enum punit_power_well {
#define SDVO_MULTIPLIER_SHIFT_HIRES 4
#define SDVO_MULTIPLIER_SHIFT_VGA 0
-#define DPLL_A_MD_OFFSET 0x601c /* 965+ only */
-#define DPLL_B_MD_OFFSET 0x6020 /* 965+ only */
-#define CHV_DPLL_C_MD_OFFSET 0x603c
-#define DPLL_MD(pipe) (dev_priv->info.dpll_md_offsets[pipe] + \
- dev_priv->info.display_mmio_offset)
+#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
+#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
+#define _CHV_DPLL_C_MD (dev_priv->info.display_mmio_offset + 0x603c)
+#define DPLL_MD(pipe) _PIPE3((pipe), _DPLL_A_MD, _DPLL_B_MD, _CHV_DPLL_C_MD)
/*
* UDI pixel divider, controlling how many pixels are stuffed into a packet.
@@ -2231,7 +2284,7 @@ enum punit_power_well {
/* Same as Haswell, but 72064 bytes now. */
#define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE)
-
+#define CHV_CLK_CTL1 0x101100
#define VLV_CLK_CTL2 0x101104
#define CLK_CTL2_CZCOUNT_30NS_SHIFT 28
@@ -2376,6 +2429,7 @@ enum punit_power_well {
#define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800)
#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0)
#define EDP_PSR_ENABLE (1<<31)
+#define BDW_PSR_SINGLE_FRAME (1<<30)
#define EDP_PSR_LINK_DISABLE (0<<27)
#define EDP_PSR_LINK_STANDBY (1<<27)
#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3<<25)
@@ -2533,8 +2587,14 @@ enum punit_power_well {
#define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28)
#define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29)
#define PORTD_HOTPLUG_INT_STATUS (3 << 21)
+#define PORTD_HOTPLUG_INT_LONG_PULSE (2 << 21)
+#define PORTD_HOTPLUG_INT_SHORT_PULSE (1 << 21)
#define PORTC_HOTPLUG_INT_STATUS (3 << 19)
+#define PORTC_HOTPLUG_INT_LONG_PULSE (2 << 19)
+#define PORTC_HOTPLUG_INT_SHORT_PULSE (1 << 19)
#define PORTB_HOTPLUG_INT_STATUS (3 << 17)
+#define PORTB_HOTPLUG_INT_LONG_PULSE (2 << 17)
+#define PORTB_HOTPLUG_INT_SHORT_PLUSE (1 << 17)
/* CRT/TV common between gen3+ */
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10)
@@ -2588,7 +2648,7 @@ enum punit_power_well {
#define PORT_DFT_I9XX 0x61150
#define DC_BALANCE_RESET (1 << 25)
-#define PORT_DFT2_G4X 0x61154
+#define PORT_DFT2_G4X (dev_priv->info.display_mmio_offset + 0x61154)
#define DC_BALANCE_RESET_VLV (1 << 31)
#define PIPE_SCRAMBLE_RESET_MASK (0x3 << 0)
#define PIPE_B_SCRAMBLE_RESET (1 << 1)
@@ -3803,47 +3863,47 @@ enum punit_power_well {
/* drain latency register values*/
#define DRAIN_LATENCY_PRECISION_32 32
-#define DRAIN_LATENCY_PRECISION_16 16
+#define DRAIN_LATENCY_PRECISION_64 64
#define VLV_DDL1 (VLV_DISPLAY_BASE + 0x70050)
-#define DDL_CURSORA_PRECISION_32 (1<<31)
-#define DDL_CURSORA_PRECISION_16 (0<<31)
+#define DDL_CURSORA_PRECISION_64 (1<<31)
+#define DDL_CURSORA_PRECISION_32 (0<<31)
#define DDL_CURSORA_SHIFT 24
-#define DDL_SPRITEB_PRECISION_32 (1<<23)
-#define DDL_SPRITEB_PRECISION_16 (0<<23)
+#define DDL_SPRITEB_PRECISION_64 (1<<23)
+#define DDL_SPRITEB_PRECISION_32 (0<<23)
#define DDL_SPRITEB_SHIFT 16
-#define DDL_SPRITEA_PRECISION_32 (1<<15)
-#define DDL_SPRITEA_PRECISION_16 (0<<15)
+#define DDL_SPRITEA_PRECISION_64 (1<<15)
+#define DDL_SPRITEA_PRECISION_32 (0<<15)
#define DDL_SPRITEA_SHIFT 8
-#define DDL_PLANEA_PRECISION_32 (1<<7)
-#define DDL_PLANEA_PRECISION_16 (0<<7)
+#define DDL_PLANEA_PRECISION_64 (1<<7)
+#define DDL_PLANEA_PRECISION_32 (0<<7)
#define DDL_PLANEA_SHIFT 0
#define VLV_DDL2 (VLV_DISPLAY_BASE + 0x70054)
-#define DDL_CURSORB_PRECISION_32 (1<<31)
-#define DDL_CURSORB_PRECISION_16 (0<<31)
+#define DDL_CURSORB_PRECISION_64 (1<<31)
+#define DDL_CURSORB_PRECISION_32 (0<<31)
#define DDL_CURSORB_SHIFT 24
-#define DDL_SPRITED_PRECISION_32 (1<<23)
-#define DDL_SPRITED_PRECISION_16 (0<<23)
+#define DDL_SPRITED_PRECISION_64 (1<<23)
+#define DDL_SPRITED_PRECISION_32 (0<<23)
#define DDL_SPRITED_SHIFT 16
-#define DDL_SPRITEC_PRECISION_32 (1<<15)
-#define DDL_SPRITEC_PRECISION_16 (0<<15)
+#define DDL_SPRITEC_PRECISION_64 (1<<15)
+#define DDL_SPRITEC_PRECISION_32 (0<<15)
#define DDL_SPRITEC_SHIFT 8
-#define DDL_PLANEB_PRECISION_32 (1<<7)
-#define DDL_PLANEB_PRECISION_16 (0<<7)
+#define DDL_PLANEB_PRECISION_64 (1<<7)
+#define DDL_PLANEB_PRECISION_32 (0<<7)
#define DDL_PLANEB_SHIFT 0
#define VLV_DDL3 (VLV_DISPLAY_BASE + 0x70058)
-#define DDL_CURSORC_PRECISION_32 (1<<31)
-#define DDL_CURSORC_PRECISION_16 (0<<31)
+#define DDL_CURSORC_PRECISION_64 (1<<31)
+#define DDL_CURSORC_PRECISION_32 (0<<31)
#define DDL_CURSORC_SHIFT 24
-#define DDL_SPRITEF_PRECISION_32 (1<<23)
-#define DDL_SPRITEF_PRECISION_16 (0<<23)
+#define DDL_SPRITEF_PRECISION_64 (1<<23)
+#define DDL_SPRITEF_PRECISION_32 (0<<23)
#define DDL_SPRITEF_SHIFT 16
-#define DDL_SPRITEE_PRECISION_32 (1<<15)
-#define DDL_SPRITEE_PRECISION_16 (0<<15)
+#define DDL_SPRITEE_PRECISION_64 (1<<15)
+#define DDL_SPRITEE_PRECISION_32 (0<<15)
#define DDL_SPRITEE_SHIFT 8
-#define DDL_PLANEC_PRECISION_32 (1<<7)
-#define DDL_PLANEC_PRECISION_16 (0<<7)
+#define DDL_PLANEC_PRECISION_64 (1<<7)
+#define DDL_PLANEC_PRECISION_32 (0<<7)
#define DDL_PLANEC_SHIFT 0
/* FIFO watermark sizes etc */
@@ -4630,6 +4690,8 @@ enum punit_power_well {
#define GEN7_L3CNTLREG1 0xB01C
#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C
#define GEN7_L3AGDIS (1<<19)
+#define GEN7_L3CNTLREG2 0xB020
+#define GEN7_L3CNTLREG3 0xB024
#define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030
#define GEN7_WA_L3_CHICKEN_MODE 0x20000000
@@ -4876,8 +4938,7 @@ enum punit_power_well {
#define _PCH_TRANSA_LINK_M2 0xe0048
#define _PCH_TRANSA_LINK_N2 0xe004c
-/* Per-transcoder DIP controls */
-
+/* Per-transcoder DIP controls (PCH) */
#define _VIDEO_DIP_CTL_A 0xe0200
#define _VIDEO_DIP_DATA_A 0xe0208
#define _VIDEO_DIP_GCP_A 0xe0210
@@ -4890,6 +4951,7 @@ enum punit_power_well {
#define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
#define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
+/* Per-transcoder DIP controls (VLV) */
#define VLV_VIDEO_DIP_CTL_A (VLV_DISPLAY_BASE + 0x60200)
#define VLV_VIDEO_DIP_DATA_A (VLV_DISPLAY_BASE + 0x60208)
#define VLV_VIDEO_DIP_GDCP_PAYLOAD_A (VLV_DISPLAY_BASE + 0x60210)
@@ -4898,12 +4960,19 @@ enum punit_power_well {
#define VLV_VIDEO_DIP_DATA_B (VLV_DISPLAY_BASE + 0x61174)
#define VLV_VIDEO_DIP_GDCP_PAYLOAD_B (VLV_DISPLAY_BASE + 0x61178)
+#define CHV_VIDEO_DIP_CTL_C (VLV_DISPLAY_BASE + 0x611f0)
+#define CHV_VIDEO_DIP_DATA_C (VLV_DISPLAY_BASE + 0x611f4)
+#define CHV_VIDEO_DIP_GDCP_PAYLOAD_C (VLV_DISPLAY_BASE + 0x611f8)
+
#define VLV_TVIDEO_DIP_CTL(pipe) \
- _PIPE(pipe, VLV_VIDEO_DIP_CTL_A, VLV_VIDEO_DIP_CTL_B)
+ _PIPE3((pipe), VLV_VIDEO_DIP_CTL_A, \
+ VLV_VIDEO_DIP_CTL_B, CHV_VIDEO_DIP_CTL_C)
#define VLV_TVIDEO_DIP_DATA(pipe) \
- _PIPE(pipe, VLV_VIDEO_DIP_DATA_A, VLV_VIDEO_DIP_DATA_B)
+ _PIPE3((pipe), VLV_VIDEO_DIP_DATA_A, \
+ VLV_VIDEO_DIP_DATA_B, CHV_VIDEO_DIP_DATA_C)
#define VLV_TVIDEO_DIP_GCP(pipe) \
- _PIPE(pipe, VLV_VIDEO_DIP_GDCP_PAYLOAD_A, VLV_VIDEO_DIP_GDCP_PAYLOAD_B)
+ _PIPE3((pipe), VLV_VIDEO_DIP_GDCP_PAYLOAD_A, \
+ VLV_VIDEO_DIP_GDCP_PAYLOAD_B, CHV_VIDEO_DIP_GDCP_PAYLOAD_C)
/* Haswell DIP controls */
#define HSW_VIDEO_DIP_CTL_A 0x60200
@@ -5334,6 +5403,7 @@ enum punit_power_well {
#define VLV_GTLC_ALLOWWAKEERR (1 << 1)
#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
+#define VLV_GTLC_SURVIVABILITY_REG 0x130098
#define FORCEWAKE_MT 0xa188 /* multi-threaded */
#define FORCEWAKE_KERNEL 0x1
#define FORCEWAKE_USER 0x2
@@ -5471,6 +5541,12 @@ enum punit_power_well {
GEN6_PM_RP_DOWN_THRESHOLD | \
GEN6_PM_RP_DOWN_TIMEOUT)
+#define CHV_CZ_CLOCK_FREQ_MODE_200 200
+#define CHV_CZ_CLOCK_FREQ_MODE_267 267
+#define CHV_CZ_CLOCK_FREQ_MODE_320 320
+#define CHV_CZ_CLOCK_FREQ_MODE_333 333
+#define CHV_CZ_CLOCK_FREQ_MODE_400 400
+
#define GEN7_GT_SCRATCH_BASE 0x4F100
#define GEN7_GT_SCRATCH_REG_NUM 8
@@ -5481,6 +5557,8 @@ enum punit_power_well {
#define GEN6_GT_GFX_RC6_LOCKED 0x138104
#define VLV_COUNTER_CONTROL 0x138104
#define VLV_COUNT_RANGE_HIGH (1<<15)
+#define VLV_MEDIA_RC0_COUNT_EN (1<<5)
+#define VLV_RENDER_RC0_COUNT_EN (1<<4)
#define VLV_MEDIA_RC6_COUNT_EN (1<<1)
#define VLV_RENDER_RC6_COUNT_EN (1<<0)
#define GEN6_GT_GFX_RC6 0x138108
@@ -5489,6 +5567,8 @@ enum punit_power_well {
#define GEN6_GT_GFX_RC6p 0x13810C
#define GEN6_GT_GFX_RC6pp 0x138110
+#define VLV_RENDER_C0_COUNT_REG 0x138118
+#define VLV_MEDIA_C0_COUNT_REG 0x13811C
#define GEN6_PCODE_MAILBOX 0x138124
#define GEN6_PCODE_READY (1<<31)
@@ -5723,6 +5803,7 @@ enum punit_power_well {
#define TRANS_DDI_FUNC_ENABLE (1<<31)
/* Those bits are ignored by pipe EDP since it can only connect to DDI A */
#define TRANS_DDI_PORT_MASK (7<<28)
+#define TRANS_DDI_PORT_SHIFT 28
#define TRANS_DDI_SELECT_PORT(x) ((x)<<28)
#define TRANS_DDI_PORT_NONE (0<<28)
#define TRANS_DDI_MODE_SELECT_MASK (7<<24)
@@ -5743,6 +5824,7 @@ enum punit_power_well {
#define TRANS_DDI_EDP_INPUT_A_ONOFF (4<<12)
#define TRANS_DDI_EDP_INPUT_B_ONOFF (5<<12)
#define TRANS_DDI_EDP_INPUT_C_ONOFF (6<<12)
+#define TRANS_DDI_DP_VC_PAYLOAD_ALLOC (1<<8)
#define TRANS_DDI_BFI_ENABLE (1<<4)
/* DisplayPort Transport Control */
@@ -5752,6 +5834,7 @@ enum punit_power_well {
#define DP_TP_CTL_ENABLE (1<<31)
#define DP_TP_CTL_MODE_SST (0<<27)
#define DP_TP_CTL_MODE_MST (1<<27)
+#define DP_TP_CTL_FORCE_ACT (1<<25)
#define DP_TP_CTL_ENHANCED_FRAME_ENABLE (1<<18)
#define DP_TP_CTL_FDI_AUTOTRAIN (1<<15)
#define DP_TP_CTL_LINK_TRAIN_MASK (7<<8)
@@ -5766,15 +5849,19 @@ enum punit_power_well {
#define DP_TP_STATUS_A 0x64044
#define DP_TP_STATUS_B 0x64144
#define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
-#define DP_TP_STATUS_IDLE_DONE (1<<25)
-#define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12)
+#define DP_TP_STATUS_IDLE_DONE (1<<25)
+#define DP_TP_STATUS_ACT_SENT (1<<24)
+#define DP_TP_STATUS_MODE_STATUS_MST (1<<23)
+#define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12)
+#define DP_TP_STATUS_PAYLOAD_MAPPING_VC2 (3 << 8)
+#define DP_TP_STATUS_PAYLOAD_MAPPING_VC1 (3 << 4)
+#define DP_TP_STATUS_PAYLOAD_MAPPING_VC0 (3 << 0)
/* DDI Buffer Control */
#define DDI_BUF_CTL_A 0x64000
#define DDI_BUF_CTL_B 0x64100
#define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B)
#define DDI_BUF_CTL_ENABLE (1<<31)
-/* Haswell */
#define DDI_BUF_EMP_400MV_0DB_HSW (0<<24) /* Sel0 */
#define DDI_BUF_EMP_400MV_3_5DB_HSW (1<<24) /* Sel1 */
#define DDI_BUF_EMP_400MV_6DB_HSW (2<<24) /* Sel2 */
@@ -5784,16 +5871,6 @@ enum punit_power_well {
#define DDI_BUF_EMP_600MV_6DB_HSW (6<<24) /* Sel6 */
#define DDI_BUF_EMP_800MV_0DB_HSW (7<<24) /* Sel7 */
#define DDI_BUF_EMP_800MV_3_5DB_HSW (8<<24) /* Sel8 */
-/* Broadwell */
-#define DDI_BUF_EMP_400MV_0DB_BDW (0<<24) /* Sel0 */
-#define DDI_BUF_EMP_400MV_3_5DB_BDW (1<<24) /* Sel1 */
-#define DDI_BUF_EMP_400MV_6DB_BDW (2<<24) /* Sel2 */
-#define DDI_BUF_EMP_600MV_0DB_BDW (3<<24) /* Sel3 */
-#define DDI_BUF_EMP_600MV_3_5DB_BDW (4<<24) /* Sel4 */
-#define DDI_BUF_EMP_600MV_6DB_BDW (5<<24) /* Sel5 */
-#define DDI_BUF_EMP_800MV_0DB_BDW (6<<24) /* Sel6 */
-#define DDI_BUF_EMP_800MV_3_5DB_BDW (7<<24) /* Sel7 */
-#define DDI_BUF_EMP_1200MV_0DB_BDW (8<<24) /* Sel8 */
#define DDI_BUF_EMP_MASK (0xf<<24)
#define DDI_BUF_PORT_REVERSAL (1<<16)
#define DDI_BUF_IS_IDLE (1<<7)
@@ -5861,10 +5938,12 @@ enum punit_power_well {
/* WRPLL */
#define WRPLL_CTL1 0x46040
#define WRPLL_CTL2 0x46060
+#define WRPLL_CTL(pll) (pll == 0 ? WRPLL_CTL1 : WRPLL_CTL2)
#define WRPLL_PLL_ENABLE (1<<31)
-#define WRPLL_PLL_SELECT_SSC (0x01<<28)
-#define WRPLL_PLL_SELECT_NON_SSC (0x02<<28)
-#define WRPLL_PLL_SELECT_LCPLL_2700 (0x03<<28)
+#define WRPLL_PLL_SSC (1<<28)
+#define WRPLL_PLL_NON_SSC (2<<28)
+#define WRPLL_PLL_LCPLL (3<<28)
+#define WRPLL_PLL_REF_MASK (3<<28)
/* WRPLL divider programming */
#define WRPLL_DIVIDER_REFERENCE(x) ((x)<<0)
#define WRPLL_DIVIDER_REF_MASK (0xff)
@@ -5883,6 +5962,7 @@ enum punit_power_well {
#define PORT_CLK_SEL_LCPLL_1350 (1<<29)
#define PORT_CLK_SEL_LCPLL_810 (2<<29)
#define PORT_CLK_SEL_SPLL (3<<29)
+#define PORT_CLK_SEL_WRPLL(pll) (((pll)+4)<<29)
#define PORT_CLK_SEL_WRPLL1 (4<<29)
#define PORT_CLK_SEL_WRPLL2 (5<<29)
#define PORT_CLK_SEL_NONE (7<<29)
@@ -5924,7 +6004,10 @@ enum punit_power_well {
#define LCPLL_CD_SOURCE_FCLK (1<<21)
#define LCPLL_CD_SOURCE_FCLK_DONE (1<<19)
-#define D_COMP (MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+/* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
+ * since on HSW we can't write to it using I915_WRITE. */
+#define D_COMP_HSW (MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
+#define D_COMP_BDW 0x138144
#define D_COMP_RCOMP_IN_PROGRESS (1<<9)
#define D_COMP_COMP_FORCE (1<<8)
#define D_COMP_COMP_DISABLE (1<<0)
@@ -6005,7 +6088,8 @@ enum punit_power_well {
#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190)
#define _MIPIB_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700)
-#define MIPI_PORT_CTRL(pipe) _PIPE(pipe, _MIPIA_PORT_CTRL, _MIPIB_PORT_CTRL)
+#define MIPI_PORT_CTRL(tc) _TRANSCODER(tc, _MIPIA_PORT_CTRL, \
+ _MIPIB_PORT_CTRL)
#define DPI_ENABLE (1 << 31) /* A + B */
#define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27
#define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27)
@@ -6047,18 +6131,20 @@ enum punit_power_well {
#define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194)
#define _MIPIB_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704)
-#define MIPI_TEARING_CTRL(pipe) _PIPE(pipe, _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL)
+#define MIPI_TEARING_CTRL(tc) _TRANSCODER(tc, \
+ _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL)
#define TEARING_EFFECT_DELAY_SHIFT 0
#define TEARING_EFFECT_DELAY_MASK (0xffff << 0)
/* XXX: all bits reserved */
-#define _MIPIA_AUTOPWG (VLV_DISPLAY_BASE + 0x611a0)
+#define _MIPIA_AUTOPWG (VLV_DISPLAY_BASE + 0x611a0)
/* MIPI DSI Controller and D-PHY registers */
-#define _MIPIA_DEVICE_READY (VLV_DISPLAY_BASE + 0xb000)
-#define _MIPIB_DEVICE_READY (VLV_DISPLAY_BASE + 0xb800)
-#define MIPI_DEVICE_READY(pipe) _PIPE(pipe, _MIPIA_DEVICE_READY, _MIPIB_DEVICE_READY)
+#define _MIPIA_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb000)
+#define _MIPIB_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb800)
+#define MIPI_DEVICE_READY(tc) _TRANSCODER(tc, _MIPIA_DEVICE_READY, \
+ _MIPIB_DEVICE_READY)
#define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */
#define ULPS_STATE_MASK (3 << 1)
#define ULPS_STATE_ENTER (2 << 1)
@@ -6066,12 +6152,14 @@ enum punit_power_well {
#define ULPS_STATE_NORMAL_OPERATION (0 << 1)
#define DEVICE_READY (1 << 0)
-#define _MIPIA_INTR_STAT (VLV_DISPLAY_BASE + 0xb004)
-#define _MIPIB_INTR_STAT (VLV_DISPLAY_BASE + 0xb804)
-#define MIPI_INTR_STAT(pipe) _PIPE(pipe, _MIPIA_INTR_STAT, _MIPIB_INTR_STAT)
-#define _MIPIA_INTR_EN (VLV_DISPLAY_BASE + 0xb008)
-#define _MIPIB_INTR_EN (VLV_DISPLAY_BASE + 0xb808)
-#define MIPI_INTR_EN(pipe) _PIPE(pipe, _MIPIA_INTR_EN, _MIPIB_INTR_EN)
+#define _MIPIA_INTR_STAT (dev_priv->mipi_mmio_base + 0xb004)
+#define _MIPIB_INTR_STAT (dev_priv->mipi_mmio_base + 0xb804)
+#define MIPI_INTR_STAT(tc) _TRANSCODER(tc, _MIPIA_INTR_STAT, \
+ _MIPIB_INTR_STAT)
+#define _MIPIA_INTR_EN (dev_priv->mipi_mmio_base + 0xb008)
+#define _MIPIB_INTR_EN (dev_priv->mipi_mmio_base + 0xb808)
+#define MIPI_INTR_EN(tc) _TRANSCODER(tc, _MIPIA_INTR_EN, \
+ _MIPIB_INTR_EN)
#define TEARING_EFFECT (1 << 31)
#define SPL_PKT_SENT_INTERRUPT (1 << 30)
#define GEN_READ_DATA_AVAIL (1 << 29)
@@ -6105,9 +6193,10 @@ enum punit_power_well {
#define RXSOT_SYNC_ERROR (1 << 1)
#define RXSOT_ERROR (1 << 0)
-#define _MIPIA_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb00c)
-#define _MIPIB_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb80c)
-#define MIPI_DSI_FUNC_PRG(pipe) _PIPE(pipe, _MIPIA_DSI_FUNC_PRG, _MIPIB_DSI_FUNC_PRG)
+#define _MIPIA_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb00c)
+#define _MIPIB_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb80c)
+#define MIPI_DSI_FUNC_PRG(tc) _TRANSCODER(tc, _MIPIA_DSI_FUNC_PRG, \
+ _MIPIB_DSI_FUNC_PRG)
#define CMD_MODE_DATA_WIDTH_MASK (7 << 13)
#define CMD_MODE_NOT_SUPPORTED (0 << 13)
#define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13)
@@ -6128,78 +6217,94 @@ enum punit_power_well {
#define DATA_LANES_PRG_REG_SHIFT 0
#define DATA_LANES_PRG_REG_MASK (7 << 0)
-#define _MIPIA_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb010)
-#define _MIPIB_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb810)
-#define MIPI_HS_TX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_HS_TX_TIMEOUT, _MIPIB_HS_TX_TIMEOUT)
+#define _MIPIA_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb010)
+#define _MIPIB_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb810)
+#define MIPI_HS_TX_TIMEOUT(tc) _TRANSCODER(tc, _MIPIA_HS_TX_TIMEOUT, \
+ _MIPIB_HS_TX_TIMEOUT)
#define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff
-#define _MIPIA_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb014)
-#define _MIPIB_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb814)
-#define MIPI_LP_RX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_LP_RX_TIMEOUT, _MIPIB_LP_RX_TIMEOUT)
+#define _MIPIA_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb014)
+#define _MIPIB_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb814)
+#define MIPI_LP_RX_TIMEOUT(tc) _TRANSCODER(tc, _MIPIA_LP_RX_TIMEOUT, \
+ _MIPIB_LP_RX_TIMEOUT)
#define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff
-#define _MIPIA_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb018)
-#define _MIPIB_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb818)
-#define MIPI_TURN_AROUND_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT)
+#define _MIPIA_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb018)
+#define _MIPIB_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb818)
+#define MIPI_TURN_AROUND_TIMEOUT(tc) _TRANSCODER(tc, \
+ _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT)
#define TURN_AROUND_TIMEOUT_MASK 0x3f
-#define _MIPIA_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb01c)
-#define _MIPIB_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb81c)
-#define MIPI_DEVICE_RESET_TIMER(pipe) _PIPE(pipe, _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER)
+#define _MIPIA_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb01c)
+#define _MIPIB_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb81c)
+#define MIPI_DEVICE_RESET_TIMER(tc) _TRANSCODER(tc, \
+ _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER)
#define DEVICE_RESET_TIMER_MASK 0xffff
-#define _MIPIA_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb020)
-#define _MIPIB_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb820)
-#define MIPI_DPI_RESOLUTION(pipe) _PIPE(pipe, _MIPIA_DPI_RESOLUTION, _MIPIB_DPI_RESOLUTION)
+#define _MIPIA_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb020)
+#define _MIPIB_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb820)
+#define MIPI_DPI_RESOLUTION(tc) _TRANSCODER(tc, _MIPIA_DPI_RESOLUTION, \
+ _MIPIB_DPI_RESOLUTION)
#define VERTICAL_ADDRESS_SHIFT 16
#define VERTICAL_ADDRESS_MASK (0xffff << 16)
#define HORIZONTAL_ADDRESS_SHIFT 0
#define HORIZONTAL_ADDRESS_MASK 0xffff
-#define _MIPIA_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb024)
-#define _MIPIB_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb824)
-#define MIPI_DBI_FIFO_THROTTLE(pipe) _PIPE(pipe, _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE)
+#define _MIPIA_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb024)
+#define _MIPIB_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb824)
+#define MIPI_DBI_FIFO_THROTTLE(tc) _TRANSCODER(tc, \
+ _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE)
#define DBI_FIFO_EMPTY_HALF (0 << 0)
#define DBI_FIFO_EMPTY_QUARTER (1 << 0)
#define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0)
/* regs below are bits 15:0 */
-#define _MIPIA_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb028)
-#define _MIPIB_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb828)
-#define MIPI_HSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT)
-
-#define _MIPIA_HBP_COUNT (VLV_DISPLAY_BASE + 0xb02c)
-#define _MIPIB_HBP_COUNT (VLV_DISPLAY_BASE + 0xb82c)
-#define MIPI_HBP_COUNT(pipe) _PIPE(pipe, _MIPIA_HBP_COUNT, _MIPIB_HBP_COUNT)
-
-#define _MIPIA_HFP_COUNT (VLV_DISPLAY_BASE + 0xb030)
-#define _MIPIB_HFP_COUNT (VLV_DISPLAY_BASE + 0xb830)
-#define MIPI_HFP_COUNT(pipe) _PIPE(pipe, _MIPIA_HFP_COUNT, _MIPIB_HFP_COUNT)
-
-#define _MIPIA_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb034)
-#define _MIPIB_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb834)
-#define MIPI_HACTIVE_AREA_COUNT(pipe) _PIPE(pipe, _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT)
-
-#define _MIPIA_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb038)
-#define _MIPIB_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb838)
-#define MIPI_VSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT)
+#define _MIPIA_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb028)
+#define _MIPIB_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb828)
+#define MIPI_HSYNC_PADDING_COUNT(tc) _TRANSCODER(tc, \
+ _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT)
+
+#define _MIPIA_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb02c)
+#define _MIPIB_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb82c)
+#define MIPI_HBP_COUNT(tc) _TRANSCODER(tc, _MIPIA_HBP_COUNT, \
+ _MIPIB_HBP_COUNT)
+
+#define _MIPIA_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb030)
+#define _MIPIB_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb830)
+#define MIPI_HFP_COUNT(tc) _TRANSCODER(tc, _MIPIA_HFP_COUNT, \
+ _MIPIB_HFP_COUNT)
+
+#define _MIPIA_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb034)
+#define _MIPIB_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb834)
+#define MIPI_HACTIVE_AREA_COUNT(tc) _TRANSCODER(tc, \
+ _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT)
+
+#define _MIPIA_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb038)
+#define _MIPIB_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb838)
+#define MIPI_VSYNC_PADDING_COUNT(tc) _TRANSCODER(tc, \
+ _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT)
+
+#define _MIPIA_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb03c)
+#define _MIPIB_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb83c)
+#define MIPI_VBP_COUNT(tc) _TRANSCODER(tc, _MIPIA_VBP_COUNT, \
+ _MIPIB_VBP_COUNT)
+
+#define _MIPIA_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb040)
+#define _MIPIB_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb840)
+#define MIPI_VFP_COUNT(tc) _TRANSCODER(tc, _MIPIA_VFP_COUNT, \
+ _MIPIB_VFP_COUNT)
+
+#define _MIPIA_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb044)
+#define _MIPIB_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb844)
+#define MIPI_HIGH_LOW_SWITCH_COUNT(tc) _TRANSCODER(tc, \
+ _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT)
-#define _MIPIA_VBP_COUNT (VLV_DISPLAY_BASE + 0xb03c)
-#define _MIPIB_VBP_COUNT (VLV_DISPLAY_BASE + 0xb83c)
-#define MIPI_VBP_COUNT(pipe) _PIPE(pipe, _MIPIA_VBP_COUNT, _MIPIB_VBP_COUNT)
-
-#define _MIPIA_VFP_COUNT (VLV_DISPLAY_BASE + 0xb040)
-#define _MIPIB_VFP_COUNT (VLV_DISPLAY_BASE + 0xb840)
-#define MIPI_VFP_COUNT(pipe) _PIPE(pipe, _MIPIA_VFP_COUNT, _MIPIB_VFP_COUNT)
-
-#define _MIPIA_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb044)
-#define _MIPIB_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb844)
-#define MIPI_HIGH_LOW_SWITCH_COUNT(pipe) _PIPE(pipe, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT)
/* regs above are bits 15:0 */
-#define _MIPIA_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb048)
-#define _MIPIB_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb848)
-#define MIPI_DPI_CONTROL(pipe) _PIPE(pipe, _MIPIA_DPI_CONTROL, _MIPIB_DPI_CONTROL)
+#define _MIPIA_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb048)
+#define _MIPIB_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb848)
+#define MIPI_DPI_CONTROL(tc) _TRANSCODER(tc, _MIPIA_DPI_CONTROL, \
+ _MIPIB_DPI_CONTROL)
#define DPI_LP_MODE (1 << 6)
#define BACKLIGHT_OFF (1 << 5)
#define BACKLIGHT_ON (1 << 4)
@@ -6208,27 +6313,31 @@ enum punit_power_well {
#define TURN_ON (1 << 1)
#define SHUTDOWN (1 << 0)
-#define _MIPIA_DPI_DATA (VLV_DISPLAY_BASE + 0xb04c)
-#define _MIPIB_DPI_DATA (VLV_DISPLAY_BASE + 0xb84c)
-#define MIPI_DPI_DATA(pipe) _PIPE(pipe, _MIPIA_DPI_DATA, _MIPIB_DPI_DATA)
+#define _MIPIA_DPI_DATA (dev_priv->mipi_mmio_base + 0xb04c)
+#define _MIPIB_DPI_DATA (dev_priv->mipi_mmio_base + 0xb84c)
+#define MIPI_DPI_DATA(tc) _TRANSCODER(tc, _MIPIA_DPI_DATA, \
+ _MIPIB_DPI_DATA)
#define COMMAND_BYTE_SHIFT 0
#define COMMAND_BYTE_MASK (0x3f << 0)
-#define _MIPIA_INIT_COUNT (VLV_DISPLAY_BASE + 0xb050)
-#define _MIPIB_INIT_COUNT (VLV_DISPLAY_BASE + 0xb850)
-#define MIPI_INIT_COUNT(pipe) _PIPE(pipe, _MIPIA_INIT_COUNT, _MIPIB_INIT_COUNT)
+#define _MIPIA_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb050)
+#define _MIPIB_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb850)
+#define MIPI_INIT_COUNT(tc) _TRANSCODER(tc, _MIPIA_INIT_COUNT, \
+ _MIPIB_INIT_COUNT)
#define MASTER_INIT_TIMER_SHIFT 0
#define MASTER_INIT_TIMER_MASK (0xffff << 0)
-#define _MIPIA_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb054)
-#define _MIPIB_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb854)
-#define MIPI_MAX_RETURN_PKT_SIZE(pipe) _PIPE(pipe, _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE)
+#define _MIPIA_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb054)
+#define _MIPIB_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb854)
+#define MIPI_MAX_RETURN_PKT_SIZE(tc) _TRANSCODER(tc, \
+ _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE)
#define MAX_RETURN_PKT_SIZE_SHIFT 0
#define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0)
-#define _MIPIA_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb058)
-#define _MIPIB_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb858)
-#define MIPI_VIDEO_MODE_FORMAT(pipe) _PIPE(pipe, _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT)
+#define _MIPIA_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb058)
+#define _MIPIB_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb858)
+#define MIPI_VIDEO_MODE_FORMAT(tc) _TRANSCODER(tc, \
+ _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT)
#define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4)
#define DISABLE_VIDEO_BTA (1 << 3)
#define IP_TG_CONFIG (1 << 2)
@@ -6236,9 +6345,10 @@ enum punit_power_well {
#define VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS (2 << 0)
#define VIDEO_MODE_BURST (3 << 0)
-#define _MIPIA_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb05c)
-#define _MIPIB_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb85c)
-#define MIPI_EOT_DISABLE(pipe) _PIPE(pipe, _MIPIA_EOT_DISABLE, _MIPIB_EOT_DISABLE)
+#define _MIPIA_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb05c)
+#define _MIPIB_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb85c)
+#define MIPI_EOT_DISABLE(tc) _TRANSCODER(tc, _MIPIA_EOT_DISABLE, \
+ _MIPIB_EOT_DISABLE)
#define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7)
#define HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 6)
#define LOW_CONTENTION_RECOVERY_DISABLE (1 << 5)
@@ -6248,28 +6358,33 @@ enum punit_power_well {
#define CLOCKSTOP (1 << 1)
#define EOT_DISABLE (1 << 0)
-#define _MIPIA_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb060)
-#define _MIPIB_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb860)
-#define MIPI_LP_BYTECLK(pipe) _PIPE(pipe, _MIPIA_LP_BYTECLK, _MIPIB_LP_BYTECLK)
+#define _MIPIA_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb060)
+#define _MIPIB_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb860)
+#define MIPI_LP_BYTECLK(tc) _TRANSCODER(tc, _MIPIA_LP_BYTECLK, \
+ _MIPIB_LP_BYTECLK)
#define LP_BYTECLK_SHIFT 0
#define LP_BYTECLK_MASK (0xffff << 0)
/* bits 31:0 */
-#define _MIPIA_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb064)
-#define _MIPIB_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb864)
-#define MIPI_LP_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_LP_GEN_DATA, _MIPIB_LP_GEN_DATA)
+#define _MIPIA_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb064)
+#define _MIPIB_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb864)
+#define MIPI_LP_GEN_DATA(tc) _TRANSCODER(tc, _MIPIA_LP_GEN_DATA, \
+ _MIPIB_LP_GEN_DATA)
/* bits 31:0 */
-#define _MIPIA_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb068)
-#define _MIPIB_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb868)
-#define MIPI_HS_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_HS_GEN_DATA, _MIPIB_HS_GEN_DATA)
-
-#define _MIPIA_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb06c)
-#define _MIPIB_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb86c)
-#define MIPI_LP_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_LP_GEN_CTRL, _MIPIB_LP_GEN_CTRL)
-#define _MIPIA_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb070)
-#define _MIPIB_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb870)
-#define MIPI_HS_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_HS_GEN_CTRL, _MIPIB_HS_GEN_CTRL)
+#define _MIPIA_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb068)
+#define _MIPIB_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb868)
+#define MIPI_HS_GEN_DATA(tc) _TRANSCODER(tc, _MIPIA_HS_GEN_DATA, \
+ _MIPIB_HS_GEN_DATA)
+
+#define _MIPIA_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb06c)
+#define _MIPIB_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb86c)
+#define MIPI_LP_GEN_CTRL(tc) _TRANSCODER(tc, _MIPIA_LP_GEN_CTRL, \
+ _MIPIB_LP_GEN_CTRL)
+#define _MIPIA_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb070)
+#define _MIPIB_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb870)
+#define MIPI_HS_GEN_CTRL(tc) _TRANSCODER(tc, _MIPIA_HS_GEN_CTRL, \
+ _MIPIB_HS_GEN_CTRL)
#define LONG_PACKET_WORD_COUNT_SHIFT 8
#define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8)
#define SHORT_PACKET_PARAM_SHIFT 8
@@ -6280,9 +6395,10 @@ enum punit_power_well {
#define DATA_TYPE_MASK (3f << 0)
/* data type values, see include/video/mipi_display.h */
-#define _MIPIA_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb074)
-#define _MIPIB_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb874)
-#define MIPI_GEN_FIFO_STAT(pipe) _PIPE(pipe, _MIPIA_GEN_FIFO_STAT, _MIPIB_GEN_FIFO_STAT)
+#define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074)
+#define _MIPIB_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb874)
+#define MIPI_GEN_FIFO_STAT(tc) _TRANSCODER(tc, _MIPIA_GEN_FIFO_STAT, \
+ _MIPIB_GEN_FIFO_STAT)
#define DPI_FIFO_EMPTY (1 << 28)
#define DBI_FIFO_EMPTY (1 << 27)
#define LP_CTRL_FIFO_EMPTY (1 << 26)
@@ -6298,16 +6414,18 @@ enum punit_power_well {
#define HS_DATA_FIFO_HALF_EMPTY (1 << 1)
#define HS_DATA_FIFO_FULL (1 << 0)
-#define _MIPIA_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb078)
-#define _MIPIB_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb878)
-#define MIPI_HS_LP_DBI_ENABLE(pipe) _PIPE(pipe, _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE)
+#define _MIPIA_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb078)
+#define _MIPIB_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb878)
+#define MIPI_HS_LP_DBI_ENABLE(tc) _TRANSCODER(tc, \
+ _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE)
#define DBI_HS_LP_MODE_MASK (1 << 0)
#define DBI_LP_MODE (1 << 0)
#define DBI_HS_MODE (0 << 0)
-#define _MIPIA_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb080)
-#define _MIPIB_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb880)
-#define MIPI_DPHY_PARAM(pipe) _PIPE(pipe, _MIPIA_DPHY_PARAM, _MIPIB_DPHY_PARAM)
+#define _MIPIA_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb080)
+#define _MIPIB_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb880)
+#define MIPI_DPHY_PARAM(tc) _TRANSCODER(tc, _MIPIA_DPHY_PARAM, \
+ _MIPIB_DPHY_PARAM)
#define EXIT_ZERO_COUNT_SHIFT 24
#define EXIT_ZERO_COUNT_MASK (0x3f << 24)
#define TRAIL_COUNT_SHIFT 16
@@ -6318,34 +6436,41 @@ enum punit_power_well {
#define PREPARE_COUNT_MASK (0x3f << 0)
/* bits 31:0 */
-#define _MIPIA_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb084)
-#define _MIPIB_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb884)
-#define MIPI_DBI_BW_CTRL(pipe) _PIPE(pipe, _MIPIA_DBI_BW_CTRL, _MIPIB_DBI_BW_CTRL)
-
-#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb088)
-#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb888)
-#define MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe) _PIPE(pipe, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT)
+#define _MIPIA_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb084)
+#define _MIPIB_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884)
+#define MIPI_DBI_BW_CTRL(tc) _TRANSCODER(tc, _MIPIA_DBI_BW_CTRL, \
+ _MIPIB_DBI_BW_CTRL)
+
+#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \
+ + 0xb088)
+#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \
+ + 0xb888)
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT(tc) _TRANSCODER(tc, \
+ _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT)
#define LP_HS_SSW_CNT_SHIFT 16
#define LP_HS_SSW_CNT_MASK (0xffff << 16)
#define HS_LP_PWR_SW_CNT_SHIFT 0
#define HS_LP_PWR_SW_CNT_MASK (0xffff << 0)
-#define _MIPIA_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb08c)
-#define _MIPIB_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb88c)
-#define MIPI_STOP_STATE_STALL(pipe) _PIPE(pipe, _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL)
+#define _MIPIA_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb08c)
+#define _MIPIB_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb88c)
+#define MIPI_STOP_STATE_STALL(tc) _TRANSCODER(tc, \
+ _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL)
#define STOP_STATE_STALL_COUNTER_SHIFT 0
#define STOP_STATE_STALL_COUNTER_MASK (0xff << 0)
-#define _MIPIA_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb090)
-#define _MIPIB_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb890)
-#define MIPI_INTR_STAT_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1)
-#define _MIPIA_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb094)
-#define _MIPIB_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb894)
-#define MIPI_INTR_EN_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_EN_REG_1, _MIPIB_INTR_EN_REG_1)
+#define _MIPIA_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb090)
+#define _MIPIB_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb890)
+#define MIPI_INTR_STAT_REG_1(tc) _TRANSCODER(tc, \
+ _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1)
+#define _MIPIA_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb094)
+#define _MIPIB_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb894)
+#define MIPI_INTR_EN_REG_1(tc) _TRANSCODER(tc, _MIPIA_INTR_EN_REG_1, \
+ _MIPIB_INTR_EN_REG_1)
#define RX_CONTENTION_DETECTED (1 << 0)
/* XXX: only pipe A ?!? */
-#define MIPIA_DBI_TYPEC_CTRL (VLV_DISPLAY_BASE + 0xb100)
+#define MIPIA_DBI_TYPEC_CTRL (dev_priv->mipi_mmio_base + 0xb100)
#define DBI_TYPEC_ENABLE (1 << 31)
#define DBI_TYPEC_WIP (1 << 30)
#define DBI_TYPEC_OPTION_SHIFT 28
@@ -6359,9 +6484,10 @@ enum punit_power_well {
/* MIPI adapter registers */
-#define _MIPIA_CTRL (VLV_DISPLAY_BASE + 0xb104)
-#define _MIPIB_CTRL (VLV_DISPLAY_BASE + 0xb904)
-#define MIPI_CTRL(pipe) _PIPE(pipe, _MIPIA_CTRL, _MIPIB_CTRL)
+#define _MIPIA_CTRL (dev_priv->mipi_mmio_base + 0xb104)
+#define _MIPIB_CTRL (dev_priv->mipi_mmio_base + 0xb904)
+#define MIPI_CTRL(tc) _TRANSCODER(tc, _MIPIA_CTRL, \
+ _MIPIB_CTRL)
#define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */
#define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5)
#define ESCAPE_CLOCK_DIVIDER_1 (0 << 5)
@@ -6373,50 +6499,52 @@ enum punit_power_well {
#define READ_REQUEST_PRIORITY_HIGH (3 << 3)
#define RGB_FLIP_TO_BGR (1 << 2)
-#define _MIPIA_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb108)
-#define _MIPIB_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb908)
-#define MIPI_DATA_ADDRESS(pipe) _PIPE(pipe, _MIPIA_DATA_ADDRESS, _MIPIB_DATA_ADDRESS)
+#define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108)
+#define _MIPIB_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908)
+#define MIPI_DATA_ADDRESS(tc) _TRANSCODER(tc, _MIPIA_DATA_ADDRESS, \
+ _MIPIB_DATA_ADDRESS)
#define DATA_MEM_ADDRESS_SHIFT 5
#define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5)
#define DATA_VALID (1 << 0)
-#define _MIPIA_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb10c)
-#define _MIPIB_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb90c)
-#define MIPI_DATA_LENGTH(pipe) _PIPE(pipe, _MIPIA_DATA_LENGTH, _MIPIB_DATA_LENGTH)
+#define _MIPIA_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb10c)
+#define _MIPIB_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb90c)
+#define MIPI_DATA_LENGTH(tc) _TRANSCODER(tc, _MIPIA_DATA_LENGTH, \
+ _MIPIB_DATA_LENGTH)
#define DATA_LENGTH_SHIFT 0
#define DATA_LENGTH_MASK (0xfffff << 0)
-#define _MIPIA_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb110)
-#define _MIPIB_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb910)
-#define MIPI_COMMAND_ADDRESS(pipe) _PIPE(pipe, _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS)
+#define _MIPIA_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb110)
+#define _MIPIB_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb910)
+#define MIPI_COMMAND_ADDRESS(tc) _TRANSCODER(tc, \
+ _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS)
#define COMMAND_MEM_ADDRESS_SHIFT 5
#define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5)
#define AUTO_PWG_ENABLE (1 << 2)
#define MEMORY_WRITE_DATA_FROM_PIPE_RENDERING (1 << 1)
#define COMMAND_VALID (1 << 0)
-#define _MIPIA_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb114)
-#define _MIPIB_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb914)
-#define MIPI_COMMAND_LENGTH(pipe) _PIPE(pipe, _MIPIA_COMMAND_LENGTH, _MIPIB_COMMAND_LENGTH)
+#define _MIPIA_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb114)
+#define _MIPIB_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb914)
+#define MIPI_COMMAND_LENGTH(tc) _TRANSCODER(tc, _MIPIA_COMMAND_LENGTH, \
+ _MIPIB_COMMAND_LENGTH)
#define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */
#define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n)))
-#define _MIPIA_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb118)
-#define _MIPIB_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb918)
-#define MIPI_READ_DATA_RETURN(pipe, n) \
- (_PIPE(pipe, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */
+#define _MIPIA_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb118)
+#define _MIPIB_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb918)
+#define MIPI_READ_DATA_RETURN(tc, n) \
+ (_TRANSCODER(tc, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) \
+ + 4 * (n)) /* n: 0...7 */
-#define _MIPIA_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb138)
-#define _MIPIB_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb938)
-#define MIPI_READ_DATA_VALID(pipe) _PIPE(pipe, _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
+#define _MIPIA_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb138)
+#define _MIPIB_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb938)
+#define MIPI_READ_DATA_VALID(tc) _TRANSCODER(tc, \
+ _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
#define READ_DATA_VALID(n) (1 << (n))
/* For UMS only (deprecated): */
#define _PALETTE_A (dev_priv->info.display_mmio_offset + 0xa000)
#define _PALETTE_B (dev_priv->info.display_mmio_offset + 0xa800)
-#define _DPLL_A (dev_priv->info.display_mmio_offset + 0x6014)
-#define _DPLL_B (dev_priv->info.display_mmio_offset + 0x6018)
-#define _DPLL_A_MD (dev_priv->info.display_mmio_offset + 0x601c)
-#define _DPLL_B_MD (dev_priv->info.display_mmio_offset + 0x6020)
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 86ce39aad0ff..ae7fd8fc27f0 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -47,22 +47,45 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
intel_runtime_pm_get(dev_priv);
- /* On VLV, residency time is in CZ units rather than 1.28us */
+ /* On VLV and CHV, residency time is in CZ units rather than 1.28us */
if (IS_VALLEYVIEW(dev)) {
- u32 clkctl2;
+ u32 reg, czcount_30ns;
- clkctl2 = I915_READ(VLV_CLK_CTL2) >>
- CLK_CTL2_CZCOUNT_30NS_SHIFT;
- if (!clkctl2) {
- WARN(!clkctl2, "bogus CZ count value");
+ if (IS_CHERRYVIEW(dev))
+ reg = CHV_CLK_CTL1;
+ else
+ reg = VLV_CLK_CTL2;
+
+ czcount_30ns = I915_READ(reg) >> CLK_CTL2_CZCOUNT_30NS_SHIFT;
+
+ if (!czcount_30ns) {
+ WARN(!czcount_30ns, "bogus CZ count value");
ret = 0;
goto out;
}
- units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
+
+ units = 0;
+ div = 1000000ULL;
+
+ if (IS_CHERRYVIEW(dev)) {
+ /* Special case for 320Mhz */
+ if (czcount_30ns == 1) {
+ div = 10000000ULL;
+ units = 3125ULL;
+ } else {
+ /* chv counts are one less */
+ czcount_30ns += 1;
+ }
+ }
+
+ if (units == 0)
+ units = DIV_ROUND_UP_ULL(30ULL * bias,
+ (u64)czcount_30ns);
+
if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
units <<= 8;
- div = 1000000ULL * bias;
+ div = div * bias;
}
raw_time = I915_READ(reg) * units;
@@ -461,11 +484,20 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
mutex_unlock(&dev->struct_mutex);
if (attr == &dev_attr_gt_RP0_freq_mhz) {
- val = ((rp_state_cap & 0x0000ff) >> 0) * GT_FREQUENCY_MULTIPLIER;
+ if (IS_VALLEYVIEW(dev))
+ val = vlv_gpu_freq(dev_priv, dev_priv->rps.rp0_freq);
+ else
+ val = ((rp_state_cap & 0x0000ff) >> 0) * GT_FREQUENCY_MULTIPLIER;
} else if (attr == &dev_attr_gt_RP1_freq_mhz) {
- val = ((rp_state_cap & 0x00ff00) >> 8) * GT_FREQUENCY_MULTIPLIER;
+ if (IS_VALLEYVIEW(dev))
+ val = vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq);
+ else
+ val = ((rp_state_cap & 0x00ff00) >> 8) * GT_FREQUENCY_MULTIPLIER;
} else if (attr == &dev_attr_gt_RPn_freq_mhz) {
- val = ((rp_state_cap & 0xff0000) >> 16) * GT_FREQUENCY_MULTIPLIER;
+ if (IS_VALLEYVIEW(dev))
+ val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq);
+ else
+ val = ((rp_state_cap & 0xff0000) >> 16) * GT_FREQUENCY_MULTIPLIER;
} else {
BUG();
}
@@ -486,6 +518,9 @@ static const struct attribute *vlv_attrs[] = {
&dev_attr_gt_cur_freq_mhz.attr,
&dev_attr_gt_max_freq_mhz.attr,
&dev_attr_gt_min_freq_mhz.attr,
+ &dev_attr_gt_RP0_freq_mhz.attr,
+ &dev_attr_gt_RP1_freq_mhz.attr,
+ &dev_attr_gt_RPn_freq_mhz.attr,
&dev_attr_vlv_rpe_freq_mhz.attr,
NULL,
};
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 827498e081df..a66955037e4e 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -336,11 +336,12 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+ dev_priv->vbt.backlight.min_brightness = entry->min_brightness;
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
"active %s, min brightness %u, level %u\n",
dev_priv->vbt.backlight.pwm_freq_hz,
dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
- entry->min_brightness,
+ dev_priv->vbt.backlight.min_brightness,
backlight_data->level[panel_type]);
}
@@ -877,7 +878,7 @@ err:
/* error during parsing so set all pointers to null
* because of partial parsing */
- memset(dev_priv->vbt.dsi.sequence, 0, MIPI_SEQ_MAX);
+ memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence));
}
static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 5a045d3bd77e..2efaf8e8d9c4 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -137,6 +137,18 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
+static void hsw_crt_pre_enable(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
+ I915_WRITE(SPLL_CTL,
+ SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
+ POSTING_READ(SPLL_CTL);
+ udelay(20);
+}
+
/* Note: The caller is required to filter out dpms modes not supported by the
* platform. */
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -194,6 +206,20 @@ static void intel_disable_crt(struct intel_encoder *encoder)
intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
}
+
+static void hsw_crt_post_disable(struct intel_encoder *encoder)
+{
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t val;
+
+ DRM_DEBUG_KMS("Disabling SPLL\n");
+ val = I915_READ(SPLL_CTL);
+ WARN_ON(!(val & SPLL_PLL_ENABLE));
+ I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+ POSTING_READ(SPLL_CTL);
+}
+
static void intel_enable_crt(struct intel_encoder *encoder)
{
struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -289,8 +315,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
pipe_config->pipe_bpp = 24;
/* FDI must always be 2.7 GHz */
- if (HAS_DDI(dev))
+ if (HAS_DDI(dev)) {
+ pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
pipe_config->port_clock = 135000 * 2;
+ }
return true;
}
@@ -632,8 +660,6 @@ intel_crt_detect(struct drm_connector *connector, bool force)
struct intel_load_detect_pipe tmp;
struct drm_modeset_acquire_ctx ctx;
- intel_runtime_pm_get(dev_priv);
-
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
connector->base.id, connector->name,
force);
@@ -685,8 +711,6 @@ intel_crt_detect(struct drm_connector *connector, bool force)
out:
intel_display_power_put(dev_priv, power_domain);
- intel_runtime_pm_put(dev_priv);
-
return status;
}
@@ -860,6 +884,8 @@ void intel_crt_init(struct drm_device *dev)
if (HAS_DDI(dev)) {
crt->base.get_config = hsw_crt_get_config;
crt->base.get_hw_state = intel_ddi_get_hw_state;
+ crt->base.pre_enable = hsw_crt_pre_enable;
+ crt->base.post_disable = hsw_crt_post_disable;
} else {
crt->base.get_config = intel_crt_get_config;
crt->base.get_hw_state = intel_crt_get_hw_state;
@@ -869,7 +895,7 @@ void intel_crt_init(struct drm_device *dev)
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
if (!I915_HAS_HOTPLUG(dev))
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b17b9c7c769f..5db0b5552e39 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -76,12 +76,12 @@ static const u32 bdw_ddi_translations_edp[] = {
0x00FFFFFF, 0x00000012, /* eDP parameters */
0x00EBAFFF, 0x00020011,
0x00C71FFF, 0x0006000F,
+ 0x00AAAFFF, 0x000E000A,
0x00FFFFFF, 0x00020011,
0x00DB6FFF, 0x0005000F,
0x00BEEFFF, 0x000A000C,
0x00FFFFFF, 0x0005000F,
0x00DB6FFF, 0x000A000C,
- 0x00FFFFFF, 0x000A000C,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
};
@@ -89,12 +89,12 @@ static const u32 bdw_ddi_translations_dp[] = {
0x00FFFFFF, 0x0007000E, /* DP parameters */
0x00D75FFF, 0x000E000A,
0x00BEFFFF, 0x00140006,
+ 0x80B2CFFF, 0x001B0002,
0x00FFFFFF, 0x000E000A,
0x00D75FFF, 0x00180004,
0x80CB2FFF, 0x001B0002,
0x00F7DFFF, 0x00180004,
0x80D75FFF, 0x001B0002,
- 0x80FFFFFF, 0x001B0002,
0x00FFFFFF, 0x00140006 /* HDMI parameters 800mV 0dB*/
};
@@ -116,7 +116,10 @@ enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
struct drm_encoder *encoder = &intel_encoder->base;
int type = intel_encoder->type;
- if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
+ if (type == INTEL_OUTPUT_DP_MST) {
+ struct intel_digital_port *intel_dig_port = enc_to_mst(encoder)->primary;
+ return intel_dig_port->port;
+ } else if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(encoder);
@@ -277,7 +280,8 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
/* Configure Port Clock Select */
- I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel);
+ I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config.ddi_pll_sel);
+ WARN_ON(intel_crtc->config.ddi_pll_sel != PORT_CLK_SEL_SPLL);
/* Start the training iterating through available voltages and emphasis,
* testing each value twice. */
@@ -364,6 +368,18 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
DRM_ERROR("FDI link training failed!\n");
}
+void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+ struct intel_digital_port *intel_dig_port =
+ enc_to_dig_port(&encoder->base);
+
+ intel_dp->DP = intel_dig_port->saved_port_bits |
+ DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
+ intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
+
+}
+
static struct intel_encoder *
intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
{
@@ -385,53 +401,6 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
return ret;
}
-void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = crtc->dev->dev_private;
- struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t val;
-
- switch (intel_crtc->ddi_pll_sel) {
- case PORT_CLK_SEL_SPLL:
- plls->spll_refcount--;
- if (plls->spll_refcount == 0) {
- DRM_DEBUG_KMS("Disabling SPLL\n");
- val = I915_READ(SPLL_CTL);
- WARN_ON(!(val & SPLL_PLL_ENABLE));
- I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
- POSTING_READ(SPLL_CTL);
- }
- break;
- case PORT_CLK_SEL_WRPLL1:
- plls->wrpll1_refcount--;
- if (plls->wrpll1_refcount == 0) {
- DRM_DEBUG_KMS("Disabling WRPLL 1\n");
- val = I915_READ(WRPLL_CTL1);
- WARN_ON(!(val & WRPLL_PLL_ENABLE));
- I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE);
- POSTING_READ(WRPLL_CTL1);
- }
- break;
- case PORT_CLK_SEL_WRPLL2:
- plls->wrpll2_refcount--;
- if (plls->wrpll2_refcount == 0) {
- DRM_DEBUG_KMS("Disabling WRPLL 2\n");
- val = I915_READ(WRPLL_CTL2);
- WARN_ON(!(val & WRPLL_PLL_ENABLE));
- I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE);
- POSTING_READ(WRPLL_CTL2);
- }
- break;
- }
-
- WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n");
- WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n");
- WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n");
-
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
-}
-
#define LC_FREQ 2700
#define LC_FREQ_2K (LC_FREQ * 2000)
@@ -592,9 +561,9 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
u32 wrpll;
wrpll = I915_READ(reg);
- switch (wrpll & SPLL_PLL_REF_MASK) {
- case SPLL_PLL_SSC:
- case SPLL_PLL_NON_SSC:
+ switch (wrpll & WRPLL_PLL_REF_MASK) {
+ case WRPLL_PLL_SSC:
+ case WRPLL_PLL_NON_SSC:
/*
* We could calculate spread here, but our checking
* code only cares about 5% accuracy, and spread is a max of
@@ -602,7 +571,7 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
*/
refclk = 135;
break;
- case SPLL_PLL_LCPLL:
+ case WRPLL_PLL_LCPLL:
refclk = LC_FREQ;
break;
default:
@@ -618,15 +587,14 @@ static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
return (refclk * n * 100) / (p * r);
}
-static void intel_ddi_clock_get(struct intel_encoder *encoder,
- struct intel_crtc_config *pipe_config)
+void intel_ddi_clock_get(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
- enum port port = intel_ddi_get_encoder_port(encoder);
int link_clock = 0;
u32 val, pll;
- val = I915_READ(PORT_CLK_SEL(port));
+ val = pipe_config->ddi_pll_sel;
switch (val & PORT_CLK_SEL_MASK) {
case PORT_CLK_SEL_LCPLL_810:
link_clock = 81000;
@@ -750,173 +718,37 @@ bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
- struct drm_encoder *encoder = &intel_encoder->base;
- struct drm_i915_private *dev_priv = crtc->dev->dev_private;
- struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
int type = intel_encoder->type;
- enum pipe pipe = intel_crtc->pipe;
int clock = intel_crtc->config.port_clock;
- intel_ddi_put_crtc_pll(crtc);
-
- if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ intel_put_shared_dpll(intel_crtc);
- switch (intel_dp->link_bw) {
- case DP_LINK_BW_1_62:
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
- break;
- case DP_LINK_BW_2_7:
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
- break;
- case DP_LINK_BW_5_4:
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
- break;
- default:
- DRM_ERROR("Link bandwidth %d unsupported\n",
- intel_dp->link_bw);
- return false;
- }
-
- } else if (type == INTEL_OUTPUT_HDMI) {
- uint32_t reg, val;
+ if (type == INTEL_OUTPUT_HDMI) {
+ struct intel_shared_dpll *pll;
+ uint32_t val;
unsigned p, n2, r2;
intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
- val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+ val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
WRPLL_DIVIDER_POST(p);
- if (val == I915_READ(WRPLL_CTL1)) {
- DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n",
- pipe_name(pipe));
- reg = WRPLL_CTL1;
- } else if (val == I915_READ(WRPLL_CTL2)) {
- DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n",
- pipe_name(pipe));
- reg = WRPLL_CTL2;
- } else if (plls->wrpll1_refcount == 0) {
- DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
- pipe_name(pipe));
- reg = WRPLL_CTL1;
- } else if (plls->wrpll2_refcount == 0) {
- DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
- pipe_name(pipe));
- reg = WRPLL_CTL2;
- } else {
- DRM_ERROR("No WRPLLs available!\n");
- return false;
- }
-
- DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
- clock, p, n2, r2);
-
- if (reg == WRPLL_CTL1) {
- plls->wrpll1_refcount++;
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
- } else {
- plls->wrpll2_refcount++;
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
- }
+ intel_crtc->config.dpll_hw_state.wrpll = val;
- } else if (type == INTEL_OUTPUT_ANALOG) {
- if (plls->spll_refcount == 0) {
- DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
- pipe_name(pipe));
- plls->spll_refcount++;
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
- } else {
- DRM_ERROR("SPLL already in use\n");
+ pll = intel_get_shared_dpll(intel_crtc);
+ if (pll == NULL) {
+ DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+ pipe_name(intel_crtc->pipe));
return false;
}
- } else {
- WARN(1, "Invalid DDI encoder type %d\n", type);
- return false;
+ intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
}
return true;
}
-/*
- * To be called after intel_ddi_pll_select(). That one selects the PLL to be
- * used, this one actually enables the PLL.
- */
-void intel_ddi_pll_enable(struct intel_crtc *crtc)
-{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
- int clock = crtc->config.port_clock;
- uint32_t reg, cur_val, new_val;
- int refcount;
- const char *pll_name;
- uint32_t enable_bit = (1 << 31);
- unsigned int p, n2, r2;
-
- BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
- BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
-
- switch (crtc->ddi_pll_sel) {
- case PORT_CLK_SEL_LCPLL_2700:
- case PORT_CLK_SEL_LCPLL_1350:
- case PORT_CLK_SEL_LCPLL_810:
- /*
- * LCPLL should always be enabled at this point of the mode set
- * sequence, so nothing to do.
- */
- return;
-
- case PORT_CLK_SEL_SPLL:
- pll_name = "SPLL";
- reg = SPLL_CTL;
- refcount = plls->spll_refcount;
- new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
- SPLL_PLL_SSC;
- break;
-
- case PORT_CLK_SEL_WRPLL1:
- case PORT_CLK_SEL_WRPLL2:
- if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
- pll_name = "WRPLL1";
- reg = WRPLL_CTL1;
- refcount = plls->wrpll1_refcount;
- } else {
- pll_name = "WRPLL2";
- reg = WRPLL_CTL2;
- refcount = plls->wrpll2_refcount;
- }
-
- intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
- new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
- WRPLL_DIVIDER_REFERENCE(r2) |
- WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
-
- break;
-
- case PORT_CLK_SEL_NONE:
- WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
- return;
- default:
- WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
- return;
- }
-
- cur_val = I915_READ(reg);
-
- WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
- if (refcount == 1) {
- WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
- I915_WRITE(reg, new_val);
- POSTING_READ(reg);
- udelay(20);
- } else {
- WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
- }
-}
-
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -926,8 +758,7 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
int type = intel_encoder->type;
uint32_t temp;
- if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
-
+ if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) {
temp = TRANS_MSA_SYNC_CLK;
switch (intel_crtc->config.pipe_bpp) {
case 18:
@@ -949,6 +780,21 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
}
}
+void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+ uint32_t temp;
+ temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+ if (state == true)
+ temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+ else
+ temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+ I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
+}
+
void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -995,7 +841,9 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
* eDP when not using the panel fitter, and when not
* using motion blur mitigation (which we don't
* support). */
- if (IS_HASWELL(dev) && intel_crtc->config.pch_pfit.enabled)
+ if (IS_HASWELL(dev) &&
+ (intel_crtc->config.pch_pfit.enabled ||
+ intel_crtc->config.pch_pfit.force_thru))
temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
else
temp |= TRANS_DDI_EDP_INPUT_A_ON;
@@ -1026,7 +874,19 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+ if (intel_dp->is_mst) {
+ temp |= TRANS_DDI_MODE_SELECT_DP_MST;
+ } else
+ temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+
+ temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
+ } else if (type == INTEL_OUTPUT_DP_MST) {
+ struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
+
+ if (intel_dp->is_mst) {
+ temp |= TRANS_DDI_MODE_SELECT_DP_MST;
+ } else
+ temp |= TRANS_DDI_MODE_SELECT_DP_SST;
temp |= DDI_PORT_WIDTH(intel_dp->lane_count);
} else {
@@ -1043,7 +903,7 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
uint32_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
uint32_t val = I915_READ(reg);
- val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK);
+ val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
val |= TRANS_DDI_PORT_NONE;
I915_WRITE(reg, val);
}
@@ -1082,8 +942,11 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
case TRANS_DDI_MODE_SELECT_DP_SST:
if (type == DRM_MODE_CONNECTOR_eDP)
return true;
- case TRANS_DDI_MODE_SELECT_DP_MST:
return (type == DRM_MODE_CONNECTOR_DisplayPort);
+ case TRANS_DDI_MODE_SELECT_DP_MST:
+ /* if the transcoder is in MST state then
+ * connector isn't connected */
+ return false;
case TRANS_DDI_MODE_SELECT_FDI:
return (type == DRM_MODE_CONNECTOR_VGA);
@@ -1135,6 +998,9 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
if ((tmp & TRANS_DDI_PORT_MASK)
== TRANS_DDI_SELECT_PORT(port)) {
+ if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST)
+ return false;
+
*pipe = i;
return true;
}
@@ -1146,76 +1012,6 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
return false;
}
-static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- uint32_t temp, ret;
- enum port port = I915_MAX_PORTS;
- enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
- pipe);
- int i;
-
- if (cpu_transcoder == TRANSCODER_EDP) {
- port = PORT_A;
- } else {
- temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
- temp &= TRANS_DDI_PORT_MASK;
-
- for (i = PORT_B; i <= PORT_E; i++)
- if (temp == TRANS_DDI_SELECT_PORT(i))
- port = i;
- }
-
- if (port == I915_MAX_PORTS) {
- WARN(1, "Pipe %c enabled on an unknown port\n",
- pipe_name(pipe));
- ret = PORT_CLK_SEL_NONE;
- } else {
- ret = I915_READ(PORT_CLK_SEL(port));
- DRM_DEBUG_KMS("Pipe %c connected to port %c using clock "
- "0x%08x\n", pipe_name(pipe), port_name(port),
- ret);
- }
-
- return ret;
-}
-
-void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- enum pipe pipe;
- struct intel_crtc *intel_crtc;
-
- dev_priv->ddi_plls.spll_refcount = 0;
- dev_priv->ddi_plls.wrpll1_refcount = 0;
- dev_priv->ddi_plls.wrpll2_refcount = 0;
-
- for_each_pipe(pipe) {
- intel_crtc =
- to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-
- if (!intel_crtc->active) {
- intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
- continue;
- }
-
- intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
- pipe);
-
- switch (intel_crtc->ddi_pll_sel) {
- case PORT_CLK_SEL_SPLL:
- dev_priv->ddi_plls.spll_refcount++;
- break;
- case PORT_CLK_SEL_WRPLL1:
- dev_priv->ddi_plls.wrpll1_refcount++;
- break;
- case PORT_CLK_SEL_WRPLL2:
- dev_priv->ddi_plls.wrpll2_refcount++;
- break;
- }
- }
-}
-
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
@@ -1261,17 +1057,13 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
intel_edp_panel_on(intel_dp);
}
- WARN_ON(crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
- I915_WRITE(PORT_CLK_SEL(port), crtc->ddi_pll_sel);
+ WARN_ON(crtc->config.ddi_pll_sel == PORT_CLK_SEL_NONE);
+ I915_WRITE(PORT_CLK_SEL(port), crtc->config.ddi_pll_sel);
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct intel_digital_port *intel_dig_port =
- enc_to_dig_port(encoder);
- intel_dp->DP = intel_dig_port->saved_port_bits |
- DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
- intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
+ intel_ddi_init_dp_buf_reg(intel_encoder);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
intel_dp_start_link_train(intel_dp);
@@ -1418,10 +1210,60 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
}
}
+static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll);
+ POSTING_READ(WRPLL_CTL(pll->id));
+ udelay(20);
+}
+
+static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll)
+{
+ uint32_t val;
+
+ val = I915_READ(WRPLL_CTL(pll->id));
+ I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
+ POSTING_READ(WRPLL_CTL(pll->id));
+}
+
+static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+ struct intel_shared_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
+{
+ uint32_t val;
+
+ if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+ return false;
+
+ val = I915_READ(WRPLL_CTL(pll->id));
+ hw_state->wrpll = val;
+
+ return val & WRPLL_PLL_ENABLE;
+}
+
+static const char * const hsw_ddi_pll_names[] = {
+ "WRPLL 1",
+ "WRPLL 2",
+};
+
void intel_ddi_pll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
+ int i;
+
+ dev_priv->num_shared_dpll = 2;
+
+ for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+ dev_priv->shared_dplls[i].id = i;
+ dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
+ dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
+ dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
+ dev_priv->shared_dplls[i].get_hw_state =
+ hsw_ddi_pll_get_hw_state;
+ }
/* The LCPLL register should be turned on by the BIOS. For now let's
* just check its state and print errors in case something is wrong.
@@ -1465,10 +1307,15 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
intel_wait_ddi_buf_idle(dev_priv, port);
}
- val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
+ val = DP_TP_CTL_ENABLE |
DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
- if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
- val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+ if (intel_dp->is_mst)
+ val |= DP_TP_CTL_MODE_MST;
+ else {
+ val |= DP_TP_CTL_MODE_SST;
+ if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+ val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+ }
I915_WRITE(DP_TP_CTL(port), val);
POSTING_READ(DP_TP_CTL(port));
@@ -1507,11 +1354,16 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc)
static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
{
- struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
- int type = intel_encoder->type;
+ struct intel_digital_port *intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+ int type = intel_dig_port->base.type;
+
+ if (type != INTEL_OUTPUT_DISPLAYPORT &&
+ type != INTEL_OUTPUT_EDP &&
+ type != INTEL_OUTPUT_UNKNOWN) {
+ return;
+ }
- if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP)
- intel_dp_check_link_status(intel_dp);
+ intel_dp_hot_plug(intel_encoder);
}
void intel_ddi_get_config(struct intel_encoder *encoder,
@@ -1663,15 +1515,13 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
- struct intel_connector *hdmi_connector = NULL;
- struct intel_connector *dp_connector = NULL;
bool init_hdmi, init_dp;
init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
dev_priv->vbt.ddi_port_info[port].supports_hdmi);
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
if (!init_dp && !init_hdmi) {
- DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n",
+ DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n",
port_name(port));
init_hdmi = true;
init_dp = true;
@@ -1701,20 +1551,28 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
DDI_A_4_LANES);
intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
- intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = 0;
intel_encoder->hot_plug = intel_ddi_hot_plug;
- if (init_dp)
- dp_connector = intel_ddi_init_dp_connector(intel_dig_port);
+ if (init_dp) {
+ if (!intel_ddi_init_dp_connector(intel_dig_port))
+ goto err;
+
+ intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
+ dev_priv->hpd_irq_port[port] = intel_dig_port;
+ }
/* In theory we don't need the encoder->type check, but leave it just in
* case we have some really bad VBTs... */
- if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi)
- hdmi_connector = intel_ddi_init_hdmi_connector(intel_dig_port);
-
- if (!dp_connector && !hdmi_connector) {
- drm_encoder_cleanup(encoder);
- kfree(intel_dig_port);
+ if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
+ if (!intel_ddi_init_hdmi_connector(intel_dig_port))
+ goto err;
}
+
+ return;
+
+err:
+ drm_encoder_cleanup(encoder);
+ kfree(intel_dig_port);
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f0be855ddf45..018fb7222f60 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -39,12 +39,45 @@
#include "i915_trace.h"
#include <drm/drm_dp_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_rect.h>
#include <linux/dma_remapping.h>
+/* Primary plane formats supported by all gen */
+#define COMMON_PRIMARY_FORMATS \
+ DRM_FORMAT_C8, \
+ DRM_FORMAT_RGB565, \
+ DRM_FORMAT_XRGB8888, \
+ DRM_FORMAT_ARGB8888
+
+/* Primary plane formats for gen <= 3 */
+static const uint32_t intel_primary_formats_gen2[] = {
+ COMMON_PRIMARY_FORMATS,
+ DRM_FORMAT_XRGB1555,
+ DRM_FORMAT_ARGB1555,
+};
+
+/* Primary plane formats for gen >= 4 */
+static const uint32_t intel_primary_formats_gen4[] = {
+ COMMON_PRIMARY_FORMATS, \
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XRGB2101010,
+ DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_ABGR2101010,
+};
+
+/* Cursor formats */
+static const uint32_t intel_cursor_formats[] = {
+ DRM_FORMAT_ARGB8888,
+};
+
#define DIV_ROUND_CLOSEST_ULL(ll, d) \
- ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
+({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
-static void intel_increase_pllclock(struct drm_crtc *crtc);
+static void intel_increase_pllclock(struct drm_device *dev,
+ enum pipe pipe);
static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
@@ -68,6 +101,14 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc);
static void intel_set_pipe_csc(struct drm_crtc *crtc);
static void vlv_prepare_pll(struct intel_crtc *crtc);
+static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
+{
+ if (!connector->mst_port)
+ return connector->encoder;
+ else
+ return &connector->mst_port->mst_encoders[pipe]->base;
+}
+
typedef struct {
int min, max;
} intel_range_t;
@@ -1061,11 +1102,6 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
bool cur_state;
struct intel_dpll_hw_state hw_state;
- if (HAS_PCH_LPT(dev_priv->dev)) {
- DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
- return;
- }
-
if (WARN (!pll,
"asserting DPLL %s with no DPLL\n", state_string(state)))
return;
@@ -1481,9 +1517,6 @@ static void intel_reset_dpio(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (!IS_VALLEYVIEW(dev))
- return;
-
if (IS_CHERRYVIEW(dev)) {
enum dpio_phy phy;
u32 val;
@@ -1505,26 +1538,6 @@ static void intel_reset_dpio(struct drm_device *dev)
I915_WRITE(DISPLAY_PHY_CONTROL,
PHY_COM_LANE_RESET_DEASSERT(phy, val));
}
-
- } else {
- /*
- * If DPIO has already been reset, e.g. by BIOS, just skip all
- * this.
- */
- if (I915_READ(DPIO_CTL) & DPIO_CMNRST)
- return;
-
- /*
- * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
- * Need to assert and de-assert PHY SB reset by gating the
- * common lane power, then un-gating it.
- * Simply ungating isn't enough to reset the PHY enough to get
- * ports and lanes running.
- */
- __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
- false);
- __vlv_set_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC,
- true);
}
}
@@ -1712,6 +1725,17 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
val &= ~DPIO_DCLKP_EN;
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
+ /* disable left/right clock distribution */
+ if (pipe != PIPE_B) {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+ val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+ } else {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+ val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+ }
+
mutex_unlock(&dev_priv->dpio_lock);
}
@@ -1749,6 +1773,9 @@ static void intel_prepare_shared_dpll(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
+ if (WARN_ON(pll == NULL))
+ return;
+
WARN_ON(!pll->refcount);
if (pll->active == 0) {
DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
@@ -1790,12 +1817,14 @@ static void intel_enable_shared_dpll(struct intel_crtc *crtc)
}
WARN_ON(pll->on);
+ intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
+
DRM_DEBUG_KMS("enabling %s\n", pll->name);
pll->enable(dev_priv, pll);
pll->on = true;
}
-static void intel_disable_shared_dpll(struct intel_crtc *crtc)
+void intel_disable_shared_dpll(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1826,6 +1855,8 @@ static void intel_disable_shared_dpll(struct intel_crtc *crtc)
DRM_DEBUG_KMS("disabling %s\n", pll->name);
pll->disable(dev_priv, pll);
pll->on = false;
+
+ intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
}
static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
@@ -2172,6 +2203,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
u32 alignment;
int ret;
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
switch (obj->tiling_mode) {
case I915_TILING_NONE:
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
@@ -2228,6 +2261,8 @@ err_interruptible:
void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
{
+ WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
+
i915_gem_object_unpin_fence(obj);
i915_gem_object_unpin_from_display_plane(obj);
}
@@ -2314,6 +2349,7 @@ static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
goto out_unref_obj;
}
+ obj->frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(crtc->pipe);
mutex_unlock(&dev->struct_mutex);
DRM_DEBUG_KMS("plane fb obj %p\n", obj);
@@ -2331,7 +2367,7 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
struct drm_device *dev = intel_crtc->base.dev;
struct drm_crtc *c;
struct intel_crtc *i;
- struct intel_framebuffer *fb;
+ struct drm_i915_gem_object *obj;
if (!intel_crtc->base.primary->fb)
return;
@@ -2352,13 +2388,17 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
if (c == &intel_crtc->base)
continue;
- if (!i->active || !c->primary->fb)
+ if (!i->active)
+ continue;
+
+ obj = intel_fb_obj(c->primary->fb);
+ if (obj == NULL)
continue;
- fb = to_intel_framebuffer(c->primary->fb);
- if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
+ if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
drm_framebuffer_reference(c->primary->fb);
intel_crtc->base.primary->fb = c->primary->fb;
+ obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
break;
}
}
@@ -2371,16 +2411,12 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_framebuffer *intel_fb;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
u32 reg;
- intel_fb = to_intel_framebuffer(fb);
- obj = intel_fb->obj;
-
reg = DSPCNTR(plane);
dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */
@@ -2461,16 +2497,12 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_framebuffer *intel_fb;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
u32 reg;
- intel_fb = to_intel_framebuffer(fb);
- obj = intel_fb->obj;
-
reg = DSPCNTR(plane);
dspcntr = I915_READ(reg);
/* Mask out pixel format bits in case we change it */
@@ -2546,7 +2578,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
if (dev_priv->display.disable_fbc)
dev_priv->display.disable_fbc(dev);
- intel_increase_pllclock(crtc);
+ intel_increase_pllclock(dev, to_intel_crtc(crtc)->pipe);
dev_priv->display.update_primary_plane(crtc, fb, x, y);
@@ -2601,7 +2633,7 @@ void intel_display_handle_reset(struct drm_device *dev)
static int
intel_finish_fb(struct drm_framebuffer *old_fb)
{
- struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
bool was_interruptible = dev_priv->mm.interruptible;
int ret;
@@ -2647,7 +2679,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_framebuffer *old_fb;
+ enum pipe pipe = intel_crtc->pipe;
+ struct drm_framebuffer *old_fb = crtc->primary->fb;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
int ret;
if (intel_crtc_has_pending_flip(crtc)) {
@@ -2669,9 +2704,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
}
mutex_lock(&dev->struct_mutex);
- ret = intel_pin_and_fence_fb_obj(dev,
- to_intel_framebuffer(fb)->obj,
- NULL);
+ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+ if (ret == 0)
+ i915_gem_track_fb(old_obj, obj,
+ INTEL_FRONTBUFFER_PRIMARY(pipe));
mutex_unlock(&dev->struct_mutex);
if (ret != 0) {
DRM_ERROR("pin & fence failed\n");
@@ -2711,7 +2747,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
dev_priv->display.update_primary_plane(crtc, fb, x, y);
- old_fb = crtc->primary->fb;
+ if (intel_crtc->active)
+ intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
+
crtc->primary->fb = fb;
crtc->x = x;
crtc->y = y;
@@ -2720,13 +2758,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
if (intel_crtc->active && old_fb != fb)
intel_wait_for_vblank(dev, intel_crtc->pipe);
mutex_lock(&dev->struct_mutex);
- intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
+ intel_unpin_fb_obj(old_obj);
mutex_unlock(&dev->struct_mutex);
}
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
- intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
return 0;
@@ -3587,7 +3624,7 @@ static void lpt_pch_enable(struct drm_crtc *crtc)
lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
}
-static void intel_put_shared_dpll(struct intel_crtc *crtc)
+void intel_put_shared_dpll(struct intel_crtc *crtc)
{
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
@@ -3607,7 +3644,7 @@ static void intel_put_shared_dpll(struct intel_crtc *crtc)
crtc->config.shared_dpll = DPLL_ID_PRIVATE;
}
-static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
@@ -3818,7 +3855,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
}
/* use legacy palette for Ironlake */
- if (HAS_PCH_SPLIT(dev))
+ if (!HAS_GMCH_DISPLAY(dev))
palreg = LGC_PALETTE(pipe);
/* Workaround : Do not read or write the pipe palette/gamma data while
@@ -3860,30 +3897,6 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
*/
}
-/**
- * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
- * cursor plane briefly if not already running after enabling the display
- * plane.
- * This workaround avoids occasional blank screens when self refresh is
- * enabled.
- */
-static void
-g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
- u32 cntl = I915_READ(CURCNTR(pipe));
-
- if ((cntl & CURSOR_MODE) == 0) {
- u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
-
- I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
- I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
- intel_wait_for_vblank(dev_priv->dev, pipe);
- I915_WRITE(CURCNTR(pipe), cntl);
- I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
- I915_WRITE(FW_BLC_SELF, fw_bcl_self);
- }
-}
-
static void intel_crtc_enable_planes(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3892,11 +3905,10 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
+ drm_vblank_on(dev, pipe);
+
intel_enable_primary_hw_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
- /* The fixup needs to happen before cursor is enabled */
- if (IS_G4X(dev))
- g4x_fixup_plane(dev_priv, pipe);
intel_crtc_update_cursor(crtc, true);
intel_crtc_dpms_overlay(intel_crtc, true);
@@ -3904,8 +3916,14 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
- intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
+
+ /*
+ * FIXME: Once we grow proper nuclear flip support out of this we need
+ * to compute the mask of flip planes precisely. For the time being
+ * consider this a flip from a NULL plane.
+ */
+ intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
}
static void intel_crtc_disable_planes(struct drm_crtc *crtc)
@@ -3917,7 +3935,6 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
int plane = intel_crtc->plane;
intel_crtc_wait_for_pending_flips(crtc);
- drm_crtc_vblank_off(crtc);
if (dev_priv->fbc.plane == plane)
intel_disable_fbc(dev);
@@ -3928,6 +3945,15 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, false);
intel_disable_planes(crtc);
intel_disable_primary_hw_plane(dev_priv, plane, pipe);
+
+ /*
+ * FIXME: Once we grow proper nuclear flip support out of this we need
+ * to compute the mask of flip planes precisely. For the time being
+ * consider this a flip to a NULL plane.
+ */
+ intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
+
+ drm_vblank_off(dev, pipe);
}
static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@ -4006,8 +4032,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
cpt_verify_modeset(dev, intel_crtc->pipe);
intel_crtc_enable_planes(crtc);
-
- drm_crtc_vblank_on(crtc);
}
/* IPS only exists on ULT machines and is tied to pipe A. */
@@ -4059,6 +4083,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->active)
return;
+ if (intel_crtc_to_shared_dpll(intel_crtc))
+ intel_enable_shared_dpll(intel_crtc);
+
if (intel_crtc->config.has_dp_encoder)
intel_dp_set_m_n(intel_crtc);
@@ -4083,16 +4110,15 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
- if (intel_crtc->config.has_pch_encoder)
- intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
-
- if (intel_crtc->config.has_pch_encoder)
- dev_priv->display.fdi_link_train(crtc);
-
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
encoder->pre_enable(encoder);
+ if (intel_crtc->config.has_pch_encoder) {
+ intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
+ dev_priv->display.fdi_link_train(crtc);
+ }
+
intel_ddi_enable_pipe_clock(intel_crtc);
ironlake_pfit_enable(intel_crtc);
@@ -4112,6 +4138,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config.has_pch_encoder)
lpt_pch_enable(crtc);
+ if (intel_crtc->config.dp_encoder_is_mst)
+ intel_ddi_set_vc_payload_alloc(crtc, true);
+
for_each_encoder_on_crtc(dev, crtc, encoder) {
encoder->enable(encoder);
intel_opregion_notify_encoder(encoder, true);
@@ -4121,8 +4150,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
* to change the workaround. */
haswell_mode_set_planes_workaround(intel_crtc);
intel_crtc_enable_planes(crtc);
-
- drm_crtc_vblank_on(crtc);
}
static void ironlake_pfit_disable(struct intel_crtc *crtc)
@@ -4162,6 +4189,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
intel_disable_pipe(dev_priv, pipe);
+ if (intel_crtc->config.dp_encoder_is_mst)
+ intel_ddi_set_vc_payload_alloc(crtc, false);
+
ironlake_pfit_disable(intel_crtc);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4200,7 +4230,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
- intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4233,23 +4262,25 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
intel_ddi_disable_pipe_clock(intel_crtc);
- for_each_encoder_on_crtc(dev, crtc, encoder)
- if (encoder->post_disable)
- encoder->post_disable(encoder);
-
if (intel_crtc->config.has_pch_encoder) {
lpt_disable_pch_transcoder(dev_priv);
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
intel_ddi_fdi_disable(crtc);
}
+ for_each_encoder_on_crtc(dev, crtc, encoder)
+ if (encoder->post_disable)
+ encoder->post_disable(encoder);
+
intel_crtc->active = false;
intel_update_watermarks(crtc);
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
- intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
+
+ if (intel_crtc_to_shared_dpll(intel_crtc))
+ intel_disable_shared_dpll(intel_crtc);
}
static void ironlake_crtc_off(struct drm_crtc *crtc)
@@ -4258,10 +4289,6 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
intel_put_shared_dpll(intel_crtc);
}
-static void haswell_crtc_off(struct drm_crtc *crtc)
-{
- intel_ddi_put_crtc_pll(crtc);
-}
static void i9xx_pfit_enable(struct intel_crtc *crtc)
{
@@ -4287,6 +4314,23 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
I915_WRITE(BCLRPAT(crtc->pipe), 0);
}
+static enum intel_display_power_domain port_to_power_domain(enum port port)
+{
+ switch (port) {
+ case PORT_A:
+ return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+ case PORT_B:
+ return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+ case PORT_C:
+ return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+ case PORT_D:
+ return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+ default:
+ WARN_ON_ONCE(1);
+ return POWER_DOMAIN_PORT_OTHER;
+ }
+}
+
#define for_each_power_domain(domain, mask) \
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
if ((1 << (domain)) & (mask))
@@ -4305,19 +4349,10 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder)
case INTEL_OUTPUT_HDMI:
case INTEL_OUTPUT_EDP:
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
- switch (intel_dig_port->port) {
- case PORT_A:
- return POWER_DOMAIN_PORT_DDI_A_4_LANES;
- case PORT_B:
- return POWER_DOMAIN_PORT_DDI_B_4_LANES;
- case PORT_C:
- return POWER_DOMAIN_PORT_DDI_C_4_LANES;
- case PORT_D:
- return POWER_DOMAIN_PORT_DDI_D_4_LANES;
- default:
- WARN_ON_ONCE(1);
- return POWER_DOMAIN_PORT_OTHER;
- }
+ return port_to_power_domain(intel_dig_port->port);
+ case INTEL_OUTPUT_DP_MST:
+ intel_dig_port = enc_to_mst(&intel_encoder->base)->primary;
+ return port_to_power_domain(intel_dig_port->port);
case INTEL_OUTPUT_ANALOG:
return POWER_DOMAIN_PORT_CRT;
case INTEL_OUTPUT_DSI:
@@ -4333,7 +4368,6 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
struct intel_encoder *intel_encoder;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
- bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
unsigned long mask;
enum transcoder transcoder;
@@ -4341,7 +4375,8 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
mask = BIT(POWER_DOMAIN_PIPE(pipe));
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
- if (pfit_enabled)
+ if (intel_crtc->config.pch_pfit.enabled ||
+ intel_crtc->config.pch_pfit.force_thru)
mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
@@ -4398,7 +4433,8 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev)
intel_display_set_init_power(dev_priv, false);
}
-int valleyview_get_vco(struct drm_i915_private *dev_priv)
+/* returns HPLL frequency in kHz */
+static int valleyview_get_vco(struct drm_i915_private *dev_priv)
{
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
@@ -4408,7 +4444,23 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv)
CCK_FUSE_HPLL_FREQ_MASK;
mutex_unlock(&dev_priv->dpio_lock);
- return vco_freq[hpll_freq];
+ return vco_freq[hpll_freq] * 1000;
+}
+
+static void vlv_update_cdclk(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ dev_priv->vlv_cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+ DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz",
+ dev_priv->vlv_cdclk_freq);
+
+ /*
+ * Program the gmbus_freq based on the cdclk frequency.
+ * BSpec erroneously claims we should aim for 4MHz, but
+ * in fact 1MHz is the correct frequency.
+ */
+ I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq);
}
/* Adjust CDclk dividers to allow high res or save power if possible */
@@ -4417,12 +4469,11 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 val, cmd;
- WARN_ON(valleyview_cur_cdclk(dev_priv) != dev_priv->vlv_cdclk_freq);
- dev_priv->vlv_cdclk_freq = cdclk;
+ WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq);
- if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
+ if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
cmd = 2;
- else if (cdclk == 266)
+ else if (cdclk == 266667)
cmd = 1;
else
cmd = 0;
@@ -4439,18 +4490,23 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
}
mutex_unlock(&dev_priv->rps.hw_lock);
- if (cdclk == 400) {
+ if (cdclk == 400000) {
u32 divider, vco;
vco = valleyview_get_vco(dev_priv);
- divider = ((vco << 1) / cdclk) - 1;
+ divider = DIV_ROUND_CLOSEST(vco << 1, cdclk) - 1;
mutex_lock(&dev_priv->dpio_lock);
/* adjust cdclk divider */
val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
- val &= ~0xf;
+ val &= ~DISPLAY_FREQUENCY_VALUES;
val |= divider;
vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+
+ if (wait_for((vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL) &
+ DISPLAY_FREQUENCY_STATUS) == (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
+ 50))
+ DRM_ERROR("timed out waiting for CDclk change\n");
mutex_unlock(&dev_priv->dpio_lock);
}
@@ -4463,54 +4519,43 @@ static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
* For high bandwidth configs, we set a higher latency in the bunit
* so that the core display fetch happens in time to avoid underruns.
*/
- if (cdclk == 400)
+ if (cdclk == 400000)
val |= 4500 / 250; /* 4.5 usec */
else
val |= 3000 / 250; /* 3.0 usec */
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
mutex_unlock(&dev_priv->dpio_lock);
- /* Since we changed the CDclk, we need to update the GMBUSFREQ too */
- intel_i2c_reset(dev);
-}
-
-int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
-{
- int cur_cdclk, vco;
- int divider;
-
- vco = valleyview_get_vco(dev_priv);
-
- mutex_lock(&dev_priv->dpio_lock);
- divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
- mutex_unlock(&dev_priv->dpio_lock);
-
- divider &= 0xf;
-
- cur_cdclk = (vco << 1) / (divider + 1);
-
- return cur_cdclk;
+ vlv_update_cdclk(dev);
}
static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
int max_pixclk)
{
+ int vco = valleyview_get_vco(dev_priv);
+ int freq_320 = (vco << 1) % 320000 != 0 ? 333333 : 320000;
+
/*
* Really only a few cases to deal with, as only 4 CDclks are supported:
* 200MHz
* 267MHz
- * 320MHz
+ * 320/333MHz (depends on HPLL freq)
* 400MHz
* So we check to see whether we're above 90% of the lower bin and
* adjust if needed.
+ *
+ * We seem to get an unstable or solid color picture at 200MHz.
+ * Not sure what's wrong. For now use 200MHz only when all pipes
+ * are off.
*/
- if (max_pixclk > 288000) {
- return 400;
- } else if (max_pixclk > 240000) {
- return 320;
- } else
- return 266;
- /* Looks like the 200MHz CDclk freq doesn't work on some configs */
+ if (max_pixclk > freq_320*9/10)
+ return 400000;
+ else if (max_pixclk > 266667*9/10)
+ return freq_320;
+ else if (max_pixclk > 0)
+ return 266667;
+ else
+ return 200000;
}
/* compute the max pixel clock for new configuration */
@@ -4633,8 +4678,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_enable_planes(crtc);
- drm_crtc_vblank_on(crtc);
-
/* Underruns don't raise interrupts, so check manually. */
i9xx_check_fifo_underruns(dev);
}
@@ -4727,8 +4770,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
- drm_crtc_vblank_on(crtc);
-
/* Underruns don't raise interrupts, so check manually. */
i9xx_check_fifo_underruns(dev);
}
@@ -4768,6 +4809,16 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
+ /*
+ * Vblank time updates from the shadow to live plane control register
+ * are blocked if the memory self-refresh mode is active at that
+ * moment. So to make sure the plane gets truly disabled, disable
+ * first the self-refresh mode. The self-refresh enable bit in turn
+ * will be checked/applied by the HW only at the next frame start
+ * event which is after the vblank start event, so we need to have a
+ * wait-for-vblank between disabling the plane and the pipe.
+ */
+ intel_set_memory_cxsr(dev_priv, false);
intel_crtc_disable_planes(crtc);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4776,9 +4827,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
/*
* On gen2 planes are double buffered but the pipe isn't, so we must
* wait for planes to fully turn off before disabling the pipe.
+ * We also need to wait on all gmch platforms because of the
+ * self-refresh mode constraint explained above.
*/
- if (IS_GEN2(dev))
- intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev, pipe);
intel_disable_pipe(dev_priv, pipe);
@@ -4805,7 +4857,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
- intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4843,23 +4894,49 @@ static void intel_crtc_update_sarea(struct drm_crtc *crtc,
}
}
+/* Master function to enable/disable CRTC and corresponding power wells */
+void intel_crtc_control(struct drm_crtc *crtc, bool enable)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum intel_display_power_domain domain;
+ unsigned long domains;
+
+ if (enable) {
+ if (!intel_crtc->active) {
+ domains = get_crtc_power_domains(crtc);
+ for_each_power_domain(domain, domains)
+ intel_display_power_get(dev_priv, domain);
+ intel_crtc->enabled_power_domains = domains;
+
+ dev_priv->display.crtc_enable(crtc);
+ }
+ } else {
+ if (intel_crtc->active) {
+ dev_priv->display.crtc_disable(crtc);
+
+ domains = intel_crtc->enabled_power_domains;
+ for_each_power_domain(domain, domains)
+ intel_display_power_put(dev_priv, domain);
+ intel_crtc->enabled_power_domains = 0;
+ }
+ }
+}
+
/**
* Sets the power management mode of the pipe and plane.
*/
void intel_crtc_update_dpms(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder;
bool enable = false;
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
enable |= intel_encoder->connectors_active;
- if (enable)
- dev_priv->display.crtc_enable(crtc);
- else
- dev_priv->display.crtc_disable(crtc);
+ intel_crtc_control(crtc, enable);
intel_crtc_update_sarea(crtc, enable);
}
@@ -4869,6 +4946,8 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_connector *connector;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb);
+ enum pipe pipe = to_intel_crtc(crtc)->pipe;
/* crtc should still be enabled when we disable it. */
WARN_ON(!crtc->enabled);
@@ -4877,13 +4956,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
intel_crtc_update_sarea(crtc, false);
dev_priv->display.off(crtc);
- assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
- assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
- assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
-
if (crtc->primary->fb) {
mutex_lock(&dev->struct_mutex);
- intel_unpin_fb_obj(to_intel_framebuffer(crtc->primary->fb)->obj);
+ intel_unpin_fb_obj(old_obj);
+ i915_gem_track_fb(old_obj, NULL,
+ INTEL_FRONTBUFFER_PRIMARY(pipe));
mutex_unlock(&dev->struct_mutex);
crtc->primary->fb = NULL;
}
@@ -4939,24 +5016,31 @@ static void intel_connector_check_state(struct intel_connector *connector)
connector->base.base.id,
connector->base.name);
+ /* there is no real hw state for MST connectors */
+ if (connector->mst_port)
+ return;
+
WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
"wrong connector dpms state\n");
WARN(connector->base.encoder != &encoder->base,
"active connector not linked to encoder\n");
- WARN(!encoder->connectors_active,
- "encoder->connectors_active not set\n");
- encoder_enabled = encoder->get_hw_state(encoder, &pipe);
- WARN(!encoder_enabled, "encoder not enabled\n");
- if (WARN_ON(!encoder->base.crtc))
- return;
+ if (encoder) {
+ WARN(!encoder->connectors_active,
+ "encoder->connectors_active not set\n");
+
+ encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+ WARN(!encoder_enabled, "encoder not enabled\n");
+ if (WARN_ON(!encoder->base.crtc))
+ return;
- crtc = encoder->base.crtc;
+ crtc = encoder->base.crtc;
- WARN(!crtc->enabled, "crtc not enabled\n");
- WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
- WARN(pipe != to_intel_crtc(crtc)->pipe,
- "encoder active on the wrong pipe\n");
+ WARN(!crtc->enabled, "crtc not enabled\n");
+ WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
+ WARN(pipe != to_intel_crtc(crtc)->pipe,
+ "encoder active on the wrong pipe\n");
+ }
}
}
@@ -5161,9 +5245,11 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
if (HAS_IPS(dev))
hsw_compute_ips_config(crtc, pipe_config);
- /* XXX: PCH clock sharing is done in ->mode_set, so make sure the old
- * clock survives for now. */
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+ /*
+ * XXX: PCH/WRPLL clock sharing is done in ->mode_set, so make sure the
+ * old clock survives for now.
+ */
+ if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev) || HAS_DDI(dev))
pipe_config->shared_dpll = crtc->config.shared_dpll;
if (pipe_config->has_pch_encoder)
@@ -5174,7 +5260,22 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
static int valleyview_get_display_clock_speed(struct drm_device *dev)
{
- return 400000; /* FIXME */
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int vco = valleyview_get_vco(dev_priv);
+ u32 val;
+ int divider;
+
+ mutex_lock(&dev_priv->dpio_lock);
+ val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ divider = val & DISPLAY_FREQUENCY_VALUES;
+
+ WARN((val & DISPLAY_FREQUENCY_STATUS) !=
+ (divider << DISPLAY_FREQUENCY_STATUS_SHIFT),
+ "cdclk change in progress\n");
+
+ return DIV_ROUND_CLOSEST(vco << 1, divider + 1);
}
static int i945_get_display_clock_speed(struct drm_device *dev)
@@ -6060,6 +6161,10 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
u32 mdiv;
int refclk = 100000;
+ /* In case of MIPI DPLL will not even be used */
+ if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
+ return;
+
mutex_lock(&dev_priv->dpio_lock);
mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
mutex_unlock(&dev_priv->dpio_lock);
@@ -6125,8 +6230,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
plane_config->tiled);
- plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
- aligned_height, PAGE_SIZE);
+ plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
+ aligned_height);
DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
pipe, plane, crtc->base.primary->fb->width,
@@ -7145,8 +7250,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
aligned_height = intel_align_height(dev, crtc->base.primary->fb->height,
plane_config->tiled);
- plane_config->size = ALIGN(crtc->base.primary->fb->pitches[0] *
- aligned_height, PAGE_SIZE);
+ plane_config->size = PAGE_ALIGN(crtc->base.primary->fb->pitches[0] *
+ aligned_height);
DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
pipe, plane, crtc->base.primary->fb->width,
@@ -7163,6 +7268,10 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t tmp;
+ if (!intel_display_power_enabled(dev_priv,
+ POWER_DOMAIN_PIPE(crtc->pipe)))
+ return false;
+
pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
@@ -7237,7 +7346,6 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
- struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
struct intel_crtc *crtc;
for_each_intel_crtc(dev, crtc)
@@ -7245,14 +7353,15 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
pipe_name(crtc->pipe));
WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
- WARN(plls->spll_refcount, "SPLL enabled\n");
- WARN(plls->wrpll1_refcount, "WRPLL1 enabled\n");
- WARN(plls->wrpll2_refcount, "WRPLL2 enabled\n");
+ WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
+ WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
+ WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
"CPU PWM1 enabled\n");
- WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
- "CPU PWM2 enabled\n");
+ if (IS_HASWELL(dev))
+ WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
+ "CPU PWM2 enabled\n");
WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
"PCH PWM1 enabled\n");
WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
@@ -7265,7 +7374,17 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
* gen-specific and since we only disable LCPLL after we fully disable
* the interrupts, the check below should be enough.
*/
- WARN(!dev_priv->pm.irqs_disabled, "IRQs enabled\n");
+ WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
+}
+
+static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
+{
+ struct drm_device *dev = dev_priv->dev;
+
+ if (IS_HASWELL(dev))
+ return I915_READ(D_COMP_HSW);
+ else
+ return I915_READ(D_COMP_BDW);
}
static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
@@ -7276,12 +7395,12 @@ static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
mutex_lock(&dev_priv->rps.hw_lock);
if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
val))
- DRM_ERROR("Failed to disable D_COMP\n");
+ DRM_ERROR("Failed to write to D_COMP\n");
mutex_unlock(&dev_priv->rps.hw_lock);
} else {
- I915_WRITE(D_COMP, val);
+ I915_WRITE(D_COMP_BDW, val);
+ POSTING_READ(D_COMP_BDW);
}
- POSTING_READ(D_COMP);
}
/*
@@ -7319,12 +7438,13 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
if (wait_for((I915_READ(LCPLL_CTL) & LCPLL_PLL_LOCK) == 0, 1))
DRM_ERROR("LCPLL still locked\n");
- val = I915_READ(D_COMP);
+ val = hsw_read_dcomp(dev_priv);
val |= D_COMP_COMP_DISABLE;
hsw_write_dcomp(dev_priv, val);
ndelay(100);
- if (wait_for((I915_READ(D_COMP) & D_COMP_RCOMP_IN_PROGRESS) == 0, 1))
+ if (wait_for((hsw_read_dcomp(dev_priv) & D_COMP_RCOMP_IN_PROGRESS) == 0,
+ 1))
DRM_ERROR("D_COMP RCOMP still in progress\n");
if (allow_power_down) {
@@ -7373,7 +7493,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
POSTING_READ(LCPLL_CTL);
}
- val = I915_READ(D_COMP);
+ val = hsw_read_dcomp(dev_priv);
val |= D_COMP_COMP_FORCE;
val &= ~D_COMP_COMP_DISABLE;
hsw_write_dcomp(dev_priv, val);
@@ -7479,13 +7599,59 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
if (!intel_ddi_pll_select(intel_crtc))
return -EINVAL;
- intel_ddi_pll_enable(intel_crtc);
intel_crtc->lowfreq_avail = false;
return 0;
}
+static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_shared_dpll *pll;
+ enum port port;
+ uint32_t tmp;
+
+ tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
+
+ port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
+
+ pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
+
+ switch (pipe_config->ddi_pll_sel) {
+ case PORT_CLK_SEL_WRPLL1:
+ pipe_config->shared_dpll = DPLL_ID_WRPLL1;
+ break;
+ case PORT_CLK_SEL_WRPLL2:
+ pipe_config->shared_dpll = DPLL_ID_WRPLL2;
+ break;
+ }
+
+ if (pipe_config->shared_dpll >= 0) {
+ pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
+
+ WARN_ON(!pll->get_hw_state(dev_priv, pll,
+ &pipe_config->dpll_hw_state));
+ }
+
+ /*
+ * Haswell has only FDI/PCH transcoder A. It is which is connected to
+ * DDI E. So just check whether this pipe is wired to DDI E and whether
+ * the PCH transcoder is on.
+ */
+ if ((port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
+ pipe_config->has_pch_encoder = true;
+
+ tmp = I915_READ(FDI_RX_CTL(PIPE_A));
+ pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
+ FDI_DP_PORT_WIDTH_SHIFT) + 1;
+
+ ironlake_get_fdi_m_n_config(crtc, pipe_config);
+ }
+}
+
static bool haswell_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
@@ -7531,22 +7697,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
- /*
- * Haswell has only FDI/PCH transcoder A. It is which is connected to
- * DDI E. So just check whether this pipe is wired to DDI E and whether
- * the PCH transcoder is on.
- */
- tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
- if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
- I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
- pipe_config->has_pch_encoder = true;
-
- tmp = I915_READ(FDI_RX_CTL(PIPE_A));
- pipe_config->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
- FDI_DP_PORT_WIDTH_SHIFT) + 1;
-
- ironlake_get_fdi_m_n_config(crtc, pipe_config);
- }
+ haswell_get_ddi_port_state(crtc, pipe_config);
intel_get_pipe_timings(crtc, pipe_config);
@@ -7991,8 +8142,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- int x = intel_crtc->cursor_x;
- int y = intel_crtc->cursor_y;
+ int x = crtc->cursor_x;
+ int y = crtc->cursor_y;
u32 base = 0, pos = 0;
if (on)
@@ -8036,21 +8187,27 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
intel_crtc->cursor_base = base;
}
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file,
- uint32_t handle,
- uint32_t width, uint32_t height)
+/*
+ * intel_crtc_cursor_set_obj - Set cursor to specified GEM object
+ *
+ * Note that the object's reference will be consumed if the update fails. If
+ * the update succeeds, the reference of the old object (if any) will be
+ * consumed.
+ */
+static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
+ struct drm_i915_gem_object *obj,
+ uint32_t width, uint32_t height)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_i915_gem_object *obj;
+ enum pipe pipe = intel_crtc->pipe;
unsigned old_width;
uint32_t addr;
int ret;
/* if we want to turn off the cursor ignore width and height */
- if (!handle) {
+ if (!obj) {
DRM_DEBUG_KMS("cursor off\n");
addr = 0;
obj = NULL;
@@ -8066,12 +8223,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
return -EINVAL;
}
- obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
- if (&obj->base == NULL)
- return -ENOENT;
-
if (obj->base.size < width * height * 4) {
- DRM_DEBUG_KMS("buffer is to small\n");
+ DRM_DEBUG_KMS("buffer is too small\n");
ret = -ENOMEM;
goto fail;
}
@@ -8126,9 +8279,10 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (intel_crtc->cursor_bo) {
if (!INTEL_INFO(dev)->cursor_needs_physical)
i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo);
- drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
}
+ i915_gem_track_fb(intel_crtc->cursor_bo, obj,
+ INTEL_FRONTBUFFER_CURSOR(pipe));
mutex_unlock(&dev->struct_mutex);
old_width = intel_crtc->cursor_width;
@@ -8144,6 +8298,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
}
+ intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe));
+
return 0;
fail_unpin:
i915_gem_object_unpin_from_display_plane(obj);
@@ -8154,19 +8310,6 @@ fail:
return ret;
}
-static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
- intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX);
- intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX);
-
- if (intel_crtc->active)
- intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
-
- return 0;
-}
-
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t start, uint32_t size)
{
@@ -8242,7 +8385,7 @@ static u32
intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
{
u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
- return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
+ return PAGE_ALIGN(pitch * mode->vdisplay);
}
static struct drm_framebuffer *
@@ -8667,16 +8810,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
-static void intel_increase_pllclock(struct drm_crtc *crtc)
+static void intel_increase_pllclock(struct drm_device *dev,
+ enum pipe pipe)
{
- struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
int dpll_reg = DPLL(pipe);
int dpll;
- if (HAS_PCH_SPLIT(dev))
+ if (!HAS_GMCH_DISPLAY(dev))
return;
if (!dev_priv->lvds_downclock_avail)
@@ -8704,7 +8845,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- if (HAS_PCH_SPLIT(dev))
+ if (!HAS_GMCH_DISPLAY(dev))
return;
if (!dev_priv->lvds_downclock_avail)
@@ -8773,28 +8914,179 @@ out:
intel_runtime_pm_put(dev_priv);
}
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring)
+
+/**
+ * intel_mark_fb_busy - mark given planes as busy
+ * @dev: DRM device
+ * @frontbuffer_bits: bits for the affected planes
+ * @ring: optional ring for asynchronous commands
+ *
+ * This function gets called every time the screen contents change. It can be
+ * used to keep e.g. the update rate at the nominal refresh rate with DRRS.
+ */
+static void intel_mark_fb_busy(struct drm_device *dev,
+ unsigned frontbuffer_bits,
+ struct intel_engine_cs *ring)
{
- struct drm_device *dev = obj->base.dev;
- struct drm_crtc *crtc;
+ enum pipe pipe;
if (!i915.powersave)
return;
- for_each_crtc(dev, crtc) {
- if (!crtc->primary->fb)
- continue;
-
- if (to_intel_framebuffer(crtc->primary->fb)->obj != obj)
+ for_each_pipe(pipe) {
+ if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)))
continue;
- intel_increase_pllclock(crtc);
+ intel_increase_pllclock(dev, pipe);
if (ring && intel_fbc_enabled(dev))
ring->fbc_dirty = true;
}
}
+/**
+ * intel_fb_obj_invalidate - invalidate frontbuffer object
+ * @obj: GEM object to invalidate
+ * @ring: set for asynchronous rendering
+ *
+ * This function gets called every time rendering on the given object starts and
+ * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must
+ * be invalidated. If @ring is non-NULL any subsequent invalidation will be delayed
+ * until the rendering completes or a flip on this frontbuffer plane is
+ * scheduled.
+ */
+void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+ struct intel_engine_cs *ring)
+{
+ struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ if (!obj->frontbuffer_bits)
+ return;
+
+ if (ring) {
+ mutex_lock(&dev_priv->fb_tracking.lock);
+ dev_priv->fb_tracking.busy_bits
+ |= obj->frontbuffer_bits;
+ dev_priv->fb_tracking.flip_bits
+ &= ~obj->frontbuffer_bits;
+ mutex_unlock(&dev_priv->fb_tracking.lock);
+ }
+
+ intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
+
+ intel_edp_psr_invalidate(dev, obj->frontbuffer_bits);
+}
+
+/**
+ * intel_frontbuffer_flush - flush frontbuffer
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called every time rendering on the given planes has
+ * completed and frontbuffer caching can be started again. Flushes will get
+ * delayed if they're blocked by some oustanding asynchronous rendering.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flush(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Delay flushing when rings are still busy.*/
+ mutex_lock(&dev_priv->fb_tracking.lock);
+ frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits;
+ mutex_unlock(&dev_priv->fb_tracking.lock);
+
+ intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
+
+ intel_edp_psr_flush(dev, frontbuffer_bits);
+}
+
+/**
+ * intel_fb_obj_flush - flush frontbuffer object
+ * @obj: GEM object to flush
+ * @retire: set when retiring asynchronous rendering
+ *
+ * This function gets called every time rendering on the given object has
+ * completed and frontbuffer caching can be started again. If @retire is true
+ * then any delayed flushes will be unblocked.
+ */
+void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
+ bool retire)
+{
+ struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned frontbuffer_bits;
+
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ if (!obj->frontbuffer_bits)
+ return;
+
+ frontbuffer_bits = obj->frontbuffer_bits;
+
+ if (retire) {
+ mutex_lock(&dev_priv->fb_tracking.lock);
+ /* Filter out new bits since rendering started. */
+ frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
+
+ dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
+ mutex_unlock(&dev_priv->fb_tracking.lock);
+ }
+
+ intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
+/**
+ * intel_frontbuffer_flip_prepare - prepare asnychronous frontbuffer flip
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after scheduling a flip on @obj. The actual
+ * frontbuffer flushing will be delayed until completion is signalled with
+ * intel_frontbuffer_flip_complete. If an invalidate happens in between this
+ * flush will be cancelled.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flip_prepare(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ mutex_lock(&dev_priv->fb_tracking.lock);
+ dev_priv->fb_tracking.flip_bits
+ |= frontbuffer_bits;
+ mutex_unlock(&dev_priv->fb_tracking.lock);
+}
+
+/**
+ * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flush
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after the flip has been latched and will complete
+ * on the next vblank. It will execute the fush if it hasn't been cancalled yet.
+ *
+ * Can be called without any locks held.
+ */
+void intel_frontbuffer_flip_complete(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ mutex_lock(&dev_priv->fb_tracking.lock);
+ /* Mask any cancelled flips. */
+ frontbuffer_bits &= dev_priv->fb_tracking.flip_bits;
+ dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
+ mutex_unlock(&dev_priv->fb_tracking.lock);
+
+ intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
static void intel_crtc_destroy(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -8812,8 +9104,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
kfree(work);
}
- intel_crtc_cursor_set(crtc, NULL, 0, 0, 0);
-
drm_crtc_cleanup(crtc);
kfree(intel_crtc);
@@ -8824,6 +9114,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
struct intel_unpin_work *work =
container_of(__work, struct intel_unpin_work, work);
struct drm_device *dev = work->crtc->dev;
+ enum pipe pipe = to_intel_crtc(work->crtc)->pipe;
mutex_lock(&dev->struct_mutex);
intel_unpin_fb_obj(work->old_fb_obj);
@@ -8833,6 +9124,8 @@ static void intel_unpin_work_fn(struct work_struct *__work)
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
+ intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
+
BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
@@ -9202,6 +9495,150 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
return 0;
}
+static bool use_mmio_flip(struct intel_engine_cs *ring,
+ struct drm_i915_gem_object *obj)
+{
+ /*
+ * This is not being used for older platforms, because
+ * non-availability of flip done interrupt forces us to use
+ * CS flips. Older platforms derive flip done using some clever
+ * tricks involving the flip_pending status bits and vblank irqs.
+ * So using MMIO flips there would disrupt this mechanism.
+ */
+
+ if (ring == NULL)
+ return true;
+
+ if (INTEL_INFO(ring->dev)->gen < 5)
+ return false;
+
+ if (i915.use_mmio_flip < 0)
+ return false;
+ else if (i915.use_mmio_flip > 0)
+ return true;
+ else
+ return ring != obj->ring;
+}
+
+static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
+{
+ struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_framebuffer *intel_fb =
+ to_intel_framebuffer(intel_crtc->base.primary->fb);
+ struct drm_i915_gem_object *obj = intel_fb->obj;
+ u32 dspcntr;
+ u32 reg;
+
+ intel_mark_page_flip_active(intel_crtc);
+
+ reg = DSPCNTR(intel_crtc->plane);
+ dspcntr = I915_READ(reg);
+
+ if (INTEL_INFO(dev)->gen >= 4) {
+ if (obj->tiling_mode != I915_TILING_NONE)
+ dspcntr |= DISPPLANE_TILED;
+ else
+ dspcntr &= ~DISPPLANE_TILED;
+ }
+ I915_WRITE(reg, dspcntr);
+
+ I915_WRITE(DSPSURF(intel_crtc->plane),
+ intel_crtc->unpin_work->gtt_offset);
+ POSTING_READ(DSPSURF(intel_crtc->plane));
+}
+
+static int intel_postpone_flip(struct drm_i915_gem_object *obj)
+{
+ struct intel_engine_cs *ring;
+ int ret;
+
+ lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+ if (!obj->last_write_seqno)
+ return 0;
+
+ ring = obj->ring;
+
+ if (i915_seqno_passed(ring->get_seqno(ring, true),
+ obj->last_write_seqno))
+ return 0;
+
+ ret = i915_gem_check_olr(ring, obj->last_write_seqno);
+ if (ret)
+ return ret;
+
+ if (WARN_ON(!ring->irq_get(ring)))
+ return 0;
+
+ return 1;
+}
+
+void intel_notify_mmio_flip(struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = to_i915(ring->dev);
+ struct intel_crtc *intel_crtc;
+ unsigned long irq_flags;
+ u32 seqno;
+
+ seqno = ring->get_seqno(ring, false);
+
+ spin_lock_irqsave(&dev_priv->mmio_flip_lock, irq_flags);
+ for_each_intel_crtc(ring->dev, intel_crtc) {
+ struct intel_mmio_flip *mmio_flip;
+
+ mmio_flip = &intel_crtc->mmio_flip;
+ if (mmio_flip->seqno == 0)
+ continue;
+
+ if (ring->id != mmio_flip->ring_id)
+ continue;
+
+ if (i915_seqno_passed(seqno, mmio_flip->seqno)) {
+ intel_do_mmio_flip(intel_crtc);
+ mmio_flip->seqno = 0;
+ ring->irq_put(ring);
+ }
+ }
+ spin_unlock_irqrestore(&dev_priv->mmio_flip_lock, irq_flags);
+}
+
+static int intel_queue_mmio_flip(struct drm_device *dev,
+ struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_i915_gem_object *obj,
+ struct intel_engine_cs *ring,
+ uint32_t flags)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ unsigned long irq_flags;
+ int ret;
+
+ if (WARN_ON(intel_crtc->mmio_flip.seqno))
+ return -EBUSY;
+
+ ret = intel_postpone_flip(obj);
+ if (ret < 0)
+ return ret;
+ if (ret == 0) {
+ intel_do_mmio_flip(intel_crtc);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dev_priv->mmio_flip_lock, irq_flags);
+ intel_crtc->mmio_flip.seqno = obj->last_write_seqno;
+ intel_crtc->mmio_flip.ring_id = obj->ring->id;
+ spin_unlock_irqrestore(&dev_priv->mmio_flip_lock, irq_flags);
+
+ /*
+ * Double check to catch cases where irq fired before
+ * mmio flip data was ready
+ */
+ intel_notify_mmio_flip(obj->ring);
+ return 0;
+}
+
static int intel_default_queue_flip(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
@@ -9220,13 +9657,22 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *old_fb = crtc->primary->fb;
- struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum pipe pipe = intel_crtc->pipe;
struct intel_unpin_work *work;
struct intel_engine_cs *ring;
unsigned long flags;
int ret;
+ /*
+ * drm_mode_page_flip_ioctl() should already catch this, but double
+ * check to be safe. In the future we may enable pageflipping from
+ * a disabled primary plane.
+ */
+ if (WARN_ON(intel_fb_obj(old_fb) == NULL))
+ return -EBUSY;
+
/* Can't change pixel format via MI display flips. */
if (fb->pixel_format != crtc->primary->fb->pixel_format)
return -EINVAL;
@@ -9249,7 +9695,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->event = event;
work->crtc = crtc;
- work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
+ work->old_fb_obj = intel_fb_obj(old_fb);
INIT_WORK(&work->work, intel_unpin_work_fn);
ret = drm_crtc_vblank_get(crtc);
@@ -9290,10 +9736,15 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
- work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(intel_crtc->pipe)) + 1;
+ work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(pipe)) + 1;
if (IS_VALLEYVIEW(dev)) {
ring = &dev_priv->ring[BCS];
+ if (obj->tiling_mode != work->old_fb_obj->tiling_mode)
+ /* vlv: DISPLAY_FLIP fails to change tiling */
+ ring = NULL;
+ } else if (IS_IVYBRIDGE(dev)) {
+ ring = &dev_priv->ring[BCS];
} else if (INTEL_INFO(dev)->gen >= 7) {
ring = obj->ring;
if (ring == NULL || ring->id != RCS)
@@ -9309,12 +9760,20 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->gtt_offset =
i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
- ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, page_flip_flags);
+ if (use_mmio_flip(ring, obj))
+ ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
+ page_flip_flags);
+ else
+ ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
+ page_flip_flags);
if (ret)
goto cleanup_unpin;
+ i915_gem_track_fb(work->old_fb_obj, obj,
+ INTEL_FRONTBUFFER_PRIMARY(pipe));
+
intel_disable_fbc(dev);
- intel_mark_fb_busy(obj, NULL);
+ intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
mutex_unlock(&dev->struct_mutex);
trace_i915_flip_request(intel_crtc->plane, obj);
@@ -9344,7 +9803,7 @@ out_hang:
intel_crtc_wait_for_pending_flips(crtc);
ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb);
if (ret == 0 && event)
- drm_send_vblank_event(dev, intel_crtc->pipe, event);
+ drm_send_vblank_event(dev, pipe, event);
}
return ret;
}
@@ -10017,11 +10476,14 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(double_wide);
+ PIPE_CONF_CHECK_X(ddi_pll_sel);
+
PIPE_CONF_CHECK_I(shared_dpll);
PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
+ PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
PIPE_CONF_CHECK_I(pipe_bpp);
@@ -10083,6 +10545,14 @@ check_encoder_state(struct drm_device *dev)
if (connector->base.dpms != DRM_MODE_DPMS_OFF)
active = true;
}
+ /*
+ * for MST connectors if we unplug the connector is gone
+ * away but the encoder is still connected to a crtc
+ * until a modeset happens in response to the hotplug.
+ */
+ if (!enabled && encoder->base.encoder_type == DRM_MODE_ENCODER_DPMST)
+ continue;
+
WARN(!!encoder->base.crtc != enabled,
"encoder's enabled state mismatch "
"(expected %i, found %i)\n",
@@ -10378,20 +10848,23 @@ static int __intel_set_mode(struct drm_crtc *crtc,
* on the DPLL.
*/
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
- struct drm_framebuffer *old_fb;
+ struct drm_framebuffer *old_fb = crtc->primary->fb;
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb);
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev,
- to_intel_framebuffer(fb)->obj,
+ obj,
NULL);
if (ret != 0) {
DRM_ERROR("pin & fence failed\n");
mutex_unlock(&dev->struct_mutex);
goto done;
}
- old_fb = crtc->primary->fb;
if (old_fb)
- intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
+ intel_unpin_fb_obj(old_obj);
+ i915_gem_track_fb(old_obj, obj,
+ INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
mutex_unlock(&dev->struct_mutex);
crtc->primary->fb = fb;
@@ -10563,12 +11036,17 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
if (is_crtc_connector_off(set)) {
config->mode_changed = true;
} else if (set->crtc->primary->fb != set->fb) {
- /* If we have no fb then treat it as a full mode set */
+ /*
+ * If we have no fb, we can only flip as long as the crtc is
+ * active, otherwise we need a full mode set. The crtc may
+ * be active if we've only disabled the primary plane, or
+ * in fastboot situations.
+ */
if (set->crtc->primary->fb == NULL) {
struct intel_crtc *intel_crtc =
to_intel_crtc(set->crtc);
- if (intel_crtc->active && i915.fastboot) {
+ if (intel_crtc->active) {
DRM_DEBUG_KMS("crtc has no fb, will flip\n");
config->fb_changed = true;
} else {
@@ -10620,7 +11098,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
* for them. */
for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == &connector->base) {
- connector->new_encoder = connector->encoder;
+ connector->new_encoder = intel_find_encoder(connector, to_intel_crtc(set->crtc)->pipe);
break;
}
}
@@ -10666,7 +11144,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
new_crtc)) {
return -EINVAL;
}
- connector->encoder->new_crtc = to_intel_crtc(new_crtc);
+ connector->new_encoder->new_crtc = to_intel_crtc(new_crtc);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
connector->base.base.id,
@@ -10700,7 +11178,12 @@ intel_modeset_stage_output_state(struct drm_device *dev,
}
}
/* Now we've also updated encoder->new_crtc for all encoders. */
-
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ base.head) {
+ if (connector->new_encoder)
+ if (connector->new_encoder != connector->encoder)
+ connector->encoder = connector->new_encoder;
+ }
for_each_intel_crtc(dev, crtc) {
crtc->new_enabled = false;
@@ -10806,10 +11289,24 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
ret = intel_set_mode(set->crtc, set->mode,
set->x, set->y, set->fb);
} else if (config->fb_changed) {
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
+
intel_crtc_wait_for_pending_flips(set->crtc);
ret = intel_pipe_set_base(set->crtc,
set->x, set->y, set->fb);
+
+ /*
+ * We need to make sure the primary plane is re-enabled if it
+ * has previously been turned off.
+ */
+ if (!intel_crtc->primary_enabled && ret == 0) {
+ WARN_ON(!intel_crtc->active);
+ intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
+ intel_crtc->pipe);
+ }
+
/*
* In the fastboot case this may be our only check of the
* state after boot. It would be better to only do it on
@@ -10850,26 +11347,21 @@ out_config:
}
static const struct drm_crtc_funcs intel_crtc_funcs = {
- .cursor_set = intel_crtc_cursor_set,
- .cursor_move = intel_crtc_cursor_move,
.gamma_set = intel_crtc_gamma_set,
.set_config = intel_crtc_set_config,
.destroy = intel_crtc_destroy,
.page_flip = intel_crtc_page_flip,
};
-static void intel_cpu_pll_init(struct drm_device *dev)
-{
- if (HAS_DDI(dev))
- intel_ddi_pll_init(dev);
-}
-
static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
uint32_t val;
+ if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+ return false;
+
val = I915_READ(PCH_DPLL(pll->id));
hw_state->dpll = val;
hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
@@ -10951,7 +11443,9 @@ static void intel_shared_dpll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+ if (HAS_DDI(dev))
+ intel_ddi_pll_init(dev);
+ else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
ibx_pch_dpll_init(dev);
else
dev_priv->num_shared_dpll = 0;
@@ -10959,17 +11453,328 @@ static void intel_shared_dpll_init(struct drm_device *dev)
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
}
+static int
+intel_primary_plane_disable(struct drm_plane *plane)
+{
+ struct drm_device *dev = plane->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct intel_crtc *intel_crtc;
+
+ if (!plane->fb)
+ return 0;
+
+ BUG_ON(!plane->crtc);
+
+ intel_crtc = to_intel_crtc(plane->crtc);
+
+ /*
+ * Even though we checked plane->fb above, it's still possible that
+ * the primary plane has been implicitly disabled because the crtc
+ * coordinates given weren't visible, or because we detected
+ * that it was 100% covered by a sprite plane. Or, the CRTC may be
+ * off and we've set a fb, but haven't actually turned on the CRTC yet.
+ * In either case, we need to unpin the FB and let the fb pointer get
+ * updated, but otherwise we don't need to touch the hardware.
+ */
+ if (!intel_crtc->primary_enabled)
+ goto disable_unpin;
+
+ intel_crtc_wait_for_pending_flips(plane->crtc);
+ intel_disable_primary_hw_plane(dev_priv, intel_plane->plane,
+ intel_plane->pipe);
+disable_unpin:
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
+ INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+ intel_unpin_fb_obj(intel_fb_obj(plane->fb));
+ mutex_unlock(&dev->struct_mutex);
+ plane->fb = NULL;
+
+ return 0;
+}
+
+static int
+intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
+ struct drm_rect dest = {
+ /* integer pixels */
+ .x1 = crtc_x,
+ .y1 = crtc_y,
+ .x2 = crtc_x + crtc_w,
+ .y2 = crtc_y + crtc_h,
+ };
+ struct drm_rect src = {
+ /* 16.16 fixed point */
+ .x1 = src_x,
+ .y1 = src_y,
+ .x2 = src_x + src_w,
+ .y2 = src_y + src_h,
+ };
+ const struct drm_rect clip = {
+ /* integer pixels */
+ .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
+ .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
+ };
+ bool visible;
+ int ret;
+
+ ret = drm_plane_helper_check_update(plane, crtc, fb,
+ &src, &dest, &clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ false, true, &visible);
+
+ if (ret)
+ return ret;
+
+ /*
+ * If the CRTC isn't enabled, we're just pinning the framebuffer,
+ * updating the fb pointer, and returning without touching the
+ * hardware. This allows us to later do a drmModeSetCrtc with fb=-1 to
+ * turn on the display with all planes setup as desired.
+ */
+ if (!crtc->enabled) {
+ mutex_lock(&dev->struct_mutex);
+
+ /*
+ * If we already called setplane while the crtc was disabled,
+ * we may have an fb pinned; unpin it.
+ */
+ if (plane->fb)
+ intel_unpin_fb_obj(old_obj);
+
+ i915_gem_track_fb(old_obj, obj,
+ INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+
+ /* Pin and return without programming hardware */
+ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+ mutex_unlock(&dev->struct_mutex);
+
+ return ret;
+ }
+
+ intel_crtc_wait_for_pending_flips(crtc);
+
+ /*
+ * If clipping results in a non-visible primary plane, we'll disable
+ * the primary plane. Note that this is a bit different than what
+ * happens if userspace explicitly disables the plane by passing fb=0
+ * because plane->fb still gets set and pinned.
+ */
+ if (!visible) {
+ mutex_lock(&dev->struct_mutex);
+
+ /*
+ * Try to pin the new fb first so that we can bail out if we
+ * fail.
+ */
+ if (plane->fb != fb) {
+ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
+ }
+
+ i915_gem_track_fb(old_obj, obj,
+ INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
+
+ if (intel_crtc->primary_enabled)
+ intel_disable_primary_hw_plane(dev_priv,
+ intel_plane->plane,
+ intel_plane->pipe);
+
+
+ if (plane->fb != fb)
+ if (plane->fb)
+ intel_unpin_fb_obj(old_obj);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+ }
+
+ ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb);
+ if (ret)
+ return ret;
+
+ if (!intel_crtc->primary_enabled)
+ intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
+ intel_crtc->pipe);
+
+ return 0;
+}
+
+/* Common destruction function for both primary and cursor planes */
+static void intel_plane_destroy(struct drm_plane *plane)
+{
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ drm_plane_cleanup(plane);
+ kfree(intel_plane);
+}
+
+static const struct drm_plane_funcs intel_primary_plane_funcs = {
+ .update_plane = intel_primary_plane_setplane,
+ .disable_plane = intel_primary_plane_disable,
+ .destroy = intel_plane_destroy,
+};
+
+static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
+ int pipe)
+{
+ struct intel_plane *primary;
+ const uint32_t *intel_primary_formats;
+ int num_formats;
+
+ primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+ if (primary == NULL)
+ return NULL;
+
+ primary->can_scale = false;
+ primary->max_downscale = 1;
+ primary->pipe = pipe;
+ primary->plane = pipe;
+ if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
+ primary->plane = !pipe;
+
+ if (INTEL_INFO(dev)->gen <= 3) {
+ intel_primary_formats = intel_primary_formats_gen2;
+ num_formats = ARRAY_SIZE(intel_primary_formats_gen2);
+ } else {
+ intel_primary_formats = intel_primary_formats_gen4;
+ num_formats = ARRAY_SIZE(intel_primary_formats_gen4);
+ }
+
+ drm_universal_plane_init(dev, &primary->base, 0,
+ &intel_primary_plane_funcs,
+ intel_primary_formats, num_formats,
+ DRM_PLANE_TYPE_PRIMARY);
+ return &primary->base;
+}
+
+static int
+intel_cursor_plane_disable(struct drm_plane *plane)
+{
+ if (!plane->fb)
+ return 0;
+
+ BUG_ON(!plane->crtc);
+
+ return intel_crtc_cursor_set_obj(plane->crtc, NULL, 0, 0);
+}
+
+static int
+intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+ struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_rect dest = {
+ /* integer pixels */
+ .x1 = crtc_x,
+ .y1 = crtc_y,
+ .x2 = crtc_x + crtc_w,
+ .y2 = crtc_y + crtc_h,
+ };
+ struct drm_rect src = {
+ /* 16.16 fixed point */
+ .x1 = src_x,
+ .y1 = src_y,
+ .x2 = src_x + src_w,
+ .y2 = src_y + src_h,
+ };
+ const struct drm_rect clip = {
+ /* integer pixels */
+ .x2 = intel_crtc->config.pipe_src_w,
+ .y2 = intel_crtc->config.pipe_src_h,
+ };
+ bool visible;
+ int ret;
+
+ ret = drm_plane_helper_check_update(plane, crtc, fb,
+ &src, &dest, &clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true, &visible);
+ if (ret)
+ return ret;
+
+ crtc->cursor_x = crtc_x;
+ crtc->cursor_y = crtc_y;
+ if (fb != crtc->cursor->fb) {
+ return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h);
+ } else {
+ intel_crtc_update_cursor(crtc, visible);
+ return 0;
+ }
+}
+static const struct drm_plane_funcs intel_cursor_plane_funcs = {
+ .update_plane = intel_cursor_plane_update,
+ .disable_plane = intel_cursor_plane_disable,
+ .destroy = intel_plane_destroy,
+};
+
+static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
+ int pipe)
+{
+ struct intel_plane *cursor;
+
+ cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
+ if (cursor == NULL)
+ return NULL;
+
+ cursor->can_scale = false;
+ cursor->max_downscale = 1;
+ cursor->pipe = pipe;
+ cursor->plane = pipe;
+
+ drm_universal_plane_init(dev, &cursor->base, 0,
+ &intel_cursor_plane_funcs,
+ intel_cursor_formats,
+ ARRAY_SIZE(intel_cursor_formats),
+ DRM_PLANE_TYPE_CURSOR);
+ return &cursor->base;
+}
+
static void intel_crtc_init(struct drm_device *dev, int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc;
- int i;
+ struct drm_plane *primary = NULL;
+ struct drm_plane *cursor = NULL;
+ int i, ret;
intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
if (intel_crtc == NULL)
return;
- drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
+ primary = intel_primary_plane_create(dev, pipe);
+ if (!primary)
+ goto fail;
+
+ cursor = intel_cursor_plane_create(dev, pipe);
+ if (!cursor)
+ goto fail;
+
+ ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
+ cursor, &intel_crtc_funcs);
+ if (ret)
+ goto fail;
drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
for (i = 0; i < 256; i++) {
@@ -10980,7 +11785,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
/*
* On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
- * is hooked to plane B. Hence we want plane A feeding pipe B.
+ * is hooked to pipe B. Hence we want plane A feeding pipe B.
*/
intel_crtc->pipe = pipe;
intel_crtc->plane = pipe;
@@ -11002,6 +11807,14 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
+ return;
+
+fail:
+ if (primary)
+ drm_plane_cleanup(primary);
+ if (cursor)
+ drm_plane_cleanup(cursor);
+ kfree(intel_crtc);
}
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
@@ -11021,21 +11834,20 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
- struct drm_mode_object *drmmode_obj;
+ struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
- drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
- DRM_MODE_OBJECT_CRTC);
+ drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id);
- if (!drmmode_obj) {
+ if (!drmmode_crtc) {
DRM_ERROR("no such CRTC id\n");
return -ENOENT;
}
- crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+ crtc = to_intel_crtc(drmmode_crtc);
pipe_from_crtc_id->pipe = crtc->pipe;
return 0;
@@ -11236,6 +12048,8 @@ static void intel_setup_outputs(struct drm_device *dev)
if (SUPPORTS_TV(dev))
intel_tv_init(dev);
+ intel_edp_psr_init(dev);
+
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
encoder->base.possible_crtcs = encoder->crtc_mask;
encoder->base.possible_clones =
@@ -11249,11 +12063,14 @@ static void intel_setup_outputs(struct drm_device *dev)
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
+ struct drm_device *dev = fb->dev;
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
drm_framebuffer_cleanup(fb);
+ mutex_lock(&dev->struct_mutex);
WARN_ON(!intel_fb->obj->framebuffer_references--);
- drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
+ drm_gem_object_unreference(&intel_fb->obj->base);
+ mutex_unlock(&dev->struct_mutex);
kfree(intel_fb);
}
@@ -11438,7 +12255,7 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
dev_priv->display.crtc_enable = haswell_crtc_enable;
dev_priv->display.crtc_disable = haswell_crtc_disable;
- dev_priv->display.off = haswell_crtc_off;
+ dev_priv->display.off = ironlake_crtc_off;
dev_priv->display.update_primary_plane =
ironlake_update_primary_plane;
} else if (HAS_PCH_SPLIT(dev)) {
@@ -11722,6 +12539,9 @@ void intel_modeset_init_hw(struct drm_device *dev)
{
intel_prepare_ddi(dev);
+ if (IS_VALLEYVIEW(dev))
+ vlv_update_cdclk(dev);
+
intel_init_clock_gating(dev);
intel_reset_dpio(dev);
@@ -11798,7 +12618,6 @@ void intel_modeset_init(struct drm_device *dev)
intel_init_dpio(dev);
intel_reset_dpio(dev);
- intel_cpu_pll_init(dev);
intel_shared_dpll_init(dev);
/* Just disable it once at startup */
@@ -12024,6 +12843,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
encoder->base.base.id,
encoder->base.name);
encoder->disable(encoder);
+ if (encoder->post_disable)
+ encoder->post_disable(encoder);
}
encoder->base.crtc = NULL;
encoder->connectors_active = false;
@@ -12108,10 +12929,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->active ? "enabled" : "disabled");
}
- /* FIXME: Smash this into the new shared dpll infrastructure. */
- if (HAS_DDI(dev))
- intel_ddi_setup_hw_pll_state(dev);
-
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
@@ -12125,6 +12942,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
pll->name, pll->refcount, pll->on);
+
+ if (pll->refcount)
+ intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
@@ -12242,7 +13062,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
void intel_modeset_gem_init(struct drm_device *dev)
{
struct drm_crtc *c;
- struct intel_framebuffer *fb;
+ struct drm_i915_gem_object *obj;
mutex_lock(&dev->struct_mutex);
intel_init_gt_powersave(dev);
@@ -12259,11 +13079,11 @@ void intel_modeset_gem_init(struct drm_device *dev)
*/
mutex_lock(&dev->struct_mutex);
for_each_crtc(dev, c) {
- if (!c->primary->fb)
+ obj = intel_fb_obj(c->primary->fb);
+ if (obj == NULL)
continue;
- fb = to_intel_framebuffer(c->primary->fb);
- if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
+ if (intel_pin_and_fence_fb_obj(dev, obj, NULL)) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
to_intel_crtc(c)->pipe);
drm_framebuffer_unreference(c->primary->fb);
@@ -12278,13 +13098,12 @@ void intel_connector_unregister(struct intel_connector *intel_connector)
struct drm_connector *connector = &intel_connector->base;
intel_panel_destroy_backlight(connector);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
}
void intel_modeset_cleanup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
struct drm_connector *connector;
/*
@@ -12294,6 +13113,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
*/
drm_irq_uninstall(dev);
cancel_work_sync(&dev_priv->hotplug_work);
+ dev_priv->pm._irqs_disabled = true;
+
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
* poll handlers. Hence disable polling after hpd handling is shut down.
@@ -12304,14 +13125,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_unregister_dsm_handler();
- for_each_crtc(dev, crtc) {
- /* Skip inactive CRTCs */
- if (!crtc->primary->fb)
- continue;
-
- intel_increase_pllclock(crtc);
- }
-
intel_disable_fbc(dev);
intel_disable_gt_powersave(dev);
@@ -12479,7 +13292,7 @@ intel_display_capture_error_state(struct drm_device *dev)
error->pipe[i].source = I915_READ(PIPESRC(i));
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
error->pipe[i].stat = I915_READ(PIPESTAT(i));
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8a1a4fbc06ac..ee3942f0b068 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -114,7 +114,7 @@ static void intel_dp_link_down(struct intel_dp *intel_dp);
static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-static int
+int
intel_dp_max_link_bw(struct intel_dp *intel_dp)
{
int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
@@ -773,12 +773,29 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector)
{
struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base);
- sysfs_remove_link(&intel_connector->base.kdev->kobj,
- intel_dp->aux.ddc.dev.kobj.name);
+ if (!intel_connector->mst_port)
+ sysfs_remove_link(&intel_connector->base.kdev->kobj,
+ intel_dp->aux.ddc.dev.kobj.name);
intel_connector_unregister(intel_connector);
}
static void
+hsw_dp_set_ddi_pll_sel(struct intel_crtc_config *pipe_config, int link_bw)
+{
+ switch (link_bw) {
+ case DP_LINK_BW_1_62:
+ pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
+ break;
+ case DP_LINK_BW_2_7:
+ pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
+ break;
+ case DP_LINK_BW_5_4:
+ pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
+ break;
+ }
+}
+
+static void
intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config, int link_bw)
{
@@ -789,8 +806,6 @@ intel_dp_set_clock(struct intel_encoder *encoder,
if (IS_G4X(dev)) {
divisor = gen4_dpll;
count = ARRAY_SIZE(gen4_dpll);
- } else if (IS_HASWELL(dev)) {
- /* Haswell has special-purpose DP DDI clocks. */
} else if (HAS_PCH_SPLIT(dev)) {
divisor = pch_dpll;
count = ARRAY_SIZE(pch_dpll);
@@ -961,7 +976,10 @@ found:
&pipe_config->dp_m2_n2);
}
- intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
+ if (HAS_DDI(dev))
+ hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw);
+ else
+ intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
return true;
}
@@ -1267,6 +1285,19 @@ static void edp_panel_vdd_work(struct work_struct *__work)
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
+static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
+{
+ unsigned long delay;
+
+ /*
+ * Queue the timer to fire a long time from now (relative to the power
+ * down delay) to keep the panel power up across a sequence of
+ * operations.
+ */
+ delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
+ schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
+}
+
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
{
if (!is_edp(intel_dp))
@@ -1276,17 +1307,10 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
intel_dp->want_panel_vdd = false;
- if (sync) {
+ if (sync)
edp_panel_vdd_off_sync(intel_dp);
- } else {
- /*
- * Queue the timer to fire a long
- * time from now (relative to the power down delay)
- * to keep the panel power up across a sequence of operations
- */
- schedule_delayed_work(&intel_dp->panel_vdd_work,
- msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
- }
+ else
+ edp_panel_vdd_schedule_off(intel_dp);
}
void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1349,8 +1373,6 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("Turn eDP power off\n");
- edp_wait_backlight_off(intel_dp);
-
WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
pp = ironlake_get_pp_control(intel_dp);
@@ -1386,6 +1408,9 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
return;
DRM_DEBUG_KMS("\n");
+
+ intel_panel_enable_backlight(intel_dp->attached_connector);
+
/*
* If we enable the backlight right away following a panel power
* on, we may see slight flicker as the panel syncs with the eDP
@@ -1400,8 +1425,6 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
-
- intel_panel_enable_backlight(intel_dp->attached_connector);
}
void intel_edp_backlight_off(struct intel_dp *intel_dp)
@@ -1414,8 +1437,6 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
if (!is_edp(intel_dp))
return;
- intel_panel_disable_backlight(intel_dp->attached_connector);
-
DRM_DEBUG_KMS("\n");
pp = ironlake_get_pp_control(intel_dp);
pp &= ~EDP_BLC_ENABLE;
@@ -1425,6 +1446,10 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
intel_dp->last_backlight_off = jiffies;
+
+ edp_wait_backlight_off(intel_dp);
+
+ intel_panel_disable_backlight(intel_dp->attached_connector);
}
static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
@@ -1646,11 +1671,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
}
}
-static bool is_edp_psr(struct drm_device *dev)
+static bool is_edp_psr(struct intel_dp *intel_dp)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- return dev_priv->psr.sink_support;
+ return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED;
}
static bool intel_edp_is_psr_enabled(struct drm_device *dev)
@@ -1698,9 +1721,6 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
struct edp_vsc_psr psr_vsc;
- if (intel_dp->psr_setup_done)
- return;
-
/* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
memset(&psr_vsc, 0, sizeof(psr_vsc));
psr_vsc.sdp_header.HB0 = 0;
@@ -1712,22 +1732,25 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp)
/* Avoid continuous PSR exit by masking memup and hpd */
I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
-
- intel_dp->psr_setup_done = true;
}
static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t aux_clock_divider;
int precharge = 0x3;
int msg_size = 5; /* Header(4) + Message(1) */
+ bool only_standby = false;
aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
+ if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
+ only_standby = true;
+
/* Enable PSR in sink */
- if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
+ if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
else
@@ -1746,18 +1769,24 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t max_sleep_time = 0x1f;
uint32_t idle_frames = 1;
uint32_t val = 0x0;
const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
+ bool only_standby = false;
- if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
+ if (IS_BROADWELL(dev) && dig_port->port != PORT_A)
+ only_standby = true;
+
+ if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT || only_standby) {
val |= EDP_PSR_LINK_STANDBY;
val |= EDP_PSR_TP2_TP3_TIME_0us;
val |= EDP_PSR_TP1_TIME_0us;
val |= EDP_PSR_SKIP_AUX_EXIT;
+ val |= IS_BROADWELL(dev) ? BDW_PSR_SINGLE_FRAME : 0;
} else
val |= EDP_PSR_LINK_DISABLE;
@@ -1775,18 +1804,14 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dig_port->base.base.crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->primary->fb)->obj;
- struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
- dev_priv->psr.source_ok = false;
+ lockdep_assert_held(&dev_priv->psr.lock);
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
- if (!HAS_PSR(dev)) {
- DRM_DEBUG_KMS("PSR not supported on this platform\n");
- return false;
- }
+ dev_priv->psr.source_ok = false;
- if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
- (dig_port->port != PORT_A)) {
+ if (IS_HASWELL(dev) && dig_port->port != PORT_A) {
DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
return false;
}
@@ -1796,29 +1821,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
return false;
}
- crtc = dig_port->base.base.crtc;
- if (crtc == NULL) {
- DRM_DEBUG_KMS("crtc not active for PSR\n");
- return false;
- }
-
- intel_crtc = to_intel_crtc(crtc);
- if (!intel_crtc_active(crtc)) {
- DRM_DEBUG_KMS("crtc not active for PSR\n");
- return false;
- }
-
- obj = to_intel_framebuffer(crtc->primary->fb)->obj;
- if (obj->tiling_mode != I915_TILING_X ||
- obj->fence_reg == I915_FENCE_REG_NONE) {
- DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
- return false;
- }
-
- if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
- DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
- return false;
- }
+ /* Below limitations aren't valid for Broadwell */
+ if (IS_BROADWELL(dev))
+ goto out;
if (I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config.cpu_transcoder)) &
S3D_ENABLE) {
@@ -1831,35 +1836,60 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
return false;
}
+ out:
dev_priv->psr.source_ok = true;
return true;
}
static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
{
- struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
- if (!intel_edp_psr_match_conditions(intel_dp) ||
- intel_edp_is_psr_enabled(dev))
- return;
-
- /* Setup PSR once */
- intel_edp_psr_setup(intel_dp);
+ WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+ WARN_ON(dev_priv->psr.active);
+ lockdep_assert_held(&dev_priv->psr.lock);
/* Enable PSR on the panel */
intel_edp_psr_enable_sink(intel_dp);
/* Enable PSR on the host */
intel_edp_psr_enable_source(intel_dp);
+
+ dev_priv->psr.active = true;
}
void intel_edp_psr_enable(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!HAS_PSR(dev)) {
+ DRM_DEBUG_KMS("PSR not supported on this platform\n");
+ return;
+ }
- if (intel_edp_psr_match_conditions(intel_dp) &&
- !intel_edp_is_psr_enabled(dev))
- intel_edp_psr_do_enable(intel_dp);
+ if (!is_edp_psr(intel_dp)) {
+ DRM_DEBUG_KMS("PSR not supported by this panel\n");
+ return;
+ }
+
+ mutex_lock(&dev_priv->psr.lock);
+ if (dev_priv->psr.enabled) {
+ DRM_DEBUG_KMS("PSR already in use\n");
+ mutex_unlock(&dev_priv->psr.lock);
+ return;
+ }
+
+ dev_priv->psr.busy_frontbuffer_bits = 0;
+
+ /* Setup PSR once */
+ intel_edp_psr_setup(intel_dp);
+
+ if (intel_edp_psr_match_conditions(intel_dp))
+ dev_priv->psr.enabled = intel_dp;
+ mutex_unlock(&dev_priv->psr.lock);
}
void intel_edp_psr_disable(struct intel_dp *intel_dp)
@@ -1867,36 +1897,136 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- if (!intel_edp_is_psr_enabled(dev))
+ mutex_lock(&dev_priv->psr.lock);
+ if (!dev_priv->psr.enabled) {
+ mutex_unlock(&dev_priv->psr.lock);
return;
+ }
+
+ if (dev_priv->psr.active) {
+ I915_WRITE(EDP_PSR_CTL(dev),
+ I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
- I915_WRITE(EDP_PSR_CTL(dev),
- I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
+ /* Wait till PSR is idle */
+ if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
+ EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+ DRM_ERROR("Timed out waiting for PSR Idle State\n");
- /* Wait till PSR is idle */
- if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
- EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
- DRM_ERROR("Timed out waiting for PSR Idle State\n");
+ dev_priv->psr.active = false;
+ } else {
+ WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE);
+ }
+
+ dev_priv->psr.enabled = NULL;
+ mutex_unlock(&dev_priv->psr.lock);
+
+ cancel_delayed_work_sync(&dev_priv->psr.work);
}
-void intel_edp_psr_update(struct drm_device *dev)
+static void intel_edp_psr_work(struct work_struct *work)
{
- struct intel_encoder *encoder;
- struct intel_dp *intel_dp = NULL;
+ struct drm_i915_private *dev_priv =
+ container_of(work, typeof(*dev_priv), psr.work.work);
+ struct intel_dp *intel_dp = dev_priv->psr.enabled;
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
- if (encoder->type == INTEL_OUTPUT_EDP) {
- intel_dp = enc_to_intel_dp(&encoder->base);
+ mutex_lock(&dev_priv->psr.lock);
+ intel_dp = dev_priv->psr.enabled;
- if (!is_edp_psr(dev))
- return;
+ if (!intel_dp)
+ goto unlock;
- if (!intel_edp_psr_match_conditions(intel_dp))
- intel_edp_psr_disable(intel_dp);
- else
- if (!intel_edp_is_psr_enabled(dev))
- intel_edp_psr_do_enable(intel_dp);
- }
+ /*
+ * The delayed work can race with an invalidate hence we need to
+ * recheck. Since psr_flush first clears this and then reschedules we
+ * won't ever miss a flush when bailing out here.
+ */
+ if (dev_priv->psr.busy_frontbuffer_bits)
+ goto unlock;
+
+ intel_edp_psr_do_enable(intel_dp);
+unlock:
+ mutex_unlock(&dev_priv->psr.lock);
+}
+
+static void intel_edp_psr_do_exit(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (dev_priv->psr.active) {
+ u32 val = I915_READ(EDP_PSR_CTL(dev));
+
+ WARN_ON(!(val & EDP_PSR_ENABLE));
+
+ I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE);
+
+ dev_priv->psr.active = false;
+ }
+
+}
+
+void intel_edp_psr_invalidate(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc;
+ enum pipe pipe;
+
+ mutex_lock(&dev_priv->psr.lock);
+ if (!dev_priv->psr.enabled) {
+ mutex_unlock(&dev_priv->psr.lock);
+ return;
+ }
+
+ crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+ pipe = to_intel_crtc(crtc)->pipe;
+
+ intel_edp_psr_do_exit(dev);
+
+ frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
+
+ dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits;
+ mutex_unlock(&dev_priv->psr.lock);
+}
+
+void intel_edp_psr_flush(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc;
+ enum pipe pipe;
+
+ mutex_lock(&dev_priv->psr.lock);
+ if (!dev_priv->psr.enabled) {
+ mutex_unlock(&dev_priv->psr.lock);
+ return;
+ }
+
+ crtc = dp_to_dig_port(dev_priv->psr.enabled)->base.base.crtc;
+ pipe = to_intel_crtc(crtc)->pipe;
+ dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits;
+
+ /*
+ * On Haswell sprite plane updates don't result in a psr invalidating
+ * signal in the hardware. Which means we need to manually fake this in
+ * software for all flushes, not just when we've seen a preceding
+ * invalidation through frontbuffer rendering.
+ */
+ if (IS_HASWELL(dev) &&
+ (frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe)))
+ intel_edp_psr_do_exit(dev);
+
+ if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
+ schedule_delayed_work(&dev_priv->psr.work,
+ msecs_to_jiffies(100));
+ mutex_unlock(&dev_priv->psr.lock);
+}
+
+void intel_edp_psr_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ INIT_DELAYED_WORK(&dev_priv->psr.work, intel_edp_psr_work);
+ mutex_init(&dev_priv->psr.lock);
}
static void intel_disable_dp(struct intel_encoder *encoder)
@@ -2152,6 +2282,70 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
vlv_wait_port_ready(dev_priv, dport);
}
+static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(encoder->base.crtc);
+ enum dpio_channel ch = vlv_dport_to_channel(dport);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 val;
+
+ mutex_lock(&dev_priv->dpio_lock);
+
+ /* program left/right clock distribution */
+ if (pipe != PIPE_B) {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+ val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+ if (ch == DPIO_CH0)
+ val |= CHV_BUFLEFTENA1_FORCE;
+ if (ch == DPIO_CH1)
+ val |= CHV_BUFRIGHTENA1_FORCE;
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+ } else {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+ val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+ if (ch == DPIO_CH0)
+ val |= CHV_BUFLEFTENA2_FORCE;
+ if (ch == DPIO_CH1)
+ val |= CHV_BUFRIGHTENA2_FORCE;
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+ }
+
+ /* program clock channel usage */
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch));
+ val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+ if (pipe != PIPE_B)
+ val &= ~CHV_PCS_USEDCLKCHANNEL;
+ else
+ val |= CHV_PCS_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+ val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+ if (pipe != PIPE_B)
+ val &= ~CHV_PCS_USEDCLKCHANNEL;
+ else
+ val |= CHV_PCS_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+
+ /*
+ * This a a bit weird since generally CL
+ * matches the pipe, but here we need to
+ * pick the CL based on the port.
+ */
+ val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch));
+ if (pipe != PIPE_B)
+ val &= ~CHV_CMN_USEDCLKCHANNEL;
+ else
+ val |= CHV_CMN_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
+
+ mutex_unlock(&dev_priv->dpio_lock);
+}
+
/*
* Native read with retry for link status and receiver capability reads for
* cases where the sink may still be asleep.
@@ -2189,18 +2383,14 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
}
-/*
- * These are source-specific values; current Intel hardware supports
- * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
- */
-
+/* These are source-specific values. */
static uint8_t
intel_dp_voltage_max(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
enum port port = dp_to_dig_port(intel_dp)->port;
- if (IS_VALLEYVIEW(dev) || IS_BROADWELL(dev))
+ if (IS_VALLEYVIEW(dev))
return DP_TRAIN_VOLTAGE_SWING_1200;
else if (IS_GEN7(dev) && port == PORT_A)
return DP_TRAIN_VOLTAGE_SWING_800;
@@ -2216,18 +2406,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
enum port port = dp_to_dig_port(intel_dp)->port;
- if (IS_BROADWELL(dev)) {
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- case DP_TRAIN_VOLTAGE_SWING_600:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
- } else if (IS_HASWELL(dev)) {
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
case DP_TRAIN_VOLTAGE_SWING_400:
return DP_TRAIN_PRE_EMPHASIS_9_5;
@@ -2699,41 +2878,6 @@ intel_hsw_signal_levels(uint8_t train_set)
}
}
-static uint32_t
-intel_bdw_signal_levels(uint8_t train_set)
-{
- int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
- DP_TRAIN_PRE_EMPHASIS_MASK);
- switch (signal_levels) {
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_400MV_0DB_BDW; /* Sel0 */
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_400MV_3_5DB_BDW; /* Sel1 */
- case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
- return DDI_BUF_EMP_400MV_6DB_BDW; /* Sel2 */
-
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_600MV_0DB_BDW; /* Sel3 */
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_600MV_3_5DB_BDW; /* Sel4 */
- case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
- return DDI_BUF_EMP_600MV_6DB_BDW; /* Sel5 */
-
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_800MV_0DB_BDW; /* Sel6 */
- case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
- return DDI_BUF_EMP_800MV_3_5DB_BDW; /* Sel7 */
-
- case DP_TRAIN_VOLTAGE_SWING_1200 | DP_TRAIN_PRE_EMPHASIS_0:
- return DDI_BUF_EMP_1200MV_0DB_BDW; /* Sel8 */
-
- default:
- DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
- "0x%x\n", signal_levels);
- return DDI_BUF_EMP_400MV_0DB_BDW; /* Sel0 */
- }
-}
-
/* Properly updates "DP" with the correct signal levels. */
static void
intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
@@ -2744,10 +2888,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
uint32_t signal_levels, mask;
uint8_t train_set = intel_dp->train_set[0];
- if (IS_BROADWELL(dev)) {
- signal_levels = intel_bdw_signal_levels(train_set);
- mask = DDI_BUF_EMP_MASK;
- } else if (IS_HASWELL(dev)) {
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
signal_levels = intel_hsw_signal_levels(train_set);
mask = DDI_BUF_EMP_MASK;
} else if (IS_CHERRYVIEW(dev)) {
@@ -3246,6 +3387,33 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
edp_panel_vdd_off(intel_dp, false);
}
+static bool
+intel_dp_probe_mst(struct intel_dp *intel_dp)
+{
+ u8 buf[1];
+
+ if (!intel_dp->can_mst)
+ return false;
+
+ if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
+ return false;
+
+ _edp_panel_vdd_on(intel_dp);
+ if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
+ if (buf[0] & DP_MST_CAP) {
+ DRM_DEBUG_KMS("Sink is MST capable\n");
+ intel_dp->is_mst = true;
+ } else {
+ DRM_DEBUG_KMS("Sink is not MST capable\n");
+ intel_dp->is_mst = false;
+ }
+ }
+ edp_panel_vdd_off(intel_dp, false);
+
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+ return intel_dp->is_mst;
+}
+
int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -3283,6 +3451,20 @@ intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
sink_irq_vector, 1) == 1;
}
+static bool
+intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector)
+{
+ int ret;
+
+ ret = intel_dp_dpcd_read_wake(&intel_dp->aux,
+ DP_SINK_COUNT_ESI,
+ sink_irq_vector, 14);
+ if (ret != 14)
+ return false;
+
+ return true;
+}
+
static void
intel_dp_handle_test_request(struct intel_dp *intel_dp)
{
@@ -3290,6 +3472,63 @@ intel_dp_handle_test_request(struct intel_dp *intel_dp)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK);
}
+static int
+intel_dp_check_mst_status(struct intel_dp *intel_dp)
+{
+ bool bret;
+
+ if (intel_dp->is_mst) {
+ u8 esi[16] = { 0 };
+ int ret = 0;
+ int retry;
+ bool handled;
+ bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
+go_again:
+ if (bret == true) {
+
+ /* check link status - esi[10] = 0x200c */
+ if (intel_dp->active_mst_links && !drm_dp_channel_eq_ok(&esi[10], intel_dp->lane_count)) {
+ DRM_DEBUG_KMS("channel EQ not ok, retraining\n");
+ intel_dp_start_link_train(intel_dp);
+ intel_dp_complete_link_train(intel_dp);
+ intel_dp_stop_link_train(intel_dp);
+ }
+
+ DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+ ret = drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
+
+ if (handled) {
+ for (retry = 0; retry < 3; retry++) {
+ int wret;
+ wret = drm_dp_dpcd_write(&intel_dp->aux,
+ DP_SINK_COUNT_ESI+1,
+ &esi[1], 3);
+ if (wret == 3) {
+ break;
+ }
+ }
+
+ bret = intel_dp_get_sink_irq_esi(intel_dp, esi);
+ if (bret == true) {
+ DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+ goto go_again;
+ }
+ } else
+ ret = 0;
+
+ return ret;
+ } else {
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ DRM_DEBUG_KMS("failed to get ESI - device may have failed\n");
+ intel_dp->is_mst = false;
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+ /* send a hotplug event */
+ drm_kms_helper_hotplug_event(intel_dig_port->base.base.dev);
+ }
+ }
+ return -EINVAL;
+}
+
/*
* According to DP spec
* 5.1.2:
@@ -3298,15 +3537,16 @@ intel_dp_handle_test_request(struct intel_dp *intel_dp)
* 3. Use Link Training from 2.5.3.3 and 3.5.1.3
* 4. Check link status on receipt of hot-plug interrupt
*/
-
void
intel_dp_check_link_status(struct intel_dp *intel_dp)
{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
u8 sink_irq_vector;
u8 link_status[DP_LINK_STATUS_SIZE];
- /* FIXME: This access isn't protected by any locks. */
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
if (!intel_encoder->connectors_active)
return;
@@ -3518,8 +3758,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
enum drm_connector_status status;
enum intel_display_power_domain power_domain;
struct edid *edid = NULL;
-
- intel_runtime_pm_get(dev_priv);
+ bool ret;
power_domain = intel_display_port_power_domain(intel_encoder);
intel_display_power_get(dev_priv, power_domain);
@@ -3527,6 +3766,14 @@ intel_dp_detect(struct drm_connector *connector, bool force)
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
+ if (intel_dp->is_mst) {
+ /* MST devices are disconnected from a monitor POV */
+ if (intel_encoder->type != INTEL_OUTPUT_EDP)
+ intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+ status = connector_status_disconnected;
+ goto out;
+ }
+
intel_dp->has_audio = false;
if (HAS_PCH_SPLIT(dev))
@@ -3539,6 +3786,16 @@ intel_dp_detect(struct drm_connector *connector, bool force)
intel_dp_probe_oui(intel_dp);
+ ret = intel_dp_probe_mst(intel_dp);
+ if (ret) {
+ /* if we are in MST mode then this connector
+ won't appear connected or have anything with EDID on it */
+ if (intel_encoder->type != INTEL_OUTPUT_EDP)
+ intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+ status = connector_status_disconnected;
+ goto out;
+ }
+
if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
} else {
@@ -3555,9 +3812,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
out:
intel_display_power_put(dev_priv, power_domain);
-
- intel_runtime_pm_put(dev_priv);
-
return status;
}
@@ -3734,6 +3988,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
drm_dp_aux_unregister(&intel_dp->aux);
+ intel_dp_mst_encoder_cleanup(intel_dig_port);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
@@ -3748,6 +4003,11 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
kfree(intel_dig_port);
}
+static void intel_dp_encoder_reset(struct drm_encoder *encoder)
+{
+ intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
+}
+
static const struct drm_connector_funcs intel_dp_connector_funcs = {
.dpms = intel_connector_dpms,
.detect = intel_dp_detect,
@@ -3763,15 +4023,68 @@ static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs =
};
static const struct drm_encoder_funcs intel_dp_enc_funcs = {
+ .reset = intel_dp_encoder_reset,
.destroy = intel_dp_encoder_destroy,
};
-static void
+void
intel_dp_hot_plug(struct intel_encoder *intel_encoder)
{
- struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+ return;
+}
+
+bool
+intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
+{
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+ if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
+ intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
+
+ DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
+ long_hpd ? "long" : "short");
+
+ if (long_hpd) {
+ if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
+ goto mst_fail;
+
+ if (!intel_dp_get_dpcd(intel_dp)) {
+ goto mst_fail;
+ }
+
+ intel_dp_probe_oui(intel_dp);
+
+ if (!intel_dp_probe_mst(intel_dp))
+ goto mst_fail;
- intel_dp_check_link_status(intel_dp);
+ } else {
+ if (intel_dp->is_mst) {
+ ret = intel_dp_check_mst_status(intel_dp);
+ if (ret == -EINVAL)
+ goto mst_fail;
+ }
+
+ if (!intel_dp->is_mst) {
+ /*
+ * we'll check the link status via the normal hot plug path later -
+ * but for short hpds we should check it now
+ */
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+ intel_dp_check_link_status(intel_dp);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
+ }
+ }
+ return false;
+mst_fail:
+ /* if we were in MST mode, and device is not there get out of MST mode */
+ if (intel_dp->is_mst) {
+ DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+ intel_dp->is_mst = false;
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+ }
+ return true;
}
/* Return which DP Port should be selected for Transcoder DP control */
@@ -3822,7 +4135,7 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port)
return false;
}
-static void
+void
intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -4035,6 +4348,11 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
return;
}
+ /*
+ * FIXME: This needs proper synchronization with psr state. But really
+ * hard to tell without seeing the user of this function of this code.
+ * Check locking and ordering once that lands.
+ */
if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
return;
@@ -4138,6 +4456,32 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
return downclock_mode;
}
+void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
+{
+ struct drm_device *dev = intel_encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp;
+ enum intel_display_power_domain power_domain;
+
+ if (intel_encoder->type != INTEL_OUTPUT_EDP)
+ return;
+
+ intel_dp = enc_to_intel_dp(&intel_encoder->base);
+ if (!edp_have_panel_vdd(intel_dp))
+ return;
+ /*
+ * The VDD bit needs a power domain reference, so if the bit is
+ * already enabled when we boot or resume, grab this reference and
+ * schedule a vdd off, so we don't hold on to the reference
+ * indefinitely.
+ */
+ DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n");
+ power_domain = intel_display_port_power_domain(intel_encoder);
+ intel_display_power_get(dev_priv, power_domain);
+
+ edp_panel_vdd_schedule_off(intel_dp);
+}
+
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct intel_connector *intel_connector,
struct edp_power_seq *power_seq)
@@ -4158,13 +4502,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!is_edp(intel_dp))
return true;
- /* The VDD bit needs a power domain reference, so if the bit is already
- * enabled when we boot, grab this reference. */
- if (edp_have_panel_vdd(intel_dp)) {
- enum intel_display_power_domain power_domain;
- power_domain = intel_display_port_power_domain(intel_encoder);
- intel_display_power_get(dev_priv, power_domain);
- }
+ intel_edp_panel_vdd_sanitize(intel_encoder);
/* Cache DPCD and EDID for edp. */
intel_edp_panel_vdd_on(intel_dp);
@@ -4288,7 +4626,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
edp_panel_vdd_work);
intel_connector_attach_encoder(intel_connector, intel_encoder);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
if (HAS_DDI(dev))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
@@ -4321,7 +4659,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
intel_dp_aux_init(intel_dp, intel_connector);
- intel_dp->psr_setup_done = false;
+ /* init MST on ports that can support it */
+ if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+ if (port == PORT_B || port == PORT_C || port == PORT_D) {
+ intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id);
+ }
+ }
if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
drm_dp_aux_unregister(&intel_dp->aux);
@@ -4331,7 +4674,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
edp_panel_vdd_off_sync(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
return false;
}
@@ -4353,6 +4696,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
void
intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
@@ -4379,6 +4723,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
if (IS_CHERRYVIEW(dev)) {
+ intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
intel_encoder->pre_enable = chv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
intel_encoder->post_disable = chv_post_disable_dp;
@@ -4408,9 +4753,55 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->cloneable = 0;
intel_encoder->hot_plug = intel_dp_hot_plug;
+ intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
+ dev_priv->hpd_irq_port[port] = intel_dig_port;
+
if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
drm_encoder_cleanup(encoder);
kfree(intel_dig_port);
kfree(intel_connector);
}
}
+
+void intel_dp_mst_suspend(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ /* disable MST */
+ for (i = 0; i < I915_MAX_PORTS; i++) {
+ struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+ if (!intel_dig_port)
+ continue;
+
+ if (intel_dig_port->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+ if (!intel_dig_port->dp.can_mst)
+ continue;
+ if (intel_dig_port->dp.is_mst)
+ drm_dp_mst_topology_mgr_suspend(&intel_dig_port->dp.mst_mgr);
+ }
+ }
+}
+
+void intel_dp_mst_resume(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int i;
+
+ for (i = 0; i < I915_MAX_PORTS; i++) {
+ struct intel_digital_port *intel_dig_port = dev_priv->hpd_irq_port[i];
+ if (!intel_dig_port)
+ continue;
+ if (intel_dig_port->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+ int ret;
+
+ if (!intel_dig_port->dp.can_mst)
+ continue;
+
+ ret = drm_dp_mst_topology_mgr_resume(&intel_dig_port->dp.mst_mgr);
+ if (ret != 0) {
+ intel_dp_check_mst_status(&intel_dig_port->dp);
+ }
+ }
+ }
+}
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
new file mode 100644
index 000000000000..d9a7a7865f66
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ * 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <drm/drmP.h>
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+
+static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = encoder->base.dev;
+ int bpp;
+ int lane_count, slots;
+ struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+ struct intel_connector *found = NULL, *intel_connector;
+ int mst_pbn;
+
+ pipe_config->dp_encoder_is_mst = true;
+ pipe_config->has_pch_encoder = false;
+ pipe_config->has_dp_encoder = true;
+ bpp = 24;
+ /*
+ * for MST we always configure max link bw - the spec doesn't
+ * seem to suggest we should do otherwise.
+ */
+ lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+ intel_dp->link_bw = intel_dp_max_link_bw(intel_dp);
+ intel_dp->lane_count = lane_count;
+
+ pipe_config->pipe_bpp = 24;
+ pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+
+ list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) {
+ if (intel_connector->new_encoder == encoder) {
+ found = intel_connector;
+ break;
+ }
+ }
+
+ if (!found) {
+ DRM_ERROR("can't find connector\n");
+ return false;
+ }
+
+ mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
+
+ pipe_config->pbn = mst_pbn;
+ slots = drm_dp_find_vcpi_slots(&intel_dp->mst_mgr, mst_pbn);
+
+ intel_link_compute_m_n(bpp, lane_count,
+ adjusted_mode->crtc_clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m_n);
+
+ pipe_config->dp_m_n.tu = slots;
+ return true;
+
+}
+
+static void intel_mst_disable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ int ret;
+
+ DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+ drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->port);
+
+ ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
+ if (ret) {
+ DRM_ERROR("failed to update payload %d\n", ret);
+ }
+}
+
+static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+ DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+ /* this can fail */
+ drm_dp_check_act_status(&intel_dp->mst_mgr);
+ /* and this can also fail */
+ drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+ drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->port);
+
+ intel_dp->active_mst_links--;
+ intel_mst->port = NULL;
+ if (intel_dp->active_mst_links == 0) {
+ intel_dig_port->base.post_disable(&intel_dig_port->base);
+ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
+ }
+}
+
+static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum port port = intel_dig_port->port;
+ int ret;
+ uint32_t temp;
+ struct intel_connector *found = NULL, *intel_connector;
+ int slots;
+ struct drm_crtc *crtc = encoder->base.crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) {
+ if (intel_connector->new_encoder == encoder) {
+ found = intel_connector;
+ break;
+ }
+ }
+
+ if (!found) {
+ DRM_ERROR("can't find connector\n");
+ return;
+ }
+
+ DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+ intel_mst->port = found->port;
+
+ if (intel_dp->active_mst_links == 0) {
+ enum port port = intel_ddi_get_encoder_port(encoder);
+
+ I915_WRITE(PORT_CLK_SEL(port), intel_crtc->config.ddi_pll_sel);
+
+ intel_ddi_init_dp_buf_reg(&intel_dig_port->base);
+
+ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+
+
+ intel_dp_start_link_train(intel_dp);
+ intel_dp_complete_link_train(intel_dp);
+ intel_dp_stop_link_train(intel_dp);
+ }
+
+ ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
+ intel_mst->port, intel_crtc->config.pbn, &slots);
+ if (ret == false) {
+ DRM_ERROR("failed to allocate vcpi\n");
+ return;
+ }
+
+
+ intel_dp->active_mst_links++;
+ temp = I915_READ(DP_TP_STATUS(port));
+ I915_WRITE(DP_TP_STATUS(port), temp);
+
+ ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
+}
+
+static void intel_mst_enable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum port port = intel_dig_port->port;
+ int ret;
+
+ DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
+
+ if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_ACT_SENT),
+ 1))
+ DRM_ERROR("Timed out waiting for ACT sent\n");
+
+ ret = drm_dp_check_act_status(&intel_dp->mst_mgr);
+
+ ret = drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+}
+
+static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
+ enum pipe *pipe)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ *pipe = intel_mst->pipe;
+ if (intel_mst->port)
+ return true;
+ return false;
+}
+
+static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+ struct intel_digital_port *intel_dig_port = intel_mst->primary;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
+ u32 temp, flags = 0;
+
+ pipe_config->has_dp_encoder = true;
+
+ temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+ if (temp & TRANS_DDI_PHSYNC)
+ flags |= DRM_MODE_FLAG_PHSYNC;
+ else
+ flags |= DRM_MODE_FLAG_NHSYNC;
+ if (temp & TRANS_DDI_PVSYNC)
+ flags |= DRM_MODE_FLAG_PVSYNC;
+ else
+ flags |= DRM_MODE_FLAG_NVSYNC;
+
+ switch (temp & TRANS_DDI_BPC_MASK) {
+ case TRANS_DDI_BPC_6:
+ pipe_config->pipe_bpp = 18;
+ break;
+ case TRANS_DDI_BPC_8:
+ pipe_config->pipe_bpp = 24;
+ break;
+ case TRANS_DDI_BPC_10:
+ pipe_config->pipe_bpp = 30;
+ break;
+ case TRANS_DDI_BPC_12:
+ pipe_config->pipe_bpp = 36;
+ break;
+ default:
+ break;
+ }
+ pipe_config->adjusted_mode.flags |= flags;
+ intel_dp_get_m_n(crtc, pipe_config);
+
+ intel_ddi_clock_get(&intel_dig_port->base, pipe_config);
+}
+
+static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_dp *intel_dp = intel_connector->mst_port;
+ struct edid *edid;
+ int ret;
+
+ edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
+ if (!edid)
+ return 0;
+
+ ret = intel_connector_update_modes(connector, edid);
+ kfree(edid);
+
+ return ret;
+}
+
+static enum drm_connector_status
+intel_mst_port_dp_detect(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_dp *intel_dp = intel_connector->mst_port;
+
+ return drm_dp_mst_detect_port(&intel_dp->mst_mgr, intel_connector->port);
+}
+
+static enum drm_connector_status
+intel_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+ enum drm_connector_status status;
+ status = intel_mst_port_dp_detect(connector);
+ return status;
+}
+
+static int
+intel_dp_mst_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t val)
+{
+ return 0;
+}
+
+static void
+intel_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+
+ if (!IS_ERR_OR_NULL(intel_connector->edid))
+ kfree(intel_connector->edid);
+
+ drm_connector_cleanup(connector);
+ kfree(connector);
+}
+
+static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
+ .dpms = intel_connector_dpms,
+ .detect = intel_dp_mst_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = intel_dp_mst_set_property,
+ .destroy = intel_dp_mst_connector_destroy,
+};
+
+static int intel_dp_mst_get_modes(struct drm_connector *connector)
+{
+ return intel_dp_mst_get_ddc_modes(connector);
+}
+
+static enum drm_mode_status
+intel_dp_mst_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ /* TODO - validate mode against available PBN for link */
+ if (mode->clock < 10000)
+ return MODE_CLOCK_LOW;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ return MODE_H_ILLEGAL;
+
+ return MODE_OK;
+}
+
+static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_dp *intel_dp = intel_connector->mst_port;
+ return &intel_dp->mst_encoders[0]->base.base;
+}
+
+static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
+ .get_modes = intel_dp_mst_get_modes,
+ .mode_valid = intel_dp_mst_mode_valid,
+ .best_encoder = intel_mst_best_encoder,
+};
+
+static void intel_dp_mst_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
+
+ drm_encoder_cleanup(encoder);
+ kfree(intel_mst);
+}
+
+static const struct drm_encoder_funcs intel_dp_mst_enc_funcs = {
+ .destroy = intel_dp_mst_encoder_destroy,
+};
+
+static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
+{
+ if (connector->encoder) {
+ enum pipe pipe;
+ if (!connector->encoder->get_hw_state(connector->encoder, &pipe))
+ return false;
+ return true;
+ }
+ return false;
+}
+
+static void intel_connector_add_to_fbdev(struct intel_connector *connector)
+{
+#ifdef CONFIG_DRM_I915_FBDEV
+ struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ drm_fb_helper_add_one_connector(&dev_priv->fbdev->helper, &connector->base);
+#endif
+}
+
+static void intel_connector_remove_from_fbdev(struct intel_connector *connector)
+{
+#ifdef CONFIG_DRM_I915_FBDEV
+ struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+ drm_fb_helper_remove_one_connector(&dev_priv->fbdev->helper, &connector->base);
+#endif
+}
+
+static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, char *pathprop)
+{
+ struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct intel_connector *intel_connector;
+ struct drm_connector *connector;
+ int i;
+
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+ if (!intel_connector)
+ return NULL;
+
+ connector = &intel_connector->base;
+ drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort);
+ drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
+
+ intel_connector->unregister = intel_connector_unregister;
+ intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
+ intel_connector->mst_port = intel_dp;
+ intel_connector->port = port;
+
+ for (i = PIPE_A; i <= PIPE_C; i++) {
+ drm_mode_connector_attach_encoder(&intel_connector->base,
+ &intel_dp->mst_encoders[i]->base.base);
+ }
+ intel_dp_add_properties(intel_dp, connector);
+
+ drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+ drm_mode_connector_set_path_property(connector, pathprop);
+ drm_reinit_primary_mode_group(dev);
+ mutex_lock(&dev->mode_config.mutex);
+ intel_connector_add_to_fbdev(intel_connector);
+ mutex_unlock(&dev->mode_config.mutex);
+ drm_connector_register(&intel_connector->base);
+ return connector;
+}
+
+static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct drm_device *dev = connector->dev;
+ /* need to nuke the connector */
+ mutex_lock(&dev->mode_config.mutex);
+ intel_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ mutex_unlock(&dev->mode_config.mutex);
+
+ intel_connector->unregister(intel_connector);
+
+ mutex_lock(&dev->mode_config.mutex);
+ intel_connector_remove_from_fbdev(intel_connector);
+ drm_connector_cleanup(connector);
+ mutex_unlock(&dev->mode_config.mutex);
+
+ drm_reinit_primary_mode_group(dev);
+
+ kfree(intel_connector);
+ DRM_DEBUG_KMS("\n");
+}
+
+static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+ struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+
+ drm_kms_helper_hotplug_event(dev);
+}
+
+static struct drm_dp_mst_topology_cbs mst_cbs = {
+ .add_connector = intel_dp_add_mst_connector,
+ .destroy_connector = intel_dp_destroy_mst_connector,
+ .hotplug = intel_dp_mst_hotplug,
+};
+
+static struct intel_dp_mst_encoder *
+intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum pipe pipe)
+{
+ struct intel_dp_mst_encoder *intel_mst;
+ struct intel_encoder *intel_encoder;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+
+ intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL);
+
+ if (!intel_mst)
+ return NULL;
+
+ intel_mst->pipe = pipe;
+ intel_encoder = &intel_mst->base;
+ intel_mst->primary = intel_dig_port;
+
+ drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
+ DRM_MODE_ENCODER_DPMST);
+
+ intel_encoder->type = INTEL_OUTPUT_DP_MST;
+ intel_encoder->crtc_mask = 0x7;
+ intel_encoder->cloneable = 0;
+
+ intel_encoder->compute_config = intel_dp_mst_compute_config;
+ intel_encoder->disable = intel_mst_disable_dp;
+ intel_encoder->post_disable = intel_mst_post_disable_dp;
+ intel_encoder->pre_enable = intel_mst_pre_enable_dp;
+ intel_encoder->enable = intel_mst_enable_dp;
+ intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state;
+ intel_encoder->get_config = intel_dp_mst_enc_get_config;
+
+ return intel_mst;
+
+}
+
+static bool
+intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port)
+{
+ int i;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+ for (i = PIPE_A; i <= PIPE_C; i++)
+ intel_dp->mst_encoders[i] = intel_dp_create_fake_mst_encoder(intel_dig_port, i);
+ return true;
+}
+
+int
+intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id)
+{
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ int ret;
+
+ intel_dp->can_mst = true;
+ intel_dp->mst_mgr.cbs = &mst_cbs;
+
+ /* create encoders */
+ intel_dp_create_fake_mst_encoders(intel_dig_port);
+ ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev->dev, &intel_dp->aux, 16, 3, conn_base_id);
+ if (ret) {
+ intel_dp->can_mst = false;
+ return ret;
+ }
+ return 0;
+}
+
+void
+intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port)
+{
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+ if (!intel_dp->can_mst)
+ return;
+
+ drm_dp_mst_topology_mgr_destroy(&intel_dp->mst_mgr);
+ /* encoders will get killed by normal cleanup */
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f67340ed2c12..4b2664bd5b81 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -32,7 +32,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
-#include <drm/drm_dp_helper.h>
+#include <drm/drm_dp_mst_helper.h>
/**
* _wait_for - magic (register) wait macro
@@ -100,6 +100,7 @@
#define INTEL_OUTPUT_EDP 8
#define INTEL_OUTPUT_DSI 9
#define INTEL_OUTPUT_UNKNOWN 10
+#define INTEL_OUTPUT_DP_MST 11
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
@@ -165,6 +166,7 @@ struct intel_panel {
struct {
bool present;
u32 level;
+ u32 min;
u32 max;
bool enabled;
bool combination_mode; /* gen 2/4 only */
@@ -207,6 +209,10 @@ struct intel_connector {
/* since POLL and HPD connectors may use the same HPD line keep the native
state of connector->polled in case hotplug storm detection changes it */
u8 polled;
+
+ void *port; /* store this opaque as its illegal to dereference it */
+
+ struct intel_dp *mst_port;
};
typedef struct dpll {
@@ -307,6 +313,9 @@ struct intel_crtc_config {
/* Selected dpll when shared or DPLL_ID_PRIVATE. */
enum intel_dpll_id shared_dpll;
+ /* PORT_CLK_SEL for DDI ports. */
+ uint32_t ddi_pll_sel;
+
/* Actual register state of the dpll, for shared dpll cross-checking. */
struct intel_dpll_hw_state dpll_hw_state;
@@ -338,6 +347,7 @@ struct intel_crtc_config {
u32 pos;
u32 size;
bool enabled;
+ bool force_thru;
} pch_pfit;
/* FDI configuration, only valid if has_pch_encoder is set. */
@@ -347,6 +357,9 @@ struct intel_crtc_config {
bool ips_enabled;
bool double_wide;
+
+ bool dp_encoder_is_mst;
+ int pbn;
};
struct intel_pipe_wm {
@@ -358,6 +371,11 @@ struct intel_pipe_wm {
bool sprites_scaled;
};
+struct intel_mmio_flip {
+ u32 seqno;
+ u32 ring_id;
+};
+
struct intel_crtc {
struct drm_crtc base;
enum pipe pipe;
@@ -384,7 +402,6 @@ struct intel_crtc {
struct drm_i915_gem_object *cursor_bo;
uint32_t cursor_addr;
- int16_t cursor_x, cursor_y;
int16_t cursor_width, cursor_height;
uint32_t cursor_cntl;
uint32_t cursor_base;
@@ -394,8 +411,6 @@ struct intel_crtc {
struct intel_crtc_config *new_config;
bool new_enabled;
- uint32_t ddi_pll_sel;
-
/* reset counter value when the last flip was submitted */
unsigned int reset_counter;
@@ -412,10 +427,12 @@ struct intel_crtc {
wait_queue_head_t vbl_wait;
int scanline_offset;
+ struct intel_mmio_flip mmio_flip;
};
struct intel_plane_wm_parameters {
uint32_t horiz_pixels;
+ uint32_t vert_pixels;
uint8_t bytes_per_pixel;
bool enabled;
bool scaled;
@@ -428,7 +445,6 @@ struct intel_plane {
struct drm_i915_gem_object *obj;
bool can_scale;
int max_downscale;
- u32 lut_r[1024], lut_g[1024], lut_b[1024];
int crtc_x, crtc_y;
unsigned int crtc_w, crtc_h;
uint32_t src_x, src_y;
@@ -481,6 +497,7 @@ struct cxsr_latency {
#define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
#define to_intel_plane(x) container_of(x, struct intel_plane, base)
+#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
struct intel_hdmi {
u32 hdmi_reg;
@@ -491,6 +508,7 @@ struct intel_hdmi {
bool has_audio;
enum hdmi_force_audio force_audio;
bool rgb_quant_range_selectable;
+ enum hdmi_picture_aspect aspect_ratio;
void (*write_infoframe)(struct drm_encoder *encoder,
enum hdmi_infoframe_type type,
const void *frame, ssize_t len);
@@ -499,6 +517,7 @@ struct intel_hdmi {
struct drm_display_mode *adjusted_mode);
};
+struct intel_dp_mst_encoder;
#define DP_MAX_DOWNSTREAM_PORTS 0x10
/**
@@ -537,12 +556,20 @@ struct intel_dp {
unsigned long last_power_cycle;
unsigned long last_power_on;
unsigned long last_backlight_off;
- bool psr_setup_done;
+
struct notifier_block edp_notifier;
bool use_tps3;
+ bool can_mst; /* this port supports mst */
+ bool is_mst;
+ int active_mst_links;
+ /* connector directly attached - won't be use for modeset in mst world */
struct intel_connector *attached_connector;
+ /* mst connector list */
+ struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES];
+ struct drm_dp_mst_topology_mgr mst_mgr;
+
uint32_t (*get_aux_clock_divider)(struct intel_dp *dp, int index);
/*
* This function returns the value we have to program the AUX_CTL
@@ -566,6 +593,14 @@ struct intel_digital_port {
u32 saved_port_bits;
struct intel_dp dp;
struct intel_hdmi hdmi;
+ bool (*hpd_pulse)(struct intel_digital_port *, bool);
+};
+
+struct intel_dp_mst_encoder {
+ struct intel_encoder base;
+ enum pipe pipe;
+ struct intel_digital_port *primary;
+ void *port; /* store this opaque as its illegal to dereference it */
};
static inline int
@@ -652,6 +687,12 @@ enc_to_dig_port(struct drm_encoder *encoder)
return container_of(encoder, struct intel_digital_port, base.base);
}
+static inline struct intel_dp_mst_encoder *
+enc_to_mst(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct intel_dp_mst_encoder, base.base);
+}
+
static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
{
return &enc_to_dig_port(encoder)->dp;
@@ -676,17 +717,26 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable);
-void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void bdw_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-void bdw_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen8_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen8_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
void intel_runtime_pm_disable_interrupts(struct drm_device *dev);
void intel_runtime_pm_restore_interrupts(struct drm_device *dev);
+static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
+{
+ /*
+ * We only use drm_irq_uninstall() at unload and VT switch, so
+ * this is the only thing we need to check.
+ */
+ return !dev_priv->pm._irqs_disabled;
+}
+
int intel_get_crtc_scanline(struct intel_crtc *crtc);
void i9xx_check_fifo_underruns(struct drm_device *dev);
-
+void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);
/* intel_crt.c */
void intel_crt_init(struct drm_device *dev);
@@ -705,10 +755,7 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
enum transcoder cpu_transcoder);
void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
-void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
bool intel_ddi_pll_select(struct intel_crtc *crtc);
-void intel_ddi_pll_enable(struct intel_crtc *crtc);
-void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
@@ -716,17 +763,46 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc);
void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config);
+void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder);
+void intel_ddi_clock_get(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config);
+void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state);
/* intel_display.c */
const char *intel_output_name(int output);
bool intel_has_pending_fb_unpin(struct drm_device *dev);
int intel_pch_rawclk(struct drm_device *dev);
-int valleyview_cur_cdclk(struct drm_i915_private *dev_priv);
void intel_mark_busy(struct drm_device *dev);
-void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring);
+void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+ struct intel_engine_cs *ring);
+void intel_frontbuffer_flip_prepare(struct drm_device *dev,
+ unsigned frontbuffer_bits);
+void intel_frontbuffer_flip_complete(struct drm_device *dev,
+ unsigned frontbuffer_bits);
+void intel_frontbuffer_flush(struct drm_device *dev,
+ unsigned frontbuffer_bits);
+/**
+ * intel_frontbuffer_flip - prepare frontbuffer flip
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called after scheduling a flip on @obj. This is for
+ * synchronous plane updates which will happen on the next vblank and which will
+ * not get delayed by pending gpu rendering.
+ *
+ * Can be called without any locks held.
+ */
+static inline
+void intel_frontbuffer_flip(struct drm_device *dev,
+ unsigned frontbuffer_bits)
+{
+ intel_frontbuffer_flush(dev, frontbuffer_bits);
+}
+
+void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire);
void intel_mark_idle(struct drm_device *dev);
void intel_crtc_restore_mode(struct drm_crtc *crtc);
+void intel_crtc_control(struct drm_crtc *crtc, bool enable);
void intel_crtc_update_dpms(struct drm_crtc *crtc);
void intel_encoder_destroy(struct drm_encoder *encoder);
void intel_connector_dpms(struct drm_connector *, int mode);
@@ -767,12 +843,18 @@ __intel_framebuffer_create(struct drm_device *dev,
void intel_prepare_page_flip(struct drm_device *dev, int plane);
void intel_finish_page_flip(struct drm_device *dev, int pipe);
void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
+
+/* shared dpll functions */
struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
bool state);
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc);
+void intel_put_shared_dpll(struct intel_crtc *crtc);
+
+/* modesetting asserts */
void assert_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_pll_enabled(d, p) assert_pll(d, p, true)
@@ -805,7 +887,6 @@ void hsw_disable_ips(struct intel_crtc *crtc);
void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
enum intel_display_power_domain
intel_display_port_power_domain(struct intel_encoder *intel_encoder);
-int valleyview_get_vco(struct drm_i915_private *dev_priv);
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_config *pipe_config);
int intel_format_to_fourcc(int format);
@@ -826,18 +907,34 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc);
bool intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config);
bool intel_dp_is_edp(struct drm_device *dev, enum port port);
+bool intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
+ bool long_hpd);
void intel_edp_backlight_on(struct intel_dp *intel_dp);
void intel_edp_backlight_off(struct intel_dp *intel_dp);
void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
+void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder);
void intel_edp_panel_on(struct intel_dp *intel_dp);
void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_edp_psr_enable(struct intel_dp *intel_dp);
void intel_edp_psr_disable(struct intel_dp *intel_dp);
-void intel_edp_psr_update(struct drm_device *dev);
void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
-
+void intel_edp_psr_invalidate(struct drm_device *dev,
+ unsigned frontbuffer_bits);
+void intel_edp_psr_flush(struct drm_device *dev,
+ unsigned frontbuffer_bits);
+void intel_edp_psr_init(struct drm_device *dev);
+
+int intel_dp_handle_hpd_irq(struct intel_digital_port *digport, bool long_hpd);
+void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector);
+void intel_dp_mst_suspend(struct drm_device *dev);
+void intel_dp_mst_resume(struct drm_device *dev);
+int intel_dp_max_link_bw(struct intel_dp *intel_dp);
+void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
+/* intel_dp_mst.c */
+int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
+void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
/* intel_dsi.c */
-bool intel_dsi_init(struct drm_device *dev);
+void intel_dsi_init(struct drm_device *dev);
/* intel_dvo.c */
@@ -920,8 +1017,8 @@ void intel_pch_panel_fitting(struct intel_crtc *crtc,
void intel_gmch_panel_fitting(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config,
int fitting_mode);
-void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
- u32 max);
+void intel_panel_set_backlight_acpi(struct intel_connector *connector,
+ u32 level, u32 max);
int intel_panel_setup_backlight(struct drm_connector *connector);
void intel_panel_enable_backlight(struct intel_connector *connector);
void intel_panel_disable_backlight(struct intel_connector *connector);
@@ -940,7 +1037,9 @@ int ilk_wm_max_level(const struct drm_device *dev);
void intel_update_watermarks(struct drm_crtc *crtc);
void intel_update_sprite_watermarks(struct drm_plane *plane,
struct drm_crtc *crtc,
- uint32_t sprite_width, int pixel_size,
+ uint32_t sprite_width,
+ uint32_t sprite_height,
+ int pixel_size,
bool enabled, bool scaled);
void intel_init_pm(struct drm_device *dev);
void intel_pm_setup(struct drm_device *dev);
@@ -963,6 +1062,7 @@ void intel_init_gt_powersave(struct drm_device *dev);
void intel_cleanup_gt_powersave(struct drm_device *dev);
void intel_enable_gt_powersave(struct drm_device *dev);
void intel_disable_gt_powersave(struct drm_device *dev);
+void intel_suspend_gt_powersave(struct drm_device *dev);
void intel_reset_gt_powersave(struct drm_device *dev);
void ironlake_teardown_rc6(struct drm_device *dev);
void gen6_update_ring_freq(struct drm_device *dev);
@@ -976,8 +1076,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-void __vlv_set_power_well(struct drm_i915_private *dev_priv,
- enum punit_power_well power_well_id, bool enable);
+
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 3fd082933c87..670c29a7b5dd 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -92,6 +92,9 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
if (fixed_mode)
intel_fixed_panel_mode(fixed_mode, adjusted_mode);
+ /* DSI uses short packets for sync events, so clear mode flags for DSI */
+ adjusted_mode->flags = 0;
+
if (intel_dsi->dev.dev_ops->mode_fixup)
return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev,
mode, adjusted_mode);
@@ -152,6 +155,8 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
if (intel_dsi->dev.dev_ops->enable)
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+ wait_for_dsi_fifo_empty(intel_dsi);
+
/* assert ip_tg_enable signal */
temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
temp = temp | intel_dsi->port_bits;
@@ -177,6 +182,10 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
tmp |= DPLL_REFA_CLK_ENABLE_VLV;
I915_WRITE(DPLL(pipe), tmp);
+ /* update the hw state for DPLL */
+ intel_crtc->config.dpll_hw_state.dpll = DPLL_INTEGRATED_CLOCK_VLV |
+ DPLL_REFA_CLK_ENABLE_VLV;
+
tmp = I915_READ(DSPCLK_GATE_D);
tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
I915_WRITE(DSPCLK_GATE_D, tmp);
@@ -192,6 +201,8 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder)
if (intel_dsi->dev.dev_ops->send_otp_cmds)
intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
+ wait_for_dsi_fifo_empty(intel_dsi);
+
/* Enable port in pre-enable phase itself because as per hw team
* recommendation, port should be enabled befor plane & pipe */
intel_dsi_enable(encoder);
@@ -232,6 +243,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
DRM_DEBUG_KMS("\n");
if (is_vid_mode(intel_dsi)) {
+ wait_for_dsi_fifo_empty(intel_dsi);
+
/* de-assert ip_tg_enable signal */
temp = I915_READ(MIPI_PORT_CTRL(pipe));
I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE);
@@ -261,6 +274,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
* some next enable sequence send turn on packet error is observed */
if (intel_dsi->dev.dev_ops->disable)
intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
+
+ wait_for_dsi_fifo_empty(intel_dsi);
}
static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
@@ -351,9 +366,21 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
static void intel_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
+ u32 pclk;
DRM_DEBUG_KMS("\n");
- /* XXX: read flags, set to adjusted_mode */
+ /*
+ * DPLL_MD is not used in case of DSI, reading will get some default value
+ * set dpll_md = 0
+ */
+ pipe_config->dpll_hw_state.dpll_md = 0;
+
+ pclk = vlv_get_dsi_pclk(encoder, pipe_config->pipe_bpp);
+ if (!pclk)
+ return;
+
+ pipe_config->adjusted_mode.crtc_clock = pclk;
+ pipe_config->port_clock = pclk;
}
static enum drm_mode_status
@@ -658,7 +685,7 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
};
-bool intel_dsi_init(struct drm_device *dev)
+void intel_dsi_init(struct drm_device *dev)
{
struct intel_dsi *intel_dsi;
struct intel_encoder *intel_encoder;
@@ -674,29 +701,29 @@ bool intel_dsi_init(struct drm_device *dev)
/* There is no detection method for MIPI so rely on VBT */
if (!dev_priv->vbt.has_mipi)
- return false;
+ return;
+
+ if (IS_VALLEYVIEW(dev)) {
+ dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
+ } else {
+ DRM_ERROR("Unsupported Mipi device to reg base");
+ return;
+ }
intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
if (!intel_dsi)
- return false;
+ return;
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_dsi);
- return false;
+ return;
}
intel_encoder = &intel_dsi->base;
encoder = &intel_encoder->base;
intel_dsi->attached_connector = intel_connector;
- if (IS_VALLEYVIEW(dev)) {
- dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
- } else {
- DRM_ERROR("Unsupported Mipi device to reg base");
- return false;
- }
-
connector = &intel_connector->base;
drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI);
@@ -743,7 +770,7 @@ bool intel_dsi_init(struct drm_device *dev)
intel_connector_attach_encoder(intel_connector, intel_encoder);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev);
if (!fixed_mode) {
@@ -754,12 +781,10 @@ bool intel_dsi_init(struct drm_device *dev)
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
- return true;
+ return;
err:
drm_encoder_cleanup(&intel_encoder->base);
kfree(intel_dsi);
kfree(intel_connector);
-
- return false;
}
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index 31db33d3e5cc..fd51867fd0d3 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -132,6 +132,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
+extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp);
extern struct intel_dsi_dev_ops vbt_generic_dsi_display_ops;
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c
index 933c86305237..7f1430ac8543 100644
--- a/drivers/gpu/drm/i915/intel_dsi_cmd.c
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c
@@ -419,3 +419,19 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs)
return 0;
}
+
+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 mask;
+
+ mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY |
+ LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY;
+
+ if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 100))
+ DRM_ERROR("DPI FIFOs are not empty\n");
+}
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.h b/drivers/gpu/drm/i915/intel_dsi_cmd.h
index 9a18cbfa5460..46aa1acc00eb 100644
--- a/drivers/gpu/drm/i915/intel_dsi_cmd.h
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.h
@@ -51,6 +51,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
u8 *reqdata, int reqlen, u8 *buf, int buflen);
int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs);
+void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi);
/* XXX: questionable write helpers */
static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi,
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
index 21a0d348cedc..47c7584a4aa0 100644
--- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
@@ -143,7 +143,7 @@ static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data)
case MIPI_DSI_DCS_LONG_WRITE:
dsi_vc_dcs_write(intel_dsi, vc, data, len);
break;
- };
+ }
data += len;
@@ -294,7 +294,8 @@ static bool generic_init(struct intel_dsi_device *dsi)
intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
intel_dsi->init_count = mipi_config->master_init_timer;
intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
- intel_dsi->video_frmt_cfg_bits = mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
+ intel_dsi->video_frmt_cfg_bits =
+ mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
switch (intel_dsi->escape_clk_div) {
case 0:
@@ -351,7 +352,8 @@ static bool generic_init(struct intel_dsi_device *dsi)
*
* prepare count
*/
- ths_prepare_ns = max(mipi_config->ths_prepare, mipi_config->tclk_prepare);
+ ths_prepare_ns = max(mipi_config->ths_prepare,
+ mipi_config->tclk_prepare);
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * 2);
/* exit zero count */
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index ba79ec19da3b..d8bb1ea2f0da 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -298,3 +298,84 @@ void vlv_disable_dsi_pll(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->dpio_lock);
}
+
+static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
+{
+ int bpp;
+
+ switch (pixel_format) {
+ default:
+ case VID_MODE_FORMAT_RGB888:
+ case VID_MODE_FORMAT_RGB666_LOOSE:
+ bpp = 24;
+ break;
+ case VID_MODE_FORMAT_RGB666:
+ bpp = 18;
+ break;
+ case VID_MODE_FORMAT_RGB565:
+ bpp = 16;
+ break;
+ }
+
+ WARN(bpp != pipe_bpp,
+ "bpp match assertion failure (expected %d, current %d)\n",
+ bpp, pipe_bpp);
+}
+
+u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ u32 dsi_clock, pclk;
+ u32 pll_ctl, pll_div;
+ u32 m = 0, p = 0;
+ int refclk = 25000;
+ int i;
+
+ DRM_DEBUG_KMS("\n");
+
+ mutex_lock(&dev_priv->dpio_lock);
+ pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
+ pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER);
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ /* mask out other bits and extract the P1 divisor */
+ pll_ctl &= DSI_PLL_P1_POST_DIV_MASK;
+ pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);
+
+ /* mask out the other bits and extract the M1 divisor */
+ pll_div &= DSI_PLL_M1_DIV_MASK;
+ pll_div = pll_div >> DSI_PLL_M1_DIV_SHIFT;
+
+ while (pll_ctl) {
+ pll_ctl = pll_ctl >> 1;
+ p++;
+ }
+ p--;
+
+ if (!p) {
+ DRM_ERROR("wrong P1 divisor\n");
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lfsr_converts); i++) {
+ if (lfsr_converts[i] == pll_div)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(lfsr_converts)) {
+ DRM_ERROR("wrong m_seed programmed\n");
+ return 0;
+ }
+
+ m = i + 62;
+
+ dsi_clock = (m * refclk) / p;
+
+ /* pixel_format and pipe_bpp should agree */
+ assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp);
+
+ pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp);
+
+ return pclk;
+}
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index a3631c0a5c28..56b47d2ffaf7 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -112,7 +112,15 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base);
+ u32 tmp;
+
+ tmp = I915_READ(intel_dvo->dev.dvo_reg);
+
+ if (!(tmp & DVO_ENABLE))
+ return false;
return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
}
@@ -558,7 +566,7 @@ void intel_dvo_init(struct drm_device *dev)
intel_dvo->panel_wants_dither = true;
}
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return;
}
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 088fe9378a4c..f475414671d8 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -43,10 +43,36 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
+static int intel_fbdev_set_par(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct intel_fbdev *ifbdev =
+ container_of(fb_helper, struct intel_fbdev, helper);
+ int ret;
+
+ ret = drm_fb_helper_set_par(info);
+
+ if (ret == 0) {
+ /*
+ * FIXME: fbdev presumes that all callbacks also work from
+ * atomic contexts and relies on that for emergency oops
+ * printing. KMS totally doesn't do that and the locking here is
+ * by far not the only place this goes wrong. Ignore this for
+ * now until we solve this for real.
+ */
+ mutex_lock(&fb_helper->dev->struct_mutex);
+ ret = i915_gem_object_set_to_gtt_domain(ifbdev->fb->obj,
+ true);
+ mutex_unlock(&fb_helper->dev->struct_mutex);
+ }
+
+ return ret;
+}
+
static struct fb_ops intelfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
+ .fb_set_par = intel_fbdev_set_par,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
@@ -81,7 +107,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
sizes->surface_depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
+ size = PAGE_ALIGN(size);
obj = i915_gem_object_create_stolen(dev, size);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, size);
@@ -417,7 +443,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
}
crtcs[i] = new_crtc;
- DRM_DEBUG_KMS("connector %s on pipe %d [CRTC:%d]: %dx%d%s\n",
+ DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
connector->name,
pipe_name(to_intel_crtc(encoder->crtc)->pipe),
encoder->crtc->base.id,
@@ -452,7 +478,7 @@ out:
return true;
}
-static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.initial_config = intel_fb_initial_config,
.gamma_set = intel_crtc_fb_gamma_set,
.gamma_get = intel_crtc_fb_gamma_get,
@@ -623,7 +649,8 @@ int intel_fbdev_init(struct drm_device *dev)
if (ifbdev == NULL)
return -ENOMEM;
- ifbdev->helper.funcs = &intel_fb_helper_funcs;
+ drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
+
if (!intel_fbdev_init_bios(dev, ifbdev))
ifbdev->preferred_bpp = 32;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index eee2bbec2958..f9151f6641d9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -367,6 +367,9 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
union hdmi_infoframe frame;
int ret;
+ /* Set user selected PAR to incoming mode's member */
+ adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
+
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
adjusted_mode);
if (ret < 0) {
@@ -879,7 +882,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
struct intel_encoder *encoder;
int count = 0, count_hdmi = 0;
- if (!HAS_PCH_SPLIT(dev))
+ if (HAS_GMCH_DISPLAY(dev))
return false;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
@@ -1124,6 +1127,23 @@ intel_hdmi_set_property(struct drm_connector *connector,
goto done;
}
+ if (property == connector->dev->mode_config.aspect_ratio_property) {
+ switch (val) {
+ case DRM_MODE_PICTURE_ASPECT_NONE:
+ intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
+ break;
+ case DRM_MODE_PICTURE_ASPECT_4_3:
+ intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
+ break;
+ case DRM_MODE_PICTURE_ASPECT_16_9:
+ intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
+ break;
+ default:
+ return -EINVAL;
+ }
+ goto done;
+ }
+
return -EINVAL;
done:
@@ -1229,6 +1249,70 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->dpio_lock);
}
+static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+ struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(encoder->base.crtc);
+ enum dpio_channel ch = vlv_dport_to_channel(dport);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 val;
+
+ mutex_lock(&dev_priv->dpio_lock);
+
+ /* program left/right clock distribution */
+ if (pipe != PIPE_B) {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+ val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+ if (ch == DPIO_CH0)
+ val |= CHV_BUFLEFTENA1_FORCE;
+ if (ch == DPIO_CH1)
+ val |= CHV_BUFRIGHTENA1_FORCE;
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+ } else {
+ val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+ val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+ if (ch == DPIO_CH0)
+ val |= CHV_BUFLEFTENA2_FORCE;
+ if (ch == DPIO_CH1)
+ val |= CHV_BUFRIGHTENA2_FORCE;
+ vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+ }
+
+ /* program clock channel usage */
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch));
+ val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+ if (pipe != PIPE_B)
+ val &= ~CHV_PCS_USEDCLKCHANNEL;
+ else
+ val |= CHV_PCS_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+ val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+ if (pipe != PIPE_B)
+ val &= ~CHV_PCS_USEDCLKCHANNEL;
+ else
+ val |= CHV_PCS_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+
+ /*
+ * This a a bit weird since generally CL
+ * matches the pipe, but here we need to
+ * pick the CL based on the port.
+ */
+ val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch));
+ if (pipe != PIPE_B)
+ val &= ~CHV_CMN_USEDCLKCHANNEL;
+ else
+ val |= CHV_CMN_USEDCLKCHANNEL;
+ vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
+
+ mutex_unlock(&dev_priv->dpio_lock);
+}
+
static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1416,11 +1500,22 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
};
static void
+intel_attach_aspect_ratio_property(struct drm_connector *connector)
+{
+ if (!drm_mode_create_aspect_ratio_property(connector->dev))
+ drm_object_attach_property(&connector->base,
+ connector->dev->mode_config.aspect_ratio_property,
+ DRM_MODE_PICTURE_ASPECT_NONE);
+}
+
+static void
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
{
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
intel_hdmi->color_range_auto = true;
+ intel_attach_aspect_ratio_property(connector);
+ intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
}
void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
@@ -1467,7 +1562,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
if (IS_VALLEYVIEW(dev)) {
intel_hdmi->write_infoframe = vlv_write_infoframe;
intel_hdmi->set_infoframes = vlv_set_infoframes;
- } else if (!HAS_PCH_SPLIT(dev)) {
+ } else if (IS_G4X(dev)) {
intel_hdmi->write_infoframe = g4x_write_infoframe;
intel_hdmi->set_infoframes = g4x_set_infoframes;
} else if (HAS_DDI(dev)) {
@@ -1490,7 +1585,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
intel_hdmi_add_properties(intel_hdmi, connector);
intel_connector_attach_encoder(intel_connector, intel_encoder);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
* 0xd. Failure to do so will result in spurious interrupts being
@@ -1528,6 +1623,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
intel_encoder->get_config = intel_hdmi_get_config;
if (IS_CHERRYVIEW(dev)) {
+ intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable;
intel_encoder->pre_enable = chv_hdmi_pre_enable;
intel_encoder->enable = vlv_enable_hdmi;
intel_encoder->post_disable = chv_hdmi_post_disable;
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index d33b61d0dd33..b31088a551f2 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -34,11 +34,6 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
-enum disp_clk {
- CDCLK,
- CZCLK
-};
-
struct gmbus_port {
const char *name;
int reg;
@@ -63,60 +58,11 @@ to_intel_gmbus(struct i2c_adapter *i2c)
return container_of(i2c, struct intel_gmbus, adapter);
}
-static int get_disp_clk_div(struct drm_i915_private *dev_priv,
- enum disp_clk clk)
-{
- u32 reg_val;
- int clk_ratio;
-
- reg_val = I915_READ(CZCLK_CDCLK_FREQ_RATIO);
-
- if (clk == CDCLK)
- clk_ratio =
- ((reg_val & CDCLK_FREQ_MASK) >> CDCLK_FREQ_SHIFT) + 1;
- else
- clk_ratio = (reg_val & CZCLK_FREQ_MASK) + 1;
-
- return clk_ratio;
-}
-
-static void gmbus_set_freq(struct drm_i915_private *dev_priv)
-{
- int vco, gmbus_freq = 0, cdclk_div;
-
- BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
-
- vco = valleyview_get_vco(dev_priv);
-
- /* Get the CDCLK divide ratio */
- cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
-
- /*
- * Program the gmbus_freq based on the cdclk frequency.
- * BSpec erroneously claims we should aim for 4MHz, but
- * in fact 1MHz is the correct frequency.
- */
- if (cdclk_div)
- gmbus_freq = (vco << 1) / cdclk_div;
-
- if (WARN_ON(gmbus_freq == 0))
- return;
-
- I915_WRITE(GMBUSFREQ_VLV, gmbus_freq);
-}
-
void
intel_i2c_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- /*
- * In BIOS-less system, program the correct gmbus frequency
- * before reading edid.
- */
- if (IS_VALLEYVIEW(dev))
- gmbus_set_freq(dev_priv);
-
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);
}
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 5e5a72fca5fb..881361c0f27e 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -51,6 +51,7 @@ struct intel_lvds_encoder {
bool is_dual_link;
u32 reg;
+ u32 a3_power;
struct intel_lvds_connector *attached_connector;
};
@@ -71,8 +72,13 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ enum intel_display_power_domain power_domain;
u32 tmp;
+ power_domain = intel_display_port_power_domain(encoder);
+ if (!intel_display_power_enabled(dev_priv, power_domain))
+ return false;
+
tmp = I915_READ(lvds_encoder->reg);
if (!(tmp & LVDS_PORT_EN))
@@ -172,8 +178,11 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
* appropriately here, but we need to look more thoroughly into how
- * panels behave in the two modes.
+ * panels behave in the two modes. For now, let's just maintain the
+ * value we got from the BIOS.
*/
+ temp &= ~LVDS_A3_POWER_MASK;
+ temp |= lvds_encoder->a3_power;
/* Set the dithering flag on LVDS as needed, note that there is no
* special lvds dither control bit on pch-split platforms, dithering is
@@ -271,7 +280,6 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_device *dev = intel_encoder->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds_encoder *lvds_encoder =
to_lvds_encoder(&intel_encoder->base);
struct intel_connector *intel_connector =
@@ -286,8 +294,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
return false;
}
- if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) ==
- LVDS_A3_POWER_UP)
+ if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
lvds_bpp = 8*3;
else
lvds_bpp = 6*3;
@@ -1088,6 +1095,9 @@ out:
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
+ lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
+ LVDS_A3_POWER_MASK;
+
/*
* Unlock registers and just
* leave them unlocked
@@ -1104,7 +1114,7 @@ out:
DRM_DEBUG_KMS("lid notifier registration failed\n");
lvds_connector->lid_notifier.notifier_call = NULL;
}
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 4f6b53998d79..ca52ad2ae7d1 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -352,6 +352,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
case INTEL_OUTPUT_UNKNOWN:
case INTEL_OUTPUT_DISPLAYPORT:
case INTEL_OUTPUT_HDMI:
+ case INTEL_OUTPUT_DP_MST:
type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
break;
case INTEL_OUTPUT_EDP:
@@ -427,7 +428,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
*/
DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
- intel_panel_set_backlight(intel_connector, bclp, 255);
+ intel_panel_set_backlight_acpi(intel_connector, bclp, 255);
iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index daa118978eec..dc2f4f26c961 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -415,6 +415,10 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
}
intel_overlay_release_old_vid_tail(overlay);
+
+
+ i915_gem_track_fb(overlay->old_vid_bo, NULL,
+ INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
return 0;
}
@@ -686,6 +690,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
bool scale_changed = false;
struct drm_device *dev = overlay->dev;
u32 swidth, swidthsw, sheight, ostride;
+ enum pipe pipe = overlay->crtc->pipe;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
@@ -713,7 +718,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
oconfig = OCONF_CC_OUT_8BIT;
if (IS_GEN4(overlay->dev))
oconfig |= OCONF_CSC_MODE_BT709;
- oconfig |= overlay->crtc->pipe == 0 ?
+ oconfig |= pipe == 0 ?
OCONF_PIPE_A : OCONF_PIPE_B;
iowrite32(oconfig, &regs->OCONFIG);
intel_overlay_unmap_regs(overlay, regs);
@@ -776,9 +781,15 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret)
goto out_unpin;
+ i915_gem_track_fb(overlay->vid_bo, new_bo,
+ INTEL_FRONTBUFFER_OVERLAY(pipe));
+
overlay->old_vid_bo = overlay->vid_bo;
overlay->vid_bo = new_bo;
+ intel_frontbuffer_flip(dev,
+ INTEL_FRONTBUFFER_OVERLAY(pipe));
+
return 0;
out_unpin:
@@ -1028,7 +1039,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
struct drm_intel_overlay_put_image *put_image_rec = data;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_overlay *overlay;
- struct drm_mode_object *drmmode_obj;
+ struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc;
struct drm_i915_gem_object *new_bo;
struct put_image_params *params;
@@ -1057,13 +1068,12 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
if (!params)
return -ENOMEM;
- drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!drmmode_obj) {
+ drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
+ if (!drmmode_crtc) {
ret = -ENOENT;
goto out_free;
}
- crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+ crtc = to_intel_crtc(drmmode_crtc);
new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
put_image_rec->bo_handle));
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 12b02fe1d0ae..59b028f0b1e8 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -398,6 +398,69 @@ intel_panel_detect(struct drm_device *dev)
}
}
+/**
+ * scale - scale values from one range to another
+ *
+ * @source_val: value in range [@source_min..@source_max]
+ *
+ * Return @source_val in range [@source_min..@source_max] scaled to range
+ * [@target_min..@target_max].
+ */
+static uint32_t scale(uint32_t source_val,
+ uint32_t source_min, uint32_t source_max,
+ uint32_t target_min, uint32_t target_max)
+{
+ uint64_t target_val;
+
+ WARN_ON(source_min > source_max);
+ WARN_ON(target_min > target_max);
+
+ /* defensive */
+ source_val = clamp(source_val, source_min, source_max);
+
+ /* avoid overflows */
+ target_val = (uint64_t)(source_val - source_min) *
+ (target_max - target_min);
+ do_div(target_val, source_max - source_min);
+ target_val += target_min;
+
+ return target_val;
+}
+
+/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
+static inline u32 scale_user_to_hw(struct intel_connector *connector,
+ u32 user_level, u32 user_max)
+{
+ struct intel_panel *panel = &connector->panel;
+
+ return scale(user_level, 0, user_max,
+ panel->backlight.min, panel->backlight.max);
+}
+
+/* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
+ * to [hw_min..hw_max]. */
+static inline u32 clamp_user_to_hw(struct intel_connector *connector,
+ u32 user_level, u32 user_max)
+{
+ struct intel_panel *panel = &connector->panel;
+ u32 hw_level;
+
+ hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
+ hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
+
+ return hw_level;
+}
+
+/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
+static inline u32 scale_hw_to_user(struct intel_connector *connector,
+ u32 hw_level, u32 user_max)
+{
+ struct intel_panel *panel = &connector->panel;
+
+ return scale(hw_level, panel->backlight.min, panel->backlight.max,
+ 0, user_max);
+}
+
static u32 intel_panel_compute_brightness(struct intel_connector *connector,
u32 val)
{
@@ -557,17 +620,16 @@ intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
dev_priv->display.set_backlight(connector, level);
}
-/* set backlight brightness to level in range [0..max] */
-void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
- u32 max)
+/* set backlight brightness to level in range [0..max], scaling wrt hw min */
+static void intel_panel_set_backlight(struct intel_connector *connector,
+ u32 user_level, u32 user_max)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_panel *panel = &connector->panel;
enum pipe pipe = intel_get_pipe_from_connector(connector);
- u32 freq;
+ u32 hw_level;
unsigned long flags;
- u64 n;
if (!panel->backlight.present || pipe == INVALID_PIPE)
return;
@@ -576,18 +638,46 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
WARN_ON(panel->backlight.max == 0);
- /* scale to hardware max, but be careful to not overflow */
- freq = panel->backlight.max;
- n = (u64)level * freq;
- do_div(n, max);
- level = n;
+ hw_level = scale_user_to_hw(connector, user_level, user_max);
+ panel->backlight.level = hw_level;
+
+ if (panel->backlight.enabled)
+ intel_panel_actually_set_backlight(connector, hw_level);
+
+ spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
+
+/* set backlight brightness to level in range [0..max], assuming hw min is
+ * respected.
+ */
+void intel_panel_set_backlight_acpi(struct intel_connector *connector,
+ u32 user_level, u32 user_max)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_panel *panel = &connector->panel;
+ enum pipe pipe = intel_get_pipe_from_connector(connector);
+ u32 hw_level;
+ unsigned long flags;
+
+ if (!panel->backlight.present || pipe == INVALID_PIPE)
+ return;
+
+ spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+
+ WARN_ON(panel->backlight.max == 0);
+
+ hw_level = clamp_user_to_hw(connector, user_level, user_max);
+ panel->backlight.level = hw_level;
- panel->backlight.level = level;
if (panel->backlight.device)
- panel->backlight.device->props.brightness = level;
+ panel->backlight.device->props.brightness =
+ scale_hw_to_user(connector,
+ panel->backlight.level,
+ panel->backlight.device->props.max_brightness);
if (panel->backlight.enabled)
- intel_panel_actually_set_backlight(connector, level);
+ intel_panel_actually_set_backlight(connector, hw_level);
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
}
@@ -860,7 +950,9 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
panel->backlight.level = panel->backlight.max;
if (panel->backlight.device)
panel->backlight.device->props.brightness =
- panel->backlight.level;
+ scale_hw_to_user(connector,
+ panel->backlight.level,
+ panel->backlight.device->props.max_brightness);
}
dev_priv->display.enable_backlight(connector);
@@ -889,11 +981,15 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
struct intel_connector *connector = bl_get_data(bd);
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 hw_level;
int ret;
intel_runtime_pm_get(dev_priv);
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
- ret = intel_panel_get_backlight(connector);
+
+ hw_level = intel_panel_get_backlight(connector);
+ ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
+
drm_modeset_unlock(&dev->mode_config.connection_mutex);
intel_runtime_pm_put(dev_priv);
@@ -913,12 +1009,19 @@ static int intel_backlight_device_register(struct intel_connector *connector)
if (WARN_ON(panel->backlight.device))
return -ENODEV;
- BUG_ON(panel->backlight.max == 0);
+ WARN_ON(panel->backlight.max == 0);
memset(&props, 0, sizeof(props));
props.type = BACKLIGHT_RAW;
- props.brightness = panel->backlight.level;
+
+ /*
+ * Note: Everything should work even if the backlight device max
+ * presented to the userspace is arbitrarily chosen.
+ */
props.max_brightness = panel->backlight.max;
+ props.brightness = scale_hw_to_user(connector,
+ panel->backlight.level,
+ props.max_brightness);
/*
* Note: using the same name independent of the connector prevents
@@ -964,6 +1067,19 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
* XXX: Query mode clock or hardware clock and program PWM modulation frequency
* appropriately when it's 0. Use VBT and/or sane defaults.
*/
+static u32 get_backlight_min_vbt(struct intel_connector *connector)
+{
+ struct drm_device *dev = connector->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_panel *panel = &connector->panel;
+
+ WARN_ON(panel->backlight.max == 0);
+
+ /* vbt value is a coefficient in range [0..255] */
+ return scale(dev_priv->vbt.backlight.min_brightness, 0, 255,
+ 0, panel->backlight.max);
+}
+
static int bdw_setup_backlight(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
@@ -979,6 +1095,8 @@ static int bdw_setup_backlight(struct intel_connector *connector)
if (!panel->backlight.max)
return -ENODEV;
+ panel->backlight.min = get_backlight_min_vbt(connector);
+
val = bdw_get_backlight(connector);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
@@ -1003,6 +1121,8 @@ static int pch_setup_backlight(struct intel_connector *connector)
if (!panel->backlight.max)
return -ENODEV;
+ panel->backlight.min = get_backlight_min_vbt(connector);
+
val = pch_get_backlight(connector);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
@@ -1035,6 +1155,8 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
if (!panel->backlight.max)
return -ENODEV;
+ panel->backlight.min = get_backlight_min_vbt(connector);
+
val = i9xx_get_backlight(connector);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
@@ -1062,6 +1184,8 @@ static int i965_setup_backlight(struct intel_connector *connector)
if (!panel->backlight.max)
return -ENODEV;
+ panel->backlight.min = get_backlight_min_vbt(connector);
+
val = i9xx_get_backlight(connector);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
@@ -1099,6 +1223,8 @@ static int vlv_setup_backlight(struct intel_connector *connector)
if (!panel->backlight.max)
return -ENODEV;
+ panel->backlight.min = get_backlight_min_vbt(connector);
+
val = _vlv_get_backlight(dev, PIPE_A);
panel->backlight.level = intel_panel_compute_brightness(connector, val);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ee72807069e4..40c12295c0bd 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -93,8 +93,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = crtc->primary->fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int cfb_pitch;
int i;
@@ -150,8 +149,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = crtc->primary->fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
u32 dpfc_ctl;
@@ -222,16 +220,26 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = crtc->primary->fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
u32 dpfc_ctl;
dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane);
if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+ dev_priv->fbc.threshold++;
+
+ switch (dev_priv->fbc.threshold) {
+ case 4:
+ case 3:
+ dpfc_ctl |= DPFC_CTL_LIMIT_4X;
+ break;
+ case 2:
dpfc_ctl |= DPFC_CTL_LIMIT_2X;
- else
+ break;
+ case 1:
dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+ break;
+ }
dpfc_ctl |= DPFC_CTL_FENCE_EN;
if (IS_GEN5(dev))
dpfc_ctl |= obj->fence_reg;
@@ -278,16 +286,27 @@ static void gen7_enable_fbc(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = crtc->primary->fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
u32 dpfc_ctl;
dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane);
if (drm_format_plane_cpp(fb->pixel_format, 0) == 2)
+ dev_priv->fbc.threshold++;
+
+ switch (dev_priv->fbc.threshold) {
+ case 4:
+ case 3:
+ dpfc_ctl |= DPFC_CTL_LIMIT_4X;
+ break;
+ case 2:
dpfc_ctl |= DPFC_CTL_LIMIT_2X;
- else
+ break;
+ case 1:
dpfc_ctl |= DPFC_CTL_LIMIT_1X;
+ break;
+ }
+
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
@@ -462,7 +481,6 @@ void intel_update_fbc(struct drm_device *dev)
struct drm_crtc *crtc = NULL, *tmp_crtc;
struct intel_crtc *intel_crtc;
struct drm_framebuffer *fb;
- struct intel_framebuffer *intel_fb;
struct drm_i915_gem_object *obj;
const struct drm_display_mode *adjusted_mode;
unsigned int max_width, max_height;
@@ -507,8 +525,7 @@ void intel_update_fbc(struct drm_device *dev)
intel_crtc = to_intel_crtc(crtc);
fb = crtc->primary->fb;
- intel_fb = to_intel_framebuffer(fb);
- obj = intel_fb->obj;
+ obj = intel_fb_obj(fb);
adjusted_mode = &intel_crtc->config.adjusted_mode;
if (i915.enable_fbc < 0) {
@@ -529,7 +546,10 @@ void intel_update_fbc(struct drm_device *dev)
goto out_disable;
}
- if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+ if (INTEL_INFO(dev)->gen >= 8 || IS_HASWELL(dev)) {
+ max_width = 4096;
+ max_height = 4096;
+ } else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
max_width = 4096;
max_height = 2048;
} else {
@@ -563,7 +583,8 @@ void intel_update_fbc(struct drm_device *dev)
if (in_dbg_master())
goto out_disable;
- if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) {
+ if (i915_gem_stolen_setup_compression(dev, obj->base.size,
+ drm_format_plane_cpp(fb->pixel_format, 0))) {
if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL))
DRM_DEBUG_KMS("framebuffer too large, disabling compression\n");
goto out_disable;
@@ -789,12 +810,33 @@ static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
return NULL;
}
-static void pineview_disable_cxsr(struct drm_device *dev)
+void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_device *dev = dev_priv->dev;
+ u32 val;
+
+ if (IS_VALLEYVIEW(dev)) {
+ I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
+ } else if (IS_G4X(dev) || IS_CRESTLINE(dev)) {
+ I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0);
+ } else if (IS_PINEVIEW(dev)) {
+ val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN;
+ val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0;
+ I915_WRITE(DSPFW3, val);
+ } else if (IS_I945G(dev) || IS_I945GM(dev)) {
+ val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
+ _MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
+ I915_WRITE(FW_BLC_SELF, val);
+ } else if (IS_I915GM(dev)) {
+ val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) :
+ _MASKED_BIT_DISABLE(INSTPM_SELF_EN);
+ I915_WRITE(INSTPM, val);
+ } else {
+ return;
+ }
- /* deactivate cxsr */
- I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN);
+ DRM_DEBUG_KMS("memory self-refresh is %s\n",
+ enable ? "enabled" : "disabled");
}
/*
@@ -864,95 +906,95 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane)
/* Pineview has different values for various configs */
static const struct intel_watermark_params pineview_display_wm = {
- PINEVIEW_DISPLAY_FIFO,
- PINEVIEW_MAX_WM,
- PINEVIEW_DFT_WM,
- PINEVIEW_GUARD_WM,
- PINEVIEW_FIFO_LINE_SIZE
+ .fifo_size = PINEVIEW_DISPLAY_FIFO,
+ .max_wm = PINEVIEW_MAX_WM,
+ .default_wm = PINEVIEW_DFT_WM,
+ .guard_size = PINEVIEW_GUARD_WM,
+ .cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params pineview_display_hplloff_wm = {
- PINEVIEW_DISPLAY_FIFO,
- PINEVIEW_MAX_WM,
- PINEVIEW_DFT_HPLLOFF_WM,
- PINEVIEW_GUARD_WM,
- PINEVIEW_FIFO_LINE_SIZE
+ .fifo_size = PINEVIEW_DISPLAY_FIFO,
+ .max_wm = PINEVIEW_MAX_WM,
+ .default_wm = PINEVIEW_DFT_HPLLOFF_WM,
+ .guard_size = PINEVIEW_GUARD_WM,
+ .cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params pineview_cursor_wm = {
- PINEVIEW_CURSOR_FIFO,
- PINEVIEW_CURSOR_MAX_WM,
- PINEVIEW_CURSOR_DFT_WM,
- PINEVIEW_CURSOR_GUARD_WM,
- PINEVIEW_FIFO_LINE_SIZE,
+ .fifo_size = PINEVIEW_CURSOR_FIFO,
+ .max_wm = PINEVIEW_CURSOR_MAX_WM,
+ .default_wm = PINEVIEW_CURSOR_DFT_WM,
+ .guard_size = PINEVIEW_CURSOR_GUARD_WM,
+ .cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
- PINEVIEW_CURSOR_FIFO,
- PINEVIEW_CURSOR_MAX_WM,
- PINEVIEW_CURSOR_DFT_WM,
- PINEVIEW_CURSOR_GUARD_WM,
- PINEVIEW_FIFO_LINE_SIZE
+ .fifo_size = PINEVIEW_CURSOR_FIFO,
+ .max_wm = PINEVIEW_CURSOR_MAX_WM,
+ .default_wm = PINEVIEW_CURSOR_DFT_WM,
+ .guard_size = PINEVIEW_CURSOR_GUARD_WM,
+ .cacheline_size = PINEVIEW_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params g4x_wm_info = {
- G4X_FIFO_SIZE,
- G4X_MAX_WM,
- G4X_MAX_WM,
- 2,
- G4X_FIFO_LINE_SIZE,
+ .fifo_size = G4X_FIFO_SIZE,
+ .max_wm = G4X_MAX_WM,
+ .default_wm = G4X_MAX_WM,
+ .guard_size = 2,
+ .cacheline_size = G4X_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params g4x_cursor_wm_info = {
- I965_CURSOR_FIFO,
- I965_CURSOR_MAX_WM,
- I965_CURSOR_DFT_WM,
- 2,
- G4X_FIFO_LINE_SIZE,
+ .fifo_size = I965_CURSOR_FIFO,
+ .max_wm = I965_CURSOR_MAX_WM,
+ .default_wm = I965_CURSOR_DFT_WM,
+ .guard_size = 2,
+ .cacheline_size = G4X_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params valleyview_wm_info = {
- VALLEYVIEW_FIFO_SIZE,
- VALLEYVIEW_MAX_WM,
- VALLEYVIEW_MAX_WM,
- 2,
- G4X_FIFO_LINE_SIZE,
+ .fifo_size = VALLEYVIEW_FIFO_SIZE,
+ .max_wm = VALLEYVIEW_MAX_WM,
+ .default_wm = VALLEYVIEW_MAX_WM,
+ .guard_size = 2,
+ .cacheline_size = G4X_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params valleyview_cursor_wm_info = {
- I965_CURSOR_FIFO,
- VALLEYVIEW_CURSOR_MAX_WM,
- I965_CURSOR_DFT_WM,
- 2,
- G4X_FIFO_LINE_SIZE,
+ .fifo_size = I965_CURSOR_FIFO,
+ .max_wm = VALLEYVIEW_CURSOR_MAX_WM,
+ .default_wm = I965_CURSOR_DFT_WM,
+ .guard_size = 2,
+ .cacheline_size = G4X_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params i965_cursor_wm_info = {
- I965_CURSOR_FIFO,
- I965_CURSOR_MAX_WM,
- I965_CURSOR_DFT_WM,
- 2,
- I915_FIFO_LINE_SIZE,
+ .fifo_size = I965_CURSOR_FIFO,
+ .max_wm = I965_CURSOR_MAX_WM,
+ .default_wm = I965_CURSOR_DFT_WM,
+ .guard_size = 2,
+ .cacheline_size = I915_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params i945_wm_info = {
- I945_FIFO_SIZE,
- I915_MAX_WM,
- 1,
- 2,
- I915_FIFO_LINE_SIZE
+ .fifo_size = I945_FIFO_SIZE,
+ .max_wm = I915_MAX_WM,
+ .default_wm = 1,
+ .guard_size = 2,
+ .cacheline_size = I915_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params i915_wm_info = {
- I915_FIFO_SIZE,
- I915_MAX_WM,
- 1,
- 2,
- I915_FIFO_LINE_SIZE
+ .fifo_size = I915_FIFO_SIZE,
+ .max_wm = I915_MAX_WM,
+ .default_wm = 1,
+ .guard_size = 2,
+ .cacheline_size = I915_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params i830_wm_info = {
- I855GM_FIFO_SIZE,
- I915_MAX_WM,
- 1,
- 2,
- I830_FIFO_LINE_SIZE
+ .fifo_size = I855GM_FIFO_SIZE,
+ .max_wm = I915_MAX_WM,
+ .default_wm = 1,
+ .guard_size = 2,
+ .cacheline_size = I830_FIFO_LINE_SIZE,
};
static const struct intel_watermark_params i845_wm_info = {
- I830_FIFO_SIZE,
- I915_MAX_WM,
- 1,
- 2,
- I830_FIFO_LINE_SIZE
+ .fifo_size = I830_FIFO_SIZE,
+ .max_wm = I915_MAX_WM,
+ .default_wm = 1,
+ .guard_size = 2,
+ .cacheline_size = I830_FIFO_LINE_SIZE,
};
/**
@@ -1033,7 +1075,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
dev_priv->fsb_freq, dev_priv->mem_freq);
if (!latency) {
DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
- pineview_disable_cxsr(dev);
+ intel_set_memory_cxsr(dev_priv, false);
return;
}
@@ -1084,13 +1126,9 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
I915_WRITE(DSPFW3, reg);
DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
- /* activate cxsr */
- I915_WRITE(DSPFW3,
- I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN);
- DRM_DEBUG_KMS("Self-refresh is enabled\n");
+ intel_set_memory_cxsr(dev_priv, true);
} else {
- pineview_disable_cxsr(dev);
- DRM_DEBUG_KMS("Self-refresh is disabled\n");
+ intel_set_memory_cxsr(dev_priv, false);
}
}
@@ -1249,15 +1287,14 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
pixel_size = crtc->primary->fb->bits_per_pixel / 8; /* BPP */
entries = (clock / 1000) * pixel_size;
- *plane_prec_mult = (entries > 256) ?
- DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
- *plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) *
- pixel_size);
+ *plane_prec_mult = (entries > 128) ?
+ DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
+ *plane_dl = (64 * (*plane_prec_mult) * 4) / entries;
entries = (clock / 1000) * 4; /* BPP is always 4 for cursor */
- *cursor_prec_mult = (entries > 256) ?
- DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
- *cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4);
+ *cursor_prec_mult = (entries > 128) ?
+ DRAIN_LATENCY_PRECISION_64 : DRAIN_LATENCY_PRECISION_32;
+ *cursor_dl = (64 * (*cursor_prec_mult) * 4) / entries;
return true;
}
@@ -1282,9 +1319,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl,
&cursor_prec_mult, &cursora_dl)) {
cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
- DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16;
+ DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_64;
planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
- DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16;
+ DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_64;
I915_WRITE(VLV_DDL1, cursora_prec |
(cursora_dl << DDL_CURSORA_SHIFT) |
@@ -1295,9 +1332,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl,
&cursor_prec_mult, &cursorb_dl)) {
cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
- DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16;
+ DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_64;
planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
- DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16;
+ DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_64;
I915_WRITE(VLV_DDL2, cursorb_prec |
(cursorb_dl << DDL_CURSORB_SHIFT) |
@@ -1316,6 +1353,7 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
int plane_sr, cursor_sr;
int ignore_plane_sr, ignore_cursor_sr;
unsigned int enabled = 0;
+ bool cxsr_enabled;
vlv_update_drain_latency(dev);
@@ -1342,10 +1380,10 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
&valleyview_wm_info,
&valleyview_cursor_wm_info,
&ignore_plane_sr, &cursor_sr)) {
- I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN);
+ cxsr_enabled = true;
} else {
- I915_WRITE(FW_BLC_SELF_VLV,
- I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN);
+ cxsr_enabled = false;
+ intel_set_memory_cxsr(dev_priv, false);
plane_sr = cursor_sr = 0;
}
@@ -1365,6 +1403,9 @@ static void valleyview_update_wm(struct drm_crtc *crtc)
I915_WRITE(DSPFW3,
(I915_READ(DSPFW3) & ~DSPFW_CURSOR_SR_MASK) |
(cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+ if (cxsr_enabled)
+ intel_set_memory_cxsr(dev_priv, true);
}
static void g4x_update_wm(struct drm_crtc *crtc)
@@ -1375,6 +1416,7 @@ static void g4x_update_wm(struct drm_crtc *crtc)
int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
int plane_sr, cursor_sr;
unsigned int enabled = 0;
+ bool cxsr_enabled;
if (g4x_compute_wm0(dev, PIPE_A,
&g4x_wm_info, latency_ns,
@@ -1394,10 +1436,10 @@ static void g4x_update_wm(struct drm_crtc *crtc)
&g4x_wm_info,
&g4x_cursor_wm_info,
&plane_sr, &cursor_sr)) {
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+ cxsr_enabled = true;
} else {
- I915_WRITE(FW_BLC_SELF,
- I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
+ cxsr_enabled = false;
+ intel_set_memory_cxsr(dev_priv, false);
plane_sr = cursor_sr = 0;
}
@@ -1418,6 +1460,9 @@ static void g4x_update_wm(struct drm_crtc *crtc)
I915_WRITE(DSPFW3,
(I915_READ(DSPFW3) & ~(DSPFW_HPLL_SR_EN | DSPFW_CURSOR_SR_MASK)) |
(cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+ if (cxsr_enabled)
+ intel_set_memory_cxsr(dev_priv, true);
}
static void i965_update_wm(struct drm_crtc *unused_crtc)
@@ -1427,6 +1472,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
struct drm_crtc *crtc;
int srwm = 1;
int cursor_sr = 16;
+ bool cxsr_enabled;
/* Calc sr entries for one plane configs */
crtc = single_enabled_crtc(dev);
@@ -1468,13 +1514,11 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
"cursor %d\n", srwm, cursor_sr);
- if (IS_CRESTLINE(dev))
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+ cxsr_enabled = true;
} else {
+ cxsr_enabled = false;
/* Turn off self refresh if both pipes are enabled */
- if (IS_CRESTLINE(dev))
- I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
- & ~FW_BLC_SELF_EN);
+ intel_set_memory_cxsr(dev_priv, false);
}
DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
@@ -1486,6 +1530,9 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
/* update cursor SR watermark */
I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+
+ if (cxsr_enabled)
+ intel_set_memory_cxsr(dev_priv, true);
}
static void i9xx_update_wm(struct drm_crtc *unused_crtc)
@@ -1545,12 +1592,12 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
if (IS_I915GM(dev) && enabled) {
- struct intel_framebuffer *fb;
+ struct drm_i915_gem_object *obj;
- fb = to_intel_framebuffer(enabled->primary->fb);
+ obj = intel_fb_obj(enabled->primary->fb);
/* self-refresh seems busted with untiled */
- if (fb->obj->tiling_mode == I915_TILING_NONE)
+ if (obj->tiling_mode == I915_TILING_NONE)
enabled = NULL;
}
@@ -1560,10 +1607,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
cwm = 2;
/* Play safe and disable self-refresh before adjusting watermarks. */
- if (IS_I945G(dev) || IS_I945GM(dev))
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
- else if (IS_I915GM(dev))
- I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_SELF_EN));
+ intel_set_memory_cxsr(dev_priv, false);
/* Calc sr entries for one plane configs */
if (HAS_FW_BLC(dev) && enabled) {
@@ -1609,17 +1653,8 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
I915_WRITE(FW_BLC, fwater_lo);
I915_WRITE(FW_BLC2, fwater_hi);
- if (HAS_FW_BLC(dev)) {
- if (enabled) {
- if (IS_I945G(dev) || IS_I945GM(dev))
- I915_WRITE(FW_BLC_SELF,
- FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
- else if (IS_I915GM(dev))
- I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_SELF_EN));
- DRM_DEBUG_KMS("memory self refresh enabled\n");
- } else
- DRM_DEBUG_KMS("memory self refresh disabled\n");
- }
+ if (enabled)
+ intel_set_memory_cxsr(dev_priv, true);
}
static void i845_update_wm(struct drm_crtc *unused_crtc)
@@ -2707,10 +2742,11 @@ static void ilk_update_wm(struct drm_crtc *crtc)
ilk_write_wm_values(dev_priv, &results);
}
-static void ilk_update_sprite_wm(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width, int pixel_size,
- bool enabled, bool scaled)
+static void
+ilk_update_sprite_wm(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width, uint32_t sprite_height,
+ int pixel_size, bool enabled, bool scaled)
{
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -2718,6 +2754,7 @@ static void ilk_update_sprite_wm(struct drm_plane *plane,
intel_plane->wm.enabled = enabled;
intel_plane->wm.scaled = scaled;
intel_plane->wm.horiz_pixels = sprite_width;
+ intel_plane->wm.vert_pixels = sprite_width;
intel_plane->wm.bytes_per_pixel = pixel_size;
/*
@@ -2852,13 +2889,16 @@ void intel_update_watermarks(struct drm_crtc *crtc)
void intel_update_sprite_watermarks(struct drm_plane *plane,
struct drm_crtc *crtc,
- uint32_t sprite_width, int pixel_size,
+ uint32_t sprite_width,
+ uint32_t sprite_height,
+ int pixel_size,
bool enabled, bool scaled)
{
struct drm_i915_private *dev_priv = plane->dev->dev_private;
if (dev_priv->display.update_sprite_wm)
- dev_priv->display.update_sprite_wm(plane, crtc, sprite_width,
+ dev_priv->display.update_sprite_wm(plane, crtc,
+ sprite_width, sprite_height,
pixel_size, enabled, scaled);
}
@@ -2993,7 +3033,7 @@ static void ironlake_enable_drps(struct drm_device *dev)
I915_READ(0x112e0);
dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies);
dev_priv->ips.last_count2 = I915_READ(0x112f4);
- getrawmonotonic(&dev_priv->ips.last_time2);
+ dev_priv->ips.last_time2 = ktime_get_raw_ns();
spin_unlock_irq(&mchdev_lock);
}
@@ -3147,6 +3187,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)
if (val < dev_priv->rps.max_freq_softlimit)
mask |= GEN6_PM_RP_UP_THRESHOLD;
+ mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED);
+ mask &= dev_priv->pm_rps_events;
+
/* IVB and SNB hard hangs on looping batchbuffer
* if GEN6_PM_UP_EI_EXPIRED is masked.
*/
@@ -3250,7 +3293,9 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
mutex_lock(&dev_priv->rps.hw_lock);
if (dev_priv->rps.enabled) {
- if (IS_VALLEYVIEW(dev))
+ if (IS_CHERRYVIEW(dev))
+ valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
+ else if (IS_VALLEYVIEW(dev))
vlv_set_rps_idle(dev_priv);
else
gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
@@ -3348,6 +3393,15 @@ static void gen6_disable_rps(struct drm_device *dev)
gen6_disable_rps_interrupts(dev);
}
+static void cherryview_disable_rps(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ I915_WRITE(GEN6_RC_CONTROL, 0);
+
+ gen8_disable_rps_interrupts(dev);
+}
+
static void valleyview_disable_rps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3365,10 +3419,10 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
else
mode = 0;
}
- DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
- (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
- (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
- (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+ DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
+ (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
+ (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
+ (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
}
static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
@@ -3392,8 +3446,8 @@ static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
mask = INTEL_RC6_ENABLE;
if ((enable_rc6 & mask) != enable_rc6)
- DRM_INFO("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
- enable_rc6 & mask, enable_rc6, mask);
+ DRM_DEBUG_KMS("Adjusting RC6 mask to %d (requested %d, valid %d)\n",
+ enable_rc6 & mask, enable_rc6, mask);
return enable_rc6 & mask;
}
@@ -3419,7 +3473,7 @@ static void gen8_enable_rps_interrupts(struct drm_device *dev)
spin_lock_irq(&dev_priv->irq_lock);
WARN_ON(dev_priv->rps.pm_iir);
- bdw_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+ gen8_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
I915_WRITE(GEN8_GT_IIR(2), dev_priv->pm_rps_events);
spin_unlock_irq(&dev_priv->irq_lock);
}
@@ -3430,7 +3484,7 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev)
spin_lock_irq(&dev_priv->irq_lock);
WARN_ON(dev_priv->rps.pm_iir);
- snb_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+ gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
I915_WRITE(GEN6_PMIIR, dev_priv->pm_rps_events);
spin_unlock_irq(&dev_priv->irq_lock);
}
@@ -3483,15 +3537,23 @@ static void gen8_enable_rps(struct drm_device *dev)
for_each_ring(ring, dev_priv, unused)
I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
I915_WRITE(GEN6_RC_SLEEP, 0);
- I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+ if (IS_BROADWELL(dev))
+ I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
+ else
+ I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
/* 3: Enable RC6 */
if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
intel_print_rc6_info(dev, rc6_mask);
- I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
- GEN6_RC_CTL_EI_MODE(1) |
- rc6_mask);
+ if (IS_BROADWELL(dev))
+ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+ GEN7_RC_CTL_TO_MODE |
+ rc6_mask);
+ else
+ I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
+ GEN6_RC_CTL_EI_MODE(1) |
+ rc6_mask);
/* 4 Program defaults and thresholds for RPS*/
I915_WRITE(GEN6_RPNSWREQ,
@@ -3727,7 +3789,57 @@ void gen6_update_ring_freq(struct drm_device *dev)
mutex_unlock(&dev_priv->rps.hw_lock);
}
-int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
+static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv)
+{
+ u32 val, rp0;
+
+ val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
+ rp0 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+
+ return rp0;
+}
+
+static int cherryview_rps_rpe_freq(struct drm_i915_private *dev_priv)
+{
+ u32 val, rpe;
+
+ val = vlv_punit_read(dev_priv, PUNIT_GPU_DUTYCYCLE_REG);
+ rpe = (val >> PUNIT_GPU_DUTYCYCLE_RPE_FREQ_SHIFT) & PUNIT_GPU_DUTYCYCLE_RPE_FREQ_MASK;
+
+ return rpe;
+}
+
+static int cherryview_rps_guar_freq(struct drm_i915_private *dev_priv)
+{
+ u32 val, rp1;
+
+ val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+ rp1 = (val >> PUNIT_GPU_STATUS_MAX_FREQ_SHIFT) & PUNIT_GPU_STATUS_MAX_FREQ_MASK;
+
+ return rp1;
+}
+
+static int cherryview_rps_min_freq(struct drm_i915_private *dev_priv)
+{
+ u32 val, rpn;
+
+ val = vlv_punit_read(dev_priv, PUNIT_GPU_STATUS_REG);
+ rpn = (val >> PUNIT_GPU_STATIS_GFX_MIN_FREQ_SHIFT) & PUNIT_GPU_STATUS_GFX_MIN_FREQ_MASK;
+ return rpn;
+}
+
+static int valleyview_rps_guar_freq(struct drm_i915_private *dev_priv)
+{
+ u32 val, rp1;
+
+ val = vlv_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE);
+
+ rp1 = (val & FB_GFX_FGUARANTEED_FREQ_FUSE_MASK) >> FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT;
+
+ return rp1;
+}
+
+static int valleyview_rps_max_freq(struct drm_i915_private *dev_priv)
{
u32 val, rp0;
@@ -3752,7 +3864,7 @@ static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv)
return rpe;
}
-int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
+static int valleyview_rps_min_freq(struct drm_i915_private *dev_priv)
{
return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff;
}
@@ -3766,6 +3878,35 @@ static void valleyview_check_pctx(struct drm_i915_private *dev_priv)
dev_priv->vlv_pctx->stolen->start);
}
+
+/* Check that the pcbr address is not empty. */
+static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
+{
+ unsigned long pctx_addr = I915_READ(VLV_PCBR) & ~4095;
+
+ WARN_ON((pctx_addr >> VLV_PCBR_ADDR_SHIFT) == 0);
+}
+
+static void cherryview_setup_pctx(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long pctx_paddr, paddr;
+ struct i915_gtt *gtt = &dev_priv->gtt;
+ u32 pcbr;
+ int pctx_size = 32*1024;
+
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ pcbr = I915_READ(VLV_PCBR);
+ if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
+ paddr = (dev_priv->mm.stolen_base +
+ (gtt->stolen_size - pctx_size));
+
+ pctx_paddr = (paddr & (~4095));
+ I915_WRITE(VLV_PCBR, pctx_paddr);
+ }
+}
+
static void valleyview_setup_pctx(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3840,6 +3981,11 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
dev_priv->rps.efficient_freq);
+ dev_priv->rps.rp1_freq = valleyview_rps_guar_freq(dev_priv);
+ DRM_DEBUG_DRIVER("RP1(Guar Freq) GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq),
+ dev_priv->rps.rp1_freq);
+
dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv);
DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
@@ -3855,11 +4001,142 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
mutex_unlock(&dev_priv->rps.hw_lock);
}
+static void cherryview_init_gt_powersave(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ cherryview_setup_pctx(dev);
+
+ mutex_lock(&dev_priv->rps.hw_lock);
+
+ dev_priv->rps.max_freq = cherryview_rps_max_freq(dev_priv);
+ dev_priv->rps.rp0_freq = dev_priv->rps.max_freq;
+ DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.max_freq),
+ dev_priv->rps.max_freq);
+
+ dev_priv->rps.efficient_freq = cherryview_rps_rpe_freq(dev_priv);
+ DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+ dev_priv->rps.efficient_freq);
+
+ dev_priv->rps.rp1_freq = cherryview_rps_guar_freq(dev_priv);
+ DRM_DEBUG_DRIVER("RP1(Guar) GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.rp1_freq),
+ dev_priv->rps.rp1_freq);
+
+ dev_priv->rps.min_freq = cherryview_rps_min_freq(dev_priv);
+ DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.min_freq),
+ dev_priv->rps.min_freq);
+
+ /* Preserve min/max settings in case of re-init */
+ if (dev_priv->rps.max_freq_softlimit == 0)
+ dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
+
+ if (dev_priv->rps.min_freq_softlimit == 0)
+ dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq;
+
+ mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
{
valleyview_cleanup_pctx(dev);
}
+static void cherryview_enable_rps(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *ring;
+ u32 gtfifodbg, val, rc6_mode = 0, pcbr;
+ int i;
+
+ WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+ gtfifodbg = I915_READ(GTFIFODBG);
+ if (gtfifodbg) {
+ DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
+ gtfifodbg);
+ I915_WRITE(GTFIFODBG, gtfifodbg);
+ }
+
+ cherryview_check_pctx(dev_priv);
+
+ /* 1a & 1b: Get forcewake during program sequence. Although the driver
+ * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
+ gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
+ /* 2a: Program RC6 thresholds.*/
+ I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
+ I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
+ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
+
+ for_each_ring(ring, dev_priv, i)
+ I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+ I915_WRITE(GEN6_RC_SLEEP, 0);
+
+ I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */
+
+ /* allows RC6 residency counter to work */
+ I915_WRITE(VLV_COUNTER_CONTROL,
+ _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+ VLV_MEDIA_RC6_COUNT_EN |
+ VLV_RENDER_RC6_COUNT_EN));
+
+ /* For now we assume BIOS is allocating and populating the PCBR */
+ pcbr = I915_READ(VLV_PCBR);
+
+ DRM_DEBUG_DRIVER("PCBR offset : 0x%x\n", pcbr);
+
+ /* 3: Enable RC6 */
+ if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) &&
+ (pcbr >> VLV_PCBR_ADDR_SHIFT))
+ rc6_mode = GEN6_RC_CTL_EI_MODE(1);
+
+ I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
+
+ /* 4 Program defaults and thresholds for RPS*/
+ I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
+ I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
+ I915_WRITE(GEN6_RP_UP_EI, 66000);
+ I915_WRITE(GEN6_RP_DOWN_EI, 350000);
+
+ I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+
+ /* WaDisablePwrmtrEvent:chv (pre-production hw) */
+ I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff);
+ I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00);
+
+ /* 5: Enable RPS */
+ I915_WRITE(GEN6_RP_CONTROL,
+ GEN6_RP_MEDIA_HW_NORMAL_MODE |
+ GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */
+ GEN6_RP_ENABLE |
+ GEN6_RP_UP_BUSY_AVG |
+ GEN6_RP_DOWN_IDLE_AVG);
+
+ val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+
+ DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
+ DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
+
+ dev_priv->rps.cur_freq = (val >> 8) & 0xff;
+ DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.cur_freq),
+ dev_priv->rps.cur_freq);
+
+ DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
+ vlv_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
+ dev_priv->rps.efficient_freq);
+
+ valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
+
+ gen8_enable_rps_interrupts(dev);
+
+ gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+}
+
static void valleyview_enable_rps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3886,6 +4163,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RP_DOWN_EI, 350000);
I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+ I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 0xf4240);
I915_WRITE(GEN6_RP_CONTROL,
GEN6_RP_MEDIA_TURBO |
@@ -3906,9 +4184,11 @@ static void valleyview_enable_rps(struct drm_device *dev)
/* allows RC6 residency counter to work */
I915_WRITE(VLV_COUNTER_CONTROL,
- _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH |
+ _MASKED_BIT_ENABLE(VLV_MEDIA_RC0_COUNT_EN |
+ VLV_RENDER_RC0_COUNT_EN |
VLV_MEDIA_RC6_COUNT_EN |
VLV_RENDER_RC6_COUNT_EN));
+
if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
@@ -4314,18 +4594,16 @@ static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
{
- struct timespec now, diff1;
- u64 diff;
- unsigned long diffms;
+ u64 now, diff, diffms;
u32 count;
assert_spin_locked(&mchdev_lock);
- getrawmonotonic(&now);
- diff1 = timespec_sub(now, dev_priv->ips.last_time2);
+ now = ktime_get_raw_ns();
+ diffms = now - dev_priv->ips.last_time2;
+ do_div(diffms, NSEC_PER_MSEC);
/* Don't divide by 0 */
- diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
if (!diffms)
return;
@@ -4668,33 +4946,60 @@ void intel_init_gt_powersave(struct drm_device *dev)
{
i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
- if (IS_VALLEYVIEW(dev))
+ if (IS_CHERRYVIEW(dev))
+ cherryview_init_gt_powersave(dev);
+ else if (IS_VALLEYVIEW(dev))
valleyview_init_gt_powersave(dev);
}
void intel_cleanup_gt_powersave(struct drm_device *dev)
{
- if (IS_VALLEYVIEW(dev))
+ if (IS_CHERRYVIEW(dev))
+ return;
+ else if (IS_VALLEYVIEW(dev))
valleyview_cleanup_gt_powersave(dev);
}
+/**
+ * intel_suspend_gt_powersave - suspend PM work and helper threads
+ * @dev: drm device
+ *
+ * We don't want to disable RC6 or other features here, we just want
+ * to make sure any work we've queued has finished and won't bother
+ * us while we're suspended.
+ */
+void intel_suspend_gt_powersave(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Interrupts should be disabled already to avoid re-arming. */
+ WARN_ON(intel_irqs_enabled(dev_priv));
+
+ flush_delayed_work(&dev_priv->rps.delayed_resume_work);
+
+ cancel_work_sync(&dev_priv->rps.work);
+
+ /* Force GPU to min freq during suspend */
+ gen6_rps_idle(dev_priv);
+}
+
void intel_disable_gt_powersave(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
/* Interrupts should be disabled already to avoid re-arming. */
- WARN_ON(dev->irq_enabled);
+ WARN_ON(intel_irqs_enabled(dev_priv));
if (IS_IRONLAKE_M(dev)) {
ironlake_disable_drps(dev);
ironlake_disable_rc6(dev);
- } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
- if (cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work))
- intel_runtime_pm_put(dev_priv);
+ } else if (INTEL_INFO(dev)->gen >= 6) {
+ intel_suspend_gt_powersave(dev);
- cancel_work_sync(&dev_priv->rps.work);
mutex_lock(&dev_priv->rps.hw_lock);
- if (IS_VALLEYVIEW(dev))
+ if (IS_CHERRYVIEW(dev))
+ cherryview_disable_rps(dev);
+ else if (IS_VALLEYVIEW(dev))
valleyview_disable_rps(dev);
else
gen6_disable_rps(dev);
@@ -4712,7 +5017,9 @@ static void intel_gen6_powersave_work(struct work_struct *work)
mutex_lock(&dev_priv->rps.hw_lock);
- if (IS_VALLEYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev)) {
+ cherryview_enable_rps(dev);
+ } else if (IS_VALLEYVIEW(dev)) {
valleyview_enable_rps(dev);
} else if (IS_BROADWELL(dev)) {
gen8_enable_rps(dev);
@@ -4737,7 +5044,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
ironlake_enable_rc6(dev);
intel_init_emon(dev);
mutex_unlock(&dev->struct_mutex);
- } else if (IS_GEN6(dev) || IS_GEN7(dev) || IS_BROADWELL(dev)) {
+ } else if (INTEL_INFO(dev)->gen >= 6) {
/*
* PCU communication is slow and this doesn't need to be
* done at any specific time, so do this out of our fast path
@@ -4920,11 +5227,9 @@ static void gen6_check_mch_setup(struct drm_device *dev)
uint32_t tmp;
tmp = I915_READ(MCH_SSKPD);
- if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL) {
- DRM_INFO("Wrong MCH_SSKPD value: 0x%08x\n", tmp);
- DRM_INFO("This can cause pipe underruns and display issues.\n");
- DRM_INFO("Please upgrade your BIOS to fix this.\n");
- }
+ if ((tmp & MCH_SSKPD_WM0_MASK) != MCH_SSKPD_WM0_VAL)
+ DRM_DEBUG_KMS("Wrong MCH_SSKPD value: 0x%08x This can cause underruns.\n",
+ tmp);
}
static void gen6_init_clock_gating(struct drm_device *dev)
@@ -5110,7 +5415,7 @@ static void gen8_init_clock_gating(struct drm_device *dev)
I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE));
I915_WRITE(_3D_CHICKEN3,
- _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2));
+ _MASKED_BIT_ENABLE(_3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)));
I915_WRITE(COMMON_SLICE_CHICKEN2,
_MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE));
@@ -5345,10 +5650,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
}
DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
- dev_priv->vlv_cdclk_freq = valleyview_cur_cdclk(dev_priv);
- DRM_DEBUG_DRIVER("Current CD clock rate: %d MHz",
- dev_priv->vlv_cdclk_freq);
-
I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
/* WaDisableEarlyCull:vlv */
@@ -5423,6 +5724,35 @@ static void valleyview_init_clock_gating(struct drm_device *dev)
static void cherryview_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 val;
+
+ mutex_lock(&dev_priv->rps.hw_lock);
+ val = vlv_punit_read(dev_priv, CCK_FUSE_REG);
+ mutex_unlock(&dev_priv->rps.hw_lock);
+ switch ((val >> 2) & 0x7) {
+ case 0:
+ case 1:
+ dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_200;
+ dev_priv->mem_freq = 1600;
+ break;
+ case 2:
+ dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_267;
+ dev_priv->mem_freq = 1600;
+ break;
+ case 3:
+ dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_333;
+ dev_priv->mem_freq = 2000;
+ break;
+ case 4:
+ dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_320;
+ dev_priv->mem_freq = 1600;
+ break;
+ case 5:
+ dev_priv->rps.cz_freq = CHV_CZ_CLOCK_FREQ_MODE_400;
+ dev_priv->mem_freq = 1600;
+ break;
+ }
+ DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
@@ -5663,7 +5993,6 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
- unsigned long irqflags;
/*
* After we re-enable the power well, if we touch VGA register 0x3d5
@@ -5679,21 +6008,8 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
- if (IS_BROADWELL(dev)) {
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
- I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
- dev_priv->de_irq_mask[PIPE_B]);
- I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
- ~dev_priv->de_irq_mask[PIPE_B] |
- GEN8_PIPE_VBLANK);
- I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
- dev_priv->de_irq_mask[PIPE_C]);
- I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
- ~dev_priv->de_irq_mask[PIPE_C] |
- GEN8_PIPE_VBLANK);
- POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
- }
+ if (IS_BROADWELL(dev))
+ gen8_irq_power_well_post_enable(dev_priv);
}
static void hsw_set_power_well(struct drm_i915_private *dev_priv,
@@ -5764,34 +6080,13 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
return true;
}
-void __vlv_set_power_well(struct drm_i915_private *dev_priv,
- enum punit_power_well power_well_id, bool enable)
+static void vlv_set_power_well(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well, bool enable)
{
- struct drm_device *dev = dev_priv->dev;
+ enum punit_power_well power_well_id = power_well->data;
u32 mask;
u32 state;
u32 ctrl;
- enum pipe pipe;
-
- if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
- if (enable) {
- /*
- * Enable the CRI clock source so we can get at the
- * display and the reference clock for VGA
- * hotplug / manual detection.
- */
- I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
- DPLL_REFA_CLK_ENABLE_VLV |
- DPLL_INTEGRATED_CRI_CLK_VLV);
- udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
- } else {
- for_each_pipe(pipe)
- assert_pll_disabled(dev_priv, pipe);
- /* Assert common reset */
- I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) &
- ~DPIO_CMNRST);
- }
- }
mask = PUNIT_PWRGT_MASK(power_well_id);
state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
@@ -5819,28 +6114,6 @@ void __vlv_set_power_well(struct drm_i915_private *dev_priv,
out:
mutex_unlock(&dev_priv->rps.hw_lock);
-
- /*
- * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
- * 6. De-assert cmn_reset/side_reset. Same as VLV X0.
- * a. GUnit 0x2110 bit[0] set to 1 (def 0)
- * b. The other bits such as sfr settings / modesel may all
- * be set to 0.
- *
- * This should only be done on init and resume from S3 with
- * both PLLs disabled, or we risk losing DPIO and PLL
- * synchronization.
- */
- if (power_well_id == PUNIT_POWER_WELL_DPIO_CMN_BC && enable)
- I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
-}
-
-static void vlv_set_power_well(struct drm_i915_private *dev_priv,
- struct i915_power_well *power_well, bool enable)
-{
- enum punit_power_well power_well_id = power_well->data;
-
- __vlv_set_power_well(dev_priv, power_well_id, enable);
}
static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
@@ -5932,6 +6205,53 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
vlv_set_power_well(dev_priv, power_well, false);
}
+static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+
+ /*
+ * Enable the CRI clock source so we can get at the
+ * display and the reference clock for VGA
+ * hotplug / manual detection.
+ */
+ I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+ DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
+ udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
+
+ vlv_set_power_well(dev_priv, power_well, true);
+
+ /*
+ * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
+ * 6. De-assert cmn_reset/side_reset. Same as VLV X0.
+ * a. GUnit 0x2110 bit[0] set to 1 (def 0)
+ * b. The other bits such as sfr settings / modesel may all
+ * be set to 0.
+ *
+ * This should only be done on init and resume from S3 with
+ * both PLLs disabled, or we risk losing DPIO and PLL
+ * synchronization.
+ */
+ I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) | DPIO_CMNRST);
+}
+
+static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ struct drm_device *dev = dev_priv->dev;
+ enum pipe pipe;
+
+ WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+
+ for_each_pipe(pipe)
+ assert_pll_disabled(dev_priv, pipe);
+
+ /* Assert common reset */
+ I915_WRITE(DPIO_CTL, I915_READ(DPIO_CTL) & ~DPIO_CMNRST);
+
+ vlv_set_power_well(dev_priv, power_well, false);
+}
+
static void check_power_well_state(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
@@ -6081,6 +6401,7 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_PORT_CRT) | \
+ BIT(POWER_DOMAIN_PLLS) | \
BIT(POWER_DOMAIN_INIT))
#define HSW_DISPLAY_POWER_DOMAINS ( \
(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) | \
@@ -6180,6 +6501,13 @@ static const struct i915_power_well_ops vlv_display_power_well_ops = {
.is_enabled = vlv_power_well_enabled,
};
+static const struct i915_power_well_ops vlv_dpio_cmn_power_well_ops = {
+ .sync_hw = vlv_power_well_sync_hw,
+ .enable = vlv_dpio_cmn_power_well_enable,
+ .disable = vlv_dpio_cmn_power_well_disable,
+ .is_enabled = vlv_power_well_enabled,
+};
+
static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
.sync_hw = vlv_power_well_sync_hw,
.enable = vlv_power_well_enable,
@@ -6240,10 +6568,25 @@ static struct i915_power_well vlv_power_wells[] = {
.name = "dpio-common",
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
- .ops = &vlv_dpio_power_well_ops,
+ .ops = &vlv_dpio_cmn_power_well_ops,
},
};
+static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
+ enum punit_power_well power_well_id)
+{
+ struct i915_power_domains *power_domains = &dev_priv->power_domains;
+ struct i915_power_well *power_well;
+ int i;
+
+ for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+ if (power_well->data == power_well_id)
+ return power_well;
+ }
+
+ return NULL;
+}
+
#define set_power_wells(power_domains, __power_wells) ({ \
(power_domains)->power_wells = (__power_wells); \
(power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \
@@ -6294,11 +6637,50 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
mutex_unlock(&power_domains->lock);
}
+static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_well *cmn =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
+ struct i915_power_well *disp2d =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D);
+
+ /* nothing to do if common lane is already off */
+ if (!cmn->ops->is_enabled(dev_priv, cmn))
+ return;
+
+ /* If the display might be already active skip this */
+ if (disp2d->ops->is_enabled(dev_priv, disp2d) &&
+ I915_READ(DPIO_CTL) & DPIO_CMNRST)
+ return;
+
+ DRM_DEBUG_KMS("toggling display PHY side reset\n");
+
+ /* cmnlane needs DPLL registers */
+ disp2d->ops->enable(dev_priv, disp2d);
+
+ /*
+ * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:
+ * Need to assert and de-assert PHY SB reset by gating the
+ * common lane power, then un-gating it.
+ * Simply ungating isn't enough to reset the PHY enough to get
+ * ports and lanes running.
+ */
+ cmn->ops->disable(dev_priv, cmn);
+}
+
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
{
+ struct drm_device *dev = dev_priv->dev;
struct i915_power_domains *power_domains = &dev_priv->power_domains;
power_domains->initializing = true;
+
+ if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+ mutex_lock(&power_domains->lock);
+ vlv_cmnlane_wa(dev_priv);
+ mutex_unlock(&power_domains->lock);
+ }
+
/* For now, we need the power well to be always enabled. */
intel_display_set_init_power(dev_priv, true);
intel_power_domains_resume(dev_priv);
@@ -6471,7 +6853,7 @@ void intel_init_pm(struct drm_device *dev)
(dev_priv->is_ddr3 == 1) ? "3" : "2",
dev_priv->fsb_freq, dev_priv->mem_freq);
/* Disable CxSR and never update its watermark again */
- pineview_disable_cxsr(dev);
+ intel_set_memory_cxsr(dev_priv, false);
dev_priv->display.update_wm = NULL;
} else
dev_priv->display.update_wm = pineview_update_wm;
@@ -6554,7 +6936,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
return 0;
}
-int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
int div;
@@ -6576,7 +6958,7 @@ int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div);
}
-int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
int mul;
@@ -6598,6 +6980,80 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6;
}
+static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+{
+ int div, freq;
+
+ switch (dev_priv->rps.cz_freq) {
+ case 200:
+ div = 5;
+ break;
+ case 267:
+ div = 6;
+ break;
+ case 320:
+ case 333:
+ case 400:
+ div = 8;
+ break;
+ default:
+ return -1;
+ }
+
+ freq = (DIV_ROUND_CLOSEST((dev_priv->rps.cz_freq * val), 2 * div) / 2);
+
+ return freq;
+}
+
+static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+{
+ int mul, opcode;
+
+ switch (dev_priv->rps.cz_freq) {
+ case 200:
+ mul = 5;
+ break;
+ case 267:
+ mul = 6;
+ break;
+ case 320:
+ case 333:
+ case 400:
+ mul = 8;
+ break;
+ default:
+ return -1;
+ }
+
+ opcode = (DIV_ROUND_CLOSEST((val * 2 * mul), dev_priv->rps.cz_freq) * 2);
+
+ return opcode;
+}
+
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
+{
+ int ret = -1;
+
+ if (IS_CHERRYVIEW(dev_priv->dev))
+ ret = chv_gpu_freq(dev_priv, val);
+ else if (IS_VALLEYVIEW(dev_priv->dev))
+ ret = byt_gpu_freq(dev_priv, val);
+
+ return ret;
+}
+
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
+{
+ int ret = -1;
+
+ if (IS_CHERRYVIEW(dev_priv->dev))
+ ret = chv_freq_opcode(dev_priv, val);
+ else if (IS_VALLEYVIEW(dev_priv->dev))
+ ret = byt_freq_opcode(dev_priv, val);
+
+ return ret;
+}
+
void intel_pm_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6608,5 +7064,5 @@ void intel_pm_setup(struct drm_device *dev)
intel_gen6_powersave_work);
dev_priv->pm.suspended = false;
- dev_priv->pm.irqs_disabled = false;
+ dev_priv->pm._irqs_disabled = false;
}
diff --git a/drivers/gpu/drm/i915/intel_renderstate.h b/drivers/gpu/drm/i915/intel_renderstate.h
index a5e783a9928a..fd4f66231d30 100644
--- a/drivers/gpu/drm/i915/intel_renderstate.h
+++ b/drivers/gpu/drm/i915/intel_renderstate.h
@@ -28,7 +28,6 @@
struct intel_renderstate_rodata {
const u32 *reloc;
- const u32 reloc_items;
const u32 *batch;
const u32 batch_items;
};
@@ -40,7 +39,6 @@ extern const struct intel_renderstate_rodata gen8_null_state;
#define RO_RENDERSTATE(_g) \
const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
.reloc = gen ## _g ## _null_state_relocs, \
- .reloc_items = sizeof(gen ## _g ## _null_state_relocs)/4, \
.batch = gen ## _g ## _null_state_batch, \
.batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
}
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen6.c b/drivers/gpu/drm/i915/intel_renderstate_gen6.c
index 740538ad0977..56c1429d8a60 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen6.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen6.c
@@ -6,6 +6,7 @@ static const u32 gen6_null_state_relocs[] = {
0x0000002c,
0x000001e0,
0x000001e4,
+ -1,
};
static const u32 gen6_null_state_batch[] = {
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen7.c b/drivers/gpu/drm/i915/intel_renderstate_gen7.c
index 6fa7ff2a1298..419e35a7b0ff 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen7.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen7.c
@@ -5,6 +5,7 @@ static const u32 gen7_null_state_relocs[] = {
0x00000010,
0x00000018,
0x000001ec,
+ -1,
};
static const u32 gen7_null_state_batch[] = {
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen8.c b/drivers/gpu/drm/i915/intel_renderstate_gen8.c
index 5c875615d42a..75ef1b5de45c 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen8.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen8.c
@@ -5,6 +5,7 @@ static const u32 gen8_null_state_relocs[] = {
0x00000050,
0x00000060,
0x000003ec,
+ -1,
};
static const u32 gen8_null_state_batch[] = {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 279488addf3f..16371a444426 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -48,9 +48,8 @@ static inline int __ring_space(int head, int tail, int size)
return space;
}
-static inline int ring_space(struct intel_engine_cs *ring)
+static inline int ring_space(struct intel_ringbuffer *ringbuf)
{
- struct intel_ringbuffer *ringbuf = ring->buffer;
return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size);
}
@@ -381,6 +380,27 @@ gen7_render_ring_flush(struct intel_engine_cs *ring,
}
static int
+gen8_emit_pipe_control(struct intel_engine_cs *ring,
+ u32 flags, u32 scratch_addr)
+{
+ int ret;
+
+ ret = intel_ring_begin(ring, 6);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
+ intel_ring_emit(ring, flags);
+ intel_ring_emit(ring, scratch_addr);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+
+ return 0;
+}
+
+static int
gen8_render_ring_flush(struct intel_engine_cs *ring,
u32 invalidate_domains, u32 flush_domains)
{
@@ -403,22 +423,17 @@ gen8_render_ring_flush(struct intel_engine_cs *ring,
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_QW_WRITE;
flags |= PIPE_CONTROL_GLOBAL_GTT_IVB;
- }
-
- ret = intel_ring_begin(ring, 6);
- if (ret)
- return ret;
- intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
- intel_ring_emit(ring, flags);
- intel_ring_emit(ring, scratch_addr);
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, 0);
- intel_ring_advance(ring);
-
- return 0;
+ /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */
+ ret = gen8_emit_pipe_control(ring,
+ PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_STALL_AT_SCOREBOARD,
+ 0);
+ if (ret)
+ return ret;
+ }
+ return gen8_emit_pipe_control(ring, flags, scratch_addr);
}
static void ring_write_tail(struct intel_engine_cs *ring,
@@ -517,6 +532,9 @@ static int init_ring_common(struct intel_engine_cs *ring)
else
ring_setup_phys_status_page(ring);
+ /* Enforce ordering by reading HEAD register back */
+ I915_READ_HEAD(ring);
+
/* Initialize the ring. This must happen _after_ we've cleared the ring
* registers with the above sequence (the readback of the HEAD registers
* also enforces ordering), otherwise the hw might lose the new ring
@@ -545,7 +563,7 @@ static int init_ring_common(struct intel_engine_cs *ring)
else {
ringbuf->head = I915_READ_HEAD(ring);
ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
- ringbuf->space = ring_space(ring);
+ ringbuf->space = ring_space(ringbuf);
ringbuf->last_retired_head = -1;
}
@@ -604,6 +622,8 @@ static int init_render_ring(struct intel_engine_cs *ring)
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret = init_ring_common(ring);
+ if (ret)
+ return ret;
/* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */
if (INTEL_INFO(dev)->gen >= 4 && INTEL_INFO(dev)->gen < 7)
@@ -658,6 +678,13 @@ static int init_render_ring(struct intel_engine_cs *ring)
static void render_ring_cleanup(struct intel_engine_cs *ring)
{
struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (dev_priv->semaphore_obj) {
+ i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
+ drm_gem_object_unreference(&dev_priv->semaphore_obj->base);
+ dev_priv->semaphore_obj = NULL;
+ }
if (ring->scratch.obj == NULL)
return;
@@ -671,29 +698,96 @@ static void render_ring_cleanup(struct intel_engine_cs *ring)
ring->scratch.obj = NULL;
}
+static int gen8_rcs_signal(struct intel_engine_cs *signaller,
+ unsigned int num_dwords)
+{
+#define MBOX_UPDATE_DWORDS 8
+ struct drm_device *dev = signaller->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *waiter;
+ int i, ret, num_rings;
+
+ num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+ num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
+#undef MBOX_UPDATE_DWORDS
+
+ ret = intel_ring_begin(signaller, num_dwords);
+ if (ret)
+ return ret;
+
+ for_each_ring(waiter, dev_priv, i) {
+ u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+ if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
+ continue;
+
+ intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6));
+ intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB |
+ PIPE_CONTROL_QW_WRITE |
+ PIPE_CONTROL_FLUSH_ENABLE);
+ intel_ring_emit(signaller, lower_32_bits(gtt_offset));
+ intel_ring_emit(signaller, upper_32_bits(gtt_offset));
+ intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
+ intel_ring_emit(signaller, 0);
+ intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
+ MI_SEMAPHORE_TARGET(waiter->id));
+ intel_ring_emit(signaller, 0);
+ }
+
+ return 0;
+}
+
+static int gen8_xcs_signal(struct intel_engine_cs *signaller,
+ unsigned int num_dwords)
+{
+#define MBOX_UPDATE_DWORDS 6
+ struct drm_device *dev = signaller->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_engine_cs *waiter;
+ int i, ret, num_rings;
+
+ num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+ num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
+#undef MBOX_UPDATE_DWORDS
+
+ ret = intel_ring_begin(signaller, num_dwords);
+ if (ret)
+ return ret;
+
+ for_each_ring(waiter, dev_priv, i) {
+ u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+ if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
+ continue;
+
+ intel_ring_emit(signaller, (MI_FLUSH_DW + 1) |
+ MI_FLUSH_DW_OP_STOREDW);
+ intel_ring_emit(signaller, lower_32_bits(gtt_offset) |
+ MI_FLUSH_DW_USE_GTT);
+ intel_ring_emit(signaller, upper_32_bits(gtt_offset));
+ intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
+ intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
+ MI_SEMAPHORE_TARGET(waiter->id));
+ intel_ring_emit(signaller, 0);
+ }
+
+ return 0;
+}
+
static int gen6_signal(struct intel_engine_cs *signaller,
unsigned int num_dwords)
{
struct drm_device *dev = signaller->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *useless;
- int i, ret;
+ int i, ret, num_rings;
- /* NB: In order to be able to do semaphore MBOX updates for varying
- * number of rings, it's easiest if we round up each individual update
- * to a multiple of 2 (since ring updates must always be a multiple of
- * 2) even though the actual update only requires 3 dwords.
- */
-#define MBOX_UPDATE_DWORDS 4
- if (i915_semaphore_is_enabled(dev))
- num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
- else
- return intel_ring_begin(signaller, num_dwords);
+#define MBOX_UPDATE_DWORDS 3
+ num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+ num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
+#undef MBOX_UPDATE_DWORDS
ret = intel_ring_begin(signaller, num_dwords);
if (ret)
return ret;
-#undef MBOX_UPDATE_DWORDS
for_each_ring(useless, dev_priv, i) {
u32 mbox_reg = signaller->semaphore.mbox.signal[i];
@@ -701,15 +795,13 @@ static int gen6_signal(struct intel_engine_cs *signaller,
intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(signaller, mbox_reg);
intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
- intel_ring_emit(signaller, MI_NOOP);
- } else {
- intel_ring_emit(signaller, MI_NOOP);
- intel_ring_emit(signaller, MI_NOOP);
- intel_ring_emit(signaller, MI_NOOP);
- intel_ring_emit(signaller, MI_NOOP);
}
}
+ /* If num_dwords was rounded, make sure the tail pointer is correct */
+ if (num_rings % 2 == 0)
+ intel_ring_emit(signaller, MI_NOOP);
+
return 0;
}
@@ -727,7 +819,11 @@ gen6_add_request(struct intel_engine_cs *ring)
{
int ret;
- ret = ring->semaphore.signal(ring, 4);
+ if (ring->semaphore.signal)
+ ret = ring->semaphore.signal(ring, 4);
+ else
+ ret = intel_ring_begin(ring, 4);
+
if (ret)
return ret;
@@ -754,6 +850,32 @@ static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev,
* @signaller - ring which has, or will signal
* @seqno - seqno which the waiter will block on
*/
+
+static int
+gen8_ring_sync(struct intel_engine_cs *waiter,
+ struct intel_engine_cs *signaller,
+ u32 seqno)
+{
+ struct drm_i915_private *dev_priv = waiter->dev->dev_private;
+ int ret;
+
+ ret = intel_ring_begin(waiter, 4);
+ if (ret)
+ return ret;
+
+ intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
+ MI_SEMAPHORE_GLOBAL_GTT |
+ MI_SEMAPHORE_POLL |
+ MI_SEMAPHORE_SAD_GTE_SDD);
+ intel_ring_emit(waiter, seqno);
+ intel_ring_emit(waiter,
+ lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+ intel_ring_emit(waiter,
+ upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+ intel_ring_advance(waiter);
+ return 0;
+}
+
static int
gen6_ring_sync(struct intel_engine_cs *waiter,
struct intel_engine_cs *signaller,
@@ -901,7 +1023,7 @@ gen5_ring_get_irq(struct intel_engine_cs *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0)
- ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+ gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return true;
@@ -916,7 +1038,7 @@ gen5_ring_put_irq(struct intel_engine_cs *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0)
- ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+ gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
@@ -1109,7 +1231,7 @@ gen6_ring_get_irq(struct intel_engine_cs *ring)
GT_PARITY_ERROR(dev)));
else
I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
- ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+ gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
@@ -1129,7 +1251,7 @@ gen6_ring_put_irq(struct intel_engine_cs *ring)
I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
else
I915_WRITE_IMR(ring, ~0);
- ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+ gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
@@ -1147,7 +1269,7 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
- snb_enable_pm_irq(dev_priv, ring->irq_enable_mask);
+ gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
@@ -1167,7 +1289,7 @@ hsw_vebox_put_irq(struct intel_engine_cs *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
I915_WRITE_IMR(ring, ~0);
- snb_disable_pm_irq(dev_priv, ring->irq_enable_mask);
+ gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
@@ -1329,6 +1451,7 @@ static int init_status_page(struct intel_engine_cs *ring)
struct drm_i915_gem_object *obj;
if ((obj = ring->status_page.obj) == NULL) {
+ unsigned flags;
int ret;
obj = i915_gem_alloc_object(ring->dev, 4096);
@@ -1341,7 +1464,20 @@ static int init_status_page(struct intel_engine_cs *ring)
if (ret)
goto err_unref;
- ret = i915_gem_obj_ggtt_pin(obj, 4096, 0);
+ flags = 0;
+ if (!HAS_LLC(ring->dev))
+ /* On g33, we cannot place HWS above 256MiB, so
+ * restrict its pinning to the low mappable arena.
+ * Though this restriction is not documented for
+ * gen4, gen5, or byt, they also behave similarly
+ * and hang if the HWS is placed at the top of the
+ * GTT. To generalise, it appears that all !llc
+ * platforms have issues with us placing the HWS
+ * above the mappable region (even though we never
+ * actualy map it).
+ */
+ flags |= PIN_MAPPABLE;
+ ret = i915_gem_obj_ggtt_pin(obj, 4096, flags);
if (ret) {
err_unref:
drm_gem_object_unreference(&obj->base);
@@ -1378,15 +1514,25 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
return 0;
}
-static int allocate_ring_buffer(struct intel_engine_cs *ring)
+static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
+{
+ if (!ringbuf->obj)
+ return;
+
+ iounmap(ringbuf->virtual_start);
+ i915_gem_object_ggtt_unpin(ringbuf->obj);
+ drm_gem_object_unreference(&ringbuf->obj->base);
+ ringbuf->obj = NULL;
+}
+
+static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+ struct intel_ringbuffer *ringbuf)
{
- struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_ringbuffer *ringbuf = ring->buffer;
struct drm_i915_gem_object *obj;
int ret;
- if (intel_ring_initialized(ring))
+ if (ringbuf->obj)
return 0;
obj = NULL;
@@ -1397,6 +1543,9 @@ static int allocate_ring_buffer(struct intel_engine_cs *ring)
if (obj == NULL)
return -ENOMEM;
+ /* mark ring buffers as read-only from GPU side by default */
+ obj->gt_ro = 1;
+
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
if (ret)
goto err_unref;
@@ -1455,7 +1604,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
goto error;
}
- ret = allocate_ring_buffer(ring);
+ ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
if (ret) {
DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret);
goto error;
@@ -1496,11 +1645,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
intel_stop_ring_buffer(ring);
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
- iounmap(ringbuf->virtual_start);
-
- i915_gem_object_ggtt_unpin(ringbuf->obj);
- drm_gem_object_unreference(&ringbuf->obj->base);
- ringbuf->obj = NULL;
+ intel_destroy_ringbuffer_obj(ringbuf);
ring->preallocated_lazy_request = NULL;
ring->outstanding_lazy_seqno = 0;
@@ -1526,7 +1671,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
ringbuf->head = ringbuf->last_retired_head;
ringbuf->last_retired_head = -1;
- ringbuf->space = ring_space(ring);
+ ringbuf->space = ring_space(ringbuf);
if (ringbuf->space >= n)
return 0;
}
@@ -1549,7 +1694,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
ringbuf->head = ringbuf->last_retired_head;
ringbuf->last_retired_head = -1;
- ringbuf->space = ring_space(ring);
+ ringbuf->space = ring_space(ringbuf);
return 0;
}
@@ -1578,7 +1723,7 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
trace_i915_ring_wait_begin(ring);
do {
ringbuf->head = I915_READ_HEAD(ring);
- ringbuf->space = ring_space(ring);
+ ringbuf->space = ring_space(ringbuf);
if (ringbuf->space >= n) {
ret = 0;
break;
@@ -1630,7 +1775,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)
iowrite32(MI_NOOP, virt++);
ringbuf->tail = 0;
- ringbuf->space = ring_space(ring);
+ ringbuf->space = ring_space(ringbuf);
return 0;
}
@@ -1746,14 +1891,15 @@ int intel_ring_cacheline_align(struct intel_engine_cs *ring)
void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
{
- struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
BUG_ON(ring->outstanding_lazy_seqno);
- if (INTEL_INFO(ring->dev)->gen >= 6) {
+ if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
- if (HAS_VEBOX(ring->dev))
+ if (HAS_VEBOX(dev))
I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
}
@@ -1941,45 +2087,74 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+ struct drm_i915_gem_object *obj;
+ int ret;
ring->name = "render ring";
ring->id = RCS;
ring->mmio_base = RENDER_RING_BASE;
- if (INTEL_INFO(dev)->gen >= 6) {
+ if (INTEL_INFO(dev)->gen >= 8) {
+ if (i915_semaphore_is_enabled(dev)) {
+ obj = i915_gem_alloc_object(dev, 4096);
+ if (obj == NULL) {
+ DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
+ i915.semaphores = 0;
+ } else {
+ i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+ ret = i915_gem_obj_ggtt_pin(obj, 0, PIN_NONBLOCK);
+ if (ret != 0) {
+ drm_gem_object_unreference(&obj->base);
+ DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
+ i915.semaphores = 0;
+ } else
+ dev_priv->semaphore_obj = obj;
+ }
+ }
+ ring->add_request = gen6_add_request;
+ ring->flush = gen8_render_ring_flush;
+ ring->irq_get = gen8_ring_get_irq;
+ ring->irq_put = gen8_ring_put_irq;
+ ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+ ring->get_seqno = gen6_ring_get_seqno;
+ ring->set_seqno = ring_set_seqno;
+ if (i915_semaphore_is_enabled(dev)) {
+ WARN_ON(!dev_priv->semaphore_obj);
+ ring->semaphore.sync_to = gen8_ring_sync;
+ ring->semaphore.signal = gen8_rcs_signal;
+ GEN8_RING_SEMAPHORE_INIT;
+ }
+ } else if (INTEL_INFO(dev)->gen >= 6) {
ring->add_request = gen6_add_request;
ring->flush = gen7_render_ring_flush;
if (INTEL_INFO(dev)->gen == 6)
ring->flush = gen6_render_ring_flush;
- if (INTEL_INFO(dev)->gen >= 8) {
- ring->flush = gen8_render_ring_flush;
- ring->irq_get = gen8_ring_get_irq;
- ring->irq_put = gen8_ring_put_irq;
- } else {
- ring->irq_get = gen6_ring_get_irq;
- ring->irq_put = gen6_ring_put_irq;
- }
+ ring->irq_get = gen6_ring_get_irq;
+ ring->irq_put = gen6_ring_put_irq;
ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
ring->get_seqno = gen6_ring_get_seqno;
ring->set_seqno = ring_set_seqno;
- ring->semaphore.sync_to = gen6_ring_sync;
- ring->semaphore.signal = gen6_signal;
- /*
- * The current semaphore is only applied on pre-gen8 platform.
- * And there is no VCS2 ring on the pre-gen8 platform. So the
- * semaphore between RCS and VCS2 is initialized as INVALID.
- * Gen8 will initialize the sema between VCS2 and RCS later.
- */
- ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
- ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
- ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
- ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
- ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
- ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
- ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen6_ring_sync;
+ ring->semaphore.signal = gen6_signal;
+ /*
+ * The current semaphore is only applied on pre-gen8
+ * platform. And there is no VCS2 ring on the pre-gen8
+ * platform. So the semaphore between RCS and VCS2 is
+ * initialized as INVALID. Gen8 will initialize the
+ * sema between VCS2 and RCS later.
+ */
+ ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+ ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+ ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+ ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+ ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+ ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+ ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+ ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+ }
} else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request;
ring->flush = gen4_render_ring_flush;
@@ -2007,6 +2182,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
ring->irq_enable_mask = I915_USER_INTERRUPT;
}
ring->write_tail = ring_write_tail;
+
if (IS_HASWELL(dev))
ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
else if (IS_GEN8(dev))
@@ -2024,9 +2200,6 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
/* Workaround batchbuffer to combat CS tlb bug. */
if (HAS_BROKEN_CS_TLB(dev)) {
- struct drm_i915_gem_object *obj;
- int ret;
-
obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT);
if (obj == NULL) {
DRM_ERROR("Failed to allocate batch bo\n");
@@ -2157,31 +2330,32 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
ring->irq_put = gen8_ring_put_irq;
ring->dispatch_execbuffer =
gen8_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen8_ring_sync;
+ ring->semaphore.signal = gen8_xcs_signal;
+ GEN8_RING_SEMAPHORE_INIT;
+ }
} else {
ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq;
ring->dispatch_execbuffer =
gen6_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen6_ring_sync;
+ ring->semaphore.signal = gen6_signal;
+ ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+ ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+ ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+ ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+ ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+ ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+ ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+ ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+ }
}
- ring->semaphore.sync_to = gen6_ring_sync;
- ring->semaphore.signal = gen6_signal;
- /*
- * The current semaphore is only applied on pre-gen8 platform.
- * And there is no VCS2 ring on the pre-gen8 platform. So the
- * semaphore between VCS and VCS2 is initialized as INVALID.
- * Gen8 will initialize the sema between VCS2 and VCS later.
- */
- ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
- ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
- ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
- ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
- ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
- ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
- ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
} else {
ring->mmio_base = BSD_RING_BASE;
ring->flush = bsd_ring_flush;
@@ -2218,7 +2392,7 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev)
return -EINVAL;
}
- ring->name = "bds2_ring";
+ ring->name = "bsd2 ring";
ring->id = VCS2;
ring->write_tail = ring_write_tail;
@@ -2233,25 +2407,11 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev)
ring->irq_put = gen8_ring_put_irq;
ring->dispatch_execbuffer =
gen8_ring_dispatch_execbuffer;
- ring->semaphore.sync_to = gen6_ring_sync;
- ring->semaphore.signal = gen6_signal;
- /*
- * The current semaphore is only applied on the pre-gen8. And there
- * is no bsd2 ring on the pre-gen8. So now the semaphore_register
- * between VCS2 and other ring is initialized as invalid.
- * Gen8 will initialize the sema between VCS2 and other ring later.
- */
- ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
-
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen8_ring_sync;
+ ring->semaphore.signal = gen8_xcs_signal;
+ GEN8_RING_SEMAPHORE_INIT;
+ }
ring->init = init_ring_common;
return intel_init_ring_buffer(dev, ring);
@@ -2277,30 +2437,38 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
ring->irq_get = gen8_ring_get_irq;
ring->irq_put = gen8_ring_put_irq;
ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen8_ring_sync;
+ ring->semaphore.signal = gen8_xcs_signal;
+ GEN8_RING_SEMAPHORE_INIT;
+ }
} else {
ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq;
ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.signal = gen6_signal;
+ ring->semaphore.sync_to = gen6_ring_sync;
+ /*
+ * The current semaphore is only applied on pre-gen8
+ * platform. And there is no VCS2 ring on the pre-gen8
+ * platform. So the semaphore between BCS and VCS2 is
+ * initialized as INVALID. Gen8 will initialize the
+ * sema between BCS and VCS2 later.
+ */
+ ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+ ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+ ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+ ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+ ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+ ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+ ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+ ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+ }
}
- ring->semaphore.sync_to = gen6_ring_sync;
- ring->semaphore.signal = gen6_signal;
- /*
- * The current semaphore is only applied on pre-gen8 platform. And
- * there is no VCS2 ring on the pre-gen8 platform. So the semaphore
- * between BCS and VCS2 is initialized as INVALID.
- * Gen8 will initialize the sema between BCS and VCS2 later.
- */
- ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
- ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
- ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
- ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
- ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
- ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
- ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
ring->init = init_ring_common;
return intel_init_ring_buffer(dev, ring);
@@ -2327,24 +2495,31 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
ring->irq_get = gen8_ring_get_irq;
ring->irq_put = gen8_ring_put_irq;
ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen8_ring_sync;
+ ring->semaphore.signal = gen8_xcs_signal;
+ GEN8_RING_SEMAPHORE_INIT;
+ }
} else {
ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
ring->irq_get = hsw_vebox_get_irq;
ring->irq_put = hsw_vebox_put_irq;
ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+ if (i915_semaphore_is_enabled(dev)) {
+ ring->semaphore.sync_to = gen6_ring_sync;
+ ring->semaphore.signal = gen6_signal;
+ ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+ ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+ ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+ ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+ ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+ ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+ ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+ ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+ ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+ }
}
- ring->semaphore.sync_to = gen6_ring_sync;
- ring->semaphore.signal = gen6_signal;
- ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
- ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
- ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
- ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
- ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
- ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
- ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
- ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
- ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
ring->init = init_ring_common;
return intel_init_ring_buffer(dev, ring);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index e72017bdcd7f..70525d0c2c74 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -40,10 +40,37 @@ struct intel_hw_status_page {
#define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base))
#define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val)
+/* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
+ * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
+ */
+#define i915_semaphore_seqno_size sizeof(uint64_t)
+#define GEN8_SIGNAL_OFFSET(__ring, to) \
+ (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+ ((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
+ (i915_semaphore_seqno_size * (to)))
+
+#define GEN8_WAIT_OFFSET(__ring, from) \
+ (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+ ((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
+ (i915_semaphore_seqno_size * (__ring)->id))
+
+#define GEN8_RING_SEMAPHORE_INIT do { \
+ if (!dev_priv->semaphore_obj) { \
+ break; \
+ } \
+ ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \
+ ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \
+ ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \
+ ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \
+ ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \
+ ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \
+ } while(0)
+
enum intel_ring_hangcheck_action {
HANGCHECK_IDLE = 0,
HANGCHECK_WAIT,
HANGCHECK_ACTIVE,
+ HANGCHECK_ACTIVE_LOOP,
HANGCHECK_KICK,
HANGCHECK_HUNG,
};
@@ -52,6 +79,7 @@ enum intel_ring_hangcheck_action {
struct intel_ring_hangcheck {
u64 acthd;
+ u64 max_acthd;
u32 seqno;
int score;
enum intel_ring_hangcheck_action action;
@@ -127,15 +155,55 @@ struct intel_engine_cs {
#define I915_DISPATCH_PINNED 0x2
void (*cleanup)(struct intel_engine_cs *ring);
+ /* GEN8 signal/wait table - never trust comments!
+ * signal to signal to signal to signal to signal to
+ * RCS VCS BCS VECS VCS2
+ * --------------------------------------------------------------------
+ * RCS | NOP (0x00) | VCS (0x08) | BCS (0x10) | VECS (0x18) | VCS2 (0x20) |
+ * |-------------------------------------------------------------------
+ * VCS | RCS (0x28) | NOP (0x30) | BCS (0x38) | VECS (0x40) | VCS2 (0x48) |
+ * |-------------------------------------------------------------------
+ * BCS | RCS (0x50) | VCS (0x58) | NOP (0x60) | VECS (0x68) | VCS2 (0x70) |
+ * |-------------------------------------------------------------------
+ * VECS | RCS (0x78) | VCS (0x80) | BCS (0x88) | NOP (0x90) | VCS2 (0x98) |
+ * |-------------------------------------------------------------------
+ * VCS2 | RCS (0xa0) | VCS (0xa8) | BCS (0xb0) | VECS (0xb8) | NOP (0xc0) |
+ * |-------------------------------------------------------------------
+ *
+ * Generalization:
+ * f(x, y) := (x->id * NUM_RINGS * seqno_size) + (seqno_size * y->id)
+ * ie. transpose of g(x, y)
+ *
+ * sync from sync from sync from sync from sync from
+ * RCS VCS BCS VECS VCS2
+ * --------------------------------------------------------------------
+ * RCS | NOP (0x00) | VCS (0x28) | BCS (0x50) | VECS (0x78) | VCS2 (0xa0) |
+ * |-------------------------------------------------------------------
+ * VCS | RCS (0x08) | NOP (0x30) | BCS (0x58) | VECS (0x80) | VCS2 (0xa8) |
+ * |-------------------------------------------------------------------
+ * BCS | RCS (0x10) | VCS (0x38) | NOP (0x60) | VECS (0x88) | VCS2 (0xb0) |
+ * |-------------------------------------------------------------------
+ * VECS | RCS (0x18) | VCS (0x40) | BCS (0x68) | NOP (0x90) | VCS2 (0xb8) |
+ * |-------------------------------------------------------------------
+ * VCS2 | RCS (0x20) | VCS (0x48) | BCS (0x70) | VECS (0x98) | NOP (0xc0) |
+ * |-------------------------------------------------------------------
+ *
+ * Generalization:
+ * g(x, y) := (y->id * NUM_RINGS * seqno_size) + (seqno_size * x->id)
+ * ie. transpose of f(x, y)
+ */
struct {
u32 sync_seqno[I915_NUM_RINGS-1];
- struct {
- /* our mbox written by others */
- u32 wait[I915_NUM_RINGS];
- /* mboxes this ring signals to */
- u32 signal[I915_NUM_RINGS];
- } mbox;
+ union {
+ struct {
+ /* our mbox written by others */
+ u32 wait[I915_NUM_RINGS];
+ /* mboxes this ring signals to */
+ u32 signal[I915_NUM_RINGS];
+ } mbox;
+ u64 signal_ggtt[I915_NUM_RINGS];
+ };
/* AKA wait() */
int (*sync_to)(struct intel_engine_cs *ring,
@@ -238,9 +306,11 @@ intel_ring_sync_index(struct intel_engine_cs *ring,
int idx;
/*
- * cs -> 0 = vcs, 1 = bcs
- * vcs -> 0 = bcs, 1 = cs,
- * bcs -> 0 = cs, 1 = vcs.
+ * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2;
+ * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs;
+ * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs;
+ * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs;
+ * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
*/
idx = (other - ring) - 1;
@@ -318,9 +388,9 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev);
u64 intel_ring_get_active_head(struct intel_engine_cs *ring);
void intel_ring_setup_status_page(struct intel_engine_cs *ring);
-static inline u32 intel_ring_get_tail(struct intel_engine_cs *ring)
+static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf)
{
- return ring->buffer->tail;
+ return ringbuf->tail;
}
static inline u32 intel_ring_get_seqno(struct intel_engine_cs *ring)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 20375cc7f82d..9350edd6728d 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2433,7 +2433,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
connector->base.unregister = intel_sdvo_connector_unregister;
intel_connector_attach_encoder(&connector->base, &encoder->base);
- ret = drm_sysfs_connector_add(drm_connector);
+ ret = drm_connector_register(drm_connector);
if (ret < 0)
goto err1;
@@ -2446,7 +2446,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
return 0;
err2:
- drm_sysfs_connector_remove(drm_connector);
+ drm_connector_unregister(drm_connector);
err1:
drm_connector_cleanup(drm_connector);
@@ -2559,7 +2559,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
return true;
err:
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
intel_sdvo_destroy(connector);
return false;
}
@@ -2638,7 +2638,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
return true;
err:
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
intel_sdvo_destroy(connector);
return false;
}
@@ -2711,7 +2711,7 @@ static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
list_for_each_entry_safe(connector, tmp,
&dev->mode_config.connector_list, head) {
if (intel_attached_encoder(connector) == &intel_sdvo->base) {
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
intel_sdvo_destroy(connector);
}
}
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 9a17b4e92ef4..168c6652cda1 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -218,7 +218,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
sprctl |= SP_ENABLE;
- intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
+ intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
+ pixel_size, true,
src_w != crtc_w || src_h != crtc_h);
/* Sizes are 0 based */
@@ -283,7 +284,7 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
if (atomic_update)
intel_pipe_update_end(intel_crtc, start_vbl_count);
- intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
+ intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
}
static int
@@ -406,7 +407,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
sprctl |= SPRITE_PIPE_CSC_ENABLE;
- intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+ intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
+ true,
src_w != crtc_w || src_h != crtc_h);
/* Sizes are 0 based */
@@ -486,7 +488,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
*/
intel_wait_for_vblank(dev, pipe);
- intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+ intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
}
static int
@@ -606,7 +608,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
dvscntr |= DVS_ENABLE;
- intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+ intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
+ pixel_size, true,
src_w != crtc_w || src_h != crtc_h);
/* Sizes are 0 based */
@@ -681,7 +684,7 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
*/
intel_wait_for_vblank(dev, pipe);
- intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
+ intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
}
static void
@@ -819,6 +822,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_device *dev = plane->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane = to_intel_plane(plane);
+ enum pipe pipe = intel_crtc->pipe;
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
struct drm_i915_gem_object *old_obj = intel_plane->obj;
@@ -1006,6 +1010,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
*/
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+ i915_gem_track_fb(old_obj, obj,
+ INTEL_FRONTBUFFER_SPRITE(pipe));
mutex_unlock(&dev->struct_mutex);
if (ret)
@@ -1039,6 +1045,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
else
intel_plane->disable_plane(plane, crtc);
+ intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
+
if (!primary_was_enabled && primary_enabled)
intel_post_enable_primary(crtc);
}
@@ -1068,6 +1076,7 @@ intel_disable_plane(struct drm_plane *plane)
struct drm_device *dev = plane->dev;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct intel_crtc *intel_crtc;
+ enum pipe pipe;
if (!plane->fb)
return 0;
@@ -1076,6 +1085,7 @@ intel_disable_plane(struct drm_plane *plane)
return -EINVAL;
intel_crtc = to_intel_crtc(plane->crtc);
+ pipe = intel_crtc->pipe;
if (intel_crtc->active) {
bool primary_was_enabled = intel_crtc->primary_enabled;
@@ -1094,6 +1104,8 @@ intel_disable_plane(struct drm_plane *plane)
mutex_lock(&dev->struct_mutex);
intel_unpin_fb_obj(intel_plane->obj);
+ i915_gem_track_fb(intel_plane->obj, NULL,
+ INTEL_FRONTBUFFER_SPRITE(pipe));
mutex_unlock(&dev->struct_mutex);
intel_plane->obj = NULL;
@@ -1114,7 +1126,6 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_intel_sprite_colorkey *set = data;
- struct drm_mode_object *obj;
struct drm_plane *plane;
struct intel_plane *intel_plane;
int ret = 0;
@@ -1128,13 +1139,12 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
- if (!obj) {
+ plane = drm_plane_find(dev, set->plane_id);
+ if (!plane) {
ret = -ENOENT;
goto out_unlock;
}
- plane = obj_to_plane(obj);
intel_plane = to_intel_plane(plane);
ret = intel_plane->update_colorkey(plane, set);
@@ -1147,7 +1157,6 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_intel_sprite_colorkey *get = data;
- struct drm_mode_object *obj;
struct drm_plane *plane;
struct intel_plane *intel_plane;
int ret = 0;
@@ -1157,13 +1166,12 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
- if (!obj) {
+ plane = drm_plane_find(dev, get->plane_id);
+ if (!plane) {
ret = -ENOENT;
goto out_unlock;
}
- plane = obj_to_plane(obj);
intel_plane = to_intel_plane(plane);
intel_plane->get_colorkey(plane, get);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 67c6c9a2eb1c..e211eef4b7e4 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1680,5 +1680,5 @@ intel_tv_init(struct drm_device *dev)
drm_object_attach_property(&connector->base,
dev->mode_config.tv_bottom_margin_property,
intel_tv->margin[TV_MARGIN_BOTTOM]);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
}
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 4f6fef7ac069..e81bc3bdc533 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -231,8 +231,8 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
}
/* WaRsForcewakeWaitTC0:vlv */
- __gen6_gt_wait_for_thread_c0(dev_priv);
-
+ if (!IS_CHERRYVIEW(dev_priv->dev))
+ __gen6_gt_wait_for_thread_c0(dev_priv);
}
static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
@@ -250,9 +250,10 @@ static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
- /* The below doubles as a POSTING_READ */
- gen6_gt_check_fifodbg(dev_priv);
-
+ /* something from same cacheline, but !FORCEWAKE_VLV */
+ __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
+ if (!IS_CHERRYVIEW(dev_priv->dev))
+ gen6_gt_check_fifodbg(dev_priv);
}
static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
@@ -315,7 +316,7 @@ static void gen6_force_wake_timer(unsigned long arg)
intel_runtime_pm_put(dev_priv);
}
-static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
+void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
@@ -357,16 +358,12 @@ static void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
dev_priv->uncore.fifo_count =
__raw_i915_read32(dev_priv, GTFIFOCTL) &
GT_FIFO_FREE_ENTRIES_MASK;
- } else {
- dev_priv->uncore.forcewake_count = 0;
- dev_priv->uncore.fw_rendercount = 0;
- dev_priv->uncore.fw_mediacount = 0;
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
-void intel_uncore_early_sanitize(struct drm_device *dev)
+void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -389,7 +386,7 @@ void intel_uncore_early_sanitize(struct drm_device *dev)
__raw_i915_write32(dev_priv, GTFIFODBG,
__raw_i915_read32(dev_priv, GTFIFODBG));
- intel_uncore_forcewake_reset(dev, false);
+ intel_uncore_forcewake_reset(dev, restore_forcewake);
}
void intel_uncore_sanitize(struct drm_device *dev)
@@ -469,16 +466,43 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
((reg) < 0x40000 && (reg) != FORCEWAKE)
-#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
- (((reg) >= 0x2000 && (reg) < 0x4000) ||\
- ((reg) >= 0x5000 && (reg) < 0x8000) ||\
- ((reg) >= 0xB000 && (reg) < 0x12000) ||\
- ((reg) >= 0x2E000 && (reg) < 0x30000))
+#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
- (((reg) >= 0x12000 && (reg) < 0x14000) ||\
- ((reg) >= 0x22000 && (reg) < 0x24000) ||\
- ((reg) >= 0x30000 && (reg) < 0x40000))
+#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
+ (REG_RANGE((reg), 0x2000, 0x4000) || \
+ REG_RANGE((reg), 0x5000, 0x8000) || \
+ REG_RANGE((reg), 0xB000, 0x12000) || \
+ REG_RANGE((reg), 0x2E000, 0x30000))
+
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
+ (REG_RANGE((reg), 0x12000, 0x14000) || \
+ REG_RANGE((reg), 0x22000, 0x24000) || \
+ REG_RANGE((reg), 0x30000, 0x40000))
+
+#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
+ (REG_RANGE((reg), 0x2000, 0x4000) || \
+ REG_RANGE((reg), 0x5000, 0x8000) || \
+ REG_RANGE((reg), 0x8300, 0x8500) || \
+ REG_RANGE((reg), 0xB000, 0xC000) || \
+ REG_RANGE((reg), 0xE000, 0xE800))
+
+#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \
+ (REG_RANGE((reg), 0x8800, 0x8900) || \
+ REG_RANGE((reg), 0xD000, 0xD800) || \
+ REG_RANGE((reg), 0x12000, 0x14000) || \
+ REG_RANGE((reg), 0x1A000, 0x1C000) || \
+ REG_RANGE((reg), 0x1E800, 0x1EA00) || \
+ REG_RANGE((reg), 0x30000, 0x40000))
+
+#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \
+ (REG_RANGE((reg), 0x4000, 0x5000) || \
+ REG_RANGE((reg), 0x8000, 0x8300) || \
+ REG_RANGE((reg), 0x8500, 0x8600) || \
+ REG_RANGE((reg), 0x9000, 0xB000) || \
+ REG_RANGE((reg), 0xC000, 0xC800) || \
+ REG_RANGE((reg), 0xF000, 0x10000) || \
+ REG_RANGE((reg), 0x14000, 0x14400) || \
+ REG_RANGE((reg), 0x22000, 0x24000))
static void
ilk_dummy_write(struct drm_i915_private *dev_priv)
@@ -490,20 +514,30 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)
}
static void
-hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
+hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,
+ bool before)
{
+ const char *op = read ? "reading" : "writing to";
+ const char *when = before ? "before" : "after";
+
+ if (!i915.mmio_debug)
+ return;
+
if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
- DRM_ERROR("Unknown unclaimed register before writing to %x\n",
- reg);
+ WARN(1, "Unclaimed register detected %s %s register 0x%x\n",
+ when, op, reg);
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
}
}
static void
-hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
+hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)
{
+ if (i915.mmio_debug)
+ return;
+
if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
- DRM_ERROR("Unclaimed write to %x\n", reg);
+ DRM_ERROR("Unclaimed register detected. Please use the i915.mmio_debug=1 to debug this problem.");
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
}
}
@@ -540,6 +574,7 @@ gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
static u##x \
gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
REG_READ_HEADER(x); \
+ hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
if (dev_priv->uncore.forcewake_count == 0 && \
NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
@@ -550,6 +585,7 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
} else { \
val = __raw_i915_read##x(dev_priv, reg); \
} \
+ hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
REG_READ_FOOTER; \
}
@@ -573,7 +609,35 @@ vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
REG_READ_FOOTER; \
}
+#define __chv_read(x) \
+static u##x \
+chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+ unsigned fwengine = 0; \
+ REG_READ_HEADER(x); \
+ if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_rendercount == 0) \
+ fwengine = FORCEWAKE_RENDER; \
+ } else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_mediacount == 0) \
+ fwengine = FORCEWAKE_MEDIA; \
+ } else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_rendercount == 0) \
+ fwengine |= FORCEWAKE_RENDER; \
+ if (dev_priv->uncore.fw_mediacount == 0) \
+ fwengine |= FORCEWAKE_MEDIA; \
+ } \
+ if (fwengine) \
+ dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
+ val = __raw_i915_read##x(dev_priv, reg); \
+ if (fwengine) \
+ dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
+ REG_READ_FOOTER; \
+}
+__chv_read(8)
+__chv_read(16)
+__chv_read(32)
+__chv_read(64)
__vlv_read(8)
__vlv_read(16)
__vlv_read(32)
@@ -591,6 +655,7 @@ __gen4_read(16)
__gen4_read(32)
__gen4_read(64)
+#undef __chv_read
#undef __vlv_read
#undef __gen6_read
#undef __gen5_read
@@ -647,12 +712,13 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
- hsw_unclaimed_reg_clear(dev_priv, reg); \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
__raw_i915_write##x(dev_priv, reg, val); \
if (unlikely(__fifo_ret)) { \
gen6_gt_check_fifodbg(dev_priv); \
} \
- hsw_unclaimed_reg_check(dev_priv, reg); \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
+ hsw_unclaimed_reg_detect(dev_priv); \
REG_WRITE_FOOTER; \
}
@@ -681,6 +747,7 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
static void \
gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
REG_WRITE_HEADER; \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) { \
if (dev_priv->uncore.forcewake_count == 0) \
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
@@ -692,9 +759,43 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
} else { \
__raw_i915_write##x(dev_priv, reg, val); \
} \
+ hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
+ hsw_unclaimed_reg_detect(dev_priv); \
REG_WRITE_FOOTER; \
}
+#define __chv_write(x) \
+static void \
+chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
+ unsigned fwengine = 0; \
+ bool shadowed = is_gen8_shadowed(dev_priv, reg); \
+ REG_WRITE_HEADER; \
+ if (!shadowed) { \
+ if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_rendercount == 0) \
+ fwengine = FORCEWAKE_RENDER; \
+ } else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_mediacount == 0) \
+ fwengine = FORCEWAKE_MEDIA; \
+ } else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
+ if (dev_priv->uncore.fw_rendercount == 0) \
+ fwengine |= FORCEWAKE_RENDER; \
+ if (dev_priv->uncore.fw_mediacount == 0) \
+ fwengine |= FORCEWAKE_MEDIA; \
+ } \
+ } \
+ if (fwengine) \
+ dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
+ __raw_i915_write##x(dev_priv, reg, val); \
+ if (fwengine) \
+ dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
+ REG_WRITE_FOOTER; \
+}
+
+__chv_write(8)
+__chv_write(16)
+__chv_write(32)
+__chv_write(64)
__gen8_write(8)
__gen8_write(16)
__gen8_write(32)
@@ -716,6 +817,7 @@ __gen4_write(16)
__gen4_write(32)
__gen4_write(64)
+#undef __chv_write
#undef __gen8_write
#undef __hsw_write
#undef __gen6_write
@@ -731,7 +833,7 @@ void intel_uncore_init(struct drm_device *dev)
setup_timer(&dev_priv->uncore.force_wake_timer,
gen6_force_wake_timer, (unsigned long)dev_priv);
- intel_uncore_early_sanitize(dev);
+ intel_uncore_early_sanitize(dev, false);
if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
@@ -779,14 +881,26 @@ void intel_uncore_init(struct drm_device *dev)
switch (INTEL_INFO(dev)->gen) {
default:
- dev_priv->uncore.funcs.mmio_writeb = gen8_write8;
- dev_priv->uncore.funcs.mmio_writew = gen8_write16;
- dev_priv->uncore.funcs.mmio_writel = gen8_write32;
- dev_priv->uncore.funcs.mmio_writeq = gen8_write64;
- dev_priv->uncore.funcs.mmio_readb = gen6_read8;
- dev_priv->uncore.funcs.mmio_readw = gen6_read16;
- dev_priv->uncore.funcs.mmio_readl = gen6_read32;
- dev_priv->uncore.funcs.mmio_readq = gen6_read64;
+ if (IS_CHERRYVIEW(dev)) {
+ dev_priv->uncore.funcs.mmio_writeb = chv_write8;
+ dev_priv->uncore.funcs.mmio_writew = chv_write16;
+ dev_priv->uncore.funcs.mmio_writel = chv_write32;
+ dev_priv->uncore.funcs.mmio_writeq = chv_write64;
+ dev_priv->uncore.funcs.mmio_readb = chv_read8;
+ dev_priv->uncore.funcs.mmio_readw = chv_read16;
+ dev_priv->uncore.funcs.mmio_readl = chv_read32;
+ dev_priv->uncore.funcs.mmio_readq = chv_read64;
+
+ } else {
+ dev_priv->uncore.funcs.mmio_writeb = gen8_write8;
+ dev_priv->uncore.funcs.mmio_writew = gen8_write16;
+ dev_priv->uncore.funcs.mmio_writel = gen8_write32;
+ dev_priv->uncore.funcs.mmio_writeq = gen8_write64;
+ dev_priv->uncore.funcs.mmio_readb = gen6_read8;
+ dev_priv->uncore.funcs.mmio_readw = gen6_read16;
+ dev_priv->uncore.funcs.mmio_readl = gen6_read32;
+ dev_priv->uncore.funcs.mmio_readq = gen6_read64;
+ }
break;
case 7:
case 6:
@@ -912,7 +1026,7 @@ int i915_get_reset_stats_ioctl(struct drm_device *dev,
if (args->flags || args->pad)
return -EINVAL;
- if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN))
+ if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN))
return -EPERM;
ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1053,18 +1167,16 @@ static int gen6_do_reset(struct drm_device *dev)
int intel_gpu_reset(struct drm_device *dev)
{
- switch (INTEL_INFO(dev)->gen) {
- case 8:
- case 7:
- case 6: return gen6_do_reset(dev);
- case 5: return ironlake_do_reset(dev);
- case 4:
- if (IS_G4X(dev))
- return g4x_do_reset(dev);
- else
- return i965_do_reset(dev);
- default: return -ENODEV;
- }
+ if (INTEL_INFO(dev)->gen >= 6)
+ return gen6_do_reset(dev);
+ else if (IS_GEN5(dev))
+ return ironlake_do_reset(dev);
+ else if (IS_G4X(dev))
+ return g4x_do_reset(dev);
+ else if (IS_GEN4(dev))
+ return i965_do_reset(dev);
+ else
+ return -ENODEV;
}
void intel_uncore_check_errors(struct drm_device *dev)
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index f15ea3c4a90a..2d75d6df0789 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -28,7 +28,7 @@ module_param_named(modeset, mgag200_modeset, int, 0400);
static struct drm_driver driver;
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index cf11ee68a6d9..80de23d9b9c9 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -280,7 +280,7 @@ static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
{
int ret;
- ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
+ ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
if (ret) {
if (ret != -ERESTARTSYS && ret != -EBUSY)
DRM_ERROR("reserve failed %p\n", bo);
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
index 13b7dd83faa9..5451dc58eff1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -272,7 +272,7 @@ static int mga_fbdev_destroy(struct drm_device *dev,
return 0;
}
-static struct drm_fb_helper_funcs mga_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs mga_fb_helper_funcs = {
.gamma_set = mga_crtc_fb_gamma_set,
.gamma_get = mga_crtc_fb_gamma_get,
.fb_probe = mgag200fb_create,
@@ -293,9 +293,10 @@ int mgag200_fbdev_init(struct mga_device *mdev)
return -ENOMEM;
mdev->mfbdev = mfbdev;
- mfbdev->helper.funcs = &mga_fb_helper_funcs;
spin_lock_init(&mfbdev->dirty_lock);
+ drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
+
ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
mdev->num_crtc, MGAG200FB_CONN_LIMIT);
if (ret)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index a034ed408252..45f04dea0ac2 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1562,19 +1562,9 @@ static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
*connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
/* pick the encoder ids */
- if (enc_id) {
- obj =
- drm_mode_object_find(connector->dev, enc_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
@@ -1621,7 +1611,7 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev)
drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
mga_connector->i2c = mgag200_i2c_create(dev);
if (!mga_connector->i2c)
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index f12388967856..c99c50de3226 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -2,7 +2,6 @@
config DRM_MSM
tristate "MSM DRM"
depends on DRM
- depends on MSM_IOMMU
depends on ARCH_QCOM || (ARM && COMPILE_TEST)
select DRM_KMS_HELPER
select SHMEM
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index 85d615e7d62f..a8a144b38eaa 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -203,6 +203,15 @@ enum a2xx_rb_copy_sample_select {
SAMPLE_0123 = 6,
};
+enum a2xx_rb_blend_opcode {
+ BLEND_DST_PLUS_SRC = 0,
+ BLEND_SRC_MINUS_DST = 1,
+ BLEND_MIN_DST_SRC = 2,
+ BLEND_MAX_DST_SRC = 3,
+ BLEND_DST_MINUS_SRC = 4,
+ BLEND_DST_PLUS_SRC_BIAS = 5,
+};
+
enum adreno_mmu_clnt_beh {
BEH_NEVR = 0,
BEH_TRAN_RNG = 1,
@@ -890,6 +899,39 @@ static inline uint32_t A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(uint32_t val)
#define REG_A2XX_VGT_EVENT_INITIATOR 0x000021f9
#define REG_A2XX_VGT_DRAW_INITIATOR 0x000021fc
+#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK 0x0000003f
+#define A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT 0
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
+{
+ return ((val) << A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK 0x000000c0
+#define A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT 6
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+ return ((val) << A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A2XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK 0x00000600
+#define A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT 9
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << A2XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A2XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK 0x00000800
+#define A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT 11
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
+{
+ return ((val) << A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A2XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
+}
+#define A2XX_VGT_DRAW_INITIATOR_NOT_EOP 0x00001000
+#define A2XX_VGT_DRAW_INITIATOR_SMALL_INDEX 0x00002000
+#define A2XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x00004000
+#define A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK 0xffff0000
+#define A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT 16
+static inline uint32_t A2XX_VGT_DRAW_INITIATOR_NUM_INDICES(uint32_t val)
+{
+ return ((val) << A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT) & A2XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK;
+}
#define REG_A2XX_VGT_IMMED_DATA 0x000021fd
@@ -963,7 +1005,7 @@ static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(enum adreno_rb_blend
}
#define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK 0x000000e0
#define A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT 5
-static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(enum adreno_rb_blend_opcode val)
+static inline uint32_t A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(enum a2xx_rb_blend_opcode val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN__MASK;
}
@@ -981,7 +1023,7 @@ static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(enum adreno_rb_blend
}
#define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK 0x00e00000
#define A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT 21
-static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(enum adreno_rb_blend_opcode val)
+static inline uint32_t A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(enum a2xx_rb_blend_opcode val)
{
return ((val) << A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__SHIFT) & A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN__MASK;
}
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index a7be56163d23..303e8a9e91a5 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -41,31 +41,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-enum a3xx_render_mode {
- RB_RENDERING_PASS = 0,
- RB_TILING_PASS = 1,
- RB_RESOLVE_PASS = 2,
-};
-
enum a3xx_tile_mode {
LINEAR = 0,
TILE_32X32 = 2,
};
-enum a3xx_threadmode {
- MULTI = 0,
- SINGLE = 1,
-};
-
-enum a3xx_instrbuffermode {
- BUFFER = 1,
-};
-
-enum a3xx_threadsize {
- TWO_QUADS = 0,
- FOUR_QUADS = 1,
-};
-
enum a3xx_state_block_id {
HLSQ_BLOCK_ID_TP_TEX = 2,
HLSQ_BLOCK_ID_TP_MIPMAP = 3,
@@ -169,6 +149,8 @@ enum a3xx_color_fmt {
RB_R8G8B8A8_UNORM = 8,
RB_Z16_UNORM = 12,
RB_A8_UNORM = 20,
+ RB_R16G16B16A16_FLOAT = 27,
+ RB_R32G32B32A32_FLOAT = 51,
};
enum a3xx_color_swap {
@@ -178,12 +160,6 @@ enum a3xx_color_swap {
XYZW = 3,
};
-enum a3xx_msaa_samples {
- MSAA_ONE = 0,
- MSAA_TWO = 1,
- MSAA_FOUR = 2,
-};
-
enum a3xx_sp_perfcounter_select {
SP_FS_CFLOW_INSTRUCTIONS = 12,
SP_FS_FULL_ALU_INSTRUCTIONS = 14,
@@ -191,21 +167,45 @@ enum a3xx_sp_perfcounter_select {
SP_ALU_ACTIVE_CYCLES = 29,
};
-enum adreno_rb_copy_control_mode {
- RB_COPY_RESOLVE = 1,
- RB_COPY_DEPTH_STENCIL = 5,
+enum a3xx_rop_code {
+ ROP_CLEAR = 0,
+ ROP_NOR = 1,
+ ROP_AND_INVERTED = 2,
+ ROP_COPY_INVERTED = 3,
+ ROP_AND_REVERSE = 4,
+ ROP_INVERT = 5,
+ ROP_XOR = 6,
+ ROP_NAND = 7,
+ ROP_AND = 8,
+ ROP_EQUIV = 9,
+ ROP_NOOP = 10,
+ ROP_OR_INVERTED = 11,
+ ROP_COPY = 12,
+ ROP_OR_REVERSE = 13,
+ ROP_OR = 14,
+ ROP_SET = 15,
+};
+
+enum a3xx_rb_blend_opcode {
+ BLEND_DST_PLUS_SRC = 0,
+ BLEND_SRC_MINUS_DST = 1,
+ BLEND_DST_MINUS_SRC = 2,
+ BLEND_MIN_DST_SRC = 3,
+ BLEND_MAX_DST_SRC = 4,
};
enum a3xx_tex_filter {
A3XX_TEX_NEAREST = 0,
A3XX_TEX_LINEAR = 1,
+ A3XX_TEX_ANISO = 2,
};
enum a3xx_tex_clamp {
A3XX_TEX_REPEAT = 0,
A3XX_TEX_CLAMP_TO_EDGE = 1,
A3XX_TEX_MIRROR_REPEAT = 2,
- A3XX_TEX_CLAMP_NONE = 3,
+ A3XX_TEX_CLAMP_TO_BORDER = 3,
+ A3XX_TEX_MIRROR_CLAMP = 4,
};
enum a3xx_tex_swiz {
@@ -316,6 +316,7 @@ enum a3xx_tex_type {
#define REG_A3XX_RBBM_INT_0_STATUS 0x00000064
#define REG_A3XX_RBBM_PERFCTR_CTL 0x00000080
+#define A3XX_RBBM_PERFCTR_CTL_ENABLE 0x00000001
#define REG_A3XX_RBBM_PERFCTR_LOAD_CMD0 0x00000081
@@ -549,6 +550,10 @@ static inline uint32_t REG_A3XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000460
#define REG_A3XX_CP_AHB_FAULT 0x0000054d
+#define REG_A3XX_SP_GLOBAL_MEM_SIZE 0x00000e22
+
+#define REG_A3XX_SP_GLOBAL_MEM_ADDR 0x00000e23
+
#define REG_A3XX_GRAS_CL_CLIP_CNTL 0x00002040
#define A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER 0x00001000
#define A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE 0x00010000
@@ -556,6 +561,9 @@ static inline uint32_t REG_A3XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000460
#define A3XX_GRAS_CL_CLIP_CNTL_VP_CLIP_CODE_IGNORE 0x00080000
#define A3XX_GRAS_CL_CLIP_CNTL_VP_XFORM_DISABLE 0x00100000
#define A3XX_GRAS_CL_CLIP_CNTL_PERSP_DIVISION_DISABLE 0x00200000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZCOORD 0x00800000
+#define A3XX_GRAS_CL_CLIP_CNTL_WCOORD 0x01000000
+#define A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE 0x02000000
#define REG_A3XX_GRAS_CL_GB_CLIP_ADJ 0x00002044
#define A3XX_GRAS_CL_GB_CLIP_ADJ_HORZ__MASK 0x000003ff
@@ -620,8 +628,26 @@ static inline uint32_t A3XX_GRAS_CL_VPORT_ZSCALE(float val)
}
#define REG_A3XX_GRAS_SU_POINT_MINMAX 0x00002068
+#define A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK 0x0000ffff
+#define A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT 0
+static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MIN(float val)
+{
+ return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
+}
+#define A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK 0xffff0000
+#define A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT 16
+static inline uint32_t A3XX_GRAS_SU_POINT_MINMAX_MAX(float val)
+{
+ return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A3XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
+}
#define REG_A3XX_GRAS_SU_POINT_SIZE 0x00002069
+#define A3XX_GRAS_SU_POINT_SIZE__MASK 0xffffffff
+#define A3XX_GRAS_SU_POINT_SIZE__SHIFT 0
+static inline uint32_t A3XX_GRAS_SU_POINT_SIZE(float val)
+{
+ return ((((uint32_t)(val * 8.0))) << A3XX_GRAS_SU_POINT_SIZE__SHIFT) & A3XX_GRAS_SU_POINT_SIZE__MASK;
+}
#define REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE 0x0000206c
#define A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL__MASK 0x00ffffff
@@ -743,6 +769,7 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_RENDER_MODE(enum a3xx_render_mode va
#define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE 0x00010000
#define REG_A3XX_RB_RENDER_CONTROL 0x000020c1
+#define A3XX_RB_RENDER_CONTROL_FACENESS 0x00000008
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK 0x00000ff0
#define A3XX_RB_RENDER_CONTROL_BIN_WIDTH__SHIFT 4
static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
@@ -751,6 +778,10 @@ static inline uint32_t A3XX_RB_RENDER_CONTROL_BIN_WIDTH(uint32_t val)
}
#define A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE 0x00001000
#define A3XX_RB_RENDER_CONTROL_ENABLE_GMEM 0x00002000
+#define A3XX_RB_RENDER_CONTROL_XCOORD 0x00004000
+#define A3XX_RB_RENDER_CONTROL_YCOORD 0x00008000
+#define A3XX_RB_RENDER_CONTROL_ZCOORD 0x00010000
+#define A3XX_RB_RENDER_CONTROL_WCOORD 0x00020000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST 0x00400000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK 0x07000000
#define A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__SHIFT 24
@@ -796,7 +827,7 @@ static inline uint32_t REG_A3XX_RB_MRT_CONTROL(uint32_t i0) { return 0x000020c4
#define A3XX_RB_MRT_CONTROL_BLEND2 0x00000020
#define A3XX_RB_MRT_CONTROL_ROP_CODE__MASK 0x00000f00
#define A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT 8
-static inline uint32_t A3XX_RB_MRT_CONTROL_ROP_CODE(uint32_t val)
+static inline uint32_t A3XX_RB_MRT_CONTROL_ROP_CODE(enum a3xx_rop_code val)
{
return ((val) << A3XX_RB_MRT_CONTROL_ROP_CODE__SHIFT) & A3XX_RB_MRT_CONTROL_ROP_CODE__MASK;
}
@@ -856,7 +887,7 @@ static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_b
}
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK 0x000000e0
#define A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT 5
-static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum adreno_rb_blend_opcode val)
+static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
}
@@ -874,7 +905,7 @@ static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb
}
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK 0x00e00000
#define A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT 21
-static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum adreno_rb_blend_opcode val)
+static inline uint32_t A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
{
return ((val) << A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A3XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
}
@@ -957,17 +988,24 @@ static inline uint32_t A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(enum a3xx_msaa_samples
{
return ((val) << A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__SHIFT) & A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK;
}
+#define A3XX_RB_COPY_CONTROL_DEPTHCLEAR 0x00000008
#define A3XX_RB_COPY_CONTROL_MODE__MASK 0x00000070
#define A3XX_RB_COPY_CONTROL_MODE__SHIFT 4
static inline uint32_t A3XX_RB_COPY_CONTROL_MODE(enum adreno_rb_copy_control_mode val)
{
return ((val) << A3XX_RB_COPY_CONTROL_MODE__SHIFT) & A3XX_RB_COPY_CONTROL_MODE__MASK;
}
-#define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK 0xfffffc00
-#define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT 10
+#define A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK 0x00000f00
+#define A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT 8
+static inline uint32_t A3XX_RB_COPY_CONTROL_FASTCLEAR(uint32_t val)
+{
+ return ((val) << A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT) & A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK;
+}
+#define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK 0xffffc000
+#define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT 14
static inline uint32_t A3XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
{
- return ((val >> 10) << A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
+ return ((val >> 14) << A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT) & A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK;
}
#define REG_A3XX_RB_COPY_DEST_BASE 0x000020ed
@@ -1005,6 +1043,12 @@ static inline uint32_t A3XX_RB_COPY_DEST_INFO_SWAP(enum a3xx_color_swap val)
{
return ((val) << A3XX_RB_COPY_DEST_INFO_SWAP__SHIFT) & A3XX_RB_COPY_DEST_INFO_SWAP__MASK;
}
+#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK 0x00000c00
+#define A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT 10
+static inline uint32_t A3XX_RB_COPY_DEST_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
+{
+ return ((val) << A3XX_RB_COPY_DEST_INFO_DITHER_MODE__SHIFT) & A3XX_RB_COPY_DEST_INFO_DITHER_MODE__MASK;
+}
#define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__MASK 0x0003c000
#define A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE__SHIFT 14
static inline uint32_t A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(uint32_t val)
@@ -1019,6 +1063,7 @@ static inline uint32_t A3XX_RB_COPY_DEST_INFO_ENDIAN(enum adreno_rb_surface_endi
}
#define REG_A3XX_RB_DEPTH_CONTROL 0x00002100
+#define A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z 0x00000001
#define A3XX_RB_DEPTH_CONTROL_Z_ENABLE 0x00000002
#define A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE 0x00000004
#define A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE 0x00000008
@@ -1044,7 +1089,7 @@ static inline uint32_t A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(enum adreno_rb_depth_form
#define A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT 11
static inline uint32_t A3XX_RB_DEPTH_INFO_DEPTH_BASE(uint32_t val)
{
- return ((val >> 10) << A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
+ return ((val >> 12) << A3XX_RB_DEPTH_INFO_DEPTH_BASE__SHIFT) & A3XX_RB_DEPTH_INFO_DEPTH_BASE__MASK;
}
#define REG_A3XX_RB_DEPTH_PITCH 0x00002103
@@ -1172,6 +1217,8 @@ static inline uint32_t A3XX_RB_WINDOW_OFFSET_Y(uint32_t val)
}
#define REG_A3XX_RB_SAMPLE_COUNT_CONTROL 0x00002110
+#define A3XX_RB_SAMPLE_COUNT_CONTROL_RESET 0x00000001
+#define A3XX_RB_SAMPLE_COUNT_CONTROL_COPY 0x00000002
#define REG_A3XX_RB_SAMPLE_COUNT_ADDR 0x00002111
@@ -1179,7 +1226,23 @@ static inline uint32_t A3XX_RB_WINDOW_OFFSET_Y(uint32_t val)
#define REG_A3XX_RB_Z_CLAMP_MAX 0x00002115
+#define REG_A3XX_VGT_BIN_BASE 0x000021e1
+
+#define REG_A3XX_VGT_BIN_SIZE 0x000021e2
+
#define REG_A3XX_PC_VSTREAM_CONTROL 0x000021e4
+#define A3XX_PC_VSTREAM_CONTROL_SIZE__MASK 0x003f0000
+#define A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT 16
+static inline uint32_t A3XX_PC_VSTREAM_CONTROL_SIZE(uint32_t val)
+{
+ return ((val) << A3XX_PC_VSTREAM_CONTROL_SIZE__SHIFT) & A3XX_PC_VSTREAM_CONTROL_SIZE__MASK;
+}
+#define A3XX_PC_VSTREAM_CONTROL_N__MASK 0x07c00000
+#define A3XX_PC_VSTREAM_CONTROL_N__SHIFT 22
+static inline uint32_t A3XX_PC_VSTREAM_CONTROL_N(uint32_t val)
+{
+ return ((val) << A3XX_PC_VSTREAM_CONTROL_N__SHIFT) & A3XX_PC_VSTREAM_CONTROL_N__MASK;
+}
#define REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x000021ea
@@ -1203,6 +1266,7 @@ static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(enum adreno_pa_
return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;
}
#define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST 0x02000000
+#define A3XX_PC_PRIM_VTX_CNTL_PSIZE 0x04000000
#define REG_A3XX_PC_RESTART_INDEX 0x000021ed
@@ -1232,6 +1296,7 @@ static inline uint32_t A3XX_HLSQ_CONTROL_1_REG_VSTHREADSIZE(enum a3xx_threadsize
}
#define A3XX_HLSQ_CONTROL_1_REG_VSSUPERTHREADENABLE 0x00000100
#define A3XX_HLSQ_CONTROL_1_REG_RESERVED1 0x00000200
+#define A3XX_HLSQ_CONTROL_1_REG_ZWCOORD 0x02000000
#define REG_A3XX_HLSQ_CONTROL_2_REG 0x00002202
#define A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK 0xfc000000
@@ -1242,6 +1307,12 @@ static inline uint32_t A3XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD(uint32_t val)
}
#define REG_A3XX_HLSQ_CONTROL_3_REG 0x00002203
+#define A3XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff
+#define A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT 0
+static inline uint32_t A3XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
+{
+ return ((val) << A3XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A3XX_HLSQ_CONTROL_3_REG_REGID__MASK;
+}
#define REG_A3XX_HLSQ_VS_CONTROL_REG 0x00002204
#define A3XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK 0x00000fff
@@ -1312,10 +1383,36 @@ static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
}
#define REG_A3XX_HLSQ_CL_NDRANGE_0_REG 0x0000220a
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK 0x00000003
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT 0
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM(uint32_t val)
+{
+ return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_WORKDIM__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK 0x00000ffc
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT 2
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0(uint32_t val)
+{
+ return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE0__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK 0x003ff000
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT 12
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1(uint32_t val)
+{
+ return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE1__MASK;
+}
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK 0xffc00000
+#define A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT 22
+static inline uint32_t A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2(uint32_t val)
+{
+ return ((val) << A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__SHIFT) & A3XX_HLSQ_CL_NDRANGE_0_REG_LOCALSIZE2__MASK;
+}
+
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK(uint32_t i0) { return 0x0000220b + 0x2*i0; }
-#define REG_A3XX_HLSQ_CL_NDRANGE_1_REG 0x0000220b
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_SIZE(uint32_t i0) { return 0x0000220b + 0x2*i0; }
-#define REG_A3XX_HLSQ_CL_NDRANGE_2_REG 0x0000220c
+static inline uint32_t REG_A3XX_HLSQ_CL_GLOBAL_WORK_OFFSET(uint32_t i0) { return 0x0000220c + 0x2*i0; }
#define REG_A3XX_HLSQ_CL_CONTROL_0_REG 0x00002211
@@ -1323,7 +1420,9 @@ static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
#define REG_A3XX_HLSQ_CL_KERNEL_CONST_REG 0x00002214
-#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG 0x00002215
+static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP(uint32_t i0) { return 0x00002215 + 0x1*i0; }
+
+static inline uint32_t REG_A3XX_HLSQ_CL_KERNEL_GROUP_RATIO(uint32_t i0) { return 0x00002215 + 0x1*i0; }
#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x00002216
@@ -1438,6 +1537,12 @@ static inline uint32_t A3XX_VFD_DECODE_INSTR_REGID(uint32_t val)
{
return ((val) << A3XX_VFD_DECODE_INSTR_REGID__SHIFT) & A3XX_VFD_DECODE_INSTR_REGID__MASK;
}
+#define A3XX_VFD_DECODE_INSTR_SWAP__MASK 0x00c00000
+#define A3XX_VFD_DECODE_INSTR_SWAP__SHIFT 22
+static inline uint32_t A3XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
+{
+ return ((val) << A3XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A3XX_VFD_DECODE_INSTR_SWAP__MASK;
+}
#define A3XX_VFD_DECODE_INSTR_SHIFTCNT__MASK 0x1f000000
#define A3XX_VFD_DECODE_INSTR_SHIFTCNT__SHIFT 24
static inline uint32_t A3XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
@@ -1462,12 +1567,13 @@ static inline uint32_t A3XX_VFD_VS_THREADING_THRESHOLD_REGID_VTXCNT(uint32_t val
}
#define REG_A3XX_VPC_ATTR 0x00002280
-#define A3XX_VPC_ATTR_TOTALATTR__MASK 0x00000fff
+#define A3XX_VPC_ATTR_TOTALATTR__MASK 0x000001ff
#define A3XX_VPC_ATTR_TOTALATTR__SHIFT 0
static inline uint32_t A3XX_VPC_ATTR_TOTALATTR(uint32_t val)
{
return ((val) << A3XX_VPC_ATTR_TOTALATTR__SHIFT) & A3XX_VPC_ATTR_TOTALATTR__MASK;
}
+#define A3XX_VPC_ATTR_PSIZE 0x00000200
#define A3XX_VPC_ATTR_THRDASSIGN__MASK 0x0ffff000
#define A3XX_VPC_ATTR_THRDASSIGN__SHIFT 12
static inline uint32_t A3XX_VPC_ATTR_THRDASSIGN(uint32_t val)
@@ -1522,11 +1628,11 @@ static inline uint32_t A3XX_SP_SP_CTRL_REG_SLEEPMODE(uint32_t val)
{
return ((val) << A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK;
}
-#define A3XX_SP_SP_CTRL_REG_LOMODE__MASK 0x00c00000
-#define A3XX_SP_SP_CTRL_REG_LOMODE__SHIFT 22
-static inline uint32_t A3XX_SP_SP_CTRL_REG_LOMODE(uint32_t val)
+#define A3XX_SP_SP_CTRL_REG_L0MODE__MASK 0x00c00000
+#define A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT 22
+static inline uint32_t A3XX_SP_SP_CTRL_REG_L0MODE(uint32_t val)
{
- return ((val) << A3XX_SP_SP_CTRL_REG_LOMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_LOMODE__MASK;
+ return ((val) << A3XX_SP_SP_CTRL_REG_L0MODE__SHIFT) & A3XX_SP_SP_CTRL_REG_L0MODE__MASK;
}
#define REG_A3XX_SP_VS_CTRL_REG0 0x000022c4
@@ -1569,6 +1675,7 @@ static inline uint32_t A3XX_SP_VS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
}
#define A3XX_SP_VS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A3XX_SP_VS_CTRL_REG0_PIXLODENABLE 0x00400000
+#define A3XX_SP_VS_CTRL_REG0_COMPUTEMODE 0x00800000
#define A3XX_SP_VS_CTRL_REG0_LENGTH__MASK 0xff000000
#define A3XX_SP_VS_CTRL_REG0_LENGTH__SHIFT 24
static inline uint32_t A3XX_SP_VS_CTRL_REG0_LENGTH(uint32_t val)
@@ -1742,6 +1849,7 @@ static inline uint32_t A3XX_SP_FS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
}
#define A3XX_SP_FS_CTRL_REG0_SUPERTHREADMODE 0x00200000
#define A3XX_SP_FS_CTRL_REG0_PIXLODENABLE 0x00400000
+#define A3XX_SP_FS_CTRL_REG0_COMPUTEMODE 0x00800000
#define A3XX_SP_FS_CTRL_REG0_LENGTH__MASK 0xff000000
#define A3XX_SP_FS_CTRL_REG0_LENGTH__SHIFT 24
static inline uint32_t A3XX_SP_FS_CTRL_REG0_LENGTH(uint32_t val)
@@ -1802,6 +1910,13 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
#define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x000022e9
#define REG_A3XX_SP_FS_OUTPUT_REG 0x000022ec
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE 0x00000080
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK 0x0000ff00
+#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT 8
+static inline uint32_t A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
+{
+ return ((val) << A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
+}
static inline uint32_t REG_A3XX_SP_FS_MRT(uint32_t i0) { return 0x000022f0 + 0x1*i0; }
@@ -1914,6 +2029,42 @@ static inline uint32_t A3XX_TPL1_TP_FS_TEX_OFFSET_BASETABLEPTR(uint32_t val)
#define REG_A3XX_VBIF_OUT_AXI_AOOO 0x0000305f
+#define REG_A3XX_VBIF_PERF_CNT_EN 0x00003070
+#define A3XX_VBIF_PERF_CNT_EN_CNT0 0x00000001
+#define A3XX_VBIF_PERF_CNT_EN_CNT1 0x00000002
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT0 0x00000004
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT1 0x00000008
+#define A3XX_VBIF_PERF_CNT_EN_PWRCNT2 0x00000010
+
+#define REG_A3XX_VBIF_PERF_CNT_CLR 0x00003071
+#define A3XX_VBIF_PERF_CNT_CLR_CNT0 0x00000001
+#define A3XX_VBIF_PERF_CNT_CLR_CNT1 0x00000002
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT0 0x00000004
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT1 0x00000008
+#define A3XX_VBIF_PERF_CNT_CLR_PWRCNT2 0x00000010
+
+#define REG_A3XX_VBIF_PERF_CNT_SEL 0x00003072
+
+#define REG_A3XX_VBIF_PERF_CNT0_LO 0x00003073
+
+#define REG_A3XX_VBIF_PERF_CNT0_HI 0x00003074
+
+#define REG_A3XX_VBIF_PERF_CNT1_LO 0x00003075
+
+#define REG_A3XX_VBIF_PERF_CNT1_HI 0x00003076
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT0_LO 0x00003077
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT0_HI 0x00003078
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT1_LO 0x00003079
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT1_HI 0x0000307a
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT2_LO 0x0000307b
+
+#define REG_A3XX_VBIF_PERF_PWR_CNT2_HI 0x0000307c
+
#define REG_A3XX_VSC_BIN_SIZE 0x00000c01
#define A3XX_VSC_BIN_SIZE_WIDTH__MASK 0x0000001f
#define A3XX_VSC_BIN_SIZE_WIDTH__SHIFT 0
@@ -2080,6 +2231,8 @@ static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(enum a3xx_cache_op
}
#define A3XX_UCHE_CACHE_INVALIDATE1_REG_ENTIRE_CACHE 0x80000000
+#define REG_A3XX_UNKNOWN_0EA6 0x00000ea6
+
#define REG_A3XX_SP_PERFCOUNTER0_SELECT 0x00000ec4
#define REG_A3XX_SP_PERFCOUNTER1_SELECT 0x00000ec5
@@ -2117,6 +2270,39 @@ static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(enum a3xx_cache_op
#define REG_A3XX_VGT_EVENT_INITIATOR 0x000021f9
#define REG_A3XX_VGT_DRAW_INITIATOR 0x000021fc
+#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK 0x0000003f
+#define A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT 0
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE(enum pc_di_primtype val)
+{
+ return ((val) << A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_PRIM_TYPE__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK 0x000000c0
+#define A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT 6
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+ return ((val) << A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__SHIFT) & A3XX_VGT_DRAW_INITIATOR_SOURCE_SELECT__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK 0x00000600
+#define A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT 9
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << A3XX_VGT_DRAW_INITIATOR_VIS_CULL__SHIFT) & A3XX_VGT_DRAW_INITIATOR_VIS_CULL__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK 0x00000800
+#define A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT 11
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE(enum pc_di_index_size val)
+{
+ return ((val) << A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__SHIFT) & A3XX_VGT_DRAW_INITIATOR_INDEX_SIZE__MASK;
+}
+#define A3XX_VGT_DRAW_INITIATOR_NOT_EOP 0x00001000
+#define A3XX_VGT_DRAW_INITIATOR_SMALL_INDEX 0x00002000
+#define A3XX_VGT_DRAW_INITIATOR_PRE_DRAW_INITIATOR_ENABLE 0x00004000
+#define A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK 0xffff0000
+#define A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT 16
+static inline uint32_t A3XX_VGT_DRAW_INITIATOR_NUM_INDICES(uint32_t val)
+{
+ return ((val) << A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__SHIFT) & A3XX_VGT_DRAW_INITIATOR_NUM_INDICES__MASK;
+}
#define REG_A3XX_VGT_IMMED_DATA 0x000021fd
@@ -2152,6 +2338,12 @@ static inline uint32_t A3XX_TEX_SAMP_0_WRAP_R(enum a3xx_tex_clamp val)
{
return ((val) << A3XX_TEX_SAMP_0_WRAP_R__SHIFT) & A3XX_TEX_SAMP_0_WRAP_R__MASK;
}
+#define A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK 0x00700000
+#define A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT 20
+static inline uint32_t A3XX_TEX_SAMP_0_COMPARE_FUNC(enum adreno_compare_func val)
+{
+ return ((val) << A3XX_TEX_SAMP_0_COMPARE_FUNC__SHIFT) & A3XX_TEX_SAMP_0_COMPARE_FUNC__MASK;
+}
#define A3XX_TEX_SAMP_0_UNNORM_COORDS 0x80000000
#define REG_A3XX_TEX_SAMP_1 0x00000001
@@ -2170,6 +2362,7 @@ static inline uint32_t A3XX_TEX_SAMP_1_MIN_LOD(float val)
#define REG_A3XX_TEX_CONST_0 0x00000000
#define A3XX_TEX_CONST_0_TILED 0x00000001
+#define A3XX_TEX_CONST_0_SRGB 0x00000004
#define A3XX_TEX_CONST_0_SWIZ_X__MASK 0x00000070
#define A3XX_TEX_CONST_0_SWIZ_X__SHIFT 4
static inline uint32_t A3XX_TEX_CONST_0_SWIZ_X(enum a3xx_tex_swiz val)
@@ -2206,6 +2399,7 @@ static inline uint32_t A3XX_TEX_CONST_0_FMT(enum a3xx_tex_fmt val)
{
return ((val) << A3XX_TEX_CONST_0_FMT__SHIFT) & A3XX_TEX_CONST_0_FMT__MASK;
}
+#define A3XX_TEX_CONST_0_NOCONVERT 0x20000000
#define A3XX_TEX_CONST_0_TYPE__MASK 0xc0000000
#define A3XX_TEX_CONST_0_TYPE__SHIFT 30
static inline uint32_t A3XX_TEX_CONST_0_TYPE(enum a3xx_tex_type val)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 942e09d898a8..2773600c9488 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -392,13 +392,10 @@ static const unsigned int a3xx_registers[] = {
#ifdef CONFIG_DEBUG_FS
static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
{
- struct drm_device *dev = gpu->dev;
int i;
adreno_show(gpu, m);
- mutex_lock(&dev->struct_mutex);
-
gpu->funcs->pm_resume(gpu);
seq_printf(m, "status: %08x\n",
@@ -418,8 +415,6 @@ static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
}
gpu->funcs->pm_suspend(gpu);
-
- mutex_unlock(&dev->struct_mutex);
}
#endif
@@ -685,6 +680,8 @@ static int a3xx_remove(struct platform_device *pdev)
}
static const struct of_device_id dt_match[] = {
+ { .compatible = "qcom,adreno-3xx" },
+ /* for backwards compat w/ downstream kgsl DT files: */
{ .compatible = "qcom,kgsl-3d0" },
{}
};
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
index bb9a8ca0507b..85ff66cbddd6 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.h
@@ -19,6 +19,11 @@
#define __A3XX_GPU_H__
#include "adreno_gpu.h"
+
+/* arrg, somehow fb.h is getting pulled in: */
+#undef ROP_COPY
+#undef ROP_XOR
+
#include "a3xx.xml.h"
struct a3xx_gpu {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index d6e6ce2d1abd..9de19ac2e86c 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -87,15 +87,6 @@ enum adreno_rb_blend_factor {
FACTOR_SRC_ALPHA_SATURATE = 16,
};
-enum adreno_rb_blend_opcode {
- BLEND_DST_PLUS_SRC = 0,
- BLEND_SRC_MINUS_DST = 1,
- BLEND_MIN_DST_SRC = 2,
- BLEND_MAX_DST_SRC = 3,
- BLEND_DST_MINUS_SRC = 4,
- BLEND_DST_PLUS_SRC_BIAS = 5,
-};
-
enum adreno_rb_surface_endian {
ENDIAN_NONE = 0,
ENDIAN_8IN16 = 1,
@@ -116,6 +107,39 @@ enum adreno_rb_depth_format {
DEPTHX_24_8 = 1,
};
+enum adreno_rb_copy_control_mode {
+ RB_COPY_RESOLVE = 1,
+ RB_COPY_CLEAR = 2,
+ RB_COPY_DEPTH_STENCIL = 5,
+};
+
+enum a3xx_render_mode {
+ RB_RENDERING_PASS = 0,
+ RB_TILING_PASS = 1,
+ RB_RESOLVE_PASS = 2,
+ RB_COMPUTE_PASS = 3,
+};
+
+enum a3xx_msaa_samples {
+ MSAA_ONE = 0,
+ MSAA_TWO = 1,
+ MSAA_FOUR = 2,
+};
+
+enum a3xx_threadmode {
+ MULTI = 0,
+ SINGLE = 1,
+};
+
+enum a3xx_instrbuffermode {
+ BUFFER = 1,
+};
+
+enum a3xx_threadsize {
+ TWO_QUADS = 0,
+ FOUR_QUADS = 1,
+};
+
#define REG_AXXX_CP_RB_BASE 0x000001c0
#define REG_AXXX_CP_RB_CNTL 0x000001c1
@@ -264,6 +288,8 @@ static inline uint32_t AXXX_SCRATCH_UMSK_SWAP(uint32_t val)
#define REG_AXXX_CP_INT_ACK 0x000001f4
#define REG_AXXX_CP_ME_CNTL 0x000001f6
+#define AXXX_CP_ME_CNTL_BUSY 0x20000000
+#define AXXX_CP_ME_CNTL_HALT 0x10000000
#define REG_AXXX_CP_ME_STATUS 0x000001f7
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 28ca8cd8b09e..655ce5b14ad0 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -91,9 +91,17 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
int adreno_hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ int ret;
DBG("%s", gpu->name);
+ ret = msm_gem_get_iova(gpu->rb->bo, gpu->id, &gpu->rb_iova);
+ if (ret) {
+ gpu->rb_iova = 0;
+ dev_err(gpu->dev->dev, "could not map ringbuffer: %d\n", ret);
+ return ret;
+ }
+
/* Setup REG_CP_RB_CNTL: */
gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
/* size is log2(quad-words): */
@@ -362,8 +370,10 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret;
}
+ mutex_lock(&drm->struct_mutex);
gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs),
MSM_BO_UNCACHED);
+ mutex_unlock(&drm->struct_mutex);
if (IS_ERR(gpu->memptrs_bo)) {
ret = PTR_ERR(gpu->memptrs_bo);
gpu->memptrs_bo = NULL;
@@ -371,13 +381,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret;
}
- gpu->memptrs = msm_gem_vaddr_locked(gpu->memptrs_bo);
+ gpu->memptrs = msm_gem_vaddr(gpu->memptrs_bo);
if (!gpu->memptrs) {
dev_err(drm->dev, "could not vmap memptrs\n");
return -ENOMEM;
}
- ret = msm_gem_get_iova_locked(gpu->memptrs_bo, gpu->base.id,
+ ret = msm_gem_get_iova(gpu->memptrs_bo, gpu->base.id,
&gpu->memptrs_iova);
if (ret) {
dev_err(drm->dev, "could not map memptrs: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index ae992c71703f..4eee0ec8f069 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -10,13 +10,13 @@ git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml ( 364 bytes, from 2013-11-30 14:47:15)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32814 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 8900 bytes, from 2013-10-22 23:57:49)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 10574 bytes, from 2013-11-13 05:44:45)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 53644 bytes, from 2013-11-30 15:07:33)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 8344 bytes, from 2013-11-30 14:49:47)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 9859 bytes, from 2014-06-02 15:21:30)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14477 bytes, from 2014-05-16 11:51:57)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 58020 bytes, from 2014-06-25 12:57:16)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 26602 bytes, from 2014-06-25 12:57:16)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -105,6 +105,7 @@ enum pc_di_index_size {
enum pc_di_vis_cull_mode {
IGNORE_VISIBILITY = 0,
+ USE_VISIBILITY = 1,
};
enum adreno_pm4_packet_type {
@@ -163,6 +164,11 @@ enum adreno_pm4_type3_packets {
CP_SET_BIN = 76,
CP_TEST_TWO_MEMS = 113,
CP_WAIT_FOR_ME = 19,
+ CP_SET_DRAW_STATE = 67,
+ CP_DRAW_INDX_OFFSET = 56,
+ CP_DRAW_INDIRECT = 40,
+ CP_DRAW_INDX_INDIRECT = 41,
+ CP_DRAW_AUTO = 36,
IN_IB_PREFETCH_END = 23,
IN_SUBBLK_PREFETCH = 31,
IN_INSTR_PREFETCH = 32,
@@ -232,6 +238,211 @@ static inline uint32_t CP_LOAD_STATE_1_EXT_SRC_ADDR(uint32_t val)
return ((val >> 2) << CP_LOAD_STATE_1_EXT_SRC_ADDR__SHIFT) & CP_LOAD_STATE_1_EXT_SRC_ADDR__MASK;
}
+#define REG_CP_DRAW_INDX_0 0x00000000
+#define CP_DRAW_INDX_0_VIZ_QUERY__MASK 0xffffffff
+#define CP_DRAW_INDX_0_VIZ_QUERY__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_0_VIZ_QUERY(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_0_VIZ_QUERY__MASK;
+}
+
+#define REG_CP_DRAW_INDX_1 0x00000001
+#define CP_DRAW_INDX_1_PRIM_TYPE__MASK 0x0000003f
+#define CP_DRAW_INDX_1_PRIM_TYPE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_1_PRIM_TYPE(enum pc_di_primtype val)
+{
+ return ((val) << CP_DRAW_INDX_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_1_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_1_SOURCE_SELECT__MASK 0x000000c0
+#define CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT 6
+static inline uint32_t CP_DRAW_INDX_1_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+ return ((val) << CP_DRAW_INDX_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_1_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_1_VIS_CULL__MASK 0x00000600
+#define CP_DRAW_INDX_1_VIS_CULL__SHIFT 9
+static inline uint32_t CP_DRAW_INDX_1_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << CP_DRAW_INDX_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_1_VIS_CULL__MASK;
+}
+#define CP_DRAW_INDX_1_INDEX_SIZE__MASK 0x00000800
+#define CP_DRAW_INDX_1_INDEX_SIZE__SHIFT 11
+static inline uint32_t CP_DRAW_INDX_1_INDEX_SIZE(enum pc_di_index_size val)
+{
+ return ((val) << CP_DRAW_INDX_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_1_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_1_NOT_EOP 0x00001000
+#define CP_DRAW_INDX_1_SMALL_INDEX 0x00002000
+#define CP_DRAW_INDX_1_PRE_DRAW_INITIATOR_ENABLE 0x00004000
+#define CP_DRAW_INDX_1_NUM_INDICES__MASK 0xffff0000
+#define CP_DRAW_INDX_1_NUM_INDICES__SHIFT 16
+static inline uint32_t CP_DRAW_INDX_1_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_1_NUM_INDICES__SHIFT) & CP_DRAW_INDX_1_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2 0x00000002
+#define CP_DRAW_INDX_2_NUM_INDICES__MASK 0xffffffff
+#define CP_DRAW_INDX_2_NUM_INDICES__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2 0x00000002
+#define CP_DRAW_INDX_2_INDX_BASE__MASK 0xffffffff
+#define CP_DRAW_INDX_2_INDX_BASE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_INDX_BASE(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_INDX_BASE__SHIFT) & CP_DRAW_INDX_2_INDX_BASE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2 0x00000002
+#define CP_DRAW_INDX_2_INDX_SIZE__MASK 0xffffffff
+#define CP_DRAW_INDX_2_INDX_SIZE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_INDX_SIZE(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_INDX_SIZE__SHIFT) & CP_DRAW_INDX_2_INDX_SIZE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_0 0x00000000
+#define CP_DRAW_INDX_2_0_VIZ_QUERY__MASK 0xffffffff
+#define CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_0_VIZ_QUERY(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_0_VIZ_QUERY__SHIFT) & CP_DRAW_INDX_2_0_VIZ_QUERY__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_1 0x00000001
+#define CP_DRAW_INDX_2_1_PRIM_TYPE__MASK 0x0000003f
+#define CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_1_PRIM_TYPE(enum pc_di_primtype val)
+{
+ return ((val) << CP_DRAW_INDX_2_1_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_2_1_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK 0x000000c0
+#define CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT 6
+static inline uint32_t CP_DRAW_INDX_2_1_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+ return ((val) << CP_DRAW_INDX_2_1_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_2_1_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_2_1_VIS_CULL__MASK 0x00000600
+#define CP_DRAW_INDX_2_1_VIS_CULL__SHIFT 9
+static inline uint32_t CP_DRAW_INDX_2_1_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << CP_DRAW_INDX_2_1_VIS_CULL__SHIFT) & CP_DRAW_INDX_2_1_VIS_CULL__MASK;
+}
+#define CP_DRAW_INDX_2_1_INDEX_SIZE__MASK 0x00000800
+#define CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT 11
+static inline uint32_t CP_DRAW_INDX_2_1_INDEX_SIZE(enum pc_di_index_size val)
+{
+ return ((val) << CP_DRAW_INDX_2_1_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_2_1_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_2_1_NOT_EOP 0x00001000
+#define CP_DRAW_INDX_2_1_SMALL_INDEX 0x00002000
+#define CP_DRAW_INDX_2_1_PRE_DRAW_INITIATOR_ENABLE 0x00004000
+#define CP_DRAW_INDX_2_1_NUM_INDICES__MASK 0xffff0000
+#define CP_DRAW_INDX_2_1_NUM_INDICES__SHIFT 16
+static inline uint32_t CP_DRAW_INDX_2_1_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_1_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_1_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_2_2 0x00000002
+#define CP_DRAW_INDX_2_2_NUM_INDICES__MASK 0xffffffff
+#define CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_2_2_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_2_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_2_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_0 0x00000000
+#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK 0x0000003f
+#define CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_PRIM_TYPE(enum pc_di_primtype val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__SHIFT) & CP_DRAW_INDX_OFFSET_0_PRIM_TYPE__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK 0x000000c0
+#define CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT 6
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK 0x00000700
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT 8
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT) & CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000800
+#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 11
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum pc_di_index_size val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
+}
+#define CP_DRAW_INDX_OFFSET_0_NOT_EOP 0x00001000
+#define CP_DRAW_INDX_OFFSET_0_SMALL_INDEX 0x00002000
+#define CP_DRAW_INDX_OFFSET_0_PRE_DRAW_INITIATOR_ENABLE 0x00004000
+#define CP_DRAW_INDX_OFFSET_0_NUM_INDICES__MASK 0xffff0000
+#define CP_DRAW_INDX_OFFSET_0_NUM_INDICES__SHIFT 16
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_NUM_INDICES__SHIFT) & CP_DRAW_INDX_OFFSET_0_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_1 0x00000001
+
+#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002
+#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK 0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_NUM_INDICES(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_2_NUM_INDICES__SHIFT) & CP_DRAW_INDX_OFFSET_2_NUM_INDICES__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002
+#define CP_DRAW_INDX_OFFSET_2_INDX_BASE__MASK 0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_INDX_BASE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_INDX_BASE(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_2_INDX_BASE__SHIFT) & CP_DRAW_INDX_OFFSET_2_INDX_BASE__MASK;
+}
+
+#define REG_CP_DRAW_INDX_OFFSET_2 0x00000002
+#define CP_DRAW_INDX_OFFSET_2_INDX_SIZE__MASK 0xffffffff
+#define CP_DRAW_INDX_OFFSET_2_INDX_SIZE__SHIFT 0
+static inline uint32_t CP_DRAW_INDX_OFFSET_2_INDX_SIZE(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_2_INDX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_2_INDX_SIZE__MASK;
+}
+
+#define REG_CP_SET_DRAW_STATE_0 0x00000000
+#define CP_SET_DRAW_STATE_0_COUNT__MASK 0x0000ffff
+#define CP_SET_DRAW_STATE_0_COUNT__SHIFT 0
+static inline uint32_t CP_SET_DRAW_STATE_0_COUNT(uint32_t val)
+{
+ return ((val) << CP_SET_DRAW_STATE_0_COUNT__SHIFT) & CP_SET_DRAW_STATE_0_COUNT__MASK;
+}
+#define CP_SET_DRAW_STATE_0_DIRTY 0x00010000
+#define CP_SET_DRAW_STATE_0_DISABLE 0x00020000
+#define CP_SET_DRAW_STATE_0_DISABLE_ALL_GROUPS 0x00040000
+#define CP_SET_DRAW_STATE_0_LOAD_IMMED 0x00080000
+#define CP_SET_DRAW_STATE_0_GROUP_ID__MASK 0x1f000000
+#define CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT 24
+static inline uint32_t CP_SET_DRAW_STATE_0_GROUP_ID(uint32_t val)
+{
+ return ((val) << CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE_0_GROUP_ID__MASK;
+}
+
+#define REG_CP_SET_DRAW_STATE_1 0x00000001
+#define CP_SET_DRAW_STATE_1_ADDR__MASK 0xffffffff
+#define CP_SET_DRAW_STATE_1_ADDR__SHIFT 0
+static inline uint32_t CP_SET_DRAW_STATE_1_ADDR(uint32_t val)
+{
+ return ((val) << CP_SET_DRAW_STATE_1_ADDR__SHIFT) & CP_SET_DRAW_STATE_1_ADDR__MASK;
+}
+
#define REG_CP_SET_BIN_0 0x00000000
#define REG_CP_SET_BIN_1 0x00000001
@@ -262,5 +473,21 @@ static inline uint32_t CP_SET_BIN_2_Y2(uint32_t val)
return ((val) << CP_SET_BIN_2_Y2__SHIFT) & CP_SET_BIN_2_Y2__MASK;
}
+#define REG_CP_SET_BIN_DATA_0 0x00000000
+#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK 0xffffffff
+#define CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT 0
+static inline uint32_t CP_SET_BIN_DATA_0_BIN_DATA_ADDR(uint32_t val)
+{
+ return ((val) << CP_SET_BIN_DATA_0_BIN_DATA_ADDR__SHIFT) & CP_SET_BIN_DATA_0_BIN_DATA_ADDR__MASK;
+}
+
+#define REG_CP_SET_BIN_DATA_1 0x00000001
+#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK 0xffffffff
+#define CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT 0
+static inline uint32_t CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS(uint32_t val)
+{
+ return ((val) << CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__SHIFT) & CP_SET_BIN_DATA_1_BIN_SIZE_ADDRESS__MASK;
+}
+
#endif /* ADRENO_PM4_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 87be647e3825..0f1f5b9459a5 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 747a6ef4211f..d468f86f637c 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 48e03acf19bf..da8740054cdf 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 7f7aadef8a82..a125a7e32742 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -123,7 +123,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
for (i = 0; i < config->hpd_reg_cnt; i++) {
struct regulator *reg;
- reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]);
+ reg = devm_regulator_get_exclusive(&pdev->dev,
+ config->hpd_reg_names[i]);
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
@@ -138,7 +139,8 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
for (i = 0; i < config->pwr_reg_cnt; i++) {
struct regulator *reg;
- reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]);
+ reg = devm_regulator_get_exclusive(&pdev->dev,
+ config->pwr_reg_names[i]);
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
@@ -266,37 +268,56 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
{
int gpio = of_get_named_gpio(of_node, name, 0);
if (gpio < 0) {
- dev_err(dev, "failed to get gpio: %s (%d)\n",
- name, gpio);
- gpio = -1;
+ char name2[32];
+ snprintf(name2, sizeof(name2), "%s-gpio", name);
+ gpio = of_get_named_gpio(of_node, name2, 0);
+ if (gpio < 0) {
+ dev_err(dev, "failed to get gpio: %s (%d)\n",
+ name, gpio);
+ gpio = -1;
+ }
}
return gpio;
}
- /* TODO actually use DT.. */
- static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
- static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
- static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
- static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
- static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+ if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) {
+ static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
+ static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
+ static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
+ static unsigned long hpd_clk_freq[] = {0, 19200000, 0};
+ static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+ config.phy_init = hdmi_phy_8x74_init;
+ config.hpd_reg_names = hpd_reg_names;
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
+ config.pwr_reg_names = pwr_reg_names;
+ config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names);
+ config.hpd_clk_names = hpd_clk_names;
+ config.hpd_freq = hpd_clk_freq;
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
+ config.pwr_clk_names = pwr_clk_names;
+ config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
+ config.shared_irq = true;
+ } else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8960")) {
+ static const char *hpd_clk_names[] = {"core_clk", "master_iface_clk", "slave_iface_clk"};
+ static const char *hpd_reg_names[] = {"core-vdda", "hdmi-mux"};
+ config.phy_init = hdmi_phy_8960_init;
+ config.hpd_reg_names = hpd_reg_names;
+ config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
+ config.hpd_clk_names = hpd_clk_names;
+ config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
+ } else if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8660")) {
+ config.phy_init = hdmi_phy_8x60_init;
+ } else {
+ dev_err(dev, "unknown phy: %s\n", of_node->name);
+ }
- config.phy_init = hdmi_phy_8x74_init;
config.mmio_name = "core_physical";
- config.hpd_reg_names = hpd_reg_names;
- config.hpd_reg_cnt = ARRAY_SIZE(hpd_reg_names);
- config.pwr_reg_names = pwr_reg_names;
- config.pwr_reg_cnt = ARRAY_SIZE(pwr_reg_names);
- config.hpd_clk_names = hpd_clk_names;
- config.hpd_freq = hpd_clk_freq;
- config.hpd_clk_cnt = ARRAY_SIZE(hpd_clk_names);
- config.pwr_clk_names = pwr_clk_names;
- config.pwr_clk_cnt = ARRAY_SIZE(pwr_clk_names);
config.ddc_clk_gpio = get_gpio("qcom,hdmi-tx-ddc-clk");
config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
config.hpd_gpio = get_gpio("qcom,hdmi-tx-hpd");
config.mux_en_gpio = get_gpio("qcom,hdmi-tx-mux-en");
config.mux_sel_gpio = get_gpio("qcom,hdmi-tx-mux-sel");
- config.shared_irq = true;
+ config.mux_lpm_gpio = get_gpio("qcom,hdmi-tx-mux-lpm");
#else
static const char *hpd_clk_names[] = {
@@ -373,7 +394,9 @@ static int hdmi_dev_remove(struct platform_device *pdev)
}
static const struct of_device_id dt_match[] = {
- { .compatible = "qcom,hdmi-tx" },
+ { .compatible = "qcom,hdmi-tx-8074" },
+ { .compatible = "qcom,hdmi-tx-8960" },
+ { .compatible = "qcom,hdmi-tx-8660" },
{}
};
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 9d7723c6528a..b981995410b5 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -96,6 +96,7 @@ struct hdmi_platform_config {
/* gpio's: */
int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
+ int mux_lpm_gpio;
/* older devices had their own irq, mdp5+ it is shared w/ mdp: */
bool shared_irq;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index e2636582cfd7..e89fe053d375 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -12,14 +12,14 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -148,9 +148,9 @@ static inline uint32_t REG_HDMI_GENERIC0(uint32_t i0) { return 0x00000088 + 0x4*
static inline uint32_t REG_HDMI_GENERIC1(uint32_t i0) { return 0x000000a8 + 0x4*i0; }
-static inline uint32_t REG_HDMI_ACR(uint32_t i0) { return 0x000000c4 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
-static inline uint32_t REG_HDMI_ACR_0(uint32_t i0) { return 0x000000c4 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR_0(enum hdmi_acr_cts i0) { return 0x000000c4 + 0x8*i0; }
#define HDMI_ACR_0_CTS__MASK 0xfffff000
#define HDMI_ACR_0_CTS__SHIFT 12
static inline uint32_t HDMI_ACR_0_CTS(uint32_t val)
@@ -158,7 +158,7 @@ static inline uint32_t HDMI_ACR_0_CTS(uint32_t val)
return ((val) << HDMI_ACR_0_CTS__SHIFT) & HDMI_ACR_0_CTS__MASK;
}
-static inline uint32_t REG_HDMI_ACR_1(uint32_t i0) { return 0x000000c8 + 0x8*i0; }
+static inline uint32_t REG_HDMI_ACR_1(enum hdmi_acr_cts i0) { return 0x000000c8 + 0x8*i0; }
#define HDMI_ACR_1_N__MASK 0xffffffff
#define HDMI_ACR_1_N__SHIFT 0
static inline uint32_t HDMI_ACR_1_N(uint32_t val)
@@ -552,6 +552,103 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
#define REG_HDMI_8960_PHY_REG11 0x0000042c
#define REG_HDMI_8960_PHY_REG12 0x00000430
+#define HDMI_8960_PHY_REG12_SW_RESET 0x00000020
+#define HDMI_8960_PHY_REG12_PWRDN_B 0x00000080
+
+#define REG_HDMI_8960_PHY_REG_BIST_CFG 0x00000434
+
+#define REG_HDMI_8960_PHY_DEBUG_BUS_SEL 0x00000438
+
+#define REG_HDMI_8960_PHY_REG_MISC0 0x0000043c
+
+#define REG_HDMI_8960_PHY_REG13 0x00000440
+
+#define REG_HDMI_8960_PHY_REG14 0x00000444
+
+#define REG_HDMI_8960_PHY_REG15 0x00000448
+
+#define REG_HDMI_8960_PHY_PLL_REFCLK_CFG 0x00000500
+
+#define REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG 0x00000504
+
+#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 0x00000508
+
+#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 0x0000050c
+
+#define REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG 0x00000510
+
+#define REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG 0x00000514
+
+#define REG_HDMI_8960_PHY_PLL_PWRDN_B 0x00000518
+#define HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL 0x00000002
+#define HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B 0x00000008
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG0 0x0000051c
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG1 0x00000520
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG2 0x00000524
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG3 0x00000528
+
+#define REG_HDMI_8960_PHY_PLL_SDM_CFG4 0x0000052c
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG0 0x00000530
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG1 0x00000534
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG2 0x00000538
+
+#define REG_HDMI_8960_PHY_PLL_SSC_CFG3 0x0000053c
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 0x00000540
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 0x00000544
+
+#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 0x00000548
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 0x0000054c
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 0x00000550
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 0x00000554
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 0x00000558
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 0x0000055c
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 0x00000560
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 0x00000564
+
+#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 0x00000568
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_SEL 0x0000056c
+
+#define REG_HDMI_8960_PHY_PLL_MISC0 0x00000570
+
+#define REG_HDMI_8960_PHY_PLL_MISC1 0x00000574
+
+#define REG_HDMI_8960_PHY_PLL_MISC2 0x00000578
+
+#define REG_HDMI_8960_PHY_PLL_MISC3 0x0000057c
+
+#define REG_HDMI_8960_PHY_PLL_MISC4 0x00000580
+
+#define REG_HDMI_8960_PHY_PLL_MISC5 0x00000584
+
+#define REG_HDMI_8960_PHY_PLL_MISC6 0x00000588
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS0 0x0000058c
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS1 0x00000590
+
+#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS2 0x00000594
+
+#define REG_HDMI_8960_PHY_PLL_STATUS0 0x00000598
+#define HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK 0x00000001
+
+#define REG_HDMI_8960_PHY_PLL_STATUS1 0x0000059c
#define REG_HDMI_8x74_ANA_CFG0 0x00000000
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index 28f7e3ec6c28..4aca2a3c667c 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -63,7 +63,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
if (ret) {
dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
- "HDMI_MUX_SEL", config->mux_en_gpio, ret);
+ "HDMI_MUX_EN", config->mux_en_gpio, ret);
goto error4;
}
gpio_set_value_cansleep(config->mux_en_gpio, 1);
@@ -78,6 +78,19 @@ static int gpio_config(struct hdmi *hdmi, bool on)
}
gpio_set_value_cansleep(config->mux_sel_gpio, 0);
}
+
+ if (config->mux_lpm_gpio != -1) {
+ ret = gpio_request(config->mux_lpm_gpio,
+ "HDMI_MUX_LPM");
+ if (ret) {
+ dev_err(dev->dev,
+ "'%s'(%d) gpio_request failed: %d\n",
+ "HDMI_MUX_LPM",
+ config->mux_lpm_gpio, ret);
+ goto error6;
+ }
+ gpio_set_value_cansleep(config->mux_lpm_gpio, 1);
+ }
DBG("gpio on");
} else {
gpio_free(config->ddc_clk_gpio);
@@ -93,11 +106,19 @@ static int gpio_config(struct hdmi *hdmi, bool on)
gpio_set_value_cansleep(config->mux_sel_gpio, 1);
gpio_free(config->mux_sel_gpio);
}
+
+ if (config->mux_lpm_gpio != -1) {
+ gpio_set_value_cansleep(config->mux_lpm_gpio, 0);
+ gpio_free(config->mux_lpm_gpio);
+ }
DBG("gpio off");
}
return 0;
+error6:
+ if (config->mux_sel_gpio != -1)
+ gpio_free(config->mux_sel_gpio);
error5:
if (config->mux_en_gpio != -1)
gpio_free(config->mux_en_gpio);
@@ -306,7 +327,7 @@ static void hdmi_connector_destroy(struct drm_connector *connector)
hdp_disable(hdmi_connector);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
hdmi_unreference(hdmi_connector->hdmi);
@@ -416,7 +437,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
ret = hpd_enable(hdmi_connector);
if (ret) {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
index e5b7ed5b8f01..902d7685d441 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
@@ -15,13 +15,370 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
#include "hdmi.h"
struct hdmi_phy_8960 {
struct hdmi_phy base;
struct hdmi *hdmi;
+ struct clk_hw pll_hw;
+ struct clk *pll;
+ unsigned long pixclk;
};
#define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
+#define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
+
+/*
+ * HDMI PLL:
+ *
+ * To get the parent clock setup properly, we need to plug in hdmi pll
+ * configuration into common-clock-framework.
+ */
+
+struct pll_rate {
+ unsigned long rate;
+ struct {
+ uint32_t val;
+ uint32_t reg;
+ } conf[32];
+};
+
+/* NOTE: keep sorted highest freq to lowest: */
+static const struct pll_rate freqtbl[] = {
+ /* 1080p60/1080p50 case */
+ { 148500000, {
+ { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+ { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
+ { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+ { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
+ { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
+ { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
+ { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
+ { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
+ { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
+ { 0, 0 } }
+ },
+ { 108000000, {
+ { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0, 0 } }
+ },
+ /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */
+ { 74250000, {
+ { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
+ { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0, 0 } }
+ },
+ { 65000000, {
+ { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0, 0 } }
+ },
+ /* 480p60/480i60 */
+ { 27030000, {
+ { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
+ { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+ { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
+ { 0, 0 } }
+ },
+ /* 576p50/576i50 */
+ { 27000000, {
+ { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+ { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
+ { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+ { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
+ { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
+ { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
+ { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
+ { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
+ { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
+ { 0, 0 } }
+ },
+ /* 640x480p60 */
+ { 25200000, {
+ { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG },
+ { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG },
+ { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 },
+ { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG },
+ { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG },
+ { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B },
+ { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 },
+ { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 },
+ { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 },
+ { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 },
+ { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 },
+ { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 },
+ { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 },
+ { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 },
+ { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 },
+ { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 },
+ { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 },
+ { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 },
+ { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 },
+ { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 },
+ { 0, 0 } }
+ },
+};
+
+static int hdmi_pll_enable(struct clk_hw *hw)
+{
+ struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+ struct hdmi *hdmi = phy_8960->hdmi;
+ int timeout_count, pll_lock_retry = 10;
+ unsigned int val;
+
+ DBG("");
+
+ /* Assert PLL S/W reset */
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10);
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a);
+
+ /* Wait for a short time before de-asserting
+ * to allow the hardware to complete its job.
+ * This much of delay should be fine for hardware
+ * to assert and de-assert.
+ */
+ udelay(10);
+
+ /* De-assert PLL S/W reset */
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
+
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+ val |= HDMI_8960_PHY_REG12_SW_RESET;
+ /* Assert PHY S/W reset */
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+ val &= ~HDMI_8960_PHY_REG12_SW_RESET;
+ /* Wait for a short time before de-asserting
+ to allow the hardware to complete its job.
+ This much of delay should be fine for hardware
+ to assert and de-assert. */
+ udelay(10);
+ /* De-assert PHY S/W reset */
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x3f);
+
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+ val |= HDMI_8960_PHY_REG12_PWRDN_B;
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+ /* Wait 10 us for enabling global power for PHY */
+ mb();
+ udelay(10);
+
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
+ val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B;
+ val &= ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL;
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x80);
+
+ timeout_count = 1000;
+ while (--pll_lock_retry > 0) {
+
+ /* are we there yet? */
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_STATUS0);
+ if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK)
+ break;
+
+ udelay(1);
+
+ if (--timeout_count > 0)
+ continue;
+
+ /*
+ * PLL has still not locked.
+ * Do a software reset and try again
+ * Assert PLL S/W reset first
+ */
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d);
+ udelay(10);
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d);
+
+ /*
+ * Wait for a short duration for the PLL calibration
+ * before checking if the PLL gets locked
+ */
+ udelay(350);
+
+ timeout_count = 1000;
+ }
+
+ return 0;
+}
+
+static void hdmi_pll_disable(struct clk_hw *hw)
+{
+ struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+ struct hdmi *hdmi = phy_8960->hdmi;
+ unsigned int val;
+
+ DBG("");
+
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_REG12);
+ val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG12, val);
+
+ val = hdmi_read(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B);
+ val |= HDMI_8960_PHY_REG12_SW_RESET;
+ val &= ~HDMI_8960_PHY_REG12_PWRDN_B;
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_PLL_PWRDN_B, val);
+ /* Make sure HDMI PHY/PLL are powered down */
+ mb();
+}
+
+static const struct pll_rate *find_rate(unsigned long rate)
+{
+ int i;
+ for (i = 1; i < ARRAY_SIZE(freqtbl); i++)
+ if (rate > freqtbl[i].rate)
+ return &freqtbl[i-1];
+ return &freqtbl[i-1];
+}
+
+static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+ return phy_8960->pixclk;
+}
+
+static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ const struct pll_rate *pll_rate = find_rate(rate);
+ return pll_rate->rate;
+}
+
+static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct hdmi_phy_8960 *phy_8960 = clk_to_phy(hw);
+ struct hdmi *hdmi = phy_8960->hdmi;
+ const struct pll_rate *pll_rate = find_rate(rate);
+ int i;
+
+ DBG("rate=%lu", rate);
+
+ for (i = 0; pll_rate->conf[i].reg; i++)
+ hdmi_write(hdmi, pll_rate->conf[i].reg, pll_rate->conf[i].val);
+
+ phy_8960->pixclk = rate;
+
+ return 0;
+}
+
+
+static const struct clk_ops hdmi_pll_ops = {
+ .enable = hdmi_pll_enable,
+ .disable = hdmi_pll_disable,
+ .recalc_rate = hdmi_pll_recalc_rate,
+ .round_rate = hdmi_pll_round_rate,
+ .set_rate = hdmi_pll_set_rate,
+};
+
+static const char *hdmi_pll_parents[] = {
+ "pxo",
+};
+
+static struct clk_init_data pll_init = {
+ .name = "hdmi_pll",
+ .ops = &hdmi_pll_ops,
+ .parent_names = hdmi_pll_parents,
+ .num_parents = ARRAY_SIZE(hdmi_pll_parents),
+};
+
+
+/*
+ * HDMI Phy:
+ */
static void hdmi_phy_8960_destroy(struct hdmi_phy *phy)
{
@@ -86,6 +443,9 @@ static void hdmi_phy_8960_powerup(struct hdmi_phy *phy,
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
struct hdmi *hdmi = phy_8960->hdmi;
+ DBG("pixclock: %lu", pixclock);
+
+ hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x00);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2);
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00);
@@ -104,6 +464,8 @@ static void hdmi_phy_8960_powerdown(struct hdmi_phy *phy)
struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
struct hdmi *hdmi = phy_8960->hdmi;
+ DBG("");
+
hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f);
}
@@ -118,7 +480,12 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
{
struct hdmi_phy_8960 *phy_8960;
struct hdmi_phy *phy = NULL;
- int ret;
+ int ret, i;
+
+ /* sanity check: */
+ for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
+ if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate))
+ return ERR_PTR(-EINVAL);
phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
if (!phy_8960) {
@@ -132,6 +499,14 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
phy_8960->hdmi = hdmi;
+ phy_8960->pll_hw.init = &pll_init;
+ phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw);
+ if (IS_ERR(phy_8960->pll)) {
+ ret = PTR_ERR(phy_8960->pll);
+ phy_8960->pll = NULL;
+ goto fail;
+ }
+
return phy;
fail:
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index d591567173c4..bd81db6a7829 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 416a26e1e58d..122208e8a2ee 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index 0bb4faa17523..733646c0d3f8 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -147,7 +147,7 @@ static void mdp4_destroy(struct msm_kms *kms)
if (mdp4_kms->blank_cursor_iova)
msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
if (mdp4_kms->blank_cursor_bo)
- drm_gem_object_unreference(mdp4_kms->blank_cursor_bo);
+ drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo);
kfree(mdp4_kms);
}
@@ -176,6 +176,8 @@ int mdp4_disable(struct mdp4_kms *mdp4_kms)
if (mdp4_kms->pclk)
clk_disable_unprepare(mdp4_kms->pclk);
clk_disable_unprepare(mdp4_kms->lut_clk);
+ if (mdp4_kms->axi_clk)
+ clk_disable_unprepare(mdp4_kms->axi_clk);
return 0;
}
@@ -188,6 +190,8 @@ int mdp4_enable(struct mdp4_kms *mdp4_kms)
if (mdp4_kms->pclk)
clk_prepare_enable(mdp4_kms->pclk);
clk_prepare_enable(mdp4_kms->lut_clk);
+ if (mdp4_kms->axi_clk)
+ clk_prepare_enable(mdp4_kms->axi_clk);
return 0;
}
@@ -294,15 +298,17 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
goto fail;
}
- mdp4_kms->dsi_pll_vdda = devm_regulator_get(&pdev->dev, "dsi_pll_vdda");
+ mdp4_kms->dsi_pll_vdda =
+ devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda");
if (IS_ERR(mdp4_kms->dsi_pll_vdda))
mdp4_kms->dsi_pll_vdda = NULL;
- mdp4_kms->dsi_pll_vddio = devm_regulator_get(&pdev->dev, "dsi_pll_vddio");
+ mdp4_kms->dsi_pll_vddio =
+ devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio");
if (IS_ERR(mdp4_kms->dsi_pll_vddio))
mdp4_kms->dsi_pll_vddio = NULL;
- mdp4_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
+ mdp4_kms->vdd = devm_regulator_get_exclusive(&pdev->dev, "vdd");
if (IS_ERR(mdp4_kms->vdd))
mdp4_kms->vdd = NULL;
@@ -333,6 +339,13 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
goto fail;
}
+ mdp4_kms->axi_clk = devm_clk_get(&pdev->dev, "mdp_axi_clk");
+ if (IS_ERR(mdp4_kms->axi_clk)) {
+ dev_err(dev->dev, "failed to get axi_clk\n");
+ ret = PTR_ERR(mdp4_kms->axi_clk);
+ goto fail;
+ }
+
clk_set_rate(mdp4_kms->clk, config->max_clk);
clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
@@ -348,7 +361,7 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
mdelay(16);
if (config->iommu) {
- mmu = msm_iommu_new(dev, config->iommu);
+ mmu = msm_iommu_new(&pdev->dev, config->iommu);
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
goto fail;
@@ -406,6 +419,8 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
static struct mdp4_platform_config config = {};
#ifdef CONFIG_OF
/* TODO */
+ config.max_clk = 266667000;
+ config.iommu = iommu_domain_alloc(&platform_bus_type);
#else
if (cpu_is_apq8064())
config.max_clk = 266667000;
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 715520c54cde..3225da804c61 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -42,6 +42,7 @@ struct mdp4_kms {
struct clk *clk;
struct clk *pclk;
struct clk *lut_clk;
+ struct clk *axi_clk;
struct mdp_irq error_handler;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index 0aa51517f826..67f4f896ba8c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -12,14 +12,14 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
-Copyright (C) 2013 by the following authors:
+Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -68,6 +68,8 @@ enum mdp5_pipe {
SSPP_RGB2 = 5,
SSPP_DMA0 = 6,
SSPP_DMA1 = 7,
+ SSPP_VIG3 = 8,
+ SSPP_RGB3 = 9,
};
enum mdp5_ctl_mode {
@@ -126,7 +128,11 @@ enum mdp5_client_id {
CID_RGB0 = 16,
CID_RGB1 = 17,
CID_RGB2 = 18,
- CID_MAX = 19,
+ CID_VIG3_Y = 19,
+ CID_VIG3_CR = 20,
+ CID_VIG3_CB = 21,
+ CID_RGB3 = 22,
+ CID_MAX = 23,
};
enum mdp5_igc_type {
@@ -299,11 +305,34 @@ static inline uint32_t MDP5_IGC_LUT_REG_VAL(uint32_t val)
#define MDP5_IGC_LUT_REG_DISABLE_PIPE_1 0x20000000
#define MDP5_IGC_LUT_REG_DISABLE_PIPE_2 0x40000000
-static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000600 + 0x100*i0; }
+static inline uint32_t __offset_CTL(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return (mdp5_cfg->ctl.base[0]);
+ case 1: return (mdp5_cfg->ctl.base[1]);
+ case 2: return (mdp5_cfg->ctl.base[2]);
+ case 3: return (mdp5_cfg->ctl.base[3]);
+ case 4: return (mdp5_cfg->ctl.base[4]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000000 + __offset_CTL(i0); }
-static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+static inline uint32_t __offset_LAYER(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return 0x00000000;
+ case 1: return 0x00000004;
+ case 2: return 0x00000008;
+ case 3: return 0x0000000c;
+ case 4: return 0x00000010;
+ case 5: return 0x00000024;
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_CTL(i0) + __offset_LAYER(i1); }
-static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_CTL(i0) + __offset_LAYER(i1); }
#define MDP5_CTL_LAYER_REG_VIG0__MASK 0x00000007
#define MDP5_CTL_LAYER_REG_VIG0__SHIFT 0
static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val)
@@ -354,8 +383,20 @@ static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val)
}
#define MDP5_CTL_LAYER_REG_BORDER_COLOR 0x01000000
#define MDP5_CTL_LAYER_REG_CURSOR_OUT 0x02000000
+#define MDP5_CTL_LAYER_REG_VIG3__MASK 0x1c000000
+#define MDP5_CTL_LAYER_REG_VIG3__SHIFT 26
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG3(enum mdp_mixer_stage_id val)
+{
+ return ((val) << MDP5_CTL_LAYER_REG_VIG3__SHIFT) & MDP5_CTL_LAYER_REG_VIG3__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB3__MASK 0xe0000000
+#define MDP5_CTL_LAYER_REG_RGB3__SHIFT 29
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB3(enum mdp_mixer_stage_id val)
+{
+ return ((val) << MDP5_CTL_LAYER_REG_RGB3__SHIFT) & MDP5_CTL_LAYER_REG_RGB3__MASK;
+}
-static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000614 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000014 + __offset_CTL(i0); }
#define MDP5_CTL_OP_MODE__MASK 0x0000000f
#define MDP5_CTL_OP_MODE__SHIFT 0
static inline uint32_t MDP5_CTL_OP_MODE(enum mdp5_ctl_mode val)
@@ -377,7 +418,7 @@ static inline uint32_t MDP5_CTL_OP_PACK_3D(enum mdp5_pack_3d val)
return ((val) << MDP5_CTL_OP_PACK_3D__SHIFT) & MDP5_CTL_OP_PACK_3D__MASK;
}
-static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000618 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000018 + __offset_CTL(i0); }
#define MDP5_CTL_FLUSH_VIG0 0x00000001
#define MDP5_CTL_FLUSH_VIG1 0x00000002
#define MDP5_CTL_FLUSH_VIG2 0x00000004
@@ -387,26 +428,48 @@ static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000618 + 0x1
#define MDP5_CTL_FLUSH_LM0 0x00000040
#define MDP5_CTL_FLUSH_LM1 0x00000080
#define MDP5_CTL_FLUSH_LM2 0x00000100
+#define MDP5_CTL_FLUSH_LM3 0x00000200
+#define MDP5_CTL_FLUSH_LM4 0x00000400
#define MDP5_CTL_FLUSH_DMA0 0x00000800
#define MDP5_CTL_FLUSH_DMA1 0x00001000
#define MDP5_CTL_FLUSH_DSPP0 0x00002000
#define MDP5_CTL_FLUSH_DSPP1 0x00004000
#define MDP5_CTL_FLUSH_DSPP2 0x00008000
#define MDP5_CTL_FLUSH_CTL 0x00020000
+#define MDP5_CTL_FLUSH_VIG3 0x00040000
+#define MDP5_CTL_FLUSH_RGB3 0x00080000
+#define MDP5_CTL_FLUSH_LM5 0x00100000
+#define MDP5_CTL_FLUSH_DSPP3 0x00200000
-static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000061c + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000001c + __offset_CTL(i0); }
-static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000620 + 0x100*i0; }
+static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000020 + __offset_CTL(i0); }
-static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)
+{
+ switch (idx) {
+ case SSPP_VIG0: return (mdp5_cfg->pipe_vig.base[0]);
+ case SSPP_VIG1: return (mdp5_cfg->pipe_vig.base[1]);
+ case SSPP_VIG2: return (mdp5_cfg->pipe_vig.base[2]);
+ case SSPP_RGB0: return (mdp5_cfg->pipe_rgb.base[0]);
+ case SSPP_RGB1: return (mdp5_cfg->pipe_rgb.base[1]);
+ case SSPP_RGB2: return (mdp5_cfg->pipe_rgb.base[2]);
+ case SSPP_DMA0: return (mdp5_cfg->pipe_dma.base[0]);
+ case SSPP_DMA1: return (mdp5_cfg->pipe_dma.base[1]);
+ case SSPP_VIG3: return (mdp5_cfg->pipe_vig.base[3]);
+ case SSPP_RGB3: return (mdp5_cfg->pipe_rgb.base[3]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000014c4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000002c4 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000014f0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000002f0 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00001500 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00000300 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00000000 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK 0xffff0000
#define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT 16
static inline uint32_t MDP5_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
@@ -420,7 +483,7 @@ static inline uint32_t MDP5_PIPE_SRC_SIZE_WIDTH(uint32_t val)
return ((val) << MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_SIZE_WIDTH__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00001204 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00000004 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK 0xffff0000
#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT 16
static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(uint32_t val)
@@ -434,7 +497,7 @@ static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_WIDTH(uint32_t val)
return ((val) << MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00001208 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00000008 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_XY_Y__MASK 0xffff0000
#define MDP5_PIPE_SRC_XY_Y__SHIFT 16
static inline uint32_t MDP5_PIPE_SRC_XY_Y(uint32_t val)
@@ -448,7 +511,7 @@ static inline uint32_t MDP5_PIPE_SRC_XY_X(uint32_t val)
return ((val) << MDP5_PIPE_SRC_XY_X__SHIFT) & MDP5_PIPE_SRC_XY_X__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000120c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000000c + __offset_PIPE(i0); }
#define MDP5_PIPE_OUT_SIZE_HEIGHT__MASK 0xffff0000
#define MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT 16
static inline uint32_t MDP5_PIPE_OUT_SIZE_HEIGHT(uint32_t val)
@@ -462,7 +525,7 @@ static inline uint32_t MDP5_PIPE_OUT_SIZE_WIDTH(uint32_t val)
return ((val) << MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT) & MDP5_PIPE_OUT_SIZE_WIDTH__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00001210 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00000010 + __offset_PIPE(i0); }
#define MDP5_PIPE_OUT_XY_Y__MASK 0xffff0000
#define MDP5_PIPE_OUT_XY_Y__SHIFT 16
static inline uint32_t MDP5_PIPE_OUT_XY_Y(uint32_t val)
@@ -476,15 +539,15 @@ static inline uint32_t MDP5_PIPE_OUT_XY_X(uint32_t val)
return ((val) << MDP5_PIPE_OUT_XY_X__SHIFT) & MDP5_PIPE_OUT_XY_X__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00001214 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00000014 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00001218 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00000018 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000121c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000001c + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00001220 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00000020 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00001224 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00000024 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_STRIDE_A_P0__MASK 0x0000ffff
#define MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT 0
static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P0(uint32_t val)
@@ -498,7 +561,7 @@ static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P1(uint32_t val)
return ((val) << MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P1__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00001228 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00000028 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_STRIDE_B_P2__MASK 0x0000ffff
#define MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT 0
static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P2(uint32_t val)
@@ -512,9 +575,9 @@ static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P3(uint32_t val)
return ((val) << MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P3__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000122c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000002c + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00001230 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00000030 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_FORMAT_G_BPC__MASK 0x00000003
#define MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT 0
static inline uint32_t MDP5_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
@@ -568,7 +631,7 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp5_chroma_samp_ty
return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00001234 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00000034 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_UNPACK_ELEM0__MASK 0x000000ff
#define MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT 0
static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
@@ -594,7 +657,7 @@ static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM3__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00001238 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00000038 + __offset_PIPE(i0); }
#define MDP5_PIPE_SRC_OP_MODE_BWC_EN 0x00000001
#define MDP5_PIPE_SRC_OP_MODE_BWC__MASK 0x00000006
#define MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT 1
@@ -610,29 +673,29 @@ static inline uint32_t MDP5_PIPE_SRC_OP_MODE_BWC(enum mdp5_pipe_bwc val)
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE 0x00400000
#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD 0x00800000
-static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000123c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000003c + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00001248 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00000048 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000124c + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000004c + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00001250 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00000050 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00001254 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00000054 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00001258 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00000058 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00001270 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00000070 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000012a4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000000a4 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000012a8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000000a8 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000012ac + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000000ac + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000012b0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000000b0 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000012b4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000000b4 + __offset_PIPE(i0); }
#define MDP5_PIPE_DECIMATION_VERT__MASK 0x000000ff
#define MDP5_PIPE_DECIMATION_VERT__SHIFT 0
static inline uint32_t MDP5_PIPE_DECIMATION_VERT(uint32_t val)
@@ -646,7 +709,7 @@ static inline uint32_t MDP5_PIPE_DECIMATION_HORZ(uint32_t val)
return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00001404 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00000204 + __offset_PIPE(i0); }
#define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN 0x00000001
#define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN 0x00000002
#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK 0x00000300
@@ -686,23 +749,34 @@ static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(enum mdp5_scale_
return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK;
}
-static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00001410 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00000210 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00001414 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00000214 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00001420 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00000220 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00001424 + 0x400*i0; }
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00000224 + __offset_PIPE(i0); }
-static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+static inline uint32_t __offset_LM(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return (mdp5_cfg->lm.base[0]);
+ case 1: return (mdp5_cfg->lm.base[1]);
+ case 2: return (mdp5_cfg->lm.base[2]);
+ case 3: return (mdp5_cfg->lm.base[3]);
+ case 4: return (mdp5_cfg->lm.base[4]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00000000 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00000000 + __offset_LM(i0); }
#define MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA 0x00000002
#define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA 0x00000004
#define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA 0x00000008
#define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA 0x00000010
-static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00003204 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00000004 + __offset_LM(i0); }
#define MDP5_LM_OUT_SIZE_HEIGHT__MASK 0xffff0000
#define MDP5_LM_OUT_SIZE_HEIGHT__SHIFT 16
static inline uint32_t MDP5_LM_OUT_SIZE_HEIGHT(uint32_t val)
@@ -716,13 +790,13 @@ static inline uint32_t MDP5_LM_OUT_SIZE_WIDTH(uint32_t val)
return ((val) << MDP5_LM_OUT_SIZE_WIDTH__SHIFT) & MDP5_LM_OUT_SIZE_WIDTH__MASK;
}
-static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00003208 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00000008 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00003210 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00000010 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00000020 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00000020 + __offset_LM(i0) + 0x30*i1; }
#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK 0x00000003
#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT 0
static inline uint32_t MDP5_LM_BLEND_OP_MODE_FG_ALPHA(enum mdp_alpha_type val)
@@ -744,57 +818,67 @@ static inline uint32_t MDP5_LM_BLEND_OP_MODE_BG_ALPHA(enum mdp_alpha_type val)
#define MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA 0x00001000
#define MDP5_LM_BLEND_OP_MODE_BG_TRANSP_EN 0x00002000
-static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003224 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000024 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003228 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000028 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000322c + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000002c + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003230 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000030 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003234 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000034 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003238 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000038 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000323c + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000003c + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003240 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000040 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003244 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000044 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003248 + 0x400*i0 + 0x30*i1; }
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000048 + __offset_LM(i0) + 0x30*i1; }
-static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000032e0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000000e0 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000032e4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000000e4 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000032e8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000000e8 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000032dc + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000000dc + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000032ec + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000000ec + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000032f0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000000f0 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000032f4 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000000f4 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000032f8 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000000f8 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000032fc + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000000fc + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00003300 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00000100 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00003304 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00000104 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00003308 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00000108 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000330c + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000010c + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00003310 + 0x400*i0; }
+static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00000110 + __offset_LM(i0); }
-static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+static inline uint32_t __offset_DSPP(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return (mdp5_cfg->dspp.base[0]);
+ case 1: return (mdp5_cfg->dspp.base[1]);
+ case 2: return (mdp5_cfg->dspp.base[2]);
+ case 3: return (mdp5_cfg->dspp.base[3]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00000000 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00000000 + __offset_DSPP(i0); }
#define MDP5_DSPP_OP_MODE_IGC_LUT_EN 0x00000001
#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK 0x0000000e
#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT 1
@@ -811,29 +895,40 @@ static inline uint32_t MDP5_DSPP_OP_MODE_IGC_TBL_IDX(uint32_t val)
#define MDP5_DSPP_OP_MODE_GAMUT_EN 0x00800000
#define MDP5_DSPP_OP_MODE_GAMUT_ORDER 0x01000000
-static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00004630 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00000030 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00004750 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00000150 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00004810 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00000210 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00004830 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00000230 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00004834 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00000234 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00004838 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00000238 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000048dc + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000002dc + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000048b0 + 0x400*i0; }
+static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000002b0 + __offset_DSPP(i0); }
-static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+static inline uint32_t __offset_INTF(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return (mdp5_cfg->intf.base[0]);
+ case 1: return (mdp5_cfg->intf.base[1]);
+ case 2: return (mdp5_cfg->intf.base[2]);
+ case 3: return (mdp5_cfg->intf.base[3]);
+ case 4: return (mdp5_cfg->intf.base[4]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00000000 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00000000 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00012504 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00000004 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00012508 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00000008 + __offset_INTF(i0); }
#define MDP5_INTF_HSYNC_CTL_PULSEW__MASK 0x0000ffff
#define MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT 0
static inline uint32_t MDP5_INTF_HSYNC_CTL_PULSEW(uint32_t val)
@@ -847,23 +942,23 @@ static inline uint32_t MDP5_INTF_HSYNC_CTL_PERIOD(uint32_t val)
return ((val) << MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT) & MDP5_INTF_HSYNC_CTL_PERIOD__MASK;
}
-static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0001250c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0000000c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00012510 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00000010 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00012514 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00000014 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00012518 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00000018 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0001251c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0000001c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00012520 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00000020 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00012524 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00000024 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00012528 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00000028 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0001252c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0000002c + __offset_INTF(i0); }
#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK 0x7fffffff
#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT 0
static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F0_VAL(uint32_t val)
@@ -872,7 +967,7 @@ static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F0_VAL(uint32_t val)
}
#define MDP5_INTF_ACTIVE_VSTART_F0_ACTIVE_V_ENABLE 0x80000000
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00012530 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00000030 + __offset_INTF(i0); }
#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK 0x7fffffff
#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT 0
static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F1_VAL(uint32_t val)
@@ -880,11 +975,11 @@ static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F1_VAL(uint32_t val)
return ((val) << MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK;
}
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00012534 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00000034 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00012538 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00000038 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0001253c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0000003c + __offset_INTF(i0); }
#define MDP5_INTF_DISPLAY_HCTL_START__MASK 0x0000ffff
#define MDP5_INTF_DISPLAY_HCTL_START__SHIFT 0
static inline uint32_t MDP5_INTF_DISPLAY_HCTL_START(uint32_t val)
@@ -898,7 +993,7 @@ static inline uint32_t MDP5_INTF_DISPLAY_HCTL_END(uint32_t val)
return ((val) << MDP5_INTF_DISPLAY_HCTL_END__SHIFT) & MDP5_INTF_DISPLAY_HCTL_END__MASK;
}
-static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00012540 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00000040 + __offset_INTF(i0); }
#define MDP5_INTF_ACTIVE_HCTL_START__MASK 0x00007fff
#define MDP5_INTF_ACTIVE_HCTL_START__SHIFT 0
static inline uint32_t MDP5_INTF_ACTIVE_HCTL_START(uint32_t val)
@@ -913,124 +1008,132 @@ static inline uint32_t MDP5_INTF_ACTIVE_HCTL_END(uint32_t val)
}
#define MDP5_INTF_ACTIVE_HCTL_ACTIVE_H_ENABLE 0x80000000
-static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00012544 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00000044 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00012548 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00000048 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0001254c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0000004c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00012550 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00000050 + __offset_INTF(i0); }
#define MDP5_INTF_POLARITY_CTL_HSYNC_LOW 0x00000001
#define MDP5_INTF_POLARITY_CTL_VSYNC_LOW 0x00000002
#define MDP5_INTF_POLARITY_CTL_DATA_EN_LOW 0x00000004
-static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00012554 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00000054 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00012558 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00000058 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0001255c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0000005c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00012584 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00000084 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00012590 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00000090 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000125a8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000000a8 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000125ac + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000000ac + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000125b0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000000b0 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000125f0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000000f0 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000125f4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000000f4 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000125f8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000000f8 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00012600 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00000100 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00012604 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00000104 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00012608 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00000108 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0001260c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0000010c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00012610 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00000110 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00012614 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00000114 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00012618 + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00000118 + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0001261c + 0x200*i0; }
+static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0000011c + __offset_INTF(i0); }
-static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+static inline uint32_t __offset_AD(uint32_t idx)
+{
+ switch (idx) {
+ case 0: return (mdp5_cfg->ad.base[0]);
+ case 1: return (mdp5_cfg->ad.base[1]);
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00000000 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00000000 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00013104 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00000004 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00013108 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00000008 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0001310c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0000000c + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00013110 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00000010 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00013114 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00000014 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00013118 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00000018 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0001311c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0000001c + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00013120 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00000020 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00013124 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00000024 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00013128 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00000028 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0001312c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0000002c + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00013130 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00000030 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00013134 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00000034 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00013138 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00000038 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0001317c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0000007c + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000131c8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000000c8 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000131cc + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000000cc + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000131d0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000000d0 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000131d4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000000d4 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000131d8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000000d8 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000131dc + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000000dc + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000131e0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000000e0 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000131e8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000000e8 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000131ec + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000000ec + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000131f0 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000000f0 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000131f4 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000000f4 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000131f8 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000000f8 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00013200 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00000100 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00013244 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00000144 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00013248 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00000148 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0001324c + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0000014c + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00013254 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00000154 + __offset_AD(i0); }
-static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00013258 + 0x200*i0; }
+static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00000158 + __offset_AD(i0); }
#endif /* MDP5_XML */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 71510ee26e96..31a2c6331a1d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -26,14 +26,98 @@ static const char *iommu_ports[] = {
static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev);
-static int mdp5_hw_init(struct msm_kms *kms)
+const struct mdp5_config *mdp5_cfg;
+
+static const struct mdp5_config msm8x74_config = {
+ .name = "msm8x74",
+ .ctl = {
+ .count = 5,
+ .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
+ },
+ .pipe_vig = {
+ .count = 3,
+ .base = { 0x01200, 0x01600, 0x01a00 },
+ },
+ .pipe_rgb = {
+ .count = 3,
+ .base = { 0x01e00, 0x02200, 0x02600 },
+ },
+ .pipe_dma = {
+ .count = 2,
+ .base = { 0x02a00, 0x02e00 },
+ },
+ .lm = {
+ .count = 5,
+ .base = { 0x03200, 0x03600, 0x03a00, 0x03e00, 0x04200 },
+ },
+ .dspp = {
+ .count = 3,
+ .base = { 0x04600, 0x04a00, 0x04e00 },
+ },
+ .ad = {
+ .count = 2,
+ .base = { 0x13100, 0x13300 }, /* NOTE: no ad in v1.0 */
+ },
+ .intf = {
+ .count = 4,
+ .base = { 0x12500, 0x12700, 0x12900, 0x12b00 },
+ },
+};
+
+static const struct mdp5_config apq8084_config = {
+ .name = "apq8084",
+ .ctl = {
+ .count = 5,
+ .base = { 0x00600, 0x00700, 0x00800, 0x00900, 0x00a00 },
+ },
+ .pipe_vig = {
+ .count = 4,
+ .base = { 0x01200, 0x01600, 0x01a00, 0x01e00 },
+ },
+ .pipe_rgb = {
+ .count = 4,
+ .base = { 0x02200, 0x02600, 0x02a00, 0x02e00 },
+ },
+ .pipe_dma = {
+ .count = 2,
+ .base = { 0x03200, 0x03600 },
+ },
+ .lm = {
+ .count = 6,
+ .base = { 0x03a00, 0x03e00, 0x04200, 0x04600, 0x04a00, 0x04e00 },
+ },
+ .dspp = {
+ .count = 4,
+ .base = { 0x05200, 0x05600, 0x05a00, 0x05e00 },
+
+ },
+ .ad = {
+ .count = 3,
+ .base = { 0x13500, 0x13700, 0x13900 },
+ },
+ .intf = {
+ .count = 5,
+ .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 },
+ },
+};
+
+struct mdp5_config_entry {
+ int revision;
+ const struct mdp5_config *config;
+};
+
+static const struct mdp5_config_entry mdp5_configs[] = {
+ { .revision = 0, .config = &msm8x74_config },
+ { .revision = 2, .config = &msm8x74_config },
+ { .revision = 3, .config = &apq8084_config },
+};
+
+static int mdp5_select_hw_cfg(struct msm_kms *kms)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
struct drm_device *dev = mdp5_kms->dev;
uint32_t version, major, minor;
- int ret = 0;
-
- pm_runtime_get_sync(dev->dev);
+ int i, ret = 0;
mdp5_enable(mdp5_kms);
version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION);
@@ -44,8 +128,8 @@ static int mdp5_hw_init(struct msm_kms *kms)
DBG("found MDP5 version v%d.%d", major, minor);
- if ((major != 1) || ((minor != 0) && (minor != 2))) {
- dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
+ if (major != 1) {
+ dev_err(dev->dev, "unexpected MDP major version: v%d.%d\n",
major, minor);
ret = -ENXIO;
goto out;
@@ -53,6 +137,35 @@ static int mdp5_hw_init(struct msm_kms *kms)
mdp5_kms->rev = minor;
+ /* only after mdp5_cfg global pointer's init can we access the hw */
+ for (i = 0; i < ARRAY_SIZE(mdp5_configs); i++) {
+ if (mdp5_configs[i].revision != minor)
+ continue;
+ mdp5_kms->hw_cfg = mdp5_cfg = mdp5_configs[i].config;
+ break;
+ }
+ if (unlikely(!mdp5_kms->hw_cfg)) {
+ dev_err(dev->dev, "unexpected MDP minor revision: v%d.%d\n",
+ major, minor);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ DBG("MDP5: %s config selected", mdp5_kms->hw_cfg->name);
+
+ return 0;
+out:
+ return ret;
+}
+
+static int mdp5_hw_init(struct msm_kms *kms)
+{
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+ struct drm_device *dev = mdp5_kms->dev;
+ int i;
+
+ pm_runtime_get_sync(dev->dev);
+
/* Magic unknown register writes:
*
* W VBIF:0x004 00000001 (mdss_mdp.c:839)
@@ -78,15 +191,13 @@ static int mdp5_hw_init(struct msm_kms *kms)
*/
mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0);
- mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(0), 0);
- mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(1), 0);
- mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(2), 0);
- mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(3), 0);
-out:
+ for (i = 0; i < mdp5_kms->hw_cfg->ctl.count; i++)
+ mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(i), 0);
+
pm_runtime_put_sync(dev->dev);
- return ret;
+ return 0;
}
static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
@@ -161,7 +272,7 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
static int modeset_init(struct mdp5_kms *mdp5_kms)
{
static const enum mdp5_pipe crtcs[] = {
- SSPP_RGB0, SSPP_RGB1, SSPP_RGB2,
+ SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
};
struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
@@ -169,7 +280,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
int i, ret;
/* construct CRTCs: */
- for (i = 0; i < ARRAY_SIZE(crtcs); i++) {
+ for (i = 0; i < mdp5_kms->hw_cfg->pipe_rgb.count; i++) {
struct drm_plane *plane;
struct drm_crtc *crtc;
@@ -246,7 +357,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
struct mdp5_kms *mdp5_kms;
struct msm_kms *kms = NULL;
struct msm_mmu *mmu;
- int ret;
+ int i, ret;
mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL);
if (!mdp5_kms) {
@@ -307,20 +418,22 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk);
+ ret = mdp5_select_hw_cfg(kms);
+ if (ret)
+ goto fail;
+
/* make sure things are off before attaching iommu (bootloader could
* have left things on, in which case we'll start getting faults if
* we don't disable):
*/
mdp5_enable(mdp5_kms);
- mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(0), 0);
- mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(1), 0);
- mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(2), 0);
- mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(3), 0);
+ for (i = 0; i < mdp5_kms->hw_cfg->intf.count; i++)
+ mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(i), 0);
mdp5_disable(mdp5_kms);
mdelay(16);
if (config->iommu) {
- mmu = msm_iommu_new(dev, config->iommu);
+ mmu = msm_iommu_new(&pdev->dev, config->iommu);
if (IS_ERR(mmu)) {
ret = PTR_ERR(mmu);
dev_err(dev->dev, "failed to init iommu: %d\n", ret);
@@ -368,5 +481,11 @@ static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev)
#ifdef CONFIG_OF
/* TODO */
#endif
+ config.iommu = iommu_domain_alloc(&platform_bus_type);
+ /* TODO hard-coded in downstream mdss, but should it be? */
+ config.max_clk = 200000000;
+ /* TODO get from DT: */
+ config.smp_blk_cnt = 22;
+
return &config;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 6e981b692d1d..5bf340dd0f00 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -21,6 +21,24 @@
#include "msm_drv.h"
#include "msm_kms.h"
#include "mdp/mdp_kms.h"
+/* dynamic offsets used by mdp5.xml.h (initialized in mdp5_kms.c) */
+#define MDP5_MAX_BASES 8
+struct mdp5_sub_block {
+ int count;
+ uint32_t base[MDP5_MAX_BASES];
+};
+struct mdp5_config {
+ char *name;
+ struct mdp5_sub_block ctl;
+ struct mdp5_sub_block pipe_vig;
+ struct mdp5_sub_block pipe_rgb;
+ struct mdp5_sub_block pipe_dma;
+ struct mdp5_sub_block lm;
+ struct mdp5_sub_block dspp;
+ struct mdp5_sub_block ad;
+ struct mdp5_sub_block intf;
+};
+extern const struct mdp5_config *mdp5_cfg;
#include "mdp5.xml.h"
#include "mdp5_smp.h"
@@ -30,6 +48,7 @@ struct mdp5_kms {
struct drm_device *dev;
int rev;
+ const struct mdp5_config *hw_cfg;
/* mapper-id used to request GEM buffer mapped for scanout: */
int id;
@@ -82,6 +101,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)
NAME(VIG0), NAME(VIG1), NAME(VIG2),
NAME(RGB0), NAME(RGB1), NAME(RGB2),
NAME(DMA0), NAME(DMA1),
+ NAME(VIG3), NAME(RGB3),
#undef NAME
};
return names[pipe];
@@ -98,6 +118,8 @@ static inline uint32_t pipe2flush(enum mdp5_pipe pipe)
case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2;
case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0;
case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
+ case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
+ case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
default: return 0;
}
}
@@ -108,6 +130,7 @@ static inline int pipe2nclients(enum mdp5_pipe pipe)
case SSPP_RGB0:
case SSPP_RGB1:
case SSPP_RGB2:
+ case SSPP_RGB3:
return 1;
default:
return 3;
@@ -126,6 +149,8 @@ static inline enum mdp5_client_id pipe2client(enum mdp5_pipe pipe, int plane)
case SSPP_RGB2: return CID_RGB2;
case SSPP_DMA0: return CID_DMA0_Y + plane;
case SSPP_DMA1: return CID_DMA1_Y + plane;
+ case SSPP_VIG3: return CID_VIG3_Y + plane;
+ case SSPP_RGB3: return CID_RGB3;
default: return CID_UNUSED;
}
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index a9629b85b983..64c1afd6030a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 17996 bytes, from 2013-12-01 19:10:31)
- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 22517 bytes, from 2014-06-25 12:55:02)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1544 bytes, from 2013-08-16 19:17:05)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 20932 bytes, from 2013-12-01 15:13:04)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 23613 bytes, from 2014-06-25 12:53:44)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9a5d87db5c23..b447c01ad89c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -181,7 +181,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
struct msm_kms *kms;
int ret;
-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(dev->dev, "failed to allocate private data\n");
@@ -314,13 +313,15 @@ fail:
static void load_gpu(struct drm_device *dev)
{
+ static DEFINE_MUTEX(init_lock);
struct msm_drm_private *priv = dev->dev_private;
struct msm_gpu *gpu;
+ mutex_lock(&init_lock);
+
if (priv->gpu)
- return;
+ goto out;
- mutex_lock(&dev->struct_mutex);
gpu = a3xx_gpu_init(dev);
if (IS_ERR(gpu)) {
dev_warn(dev->dev, "failed to load a3xx gpu\n");
@@ -330,7 +331,9 @@ static void load_gpu(struct drm_device *dev)
if (gpu) {
int ret;
+ mutex_lock(&dev->struct_mutex);
gpu->funcs->pm_resume(gpu);
+ mutex_unlock(&dev->struct_mutex);
ret = gpu->funcs->hw_init(gpu);
if (ret) {
dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
@@ -340,12 +343,12 @@ static void load_gpu(struct drm_device *dev)
/* give inactive pm a chance to kick in: */
msm_gpu_retire(gpu);
}
-
}
priv->gpu = gpu;
- mutex_unlock(&dev->struct_mutex);
+out:
+ mutex_unlock(&init_lock);
}
static int msm_open(struct drm_device *dev, struct drm_file *file)
@@ -906,25 +909,22 @@ static int compare_of(struct device *dev, void *data)
return dev->of_node == data;
}
-static int msm_drm_add_components(struct device *master, struct master *m)
+static int add_components(struct device *dev, struct component_match **matchptr,
+ const char *name)
{
- struct device_node *np = master->of_node;
+ struct device_node *np = dev->of_node;
unsigned i;
- int ret;
for (i = 0; ; i++) {
struct device_node *node;
- node = of_parse_phandle(np, "connectors", i);
+ node = of_parse_phandle(np, name, i);
if (!node)
break;
- ret = component_master_add_child(m, compare_of, node);
- of_node_put(node);
-
- if (ret)
- return ret;
+ component_match_add(dev, matchptr, compare_of, node);
}
+
return 0;
}
#else
@@ -932,9 +932,34 @@ static int compare_dev(struct device *dev, void *data)
{
return dev == data;
}
+#endif
+
+static int msm_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&msm_driver, to_platform_device(dev));
+}
+
+static void msm_drm_unbind(struct device *dev)
+{
+ drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+}
+
+static const struct component_master_ops msm_drm_ops = {
+ .bind = msm_drm_bind,
+ .unbind = msm_drm_unbind,
+};
+
+/*
+ * Platform driver:
+ */
-static int msm_drm_add_components(struct device *master, struct master *m)
+static int msm_pdev_probe(struct platform_device *pdev)
{
+ struct component_match *match = NULL;
+#ifdef CONFIG_OF
+ add_components(&pdev->dev, &match, "connectors");
+ add_components(&pdev->dev, &match, "gpus");
+#else
/* For non-DT case, it kinda sucks. We don't actually have a way
* to know whether or not we are waiting for certain devices (or if
* they are simply not present). But for non-DT we only need to
@@ -958,41 +983,12 @@ static int msm_drm_add_components(struct device *master, struct master *m)
return -EPROBE_DEFER;
}
- ret = component_master_add_child(m, compare_dev, dev);
- if (ret) {
- DBG("could not add child: %d", ret);
- return ret;
- }
+ component_match_add(&pdev->dev, &match, compare_dev, dev);
}
-
- return 0;
-}
#endif
-static int msm_drm_bind(struct device *dev)
-{
- return drm_platform_init(&msm_driver, to_platform_device(dev));
-}
-
-static void msm_drm_unbind(struct device *dev)
-{
- drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
-}
-
-static const struct component_master_ops msm_drm_ops = {
- .add_components = msm_drm_add_components,
- .bind = msm_drm_bind,
- .unbind = msm_drm_unbind,
-};
-
-/*
- * Platform driver:
- */
-
-static int msm_pdev_probe(struct platform_device *pdev)
-{
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- return component_master_add(&pdev->dev, &msm_drm_ops);
+ return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
}
static int msm_pdev_remove(struct platform_device *pdev)
@@ -1008,7 +1004,8 @@ static const struct platform_device_id msm_id[] = {
};
static const struct of_device_id dt_match[] = {
- { .compatible = "qcom,mdss_mdp" },
+ { .compatible = "qcom,mdp" }, /* mdp4 */
+ { .compatible = "qcom,mdss_mdp" }, /* mdp5 */
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 5107fc4826bc..9c5221ce391a 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -19,6 +19,11 @@
#include "drm_crtc.h"
#include "drm_fb_helper.h"
+#include "msm_gem.h"
+
+extern int msm_gem_mmap_obj(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma);
/*
* fbdev funcs, to implement legacy fbdev interface on top of drm driver
@@ -43,6 +48,7 @@ static struct fb_ops msm_fb_ops = {
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
+ .fb_mmap = msm_fbdev_mmap,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
@@ -51,6 +57,31 @@ static struct fb_ops msm_fb_ops = {
.fb_setcmap = drm_fb_helper_setcmap,
};
+static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
+ struct msm_fbdev *fbdev = to_msm_fbdev(helper);
+ struct drm_gem_object *drm_obj = fbdev->bo;
+ struct drm_device *dev = helper->dev;
+ int ret = 0;
+
+ if (drm_device_is_unplugged(dev))
+ return -ENODEV;
+
+ mutex_lock(&dev->struct_mutex);
+
+ ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ if (ret) {
+ pr_err("%s:drm_gem_mmap_obj fail\n", __func__);
+ return ret;
+ }
+
+ return msm_gem_mmap_obj(drm_obj, vma);
+}
+
static int msm_fbdev_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
@@ -104,8 +135,16 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
mutex_lock(&dev->struct_mutex);
- /* TODO implement our own fb_mmap so we don't need this: */
- msm_gem_get_iova_locked(fbdev->bo, 0, &paddr);
+ /*
+ * NOTE: if we can be guaranteed to be able to map buffer
+ * in panic (ie. lock-safe, etc) we could avoid pinning the
+ * buffer now:
+ */
+ ret = msm_gem_get_iova_locked(fbdev->bo, 0, &paddr);
+ if (ret) {
+ dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
+ goto fail;
+ }
fbi = framebuffer_alloc(0, dev->dev);
if (!fbi) {
@@ -177,7 +216,7 @@ static void msm_crtc_fb_gamma_get(struct drm_crtc *crtc,
DBG("fbdev: get gamma");
}
-static struct drm_fb_helper_funcs msm_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs msm_fb_helper_funcs = {
.gamma_set = msm_crtc_fb_gamma_set,
.gamma_get = msm_crtc_fb_gamma_get,
.fb_probe = msm_fbdev_create,
@@ -189,7 +228,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct msm_fbdev *fbdev = NULL;
struct drm_fb_helper *helper;
- int ret = 0;
+ int ret;
fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
if (!fbdev)
@@ -197,7 +236,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
helper = &fbdev->base;
- helper->funcs = &msm_fb_helper_funcs;
+ drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper,
priv->num_crtcs, priv->num_connectors);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 690d7e7b6d1e..4b1b82adabde 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -73,7 +73,7 @@ static struct page **get_pages(struct drm_gem_object *obj)
int npages = obj->size >> PAGE_SHIFT;
if (iommu_present(&platform_bus_type))
- p = drm_gem_get_pages(obj, 0);
+ p = drm_gem_get_pages(obj);
else
p = get_pages_vram(obj, npages);
@@ -278,24 +278,23 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
uint32_t *iova)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
- struct drm_device *dev = obj->dev;
int ret = 0;
if (!msm_obj->domain[id].iova) {
struct msm_drm_private *priv = obj->dev->dev_private;
- struct msm_mmu *mmu = priv->mmus[id];
struct page **pages = get_pages(obj);
- if (!mmu) {
- dev_err(dev->dev, "null MMU pointer\n");
- return -EINVAL;
- }
-
if (IS_ERR(pages))
return PTR_ERR(pages);
if (iommu_present(&platform_bus_type)) {
- uint32_t offset = (uint32_t)mmap_offset(obj);
+ struct msm_mmu *mmu = priv->mmus[id];
+ uint32_t offset;
+
+ if (WARN_ON(!mmu))
+ return -EINVAL;
+
+ offset = (uint32_t)mmap_offset(obj);
ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
obj->size, IOMMU_READ | IOMMU_WRITE);
msm_obj->domain[id].iova = offset;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index c6322197db8c..4a0dce587745 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -606,14 +606,17 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
iommu = iommu_domain_alloc(&platform_bus_type);
if (iommu) {
dev_info(drm->dev, "%s: using IOMMU\n", name);
- gpu->mmu = msm_iommu_new(drm, iommu);
+ gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
} else {
dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
}
gpu->id = msm_register_mmu(drm, gpu->mmu);
+
/* Create ringbuffer: */
+ mutex_lock(&drm->struct_mutex);
gpu->rb = msm_ringbuffer_new(gpu, ringsz);
+ mutex_unlock(&drm->struct_mutex);
if (IS_ERR(gpu->rb)) {
ret = PTR_ERR(gpu->rb);
gpu->rb = NULL;
@@ -621,13 +624,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
goto fail;
}
- ret = msm_gem_get_iova_locked(gpu->rb->bo, gpu->id, &gpu->rb_iova);
- if (ret) {
- gpu->rb_iova = 0;
- dev_err(drm->dev, "could not map ringbuffer: %d\n", ret);
- goto fail;
- }
-
bs_init(gpu);
return 0;
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 4b2ad9181edf..099af483fdf0 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -33,39 +33,14 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
{
- struct drm_device *dev = mmu->dev;
struct msm_iommu *iommu = to_msm_iommu(mmu);
- int i, ret;
-
- for (i = 0; i < cnt; i++) {
- struct device *msm_iommu_get_ctx(const char *ctx_name);
- struct device *ctx = msm_iommu_get_ctx(names[i]);
- if (IS_ERR_OR_NULL(ctx)) {
- dev_warn(dev->dev, "couldn't get %s context", names[i]);
- continue;
- }
- ret = iommu_attach_device(iommu->domain, ctx);
- if (ret) {
- dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
- return ret;
- }
- }
-
- return 0;
+ return iommu_attach_device(iommu->domain, mmu->dev);
}
static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
- int i;
-
- for (i = 0; i < cnt; i++) {
- struct device *msm_iommu_get_ctx(const char *ctx_name);
- struct device *ctx = msm_iommu_get_ctx(names[i]);
- if (IS_ERR_OR_NULL(ctx))
- continue;
- iommu_detach_device(iommu->domain, ctx);
- }
+ iommu_detach_device(iommu->domain, mmu->dev);
}
static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
@@ -149,7 +124,7 @@ static const struct msm_mmu_funcs funcs = {
.destroy = msm_iommu_destroy,
};
-struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain)
+struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
{
struct msm_iommu *iommu;
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 21da6d154f71..7cd88d9dc155 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -32,17 +32,17 @@ struct msm_mmu_funcs {
struct msm_mmu {
const struct msm_mmu_funcs *funcs;
- struct drm_device *dev;
+ struct device *dev;
};
-static inline void msm_mmu_init(struct msm_mmu *mmu, struct drm_device *dev,
+static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
const struct msm_mmu_funcs *funcs)
{
mmu->dev = dev;
mmu->funcs = funcs;
}
-struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain);
-struct msm_mmu *msm_gpummu_new(struct drm_device *dev, struct msm_gpu *gpu);
+struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
+struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
#endif /* __MSM_MMU_H__ */
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 637c29a33127..40afc69a3778 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -1,5 +1,5 @@
config DRM_NOUVEAU
- tristate "Nouveau (nVidia) cards"
+ tristate "Nouveau (NVIDIA) cards"
depends on DRM && PCI
select FW_LOADER
select DRM_KMS_HELPER
@@ -23,7 +23,15 @@ config DRM_NOUVEAU
select THERMAL if ACPI && X86
select ACPI_VIDEO if ACPI && X86
help
- Choose this option for open-source nVidia support.
+ Choose this option for open-source NVIDIA support.
+
+config NOUVEAU_PLATFORM_DRIVER
+ tristate "Nouveau (NVIDIA) SoC GPUs"
+ depends on DRM_NOUVEAU && ARCH_TEGRA
+ default y
+ help
+ Support for Nouveau platform driver, used for SoC GPUs as found
+ on NVIDIA Tegra K1.
config NOUVEAU_DEBUG
int "Maximum debug level"
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 8b307e143632..f5d7f7ce4bc6 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -14,8 +14,10 @@ nouveau-y += core/core/enum.o
nouveau-y += core/core/event.o
nouveau-y += core/core/gpuobj.o
nouveau-y += core/core/handle.o
+nouveau-y += core/core/ioctl.o
nouveau-y += core/core/mm.o
nouveau-y += core/core/namedb.o
+nouveau-y += core/core/notify.o
nouveau-y += core/core/object.o
nouveau-y += core/core/option.o
nouveau-y += core/core/parent.o
@@ -26,6 +28,7 @@ nouveau-y += core/core/subdev.o
nouveau-y += core/subdev/bar/base.o
nouveau-y += core/subdev/bar/nv50.o
nouveau-y += core/subdev/bar/nvc0.o
+nouveau-y += core/subdev/bar/gk20a.o
nouveau-y += core/subdev/bios/base.o
nouveau-y += core/subdev/bios/bit.o
nouveau-y += core/subdev/bios/boost.o
@@ -64,6 +67,7 @@ nouveau-y += core/subdev/clock/nva3.o
nouveau-y += core/subdev/clock/nvaa.o
nouveau-y += core/subdev/clock/nvc0.o
nouveau-y += core/subdev/clock/nve0.o
+nouveau-y += core/subdev/clock/gk20a.o
nouveau-y += core/subdev/clock/pllnv04.o
nouveau-y += core/subdev/clock/pllnva3.o
nouveau-y += core/subdev/devinit/base.o
@@ -149,8 +153,10 @@ nouveau-y += core/subdev/instmem/base.o
nouveau-y += core/subdev/instmem/nv04.o
nouveau-y += core/subdev/instmem/nv40.o
nouveau-y += core/subdev/instmem/nv50.o
-nouveau-y += core/subdev/ltcg/gf100.o
-nouveau-y += core/subdev/ltcg/gm107.o
+nouveau-y += core/subdev/ltc/base.o
+nouveau-y += core/subdev/ltc/gf100.o
+nouveau-y += core/subdev/ltc/gk104.o
+nouveau-y += core/subdev/ltc/gm107.o
nouveau-y += core/subdev/mc/base.o
nouveau-y += core/subdev/mc/nv04.o
nouveau-y += core/subdev/mc/nv40.o
@@ -161,6 +167,7 @@ nouveau-y += core/subdev/mc/nv94.o
nouveau-y += core/subdev/mc/nv98.o
nouveau-y += core/subdev/mc/nvc0.o
nouveau-y += core/subdev/mc/nvc3.o
+nouveau-y += core/subdev/mc/gk20a.o
nouveau-y += core/subdev/mxm/base.o
nouveau-y += core/subdev/mxm/mxms.o
nouveau-y += core/subdev/mxm/nv50.o
@@ -169,6 +176,7 @@ nouveau-y += core/subdev/pwr/memx.o
nouveau-y += core/subdev/pwr/nva3.o
nouveau-y += core/subdev/pwr/nvc0.o
nouveau-y += core/subdev/pwr/nvd0.o
+nouveau-y += core/subdev/pwr/gk104.o
nouveau-y += core/subdev/pwr/nv108.o
nouveau-y += core/subdev/therm/base.o
nouveau-y += core/subdev/therm/fan.o
@@ -211,6 +219,7 @@ nouveau-y += core/engine/copy/nvc0.o
nouveau-y += core/engine/copy/nve0.o
nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
+nouveau-y += core/engine/device/acpi.o
nouveau-y += core/engine/device/base.o
nouveau-y += core/engine/device/ctrl.o
nouveau-y += core/engine/device/nv04.o
@@ -270,6 +279,7 @@ nouveau-y += core/engine/graph/ctxnvd9.o
nouveau-y += core/engine/graph/ctxnve4.o
nouveau-y += core/engine/graph/ctxgk20a.o
nouveau-y += core/engine/graph/ctxnvf0.o
+nouveau-y += core/engine/graph/ctxgk110b.o
nouveau-y += core/engine/graph/ctxnv108.o
nouveau-y += core/engine/graph/ctxgm107.o
nouveau-y += core/engine/graph/nv04.o
@@ -291,6 +301,7 @@ nouveau-y += core/engine/graph/nvd9.o
nouveau-y += core/engine/graph/nve4.o
nouveau-y += core/engine/graph/gk20a.o
nouveau-y += core/engine/graph/nvf0.o
+nouveau-y += core/engine/graph/gk110b.o
nouveau-y += core/engine/graph/nv108.o
nouveau-y += core/engine/graph/gm107.o
nouveau-y += core/engine/mpeg/nv31.o
@@ -318,11 +329,18 @@ nouveau-y += core/engine/vp/nv98.o
nouveau-y += core/engine/vp/nvc0.o
nouveau-y += core/engine/vp/nve0.o
+# nvif
+nouveau-y += nvif/object.o
+nouveau-y += nvif/client.o
+nouveau-y += nvif/device.o
+nouveau-y += nvif/notify.o
+
# drm/core
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
nouveau-y += nouveau_vga.o nouveau_agp.o
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
nouveau-y += nouveau_prime.o nouveau_abi16.o
+nouveau-y += nouveau_nvif.o nouveau_usif.o
nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o
@@ -349,3 +367,6 @@ nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o
obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
+
+# platform driver
+obj-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c
index 9079c0ac58e6..68bf06768123 100644
--- a/drivers/gpu/drm/nouveau/core/core/client.c
+++ b/drivers/gpu/drm/nouveau/core/core/client.c
@@ -26,13 +26,167 @@
#include <core/client.h>
#include <core/handle.h>
#include <core/option.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+
+#include <nvif/unpack.h>
+#include <nvif/event.h>
#include <engine/device.h>
+struct nvkm_client_notify {
+ struct nouveau_client *client;
+ struct nvkm_notify n;
+ u8 version;
+ u8 size;
+ union {
+ struct nvif_notify_rep_v0 v0;
+ } rep;
+};
+
+static int
+nvkm_client_notify(struct nvkm_notify *n)
+{
+ struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
+ struct nouveau_client *client = notify->client;
+ return client->ntfy(&notify->rep, notify->size, n->data, n->size);
+}
+
+int
+nvkm_client_notify_put(struct nouveau_client *client, int index)
+{
+ if (index < ARRAY_SIZE(client->notify)) {
+ if (client->notify[index]) {
+ nvkm_notify_put(&client->notify[index]->n);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+int
+nvkm_client_notify_get(struct nouveau_client *client, int index)
+{
+ if (index < ARRAY_SIZE(client->notify)) {
+ if (client->notify[index]) {
+ nvkm_notify_get(&client->notify[index]->n);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+int
+nvkm_client_notify_del(struct nouveau_client *client, int index)
+{
+ if (index < ARRAY_SIZE(client->notify)) {
+ if (client->notify[index]) {
+ nvkm_notify_fini(&client->notify[index]->n);
+ kfree(client->notify[index]);
+ client->notify[index] = NULL;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+int
+nvkm_client_notify_new(struct nouveau_client *client,
+ struct nvkm_event *event, void *data, u32 size)
+{
+ struct nvkm_client_notify *notify;
+ union {
+ struct nvif_notify_req_v0 v0;
+ } *req = data;
+ u8 index, reply;
+ int ret;
+
+ for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
+ if (!client->notify[index])
+ break;
+ }
+
+ if (index == ARRAY_SIZE(client->notify))
+ return -ENOSPC;
+
+ notify = kzalloc(sizeof(*notify), GFP_KERNEL);
+ if (!notify)
+ return -ENOMEM;
+
+ nv_ioctl(client, "notify new size %d\n", size);
+ if (nvif_unpack(req->v0, 0, 0, true)) {
+ nv_ioctl(client, "notify new vers %d reply %d route %02x "
+ "token %llx\n", req->v0.version,
+ req->v0.reply, req->v0.route, req->v0.token);
+ notify->version = req->v0.version;
+ notify->size = sizeof(notify->rep.v0);
+ notify->rep.v0.version = req->v0.version;
+ notify->rep.v0.route = req->v0.route;
+ notify->rep.v0.token = req->v0.token;
+ reply = req->v0.reply;
+ }
+
+ if (ret == 0) {
+ ret = nvkm_notify_init(event, nvkm_client_notify, false,
+ data, size, reply, &notify->n);
+ if (ret == 0) {
+ client->notify[index] = notify;
+ notify->client = client;
+ return index;
+ }
+ }
+
+ kfree(notify);
+ return ret;
+}
+
+static int
+nouveau_client_devlist(struct nouveau_object *object, void *data, u32 size)
+{
+ union {
+ struct nv_client_devlist_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "client devlist size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "client devlist vers %d count %d\n",
+ args->v0.version, args->v0.count);
+ if (size == sizeof(args->v0.device[0]) * args->v0.count) {
+ ret = nouveau_device_list(args->v0.device,
+ args->v0.count);
+ if (ret >= 0) {
+ args->v0.count = ret;
+ ret = 0;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nouveau_client_mthd(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ switch (mthd) {
+ case NV_CLIENT_DEVLIST:
+ return nouveau_client_devlist(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
static void
nouveau_client_dtor(struct nouveau_object *object)
{
struct nouveau_client *client = (void *)object;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(client->notify); i++)
+ nvkm_client_notify_del(client, i);
nouveau_object_ref(NULL, &client->device);
nouveau_handle_destroy(client->root);
nouveau_namedb_destroy(&client->base);
@@ -42,6 +196,7 @@ static struct nouveau_oclass
nouveau_client_oclass = {
.ofuncs = &(struct nouveau_ofuncs) {
.dtor = nouveau_client_dtor,
+ .mthd = nouveau_client_mthd,
},
};
@@ -93,9 +248,12 @@ int
nouveau_client_fini(struct nouveau_client *client, bool suspend)
{
const char *name[2] = { "fini", "suspend" };
- int ret;
-
+ int ret, i;
nv_debug(client, "%s running\n", name[suspend]);
+ nv_debug(client, "%s notify\n", name[suspend]);
+ for (i = 0; i < ARRAY_SIZE(client->notify); i++)
+ nvkm_client_notify_put(client, i);
+ nv_debug(client, "%s object\n", name[suspend]);
ret = nouveau_handle_fini(client->root, suspend);
nv_debug(client, "%s completed with %d\n", name[suspend], ret);
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c
index ae81d3b5d8b7..0540a48c5678 100644
--- a/drivers/gpu/drm/nouveau/core/core/event.c
+++ b/drivers/gpu/drm/nouveau/core/core/event.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 Red Hat Inc.
+ * Copyright 2013-2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -24,173 +24,77 @@
#include <core/event.h>
void
-nouveau_event_put(struct nouveau_eventh *handler)
+nvkm_event_put(struct nvkm_event *event, u32 types, int index)
{
- struct nouveau_event *event = handler->event;
- unsigned long flags;
- u32 m, t;
-
- if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags))
- return;
-
- spin_lock_irqsave(&event->refs_lock, flags);
- for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
- if (!--event->refs[handler->index * event->types_nr + t]) {
- if (event->disable)
- event->disable(event, 1 << t, handler->index);
+ BUG_ON(!spin_is_locked(&event->refs_lock));
+ while (types) {
+ int type = __ffs(types); types &= ~(1 << type);
+ if (--event->refs[index * event->types_nr + type] == 0) {
+ if (event->func->fini)
+ event->func->fini(event, 1 << type, index);
}
-
}
- spin_unlock_irqrestore(&event->refs_lock, flags);
}
void
-nouveau_event_get(struct nouveau_eventh *handler)
+nvkm_event_get(struct nvkm_event *event, u32 types, int index)
{
- struct nouveau_event *event = handler->event;
- unsigned long flags;
- u32 m, t;
-
- if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags))
- return;
-
- spin_lock_irqsave(&event->refs_lock, flags);
- for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
- if (!event->refs[handler->index * event->types_nr + t]++) {
- if (event->enable)
- event->enable(event, 1 << t, handler->index);
+ BUG_ON(!spin_is_locked(&event->refs_lock));
+ while (types) {
+ int type = __ffs(types); types &= ~(1 << type);
+ if (++event->refs[index * event->types_nr + type] == 1) {
+ if (event->func->init)
+ event->func->init(event, 1 << type, index);
}
-
}
- spin_unlock_irqrestore(&event->refs_lock, flags);
-}
-
-static void
-nouveau_event_fini(struct nouveau_eventh *handler)
-{
- struct nouveau_event *event = handler->event;
- unsigned long flags;
- nouveau_event_put(handler);
- spin_lock_irqsave(&event->list_lock, flags);
- list_del(&handler->head);
- spin_unlock_irqrestore(&event->list_lock, flags);
-}
-
-static int
-nouveau_event_init(struct nouveau_event *event, u32 types, int index,
- int (*func)(void *, u32, int), void *priv,
- struct nouveau_eventh *handler)
-{
- unsigned long flags;
-
- if (types & ~((1 << event->types_nr) - 1))
- return -EINVAL;
- if (index >= event->index_nr)
- return -EINVAL;
-
- handler->event = event;
- handler->flags = 0;
- handler->types = types;
- handler->index = index;
- handler->func = func;
- handler->priv = priv;
-
- spin_lock_irqsave(&event->list_lock, flags);
- list_add_tail(&handler->head, &event->list[index]);
- spin_unlock_irqrestore(&event->list_lock, flags);
- return 0;
-}
-
-int
-nouveau_event_new(struct nouveau_event *event, u32 types, int index,
- int (*func)(void *, u32, int), void *priv,
- struct nouveau_eventh **phandler)
-{
- struct nouveau_eventh *handler;
- int ret = -ENOMEM;
-
- if (event->check) {
- ret = event->check(event, types, index);
- if (ret)
- return ret;
- }
-
- handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
- if (handler) {
- ret = nouveau_event_init(event, types, index, func, priv, handler);
- if (ret)
- kfree(handler);
- }
-
- return ret;
-}
-
-void
-nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
-{
- BUG_ON(handler != NULL);
- if (*ref) {
- nouveau_event_fini(*ref);
- kfree(*ref);
- }
- *ref = handler;
}
void
-nouveau_event_trigger(struct nouveau_event *event, u32 types, int index)
+nvkm_event_send(struct nvkm_event *event, u32 types, int index,
+ void *data, u32 size)
{
- struct nouveau_eventh *handler;
+ struct nvkm_notify *notify;
unsigned long flags;
- if (WARN_ON(index >= event->index_nr))
+ if (!event->refs || WARN_ON(index >= event->index_nr))
return;
spin_lock_irqsave(&event->list_lock, flags);
- list_for_each_entry(handler, &event->list[index], head) {
- if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags))
- continue;
- if (!(handler->types & types))
- continue;
- if (handler->func(handler->priv, handler->types & types, index)
- != NVKM_EVENT_DROP)
- continue;
- nouveau_event_put(handler);
+ list_for_each_entry(notify, &event->list, head) {
+ if (notify->index == index && (notify->types & types)) {
+ if (event->func->send) {
+ event->func->send(data, size, notify);
+ continue;
+ }
+ nvkm_notify_send(notify, data, size);
+ }
}
spin_unlock_irqrestore(&event->list_lock, flags);
}
void
-nouveau_event_destroy(struct nouveau_event **pevent)
+nvkm_event_fini(struct nvkm_event *event)
{
- struct nouveau_event *event = *pevent;
- if (event) {
- kfree(event);
- *pevent = NULL;
+ if (event->refs) {
+ kfree(event->refs);
+ event->refs = NULL;
}
}
int
-nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent)
+nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
+ struct nvkm_event *event)
{
- struct nouveau_event *event;
- int i;
-
- event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) *
- sizeof(event->refs[0]), GFP_KERNEL);
- if (!event)
- return -ENOMEM;
-
- event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL);
- if (!event->list) {
- kfree(event);
+ event->refs = kzalloc(sizeof(*event->refs) * index_nr * types_nr,
+ GFP_KERNEL);
+ if (!event->refs)
return -ENOMEM;
- }
- spin_lock_init(&event->list_lock);
- spin_lock_init(&event->refs_lock);
- for (i = 0; i < index_nr; i++)
- INIT_LIST_HEAD(&event->list[i]);
+ event->func = func;
event->types_nr = types_nr;
event->index_nr = index_nr;
+ spin_lock_init(&event->refs_lock);
+ spin_lock_init(&event->list_lock);
+ INIT_LIST_HEAD(&event->list);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c
index 264c2b338ac3..a490b805d7e3 100644
--- a/drivers/gpu/drm/nouveau/core/core/handle.c
+++ b/drivers/gpu/drm/nouveau/core/core/handle.c
@@ -146,9 +146,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle,
}
hprintk(handle, TRACE, "created\n");
-
*phandle = handle;
-
return 0;
}
@@ -224,3 +222,116 @@ nouveau_handle_put(struct nouveau_handle *handle)
if (handle)
nouveau_namedb_put(handle);
}
+
+int
+nouveau_handle_new(struct nouveau_object *client, u32 _parent, u32 _handle,
+ u16 _oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_object *parent = NULL;
+ struct nouveau_object *engctx = NULL;
+ struct nouveau_object *object = NULL;
+ struct nouveau_object *engine;
+ struct nouveau_oclass *oclass;
+ struct nouveau_handle *handle;
+ int ret;
+
+ /* lookup parent object and ensure it *is* a parent */
+ parent = nouveau_handle_ref(client, _parent);
+ if (!parent) {
+ nv_error(client, "parent 0x%08x not found\n", _parent);
+ return -ENOENT;
+ }
+
+ if (!nv_iclass(parent, NV_PARENT_CLASS)) {
+ nv_error(parent, "cannot have children\n");
+ ret = -EINVAL;
+ goto fail_class;
+ }
+
+ /* check that parent supports the requested subclass */
+ ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
+ if (ret) {
+ nv_debug(parent, "illegal class 0x%04x\n", _oclass);
+ goto fail_class;
+ }
+
+ /* make sure engine init has been completed *before* any objects
+ * it controls are created - the constructors may depend on
+ * state calculated at init (ie. default context construction)
+ */
+ if (engine) {
+ ret = nouveau_object_inc(engine);
+ if (ret)
+ goto fail_class;
+ }
+
+ /* if engine requires it, create a context object to insert
+ * between the parent and its children (eg. PGRAPH context)
+ */
+ if (engine && nv_engine(engine)->cclass) {
+ ret = nouveau_object_ctor(parent, engine,
+ nv_engine(engine)->cclass,
+ data, size, &engctx);
+ if (ret)
+ goto fail_engctx;
+ } else {
+ nouveau_object_ref(parent, &engctx);
+ }
+
+ /* finally, create new object and bind it to its handle */
+ ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
+ *pobject = object;
+ if (ret)
+ goto fail_ctor;
+
+ ret = nouveau_object_inc(object);
+ if (ret)
+ goto fail_init;
+
+ ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
+ if (ret)
+ goto fail_handle;
+
+ ret = nouveau_handle_init(handle);
+ if (ret)
+ nouveau_handle_destroy(handle);
+
+fail_handle:
+ nouveau_object_dec(object, false);
+fail_init:
+ nouveau_object_ref(NULL, &object);
+fail_ctor:
+ nouveau_object_ref(NULL, &engctx);
+fail_engctx:
+ if (engine)
+ nouveau_object_dec(engine, false);
+fail_class:
+ nouveau_object_ref(NULL, &parent);
+ return ret;
+}
+
+int
+nouveau_handle_del(struct nouveau_object *client, u32 _parent, u32 _handle)
+{
+ struct nouveau_object *parent = NULL;
+ struct nouveau_object *namedb = NULL;
+ struct nouveau_handle *handle = NULL;
+
+ parent = nouveau_handle_ref(client, _parent);
+ if (!parent)
+ return -ENOENT;
+
+ namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
+ if (namedb) {
+ handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
+ if (handle) {
+ nouveau_namedb_put(handle);
+ nouveau_handle_fini(handle, false);
+ nouveau_handle_destroy(handle);
+ }
+ }
+
+ nouveau_object_ref(NULL, &parent);
+ return handle ? 0 : -EINVAL;
+}
diff --git a/drivers/gpu/drm/nouveau/core/core/ioctl.c b/drivers/gpu/drm/nouveau/core/core/ioctl.c
new file mode 100644
index 000000000000..f7e19bfb489c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/core/ioctl.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <core/object.h>
+#include <core/parent.h>
+#include <core/handle.h>
+#include <core/namedb.h>
+#include <core/client.h>
+#include <core/device.h>
+#include <core/ioctl.h>
+#include <core/event.h>
+
+#include <nvif/unpack.h>
+#include <nvif/ioctl.h>
+
+static int
+nvkm_ioctl_nop(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_nop none;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "nop size %d\n", size);
+ if (nvif_unvers(args->none)) {
+ nv_ioctl(object, "nop\n");
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_sclass(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_sclass_v0 v0;
+ } *args = data;
+ int ret;
+
+ if (!nv_iclass(object, NV_PARENT_CLASS)) {
+ nv_debug(object, "cannot have children (sclass)\n");
+ return -ENODEV;
+ }
+
+ nv_ioctl(object, "sclass size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "sclass vers %d count %d\n",
+ args->v0.version, args->v0.count);
+ if (size == args->v0.count * sizeof(args->v0.oclass[0])) {
+ ret = nouveau_parent_lclass(object, args->v0.oclass,
+ args->v0.count);
+ if (ret >= 0) {
+ args->v0.count = ret;
+ ret = 0;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_new(struct nouveau_handle *parent, void *data, u32 size)
+{
+ union {
+ struct nvif_ioctl_new_v0 v0;
+ } *args = data;
+ struct nouveau_client *client = nouveau_client(parent->object);
+ struct nouveau_object *engctx = NULL;
+ struct nouveau_object *object = NULL;
+ struct nouveau_object *engine;
+ struct nouveau_oclass *oclass;
+ struct nouveau_handle *handle;
+ u32 _handle, _oclass;
+ int ret;
+
+ nv_ioctl(client, "new size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ _handle = args->v0.handle;
+ _oclass = args->v0.oclass;
+ } else
+ return ret;
+
+ nv_ioctl(client, "new vers %d handle %08x class %08x "
+ "route %02x token %llx\n",
+ args->v0.version, _handle, _oclass,
+ args->v0.route, args->v0.token);
+
+ if (!nv_iclass(parent->object, NV_PARENT_CLASS)) {
+ nv_debug(parent->object, "cannot have children (ctor)\n");
+ ret = -ENODEV;
+ goto fail_class;
+ }
+
+ /* check that parent supports the requested subclass */
+ ret = nouveau_parent_sclass(parent->object, _oclass, &engine, &oclass);
+ if (ret) {
+ nv_debug(parent->object, "illegal class 0x%04x\n", _oclass);
+ goto fail_class;
+ }
+
+ /* make sure engine init has been completed *before* any objects
+ * it controls are created - the constructors may depend on
+ * state calculated at init (ie. default context construction)
+ */
+ if (engine) {
+ ret = nouveau_object_inc(engine);
+ if (ret)
+ goto fail_class;
+ }
+
+ /* if engine requires it, create a context object to insert
+ * between the parent and its children (eg. PGRAPH context)
+ */
+ if (engine && nv_engine(engine)->cclass) {
+ ret = nouveau_object_ctor(parent->object, engine,
+ nv_engine(engine)->cclass,
+ data, size, &engctx);
+ if (ret)
+ goto fail_engctx;
+ } else {
+ nouveau_object_ref(parent->object, &engctx);
+ }
+
+ /* finally, create new object and bind it to its handle */
+ ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
+ client->data = object;
+ if (ret)
+ goto fail_ctor;
+
+ ret = nouveau_object_inc(object);
+ if (ret)
+ goto fail_init;
+
+ ret = nouveau_handle_create(parent->object, parent->name,
+ _handle, object, &handle);
+ if (ret)
+ goto fail_handle;
+
+ ret = nouveau_handle_init(handle);
+ handle->route = args->v0.route;
+ handle->token = args->v0.token;
+ if (ret)
+ nouveau_handle_destroy(handle);
+
+fail_handle:
+ nouveau_object_dec(object, false);
+fail_init:
+ nouveau_object_ref(NULL, &object);
+fail_ctor:
+ nouveau_object_ref(NULL, &engctx);
+fail_engctx:
+ if (engine)
+ nouveau_object_dec(engine, false);
+fail_class:
+ return ret;
+}
+
+static int
+nvkm_ioctl_del(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_del none;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "delete size %d\n", size);
+ if (nvif_unvers(args->none)) {
+ nv_ioctl(object, "delete\n");
+ nouveau_handle_fini(handle, false);
+ nouveau_handle_destroy(handle);
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_mthd(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+ union {
+ struct nvif_ioctl_mthd_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "mthd size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "mthd vers %d mthd %02x\n",
+ args->v0.version, args->v0.method);
+ if (ret = -ENODEV, ofuncs->mthd)
+ ret = ofuncs->mthd(object, args->v0.method, data, size);
+ }
+
+ return ret;
+}
+
+
+static int
+nvkm_ioctl_rd(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+ union {
+ struct nvif_ioctl_rd_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "rd size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "rd vers %d size %d addr %016llx\n",
+ args->v0.version, args->v0.size, args->v0.addr);
+ switch (args->v0.size) {
+ case 1:
+ if (ret = -ENODEV, ofuncs->rd08) {
+ args->v0.data = nv_ro08(object, args->v0.addr);
+ ret = 0;
+ }
+ break;
+ case 2:
+ if (ret = -ENODEV, ofuncs->rd16) {
+ args->v0.data = nv_ro16(object, args->v0.addr);
+ ret = 0;
+ }
+ break;
+ case 4:
+ if (ret = -ENODEV, ofuncs->rd32) {
+ args->v0.data = nv_ro32(object, args->v0.addr);
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_wr(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+ union {
+ struct nvif_ioctl_wr_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "wr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "wr vers %d size %d addr %016llx data %08x\n",
+ args->v0.version, args->v0.size, args->v0.addr,
+ args->v0.data);
+ switch (args->v0.size) {
+ case 1:
+ if (ret = -ENODEV, ofuncs->wr08) {
+ nv_wo08(object, args->v0.addr, args->v0.data);
+ ret = 0;
+ }
+ break;
+ case 2:
+ if (ret = -ENODEV, ofuncs->wr16) {
+ nv_wo16(object, args->v0.addr, args->v0.data);
+ ret = 0;
+ }
+ break;
+ case 4:
+ if (ret = -ENODEV, ofuncs->wr32) {
+ nv_wo32(object, args->v0.addr, args->v0.data);
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_map(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+ union {
+ struct nvif_ioctl_map_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "map size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "map vers %d\n", args->v0.version);
+ if (ret = -ENODEV, ofuncs->map) {
+ ret = ofuncs->map(object, &args->v0.handle,
+ &args->v0.length);
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_unmap(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_unmap none;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "unmap size %d\n", size);
+ if (nvif_unvers(args->none)) {
+ nv_ioctl(object, "unmap\n");
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_new(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_client *client = nouveau_client(handle->object);
+ struct nouveau_object *object = handle->object;
+ struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
+ union {
+ struct nvif_ioctl_ntfy_new_v0 v0;
+ } *args = data;
+ struct nvkm_event *event;
+ int ret;
+
+ nv_ioctl(object, "ntfy new size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "ntfy new vers %d event %02x\n",
+ args->v0.version, args->v0.event);
+ if (ret = -ENODEV, ofuncs->ntfy)
+ ret = ofuncs->ntfy(object, args->v0.event, &event);
+ if (ret == 0) {
+ ret = nvkm_client_notify_new(client, event, data, size);
+ if (ret >= 0) {
+ args->v0.index = ret;
+ ret = 0;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_del(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_client *client = nouveau_client(handle->object);
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_ntfy_del_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "ntfy del size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "ntfy del vers %d index %d\n",
+ args->v0.version, args->v0.index);
+ ret = nvkm_client_notify_del(client, args->v0.index);
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_get(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_client *client = nouveau_client(handle->object);
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_ntfy_get_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "ntfy get size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "ntfy get vers %d index %d\n",
+ args->v0.version, args->v0.index);
+ ret = nvkm_client_notify_get(client, args->v0.index);
+ }
+
+ return ret;
+}
+
+static int
+nvkm_ioctl_ntfy_put(struct nouveau_handle *handle, void *data, u32 size)
+{
+ struct nouveau_client *client = nouveau_client(handle->object);
+ struct nouveau_object *object = handle->object;
+ union {
+ struct nvif_ioctl_ntfy_put_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "ntfy put size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "ntfy put vers %d index %d\n",
+ args->v0.version, args->v0.index);
+ ret = nvkm_client_notify_put(client, args->v0.index);
+ }
+
+ return ret;
+}
+
+static struct {
+ int version;
+ int (*func)(struct nouveau_handle *, void *, u32);
+}
+nvkm_ioctl_v0[] = {
+ { 0x00, nvkm_ioctl_nop },
+ { 0x00, nvkm_ioctl_sclass },
+ { 0x00, nvkm_ioctl_new },
+ { 0x00, nvkm_ioctl_del },
+ { 0x00, nvkm_ioctl_mthd },
+ { 0x00, nvkm_ioctl_rd },
+ { 0x00, nvkm_ioctl_wr },
+ { 0x00, nvkm_ioctl_map },
+ { 0x00, nvkm_ioctl_unmap },
+ { 0x00, nvkm_ioctl_ntfy_new },
+ { 0x00, nvkm_ioctl_ntfy_del },
+ { 0x00, nvkm_ioctl_ntfy_get },
+ { 0x00, nvkm_ioctl_ntfy_put },
+};
+
+static int
+nvkm_ioctl_path(struct nouveau_handle *parent, u32 type, u32 nr,
+ u32 *path, void *data, u32 size,
+ u8 owner, u8 *route, u64 *token)
+{
+ struct nouveau_handle *handle = parent;
+ struct nouveau_namedb *namedb;
+ struct nouveau_object *object;
+ int ret;
+
+ while ((object = parent->object), nr--) {
+ nv_ioctl(object, "path 0x%08x\n", path[nr]);
+ if (!nv_iclass(object, NV_PARENT_CLASS)) {
+ nv_debug(object, "cannot have children (path)\n");
+ return -EINVAL;
+ }
+
+ if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) ||
+ !(handle = nouveau_namedb_get(namedb, path[nr]))) {
+ nv_debug(object, "handle 0x%08x not found\n", path[nr]);
+ return -ENOENT;
+ }
+ nouveau_namedb_put(handle);
+ parent = handle;
+ }
+
+ if (owner != NVIF_IOCTL_V0_OWNER_ANY &&
+ owner != handle->route) {
+ nv_ioctl(object, "object route != owner\n");
+ return -EACCES;
+ }
+ *route = handle->route;
+ *token = handle->token;
+
+ if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {
+ if (nvkm_ioctl_v0[type].version == 0) {
+ ret = nvkm_ioctl_v0[type].func(handle, data, size);
+ }
+ }
+
+ return ret;
+}
+
+int
+nvkm_ioctl(struct nouveau_client *client, bool supervisor,
+ void *data, u32 size, void **hack)
+{
+ union {
+ struct nvif_ioctl_v0 v0;
+ } *args = data;
+ int ret;
+
+ client->super = supervisor;
+ nv_ioctl(client, "size %d\n", size);
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(client, "vers %d type %02x path %d owner %02x\n",
+ args->v0.version, args->v0.type, args->v0.path_nr,
+ args->v0.owner);
+ ret = nvkm_ioctl_path(client->root, args->v0.type,
+ args->v0.path_nr, args->v0.path,
+ data, size, args->v0.owner,
+ &args->v0.route, &args->v0.token);
+ }
+
+ nv_ioctl(client, "return %d\n", ret);
+ if (hack) {
+ *hack = client->data;
+ client->data = NULL;
+ }
+ client->super = false;
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/core/core/notify.c b/drivers/gpu/drm/nouveau/core/core/notify.c
new file mode 100644
index 000000000000..76adb81bdea2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/core/notify.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <core/client.h>
+#include <core/event.h>
+#include <core/notify.h>
+
+#include <nvif/unpack.h>
+#include <nvif/event.h>
+
+static inline void
+nvkm_notify_put_locked(struct nvkm_notify *notify)
+{
+ if (notify->block++ == 0)
+ nvkm_event_put(notify->event, notify->types, notify->index);
+}
+
+void
+nvkm_notify_put(struct nvkm_notify *notify)
+{
+ struct nvkm_event *event = notify->event;
+ unsigned long flags;
+ if (likely(event) &&
+ test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+ spin_lock_irqsave(&event->refs_lock, flags);
+ nvkm_notify_put_locked(notify);
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+ if (test_bit(NVKM_NOTIFY_WORK, &notify->flags))
+ flush_work(&notify->work);
+ }
+}
+
+static inline void
+nvkm_notify_get_locked(struct nvkm_notify *notify)
+{
+ if (--notify->block == 0)
+ nvkm_event_get(notify->event, notify->types, notify->index);
+}
+
+void
+nvkm_notify_get(struct nvkm_notify *notify)
+{
+ struct nvkm_event *event = notify->event;
+ unsigned long flags;
+ if (likely(event) &&
+ !test_and_set_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+ spin_lock_irqsave(&event->refs_lock, flags);
+ nvkm_notify_get_locked(notify);
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+ }
+}
+
+static inline void
+nvkm_notify_func(struct nvkm_notify *notify)
+{
+ struct nvkm_event *event = notify->event;
+ int ret = notify->func(notify);
+ unsigned long flags;
+ if ((ret == NVKM_NOTIFY_KEEP) ||
+ !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+ spin_lock_irqsave(&event->refs_lock, flags);
+ nvkm_notify_get_locked(notify);
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+ }
+}
+
+static void
+nvkm_notify_work(struct work_struct *work)
+{
+ struct nvkm_notify *notify = container_of(work, typeof(*notify), work);
+ nvkm_notify_func(notify);
+}
+
+void
+nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size)
+{
+ struct nvkm_event *event = notify->event;
+ unsigned long flags;
+
+ BUG_ON(!spin_is_locked(&event->list_lock));
+ BUG_ON(size != notify->size);
+
+ spin_lock_irqsave(&event->refs_lock, flags);
+ if (notify->block) {
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+ return;
+ }
+ nvkm_notify_put_locked(notify);
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+
+ if (test_bit(NVKM_NOTIFY_WORK, &notify->flags)) {
+ memcpy((void *)notify->data, data, size);
+ schedule_work(&notify->work);
+ } else {
+ notify->data = data;
+ nvkm_notify_func(notify);
+ notify->data = NULL;
+ }
+}
+
+void
+nvkm_notify_fini(struct nvkm_notify *notify)
+{
+ unsigned long flags;
+ if (notify->event) {
+ nvkm_notify_put(notify);
+ spin_lock_irqsave(&notify->event->list_lock, flags);
+ list_del(&notify->head);
+ spin_unlock_irqrestore(&notify->event->list_lock, flags);
+ kfree((void *)notify->data);
+ notify->event = NULL;
+ }
+}
+
+int
+nvkm_notify_init(struct nvkm_event *event, int (*func)(struct nvkm_notify *),
+ bool work, void *data, u32 size, u32 reply,
+ struct nvkm_notify *notify)
+{
+ unsigned long flags;
+ int ret = -ENODEV;
+ if ((notify->event = event), event->refs) {
+ ret = event->func->ctor(data, size, notify);
+ if (ret == 0 && (ret = -EINVAL, notify->size == reply)) {
+ notify->flags = 0;
+ notify->block = 1;
+ notify->func = func;
+ notify->data = NULL;
+ if (ret = 0, work) {
+ INIT_WORK(&notify->work, nvkm_notify_work);
+ set_bit(NVKM_NOTIFY_WORK, &notify->flags);
+ notify->data = kmalloc(reply, GFP_KERNEL);
+ if (!notify->data)
+ ret = -ENOMEM;
+ }
+ }
+ if (ret == 0) {
+ spin_lock_irqsave(&event->list_lock, flags);
+ list_add_tail(&notify->head, &event->list);
+ spin_unlock_irqrestore(&event->list_lock, flags);
+ }
+ }
+ if (ret)
+ notify->event = NULL;
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c
index 124538555904..b08630577c82 100644
--- a/drivers/gpu/drm/nouveau/core/core/object.c
+++ b/drivers/gpu/drm/nouveau/core/core/object.c
@@ -23,9 +23,6 @@
*/
#include <core/object.h>
-#include <core/parent.h>
-#include <core/namedb.h>
-#include <core/handle.h>
#include <core/engine.h>
#ifdef NOUVEAU_OBJECT_MAGIC
@@ -61,21 +58,15 @@ nouveau_object_create_(struct nouveau_object *parent,
return 0;
}
-static int
+int
_nouveau_object_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nouveau_object *object;
- int ret;
-
- ret = nouveau_object_create(parent, engine, oclass, 0, &object);
- *pobject = nv_object(object);
- if (ret)
- return ret;
-
- return 0;
+ if (size != 0)
+ return -ENOSYS;
+ return nouveau_object_create(parent, engine, oclass, 0, pobject);
}
void
@@ -91,42 +82,24 @@ nouveau_object_destroy(struct nouveau_object *object)
kfree(object);
}
-static void
-_nouveau_object_dtor(struct nouveau_object *object)
-{
- nouveau_object_destroy(object);
-}
-
int
nouveau_object_init(struct nouveau_object *object)
{
return 0;
}
-static int
-_nouveau_object_init(struct nouveau_object *object)
-{
- return nouveau_object_init(object);
-}
-
int
nouveau_object_fini(struct nouveau_object *object, bool suspend)
{
return 0;
}
-static int
-_nouveau_object_fini(struct nouveau_object *object, bool suspend)
-{
- return nouveau_object_fini(object, suspend);
-}
-
struct nouveau_ofuncs
nouveau_object_ofuncs = {
.ctor = _nouveau_object_ctor,
- .dtor = _nouveau_object_dtor,
- .init = _nouveau_object_init,
- .fini = _nouveau_object_fini,
+ .dtor = nouveau_object_destroy,
+ .init = nouveau_object_init,
+ .fini = nouveau_object_fini,
};
int
@@ -189,119 +162,6 @@ nouveau_object_ref(struct nouveau_object *obj, struct nouveau_object **ref)
}
int
-nouveau_object_new(struct nouveau_object *client, u32 _parent, u32 _handle,
- u16 _oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nouveau_object *parent = NULL;
- struct nouveau_object *engctx = NULL;
- struct nouveau_object *object = NULL;
- struct nouveau_object *engine;
- struct nouveau_oclass *oclass;
- struct nouveau_handle *handle;
- int ret;
-
- /* lookup parent object and ensure it *is* a parent */
- parent = nouveau_handle_ref(client, _parent);
- if (!parent) {
- nv_error(client, "parent 0x%08x not found\n", _parent);
- return -ENOENT;
- }
-
- if (!nv_iclass(parent, NV_PARENT_CLASS)) {
- nv_error(parent, "cannot have children\n");
- ret = -EINVAL;
- goto fail_class;
- }
-
- /* check that parent supports the requested subclass */
- ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
- if (ret) {
- nv_debug(parent, "illegal class 0x%04x\n", _oclass);
- goto fail_class;
- }
-
- /* make sure engine init has been completed *before* any objects
- * it controls are created - the constructors may depend on
- * state calculated at init (ie. default context construction)
- */
- if (engine) {
- ret = nouveau_object_inc(engine);
- if (ret)
- goto fail_class;
- }
-
- /* if engine requires it, create a context object to insert
- * between the parent and its children (eg. PGRAPH context)
- */
- if (engine && nv_engine(engine)->cclass) {
- ret = nouveau_object_ctor(parent, engine,
- nv_engine(engine)->cclass,
- data, size, &engctx);
- if (ret)
- goto fail_engctx;
- } else {
- nouveau_object_ref(parent, &engctx);
- }
-
- /* finally, create new object and bind it to its handle */
- ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
- *pobject = object;
- if (ret)
- goto fail_ctor;
-
- ret = nouveau_object_inc(object);
- if (ret)
- goto fail_init;
-
- ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
- if (ret)
- goto fail_handle;
-
- ret = nouveau_handle_init(handle);
- if (ret)
- nouveau_handle_destroy(handle);
-
-fail_handle:
- nouveau_object_dec(object, false);
-fail_init:
- nouveau_object_ref(NULL, &object);
-fail_ctor:
- nouveau_object_ref(NULL, &engctx);
-fail_engctx:
- if (engine)
- nouveau_object_dec(engine, false);
-fail_class:
- nouveau_object_ref(NULL, &parent);
- return ret;
-}
-
-int
-nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
-{
- struct nouveau_object *parent = NULL;
- struct nouveau_object *namedb = NULL;
- struct nouveau_handle *handle = NULL;
-
- parent = nouveau_handle_ref(client, _parent);
- if (!parent)
- return -ENOENT;
-
- namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
- if (namedb) {
- handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
- if (handle) {
- nouveau_namedb_put(handle);
- nouveau_handle_fini(handle, false);
- nouveau_handle_destroy(handle);
- }
- }
-
- nouveau_object_ref(NULL, &parent);
- return handle ? 0 : -EINVAL;
-}
-
-int
nouveau_object_inc(struct nouveau_object *object)
{
int ref = atomic_add_return(1, &object->usecount);
diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c
index dee5d1235e9b..8701968a9743 100644
--- a/drivers/gpu/drm/nouveau/core/core/parent.c
+++ b/drivers/gpu/drm/nouveau/core/core/parent.c
@@ -75,6 +75,39 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
}
int
+nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
+{
+ struct nouveau_sclass *sclass;
+ struct nouveau_engine *engine;
+ struct nouveau_oclass *oclass;
+ int nr = -1, i;
+ u64 mask;
+
+ sclass = nv_parent(parent)->sclass;
+ while (sclass) {
+ if (++nr < size)
+ lclass[nr] = sclass->oclass->handle;
+ sclass = sclass->sclass;
+ }
+
+ mask = nv_parent(parent)->engine;
+ while (i = __ffs64(mask), mask) {
+ engine = nouveau_engine(parent, i);
+ if (engine && (oclass = engine->sclass)) {
+ while (oclass->ofuncs) {
+ if (++nr < size)
+ lclass[nr] = oclass->handle;
+ oclass++;
+ }
+ }
+
+ mask &= ~(1ULL << i);
+ }
+
+ return nr + 1;
+}
+
+int
nouveau_parent_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, u32 pclass,
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
index f31527733e00..abb410ef09ea 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
@@ -30,7 +30,6 @@
#include <subdev/vm.h>
#include <core/client.h>
-#include <core/class.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
index ac3291f781f6..9261694d0d35 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
@@ -26,9 +26,7 @@
#include <engine/fifo.h>
#include <engine/copy.h>
-#include <core/class.h>
#include <core/enum.h>
-#include <core/class.h>
#include <core/enum.h>
#include "fuc/nvc0.fuc.h"
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
index 748a61eb3c6f..c7194b354605 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
@@ -24,7 +24,6 @@
#include <core/os.h>
#include <core/enum.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <engine/copy.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
index 2551dafbec73..ea5c42f31791 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
@@ -25,7 +25,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/gpuobj.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
index c7082377ec76..5571c09534cb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
@@ -25,7 +25,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <subdev/timer.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/acpi.c b/drivers/gpu/drm/nouveau/core/engine/device/acpi.c
new file mode 100644
index 000000000000..4dbf0ba89e5c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/acpi.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "acpi.h"
+
+#ifdef CONFIG_ACPI
+static int
+nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data)
+{
+ struct nouveau_device *device =
+ container_of(nb, typeof(*device), acpi.nb);
+ struct acpi_bus_event *info = data;
+
+ if (!strcmp(info->device_class, "ac_adapter"))
+ nvkm_event_send(&device->event, 1, 0, NULL, 0);
+
+ return NOTIFY_DONE;
+}
+#endif
+
+int
+nvkm_acpi_fini(struct nouveau_device *device, bool suspend)
+{
+#ifdef CONFIG_ACPI
+ unregister_acpi_notifier(&device->acpi.nb);
+#endif
+ return 0;
+}
+
+int
+nvkm_acpi_init(struct nouveau_device *device)
+{
+#ifdef CONFIG_ACPI
+ device->acpi.nb.notifier_call = nvkm_acpi_ntfy;
+ register_acpi_notifier(&device->acpi.nb);
+#endif
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/acpi.h b/drivers/gpu/drm/nouveau/core/engine/device/acpi.h
new file mode 100644
index 000000000000..cc49f4f568cd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/acpi.h
@@ -0,0 +1,9 @@
+#ifndef __NVKM_DEVICE_ACPI_H__
+#define __NVKM_DEVICE_ACPI_H__
+
+#include <engine/device.h>
+
+int nvkm_acpi_init(struct nouveau_device *);
+int nvkm_acpi_fini(struct nouveau_device *, bool);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index 18c8c7245b73..8928f7981d4a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -26,10 +26,14 @@
#include <core/device.h>
#include <core/client.h>
#include <core/option.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
-#include <core/class.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
#include "priv.h"
+#include "acpi.h"
static DEFINE_MUTEX(nv_devices_mutex);
static LIST_HEAD(nv_devices);
@@ -49,74 +53,258 @@ nouveau_device_find(u64 name)
return match;
}
+int
+nouveau_device_list(u64 *name, int size)
+{
+ struct nouveau_device *device;
+ int nr = 0;
+ mutex_lock(&nv_devices_mutex);
+ list_for_each_entry(device, &nv_devices, head) {
+ if (nr++ < size)
+ name[nr - 1] = device->handle;
+ }
+ mutex_unlock(&nv_devices_mutex);
+ return nr;
+}
+
/******************************************************************************
* nouveau_devobj (0x0080): class implementation
*****************************************************************************/
+
struct nouveau_devobj {
struct nouveau_parent base;
struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
};
+static int
+nouveau_devobj_info(struct nouveau_object *object, void *data, u32 size)
+{
+ struct nouveau_device *device = nv_device(object);
+ struct nouveau_fb *pfb = nouveau_fb(device);
+ struct nouveau_instmem *imem = nouveau_instmem(device);
+ union {
+ struct nv_device_info_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "device info size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "device info vers %d\n", args->v0.version);
+ } else
+ return ret;
+
+ switch (device->chipset) {
+ case 0x01a:
+ case 0x01f:
+ case 0x04c:
+ case 0x04e:
+ case 0x063:
+ case 0x067:
+ case 0x068:
+ case 0x0aa:
+ case 0x0ac:
+ case 0x0af:
+ args->v0.platform = NV_DEVICE_INFO_V0_IGP;
+ break;
+ default:
+ if (device->pdev) {
+ if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP))
+ args->v0.platform = NV_DEVICE_INFO_V0_AGP;
+ else
+ if (pci_is_pcie(device->pdev))
+ args->v0.platform = NV_DEVICE_INFO_V0_PCIE;
+ else
+ args->v0.platform = NV_DEVICE_INFO_V0_PCI;
+ } else {
+ args->v0.platform = NV_DEVICE_INFO_V0_SOC;
+ }
+ break;
+ }
+
+ switch (device->card_type) {
+ case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break;
+ case NV_10:
+ case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break;
+ case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break;
+ case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break;
+ case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break;
+ case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break;
+ case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break;
+ case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break;
+ case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
+ default:
+ args->v0.family = 0;
+ break;
+ }
+
+ args->v0.chipset = device->chipset;
+ args->v0.revision = device->chipset >= 0x10 ? nv_rd32(device, 0) : 0x00;
+ if (pfb) args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
+ else args->v0.ram_size = args->v0.ram_user = 0;
+ if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved;
+ return 0;
+}
+
+static int
+nouveau_devobj_mthd(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ switch (mthd) {
+ case NV_DEVICE_V0_INFO:
+ return nouveau_devobj_info(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
+static u8
+nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd08(object->engine, addr);
+}
+
+static u16
+nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd16(object->engine, addr);
+}
+
+static u32
+nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd32(object->engine, addr);
+}
+
+static void
+nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
+{
+ nv_wr08(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
+{
+ nv_wr16(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+ nv_wr32(object->engine, addr, data);
+}
+
+static int
+nouveau_devobj_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+ struct nouveau_device *device = nv_device(object);
+ *addr = nv_device_resource_start(device, 0);
+ *size = nv_device_resource_len(device, 0);
+ return 0;
+}
+
static const u64 disable_map[] = {
- [NVDEV_SUBDEV_VBIOS] = NV_DEVICE_DISABLE_VBIOS,
- [NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_GPIO] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_I2C] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_IBUS] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_VM] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_SUBDEV_PWR] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_ENGINE_PERFMON] = NV_DEVICE_DISABLE_CORE,
- [NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO,
- [NVDEV_ENGINE_SW] = NV_DEVICE_DISABLE_FIFO,
- [NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH,
- [NVDEV_ENGINE_MPEG] = NV_DEVICE_DISABLE_MPEG,
- [NVDEV_ENGINE_ME] = NV_DEVICE_DISABLE_ME,
- [NVDEV_ENGINE_VP] = NV_DEVICE_DISABLE_VP,
- [NVDEV_ENGINE_CRYPT] = NV_DEVICE_DISABLE_CRYPT,
- [NVDEV_ENGINE_BSP] = NV_DEVICE_DISABLE_BSP,
- [NVDEV_ENGINE_PPP] = NV_DEVICE_DISABLE_PPP,
- [NVDEV_ENGINE_COPY0] = NV_DEVICE_DISABLE_COPY0,
- [NVDEV_ENGINE_COPY1] = NV_DEVICE_DISABLE_COPY1,
- [NVDEV_ENGINE_VIC] = NV_DEVICE_DISABLE_VIC,
- [NVDEV_ENGINE_VENC] = NV_DEVICE_DISABLE_VENC,
- [NVDEV_ENGINE_DISP] = NV_DEVICE_DISABLE_DISP,
+ [NVDEV_SUBDEV_VBIOS] = NV_DEVICE_V0_DISABLE_VBIOS,
+ [NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_GPIO] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_I2C] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_MXM] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_MC] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_BUS] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_TIMER] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_FB] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_LTC] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_IBUS] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_VM] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_BAR] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_VOLT] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_THERM] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_SUBDEV_PWR] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_ENGINE_PERFMON] = NV_DEVICE_V0_DISABLE_CORE,
+ [NVDEV_ENGINE_FIFO] = NV_DEVICE_V0_DISABLE_FIFO,
+ [NVDEV_ENGINE_SW] = NV_DEVICE_V0_DISABLE_FIFO,
+ [NVDEV_ENGINE_GR] = NV_DEVICE_V0_DISABLE_GRAPH,
+ [NVDEV_ENGINE_MPEG] = NV_DEVICE_V0_DISABLE_MPEG,
+ [NVDEV_ENGINE_ME] = NV_DEVICE_V0_DISABLE_ME,
+ [NVDEV_ENGINE_VP] = NV_DEVICE_V0_DISABLE_VP,
+ [NVDEV_ENGINE_CRYPT] = NV_DEVICE_V0_DISABLE_CRYPT,
+ [NVDEV_ENGINE_BSP] = NV_DEVICE_V0_DISABLE_BSP,
+ [NVDEV_ENGINE_PPP] = NV_DEVICE_V0_DISABLE_PPP,
+ [NVDEV_ENGINE_COPY0] = NV_DEVICE_V0_DISABLE_COPY0,
+ [NVDEV_ENGINE_COPY1] = NV_DEVICE_V0_DISABLE_COPY1,
+ [NVDEV_ENGINE_VIC] = NV_DEVICE_V0_DISABLE_VIC,
+ [NVDEV_ENGINE_VENC] = NV_DEVICE_V0_DISABLE_VENC,
+ [NVDEV_ENGINE_DISP] = NV_DEVICE_V0_DISABLE_DISP,
[NVDEV_SUBDEV_NR] = 0,
};
+static void
+nouveau_devobj_dtor(struct nouveau_object *object)
+{
+ struct nouveau_devobj *devobj = (void *)object;
+ int i;
+
+ for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
+ nouveau_object_ref(NULL, &devobj->subdev[i]);
+
+ nouveau_parent_destroy(&devobj->base);
+}
+
+static struct nouveau_oclass
+nouveau_devobj_oclass_super = {
+ .handle = NV_DEVICE,
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .dtor = nouveau_devobj_dtor,
+ .init = _nouveau_parent_init,
+ .fini = _nouveau_parent_fini,
+ .mthd = nouveau_devobj_mthd,
+ .map = nouveau_devobj_map,
+ .rd08 = nouveau_devobj_rd08,
+ .rd16 = nouveau_devobj_rd16,
+ .rd32 = nouveau_devobj_rd32,
+ .wr08 = nouveau_devobj_wr08,
+ .wr16 = nouveau_devobj_wr16,
+ .wr32 = nouveau_devobj_wr32,
+ }
+};
+
static int
nouveau_devobj_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv_device_v0 v0;
+ } *args = data;
struct nouveau_client *client = nv_client(parent);
struct nouveau_device *device;
struct nouveau_devobj *devobj;
- struct nv_device_class *args = data;
u32 boot0, strap;
u64 disable, mmio_base, mmio_size;
void __iomem *map;
int ret, i, c;
- if (size < sizeof(struct nv_device_class))
- return -EINVAL;
+ nv_ioctl(parent, "create device size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create device v%d device %016llx "
+ "disable %016llx debug0 %016llx\n",
+ args->v0.version, args->v0.device,
+ args->v0.disable, args->v0.debug0);
+ } else
+ return ret;
+
+ /* give priviledged clients register access */
+ if (client->super)
+ oclass = &nouveau_devobj_oclass_super;
/* find the device subdev that matches what the client requested */
device = nv_device(client->device);
- if (args->device != ~0) {
- device = nouveau_device_find(args->device);
+ if (args->v0.device != ~0) {
+ device = nouveau_device_find(args->v0.device);
if (!device)
return -ENODEV;
}
@@ -135,14 +323,14 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
mmio_size = nv_device_resource_len(device, 0);
/* translate api disable mask into internal mapping */
- disable = args->debug0;
+ disable = args->v0.debug0;
for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
- if (args->disable & disable_map[i])
+ if (args->v0.disable & disable_map[i])
disable |= (1ULL << i);
}
/* identify the chipset, and determine classes of subdev/engines */
- if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
+ if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY) &&
!device->card_type) {
map = ioremap(mmio_base, 0x102000);
if (map == NULL)
@@ -180,8 +368,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
case 0x080:
case 0x090:
case 0x0a0: device->card_type = NV_50; break;
- case 0x0c0: device->card_type = NV_C0; break;
- case 0x0d0: device->card_type = NV_D0; break;
+ case 0x0c0:
+ case 0x0d0: device->card_type = NV_C0; break;
case 0x0e0:
case 0x0f0:
case 0x100: device->card_type = NV_E0; break;
@@ -206,8 +394,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
case NV_30: ret = nv30_identify(device); break;
case NV_40: ret = nv40_identify(device); break;
case NV_50: ret = nv50_identify(device); break;
- case NV_C0:
- case NV_D0: ret = nvc0_identify(device); break;
+ case NV_C0: ret = nvc0_identify(device); break;
case NV_E0: ret = nve0_identify(device); break;
case GM100: ret = gm100_identify(device); break;
default:
@@ -242,7 +429,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
}
- if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
+ if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_MMIO) &&
!nv_subdev(device)->mmio) {
nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size);
if (!nv_subdev(device)->mmio) {
@@ -298,71 +485,19 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
return 0;
}
-static void
-nouveau_devobj_dtor(struct nouveau_object *object)
-{
- struct nouveau_devobj *devobj = (void *)object;
- int i;
-
- for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
- nouveau_object_ref(NULL, &devobj->subdev[i]);
-
- nouveau_parent_destroy(&devobj->base);
-}
-
-static u8
-nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
-{
- return nv_rd08(object->engine, addr);
-}
-
-static u16
-nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
-{
- return nv_rd16(object->engine, addr);
-}
-
-static u32
-nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
-{
- return nv_rd32(object->engine, addr);
-}
-
-static void
-nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
-{
- nv_wr08(object->engine, addr, data);
-}
-
-static void
-nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
-{
- nv_wr16(object->engine, addr, data);
-}
-
-static void
-nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
- nv_wr32(object->engine, addr, data);
-}
-
static struct nouveau_ofuncs
nouveau_devobj_ofuncs = {
.ctor = nouveau_devobj_ctor,
.dtor = nouveau_devobj_dtor,
.init = _nouveau_parent_init,
.fini = _nouveau_parent_fini,
- .rd08 = nouveau_devobj_rd08,
- .rd16 = nouveau_devobj_rd16,
- .rd32 = nouveau_devobj_rd32,
- .wr08 = nouveau_devobj_wr08,
- .wr16 = nouveau_devobj_wr16,
- .wr32 = nouveau_devobj_wr32,
+ .mthd = nouveau_devobj_mthd,
};
/******************************************************************************
* nouveau_device: engine functions
*****************************************************************************/
+
static struct nouveau_oclass
nouveau_device_sclass[] = {
{ 0x0080, &nouveau_devobj_ofuncs },
@@ -370,6 +505,23 @@ nouveau_device_sclass[] = {
};
static int
+nouveau_device_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ if (!WARN_ON(size != 0)) {
+ notify->size = 0;
+ notify->types = 1;
+ notify->index = 0;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static const struct nvkm_event_func
+nouveau_device_event_func = {
+ .ctor = nouveau_device_event_ctor,
+};
+
+static int
nouveau_device_fini(struct nouveau_object *object, bool suspend)
{
struct nouveau_device *device = (void *)object;
@@ -386,7 +538,7 @@ nouveau_device_fini(struct nouveau_object *object, bool suspend)
}
}
- ret = 0;
+ ret = nvkm_acpi_fini(device, suspend);
fail:
for (; ret && i < NVDEV_SUBDEV_NR; i++) {
if ((subdev = device->subdev[i])) {
@@ -407,7 +559,11 @@ nouveau_device_init(struct nouveau_object *object)
{
struct nouveau_device *device = (void *)object;
struct nouveau_object *subdev;
- int ret, i;
+ int ret, i = 0;
+
+ ret = nvkm_acpi_init(device);
+ if (ret)
+ goto fail;
for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
if ((subdev = device->subdev[i])) {
@@ -430,6 +586,8 @@ fail:
}
}
+ if (ret)
+ nvkm_acpi_fini(device, false);
return ret;
}
@@ -438,6 +596,8 @@ nouveau_device_dtor(struct nouveau_object *object)
{
struct nouveau_device *device = (void *)object;
+ nvkm_event_fini(&device->event);
+
mutex_lock(&nv_devices_mutex);
list_del(&device->head);
mutex_unlock(&nv_devices_mutex);
@@ -478,31 +638,6 @@ nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
}
}
-dma_addr_t
-nv_device_map_page(struct nouveau_device *device, struct page *page)
-{
- dma_addr_t ret;
-
- if (nv_device_is_pci(device)) {
- ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
- if (pci_dma_mapping_error(device->pdev, ret))
- ret = 0;
- } else {
- ret = page_to_phys(page);
- }
-
- return ret;
-}
-
-void
-nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
-{
- if (nv_device_is_pci(device))
- pci_unmap_page(device->pdev, addr, PAGE_SIZE,
- PCI_DMA_BIDIRECTIONAL);
-}
-
int
nv_device_get_irq(struct nouveau_device *device, bool stall)
{
@@ -560,6 +695,9 @@ nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
nv_engine(device)->sclass = nouveau_device_sclass;
list_add(&device->head, &nv_devices);
+
+ ret = nvkm_event_init(&nouveau_device_event_func, 1, 1,
+ &device->event);
done:
mutex_unlock(&nv_devices_mutex);
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
index 4b69bf56ed01..e34101a3490e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
@@ -22,55 +22,82 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
+#include <core/client.h>
#include <core/object.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
#include <subdev/clock.h>
#include "priv.h"
static int
-nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_control_mthd_pstate_info(struct nouveau_object *object,
+ void *data, u32 size)
{
+ union {
+ struct nvif_control_pstate_info_v0 v0;
+ } *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
- struct nv_control_pstate_info *args = data;
+ int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(object, "control pstate info size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "control pstate info vers %d\n",
+ args->v0.version);
+ } else
+ return ret;
if (clk) {
- args->count = clk->state_nr;
- args->ustate = clk->ustate;
- args->pstate = clk->pstate;
+ args->v0.count = clk->state_nr;
+ args->v0.ustate_ac = clk->ustate_ac;
+ args->v0.ustate_dc = clk->ustate_dc;
+ args->v0.pwrsrc = clk->pwrsrc;
+ args->v0.pstate = clk->pstate;
} else {
- args->count = 0;
- args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
- args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN;
+ args->v0.count = 0;
+ args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
+ args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
+ args->v0.pwrsrc = -ENOSYS;
+ args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
}
return 0;
}
static int
-nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_control_mthd_pstate_attr(struct nouveau_object *object,
+ void *data, u32 size)
{
+ union {
+ struct nvif_control_pstate_attr_v0 v0;
+ } *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
- struct nv_control_pstate_attr *args = data;
struct nouveau_clocks *domain;
struct nouveau_pstate *pstate;
struct nouveau_cstate *cstate;
int i = 0, j = -1;
u32 lo, hi;
-
- if ((size < sizeof(*args)) || !clk ||
- (args->state >= 0 && args->state >= clk->state_nr))
- return -EINVAL;
+ int ret;
+
+ nv_ioctl(object, "control pstate attr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "control pstate attr vers %d state %d "
+ "index %d\n",
+ args->v0.version, args->v0.state, args->v0.index);
+ if (!clk)
+ return -ENODEV;
+ if (args->v0.state < NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT)
+ return -EINVAL;
+ if (args->v0.state >= clk->state_nr)
+ return -EINVAL;
+ } else
+ return ret;
domain = clk->domains;
while (domain->name != nv_clk_src_max) {
- if (domain->mname && ++j == args->index)
+ if (domain->mname && ++j == args->v0.index)
break;
domain++;
}
@@ -78,9 +105,9 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
if (domain->name == nv_clk_src_max)
return -EINVAL;
- if (args->state != NV_CONTROL_PSTATE_ATTR_STATE_CURRENT) {
+ if (args->v0.state != NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT) {
list_for_each_entry(pstate, &clk->states, head) {
- if (i++ == args->state)
+ if (i++ == args->v0.state)
break;
}
@@ -91,21 +118,21 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
hi = max(hi, cstate->domain[domain->name]);
}
- args->state = pstate->pstate;
+ args->v0.state = pstate->pstate;
} else {
lo = max(clk->read(clk, domain->name), 0);
hi = lo;
}
- snprintf(args->name, sizeof(args->name), "%s", domain->mname);
- snprintf(args->unit, sizeof(args->unit), "MHz");
- args->min = lo / domain->mdiv;
- args->max = hi / domain->mdiv;
+ snprintf(args->v0.name, sizeof(args->v0.name), "%s", domain->mname);
+ snprintf(args->v0.unit, sizeof(args->v0.unit), "MHz");
+ args->v0.min = lo / domain->mdiv;
+ args->v0.max = hi / domain->mdiv;
- args->index = 0;
+ args->v0.index = 0;
while ((++domain)->name != nv_clk_src_max) {
if (domain->mname) {
- args->index = ++j;
+ args->v0.index = ++j;
break;
}
}
@@ -114,31 +141,65 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
}
static int
-nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_control_mthd_pstate_user(struct nouveau_object *object,
+ void *data, u32 size)
{
+ union {
+ struct nvif_control_pstate_user_v0 v0;
+ } *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
- struct nv_control_pstate_user *args = data;
+ int ret;
+
+ nv_ioctl(object, "control pstate user size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "control pstate user vers %d ustate %d "
+ "pwrsrc %d\n", args->v0.version,
+ args->v0.ustate, args->v0.pwrsrc);
+ if (!clk)
+ return -ENODEV;
+ } else
+ return ret;
+
+ if (args->v0.pwrsrc >= 0) {
+ ret |= nouveau_clock_ustate(clk, args->v0.ustate, args->v0.pwrsrc);
+ } else {
+ ret |= nouveau_clock_ustate(clk, args->v0.ustate, 0);
+ ret |= nouveau_clock_ustate(clk, args->v0.ustate, 1);
+ }
- if (size < sizeof(*args) || !clk)
- return -EINVAL;
+ return ret;
+}
- return nouveau_clock_ustate(clk, args->state);
+static int
+nouveau_control_mthd(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ switch (mthd) {
+ case NVIF_CONTROL_PSTATE_INFO:
+ return nouveau_control_mthd_pstate_info(object, data, size);
+ case NVIF_CONTROL_PSTATE_ATTR:
+ return nouveau_control_mthd_pstate_attr(object, data, size);
+ case NVIF_CONTROL_PSTATE_USER:
+ return nouveau_control_mthd_pstate_user(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
}
+static struct nouveau_ofuncs
+nouveau_control_ofuncs = {
+ .ctor = _nouveau_object_ctor,
+ .dtor = nouveau_object_destroy,
+ .init = nouveau_object_init,
+ .fini = nouveau_object_fini,
+ .mthd = nouveau_control_mthd,
+};
+
struct nouveau_oclass
nouveau_control_oclass[] = {
- { .handle = NV_CONTROL_CLASS,
- .ofuncs = &nouveau_object_ofuncs,
- .omthds = (struct nouveau_omthds[]) {
- { NV_CONTROL_PSTATE_INFO,
- NV_CONTROL_PSTATE_INFO, nouveau_control_mthd_pstate_info },
- { NV_CONTROL_PSTATE_ATTR,
- NV_CONTROL_PSTATE_ATTR, nouveau_control_mthd_pstate_attr },
- { NV_CONTROL_PSTATE_USER,
- NV_CONTROL_PSTATE_USER, nouveau_control_mthd_pstate_user },
- {},
- },
+ { .handle = NVIF_IOCTL_NEW_V0_CONTROL,
+ .ofuncs = &nouveau_control_ofuncs
},
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
index a520029e25d9..377ec0b8851e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
@@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@@ -68,20 +68,20 @@ gm100_identify(struct nouveau_device *device)
#endif
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = gm107_devinit_oclass;
- device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gm107_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gm107_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
#if 0
- device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
#endif
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gm107_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
index 40b29d0214cb..573b55f5c2f9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
@@ -56,7 +56,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
@@ -74,7 +74,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
index 5f7c25ff523d..183a85a6204e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
@@ -58,7 +58,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
break;
@@ -75,7 +75,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -94,7 +94,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -113,7 +113,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -132,7 +132,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -151,7 +151,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -170,7 +170,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@@ -189,7 +189,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
index 75fed11bba0a..aa564c68a920 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
@@ -59,7 +59,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv20_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass;
@@ -78,7 +78,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
@@ -97,7 +97,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
@@ -116,7 +116,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
index 36919d7db7cc..11bd31da82ab 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
@@ -59,7 +59,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
@@ -78,7 +78,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv35_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
@@ -97,7 +97,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
@@ -117,7 +117,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv36_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
@@ -137,7 +137,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
index 1130a62be2c7..e96c223cb797 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -65,7 +65,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -88,7 +88,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -111,7 +111,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -134,7 +134,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -157,7 +157,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -180,7 +180,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -203,7 +203,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -226,7 +226,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -249,7 +249,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -272,7 +272,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -295,7 +295,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -341,7 +341,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -364,7 +364,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -387,7 +387,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@@ -410,7 +410,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
index ef0b0bde1a91..932f84fae459 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -74,7 +74,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv50_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -99,7 +99,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -127,7 +127,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -155,7 +155,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -183,7 +183,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -211,7 +211,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -239,7 +239,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -267,7 +267,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -295,7 +295,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -323,7 +323,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -350,9 +350,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -380,9 +380,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -409,9 +409,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@@ -438,9 +438,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
index 8d55ed633b19..b4a2917ce555 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@@ -70,14 +70,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc0_graph_oclass;
@@ -102,14 +102,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@@ -134,14 +134,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@@ -165,14 +165,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@@ -197,14 +197,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@@ -229,14 +229,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc1_graph_oclass;
@@ -260,14 +260,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc8_graph_oclass;
@@ -292,14 +292,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvd9_graph_oclass;
@@ -323,12 +323,12 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvd7_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 2d1e97d4264f..cdf9147f32a1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@@ -70,14 +70,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@@ -103,14 +103,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@@ -136,14 +136,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@@ -158,15 +158,17 @@ nve0_identify(struct nouveau_device *device)
break;
case 0xea:
device->cname = "GK20A";
- device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &gk20a_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
- device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &gk20a_bar_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = gk20a_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gk20a_graph_oclass;
@@ -186,14 +188,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
@@ -219,17 +221,17 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
- device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = gk110b_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass;
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
@@ -248,18 +250,18 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
- device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
- device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
- device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
- device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nv108_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/base.c b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
index 9c38c5e40500..22d55f6cde50 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
@@ -22,23 +22,93 @@
* Authors: Ben Skeggs
*/
+#include <core/os.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/event.h>
+
#include "priv.h"
#include "outp.h"
#include "conn.h"
+int
+nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ struct nouveau_disp *disp =
+ container_of(notify->event, typeof(*disp), vblank);
+ union {
+ struct nvif_notify_head_req_v0 v0;
+ } *req = data;
+ int ret;
+
+ if (nvif_unpack(req->v0, 0, 0, false)) {
+ notify->size = sizeof(struct nvif_notify_head_rep_v0);
+ if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
+ notify->types = 1;
+ notify->index = req->v0.head;
+ return 0;
+ }
+ }
+
+ return ret;
+}
+
+void
+nouveau_disp_vblank(struct nouveau_disp *disp, int head)
+{
+ struct nvif_notify_head_rep_v0 rep = {};
+ nvkm_event_send(&disp->vblank, 1, head, &rep, sizeof(rep));
+}
+
static int
-nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index)
+nouveau_disp_hpd_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
- struct nouveau_disp *disp = event->priv;
+ struct nouveau_disp *disp =
+ container_of(notify->event, typeof(*disp), hpd);
+ union {
+ struct nvif_notify_conn_req_v0 v0;
+ } *req = data;
struct nvkm_output *outp;
- list_for_each_entry(outp, &disp->outp, head) {
- if (outp->conn->index == index) {
- if (outp->conn->hpd.event)
- return 0;
- break;
+ int ret;
+
+ if (nvif_unpack(req->v0, 0, 0, false)) {
+ notify->size = sizeof(struct nvif_notify_conn_rep_v0);
+ list_for_each_entry(outp, &disp->outp, head) {
+ if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
+ if (ret = -ENODEV, outp->conn->hpd.event) {
+ notify->types = req->v0.mask;
+ notify->index = req->v0.conn;
+ ret = 0;
+ }
+ break;
+ }
}
}
- return -ENOSYS;
+
+ return ret;
+}
+
+static const struct nvkm_event_func
+nouveau_disp_hpd_func = {
+ .ctor = nouveau_disp_hpd_ctor
+};
+
+int
+nouveau_disp_ntfy(struct nouveau_object *object, u32 type,
+ struct nvkm_event **event)
+{
+ struct nouveau_disp *disp = (void *)object->engine;
+ switch (type) {
+ case NV04_DISP_NTFY_VBLANK:
+ *event = &disp->vblank;
+ return 0;
+ case NV04_DISP_NTFY_CONN:
+ *event = &disp->hpd;
+ return 0;
+ default:
+ break;
+ }
+ return -EINVAL;
}
int
@@ -97,7 +167,8 @@ _nouveau_disp_dtor(struct nouveau_object *object)
struct nouveau_disp *disp = (void *)object;
struct nvkm_output *outp, *outt;
- nouveau_event_destroy(&disp->vblank);
+ nvkm_event_fini(&disp->vblank);
+ nvkm_event_fini(&disp->hpd);
if (disp->outp.next) {
list_for_each_entry_safe(outp, outt, &disp->outp, head) {
@@ -157,14 +228,11 @@ nouveau_disp_create_(struct nouveau_object *parent,
hpd = max(hpd, (u8)(dcbE.connector + 1));
}
- ret = nouveau_event_create(3, hpd, &disp->hpd);
+ ret = nvkm_event_init(&nouveau_disp_hpd_func, 3, hpd, &disp->hpd);
if (ret)
return ret;
- disp->hpd->priv = disp;
- disp->hpd->check = nouveau_disp_hpd_check;
-
- ret = nouveau_event_create(1, heads, &disp->vblank);
+ ret = nvkm_event_init(impl->vblank, 1, heads, &disp->vblank);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.c b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
index 4ffbc70ecf5a..3d1070228977 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
@@ -22,39 +22,41 @@
* Authors: Ben Skeggs
*/
+#include <core/os.h>
+#include <nvif/event.h>
+
#include <subdev/gpio.h>
#include "conn.h"
#include "outp.h"
-static void
-nvkm_connector_hpd_work(struct work_struct *w)
+static int
+nvkm_connector_hpd(struct nvkm_notify *notify)
{
- struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work);
+ struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
struct nouveau_disp *disp = nouveau_disp(conn);
struct nouveau_gpio *gpio = nouveau_gpio(conn);
- u32 send = NVKM_HPD_UNPLUG;
- if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index))
- send = NVKM_HPD_PLUG;
- nouveau_event_trigger(disp->hpd, send, conn->index);
- nouveau_event_get(conn->hpd.event);
-}
+ const struct nvkm_gpio_ntfy_rep *line = notify->data;
+ struct nvif_notify_conn_rep_v0 rep;
+ int index = conn->index;
-static int
-nvkm_connector_hpd(void *data, u32 type, int index)
-{
- struct nvkm_connector *conn = data;
- DBG("HPD: %d\n", type);
- schedule_work(&conn->hpd.work);
- return NVKM_EVENT_DROP;
+ DBG("HPD: %d\n", line->mask);
+
+ if (!gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
+ rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
+ else
+ rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
+ rep.version = 0;
+
+ nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
+ return NVKM_NOTIFY_KEEP;
}
int
_nvkm_connector_fini(struct nouveau_object *object, bool suspend)
{
struct nvkm_connector *conn = (void *)object;
- if (conn->hpd.event)
- nouveau_event_put(conn->hpd.event);
+ nvkm_notify_put(&conn->hpd);
return nouveau_object_fini(&conn->base, suspend);
}
@@ -63,10 +65,8 @@ _nvkm_connector_init(struct nouveau_object *object)
{
struct nvkm_connector *conn = (void *)object;
int ret = nouveau_object_init(&conn->base);
- if (ret == 0) {
- if (conn->hpd.event)
- nouveau_event_get(conn->hpd.event);
- }
+ if (ret == 0)
+ nvkm_notify_get(&conn->hpd);
return ret;
}
@@ -74,7 +74,7 @@ void
_nvkm_connector_dtor(struct nouveau_object *object)
{
struct nvkm_connector *conn = (void *)object;
- nouveau_event_ref(NULL, &conn->hpd.event);
+ nvkm_notify_fini(&conn->hpd);
nouveau_object_destroy(&conn->base);
}
@@ -116,19 +116,24 @@ nvkm_connector_create_(struct nouveau_object *parent,
if ((info->hpd = ffs(info->hpd))) {
if (--info->hpd >= ARRAY_SIZE(hpd)) {
ERR("hpd %02x unknown\n", info->hpd);
- goto done;
+ return 0;
}
info->hpd = hpd[info->hpd];
ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
if (ret) {
ERR("func %02x lookup failed, %d\n", info->hpd, ret);
- goto done;
+ return 0;
}
- ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED,
- func.line, nvkm_connector_hpd,
- conn, &conn->hpd.event);
+ ret = nvkm_notify_init(&gpio->event, nvkm_connector_hpd, true,
+ &(struct nvkm_gpio_ntfy_req) {
+ .mask = NVKM_GPIO_TOGGLED,
+ .line = func.line,
+ },
+ sizeof(struct nvkm_gpio_ntfy_req),
+ sizeof(struct nvkm_gpio_ntfy_rep),
+ &conn->hpd);
if (ret) {
ERR("func %02x failed, %d\n", info->hpd, ret);
} else {
@@ -136,8 +141,6 @@ nvkm_connector_create_(struct nouveau_object *parent,
}
}
-done:
- INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.h b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
index 035ebeacbb1c..55e5f5c82c14 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
@@ -10,10 +10,7 @@ struct nvkm_connector {
struct nvbios_connE info;
int index;
- struct {
- struct nouveau_eventh *event;
- struct work_struct work;
- } hpd;
+ struct nvkm_notify hpd;
};
#define nvkm_connector_create(p,e,c,b,i,d) \
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
index a66b27c0fcab..b36addff06a9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -32,13 +33,28 @@
#include "nv50.h"
int
-nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
+nv50_dac_power(NV50_DISP_MTHD_V1)
{
- const u32 stat = (data & NV50_DISP_DAC_PWR_HSYNC) |
- (data & NV50_DISP_DAC_PWR_VSYNC) |
- (data & NV50_DISP_DAC_PWR_DATA) |
- (data & NV50_DISP_DAC_PWR_STATE);
- const u32 doff = (or * 0x800);
+ const u32 doff = outp->or * 0x800;
+ union {
+ struct nv50_disp_dac_pwr_v0 v0;
+ } *args = data;
+ u32 stat;
+ int ret;
+
+ nv_ioctl(object, "disp dac pwr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp dac pwr vers %d state %d data %d "
+ "vsync %d hsync %d\n",
+ args->v0.version, args->v0.state, args->v0.data,
+ args->v0.vsync, args->v0.hsync);
+ stat = 0x00000040 * !args->v0.state;
+ stat |= 0x00000010 * !args->v0.data;
+ stat |= 0x00000004 * !args->v0.vsync;
+ stat |= 0x00000001 * !args->v0.hsync;
+ } else
+ return ret;
+
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@@ -46,9 +62,24 @@ nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
}
int
-nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
+nv50_dac_sense(NV50_DISP_MTHD_V1)
{
- const u32 doff = (or * 0x800);
+ union {
+ struct nv50_disp_dac_load_v0 v0;
+ } *args = data;
+ const u32 doff = outp->or * 0x800;
+ u32 loadval;
+ int ret;
+
+ nv_ioctl(object, "disp dac load size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp dac load vers %d data %08x\n",
+ args->v0.version, args->v0.data);
+ if (args->v0.data & 0xfff00000)
+ return -EINVAL;
+ loadval = args->v0.data;
+ } else
+ return ret;
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@@ -61,38 +92,10 @@ nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
- nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval);
+ nv_debug(priv, "DAC%d sense: 0x%08x\n", outp->or, loadval);
if (!(loadval & 0x80000000))
return -ETIMEDOUT;
- return (loadval & 0x38000000) >> 27;
-}
-
-int
-nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
-{
- struct nv50_disp_priv *priv = (void *)object->engine;
- const u8 or = (mthd & NV50_DISP_DAC_MTHD_OR);
- u32 *data = args;
- int ret;
-
- if (size < sizeof(u32))
- return -EINVAL;
-
- switch (mthd & ~0x3f) {
- case NV50_DISP_DAC_PWR:
- ret = priv->dac.power(priv, or, data[0]);
- break;
- case NV50_DISP_DAC_LOAD:
- ret = priv->dac.sense(priv, or, data[0]);
- if (ret >= 0) {
- data[0] = ret;
- ret = 0;
- }
- break;
- default:
- BUG_ON(1);
- }
-
- return ret;
+ args->v0.load = (loadval & 0x38000000) >> 27;
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
index 5a5b59b21130..39890221b91c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -30,7 +30,7 @@
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "dport.h"
#include "outpdp.h"
@@ -335,7 +335,7 @@ nouveau_dp_train(struct work_struct *w)
int ret;
/* bring capabilities within encoder limits */
- if (nv_mclass(disp) < NVD0_DISP_CLASS)
+ if (nv_mclass(disp) < GF110_DISP)
outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
@@ -354,7 +354,7 @@ nouveau_dp_train(struct work_struct *w)
cfg--;
/* disable link interrupt handling during link training */
- nouveau_event_put(outp->irq);
+ nvkm_notify_put(&outp->irq);
/* enable down-spreading and execute pre-train script from vbios */
dp_link_train_init(dp, outp->dpcd[3] & 0x01);
@@ -395,5 +395,5 @@ nouveau_dp_train(struct work_struct *w)
DBG("training complete\n");
atomic_set(&outp->lt.done, 1);
wake_up(&outp->lt.wait);
- nouveau_event_get(outp->irq);
+ nvkm_notify_get(&outp->irq);
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
index 9fc7447fec90..d54da8b5f87e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -35,17 +35,17 @@
static struct nouveau_oclass
gm107_disp_sclass[] = {
- { GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
- { GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
- { GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
- { GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
- { GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ { GM107_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+ { GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+ { GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+ { GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+ { GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
gm107_disp_base_oclass[] = {
- { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { GM107_DISP, &nvd0_disp_base_ofuncs },
{}
};
@@ -93,9 +93,11 @@ gm107_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
index a19e7d79b847..8b4e06abe533 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
@@ -22,25 +22,37 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include "nv50.h"
int
-nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+nva3_hda_eld(NV50_DISP_MTHD_V1)
{
- const u32 soff = (or * 0x800);
- int i;
+ union {
+ struct nv50_disp_sor_hda_eld_v0 v0;
+ } *args = data;
+ const u32 soff = outp->or * 0x800;
+ int ret, i;
- if (data && data[0]) {
+ nv_ioctl(object, "disp sor hda eld size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
+ if (size > 0x60)
+ return -E2BIG;
+ } else
+ return ret;
+
+ if (size && args->v0.data[0]) {
for (i = 0; i < size; i++)
- nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
+ nv_wr32(priv, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8));
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
} else
- if (data) {
+ if (size) {
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000001);
} else {
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
index 717639386ced..baf558fc12fb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -33,19 +34,30 @@
#include "nv50.h"
int
-nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
+nvd0_hda_eld(NV50_DISP_MTHD_V1)
{
- const u32 soff = (or * 0x030);
- int i;
+ union {
+ struct nv50_disp_sor_hda_eld_v0 v0;
+ } *args = data;
+ const u32 soff = outp->or * 0x030;
+ int ret, i;
- if (data && data[0]) {
+ nv_ioctl(object, "disp sor hda eld size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
+ if (size > 0x60)
+ return -E2BIG;
+ } else
+ return ret;
+
+ if (size && args->v0.data[0]) {
for (i = 0; i < size; i++)
- nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
+ nv_wr32(priv, 0x10ec00 + soff, (i << 8) | args->v0.data[i]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8));
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
} else
- if (data) {
+ if (size) {
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000001);
} else {
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
index 7fdade6e604d..fa276dede9cd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
@@ -22,17 +22,38 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include "nv50.h"
int
-nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nv84_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
const u32 hoff = (head * 0x800);
+ union {
+ struct nv50_disp_sor_hdmi_pwr_v0 v0;
+ } *args = data;
+ u32 ctrl;
+ int ret;
- if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+ nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+ "max_ac_packet %d rekey %d\n",
+ args->v0.version, args->v0.state,
+ args->v0.max_ac_packet, args->v0.rekey);
+ if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+ return -EINVAL;
+ ctrl = 0x40000000 * !!args->v0.state;
+ ctrl |= args->v0.max_ac_packet << 16;
+ ctrl |= args->v0.rekey;
+ ctrl |= 0x1f000000; /* ??? */
+ } else
+ return ret;
+
+ if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000);
nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000);
nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* HDMI_CTRL */
- nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
+ nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
index db8c6fd46278..57eeed1d1942 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
@@ -22,17 +22,38 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include "nv50.h"
int
-nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nva3_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
- const u32 soff = (or * 0x800);
+ const u32 soff = outp->or * 0x800;
+ union {
+ struct nv50_disp_sor_hdmi_pwr_v0 v0;
+ } *args = data;
+ u32 ctrl;
+ int ret;
- if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+ nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+ "max_ac_packet %d rekey %d\n",
+ args->v0.version, args->v0.state,
+ args->v0.max_ac_packet, args->v0.rekey);
+ if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+ return -EINVAL;
+ ctrl = 0x40000000 * !!args->v0.state;
+ ctrl |= args->v0.max_ac_packet << 16;
+ ctrl |= args->v0.rekey;
+ ctrl |= 0x1f000000; /* ??? */
+ } else
+ return ret;
+
+ if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000);
nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000);
nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000);
@@ -65,6 +86,6 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* HDMI_CTRL */
- nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
+ nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
index 5151bb261832..3106d295b48d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminvd0.c
@@ -22,17 +22,37 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include "nv50.h"
int
-nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
+nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
const u32 hoff = (head * 0x800);
+ union {
+ struct nv50_disp_sor_hdmi_pwr_v0 v0;
+ } *args = data;
+ u32 ctrl;
+ int ret;
- if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
+ nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
+ "max_ac_packet %d rekey %d\n",
+ args->v0.version, args->v0.state,
+ args->v0.max_ac_packet, args->v0.rekey);
+ if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
+ return -EINVAL;
+ ctrl = 0x40000000 * !!args->v0.state;
+ ctrl |= args->v0.max_ac_packet << 16;
+ ctrl |= args->v0.rekey;
+ } else
+ return ret;
+
+ if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000);
nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000);
nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000);
@@ -54,7 +74,7 @@ nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001);
/* HDMI_CTRL */
- nv_mask(priv, 0x616798 + hoff, 0x401f007f, data);
+ nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl);
/* NFI, audio doesn't work without it though.. */
nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index a32666ed0c47..366f315fc9a5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -24,60 +24,100 @@
#include "priv.h"
+#include <core/client.h>
#include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
struct nv04_disp_priv {
struct nouveau_disp base;
};
static int
-nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nv04_disp_scanoutpos(struct nouveau_object *object, struct nv04_disp_priv *priv,
+ void *data, u32 size, int head)
{
- struct nv04_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV04_DISP_MTHD_HEAD);
+ const u32 hoff = head * 0x2000;
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
u32 line;
+ int ret;
+
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff;
+ args->v0.vtotal = nv_rd32(priv, 0x680804 + hoff) & 0xffff;
+ args->v0.vblanke = args->v0.vtotal - 1;
+
+ args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff;
+ args->v0.htotal = nv_rd32(priv, 0x680824 + hoff) & 0xffff;
+ args->v0.hblanke = args->v0.htotal - 1;
+
+ /*
+ * If output is vga instead of digital then vtotal/htotal is
+ * invalid so we have to give up and trigger the timestamping
+ * fallback in the drm core.
+ */
+ if (!args->v0.vtotal || !args->v0.htotal)
+ return -ENOTSUPP;
+
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ line = nv_rd32(priv, 0x600868 + hoff);
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline = (line & 0xffff0000) >> 16;
+ args->v0.vline = (line & 0x0000ffff);
+ } else
+ return ret;
- if (size < sizeof(*args))
- return -EINVAL;
-
- args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
- args->vtotal = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
- args->vblanke = args->vtotal - 1;
-
- args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
- args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
- args->hblanke = args->htotal - 1;
-
- /*
- * If output is vga instead of digital then vtotal/htotal is invalid
- * so we have to give up and trigger the timestamping fallback in the
- * drm core.
- */
- if (!args->vtotal || !args->htotal)
- return -ENOTSUPP;
-
- args->time[0] = ktime_to_ns(ktime_get());
- line = nv_rd32(priv, 0x600868 + (head * 0x2000));
- args->time[1] = ktime_to_ns(ktime_get());
- args->hline = (line & 0xffff0000) >> 16;
- args->vline = (line & 0x0000ffff);
return 0;
}
-#define HEAD_MTHD(n) (n), (n) + 0x01
+static int
+nv04_disp_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+ union {
+ struct nv04_disp_mthd_v0 v0;
+ } *args = data;
+ struct nv04_disp_priv *priv = (void *)object->engine;
+ int head, ret;
+
+ nv_ioctl(object, "disp mthd size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+ args->v0.version, args->v0.method, args->v0.head);
+ mthd = args->v0.method;
+ head = args->v0.head;
+ } else
+ return ret;
-static struct nouveau_omthds
-nv04_disp_omthds[] = {
- { HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
- {}
+ if (head < 0 || head >= 2)
+ return -ENXIO;
+
+ switch (mthd) {
+ case NV04_DISP_SCANOUTPOS:
+ return nv04_disp_scanoutpos(object, priv, data, size, head);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static struct nouveau_ofuncs
+nv04_disp_ofuncs = {
+ .ctor = _nouveau_object_ctor,
+ .dtor = nouveau_object_destroy,
+ .init = nouveau_object_init,
+ .fini = nouveau_object_fini,
+ .mthd = nv04_disp_mthd,
+ .ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nv04_disp_sclass[] = {
- { NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
+ { NV04_DISP, &nv04_disp_ofuncs },
{},
};
@@ -86,17 +126,26 @@ nv04_disp_sclass[] = {
******************************************************************************/
static void
-nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)
+nv04_disp_vblank_init(struct nvkm_event *event, int type, int head)
{
- nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000001);
}
static void
-nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)
+nv04_disp_vblank_fini(struct nvkm_event *event, int type, int head)
{
- nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000000);
}
+static const struct nvkm_event_func
+nv04_disp_vblank_func = {
+ .ctor = nouveau_disp_vblank_ctor,
+ .init = nv04_disp_vblank_init,
+ .fini = nv04_disp_vblank_fini,
+};
+
static void
nv04_disp_intr(struct nouveau_subdev *subdev)
{
@@ -106,12 +155,12 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
u32 pvideo;
if (crtc0 & 0x00000001) {
- nouveau_event_trigger(priv->base.vblank, 1, 0);
+ nouveau_disp_vblank(&priv->base, 0);
nv_wr32(priv, 0x600100, 0x00000001);
}
if (crtc1 & 0x00000001) {
- nouveau_event_trigger(priv->base.vblank, 1, 1);
+ nouveau_disp_vblank(&priv->base, 1);
nv_wr32(priv, 0x602100, 0x00000001);
}
@@ -140,9 +189,6 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv04_disp_sclass;
nv_subdev(priv)->intr = nv04_disp_intr;
- priv->base.vblank->priv = priv;
- priv->base.vblank->enable = nv04_disp_vblank_enable;
- priv->base.vblank->disable = nv04_disp_vblank_disable;
return 0;
}
@@ -155,4 +201,5 @@ nv04_disp_oclass = &(struct nouveau_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .vblank = &nv04_disp_vblank_func,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 2283c442a10d..4b5bb5d58a54 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -23,10 +23,12 @@
*/
#include <core/object.h>
+#include <core/client.h>
#include <core/parent.h>
#include <core/handle.h>
-#include <core/class.h>
#include <core/enum.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -43,14 +45,16 @@
* EVO channel base class
******************************************************************************/
-int
+static int
nv50_disp_chan_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
- struct nouveau_oclass *oclass, int chid,
+ struct nouveau_oclass *oclass, int head,
int length, void **pobject)
{
+ const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
struct nv50_disp_base *base = (void *)parent;
struct nv50_disp_chan *chan;
+ int chid = impl->chid + head;
int ret;
if (base->chan & (1 << chid))
@@ -63,12 +67,14 @@ nv50_disp_chan_create_(struct nouveau_object *parent,
chan = *pobject;
if (ret)
return ret;
-
chan->chid = chid;
+
+ nv_parent(chan)->object_attach = impl->attach;
+ nv_parent(chan)->object_detach = impl->detach;
return 0;
}
-void
+static void
nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
{
struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
@@ -76,6 +82,16 @@ nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
nouveau_namedb_destroy(&chan->base);
}
+int
+nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+ struct nv50_disp_chan *chan = (void *)object;
+ *addr = nv_device_resource_start(nv_device(object), 0) +
+ 0x640000 + (chan->chid * 0x1000);
+ *size = 0x001000;
+ return 0;
+}
+
u32
nv50_disp_chan_rd32(struct nouveau_object *object, u64 addr)
{
@@ -115,16 +131,16 @@ nv50_disp_dmac_object_detach(struct nouveau_object *parent, int cookie)
nouveau_ramht_remove(base->ramht, cookie);
}
-int
+static int
nv50_disp_dmac_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
- struct nouveau_oclass *oclass, u32 pushbuf, int chid,
+ struct nouveau_oclass *oclass, u32 pushbuf, int head,
int length, void **pobject)
{
struct nv50_disp_dmac *dmac;
int ret;
- ret = nv50_disp_chan_create_(parent, engine, oclass, chid,
+ ret = nv50_disp_chan_create_(parent, engine, oclass, head,
length, pobject);
dmac = *pobject;
if (ret)
@@ -397,27 +413,32 @@ nv50_disp_mast_mthd_chan = {
}
};
-static int
+int
nv50_disp_mast_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_display_mast_class *args = data;
+ union {
+ struct nv50_disp_core_channel_dma_v0 v0;
+ } *args = data;
struct nv50_disp_dmac *mast;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create disp core channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create disp core channel dma vers %d "
+ "pushbuf %08x\n",
+ args->v0.version, args->v0.pushbuf);
+ } else
+ return ret;
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
+ ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
0, sizeof(*mast), (void **)&mast);
*pobject = nv_object(mast);
if (ret)
return ret;
- nv_parent(mast)->object_attach = nv50_disp_dmac_object_attach;
- nv_parent(mast)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
@@ -479,14 +500,18 @@ nv50_disp_mast_fini(struct nouveau_object *object, bool suspend)
return nv50_disp_chan_fini(&mast->base, suspend);
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nv50_disp_mast_ofuncs = {
- .ctor = nv50_disp_mast_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nv50_disp_mast_init,
- .fini = nv50_disp_mast_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_mast_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nv50_disp_mast_init,
+ .base.fini = nv50_disp_mast_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 0,
+ .attach = nv50_disp_dmac_object_attach,
+ .detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -543,39 +568,51 @@ nv50_disp_sync_mthd_chan = {
}
};
-static int
+int
nv50_disp_sync_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_display_sync_class *args = data;
+ union {
+ struct nv50_disp_base_channel_dma_v0 v0;
+ } *args = data;
+ struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*args) || args->head > 1)
- return -EINVAL;
+ nv_ioctl(parent, "create disp base channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create disp base channel dma vers %d "
+ "pushbuf %08x head %d\n",
+ args->v0.version, args->v0.pushbuf, args->v0.head);
+ if (args->v0.head > priv->head.nr)
+ return -EINVAL;
+ } else
+ return ret;
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
- 1 + args->head, sizeof(*dmac),
+ ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
+ args->v0.head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
- nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
- nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nv50_disp_sync_ofuncs = {
- .ctor = nv50_disp_sync_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nv50_disp_dmac_init,
- .fini = nv50_disp_dmac_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_sync_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nv50_disp_dmac_init,
+ .base.fini = nv50_disp_dmac_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 1,
+ .attach = nv50_disp_dmac_object_attach,
+ .detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -620,39 +657,51 @@ nv50_disp_ovly_mthd_chan = {
}
};
-static int
+int
nv50_disp_ovly_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_display_ovly_class *args = data;
+ union {
+ struct nv50_disp_overlay_channel_dma_v0 v0;
+ } *args = data;
+ struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*args) || args->head > 1)
- return -EINVAL;
+ nv_ioctl(parent, "create disp overlay channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create disp overlay channel dma vers %d "
+ "pushbuf %08x head %d\n",
+ args->v0.version, args->v0.pushbuf, args->v0.head);
+ if (args->v0.head > priv->head.nr)
+ return -EINVAL;
+ } else
+ return ret;
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
- 3 + args->head, sizeof(*dmac),
+ ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
+ args->v0.head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
- nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
- nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nv50_disp_ovly_ofuncs = {
- .ctor = nv50_disp_ovly_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nv50_disp_dmac_init,
- .fini = nv50_disp_dmac_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_ovly_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nv50_disp_dmac_init,
+ .base.fini = nv50_disp_dmac_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 3,
+ .attach = nv50_disp_dmac_object_attach,
+ .detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -662,14 +711,14 @@ nv50_disp_ovly_ofuncs = {
static int
nv50_disp_pioc_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
- struct nouveau_oclass *oclass, int chid,
+ struct nouveau_oclass *oclass, int head,
int length, void **pobject)
{
- return nv50_disp_chan_create_(parent, engine, oclass, chid,
+ return nv50_disp_chan_create_(parent, engine, oclass, head,
length, pobject);
}
-static void
+void
nv50_disp_pioc_dtor(struct nouveau_object *object)
{
struct nv50_disp_pioc *pioc = (void *)object;
@@ -727,20 +776,29 @@ nv50_disp_pioc_fini(struct nouveau_object *object, bool suspend)
* EVO immediate overlay channel objects
******************************************************************************/
-static int
+int
nv50_disp_oimm_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_display_oimm_class *args = data;
+ union {
+ struct nv50_disp_overlay_v0 v0;
+ } *args = data;
+ struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
- if (size < sizeof(*args) || args->head > 1)
- return -EINVAL;
+ nv_ioctl(parent, "create disp overlay size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create disp overlay vers %d head %d\n",
+ args->v0.version, args->v0.head);
+ if (args->v0.head > priv->head.nr)
+ return -EINVAL;
+ } else
+ return ret;
- ret = nv50_disp_pioc_create_(parent, engine, oclass, 5 + args->head,
+ ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
@@ -749,34 +807,45 @@ nv50_disp_oimm_ctor(struct nouveau_object *parent,
return 0;
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nv50_disp_oimm_ofuncs = {
- .ctor = nv50_disp_oimm_ctor,
- .dtor = nv50_disp_pioc_dtor,
- .init = nv50_disp_pioc_init,
- .fini = nv50_disp_pioc_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_oimm_ctor,
+ .base.dtor = nv50_disp_pioc_dtor,
+ .base.init = nv50_disp_pioc_init,
+ .base.fini = nv50_disp_pioc_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 5,
};
/*******************************************************************************
* EVO cursor channel objects
******************************************************************************/
-static int
+int
nv50_disp_curs_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_display_curs_class *args = data;
+ union {
+ struct nv50_disp_cursor_v0 v0;
+ } *args = data;
+ struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
- if (size < sizeof(*args) || args->head > 1)
- return -EINVAL;
+ nv_ioctl(parent, "create disp cursor size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create disp cursor vers %d head %d\n",
+ args->v0.version, args->v0.head);
+ if (args->v0.head > priv->head.nr)
+ return -EINVAL;
+ } else
+ return ret;
- ret = nv50_disp_pioc_create_(parent, engine, oclass, 7 + args->head,
+ ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
@@ -785,14 +854,16 @@ nv50_disp_curs_ctor(struct nouveau_object *parent,
return 0;
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nv50_disp_curs_ofuncs = {
- .ctor = nv50_disp_curs_ctor,
- .dtor = nv50_disp_pioc_dtor,
- .init = nv50_disp_pioc_init,
- .fini = nv50_disp_pioc_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_curs_ctor,
+ .base.dtor = nv50_disp_pioc_dtor,
+ .base.init = nv50_disp_pioc_init,
+ .base.fini = nv50_disp_pioc_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 7,
};
/*******************************************************************************
@@ -800,47 +871,162 @@ nv50_disp_curs_ofuncs = {
******************************************************************************/
int
-nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
- struct nv50_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV50_DISP_MTHD_HEAD);
- u32 blanke, blanks, total;
+ const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+ const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+ const u32 total = nv_rd32(priv, 0x610afc + (head * 0x540));
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
+ int ret;
+
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+ args->v0.hblanke = (blanke & 0x0000ffff);
+ args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+ args->v0.hblanks = (blanks & 0x0000ffff);
+ args->v0.vtotal = ( total & 0xffff0000) >> 16;
+ args->v0.htotal = ( total & 0x0000ffff);
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ args->v0.vline = /* vline read locks hline */
+ nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline =
+ nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ } else
+ return ret;
- if (size < sizeof(*args) || head >= priv->head.nr)
- return -EINVAL;
- blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
- blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
- total = nv_rd32(priv, 0x610afc + (head * 0x540));
-
- args->vblanke = (blanke & 0xffff0000) >> 16;
- args->hblanke = (blanke & 0x0000ffff);
- args->vblanks = (blanks & 0xffff0000) >> 16;
- args->hblanks = (blanks & 0x0000ffff);
- args->vtotal = ( total & 0xffff0000) >> 16;
- args->htotal = ( total & 0x0000ffff);
-
- args->time[0] = ktime_to_ns(ktime_get());
- args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
- args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
- args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
return 0;
}
-static void
-nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
+int
+nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
{
- nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
-}
+ const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
+ union {
+ struct nv50_disp_mthd_v0 v0;
+ struct nv50_disp_mthd_v1 v1;
+ } *args = data;
+ struct nv50_disp_priv *priv = (void *)object->engine;
+ struct nvkm_output *outp = NULL;
+ struct nvkm_output *temp;
+ u16 type, mask = 0;
+ int head, ret;
-static void
-nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
-{
- nv_mask(event->priv, 0x61002c, (4 << head), 0);
+ if (mthd != NV50_DISP_MTHD)
+ return -EINVAL;
+
+ nv_ioctl(object, "disp mthd size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
+ args->v0.version, args->v0.method, args->v0.head);
+ mthd = args->v0.method;
+ head = args->v0.head;
+ } else
+ if (nvif_unpack(args->v1, 1, 1, true)) {
+ nv_ioctl(object, "disp mthd vers %d mthd %02x "
+ "type %04x mask %04x\n",
+ args->v1.version, args->v1.method,
+ args->v1.hasht, args->v1.hashm);
+ mthd = args->v1.method;
+ type = args->v1.hasht;
+ mask = args->v1.hashm;
+ head = ffs((mask >> 8) & 0x0f) - 1;
+ } else
+ return ret;
+
+ if (head < 0 || head >= priv->head.nr)
+ return -ENXIO;
+
+ if (mask) {
+ list_for_each_entry(temp, &priv->base.outp, head) {
+ if ((temp->info.hasht == type) &&
+ (temp->info.hashm & mask) == mask) {
+ outp = temp;
+ break;
+ }
+ }
+ if (outp == NULL)
+ return -ENXIO;
+ }
+
+ switch (mthd) {
+ case NV50_DISP_SCANOUTPOS:
+ return impl->head.scanoutpos(object, priv, data, size, head);
+ default:
+ break;
+ }
+
+ switch (mthd * !!outp) {
+ case NV50_DISP_MTHD_V1_DAC_PWR:
+ return priv->dac.power(object, priv, data, size, head, outp);
+ case NV50_DISP_MTHD_V1_DAC_LOAD:
+ return priv->dac.sense(object, priv, data, size, head, outp);
+ case NV50_DISP_MTHD_V1_SOR_PWR:
+ return priv->sor.power(object, priv, data, size, head, outp);
+ case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
+ if (!priv->sor.hda_eld)
+ return -ENODEV;
+ return priv->sor.hda_eld(object, priv, data, size, head, outp);
+ case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
+ if (!priv->sor.hdmi)
+ return -ENODEV;
+ return priv->sor.hdmi(object, priv, data, size, head, outp);
+ case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
+ union {
+ struct nv50_disp_sor_lvds_script_v0 v0;
+ } *args = data;
+ nv_ioctl(object, "disp sor lvds script size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor lvds script "
+ "vers %d name %04x\n",
+ args->v0.version, args->v0.script);
+ priv->sor.lvdsconf = args->v0.script;
+ return 0;
+ } else
+ return ret;
+ }
+ break;
+ case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
+ struct nvkm_output_dp *outpdp = (void *)outp;
+ union {
+ struct nv50_disp_sor_dp_pwr_v0 v0;
+ } *args = data;
+ nv_ioctl(object, "disp sor dp pwr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor dp pwr vers %d state %d\n",
+ args->v0.version, args->v0.state);
+ if (args->v0.state == 0) {
+ nvkm_notify_put(&outpdp->irq);
+ ((struct nvkm_output_dp_impl *)nv_oclass(outp))
+ ->lnk_pwr(outpdp, 0);
+ atomic_set(&outpdp->lt.done, 0);
+ return 0;
+ } else
+ if (args->v0.state != 0) {
+ nvkm_output_dp_train(&outpdp->base, 0, true);
+ return 0;
+ }
+ } else
+ return ret;
+ }
+ break;
+ case NV50_DISP_MTHD_V1_PIOR_PWR:
+ if (!priv->pior.power)
+ return -ENODEV;
+ return priv->pior.power(object, priv, data, size, head, outp);
+ default:
+ break;
+ }
+
+ return -EINVAL;
}
-static int
+int
nv50_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -856,14 +1042,11 @@ nv50_disp_base_ctor(struct nouveau_object *parent,
if (ret)
return ret;
- priv->base.vblank->priv = priv;
- priv->base.vblank->enable = nv50_disp_base_vblank_enable;
- priv->base.vblank->disable = nv50_disp_base_vblank_disable;
return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
&base->ramht);
}
-static void
+void
nv50_disp_base_dtor(struct nouveau_object *object)
{
struct nv50_disp_base *base = (void *)object;
@@ -958,34 +1141,23 @@ nv50_disp_base_ofuncs = {
.dtor = nv50_disp_base_dtor,
.init = nv50_disp_base_init,
.fini = nv50_disp_base_fini,
-};
-
-static struct nouveau_omthds
-nv50_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
- { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
- {},
+ .mthd = nv50_disp_base_mthd,
+ .ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nv50_disp_base_oclass[] = {
- { NV50_DISP_CLASS, &nv50_disp_base_ofuncs, nv50_disp_base_omthds },
+ { NV50_DISP, &nv50_disp_base_ofuncs },
{}
};
static struct nouveau_oclass
nv50_disp_sclass[] = {
- { NV50_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
- { NV50_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
- { NV50_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
- { NV50_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
- { NV50_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+ { NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+ { NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+ { NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+ { NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+ { NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
@@ -1005,7 +1177,7 @@ nv50_disp_data_ctor(struct nouveau_object *parent,
int ret = -EBUSY;
/* no context needed for channel objects... */
- if (nv_mclass(parent) != NV_DEVICE_CLASS) {
+ if (nv_mclass(parent) != NV_DEVICE) {
atomic_inc(&parent->refcount);
*pobject = parent;
return 1;
@@ -1040,6 +1212,27 @@ nv50_disp_cclass = {
* Display engine implementation
******************************************************************************/
+static void
+nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
+{
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_mask(disp, 0x61002c, (4 << head), 0);
+}
+
+static void
+nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
+{
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_mask(disp, 0x61002c, (4 << head), (4 << head));
+}
+
+const struct nvkm_event_func
+nv50_disp_vblank_func = {
+ .ctor = nouveau_disp_vblank_ctor,
+ .init = nv50_disp_vblank_init,
+ .fini = nv50_disp_vblank_fini,
+};
+
static const struct nouveau_enum
nv50_disp_intr_error_type[] = {
{ 3, "ILLEGAL_MTHD" },
@@ -1381,7 +1574,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
int TU, VTUi, VTUf, VTUa;
u64 link_data_rate, link_ratio, unk;
u32 best_diff = 64 * symbol;
- u32 link_nr, link_bw, bits, r;
+ u32 link_nr, link_bw, bits;
/* calculate packed data rate for each lane */
if (dpctrl > 0x00030000) link_nr = 4;
@@ -1401,7 +1594,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
/* calculate ratio of packed data rate to link symbol rate */
link_ratio = link_data_rate * symbol;
- r = do_div(link_ratio, link_bw);
+ do_div(link_ratio, link_bw);
for (TU = 64; TU >= 32; TU--) {
/* calculate average number of valid symbols in each TU */
@@ -1462,8 +1655,8 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
/* XXX close to vbios numbers, but not right */
unk = (symbol - link_ratio) * bestTU;
unk *= link_ratio;
- r = do_div(unk, symbol);
- r = do_div(unk, symbol);
+ do_div(unk, symbol);
+ do_div(unk, symbol);
unk += 6;
nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2);
@@ -1654,13 +1847,13 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
}
if (intr1 & 0x00000004) {
- nouveau_event_trigger(priv->base.vblank, 1, 0);
+ nouveau_disp_vblank(&priv->base, 0);
nv_wr32(priv, 0x610024, 0x00000004);
intr1 &= ~0x00000004;
}
if (intr1 & 0x00000008) {
- nouveau_event_trigger(priv->base.vblank, 1, 1);
+ nouveau_disp_vblank(&priv->base, 1);
nv_wr32(priv, 0x610024, 0x00000008);
intr1 &= ~0x00000008;
}
@@ -1718,9 +1911,11 @@ nv50_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv50_disp_mast_mthd_chan,
.mthd.base = &nv50_disp_sync_mthd_chan,
.mthd.ovly = &nv50_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index 1a886472b6f5..8ab14461f70c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -14,15 +14,10 @@
#include "outp.h"
#include "outpdp.h"
-struct nv50_disp_impl {
- struct nouveau_disp_impl base;
- struct {
- const struct nv50_disp_mthd_chan *core;
- const struct nv50_disp_mthd_chan *base;
- const struct nv50_disp_mthd_chan *ovly;
- int prev;
- } mthd;
-};
+#define NV50_DISP_MTHD_ struct nouveau_object *object, \
+ struct nv50_disp_priv *priv, void *data, u32 size
+#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
+#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp
struct nv50_disp_priv {
struct nouveau_disp base;
@@ -36,44 +31,52 @@ struct nv50_disp_priv {
} head;
struct {
int nr;
- int (*power)(struct nv50_disp_priv *, int dac, u32 data);
- int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
+ int (*power)(NV50_DISP_MTHD_V1);
+ int (*sense)(NV50_DISP_MTHD_V1);
} dac;
struct {
int nr;
- int (*power)(struct nv50_disp_priv *, int sor, u32 data);
- int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
- int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
+ int (*power)(NV50_DISP_MTHD_V1);
+ int (*hda_eld)(NV50_DISP_MTHD_V1);
+ int (*hdmi)(NV50_DISP_MTHD_V1);
u32 lvdsconf;
} sor;
struct {
int nr;
- int (*power)(struct nv50_disp_priv *, int ext, u32 data);
+ int (*power)(NV50_DISP_MTHD_V1);
u8 type[3];
} pior;
};
-#define HEAD_MTHD(n) (n), (n) + 0x03
-
-int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+struct nv50_disp_impl {
+ struct nouveau_disp_impl base;
+ struct {
+ const struct nv50_disp_mthd_chan *core;
+ const struct nv50_disp_mthd_chan *base;
+ const struct nv50_disp_mthd_chan *ovly;
+ int prev;
+ } mthd;
+ struct {
+ int (*scanoutpos)(NV50_DISP_MTHD_V0);
+ } head;
+};
-#define DAC_MTHD(n) (n), (n) + 0x03
+int nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
+int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_dac_power(struct nv50_disp_priv *, int, u32);
-int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
+int nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
-#define SOR_MTHD(n) (n), (n) + 0x3f
+int nv50_dac_power(NV50_DISP_MTHD_V1);
+int nv50_dac_sense(NV50_DISP_MTHD_V1);
-int nva3_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
-int nvd0_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
+int nva3_hda_eld(NV50_DISP_MTHD_V1);
+int nvd0_hda_eld(NV50_DISP_MTHD_V1);
-int nv84_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
-int nva3_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
-int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
+int nv84_hdmi_ctrl(NV50_DISP_MTHD_V1);
+int nva3_hdmi_ctrl(NV50_DISP_MTHD_V1);
+int nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1);
-int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_sor_power(struct nv50_disp_priv *, int, u32);
+int nv50_sor_power(NV50_DISP_MTHD_V1);
int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16,
u32, struct dcb_output *);
@@ -93,10 +96,7 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
struct dcb_output *);
-#define PIOR_MTHD(n) (n), (n) + 0x03
-
-int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32);
-int nv50_pior_power(struct nv50_disp_priv *, int, u32);
+int nv50_pior_power(NV50_DISP_MTHD_V1);
struct nv50_disp_base {
struct nouveau_parent base;
@@ -104,14 +104,19 @@ struct nv50_disp_base {
u32 chan;
};
+struct nv50_disp_chan_impl {
+ struct nouveau_ofuncs base;
+ int chid;
+ int (*attach)(struct nouveau_object *, struct nouveau_object *, u32);
+ void (*detach)(struct nouveau_object *, int);
+};
+
struct nv50_disp_chan {
struct nouveau_namedb base;
int chid;
};
-int nv50_disp_chan_create_(struct nouveau_object *, struct nouveau_object *,
- struct nouveau_oclass *, int, int, void **);
-void nv50_disp_chan_destroy(struct nv50_disp_chan *);
+int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *);
u32 nv50_disp_chan_rd32(struct nouveau_object *, u64);
void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
@@ -120,20 +125,20 @@ void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
#define nv50_disp_chan_fini(a,b) \
nouveau_namedb_fini(&(a)->base, (b))
-int nv50_disp_dmac_create_(struct nouveau_object *, struct nouveau_object *,
- struct nouveau_oclass *, u32, int, int, void **);
-void nv50_disp_dmac_dtor(struct nouveau_object *);
-
struct nv50_disp_dmac {
struct nv50_disp_chan base;
struct nouveau_dmaobj *pushdma;
u32 push;
};
+void nv50_disp_dmac_dtor(struct nouveau_object *);
+
struct nv50_disp_pioc {
struct nv50_disp_chan base;
};
+void nv50_disp_pioc_dtor(struct nouveau_object *);
+
struct nv50_disp_mthd_list {
u32 mthd;
u32 addr;
@@ -154,47 +159,67 @@ struct nv50_disp_mthd_chan {
} data[];
};
-extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_mast_ofuncs;
+int nv50_disp_mast_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
-extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_sync_ofuncs;
+int nv50_disp_sync_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
-extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs;
+int nv50_disp_ovly_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
-extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
-extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
+extern struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs;
+int nv50_disp_oimm_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+extern struct nv50_disp_chan_impl nv50_disp_curs_ofuncs;
+int nv50_disp_curs_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
+int nv50_disp_base_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void nv50_disp_base_dtor(struct nouveau_object *);
+extern struct nouveau_omthds nv50_disp_base_omthds[];
extern struct nouveau_oclass nv50_disp_cclass;
void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
const struct nv50_disp_mthd_chan *);
void nv50_disp_intr_supervisor(struct work_struct *);
void nv50_disp_intr(struct nouveau_subdev *);
+extern const struct nvkm_event_func nv50_disp_vblank_func;
extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
-extern struct nouveau_omthds nv84_disp_base_omthds[];
extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
-extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_mast_ofuncs;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
-extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
-extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_sync_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_ovly_ofuncs;
extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
-extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
-extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
-extern struct nouveau_omthds nvd0_disp_base_omthds[];
+extern struct nv50_disp_chan_impl nvd0_disp_oimm_ofuncs;
+extern struct nv50_disp_chan_impl nvd0_disp_curs_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
extern struct nouveau_oclass nvd0_disp_cclass;
void nvd0_disp_intr_supervisor(struct work_struct *);
void nvd0_disp_intr(struct nouveau_subdev *);
+extern const struct nvkm_event_func nvd0_disp_vblank_func;
extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index 1cc62e434683..788ced1b6182 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -204,31 +204,17 @@ nv84_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nv84_disp_sclass[] = {
- { NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
- { NV84_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
- { NV84_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
- { NV84_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
- { NV84_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+ { G82_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+ { G82_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+ { G82_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+ { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+ { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
-struct nouveau_omthds
-nv84_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
- { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
- {},
-};
-
static struct nouveau_oclass
nv84_disp_base_oclass[] = {
- { NV84_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+ { G82_DISP, &nv50_disp_base_ofuncs },
{}
};
@@ -276,9 +262,11 @@ nv84_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv84_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index 4f718a9f5aef..fa79de906eae 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -63,32 +63,17 @@ nv94_disp_mast_mthd_chan = {
static struct nouveau_oclass
nv94_disp_sclass[] = {
- { NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
- { NV94_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
- { NV94_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
- { NV94_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
- { NV94_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+ { GT206_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+ { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+ { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+ { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+ { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
-static struct nouveau_omthds
-nv94_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
- { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
- { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
- {},
-};
-
static struct nouveau_oclass
nv94_disp_base_oclass[] = {
- { NV94_DISP_CLASS, &nv50_disp_base_ofuncs, nv94_disp_base_omthds },
+ { GT206_DISP, &nv50_disp_base_ofuncs },
{}
};
@@ -143,9 +128,11 @@ nv94_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nv50_disp_vblank_func,
.base.outp = nv94_disp_outp_sclass,
.mthd.core = &nv94_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 6237a9a36f70..7af15f5d48dc 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -80,17 +80,17 @@ nva0_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nva0_disp_sclass[] = {
- { NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
- { NVA0_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
- { NVA0_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
- { NVA0_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
- { NVA0_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+ { GT200_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+ { GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+ { GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+ { G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+ { G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nva0_disp_base_oclass[] = {
- { NVA0_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
+ { GT200_DISP, &nv50_disp_base_ofuncs },
{}
};
@@ -138,9 +138,11 @@ nva0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv84_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nva0_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index 019124d4782b..6bd39448f8da 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -35,33 +35,17 @@
static struct nouveau_oclass
nva3_disp_sclass[] = {
- { NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
- { NVA3_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
- { NVA3_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
- { NVA3_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
- { NVA3_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
+ { GT214_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
+ { GT214_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
+ { GT214_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
+ { GT214_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
+ { GT214_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
-static struct nouveau_omthds
-nva3_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
- { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
- { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
- { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
- { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
- {},
-};
-
static struct nouveau_oclass
nva3_disp_base_oclass[] = {
- { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs, nva3_disp_base_omthds },
+ { GT214_DISP, &nv50_disp_base_ofuncs },
{}
};
@@ -110,9 +94,11 @@ nva3_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nv50_disp_vblank_func,
.base.outp = nv94_disp_outp_sclass,
.mthd.core = &nv94_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
+ .head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index fa30d8196f35..a4bb3c774ee1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -23,9 +23,11 @@
*/
#include <core/object.h>
+#include <core/client.h>
#include <core/parent.h>
#include <core/handle.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <engine/disp.h>
@@ -265,30 +267,6 @@ nvd0_disp_mast_mthd_chan = {
};
static int
-nvd0_disp_mast_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_display_mast_class *args = data;
- struct nv50_disp_dmac *mast;
- int ret;
-
- if (size < sizeof(*args))
- return -EINVAL;
-
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
- 0, sizeof(*mast), (void **)&mast);
- *pobject = nv_object(mast);
- if (ret)
- return ret;
-
- nv_parent(mast)->object_attach = nvd0_disp_dmac_object_attach;
- nv_parent(mast)->object_detach = nvd0_disp_dmac_object_detach;
- return 0;
-}
-
-static int
nvd0_disp_mast_init(struct nouveau_object *object)
{
struct nv50_disp_priv *priv = (void *)object->engine;
@@ -342,14 +320,18 @@ nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend)
return nv50_disp_chan_fini(&mast->base, suspend);
}
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nvd0_disp_mast_ofuncs = {
- .ctor = nvd0_disp_mast_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nvd0_disp_mast_init,
- .fini = nvd0_disp_mast_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_mast_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nvd0_disp_mast_init,
+ .base.fini = nvd0_disp_mast_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 0,
+ .attach = nvd0_disp_dmac_object_attach,
+ .detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -431,40 +413,18 @@ nvd0_disp_sync_mthd_chan = {
}
};
-static int
-nvd0_disp_sync_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_display_sync_class *args = data;
- struct nv50_disp_priv *priv = (void *)engine;
- struct nv50_disp_dmac *dmac;
- int ret;
-
- if (size < sizeof(*args) || args->head >= priv->head.nr)
- return -EINVAL;
-
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
- 1 + args->head, sizeof(*dmac),
- (void **)&dmac);
- *pobject = nv_object(dmac);
- if (ret)
- return ret;
-
- nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
- nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
- return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nvd0_disp_sync_ofuncs = {
- .ctor = nvd0_disp_sync_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nvd0_disp_dmac_init,
- .fini = nvd0_disp_dmac_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_sync_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nvd0_disp_dmac_init,
+ .base.fini = nvd0_disp_dmac_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 1,
+ .attach = nvd0_disp_dmac_object_attach,
+ .detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -533,40 +493,18 @@ nvd0_disp_ovly_mthd_chan = {
}
};
-static int
-nvd0_disp_ovly_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_display_ovly_class *args = data;
- struct nv50_disp_priv *priv = (void *)engine;
- struct nv50_disp_dmac *dmac;
- int ret;
-
- if (size < sizeof(*args) || args->head >= priv->head.nr)
- return -EINVAL;
-
- ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
- 5 + args->head, sizeof(*dmac),
- (void **)&dmac);
- *pobject = nv_object(dmac);
- if (ret)
- return ret;
-
- nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
- nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
- return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nvd0_disp_ovly_ofuncs = {
- .ctor = nvd0_disp_ovly_ctor,
- .dtor = nv50_disp_dmac_dtor,
- .init = nvd0_disp_dmac_init,
- .fini = nvd0_disp_dmac_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_ovly_ctor,
+ .base.dtor = nv50_disp_dmac_dtor,
+ .base.init = nvd0_disp_dmac_init,
+ .base.fini = nvd0_disp_dmac_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 5,
+ .attach = nvd0_disp_dmac_object_attach,
+ .detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
@@ -574,23 +512,6 @@ nvd0_disp_ovly_ofuncs = {
******************************************************************************/
static int
-nvd0_disp_pioc_create_(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, int chid,
- int length, void **pobject)
-{
- return nv50_disp_chan_create_(parent, engine, oclass, chid,
- length, pobject);
-}
-
-static void
-nvd0_disp_pioc_dtor(struct nouveau_object *object)
-{
- struct nv50_disp_pioc *pioc = (void *)object;
- nv50_disp_chan_destroy(&pioc->base);
-}
-
-static int
nvd0_disp_pioc_init(struct nouveau_object *object)
{
struct nv50_disp_priv *priv = (void *)object->engine;
@@ -643,152 +564,68 @@ nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend)
* EVO immediate overlay channel objects
******************************************************************************/
-static int
-nvd0_disp_oimm_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_display_oimm_class *args = data;
- struct nv50_disp_priv *priv = (void *)engine;
- struct nv50_disp_pioc *pioc;
- int ret;
-
- if (size < sizeof(*args) || args->head >= priv->head.nr)
- return -EINVAL;
-
- ret = nvd0_disp_pioc_create_(parent, engine, oclass, 9 + args->head,
- sizeof(*pioc), (void **)&pioc);
- *pobject = nv_object(pioc);
- if (ret)
- return ret;
-
- return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nvd0_disp_oimm_ofuncs = {
- .ctor = nvd0_disp_oimm_ctor,
- .dtor = nvd0_disp_pioc_dtor,
- .init = nvd0_disp_pioc_init,
- .fini = nvd0_disp_pioc_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_oimm_ctor,
+ .base.dtor = nv50_disp_pioc_dtor,
+ .base.init = nvd0_disp_pioc_init,
+ .base.fini = nvd0_disp_pioc_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 9,
};
/*******************************************************************************
* EVO cursor channel objects
******************************************************************************/
-static int
-nvd0_disp_curs_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_display_curs_class *args = data;
- struct nv50_disp_priv *priv = (void *)engine;
- struct nv50_disp_pioc *pioc;
- int ret;
-
- if (size < sizeof(*args) || args->head >= priv->head.nr)
- return -EINVAL;
-
- ret = nvd0_disp_pioc_create_(parent, engine, oclass, 13 + args->head,
- sizeof(*pioc), (void **)&pioc);
- *pobject = nv_object(pioc);
- if (ret)
- return ret;
-
- return 0;
-}
-
-struct nouveau_ofuncs
+struct nv50_disp_chan_impl
nvd0_disp_curs_ofuncs = {
- .ctor = nvd0_disp_curs_ctor,
- .dtor = nvd0_disp_pioc_dtor,
- .init = nvd0_disp_pioc_init,
- .fini = nvd0_disp_pioc_fini,
- .rd32 = nv50_disp_chan_rd32,
- .wr32 = nv50_disp_chan_wr32,
+ .base.ctor = nv50_disp_curs_ctor,
+ .base.dtor = nv50_disp_pioc_dtor,
+ .base.init = nvd0_disp_pioc_init,
+ .base.fini = nvd0_disp_pioc_fini,
+ .base.map = nv50_disp_chan_map,
+ .base.rd32 = nv50_disp_chan_rd32,
+ .base.wr32 = nv50_disp_chan_wr32,
+ .chid = 13,
};
/*******************************************************************************
* Base display object
******************************************************************************/
-static int
-nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
-{
- struct nv50_disp_priv *priv = (void *)object->engine;
- struct nv04_display_scanoutpos *args = data;
- const int head = (mthd & NV50_DISP_MTHD_HEAD);
- u32 blanke, blanks, total;
-
- if (size < sizeof(*args) || head >= priv->head.nr)
- return -EINVAL;
-
- total = nv_rd32(priv, 0x640414 + (head * 0x300));
- blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
- blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
-
- args->vblanke = (blanke & 0xffff0000) >> 16;
- args->hblanke = (blanke & 0x0000ffff);
- args->vblanks = (blanks & 0xffff0000) >> 16;
- args->hblanks = (blanks & 0x0000ffff);
- args->vtotal = ( total & 0xffff0000) >> 16;
- args->htotal = ( total & 0x0000ffff);
-
- args->time[0] = ktime_to_ns(ktime_get());
- args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
- args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
- args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
- return 0;
-}
-
-static void
-nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
-{
- nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
-}
-
-static void
-nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
+int
+nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
- nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
-}
-
-static int
-nvd0_disp_base_ctor(struct nouveau_object *parent,
- struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_disp_priv *priv = (void *)engine;
- struct nv50_disp_base *base;
+ const u32 total = nv_rd32(priv, 0x640414 + (head * 0x300));
+ const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+ const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+ union {
+ struct nv04_disp_scanoutpos_v0 v0;
+ } *args = data;
int ret;
- ret = nouveau_parent_create(parent, engine, oclass, 0,
- priv->sclass, 0, &base);
- *pobject = nv_object(base);
- if (ret)
+ nv_ioctl(object, "disp scanoutpos size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
+ args->v0.vblanke = (blanke & 0xffff0000) >> 16;
+ args->v0.hblanke = (blanke & 0x0000ffff);
+ args->v0.vblanks = (blanks & 0xffff0000) >> 16;
+ args->v0.hblanks = (blanks & 0x0000ffff);
+ args->v0.vtotal = ( total & 0xffff0000) >> 16;
+ args->v0.htotal = ( total & 0x0000ffff);
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ args->v0.vline = /* vline read locks hline */
+ nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ args->v0.hline =
+ nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ } else
return ret;
- priv->base.vblank->priv = priv;
- priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
- priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
-
- return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
- &base->ramht);
-}
-
-static void
-nvd0_disp_base_dtor(struct nouveau_object *object)
-{
- struct nv50_disp_base *base = (void *)object;
- nouveau_ramht_ref(NULL, &base->ramht);
- nouveau_parent_destroy(&base->base);
+ return 0;
}
static int
@@ -874,41 +711,27 @@ nvd0_disp_base_fini(struct nouveau_object *object, bool suspend)
struct nouveau_ofuncs
nvd0_disp_base_ofuncs = {
- .ctor = nvd0_disp_base_ctor,
- .dtor = nvd0_disp_base_dtor,
+ .ctor = nv50_disp_base_ctor,
+ .dtor = nv50_disp_base_dtor,
.init = nvd0_disp_base_init,
.fini = nvd0_disp_base_fini,
-};
-
-struct nouveau_omthds
-nvd0_disp_base_omthds[] = {
- { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
- { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
- { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
- { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
- { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
- { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
- { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
- {},
+ .mthd = nv50_disp_base_mthd,
+ .ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nvd0_disp_base_oclass[] = {
- { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { GF110_DISP, &nvd0_disp_base_ofuncs },
{}
};
static struct nouveau_oclass
nvd0_disp_sclass[] = {
- { NVD0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
- { NVD0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
- { NVD0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
- { NVD0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
- { NVD0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ { GF110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+ { GF110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+ { GF110_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+ { GF110_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+ { GF110_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
@@ -916,6 +739,27 @@ nvd0_disp_sclass[] = {
* Display engine implementation
******************************************************************************/
+static void
+nvd0_disp_vblank_init(struct nvkm_event *event, int type, int head)
+{
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
+}
+
+static void
+nvd0_disp_vblank_fini(struct nvkm_event *event, int type, int head)
+{
+ struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
+ nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
+}
+
+const struct nvkm_event_func
+nvd0_disp_vblank_func = {
+ .ctor = nouveau_disp_vblank_ctor,
+ .init = nvd0_disp_vblank_init,
+ .fini = nvd0_disp_vblank_fini,
+};
+
static struct nvkm_output *
exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@@ -1343,7 +1187,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
if (mask & intr) {
u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
if (stat & 0x00000001)
- nouveau_event_trigger(priv->base.vblank, 1, i);
+ nouveau_disp_vblank(&priv->base, i);
nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
nv_rd32(priv, 0x6100c0 + (i * 0x800));
}
@@ -1396,9 +1240,11 @@ nvd0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nvd0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nvd0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 11328e3f5df1..47fef1e398c4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -200,17 +200,17 @@ nve0_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nve0_disp_sclass[] = {
- { NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
- { NVE0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
- { NVE0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
- { NVE0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
- { NVE0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ { GK104_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+ { GK104_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+ { GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+ { GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+ { GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nve0_disp_base_oclass[] = {
- { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { GK104_DISP, &nvd0_disp_base_ofuncs },
{}
};
@@ -258,9 +258,11 @@ nve0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
index 104388081d73..04bda4ac4ed3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include "nv50.h"
@@ -35,17 +35,17 @@
static struct nouveau_oclass
nvf0_disp_sclass[] = {
- { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
- { NVF0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
- { NVF0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
- { NVF0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
- { NVF0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ { GK110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
+ { GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
+ { GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
+ { GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
+ { GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nvf0_disp_base_oclass[] = {
- { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ { GK110_DISP, &nvd0_disp_base_ofuncs },
{}
};
@@ -93,9 +93,11 @@ nvf0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
+ .base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
+ .head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
index ad9ba7ccec7f..a5ff00a9cedc 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
@@ -78,6 +78,7 @@ nvkm_output_create_(struct nouveau_object *parent,
outp->info = *dcbE;
outp->index = index;
+ outp->or = ffs(outp->info.or) - 1;
DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n",
dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ?
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
index bc76fbf85710..187f435ad0e2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
@@ -9,6 +9,7 @@ struct nvkm_output {
struct dcb_output info;
int index;
+ int or;
struct nouveau_i2c_port *port;
struct nouveau_i2c_port *edid;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
index eb2d7789555d..6f6e2a898270 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
@@ -22,6 +22,9 @@
* Authors: Ben Skeggs
*/
+#include <core/os.h>
+#include <nvif/event.h>
+
#include <subdev/i2c.h>
#include "outpdp.h"
@@ -86,7 +89,7 @@ done:
atomic_set(&outp->lt.done, 0);
schedule_work(&outp->lt.work);
} else {
- nouveau_event_get(outp->irq);
+ nvkm_notify_get(&outp->irq);
}
if (wait) {
@@ -133,46 +136,59 @@ nvkm_output_dp_detect(struct nvkm_output_dp *outp)
}
}
-static void
-nvkm_output_dp_service_work(struct work_struct *work)
+static int
+nvkm_output_dp_hpd(struct nvkm_notify *notify)
{
- struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work);
- struct nouveau_disp *disp = nouveau_disp(outp);
- int type = atomic_xchg(&outp->pending, 0);
- u32 send = 0;
-
- if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) {
- nvkm_output_dp_detect(outp);
- if (type & NVKM_I2C_UNPLUG)
- send |= NVKM_HPD_UNPLUG;
- if (type & NVKM_I2C_PLUG)
- send |= NVKM_HPD_PLUG;
- nouveau_event_get(outp->base.conn->hpd.event);
- }
-
- if (type & NVKM_I2C_IRQ) {
- nvkm_output_dp_train(&outp->base, 0, true);
- send |= NVKM_HPD_IRQ;
+ struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
+ struct nvkm_output_dp *outp;
+ struct nouveau_disp *disp = nouveau_disp(conn);
+ const struct nvkm_i2c_ntfy_rep *line = notify->data;
+ struct nvif_notify_conn_rep_v0 rep = {};
+
+ list_for_each_entry(outp, &disp->outp, base.head) {
+ if (outp->base.conn == conn &&
+ outp->info.type == DCB_OUTPUT_DP) {
+ DBG("HPD: %d\n", line->mask);
+ nvkm_output_dp_detect(outp);
+
+ if (line->mask & NVKM_I2C_UNPLUG)
+ rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG;
+ if (line->mask & NVKM_I2C_PLUG)
+ rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG;
+
+ nvkm_event_send(&disp->hpd, rep.mask, conn->index,
+ &rep, sizeof(rep));
+ return NVKM_NOTIFY_KEEP;
+ }
}
- nouveau_event_trigger(disp->hpd, send, outp->base.info.connector);
+ WARN_ON(1);
+ return NVKM_NOTIFY_DROP;
}
static int
-nvkm_output_dp_service(void *data, u32 type, int index)
+nvkm_output_dp_irq(struct nvkm_notify *notify)
{
- struct nvkm_output_dp *outp = data;
- DBG("HPD: %d\n", type);
- atomic_or(type, &outp->pending);
- schedule_work(&outp->work);
- return NVKM_EVENT_DROP;
+ struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), irq);
+ struct nouveau_disp *disp = nouveau_disp(outp);
+ const struct nvkm_i2c_ntfy_rep *line = notify->data;
+ struct nvif_notify_conn_rep_v0 rep = {
+ .mask = NVIF_NOTIFY_CONN_V0_IRQ,
+ };
+ int index = outp->base.info.connector;
+
+ DBG("IRQ: %d\n", line->mask);
+ nvkm_output_dp_train(&outp->base, 0, true);
+
+ nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
+ return NVKM_NOTIFY_DROP;
}
int
_nvkm_output_dp_fini(struct nouveau_object *object, bool suspend)
{
struct nvkm_output_dp *outp = (void *)object;
- nouveau_event_put(outp->irq);
+ nvkm_notify_put(&outp->irq);
nvkm_output_dp_enable(outp, false);
return nvkm_output_fini(&outp->base, suspend);
}
@@ -189,7 +205,7 @@ void
_nvkm_output_dp_dtor(struct nouveau_object *object)
{
struct nvkm_output_dp *outp = (void *)object;
- nouveau_event_ref(NULL, &outp->irq);
+ nvkm_notify_fini(&outp->irq);
nvkm_output_destroy(&outp->base);
}
@@ -213,7 +229,7 @@ nvkm_output_dp_create_(struct nouveau_object *parent,
if (ret)
return ret;
- nouveau_event_ref(NULL, &outp->base.conn->hpd.event);
+ nvkm_notify_fini(&outp->base.conn->hpd);
/* access to the aux channel is not optional... */
if (!outp->base.edid) {
@@ -238,20 +254,28 @@ nvkm_output_dp_create_(struct nouveau_object *parent,
atomic_set(&outp->lt.done, 0);
/* link maintenance */
- ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_IRQ, outp->base.edid->index,
- nvkm_output_dp_service, outp, &outp->irq);
+ ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_irq, true,
+ &(struct nvkm_i2c_ntfy_req) {
+ .mask = NVKM_I2C_IRQ,
+ .port = outp->base.edid->index,
+ },
+ sizeof(struct nvkm_i2c_ntfy_req),
+ sizeof(struct nvkm_i2c_ntfy_rep),
+ &outp->irq);
if (ret) {
ERR("error monitoring aux irq event: %d\n", ret);
return ret;
}
- INIT_WORK(&outp->work, nvkm_output_dp_service_work);
-
/* hotplug detect, replaces gpio-based mechanism with aux events */
- ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
- outp->base.edid->index,
- nvkm_output_dp_service, outp,
- &outp->base.conn->hpd.event);
+ ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_hpd, true,
+ &(struct nvkm_i2c_ntfy_req) {
+ .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
+ .port = outp->base.edid->index,
+ },
+ sizeof(struct nvkm_i2c_ntfy_req),
+ sizeof(struct nvkm_i2c_ntfy_rep),
+ &outp->base.conn->hpd);
if (ret) {
ERR("error monitoring aux hpd events: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
index ff33ba12cb67..1fac367cc867 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
@@ -12,10 +12,7 @@ struct nvkm_output_dp {
struct nvbios_dpout info;
u8 version;
- struct nouveau_eventh *irq;
- struct nouveau_eventh *hpd;
- struct work_struct work;
- atomic_t pending;
+ struct nvkm_notify irq;
bool present;
u8 dpcd[16];
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
index fe0f256f11bf..d00f89a468a7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -143,38 +144,29 @@ nv50_pior_dp_impl = {
*****************************************************************************/
int
-nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data)
+nv50_pior_power(NV50_DISP_MTHD_V1)
{
- const u32 stat = data & NV50_DISP_PIOR_PWR_STATE;
- const u32 soff = (or * 0x800);
+ const u32 soff = outp->or * 0x800;
+ union {
+ struct nv50_disp_pior_pwr_v0 v0;
+ } *args = data;
+ u32 ctrl, type;
+ int ret;
+
+ nv_ioctl(object, "disp pior pwr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
+ args->v0.version, args->v0.state, args->v0.type);
+ if (args->v0.type > 0x0f)
+ return -EINVAL;
+ ctrl = !!args->v0.state;
+ type = args->v0.type;
+ } else
+ return ret;
+
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
- nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat);
+ nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
+ priv->pior.type[outp->or] = type;
return 0;
}
-
-int
-nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
-{
- struct nv50_disp_priv *priv = (void *)object->engine;
- const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12;
- const u8 or = (mthd & NV50_DISP_PIOR_MTHD_OR);
- u32 *data = args;
- int ret;
-
- if (size < sizeof(u32))
- return -EINVAL;
-
- mthd &= ~NV50_DISP_PIOR_MTHD_TYPE;
- mthd &= ~NV50_DISP_PIOR_MTHD_OR;
- switch (mthd) {
- case NV50_DISP_PIOR_PWR:
- ret = priv->pior.power(priv, or, data[0]);
- priv->pior.type[or] = type;
- break;
- default:
- return -EINVAL;
- }
-
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/priv.h b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
index 26e9a42569c7..dbd43ae9df81 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h
@@ -11,6 +11,7 @@ struct nouveau_disp_impl {
struct nouveau_oclass base;
struct nouveau_oclass **outp;
struct nouveau_oclass **conn;
+ const struct nvkm_event_func *vblank;
};
#define nouveau_disp_create(p,e,c,h,i,x,d) \
@@ -39,4 +40,8 @@ int _nouveau_disp_fini(struct nouveau_object *, bool);
extern struct nouveau_oclass *nvkm_output_oclass;
extern struct nouveau_oclass *nvkm_connector_oclass;
+int nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *);
+void nouveau_disp_vblank(struct nouveau_disp *, int head);
+int nouveau_disp_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
index 7a1ebdfa9e1b..ddf1760c4400 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -32,77 +33,26 @@
#include "nv50.h"
int
-nv50_sor_power(struct nv50_disp_priv *priv, int or, u32 data)
+nv50_sor_power(NV50_DISP_MTHD_V1)
{
- const u32 stat = data & NV50_DISP_SOR_PWR_STATE;
- const u32 soff = (or * 0x800);
+ union {
+ struct nv50_disp_sor_pwr_v0 v0;
+ } *args = data;
+ const u32 soff = outp->or * 0x800;
+ u32 stat;
+ int ret;
+
+ nv_ioctl(object, "disp sor pwr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "disp sor pwr vers %d state %d\n",
+ args->v0.version, args->v0.state);
+ stat = !!args->v0.state;
+ } else
+ return ret;
+
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat);
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000);
return 0;
}
-
-int
-nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
-{
- struct nv50_disp_priv *priv = (void *)object->engine;
- const u8 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
- const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
- const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
- const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR);
- const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
- struct nvkm_output *outp = NULL, *temp;
- u32 data;
- int ret = -EINVAL;
-
- if (size < sizeof(u32))
- return -EINVAL;
- data = *(u32 *)args;
-
- list_for_each_entry(temp, &priv->base.outp, head) {
- if ((temp->info.hasht & 0xff) == type &&
- (temp->info.hashm & mask) == mask) {
- outp = temp;
- break;
- }
- }
-
- switch (mthd & ~0x3f) {
- case NV50_DISP_SOR_PWR:
- ret = priv->sor.power(priv, or, data);
- break;
- case NVA3_DISP_SOR_HDA_ELD:
- ret = priv->sor.hda_eld(priv, or, args, size);
- break;
- case NV84_DISP_SOR_HDMI_PWR:
- ret = priv->sor.hdmi(priv, head, or, data);
- break;
- case NV50_DISP_SOR_LVDS_SCRIPT:
- priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
- ret = 0;
- break;
- case NV94_DISP_SOR_DP_PWR:
- if (outp) {
- struct nvkm_output_dp *outpdp = (void *)outp;
- switch (data) {
- case NV94_DISP_SOR_DP_PWR_STATE_OFF:
- nouveau_event_put(outpdp->irq);
- ((struct nvkm_output_dp_impl *)nv_oclass(outp))
- ->lnk_pwr(outpdp, 0);
- atomic_set(&outpdp->lt.done, 0);
- break;
- case NV94_DISP_SOR_DP_PWR_STATE_ON:
- nvkm_output_dp_train(&outpdp->base, 0, true);
- break;
- default:
- return -EINVAL;
- }
- }
- break;
- default:
- BUG_ON(1);
- }
-
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
index 05487cda84a8..39f85d627336 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
index 97f0e9cd3d40..7b7bbc3e459e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
index 5103e88d1877..e1500f77a56a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/base.c
@@ -23,98 +23,143 @@
*/
#include <core/object.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/fb.h>
-#include <engine/dmaobj.h>
+#include <subdev/instmem.h>
+
+#include "priv.h"
static int
-nouveau_dmaobj_ctor(struct nouveau_object *parent,
+nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
+ struct nouveau_gpuobj **pgpuobj)
+{
+ const struct nvkm_dmaeng_impl *impl = (void *)
+ nv_oclass(nv_object(dmaobj)->engine);
+ int ret = 0;
+
+ if (nv_object(dmaobj) == parent) { /* ctor bind */
+ if (nv_mclass(parent->parent) == NV_DEVICE) {
+ /* delayed, or no, binding */
+ return 0;
+ }
+ ret = impl->bind(dmaobj, parent, pgpuobj);
+ if (ret == 0)
+ nouveau_object_ref(NULL, &parent);
+ return ret;
+ }
+
+ return impl->bind(dmaobj, parent, pgpuobj);
+}
+
+int
+nvkm_dmaobj_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
+ struct nouveau_oclass *oclass, void **pdata, u32 *psize,
+ int length, void **pobject)
{
- struct nouveau_dmaeng *dmaeng = (void *)engine;
+ union {
+ struct nv_dma_v0 v0;
+ } *args = *pdata;
+ struct nouveau_instmem *instmem = nouveau_instmem(parent);
+ struct nouveau_client *client = nouveau_client(parent);
+ struct nouveau_device *device = nv_device(parent);
+ struct nouveau_fb *pfb = nouveau_fb(parent);
struct nouveau_dmaobj *dmaobj;
- struct nouveau_gpuobj *gpuobj;
- struct nv_dma_class *args = data;
+ void *data = *pdata;
+ u32 size = *psize;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
-
- ret = nouveau_object_create(parent, engine, oclass, 0, &dmaobj);
- *pobject = nv_object(dmaobj);
+ ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
+ dmaobj = *pobject;
if (ret)
return ret;
- switch (args->flags & NV_DMA_TARGET_MASK) {
- case NV_DMA_TARGET_VM:
+ nv_ioctl(parent, "create dma size %d\n", *psize);
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ nv_ioctl(parent, "create dma vers %d target %d access %d "
+ "start %016llx limit %016llx\n",
+ args->v0.version, args->v0.target, args->v0.access,
+ args->v0.start, args->v0.limit);
+ dmaobj->target = args->v0.target;
+ dmaobj->access = args->v0.access;
+ dmaobj->start = args->v0.start;
+ dmaobj->limit = args->v0.limit;
+ } else
+ return ret;
+
+ *pdata = data;
+ *psize = size;
+
+ if (dmaobj->start > dmaobj->limit)
+ return -EINVAL;
+
+ switch (dmaobj->target) {
+ case NV_DMA_V0_TARGET_VM:
dmaobj->target = NV_MEM_TARGET_VM;
break;
- case NV_DMA_TARGET_VRAM:
+ case NV_DMA_V0_TARGET_VRAM:
+ if (!client->super) {
+ if (dmaobj->limit >= pfb->ram->size - instmem->reserved)
+ return -EACCES;
+ if (device->card_type >= NV_50)
+ return -EACCES;
+ }
dmaobj->target = NV_MEM_TARGET_VRAM;
break;
- case NV_DMA_TARGET_PCI:
+ case NV_DMA_V0_TARGET_PCI:
+ if (!client->super)
+ return -EACCES;
dmaobj->target = NV_MEM_TARGET_PCI;
break;
- case NV_DMA_TARGET_PCI_US:
- case NV_DMA_TARGET_AGP:
+ case NV_DMA_V0_TARGET_PCI_US:
+ case NV_DMA_V0_TARGET_AGP:
+ if (!client->super)
+ return -EACCES;
dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP;
break;
default:
return -EINVAL;
}
- switch (args->flags & NV_DMA_ACCESS_MASK) {
- case NV_DMA_ACCESS_VM:
+ switch (dmaobj->access) {
+ case NV_DMA_V0_ACCESS_VM:
dmaobj->access = NV_MEM_ACCESS_VM;
break;
- case NV_DMA_ACCESS_RD:
+ case NV_DMA_V0_ACCESS_RD:
dmaobj->access = NV_MEM_ACCESS_RO;
break;
- case NV_DMA_ACCESS_WR:
+ case NV_DMA_V0_ACCESS_WR:
dmaobj->access = NV_MEM_ACCESS_WO;
break;
- case NV_DMA_ACCESS_RDWR:
+ case NV_DMA_V0_ACCESS_RDWR:
dmaobj->access = NV_MEM_ACCESS_RW;
break;
default:
return -EINVAL;
}
- dmaobj->start = args->start;
- dmaobj->limit = args->limit;
- dmaobj->conf0 = args->conf0;
-
- switch (nv_mclass(parent)) {
- case NV_DEVICE_CLASS:
- /* delayed, or no, binding */
- break;
- default:
- ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
- if (ret == 0) {
- nouveau_object_ref(NULL, pobject);
- *pobject = nv_object(gpuobj);
- }
- break;
- }
-
return ret;
}
-static struct nouveau_ofuncs
-nouveau_dmaobj_ofuncs = {
- .ctor = nouveau_dmaobj_ctor,
- .dtor = nouveau_object_destroy,
- .init = nouveau_object_init,
- .fini = nouveau_object_fini,
-};
-
-struct nouveau_oclass
-nouveau_dmaobj_sclass[] = {
- { NV_DMA_FROM_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
- { NV_DMA_TO_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
- { NV_DMA_IN_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
- {}
-};
+int
+_nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ const struct nvkm_dmaeng_impl *impl = (void *)oclass;
+ struct nouveau_dmaeng *dmaeng;
+ int ret;
+
+ ret = nouveau_engine_create(parent, engine, oclass, true, "DMAOBJ",
+ "dmaobj", &dmaeng);
+ *pobject = nv_object(dmaeng);
+ if (ret)
+ return ret;
+
+ nv_engine(dmaeng)->sclass = impl->sclass;
+ dmaeng->bind = nvkm_dmaobj_bind;
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
index 027d8217c0fa..20c9dbfe3b2e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv04.c
@@ -23,121 +23,143 @@
*/
#include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/class.h>
#include <subdev/fb.h>
#include <subdev/vm/nv04.h>
-#include <engine/dmaobj.h>
+#include "priv.h"
-struct nv04_dmaeng_priv {
- struct nouveau_dmaeng base;
+struct nv04_dmaobj_priv {
+ struct nouveau_dmaobj base;
+ bool clone;
+ u32 flags0;
+ u32 flags2;
};
static int
-nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
- struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
- struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng);
+ struct nv04_dmaobj_priv *priv = (void *)dmaobj;
struct nouveau_gpuobj *gpuobj;
- u32 flags0 = nv_mclass(dmaobj);
- u32 flags2 = 0x00000000;
- u64 offset = dmaobj->start & 0xfffff000;
- u64 adjust = dmaobj->start & 0x00000fff;
- u32 length = dmaobj->limit - dmaobj->start;
+ u64 offset = priv->base.start & 0xfffff000;
+ u64 adjust = priv->base.start & 0x00000fff;
+ u32 length = priv->base.limit - priv->base.start;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
- case NV03_CHANNEL_DMA_CLASS:
- case NV10_CHANNEL_DMA_CLASS:
- case NV17_CHANNEL_DMA_CLASS:
- case NV40_CHANNEL_DMA_CLASS:
+ case NV03_CHANNEL_DMA:
+ case NV10_CHANNEL_DMA:
+ case NV17_CHANNEL_DMA:
+ case NV40_CHANNEL_DMA:
break;
default:
return -EINVAL;
}
}
- if (dmaobj->target == NV_MEM_TARGET_VM) {
- if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) {
- struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
- if (!dmaobj->start)
- return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
- offset = nv_ro32(pgt, 8 + (offset >> 10));
- offset &= 0xfffff000;
- }
+ if (priv->clone) {
+ struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaobj);
+ struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
+ if (!dmaobj->start)
+ return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
+ offset = nv_ro32(pgt, 8 + (offset >> 10));
+ offset &= 0xfffff000;
+ }
+
+ ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
+ *pgpuobj = gpuobj;
+ if (ret == 0) {
+ nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
+ nv_wo32(*pgpuobj, 0x04, length);
+ nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset);
+ nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset);
+ }
+
+ return ret;
+}
+
+static int
+nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_dmaeng *dmaeng = (void *)engine;
+ struct nv04_vmmgr_priv *vmm = nv04_vmmgr(engine);
+ struct nv04_dmaobj_priv *priv;
+ int ret;
+
+ ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+ *pobject = nv_object(priv);
+ if (ret || (ret = -ENOSYS, size))
+ return ret;
- dmaobj->target = NV_MEM_TARGET_PCI;
- dmaobj->access = NV_MEM_ACCESS_RW;
+ if (priv->base.target == NV_MEM_TARGET_VM) {
+ if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass)
+ priv->clone = true;
+ priv->base.target = NV_MEM_TARGET_PCI;
+ priv->base.access = NV_MEM_ACCESS_RW;
}
- switch (dmaobj->target) {
+ priv->flags0 = nv_mclass(priv);
+ switch (priv->base.target) {
case NV_MEM_TARGET_VRAM:
- flags0 |= 0x00003000;
+ priv->flags0 |= 0x00003000;
break;
case NV_MEM_TARGET_PCI:
- flags0 |= 0x00023000;
+ priv->flags0 |= 0x00023000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
- flags0 |= 0x00033000;
+ priv->flags0 |= 0x00033000;
break;
default:
return -EINVAL;
}
- switch (dmaobj->access) {
+ switch (priv->base.access) {
case NV_MEM_ACCESS_RO:
- flags0 |= 0x00004000;
+ priv->flags0 |= 0x00004000;
break;
case NV_MEM_ACCESS_WO:
- flags0 |= 0x00008000;
+ priv->flags0 |= 0x00008000;
case NV_MEM_ACCESS_RW:
- flags2 |= 0x00000002;
+ priv->flags2 |= 0x00000002;
break;
default:
return -EINVAL;
}
- ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
- *pgpuobj = gpuobj;
- if (ret == 0) {
- nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
- nv_wo32(*pgpuobj, 0x04, length);
- nv_wo32(*pgpuobj, 0x08, flags2 | offset);
- nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
- }
-
- return ret;
+ return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
-static int
-nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv04_dmaeng_priv *priv;
- int ret;
-
- ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
+static struct nouveau_ofuncs
+nv04_dmaobj_ofuncs = {
+ .ctor = nv04_dmaobj_ctor,
+ .dtor = _nvkm_dmaobj_dtor,
+ .init = _nvkm_dmaobj_init,
+ .fini = _nvkm_dmaobj_fini,
+};
- nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
- priv->base.bind = nv04_dmaobj_bind;
- return 0;
-}
+static struct nouveau_oclass
+nv04_dmaeng_sclass[] = {
+ { NV_DMA_FROM_MEMORY, &nv04_dmaobj_ofuncs },
+ { NV_DMA_TO_MEMORY, &nv04_dmaobj_ofuncs },
+ { NV_DMA_IN_MEMORY, &nv04_dmaobj_ofuncs },
+ {}
+};
-struct nouveau_oclass
-nv04_dmaeng_oclass = {
- .handle = NV_ENGINE(DMAOBJ, 0x04),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nv04_dmaeng_ctor,
- .dtor = _nouveau_dmaeng_dtor,
- .init = _nouveau_dmaeng_init,
- .fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+ .base.handle = NV_ENGINE(DMAOBJ, 0x04),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_dmaeng_ctor,
+ .dtor = _nvkm_dmaeng_dtor,
+ .init = _nvkm_dmaeng_init,
+ .fini = _nvkm_dmaeng_fini,
},
-};
+ .sclass = nv04_dmaeng_sclass,
+ .bind = nv04_dmaobj_bind,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
index 750183f7c057..a740ddba2ee2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nv50.c
@@ -22,140 +22,176 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/fb.h>
-#include <engine/dmaobj.h>
-struct nv50_dmaeng_priv {
- struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nv50_dmaobj_priv {
+ struct nouveau_dmaobj base;
+ u32 flags0;
+ u32 flags5;
};
static int
-nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
- struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
- u32 flags0 = nv_mclass(dmaobj);
- u32 flags5 = 0x00000000;
+ struct nv50_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
- case NV50_CHANNEL_DMA_CLASS:
- case NV84_CHANNEL_DMA_CLASS:
- case NV50_CHANNEL_IND_CLASS:
- case NV84_CHANNEL_IND_CLASS:
- case NV50_DISP_MAST_CLASS:
- case NV84_DISP_MAST_CLASS:
- case NV94_DISP_MAST_CLASS:
- case NVA0_DISP_MAST_CLASS:
- case NVA3_DISP_MAST_CLASS:
- case NV50_DISP_SYNC_CLASS:
- case NV84_DISP_SYNC_CLASS:
- case NV94_DISP_SYNC_CLASS:
- case NVA0_DISP_SYNC_CLASS:
- case NVA3_DISP_SYNC_CLASS:
- case NV50_DISP_OVLY_CLASS:
- case NV84_DISP_OVLY_CLASS:
- case NV94_DISP_OVLY_CLASS:
- case NVA0_DISP_OVLY_CLASS:
- case NVA3_DISP_OVLY_CLASS:
+ case NV40_CHANNEL_DMA:
+ case NV50_CHANNEL_GPFIFO:
+ case G82_CHANNEL_GPFIFO:
+ case NV50_DISP_CORE_CHANNEL_DMA:
+ case G82_DISP_CORE_CHANNEL_DMA:
+ case GT206_DISP_CORE_CHANNEL_DMA:
+ case GT200_DISP_CORE_CHANNEL_DMA:
+ case GT214_DISP_CORE_CHANNEL_DMA:
+ case NV50_DISP_BASE_CHANNEL_DMA:
+ case G82_DISP_BASE_CHANNEL_DMA:
+ case GT200_DISP_BASE_CHANNEL_DMA:
+ case GT214_DISP_BASE_CHANNEL_DMA:
+ case NV50_DISP_OVERLAY_CHANNEL_DMA:
+ case G82_DISP_OVERLAY_CHANNEL_DMA:
+ case GT200_DISP_OVERLAY_CHANNEL_DMA:
+ case GT214_DISP_OVERLAY_CHANNEL_DMA:
break;
default:
return -EINVAL;
}
}
- if (!(dmaobj->conf0 & NV50_DMA_CONF0_ENABLE)) {
- if (dmaobj->target == NV_MEM_TARGET_VM) {
- dmaobj->conf0 = NV50_DMA_CONF0_PRIV_VM;
- dmaobj->conf0 |= NV50_DMA_CONF0_PART_VM;
- dmaobj->conf0 |= NV50_DMA_CONF0_COMP_VM;
- dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_VM;
+ ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+ if (ret == 0) {
+ nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+ nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+ nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+ nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+ upper_32_bits(priv->base.start));
+ nv_wo32(*pgpuobj, 0x10, 0x00000000);
+ nv_wo32(*pgpuobj, 0x14, priv->flags5);
+ }
+
+ return ret;
+}
+
+static int
+nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_dmaeng *dmaeng = (void *)engine;
+ union {
+ struct nv50_dma_v0 v0;
+ } *args;
+ struct nv50_dmaobj_priv *priv;
+ u32 user, part, comp, kind;
+ int ret;
+
+ ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+ args = data;
+
+ nv_ioctl(parent, "create nv50 dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create nv50 dma vers %d priv %d part %d "
+ "comp %d kind %02x\n", args->v0.version,
+ args->v0.priv, args->v0.part, args->v0.comp,
+ args->v0.kind);
+ user = args->v0.priv;
+ part = args->v0.part;
+ comp = args->v0.comp;
+ kind = args->v0.kind;
+ } else
+ if (size == 0) {
+ if (priv->base.target != NV_MEM_TARGET_VM) {
+ user = NV50_DMA_V0_PRIV_US;
+ part = NV50_DMA_V0_PART_256;
+ comp = NV50_DMA_V0_COMP_NONE;
+ kind = NV50_DMA_V0_KIND_PITCH;
} else {
- dmaobj->conf0 = NV50_DMA_CONF0_PRIV_US;
- dmaobj->conf0 |= NV50_DMA_CONF0_PART_256;
- dmaobj->conf0 |= NV50_DMA_CONF0_COMP_NONE;
- dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
+ user = NV50_DMA_V0_PRIV_VM;
+ part = NV50_DMA_V0_PART_VM;
+ comp = NV50_DMA_V0_COMP_VM;
+ kind = NV50_DMA_V0_KIND_VM;
}
- }
+ } else
+ return ret;
- flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_COMP) << 22;
- flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_TYPE) << 22;
- flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_PRIV);
- flags5 |= (dmaobj->conf0 & NV50_DMA_CONF0_PART);
+ if (user > 2 || part > 2 || comp > 3 || kind > 0x7f)
+ return -EINVAL;
+ priv->flags0 = (comp << 29) | (kind << 22) | (user << 20);
+ priv->flags5 = (part << 16);
- switch (dmaobj->target) {
+ switch (priv->base.target) {
case NV_MEM_TARGET_VM:
- flags0 |= 0x00000000;
+ priv->flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
- flags0 |= 0x00010000;
+ priv->flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
- flags0 |= 0x00020000;
+ priv->flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
- flags0 |= 0x00030000;
+ priv->flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
- switch (dmaobj->access) {
+ switch (priv->base.access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
- flags0 |= 0x00040000;
+ priv->flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
- flags0 |= 0x00080000;
+ priv->flags0 |= 0x00080000;
break;
+ default:
+ return -EINVAL;
}
- ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
- if (ret == 0) {
- nv_wo32(*pgpuobj, 0x00, flags0);
- nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
- nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
- nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
- upper_32_bits(dmaobj->start));
- nv_wo32(*pgpuobj, 0x10, 0x00000000);
- nv_wo32(*pgpuobj, 0x14, flags5);
- }
-
- return ret;
+ return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
-static int
-nv50_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv50_dmaeng_priv *priv;
- int ret;
-
- ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
+static struct nouveau_ofuncs
+nv50_dmaobj_ofuncs = {
+ .ctor = nv50_dmaobj_ctor,
+ .dtor = _nvkm_dmaobj_dtor,
+ .init = _nvkm_dmaobj_init,
+ .fini = _nvkm_dmaobj_fini,
+};
- nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
- priv->base.bind = nv50_dmaobj_bind;
- return 0;
-}
+static struct nouveau_oclass
+nv50_dmaeng_sclass[] = {
+ { NV_DMA_FROM_MEMORY, &nv50_dmaobj_ofuncs },
+ { NV_DMA_TO_MEMORY, &nv50_dmaobj_ofuncs },
+ { NV_DMA_IN_MEMORY, &nv50_dmaobj_ofuncs },
+ {}
+};
-struct nouveau_oclass
-nv50_dmaeng_oclass = {
- .handle = NV_ENGINE(DMAOBJ, 0x50),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nv50_dmaeng_ctor,
- .dtor = _nouveau_dmaeng_dtor,
- .init = _nouveau_dmaeng_init,
- .fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+ .base.handle = NV_ENGINE(DMAOBJ, 0x50),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_dmaeng_ctor,
+ .dtor = _nvkm_dmaeng_dtor,
+ .init = _nvkm_dmaeng_init,
+ .fini = _nvkm_dmaeng_fini,
},
-};
+ .sclass = nv50_dmaeng_sclass,
+ .bind = nv50_dmaobj_bind,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
index cd3970d03b80..88ec33b20048 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvc0.c
@@ -22,32 +22,35 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/device.h>
#include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/fb.h>
-#include <engine/dmaobj.h>
-struct nvc0_dmaeng_priv {
- struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nvc0_dmaobj_priv {
+ struct nouveau_dmaobj base;
+ u32 flags0;
+ u32 flags5;
};
static int
-nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvc0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
- struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
- u32 flags0 = nv_mclass(dmaobj);
- u32 flags5 = 0x00000000;
+ struct nvc0_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
- case NVA3_DISP_MAST_CLASS:
- case NVA3_DISP_SYNC_CLASS:
- case NVA3_DISP_OVLY_CLASS:
+ case GT214_DISP_CORE_CHANNEL_DMA:
+ case GT214_DISP_BASE_CHANNEL_DMA:
+ case GT214_DISP_OVERLAY_CHANNEL_DMA:
break;
default:
return -EINVAL;
@@ -55,89 +58,122 @@ nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
} else
return 0;
- if (!(dmaobj->conf0 & NVC0_DMA_CONF0_ENABLE)) {
- if (dmaobj->target == NV_MEM_TARGET_VM) {
- dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_VM;
- dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
+ ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
+ if (ret == 0) {
+ nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
+ nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
+ nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
+ nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
+ upper_32_bits(priv->base.start));
+ nv_wo32(*pgpuobj, 0x10, 0x00000000);
+ nv_wo32(*pgpuobj, 0x14, priv->flags5);
+ }
+
+ return ret;
+}
+
+static int
+nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_dmaeng *dmaeng = (void *)engine;
+ union {
+ struct gf100_dma_v0 v0;
+ } *args;
+ struct nvc0_dmaobj_priv *priv;
+ u32 kind, user, unkn;
+ int ret;
+
+ ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+ args = data;
+
+ nv_ioctl(parent, "create gf100 dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create gf100 dma vers %d priv %d kind %02x\n",
+ args->v0.version, args->v0.priv, args->v0.kind);
+ kind = args->v0.kind;
+ user = args->v0.priv;
+ unkn = 0;
+ } else
+ if (size == 0) {
+ if (priv->base.target != NV_MEM_TARGET_VM) {
+ kind = GF100_DMA_V0_KIND_PITCH;
+ user = GF100_DMA_V0_PRIV_US;
+ unkn = 2;
} else {
- dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_US;
- dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
- dmaobj->conf0 |= 0x00020000;
+ kind = GF100_DMA_V0_KIND_VM;
+ user = GF100_DMA_V0_PRIV_VM;
+ unkn = 0;
}
- }
+ } else
+ return ret;
- flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
- flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_PRIV);
- flags5 |= (dmaobj->conf0 & NVC0_DMA_CONF0_UNKN);
+ if (user > 2)
+ return -EINVAL;
+ priv->flags0 |= (kind << 22) | (user << 20);
+ priv->flags5 |= (unkn << 16);
- switch (dmaobj->target) {
+ switch (priv->base.target) {
case NV_MEM_TARGET_VM:
- flags0 |= 0x00000000;
+ priv->flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
- flags0 |= 0x00010000;
+ priv->flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
- flags0 |= 0x00020000;
+ priv->flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
- flags0 |= 0x00030000;
+ priv->flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
- switch (dmaobj->access) {
+ switch (priv->base.access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
- flags0 |= 0x00040000;
+ priv->flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
- flags0 |= 0x00080000;
+ priv->flags0 |= 0x00080000;
break;
}
- ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
- if (ret == 0) {
- nv_wo32(*pgpuobj, 0x00, flags0);
- nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
- nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
- nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
- upper_32_bits(dmaobj->start));
- nv_wo32(*pgpuobj, 0x10, 0x00000000);
- nv_wo32(*pgpuobj, 0x14, flags5);
- }
-
- return ret;
+ return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
-static int
-nvc0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nvc0_dmaeng_priv *priv;
- int ret;
-
- ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
+static struct nouveau_ofuncs
+nvc0_dmaobj_ofuncs = {
+ .ctor = nvc0_dmaobj_ctor,
+ .dtor = _nvkm_dmaobj_dtor,
+ .init = _nvkm_dmaobj_init,
+ .fini = _nvkm_dmaobj_fini,
+};
- nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
- priv->base.bind = nvc0_dmaobj_bind;
- return 0;
-}
+static struct nouveau_oclass
+nvc0_dmaeng_sclass[] = {
+ { NV_DMA_FROM_MEMORY, &nvc0_dmaobj_ofuncs },
+ { NV_DMA_TO_MEMORY, &nvc0_dmaobj_ofuncs },
+ { NV_DMA_IN_MEMORY, &nvc0_dmaobj_ofuncs },
+ {}
+};
-struct nouveau_oclass
-nvc0_dmaeng_oclass = {
- .handle = NV_ENGINE(DMAOBJ, 0xc0),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nvc0_dmaeng_ctor,
- .dtor = _nouveau_dmaeng_dtor,
- .init = _nouveau_dmaeng_init,
- .fini = _nouveau_dmaeng_fini,
+struct nouveau_oclass *
+nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+ .base.handle = NV_ENGINE(DMAOBJ, 0xc0),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_dmaeng_ctor,
+ .dtor = _nvkm_dmaeng_dtor,
+ .init = _nvkm_dmaeng_init,
+ .fini = _nvkm_dmaeng_fini,
},
-};
+ .sclass = nvc0_dmaeng_sclass,
+ .bind = nvc0_dmaobj_bind,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
index 1cfb3bb90131..3fc4f0b0eaca 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
@@ -22,40 +22,40 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/device.h>
#include <core/gpuobj.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/fb.h>
-#include <engine/dmaobj.h>
-struct nvd0_dmaeng_priv {
- struct nouveau_dmaeng base;
+#include "priv.h"
+
+struct nvd0_dmaobj_priv {
+ struct nouveau_dmaobj base;
+ u32 flags0;
};
static int
-nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
+nvd0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
- struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
- u32 flags0 = 0x00000000;
+ struct nvd0_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
- case NVD0_DISP_MAST_CLASS:
- case NVD0_DISP_SYNC_CLASS:
- case NVD0_DISP_OVLY_CLASS:
- case NVE0_DISP_MAST_CLASS:
- case NVE0_DISP_SYNC_CLASS:
- case NVE0_DISP_OVLY_CLASS:
- case NVF0_DISP_MAST_CLASS:
- case NVF0_DISP_SYNC_CLASS:
- case NVF0_DISP_OVLY_CLASS:
- case GM107_DISP_MAST_CLASS:
- case GM107_DISP_SYNC_CLASS:
- case GM107_DISP_OVLY_CLASS:
+ case GF110_DISP_CORE_CHANNEL_DMA:
+ case GK104_DISP_CORE_CHANNEL_DMA:
+ case GK110_DISP_CORE_CHANNEL_DMA:
+ case GM107_DISP_CORE_CHANNEL_DMA:
+ case GF110_DISP_BASE_CHANNEL_DMA:
+ case GK104_DISP_BASE_CHANNEL_DMA:
+ case GK110_DISP_BASE_CHANNEL_DMA:
+ case GF110_DISP_OVERLAY_CONTROL_DMA:
+ case GK104_DISP_OVERLAY_CONTROL_DMA:
break;
default:
return -EINVAL;
@@ -63,33 +63,11 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
} else
return 0;
- if (!(dmaobj->conf0 & NVD0_DMA_CONF0_ENABLE)) {
- if (dmaobj->target == NV_MEM_TARGET_VM) {
- dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
- dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
- } else {
- dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
- dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
- }
- }
-
- flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
- flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
-
- switch (dmaobj->target) {
- case NV_MEM_TARGET_VRAM:
- flags0 |= 0x00000009;
- break;
- default:
- return -EINVAL;
- break;
- }
-
ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
if (ret == 0) {
- nv_wo32(*pgpuobj, 0x00, flags0);
- nv_wo32(*pgpuobj, 0x04, dmaobj->start >> 8);
- nv_wo32(*pgpuobj, 0x08, dmaobj->limit >> 8);
+ nv_wo32(*pgpuobj, 0x00, priv->flags0);
+ nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8);
+ nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8);
nv_wo32(*pgpuobj, 0x0c, 0x00000000);
nv_wo32(*pgpuobj, 0x10, 0x00000000);
nv_wo32(*pgpuobj, 0x14, 0x00000000);
@@ -99,30 +77,91 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
}
static int
-nvd0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+nvd0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nvd0_dmaeng_priv *priv;
+ struct nouveau_dmaeng *dmaeng = (void *)engine;
+ union {
+ struct gf110_dma_v0 v0;
+ } *args;
+ struct nvd0_dmaobj_priv *priv;
+ u32 kind, page;
int ret;
- ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
+ ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
+ args = data;
- nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
- priv->base.bind = nvd0_dmaobj_bind;
- return 0;
+ nv_ioctl(parent, "create gf110 dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create gf100 dma vers %d page %d kind %02x\n",
+ args->v0.version, args->v0.page, args->v0.kind);
+ kind = args->v0.kind;
+ page = args->v0.page;
+ } else
+ if (size == 0) {
+ if (priv->base.target != NV_MEM_TARGET_VM) {
+ kind = GF110_DMA_V0_KIND_PITCH;
+ page = GF110_DMA_V0_PAGE_SP;
+ } else {
+ kind = GF110_DMA_V0_KIND_VM;
+ page = GF110_DMA_V0_PAGE_LP;
+ }
+ } else
+ return ret;
+
+ if (page > 1)
+ return -EINVAL;
+ priv->flags0 = (kind << 20) | (page << 6);
+
+ switch (priv->base.target) {
+ case NV_MEM_TARGET_VRAM:
+ priv->flags0 |= 0x00000009;
+ break;
+ case NV_MEM_TARGET_VM:
+ case NV_MEM_TARGET_PCI:
+ case NV_MEM_TARGET_PCI_NOSNOOP:
+ /* XXX: don't currently know how to construct a real one
+ * of these. we only use them to represent pushbufs
+ * on these chipsets, and the classes that use them
+ * deal with the target themselves.
+ */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
-struct nouveau_oclass
-nvd0_dmaeng_oclass = {
- .handle = NV_ENGINE(DMAOBJ, 0xd0),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nvd0_dmaeng_ctor,
- .dtor = _nouveau_dmaeng_dtor,
- .init = _nouveau_dmaeng_init,
- .fini = _nouveau_dmaeng_fini,
- },
+static struct nouveau_ofuncs
+nvd0_dmaobj_ofuncs = {
+ .ctor = nvd0_dmaobj_ctor,
+ .dtor = _nvkm_dmaobj_dtor,
+ .init = _nvkm_dmaobj_init,
+ .fini = _nvkm_dmaobj_fini,
};
+
+static struct nouveau_oclass
+nvd0_dmaeng_sclass[] = {
+ { NV_DMA_FROM_MEMORY, &nvd0_dmaobj_ofuncs },
+ { NV_DMA_TO_MEMORY, &nvd0_dmaobj_ofuncs },
+ { NV_DMA_IN_MEMORY, &nvd0_dmaobj_ofuncs },
+ {}
+};
+
+struct nouveau_oclass *
+nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
+ .base.handle = NV_ENGINE(DMAOBJ, 0xd0),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_dmaeng_ctor,
+ .dtor = _nvkm_dmaeng_dtor,
+ .init = _nvkm_dmaeng_init,
+ .fini = _nvkm_dmaeng_fini,
+ },
+ .sclass = nvd0_dmaeng_sclass,
+ .bind = nvd0_dmaobj_bind,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h b/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
new file mode 100644
index 000000000000..36f743866937
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
@@ -0,0 +1,30 @@
+#ifndef __NVKM_DMAOBJ_PRIV_H__
+#define __NVKM_DMAOBJ_PRIV_H__
+
+#include <engine/dmaobj.h>
+
+#define nvkm_dmaobj_create(p,e,c,pa,sa,d) \
+ nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d)
+
+int nvkm_dmaobj_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void **, u32 *,
+ int, void **);
+#define _nvkm_dmaobj_dtor nouveau_object_destroy
+#define _nvkm_dmaobj_init nouveau_object_init
+#define _nvkm_dmaobj_fini nouveau_object_fini
+
+int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+#define _nvkm_dmaeng_dtor _nouveau_engine_dtor
+#define _nvkm_dmaeng_init _nouveau_engine_init
+#define _nvkm_dmaeng_fini _nouveau_engine_fini
+
+struct nvkm_dmaeng_impl {
+ struct nouveau_oclass base;
+ struct nouveau_oclass *sclass;
+ int (*bind)(struct nouveau_dmaobj *, struct nouveau_object *,
+ struct nouveau_gpuobj **);
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
index 56ed3d73bf8e..0f999fc45ab9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c
@@ -26,11 +26,30 @@
#include <core/object.h>
#include <core/handle.h>
#include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/event.h>
#include <engine/dmaobj.h>
#include <engine/fifo.h>
+static int
+nouveau_fifo_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ if (size == 0) {
+ notify->size = 0;
+ notify->types = 1;
+ notify->index = 0;
+ return 0;
+ }
+ return -ENOSYS;
+}
+
+static const struct nvkm_event_func
+nouveau_fifo_event_func = {
+ .ctor = nouveau_fifo_event_ctor,
+};
+
int
nouveau_fifo_channel_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -59,14 +78,14 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
dmaeng = (void *)chan->pushdma->base.engine;
switch (chan->pushdma->base.oclass->handle) {
- case NV_DMA_FROM_MEMORY_CLASS:
- case NV_DMA_IN_MEMORY_CLASS:
+ case NV_DMA_FROM_MEMORY:
+ case NV_DMA_IN_MEMORY:
break;
default:
return -EINVAL;
}
- ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu);
+ ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu);
if (ret)
return ret;
@@ -85,15 +104,10 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
return -ENOSPC;
}
- /* map fifo control registers */
- chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
- (chan->chid * size), size);
- if (!chan->user)
- return -EFAULT;
-
- nouveau_event_trigger(priv->cevent, 1, 0);
-
+ chan->addr = nv_device_resource_start(device, bar) +
+ addr + size * chan->chid;
chan->size = size;
+ nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
return 0;
}
@@ -103,7 +117,8 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan)
struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
unsigned long flags;
- iounmap(chan->user);
+ if (chan->user)
+ iounmap(chan->user);
spin_lock_irqsave(&priv->lock, flags);
priv->channel[chan->chid] = NULL;
@@ -121,10 +136,24 @@ _nouveau_fifo_channel_dtor(struct nouveau_object *object)
nouveau_fifo_channel_destroy(chan);
}
+int
+_nouveau_fifo_channel_map(struct nouveau_object *object, u64 *addr, u32 *size)
+{
+ struct nouveau_fifo_chan *chan = (void *)object;
+ *addr = chan->addr;
+ *size = chan->size;
+ return 0;
+}
+
u32
_nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr)
{
struct nouveau_fifo_chan *chan = (void *)object;
+ if (unlikely(!chan->user)) {
+ chan->user = ioremap(chan->addr, chan->size);
+ if (WARN_ON_ONCE(chan->user == NULL))
+ return 0;
+ }
return ioread32_native(chan->user + addr);
}
@@ -132,9 +161,57 @@ void
_nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data)
{
struct nouveau_fifo_chan *chan = (void *)object;
+ if (unlikely(!chan->user)) {
+ chan->user = ioremap(chan->addr, chan->size);
+ if (WARN_ON_ONCE(chan->user == NULL))
+ return;
+ }
iowrite32_native(data, chan->user + addr);
}
+int
+nouveau_fifo_uevent_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ union {
+ struct nvif_notify_uevent_req none;
+ } *req = data;
+ int ret;
+
+ if (nvif_unvers(req->none)) {
+ notify->size = sizeof(struct nvif_notify_uevent_rep);
+ notify->types = 1;
+ notify->index = 0;
+ }
+
+ return ret;
+}
+
+void
+nouveau_fifo_uevent(struct nouveau_fifo *fifo)
+{
+ struct nvif_notify_uevent_rep rep = {
+ };
+ nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
+}
+
+int
+_nouveau_fifo_channel_ntfy(struct nouveau_object *object, u32 type,
+ struct nvkm_event **event)
+{
+ struct nouveau_fifo *fifo = (void *)object->engine;
+ switch (type) {
+ case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
+ if (nv_mclass(object) >= G82_CHANNEL_DMA) {
+ *event = &fifo->uevent;
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
static int
nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object)
{
@@ -168,8 +245,8 @@ void
nouveau_fifo_destroy(struct nouveau_fifo *priv)
{
kfree(priv->channel);
- nouveau_event_destroy(&priv->uevent);
- nouveau_event_destroy(&priv->cevent);
+ nvkm_event_fini(&priv->uevent);
+ nvkm_event_fini(&priv->cevent);
nouveau_engine_destroy(&priv->base);
}
@@ -194,11 +271,7 @@ nouveau_fifo_create_(struct nouveau_object *parent,
if (!priv->channel)
return -ENOMEM;
- ret = nouveau_event_create(1, 1, &priv->cevent);
- if (ret)
- return ret;
-
- ret = nouveau_event_create(1, 1, &priv->uevent);
+ ret = nvkm_event_init(&nouveau_fifo_event_func, 1, 1, &priv->cevent);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
index c61b16a63884..5ae6a43893b5 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/engctx.h>
#include <core/namedb.h>
#include <core/handle.h>
@@ -117,16 +118,23 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->pushbuf,
+ 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan);
@@ -134,13 +142,15 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
- nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
- nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x10,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -242,13 +252,15 @@ nv04_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv04_fifo_sclass[] = {
- { NV03_CHANNEL_DMA_CLASS, &nv04_fifo_ofuncs },
+ { NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
{}
};
@@ -539,7 +551,7 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
}
if (status & 0x40000000) {
- nouveau_event_trigger(priv->base.uevent, 1, 0);
+ nouveau_fifo_uevent(&priv->base);
nv_wr32(priv, 0x002100, 0x40000000);
status &= ~0x40000000;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c
index 571a22aa1ae5..2a32add51c81 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@@ -59,16 +60,23 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->pushbuf,
+ 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan);
@@ -76,13 +84,15 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
- nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
- nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -100,13 +110,15 @@ nv10_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv10_fifo_sclass[] = {
- { NV10_CHANNEL_DMA_CLASS, &nv10_fifo_ofuncs },
+ { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c
index f25760209316..12d76c8adb23 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@@ -64,16 +65,23 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
- 0x10000, args->pushbuf,
+ 0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -83,13 +91,15 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 64;
- nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
- nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -107,13 +117,15 @@ nv17_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv17_fifo_sclass[] = {
- { NV17_CHANNEL_DMA_CLASS, &nv17_fifo_ofuncs },
+ { NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c
index 343487ed2238..9f49c3a24dc6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c
@@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
-#include <core/class.h>
+#include <core/client.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@@ -182,16 +183,23 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x1000, args->pushbuf,
+ 0x1000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -200,14 +208,16 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->context_attach = nv40_fifo_context_attach;
nv_parent(chan)->context_detach = nv40_fifo_context_detach;
nv_parent(chan)->object_attach = nv40_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
chan->ramfc = chan->base.chid * 128;
- nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
- nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
+ nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 |
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@@ -226,13 +236,15 @@ nv40_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv40_fifo_sclass[] = {
- { NV40_CHANNEL_DMA_CLASS, &nv40_fifo_ofuncs },
+ { NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
index e6352bd5b4ff..5d1e86bc244c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
@@ -25,7 +25,8 @@
#include <core/client.h>
#include <core/engctx.h>
#include <core/ramht.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/timer.h>
#include <subdev/bar.h>
@@ -194,17 +195,24 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->pushbuf,
+ 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -213,6 +221,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@@ -223,10 +233,10 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
- nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
+ nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@@ -247,18 +257,26 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv50_channel_ind_class *args = data;
+ union {
+ struct nv50_channel_gpfifo_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+ "ioffset %016llx ilength %08x\n",
+ args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+ args->v0.ilength);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->pushbuf,
+ 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -267,6 +285,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@@ -277,8 +297,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
- ioffset = args->ioffset;
- ilength = order_base_2(args->ilength / 8);
+ ioffset = args->v0.ioffset;
+ ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
@@ -343,8 +363,10 @@ nv50_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_ofuncs
@@ -353,14 +375,16 @@ nv50_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv50_fifo_sclass[] = {
- { NV50_CHANNEL_DMA_CLASS, &nv50_fifo_ofuncs_dma },
- { NV50_CHANNEL_IND_CLASS, &nv50_fifo_ofuncs_ind },
+ { NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
+ { NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
index 6e5ac16e5460..1f42996b354a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
@@ -27,7 +27,8 @@
#include <core/engctx.h>
#include <core/ramht.h>
#include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <subdev/timer.h>
#include <subdev/bar.h>
@@ -160,17 +161,24 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv03_channel_dma_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
- struct nv03_channel_dma_class *args = data;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel dma size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
+ "offset %016llx\n", args->v0.version,
+ args->v0.pushbuf, args->v0.offset);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->pushbuf,
+ 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -186,6 +194,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht);
if (ret)
@@ -196,10 +206,10 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach;
- nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
- nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
+ nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
+ nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@@ -222,18 +232,26 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv50_channel_gpfifo_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
- struct nv50_channel_ind_class *args = data;
u64 ioffset, ilength;
int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+ "ioffset %016llx ilength %08x\n",
+ args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+ args->v0.ilength);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
- 0x2000, args->pushbuf,
+ 0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@@ -249,6 +267,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht);
if (ret)
@@ -259,8 +279,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach;
- ioffset = args->ioffset;
- ilength = order_base_2(args->ilength / 8);
+ ioffset = args->v0.ioffset;
+ ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
@@ -304,8 +324,10 @@ nv84_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_ofuncs
@@ -314,14 +336,16 @@ nv84_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv84_fifo_sclass[] = {
- { NV84_CHANNEL_DMA_CLASS, &nv84_fifo_ofuncs_dma },
- { NV84_CHANNEL_IND_CLASS, &nv84_fifo_ofuncs_ind },
+ { G82_CHANNEL_DMA, &nv84_fifo_ofuncs_dma },
+ { G82_CHANNEL_GPFIFO, &nv84_fifo_ofuncs_ind },
{}
};
@@ -389,19 +413,26 @@ nv84_fifo_cclass = {
******************************************************************************/
static void
-nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nv84_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
- struct nv84_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x40000000, 0x40000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x40000000, 0x40000000);
}
static void
-nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nv84_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
- struct nv84_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x40000000, 0x00000000);
}
+static const struct nvkm_event_func
+nv84_fifo_uevent_func = {
+ .ctor = nouveau_fifo_uevent_ctor,
+ .init = nv84_fifo_uevent_init,
+ .fini = nv84_fifo_uevent_fini,
+};
+
static int
nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -425,9 +456,9 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- priv->base.uevent->enable = nv84_fifo_uevent_enable;
- priv->base.uevent->disable = nv84_fifo_uevent_disable;
- priv->base.uevent->priv = priv;
+ ret = nvkm_event_init(&nv84_fifo_uevent_func, 1, 1, &priv->base.uevent);
+ if (ret)
+ return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nv04_fifo_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
index ae4a4dc5642a..1fe1f8fbda0c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
@@ -28,7 +28,8 @@
#include <core/gpuobj.h>
#include <core/engctx.h>
#include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/enum.h>
#include <subdev/timer.h>
@@ -187,20 +188,28 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nv50_channel_gpfifo_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nvc0_fifo_priv *priv = (void *)engine;
struct nvc0_fifo_base *base = (void *)parent;
struct nvc0_fifo_chan *chan;
- struct nv50_channel_ind_class *args = data;
u64 usermem, ioffset, ilength;
int ret, i;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+ "ioffset %016llx ilength %08x\n",
+ args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+ args->v0.ilength);
+ } else
+ return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x1000,
- args->pushbuf,
+ args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
(1ULL << NVDEV_ENGINE_COPY0) |
@@ -212,12 +221,14 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->context_attach = nvc0_fifo_context_attach;
nv_parent(chan)->context_detach = nvc0_fifo_context_detach;
usermem = chan->base.chid * 0x1000;
- ioffset = args->ioffset;
- ilength = order_base_2(args->ilength / 8);
+ ioffset = args->v0.ioffset;
+ ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x1000; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@@ -291,13 +302,15 @@ nvc0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor,
.init = nvc0_fifo_chan_init,
.fini = nvc0_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nvc0_fifo_sclass[] = {
- { NVC0_CHANNEL_IND_CLASS, &nvc0_fifo_ofuncs },
+ { FERMI_CHANNEL_GPFIFO, &nvc0_fifo_ofuncs },
{}
};
@@ -654,7 +667,7 @@ nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)
object = engctx;
while (object) {
switch (nv_mclass(object)) {
- case NVC0_CHANNEL_IND_CLASS:
+ case FERMI_CHANNEL_GPFIFO:
nvc0_fifo_recover(priv, engine, (void *)object);
break;
}
@@ -730,7 +743,7 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
for (unkn = 0; unkn < 8; unkn++) {
u32 ints = (intr >> (unkn * 0x04)) & inte;
if (ints & 0x1) {
- nouveau_event_trigger(priv->base.uevent, 1, 0);
+ nouveau_fifo_uevent(&priv->base);
ints &= ~1;
}
if (ints) {
@@ -827,19 +840,26 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
}
static void
-nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nvc0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
- struct nvc0_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
}
static void
-nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nvc0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
- struct nvc0_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
}
+static const struct nvkm_event_func
+nvc0_fifo_uevent_func = {
+ .ctor = nouveau_fifo_uevent_ctor,
+ .init = nvc0_fifo_uevent_init,
+ .fini = nvc0_fifo_uevent_fini,
+};
+
static int
nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -877,9 +897,9 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- priv->base.uevent->enable = nvc0_fifo_uevent_enable;
- priv->base.uevent->disable = nvc0_fifo_uevent_disable;
- priv->base.uevent->priv = priv;
+ ret = nvkm_event_init(&nvc0_fifo_uevent_func, 1, 1, &priv->base.uevent);
+ if (ret)
+ return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nvc0_fifo_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
index 298063edb92d..d2f0fd39c145 100644
--- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
@@ -28,7 +28,8 @@
#include <core/gpuobj.h>
#include <core/engctx.h>
#include <core/event.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
#include <core/enum.h>
#include <subdev/timer.h>
@@ -216,46 +217,56 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct kepler_channel_gpfifo_a_v0 v0;
+ } *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nve0_fifo_priv *priv = (void *)engine;
struct nve0_fifo_base *base = (void *)parent;
struct nve0_fifo_chan *chan;
- struct nve0_channel_ind_class *args = data;
u64 usermem, ioffset, ilength;
int ret, i;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create channel gpfifo size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
+ "ioffset %016llx ilength %08x engine %08x\n",
+ args->v0.version, args->v0.pushbuf, args->v0.ioffset,
+ args->v0.ilength, args->v0.engine);
+ } else
+ return ret;
for (i = 0; i < FIFO_ENGINE_NR; i++) {
- if (args->engine & (1 << i)) {
+ if (args->v0.engine & (1 << i)) {
if (nouveau_engine(parent, fifo_engine[i].subdev)) {
- args->engine = (1 << i);
+ args->v0.engine = (1 << i);
break;
}
}
}
if (i == FIFO_ENGINE_NR) {
- nv_error(priv, "unsupported engines 0x%08x\n", args->engine);
+ nv_error(priv, "unsupported engines 0x%08x\n", args->v0.engine);
return -ENODEV;
}
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x200,
- args->pushbuf,
+ args->v0.pushbuf,
fifo_engine[i].mask, &chan);
*pobject = nv_object(chan);
if (ret)
return ret;
+ args->v0.chid = chan->base.chid;
+
nv_parent(chan)->context_attach = nve0_fifo_context_attach;
nv_parent(chan)->context_detach = nve0_fifo_context_detach;
chan->engine = i;
usermem = chan->base.chid * 0x200;
- ioffset = args->ioffset;
- ilength = order_base_2(args->ilength / 8);
+ ioffset = args->v0.ioffset;
+ ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x200; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@@ -325,13 +336,15 @@ nve0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor,
.init = nve0_fifo_chan_init,
.fini = nve0_fifo_chan_fini,
+ .map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
+ .ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nve0_fifo_sclass[] = {
- { NVE0_CHANNEL_IND_CLASS, &nve0_fifo_ofuncs },
+ { KEPLER_CHANNEL_GPFIFO_A, &nve0_fifo_ofuncs },
{}
};
@@ -769,7 +782,7 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
object = engctx;
while (object) {
switch (nv_mclass(object)) {
- case NVE0_CHANNEL_IND_CLASS:
+ case KEPLER_CHANNEL_GPFIFO_A:
nve0_fifo_recover(priv, engine, (void *)object);
break;
}
@@ -859,7 +872,7 @@ nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv)
static void
nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
{
- nouveau_event_trigger(priv->base.uevent, 1, 0);
+ nouveau_fifo_uevent(&priv->base);
}
static void
@@ -952,19 +965,26 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
}
static void
-nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
+nve0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
- struct nve0_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
}
static void
-nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
+nve0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
- struct nve0_fifo_priv *priv = event->priv;
- nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+ struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
+ nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
}
+static const struct nvkm_event_func
+nve0_fifo_uevent_func = {
+ .ctor = nouveau_fifo_uevent_ctor,
+ .init = nve0_fifo_uevent_init,
+ .fini = nve0_fifo_uevent_fini,
+};
+
int
nve0_fifo_fini(struct nouveau_object *object, bool suspend)
{
@@ -1067,9 +1087,9 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
- priv->base.uevent->enable = nve0_fifo_uevent_enable;
- priv->base.uevent->disable = nve0_fifo_uevent_disable;
- priv->base.uevent->priv = priv;
+ ret = nvkm_event_init(&nve0_fifo_uevent_func, 1, 1, &priv->base.uevent);
+ if (ret)
+ return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nve0_fifo_intr;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
new file mode 100644
index 000000000000..3adb7fe91772
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH context register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gk110b_grctx_init_sm_0[] = {
+ { 0x419e04, 1, 0x04, 0x00000000 },
+ { 0x419e08, 1, 0x04, 0x0000001d },
+ { 0x419e0c, 1, 0x04, 0x00000000 },
+ { 0x419e10, 1, 0x04, 0x00001c02 },
+ { 0x419e44, 1, 0x04, 0x0013eff2 },
+ { 0x419e48, 1, 0x04, 0x00000000 },
+ { 0x419e4c, 1, 0x04, 0x0000007f },
+ { 0x419e50, 2, 0x04, 0x00000000 },
+ { 0x419e58, 1, 0x04, 0x00000001 },
+ { 0x419e5c, 3, 0x04, 0x00000000 },
+ { 0x419e68, 1, 0x04, 0x00000002 },
+ { 0x419e6c, 12, 0x04, 0x00000000 },
+ { 0x419eac, 1, 0x04, 0x00001f8f },
+ { 0x419eb0, 1, 0x04, 0x0db00d2f },
+ { 0x419eb8, 1, 0x04, 0x00000000 },
+ { 0x419ec8, 1, 0x04, 0x0001304f },
+ { 0x419f30, 4, 0x04, 0x00000000 },
+ { 0x419f40, 1, 0x04, 0x00000018 },
+ { 0x419f44, 3, 0x04, 0x00000000 },
+ { 0x419f58, 1, 0x04, 0x00000000 },
+ { 0x419f70, 1, 0x04, 0x00006300 },
+ { 0x419f78, 1, 0x04, 0x000000eb },
+ { 0x419f7c, 1, 0x04, 0x00000404 },
+ {}
+};
+
+static const struct nvc0_graph_pack
+gk110b_grctx_pack_tpc[] = {
+ { nvd7_grctx_init_pe_0 },
+ { nvf0_grctx_init_tex_0 },
+ { nvf0_grctx_init_mpc_0 },
+ { nvf0_grctx_init_l1c_0 },
+ { gk110b_grctx_init_sm_0 },
+ {}
+};
+
+/*******************************************************************************
+ * PGRAPH context implementation
+ ******************************************************************************/
+
+struct nouveau_oclass *
+gk110b_grctx_oclass = &(struct nvc0_grctx_oclass) {
+ .base.handle = NV_ENGCTX(GR, 0xf1),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nvc0_graph_context_ctor,
+ .dtor = nvc0_graph_context_dtor,
+ .init = _nouveau_graph_context_init,
+ .fini = _nouveau_graph_context_fini,
+ .rd32 = _nouveau_graph_context_rd32,
+ .wr32 = _nouveau_graph_context_wr32,
+ },
+ .main = nve4_grctx_generate_main,
+ .unkn = nve4_grctx_generate_unkn,
+ .hub = nvf0_grctx_pack_hub,
+ .gpc = nvf0_grctx_pack_gpc,
+ .zcull = nvc0_grctx_pack_zcull,
+ .tpc = gk110b_grctx_pack_tpc,
+ .ppc = nvf0_grctx_pack_ppc,
+ .icmd = nvf0_grctx_pack_icmd,
+ .mthd = nvf0_grctx_pack_mthd,
+ .bundle = nve4_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0x180,
+ .bundle_token_limit = 0x600,
+ .pagepool = nve4_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x7ff,
+ .alpha_nr = 0x648,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
index 224ee0287ab7..36fc9831cc93 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
@@ -41,7 +41,6 @@ gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
- .mods = nve4_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nve4_grctx_pack_hub,
.gpc = nve4_grctx_pack_gpc,
@@ -50,4 +49,15 @@ gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nve4_grctx_pack_ppc,
.icmd = nve4_grctx_pack_icmd,
.mthd = gk20a_grctx_pack_mthd,
+ .bundle = nve4_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .bundle_min_gpm_fifo_depth = 0x62,
+ .bundle_token_limit = 0x100,
+ .pagepool = nve4_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x240,
+ .attrib_nr = 0x240,
+ .alpha_nr_max = 0x648 + (0x648 / 2),
+ .alpha_nr = 0x648,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
index b0d0fb2f4d08..62e918b9fa81 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
@@ -859,45 +859,74 @@ gm107_grctx_pack_ppc[] = {
******************************************************************************/
static void
-gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+gm107_grctx_generate_bundle(struct nvc0_grctx *info)
{
- mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW);
-
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x4064cc, 0x80000000, 0, 0);
- mmio_list(0x418e30, 0x80000000, 0, 0);
-
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000030, 0, 0);
- mmio_list(0x418e24, 0x00000000, 8, 0);
- mmio_list(0x418e28, 0x80000030, 0, 0);
-
- mmio_list(0x4064c8, 0x018002c0, 0, 0);
-
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
- mmio_list(0x419c2c, 0x10000000, 12, 2);
-
- mmio_list(0x405830, 0x0aa01000, 0, 0);
- mmio_list(0x4064c4, 0x0400ffff, 0, 0);
-
- /*XXX*/
- mmio_list(0x5030c0, 0x00001540, 0, 0);
- mmio_list(0x5030f4, 0x00000000, 0, 0);
- mmio_list(0x5030e4, 0x00002000, 0, 0);
- mmio_list(0x5030f8, 0x00003fc0, 0, 0);
- mmio_list(0x418ea0, 0x07151540, 0, 0);
-
- mmio_list(0x5032c0, 0x00001540, 0, 0);
- mmio_list(0x5032f4, 0x00001fe0, 0, 0);
- mmio_list(0x5032e4, 0x00002000, 0, 0);
- mmio_list(0x5032f8, 0x00006fc0, 0, 0);
- mmio_list(0x418ea4, 0x07151540, 0, 0);
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
+ impl->bundle_size / 0x20);
+ const u32 token_limit = impl->bundle_token_limit;
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+ mmio_refn(info, 0x408004, 0x00000000, s, b);
+ mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+ mmio_refn(info, 0x418e24, 0x00000000, s, b);
+ mmio_refn(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s), 0, b);
+ mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+}
+
+static void
+gm107_grctx_generate_pagepool(struct nvc0_grctx *info)
+{
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+ mmio_refn(info, 0x40800c, 0x00000000, s, b);
+ mmio_wr32(info, 0x408010, 0x80000000);
+ mmio_refn(info, 0x419004, 0x00000000, s, b);
+ mmio_wr32(info, 0x419008, 0x00000000);
+ mmio_wr32(info, 0x4064cc, 0x80000000);
+ mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */
+}
+
+static void
+gm107_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+ struct nvc0_graph_priv *priv = info->priv;
+ const struct nvc0_grctx_oclass *impl = (void *)nvc0_grctx_impl(priv);
+ const u32 alpha = impl->alpha_nr;
+ const u32 attrib = impl->attrib_nr;
+ const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+ const u32 access = NV_MEM_ACCESS_RW;
+ const int s = 12;
+ const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+ const int max_batches = 0xffff;
+ u32 bo = 0;
+ u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+ int gpc, ppc, n = 0;
+
+ mmio_refn(info, 0x418810, 0x80000000, s, b);
+ mmio_refn(info, 0x419848, 0x10000000, s, b);
+ mmio_refn(info, 0x419c2c, 0x10000000, s, b);
+ mmio_wr32(info, 0x405830, (attrib << 16) | alpha);
+ mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+
+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+ for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++, n++) {
+ const u32 as = alpha * priv->ppc_tpc_nr[gpc][ppc];
+ const u32 bs = attrib * priv->ppc_tpc_nr[gpc][ppc];
+ const u32 u = 0x418ea0 + (n * 0x04);
+ const u32 o = PPC_UNIT(gpc, ppc, 0);
+ mmio_wr32(info, o + 0xc0, bs);
+ mmio_wr32(info, o + 0xf4, bo);
+ bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+ mmio_wr32(info, o + 0xe4, as);
+ mmio_wr32(info, o + 0xf8, ao);
+ ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+ mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs);
+ }
+ }
}
static void
@@ -934,7 +963,9 @@ gm107_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
- oclass->mods(priv, info);
+ oclass->bundle(info);
+ oclass->pagepool(info);
+ oclass->attrib(info);
oclass->unkn(priv);
gm107_grctx_generate_tpcid(priv);
@@ -979,7 +1010,6 @@ gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = gm107_grctx_generate_main,
- .mods = gm107_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = gm107_grctx_pack_hub,
.gpc = gm107_grctx_pack_gpc,
@@ -988,4 +1018,15 @@ gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = gm107_grctx_pack_ppc,
.icmd = gm107_grctx_pack_icmd,
.mthd = gm107_grctx_pack_mthd,
+ .bundle = gm107_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0x180,
+ .bundle_token_limit = 0x2c0,
+ .pagepool = gm107_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = gm107_grctx_generate_attrib,
+ .attrib_nr_max = 0xff0,
+ .attrib_nr = 0xaa0,
+ .alpha_nr_max = 0x1800,
+ .alpha_nr = 0x1000,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
index 8de4a4291548..ce252adbef81 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
@@ -531,50 +531,6 @@ nv108_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
-static void
-nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
-{
- u32 magic[GPC_MAX][2];
- u32 offset;
- int gpc;
-
- mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x4064cc, 0x80000000, 0, 0);
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000030, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000030, 0, 0);
- mmio_list(0x4064c8, 0x00c20200, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
-
- mmio_list(0x405830, 0x02180648, 0, 0);
- mmio_list(0x4064c4, 0x0192ffff, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
- u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
- u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
- magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
- magic[gpc][1] = 0x00000000 | (magic1 << 16);
- offset += 0x0324 * priv->tpc_nr[gpc];
- }
-
- for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
- mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
- mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
- offset += 0x07ff * priv->tpc_nr[gpc];
- }
-
- mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
- mmio_list(0x17e920, 0x00090d08, 0, 0);
-}
-
struct nouveau_oclass *
nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0x08),
@@ -587,7 +543,6 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
- .mods = nv108_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nv108_grctx_pack_hub,
.gpc = nv108_grctx_pack_gpc,
@@ -596,4 +551,15 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nv108_grctx_pack_ppc,
.icmd = nv108_grctx_pack_icmd,
.mthd = nvf0_grctx_pack_mthd,
+ .bundle = nve4_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0xc2,
+ .bundle_token_limit = 0x200,
+ .pagepool = nve4_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x7ff,
+ .alpha_nr = 0x648,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
index 833a96508c4e..b8e5fe60a1eb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
@@ -982,34 +982,93 @@ nvc0_grctx_pack_tpc[] = {
* PGRAPH context implementation
******************************************************************************/
+int
+nvc0_grctx_mmio_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access)
+{
+ if (info->data) {
+ info->buffer[info->buffer_nr] = round_up(info->addr, align);
+ info->addr = info->buffer[info->buffer_nr] + size;
+ info->data->size = size;
+ info->data->align = align;
+ info->data->access = access;
+ info->data++;
+ return info->buffer_nr++;
+ }
+ return -1;
+}
+
+void
+nvc0_grctx_mmio_item(struct nvc0_grctx *info, u32 addr, u32 data,
+ int shift, int buffer)
+{
+ if (info->data) {
+ if (shift >= 0) {
+ info->mmio->addr = addr;
+ info->mmio->data = data;
+ info->mmio->shift = shift;
+ info->mmio->buffer = buffer;
+ if (buffer >= 0)
+ data |= info->buffer[buffer] >> shift;
+ info->mmio++;
+ } else
+ return;
+ } else {
+ if (buffer >= 0)
+ return;
+ }
+
+ nv_wr32(info->priv, addr, data);
+}
+
+void
+nvc0_grctx_generate_bundle(struct nvc0_grctx *info)
+{
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+ mmio_refn(info, 0x408004, 0x00000000, s, b);
+ mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+ mmio_refn(info, 0x418808, 0x00000000, s, b);
+ mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+}
+
void
-nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc0_grctx_generate_pagepool(struct nvc0_grctx *info)
{
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+ mmio_refn(info, 0x40800c, 0x00000000, s, b);
+ mmio_wr32(info, 0x408010, 0x80000000);
+ mmio_refn(info, 0x419004, 0x00000000, s, b);
+ mmio_wr32(info, 0x419008, 0x00000000);
+}
+
+void
+nvc0_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+ struct nvc0_graph_priv *priv = info->priv;
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+ const u32 attrib = impl->attrib_nr;
+ const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+ const u32 access = NV_MEM_ACCESS_RW;
+ const int s = 12;
+ const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
int gpc, tpc;
- u32 offset;
-
- mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000018, 0, 0);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000018, 0, 0);
-
- mmio_list(0x405830, 0x02180000, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+ u32 bo = 0;
+
+ mmio_refn(info, 0x418810, 0x80000000, s, b);
+ mmio_refn(info, 0x419848, 0x10000000, s, b);
+ mmio_wr32(info, 0x405830, (attrib << 16));
+
+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
- u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
- mmio_list(addr, 0x02180000 | offset, 0, 0);
- offset += 0x0324;
+ const u32 o = TPC_UNIT(gpc, tpc, 0x0520);
+ mmio_skip(info, o, (attrib << 16) | ++bo);
+ mmio_wr32(info, o, (attrib << 16) | --bo);
+ bo += impl->attrib_nr_max;
}
}
}
@@ -1170,7 +1229,7 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
{
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
- nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@@ -1180,7 +1239,9 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
- oclass->mods(priv, info);
+ oclass->bundle(info);
+ oclass->pagepool(info);
+ oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@@ -1192,7 +1253,7 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
- nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
}
int
@@ -1308,7 +1369,6 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
- .mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc0_grctx_pack_gpc,
@@ -1316,4 +1376,11 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc0_grctx_pack_tpc,
.icmd = nvc0_grctx_pack_icmd,
.mthd = nvc0_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvc0_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
index 8da8b627b9d0..c776cd715e33 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
@@ -12,12 +12,19 @@ struct nvc0_grctx {
u64 addr;
};
+int nvc0_grctx_mmio_data(struct nvc0_grctx *, u32 size, u32 align, u32 access);
+void nvc0_grctx_mmio_item(struct nvc0_grctx *, u32 addr, u32 data, int s, int);
+
+#define mmio_vram(a,b,c,d) nvc0_grctx_mmio_data((a), (b), (c), (d))
+#define mmio_refn(a,b,c,d,e) nvc0_grctx_mmio_item((a), (b), (c), (d), (e))
+#define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1)
+#define mmio_wr32(a,b,c) mmio_refn((a), (b), (c), 0, -1)
+
struct nvc0_grctx_oclass {
struct nouveau_oclass base;
/* main context generation function */
void (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
/* context-specific modify-on-first-load list generation function */
- void (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
void (*unkn)(struct nvc0_graph_priv *);
/* mmio context data */
const struct nvc0_graph_pack *hub;
@@ -28,30 +35,34 @@ struct nvc0_grctx_oclass {
/* indirect context data, generated with icmds/mthds */
const struct nvc0_graph_pack *icmd;
const struct nvc0_graph_pack *mthd;
+ /* bundle circular buffer */
+ void (*bundle)(struct nvc0_grctx *);
+ u32 bundle_size;
+ u32 bundle_min_gpm_fifo_depth;
+ u32 bundle_token_limit;
+ /* pagepool */
+ void (*pagepool)(struct nvc0_grctx *);
+ u32 pagepool_size;
+ /* attribute(/alpha) circular buffer */
+ void (*attrib)(struct nvc0_grctx *);
+ u32 attrib_nr_max;
+ u32 attrib_nr;
+ u32 alpha_nr_max;
+ u32 alpha_nr;
};
-#define mmio_data(s,a,p) do { \
- info->buffer[info->buffer_nr] = round_up(info->addr, (a)); \
- info->addr = info->buffer[info->buffer_nr++] + (s); \
- info->data->size = (s); \
- info->data->align = (a); \
- info->data->access = (p); \
- info->data++; \
-} while(0)
-
-#define mmio_list(r,d,s,b) do { \
- info->mmio->addr = (r); \
- info->mmio->data = (d); \
- info->mmio->shift = (s); \
- info->mmio->buffer = (b); \
- info->mmio++; \
- nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0)); \
-} while(0)
+static inline const struct nvc0_grctx_oclass *
+nvc0_grctx_impl(struct nvc0_graph_priv *priv)
+{
+ return (void *)nv_engine(priv)->cclass;
+}
extern struct nouveau_oclass *nvc0_grctx_oclass;
int nvc0_grctx_generate(struct nvc0_graph_priv *);
void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc0_grctx_generate_bundle(struct nvc0_grctx *);
+void nvc0_grctx_generate_pagepool(struct nvc0_grctx *);
+void nvc0_grctx_generate_attrib(struct nvc0_grctx *);
void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
@@ -60,22 +71,27 @@ void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *);
void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvc1_grctx_oclass;
-void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nvc1_grctx_generate_attrib(struct nvc0_grctx *);
void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvc4_grctx_oclass;
extern struct nouveau_oclass *nvc8_grctx_oclass;
+
extern struct nouveau_oclass *nvd7_grctx_oclass;
+void nvd7_grctx_generate_attrib(struct nvc0_grctx *);
+
extern struct nouveau_oclass *nvd9_grctx_oclass;
extern struct nouveau_oclass *nve4_grctx_oclass;
extern struct nouveau_oclass *gk20a_grctx_oclass;
void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
-void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nve4_grctx_generate_bundle(struct nvc0_grctx *);
+void nve4_grctx_generate_pagepool(struct nvc0_grctx *);
void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nouveau_oclass *gk110b_grctx_oclass;
extern struct nouveau_oclass *nv108_grctx_oclass;
extern struct nouveau_oclass *gm107_grctx_oclass;
@@ -160,16 +176,23 @@ extern const struct nvc0_graph_pack nve4_grctx_pack_ppc[];
extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[];
extern const struct nvc0_graph_init nve4_grctx_init_a097_0[];
+extern const struct nvc0_graph_pack nvf0_grctx_pack_icmd[];
+
extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
+extern const struct nvc0_graph_pack nvf0_grctx_pack_hub[];
extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[];
+extern const struct nvc0_graph_pack nvf0_grctx_pack_gpc[];
extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[];
+extern const struct nvc0_graph_init nvf0_grctx_init_tex_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[];
+extern const struct nvc0_graph_pack nvf0_grctx_pack_ppc[];
+
extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[];
extern const struct nvc0_graph_init nv108_grctx_init_prop_0[];
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
index 24a92c569c0a..c6ba8fed18f1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
@@ -727,38 +727,38 @@ nvc1_grctx_pack_tpc[] = {
******************************************************************************/
void
-nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc1_grctx_generate_attrib(struct nvc0_grctx *info)
{
+ struct nvc0_graph_priv *priv = info->priv;
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+ const u32 alpha = impl->alpha_nr;
+ const u32 beta = impl->attrib_nr;
+ const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+ const u32 access = NV_MEM_ACCESS_RW;
+ const int s = 12;
+ const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+ const int timeslice_mode = 1;
+ const int max_batches = 0xffff;
+ u32 bo = 0;
+ u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
int gpc, tpc;
- u32 offset;
- mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000018, 0, 0);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000018, 0, 0);
+ mmio_refn(info, 0x418810, 0x80000000, s, b);
+ mmio_refn(info, 0x419848, 0x10000000, s, b);
+ mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+ mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
- mmio_list(0x405830, 0x02180218, 0, 0);
- mmio_list(0x4064c4, 0x0086ffff, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
- for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
- u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
- mmio_list(addr, 0x12180000 | offset, 0, 0);
- offset += 0x0324;
- }
+ for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
- u32 addr = TPC_UNIT(gpc, tpc, 0x0544);
- mmio_list(addr, 0x02180000 | offset, 0, 0);
- offset += 0x0324;
+ const u32 a = alpha;
+ const u32 b = beta;
+ const u32 t = timeslice_mode;
+ const u32 o = TPC_UNIT(gpc, tpc, 0x500);
+ mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo);
+ mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo);
+ bo += impl->attrib_nr_max;
+ mmio_wr32(info, o + 0x44, (a << 16) | ao);
+ ao += impl->alpha_nr_max;
}
}
}
@@ -786,7 +786,6 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
- .mods = nvc1_grctx_generate_mods,
.unkn = nvc1_grctx_generate_unkn,
.hub = nvc1_grctx_pack_hub,
.gpc = nvc1_grctx_pack_gpc,
@@ -794,4 +793,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc1_grctx_pack_tpc,
.icmd = nvc1_grctx_pack_icmd,
.mthd = nvc1_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvc1_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x324,
+ .alpha_nr = 0x218,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
index e11ed5538193..41705c60cc47 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
@@ -92,7 +92,6 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
- .mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc0_grctx_pack_gpc,
@@ -100,4 +99,11 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc4_grctx_pack_tpc,
.icmd = nvc0_grctx_pack_icmd,
.mthd = nvc0_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvc0_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
index feebd58dfe8d..8f804cd8f9c7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
@@ -343,7 +343,6 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
- .mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc8_grctx_pack_gpc,
@@ -351,4 +350,11 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc0_grctx_pack_tpc,
.icmd = nvc8_grctx_pack_icmd,
.mthd = nvc8_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvc0_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
index 1dbc8d7f2e86..fcf534fd9e65 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
@@ -177,44 +177,41 @@ nvd7_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
-static void
-nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+void
+nvd7_grctx_generate_attrib(struct nvc0_grctx *info)
{
- u32 magic[GPC_MAX][2];
- u32 offset;
- int gpc;
-
- mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000018, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000018, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
+ struct nvc0_graph_priv *priv = info->priv;
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+ const u32 alpha = impl->alpha_nr;
+ const u32 beta = impl->attrib_nr;
+ const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+ const u32 access = NV_MEM_ACCESS_RW;
+ const int s = 12;
+ const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+ const int timeslice_mode = 1;
+ const int max_batches = 0xffff;
+ u32 bo = 0;
+ u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+ int gpc, ppc;
- mmio_list(0x405830, 0x02180324, 0, 0);
- mmio_list(0x4064c4, 0x00c9ffff, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
- u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
- u16 magic1 = 0x0324 * priv->tpc_nr[gpc];
- magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
- magic[gpc][1] = 0x00000000 | (magic1 << 16);
- offset += 0x0324 * priv->tpc_nr[gpc];
- }
+ mmio_refn(info, 0x418810, 0x80000000, s, b);
+ mmio_refn(info, 0x419848, 0x10000000, s, b);
+ mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+ mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
- mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
- mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
- offset += 0x07ff * priv->tpc_nr[gpc];
+ for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) {
+ const u32 a = alpha * priv->ppc_tpc_nr[gpc][ppc];
+ const u32 b = beta * priv->ppc_tpc_nr[gpc][ppc];
+ const u32 t = timeslice_mode;
+ const u32 o = PPC_UNIT(gpc, ppc, 0);
+ mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo);
+ mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo);
+ bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+ mmio_wr32(info, o + 0xe4, (a << 16) | ao);
+ ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+ }
}
- mmio_list(0x17e91c, 0x03060609, 0, 0); /* different from kepler */
}
void
@@ -223,7 +220,7 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
int i;
- nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@@ -233,7 +230,9 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
- oclass->mods(priv, info);
+ oclass->bundle(info);
+ oclass->pagepool(info);
+ oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@@ -248,7 +247,7 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
- nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
}
struct nouveau_oclass *
@@ -263,7 +262,6 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvd7_grctx_generate_main,
- .mods = nvd7_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nvd7_grctx_pack_hub,
.gpc = nvd7_grctx_pack_gpc,
@@ -272,4 +270,13 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nvd7_grctx_pack_ppc,
.icmd = nvd9_grctx_pack_icmd,
.mthd = nvd9_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x7ff,
+ .alpha_nr = 0x324,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
index c665fb7e4660..b9a301b6fd9f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
@@ -511,7 +511,6 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
- .mods = nvc1_grctx_generate_mods,
.unkn = nvc1_grctx_generate_unkn,
.hub = nvd9_grctx_pack_hub,
.gpc = nvd9_grctx_pack_gpc,
@@ -519,4 +518,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvd9_grctx_pack_tpc,
.icmd = nvd9_grctx_pack_icmd,
.mthd = nvd9_grctx_pack_mthd,
+ .bundle = nvc0_grctx_generate_bundle,
+ .bundle_size = 0x1800,
+ .pagepool = nvc0_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvc1_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x324,
+ .alpha_nr = 0x218,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
index c5b249238587..ccac2ee1a1cb 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
@@ -839,47 +839,34 @@ nve4_grctx_pack_ppc[] = {
******************************************************************************/
void
-nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nve4_grctx_generate_bundle(struct nvc0_grctx *info)
{
- u32 magic[GPC_MAX][2];
- u32 offset;
- int gpc;
-
- mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x4064cc, 0x80000000, 0, 0);
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000030, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000030, 0, 0);
- mmio_list(0x4064c8, 0x01800600, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
-
- mmio_list(0x405830, 0x02180648, 0, 0);
- mmio_list(0x4064c4, 0x0192ffff, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
- u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
- u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
- magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
- magic[gpc][1] = 0x00000000 | (magic1 << 16);
- offset += 0x0324 * priv->tpc_nr[gpc];
- }
-
- for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
- mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
- mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
- offset += 0x07ff * priv->tpc_nr[gpc];
- }
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
+ impl->bundle_size / 0x20);
+ const u32 token_limit = impl->bundle_token_limit;
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
+ mmio_refn(info, 0x408004, 0x00000000, s, b);
+ mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
+ mmio_refn(info, 0x418808, 0x00000000, s, b);
+ mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
+ mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+}
- mmio_list(0x17e91c, 0x06060609, 0, 0);
- mmio_list(0x17e920, 0x00090a05, 0, 0);
+void
+nve4_grctx_generate_pagepool(struct nvc0_grctx *info)
+{
+ const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
+ const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
+ const int s = 8;
+ const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
+ mmio_refn(info, 0x40800c, 0x00000000, s, b);
+ mmio_wr32(info, 0x408010, 0x80000000);
+ mmio_refn(info, 0x419004, 0x00000000, s, b);
+ mmio_wr32(info, 0x419008, 0x00000000);
+ mmio_wr32(info, 0x4064cc, 0x80000000);
}
void
@@ -957,7 +944,7 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
int i;
- nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@@ -967,7 +954,9 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
- oclass->mods(priv, info);
+ oclass->bundle(info);
+ oclass->pagepool(info);
+ oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@@ -991,7 +980,7 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
- nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
nv_mask(priv, 0x418800, 0x00200000, 0x00200000);
nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);
@@ -1009,7 +998,6 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
- .mods = nve4_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nve4_grctx_pack_hub,
.gpc = nve4_grctx_pack_gpc,
@@ -1018,4 +1006,15 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nve4_grctx_pack_ppc,
.icmd = nve4_grctx_pack_icmd,
.mthd = nve4_grctx_pack_mthd,
+ .bundle = nve4_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0x180,
+ .bundle_token_limit = 0x600,
+ .pagepool = nve4_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x7ff,
+ .alpha_nr = 0x648,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
index dec03f04114d..e9b0dcf95a49 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
@@ -279,7 +279,7 @@ nvf0_grctx_init_icmd_0[] = {
{}
};
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
nvf0_grctx_pack_icmd[] = {
{ nvf0_grctx_init_icmd_0 },
{}
@@ -668,7 +668,7 @@ nvf0_grctx_init_be_0[] = {
{}
};
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
nvf0_grctx_pack_hub[] = {
{ nvc0_grctx_init_main_0 },
{ nvf0_grctx_init_fe_0 },
@@ -704,7 +704,7 @@ nvf0_grctx_init_gpc_unk_2[] = {
{}
};
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
nvf0_grctx_pack_gpc[] = {
{ nvc0_grctx_init_gpc_unk_0 },
{ nvd9_grctx_init_prop_0 },
@@ -718,7 +718,7 @@ nvf0_grctx_pack_gpc[] = {
{}
};
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
nvf0_grctx_init_tex_0[] = {
{ 0x419a00, 1, 0x04, 0x000000f0 },
{ 0x419a04, 1, 0x04, 0x00000001 },
@@ -797,7 +797,7 @@ nvf0_grctx_init_cbm_0[] = {
{}
};
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
nvf0_grctx_pack_ppc[] = {
{ nve4_grctx_init_pes_0 },
{ nvf0_grctx_init_cbm_0 },
@@ -809,58 +809,6 @@ nvf0_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
-static void
-nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
-{
- u32 magic[GPC_MAX][4];
- u32 offset;
- int gpc;
-
- mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
- mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
- mmio_list(0x40800c, 0x00000000, 8, 1);
- mmio_list(0x408010, 0x80000000, 0, 0);
- mmio_list(0x419004, 0x00000000, 8, 1);
- mmio_list(0x419008, 0x00000000, 0, 0);
- mmio_list(0x4064cc, 0x80000000, 0, 0);
- mmio_list(0x408004, 0x00000000, 8, 0);
- mmio_list(0x408008, 0x80000030, 0, 0);
- mmio_list(0x418808, 0x00000000, 8, 0);
- mmio_list(0x41880c, 0x80000030, 0, 0);
- mmio_list(0x4064c8, 0x01800600, 0, 0);
- mmio_list(0x418810, 0x80000000, 12, 2);
- mmio_list(0x419848, 0x10000000, 12, 2);
-
- mmio_list(0x405830, 0x02180648, 0, 0);
- mmio_list(0x4064c4, 0x0192ffff, 0, 0);
-
- for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
- u16 magic0 = 0x0218 * (priv->tpc_nr[gpc] - 1);
- u16 magic1 = 0x0648 * (priv->tpc_nr[gpc] - 1);
- u16 magic2 = 0x0218;
- u16 magic3 = 0x0648;
- magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
- magic[gpc][1] = 0x00000000 | (magic1 << 16);
- offset += 0x0324 * (priv->tpc_nr[gpc] - 1);
- magic[gpc][2] = 0x10000000 | (magic2 << 16) | offset;
- magic[gpc][3] = 0x00000000 | (magic3 << 16);
- offset += 0x0324;
- }
-
- for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
- mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
- mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
- offset += 0x07ff * (priv->tpc_nr[gpc] - 1);
- mmio_list(GPC_UNIT(gpc, 0x32c0), magic[gpc][2], 0, 0);
- mmio_list(GPC_UNIT(gpc, 0x32e4), magic[gpc][3] | offset, 0, 0);
- offset += 0x07ff;
- }
-
- mmio_list(0x17e91c, 0x06060609, 0, 0);
- mmio_list(0x17e920, 0x00090a05, 0, 0);
-}
-
struct nouveau_oclass *
nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0xf0),
@@ -873,7 +821,6 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
- .mods = nvf0_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nvf0_grctx_pack_hub,
.gpc = nvf0_grctx_pack_gpc,
@@ -882,4 +829,15 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nvf0_grctx_pack_ppc,
.icmd = nvf0_grctx_pack_icmd,
.mthd = nvf0_grctx_pack_mthd,
+ .bundle = nve4_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0x180,
+ .bundle_token_limit = 0x7c0,
+ .pagepool = nve4_grctx_generate_pagepool,
+ .pagepool_size = 0x8000,
+ .attrib = nvd7_grctx_generate_attrib,
+ .attrib_nr_max = 0x324,
+ .attrib_nr = 0x218,
+ .alpha_nr_max = 0x7ff,
+ .alpha_nr = 0x648,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c b/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c
new file mode 100644
index 000000000000..d07b19dc168d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+#include "ctxnvc0.h"
+
+/*******************************************************************************
+ * PGRAPH register lists
+ ******************************************************************************/
+
+static const struct nvc0_graph_init
+gk110b_graph_init_l1c_0[] = {
+ { 0x419c98, 1, 0x04, 0x00000000 },
+ { 0x419ca8, 1, 0x04, 0x00000000 },
+ { 0x419cb0, 1, 0x04, 0x09000000 },
+ { 0x419cb4, 1, 0x04, 0x00000000 },
+ { 0x419cb8, 1, 0x04, 0x00b08bea },
+ { 0x419c84, 1, 0x04, 0x00010384 },
+ { 0x419cbc, 1, 0x04, 0x281b3646 },
+ { 0x419cc0, 2, 0x04, 0x00000000 },
+ { 0x419c80, 1, 0x04, 0x00020230 },
+ { 0x419ccc, 2, 0x04, 0x00000000 },
+ {}
+};
+
+static const struct nvc0_graph_init
+gk110b_graph_init_sm_0[] = {
+ { 0x419e00, 1, 0x04, 0x00000080 },
+ { 0x419ea0, 1, 0x04, 0x00000000 },
+ { 0x419ee4, 1, 0x04, 0x00000000 },
+ { 0x419ea4, 1, 0x04, 0x00000100 },
+ { 0x419ea8, 1, 0x04, 0x00000000 },
+ { 0x419eb4, 1, 0x04, 0x00000000 },
+ { 0x419ebc, 2, 0x04, 0x00000000 },
+ { 0x419edc, 1, 0x04, 0x00000000 },
+ { 0x419f00, 1, 0x04, 0x00000000 },
+ { 0x419ed0, 1, 0x04, 0x00002616 },
+ { 0x419f74, 1, 0x04, 0x00015555 },
+ { 0x419f80, 4, 0x04, 0x00000000 },
+ {}
+};
+
+static const struct nvc0_graph_pack
+gk110b_graph_pack_mmio[] = {
+ { nve4_graph_init_main_0 },
+ { nvf0_graph_init_fe_0 },
+ { nvc0_graph_init_pri_0 },
+ { nvc0_graph_init_rstr2d_0 },
+ { nvd9_graph_init_pd_0 },
+ { nvf0_graph_init_ds_0 },
+ { nvc0_graph_init_scc_0 },
+ { nvf0_graph_init_sked_0 },
+ { nvf0_graph_init_cwd_0 },
+ { nvd9_graph_init_prop_0 },
+ { nvc1_graph_init_gpc_unk_0 },
+ { nvc0_graph_init_setup_0 },
+ { nvc0_graph_init_crstr_0 },
+ { nvc1_graph_init_setup_1 },
+ { nvc0_graph_init_zcull_0 },
+ { nvd9_graph_init_gpm_0 },
+ { nvf0_graph_init_gpc_unk_1 },
+ { nvc0_graph_init_gcc_0 },
+ { nve4_graph_init_tpccs_0 },
+ { nvf0_graph_init_tex_0 },
+ { nve4_graph_init_pe_0 },
+ { gk110b_graph_init_l1c_0 },
+ { nvc0_graph_init_mpc_0 },
+ { gk110b_graph_init_sm_0 },
+ { nvd7_graph_init_pes_0 },
+ { nvd7_graph_init_wwdx_0 },
+ { nvd7_graph_init_cbm_0 },
+ { nve4_graph_init_be_0 },
+ { nvc0_graph_init_fe_1 },
+ {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+struct nouveau_oclass *
+gk110b_graph_oclass = &(struct nvc0_graph_oclass) {
+ .base.handle = NV_ENGINE(GR, 0xf1),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nvc0_graph_ctor,
+ .dtor = nvc0_graph_dtor,
+ .init = nve4_graph_init,
+ .fini = nvf0_graph_fini,
+ },
+ .cclass = &gk110b_grctx_oclass,
+ .sclass = nvf0_graph_sclass,
+ .mmio = gk110b_graph_pack_mmio,
+ .fecs.ucode = &nvf0_graph_fecs_ucode,
+ .gpccs.ucode = &nvf0_graph_gpccs_ucode,
+ .ppc_nr = 2,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c
index 83048a56430d..7d0abe9f3fe7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c
@@ -27,8 +27,8 @@ static struct nouveau_oclass
gk20a_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa040, &nouveau_object_ofuncs },
- { 0xa297, &nouveau_object_ofuncs },
- { 0xa0c0, &nouveau_object_ofuncs },
+ { KEPLER_C, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { KEPLER_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@@ -39,9 +39,10 @@ gk20a_graph_oclass = &(struct nvc0_graph_oclass) {
.ctor = nvc0_graph_ctor,
.dtor = nvc0_graph_dtor,
.init = nve4_graph_init,
- .fini = nve4_graph_fini,
+ .fini = _nouveau_graph_fini,
},
.cclass = &gk20a_grctx_oclass,
.sclass = gk20a_graph_sclass,
.mmio = nve4_graph_pack_mmio,
+ .ppc_nr = 1,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
index 21c5f31d607f..4bdbdab2fd9a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c
@@ -36,8 +36,8 @@ static struct nouveau_oclass
gm107_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa140, &nouveau_object_ofuncs },
- { 0xb097, &nouveau_object_ofuncs },
- { 0xb0c0, &nouveau_object_ofuncs },
+ { MAXWELL_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { MAXWELL_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@@ -425,6 +425,9 @@ gm107_graph_init(struct nouveau_object *object)
nv_wr32(priv, 0x400134, 0xffffffff);
nv_wr32(priv, 0x400054, 0x2c350f63);
+
+ nvc0_graph_zbc_init(priv);
+
return nvc0_graph_init_ctxctl(priv);
}
@@ -462,4 +465,5 @@ gm107_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = gm107_graph_pack_mmio,
.fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL,
.gpccs.ucode = &gm107_graph_gpccs_ucode,
+ .ppc_nr = 2,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
index ad13dcdd15f9..f70e2f67a4dd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
@@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
-#include <core/class.h>
#include <core/handle.h>
#include <core/namedb.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
index 4532f7e5618c..2b12b09683c8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
@@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
-#include <core/class.h>
#include <core/handle.h>
#include <subdev/fb.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
index 00ea1a089822..2b0e8f48c029 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
@@ -33,7 +33,7 @@ static struct nouveau_oclass
nv108_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa140, &nouveau_object_ofuncs },
- { 0xa197, &nouveau_object_ofuncs },
+ { KEPLER_B, &nvc0_fermi_ofuncs },
{ 0xa1c0, &nouveau_object_ofuncs },
{}
};
@@ -220,4 +220,5 @@ nv108_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = nv108_graph_pack_mmio,
.fecs.ucode = &nv108_graph_fecs_ucode,
.gpccs.ucode = &nv108_graph_gpccs_ucode,
+ .ppc_nr = 1,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
index d145e080899a..ceb9c746d94e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
@@ -1,6 +1,5 @@
#include <core/client.h>
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/handle.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
index 7a80d005a974..f8a6fdd7d5e8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c
@@ -1,5 +1,4 @@
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
index 3e1f32ee43d4..5de9caa2ef67 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c
@@ -1,5 +1,4 @@
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
index e451db32e92a..2f9dbc709389 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c
@@ -1,5 +1,4 @@
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
index 9385ac7b44a4..34dd26c70b64 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c
@@ -1,5 +1,4 @@
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
index 9ce84b73f86a..2fb5756d9f66 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c
@@ -1,5 +1,4 @@
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 6477fbf6a550..4f401174868d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
-#include <core/class.h>
#include <core/handle.h>
#include <core/engctx.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
index 20665c21d80e..38e0aa26f1cd 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/client.h>
#include <core/handle.h>
#include <core/engctx.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index aa0838916354..30fd1dc64f93 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -26,15 +26,232 @@
#include "ctxnvc0.h"
/*******************************************************************************
+ * Zero Bandwidth Clear
+ ******************************************************************************/
+
+static void
+nvc0_graph_zbc_clear_color(struct nvc0_graph_priv *priv, int zbc)
+{
+ if (priv->zbc_color[zbc].format) {
+ nv_wr32(priv, 0x405804, priv->zbc_color[zbc].ds[0]);
+ nv_wr32(priv, 0x405808, priv->zbc_color[zbc].ds[1]);
+ nv_wr32(priv, 0x40580c, priv->zbc_color[zbc].ds[2]);
+ nv_wr32(priv, 0x405810, priv->zbc_color[zbc].ds[3]);
+ }
+ nv_wr32(priv, 0x405814, priv->zbc_color[zbc].format);
+ nv_wr32(priv, 0x405820, zbc);
+ nv_wr32(priv, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
+}
+
+static int
+nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format,
+ const u32 ds[4], const u32 l2[4])
+{
+ struct nouveau_ltc *ltc = nouveau_ltc(priv);
+ int zbc = -ENOSPC, i;
+
+ for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ if (priv->zbc_color[i].format) {
+ if (priv->zbc_color[i].format != format)
+ continue;
+ if (memcmp(priv->zbc_color[i].ds, ds, sizeof(
+ priv->zbc_color[i].ds)))
+ continue;
+ if (memcmp(priv->zbc_color[i].l2, l2, sizeof(
+ priv->zbc_color[i].l2))) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ return i;
+ } else {
+ zbc = (zbc < 0) ? i : zbc;
+ }
+ }
+
+ if (zbc < 0)
+ return zbc;
+
+ memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds));
+ memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2));
+ priv->zbc_color[zbc].format = format;
+ ltc->zbc_color_get(ltc, zbc, l2);
+ nvc0_graph_zbc_clear_color(priv, zbc);
+ return zbc;
+}
+
+static void
+nvc0_graph_zbc_clear_depth(struct nvc0_graph_priv *priv, int zbc)
+{
+ if (priv->zbc_depth[zbc].format)
+ nv_wr32(priv, 0x405818, priv->zbc_depth[zbc].ds);
+ nv_wr32(priv, 0x40581c, priv->zbc_depth[zbc].format);
+ nv_wr32(priv, 0x405820, zbc);
+ nv_wr32(priv, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
+}
+
+static int
+nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format,
+ const u32 ds, const u32 l2)
+{
+ struct nouveau_ltc *ltc = nouveau_ltc(priv);
+ int zbc = -ENOSPC, i;
+
+ for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ if (priv->zbc_depth[i].format) {
+ if (priv->zbc_depth[i].format != format)
+ continue;
+ if (priv->zbc_depth[i].ds != ds)
+ continue;
+ if (priv->zbc_depth[i].l2 != l2) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ return i;
+ } else {
+ zbc = (zbc < 0) ? i : zbc;
+ }
+ }
+
+ if (zbc < 0)
+ return zbc;
+
+ priv->zbc_depth[zbc].format = format;
+ priv->zbc_depth[zbc].ds = ds;
+ priv->zbc_depth[zbc].l2 = l2;
+ ltc->zbc_depth_get(ltc, zbc, l2);
+ nvc0_graph_zbc_clear_depth(priv, zbc);
+ return zbc;
+}
+
+/*******************************************************************************
* Graphics object classes
******************************************************************************/
+static int
+nvc0_fermi_mthd_zbc_color(struct nouveau_object *object, void *data, u32 size)
+{
+ struct nvc0_graph_priv *priv = (void *)object->engine;
+ union {
+ struct fermi_a_zbc_color_v0 v0;
+ } *args = data;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ switch (args->v0.format) {
+ case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
+ case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
+ case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
+ case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
+ case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
+ case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
+ case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
+ case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
+ case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
+ case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
+ case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
+ ret = nvc0_graph_zbc_color_get(priv, args->v0.format,
+ args->v0.ds,
+ args->v0.l2);
+ if (ret >= 0) {
+ args->v0.index = ret;
+ return 0;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvc0_fermi_mthd_zbc_depth(struct nouveau_object *object, void *data, u32 size)
+{
+ struct nvc0_graph_priv *priv = (void *)object->engine;
+ union {
+ struct fermi_a_zbc_depth_v0 v0;
+ } *args = data;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ switch (args->v0.format) {
+ case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
+ ret = nvc0_graph_zbc_depth_get(priv, args->v0.format,
+ args->v0.ds,
+ args->v0.l2);
+ return (ret >= 0) ? 0 : -ENOSPC;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int
+nvc0_fermi_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
+{
+ switch (mthd) {
+ case FERMI_A_ZBC_COLOR:
+ return nvc0_fermi_mthd_zbc_color(object, data, size);
+ case FERMI_A_ZBC_DEPTH:
+ return nvc0_fermi_mthd_zbc_depth(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
+struct nouveau_ofuncs
+nvc0_fermi_ofuncs = {
+ .ctor = _nouveau_object_ctor,
+ .dtor = nouveau_object_destroy,
+ .init = nouveau_object_init,
+ .fini = nouveau_object_fini,
+ .mthd = nvc0_fermi_mthd,
+};
+
+static int
+nvc0_graph_set_shader_exceptions(struct nouveau_object *object, u32 mthd,
+ void *pdata, u32 size)
+{
+ struct nvc0_graph_priv *priv = (void *)nv_engine(object);
+ if (size >= sizeof(u32)) {
+ u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
+ nv_wr32(priv, 0x419e44, data);
+ nv_wr32(priv, 0x419e4c, data);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+struct nouveau_omthds
+nvc0_graph_9097_omthds[] = {
+ { 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
+ {}
+};
+
+struct nouveau_omthds
+nvc0_graph_90c0_omthds[] = {
+ { 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
+ {}
+};
+
struct nouveau_oclass
nvc0_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0x9039, &nouveau_object_ofuncs },
- { 0x9097, &nouveau_object_ofuncs },
- { 0x90c0, &nouveau_object_ofuncs },
+ { FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@@ -98,7 +315,7 @@ nvc0_graph_context_ctor(struct nouveau_object *parent,
u32 addr = mmio->addr;
u32 data = mmio->data;
- if (mmio->shift) {
+ if (mmio->buffer >= 0) {
u64 info = chan->data[mmio->buffer].vma.offset;
data |= info >> mmio->shift;
}
@@ -407,6 +624,35 @@ nvc0_graph_pack_mmio[] = {
******************************************************************************/
void
+nvc0_graph_zbc_init(struct nvc0_graph_priv *priv)
+{
+ const u32 zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
+ const u32 one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+ const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
+ const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
+ 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
+ struct nouveau_ltc *ltc = nouveau_ltc(priv);
+ int index;
+
+ if (!priv->zbc_color[0].format) {
+ nvc0_graph_zbc_color_get(priv, 1, & zero[0], &zero[4]);
+ nvc0_graph_zbc_color_get(priv, 2, & one[0], &one[4]);
+ nvc0_graph_zbc_color_get(priv, 4, &f32_0[0], &f32_0[4]);
+ nvc0_graph_zbc_color_get(priv, 4, &f32_1[0], &f32_1[4]);
+ nvc0_graph_zbc_depth_get(priv, 1, 0x00000000, 0x00000000);
+ nvc0_graph_zbc_depth_get(priv, 1, 0x3f800000, 0x3f800000);
+ }
+
+ for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
+ nvc0_graph_zbc_clear_color(priv, index);
+ for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
+ nvc0_graph_zbc_clear_depth(priv, index);
+}
+
+void
nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
{
const struct nvc0_graph_pack *pack;
@@ -969,17 +1215,16 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
{
struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
- u32 r000260;
int i;
if (priv->firmware) {
/* load fuc microcode */
- r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c,
&priv->fuc409d);
nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac,
&priv->fuc41ad);
- nv_wr32(priv, 0x000260, r000260);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
/* start both of them running */
nv_wr32(priv, 0x409840, 0xffffffff);
@@ -1066,7 +1311,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
}
/* load HUB microcode */
- r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nv_wr32(priv, 0x4091c0, 0x01000000);
for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
nv_wr32(priv, 0x4091c4, oclass->fecs.ucode->data.data[i]);
@@ -1089,7 +1334,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x41a188, i >> 6);
nv_wr32(priv, 0x41a184, oclass->gpccs.ucode->code.data[i]);
}
- nv_wr32(priv, 0x000260, r000260);
+ nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
/* load register lists */
nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
@@ -1224,6 +1469,9 @@ nvc0_graph_init(struct nouveau_object *object)
nv_wr32(priv, 0x400134, 0xffffffff);
nv_wr32(priv, 0x400054, 0x34ce3464);
+
+ nvc0_graph_zbc_init(priv);
+
return nvc0_graph_init_ctxctl(priv);
}
@@ -1287,7 +1535,7 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_device *device = nv_device(parent);
struct nvc0_graph_priv *priv;
bool use_ext_fw, enable;
- int ret, i;
+ int ret, i, j;
use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
oclass->fecs.ucode == NULL);
@@ -1333,6 +1581,11 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
for (i = 0; i < priv->gpc_nr; i++) {
priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608));
priv->tpc_total += priv->tpc_nr[i];
+ priv->ppc_nr[i] = oclass->ppc_nr;
+ for (j = 0; j < priv->ppc_nr[i]; j++) {
+ u8 mask = nv_rd32(priv, GPC_UNIT(i, 0x0c30 + (j * 4)));
+ priv->ppc_tpc_nr[i][j] = hweight8(mask);
+ }
}
/*XXX: these need figuring out... though it might not even matter */
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
index ffc289198dd8..7ed9e89c3435 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
@@ -30,10 +30,15 @@
#include <core/gpuobj.h>
#include <core/option.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+
#include <subdev/fb.h>
#include <subdev/vm.h>
#include <subdev/bar.h>
#include <subdev/timer.h>
+#include <subdev/mc.h>
+#include <subdev/ltc.h>
#include <engine/fifo.h>
#include <engine/graph.h>
@@ -60,7 +65,7 @@ struct nvc0_graph_mmio {
u32 addr;
u32 data;
u32 shift;
- u32 buffer;
+ int buffer;
};
struct nvc0_graph_fuc {
@@ -68,6 +73,18 @@ struct nvc0_graph_fuc {
u32 size;
};
+struct nvc0_graph_zbc_color {
+ u32 format;
+ u32 ds[4];
+ u32 l2[4];
+};
+
+struct nvc0_graph_zbc_depth {
+ u32 format;
+ u32 ds;
+ u32 l2;
+};
+
struct nvc0_graph_priv {
struct nouveau_graph base;
@@ -77,10 +94,15 @@ struct nvc0_graph_priv {
struct nvc0_graph_fuc fuc41ad;
bool firmware;
+ struct nvc0_graph_zbc_color zbc_color[NOUVEAU_LTC_MAX_ZBC_CNT];
+ struct nvc0_graph_zbc_depth zbc_depth[NOUVEAU_LTC_MAX_ZBC_CNT];
+
u8 rop_nr;
u8 gpc_nr;
u8 tpc_nr[GPC_MAX];
u8 tpc_total;
+ u8 ppc_nr[GPC_MAX];
+ u8 ppc_tpc_nr[GPC_MAX][4];
struct nouveau_gpuobj *unk4188b4;
struct nouveau_gpuobj *unk4188b8;
@@ -118,12 +140,20 @@ int nvc0_graph_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_object **);
void nvc0_graph_dtor(struct nouveau_object *);
int nvc0_graph_init(struct nouveau_object *);
+void nvc0_graph_zbc_init(struct nvc0_graph_priv *);
+
int nve4_graph_fini(struct nouveau_object *, bool);
int nve4_graph_init(struct nouveau_object *);
-extern struct nouveau_oclass nvc0_graph_sclass[];
+int nvf0_graph_fini(struct nouveau_object *, bool);
+
+extern struct nouveau_ofuncs nvc0_fermi_ofuncs;
+extern struct nouveau_oclass nvc0_graph_sclass[];
+extern struct nouveau_omthds nvc0_graph_9097_omthds[];
+extern struct nouveau_omthds nvc0_graph_90c0_omthds[];
extern struct nouveau_oclass nvc8_graph_sclass[];
+extern struct nouveau_oclass nvf0_graph_sclass[];
struct nvc0_graph_init {
u32 addr;
@@ -149,6 +179,9 @@ struct nvc0_graph_ucode {
extern struct nvc0_graph_ucode nvc0_graph_fecs_ucode;
extern struct nvc0_graph_ucode nvc0_graph_gpccs_ucode;
+extern struct nvc0_graph_ucode nvf0_graph_fecs_ucode;
+extern struct nvc0_graph_ucode nvf0_graph_gpccs_ucode;
+
struct nvc0_graph_oclass {
struct nouveau_oclass base;
struct nouveau_oclass **cclass;
@@ -160,6 +193,7 @@ struct nvc0_graph_oclass {
struct {
struct nvc0_graph_ucode *ucode;
} gpccs;
+ int ppc_nr;
};
void nvc0_graph_mmio(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);
@@ -223,9 +257,11 @@ extern const struct nvc0_graph_init nve4_graph_init_be_0[];
extern const struct nvc0_graph_pack nve4_graph_pack_mmio[];
extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
+extern const struct nvc0_graph_init nvf0_graph_init_ds_0[];
extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
extern const struct nvc0_graph_init nvf0_graph_init_cwd_0[];
extern const struct nvc0_graph_init nvf0_graph_init_gpc_unk_1[];
+extern const struct nvc0_graph_init nvf0_graph_init_tex_0[];
extern const struct nvc0_graph_init nvf0_graph_init_sm_0[];
extern const struct nvc0_graph_init nv108_graph_init_gpc_unk_0[];
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
index 30cab0b2eba1..93d58e5b82c2 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c
@@ -33,9 +33,9 @@ static struct nouveau_oclass
nvc1_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0x9039, &nouveau_object_ofuncs },
- { 0x9097, &nouveau_object_ofuncs },
- { 0x90c0, &nouveau_object_ofuncs },
- { 0x9197, &nouveau_object_ofuncs },
+ { FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
index a6bf783e1256..692e1eda0eb4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c
@@ -33,10 +33,10 @@ struct nouveau_oclass
nvc8_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0x9039, &nouveau_object_ofuncs },
- { 0x9097, &nouveau_object_ofuncs },
- { 0x90c0, &nouveau_object_ofuncs },
- { 0x9197, &nouveau_object_ofuncs },
- { 0x9297, &nouveau_object_ofuncs },
+ { FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_C, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
index 2a6a94e2a041..41e8445c7eea 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c
@@ -133,4 +133,5 @@ nvd7_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = nvd7_graph_pack_mmio,
.fecs.ucode = &nvd7_graph_fecs_ucode,
.gpccs.ucode = &nvd7_graph_gpccs_ucode,
+ .ppc_nr = 1,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
index 51e0c075ad34..0c71f5c67ae0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
@@ -22,6 +22,8 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
+#include <subdev/pwr.h>
+
#include "nvc0.h"
#include "ctxnvc0.h"
@@ -33,8 +35,8 @@ static struct nouveau_oclass
nve4_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa040, &nouveau_object_ofuncs },
- { 0xa097, &nouveau_object_ofuncs },
- { 0xa0c0, &nouveau_object_ofuncs },
+ { KEPLER_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { KEPLER_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@@ -190,39 +192,20 @@ nve4_graph_pack_mmio[] = {
******************************************************************************/
int
-nve4_graph_fini(struct nouveau_object *object, bool suspend)
-{
- struct nvc0_graph_priv *priv = (void *)object;
-
- /*XXX: this is a nasty hack to power on gr on certain boards
- * where it's disabled by therm, somehow. ideally it'd
- * be nice to know when we should be doing this, and why,
- * but, it's yet to be determined. for now we test for
- * the particular mmio error that occurs in the situation,
- * and then bash therm in the way nvidia do.
- */
- nv_mask(priv, 0x000200, 0x08001000, 0x08001000);
- nv_rd32(priv, 0x000200);
- if (nv_rd32(priv, 0x400700) == 0xbadf1000) {
- nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
- nv_rd32(priv, 0x000200);
- nv_mask(priv, 0x020004, 0xc0000000, 0x40000000);
- }
-
- return nouveau_graph_fini(&priv->base, suspend);
-}
-
-int
nve4_graph_init(struct nouveau_object *object)
{
struct nvc0_graph_oclass *oclass = (void *)object->oclass;
struct nvc0_graph_priv *priv = (void *)object;
+ struct nouveau_pwr *ppwr = nouveau_pwr(priv);
const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
u32 data[TPC_MAX / 8] = {};
u8 tpcnr[GPC_MAX];
int gpc, tpc, rop;
int ret, i;
+ if (ppwr)
+ ppwr->pgob(ppwr, false);
+
ret = nouveau_graph_init(&priv->base);
if (ret)
return ret;
@@ -320,6 +303,9 @@ nve4_graph_init(struct nouveau_object *object)
nv_wr32(priv, 0x400134, 0xffffffff);
nv_wr32(priv, 0x400054, 0x34ce3464);
+
+ nvc0_graph_zbc_init(priv);
+
return nvc0_graph_init_ctxctl(priv);
}
@@ -350,11 +336,12 @@ nve4_graph_oclass = &(struct nvc0_graph_oclass) {
.ctor = nvc0_graph_ctor,
.dtor = nvc0_graph_dtor,
.init = nve4_graph_init,
- .fini = nve4_graph_fini,
+ .fini = _nouveau_graph_fini,
},
.cclass = &nve4_grctx_oclass,
.sclass = nve4_graph_sclass,
.mmio = nve4_graph_pack_mmio,
.fecs.ucode = &nve4_graph_fecs_ucode,
.gpccs.ucode = &nve4_graph_gpccs_ucode,
+ .ppc_nr = 1,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
index c96762122b9b..c306c0f2fc84 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
@@ -29,12 +29,12 @@
* Graphics object classes
******************************************************************************/
-static struct nouveau_oclass
+struct nouveau_oclass
nvf0_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa140, &nouveau_object_ofuncs },
- { 0xa197, &nouveau_object_ofuncs },
- { 0xa1c0, &nouveau_object_ofuncs },
+ { KEPLER_B, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
+ { KEPLER_COMPUTE_B, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@@ -50,7 +50,7 @@ nvf0_graph_init_fe_0[] = {
{}
};
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
nvf0_graph_init_ds_0[] = {
{ 0x405844, 1, 0x04, 0x00ffffff },
{ 0x405850, 1, 0x04, 0x00000000 },
@@ -88,7 +88,7 @@ nvf0_graph_init_gpc_unk_1[] = {
{}
};
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
nvf0_graph_init_tex_0[] = {
{ 0x419ab0, 1, 0x04, 0x00000000 },
{ 0x419ac8, 1, 0x04, 0x00000000 },
@@ -170,7 +170,7 @@ nvf0_graph_pack_mmio[] = {
* PGRAPH engine/subdev functions
******************************************************************************/
-static int
+int
nvf0_graph_fini(struct nouveau_object *object, bool suspend)
{
struct nvc0_graph_priv *priv = (void *)object;
@@ -209,7 +209,7 @@ nvf0_graph_fini(struct nouveau_object *object, bool suspend)
#include "fuc/hubnvf0.fuc.h"
-static struct nvc0_graph_ucode
+struct nvc0_graph_ucode
nvf0_graph_fecs_ucode = {
.code.data = nvf0_grhub_code,
.code.size = sizeof(nvf0_grhub_code),
@@ -219,7 +219,7 @@ nvf0_graph_fecs_ucode = {
#include "fuc/gpcnvf0.fuc.h"
-static struct nvc0_graph_ucode
+struct nvc0_graph_ucode
nvf0_graph_gpccs_ucode = {
.code.data = nvf0_grgpc_code,
.code.size = sizeof(nvf0_grgpc_code),
@@ -241,4 +241,5 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = nvf0_graph_pack_mmio,
.fecs.ucode = &nvf0_graph_fecs_ucode,
.gpccs.ucode = &nvf0_graph_gpccs_ucode,
+ .ppc_nr = 2,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
index 7eb6d94c84e2..d88c700b2f69 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
@@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/handle.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
index d4e7ec0ba68c..bdb2f20ff7b1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <subdev/fb.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
index 3d8c2133e0e8..72c7f33fd29b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/client.h>
#include <core/engctx.h>
#include <core/handle.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c
index 37a2bd9e8078..cae33f86b11a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <subdev/vm.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c
index 96f5aa92677b..e9cc8b116a24 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <subdev/vm.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
index e9c5e51943ef..63013812f7c9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c
@@ -22,8 +22,11 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/option.h>
-#include <core/class.h>
+#include <nvif/unpack.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
#include <subdev/clock.h>
@@ -101,24 +104,28 @@ nouveau_perfsig_wrap(struct nouveau_perfmon *ppm, const char *name,
* Perfmon object classes
******************************************************************************/
static int
-nouveau_perfctr_query(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_perfctr_query(struct nouveau_object *object, void *data, u32 size)
{
+ union {
+ struct nvif_perfctr_query_v0 v0;
+ } *args = data;
struct nouveau_device *device = nv_device(object);
struct nouveau_perfmon *ppm = (void *)object->engine;
struct nouveau_perfdom *dom = NULL, *chk;
- struct nv_perfctr_query *args = data;
const bool all = nouveau_boolopt(device->cfgopt, "NvPmShowAll", false);
const bool raw = nouveau_boolopt(device->cfgopt, "NvPmUnnamed", all);
const char *name;
int tmp = 0, di, si;
- char path[64];
-
- if (size < sizeof(*args))
- return -EINVAL;
+ int ret;
- di = (args->iter & 0xff000000) >> 24;
- si = (args->iter & 0x00ffffff) - 1;
+ nv_ioctl(object, "perfctr query size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "perfctr query vers %d iter %08x\n",
+ args->v0.version, args->v0.iter);
+ di = (args->v0.iter & 0xff000000) >> 24;
+ si = (args->v0.iter & 0x00ffffff) - 1;
+ } else
+ return ret;
list_for_each_entry(chk, &ppm->domains, head) {
if (tmp++ == di) {
@@ -132,19 +139,17 @@ nouveau_perfctr_query(struct nouveau_object *object, u32 mthd,
if (si >= 0) {
if (raw || !(name = dom->signal[si].name)) {
- snprintf(path, sizeof(path), "/%s/%02x", dom->name, si);
- name = path;
+ snprintf(args->v0.name, sizeof(args->v0.name),
+ "/%s/%02x", dom->name, si);
+ } else {
+ strncpy(args->v0.name, name, sizeof(args->v0.name));
}
-
- if (args->name)
- strncpy(args->name, name, args->size);
- args->size = strlen(name) + 1;
}
do {
while (++si < dom->signal_nr) {
if (all || dom->signal[si].name) {
- args->iter = (di << 24) | ++si;
+ args->v0.iter = (di << 24) | ++si;
return 0;
}
}
@@ -153,21 +158,26 @@ nouveau_perfctr_query(struct nouveau_object *object, u32 mthd,
dom = list_entry(dom->head.next, typeof(*dom), head);
} while (&dom->head != &ppm->domains);
- args->iter = 0xffffffff;
+ args->v0.iter = 0xffffffff;
return 0;
}
static int
-nouveau_perfctr_sample(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_perfctr_sample(struct nouveau_object *object, void *data, u32 size)
{
+ union {
+ struct nvif_perfctr_sample none;
+ } *args = data;
struct nouveau_perfmon *ppm = (void *)object->engine;
struct nouveau_perfctr *ctr, *tmp;
struct nouveau_perfdom *dom;
- struct nv_perfctr_sample *args = data;
+ int ret;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(object, "perfctr sample size %d\n", size);
+ if (nvif_unvers(args->none)) {
+ nv_ioctl(object, "perfctr sample\n");
+ } else
+ return ret;
ppm->sequence++;
list_for_each_entry(dom, &ppm->domains, head) {
@@ -206,22 +216,45 @@ nouveau_perfctr_sample(struct nouveau_object *object, u32 mthd,
}
static int
-nouveau_perfctr_read(struct nouveau_object *object, u32 mthd,
- void *data, u32 size)
+nouveau_perfctr_read(struct nouveau_object *object, void *data, u32 size)
{
+ union {
+ struct nvif_perfctr_read_v0 v0;
+ } *args = data;
struct nouveau_perfctr *ctr = (void *)object;
- struct nv_perfctr_read *args = data;
+ int ret;
+
+ nv_ioctl(object, "perfctr read size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(object, "perfctr read vers %d\n", args->v0.version);
+ } else
+ return ret;
- if (size < sizeof(*args))
- return -EINVAL;
if (!ctr->clk)
return -EAGAIN;
- args->clk = ctr->clk;
- args->ctr = ctr->ctr;
+ args->v0.clk = ctr->clk;
+ args->v0.ctr = ctr->ctr;
return 0;
}
+static int
+nouveau_perfctr_mthd(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ switch (mthd) {
+ case NVIF_PERFCTR_V0_QUERY:
+ return nouveau_perfctr_query(object, data, size);
+ case NVIF_PERFCTR_V0_SAMPLE:
+ return nouveau_perfctr_sample(object, data, size);
+ case NVIF_PERFCTR_V0_READ:
+ return nouveau_perfctr_read(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
static void
nouveau_perfctr_dtor(struct nouveau_object *object)
{
@@ -237,19 +270,27 @@ nouveau_perfctr_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
+ union {
+ struct nvif_perfctr_v0 v0;
+ } *args = data;
struct nouveau_perfmon *ppm = (void *)engine;
struct nouveau_perfdom *dom = NULL;
struct nouveau_perfsig *sig[4] = {};
struct nouveau_perfctr *ctr;
- struct nv_perfctr_class *args = data;
int ret, i;
- if (size < sizeof(*args))
- return -EINVAL;
+ nv_ioctl(parent, "create perfctr size %d\n", size);
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ nv_ioctl(parent, "create perfctr vers %d logic_op %04x\n",
+ args->v0.version, args->v0.logic_op);
+ } else
+ return ret;
- for (i = 0; i < ARRAY_SIZE(args->signal) && args->signal[i].name; i++) {
- sig[i] = nouveau_perfsig_find(ppm, args->signal[i].name,
- args->signal[i].size, &dom);
+ for (i = 0; i < ARRAY_SIZE(args->v0.name) && args->v0.name[i][0]; i++) {
+ sig[i] = nouveau_perfsig_find(ppm, args->v0.name[i],
+ strnlen(args->v0.name[i],
+ sizeof(args->v0.name[i])),
+ &dom);
if (!sig[i])
return -EINVAL;
}
@@ -260,7 +301,7 @@ nouveau_perfctr_ctor(struct nouveau_object *parent,
return ret;
ctr->slot = -1;
- ctr->logic_op = args->logic_op;
+ ctr->logic_op = args->v0.logic_op;
ctr->signal[0] = sig[0];
ctr->signal[1] = sig[1];
ctr->signal[2] = sig[2];
@@ -276,21 +317,13 @@ nouveau_perfctr_ofuncs = {
.dtor = nouveau_perfctr_dtor,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
-};
-
-static struct nouveau_omthds
-nouveau_perfctr_omthds[] = {
- { NV_PERFCTR_QUERY, NV_PERFCTR_QUERY, nouveau_perfctr_query },
- { NV_PERFCTR_SAMPLE, NV_PERFCTR_SAMPLE, nouveau_perfctr_sample },
- { NV_PERFCTR_READ, NV_PERFCTR_READ, nouveau_perfctr_read },
- {}
+ .mthd = nouveau_perfctr_mthd,
};
struct nouveau_oclass
nouveau_perfmon_sclass[] = {
- { .handle = NV_PERFCTR_CLASS,
+ { .handle = NVIF_IOCTL_NEW_V0_PERFCTR,
.ofuncs = &nouveau_perfctr_ofuncs,
- .omthds = nouveau_perfctr_omthds,
},
{},
};
@@ -303,6 +336,7 @@ nouveau_perfctx_dtor(struct nouveau_object *object)
{
struct nouveau_perfmon *ppm = (void *)object->engine;
mutex_lock(&nv_subdev(ppm)->mutex);
+ nouveau_engctx_destroy(&ppm->context->base);
ppm->context = NULL;
mutex_unlock(&nv_subdev(ppm)->mutex);
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c
index c571758e4a27..64df15c7f051 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <engine/software.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c
index a62f11a78430..f54a2253deca 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <engine/software.h>
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
index f3b4d9dbf23c..4d2994d8cc32 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c
@@ -23,12 +23,12 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/namedb.h>
#include <core/handle.h>
#include <core/gpuobj.h>
#include <core/event.h>
+#include <nvif/event.h>
#include <subdev/bar.h>
@@ -86,10 +86,10 @@ nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,
{
struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);
u32 head = *(u32 *)args;
- if (head >= chan->vblank.nr_event)
+ if (head >= nouveau_disp(chan)->vblank.index_nr)
return -EINVAL;
- nouveau_event_get(chan->vblank.event[head]);
+ nvkm_notify_get(&chan->vblank.notify[head]);
return 0;
}
@@ -124,9 +124,10 @@ nv50_software_sclass[] = {
******************************************************************************/
static int
-nv50_software_vblsem_release(void *data, u32 type, int head)
+nv50_software_vblsem_release(struct nvkm_notify *notify)
{
- struct nv50_software_chan *chan = data;
+ struct nv50_software_chan *chan =
+ container_of(notify, typeof(*chan), vblank.notify[notify->index]);
struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
struct nouveau_bar *bar = nouveau_bar(priv);
@@ -142,7 +143,7 @@ nv50_software_vblsem_release(void *data, u32 type, int head)
nv_wr32(priv, 0x060014, chan->vblank.value);
}
- return NVKM_EVENT_DROP;
+ return NVKM_NOTIFY_DROP;
}
void
@@ -151,11 +152,8 @@ nv50_software_context_dtor(struct nouveau_object *object)
struct nv50_software_chan *chan = (void *)object;
int i;
- if (chan->vblank.event) {
- for (i = 0; i < chan->vblank.nr_event; i++)
- nouveau_event_ref(NULL, &chan->vblank.event[i]);
- kfree(chan->vblank.event);
- }
+ for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++)
+ nvkm_notify_fini(&chan->vblank.notify[i]);
nouveau_software_context_destroy(&chan->base);
}
@@ -176,15 +174,14 @@ nv50_software_context_ctor(struct nouveau_object *parent,
if (ret)
return ret;
- chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0;
- chan->vblank.event = kzalloc(chan->vblank.nr_event *
- sizeof(*chan->vblank.event), GFP_KERNEL);
- if (!chan->vblank.event)
- return -ENOMEM;
-
- for (i = 0; i < chan->vblank.nr_event; i++) {
- ret = nouveau_event_new(pdisp->vblank, 1, i, pclass->vblank,
- chan, &chan->vblank.event[i]);
+ for (i = 0; pdisp && i < pdisp->vblank.index_nr; i++) {
+ ret = nvkm_notify_init(&pdisp->vblank, pclass->vblank, false,
+ &(struct nvif_notify_head_req_v0) {
+ .head = i,
+ },
+ sizeof(struct nvif_notify_head_req_v0),
+ sizeof(struct nvif_notify_head_rep_v0),
+ &chan->vblank.notify[i]);
if (ret)
return ret;
}
@@ -198,7 +195,7 @@ nv50_software_cclass = {
.base.handle = NV_ENGCTX(SW, 0x50),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv50_software_context_ctor,
- .dtor = _nouveau_software_context_dtor,
+ .dtor = nv50_software_context_dtor,
.init = _nouveau_software_context_init,
.fini = _nouveau_software_context_fini,
},
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.h b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
index bb49a7a20857..41542e725b4b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h
@@ -19,14 +19,13 @@ int nv50_software_ctor(struct nouveau_object *, struct nouveau_object *,
struct nv50_software_cclass {
struct nouveau_oclass base;
- int (*vblank)(void *, u32, int);
+ int (*vblank)(struct nvkm_notify *);
};
struct nv50_software_chan {
struct nouveau_software_chan base;
struct {
- struct nouveau_eventh **event;
- int nr_event;
+ struct nvkm_notify notify[4];
u32 channel;
u32 ctxdma;
u64 offset;
diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
index 135c20f38356..6af370d3a06d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
@@ -23,7 +23,6 @@
*/
#include <core/os.h>
-#include <core/class.h>
#include <core/engctx.h>
#include <core/event.h>
@@ -104,9 +103,10 @@ nvc0_software_sclass[] = {
******************************************************************************/
static int
-nvc0_software_vblsem_release(void *data, u32 type, int head)
+nvc0_software_vblsem_release(struct nvkm_notify *notify)
{
- struct nv50_software_chan *chan = data;
+ struct nv50_software_chan *chan =
+ container_of(notify, typeof(*chan), vblank.notify[notify->index]);
struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
struct nouveau_bar *bar = nouveau_bar(priv);
@@ -116,7 +116,7 @@ nvc0_software_vblsem_release(void *data, u32 type, int head)
nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060014, chan->vblank.value);
- return NVKM_EVENT_DROP;
+ return NVKM_NOTIFY_DROP;
}
static struct nv50_software_cclass
@@ -124,7 +124,7 @@ nvc0_software_cclass = {
.base.handle = NV_ENGCTX(SW, 0xc0),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv50_software_context_ctor,
- .dtor = _nouveau_software_context_dtor,
+ .dtor = nv50_software_context_dtor,
.init = _nouveau_software_context_init,
.fini = _nouveau_software_context_fini,
},
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
deleted file mode 100644
index e0c812bc884f..000000000000
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ /dev/null
@@ -1,470 +0,0 @@
-#ifndef __NOUVEAU_CLASS_H__
-#define __NOUVEAU_CLASS_H__
-
-/* Device class
- *
- * 0080: NV_DEVICE
- */
-#define NV_DEVICE_CLASS 0x00000080
-
-#define NV_DEVICE_DISABLE_IDENTIFY 0x0000000000000001ULL
-#define NV_DEVICE_DISABLE_MMIO 0x0000000000000002ULL
-#define NV_DEVICE_DISABLE_VBIOS 0x0000000000000004ULL
-#define NV_DEVICE_DISABLE_CORE 0x0000000000000008ULL
-#define NV_DEVICE_DISABLE_DISP 0x0000000000010000ULL
-#define NV_DEVICE_DISABLE_FIFO 0x0000000000020000ULL
-#define NV_DEVICE_DISABLE_GRAPH 0x0000000100000000ULL
-#define NV_DEVICE_DISABLE_MPEG 0x0000000200000000ULL
-#define NV_DEVICE_DISABLE_ME 0x0000000400000000ULL
-#define NV_DEVICE_DISABLE_VP 0x0000000800000000ULL
-#define NV_DEVICE_DISABLE_CRYPT 0x0000001000000000ULL
-#define NV_DEVICE_DISABLE_BSP 0x0000002000000000ULL
-#define NV_DEVICE_DISABLE_PPP 0x0000004000000000ULL
-#define NV_DEVICE_DISABLE_COPY0 0x0000008000000000ULL
-#define NV_DEVICE_DISABLE_COPY1 0x0000010000000000ULL
-#define NV_DEVICE_DISABLE_VIC 0x0000020000000000ULL
-#define NV_DEVICE_DISABLE_VENC 0x0000040000000000ULL
-
-struct nv_device_class {
- u64 device; /* device identifier, ~0 for client default */
- u64 disable; /* disable particular subsystems */
- u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */
-};
-
-/* DMA object classes
- *
- * 0002: NV_DMA_FROM_MEMORY
- * 0003: NV_DMA_TO_MEMORY
- * 003d: NV_DMA_IN_MEMORY
- */
-#define NV_DMA_FROM_MEMORY_CLASS 0x00000002
-#define NV_DMA_TO_MEMORY_CLASS 0x00000003
-#define NV_DMA_IN_MEMORY_CLASS 0x0000003d
-
-#define NV_DMA_TARGET_MASK 0x000000ff
-#define NV_DMA_TARGET_VM 0x00000000
-#define NV_DMA_TARGET_VRAM 0x00000001
-#define NV_DMA_TARGET_PCI 0x00000002
-#define NV_DMA_TARGET_PCI_US 0x00000003
-#define NV_DMA_TARGET_AGP 0x00000004
-#define NV_DMA_ACCESS_MASK 0x00000f00
-#define NV_DMA_ACCESS_VM 0x00000000
-#define NV_DMA_ACCESS_RD 0x00000100
-#define NV_DMA_ACCESS_WR 0x00000200
-#define NV_DMA_ACCESS_RDWR 0x00000300
-
-/* NV50:NVC0 */
-#define NV50_DMA_CONF0_ENABLE 0x80000000
-#define NV50_DMA_CONF0_PRIV 0x00300000
-#define NV50_DMA_CONF0_PRIV_VM 0x00000000
-#define NV50_DMA_CONF0_PRIV_US 0x00100000
-#define NV50_DMA_CONF0_PRIV__S 0x00200000
-#define NV50_DMA_CONF0_PART 0x00030000
-#define NV50_DMA_CONF0_PART_VM 0x00000000
-#define NV50_DMA_CONF0_PART_256 0x00010000
-#define NV50_DMA_CONF0_PART_1KB 0x00020000
-#define NV50_DMA_CONF0_COMP 0x00000180
-#define NV50_DMA_CONF0_COMP_NONE 0x00000000
-#define NV50_DMA_CONF0_COMP_VM 0x00000180
-#define NV50_DMA_CONF0_TYPE 0x0000007f
-#define NV50_DMA_CONF0_TYPE_LINEAR 0x00000000
-#define NV50_DMA_CONF0_TYPE_VM 0x0000007f
-
-/* NVC0:NVD9 */
-#define NVC0_DMA_CONF0_ENABLE 0x80000000
-#define NVC0_DMA_CONF0_PRIV 0x00300000
-#define NVC0_DMA_CONF0_PRIV_VM 0x00000000
-#define NVC0_DMA_CONF0_PRIV_US 0x00100000
-#define NVC0_DMA_CONF0_PRIV__S 0x00200000
-#define NVC0_DMA_CONF0_UNKN /* PART? */ 0x00030000
-#define NVC0_DMA_CONF0_TYPE 0x000000ff
-#define NVC0_DMA_CONF0_TYPE_LINEAR 0x00000000
-#define NVC0_DMA_CONF0_TYPE_VM 0x000000ff
-
-/* NVD9- */
-#define NVD0_DMA_CONF0_ENABLE 0x80000000
-#define NVD0_DMA_CONF0_PAGE 0x00000400
-#define NVD0_DMA_CONF0_PAGE_LP 0x00000000
-#define NVD0_DMA_CONF0_PAGE_SP 0x00000400
-#define NVD0_DMA_CONF0_TYPE 0x000000ff
-#define NVD0_DMA_CONF0_TYPE_LINEAR 0x00000000
-#define NVD0_DMA_CONF0_TYPE_VM 0x000000ff
-
-struct nv_dma_class {
- u32 flags;
- u32 pad0;
- u64 start;
- u64 limit;
- u32 conf0;
-};
-
-/* Perfmon counter class
- *
- * XXXX: NV_PERFCTR
- */
-#define NV_PERFCTR_CLASS 0x0000ffff
-#define NV_PERFCTR_QUERY 0x00000000
-#define NV_PERFCTR_SAMPLE 0x00000001
-#define NV_PERFCTR_READ 0x00000002
-
-struct nv_perfctr_class {
- u16 logic_op;
- struct {
- char __user *name; /*XXX: use cfu when exposed to userspace */
- u32 size;
- } signal[4];
-};
-
-struct nv_perfctr_query {
- u32 iter;
- u32 size;
- char __user *name; /*XXX: use ctu when exposed to userspace */
-};
-
-struct nv_perfctr_sample {
-};
-
-struct nv_perfctr_read {
- u32 ctr;
- u32 clk;
-};
-
-/* Device control class
- *
- * XXXX: NV_CONTROL
- */
-#define NV_CONTROL_CLASS 0x0000fffe
-
-#define NV_CONTROL_PSTATE_INFO 0x00000000
-#define NV_CONTROL_PSTATE_INFO_USTATE_DISABLE (-1)
-#define NV_CONTROL_PSTATE_INFO_USTATE_PERFMON (-2)
-#define NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN (-1)
-#define NV_CONTROL_PSTATE_INFO_PSTATE_PERFMON (-2)
-#define NV_CONTROL_PSTATE_ATTR 0x00000001
-#define NV_CONTROL_PSTATE_ATTR_STATE_CURRENT (-1)
-#define NV_CONTROL_PSTATE_USER 0x00000002
-#define NV_CONTROL_PSTATE_USER_STATE_UNKNOWN (-1)
-#define NV_CONTROL_PSTATE_USER_STATE_PERFMON (-2)
-
-struct nv_control_pstate_info {
- u32 count; /* out: number of power states */
- s32 ustate; /* out: current target pstate index */
- u32 pstate; /* out: current pstate index */
-};
-
-struct nv_control_pstate_attr {
- s32 state; /* in: index of pstate to query
- * out: pstate identifier
- */
- u32 index; /* in: index of attribute to query
- * out: index of next attribute, or 0 if no more
- */
- char name[32];
- char unit[16];
- u32 min;
- u32 max;
-};
-
-struct nv_control_pstate_user {
- s32 state; /* in: pstate identifier */
-};
-
-/* DMA FIFO channel classes
- *
- * 006b: NV03_CHANNEL_DMA
- * 006e: NV10_CHANNEL_DMA
- * 176e: NV17_CHANNEL_DMA
- * 406e: NV40_CHANNEL_DMA
- * 506e: NV50_CHANNEL_DMA
- * 826e: NV84_CHANNEL_DMA
- */
-#define NV03_CHANNEL_DMA_CLASS 0x0000006b
-#define NV10_CHANNEL_DMA_CLASS 0x0000006e
-#define NV17_CHANNEL_DMA_CLASS 0x0000176e
-#define NV40_CHANNEL_DMA_CLASS 0x0000406e
-#define NV50_CHANNEL_DMA_CLASS 0x0000506e
-#define NV84_CHANNEL_DMA_CLASS 0x0000826e
-
-struct nv03_channel_dma_class {
- u32 pushbuf;
- u32 pad0;
- u64 offset;
-};
-
-/* Indirect FIFO channel classes
- *
- * 506f: NV50_CHANNEL_IND
- * 826f: NV84_CHANNEL_IND
- * 906f: NVC0_CHANNEL_IND
- * a06f: NVE0_CHANNEL_IND
- */
-
-#define NV50_CHANNEL_IND_CLASS 0x0000506f
-#define NV84_CHANNEL_IND_CLASS 0x0000826f
-#define NVC0_CHANNEL_IND_CLASS 0x0000906f
-#define NVE0_CHANNEL_IND_CLASS 0x0000a06f
-
-struct nv50_channel_ind_class {
- u32 pushbuf;
- u32 ilength;
- u64 ioffset;
-};
-
-#define NVE0_CHANNEL_IND_ENGINE_GR 0x00000001
-#define NVE0_CHANNEL_IND_ENGINE_VP 0x00000002
-#define NVE0_CHANNEL_IND_ENGINE_PPP 0x00000004
-#define NVE0_CHANNEL_IND_ENGINE_BSP 0x00000008
-#define NVE0_CHANNEL_IND_ENGINE_CE0 0x00000010
-#define NVE0_CHANNEL_IND_ENGINE_CE1 0x00000020
-#define NVE0_CHANNEL_IND_ENGINE_ENC 0x00000040
-
-struct nve0_channel_ind_class {
- u32 pushbuf;
- u32 ilength;
- u64 ioffset;
- u32 engine;
-};
-
-/* 0046: NV04_DISP
- */
-
-#define NV04_DISP_CLASS 0x00000046
-
-#define NV04_DISP_MTHD 0x00000000
-#define NV04_DISP_MTHD_HEAD 0x00000001
-
-#define NV04_DISP_SCANOUTPOS 0x00000000
-
-struct nv04_display_class {
-};
-
-struct nv04_display_scanoutpos {
- s64 time[2];
- u32 vblanks;
- u32 vblanke;
- u32 vtotal;
- u32 vline;
- u32 hblanks;
- u32 hblanke;
- u32 htotal;
- u32 hline;
-};
-
-/* 5070: NV50_DISP
- * 8270: NV84_DISP
- * 8370: NVA0_DISP
- * 8870: NV94_DISP
- * 8570: NVA3_DISP
- * 9070: NVD0_DISP
- * 9170: NVE0_DISP
- * 9270: NVF0_DISP
- * 9470: GM107_DISP
- */
-
-#define NV50_DISP_CLASS 0x00005070
-#define NV84_DISP_CLASS 0x00008270
-#define NVA0_DISP_CLASS 0x00008370
-#define NV94_DISP_CLASS 0x00008870
-#define NVA3_DISP_CLASS 0x00008570
-#define NVD0_DISP_CLASS 0x00009070
-#define NVE0_DISP_CLASS 0x00009170
-#define NVF0_DISP_CLASS 0x00009270
-#define GM107_DISP_CLASS 0x00009470
-
-#define NV50_DISP_MTHD 0x00000000
-#define NV50_DISP_MTHD_HEAD 0x00000003
-
-#define NV50_DISP_SCANOUTPOS 0x00000000
-
-#define NV50_DISP_SOR_MTHD 0x00010000
-#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000
-#define NV50_DISP_SOR_MTHD_HEAD 0x00000018
-#define NV50_DISP_SOR_MTHD_LINK 0x00000004
-#define NV50_DISP_SOR_MTHD_OR 0x00000003
-
-#define NV50_DISP_SOR_PWR 0x00010000
-#define NV50_DISP_SOR_PWR_STATE 0x00000001
-#define NV50_DISP_SOR_PWR_STATE_ON 0x00000001
-#define NV50_DISP_SOR_PWR_STATE_OFF 0x00000000
-#define NVA3_DISP_SOR_HDA_ELD 0x00010100
-#define NV84_DISP_SOR_HDMI_PWR 0x00012000
-#define NV84_DISP_SOR_HDMI_PWR_STATE 0x40000000
-#define NV84_DISP_SOR_HDMI_PWR_STATE_OFF 0x00000000
-#define NV84_DISP_SOR_HDMI_PWR_STATE_ON 0x40000000
-#define NV84_DISP_SOR_HDMI_PWR_MAX_AC_PACKET 0x001f0000
-#define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f
-#define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000
-#define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff
-#define NV94_DISP_SOR_DP_PWR 0x00016000
-#define NV94_DISP_SOR_DP_PWR_STATE 0x00000001
-#define NV94_DISP_SOR_DP_PWR_STATE_OFF 0x00000000
-#define NV94_DISP_SOR_DP_PWR_STATE_ON 0x00000001
-
-#define NV50_DISP_DAC_MTHD 0x00020000
-#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000
-#define NV50_DISP_DAC_MTHD_OR 0x00000003
-
-#define NV50_DISP_DAC_PWR 0x00020000
-#define NV50_DISP_DAC_PWR_HSYNC 0x00000001
-#define NV50_DISP_DAC_PWR_HSYNC_ON 0x00000000
-#define NV50_DISP_DAC_PWR_HSYNC_LO 0x00000001
-#define NV50_DISP_DAC_PWR_VSYNC 0x00000004
-#define NV50_DISP_DAC_PWR_VSYNC_ON 0x00000000
-#define NV50_DISP_DAC_PWR_VSYNC_LO 0x00000004
-#define NV50_DISP_DAC_PWR_DATA 0x00000010
-#define NV50_DISP_DAC_PWR_DATA_ON 0x00000000
-#define NV50_DISP_DAC_PWR_DATA_LO 0x00000010
-#define NV50_DISP_DAC_PWR_STATE 0x00000040
-#define NV50_DISP_DAC_PWR_STATE_ON 0x00000000
-#define NV50_DISP_DAC_PWR_STATE_OFF 0x00000040
-#define NV50_DISP_DAC_LOAD 0x00020100
-#define NV50_DISP_DAC_LOAD_VALUE 0x00000007
-
-#define NV50_DISP_PIOR_MTHD 0x00030000
-#define NV50_DISP_PIOR_MTHD_TYPE 0x0000f000
-#define NV50_DISP_PIOR_MTHD_OR 0x00000003
-
-#define NV50_DISP_PIOR_PWR 0x00030000
-#define NV50_DISP_PIOR_PWR_STATE 0x00000001
-#define NV50_DISP_PIOR_PWR_STATE_ON 0x00000001
-#define NV50_DISP_PIOR_PWR_STATE_OFF 0x00000000
-#define NV50_DISP_PIOR_TMDS_PWR 0x00032000
-#define NV50_DISP_PIOR_TMDS_PWR_STATE 0x00000001
-#define NV50_DISP_PIOR_TMDS_PWR_STATE_ON 0x00000001
-#define NV50_DISP_PIOR_TMDS_PWR_STATE_OFF 0x00000000
-#define NV50_DISP_PIOR_DP_PWR 0x00036000
-#define NV50_DISP_PIOR_DP_PWR_STATE 0x00000001
-#define NV50_DISP_PIOR_DP_PWR_STATE_ON 0x00000001
-#define NV50_DISP_PIOR_DP_PWR_STATE_OFF 0x00000000
-
-struct nv50_display_class {
-};
-
-/* 507a: NV50_DISP_CURS
- * 827a: NV84_DISP_CURS
- * 837a: NVA0_DISP_CURS
- * 887a: NV94_DISP_CURS
- * 857a: NVA3_DISP_CURS
- * 907a: NVD0_DISP_CURS
- * 917a: NVE0_DISP_CURS
- * 927a: NVF0_DISP_CURS
- * 947a: GM107_DISP_CURS
- */
-
-#define NV50_DISP_CURS_CLASS 0x0000507a
-#define NV84_DISP_CURS_CLASS 0x0000827a
-#define NVA0_DISP_CURS_CLASS 0x0000837a
-#define NV94_DISP_CURS_CLASS 0x0000887a
-#define NVA3_DISP_CURS_CLASS 0x0000857a
-#define NVD0_DISP_CURS_CLASS 0x0000907a
-#define NVE0_DISP_CURS_CLASS 0x0000917a
-#define NVF0_DISP_CURS_CLASS 0x0000927a
-#define GM107_DISP_CURS_CLASS 0x0000947a
-
-struct nv50_display_curs_class {
- u32 head;
-};
-
-/* 507b: NV50_DISP_OIMM
- * 827b: NV84_DISP_OIMM
- * 837b: NVA0_DISP_OIMM
- * 887b: NV94_DISP_OIMM
- * 857b: NVA3_DISP_OIMM
- * 907b: NVD0_DISP_OIMM
- * 917b: NVE0_DISP_OIMM
- * 927b: NVE0_DISP_OIMM
- * 947b: GM107_DISP_OIMM
- */
-
-#define NV50_DISP_OIMM_CLASS 0x0000507b
-#define NV84_DISP_OIMM_CLASS 0x0000827b
-#define NVA0_DISP_OIMM_CLASS 0x0000837b
-#define NV94_DISP_OIMM_CLASS 0x0000887b
-#define NVA3_DISP_OIMM_CLASS 0x0000857b
-#define NVD0_DISP_OIMM_CLASS 0x0000907b
-#define NVE0_DISP_OIMM_CLASS 0x0000917b
-#define NVF0_DISP_OIMM_CLASS 0x0000927b
-#define GM107_DISP_OIMM_CLASS 0x0000947b
-
-struct nv50_display_oimm_class {
- u32 head;
-};
-
-/* 507c: NV50_DISP_SYNC
- * 827c: NV84_DISP_SYNC
- * 837c: NVA0_DISP_SYNC
- * 887c: NV94_DISP_SYNC
- * 857c: NVA3_DISP_SYNC
- * 907c: NVD0_DISP_SYNC
- * 917c: NVE0_DISP_SYNC
- * 927c: NVF0_DISP_SYNC
- * 947c: GM107_DISP_SYNC
- */
-
-#define NV50_DISP_SYNC_CLASS 0x0000507c
-#define NV84_DISP_SYNC_CLASS 0x0000827c
-#define NVA0_DISP_SYNC_CLASS 0x0000837c
-#define NV94_DISP_SYNC_CLASS 0x0000887c
-#define NVA3_DISP_SYNC_CLASS 0x0000857c
-#define NVD0_DISP_SYNC_CLASS 0x0000907c
-#define NVE0_DISP_SYNC_CLASS 0x0000917c
-#define NVF0_DISP_SYNC_CLASS 0x0000927c
-#define GM107_DISP_SYNC_CLASS 0x0000947c
-
-struct nv50_display_sync_class {
- u32 pushbuf;
- u32 head;
-};
-
-/* 507d: NV50_DISP_MAST
- * 827d: NV84_DISP_MAST
- * 837d: NVA0_DISP_MAST
- * 887d: NV94_DISP_MAST
- * 857d: NVA3_DISP_MAST
- * 907d: NVD0_DISP_MAST
- * 917d: NVE0_DISP_MAST
- * 927d: NVF0_DISP_MAST
- * 947d: GM107_DISP_MAST
- */
-
-#define NV50_DISP_MAST_CLASS 0x0000507d
-#define NV84_DISP_MAST_CLASS 0x0000827d
-#define NVA0_DISP_MAST_CLASS 0x0000837d
-#define NV94_DISP_MAST_CLASS 0x0000887d
-#define NVA3_DISP_MAST_CLASS 0x0000857d
-#define NVD0_DISP_MAST_CLASS 0x0000907d
-#define NVE0_DISP_MAST_CLASS 0x0000917d
-#define NVF0_DISP_MAST_CLASS 0x0000927d
-#define GM107_DISP_MAST_CLASS 0x0000947d
-
-struct nv50_display_mast_class {
- u32 pushbuf;
-};
-
-/* 507e: NV50_DISP_OVLY
- * 827e: NV84_DISP_OVLY
- * 837e: NVA0_DISP_OVLY
- * 887e: NV94_DISP_OVLY
- * 857e: NVA3_DISP_OVLY
- * 907e: NVD0_DISP_OVLY
- * 917e: NVE0_DISP_OVLY
- * 927e: NVF0_DISP_OVLY
- * 947e: GM107_DISP_OVLY
- */
-
-#define NV50_DISP_OVLY_CLASS 0x0000507e
-#define NV84_DISP_OVLY_CLASS 0x0000827e
-#define NVA0_DISP_OVLY_CLASS 0x0000837e
-#define NV94_DISP_OVLY_CLASS 0x0000887e
-#define NVA3_DISP_OVLY_CLASS 0x0000857e
-#define NVD0_DISP_OVLY_CLASS 0x0000907e
-#define NVE0_DISP_OVLY_CLASS 0x0000917e
-#define NVF0_DISP_OVLY_CLASS 0x0000927e
-#define GM107_DISP_OVLY_CLASS 0x0000947e
-
-struct nv50_display_ovly_class {
- u32 pushbuf;
- u32 head;
-};
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h
index c66eac513803..1794a05205d8 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/client.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/client.h
@@ -10,6 +10,11 @@ struct nouveau_client {
char name[32];
u32 debug;
struct nouveau_vm *vm;
+ bool super;
+ void *data;
+
+ int (*ntfy)(const void *, u32, const void *, u32);
+ struct nvkm_client_notify *notify[16];
};
static inline struct nouveau_client *
@@ -43,4 +48,10 @@ int nouveau_client_init(struct nouveau_client *);
int nouveau_client_fini(struct nouveau_client *, bool suspend);
const char *nouveau_client_name(void *obj);
+int nvkm_client_notify_new(struct nouveau_client *, struct nvkm_event *,
+ void *data, u32 size);
+int nvkm_client_notify_del(struct nouveau_client *, int index);
+int nvkm_client_notify_get(struct nouveau_client *, int index);
+int nvkm_client_notify_put(struct nouveau_client *, int index);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h
index a8a9a9cf16cb..8743766454a5 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/device.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/device.h
@@ -4,6 +4,7 @@
#include <core/object.h>
#include <core/subdev.h>
#include <core/engine.h>
+#include <core/event.h>
enum nv_subdev_type {
NVDEV_ENGINE_DEVICE,
@@ -28,7 +29,7 @@ enum nv_subdev_type {
NVDEV_SUBDEV_BUS,
NVDEV_SUBDEV_TIMER,
NVDEV_SUBDEV_FB,
- NVDEV_SUBDEV_LTCG,
+ NVDEV_SUBDEV_LTC,
NVDEV_SUBDEV_IBUS,
NVDEV_SUBDEV_INSTMEM,
NVDEV_SUBDEV_VM,
@@ -69,6 +70,8 @@ struct nouveau_device {
struct platform_device *platformdev;
u64 handle;
+ struct nvkm_event event;
+
const char *cfgopt;
const char *dbgopt;
const char *name;
@@ -84,7 +87,6 @@ struct nouveau_device {
NV_40 = 0x40,
NV_50 = 0x50,
NV_C0 = 0xc0,
- NV_D0 = 0xd0,
NV_E0 = 0xe0,
GM100 = 0x110,
} card_type;
@@ -93,8 +95,14 @@ struct nouveau_device {
struct nouveau_oclass *oclass[NVDEV_SUBDEV_NR];
struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
+
+ struct {
+ struct notifier_block nb;
+ } acpi;
};
+int nouveau_device_list(u64 *name, int size);
+
static inline struct nouveau_device *
nv_device(void *obj)
{
@@ -162,12 +170,6 @@ nv_device_resource_start(struct nouveau_device *device, unsigned int bar);
resource_size_t
nv_device_resource_len(struct nouveau_device *device, unsigned int bar);
-dma_addr_t
-nv_device_map_page(struct nouveau_device *device, struct page *page);
-
-void
-nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr);
-
int
nv_device_get_irq(struct nouveau_device *device, bool stall);
diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h
index ba3f1a76a815..51e55d03330a 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/event.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/event.h
@@ -1,47 +1,34 @@
#ifndef __NVKM_EVENT_H__
#define __NVKM_EVENT_H__
-/* return codes from event handlers */
-#define NVKM_EVENT_DROP 0
-#define NVKM_EVENT_KEEP 1
+#include <core/notify.h>
-/* nouveau_eventh.flags bit #s */
-#define NVKM_EVENT_ENABLE 0
-
-struct nouveau_eventh {
- struct nouveau_event *event;
- struct list_head head;
- unsigned long flags;
- u32 types;
- int index;
- int (*func)(void *, u32, int);
- void *priv;
+struct nvkm_event_func {
+ int (*ctor)(void *data, u32 size, struct nvkm_notify *);
+ void (*send)(void *data, u32 size, struct nvkm_notify *);
+ void (*init)(struct nvkm_event *, int type, int index);
+ void (*fini)(struct nvkm_event *, int type, int index);
};
-struct nouveau_event {
- void *priv;
- int (*check)(struct nouveau_event *, u32 type, int index);
- void (*enable)(struct nouveau_event *, int type, int index);
- void (*disable)(struct nouveau_event *, int type, int index);
+struct nvkm_event {
+ const struct nvkm_event_func *func;
int types_nr;
int index_nr;
- spinlock_t list_lock;
- struct list_head *list;
spinlock_t refs_lock;
- int refs[];
+ spinlock_t list_lock;
+ struct list_head list;
+ int *refs;
};
-int nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **);
-void nouveau_event_destroy(struct nouveau_event **);
-void nouveau_event_trigger(struct nouveau_event *, u32 types, int index);
-
-int nouveau_event_new(struct nouveau_event *, u32 types, int index,
- int (*func)(void *, u32, int), void *,
- struct nouveau_eventh **);
-void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **);
-void nouveau_event_get(struct nouveau_eventh *);
-void nouveau_event_put(struct nouveau_eventh *);
+int nvkm_event_init(const struct nvkm_event_func *func,
+ int types_nr, int index_nr,
+ struct nvkm_event *);
+void nvkm_event_fini(struct nvkm_event *);
+void nvkm_event_get(struct nvkm_event *, u32 types, int index);
+void nvkm_event_put(struct nvkm_event *, u32 types, int index);
+void nvkm_event_send(struct nvkm_event *, u32 types, int index,
+ void *data, u32 size);
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/handle.h b/drivers/gpu/drm/nouveau/core/include/core/handle.h
index 363674cdf8ab..ceb67d770875 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/handle.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/handle.h
@@ -10,6 +10,9 @@ struct nouveau_handle {
u32 name;
u32 priv;
+ u8 route;
+ u64 token;
+
struct nouveau_handle *parent;
struct nouveau_object *object;
};
@@ -20,6 +23,11 @@ void nouveau_handle_destroy(struct nouveau_handle *);
int nouveau_handle_init(struct nouveau_handle *);
int nouveau_handle_fini(struct nouveau_handle *, bool suspend);
+int nouveau_handle_new(struct nouveau_object *, u32 parent, u32 handle,
+ u16 oclass, void *data, u32 size,
+ struct nouveau_object **);
+int nouveau_handle_del(struct nouveau_object *, u32 parent, u32 handle);
+
struct nouveau_object *
nouveau_handle_ref(struct nouveau_object *, u32 name);
diff --git a/drivers/gpu/drm/nouveau/core/include/core/ioctl.h b/drivers/gpu/drm/nouveau/core/include/core/ioctl.h
new file mode 100644
index 000000000000..ac7935c2474e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/core/ioctl.h
@@ -0,0 +1,6 @@
+#ifndef __NVKM_IOCTL_H__
+#define __NVKM_IOCTL_H__
+
+int nvkm_ioctl(struct nouveau_client *, bool, void *, u32, void **);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/notify.h b/drivers/gpu/drm/nouveau/core/include/core/notify.h
new file mode 100644
index 000000000000..1262d8f020f3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/core/notify.h
@@ -0,0 +1,36 @@
+#ifndef __NVKM_NOTIFY_H__
+#define __NVKM_NOTIFY_H__
+
+struct nvkm_notify {
+ struct nvkm_event *event;
+ struct list_head head;
+#define NVKM_NOTIFY_USER 0
+#define NVKM_NOTIFY_WORK 1
+ unsigned long flags;
+ int block;
+#define NVKM_NOTIFY_DROP 0
+#define NVKM_NOTIFY_KEEP 1
+ int (*func)(struct nvkm_notify *);
+
+ /* set by nvkm_event ctor */
+ u32 types;
+ int index;
+ u32 size;
+
+ struct work_struct work;
+ /* this is const for a *very* good reason - the data might be on the
+ * stack from an irq handler. if you're not core/notify.c then you
+ * should probably think twice before casting it away...
+ */
+ const void *data;
+};
+
+int nvkm_notify_init(struct nvkm_event *, int (*func)(struct nvkm_notify *),
+ bool work, void *data, u32 size, u32 reply,
+ struct nvkm_notify *);
+void nvkm_notify_fini(struct nvkm_notify *);
+void nvkm_notify_get(struct nvkm_notify *);
+void nvkm_notify_put(struct nvkm_notify *);
+void nvkm_notify_send(struct nvkm_notify *, void *data, u32 size);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h
index 62e68baef087..d7039482d6fd 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/object.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/object.h
@@ -48,6 +48,10 @@ void nouveau_object_destroy(struct nouveau_object *);
int nouveau_object_init(struct nouveau_object *);
int nouveau_object_fini(struct nouveau_object *, bool suspend);
+int _nouveau_object_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+
extern struct nouveau_ofuncs nouveau_object_ofuncs;
/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
@@ -78,6 +82,7 @@ struct nouveau_omthds {
int (*call)(struct nouveau_object *, u32, void *, u32);
};
+struct nvkm_event;
struct nouveau_ofuncs {
int (*ctor)(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *data, u32 size,
@@ -85,6 +90,9 @@ struct nouveau_ofuncs {
void (*dtor)(struct nouveau_object *);
int (*init)(struct nouveau_object *);
int (*fini)(struct nouveau_object *, bool suspend);
+ int (*mthd)(struct nouveau_object *, u32, void *, u32);
+ int (*ntfy)(struct nouveau_object *, u32, struct nvkm_event **);
+ int (* map)(struct nouveau_object *, u64 *, u32 *);
u8 (*rd08)(struct nouveau_object *, u64 offset);
u16 (*rd16)(struct nouveau_object *, u64 offset);
u32 (*rd32)(struct nouveau_object *, u64 offset);
@@ -106,10 +114,6 @@ void nouveau_object_ref(struct nouveau_object *, struct nouveau_object **);
int nouveau_object_inc(struct nouveau_object *);
int nouveau_object_dec(struct nouveau_object *, bool suspend);
-int nouveau_object_new(struct nouveau_object *, u32 parent, u32 handle,
- u16 oclass, void *data, u32 size,
- struct nouveau_object **);
-int nouveau_object_del(struct nouveau_object *, u32 parent, u32 handle);
void nouveau_object_debug(void);
static inline int
@@ -199,4 +203,21 @@ nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
return 0;
}
+#include <core/handle.h>
+
+static inline int
+nouveau_object_new(struct nouveau_object *client, u32 parent, u32 handle,
+ u16 oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ return nouveau_handle_new(client, parent, handle, oclass,
+ data, size, pobject);
+}
+
+static inline int
+nouveau_object_del(struct nouveau_object *client, u32 parent, u32 handle)
+{
+ return nouveau_handle_del(client, parent, handle);
+}
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/parent.h b/drivers/gpu/drm/nouveau/core/include/core/parent.h
index 9f5ea900ff00..12da418ec70a 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/parent.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/parent.h
@@ -57,5 +57,6 @@ void _nouveau_parent_dtor(struct nouveau_object *);
int nouveau_parent_sclass(struct nouveau_object *, u16 handle,
struct nouveau_object **pengine,
struct nouveau_oclass **poclass);
+int nouveau_parent_lclass(struct nouveau_object *, u32 *, int);
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/printk.h b/drivers/gpu/drm/nouveau/core/include/core/printk.h
index 0f9a37bd32b0..451b6ed20b7e 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/printk.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/printk.h
@@ -21,6 +21,7 @@ nv_printk_(struct nouveau_object *, int, const char *, ...);
#define nv_debug(o,f,a...) nv_printk((o), DEBUG, f, ##a)
#define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a)
#define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a)
+#define nv_ioctl(o,f,a...) nv_trace(nouveau_client(o), "ioctl: "f, ##a)
#define nv_assert(f,a...) do { \
if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG) \
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
index fde842896806..7a64f347b385 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
@@ -6,20 +6,13 @@
#include <core/device.h>
#include <core/event.h>
-enum nvkm_hpd_event {
- NVKM_HPD_PLUG = 1,
- NVKM_HPD_UNPLUG = 2,
- NVKM_HPD_IRQ = 4,
- NVKM_HPD = (NVKM_HPD_PLUG | NVKM_HPD_UNPLUG | NVKM_HPD_IRQ)
-};
-
struct nouveau_disp {
struct nouveau_engine base;
struct list_head outp;
- struct nouveau_event *hpd;
- struct nouveau_event *vblank;
+ struct nvkm_event hpd;
+ struct nvkm_event vblank;
};
static inline struct nouveau_disp *
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
index b28914ed1752..1b283a7b78e6 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/dmaobj.h
@@ -12,37 +12,20 @@ struct nouveau_dmaobj {
u32 access;
u64 start;
u64 limit;
- u32 conf0;
};
struct nouveau_dmaeng {
struct nouveau_engine base;
/* creates a "physical" dma object from a struct nouveau_dmaobj */
- int (*bind)(struct nouveau_dmaeng *dmaeng,
+ int (*bind)(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
- struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **);
};
-#define nouveau_dmaeng_create(p,e,c,d) \
- nouveau_engine_create((p), (e), (c), true, "DMAOBJ", "dmaobj", (d))
-#define nouveau_dmaeng_destroy(p) \
- nouveau_engine_destroy(&(p)->base)
-#define nouveau_dmaeng_init(p) \
- nouveau_engine_init(&(p)->base)
-#define nouveau_dmaeng_fini(p,s) \
- nouveau_engine_fini(&(p)->base, (s))
-
-#define _nouveau_dmaeng_dtor _nouveau_engine_dtor
-#define _nouveau_dmaeng_init _nouveau_engine_init
-#define _nouveau_dmaeng_fini _nouveau_engine_fini
-
-extern struct nouveau_oclass nv04_dmaeng_oclass;
-extern struct nouveau_oclass nv50_dmaeng_oclass;
-extern struct nouveau_oclass nvc0_dmaeng_oclass;
-extern struct nouveau_oclass nvd0_dmaeng_oclass;
-
-extern struct nouveau_oclass nouveau_dmaobj_sclass[];
+extern struct nouveau_oclass *nv04_dmaeng_oclass;
+extern struct nouveau_oclass *nv50_dmaeng_oclass;
+extern struct nouveau_oclass *nvc0_dmaeng_oclass;
+extern struct nouveau_oclass *nvd0_dmaeng_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
index b639eb2c74ff..e5e4d930b2c2 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h
@@ -4,12 +4,14 @@
#include <core/namedb.h>
#include <core/gpuobj.h>
#include <core/engine.h>
+#include <core/event.h>
struct nouveau_fifo_chan {
struct nouveau_namedb base;
struct nouveau_dmaobj *pushdma;
struct nouveau_gpuobj *pushgpu;
void __iomem *user;
+ u64 addr;
u32 size;
u16 chid;
atomic_t refcnt; /* NV04_NVSW_SET_REF */
@@ -40,8 +42,10 @@ void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *);
#define _nouveau_fifo_channel_fini _nouveau_namedb_fini
void _nouveau_fifo_channel_dtor(struct nouveau_object *);
+int _nouveau_fifo_channel_map(struct nouveau_object *, u64 *, u32 *);
u32 _nouveau_fifo_channel_rd32(struct nouveau_object *, u64);
void _nouveau_fifo_channel_wr32(struct nouveau_object *, u64, u32);
+int _nouveau_fifo_channel_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
struct nouveau_fifo_base {
struct nouveau_gpuobj base;
@@ -65,8 +69,8 @@ struct nouveau_fifo_base {
struct nouveau_fifo {
struct nouveau_engine base;
- struct nouveau_event *cevent; /* channel creation event */
- struct nouveau_event *uevent; /* async user trigger */
+ struct nvkm_event cevent; /* channel creation event */
+ struct nvkm_event uevent; /* async user trigger */
struct nouveau_object **channel;
spinlock_t lock;
@@ -112,6 +116,9 @@ extern struct nouveau_oclass *nve0_fifo_oclass;
extern struct nouveau_oclass *gk20a_fifo_oclass;
extern struct nouveau_oclass *nv108_fifo_oclass;
+int nouveau_fifo_uevent_ctor(void *, u32, struct nvkm_notify *);
+void nouveau_fifo_uevent(struct nouveau_fifo *);
+
void nv04_fifo_intr(struct nouveau_subdev *);
int nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *);
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
index 8c1d4772da0c..d5055570d01b 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h
@@ -70,6 +70,7 @@ extern struct nouveau_oclass *nvd9_graph_oclass;
extern struct nouveau_oclass *nve4_graph_oclass;
extern struct nouveau_oclass *gk20a_graph_oclass;
extern struct nouveau_oclass *nvf0_graph_oclass;
+extern struct nouveau_oclass *gk110b_graph_oclass;
extern struct nouveau_oclass *nv108_graph_oclass;
extern struct nouveau_oclass *gm107_graph_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
index 49b0024910fe..88cc812baaa3 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h
@@ -4,7 +4,6 @@
#include <core/device.h>
#include <core/engine.h>
#include <core/engctx.h>
-#include <core/class.h>
struct nouveau_perfdom;
struct nouveau_perfctr;
diff --git a/drivers/gpu/drm/nouveau/core/include/nvif/class.h b/drivers/gpu/drm/nouveau/core/include/nvif/class.h
new file mode 120000
index 000000000000..f1ac4859edd4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/nvif/class.h
@@ -0,0 +1 @@
+../../../nvif/class.h \ No newline at end of file
diff --git a/drivers/gpu/drm/nouveau/core/include/nvif/event.h b/drivers/gpu/drm/nouveau/core/include/nvif/event.h
new file mode 120000
index 000000000000..1b798538a725
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/nvif/event.h
@@ -0,0 +1 @@
+../../../nvif/event.h \ No newline at end of file
diff --git a/drivers/gpu/drm/nouveau/core/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/core/include/nvif/ioctl.h
new file mode 120000
index 000000000000..8569c86907c5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/nvif/ioctl.h
@@ -0,0 +1 @@
+../../../nvif/ioctl.h \ No newline at end of file
diff --git a/drivers/gpu/drm/nouveau/core/include/nvif/unpack.h b/drivers/gpu/drm/nouveau/core/include/nvif/unpack.h
new file mode 120000
index 000000000000..69d99292bca4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/nvif/unpack.h
@@ -0,0 +1 @@
+../../../nvif/unpack.h \ No newline at end of file
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
index 9faa98e67ad8..be037fac534c 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h
@@ -20,6 +20,9 @@ struct nouveau_bar {
u32 flags, struct nouveau_vma *);
void (*unmap)(struct nouveau_bar *, struct nouveau_vma *);
void (*flush)(struct nouveau_bar *);
+
+ /* whether the BAR supports to be ioremapped WC or should be uncached */
+ bool iomap_uncached;
};
static inline struct nouveau_bar *
@@ -30,5 +33,6 @@ nouveau_bar(void *obj)
extern struct nouveau_oclass nv50_bar_oclass;
extern struct nouveau_oclass nvc0_bar_oclass;
+extern struct nouveau_oclass gk20a_bar_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
index c01e29c9f89a..a5ca00dd2f61 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
@@ -71,8 +71,15 @@ struct nouveau_clock {
struct list_head states;
int state_nr;
+ struct work_struct work;
+ wait_queue_head_t wait;
+ atomic_t waiting;
+
+ struct nvkm_notify pwrsrc_ntfy;
+ int pwrsrc;
int pstate; /* current */
- int ustate; /* user-requested (-1 disabled, -2 perfmon) */
+ int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
+ int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
int astate; /* perfmon adjustment (base) */
int tstate; /* thermal adjustment (max-) */
int dstate; /* display adjustment (min+) */
@@ -108,8 +115,9 @@ struct nouveau_clocks {
int mdiv;
};
-#define nouveau_clock_create(p,e,o,i,r,d) \
- nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
+#define nouveau_clock_create(p,e,o,i,r,s,n,d) \
+ nouveau_clock_create_((p), (e), (o), (i), (r), (s), (n), sizeof(**d), \
+ (void **)d)
#define nouveau_clock_destroy(p) ({ \
struct nouveau_clock *clk = (p); \
_nouveau_clock_dtor(nv_object(clk)); \
@@ -118,15 +126,18 @@ struct nouveau_clocks {
struct nouveau_clock *clk = (p); \
_nouveau_clock_init(nv_object(clk)); \
})
-#define nouveau_clock_fini(p,s) \
- nouveau_subdev_fini(&(p)->base, (s))
+#define nouveau_clock_fini(p,s) ({ \
+ struct nouveau_clock *clk = (p); \
+ _nouveau_clock_fini(nv_object(clk), (s)); \
+})
int nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *,
- struct nouveau_clocks *, bool, int, void **);
+ struct nouveau_clocks *, struct nouveau_pstate *,
+ int, bool, int, void **);
void _nouveau_clock_dtor(struct nouveau_object *);
-int _nouveau_clock_init(struct nouveau_object *);
-#define _nouveau_clock_fini _nouveau_subdev_fini
+int _nouveau_clock_init(struct nouveau_object *);
+int _nouveau_clock_fini(struct nouveau_object *, bool);
extern struct nouveau_oclass nv04_clock_oclass;
extern struct nouveau_oclass nv40_clock_oclass;
@@ -136,6 +147,7 @@ extern struct nouveau_oclass *nvaa_clock_oclass;
extern struct nouveau_oclass nva3_clock_oclass;
extern struct nouveau_oclass nvc0_clock_oclass;
extern struct nouveau_oclass nve0_clock_oclass;
+extern struct nouveau_oclass gk20a_clock_oclass;
int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq);
int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
@@ -145,7 +157,7 @@ int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
int clk, struct nouveau_pll_vals *);
-int nouveau_clock_ustate(struct nouveau_clock *, int req);
+int nouveau_clock_ustate(struct nouveau_clock *, int req, int pwr);
int nouveau_clock_astate(struct nouveau_clock *, int req, int rel);
int nouveau_clock_dstate(struct nouveau_clock *, int req, int rel);
int nouveau_clock_tstate(struct nouveau_clock *, int req, int rel);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
index 612d82ab683d..b73733d21cc7 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
@@ -8,16 +8,22 @@
#include <subdev/bios.h>
#include <subdev/bios/gpio.h>
-enum nvkm_gpio_event {
- NVKM_GPIO_HI = 1,
- NVKM_GPIO_LO = 2,
- NVKM_GPIO_TOGGLED = (NVKM_GPIO_HI | NVKM_GPIO_LO),
+struct nvkm_gpio_ntfy_req {
+#define NVKM_GPIO_HI 0x01
+#define NVKM_GPIO_LO 0x02
+#define NVKM_GPIO_TOGGLED 0x03
+ u8 mask;
+ u8 line;
+};
+
+struct nvkm_gpio_ntfy_rep {
+ u8 mask;
};
struct nouveau_gpio {
struct nouveau_subdev base;
- struct nouveau_event *events;
+ struct nvkm_event event;
void (*reset)(struct nouveau_gpio *, u8 func);
int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line,
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
index 825f7bb46b67..1b937c2c25ae 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
@@ -14,15 +14,18 @@
#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)
#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8)
-enum nvkm_i2c_event {
- NVKM_I2C_PLUG = 1,
- NVKM_I2C_UNPLUG = 2,
- NVKM_I2C_IRQ = 4,
- NVKM_I2C_DONE = 8,
- NVKM_I2C_ANY = (NVKM_I2C_PLUG |
- NVKM_I2C_UNPLUG |
- NVKM_I2C_IRQ |
- NVKM_I2C_DONE),
+struct nvkm_i2c_ntfy_req {
+#define NVKM_I2C_PLUG 0x01
+#define NVKM_I2C_UNPLUG 0x02
+#define NVKM_I2C_IRQ 0x04
+#define NVKM_I2C_DONE 0x08
+#define NVKM_I2C_ANY 0x0f
+ u8 mask;
+ u8 port;
+};
+
+struct nvkm_i2c_ntfy_rep {
+ u8 mask;
};
struct nouveau_i2c_port {
@@ -56,7 +59,7 @@ struct nouveau_i2c_board_info {
struct nouveau_i2c {
struct nouveau_subdev base;
- struct nouveau_event *ntfy;
+ struct nvkm_event event;
struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);
struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
new file mode 100644
index 000000000000..b909a7363f6b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
@@ -0,0 +1,35 @@
+#ifndef __NOUVEAU_LTC_H__
+#define __NOUVEAU_LTC_H__
+
+#include <core/subdev.h>
+#include <core/device.h>
+
+#define NOUVEAU_LTC_MAX_ZBC_CNT 16
+
+struct nouveau_mm_node;
+
+struct nouveau_ltc {
+ struct nouveau_subdev base;
+
+ int (*tags_alloc)(struct nouveau_ltc *, u32 count,
+ struct nouveau_mm_node **);
+ void (*tags_free)(struct nouveau_ltc *, struct nouveau_mm_node **);
+ void (*tags_clear)(struct nouveau_ltc *, u32 first, u32 count);
+
+ int zbc_min;
+ int zbc_max;
+ int (*zbc_color_get)(struct nouveau_ltc *, int index, const u32[4]);
+ int (*zbc_depth_get)(struct nouveau_ltc *, int index, const u32);
+};
+
+static inline struct nouveau_ltc *
+nouveau_ltc(void *obj)
+{
+ return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTC];
+}
+
+extern struct nouveau_oclass *gf100_ltc_oclass;
+extern struct nouveau_oclass *gk104_ltc_oclass;
+extern struct nouveau_oclass *gm107_ltc_oclass;
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
deleted file mode 100644
index c9c1950b7743..000000000000
--- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __NOUVEAU_LTCG_H__
-#define __NOUVEAU_LTCG_H__
-
-#include <core/subdev.h>
-#include <core/device.h>
-
-struct nouveau_mm_node;
-
-struct nouveau_ltcg {
- struct nouveau_subdev base;
-
- int (*tags_alloc)(struct nouveau_ltcg *, u32 count,
- struct nouveau_mm_node **);
- void (*tags_free)(struct nouveau_ltcg *, struct nouveau_mm_node **);
- void (*tags_clear)(struct nouveau_ltcg *, u32 first, u32 count);
-};
-
-static inline struct nouveau_ltcg *
-nouveau_ltcg(void *obj)
-{
- return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_LTCG];
-}
-
-#define nouveau_ltcg_create(p,e,o,d) \
- nouveau_subdev_create_((p), (e), (o), 0, "PLTCG", "level2", \
- sizeof(**d), (void **)d)
-#define nouveau_ltcg_destroy(p) \
- nouveau_subdev_destroy(&(p)->base)
-#define nouveau_ltcg_init(p) \
- nouveau_subdev_init(&(p)->base)
-#define nouveau_ltcg_fini(p,s) \
- nouveau_subdev_fini(&(p)->base, (s))
-
-#define _nouveau_ltcg_dtor _nouveau_subdev_dtor
-#define _nouveau_ltcg_init _nouveau_subdev_init
-#define _nouveau_ltcg_fini _nouveau_subdev_fini
-
-extern struct nouveau_oclass *gf100_ltcg_oclass;
-extern struct nouveau_oclass *gm107_ltcg_oclass;
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
index 72b176831be6..568e4dfc5e9e 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h
@@ -4,15 +4,11 @@
#include <core/subdev.h>
#include <core/device.h>
-struct nouveau_mc_intr {
- u32 stat;
- u32 unit;
-};
-
struct nouveau_mc {
struct nouveau_subdev base;
bool use_msi;
unsigned int irq;
+ void (*unk260)(struct nouveau_mc *, u32);
};
static inline struct nouveau_mc *
@@ -21,30 +17,6 @@ nouveau_mc(void *obj)
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
}
-#define nouveau_mc_create(p,e,o,d) \
- nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_mc_destroy(p) ({ \
- struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
-})
-#define nouveau_mc_init(p) ({ \
- struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc)); \
-})
-#define nouveau_mc_fini(p,s) ({ \
- struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s)); \
-})
-
-int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
- struct nouveau_oclass *, int, void **);
-void _nouveau_mc_dtor(struct nouveau_object *);
-int _nouveau_mc_init(struct nouveau_object *);
-int _nouveau_mc_fini(struct nouveau_object *, bool);
-
-struct nouveau_mc_oclass {
- struct nouveau_oclass base;
- const struct nouveau_mc_intr *intr;
- void (*msi_rearm)(struct nouveau_mc *);
-};
-
extern struct nouveau_oclass *nv04_mc_oclass;
extern struct nouveau_oclass *nv40_mc_oclass;
extern struct nouveau_oclass *nv44_mc_oclass;
@@ -54,5 +26,6 @@ extern struct nouveau_oclass *nv94_mc_oclass;
extern struct nouveau_oclass *nv98_mc_oclass;
extern struct nouveau_oclass *nvc0_mc_oclass;
extern struct nouveau_oclass *nvc3_mc_oclass;
+extern struct nouveau_oclass *gk20a_mc_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h b/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h
index c5c92cbed33f..f73feec151db 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h
@@ -8,18 +8,6 @@ struct nouveau_pwr {
struct nouveau_subdev base;
struct {
- u32 limit;
- u32 *data;
- u32 size;
- } code;
-
- struct {
- u32 limit;
- u32 *data;
- u32 size;
- } data;
-
- struct {
u32 base;
u32 size;
} send;
@@ -35,7 +23,8 @@ struct nouveau_pwr {
u32 data[2];
} recv;
- int (*message)(struct nouveau_pwr *, u32[2], u32, u32, u32, u32);
+ int (*message)(struct nouveau_pwr *, u32[2], u32, u32, u32, u32);
+ void (*pgob)(struct nouveau_pwr *, bool);
};
static inline struct nouveau_pwr *
@@ -44,29 +33,11 @@ nouveau_pwr(void *obj)
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_PWR];
}
-#define nouveau_pwr_create(p, e, o, d) \
- nouveau_pwr_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_pwr_destroy(p) \
- nouveau_subdev_destroy(&(p)->base)
-#define nouveau_pwr_init(p) ({ \
- struct nouveau_pwr *ppwr = (p); \
- _nouveau_pwr_init(nv_object(ppwr)); \
-})
-#define nouveau_pwr_fini(p,s) ({ \
- struct nouveau_pwr *ppwr = (p); \
- _nouveau_pwr_fini(nv_object(ppwr), (s)); \
-})
-
-int nouveau_pwr_create_(struct nouveau_object *, struct nouveau_object *,
- struct nouveau_oclass *, int, void **);
-#define _nouveau_pwr_dtor _nouveau_subdev_dtor
-int _nouveau_pwr_init(struct nouveau_object *);
-int _nouveau_pwr_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nva3_pwr_oclass;
-extern struct nouveau_oclass nvc0_pwr_oclass;
-extern struct nouveau_oclass nvd0_pwr_oclass;
-extern struct nouveau_oclass nv108_pwr_oclass;
+extern struct nouveau_oclass *nva3_pwr_oclass;
+extern struct nouveau_oclass *nvc0_pwr_oclass;
+extern struct nouveau_oclass *nvd0_pwr_oclass;
+extern struct nouveau_oclass *gk104_pwr_oclass;
+extern struct nouveau_oclass *nv108_pwr_oclass;
/* interface to MEMX process running on PPWR */
struct nouveau_memx;
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h
index d0ced94ca54c..ccfa21d72ddc 100644
--- a/drivers/gpu/drm/nouveau/core/os.h
+++ b/drivers/gpu/drm/nouveau/core/os.h
@@ -21,6 +21,8 @@
#include <linux/interrupt.h>
#include <linux/log2.h>
#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
+#include <linux/clk.h>
#include <asm/unaligned.h>
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
index 73b1ed20c8d5..8bcbdf39cfb2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
@@ -99,8 +99,13 @@ nouveau_bar_alloc(struct nouveau_bar *bar, struct nouveau_object *parent,
struct nouveau_mem *mem, struct nouveau_object **pobject)
{
struct nouveau_object *engine = nv_object(bar);
- return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass,
- mem, 0, pobject);
+ int ret = -ENOMEM;
+ if (bar->iomem) {
+ ret = nouveau_object_ctor(parent, engine,
+ &nouveau_barobj_oclass,
+ mem, 0, pobject);
+ }
+ return ret;
}
int
@@ -118,9 +123,12 @@ nouveau_bar_create_(struct nouveau_object *parent,
if (ret)
return ret;
- if (nv_device_resource_len(device, 3) != 0)
+ if (nv_device_resource_len(device, 3) != 0) {
bar->iomem = ioremap(nv_device_resource_start(device, 3),
nv_device_resource_len(device, 3));
+ if (!bar->iomem)
+ nv_warn(bar, "PRAMIN ioremap failed\n");
+ }
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c
new file mode 100644
index 000000000000..bf877af9d3bd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/gk20a.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <subdev/bar.h>
+
+#include "priv.h"
+
+int
+gk20a_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_bar *bar;
+ int ret;
+
+ ret = nvc0_bar_ctor(parent, engine, oclass, data, size, pobject);
+ if (ret)
+ return ret;
+
+ bar = (struct nouveau_bar *)*pobject;
+ bar->iomap_uncached = true;
+
+ return 0;
+}
+
+struct nouveau_oclass
+gk20a_bar_oclass = {
+ .handle = NV_SUBDEV(BAR, 0xea),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gk20a_bar_ctor,
+ .dtor = nvc0_bar_dtor,
+ .init = nvc0_bar_init,
+ .fini = _nouveau_bar_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index ca8139b9ab27..0a44459844e3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -133,7 +133,7 @@ nvc0_bar_init_vm(struct nvc0_bar_priv *priv, struct nvc0_bar_priv_vm *bar_vm,
return 0;
}
-static int
+int
nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
@@ -169,7 +169,7 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return 0;
}
-static void
+void
nvc0_bar_dtor(struct nouveau_object *object)
{
struct nvc0_bar_priv *priv = (void *)object;
@@ -188,7 +188,7 @@ nvc0_bar_dtor(struct nouveau_object *object)
nouveau_bar_destroy(&priv->base);
}
-static int
+int
nvc0_bar_init(struct nouveau_object *object)
{
struct nvc0_bar_priv *priv = (void *)object;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
index ffad8f337ead..3ee8b1476d00 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
@@ -23,4 +23,10 @@ int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
void nv84_bar_flush(struct nouveau_bar *);
+int nvc0_bar_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void nvc0_bar_dtor(struct nouveau_object *);
+int nvc0_bar_init(struct nouveau_object *);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
index 22351f594d2a..a276a711294a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c
@@ -90,16 +90,20 @@ nouveau_cstate_prog(struct nouveau_clock *clk,
cstate = &pstate->base;
}
- ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
- if (ret && ret != -ENODEV) {
- nv_error(clk, "failed to raise fan speed: %d\n", ret);
- return ret;
+ if (ptherm) {
+ ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1);
+ if (ret && ret != -ENODEV) {
+ nv_error(clk, "failed to raise fan speed: %d\n", ret);
+ return ret;
+ }
}
- ret = volt->set_id(volt, cstate->voltage, +1);
- if (ret && ret != -ENODEV) {
- nv_error(clk, "failed to raise voltage: %d\n", ret);
- return ret;
+ if (volt) {
+ ret = volt->set_id(volt, cstate->voltage, +1);
+ if (ret && ret != -ENODEV) {
+ nv_error(clk, "failed to raise voltage: %d\n", ret);
+ return ret;
+ }
}
ret = clk->calc(clk, cstate);
@@ -108,13 +112,17 @@ nouveau_cstate_prog(struct nouveau_clock *clk,
clk->tidy(clk);
}
- ret = volt->set_id(volt, cstate->voltage, -1);
- if (ret && ret != -ENODEV)
- nv_error(clk, "failed to lower voltage: %d\n", ret);
+ if (volt) {
+ ret = volt->set_id(volt, cstate->voltage, -1);
+ if (ret && ret != -ENODEV)
+ nv_error(clk, "failed to lower voltage: %d\n", ret);
+ }
- ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
- if (ret && ret != -ENODEV)
- nv_error(clk, "failed to lower fan speed: %d\n", ret);
+ if (ptherm) {
+ ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1);
+ if (ret && ret != -ENODEV)
+ nv_error(clk, "failed to lower fan speed: %d\n", ret);
+ }
return 0;
}
@@ -194,16 +202,23 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
return nouveau_cstate_prog(clk, pstate, 0);
}
-static int
-nouveau_pstate_calc(struct nouveau_clock *clk)
+static void
+nouveau_pstate_work(struct work_struct *work)
{
- int pstate, ret = 0;
+ struct nouveau_clock *clk = container_of(work, typeof(*clk), work);
+ int pstate;
- nv_trace(clk, "P %d U %d A %d T %d D %d\n", clk->pstate,
- clk->ustate, clk->astate, clk->tstate, clk->dstate);
+ if (!atomic_xchg(&clk->waiting, 0))
+ return;
+ clk->pwrsrc = power_supply_is_system_supplied();
- if (clk->state_nr && clk->ustate != -1) {
- pstate = (clk->ustate < 0) ? clk->astate : clk->ustate;
+ nv_trace(clk, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
+ clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
+ clk->astate, clk->tstate, clk->dstate);
+
+ pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
+ if (clk->state_nr && pstate != -1) {
+ pstate = (pstate < 0) ? clk->astate : pstate;
pstate = min(pstate, clk->state_nr - 1 - clk->tstate);
pstate = max(pstate, clk->dstate);
} else {
@@ -211,9 +226,26 @@ nouveau_pstate_calc(struct nouveau_clock *clk)
}
nv_trace(clk, "-> %d\n", pstate);
- if (pstate != clk->pstate)
- ret = nouveau_pstate_prog(clk, pstate);
- return ret;
+ if (pstate != clk->pstate) {
+ int ret = nouveau_pstate_prog(clk, pstate);
+ if (ret) {
+ nv_error(clk, "error setting pstate %d: %d\n",
+ pstate, ret);
+ }
+ }
+
+ wake_up_all(&clk->wait);
+ nvkm_notify_get(&clk->pwrsrc_ntfy);
+}
+
+static int
+nouveau_pstate_calc(struct nouveau_clock *clk, bool wait)
+{
+ atomic_set(&clk->waiting, 1);
+ schedule_work(&clk->work);
+ if (wait)
+ wait_event(clk->wait, !atomic_read(&clk->waiting));
+ return 0;
}
static void
@@ -361,17 +393,40 @@ nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
req = i;
}
- clk->ustate = req;
- return 0;
+ return req + 2;
+}
+
+static int
+nouveau_clock_nstate(struct nouveau_clock *clk, const char *mode, int arglen)
+{
+ int ret = 1;
+
+ if (strncasecmpz(mode, "disabled", arglen)) {
+ char save = mode[arglen];
+ long v;
+
+ ((char *)mode)[arglen] = '\0';
+ if (!kstrtol(mode, 0, &v)) {
+ ret = nouveau_clock_ustate_update(clk, v);
+ if (ret < 0)
+ ret = 1;
+ }
+ ((char *)mode)[arglen] = save;
+ }
+
+ return ret - 2;
}
int
-nouveau_clock_ustate(struct nouveau_clock *clk, int req)
+nouveau_clock_ustate(struct nouveau_clock *clk, int req, int pwr)
{
int ret = nouveau_clock_ustate_update(clk, req);
- if (ret)
- return ret;
- return nouveau_pstate_calc(clk);
+ if (ret >= 0) {
+ if (ret -= 2, pwr) clk->ustate_ac = ret;
+ else clk->ustate_dc = ret;
+ return nouveau_pstate_calc(clk, true);
+ }
+ return ret;
}
int
@@ -381,7 +436,7 @@ nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->astate += rel;
clk->astate = min(clk->astate, clk->state_nr - 1);
clk->astate = max(clk->astate, 0);
- return nouveau_pstate_calc(clk);
+ return nouveau_pstate_calc(clk, true);
}
int
@@ -391,7 +446,7 @@ nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->tstate += rel;
clk->tstate = min(clk->tstate, 0);
clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
- return nouveau_pstate_calc(clk);
+ return nouveau_pstate_calc(clk, true);
}
int
@@ -401,12 +456,30 @@ nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->dstate += rel;
clk->dstate = min(clk->dstate, clk->state_nr - 1);
clk->dstate = max(clk->dstate, 0);
- return nouveau_pstate_calc(clk);
+ return nouveau_pstate_calc(clk, true);
+}
+
+static int
+nouveau_clock_pwrsrc(struct nvkm_notify *notify)
+{
+ struct nouveau_clock *clk =
+ container_of(notify, typeof(*clk), pwrsrc_ntfy);
+ nouveau_pstate_calc(clk, false);
+ return NVKM_NOTIFY_DROP;
}
/******************************************************************************
* subdev base class implementation
*****************************************************************************/
+
+int
+_nouveau_clock_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nouveau_clock *clk = (void *)object;
+ nvkm_notify_put(&clk->pwrsrc_ntfy);
+ return nouveau_subdev_fini(&clk->base, suspend);
+}
+
int
_nouveau_clock_init(struct nouveau_object *object)
{
@@ -414,6 +487,10 @@ _nouveau_clock_init(struct nouveau_object *object)
struct nouveau_clocks *clock = clk->domains;
int ret;
+ ret = nouveau_subdev_init(&clk->base);
+ if (ret)
+ return ret;
+
memset(&clk->bstate, 0x00, sizeof(clk->bstate));
INIT_LIST_HEAD(&clk->bstate.list);
clk->bstate.pstate = 0xff;
@@ -434,7 +511,7 @@ _nouveau_clock_init(struct nouveau_object *object)
clk->tstate = 0;
clk->dstate = 0;
clk->pstate = -1;
- nouveau_pstate_calc(clk);
+ nouveau_pstate_calc(clk, true);
return 0;
}
@@ -444,6 +521,8 @@ _nouveau_clock_dtor(struct nouveau_object *object)
struct nouveau_clock *clk = (void *)object;
struct nouveau_pstate *pstate, *temp;
+ nvkm_notify_fini(&clk->pwrsrc_ntfy);
+
list_for_each_entry_safe(pstate, temp, &clk->states, head) {
nouveau_pstate_del(pstate);
}
@@ -456,6 +535,7 @@ nouveau_clock_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass,
struct nouveau_clocks *clocks,
+ struct nouveau_pstate *pstates, int nb_pstates,
bool allow_reclock,
int length, void **object)
{
@@ -472,29 +552,46 @@ nouveau_clock_create_(struct nouveau_object *parent,
INIT_LIST_HEAD(&clk->states);
clk->domains = clocks;
- clk->ustate = -1;
+ clk->ustate_ac = -1;
+ clk->ustate_dc = -1;
+
+ INIT_WORK(&clk->work, nouveau_pstate_work);
+ init_waitqueue_head(&clk->wait);
+ atomic_set(&clk->waiting, 0);
- idx = 0;
- do {
- ret = nouveau_pstate_new(clk, idx++);
- } while (ret == 0);
+ /* If no pstates are provided, try and fetch them from the BIOS */
+ if (!pstates) {
+ idx = 0;
+ do {
+ ret = nouveau_pstate_new(clk, idx++);
+ } while (ret == 0);
+ } else {
+ for (idx = 0; idx < nb_pstates; idx++)
+ list_add_tail(&pstates[idx].head, &clk->states);
+ clk->state_nr = nb_pstates;
+ }
clk->allow_reclock = allow_reclock;
+ ret = nvkm_notify_init(&device->event, nouveau_clock_pwrsrc, true,
+ NULL, 0, 0, &clk->pwrsrc_ntfy);
+ if (ret)
+ return ret;
+
mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
if (mode) {
- if (!strncasecmpz(mode, "disabled", arglen)) {
- clk->ustate = -1;
- } else {
- char save = mode[arglen];
- long v;
-
- ((char *)mode)[arglen] = '\0';
- if (!kstrtol(mode, 0, &v))
- nouveau_clock_ustate_update(clk, v);
- ((char *)mode)[arglen] = save;
- }
+ clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
+ clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
}
+ mode = nouveau_stropt(device->cfgopt, "NvClkModeAC", &arglen);
+ if (mode)
+ clk->ustate_ac = nouveau_clock_nstate(clk, mode, arglen);
+
+ mode = nouveau_stropt(device->cfgopt, "NvClkModeDC", &arglen);
+ if (mode)
+ clk->ustate_dc = nouveau_clock_nstate(clk, mode, arglen);
+
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c
new file mode 100644
index 000000000000..425a8d5e9129
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/gk20a.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c
+ *
+ */
+
+#define MHZ (1000 * 1000)
+
+#define MASK(w) ((1 << w) - 1)
+
+#define SYS_GPCPLL_CFG_BASE 0x00137000
+#define GPC_BCASE_GPCPLL_CFG_BASE 0x00132800
+
+#define GPCPLL_CFG (SYS_GPCPLL_CFG_BASE + 0)
+#define GPCPLL_CFG_ENABLE BIT(0)
+#define GPCPLL_CFG_IDDQ BIT(1)
+#define GPCPLL_CFG_LOCK_DET_OFF BIT(4)
+#define GPCPLL_CFG_LOCK BIT(17)
+
+#define GPCPLL_COEFF (SYS_GPCPLL_CFG_BASE + 4)
+#define GPCPLL_COEFF_M_SHIFT 0
+#define GPCPLL_COEFF_M_WIDTH 8
+#define GPCPLL_COEFF_N_SHIFT 8
+#define GPCPLL_COEFF_N_WIDTH 8
+#define GPCPLL_COEFF_P_SHIFT 16
+#define GPCPLL_COEFF_P_WIDTH 6
+
+#define GPCPLL_CFG2 (SYS_GPCPLL_CFG_BASE + 0xc)
+#define GPCPLL_CFG2_SETUP2_SHIFT 16
+#define GPCPLL_CFG2_PLL_STEPA_SHIFT 24
+
+#define GPCPLL_CFG3 (SYS_GPCPLL_CFG_BASE + 0x18)
+#define GPCPLL_CFG3_PLL_STEPB_SHIFT 16
+
+#define GPCPLL_NDIV_SLOWDOWN (SYS_GPCPLL_CFG_BASE + 0x1c)
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT 0
+#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT 8
+#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT 16
+#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT 22
+#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT 31
+
+#define SEL_VCO (SYS_GPCPLL_CFG_BASE + 0x100)
+#define SEL_VCO_GPC2CLK_OUT_SHIFT 0
+
+#define GPC2CLK_OUT (SYS_GPCPLL_CFG_BASE + 0x250)
+#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH 1
+#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT 31
+#define GPC2CLK_OUT_SDIV14_INDIV4_MODE 1
+#define GPC2CLK_OUT_VCODIV_WIDTH 6
+#define GPC2CLK_OUT_VCODIV_SHIFT 8
+#define GPC2CLK_OUT_VCODIV1 0
+#define GPC2CLK_OUT_VCODIV_MASK (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \
+ GPC2CLK_OUT_VCODIV_SHIFT)
+#define GPC2CLK_OUT_BYPDIV_WIDTH 6
+#define GPC2CLK_OUT_BYPDIV_SHIFT 0
+#define GPC2CLK_OUT_BYPDIV31 0x3c
+#define GPC2CLK_OUT_INIT_MASK ((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \
+ GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\
+ | (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\
+ | (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT))
+#define GPC2CLK_OUT_INIT_VAL ((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \
+ GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \
+ | (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \
+ | (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT))
+
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG (GPC_BCASE_GPCPLL_CFG_BASE + 0xa0)
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT 24
+#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
+ (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
+
+#include <subdev/clock.h>
+#include <subdev/timer.h>
+
+#ifdef __KERNEL__
+#include <nouveau_platform.h>
+#endif
+
+static const u8 pl_to_div[] = {
+/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
+/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
+};
+
+/* All frequencies in Mhz */
+struct gk20a_clk_pllg_params {
+ u32 min_vco, max_vco;
+ u32 min_u, max_u;
+ u32 min_m, max_m;
+ u32 min_n, max_n;
+ u32 min_pl, max_pl;
+};
+
+static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
+ .min_vco = 1000, .max_vco = 1700,
+ .min_u = 12, .max_u = 38,
+ .min_m = 1, .max_m = 255,
+ .min_n = 8, .max_n = 255,
+ .min_pl = 1, .max_pl = 32,
+};
+
+struct gk20a_clock_priv {
+ struct nouveau_clock base;
+ const struct gk20a_clk_pllg_params *params;
+ u32 m, n, pl;
+ u32 parent_rate;
+};
+#define to_gk20a_clock(base) container_of(base, struct gk20a_clock_priv, base)
+
+static void
+gk20a_pllg_read_mnp(struct gk20a_clock_priv *priv)
+{
+ u32 val;
+
+ val = nv_rd32(priv, GPCPLL_COEFF);
+ priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+ priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH);
+ priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+}
+
+static u32
+gk20a_pllg_calc_rate(struct gk20a_clock_priv *priv)
+{
+ u32 rate;
+ u32 divider;
+
+ rate = priv->parent_rate * priv->n;
+ divider = priv->m * pl_to_div[priv->pl];
+ do_div(rate, divider);
+
+ return rate / 2;
+}
+
+static int
+gk20a_pllg_calc_mnp(struct gk20a_clock_priv *priv, unsigned long rate)
+{
+ u32 target_clk_f, ref_clk_f, target_freq;
+ u32 min_vco_f, max_vco_f;
+ u32 low_pl, high_pl, best_pl;
+ u32 target_vco_f, vco_f;
+ u32 best_m, best_n;
+ u32 u_f;
+ u32 m, n, n2;
+ u32 delta, lwv, best_delta = ~0;
+ u32 pl;
+
+ target_clk_f = rate * 2 / MHZ;
+ ref_clk_f = priv->parent_rate / MHZ;
+
+ max_vco_f = priv->params->max_vco;
+ min_vco_f = priv->params->min_vco;
+ best_m = priv->params->max_m;
+ best_n = priv->params->min_n;
+ best_pl = priv->params->min_pl;
+
+ target_vco_f = target_clk_f + target_clk_f / 50;
+ if (max_vco_f < target_vco_f)
+ max_vco_f = target_vco_f;
+
+ /* min_pl <= high_pl <= max_pl */
+ high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
+ high_pl = min(high_pl, priv->params->max_pl);
+ high_pl = max(high_pl, priv->params->min_pl);
+
+ /* min_pl <= low_pl <= max_pl */
+ low_pl = min_vco_f / target_vco_f;
+ low_pl = min(low_pl, priv->params->max_pl);
+ low_pl = max(low_pl, priv->params->min_pl);
+
+ /* Find Indices of high_pl and low_pl */
+ for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+ if (pl_to_div[pl] >= low_pl) {
+ low_pl = pl;
+ break;
+ }
+ }
+ for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
+ if (pl_to_div[pl] >= high_pl) {
+ high_pl = pl;
+ break;
+ }
+ }
+
+ nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
+ pl_to_div[low_pl], high_pl, pl_to_div[high_pl]);
+
+ /* Select lowest possible VCO */
+ for (pl = low_pl; pl <= high_pl; pl++) {
+ target_vco_f = target_clk_f * pl_to_div[pl];
+ for (m = priv->params->min_m; m <= priv->params->max_m; m++) {
+ u_f = ref_clk_f / m;
+
+ if (u_f < priv->params->min_u)
+ break;
+ if (u_f > priv->params->max_u)
+ continue;
+
+ n = (target_vco_f * m) / ref_clk_f;
+ n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
+
+ if (n > priv->params->max_n)
+ break;
+
+ for (; n <= n2; n++) {
+ if (n < priv->params->min_n)
+ continue;
+ if (n > priv->params->max_n)
+ break;
+
+ vco_f = ref_clk_f * n / m;
+
+ if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
+ lwv = (vco_f + (pl_to_div[pl] / 2))
+ / pl_to_div[pl];
+ delta = abs(lwv - target_clk_f);
+
+ if (delta < best_delta) {
+ best_delta = delta;
+ best_m = m;
+ best_n = n;
+ best_pl = pl;
+
+ if (best_delta == 0)
+ goto found_match;
+ }
+ }
+ }
+ }
+ }
+
+found_match:
+ WARN_ON(best_delta == ~0);
+
+ if (best_delta != 0)
+ nv_debug(priv, "no best match for target @ %dMHz on gpc_pll",
+ target_clk_f);
+
+ priv->m = best_m;
+ priv->n = best_n;
+ priv->pl = best_pl;
+
+ target_freq = gk20a_pllg_calc_rate(priv) / MHZ;
+
+ nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
+ target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]);
+
+ return 0;
+}
+
+static int
+gk20a_pllg_slide(struct gk20a_clock_priv *priv, u32 n)
+{
+ u32 val;
+ int ramp_timeout;
+
+ /* get old coefficients */
+ val = nv_rd32(priv, GPCPLL_COEFF);
+ /* do nothing if NDIV is the same */
+ if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH)))
+ return 0;
+
+ /* setup */
+ nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
+ 0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
+ nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
+ 0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
+
+ /* pll slowdown mode */
+ nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+ BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
+ BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
+
+ /* new ndiv ready for ramp */
+ val = nv_rd32(priv, GPCPLL_COEFF);
+ val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT);
+ val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
+ udelay(1);
+ nv_wr32(priv, GPCPLL_COEFF, val);
+
+ /* dynamic ramp to new ndiv */
+ val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+ val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT;
+ udelay(1);
+ nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val);
+
+ for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) {
+ udelay(1);
+ val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG);
+ if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK)
+ break;
+ }
+
+ /* exit slowdown mode */
+ nv_mask(priv, GPCPLL_NDIV_SLOWDOWN,
+ BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
+ BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
+ nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN);
+
+ if (ramp_timeout <= 0) {
+ nv_error(priv, "gpcpll dynamic ramp timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void
+_gk20a_pllg_enable(struct gk20a_clock_priv *priv)
+{
+ nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
+ nv_rd32(priv, GPCPLL_CFG);
+}
+
+static void
+_gk20a_pllg_disable(struct gk20a_clock_priv *priv)
+{
+ nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
+ nv_rd32(priv, GPCPLL_CFG);
+}
+
+static int
+_gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv, bool allow_slide)
+{
+ u32 val, cfg;
+ u32 m_old, pl_old, n_lo;
+
+ /* get old coefficients */
+ val = nv_rd32(priv, GPCPLL_COEFF);
+ m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+ pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
+
+ /* do NDIV slide if there is no change in M and PL */
+ cfg = nv_rd32(priv, GPCPLL_CFG);
+ if (allow_slide && priv->m == m_old && priv->pl == pl_old &&
+ (cfg & GPCPLL_CFG_ENABLE)) {
+ return gk20a_pllg_slide(priv, priv->n);
+ }
+
+ /* slide down to NDIV_LO */
+ n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco,
+ priv->parent_rate / MHZ);
+ if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) {
+ int ret = gk20a_pllg_slide(priv, n_lo);
+
+ if (ret)
+ return ret;
+ }
+
+ /* split FO-to-bypass jump in halfs by setting out divider 1:2 */
+ nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
+ 0x2 << GPC2CLK_OUT_VCODIV_SHIFT);
+
+ /* put PLL in bypass before programming it */
+ val = nv_rd32(priv, SEL_VCO);
+ val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+ udelay(2);
+ nv_wr32(priv, SEL_VCO, val);
+
+ /* get out from IDDQ */
+ val = nv_rd32(priv, GPCPLL_CFG);
+ if (val & GPCPLL_CFG_IDDQ) {
+ val &= ~GPCPLL_CFG_IDDQ;
+ nv_wr32(priv, GPCPLL_CFG, val);
+ nv_rd32(priv, GPCPLL_CFG);
+ udelay(2);
+ }
+
+ _gk20a_pllg_disable(priv);
+
+ nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n,
+ priv->pl);
+
+ n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco,
+ priv->parent_rate / MHZ);
+ val = priv->m << GPCPLL_COEFF_M_SHIFT;
+ val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT;
+ val |= priv->pl << GPCPLL_COEFF_P_SHIFT;
+ nv_wr32(priv, GPCPLL_COEFF, val);
+
+ _gk20a_pllg_enable(priv);
+
+ val = nv_rd32(priv, GPCPLL_CFG);
+ if (val & GPCPLL_CFG_LOCK_DET_OFF) {
+ val &= ~GPCPLL_CFG_LOCK_DET_OFF;
+ nv_wr32(priv, GPCPLL_CFG, val);
+ }
+
+ if (!nouveau_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK,
+ GPCPLL_CFG_LOCK)) {
+ nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* switch to VCO mode */
+ nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
+
+ /* restore out divider 1:1 */
+ val = nv_rd32(priv, GPC2CLK_OUT);
+ val &= ~GPC2CLK_OUT_VCODIV_MASK;
+ udelay(2);
+ nv_wr32(priv, GPC2CLK_OUT, val);
+
+ /* slide up to new NDIV */
+ return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0;
+}
+
+static int
+gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv)
+{
+ int err;
+
+ err = _gk20a_pllg_program_mnp(priv, true);
+ if (err)
+ err = _gk20a_pllg_program_mnp(priv, false);
+
+ return err;
+}
+
+static void
+gk20a_pllg_disable(struct gk20a_clock_priv *priv)
+{
+ u32 val;
+
+ /* slide to VCO min */
+ val = nv_rd32(priv, GPCPLL_CFG);
+ if (val & GPCPLL_CFG_ENABLE) {
+ u32 coeff, m, n_lo;
+
+ coeff = nv_rd32(priv, GPCPLL_COEFF);
+ m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
+ n_lo = DIV_ROUND_UP(m * priv->params->min_vco,
+ priv->parent_rate / MHZ);
+ gk20a_pllg_slide(priv, n_lo);
+ }
+
+ /* put PLL in bypass before disabling it */
+ nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
+
+ _gk20a_pllg_disable(priv);
+}
+
+#define GK20A_CLK_GPC_MDIV 1000
+
+static struct nouveau_clocks
+gk20a_domains[] = {
+ { nv_clk_src_crystal, 0xff },
+ { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
+ { nv_clk_src_max }
+};
+
+static struct nouveau_pstate
+gk20a_pstates[] = {
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 72000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 108000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 180000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 252000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 324000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 396000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 468000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 540000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 612000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 648000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 684000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 708000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 756000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 804000,
+ },
+ },
+ {
+ .base = {
+ .domain[nv_clk_src_gpc] = 852000,
+ },
+ },
+};
+
+static int
+gk20a_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
+{
+ struct gk20a_clock_priv *priv = (void *)clk;
+
+ switch (src) {
+ case nv_clk_src_crystal:
+ return nv_device(clk)->crystal;
+ case nv_clk_src_gpc:
+ gk20a_pllg_read_mnp(priv);
+ return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV;
+ default:
+ nv_error(clk, "invalid clock source %d\n", src);
+ return -EINVAL;
+ }
+}
+
+static int
+gk20a_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
+{
+ struct gk20a_clock_priv *priv = (void *)clk;
+
+ return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] *
+ GK20A_CLK_GPC_MDIV);
+}
+
+static int
+gk20a_clock_prog(struct nouveau_clock *clk)
+{
+ struct gk20a_clock_priv *priv = (void *)clk;
+
+ return gk20a_pllg_program_mnp(priv);
+}
+
+static void
+gk20a_clock_tidy(struct nouveau_clock *clk)
+{
+}
+
+static int
+gk20a_clock_fini(struct nouveau_object *object, bool suspend)
+{
+ struct gk20a_clock_priv *priv = (void *)object;
+ int ret;
+
+ ret = nouveau_clock_fini(&priv->base, false);
+
+ gk20a_pllg_disable(priv);
+
+ return ret;
+}
+
+static int
+gk20a_clock_init(struct nouveau_object *object)
+{
+ struct gk20a_clock_priv *priv = (void *)object;
+ int ret;
+
+ nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL);
+
+ ret = nouveau_clock_init(&priv->base);
+ if (ret)
+ return ret;
+
+ ret = gk20a_clock_prog(&priv->base);
+ if (ret) {
+ nv_error(priv, "cannot initialize clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+gk20a_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct gk20a_clock_priv *priv;
+ struct nouveau_platform_device *plat;
+ int ret;
+ int i;
+
+ /* Finish initializing the pstates */
+ for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) {
+ INIT_LIST_HEAD(&gk20a_pstates[i].list);
+ gk20a_pstates[i].pstate = i + 1;
+ }
+
+ ret = nouveau_clock_create(parent, engine, oclass, gk20a_domains,
+ gk20a_pstates, ARRAY_SIZE(gk20a_pstates), true, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ priv->params = &gk20a_pllg_params;
+
+ plat = nv_device_to_platform(nv_device(parent));
+ priv->parent_rate = clk_get_rate(plat->gpu->clk);
+ nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ);
+
+ priv->base.read = gk20a_clock_read;
+ priv->base.calc = gk20a_clock_calc;
+ priv->base.prog = gk20a_clock_prog;
+ priv->base.tidy = gk20a_clock_tidy;
+
+ return 0;
+}
+
+struct nouveau_oclass
+gk20a_clock_oclass = {
+ .handle = NV_SUBDEV(CLOCK, 0xea),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gk20a_clock_ctor,
+ .dtor = _nouveau_subdev_dtor,
+ .init = gk20a_clock_init,
+ .fini = gk20a_clock_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
index eb2d4425a49e..4c48232686be 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
@@ -82,8 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv04_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, NULL, 0,
+ false, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
index 8a9e16839791..08368fe97029 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
@@ -213,8 +213,8 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv40_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, NULL, 0,
+ true, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
index 8c132772ba9e..5070ebc260f8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
int ret;
ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
- false, &priv);
+ NULL, 0, false, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
index 9fb58354a80b..087012b18956 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
@@ -302,8 +302,8 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nva3_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, NULL, 0,
+ false, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
index 6a65fc9e9663..74e19731b1b7 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
@@ -421,8 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvaa_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, NULL,
+ 0, true, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
index dbf8517f54da..1234abaab2db 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
@@ -437,8 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, NULL, 0,
+ false, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
index 0e62a3240144..7eccad57512e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
@@ -475,8 +475,8 @@ nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nve0_clock_priv *priv;
int ret;
- ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
- &priv);
+ ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, NULL, 0,
+ true, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
index 1fc55c1e91a1..4150b0d10af8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
@@ -250,9 +250,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (priv->r100c08_page) {
- priv->r100c08 = nv_device_map_page(device, priv->r100c08_page);
- if (!priv->r100c08)
- nv_warn(priv, "failed 0x100c08 page map\n");
+ priv->r100c08 = dma_map_page(nv_device_base(device),
+ priv->r100c08_page, 0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(nv_device_base(device), priv->r100c08))
+ return -EFAULT;
} else {
nv_warn(priv, "failed 0x100c08 page alloc\n");
}
@@ -268,7 +270,8 @@ nv50_fb_dtor(struct nouveau_object *object)
struct nv50_fb_priv *priv = (void *)object;
if (priv->r100c08_page) {
- nv_device_unmap_page(device, priv->r100c08);
+ dma_unmap_page(nv_device_base(device), priv->r100c08, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(priv->r100c08_page);
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 0670ae33ee45..b19a2b3c1081 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -70,7 +70,8 @@ nvc0_fb_dtor(struct nouveau_object *object)
struct nvc0_fb_priv *priv = (void *)object;
if (priv->r100c10_page) {
- nv_device_unmap_page(device, priv->r100c10);
+ dma_unmap_page(nv_device_base(device), priv->r100c10, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
__free_page(priv->r100c10_page);
}
@@ -93,8 +94,10 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (priv->r100c10_page) {
- priv->r100c10 = nv_device_map_page(device, priv->r100c10_page);
- if (!priv->r100c10)
+ priv->r100c10 = dma_map_page(nv_device_base(device),
+ priv->r100c10_page, 0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(nv_device_base(device), priv->r100c10))
return -EFAULT;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index 5a6a5027f749..2b284b192763 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -26,7 +26,7 @@
#include <subdev/bios/pll.h>
#include <subdev/bios/rammap.h>
#include <subdev/bios/timing.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
#include <subdev/clock.h>
#include <subdev/clock/pll.h>
@@ -425,7 +425,7 @@ extern const u8 nvc0_pte_storage_type_map[256];
void
nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
- struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
+ struct nouveau_ltc *ltc = nouveau_ltc(pfb);
struct nouveau_mem *mem = *pmem;
*pmem = NULL;
@@ -434,7 +434,7 @@ nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
mutex_lock(&pfb->base.mutex);
if (mem->tag)
- ltcg->tags_free(ltcg, &mem->tag);
+ ltc->tags_free(ltc, &mem->tag);
__nv50_ram_put(pfb, mem);
mutex_unlock(&pfb->base.mutex);
@@ -468,12 +468,12 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
mutex_lock(&pfb->base.mutex);
if (comp) {
- struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
+ struct nouveau_ltc *ltc = nouveau_ltc(pfb);
/* compression only works with lpages */
if (align == (1 << (17 - 12))) {
int n = size >> 5;
- ltcg->tags_alloc(ltcg, n, &mem->tag);
+ ltc->tags_alloc(ltc, n, &mem->tag);
}
if (unlikely(!mem->tag))
@@ -554,13 +554,13 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
} else {
/* otherwise, address lowest common amount from 0GiB */
ret = nouveau_mm_init(&pfb->vram, rsvd_head,
- (bsize << 8) * parts, 1);
+ (bsize << 8) * parts - rsvd_head, 1);
if (ret)
return ret;
/* and the rest starting from (8GiB + common_size) */
offset = (0x0200000000ULL >> 12) + (bsize << 8);
- length = (ram->size >> 12) - (bsize << 8) - rsvd_tail;
+ length = (ram->size >> 12) - ((bsize * parts) << 8) - rsvd_tail;
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
index 45e0202f3151..b1e3ed7c8beb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
@@ -106,39 +106,59 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line)
}
static void
-nouveau_gpio_intr_disable(struct nouveau_event *event, int type, int index)
+nouveau_gpio_intr_fini(struct nvkm_event *event, int type, int index)
{
- struct nouveau_gpio *gpio = nouveau_gpio(event->priv);
+ struct nouveau_gpio *gpio = container_of(event, typeof(*gpio), event);
const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
impl->intr_mask(gpio, type, 1 << index, 0);
}
static void
-nouveau_gpio_intr_enable(struct nouveau_event *event, int type, int index)
+nouveau_gpio_intr_init(struct nvkm_event *event, int type, int index)
{
- struct nouveau_gpio *gpio = nouveau_gpio(event->priv);
+ struct nouveau_gpio *gpio = container_of(event, typeof(*gpio), event);
const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
impl->intr_mask(gpio, type, 1 << index, 1 << index);
}
+static int
+nouveau_gpio_intr_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ struct nvkm_gpio_ntfy_req *req = data;
+ if (!WARN_ON(size != sizeof(*req))) {
+ notify->size = sizeof(struct nvkm_gpio_ntfy_rep);
+ notify->types = req->mask;
+ notify->index = req->line;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static void
nouveau_gpio_intr(struct nouveau_subdev *subdev)
{
struct nouveau_gpio *gpio = nouveau_gpio(subdev);
const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass;
- u32 hi, lo, e, i;
+ u32 hi, lo, i;
impl->intr_stat(gpio, &hi, &lo);
- for (i = 0; e = 0, (hi | lo) && i < impl->lines; i++) {
- if (hi & (1 << i))
- e |= NVKM_GPIO_HI;
- if (lo & (1 << i))
- e |= NVKM_GPIO_LO;
- nouveau_event_trigger(gpio->events, e, i);
+ for (i = 0; (hi | lo) && i < impl->lines; i++) {
+ struct nvkm_gpio_ntfy_rep rep = {
+ .mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
+ (NVKM_GPIO_LO * !!(lo & (1 << i))),
+ };
+ nvkm_event_send(&gpio->event, rep.mask, i, &rep, sizeof(rep));
}
}
+static const struct nvkm_event_func
+nouveau_gpio_intr_func = {
+ .ctor = nouveau_gpio_intr_ctor,
+ .init = nouveau_gpio_intr_init,
+ .fini = nouveau_gpio_intr_fini,
+};
+
int
_nouveau_gpio_fini(struct nouveau_object *object, bool suspend)
{
@@ -183,7 +203,7 @@ void
_nouveau_gpio_dtor(struct nouveau_object *object)
{
struct nouveau_gpio *gpio = (void *)object;
- nouveau_event_destroy(&gpio->events);
+ nvkm_event_fini(&gpio->event);
nouveau_subdev_destroy(&gpio->base);
}
@@ -208,13 +228,11 @@ nouveau_gpio_create_(struct nouveau_object *parent,
gpio->get = nouveau_gpio_get;
gpio->reset = impl->reset;
- ret = nouveau_event_create(2, impl->lines, &gpio->events);
+ ret = nvkm_event_init(&nouveau_gpio_intr_func, 2, impl->lines,
+ &gpio->event);
if (ret)
return ret;
- gpio->events->priv = gpio;
- gpio->events->enable = nouveau_gpio_intr_enable;
- gpio->events->disable = nouveau_gpio_intr_disable;
nv_subdev(gpio)->intr = nouveau_gpio_intr;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
index 09ba2cc851cf..a652cafde3d6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
@@ -326,9 +326,9 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
}
static void
-nouveau_i2c_intr_disable(struct nouveau_event *event, int type, int index)
+nouveau_i2c_intr_fini(struct nvkm_event *event, int type, int index)
{
- struct nouveau_i2c *i2c = nouveau_i2c(event->priv);
+ struct nouveau_i2c *i2c = container_of(event, typeof(*i2c), event);
struct nouveau_i2c_port *port = i2c->find(i2c, index);
const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass;
if (port && port->aux >= 0)
@@ -336,15 +336,28 @@ nouveau_i2c_intr_disable(struct nouveau_event *event, int type, int index)
}
static void
-nouveau_i2c_intr_enable(struct nouveau_event *event, int type, int index)
+nouveau_i2c_intr_init(struct nvkm_event *event, int type, int index)
{
- struct nouveau_i2c *i2c = nouveau_i2c(event->priv);
+ struct nouveau_i2c *i2c = container_of(event, typeof(*i2c), event);
struct nouveau_i2c_port *port = i2c->find(i2c, index);
const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass;
if (port && port->aux >= 0)
impl->aux_mask(i2c, type, 1 << port->aux, 1 << port->aux);
}
+static int
+nouveau_i2c_intr_ctor(void *data, u32 size, struct nvkm_notify *notify)
+{
+ struct nvkm_i2c_ntfy_req *req = data;
+ if (!WARN_ON(size != sizeof(*req))) {
+ notify->size = sizeof(struct nvkm_i2c_ntfy_rep);
+ notify->types = req->mask;
+ notify->index = req->port;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static void
nouveau_i2c_intr(struct nouveau_subdev *subdev)
{
@@ -364,13 +377,26 @@ nouveau_i2c_intr(struct nouveau_subdev *subdev)
if (lo & (1 << port->aux)) e |= NVKM_I2C_UNPLUG;
if (rq & (1 << port->aux)) e |= NVKM_I2C_IRQ;
if (tx & (1 << port->aux)) e |= NVKM_I2C_DONE;
-
- nouveau_event_trigger(i2c->ntfy, e, port->index);
+ if (e) {
+ struct nvkm_i2c_ntfy_rep rep = {
+ .mask = e,
+ };
+ nvkm_event_send(&i2c->event, rep.mask,
+ port->index, &rep,
+ sizeof(rep));
+ }
}
}
}
}
+static const struct nvkm_event_func
+nouveau_i2c_intr_func = {
+ .ctor = nouveau_i2c_intr_ctor,
+ .init = nouveau_i2c_intr_init,
+ .fini = nouveau_i2c_intr_fini,
+};
+
int
_nouveau_i2c_fini(struct nouveau_object *object, bool suspend)
{
@@ -431,7 +457,7 @@ _nouveau_i2c_dtor(struct nouveau_object *object)
struct nouveau_i2c *i2c = (void *)object;
struct nouveau_i2c_port *port, *temp;
- nouveau_event_destroy(&i2c->ntfy);
+ nvkm_event_fini(&i2c->event);
list_for_each_entry_safe(port, temp, &i2c->ports, head) {
nouveau_object_ref(NULL, (struct nouveau_object **)&port);
@@ -547,13 +573,10 @@ nouveau_i2c_create_(struct nouveau_object *parent,
}
}
- ret = nouveau_event_create(4, index, &i2c->ntfy);
+ ret = nvkm_event_init(&nouveau_i2c_intr_func, 4, index, &i2c->event);
if (ret)
return ret;
- i2c->ntfy->priv = i2c;
- i2c->ntfy->enable = nouveau_i2c_intr_enable;
- i2c->ntfy->disable = nouveau_i2c_intr_disable;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
new file mode 100644
index 000000000000..32ed442c5913
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "priv.h"
+
+static int
+nvkm_ltc_tags_alloc(struct nouveau_ltc *ltc, u32 n,
+ struct nouveau_mm_node **pnode)
+{
+ struct nvkm_ltc_priv *priv = (void *)ltc;
+ int ret;
+
+ ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
+ if (ret)
+ *pnode = NULL;
+
+ return ret;
+}
+
+static void
+nvkm_ltc_tags_free(struct nouveau_ltc *ltc, struct nouveau_mm_node **pnode)
+{
+ struct nvkm_ltc_priv *priv = (void *)ltc;
+ nouveau_mm_free(&priv->tags, pnode);
+}
+
+static void
+nvkm_ltc_tags_clear(struct nouveau_ltc *ltc, u32 first, u32 count)
+{
+ const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+ struct nvkm_ltc_priv *priv = (void *)ltc;
+ const u32 limit = first + count - 1;
+
+ BUG_ON((first > limit) || (limit >= priv->num_tags));
+
+ impl->cbc_clear(priv, first, limit);
+ impl->cbc_wait(priv);
+}
+
+static int
+nvkm_ltc_zbc_color_get(struct nouveau_ltc *ltc, int index, const u32 color[4])
+{
+ const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+ struct nvkm_ltc_priv *priv = (void *)ltc;
+ memcpy(priv->zbc_color[index], color, sizeof(priv->zbc_color[index]));
+ impl->zbc_clear_color(priv, index, color);
+ return index;
+}
+
+static int
+nvkm_ltc_zbc_depth_get(struct nouveau_ltc *ltc, int index, const u32 depth)
+{
+ const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+ struct nvkm_ltc_priv *priv = (void *)ltc;
+ priv->zbc_depth[index] = depth;
+ impl->zbc_clear_depth(priv, index, depth);
+ return index;
+}
+
+int
+_nvkm_ltc_init(struct nouveau_object *object)
+{
+ const struct nvkm_ltc_impl *impl = (void *)nv_oclass(object);
+ struct nvkm_ltc_priv *priv = (void *)object;
+ int ret, i;
+
+ ret = nouveau_subdev_init(&priv->base.base);
+ if (ret)
+ return ret;
+
+ for (i = priv->base.zbc_min; i <= priv->base.zbc_max; i++) {
+ impl->zbc_clear_color(priv, i, priv->zbc_color[i]);
+ impl->zbc_clear_depth(priv, i, priv->zbc_depth[i]);
+ }
+
+ return 0;
+}
+
+int
+nvkm_ltc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, int length, void **pobject)
+{
+ const struct nvkm_ltc_impl *impl = (void *)oclass;
+ struct nvkm_ltc_priv *priv;
+ int ret;
+
+ ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PLTCG",
+ "l2c", length, pobject);
+ priv = *pobject;
+ if (ret)
+ return ret;
+
+ memset(priv->zbc_color, 0x00, sizeof(priv->zbc_color));
+ memset(priv->zbc_depth, 0x00, sizeof(priv->zbc_depth));
+
+ priv->base.base.intr = impl->intr;
+ priv->base.tags_alloc = nvkm_ltc_tags_alloc;
+ priv->base.tags_free = nvkm_ltc_tags_free;
+ priv->base.tags_clear = nvkm_ltc_tags_clear;
+ priv->base.zbc_min = 1; /* reserve 0 for disabled */
+ priv->base.zbc_max = min(impl->zbc, NOUVEAU_LTC_MAX_ZBC_CNT) - 1;
+ priv->base.zbc_color_get = nvkm_ltc_zbc_color_get;
+ priv->base.zbc_depth_get = nvkm_ltc_zbc_depth_get;
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
index f2f3338a967a..b54b582e72c4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
@@ -25,10 +25,45 @@
#include <subdev/fb.h>
#include <subdev/timer.h>
-#include "gf100.h"
+#include "priv.h"
+
+void
+gf100_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit)
+{
+ nv_wr32(priv, 0x17e8cc, start);
+ nv_wr32(priv, 0x17e8d0, limit);
+ nv_wr32(priv, 0x17e8c8, 0x00000004);
+}
+
+void
+gf100_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
+{
+ int c, s;
+ for (c = 0; c < priv->ltc_nr; c++) {
+ for (s = 0; s < priv->lts_nr; s++)
+ nv_wait(priv, 0x1410c8 + c * 0x2000 + s * 0x400, ~0, 0);
+ }
+}
+
+void
+gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+ nv_mask(priv, 0x17ea44, 0x0000000f, i);
+ nv_wr32(priv, 0x17ea48, color[0]);
+ nv_wr32(priv, 0x17ea4c, color[1]);
+ nv_wr32(priv, 0x17ea50, color[2]);
+ nv_wr32(priv, 0x17ea54, color[3]);
+}
+
+void
+gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+ nv_mask(priv, 0x17ea44, 0x0000000f, i);
+ nv_wr32(priv, 0x17ea58, depth);
+}
static void
-gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
+gf100_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
{
u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400);
u32 stat = nv_rd32(priv, base + 0x020);
@@ -39,17 +74,17 @@ gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
}
}
-static void
-gf100_ltcg_intr(struct nouveau_subdev *subdev)
+void
+gf100_ltc_intr(struct nouveau_subdev *subdev)
{
- struct gf100_ltcg_priv *priv = (void *)subdev;
+ struct nvkm_ltc_priv *priv = (void *)subdev;
u32 mask;
mask = nv_rd32(priv, 0x00017c);
while (mask) {
u32 lts, ltc = __ffs(mask);
for (lts = 0; lts < priv->lts_nr; lts++)
- gf100_ltcg_lts_isr(priv, ltc, lts);
+ gf100_ltc_lts_isr(priv, ltc, lts);
mask &= ~(1 << ltc);
}
@@ -59,52 +94,38 @@ gf100_ltcg_intr(struct nouveau_subdev *subdev)
nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
}
-int
-gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,
- struct nouveau_mm_node **pnode)
+static int
+gf100_ltc_init(struct nouveau_object *object)
{
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
+ struct nvkm_ltc_priv *priv = (void *)object;
int ret;
- ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode);
+ ret = nvkm_ltc_init(priv);
if (ret)
- *pnode = NULL;
+ return ret;
- return ret;
+ nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
+ nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
+ nv_wr32(priv, 0x17e8d4, priv->tag_base);
+ return 0;
}
void
-gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)
-{
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
-
- nouveau_mm_free(&priv->tags, pnode);
-}
-
-static void
-gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+gf100_ltc_dtor(struct nouveau_object *object)
{
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
- u32 last = first + count - 1;
- int p, i;
-
- BUG_ON((first > last) || (last >= priv->num_tags));
+ struct nouveau_fb *pfb = nouveau_fb(object);
+ struct nvkm_ltc_priv *priv = (void *)object;
- nv_wr32(priv, 0x17e8cc, first);
- nv_wr32(priv, 0x17e8d0, last);
- nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */
+ nouveau_mm_fini(&priv->tags);
+ nouveau_mm_free(&pfb->vram, &priv->tag_ram);
- /* wait until it's finished with clearing */
- for (p = 0; p < priv->ltc_nr; ++p) {
- for (i = 0; i < priv->lts_nr; ++i)
- nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);
- }
+ nvkm_ltc_destroy(priv);
}
/* TODO: Figure out tag memory details and drop the over-cautious allocation.
*/
int
-gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
+gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv)
{
u32 tag_size, tag_margin, tag_align;
int ret;
@@ -135,29 +156,29 @@ gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)
if (ret) {
priv->num_tags = 0;
} else {
- u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
+ u64 tag_base = ((u64)priv->tag_ram->offset << 12) + tag_margin;
tag_base += tag_align - 1;
ret = do_div(tag_base, tag_align);
priv->tag_base = tag_base;
}
- ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
+ ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
return ret;
}
-static int
-gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+int
+gf100_ltc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct gf100_ltcg_priv *priv;
struct nouveau_fb *pfb = nouveau_fb(parent);
+ struct nvkm_ltc_priv *priv;
u32 parts, mask;
int ret, i;
- ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
+ ret = nvkm_ltc_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
@@ -170,57 +191,27 @@ gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
}
priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28;
- ret = gf100_ltcg_init_tag_ram(pfb, priv);
+ ret = gf100_ltc_init_tag_ram(pfb, priv);
if (ret)
return ret;
- priv->base.tags_alloc = gf100_ltcg_tags_alloc;
- priv->base.tags_free = gf100_ltcg_tags_free;
- priv->base.tags_clear = gf100_ltcg_tags_clear;
-
- nv_subdev(priv)->intr = gf100_ltcg_intr;
- return 0;
-}
-
-void
-gf100_ltcg_dtor(struct nouveau_object *object)
-{
- struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
- struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);
-
- nouveau_mm_fini(&priv->tags);
- nouveau_mm_free(&pfb->vram, &priv->tag_ram);
-
- nouveau_ltcg_destroy(ltcg);
-}
-
-static int
-gf100_ltcg_init(struct nouveau_object *object)
-{
- struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
- int ret;
-
- ret = nouveau_ltcg_init(ltcg);
- if (ret)
- return ret;
-
- nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
- nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
- if (nv_device(ltcg)->card_type >= NV_E0)
- nv_wr32(priv, 0x17e000, priv->ltc_nr);
- nv_wr32(priv, 0x17e8d4, priv->tag_base);
+ nv_subdev(priv)->intr = gf100_ltc_intr;
return 0;
}
struct nouveau_oclass *
-gf100_ltcg_oclass = &(struct nouveau_oclass) {
- .handle = NV_SUBDEV(LTCG, 0xc0),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = gf100_ltcg_ctor,
- .dtor = gf100_ltcg_dtor,
- .init = gf100_ltcg_init,
- .fini = _nouveau_ltcg_fini,
+gf100_ltc_oclass = &(struct nvkm_ltc_impl) {
+ .base.handle = NV_SUBDEV(LTC, 0xc0),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gf100_ltc_ctor,
+ .dtor = gf100_ltc_dtor,
+ .init = gf100_ltc_init,
+ .fini = _nvkm_ltc_fini,
},
-};
+ .intr = gf100_ltc_intr,
+ .cbc_clear = gf100_ltc_cbc_clear,
+ .cbc_wait = gf100_ltc_cbc_wait,
+ .zbc = 16,
+ .zbc_clear_color = gf100_ltc_zbc_clear_color,
+ .zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
new file mode 100644
index 000000000000..ea716569745d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "priv.h"
+
+static int
+gk104_ltc_init(struct nouveau_object *object)
+{
+ struct nvkm_ltc_priv *priv = (void *)object;
+ int ret;
+
+ ret = nvkm_ltc_init(priv);
+ if (ret)
+ return ret;
+
+ nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
+ nv_wr32(priv, 0x17e000, priv->ltc_nr);
+ nv_wr32(priv, 0x17e8d4, priv->tag_base);
+ return 0;
+}
+
+struct nouveau_oclass *
+gk104_ltc_oclass = &(struct nvkm_ltc_impl) {
+ .base.handle = NV_SUBDEV(LTC, 0xe4),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gf100_ltc_ctor,
+ .dtor = gf100_ltc_dtor,
+ .init = gk104_ltc_init,
+ .fini = _nvkm_ltc_fini,
+ },
+ .intr = gf100_ltc_intr,
+ .cbc_clear = gf100_ltc_cbc_clear,
+ .cbc_wait = gf100_ltc_cbc_wait,
+ .zbc = 16,
+ .zbc_clear_color = gf100_ltc_zbc_clear_color,
+ .zbc_clear_depth = gf100_ltc_zbc_clear_depth,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
index e79d0e81de40..4761b2e9af00 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
@@ -25,10 +25,45 @@
#include <subdev/fb.h>
#include <subdev/timer.h>
-#include "gf100.h"
+#include "priv.h"
static void
-gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
+gm107_ltc_cbc_clear(struct nvkm_ltc_priv *priv, u32 start, u32 limit)
+{
+ nv_wr32(priv, 0x17e270, start);
+ nv_wr32(priv, 0x17e274, limit);
+ nv_wr32(priv, 0x17e26c, 0x00000004);
+}
+
+static void
+gm107_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
+{
+ int c, s;
+ for (c = 0; c < priv->ltc_nr; c++) {
+ for (s = 0; s < priv->lts_nr; s++)
+ nv_wait(priv, 0x14046c + c * 0x2000 + s * 0x200, ~0, 0);
+ }
+}
+
+static void
+gm107_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+ nv_mask(priv, 0x17e338, 0x0000000f, i);
+ nv_wr32(priv, 0x17e33c, color[0]);
+ nv_wr32(priv, 0x17e340, color[1]);
+ nv_wr32(priv, 0x17e344, color[2]);
+ nv_wr32(priv, 0x17e348, color[3]);
+}
+
+static void
+gm107_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+ nv_mask(priv, 0x17e338, 0x0000000f, i);
+ nv_wr32(priv, 0x17e34c, depth);
+}
+
+static void
+gm107_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
{
u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
u32 stat = nv_rd32(priv, base + 0x00c);
@@ -40,16 +75,16 @@ gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)
}
static void
-gm107_ltcg_intr(struct nouveau_subdev *subdev)
+gm107_ltc_intr(struct nouveau_subdev *subdev)
{
- struct gf100_ltcg_priv *priv = (void *)subdev;
+ struct nvkm_ltc_priv *priv = (void *)subdev;
u32 mask;
mask = nv_rd32(priv, 0x00017c);
while (mask) {
u32 lts, ltc = __ffs(mask);
for (lts = 0; lts < priv->lts_nr; lts++)
- gm107_ltcg_lts_isr(priv, ltc, lts);
+ gm107_ltc_lts_isr(priv, ltc, lts);
mask &= ~(1 << ltc);
}
@@ -59,37 +94,32 @@ gm107_ltcg_intr(struct nouveau_subdev *subdev)
nv_mask(priv, 0x000640, 0x02000000, 0x00000000);
}
-static void
-gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)
+static int
+gm107_ltc_init(struct nouveau_object *object)
{
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
- u32 last = first + count - 1;
- int p, i;
-
- BUG_ON((first > last) || (last >= priv->num_tags));
+ struct nvkm_ltc_priv *priv = (void *)object;
+ int ret;
- nv_wr32(priv, 0x17e270, first);
- nv_wr32(priv, 0x17e274, last);
- nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */
+ ret = nvkm_ltc_init(priv);
+ if (ret)
+ return ret;
- /* wait until it's finished with clearing */
- for (p = 0; p < priv->ltc_nr; ++p) {
- for (i = 0; i < priv->lts_nr; ++i)
- nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0);
- }
+ nv_wr32(priv, 0x17e27c, priv->ltc_nr);
+ nv_wr32(priv, 0x17e278, priv->tag_base);
+ return 0;
}
static int
-gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+gm107_ltc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct gf100_ltcg_priv *priv;
struct nouveau_fb *pfb = nouveau_fb(parent);
+ struct nvkm_ltc_priv *priv;
u32 parts, mask;
int ret, i;
- ret = nouveau_ltcg_create(parent, engine, oclass, &priv);
+ ret = nvkm_ltc_create(parent, engine, oclass, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
@@ -102,41 +132,26 @@ gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
}
priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28;
- ret = gf100_ltcg_init_tag_ram(pfb, priv);
- if (ret)
- return ret;
-
- priv->base.tags_alloc = gf100_ltcg_tags_alloc;
- priv->base.tags_free = gf100_ltcg_tags_free;
- priv->base.tags_clear = gm107_ltcg_tags_clear;
-
- nv_subdev(priv)->intr = gm107_ltcg_intr;
- return 0;
-}
-
-static int
-gm107_ltcg_init(struct nouveau_object *object)
-{
- struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
- struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;
- int ret;
-
- ret = nouveau_ltcg_init(ltcg);
+ ret = gf100_ltc_init_tag_ram(pfb, priv);
if (ret)
return ret;
- nv_wr32(priv, 0x17e27c, priv->ltc_nr);
- nv_wr32(priv, 0x17e278, priv->tag_base);
return 0;
}
struct nouveau_oclass *
-gm107_ltcg_oclass = &(struct nouveau_oclass) {
- .handle = NV_SUBDEV(LTCG, 0xff),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = gm107_ltcg_ctor,
- .dtor = gf100_ltcg_dtor,
- .init = gm107_ltcg_init,
- .fini = _nouveau_ltcg_fini,
+gm107_ltc_oclass = &(struct nvkm_ltc_impl) {
+ .base.handle = NV_SUBDEV(LTC, 0xff),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gm107_ltc_ctor,
+ .dtor = gf100_ltc_dtor,
+ .init = gm107_ltc_init,
+ .fini = _nvkm_ltc_fini,
},
-};
+ .intr = gm107_ltc_intr,
+ .cbc_clear = gm107_ltc_cbc_clear,
+ .cbc_wait = gm107_ltc_cbc_wait,
+ .zbc = 16,
+ .zbc_clear_color = gm107_ltc_zbc_clear_color,
+ .zbc_clear_depth = gm107_ltc_zbc_clear_depth,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
new file mode 100644
index 000000000000..594924f39126
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
@@ -0,0 +1,69 @@
+#ifndef __NVKM_LTC_PRIV_H__
+#define __NVKM_LTC_PRIV_H__
+
+#include <subdev/ltc.h>
+#include <subdev/fb.h>
+
+struct nvkm_ltc_priv {
+ struct nouveau_ltc base;
+ u32 ltc_nr;
+ u32 lts_nr;
+
+ u32 num_tags;
+ u32 tag_base;
+ struct nouveau_mm tags;
+ struct nouveau_mm_node *tag_ram;
+
+ u32 zbc_color[NOUVEAU_LTC_MAX_ZBC_CNT][4];
+ u32 zbc_depth[NOUVEAU_LTC_MAX_ZBC_CNT];
+};
+
+#define nvkm_ltc_create(p,e,o,d) \
+ nvkm_ltc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nvkm_ltc_destroy(p) ({ \
+ struct nvkm_ltc_priv *_priv = (p); \
+ _nvkm_ltc_dtor(nv_object(_priv)); \
+})
+#define nvkm_ltc_init(p) ({ \
+ struct nvkm_ltc_priv *_priv = (p); \
+ _nvkm_ltc_init(nv_object(_priv)); \
+})
+#define nvkm_ltc_fini(p,s) ({ \
+ struct nvkm_ltc_priv *_priv = (p); \
+ _nvkm_ltc_fini(nv_object(_priv), (s)); \
+})
+
+int nvkm_ltc_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, int, void **);
+
+#define _nvkm_ltc_dtor _nouveau_subdev_dtor
+int _nvkm_ltc_init(struct nouveau_object *);
+#define _nvkm_ltc_fini _nouveau_subdev_fini
+
+int gf100_ltc_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void gf100_ltc_dtor(struct nouveau_object *);
+int gf100_ltc_init_tag_ram(struct nouveau_fb *, struct nvkm_ltc_priv *);
+int gf100_ltc_tags_alloc(struct nouveau_ltc *, u32, struct nouveau_mm_node **);
+void gf100_ltc_tags_free(struct nouveau_ltc *, struct nouveau_mm_node **);
+
+struct nvkm_ltc_impl {
+ struct nouveau_oclass base;
+ void (*intr)(struct nouveau_subdev *);
+
+ void (*cbc_clear)(struct nvkm_ltc_priv *, u32 start, u32 limit);
+ void (*cbc_wait)(struct nvkm_ltc_priv *);
+
+ int zbc;
+ void (*zbc_clear_color)(struct nvkm_ltc_priv *, int, const u32[4]);
+ void (*zbc_clear_depth)(struct nvkm_ltc_priv *, int, const u32);
+};
+
+void gf100_ltc_intr(struct nouveau_subdev *);
+void gf100_ltc_cbc_clear(struct nvkm_ltc_priv *, u32, u32);
+void gf100_ltc_cbc_wait(struct nvkm_ltc_priv *);
+void gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *, int, const u32[4]);
+void gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *, int, const u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
deleted file mode 100644
index 87b10b8412ea..000000000000
--- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __NVKM_LTCG_PRIV_GF100_H__
-#define __NVKM_LTCG_PRIV_GF100_H__
-
-#include <subdev/ltcg.h>
-
-struct gf100_ltcg_priv {
- struct nouveau_ltcg base;
- u32 ltc_nr;
- u32 lts_nr;
- u32 num_tags;
- u32 tag_base;
- struct nouveau_mm tags;
- struct nouveau_mm_node *tag_ram;
-};
-
-void gf100_ltcg_dtor(struct nouveau_object *);
-int gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *);
-int gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **);
-void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **);
-
-#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
index 8a5555192fa5..ca7cee3a314a 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
@@ -22,9 +22,17 @@
* Authors: Ben Skeggs
*/
-#include <subdev/mc.h>
+#include "priv.h"
#include <core/option.h>
+static inline void
+nouveau_mc_unk260(struct nouveau_mc *pmc, u32 data)
+{
+ const struct nouveau_mc_oclass *impl = (void *)nv_oclass(pmc);
+ if (impl->unk260)
+ impl->unk260(pmc, data);
+}
+
static inline u32
nouveau_mc_intr_mask(struct nouveau_mc *pmc)
{
@@ -114,6 +122,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
+ pmc->unk260 = nouveau_mc_unk260;
+
if (nv_device_is_pci(device))
switch (device->pdev->device & 0x0ff0) {
case 0x00f0:
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c
new file mode 100644
index 000000000000..b8d6cb435d0a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/gk20a.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv04.h"
+
+struct nouveau_oclass *
+gk20a_mc_oclass = &(struct nouveau_mc_oclass) {
+ .base.handle = NV_SUBDEV(MC, 0xea),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nv04_mc_ctor,
+ .dtor = _nouveau_mc_dtor,
+ .init = nv50_mc_init,
+ .fini = _nouveau_mc_fini,
+ },
+ .intr = nvc0_mc_intr,
+ .msi_rearm = nv40_mc_msi_rearm,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
index 81a408e7d034..4d9ea46c47c2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
@@ -1,7 +1,7 @@
#ifndef __NVKM_MC_NV04_H__
#define __NVKM_MC_NV04_H__
-#include <subdev/mc.h>
+#include "priv.h"
struct nv04_mc_priv {
struct nouveau_mc base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
index f9c6a678b47d..15d41dc176ff 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
@@ -41,7 +41,7 @@ nvc0_mc_intr[] = {
{ 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */
{ 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */
{ 0x01000000, NVDEV_SUBDEV_PWR },
- { 0x02000000, NVDEV_SUBDEV_LTCG },
+ { 0x02000000, NVDEV_SUBDEV_LTC },
{ 0x08000000, NVDEV_SUBDEV_FB },
{ 0x10000000, NVDEV_SUBDEV_BUS },
{ 0x40000000, NVDEV_SUBDEV_IBUS },
@@ -56,6 +56,12 @@ nvc0_mc_msi_rearm(struct nouveau_mc *pmc)
nv_wr32(priv, 0x088704, 0x00000000);
}
+void
+nvc0_mc_unk260(struct nouveau_mc *pmc, u32 data)
+{
+ nv_wr32(pmc, 0x000260, data);
+}
+
struct nouveau_oclass *
nvc0_mc_oclass = &(struct nouveau_mc_oclass) {
.base.handle = NV_SUBDEV(MC, 0xc0),
@@ -67,4 +73,5 @@ nvc0_mc_oclass = &(struct nouveau_mc_oclass) {
},
.intr = nvc0_mc_intr,
.msi_rearm = nvc0_mc_msi_rearm,
+ .unk260 = nvc0_mc_unk260,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c
index 837e545aeb9f..68b5f61aadb5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c
@@ -35,4 +35,5 @@ nvc3_mc_oclass = &(struct nouveau_mc_oclass) {
},
.intr = nvc0_mc_intr,
.msi_rearm = nv40_mc_msi_rearm,
+ .unk260 = nvc0_mc_unk260,
}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h
new file mode 100644
index 000000000000..911e66392587
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/priv.h
@@ -0,0 +1,38 @@
+#ifndef __NVKM_MC_PRIV_H__
+#define __NVKM_MC_PRIV_H__
+
+#include <subdev/mc.h>
+
+#define nouveau_mc_create(p,e,o,d) \
+ nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_mc_destroy(p) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
+})
+#define nouveau_mc_init(p) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc)); \
+})
+#define nouveau_mc_fini(p,s) ({ \
+ struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s)); \
+})
+
+int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, int, void **);
+void _nouveau_mc_dtor(struct nouveau_object *);
+int _nouveau_mc_init(struct nouveau_object *);
+int _nouveau_mc_fini(struct nouveau_object *, bool);
+
+struct nouveau_mc_intr {
+ u32 stat;
+ u32 unit;
+};
+
+struct nouveau_mc_oclass {
+ struct nouveau_oclass base;
+ const struct nouveau_mc_intr *intr;
+ void (*msi_rearm)(struct nouveau_mc *);
+ void (*unk260)(struct nouveau_mc *, u32);
+};
+
+void nvc0_mc_unk260(struct nouveau_mc *, u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c
index d4fd3bc9c66f..69f1f34f6931 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c
@@ -22,9 +22,18 @@
* Authors: Ben Skeggs
*/
-#include <subdev/pwr.h>
#include <subdev/timer.h>
+#include "priv.h"
+
+static void
+nouveau_pwr_pgob(struct nouveau_pwr *ppwr, bool enable)
+{
+ const struct nvkm_pwr_impl *impl = (void *)nv_oclass(ppwr);
+ if (impl->pgob)
+ impl->pgob(ppwr, enable);
+}
+
static int
nouveau_pwr_send(struct nouveau_pwr *ppwr, u32 reply[2],
u32 process, u32 message, u32 data0, u32 data1)
@@ -177,6 +186,7 @@ _nouveau_pwr_fini(struct nouveau_object *object, bool suspend)
int
_nouveau_pwr_init(struct nouveau_object *object)
{
+ const struct nvkm_pwr_impl *impl = (void *)object->oclass;
struct nouveau_pwr *ppwr = (void *)object;
int ret, i;
@@ -186,6 +196,7 @@ _nouveau_pwr_init(struct nouveau_object *object)
nv_subdev(ppwr)->intr = nouveau_pwr_intr;
ppwr->message = nouveau_pwr_send;
+ ppwr->pgob = nouveau_pwr_pgob;
/* prevent previous ucode from running, wait for idle, reset */
nv_wr32(ppwr, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */
@@ -195,15 +206,15 @@ _nouveau_pwr_init(struct nouveau_object *object)
/* upload data segment */
nv_wr32(ppwr, 0x10a1c0, 0x01000000);
- for (i = 0; i < ppwr->data.size / 4; i++)
- nv_wr32(ppwr, 0x10a1c4, ppwr->data.data[i]);
+ for (i = 0; i < impl->data.size / 4; i++)
+ nv_wr32(ppwr, 0x10a1c4, impl->data.data[i]);
/* upload code segment */
nv_wr32(ppwr, 0x10a180, 0x01000000);
- for (i = 0; i < ppwr->code.size / 4; i++) {
+ for (i = 0; i < impl->code.size / 4; i++) {
if ((i & 0x3f) == 0)
nv_wr32(ppwr, 0x10a188, i >> 6);
- nv_wr32(ppwr, 0x10a184, ppwr->code.data[i]);
+ nv_wr32(ppwr, 0x10a184, impl->code.data[i]);
}
/* start it running */
@@ -245,3 +256,15 @@ nouveau_pwr_create_(struct nouveau_object *parent,
init_waitqueue_head(&ppwr->recv.wait);
return 0;
}
+
+int
+_nouveau_pwr_ctor(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_pwr *ppwr;
+ int ret = nouveau_pwr_create(parent, engine, oclass, &ppwr);
+ *pobject = nv_object(ppwr);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
index e2a63ac5422b..5668e045bac1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
@@ -242,7 +242,7 @@
*/ push reg /*
*/ pop $r13 /*
*/ pop $r14 /*
-*/ call(wr32) /*
+*/ call(wr32)
#else
#define nv_wr32(addr,reg) /*
*/ sethi $r0 0x14000000 /*
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
index 39a5dc150a05..986495d533dd 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
@@ -46,8 +46,8 @@ uint32_t nv108_pwr_data[] = {
0x00000000,
0x00000000,
0x584d454d,
- 0x0000046f,
- 0x00000461,
+ 0x00000464,
+ 0x00000456,
0x00000000,
0x00000000,
0x00000000,
@@ -68,8 +68,8 @@ uint32_t nv108_pwr_data[] = {
0x00000000,
0x00000000,
0x46524550,
- 0x00000473,
- 0x00000471,
+ 0x00000468,
+ 0x00000466,
0x00000000,
0x00000000,
0x00000000,
@@ -90,8 +90,8 @@ uint32_t nv108_pwr_data[] = {
0x00000000,
0x00000000,
0x5f433249,
- 0x00000877,
- 0x0000071e,
+ 0x0000086c,
+ 0x00000713,
0x00000000,
0x00000000,
0x00000000,
@@ -112,8 +112,8 @@ uint32_t nv108_pwr_data[] = {
0x00000000,
0x00000000,
0x54534554,
- 0x00000898,
- 0x00000879,
+ 0x0000088d,
+ 0x0000086e,
0x00000000,
0x00000000,
0x00000000,
@@ -134,8 +134,8 @@ uint32_t nv108_pwr_data[] = {
0x00000000,
0x00000000,
0x454c4449,
- 0x000008a3,
- 0x000008a1,
+ 0x00000898,
+ 0x00000896,
0x00000000,
0x00000000,
0x00000000,
@@ -239,10 +239,10 @@ uint32_t nv108_pwr_data[] = {
0x000003df,
0x00040003,
0x00000000,
- 0x00000407,
+ 0x000003fc,
0x00010004,
0x00000000,
- 0x00000421,
+ 0x00000416,
/* 0x03ac: memx_func_tail */
/* 0x03ac: memx_data_head */
0x00000000,
@@ -1080,375 +1080,375 @@ uint32_t nv108_pwr_code[] = {
0x50f960f9,
0xe0fcd0fc,
0x00002e7e,
- 0x140003f1,
- 0xa00506fd,
- 0xb604bd05,
- 0x1bf40242,
-/* 0x0407: memx_func_wait */
- 0x0800f8dd,
- 0x0088cf2c,
- 0x98001e98,
- 0x1c98011d,
- 0x031b9802,
- 0x7e1010b6,
- 0xf8000071,
-/* 0x0421: memx_func_delay */
+ 0xf40242b6,
+ 0x00f8e81b,
+/* 0x03fc: memx_func_wait */
+ 0x88cf2c08,
0x001e9800,
- 0x7e0410b6,
- 0xf800005d,
-/* 0x042d: memx_exec */
- 0xf9e0f900,
- 0xb2c1b2d0,
-/* 0x0435: memx_exec_next */
- 0x001398b2,
- 0x950410b6,
- 0x30f01034,
- 0xde35980c,
- 0x12a655f9,
- 0xfced1ef4,
- 0x7ee0fcd0,
- 0xf800023f,
-/* 0x0455: memx_info */
- 0x03ac4c00,
- 0x7e08004b,
- 0xf800023f,
-/* 0x0461: memx_recv */
- 0x01d6b000,
- 0xb0c90bf4,
- 0x0bf400d6,
-/* 0x046f: memx_init */
- 0xf800f8eb,
-/* 0x0471: perf_recv */
-/* 0x0473: perf_init */
- 0xf800f800,
-/* 0x0475: i2c_drive_scl */
- 0x0036b000,
- 0x400d0bf4,
- 0x01f607e0,
- 0xf804bd00,
-/* 0x0485: i2c_drive_scl_lo */
- 0x07e44000,
- 0xbd0001f6,
-/* 0x048f: i2c_drive_sda */
- 0xb000f804,
- 0x0bf40036,
- 0x07e0400d,
- 0xbd0002f6,
-/* 0x049f: i2c_drive_sda_lo */
- 0x4000f804,
- 0x02f607e4,
- 0xf804bd00,
-/* 0x04a9: i2c_sense_scl */
- 0x0132f400,
- 0xcf07c443,
- 0x31fd0033,
- 0x060bf404,
-/* 0x04bb: i2c_sense_scl_done */
- 0xf80131f4,
-/* 0x04bd: i2c_sense_sda */
- 0x0132f400,
- 0xcf07c443,
- 0x32fd0033,
- 0x060bf404,
-/* 0x04cf: i2c_sense_sda_done */
- 0xf80131f4,
-/* 0x04d1: i2c_raise_scl */
- 0x4440f900,
- 0x01030898,
- 0x0004757e,
-/* 0x04dc: i2c_raise_scl_wait */
- 0x7e03e84e,
- 0x7e00005d,
- 0xf40004a9,
- 0x42b60901,
- 0xef1bf401,
-/* 0x04f0: i2c_raise_scl_done */
- 0x00f840fc,
-/* 0x04f4: i2c_start */
- 0x0004a97e,
- 0x7e0d11f4,
- 0xf40004bd,
- 0x0ef40611,
-/* 0x0505: i2c_start_rep */
- 0x7e00032e,
- 0x03000475,
- 0x048f7e01,
- 0x0076bb00,
- 0xf90465b6,
- 0x04659450,
- 0xbd0256bb,
- 0x0475fd50,
- 0xd17e50fc,
- 0x64b60004,
- 0x1d11f404,
-/* 0x0530: i2c_start_send */
- 0x8f7e0003,
- 0x884e0004,
- 0x005d7e13,
- 0x7e000300,
- 0x4e000475,
- 0x5d7e1388,
-/* 0x054a: i2c_start_out */
- 0x00f80000,
-/* 0x054c: i2c_stop */
- 0x757e0003,
- 0x00030004,
- 0x00048f7e,
- 0x7e03e84e,
- 0x0300005d,
- 0x04757e01,
- 0x13884e00,
+ 0x98011d98,
+ 0x1b98021c,
+ 0x1010b603,
+ 0x0000717e,
+/* 0x0416: memx_func_delay */
+ 0x1e9800f8,
+ 0x0410b600,
0x00005d7e,
- 0x8f7e0103,
- 0x884e0004,
- 0x005d7e13,
-/* 0x057b: i2c_bitw */
- 0x7e00f800,
- 0x4e00048f,
- 0x5d7e03e8,
- 0x76bb0000,
+/* 0x0422: memx_exec */
+ 0xe0f900f8,
+ 0xc1b2d0f9,
+/* 0x042a: memx_exec_next */
+ 0x1398b2b2,
+ 0x0410b600,
+ 0xf0103495,
+ 0x35980c30,
+ 0xa655f9de,
+ 0xed1ef412,
+ 0xe0fcd0fc,
+ 0x00023f7e,
+/* 0x044a: memx_info */
+ 0xac4c00f8,
+ 0x08004b03,
+ 0x00023f7e,
+/* 0x0456: memx_recv */
+ 0xd6b000f8,
+ 0xc90bf401,
+ 0xf400d6b0,
+ 0x00f8eb0b,
+/* 0x0464: memx_init */
+/* 0x0466: perf_recv */
+ 0x00f800f8,
+/* 0x0468: perf_init */
+/* 0x046a: i2c_drive_scl */
+ 0x36b000f8,
+ 0x0d0bf400,
+ 0xf607e040,
+ 0x04bd0001,
+/* 0x047a: i2c_drive_scl_lo */
+ 0xe44000f8,
+ 0x0001f607,
+ 0x00f804bd,
+/* 0x0484: i2c_drive_sda */
+ 0xf40036b0,
+ 0xe0400d0b,
+ 0x0002f607,
+ 0x00f804bd,
+/* 0x0494: i2c_drive_sda_lo */
+ 0xf607e440,
+ 0x04bd0002,
+/* 0x049e: i2c_sense_scl */
+ 0x32f400f8,
+ 0x07c44301,
+ 0xfd0033cf,
+ 0x0bf40431,
+ 0x0131f406,
+/* 0x04b0: i2c_sense_scl_done */
+/* 0x04b2: i2c_sense_sda */
+ 0x32f400f8,
+ 0x07c44301,
+ 0xfd0033cf,
+ 0x0bf40432,
+ 0x0131f406,
+/* 0x04c4: i2c_sense_sda_done */
+/* 0x04c6: i2c_raise_scl */
+ 0x40f900f8,
+ 0x03089844,
+ 0x046a7e01,
+/* 0x04d1: i2c_raise_scl_wait */
+ 0x03e84e00,
+ 0x00005d7e,
+ 0x00049e7e,
+ 0xb60901f4,
+ 0x1bf40142,
+/* 0x04e5: i2c_raise_scl_done */
+ 0xf840fcef,
+/* 0x04e9: i2c_start */
+ 0x049e7e00,
+ 0x0d11f400,
+ 0x0004b27e,
+ 0xf40611f4,
+/* 0x04fa: i2c_start_rep */
+ 0x00032e0e,
+ 0x00046a7e,
+ 0x847e0103,
+ 0x76bb0004,
0x0465b600,
0x659450f9,
0x0256bb04,
0x75fd50bd,
0x7e50fc04,
- 0xb60004d1,
+ 0xb60004c6,
0x11f40464,
- 0x13884e17,
+/* 0x0525: i2c_start_send */
+ 0x7e00031d,
+ 0x4e000484,
+ 0x5d7e1388,
+ 0x00030000,
+ 0x00046a7e,
+ 0x7e13884e,
+/* 0x053f: i2c_start_out */
+ 0xf800005d,
+/* 0x0541: i2c_stop */
+ 0x7e000300,
+ 0x0300046a,
+ 0x04847e00,
+ 0x03e84e00,
0x00005d7e,
- 0x757e0003,
+ 0x6a7e0103,
0x884e0004,
0x005d7e13,
-/* 0x05b9: i2c_bitw_out */
-/* 0x05bb: i2c_bitr */
- 0x0300f800,
- 0x048f7e01,
- 0x03e84e00,
- 0x00005d7e,
- 0xb60076bb,
- 0x50f90465,
- 0xbb046594,
- 0x50bd0256,
- 0xfc0475fd,
- 0x04d17e50,
- 0x0464b600,
- 0x7e1a11f4,
- 0x030004bd,
- 0x04757e00,
- 0x13884e00,
- 0x00005d7e,
- 0xf4013cf0,
-/* 0x05fe: i2c_bitr_done */
- 0x00f80131,
-/* 0x0600: i2c_get_byte */
- 0x08040005,
-/* 0x0604: i2c_get_byte_next */
- 0xbb0154b6,
+ 0x7e010300,
+ 0x4e000484,
+ 0x5d7e1388,
+ 0x00f80000,
+/* 0x0570: i2c_bitw */
+ 0x0004847e,
+ 0x7e03e84e,
+ 0xbb00005d,
0x65b60076,
0x9450f904,
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x0005bb7e,
+ 0x0004c67e,
0xf40464b6,
- 0x53fd2a11,
- 0x0142b605,
- 0x03d81bf4,
- 0x0076bb01,
+ 0x884e1711,
+ 0x005d7e13,
+ 0x7e000300,
+ 0x4e00046a,
+ 0x5d7e1388,
+/* 0x05ae: i2c_bitw_out */
+ 0x00f80000,
+/* 0x05b0: i2c_bitr */
+ 0x847e0103,
+ 0xe84e0004,
+ 0x005d7e03,
+ 0x0076bb00,
0xf90465b6,
0x04659450,
0xbd0256bb,
0x0475fd50,
- 0x7b7e50fc,
- 0x64b60005,
-/* 0x064d: i2c_get_byte_done */
-/* 0x064f: i2c_put_byte */
- 0x0400f804,
-/* 0x0651: i2c_put_byte_next */
- 0x0142b608,
- 0xbb3854ff,
- 0x65b60076,
- 0x9450f904,
- 0x56bb0465,
- 0xfd50bd02,
- 0x50fc0475,
- 0x00057b7e,
- 0xf40464b6,
- 0x46b03411,
- 0xd81bf400,
+ 0xc67e50fc,
+ 0x64b60004,
+ 0x1a11f404,
+ 0x0004b27e,
+ 0x6a7e0003,
+ 0x884e0004,
+ 0x005d7e13,
+ 0x013cf000,
+/* 0x05f3: i2c_bitr_done */
+ 0xf80131f4,
+/* 0x05f5: i2c_get_byte */
+ 0x04000500,
+/* 0x05f9: i2c_get_byte_next */
+ 0x0154b608,
0xb60076bb,
0x50f90465,
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x05bb7e50,
+ 0x05b07e50,
0x0464b600,
- 0xbb0f11f4,
- 0x36b00076,
- 0x061bf401,
-/* 0x06a7: i2c_put_byte_done */
- 0xf80132f4,
-/* 0x06a9: i2c_addr */
- 0x0076bb00,
- 0xf90465b6,
- 0x04659450,
- 0xbd0256bb,
- 0x0475fd50,
- 0xf47e50fc,
- 0x64b60004,
- 0x2911f404,
- 0x012ec3e7,
- 0xfd0134b6,
- 0x76bb0553,
+ 0xfd2a11f4,
+ 0x42b60553,
+ 0xd81bf401,
+ 0x76bb0103,
0x0465b600,
0x659450f9,
0x0256bb04,
0x75fd50bd,
0x7e50fc04,
- 0xb600064f,
-/* 0x06ee: i2c_addr_done */
+ 0xb6000570,
+/* 0x0642: i2c_get_byte_done */
0x00f80464,
-/* 0x06f0: i2c_acquire_addr */
- 0xb6f8cec7,
- 0xe0b705e4,
- 0x00f8d014,
-/* 0x06fc: i2c_acquire */
- 0x0006f07e,
- 0x0000047e,
- 0x7e03d9f0,
- 0xf800002e,
-/* 0x070d: i2c_release */
- 0x06f07e00,
- 0x00047e00,
- 0x03daf000,
- 0x00002e7e,
-/* 0x071e: i2c_recv */
- 0x32f400f8,
- 0xf8c1c701,
- 0xb00214b6,
- 0x1ff52816,
- 0x13b80137,
- 0x98000bd4,
- 0x13b80032,
- 0x98000bac,
- 0x31f40031,
- 0xf9d0f902,
- 0xf1d0f9e0,
- 0xf1000067,
- 0x92100063,
- 0x76bb0167,
- 0x0465b600,
- 0x659450f9,
- 0x0256bb04,
- 0x75fd50bd,
- 0x7e50fc04,
- 0xb60006fc,
- 0xd0fc0464,
- 0xf500d6b0,
- 0x0500b01b,
- 0x0076bb00,
- 0xf90465b6,
- 0x04659450,
- 0xbd0256bb,
- 0x0475fd50,
- 0xa97e50fc,
- 0x64b60006,
- 0xcc11f504,
- 0xe0c5c700,
+/* 0x0644: i2c_put_byte */
+/* 0x0646: i2c_put_byte_next */
+ 0x42b60804,
+ 0x3854ff01,
0xb60076bb,
0x50f90465,
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x064f7e50,
+ 0x05707e50,
0x0464b600,
- 0x00a911f5,
- 0x76bb0105,
+ 0xb03411f4,
+ 0x1bf40046,
+ 0x0076bbd8,
+ 0xf90465b6,
+ 0x04659450,
+ 0xbd0256bb,
+ 0x0475fd50,
+ 0xb07e50fc,
+ 0x64b60005,
+ 0x0f11f404,
+ 0xb00076bb,
+ 0x1bf40136,
+ 0x0132f406,
+/* 0x069c: i2c_put_byte_done */
+/* 0x069e: i2c_addr */
+ 0x76bb00f8,
0x0465b600,
0x659450f9,
0x0256bb04,
0x75fd50bd,
0x7e50fc04,
- 0xb60006a9,
- 0x11f50464,
- 0x76bb0087,
+ 0xb60004e9,
+ 0x11f40464,
+ 0x2ec3e729,
+ 0x0134b601,
+ 0xbb0553fd,
+ 0x65b60076,
+ 0x9450f904,
+ 0x56bb0465,
+ 0xfd50bd02,
+ 0x50fc0475,
+ 0x0006447e,
+/* 0x06e3: i2c_addr_done */
+ 0xf80464b6,
+/* 0x06e5: i2c_acquire_addr */
+ 0xf8cec700,
+ 0xb705e4b6,
+ 0xf8d014e0,
+/* 0x06f1: i2c_acquire */
+ 0x06e57e00,
+ 0x00047e00,
+ 0x03d9f000,
+ 0x00002e7e,
+/* 0x0702: i2c_release */
+ 0xe57e00f8,
+ 0x047e0006,
+ 0xdaf00000,
+ 0x002e7e03,
+/* 0x0713: i2c_recv */
+ 0xf400f800,
+ 0xc1c70132,
+ 0x0214b6f8,
+ 0xf52816b0,
+ 0xb801371f,
+ 0x000bd413,
+ 0xb8003298,
+ 0x000bac13,
+ 0xf4003198,
+ 0xd0f90231,
+ 0xd0f9e0f9,
+ 0x000067f1,
+ 0x100063f1,
+ 0xbb016792,
+ 0x65b60076,
+ 0x9450f904,
+ 0x56bb0465,
+ 0xfd50bd02,
+ 0x50fc0475,
+ 0x0006f17e,
+ 0xfc0464b6,
+ 0x00d6b0d0,
+ 0x00b01bf5,
+ 0x76bb0005,
0x0465b600,
0x659450f9,
0x0256bb04,
0x75fd50bd,
0x7e50fc04,
- 0xb6000600,
- 0x11f40464,
- 0xe05bcb67,
- 0xb60076bb,
- 0x50f90465,
- 0xbb046594,
- 0x50bd0256,
- 0xfc0475fd,
- 0x054c7e50,
- 0x0464b600,
- 0x74bd5bb2,
-/* 0x0823: i2c_recv_not_rd08 */
- 0xb0410ef4,
- 0x1bf401d6,
- 0x7e00053b,
- 0xf40006a9,
- 0xc5c73211,
- 0x064f7ee0,
- 0x2811f400,
- 0xa97e0005,
+ 0xb600069e,
+ 0x11f50464,
+ 0xc5c700cc,
+ 0x0076bbe0,
+ 0xf90465b6,
+ 0x04659450,
+ 0xbd0256bb,
+ 0x0475fd50,
+ 0x447e50fc,
+ 0x64b60006,
+ 0xa911f504,
+ 0xbb010500,
+ 0x65b60076,
+ 0x9450f904,
+ 0x56bb0465,
+ 0xfd50bd02,
+ 0x50fc0475,
+ 0x00069e7e,
+ 0xf50464b6,
+ 0xbb008711,
+ 0x65b60076,
+ 0x9450f904,
+ 0x56bb0465,
+ 0xfd50bd02,
+ 0x50fc0475,
+ 0x0005f57e,
+ 0xf40464b6,
+ 0x5bcb6711,
+ 0x0076bbe0,
+ 0xf90465b6,
+ 0x04659450,
+ 0xbd0256bb,
+ 0x0475fd50,
+ 0x417e50fc,
+ 0x64b60005,
+ 0xbd5bb204,
+ 0x410ef474,
+/* 0x0818: i2c_recv_not_rd08 */
+ 0xf401d6b0,
+ 0x00053b1b,
+ 0x00069e7e,
+ 0xc73211f4,
+ 0x447ee0c5,
0x11f40006,
- 0xe0b5c71f,
- 0x00064f7e,
- 0x7e1511f4,
- 0xbd00054c,
- 0x08c5c774,
- 0xf4091bf4,
- 0x0ef40232,
-/* 0x0861: i2c_recv_not_wr08 */
-/* 0x0861: i2c_recv_done */
- 0xf8cec703,
- 0x00070d7e,
- 0xd0fce0fc,
- 0xb20912f4,
- 0x023f7e7c,
-/* 0x0875: i2c_recv_exit */
-/* 0x0877: i2c_init */
- 0xf800f800,
-/* 0x0879: test_recv */
- 0x04584100,
- 0xb60011cf,
- 0x58400110,
- 0x0001f604,
- 0xe7f104bd,
- 0xe3f1d900,
- 0x967e134f,
- 0x00f80001,
-/* 0x0898: test_init */
- 0x7e08004e,
- 0xf8000196,
-/* 0x08a1: idle_recv */
-/* 0x08a3: idle */
- 0xf400f800,
- 0x54410031,
+ 0x7e000528,
+ 0xf400069e,
+ 0xb5c71f11,
+ 0x06447ee0,
+ 0x1511f400,
+ 0x0005417e,
+ 0xc5c774bd,
+ 0x091bf408,
+ 0xf40232f4,
+/* 0x0856: i2c_recv_not_wr08 */
+/* 0x0856: i2c_recv_done */
+ 0xcec7030e,
+ 0x07027ef8,
+ 0xfce0fc00,
+ 0x0912f4d0,
+ 0x3f7e7cb2,
+/* 0x086a: i2c_recv_exit */
+ 0x00f80002,
+/* 0x086c: i2c_init */
+/* 0x086e: test_recv */
+ 0x584100f8,
0x0011cf04,
0x400110b6,
- 0x01f60454,
-/* 0x08b7: idle_loop */
- 0x0104bd00,
- 0x0232f458,
-/* 0x08bc: idle_proc */
-/* 0x08bc: idle_proc_exec */
- 0x1eb210f9,
- 0x0002487e,
- 0x11f410fc,
- 0x0231f409,
-/* 0x08cf: idle_proc_next */
- 0xb6f00ef4,
- 0x1fa65810,
- 0xf4e81bf4,
- 0x28f4e002,
- 0xc60ef400,
+ 0x01f60458,
+ 0xf104bd00,
+ 0xf1d900e7,
+ 0x7e134fe3,
+ 0xf8000196,
+/* 0x088d: test_init */
+ 0x08004e00,
+ 0x0001967e,
+/* 0x0896: idle_recv */
+ 0x00f800f8,
+/* 0x0898: idle */
+ 0x410031f4,
+ 0x11cf0454,
+ 0x0110b600,
+ 0xf6045440,
+ 0x04bd0001,
+/* 0x08ac: idle_loop */
+ 0x32f45801,
+/* 0x08b1: idle_proc */
+/* 0x08b1: idle_proc_exec */
+ 0xb210f902,
+ 0x02487e1e,
+ 0xf410fc00,
+ 0x31f40911,
+ 0xf00ef402,
+/* 0x08c4: idle_proc_next */
+ 0xa65810b6,
+ 0xe81bf41f,
+ 0xf4e002f4,
+ 0x0ef40028,
+ 0x000000c6,
+ 0x00000000,
+ 0x00000000,
0x00000000,
0x00000000,
0x00000000,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
index 254205cd5166..e087ce3041be 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
@@ -46,8 +46,8 @@ uint32_t nva3_pwr_data[] = {
0x00000000,
0x00000000,
0x584d454d,
- 0x0000054e,
- 0x00000540,
+ 0x00000542,
+ 0x00000534,
0x00000000,
0x00000000,
0x00000000,
@@ -68,8 +68,8 @@ uint32_t nva3_pwr_data[] = {
0x00000000,
0x00000000,
0x46524550,
- 0x00000552,
- 0x00000550,
+ 0x00000546,
+ 0x00000544,
0x00000000,
0x00000000,
0x00000000,
@@ -90,8 +90,8 @@ uint32_t nva3_pwr_data[] = {
0x00000000,
0x00000000,
0x5f433249,
- 0x00000982,
- 0x00000825,
+ 0x00000976,
+ 0x00000819,
0x00000000,
0x00000000,
0x00000000,
@@ -112,8 +112,8 @@ uint32_t nva3_pwr_data[] = {
0x00000000,
0x00000000,
0x54534554,
- 0x000009ab,
- 0x00000984,
+ 0x0000099f,
+ 0x00000978,
0x00000000,
0x00000000,
0x00000000,
@@ -134,8 +134,8 @@ uint32_t nva3_pwr_data[] = {
0x00000000,
0x00000000,
0x454c4449,
- 0x000009b7,
- 0x000009b5,
+ 0x000009ab,
+ 0x000009a9,
0x00000000,
0x00000000,
0x00000000,
@@ -239,10 +239,10 @@ uint32_t nva3_pwr_data[] = {
0x000004b7,
0x00040003,
0x00000000,
- 0x000004df,
+ 0x000004d3,
0x00010004,
0x00000000,
- 0x000004fc,
+ 0x000004f0,
/* 0x03ac: memx_func_tail */
/* 0x03ac: memx_data_head */
0x00000000,
@@ -1198,13 +1198,10 @@ uint32_t nva3_pwr_code[] = {
0x0810b601,
0x50f960f9,
0xe0fcd0fc,
- 0xf13f21f4,
- 0xfd140003,
- 0x05800506,
- 0xb604bd00,
+ 0xb63f21f4,
0x1bf40242,
-/* 0x04df: memx_func_wait */
- 0xf000f8dd,
+/* 0x04d3: memx_func_wait */
+ 0xf000f8e9,
0x84b62c87,
0x0088cf06,
0x98001e98,
@@ -1212,14 +1209,14 @@ uint32_t nva3_pwr_code[] = {
0x031b9802,
0xf41010b6,
0x00f89c21,
-/* 0x04fc: memx_func_delay */
+/* 0x04f0: memx_func_delay */
0xb6001e98,
0x21f40410,
-/* 0x0507: memx_exec */
+/* 0x04fb: memx_exec */
0xf900f87f,
0xb9d0f9e0,
0xb2b902c1,
-/* 0x0511: memx_exec_next */
+/* 0x0505: memx_exec_next */
0x00139802,
0x950410b6,
0x30f01034,
@@ -1228,112 +1225,112 @@ uint32_t nva3_pwr_code[] = {
0xec1ef406,
0xe0fcd0fc,
0x02b921f5,
-/* 0x0532: memx_info */
+/* 0x0526: memx_info */
0xc7f100f8,
0xb7f103ac,
0x21f50800,
0x00f802b9,
-/* 0x0540: memx_recv */
+/* 0x0534: memx_recv */
0xf401d6b0,
0xd6b0c40b,
0xe90bf400,
-/* 0x054e: memx_init */
+/* 0x0542: memx_init */
0x00f800f8,
-/* 0x0550: perf_recv */
-/* 0x0552: perf_init */
+/* 0x0544: perf_recv */
+/* 0x0546: perf_init */
0x00f800f8,
-/* 0x0554: i2c_drive_scl */
+/* 0x0548: i2c_drive_scl */
0xf40036b0,
0x07f1110b,
0x04b607e0,
0x0001d006,
0x00f804bd,
-/* 0x0568: i2c_drive_scl_lo */
+/* 0x055c: i2c_drive_scl_lo */
0x07e407f1,
0xd00604b6,
0x04bd0001,
-/* 0x0576: i2c_drive_sda */
+/* 0x056a: i2c_drive_sda */
0x36b000f8,
0x110bf400,
0x07e007f1,
0xd00604b6,
0x04bd0002,
-/* 0x058a: i2c_drive_sda_lo */
+/* 0x057e: i2c_drive_sda_lo */
0x07f100f8,
0x04b607e4,
0x0002d006,
0x00f804bd,
-/* 0x0598: i2c_sense_scl */
+/* 0x058c: i2c_sense_scl */
0xf10132f4,
0xb607c437,
0x33cf0634,
0x0431fd00,
0xf4060bf4,
-/* 0x05ae: i2c_sense_scl_done */
+/* 0x05a2: i2c_sense_scl_done */
0x00f80131,
-/* 0x05b0: i2c_sense_sda */
+/* 0x05a4: i2c_sense_sda */
0xf10132f4,
0xb607c437,
0x33cf0634,
0x0432fd00,
0xf4060bf4,
-/* 0x05c6: i2c_sense_sda_done */
+/* 0x05ba: i2c_sense_sda_done */
0x00f80131,
-/* 0x05c8: i2c_raise_scl */
+/* 0x05bc: i2c_raise_scl */
0x47f140f9,
0x37f00898,
- 0x5421f501,
-/* 0x05d5: i2c_raise_scl_wait */
+ 0x4821f501,
+/* 0x05c9: i2c_raise_scl_wait */
0xe8e7f105,
0x7f21f403,
- 0x059821f5,
+ 0x058c21f5,
0xb60901f4,
0x1bf40142,
-/* 0x05e9: i2c_raise_scl_done */
+/* 0x05dd: i2c_raise_scl_done */
0xf840fcef,
-/* 0x05ed: i2c_start */
- 0x9821f500,
+/* 0x05e1: i2c_start */
+ 0x8c21f500,
0x0d11f405,
- 0x05b021f5,
+ 0x05a421f5,
0xf40611f4,
-/* 0x05fe: i2c_start_rep */
+/* 0x05f2: i2c_start_rep */
0x37f0300e,
- 0x5421f500,
+ 0x4821f500,
0x0137f005,
- 0x057621f5,
+ 0x056a21f5,
0xb60076bb,
0x50f90465,
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xc821f550,
+ 0xbc21f550,
0x0464b605,
-/* 0x062b: i2c_start_send */
+/* 0x061f: i2c_start_send */
0xf01f11f4,
0x21f50037,
- 0xe7f10576,
+ 0xe7f1056a,
0x21f41388,
0x0037f07f,
- 0x055421f5,
+ 0x054821f5,
0x1388e7f1,
-/* 0x0647: i2c_start_out */
+/* 0x063b: i2c_start_out */
0xf87f21f4,
-/* 0x0649: i2c_stop */
+/* 0x063d: i2c_stop */
0x0037f000,
- 0x055421f5,
+ 0x054821f5,
0xf50037f0,
- 0xf1057621,
+ 0xf1056a21,
0xf403e8e7,
0x37f07f21,
- 0x5421f501,
+ 0x4821f501,
0x88e7f105,
0x7f21f413,
0xf50137f0,
- 0xf1057621,
+ 0xf1056a21,
0xf41388e7,
0x00f87f21,
-/* 0x067c: i2c_bitw */
- 0x057621f5,
+/* 0x0670: i2c_bitw */
+ 0x056a21f5,
0x03e8e7f1,
0xbb7f21f4,
0x65b60076,
@@ -1341,18 +1338,18 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x05c821f5,
+ 0x05bc21f5,
0xf40464b6,
0xe7f11811,
0x21f41388,
0x0037f07f,
- 0x055421f5,
+ 0x054821f5,
0x1388e7f1,
-/* 0x06bb: i2c_bitw_out */
+/* 0x06af: i2c_bitw_out */
0xf87f21f4,
-/* 0x06bd: i2c_bitr */
+/* 0x06b1: i2c_bitr */
0x0137f000,
- 0x057621f5,
+ 0x056a21f5,
0x03e8e7f1,
0xbb7f21f4,
0x65b60076,
@@ -1360,19 +1357,19 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x05c821f5,
+ 0x05bc21f5,
0xf40464b6,
0x21f51b11,
- 0x37f005b0,
- 0x5421f500,
+ 0x37f005a4,
+ 0x4821f500,
0x88e7f105,
0x7f21f413,
0xf4013cf0,
-/* 0x0702: i2c_bitr_done */
+/* 0x06f6: i2c_bitr_done */
0x00f80131,
-/* 0x0704: i2c_get_byte */
+/* 0x06f8: i2c_get_byte */
0xf00057f0,
-/* 0x070a: i2c_get_byte_next */
+/* 0x06fe: i2c_get_byte_next */
0x54b60847,
0x0076bb01,
0xf90465b6,
@@ -1380,7 +1377,7 @@ uint32_t nva3_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b606bd,
+ 0x64b606b1,
0x2b11f404,
0xb60553fd,
0x1bf40142,
@@ -1390,12 +1387,12 @@ uint32_t nva3_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x7c21f550,
+ 0x7021f550,
0x0464b606,
-/* 0x0754: i2c_get_byte_done */
-/* 0x0756: i2c_put_byte */
+/* 0x0748: i2c_get_byte_done */
+/* 0x074a: i2c_put_byte */
0x47f000f8,
-/* 0x0759: i2c_put_byte_next */
+/* 0x074d: i2c_put_byte_next */
0x0142b608,
0xbb3854ff,
0x65b60076,
@@ -1403,7 +1400,7 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x067c21f5,
+ 0x067021f5,
0xf40464b6,
0x46b03411,
0xd81bf400,
@@ -1412,21 +1409,21 @@ uint32_t nva3_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xbd21f550,
+ 0xb121f550,
0x0464b606,
0xbb0f11f4,
0x36b00076,
0x061bf401,
-/* 0x07af: i2c_put_byte_done */
+/* 0x07a3: i2c_put_byte_done */
0xf80132f4,
-/* 0x07b1: i2c_addr */
+/* 0x07a5: i2c_addr */
0x0076bb00,
0xf90465b6,
0x04659450,
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b605ed,
+ 0x64b605e1,
0x2911f404,
0x012ec3e7,
0xfd0134b6,
@@ -1436,24 +1433,24 @@ uint32_t nva3_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6075621,
-/* 0x07f6: i2c_addr_done */
+ 0xb6074a21,
+/* 0x07ea: i2c_addr_done */
0x00f80464,
-/* 0x07f8: i2c_acquire_addr */
+/* 0x07ec: i2c_acquire_addr */
0xb6f8cec7,
0xe0b702e4,
0xee980bfc,
-/* 0x0807: i2c_acquire */
+/* 0x07fb: i2c_acquire */
0xf500f800,
- 0xf407f821,
+ 0xf407ec21,
0xd9f00421,
0x3f21f403,
-/* 0x0816: i2c_release */
+/* 0x080a: i2c_release */
0x21f500f8,
- 0x21f407f8,
+ 0x21f407ec,
0x03daf004,
0xf83f21f4,
-/* 0x0825: i2c_recv */
+/* 0x0819: i2c_recv */
0x0132f400,
0xb6f8c1c7,
0x16b00214,
@@ -1472,7 +1469,7 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x080721f5,
+ 0x07fb21f5,
0xfc0464b6,
0x00d6b0d0,
0x00b31bf5,
@@ -1482,7 +1479,7 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x07b121f5,
+ 0x07a521f5,
0xf50464b6,
0xc700d011,
0x76bbe0c5,
@@ -1491,7 +1488,7 @@ uint32_t nva3_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6075621,
+ 0xb6074a21,
0x11f50464,
0x57f000ad,
0x0076bb01,
@@ -1500,7 +1497,7 @@ uint32_t nva3_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b607b1,
+ 0x64b607a5,
0x8a11f504,
0x0076bb00,
0xf90465b6,
@@ -1508,7 +1505,7 @@ uint32_t nva3_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b60704,
+ 0x64b606f8,
0x6a11f404,
0xbbe05bcb,
0x65b60076,
@@ -1516,38 +1513,38 @@ uint32_t nva3_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x064921f5,
+ 0x063d21f5,
0xb90464b6,
0x74bd025b,
-/* 0x092b: i2c_recv_not_rd08 */
+/* 0x091f: i2c_recv_not_rd08 */
0xb0430ef4,
0x1bf401d6,
0x0057f03d,
- 0x07b121f5,
+ 0x07a521f5,
0xc73311f4,
0x21f5e0c5,
- 0x11f40756,
+ 0x11f4074a,
0x0057f029,
- 0x07b121f5,
+ 0x07a521f5,
0xc71f11f4,
0x21f5e0b5,
- 0x11f40756,
- 0x4921f515,
+ 0x11f4074a,
+ 0x3d21f515,
0xc774bd06,
0x1bf408c5,
0x0232f409,
-/* 0x096b: i2c_recv_not_wr08 */
-/* 0x096b: i2c_recv_done */
+/* 0x095f: i2c_recv_not_wr08 */
+/* 0x095f: i2c_recv_done */
0xc7030ef4,
0x21f5f8ce,
- 0xe0fc0816,
+ 0xe0fc080a,
0x12f4d0fc,
0x027cb90a,
0x02b921f5,
-/* 0x0980: i2c_recv_exit */
-/* 0x0982: i2c_init */
+/* 0x0974: i2c_recv_exit */
+/* 0x0976: i2c_init */
0x00f800f8,
-/* 0x0984: test_recv */
+/* 0x0978: test_recv */
0x05d817f1,
0xcf0614b6,
0x10b60011,
@@ -1557,12 +1554,12 @@ uint32_t nva3_pwr_code[] = {
0x00e7f104,
0x4fe3f1d9,
0xf521f513,
-/* 0x09ab: test_init */
+/* 0x099f: test_init */
0xf100f801,
0xf50800e7,
0xf801f521,
-/* 0x09b5: idle_recv */
-/* 0x09b7: idle */
+/* 0x09a9: idle_recv */
+/* 0x09ab: idle */
0xf400f800,
0x17f10031,
0x14b605d4,
@@ -1570,20 +1567,23 @@ uint32_t nva3_pwr_code[] = {
0xf10110b6,
0xb605d407,
0x01d00604,
-/* 0x09d3: idle_loop */
+/* 0x09c7: idle_loop */
0xf004bd00,
0x32f45817,
-/* 0x09d9: idle_proc */
-/* 0x09d9: idle_proc_exec */
+/* 0x09cd: idle_proc */
+/* 0x09cd: idle_proc_exec */
0xb910f902,
0x21f5021e,
0x10fc02c2,
0xf40911f4,
0x0ef40231,
-/* 0x09ed: idle_proc_next */
+/* 0x09e1: idle_proc_next */
0x5810b6ef,
0xf4061fb8,
0x02f4e61b,
0x0028f4dd,
0x00bb0ef4,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
index 7ac87405d01b..0773ff0e3dc3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
@@ -46,8 +46,8 @@ uint32_t nvc0_pwr_data[] = {
0x00000000,
0x00000000,
0x584d454d,
- 0x0000054e,
- 0x00000540,
+ 0x00000542,
+ 0x00000534,
0x00000000,
0x00000000,
0x00000000,
@@ -68,8 +68,8 @@ uint32_t nvc0_pwr_data[] = {
0x00000000,
0x00000000,
0x46524550,
- 0x00000552,
- 0x00000550,
+ 0x00000546,
+ 0x00000544,
0x00000000,
0x00000000,
0x00000000,
@@ -90,8 +90,8 @@ uint32_t nvc0_pwr_data[] = {
0x00000000,
0x00000000,
0x5f433249,
- 0x00000982,
- 0x00000825,
+ 0x00000976,
+ 0x00000819,
0x00000000,
0x00000000,
0x00000000,
@@ -112,8 +112,8 @@ uint32_t nvc0_pwr_data[] = {
0x00000000,
0x00000000,
0x54534554,
- 0x000009ab,
- 0x00000984,
+ 0x0000099f,
+ 0x00000978,
0x00000000,
0x00000000,
0x00000000,
@@ -134,8 +134,8 @@ uint32_t nvc0_pwr_data[] = {
0x00000000,
0x00000000,
0x454c4449,
- 0x000009b7,
- 0x000009b5,
+ 0x000009ab,
+ 0x000009a9,
0x00000000,
0x00000000,
0x00000000,
@@ -239,10 +239,10 @@ uint32_t nvc0_pwr_data[] = {
0x000004b7,
0x00040003,
0x00000000,
- 0x000004df,
+ 0x000004d3,
0x00010004,
0x00000000,
- 0x000004fc,
+ 0x000004f0,
/* 0x03ac: memx_func_tail */
/* 0x03ac: memx_data_head */
0x00000000,
@@ -1198,13 +1198,10 @@ uint32_t nvc0_pwr_code[] = {
0x0810b601,
0x50f960f9,
0xe0fcd0fc,
- 0xf13f21f4,
- 0xfd140003,
- 0x05800506,
- 0xb604bd00,
+ 0xb63f21f4,
0x1bf40242,
-/* 0x04df: memx_func_wait */
- 0xf000f8dd,
+/* 0x04d3: memx_func_wait */
+ 0xf000f8e9,
0x84b62c87,
0x0088cf06,
0x98001e98,
@@ -1212,14 +1209,14 @@ uint32_t nvc0_pwr_code[] = {
0x031b9802,
0xf41010b6,
0x00f89c21,
-/* 0x04fc: memx_func_delay */
+/* 0x04f0: memx_func_delay */
0xb6001e98,
0x21f40410,
-/* 0x0507: memx_exec */
+/* 0x04fb: memx_exec */
0xf900f87f,
0xb9d0f9e0,
0xb2b902c1,
-/* 0x0511: memx_exec_next */
+/* 0x0505: memx_exec_next */
0x00139802,
0x950410b6,
0x30f01034,
@@ -1228,112 +1225,112 @@ uint32_t nvc0_pwr_code[] = {
0xec1ef406,
0xe0fcd0fc,
0x02b921f5,
-/* 0x0532: memx_info */
+/* 0x0526: memx_info */
0xc7f100f8,
0xb7f103ac,
0x21f50800,
0x00f802b9,
-/* 0x0540: memx_recv */
+/* 0x0534: memx_recv */
0xf401d6b0,
0xd6b0c40b,
0xe90bf400,
-/* 0x054e: memx_init */
+/* 0x0542: memx_init */
0x00f800f8,
-/* 0x0550: perf_recv */
-/* 0x0552: perf_init */
+/* 0x0544: perf_recv */
+/* 0x0546: perf_init */
0x00f800f8,
-/* 0x0554: i2c_drive_scl */
+/* 0x0548: i2c_drive_scl */
0xf40036b0,
0x07f1110b,
0x04b607e0,
0x0001d006,
0x00f804bd,
-/* 0x0568: i2c_drive_scl_lo */
+/* 0x055c: i2c_drive_scl_lo */
0x07e407f1,
0xd00604b6,
0x04bd0001,
-/* 0x0576: i2c_drive_sda */
+/* 0x056a: i2c_drive_sda */
0x36b000f8,
0x110bf400,
0x07e007f1,
0xd00604b6,
0x04bd0002,
-/* 0x058a: i2c_drive_sda_lo */
+/* 0x057e: i2c_drive_sda_lo */
0x07f100f8,
0x04b607e4,
0x0002d006,
0x00f804bd,
-/* 0x0598: i2c_sense_scl */
+/* 0x058c: i2c_sense_scl */
0xf10132f4,
0xb607c437,
0x33cf0634,
0x0431fd00,
0xf4060bf4,
-/* 0x05ae: i2c_sense_scl_done */
+/* 0x05a2: i2c_sense_scl_done */
0x00f80131,
-/* 0x05b0: i2c_sense_sda */
+/* 0x05a4: i2c_sense_sda */
0xf10132f4,
0xb607c437,
0x33cf0634,
0x0432fd00,
0xf4060bf4,
-/* 0x05c6: i2c_sense_sda_done */
+/* 0x05ba: i2c_sense_sda_done */
0x00f80131,
-/* 0x05c8: i2c_raise_scl */
+/* 0x05bc: i2c_raise_scl */
0x47f140f9,
0x37f00898,
- 0x5421f501,
-/* 0x05d5: i2c_raise_scl_wait */
+ 0x4821f501,
+/* 0x05c9: i2c_raise_scl_wait */
0xe8e7f105,
0x7f21f403,
- 0x059821f5,
+ 0x058c21f5,
0xb60901f4,
0x1bf40142,
-/* 0x05e9: i2c_raise_scl_done */
+/* 0x05dd: i2c_raise_scl_done */
0xf840fcef,
-/* 0x05ed: i2c_start */
- 0x9821f500,
+/* 0x05e1: i2c_start */
+ 0x8c21f500,
0x0d11f405,
- 0x05b021f5,
+ 0x05a421f5,
0xf40611f4,
-/* 0x05fe: i2c_start_rep */
+/* 0x05f2: i2c_start_rep */
0x37f0300e,
- 0x5421f500,
+ 0x4821f500,
0x0137f005,
- 0x057621f5,
+ 0x056a21f5,
0xb60076bb,
0x50f90465,
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xc821f550,
+ 0xbc21f550,
0x0464b605,
-/* 0x062b: i2c_start_send */
+/* 0x061f: i2c_start_send */
0xf01f11f4,
0x21f50037,
- 0xe7f10576,
+ 0xe7f1056a,
0x21f41388,
0x0037f07f,
- 0x055421f5,
+ 0x054821f5,
0x1388e7f1,
-/* 0x0647: i2c_start_out */
+/* 0x063b: i2c_start_out */
0xf87f21f4,
-/* 0x0649: i2c_stop */
+/* 0x063d: i2c_stop */
0x0037f000,
- 0x055421f5,
+ 0x054821f5,
0xf50037f0,
- 0xf1057621,
+ 0xf1056a21,
0xf403e8e7,
0x37f07f21,
- 0x5421f501,
+ 0x4821f501,
0x88e7f105,
0x7f21f413,
0xf50137f0,
- 0xf1057621,
+ 0xf1056a21,
0xf41388e7,
0x00f87f21,
-/* 0x067c: i2c_bitw */
- 0x057621f5,
+/* 0x0670: i2c_bitw */
+ 0x056a21f5,
0x03e8e7f1,
0xbb7f21f4,
0x65b60076,
@@ -1341,18 +1338,18 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x05c821f5,
+ 0x05bc21f5,
0xf40464b6,
0xe7f11811,
0x21f41388,
0x0037f07f,
- 0x055421f5,
+ 0x054821f5,
0x1388e7f1,
-/* 0x06bb: i2c_bitw_out */
+/* 0x06af: i2c_bitw_out */
0xf87f21f4,
-/* 0x06bd: i2c_bitr */
+/* 0x06b1: i2c_bitr */
0x0137f000,
- 0x057621f5,
+ 0x056a21f5,
0x03e8e7f1,
0xbb7f21f4,
0x65b60076,
@@ -1360,19 +1357,19 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x05c821f5,
+ 0x05bc21f5,
0xf40464b6,
0x21f51b11,
- 0x37f005b0,
- 0x5421f500,
+ 0x37f005a4,
+ 0x4821f500,
0x88e7f105,
0x7f21f413,
0xf4013cf0,
-/* 0x0702: i2c_bitr_done */
+/* 0x06f6: i2c_bitr_done */
0x00f80131,
-/* 0x0704: i2c_get_byte */
+/* 0x06f8: i2c_get_byte */
0xf00057f0,
-/* 0x070a: i2c_get_byte_next */
+/* 0x06fe: i2c_get_byte_next */
0x54b60847,
0x0076bb01,
0xf90465b6,
@@ -1380,7 +1377,7 @@ uint32_t nvc0_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b606bd,
+ 0x64b606b1,
0x2b11f404,
0xb60553fd,
0x1bf40142,
@@ -1390,12 +1387,12 @@ uint32_t nvc0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x7c21f550,
+ 0x7021f550,
0x0464b606,
-/* 0x0754: i2c_get_byte_done */
-/* 0x0756: i2c_put_byte */
+/* 0x0748: i2c_get_byte_done */
+/* 0x074a: i2c_put_byte */
0x47f000f8,
-/* 0x0759: i2c_put_byte_next */
+/* 0x074d: i2c_put_byte_next */
0x0142b608,
0xbb3854ff,
0x65b60076,
@@ -1403,7 +1400,7 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x067c21f5,
+ 0x067021f5,
0xf40464b6,
0x46b03411,
0xd81bf400,
@@ -1412,21 +1409,21 @@ uint32_t nvc0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xbd21f550,
+ 0xb121f550,
0x0464b606,
0xbb0f11f4,
0x36b00076,
0x061bf401,
-/* 0x07af: i2c_put_byte_done */
+/* 0x07a3: i2c_put_byte_done */
0xf80132f4,
-/* 0x07b1: i2c_addr */
+/* 0x07a5: i2c_addr */
0x0076bb00,
0xf90465b6,
0x04659450,
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b605ed,
+ 0x64b605e1,
0x2911f404,
0x012ec3e7,
0xfd0134b6,
@@ -1436,24 +1433,24 @@ uint32_t nvc0_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6075621,
-/* 0x07f6: i2c_addr_done */
+ 0xb6074a21,
+/* 0x07ea: i2c_addr_done */
0x00f80464,
-/* 0x07f8: i2c_acquire_addr */
+/* 0x07ec: i2c_acquire_addr */
0xb6f8cec7,
0xe0b702e4,
0xee980bfc,
-/* 0x0807: i2c_acquire */
+/* 0x07fb: i2c_acquire */
0xf500f800,
- 0xf407f821,
+ 0xf407ec21,
0xd9f00421,
0x3f21f403,
-/* 0x0816: i2c_release */
+/* 0x080a: i2c_release */
0x21f500f8,
- 0x21f407f8,
+ 0x21f407ec,
0x03daf004,
0xf83f21f4,
-/* 0x0825: i2c_recv */
+/* 0x0819: i2c_recv */
0x0132f400,
0xb6f8c1c7,
0x16b00214,
@@ -1472,7 +1469,7 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x080721f5,
+ 0x07fb21f5,
0xfc0464b6,
0x00d6b0d0,
0x00b31bf5,
@@ -1482,7 +1479,7 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x07b121f5,
+ 0x07a521f5,
0xf50464b6,
0xc700d011,
0x76bbe0c5,
@@ -1491,7 +1488,7 @@ uint32_t nvc0_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6075621,
+ 0xb6074a21,
0x11f50464,
0x57f000ad,
0x0076bb01,
@@ -1500,7 +1497,7 @@ uint32_t nvc0_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b607b1,
+ 0x64b607a5,
0x8a11f504,
0x0076bb00,
0xf90465b6,
@@ -1508,7 +1505,7 @@ uint32_t nvc0_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b60704,
+ 0x64b606f8,
0x6a11f404,
0xbbe05bcb,
0x65b60076,
@@ -1516,38 +1513,38 @@ uint32_t nvc0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x064921f5,
+ 0x063d21f5,
0xb90464b6,
0x74bd025b,
-/* 0x092b: i2c_recv_not_rd08 */
+/* 0x091f: i2c_recv_not_rd08 */
0xb0430ef4,
0x1bf401d6,
0x0057f03d,
- 0x07b121f5,
+ 0x07a521f5,
0xc73311f4,
0x21f5e0c5,
- 0x11f40756,
+ 0x11f4074a,
0x0057f029,
- 0x07b121f5,
+ 0x07a521f5,
0xc71f11f4,
0x21f5e0b5,
- 0x11f40756,
- 0x4921f515,
+ 0x11f4074a,
+ 0x3d21f515,
0xc774bd06,
0x1bf408c5,
0x0232f409,
-/* 0x096b: i2c_recv_not_wr08 */
-/* 0x096b: i2c_recv_done */
+/* 0x095f: i2c_recv_not_wr08 */
+/* 0x095f: i2c_recv_done */
0xc7030ef4,
0x21f5f8ce,
- 0xe0fc0816,
+ 0xe0fc080a,
0x12f4d0fc,
0x027cb90a,
0x02b921f5,
-/* 0x0980: i2c_recv_exit */
-/* 0x0982: i2c_init */
+/* 0x0974: i2c_recv_exit */
+/* 0x0976: i2c_init */
0x00f800f8,
-/* 0x0984: test_recv */
+/* 0x0978: test_recv */
0x05d817f1,
0xcf0614b6,
0x10b60011,
@@ -1557,12 +1554,12 @@ uint32_t nvc0_pwr_code[] = {
0x00e7f104,
0x4fe3f1d9,
0xf521f513,
-/* 0x09ab: test_init */
+/* 0x099f: test_init */
0xf100f801,
0xf50800e7,
0xf801f521,
-/* 0x09b5: idle_recv */
-/* 0x09b7: idle */
+/* 0x09a9: idle_recv */
+/* 0x09ab: idle */
0xf400f800,
0x17f10031,
0x14b605d4,
@@ -1570,20 +1567,23 @@ uint32_t nvc0_pwr_code[] = {
0xf10110b6,
0xb605d407,
0x01d00604,
-/* 0x09d3: idle_loop */
+/* 0x09c7: idle_loop */
0xf004bd00,
0x32f45817,
-/* 0x09d9: idle_proc */
-/* 0x09d9: idle_proc_exec */
+/* 0x09cd: idle_proc */
+/* 0x09cd: idle_proc_exec */
0xb910f902,
0x21f5021e,
0x10fc02c2,
0xf40911f4,
0x0ef40231,
-/* 0x09ed: idle_proc_next */
+/* 0x09e1: idle_proc_next */
0x5810b6ef,
0xf4061fb8,
0x02f4e61b,
0x0028f4dd,
0x00bb0ef4,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
index cd9ff1a73284..8d369b3faaba 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
@@ -46,8 +46,8 @@ uint32_t nvd0_pwr_data[] = {
0x00000000,
0x00000000,
0x584d454d,
- 0x000004c4,
- 0x000004b6,
+ 0x000004b8,
+ 0x000004aa,
0x00000000,
0x00000000,
0x00000000,
@@ -68,8 +68,8 @@ uint32_t nvd0_pwr_data[] = {
0x00000000,
0x00000000,
0x46524550,
- 0x000004c8,
- 0x000004c6,
+ 0x000004bc,
+ 0x000004ba,
0x00000000,
0x00000000,
0x00000000,
@@ -90,8 +90,8 @@ uint32_t nvd0_pwr_data[] = {
0x00000000,
0x00000000,
0x5f433249,
- 0x000008e3,
- 0x00000786,
+ 0x000008d7,
+ 0x0000077a,
0x00000000,
0x00000000,
0x00000000,
@@ -112,8 +112,8 @@ uint32_t nvd0_pwr_data[] = {
0x00000000,
0x00000000,
0x54534554,
- 0x00000906,
- 0x000008e5,
+ 0x000008fa,
+ 0x000008d9,
0x00000000,
0x00000000,
0x00000000,
@@ -134,8 +134,8 @@ uint32_t nvd0_pwr_data[] = {
0x00000000,
0x00000000,
0x454c4449,
- 0x00000912,
- 0x00000910,
+ 0x00000906,
+ 0x00000904,
0x00000000,
0x00000000,
0x00000000,
@@ -239,10 +239,10 @@ uint32_t nvd0_pwr_data[] = {
0x00000430,
0x00040003,
0x00000000,
- 0x00000458,
+ 0x0000044c,
0x00010004,
0x00000000,
- 0x00000472,
+ 0x00000466,
/* 0x03ac: memx_func_tail */
/* 0x03ac: memx_data_head */
0x00000000,
@@ -1100,26 +1100,23 @@ uint32_t nvd0_pwr_code[] = {
0xf960f908,
0xfcd0fc50,
0x3321f4e0,
- 0x140003f1,
- 0x800506fd,
- 0x04bd0005,
0xf40242b6,
- 0x00f8dd1b,
-/* 0x0458: memx_func_wait */
+ 0x00f8e91b,
+/* 0x044c: memx_func_wait */
0xcf2c87f0,
0x1e980088,
0x011d9800,
0x98021c98,
0x10b6031b,
0x7e21f410,
-/* 0x0472: memx_func_delay */
+/* 0x0466: memx_func_delay */
0x1e9800f8,
0x0410b600,
0xf86721f4,
-/* 0x047d: memx_exec */
+/* 0x0471: memx_exec */
0xf9e0f900,
0x02c1b9d0,
-/* 0x0487: memx_exec_next */
+/* 0x047b: memx_exec_next */
0x9802b2b9,
0x10b60013,
0x10349504,
@@ -1129,107 +1126,107 @@ uint32_t nvd0_pwr_code[] = {
0xd0fcec1e,
0x21f5e0fc,
0x00f8026b,
-/* 0x04a8: memx_info */
+/* 0x049c: memx_info */
0x03acc7f1,
0x0800b7f1,
0x026b21f5,
-/* 0x04b6: memx_recv */
+/* 0x04aa: memx_recv */
0xd6b000f8,
0xc40bf401,
0xf400d6b0,
0x00f8e90b,
-/* 0x04c4: memx_init */
-/* 0x04c6: perf_recv */
+/* 0x04b8: memx_init */
+/* 0x04ba: perf_recv */
0x00f800f8,
-/* 0x04c8: perf_init */
-/* 0x04ca: i2c_drive_scl */
+/* 0x04bc: perf_init */
+/* 0x04be: i2c_drive_scl */
0x36b000f8,
0x0e0bf400,
0x07e007f1,
0xbd0001d0,
-/* 0x04db: i2c_drive_scl_lo */
+/* 0x04cf: i2c_drive_scl_lo */
0xf100f804,
0xd007e407,
0x04bd0001,
-/* 0x04e6: i2c_drive_sda */
+/* 0x04da: i2c_drive_sda */
0x36b000f8,
0x0e0bf400,
0x07e007f1,
0xbd0002d0,
-/* 0x04f7: i2c_drive_sda_lo */
+/* 0x04eb: i2c_drive_sda_lo */
0xf100f804,
0xd007e407,
0x04bd0002,
-/* 0x0502: i2c_sense_scl */
+/* 0x04f6: i2c_sense_scl */
0x32f400f8,
0xc437f101,
0x0033cf07,
0xf40431fd,
0x31f4060b,
-/* 0x0515: i2c_sense_scl_done */
-/* 0x0517: i2c_sense_sda */
+/* 0x0509: i2c_sense_scl_done */
+/* 0x050b: i2c_sense_sda */
0xf400f801,
0x37f10132,
0x33cf07c4,
0x0432fd00,
0xf4060bf4,
-/* 0x052a: i2c_sense_sda_done */
+/* 0x051e: i2c_sense_sda_done */
0x00f80131,
-/* 0x052c: i2c_raise_scl */
+/* 0x0520: i2c_raise_scl */
0x47f140f9,
0x37f00898,
- 0xca21f501,
-/* 0x0539: i2c_raise_scl_wait */
+ 0xbe21f501,
+/* 0x052d: i2c_raise_scl_wait */
0xe8e7f104,
0x6721f403,
- 0x050221f5,
+ 0x04f621f5,
0xb60901f4,
0x1bf40142,
-/* 0x054d: i2c_raise_scl_done */
+/* 0x0541: i2c_raise_scl_done */
0xf840fcef,
-/* 0x0551: i2c_start */
- 0x0221f500,
- 0x0d11f405,
- 0x051721f5,
+/* 0x0545: i2c_start */
+ 0xf621f500,
+ 0x0d11f404,
+ 0x050b21f5,
0xf40611f4,
-/* 0x0562: i2c_start_rep */
+/* 0x0556: i2c_start_rep */
0x37f0300e,
- 0xca21f500,
+ 0xbe21f500,
0x0137f004,
- 0x04e621f5,
+ 0x04da21f5,
0xb60076bb,
0x50f90465,
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x2c21f550,
+ 0x2021f550,
0x0464b605,
-/* 0x058f: i2c_start_send */
+/* 0x0583: i2c_start_send */
0xf01f11f4,
0x21f50037,
- 0xe7f104e6,
+ 0xe7f104da,
0x21f41388,
0x0037f067,
- 0x04ca21f5,
+ 0x04be21f5,
0x1388e7f1,
-/* 0x05ab: i2c_start_out */
+/* 0x059f: i2c_start_out */
0xf86721f4,
-/* 0x05ad: i2c_stop */
+/* 0x05a1: i2c_stop */
0x0037f000,
- 0x04ca21f5,
+ 0x04be21f5,
0xf50037f0,
- 0xf104e621,
+ 0xf104da21,
0xf403e8e7,
0x37f06721,
- 0xca21f501,
+ 0xbe21f501,
0x88e7f104,
0x6721f413,
0xf50137f0,
- 0xf104e621,
+ 0xf104da21,
0xf41388e7,
0x00f86721,
-/* 0x05e0: i2c_bitw */
- 0x04e621f5,
+/* 0x05d4: i2c_bitw */
+ 0x04da21f5,
0x03e8e7f1,
0xbb6721f4,
0x65b60076,
@@ -1237,18 +1234,18 @@ uint32_t nvd0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x052c21f5,
+ 0x052021f5,
0xf40464b6,
0xe7f11811,
0x21f41388,
0x0037f067,
- 0x04ca21f5,
+ 0x04be21f5,
0x1388e7f1,
-/* 0x061f: i2c_bitw_out */
+/* 0x0613: i2c_bitw_out */
0xf86721f4,
-/* 0x0621: i2c_bitr */
+/* 0x0615: i2c_bitr */
0x0137f000,
- 0x04e621f5,
+ 0x04da21f5,
0x03e8e7f1,
0xbb6721f4,
0x65b60076,
@@ -1256,19 +1253,19 @@ uint32_t nvd0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x052c21f5,
+ 0x052021f5,
0xf40464b6,
0x21f51b11,
- 0x37f00517,
- 0xca21f500,
+ 0x37f0050b,
+ 0xbe21f500,
0x88e7f104,
0x6721f413,
0xf4013cf0,
-/* 0x0666: i2c_bitr_done */
+/* 0x065a: i2c_bitr_done */
0x00f80131,
-/* 0x0668: i2c_get_byte */
+/* 0x065c: i2c_get_byte */
0xf00057f0,
-/* 0x066e: i2c_get_byte_next */
+/* 0x0662: i2c_get_byte_next */
0x54b60847,
0x0076bb01,
0xf90465b6,
@@ -1276,7 +1273,7 @@ uint32_t nvd0_pwr_code[] = {
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b60621,
+ 0x64b60615,
0x2b11f404,
0xb60553fd,
0x1bf40142,
@@ -1286,12 +1283,12 @@ uint32_t nvd0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xe021f550,
+ 0xd421f550,
0x0464b605,
-/* 0x06b8: i2c_get_byte_done */
-/* 0x06ba: i2c_put_byte */
+/* 0x06ac: i2c_get_byte_done */
+/* 0x06ae: i2c_put_byte */
0x47f000f8,
-/* 0x06bd: i2c_put_byte_next */
+/* 0x06b1: i2c_put_byte_next */
0x0142b608,
0xbb3854ff,
0x65b60076,
@@ -1299,7 +1296,7 @@ uint32_t nvd0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x05e021f5,
+ 0x05d421f5,
0xf40464b6,
0x46b03411,
0xd81bf400,
@@ -1308,21 +1305,21 @@ uint32_t nvd0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x2121f550,
+ 0x1521f550,
0x0464b606,
0xbb0f11f4,
0x36b00076,
0x061bf401,
-/* 0x0713: i2c_put_byte_done */
+/* 0x0707: i2c_put_byte_done */
0xf80132f4,
-/* 0x0715: i2c_addr */
+/* 0x0709: i2c_addr */
0x0076bb00,
0xf90465b6,
0x04659450,
0xbd0256bb,
0x0475fd50,
0x21f550fc,
- 0x64b60551,
+ 0x64b60545,
0x2911f404,
0x012ec3e7,
0xfd0134b6,
@@ -1332,23 +1329,23 @@ uint32_t nvd0_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb606ba21,
-/* 0x075a: i2c_addr_done */
+ 0xb606ae21,
+/* 0x074e: i2c_addr_done */
0x00f80464,
-/* 0x075c: i2c_acquire_addr */
+/* 0x0750: i2c_acquire_addr */
0xb6f8cec7,
0xe0b705e4,
0x00f8d014,
-/* 0x0768: i2c_acquire */
- 0x075c21f5,
+/* 0x075c: i2c_acquire */
+ 0x075021f5,
0xf00421f4,
0x21f403d9,
-/* 0x0777: i2c_release */
+/* 0x076b: i2c_release */
0xf500f833,
- 0xf4075c21,
+ 0xf4075021,
0xdaf00421,
0x3321f403,
-/* 0x0786: i2c_recv */
+/* 0x077a: i2c_recv */
0x32f400f8,
0xf8c1c701,
0xb00214b6,
@@ -1367,7 +1364,7 @@ uint32_t nvd0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x6821f550,
+ 0x5c21f550,
0x0464b607,
0xd6b0d0fc,
0xb31bf500,
@@ -1377,7 +1374,7 @@ uint32_t nvd0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0x1521f550,
+ 0x0921f550,
0x0464b607,
0x00d011f5,
0xbbe0c5c7,
@@ -1386,7 +1383,7 @@ uint32_t nvd0_pwr_code[] = {
0x56bb0465,
0xfd50bd02,
0x50fc0475,
- 0x06ba21f5,
+ 0x06ae21f5,
0xf50464b6,
0xf000ad11,
0x76bb0157,
@@ -1395,7 +1392,7 @@ uint32_t nvd0_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6071521,
+ 0xb6070921,
0x11f50464,
0x76bb008a,
0x0465b600,
@@ -1403,7 +1400,7 @@ uint32_t nvd0_pwr_code[] = {
0x0256bb04,
0x75fd50bd,
0xf550fc04,
- 0xb6066821,
+ 0xb6065c21,
0x11f40464,
0xe05bcb6a,
0xb60076bb,
@@ -1411,38 +1408,38 @@ uint32_t nvd0_pwr_code[] = {
0xbb046594,
0x50bd0256,
0xfc0475fd,
- 0xad21f550,
+ 0xa121f550,
0x0464b605,
0xbd025bb9,
0x430ef474,
-/* 0x088c: i2c_recv_not_rd08 */
+/* 0x0880: i2c_recv_not_rd08 */
0xf401d6b0,
0x57f03d1b,
- 0x1521f500,
+ 0x0921f500,
0x3311f407,
0xf5e0c5c7,
- 0xf406ba21,
+ 0xf406ae21,
0x57f02911,
- 0x1521f500,
+ 0x0921f500,
0x1f11f407,
0xf5e0b5c7,
- 0xf406ba21,
+ 0xf406ae21,
0x21f51511,
- 0x74bd05ad,
+ 0x74bd05a1,
0xf408c5c7,
0x32f4091b,
0x030ef402,
-/* 0x08cc: i2c_recv_not_wr08 */
-/* 0x08cc: i2c_recv_done */
+/* 0x08c0: i2c_recv_not_wr08 */
+/* 0x08c0: i2c_recv_done */
0xf5f8cec7,
- 0xfc077721,
+ 0xfc076b21,
0xf4d0fce0,
0x7cb90a12,
0x6b21f502,
-/* 0x08e1: i2c_recv_exit */
-/* 0x08e3: i2c_init */
+/* 0x08d5: i2c_recv_exit */
+/* 0x08d7: i2c_init */
0xf800f802,
-/* 0x08e5: test_recv */
+/* 0x08d9: test_recv */
0xd817f100,
0x0011cf05,
0xf10110b6,
@@ -1451,28 +1448,28 @@ uint32_t nvd0_pwr_code[] = {
0xd900e7f1,
0x134fe3f1,
0x01b621f5,
-/* 0x0906: test_init */
+/* 0x08fa: test_init */
0xe7f100f8,
0x21f50800,
0x00f801b6,
-/* 0x0910: idle_recv */
-/* 0x0912: idle */
+/* 0x0904: idle_recv */
+/* 0x0906: idle */
0x31f400f8,
0xd417f100,
0x0011cf05,
0xf10110b6,
0xd005d407,
0x04bd0001,
-/* 0x0928: idle_loop */
+/* 0x091c: idle_loop */
0xf45817f0,
-/* 0x092e: idle_proc */
-/* 0x092e: idle_proc_exec */
+/* 0x0922: idle_proc */
+/* 0x0922: idle_proc_exec */
0x10f90232,
0xf5021eb9,
0xfc027421,
0x0911f410,
0xf40231f4,
-/* 0x0942: idle_proc_next */
+/* 0x0936: idle_proc_next */
0x10b6ef0e,
0x061fb858,
0xf4e61bf4,
@@ -1521,4 +1518,7 @@ uint32_t nvd0_pwr_code[] = {
0x00000000,
0x00000000,
0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
};
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c
new file mode 100644
index 000000000000..d76612999b9f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/gk104.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "priv.h"
+
+#define nvd0_pwr_code gk104_pwr_code
+#define nvd0_pwr_data gk104_pwr_data
+#include "fuc/nvd0.fuc.h"
+
+static void
+gk104_pwr_pgob(struct nouveau_pwr *ppwr, bool enable)
+{
+ nv_mask(ppwr, 0x000200, 0x00001000, 0x00000000);
+ nv_rd32(ppwr, 0x000200);
+ nv_mask(ppwr, 0x000200, 0x08000000, 0x08000000);
+ msleep(50);
+
+ nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000002);
+ nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001);
+ nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000);
+
+ nv_mask(ppwr, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000);
+ msleep(50);
+
+ nv_mask(ppwr, 0x10a78c, 0x00000002, 0x00000000);
+ nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000001);
+ nv_mask(ppwr, 0x10a78c, 0x00000001, 0x00000000);
+
+ nv_mask(ppwr, 0x000200, 0x08000000, 0x00000000);
+ nv_mask(ppwr, 0x000200, 0x00001000, 0x00001000);
+ nv_rd32(ppwr, 0x000200);
+}
+
+struct nouveau_oclass *
+gk104_pwr_oclass = &(struct nvkm_pwr_impl) {
+ .base.handle = NV_SUBDEV(PWR, 0xe4),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_pwr_ctor,
+ .dtor = _nouveau_pwr_dtor,
+ .init = _nouveau_pwr_init,
+ .fini = _nouveau_pwr_fini,
+ },
+ .code.data = gk104_pwr_code,
+ .code.size = sizeof(gk104_pwr_code),
+ .data.data = gk104_pwr_data,
+ .data.size = sizeof(gk104_pwr_data),
+ .pgob = gk104_pwr_pgob,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c
index 03de3107d29f..def6a9ac68cf 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c
@@ -1,8 +1,7 @@
#ifndef __NVKM_PWR_MEMX_H__
#define __NVKM_PWR_MEMX_H__
-#include <subdev/pwr.h>
-#include <subdev/pwr/fuc/os.h>
+#include "priv.h"
struct nouveau_memx {
struct nouveau_pwr *ppwr;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c
index 52c85414866a..04ff7c3c34e9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c
@@ -22,41 +22,20 @@
* Authors: Ben Skeggs
*/
-#include <subdev/pwr.h>
-
+#include "priv.h"
#include "fuc/nv108.fuc.h"
-struct nv108_pwr_priv {
- struct nouveau_pwr base;
-};
-
-static int
-nv108_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nv108_pwr_priv *priv;
- int ret;
-
- ret = nouveau_pwr_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.code.data = nv108_pwr_code;
- priv->base.code.size = sizeof(nv108_pwr_code);
- priv->base.data.data = nv108_pwr_data;
- priv->base.data.size = sizeof(nv108_pwr_data);
- return 0;
-}
-
-struct nouveau_oclass
-nv108_pwr_oclass = {
- .handle = NV_SUBDEV(PWR, 0x00),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nv108_pwr_ctor,
+struct nouveau_oclass *
+nv108_pwr_oclass = &(struct nvkm_pwr_impl) {
+ .base.handle = NV_SUBDEV(PWR, 0x00),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_pwr_ctor,
.dtor = _nouveau_pwr_dtor,
.init = _nouveau_pwr_init,
.fini = _nouveau_pwr_fini,
},
-};
+ .code.data = nv108_pwr_code,
+ .code.size = sizeof(nv108_pwr_code),
+ .data.data = nv108_pwr_data,
+ .data.size = sizeof(nv108_pwr_data),
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c
index c132b7ca9747..998d53076b8b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c
@@ -22,50 +22,29 @@
* Authors: Ben Skeggs
*/
-#include <subdev/pwr.h>
-
+#include "priv.h"
#include "fuc/nva3.fuc.h"
-struct nva3_pwr_priv {
- struct nouveau_pwr base;
-};
-
static int
nva3_pwr_init(struct nouveau_object *object)
{
- struct nva3_pwr_priv *priv = (void *)object;
- nv_mask(priv, 0x022210, 0x00000001, 0x00000000);
- nv_mask(priv, 0x022210, 0x00000001, 0x00000001);
- return nouveau_pwr_init(&priv->base);
-}
-
-static int
-nva3_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nva3_pwr_priv *priv;
- int ret;
-
- ret = nouveau_pwr_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.code.data = nva3_pwr_code;
- priv->base.code.size = sizeof(nva3_pwr_code);
- priv->base.data.data = nva3_pwr_data;
- priv->base.data.size = sizeof(nva3_pwr_data);
- return 0;
+ struct nouveau_pwr *ppwr = (void *)object;
+ nv_mask(ppwr, 0x022210, 0x00000001, 0x00000000);
+ nv_mask(ppwr, 0x022210, 0x00000001, 0x00000001);
+ return nouveau_pwr_init(ppwr);
}
-struct nouveau_oclass
-nva3_pwr_oclass = {
- .handle = NV_SUBDEV(PWR, 0xa3),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nva3_pwr_ctor,
+struct nouveau_oclass *
+nva3_pwr_oclass = &(struct nvkm_pwr_impl) {
+ .base.handle = NV_SUBDEV(PWR, 0xa3),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_pwr_ctor,
.dtor = _nouveau_pwr_dtor,
.init = nva3_pwr_init,
.fini = _nouveau_pwr_fini,
},
-};
+ .code.data = nva3_pwr_code,
+ .code.size = sizeof(nva3_pwr_code),
+ .data.data = nva3_pwr_data,
+ .data.size = sizeof(nva3_pwr_data),
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c
index 495f6857428d..9a773e66efa4 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c
@@ -22,41 +22,20 @@
* Authors: Ben Skeggs
*/
-#include <subdev/pwr.h>
-
+#include "priv.h"
#include "fuc/nvc0.fuc.h"
-struct nvc0_pwr_priv {
- struct nouveau_pwr base;
-};
-
-static int
-nvc0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nvc0_pwr_priv *priv;
- int ret;
-
- ret = nouveau_pwr_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.code.data = nvc0_pwr_code;
- priv->base.code.size = sizeof(nvc0_pwr_code);
- priv->base.data.data = nvc0_pwr_data;
- priv->base.data.size = sizeof(nvc0_pwr_data);
- return 0;
-}
-
-struct nouveau_oclass
-nvc0_pwr_oclass = {
- .handle = NV_SUBDEV(PWR, 0xc0),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nvc0_pwr_ctor,
+struct nouveau_oclass *
+nvc0_pwr_oclass = &(struct nvkm_pwr_impl) {
+ .base.handle = NV_SUBDEV(PWR, 0xc0),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_pwr_ctor,
.dtor = _nouveau_pwr_dtor,
.init = _nouveau_pwr_init,
.fini = _nouveau_pwr_fini,
},
-};
+ .code.data = nvc0_pwr_code,
+ .code.size = sizeof(nvc0_pwr_code),
+ .data.data = nvc0_pwr_data,
+ .data.size = sizeof(nvc0_pwr_data),
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c
index 043aa142fe82..2b29be5d08ac 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c
@@ -22,41 +22,20 @@
* Authors: Ben Skeggs
*/
-#include <subdev/pwr.h>
-
+#include "priv.h"
#include "fuc/nvd0.fuc.h"
-struct nvd0_pwr_priv {
- struct nouveau_pwr base;
-};
-
-static int
-nvd0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
-{
- struct nvd0_pwr_priv *priv;
- int ret;
-
- ret = nouveau_pwr_create(parent, engine, oclass, &priv);
- *pobject = nv_object(priv);
- if (ret)
- return ret;
-
- priv->base.code.data = nvd0_pwr_code;
- priv->base.code.size = sizeof(nvd0_pwr_code);
- priv->base.data.data = nvd0_pwr_data;
- priv->base.data.size = sizeof(nvd0_pwr_data);
- return 0;
-}
-
-struct nouveau_oclass
-nvd0_pwr_oclass = {
- .handle = NV_SUBDEV(PWR, 0xd0),
- .ofuncs = &(struct nouveau_ofuncs) {
- .ctor = nvd0_pwr_ctor,
+struct nouveau_oclass *
+nvd0_pwr_oclass = &(struct nvkm_pwr_impl) {
+ .base.handle = NV_SUBDEV(PWR, 0xd0),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_pwr_ctor,
.dtor = _nouveau_pwr_dtor,
.init = _nouveau_pwr_init,
.fini = _nouveau_pwr_fini,
},
-};
+ .code.data = nvd0_pwr_code,
+ .code.size = sizeof(nvd0_pwr_code),
+ .data.data = nvd0_pwr_data,
+ .data.size = sizeof(nvd0_pwr_data),
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h
new file mode 100644
index 000000000000..3814a341db32
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/priv.h
@@ -0,0 +1,44 @@
+#ifndef __NVKM_PWR_PRIV_H__
+#define __NVKM_PWR_PRIV_H__
+
+#include <subdev/pwr.h>
+#include <subdev/pwr/fuc/os.h>
+
+#define nouveau_pwr_create(p, e, o, d) \
+ nouveau_pwr_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_pwr_destroy(p) \
+ nouveau_subdev_destroy(&(p)->base)
+#define nouveau_pwr_init(p) ({ \
+ struct nouveau_pwr *_ppwr = (p); \
+ _nouveau_pwr_init(nv_object(_ppwr)); \
+})
+#define nouveau_pwr_fini(p,s) ({ \
+ struct nouveau_pwr *_ppwr = (p); \
+ _nouveau_pwr_fini(nv_object(_ppwr), (s)); \
+})
+
+int nouveau_pwr_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, int, void **);
+
+int _nouveau_pwr_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+#define _nouveau_pwr_dtor _nouveau_subdev_dtor
+int _nouveau_pwr_init(struct nouveau_object *);
+int _nouveau_pwr_fini(struct nouveau_object *, bool);
+
+struct nvkm_pwr_impl {
+ struct nouveau_oclass base;
+ struct {
+ u32 *data;
+ u32 size;
+ } code;
+ struct {
+ u32 *data;
+ u32 size;
+ } data;
+
+ void (*pgob)(struct nouveau_pwr *, bool);
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
index 668cf964e4a9..2d0988755530 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c
@@ -28,7 +28,7 @@
#include <subdev/timer.h>
#include <subdev/fb.h>
#include <subdev/vm.h>
-#include <subdev/ltcg.h>
+#include <subdev/ltc.h>
#include <subdev/bar.h>
struct nvc0_vmmgr_priv {
@@ -116,12 +116,12 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
pte <<= 3;
if (mem->tag) {
- struct nouveau_ltcg *ltcg =
- nouveau_ltcg(vma->vm->vmm->base.base.parent);
+ struct nouveau_ltc *ltc =
+ nouveau_ltc(vma->vm->vmm->base.base.parent);
u32 tag = mem->tag->offset + (delta >> 17);
phys |= (u64)tag << (32 + 12);
next |= (u64)1 << (32 + 12);
- ltcg->tags_clear(ltcg, tag, cnt);
+ ltc->tags_clear(ltc, tag, cnt);
}
while (cnt--) {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c
index 2a15b98b4d2b..c6361422a0b2 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/arb.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c
@@ -198,12 +198,12 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
int *burst, int *lwm)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nv_fifo_info fifo_data;
struct nv_sim_state sim_data;
int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY);
int NVClk = nouveau_hw_get_clock(dev, PLL_CORE);
- uint32_t cfg1 = nv_rd32(device, NV04_PFB_CFG1);
+ uint32_t cfg1 = nvif_rd32(device, NV04_PFB_CFG1);
sim_data.pclk_khz = VClk;
sim_data.mclk_khz = MClk;
@@ -221,13 +221,13 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
sim_data.mem_latency = 3;
sim_data.mem_page_miss = 10;
} else {
- sim_data.memory_type = nv_rd32(device, NV04_PFB_CFG0) & 0x1;
- sim_data.memory_width = (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
+ sim_data.memory_type = nvif_rd32(device, NV04_PFB_CFG0) & 0x1;
+ sim_data.memory_width = (nvif_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
sim_data.mem_latency = cfg1 & 0xf;
sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
}
- if (nv_device(drm->device)->card_type == NV_04)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT)
nv04_calc_arb(&fifo_data, &sim_data);
else
nv10_calc_arb(&fifo_data, &sim_data);
@@ -254,7 +254,7 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (nv_device(drm->device)->card_type < NV_20)
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_KELVIN)
nv04_update_arb(dev, vclk, bpp, burst, lwm);
else if ((dev->pdev->device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ ||
(dev->pdev->device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 41be3424c906..b90aa5c1f90a 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -111,8 +111,8 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
{
struct drm_device *dev = crtc->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_bios *bios = nouveau_bios(drm->device);
- struct nouveau_clock *clk = nouveau_clock(drm->device);
+ struct nouveau_bios *bios = nvkm_bios(&drm->device);
+ struct nouveau_clock *clk = nvkm_clock(&drm->device);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index];
@@ -136,7 +136,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
* has yet been observed in allowing the use a single stage pll on all
* nv43 however. the behaviour of single stage use is untested on nv40
*/
- if (nv_device(drm->device)->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2))
+ if (drm->device.info.chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2))
memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2));
@@ -146,10 +146,10 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK;
/* The blob uses this always, so let's do the same */
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE;
/* again nv40 and some nv43 act more like nv3x as described above */
- if (nv_device(drm->device)->chipset < 0x41)
+ if (drm->device.info.chipset < 0x41)
state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL |
NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL;
state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK;
@@ -275,7 +275,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
horizEnd = horizTotal - 2;
horizBlankEnd = horizTotal + 4;
#if 0
- if (dev->overlayAdaptor && nv_device(drm->device)->card_type >= NV_10)
+ if (dev->overlayAdaptor && drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
/* This reportedly works around some video overlay bandwidth problems */
horizTotal += 2;
#endif
@@ -509,7 +509,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 |
NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 |
NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM;
- if (nv_device(drm->device)->chipset >= 0x11)
+ if (drm->device.info.chipset >= 0x11)
regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE;
@@ -550,26 +550,26 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
* 1 << 30 on 0x60.830), for no apparent reason */
regp->CRTC[NV_CIO_CRE_59] = off_chip_digital;
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1;
regp->crtc_830 = mode->crtc_vdisplay - 3;
regp->crtc_834 = mode->crtc_vdisplay - 1;
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
/* This is what the blob does */
regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850);
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT);
- if (nv_device(drm->device)->card_type >= NV_10)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC;
else
regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC;
/* Some misc regs */
- if (nv_device(drm->device)->card_type == NV_40) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
regp->CRTC[NV_CIO_CRE_85] = 0xFF;
regp->CRTC[NV_CIO_CRE_86] = 0x1;
}
@@ -581,7 +581,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
/* Generic PRAMDAC regs */
- if (nv_device(drm->device)->card_type >= NV_10)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
/* Only bit that bios and blob set. */
regp->nv10_cursync = (1 << 25);
@@ -590,7 +590,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
if (crtc->primary->fb->depth == 16)
regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
- if (nv_device(drm->device)->chipset >= 0x11)
+ if (drm->device.info.chipset >= 0x11)
regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */
@@ -653,7 +653,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
nv_crtc_mode_set_vga(crtc, adjusted_mode);
/* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk);
nv_crtc_mode_set_regs(crtc, adjusted_mode);
nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock);
@@ -714,7 +714,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc)
/* Some more preparation. */
NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
- if (nv_device(drm->device)->card_type == NV_40) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900);
NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000);
}
@@ -888,7 +888,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
- if (nv_device(drm->device)->card_type >= NV_20) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN) {
regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
}
@@ -915,9 +915,9 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
struct drm_device *dev = drm->dev;
if (state == ENTER_ATOMIC_MODE_SET)
- nouveau_fbcon_save_disable_accel(dev);
+ nouveau_fbcon_accel_save_disable(dev);
else
- nouveau_fbcon_restore_accel(dev);
+ nouveau_fbcon_accel_restore(dev);
return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
}
@@ -969,7 +969,7 @@ static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (nv_device(drm->device)->chipset == 0x11) {
+ if (drm->device.info.chipset == 0x11) {
pixel = ((pixel & 0x000000ff) << 24) |
((pixel & 0x0000ff00) << 8) |
((pixel & 0x00ff0000) >> 8) |
@@ -1010,7 +1010,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
if (ret)
goto out;
- if (nv_device(drm->device)->chipset >= 0x11)
+ if (drm->device.info.chipset >= 0x11)
nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
else
nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/cursor.c b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
index a810303169de..4e61173c3353 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/cursor.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/cursor.c
@@ -55,7 +55,7 @@ nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
nv_fix_nv40_hw_cursor(dev, nv_crtc->index);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c
index a96dda48718e..2d8056cde996 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dac.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c
@@ -65,8 +65,8 @@ int nv04_dac_output_offset(struct drm_encoder *encoder)
static int sample_load_twice(struct drm_device *dev, bool sense[2])
{
- struct nouveau_device *device = nouveau_dev(dev);
- struct nouveau_timer *ptimer = nouveau_timer(device);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ struct nouveau_timer *ptimer = nvkm_timer(device);
int i;
for (i = 0; i < 2; i++) {
@@ -95,15 +95,15 @@ static int sample_load_twice(struct drm_device *dev, bool sense[2])
udelay(100);
/* when level triggers, sense is _LO_ */
- sense_a = nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+ sense_a = nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
/* take another reading until it agrees with sense_a... */
do {
udelay(100);
- sense_b = nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+ sense_b = nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
if (sense_a != sense_b) {
sense_b_prime =
- nv_rd08(device, NV_PRMCIO_INP0) & 0x10;
+ nvif_rd08(device, NV_PRMCIO_INP0) & 0x10;
if (sense_b == sense_b_prime) {
/* ... unless two consecutive subsequent
* samples agree; sense_a is replaced */
@@ -128,7 +128,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode;
uint8_t saved_palette0[3], saved_palette_mask;
@@ -164,11 +164,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX);
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0);
- nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
+ nvif_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
for (i = 0; i < 3; i++)
- saved_palette0[i] = nv_rd08(device, NV_PRMDIO_PALETTE_DATA);
- saved_palette_mask = nv_rd08(device, NV_PRMDIO_PIXEL_MASK);
- nv_wr08(device, NV_PRMDIO_PIXEL_MASK, 0);
+ saved_palette0[i] = nvif_rd08(device, NV_PRMDIO_PALETTE_DATA);
+ saved_palette_mask = nvif_rd08(device, NV_PRMDIO_PIXEL_MASK);
+ nvif_wr08(device, NV_PRMDIO_PIXEL_MASK, 0);
saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL,
@@ -181,11 +181,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
do {
bool sense_pair[2];
- nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
- nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
- nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
+ nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+ nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
+ nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, 0);
/* testing blue won't find monochrome monitors. I don't care */
- nv_wr08(device, NV_PRMDIO_PALETTE_DATA, blue);
+ nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, blue);
i = 0;
/* take sample pairs until both samples in the pair agree */
@@ -208,11 +208,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
} while (++blue < 0x18 && sense);
out:
- nv_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
+ nvif_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl);
- nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+ nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
for (i = 0; i < 3; i++)
- nv_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
+ nvif_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl);
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi);
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1);
@@ -231,8 +231,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nouveau_dev(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(device);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ struct nouveau_gpio *gpio = nvkm_gpio(device);
struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
@@ -256,12 +256,12 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
- saved_powerctrl_2 = nv_rd32(device, NV_PBUS_POWERCTRL_2);
+ saved_powerctrl_2 = nvif_rd32(device, NV_PBUS_POWERCTRL_2);
- nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
if (regoffset == 0x68) {
- saved_powerctrl_4 = nv_rd32(device, NV_PBUS_POWERCTRL_4);
- nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
+ saved_powerctrl_4 = nvif_rd32(device, NV_PBUS_POWERCTRL_4);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
}
if (gpio) {
@@ -283,7 +283,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
routput = (saved_routput & 0xfffffece) | head << 8;
- if (nv_device(drm->device)->card_type >= NV_40) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CURIE) {
if (dcb->type == DCB_OUTPUT_TV)
routput |= 0x1a << 16;
else
@@ -316,8 +316,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
if (regoffset == 0x68)
- nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
- nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
if (gpio) {
gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1);
@@ -398,7 +398,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder,
}
/* This could use refinement for flatpanels, but it should work this way */
- if (nv_device(drm->device)->chipset < 0x44)
+ if (drm->device.info.chipset < 0x44)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
else
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
index e57babb206d3..42a5435259f7 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c
@@ -281,7 +281,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index];
@@ -335,7 +335,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE;
else /* gpu needs to scale */
regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE;
- if (nv_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
+ if (nvif_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP &&
output_mode->clock > 165000)
@@ -416,7 +416,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||
(nv_connector->dithering_mode == DITHERING_MODE_AUTO &&
encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {
- if (nv_device(drm->device)->chipset == 0x11)
+ if (drm->device.info.chipset == 0x11)
regp->dither = savep->dither | 0x00010000;
else {
int i;
@@ -427,7 +427,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
}
}
} else {
- if (nv_device(drm->device)->chipset != 0x11) {
+ if (drm->device.info.chipset != 0x11) {
/* reset them */
int i;
for (i = 0; i < 3; i++) {
@@ -463,7 +463,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
/* This could use refinement for flatpanels, but it should work this way */
- if (nv_device(drm->device)->chipset < 0x44)
+ if (drm->device.info.chipset < 0x44)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
else
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
@@ -485,7 +485,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
{
#ifdef __powerpc__
struct drm_device *dev = encoder->dev;
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
/* BIOS scripts usually take care of the backlight, thanks
* Apple for your consistency.
@@ -623,7 +623,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
struct drm_device *dev = encoder->dev;
struct dcb_output *dcb = nouveau_encoder(encoder)->dcb;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct nouveau_i2c_port *port = i2c->find(i2c, 2);
struct nouveau_i2c_board_info info[] = {
{
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 4342fdaee707..3d0afa1c6cff 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -22,9 +22,6 @@
* Author: Ben Skeggs
*/
-#include <core/object.h>
-#include <core/class.h>
-
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -34,8 +31,6 @@
#include "nouveau_encoder.h"
#include "nouveau_connector.h"
-#include <subdev/i2c.h>
-
int
nv04_display_early_init(struct drm_device *dev)
{
@@ -58,7 +53,7 @@ int
nv04_display_create(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct dcb_table *dcb = &drm->vbios.dcb;
struct drm_connector *connector, *ct;
struct drm_encoder *encoder;
@@ -70,6 +65,8 @@ nv04_display_create(struct drm_device *dev)
if (!disp)
return -ENOMEM;
+ nvif_object_map(nvif_object(&drm->device));
+
nouveau_display(dev)->priv = disp;
nouveau_display(dev)->dtor = nv04_display_destroy;
nouveau_display(dev)->init = nv04_display_init;
@@ -144,6 +141,7 @@ void
nv04_display_destroy(struct drm_device *dev)
{
struct nv04_display *disp = nv04_display(dev);
+ struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_encoder *encoder;
struct drm_crtc *crtc;
@@ -170,6 +168,8 @@ nv04_display_destroy(struct drm_device *dev)
nouveau_display(dev)->priv = NULL;
kfree(disp);
+
+ nvif_object_unmap(nvif_object(&drm->device));
}
int
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index 4245fc3dab70..17b899d9aba3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
@@ -131,7 +131,7 @@ nv_two_heads(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev);
const int impl = dev->pdev->device & 0x0ff0;
- if (nv_device(drm->device)->card_type >= NV_10 && impl != 0x0100 &&
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS && impl != 0x0100 &&
impl != 0x0150 && impl != 0x01a0 && impl != 0x0200)
return true;
@@ -150,7 +150,7 @@ nv_two_reg_pll(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev);
const int impl = dev->pdev->device & 0x0ff0;
- if (impl == 0x0310 || impl == 0x0340 || nv_device(drm->device)->card_type >= NV_40)
+ if (impl == 0x0310 || impl == 0x0340 || drm->device.info.family >= NV_DEVICE_INFO_V0_CURIE)
return true;
return false;
}
@@ -171,8 +171,8 @@ static inline void
nouveau_bios_run_init_table(struct drm_device *dev, u16 table,
struct dcb_output *outp, int crtc)
{
- struct nouveau_device *device = nouveau_dev(dev);
- struct nouveau_bios *bios = nouveau_bios(device);
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_bios *bios = nvkm_bios(&drm->device);
struct nvbios_init init = {
.subdev = nv_subdev(bios),
.bios = bios,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
index aca76af115b3..3d4c19300768 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
@@ -27,9 +27,6 @@
#include "hw.h"
#include <subdev/bios/pll.h>
-#include <subdev/fb.h>
-#include <subdev/clock.h>
-#include <subdev/timer.h>
#define CHIPSET_NFORCE 0x01a0
#define CHIPSET_NFORCE2 0x01f0
@@ -92,7 +89,7 @@ NVSetOwner(struct drm_device *dev, int owner)
if (owner == 1)
owner *= 3;
- if (nv_device(drm->device)->chipset == 0x11) {
+ if (drm->device.info.chipset == 0x11) {
/* This might seem stupid, but the blob does it and
* omitting it often locks the system up.
*/
@@ -103,7 +100,7 @@ NVSetOwner(struct drm_device *dev, int owner)
/* CR44 is always changed on CRTC0 */
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner);
- if (nv_device(drm->device)->chipset == 0x11) { /* set me harder */
+ if (drm->device.info.chipset == 0x11) { /* set me harder */
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
}
@@ -152,7 +149,7 @@ nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1,
pllvals->NM1 = pll1 & 0xffff;
if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2)
pllvals->NM2 = pll2 & 0xffff;
- else if (nv_device(drm->device)->chipset == 0x30 || nv_device(drm->device)->chipset == 0x35) {
+ else if (drm->device.info.chipset == 0x30 || drm->device.info.chipset == 0x35) {
pllvals->M1 &= 0xf; /* only 4 bits */
if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
pllvals->M2 = (pll1 >> 4) & 0x7;
@@ -168,8 +165,8 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype,
struct nouveau_pll_vals *pllvals)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_bios *bios = nouveau_bios(device);
+ struct nvif_device *device = &drm->device;
+ struct nouveau_bios *bios = nvkm_bios(device);
uint32_t reg1, pll1, pll2 = 0;
struct nvbios_pll pll_lim;
int ret;
@@ -178,16 +175,16 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype,
if (ret || !(reg1 = pll_lim.reg))
return -ENOENT;
- pll1 = nv_rd32(device, reg1);
+ pll1 = nvif_rd32(device, reg1);
if (reg1 <= 0x405c)
- pll2 = nv_rd32(device, reg1 + 4);
+ pll2 = nvif_rd32(device, reg1 + 4);
else if (nv_two_reg_pll(dev)) {
uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70);
- pll2 = nv_rd32(device, reg2);
+ pll2 = nvif_rd32(device, reg2);
}
- if (nv_device(drm->device)->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580);
/* check whether vpll has been forced into single stage mode */
@@ -255,9 +252,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
*/
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_clock *clk = nouveau_clock(device);
- struct nouveau_bios *bios = nouveau_bios(device);
+ struct nvif_device *device = &drm->device;
+ struct nouveau_clock *clk = nvkm_clock(device);
+ struct nouveau_bios *bios = nvkm_bios(device);
struct nvbios_pll pll_lim;
struct nouveau_pll_vals pv;
enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0;
@@ -394,21 +391,21 @@ nv_save_state_ramdac(struct drm_device *dev, int head,
struct nv04_crtc_reg *regp = &state->crtc_reg[head];
int i;
- if (nv_device(drm->device)->card_type >= NV_10)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC);
nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, &regp->pllvals);
state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
if (nv_two_heads(dev))
state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK);
- if (nv_device(drm->device)->chipset == 0x11)
+ if (drm->device.info.chipset == 0x11)
regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11);
regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL);
if (nv_gf4_disp_arch(dev))
regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630);
- if (nv_device(drm->device)->chipset >= 0x30)
+ if (drm->device.info.chipset >= 0x30)
regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634);
regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP);
@@ -450,7 +447,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head,
if (nv_gf4_disp_arch(dev))
regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0);
- if (nv_device(drm->device)->card_type == NV_40) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20);
regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24);
regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34);
@@ -466,26 +463,26 @@ nv_load_state_ramdac(struct drm_device *dev, int head,
struct nv04_mode_state *state)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_clock *clk = nouveau_clock(drm->device);
+ struct nouveau_clock *clk = nvkm_clock(&drm->device);
struct nv04_crtc_reg *regp = &state->crtc_reg[head];
uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
int i;
- if (nv_device(drm->device)->card_type >= NV_10)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS)
NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
clk->pll_prog(clk, pllreg, &regp->pllvals);
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
if (nv_two_heads(dev))
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
- if (nv_device(drm->device)->chipset == 0x11)
+ if (drm->device.info.chipset == 0x11)
NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
if (nv_gf4_disp_arch(dev))
NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630);
- if (nv_device(drm->device)->chipset >= 0x30)
+ if (drm->device.info.chipset >= 0x30)
NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup);
@@ -522,7 +519,7 @@ nv_load_state_ramdac(struct drm_device *dev, int head,
if (nv_gf4_disp_arch(dev))
NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0);
- if (nv_device(drm->device)->card_type == NV_40) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34);
@@ -603,10 +600,10 @@ nv_save_state_ext(struct drm_device *dev, int head,
rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
rd_cio_state(dev, head, regp, NV_CIO_CRE_21);
- if (nv_device(drm->device)->card_type >= NV_20)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN)
rd_cio_state(dev, head, regp, NV_CIO_CRE_47);
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
rd_cio_state(dev, head, regp, 0x9f);
rd_cio_state(dev, head, regp, NV_CIO_CRE_49);
@@ -615,14 +612,14 @@ nv_save_state_ext(struct drm_device *dev, int head,
rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
- if (nv_device(drm->device)->card_type >= NV_10) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830);
regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834);
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT);
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850);
if (nv_two_heads(dev))
@@ -634,7 +631,7 @@ nv_save_state_ext(struct drm_device *dev, int head,
rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
- if (nv_device(drm->device)->card_type >= NV_10) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
rd_cio_state(dev, head, regp, NV_CIO_CRE_4B);
@@ -663,14 +660,13 @@ nv_load_state_ext(struct drm_device *dev, int head,
struct nv04_mode_state *state)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_timer *ptimer = nouveau_timer(device);
- struct nouveau_fb *pfb = nouveau_fb(device);
+ struct nvif_device *device = &drm->device;
+ struct nouveau_timer *ptimer = nvkm_timer(device);
struct nv04_crtc_reg *regp = &state->crtc_reg[head];
uint32_t reg900;
int i;
- if (nv_device(drm->device)->card_type >= NV_10) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
if (nv_two_heads(dev))
/* setting ENGINE_CTRL (EC) *must* come before
* CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in
@@ -678,24 +674,24 @@ nv_load_state_ext(struct drm_device *dev, int head,
*/
NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl);
- nv_wr32(device, NV_PVIDEO_STOP, 1);
- nv_wr32(device, NV_PVIDEO_INTR_EN, 0);
- nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);
- nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0);
- nv_wr32(device, NV_PVIDEO_LIMIT(0), pfb->ram->size - 1);
- nv_wr32(device, NV_PVIDEO_LIMIT(1), pfb->ram->size - 1);
- nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), pfb->ram->size - 1);
- nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), pfb->ram->size - 1);
- nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);
+ nvif_wr32(device, NV_PVIDEO_STOP, 1);
+ nvif_wr32(device, NV_PVIDEO_INTR_EN, 0);
+ nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);
+ nvif_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0);
+ nvif_wr32(device, NV_PVIDEO_LIMIT(0), device->info.ram_size - 1);
+ nvif_wr32(device, NV_PVIDEO_LIMIT(1), device->info.ram_size - 1);
+ nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), device->info.ram_size - 1);
+ nvif_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), device->info.ram_size - 1);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830);
NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834);
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext);
- if (nv_device(drm->device)->card_type == NV_40) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE) {
NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850);
reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900);
@@ -718,23 +714,23 @@ nv_load_state_ext(struct drm_device *dev, int head,
wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
- if (nv_device(drm->device)->card_type >= NV_20)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_KELVIN)
wr_cio_state(dev, head, regp, NV_CIO_CRE_47);
- if (nv_device(drm->device)->card_type >= NV_30)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE)
wr_cio_state(dev, head, regp, 0x9f);
wr_cio_state(dev, head, regp, NV_CIO_CRE_49);
wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
nv_fix_nv40_hw_cursor(dev, head);
wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
- if (nv_device(drm->device)->card_type >= NV_10) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
wr_cio_state(dev, head, regp, NV_CIO_CRE_4B);
@@ -742,7 +738,7 @@ nv_load_state_ext(struct drm_device *dev, int head,
}
/* NV11 and NV20 stop at 0x52. */
if (nv_gf4_disp_arch(dev)) {
- if (nv_device(drm->device)->card_type < NV_20) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_KELVIN) {
/* Not waiting for vertical retrace before modifying
CRE_53/CRE_54 causes lockups. */
nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
@@ -769,15 +765,15 @@ static void
nv_save_state_palette(struct drm_device *dev, int head,
struct nv04_mode_state *state)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
int head_offset = head * NV_PRMDIO_SIZE, i;
- nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
+ nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
NV_PRMDIO_PIXEL_MASK_MASK);
- nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
+ nvif_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
for (i = 0; i < 768; i++) {
- state->crtc_reg[head].DAC[i] = nv_rd08(device,
+ state->crtc_reg[head].DAC[i] = nvif_rd08(device,
NV_PRMDIO_PALETTE_DATA + head_offset);
}
@@ -788,15 +784,15 @@ void
nouveau_hw_load_state_palette(struct drm_device *dev, int head,
struct nv04_mode_state *state)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
int head_offset = head * NV_PRMDIO_SIZE, i;
- nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
+ nvif_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset,
NV_PRMDIO_PIXEL_MASK_MASK);
- nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
+ nvif_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
for (i = 0; i < 768; i++) {
- nv_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset,
+ nvif_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset,
state->crtc_reg[head].DAC[i]);
}
@@ -808,7 +804,7 @@ void nouveau_hw_save_state(struct drm_device *dev, int head,
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (nv_device(drm->device)->chipset == 0x11)
+ if (drm->device.info.chipset == 0x11)
/* NB: no attempt is made to restore the bad pll later on */
nouveau_hw_fix_bad_vpll(dev, head);
nv_save_state_ramdac(dev, head, state);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.h b/drivers/gpu/drm/nouveau/dispnv04/hw.h
index eeb70d912d99..7f53c571f31f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/hw.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/hw.h
@@ -60,41 +60,41 @@ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
static inline uint32_t NVReadCRTC(struct drm_device *dev,
int head, uint32_t reg)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
uint32_t val;
if (head)
reg += NV_PCRTC0_SIZE;
- val = nv_rd32(device, reg);
+ val = nvif_rd32(device, reg);
return val;
}
static inline void NVWriteCRTC(struct drm_device *dev,
int head, uint32_t reg, uint32_t val)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
if (head)
reg += NV_PCRTC0_SIZE;
- nv_wr32(device, reg, val);
+ nvif_wr32(device, reg, val);
}
static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
int head, uint32_t reg)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
uint32_t val;
if (head)
reg += NV_PRAMDAC0_SIZE;
- val = nv_rd32(device, reg);
+ val = nvif_rd32(device, reg);
return val;
}
static inline void NVWriteRAMDAC(struct drm_device *dev,
int head, uint32_t reg, uint32_t val)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
if (head)
reg += NV_PRAMDAC0_SIZE;
- nv_wr32(device, reg, val);
+ nvif_wr32(device, reg, val);
}
static inline uint8_t nv_read_tmds(struct drm_device *dev,
@@ -120,18 +120,18 @@ static inline void nv_write_tmds(struct drm_device *dev,
static inline void NVWriteVgaCrtc(struct drm_device *dev,
int head, uint8_t index, uint8_t value)
{
- struct nouveau_device *device = nouveau_dev(dev);
- nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
- nv_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+ nvif_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
}
static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
int head, uint8_t index)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
uint8_t val;
- nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
- val = nv_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
+ nvif_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+ val = nvif_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
return val;
}
@@ -165,74 +165,74 @@ static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_
static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
int head, uint32_t reg)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
uint8_t val;
/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
* NVSetOwner for the relevant head to be programmed */
- if (head && nv_device(drm->device)->card_type == NV_40)
+ if (head && drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
reg += NV_PRMVIO_SIZE;
- val = nv_rd08(device, reg);
+ val = nvif_rd08(device, reg);
return val;
}
static inline void NVWritePRMVIO(struct drm_device *dev,
int head, uint32_t reg, uint8_t value)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
* NVSetOwner for the relevant head to be programmed */
- if (head && nv_device(drm->device)->card_type == NV_40)
+ if (head && drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
reg += NV_PRMVIO_SIZE;
- nv_wr08(device, reg, value);
+ nvif_wr08(device, reg, value);
}
static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
{
- struct nouveau_device *device = nouveau_dev(dev);
- nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
- nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+ nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
}
static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
{
- struct nouveau_device *device = nouveau_dev(dev);
- nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
- return !(nv_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+ return !(nvif_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
}
static inline void NVWriteVgaAttr(struct drm_device *dev,
int head, uint8_t index, uint8_t value)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
if (NVGetEnablePalette(dev, head))
index &= ~0x20;
else
index |= 0x20;
- nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
- nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
- nv_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
+ nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+ nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+ nvif_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
}
static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
int head, uint8_t index)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
uint8_t val;
if (NVGetEnablePalette(dev, head))
index &= ~0x20;
else
index |= 0x20;
- nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
- nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
- val = nv_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
+ nvif_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+ nvif_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+ val = nvif_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
return val;
}
@@ -259,11 +259,11 @@ static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
static inline bool
nv_heads_tied(struct drm_device *dev)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
- if (nv_device(drm->device)->chipset == 0x11)
- return !!(nv_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
+ if (drm->device.info.chipset == 0x11)
+ return !!(nvif_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
}
@@ -318,7 +318,7 @@ NVLockVgaCrtcs(struct drm_device *dev, bool lock)
NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
/* NV11 has independently lockable extended crtcs, except when tied */
- if (nv_device(drm->device)->chipset == 0x11 && !nv_heads_tied(dev))
+ if (drm->device.info.chipset == 0x11 && !nv_heads_tied(dev))
NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
lock ? NV_CIO_SR_LOCK_VALUE :
NV_CIO_SR_UNLOCK_RW_VALUE);
@@ -335,7 +335,7 @@ static inline int nv_cursor_width(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- return nv_device(drm->device)->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
+ return drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
}
static inline void
@@ -357,7 +357,7 @@ nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
- if (nv_device(drm->device)->card_type == NV_04) {
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT) {
/*
* Hilarious, the 24th bit doesn't want to stick to
* PCRTC_START...
@@ -382,7 +382,7 @@ nv_show_cursor(struct drm_device *dev, int head, bool show)
*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
nv_fix_nv40_hw_cursor(dev, head);
}
@@ -398,7 +398,7 @@ nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
bpp = 8;
/* Alignment requirements taken from the Haiku driver */
- if (nv_device(drm->device)->card_type == NV_04)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_TNT)
mask = 128 / bpp - 1;
else
mask = 512 / bpp - 1;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index ab03f7719d2d..b36afcbbc83f 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -96,7 +96,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
- struct nouveau_device *dev = nouveau_dev(plane->dev);
+ struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -117,7 +117,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (format > 0xffff)
return -ERANGE;
- if (dev->chipset >= 0x30) {
+ if (dev->info.chipset >= 0x30) {
if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
return -ERANGE;
} else {
@@ -131,17 +131,17 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
nv_plane->cur = nv_fb->nvbo;
- nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
- nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
+ nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
+ nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
- nv_wr32(dev, NV_PVIDEO_BASE(flip), 0);
- nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset);
- nv_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
- nv_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
- nv_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
- nv_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
- nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
- nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
+ nvif_wr32(dev, NV_PVIDEO_BASE(flip), 0);
+ nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset);
+ nvif_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
+ nvif_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
+ nvif_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
+ nvif_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h);
+ nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
+ nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
if (fb->pixel_format != DRM_FORMAT_UYVY)
format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
@@ -153,14 +153,14 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
if (fb->pixel_format == DRM_FORMAT_NV12) {
- nv_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
- nv_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
+ nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
+ nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
nv_fb->nvbo->bo.offset + fb->offsets[1]);
}
- nv_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
- nv_wr32(dev, NV_PVIDEO_STOP, 0);
+ nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format);
+ nvif_wr32(dev, NV_PVIDEO_STOP, 0);
/* TODO: wait for vblank? */
- nv_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
+ nvif_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1);
nv_plane->flip = !flip;
if (cur)
@@ -172,10 +172,10 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
static int
nv10_disable_plane(struct drm_plane *plane)
{
- struct nouveau_device *dev = nouveau_dev(plane->dev);
+ struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
- nv_wr32(dev, NV_PVIDEO_STOP, 1);
+ nvif_wr32(dev, NV_PVIDEO_STOP, 1);
if (nv_plane->cur) {
nouveau_bo_unpin(nv_plane->cur);
nv_plane->cur = NULL;
@@ -195,24 +195,24 @@ nv_destroy_plane(struct drm_plane *plane)
static void
nv10_set_params(struct nouveau_plane *plane)
{
- struct nouveau_device *dev = nouveau_dev(plane->base.dev);
+ struct nvif_device *dev = &nouveau_drm(plane->base.dev)->device;
u32 luma = (plane->brightness - 512) << 16 | plane->contrast;
u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) |
(cos_mul(plane->hue, plane->saturation) & 0xffff);
u32 format = 0;
- nv_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
- nv_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
- nv_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
- nv_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
- nv_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
+ nvif_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma);
+ nvif_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma);
+ nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma);
+ nvif_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma);
+ nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
if (plane->cur) {
if (plane->iturbt_709)
format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
if (plane->colorkey & (1 << 24))
format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
- nv_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
+ nvif_mask(dev, NV_PVIDEO_FORMAT(plane->flip),
NV_PVIDEO_FORMAT_MATRIX_ITURBT709 |
NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY,
format);
@@ -256,7 +256,7 @@ static const struct drm_plane_funcs nv10_plane_funcs = {
static void
nv10_overlay_init(struct drm_device *device)
{
- struct nouveau_device *dev = nouveau_dev(device);
+ struct nouveau_drm *drm = nouveau_drm(device);
struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
int num_formats = ARRAY_SIZE(formats);
int ret;
@@ -264,7 +264,7 @@ nv10_overlay_init(struct drm_device *device)
if (!plane)
return;
- switch (dev->chipset) {
+ switch (drm->device.info.chipset) {
case 0x10:
case 0x11:
case 0x15:
@@ -333,7 +333,7 @@ cleanup:
drm_plane_cleanup(&plane->base);
err:
kfree(plane);
- nv_error(dev, "Failed to create plane\n");
+ NV_ERROR(drm, "Failed to create plane\n");
}
static int
@@ -343,7 +343,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
- struct nouveau_device *dev = nouveau_dev(plane->dev);
+ struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
struct nouveau_bo *cur = nv_plane->cur;
@@ -375,43 +375,43 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
nv_plane->cur = nv_fb->nvbo;
- nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
- nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
- nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+ nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+ nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+ nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);
for (i = 0; i < 2; i++) {
- nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+ nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
nv_fb->nvbo->bo.offset);
- nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
- nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+ nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
+ nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
}
- nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
- nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
- nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
+ nvif_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
+ nvif_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
+ nvif_wr32(dev, NV_PVIDEO_STEP_SIZE,
(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
/* It should be possible to convert hue/contrast to this */
- nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
- nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
- nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
- nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
+ nvif_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
+ nvif_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
+ nvif_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
+ nvif_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
- nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
- nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
+ nvif_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
+ nvif_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
- nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
- nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
+ nvif_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
+ nvif_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
- nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
+ nvif_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
if (nv_plane->colorkey & (1 << 24))
overlay |= 0x10;
if (fb->pixel_format == DRM_FORMAT_YUYV)
overlay |= 0x100;
- nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
+ nvif_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
- nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
+ nvif_wr32(dev, NV_PVIDEO_SU_STATE, nvif_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
if (cur)
nouveau_bo_unpin(cur);
@@ -422,13 +422,13 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
static int
nv04_disable_plane(struct drm_plane *plane)
{
- struct nouveau_device *dev = nouveau_dev(plane->dev);
+ struct nvif_device *dev = &nouveau_drm(plane->dev)->device;
struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
- nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
- nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
- nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
- nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+ nvif_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
+ nvif_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+ nvif_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+ nvif_wr32(dev, NV_PVIDEO_RM_STATE, 0);
if (nv_plane->cur) {
nouveau_bo_unpin(nv_plane->cur);
nv_plane->cur = NULL;
@@ -447,7 +447,7 @@ static const struct drm_plane_funcs nv04_plane_funcs = {
static void
nv04_overlay_init(struct drm_device *device)
{
- struct nouveau_device *dev = nouveau_dev(device);
+ struct nouveau_drm *drm = nouveau_drm(device);
struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
int ret;
@@ -483,15 +483,15 @@ cleanup:
drm_plane_cleanup(&plane->base);
err:
kfree(plane);
- nv_error(dev, "Failed to create plane\n");
+ NV_ERROR(drm, "Failed to create plane\n");
}
void
nouveau_overlay_init(struct drm_device *device)
{
- struct nouveau_device *dev = nouveau_dev(device);
- if (dev->chipset < 0x10)
+ struct nvif_device *dev = &nouveau_drm(device)->device;
+ if (dev->info.chipset < 0x10)
nv04_overlay_init(device);
- else if (dev->chipset <= 0x40)
+ else if (dev->info.chipset <= 0x40)
nv10_overlay_init(device);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
index 8667620b703a..8061d8d0ce79 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
@@ -35,8 +35,6 @@
#include <drm/i2c/ch7006.h>
-#include <subdev/i2c.h>
-
static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {
{
{
@@ -56,7 +54,7 @@ static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {
int nv04_tv_identify(struct drm_device *dev, int i2c_index)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
return i2c->identify(i2c, i2c_index, "TV encoder",
nv04_tv_encoder_info, NULL, NULL);
@@ -206,7 +204,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
struct drm_encoder *encoder;
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
int type, ret;
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 195bd8e86c6a..72d2ab04db47 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -34,11 +34,6 @@
#include "hw.h"
#include "tvnv17.h"
-#include <core/device.h>
-
-#include <subdev/bios/gpio.h>
-#include <subdev/gpio.h>
-
MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
"\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
"\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
@@ -51,7 +46,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+ struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
@@ -135,17 +130,17 @@ static bool
get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_object *device = drm->device;
+ struct nvif_device *device = &drm->device;
/* Zotac FX5200 */
- if (nv_device_match(device, 0x0322, 0x19da, 0x1035) ||
- nv_device_match(device, 0x0322, 0x19da, 0x2035)) {
+ if (nv_device_match(nvkm_object(device), 0x0322, 0x19da, 0x1035) ||
+ nv_device_match(nvkm_object(device), 0x0322, 0x19da, 0x2035)) {
*pin_mask = 0xc;
return false;
}
/* MSI nForce2 IGP */
- if (nv_device_match(device, 0x01f0, 0x1462, 0x5710)) {
+ if (nv_device_match(nvkm_object(device), 0x01f0, 0x1462, 0x5710)) {
*pin_mask = 0xc;
return false;
}
@@ -167,8 +162,8 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
return connector_status_disconnected;
if (reliable) {
- if (nv_device(drm->device)->chipset == 0x42 ||
- nv_device(drm->device)->chipset == 0x43)
+ if (drm->device.info.chipset == 0x42 ||
+ drm->device.info.chipset == 0x43)
tv_enc->pin_mask =
nv42_tv_sample_load(encoder) >> 28 & 0xe;
else
@@ -375,7 +370,7 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+ struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
@@ -448,7 +443,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder)
/* Set the DACCLK register */
dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1;
- if (nv_device(drm->device)->card_type == NV_40)
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CURIE)
dacclk |= 0x1a << 16;
if (tv_norm->kind == CTV_ENC_MODE) {
@@ -505,7 +500,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder,
tv_regs->ptv_614 = 0x13;
}
- if (nv_device(drm->device)->card_type >= NV_30) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_RANKINE) {
tv_regs->ptv_500 = 0xe8e0;
tv_regs->ptv_504 = 0x1710;
tv_regs->ptv_604 = 0x0;
@@ -600,7 +595,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder)
nv17_tv_state_load(dev, &to_tv_enc(encoder)->state);
/* This could use refinement for flatpanels, but it should work */
- if (nv_device(drm->device)->chipset < 0x44)
+ if (drm->device.info.chipset < 0x44)
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
nv04_dac_output_offset(encoder),
0xf0000000);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
index 7b331543a41b..225894cdcac2 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.h
@@ -130,14 +130,14 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder);
static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg,
uint32_t val)
{
- struct nouveau_device *device = nouveau_dev(dev);
- nv_wr32(device, reg, val);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ nvif_wr32(device, reg, val);
}
static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg)
{
- struct nouveau_device *device = nouveau_dev(dev);
- return nv_rd32(device, reg);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
+ return nvif_rd32(device, reg);
}
static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg,
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index b13f441c6431..615714c1727d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -21,16 +21,10 @@
*
*/
-#include <core/object.h>
-#include <core/client.h>
-#include <core/device.h>
-#include <core/class.h>
-#include <core/mm.h>
-
-#include <subdev/fb.h>
-#include <subdev/timer.h>
-#include <subdev/instmem.h>
-#include <engine/graph.h>
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/ioctl.h>
+#include <nvif/class.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -47,20 +41,20 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
struct nouveau_abi16 *abi16;
cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL);
if (cli->abi16) {
+ struct nv_device_v0 args = {
+ .device = ~0ULL,
+ };
+
INIT_LIST_HEAD(&abi16->channels);
- abi16->client = nv_object(cli);
/* allocate device object targeting client's default
* device (ie. the one that belongs to the fd it
* opened)
*/
- if (nouveau_object_new(abi16->client, NVDRM_CLIENT,
- NVDRM_DEVICE, 0x0080,
- &(struct nv_device_class) {
- .device = ~0ULL,
- },
- sizeof(struct nv_device_class),
- &abi16->device) == 0)
+ if (nvif_device_init(&cli->base.base, NULL,
+ NOUVEAU_ABI16_DEVICE, NV_DEVICE,
+ &args, sizeof(args),
+ &abi16->device) == 0)
return cli->abi16;
kfree(cli->abi16);
@@ -75,7 +69,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
int
nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
{
- struct nouveau_cli *cli = (void *)abi16->client;
+ struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base);
mutex_unlock(&cli->mutex);
return ret;
}
@@ -83,21 +77,19 @@ nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
u16
nouveau_abi16_swclass(struct nouveau_drm *drm)
{
- switch (nv_device(drm->device)->card_type) {
- case NV_04:
+ switch (drm->device.info.family) {
+ case NV_DEVICE_INFO_V0_TNT:
return 0x006e;
- case NV_10:
- case NV_11:
- case NV_20:
- case NV_30:
- case NV_40:
+ case NV_DEVICE_INFO_V0_CELSIUS:
+ case NV_DEVICE_INFO_V0_KELVIN:
+ case NV_DEVICE_INFO_V0_RANKINE:
+ case NV_DEVICE_INFO_V0_CURIE:
return 0x016e;
- case NV_50:
+ case NV_DEVICE_INFO_V0_TESLA:
return 0x506e;
- case NV_C0:
- case NV_D0:
- case NV_E0:
- case GM100:
+ case NV_DEVICE_INFO_V0_FERMI:
+ case NV_DEVICE_INFO_V0_KEPLER:
+ case NV_DEVICE_INFO_V0_MAXWELL:
return 0x906e;
}
@@ -140,7 +132,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
/* destroy channel object, all children will be killed too */
if (chan->chan) {
- abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));
+ abi16->handles &= ~(1ULL << (chan->chan->object->handle & 0xffff));
nouveau_channel_del(&chan->chan);
}
@@ -151,7 +143,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
void
nouveau_abi16_fini(struct nouveau_abi16 *abi16)
{
- struct nouveau_cli *cli = (void *)abi16->client;
+ struct nouveau_cli *cli = (void *)nvif_client(&abi16->device.base);
struct nouveau_abi16_chan *chan, *temp;
/* cleanup channels */
@@ -160,7 +152,7 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16)
}
/* destroy the device object */
- nouveau_object_del(abi16->client, NVDRM_CLIENT, NVDRM_DEVICE);
+ nvif_device_fini(&abi16->device);
kfree(cli->abi16);
cli->abi16 = NULL;
@@ -169,30 +161,31 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16)
int
nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
{
+ struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_timer *ptimer = nouveau_timer(device);
- struct nouveau_graph *graph = (void *)nouveau_engine(device, NVDEV_ENGINE_GR);
+ struct nvif_device *device = &drm->device;
+ struct nouveau_timer *ptimer = nvkm_timer(device);
+ struct nouveau_graph *graph = nvkm_gr(device);
struct drm_nouveau_getparam *getparam = data;
switch (getparam->param) {
case NOUVEAU_GETPARAM_CHIPSET_ID:
- getparam->value = device->chipset;
+ getparam->value = device->info.chipset;
break;
case NOUVEAU_GETPARAM_PCI_VENDOR:
- if (nv_device_is_pci(device))
+ if (nv_device_is_pci(nvkm_device(device)))
getparam->value = dev->pdev->vendor;
else
getparam->value = 0;
break;
case NOUVEAU_GETPARAM_PCI_DEVICE:
- if (nv_device_is_pci(device))
+ if (nv_device_is_pci(nvkm_device(device)))
getparam->value = dev->pdev->device;
else
getparam->value = 0;
break;
case NOUVEAU_GETPARAM_BUS_TYPE:
- if (!nv_device_is_pci(device))
+ if (!nv_device_is_pci(nvkm_device(device)))
getparam->value = 3;
else
if (drm_pci_device_is_agp(dev))
@@ -225,7 +218,7 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
getparam->value = graph->units ? graph->units(graph) : 0;
break;
default:
- nv_debug(device, "unknown parameter %lld\n", getparam->param);
+ NV_PRINTK(debug, cli, "unknown parameter %lld\n", getparam->param);
return -EINVAL;
}
@@ -246,10 +239,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
struct nouveau_abi16_chan *chan;
- struct nouveau_client *client;
- struct nouveau_device *device;
- struct nouveau_instmem *imem;
- struct nouveau_fb *pfb;
+ struct nvif_device *device;
int ret;
if (unlikely(!abi16))
@@ -258,21 +248,18 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
if (!drm->channel)
return nouveau_abi16_put(abi16, -ENODEV);
- client = nv_client(abi16->client);
- device = nv_device(abi16->device);
- imem = nouveau_instmem(device);
- pfb = nouveau_fb(device);
+ device = &abi16->device;
/* hack to allow channel engine type specification on kepler */
- if (device->card_type >= NV_E0) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
if (init->fb_ctxdma_handle != ~0)
- init->fb_ctxdma_handle = NVE0_CHANNEL_IND_ENGINE_GR;
+ init->fb_ctxdma_handle = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
else
init->fb_ctxdma_handle = init->tt_ctxdma_handle;
/* allow flips to be executed if this is a graphics channel */
init->tt_ctxdma_handle = 0;
- if (init->fb_ctxdma_handle == NVE0_CHANNEL_IND_ENGINE_GR)
+ if (init->fb_ctxdma_handle == KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR)
init->tt_ctxdma_handle = 1;
}
@@ -293,13 +280,14 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
abi16->handles |= (1ULL << init->channel);
/* create channel object and initialise dma and fence management */
- ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN |
- init->channel, init->fb_ctxdma_handle,
+ ret = nouveau_channel_new(drm, device,
+ NOUVEAU_ABI16_CHAN(init->channel),
+ init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan);
if (ret)
goto done;
- if (device->card_type >= NV_50)
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
NOUVEAU_GEM_DOMAIN_GART;
else
@@ -308,10 +296,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
else
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
- if (device->card_type < NV_10) {
+ if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
init->subchan[0].handle = 0x00000000;
init->subchan[0].grclass = 0x0000;
- init->subchan[1].handle = NvSw;
+ init->subchan[1].handle = chan->chan->nvsw.handle;
init->subchan[1].grclass = 0x506e;
init->nr_subchan = 2;
}
@@ -324,8 +312,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
if (ret)
goto done;
- if (device->card_type >= NV_50) {
- ret = nouveau_bo_vma_add(chan->ntfy, client->vm,
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ ret = nouveau_bo_vma_add(chan->ntfy, cli->vm,
&chan->ntfy_vma);
if (ret)
goto done;
@@ -343,6 +331,18 @@ done:
return nouveau_abi16_put(abi16, ret);
}
+static struct nouveau_abi16_chan *
+nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
+{
+ struct nouveau_abi16_chan *chan;
+
+ list_for_each_entry(chan, &abi16->channels, head) {
+ if (chan->chan->object->handle == NOUVEAU_ABI16_CHAN(channel))
+ return chan;
+ }
+
+ return NULL;
+}
int
nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
@@ -350,28 +350,38 @@ nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
struct drm_nouveau_channel_free *req = data;
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
struct nouveau_abi16_chan *chan;
- int ret = -ENOENT;
if (unlikely(!abi16))
return -ENOMEM;
- list_for_each_entry(chan, &abi16->channels, head) {
- if (chan->chan->handle == (NVDRM_CHAN | req->channel)) {
- nouveau_abi16_chan_fini(abi16, chan);
- return nouveau_abi16_put(abi16, 0);
- }
- }
-
- return nouveau_abi16_put(abi16, ret);
+ chan = nouveau_abi16_chan(abi16, req->channel);
+ if (!chan)
+ return nouveau_abi16_put(abi16, -ENOENT);
+ nouveau_abi16_chan_fini(abi16, chan);
+ return nouveau_abi16_put(abi16, 0);
}
int
nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_grobj_alloc *init = data;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_new_v0 new;
+ } args = {
+ .ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY,
+ .ioctl.type = NVIF_IOCTL_V0_NEW,
+ .ioctl.path_nr = 3,
+ .ioctl.path[2] = NOUVEAU_ABI16_CLIENT,
+ .ioctl.path[1] = NOUVEAU_ABI16_DEVICE,
+ .ioctl.path[0] = NOUVEAU_ABI16_CHAN(init->channel),
+ .new.route = NVDRM_OBJECT_ABI16,
+ .new.handle = init->handle,
+ .new.oclass = init->class,
+ };
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_object *object;
+ struct nvif_client *client;
int ret;
if (unlikely(!abi16))
@@ -379,6 +389,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if (init->handle == ~0)
return nouveau_abi16_put(abi16, -EINVAL);
+ client = nvif_client(nvif_object(&abi16->device));
/* compatibility with userspace that assumes 506e for all chipsets */
if (init->class == 0x506e) {
@@ -387,8 +398,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
return nouveau_abi16_put(abi16, 0);
}
- ret = nouveau_object_new(abi16->client, NVDRM_CHAN | init->channel,
- init->handle, init->class, NULL, 0, &object);
+ ret = nvif_client_ioctl(client, &args, sizeof(args));
return nouveau_abi16_put(abi16, ret);
}
@@ -396,29 +406,38 @@ int
nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_notifierobj_alloc *info = data;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_new_v0 new;
+ struct nv_dma_v0 ctxdma;
+ } args = {
+ .ioctl.owner = NVIF_IOCTL_V0_OWNER_ANY,
+ .ioctl.type = NVIF_IOCTL_V0_NEW,
+ .ioctl.path_nr = 3,
+ .ioctl.path[2] = NOUVEAU_ABI16_CLIENT,
+ .ioctl.path[1] = NOUVEAU_ABI16_DEVICE,
+ .ioctl.path[0] = NOUVEAU_ABI16_CHAN(info->channel),
+ .new.route = NVDRM_OBJECT_ABI16,
+ .new.handle = info->handle,
+ .new.oclass = NV_DMA_IN_MEMORY,
+ };
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
- struct nouveau_abi16_chan *chan = NULL, *temp;
+ struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
- struct nouveau_object *object;
- struct nv_dma_class args = {};
+ struct nvif_device *device = &abi16->device;
+ struct nvif_client *client;
int ret;
if (unlikely(!abi16))
return -ENOMEM;
/* completely unnecessary for these chipsets... */
- if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
+ if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI))
return nouveau_abi16_put(abi16, -EINVAL);
+ client = nvif_client(nvif_object(&abi16->device));
- list_for_each_entry(temp, &abi16->channels, head) {
- if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
- chan = temp;
- break;
- }
- }
-
+ chan = nouveau_abi16_chan(abi16, info->channel);
if (!chan)
return nouveau_abi16_put(abi16, -ENOENT);
@@ -434,26 +453,29 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
if (ret)
goto done;
- args.start = ntfy->node->offset;
- args.limit = ntfy->node->offset + ntfy->node->length - 1;
- if (device->card_type >= NV_50) {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
- args.start += chan->ntfy_vma.offset;
- args.limit += chan->ntfy_vma.offset;
+ args.ctxdma.start = ntfy->node->offset;
+ args.ctxdma.limit = ntfy->node->offset + ntfy->node->length - 1;
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ args.ctxdma.target = NV_DMA_V0_TARGET_VM;
+ args.ctxdma.access = NV_DMA_V0_ACCESS_VM;
+ args.ctxdma.start += chan->ntfy_vma.offset;
+ args.ctxdma.limit += chan->ntfy_vma.offset;
} else
if (drm->agp.stat == ENABLED) {
- args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
- args.start += drm->agp.base + chan->ntfy->bo.offset;
- args.limit += drm->agp.base + chan->ntfy->bo.offset;
+ args.ctxdma.target = NV_DMA_V0_TARGET_AGP;
+ args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR;
+ args.ctxdma.start += drm->agp.base + chan->ntfy->bo.offset;
+ args.ctxdma.limit += drm->agp.base + chan->ntfy->bo.offset;
+ client->super = true;
} else {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
- args.start += chan->ntfy->bo.offset;
- args.limit += chan->ntfy->bo.offset;
+ args.ctxdma.target = NV_DMA_V0_TARGET_VM;
+ args.ctxdma.access = NV_DMA_V0_ACCESS_RDWR;
+ args.ctxdma.start += chan->ntfy->bo.offset;
+ args.ctxdma.limit += chan->ntfy->bo.offset;
}
- ret = nouveau_object_new(abi16->client, chan->chan->handle,
- ntfy->handle, 0x003d, &args,
- sizeof(args), &object);
+ ret = nvif_client_ioctl(client, &args, sizeof(args));
+ client->super = false;
if (ret)
goto done;
@@ -469,28 +491,36 @@ int
nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_gpuobj_free *fini = data;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_del del;
+ } args = {
+ .ioctl.owner = NVDRM_OBJECT_ABI16,
+ .ioctl.type = NVIF_IOCTL_V0_DEL,
+ .ioctl.path_nr = 4,
+ .ioctl.path[3] = NOUVEAU_ABI16_CLIENT,
+ .ioctl.path[2] = NOUVEAU_ABI16_DEVICE,
+ .ioctl.path[1] = NOUVEAU_ABI16_CHAN(fini->channel),
+ .ioctl.path[0] = fini->handle,
+ };
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
- struct nouveau_abi16_chan *chan = NULL, *temp;
+ struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
+ struct nvif_client *client;
int ret;
if (unlikely(!abi16))
return -ENOMEM;
- list_for_each_entry(temp, &abi16->channels, head) {
- if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
- chan = temp;
- break;
- }
- }
-
+ chan = nouveau_abi16_chan(abi16, fini->channel);
if (!chan)
return nouveau_abi16_put(abi16, -ENOENT);
+ client = nvif_client(nvif_object(&abi16->device));
/* synchronize with the user channel and destroy the gpu object */
nouveau_channel_idle(chan->chan);
- ret = nouveau_object_del(abi16->client, chan->chan->handle, fini->handle);
+ ret = nvif_client_ioctl(client, &args, sizeof(args));
if (ret)
return nouveau_abi16_put(abi16, ret);
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h
index 90004081a501..39844e6bfbff 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
@@ -28,8 +28,7 @@ struct nouveau_abi16_chan {
};
struct nouveau_abi16 {
- struct nouveau_object *client;
- struct nouveau_object *device;
+ struct nvif_device device;
struct list_head channels;
u64 handles;
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c
index 51666daddb94..1f6f6ba6847a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_agp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_agp.c
@@ -1,7 +1,5 @@
#include <linux/module.h>
-#include <core/device.h>
-
#include "nouveau_drm.h"
#include "nouveau_agp.h"
#include "nouveau_reg.h"
@@ -29,7 +27,7 @@ static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = {
static unsigned long
get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
{
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list;
int agpmode = nouveau_agpmode;
unsigned long mode = info->mode;
@@ -38,7 +36,7 @@ get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
* FW seems to be broken on nv18, it makes the card lock up
* randomly.
*/
- if (device->chipset == 0x18)
+ if (device->info.chipset == 0x18)
mode &= ~PCI_AGP_COMMAND_FW;
/*
@@ -47,10 +45,10 @@ get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
while (agpmode == -1 && quirk->hostbridge_vendor) {
if (info->id_vendor == quirk->hostbridge_vendor &&
info->id_device == quirk->hostbridge_device &&
- device->pdev->vendor == quirk->chip_vendor &&
- device->pdev->device == quirk->chip_device) {
+ nvkm_device(device)->pdev->vendor == quirk->chip_vendor &&
+ nvkm_device(device)->pdev->device == quirk->chip_device) {
agpmode = quirk->mode;
- nv_info(device, "Forcing agp mode to %dX. Use agpmode to override.\n",
+ NV_INFO(drm, "Forcing agp mode to %dX. Use agpmode to override.\n",
agpmode);
break;
}
@@ -104,7 +102,7 @@ void
nouveau_agp_reset(struct nouveau_drm *drm)
{
#if __OS_HAS_AGP
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct drm_device *dev = drm->dev;
u32 save[2];
int ret;
@@ -115,7 +113,7 @@ nouveau_agp_reset(struct nouveau_drm *drm)
/* First of all, disable fast writes, otherwise if it's
* already enabled in the AGP bridge and we disable the card's
* AGP controller we might be locking ourselves out of it. */
- if ((nv_rd32(device, NV04_PBUS_PCI_NV_19) |
+ if ((nvif_rd32(device, NV04_PBUS_PCI_NV_19) |
dev->agp->mode) & PCI_AGP_COMMAND_FW) {
struct drm_agp_info info;
struct drm_agp_mode mode;
@@ -134,15 +132,15 @@ nouveau_agp_reset(struct nouveau_drm *drm)
/* clear busmaster bit, and disable AGP */
- save[0] = nv_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000);
- nv_wr32(device, NV04_PBUS_PCI_NV_19, 0);
+ save[0] = nvif_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000);
+ nvif_wr32(device, NV04_PBUS_PCI_NV_19, 0);
/* reset PGRAPH, PFIFO and PTIMER */
- save[1] = nv_mask(device, 0x000200, 0x00011100, 0x00000000);
- nv_mask(device, 0x000200, 0x00011100, save[1]);
+ save[1] = nvif_mask(device, 0x000200, 0x00011100, 0x00000000);
+ nvif_mask(device, 0x000200, 0x00011100, save[1]);
/* and restore bustmaster bit (gives effect of resetting AGP) */
- nv_wr32(device, NV04_PBUS_PCI_NV_1, save[0]);
+ nvif_wr32(device, NV04_PBUS_PCI_NV_1, save[0]);
#endif
}
@@ -150,7 +148,6 @@ void
nouveau_agp_init(struct nouveau_drm *drm)
{
#if __OS_HAS_AGP
- struct nouveau_device *device = nv_device(drm->device);
struct drm_device *dev = drm->dev;
struct drm_agp_info info;
struct drm_agp_mode mode;
@@ -162,13 +159,13 @@ nouveau_agp_init(struct nouveau_drm *drm)
ret = drm_agp_acquire(dev);
if (ret) {
- nv_error(device, "unable to acquire AGP: %d\n", ret);
+ NV_ERROR(drm, "unable to acquire AGP: %d\n", ret);
return;
}
ret = drm_agp_info(dev, &info);
if (ret) {
- nv_error(device, "unable to get AGP info: %d\n", ret);
+ NV_ERROR(drm, "unable to get AGP info: %d\n", ret);
return;
}
@@ -177,7 +174,7 @@ nouveau_agp_init(struct nouveau_drm *drm)
ret = drm_agp_enable(dev, mode);
if (ret) {
- nv_error(device, "unable to enable AGP: %d\n", ret);
+ NV_ERROR(drm, "unable to enable AGP: %d\n", ret);
return;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 2c1e4aad7da3..e566c5b53651 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -40,8 +40,8 @@ static int
nv40_get_intensity(struct backlight_device *bd)
{
struct nouveau_drm *drm = bl_get_data(bd);
- struct nouveau_device *device = nv_device(drm->device);
- int val = (nv_rd32(device, NV40_PMC_BACKLIGHT) &
+ struct nvif_device *device = &drm->device;
+ int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
NV40_PMC_BACKLIGHT_MASK) >> 16;
return val;
@@ -51,11 +51,11 @@ static int
nv40_set_intensity(struct backlight_device *bd)
{
struct nouveau_drm *drm = bl_get_data(bd);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int val = bd->props.brightness;
- int reg = nv_rd32(device, NV40_PMC_BACKLIGHT);
+ int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
- nv_wr32(device, NV40_PMC_BACKLIGHT,
+ nvif_wr32(device, NV40_PMC_BACKLIGHT,
(val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
return 0;
@@ -71,11 +71,11 @@ static int
nv40_backlight_init(struct drm_connector *connector)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct backlight_properties props;
struct backlight_device *bd;
- if (!(nv_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
+ if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
return 0;
memset(&props, 0, sizeof(struct backlight_properties));
@@ -97,12 +97,12 @@ nv50_get_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int or = nv_encoder->or;
u32 div = 1025;
u32 val;
- val = nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
+ val = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
val &= NV50_PDISP_SOR_PWM_CTL_VAL;
return ((val * 100) + (div / 2)) / div;
}
@@ -112,12 +112,12 @@ nv50_set_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int or = nv_encoder->or;
u32 div = 1025;
u32 val = (bd->props.brightness * div) / 100;
- nv_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
+ nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
NV50_PDISP_SOR_PWM_CTL_NEW | val);
return 0;
}
@@ -133,12 +133,12 @@ nva3_get_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int or = nv_encoder->or;
u32 div, val;
- div = nv_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
- val = nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
+ div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
+ val = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
if (div && div >= val)
return ((val * 100) + (div / 2)) / div;
@@ -151,14 +151,14 @@ nva3_set_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int or = nv_encoder->or;
u32 div, val;
- div = nv_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
+ div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
val = (bd->props.brightness * div) / 100;
if (div) {
- nv_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
+ nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
NV50_PDISP_SOR_PWM_CTL_NEW |
NVA3_PDISP_SOR_PWM_CTL_UNK);
return 0;
@@ -177,7 +177,7 @@ static int
nv50_backlight_init(struct drm_connector *connector)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct nouveau_encoder *nv_encoder;
struct backlight_properties props;
struct backlight_device *bd;
@@ -190,12 +190,12 @@ nv50_backlight_init(struct drm_connector *connector)
return -ENODEV;
}
- if (!nv_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
+ if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
return 0;
- if (device->chipset <= 0xa0 ||
- device->chipset == 0xaa ||
- device->chipset == 0xac)
+ if (device->info.chipset <= 0xa0 ||
+ device->info.chipset == 0xaa ||
+ device->info.chipset == 0xac)
ops = &nv50_bl_ops;
else
ops = &nva3_bl_ops;
@@ -218,7 +218,7 @@ int
nouveau_backlight_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -226,13 +226,12 @@ nouveau_backlight_init(struct drm_device *dev)
connector->connector_type != DRM_MODE_CONNECTOR_eDP)
continue;
- switch (device->card_type) {
- case NV_40:
+ switch (device->info.family) {
+ case NV_DEVICE_INFO_V0_CURIE:
return nv40_backlight_init(connector);
- case NV_50:
- case NV_C0:
- case NV_D0:
- case NV_E0:
+ case NV_DEVICE_INFO_V0_TESLA:
+ case NV_DEVICE_INFO_V0_FERMI:
+ case NV_DEVICE_INFO_V0_KEPLER:
return nv50_backlight_init(connector);
default:
break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 8268a4ccac15..dae2c96deef8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -22,8 +22,6 @@
* SOFTWARE.
*/
-#include <subdev/bios.h>
-
#include <drm/drmP.h>
#include "nouveau_drm.h"
@@ -217,7 +215,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head
*/
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct nvbios *bios = &drm->vbios;
uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
uint32_t sel_clk_binding, sel_clk;
@@ -240,7 +238,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head
NV_INFO(drm, "Calling LVDS script %d:\n", script);
/* don't let script change pll->head binding */
- sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
+ sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
if (lvds_ver < 0x30)
ret = call_lvds_manufacturer_script(dev, dcbent, head, script);
@@ -252,7 +250,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head
sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
/* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
- nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);
+ nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
return ret;
}
@@ -320,7 +318,7 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n
static int
get_fp_strap(struct drm_device *dev, struct nvbios *bios)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
/*
* The fp strap is normally dictated by the "User Strap" in
@@ -334,10 +332,10 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios)
if (bios->major_version < 5 && bios->data[0x48] & 0x4)
return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
- if (device->card_type >= NV_50)
- return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
+ return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
else
- return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
+ return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
}
static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
@@ -636,7 +634,7 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head,
*/
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct nvbios *bios = &drm->vbios;
int cv = bios->chip_version;
uint16_t clktable = 0, scriptptr;
@@ -670,7 +668,7 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head,
}
/* don't let script change pll->head binding */
- sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
+ sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000);
sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
@@ -1253,7 +1251,7 @@ olddcb_table(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev);
u8 *dcb = NULL;
- if (nv_device(drm->device)->card_type > NV_04)
+ if (drm->device.info.family > NV_DEVICE_INFO_V0_TNT)
dcb = ROMPTR(dev, drm->vbios.data[0x36]);
if (!dcb) {
NV_WARN(drm, "No DCB data found in VBIOS\n");
@@ -1399,6 +1397,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
uint32_t conn, uint32_t conf, struct dcb_output *entry)
{
struct nouveau_drm *drm = nouveau_drm(dev);
+ int link = 0;
entry->type = conn & 0xf;
entry->i2c_index = (conn >> 4) & 0xf;
@@ -1444,6 +1443,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
if (conf & 0x4)
entry->lvdsconf.use_power_scripts = true;
entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4;
+ link = entry->lvdsconf.sor.link;
}
if (conf & mask) {
/*
@@ -1492,17 +1492,18 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
entry->dpconf.link_nr = 1;
break;
}
+ link = entry->dpconf.sor.link;
break;
case DCB_OUTPUT_TMDS:
if (dcb->version >= 0x40) {
entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
entry->extdev = (conf & 0x0000ff00) >> 8;
+ link = entry->tmdsconf.sor.link;
}
else if (dcb->version >= 0x30)
entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
else if (dcb->version >= 0x22)
entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
-
break;
case DCB_OUTPUT_EOL:
/* weird g80 mobile type that "nv" treats as a terminator */
@@ -1526,6 +1527,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
if (conf & 0x100000)
entry->i2c_upper_default = true;
+ entry->hasht = (entry->location << 4) | entry->type;
+ entry->hashm = (entry->heads << 8) | (link << 6) | entry->or;
return true;
}
@@ -1908,7 +1911,7 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio
*/
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
uint8_t bytes_to_write;
uint16_t hwsq_entry_offset;
int i;
@@ -1931,15 +1934,15 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio
hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
/* set sequencer control */
- nv_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
+ nvif_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
bytes_to_write -= 4;
/* write ucode */
for (i = 0; i < bytes_to_write; i += 4)
- nv_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
+ nvif_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
/* twiddle NV_PBUS_DEBUG_4 */
- nv_wr32(device, NV_PBUS_DEBUG_4, nv_rd32(device, NV_PBUS_DEBUG_4) | 0x18);
+ nvif_wr32(device, NV_PBUS_DEBUG_4, nvif_rd32(device, NV_PBUS_DEBUG_4) | 0x18);
return 0;
}
@@ -2002,7 +2005,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
static bool NVInitVBIOS(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_bios *bios = nouveau_bios(drm->device);
+ struct nouveau_bios *bios = nvkm_bios(&drm->device);
struct nvbios *legacy = &drm->vbios;
memset(legacy, 0, sizeof(struct nvbios));
@@ -2054,7 +2057,7 @@ nouveau_bios_posted(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev);
unsigned htotal;
- if (nv_device(drm->device)->card_type >= NV_50)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
return true;
htotal = NVReadVgaCrtc(dev, 0, 0x06);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index b6dc85c614be..01da508625f2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -27,13 +27,9 @@
* Jeremy Kolb <jkolb@brandeis.edu>
*/
-#include <core/engine.h>
+#include <linux/dma-mapping.h>
#include <linux/swiotlb.h>
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/bar.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
@@ -52,7 +48,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
{
struct nouveau_drm *drm = nouveau_drm(dev);
int i = reg - drm->tile.reg;
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
struct nouveau_fb_tile *tile = &pfb->tile.region[i];
struct nouveau_engine *engine;
@@ -109,7 +105,7 @@ nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
u32 size, u32 pitch, u32 flags)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
struct nouveau_drm_tile *tile, *found = NULL;
int i;
@@ -153,23 +149,23 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
int *align, int *size)
{
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
- if (device->card_type < NV_50) {
+ if (device->info.family < NV_DEVICE_INFO_V0_TESLA) {
if (nvbo->tile_mode) {
- if (device->chipset >= 0x40) {
+ if (device->info.chipset >= 0x40) {
*align = 65536;
*size = roundup(*size, 64 * nvbo->tile_mode);
- } else if (device->chipset >= 0x30) {
+ } else if (device->info.chipset >= 0x30) {
*align = 32768;
*size = roundup(*size, 64 * nvbo->tile_mode);
- } else if (device->chipset >= 0x20) {
+ } else if (device->info.chipset >= 0x20) {
*align = 16384;
*size = roundup(*size, 64 * nvbo->tile_mode);
- } else if (device->chipset >= 0x10) {
+ } else if (device->info.chipset >= 0x10) {
*align = 16384;
*size = roundup(*size, 32 * nvbo->tile_mode);
}
@@ -196,12 +192,12 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
int lpg_shift = 12;
int max_size;
- if (drm->client.base.vm)
- lpg_shift = drm->client.base.vm->vmm->lpg_shift;
+ if (drm->client.vm)
+ lpg_shift = drm->client.vm->vmm->lpg_shift;
max_size = INT_MAX & ~((1 << lpg_shift) - 1);
if (size <= 0 || size > max_size) {
- nv_warn(drm, "skipped size %x\n", (u32)size);
+ NV_WARN(drm, "skipped size %x\n", (u32)size);
return -EINVAL;
}
@@ -219,9 +215,9 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
nvbo->bo.bdev = &drm->ttm.bdev;
nvbo->page_shift = 12;
- if (drm->client.base.vm) {
+ if (drm->client.vm) {
if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024)
- nvbo->page_shift = drm->client.base.vm->vmm->lpg_shift;
+ nvbo->page_shift = drm->client.vm->vmm->lpg_shift;
}
nouveau_bo_fixup_align(nvbo, flags, &align, &size);
@@ -261,11 +257,9 @@ static void
set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
{
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
- u32 vram_pages = pfb->ram->size >> PAGE_SHIFT;
+ u32 vram_pages = drm->device.info.ram_size >> PAGE_SHIFT;
- if ((nv_device(drm->device)->card_type == NV_10 ||
- nv_device(drm->device)->card_type == NV_11) &&
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
nvbo->bo.mem.num_pages < vram_pages / 4) {
/*
@@ -309,7 +303,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
struct ttm_buffer_object *bo = &nvbo->bo;
int ret;
- ret = ttm_bo_reserve(bo, false, false, false, 0);
+ ret = ttm_bo_reserve(bo, false, false, false, NULL);
if (ret)
goto out;
@@ -350,7 +344,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
struct ttm_buffer_object *bo = &nvbo->bo;
int ret, ref;
- ret = ttm_bo_reserve(bo, false, false, false, 0);
+ ret = ttm_bo_reserve(bo, false, false, false, NULL);
if (ret)
return ret;
@@ -385,7 +379,7 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
{
int ret;
- ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
if (ret)
return ret;
@@ -500,21 +494,28 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->default_caching = TTM_PL_FLAG_CACHED;
break;
case TTM_PL_VRAM:
- if (nv_device(drm->device)->card_type >= NV_50) {
+ man->flags = TTM_MEMTYPE_FLAG_FIXED |
+ TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_FLAG_UNCACHED |
+ TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_WC;
+
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ /* Some BARs do not support being ioremapped WC */
+ if (nvkm_bar(&drm->device)->iomap_uncached) {
+ man->available_caching = TTM_PL_FLAG_UNCACHED;
+ man->default_caching = TTM_PL_FLAG_UNCACHED;
+ }
+
man->func = &nouveau_vram_manager;
man->io_reserve_fastpath = false;
man->use_io_reserve_lru = true;
} else {
man->func = &ttm_bo_manager_func;
}
- man->flags = TTM_MEMTYPE_FLAG_FIXED |
- TTM_MEMTYPE_FLAG_MAPPABLE;
- man->available_caching = TTM_PL_FLAG_UNCACHED |
- TTM_PL_FLAG_WC;
- man->default_caching = TTM_PL_FLAG_WC;
break;
case TTM_PL_TT:
- if (nv_device(drm->device)->card_type >= NV_50)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
man->func = &nouveau_gart_manager;
else
if (drm->agp.stat != ENABLED)
@@ -763,9 +764,9 @@ nv50_bo_move_init(struct nouveau_channel *chan, u32 handle)
BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
OUT_RING (chan, handle);
BEGIN_NV04(chan, NvSubCopy, 0x0180, 3);
- OUT_RING (chan, NvNotify0);
- OUT_RING (chan, NvDmaFB);
- OUT_RING (chan, NvDmaFB);
+ OUT_RING (chan, chan->drm->ntfy.handle);
+ OUT_RING (chan, chan->vram.handle);
+ OUT_RING (chan, chan->vram.handle);
}
return ret;
@@ -852,7 +853,7 @@ nv04_bo_move_init(struct nouveau_channel *chan, u32 handle)
BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
OUT_RING (chan, handle);
BEGIN_NV04(chan, NvSubCopy, 0x0180, 1);
- OUT_RING (chan, NvNotify0);
+ OUT_RING (chan, chan->drm->ntfy.handle);
}
return ret;
@@ -864,7 +865,7 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
{
if (mem->mem_type == TTM_PL_TT)
return NvDmaTT;
- return NvDmaFB;
+ return chan->vram.handle;
}
static int
@@ -922,12 +923,12 @@ nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
u64 size = (u64)mem->num_pages << PAGE_SHIFT;
int ret;
- ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift,
+ ret = nouveau_vm_get(drm->client.vm, size, old_node->page_shift,
NV_MEM_ACCESS_RW, &old_node->vma[0]);
if (ret)
return ret;
- ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift,
+ ret = nouveau_vm_get(drm->client.vm, size, new_node->page_shift,
NV_MEM_ACCESS_RW, &old_node->vma[1]);
if (ret) {
nouveau_vm_put(&old_node->vma[0]);
@@ -945,6 +946,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
{
struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
struct nouveau_channel *chan = drm->ttm.chan;
+ struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
struct nouveau_fence *fence;
int ret;
@@ -952,13 +954,13 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
* old nouveau_mem node, these will get cleaned up after ttm has
* destroyed the ttm_mem_reg
*/
- if (nv_device(drm->device)->card_type >= NV_50) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
ret = nouveau_bo_move_prep(drm, bo, new_mem);
if (ret)
return ret;
}
- mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
+ mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
ret = nouveau_fence_sync(bo->sync_obj, chan);
if (ret == 0) {
ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
@@ -973,7 +975,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
}
}
}
- mutex_unlock(&chan->cli->mutex);
+ mutex_unlock(&cli->mutex);
return ret;
}
@@ -1005,9 +1007,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
int ret;
do {
- struct nouveau_object *object;
struct nouveau_channel *chan;
- u32 handle = (mthd->engine << 16) | mthd->oclass;
if (mthd->engine)
chan = drm->cechan;
@@ -1016,13 +1016,14 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
if (chan == NULL)
continue;
- ret = nouveau_object_new(nv_object(drm), chan->handle, handle,
- mthd->oclass, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL,
+ mthd->oclass | (mthd->engine << 16),
+ mthd->oclass, NULL, 0,
+ &drm->ttm.copy);
if (ret == 0) {
- ret = mthd->init(chan, handle);
+ ret = mthd->init(chan, drm->ttm.copy.handle);
if (ret) {
- nouveau_object_del(nv_object(drm),
- chan->handle, handle);
+ nvif_object_fini(&drm->ttm.copy);
continue;
}
@@ -1135,7 +1136,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
if (new_mem->mem_type != TTM_PL_VRAM)
return 0;
- if (nv_device(drm->device)->card_type >= NV_10) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
*new_tile = nv10_bo_set_tiling(dev, offset, new_mem->size,
nvbo->tile_mode,
nvbo->tile_flags);
@@ -1166,7 +1167,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
struct nouveau_drm_tile *new_tile = NULL;
int ret = 0;
- if (nv_device(drm->device)->card_type < NV_50) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
if (ret)
return ret;
@@ -1203,7 +1204,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
out:
- if (nv_device(drm->device)->card_type < NV_50) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
if (ret)
nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
else
@@ -1227,7 +1228,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
struct nouveau_drm *drm = nouveau_bdev(bdev);
struct nouveau_mem *node = mem->mm_node;
- struct drm_device *dev = drm->dev;
int ret;
mem->bus.addr = NULL;
@@ -1246,19 +1246,19 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
if (drm->agp.stat == ENABLED) {
mem->bus.offset = mem->start << PAGE_SHIFT;
mem->bus.base = drm->agp.base;
- mem->bus.is_iomem = !dev->agp->cant_use_aperture;
+ mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture;
}
#endif
- if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype)
/* untiled */
break;
/* fallthrough, tiled memory */
case TTM_PL_VRAM:
mem->bus.offset = mem->start << PAGE_SHIFT;
- mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);
+ mem->bus.base = nv_device_resource_start(nvkm_device(&drm->device), 1);
mem->bus.is_iomem = true;
- if (nv_device(drm->device)->card_type >= NV_50) {
- struct nouveau_bar *bar = nouveau_bar(drm->device);
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ struct nouveau_bar *bar = nvkm_bar(&drm->device);
ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,
&node->bar_vma);
@@ -1278,7 +1278,7 @@ static void
nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
{
struct nouveau_drm *drm = nouveau_bdev(bdev);
- struct nouveau_bar *bar = nouveau_bar(drm->device);
+ struct nouveau_bar *bar = nvkm_bar(&drm->device);
struct nouveau_mem *node = mem->mm_node;
if (!node->bar_vma.node)
@@ -1292,15 +1292,15 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
{
struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
struct nouveau_bo *nvbo = nouveau_bo(bo);
- struct nouveau_device *device = nv_device(drm->device);
- u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT;
+ struct nvif_device *device = &drm->device;
+ u32 mappable = nv_device_resource_len(nvkm_device(device), 1) >> PAGE_SHIFT;
int ret;
/* as long as the bo isn't in vram, and isn't tiled, we've got
* nothing to do here.
*/
if (bo->mem.mem_type != TTM_PL_VRAM) {
- if (nv_device(drm->device)->card_type < NV_50 ||
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA ||
!nouveau_bo_tile_layout(nvbo))
return 0;
@@ -1315,7 +1315,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
}
/* make sure bo is in mappable vram */
- if (nv_device(drm->device)->card_type >= NV_50 ||
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA ||
bo->mem.start + bo->mem.num_pages < mappable)
return 0;
@@ -1333,6 +1333,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
struct nouveau_drm *drm;
struct nouveau_device *device;
struct drm_device *dev;
+ struct device *pdev;
unsigned i;
int r;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1349,8 +1350,9 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
}
drm = nouveau_bdev(ttm->bdev);
- device = nv_device(drm->device);
+ device = nvkm_device(&drm->device);
dev = drm->dev;
+ pdev = nv_device_base(device);
#if __OS_HAS_AGP
if (drm->agp.stat == ENABLED) {
@@ -1370,17 +1372,22 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
}
for (i = 0; i < ttm->num_pages; i++) {
- ttm_dma->dma_address[i] = nv_device_map_page(device,
- ttm->pages[i]);
- if (!ttm_dma->dma_address[i]) {
+ dma_addr_t addr;
+
+ addr = dma_map_page(pdev, ttm->pages[i], 0, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+
+ if (dma_mapping_error(pdev, addr)) {
while (--i) {
- nv_device_unmap_page(device,
- ttm_dma->dma_address[i]);
+ dma_unmap_page(pdev, ttm_dma->dma_address[i],
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
ttm_dma->dma_address[i] = 0;
}
ttm_pool_unpopulate(ttm);
return -EFAULT;
}
+
+ ttm_dma->dma_address[i] = addr;
}
return 0;
}
@@ -1392,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
struct nouveau_drm *drm;
struct nouveau_device *device;
struct drm_device *dev;
+ struct device *pdev;
unsigned i;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1399,8 +1407,9 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
return;
drm = nouveau_bdev(ttm->bdev);
- device = nv_device(drm->device);
+ device = nvkm_device(&drm->device);
dev = drm->dev;
+ pdev = nv_device_base(device);
#if __OS_HAS_AGP
if (drm->agp.stat == ENABLED) {
@@ -1418,7 +1427,8 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
for (i = 0; i < ttm->num_pages; i++) {
if (ttm_dma->dma_address[i]) {
- nv_device_unmap_page(device, ttm_dma->dma_address[i]);
+ dma_unmap_page(pdev, ttm_dma->dma_address[i], PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
}
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index ccb6b452d6d0..99cd9e4a2aa6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -22,16 +22,11 @@
* Authors: Ben Skeggs
*/
-#include <core/object.h>
-#include <core/client.h>
-#include <core/device.h>
-#include <core/class.h>
-
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/instmem.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
-#include <engine/software.h>
+/*XXX*/
+#include <core/client.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -47,7 +42,7 @@ module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
int
nouveau_channel_idle(struct nouveau_channel *chan)
{
- struct nouveau_cli *cli = chan->cli;
+ struct nouveau_cli *cli = (void *)nvif_client(chan->object);
struct nouveau_fence *fence = NULL;
int ret;
@@ -58,8 +53,8 @@ nouveau_channel_idle(struct nouveau_channel *chan)
}
if (ret)
- NV_ERROR(cli, "failed to idle channel 0x%08x [%s]\n",
- chan->handle, cli->base.name);
+ NV_PRINTK(error, cli, "failed to idle channel 0x%08x [%s]\n",
+ chan->object->handle, nvkm_client(&cli->base)->name);
return ret;
}
@@ -68,36 +63,34 @@ nouveau_channel_del(struct nouveau_channel **pchan)
{
struct nouveau_channel *chan = *pchan;
if (chan) {
- struct nouveau_object *client = nv_object(chan->cli);
if (chan->fence) {
nouveau_channel_idle(chan);
nouveau_fence(chan->drm)->context_del(chan);
}
- nouveau_object_del(client, NVDRM_DEVICE, chan->handle);
- nouveau_object_del(client, NVDRM_DEVICE, chan->push.handle);
+ nvif_object_fini(&chan->nvsw);
+ nvif_object_fini(&chan->gart);
+ nvif_object_fini(&chan->vram);
+ nvif_object_ref(NULL, &chan->object);
+ nvif_object_fini(&chan->push.ctxdma);
nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma);
nouveau_bo_unmap(chan->push.buffer);
if (chan->push.buffer && chan->push.buffer->pin_refcnt)
nouveau_bo_unpin(chan->push.buffer);
nouveau_bo_ref(NULL, &chan->push.buffer);
+ nvif_device_ref(NULL, &chan->device);
kfree(chan);
}
*pchan = NULL;
}
static int
-nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
- u32 parent, u32 handle, u32 size,
- struct nouveau_channel **pchan)
+nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
+ u32 handle, u32 size, struct nouveau_channel **pchan)
{
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_instmem *imem = nouveau_instmem(device);
- struct nouveau_vmmgr *vmm = nouveau_vmmgr(device);
- struct nouveau_fb *pfb = nouveau_fb(device);
- struct nouveau_client *client = &cli->base;
- struct nv_dma_class args = {};
+ struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+ struct nouveau_vmmgr *vmm = nvkm_vmmgr(device);
+ struct nv_dma_v0 args = {};
struct nouveau_channel *chan;
- struct nouveau_object *push;
u32 target;
int ret;
@@ -105,9 +98,8 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
if (!chan)
return -ENOMEM;
- chan->cli = cli;
+ nvif_device_ref(device, &chan->device);
chan->drm = drm;
- chan->handle = handle;
/* allocate memory for dma push buffer */
target = TTM_PL_FLAG_TT;
@@ -132,51 +124,54 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
* we be able to call out to other (indirect) push buffers
*/
chan->push.vma.offset = chan->push.buffer->bo.offset;
- chan->push.handle = NVDRM_PUSH | (handle & 0xffff);
- if (device->card_type >= NV_50) {
- ret = nouveau_bo_vma_add(chan->push.buffer, client->vm,
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ ret = nouveau_bo_vma_add(chan->push.buffer, cli->vm,
&chan->push.vma);
if (ret) {
nouveau_channel_del(pchan);
return ret;
}
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+ args.target = NV_DMA_V0_TARGET_VM;
+ args.access = NV_DMA_V0_ACCESS_VM;
args.start = 0;
- args.limit = client->vm->vmm->limit - 1;
+ args.limit = cli->vm->vmm->limit - 1;
} else
if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
- u64 limit = pfb->ram->size - imem->reserved - 1;
- if (device->card_type == NV_04) {
+ if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
/* nv04 vram pushbuf hack, retarget to its location in
* the framebuffer bar rather than direct vram access..
* nfi why this exists, it came from the -nv ddx.
*/
- args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR;
- args.start = nv_device_resource_start(device, 1);
- args.limit = args.start + limit;
+ args.target = NV_DMA_V0_TARGET_PCI;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
+ args.start = nv_device_resource_start(nvkm_device(device), 1);
+ args.limit = args.start + device->info.ram_user - 1;
} else {
- args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_VRAM;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = 0;
- args.limit = limit;
+ args.limit = device->info.ram_user - 1;
}
} else {
if (chan->drm->agp.stat == ENABLED) {
- args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_AGP;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = chan->drm->agp.base;
args.limit = chan->drm->agp.base +
chan->drm->agp.size - 1;
} else {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_VM;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = 0;
args.limit = vmm->limit - 1;
}
}
- ret = nouveau_object_new(nv_object(chan->cli), parent,
- chan->push.handle, 0x0002,
- &args, sizeof(args), &push);
+ ret = nvif_object_init(nvif_object(device), NULL, NVDRM_PUSH |
+ (handle & 0xffff), NV_DMA_FROM_MEMORY,
+ &args, sizeof(args), &chan->push.ctxdma);
if (ret) {
nouveau_channel_del(pchan);
return ret;
@@ -186,38 +181,56 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,
}
static int
-nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli,
- u32 parent, u32 handle, u32 engine,
- struct nouveau_channel **pchan)
+nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
+ u32 handle, u32 engine, struct nouveau_channel **pchan)
{
- static const u16 oclasses[] = { NVE0_CHANNEL_IND_CLASS,
- NVC0_CHANNEL_IND_CLASS,
- NV84_CHANNEL_IND_CLASS,
- NV50_CHANNEL_IND_CLASS,
+ static const u16 oclasses[] = { KEPLER_CHANNEL_GPFIFO_A,
+ FERMI_CHANNEL_GPFIFO,
+ G82_CHANNEL_GPFIFO,
+ NV50_CHANNEL_GPFIFO,
0 };
const u16 *oclass = oclasses;
- struct nve0_channel_ind_class args;
+ union {
+ struct nv50_channel_gpfifo_v0 nv50;
+ struct kepler_channel_gpfifo_a_v0 kepler;
+ } args, *retn;
struct nouveau_channel *chan;
+ u32 size;
int ret;
/* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, cli, parent, handle, 0x12000, &chan);
+ ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan);
*pchan = chan;
if (ret)
return ret;
/* create channel object */
- args.pushbuf = chan->push.handle;
- args.ioffset = 0x10000 + chan->push.vma.offset;
- args.ilength = 0x02000;
- args.engine = engine;
-
do {
- ret = nouveau_object_new(nv_object(cli), parent, handle,
- *oclass++, &args, sizeof(args),
- &chan->object);
- if (ret == 0)
+ if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
+ args.kepler.version = 0;
+ args.kepler.engine = engine;
+ args.kepler.pushbuf = chan->push.ctxdma.handle;
+ args.kepler.ilength = 0x02000;
+ args.kepler.ioffset = 0x10000 + chan->push.vma.offset;
+ size = sizeof(args.kepler);
+ } else {
+ args.nv50.version = 0;
+ args.nv50.pushbuf = chan->push.ctxdma.handle;
+ args.nv50.ilength = 0x02000;
+ args.nv50.ioffset = 0x10000 + chan->push.vma.offset;
+ size = sizeof(args.nv50);
+ }
+
+ ret = nvif_object_new(nvif_object(device), handle, *oclass++,
+ &args, size, &chan->object);
+ if (ret == 0) {
+ retn = chan->object->data;
+ if (chan->object->oclass >= KEPLER_CHANNEL_GPFIFO_A)
+ chan->chid = retn->kepler.chid;
+ else
+ chan->chid = retn->nv50.chid;
return ret;
+ }
} while (*oclass);
nouveau_channel_del(pchan);
@@ -225,35 +238,38 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli,
}
static int
-nouveau_channel_dma(struct nouveau_drm *drm, struct nouveau_cli *cli,
- u32 parent, u32 handle, struct nouveau_channel **pchan)
+nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
+ u32 handle, struct nouveau_channel **pchan)
{
- static const u16 oclasses[] = { NV40_CHANNEL_DMA_CLASS,
- NV17_CHANNEL_DMA_CLASS,
- NV10_CHANNEL_DMA_CLASS,
- NV03_CHANNEL_DMA_CLASS,
+ static const u16 oclasses[] = { NV40_CHANNEL_DMA,
+ NV17_CHANNEL_DMA,
+ NV10_CHANNEL_DMA,
+ NV03_CHANNEL_DMA,
0 };
const u16 *oclass = oclasses;
- struct nv03_channel_dma_class args;
+ struct nv03_channel_dma_v0 args, *retn;
struct nouveau_channel *chan;
int ret;
/* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, cli, parent, handle, 0x10000, &chan);
+ ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan);
*pchan = chan;
if (ret)
return ret;
/* create channel object */
- args.pushbuf = chan->push.handle;
+ args.version = 0;
+ args.pushbuf = chan->push.ctxdma.handle;
args.offset = chan->push.vma.offset;
do {
- ret = nouveau_object_new(nv_object(cli), parent, handle,
- *oclass++, &args, sizeof(args),
- &chan->object);
- if (ret == 0)
+ ret = nvif_object_new(nvif_object(device), handle, *oclass++,
+ &args, sizeof(args), &chan->object);
+ if (ret == 0) {
+ retn = chan->object->data;
+ chan->chid = retn->chid;
return ret;
+ }
} while (ret && *oclass);
nouveau_channel_del(pchan);
@@ -263,60 +279,63 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nouveau_cli *cli,
static int
nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
{
- struct nouveau_client *client = nv_client(chan->cli);
- struct nouveau_device *device = nv_device(chan->drm->device);
- struct nouveau_instmem *imem = nouveau_instmem(device);
- struct nouveau_vmmgr *vmm = nouveau_vmmgr(device);
- struct nouveau_fb *pfb = nouveau_fb(device);
+ struct nvif_device *device = chan->device;
+ struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+ struct nouveau_vmmgr *vmm = nvkm_vmmgr(device);
struct nouveau_software_chan *swch;
- struct nouveau_object *object;
- struct nv_dma_class args = {};
+ struct nv_dma_v0 args = {};
int ret, i;
+ nvif_object_map(chan->object);
+
/* allocate dma objects to cover all allowed vram, and gart */
- if (device->card_type < NV_C0) {
- if (device->card_type >= NV_50) {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ args.target = NV_DMA_V0_TARGET_VM;
+ args.access = NV_DMA_V0_ACCESS_VM;
args.start = 0;
- args.limit = client->vm->vmm->limit - 1;
+ args.limit = cli->vm->vmm->limit - 1;
} else {
- args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_VRAM;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = 0;
- args.limit = pfb->ram->size - imem->reserved - 1;
+ args.limit = device->info.ram_user - 1;
}
- ret = nouveau_object_new(nv_object(client), chan->handle, vram,
- 0x003d, &args, sizeof(args), &object);
+ ret = nvif_object_init(chan->object, NULL, vram,
+ NV_DMA_IN_MEMORY, &args,
+ sizeof(args), &chan->vram);
if (ret)
return ret;
- if (device->card_type >= NV_50) {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_VM;
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ args.target = NV_DMA_V0_TARGET_VM;
+ args.access = NV_DMA_V0_ACCESS_VM;
args.start = 0;
- args.limit = client->vm->vmm->limit - 1;
+ args.limit = cli->vm->vmm->limit - 1;
} else
if (chan->drm->agp.stat == ENABLED) {
- args.flags = NV_DMA_TARGET_AGP | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_AGP;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = chan->drm->agp.base;
args.limit = chan->drm->agp.base +
chan->drm->agp.size - 1;
} else {
- args.flags = NV_DMA_TARGET_VM | NV_DMA_ACCESS_RDWR;
+ args.target = NV_DMA_V0_TARGET_VM;
+ args.access = NV_DMA_V0_ACCESS_RDWR;
args.start = 0;
args.limit = vmm->limit - 1;
}
- ret = nouveau_object_new(nv_object(client), chan->handle, gart,
- 0x003d, &args, sizeof(args), &object);
+ ret = nvif_object_init(chan->object, NULL, gart,
+ NV_DMA_IN_MEMORY, &args,
+ sizeof(args), &chan->gart);
if (ret)
return ret;
-
- chan->vram = vram;
- chan->gart = gart;
}
/* initialise dma tracking parameters */
- switch (nv_hclass(chan->object) & 0x00ff) {
+ switch (chan->object->oclass & 0x00ff) {
case 0x006b:
case 0x006e:
chan->user_put = 0x40;
@@ -347,13 +366,13 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
OUT_RING(chan, 0x00000000);
/* allocate software object class (used for fences on <= nv05) */
- if (device->card_type < NV_10) {
- ret = nouveau_object_new(nv_object(client), chan->handle,
- NvSw, 0x006e, NULL, 0, &object);
+ if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) {
+ ret = nvif_object_init(chan->object, NULL, 0x006e, 0x006e,
+ NULL, 0, &chan->nvsw);
if (ret)
return ret;
- swch = (void *)object->parent;
+ swch = (void *)nvkm_object(&chan->nvsw)->parent;
swch->flip = nouveau_flip_complete;
swch->flip_data = chan;
@@ -362,7 +381,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
return ret;
BEGIN_NV04(chan, NvSubSw, 0x0000, 1);
- OUT_RING (chan, NvSw);
+ OUT_RING (chan, chan->nvsw.handle);
FIRE_RING (chan);
}
@@ -371,25 +390,26 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
}
int
-nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli,
- u32 parent, u32 handle, u32 arg0, u32 arg1,
+nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
+ u32 handle, u32 arg0, u32 arg1,
struct nouveau_channel **pchan)
{
+ struct nouveau_cli *cli = (void *)nvif_client(&device->base);
int ret;
- ret = nouveau_channel_ind(drm, cli, parent, handle, arg0, pchan);
+ ret = nouveau_channel_ind(drm, device, handle, arg0, pchan);
if (ret) {
- NV_DEBUG(cli, "ib channel create, %d\n", ret);
- ret = nouveau_channel_dma(drm, cli, parent, handle, pchan);
+ NV_PRINTK(debug, cli, "ib channel create, %d\n", ret);
+ ret = nouveau_channel_dma(drm, device, handle, pchan);
if (ret) {
- NV_DEBUG(cli, "dma channel create, %d\n", ret);
+ NV_PRINTK(debug, cli, "dma channel create, %d\n", ret);
return ret;
}
}
ret = nouveau_channel_init(*pchan, arg0, arg1);
if (ret) {
- NV_ERROR(cli, "channel failed to initialise, %d\n", ret);
+ NV_PRINTK(error, cli, "channel failed to initialise, %d\n", ret);
nouveau_channel_del(pchan);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
index 40f97e2c47b6..20163709d608 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
@@ -1,20 +1,23 @@
#ifndef __NOUVEAU_CHAN_H__
#define __NOUVEAU_CHAN_H__
-struct nouveau_cli;
+#include <nvif/object.h>
+struct nvif_device;
struct nouveau_channel {
- struct nouveau_cli *cli;
+ struct nvif_device *device;
struct nouveau_drm *drm;
- u32 handle;
- u32 vram;
- u32 gart;
+ int chid;
+
+ struct nvif_object vram;
+ struct nvif_object gart;
+ struct nvif_object nvsw;
struct {
struct nouveau_bo *buffer;
struct nouveau_vma vma;
- u32 handle;
+ struct nvif_object ctxdma;
} push;
/* TODO: this will be reworked in the near future */
@@ -34,12 +37,12 @@ struct nouveau_channel {
u32 user_get;
u32 user_put;
- struct nouveau_object *object;
+ struct nvif_object *object;
};
-int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *,
- u32 parent, u32 handle, u32 arg0, u32 arg1,
+int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
+ u32 handle, u32 arg0, u32 arg1,
struct nouveau_channel **);
void nouveau_channel_del(struct nouveau_channel **);
int nouveau_channel_idle(struct nouveau_channel *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 1fa222e8f007..1ec44c83e919 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -42,9 +42,7 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
-#include <subdev/i2c.h>
-#include <subdev/gpio.h>
-#include <engine/disp.h>
+#include <nvif/event.h>
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
static int nouveau_tv_disable = 0;
@@ -63,7 +61,7 @@ find_encoder(struct drm_connector *connector, int type)
{
struct drm_device *dev = connector->dev;
struct nouveau_encoder *nv_encoder;
- struct drm_mode_object *obj;
+ struct drm_encoder *enc;
int i, id;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
@@ -71,10 +69,10 @@ find_encoder(struct drm_connector *connector, int type)
if (!id)
break;
- obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ enc = drm_encoder_find(dev, id);
+ if (!enc)
continue;
- nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+ nv_encoder = nouveau_encoder(enc);
if (type == DCB_OUTPUT_ANY ||
(nv_encoder->dcb && nv_encoder->dcb->type == type))
@@ -102,9 +100,9 @@ static void
nouveau_connector_destroy(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
- nouveau_event_ref(NULL, &nv_connector->hpd);
+ nvif_notify_fini(&nv_connector->hpd);
kfree(nv_connector->edid);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
if (nv_connector->aux.transfer)
drm_dp_aux_unregister(&nv_connector->aux);
@@ -117,9 +115,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
+ struct nouveau_gpio *gpio = nvkm_gpio(&drm->device);
struct nouveau_encoder *nv_encoder;
- struct drm_mode_object *obj;
+ struct drm_encoder *encoder;
int i, panel = -ENODEV;
/* eDP panels need powering on by us (if the VBIOS doesn't default it
@@ -139,10 +137,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
if (id == 0)
break;
- obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(dev, id);
+ if (!encoder)
continue;
- nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+ nv_encoder = nouveau_encoder(encoder);
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
int ret = nouveau_dp_detect(nv_encoder);
@@ -206,7 +204,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
return;
nv_connector->detected_encoder = nv_encoder;
- if (nv_device(drm->device)->card_type >= NV_50) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
connector->interlace_allowed = true;
connector->doublescan_allowed = true;
} else
@@ -216,9 +214,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
connector->interlace_allowed = false;
} else {
connector->doublescan_allowed = true;
- if (nv_device(drm->device)->card_type == NV_20 ||
- ((nv_device(drm->device)->card_type == NV_10 ||
- nv_device(drm->device)->card_type == NV_11) &&
+ if (drm->device.info.family == NV_DEVICE_INFO_V0_KELVIN ||
+ (drm->device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
(dev->pdev->device & 0x0ff0) != 0x0100 &&
(dev->pdev->device & 0x0ff0) != 0x0150))
/* HW is broken */
@@ -802,11 +799,11 @@ get_tmds_link_bandwidth(struct drm_connector *connector)
struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
if (dcb->location != DCB_LOC_ON_CHIP ||
- nv_device(drm->device)->chipset >= 0x46)
+ drm->device.info.chipset >= 0x46)
return 165000;
- else if (nv_device(drm->device)->chipset >= 0x40)
+ else if (drm->device.info.chipset >= 0x40)
return 155000;
- else if (nv_device(drm->device)->chipset >= 0x18)
+ else if (drm->device.info.chipset >= 0x18)
return 135000;
else
return 112000;
@@ -939,18 +936,19 @@ nouveau_connector_funcs_dp = {
.force = nouveau_connector_force
};
-static void
-nouveau_connector_hotplug_work(struct work_struct *work)
+static int
+nouveau_connector_hotplug(struct nvif_notify *notify)
{
struct nouveau_connector *nv_connector =
- container_of(work, typeof(*nv_connector), work);
+ container_of(notify, typeof(*nv_connector), hpd);
struct drm_connector *connector = &nv_connector->base;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ const struct nvif_notify_conn_rep_v0 *rep = notify->data;
const char *name = connector->name;
- if (nv_connector->status & NVKM_HPD_IRQ) {
+ if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
} else {
- bool plugged = (nv_connector->status != NVKM_HPD_UNPLUG);
+ bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
@@ -961,16 +959,7 @@ nouveau_connector_hotplug_work(struct work_struct *work)
drm_helper_hpd_irq_event(connector->dev);
}
- nouveau_event_get(nv_connector->hpd);
-}
-
-static int
-nouveau_connector_hotplug(void *data, u32 type, int index)
-{
- struct nouveau_connector *nv_connector = data;
- nv_connector->status = type;
- schedule_work(&nv_connector->work);
- return NVKM_EVENT_DROP;
+ return NVIF_NOTIFY_KEEP;
}
static ssize_t
@@ -1040,7 +1029,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_connector *nv_connector = NULL;
- struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct drm_connector *connector;
int type, ret = 0;
bool dummy;
@@ -1194,7 +1182,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
switch (nv_connector->type) {
case DCB_CONNECTOR_VGA:
- if (nv_device(drm->device)->card_type >= NV_50) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
drm_object_attach_property(&connector->base,
dev->mode_config.scaling_mode_property,
nv_connector->scaling_mode);
@@ -1226,16 +1214,20 @@ nouveau_connector_create(struct drm_device *dev, int index)
break;
}
- ret = nouveau_event_new(pdisp->hpd, NVKM_HPD, index,
- nouveau_connector_hotplug,
- nv_connector, &nv_connector->hpd);
+ ret = nvif_notify_init(&disp->disp, NULL, nouveau_connector_hotplug,
+ true, NV04_DISP_NTFY_CONN,
+ &(struct nvif_notify_conn_req_v0) {
+ .mask = NVIF_NOTIFY_CONN_V0_ANY,
+ .conn = index,
+ },
+ sizeof(struct nvif_notify_conn_req_v0),
+ sizeof(struct nvif_notify_conn_rep_v0),
+ &nv_connector->hpd);
if (ret)
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
else
connector->polled = DRM_CONNECTOR_POLL_HPD;
- INIT_WORK(&nv_connector->work, nouveau_connector_hotplug_work);
-
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return connector;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 8861b6c579ad..68029d041dd2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -27,14 +27,12 @@
#ifndef __NOUVEAU_CONNECTOR_H__
#define __NOUVEAU_CONNECTOR_H__
+#include <nvif/notify.h>
+
#include <drm/drm_edid.h>
#include <drm/drm_dp_helper.h>
#include "nouveau_crtc.h"
-#include <core/event.h>
-
-#include <subdev/bios.h>
-
struct nouveau_i2c_port;
enum nouveau_underscan_type {
@@ -67,9 +65,7 @@ struct nouveau_connector {
u8 index;
u8 *dcb;
- struct nouveau_eventh *hpd;
- u32 status;
- struct work_struct work;
+ struct nvif_notify hpd;
struct drm_dp_aux aux;
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index a0534489d23f..f19cb1c5fc5a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -27,10 +27,13 @@
#ifndef __NOUVEAU_CRTC_H__
#define __NOUVEAU_CRTC_H__
+#include <nvif/notify.h>
+
struct nouveau_crtc {
struct drm_crtc base;
int index;
+ struct nvif_notify vblank;
uint32_t dpms_saved_fp_control;
uint32_t fp_users;
@@ -46,7 +49,7 @@ struct nouveau_crtc {
int cpp;
bool blanked;
uint32_t offset;
- uint32_t tile_flags;
+ uint32_t handle;
} fb;
struct {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 47ad74255bf1..65b4fd53dd4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -27,6 +27,8 @@
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <nvif/class.h>
+
#include "nouveau_fbcon.h"
#include "dispnv04/hw.h"
#include "nouveau_crtc.h"
@@ -37,35 +39,42 @@
#include "nouveau_fence.h"
-#include <engine/disp.h>
-
-#include <core/class.h>
+#include <nvif/event.h>
static int
-nouveau_display_vblank_handler(void *data, u32 type, int head)
+nouveau_display_vblank_handler(struct nvif_notify *notify)
{
- struct nouveau_drm *drm = data;
- drm_handle_vblank(drm->dev, head);
- return NVKM_EVENT_KEEP;
+ struct nouveau_crtc *nv_crtc =
+ container_of(notify, typeof(*nv_crtc), vblank);
+ drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index);
+ return NVIF_NOTIFY_KEEP;
}
int
nouveau_display_vblank_enable(struct drm_device *dev, int head)
{
- struct nouveau_display *disp = nouveau_display(dev);
- if (disp) {
- nouveau_event_get(disp->vblank[head]);
- return 0;
+ struct drm_crtc *crtc;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ if (nv_crtc->index == head) {
+ nvif_notify_get(&nv_crtc->vblank);
+ return 0;
+ }
}
- return -EIO;
+ return -EINVAL;
}
void
nouveau_display_vblank_disable(struct drm_device *dev, int head)
{
- struct nouveau_display *disp = nouveau_display(dev);
- if (disp)
- nouveau_event_put(disp->vblank[head]);
+ struct drm_crtc *crtc;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ if (nv_crtc->index == head) {
+ nvif_notify_put(&nv_crtc->vblank);
+ return;
+ }
+ }
}
static inline int
@@ -86,17 +95,22 @@ int
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime)
{
- const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index;
+ struct {
+ struct nv04_disp_mthd_v0 base;
+ struct nv04_disp_scanoutpos_v0 scan;
+ } args = {
+ .base.method = NV04_DISP_SCANOUTPOS,
+ .base.head = nouveau_crtc(crtc)->index,
+ };
struct nouveau_display *disp = nouveau_display(crtc->dev);
- struct nv04_display_scanoutpos args;
int ret, retry = 1;
do {
- ret = nv_exec(disp->core, mthd, &args, sizeof(args));
+ ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
if (ret != 0)
return 0;
- if (args.vline) {
+ if (args.scan.vline) {
ret |= DRM_SCANOUTPOS_ACCURATE;
ret |= DRM_SCANOUTPOS_VALID;
break;
@@ -105,10 +119,11 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
if (retry) ndelay(crtc->linedur_ns);
} while (retry--);
- *hpos = args.hline;
- *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
- if (stime) *stime = ns_to_ktime(args.time[0]);
- if (etime) *etime = ns_to_ktime(args.time[1]);
+ *hpos = args.scan.hline;
+ *vpos = calc(args.scan.vblanks, args.scan.vblanke,
+ args.scan.vtotal, args.scan.vline);
+ if (stime) *stime = ns_to_ktime(args.scan.time[0]);
+ if (etime) *etime = ns_to_ktime(args.scan.time[1]);
if (*vpos < 0)
ret |= DRM_SCANOUTPOS_INVBL;
@@ -151,16 +166,13 @@ nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
static void
nouveau_display_vblank_fini(struct drm_device *dev)
{
- struct nouveau_display *disp = nouveau_display(dev);
- int i;
+ struct drm_crtc *crtc;
drm_vblank_cleanup(dev);
- if (disp->vblank) {
- for (i = 0; i < dev->mode_config.num_crtc; i++)
- nouveau_event_ref(NULL, &disp->vblank[i]);
- kfree(disp->vblank);
- disp->vblank = NULL;
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ nvif_notify_fini(&nv_crtc->vblank);
}
}
@@ -168,19 +180,20 @@ static int
nouveau_display_vblank_init(struct drm_device *dev)
{
struct nouveau_display *disp = nouveau_display(dev);
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_disp *pdisp = nouveau_disp(drm->device);
- int ret, i;
-
- disp->vblank = kzalloc(dev->mode_config.num_crtc *
- sizeof(*disp->vblank), GFP_KERNEL);
- if (!disp->vblank)
- return -ENOMEM;
+ struct drm_crtc *crtc;
+ int ret;
- for (i = 0; i < dev->mode_config.num_crtc; i++) {
- ret = nouveau_event_new(pdisp->vblank, 1, i,
- nouveau_display_vblank_handler,
- drm, &disp->vblank[i]);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+ ret = nvif_notify_init(&disp->disp, NULL,
+ nouveau_display_vblank_handler, false,
+ NV04_DISP_NTFY_VBLANK,
+ &(struct nvif_notify_head_req_v0) {
+ .head = nv_crtc->index,
+ },
+ sizeof(struct nvif_notify_head_req_v0),
+ sizeof(struct nvif_notify_head_rep_v0),
+ &nv_crtc->vblank);
if (ret) {
nouveau_display_vblank_fini(dev);
return ret;
@@ -200,6 +213,10 @@ static void
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
{
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+ struct nouveau_display *disp = nouveau_display(drm_fb->dev);
+
+ if (disp->fb_dtor)
+ disp->fb_dtor(drm_fb);
if (fb->nvbo)
drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
@@ -229,63 +246,24 @@ nouveau_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct nouveau_bo *nvbo)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_display *disp = nouveau_display(dev);
struct drm_framebuffer *fb = &nv_fb->base;
int ret;
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
nv_fb->nvbo = nvbo;
- if (nv_device(drm->device)->card_type >= NV_50) {
- u32 tile_flags = nouveau_bo_tile_layout(nvbo);
- if (tile_flags == 0x7a00 ||
- tile_flags == 0xfe00)
- nv_fb->r_dma = NvEvoFB32;
- else
- if (tile_flags == 0x7000)
- nv_fb->r_dma = NvEvoFB16;
- else
- nv_fb->r_dma = NvEvoVRAM_LP;
-
- switch (fb->depth) {
- case 8: nv_fb->r_format = 0x1e00; break;
- case 15: nv_fb->r_format = 0xe900; break;
- case 16: nv_fb->r_format = 0xe800; break;
- case 24:
- case 32: nv_fb->r_format = 0xcf00; break;
- case 30: nv_fb->r_format = 0xd100; break;
- default:
- NV_ERROR(drm, "unknown depth %d\n", fb->depth);
- return -EINVAL;
- }
-
- if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
- NV_ERROR(drm, "framebuffer requires contiguous bo\n");
- return -EINVAL;
- }
-
- if (nv_device(drm->device)->chipset == 0x50)
- nv_fb->r_format |= (tile_flags << 8);
-
- if (!tile_flags) {
- if (nv_device(drm->device)->card_type < NV_D0)
- nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
- else
- nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
- } else {
- u32 mode = nvbo->tile_mode;
- if (nv_device(drm->device)->card_type >= NV_C0)
- mode >>= 4;
- nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
- }
- }
-
ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
- if (ret) {
+ if (ret)
return ret;
+
+ if (disp->fb_ctor) {
+ ret = disp->fb_ctor(fb);
+ if (ret)
+ disp->fb_dtor(fb);
}
- return 0;
+ return ret;
}
static struct drm_framebuffer *
@@ -393,7 +371,7 @@ nouveau_display_init(struct drm_device *dev)
/* enable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
- if (conn->hpd) nouveau_event_get(conn->hpd);
+ nvif_notify_get(&conn->hpd);
}
return ret;
@@ -404,37 +382,32 @@ nouveau_display_fini(struct drm_device *dev)
{
struct nouveau_display *disp = nouveau_display(dev);
struct drm_connector *connector;
+ int head;
+
+ /* Make sure that drm and hw vblank irqs get properly disabled. */
+ for (head = 0; head < dev->mode_config.num_crtc; head++)
+ drm_vblank_off(dev, head);
/* disable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
- if (conn->hpd) nouveau_event_put(conn->hpd);
+ nvif_notify_put(&conn->hpd);
}
drm_kms_helper_poll_disable(dev);
disp->fini(dev);
}
-int
-nouveau_display_create(struct drm_device *dev)
+static void
+nouveau_display_create_properties(struct drm_device *dev)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nouveau_dev(dev);
- struct nouveau_display *disp;
- int ret, gen;
-
- disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
- if (!disp)
- return -ENOMEM;
-
- drm_mode_config_init(dev);
- drm_mode_create_scaling_mode_property(dev);
- drm_mode_create_dvi_i_properties(dev);
+ struct nouveau_display *disp = nouveau_display(dev);
+ int gen;
- if (nv_device(drm->device)->card_type < NV_50)
+ if (disp->disp.oclass < NV50_DISP)
gen = 0;
else
- if (nv_device(drm->device)->card_type < NV_D0)
+ if (disp->disp.oclass < GF110_DISP)
gen = 1;
else
gen = 2;
@@ -449,26 +422,43 @@ nouveau_display_create(struct drm_device *dev)
disp->underscan_vborder_property =
drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
- if (gen >= 1) {
- /* -90..+90 */
- disp->vibrant_hue_property =
- drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
+ if (gen < 1)
+ return;
- /* -100..+100 */
- disp->color_vibrance_property =
- drm_property_create_range(dev, 0, "color vibrance", 0, 200);
- }
+ /* -90..+90 */
+ disp->vibrant_hue_property =
+ drm_property_create_range(dev, 0, "vibrant hue", 0, 180);
+
+ /* -100..+100 */
+ disp->color_vibrance_property =
+ drm_property_create_range(dev, 0, "color vibrance", 0, 200);
+}
+
+int
+nouveau_display_create(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_display *disp;
+ int ret;
+
+ disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
+ if (!disp)
+ return -ENOMEM;
+
+ drm_mode_config_init(dev);
+ drm_mode_create_scaling_mode_property(dev);
+ drm_mode_create_dvi_i_properties(dev);
dev->mode_config.funcs = &nouveau_mode_config_funcs;
- dev->mode_config.fb_base = nv_device_resource_start(device, 1);
+ dev->mode_config.fb_base = nv_device_resource_start(nvkm_device(&drm->device), 1);
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
- if (nv_device(drm->device)->card_type < NV_10) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_CELSIUS) {
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
} else
- if (nv_device(drm->device)->card_type < NV_50) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
} else {
@@ -479,7 +469,7 @@ nouveau_display_create(struct drm_device *dev)
dev->mode_config.preferred_depth = 24;
dev->mode_config.prefer_shadow = 1;
- if (nv_device(drm->device)->chipset < 0x11)
+ if (drm->device.info.chipset < 0x11)
dev->mode_config.async_page_flip = false;
else
dev->mode_config.async_page_flip = true;
@@ -487,29 +477,30 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
- if (drm->vbios.dcb.entries) {
+ if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
static const u16 oclass[] = {
- GM107_DISP_CLASS,
- NVF0_DISP_CLASS,
- NVE0_DISP_CLASS,
- NVD0_DISP_CLASS,
- NVA3_DISP_CLASS,
- NV94_DISP_CLASS,
- NVA0_DISP_CLASS,
- NV84_DISP_CLASS,
- NV50_DISP_CLASS,
- NV04_DISP_CLASS,
+ GM107_DISP,
+ GK110_DISP,
+ GK104_DISP,
+ GF110_DISP,
+ GT214_DISP,
+ GT206_DISP,
+ GT200_DISP,
+ G82_DISP,
+ NV50_DISP,
+ NV04_DISP,
};
int i;
for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
- ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
- NVDRM_DISPLAY, oclass[i],
- NULL, 0, &disp->core);
+ ret = nvif_object_init(nvif_object(&drm->device), NULL,
+ NVDRM_DISPLAY, oclass[i],
+ NULL, 0, &disp->disp);
}
if (ret == 0) {
- if (nv_mclass(disp->core) < NV50_DISP_CLASS)
+ nouveau_display_create_properties(dev);
+ if (disp->disp.oclass < NV50_DISP)
ret = nv04_display_create(dev);
else
ret = nv50_display_create(dev);
@@ -542,7 +533,6 @@ void
nouveau_display_destroy(struct drm_device *dev)
{
struct nouveau_display *disp = nouveau_display(dev);
- struct nouveau_drm *drm = nouveau_drm(dev);
nouveau_backlight_exit(dev);
nouveau_display_vblank_fini(dev);
@@ -553,7 +543,7 @@ nouveau_display_destroy(struct drm_device *dev)
if (disp->dtor)
disp->dtor(dev);
- nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY);
+ nvif_object_fini(&disp->disp);
nouveau_drm(dev)->display = NULL;
kfree(disp);
@@ -602,7 +592,9 @@ nouveau_display_repin(struct drm_device *dev)
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
- nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+ ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+ if (ret)
+ NV_ERROR(drm, "Could not pin framebuffer\n");
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -620,6 +612,8 @@ void
nouveau_display_resume(struct drm_device *dev)
{
struct drm_crtc *crtc;
+ int head;
+
nouveau_display_init(dev);
/* Force CLUT to get re-loaded during modeset */
@@ -629,6 +623,10 @@ nouveau_display_resume(struct drm_device *dev)
nv_crtc->lut.depth = 0;
}
+ /* Make sure that drm and hw vblank irqs get resumed if needed. */
+ for (head = 0; head < dev->mode_config.num_crtc; head++)
+ drm_vblank_on(dev, head);
+
drm_helper_resume_force_mode(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -669,7 +667,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
if (ret)
goto fail;
- if (nv_device(drm->device)->card_type < NV_C0)
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
else
BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
@@ -698,12 +696,15 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;
struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
struct nouveau_page_flip_state *s;
- struct nouveau_channel *chan = drm->channel;
+ struct nouveau_channel *chan;
+ struct nouveau_cli *cli;
struct nouveau_fence *fence;
int ret;
- if (!drm->channel)
+ chan = drm->channel;
+ if (!chan)
return -ENODEV;
+ cli = (void *)nvif_client(&chan->device->base);
s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
@@ -715,7 +716,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
goto fail_free;
}
- mutex_lock(&chan->cli->mutex);
+ mutex_lock(&cli->mutex);
/* synchronise rendering channel with the kernel's channel */
spin_lock(&new_bo->bo.bdev->fence_lock);
@@ -740,7 +741,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
drm_vblank_get(dev, nouveau_crtc(crtc)->index);
/* Emit a page flip */
- if (nv_device(drm->device)->card_type >= NV_50) {
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
if (ret)
goto fail_unreserve;
@@ -769,7 +770,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
if (ret)
goto fail_unreserve;
- mutex_unlock(&chan->cli->mutex);
+ mutex_unlock(&cli->mutex);
/* Update the crtc struct and cleanup */
crtc->primary->fb = fb;
@@ -785,7 +786,7 @@ fail_unreserve:
drm_vblank_put(dev, nouveau_crtc(crtc)->index);
ttm_bo_unreserve(&old_bo->bo);
fail_unpin:
- mutex_unlock(&chan->cli->mutex);
+ mutex_unlock(&cli->mutex);
if (old_bo != new_bo)
nouveau_bo_unpin(new_bo);
fail_free:
@@ -815,7 +816,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
if (s->event) {
/* Vblank timestamps/counts are only correct on >= NV-50 */
- if (nv_device(drm->device)->card_type >= NV_50)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
crtcid = s->crtc;
drm_send_vblank_event(dev, crtcid, s->event);
@@ -841,7 +842,7 @@ nouveau_flip_complete(void *data)
struct nouveau_page_flip_state state;
if (!nouveau_finish_page_flip(chan, &state)) {
- if (nv_device(drm->device)->card_type < NV_50) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
nv_set_crtc_base(drm->dev, state.crtc, state.offset +
state.y * state.pitch +
state.x * state.bpp / 8);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index a71cf77e55b2..88ca177cb1c7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -9,9 +9,11 @@ struct nouveau_framebuffer {
struct drm_framebuffer base;
struct nouveau_bo *nvbo;
struct nouveau_vma vma;
- u32 r_dma;
+ u32 r_handle;
u32 r_format;
u32 r_pitch;
+ struct nvif_object h_base[4];
+ struct nvif_object h_core;
};
static inline struct nouveau_framebuffer *
@@ -36,8 +38,10 @@ struct nouveau_display {
int (*init)(struct drm_device *);
void (*fini)(struct drm_device *);
- struct nouveau_object *core;
- struct nouveau_eventh **vblank;
+ int (*fb_ctor)(struct drm_framebuffer *);
+ void (*fb_dtor)(struct drm_framebuffer *);
+
+ struct nvif_object disp;
struct drm_property *dithering_mode;
struct drm_property *dithering_depth;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index c177272152e2..8508603cc8c3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -24,8 +24,6 @@
*
*/
-#include <core/client.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -54,9 +52,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
{
uint64_t val;
- val = nv_ro32(chan->object, chan->user_get);
+ val = nvif_rd32(chan, chan->user_get);
if (chan->user_get_hi)
- val |= (uint64_t)nv_ro32(chan->object, chan->user_get_hi) << 32;
+ val |= (uint64_t)nvif_rd32(chan, chan->user_get_hi) << 32;
/* reset counter as long as GET is still advancing, this is
* to avoid misdetecting a GPU lockup if the GPU happens to
@@ -84,12 +82,13 @@ void
nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
int delta, int length)
{
+ struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
struct nouveau_bo *pb = chan->push.buffer;
struct nouveau_vma *vma;
int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
u64 offset;
- vma = nouveau_bo_vma_find(bo, nv_client(chan->cli)->vm);
+ vma = nouveau_bo_vma_find(bo, cli->vm);
BUG_ON(!vma);
offset = vma->offset + delta;
@@ -104,7 +103,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
/* Flush writes. */
nouveau_bo_rd32(pb, 0);
- nv_wo32(chan->object, 0x8c, chan->dma.ib_put);
+ nvif_wr32(chan, 0x8c, chan->dma.ib_put);
chan->dma.ib_free--;
}
@@ -114,7 +113,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
uint32_t cnt = 0, prev_get = 0;
while (chan->dma.ib_free < count) {
- uint32_t get = nv_ro32(chan->object, 0x88);
+ uint32_t get = nvif_rd32(chan, 0x88);
if (get != prev_get) {
prev_get = get;
cnt = 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index dc0e0c5cadb4..8da0a272c45a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -58,31 +58,14 @@ enum {
FermiSw = 5, /* DO NOT CHANGE (well.. 6/7 will work...) */
};
-/* Object handles. */
+/* Object handles - for stuff that's doesn't use handle == oclass. */
enum {
- NvM2MF = 0x80000001,
NvDmaFB = 0x80000002,
NvDmaTT = 0x80000003,
NvNotify0 = 0x80000006,
- Nv2D = 0x80000007,
- NvCtxSurf2D = 0x80000008,
- NvRop = 0x80000009,
- NvImagePatt = 0x8000000a,
- NvClipRect = 0x8000000b,
- NvGdiRect = 0x8000000c,
- NvImageBlit = 0x8000000d,
- NvSw = 0x8000000e,
NvSema = 0x8000000f,
NvEvoSema0 = 0x80000010,
NvEvoSema1 = 0x80000011,
- NvNotify1 = 0x80000012,
-
- /* G80+ display objects */
- NvEvoVRAM = 0x01000000,
- NvEvoFB16 = 0x01000001,
- NvEvoFB32 = 0x01000002,
- NvEvoVRAM_LP = 0x01000003,
- NvEvoSync = 0xcafe0000
};
#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039
@@ -157,7 +140,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data)
#define WRITE_PUT(val) do { \
mb(); \
nouveau_bo_rd32(chan->push.buffer, 0); \
- nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset); \
+ nvif_wr32(chan, chan->user_put, ((val) << 2) + chan->push.vma.offset); \
} while (0)
static inline void
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 5675ffc175ae..c5137cccce7d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -30,11 +30,6 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
-#include <core/class.h>
-
-#include <subdev/gpio.h>
-#include <subdev/i2c.h>
-
static void
nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
u8 *dpcd)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 5425ffe3931d..250a5e88c751 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -27,21 +27,14 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/vga_switcheroo.h>
+
#include "drmP.h"
#include "drm_crtc_helper.h"
+
#include <core/device.h>
-#include <core/client.h>
#include <core/gpuobj.h>
-#include <core/class.h>
#include <core/option.h>
-#include <engine/device.h>
-#include <engine/disp.h>
-#include <engine/fifo.h>
-#include <engine/software.h>
-
-#include <subdev/vm.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_ttm.h"
@@ -57,6 +50,7 @@
#include "nouveau_fbcon.h"
#include "nouveau_fence.h"
#include "nouveau_debugfs.h"
+#include "nouveau_usif.h"
MODULE_PARM_DESC(config, "option string to pass to driver core");
static char *nouveau_config;
@@ -109,40 +103,37 @@ static int
nouveau_cli_create(u64 name, const char *sname,
int size, void **pcli)
{
- struct nouveau_cli *cli;
- int ret;
-
- *pcli = NULL;
- ret = nouveau_client_create_(sname, name, nouveau_config,
- nouveau_debug, size, pcli);
- cli = *pcli;
- if (ret) {
- if (cli)
- nouveau_client_destroy(&cli->base);
- *pcli = NULL;
+ struct nouveau_cli *cli = *pcli = kzalloc(size, GFP_KERNEL);
+ if (cli) {
+ int ret = nvif_client_init(NULL, NULL, sname, name,
+ nouveau_config, nouveau_debug,
+ &cli->base);
+ if (ret == 0) {
+ mutex_init(&cli->mutex);
+ usif_client_init(cli);
+ }
return ret;
}
-
- mutex_init(&cli->mutex);
- return 0;
+ return -ENOMEM;
}
static void
nouveau_cli_destroy(struct nouveau_cli *cli)
{
- struct nouveau_object *client = nv_object(cli);
- nouveau_vm_ref(NULL, &cli->base.vm, NULL);
- nouveau_client_fini(&cli->base, false);
- atomic_set(&client->refcount, 1);
- nouveau_object_ref(NULL, &client);
+ nouveau_vm_ref(NULL, &nvkm_client(&cli->base)->vm, NULL);
+ nvif_client_fini(&cli->base);
+ usif_client_fini(cli);
}
static void
nouveau_accel_fini(struct nouveau_drm *drm)
{
- nouveau_gpuobj_ref(NULL, &drm->notify);
nouveau_channel_del(&drm->channel);
+ nvif_object_fini(&drm->ntfy);
+ nouveau_gpuobj_ref(NULL, &drm->notify);
+ nvif_object_fini(&drm->nvsw);
nouveau_channel_del(&drm->cechan);
+ nvif_object_fini(&drm->ttm.copy);
if (drm->fence)
nouveau_fence(drm)->dtor(drm);
}
@@ -150,46 +141,71 @@ nouveau_accel_fini(struct nouveau_drm *drm)
static void
nouveau_accel_init(struct nouveau_drm *drm)
{
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_object *object;
+ struct nvif_device *device = &drm->device;
u32 arg0, arg1;
- int ret;
+ u32 sclass[16];
+ int ret, i;
- if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/)
+ if (nouveau_noaccel)
return;
/* initialise synchronisation routines */
- if (device->card_type < NV_10) ret = nv04_fence_create(drm);
- else if (device->card_type < NV_11 ||
- device->chipset < 0x17) ret = nv10_fence_create(drm);
- else if (device->card_type < NV_50) ret = nv17_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);
+ /*XXX: this is crap, but the fence/channel stuff is a little
+ * backwards in some places. this will be fixed.
+ */
+ ret = nvif_object_sclass(&device->base, sclass, ARRAY_SIZE(sclass));
+ if (ret < 0)
+ return;
+
+ for (ret = -ENOSYS, i = 0; ret && i < ARRAY_SIZE(sclass); i++) {
+ switch (sclass[i]) {
+ case NV03_CHANNEL_DMA:
+ ret = nv04_fence_create(drm);
+ break;
+ case NV10_CHANNEL_DMA:
+ ret = nv10_fence_create(drm);
+ break;
+ case NV17_CHANNEL_DMA:
+ case NV40_CHANNEL_DMA:
+ ret = nv17_fence_create(drm);
+ break;
+ case NV50_CHANNEL_GPFIFO:
+ ret = nv50_fence_create(drm);
+ break;
+ case G82_CHANNEL_GPFIFO:
+ ret = nv84_fence_create(drm);
+ break;
+ case FERMI_CHANNEL_GPFIFO:
+ case KEPLER_CHANNEL_GPFIFO_A:
+ ret = nvc0_fence_create(drm);
+ break;
+ default:
+ break;
+ }
+ }
+
if (ret) {
NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret);
nouveau_accel_fini(drm);
return;
}
- if (device->card_type >= NV_E0) {
- ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE,
- NVDRM_CHAN + 1,
- NVE0_CHANNEL_IND_ENGINE_CE0 |
- NVE0_CHANNEL_IND_ENGINE_CE1, 0,
- &drm->cechan);
+ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
+ ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+ KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0|
+ KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1,
+ 0, &drm->cechan);
if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
- arg0 = NVE0_CHANNEL_IND_ENGINE_GR;
+ arg0 = KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR;
arg1 = 1;
} else
- if (device->chipset >= 0xa3 &&
- device->chipset != 0xaa &&
- device->chipset != 0xac) {
- ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE,
- NVDRM_CHAN + 1, NvDmaFB, NvDmaTT,
- &drm->cechan);
+ if (device->info.chipset >= 0xa3 &&
+ device->info.chipset != 0xaa &&
+ device->info.chipset != 0xac) {
+ ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1,
+ NvDmaFB, NvDmaTT, &drm->cechan);
if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
@@ -200,30 +216,30 @@ nouveau_accel_init(struct nouveau_drm *drm)
arg1 = NvDmaTT;
}
- ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN,
- arg0, arg1, &drm->channel);
+ ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1,
+ &drm->channel);
if (ret) {
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
nouveau_accel_fini(drm);
return;
}
- ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW,
- nouveau_abi16_swclass(drm), NULL, 0, &object);
+ ret = nvif_object_init(drm->channel->object, NULL, NVDRM_NVSW,
+ nouveau_abi16_swclass(drm), NULL, 0, &drm->nvsw);
if (ret == 0) {
- struct nouveau_software_chan *swch = (void *)object->parent;
+ struct nouveau_software_chan *swch;
ret = RING_SPACE(drm->channel, 2);
if (ret == 0) {
- if (device->card_type < NV_C0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
BEGIN_NV04(drm->channel, NvSubSw, 0, 1);
OUT_RING (drm->channel, NVDRM_NVSW);
} else
- if (device->card_type < NV_E0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_KEPLER) {
BEGIN_NVC0(drm->channel, FermiSw, 0, 1);
OUT_RING (drm->channel, 0x001f0000);
}
}
- swch = (void *)object->parent;
+ swch = (void *)nvkm_object(&drm->nvsw)->parent;
swch->flip = nouveau_flip_complete;
swch->flip_data = drm->channel;
}
@@ -234,24 +250,24 @@ nouveau_accel_init(struct nouveau_drm *drm)
return;
}
- if (device->card_type < NV_C0) {
- ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0,
- &drm->notify);
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
+ ret = nouveau_gpuobj_new(nvkm_object(&drm->device), NULL, 32,
+ 0, 0, &drm->notify);
if (ret) {
NV_ERROR(drm, "failed to allocate notifier, %d\n", ret);
nouveau_accel_fini(drm);
return;
}
- ret = nouveau_object_new(nv_object(drm),
- drm->channel->handle, NvNotify0,
- 0x003d, &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(drm->channel->object, NULL, NvNotify0,
+ NV_DMA_IN_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = drm->notify->addr,
.limit = drm->notify->addr + 31
- }, sizeof(struct nv_dma_class),
- &object);
+ }, sizeof(struct nv_dma_v0),
+ &drm->ntfy);
if (ret) {
nouveau_accel_fini(drm);
return;
@@ -294,7 +310,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
#ifdef CONFIG_X86
boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
#endif
- remove_conflicting_framebuffers(aper, "nouveaufb", boot);
+ if (nouveau_modeset != 2)
+ remove_conflicting_framebuffers(aper, "nouveaufb", boot);
kfree(aper);
ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
@@ -348,7 +365,6 @@ static int
nouveau_drm_load(struct drm_device *dev, unsigned long flags)
{
struct pci_dev *pdev = dev->pdev;
- struct nouveau_device *device;
struct nouveau_drm *drm;
int ret;
@@ -359,7 +375,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = drm;
drm->dev = dev;
- nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");
+ nvkm_client(&drm->client.base)->debug =
+ nouveau_dbgopt(nouveau_debug, "DRM");
INIT_LIST_HEAD(&drm->clients);
spin_lock_init(&drm->tile.lock);
@@ -370,33 +387,34 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
* (possibly) execute vbios init tables (see nouveau_agp.h)
*/
if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {
+ const u64 enables = NV_DEVICE_V0_DISABLE_IDENTIFY |
+ NV_DEVICE_V0_DISABLE_MMIO;
/* dummy device object, doesn't init anything, but allows
* agp code access to registers
*/
- ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT,
- NVDRM_DEVICE, 0x0080,
- &(struct nv_device_class) {
+ ret = nvif_device_init(&drm->client.base.base, NULL,
+ NVDRM_DEVICE, NV_DEVICE,
+ &(struct nv_device_v0) {
.device = ~0,
- .disable =
- ~(NV_DEVICE_DISABLE_MMIO |
- NV_DEVICE_DISABLE_IDENTIFY),
+ .disable = ~enables,
.debug0 = ~0,
- }, sizeof(struct nv_device_class),
- &drm->device);
+ }, sizeof(struct nv_device_v0),
+ &drm->device);
if (ret)
goto fail_device;
nouveau_agp_reset(drm);
- nouveau_object_del(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE);
+ nvif_device_fini(&drm->device);
}
- ret = nouveau_object_new(nv_object(drm), NVDRM_CLIENT, NVDRM_DEVICE,
- 0x0080, &(struct nv_device_class) {
+ ret = nvif_device_init(&drm->client.base.base, NULL, NVDRM_DEVICE,
+ NV_DEVICE,
+ &(struct nv_device_v0) {
.device = ~0,
.disable = 0,
.debug0 = 0,
- }, sizeof(struct nv_device_class),
- &drm->device);
+ }, sizeof(struct nv_device_v0),
+ &drm->device);
if (ret)
goto fail_device;
@@ -406,18 +424,19 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
* nosnoop capability. hopefully won't cause issues until a
* better fix is found - assuming there is one...
*/
- device = nv_device(drm->device);
- if (nv_device(drm->device)->chipset == 0xc1)
- nv_mask(device, 0x00088080, 0x00000800, 0x00000000);
+ if (drm->device.info.chipset == 0xc1)
+ nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000);
nouveau_vga_init(drm);
nouveau_agp_init(drm);
- if (device->card_type >= NV_50) {
- ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
- 0x1000, &drm->client.base.vm);
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
+ 0x1000, &drm->client.vm);
if (ret)
goto fail_device;
+
+ nvkm_client(&drm->client.base)->vm = drm->client.vm;
}
ret = nouveau_ttm_init(drm);
@@ -463,6 +482,7 @@ fail_ttm:
nouveau_agp_fini(drm);
nouveau_vga_fini(drm);
fail_device:
+ nvif_device_fini(&drm->device);
nouveau_cli_destroy(&drm->client);
return ret;
}
@@ -488,26 +508,37 @@ nouveau_drm_unload(struct drm_device *dev)
nouveau_agp_fini(drm);
nouveau_vga_fini(drm);
+ nvif_device_fini(&drm->device);
if (drm->hdmi_device)
pci_dev_put(drm->hdmi_device);
nouveau_cli_destroy(&drm->client);
return 0;
}
-static void
-nouveau_drm_remove(struct pci_dev *pdev)
+void
+nouveau_drm_device_remove(struct drm_device *dev)
{
- struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_client *client;
struct nouveau_object *device;
dev->irq_enabled = false;
- device = drm->client.base.device;
+ client = nvkm_client(&drm->client.base);
+ device = client->device;
drm_put_dev(dev);
nouveau_object_ref(NULL, &device);
nouveau_object_debug();
}
+EXPORT_SYMBOL(nouveau_drm_device_remove);
+
+static void
+nouveau_drm_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ nouveau_drm_device_remove(dev);
+}
static int
nouveau_do_suspend(struct drm_device *dev, bool runtime)
@@ -548,13 +579,13 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
}
list_for_each_entry(cli, &drm->clients, head) {
- ret = nouveau_client_fini(&cli->base, true);
+ ret = nvif_client_suspend(&cli->base);
if (ret)
goto fail_client;
}
NV_INFO(drm, "suspending kernel object tree...\n");
- ret = nouveau_client_fini(&drm->client.base, true);
+ ret = nvif_client_suspend(&drm->client.base);
if (ret)
goto fail_client;
@@ -563,7 +594,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
fail_client:
list_for_each_entry_continue_reverse(cli, &drm->clients, head) {
- nouveau_client_init(&cli->base);
+ nvif_client_resume(&cli->base);
}
if (drm->fence && nouveau_fence(drm)->resume)
@@ -611,7 +642,7 @@ nouveau_do_resume(struct drm_device *dev)
nouveau_agp_reset(drm);
NV_INFO(drm, "resuming kernel object tree...\n");
- nouveau_client_init(&drm->client.base);
+ nvif_client_resume(&drm->client.base);
nouveau_agp_init(drm);
NV_INFO(drm, "resuming client object trees...\n");
@@ -619,7 +650,7 @@ nouveau_do_resume(struct drm_device *dev)
nouveau_fence(drm)->resume(drm);
list_for_each_entry(cli, &drm->clients, head) {
- nouveau_client_init(&cli->base);
+ nvif_client_resume(&cli->base);
}
nouveau_run_vbios_init(dev);
@@ -715,13 +746,17 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
if (ret)
goto out_suspend;
- if (nv_device(drm->device)->card_type >= NV_50) {
- ret = nouveau_vm_new(nv_device(drm->device), 0, (1ULL << 40),
- 0x1000, &cli->base.vm);
+ cli->base.super = false;
+
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ ret = nouveau_vm_new(nvkm_device(&drm->device), 0, (1ULL << 40),
+ 0x1000, &cli->vm);
if (ret) {
nouveau_cli_destroy(cli);
goto out_suspend;
}
+
+ nvkm_client(&cli->base)->vm = cli->vm;
}
fpriv->driver_priv = cli;
@@ -779,24 +814,31 @@ nouveau_ioctls[] = {
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
};
-long nouveau_drm_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
+long
+nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct drm_file *file_priv = filp->private_data;
- struct drm_device *dev;
+ struct drm_file *filp = file->private_data;
+ struct drm_device *dev = filp->minor->dev;
long ret;
- dev = file_priv->minor->dev;
ret = pm_runtime_get_sync(dev->dev);
if (ret < 0 && ret != -EACCES)
return ret;
- ret = drm_ioctl(filp, cmd, arg);
+ switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) {
+ case DRM_NOUVEAU_NVIF:
+ ret = usif_ioctl(filp, (void __user *)arg, _IOC_SIZE(cmd));
+ break;
+ default:
+ ret = drm_ioctl(file, cmd, arg);
+ break;
+ }
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return ret;
}
+
static const struct file_operations
nouveau_driver_fops = {
.owner = THIS_MODULE,
@@ -845,6 +887,7 @@ driver = {
.gem_prime_export = drm_gem_prime_export,
.gem_prime_import = drm_gem_prime_import,
.gem_prime_pin = nouveau_gem_prime_pin,
+ .gem_prime_res_obj = nouveau_gem_prime_res_obj,
.gem_prime_unpin = nouveau_gem_prime_unpin,
.gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table,
.gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table,
@@ -920,7 +963,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
- struct nouveau_device *device = nouveau_dev(drm_dev);
+ struct nvif_device *device = &nouveau_drm(drm_dev)->device;
int ret;
if (nouveau_runtime_pm == 0)
@@ -936,7 +979,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev)
ret = nouveau_do_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);
/* do magic */
- nv_mask(device, 0x88488, (1 << 25), (1 << 25));
+ nvif_mask(device, 0x88488, (1 << 25), (1 << 25));
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
nv_debug_level(NORMAL);
@@ -1004,24 +1047,41 @@ nouveau_drm_pci_driver = {
.driver.pm = &nouveau_pm_ops,
};
-int nouveau_drm_platform_probe(struct platform_device *pdev)
+struct drm_device *
+nouveau_platform_device_create_(struct platform_device *pdev, int size,
+ void **pobject)
{
- struct nouveau_device *device;
- int ret;
+ struct drm_device *drm;
+ int err;
- ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM,
+ err = nouveau_device_create_(pdev, NOUVEAU_BUS_PLATFORM,
nouveau_platform_name(pdev),
dev_name(&pdev->dev), nouveau_config,
- nouveau_debug, &device);
-
- ret = drm_platform_init(&driver, pdev);
- if (ret) {
- nouveau_object_ref(NULL, (struct nouveau_object **)&device);
- return ret;
+ nouveau_debug, size, pobject);
+ if (err)
+ return ERR_PTR(err);
+
+ drm = drm_dev_alloc(&driver, &pdev->dev);
+ if (!drm) {
+ err = -ENOMEM;
+ goto err_free;
}
- return ret;
+ err = drm_dev_set_unique(drm, "%s", dev_name(&pdev->dev));
+ if (err < 0)
+ goto err_free;
+
+ drm->platformdev = pdev;
+ platform_set_drvdata(pdev, drm);
+
+ return drm;
+
+err_free:
+ nouveau_object_ref(NULL, (struct nouveau_object **)pobject);
+
+ return ERR_PTR(err);
}
+EXPORT_SYMBOL(nouveau_platform_device_create_);
static int __init
nouveau_drm_init(void)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index 7efbafaf7c1d..b02b02452c85 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -9,8 +9,8 @@
#define DRIVER_DATE "20120801"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 1
-#define DRIVER_PATCHLEVEL 1
+#define DRIVER_MINOR 2
+#define DRIVER_PATCHLEVEL 0
/*
* 1.1.1:
@@ -21,15 +21,17 @@
* to control registers on the MPs to enable performance counters,
* and to control the warp error enable mask (OpenGL requires out of
* bounds access to local memory to be silently ignored / return 0).
+ * 1.1.2:
+ * - fixes multiple bugs in flip completion events and timestamping
+ * 1.2.0:
+ * - object api exposed to userspace
+ * - fermi,kepler,maxwell zbc
*/
-#include <core/client.h>
-#include <core/event.h>
-
-#include <subdev/vm.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
#include <drmP.h>
-#include <drm/nouveau_drm.h>
#include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h>
@@ -38,7 +40,10 @@
#include <drm/ttm/ttm_module.h>
#include <drm/ttm/ttm_page_alloc.h>
+#include "uapi/drm/nouveau_drm.h"
+
struct nouveau_channel;
+struct platform_device;
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
@@ -50,6 +55,17 @@ struct nouveau_drm_tile {
bool used;
};
+enum nouveau_drm_object_route {
+ NVDRM_OBJECT_NVIF = 0,
+ NVDRM_OBJECT_USIF,
+ NVDRM_OBJECT_ABI16,
+};
+
+enum nouveau_drm_notify_route {
+ NVDRM_NOTIFY_NVIF = 0,
+ NVDRM_NOTIFY_USIF
+};
+
enum nouveau_drm_handle {
NVDRM_CLIENT = 0xffffffff,
NVDRM_DEVICE = 0xdddddddd,
@@ -61,10 +77,13 @@ enum nouveau_drm_handle {
};
struct nouveau_cli {
- struct nouveau_client base;
+ struct nvif_client base;
+ struct nouveau_vm *vm; /*XXX*/
struct list_head head;
struct mutex mutex;
void *abi16;
+ struct list_head objects;
+ struct list_head notifys;
};
static inline struct nouveau_cli *
@@ -73,13 +92,16 @@ nouveau_cli(struct drm_file *fpriv)
return fpriv ? fpriv->driver_priv : NULL;
}
+#include <nvif/object.h>
+#include <nvif/device.h>
+
extern int nouveau_runtime_pm;
struct nouveau_drm {
struct nouveau_cli client;
struct drm_device *dev;
- struct nouveau_object *device;
+ struct nvif_device device;
struct list_head clients;
struct {
@@ -102,6 +124,7 @@ struct nouveau_drm {
struct ttm_buffer_object *,
struct ttm_mem_reg *, struct ttm_mem_reg *);
struct nouveau_channel *chan;
+ struct nvif_object copy;
int mtrr;
} ttm;
@@ -119,6 +142,8 @@ struct nouveau_drm {
struct nouveau_channel *channel;
struct nouveau_gpuobj *notify;
struct nouveau_fbdev *fbcon;
+ struct nvif_object nvsw;
+ struct nvif_object ntfy;
/* nv10-nv40 tiling regions */
struct {
@@ -148,20 +173,25 @@ nouveau_drm(struct drm_device *dev)
return dev->dev_private;
}
-static inline struct nouveau_device *
-nouveau_dev(struct drm_device *dev)
-{
- return nv_device(nouveau_drm(dev)->device);
-}
-
int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *);
-#define NV_FATAL(cli, fmt, args...) nv_fatal((cli), fmt, ##args)
-#define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)
-#define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)
-#define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args)
-#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)
+#define nouveau_platform_device_create(p, u) \
+ nouveau_platform_device_create_(p, sizeof(**u), (void **)u)
+struct drm_device *
+nouveau_platform_device_create_(struct platform_device *pdev,
+ int size, void **pobject);
+void nouveau_drm_device_remove(struct drm_device *dev);
+
+#define NV_PRINTK(l,c,f,a...) do { \
+ struct nouveau_cli *_cli = (c); \
+ nv_##l(_cli->base.base.priv, f, ##a); \
+} while(0)
+#define NV_FATAL(drm,f,a...) NV_PRINTK(fatal, &(drm)->client, f, ##a)
+#define NV_ERROR(drm,f,a...) NV_PRINTK(error, &(drm)->client, f, ##a)
+#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
+#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
+#define NV_DEBUG(drm,f,a...) NV_PRINTK(debug, &(drm)->client, f, ##a)
extern int nouveau_modeset;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 191665ee7f52..8bdd27091db8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -51,11 +51,6 @@
#include "nouveau_crtc.h"
-#include <core/client.h>
-#include <core/device.h>
-
-#include <subdev/fb.h>
-
MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
static int nouveau_nofbaccel = 0;
module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
@@ -65,7 +60,7 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int ret;
if (info->state != FBINFO_STATE_RUNNING)
@@ -74,10 +69,10 @@ nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
ret = -ENODEV;
if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
mutex_trylock(&drm->client.mutex)) {
- if (device->card_type < NV_50)
+ if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
ret = nv04_fbcon_fillrect(info, rect);
else
- if (device->card_type < NV_C0)
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
ret = nv50_fbcon_fillrect(info, rect);
else
ret = nvc0_fbcon_fillrect(info, rect);
@@ -97,7 +92,7 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int ret;
if (info->state != FBINFO_STATE_RUNNING)
@@ -106,10 +101,10 @@ nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
ret = -ENODEV;
if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
mutex_trylock(&drm->client.mutex)) {
- if (device->card_type < NV_50)
+ if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
ret = nv04_fbcon_copyarea(info, image);
else
- if (device->card_type < NV_C0)
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
ret = nv50_fbcon_copyarea(info, image);
else
ret = nvc0_fbcon_copyarea(info, image);
@@ -129,7 +124,7 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
int ret;
if (info->state != FBINFO_STATE_RUNNING)
@@ -138,10 +133,10 @@ nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
ret = -ENODEV;
if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) &&
mutex_trylock(&drm->client.mutex)) {
- if (device->card_type < NV_50)
+ if (device->info.family < NV_DEVICE_INFO_V0_TESLA)
ret = nv04_fbcon_imageblit(info, image);
else
- if (device->card_type < NV_C0)
+ if (device->info.family < NV_DEVICE_INFO_V0_FERMI)
ret = nv50_fbcon_imageblit(info, image);
else
ret = nvc0_fbcon_imageblit(info, image);
@@ -212,6 +207,65 @@ static struct fb_ops nouveau_fbcon_sw_ops = {
.fb_debug_leave = drm_fb_helper_debug_leave,
};
+void
+nouveau_fbcon_accel_save_disable(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ if (drm->fbcon) {
+ drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
+ drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+ }
+}
+
+void
+nouveau_fbcon_accel_restore(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ if (drm->fbcon) {
+ drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
+ }
+}
+
+static void
+nouveau_fbcon_accel_fini(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_fbdev *fbcon = drm->fbcon;
+ if (fbcon && drm->channel) {
+ console_lock();
+ fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+ console_unlock();
+ nouveau_channel_idle(drm->channel);
+ nvif_object_fini(&fbcon->twod);
+ nvif_object_fini(&fbcon->blit);
+ nvif_object_fini(&fbcon->gdi);
+ nvif_object_fini(&fbcon->patt);
+ nvif_object_fini(&fbcon->rop);
+ nvif_object_fini(&fbcon->clip);
+ nvif_object_fini(&fbcon->surf2d);
+ }
+}
+
+static void
+nouveau_fbcon_accel_init(struct drm_device *dev)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_fbdev *fbcon = drm->fbcon;
+ struct fb_info *info = fbcon->helper.fbdev;
+ int ret;
+
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA)
+ ret = nv04_fbcon_accel_init(info);
+ else
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
+ ret = nv50_fbcon_accel_init(info);
+ else
+ ret = nvc0_fbcon_accel_init(info);
+
+ if (ret == 0)
+ info->fbops = &nouveau_fbcon_ops;
+}
+
static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno)
{
@@ -257,7 +311,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper;
struct drm_device *dev = fbcon->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct fb_info *info;
struct drm_framebuffer *fb;
struct nouveau_framebuffer *nouveau_fb;
@@ -299,8 +353,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
}
chan = nouveau_nofbaccel ? NULL : drm->channel;
- if (chan && device->card_type >= NV_50) {
- ret = nouveau_bo_vma_add(nvbo, nv_client(chan->cli)->vm,
+ if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ ret = nouveau_bo_vma_add(nvbo, drm->client.vm,
&fbcon->nouveau_fb.vma);
if (ret) {
NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
@@ -357,20 +411,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
mutex_unlock(&dev->struct_mutex);
- if (chan) {
- ret = -ENODEV;
- if (device->card_type < NV_50)
- ret = nv04_fbcon_accel_init(info);
- else
- if (device->card_type < NV_C0)
- ret = nv50_fbcon_accel_init(info);
- else
- ret = nvc0_fbcon_accel_init(info);
-
- if (ret == 0)
- info->fbops = &nouveau_fbcon_ops;
- }
-
+ if (chan)
+ nouveau_fbcon_accel_init(dev);
nouveau_fbcon_zfill(dev, fbcon);
/* To allow resizeing without swapping buffers */
@@ -438,7 +480,7 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info)
info->flags |= FBINFO_HWACCEL_DISABLED;
}
-static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
+static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
.gamma_set = nouveau_fbcon_gamma_set,
.gamma_get = nouveau_fbcon_gamma_get,
.fb_probe = nouveau_fbcon_create,
@@ -449,7 +491,6 @@ int
nouveau_fbcon_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
struct nouveau_fbdev *fbcon;
int preferred_bpp;
int ret;
@@ -464,7 +505,8 @@ nouveau_fbcon_init(struct drm_device *dev)
fbcon->dev = dev;
drm->fbcon = fbcon;
- fbcon->helper.funcs = &nouveau_fbcon_helper_funcs;
+
+ drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
ret = drm_fb_helper_init(dev, &fbcon->helper,
dev->mode_config.num_crtc, 4);
@@ -475,10 +517,10 @@ nouveau_fbcon_init(struct drm_device *dev)
drm_fb_helper_single_add_all_connectors(&fbcon->helper);
- if (pfb->ram->size <= 32 * 1024 * 1024)
+ if (drm->device.info.ram_size <= 32 * 1024 * 1024)
preferred_bpp = 8;
else
- if (pfb->ram->size <= 64 * 1024 * 1024)
+ if (drm->device.info.ram_size <= 64 * 1024 * 1024)
preferred_bpp = 16;
else
preferred_bpp = 32;
@@ -498,43 +540,25 @@ nouveau_fbcon_fini(struct drm_device *dev)
if (!drm->fbcon)
return;
+ nouveau_fbcon_accel_fini(dev);
nouveau_fbcon_destroy(dev, drm->fbcon);
kfree(drm->fbcon);
drm->fbcon = NULL;
}
void
-nouveau_fbcon_save_disable_accel(struct drm_device *dev)
-{
- struct nouveau_drm *drm = nouveau_drm(dev);
- if (drm->fbcon) {
- drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
- drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
- }
-}
-
-void
-nouveau_fbcon_restore_accel(struct drm_device *dev)
-{
- struct nouveau_drm *drm = nouveau_drm(dev);
- if (drm->fbcon) {
- drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
- }
-}
-
-void
nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
{
struct nouveau_drm *drm = nouveau_drm(dev);
if (drm->fbcon) {
console_lock();
- if (state == 1)
- nouveau_fbcon_save_disable_accel(dev);
- fb_set_suspend(drm->fbcon->helper.fbdev, state);
if (state == 0) {
- nouveau_fbcon_restore_accel(dev);
+ nouveau_fbcon_accel_restore(dev);
nouveau_fbcon_zfill(dev, drm->fbcon);
}
+ fb_set_suspend(drm->fbcon->helper.fbdev, state);
+ if (state == 1)
+ nouveau_fbcon_accel_save_disable(dev);
console_unlock();
}
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index fcff797d2084..34658cfa8f5d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -37,6 +37,13 @@ struct nouveau_fbdev {
struct list_head fbdev_list;
struct drm_device *dev;
unsigned int saved_flags;
+ struct nvif_object surf2d;
+ struct nvif_object clip;
+ struct nvif_object rop;
+ struct nvif_object patt;
+ struct nvif_object gdi;
+ struct nvif_object blit;
+ struct nvif_object twod;
};
void nouveau_fbcon_restore(void);
@@ -61,8 +68,8 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info);
int nouveau_fbcon_init(struct drm_device *dev);
void nouveau_fbcon_fini(struct drm_device *dev);
void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
-void nouveau_fbcon_save_disable_accel(struct drm_device *dev);
-void nouveau_fbcon_restore_accel(struct drm_device *dev);
+void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
+void nouveau_fbcon_accel_restore(struct drm_device *dev);
void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
#endif /* __NV50_FBCON_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index ab5ea3b0d666..0a93114158cd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -29,12 +29,13 @@
#include <linux/ktime.h>
#include <linux/hrtimer.h>
+#include <nvif/notify.h>
+#include <nvif/event.h>
+
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
-#include <engine/fifo.h>
-
struct fence_work {
struct work_struct base;
struct list_head head;
@@ -165,12 +166,18 @@ nouveau_fence_done(struct nouveau_fence *fence)
return !fence->channel;
}
+struct nouveau_fence_wait {
+ struct nouveau_fence_priv *priv;
+ struct nvif_notify notify;
+};
+
static int
-nouveau_fence_wait_uevent_handler(void *data, u32 type, int index)
+nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
{
- struct nouveau_fence_priv *priv = data;
- wake_up_all(&priv->waiting);
- return NVKM_EVENT_KEEP;
+ struct nouveau_fence_wait *wait =
+ container_of(notify, typeof(*wait), notify);
+ wake_up_all(&wait->priv->waiting);
+ return NVIF_NOTIFY_KEEP;
}
static int
@@ -178,18 +185,22 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
{
struct nouveau_channel *chan = fence->channel;
- struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);
struct nouveau_fence_priv *priv = chan->drm->fence;
- struct nouveau_eventh *handler;
+ struct nouveau_fence_wait wait = { .priv = priv };
int ret = 0;
- ret = nouveau_event_new(pfifo->uevent, 1, 0,
- nouveau_fence_wait_uevent_handler,
- priv, &handler);
+ ret = nvif_notify_init(chan->object, NULL,
+ nouveau_fence_wait_uevent_handler, false,
+ G82_CHANNEL_DMA_V0_NTFY_UEVENT,
+ &(struct nvif_notify_uevent_req) {
+ },
+ sizeof(struct nvif_notify_uevent_req),
+ sizeof(struct nvif_notify_uevent_rep),
+ &wait.notify);
if (ret)
return ret;
- nouveau_event_get(handler);
+ nvif_notify_get(&wait.notify);
if (fence->timeout) {
unsigned long timeout = fence->timeout - jiffies;
@@ -221,7 +232,7 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)
}
}
- nouveau_event_ref(NULL, &handler);
+ nvif_notify_fini(&wait.notify);
if (unlikely(ret < 0))
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index c90c0dc0afe8..292a677bfed4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -24,8 +24,6 @@
*
*/
-#include <subdev/fb.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
@@ -58,14 +56,14 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
struct nouveau_vma *vma;
int ret;
- if (!cli->base.vm)
+ if (!cli->vm)
return 0;
- ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
if (ret)
return ret;
- vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+ vma = nouveau_bo_vma_find(nvbo, cli->vm);
if (!vma) {
vma = kzalloc(sizeof(*vma), GFP_KERNEL);
if (!vma) {
@@ -73,7 +71,7 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
goto out;
}
- ret = nouveau_bo_vma_add(nvbo, cli->base.vm, vma);
+ ret = nouveau_bo_vma_add(nvbo, cli->vm, vma);
if (ret) {
kfree(vma);
goto out;
@@ -129,14 +127,14 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
struct nouveau_vma *vma;
int ret;
- if (!cli->base.vm)
+ if (!cli->vm)
return;
- ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
if (ret)
return;
- vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+ vma = nouveau_bo_vma_find(nvbo, cli->vm);
if (vma) {
if (--vma->refcount == 0)
nouveau_gem_object_unmap(nvbo, vma);
@@ -173,7 +171,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
*/
nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
NOUVEAU_GEM_DOMAIN_GART;
- if (nv_device(drm->device)->card_type >= NV_50)
+ if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
nvbo->valid_domains &= domain;
/* Initialize the embedded gem-object. We return a single gem-reference
@@ -202,8 +200,8 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
rep->offset = nvbo->bo.offset;
- if (cli->base.vm) {
- vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
+ if (cli->vm) {
+ vma = nouveau_bo_vma_find(nvbo, cli->vm);
if (!vma)
return -EINVAL;
@@ -223,13 +221,13 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_cli *cli = nouveau_cli(file_priv);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
struct drm_nouveau_gem_new *req = data;
struct nouveau_bo *nvbo = NULL;
int ret = 0;
if (!pfb->memtype_valid(pfb, req->info.tile_flags)) {
- NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
+ NV_PRINTK(error, cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
return -EINVAL;
}
@@ -350,7 +348,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
ww_acquire_init(&op->ticket, &reservation_ww_class);
retry:
if (++trycnt > 100000) {
- NV_ERROR(cli, "%s failed and gave up.\n", __func__);
+ NV_PRINTK(error, cli, "%s failed and gave up.\n", __func__);
return -EINVAL;
}
@@ -361,7 +359,7 @@ retry:
gem = drm_gem_object_lookup(dev, file_priv, b->handle);
if (!gem) {
- NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
+ NV_PRINTK(error, cli, "Unknown handle 0x%08x\n", b->handle);
ww_acquire_done(&op->ticket);
validate_fini(op, NULL);
return -ENOENT;
@@ -374,7 +372,7 @@ retry:
}
if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
- NV_ERROR(cli, "multiple instances of buffer %d on "
+ NV_PRINTK(error, cli, "multiple instances of buffer %d on "
"validation list\n", b->handle);
drm_gem_object_unreference_unlocked(gem);
ww_acquire_done(&op->ticket);
@@ -396,7 +394,7 @@ retry:
ww_acquire_fini(&op->ticket);
drm_gem_object_unreference_unlocked(gem);
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "fail reserve\n");
+ NV_PRINTK(error, cli, "fail reserve\n");
return ret;
}
}
@@ -414,7 +412,7 @@ retry:
if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
list_add_tail(&nvbo->entry, &op->gart_list);
else {
- NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
+ NV_PRINTK(error, cli, "invalid valid domains: 0x%08x\n",
b->valid_domains);
list_add_tail(&nvbo->entry, &op->both_list);
ww_acquire_done(&op->ticket);
@@ -465,24 +463,24 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
b->write_domains,
b->valid_domains);
if (unlikely(ret)) {
- NV_ERROR(cli, "fail set_domain\n");
+ NV_PRINTK(error, cli, "fail set_domain\n");
return ret;
}
ret = nouveau_bo_validate(nvbo, true, false);
if (unlikely(ret)) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "fail ttm_validate\n");
+ NV_PRINTK(error, cli, "fail ttm_validate\n");
return ret;
}
ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
- NV_ERROR(cli, "fail post-validate sync\n");
+ NV_PRINTK(error, cli, "fail post-validate sync\n");
return ret;
}
- if (nv_device(drm->device)->card_type < NV_50) {
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
if (nvbo->bo.offset == b->presumed.offset &&
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
@@ -527,14 +525,14 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
if (unlikely(ret)) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "validate_init\n");
+ NV_PRINTK(error, cli, "validate_init\n");
return ret;
}
ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers);
if (unlikely(ret < 0)) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "validate vram_list\n");
+ NV_PRINTK(error, cli, "validate vram_list\n");
validate_fini(op, NULL);
return ret;
}
@@ -543,7 +541,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers);
if (unlikely(ret < 0)) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "validate gart_list\n");
+ NV_PRINTK(error, cli, "validate gart_list\n");
validate_fini(op, NULL);
return ret;
}
@@ -552,7 +550,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers);
if (unlikely(ret < 0)) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "validate both_list\n");
+ NV_PRINTK(error, cli, "validate both_list\n");
validate_fini(op, NULL);
return ret;
}
@@ -613,7 +611,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
uint32_t data;
if (unlikely(r->bo_index > req->nr_buffers)) {
- NV_ERROR(cli, "reloc bo index invalid\n");
+ NV_PRINTK(error, cli, "reloc bo index invalid\n");
ret = -EINVAL;
break;
}
@@ -623,7 +621,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
continue;
if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
- NV_ERROR(cli, "reloc container bo index invalid\n");
+ NV_PRINTK(error, cli, "reloc container bo index invalid\n");
ret = -EINVAL;
break;
}
@@ -631,7 +629,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
if (unlikely(r->reloc_bo_offset + 4 >
nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
- NV_ERROR(cli, "reloc outside of bo\n");
+ NV_PRINTK(error, cli, "reloc outside of bo\n");
ret = -EINVAL;
break;
}
@@ -640,7 +638,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
&nvbo->kmap);
if (ret) {
- NV_ERROR(cli, "failed kmap for reloc\n");
+ NV_PRINTK(error, cli, "failed kmap for reloc\n");
break;
}
nvbo->validate_mapped = true;
@@ -665,7 +663,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
spin_unlock(&nvbo->bo.bdev->fence_lock);
if (ret) {
- NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret);
+ NV_PRINTK(error, cli, "reloc wait_idle failed: %d\n", ret);
break;
}
@@ -696,7 +694,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
return -ENOMEM;
list_for_each_entry(temp, &abi16->channels, head) {
- if (temp->chan->handle == (NVDRM_CHAN | req->channel)) {
+ if (temp->chan->object->handle == (NVDRM_CHAN | req->channel)) {
chan = temp->chan;
break;
}
@@ -711,19 +709,19 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
goto out_next;
if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
- NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n",
+ NV_PRINTK(error, cli, "pushbuf push count exceeds limit: %d max %d\n",
req->nr_push, NOUVEAU_GEM_MAX_PUSH);
return nouveau_abi16_put(abi16, -EINVAL);
}
if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
- NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n",
+ NV_PRINTK(error, cli, "pushbuf bo count exceeds limit: %d max %d\n",
req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
return nouveau_abi16_put(abi16, -EINVAL);
}
if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
- NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n",
+ NV_PRINTK(error, cli, "pushbuf reloc count exceeds limit: %d max %d\n",
req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
return nouveau_abi16_put(abi16, -EINVAL);
}
@@ -741,7 +739,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
/* Ensure all push buffers are on validate list */
for (i = 0; i < req->nr_push; i++) {
if (push[i].bo_index >= req->nr_buffers) {
- NV_ERROR(cli, "push %d buffer not in list\n", i);
+ NV_PRINTK(error, cli, "push %d buffer not in list\n", i);
ret = -EINVAL;
goto out_prevalid;
}
@@ -752,7 +750,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
req->nr_buffers, &op, &do_reloc);
if (ret) {
if (ret != -ERESTARTSYS)
- NV_ERROR(cli, "validate: %d\n", ret);
+ NV_PRINTK(error, cli, "validate: %d\n", ret);
goto out_prevalid;
}
@@ -760,7 +758,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
if (do_reloc) {
ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo);
if (ret) {
- NV_ERROR(cli, "reloc apply: %d\n", ret);
+ NV_PRINTK(error, cli, "reloc apply: %d\n", ret);
goto out;
}
}
@@ -768,7 +766,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
if (chan->dma.ib_max) {
ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
if (ret) {
- NV_ERROR(cli, "nv50cal_space: %d\n", ret);
+ NV_PRINTK(error, cli, "nv50cal_space: %d\n", ret);
goto out;
}
@@ -780,10 +778,10 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
push[i].length);
}
} else
- if (nv_device(drm->device)->chipset >= 0x25) {
+ if (drm->device.info.chipset >= 0x25) {
ret = RING_SPACE(chan, req->nr_push * 2);
if (ret) {
- NV_ERROR(cli, "cal_space: %d\n", ret);
+ NV_PRINTK(error, cli, "cal_space: %d\n", ret);
goto out;
}
@@ -797,7 +795,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
} else {
ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
if (ret) {
- NV_ERROR(cli, "jmp_space: %d\n", ret);
+ NV_PRINTK(error, cli, "jmp_space: %d\n", ret);
goto out;
}
@@ -835,7 +833,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
ret = nouveau_fence_new(chan, false, &fence);
if (ret) {
- NV_ERROR(cli, "error fencing pushbuf: %d\n", ret);
+ NV_PRINTK(error, cli, "error fencing pushbuf: %d\n", ret);
WIND_RING(chan);
goto out;
}
@@ -853,7 +851,7 @@ out_next:
req->suffix0 = 0x00000000;
req->suffix1 = 0x00000000;
} else
- if (nv_device(drm->device)->chipset >= 0x25) {
+ if (drm->device.info.chipset >= 0x25) {
req->suffix0 = 0x00020000;
req->suffix1 = 0x00000000;
} else {
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h
index 7caca057bc38..ddab762d81fe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.h
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.h
@@ -35,6 +35,7 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
struct drm_file *);
extern int nouveau_gem_prime_pin(struct drm_gem_object *);
+struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *);
extern void nouveau_gem_prime_unpin(struct drm_gem_object *);
extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *);
extern struct drm_gem_object *nouveau_gem_prime_import_sg_table(
diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
index 19fd767bab10..afb36d66e78d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c
@@ -34,17 +34,13 @@
#include "nouveau_drm.h"
#include "nouveau_hwmon.h"
-#include <subdev/gpio.h>
-#include <subdev/timer.h>
-#include <subdev/therm.h>
-
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
static ssize_t
nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int temp = therm->temp_get(therm);
if (temp < 0)
@@ -70,7 +66,7 @@ nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST) * 1000);
@@ -82,7 +78,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -103,7 +99,7 @@ nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
@@ -115,7 +111,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -135,7 +131,7 @@ nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK) * 1000);
@@ -146,7 +142,7 @@ nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -166,7 +162,7 @@ nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000);
@@ -177,7 +173,7 @@ nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -198,7 +194,7 @@ nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL) * 1000);
@@ -210,7 +206,7 @@ nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -231,7 +227,7 @@ nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST) * 1000);
@@ -244,7 +240,7 @@ nouveau_hwmon_set_critical_temp_hyst(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -264,7 +260,7 @@ nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN) * 1000);
@@ -276,7 +272,7 @@ nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -297,7 +293,7 @@ nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n",
therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
@@ -310,7 +306,7 @@ nouveau_hwmon_set_emergency_temp_hyst(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
if (kstrtol(buf, 10, &value) == -EINVAL)
@@ -350,7 +346,7 @@ nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm));
}
@@ -363,7 +359,7 @@ nouveau_hwmon_get_pwm1_enable(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int ret;
ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MODE);
@@ -379,7 +375,7 @@ nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
int ret;
@@ -402,7 +398,7 @@ nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int ret;
ret = therm->fan_get(therm);
@@ -418,7 +414,7 @@ nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int ret = -ENODEV;
long value;
@@ -442,7 +438,7 @@ nouveau_hwmon_get_pwm1_min(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int ret;
ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MIN_DUTY);
@@ -458,7 +454,7 @@ nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
int ret;
@@ -482,7 +478,7 @@ nouveau_hwmon_get_pwm1_max(struct device *d,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
int ret;
ret = therm->attr_get(therm, NOUVEAU_THERM_ATTR_FAN_MAX_DUTY);
@@ -498,7 +494,7 @@ nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
{
struct drm_device *dev = dev_get_drvdata(d);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
long value;
int ret;
@@ -565,7 +561,7 @@ nouveau_hwmon_init(struct drm_device *dev)
{
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_therm *therm = nouveau_therm(drm->device);
+ struct nouveau_therm *therm = nvkm_therm(&drm->device);
struct nouveau_hwmon *hwmon;
struct device *hwmon_dev;
int ret = 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c
new file mode 100644
index 000000000000..47ca88623753
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+/*******************************************************************************
+ * NVIF client driver - NVKM directly linked
+ ******************************************************************************/
+
+#include <core/client.h>
+#include <core/notify.h>
+#include <core/ioctl.h>
+
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/event.h>
+#include <nvif/ioctl.h>
+
+#include "nouveau_drm.h"
+#include "nouveau_usif.h"
+
+static void
+nvkm_client_unmap(void *priv, void *ptr, u32 size)
+{
+ iounmap(ptr);
+}
+
+static void *
+nvkm_client_map(void *priv, u64 handle, u32 size)
+{
+ return ioremap(handle, size);
+}
+
+static int
+nvkm_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)
+{
+ return nvkm_ioctl(priv, super, data, size, hack);
+}
+
+static int
+nvkm_client_resume(void *priv)
+{
+ return nouveau_client_init(priv);
+}
+
+static int
+nvkm_client_suspend(void *priv)
+{
+ return nouveau_client_fini(priv, true);
+}
+
+static void
+nvkm_client_fini(void *priv)
+{
+ struct nouveau_object *client = priv;
+ nouveau_client_fini(nv_client(client), false);
+ atomic_set(&client->refcount, 1);
+ nouveau_object_ref(NULL, &client);
+}
+
+static int
+nvkm_client_ntfy(const void *header, u32 length, const void *data, u32 size)
+{
+ const union {
+ struct nvif_notify_req_v0 v0;
+ } *args = header;
+ u8 route;
+
+ if (length == sizeof(args->v0) && args->v0.version == 0) {
+ route = args->v0.route;
+ } else {
+ WARN_ON(1);
+ return NVKM_NOTIFY_DROP;
+ }
+
+ switch (route) {
+ case NVDRM_NOTIFY_NVIF:
+ return nvif_notify(header, length, data, size);
+ case NVDRM_NOTIFY_USIF:
+ return usif_notify(header, length, data, size);
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return NVKM_NOTIFY_DROP;
+}
+
+static int
+nvkm_client_init(const char *name, u64 device, const char *cfg,
+ const char *dbg, void **ppriv)
+{
+ struct nouveau_client *client;
+ int ret;
+
+ ret = nouveau_client_create(name, device, cfg, dbg, &client);
+ *ppriv = client;
+ if (ret)
+ return ret;
+
+ client->ntfy = nvkm_client_ntfy;
+ return 0;
+}
+
+const struct nvif_driver
+nvif_driver_nvkm = {
+ .name = "nvkm",
+ .init = nvkm_client_init,
+ .fini = nvkm_client_fini,
+ .suspend = nvkm_client_suspend,
+ .resume = nvkm_client_resume,
+ .ioctl = nvkm_client_ioctl,
+ .map = nvkm_client_map,
+ .unmap = nvkm_client_unmap,
+ .keep = false,
+};
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
new file mode 100644
index 000000000000..246a824c16ca
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#include <linux/regulator/consumer.h>
+#include <soc/tegra/pmc.h>
+
+#include "nouveau_drm.h"
+#include "nouveau_platform.h"
+
+static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu)
+{
+ int err;
+
+ err = regulator_enable(gpu->vdd);
+ if (err)
+ goto err_power;
+
+ err = clk_prepare_enable(gpu->clk);
+ if (err)
+ goto err_clk;
+ err = clk_prepare_enable(gpu->clk_pwr);
+ if (err)
+ goto err_clk_pwr;
+ clk_set_rate(gpu->clk_pwr, 204000000);
+ udelay(10);
+
+ reset_control_assert(gpu->rst);
+ udelay(10);
+
+ err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
+ if (err)
+ goto err_clamp;
+ udelay(10);
+
+ reset_control_deassert(gpu->rst);
+ udelay(10);
+
+ return 0;
+
+err_clamp:
+ clk_disable_unprepare(gpu->clk_pwr);
+err_clk_pwr:
+ clk_disable_unprepare(gpu->clk);
+err_clk:
+ regulator_disable(gpu->vdd);
+err_power:
+ return err;
+}
+
+static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
+{
+ int err;
+
+ reset_control_assert(gpu->rst);
+ udelay(10);
+
+ clk_disable_unprepare(gpu->clk_pwr);
+ clk_disable_unprepare(gpu->clk);
+ udelay(10);
+
+ err = regulator_disable(gpu->vdd);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int nouveau_platform_probe(struct platform_device *pdev)
+{
+ struct nouveau_platform_gpu *gpu;
+ struct nouveau_platform_device *device;
+ struct drm_device *drm;
+ int err;
+
+ gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL);
+ if (!gpu)
+ return -ENOMEM;
+
+ gpu->vdd = devm_regulator_get(&pdev->dev, "vdd");
+ if (IS_ERR(gpu->vdd))
+ return PTR_ERR(gpu->vdd);
+
+ gpu->rst = devm_reset_control_get(&pdev->dev, "gpu");
+ if (IS_ERR(gpu->rst))
+ return PTR_ERR(gpu->rst);
+
+ gpu->clk = devm_clk_get(&pdev->dev, "gpu");
+ if (IS_ERR(gpu->clk))
+ return PTR_ERR(gpu->clk);
+
+ gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
+ if (IS_ERR(gpu->clk_pwr))
+ return PTR_ERR(gpu->clk_pwr);
+
+ err = nouveau_platform_power_up(gpu);
+ if (err)
+ return err;
+
+ drm = nouveau_platform_device_create(pdev, &device);
+ if (IS_ERR(drm)) {
+ err = PTR_ERR(drm);
+ goto power_down;
+ }
+
+ device->gpu = gpu;
+
+ err = drm_dev_register(drm, 0);
+ if (err < 0)
+ goto err_unref;
+
+ return 0;
+
+err_unref:
+ drm_dev_unref(drm);
+
+ return 0;
+
+power_down:
+ nouveau_platform_power_down(gpu);
+
+ return err;
+}
+
+static int nouveau_platform_remove(struct platform_device *pdev)
+{
+ struct drm_device *drm_dev = platform_get_drvdata(pdev);
+ struct nouveau_drm *drm = nouveau_drm(drm_dev);
+ struct nouveau_device *device = nvkm_device(&drm->device);
+ struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
+
+ nouveau_drm_device_remove(drm_dev);
+
+ return nouveau_platform_power_down(gpu);
+}
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id nouveau_platform_match[] = {
+ { .compatible = "nvidia,gk20a" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, nouveau_platform_match);
+#endif
+
+struct platform_driver nouveau_platform_driver = {
+ .driver = {
+ .name = "nouveau",
+ .of_match_table = of_match_ptr(nouveau_platform_match),
+ },
+ .probe = nouveau_platform_probe,
+ .remove = nouveau_platform_remove,
+};
+
+module_platform_driver(nouveau_platform_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.h b/drivers/gpu/drm/nouveau/nouveau_platform.h
new file mode 100644
index 000000000000..91f66504900e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_PLATFORM_H__
+#define __NOUVEAU_PLATFORM_H__
+
+#include "core/device.h"
+
+struct reset_control;
+struct clk;
+struct regulator;
+
+struct nouveau_platform_gpu {
+ struct reset_control *rst;
+ struct clk *clk;
+ struct clk *clk_pwr;
+
+ struct regulator *vdd;
+};
+
+struct nouveau_platform_device {
+ struct nouveau_device device;
+
+ struct nouveau_platform_gpu *gpu;
+};
+
+#define nv_device_to_platform(d) \
+ container_of(d, struct nouveau_platform_device, device)
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c
index 51a2cb102b44..1f51008e4d26 100644
--- a/drivers/gpu/drm/nouveau/nouveau_prime.c
+++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
@@ -102,3 +102,10 @@ void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
nouveau_bo_unpin(nvbo);
}
+
+struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+ struct nouveau_bo *nvbo = nouveau_gem_object(obj);
+
+ return nvbo->bo.resv;
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index a4d22e5eb176..01707e7deaf5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -1,8 +1,6 @@
#include <linux/pagemap.h>
#include <linux/slab.h>
-#include <subdev/fb.h>
-
#include "nouveau_drm.h"
#include "nouveau_ttm.h"
@@ -104,7 +102,7 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
return NULL;
nvbe->dev = drm->dev;
- if (nv_device(drm->device)->card_type < NV_50)
+ if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA)
nvbe->ttm.ttm.func = &nv04_sgdma_backend;
else
nvbe->ttm.ttm.func = &nv50_sgdma_backend;
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
index 75dda2b07176..3c6962d15b26 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
@@ -22,10 +22,15 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
+#include <nvif/os.h>
+#include <nvif/class.h>
+#include <nvif/ioctl.h>
+
#include "nouveau_sysfs.h"
-#include <core/object.h>
-#include <core/class.h>
+MODULE_PARM_DESC(pstate, "enable sysfs pstate file, which will be moved in the future");
+static int nouveau_pstate;
+module_param_named(pstate, nouveau_pstate, int, 0400);
static inline struct drm_device *
drm_device(struct device *d)
@@ -43,38 +48,42 @@ static ssize_t
nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
{
struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
- struct nv_control_pstate_info info;
+ struct nvif_control_pstate_info_v0 info = {};
size_t cnt = PAGE_SIZE;
char *buf = b;
int ret, i;
- ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_INFO, &info, sizeof(info));
+ ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_INFO,
+ &info, sizeof(info));
if (ret)
return ret;
for (i = 0; i < info.count + 1; i++) {
const s32 state = i < info.count ? i :
- NV_CONTROL_PSTATE_ATTR_STATE_CURRENT;
- struct nv_control_pstate_attr attr = {
+ NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT;
+ struct nvif_control_pstate_attr_v0 attr = {
.state = state,
.index = 0,
};
- ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR,
- &attr, sizeof(attr));
+ ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_ATTR,
+ &attr, sizeof(attr));
if (ret)
return ret;
if (i < info.count)
snappendf(buf, cnt, "%02x:", attr.state);
else
- snappendf(buf, cnt, "--:");
+ snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" :
+ info.pwrsrc == 1 ? "AC" :
+ "--");
attr.index = 0;
do {
attr.state = state;
- ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR,
- &attr, sizeof(attr));
+ ret = nvif_mthd(&sysfs->ctrl,
+ NVIF_CONTROL_PSTATE_ATTR,
+ &attr, sizeof(attr));
if (ret)
return ret;
@@ -84,9 +93,20 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
snappendf(buf, cnt, " %s", attr.unit);
} while (attr.index);
- if ((state >= 0 && info.pstate == state) ||
- (state < 0 && info.ustate < 0))
- snappendf(buf, cnt, " *");
+ if (state >= 0) {
+ if (info.ustate_ac == state)
+ snappendf(buf, cnt, " AC");
+ if (info.ustate_dc == state)
+ snappendf(buf, cnt, " DC");
+ if (info.pstate == state)
+ snappendf(buf, cnt, " *");
+ } else {
+ if (info.ustate_ac < -1)
+ snappendf(buf, cnt, " AC");
+ if (info.ustate_dc < -1)
+ snappendf(buf, cnt, " DC");
+ }
+
snappendf(buf, cnt, "\n");
}
@@ -98,26 +118,36 @@ nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a,
const char *buf, size_t count)
{
struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
- struct nv_control_pstate_user args;
+ struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL };
long value, ret;
char *tmp;
if ((tmp = strchr(buf, '\n')))
*tmp = '\0';
+ if (!strncasecmp(buf, "dc:", 3)) {
+ args.pwrsrc = 0;
+ buf += 3;
+ } else
+ if (!strncasecmp(buf, "ac:", 3)) {
+ args.pwrsrc = 1;
+ buf += 3;
+ }
+
if (!strcasecmp(buf, "none"))
- args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
+ args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN;
else
if (!strcasecmp(buf, "auto"))
- args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
+ args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON;
else {
ret = kstrtol(buf, 16, &value);
if (ret)
return ret;
- args.state = value;
+ args.ustate = value;
}
- ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args));
+ ret = nvif_mthd(&sysfs->ctrl, NVIF_CONTROL_PSTATE_USER,
+ &args, sizeof(args));
if (ret < 0)
return ret;
@@ -132,11 +162,11 @@ nouveau_sysfs_fini(struct drm_device *dev)
{
struct nouveau_sysfs *sysfs = nouveau_sysfs(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
- if (sysfs->ctrl) {
- device_remove_file(nv_device_base(device), &dev_attr_pstate);
- nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL);
+ if (sysfs && sysfs->ctrl.priv) {
+ device_remove_file(nv_device_base(nvkm_device(device)), &dev_attr_pstate);
+ nvif_object_fini(&sysfs->ctrl);
}
drm->sysfs = NULL;
@@ -147,18 +177,22 @@ int
nouveau_sysfs_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_device *device = nv_device(drm->device);
+ struct nvif_device *device = &drm->device;
struct nouveau_sysfs *sysfs;
int ret;
+ if (!nouveau_pstate)
+ return 0;
+
sysfs = drm->sysfs = kzalloc(sizeof(*sysfs), GFP_KERNEL);
if (!sysfs)
return -ENOMEM;
- ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL,
- NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl);
+ ret = nvif_object_init(nvif_object(device), NULL, NVDRM_CONTROL,
+ NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0,
+ &sysfs->ctrl);
if (ret == 0)
- device_create_file(nv_device_base(device), &dev_attr_pstate);
+ device_create_file(nv_device_base(nvkm_device(device)), &dev_attr_pstate);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.h b/drivers/gpu/drm/nouveau/nouveau_sysfs.h
index 74b47f1e01ed..f973378160f8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.h
+++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.h
@@ -4,7 +4,7 @@
#include "nouveau_drm.h"
struct nouveau_sysfs {
- struct nouveau_object *ctrl;
+ struct nvif_object ctrl;
};
static inline struct nouveau_sysfs *
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index ab0228f640a5..53874b76b031 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -24,10 +24,6 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <subdev/fb.h>
-#include <subdev/vm.h>
-#include <subdev/instmem.h>
-
#include "nouveau_drm.h"
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
@@ -36,7 +32,7 @@ static int
nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
{
struct nouveau_drm *drm = nouveau_bdev(man->bdev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
man->priv = pfb;
return 0;
}
@@ -67,7 +63,7 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
struct ttm_mem_reg *mem)
{
struct nouveau_drm *drm = nouveau_bdev(man->bdev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
nouveau_mem_node_cleanup(mem->mm_node);
pfb->ram->put(pfb, (struct nouveau_mem **)&mem->mm_node);
}
@@ -76,10 +72,11 @@ static int
nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
+ uint32_t flags,
struct ttm_mem_reg *mem)
{
struct nouveau_drm *drm = nouveau_bdev(man->bdev);
- struct nouveau_fb *pfb = nouveau_fb(drm->device);
+ struct nouveau_fb *pfb = nvkm_fb(&drm->device);
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_mem *node;
u32 size_nc = 0;
@@ -162,6 +159,7 @@ static int
nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
+ uint32_t flags,
struct ttm_mem_reg *mem)
{
struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
@@ -174,14 +172,13 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
node->page_shift = 12;
- switch (nv_device(drm->device)->card_type) {
- case NV_50:
- if (nv_device(drm->device)->chipset != 0x50)
+ switch (drm->device.info.family) {
+ case NV_DEVICE_INFO_V0_TESLA:
+ if (drm->device.info.chipset != 0x50)
node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
break;
- case NV_C0:
- case NV_D0:
- case NV_E0:
+ case NV_DEVICE_INFO_V0_FERMI:
+ case NV_DEVICE_INFO_V0_KEPLER:
node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
break;
default:
@@ -206,12 +203,13 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = {
nouveau_gart_manager_debug
};
+/*XXX*/
#include <core/subdev/vm/nv04.h>
static int
nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
{
struct nouveau_drm *drm = nouveau_bdev(man->bdev);
- struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device);
+ struct nouveau_vmmgr *vmm = nvkm_vmmgr(&drm->device);
struct nv04_vmmgr_priv *priv = (void *)vmm;
struct nouveau_vm *vm = NULL;
nouveau_vm_ref(priv->vm, &vm, NULL);
@@ -242,6 +240,7 @@ static int
nv04_gart_manager_new(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
+ uint32_t flags,
struct ttm_mem_reg *mem)
{
struct nouveau_mem *node;
@@ -354,12 +353,11 @@ int
nouveau_ttm_init(struct nouveau_drm *drm)
{
struct drm_device *dev = drm->dev;
- struct nouveau_device *device = nv_device(drm->device);
u32 bits;
int ret;
- bits = nouveau_vmmgr(drm->device)->dma_bits;
- if (nv_device_is_pci(device)) {
+ bits = nvkm_vmmgr(&drm->device)->dma_bits;
+ if (nv_device_is_pci(nvkm_device(&drm->device))) {
if (drm->agp.stat == ENABLED ||
!pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits)))
bits = 32;
@@ -391,8 +389,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
}
/* VRAM init */
- drm->gem.vram_available = nouveau_fb(drm->device)->ram->size;
- drm->gem.vram_available -= nouveau_instmem(drm->device)->reserved;
+ drm->gem.vram_available = drm->device.info.ram_user;
ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM,
drm->gem.vram_available >> PAGE_SHIFT);
@@ -401,12 +398,12 @@ nouveau_ttm_init(struct nouveau_drm *drm)
return ret;
}
- drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1),
- nv_device_resource_len(device, 1));
+ drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(nvkm_device(&drm->device), 1),
+ nv_device_resource_len(nvkm_device(&drm->device), 1));
/* GART init */
if (drm->agp.stat != ENABLED) {
- drm->gem.gart_available = nouveau_vmmgr(drm->device)->limit;
+ drm->gem.gart_available = nvkm_vmmgr(&drm->device)->limit;
} else {
drm->gem.gart_available = drm->agp.size;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
new file mode 100644
index 000000000000..cb1182d7e80e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nouveau_drm.h"
+#include "nouveau_usif.h"
+
+#include <nvif/notify.h>
+#include <nvif/unpack.h>
+#include <nvif/client.h>
+#include <nvif/event.h>
+#include <nvif/ioctl.h>
+
+struct usif_notify_p {
+ struct drm_pending_event base;
+ struct {
+ struct drm_event base;
+ u8 data[];
+ } e;
+};
+
+struct usif_notify {
+ struct list_head head;
+ atomic_t enabled;
+ u32 handle;
+ u16 reply;
+ u8 route;
+ u64 token;
+ struct usif_notify_p *p;
+};
+
+static inline struct usif_notify *
+usif_notify_find(struct drm_file *filp, u32 handle)
+{
+ struct nouveau_cli *cli = nouveau_cli(filp);
+ struct usif_notify *ntfy;
+ list_for_each_entry(ntfy, &cli->notifys, head) {
+ if (ntfy->handle == handle)
+ return ntfy;
+ }
+ return NULL;
+}
+
+static inline void
+usif_notify_dtor(struct usif_notify *ntfy)
+{
+ list_del(&ntfy->head);
+ kfree(ntfy);
+}
+
+int
+usif_notify(const void *header, u32 length, const void *data, u32 size)
+{
+ struct usif_notify *ntfy = NULL;
+ const union {
+ struct nvif_notify_rep_v0 v0;
+ } *rep = header;
+ struct drm_device *dev;
+ struct drm_file *filp;
+ unsigned long flags;
+
+ if (length == sizeof(rep->v0) && rep->v0.version == 0) {
+ if (WARN_ON(!(ntfy = (void *)(unsigned long)rep->v0.token)))
+ return NVIF_NOTIFY_DROP;
+ BUG_ON(rep->v0.route != NVDRM_NOTIFY_USIF);
+ } else
+ if (WARN_ON(1))
+ return NVIF_NOTIFY_DROP;
+
+ if (WARN_ON(!ntfy->p || ntfy->reply != (length + size)))
+ return NVIF_NOTIFY_DROP;
+ filp = ntfy->p->base.file_priv;
+ dev = filp->minor->dev;
+
+ memcpy(&ntfy->p->e.data[0], header, length);
+ memcpy(&ntfy->p->e.data[length], data, size);
+ switch (rep->v0.version) {
+ case 0: {
+ struct nvif_notify_rep_v0 *rep = (void *)ntfy->p->e.data;
+ rep->route = ntfy->route;
+ rep->token = ntfy->token;
+ }
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (!WARN_ON(filp->event_space < ntfy->p->e.base.length)) {
+ list_add_tail(&ntfy->p->base.link, &filp->event_list);
+ filp->event_space -= ntfy->p->e.base.length;
+ }
+ wake_up_interruptible(&filp->event_wait);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ atomic_set(&ntfy->enabled, 0);
+ return NVIF_NOTIFY_DROP;
+}
+
+static int
+usif_notify_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(f);
+ struct nvif_client *client = &cli->base;
+ union {
+ struct nvif_ioctl_ntfy_new_v0 v0;
+ } *args = data;
+ union {
+ struct nvif_notify_req_v0 v0;
+ } *req;
+ struct usif_notify *ntfy;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ if (usif_notify_find(f, args->v0.index))
+ return -EEXIST;
+ } else
+ return ret;
+ req = data;
+
+ if (!(ntfy = kmalloc(sizeof(*ntfy), GFP_KERNEL)))
+ return -ENOMEM;
+ atomic_set(&ntfy->enabled, 0);
+
+ if (nvif_unpack(req->v0, 0, 0, true)) {
+ ntfy->reply = sizeof(struct nvif_notify_rep_v0) + req->v0.reply;
+ ntfy->route = req->v0.route;
+ ntfy->token = req->v0.token;
+ req->v0.route = NVDRM_NOTIFY_USIF;
+ req->v0.token = (unsigned long)(void *)ntfy;
+ ret = nvif_client_ioctl(client, argv, argc);
+ req->v0.token = ntfy->token;
+ req->v0.route = ntfy->route;
+ ntfy->handle = args->v0.index;
+ }
+
+ if (ret == 0)
+ list_add(&ntfy->head, &cli->notifys);
+ if (ret)
+ kfree(ntfy);
+ return ret;
+}
+
+static int
+usif_notify_del(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(f);
+ struct nvif_client *client = &cli->base;
+ union {
+ struct nvif_ioctl_ntfy_del_v0 v0;
+ } *args = data;
+ struct usif_notify *ntfy;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ if (!(ntfy = usif_notify_find(f, args->v0.index)))
+ return -ENOENT;
+ } else
+ return ret;
+
+ ret = nvif_client_ioctl(client, argv, argc);
+ if (ret == 0)
+ usif_notify_dtor(ntfy);
+ return ret;
+}
+
+static int
+usif_notify_get(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(f);
+ struct nvif_client *client = &cli->base;
+ union {
+ struct nvif_ioctl_ntfy_del_v0 v0;
+ } *args = data;
+ struct usif_notify *ntfy;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ if (!(ntfy = usif_notify_find(f, args->v0.index)))
+ return -ENOENT;
+ } else
+ return ret;
+
+ if (atomic_xchg(&ntfy->enabled, 1))
+ return 0;
+
+ ntfy->p = kmalloc(sizeof(*ntfy->p) + ntfy->reply, GFP_KERNEL);
+ if (ret = -ENOMEM, !ntfy->p)
+ goto done;
+ ntfy->p->base.event = &ntfy->p->e.base;
+ ntfy->p->base.file_priv = f;
+ ntfy->p->base.pid = current->pid;
+ ntfy->p->base.destroy =(void(*)(struct drm_pending_event *))kfree;
+ ntfy->p->e.base.type = DRM_NOUVEAU_EVENT_NVIF;
+ ntfy->p->e.base.length = sizeof(ntfy->p->e.base) + ntfy->reply;
+
+ ret = nvif_client_ioctl(client, argv, argc);
+done:
+ if (ret) {
+ atomic_set(&ntfy->enabled, 0);
+ kfree(ntfy->p);
+ }
+ return ret;
+}
+
+static int
+usif_notify_put(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(f);
+ struct nvif_client *client = &cli->base;
+ union {
+ struct nvif_ioctl_ntfy_put_v0 v0;
+ } *args = data;
+ struct usif_notify *ntfy;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ if (!(ntfy = usif_notify_find(f, args->v0.index)))
+ return -ENOENT;
+ } else
+ return ret;
+
+ ret = nvif_client_ioctl(client, argv, argc);
+ if (ret == 0 && atomic_xchg(&ntfy->enabled, 0))
+ kfree(ntfy->p);
+ return ret;
+}
+
+struct usif_object {
+ struct list_head head;
+ struct list_head ntfy;
+ u8 route;
+ u64 token;
+};
+
+static void
+usif_object_dtor(struct usif_object *object)
+{
+ list_del(&object->head);
+ kfree(object);
+}
+
+static int
+usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(f);
+ struct nvif_client *client = &cli->base;
+ union {
+ struct nvif_ioctl_new_v0 v0;
+ } *args = data;
+ struct usif_object *object;
+ int ret;
+
+ if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
+ return -ENOMEM;
+ list_add(&object->head, &cli->objects);
+
+ if (nvif_unpack(args->v0, 0, 0, true)) {
+ object->route = args->v0.route;
+ object->token = args->v0.token;
+ args->v0.route = NVDRM_OBJECT_USIF;
+ args->v0.token = (unsigned long)(void *)object;
+ ret = nvif_client_ioctl(client, argv, argc);
+ args->v0.token = object->token;
+ args->v0.route = object->route;
+ }
+
+ if (ret)
+ usif_object_dtor(object);
+ return ret;
+}
+
+int
+usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
+{
+ struct nouveau_cli *cli = nouveau_cli(filp);
+ struct nvif_client *client = &cli->base;
+ void *data = kmalloc(argc, GFP_KERNEL);
+ u32 size = argc;
+ union {
+ struct nvif_ioctl_v0 v0;
+ } *argv = data;
+ struct usif_object *object;
+ u8 owner;
+ int ret;
+
+ if (ret = -ENOMEM, !argv)
+ goto done;
+ if (ret = -EFAULT, copy_from_user(argv, user, size))
+ goto done;
+
+ if (nvif_unpack(argv->v0, 0, 0, true)) {
+ /* block access to objects not created via this interface */
+ owner = argv->v0.owner;
+ argv->v0.owner = NVDRM_OBJECT_USIF;
+ } else
+ goto done;
+
+ mutex_lock(&cli->mutex);
+ switch (argv->v0.type) {
+ case NVIF_IOCTL_V0_NEW:
+ /* ... except if we're creating children */
+ argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+ ret = usif_object_new(filp, data, size, argv, argc);
+ break;
+ case NVIF_IOCTL_V0_NTFY_NEW:
+ ret = usif_notify_new(filp, data, size, argv, argc);
+ break;
+ case NVIF_IOCTL_V0_NTFY_DEL:
+ ret = usif_notify_del(filp, data, size, argv, argc);
+ break;
+ case NVIF_IOCTL_V0_NTFY_GET:
+ ret = usif_notify_get(filp, data, size, argv, argc);
+ break;
+ case NVIF_IOCTL_V0_NTFY_PUT:
+ ret = usif_notify_put(filp, data, size, argv, argc);
+ break;
+ default:
+ ret = nvif_client_ioctl(client, argv, argc);
+ break;
+ }
+ if (argv->v0.route == NVDRM_OBJECT_USIF) {
+ object = (void *)(unsigned long)argv->v0.token;
+ argv->v0.route = object->route;
+ argv->v0.token = object->token;
+ if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) {
+ list_del(&object->head);
+ kfree(object);
+ }
+ } else {
+ argv->v0.route = NVIF_IOCTL_V0_ROUTE_HIDDEN;
+ argv->v0.token = 0;
+ }
+ argv->v0.owner = owner;
+ mutex_unlock(&cli->mutex);
+
+ if (copy_to_user(user, argv, argc))
+ ret = -EFAULT;
+done:
+ kfree(argv);
+ return ret;
+}
+
+void
+usif_client_fini(struct nouveau_cli *cli)
+{
+ struct usif_object *object, *otemp;
+ struct usif_notify *notify, *ntemp;
+
+ list_for_each_entry_safe(notify, ntemp, &cli->notifys, head) {
+ usif_notify_dtor(notify);
+ }
+
+ list_for_each_entry_safe(object, otemp, &cli->objects, head) {
+ usif_object_dtor(object);
+ }
+}
+
+void
+usif_client_init(struct nouveau_cli *cli)
+{
+ INIT_LIST_HEAD(&cli->objects);
+ INIT_LIST_HEAD(&cli->notifys);
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.h b/drivers/gpu/drm/nouveau/nouveau_usif.h
new file mode 100644
index 000000000000..c037e3ae8c70
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.h
@@ -0,0 +1,9 @@
+#ifndef __NOUVEAU_USIF_H__
+#define __NOUVEAU_USIF_H__
+
+void usif_client_init(struct nouveau_cli *);
+void usif_client_fini(struct nouveau_cli *);
+int usif_ioctl(struct drm_file *, void __user *, u32);
+int usif_notify(const void *, u32, const void *, u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 4f4c3fec6916..18d55d447248 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -12,14 +12,16 @@
static unsigned int
nouveau_vga_set_decode(void *priv, bool state)
{
- struct nouveau_device *device = nouveau_dev(priv);
+ struct nvif_device *device = &nouveau_drm(priv)->device;
- if (device->card_type == NV_40 && device->chipset >= 0x4c)
- nv_wr32(device, 0x088060, state);
- else if (device->chipset >= 0x40)
- nv_wr32(device, 0x088054, state);
+ if (device->info.family == NV_DEVICE_INFO_V0_CURIE &&
+ device->info.chipset >= 0x4c)
+ nvif_wr32(device, 0x088060, state);
else
- nv_wr32(device, 0x001854, state);
+ if (device->info.chipset >= 0x40)
+ nvif_wr32(device, 0x088054, state);
+ else
+ nvif_wr32(device, 0x001854, state);
if (state)
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 8fe32bbed99a..4ef602c5469d 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -22,8 +22,6 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include <core/object.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fbcon.h"
@@ -141,8 +139,7 @@ nv04_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = nfbdev->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
- struct nouveau_device *device = nv_device(drm->device);
- struct nouveau_object *object;
+ struct nvif_device *device = &drm->device;
int surface_fmt, pattern_fmt, rect_fmt;
int ret;
@@ -174,35 +171,35 @@ nv04_fbcon_accel_init(struct fb_info *info)
return -EINVAL;
}
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvCtxSurf2D,
- device->card_type >= NV_10 ? 0x0062 : 0x0042,
- NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x0062,
+ device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ?
+ 0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d);
if (ret)
return ret;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvClipRect,
- 0x0019, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x0019, 0x0019, NULL, 0,
+ &nfbdev->clip);
if (ret)
return ret;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvRop,
- 0x0043, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x0043, 0x0043, NULL, 0,
+ &nfbdev->rop);
if (ret)
return ret;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImagePatt,
- 0x0044, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x0044, 0x0044, NULL, 0,
+ &nfbdev->patt);
if (ret)
return ret;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvGdiRect,
- 0x004a, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x004a, 0x004a, NULL, 0,
+ &nfbdev->gdi);
if (ret)
return ret;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, NvImageBlit,
- device->chipset >= 0x11 ? 0x009f : 0x005f,
- NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x005f,
+ device->info.chipset >= 0x11 ? 0x009f : 0x005f,
+ NULL, 0, &nfbdev->blit);
if (ret)
return ret;
@@ -212,10 +209,10 @@ nv04_fbcon_accel_init(struct fb_info *info)
}
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
- OUT_RING(chan, NvCtxSurf2D);
+ OUT_RING(chan, nfbdev->surf2d.handle);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0184, 2);
- OUT_RING(chan, NvDmaFB);
- OUT_RING(chan, NvDmaFB);
+ OUT_RING(chan, chan->vram.handle);
+ OUT_RING(chan, chan->vram.handle);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 4);
OUT_RING(chan, surface_fmt);
OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
@@ -223,12 +220,12 @@ nv04_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
- OUT_RING(chan, NvRop);
+ OUT_RING(chan, nfbdev->rop.handle);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 1);
OUT_RING(chan, 0x55);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
- OUT_RING(chan, NvImagePatt);
+ OUT_RING(chan, nfbdev->patt.handle);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 8);
OUT_RING(chan, pattern_fmt);
#ifdef __BIG_ENDIAN
@@ -244,18 +241,18 @@ nv04_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, ~0);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0000, 1);
- OUT_RING(chan, NvClipRect);
+ OUT_RING(chan, nfbdev->clip.handle);
BEGIN_NV04(chan, NvSubCtxSurf2D, 0x0300, 2);
OUT_RING(chan, 0);
OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
BEGIN_NV04(chan, NvSubImageBlit, 0x0000, 1);
- OUT_RING(chan, NvImageBlit);
+ OUT_RING(chan, nfbdev->blit.handle);
BEGIN_NV04(chan, NvSubImageBlit, 0x019c, 1);
- OUT_RING(chan, NvCtxSurf2D);
+ OUT_RING(chan, nfbdev->surf2d.handle);
BEGIN_NV04(chan, NvSubImageBlit, 0x02fc, 1);
OUT_RING(chan, 3);
- if (device->chipset >= 0x11 /*XXX: oclass == 0x009f*/) {
+ if (device->info.chipset >= 0x11 /*XXX: oclass == 0x009f*/) {
BEGIN_NV04(chan, NvSubImageBlit, 0x0120, 3);
OUT_RING(chan, 0);
OUT_RING(chan, 1);
@@ -263,12 +260,12 @@ nv04_fbcon_accel_init(struct fb_info *info)
}
BEGIN_NV04(chan, NvSubGdiRect, 0x0000, 1);
- OUT_RING(chan, NvGdiRect);
+ OUT_RING(chan, nfbdev->gdi.handle);
BEGIN_NV04(chan, NvSubGdiRect, 0x0198, 1);
- OUT_RING(chan, NvCtxSurf2D);
+ OUT_RING(chan, nfbdev->surf2d.handle);
BEGIN_NV04(chan, NvSubGdiRect, 0x0188, 2);
- OUT_RING(chan, NvImagePatt);
- OUT_RING(chan, NvRop);
+ OUT_RING(chan, nfbdev->patt.handle);
+ OUT_RING(chan, nfbdev->rop.handle);
BEGIN_NV04(chan, NvSubGdiRect, 0x0304, 1);
OUT_RING(chan, 1);
BEGIN_NV04(chan, NvSubGdiRect, 0x0300, 1);
diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c
index 94eadd1dd10a..239c2c5a9615 100644
--- a/drivers/gpu/drm/nouveau/nv04_fence.c
+++ b/drivers/gpu/drm/nouveau/nv04_fence.c
@@ -22,8 +22,6 @@
* Authors: Ben Skeggs
*/
-#include <engine/fifo.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
@@ -59,7 +57,7 @@ nv04_fence_sync(struct nouveau_fence *fence,
static u32
nv04_fence_read(struct nouveau_channel *chan)
{
- struct nouveau_fifo_chan *fifo = (void *)chan->object;
+ struct nouveau_fifo_chan *fifo = nvkm_fifo_chan(chan);;
return atomic_read(&fifo->refcnt);
}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c
index 06f434f03fba..4faaf0acf5d7 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.c
+++ b/drivers/gpu/drm/nouveau/nv10_fence.c
@@ -22,9 +22,6 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
-#include <core/object.h>
-#include <core/class.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nv10_fence.h"
@@ -53,14 +50,18 @@ nv10_fence_sync(struct nouveau_fence *fence,
u32
nv10_fence_read(struct nouveau_channel *chan)
{
- return nv_ro32(chan->object, 0x0048);
+ return nvif_rd32(chan, 0x0048);
}
void
nv10_fence_context_del(struct nouveau_channel *chan)
{
struct nv10_fence_chan *fctx = chan->fence;
+ int i;
nouveau_fence_context_del(&fctx->base);
+ for (i = 0; i < ARRAY_SIZE(fctx->head); i++)
+ nvif_object_fini(&fctx->head[i]);
+ nvif_object_fini(&fctx->sema);
chan->fence = NULL;
kfree(fctx);
}
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.h b/drivers/gpu/drm/nouveau/nv10_fence.h
index e5d9204826c2..a87259f3983a 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.h
+++ b/drivers/gpu/drm/nouveau/nv10_fence.h
@@ -1,12 +1,13 @@
#ifndef __NV10_FENCE_H_
#define __NV10_FENCE_H_
-#include <core/os.h>
#include "nouveau_fence.h"
#include "nouveau_bo.h"
struct nv10_fence_chan {
struct nouveau_fence_chan base;
+ struct nvif_object sema;
+ struct nvif_object head[4];
};
struct nv10_fence_priv {
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c
index 22aa9963ea6f..ca907479f92f 100644
--- a/drivers/gpu/drm/nouveau/nv17_fence.c
+++ b/drivers/gpu/drm/nouveau/nv17_fence.c
@@ -22,8 +22,8 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
-#include <core/object.h>
-#include <core/class.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -33,11 +33,13 @@ int
nv17_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *prev, struct nouveau_channel *chan)
{
+ struct nouveau_cli *cli = (void *)nvif_client(&prev->device->base);
struct nv10_fence_priv *priv = chan->drm->fence;
+ struct nv10_fence_chan *fctx = chan->fence;
u32 value;
int ret;
- if (!mutex_trylock(&prev->cli->mutex))
+ if (!mutex_trylock(&cli->mutex))
return -EBUSY;
spin_lock(&priv->lock);
@@ -48,7 +50,7 @@ nv17_fence_sync(struct nouveau_fence *fence,
ret = RING_SPACE(prev, 5);
if (!ret) {
BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
- OUT_RING (prev, NvSema);
+ OUT_RING (prev, fctx->sema.handle);
OUT_RING (prev, 0);
OUT_RING (prev, value + 0);
OUT_RING (prev, value + 1);
@@ -57,14 +59,14 @@ nv17_fence_sync(struct nouveau_fence *fence,
if (!ret && !(ret = RING_SPACE(chan, 5))) {
BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4);
- OUT_RING (chan, NvSema);
+ OUT_RING (chan, fctx->sema.handle);
OUT_RING (chan, 0);
OUT_RING (chan, value + 1);
OUT_RING (chan, value + 2);
FIRE_RING (chan);
}
- mutex_unlock(&prev->cli->mutex);
+ mutex_unlock(&cli->mutex);
return 0;
}
@@ -74,7 +76,6 @@ nv17_fence_context_new(struct nouveau_channel *chan)
struct nv10_fence_priv *priv = chan->drm->fence;
struct nv10_fence_chan *fctx;
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
- struct nouveau_object *object;
u32 start = mem->start * PAGE_SIZE;
u32 limit = start + mem->size - 1;
int ret = 0;
@@ -88,15 +89,14 @@ nv17_fence_context_new(struct nouveau_channel *chan)
fctx->base.read = nv10_fence_read;
fctx->base.sync = nv17_fence_sync;
- ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
- NvSema, 0x0002,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(chan->object, NULL, NvSema, NV_DMA_FROM_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = start,
.limit = limit,
- }, sizeof(struct nv_dma_class),
- &object);
+ }, sizeof(struct nv_dma_v0),
+ &fctx->sema);
if (ret)
nv10_fence_context_del(chan);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 4c534b7b04da..03949eaa629f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -28,6 +28,8 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_dp_helper.h>
+#include <nvif/class.h>
+
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_gem.h"
@@ -37,15 +39,6 @@
#include "nouveau_fence.h"
#include "nv50_display.h"
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <core/class.h>
-
-#include <subdev/timer.h>
-#include <subdev/bar.h>
-#include <subdev/fb.h>
-#include <subdev/i2c.h>
-
#define EVO_DMA_NR 9
#define EVO_MASTER (0x00)
@@ -60,45 +53,34 @@
#define EVO_FLIP_SEM0(c) EVO_SYNC((c) + 1, 0x00)
#define EVO_FLIP_SEM1(c) EVO_SYNC((c) + 1, 0x10)
-#define EVO_CORE_HANDLE (0xd1500000)
-#define EVO_CHAN_HANDLE(t,i) (0xd15c0000 | (((t) & 0x00ff) << 8) | (i))
-#define EVO_CHAN_OCLASS(t,c) ((nv_hclass(c) & 0xff00) | ((t) & 0x00ff))
-#define EVO_PUSH_HANDLE(t,i) (0xd15b0000 | (i) | \
- (((NV50_DISP_##t##_CLASS) & 0x00ff) << 8))
-
/******************************************************************************
* EVO channel
*****************************************************************************/
struct nv50_chan {
- struct nouveau_object *user;
- u32 handle;
+ struct nvif_object user;
};
static int
-nv50_chan_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_chan_create(struct nvif_object *disp, const u32 *oclass, u8 head,
void *data, u32 size, struct nv50_chan *chan)
{
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- const u32 oclass = EVO_CHAN_OCLASS(bclass, core);
- const u32 handle = EVO_CHAN_HANDLE(bclass, head);
- int ret;
-
- ret = nouveau_object_new(client, EVO_CORE_HANDLE, handle,
- oclass, data, size, &chan->user);
- if (ret)
- return ret;
-
- chan->handle = handle;
- return 0;
+ while (oclass[0]) {
+ int ret = nvif_object_init(disp, NULL, (oclass[0] << 16) | head,
+ oclass[0], data, size,
+ &chan->user);
+ if (oclass++, ret == 0) {
+ nvif_object_map(&chan->user);
+ return ret;
+ }
+ }
+ return -ENOSYS;
}
static void
-nv50_chan_destroy(struct nouveau_object *core, struct nv50_chan *chan)
+nv50_chan_destroy(struct nv50_chan *chan)
{
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- if (chan->handle)
- nouveau_object_del(client, EVO_CORE_HANDLE, chan->handle);
+ nvif_object_fini(&chan->user);
}
/******************************************************************************
@@ -110,16 +92,70 @@ struct nv50_pioc {
};
static void
-nv50_pioc_destroy(struct nouveau_object *core, struct nv50_pioc *pioc)
+nv50_pioc_destroy(struct nv50_pioc *pioc)
{
- nv50_chan_destroy(core, &pioc->base);
+ nv50_chan_destroy(&pioc->base);
}
static int
-nv50_pioc_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_pioc_create(struct nvif_object *disp, const u32 *oclass, u8 head,
void *data, u32 size, struct nv50_pioc *pioc)
{
- return nv50_chan_create(core, bclass, head, data, size, &pioc->base);
+ return nv50_chan_create(disp, oclass, head, data, size, &pioc->base);
+}
+
+/******************************************************************************
+ * Cursor Immediate
+ *****************************************************************************/
+
+struct nv50_curs {
+ struct nv50_pioc base;
+};
+
+static int
+nv50_curs_create(struct nvif_object *disp, int head, struct nv50_curs *curs)
+{
+ struct nv50_disp_cursor_v0 args = {
+ .head = head,
+ };
+ static const u32 oclass[] = {
+ GK104_DISP_CURSOR,
+ GF110_DISP_CURSOR,
+ GT214_DISP_CURSOR,
+ G82_DISP_CURSOR,
+ NV50_DISP_CURSOR,
+ 0
+ };
+
+ return nv50_pioc_create(disp, oclass, head, &args, sizeof(args),
+ &curs->base);
+}
+
+/******************************************************************************
+ * Overlay Immediate
+ *****************************************************************************/
+
+struct nv50_oimm {
+ struct nv50_pioc base;
+};
+
+static int
+nv50_oimm_create(struct nvif_object *disp, int head, struct nv50_oimm *oimm)
+{
+ struct nv50_disp_cursor_v0 args = {
+ .head = head,
+ };
+ static const u32 oclass[] = {
+ GK104_DISP_OVERLAY,
+ GF110_DISP_OVERLAY,
+ GT214_DISP_OVERLAY,
+ G82_DISP_OVERLAY,
+ NV50_DISP_OVERLAY,
+ 0
+ };
+
+ return nv50_pioc_create(disp, oclass, head, &args, sizeof(args),
+ &oimm->base);
}
/******************************************************************************
@@ -131,6 +167,9 @@ struct nv50_dmac {
dma_addr_t handle;
u32 *ptr;
+ struct nvif_object sync;
+ struct nvif_object vram;
+
/* Protects against concurrent pushbuf access to this channel, lock is
* grabbed by evo_wait (if the pushbuf reservation is successful) and
* dropped again by evo_kick. */
@@ -138,207 +177,113 @@ struct nv50_dmac {
};
static void
-nv50_dmac_destroy(struct nouveau_object *core, struct nv50_dmac *dmac)
+nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp)
{
+ nvif_object_fini(&dmac->vram);
+ nvif_object_fini(&dmac->sync);
+
+ nv50_chan_destroy(&dmac->base);
+
if (dmac->ptr) {
- struct pci_dev *pdev = nv_device(core)->pdev;
+ struct pci_dev *pdev = nvkm_device(nvif_device(disp))->pdev;
pci_free_consistent(pdev, PAGE_SIZE, dmac->ptr, dmac->handle);
}
-
- nv50_chan_destroy(core, &dmac->base);
-}
-
-static int
-nv50_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
- struct nouveau_fb *pfb = nouveau_fb(core);
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- struct nouveau_object *object;
- int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NV50_DMA_CONF0_ENABLE |
- NV50_DMA_CONF0_PART_256,
- }, sizeof(struct nv_dma_class), &object);
- if (ret)
- return ret;
-
- ret = nouveau_object_new(client, parent, NvEvoFB16,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NV50_DMA_CONF0_ENABLE | 0x70 |
- NV50_DMA_CONF0_PART_256,
- }, sizeof(struct nv_dma_class), &object);
- if (ret)
- return ret;
-
- ret = nouveau_object_new(client, parent, NvEvoFB32,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NV50_DMA_CONF0_ENABLE | 0x7a |
- NV50_DMA_CONF0_PART_256,
- }, sizeof(struct nv_dma_class), &object);
- return ret;
-}
-
-static int
-nvc0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
- struct nouveau_fb *pfb = nouveau_fb(core);
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- struct nouveau_object *object;
- int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NVC0_DMA_CONF0_ENABLE,
- }, sizeof(struct nv_dma_class), &object);
- if (ret)
- return ret;
-
- ret = nouveau_object_new(client, parent, NvEvoFB16,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
- }, sizeof(struct nv_dma_class), &object);
- if (ret)
- return ret;
-
- ret = nouveau_object_new(client, parent, NvEvoFB32,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NVC0_DMA_CONF0_ENABLE | 0xfe,
- }, sizeof(struct nv_dma_class), &object);
- return ret;
-}
-
-static int
-nvd0_dmac_create_fbdma(struct nouveau_object *core, u32 parent)
-{
- struct nouveau_fb *pfb = nouveau_fb(core);
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- struct nouveau_object *object;
- int ret = nouveau_object_new(client, parent, NvEvoVRAM_LP,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NVD0_DMA_CONF0_ENABLE |
- NVD0_DMA_CONF0_PAGE_LP,
- }, sizeof(struct nv_dma_class), &object);
- if (ret)
- return ret;
-
- ret = nouveau_object_new(client, parent, NvEvoFB32,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
- .start = 0,
- .limit = pfb->ram->size - 1,
- .conf0 = NVD0_DMA_CONF0_ENABLE | 0xfe |
- NVD0_DMA_CONF0_PAGE_LP,
- }, sizeof(struct nv_dma_class), &object);
- return ret;
}
static int
-nv50_dmac_create(struct nouveau_object *core, u32 bclass, u8 head,
+nv50_dmac_create(struct nvif_object *disp, const u32 *oclass, u8 head,
void *data, u32 size, u64 syncbuf,
struct nv50_dmac *dmac)
{
- struct nouveau_fb *pfb = nouveau_fb(core);
- struct nouveau_object *client = nv_pclass(core, NV_CLIENT_CLASS);
- struct nouveau_object *object;
- u32 pushbuf = *(u32 *)data;
+ struct nvif_device *device = nvif_device(disp);
+ struct nv50_disp_core_channel_dma_v0 *args = data;
+ struct nvif_object pushbuf;
int ret;
mutex_init(&dmac->lock);
- dmac->ptr = pci_alloc_consistent(nv_device(core)->pdev, PAGE_SIZE,
- &dmac->handle);
+ dmac->ptr = pci_alloc_consistent(nvkm_device(device)->pdev,
+ PAGE_SIZE, &dmac->handle);
if (!dmac->ptr)
return -ENOMEM;
- ret = nouveau_object_new(client, NVDRM_DEVICE, pushbuf,
- NV_DMA_FROM_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_PCI_US |
- NV_DMA_ACCESS_RD,
+ ret = nvif_object_init(nvif_object(device), NULL,
+ args->pushbuf, NV_DMA_FROM_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_PCI_US,
+ .access = NV_DMA_V0_ACCESS_RD,
.start = dmac->handle + 0x0000,
.limit = dmac->handle + 0x0fff,
- }, sizeof(struct nv_dma_class), &object);
+ }, sizeof(struct nv_dma_v0), &pushbuf);
if (ret)
return ret;
- ret = nv50_chan_create(core, bclass, head, data, size, &dmac->base);
+ ret = nv50_chan_create(disp, oclass, head, data, size, &dmac->base);
+ nvif_object_fini(&pushbuf);
if (ret)
return ret;
- ret = nouveau_object_new(client, dmac->base.handle, NvEvoSync,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000000,
+ NV_DMA_IN_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = syncbuf + 0x0000,
.limit = syncbuf + 0x0fff,
- }, sizeof(struct nv_dma_class), &object);
+ }, sizeof(struct nv_dma_v0),
+ &dmac->sync);
if (ret)
return ret;
- ret = nouveau_object_new(client, dmac->base.handle, NvEvoVRAM,
- NV_DMA_IN_MEMORY_CLASS,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(&dmac->base.user, NULL, 0xf0000001,
+ NV_DMA_IN_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = 0,
- .limit = pfb->ram->size - 1,
- }, sizeof(struct nv_dma_class), &object);
+ .limit = device->info.ram_user - 1,
+ }, sizeof(struct nv_dma_v0),
+ &dmac->vram);
if (ret)
return ret;
- if (nv_device(core)->card_type < NV_C0)
- ret = nv50_dmac_create_fbdma(core, dmac->base.handle);
- else
- if (nv_device(core)->card_type < NV_D0)
- ret = nvc0_dmac_create_fbdma(core, dmac->base.handle);
- else
- ret = nvd0_dmac_create_fbdma(core, dmac->base.handle);
return ret;
}
+/******************************************************************************
+ * Core
+ *****************************************************************************/
+
struct nv50_mast {
struct nv50_dmac base;
};
-struct nv50_curs {
- struct nv50_pioc base;
-};
+static int
+nv50_core_create(struct nvif_object *disp, u64 syncbuf, struct nv50_mast *core)
+{
+ struct nv50_disp_core_channel_dma_v0 args = {
+ .pushbuf = 0xb0007d00,
+ };
+ static const u32 oclass[] = {
+ GM107_DISP_CORE_CHANNEL_DMA,
+ GK110_DISP_CORE_CHANNEL_DMA,
+ GK104_DISP_CORE_CHANNEL_DMA,
+ GF110_DISP_CORE_CHANNEL_DMA,
+ GT214_DISP_CORE_CHANNEL_DMA,
+ GT206_DISP_CORE_CHANNEL_DMA,
+ GT200_DISP_CORE_CHANNEL_DMA,
+ G82_DISP_CORE_CHANNEL_DMA,
+ NV50_DISP_CORE_CHANNEL_DMA,
+ 0
+ };
+
+ return nv50_dmac_create(disp, oclass, 0, &args, sizeof(args), syncbuf,
+ &core->base);
+}
+
+/******************************************************************************
+ * Base
+ *****************************************************************************/
struct nv50_sync {
struct nv50_dmac base;
@@ -346,13 +291,58 @@ struct nv50_sync {
u32 data;
};
+static int
+nv50_base_create(struct nvif_object *disp, int head, u64 syncbuf,
+ struct nv50_sync *base)
+{
+ struct nv50_disp_base_channel_dma_v0 args = {
+ .pushbuf = 0xb0007c00 | head,
+ .head = head,
+ };
+ static const u32 oclass[] = {
+ GK110_DISP_BASE_CHANNEL_DMA,
+ GK104_DISP_BASE_CHANNEL_DMA,
+ GF110_DISP_BASE_CHANNEL_DMA,
+ GT214_DISP_BASE_CHANNEL_DMA,
+ GT200_DISP_BASE_CHANNEL_DMA,
+ G82_DISP_BASE_CHANNEL_DMA,
+ NV50_DISP_BASE_CHANNEL_DMA,
+ 0
+ };
+
+ return nv50_dmac_create(disp, oclass, head, &args, sizeof(args),
+ syncbuf, &base->base);
+}
+
+/******************************************************************************
+ * Overlay
+ *****************************************************************************/
+
struct nv50_ovly {
struct nv50_dmac base;
};
-struct nv50_oimm {
- struct nv50_pioc base;
-};
+static int
+nv50_ovly_create(struct nvif_object *disp, int head, u64 syncbuf,
+ struct nv50_ovly *ovly)
+{
+ struct nv50_disp_overlay_channel_dma_v0 args = {
+ .pushbuf = 0xb0007e00 | head,
+ .head = head,
+ };
+ static const u32 oclass[] = {
+ GK104_DISP_OVERLAY_CONTROL_DMA,
+ GF110_DISP_OVERLAY_CONTROL_DMA,
+ GT214_DISP_OVERLAY_CHANNEL_DMA,
+ GT200_DISP_OVERLAY_CHANNEL_DMA,
+ G82_DISP_OVERLAY_CHANNEL_DMA,
+ NV50_DISP_OVERLAY_CHANNEL_DMA,
+ 0
+ };
+
+ return nv50_dmac_create(disp, oclass, head, &args, sizeof(args),
+ syncbuf, &ovly->base);
+}
struct nv50_head {
struct nouveau_crtc base;
@@ -369,13 +359,19 @@ struct nv50_head {
#define nv50_ovly(c) (&nv50_head(c)->ovly)
#define nv50_oimm(c) (&nv50_head(c)->oimm)
#define nv50_chan(c) (&(c)->base.base)
-#define nv50_vers(c) nv_mclass(nv50_chan(c)->user)
+#define nv50_vers(c) nv50_chan(c)->user.oclass
+
+struct nv50_fbdma {
+ struct list_head head;
+ struct nvif_object core;
+ struct nvif_object base[4];
+};
struct nv50_disp {
- struct nouveau_object *core;
+ struct nvif_object *disp;
struct nv50_mast mast;
- u32 modeset;
+ struct list_head fbdma;
struct nouveau_bo *sync;
};
@@ -401,16 +397,16 @@ static u32 *
evo_wait(void *evoc, int nr)
{
struct nv50_dmac *dmac = evoc;
- u32 put = nv_ro32(dmac->base.user, 0x0000) / 4;
+ u32 put = nvif_rd32(&dmac->base.user, 0x0000) / 4;
mutex_lock(&dmac->lock);
if (put + nr >= (PAGE_SIZE / 4) - 8) {
dmac->ptr[put] = 0x20000000;
- nv_wo32(dmac->base.user, 0x0000, 0x00000000);
- if (!nv_wait(dmac->base.user, 0x0004, ~0, 0x00000000)) {
+ nvif_wr32(&dmac->base.user, 0x0000, 0x00000000);
+ if (!nvkm_wait(&dmac->base.user, 0x0004, ~0, 0x00000000)) {
mutex_unlock(&dmac->lock);
- NV_ERROR(dmac->base.user, "channel stalled\n");
+ nv_error(nvkm_object(&dmac->base.user), "channel stalled\n");
return NULL;
}
@@ -424,7 +420,7 @@ static void
evo_kick(u32 *push, void *evoc)
{
struct nv50_dmac *dmac = evoc;
- nv_wo32(dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
+ nvif_wr32(&dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
mutex_unlock(&dmac->lock);
}
@@ -443,7 +439,7 @@ evo_sync_wait(void *data)
static int
evo_sync(struct drm_device *dev)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_mast *mast = nv50_mast(dev);
u32 *push = evo_wait(mast, 8);
@@ -455,7 +451,7 @@ evo_sync(struct drm_device *dev)
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
evo_kick(push, mast);
- if (nv_wait_cb(device, evo_sync_wait, disp->sync))
+ if (nv_wait_cb(nvkm_device(device), evo_sync_wait, disp->sync))
return 0;
}
@@ -490,7 +486,7 @@ nv50_display_flip_wait(void *data)
void
nv50_display_flip_stop(struct drm_crtc *crtc)
{
- struct nouveau_device *device = nouveau_dev(crtc->dev);
+ struct nvif_device *device = &nouveau_drm(crtc->dev)->device;
struct nv50_display_flip flip = {
.disp = nv50_disp(crtc->dev),
.chan = nv50_sync(crtc),
@@ -510,7 +506,7 @@ nv50_display_flip_stop(struct drm_crtc *crtc)
evo_kick(push, flip.chan);
}
- nv_wait_cb(device, nv50_display_flip_wait, &flip);
+ nv_wait_cb(nvkm_device(device), nv50_display_flip_wait, &flip);
}
int
@@ -534,7 +530,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
if (unlikely(push == NULL))
return -EBUSY;
- if (chan && nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) {
+ if (chan && chan->object->oclass < G82_CHANNEL_GPFIFO) {
ret = RING_SPACE(chan, 8);
if (ret)
return ret;
@@ -548,14 +544,14 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
OUT_RING (chan, sync->addr);
OUT_RING (chan, sync->data);
} else
- if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) {
+ if (chan && chan->object->oclass < FERMI_CHANNEL_GPFIFO) {
u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
ret = RING_SPACE(chan, 12);
if (ret)
return ret;
BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
- OUT_RING (chan, chan->vram);
+ OUT_RING (chan, chan->vram.handle);
BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
OUT_RING (chan, upper_32_bits(addr ^ 0x10));
OUT_RING (chan, lower_32_bits(addr ^ 0x10));
@@ -606,16 +602,16 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
evo_data(push, sync->addr);
evo_data(push, sync->data++);
evo_data(push, sync->data);
- evo_data(push, NvEvoSync);
+ evo_data(push, sync->base.sync.handle);
evo_mthd(push, 0x00a0, 2);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
evo_mthd(push, 0x00c0, 1);
- evo_data(push, nv_fb->r_dma);
+ evo_data(push, nv_fb->r_handle);
evo_mthd(push, 0x0110, 2);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
- if (nv50_vers(sync) < NVD0_DISP_SYNC_CLASS) {
+ if (nv50_vers(sync) < GF110_DISP_BASE_CHANNEL_DMA) {
evo_mthd(push, 0x0800, 5);
evo_data(push, nv_fb->nvbo->bo.offset >> 8);
evo_data(push, 0);
@@ -667,11 +663,11 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
push = evo_wait(mast, 4);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x08a0 + (nv_crtc->index * 0x0400), 1);
evo_data(push, mode);
} else
- if (nv50_vers(mast) < NVE0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GK104_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0490 + (nv_crtc->index * 0x0300), 1);
evo_data(push, mode);
} else {
@@ -762,7 +758,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
push = evo_wait(mast, 8);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
/*XXX: SCALE_CTRL_ACTIVE??? */
evo_mthd(push, 0x08d8 + (nv_crtc->index * 0x400), 2);
evo_data(push, (oY << 16) | oX);
@@ -807,7 +803,7 @@ nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
push = evo_wait(mast, 16);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x08a8 + (nv_crtc->index * 0x400), 1);
evo_data(push, (hue << 20) | (vib << 8));
} else {
@@ -835,7 +831,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
push = evo_wait(mast, 16);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0860 + (nv_crtc->index * 0x400), 1);
evo_data(push, nvfb->nvbo->bo.offset >> 8);
evo_mthd(push, 0x0868 + (nv_crtc->index * 0x400), 3);
@@ -844,9 +840,9 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
evo_data(push, nvfb->r_format);
evo_mthd(push, 0x08c0 + (nv_crtc->index * 0x400), 1);
evo_data(push, (y << 16) | x);
- if (nv50_vers(mast) > NV50_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) > NV50_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nvfb->r_dma);
+ evo_data(push, nvfb->r_handle);
}
} else {
evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1);
@@ -855,7 +851,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
evo_data(push, (fb->height << 16) | fb->width);
evo_data(push, nvfb->r_pitch);
evo_data(push, nvfb->r_format);
- evo_data(push, nvfb->r_dma);
+ evo_data(push, nvfb->r_handle);
evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
evo_data(push, (y << 16) | x);
}
@@ -867,7 +863,7 @@ nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
evo_kick(push, mast);
}
- nv_crtc->fb.tile_flags = nvfb->r_dma;
+ nv_crtc->fb.handle = nvfb->r_handle;
return 0;
}
@@ -877,23 +873,23 @@ nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
u32 *push = evo_wait(mast, 16);
if (push) {
- if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x85000000);
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
} else
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x85000000);
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
- evo_data(push, NvEvoVRAM);
+ evo_data(push, mast->base.vram.handle);
} else {
evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2);
evo_data(push, 0x85000000);
evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
- evo_data(push, NvEvoVRAM);
+ evo_data(push, mast->base.vram.handle);
}
evo_kick(push, mast);
}
@@ -905,11 +901,11 @@ nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
u32 *push = evo_wait(mast, 16);
if (push) {
- if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x05000000);
} else
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x05000000);
evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
@@ -960,13 +956,13 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
push = evo_wait(mast, 6);
if (push) {
- if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x00000000);
evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x40000000);
} else
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
evo_data(push, 0x00000000);
evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
@@ -997,31 +993,31 @@ nv50_crtc_commit(struct drm_crtc *crtc)
push = evo_wait(mast, 32);
if (push) {
- if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, NvEvoVRAM_LP);
+ evo_data(push, nv_crtc->fb.handle);
evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0xc0000000);
evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
} else
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
- evo_data(push, nv_crtc->fb.tile_flags);
+ evo_data(push, nv_crtc->fb.handle);
evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0xc0000000);
evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
- evo_data(push, NvEvoVRAM);
+ evo_data(push, mast->base.vram.handle);
} else {
evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
- evo_data(push, nv_crtc->fb.tile_flags);
+ evo_data(push, nv_crtc->fb.handle);
evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
evo_data(push, 0x83000000);
evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
evo_data(push, 0x00000000);
evo_data(push, 0x00000000);
evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
- evo_data(push, NvEvoVRAM);
+ evo_data(push, mast->base.vram.handle);
evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
evo_data(push, 0xffffff00);
}
@@ -1099,7 +1095,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
push = evo_wait(mast, 64);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
evo_data(push, 0x00800000 | mode->clock);
evo_data(push, (ilace == 2) ? 2 : 0);
@@ -1192,7 +1188,7 @@ nv50_crtc_lut_load(struct drm_crtc *crtc)
u16 g = nv_crtc->lut.g[i] >> 2;
u16 b = nv_crtc->lut.b[i] >> 2;
- if (nv_mclass(disp->core) < NVD0_DISP_CLASS) {
+ if (disp->disp->oclass < GF110_DISP) {
writew(r + 0x0000, lut + (i * 0x08) + 0);
writew(g + 0x0000, lut + (i * 0x08) + 2);
writew(b + 0x0000, lut + (i * 0x08) + 4);
@@ -1259,8 +1255,8 @@ nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{
struct nv50_curs *curs = nv50_curs(crtc);
struct nv50_chan *chan = nv50_chan(curs);
- nv_wo32(chan->user, 0x0084, (y << 16) | (x & 0xffff));
- nv_wo32(chan->user, 0x0080, 0x00000000);
+ nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
+ nvif_wr32(&chan->user, 0x0080, 0x00000000);
return 0;
}
@@ -1287,11 +1283,16 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct nv50_disp *disp = nv50_disp(crtc->dev);
struct nv50_head *head = nv50_head(crtc);
+ struct nv50_fbdma *fbdma;
+
+ list_for_each_entry(fbdma, &disp->fbdma, head) {
+ nvif_object_fini(&fbdma->base[nv_crtc->index]);
+ }
- nv50_dmac_destroy(disp->core, &head->ovly.base);
- nv50_pioc_destroy(disp->core, &head->oimm.base);
- nv50_dmac_destroy(disp->core, &head->sync.base);
- nv50_pioc_destroy(disp->core, &head->curs.base);
+ nv50_dmac_destroy(&head->ovly.base, disp->disp);
+ nv50_pioc_destroy(&head->oimm.base);
+ nv50_dmac_destroy(&head->sync.base, disp->disp);
+ nv50_pioc_destroy(&head->curs.base);
/*XXX: this shouldn't be necessary, but the core doesn't call
* disconnect() during the cleanup paths
@@ -1346,7 +1347,7 @@ nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
}
static int
-nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
+nv50_crtc_create(struct drm_device *dev, int index)
{
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_head *head;
@@ -1395,11 +1396,7 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
nv50_crtc_lut_load(crtc);
/* allocate cursor resources */
- ret = nv50_pioc_create(disp->core, NV50_DISP_CURS_CLASS, index,
- &(struct nv50_display_curs_class) {
- .head = index,
- }, sizeof(struct nv50_display_curs_class),
- &head->curs.base);
+ ret = nv50_curs_create(disp->disp, index, &head->curs);
if (ret)
goto out;
@@ -1420,12 +1417,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
goto out;
/* allocate page flip / sync resources */
- ret = nv50_dmac_create(disp->core, NV50_DISP_SYNC_CLASS, index,
- &(struct nv50_display_sync_class) {
- .pushbuf = EVO_PUSH_HANDLE(SYNC, index),
- .head = index,
- }, sizeof(struct nv50_display_sync_class),
- disp->sync->bo.offset, &head->sync.base);
+ ret = nv50_base_create(disp->disp, index, disp->sync->bo.offset,
+ &head->sync);
if (ret)
goto out;
@@ -1433,20 +1426,12 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index)
head->sync.data = 0x00000000;
/* allocate overlay resources */
- ret = nv50_pioc_create(disp->core, NV50_DISP_OIMM_CLASS, index,
- &(struct nv50_display_oimm_class) {
- .head = index,
- }, sizeof(struct nv50_display_oimm_class),
- &head->oimm.base);
+ ret = nv50_oimm_create(disp->disp, index, &head->oimm);
if (ret)
goto out;
- ret = nv50_dmac_create(disp->core, NV50_DISP_OVLY_CLASS, index,
- &(struct nv50_display_ovly_class) {
- .pushbuf = EVO_PUSH_HANDLE(OVLY, index),
- .head = index,
- }, sizeof(struct nv50_display_ovly_class),
- disp->sync->bo.offset, &head->ovly.base);
+ ret = nv50_ovly_create(disp->disp, index, disp->sync->bo.offset,
+ &head->ovly);
if (ret)
goto out;
@@ -1464,16 +1449,23 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
- int or = nv_encoder->or;
- u32 dpms_ctrl;
-
- dpms_ctrl = 0x00000000;
- if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF)
- dpms_ctrl |= 0x00000001;
- if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF)
- dpms_ctrl |= 0x00000004;
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_dac_pwr_v0 pwr;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_DAC_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ .pwr.state = 1,
+ .pwr.data = 1,
+ .pwr.vsync = (mode != DRM_MODE_DPMS_SUSPEND &&
+ mode != DRM_MODE_DPMS_OFF),
+ .pwr.hsync = (mode != DRM_MODE_DPMS_STANDBY &&
+ mode != DRM_MODE_DPMS_OFF),
+ };
- nv_call(disp->core, NV50_DISP_DAC_PWR + or, dpms_ctrl);
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
static bool
@@ -1514,7 +1506,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
push = evo_wait(mast, 8);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
u32 syncs = 0x00000000;
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
@@ -1563,7 +1555,7 @@ nv50_dac_disconnect(struct drm_encoder *encoder)
push = evo_wait(mast, 4);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0400 + (or * 0x080), 1);
evo_data(push, 0x00000000);
} else {
@@ -1580,14 +1572,25 @@ nv50_dac_disconnect(struct drm_encoder *encoder)
static enum drm_connector_status
nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
- int ret, or = nouveau_encoder(encoder)->or;
- u32 load = nouveau_drm(encoder->dev)->vbios.dactestval;
- if (load == 0)
- load = 340;
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_dac_load_v0 load;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_DAC_LOAD,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ };
+ int ret;
+
+ args.load.data = nouveau_drm(encoder->dev)->vbios.dactestval;
+ if (args.load.data == 0)
+ args.load.data = 340;
- ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
- if (ret || !load)
+ ret = nvif_mthd(disp->disp, 0, &args, sizeof(args));
+ if (ret || !args.load.load)
return connector_status_disconnected;
return connector_status_connected;
@@ -1619,7 +1622,7 @@ static int
nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
int type = DRM_MODE_ENCODER_DAC;
@@ -1650,16 +1653,25 @@ nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_connector *nv_connector;
struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_hda_eld_v0 eld;
+ u8 data[sizeof(nv_connector->base.eld)];
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ };
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (!drm_detect_monitor_audio(nv_connector->edid))
return;
drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
+ memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
- nv_exec(disp->core, NVA3_DISP_SOR_HDA_ELD + nv_encoder->or,
- nv_connector->base.eld,
- nv_connector->base.eld[2] * 4);
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
static void
@@ -1667,8 +1679,17 @@ nv50_audio_disconnect(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_hda_eld_v0 eld;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ };
- nv_exec(disp->core, NVA3_DISP_SOR_HDA_ELD + nv_encoder->or, NULL, 0);
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
/******************************************************************************
@@ -1679,10 +1700,20 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
- struct nouveau_connector *nv_connector;
struct nv50_disp *disp = nv50_disp(encoder->dev);
- const u32 moff = (nv_crtc->index << 3) | nv_encoder->or;
- u32 rekey = 56; /* binary driver, and tegra constant */
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
+ (0x0100 << nv_crtc->index),
+ .pwr.state = 1,
+ .pwr.rekey = 56, /* binary driver, and tegra, constant */
+ };
+ struct nouveau_connector *nv_connector;
u32 max_ac_packet;
nv_connector = nouveau_encoder_connector_get(nv_encoder);
@@ -1690,14 +1721,11 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
return;
max_ac_packet = mode->htotal - mode->hdisplay;
- max_ac_packet -= rekey;
+ max_ac_packet -= args.pwr.rekey;
max_ac_packet -= 18; /* constant from tegra */
- max_ac_packet /= 32;
-
- nv_call(disp->core, NV84_DISP_SOR_HDMI_PWR + moff,
- NV84_DISP_SOR_HDMI_PWR_STATE_ON |
- (max_ac_packet << 16) | rekey);
+ args.pwr.max_ac_packet = max_ac_packet / 32;
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
nv50_audio_mode_set(encoder, mode);
}
@@ -1706,11 +1734,20 @@ nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
- const u32 moff = (nv_crtc->index << 3) | nv_encoder->or;
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
+ (0x0100 << nv_crtc->index),
+ };
nv50_audio_disconnect(encoder);
- nv_call(disp->core, NV84_DISP_SOR_HDMI_PWR + moff, 0x00000000);
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
/******************************************************************************
@@ -1720,10 +1757,29 @@ static void
nv50_sor_dpms(struct drm_encoder *encoder, int mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_pwr_v0 pwr;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ .pwr.state = mode == DRM_MODE_DPMS_ON,
+ };
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_dp_pwr_v0 pwr;
+ } link = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_DP_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ .pwr.state = mode == DRM_MODE_DPMS_ON,
+ };
struct drm_device *dev = encoder->dev;
- struct nv50_disp *disp = nv50_disp(dev);
struct drm_encoder *partner;
- u32 mthd;
nv_encoder->last_dpms = mode;
@@ -1741,18 +1797,13 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
}
}
- mthd = (ffs(nv_encoder->dcb->heads) - 1) << 3;
- mthd |= (ffs(nv_encoder->dcb->sorconf.link) - 1) << 2;
- mthd |= nv_encoder->or;
-
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
- nv_call(disp->core, NV50_DISP_SOR_PWR | mthd, 1);
- mthd |= NV94_DISP_SOR_DP_PWR;
+ args.pwr.state = 1;
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
+ nvif_mthd(disp->disp, 0, &link, sizeof(link));
} else {
- mthd |= NV50_DISP_SOR_PWR;
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
-
- nv_call(disp->core, mthd, (mode == DRM_MODE_DPMS_ON));
}
static bool
@@ -1781,7 +1832,7 @@ nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data)
struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev);
u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push;
if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1);
evo_data(push, (nv_encoder->ctrl = temp));
} else {
@@ -1817,15 +1868,24 @@ static void
nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
struct drm_display_mode *mode)
{
+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_sor_lvds_script_v0 lvds;
+ } lvds = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ };
struct nv50_disp *disp = nv50_disp(encoder->dev);
struct nv50_mast *mast = nv50_mast(encoder->dev);
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nouveau_connector *nv_connector;
struct nvbios *bios = &drm->vbios;
- u32 lvds = 0, mask, ctrl;
+ u32 mask, ctrl;
u8 owner = 1 << nv_crtc->index;
u8 proto = 0xf;
u8 depth = 0x0;
@@ -1851,31 +1911,31 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
if (bios->fp_no_ddc) {
if (bios->fp.dual_link)
- lvds |= 0x0100;
+ lvds.lvds.script |= 0x0100;
if (bios->fp.if_is_24bit)
- lvds |= 0x0200;
+ lvds.lvds.script |= 0x0200;
} else {
if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
if (((u8 *)nv_connector->edid)[121] == 2)
- lvds |= 0x0100;
+ lvds.lvds.script |= 0x0100;
} else
if (mode->clock >= bios->fp.duallink_transition_clk) {
- lvds |= 0x0100;
+ lvds.lvds.script |= 0x0100;
}
- if (lvds & 0x0100) {
+ if (lvds.lvds.script & 0x0100) {
if (bios->fp.strapless_is_24bit & 2)
- lvds |= 0x0200;
+ lvds.lvds.script |= 0x0200;
} else {
if (bios->fp.strapless_is_24bit & 1)
- lvds |= 0x0200;
+ lvds.lvds.script |= 0x0200;
}
if (nv_connector->base.display_info.bpc == 8)
- lvds |= 0x0200;
+ lvds.lvds.script |= 0x0200;
}
- nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, lvds);
+ nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
break;
case DCB_OUTPUT_DP:
if (nv_connector->base.display_info.bpc == 6) {
@@ -1902,7 +1962,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON);
- if (nv50_vers(mast) >= NVD0_DISP_CLASS) {
+ if (nv50_vers(mast) >= GF110_DISP) {
u32 *push = evo_wait(mast, 3);
if (push) {
u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
@@ -1961,7 +2021,7 @@ static int
nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
int type;
@@ -2002,9 +2062,19 @@ nv50_pior_dpms(struct drm_encoder *encoder, int mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nv50_disp *disp = nv50_disp(encoder->dev);
- u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or;
- u32 ctrl = (mode == DRM_MODE_DPMS_ON);
- nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl);
+ struct {
+ struct nv50_disp_mthd_v1 base;
+ struct nv50_disp_pior_pwr_v0 pwr;
+ } args = {
+ .base.version = 1,
+ .base.method = NV50_DISP_MTHD_V1_PIOR_PWR,
+ .base.hasht = nv_encoder->dcb->hasht,
+ .base.hashm = nv_encoder->dcb->hashm,
+ .pwr.state = mode == DRM_MODE_DPMS_ON,
+ .pwr.type = nv_encoder->dcb->type,
+ };
+
+ nvif_mthd(disp->disp, 0, &args, sizeof(args));
}
static bool
@@ -2067,7 +2137,7 @@ nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
push = evo_wait(mast, 8);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
u32 ctrl = (depth << 16) | (proto << 8) | owner;
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
ctrl |= 0x00001000;
@@ -2096,7 +2166,7 @@ nv50_pior_disconnect(struct drm_encoder *encoder)
push = evo_wait(mast, 4);
if (push) {
- if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) {
+ if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
evo_mthd(push, 0x0700 + (or * 0x040), 1);
evo_data(push, 0x00000000);
}
@@ -2132,7 +2202,7 @@ static int
nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
- struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c *i2c = nvkm_i2c(&drm->device);
struct nouveau_i2c_port *ddc = NULL;
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
@@ -2169,8 +2239,151 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
}
/******************************************************************************
+ * Framebuffer
+ *****************************************************************************/
+
+static void
+nv50_fbdma_fini(struct nv50_fbdma *fbdma)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(fbdma->base); i++)
+ nvif_object_fini(&fbdma->base[i]);
+ nvif_object_fini(&fbdma->core);
+ list_del(&fbdma->head);
+ kfree(fbdma);
+}
+
+static int
+nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kind)
+{
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nv50_disp *disp = nv50_disp(dev);
+ struct nv50_mast *mast = nv50_mast(dev);
+ struct __attribute__ ((packed)) {
+ struct nv_dma_v0 base;
+ union {
+ struct nv50_dma_v0 nv50;
+ struct gf100_dma_v0 gf100;
+ struct gf110_dma_v0 gf110;
+ };
+ } args = {};
+ struct nv50_fbdma *fbdma;
+ struct drm_crtc *crtc;
+ u32 size = sizeof(args.base);
+ int ret;
+
+ list_for_each_entry(fbdma, &disp->fbdma, head) {
+ if (fbdma->core.handle == name)
+ return 0;
+ }
+
+ fbdma = kzalloc(sizeof(*fbdma), GFP_KERNEL);
+ if (!fbdma)
+ return -ENOMEM;
+ list_add(&fbdma->head, &disp->fbdma);
+
+ args.base.target = NV_DMA_V0_TARGET_VRAM;
+ args.base.access = NV_DMA_V0_ACCESS_RDWR;
+ args.base.start = offset;
+ args.base.limit = offset + length - 1;
+
+ if (drm->device.info.chipset < 0x80) {
+ args.nv50.part = NV50_DMA_V0_PART_256;
+ size += sizeof(args.nv50);
+ } else
+ if (drm->device.info.chipset < 0xc0) {
+ args.nv50.part = NV50_DMA_V0_PART_256;
+ args.nv50.kind = kind;
+ size += sizeof(args.nv50);
+ } else
+ if (drm->device.info.chipset < 0xd0) {
+ args.gf100.kind = kind;
+ size += sizeof(args.gf100);
+ } else {
+ args.gf110.page = GF110_DMA_V0_PAGE_LP;
+ args.gf110.kind = kind;
+ size += sizeof(args.gf110);
+ }
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nv50_head *head = nv50_head(crtc);
+ int ret = nvif_object_init(&head->sync.base.base.user, NULL,
+ name, NV_DMA_IN_MEMORY, &args, size,
+ &fbdma->base[head->base.index]);
+ if (ret) {
+ nv50_fbdma_fini(fbdma);
+ return ret;
+ }
+ }
+
+ ret = nvif_object_init(&mast->base.base.user, NULL, name,
+ NV_DMA_IN_MEMORY, &args, size,
+ &fbdma->core);
+ if (ret) {
+ nv50_fbdma_fini(fbdma);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void
+nv50_fb_dtor(struct drm_framebuffer *fb)
+{
+}
+
+static int
+nv50_fb_ctor(struct drm_framebuffer *fb)
+{
+ struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+ struct nouveau_drm *drm = nouveau_drm(fb->dev);
+ struct nouveau_bo *nvbo = nv_fb->nvbo;
+ struct nv50_disp *disp = nv50_disp(fb->dev);
+ u8 kind = nouveau_bo_tile_layout(nvbo) >> 8;
+ u8 tile = nvbo->tile_mode;
+
+ if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) {
+ NV_ERROR(drm, "framebuffer requires contiguous bo\n");
+ return -EINVAL;
+ }
+
+ if (drm->device.info.chipset >= 0xc0)
+ tile >>= 4; /* yep.. */
+
+ switch (fb->depth) {
+ case 8: nv_fb->r_format = 0x1e00; break;
+ case 15: nv_fb->r_format = 0xe900; break;
+ case 16: nv_fb->r_format = 0xe800; break;
+ case 24:
+ case 32: nv_fb->r_format = 0xcf00; break;
+ case 30: nv_fb->r_format = 0xd100; break;
+ default:
+ NV_ERROR(drm, "unknown depth %d\n", fb->depth);
+ return -EINVAL;
+ }
+
+ if (disp->disp->oclass < G82_DISP) {
+ nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
+ (fb->pitches[0] | 0x00100000);
+ nv_fb->r_format |= kind << 16;
+ } else
+ if (disp->disp->oclass < GF110_DISP) {
+ nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
+ (fb->pitches[0] | 0x00100000);
+ } else {
+ nv_fb->r_pitch = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
+ (fb->pitches[0] | 0x01000000);
+ }
+ nv_fb->r_handle = 0xffff0000 | kind;
+
+ return nv50_fbdma_init(fb->dev, nv_fb->r_handle, 0,
+ drm->device.info.ram_user, kind);
+}
+
+/******************************************************************************
* Init
*****************************************************************************/
+
void
nv50_display_fini(struct drm_device *dev)
{
@@ -2193,7 +2406,7 @@ nv50_display_init(struct drm_device *dev)
}
evo_mthd(push, 0x0088, 1);
- evo_data(push, NvEvoSync);
+ evo_data(push, nv50_mast(dev)->base.sync.handle);
evo_kick(push, nv50_mast(dev));
return 0;
}
@@ -2202,8 +2415,13 @@ void
nv50_display_destroy(struct drm_device *dev)
{
struct nv50_disp *disp = nv50_disp(dev);
+ struct nv50_fbdma *fbdma, *fbtmp;
+
+ list_for_each_entry_safe(fbdma, fbtmp, &disp->fbdma, head) {
+ nv50_fbdma_fini(fbdma);
+ }
- nv50_dmac_destroy(disp->core, &disp->mast.base);
+ nv50_dmac_destroy(&disp->mast.base, disp->disp);
nouveau_bo_unmap(disp->sync);
if (disp->sync)
@@ -2217,7 +2435,7 @@ nv50_display_destroy(struct drm_device *dev)
int
nv50_display_create(struct drm_device *dev)
{
- struct nouveau_device *device = nouveau_dev(dev);
+ struct nvif_device *device = &nouveau_drm(dev)->device;
struct nouveau_drm *drm = nouveau_drm(dev);
struct dcb_table *dcb = &drm->vbios.dcb;
struct drm_connector *connector, *tmp;
@@ -2228,12 +2446,15 @@ nv50_display_create(struct drm_device *dev)
disp = kzalloc(sizeof(*disp), GFP_KERNEL);
if (!disp)
return -ENOMEM;
+ INIT_LIST_HEAD(&disp->fbdma);
nouveau_display(dev)->priv = disp;
nouveau_display(dev)->dtor = nv50_display_destroy;
nouveau_display(dev)->init = nv50_display_init;
nouveau_display(dev)->fini = nv50_display_fini;
- disp->core = nouveau_display(dev)->core;
+ nouveau_display(dev)->fb_ctor = nv50_fb_ctor;
+ nouveau_display(dev)->fb_dtor = nv50_fb_dtor;
+ disp->disp = &nouveau_display(dev)->disp;
/* small shared memory area we use for notifiers and semaphores */
ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2253,22 +2474,19 @@ nv50_display_create(struct drm_device *dev)
goto out;
/* allocate master evo channel */
- ret = nv50_dmac_create(disp->core, NV50_DISP_MAST_CLASS, 0,
- &(struct nv50_display_mast_class) {
- .pushbuf = EVO_PUSH_HANDLE(MAST, 0),
- }, sizeof(struct nv50_display_mast_class),
- disp->sync->bo.offset, &disp->mast.base);
+ ret = nv50_core_create(disp->disp, disp->sync->bo.offset,
+ &disp->mast);
if (ret)
goto out;
/* create crtc objects to represent the hw heads */
- if (nv_mclass(disp->core) >= NVD0_DISP_CLASS)
- crtcs = nv_rd32(device, 0x022448);
+ if (disp->disp->oclass >= GF110_DISP)
+ crtcs = nvif_rd32(device, 0x022448);
else
crtcs = 2;
for (i = 0; i < crtcs; i++) {
- ret = nv50_crtc_create(dev, disp->core, i);
+ ret = nv50_crtc_create(dev, i);
if (ret)
goto out;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 52068a0910dc..394c89abcc97 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -154,7 +154,6 @@ nv50_fbcon_accel_init(struct fb_info *info)
struct drm_device *dev = nfbdev->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
- struct nouveau_object *object;
int ret, format;
switch (info->var.bits_per_pixel) {
@@ -184,8 +183,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
return -EINVAL;
}
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D,
- 0x502d, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x502d, 0x502d, NULL, 0,
+ &nfbdev->twod);
if (ret)
return ret;
@@ -196,11 +195,11 @@ nv50_fbcon_accel_init(struct fb_info *info)
}
BEGIN_NV04(chan, NvSub2D, 0x0000, 1);
- OUT_RING(chan, Nv2D);
+ OUT_RING(chan, nfbdev->twod.handle);
BEGIN_NV04(chan, NvSub2D, 0x0184, 3);
- OUT_RING(chan, NvDmaFB);
- OUT_RING(chan, NvDmaFB);
- OUT_RING(chan, NvDmaFB);
+ OUT_RING(chan, chan->vram.handle);
+ OUT_RING(chan, chan->vram.handle);
+ OUT_RING(chan, chan->vram.handle);
BEGIN_NV04(chan, NvSub2D, 0x0290, 1);
OUT_RING(chan, 0);
BEGIN_NV04(chan, NvSub2D, 0x0888, 1);
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index 0ee363840035..195cf51a7c31 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -22,8 +22,8 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
-#include <core/object.h>
-#include <core/class.h>
+#include <nvif/os.h>
+#include <nvif/class.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
@@ -38,7 +38,6 @@ nv50_fence_context_new(struct nouveau_channel *chan)
struct nv10_fence_priv *priv = chan->drm->fence;
struct nv10_fence_chan *fctx;
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
- struct nouveau_object *object;
u32 start = mem->start * PAGE_SIZE;
u32 limit = start + mem->size - 1;
int ret, i;
@@ -52,15 +51,14 @@ nv50_fence_context_new(struct nouveau_channel *chan)
fctx->base.read = nv10_fence_read;
fctx->base.sync = nv17_fence_sync;
- ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
- NvSema, 0x003d,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(chan->object, NULL, NvSema, NV_DMA_IN_MEMORY,
+ &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = start,
.limit = limit,
- }, sizeof(struct nv_dma_class),
- &object);
+ }, sizeof(struct nv_dma_v0),
+ &fctx->sema);
/* dma objects for display sync channel semaphore blocks */
for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
@@ -68,15 +66,14 @@ nv50_fence_context_new(struct nouveau_channel *chan)
u32 start = bo->bo.mem.start * PAGE_SIZE;
u32 limit = start + bo->bo.mem.size - 1;
- ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
- NvEvoSema0 + i, 0x003d,
- &(struct nv_dma_class) {
- .flags = NV_DMA_TARGET_VRAM |
- NV_DMA_ACCESS_RDWR,
+ ret = nvif_object_init(chan->object, NULL, NvEvoSema0 + i,
+ NV_DMA_IN_MEMORY, &(struct nv_dma_v0) {
+ .target = NV_DMA_V0_TARGET_VRAM,
+ .access = NV_DMA_V0_ACCESS_RDWR,
.start = start,
.limit = limit,
- }, sizeof(struct nv_dma_class),
- &object);
+ }, sizeof(struct nv_dma_v0),
+ &fctx->head[i]);
}
if (ret)
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 9fd475c89820..933a779c93ab 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -22,12 +22,6 @@
* Authors: Ben Skeggs
*/
-#include <core/object.h>
-#include <core/client.h>
-#include <core/class.h>
-
-#include <engine/fifo.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
@@ -47,7 +41,7 @@ nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
int ret = RING_SPACE(chan, 8);
if (ret == 0) {
BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
- OUT_RING (chan, chan->vram);
+ OUT_RING (chan, chan->vram.handle);
BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5);
OUT_RING (chan, upper_32_bits(virtual));
OUT_RING (chan, lower_32_bits(virtual));
@@ -65,7 +59,7 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
int ret = RING_SPACE(chan, 7);
if (ret == 0) {
BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
- OUT_RING (chan, chan->vram);
+ OUT_RING (chan, chan->vram.handle);
BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
OUT_RING (chan, upper_32_bits(virtual));
OUT_RING (chan, lower_32_bits(virtual));
@@ -81,8 +75,7 @@ nv84_fence_emit(struct nouveau_fence *fence)
{
struct nouveau_channel *chan = fence->channel;
struct nv84_fence_chan *fctx = chan->fence;
- struct nouveau_fifo_chan *fifo = (void *)chan->object;
- u64 addr = fifo->chid * 16;
+ u64 addr = chan->chid * 16;
if (fence->sysmem)
addr += fctx->vma_gart.offset;
@@ -97,8 +90,7 @@ nv84_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *prev, struct nouveau_channel *chan)
{
struct nv84_fence_chan *fctx = chan->fence;
- struct nouveau_fifo_chan *fifo = (void *)prev->object;
- u64 addr = fifo->chid * 16;
+ u64 addr = prev->chid * 16;
if (fence->sysmem)
addr += fctx->vma_gart.offset;
@@ -111,9 +103,8 @@ nv84_fence_sync(struct nouveau_fence *fence,
static u32
nv84_fence_read(struct nouveau_channel *chan)
{
- struct nouveau_fifo_chan *fifo = (void *)chan->object;
struct nv84_fence_priv *priv = chan->drm->fence;
- return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4);
+ return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
}
static void
@@ -139,8 +130,7 @@ nv84_fence_context_del(struct nouveau_channel *chan)
int
nv84_fence_context_new(struct nouveau_channel *chan)
{
- struct nouveau_fifo_chan *fifo = (void *)chan->object;
- struct nouveau_client *client = nouveau_client(fifo);
+ struct nouveau_cli *cli = (void *)nvif_client(&chan->device->base);
struct nv84_fence_priv *priv = chan->drm->fence;
struct nv84_fence_chan *fctx;
int ret, i;
@@ -156,19 +146,19 @@ nv84_fence_context_new(struct nouveau_channel *chan)
fctx->base.emit32 = nv84_fence_emit32;
fctx->base.sync32 = nv84_fence_sync32;
- ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma);
+ ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
if (ret == 0) {
- ret = nouveau_bo_vma_add(priv->bo_gart, client->vm,
+ ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
&fctx->vma_gart);
}
/* map display semaphore buffers into channel's vm */
for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
- ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]);
+ ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
}
- nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000);
+ nouveau_bo_wr32(priv->bo, chan->chid * 16/4, 0x00000000);
if (ret)
nv84_fence_context_del(chan);
@@ -178,7 +168,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
static bool
nv84_fence_suspend(struct nouveau_drm *drm)
{
- struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+ struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
struct nv84_fence_priv *priv = drm->fence;
int i;
@@ -194,7 +184,7 @@ nv84_fence_suspend(struct nouveau_drm *drm)
static void
nv84_fence_resume(struct nouveau_drm *drm)
{
- struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+ struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
struct nv84_fence_priv *priv = drm->fence;
int i;
@@ -225,7 +215,7 @@ nv84_fence_destroy(struct nouveau_drm *drm)
int
nv84_fence_create(struct nouveau_drm *drm)
{
- struct nouveau_fifo *pfifo = nouveau_fifo(drm->device);
+ struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
struct nv84_fence_priv *priv;
int ret;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index 9dcd30f3e1e0..61246677e8dc 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -154,11 +154,10 @@ nvc0_fbcon_accel_init(struct fb_info *info)
struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_channel *chan = drm->channel;
- struct nouveau_object *object;
int ret, format;
- ret = nouveau_object_new(nv_object(chan->cli), NVDRM_CHAN, Nv2D,
- 0x902d, NULL, 0, &object);
+ ret = nvif_object_init(chan->object, NULL, 0x902d, 0x902d, NULL, 0,
+ &nfbdev->twod);
if (ret)
return ret;
@@ -197,7 +196,7 @@ nvc0_fbcon_accel_init(struct fb_info *info)
}
BEGIN_NVC0(chan, NvSub2D, 0x0000, 1);
- OUT_RING (chan, 0x0000902d);
+ OUT_RING (chan, nfbdev->twod.handle);
BEGIN_NVC0(chan, NvSub2D, 0x0290, 1);
OUT_RING (chan, 0);
BEGIN_NVC0(chan, NvSub2D, 0x0888, 1);
diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c
index 9566267fbc42..becf19abda2d 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fence.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fence.c
@@ -22,12 +22,6 @@
* Authors: Ben Skeggs
*/
-#include <core/object.h>
-#include <core/client.h>
-#include <core/class.h>
-
-#include <engine/fifo.h>
-
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_fence.h"
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h
new file mode 100644
index 000000000000..573491f84792
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/class.h
@@ -0,0 +1,558 @@
+#ifndef __NVIF_CLASS_H__
+#define __NVIF_CLASS_H__
+
+/*******************************************************************************
+ * class identifiers
+ ******************************************************************************/
+
+/* the below match nvidia-assigned (either in hw, or sw) class numbers */
+#define NV_DEVICE 0x00000080
+
+#define NV_DMA_FROM_MEMORY 0x00000002
+#define NV_DMA_TO_MEMORY 0x00000003
+#define NV_DMA_IN_MEMORY 0x0000003d
+
+#define NV04_DISP 0x00000046
+
+#define NV03_CHANNEL_DMA 0x0000006b
+#define NV10_CHANNEL_DMA 0x0000006e
+#define NV17_CHANNEL_DMA 0x0000176e
+#define NV40_CHANNEL_DMA 0x0000406e
+#define NV50_CHANNEL_DMA 0x0000506e
+#define G82_CHANNEL_DMA 0x0000826e
+
+#define NV50_CHANNEL_GPFIFO 0x0000506f
+#define G82_CHANNEL_GPFIFO 0x0000826f
+#define FERMI_CHANNEL_GPFIFO 0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A 0x0000a06f
+
+#define NV50_DISP 0x00005070
+#define G82_DISP 0x00008270
+#define GT200_DISP 0x00008370
+#define GT214_DISP 0x00008570
+#define GT206_DISP 0x00008870
+#define GF110_DISP 0x00009070
+#define GK104_DISP 0x00009170
+#define GK110_DISP 0x00009270
+#define GM107_DISP 0x00009470
+
+#define NV50_DISP_CURSOR 0x0000507a
+#define G82_DISP_CURSOR 0x0000827a
+#define GT214_DISP_CURSOR 0x0000857a
+#define GF110_DISP_CURSOR 0x0000907a
+#define GK104_DISP_CURSOR 0x0000917a
+
+#define NV50_DISP_OVERLAY 0x0000507b
+#define G82_DISP_OVERLAY 0x0000827b
+#define GT214_DISP_OVERLAY 0x0000857b
+#define GF110_DISP_OVERLAY 0x0000907b
+#define GK104_DISP_OVERLAY 0x0000917b
+
+#define NV50_DISP_BASE_CHANNEL_DMA 0x0000507c
+#define G82_DISP_BASE_CHANNEL_DMA 0x0000827c
+#define GT200_DISP_BASE_CHANNEL_DMA 0x0000837c
+#define GT214_DISP_BASE_CHANNEL_DMA 0x0000857c
+#define GF110_DISP_BASE_CHANNEL_DMA 0x0000907c
+#define GK104_DISP_BASE_CHANNEL_DMA 0x0000917c
+#define GK110_DISP_BASE_CHANNEL_DMA 0x0000927c
+
+#define NV50_DISP_CORE_CHANNEL_DMA 0x0000507d
+#define G82_DISP_CORE_CHANNEL_DMA 0x0000827d
+#define GT200_DISP_CORE_CHANNEL_DMA 0x0000837d
+#define GT214_DISP_CORE_CHANNEL_DMA 0x0000857d
+#define GT206_DISP_CORE_CHANNEL_DMA 0x0000887d
+#define GF110_DISP_CORE_CHANNEL_DMA 0x0000907d
+#define GK104_DISP_CORE_CHANNEL_DMA 0x0000917d
+#define GK110_DISP_CORE_CHANNEL_DMA 0x0000927d
+#define GM107_DISP_CORE_CHANNEL_DMA 0x0000947d
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA 0x0000507e
+#define G82_DISP_OVERLAY_CHANNEL_DMA 0x0000827e
+#define GT200_DISP_OVERLAY_CHANNEL_DMA 0x0000837e
+#define GT214_DISP_OVERLAY_CHANNEL_DMA 0x0000857e
+#define GF110_DISP_OVERLAY_CONTROL_DMA 0x0000907e
+#define GK104_DISP_OVERLAY_CONTROL_DMA 0x0000917e
+
+#define FERMI_A 0x00009097
+#define FERMI_B 0x00009197
+#define FERMI_C 0x00009297
+
+#define KEPLER_A 0x0000a097
+#define KEPLER_B 0x0000a197
+#define KEPLER_C 0x0000a297
+
+#define MAXWELL_A 0x0000b097
+
+#define FERMI_COMPUTE_A 0x000090c0
+#define FERMI_COMPUTE_B 0x000091c0
+
+#define KEPLER_COMPUTE_A 0x0000a0c0
+#define KEPLER_COMPUTE_B 0x0000a1c0
+
+#define MAXWELL_COMPUTE_A 0x0000b0c0
+
+
+/*******************************************************************************
+ * client
+ ******************************************************************************/
+
+#define NV_CLIENT_DEVLIST 0x00
+
+struct nv_client_devlist_v0 {
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ __u64 device[];
+};
+
+
+/*******************************************************************************
+ * device
+ ******************************************************************************/
+
+struct nv_device_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 device; /* device identifier, ~0 for client default */
+#define NV_DEVICE_V0_DISABLE_IDENTIFY 0x0000000000000001ULL
+#define NV_DEVICE_V0_DISABLE_MMIO 0x0000000000000002ULL
+#define NV_DEVICE_V0_DISABLE_VBIOS 0x0000000000000004ULL
+#define NV_DEVICE_V0_DISABLE_CORE 0x0000000000000008ULL
+#define NV_DEVICE_V0_DISABLE_DISP 0x0000000000010000ULL
+#define NV_DEVICE_V0_DISABLE_FIFO 0x0000000000020000ULL
+#define NV_DEVICE_V0_DISABLE_GRAPH 0x0000000100000000ULL
+#define NV_DEVICE_V0_DISABLE_MPEG 0x0000000200000000ULL
+#define NV_DEVICE_V0_DISABLE_ME 0x0000000400000000ULL
+#define NV_DEVICE_V0_DISABLE_VP 0x0000000800000000ULL
+#define NV_DEVICE_V0_DISABLE_CRYPT 0x0000001000000000ULL
+#define NV_DEVICE_V0_DISABLE_BSP 0x0000002000000000ULL
+#define NV_DEVICE_V0_DISABLE_PPP 0x0000004000000000ULL
+#define NV_DEVICE_V0_DISABLE_COPY0 0x0000008000000000ULL
+#define NV_DEVICE_V0_DISABLE_COPY1 0x0000010000000000ULL
+#define NV_DEVICE_V0_DISABLE_VIC 0x0000020000000000ULL
+#define NV_DEVICE_V0_DISABLE_VENC 0x0000040000000000ULL
+ __u64 disable; /* disable particular subsystems */
+ __u64 debug0; /* as above, but *internal* ids, and *NOT* ABI */
+};
+
+#define NV_DEVICE_V0_INFO 0x00
+
+struct nv_device_info_v0 {
+ __u8 version;
+#define NV_DEVICE_INFO_V0_IGP 0x00
+#define NV_DEVICE_INFO_V0_PCI 0x01
+#define NV_DEVICE_INFO_V0_AGP 0x02
+#define NV_DEVICE_INFO_V0_PCIE 0x03
+#define NV_DEVICE_INFO_V0_SOC 0x04
+ __u8 platform;
+ __u16 chipset; /* from NV_PMC_BOOT_0 */
+ __u8 revision; /* from NV_PMC_BOOT_0 */
+#define NV_DEVICE_INFO_V0_TNT 0x01
+#define NV_DEVICE_INFO_V0_CELSIUS 0x02
+#define NV_DEVICE_INFO_V0_KELVIN 0x03
+#define NV_DEVICE_INFO_V0_RANKINE 0x04
+#define NV_DEVICE_INFO_V0_CURIE 0x05
+#define NV_DEVICE_INFO_V0_TESLA 0x06
+#define NV_DEVICE_INFO_V0_FERMI 0x07
+#define NV_DEVICE_INFO_V0_KEPLER 0x08
+#define NV_DEVICE_INFO_V0_MAXWELL 0x09
+ __u8 family;
+ __u8 pad06[2];
+ __u64 ram_size;
+ __u64 ram_user;
+};
+
+
+/*******************************************************************************
+ * context dma
+ ******************************************************************************/
+
+struct nv_dma_v0 {
+ __u8 version;
+#define NV_DMA_V0_TARGET_VM 0x00
+#define NV_DMA_V0_TARGET_VRAM 0x01
+#define NV_DMA_V0_TARGET_PCI 0x02
+#define NV_DMA_V0_TARGET_PCI_US 0x03
+#define NV_DMA_V0_TARGET_AGP 0x04
+ __u8 target;
+#define NV_DMA_V0_ACCESS_VM 0x00
+#define NV_DMA_V0_ACCESS_RD 0x01
+#define NV_DMA_V0_ACCESS_WR 0x02
+#define NV_DMA_V0_ACCESS_RDWR (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
+ __u8 access;
+ __u8 pad03[5];
+ __u64 start;
+ __u64 limit;
+ /* ... chipset-specific class data */
+};
+
+struct nv50_dma_v0 {
+ __u8 version;
+#define NV50_DMA_V0_PRIV_VM 0x00
+#define NV50_DMA_V0_PRIV_US 0x01
+#define NV50_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define NV50_DMA_V0_PART_VM 0x00
+#define NV50_DMA_V0_PART_256 0x01
+#define NV50_DMA_V0_PART_1KB 0x02
+ __u8 part;
+#define NV50_DMA_V0_COMP_NONE 0x00
+#define NV50_DMA_V0_COMP_1 0x01
+#define NV50_DMA_V0_COMP_2 0x02
+#define NV50_DMA_V0_COMP_VM 0x03
+ __u8 comp;
+#define NV50_DMA_V0_KIND_PITCH 0x00
+#define NV50_DMA_V0_KIND_VM 0x7f
+ __u8 kind;
+ __u8 pad05[3];
+};
+
+struct gf100_dma_v0 {
+ __u8 version;
+#define GF100_DMA_V0_PRIV_VM 0x00
+#define GF100_DMA_V0_PRIV_US 0x01
+#define GF100_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define GF100_DMA_V0_KIND_PITCH 0x00
+#define GF100_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+
+struct gf110_dma_v0 {
+ __u8 version;
+#define GF110_DMA_V0_PAGE_LP 0x00
+#define GF110_DMA_V0_PAGE_SP 0x01
+ __u8 page;
+#define GF110_DMA_V0_KIND_PITCH 0x00
+#define GF110_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+
+
+/*******************************************************************************
+ * perfmon
+ ******************************************************************************/
+
+struct nvif_perfctr_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 logic_op;
+ __u8 pad04[4];
+ char name[4][64];
+};
+
+#define NVIF_PERFCTR_V0_QUERY 0x00
+#define NVIF_PERFCTR_V0_SAMPLE 0x01
+#define NVIF_PERFCTR_V0_READ 0x02
+
+struct nvif_perfctr_query_v0 {
+ __u8 version;
+ __u8 pad01[3];
+ __u32 iter;
+ char name[64];
+};
+
+struct nvif_perfctr_sample {
+};
+
+struct nvif_perfctr_read_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u32 ctr;
+ __u32 clk;
+};
+
+
+/*******************************************************************************
+ * device control
+ ******************************************************************************/
+
+#define NVIF_CONTROL_PSTATE_INFO 0x00
+#define NVIF_CONTROL_PSTATE_ATTR 0x01
+#define NVIF_CONTROL_PSTATE_USER 0x02
+
+struct nvif_control_pstate_info_v0 {
+ __u8 version;
+ __u8 count; /* out: number of power states */
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON (-2)
+ __s8 ustate_ac; /* out: target pstate index */
+ __s8 ustate_dc; /* out: target pstate index */
+ __s8 pwrsrc; /* out: current power source */
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON (-2)
+ __s8 pstate; /* out: current pstate index */
+ __u8 pad06[2];
+};
+
+struct nvif_control_pstate_attr_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT (-1)
+ __s8 state; /* in: index of pstate to query
+ * out: pstate identifier
+ */
+ __u8 index; /* in: index of attribute to query
+ * out: index of next attribute, or 0 if no more
+ */
+ __u8 pad03[5];
+ __u32 min;
+ __u32 max;
+ char name[32];
+ char unit[16];
+};
+
+struct nvif_control_pstate_user_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON (-2)
+ __s8 ustate; /* in: pstate identifier */
+ __s8 pwrsrc; /* in: target power source */
+ __u8 pad03[5];
+};
+
+
+/*******************************************************************************
+ * DMA FIFO channels
+ ******************************************************************************/
+
+struct nv03_channel_dma_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 pushbuf;
+ __u64 offset;
+};
+
+#define G82_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+
+/*******************************************************************************
+ * GPFIFO channels
+ ******************************************************************************/
+
+struct nv50_channel_gpfifo_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad01[6];
+ __u32 pushbuf;
+ __u32 ilength;
+ __u64 ioffset;
+};
+
+struct kepler_channel_gpfifo_a_v0 {
+ __u8 version;
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_GR 0x01
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_VP 0x02
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_PPP 0x04
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_BSP 0x08
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0 0x10
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1 0x20
+#define KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_ENC 0x40
+ __u8 engine;
+ __u16 chid;
+ __u8 pad04[4];
+ __u32 pushbuf;
+ __u32 ilength;
+ __u64 ioffset;
+};
+
+/*******************************************************************************
+ * legacy display
+ ******************************************************************************/
+
+#define NV04_DISP_NTFY_VBLANK 0x00
+#define NV04_DISP_NTFY_CONN 0x01
+
+struct nv04_disp_mthd_v0 {
+ __u8 version;
+#define NV04_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __s64 time[2];
+ __u16 vblanks;
+ __u16 vblanke;
+ __u16 vtotal;
+ __u16 vline;
+ __u16 hblanks;
+ __u16 hblanke;
+ __u16 htotal;
+ __u16 hline;
+};
+
+/*******************************************************************************
+ * display
+ ******************************************************************************/
+
+#define NV50_DISP_MTHD 0x00
+
+struct nv50_disp_mthd_v0 {
+ __u8 version;
+#define NV50_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv50_disp_mthd_v1 {
+ __u8 version;
+#define NV50_DISP_MTHD_V1_DAC_PWR 0x10
+#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11
+#define NV50_DISP_MTHD_V1_SOR_PWR 0x20
+#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
+#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
+#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
+#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
+ __u8 method;
+ __u16 hasht;
+ __u16 hashm;
+ __u8 pad06[2];
+};
+
+struct nv50_disp_dac_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 data;
+ __u8 vsync;
+ __u8 hsync;
+ __u8 pad05[3];
+};
+
+struct nv50_disp_dac_load_v0 {
+ __u8 version;
+ __u8 load;
+ __u8 pad02[2];
+ __u32 data;
+};
+
+struct nv50_disp_sor_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_sor_hda_eld_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u8 data[];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 max_ac_packet;
+ __u8 rekey;
+ __u8 pad04[4];
+};
+
+struct nv50_disp_sor_lvds_script_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 script;
+ __u8 pad04[4];
+};
+
+struct nv50_disp_sor_dp_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_pior_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 type;
+ __u8 pad03[5];
+};
+
+/* core */
+struct nv50_disp_core_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[3];
+ __u32 pushbuf;
+};
+
+/* cursor immediate */
+struct nv50_disp_cursor_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+/* base */
+struct nv50_disp_base_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[2];
+ __u8 head;
+ __u32 pushbuf;
+};
+
+/* overlay */
+struct nv50_disp_overlay_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[2];
+ __u8 head;
+ __u32 pushbuf;
+};
+
+/* overlay immediate */
+struct nv50_disp_overlay_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+
+/*******************************************************************************
+ * fermi
+ ******************************************************************************/
+
+#define FERMI_A_ZBC_COLOR 0x00
+#define FERMI_A_ZBC_DEPTH 0x01
+
+struct fermi_a_zbc_color_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO 0x01
+#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE 0x02
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32 0x04
+#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16 0x08
+#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16 0x0c
+#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16 0x10
+#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16 0x14
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16 0x16
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8 0x18
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8 0x1c
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10 0x20
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10 0x24
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8 0x28
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8 0x2c
+#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8 0x30
+#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8 0x34
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8 0x38
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10 0x3c
+#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11 0x40
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds[4];
+ __u32 l2[4];
+};
+
+struct fermi_a_zbc_depth_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds;
+ __u32 l2;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/client.c b/drivers/gpu/drm/nouveau/nvif/client.c
new file mode 100644
index 000000000000..3c4df1fc26dc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/client.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_client_ioctl(struct nvif_client *client, void *data, u32 size)
+{
+ return client->driver->ioctl(client->base.priv, client->super, data, size, NULL);
+}
+
+int
+nvif_client_suspend(struct nvif_client *client)
+{
+ return client->driver->suspend(client->base.priv);
+}
+
+int
+nvif_client_resume(struct nvif_client *client)
+{
+ return client->driver->resume(client->base.priv);
+}
+
+void
+nvif_client_fini(struct nvif_client *client)
+{
+ if (client->driver) {
+ client->driver->fini(client->base.priv);
+ client->driver = NULL;
+ client->base.parent = NULL;
+ nvif_object_fini(&client->base);
+ }
+}
+
+const struct nvif_driver *
+nvif_drivers[] = {
+#ifdef __KERNEL__
+ &nvif_driver_nvkm,
+#else
+ &nvif_driver_drm,
+ &nvif_driver_lib,
+#endif
+ NULL
+};
+
+int
+nvif_client_init(void (*dtor)(struct nvif_client *), const char *driver,
+ const char *name, u64 device, const char *cfg, const char *dbg,
+ struct nvif_client *client)
+{
+ int ret, i;
+
+ ret = nvif_object_init(NULL, (void*)dtor, 0, 0, NULL, 0, &client->base);
+ if (ret)
+ return ret;
+
+ client->base.parent = &client->base;
+ client->base.handle = ~0;
+ client->object = &client->base;
+ client->super = true;
+
+ for (i = 0, ret = -EINVAL; (client->driver = nvif_drivers[i]); i++) {
+ if (!driver || !strcmp(client->driver->name, driver)) {
+ ret = client->driver->init(name, device, cfg, dbg,
+ &client->base.priv);
+ if (!ret || driver)
+ break;
+ }
+ }
+
+ if (ret)
+ nvif_client_fini(client);
+ return ret;
+}
+
+static void
+nvif_client_del(struct nvif_client *client)
+{
+ nvif_client_fini(client);
+ kfree(client);
+}
+
+int
+nvif_client_new(const char *driver, const char *name, u64 device,
+ const char *cfg, const char *dbg,
+ struct nvif_client **pclient)
+{
+ struct nvif_client *client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (client) {
+ int ret = nvif_client_init(nvif_client_del, driver, name,
+ device, cfg, dbg, client);
+ if (ret) {
+ kfree(client);
+ client = NULL;
+ }
+ *pclient = client;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+void
+nvif_client_ref(struct nvif_client *client, struct nvif_client **pclient)
+{
+ nvif_object_ref(&client->base, (struct nvif_object **)pclient);
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/client.h b/drivers/gpu/drm/nouveau/nvif/client.h
new file mode 100644
index 000000000000..28352f0882ec
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/client.h
@@ -0,0 +1,39 @@
+#ifndef __NVIF_CLIENT_H__
+#define __NVIF_CLIENT_H__
+
+#include "object.h"
+
+struct nvif_client {
+ struct nvif_object base;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ const struct nvif_driver *driver;
+ bool super;
+};
+
+static inline struct nvif_client *
+nvif_client(struct nvif_object *object)
+{
+ while (object && object->parent != object)
+ object = object->parent;
+ return (void *)object;
+}
+
+int nvif_client_init(void (*dtor)(struct nvif_client *), const char *,
+ const char *, u64, const char *, const char *,
+ struct nvif_client *);
+void nvif_client_fini(struct nvif_client *);
+int nvif_client_new(const char *, const char *, u64, const char *,
+ const char *, struct nvif_client **);
+void nvif_client_ref(struct nvif_client *, struct nvif_client **);
+int nvif_client_ioctl(struct nvif_client *, void *, u32);
+int nvif_client_suspend(struct nvif_client *);
+int nvif_client_resume(struct nvif_client *);
+
+/*XXX*/
+#include <core/client.h>
+#define nvkm_client(a) ({ \
+ struct nvif_client *_client = nvif_client(nvif_object(a)); \
+ nouveau_client(_client->base.priv); \
+})
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/device.c b/drivers/gpu/drm/nouveau/nvif/device.c
new file mode 100644
index 000000000000..f477579725e3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/device.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "device.h"
+
+void
+nvif_device_fini(struct nvif_device *device)
+{
+ nvif_object_fini(&device->base);
+}
+
+int
+nvif_device_init(struct nvif_object *parent, void (*dtor)(struct nvif_device *),
+ u32 handle, u32 oclass, void *data, u32 size,
+ struct nvif_device *device)
+{
+ int ret = nvif_object_init(parent, (void *)dtor, handle, oclass,
+ data, size, &device->base);
+ if (ret == 0) {
+ device->object = &device->base;
+ device->info.version = 0;
+ ret = nvif_object_mthd(&device->base, NV_DEVICE_V0_INFO,
+ &device->info, sizeof(device->info));
+ }
+ return ret;
+}
+
+static void
+nvif_device_del(struct nvif_device *device)
+{
+ nvif_device_fini(device);
+ kfree(device);
+}
+
+int
+nvif_device_new(struct nvif_object *parent, u32 handle, u32 oclass,
+ void *data, u32 size, struct nvif_device **pdevice)
+{
+ struct nvif_device *device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (device) {
+ int ret = nvif_device_init(parent, nvif_device_del, handle,
+ oclass, data, size, device);
+ if (ret) {
+ kfree(device);
+ device = NULL;
+ }
+ *pdevice = device;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+void
+nvif_device_ref(struct nvif_device *device, struct nvif_device **pdevice)
+{
+ nvif_object_ref(&device->base, (struct nvif_object **)pdevice);
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/device.h b/drivers/gpu/drm/nouveau/nvif/device.h
new file mode 100644
index 000000000000..43180f9fe630
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/device.h
@@ -0,0 +1,62 @@
+#ifndef __NVIF_DEVICE_H__
+#define __NVIF_DEVICE_H__
+
+#include "object.h"
+#include "class.h"
+
+struct nvif_device {
+ struct nvif_object base;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ struct nv_device_info_v0 info;
+};
+
+static inline struct nvif_device *
+nvif_device(struct nvif_object *object)
+{
+ while (object && object->oclass != 0x0080 /*XXX: NV_DEVICE_CLASS*/ )
+ object = object->parent;
+ return (void *)object;
+}
+
+int nvif_device_init(struct nvif_object *, void (*dtor)(struct nvif_device *),
+ u32 handle, u32 oclass, void *, u32,
+ struct nvif_device *);
+void nvif_device_fini(struct nvif_device *);
+int nvif_device_new(struct nvif_object *, u32 handle, u32 oclass,
+ void *, u32, struct nvif_device **);
+void nvif_device_ref(struct nvif_device *, struct nvif_device **);
+
+/*XXX*/
+#include <subdev/bios.h>
+#include <subdev/fb.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/gpio.h>
+#include <subdev/clock.h>
+#include <subdev/i2c.h>
+#include <subdev/timer.h>
+#include <subdev/therm.h>
+
+#define nvkm_device(a) nv_device(nvkm_object((a)))
+#define nvkm_bios(a) nouveau_bios(nvkm_device(a))
+#define nvkm_fb(a) nouveau_fb(nvkm_device(a))
+#define nvkm_vmmgr(a) nouveau_vmmgr(nvkm_device(a))
+#define nvkm_bar(a) nouveau_bar(nvkm_device(a))
+#define nvkm_gpio(a) nouveau_gpio(nvkm_device(a))
+#define nvkm_clock(a) nouveau_clock(nvkm_device(a))
+#define nvkm_i2c(a) nouveau_i2c(nvkm_device(a))
+#define nvkm_timer(a) nouveau_timer(nvkm_device(a))
+#define nvkm_wait(a,b,c,d) nv_wait(nvkm_timer(a), (b), (c), (d))
+#define nvkm_wait_cb(a,b,c) nv_wait_cb(nvkm_timer(a), (b), (c))
+#define nvkm_therm(a) nouveau_therm(nvkm_device(a))
+
+#include <engine/device.h>
+#include <engine/fifo.h>
+#include <engine/graph.h>
+#include <engine/software.h>
+
+#define nvkm_fifo(a) nouveau_fifo(nvkm_device(a))
+#define nvkm_fifo_chan(a) ((struct nouveau_fifo_chan *)nvkm_object(a))
+#define nvkm_gr(a) ((struct nouveau_graph *)nouveau_engine(nvkm_object(a), NVDEV_ENGINE_GR))
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/driver.h b/drivers/gpu/drm/nouveau/nvif/driver.h
new file mode 100644
index 000000000000..b72a8f0c2758
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/driver.h
@@ -0,0 +1,21 @@
+#ifndef __NVIF_DRIVER_H__
+#define __NVIF_DRIVER_H__
+
+struct nvif_driver {
+ const char *name;
+ int (*init)(const char *name, u64 device, const char *cfg,
+ const char *dbg, void **priv);
+ void (*fini)(void *priv);
+ int (*suspend)(void *priv);
+ int (*resume)(void *priv);
+ int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack);
+ void *(*map)(void *priv, u64 handle, u32 size);
+ void (*unmap)(void *priv, void *ptr, u32 size);
+ bool keep;
+};
+
+extern const struct nvif_driver nvif_driver_nvkm;
+extern const struct nvif_driver nvif_driver_drm;
+extern const struct nvif_driver nvif_driver_lib;
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/event.h b/drivers/gpu/drm/nouveau/nvif/event.h
new file mode 100644
index 000000000000..21764499b4be
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/event.h
@@ -0,0 +1,62 @@
+#ifndef __NVIF_EVENT_H__
+#define __NVIF_EVENT_H__
+
+struct nvif_notify_req_v0 {
+ __u8 version;
+ __u8 reply;
+ __u8 pad02[5];
+#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00
+ __u8 route;
+ __u64 token; /* must be unique */
+ __u8 data[]; /* request data (below) */
+};
+
+struct nvif_notify_rep_v0 {
+ __u8 version;
+ __u8 pad01[6];
+ __u8 route;
+ __u64 token;
+ __u8 data[]; /* reply data (below) */
+};
+
+struct nvif_notify_head_req_v0 {
+ /* nvif_notify_req ... */
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+struct nvif_notify_head_rep_v0 {
+ /* nvif_notify_rep ... */
+ __u8 version;
+ __u8 pad01[7];
+};
+
+struct nvif_notify_conn_req_v0 {
+ /* nvif_notify_req ... */
+ __u8 version;
+#define NVIF_NOTIFY_CONN_V0_PLUG 0x01
+#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02
+#define NVIF_NOTIFY_CONN_V0_IRQ 0x04
+#define NVIF_NOTIFY_CONN_V0_ANY 0x07
+ __u8 mask;
+ __u8 conn;
+ __u8 pad03[5];
+};
+
+struct nvif_notify_conn_rep_v0 {
+ /* nvif_notify_rep ... */
+ __u8 version;
+ __u8 mask;
+ __u8 pad02[6];
+};
+
+struct nvif_notify_uevent_req {
+ /* nvif_notify_req ... */
+};
+
+struct nvif_notify_uevent_rep {
+ /* nvif_notify_rep ... */
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/ioctl.h b/drivers/gpu/drm/nouveau/nvif/ioctl.h
new file mode 100644
index 000000000000..4cd8e323b23d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/ioctl.h
@@ -0,0 +1,128 @@
+#ifndef __NVIF_IOCTL_H__
+#define __NVIF_IOCTL_H__
+
+struct nvif_ioctl_v0 {
+ __u8 version;
+#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
+#define NVIF_IOCTL_V0_OWNER_ANY 0xff
+ __u8 owner;
+#define NVIF_IOCTL_V0_NOP 0x00
+#define NVIF_IOCTL_V0_SCLASS 0x01
+#define NVIF_IOCTL_V0_NEW 0x02
+#define NVIF_IOCTL_V0_DEL 0x03
+#define NVIF_IOCTL_V0_MTHD 0x04
+#define NVIF_IOCTL_V0_RD 0x05
+#define NVIF_IOCTL_V0_WR 0x06
+#define NVIF_IOCTL_V0_MAP 0x07
+#define NVIF_IOCTL_V0_UNMAP 0x08
+#define NVIF_IOCTL_V0_NTFY_NEW 0x09
+#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
+#define NVIF_IOCTL_V0_NTFY_GET 0x0b
+#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
+ __u8 type;
+ __u8 path_nr;
+#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00
+#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff
+ __u8 pad04[3];
+ __u8 route;
+ __u64 token;
+ __u32 path[8]; /* in reverse */
+ __u8 data[]; /* ioctl data (below) */
+};
+
+struct nvif_ioctl_nop {
+};
+
+struct nvif_ioctl_sclass_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ __u32 oclass[];
+};
+
+struct nvif_ioctl_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 pad01[6];
+ __u8 route;
+ __u64 token;
+ __u32 handle;
+/* these class numbers are made up by us, and not nvidia-assigned */
+#define NVIF_IOCTL_NEW_V0_PERFCTR 0x0000ffff
+#define NVIF_IOCTL_NEW_V0_CONTROL 0x0000fffe
+ __u32 oclass;
+ __u8 data[]; /* class data (class.h) */
+};
+
+struct nvif_ioctl_del {
+};
+
+struct nvif_ioctl_rd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_wr_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_map_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 pad01[3];
+ __u32 length;
+ __u64 handle;
+};
+
+struct nvif_ioctl_unmap {
+};
+
+struct nvif_ioctl_ntfy_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 event;
+ __u8 index;
+ __u8 pad03[5];
+ __u8 data[]; /* event request data (event.h) */
+};
+
+struct nvif_ioctl_ntfy_del_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_get_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_put_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_mthd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 method;
+ __u8 pad02[6];
+ __u8 data[]; /* method data (class.h) */
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/list.h b/drivers/gpu/drm/nouveau/nvif/list.h
new file mode 100644
index 000000000000..8af5d144ecb0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/list.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ * Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+/* Modified by Ben Skeggs <bskeggs@redhat.com> to match kernel list APIs */
+
+#ifndef _XORG_LIST_H_
+#define _XORG_LIST_H_
+
+/**
+ * @file Classic doubly-link circular list implementation.
+ * For real usage examples of the linked list, see the file test/list.c
+ *
+ * Example:
+ * We need to keep a list of struct foo in the parent struct bar, i.e. what
+ * we want is something like this.
+ *
+ * struct bar {
+ * ...
+ * struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{}
+ * ...
+ * }
+ *
+ * We need one list head in bar and a list element in all list_of_foos (both are of
+ * data type 'struct list_head').
+ *
+ * struct bar {
+ * ...
+ * struct list_head list_of_foos;
+ * ...
+ * }
+ *
+ * struct foo {
+ * ...
+ * struct list_head entry;
+ * ...
+ * }
+ *
+ * Now we initialize the list head:
+ *
+ * struct bar bar;
+ * ...
+ * INIT_LIST_HEAD(&bar.list_of_foos);
+ *
+ * Then we create the first element and add it to this list:
+ *
+ * struct foo *foo = malloc(...);
+ * ....
+ * list_add(&foo->entry, &bar.list_of_foos);
+ *
+ * Repeat the above for each element you want to add to the list. Deleting
+ * works with the element itself.
+ * list_del(&foo->entry);
+ * free(foo);
+ *
+ * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty
+ * list again.
+ *
+ * Looping through the list requires a 'struct foo' as iterator and the
+ * name of the field the subnodes use.
+ *
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar.list_of_foos, entry) {
+ * if (iterator->something == ...)
+ * ...
+ * }
+ *
+ * Note: You must not call list_del() on the iterator if you continue the
+ * loop. You need to run the safe for-each loop instead:
+ *
+ * struct foo *iterator, *next;
+ * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) {
+ * if (...)
+ * list_del(&iterator->entry);
+ * }
+ *
+ */
+
+/**
+ * The linkage struct for list nodes. This struct must be part of your
+ * to-be-linked struct. struct list_head is required for both the head of the
+ * list and for each list node.
+ *
+ * Position and name of the struct list_head field is irrelevant.
+ * There are no requirements that elements of a list are of the same type.
+ * There are no requirements for a list head, any struct list_head can be a list
+ * head.
+ */
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+/**
+ * Initialize the list as an empty list.
+ *
+ * Example:
+ * INIT_LIST_HEAD(&bar->list_of_foos);
+ *
+ * @param The list to initialized.
+ */
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void
+INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list->prev = list;
+}
+
+static inline void
+__list_add(struct list_head *entry,
+ struct list_head *prev, struct list_head *next)
+{
+ next->prev = entry;
+ entry->next = next;
+ entry->prev = prev;
+ prev->next = entry;
+}
+
+/**
+ * Insert a new element after the given list head. The new element does not
+ * need to be initialised as empty list.
+ * The list changes from:
+ * head → some element → ...
+ * to
+ * head → new element → older element → ...
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add(struct list_head *entry, struct list_head *head)
+{
+ __list_add(entry, head, head->next);
+}
+
+/**
+ * Append a new element to the end of the list given with this list head.
+ *
+ * The list changes from:
+ * head → some element → ... → lastelement
+ * to
+ * head → some element → ... → lastelement → new element
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add_tail(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add_tail(struct list_head *entry, struct list_head *head)
+{
+ __list_add(entry, head->prev, head);
+}
+
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * Remove the element from the list it is in. Using this function will reset
+ * the pointers to/from this element so it is removed from the list. It does
+ * NOT free the element itself or manipulate it otherwise.
+ *
+ * Using list_del on a pure list head (like in the example at the top of
+ * this file) will NOT remove the first element from
+ * the list but rather reset the list as empty list.
+ *
+ * Example:
+ * list_del(&foo->entry);
+ *
+ * @param entry The element to remove.
+ */
+static inline void
+list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void
+list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * Check if the list is empty.
+ *
+ * Example:
+ * list_empty(&bar->list_of_foos);
+ *
+ * @return True if the list contains one or more elements or False otherwise.
+ */
+static inline bool
+list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * Returns a pointer to the container of this list element.
+ *
+ * Example:
+ * struct foo* f;
+ * f = container_of(&foo->entry, struct foo, entry);
+ * assert(f == foo);
+ *
+ * @param ptr Pointer to the struct list_head.
+ * @param type Data type of the list element.
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the data struct containing the list head.
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) \
+ (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+#endif
+
+/**
+ * Alias of container_of
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * Retrieve the first list entry for the given list pointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the first list element.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * Retrieve the last list entry for the given listpointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the last list element.
+ */
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+#define __container_of(ptr, sample, member) \
+ (void *)container_of((ptr), typeof(*(sample)), member)
+
+/**
+ * Loop through the list given by head and set pos to struct in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar->list_of_foos, entry) {
+ * [modify iterator]
+ * }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param pos Iterator variable of the type of the list elements.
+ * @param head List head
+ * @param member Member name of the struct list_head in the list elements.
+ *
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = __container_of((head)->next, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+/**
+ * Loop through the list, keeping a backup pointer to the element. This
+ * macro allows for the deletion of a list element while looping through the
+ * list.
+ *
+ * See list_for_each_entry for more details.
+ */
+#define list_for_each_entry_safe(pos, tmp, head, member) \
+ for (pos = __container_of((head)->next, pos, member), \
+ tmp = __container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
+
+
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = __container_of((head)->prev, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = __container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = __container_of(pos->member.prev, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_from(pos, head, member) \
+ for (; \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c
new file mode 100644
index 000000000000..0898c3155292
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/notify.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/object.h>
+#include <nvif/ioctl.h>
+#include <nvif/event.h>
+
+static inline int
+nvif_notify_put_(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_put_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_PUT,
+ .ntfy.index = notify->index,
+ };
+
+ if (atomic_inc_return(&notify->putcnt) != 1)
+ return 0;
+
+ return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_put(struct nvif_notify *notify)
+{
+ if (likely(notify->object) &&
+ test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
+ int ret = nvif_notify_put_(notify);
+ if (test_bit(NVIF_NOTIFY_WORK, &notify->flags))
+ flush_work(&notify->work);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int
+nvif_notify_get_(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_get_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_GET,
+ .ntfy.index = notify->index,
+ };
+
+ if (atomic_dec_return(&notify->putcnt) != 0)
+ return 0;
+
+ return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_get(struct nvif_notify *notify)
+{
+ if (likely(notify->object) &&
+ !test_and_set_bit(NVIF_NOTIFY_USER, &notify->flags))
+ return nvif_notify_get_(notify);
+ return 0;
+}
+
+static inline int
+nvif_notify_func(struct nvif_notify *notify, bool keep)
+{
+ int ret = notify->func(notify);
+ if (ret == NVIF_NOTIFY_KEEP ||
+ !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+ if (!keep)
+ atomic_dec(&notify->putcnt);
+ else
+ nvif_notify_get_(notify);
+ }
+ return ret;
+}
+
+static void
+nvif_notify_work(struct work_struct *work)
+{
+ struct nvif_notify *notify = container_of(work, typeof(*notify), work);
+ nvif_notify_func(notify, true);
+}
+
+int
+nvif_notify(const void *header, u32 length, const void *data, u32 size)
+{
+ struct nvif_notify *notify = NULL;
+ const union {
+ struct nvif_notify_rep_v0 v0;
+ } *args = header;
+ int ret = NVIF_NOTIFY_DROP;
+
+ if (length == sizeof(args->v0) && args->v0.version == 0) {
+ if (WARN_ON(args->v0.route))
+ return NVIF_NOTIFY_DROP;
+ notify = (void *)(unsigned long)args->v0.token;
+ }
+
+ if (!WARN_ON(notify == NULL)) {
+ struct nvif_client *client = nvif_client(notify->object);
+ if (!WARN_ON(notify->size != size)) {
+ atomic_inc(&notify->putcnt);
+ if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
+ memcpy((void *)notify->data, data, size);
+ schedule_work(&notify->work);
+ return NVIF_NOTIFY_DROP;
+ }
+ notify->data = data;
+ ret = nvif_notify_func(notify, client->driver->keep);
+ notify->data = NULL;
+ }
+ }
+
+ return ret;
+}
+
+int
+nvif_notify_fini(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_del_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_DEL,
+ .ntfy.index = notify->index,
+ };
+ int ret = nvif_notify_put(notify);
+ if (ret >= 0 && object) {
+ ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret == 0) {
+ nvif_object_ref(NULL, &notify->object);
+ kfree((void *)notify->data);
+ }
+ }
+ return ret;
+}
+
+int
+nvif_notify_init(struct nvif_object *object, void (*dtor)(struct nvif_notify *),
+ int (*func)(struct nvif_notify *), bool work, u8 event,
+ void *data, u32 size, u32 reply, struct nvif_notify *notify)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_new_v0 ntfy;
+ struct nvif_notify_req_v0 req;
+ } *args;
+ int ret = -ENOMEM;
+
+ notify->object = NULL;
+ nvif_object_ref(object, &notify->object);
+ notify->flags = 0;
+ atomic_set(&notify->putcnt, 1);
+ notify->dtor = dtor;
+ notify->func = func;
+ notify->data = NULL;
+ notify->size = reply;
+ if (work) {
+ INIT_WORK(&notify->work, nvif_notify_work);
+ set_bit(NVIF_NOTIFY_WORK, &notify->flags);
+ notify->data = kmalloc(notify->size, GFP_KERNEL);
+ if (!notify->data)
+ goto done;
+ }
+
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ goto done;
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW;
+ args->ntfy.version = 0;
+ args->ntfy.event = event;
+ args->req.version = 0;
+ args->req.reply = notify->size;
+ args->req.route = 0;
+ args->req.token = (unsigned long)(void *)notify;
+
+ memcpy(args->req.data, data, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ notify->index = args->ntfy.index;
+ kfree(args);
+done:
+ if (ret)
+ nvif_notify_fini(notify);
+ return ret;
+}
+
+static void
+nvif_notify_del(struct nvif_notify *notify)
+{
+ nvif_notify_fini(notify);
+ kfree(notify);
+}
+
+void
+nvif_notify_ref(struct nvif_notify *notify, struct nvif_notify **pnotify)
+{
+ BUG_ON(notify != NULL);
+ if (*pnotify)
+ (*pnotify)->dtor(*pnotify);
+ *pnotify = notify;
+}
+
+int
+nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *),
+ bool work, u8 type, void *data, u32 size, u32 reply,
+ struct nvif_notify **pnotify)
+{
+ struct nvif_notify *notify = kzalloc(sizeof(*notify), GFP_KERNEL);
+ if (notify) {
+ int ret = nvif_notify_init(object, nvif_notify_del, func, work,
+ type, data, size, reply, notify);
+ if (ret) {
+ kfree(notify);
+ notify = NULL;
+ }
+ *pnotify = notify;
+ return ret;
+ }
+ return -ENOMEM;
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.h b/drivers/gpu/drm/nouveau/nvif/notify.h
new file mode 100644
index 000000000000..9ebfa3b45e76
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/notify.h
@@ -0,0 +1,39 @@
+#ifndef __NVIF_NOTIFY_H__
+#define __NVIF_NOTIFY_H__
+
+struct nvif_notify {
+ struct nvif_object *object;
+ int index;
+
+#define NVIF_NOTIFY_USER 0
+#define NVIF_NOTIFY_WORK 1
+ unsigned long flags;
+ atomic_t putcnt;
+ void (*dtor)(struct nvif_notify *);
+#define NVIF_NOTIFY_DROP 0
+#define NVIF_NOTIFY_KEEP 1
+ int (*func)(struct nvif_notify *);
+
+ /* this is const for a *very* good reason - the data might be on the
+ * stack from an irq handler. if you're not nvif/notify.c then you
+ * should probably think twice before casting it away...
+ */
+ const void *data;
+ u32 size;
+ struct work_struct work;
+};
+
+int nvif_notify_init(struct nvif_object *, void (*dtor)(struct nvif_notify *),
+ int (*func)(struct nvif_notify *), bool work, u8 type,
+ void *data, u32 size, u32 reply, struct nvif_notify *);
+int nvif_notify_fini(struct nvif_notify *);
+int nvif_notify_get(struct nvif_notify *);
+int nvif_notify_put(struct nvif_notify *);
+int nvif_notify(const void *, u32, const void *, u32);
+
+int nvif_notify_new(struct nvif_object *, int (*func)(struct nvif_notify *),
+ bool work, u8 type, void *data, u32 size, u32 reply,
+ struct nvif_notify **);
+void nvif_notify_ref(struct nvif_notify *, struct nvif_notify **);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c
new file mode 100644
index 000000000000..dd85b56f6aa5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/object.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "object.h"
+#include "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
+{
+ struct nvif_client *client = nvif_client(object);
+ union {
+ struct nvif_ioctl_v0 v0;
+ } *args = data;
+
+ if (size >= sizeof(*args) && args->v0.version == 0) {
+ args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+ args->v0.path_nr = 0;
+ while (args->v0.path_nr < ARRAY_SIZE(args->v0.path)) {
+ args->v0.path[args->v0.path_nr++] = object->handle;
+ if (object->parent == object)
+ break;
+ object = object->parent;
+ }
+ } else
+ return -ENOSYS;
+
+ return client->driver->ioctl(client->base.priv, client->super, data, size, hack);
+}
+
+int
+nvif_object_sclass(struct nvif_object *object, u32 *oclass, int count)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_sclass_v0 sclass;
+ } *args;
+ u32 size = count * sizeof(args->sclass.oclass[0]);
+ int ret;
+
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ return -ENOMEM;
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
+ args->sclass.version = 0;
+ args->sclass.count = count;
+
+ memcpy(args->sclass.oclass, oclass, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ ret = ret ? ret : args->sclass.count;
+ memcpy(oclass, args->sclass.oclass, size);
+ kfree(args);
+ return ret;
+}
+
+u32
+nvif_object_rd(struct nvif_object *object, int size, u64 addr)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_rd_v0 rd;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_RD,
+ .rd.size = size,
+ .rd.addr = addr,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret) {
+ /*XXX: warn? */
+ return 0;
+ }
+ return args.rd.data;
+}
+
+void
+nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_wr_v0 wr;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_WR,
+ .wr.size = size,
+ .wr.addr = addr,
+ .wr.data = data,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret) {
+ /*XXX: warn? */
+ }
+}
+
+int
+nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_mthd_v0 mthd;
+ } *args;
+ u8 stack[128];
+ int ret;
+
+ if (sizeof(*args) + size > sizeof(stack)) {
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ return -ENOMEM;
+ } else {
+ args = (void *)stack;
+ }
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_MTHD;
+ args->mthd.version = 0;
+ args->mthd.method = mthd;
+
+ memcpy(args->mthd.data, data, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ memcpy(data, args->mthd.data, size);
+ if (args != (void *)stack)
+ kfree(args);
+ return ret;
+}
+
+void
+nvif_object_unmap(struct nvif_object *object)
+{
+ if (object->map.size) {
+ struct nvif_client *client = nvif_client(object);
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_unmap unmap;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_UNMAP,
+ };
+
+ if (object->map.ptr) {
+ client->driver->unmap(client, object->map.ptr,
+ object->map.size);
+ object->map.ptr = NULL;
+ }
+
+ nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ object->map.size = 0;
+ }
+}
+
+int
+nvif_object_map(struct nvif_object *object)
+{
+ struct nvif_client *client = nvif_client(object);
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_map_v0 map;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_MAP,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret == 0) {
+ object->map.size = args.map.length;
+ object->map.ptr = client->driver->map(client, args.map.handle,
+ object->map.size);
+ if (ret = -ENOMEM, object->map.ptr)
+ return 0;
+ nvif_object_unmap(object);
+ }
+ return ret;
+}
+
+struct ctor {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_new_v0 new;
+};
+
+void
+nvif_object_fini(struct nvif_object *object)
+{
+ struct ctor *ctor = container_of(object->data, typeof(*ctor), new.data);
+ if (object->parent) {
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_del del;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_DEL,
+ };
+
+ nvif_object_unmap(object);
+ nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (object->data) {
+ object->size = 0;
+ object->data = NULL;
+ kfree(ctor);
+ }
+ nvif_object_ref(NULL, &object->parent);
+ }
+}
+
+int
+nvif_object_init(struct nvif_object *parent, void (*dtor)(struct nvif_object *),
+ u32 handle, u32 oclass, void *data, u32 size,
+ struct nvif_object *object)
+{
+ struct ctor *ctor;
+ int ret = 0;
+
+ object->parent = NULL;
+ object->object = object;
+ nvif_object_ref(parent, &object->parent);
+ kref_init(&object->refcount);
+ object->handle = handle;
+ object->oclass = oclass;
+ object->data = NULL;
+ object->size = 0;
+ object->dtor = dtor;
+ object->map.ptr = NULL;
+ object->map.size = 0;
+
+ if (object->parent) {
+ if (!(ctor = kmalloc(sizeof(*ctor) + size, GFP_KERNEL))) {
+ nvif_object_fini(object);
+ return -ENOMEM;
+ }
+ object->data = ctor->new.data;
+ object->size = size;
+ memcpy(object->data, data, size);
+
+ ctor->ioctl.version = 0;
+ ctor->ioctl.type = NVIF_IOCTL_V0_NEW;
+ ctor->new.version = 0;
+ ctor->new.route = NVIF_IOCTL_V0_ROUTE_NVIF;
+ ctor->new.token = (unsigned long)(void *)object;
+ ctor->new.handle = handle;
+ ctor->new.oclass = oclass;
+
+ ret = nvif_object_ioctl(parent, ctor, sizeof(*ctor) +
+ object->size, &object->priv);
+ }
+
+ if (ret)
+ nvif_object_fini(object);
+ return ret;
+}
+
+static void
+nvif_object_del(struct nvif_object *object)
+{
+ nvif_object_fini(object);
+ kfree(object);
+}
+
+int
+nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass,
+ void *data, u32 size, struct nvif_object **pobject)
+{
+ struct nvif_object *object = kzalloc(sizeof(*object), GFP_KERNEL);
+ if (object) {
+ int ret = nvif_object_init(parent, nvif_object_del, handle,
+ oclass, data, size, object);
+ if (ret) {
+ kfree(object);
+ object = NULL;
+ }
+ *pobject = object;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+static void
+nvif_object_put(struct kref *kref)
+{
+ struct nvif_object *object =
+ container_of(kref, typeof(*object), refcount);
+ object->dtor(object);
+}
+
+void
+nvif_object_ref(struct nvif_object *object, struct nvif_object **pobject)
+{
+ if (object)
+ kref_get(&object->refcount);
+ if (*pobject)
+ kref_put(&(*pobject)->refcount, nvif_object_put);
+ *pobject = object;
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/object.h b/drivers/gpu/drm/nouveau/nvif/object.h
new file mode 100644
index 000000000000..fac3a3bbec44
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/object.h
@@ -0,0 +1,75 @@
+#ifndef __NVIF_OBJECT_H__
+#define __NVIF_OBJECT_H__
+
+#include <nvif/os.h>
+
+struct nvif_object {
+ struct nvif_object *parent;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ struct kref refcount;
+ u32 handle;
+ u32 oclass;
+ void *data;
+ u32 size;
+ void *priv; /*XXX: hack */
+ void (*dtor)(struct nvif_object *);
+ struct {
+ void *ptr;
+ u32 size;
+ } map;
+};
+
+int nvif_object_init(struct nvif_object *, void (*dtor)(struct nvif_object *),
+ u32 handle, u32 oclass, void *, u32,
+ struct nvif_object *);
+void nvif_object_fini(struct nvif_object *);
+int nvif_object_new(struct nvif_object *, u32 handle, u32 oclass,
+ void *, u32, struct nvif_object **);
+void nvif_object_ref(struct nvif_object *, struct nvif_object **);
+int nvif_object_ioctl(struct nvif_object *, void *, u32, void **);
+int nvif_object_sclass(struct nvif_object *, u32 *, int);
+u32 nvif_object_rd(struct nvif_object *, int, u64);
+void nvif_object_wr(struct nvif_object *, int, u64, u32);
+int nvif_object_mthd(struct nvif_object *, u32, void *, u32);
+int nvif_object_map(struct nvif_object *);
+void nvif_object_unmap(struct nvif_object *);
+
+#define nvif_object(a) (a)->object
+
+#define ioread8_native ioread8
+#define iowrite8_native iowrite8
+#define nvif_rd(a,b,c) ({ \
+ struct nvif_object *_object = nvif_object(a); \
+ u32 _data; \
+ if (likely(_object->map.ptr)) \
+ _data = ioread##b##_native((u8 *)_object->map.ptr + (c)); \
+ else \
+ _data = nvif_object_rd(_object, (b) / 8, (c)); \
+ _data; \
+})
+#define nvif_wr(a,b,c,d) ({ \
+ struct nvif_object *_object = nvif_object(a); \
+ if (likely(_object->map.ptr)) \
+ iowrite##b##_native((d), (u8 *)_object->map.ptr + (c)); \
+ else \
+ nvif_object_wr(_object, (b) / 8, (c), (d)); \
+})
+#define nvif_rd08(a,b) ({ u8 _v = nvif_rd((a), 8, (b)); _v; })
+#define nvif_rd16(a,b) ({ u16 _v = nvif_rd((a), 16, (b)); _v; })
+#define nvif_rd32(a,b) ({ u32 _v = nvif_rd((a), 32, (b)); _v; })
+#define nvif_wr08(a,b,c) nvif_wr((a), 8, (b), (u8)(c))
+#define nvif_wr16(a,b,c) nvif_wr((a), 16, (b), (u16)(c))
+#define nvif_wr32(a,b,c) nvif_wr((a), 32, (b), (u32)(c))
+#define nvif_mask(a,b,c,d) ({ \
+ u32 _v = nvif_rd32(nvif_object(a), (b)); \
+ nvif_wr32(nvif_object(a), (b), (_v & ~(c)) | (d)); \
+ _v; \
+})
+
+#define nvif_mthd(a,b,c,d) nvif_object_mthd(nvif_object(a), (b), (c), (d))
+
+/*XXX*/
+#include <core/object.h>
+#define nvkm_object(a) ((struct nouveau_object *)nvif_object(a)->priv)
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvif/os.h b/drivers/gpu/drm/nouveau/nvif/os.h
new file mode 120000
index 000000000000..bd744b2cf5cf
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/os.h
@@ -0,0 +1 @@
+../core/os.h \ No newline at end of file
diff --git a/drivers/gpu/drm/nouveau/nvif/unpack.h b/drivers/gpu/drm/nouveau/nvif/unpack.h
new file mode 100644
index 000000000000..5933188b4a77
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/unpack.h
@@ -0,0 +1,24 @@
+#ifndef __NVIF_UNPACK_H__
+#define __NVIF_UNPACK_H__
+
+#define nvif_unvers(d) ({ \
+ ret = (size == sizeof(d)) ? 0 : -ENOSYS; \
+ (ret == 0); \
+})
+
+#define nvif_unpack(d,vl,vh,m) ({ \
+ if ((vl) == 0 || ret == -ENOSYS) { \
+ int _size = sizeof(d); \
+ if (_size <= size && (d).version >= (vl) && \
+ (d).version <= (vh)) { \
+ data = (u8 *)data + _size; \
+ size = size - _size; \
+ ret = ((m) || !size) ? 0 : -E2BIG; \
+ } else { \
+ ret = -ENOSYS; \
+ } \
+ } \
+ (ret == 0); \
+})
+
+#endif
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 86f4ead0441d..a94b11f7859d 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -32,8 +32,16 @@ struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
struct drm_encoder *encoder;
+ bool hdmi_mode;
};
+bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
+{
+ struct omap_connector *omap_connector = to_omap_connector(connector);
+
+ return omap_connector->hdmi_mode;
+}
+
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings)
{
@@ -130,7 +138,7 @@ static void omap_connector_destroy(struct drm_connector *connector)
struct omap_dss_device *dssdev = omap_connector->dssdev;
DBG("%s", omap_connector->dssdev->name);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(omap_connector);
@@ -162,10 +170,14 @@ static int omap_connector_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(
connector, edid);
n = drm_add_edid_modes(connector, edid);
+
+ omap_connector->hdmi_mode =
+ drm_detect_hdmi_monitor(edid);
} else {
drm_mode_connector_update_edid_property(
connector, NULL);
}
+
kfree(edid);
} else {
struct drm_display_mode *mode = drm_mode_create(dev);
@@ -307,7 +319,7 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return connector;
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index f926b4caf449..56c60552abba 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -199,7 +199,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
struct page **pages, uint32_t npages, uint32_t roll)
{
- dma_addr_t pat_pa = 0;
+ dma_addr_t pat_pa = 0, data_pa = 0;
uint32_t *data;
struct pat *pat;
struct refill_engine *engine = txn->engine_handle;
@@ -223,7 +223,9 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
.lut_id = engine->tcm->lut_id,
};
- data = alloc_dma(txn, 4*i, &pat->data_pa);
+ data = alloc_dma(txn, 4*i, &data_pa);
+ /* FIXME: what if data_pa is more than 32-bit ? */
+ pat->data_pa = data_pa;
while (i--) {
int n = i + roll;
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 284b80fc3c54..84d73a61b34b 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -119,13 +119,6 @@ struct omap_drm_private {
struct omap_drm_irq error_handler;
};
-/* this should probably be in drm-core to standardize amongst drivers */
-#define DRM_ROTATE_0 0
-#define DRM_ROTATE_90 1
-#define DRM_ROTATE_180 2
-#define DRM_ROTATE_270 3
-#define DRM_REFLECT_X 4
-#define DRM_REFLECT_Y 5
#ifdef CONFIG_DEBUG_FS
int omap_debugfs_init(struct drm_minor *minor);
@@ -194,6 +187,7 @@ struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
void omap_connector_flush(struct drm_connector *connector,
int x, int y, int w, int h);
+bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 5290a88c681d..7445fb1491ae 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -17,6 +17,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_edid.h>
+
#include "omap_drv.h"
#include "drm_crtc.h"
@@ -89,6 +91,31 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
+ struct drm_device *dev = encoder->dev;
+ struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+ struct omap_dss_device *dssdev = omap_encoder->dssdev;
+ struct drm_connector *connector;
+ bool hdmi_mode;
+ int r;
+
+ hdmi_mode = false;
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (connector->encoder == encoder) {
+ hdmi_mode = omap_connector_get_hdmi_mode(connector);
+ break;
+ }
+ }
+
+ if (dssdev->driver->set_hdmi_mode)
+ dssdev->driver->set_hdmi_mode(dssdev, hdmi_mode);
+
+ if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
+ struct hdmi_avi_infoframe avi;
+
+ r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
+ if (r == 0)
+ dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
+ }
}
static void omap_encoder_prepare(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 1388ca7f87e8..8436c6857cda 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -281,7 +281,7 @@ fail:
return ret;
}
-static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs omap_fb_helper_funcs = {
.fb_probe = omap_fbdev_create,
};
@@ -325,7 +325,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
helper = &fbdev->base;
- helper->funcs = &omap_fb_helper_funcs;
+ drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper,
priv->num_crtcs, priv->num_connectors);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 95dbce286a41..e4849413ee80 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -233,11 +233,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
WARN_ON(omap_obj->pages);
- /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the
- * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
- * we actually want CMA memory for it all anyways..
- */
- pages = drm_gem_get_pages(obj, GFP_KERNEL);
+ pages = drm_gem_get_pages(obj);
if (IS_ERR(pages)) {
dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
return PTR_ERR(pages);
@@ -791,7 +787,7 @@ int omap_gem_get_paddr(struct drm_gem_object *obj,
omap_obj->paddr = tiler_ssptr(block);
omap_obj->block = block;
- DBG("got paddr: %08x", omap_obj->paddr);
+ DBG("got paddr: %pad", &omap_obj->paddr);
}
omap_obj->paddr_cnt++;
@@ -985,9 +981,9 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
off = drm_vma_node_start(&obj->vma_node);
- seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
+ seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
omap_obj->flags, obj->name, obj->refcount.refcount.counter,
- off, omap_obj->paddr, omap_obj->paddr_cnt,
+ off, &omap_obj->paddr, omap_obj->paddr_cnt,
omap_obj->vaddr, omap_obj->roll);
if (omap_obj->flags & OMAP_BO_TILED) {
@@ -1183,9 +1179,7 @@ int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
}
}
spin_unlock(&sync_lock);
-
- if (waiter)
- kfree(waiter);
+ kfree(waiter);
}
return ret;
}
@@ -1347,6 +1341,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
struct omap_drm_private *priv = dev->dev_private;
struct omap_gem_object *omap_obj;
struct drm_gem_object *obj = NULL;
+ struct address_space *mapping;
size_t size;
int ret;
@@ -1404,14 +1399,16 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
omap_obj->height = gsize.tiled.height;
}
- ret = 0;
- if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
+ if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) {
drm_gem_private_object_init(dev, obj, size);
- else
+ } else {
ret = drm_gem_object_init(dev, obj, size);
+ if (ret)
+ goto fail;
- if (ret)
- goto fail;
+ mapping = file_inode(obj->filp)->i_mapping;
+ mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
+ }
return obj;
@@ -1467,8 +1464,8 @@ void omap_gem_init(struct drm_device *dev)
entry->paddr = tiler_ssptr(block);
entry->block = block;
- DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h,
- entry->paddr,
+ DBG("%d:%d: %dx%d: paddr=%pad stride=%d", i, j, w, h,
+ &entry->paddr,
usergart[i].stride_pfn << PAGE_SHIFT);
}
}
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index 4fcca8d42796..a2dbfb1737b4 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -171,7 +171,7 @@ static struct dma_buf_ops omap_dmabuf_ops = {
struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *obj, int flags)
{
- return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
+ return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags, NULL);
}
struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 3cf31ee59aac..891a4dc608af 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -142,8 +142,8 @@ static void omap_plane_pre_apply(struct omap_drm_apply *apply)
DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
info->out_width, info->out_height,
info->screen_width);
- DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
- info->paddr, info->p_uv_addr);
+ DBG("%d,%d %pad %pad", info->pos_x, info->pos_y,
+ &info->paddr, &info->p_uv_addr);
/* TODO: */
ilace = false;
@@ -308,16 +308,13 @@ void omap_plane_install_properties(struct drm_plane *plane,
if (priv->has_dmm) {
prop = priv->rotation_prop;
if (!prop) {
- const struct drm_prop_enum_list props[] = {
- { DRM_ROTATE_0, "rotate-0" },
- { DRM_ROTATE_90, "rotate-90" },
- { DRM_ROTATE_180, "rotate-180" },
- { DRM_ROTATE_270, "rotate-270" },
- { DRM_REFLECT_X, "reflect-x" },
- { DRM_REFLECT_Y, "reflect-y" },
- };
- prop = drm_property_create_bitmask(dev, 0, "rotation",
- props, ARRAY_SIZE(props));
+ prop = drm_mode_create_rotation_property(dev,
+ BIT(DRM_ROTATE_0) |
+ BIT(DRM_ROTATE_90) |
+ BIT(DRM_ROTATE_180) |
+ BIT(DRM_ROTATE_270) |
+ BIT(DRM_REFLECT_X) |
+ BIT(DRM_REFLECT_Y));
if (prop == NULL)
return;
priv->rotation_prop = prop;
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 4ec874da5668..bee9f72b3a93 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -5,7 +5,7 @@ config DRM_PANEL
Panel registration and lookup framework.
menu "Display Panels"
- depends on DRM_PANEL
+ depends on DRM && DRM_PANEL
config DRM_PANEL_SIMPLE
tristate "support for simple panels"
@@ -18,14 +18,11 @@ config DRM_PANEL_SIMPLE
config DRM_PANEL_LD9040
tristate "LD9040 RGB/SPI panel"
- depends on DRM && DRM_PANEL
- depends on OF
- select SPI
+ depends on OF && SPI
select VIDEOMODE_HELPERS
config DRM_PANEL_S6E8AA0
tristate "S6E8AA0 DSI video mode panel"
- depends on DRM && DRM_PANEL
depends on OF
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/panel/panel-ld9040.c b/drivers/gpu/drm/panel/panel-ld9040.c
index db1601fdbe29..42ac67b21e9f 100644
--- a/drivers/gpu/drm/panel/panel-ld9040.c
+++ b/drivers/gpu/drm/panel/panel-ld9040.c
@@ -110,7 +110,10 @@ struct ld9040 {
int error;
};
-#define panel_to_ld9040(p) container_of(p, struct ld9040, panel)
+static inline struct ld9040 *panel_to_ld9040(struct drm_panel *panel)
+{
+ return container_of(panel, struct ld9040, panel);
+}
static int ld9040_clear_error(struct ld9040 *ctx)
{
@@ -216,6 +219,11 @@ static int ld9040_power_off(struct ld9040 *ctx)
static int ld9040_disable(struct drm_panel *panel)
{
+ return 0;
+}
+
+static int ld9040_unprepare(struct drm_panel *panel)
+{
struct ld9040 *ctx = panel_to_ld9040(panel);
msleep(120);
@@ -228,7 +236,7 @@ static int ld9040_disable(struct drm_panel *panel)
return ld9040_power_off(ctx);
}
-static int ld9040_enable(struct drm_panel *panel)
+static int ld9040_prepare(struct drm_panel *panel)
{
struct ld9040 *ctx = panel_to_ld9040(panel);
int ret;
@@ -242,11 +250,16 @@ static int ld9040_enable(struct drm_panel *panel)
ret = ld9040_clear_error(ctx);
if (ret < 0)
- ld9040_disable(panel);
+ ld9040_unprepare(panel);
return ret;
}
+static int ld9040_enable(struct drm_panel *panel)
+{
+ return 0;
+}
+
static int ld9040_get_modes(struct drm_panel *panel)
{
struct drm_connector *connector = panel->connector;
@@ -273,6 +286,8 @@ static int ld9040_get_modes(struct drm_panel *panel)
static const struct drm_panel_funcs ld9040_drm_funcs = {
.disable = ld9040_disable,
+ .unprepare = ld9040_unprepare,
+ .prepare = ld9040_prepare,
.enable = ld9040_enable,
.get_modes = ld9040_get_modes,
};
diff --git a/drivers/gpu/drm/panel/panel-s6e8aa0.c b/drivers/gpu/drm/panel/panel-s6e8aa0.c
index 06e57a26db7a..b5217fe37f02 100644
--- a/drivers/gpu/drm/panel/panel-s6e8aa0.c
+++ b/drivers/gpu/drm/panel/panel-s6e8aa0.c
@@ -120,7 +120,10 @@ struct s6e8aa0 {
int error;
};
-#define panel_to_s6e8aa0(p) container_of(p, struct s6e8aa0, panel)
+static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
+{
+ return container_of(panel, struct s6e8aa0, panel);
+}
static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
{
@@ -133,14 +136,14 @@ static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
{
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- int ret;
+ ssize_t ret;
if (ctx->error < 0)
return;
- ret = mipi_dsi_dcs_write(dsi, dsi->channel, data, len);
+ ret = mipi_dsi_dcs_write(dsi, data, len);
if (ret < 0) {
- dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len,
+ dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret, len,
data);
ctx->error = ret;
}
@@ -154,7 +157,7 @@ static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len)
if (ctx->error < 0)
return ctx->error;
- ret = mipi_dsi_dcs_read(dsi, dsi->channel, cmd, data, len);
+ ret = mipi_dsi_dcs_read(dsi, cmd, data, len);
if (ret < 0) {
dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
ctx->error = ret;
@@ -889,6 +892,11 @@ static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
static int s6e8aa0_disable(struct drm_panel *panel)
{
+ return 0;
+}
+
+static int s6e8aa0_unprepare(struct drm_panel *panel)
+{
struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
@@ -900,7 +908,7 @@ static int s6e8aa0_disable(struct drm_panel *panel)
return s6e8aa0_power_off(ctx);
}
-static int s6e8aa0_enable(struct drm_panel *panel)
+static int s6e8aa0_prepare(struct drm_panel *panel)
{
struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
int ret;
@@ -913,11 +921,16 @@ static int s6e8aa0_enable(struct drm_panel *panel)
ret = ctx->error;
if (ret < 0)
- s6e8aa0_disable(panel);
+ s6e8aa0_unprepare(panel);
return ret;
}
+static int s6e8aa0_enable(struct drm_panel *panel)
+{
+ return 0;
+}
+
static int s6e8aa0_get_modes(struct drm_panel *panel)
{
struct drm_connector *connector = panel->connector;
@@ -944,6 +957,8 @@ static int s6e8aa0_get_modes(struct drm_panel *panel)
static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
.disable = s6e8aa0_disable,
+ .unprepare = s6e8aa0_unprepare,
+ .prepare = s6e8aa0_prepare,
.enable = s6e8aa0_enable,
.get_modes = s6e8aa0_get_modes,
};
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index a25136132c31..4ce1db0a68ff 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -37,14 +37,35 @@ struct panel_desc {
const struct drm_display_mode *modes;
unsigned int num_modes;
+ unsigned int bpc;
+
struct {
unsigned int width;
unsigned int height;
} size;
+
+ /**
+ * @prepare: the time (in milliseconds) that it takes for the panel to
+ * become ready and start receiving video data
+ * @enable: the time (in milliseconds) that it takes for the panel to
+ * display the first valid frame after starting to receive
+ * video data
+ * @disable: the time (in milliseconds) that it takes for the panel to
+ * turn the display off (no content is visible)
+ * @unprepare: the time (in milliseconds) that it takes for the panel
+ * to power itself down completely
+ */
+ struct {
+ unsigned int prepare;
+ unsigned int enable;
+ unsigned int disable;
+ unsigned int unprepare;
+ } delay;
};
struct panel_simple {
struct drm_panel base;
+ bool prepared;
bool enabled;
const struct panel_desc *desc;
@@ -87,6 +108,7 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
num++;
}
+ connector->display_info.bpc = panel->desc->bpc;
connector->display_info.width_mm = panel->desc->size.width;
connector->display_info.height_mm = panel->desc->size.height;
@@ -105,21 +127,40 @@ static int panel_simple_disable(struct drm_panel *panel)
backlight_update_status(p->backlight);
}
+ if (p->desc->delay.disable)
+ msleep(p->desc->delay.disable);
+
+ p->enabled = false;
+
+ return 0;
+}
+
+static int panel_simple_unprepare(struct drm_panel *panel)
+{
+ struct panel_simple *p = to_panel_simple(panel);
+
+ if (!p->prepared)
+ return 0;
+
if (p->enable_gpio)
gpiod_set_value_cansleep(p->enable_gpio, 0);
regulator_disable(p->supply);
- p->enabled = false;
+
+ if (p->desc->delay.unprepare)
+ msleep(p->desc->delay.unprepare);
+
+ p->prepared = false;
return 0;
}
-static int panel_simple_enable(struct drm_panel *panel)
+static int panel_simple_prepare(struct drm_panel *panel)
{
struct panel_simple *p = to_panel_simple(panel);
int err;
- if (p->enabled)
+ if (p->prepared)
return 0;
err = regulator_enable(p->supply);
@@ -131,6 +172,24 @@ static int panel_simple_enable(struct drm_panel *panel)
if (p->enable_gpio)
gpiod_set_value_cansleep(p->enable_gpio, 1);
+ if (p->desc->delay.prepare)
+ msleep(p->desc->delay.prepare);
+
+ p->prepared = true;
+
+ return 0;
+}
+
+static int panel_simple_enable(struct drm_panel *panel)
+{
+ struct panel_simple *p = to_panel_simple(panel);
+
+ if (p->enabled)
+ return 0;
+
+ if (p->desc->delay.enable)
+ msleep(p->desc->delay.enable);
+
if (p->backlight) {
p->backlight->props.power = FB_BLANK_UNBLANK;
backlight_update_status(p->backlight);
@@ -164,6 +223,8 @@ static int panel_simple_get_modes(struct drm_panel *panel)
static const struct drm_panel_funcs panel_simple_funcs = {
.disable = panel_simple_disable,
+ .unprepare = panel_simple_unprepare,
+ .prepare = panel_simple_prepare,
.enable = panel_simple_enable,
.get_modes = panel_simple_get_modes,
};
@@ -179,22 +240,21 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
return -ENOMEM;
panel->enabled = false;
+ panel->prepared = false;
panel->desc = desc;
panel->supply = devm_regulator_get(dev, "power");
if (IS_ERR(panel->supply))
return PTR_ERR(panel->supply);
- panel->enable_gpio = devm_gpiod_get(dev, "enable");
+ panel->enable_gpio = devm_gpiod_get_optional(dev, "enable");
if (IS_ERR(panel->enable_gpio)) {
err = PTR_ERR(panel->enable_gpio);
- if (err != -ENOENT) {
- dev_err(dev, "failed to request GPIO: %d\n", err);
- return err;
- }
+ dev_err(dev, "failed to request GPIO: %d\n", err);
+ return err;
+ }
- panel->enable_gpio = NULL;
- } else {
+ if (panel->enable_gpio) {
err = gpiod_direction_output(panel->enable_gpio, 0);
if (err < 0) {
dev_err(dev, "failed to setup GPIO: %d\n", err);
@@ -285,6 +345,7 @@ static const struct drm_display_mode auo_b101aw03_mode = {
static const struct panel_desc auo_b101aw03 = {
.modes = &auo_b101aw03_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 223,
.height = 125,
@@ -307,12 +368,40 @@ static const struct drm_display_mode auo_b133xtn01_mode = {
static const struct panel_desc auo_b133xtn01 = {
.modes = &auo_b133xtn01_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 293,
.height = 165,
},
};
+static const struct drm_display_mode auo_b133htn01_mode = {
+ .clock = 150660,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 172,
+ .hsync_end = 1920 + 172 + 80,
+ .htotal = 1920 + 172 + 80 + 60,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 25,
+ .vsync_end = 1080 + 25 + 10,
+ .vtotal = 1080 + 25 + 10 + 10,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc auo_b133htn01 = {
+ .modes = &auo_b133htn01_mode,
+ .num_modes = 1,
+ .size = {
+ .width = 293,
+ .height = 165,
+ },
+ .delay = {
+ .prepare = 105,
+ .enable = 20,
+ .unprepare = 50,
+ },
+};
+
static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
.clock = 72070,
.hdisplay = 1366,
@@ -329,6 +418,7 @@ static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
static const struct panel_desc chunghwa_claa101wa01a = {
.modes = &chunghwa_claa101wa01a_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 220,
.height = 120,
@@ -351,6 +441,7 @@ static const struct drm_display_mode chunghwa_claa101wb01_mode = {
static const struct panel_desc chunghwa_claa101wb01 = {
.modes = &chunghwa_claa101wb01_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 223,
.height = 125,
@@ -374,6 +465,7 @@ static const struct drm_display_mode edt_et057090dhu_mode = {
static const struct panel_desc edt_et057090dhu = {
.modes = &edt_et057090dhu_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 115,
.height = 86,
@@ -397,12 +489,82 @@ static const struct drm_display_mode edt_etm0700g0dh6_mode = {
static const struct panel_desc edt_etm0700g0dh6 = {
.modes = &edt_etm0700g0dh6_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 152,
.height = 91,
},
};
+static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
+ .clock = 32260,
+ .hdisplay = 800,
+ .hsync_start = 800 + 168,
+ .hsync_end = 800 + 168 + 64,
+ .htotal = 800 + 168 + 64 + 88,
+ .vdisplay = 480,
+ .vsync_start = 480 + 37,
+ .vsync_end = 480 + 37 + 2,
+ .vtotal = 480 + 37 + 2 + 8,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc foxlink_fl500wvr00_a0t = {
+ .modes = &foxlink_fl500wvr00_a0t_mode,
+ .num_modes = 1,
+ .size = {
+ .width = 108,
+ .height = 65,
+ },
+};
+
+static const struct drm_display_mode innolux_n116bge_mode = {
+ .clock = 71000,
+ .hdisplay = 1366,
+ .hsync_start = 1366 + 64,
+ .hsync_end = 1366 + 64 + 6,
+ .htotal = 1366 + 64 + 6 + 64,
+ .vdisplay = 768,
+ .vsync_start = 768 + 8,
+ .vsync_end = 768 + 8 + 4,
+ .vtotal = 768 + 8 + 4 + 8,
+ .vrefresh = 60,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+};
+
+static const struct panel_desc innolux_n116bge = {
+ .modes = &innolux_n116bge_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 256,
+ .height = 144,
+ },
+};
+
+static const struct drm_display_mode innolux_n156bge_l21_mode = {
+ .clock = 69300,
+ .hdisplay = 1366,
+ .hsync_start = 1366 + 16,
+ .hsync_end = 1366 + 16 + 34,
+ .htotal = 1366 + 16 + 34 + 50,
+ .vdisplay = 768,
+ .vsync_start = 768 + 2,
+ .vsync_end = 768 + 2 + 6,
+ .vtotal = 768 + 2 + 6 + 12,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc innolux_n156bge_l21 = {
+ .modes = &innolux_n156bge_l21_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 344,
+ .height = 193,
+ },
+};
+
static const struct drm_display_mode lg_lp129qe_mode = {
.clock = 285250,
.hdisplay = 2560,
@@ -419,6 +581,7 @@ static const struct drm_display_mode lg_lp129qe_mode = {
static const struct panel_desc lg_lp129qe = {
.modes = &lg_lp129qe_mode,
.num_modes = 1,
+ .bpc = 8,
.size = {
.width = 272,
.height = 181,
@@ -441,6 +604,7 @@ static const struct drm_display_mode samsung_ltn101nt05_mode = {
static const struct panel_desc samsung_ltn101nt05 = {
.modes = &samsung_ltn101nt05_mode,
.num_modes = 1,
+ .bpc = 6,
.size = {
.width = 1024,
.height = 600,
@@ -452,6 +616,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "auo,b101aw03",
.data = &auo_b101aw03,
}, {
+ .compatible = "auo,b133htn01",
+ .data = &auo_b133htn01,
+ }, {
.compatible = "auo,b133xtn01",
.data = &auo_b133xtn01,
}, {
@@ -470,14 +637,21 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "edt,etm0700g0dh6",
.data = &edt_etm0700g0dh6,
}, {
+ .compatible = "foxlink,fl500wvr00-a0t",
+ .data = &foxlink_fl500wvr00_a0t,
+ }, {
+ .compatible = "innolux,n116bge",
+ .data = &innolux_n116bge,
+ }, {
+ .compatible = "innolux,n156bge-l21",
+ .data = &innolux_n156bge_l21,
+ }, {
.compatible = "lg,lp129qe",
.data = &lg_lp129qe,
}, {
.compatible = "samsung,ltn101nt05",
.data = &samsung_ltn101nt05,
}, {
- .compatible = "simple-panel",
- }, {
/* sentinel */
}
};
@@ -545,7 +719,7 @@ static const struct panel_desc_dsi lg_ld070wx3_sl01 = {
.height = 151,
},
},
- .flags = MIPI_DSI_MODE_VIDEO,
+ .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
@@ -599,7 +773,8 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
.height = 136,
},
},
- .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+ .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS,
.format = MIPI_DSI_FMT_RGB888,
.lanes = 4,
};
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 5d7ea2461852..b8ced08b6291 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -835,7 +835,7 @@ static void qxl_conn_destroy(struct drm_connector *connector)
struct qxl_output *qxl_output =
drm_connector_to_qxl_output(connector);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(qxl_output);
}
@@ -902,7 +902,7 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
drm_object_attach_property(&connector->base,
qdev->hotplug_mode_update_property, 0);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 6e936634d65c..a3fd92029a14 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -38,7 +38,7 @@
#include "qxl_object.h"
extern int qxl_max_ioctls;
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+static const struct pci_device_id pciidlist[] = {
{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8,
0xffff00, 0 },
{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_OTHER << 8,
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index f437b30ce689..df567888bb1e 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -660,7 +660,7 @@ static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
return 0;
}
-static struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
.fb_probe = qxl_fb_find_or_create_single,
};
@@ -676,9 +676,12 @@ int qxl_fbdev_init(struct qxl_device *qdev)
qfbdev->qdev = qdev;
qdev->mode_info.qfbdev = qfbdev;
- qfbdev->helper.funcs = &qxl_fb_helper_funcs;
spin_lock_init(&qfbdev->delayed_ops_lock);
INIT_LIST_HEAD(&qfbdev->delayed_ops);
+
+ drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper,
+ &qxl_fb_helper_funcs);
+
ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper,
qxl_num_crtc /* num_crtc - QXL supports just 1 */,
QXLFB_CONN_LIMIT);
diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h
index d458a140c024..83a423293afd 100644
--- a/drivers/gpu/drm/qxl/qxl_object.h
+++ b/drivers/gpu/drm/qxl/qxl_object.h
@@ -31,7 +31,7 @@ static inline int qxl_bo_reserve(struct qxl_bo *bo, bool no_wait)
{
int r;
- r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+ r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS) {
struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
@@ -67,7 +67,7 @@ static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type,
{
int r;
- r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+ r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS) {
struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index dbcbfe80aac0..0013ad0db9ef 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -80,7 +80,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
- ci_dpm.o dce6_afmt.o radeon_vm.o
+ ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o
# add async DMA block
radeon-y += \
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 7d68203a3737..a7f2ddf09a9d 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -331,12 +331,10 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
&& (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
- /* get the native mode for LVDS */
- if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+ /* get the native mode for scaling */
+ if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
radeon_panel_mode_fixup(encoder, adjusted_mode);
-
- /* get the native mode for TV */
- if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
+ } else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
if (tv_dac) {
if (tv_dac->tv_std == TV_STD_NTSC ||
@@ -346,6 +344,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
else
radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
}
+ } else if (radeon_encoder->rmx_type != RMX_OFF) {
+ radeon_panel_mode_fixup(encoder, adjusted_mode);
}
if (ASIC_IS_DCE3(rdev) &&
@@ -716,7 +716,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_connector->use_digital &&
(radeon_connector->audio == RADEON_AUDIO_ENABLE))
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+ else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
@@ -735,7 +735,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+ else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
@@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
} else if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
- else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+ else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
(radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 584090ac3eb9..022561e28707 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -940,7 +940,18 @@ static void ci_get_leakage_voltages(struct radeon_device *rdev)
pi->vddc_leakage.count = 0;
pi->vddci_leakage.count = 0;
- if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
+ if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
+ for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
+ virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+ if (radeon_atom_get_voltage_evv(rdev, virtual_voltage_id, &vddc) != 0)
+ continue;
+ if (vddc != 0 && vddc != virtual_voltage_id) {
+ pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc;
+ pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id;
+ pi->vddc_leakage.count++;
+ }
+ }
+ } else if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) {
for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) {
virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
if (radeon_atom_get_leakage_vddc_based_on_leakage_params(rdev, &vddc, &vddci,
diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c
index 8debc9d47362..b630edc2fd0c 100644
--- a/drivers/gpu/drm/radeon/ci_smc.c
+++ b/drivers/gpu/drm/radeon/ci_smc.c
@@ -213,24 +213,37 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
if (!rdev->smc_fw)
return -EINVAL;
- switch (rdev->family) {
- case CHIP_BONAIRE:
- ucode_start_address = BONAIRE_SMC_UCODE_START;
- ucode_size = BONAIRE_SMC_UCODE_SIZE;
- break;
- case CHIP_HAWAII:
- ucode_start_address = HAWAII_SMC_UCODE_START;
- ucode_size = HAWAII_SMC_UCODE_SIZE;
- break;
- default:
- DRM_ERROR("unknown asic in smc ucode loader\n");
- BUG();
+ if (rdev->new_fw) {
+ const struct smc_firmware_header_v1_0 *hdr =
+ (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
+
+ radeon_ucode_print_smc_hdr(&hdr->header);
+
+ ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
+ ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
+ src = (const u8 *)
+ (rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ } else {
+ switch (rdev->family) {
+ case CHIP_BONAIRE:
+ ucode_start_address = BONAIRE_SMC_UCODE_START;
+ ucode_size = BONAIRE_SMC_UCODE_SIZE;
+ break;
+ case CHIP_HAWAII:
+ ucode_start_address = HAWAII_SMC_UCODE_START;
+ ucode_size = HAWAII_SMC_UCODE_SIZE;
+ break;
+ default:
+ DRM_ERROR("unknown asic in smc ucode loader\n");
+ BUG();
+ }
+
+ src = (const u8 *)rdev->smc_fw->data;
}
if (ucode_size & 3)
return -EINVAL;
- src = (const u8 *)rdev->smc_fw->data;
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
WREG32(SMC_IND_INDEX_0, ucode_start_address);
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index c0ea66192fe0..b625646bf3e2 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -42,6 +42,16 @@ MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin");
MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin");
MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin");
MODULE_FIRMWARE("radeon/BONAIRE_smc.bin");
+
+MODULE_FIRMWARE("radeon/bonaire_pfp.bin");
+MODULE_FIRMWARE("radeon/bonaire_me.bin");
+MODULE_FIRMWARE("radeon/bonaire_ce.bin");
+MODULE_FIRMWARE("radeon/bonaire_mec.bin");
+MODULE_FIRMWARE("radeon/bonaire_mc.bin");
+MODULE_FIRMWARE("radeon/bonaire_rlc.bin");
+MODULE_FIRMWARE("radeon/bonaire_sdma.bin");
+MODULE_FIRMWARE("radeon/bonaire_smc.bin");
+
MODULE_FIRMWARE("radeon/HAWAII_pfp.bin");
MODULE_FIRMWARE("radeon/HAWAII_me.bin");
MODULE_FIRMWARE("radeon/HAWAII_ce.bin");
@@ -51,18 +61,45 @@ MODULE_FIRMWARE("radeon/HAWAII_mc2.bin");
MODULE_FIRMWARE("radeon/HAWAII_rlc.bin");
MODULE_FIRMWARE("radeon/HAWAII_sdma.bin");
MODULE_FIRMWARE("radeon/HAWAII_smc.bin");
+
+MODULE_FIRMWARE("radeon/hawaii_pfp.bin");
+MODULE_FIRMWARE("radeon/hawaii_me.bin");
+MODULE_FIRMWARE("radeon/hawaii_ce.bin");
+MODULE_FIRMWARE("radeon/hawaii_mec.bin");
+MODULE_FIRMWARE("radeon/hawaii_mc.bin");
+MODULE_FIRMWARE("radeon/hawaii_rlc.bin");
+MODULE_FIRMWARE("radeon/hawaii_sdma.bin");
+MODULE_FIRMWARE("radeon/hawaii_smc.bin");
+
MODULE_FIRMWARE("radeon/KAVERI_pfp.bin");
MODULE_FIRMWARE("radeon/KAVERI_me.bin");
MODULE_FIRMWARE("radeon/KAVERI_ce.bin");
MODULE_FIRMWARE("radeon/KAVERI_mec.bin");
MODULE_FIRMWARE("radeon/KAVERI_rlc.bin");
MODULE_FIRMWARE("radeon/KAVERI_sdma.bin");
+
+MODULE_FIRMWARE("radeon/kaveri_pfp.bin");
+MODULE_FIRMWARE("radeon/kaveri_me.bin");
+MODULE_FIRMWARE("radeon/kaveri_ce.bin");
+MODULE_FIRMWARE("radeon/kaveri_mec.bin");
+MODULE_FIRMWARE("radeon/kaveri_mec2.bin");
+MODULE_FIRMWARE("radeon/kaveri_rlc.bin");
+MODULE_FIRMWARE("radeon/kaveri_sdma.bin");
+
MODULE_FIRMWARE("radeon/KABINI_pfp.bin");
MODULE_FIRMWARE("radeon/KABINI_me.bin");
MODULE_FIRMWARE("radeon/KABINI_ce.bin");
MODULE_FIRMWARE("radeon/KABINI_mec.bin");
MODULE_FIRMWARE("radeon/KABINI_rlc.bin");
MODULE_FIRMWARE("radeon/KABINI_sdma.bin");
+
+MODULE_FIRMWARE("radeon/kabini_pfp.bin");
+MODULE_FIRMWARE("radeon/kabini_me.bin");
+MODULE_FIRMWARE("radeon/kabini_ce.bin");
+MODULE_FIRMWARE("radeon/kabini_mec.bin");
+MODULE_FIRMWARE("radeon/kabini_rlc.bin");
+MODULE_FIRMWARE("radeon/kabini_sdma.bin");
+
MODULE_FIRMWARE("radeon/MULLINS_pfp.bin");
MODULE_FIRMWARE("radeon/MULLINS_me.bin");
MODULE_FIRMWARE("radeon/MULLINS_ce.bin");
@@ -70,6 +107,13 @@ MODULE_FIRMWARE("radeon/MULLINS_mec.bin");
MODULE_FIRMWARE("radeon/MULLINS_rlc.bin");
MODULE_FIRMWARE("radeon/MULLINS_sdma.bin");
+MODULE_FIRMWARE("radeon/mullins_pfp.bin");
+MODULE_FIRMWARE("radeon/mullins_me.bin");
+MODULE_FIRMWARE("radeon/mullins_ce.bin");
+MODULE_FIRMWARE("radeon/mullins_mec.bin");
+MODULE_FIRMWARE("radeon/mullins_rlc.bin");
+MODULE_FIRMWARE("radeon/mullins_sdma.bin");
+
extern int r600_ih_ring_alloc(struct radeon_device *rdev);
extern void r600_ih_ring_fini(struct radeon_device *rdev);
extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
@@ -1760,27 +1804,44 @@ static void cik_srbm_select(struct radeon_device *rdev,
*/
int ci_mc_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
+ const __be32 *fw_data = NULL;
+ const __le32 *new_fw_data = NULL;
u32 running, blackout = 0;
- u32 *io_mc_regs;
+ u32 *io_mc_regs = NULL;
+ const __le32 *new_io_mc_regs = NULL;
int i, regs_size, ucode_size;
if (!rdev->mc_fw)
return -EINVAL;
- ucode_size = rdev->mc_fw->size / 4;
+ if (rdev->new_fw) {
+ const struct mc_firmware_header_v1_0 *hdr =
+ (const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
- switch (rdev->family) {
- case CHIP_BONAIRE:
- io_mc_regs = (u32 *)&bonaire_io_mc_regs;
- regs_size = BONAIRE_IO_MC_REGS_SIZE;
- break;
- case CHIP_HAWAII:
- io_mc_regs = (u32 *)&hawaii_io_mc_regs;
- regs_size = HAWAII_IO_MC_REGS_SIZE;
- break;
- default:
- return -EINVAL;
+ radeon_ucode_print_mc_hdr(&hdr->header);
+
+ regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
+ new_io_mc_regs = (const __le32 *)
+ (rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
+ ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ new_fw_data = (const __le32 *)
+ (rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ } else {
+ ucode_size = rdev->mc_fw->size / 4;
+
+ switch (rdev->family) {
+ case CHIP_BONAIRE:
+ io_mc_regs = (u32 *)&bonaire_io_mc_regs;
+ regs_size = BONAIRE_IO_MC_REGS_SIZE;
+ break;
+ case CHIP_HAWAII:
+ io_mc_regs = (u32 *)&hawaii_io_mc_regs;
+ regs_size = HAWAII_IO_MC_REGS_SIZE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ fw_data = (const __be32 *)rdev->mc_fw->data;
}
running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1797,13 +1858,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev)
/* load mc io regs */
for (i = 0; i < regs_size; i++) {
- WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
- WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+ if (rdev->new_fw) {
+ WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
+ WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
+ } else {
+ WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
+ WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+ }
}
/* load the MC ucode */
- fw_data = (const __be32 *)rdev->mc_fw->data;
- for (i = 0; i < ucode_size; i++)
- WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+ for (i = 0; i < ucode_size; i++) {
+ if (rdev->new_fw)
+ WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+ else
+ WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+ }
/* put the engine back into the active state */
WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
@@ -1841,17 +1910,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev)
static int cik_init_microcode(struct radeon_device *rdev)
{
const char *chip_name;
+ const char *new_chip_name;
size_t pfp_req_size, me_req_size, ce_req_size,
mec_req_size, rlc_req_size, mc_req_size = 0,
sdma_req_size, smc_req_size = 0, mc2_req_size = 0;
char fw_name[30];
+ int new_fw = 0;
int err;
+ int num_fw;
DRM_DEBUG("\n");
switch (rdev->family) {
case CHIP_BONAIRE:
chip_name = "BONAIRE";
+ new_chip_name = "bonaire";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4;
@@ -1861,9 +1934,11 @@ static int cik_init_microcode(struct radeon_device *rdev)
mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4);
+ num_fw = 8;
break;
case CHIP_HAWAII:
chip_name = "HAWAII";
+ new_chip_name = "hawaii";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4;
@@ -1873,142 +1948,285 @@ static int cik_init_microcode(struct radeon_device *rdev)
mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4);
+ num_fw = 8;
break;
case CHIP_KAVERI:
chip_name = "KAVERI";
+ new_chip_name = "kaveri";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = KV_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+ num_fw = 7;
break;
case CHIP_KABINI:
chip_name = "KABINI";
+ new_chip_name = "kabini";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = KB_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+ num_fw = 6;
break;
case CHIP_MULLINS:
chip_name = "MULLINS";
+ new_chip_name = "mullins";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = ML_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+ num_fw = 6;
break;
default: BUG();
}
- DRM_INFO("Loading %s Microcode\n", chip_name);
+ DRM_INFO("Loading %s Microcode\n", new_chip_name);
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->pfp_fw->size != pfp_req_size) {
- printk(KERN_ERR
- "cik_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->pfp_fw->size, fw_name);
- err = -EINVAL;
- goto out;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
+ err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->pfp_fw->size != pfp_req_size) {
+ printk(KERN_ERR
+ "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->pfp_fw->size, fw_name);
+ err = -EINVAL;
+ goto out;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->pfp_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", new_chip_name);
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->me_fw->size != me_req_size) {
- printk(KERN_ERR
- "cik_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->me_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
+ err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->me_fw->size != me_req_size) {
+ printk(KERN_ERR
+ "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->me_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->me_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", new_chip_name);
err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->ce_fw->size != ce_req_size) {
- printk(KERN_ERR
- "cik_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->ce_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
+ err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->ce_fw->size != ce_req_size) {
+ printk(KERN_ERR
+ "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->ce_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->ce_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", new_chip_name);
err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->mec_fw->size != mec_req_size) {
- printk(KERN_ERR
- "cik_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->mec_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", chip_name);
+ err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->mec_fw->size != mec_req_size) {
+ printk(KERN_ERR
+ "cik_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->mec_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->mec_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
+ }
+
+ if (rdev->family == CHIP_KAVERI) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec2.bin", new_chip_name);
+ err = request_firmware(&rdev->mec2_fw, fw_name, rdev->dev);
+ if (err) {
+ goto out;
+ } else {
+ err = radeon_ucode_validate(rdev->mec2_fw);
+ if (err) {
+ goto out;
+ } else {
+ new_fw++;
+ }
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", new_chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->rlc_fw->size != rlc_req_size) {
- printk(KERN_ERR
- "cik_rlc: Bogus length %zu in firmware \"%s\"\n",
- rdev->rlc_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
+ err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->rlc_fw->size != rlc_req_size) {
+ printk(KERN_ERR
+ "cik_rlc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->rlc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->rlc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", new_chip_name);
err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->sdma_fw->size != sdma_req_size) {
- printk(KERN_ERR
- "cik_sdma: Bogus length %zu in firmware \"%s\"\n",
- rdev->sdma_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name);
+ err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->sdma_fw->size != sdma_req_size) {
+ printk(KERN_ERR
+ "cik_sdma: Bogus length %zu in firmware \"%s\"\n",
+ rdev->sdma_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->sdma_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
/* No SMC, MC ucode on APUs */
if (!(rdev->flags & RADEON_IS_IGP)) {
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) {
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
- if (err)
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ }
+ if ((rdev->mc_fw->size != mc_req_size) &&
+ (rdev->mc_fw->size != mc2_req_size)){
+ printk(KERN_ERR
+ "cik_mc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->mc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
+ } else {
+ err = radeon_ucode_validate(rdev->mc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
goto out;
+ } else {
+ new_fw++;
+ }
}
- if ((rdev->mc_fw->size != mc_req_size) &&
- (rdev->mc_fw->size != mc2_req_size)){
- printk(KERN_ERR
- "cik_mc: Bogus length %zu in firmware \"%s\"\n",
- rdev->mc_fw->size, fw_name);
- err = -EINVAL;
- }
- DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) {
- printk(KERN_ERR
- "smc: error loading firmware \"%s\"\n",
- fw_name);
- release_firmware(rdev->smc_fw);
- rdev->smc_fw = NULL;
- err = 0;
- } else if (rdev->smc_fw->size != smc_req_size) {
- printk(KERN_ERR
- "cik_smc: Bogus length %zu in firmware \"%s\"\n",
- rdev->smc_fw->size, fw_name);
- err = -EINVAL;
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
+ err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
+ if (err) {
+ printk(KERN_ERR
+ "smc: error loading firmware \"%s\"\n",
+ fw_name);
+ release_firmware(rdev->smc_fw);
+ rdev->smc_fw = NULL;
+ err = 0;
+ } else if (rdev->smc_fw->size != smc_req_size) {
+ printk(KERN_ERR
+ "cik_smc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->smc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->smc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "cik_fw: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
}
+ if (new_fw == 0) {
+ rdev->new_fw = false;
+ } else if (new_fw < num_fw) {
+ printk(KERN_ERR "ci_fw: mixing new and old firmware!\n");
+ err = -EINVAL;
+ } else {
+ rdev->new_fw = true;
+ }
+
out:
if (err) {
if (err != -EINVAL)
@@ -2021,8 +2239,14 @@ out:
rdev->me_fw = NULL;
release_firmware(rdev->ce_fw);
rdev->ce_fw = NULL;
+ release_firmware(rdev->mec_fw);
+ rdev->mec_fw = NULL;
+ release_firmware(rdev->mec2_fw);
+ rdev->mec2_fw = NULL;
release_firmware(rdev->rlc_fw);
rdev->rlc_fw = NULL;
+ release_firmware(rdev->sdma_fw);
+ rdev->sdma_fw = NULL;
release_firmware(rdev->mc_fw);
rdev->mc_fw = NULL;
release_firmware(rdev->smc_fw);
@@ -3666,8 +3890,6 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | DATA_SEL(1) | INT_SEL(2));
radeon_ring_write(ring, fence->seq);
radeon_ring_write(ring, 0);
- /* HDP flush */
- cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
}
/**
@@ -3696,8 +3918,6 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
radeon_ring_write(ring, upper_32_bits(addr));
radeon_ring_write(ring, fence->seq);
radeon_ring_write(ring, 0);
- /* HDP flush */
- cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
}
bool cik_semaphore_ring_emit(struct radeon_device *rdev,
@@ -3969,7 +4189,6 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable)
*/
static int cik_cp_gfx_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
int i;
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
@@ -3977,26 +4196,70 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev)
cik_cp_gfx_enable(rdev, false);
- /* PFP */
- fw_data = (const __be32 *)rdev->pfp_fw->data;
- WREG32(CP_PFP_UCODE_ADDR, 0);
- for (i = 0; i < CIK_PFP_UCODE_SIZE; i++)
- WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_PFP_UCODE_ADDR, 0);
-
- /* CE */
- fw_data = (const __be32 *)rdev->ce_fw->data;
- WREG32(CP_CE_UCODE_ADDR, 0);
- for (i = 0; i < CIK_CE_UCODE_SIZE; i++)
- WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_CE_UCODE_ADDR, 0);
-
- /* ME */
- fw_data = (const __be32 *)rdev->me_fw->data;
- WREG32(CP_ME_RAM_WADDR, 0);
- for (i = 0; i < CIK_ME_UCODE_SIZE; i++)
- WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_ME_RAM_WADDR, 0);
+ if (rdev->new_fw) {
+ const struct gfx_firmware_header_v1_0 *pfp_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+ const struct gfx_firmware_header_v1_0 *ce_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+ const struct gfx_firmware_header_v1_0 *me_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+ const __le32 *fw_data;
+ u32 fw_size;
+
+ radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
+ radeon_ucode_print_gfx_hdr(&ce_hdr->header);
+ radeon_ucode_print_gfx_hdr(&me_hdr->header);
+
+ /* PFP */
+ fw_data = (const __le32 *)
+ (rdev->pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+
+ /* CE */
+ fw_data = (const __le32 *)
+ (rdev->ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_CE_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_CE_UCODE_ADDR, 0);
+
+ /* ME */
+ fw_data = (const __be32 *)
+ (rdev->me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_ME_RAM_WADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_ME_RAM_WADDR, 0);
+ } else {
+ const __be32 *fw_data;
+
+ /* PFP */
+ fw_data = (const __be32 *)rdev->pfp_fw->data;
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < CIK_PFP_UCODE_SIZE; i++)
+ WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+
+ /* CE */
+ fw_data = (const __be32 *)rdev->ce_fw->data;
+ WREG32(CP_CE_UCODE_ADDR, 0);
+ for (i = 0; i < CIK_CE_UCODE_SIZE; i++)
+ WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_CE_UCODE_ADDR, 0);
+
+ /* ME */
+ fw_data = (const __be32 *)rdev->me_fw->data;
+ WREG32(CP_ME_RAM_WADDR, 0);
+ for (i = 0; i < CIK_ME_UCODE_SIZE; i++)
+ WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_ME_RAM_WADDR, 0);
+ }
WREG32(CP_PFP_UCODE_ADDR, 0);
WREG32(CP_CE_UCODE_ADDR, 0);
@@ -4261,7 +4524,6 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable)
*/
static int cik_cp_compute_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
int i;
if (!rdev->mec_fw)
@@ -4269,20 +4531,55 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev)
cik_cp_compute_enable(rdev, false);
- /* MEC1 */
- fw_data = (const __be32 *)rdev->mec_fw->data;
- WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
- for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
- WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+ if (rdev->new_fw) {
+ const struct gfx_firmware_header_v1_0 *mec_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
+ const __le32 *fw_data;
+ u32 fw_size;
+
+ radeon_ucode_print_gfx_hdr(&mec_hdr->header);
+
+ /* MEC1 */
+ fw_data = (const __le32 *)
+ (rdev->mec_fw->data + le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(mec_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
- if (rdev->family == CHIP_KAVERI) {
/* MEC2 */
+ if (rdev->family == CHIP_KAVERI) {
+ const struct gfx_firmware_header_v1_0 *mec2_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
+
+ fw_data = (const __le32 *)
+ (rdev->mec2_fw->data +
+ le32_to_cpu(mec2_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(mec2_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_MEC_ME2_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ }
+ } else {
+ const __be32 *fw_data;
+
+ /* MEC1 */
fw_data = (const __be32 *)rdev->mec_fw->data;
- WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
- WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
+
+ if (rdev->family == CHIP_KAVERI) {
+ /* MEC2 */
+ fw_data = (const __be32 *)rdev->mec_fw->data;
+ WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
+ WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
+ }
}
return 0;
@@ -4375,7 +4672,7 @@ static int cik_mec_init(struct radeon_device *rdev)
r = radeon_bo_create(rdev,
rdev->mec.num_mec *rdev->mec.num_pipe * MEC_HPD_SIZE * 2,
PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_GTT, NULL,
+ RADEON_GEM_DOMAIN_GTT, 0, NULL,
&rdev->mec.hpd_eop_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create HDP EOP bo failed\n", r);
@@ -4545,7 +4842,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
r = radeon_bo_create(rdev,
sizeof(struct bonaire_mqd),
PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_GTT, NULL,
+ RADEON_GEM_DOMAIN_GTT, 0, NULL,
&rdev->ring[idx].mqd_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create MQD bo failed\n", r);
@@ -5402,7 +5699,6 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup TLB control */
WREG32(MC_VM_MX_L1_TLB_CNTL,
(0xA << 7) |
@@ -5642,12 +5938,13 @@ static void cik_vm_decode_fault(struct radeon_device *rdev,
void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
{
struct radeon_ring *ring = &rdev->ring[ridx];
+ int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX);
if (vm == NULL)
return;
radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
WRITE_DATA_DST_SEL(0)));
if (vm->id < 8) {
radeon_ring_write(ring,
@@ -5697,7 +5994,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
radeon_ring_write(ring, 1 << vm->id);
/* compute doesn't have PFP */
- if (ridx == RADEON_RING_TYPE_GFX_INDEX) {
+ if (usepfp) {
/* sync PFP to ME, otherwise we might get invalid PFP reads */
radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
radeon_ring_write(ring, 0x0);
@@ -5865,28 +6162,10 @@ static void cik_rlc_start(struct radeon_device *rdev)
static int cik_rlc_resume(struct radeon_device *rdev)
{
u32 i, size, tmp;
- const __be32 *fw_data;
if (!rdev->rlc_fw)
return -EINVAL;
- switch (rdev->family) {
- case CHIP_BONAIRE:
- case CHIP_HAWAII:
- default:
- size = BONAIRE_RLC_UCODE_SIZE;
- break;
- case CHIP_KAVERI:
- size = KV_RLC_UCODE_SIZE;
- break;
- case CHIP_KABINI:
- size = KB_RLC_UCODE_SIZE;
- break;
- case CHIP_MULLINS:
- size = ML_RLC_UCODE_SIZE;
- break;
- }
-
cik_rlc_stop(rdev);
/* disable CG */
@@ -5910,11 +6189,45 @@ static int cik_rlc_resume(struct radeon_device *rdev)
WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0);
- fw_data = (const __be32 *)rdev->rlc_fw->data;
+ if (rdev->new_fw) {
+ const struct rlc_firmware_header_v1_0 *hdr =
+ (const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
+ const __le32 *fw_data = (const __le32 *)
+ (rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+ radeon_ucode_print_rlc_hdr(&hdr->header);
+
+ size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
WREG32(RLC_GPM_UCODE_ADDR, 0);
- for (i = 0; i < size; i++)
- WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(RLC_GPM_UCODE_ADDR, 0);
+ for (i = 0; i < size; i++)
+ WREG32(RLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(RLC_GPM_UCODE_ADDR, 0);
+ } else {
+ const __be32 *fw_data;
+
+ switch (rdev->family) {
+ case CHIP_BONAIRE:
+ case CHIP_HAWAII:
+ default:
+ size = BONAIRE_RLC_UCODE_SIZE;
+ break;
+ case CHIP_KAVERI:
+ size = KV_RLC_UCODE_SIZE;
+ break;
+ case CHIP_KABINI:
+ size = KB_RLC_UCODE_SIZE;
+ break;
+ case CHIP_MULLINS:
+ size = ML_RLC_UCODE_SIZE;
+ break;
+ }
+
+ fw_data = (const __be32 *)rdev->rlc_fw->data;
+ WREG32(RLC_GPM_UCODE_ADDR, 0);
+ for (i = 0; i < size; i++)
+ WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(RLC_GPM_UCODE_ADDR, 0);
+ }
/* XXX - find out what chips support lbpw */
cik_enable_lbpw(rdev, false);
@@ -6348,11 +6661,10 @@ static void cik_enable_gds_pg(struct radeon_device *rdev, bool enable)
void cik_init_cp_pg_table(struct radeon_device *rdev)
{
- const __be32 *fw_data;
volatile u32 *dst_ptr;
int me, i, max_me = 4;
u32 bo_offset = 0;
- u32 table_offset;
+ u32 table_offset, table_size;
if (rdev->family == CHIP_KAVERI)
max_me = 5;
@@ -6363,24 +6675,71 @@ void cik_init_cp_pg_table(struct radeon_device *rdev)
/* write the cp table buffer */
dst_ptr = rdev->rlc.cp_table_ptr;
for (me = 0; me < max_me; me++) {
- if (me == 0) {
- fw_data = (const __be32 *)rdev->ce_fw->data;
- table_offset = CP_ME_TABLE_OFFSET;
- } else if (me == 1) {
- fw_data = (const __be32 *)rdev->pfp_fw->data;
- table_offset = CP_ME_TABLE_OFFSET;
- } else if (me == 2) {
- fw_data = (const __be32 *)rdev->me_fw->data;
- table_offset = CP_ME_TABLE_OFFSET;
+ if (rdev->new_fw) {
+ const __le32 *fw_data;
+ const struct gfx_firmware_header_v1_0 *hdr;
+
+ if (me == 0) {
+ hdr = (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+ fw_data = (const __le32 *)
+ (rdev->ce_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ table_offset = le32_to_cpu(hdr->jt_offset);
+ table_size = le32_to_cpu(hdr->jt_size);
+ } else if (me == 1) {
+ hdr = (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+ fw_data = (const __le32 *)
+ (rdev->pfp_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ table_offset = le32_to_cpu(hdr->jt_offset);
+ table_size = le32_to_cpu(hdr->jt_size);
+ } else if (me == 2) {
+ hdr = (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+ fw_data = (const __le32 *)
+ (rdev->me_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ table_offset = le32_to_cpu(hdr->jt_offset);
+ table_size = le32_to_cpu(hdr->jt_size);
+ } else if (me == 3) {
+ hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
+ fw_data = (const __le32 *)
+ (rdev->mec_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ table_offset = le32_to_cpu(hdr->jt_offset);
+ table_size = le32_to_cpu(hdr->jt_size);
+ } else {
+ hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
+ fw_data = (const __le32 *)
+ (rdev->mec2_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ table_offset = le32_to_cpu(hdr->jt_offset);
+ table_size = le32_to_cpu(hdr->jt_size);
+ }
+
+ for (i = 0; i < table_size; i ++) {
+ dst_ptr[bo_offset + i] =
+ cpu_to_le32(le32_to_cpu(fw_data[table_offset + i]));
+ }
+ bo_offset += table_size;
} else {
- fw_data = (const __be32 *)rdev->mec_fw->data;
- table_offset = CP_MEC_TABLE_OFFSET;
- }
+ const __be32 *fw_data;
+ table_size = CP_ME_TABLE_SIZE;
+
+ if (me == 0) {
+ fw_data = (const __be32 *)rdev->ce_fw->data;
+ table_offset = CP_ME_TABLE_OFFSET;
+ } else if (me == 1) {
+ fw_data = (const __be32 *)rdev->pfp_fw->data;
+ table_offset = CP_ME_TABLE_OFFSET;
+ } else if (me == 2) {
+ fw_data = (const __be32 *)rdev->me_fw->data;
+ table_offset = CP_ME_TABLE_OFFSET;
+ } else {
+ fw_data = (const __be32 *)rdev->mec_fw->data;
+ table_offset = CP_MEC_TABLE_OFFSET;
+ }
- for (i = 0; i < CP_ME_TABLE_SIZE; i ++) {
- dst_ptr[bo_offset + i] = cpu_to_le32(be32_to_cpu(fw_data[table_offset + i]));
+ for (i = 0; i < table_size; i ++) {
+ dst_ptr[bo_offset + i] =
+ cpu_to_le32(be32_to_cpu(fw_data[table_offset + i]));
+ }
+ bo_offset += table_size;
}
- bo_offset += CP_ME_TABLE_SIZE;
}
}
@@ -7618,7 +7977,8 @@ restart_ih:
case 16: /* D5 page flip */
case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
- radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+ if (radeon_use_pflipirq > 0)
+ radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break;
case 42: /* HPD hotplug */
switch (src_data) {
@@ -7900,6 +8260,7 @@ restart_ih:
static int cik_startup(struct radeon_device *rdev)
{
struct radeon_ring *ring;
+ u32 nop;
int r;
/* enable pcie gen2/3 link */
@@ -8033,9 +8394,18 @@ static int cik_startup(struct radeon_device *rdev)
}
cik_irq_set(rdev);
+ if (rdev->family == CHIP_HAWAII) {
+ if (rdev->new_fw)
+ nop = PACKET3(PACKET3_NOP, 0x3FFF);
+ else
+ nop = RADEON_CP_PACKET2;
+ } else {
+ nop = PACKET3(PACKET3_NOP, 0x3FFF);
+ }
+
ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
- PACKET3(PACKET3_NOP, 0x3FFF));
+ nop);
if (r)
return r;
@@ -8043,7 +8413,7 @@ static int cik_startup(struct radeon_device *rdev)
/* type-2 packets are deprecated on MEC, use type-3 instead */
ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
- PACKET3(PACKET3_NOP, 0x3FFF));
+ nop);
if (r)
return r;
ring->me = 1; /* first MEC */
@@ -8054,7 +8424,7 @@ static int cik_startup(struct radeon_device *rdev)
/* type-2 packets are deprecated on MEC, use type-3 instead */
ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
- PACKET3(PACKET3_NOP, 0x3FFF));
+ nop);
if (r)
return r;
/* dGPU only have 1 MEC */
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
index 8e9d0f1d858e..bcf480510ac2 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -24,6 +24,7 @@
#include <linux/firmware.h>
#include <drm/drmP.h>
#include "radeon.h"
+#include "radeon_ucode.h"
#include "radeon_asic.h"
#include "radeon_trace.h"
#include "cikd.h"
@@ -118,6 +119,7 @@ void cik_sdma_set_wptr(struct radeon_device *rdev,
reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+ (void)RREG32(reg);
}
/**
@@ -419,7 +421,6 @@ static int cik_sdma_rlc_resume(struct radeon_device *rdev)
*/
static int cik_sdma_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
int i;
if (!rdev->sdma_fw)
@@ -428,19 +429,48 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev)
/* halt the MEs */
cik_sdma_enable(rdev, false);
- /* sdma0 */
- fw_data = (const __be32 *)rdev->sdma_fw->data;
- WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
- for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
- WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
- WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
-
- /* sdma1 */
- fw_data = (const __be32 *)rdev->sdma_fw->data;
- WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
- for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
- WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
- WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+ if (rdev->new_fw) {
+ const struct sdma_firmware_header_v1_0 *hdr =
+ (const struct sdma_firmware_header_v1_0 *)rdev->sdma_fw->data;
+ const __le32 *fw_data;
+ u32 fw_size;
+
+ radeon_ucode_print_sdma_hdr(&hdr->header);
+
+ /* sdma0 */
+ fw_data = (const __le32 *)
+ (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+ WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+ /* sdma1 */
+ fw_data = (const __le32 *)
+ (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, le32_to_cpup(fw_data++));
+ WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+ } else {
+ const __be32 *fw_data;
+
+ /* sdma0 */
+ fw_data = (const __be32 *)rdev->sdma_fw->data;
+ WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
+ for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+ WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+ WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+
+ /* sdma1 */
+ fw_data = (const __be32 *)rdev->sdma_fw->data;
+ WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
+ for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
+ WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
+ WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
+ }
WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
@@ -719,7 +749,43 @@ bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
}
/**
- * cik_sdma_vm_set_page - update the page tables using sDMA
+ * cik_sdma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using sDMA (CIK).
+ */
+void cik_sdma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count)
+{
+ while (count) {
+ unsigned bytes = count * 8;
+ if (bytes > 0x1FFFF8)
+ bytes = 0x1FFFF8;
+
+ ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY,
+ SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+ ib->ptr[ib->length_dw++] = bytes;
+ ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
+ ib->ptr[ib->length_dw++] = lower_32_bits(src);
+ ib->ptr[ib->length_dw++] = upper_32_bits(src);
+ ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+
+ pe += bytes;
+ src += bytes;
+ count -= bytes / 8;
+ }
+}
+
+/**
+ * cik_sdma_vm_write_pages - update PTEs by writing them manually
*
* @rdev: radeon_device pointer
* @ib: indirect buffer to fill with commands
@@ -729,84 +795,103 @@ bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
* @incr: increase next addr by incr bytes
* @flags: access flags
*
- * Update the page tables using sDMA (CIK).
+ * Update PTEs by writing them manually using sDMA (CIK).
*/
-void cik_sdma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags)
+void cik_sdma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
{
uint64_t value;
unsigned ndw;
- trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
- if (flags == R600_PTE_GART) {
- uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
- while (count) {
- unsigned bytes = count * 8;
- if (bytes > 0x1FFFF8)
- bytes = 0x1FFFF8;
-
- ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
- ib->ptr[ib->length_dw++] = bytes;
- ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
- ib->ptr[ib->length_dw++] = lower_32_bits(src);
- ib->ptr[ib->length_dw++] = upper_32_bits(src);
- ib->ptr[ib->length_dw++] = lower_32_bits(pe);
- ib->ptr[ib->length_dw++] = upper_32_bits(pe);
-
- pe += bytes;
- src += bytes;
- count -= bytes / 8;
- }
- } else if (flags & R600_PTE_SYSTEM) {
- while (count) {
- ndw = count * 2;
- if (ndw > 0xFFFFE)
- ndw = 0xFFFFE;
-
- /* for non-physically contiguous pages (system) */
- ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
- ib->ptr[ib->length_dw++] = pe;
- ib->ptr[ib->length_dw++] = upper_32_bits(pe);
- ib->ptr[ib->length_dw++] = ndw;
- for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ /* for non-physically contiguous pages (system) */
+ ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_WRITE,
+ SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
+ ib->ptr[ib->length_dw++] = pe;
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+ ib->ptr[ib->length_dw++] = ndw;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ if (flags & R600_PTE_SYSTEM) {
value = radeon_vm_map_gart(rdev, addr);
value &= 0xFFFFFFFFFFFFF000ULL;
- addr += incr;
- value |= flags;
- ib->ptr[ib->length_dw++] = value;
- ib->ptr[ib->length_dw++] = upper_32_bits(value);
- }
- }
- } else {
- while (count) {
- ndw = count;
- if (ndw > 0x7FFFF)
- ndw = 0x7FFFF;
-
- if (flags & R600_PTE_VALID)
+ } else if (flags & R600_PTE_VALID) {
value = addr;
- else
+ } else {
value = 0;
- /* for physically contiguous pages (vram) */
- ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
- ib->ptr[ib->length_dw++] = pe; /* dst addr */
- ib->ptr[ib->length_dw++] = upper_32_bits(pe);
- ib->ptr[ib->length_dw++] = flags; /* mask */
- ib->ptr[ib->length_dw++] = 0;
- ib->ptr[ib->length_dw++] = value; /* value */
+ }
+ addr += incr;
+ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value);
- ib->ptr[ib->length_dw++] = incr; /* increment size */
- ib->ptr[ib->length_dw++] = 0;
- ib->ptr[ib->length_dw++] = ndw; /* number of entries */
- pe += ndw * 8;
- addr += ndw * incr;
- count -= ndw;
}
}
+}
+
+/**
+ * cik_sdma_vm_set_pages - update the page tables using sDMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: access flags
+ *
+ * Update the page tables using sDMA (CIK).
+ */
+void cik_sdma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+{
+ uint64_t value;
+ unsigned ndw;
+
+ while (count) {
+ ndw = count;
+ if (ndw > 0x7FFFF)
+ ndw = 0x7FFFF;
+
+ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+
+ /* for physically contiguous pages (vram) */
+ ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ ib->ptr[ib->length_dw++] = incr; /* increment size */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = ndw; /* number of entries */
+
+ pe += ndw * 8;
+ addr += ndw * incr;
+ count -= ndw;
+ }
+}
+
+/**
+ * cik_sdma_vm_pad_ib - pad the IB to the required number of dw
+ *
+ * @ib: indirect buffer to fill with padding
+ *
+ */
+void cik_sdma_vm_pad_ib(struct radeon_ib *ib)
+{
while (ib->length_dw & 0x7)
ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0);
}
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 0a65dc7e93e7..ab29f953a767 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -136,13 +136,13 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
AUDIO_LIPSYNC(connector->audio_latency[1]);
else
- tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+ tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
} else {
if (connector->latency_present[0])
tmp = VIDEO_LIPSYNC(connector->video_latency[0]) |
AUDIO_LIPSYNC(connector->audio_latency[0]);
else
- tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+ tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
}
WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
}
@@ -164,8 +164,10 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
offset = dig->afmt->pin->offset;
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
+ if (connector->encoder == encoder) {
radeon_connector = to_radeon_connector(connector);
+ break;
+ }
}
if (!radeon_connector) {
@@ -173,7 +175,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
if (sad_count <= 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
return;
@@ -225,8 +227,10 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
offset = dig->afmt->pin->offset;
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
+ if (connector->encoder == encoder) {
radeon_connector = to_radeon_connector(connector);
+ break;
+ }
}
if (!radeon_connector) {
@@ -234,7 +238,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+ sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
if (sad_count <= 0) {
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
return;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 15e4f28015e1..4fedd14e670a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2424,7 +2424,6 @@ static int evergreen_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup L2 cache */
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
@@ -2677,7 +2676,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
if (save->crtc_enabled[i]) {
if (ASIC_IS_DCE6(rdev)) {
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
- tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+ tmp &= ~EVERGREEN_CRTC_BLANK_DATA_EN;
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
@@ -4023,7 +4022,8 @@ int sumo_rlc_init(struct radeon_device *rdev)
/* save restore block */
if (rdev->rlc.save_restore_obj == NULL) {
r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.save_restore_obj);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+ &rdev->rlc.save_restore_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r);
return r;
@@ -4101,7 +4101,8 @@ int sumo_rlc_init(struct radeon_device *rdev)
if (rdev->rlc.clear_state_obj == NULL) {
r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.clear_state_obj);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+ &rdev->rlc.clear_state_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r);
sumo_rlc_fini(rdev);
@@ -4175,8 +4176,10 @@ int sumo_rlc_init(struct radeon_device *rdev)
if (rdev->rlc.cp_table_size) {
if (rdev->rlc.cp_table_obj == NULL) {
- r = radeon_bo_create(rdev, rdev->rlc.cp_table_size, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.cp_table_obj);
+ r = radeon_bo_create(rdev, rdev->rlc.cp_table_size,
+ PAGE_SIZE, true,
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL,
+ &rdev->rlc.cp_table_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create RLC cp table bo failed\n", r);
sumo_rlc_fini(rdev);
@@ -4961,7 +4964,8 @@ restart_ih:
case 16: /* D5 page flip */
case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
- radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+ if (radeon_use_pflipirq > 0)
+ radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break;
case 42: /* HPD hotplug */
switch (src_data) {
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 1ec0e6e83f9f..278c7a139d74 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -117,7 +117,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
if (sad_count <= 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
return;
@@ -172,7 +172,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
return;
}
- sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+ sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
if (sad_count <= 0) {
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
return;
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 5a33ca681867..327b85f7fd0d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1229,7 +1229,6 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup TLB control */
WREG32(MC_VM_MX_L1_TLB_CNTL,
(0xA << 7) |
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
index 6378e0276691..8a3e6221cece 100644
--- a/drivers/gpu/drm/radeon/ni_dma.c
+++ b/drivers/gpu/drm/radeon/ni_dma.c
@@ -307,7 +307,43 @@ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
}
/**
- * cayman_dma_vm_set_page - update the page tables using the DMA
+ * cayman_dma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr where to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using the DMA (cayman/TN).
+ */
+void cayman_dma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count)
+{
+ unsigned ndw;
+
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
+ 0, 0, ndw);
+ ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+ ib->ptr[ib->length_dw++] = lower_32_bits(src);
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
+
+ pe += ndw * 4;
+ src += ndw * 4;
+ count -= ndw / 2;
+ }
+}
+
+/**
+ * cayman_dma_vm_write_pages - update PTEs by writing them manually
*
* @rdev: radeon_device pointer
* @ib: indirect buffer to fill with commands
@@ -315,71 +351,103 @@ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
* @addr: dst addr to write into pe
* @count: number of page entries to update
* @incr: increase next addr by incr bytes
- * @flags: hw access flags
+ * @flags: hw access flags
*
- * Update the page tables using the DMA (cayman/TN).
+ * Update PTEs by writing them manually using the DMA (cayman/TN).
*/
-void cayman_dma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags)
+void cayman_dma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
{
uint64_t value;
unsigned ndw;
- trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
- if ((flags & R600_PTE_SYSTEM) || (count == 1)) {
- while (count) {
- ndw = count * 2;
- if (ndw > 0xFFFFE)
- ndw = 0xFFFFE;
-
- /* for non-physically contiguous pages (system) */
- ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw);
- ib->ptr[ib->length_dw++] = pe;
- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
- for (; ndw > 0; ndw -= 2, --count, pe += 8) {
- if (flags & R600_PTE_SYSTEM) {
- value = radeon_vm_map_gart(rdev, addr);
- value &= 0xFFFFFFFFFFFFF000ULL;
- } else if (flags & R600_PTE_VALID) {
- value = addr;
- } else {
- value = 0;
- }
- addr += incr;
- value |= flags;
- ib->ptr[ib->length_dw++] = value;
- ib->ptr[ib->length_dw++] = upper_32_bits(value);
- }
- }
- } else {
- while (count) {
- ndw = count * 2;
- if (ndw > 0xFFFFE)
- ndw = 0xFFFFE;
-
- if (flags & R600_PTE_VALID)
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ /* for non-physically contiguous pages (system) */
+ ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE,
+ 0, 0, ndw);
+ ib->ptr[ib->length_dw++] = pe;
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ if (flags & R600_PTE_SYSTEM) {
+ value = radeon_vm_map_gart(rdev, addr);
+ value &= 0xFFFFFFFFFFFFF000ULL;
+ } else if (flags & R600_PTE_VALID) {
value = addr;
- else
+ } else {
value = 0;
- /* for physically contiguous pages (vram) */
- ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
- ib->ptr[ib->length_dw++] = pe; /* dst addr */
- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
- ib->ptr[ib->length_dw++] = flags; /* mask */
- ib->ptr[ib->length_dw++] = 0;
- ib->ptr[ib->length_dw++] = value; /* value */
+ }
+ addr += incr;
+ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value);
- ib->ptr[ib->length_dw++] = incr; /* increment size */
- ib->ptr[ib->length_dw++] = 0;
- pe += ndw * 4;
- addr += (ndw / 2) * incr;
- count -= ndw / 2;
}
}
+}
+
+/**
+ * cayman_dma_vm_set_pages - update the page tables using the DMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: hw access flags
+ *
+ * Update the page tables using the DMA (cayman/TN).
+ */
+void cayman_dma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+{
+ uint64_t value;
+ unsigned ndw;
+
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+
+ /* for physically contiguous pages (vram) */
+ ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ ib->ptr[ib->length_dw++] = incr; /* increment size */
+ ib->ptr[ib->length_dw++] = 0;
+
+ pe += ndw * 4;
+ addr += (ndw / 2) * incr;
+ count -= ndw / 2;
+ }
+}
+
+/**
+ * cayman_dma_vm_pad_ib - pad the IB to the required number of dw
+ *
+ * @ib: indirect buffer to fill with padding
+ *
+ */
+void cayman_dma_vm_pad_ib(struct radeon_ib *ib)
+{
while (ib->length_dw & 0x7)
ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0);
}
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 1544efcf1c3a..04b5940b8923 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -652,7 +652,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
{
uint32_t tmp;
- radeon_gart_restore(rdev);
/* discard memory request outside of configured range */
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
WREG32(RADEON_AIC_CNTL, tmp);
@@ -683,7 +682,7 @@ void r100_pci_gart_disable(struct radeon_device *rdev)
}
void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr)
+ uint64_t addr, uint32_t flags)
{
u32 *gtt = rdev->gart.ptr;
gtt[i] = cpu_to_le32(lower_32_bits(addr));
@@ -838,11 +837,7 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
/* Wait until IDLE & CLEAN */
radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
radeon_ring_write(ring, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
- radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
- radeon_ring_write(ring, rdev->config.r100.hdp_cntl |
- RADEON_HDP_READ_BUFFER_INVALIDATE);
- radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
- radeon_ring_write(ring, rdev->config.r100.hdp_cntl);
+ r100_ring_hdp_flush(rdev, ring);
/* Emit fence sequence & fire IRQ */
radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0));
radeon_ring_write(ring, fence->seq);
@@ -1061,6 +1056,20 @@ void r100_gfx_set_wptr(struct radeon_device *rdev,
(void)RREG32(RADEON_CP_RB_WPTR);
}
+/**
+ * r100_ring_hdp_flush - flush Host Data Path via the ring buffer
+ * rdev: radeon device structure
+ * ring: ring buffer struct for emitting packets
+ */
+void r100_ring_hdp_flush(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+ radeon_ring_write(ring, rdev->config.r100.hdp_cntl |
+ RADEON_HDP_READ_BUFFER_INVALIDATE);
+ radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+ radeon_ring_write(ring, rdev->config.r100.hdp_cntl);
+}
+
static void r100_cp_load_microcode(struct radeon_device *rdev)
{
const __be32 *fw_data;
@@ -1401,7 +1410,6 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
*/
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
{
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
struct radeon_cs_packet p3reloc, waitreloc;
@@ -1441,12 +1449,11 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 5);
reg = R100_CP_PACKET0_GET_REG(header);
- obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+ if (!crtc) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
return -ENOENT;
}
- crtc = obj_to_crtc(obj);
radeon_crtc = to_radeon_crtc(crtc);
crtc_id = radeon_crtc->crtc_id;
@@ -4067,39 +4074,6 @@ int r100_init(struct radeon_device *rdev)
return 0;
}
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
- bool always_indirect)
-{
- if (reg < rdev->rmmio_size && !always_indirect)
- return readl(((void __iomem *)rdev->rmmio) + reg);
- else {
- unsigned long flags;
- uint32_t ret;
-
- spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
- writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
- ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
- spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
-
- return ret;
- }
-}
-
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
- bool always_indirect)
-{
- if (reg < rdev->rmmio_size && !always_indirect)
- writel(v, ((void __iomem *)rdev->rmmio) + reg);
- else {
- unsigned long flags;
-
- spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
- writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
- writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
- spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
- }
-}
-
u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
{
if (reg < rdev->rio_mem_size)
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 3c21d77a483d..75b30338c226 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -69,17 +69,23 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
mb();
}
+#define R300_PTE_UNSNOOPED (1 << 0)
#define R300_PTE_WRITEABLE (1 << 2)
#define R300_PTE_READABLE (1 << 3)
void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr)
+ uint64_t addr, uint32_t flags)
{
void __iomem *ptr = rdev->gart.ptr;
addr = (lower_32_bits(addr) >> 8) |
- ((upper_32_bits(addr) & 0xff) << 24) |
- R300_PTE_WRITEABLE | R300_PTE_READABLE;
+ ((upper_32_bits(addr) & 0xff) << 24);
+ if (flags & RADEON_GART_PAGE_READ)
+ addr |= R300_PTE_READABLE;
+ if (flags & RADEON_GART_PAGE_WRITE)
+ addr |= R300_PTE_WRITEABLE;
+ if (!(flags & RADEON_GART_PAGE_SNOOP))
+ addr |= R300_PTE_UNSNOOPED;
/* on x86 we want this to be CPU endian, on powerpc
* on powerpc without HW swappers, it'll get swapped on way
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
@@ -120,7 +126,6 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* discard memory request outside of configured range */
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 3c69f58e46ef..c70a504d96af 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -968,7 +968,6 @@ static int r600_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup L2 cache */
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
@@ -1339,7 +1338,7 @@ int r600_vram_scratch_init(struct radeon_device *rdev)
if (rdev->vram_scratch.robj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
- NULL, &rdev->vram_scratch.robj);
+ 0, NULL, &rdev->vram_scratch.robj);
if (r) {
return r;
}
@@ -3227,7 +3226,7 @@ int r600_ih_ring_alloc(struct radeon_device *rdev)
if (rdev->ih.ring_obj == NULL) {
r = radeon_bo_create(rdev, rdev->ih.ring_size,
PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_GTT,
+ RADEON_GEM_DOMAIN_GTT, 0,
NULL, &rdev->ih.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r);
@@ -3924,11 +3923,13 @@ restart_ih:
break;
case 9: /* D1 pflip */
DRM_DEBUG("IH: D1 flip\n");
- radeon_crtc_handle_flip(rdev, 0);
+ if (radeon_use_pflipirq > 0)
+ radeon_crtc_handle_flip(rdev, 0);
break;
case 11: /* D2 pflip */
DRM_DEBUG("IH: D2 flip\n");
- radeon_crtc_handle_flip(rdev, 1);
+ if (radeon_use_pflipirq > 0)
+ radeon_crtc_handle_flip(rdev, 1);
break;
case 19: /* HPD/DAC hotplug */
switch (src_data) {
@@ -4089,16 +4090,15 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
}
/**
- * r600_ioctl_wait_idle - flush host path cache on wait idle ioctl
+ * r600_mmio_hdp_flush - flush Host Data Path cache via MMIO
* rdev: radeon device structure
- * bo: buffer object struct which userspace is waiting for idle
*
- * Some R6XX/R7XX doesn't seems to take into account HDP flush performed
- * through ring buffer, this leads to corruption in rendering, see
- * http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we
- * directly perform HDP flush by writing register through MMIO.
+ * Some R6XX/R7XX don't seem to take into account HDP flushes performed
+ * through the ring buffer. This leads to corruption in rendering, see
+ * http://bugzilla.kernel.org/show_bug.cgi?id=15186 . To avoid this, we
+ * directly perform the HDP flush by writing the register through MMIO.
*/
-void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
+void r600_mmio_hdp_flush(struct radeon_device *rdev)
{
/* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
* rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 12511bb5fd6f..c47537a1ddba 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -825,7 +825,6 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
uint32_t *vline_start_end,
uint32_t *vline_status)
{
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
struct radeon_cs_packet p3reloc, wait_reg_mem;
@@ -887,12 +886,11 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
reg = R600_CP_PACKET0_GET_REG(header);
- obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+ if (!crtc) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
return -ENOENT;
}
- crtc = obj_to_crtc(obj);
radeon_crtc = to_radeon_crtc(crtc);
crtc_id = radeon_crtc->crtc_id;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 60c47f829122..9e1732eb402c 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -64,6 +64,7 @@
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/kref.h>
+#include <linux/interval_tree.h>
#include <ttm/ttm_bo_api.h>
#include <ttm/ttm_bo_driver.h>
@@ -103,6 +104,7 @@ extern int radeon_hard_reset;
extern int radeon_vm_size;
extern int radeon_vm_block_size;
extern int radeon_deep_color;
+extern int radeon_use_pflipirq;
/*
* Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -304,6 +306,9 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r
u16 *vddc, u16 *vddci,
u16 virtual_voltage_id,
u16 vbios_voltage_id);
+int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
+ u16 virtual_voltage_id,
+ u16 *voltage);
int radeon_atom_round_to_true_voltage(struct radeon_device *rdev,
u8 voltage_type,
u16 nominal_voltage,
@@ -317,6 +322,9 @@ int radeon_atom_get_voltage_table(struct radeon_device *rdev,
struct atom_voltage_table *voltage_table);
bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
u8 voltage_type, u8 voltage_mode);
+int radeon_atom_get_svi2_info(struct radeon_device *rdev,
+ u8 voltage_type,
+ u8 *svd_gpio_id, u8 *svc_gpio_id);
void radeon_atom_update_memory_dll(struct radeon_device *rdev,
u32 mem_clock);
void radeon_atom_set_ac_timing(struct radeon_device *rdev,
@@ -441,14 +449,12 @@ struct radeon_mman {
struct radeon_bo_va {
/* protected by bo being reserved */
struct list_head bo_list;
- uint64_t soffset;
- uint64_t eoffset;
uint32_t flags;
- bool valid;
+ uint64_t addr;
unsigned ref_count;
/* protected by vm mutex */
- struct list_head vm_list;
+ struct interval_tree_node it;
struct list_head vm_status;
/* constant after initialization */
@@ -465,6 +471,7 @@ struct radeon_bo {
struct ttm_placement placement;
struct ttm_buffer_object tbo;
struct ttm_bo_kmap_obj kmap;
+ u32 flags;
unsigned pin_count;
void *kptr;
u32 tiling_flags;
@@ -543,9 +550,9 @@ struct radeon_gem {
int radeon_gem_init(struct radeon_device *rdev);
void radeon_gem_fini(struct radeon_device *rdev);
-int radeon_gem_object_create(struct radeon_device *rdev, int size,
+int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
int alignment, int initial_domain,
- bool discardable, bool kernel,
+ u32 flags, bool kernel,
struct drm_gem_object **obj);
int radeon_mode_dumb_create(struct drm_file *file_priv,
@@ -590,6 +597,12 @@ struct radeon_mc;
#define RADEON_GPU_PAGE_SHIFT 12
#define RADEON_GPU_PAGE_ALIGN(a) (((a) + RADEON_GPU_PAGE_MASK) & ~RADEON_GPU_PAGE_MASK)
+#define RADEON_GART_PAGE_DUMMY 0
+#define RADEON_GART_PAGE_VALID (1 << 0)
+#define RADEON_GART_PAGE_READ (1 << 1)
+#define RADEON_GART_PAGE_WRITE (1 << 2)
+#define RADEON_GART_PAGE_SNOOP (1 << 3)
+
struct radeon_gart {
dma_addr_t table_addr;
struct radeon_bo *robj;
@@ -614,8 +627,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
int pages);
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, struct page **pagelist,
- dma_addr_t *dma_addr);
-void radeon_gart_restore(struct radeon_device *rdev);
+ dma_addr_t *dma_addr, uint32_t flags);
/*
@@ -855,9 +867,9 @@ struct radeon_mec {
#define R600_PTE_FRAG_64KB (4 << 7)
#define R600_PTE_FRAG_256KB (6 << 7)
-/* flags used for GART page table entries on R600+ */
-#define R600_PTE_GART ( R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED \
- | R600_PTE_READABLE | R600_PTE_WRITEABLE)
+/* flags needed to be set so we can copy directly from the GART table */
+#define R600_PTE_GART_MASK ( R600_PTE_READABLE | R600_PTE_WRITEABLE | \
+ R600_PTE_SYSTEM | R600_PTE_VALID )
struct radeon_vm_pt {
struct radeon_bo *bo;
@@ -865,9 +877,12 @@ struct radeon_vm_pt {
};
struct radeon_vm {
- struct list_head va;
+ struct rb_root va;
unsigned id;
+ /* BOs moved, but not yet updated in the PT */
+ struct list_head invalidated;
+
/* BOs freed, but not yet updated in the PT */
struct list_head freed;
@@ -1740,6 +1755,7 @@ struct radeon_asic_ring {
/* command emmit functions */
void (*ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
void (*emit_fence)(struct radeon_device *rdev, struct radeon_fence *fence);
+ void (*hdp_flush)(struct radeon_device *rdev, struct radeon_ring *ring);
bool (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp,
struct radeon_semaphore *semaphore, bool emit_wait);
void (*vm_flush)(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
@@ -1763,13 +1779,8 @@ struct radeon_asic {
int (*suspend)(struct radeon_device *rdev);
void (*vga_set_state)(struct radeon_device *rdev, bool state);
int (*asic_reset)(struct radeon_device *rdev);
- /* ioctl hw specific callback. Some hw might want to perform special
- * operation on specific ioctl. For instance on wait idle some hw
- * might want to perform and HDP flush through MMIO as it seems that
- * some R6XX/R7XX hw doesn't take HDP flush into account if programmed
- * through ring.
- */
- void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
+ /* Flush the HDP cache via MMIO */
+ void (*mmio_hdp_flush)(struct radeon_device *rdev);
/* check if 3D engine is idle */
bool (*gui_idle)(struct radeon_device *rdev);
/* wait for mc_idle */
@@ -1782,16 +1793,26 @@ struct radeon_asic {
struct {
void (*tlb_flush)(struct radeon_device *rdev);
void (*set_page)(struct radeon_device *rdev, unsigned i,
- uint64_t addr);
+ uint64_t addr, uint32_t flags);
} gart;
struct {
int (*init)(struct radeon_device *rdev);
void (*fini)(struct radeon_device *rdev);
- void (*set_page)(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags);
+ void (*copy_pages)(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count);
+ void (*write_pages)(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+ void (*set_pages)(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+ void (*pad_ib)(struct radeon_ib *ib);
} vm;
/* ring specific callbacks */
struct radeon_asic_ring *ring[RADEON_NUM_RINGS];
@@ -2299,10 +2320,12 @@ struct radeon_device {
const struct firmware *mc_fw; /* NI MC firmware */
const struct firmware *ce_fw; /* SI CE firmware */
const struct firmware *mec_fw; /* CIK MEC firmware */
+ const struct firmware *mec2_fw; /* KV MEC2 firmware */
const struct firmware *sdma_fw; /* CIK SDMA firmware */
const struct firmware *smc_fw; /* SMC firmware */
const struct firmware *uvd_fw; /* UVD firmware */
const struct firmware *vce_fw; /* VCE firmware */
+ bool new_fw;
struct r600_vram_scratch vram_scratch;
int msi_enabled; /* msi enabled */
struct r600_ih ih; /* r6/700 interrupt ring */
@@ -2342,6 +2365,11 @@ struct radeon_device {
struct dev_pm_domain vga_pm_domain;
bool have_disp_power_ref;
+ u32 px_quirk_flags;
+
+ /* tracking pinned memory */
+ u64 vram_pin_size;
+ u64 gart_pin_size;
};
bool radeon_is_px(struct drm_device *dev);
@@ -2352,10 +2380,42 @@ int radeon_device_init(struct radeon_device *rdev,
void radeon_device_fini(struct radeon_device *rdev);
int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
- bool always_indirect);
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
- bool always_indirect);
+#define RADEON_MIN_MMIO_SIZE 0x10000
+
+static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+ bool always_indirect)
+{
+ /* The mmio size is 64kb at minimum. Allows the if to be optimized out. */
+ if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
+ return readl(((void __iomem *)rdev->rmmio) + reg);
+ else {
+ unsigned long flags;
+ uint32_t ret;
+
+ spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+ writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+ ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+ return ret;
+ }
+}
+
+static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+ bool always_indirect)
+{
+ if ((reg < rdev->rmmio_size || reg < RADEON_MIN_MMIO_SIZE) && !always_indirect)
+ writel(v, ((void __iomem *)rdev->rmmio) + reg);
+ else {
+ unsigned long flags;
+
+ spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+ writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+ writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+ spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+ }
+}
+
u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
@@ -2709,10 +2769,13 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
-#define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p))
+#define radeon_gart_set_page(rdev, i, p, f) (rdev)->asic->gart.set_page((rdev), (i), (p), (f))
#define radeon_asic_vm_init(rdev) (rdev)->asic->vm.init((rdev))
#define radeon_asic_vm_fini(rdev) (rdev)->asic->vm.fini((rdev))
-#define radeon_asic_vm_set_page(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.set_page((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_copy_pages(rdev, ib, pe, src, count) ((rdev)->asic->vm.copy_pages((rdev), (ib), (pe), (src), (count)))
+#define radeon_asic_vm_write_pages(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.write_pages((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_set_pages(rdev, ib, pe, addr, count, incr, flags) ((rdev)->asic->vm.set_pages((rdev), (ib), (pe), (addr), (count), (incr), (flags)))
+#define radeon_asic_vm_pad_ib(rdev, ib) ((rdev)->asic->vm.pad_ib((ib)))
#define radeon_ring_start(rdev, r, cp) (rdev)->asic->ring[(r)]->ring_start((rdev), (cp))
#define radeon_ring_test(rdev, r, cp) (rdev)->asic->ring[(r)]->ring_test((rdev), (cp))
#define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)]->ib_test((rdev), (cp))
@@ -2840,6 +2903,8 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
struct radeon_vm *vm);
int radeon_vm_clear_freed(struct radeon_device *rdev,
struct radeon_vm *vm);
+int radeon_vm_clear_invalids(struct radeon_device *rdev,
+ struct radeon_vm *vm);
int radeon_vm_bo_update(struct radeon_device *rdev,
struct radeon_bo_va *bo_va,
struct ttm_mem_reg *mem);
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 34b9aa9e3c06..eeeeabe09758 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -185,6 +185,7 @@ static struct radeon_asic_ring r100_gfx_ring = {
.get_rptr = &r100_gfx_get_rptr,
.get_wptr = &r100_gfx_get_wptr,
.set_wptr = &r100_gfx_set_wptr,
+ .hdp_flush = &r100_ring_hdp_flush,
};
static struct radeon_asic r100_asic = {
@@ -194,7 +195,7 @@ static struct radeon_asic r100_asic = {
.resume = &r100_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r100_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r100_mc_wait_for_idle,
.gart = {
@@ -260,7 +261,7 @@ static struct radeon_asic r200_asic = {
.resume = &r100_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r100_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r100_mc_wait_for_idle,
.gart = {
@@ -331,6 +332,7 @@ static struct radeon_asic_ring r300_gfx_ring = {
.get_rptr = &r100_gfx_get_rptr,
.get_wptr = &r100_gfx_get_wptr,
.set_wptr = &r100_gfx_set_wptr,
+ .hdp_flush = &r100_ring_hdp_flush,
};
static struct radeon_asic r300_asic = {
@@ -340,7 +342,7 @@ static struct radeon_asic r300_asic = {
.resume = &r300_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r300_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r300_mc_wait_for_idle,
.gart = {
@@ -406,7 +408,7 @@ static struct radeon_asic r300_asic_pcie = {
.resume = &r300_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r300_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r300_mc_wait_for_idle,
.gart = {
@@ -472,7 +474,7 @@ static struct radeon_asic r420_asic = {
.resume = &r420_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r300_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r300_mc_wait_for_idle,
.gart = {
@@ -538,7 +540,7 @@ static struct radeon_asic rs400_asic = {
.resume = &rs400_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &r300_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &rs400_mc_wait_for_idle,
.gart = {
@@ -604,7 +606,7 @@ static struct radeon_asic rs600_asic = {
.resume = &rs600_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &rs600_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &rs600_mc_wait_for_idle,
.gart = {
@@ -672,7 +674,7 @@ static struct radeon_asic rs690_asic = {
.resume = &rs690_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &rs600_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &rs690_mc_wait_for_idle,
.gart = {
@@ -740,7 +742,7 @@ static struct radeon_asic rv515_asic = {
.resume = &rv515_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &rs600_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &rv515_mc_wait_for_idle,
.gart = {
@@ -806,7 +808,7 @@ static struct radeon_asic r520_asic = {
.resume = &r520_resume,
.vga_set_state = &r100_vga_set_state,
.asic_reset = &rs600_asic_reset,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = NULL,
.gui_idle = &r100_gui_idle,
.mc_wait_for_idle = &r520_mc_wait_for_idle,
.gart = {
@@ -898,7 +900,7 @@ static struct radeon_asic r600_asic = {
.resume = &r600_resume,
.vga_set_state = &r600_vga_set_state,
.asic_reset = &r600_asic_reset,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &r600_mc_wait_for_idle,
.get_xclk = &r600_get_xclk,
@@ -970,7 +972,7 @@ static struct radeon_asic rv6xx_asic = {
.resume = &r600_resume,
.vga_set_state = &r600_vga_set_state,
.asic_reset = &r600_asic_reset,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &r600_mc_wait_for_idle,
.get_xclk = &r600_get_xclk,
@@ -1060,7 +1062,7 @@ static struct radeon_asic rs780_asic = {
.resume = &r600_resume,
.vga_set_state = &r600_vga_set_state,
.asic_reset = &r600_asic_reset,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &r600_mc_wait_for_idle,
.get_xclk = &r600_get_xclk,
@@ -1163,7 +1165,7 @@ static struct radeon_asic rv770_asic = {
.resume = &rv770_resume,
.asic_reset = &r600_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &r600_mc_wait_for_idle,
.get_xclk = &rv770_get_xclk,
@@ -1281,7 +1283,7 @@ static struct radeon_asic evergreen_asic = {
.resume = &evergreen_resume,
.asic_reset = &evergreen_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &rv770_get_xclk,
@@ -1373,7 +1375,7 @@ static struct radeon_asic sumo_asic = {
.resume = &evergreen_resume,
.asic_reset = &evergreen_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &r600_get_xclk,
@@ -1464,7 +1466,7 @@ static struct radeon_asic btc_asic = {
.resume = &evergreen_resume,
.asic_reset = &evergreen_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &rv770_get_xclk,
@@ -1599,7 +1601,7 @@ static struct radeon_asic cayman_asic = {
.resume = &cayman_resume,
.asic_reset = &cayman_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &rv770_get_xclk,
@@ -1611,7 +1613,10 @@ static struct radeon_asic cayman_asic = {
.vm = {
.init = &cayman_vm_init,
.fini = &cayman_vm_fini,
- .set_page = &cayman_dma_vm_set_page,
+ .copy_pages = &cayman_dma_vm_copy_pages,
+ .write_pages = &cayman_dma_vm_write_pages,
+ .set_pages = &cayman_dma_vm_set_pages,
+ .pad_ib = &cayman_dma_vm_pad_ib,
},
.ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
@@ -1699,7 +1704,7 @@ static struct radeon_asic trinity_asic = {
.resume = &cayman_resume,
.asic_reset = &cayman_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &r600_get_xclk,
@@ -1711,7 +1716,10 @@ static struct radeon_asic trinity_asic = {
.vm = {
.init = &cayman_vm_init,
.fini = &cayman_vm_fini,
- .set_page = &cayman_dma_vm_set_page,
+ .copy_pages = &cayman_dma_vm_copy_pages,
+ .write_pages = &cayman_dma_vm_write_pages,
+ .set_pages = &cayman_dma_vm_set_pages,
+ .pad_ib = &cayman_dma_vm_pad_ib,
},
.ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
@@ -1829,7 +1837,7 @@ static struct radeon_asic si_asic = {
.resume = &si_resume,
.asic_reset = &si_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .mmio_hdp_flush = r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &si_get_xclk,
@@ -1841,7 +1849,10 @@ static struct radeon_asic si_asic = {
.vm = {
.init = &si_vm_init,
.fini = &si_vm_fini,
- .set_page = &si_dma_vm_set_page,
+ .copy_pages = &si_dma_vm_copy_pages,
+ .write_pages = &si_dma_vm_write_pages,
+ .set_pages = &si_dma_vm_set_pages,
+ .pad_ib = &cayman_dma_vm_pad_ib,
},
.ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &si_gfx_ring,
@@ -1987,7 +1998,7 @@ static struct radeon_asic ci_asic = {
.resume = &cik_resume,
.asic_reset = &cik_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = &r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &cik_get_xclk,
@@ -1999,7 +2010,10 @@ static struct radeon_asic ci_asic = {
.vm = {
.init = &cik_vm_init,
.fini = &cik_vm_fini,
- .set_page = &cik_sdma_vm_set_page,
+ .copy_pages = &cik_sdma_vm_copy_pages,
+ .write_pages = &cik_sdma_vm_write_pages,
+ .set_pages = &cik_sdma_vm_set_pages,
+ .pad_ib = &cik_sdma_vm_pad_ib,
},
.ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
@@ -2091,7 +2105,7 @@ static struct radeon_asic kv_asic = {
.resume = &cik_resume,
.asic_reset = &cik_asic_reset,
.vga_set_state = &r600_vga_set_state,
- .ioctl_wait_idle = NULL,
+ .mmio_hdp_flush = &r600_mmio_hdp_flush,
.gui_idle = &r600_gui_idle,
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
.get_xclk = &cik_get_xclk,
@@ -2103,7 +2117,10 @@ static struct radeon_asic kv_asic = {
.vm = {
.init = &cik_vm_init,
.fini = &cik_vm_fini,
- .set_page = &cik_sdma_vm_set_page,
+ .copy_pages = &cik_sdma_vm_copy_pages,
+ .write_pages = &cik_sdma_vm_write_pages,
+ .set_pages = &cik_sdma_vm_set_pages,
+ .pad_ib = &cik_sdma_vm_pad_ib,
},
.ring = {
[RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
@@ -2457,7 +2474,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->cg_flags =
RADEON_CG_SUPPORT_GFX_MGCG |
RADEON_CG_SUPPORT_GFX_MGLS |
- RADEON_CG_SUPPORT_GFX_CGCG |
+ /*RADEON_CG_SUPPORT_GFX_CGCG |*/
RADEON_CG_SUPPORT_GFX_CGLS |
RADEON_CG_SUPPORT_GFX_CGTS |
RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2476,7 +2493,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->cg_flags =
RADEON_CG_SUPPORT_GFX_MGCG |
RADEON_CG_SUPPORT_GFX_MGLS |
- RADEON_CG_SUPPORT_GFX_CGCG |
+ /*RADEON_CG_SUPPORT_GFX_CGCG |*/
RADEON_CG_SUPPORT_GFX_CGLS |
RADEON_CG_SUPPORT_GFX_CGTS |
RADEON_CG_SUPPORT_GFX_CP_LS |
@@ -2502,7 +2519,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->cg_flags =
RADEON_CG_SUPPORT_GFX_MGCG |
RADEON_CG_SUPPORT_GFX_MGLS |
- RADEON_CG_SUPPORT_GFX_CGCG |
+ /*RADEON_CG_SUPPORT_GFX_CGCG |*/
RADEON_CG_SUPPORT_GFX_CGLS |
RADEON_CG_SUPPORT_GFX_CGTS |
RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2530,7 +2547,7 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->cg_flags =
RADEON_CG_SUPPORT_GFX_MGCG |
RADEON_CG_SUPPORT_GFX_MGLS |
- RADEON_CG_SUPPORT_GFX_CGCG |
+ /*RADEON_CG_SUPPORT_GFX_CGCG |*/
RADEON_CG_SUPPORT_GFX_CGLS |
RADEON_CG_SUPPORT_GFX_CGTS |
RADEON_CG_SUPPORT_GFX_CGTS_LS |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 01e7c0ad8f01..275a5dc01780 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -68,7 +68,7 @@ int r100_asic_reset(struct radeon_device *rdev);
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr);
+ uint64_t addr, uint32_t flags);
void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring);
int r100_irq_set(struct radeon_device *rdev);
int r100_irq_process(struct radeon_device *rdev);
@@ -148,7 +148,8 @@ u32 r100_gfx_get_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
void r100_gfx_set_wptr(struct radeon_device *rdev,
struct radeon_ring *ring);
-
+void r100_ring_hdp_flush(struct radeon_device *rdev,
+ struct radeon_ring *ring);
/*
* r200,rv250,rs300,rv280
*/
@@ -173,7 +174,7 @@ extern void r300_fence_ring_emit(struct radeon_device *rdev,
extern int r300_cs_parse(struct radeon_cs_parser *p);
extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
extern void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr);
+ uint64_t addr, uint32_t flags);
extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
extern void r300_set_reg_safe(struct radeon_device *rdev);
@@ -209,7 +210,7 @@ extern int rs400_suspend(struct radeon_device *rdev);
extern int rs400_resume(struct radeon_device *rdev);
void rs400_gart_tlb_flush(struct radeon_device *rdev);
void rs400_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr);
+ uint64_t addr, uint32_t flags);
uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
int rs400_gart_init(struct radeon_device *rdev);
@@ -233,7 +234,7 @@ void rs600_irq_disable(struct radeon_device *rdev);
u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
void rs600_gart_tlb_flush(struct radeon_device *rdev);
void rs600_gart_set_page(struct radeon_device *rdev, unsigned i,
- uint64_t addr);
+ uint64_t addr, uint32_t flags);
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs600_bandwidth_update(struct radeon_device *rdev);
@@ -351,7 +352,7 @@ void r600_hpd_fini(struct radeon_device *rdev);
bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
void r600_hpd_set_polarity(struct radeon_device *rdev,
enum radeon_hpd_id hpd);
-extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
+extern void r600_mmio_hdp_flush(struct radeon_device *rdev);
extern bool r600_gui_idle(struct radeon_device *rdev);
extern void r600_pm_misc(struct radeon_device *rdev);
extern void r600_pm_init_profile(struct radeon_device *rdev);
@@ -606,11 +607,22 @@ void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
struct radeon_ib *ib);
bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
-void cayman_dma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags);
+
+void cayman_dma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count);
+void cayman_dma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+void cayman_dma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+void cayman_dma_vm_pad_ib(struct radeon_ib *ib);
void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
@@ -693,11 +705,22 @@ int si_copy_dma(struct radeon_device *rdev,
uint64_t src_offset, uint64_t dst_offset,
unsigned num_gpu_pages,
struct radeon_fence **fence);
-void si_dma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags);
+
+void si_dma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count);
+void si_dma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+void si_dma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+
void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
u32 si_get_xclk(struct radeon_device *rdev);
uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
@@ -771,11 +794,23 @@ int cik_irq_process(struct radeon_device *rdev);
int cik_vm_init(struct radeon_device *rdev);
void cik_vm_fini(struct radeon_device *rdev);
void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
-void cik_sdma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags);
+
+void cik_sdma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count);
+void cik_sdma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+void cik_sdma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags);
+void cik_sdma_vm_pad_ib(struct radeon_ib *ib);
+
void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
u32 cik_gfx_get_rptr(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 173f378428a9..92b2d8dd4735 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1963,7 +1963,7 @@ static const char *thermal_controller_names[] = {
"adm1032",
"adm1030",
"max6649",
- "lm64",
+ "lm63", /* lm64 */
"f75375",
"asc7xxx",
};
@@ -1974,7 +1974,7 @@ static const char *pp_lib_thermal_controller_names[] = {
"adm1032",
"adm1030",
"max6649",
- "lm64",
+ "lm63", /* lm64 */
"f75375",
"RV6xx",
"RV770",
@@ -3236,6 +3236,41 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r
return 0;
}
+union get_voltage_info {
+ struct _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in;
+ struct _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out;
+};
+
+int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
+ u16 virtual_voltage_id,
+ u16 *voltage)
+{
+ int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo);
+ u32 entry_id;
+ u32 count = rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count;
+ union get_voltage_info args;
+
+ for (entry_id = 0; entry_id < count; entry_id++) {
+ if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].v ==
+ virtual_voltage_id)
+ break;
+ }
+
+ if (entry_id >= count)
+ return -EINVAL;
+
+ args.in.ucVoltageType = VOLTAGE_TYPE_VDDC;
+ args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;
+ args.in.ulSCLKFreq =
+ cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk);
+
+ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+ *voltage = le16_to_cpu(args.evv_out.usVoltageLevel);
+
+ return 0;
+}
+
int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev,
u16 voltage_level, u8 voltage_type,
u32 *gpio_value, u32 *gpio_mask)
@@ -3397,6 +3432,50 @@ radeon_atom_is_voltage_gpio(struct radeon_device *rdev,
return false;
}
+int radeon_atom_get_svi2_info(struct radeon_device *rdev,
+ u8 voltage_type,
+ u8 *svd_gpio_id, u8 *svc_gpio_id)
+{
+ int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo);
+ u8 frev, crev;
+ u16 data_offset, size;
+ union voltage_object_info *voltage_info;
+ union voltage_object *voltage_object = NULL;
+
+ if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size,
+ &frev, &crev, &data_offset)) {
+ voltage_info = (union voltage_object_info *)
+ (rdev->mode_info.atom_context->bios + data_offset);
+
+ switch (frev) {
+ case 3:
+ switch (crev) {
+ case 1:
+ voltage_object = (union voltage_object *)
+ atom_lookup_voltage_object_v3(&voltage_info->v3,
+ voltage_type,
+ VOLTAGE_OBJ_SVID2);
+ if (voltage_object) {
+ *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId;
+ *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId;
+ } else {
+ return -EINVAL;
+ }
+ break;
+ default:
+ DRM_ERROR("unknown voltage object table\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ DRM_ERROR("unknown voltage object table\n");
+ return -EINVAL;
+ }
+
+ }
+ return 0;
+}
+
int radeon_atom_get_max_voltage(struct radeon_device *rdev,
u8 voltage_type, u16 *max_voltage)
{
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c
index 6e05a2e75a46..69f5695bdab9 100644
--- a/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ b/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -97,7 +97,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
int time;
n = RADEON_BENCHMARK_ITERATIONS;
- r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, NULL, &sobj);
+ r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, 0, NULL, &sobj);
if (r) {
goto out_cleanup;
}
@@ -109,7 +109,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
if (r) {
goto out_cleanup;
}
- r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, NULL, &dobj);
+ r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, 0, NULL, &dobj);
if (r) {
goto out_cleanup;
}
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 44831197e82e..300c4b3d4669 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -107,7 +107,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
- if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -115,7 +115,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
- if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -124,7 +124,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
- drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (connector->display_info.bpc)
bpc = connector->display_info.bpc;
}
@@ -148,7 +148,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
break;
}
- if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* hdmi deep color only implemented on DCE4+ */
if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
@@ -197,10 +197,19 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
connector->name, bpc);
}
}
+ else if (bpc > 8) {
+ /* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
+ DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
+ connector->name);
+ bpc = 8;
+ }
}
- if ((radeon_deep_color == 0) && (bpc > 8))
+ if ((radeon_deep_color == 0) && (bpc > 8)) {
+ DRM_DEBUG("%s: Deep color disabled. Set radeon module param deep_color=1 to enable.\n",
+ connector->name);
bpc = 8;
+ }
DRM_DEBUG("%s: Display bpc=%d, returned bpc=%d\n",
connector->name, connector->display_info.bpc, bpc);
@@ -216,7 +225,6 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
struct drm_encoder *best_encoder = NULL;
struct drm_encoder *encoder = NULL;
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
- struct drm_mode_object *obj;
bool connected;
int i;
@@ -226,14 +234,11 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev,
- connector->encoder_ids[i],
- DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev,
+ connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
-
if ((encoder == best_encoder) && (status == connector_status_connected))
connected = true;
else
@@ -249,7 +254,6 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
{
- struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
@@ -257,34 +261,134 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
if (encoder->encoder_type == encoder_type)
return encoder;
}
return NULL;
}
+struct edid *radeon_connector_edid(struct drm_connector *connector)
+{
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
+
+ if (radeon_connector->edid) {
+ return radeon_connector->edid;
+ } else if (edid_blob) {
+ struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
+ if (edid)
+ radeon_connector->edid = edid;
+ }
+ return radeon_connector->edid;
+}
+
+static void radeon_connector_get_edid(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+ if (radeon_connector->edid)
+ return;
+
+ /* on hw with routers, select right port */
+ if (radeon_connector->router.ddc_valid)
+ radeon_router_select_ddc_port(radeon_connector);
+
+ if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
+ ENCODER_OBJECT_ID_NONE) &&
+ radeon_connector->ddc_bus->has_aux) {
+ radeon_connector->edid = drm_get_edid(connector,
+ &radeon_connector->ddc_bus->aux.ddc);
+ } else if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+ (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+
+ if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
+ dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
+ radeon_connector->ddc_bus->has_aux)
+ radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+ &radeon_connector->ddc_bus->aux.ddc);
+ else if (radeon_connector->ddc_bus)
+ radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+ &radeon_connector->ddc_bus->adapter);
+ } else if (radeon_connector->ddc_bus) {
+ radeon_connector->edid = drm_get_edid(&radeon_connector->base,
+ &radeon_connector->ddc_bus->adapter);
+ }
+
+ if (!radeon_connector->edid) {
+ if (rdev->is_atom_bios) {
+ /* some laptops provide a hardcoded edid in rom for LCDs */
+ if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
+ (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
+ radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+ } else {
+ /* some servers provide a hardcoded edid in rom for KVMs */
+ radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
+ }
+ }
+}
+
+static void radeon_connector_free_edid(struct drm_connector *connector)
+{
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+ if (radeon_connector->edid) {
+ kfree(radeon_connector->edid);
+ radeon_connector->edid = NULL;
+ }
+}
+
+static int radeon_ddc_get_modes(struct drm_connector *connector)
+{
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ int ret;
+
+ if (radeon_connector->edid) {
+ drm_mode_connector_update_edid_property(connector, radeon_connector->edid);
+ ret = drm_add_edid_modes(connector, radeon_connector->edid);
+ drm_edid_to_eld(connector, radeon_connector->edid);
+ return ret;
+ }
+ drm_mode_connector_update_edid_property(connector, NULL);
+ return 0;
+}
+
static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
/* pick the encoder ids */
- if (enc_id) {
- obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
+static void radeon_get_native_mode(struct drm_connector *connector)
+{
+ struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+ struct radeon_encoder *radeon_encoder;
+
+ if (encoder == NULL)
+ return;
+
+ radeon_encoder = to_radeon_encoder(encoder);
+
+ if (!list_empty(&connector->probed_modes)) {
+ struct drm_display_mode *preferred_mode =
+ list_first_entry(&connector->probed_modes,
+ struct drm_display_mode, head);
+
+ radeon_encoder->native_mode = *preferred_mode;
+ } else {
+ radeon_encoder->native_mode.clock = 0;
+ }
+}
+
/*
* radeon_connector_analog_encoder_conflict_solve
* - search for other connectors sharing this encoder
@@ -585,6 +689,35 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
radeon_property_change_mode(&radeon_encoder->base);
}
+ if (property == dev->mode_config.scaling_mode_property) {
+ enum radeon_rmx_type rmx_type;
+
+ if (connector->encoder)
+ radeon_encoder = to_radeon_encoder(connector->encoder);
+ else {
+ struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
+ radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
+ }
+
+ switch (val) {
+ default:
+ case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
+ case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
+ case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
+ case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
+ }
+ if (radeon_encoder->rmx_type == rmx_type)
+ return 0;
+
+ if ((rmx_type != DRM_MODE_SCALE_NONE) &&
+ (radeon_encoder->native_mode.clock == 0))
+ return 0;
+
+ radeon_encoder->rmx_type = rmx_type;
+
+ radeon_property_change_mode(&radeon_encoder->base);
+ }
+
return 0;
}
@@ -625,22 +758,20 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
static int radeon_lvds_get_modes(struct drm_connector *connector)
{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder;
int ret = 0;
struct drm_display_mode *mode;
- if (radeon_connector->ddc_bus) {
- ret = radeon_ddc_get_modes(radeon_connector);
- if (ret > 0) {
- encoder = radeon_best_single_encoder(connector);
- if (encoder) {
- radeon_fixup_lvds_native_mode(encoder, connector);
- /* add scaled modes */
- radeon_add_common_modes(encoder, connector);
- }
- return ret;
+ radeon_connector_get_edid(connector);
+ ret = radeon_ddc_get_modes(connector);
+ if (ret > 0) {
+ encoder = radeon_best_single_encoder(connector);
+ if (encoder) {
+ radeon_fixup_lvds_native_mode(encoder, connector);
+ /* add scaled modes */
+ radeon_add_common_modes(encoder, connector);
}
+ return ret;
}
encoder = radeon_best_single_encoder(connector);
@@ -715,16 +846,9 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
}
/* check for edid as well */
+ radeon_connector_get_edid(connector);
if (radeon_connector->edid)
ret = connector_status_connected;
- else {
- if (radeon_connector->ddc_bus) {
- radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &radeon_connector->ddc_bus->adapter);
- if (radeon_connector->edid)
- ret = connector_status_connected;
- }
- }
/* check acpi lid status ??? */
radeon_connector_update_scratch_regs(connector, ret);
@@ -737,10 +861,9 @@ static void radeon_connector_destroy(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- if (radeon_connector->edid)
- kfree(radeon_connector->edid);
+ radeon_connector_free_edid(connector);
kfree(radeon_connector->con_priv);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -797,10 +920,12 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = {
static int radeon_vga_get_modes(struct drm_connector *connector)
{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int ret;
- ret = radeon_ddc_get_modes(radeon_connector);
+ radeon_connector_get_edid(connector);
+ ret = radeon_ddc_get_modes(connector);
+
+ radeon_get_native_mode(connector);
return ret;
}
@@ -843,28 +968,26 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
dret = radeon_ddc_probe(radeon_connector, false);
if (dret) {
radeon_connector->detected_by_load = false;
- if (radeon_connector->edid) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
- }
- radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+ radeon_connector_free_edid(connector);
+ radeon_connector_get_edid(connector);
if (!radeon_connector->edid) {
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
connector->name);
ret = connector_status_connected;
} else {
- radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
+ radeon_connector->use_digital =
+ !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
/* some oems have boards with separate digital and analog connectors
* with a shared ddc line (often vga + hdmi)
*/
if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
+ radeon_connector_free_edid(connector);
ret = connector_status_disconnected;
- } else
+ } else {
ret = connector_status_connected;
+ }
}
} else {
@@ -999,15 +1122,6 @@ static const struct drm_connector_funcs radeon_tv_connector_funcs = {
.set_property = radeon_connector_set_property,
};
-static int radeon_dvi_get_modes(struct drm_connector *connector)
-{
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- int ret;
-
- ret = radeon_ddc_get_modes(radeon_connector);
- return ret;
-}
-
static bool radeon_check_hpd_status_unchanged(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -1048,7 +1162,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder = NULL;
struct drm_encoder_helper_funcs *encoder_funcs;
- struct drm_mode_object *obj;
int i, r;
enum drm_connector_status ret = connector_status_disconnected;
bool dret = false, broken_edid = false;
@@ -1066,18 +1179,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
dret = radeon_ddc_probe(radeon_connector, false);
if (dret) {
radeon_connector->detected_by_load = false;
- if (radeon_connector->edid) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
- }
- radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
+ radeon_connector_free_edid(connector);
+ radeon_connector_get_edid(connector);
if (!radeon_connector->edid) {
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
connector->name);
/* rs690 seems to have a problem with connectors not existing and always
* return a block of 0's. If we see this just stop polling on this output */
- if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
+ if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) &&
+ radeon_connector->base.null_edid_counter) {
ret = connector_status_disconnected;
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n",
connector->name);
@@ -1087,18 +1198,18 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
broken_edid = true; /* defer use_digital to later */
}
} else {
- radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
+ radeon_connector->use_digital =
+ !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
/* some oems have boards with separate digital and analog connectors
* with a shared ddc line (often vga + hdmi)
*/
if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
+ radeon_connector_free_edid(connector);
ret = connector_status_disconnected;
- } else
+ } else {
ret = connector_status_connected;
-
+ }
/* This gets complicated. We have boards with VGA + HDMI with a
* shared DDC line and we have boards with DVI-D + HDMI with a shared
* DDC line. The latter is more complex because with DVI<->HDMI adapters
@@ -1118,8 +1229,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
/* hpd is our only option in this case */
if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
+ radeon_connector_free_edid(connector);
ret = connector_status_disconnected;
}
}
@@ -1153,14 +1263,11 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev,
- connector->encoder_ids[i],
- DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev,
+ connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
-
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
continue;
@@ -1225,19 +1332,16 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
-
if (radeon_connector->use_digital == true) {
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
return encoder;
@@ -1252,13 +1356,8 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
/* then check use digitial */
/* pick the first one */
- if (enc_id) {
- obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
- }
+ if (enc_id)
+ return drm_encoder_find(connector->dev, enc_id);
return NULL;
}
@@ -1291,7 +1390,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
(radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
return MODE_OK;
- else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
@@ -1310,7 +1409,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
}
static const struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
- .get_modes = radeon_dvi_get_modes,
+ .get_modes = radeon_vga_get_modes,
.mode_valid = radeon_dvi_mode_valid,
.best_encoder = radeon_dvi_encoder,
};
@@ -1339,7 +1438,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
if (!radeon_dig_connector->edp_on)
atombios_set_edp_panel_power(connector,
ATOM_TRANSMITTER_ACTION_POWER_ON);
- ret = radeon_ddc_get_modes(radeon_connector);
+ radeon_connector_get_edid(connector);
+ ret = radeon_ddc_get_modes(connector);
if (!radeon_dig_connector->edp_on)
atombios_set_edp_panel_power(connector,
ATOM_TRANSMITTER_ACTION_POWER_OFF);
@@ -1350,7 +1450,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
if (encoder)
radeon_atom_ext_encoder_setup_ddc(encoder);
}
- ret = radeon_ddc_get_modes(radeon_connector);
+ radeon_connector_get_edid(connector);
+ ret = radeon_ddc_get_modes(connector);
}
if (ret > 0) {
@@ -1383,7 +1484,10 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
if (encoder)
radeon_atom_ext_encoder_setup_ddc(encoder);
}
- ret = radeon_ddc_get_modes(radeon_connector);
+ radeon_connector_get_edid(connector);
+ ret = radeon_ddc_get_modes(connector);
+
+ radeon_get_native_mode(connector);
}
return ret;
@@ -1391,7 +1495,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
{
- struct drm_mode_object *obj;
struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder;
int i;
@@ -1400,11 +1503,10 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
radeon_encoder = to_radeon_encoder(encoder);
switch (radeon_encoder->encoder_id) {
@@ -1419,9 +1521,8 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
return ENCODER_OBJECT_ID_NONE;
}
-bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
+static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
{
- struct drm_mode_object *obj;
struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder;
int i;
@@ -1431,11 +1532,10 @@ bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
if (connector->encoder_ids[i] == 0)
break;
- obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
- if (!obj)
+ encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ if (!encoder)
continue;
- encoder = obj_to_encoder(obj);
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
found = true;
@@ -1478,10 +1578,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
goto out;
}
- if (radeon_connector->edid) {
- kfree(radeon_connector->edid);
- radeon_connector->edid = NULL;
- }
+ radeon_connector_free_edid(connector);
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
@@ -1587,7 +1684,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
return radeon_dp_mode_valid_helper(connector, mode);
} else {
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
/* HDMI 1.3+ supports max clock of 340 Mhz */
if (mode->clock > 340000)
return MODE_CLOCK_HIGH;
@@ -1747,6 +1844,9 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
@@ -1768,6 +1868,10 @@ radeon_add_atom_connector(struct drm_device *dev,
0);
drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
+
+ drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
@@ -1817,6 +1921,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
+ if (ASIC_IS_AVIVO(rdev))
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -1835,6 +1943,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property,
1);
+ if (ASIC_IS_AVIVO(rdev))
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->interlace_allowed = true;
@@ -1868,17 +1980,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
+ drm_object_attach_property(&radeon_connector->base.base,
+ rdev->mode_info.dither_property,
+ RADEON_FMT_DITHER_DISABLE);
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
- if (ASIC_IS_AVIVO(rdev)) {
- drm_object_attach_property(&radeon_connector->base.base,
- rdev->mode_info.dither_property,
- RADEON_FMT_DITHER_DISABLE);
- }
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true;
drm_object_attach_property(&radeon_connector->base.base,
@@ -1918,17 +2031,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
+ drm_object_attach_property(&radeon_connector->base.base,
+ rdev->mode_info.dither_property,
+ RADEON_FMT_DITHER_DISABLE);
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
- if (ASIC_IS_AVIVO(rdev)) {
- drm_object_attach_property(&radeon_connector->base.base,
- rdev->mode_info.dither_property,
- RADEON_FMT_DITHER_DISABLE);
- }
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1965,18 +2079,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property,
0);
+ drm_object_attach_property(&radeon_connector->base.base,
+ rdev->mode_info.dither_property,
+ RADEON_FMT_DITHER_DISABLE);
+ drm_object_attach_property(&radeon_connector->base.base,
+ dev->mode_config.scaling_mode_property,
+ DRM_MODE_SCALE_NONE);
}
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO);
}
- if (ASIC_IS_AVIVO(rdev)) {
- drm_object_attach_property(&radeon_connector->base.base,
- rdev->mode_info.dither_property,
- RADEON_FMT_DITHER_DISABLE);
-
- }
connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false;
@@ -2050,7 +2164,7 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
if (has_aux)
radeon_dp_aux_init(radeon_connector);
@@ -2211,5 +2325,5 @@ radeon_add_legacy_connector(struct drm_device *dev,
} else
connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->display_info.subpixel_order = subpixel_order;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
}
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index ae763f60c8a0..ee712c199b25 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -500,7 +500,8 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *p,
if (r)
return r;
}
- return 0;
+
+ return radeon_vm_clear_invalids(rdev, vm);
}
static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 697add2cd4e3..c8ea050c8fa4 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -103,6 +103,31 @@ static const char radeon_family_name[][16] = {
"LAST",
};
+#define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
+#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
+
+struct radeon_px_quirk {
+ u32 chip_vendor;
+ u32 chip_device;
+ u32 subsys_vendor;
+ u32 subsys_device;
+ u32 px_quirk_flags;
+};
+
+static struct radeon_px_quirk radeon_px_quirk_list[] = {
+ /* Acer aspire 5560g (CPU: AMD A4-3305M; GPU: AMD Radeon HD 6480g + 7470m)
+ * https://bugzilla.kernel.org/show_bug.cgi?id=74551
+ */
+ { PCI_VENDOR_ID_ATI, 0x6760, 0x1025, 0x0672, RADEON_PX_QUIRK_DISABLE_PX },
+ /* Asus K73TA laptop with AMD A6-3400M APU and Radeon 6550 GPU
+ * https://bugzilla.kernel.org/show_bug.cgi?id=51381
+ */
+ { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x108c, RADEON_PX_QUIRK_DISABLE_PX },
+ /* macbook pro 8.2 */
+ { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
+ { 0, 0, 0, 0, 0 },
+};
+
bool radeon_is_px(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
@@ -112,6 +137,26 @@ bool radeon_is_px(struct drm_device *dev)
return false;
}
+static void radeon_device_handle_px_quirks(struct radeon_device *rdev)
+{
+ struct radeon_px_quirk *p = radeon_px_quirk_list;
+
+ /* Apply PX quirks */
+ while (p && p->chip_device != 0) {
+ if (rdev->pdev->vendor == p->chip_vendor &&
+ rdev->pdev->device == p->chip_device &&
+ rdev->pdev->subsystem_vendor == p->subsys_vendor &&
+ rdev->pdev->subsystem_device == p->subsys_device) {
+ rdev->px_quirk_flags = p->px_quirk_flags;
+ break;
+ }
+ ++p;
+ }
+
+ if (rdev->px_quirk_flags & RADEON_PX_QUIRK_DISABLE_PX)
+ rdev->flags &= ~RADEON_IS_PX;
+}
+
/**
* radeon_program_register_sequence - program an array of registers.
*
@@ -385,7 +430,8 @@ int radeon_wb_init(struct radeon_device *rdev)
if (rdev->wb.wb_obj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_GTT, NULL, &rdev->wb.wb_obj);
+ RADEON_GEM_DOMAIN_GTT, 0, NULL,
+ &rdev->wb.wb_obj);
if (r) {
dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
return r;
@@ -1077,7 +1123,19 @@ static void radeon_check_arguments(struct radeon_device *rdev)
/* defines number of bits in page table versus page directory,
* a page is 4KB so we have 12 bits offset, minimum 9 bits in the
* page table and the remaining bits are in the page directory */
- if (radeon_vm_block_size < 9) {
+ if (radeon_vm_block_size == -1) {
+
+ /* Total bits covered by PD + PTs */
+ unsigned bits = ilog2(radeon_vm_size) + 17;
+
+ /* Make sure the PD is 4K in size up to 8GB address space.
+ Above that split equal between PD and PTs */
+ if (radeon_vm_size <= 8)
+ radeon_vm_block_size = bits - 9;
+ else
+ radeon_vm_block_size = (bits + 3) / 2;
+
+ } else if (radeon_vm_block_size < 9) {
dev_warn(rdev->dev, "VM page table size (%d) too small\n",
radeon_vm_block_size);
radeon_vm_block_size = 9;
@@ -1092,25 +1150,6 @@ static void radeon_check_arguments(struct radeon_device *rdev)
}
/**
- * radeon_switcheroo_quirk_long_wakeup - return true if longer d3 delay is
- * needed for waking up.
- *
- * @pdev: pci dev pointer
- */
-static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
-{
-
- /* 6600m in a macbook pro */
- if (pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
- pdev->subsystem_device == 0x00e2) {
- printk(KERN_INFO "radeon: quirking longer d3 wakeup delay\n");
- return true;
- }
-
- return false;
-}
-
-/**
* radeon_switcheroo_set_state - set switcheroo state
*
* @pdev: pci dev pointer
@@ -1122,6 +1161,7 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
+ struct radeon_device *rdev = dev->dev_private;
if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return;
@@ -1133,7 +1173,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
/* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
+ if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
dev->pdev->d3_delay = 20;
radeon_resume_kms(dev, true, true);
@@ -1337,6 +1377,9 @@ int radeon_device_init(struct radeon_device *rdev,
if (rdev->rio_mem == NULL)
DRM_ERROR("Unable to find PCI I/O BAR\n");
+ if (rdev->flags & RADEON_IS_PX)
+ radeon_device_handle_px_quirks(rdev);
+
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
/* this will fail for cards that aren't VGA class devices, just
* ignore it */
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index bf25061c8ac4..3fdf87318069 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -293,6 +293,18 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
if (radeon_crtc == NULL)
return;
+ /* Skip the pageflip completion check below (based on polling) on
+ * asics which reliably support hw pageflip completion irqs. pflip
+ * irqs are a reliable and race-free method of handling pageflip
+ * completion detection. A use_pflipirq module parameter < 2 allows
+ * to override this in case of asics with faulty pflip irqs.
+ * A module parameter of 0 would only use this polling based path,
+ * a parameter of 1 would use pflip irq only as a backup to this
+ * path, as in Linux 3.16.
+ */
+ if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev))
+ return;
+
spin_lock_irqsave(&rdev->ddev->event_lock, flags);
if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
@@ -823,64 +835,6 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
return ret;
}
-int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
-{
- struct drm_device *dev = radeon_connector->base.dev;
- struct radeon_device *rdev = dev->dev_private;
- int ret = 0;
-
- /* don't leak the edid if we already fetched it in detect() */
- if (radeon_connector->edid)
- goto got_edid;
-
- /* on hw with routers, select right port */
- if (radeon_connector->router.ddc_valid)
- radeon_router_select_ddc_port(radeon_connector);
-
- if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
- ENCODER_OBJECT_ID_NONE) {
- if (radeon_connector->ddc_bus->has_aux)
- radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &radeon_connector->ddc_bus->aux.ddc);
- } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
- (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
- struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
-
- if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
- dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) &&
- radeon_connector->ddc_bus->has_aux)
- radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &radeon_connector->ddc_bus->aux.ddc);
- else if (radeon_connector->ddc_bus && !radeon_connector->edid)
- radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &radeon_connector->ddc_bus->adapter);
- } else {
- if (radeon_connector->ddc_bus && !radeon_connector->edid)
- radeon_connector->edid = drm_get_edid(&radeon_connector->base,
- &radeon_connector->ddc_bus->adapter);
- }
-
- if (!radeon_connector->edid) {
- if (rdev->is_atom_bios) {
- /* some laptops provide a hardcoded edid in rom for LCDs */
- if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) ||
- (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)))
- radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
- } else
- /* some servers provide a hardcoded edid in rom for KVMs */
- radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
- }
- if (radeon_connector->edid) {
-got_edid:
- drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
- ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
- drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
- return ret;
- }
- drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
- return 0;
-}
-
/* avivo */
/**
@@ -1749,7 +1703,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
(!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
- drm_detect_hdmi_monitor(radeon_connector->edid) &&
+ drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
is_hdtv_mode(mode)))) {
if (radeon_encoder->underscan_hborder != 0)
radeon_crtc->h_border = radeon_encoder->underscan_hborder;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index e9e361084249..092d067f93e1 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -82,9 +82,11 @@
* 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN),
* CIK: 1D and linear tiling modes contain valid PIPE_CONFIG
* 2.39.0 - Add INFO query for number of active CUs
+ * 2.40.0 - Add RADEON_GEM_GTT_WC/UC, flush HDP cache before submitting
+ * CS to GPU
*/
#define KMS_DRIVER_MAJOR 2
-#define KMS_DRIVER_MINOR 39
+#define KMS_DRIVER_MINOR 40
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
@@ -132,6 +134,7 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
struct sg_table *sg);
int radeon_gem_prime_pin(struct drm_gem_object *obj);
void radeon_gem_prime_unpin(struct drm_gem_object *obj);
+struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *);
void *radeon_gem_prime_vmap(struct drm_gem_object *obj);
void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd,
@@ -173,9 +176,10 @@ int radeon_dpm = -1;
int radeon_aspm = -1;
int radeon_runtime_pm = -1;
int radeon_hard_reset = 0;
-int radeon_vm_size = 4;
-int radeon_vm_block_size = 9;
+int radeon_vm_size = 8;
+int radeon_vm_block_size = -1;
int radeon_deep_color = 0;
+int radeon_use_pflipirq = 2;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -246,12 +250,15 @@ module_param_named(hard_reset, radeon_hard_reset, int, 0444);
MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 4GB)");
module_param_named(vm_size, radeon_vm_size, int, 0444);
-MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default 9)");
+MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default depending on vm_size)");
module_param_named(vm_block_size, radeon_vm_block_size, int, 0444);
MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))");
module_param_named(deep_color, radeon_deep_color, int, 0444);
+MODULE_PARM_DESC(use_pflipirq, "Pflip irqs for pageflip completion (0 = disable, 1 = as fallback, 2 = exclusive (default))");
+module_param_named(use_pflipirq, radeon_use_pflipirq, int, 0444);
+
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
@@ -566,6 +573,7 @@ static struct drm_driver kms_driver = {
.gem_prime_import = drm_gem_prime_import,
.gem_prime_pin = radeon_gem_prime_pin,
.gem_prime_unpin = radeon_gem_prime_unpin,
+ .gem_prime_res_obj = radeon_gem_prime_res_obj,
.gem_prime_get_sg_table = radeon_gem_prime_get_sg_table,
.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
.gem_prime_vmap = radeon_gem_prime_vmap,
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index bd4959ca23aa..3c2094c25b53 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -343,7 +343,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (pixel_clock > 340000)
return true;
else
@@ -365,7 +365,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
return false;
else {
/* HDMI 1.3 supports up to 340 Mhz over single link */
- if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
if (pixel_clock > 340000)
return true;
else
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 665ced3b7313..94b0f2aa3d7c 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -127,8 +127,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
aligned_size = ALIGN(size, PAGE_SIZE);
ret = radeon_gem_object_create(rdev, aligned_size, 0,
RADEON_GEM_DOMAIN_VRAM,
- false, true,
- &gobj);
+ 0, true, &gobj);
if (ret) {
printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
aligned_size);
@@ -331,7 +330,7 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
return 0;
}
-static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
.gamma_set = radeon_crtc_fb_gamma_set,
.gamma_get = radeon_crtc_fb_gamma_get,
.fb_probe = radeonfb_create,
@@ -353,7 +352,9 @@ int radeon_fbdev_init(struct radeon_device *rdev)
rfbdev->rdev = rdev;
rdev->mode_info.rfbdev = rfbdev;
- rfbdev->helper.funcs = &radeon_fb_helper_funcs;
+
+ drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
+ &radeon_fb_helper_funcs);
ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
rdev->num_crtc,
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 2e723651069b..a053a0779aac 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -128,7 +128,7 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
if (rdev->gart.robj == NULL) {
r = radeon_bo_create(rdev, rdev->gart.table_size,
PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
- NULL, &rdev->gart.robj);
+ 0, NULL, &rdev->gart.robj);
if (r) {
return r;
}
@@ -243,7 +243,8 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
if (rdev->gart.ptr) {
- radeon_gart_set_page(rdev, t, page_base);
+ radeon_gart_set_page(rdev, t, page_base,
+ RADEON_GART_PAGE_DUMMY);
}
page_base += RADEON_GPU_PAGE_SIZE;
}
@@ -261,13 +262,15 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
* @pages: number of pages to bind
* @pagelist: pages to bind
* @dma_addr: DMA addresses of pages
+ * @flags: RADEON_GART_PAGE_* flags
*
* Binds the requested pages to the gart page table
* (all asics).
* Returns 0 for success, -EINVAL for failure.
*/
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
- int pages, struct page **pagelist, dma_addr_t *dma_addr)
+ int pages, struct page **pagelist, dma_addr_t *dma_addr,
+ uint32_t flags)
{
unsigned t;
unsigned p;
@@ -287,7 +290,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
if (rdev->gart.ptr) {
page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
- radeon_gart_set_page(rdev, t, page_base);
+ radeon_gart_set_page(rdev, t, page_base, flags);
page_base += RADEON_GPU_PAGE_SIZE;
}
}
@@ -298,33 +301,6 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
}
/**
- * radeon_gart_restore - bind all pages in the gart page table
- *
- * @rdev: radeon_device pointer
- *
- * Binds all pages in the gart page table (all asics).
- * Used to rebuild the gart table on device startup or resume.
- */
-void radeon_gart_restore(struct radeon_device *rdev)
-{
- int i, j, t;
- u64 page_base;
-
- if (!rdev->gart.ptr) {
- return;
- }
- for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
- page_base = rdev->gart.pages_addr[i];
- for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
- radeon_gart_set_page(rdev, t, page_base);
- page_base += RADEON_GPU_PAGE_SIZE;
- }
- }
- mb();
- radeon_gart_tlb_flush(rdev);
-}
-
-/**
* radeon_gart_init - init the driver info for managing the gart
*
* @rdev: radeon_device pointer
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index d09650c1d720..bfd7e1b0ff3f 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -40,9 +40,9 @@ void radeon_gem_object_free(struct drm_gem_object *gobj)
}
}
-int radeon_gem_object_create(struct radeon_device *rdev, int size,
+int radeon_gem_object_create(struct radeon_device *rdev, unsigned long size,
int alignment, int initial_domain,
- bool discardable, bool kernel,
+ u32 flags, bool kernel,
struct drm_gem_object **obj)
{
struct radeon_bo *robj;
@@ -55,23 +55,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
alignment = PAGE_SIZE;
}
- /* maximun bo size is the minimun btw visible vram and gtt size */
- max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+ /* Maximum bo size is the unpinned gtt size since we use the gtt to
+ * handle vram to system pool migrations.
+ */
+ max_size = rdev->mc.gtt_size - rdev->gart_pin_size;
if (size > max_size) {
- printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
- __func__, __LINE__, size >> 20, max_size >> 20);
+ DRM_DEBUG("Allocation size %ldMb bigger than %ldMb limit\n",
+ size >> 20, max_size >> 20);
return -ENOMEM;
}
retry:
- r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
+ r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain,
+ flags, NULL, &robj);
if (r) {
if (r != -ERESTARTSYS) {
if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
initial_domain |= RADEON_GEM_DOMAIN_GTT;
goto retry;
}
- DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
+ DRM_ERROR("Failed to allocate GEM object (%ld, %d, %u, %d)\n",
size, initial_domain, alignment, r);
}
return r;
@@ -208,18 +211,15 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_info *args = data;
struct ttm_mem_type_manager *man;
- unsigned i;
man = &rdev->mman.bdev.man[TTM_PL_VRAM];
args->vram_size = rdev->mc.real_vram_size;
args->vram_visible = (u64)man->size << PAGE_SHIFT;
- if (rdev->stollen_vga_memory)
- args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
- args->vram_visible -= radeon_fbdev_total_size(rdev);
- args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024;
- for(i = 0; i < RADEON_NUM_RINGS; ++i)
- args->gart_size -= rdev->ring[i].ring_size;
+ args->vram_visible -= rdev->vram_pin_size;
+ args->gart_size = rdev->mc.gtt_size;
+ args->gart_size -= rdev->gart_pin_size;
+
return 0;
}
@@ -252,8 +252,8 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
/* create a gem object to contain this object in */
args->size = roundup(args->size, PAGE_SIZE);
r = radeon_gem_object_create(rdev, args->size, args->alignment,
- args->initial_domain, false,
- false, &gobj);
+ args->initial_domain, args->flags,
+ false, &gobj);
if (r) {
up_read(&rdev->exclusive_lock);
r = radeon_gem_handle_lockup(rdev, r);
@@ -358,16 +358,18 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
struct drm_gem_object *gobj;
struct radeon_bo *robj;
int r;
+ uint32_t cur_placement = 0;
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL) {
return -ENOENT;
}
robj = gem_to_radeon_bo(gobj);
- r = radeon_bo_wait(robj, NULL, false);
- /* callback hw specific functions if any */
- if (rdev->asic->ioctl_wait_idle)
- robj->rdev->asic->ioctl_wait_idle(rdev, robj);
+ r = radeon_bo_wait(robj, &cur_placement, false);
+ /* Flush HDP cache via MMIO if necessary */
+ if (rdev->asic->mmio_hdp_flush &&
+ radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM)
+ robj->rdev->asic->mmio_hdp_flush(rdev);
drm_gem_object_unreference_unlocked(gobj);
r = radeon_gem_handle_lockup(rdev, r);
return r;
@@ -461,11 +463,6 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
args->operation = RADEON_VA_RESULT_ERROR;
return -EINVAL;
}
- if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) {
- dev_err(&dev->pdev->dev, "only supported snooped mapping for now\n");
- args->operation = RADEON_VA_RESULT_ERROR;
- return -EINVAL;
- }
switch (args->operation) {
case RADEON_VA_MAP:
@@ -499,9 +496,9 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
switch (args->operation) {
case RADEON_VA_MAP:
- if (bo_va->soffset) {
+ if (bo_va->it.start) {
args->operation = RADEON_VA_RESULT_VA_EXIST;
- args->offset = bo_va->soffset;
+ args->offset = bo_va->it.start * RADEON_GPU_PAGE_SIZE;
goto out;
}
r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, args->flags);
@@ -572,9 +569,8 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
args->size = ALIGN(args->size, PAGE_SIZE);
r = radeon_gem_object_create(rdev, args->size, 0,
- RADEON_GEM_DOMAIN_VRAM,
- false, ttm_bo_type_device,
- &gobj);
+ RADEON_GEM_DOMAIN_VRAM, 0,
+ false, &gobj);
if (r)
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/radeon_ib.c b/drivers/gpu/drm/radeon/radeon_ib.c
new file mode 100644
index 000000000000..65b0c213488d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_ib.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ * Christian König
+ */
+#include <drm/drmP.h>
+#include "radeon.h"
+
+/*
+ * IB
+ * IBs (Indirect Buffers) and areas of GPU accessible memory where
+ * commands are stored. You can put a pointer to the IB in the
+ * command ring and the hw will fetch the commands from the IB
+ * and execute them. Generally userspace acceleration drivers
+ * produce command buffers which are send to the kernel and
+ * put in IBs for execution by the requested ring.
+ */
+static int radeon_debugfs_sa_init(struct radeon_device *rdev);
+
+/**
+ * radeon_ib_get - request an IB (Indirect Buffer)
+ *
+ * @rdev: radeon_device pointer
+ * @ring: ring index the IB is associated with
+ * @ib: IB object returned
+ * @size: requested IB size
+ *
+ * Request an IB (all asics). IBs are allocated using the
+ * suballocator.
+ * Returns 0 on success, error on failure.
+ */
+int radeon_ib_get(struct radeon_device *rdev, int ring,
+ struct radeon_ib *ib, struct radeon_vm *vm,
+ unsigned size)
+{
+ int r;
+
+ r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256);
+ if (r) {
+ dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
+ return r;
+ }
+
+ r = radeon_semaphore_create(rdev, &ib->semaphore);
+ if (r) {
+ return r;
+ }
+
+ ib->ring = ring;
+ ib->fence = NULL;
+ ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo);
+ ib->vm = vm;
+ if (vm) {
+ /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address
+ * space and soffset is the offset inside the pool bo
+ */
+ ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET;
+ } else {
+ ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
+ }
+ ib->is_const_ib = false;
+
+ return 0;
+}
+
+/**
+ * radeon_ib_free - free an IB (Indirect Buffer)
+ *
+ * @rdev: radeon_device pointer
+ * @ib: IB object to free
+ *
+ * Free an IB (all asics).
+ */
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+ radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
+ radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);
+ radeon_fence_unref(&ib->fence);
+}
+
+/**
+ * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
+ *
+ * @rdev: radeon_device pointer
+ * @ib: IB object to schedule
+ * @const_ib: Const IB to schedule (SI only)
+ *
+ * Schedule an IB on the associated ring (all asics).
+ * Returns 0 on success, error on failure.
+ *
+ * On SI, there are two parallel engines fed from the primary ring,
+ * the CE (Constant Engine) and the DE (Drawing Engine). Since
+ * resource descriptors have moved to memory, the CE allows you to
+ * prime the caches while the DE is updating register state so that
+ * the resource descriptors will be already in cache when the draw is
+ * processed. To accomplish this, the userspace driver submits two
+ * IBs, one for the CE and one for the DE. If there is a CE IB (called
+ * a CONST_IB), it will be put on the ring prior to the DE IB. Prior
+ * to SI there was just a DE IB.
+ */
+int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
+ struct radeon_ib *const_ib)
+{
+ struct radeon_ring *ring = &rdev->ring[ib->ring];
+ int r = 0;
+
+ if (!ib->length_dw || !ring->ready) {
+ /* TODO: Nothings in the ib we should report. */
+ dev_err(rdev->dev, "couldn't schedule ib\n");
+ return -EINVAL;
+ }
+
+ /* 64 dwords should be enough for fence too */
+ r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
+ if (r) {
+ dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
+ return r;
+ }
+
+ /* grab a vm id if necessary */
+ if (ib->vm) {
+ struct radeon_fence *vm_id_fence;
+ vm_id_fence = radeon_vm_grab_id(rdev, ib->vm, ib->ring);
+ radeon_semaphore_sync_to(ib->semaphore, vm_id_fence);
+ }
+
+ /* sync with other rings */
+ r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring);
+ if (r) {
+ dev_err(rdev->dev, "failed to sync rings (%d)\n", r);
+ radeon_ring_unlock_undo(rdev, ring);
+ return r;
+ }
+
+ if (ib->vm)
+ radeon_vm_flush(rdev, ib->vm, ib->ring);
+
+ if (const_ib) {
+ radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
+ radeon_semaphore_free(rdev, &const_ib->semaphore, NULL);
+ }
+ radeon_ring_ib_execute(rdev, ib->ring, ib);
+ r = radeon_fence_emit(rdev, &ib->fence, ib->ring);
+ if (r) {
+ dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r);
+ radeon_ring_unlock_undo(rdev, ring);
+ return r;
+ }
+ if (const_ib) {
+ const_ib->fence = radeon_fence_ref(ib->fence);
+ }
+
+ if (ib->vm)
+ radeon_vm_fence(rdev, ib->vm, ib->fence);
+
+ radeon_ring_unlock_commit(rdev, ring);
+ return 0;
+}
+
+/**
+ * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the suballocator to manage a pool of memory
+ * for use as IBs (all asics).
+ * Returns 0 on success, error on failure.
+ */
+int radeon_ib_pool_init(struct radeon_device *rdev)
+{
+ int r;
+
+ if (rdev->ib_pool_ready) {
+ return 0;
+ }
+
+ if (rdev->family >= CHIP_BONAIRE) {
+ r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
+ RADEON_IB_POOL_SIZE*64*1024,
+ RADEON_GPU_PAGE_SIZE,
+ RADEON_GEM_DOMAIN_GTT,
+ RADEON_GEM_GTT_WC);
+ } else {
+ /* Before CIK, it's better to stick to cacheable GTT due
+ * to the command stream checking
+ */
+ r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
+ RADEON_IB_POOL_SIZE*64*1024,
+ RADEON_GPU_PAGE_SIZE,
+ RADEON_GEM_DOMAIN_GTT, 0);
+ }
+ if (r) {
+ return r;
+ }
+
+ r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo);
+ if (r) {
+ return r;
+ }
+
+ rdev->ib_pool_ready = true;
+ if (radeon_debugfs_sa_init(rdev)) {
+ dev_err(rdev->dev, "failed to register debugfs file for SA\n");
+ }
+ return 0;
+}
+
+/**
+ * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Tear down the suballocator managing the pool of memory
+ * for use as IBs (all asics).
+ */
+void radeon_ib_pool_fini(struct radeon_device *rdev)
+{
+ if (rdev->ib_pool_ready) {
+ radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo);
+ radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo);
+ rdev->ib_pool_ready = false;
+ }
+}
+
+/**
+ * radeon_ib_ring_tests - test IBs on the rings
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Test an IB (Indirect Buffer) on each ring.
+ * If the test fails, disable the ring.
+ * Returns 0 on success, error if the primary GFX ring
+ * IB test fails.
+ */
+int radeon_ib_ring_tests(struct radeon_device *rdev)
+{
+ unsigned i;
+ int r;
+
+ for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+ struct radeon_ring *ring = &rdev->ring[i];
+
+ if (!ring->ready)
+ continue;
+
+ r = radeon_ib_test(rdev, i, ring);
+ if (r) {
+ ring->ready = false;
+ rdev->needs_reset = false;
+
+ if (i == RADEON_RING_TYPE_GFX_INDEX) {
+ /* oh, oh, that's really bad */
+ DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r);
+ rdev->accel_working = false;
+ return r;
+
+ } else {
+ /* still not good, but we can live with it */
+ DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Debugfs info
+ */
+#if defined(CONFIG_DEBUG_FS)
+
+static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct radeon_device *rdev = dev->dev_private;
+
+ radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
+
+ return 0;
+
+}
+
+static struct drm_info_list radeon_debugfs_sa_list[] = {
+ {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
+};
+
+#endif
+
+static int radeon_debugfs_sa_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+ return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
+#else
+ return 0;
+#endif
+}
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index d25ae6acfd5a..eb7164d07985 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -254,7 +254,18 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
}
break;
case RADEON_INFO_ACCEL_WORKING2:
- *value = rdev->accel_working;
+ if (rdev->family == CHIP_HAWAII) {
+ if (rdev->accel_working) {
+ if (rdev->new_fw)
+ *value = 3;
+ else
+ *value = 2;
+ } else {
+ *value = 0;
+ }
+ } else {
+ *value = rdev->accel_working;
+ }
break;
case RADEON_INFO_TILING_CONFIG:
if (rdev->family >= CHIP_BONAIRE)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 0592ddb0904b..e27608c29c11 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -685,10 +685,11 @@ extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
-extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
extern int radeon_get_monitor_bpc(struct drm_connector *connector);
+extern struct edid *radeon_connector_edid(struct drm_connector *connector);
+
extern void radeon_connector_hotplug(struct drm_connector *connector);
extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
struct drm_display_mode *mode);
@@ -738,7 +739,6 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux);
-extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 6c717b257d6d..480c87d8edc5 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -46,16 +46,6 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
* function are calling it.
*/
-static void radeon_bo_clear_va(struct radeon_bo *bo)
-{
- struct radeon_bo_va *bo_va, *tmp;
-
- list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) {
- /* remove from all vm address space */
- radeon_vm_bo_rmv(bo->rdev, bo_va);
- }
-}
-
static void radeon_update_memory_usage(struct radeon_bo *bo,
unsigned mem_type, int sign)
{
@@ -90,7 +80,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
list_del_init(&bo->list);
mutex_unlock(&bo->rdev->gem.mutex);
radeon_bo_clear_surface_reg(bo);
- radeon_bo_clear_va(bo);
+ WARN_ON(!list_empty(&bo->va));
drm_gem_object_release(&bo->gem_base);
kfree(bo);
}
@@ -114,15 +104,23 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM;
if (domain & RADEON_GEM_DOMAIN_GTT) {
- if (rbo->rdev->flags & RADEON_IS_AGP) {
- rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
+ if (rbo->flags & RADEON_GEM_GTT_UC) {
+ rbo->placements[c++] = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_TT;
+ } else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
+ (rbo->rdev->flags & RADEON_IS_AGP)) {
+ rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
+ TTM_PL_FLAG_TT;
} else {
rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
}
}
if (domain & RADEON_GEM_DOMAIN_CPU) {
- if (rbo->rdev->flags & RADEON_IS_AGP) {
- rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM;
+ if (rbo->flags & RADEON_GEM_GTT_UC) {
+ rbo->placements[c++] = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_SYSTEM;
+ } else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
+ rbo->rdev->flags & RADEON_IS_AGP) {
+ rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
+ TTM_PL_FLAG_SYSTEM;
} else {
rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
}
@@ -146,7 +144,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
int radeon_bo_create(struct radeon_device *rdev,
unsigned long size, int byte_align, bool kernel, u32 domain,
- struct sg_table *sg, struct radeon_bo **bo_ptr)
+ u32 flags, struct sg_table *sg, struct radeon_bo **bo_ptr)
{
struct radeon_bo *bo;
enum ttm_bo_type type;
@@ -183,6 +181,12 @@ int radeon_bo_create(struct radeon_device *rdev,
bo->initial_domain = domain & (RADEON_GEM_DOMAIN_VRAM |
RADEON_GEM_DOMAIN_GTT |
RADEON_GEM_DOMAIN_CPU);
+
+ bo->flags = flags;
+ /* PCI GART is always snooped */
+ if (!(rdev->flags & RADEON_IS_PCIE))
+ bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
+
radeon_ttm_placement_from_domain(bo, domain);
/* Kernel allocation are uninterruptible */
down_read(&rdev->pm.mclk_lock);
@@ -232,6 +236,15 @@ void radeon_bo_kunmap(struct radeon_bo *bo)
ttm_bo_kunmap(&bo->kmap);
}
+struct radeon_bo *radeon_bo_ref(struct radeon_bo *bo)
+{
+ if (bo == NULL)
+ return NULL;
+
+ ttm_bo_reference(&bo->tbo);
+ return bo;
+}
+
void radeon_bo_unref(struct radeon_bo **bo)
{
struct ttm_buffer_object *tbo;
@@ -241,9 +254,7 @@ void radeon_bo_unref(struct radeon_bo **bo)
return;
rdev = (*bo)->rdev;
tbo = &((*bo)->tbo);
- down_read(&rdev->pm.mclk_lock);
ttm_bo_unref(&tbo);
- up_read(&rdev->pm.mclk_lock);
if (tbo == NULL)
*bo = NULL;
}
@@ -292,9 +303,13 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
bo->pin_count = 1;
if (gpu_addr != NULL)
*gpu_addr = radeon_bo_gpu_offset(bo);
- }
- if (unlikely(r != 0))
+ if (domain == RADEON_GEM_DOMAIN_VRAM)
+ bo->rdev->vram_pin_size += radeon_bo_size(bo);
+ else
+ bo->rdev->gart_pin_size += radeon_bo_size(bo);
+ } else {
dev_err(bo->rdev->dev, "%p pin failed\n", bo);
+ }
return r;
}
@@ -317,8 +332,14 @@ int radeon_bo_unpin(struct radeon_bo *bo)
for (i = 0; i < bo->placement.num_placement; i++)
bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
- if (unlikely(r != 0))
+ if (likely(r == 0)) {
+ if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
+ bo->rdev->vram_pin_size -= radeon_bo_size(bo);
+ else
+ bo->rdev->gart_pin_size -= radeon_bo_size(bo);
+ } else {
dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
+ }
return r;
}
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 5a873f31a171..98a47fdf3625 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -124,11 +124,12 @@ extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
extern int radeon_bo_create(struct radeon_device *rdev,
unsigned long size, int byte_align,
- bool kernel, u32 domain,
+ bool kernel, u32 domain, u32 flags,
struct sg_table *sg,
struct radeon_bo **bo_ptr);
extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
extern void radeon_bo_kunmap(struct radeon_bo *bo);
+extern struct radeon_bo *radeon_bo_ref(struct radeon_bo *bo);
extern void radeon_bo_unref(struct radeon_bo **bo);
extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
@@ -170,7 +171,8 @@ static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)
extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,
struct radeon_sa_manager *sa_manager,
- unsigned size, u32 align, u32 domain);
+ unsigned size, u32 align, u32 domain,
+ u32 flags);
extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
struct radeon_sa_manager *sa_manager);
extern int radeon_sa_bo_manager_start(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index e447e390d09a..23314be49480 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1303,10 +1303,6 @@ int radeon_pm_init(struct radeon_device *rdev)
case CHIP_RS780:
case CHIP_RS880:
case CHIP_RV770:
- case CHIP_BARTS:
- case CHIP_TURKS:
- case CHIP_CAICOS:
- case CHIP_CAYMAN:
/* DPM requires the RLC, RV770+ dGPU requires SMC */
if (!rdev->rlc_fw)
rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1330,6 +1326,10 @@ int radeon_pm_init(struct radeon_device *rdev)
case CHIP_PALM:
case CHIP_SUMO:
case CHIP_SUMO2:
+ case CHIP_BARTS:
+ case CHIP_TURKS:
+ case CHIP_CAICOS:
+ case CHIP_CAYMAN:
case CHIP_ARUBA:
case CHIP_TAHITI:
case CHIP_PITCAIRN:
@@ -1400,9 +1400,7 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
}
radeon_hwmon_fini(rdev);
-
- if (rdev->pm.power_state)
- kfree(rdev->pm.power_state);
+ kfree(rdev->pm.power_state);
}
static void radeon_pm_fini_dpm(struct radeon_device *rdev)
@@ -1421,9 +1419,7 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
radeon_dpm_fini(rdev);
radeon_hwmon_fini(rdev);
-
- if (rdev->pm.power_state)
- kfree(rdev->pm.power_state);
+ kfree(rdev->pm.power_state);
}
void radeon_pm_fini(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c
index 20074560fc25..0b16f2cbcf17 100644
--- a/drivers/gpu/drm/radeon/radeon_prime.c
+++ b/drivers/gpu/drm/radeon/radeon_prime.c
@@ -65,7 +65,7 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
int ret;
ret = radeon_bo_create(rdev, size, PAGE_SIZE, false,
- RADEON_GEM_DOMAIN_GTT, sg, &bo);
+ RADEON_GEM_DOMAIN_GTT, 0, sg, &bo);
if (ret)
return ERR_PTR(ret);
@@ -103,3 +103,11 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj)
radeon_bo_unpin(bo);
radeon_bo_unreserve(bo);
}
+
+
+struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+ struct radeon_bo *bo = gem_to_radeon_bo(obj);
+
+ return bo->tbo.resv;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index f8050f5429e2..5b4e0cf231a0 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -26,258 +26,8 @@
* Jerome Glisse
* Christian König
*/
-#include <linux/seq_file.h>
-#include <linux/slab.h>
#include <drm/drmP.h>
-#include <drm/radeon_drm.h>
-#include "radeon_reg.h"
#include "radeon.h"
-#include "atom.h"
-
-/*
- * IB
- * IBs (Indirect Buffers) and areas of GPU accessible memory where
- * commands are stored. You can put a pointer to the IB in the
- * command ring and the hw will fetch the commands from the IB
- * and execute them. Generally userspace acceleration drivers
- * produce command buffers which are send to the kernel and
- * put in IBs for execution by the requested ring.
- */
-static int radeon_debugfs_sa_init(struct radeon_device *rdev);
-
-/**
- * radeon_ib_get - request an IB (Indirect Buffer)
- *
- * @rdev: radeon_device pointer
- * @ring: ring index the IB is associated with
- * @ib: IB object returned
- * @size: requested IB size
- *
- * Request an IB (all asics). IBs are allocated using the
- * suballocator.
- * Returns 0 on success, error on failure.
- */
-int radeon_ib_get(struct radeon_device *rdev, int ring,
- struct radeon_ib *ib, struct radeon_vm *vm,
- unsigned size)
-{
- int r;
-
- r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256);
- if (r) {
- dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
- return r;
- }
-
- r = radeon_semaphore_create(rdev, &ib->semaphore);
- if (r) {
- return r;
- }
-
- ib->ring = ring;
- ib->fence = NULL;
- ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo);
- ib->vm = vm;
- if (vm) {
- /* ib pool is bound at RADEON_VA_IB_OFFSET in virtual address
- * space and soffset is the offset inside the pool bo
- */
- ib->gpu_addr = ib->sa_bo->soffset + RADEON_VA_IB_OFFSET;
- } else {
- ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
- }
- ib->is_const_ib = false;
-
- return 0;
-}
-
-/**
- * radeon_ib_free - free an IB (Indirect Buffer)
- *
- * @rdev: radeon_device pointer
- * @ib: IB object to free
- *
- * Free an IB (all asics).
- */
-void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
-{
- radeon_semaphore_free(rdev, &ib->semaphore, ib->fence);
- radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);
- radeon_fence_unref(&ib->fence);
-}
-
-/**
- * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
- *
- * @rdev: radeon_device pointer
- * @ib: IB object to schedule
- * @const_ib: Const IB to schedule (SI only)
- *
- * Schedule an IB on the associated ring (all asics).
- * Returns 0 on success, error on failure.
- *
- * On SI, there are two parallel engines fed from the primary ring,
- * the CE (Constant Engine) and the DE (Drawing Engine). Since
- * resource descriptors have moved to memory, the CE allows you to
- * prime the caches while the DE is updating register state so that
- * the resource descriptors will be already in cache when the draw is
- * processed. To accomplish this, the userspace driver submits two
- * IBs, one for the CE and one for the DE. If there is a CE IB (called
- * a CONST_IB), it will be put on the ring prior to the DE IB. Prior
- * to SI there was just a DE IB.
- */
-int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
- struct radeon_ib *const_ib)
-{
- struct radeon_ring *ring = &rdev->ring[ib->ring];
- int r = 0;
-
- if (!ib->length_dw || !ring->ready) {
- /* TODO: Nothings in the ib we should report. */
- dev_err(rdev->dev, "couldn't schedule ib\n");
- return -EINVAL;
- }
-
- /* 64 dwords should be enough for fence too */
- r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
- if (r) {
- dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
- return r;
- }
-
- /* grab a vm id if necessary */
- if (ib->vm) {
- struct radeon_fence *vm_id_fence;
- vm_id_fence = radeon_vm_grab_id(rdev, ib->vm, ib->ring);
- radeon_semaphore_sync_to(ib->semaphore, vm_id_fence);
- }
-
- /* sync with other rings */
- r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring);
- if (r) {
- dev_err(rdev->dev, "failed to sync rings (%d)\n", r);
- radeon_ring_unlock_undo(rdev, ring);
- return r;
- }
-
- if (ib->vm)
- radeon_vm_flush(rdev, ib->vm, ib->ring);
-
- if (const_ib) {
- radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
- radeon_semaphore_free(rdev, &const_ib->semaphore, NULL);
- }
- radeon_ring_ib_execute(rdev, ib->ring, ib);
- r = radeon_fence_emit(rdev, &ib->fence, ib->ring);
- if (r) {
- dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r);
- radeon_ring_unlock_undo(rdev, ring);
- return r;
- }
- if (const_ib) {
- const_ib->fence = radeon_fence_ref(ib->fence);
- }
-
- if (ib->vm)
- radeon_vm_fence(rdev, ib->vm, ib->fence);
-
- radeon_ring_unlock_commit(rdev, ring);
- return 0;
-}
-
-/**
- * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool
- *
- * @rdev: radeon_device pointer
- *
- * Initialize the suballocator to manage a pool of memory
- * for use as IBs (all asics).
- * Returns 0 on success, error on failure.
- */
-int radeon_ib_pool_init(struct radeon_device *rdev)
-{
- int r;
-
- if (rdev->ib_pool_ready) {
- return 0;
- }
- r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
- RADEON_IB_POOL_SIZE*64*1024,
- RADEON_GPU_PAGE_SIZE,
- RADEON_GEM_DOMAIN_GTT);
- if (r) {
- return r;
- }
-
- r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo);
- if (r) {
- return r;
- }
-
- rdev->ib_pool_ready = true;
- if (radeon_debugfs_sa_init(rdev)) {
- dev_err(rdev->dev, "failed to register debugfs file for SA\n");
- }
- return 0;
-}
-
-/**
- * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool
- *
- * @rdev: radeon_device pointer
- *
- * Tear down the suballocator managing the pool of memory
- * for use as IBs (all asics).
- */
-void radeon_ib_pool_fini(struct radeon_device *rdev)
-{
- if (rdev->ib_pool_ready) {
- radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo);
- radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo);
- rdev->ib_pool_ready = false;
- }
-}
-
-/**
- * radeon_ib_ring_tests - test IBs on the rings
- *
- * @rdev: radeon_device pointer
- *
- * Test an IB (Indirect Buffer) on each ring.
- * If the test fails, disable the ring.
- * Returns 0 on success, error if the primary GFX ring
- * IB test fails.
- */
-int radeon_ib_ring_tests(struct radeon_device *rdev)
-{
- unsigned i;
- int r;
-
- for (i = 0; i < RADEON_NUM_RINGS; ++i) {
- struct radeon_ring *ring = &rdev->ring[i];
-
- if (!ring->ready)
- continue;
-
- r = radeon_ib_test(rdev, i, ring);
- if (r) {
- ring->ready = false;
- rdev->needs_reset = false;
-
- if (i == RADEON_RING_TYPE_GFX_INDEX) {
- /* oh, oh, that's really bad */
- DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r);
- rdev->accel_working = false;
- return r;
-
- } else {
- /* still not good, but we can live with it */
- DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r);
- }
- }
- }
- return 0;
-}
/*
* Rings
@@ -433,11 +183,21 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig
*/
void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
{
+ /* If we are emitting the HDP flush via the ring buffer, we need to
+ * do it before padding.
+ */
+ if (rdev->asic->ring[ring->idx]->hdp_flush)
+ rdev->asic->ring[ring->idx]->hdp_flush(rdev, ring);
/* We pad to match fetch size */
while (ring->wptr & ring->align_mask) {
radeon_ring_write(ring, ring->nop);
}
mb();
+ /* If we are emitting the HDP flush via MMIO, we need to do it after
+ * all CPU writes to VRAM finished.
+ */
+ if (rdev->asic->mmio_hdp_flush)
+ rdev->asic->mmio_hdp_flush(rdev);
radeon_ring_set_wptr(rdev, ring);
}
@@ -641,6 +401,8 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
if (ring->ring_obj == NULL) {
r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_GTT,
+ (rdev->flags & RADEON_IS_PCIE) ?
+ RADEON_GEM_GTT_WC : 0,
NULL, &ring->ring_obj);
if (r) {
dev_err(rdev->dev, "(%d) ring create failed\n", r);
@@ -791,22 +553,6 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = {
{"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index},
};
-static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct radeon_device *rdev = dev->dev_private;
-
- radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
-
- return 0;
-
-}
-
-static struct drm_info_list radeon_debugfs_sa_list[] = {
- {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
-};
-
#endif
static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring)
@@ -828,12 +574,3 @@ static int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ri
#endif
return 0;
}
-
-static int radeon_debugfs_sa_init(struct radeon_device *rdev)
-{
-#if defined(CONFIG_DEBUG_FS)
- return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
-#else
- return 0;
-#endif
-}
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
index adcf3e2f07da..b84f97c8718c 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -49,7 +49,7 @@ static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager);
int radeon_sa_bo_manager_init(struct radeon_device *rdev,
struct radeon_sa_manager *sa_manager,
- unsigned size, u32 align, u32 domain)
+ unsigned size, u32 align, u32 domain, u32 flags)
{
int i, r;
@@ -65,7 +65,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
}
r = radeon_bo_create(rdev, size, align, true,
- domain, NULL, &sa_manager->bo);
+ domain, flags, NULL, &sa_manager->bo);
if (r) {
dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index 3a13e0d1055c..5adf4207453d 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -56,13 +56,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
/* Number of tests =
* (Total GTT - IB pool - writeback page - ring buffers) / test size
*/
- n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024;
- for (i = 0; i < RADEON_NUM_RINGS; ++i)
- n -= rdev->ring[i].ring_size;
- if (rdev->wb.wb_obj)
- n -= RADEON_GPU_PAGE_SIZE;
- if (rdev->ih.ring_obj)
- n -= rdev->ih.ring_size;
+ n = rdev->mc.gtt_size - rdev->gart_pin_size;
n /= size;
gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
@@ -73,7 +67,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
}
r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
- NULL, &vram_obj);
+ 0, NULL, &vram_obj);
if (r) {
DRM_ERROR("Failed to create VRAM object\n");
goto out_cleanup;
@@ -93,7 +87,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
struct radeon_fence *fence = NULL;
r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i);
+ RADEON_GEM_DOMAIN_GTT, 0, NULL, gtt_obj + i);
if (r) {
DRM_ERROR("Failed to create GTT object %d\n", i);
goto out_lclean;
diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
index f749f2c3bbdb..9db74a96ef61 100644
--- a/drivers/gpu/drm/radeon/radeon_trace.h
+++ b/drivers/gpu/drm/radeon/radeon_trace.h
@@ -72,8 +72,8 @@ TRACE_EVENT(radeon_vm_bo_update,
),
TP_fast_assign(
- __entry->soffset = bo_va->soffset;
- __entry->eoffset = bo_va->eoffset;
+ __entry->soffset = bo_va->it.start;
+ __entry->eoffset = bo_va->it.last + 1;
__entry->flags = bo_va->flags;
),
TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
@@ -104,6 +104,24 @@ TRACE_EVENT(radeon_vm_set_page,
__entry->flags, __entry->count)
);
+TRACE_EVENT(radeon_vm_flush,
+ TP_PROTO(uint64_t pd_addr, unsigned ring, unsigned id),
+ TP_ARGS(pd_addr, ring, id),
+ TP_STRUCT__entry(
+ __field(u64, pd_addr)
+ __field(u32, ring)
+ __field(u32, id)
+ ),
+
+ TP_fast_assign(
+ __entry->pd_addr = pd_addr;
+ __entry->ring = ring;
+ __entry->id = id;
+ ),
+ TP_printk("pd_addr=%010Lx, ring=%u, id=%u",
+ __entry->pd_addr, __entry->ring, __entry->id)
+);
+
DECLARE_EVENT_CLASS(radeon_fence_request,
TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index c8a8a5144ec1..72afe82a95c9 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -521,6 +521,8 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
struct ttm_mem_reg *bo_mem)
{
struct radeon_ttm_tt *gtt = (void*)ttm;
+ uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ |
+ RADEON_GART_PAGE_WRITE;
int r;
gtt->offset = (unsigned long)(bo_mem->start << PAGE_SHIFT);
@@ -528,8 +530,10 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
ttm->num_pages, bo_mem, ttm);
}
- r = radeon_gart_bind(gtt->rdev, gtt->offset,
- ttm->num_pages, ttm->pages, gtt->ttm.dma_address);
+ if (ttm->caching_state == tt_cached)
+ flags |= RADEON_GART_PAGE_SNOOP;
+ r = radeon_gart_bind(gtt->rdev, gtt->offset, ttm->num_pages,
+ ttm->pages, gtt->ttm.dma_address, flags);
if (r) {
DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
ttm->num_pages, (unsigned)gtt->offset);
@@ -726,7 +730,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM,
+ RADEON_GEM_DOMAIN_VRAM, 0,
NULL, &rdev->stollen_vga_memory);
if (r) {
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_ucode.c b/drivers/gpu/drm/radeon/radeon_ucode.c
new file mode 100644
index 000000000000..6beec680390c
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_ucode.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "radeon.h"
+#include "radeon_ucode.h"
+
+static void radeon_ucode_print_common_hdr(const struct common_firmware_header *hdr)
+{
+ DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes));
+ DRM_DEBUG("header_size_bytes: %u\n", le32_to_cpu(hdr->header_size_bytes));
+ DRM_DEBUG("header_version_major: %u\n", le16_to_cpu(hdr->header_version_major));
+ DRM_DEBUG("header_version_minor: %u\n", le16_to_cpu(hdr->header_version_minor));
+ DRM_DEBUG("ip_version_major: %u\n", le16_to_cpu(hdr->ip_version_major));
+ DRM_DEBUG("ip_version_minor: %u\n", le16_to_cpu(hdr->ip_version_minor));
+ DRM_DEBUG("ucode_version: 0x%08x\n", le32_to_cpu(hdr->ucode_version));
+ DRM_DEBUG("ucode_size_bytes: %u\n", le32_to_cpu(hdr->ucode_size_bytes));
+ DRM_DEBUG("ucode_array_offset_bytes: %u\n",
+ le32_to_cpu(hdr->ucode_array_offset_bytes));
+ DRM_DEBUG("crc32: 0x%08x\n", le32_to_cpu(hdr->crc32));
+}
+
+void radeon_ucode_print_mc_hdr(const struct common_firmware_header *hdr)
+{
+ uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+ uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+ DRM_DEBUG("MC\n");
+ radeon_ucode_print_common_hdr(hdr);
+
+ if (version_major == 1) {
+ const struct mc_firmware_header_v1_0 *mc_hdr =
+ container_of(hdr, struct mc_firmware_header_v1_0, header);
+
+ DRM_DEBUG("io_debug_size_bytes: %u\n",
+ le32_to_cpu(mc_hdr->io_debug_size_bytes));
+ DRM_DEBUG("io_debug_array_offset_bytes: %u\n",
+ le32_to_cpu(mc_hdr->io_debug_array_offset_bytes));
+ } else {
+ DRM_ERROR("Unknown MC ucode version: %u.%u\n", version_major, version_minor);
+ }
+}
+
+void radeon_ucode_print_smc_hdr(const struct common_firmware_header *hdr)
+{
+ uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+ uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+ DRM_DEBUG("SMC\n");
+ radeon_ucode_print_common_hdr(hdr);
+
+ if (version_major == 1) {
+ const struct smc_firmware_header_v1_0 *smc_hdr =
+ container_of(hdr, struct smc_firmware_header_v1_0, header);
+
+ DRM_DEBUG("ucode_start_addr: %u\n", le32_to_cpu(smc_hdr->ucode_start_addr));
+ } else {
+ DRM_ERROR("Unknown SMC ucode version: %u.%u\n", version_major, version_minor);
+ }
+}
+
+void radeon_ucode_print_gfx_hdr(const struct common_firmware_header *hdr)
+{
+ uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+ uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+ DRM_DEBUG("GFX\n");
+ radeon_ucode_print_common_hdr(hdr);
+
+ if (version_major == 1) {
+ const struct gfx_firmware_header_v1_0 *gfx_hdr =
+ container_of(hdr, struct gfx_firmware_header_v1_0, header);
+
+ DRM_DEBUG("ucode_feature_version: %u\n",
+ le32_to_cpu(gfx_hdr->ucode_feature_version));
+ DRM_DEBUG("jt_offset: %u\n", le32_to_cpu(gfx_hdr->jt_offset));
+ DRM_DEBUG("jt_size: %u\n", le32_to_cpu(gfx_hdr->jt_size));
+ } else {
+ DRM_ERROR("Unknown GFX ucode version: %u.%u\n", version_major, version_minor);
+ }
+}
+
+void radeon_ucode_print_rlc_hdr(const struct common_firmware_header *hdr)
+{
+ uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+ uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+ DRM_DEBUG("RLC\n");
+ radeon_ucode_print_common_hdr(hdr);
+
+ if (version_major == 1) {
+ const struct rlc_firmware_header_v1_0 *rlc_hdr =
+ container_of(hdr, struct rlc_firmware_header_v1_0, header);
+
+ DRM_DEBUG("ucode_feature_version: %u\n",
+ le32_to_cpu(rlc_hdr->ucode_feature_version));
+ DRM_DEBUG("save_and_restore_offset: %u\n",
+ le32_to_cpu(rlc_hdr->save_and_restore_offset));
+ DRM_DEBUG("clear_state_descriptor_offset: %u\n",
+ le32_to_cpu(rlc_hdr->clear_state_descriptor_offset));
+ DRM_DEBUG("avail_scratch_ram_locations: %u\n",
+ le32_to_cpu(rlc_hdr->avail_scratch_ram_locations));
+ DRM_DEBUG("master_pkt_description_offset: %u\n",
+ le32_to_cpu(rlc_hdr->master_pkt_description_offset));
+ } else {
+ DRM_ERROR("Unknown RLC ucode version: %u.%u\n", version_major, version_minor);
+ }
+}
+
+void radeon_ucode_print_sdma_hdr(const struct common_firmware_header *hdr)
+{
+ uint16_t version_major = le16_to_cpu(hdr->header_version_major);
+ uint16_t version_minor = le16_to_cpu(hdr->header_version_minor);
+
+ DRM_DEBUG("SDMA\n");
+ radeon_ucode_print_common_hdr(hdr);
+
+ if (version_major == 1) {
+ const struct sdma_firmware_header_v1_0 *sdma_hdr =
+ container_of(hdr, struct sdma_firmware_header_v1_0, header);
+
+ DRM_DEBUG("ucode_feature_version: %u\n",
+ le32_to_cpu(sdma_hdr->ucode_feature_version));
+ DRM_DEBUG("ucode_change_version: %u\n",
+ le32_to_cpu(sdma_hdr->ucode_change_version));
+ DRM_DEBUG("jt_offset: %u\n", le32_to_cpu(sdma_hdr->jt_offset));
+ DRM_DEBUG("jt_size: %u\n", le32_to_cpu(sdma_hdr->jt_size));
+ } else {
+ DRM_ERROR("Unknown SDMA ucode version: %u.%u\n",
+ version_major, version_minor);
+ }
+}
+
+int radeon_ucode_validate(const struct firmware *fw)
+{
+ const struct common_firmware_header *hdr =
+ (const struct common_firmware_header *)fw->data;
+
+ if (fw->size == le32_to_cpu(hdr->size_bytes))
+ return 0;
+
+ return -EINVAL;
+}
+
diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h
index 4e7c3269b183..dc4576e4d8ad 100644
--- a/drivers/gpu/drm/radeon/radeon_ucode.h
+++ b/drivers/gpu/drm/radeon/radeon_ucode.h
@@ -153,4 +153,75 @@
#define HAWAII_SMC_UCODE_START 0x20000
#define HAWAII_SMC_UCODE_SIZE 0x1FDEC
+struct common_firmware_header {
+ uint32_t size_bytes; /* size of the entire header+image(s) in bytes */
+ uint32_t header_size_bytes; /* size of just the header in bytes */
+ uint16_t header_version_major; /* header version */
+ uint16_t header_version_minor; /* header version */
+ uint16_t ip_version_major; /* IP version */
+ uint16_t ip_version_minor; /* IP version */
+ uint32_t ucode_version;
+ uint32_t ucode_size_bytes; /* size of ucode in bytes */
+ uint32_t ucode_array_offset_bytes; /* payload offset from the start of the header */
+ uint32_t crc32; /* crc32 checksum of the payload */
+};
+
+/* version_major=1, version_minor=0 */
+struct mc_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t io_debug_size_bytes; /* size of debug array in dwords */
+ uint32_t io_debug_array_offset_bytes; /* payload offset from the start of the header */
+};
+
+/* version_major=1, version_minor=0 */
+struct smc_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t ucode_start_addr;
+};
+
+/* version_major=1, version_minor=0 */
+struct gfx_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t ucode_feature_version;
+ uint32_t jt_offset; /* jt location */
+ uint32_t jt_size; /* size of jt */
+};
+
+/* version_major=1, version_minor=0 */
+struct rlc_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t ucode_feature_version;
+ uint32_t save_and_restore_offset;
+ uint32_t clear_state_descriptor_offset;
+ uint32_t avail_scratch_ram_locations;
+ uint32_t master_pkt_description_offset;
+};
+
+/* version_major=1, version_minor=0 */
+struct sdma_firmware_header_v1_0 {
+ struct common_firmware_header header;
+ uint32_t ucode_feature_version;
+ uint32_t ucode_change_version;
+ uint32_t jt_offset; /* jt location */
+ uint32_t jt_size; /* size of jt */
+};
+
+/* header is fixed size */
+union radeon_firmware_header {
+ struct common_firmware_header common;
+ struct mc_firmware_header_v1_0 mc;
+ struct smc_firmware_header_v1_0 smc;
+ struct gfx_firmware_header_v1_0 gfx;
+ struct rlc_firmware_header_v1_0 rlc;
+ struct sdma_firmware_header_v1_0 sdma;
+ uint8_t raw[0x100];
+};
+
+void radeon_ucode_print_mc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_smc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_gfx_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
+void radeon_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
+int radeon_ucode_validate(const struct firmware *fw);
+
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index a4ad270e8261..6bf55ec85b62 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -117,7 +117,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->uvd.vcpu_bo);
if (r) {
dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r);
return r;
@@ -674,7 +674,7 @@ int radeon_uvd_get_create_msg(struct radeon_device *rdev, int ring,
int r, i;
r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
if (r)
return r;
@@ -720,7 +720,7 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
int r, i;
r = radeon_bo_create(rdev, 1024, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &bo);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL, &bo);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
index aa21c31a846c..f9b70a43aa52 100644
--- a/drivers/gpu/drm/radeon/radeon_vce.c
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -126,7 +126,7 @@ int radeon_vce_init(struct radeon_device *rdev)
size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL, &rdev->vce.vcpu_bo);
if (r) {
dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c
index 725d3669014f..ccae4d9dc3de 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -238,8 +238,8 @@ void radeon_vm_flush(struct radeon_device *rdev,
uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory);
/* if we can't remember our last VM flush then flush now! */
- /* XXX figure out why we have to flush all the time */
- if (!vm->last_flush || true || pd_addr != vm->pd_gpu_addr) {
+ if (!vm->last_flush || pd_addr != vm->pd_gpu_addr) {
+ trace_radeon_vm_flush(pd_addr, ring, vm->id);
vm->pd_gpu_addr = pd_addr;
radeon_ring_vm_flush(rdev, ring, vm);
}
@@ -325,17 +325,15 @@ struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev,
}
bo_va->vm = vm;
bo_va->bo = bo;
- bo_va->soffset = 0;
- bo_va->eoffset = 0;
+ bo_va->it.start = 0;
+ bo_va->it.last = 0;
bo_va->flags = 0;
- bo_va->valid = false;
+ bo_va->addr = 0;
bo_va->ref_count = 1;
INIT_LIST_HEAD(&bo_va->bo_list);
- INIT_LIST_HEAD(&bo_va->vm_list);
INIT_LIST_HEAD(&bo_va->vm_status);
mutex_lock(&vm->mutex);
- list_add(&bo_va->vm_list, &vm->va);
list_add_tail(&bo_va->bo_list, &bo->va);
mutex_unlock(&vm->mutex);
@@ -343,6 +341,42 @@ struct radeon_bo_va *radeon_vm_bo_add(struct radeon_device *rdev,
}
/**
+ * radeon_vm_set_pages - helper to call the right asic function
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: hw access flags
+ *
+ * Traces the parameters and calls the right asic functions
+ * to setup the page table using the DMA.
+ */
+static void radeon_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+{
+ trace_radeon_vm_set_page(pe, addr, count, incr, flags);
+
+ if ((flags & R600_PTE_GART_MASK) == R600_PTE_GART_MASK) {
+ uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
+ radeon_asic_vm_copy_pages(rdev, ib, pe, src, count);
+
+ } else if ((flags & R600_PTE_SYSTEM) || (count < 3)) {
+ radeon_asic_vm_write_pages(rdev, ib, pe, addr,
+ count, incr, flags);
+
+ } else {
+ radeon_asic_vm_set_pages(rdev, ib, pe, addr,
+ count, incr, flags);
+ }
+}
+
+/**
* radeon_vm_clear_bo - initially clear the page dir/table
*
* @rdev: radeon_device pointer
@@ -376,14 +410,15 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev,
addr = radeon_bo_gpu_offset(bo);
entries = radeon_bo_size(bo) / 8;
- r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib,
- NULL, entries * 2 + 64);
+ r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, 256);
if (r)
goto error;
ib.length_dw = 0;
- radeon_asic_vm_set_page(rdev, &ib, addr, 0, entries, 0, 0);
+ radeon_vm_set_pages(rdev, &ib, addr, 0, entries, 0, 0);
+ radeon_asic_vm_pad_ib(rdev, &ib);
+ WARN_ON(ib.length_dw > 64);
r = radeon_ib_schedule(rdev, &ib, NULL);
if (r)
@@ -419,11 +454,9 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
uint32_t flags)
{
uint64_t size = radeon_bo_size(bo_va->bo);
- uint64_t eoffset, last_offset = 0;
struct radeon_vm *vm = bo_va->vm;
- struct radeon_bo_va *tmp;
- struct list_head *head;
unsigned last_pfn, pt_idx;
+ uint64_t eoffset;
int r;
if (soffset) {
@@ -445,51 +478,49 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
}
mutex_lock(&vm->mutex);
- head = &vm->va;
- last_offset = 0;
- list_for_each_entry(tmp, &vm->va, vm_list) {
- if (bo_va == tmp) {
- /* skip over currently modified bo */
- continue;
+ if (bo_va->it.start || bo_va->it.last) {
+ if (bo_va->addr) {
+ /* add a clone of the bo_va to clear the old address */
+ struct radeon_bo_va *tmp;
+ tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
+ tmp->it.start = bo_va->it.start;
+ tmp->it.last = bo_va->it.last;
+ tmp->vm = vm;
+ tmp->addr = bo_va->addr;
+ tmp->bo = radeon_bo_ref(bo_va->bo);
+ list_add(&tmp->vm_status, &vm->freed);
}
- if (soffset >= last_offset && eoffset <= tmp->soffset) {
- /* bo can be added before this one */
- break;
- }
- if (eoffset > tmp->soffset && soffset < tmp->eoffset) {
- /* bo and tmp overlap, invalid offset */
- dev_err(rdev->dev, "bo %p va 0x%08X conflict with (bo %p 0x%08X 0x%08X)\n",
- bo_va->bo, (unsigned)bo_va->soffset, tmp->bo,
- (unsigned)tmp->soffset, (unsigned)tmp->eoffset);
- mutex_unlock(&vm->mutex);
- return -EINVAL;
- }
- last_offset = tmp->eoffset;
- head = &tmp->vm_list;
+ interval_tree_remove(&bo_va->it, &vm->va);
+ bo_va->it.start = 0;
+ bo_va->it.last = 0;
}
- if (bo_va->soffset) {
- /* add a clone of the bo_va to clear the old address */
- tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL);
- if (!tmp) {
+ soffset /= RADEON_GPU_PAGE_SIZE;
+ eoffset /= RADEON_GPU_PAGE_SIZE;
+ if (soffset || eoffset) {
+ struct interval_tree_node *it;
+ it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
+ if (it) {
+ struct radeon_bo_va *tmp;
+ tmp = container_of(it, struct radeon_bo_va, it);
+ /* bo and tmp overlap, invalid offset */
+ dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
+ "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
+ soffset, tmp->bo, tmp->it.start, tmp->it.last);
mutex_unlock(&vm->mutex);
- return -ENOMEM;
+ return -EINVAL;
}
- tmp->soffset = bo_va->soffset;
- tmp->eoffset = bo_va->eoffset;
- tmp->vm = vm;
- list_add(&tmp->vm_status, &vm->freed);
+ bo_va->it.start = soffset;
+ bo_va->it.last = eoffset - 1;
+ interval_tree_insert(&bo_va->it, &vm->va);
}
- bo_va->soffset = soffset;
- bo_va->eoffset = eoffset;
bo_va->flags = flags;
- bo_va->valid = false;
- list_move(&bo_va->vm_list, head);
+ bo_va->addr = 0;
- soffset = (soffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size;
- eoffset = (eoffset / RADEON_GPU_PAGE_SIZE) >> radeon_vm_block_size;
+ soffset >>= radeon_vm_block_size;
+ eoffset >>= radeon_vm_block_size;
BUG_ON(eoffset >= radeon_vm_num_pdes(rdev));
@@ -510,7 +541,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
r = radeon_bo_create(rdev, RADEON_VM_PTE_COUNT * 8,
RADEON_GPU_PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_VRAM, NULL, &pt);
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL, &pt);
if (r)
return r;
@@ -611,7 +642,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
ndw = 64;
/* assume the worst case */
- ndw += vm->max_pde_used * 16;
+ ndw += vm->max_pde_used * 6;
/* update too big for an IB */
if (ndw > 0xfffff)
@@ -640,9 +671,9 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
((last_pt + incr * count) != pt)) {
if (count) {
- radeon_asic_vm_set_page(rdev, &ib, last_pde,
- last_pt, count, incr,
- R600_PTE_VALID);
+ radeon_vm_set_pages(rdev, &ib, last_pde,
+ last_pt, count, incr,
+ R600_PTE_VALID);
}
count = 1;
@@ -654,12 +685,14 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
}
if (count)
- radeon_asic_vm_set_page(rdev, &ib, last_pde, last_pt, count,
- incr, R600_PTE_VALID);
+ radeon_vm_set_pages(rdev, &ib, last_pde, last_pt, count,
+ incr, R600_PTE_VALID);
if (ib.length_dw != 0) {
+ radeon_asic_vm_pad_ib(rdev, &ib);
radeon_semaphore_sync_to(ib.semaphore, pd->tbo.sync_obj);
radeon_semaphore_sync_to(ib.semaphore, vm->last_id_use);
+ WARN_ON(ib.length_dw > ndw);
r = radeon_ib_schedule(rdev, &ib, NULL);
if (r) {
radeon_ib_free(rdev, &ib);
@@ -725,30 +758,30 @@ static void radeon_vm_frag_ptes(struct radeon_device *rdev,
(frag_start >= frag_end)) {
count = (pe_end - pe_start) / 8;
- radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
- RADEON_GPU_PAGE_SIZE, flags);
+ radeon_vm_set_pages(rdev, ib, pe_start, addr, count,
+ RADEON_GPU_PAGE_SIZE, flags);
return;
}
/* handle the 4K area at the beginning */
if (pe_start != frag_start) {
count = (frag_start - pe_start) / 8;
- radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
- RADEON_GPU_PAGE_SIZE, flags);
+ radeon_vm_set_pages(rdev, ib, pe_start, addr, count,
+ RADEON_GPU_PAGE_SIZE, flags);
addr += RADEON_GPU_PAGE_SIZE * count;
}
/* handle the area in the middle */
count = (frag_end - frag_start) / 8;
- radeon_asic_vm_set_page(rdev, ib, frag_start, addr, count,
- RADEON_GPU_PAGE_SIZE, flags | frag_flags);
+ radeon_vm_set_pages(rdev, ib, frag_start, addr, count,
+ RADEON_GPU_PAGE_SIZE, flags | frag_flags);
/* handle the 4K area at the end */
if (frag_end != pe_end) {
addr += RADEON_GPU_PAGE_SIZE * count;
count = (pe_end - frag_end) / 8;
- radeon_asic_vm_set_page(rdev, ib, frag_end, addr, count,
- RADEON_GPU_PAGE_SIZE, flags);
+ radeon_vm_set_pages(rdev, ib, frag_end, addr, count,
+ RADEON_GPU_PAGE_SIZE, flags);
}
}
@@ -777,9 +810,6 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
unsigned count = 0;
uint64_t addr;
- start = start / RADEON_GPU_PAGE_SIZE;
- end = end / RADEON_GPU_PAGE_SIZE;
-
/* walk over the address space and update the page tables */
for (addr = start; addr < end; ) {
uint64_t pt_idx = addr >> radeon_vm_block_size;
@@ -842,55 +872,73 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
{
struct radeon_vm *vm = bo_va->vm;
struct radeon_ib ib;
- unsigned nptes, ndw;
+ unsigned nptes, ncmds, ndw;
uint64_t addr;
+ uint32_t flags;
int r;
-
- if (!bo_va->soffset) {
+ if (!bo_va->it.start) {
dev_err(rdev->dev, "bo %p don't has a mapping in vm %p\n",
bo_va->bo, vm);
return -EINVAL;
}
- if ((bo_va->valid && mem) || (!bo_va->valid && mem == NULL))
- return 0;
+ list_del_init(&bo_va->vm_status);
bo_va->flags &= ~RADEON_VM_PAGE_VALID;
bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM;
+ bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED;
if (mem) {
addr = mem->start << PAGE_SHIFT;
if (mem->mem_type != TTM_PL_SYSTEM) {
bo_va->flags |= RADEON_VM_PAGE_VALID;
- bo_va->valid = true;
}
if (mem->mem_type == TTM_PL_TT) {
bo_va->flags |= RADEON_VM_PAGE_SYSTEM;
+ if (!(bo_va->bo->flags & (RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC)))
+ bo_va->flags |= RADEON_VM_PAGE_SNOOPED;
+
} else {
addr += rdev->vm_manager.vram_base_offset;
}
} else {
addr = 0;
- bo_va->valid = false;
}
+ if (addr == bo_va->addr)
+ return 0;
+ bo_va->addr = addr;
+
trace_radeon_vm_bo_update(bo_va);
- nptes = (bo_va->eoffset - bo_va->soffset) / RADEON_GPU_PAGE_SIZE;
+ nptes = bo_va->it.last - bo_va->it.start + 1;
+
+ /* reserve space for one command every (1 << BLOCK_SIZE) entries
+ or 2k dwords (whatever is smaller) */
+ ncmds = (nptes >> min(radeon_vm_block_size, 11)) + 1;
/* padding, etc. */
ndw = 64;
- if (radeon_vm_block_size > 11)
- /* reserve space for one header for every 2k dwords */
- ndw += (nptes >> 11) * 4;
- else
- /* reserve space for one header for
- every (1 << BLOCK_SIZE) entries */
- ndw += (nptes >> radeon_vm_block_size) * 4;
+ flags = radeon_vm_page_flags(bo_va->flags);
+ if ((flags & R600_PTE_GART_MASK) == R600_PTE_GART_MASK) {
+ /* only copy commands needed */
+ ndw += ncmds * 7;
- /* reserve space for pte addresses */
- ndw += nptes * 2;
+ } else if (flags & R600_PTE_SYSTEM) {
+ /* header for write data commands */
+ ndw += ncmds * 4;
+
+ /* body of write data command */
+ ndw += nptes * 2;
+
+ } else {
+ /* set page commands needed */
+ ndw += ncmds * 10;
+
+ /* two extra commands for begin/end of fragment */
+ ndw += 2 * 10;
+ }
/* update too big for an IB */
if (ndw > 0xfffff)
@@ -901,8 +949,12 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
return r;
ib.length_dw = 0;
- radeon_vm_update_ptes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset,
- addr, radeon_vm_page_flags(bo_va->flags));
+ radeon_vm_update_ptes(rdev, vm, &ib, bo_va->it.start,
+ bo_va->it.last + 1, addr,
+ radeon_vm_page_flags(bo_va->flags));
+
+ radeon_asic_vm_pad_ib(rdev, &ib);
+ WARN_ON(ib.length_dw > ndw);
radeon_semaphore_sync_to(ib.semaphore, vm->fence);
r = radeon_ib_schedule(rdev, &ib, NULL);
@@ -936,8 +988,8 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
int r;
list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) {
- list_del(&bo_va->vm_status);
r = radeon_vm_bo_update(rdev, bo_va, NULL);
+ radeon_bo_unref(&bo_va->bo);
kfree(bo_va);
if (r)
return r;
@@ -947,6 +999,31 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
}
/**
+ * radeon_vm_clear_invalids - clear invalidated BOs in the PT
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ *
+ * Make sure all invalidated BOs are cleared in the PT.
+ * Returns 0 for success.
+ *
+ * PTs have to be reserved and mutex must be locked!
+ */
+int radeon_vm_clear_invalids(struct radeon_device *rdev,
+ struct radeon_vm *vm)
+{
+ struct radeon_bo_va *bo_va, *tmp;
+ int r;
+
+ list_for_each_entry_safe(bo_va, tmp, &vm->invalidated, vm_status) {
+ r = radeon_vm_bo_update(rdev, bo_va, NULL);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
+/**
* radeon_vm_bo_rmv - remove a bo to a specific vm
*
* @rdev: radeon_device pointer
@@ -964,10 +1041,11 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
list_del(&bo_va->bo_list);
mutex_lock(&vm->mutex);
- list_del(&bo_va->vm_list);
+ interval_tree_remove(&bo_va->it, &vm->va);
+ list_del(&bo_va->vm_status);
- if (bo_va->soffset) {
- bo_va->bo = NULL;
+ if (bo_va->addr) {
+ bo_va->bo = radeon_bo_ref(bo_va->bo);
list_add(&bo_va->vm_status, &vm->freed);
} else {
kfree(bo_va);
@@ -991,7 +1069,12 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
struct radeon_bo_va *bo_va;
list_for_each_entry(bo_va, &bo->va, bo_list) {
- bo_va->valid = false;
+ if (bo_va->addr) {
+ mutex_lock(&bo_va->vm->mutex);
+ list_del(&bo_va->vm_status);
+ list_add(&bo_va->vm_status, &bo_va->vm->invalidated);
+ mutex_unlock(&bo_va->vm->mutex);
+ }
}
}
@@ -1016,7 +1099,8 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
vm->last_flush = NULL;
vm->last_id_use = NULL;
mutex_init(&vm->mutex);
- INIT_LIST_HEAD(&vm->va);
+ vm->va = RB_ROOT;
+ INIT_LIST_HEAD(&vm->invalidated);
INIT_LIST_HEAD(&vm->freed);
pd_size = radeon_vm_directory_size(rdev);
@@ -1031,7 +1115,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
}
r = radeon_bo_create(rdev, pd_size, align, true,
- RADEON_GEM_DOMAIN_VRAM, NULL,
+ RADEON_GEM_DOMAIN_VRAM, 0, NULL,
&vm->page_directory);
if (r)
return r;
@@ -1060,11 +1144,11 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
struct radeon_bo_va *bo_va, *tmp;
int i, r;
- if (!list_empty(&vm->va)) {
+ if (!RB_EMPTY_ROOT(&vm->va)) {
dev_err(rdev->dev, "still active bo inside vm\n");
}
- list_for_each_entry_safe(bo_va, tmp, &vm->va, vm_list) {
- list_del_init(&bo_va->vm_list);
+ rbtree_postorder_for_each_entry_safe(bo_va, tmp, &vm->va, it.rb) {
+ interval_tree_remove(&bo_va->it, &vm->va);
r = radeon_bo_reserve(bo_va->bo, false);
if (!r) {
list_del_init(&bo_va->bo_list);
@@ -1072,8 +1156,10 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
kfree(bo_va);
}
}
- list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status)
+ list_for_each_entry_safe(bo_va, tmp, &vm->freed, vm_status) {
+ radeon_bo_unref(&bo_va->bo);
kfree(bo_va);
+ }
for (i = 0; i < radeon_vm_num_pdes(rdev); i++)
radeon_bo_unref(&vm->page_tables[i].bo);
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index a0f96decece3..6c1fc339d228 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -109,7 +109,6 @@ int rs400_gart_enable(struct radeon_device *rdev)
uint32_t size_reg;
uint32_t tmp;
- radeon_gart_restore(rdev);
tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
@@ -209,17 +208,24 @@ void rs400_gart_fini(struct radeon_device *rdev)
radeon_gart_table_ram_free(rdev);
}
+#define RS400_PTE_UNSNOOPED (1 << 0)
#define RS400_PTE_WRITEABLE (1 << 2)
#define RS400_PTE_READABLE (1 << 3)
-void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr)
+void rs400_gart_set_page(struct radeon_device *rdev, unsigned i,
+ uint64_t addr, uint32_t flags)
{
uint32_t entry;
u32 *gtt = rdev->gart.ptr;
entry = (lower_32_bits(addr) & PAGE_MASK) |
- ((upper_32_bits(addr) & 0xff) << 4) |
- RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
+ ((upper_32_bits(addr) & 0xff) << 4);
+ if (flags & RADEON_GART_PAGE_READ)
+ addr |= RS400_PTE_READABLE;
+ if (flags & RADEON_GART_PAGE_WRITE)
+ addr |= RS400_PTE_WRITEABLE;
+ if (!(flags & RADEON_GART_PAGE_SNOOP))
+ entry |= RS400_PTE_UNSNOOPED;
entry = cpu_to_le32(entry);
gtt[i] = entry;
}
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index d1a35cb1c91d..5f6db4629aaa 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -555,7 +555,6 @@ static int rs600_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Enable bus master */
tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
WREG32(RADEON_BUS_CNTL, tmp);
@@ -626,15 +625,21 @@ static void rs600_gart_fini(struct radeon_device *rdev)
radeon_gart_table_vram_free(rdev);
}
-void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, uint64_t addr)
+void rs600_gart_set_page(struct radeon_device *rdev, unsigned i,
+ uint64_t addr, uint32_t flags)
{
void __iomem *ptr = (void *)rdev->gart.ptr;
addr = addr & 0xFFFFFFFFFFFFF000ULL;
- if (addr == rdev->dummy_page.addr)
- addr |= R600_PTE_SYSTEM | R600_PTE_SNOOPED;
- else
- addr |= R600_PTE_GART;
+ addr |= R600_PTE_SYSTEM;
+ if (flags & RADEON_GART_PAGE_VALID)
+ addr |= R600_PTE_VALID;
+ if (flags & RADEON_GART_PAGE_READ)
+ addr |= R600_PTE_READABLE;
+ if (flags & RADEON_GART_PAGE_WRITE)
+ addr |= R600_PTE_WRITEABLE;
+ if (flags & RADEON_GART_PAGE_SNOOP)
+ addr |= R600_PTE_SNOOPED;
writeq(addr, ptr + (i * 8));
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index da8703d8d455..2983f17ea1b3 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -900,7 +900,6 @@ static int rv770_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup L2 cache */
WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 9e854fd016da..011779bd2b3d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -42,6 +42,14 @@ MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
+
+MODULE_FIRMWARE("radeon/tahiti_pfp.bin");
+MODULE_FIRMWARE("radeon/tahiti_me.bin");
+MODULE_FIRMWARE("radeon/tahiti_ce.bin");
+MODULE_FIRMWARE("radeon/tahiti_mc.bin");
+MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
+MODULE_FIRMWARE("radeon/tahiti_smc.bin");
+
MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
@@ -49,6 +57,14 @@ MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
+
+MODULE_FIRMWARE("radeon/pitcairn_pfp.bin");
+MODULE_FIRMWARE("radeon/pitcairn_me.bin");
+MODULE_FIRMWARE("radeon/pitcairn_ce.bin");
+MODULE_FIRMWARE("radeon/pitcairn_mc.bin");
+MODULE_FIRMWARE("radeon/pitcairn_rlc.bin");
+MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
+
MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
MODULE_FIRMWARE("radeon/VERDE_me.bin");
MODULE_FIRMWARE("radeon/VERDE_ce.bin");
@@ -56,6 +72,14 @@ MODULE_FIRMWARE("radeon/VERDE_mc.bin");
MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
MODULE_FIRMWARE("radeon/VERDE_smc.bin");
+
+MODULE_FIRMWARE("radeon/verde_pfp.bin");
+MODULE_FIRMWARE("radeon/verde_me.bin");
+MODULE_FIRMWARE("radeon/verde_ce.bin");
+MODULE_FIRMWARE("radeon/verde_mc.bin");
+MODULE_FIRMWARE("radeon/verde_rlc.bin");
+MODULE_FIRMWARE("radeon/verde_smc.bin");
+
MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
MODULE_FIRMWARE("radeon/OLAND_me.bin");
MODULE_FIRMWARE("radeon/OLAND_ce.bin");
@@ -63,6 +87,14 @@ MODULE_FIRMWARE("radeon/OLAND_mc.bin");
MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
MODULE_FIRMWARE("radeon/OLAND_smc.bin");
+
+MODULE_FIRMWARE("radeon/oland_pfp.bin");
+MODULE_FIRMWARE("radeon/oland_me.bin");
+MODULE_FIRMWARE("radeon/oland_ce.bin");
+MODULE_FIRMWARE("radeon/oland_mc.bin");
+MODULE_FIRMWARE("radeon/oland_rlc.bin");
+MODULE_FIRMWARE("radeon/oland_smc.bin");
+
MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
MODULE_FIRMWARE("radeon/HAINAN_me.bin");
MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
@@ -71,6 +103,13 @@ MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
+MODULE_FIRMWARE("radeon/hainan_pfp.bin");
+MODULE_FIRMWARE("radeon/hainan_me.bin");
+MODULE_FIRMWARE("radeon/hainan_ce.bin");
+MODULE_FIRMWARE("radeon/hainan_mc.bin");
+MODULE_FIRMWARE("radeon/hainan_rlc.bin");
+MODULE_FIRMWARE("radeon/hainan_smc.bin");
+
static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
static void si_pcie_gen3_enable(struct radeon_device *rdev);
static void si_program_aspm(struct radeon_device *rdev);
@@ -1470,38 +1509,54 @@ static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
/* ucode loading */
int si_mc_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
+ const __be32 *fw_data = NULL;
+ const __le32 *new_fw_data = NULL;
u32 running, blackout = 0;
- u32 *io_mc_regs;
+ u32 *io_mc_regs = NULL;
+ const __le32 *new_io_mc_regs = NULL;
int i, regs_size, ucode_size;
if (!rdev->mc_fw)
return -EINVAL;
- ucode_size = rdev->mc_fw->size / 4;
+ if (rdev->new_fw) {
+ const struct mc_firmware_header_v1_0 *hdr =
+ (const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
+
+ radeon_ucode_print_mc_hdr(&hdr->header);
+ regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
+ new_io_mc_regs = (const __le32 *)
+ (rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
+ ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ new_fw_data = (const __le32 *)
+ (rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ } else {
+ ucode_size = rdev->mc_fw->size / 4;
- switch (rdev->family) {
- case CHIP_TAHITI:
- io_mc_regs = (u32 *)&tahiti_io_mc_regs;
- regs_size = TAHITI_IO_MC_REGS_SIZE;
- break;
- case CHIP_PITCAIRN:
- io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
- regs_size = TAHITI_IO_MC_REGS_SIZE;
- break;
- case CHIP_VERDE:
- default:
- io_mc_regs = (u32 *)&verde_io_mc_regs;
- regs_size = TAHITI_IO_MC_REGS_SIZE;
- break;
- case CHIP_OLAND:
- io_mc_regs = (u32 *)&oland_io_mc_regs;
- regs_size = TAHITI_IO_MC_REGS_SIZE;
- break;
- case CHIP_HAINAN:
- io_mc_regs = (u32 *)&hainan_io_mc_regs;
- regs_size = TAHITI_IO_MC_REGS_SIZE;
- break;
+ switch (rdev->family) {
+ case CHIP_TAHITI:
+ io_mc_regs = (u32 *)&tahiti_io_mc_regs;
+ regs_size = TAHITI_IO_MC_REGS_SIZE;
+ break;
+ case CHIP_PITCAIRN:
+ io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
+ regs_size = TAHITI_IO_MC_REGS_SIZE;
+ break;
+ case CHIP_VERDE:
+ default:
+ io_mc_regs = (u32 *)&verde_io_mc_regs;
+ regs_size = TAHITI_IO_MC_REGS_SIZE;
+ break;
+ case CHIP_OLAND:
+ io_mc_regs = (u32 *)&oland_io_mc_regs;
+ regs_size = TAHITI_IO_MC_REGS_SIZE;
+ break;
+ case CHIP_HAINAN:
+ io_mc_regs = (u32 *)&hainan_io_mc_regs;
+ regs_size = TAHITI_IO_MC_REGS_SIZE;
+ break;
+ }
+ fw_data = (const __be32 *)rdev->mc_fw->data;
}
running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
@@ -1518,13 +1573,21 @@ int si_mc_load_microcode(struct radeon_device *rdev)
/* load mc io regs */
for (i = 0; i < regs_size; i++) {
- WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
- WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+ if (rdev->new_fw) {
+ WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
+ WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
+ } else {
+ WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
+ WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
+ }
}
/* load the MC ucode */
- fw_data = (const __be32 *)rdev->mc_fw->data;
- for (i = 0; i < ucode_size; i++)
- WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+ for (i = 0; i < ucode_size; i++) {
+ if (rdev->new_fw)
+ WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+ else
+ WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
+ }
/* put the engine back into the active state */
WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
@@ -1553,18 +1616,19 @@ int si_mc_load_microcode(struct radeon_device *rdev)
static int si_init_microcode(struct radeon_device *rdev)
{
const char *chip_name;
- const char *rlc_chip_name;
+ const char *new_chip_name;
size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
size_t smc_req_size, mc2_req_size;
char fw_name[30];
int err;
+ int new_fw = 0;
DRM_DEBUG("\n");
switch (rdev->family) {
case CHIP_TAHITI:
chip_name = "TAHITI";
- rlc_chip_name = "TAHITI";
+ new_chip_name = "tahiti";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1575,7 +1639,7 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_PITCAIRN:
chip_name = "PITCAIRN";
- rlc_chip_name = "PITCAIRN";
+ new_chip_name = "pitcairn";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1586,7 +1650,7 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_VERDE:
chip_name = "VERDE";
- rlc_chip_name = "VERDE";
+ new_chip_name = "verde";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1597,7 +1661,7 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_OLAND:
chip_name = "OLAND";
- rlc_chip_name = "OLAND";
+ new_chip_name = "oland";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1607,7 +1671,7 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_HAINAN:
chip_name = "HAINAN";
- rlc_chip_name = "HAINAN";
+ new_chip_name = "hainan";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
@@ -1618,86 +1682,178 @@ static int si_init_microcode(struct radeon_device *rdev)
default: BUG();
}
- DRM_INFO("Loading %s Microcode\n", chip_name);
+ DRM_INFO("Loading %s Microcode\n", new_chip_name);
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->pfp_fw->size != pfp_req_size) {
- printk(KERN_ERR
- "si_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->pfp_fw->size, fw_name);
- err = -EINVAL;
- goto out;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
+ err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->pfp_fw->size != pfp_req_size) {
+ printk(KERN_ERR
+ "si_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->pfp_fw->size, fw_name);
+ err = -EINVAL;
+ goto out;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->pfp_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", new_chip_name);
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->me_fw->size != me_req_size) {
- printk(KERN_ERR
- "si_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->me_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
+ err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->me_fw->size != me_req_size) {
+ printk(KERN_ERR
+ "si_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->me_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->me_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", new_chip_name);
err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->ce_fw->size != ce_req_size) {
- printk(KERN_ERR
- "si_cp: Bogus length %zu in firmware \"%s\"\n",
- rdev->ce_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
+ err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->ce_fw->size != ce_req_size) {
+ printk(KERN_ERR
+ "si_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->ce_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->ce_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", new_chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
- if (err)
- goto out;
- if (rdev->rlc_fw->size != rlc_req_size) {
- printk(KERN_ERR
- "si_rlc: Bogus length %zu in firmware \"%s\"\n",
- rdev->rlc_fw->size, fw_name);
- err = -EINVAL;
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
+ err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ if (rdev->rlc_fw->size != rlc_req_size) {
+ printk(KERN_ERR
+ "si_rlc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->rlc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->rlc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) {
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
- if (err)
+ if (err) {
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+ err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+ if (err)
+ goto out;
+ }
+ if ((rdev->mc_fw->size != mc_req_size) &&
+ (rdev->mc_fw->size != mc2_req_size)) {
+ printk(KERN_ERR
+ "si_mc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->mc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
+ } else {
+ err = radeon_ucode_validate(rdev->mc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
goto out;
+ } else {
+ new_fw++;
+ }
}
- if ((rdev->mc_fw->size != mc_req_size) &&
- (rdev->mc_fw->size != mc2_req_size)) {
- printk(KERN_ERR
- "si_mc: Bogus length %zu in firmware \"%s\"\n",
- rdev->mc_fw->size, fw_name);
- err = -EINVAL;
- }
- DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) {
- printk(KERN_ERR
- "smc: error loading firmware \"%s\"\n",
- fw_name);
- release_firmware(rdev->smc_fw);
- rdev->smc_fw = NULL;
- err = 0;
- } else if (rdev->smc_fw->size != smc_req_size) {
- printk(KERN_ERR
- "si_smc: Bogus length %zu in firmware \"%s\"\n",
- rdev->smc_fw->size, fw_name);
- err = -EINVAL;
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
+ err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
+ if (err) {
+ printk(KERN_ERR
+ "smc: error loading firmware \"%s\"\n",
+ fw_name);
+ release_firmware(rdev->smc_fw);
+ rdev->smc_fw = NULL;
+ err = 0;
+ } else if (rdev->smc_fw->size != smc_req_size) {
+ printk(KERN_ERR
+ "si_smc: Bogus length %zu in firmware \"%s\"\n",
+ rdev->smc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ } else {
+ err = radeon_ucode_validate(rdev->smc_fw);
+ if (err) {
+ printk(KERN_ERR
+ "si_cp: validation failed for firmware \"%s\"\n",
+ fw_name);
+ goto out;
+ } else {
+ new_fw++;
+ }
}
+ if (new_fw == 0) {
+ rdev->new_fw = false;
+ } else if (new_fw < 6) {
+ printk(KERN_ERR "si_fw: mixing new and old firmware!\n");
+ err = -EINVAL;
+ } else {
+ rdev->new_fw = true;
+ }
out:
if (err) {
if (err != -EINVAL)
@@ -3282,34 +3438,77 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable)
static int si_cp_load_microcode(struct radeon_device *rdev)
{
- const __be32 *fw_data;
int i;
- if (!rdev->me_fw || !rdev->pfp_fw)
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
return -EINVAL;
si_cp_enable(rdev, false);
- /* PFP */
- fw_data = (const __be32 *)rdev->pfp_fw->data;
- WREG32(CP_PFP_UCODE_ADDR, 0);
- for (i = 0; i < SI_PFP_UCODE_SIZE; i++)
- WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_PFP_UCODE_ADDR, 0);
-
- /* CE */
- fw_data = (const __be32 *)rdev->ce_fw->data;
- WREG32(CP_CE_UCODE_ADDR, 0);
- for (i = 0; i < SI_CE_UCODE_SIZE; i++)
- WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_CE_UCODE_ADDR, 0);
-
- /* ME */
- fw_data = (const __be32 *)rdev->me_fw->data;
- WREG32(CP_ME_RAM_WADDR, 0);
- for (i = 0; i < SI_PM4_UCODE_SIZE; i++)
- WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
- WREG32(CP_ME_RAM_WADDR, 0);
+ if (rdev->new_fw) {
+ const struct gfx_firmware_header_v1_0 *pfp_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
+ const struct gfx_firmware_header_v1_0 *ce_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
+ const struct gfx_firmware_header_v1_0 *me_hdr =
+ (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
+ const __le32 *fw_data;
+ u32 fw_size;
+
+ radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
+ radeon_ucode_print_gfx_hdr(&ce_hdr->header);
+ radeon_ucode_print_gfx_hdr(&me_hdr->header);
+
+ /* PFP */
+ fw_data = (const __le32 *)
+ (rdev->pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+
+ /* CE */
+ fw_data = (const __le32 *)
+ (rdev->ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_CE_UCODE_ADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_CE_UCODE_ADDR, 0);
+
+ /* ME */
+ fw_data = (const __be32 *)
+ (rdev->me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
+ fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
+ WREG32(CP_ME_RAM_WADDR, 0);
+ for (i = 0; i < fw_size; i++)
+ WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+ WREG32(CP_ME_RAM_WADDR, 0);
+ } else {
+ const __be32 *fw_data;
+
+ /* PFP */
+ fw_data = (const __be32 *)rdev->pfp_fw->data;
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < SI_PFP_UCODE_SIZE; i++)
+ WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_PFP_UCODE_ADDR, 0);
+
+ /* CE */
+ fw_data = (const __be32 *)rdev->ce_fw->data;
+ WREG32(CP_CE_UCODE_ADDR, 0);
+ for (i = 0; i < SI_CE_UCODE_SIZE; i++)
+ WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_CE_UCODE_ADDR, 0);
+
+ /* ME */
+ fw_data = (const __be32 *)rdev->me_fw->data;
+ WREG32(CP_ME_RAM_WADDR, 0);
+ for (i = 0; i < SI_PM4_UCODE_SIZE; i++)
+ WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+ WREG32(CP_ME_RAM_WADDR, 0);
+ }
WREG32(CP_PFP_UCODE_ADDR, 0);
WREG32(CP_CE_UCODE_ADDR, 0);
@@ -4048,7 +4247,6 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
- radeon_gart_restore(rdev);
/* Setup TLB control */
WREG32(MC_VM_MX_L1_TLB_CNTL,
(0xA << 7) |
@@ -4815,7 +5013,7 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
/* write new base address */
radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
WRITE_DATA_DST_SEL(0)));
if (vm->id < 8) {
@@ -5592,7 +5790,6 @@ static void si_enable_lbpw(struct radeon_device *rdev, bool enable)
static int si_rlc_resume(struct radeon_device *rdev)
{
u32 i;
- const __be32 *fw_data;
if (!rdev->rlc_fw)
return -EINVAL;
@@ -5615,10 +5812,26 @@ static int si_rlc_resume(struct radeon_device *rdev)
WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0);
- fw_data = (const __be32 *)rdev->rlc_fw->data;
- for (i = 0; i < SI_RLC_UCODE_SIZE; i++) {
- WREG32(RLC_UCODE_ADDR, i);
- WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+ if (rdev->new_fw) {
+ const struct rlc_firmware_header_v1_0 *hdr =
+ (const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
+ u32 fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
+ const __le32 *fw_data = (const __le32 *)
+ (rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+
+ radeon_ucode_print_rlc_hdr(&hdr->header);
+
+ for (i = 0; i < fw_size; i++) {
+ WREG32(RLC_UCODE_ADDR, i);
+ WREG32(RLC_UCODE_DATA, le32_to_cpup(fw_data++));
+ }
+ } else {
+ const __be32 *fw_data =
+ (const __be32 *)rdev->rlc_fw->data;
+ for (i = 0; i < SI_RLC_UCODE_SIZE; i++) {
+ WREG32(RLC_UCODE_ADDR, i);
+ WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+ }
}
WREG32(RLC_UCODE_ADDR, 0);
@@ -6318,7 +6531,8 @@ restart_ih:
case 16: /* D5 page flip */
case 18: /* D6 page flip */
DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
- radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+ if (radeon_use_pflipirq > 0)
+ radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
break;
case 42: /* HPD hotplug */
switch (src_data) {
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
index e24c94b6d14d..716505129450 100644
--- a/drivers/gpu/drm/radeon/si_dma.c
+++ b/drivers/gpu/drm/radeon/si_dma.c
@@ -56,7 +56,41 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
}
/**
- * si_dma_vm_set_page - update the page tables using the DMA
+ * si_dma_vm_copy_pages - update PTEs by copying them from the GART
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @src: src addr where to copy from
+ * @count: number of page entries to update
+ *
+ * Update PTEs by copying them from the GART using the DMA (SI).
+ */
+void si_dma_vm_copy_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe, uint64_t src,
+ unsigned count)
+{
+ while (count) {
+ unsigned bytes = count * 8;
+ if (bytes > 0xFFFF8)
+ bytes = 0xFFFF8;
+
+ ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
+ 1, 0, 0, bytes);
+ ib->ptr[ib->length_dw++] = lower_32_bits(pe);
+ ib->ptr[ib->length_dw++] = lower_32_bits(src);
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
+
+ pe += bytes;
+ src += bytes;
+ count -= bytes / 8;
+ }
+}
+
+/**
+ * si_dma_vm_write_pages - update PTEs by writing them manually
*
* @rdev: radeon_device pointer
* @ib: indirect buffer to fill with commands
@@ -66,83 +100,89 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
* @incr: increase next addr by incr bytes
* @flags: access flags
*
- * Update the page tables using the DMA (SI).
+ * Update PTEs by writing them manually using the DMA (SI).
*/
-void si_dma_vm_set_page(struct radeon_device *rdev,
- struct radeon_ib *ib,
- uint64_t pe,
- uint64_t addr, unsigned count,
- uint32_t incr, uint32_t flags)
+void si_dma_vm_write_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
{
uint64_t value;
unsigned ndw;
- trace_radeon_vm_set_page(pe, addr, count, incr, flags);
-
- if (flags == R600_PTE_GART) {
- uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8;
- while (count) {
- unsigned bytes = count * 8;
- if (bytes > 0xFFFF8)
- bytes = 0xFFFF8;
-
- ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY,
- 1, 0, 0, bytes);
- ib->ptr[ib->length_dw++] = lower_32_bits(pe);
- ib->ptr[ib->length_dw++] = lower_32_bits(src);
- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
- ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff;
-
- pe += bytes;
- src += bytes;
- count -= bytes / 8;
- }
- } else if (flags & R600_PTE_SYSTEM) {
- while (count) {
- ndw = count * 2;
- if (ndw > 0xFFFFE)
- ndw = 0xFFFFE;
-
- /* for non-physically contiguous pages (system) */
- ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw);
- ib->ptr[ib->length_dw++] = pe;
- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
- for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ /* for non-physically contiguous pages (system) */
+ ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw);
+ ib->ptr[ib->length_dw++] = pe;
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+ if (flags & R600_PTE_SYSTEM) {
value = radeon_vm_map_gart(rdev, addr);
value &= 0xFFFFFFFFFFFFF000ULL;
- addr += incr;
- value |= flags;
- ib->ptr[ib->length_dw++] = value;
- ib->ptr[ib->length_dw++] = upper_32_bits(value);
- }
- }
- } else {
- while (count) {
- ndw = count * 2;
- if (ndw > 0xFFFFE)
- ndw = 0xFFFFE;
-
- if (flags & R600_PTE_VALID)
+ } else if (flags & R600_PTE_VALID) {
value = addr;
- else
+ } else {
value = 0;
- /* for physically contiguous pages (vram) */
- ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
- ib->ptr[ib->length_dw++] = pe; /* dst addr */
- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
- ib->ptr[ib->length_dw++] = flags; /* mask */
- ib->ptr[ib->length_dw++] = 0;
- ib->ptr[ib->length_dw++] = value; /* value */
+ }
+ addr += incr;
+ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
ib->ptr[ib->length_dw++] = upper_32_bits(value);
- ib->ptr[ib->length_dw++] = incr; /* increment size */
- ib->ptr[ib->length_dw++] = 0;
- pe += ndw * 4;
- addr += (ndw / 2) * incr;
- count -= ndw / 2;
}
}
- while (ib->length_dw & 0x7)
- ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0);
+}
+
+/**
+ * si_dma_vm_set_pages - update the page tables using the DMA
+ *
+ * @rdev: radeon_device pointer
+ * @ib: indirect buffer to fill with commands
+ * @pe: addr of the page entry
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+ * @flags: access flags
+ *
+ * Update the page tables using the DMA (SI).
+ */
+void si_dma_vm_set_pages(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+{
+ uint64_t value;
+ unsigned ndw;
+
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+
+ /* for physically contiguous pages (vram) */
+ ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ ib->ptr[ib->length_dw++] = incr; /* increment size */
+ ib->ptr[ib->length_dw++] = 0;
+ pe += ndw * 4;
+ addr += (ndw / 2) * incr;
+ count -= ndw / 2;
+ }
}
void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 58918868f894..70e61ffeace2 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -3812,6 +3812,27 @@ void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
voltage_table->count = max_voltage_steps;
}
+static int si_get_svi2_voltage_table(struct radeon_device *rdev,
+ struct radeon_clock_voltage_dependency_table *voltage_dependency_table,
+ struct atom_voltage_table *voltage_table)
+{
+ u32 i;
+
+ if (voltage_dependency_table == NULL)
+ return -EINVAL;
+
+ voltage_table->mask_low = 0;
+ voltage_table->phase_delay = 0;
+
+ voltage_table->count = voltage_dependency_table->count;
+ for (i = 0; i < voltage_table->count; i++) {
+ voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
+ voltage_table->entries[i].smio_low = 0;
+ }
+
+ return 0;
+}
+
static int si_construct_voltage_tables(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
@@ -3819,15 +3840,25 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
struct si_power_info *si_pi = si_get_pi(rdev);
int ret;
- ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
- VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
- if (ret)
- return ret;
+ if (pi->voltage_control) {
+ ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
+ VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
+ if (ret)
+ return ret;
- if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
- si_trim_voltage_table_to_fit_state_table(rdev,
- SISLANDS_MAX_NO_VREG_STEPS,
- &eg_pi->vddc_voltage_table);
+ if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
+ si_trim_voltage_table_to_fit_state_table(rdev,
+ SISLANDS_MAX_NO_VREG_STEPS,
+ &eg_pi->vddc_voltage_table);
+ } else if (si_pi->voltage_control_svi2) {
+ ret = si_get_svi2_voltage_table(rdev,
+ &rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+ &eg_pi->vddc_voltage_table);
+ if (ret)
+ return ret;
+ } else {
+ return -EINVAL;
+ }
if (eg_pi->vddci_control) {
ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI,
@@ -3840,6 +3871,13 @@ static int si_construct_voltage_tables(struct radeon_device *rdev)
SISLANDS_MAX_NO_VREG_STEPS,
&eg_pi->vddci_voltage_table);
}
+ if (si_pi->vddci_control_svi2) {
+ ret = si_get_svi2_voltage_table(rdev,
+ &rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+ &eg_pi->vddci_voltage_table);
+ if (ret)
+ return ret;
+ }
if (pi->mvdd_control) {
ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC,
@@ -3893,46 +3931,55 @@ static int si_populate_smc_voltage_tables(struct radeon_device *rdev,
struct si_power_info *si_pi = si_get_pi(rdev);
u8 i;
- if (eg_pi->vddc_voltage_table.count) {
- si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
- table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
- cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
-
- for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
- if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
- table->maxVDDCIndexInPPTable = i;
- break;
+ if (si_pi->voltage_control_svi2) {
+ si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
+ si_pi->svc_gpio_id);
+ si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
+ si_pi->svd_gpio_id);
+ si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
+ 2);
+ } else {
+ if (eg_pi->vddc_voltage_table.count) {
+ si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
+ table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
+ cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
+
+ for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
+ if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
+ table->maxVDDCIndexInPPTable = i;
+ break;
+ }
}
}
- }
- if (eg_pi->vddci_voltage_table.count) {
- si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
+ if (eg_pi->vddci_voltage_table.count) {
+ si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
- table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
- cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
- }
+ table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
+ cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
+ }
- if (si_pi->mvdd_voltage_table.count) {
- si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
+ if (si_pi->mvdd_voltage_table.count) {
+ si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
- table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
- cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
- }
+ table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
+ cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
+ }
- if (si_pi->vddc_phase_shed_control) {
- if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
- &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
- si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
+ if (si_pi->vddc_phase_shed_control) {
+ if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
+ &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
+ si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
- table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
- cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
+ table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
+ cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
- si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
- (u32)si_pi->vddc_phase_shed_table.phase_delay);
- } else {
- si_pi->vddc_phase_shed_control = false;
+ si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
+ (u32)si_pi->vddc_phase_shed_table.phase_delay);
+ } else {
+ si_pi->vddc_phase_shed_control = false;
+ }
}
}
@@ -5798,16 +5845,17 @@ int si_dpm_enable(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+ struct si_power_info *si_pi = si_get_pi(rdev);
struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
int ret;
if (si_is_smc_running(rdev))
return -EINVAL;
- if (pi->voltage_control)
+ if (pi->voltage_control || si_pi->voltage_control_svi2)
si_enable_voltage_control(rdev, true);
if (pi->mvdd_control)
si_get_mvdd_configuration(rdev);
- if (pi->voltage_control) {
+ if (pi->voltage_control || si_pi->voltage_control_svi2) {
ret = si_construct_voltage_tables(rdev);
if (ret) {
DRM_ERROR("si_construct_voltage_tables failed\n");
@@ -6406,16 +6454,32 @@ int si_dpm_init(struct radeon_device *rdev)
ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
pi->voltage_control =
- radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_GPIO_LUT);
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+ VOLTAGE_OBJ_GPIO_LUT);
+ if (!pi->voltage_control) {
+ si_pi->voltage_control_svi2 =
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+ VOLTAGE_OBJ_SVID2);
+ if (si_pi->voltage_control_svi2)
+ radeon_atom_get_svi2_info(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+ &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
+ }
pi->mvdd_control =
- radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, VOLTAGE_OBJ_GPIO_LUT);
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
+ VOLTAGE_OBJ_GPIO_LUT);
eg_pi->vddci_control =
- radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, VOLTAGE_OBJ_GPIO_LUT);
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
+ VOLTAGE_OBJ_GPIO_LUT);
+ if (!eg_pi->vddci_control)
+ si_pi->vddci_control_svi2 =
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
+ VOLTAGE_OBJ_SVID2);
si_pi->vddc_phase_shed_control =
- radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, VOLTAGE_OBJ_PHASE_LUT);
+ radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
+ VOLTAGE_OBJ_PHASE_LUT);
rv770_get_engine_memory_ss(rdev);
diff --git a/drivers/gpu/drm/radeon/si_dpm.h b/drivers/gpu/drm/radeon/si_dpm.h
index 4ce5032cdf49..8b5c06a0832d 100644
--- a/drivers/gpu/drm/radeon/si_dpm.h
+++ b/drivers/gpu/drm/radeon/si_dpm.h
@@ -170,6 +170,8 @@ struct si_power_info {
bool vddc_phase_shed_control;
bool pspp_notify_required;
bool sclk_deep_sleep_above_low;
+ bool voltage_control_svi2;
+ bool vddci_control_svi2;
/* smc offsets */
u32 sram_end;
u32 state_table_start;
@@ -192,6 +194,9 @@ struct si_power_info {
SMC_SIslands_MCRegisters smc_mc_reg_table;
SISLANDS_SMC_STATETABLE smc_statetable;
PP_SIslands_PAPMParameters papm_parm;
+ /* SVI2 */
+ u8 svd_gpio_id;
+ u8 svc_gpio_id;
};
#define SISLANDS_INITIAL_STATE_ARB_INDEX 0
diff --git a/drivers/gpu/drm/radeon/si_smc.c b/drivers/gpu/drm/radeon/si_smc.c
index e80efcf0c230..73dbc79c959d 100644
--- a/drivers/gpu/drm/radeon/si_smc.c
+++ b/drivers/gpu/drm/radeon/si_smc.c
@@ -219,36 +219,48 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
if (!rdev->smc_fw)
return -EINVAL;
- switch (rdev->family) {
- case CHIP_TAHITI:
- ucode_start_address = TAHITI_SMC_UCODE_START;
- ucode_size = TAHITI_SMC_UCODE_SIZE;
- break;
- case CHIP_PITCAIRN:
- ucode_start_address = PITCAIRN_SMC_UCODE_START;
- ucode_size = PITCAIRN_SMC_UCODE_SIZE;
- break;
- case CHIP_VERDE:
- ucode_start_address = VERDE_SMC_UCODE_START;
- ucode_size = VERDE_SMC_UCODE_SIZE;
- break;
- case CHIP_OLAND:
- ucode_start_address = OLAND_SMC_UCODE_START;
- ucode_size = OLAND_SMC_UCODE_SIZE;
- break;
- case CHIP_HAINAN:
- ucode_start_address = HAINAN_SMC_UCODE_START;
- ucode_size = HAINAN_SMC_UCODE_SIZE;
- break;
- default:
- DRM_ERROR("unknown asic in smc ucode loader\n");
- BUG();
+ if (rdev->new_fw) {
+ const struct smc_firmware_header_v1_0 *hdr =
+ (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
+
+ radeon_ucode_print_smc_hdr(&hdr->header);
+
+ ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
+ ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
+ src = (const u8 *)
+ (rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
+ } else {
+ switch (rdev->family) {
+ case CHIP_TAHITI:
+ ucode_start_address = TAHITI_SMC_UCODE_START;
+ ucode_size = TAHITI_SMC_UCODE_SIZE;
+ break;
+ case CHIP_PITCAIRN:
+ ucode_start_address = PITCAIRN_SMC_UCODE_START;
+ ucode_size = PITCAIRN_SMC_UCODE_SIZE;
+ break;
+ case CHIP_VERDE:
+ ucode_start_address = VERDE_SMC_UCODE_START;
+ ucode_size = VERDE_SMC_UCODE_SIZE;
+ break;
+ case CHIP_OLAND:
+ ucode_start_address = OLAND_SMC_UCODE_START;
+ ucode_size = OLAND_SMC_UCODE_SIZE;
+ break;
+ case CHIP_HAINAN:
+ ucode_start_address = HAINAN_SMC_UCODE_START;
+ ucode_size = HAINAN_SMC_UCODE_SIZE;
+ break;
+ default:
+ DRM_ERROR("unknown asic in smc ucode loader\n");
+ BUG();
+ }
+ src = (const u8 *)rdev->smc_fw->data;
}
if (ucode_size & 3)
return -EINVAL;
- src = (const u8 *)rdev->smc_fw->data;
spin_lock_irqsave(&rdev->smc_idx_lock, flags);
WREG32(SMC_IND_INDEX_0, ucode_start_address);
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h
index 10e945a49479..623a0b1e2d9d 100644
--- a/drivers/gpu/drm/radeon/sislands_smc.h
+++ b/drivers/gpu/drm/radeon/sislands_smc.h
@@ -241,6 +241,9 @@ typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE;
#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4
#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC
#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100
+#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118
+#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c
+#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 792fd1d20e86..fda64b7b73e8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -187,7 +187,7 @@ static struct drm_driver rcar_du_driver = {
* Power management
*/
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
static int rcar_du_pm_suspend(struct device *dev)
{
struct rcar_du_device *rcdu = dev_get_drvdata(dev);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index a87edfac111f..76026104d000 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -135,7 +135,9 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
{
struct rcar_du_device *rcdu = dev->dev_private;
const struct rcar_du_format_info *format;
+ unsigned int max_pitch;
unsigned int align;
+ unsigned int bpp;
format = rcar_du_format_info(mode_cmd->pixel_format);
if (format == NULL) {
@@ -144,13 +146,20 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-EINVAL);
}
+ /*
+ * The pitch and alignment constraints are expressed in pixels on the
+ * hardware side and in bytes in the DRM API.
+ */
+ bpp = format->planes == 2 ? 1 : format->bpp / 8;
+ max_pitch = 4096 * bpp;
+
if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
align = 128;
else
- align = 16 * format->bpp / 8;
+ align = 16 * bpp;
if (mode_cmd->pitches[0] & (align - 1) ||
- mode_cmd->pitches[0] >= 8192) {
+ mode_cmd->pitches[0] >= max_pitch) {
dev_dbg(dev->dev, "invalid pitch value %u\n",
mode_cmd->pitches[0]);
return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 289048d1c7b2..21426bd234eb 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -64,7 +64,7 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
{
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
@@ -105,7 +105,7 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_sysfs_connector_add(connector);
+ ret = drm_connector_register(connector);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index ccfe64c7188f..8af3944d31b9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -32,7 +32,7 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
{
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
@@ -70,7 +70,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_sysfs_connector_add(connector);
+ ret = drm_connector_register(connector);
if (ret < 0)
return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index faf176b2daf9..47875de89010 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -692,7 +692,7 @@ static void shmob_drm_connector_destroy(struct drm_connector *connector)
struct shmob_drm_connector *scon = to_shmob_connector(connector);
shmob_drm_backlight_exit(scon);
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
@@ -726,7 +726,7 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_sysfs_connector_add(connector);
+ ret = drm_connector_register(connector);
if (ret < 0)
goto err_cleanup;
@@ -749,7 +749,7 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev,
err_backlight:
shmob_drm_backlight_exit(&sdev->connector);
err_sysfs:
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
err_cleanup:
drm_connector_cleanup(connector);
return ret;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
index 82c84c7fd4f6..ff4ba483b602 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -297,7 +297,7 @@ static struct drm_driver shmob_drm_driver = {
* Power management
*/
-#if CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
static int shmob_drm_pm_suspend(struct device *dev)
{
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
new file mode 100644
index 000000000000..2d9d4252d598
--- /dev/null
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -0,0 +1,14 @@
+config DRM_STI
+ tristate "DRM Support for STMicroelectronics SoC stiH41x Series"
+ depends on DRM && (SOC_STIH415 || SOC_STIH416 || ARCH_MULTIPLATFORM)
+ select DRM_KMS_HELPER
+ select DRM_GEM_CMA_HELPER
+ select DRM_KMS_CMA_HELPER
+ help
+ Choose this option to enable DRM on STM stiH41x chipset
+
+config DRM_STI_FBDEV
+ bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
+ depends on DRM_STI
+ help
+ Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile
new file mode 100644
index 000000000000..04ac2ceef27f
--- /dev/null
+++ b/drivers/gpu/drm/sti/Makefile
@@ -0,0 +1,21 @@
+sticompositor-y := \
+ sti_layer.o \
+ sti_mixer.o \
+ sti_gdp.o \
+ sti_vid.o \
+ sti_compositor.o \
+ sti_drm_crtc.o \
+ sti_drm_plane.o
+
+stihdmi-y := sti_hdmi.o \
+ sti_hdmi_tx3g0c55phy.o \
+ sti_hdmi_tx3g4c28phy.o \
+
+obj-$(CONFIG_DRM_STI) = \
+ sti_vtg.o \
+ sti_vtac.o \
+ stihdmi.o \
+ sti_hda.o \
+ sti_tvout.o \
+ sticompositor.o \
+ sti_drm_drv.o \ No newline at end of file
diff --git a/drivers/gpu/drm/sti/NOTES b/drivers/gpu/drm/sti/NOTES
new file mode 100644
index 000000000000..57e257969198
--- /dev/null
+++ b/drivers/gpu/drm/sti/NOTES
@@ -0,0 +1,58 @@
+1. stiH display hardware IP
+---------------------------
+The STMicroelectronics stiH SoCs use a common chain of HW display IP blocks:
+- The High Quality Video Display Processor (HQVDP) gets video frames from a
+ video decoder and does high quality video processing, including scaling.
+
+- The Compositor is a multiplane, dual-mixer (Main & Aux) digital processor. It
+ has several inputs:
+ - The graphics planes are internally processed by the Generic Display
+ Pipeline (GDP).
+ - The video plug (VID) connects to the HQVDP output.
+ - The cursor handles ... a cursor.
+- The TV OUT pre-formats (convert, clip, round) the compositor output data
+- The HDMI / DVO / HD Analog / SD analog IP builds the video signals
+ - DVO (Digital Video Output) handles a 24bits parallel signal
+ - The HD analog signal is typically driven by a YCbCr cable, supporting up to
+ 1080i mode.
+ - The SD analog signal is typically used for legacy TV
+- The VTG (Video Timing Generators) build Vsync signals used by the other HW IP
+Note that some stiH drivers support only a subset of thee HW IP.
+
+ .-------------. .-----------. .-----------.
+GPU >-------------+GDP Main | | +---+ HDMI +--> HDMI
+GPU >-------------+GDP mixer+---+ | :===========:
+GPU >-------------+Cursor | | +---+ DVO +--> 24b//
+ ------- | COMPOSITOR | | TV OUT | :===========:
+ | | | | | +---+ HD analog +--> YCbCr
+Vid >--+ HQVDP +--+VID Aux +---+ | :===========:
+dec | | | mixer| | +---+ SD analog +--> CVBS
+ '-------' '-------------' '-----------' '-----------'
+ .-----------.
+ | main+--> Vsync
+ | VTG |
+ | aux+--> Vsync
+ '-----------'
+
+2. DRM / HW mapping
+-------------------
+These IP are mapped to the DRM objects as following:
+- The CRTCs are mapped to the Compositor Main and Aux Mixers
+- The Framebuffers and planes are mapped to the Compositor GDP (non video
+ buffers) and to HQVDP+VID (video buffers)
+- The Cursor is mapped to the Compositor Cursor
+- The Encoders are mapped to the TVOut
+- The Bridges/Connectors are mapped to the HDMI / DVO / HD Analog / SD analog
+
+FB & planes Cursor CRTC Encoders Bridges/Connectors
+ | | | | |
+ | | | | |
+ | .-------------. | .-----------. .-----------. |
+ +------------> |GDP | Main | | | +-> | | HDMI | <-+
+ +------------> |GDP v mixer|<+ | | | :===========: |
+ | |Cursor | | | +-> | | DVO | <-+
+ | ------- | COMPOSITOR | | |TV OUT | | :===========: |
+ | | | | | | | +-> | | HD analog | <-+
+ +-> | HQVDP | |VID Aux |<+ | | | :===========: |
+ | | | mixer| | +-> | | SD analog | <-+
+ '-------' '-------------' '-----------' '-----------'
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
new file mode 100644
index 000000000000..390d93e9a06c
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+
+#include "sti_compositor.h"
+#include "sti_drm_crtc.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_plane.h"
+#include "sti_gdp.h"
+#include "sti_vtg.h"
+
+/*
+ * stiH407 compositor properties
+ */
+struct sti_compositor_data stih407_compositor_data = {
+ .nb_subdev = 6,
+ .subdev_desc = {
+ {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
+ {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
+ {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
+ {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
+ {STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
+ {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
+ },
+};
+
+/*
+ * stiH416 compositor properties
+ * Note:
+ * on stih416 MIXER_AUX has a different base address from MIXER_MAIN
+ * Moreover, GDPx is different for Main and Aux Mixer. So this subdev map does
+ * not fit for stiH416 if we want to enable the MIXER_AUX.
+ */
+struct sti_compositor_data stih416_compositor_data = {
+ .nb_subdev = 3,
+ .subdev_desc = {
+ {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
+ {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
+ {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
+ },
+};
+
+static int sti_compositor_init_subdev(struct sti_compositor *compo,
+ struct sti_compositor_subdev_descriptor *desc,
+ unsigned int array_size)
+{
+ unsigned int i, mixer_id = 0, layer_id = 0;
+
+ for (i = 0; i < array_size; i++) {
+ switch (desc[i].type) {
+ case STI_MIXER_MAIN_SUBDEV:
+ case STI_MIXER_AUX_SUBDEV:
+ compo->mixer[mixer_id++] =
+ sti_mixer_create(compo->dev, desc[i].id,
+ compo->regs + desc[i].offset);
+ break;
+ case STI_GPD_SUBDEV:
+ case STI_VID_SUBDEV:
+ compo->layer[layer_id++] =
+ sti_layer_create(compo->dev, desc[i].id,
+ compo->regs + desc[i].offset);
+ break;
+ /* case STI_CURSOR_SUBDEV : TODO */
+ default:
+ DRM_ERROR("Unknow subdev compoment type\n");
+ return 1;
+ }
+
+ }
+ compo->nb_mixers = mixer_id;
+ compo->nb_layers = layer_id;
+
+ return 0;
+}
+
+static int sti_compositor_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = data;
+ unsigned int i, crtc = 0, plane = 0;
+ struct sti_drm_private *dev_priv = drm_dev->dev_private;
+ struct drm_plane *cursor = NULL;
+ struct drm_plane *primary = NULL;
+
+ dev_priv->compo = compo;
+
+ for (i = 0; i < compo->nb_layers; i++) {
+ if (compo->layer[i]) {
+ enum sti_layer_desc desc = compo->layer[i]->desc;
+ enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
+ enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
+
+ if (compo->mixer[crtc])
+ plane_type = DRM_PLANE_TYPE_PRIMARY;
+
+ switch (type) {
+ case STI_CUR:
+ cursor = sti_drm_plane_init(drm_dev,
+ compo->layer[i],
+ (1 << crtc) - 1,
+ DRM_PLANE_TYPE_CURSOR);
+ break;
+ case STI_GDP:
+ case STI_VID:
+ primary = sti_drm_plane_init(drm_dev,
+ compo->layer[i],
+ (1 << crtc) - 1, plane_type);
+ plane++;
+ break;
+ case STI_BCK:
+ break;
+ }
+
+ /* The first planes are reserved for primary planes*/
+ if (compo->mixer[crtc]) {
+ sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
+ primary, cursor);
+ crtc++;
+ cursor = NULL;
+ }
+ }
+ }
+
+ drm_vblank_init(drm_dev, crtc);
+ /* Allow usage of vblank without having to call drm_irq_install */
+ drm_dev->irq_enabled = 1;
+
+ DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
+ crtc, plane);
+ DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");
+
+ return 0;
+}
+
+static void sti_compositor_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ /* do nothing */
+}
+
+static const struct component_ops sti_compositor_ops = {
+ .bind = sti_compositor_bind,
+ .unbind = sti_compositor_unbind,
+};
+
+static const struct of_device_id compositor_of_match[] = {
+ {
+ .compatible = "st,stih416-compositor",
+ .data = &stih416_compositor_data,
+ }, {
+ .compatible = "st,stih407-compositor",
+ .data = &stih407_compositor_data,
+ }, {
+ /* end node */
+ }
+};
+MODULE_DEVICE_TABLE(of, compositor_of_match);
+
+static int sti_compositor_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *vtg_np;
+ struct sti_compositor *compo;
+ struct resource *res;
+ int err;
+
+ compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
+ if (!compo) {
+ DRM_ERROR("Failed to allocate compositor context\n");
+ return -ENOMEM;
+ }
+ compo->dev = dev;
+ compo->vtg_vblank_nb.notifier_call = sti_drm_crtc_vblank_cb;
+
+ /* populate data structure depending on compatibility */
+ BUG_ON(!of_match_node(compositor_of_match, np)->data);
+
+ memcpy(&compo->data, of_match_node(compositor_of_match, np)->data,
+ sizeof(struct sti_compositor_data));
+
+ /* Get Memory ressources */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ DRM_ERROR("Get memory resource failed\n");
+ return -ENXIO;
+ }
+ compo->regs = devm_ioremap(dev, res->start, resource_size(res));
+ if (compo->regs == NULL) {
+ DRM_ERROR("Register mapping failed\n");
+ return -ENXIO;
+ }
+
+ /* Get clock resources */
+ compo->clk_compo_main = devm_clk_get(dev, "compo_main");
+ if (IS_ERR(compo->clk_compo_main)) {
+ DRM_ERROR("Cannot get compo_main clock\n");
+ return PTR_ERR(compo->clk_compo_main);
+ }
+
+ compo->clk_compo_aux = devm_clk_get(dev, "compo_aux");
+ if (IS_ERR(compo->clk_compo_aux)) {
+ DRM_ERROR("Cannot get compo_aux clock\n");
+ return PTR_ERR(compo->clk_compo_aux);
+ }
+
+ compo->clk_pix_main = devm_clk_get(dev, "pix_main");
+ if (IS_ERR(compo->clk_pix_main)) {
+ DRM_ERROR("Cannot get pix_main clock\n");
+ return PTR_ERR(compo->clk_pix_main);
+ }
+
+ compo->clk_pix_aux = devm_clk_get(dev, "pix_aux");
+ if (IS_ERR(compo->clk_pix_aux)) {
+ DRM_ERROR("Cannot get pix_aux clock\n");
+ return PTR_ERR(compo->clk_pix_aux);
+ }
+
+ /* Get reset resources */
+ compo->rst_main = devm_reset_control_get(dev, "compo-main");
+ /* Take compo main out of reset */
+ if (!IS_ERR(compo->rst_main))
+ reset_control_deassert(compo->rst_main);
+
+ compo->rst_aux = devm_reset_control_get(dev, "compo-aux");
+ /* Take compo aux out of reset */
+ if (!IS_ERR(compo->rst_aux))
+ reset_control_deassert(compo->rst_aux);
+
+ vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
+ if (vtg_np)
+ compo->vtg_main = of_vtg_find(vtg_np);
+
+ vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1);
+ if (vtg_np)
+ compo->vtg_aux = of_vtg_find(vtg_np);
+
+ /* Initialize compositor subdevices */
+ err = sti_compositor_init_subdev(compo, compo->data.subdev_desc,
+ compo->data.nb_subdev);
+ if (err)
+ return err;
+
+ platform_set_drvdata(pdev, compo);
+
+ return component_add(&pdev->dev, &sti_compositor_ops);
+}
+
+static int sti_compositor_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sti_compositor_ops);
+ return 0;
+}
+
+static struct platform_driver sti_compositor_driver = {
+ .driver = {
+ .name = "sti-compositor",
+ .owner = THIS_MODULE,
+ .of_match_table = compositor_of_match,
+ },
+ .probe = sti_compositor_probe,
+ .remove = sti_compositor_remove,
+};
+
+module_platform_driver(sti_compositor_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_compositor.h b/drivers/gpu/drm/sti/sti_compositor.h
new file mode 100644
index 000000000000..3ea19db72e0f
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_compositor.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_COMPOSITOR_H_
+#define _STI_COMPOSITOR_H_
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+
+#include "sti_layer.h"
+#include "sti_mixer.h"
+
+#define WAIT_NEXT_VSYNC_MS 50 /*ms*/
+
+#define STI_MAX_LAYER 8
+#define STI_MAX_MIXER 2
+
+enum sti_compositor_subdev_type {
+ STI_MIXER_MAIN_SUBDEV,
+ STI_MIXER_AUX_SUBDEV,
+ STI_GPD_SUBDEV,
+ STI_VID_SUBDEV,
+ STI_CURSOR_SUBDEV,
+};
+
+struct sti_compositor_subdev_descriptor {
+ enum sti_compositor_subdev_type type;
+ int id;
+ unsigned int offset;
+};
+
+/**
+ * STI Compositor data structure
+ *
+ * @nb_subdev: number of subdevices supported by the compositor
+ * @subdev_desc: subdev list description
+ */
+#define MAX_SUBDEV 9
+struct sti_compositor_data {
+ unsigned int nb_subdev;
+ struct sti_compositor_subdev_descriptor subdev_desc[MAX_SUBDEV];
+};
+
+/**
+ * STI Compositor structure
+ *
+ * @dev: driver device
+ * @regs: registers (main)
+ * @data: device data
+ * @clk_compo_main: clock for main compo
+ * @clk_compo_aux: clock for aux compo
+ * @clk_pix_main: pixel clock for main path
+ * @clk_pix_aux: pixel clock for aux path
+ * @rst_main: reset control of the main path
+ * @rst_aux: reset control of the aux path
+ * @mixer: array of mixers
+ * @vtg_main: vtg for main data path
+ * @vtg_aux: vtg for auxillary data path
+ * @layer: array of layers
+ * @nb_mixers: number of mixers for this compositor
+ * @nb_layers: number of layers (GDP,VID,...) for this compositor
+ * @enable: true if compositor is enable else false
+ * @vtg_vblank_nb: callback for VTG VSYNC notification
+ */
+struct sti_compositor {
+ struct device *dev;
+ void __iomem *regs;
+ struct sti_compositor_data data;
+ struct clk *clk_compo_main;
+ struct clk *clk_compo_aux;
+ struct clk *clk_pix_main;
+ struct clk *clk_pix_aux;
+ struct reset_control *rst_main;
+ struct reset_control *rst_aux;
+ struct sti_mixer *mixer[STI_MAX_MIXER];
+ struct sti_vtg *vtg_main;
+ struct sti_vtg *vtg_aux;
+ struct sti_layer *layer[STI_MAX_LAYER];
+ int nb_mixers;
+ int nb_layers;
+ bool enable;
+ struct notifier_block vtg_vblank_nb;
+};
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c
new file mode 100644
index 000000000000..d2ae0c0e13be
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_crtc.h"
+#include "sti_vtg.h"
+
+static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ DRM_DEBUG_KMS("\n");
+}
+
+static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ struct device *dev = mixer->dev;
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+
+ compo->enable = true;
+
+ /* Prepare and enable the compo IP clock */
+ if (mixer->id == STI_MIXER_MAIN) {
+ if (clk_prepare_enable(compo->clk_compo_main))
+ DRM_INFO("Failed to prepare/enable compo_main clk\n");
+ } else {
+ if (clk_prepare_enable(compo->clk_compo_aux))
+ DRM_INFO("Failed to prepare/enable compo_aux clk\n");
+ }
+}
+
+static void sti_drm_crtc_commit(struct drm_crtc *crtc)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ struct device *dev = mixer->dev;
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+ struct sti_layer *layer;
+
+ if ((!mixer || !compo)) {
+ DRM_ERROR("Can not find mixer or compositor)\n");
+ return;
+ }
+
+ /* get GDP which is reserved to the CRTC FB */
+ layer = to_sti_layer(crtc->primary);
+ if (layer)
+ sti_layer_commit(layer);
+ else
+ DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");
+
+ /* Enable layer on mixer */
+ if (sti_mixer_set_layer_status(mixer, layer, true))
+ DRM_ERROR("Can not enable layer at mixer\n");
+}
+
+static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /* accept the provided drm_display_mode, do not fix it up */
+ return true;
+}
+
+static int
+sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ struct device *dev = mixer->dev;
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+ struct sti_layer *layer;
+ struct clk *clk;
+ int rate = mode->clock * 1000;
+ int res;
+ unsigned int w, h;
+
+ DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n",
+ crtc->base.id, sti_mixer_to_str(mixer),
+ crtc->primary->fb->base.id, mode->base.id, mode->name);
+
+ DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
+ mode->vrefresh, mode->clock,
+ mode->hdisplay,
+ mode->hsync_start, mode->hsync_end,
+ mode->htotal,
+ mode->vdisplay,
+ mode->vsync_start, mode->vsync_end,
+ mode->vtotal, mode->type, mode->flags);
+
+ /* Set rate and prepare/enable pixel clock */
+ if (mixer->id == STI_MIXER_MAIN)
+ clk = compo->clk_pix_main;
+ else
+ clk = compo->clk_pix_aux;
+
+ res = clk_set_rate(clk, rate);
+ if (res < 0) {
+ DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
+ return -EINVAL;
+ }
+ if (clk_prepare_enable(clk)) {
+ DRM_ERROR("Failed to prepare/enable pix clk\n");
+ return -EINVAL;
+ }
+
+ sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
+ compo->vtg_main : compo->vtg_aux, &crtc->mode);
+
+ /* a GDP is reserved to the CRTC FB */
+ layer = to_sti_layer(crtc->primary);
+ if (!layer) {
+ DRM_ERROR("Can not find GDP0)\n");
+ return -EINVAL;
+ }
+
+ /* copy the mode data adjusted by mode_fixup() into crtc->mode
+ * so that hardware can be set to proper mode
+ */
+ memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
+
+ res = sti_mixer_set_layer_depth(mixer, layer);
+ if (res) {
+ DRM_ERROR("Can not set layer depth\n");
+ return -EINVAL;
+ }
+ res = sti_mixer_active_video_area(mixer, &crtc->mode);
+ if (res) {
+ DRM_ERROR("Can not set active video area\n");
+ return -EINVAL;
+ }
+
+ w = crtc->primary->fb->width - x;
+ h = crtc->primary->fb->height - y;
+
+ return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
+ mixer->id, 0, 0, w, h, x, y, w, h);
+}
+
+static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ struct sti_layer *layer;
+ unsigned int w, h;
+ int ret;
+
+ DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n",
+ crtc->base.id, sti_mixer_to_str(mixer),
+ crtc->primary->fb->base.id, x, y);
+
+ /* GDP is reserved to the CRTC FB */
+ layer = to_sti_layer(crtc->primary);
+ if (!layer) {
+ DRM_ERROR("Can not find GDP0)\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ w = crtc->primary->fb->width - crtc->x;
+ h = crtc->primary->fb->height - crtc->y;
+
+ ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
+ mixer->id, 0, 0, w, h,
+ crtc->x, crtc->y, w, h);
+ if (ret) {
+ DRM_ERROR("Can not prepare layer\n");
+ goto out;
+ }
+
+ sti_drm_crtc_commit(crtc);
+out:
+ return ret;
+}
+
+static void sti_drm_crtc_load_lut(struct drm_crtc *crtc)
+{
+ /* do nothing */
+}
+
+static void sti_drm_crtc_disable(struct drm_crtc *crtc)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ struct device *dev = mixer->dev;
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+ struct sti_layer *layer;
+
+ if (!compo->enable)
+ return;
+
+ DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
+
+ /* Disable Background */
+ sti_mixer_set_background_status(mixer, false);
+
+ /* Disable GDP */
+ layer = to_sti_layer(crtc->primary);
+ if (!layer) {
+ DRM_ERROR("Cannot find GDP0\n");
+ return;
+ }
+
+ /* Disable layer at mixer level */
+ if (sti_mixer_set_layer_status(mixer, layer, false))
+ DRM_ERROR("Can not disable %s layer at mixer\n",
+ sti_layer_to_str(layer));
+
+ /* Wait a while to be sure that a Vsync event is received */
+ msleep(WAIT_NEXT_VSYNC_MS);
+
+ /* Then disable layer itself */
+ sti_layer_disable(layer);
+
+ drm_vblank_off(crtc->dev, mixer->id);
+
+ /* Disable pixel clock and compo IP clocks */
+ if (mixer->id == STI_MIXER_MAIN) {
+ clk_disable_unprepare(compo->clk_pix_main);
+ clk_disable_unprepare(compo->clk_compo_main);
+ } else {
+ clk_disable_unprepare(compo->clk_pix_aux);
+ clk_disable_unprepare(compo->clk_compo_aux);
+ }
+
+ compo->enable = false;
+}
+
+static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
+ .dpms = sti_drm_crtc_dpms,
+ .prepare = sti_drm_crtc_prepare,
+ .commit = sti_drm_crtc_commit,
+ .mode_fixup = sti_drm_crtc_mode_fixup,
+ .mode_set = sti_drm_crtc_mode_set,
+ .mode_set_base = sti_drm_crtc_mode_set_base,
+ .load_lut = sti_drm_crtc_load_lut,
+ .disable = sti_drm_crtc_disable,
+};
+
+static int sti_drm_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags)
+{
+ struct drm_device *drm_dev = crtc->dev;
+ struct drm_framebuffer *old_fb;
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ unsigned long flags;
+ int ret;
+
+ DRM_DEBUG_KMS("fb %d --> fb %d\n",
+ crtc->primary->fb->base.id, fb->base.id);
+
+ mutex_lock(&drm_dev->struct_mutex);
+
+ old_fb = crtc->primary->fb;
+ crtc->primary->fb = fb;
+ ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+ if (ret) {
+ DRM_ERROR("failed\n");
+ crtc->primary->fb = old_fb;
+ goto out;
+ }
+
+ if (event) {
+ event->pipe = mixer->id;
+
+ ret = drm_vblank_get(drm_dev, event->pipe);
+ if (ret) {
+ DRM_ERROR("Cannot get vblank\n");
+ goto out;
+ }
+
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+ if (mixer->pending_event) {
+ drm_vblank_put(drm_dev, event->pipe);
+ ret = -EBUSY;
+ } else {
+ mixer->pending_event = event;
+ }
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+ }
+out:
+ mutex_unlock(&drm_dev->struct_mutex);
+ return ret;
+}
+
+static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+ DRM_DEBUG_KMS("\n");
+ drm_crtc_cleanup(crtc);
+}
+
+static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
+ struct drm_property *property,
+ uint64_t val)
+{
+ DRM_DEBUG_KMS("\n");
+ return 0;
+}
+
+int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct drm_device *drm_dev;
+ struct sti_compositor *compo =
+ container_of(nb, struct sti_compositor, vtg_vblank_nb);
+ int *crtc = data;
+ unsigned long flags;
+ struct sti_drm_private *priv;
+
+ drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
+ priv = drm_dev->dev_private;
+
+ if ((event != VTG_TOP_FIELD_EVENT) &&
+ (event != VTG_BOTTOM_FIELD_EVENT)) {
+ DRM_ERROR("unknown event: %lu\n", event);
+ return -EINVAL;
+ }
+
+ drm_handle_vblank(drm_dev, *crtc);
+
+ spin_lock_irqsave(&drm_dev->event_lock, flags);
+ if (compo->mixer[*crtc]->pending_event) {
+ drm_send_vblank_event(drm_dev, -1,
+ compo->mixer[*crtc]->pending_event);
+ drm_vblank_put(drm_dev, *crtc);
+ compo->mixer[*crtc]->pending_event = NULL;
+ }
+ spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+
+ return 0;
+}
+
+int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
+{
+ struct sti_drm_private *dev_priv = dev->dev_private;
+ struct sti_compositor *compo = dev_priv->compo;
+ struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+
+ if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
+ compo->vtg_main : compo->vtg_aux,
+ vtg_vblank_nb, crtc)) {
+ DRM_ERROR("Cannot register VTG notifier\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);
+
+void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
+{
+ struct sti_drm_private *priv = dev->dev_private;
+ struct sti_compositor *compo = priv->compo;
+ struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+ unsigned long flags;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
+ compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
+ DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
+
+ /* free the resources of the pending requests */
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (compo->mixer[crtc]->pending_event) {
+ drm_vblank_put(dev, crtc);
+ compo->mixer[crtc]->pending_event = NULL;
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+}
+EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
+
+static struct drm_crtc_funcs sti_crtc_funcs = {
+ .set_config = drm_crtc_helper_set_config,
+ .page_flip = sti_drm_crtc_page_flip,
+ .destroy = sti_drm_crtc_destroy,
+ .set_property = sti_drm_crtc_set_property,
+};
+
+bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
+{
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+
+ if (mixer->id == STI_MIXER_MAIN)
+ return true;
+
+ return false;
+}
+
+int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+ struct drm_plane *primary, struct drm_plane *cursor)
+{
+ struct drm_crtc *crtc = &mixer->drm_crtc;
+ int res;
+
+ res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
+ &sti_crtc_funcs);
+ if (res) {
+ DRM_ERROR("Can not initialze CRTC\n");
+ return -EINVAL;
+ }
+
+ drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
+
+ DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
+ crtc->base.id, sti_mixer_to_str(mixer));
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.h b/drivers/gpu/drm/sti/sti_drm_crtc.h
new file mode 100644
index 000000000000..caca8b14f017
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_crtc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_CRTC_H_
+#define _STI_DRM_CRTC_H_
+
+#include <drm/drmP.h>
+
+struct sti_mixer;
+
+int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
+ struct drm_plane *primary, struct drm_plane *cursor);
+int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
+void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
+int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
+ unsigned long event, void *data);
+bool sti_drm_crtc_is_main(struct drm_crtc *drm_crtc);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.c b/drivers/gpu/drm/sti/sti_drm_drv.c
new file mode 100644
index 000000000000..a7cc24917a96
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_drv.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/component.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "sti_drm_drv.h"
+#include "sti_drm_crtc.h"
+
+#define DRIVER_NAME "sti"
+#define DRIVER_DESC "STMicroelectronics SoC DRM"
+#define DRIVER_DATE "20140601"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+
+#define STI_MAX_FB_HEIGHT 4096
+#define STI_MAX_FB_WIDTH 4096
+
+static struct drm_mode_config_funcs sti_drm_mode_config_funcs = {
+ .fb_create = drm_fb_cma_create,
+};
+
+static void sti_drm_mode_config_init(struct drm_device *dev)
+{
+ dev->mode_config.min_width = 0;
+ dev->mode_config.min_height = 0;
+
+ /*
+ * set max width and height as default value.
+ * this value would be used to check framebuffer size limitation
+ * at drm_mode_addfb().
+ */
+ dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
+ dev->mode_config.max_height = STI_MAX_FB_WIDTH;
+
+ dev->mode_config.funcs = &sti_drm_mode_config_funcs;
+}
+
+static int sti_drm_load(struct drm_device *dev, unsigned long flags)
+{
+ struct sti_drm_private *private;
+ int ret;
+
+ private = kzalloc(sizeof(struct sti_drm_private), GFP_KERNEL);
+ if (!private) {
+ DRM_ERROR("Failed to allocate private\n");
+ return -ENOMEM;
+ }
+ dev->dev_private = (void *)private;
+ private->drm_dev = dev;
+
+ drm_mode_config_init(dev);
+ drm_kms_helper_poll_init(dev);
+
+ sti_drm_mode_config_init(dev);
+
+ ret = component_bind_all(dev->dev, dev);
+ if (ret)
+ return ret;
+
+ drm_helper_disable_unused_functions(dev);
+
+#ifdef CONFIG_DRM_STI_FBDEV
+ drm_fbdev_cma_init(dev, 32,
+ dev->mode_config.num_crtc,
+ dev->mode_config.num_connector);
+#endif
+ return 0;
+}
+
+static const struct file_operations sti_drm_driver_fops = {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .mmap = drm_gem_cma_mmap,
+ .poll = drm_poll,
+ .read = drm_read,
+ .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = drm_compat_ioctl,
+#endif
+ .release = drm_release,
+};
+
+static struct dma_buf *sti_drm_gem_prime_export(struct drm_device *dev,
+ struct drm_gem_object *obj,
+ int flags)
+{
+ /* we want to be able to write in mmapped buffer */
+ flags |= O_RDWR;
+ return drm_gem_prime_export(dev, obj, flags);
+}
+
+static struct drm_driver sti_drm_driver = {
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
+ DRIVER_GEM | DRIVER_PRIME,
+ .load = sti_drm_load,
+ .gem_free_object = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .fops = &sti_drm_driver_fops,
+
+ .get_vblank_counter = drm_vblank_count,
+ .enable_vblank = sti_drm_crtc_enable_vblank,
+ .disable_vblank = sti_drm_crtc_disable_vblank,
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_export = sti_drm_gem_prime_export,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int sti_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&sti_drm_driver, to_platform_device(dev));
+}
+
+static void sti_drm_unbind(struct device *dev)
+{
+ drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops sti_drm_ops = {
+ .bind = sti_drm_bind,
+ .unbind = sti_drm_unbind,
+};
+
+static int sti_drm_master_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->parent->of_node;
+ struct device_node *child_np;
+ struct component_match *match = NULL;
+
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+
+ child_np = of_get_next_available_child(node, NULL);
+
+ while (child_np) {
+ component_match_add(dev, &match, compare_of, child_np);
+ of_node_put(child_np);
+ child_np = of_get_next_available_child(node, child_np);
+ }
+
+ return component_master_add_with_match(dev, &sti_drm_ops, match);
+}
+
+static int sti_drm_master_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &sti_drm_ops);
+ return 0;
+}
+
+static struct platform_driver sti_drm_master_driver = {
+ .probe = sti_drm_master_probe,
+ .remove = sti_drm_master_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME "__master",
+ },
+};
+
+static int sti_drm_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct platform_device *master;
+
+ of_platform_populate(node, NULL, NULL, dev);
+
+ platform_driver_register(&sti_drm_master_driver);
+ master = platform_device_register_resndata(dev,
+ DRIVER_NAME "__master", -1,
+ NULL, 0, NULL, 0);
+ if (!master)
+ return -EINVAL;
+
+ platform_set_drvdata(pdev, master);
+ return 0;
+}
+
+static int sti_drm_platform_remove(struct platform_device *pdev)
+{
+ struct platform_device *master = platform_get_drvdata(pdev);
+
+ of_platform_depopulate(&pdev->dev);
+ platform_device_unregister(master);
+ platform_driver_unregister(&sti_drm_master_driver);
+ return 0;
+}
+
+static const struct of_device_id sti_drm_dt_ids[] = {
+ { .compatible = "st,sti-display-subsystem", },
+ { /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, sti_drm_dt_ids);
+
+static struct platform_driver sti_drm_platform_driver = {
+ .probe = sti_drm_platform_probe,
+ .remove = sti_drm_platform_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .of_match_table = sti_drm_dt_ids,
+ },
+};
+
+module_platform_driver(sti_drm_platform_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_drm_drv.h b/drivers/gpu/drm/sti/sti_drm_drv.h
new file mode 100644
index 000000000000..ec5e2eb8dff9
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_drv.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_DRV_H_
+#define _STI_DRM_DRV_H_
+
+#include <drm/drmP.h>
+
+struct sti_compositor;
+struct sti_tvout;
+
+/**
+ * STI drm private structure
+ * This structure is stored as private in the drm_device
+ *
+ * @compo: compositor
+ * @plane_zorder_property: z-order property for CRTC planes
+ * @drm_dev: drm device
+ */
+struct sti_drm_private {
+ struct sti_compositor *compo;
+ struct drm_property *plane_zorder_property;
+ struct drm_device *drm_dev;
+};
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
new file mode 100644
index 000000000000..f4118d4cac22
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include "sti_compositor.h"
+#include "sti_drm_drv.h"
+#include "sti_drm_plane.h"
+#include "sti_vtg.h"
+
+enum sti_layer_desc sti_layer_default_zorder[] = {
+ STI_GDP_0,
+ STI_VID_0,
+ STI_GDP_1,
+ STI_VID_1,
+ STI_GDP_2,
+ STI_GDP_3,
+};
+
+/* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
+
+static int
+sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+ struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct sti_layer *layer = to_sti_layer(plane);
+ struct sti_mixer *mixer = to_sti_mixer(crtc);
+ int res;
+
+ DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s) drm fb:%d\n",
+ crtc->base.id, sti_mixer_to_str(mixer),
+ plane->base.id, sti_layer_to_str(layer), fb->base.id);
+ DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
+
+ res = sti_mixer_set_layer_depth(mixer, layer);
+ if (res) {
+ DRM_ERROR("Can not set layer depth\n");
+ return res;
+ }
+
+ /* src_x are in 16.16 format. */
+ res = sti_layer_prepare(layer, fb, &crtc->mode, mixer->id,
+ crtc_x, crtc_y, crtc_w, crtc_h,
+ src_x >> 16, src_y >> 16,
+ src_w >> 16, src_h >> 16);
+ if (res) {
+ DRM_ERROR("Layer prepare failed\n");
+ return res;
+ }
+
+ res = sti_layer_commit(layer);
+ if (res) {
+ DRM_ERROR("Layer commit failed\n");
+ return res;
+ }
+
+ res = sti_mixer_set_layer_status(mixer, layer, true);
+ if (res) {
+ DRM_ERROR("Can not enable layer at mixer\n");
+ return res;
+ }
+
+ return 0;
+}
+
+static int sti_drm_disable_plane(struct drm_plane *plane)
+{
+ struct sti_layer *layer;
+ struct sti_mixer *mixer;
+ int lay_res, mix_res;
+
+ if (!plane->crtc) {
+ DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
+ return 0;
+ }
+ layer = to_sti_layer(plane);
+ mixer = to_sti_mixer(plane->crtc);
+
+ DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
+ plane->crtc->base.id, sti_mixer_to_str(mixer),
+ plane->base.id, sti_layer_to_str(layer));
+
+ /* Disable layer at mixer level */
+ mix_res = sti_mixer_set_layer_status(mixer, layer, false);
+ if (mix_res)
+ DRM_ERROR("Can not disable layer at mixer\n");
+
+ /* Wait a while to be sure that a Vsync event is received */
+ msleep(WAIT_NEXT_VSYNC_MS);
+
+ /* Then disable layer itself */
+ lay_res = sti_layer_disable(layer);
+ if (lay_res)
+ DRM_ERROR("Layer disable failed\n");
+
+ if (lay_res || mix_res)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void sti_drm_plane_destroy(struct drm_plane *plane)
+{
+ DRM_DEBUG_DRIVER("\n");
+
+ sti_drm_disable_plane(plane);
+ drm_plane_cleanup(plane);
+}
+
+static int sti_drm_plane_set_property(struct drm_plane *plane,
+ struct drm_property *property,
+ uint64_t val)
+{
+ struct drm_device *dev = plane->dev;
+ struct sti_drm_private *private = dev->dev_private;
+ struct sti_layer *layer = to_sti_layer(plane);
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (property == private->plane_zorder_property) {
+ layer->zorder = val;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static struct drm_plane_funcs sti_drm_plane_funcs = {
+ .update_plane = sti_drm_update_plane,
+ .disable_plane = sti_drm_disable_plane,
+ .destroy = sti_drm_plane_destroy,
+ .set_property = sti_drm_plane_set_property,
+};
+
+static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
+ uint64_t default_val)
+{
+ struct drm_device *dev = plane->dev;
+ struct sti_drm_private *private = dev->dev_private;
+ struct drm_property *prop;
+ struct sti_layer *layer = to_sti_layer(plane);
+
+ prop = private->plane_zorder_property;
+ if (!prop) {
+ prop = drm_property_create_range(dev, 0, "zpos", 0,
+ GAM_MIXER_NB_DEPTH_LEVEL - 1);
+ if (!prop)
+ return;
+
+ private->plane_zorder_property = prop;
+ }
+
+ drm_object_attach_property(&plane->base, prop, default_val);
+ layer->zorder = default_val;
+}
+
+struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
+ struct sti_layer *layer,
+ unsigned int possible_crtcs,
+ enum drm_plane_type type)
+{
+ int err, i;
+ uint64_t default_zorder = 0;
+
+ err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
+ &sti_drm_plane_funcs,
+ sti_layer_get_formats(layer),
+ sti_layer_get_nb_formats(layer), type);
+ if (err) {
+ DRM_ERROR("Failed to initialize plane\n");
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
+ if (sti_layer_default_zorder[i] == layer->desc)
+ break;
+
+ default_zorder = i;
+
+ if (type == DRM_PLANE_TYPE_OVERLAY)
+ sti_drm_plane_attach_zorder_property(&layer->plane,
+ default_zorder);
+
+ DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
+ layer->plane.base.id,
+ sti_layer_to_str(layer), default_zorder);
+
+ return &layer->plane;
+}
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.h b/drivers/gpu/drm/sti/sti_drm_plane.h
new file mode 100644
index 000000000000..4f191839f2a7
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_drm_plane.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_DRM_PLANE_H_
+#define _STI_DRM_PLANE_H_
+
+#include <drm/drmP.h>
+
+struct sti_layer;
+
+struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
+ struct sti_layer *layer,
+ unsigned int possible_crtcs,
+ enum drm_plane_type type);
+#endif
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
new file mode 100644
index 000000000000..4e30b74559f5
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
+#include "sti_compositor.h"
+#include "sti_gdp.h"
+#include "sti_layer.h"
+#include "sti_vtg.h"
+
+#define ENA_COLOR_FILL BIT(8)
+#define WAIT_NEXT_VSYNC BIT(31)
+
+/* GDP color formats */
+#define GDP_RGB565 0x00
+#define GDP_RGB888 0x01
+#define GDP_RGB888_32 0x02
+#define GDP_ARGB8565 0x04
+#define GDP_ARGB8888 0x05
+#define GDP_ARGB1555 0x06
+#define GDP_ARGB4444 0x07
+#define GDP_CLUT8 0x0B
+#define GDP_YCBR888 0x10
+#define GDP_YCBR422R 0x12
+#define GDP_AYCBR8888 0x15
+
+#define GAM_GDP_CTL_OFFSET 0x00
+#define GAM_GDP_AGC_OFFSET 0x04
+#define GAM_GDP_VPO_OFFSET 0x0C
+#define GAM_GDP_VPS_OFFSET 0x10
+#define GAM_GDP_PML_OFFSET 0x14
+#define GAM_GDP_PMP_OFFSET 0x18
+#define GAM_GDP_SIZE_OFFSET 0x1C
+#define GAM_GDP_NVN_OFFSET 0x24
+#define GAM_GDP_KEY1_OFFSET 0x28
+#define GAM_GDP_KEY2_OFFSET 0x2C
+#define GAM_GDP_PPT_OFFSET 0x34
+#define GAM_GDP_CML_OFFSET 0x3C
+#define GAM_GDP_MST_OFFSET 0x68
+
+#define GAM_GDP_ALPHARANGE_255 BIT(5)
+#define GAM_GDP_AGC_FULL_RANGE 0x00808080
+#define GAM_GDP_PPT_IGNORE (BIT(1) | BIT(0))
+#define GAM_GDP_SIZE_MAX 0x7FF
+
+#define GDP_NODE_NB_BANK 2
+#define GDP_NODE_PER_FIELD 2
+
+struct sti_gdp_node {
+ u32 gam_gdp_ctl;
+ u32 gam_gdp_agc;
+ u32 reserved1;
+ u32 gam_gdp_vpo;
+ u32 gam_gdp_vps;
+ u32 gam_gdp_pml;
+ u32 gam_gdp_pmp;
+ u32 gam_gdp_size;
+ u32 reserved2;
+ u32 gam_gdp_nvn;
+ u32 gam_gdp_key1;
+ u32 gam_gdp_key2;
+ u32 reserved3;
+ u32 gam_gdp_ppt;
+ u32 reserved4;
+ u32 gam_gdp_cml;
+};
+
+struct sti_gdp_node_list {
+ struct sti_gdp_node *top_field;
+ struct sti_gdp_node *btm_field;
+};
+
+/**
+ * STI GDP structure
+ *
+ * @layer: layer structure
+ * @clk_pix: pixel clock for the current gdp
+ * @vtg_field_nb: callback for VTG FIELD (top or bottom) notification
+ * @is_curr_top: true if the current node processed is the top field
+ * @node_list: array of node list
+ */
+struct sti_gdp {
+ struct sti_layer layer;
+ struct clk *clk_pix;
+ struct notifier_block vtg_field_nb;
+ bool is_curr_top;
+ struct sti_gdp_node_list node_list[GDP_NODE_NB_BANK];
+};
+
+#define to_sti_gdp(x) container_of(x, struct sti_gdp, layer)
+
+static const uint32_t gdp_supported_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ARGB4444,
+ DRM_FORMAT_ARGB1555,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_AYUV,
+ DRM_FORMAT_YUV444,
+ DRM_FORMAT_VYUY,
+ DRM_FORMAT_C8,
+};
+
+static const uint32_t *sti_gdp_get_formats(struct sti_layer *layer)
+{
+ return gdp_supported_formats;
+}
+
+static unsigned int sti_gdp_get_nb_formats(struct sti_layer *layer)
+{
+ return ARRAY_SIZE(gdp_supported_formats);
+}
+
+static int sti_gdp_fourcc2format(int fourcc)
+{
+ switch (fourcc) {
+ case DRM_FORMAT_XRGB8888:
+ return GDP_RGB888_32;
+ case DRM_FORMAT_ARGB8888:
+ return GDP_ARGB8888;
+ case DRM_FORMAT_ARGB4444:
+ return GDP_ARGB4444;
+ case DRM_FORMAT_ARGB1555:
+ return GDP_ARGB1555;
+ case DRM_FORMAT_RGB565:
+ return GDP_RGB565;
+ case DRM_FORMAT_RGB888:
+ return GDP_RGB888;
+ case DRM_FORMAT_AYUV:
+ return GDP_AYCBR8888;
+ case DRM_FORMAT_YUV444:
+ return GDP_YCBR888;
+ case DRM_FORMAT_VYUY:
+ return GDP_YCBR422R;
+ case DRM_FORMAT_C8:
+ return GDP_CLUT8;
+ }
+ return -1;
+}
+
+static int sti_gdp_get_alpharange(int format)
+{
+ switch (format) {
+ case GDP_ARGB8565:
+ case GDP_ARGB8888:
+ case GDP_AYCBR8888:
+ return GAM_GDP_ALPHARANGE_255;
+ }
+ return 0;
+}
+
+/**
+ * sti_gdp_get_free_nodes
+ * @layer: gdp layer
+ *
+ * Look for a GDP node list that is not currently read by the HW.
+ *
+ * RETURNS:
+ * Pointer to the free GDP node list
+ */
+static struct sti_gdp_node_list *sti_gdp_get_free_nodes(struct sti_layer *layer)
+{
+ int hw_nvn;
+ void *virt_nvn;
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ unsigned int i;
+
+ hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+ if (!hw_nvn)
+ goto end;
+
+ virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn);
+
+ for (i = 0; i < GDP_NODE_NB_BANK; i++)
+ if ((virt_nvn != gdp->node_list[i].btm_field) &&
+ (virt_nvn != gdp->node_list[i].top_field))
+ return &gdp->node_list[i];
+
+ /* in hazardious cases restart with the first node */
+ DRM_ERROR("inconsistent NVN for %s: 0x%08X\n",
+ sti_layer_to_str(layer), hw_nvn);
+
+end:
+ return &gdp->node_list[0];
+}
+
+/**
+ * sti_gdp_get_current_nodes
+ * @layer: GDP layer
+ *
+ * Look for GDP nodes that are currently read by the HW.
+ *
+ * RETURNS:
+ * Pointer to the current GDP node list
+ */
+static
+struct sti_gdp_node_list *sti_gdp_get_current_nodes(struct sti_layer *layer)
+{
+ int hw_nvn;
+ void *virt_nvn;
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ unsigned int i;
+
+ hw_nvn = readl(layer->regs + GAM_GDP_NVN_OFFSET);
+ if (!hw_nvn)
+ goto end;
+
+ virt_nvn = dma_to_virt(layer->dev, (dma_addr_t) hw_nvn);
+
+ for (i = 0; i < GDP_NODE_NB_BANK; i++)
+ if ((virt_nvn == gdp->node_list[i].btm_field) ||
+ (virt_nvn == gdp->node_list[i].top_field))
+ return &gdp->node_list[i];
+
+end:
+ DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n",
+ hw_nvn, sti_layer_to_str(layer));
+
+ return NULL;
+}
+
+/**
+ * sti_gdp_prepare_layer
+ * @lay: gdp layer
+ * @first_prepare: true if it is the first time this function is called
+ *
+ * Update the free GDP node list according to the layer properties.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
+{
+ struct sti_gdp_node_list *list;
+ struct sti_gdp_node *top_field, *btm_field;
+ struct drm_display_mode *mode = layer->mode;
+ struct device *dev = layer->dev;
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ struct sti_compositor *compo = dev_get_drvdata(dev);
+ int format;
+ unsigned int depth, bpp;
+ int rate = mode->clock * 1000;
+ int res;
+ u32 ydo, xdo, yds, xds;
+
+ list = sti_gdp_get_free_nodes(layer);
+ top_field = list->top_field;
+ btm_field = list->btm_field;
+
+ dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__,
+ sti_layer_to_str(layer), top_field, btm_field);
+
+ /* Build the top field from layer params */
+ top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE;
+ top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC;
+ format = sti_gdp_fourcc2format(layer->format);
+ if (format == -1) {
+ DRM_ERROR("Format not supported by GDP %.4s\n",
+ (char *)&layer->format);
+ return 1;
+ }
+ top_field->gam_gdp_ctl |= format;
+ top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
+ top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
+
+ /* pixel memory location */
+ drm_fb_get_bpp_depth(layer->format, &depth, &bpp);
+ top_field->gam_gdp_pml = (u32) layer->paddr + layer->offsets[0];
+ top_field->gam_gdp_pml += layer->src_x * (bpp >> 3);
+ top_field->gam_gdp_pml += layer->src_y * layer->pitches[0];
+
+ /* input parameters */
+ top_field->gam_gdp_pmp = layer->pitches[0];
+ top_field->gam_gdp_size =
+ clamp_val(layer->src_h, 0, GAM_GDP_SIZE_MAX) << 16 |
+ clamp_val(layer->src_w, 0, GAM_GDP_SIZE_MAX);
+
+ /* output parameters */
+ ydo = sti_vtg_get_line_number(*mode, layer->dst_y);
+ yds = sti_vtg_get_line_number(*mode, layer->dst_y + layer->dst_h - 1);
+ xdo = sti_vtg_get_pixel_number(*mode, layer->dst_x);
+ xds = sti_vtg_get_pixel_number(*mode, layer->dst_x + layer->dst_w - 1);
+ top_field->gam_gdp_vpo = (ydo << 16) | xdo;
+ top_field->gam_gdp_vps = (yds << 16) | xds;
+
+ /* Same content and chained together */
+ memcpy(btm_field, top_field, sizeof(*btm_field));
+ top_field->gam_gdp_nvn = virt_to_dma(dev, btm_field);
+ btm_field->gam_gdp_nvn = virt_to_dma(dev, top_field);
+
+ /* Interlaced mode */
+ if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE)
+ btm_field->gam_gdp_pml = top_field->gam_gdp_pml +
+ layer->pitches[0];
+
+ if (first_prepare) {
+ /* Register gdp callback */
+ if (sti_vtg_register_client(layer->mixer_id == STI_MIXER_MAIN ?
+ compo->vtg_main : compo->vtg_aux,
+ &gdp->vtg_field_nb, layer->mixer_id)) {
+ DRM_ERROR("Cannot register VTG notifier\n");
+ return 1;
+ }
+
+ /* Set and enable gdp clock */
+ if (gdp->clk_pix) {
+ res = clk_set_rate(gdp->clk_pix, rate);
+ if (res < 0) {
+ DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
+ rate);
+ return 1;
+ }
+
+ if (clk_prepare_enable(gdp->clk_pix)) {
+ DRM_ERROR("Failed to prepare/enable gdp\n");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * sti_gdp_commit_layer
+ * @lay: gdp layer
+ *
+ * Update the NVN field of the 'right' field of the current GDP node (being
+ * used by the HW) with the address of the updated ('free') top field GDP node.
+ * - In interlaced mode the 'right' field is the bottom field as we update
+ * frames starting from their top field
+ * - In progressive mode, we update both bottom and top fields which are
+ * equal nodes.
+ * At the next VSYNC, the updated node list will be used by the HW.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_commit_layer(struct sti_layer *layer)
+{
+ struct sti_gdp_node_list *updated_list = sti_gdp_get_free_nodes(layer);
+ struct sti_gdp_node *updated_top_node = updated_list->top_field;
+ struct sti_gdp_node *updated_btm_node = updated_list->btm_field;
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ u32 dma_updated_top = virt_to_dma(layer->dev, updated_top_node);
+ u32 dma_updated_btm = virt_to_dma(layer->dev, updated_btm_node);
+ struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer);
+
+ dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__,
+ sti_layer_to_str(layer),
+ updated_top_node, updated_btm_node);
+ dev_dbg(layer->dev, "Current NVN:0x%X\n",
+ readl(layer->regs + GAM_GDP_NVN_OFFSET));
+ dev_dbg(layer->dev, "Posted buff: %lx current buff: %x\n",
+ (unsigned long)layer->paddr,
+ readl(layer->regs + GAM_GDP_PML_OFFSET));
+
+ if (curr_list == NULL) {
+ /* First update or invalid node should directly write in the
+ * hw register */
+ DRM_DEBUG_DRIVER("%s first update (or invalid node)",
+ sti_layer_to_str(layer));
+
+ writel(gdp->is_curr_top == true ?
+ dma_updated_btm : dma_updated_top,
+ layer->regs + GAM_GDP_NVN_OFFSET);
+ return 0;
+ }
+
+ if (layer->mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ if (gdp->is_curr_top == true) {
+ /* Do not update in the middle of the frame, but
+ * postpone the update after the bottom field has
+ * been displayed */
+ curr_list->btm_field->gam_gdp_nvn = dma_updated_top;
+ } else {
+ /* Direct update to avoid one frame delay */
+ writel(dma_updated_top,
+ layer->regs + GAM_GDP_NVN_OFFSET);
+ }
+ } else {
+ /* Direct update for progressive to avoid one frame delay */
+ writel(dma_updated_top, layer->regs + GAM_GDP_NVN_OFFSET);
+ }
+
+ return 0;
+}
+
+/**
+ * sti_gdp_disable_layer
+ * @lay: gdp layer
+ *
+ * Disable a GDP.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+static int sti_gdp_disable_layer(struct sti_layer *layer)
+{
+ unsigned int i;
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ struct sti_compositor *compo = dev_get_drvdata(layer->dev);
+
+ DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+
+ /* Set the nodes as 'to be ignored on mixer' */
+ for (i = 0; i < GDP_NODE_NB_BANK; i++) {
+ gdp->node_list[i].top_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
+ gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE;
+ }
+
+ if (sti_vtg_unregister_client(layer->mixer_id == STI_MIXER_MAIN ?
+ compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb))
+ DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
+
+ if (gdp->clk_pix)
+ clk_disable_unprepare(gdp->clk_pix);
+
+ return 0;
+}
+
+/**
+ * sti_gdp_field_cb
+ * @nb: notifier block
+ * @event: event message
+ * @data: private data
+ *
+ * Handle VTG top field and bottom field event.
+ *
+ * RETURNS:
+ * 0 on success.
+ */
+int sti_gdp_field_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct sti_gdp *gdp = container_of(nb, struct sti_gdp, vtg_field_nb);
+
+ switch (event) {
+ case VTG_TOP_FIELD_EVENT:
+ gdp->is_curr_top = true;
+ break;
+ case VTG_BOTTOM_FIELD_EVENT:
+ gdp->is_curr_top = false;
+ break;
+ default:
+ DRM_ERROR("unsupported event: %lu\n", event);
+ break;
+ }
+
+ return 0;
+}
+
+static void sti_gdp_init(struct sti_layer *layer)
+{
+ struct sti_gdp *gdp = to_sti_gdp(layer);
+ struct device_node *np = layer->dev->of_node;
+ dma_addr_t dma;
+ void *base;
+ unsigned int i, size;
+
+ /* Allocate all the nodes within a single memory page */
+ size = sizeof(struct sti_gdp_node) *
+ GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK;
+
+ base = dma_alloc_writecombine(layer->dev,
+ size, &dma, GFP_KERNEL | GFP_DMA);
+ if (!base) {
+ DRM_ERROR("Failed to allocate memory for GDP node\n");
+ return;
+ }
+ memset(base, 0, size);
+
+ for (i = 0; i < GDP_NODE_NB_BANK; i++) {
+ if (virt_to_dma(layer->dev, base) & 0xF) {
+ DRM_ERROR("Mem alignment failed\n");
+ return;
+ }
+ gdp->node_list[i].top_field = base;
+ DRM_DEBUG_DRIVER("node[%d].top_field=%p\n", i, base);
+ base += sizeof(struct sti_gdp_node);
+
+ if (virt_to_dma(layer->dev, base) & 0xF) {
+ DRM_ERROR("Mem alignment failed\n");
+ return;
+ }
+ gdp->node_list[i].btm_field = base;
+ DRM_DEBUG_DRIVER("node[%d].btm_field=%p\n", i, base);
+ base += sizeof(struct sti_gdp_node);
+ }
+
+ if (of_device_is_compatible(np, "st,stih407-compositor")) {
+ /* GDP of STiH407 chip have its own pixel clock */
+ char *clk_name;
+
+ switch (layer->desc) {
+ case STI_GDP_0:
+ clk_name = "pix_gdp1";
+ break;
+ case STI_GDP_1:
+ clk_name = "pix_gdp2";
+ break;
+ case STI_GDP_2:
+ clk_name = "pix_gdp3";
+ break;
+ case STI_GDP_3:
+ clk_name = "pix_gdp4";
+ break;
+ default:
+ DRM_ERROR("GDP id not recognized\n");
+ return;
+ }
+
+ gdp->clk_pix = devm_clk_get(layer->dev, clk_name);
+ if (IS_ERR(gdp->clk_pix))
+ DRM_ERROR("Cannot get %s clock\n", clk_name);
+ }
+}
+
+static const struct sti_layer_funcs gdp_ops = {
+ .get_formats = sti_gdp_get_formats,
+ .get_nb_formats = sti_gdp_get_nb_formats,
+ .init = sti_gdp_init,
+ .prepare = sti_gdp_prepare_layer,
+ .commit = sti_gdp_commit_layer,
+ .disable = sti_gdp_disable_layer,
+};
+
+struct sti_layer *sti_gdp_create(struct device *dev, int id)
+{
+ struct sti_gdp *gdp;
+
+ gdp = devm_kzalloc(dev, sizeof(*gdp), GFP_KERNEL);
+ if (!gdp) {
+ DRM_ERROR("Failed to allocate memory for GDP\n");
+ return NULL;
+ }
+
+ gdp->layer.ops = &gdp_ops;
+ gdp->vtg_field_nb.notifier_call = sti_gdp_field_cb;
+
+ return (struct sti_layer *)gdp;
+}
diff --git a/drivers/gpu/drm/sti/sti_gdp.h b/drivers/gpu/drm/sti/sti_gdp.h
new file mode 100644
index 000000000000..1dab68274ad3
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_gdp.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_GDP_H_
+#define _STI_GDP_H_
+
+#include <linux/types.h>
+
+struct sti_layer *sti_gdp_create(struct device *dev, int id);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
new file mode 100644
index 000000000000..72d957f81c05
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+/* HDformatter registers */
+#define HDA_ANA_CFG 0x0000
+#define HDA_ANA_SCALE_CTRL_Y 0x0004
+#define HDA_ANA_SCALE_CTRL_CB 0x0008
+#define HDA_ANA_SCALE_CTRL_CR 0x000C
+#define HDA_ANA_ANC_CTRL 0x0010
+#define HDA_ANA_SRC_Y_CFG 0x0014
+#define HDA_COEFF_Y_PH1_TAP123 0x0018
+#define HDA_COEFF_Y_PH1_TAP456 0x001C
+#define HDA_COEFF_Y_PH2_TAP123 0x0020
+#define HDA_COEFF_Y_PH2_TAP456 0x0024
+#define HDA_COEFF_Y_PH3_TAP123 0x0028
+#define HDA_COEFF_Y_PH3_TAP456 0x002C
+#define HDA_COEFF_Y_PH4_TAP123 0x0030
+#define HDA_COEFF_Y_PH4_TAP456 0x0034
+#define HDA_ANA_SRC_C_CFG 0x0040
+#define HDA_COEFF_C_PH1_TAP123 0x0044
+#define HDA_COEFF_C_PH1_TAP456 0x0048
+#define HDA_COEFF_C_PH2_TAP123 0x004C
+#define HDA_COEFF_C_PH2_TAP456 0x0050
+#define HDA_COEFF_C_PH3_TAP123 0x0054
+#define HDA_COEFF_C_PH3_TAP456 0x0058
+#define HDA_COEFF_C_PH4_TAP123 0x005C
+#define HDA_COEFF_C_PH4_TAP456 0x0060
+#define HDA_SYNC_AWGI 0x0300
+
+/* HDA_ANA_CFG */
+#define CFG_AWG_ASYNC_EN BIT(0)
+#define CFG_AWG_ASYNC_HSYNC_MTD BIT(1)
+#define CFG_AWG_ASYNC_VSYNC_MTD BIT(2)
+#define CFG_AWG_SYNC_DEL BIT(3)
+#define CFG_AWG_FLTR_MODE_SHIFT 4
+#define CFG_AWG_FLTR_MODE_MASK (0xF << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_SD (0 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_ED (1 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_AWG_FLTR_MODE_HD (2 << CFG_AWG_FLTR_MODE_SHIFT)
+#define CFG_SYNC_ON_PBPR_MASK BIT(8)
+#define CFG_PREFILTER_EN_MASK BIT(9)
+#define CFG_PBPR_SYNC_OFF_SHIFT 16
+#define CFG_PBPR_SYNC_OFF_MASK (0x7FF << CFG_PBPR_SYNC_OFF_SHIFT)
+#define CFG_PBPR_SYNC_OFF_VAL 0x117 /* Voltage dependent. stiH416 */
+
+/* Default scaling values */
+#define SCALE_CTRL_Y_DFLT 0x00C50256
+#define SCALE_CTRL_CB_DFLT 0x00DB0249
+#define SCALE_CTRL_CR_DFLT 0x00DB0249
+
+/* Video DACs control */
+#define VIDEO_DACS_CONTROL_MASK 0x0FFF
+#define VIDEO_DACS_CONTROL_SYSCFG2535 0x085C /* for stih416 */
+#define DAC_CFG_HD_OFF_SHIFT 5
+#define DAC_CFG_HD_OFF_MASK (0x7 << DAC_CFG_HD_OFF_SHIFT)
+#define VIDEO_DACS_CONTROL_SYSCFG5072 0x0120 /* for stih407 */
+#define DAC_CFG_HD_HZUVW_OFF_MASK BIT(1)
+
+
+/* Upsampler values for the alternative 2X Filter */
+#define SAMPLER_COEF_NB 8
+#define HDA_ANA_SRC_Y_CFG_ALT_2X 0x01130000
+static u32 coef_y_alt_2x[] = {
+ 0x00FE83FB, 0x1F900401, 0x00000000, 0x00000000,
+ 0x00F408F9, 0x055F7C25, 0x00000000, 0x00000000
+};
+
+#define HDA_ANA_SRC_C_CFG_ALT_2X 0x01750004
+static u32 coef_c_alt_2x[] = {
+ 0x001305F7, 0x05274BD0, 0x00000000, 0x00000000,
+ 0x0004907C, 0x09C80B9D, 0x00000000, 0x00000000
+};
+
+/* Upsampler values for the 4X Filter */
+#define HDA_ANA_SRC_Y_CFG_4X 0x01ED0005
+#define HDA_ANA_SRC_C_CFG_4X 0x01ED0004
+static u32 coef_yc_4x[] = {
+ 0x00FC827F, 0x008FE20B, 0x00F684FC, 0x050F7C24,
+ 0x00F4857C, 0x0A1F402E, 0x00FA027F, 0x0E076E1D
+};
+
+/* AWG instructions for some video modes */
+#define AWG_MAX_INST 64
+
+/* 720p@50 */
+static u32 AWGi_720p_50[] = {
+ 0x00000971, 0x00000C26, 0x0000013B, 0x00000CDA,
+ 0x00000104, 0x00000E7E, 0x00000E7F, 0x0000013B,
+ 0x00000D8E, 0x00000104, 0x00001804, 0x00000971,
+ 0x00000C26, 0x0000003B, 0x00000FB4, 0x00000FB5,
+ 0x00000104, 0x00001AE8
+};
+
+#define NN_720p_50 ARRAY_SIZE(AWGi_720p_50)
+
+/* 720p@60 */
+static u32 AWGi_720p_60[] = {
+ 0x00000971, 0x00000C26, 0x0000013B, 0x00000CDA,
+ 0x00000104, 0x00000E7E, 0x00000E7F, 0x0000013B,
+ 0x00000C44, 0x00000104, 0x00001804, 0x00000971,
+ 0x00000C26, 0x0000003B, 0x00000F0F, 0x00000F10,
+ 0x00000104, 0x00001AE8
+};
+
+#define NN_720p_60 ARRAY_SIZE(AWGi_720p_60)
+
+/* 1080p@30 */
+static u32 AWGi_1080p_30[] = {
+ 0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+ 0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+ 0x00000C2A, 0x00000104, 0x00001804, 0x00000971,
+ 0x00000C2A, 0x0000003B, 0x00000EBE, 0x00000EBF,
+ 0x00000EBF, 0x00000104, 0x00001A2F, 0x00001C4B,
+ 0x00001C52
+};
+
+#define NN_1080p_30 ARRAY_SIZE(AWGi_1080p_30)
+
+/* 1080p@25 */
+static u32 AWGi_1080p_25[] = {
+ 0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+ 0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+ 0x00000DE2, 0x00000104, 0x00001804, 0x00000971,
+ 0x00000C2A, 0x0000003B, 0x00000F51, 0x00000F51,
+ 0x00000F52, 0x00000104, 0x00001A2F, 0x00001C4B,
+ 0x00001C52
+};
+
+#define NN_1080p_25 ARRAY_SIZE(AWGi_1080p_25)
+
+/* 1080p@24 */
+static u32 AWGi_1080p_24[] = {
+ 0x00000971, 0x00000C2A, 0x0000013B, 0x00000C56,
+ 0x00000104, 0x00000FDC, 0x00000FDD, 0x0000013B,
+ 0x00000E50, 0x00000104, 0x00001804, 0x00000971,
+ 0x00000C2A, 0x0000003B, 0x00000F76, 0x00000F76,
+ 0x00000F76, 0x00000104, 0x00001A2F, 0x00001C4B,
+ 0x00001C52
+};
+
+#define NN_1080p_24 ARRAY_SIZE(AWGi_1080p_24)
+
+/* 720x480p@60 */
+static u32 AWGi_720x480p_60[] = {
+ 0x00000904, 0x00000F18, 0x0000013B, 0x00001805,
+ 0x00000904, 0x00000C3D, 0x0000003B, 0x00001A06
+};
+
+#define NN_720x480p_60 ARRAY_SIZE(AWGi_720x480p_60)
+
+/* Video mode category */
+enum sti_hda_vid_cat {
+ VID_SD,
+ VID_ED,
+ VID_HD_74M,
+ VID_HD_148M
+};
+
+struct sti_hda_video_config {
+ struct drm_display_mode mode;
+ u32 *awg_instr;
+ int nb_instr;
+ enum sti_hda_vid_cat vid_cat;
+};
+
+/* HD analog supported modes
+ * Interlaced modes may be added when supported by the whole display chain
+ */
+static const struct sti_hda_video_config hda_supported_modes[] = {
+ /* 1080p30 74.250Mhz */
+ {{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_1080p_30, NN_1080p_30, VID_HD_74M},
+ /* 1080p30 74.176Mhz */
+ {{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74176, 1920, 2008,
+ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_1080p_30, NN_1080p_30, VID_HD_74M},
+ /* 1080p24 74.250Mhz */
+ {{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
+ 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_1080p_24, NN_1080p_24, VID_HD_74M},
+ /* 1080p24 74.176Mhz */
+ {{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74176, 1920, 2558,
+ 2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_1080p_24, NN_1080p_24, VID_HD_74M},
+ /* 1080p25 74.250Mhz */
+ {{DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+ 2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_1080p_25, NN_1080p_25, VID_HD_74M},
+ /* 720p60 74.250Mhz */
+ {{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_720p_60, NN_720p_60, VID_HD_74M},
+ /* 720p60 74.176Mhz */
+ {{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74176, 1280, 1390,
+ 1430, 1650, 0, 720, 725, 730, 750, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_720p_60, NN_720p_60, VID_HD_74M},
+ /* 720p50 74.250Mhz */
+ {{DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
+ 1760, 1980, 0, 720, 725, 730, 750, 0,
+ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC)},
+ AWGi_720p_50, NN_720p_50, VID_HD_74M},
+ /* 720x480p60 27.027Mhz */
+ {{DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27027, 720, 736,
+ 798, 858, 0, 480, 489, 495, 525, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)},
+ AWGi_720x480p_60, NN_720x480p_60, VID_ED},
+ /* 720x480p60 27.000Mhz */
+ {{DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
+ 798, 858, 0, 480, 489, 495, 525, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)},
+ AWGi_720x480p_60, NN_720x480p_60, VID_ED}
+};
+
+/**
+ * STI hd analog structure
+ *
+ * @dev: driver device
+ * @drm_dev: pointer to drm device
+ * @mode: current display mode selected
+ * @regs: HD analog register
+ * @video_dacs_ctrl: video DACS control register
+ * @enabled: true if HD analog is enabled else false
+ */
+struct sti_hda {
+ struct device dev;
+ struct drm_device *drm_dev;
+ struct drm_display_mode mode;
+ void __iomem *regs;
+ void __iomem *video_dacs_ctrl;
+ struct clk *clk_pix;
+ struct clk *clk_hddac;
+ bool enabled;
+};
+
+struct sti_hda_connector {
+ struct drm_connector drm_connector;
+ struct drm_encoder *encoder;
+ struct sti_hda *hda;
+};
+
+#define to_sti_hda_connector(x) \
+ container_of(x, struct sti_hda_connector, drm_connector)
+
+static u32 hda_read(struct sti_hda *hda, int offset)
+{
+ return readl(hda->regs + offset);
+}
+
+static void hda_write(struct sti_hda *hda, u32 val, int offset)
+{
+ writel(val, hda->regs + offset);
+}
+
+/**
+ * Search for a video mode in the supported modes table
+ *
+ * @mode: mode being searched
+ * @idx: index of the found mode
+ *
+ * Return true if mode is found
+ */
+static bool hda_get_mode_idx(struct drm_display_mode mode, int *idx)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(hda_supported_modes); i++)
+ if (drm_mode_equal(&hda_supported_modes[i].mode, &mode)) {
+ *idx = i;
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Enable the HD DACS
+ *
+ * @hda: pointer to HD analog structure
+ * @enable: true if HD DACS need to be enabled, else false
+ */
+static void hda_enable_hd_dacs(struct sti_hda *hda, bool enable)
+{
+ u32 mask;
+
+ if (hda->video_dacs_ctrl) {
+ u32 val;
+
+ switch ((u32)hda->video_dacs_ctrl & VIDEO_DACS_CONTROL_MASK) {
+ case VIDEO_DACS_CONTROL_SYSCFG2535:
+ mask = DAC_CFG_HD_OFF_MASK;
+ break;
+ case VIDEO_DACS_CONTROL_SYSCFG5072:
+ mask = DAC_CFG_HD_HZUVW_OFF_MASK;
+ break;
+ default:
+ DRM_INFO("Video DACS control register not supported!");
+ return;
+ }
+
+ val = readl(hda->video_dacs_ctrl);
+ if (enable)
+ val &= ~mask;
+ else
+ val |= mask;
+
+ writel(val, hda->video_dacs_ctrl);
+ }
+}
+
+/**
+ * Configure AWG, writing instructions
+ *
+ * @hda: pointer to HD analog structure
+ * @awg_instr: pointer to AWG instructions table
+ * @nb: nb of AWG instructions
+ */
+static void sti_hda_configure_awg(struct sti_hda *hda, u32 *awg_instr, int nb)
+{
+ unsigned int i;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ for (i = 0; i < nb; i++)
+ hda_write(hda, awg_instr[i], HDA_SYNC_AWGI + i * 4);
+ for (i = nb; i < AWG_MAX_INST; i++)
+ hda_write(hda, 0, HDA_SYNC_AWGI + i * 4);
+}
+
+static void sti_hda_disable(struct drm_bridge *bridge)
+{
+ struct sti_hda *hda = bridge->driver_private;
+ u32 val;
+
+ if (!hda->enabled)
+ return;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Disable HD DAC and AWG */
+ val = hda_read(hda, HDA_ANA_CFG);
+ val &= ~CFG_AWG_ASYNC_EN;
+ hda_write(hda, val, HDA_ANA_CFG);
+ hda_write(hda, 0, HDA_ANA_ANC_CTRL);
+
+ hda_enable_hd_dacs(hda, false);
+
+ /* Disable/unprepare hda clock */
+ clk_disable_unprepare(hda->clk_hddac);
+ clk_disable_unprepare(hda->clk_pix);
+
+ hda->enabled = false;
+}
+
+static void sti_hda_pre_enable(struct drm_bridge *bridge)
+{
+ struct sti_hda *hda = bridge->driver_private;
+ u32 val, i, mode_idx;
+ u32 src_filter_y, src_filter_c;
+ u32 *coef_y, *coef_c;
+ u32 filter_mode;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (hda->enabled)
+ return;
+
+ /* Prepare/enable clocks */
+ if (clk_prepare_enable(hda->clk_pix))
+ DRM_ERROR("Failed to prepare/enable hda_pix clk\n");
+ if (clk_prepare_enable(hda->clk_hddac))
+ DRM_ERROR("Failed to prepare/enable hda_hddac clk\n");
+
+ if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
+ DRM_ERROR("Undefined mode\n");
+ return;
+ }
+
+ switch (hda_supported_modes[mode_idx].vid_cat) {
+ case VID_HD_148M:
+ DRM_ERROR("Beyond HD analog capabilities\n");
+ return;
+ case VID_HD_74M:
+ /* HD use alternate 2x filter */
+ filter_mode = CFG_AWG_FLTR_MODE_HD;
+ src_filter_y = HDA_ANA_SRC_Y_CFG_ALT_2X;
+ src_filter_c = HDA_ANA_SRC_C_CFG_ALT_2X;
+ coef_y = coef_y_alt_2x;
+ coef_c = coef_c_alt_2x;
+ break;
+ case VID_ED:
+ /* ED uses 4x filter */
+ filter_mode = CFG_AWG_FLTR_MODE_ED;
+ src_filter_y = HDA_ANA_SRC_Y_CFG_4X;
+ src_filter_c = HDA_ANA_SRC_C_CFG_4X;
+ coef_y = coef_yc_4x;
+ coef_c = coef_yc_4x;
+ break;
+ case VID_SD:
+ DRM_ERROR("Not supported\n");
+ return;
+ default:
+ DRM_ERROR("Undefined resolution\n");
+ return;
+ }
+ DRM_DEBUG_DRIVER("Using HDA mode #%d\n", mode_idx);
+
+ /* Enable HD Video DACs */
+ hda_enable_hd_dacs(hda, true);
+
+ /* Configure scaler */
+ hda_write(hda, SCALE_CTRL_Y_DFLT, HDA_ANA_SCALE_CTRL_Y);
+ hda_write(hda, SCALE_CTRL_CB_DFLT, HDA_ANA_SCALE_CTRL_CB);
+ hda_write(hda, SCALE_CTRL_CR_DFLT, HDA_ANA_SCALE_CTRL_CR);
+
+ /* Configure sampler */
+ hda_write(hda , src_filter_y, HDA_ANA_SRC_Y_CFG);
+ hda_write(hda, src_filter_c, HDA_ANA_SRC_C_CFG);
+ for (i = 0; i < SAMPLER_COEF_NB; i++) {
+ hda_write(hda, coef_y[i], HDA_COEFF_Y_PH1_TAP123 + i * 4);
+ hda_write(hda, coef_c[i], HDA_COEFF_C_PH1_TAP123 + i * 4);
+ }
+
+ /* Configure main HDFormatter */
+ val = 0;
+ val |= (hda->mode.flags & DRM_MODE_FLAG_INTERLACE) ?
+ 0 : CFG_AWG_ASYNC_VSYNC_MTD;
+ val |= (CFG_PBPR_SYNC_OFF_VAL << CFG_PBPR_SYNC_OFF_SHIFT);
+ val |= filter_mode;
+ hda_write(hda, val, HDA_ANA_CFG);
+
+ /* Configure AWG */
+ sti_hda_configure_awg(hda, hda_supported_modes[mode_idx].awg_instr,
+ hda_supported_modes[mode_idx].nb_instr);
+
+ /* Enable AWG */
+ val = hda_read(hda, HDA_ANA_CFG);
+ val |= CFG_AWG_ASYNC_EN;
+ hda_write(hda, val, HDA_ANA_CFG);
+
+ hda->enabled = true;
+}
+
+static void sti_hda_set_mode(struct drm_bridge *bridge,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct sti_hda *hda = bridge->driver_private;
+ u32 mode_idx;
+ int hddac_rate;
+ int ret;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ memcpy(&hda->mode, mode, sizeof(struct drm_display_mode));
+
+ if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
+ DRM_ERROR("Undefined mode\n");
+ return;
+ }
+
+ switch (hda_supported_modes[mode_idx].vid_cat) {
+ case VID_HD_74M:
+ /* HD use alternate 2x filter */
+ hddac_rate = mode->clock * 1000 * 2;
+ break;
+ case VID_ED:
+ /* ED uses 4x filter */
+ hddac_rate = mode->clock * 1000 * 4;
+ break;
+ default:
+ DRM_ERROR("Undefined mode\n");
+ return;
+ }
+
+ /* HD DAC = 148.5Mhz or 108 Mhz */
+ ret = clk_set_rate(hda->clk_hddac, hddac_rate);
+ if (ret < 0)
+ DRM_ERROR("Cannot set rate (%dHz) for hda_hddac clk\n",
+ hddac_rate);
+
+ /* HDformatter clock = compositor clock */
+ ret = clk_set_rate(hda->clk_pix, mode->clock * 1000);
+ if (ret < 0)
+ DRM_ERROR("Cannot set rate (%dHz) for hda_pix clk\n",
+ mode->clock * 1000);
+}
+
+static void sti_hda_bridge_nope(struct drm_bridge *bridge)
+{
+ /* do nothing */
+}
+
+static void sti_hda_brigde_destroy(struct drm_bridge *bridge)
+{
+ drm_bridge_cleanup(bridge);
+ kfree(bridge);
+}
+
+static const struct drm_bridge_funcs sti_hda_bridge_funcs = {
+ .pre_enable = sti_hda_pre_enable,
+ .enable = sti_hda_bridge_nope,
+ .disable = sti_hda_disable,
+ .post_disable = sti_hda_bridge_nope,
+ .mode_set = sti_hda_set_mode,
+ .destroy = sti_hda_brigde_destroy,
+};
+
+static int sti_hda_connector_get_modes(struct drm_connector *connector)
+{
+ unsigned int i;
+ int count = 0;
+ struct sti_hda_connector *hda_connector
+ = to_sti_hda_connector(connector);
+ struct sti_hda *hda = hda_connector->hda;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ for (i = 0; i < ARRAY_SIZE(hda_supported_modes); i++) {
+ struct drm_display_mode *mode =
+ drm_mode_duplicate(hda->drm_dev,
+ &hda_supported_modes[i].mode);
+ if (!mode)
+ continue;
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ /* the first mode is the preferred mode */
+ if (i == 0)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+ count++;
+ }
+
+ drm_mode_sort(&connector->modes);
+
+ return count;
+}
+
+#define CLK_TOLERANCE_HZ 50
+
+static int sti_hda_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ int target = mode->clock * 1000;
+ int target_min = target - CLK_TOLERANCE_HZ;
+ int target_max = target + CLK_TOLERANCE_HZ;
+ int result;
+ int idx;
+ struct sti_hda_connector *hda_connector
+ = to_sti_hda_connector(connector);
+ struct sti_hda *hda = hda_connector->hda;
+
+ if (!hda_get_mode_idx(*mode, &idx)) {
+ return MODE_BAD;
+ } else {
+ result = clk_round_rate(hda->clk_pix, target);
+
+ DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
+ target, result);
+
+ if ((result < target_min) || (result > target_max)) {
+ DRM_DEBUG_DRIVER("hda pixclk=%d not supported\n",
+ target);
+ return MODE_BAD;
+ }
+ }
+
+ return MODE_OK;
+}
+
+struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
+{
+ struct sti_hda_connector *hda_connector
+ = to_sti_hda_connector(connector);
+
+ /* Best encoder is the one associated during connector creation */
+ return hda_connector->encoder;
+}
+
+static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
+ .get_modes = sti_hda_connector_get_modes,
+ .mode_valid = sti_hda_connector_mode_valid,
+ .best_encoder = sti_hda_best_encoder,
+};
+
+static enum drm_connector_status
+sti_hda_connector_detect(struct drm_connector *connector, bool force)
+{
+ return connector_status_connected;
+}
+
+static void sti_hda_connector_destroy(struct drm_connector *connector)
+{
+ struct sti_hda_connector *hda_connector
+ = to_sti_hda_connector(connector);
+
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+ kfree(hda_connector);
+}
+
+static struct drm_connector_funcs sti_hda_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = sti_hda_connector_detect,
+ .destroy = sti_hda_connector_destroy,
+};
+
+static struct drm_encoder *sti_hda_find_encoder(struct drm_device *dev)
+{
+ struct drm_encoder *encoder;
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
+ return encoder;
+ }
+
+ return NULL;
+}
+
+static int sti_hda_bind(struct device *dev, struct device *master, void *data)
+{
+ struct sti_hda *hda = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = data;
+ struct drm_encoder *encoder;
+ struct sti_hda_connector *connector;
+ struct drm_connector *drm_connector;
+ struct drm_bridge *bridge;
+ int err;
+
+ /* Set the drm device handle */
+ hda->drm_dev = drm_dev;
+
+ encoder = sti_hda_find_encoder(drm_dev);
+ if (!encoder)
+ return -ENOMEM;
+
+ connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
+ if (!connector)
+ return -ENOMEM;
+
+ connector->hda = hda;
+
+ bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
+ if (!bridge)
+ return -ENOMEM;
+
+ bridge->driver_private = hda;
+ drm_bridge_init(drm_dev, bridge, &sti_hda_bridge_funcs);
+
+ encoder->bridge = bridge;
+ connector->encoder = encoder;
+
+ drm_connector = (struct drm_connector *)connector;
+
+ drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+ drm_connector_init(drm_dev, drm_connector,
+ &sti_hda_connector_funcs, DRM_MODE_CONNECTOR_Component);
+ drm_connector_helper_add(drm_connector,
+ &sti_hda_connector_helper_funcs);
+
+ err = drm_connector_register(drm_connector);
+ if (err)
+ goto err_connector;
+
+ err = drm_mode_connector_attach_encoder(drm_connector, encoder);
+ if (err) {
+ DRM_ERROR("Failed to attach a connector to a encoder\n");
+ goto err_sysfs;
+ }
+
+ return 0;
+
+err_sysfs:
+ drm_connector_unregister(drm_connector);
+err_connector:
+ drm_bridge_cleanup(bridge);
+ drm_connector_cleanup(drm_connector);
+ return -EINVAL;
+}
+
+static void sti_hda_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ /* do nothing */
+}
+
+static const struct component_ops sti_hda_ops = {
+ .bind = sti_hda_bind,
+ .unbind = sti_hda_unbind,
+};
+
+static int sti_hda_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sti_hda *hda;
+ struct resource *res;
+
+ DRM_INFO("%s\n", __func__);
+
+ hda = devm_kzalloc(dev, sizeof(*hda), GFP_KERNEL);
+ if (!hda)
+ return -ENOMEM;
+
+ hda->dev = pdev->dev;
+
+ /* Get resources */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hda-reg");
+ if (!res) {
+ DRM_ERROR("Invalid hda resource\n");
+ return -ENOMEM;
+ }
+ hda->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+ if (IS_ERR(hda->regs))
+ return PTR_ERR(hda->regs);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "video-dacs-ctrl");
+ if (res) {
+ hda->video_dacs_ctrl = devm_ioremap_nocache(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(hda->video_dacs_ctrl))
+ return PTR_ERR(hda->video_dacs_ctrl);
+ } else {
+ /* If no existing video-dacs-ctrl resource continue the probe */
+ DRM_DEBUG_DRIVER("No video-dacs-ctrl resource\n");
+ hda->video_dacs_ctrl = NULL;
+ }
+
+ /* Get clock resources */
+ hda->clk_pix = devm_clk_get(dev, "pix");
+ if (IS_ERR(hda->clk_pix)) {
+ DRM_ERROR("Cannot get hda_pix clock\n");
+ return PTR_ERR(hda->clk_pix);
+ }
+
+ hda->clk_hddac = devm_clk_get(dev, "hddac");
+ if (IS_ERR(hda->clk_hddac)) {
+ DRM_ERROR("Cannot get hda_hddac clock\n");
+ return PTR_ERR(hda->clk_hddac);
+ }
+
+ platform_set_drvdata(pdev, hda);
+
+ return component_add(&pdev->dev, &sti_hda_ops);
+}
+
+static int sti_hda_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sti_hda_ops);
+ return 0;
+}
+
+static struct of_device_id hda_of_match[] = {
+ { .compatible = "st,stih416-hda", },
+ { .compatible = "st,stih407-hda", },
+ { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, hda_of_match);
+
+struct platform_driver sti_hda_driver = {
+ .driver = {
+ .name = "sti-hda",
+ .owner = THIS_MODULE,
+ .of_match_table = hda_of_match,
+ },
+ .probe = sti_hda_probe,
+ .remove = sti_hda_remove,
+};
+
+module_platform_driver(sti_hda_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
new file mode 100644
index 000000000000..284e541d970d
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/hdmi.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+
+#include "sti_hdmi.h"
+#include "sti_hdmi_tx3g4c28phy.h"
+#include "sti_hdmi_tx3g0c55phy.h"
+#include "sti_vtg.h"
+
+#define HDMI_CFG 0x0000
+#define HDMI_INT_EN 0x0004
+#define HDMI_INT_STA 0x0008
+#define HDMI_INT_CLR 0x000C
+#define HDMI_STA 0x0010
+#define HDMI_ACTIVE_VID_XMIN 0x0100
+#define HDMI_ACTIVE_VID_XMAX 0x0104
+#define HDMI_ACTIVE_VID_YMIN 0x0108
+#define HDMI_ACTIVE_VID_YMAX 0x010C
+#define HDMI_DFLT_CHL0_DAT 0x0110
+#define HDMI_DFLT_CHL1_DAT 0x0114
+#define HDMI_DFLT_CHL2_DAT 0x0118
+#define HDMI_SW_DI_1_HEAD_WORD 0x0210
+#define HDMI_SW_DI_1_PKT_WORD0 0x0214
+#define HDMI_SW_DI_1_PKT_WORD1 0x0218
+#define HDMI_SW_DI_1_PKT_WORD2 0x021C
+#define HDMI_SW_DI_1_PKT_WORD3 0x0220
+#define HDMI_SW_DI_1_PKT_WORD4 0x0224
+#define HDMI_SW_DI_1_PKT_WORD5 0x0228
+#define HDMI_SW_DI_1_PKT_WORD6 0x022C
+#define HDMI_SW_DI_CFG 0x0230
+
+#define HDMI_IFRAME_SLOT_AVI 1
+
+#define XCAT(prefix, x, suffix) prefix ## x ## suffix
+#define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
+#define HDMI_SW_DI_N_PKT_WORD0(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD0)
+#define HDMI_SW_DI_N_PKT_WORD1(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD1)
+#define HDMI_SW_DI_N_PKT_WORD2(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD2)
+#define HDMI_SW_DI_N_PKT_WORD3(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD3)
+#define HDMI_SW_DI_N_PKT_WORD4(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD4)
+#define HDMI_SW_DI_N_PKT_WORD5(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD5)
+#define HDMI_SW_DI_N_PKT_WORD6(x) XCAT(HDMI_SW_DI_, x, _PKT_WORD6)
+
+#define HDMI_IFRAME_DISABLED 0x0
+#define HDMI_IFRAME_SINGLE_SHOT 0x1
+#define HDMI_IFRAME_FIELD 0x2
+#define HDMI_IFRAME_FRAME 0x3
+#define HDMI_IFRAME_MASK 0x3
+#define HDMI_IFRAME_CFG_DI_N(x, n) ((x) << ((n-1)*4)) /* n from 1 to 6 */
+
+#define HDMI_CFG_DEVICE_EN BIT(0)
+#define HDMI_CFG_HDMI_NOT_DVI BIT(1)
+#define HDMI_CFG_HDCP_EN BIT(2)
+#define HDMI_CFG_ESS_NOT_OESS BIT(3)
+#define HDMI_CFG_H_SYNC_POL_NEG BIT(4)
+#define HDMI_CFG_SINK_TERM_DET_EN BIT(5)
+#define HDMI_CFG_V_SYNC_POL_NEG BIT(6)
+#define HDMI_CFG_422_EN BIT(8)
+#define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12)
+#define HDMI_CFG_FIFO_UNDERRUN_CLR BIT(13)
+#define HDMI_CFG_SW_RST_EN BIT(31)
+
+#define HDMI_INT_GLOBAL BIT(0)
+#define HDMI_INT_SW_RST BIT(1)
+#define HDMI_INT_PIX_CAP BIT(3)
+#define HDMI_INT_HOT_PLUG BIT(4)
+#define HDMI_INT_DLL_LCK BIT(5)
+#define HDMI_INT_NEW_FRAME BIT(6)
+#define HDMI_INT_GENCTRL_PKT BIT(7)
+#define HDMI_INT_SINK_TERM_PRESENT BIT(11)
+
+#define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
+ | HDMI_INT_DLL_LCK \
+ | HDMI_INT_HOT_PLUG \
+ | HDMI_INT_GLOBAL)
+
+#define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
+ | HDMI_INT_GENCTRL_PKT \
+ | HDMI_INT_NEW_FRAME \
+ | HDMI_INT_DLL_LCK \
+ | HDMI_INT_HOT_PLUG \
+ | HDMI_INT_PIX_CAP \
+ | HDMI_INT_SW_RST \
+ | HDMI_INT_GLOBAL)
+
+#define HDMI_STA_SW_RST BIT(1)
+
+struct sti_hdmi_connector {
+ struct drm_connector drm_connector;
+ struct drm_encoder *encoder;
+ struct sti_hdmi *hdmi;
+};
+
+#define to_sti_hdmi_connector(x) \
+ container_of(x, struct sti_hdmi_connector, drm_connector)
+
+u32 hdmi_read(struct sti_hdmi *hdmi, int offset)
+{
+ return readl(hdmi->regs + offset);
+}
+
+void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset)
+{
+ writel(val, hdmi->regs + offset);
+}
+
+/**
+ * HDMI interrupt handler threaded
+ *
+ * @irq: irq number
+ * @arg: connector structure
+ */
+static irqreturn_t hdmi_irq_thread(int irq, void *arg)
+{
+ struct sti_hdmi *hdmi = arg;
+
+ /* Hot plug/unplug IRQ */
+ if (hdmi->irq_status & HDMI_INT_HOT_PLUG) {
+ /* read gpio to get the status */
+ hdmi->hpd = gpio_get_value(hdmi->hpd_gpio);
+ if (hdmi->drm_dev)
+ drm_helper_hpd_irq_event(hdmi->drm_dev);
+ }
+
+ /* Sw reset and PLL lock are exclusive so we can use the same
+ * event to signal them
+ */
+ if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {
+ hdmi->event_received = true;
+ wake_up_interruptible(&hdmi->wait_event);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * HDMI interrupt handler
+ *
+ * @irq: irq number
+ * @arg: connector structure
+ */
+static irqreturn_t hdmi_irq(int irq, void *arg)
+{
+ struct sti_hdmi *hdmi = arg;
+
+ /* read interrupt status */
+ hdmi->irq_status = hdmi_read(hdmi, HDMI_INT_STA);
+
+ /* clear interrupt status */
+ hdmi_write(hdmi, hdmi->irq_status, HDMI_INT_CLR);
+
+ /* force sync bus write */
+ hdmi_read(hdmi, HDMI_INT_STA);
+
+ return IRQ_WAKE_THREAD;
+}
+
+/**
+ * Set hdmi active area depending on the drm display mode selected
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void hdmi_active_area(struct sti_hdmi *hdmi)
+{
+ u32 xmin, xmax;
+ u32 ymin, ymax;
+
+ xmin = sti_vtg_get_pixel_number(hdmi->mode, 0);
+ xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay - 1);
+ ymin = sti_vtg_get_line_number(hdmi->mode, 0);
+ ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1);
+
+ hdmi_write(hdmi, xmin, HDMI_ACTIVE_VID_XMIN);
+ hdmi_write(hdmi, xmax, HDMI_ACTIVE_VID_XMAX);
+ hdmi_write(hdmi, ymin, HDMI_ACTIVE_VID_YMIN);
+ hdmi_write(hdmi, ymax, HDMI_ACTIVE_VID_YMAX);
+}
+
+/**
+ * Overall hdmi configuration
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void hdmi_config(struct sti_hdmi *hdmi)
+{
+ u32 conf;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Clear overrun and underrun fifo */
+ conf = HDMI_CFG_FIFO_OVERRUN_CLR | HDMI_CFG_FIFO_UNDERRUN_CLR;
+
+ /* Enable HDMI mode not DVI */
+ conf |= HDMI_CFG_HDMI_NOT_DVI | HDMI_CFG_ESS_NOT_OESS;
+
+ /* Enable sink term detection */
+ conf |= HDMI_CFG_SINK_TERM_DET_EN;
+
+ /* Set Hsync polarity */
+ if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
+ DRM_DEBUG_DRIVER("H Sync Negative\n");
+ conf |= HDMI_CFG_H_SYNC_POL_NEG;
+ }
+
+ /* Set Vsync polarity */
+ if (hdmi->mode.flags & DRM_MODE_FLAG_NVSYNC) {
+ DRM_DEBUG_DRIVER("V Sync Negative\n");
+ conf |= HDMI_CFG_V_SYNC_POL_NEG;
+ }
+
+ /* Enable HDMI */
+ conf |= HDMI_CFG_DEVICE_EN;
+
+ hdmi_write(hdmi, conf, HDMI_CFG);
+}
+
+/**
+ * Prepare and configure the AVI infoframe
+ *
+ * AVI infoframe are transmitted at least once per two video field and
+ * contains information about HDMI transmission mode such as color space,
+ * colorimetry, ...
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return negative value if error occurs
+ */
+static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
+{
+ struct drm_display_mode *mode = &hdmi->mode;
+ struct hdmi_avi_infoframe infoframe;
+ u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
+ u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE;
+ u32 val;
+ int ret;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
+ if (ret < 0) {
+ DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
+ return ret;
+ }
+
+ /* fixed infoframe configuration not linked to the mode */
+ infoframe.colorspace = HDMI_COLORSPACE_RGB;
+ infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
+ infoframe.colorimetry = HDMI_COLORIMETRY_NONE;
+
+ ret = hdmi_avi_infoframe_pack(&infoframe, buffer, sizeof(buffer));
+ if (ret < 0) {
+ DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
+ return ret;
+ }
+
+ /* Disable transmission slot for AVI infoframe */
+ val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
+ val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, HDMI_IFRAME_SLOT_AVI);
+ hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
+
+ /* Infoframe header */
+ val = buffer[0x0];
+ val |= buffer[0x1] << 8;
+ val |= buffer[0x2] << 16;
+ hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI));
+
+ /* Infoframe packet bytes */
+ val = frame[0x0];
+ val |= frame[0x1] << 8;
+ val |= frame[0x2] << 16;
+ val |= frame[0x3] << 24;
+ hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI));
+
+ val = frame[0x4];
+ val |= frame[0x5] << 8;
+ val |= frame[0x6] << 16;
+ val |= frame[0x7] << 24;
+ hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI));
+
+ val = frame[0x8];
+ val |= frame[0x9] << 8;
+ val |= frame[0xA] << 16;
+ val |= frame[0xB] << 24;
+ hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI));
+
+ val = frame[0xC];
+ val |= frame[0xD] << 8;
+ hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI));
+
+ /* Enable transmission slot for AVI infoframe
+ * According to the hdmi specification, AVI infoframe should be
+ * transmitted at least once per two video fields
+ */
+ val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
+ val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI);
+ hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
+
+ return 0;
+}
+
+/**
+ * Software reset of the hdmi subsystem
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ */
+#define HDMI_TIMEOUT_SWRESET 100 /*milliseconds */
+static void hdmi_swreset(struct sti_hdmi *hdmi)
+{
+ u32 val;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Enable hdmi_audio clock only during hdmi reset */
+ if (clk_prepare_enable(hdmi->clk_audio))
+ DRM_INFO("Failed to prepare/enable hdmi_audio clk\n");
+
+ /* Sw reset */
+ hdmi->event_received = false;
+
+ val = hdmi_read(hdmi, HDMI_CFG);
+ val |= HDMI_CFG_SW_RST_EN;
+ hdmi_write(hdmi, val, HDMI_CFG);
+
+ /* Wait reset completed */
+ wait_event_interruptible_timeout(hdmi->wait_event,
+ hdmi->event_received == true,
+ msecs_to_jiffies
+ (HDMI_TIMEOUT_SWRESET));
+
+ /*
+ * HDMI_STA_SW_RST bit is set to '1' when SW_RST bit in HDMI_CFG is
+ * set to '1' and clk_audio is running.
+ */
+ if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_SW_RST) == 0)
+ DRM_DEBUG_DRIVER("Warning: HDMI sw reset timeout occurs\n");
+
+ val = hdmi_read(hdmi, HDMI_CFG);
+ val &= ~HDMI_CFG_SW_RST_EN;
+ hdmi_write(hdmi, val, HDMI_CFG);
+
+ /* Disable hdmi_audio clock. Not used anymore for drm purpose */
+ clk_disable_unprepare(hdmi->clk_audio);
+}
+
+static void sti_hdmi_disable(struct drm_bridge *bridge)
+{
+ struct sti_hdmi *hdmi = bridge->driver_private;
+
+ u32 val = hdmi_read(hdmi, HDMI_CFG);
+
+ if (!hdmi->enabled)
+ return;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Disable HDMI */
+ val &= ~HDMI_CFG_DEVICE_EN;
+ hdmi_write(hdmi, val, HDMI_CFG);
+
+ hdmi_write(hdmi, 0xffffffff, HDMI_INT_CLR);
+
+ /* Stop the phy */
+ hdmi->phy_ops->stop(hdmi);
+
+ /* Set the default channel data to be a dark red */
+ hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);
+ hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL1_DAT);
+ hdmi_write(hdmi, 0x0060, HDMI_DFLT_CHL2_DAT);
+
+ /* Disable/unprepare hdmi clock */
+ clk_disable_unprepare(hdmi->clk_phy);
+ clk_disable_unprepare(hdmi->clk_tmds);
+ clk_disable_unprepare(hdmi->clk_pix);
+
+ hdmi->enabled = false;
+}
+
+static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
+{
+ struct sti_hdmi *hdmi = bridge->driver_private;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (hdmi->enabled)
+ return;
+
+ /* Prepare/enable clocks */
+ if (clk_prepare_enable(hdmi->clk_pix))
+ DRM_ERROR("Failed to prepare/enable hdmi_pix clk\n");
+ if (clk_prepare_enable(hdmi->clk_tmds))
+ DRM_ERROR("Failed to prepare/enable hdmi_tmds clk\n");
+ if (clk_prepare_enable(hdmi->clk_phy))
+ DRM_ERROR("Failed to prepare/enable hdmi_rejec_pll clk\n");
+
+ hdmi->enabled = true;
+
+ /* Program hdmi serializer and start phy */
+ if (!hdmi->phy_ops->start(hdmi)) {
+ DRM_ERROR("Unable to start hdmi phy\n");
+ return;
+ }
+
+ /* Program hdmi active area */
+ hdmi_active_area(hdmi);
+
+ /* Enable working interrupts */
+ hdmi_write(hdmi, HDMI_WORKING_INT, HDMI_INT_EN);
+
+ /* Program hdmi config */
+ hdmi_config(hdmi);
+
+ /* Program AVI infoframe */
+ if (hdmi_avi_infoframe_config(hdmi))
+ DRM_ERROR("Unable to configure AVI infoframe\n");
+
+ /* Sw reset */
+ hdmi_swreset(hdmi);
+}
+
+static void sti_hdmi_set_mode(struct drm_bridge *bridge,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct sti_hdmi *hdmi = bridge->driver_private;
+ int ret;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Copy the drm display mode in the connector local structure */
+ memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
+
+ /* Update clock framerate according to the selected mode */
+ ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
+ if (ret < 0) {
+ DRM_ERROR("Cannot set rate (%dHz) for hdmi_pix clk\n",
+ mode->clock * 1000);
+ return;
+ }
+ ret = clk_set_rate(hdmi->clk_phy, mode->clock * 1000);
+ if (ret < 0) {
+ DRM_ERROR("Cannot set rate (%dHz) for hdmi_rejection_pll clk\n",
+ mode->clock * 1000);
+ return;
+ }
+}
+
+static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
+{
+ /* do nothing */
+}
+
+static void sti_hdmi_brigde_destroy(struct drm_bridge *bridge)
+{
+ drm_bridge_cleanup(bridge);
+ kfree(bridge);
+}
+
+static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
+ .pre_enable = sti_hdmi_pre_enable,
+ .enable = sti_hdmi_bridge_nope,
+ .disable = sti_hdmi_disable,
+ .post_disable = sti_hdmi_bridge_nope,
+ .mode_set = sti_hdmi_set_mode,
+ .destroy = sti_hdmi_brigde_destroy,
+};
+
+static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+ struct i2c_adapter *i2c_adap;
+ struct edid *edid;
+ int count;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ i2c_adap = i2c_get_adapter(1);
+ if (!i2c_adap)
+ goto fail;
+
+ edid = drm_get_edid(connector, i2c_adap);
+ if (!edid)
+ goto fail;
+
+ count = drm_add_edid_modes(connector, edid);
+ drm_mode_connector_update_edid_property(connector, edid);
+
+ kfree(edid);
+ return count;
+
+fail:
+ DRM_ERROR("Can not read HDMI EDID\n");
+ return 0;
+}
+
+#define CLK_TOLERANCE_HZ 50
+
+static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ int target = mode->clock * 1000;
+ int target_min = target - CLK_TOLERANCE_HZ;
+ int target_max = target + CLK_TOLERANCE_HZ;
+ int result;
+ struct sti_hdmi_connector *hdmi_connector
+ = to_sti_hdmi_connector(connector);
+ struct sti_hdmi *hdmi = hdmi_connector->hdmi;
+
+
+ result = clk_round_rate(hdmi->clk_pix, target);
+
+ DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
+ target, result);
+
+ if ((result < target_min) || (result > target_max)) {
+ DRM_DEBUG_DRIVER("hdmi pixclk=%d not supported\n", target);
+ return MODE_BAD;
+ }
+
+ return MODE_OK;
+}
+
+struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
+{
+ struct sti_hdmi_connector *hdmi_connector
+ = to_sti_hdmi_connector(connector);
+
+ /* Best encoder is the one associated during connector creation */
+ return hdmi_connector->encoder;
+}
+
+static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
+ .get_modes = sti_hdmi_connector_get_modes,
+ .mode_valid = sti_hdmi_connector_mode_valid,
+ .best_encoder = sti_hdmi_best_encoder,
+};
+
+/* get detection status of display device */
+static enum drm_connector_status
+sti_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct sti_hdmi_connector *hdmi_connector
+ = to_sti_hdmi_connector(connector);
+ struct sti_hdmi *hdmi = hdmi_connector->hdmi;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (hdmi->hpd) {
+ DRM_DEBUG_DRIVER("hdmi cable connected\n");
+ return connector_status_connected;
+ }
+
+ DRM_DEBUG_DRIVER("hdmi cable disconnected\n");
+ return connector_status_disconnected;
+}
+
+static void sti_hdmi_connector_destroy(struct drm_connector *connector)
+{
+ struct sti_hdmi_connector *hdmi_connector
+ = to_sti_hdmi_connector(connector);
+
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+ kfree(hdmi_connector);
+}
+
+static struct drm_connector_funcs sti_hdmi_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = sti_hdmi_connector_detect,
+ .destroy = sti_hdmi_connector_destroy,
+};
+
+static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
+{
+ struct drm_encoder *encoder;
+
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
+ return encoder;
+ }
+
+ return NULL;
+}
+
+static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+ struct sti_hdmi *hdmi = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = data;
+ struct drm_encoder *encoder;
+ struct sti_hdmi_connector *connector;
+ struct drm_connector *drm_connector;
+ struct drm_bridge *bridge;
+ struct i2c_adapter *i2c_adap;
+ int err;
+
+ i2c_adap = i2c_get_adapter(1);
+ if (!i2c_adap)
+ return -EPROBE_DEFER;
+
+ /* Set the drm device handle */
+ hdmi->drm_dev = drm_dev;
+
+ encoder = sti_hdmi_find_encoder(drm_dev);
+ if (!encoder)
+ return -ENOMEM;
+
+ connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
+ if (!connector)
+ return -ENOMEM;
+
+ connector->hdmi = hdmi;
+
+ bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
+ if (!bridge)
+ return -ENOMEM;
+
+ bridge->driver_private = hdmi;
+ drm_bridge_init(drm_dev, bridge, &sti_hdmi_bridge_funcs);
+
+ encoder->bridge = bridge;
+ connector->encoder = encoder;
+
+ drm_connector = (struct drm_connector *)connector;
+
+ drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+ drm_connector_init(drm_dev, drm_connector,
+ &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_helper_add(drm_connector,
+ &sti_hdmi_connector_helper_funcs);
+
+ err = drm_connector_register(drm_connector);
+ if (err)
+ goto err_connector;
+
+ err = drm_mode_connector_attach_encoder(drm_connector, encoder);
+ if (err) {
+ DRM_ERROR("Failed to attach a connector to a encoder\n");
+ goto err_sysfs;
+ }
+
+ /* Enable default interrupts */
+ hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);
+
+ return 0;
+
+err_sysfs:
+ drm_connector_unregister(drm_connector);
+err_connector:
+ drm_bridge_cleanup(bridge);
+ drm_connector_cleanup(drm_connector);
+ return -EINVAL;
+}
+
+static void sti_hdmi_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ /* do nothing */
+}
+
+static const struct component_ops sti_hdmi_ops = {
+ .bind = sti_hdmi_bind,
+ .unbind = sti_hdmi_unbind,
+};
+
+static struct of_device_id hdmi_of_match[] = {
+ {
+ .compatible = "st,stih416-hdmi",
+ .data = &tx3g0c55phy_ops,
+ }, {
+ .compatible = "st,stih407-hdmi",
+ .data = &tx3g4c28phy_ops,
+ }, {
+ /* end node */
+ }
+};
+MODULE_DEVICE_TABLE(of, hdmi_of_match);
+
+static int sti_hdmi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sti_hdmi *hdmi;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ int ret;
+
+ DRM_INFO("%s\n", __func__);
+
+ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ hdmi->dev = pdev->dev;
+
+ /* Get resources */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
+ if (!res) {
+ DRM_ERROR("Invalid hdmi resource\n");
+ return -ENOMEM;
+ }
+ hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+ if (IS_ERR(hdmi->regs))
+ return PTR_ERR(hdmi->regs);
+
+ if (of_device_is_compatible(np, "st,stih416-hdmi")) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "syscfg");
+ if (!res) {
+ DRM_ERROR("Invalid syscfg resource\n");
+ return -ENOMEM;
+ }
+ hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(hdmi->syscfg))
+ return PTR_ERR(hdmi->syscfg);
+
+ }
+
+ hdmi->phy_ops = (struct hdmi_phy_ops *)
+ of_match_node(hdmi_of_match, np)->data;
+
+ /* Get clock resources */
+ hdmi->clk_pix = devm_clk_get(dev, "pix");
+ if (IS_ERR(hdmi->clk_pix)) {
+ DRM_ERROR("Cannot get hdmi_pix clock\n");
+ return PTR_ERR(hdmi->clk_pix);
+ }
+
+ hdmi->clk_tmds = devm_clk_get(dev, "tmds");
+ if (IS_ERR(hdmi->clk_tmds)) {
+ DRM_ERROR("Cannot get hdmi_tmds clock\n");
+ return PTR_ERR(hdmi->clk_tmds);
+ }
+
+ hdmi->clk_phy = devm_clk_get(dev, "phy");
+ if (IS_ERR(hdmi->clk_phy)) {
+ DRM_ERROR("Cannot get hdmi_phy clock\n");
+ return PTR_ERR(hdmi->clk_phy);
+ }
+
+ hdmi->clk_audio = devm_clk_get(dev, "audio");
+ if (IS_ERR(hdmi->clk_audio)) {
+ DRM_ERROR("Cannot get hdmi_audio clock\n");
+ return PTR_ERR(hdmi->clk_audio);
+ }
+
+ hdmi->hpd_gpio = of_get_named_gpio(np, "hdmi,hpd-gpio", 0);
+ if (hdmi->hpd_gpio < 0) {
+ DRM_ERROR("Failed to get hdmi hpd-gpio\n");
+ return -EIO;
+ }
+
+ hdmi->hpd = gpio_get_value(hdmi->hpd_gpio);
+
+ init_waitqueue_head(&hdmi->wait_event);
+
+ hdmi->irq = platform_get_irq_byname(pdev, "irq");
+
+ ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
+ hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
+ if (ret) {
+ DRM_ERROR("Failed to register HDMI interrupt\n");
+ return ret;
+ }
+
+ hdmi->reset = devm_reset_control_get(dev, "hdmi");
+ /* Take hdmi out of reset */
+ if (!IS_ERR(hdmi->reset))
+ reset_control_deassert(hdmi->reset);
+
+ platform_set_drvdata(pdev, hdmi);
+
+ return component_add(&pdev->dev, &sti_hdmi_ops);
+}
+
+static int sti_hdmi_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sti_hdmi_ops);
+ return 0;
+}
+
+struct platform_driver sti_hdmi_driver = {
+ .driver = {
+ .name = "sti-hdmi",
+ .owner = THIS_MODULE,
+ .of_match_table = hdmi_of_match,
+ },
+ .probe = sti_hdmi_probe,
+ .remove = sti_hdmi_remove,
+};
+
+module_platform_driver(sti_hdmi_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h
new file mode 100644
index 000000000000..61bec6557ceb
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_H_
+#define _STI_HDMI_H_
+
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+#define HDMI_STA 0x0010
+#define HDMI_STA_DLL_LCK BIT(5)
+
+struct sti_hdmi;
+
+struct hdmi_phy_ops {
+ bool (*start)(struct sti_hdmi *hdmi);
+ void (*stop)(struct sti_hdmi *hdmi);
+};
+
+/**
+ * STI hdmi structure
+ *
+ * @dev: driver device
+ * @drm_dev: pointer to drm device
+ * @mode: current display mode selected
+ * @regs: hdmi register
+ * @syscfg: syscfg register for pll rejection configuration
+ * @clk_pix: hdmi pixel clock
+ * @clk_tmds: hdmi tmds clock
+ * @clk_phy: hdmi phy clock
+ * @clk_audio: hdmi audio clock
+ * @irq: hdmi interrupt number
+ * @irq_status: interrupt status register
+ * @phy_ops: phy start/stop operations
+ * @enabled: true if hdmi is enabled else false
+ * @hpd_gpio: hdmi hot plug detect gpio number
+ * @hpd: hot plug detect status
+ * @wait_event: wait event
+ * @event_received: wait event status
+ * @reset: reset control of the hdmi phy
+ */
+struct sti_hdmi {
+ struct device dev;
+ struct drm_device *drm_dev;
+ struct drm_display_mode mode;
+ void __iomem *regs;
+ void __iomem *syscfg;
+ struct clk *clk_pix;
+ struct clk *clk_tmds;
+ struct clk *clk_phy;
+ struct clk *clk_audio;
+ int irq;
+ u32 irq_status;
+ struct hdmi_phy_ops *phy_ops;
+ bool enabled;
+ int hpd_gpio;
+ bool hpd;
+ wait_queue_head_t wait_event;
+ bool event_received;
+ struct reset_control *reset;
+};
+
+u32 hdmi_read(struct sti_hdmi *hdmi, int offset);
+void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset);
+
+/**
+ * hdmi phy config structure
+ *
+ * A pointer to an array of these structures is passed to a TMDS (HDMI) output
+ * via the control interface to provide board and SoC specific
+ * configurations of the HDMI PHY. Each entry in the array specifies a hardware
+ * specific configuration for a given TMDS clock frequency range.
+ *
+ * @min_tmds_freq: Lower bound of TMDS clock frequency this entry applies to
+ * @max_tmds_freq: Upper bound of TMDS clock frequency this entry applies to
+ * @config: SoC specific register configuration
+ */
+struct hdmi_phy_config {
+ u32 min_tmds_freq;
+ u32 max_tmds_freq;
+ u32 config[4];
+};
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c b/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c
new file mode 100644
index 000000000000..49ae8e44b285
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include "sti_hdmi_tx3g0c55phy.h"
+
+#define HDMI_SRZ_PLL_CFG 0x0504
+#define HDMI_SRZ_TAP_1 0x0508
+#define HDMI_SRZ_TAP_2 0x050C
+#define HDMI_SRZ_TAP_3 0x0510
+#define HDMI_SRZ_CTRL 0x0514
+
+#define HDMI_SRZ_PLL_CFG_POWER_DOWN BIT(0)
+#define HDMI_SRZ_PLL_CFG_VCOR_SHIFT 1
+#define HDMI_SRZ_PLL_CFG_VCOR_425MHZ 0
+#define HDMI_SRZ_PLL_CFG_VCOR_850MHZ 1
+#define HDMI_SRZ_PLL_CFG_VCOR_1700MHZ 2
+#define HDMI_SRZ_PLL_CFG_VCOR_3000MHZ 3
+#define HDMI_SRZ_PLL_CFG_VCOR_MASK 3
+#define HDMI_SRZ_PLL_CFG_VCOR(x) (x << HDMI_SRZ_PLL_CFG_VCOR_SHIFT)
+#define HDMI_SRZ_PLL_CFG_NDIV_SHIFT 8
+#define HDMI_SRZ_PLL_CFG_NDIV_MASK (0x1F << HDMI_SRZ_PLL_CFG_NDIV_SHIFT)
+#define HDMI_SRZ_PLL_CFG_MODE_SHIFT 16
+#define HDMI_SRZ_PLL_CFG_MODE_13_5_MHZ 0x1
+#define HDMI_SRZ_PLL_CFG_MODE_25_2_MHZ 0x4
+#define HDMI_SRZ_PLL_CFG_MODE_27_MHZ 0x5
+#define HDMI_SRZ_PLL_CFG_MODE_33_75_MHZ 0x6
+#define HDMI_SRZ_PLL_CFG_MODE_40_5_MHZ 0x7
+#define HDMI_SRZ_PLL_CFG_MODE_54_MHZ 0x8
+#define HDMI_SRZ_PLL_CFG_MODE_67_5_MHZ 0x9
+#define HDMI_SRZ_PLL_CFG_MODE_74_25_MHZ 0xA
+#define HDMI_SRZ_PLL_CFG_MODE_81_MHZ 0xB
+#define HDMI_SRZ_PLL_CFG_MODE_82_5_MHZ 0xC
+#define HDMI_SRZ_PLL_CFG_MODE_108_MHZ 0xD
+#define HDMI_SRZ_PLL_CFG_MODE_148_5_MHZ 0xE
+#define HDMI_SRZ_PLL_CFG_MODE_165_MHZ 0xF
+#define HDMI_SRZ_PLL_CFG_MODE_MASK 0xF
+#define HDMI_SRZ_PLL_CFG_MODE(x) (x << HDMI_SRZ_PLL_CFG_MODE_SHIFT)
+
+#define HDMI_SRZ_CTRL_POWER_DOWN (1 << 0)
+#define HDMI_SRZ_CTRL_EXTERNAL_DATA_EN (1 << 1)
+
+/* sysconf registers */
+#define HDMI_REJECTION_PLL_CONFIGURATION 0x0858 /* SYSTEM_CONFIG2534 */
+#define HDMI_REJECTION_PLL_STATUS 0x0948 /* SYSTEM_CONFIG2594 */
+
+#define REJECTION_PLL_HDMI_ENABLE_SHIFT 0
+#define REJECTION_PLL_HDMI_ENABLE_MASK (0x1 << REJECTION_PLL_HDMI_ENABLE_SHIFT)
+#define REJECTION_PLL_HDMI_PDIV_SHIFT 24
+#define REJECTION_PLL_HDMI_PDIV_MASK (0x7 << REJECTION_PLL_HDMI_PDIV_SHIFT)
+#define REJECTION_PLL_HDMI_NDIV_SHIFT 16
+#define REJECTION_PLL_HDMI_NDIV_MASK (0xFF << REJECTION_PLL_HDMI_NDIV_SHIFT)
+#define REJECTION_PLL_HDMI_MDIV_SHIFT 8
+#define REJECTION_PLL_HDMI_MDIV_MASK (0xFF << REJECTION_PLL_HDMI_MDIV_SHIFT)
+
+#define REJECTION_PLL_HDMI_REJ_PLL_LOCK BIT(0)
+
+#define HDMI_TIMEOUT_PLL_LOCK 50 /*milliseconds */
+
+/**
+ * pll mode structure
+ *
+ * A pointer to an array of these structures is passed to a TMDS (HDMI) output
+ * via the control interface to provide board and SoC specific
+ * configurations of the HDMI PHY. Each entry in the array specifies a hardware
+ * specific configuration for a given TMDS clock frequency range. The array
+ * should be terminated with an entry that has all fields set to zero.
+ *
+ * @min: Lower bound of TMDS clock frequency this entry applies to
+ * @max: Upper bound of TMDS clock frequency this entry applies to
+ * @mode: SoC specific register configuration
+ */
+struct pllmode {
+ u32 min;
+ u32 max;
+ u32 mode;
+};
+
+#define NB_PLL_MODE 7
+static struct pllmode pllmodes[NB_PLL_MODE] = {
+ {13500000, 13513500, HDMI_SRZ_PLL_CFG_MODE_13_5_MHZ},
+ {25174800, 25200000, HDMI_SRZ_PLL_CFG_MODE_25_2_MHZ},
+ {27000000, 27027000, HDMI_SRZ_PLL_CFG_MODE_27_MHZ},
+ {54000000, 54054000, HDMI_SRZ_PLL_CFG_MODE_54_MHZ},
+ {72000000, 74250000, HDMI_SRZ_PLL_CFG_MODE_74_25_MHZ},
+ {108000000, 108108000, HDMI_SRZ_PLL_CFG_MODE_108_MHZ},
+ {148351648, 297000000, HDMI_SRZ_PLL_CFG_MODE_148_5_MHZ}
+};
+
+#define NB_HDMI_PHY_CONFIG 5
+static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
+ {0, 40000000, {0x00101010, 0x00101010, 0x00101010, 0x02} },
+ {40000000, 140000000, {0x00111111, 0x00111111, 0x00111111, 0x02} },
+ {140000000, 160000000, {0x00131313, 0x00101010, 0x00101010, 0x02} },
+ {160000000, 250000000, {0x00131313, 0x00111111, 0x00111111, 0x03FE} },
+ {250000000, 300000000, {0x00151515, 0x00101010, 0x00101010, 0x03FE} },
+};
+
+#define PLL_CHANGE_DELAY 1 /* ms */
+
+/**
+ * Disable the pll rejection
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * return true if the pll has been disabled
+ */
+static bool disable_pll_rejection(struct sti_hdmi *hdmi)
+{
+ u32 val;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+ val &= ~REJECTION_PLL_HDMI_ENABLE_MASK;
+ writel(val, hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+ msleep(PLL_CHANGE_DELAY);
+ val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_STATUS);
+
+ return !(val & REJECTION_PLL_HDMI_REJ_PLL_LOCK);
+}
+
+/**
+ * Enable the old BCH/rejection PLL is now reused to provide the CLKPXPLL
+ * clock input to the new PHY PLL that generates the serializer clock
+ * (TMDS*10) and the TMDS clock which is now fed back into the HDMI
+ * formatter instead of the TMDS clock line from ClockGenB.
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * return true if pll has been correctly set
+ */
+static bool enable_pll_rejection(struct sti_hdmi *hdmi)
+{
+ unsigned int inputclock;
+ u32 mdiv, ndiv, pdiv, val;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (!disable_pll_rejection(hdmi))
+ return false;
+
+ inputclock = hdmi->mode.clock * 1000;
+
+ DRM_DEBUG_DRIVER("hdmi rejection pll input clock = %dHz\n", inputclock);
+
+
+ /* Power up the HDMI rejection PLL
+ * Note: On this SoC (stiH416) we are forced to have the input clock
+ * be equal to the HDMI pixel clock.
+ *
+ * The values here have been suggested by validation however they are
+ * still provisional and subject to change.
+ *
+ * PLLout = (Fin*Mdiv) / ((2 * Ndiv) / 2^Pdiv)
+ */
+ if (inputclock < 50000000) {
+ /*
+ * For slower clocks we need to multiply more to keep the
+ * internal VCO frequency within the physical specification
+ * of the PLL.
+ */
+ pdiv = 4;
+ ndiv = 240;
+ mdiv = 30;
+ } else {
+ pdiv = 2;
+ ndiv = 60;
+ mdiv = 30;
+ }
+
+ val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+ val &= ~(REJECTION_PLL_HDMI_PDIV_MASK |
+ REJECTION_PLL_HDMI_NDIV_MASK |
+ REJECTION_PLL_HDMI_MDIV_MASK |
+ REJECTION_PLL_HDMI_ENABLE_MASK);
+
+ val |= (pdiv << REJECTION_PLL_HDMI_PDIV_SHIFT) |
+ (ndiv << REJECTION_PLL_HDMI_NDIV_SHIFT) |
+ (mdiv << REJECTION_PLL_HDMI_MDIV_SHIFT) |
+ (0x1 << REJECTION_PLL_HDMI_ENABLE_SHIFT);
+
+ writel(val, hdmi->syscfg + HDMI_REJECTION_PLL_CONFIGURATION);
+
+ msleep(PLL_CHANGE_DELAY);
+ val = readl(hdmi->syscfg + HDMI_REJECTION_PLL_STATUS);
+
+ return (val & REJECTION_PLL_HDMI_REJ_PLL_LOCK);
+}
+
+/**
+ * Start hdmi phy macro cell tx3g0c55
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return false if an error occur
+ */
+static bool sti_hdmi_tx3g0c55phy_start(struct sti_hdmi *hdmi)
+{
+ u32 ckpxpll = hdmi->mode.clock * 1000;
+ u32 val, tmdsck, freqvco, pllctrl = 0;
+ unsigned int i;
+
+ if (!enable_pll_rejection(hdmi))
+ return false;
+
+ DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);
+
+ /* Assuming no pixel repetition and 24bits color */
+ tmdsck = ckpxpll;
+ pllctrl = 2 << HDMI_SRZ_PLL_CFG_NDIV_SHIFT;
+
+ /*
+ * Setup the PLL mode parameter based on the ckpxpll. If we haven't got
+ * a clock frequency supported by one of the specific PLL modes then we
+ * will end up using the generic mode (0) which only supports a 10x
+ * multiplier, hence only 24bit color.
+ */
+ for (i = 0; i < NB_PLL_MODE; i++) {
+ if (ckpxpll >= pllmodes[i].min && ckpxpll <= pllmodes[i].max)
+ pllctrl |= HDMI_SRZ_PLL_CFG_MODE(pllmodes[i].mode);
+ }
+
+ freqvco = tmdsck * 10;
+ if (freqvco <= 425000000UL)
+ pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_425MHZ);
+ else if (freqvco <= 850000000UL)
+ pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_850MHZ);
+ else if (freqvco <= 1700000000UL)
+ pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_1700MHZ);
+ else if (freqvco <= 2970000000UL)
+ pllctrl |= HDMI_SRZ_PLL_CFG_VCOR(HDMI_SRZ_PLL_CFG_VCOR_3000MHZ);
+ else {
+ DRM_ERROR("PHY serializer clock out of range\n");
+ goto err;
+ }
+
+ /*
+ * Configure and power up the PHY PLL
+ */
+ hdmi->event_received = false;
+ DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
+ hdmi_write(hdmi, pllctrl, HDMI_SRZ_PLL_CFG);
+
+ /* wait PLL interrupt */
+ wait_event_interruptible_timeout(hdmi->wait_event,
+ hdmi->event_received == true,
+ msecs_to_jiffies
+ (HDMI_TIMEOUT_PLL_LOCK));
+
+ if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
+ DRM_ERROR("hdmi phy pll not locked\n");
+ goto err;
+ }
+
+ DRM_DEBUG_DRIVER("got PHY PLL Lock\n");
+
+ /*
+ * To configure the source termination and pre-emphasis appropriately
+ * for different high speed TMDS clock frequencies a phy configuration
+ * table must be provided, tailored to the SoC and board combination.
+ */
+ for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {
+ if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&
+ (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {
+ val = hdmiphy_config[i].config[0];
+ hdmi_write(hdmi, val, HDMI_SRZ_TAP_1);
+ val = hdmiphy_config[i].config[1];
+ hdmi_write(hdmi, val, HDMI_SRZ_TAP_2);
+ val = hdmiphy_config[i].config[2];
+ hdmi_write(hdmi, val, HDMI_SRZ_TAP_3);
+ val = hdmiphy_config[i].config[3];
+ val |= HDMI_SRZ_CTRL_EXTERNAL_DATA_EN;
+ val &= ~HDMI_SRZ_CTRL_POWER_DOWN;
+ hdmi_write(hdmi, val, HDMI_SRZ_CTRL);
+
+ DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x 0x%x\n",
+ hdmiphy_config[i].config[0],
+ hdmiphy_config[i].config[1],
+ hdmiphy_config[i].config[2],
+ hdmiphy_config[i].config[3]);
+ return true;
+ }
+ }
+
+ /*
+ * Default, power up the serializer with no pre-emphasis or source
+ * termination.
+ */
+ hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_1);
+ hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_2);
+ hdmi_write(hdmi, 0x0, HDMI_SRZ_TAP_3);
+ hdmi_write(hdmi, HDMI_SRZ_CTRL_EXTERNAL_DATA_EN, HDMI_SRZ_CTRL);
+
+ return true;
+
+err:
+ disable_pll_rejection(hdmi);
+
+ return false;
+}
+
+/**
+ * Stop hdmi phy macro cell tx3g0c55
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void sti_hdmi_tx3g0c55phy_stop(struct sti_hdmi *hdmi)
+{
+ DRM_DEBUG_DRIVER("\n");
+
+ hdmi->event_received = false;
+
+ hdmi_write(hdmi, HDMI_SRZ_CTRL_POWER_DOWN, HDMI_SRZ_CTRL);
+ hdmi_write(hdmi, HDMI_SRZ_PLL_CFG_POWER_DOWN, HDMI_SRZ_PLL_CFG);
+
+ /* wait PLL interrupt */
+ wait_event_interruptible_timeout(hdmi->wait_event,
+ hdmi->event_received == true,
+ msecs_to_jiffies
+ (HDMI_TIMEOUT_PLL_LOCK));
+
+ if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)
+ DRM_ERROR("hdmi phy pll not well disabled\n");
+
+ disable_pll_rejection(hdmi);
+}
+
+struct hdmi_phy_ops tx3g0c55phy_ops = {
+ .start = sti_hdmi_tx3g0c55phy_start,
+ .stop = sti_hdmi_tx3g0c55phy_stop,
+};
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h b/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h
new file mode 100644
index 000000000000..068237b3a303
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g0c55phy.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_TX3G0C55PHY_H_
+#define _STI_HDMI_TX3G0C55PHY_H_
+
+#include "sti_hdmi.h"
+
+extern struct hdmi_phy_ops tx3g0c55phy_ops;
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c
new file mode 100644
index 000000000000..8e0ceb0ced33
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include "sti_hdmi_tx3g4c28phy.h"
+
+#define HDMI_SRZ_CFG 0x504
+#define HDMI_SRZ_PLL_CFG 0x510
+#define HDMI_SRZ_ICNTL 0x518
+#define HDMI_SRZ_CALCODE_EXT 0x520
+
+#define HDMI_SRZ_CFG_EN BIT(0)
+#define HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT BIT(1)
+#define HDMI_SRZ_CFG_EXTERNAL_DATA BIT(16)
+#define HDMI_SRZ_CFG_RBIAS_EXT BIT(17)
+#define HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION BIT(18)
+#define HDMI_SRZ_CFG_EN_BIASRES_DETECTION BIT(19)
+#define HDMI_SRZ_CFG_EN_SRC_TERMINATION BIT(24)
+
+#define HDMI_SRZ_CFG_INTERNAL_MASK (HDMI_SRZ_CFG_EN | \
+ HDMI_SRZ_CFG_DISABLE_BYPASS_SINK_CURRENT | \
+ HDMI_SRZ_CFG_EXTERNAL_DATA | \
+ HDMI_SRZ_CFG_RBIAS_EXT | \
+ HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION | \
+ HDMI_SRZ_CFG_EN_BIASRES_DETECTION | \
+ HDMI_SRZ_CFG_EN_SRC_TERMINATION)
+
+#define PLL_CFG_EN BIT(0)
+#define PLL_CFG_NDIV_SHIFT (8)
+#define PLL_CFG_IDF_SHIFT (16)
+#define PLL_CFG_ODF_SHIFT (24)
+
+#define ODF_DIV_1 (0)
+#define ODF_DIV_2 (1)
+#define ODF_DIV_4 (2)
+#define ODF_DIV_8 (3)
+
+#define HDMI_TIMEOUT_PLL_LOCK 50 /*milliseconds */
+
+struct plldividers_s {
+ uint32_t min;
+ uint32_t max;
+ uint32_t idf;
+ uint32_t odf;
+};
+
+/*
+ * Functional specification recommended values
+ */
+#define NB_PLL_MODE 5
+static struct plldividers_s plldividers[NB_PLL_MODE] = {
+ {0, 20000000, 1, ODF_DIV_8},
+ {20000000, 42500000, 2, ODF_DIV_8},
+ {42500000, 85000000, 4, ODF_DIV_4},
+ {85000000, 170000000, 8, ODF_DIV_2},
+ {170000000, 340000000, 16, ODF_DIV_1}
+};
+
+#define NB_HDMI_PHY_CONFIG 2
+static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
+ {0, 250000000, {0x0, 0x0, 0x0, 0x0} },
+ {250000000, 300000000, {0x1110, 0x0, 0x0, 0x0} },
+};
+
+/**
+ * Start hdmi phy macro cell tx3g4c28
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ *
+ * Return false if an error occur
+ */
+static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi)
+{
+ u32 ckpxpll = hdmi->mode.clock * 1000;
+ u32 val, tmdsck, idf, odf, pllctrl = 0;
+ bool foundplldivides = false;
+ int i;
+
+ DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);
+
+ for (i = 0; i < NB_PLL_MODE; i++) {
+ if (ckpxpll >= plldividers[i].min &&
+ ckpxpll < plldividers[i].max) {
+ idf = plldividers[i].idf;
+ odf = plldividers[i].odf;
+ foundplldivides = true;
+ break;
+ }
+ }
+
+ if (!foundplldivides) {
+ DRM_ERROR("input TMDS clock speed (%d) not supported\n",
+ ckpxpll);
+ goto err;
+ }
+
+ /* Assuming no pixel repetition and 24bits color */
+ tmdsck = ckpxpll;
+ pllctrl |= 40 << PLL_CFG_NDIV_SHIFT;
+
+ if (tmdsck > 340000000) {
+ DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck);
+ goto err;
+ }
+
+ pllctrl |= idf << PLL_CFG_IDF_SHIFT;
+ pllctrl |= odf << PLL_CFG_ODF_SHIFT;
+
+ /*
+ * Configure and power up the PHY PLL
+ */
+ hdmi->event_received = false;
+ DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
+ hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG);
+
+ /* wait PLL interrupt */
+ wait_event_interruptible_timeout(hdmi->wait_event,
+ hdmi->event_received == true,
+ msecs_to_jiffies
+ (HDMI_TIMEOUT_PLL_LOCK));
+
+ if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
+ DRM_ERROR("hdmi phy pll not locked\n");
+ goto err;
+ }
+
+ DRM_DEBUG_DRIVER("got PHY PLL Lock\n");
+
+ val = (HDMI_SRZ_CFG_EN |
+ HDMI_SRZ_CFG_EXTERNAL_DATA |
+ HDMI_SRZ_CFG_EN_BIASRES_DETECTION |
+ HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION);
+
+ if (tmdsck > 165000000)
+ val |= HDMI_SRZ_CFG_EN_SRC_TERMINATION;
+
+ /*
+ * To configure the source termination and pre-emphasis appropriately
+ * for different high speed TMDS clock frequencies a phy configuration
+ * table must be provided, tailored to the SoC and board combination.
+ */
+ for (i = 0; i < NB_HDMI_PHY_CONFIG; i++) {
+ if ((hdmiphy_config[i].min_tmds_freq <= tmdsck) &&
+ (hdmiphy_config[i].max_tmds_freq >= tmdsck)) {
+ val |= (hdmiphy_config[i].config[0]
+ & ~HDMI_SRZ_CFG_INTERNAL_MASK);
+ hdmi_write(hdmi, val, HDMI_SRZ_CFG);
+
+ val = hdmiphy_config[i].config[1];
+ hdmi_write(hdmi, val, HDMI_SRZ_ICNTL);
+
+ val = hdmiphy_config[i].config[2];
+ hdmi_write(hdmi, val, HDMI_SRZ_CALCODE_EXT);
+
+ DRM_DEBUG_DRIVER("serializer cfg 0x%x 0x%x 0x%x\n",
+ hdmiphy_config[i].config[0],
+ hdmiphy_config[i].config[1],
+ hdmiphy_config[i].config[2]);
+ return true;
+ }
+ }
+
+ /*
+ * Default, power up the serializer with no pre-emphasis or
+ * output swing correction
+ */
+ hdmi_write(hdmi, val, HDMI_SRZ_CFG);
+ hdmi_write(hdmi, 0x0, HDMI_SRZ_ICNTL);
+ hdmi_write(hdmi, 0x0, HDMI_SRZ_CALCODE_EXT);
+
+ return true;
+
+err:
+ return false;
+}
+
+/**
+ * Stop hdmi phy macro cell tx3g4c28
+ *
+ * @hdmi: pointer on the hdmi internal structure
+ */
+static void sti_hdmi_tx3g4c28phy_stop(struct sti_hdmi *hdmi)
+{
+ int val = 0;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ hdmi->event_received = false;
+
+ val = HDMI_SRZ_CFG_EN_SINK_TERM_DETECTION;
+ val |= HDMI_SRZ_CFG_EN_BIASRES_DETECTION;
+
+ hdmi_write(hdmi, val, HDMI_SRZ_CFG);
+ hdmi_write(hdmi, 0, HDMI_SRZ_PLL_CFG);
+
+ /* wait PLL interrupt */
+ wait_event_interruptible_timeout(hdmi->wait_event,
+ hdmi->event_received == true,
+ msecs_to_jiffies
+ (HDMI_TIMEOUT_PLL_LOCK));
+
+ if (hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK)
+ DRM_ERROR("hdmi phy pll not well disabled\n");
+}
+
+struct hdmi_phy_ops tx3g4c28phy_ops = {
+ .start = sti_hdmi_tx3g4c28phy_start,
+ .stop = sti_hdmi_tx3g4c28phy_stop,
+};
diff --git a/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h
new file mode 100644
index 000000000000..f99a7ff281ef
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_HDMI_TX3G4C28PHY_H_
+#define _STI_HDMI_TX3G4C28PHY_H_
+
+#include "sti_hdmi.h"
+
+extern struct hdmi_phy_ops tx3g4c28phy_ops;
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_layer.c b/drivers/gpu/drm/sti/sti_layer.c
new file mode 100644
index 000000000000..06a587c4f1bb
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_layer.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "sti_compositor.h"
+#include "sti_gdp.h"
+#include "sti_layer.h"
+#include "sti_vid.h"
+
+const char *sti_layer_to_str(struct sti_layer *layer)
+{
+ switch (layer->desc) {
+ case STI_GDP_0:
+ return "GDP0";
+ case STI_GDP_1:
+ return "GDP1";
+ case STI_GDP_2:
+ return "GDP2";
+ case STI_GDP_3:
+ return "GDP3";
+ case STI_VID_0:
+ return "VID0";
+ case STI_VID_1:
+ return "VID1";
+ case STI_CURSOR:
+ return "CURSOR";
+ default:
+ return "<UNKNOWN LAYER>";
+ }
+}
+
+struct sti_layer *sti_layer_create(struct device *dev, int desc,
+ void __iomem *baseaddr)
+{
+
+ struct sti_layer *layer = NULL;
+
+ switch (desc & STI_LAYER_TYPE_MASK) {
+ case STI_GDP:
+ layer = sti_gdp_create(dev, desc);
+ break;
+ case STI_VID:
+ layer = sti_vid_create(dev);
+ break;
+ }
+
+ if (!layer) {
+ DRM_ERROR("Failed to create layer\n");
+ return NULL;
+ }
+
+ layer->desc = desc;
+ layer->dev = dev;
+ layer->regs = baseaddr;
+
+ layer->ops->init(layer);
+
+ DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer));
+
+ return layer;
+}
+
+int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb,
+ struct drm_display_mode *mode, int mixer_id,
+ int dest_x, int dest_y, int dest_w, int dest_h,
+ int src_x, int src_y, int src_w, int src_h)
+{
+ int ret;
+ unsigned int i;
+ struct drm_gem_cma_object *cma_obj;
+
+ if (!layer || !fb || !mode) {
+ DRM_ERROR("Null fb, layer or mode\n");
+ return 1;
+ }
+
+ cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+ if (!cma_obj) {
+ DRM_ERROR("Can't get CMA GEM object for fb\n");
+ return 1;
+ }
+
+ layer->fb = fb;
+ layer->mode = mode;
+ layer->mixer_id = mixer_id;
+ layer->dst_x = dest_x;
+ layer->dst_y = dest_y;
+ layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
+ layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
+ layer->src_x = src_x;
+ layer->src_y = src_y;
+ layer->src_w = src_w;
+ layer->src_h = src_h;
+ layer->format = fb->pixel_format;
+ layer->paddr = cma_obj->paddr;
+ for (i = 0; i < 4; i++) {
+ layer->pitches[i] = fb->pitches[i];
+ layer->offsets[i] = fb->offsets[i];
+ }
+
+ DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
+ sti_layer_to_str(layer),
+ layer->mixer_id);
+ DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
+ sti_layer_to_str(layer),
+ layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y,
+ layer->src_w, layer->src_h, layer->src_x,
+ layer->src_y);
+
+ DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
+ (char *)&layer->format, (unsigned long)layer->paddr);
+
+ if (!layer->ops->prepare)
+ goto err_no_prepare;
+
+ ret = layer->ops->prepare(layer, !layer->enabled);
+ if (!ret)
+ layer->enabled = true;
+
+ return ret;
+
+err_no_prepare:
+ DRM_ERROR("Cannot prepare\n");
+ return 1;
+}
+
+int sti_layer_commit(struct sti_layer *layer)
+{
+ if (!layer)
+ return 1;
+
+ if (!layer->ops->commit)
+ goto err_no_commit;
+
+ return layer->ops->commit(layer);
+
+err_no_commit:
+ DRM_ERROR("Cannot commit\n");
+ return 1;
+}
+
+int sti_layer_disable(struct sti_layer *layer)
+{
+ int ret;
+
+ DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer));
+ if (!layer)
+ return 1;
+
+ if (!layer->enabled)
+ return 0;
+
+ if (!layer->ops->disable)
+ goto err_no_disable;
+
+ ret = layer->ops->disable(layer);
+ if (!ret)
+ layer->enabled = false;
+ else
+ DRM_ERROR("Disable failed\n");
+
+ return ret;
+
+err_no_disable:
+ DRM_ERROR("Cannot disable\n");
+ return 1;
+}
+
+const uint32_t *sti_layer_get_formats(struct sti_layer *layer)
+{
+ if (!layer)
+ return NULL;
+
+ if (!layer->ops->get_formats)
+ return NULL;
+
+ return layer->ops->get_formats(layer);
+}
+
+unsigned int sti_layer_get_nb_formats(struct sti_layer *layer)
+{
+ if (!layer)
+ return 0;
+
+ if (!layer->ops->get_nb_formats)
+ return 0;
+
+ return layer->ops->get_nb_formats(layer);
+}
diff --git a/drivers/gpu/drm/sti/sti_layer.h b/drivers/gpu/drm/sti/sti_layer.h
new file mode 100644
index 000000000000..198c3774cc12
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_layer.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_LAYER_H_
+#define _STI_LAYER_H_
+
+#include <drm/drmP.h>
+
+#define to_sti_layer(x) container_of(x, struct sti_layer, plane)
+
+#define STI_LAYER_TYPE_SHIFT 8
+#define STI_LAYER_TYPE_MASK (~((1<<STI_LAYER_TYPE_SHIFT)-1))
+
+struct sti_layer;
+
+enum sti_layer_type {
+ STI_GDP = 1 << STI_LAYER_TYPE_SHIFT,
+ STI_VID = 2 << STI_LAYER_TYPE_SHIFT,
+ STI_CUR = 3 << STI_LAYER_TYPE_SHIFT,
+ STI_BCK = 4 << STI_LAYER_TYPE_SHIFT
+};
+
+enum sti_layer_id_of_type {
+ STI_ID_0 = 0,
+ STI_ID_1 = 1,
+ STI_ID_2 = 2,
+ STI_ID_3 = 3
+};
+
+enum sti_layer_desc {
+ STI_GDP_0 = STI_GDP | STI_ID_0,
+ STI_GDP_1 = STI_GDP | STI_ID_1,
+ STI_GDP_2 = STI_GDP | STI_ID_2,
+ STI_GDP_3 = STI_GDP | STI_ID_3,
+ STI_VID_0 = STI_VID | STI_ID_0,
+ STI_VID_1 = STI_VID | STI_ID_1,
+ STI_CURSOR = STI_CUR,
+ STI_BACK = STI_BCK
+};
+
+/**
+ * STI layer functions structure
+ *
+ * @get_formats: get layer supported formats
+ * @get_nb_formats: get number of format supported
+ * @init: initialize the layer
+ * @prepare: prepare layer before rendering
+ * @commit: set layer for rendering
+ * @disable: disable layer
+ */
+struct sti_layer_funcs {
+ const uint32_t* (*get_formats)(struct sti_layer *layer);
+ unsigned int (*get_nb_formats)(struct sti_layer *layer);
+ void (*init)(struct sti_layer *layer);
+ int (*prepare)(struct sti_layer *layer, bool first_prepare);
+ int (*commit)(struct sti_layer *layer);
+ int (*disable)(struct sti_layer *layer);
+};
+
+/**
+ * STI layer structure
+ *
+ * @plane: drm plane it is bound to (if any)
+ * @fb: drm fb it is bound to
+ * @mode: display mode
+ * @desc: layer type & id
+ * @device: driver device
+ * @regs: layer registers
+ * @ops: layer functions
+ * @zorder: layer z-order
+ * @mixer_id: id of the mixer used to display the layer
+ * @enabled: to know if the layer is active or not
+ * @src_x src_y: coordinates of the input (fb) area
+ * @src_w src_h: size of the input (fb) area
+ * @dst_x dst_y: coordinates of the output (crtc) area
+ * @dst_w dst_h: size of the output (crtc) area
+ * @format: format
+ * @pitches: pitch of 'planes' (eg: Y, U, V)
+ * @offsets: offset of 'planes'
+ * @paddr: physical address of the input buffer
+ */
+struct sti_layer {
+ struct drm_plane plane;
+ struct drm_framebuffer *fb;
+ struct drm_display_mode *mode;
+ enum sti_layer_desc desc;
+ struct device *dev;
+ void __iomem *regs;
+ const struct sti_layer_funcs *ops;
+ int zorder;
+ int mixer_id;
+ bool enabled;
+ int src_x, src_y;
+ int src_w, src_h;
+ int dst_x, dst_y;
+ int dst_w, dst_h;
+ uint32_t format;
+ unsigned int pitches[4];
+ unsigned int offsets[4];
+ dma_addr_t paddr;
+};
+
+struct sti_layer *sti_layer_create(struct device *dev, int desc,
+ void __iomem *baseaddr);
+int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb,
+ struct drm_display_mode *mode,
+ int mixer_id,
+ int dest_x, int dest_y,
+ int dest_w, int dest_h,
+ int src_x, int src_y,
+ int src_w, int src_h);
+int sti_layer_commit(struct sti_layer *layer);
+int sti_layer_disable(struct sti_layer *layer);
+const uint32_t *sti_layer_get_formats(struct sti_layer *layer);
+unsigned int sti_layer_get_nb_formats(struct sti_layer *layer);
+const char *sti_layer_to_str(struct sti_layer *layer);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
new file mode 100644
index 000000000000..79f369db9fb6
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include "sti_compositor.h"
+#include "sti_mixer.h"
+#include "sti_vtg.h"
+
+/* Identity: G=Y , B=Cb , R=Cr */
+static const u32 mixerColorSpaceMatIdentity[] = {
+ 0x10000000, 0x00000000, 0x10000000, 0x00001000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+/* regs offset */
+#define GAM_MIXER_CTL 0x00
+#define GAM_MIXER_BKC 0x04
+#define GAM_MIXER_BCO 0x0C
+#define GAM_MIXER_BCS 0x10
+#define GAM_MIXER_AVO 0x28
+#define GAM_MIXER_AVS 0x2C
+#define GAM_MIXER_CRB 0x34
+#define GAM_MIXER_ACT 0x38
+#define GAM_MIXER_MBP 0x3C
+#define GAM_MIXER_MX0 0x80
+
+/* id for depth of CRB reg */
+#define GAM_DEPTH_VID0_ID 1
+#define GAM_DEPTH_VID1_ID 2
+#define GAM_DEPTH_GDP0_ID 3
+#define GAM_DEPTH_GDP1_ID 4
+#define GAM_DEPTH_GDP2_ID 5
+#define GAM_DEPTH_GDP3_ID 6
+#define GAM_DEPTH_MASK_ID 7
+
+/* mask in CTL reg */
+#define GAM_CTL_BACK_MASK BIT(0)
+#define GAM_CTL_VID0_MASK BIT(1)
+#define GAM_CTL_VID1_MASK BIT(2)
+#define GAM_CTL_GDP0_MASK BIT(3)
+#define GAM_CTL_GDP1_MASK BIT(4)
+#define GAM_CTL_GDP2_MASK BIT(5)
+#define GAM_CTL_GDP3_MASK BIT(6)
+
+const char *sti_mixer_to_str(struct sti_mixer *mixer)
+{
+ switch (mixer->id) {
+ case STI_MIXER_MAIN:
+ return "MAIN_MIXER";
+ case STI_MIXER_AUX:
+ return "AUX_MIXER";
+ default:
+ return "<UNKNOWN MIXER>";
+ }
+}
+
+static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
+{
+ return readl(mixer->regs + reg_id);
+}
+
+static inline void sti_mixer_reg_write(struct sti_mixer *mixer,
+ u32 reg_id, u32 val)
+{
+ writel(val, mixer->regs + reg_id);
+}
+
+void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
+{
+ u32 val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
+
+ val &= ~GAM_CTL_BACK_MASK;
+ val |= enable;
+ sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
+}
+
+static void sti_mixer_set_background_color(struct sti_mixer *mixer,
+ u8 red, u8 green, u8 blue)
+{
+ u32 val = (red << 16) | (green << 8) | blue;
+
+ sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
+}
+
+static void sti_mixer_set_background_area(struct sti_mixer *mixer,
+ struct drm_display_mode *mode)
+{
+ u32 ydo, xdo, yds, xds;
+
+ ydo = sti_vtg_get_line_number(*mode, 0);
+ yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
+ xdo = sti_vtg_get_pixel_number(*mode, 0);
+ xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
+
+ sti_mixer_reg_write(mixer, GAM_MIXER_BCO, ydo << 16 | xdo);
+ sti_mixer_reg_write(mixer, GAM_MIXER_BCS, yds << 16 | xds);
+}
+
+int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer)
+{
+ int layer_id = 0, depth = layer->zorder;
+ u32 mask, val;
+
+ if (depth >= GAM_MIXER_NB_DEPTH_LEVEL)
+ return 1;
+
+ switch (layer->desc) {
+ case STI_GDP_0:
+ layer_id = GAM_DEPTH_GDP0_ID;
+ break;
+ case STI_GDP_1:
+ layer_id = GAM_DEPTH_GDP1_ID;
+ break;
+ case STI_GDP_2:
+ layer_id = GAM_DEPTH_GDP2_ID;
+ break;
+ case STI_GDP_3:
+ layer_id = GAM_DEPTH_GDP3_ID;
+ break;
+ case STI_VID_0:
+ layer_id = GAM_DEPTH_VID0_ID;
+ break;
+ case STI_VID_1:
+ layer_id = GAM_DEPTH_VID1_ID;
+ break;
+ default:
+ DRM_ERROR("Unknown layer %d\n", layer->desc);
+ return 1;
+ }
+ mask = GAM_DEPTH_MASK_ID << (3 * depth);
+ layer_id = layer_id << (3 * depth);
+
+ DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
+ sti_layer_to_str(layer), depth);
+ dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n",
+ layer_id, mask);
+
+ val = sti_mixer_reg_read(mixer, GAM_MIXER_CRB);
+ val &= ~mask;
+ val |= layer_id;
+ sti_mixer_reg_write(mixer, GAM_MIXER_CRB, val);
+
+ dev_dbg(mixer->dev, "Read GAM_MIXER_CRB 0x%x\n",
+ sti_mixer_reg_read(mixer, GAM_MIXER_CRB));
+ return 0;
+}
+
+int sti_mixer_active_video_area(struct sti_mixer *mixer,
+ struct drm_display_mode *mode)
+{
+ u32 ydo, xdo, yds, xds;
+
+ ydo = sti_vtg_get_line_number(*mode, 0);
+ yds = sti_vtg_get_line_number(*mode, mode->vdisplay - 1);
+ xdo = sti_vtg_get_pixel_number(*mode, 0);
+ xds = sti_vtg_get_pixel_number(*mode, mode->hdisplay - 1);
+
+ DRM_DEBUG_DRIVER("%s active video area xdo:%d ydo:%d xds:%d yds:%d\n",
+ sti_mixer_to_str(mixer), xdo, ydo, xds, yds);
+ sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
+ sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
+
+ sti_mixer_set_background_color(mixer, 0xFF, 0, 0);
+
+ sti_mixer_set_background_area(mixer, mode);
+ sti_mixer_set_background_status(mixer, true);
+ return 0;
+}
+
+static u32 sti_mixer_get_layer_mask(struct sti_layer *layer)
+{
+ switch (layer->desc) {
+ case STI_BACK:
+ return GAM_CTL_BACK_MASK;
+ case STI_GDP_0:
+ return GAM_CTL_GDP0_MASK;
+ case STI_GDP_1:
+ return GAM_CTL_GDP1_MASK;
+ case STI_GDP_2:
+ return GAM_CTL_GDP2_MASK;
+ case STI_GDP_3:
+ return GAM_CTL_GDP3_MASK;
+ case STI_VID_0:
+ return GAM_CTL_VID0_MASK;
+ case STI_VID_1:
+ return GAM_CTL_VID1_MASK;
+ default:
+ return 0;
+ }
+}
+
+int sti_mixer_set_layer_status(struct sti_mixer *mixer,
+ struct sti_layer *layer, bool status)
+{
+ u32 mask, val;
+
+ DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable",
+ sti_mixer_to_str(mixer), sti_layer_to_str(layer));
+
+ mask = sti_mixer_get_layer_mask(layer);
+ if (!mask) {
+ DRM_ERROR("Can not find layer mask\n");
+ return -EINVAL;
+ }
+
+ val = sti_mixer_reg_read(mixer, GAM_MIXER_CTL);
+ val &= ~mask;
+ val |= status ? mask : 0;
+ sti_mixer_reg_write(mixer, GAM_MIXER_CTL, val);
+
+ return 0;
+}
+
+void sti_mixer_set_matrix(struct sti_mixer *mixer)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mixerColorSpaceMatIdentity); i++)
+ sti_mixer_reg_write(mixer, GAM_MIXER_MX0 + (i * 4),
+ mixerColorSpaceMatIdentity[i]);
+}
+
+struct sti_mixer *sti_mixer_create(struct device *dev, int id,
+ void __iomem *baseaddr)
+{
+ struct sti_mixer *mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+ struct device_node *np = dev->of_node;
+
+ dev_dbg(dev, "%s\n", __func__);
+ if (!mixer) {
+ DRM_ERROR("Failed to allocated memory for mixer\n");
+ return NULL;
+ }
+ mixer->regs = baseaddr;
+ mixer->dev = dev;
+ mixer->id = id;
+
+ if (of_device_is_compatible(np, "st,stih416-compositor"))
+ sti_mixer_set_matrix(mixer);
+
+ DRM_DEBUG_DRIVER("%s created. Regs=%p\n",
+ sti_mixer_to_str(mixer), mixer->regs);
+
+ return mixer;
+}
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h
new file mode 100644
index 000000000000..874372102e52
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_mixer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_MIXER_H_
+#define _STI_MIXER_H_
+
+#include <drm/drmP.h>
+
+#include "sti_layer.h"
+
+#define to_sti_mixer(x) container_of(x, struct sti_mixer, drm_crtc)
+
+/**
+ * STI Mixer subdevice structure
+ *
+ * @dev: driver device
+ * @regs: mixer registers
+ * @id: id of the mixer
+ * @drm_crtc: crtc object link to the mixer
+ * @pending_event: set if a flip event is pending on crtc
+ */
+struct sti_mixer {
+ struct device *dev;
+ void __iomem *regs;
+ int id;
+ struct drm_crtc drm_crtc;
+ struct drm_pending_vblank_event *pending_event;
+};
+
+const char *sti_mixer_to_str(struct sti_mixer *mixer);
+
+struct sti_mixer *sti_mixer_create(struct device *dev, int id,
+ void __iomem *baseaddr);
+
+int sti_mixer_set_layer_status(struct sti_mixer *mixer,
+ struct sti_layer *layer, bool status);
+int sti_mixer_set_layer_depth(struct sti_mixer *mixer, struct sti_layer *layer);
+int sti_mixer_active_video_area(struct sti_mixer *mixer,
+ struct drm_display_mode *mode);
+
+void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable);
+
+/* depth in Cross-bar control = z order */
+#define GAM_MIXER_NB_DEPTH_LEVEL 7
+
+#define STI_MIXER_MAIN 0
+#define STI_MIXER_AUX 1
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
new file mode 100644
index 000000000000..b69e26fee76e
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Vincent Abriou <vincent.abriou@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+
+/* glue registers */
+#define TVO_CSC_MAIN_M0 0x000
+#define TVO_CSC_MAIN_M1 0x004
+#define TVO_CSC_MAIN_M2 0x008
+#define TVO_CSC_MAIN_M3 0x00c
+#define TVO_CSC_MAIN_M4 0x010
+#define TVO_CSC_MAIN_M5 0x014
+#define TVO_CSC_MAIN_M6 0x018
+#define TVO_CSC_MAIN_M7 0x01c
+#define TVO_MAIN_IN_VID_FORMAT 0x030
+#define TVO_CSC_AUX_M0 0x100
+#define TVO_CSC_AUX_M1 0x104
+#define TVO_CSC_AUX_M2 0x108
+#define TVO_CSC_AUX_M3 0x10c
+#define TVO_CSC_AUX_M4 0x110
+#define TVO_CSC_AUX_M5 0x114
+#define TVO_CSC_AUX_M6 0x118
+#define TVO_CSC_AUX_M7 0x11c
+#define TVO_AUX_IN_VID_FORMAT 0x130
+#define TVO_VIP_HDF 0x400
+#define TVO_HD_SYNC_SEL 0x418
+#define TVO_HD_DAC_CFG_OFF 0x420
+#define TVO_VIP_HDMI 0x500
+#define TVO_HDMI_FORCE_COLOR_0 0x504
+#define TVO_HDMI_FORCE_COLOR_1 0x508
+#define TVO_HDMI_CLIP_VALUE_B_CB 0x50c
+#define TVO_HDMI_CLIP_VALUE_Y_G 0x510
+#define TVO_HDMI_CLIP_VALUE_R_CR 0x514
+#define TVO_HDMI_SYNC_SEL 0x518
+#define TVO_HDMI_DFV_OBS 0x540
+
+#define TVO_IN_FMT_SIGNED BIT(0)
+#define TVO_SYNC_EXT BIT(4)
+
+#define TVO_VIP_REORDER_R_SHIFT 24
+#define TVO_VIP_REORDER_G_SHIFT 20
+#define TVO_VIP_REORDER_B_SHIFT 16
+#define TVO_VIP_REORDER_MASK 0x3
+#define TVO_VIP_REORDER_Y_G_SEL 0
+#define TVO_VIP_REORDER_CB_B_SEL 1
+#define TVO_VIP_REORDER_CR_R_SEL 2
+
+#define TVO_VIP_CLIP_SHIFT 8
+#define TVO_VIP_CLIP_MASK 0x7
+#define TVO_VIP_CLIP_DISABLED 0
+#define TVO_VIP_CLIP_EAV_SAV 1
+#define TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y 2
+#define TVO_VIP_CLIP_LIMITED_RANGE_CB_CR 3
+#define TVO_VIP_CLIP_PROG_RANGE 4
+
+#define TVO_VIP_RND_SHIFT 4
+#define TVO_VIP_RND_MASK 0x3
+#define TVO_VIP_RND_8BIT_ROUNDED 0
+#define TVO_VIP_RND_10BIT_ROUNDED 1
+#define TVO_VIP_RND_12BIT_ROUNDED 2
+
+#define TVO_VIP_SEL_INPUT_MASK 0xf
+#define TVO_VIP_SEL_INPUT_MAIN 0x0
+#define TVO_VIP_SEL_INPUT_AUX 0x8
+#define TVO_VIP_SEL_INPUT_FORCE_COLOR 0xf
+#define TVO_VIP_SEL_INPUT_BYPASS_MASK 0x1
+#define TVO_VIP_SEL_INPUT_BYPASSED 1
+
+#define TVO_SYNC_MAIN_VTG_SET_REF 0x00
+#define TVO_SYNC_MAIN_VTG_SET_1 0x01
+#define TVO_SYNC_MAIN_VTG_SET_2 0x02
+#define TVO_SYNC_MAIN_VTG_SET_3 0x03
+#define TVO_SYNC_MAIN_VTG_SET_4 0x04
+#define TVO_SYNC_MAIN_VTG_SET_5 0x05
+#define TVO_SYNC_MAIN_VTG_SET_6 0x06
+#define TVO_SYNC_AUX_VTG_SET_REF 0x10
+#define TVO_SYNC_AUX_VTG_SET_1 0x11
+#define TVO_SYNC_AUX_VTG_SET_2 0x12
+#define TVO_SYNC_AUX_VTG_SET_3 0x13
+#define TVO_SYNC_AUX_VTG_SET_4 0x14
+#define TVO_SYNC_AUX_VTG_SET_5 0x15
+#define TVO_SYNC_AUX_VTG_SET_6 0x16
+
+#define TVO_SYNC_HD_DCS_SHIFT 8
+
+#define ENCODER_MAIN_CRTC_MASK BIT(0)
+
+/* enum listing the supported output data format */
+enum sti_tvout_video_out_type {
+ STI_TVOUT_VIDEO_OUT_RGB,
+ STI_TVOUT_VIDEO_OUT_YUV,
+};
+
+struct sti_tvout {
+ struct device *dev;
+ struct drm_device *drm_dev;
+ void __iomem *regs;
+ struct reset_control *reset;
+ struct drm_encoder *hdmi;
+ struct drm_encoder *hda;
+};
+
+struct sti_tvout_encoder {
+ struct drm_encoder encoder;
+ struct sti_tvout *tvout;
+};
+
+#define to_sti_tvout_encoder(x) \
+ container_of(x, struct sti_tvout_encoder, encoder)
+
+#define to_sti_tvout(x) to_sti_tvout_encoder(x)->tvout
+
+/* preformatter conversion matrix */
+static const u32 rgb_to_ycbcr_601[8] = {
+ 0xF927082E, 0x04C9FEAB, 0x01D30964, 0xFA95FD3D,
+ 0x0000082E, 0x00002000, 0x00002000, 0x00000000
+};
+
+/* 709 RGB to YCbCr */
+static const u32 rgb_to_ycbcr_709[8] = {
+ 0xF891082F, 0x0367FF40, 0x01280B71, 0xF9B1FE20,
+ 0x0000082F, 0x00002000, 0x00002000, 0x00000000
+};
+
+static u32 tvout_read(struct sti_tvout *tvout, int offset)
+{
+ return readl(tvout->regs + offset);
+}
+
+static void tvout_write(struct sti_tvout *tvout, u32 val, int offset)
+{
+ writel(val, tvout->regs + offset);
+}
+
+/**
+ * Set the clipping mode of a VIP
+ *
+ * @tvout: tvout structure
+ * @cr_r:
+ * @y_g:
+ * @cb_b:
+ */
+static void tvout_vip_set_color_order(struct sti_tvout *tvout,
+ u32 cr_r, u32 y_g, u32 cb_b)
+{
+ u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+ val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT);
+ val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT);
+ val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT);
+ val |= cr_r << TVO_VIP_REORDER_R_SHIFT;
+ val |= y_g << TVO_VIP_REORDER_G_SHIFT;
+ val |= cb_b << TVO_VIP_REORDER_B_SHIFT;
+
+ tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Set the clipping mode of a VIP
+ *
+ * @tvout: tvout structure
+ * @range: clipping range
+ */
+static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range)
+{
+ u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+ val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT);
+ val |= range << TVO_VIP_CLIP_SHIFT;
+ tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Set the rounded value of a VIP
+ *
+ * @tvout: tvout structure
+ * @rnd: rounded val per component
+ */
+static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd)
+{
+ u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+ val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT);
+ val |= rnd << TVO_VIP_RND_SHIFT;
+ tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Select the VIP input
+ *
+ * @tvout: tvout structure
+ * @sel_input: selected_input (main/aux + conv)
+ */
+static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
+ bool main_path,
+ bool sel_input_logic_inverted,
+ enum sti_tvout_video_out_type video_out)
+{
+ u32 sel_input;
+ u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+ if (main_path)
+ sel_input = TVO_VIP_SEL_INPUT_MAIN;
+ else
+ sel_input = TVO_VIP_SEL_INPUT_AUX;
+
+ switch (video_out) {
+ case STI_TVOUT_VIDEO_OUT_RGB:
+ sel_input |= TVO_VIP_SEL_INPUT_BYPASSED;
+ break;
+ case STI_TVOUT_VIDEO_OUT_YUV:
+ sel_input &= ~TVO_VIP_SEL_INPUT_BYPASSED;
+ break;
+ }
+
+ /* on stih407 chip the sel_input bypass mode logic is inverted */
+ if (sel_input_logic_inverted)
+ sel_input = sel_input ^ TVO_VIP_SEL_INPUT_BYPASS_MASK;
+
+ val &= ~TVO_VIP_SEL_INPUT_MASK;
+ val |= sel_input;
+ tvout_write(tvout, val, TVO_VIP_HDMI);
+}
+
+/**
+ * Select the input video signed or unsigned
+ *
+ * @tvout: tvout structure
+ * @in_vid_signed: used video input format
+ */
+static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt)
+{
+ u32 val = tvout_read(tvout, TVO_VIP_HDMI);
+
+ val &= ~TVO_IN_FMT_SIGNED;
+ val |= in_vid_fmt;
+ tvout_write(tvout, val, TVO_MAIN_IN_VID_FORMAT);
+}
+
+/**
+ * Start VIP block for HDMI output
+ *
+ * @tvout: pointer on tvout structure
+ * @main_path: true if main path has to be used in the vip configuration
+ * else aux path is used.
+ */
+static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
+{
+ struct device_node *node = tvout->dev->of_node;
+ bool sel_input_logic_inverted = false;
+
+ dev_dbg(tvout->dev, "%s\n", __func__);
+
+ if (main_path) {
+ DRM_DEBUG_DRIVER("main vip for hdmi\n");
+ /* select the input sync for hdmi = VTG set 1 */
+ tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL);
+ } else {
+ DRM_DEBUG_DRIVER("aux vip for hdmi\n");
+ /* select the input sync for hdmi = VTG set 1 */
+ tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL);
+ }
+
+ /* set color channel order */
+ tvout_vip_set_color_order(tvout,
+ TVO_VIP_REORDER_CR_R_SEL,
+ TVO_VIP_REORDER_Y_G_SEL,
+ TVO_VIP_REORDER_CB_B_SEL);
+
+ /* set clipping mode (Limited range RGB/Y) */
+ tvout_vip_set_clip_mode(tvout, TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y);
+
+ /* set round mode (rounded to 8-bit per component) */
+ tvout_vip_set_rnd(tvout, TVO_VIP_RND_8BIT_ROUNDED);
+
+ if (of_device_is_compatible(node, "st,stih407-tvout")) {
+ /* set input video format */
+ tvout_vip_set_in_vid_fmt(tvout->regs + TVO_MAIN_IN_VID_FORMAT,
+ TVO_IN_FMT_SIGNED);
+ sel_input_logic_inverted = true;
+ }
+
+ /* input selection */
+ tvout_vip_set_sel_input(tvout, main_path,
+ sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB);
+}
+
+/**
+ * Start HDF VIP and HD DAC
+ *
+ * @tvout: pointer on tvout structure
+ * @main_path: true if main path has to be used in the vip configuration
+ * else aux path is used.
+ */
+static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
+{
+ struct device_node *node = tvout->dev->of_node;
+ bool sel_input_logic_inverted = false;
+
+ dev_dbg(tvout->dev, "%s\n", __func__);
+
+ if (!main_path) {
+ DRM_ERROR("HD Analog on aux not implemented\n");
+ return;
+ }
+
+ DRM_DEBUG_DRIVER("main vip for HDF\n");
+
+ /* set color channel order */
+ tvout_vip_set_color_order(tvout->regs + TVO_VIP_HDF,
+ TVO_VIP_REORDER_CR_R_SEL,
+ TVO_VIP_REORDER_Y_G_SEL,
+ TVO_VIP_REORDER_CB_B_SEL);
+
+ /* set clipping mode (Limited range RGB/Y) */
+ tvout_vip_set_clip_mode(tvout->regs + TVO_VIP_HDF,
+ TVO_VIP_CLIP_LIMITED_RANGE_CB_CR);
+
+ /* set round mode (rounded to 10-bit per component) */
+ tvout_vip_set_rnd(tvout->regs + TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);
+
+ if (of_device_is_compatible(node, "st,stih407-tvout")) {
+ /* set input video format */
+ tvout_vip_set_in_vid_fmt(tvout, TVO_IN_FMT_SIGNED);
+ sel_input_logic_inverted = true;
+ }
+
+ /* Input selection */
+ tvout_vip_set_sel_input(tvout->regs + TVO_VIP_HDF,
+ main_path,
+ sel_input_logic_inverted,
+ STI_TVOUT_VIDEO_OUT_YUV);
+
+ /* select the input sync for HD analog = VTG set 3
+ * and HD DCS = VTG set 2 */
+ tvout_write(tvout,
+ (TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT)
+ | TVO_SYNC_MAIN_VTG_SET_3,
+ TVO_HD_SYNC_SEL);
+
+ /* power up HD DAC */
+ tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
+}
+
+static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+static bool sti_tvout_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void sti_tvout_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void sti_tvout_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder);
+
+ drm_encoder_cleanup(encoder);
+ kfree(sti_encoder);
+}
+
+static const struct drm_encoder_funcs sti_tvout_encoder_funcs = {
+ .destroy = sti_tvout_encoder_destroy,
+};
+
+static void sti_hda_encoder_commit(struct drm_encoder *encoder)
+{
+ struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+ tvout_hda_start(tvout, true);
+}
+
+static void sti_hda_encoder_disable(struct drm_encoder *encoder)
+{
+ struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+ /* reset VIP register */
+ tvout_write(tvout, 0x0, TVO_VIP_HDF);
+
+ /* power down HD DAC */
+ tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF);
+}
+
+static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = {
+ .dpms = sti_tvout_encoder_dpms,
+ .mode_fixup = sti_tvout_encoder_mode_fixup,
+ .mode_set = sti_tvout_encoder_mode_set,
+ .prepare = sti_tvout_encoder_prepare,
+ .commit = sti_hda_encoder_commit,
+ .disable = sti_hda_encoder_disable,
+};
+
+static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
+ struct sti_tvout *tvout)
+{
+ struct sti_tvout_encoder *encoder;
+ struct drm_encoder *drm_encoder;
+
+ encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
+ if (!encoder)
+ return NULL;
+
+ encoder->tvout = tvout;
+
+ drm_encoder = (struct drm_encoder *) encoder;
+
+ drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+ drm_encoder->possible_clones = 1 << 0;
+
+ drm_encoder_init(dev, drm_encoder,
+ &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC);
+
+ drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs);
+
+ return drm_encoder;
+}
+
+static void sti_hdmi_encoder_commit(struct drm_encoder *encoder)
+{
+ struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+ tvout_hdmi_start(tvout, true);
+}
+
+static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct sti_tvout *tvout = to_sti_tvout(encoder);
+
+ /* reset VIP register */
+ tvout_write(tvout, 0x0, TVO_VIP_HDMI);
+}
+
+static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = {
+ .dpms = sti_tvout_encoder_dpms,
+ .mode_fixup = sti_tvout_encoder_mode_fixup,
+ .mode_set = sti_tvout_encoder_mode_set,
+ .prepare = sti_tvout_encoder_prepare,
+ .commit = sti_hdmi_encoder_commit,
+ .disable = sti_hdmi_encoder_disable,
+};
+
+static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
+ struct sti_tvout *tvout)
+{
+ struct sti_tvout_encoder *encoder;
+ struct drm_encoder *drm_encoder;
+
+ encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
+ if (!encoder)
+ return NULL;
+
+ encoder->tvout = tvout;
+
+ drm_encoder = (struct drm_encoder *) encoder;
+
+ drm_encoder->possible_crtcs = ENCODER_MAIN_CRTC_MASK;
+ drm_encoder->possible_clones = 1 << 1;
+
+ drm_encoder_init(dev, drm_encoder,
+ &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS);
+
+ drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs);
+
+ return drm_encoder;
+}
+
+static void sti_tvout_create_encoders(struct drm_device *dev,
+ struct sti_tvout *tvout)
+{
+ tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout);
+ tvout->hda = sti_tvout_create_hda_encoder(dev, tvout);
+}
+
+static void sti_tvout_destroy_encoders(struct sti_tvout *tvout)
+{
+ if (tvout->hdmi)
+ drm_encoder_cleanup(tvout->hdmi);
+ tvout->hdmi = NULL;
+
+ if (tvout->hda)
+ drm_encoder_cleanup(tvout->hda);
+ tvout->hda = NULL;
+}
+
+static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
+{
+ struct sti_tvout *tvout = dev_get_drvdata(dev);
+ struct drm_device *drm_dev = data;
+ unsigned int i;
+ int ret;
+
+ tvout->drm_dev = drm_dev;
+
+ /* set preformatter matrix */
+ for (i = 0; i < 8; i++) {
+ tvout_write(tvout, rgb_to_ycbcr_601[i],
+ TVO_CSC_MAIN_M0 + (i * 4));
+ tvout_write(tvout, rgb_to_ycbcr_601[i],
+ TVO_CSC_AUX_M0 + (i * 4));
+ }
+
+ sti_tvout_create_encoders(drm_dev, tvout);
+
+ ret = component_bind_all(dev, drm_dev);
+ if (ret)
+ sti_tvout_destroy_encoders(tvout);
+
+ return ret;
+}
+
+static void sti_tvout_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ /* do nothing */
+}
+
+static const struct component_ops sti_tvout_ops = {
+ .bind = sti_tvout_bind,
+ .unbind = sti_tvout_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int sti_tvout_master_bind(struct device *dev)
+{
+ return 0;
+}
+
+static void sti_tvout_master_unbind(struct device *dev)
+{
+ /* do nothing */
+}
+
+static const struct component_master_ops sti_tvout_master_ops = {
+ .bind = sti_tvout_master_bind,
+ .unbind = sti_tvout_master_unbind,
+};
+
+static int sti_tvout_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct sti_tvout *tvout;
+ struct resource *res;
+ struct device_node *child_np;
+ struct component_match *match = NULL;
+
+ DRM_INFO("%s\n", __func__);
+
+ if (!node)
+ return -ENODEV;
+
+ tvout = devm_kzalloc(dev, sizeof(*tvout), GFP_KERNEL);
+ if (!tvout)
+ return -ENOMEM;
+
+ tvout->dev = dev;
+
+ /* get Memory ressources */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg");
+ if (!res) {
+ DRM_ERROR("Invalid glue resource\n");
+ return -ENOMEM;
+ }
+ tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+ if (IS_ERR(tvout->regs))
+ return PTR_ERR(tvout->regs);
+
+ /* get reset resources */
+ tvout->reset = devm_reset_control_get(dev, "tvout");
+ /* take tvout out of reset */
+ if (!IS_ERR(tvout->reset))
+ reset_control_deassert(tvout->reset);
+
+ platform_set_drvdata(pdev, tvout);
+
+ of_platform_populate(node, NULL, NULL, dev);
+
+ child_np = of_get_next_available_child(node, NULL);
+
+ while (child_np) {
+ component_match_add(dev, &match, compare_of, child_np);
+ of_node_put(child_np);
+ child_np = of_get_next_available_child(node, child_np);
+ }
+
+ component_master_add_with_match(dev, &sti_tvout_master_ops, match);
+
+ return component_add(dev, &sti_tvout_ops);
+}
+
+static int sti_tvout_remove(struct platform_device *pdev)
+{
+ component_master_del(&pdev->dev, &sti_tvout_master_ops);
+ component_del(&pdev->dev, &sti_tvout_ops);
+ return 0;
+}
+
+static struct of_device_id tvout_of_match[] = {
+ { .compatible = "st,stih416-tvout", },
+ { .compatible = "st,stih407-tvout", },
+ { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, tvout_of_match);
+
+struct platform_driver sti_tvout_driver = {
+ .driver = {
+ .name = "sti-tvout",
+ .owner = THIS_MODULE,
+ .of_match_table = tvout_of_match,
+ },
+ .probe = sti_tvout_probe,
+ .remove = sti_tvout_remove,
+};
+
+module_platform_driver(sti_tvout_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vid.c b/drivers/gpu/drm/sti/sti_vid.c
new file mode 100644
index 000000000000..10ced6a479f4
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_vid.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <drm/drmP.h>
+
+#include "sti_layer.h"
+#include "sti_vid.h"
+#include "sti_vtg.h"
+
+/* Registers */
+#define VID_CTL 0x00
+#define VID_ALP 0x04
+#define VID_CLF 0x08
+#define VID_VPO 0x0C
+#define VID_VPS 0x10
+#define VID_KEY1 0x28
+#define VID_KEY2 0x2C
+#define VID_MPR0 0x30
+#define VID_MPR1 0x34
+#define VID_MPR2 0x38
+#define VID_MPR3 0x3C
+#define VID_MST 0x68
+#define VID_BC 0x70
+#define VID_TINT 0x74
+#define VID_CSAT 0x78
+
+/* Registers values */
+#define VID_CTL_IGNORE (BIT(31) | BIT(30))
+#define VID_CTL_PSI_ENABLE (BIT(2) | BIT(1) | BIT(0))
+#define VID_ALP_OPAQUE 0x00000080
+#define VID_BC_DFLT 0x00008000
+#define VID_TINT_DFLT 0x00000000
+#define VID_CSAT_DFLT 0x00000080
+/* YCbCr to RGB BT709:
+ * R = Y+1.5391Cr
+ * G = Y-0.4590Cr-0.1826Cb
+ * B = Y+1.8125Cb */
+#define VID_MPR0_BT709 0x0A800000
+#define VID_MPR1_BT709 0x0AC50000
+#define VID_MPR2_BT709 0x07150545
+#define VID_MPR3_BT709 0x00000AE8
+
+static int sti_vid_prepare_layer(struct sti_layer *vid, bool first_prepare)
+{
+ u32 val;
+
+ /* Unmask */
+ val = readl(vid->regs + VID_CTL);
+ val &= ~VID_CTL_IGNORE;
+ writel(val, vid->regs + VID_CTL);
+
+ return 0;
+}
+
+static int sti_vid_commit_layer(struct sti_layer *vid)
+{
+ struct drm_display_mode *mode = vid->mode;
+ u32 ydo, xdo, yds, xds;
+
+ ydo = sti_vtg_get_line_number(*mode, vid->dst_y);
+ yds = sti_vtg_get_line_number(*mode, vid->dst_y + vid->dst_h - 1);
+ xdo = sti_vtg_get_pixel_number(*mode, vid->dst_x);
+ xds = sti_vtg_get_pixel_number(*mode, vid->dst_x + vid->dst_w - 1);
+
+ writel((ydo << 16) | xdo, vid->regs + VID_VPO);
+ writel((yds << 16) | xds, vid->regs + VID_VPS);
+
+ return 0;
+}
+
+static int sti_vid_disable_layer(struct sti_layer *vid)
+{
+ u32 val;
+
+ /* Mask */
+ val = readl(vid->regs + VID_CTL);
+ val |= VID_CTL_IGNORE;
+ writel(val, vid->regs + VID_CTL);
+
+ return 0;
+}
+
+static const uint32_t *sti_vid_get_formats(struct sti_layer *layer)
+{
+ return NULL;
+}
+
+static unsigned int sti_vid_get_nb_formats(struct sti_layer *layer)
+{
+ return 0;
+}
+
+static void sti_vid_init(struct sti_layer *vid)
+{
+ /* Enable PSI, Mask layer */
+ writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
+
+ /* Opaque */
+ writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);
+
+ /* Color conversion parameters */
+ writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
+ writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
+ writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
+ writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
+
+ /* Brightness, contrast, tint, saturation */
+ writel(VID_BC_DFLT, vid->regs + VID_BC);
+ writel(VID_TINT_DFLT, vid->regs + VID_TINT);
+ writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
+}
+
+static const struct sti_layer_funcs vid_ops = {
+ .get_formats = sti_vid_get_formats,
+ .get_nb_formats = sti_vid_get_nb_formats,
+ .init = sti_vid_init,
+ .prepare = sti_vid_prepare_layer,
+ .commit = sti_vid_commit_layer,
+ .disable = sti_vid_disable_layer,
+};
+
+struct sti_layer *sti_vid_create(struct device *dev)
+{
+ struct sti_layer *vid;
+
+ vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
+ if (!vid) {
+ DRM_ERROR("Failed to allocate memory for VID\n");
+ return NULL;
+ }
+
+ vid->ops = &vid_ops;
+
+ return vid;
+}
diff --git a/drivers/gpu/drm/sti/sti_vid.h b/drivers/gpu/drm/sti/sti_vid.h
new file mode 100644
index 000000000000..2c0aecd63294
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_vid.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_VID_H_
+#define _STI_VID_H_
+
+struct sti_layer *sti_vid_create(struct device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/sti/sti_vtac.c b/drivers/gpu/drm/sti/sti_vtac.c
new file mode 100644
index 000000000000..82a51d488434
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_vtac.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+/* registers offset */
+#define VTAC_CONFIG 0x00
+#define VTAC_RX_FIFO_CONFIG 0x04
+#define VTAC_FIFO_CONFIG_VAL 0x04
+
+#define VTAC_SYS_CFG8521 0x824
+#define VTAC_SYS_CFG8522 0x828
+
+/* Number of phyts per pixel */
+#define VTAC_2_5_PPP 0x0005
+#define VTAC_3_PPP 0x0006
+#define VTAC_4_PPP 0x0008
+#define VTAC_5_PPP 0x000A
+#define VTAC_6_PPP 0x000C
+#define VTAC_13_PPP 0x001A
+#define VTAC_14_PPP 0x001C
+#define VTAC_15_PPP 0x001E
+#define VTAC_16_PPP 0x0020
+#define VTAC_17_PPP 0x0022
+#define VTAC_18_PPP 0x0024
+
+/* enable bits */
+#define VTAC_ENABLE 0x3003
+
+#define VTAC_TX_PHY_ENABLE_CLK_PHY BIT(0)
+#define VTAC_TX_PHY_ENABLE_CLK_DLL BIT(1)
+#define VTAC_TX_PHY_PLL_NOT_OSC_MODE BIT(3)
+#define VTAC_TX_PHY_RST_N_DLL_SWITCH BIT(4)
+#define VTAC_TX_PHY_PROG_N3 BIT(9)
+
+
+/**
+ * VTAC mode structure
+ *
+ * @vid_in_width: Video Data Resolution
+ * @phyts_width: Width of phyt buses(phyt low and phyt high).
+ * @phyts_per_pixel: Number of phyts sent per pixel
+ */
+struct sti_vtac_mode {
+ u32 vid_in_width;
+ u32 phyts_width;
+ u32 phyts_per_pixel;
+};
+
+static const struct sti_vtac_mode vtac_mode_main = {0x2, 0x2, VTAC_5_PPP};
+static const struct sti_vtac_mode vtac_mode_aux = {0x1, 0x0, VTAC_17_PPP};
+
+/**
+ * VTAC structure
+ *
+ * @dev: pointer to device structure
+ * @regs: ioremapped registers for RX and TX devices
+ * @phy_regs: phy registers for TX device
+ * @clk: clock
+ * @mode: main or auxillary configuration mode
+ */
+struct sti_vtac {
+ struct device *dev;
+ void __iomem *regs;
+ void __iomem *phy_regs;
+ struct clk *clk;
+ const struct sti_vtac_mode *mode;
+};
+
+static void sti_vtac_rx_set_config(struct sti_vtac *vtac)
+{
+ u32 config;
+
+ /* Enable VTAC clock */
+ if (clk_prepare_enable(vtac->clk))
+ DRM_ERROR("Failed to prepare/enable vtac_rx clock.\n");
+
+ writel(VTAC_FIFO_CONFIG_VAL, vtac->regs + VTAC_RX_FIFO_CONFIG);
+
+ config = VTAC_ENABLE;
+ config |= vtac->mode->vid_in_width << 4;
+ config |= vtac->mode->phyts_width << 16;
+ config |= vtac->mode->phyts_per_pixel << 23;
+ writel(config, vtac->regs + VTAC_CONFIG);
+}
+
+static void sti_vtac_tx_set_config(struct sti_vtac *vtac)
+{
+ u32 phy_config;
+ u32 config;
+
+ /* Enable VTAC clock */
+ if (clk_prepare_enable(vtac->clk))
+ DRM_ERROR("Failed to prepare/enable vtac_tx clock.\n");
+
+ /* Configure vtac phy */
+ phy_config = 0x00000000;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8522);
+ phy_config = VTAC_TX_PHY_ENABLE_CLK_PHY;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config |= VTAC_TX_PHY_PROG_N3;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config |= VTAC_TX_PHY_ENABLE_CLK_DLL;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config |= VTAC_TX_PHY_RST_N_DLL_SWITCH;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config = readl(vtac->phy_regs + VTAC_SYS_CFG8521);
+ phy_config |= VTAC_TX_PHY_PLL_NOT_OSC_MODE;
+ writel(phy_config, vtac->phy_regs + VTAC_SYS_CFG8521);
+
+ /* Configure vtac tx */
+ config = VTAC_ENABLE;
+ config |= vtac->mode->vid_in_width << 4;
+ config |= vtac->mode->phyts_width << 16;
+ config |= vtac->mode->phyts_per_pixel << 23;
+ writel(config, vtac->regs + VTAC_CONFIG);
+}
+
+static const struct of_device_id vtac_of_match[] = {
+ {
+ .compatible = "st,vtac-main",
+ .data = &vtac_mode_main,
+ }, {
+ .compatible = "st,vtac-aux",
+ .data = &vtac_mode_aux,
+ }, {
+ /* end node */
+ }
+};
+MODULE_DEVICE_TABLE(of, vtac_of_match);
+
+static int sti_vtac_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *id;
+ struct sti_vtac *vtac;
+ struct resource *res;
+
+ vtac = devm_kzalloc(dev, sizeof(*vtac), GFP_KERNEL);
+ if (!vtac)
+ return -ENOMEM;
+
+ vtac->dev = dev;
+
+ id = of_match_node(vtac_of_match, np);
+ if (!id)
+ return -ENOMEM;
+
+ vtac->mode = id->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ DRM_ERROR("Invalid resource\n");
+ return -ENOMEM;
+ }
+ vtac->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(vtac->regs))
+ return PTR_ERR(vtac->regs);
+
+
+ vtac->clk = devm_clk_get(dev, "vtac");
+ if (IS_ERR(vtac->clk)) {
+ DRM_ERROR("Cannot get vtac clock\n");
+ return PTR_ERR(vtac->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ vtac->phy_regs = devm_ioremap_nocache(dev, res->start,
+ resource_size(res));
+ sti_vtac_tx_set_config(vtac);
+ } else {
+
+ sti_vtac_rx_set_config(vtac);
+ }
+
+ platform_set_drvdata(pdev, vtac);
+ DRM_INFO("%s %s\n", __func__, dev_name(vtac->dev));
+
+ return 0;
+}
+
+static int sti_vtac_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+struct platform_driver sti_vtac_driver = {
+ .driver = {
+ .name = "sti-vtac",
+ .owner = THIS_MODULE,
+ .of_match_table = vtac_of_match,
+ },
+ .probe = sti_vtac_probe,
+ .remove = sti_vtac_remove,
+};
+
+module_platform_driver(sti_vtac_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c
new file mode 100644
index 000000000000..740d6e347a62
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_vtg.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * Vincent Abriou <vincent.abriou@st.com>
+ * for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+
+#include <drm/drmP.h>
+
+#include "sti_vtg.h"
+
+#define VTG_TYPE_MASTER 0
+#define VTG_TYPE_SLAVE_BY_EXT0 1
+
+/* registers offset */
+#define VTG_MODE 0x0000
+#define VTG_CLKLN 0x0008
+#define VTG_HLFLN 0x000C
+#define VTG_DRST_AUTOC 0x0010
+#define VTG_VID_TFO 0x0040
+#define VTG_VID_TFS 0x0044
+#define VTG_VID_BFO 0x0048
+#define VTG_VID_BFS 0x004C
+
+#define VTG_HOST_ITS 0x0078
+#define VTG_HOST_ITS_BCLR 0x007C
+#define VTG_HOST_ITM_BCLR 0x0088
+#define VTG_HOST_ITM_BSET 0x008C
+
+#define VTG_H_HD_1 0x00C0
+#define VTG_TOP_V_VD_1 0x00C4
+#define VTG_BOT_V_VD_1 0x00C8
+#define VTG_TOP_V_HD_1 0x00CC
+#define VTG_BOT_V_HD_1 0x00D0
+
+#define VTG_H_HD_2 0x00E0
+#define VTG_TOP_V_VD_2 0x00E4
+#define VTG_BOT_V_VD_2 0x00E8
+#define VTG_TOP_V_HD_2 0x00EC
+#define VTG_BOT_V_HD_2 0x00F0
+
+#define VTG_H_HD_3 0x0100
+#define VTG_TOP_V_VD_3 0x0104
+#define VTG_BOT_V_VD_3 0x0108
+#define VTG_TOP_V_HD_3 0x010C
+#define VTG_BOT_V_HD_3 0x0110
+
+#define VTG_IRQ_BOTTOM BIT(0)
+#define VTG_IRQ_TOP BIT(1)
+#define VTG_IRQ_MASK (VTG_IRQ_TOP | VTG_IRQ_BOTTOM)
+
+/* delay introduced by the Arbitrary Waveform Generator in nb of pixels */
+#define AWG_DELAY_HD (-9)
+#define AWG_DELAY_ED (-8)
+#define AWG_DELAY_SD (-7)
+
+LIST_HEAD(vtg_lookup);
+
+/**
+ * STI VTG structure
+ *
+ * @dev: pointer to device driver
+ * @data: data associated to the device
+ * @irq: VTG irq
+ * @type: VTG type (main or aux)
+ * @notifier_list: notifier callback
+ * @crtc_id: the crtc id for vblank event
+ * @slave: slave vtg
+ * @link: List node to link the structure in lookup list
+ */
+struct sti_vtg {
+ struct device *dev;
+ struct device_node *np;
+ void __iomem *regs;
+ int irq;
+ u32 irq_status;
+ struct raw_notifier_head notifier_list;
+ int crtc_id;
+ struct sti_vtg *slave;
+ struct list_head link;
+};
+
+static void vtg_register(struct sti_vtg *vtg)
+{
+ list_add_tail(&vtg->link, &vtg_lookup);
+}
+
+struct sti_vtg *of_vtg_find(struct device_node *np)
+{
+ struct sti_vtg *vtg;
+
+ list_for_each_entry(vtg, &vtg_lookup, link) {
+ if (vtg->np == np)
+ return vtg;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_vtg_find);
+
+static void vtg_reset(struct sti_vtg *vtg)
+{
+ /* reset slave and then master */
+ if (vtg->slave)
+ vtg_reset(vtg->slave);
+
+ writel(1, vtg->regs + VTG_DRST_AUTOC);
+}
+
+static void vtg_set_mode(struct sti_vtg *vtg,
+ int type, const struct drm_display_mode *mode)
+{
+ u32 tmp;
+
+ if (vtg->slave)
+ vtg_set_mode(vtg->slave, VTG_TYPE_SLAVE_BY_EXT0, mode);
+
+ writel(mode->htotal, vtg->regs + VTG_CLKLN);
+ writel(mode->vtotal * 2, vtg->regs + VTG_HLFLN);
+
+ tmp = (mode->vtotal - mode->vsync_start + 1) << 16;
+ tmp |= mode->htotal - mode->hsync_start;
+ writel(tmp, vtg->regs + VTG_VID_TFO);
+ writel(tmp, vtg->regs + VTG_VID_BFO);
+
+ tmp = (mode->vdisplay + mode->vtotal - mode->vsync_start + 1) << 16;
+ tmp |= mode->hdisplay + mode->htotal - mode->hsync_start;
+ writel(tmp, vtg->regs + VTG_VID_TFS);
+ writel(tmp, vtg->regs + VTG_VID_BFS);
+
+ /* prepare VTG set 1 and 2 for HDMI and VTG set 3 for HD DAC */
+ tmp = (mode->hsync_end - mode->hsync_start) << 16;
+ writel(tmp, vtg->regs + VTG_H_HD_1);
+ writel(tmp, vtg->regs + VTG_H_HD_2);
+
+ tmp = (mode->vsync_end - mode->vsync_start + 1) << 16;
+ tmp |= 1;
+ writel(tmp, vtg->regs + VTG_TOP_V_VD_1);
+ writel(tmp, vtg->regs + VTG_BOT_V_VD_1);
+ writel(0, vtg->regs + VTG_TOP_V_HD_1);
+ writel(0, vtg->regs + VTG_BOT_V_HD_1);
+
+ /* prepare VTG set 2 for for HD DCS */
+ writel(tmp, vtg->regs + VTG_TOP_V_VD_2);
+ writel(tmp, vtg->regs + VTG_BOT_V_VD_2);
+ writel(0, vtg->regs + VTG_TOP_V_HD_2);
+ writel(0, vtg->regs + VTG_BOT_V_HD_2);
+
+ /* prepare VTG set 3 for HD Analog in HD mode */
+ tmp = (mode->hsync_end - mode->hsync_start + AWG_DELAY_HD) << 16;
+ tmp |= mode->htotal + AWG_DELAY_HD;
+ writel(tmp, vtg->regs + VTG_H_HD_3);
+
+ tmp = (mode->vsync_end - mode->vsync_start) << 16;
+ tmp |= mode->vtotal;
+ writel(tmp, vtg->regs + VTG_TOP_V_VD_3);
+ writel(tmp, vtg->regs + VTG_BOT_V_VD_3);
+
+ tmp = (mode->htotal + AWG_DELAY_HD) << 16;
+ tmp |= mode->htotal + AWG_DELAY_HD;
+ writel(tmp, vtg->regs + VTG_TOP_V_HD_3);
+ writel(tmp, vtg->regs + VTG_BOT_V_HD_3);
+
+ /* mode */
+ writel(type, vtg->regs + VTG_MODE);
+}
+
+static void vtg_enable_irq(struct sti_vtg *vtg)
+{
+ /* clear interrupt status and mask */
+ writel(0xFFFF, vtg->regs + VTG_HOST_ITS_BCLR);
+ writel(0xFFFF, vtg->regs + VTG_HOST_ITM_BCLR);
+ writel(VTG_IRQ_MASK, vtg->regs + VTG_HOST_ITM_BSET);
+}
+
+void sti_vtg_set_config(struct sti_vtg *vtg,
+ const struct drm_display_mode *mode)
+{
+ /* write configuration */
+ vtg_set_mode(vtg, VTG_TYPE_MASTER, mode);
+
+ vtg_reset(vtg);
+
+ /* enable irq for the vtg vblank synchro */
+ if (vtg->slave)
+ vtg_enable_irq(vtg->slave);
+ else
+ vtg_enable_irq(vtg);
+}
+EXPORT_SYMBOL(sti_vtg_set_config);
+
+/**
+ * sti_vtg_get_line_number
+ *
+ * @mode: display mode to be used
+ * @y: line
+ *
+ * Return the line number according to the display mode taking
+ * into account the Sync and Back Porch information.
+ * Video frame line numbers start at 1, y starts at 0.
+ * In interlaced modes the start line is the field line number of the odd
+ * field, but y is still defined as a progressive frame.
+ */
+u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
+{
+ u32 start_line = mode.vtotal - mode.vsync_start + 1;
+
+ if (mode.flags & DRM_MODE_FLAG_INTERLACE)
+ start_line *= 2;
+
+ return start_line + y;
+}
+EXPORT_SYMBOL(sti_vtg_get_line_number);
+
+/**
+ * sti_vtg_get_pixel_number
+ *
+ * @mode: display mode to be used
+ * @x: row
+ *
+ * Return the pixel number according to the display mode taking
+ * into account the Sync and Back Porch information.
+ * Pixels are counted from 0.
+ */
+u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
+{
+ return mode.htotal - mode.hsync_start + x;
+}
+EXPORT_SYMBOL(sti_vtg_get_pixel_number);
+
+int sti_vtg_register_client(struct sti_vtg *vtg,
+ struct notifier_block *nb, int crtc_id)
+{
+ if (vtg->slave)
+ return sti_vtg_register_client(vtg->slave, nb, crtc_id);
+
+ vtg->crtc_id = crtc_id;
+ return raw_notifier_chain_register(&vtg->notifier_list, nb);
+}
+EXPORT_SYMBOL(sti_vtg_register_client);
+
+int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
+{
+ if (vtg->slave)
+ return sti_vtg_unregister_client(vtg->slave, nb);
+
+ return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
+}
+EXPORT_SYMBOL(sti_vtg_unregister_client);
+
+static irqreturn_t vtg_irq_thread(int irq, void *arg)
+{
+ struct sti_vtg *vtg = arg;
+ u32 event;
+
+ event = (vtg->irq_status & VTG_IRQ_TOP) ?
+ VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
+
+ raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vtg_irq(int irq, void *arg)
+{
+ struct sti_vtg *vtg = arg;
+
+ vtg->irq_status = readl(vtg->regs + VTG_HOST_ITS);
+
+ writel(vtg->irq_status, vtg->regs + VTG_HOST_ITS_BCLR);
+
+ /* force sync bus write */
+ readl(vtg->regs + VTG_HOST_ITS);
+
+ return IRQ_WAKE_THREAD;
+}
+
+static int vtg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np;
+ struct sti_vtg *vtg;
+ struct resource *res;
+ char irq_name[32];
+ int ret;
+
+ vtg = devm_kzalloc(dev, sizeof(*vtg), GFP_KERNEL);
+ if (!vtg)
+ return -ENOMEM;
+
+ vtg->dev = dev;
+ vtg->np = pdev->dev.of_node;
+
+ /* Get Memory ressources */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ DRM_ERROR("Get memory resource failed\n");
+ return -ENOMEM;
+ }
+ vtg->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+
+ np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0);
+ if (np) {
+ vtg->slave = of_vtg_find(np);
+
+ if (!vtg->slave)
+ return -EPROBE_DEFER;
+ } else {
+ vtg->irq = platform_get_irq(pdev, 0);
+ if (IS_ERR_VALUE(vtg->irq)) {
+ DRM_ERROR("Failed to get VTG interrupt\n");
+ return vtg->irq;
+ }
+
+ snprintf(irq_name, sizeof(irq_name), "vsync-%s",
+ dev_name(vtg->dev));
+
+ RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list);
+
+ ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
+ vtg_irq_thread, IRQF_ONESHOT, irq_name, vtg);
+ if (IS_ERR_VALUE(ret)) {
+ DRM_ERROR("Failed to register VTG interrupt\n");
+ return ret;
+ }
+ }
+
+ vtg_register(vtg);
+ platform_set_drvdata(pdev, vtg);
+
+ DRM_INFO("%s %s\n", __func__, dev_name(vtg->dev));
+
+ return 0;
+}
+
+static int vtg_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id vtg_of_match[] = {
+ { .compatible = "st,vtg", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, vtg_of_match);
+
+struct platform_driver sti_vtg_driver = {
+ .driver = {
+ .name = "sti-vtg",
+ .owner = THIS_MODULE,
+ .of_match_table = vtg_of_match,
+ },
+ .probe = vtg_probe,
+ .remove = vtg_remove,
+};
+
+module_platform_driver(sti_vtg_driver);
+
+MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sti/sti_vtg.h b/drivers/gpu/drm/sti/sti_vtg.h
new file mode 100644
index 000000000000..e84d23f1f57f
--- /dev/null
+++ b/drivers/gpu/drm/sti/sti_vtg.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2014
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com> for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _STI_VTG_H_
+#define _STI_VTG_H_
+
+#define VTG_TOP_FIELD_EVENT 1
+#define VTG_BOTTOM_FIELD_EVENT 2
+
+struct sti_vtg;
+struct drm_display_mode;
+struct notifier_block;
+
+struct sti_vtg *of_vtg_find(struct device_node *np);
+void sti_vtg_set_config(struct sti_vtg *vtg,
+ const struct drm_display_mode *mode);
+int sti_vtg_register_client(struct sti_vtg *vtg,
+ struct notifier_block *nb, int crtc_id);
+int sti_vtg_unregister_client(struct sti_vtg *vtg,
+ struct notifier_block *nb);
+
+u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y);
+u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x);
+
+#endif
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index ef40381f3909..6553fd238685 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -18,6 +18,8 @@
struct tegra_dc_soc_info {
bool supports_interlacing;
bool supports_cursor;
+ bool supports_block_linear;
+ unsigned int pitch_align;
};
struct tegra_plane {
@@ -212,15 +214,44 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
- if (window->tiled) {
- value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
- DC_WIN_BUFFER_ADDR_MODE_TILE;
+ if (dc->soc->supports_block_linear) {
+ unsigned long height = window->tiling.value;
+
+ switch (window->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WINBUF_SURFACE_KIND_PITCH;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WINBUF_SURFACE_KIND_TILED;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+ DC_WINBUF_SURFACE_KIND_BLOCK;
+ break;
+ }
+
+ tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
} else {
- value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
- DC_WIN_BUFFER_ADDR_MODE_LINEAR;
- }
+ switch (window->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ break;
- tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ DRM_ERROR("hardware doesn't support block linear mode\n");
+ return -EINVAL;
+ }
+
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ }
value = WIN_ENABLE;
@@ -288,6 +319,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct tegra_dc *dc = to_tegra_dc(crtc);
struct tegra_dc_window window;
unsigned int i;
+ int err;
memset(&window, 0, sizeof(window));
window.src.x = src_x >> 16;
@@ -301,7 +333,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
window.format = tegra_dc_format(fb->pixel_format, &window.swap);
window.bits_per_pixel = fb->bits_per_pixel;
window.bottom_up = tegra_fb_is_bottom_up(fb);
- window.tiled = tegra_fb_is_tiled(fb);
+
+ err = tegra_fb_get_tiling(fb, &window.tiling);
+ if (err < 0)
+ return err;
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
@@ -402,8 +437,14 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
{
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
unsigned int h_offset = 0, v_offset = 0;
+ struct tegra_bo_tiling tiling;
unsigned int format, swap;
unsigned long value;
+ int err;
+
+ err = tegra_fb_get_tiling(fb, &tiling);
+ if (err < 0)
+ return err;
tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -417,15 +458,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
- if (tegra_fb_is_tiled(fb)) {
- value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
- DC_WIN_BUFFER_ADDR_MODE_TILE;
+ if (dc->soc->supports_block_linear) {
+ unsigned long height = tiling.value;
+
+ switch (tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WINBUF_SURFACE_KIND_PITCH;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WINBUF_SURFACE_KIND_TILED;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+ DC_WINBUF_SURFACE_KIND_BLOCK;
+ break;
+ }
+
+ tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
} else {
- value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
- DC_WIN_BUFFER_ADDR_MODE_LINEAR;
- }
+ switch (tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ DRM_ERROR("hardware doesn't support block linear mode\n");
+ return -EINVAL;
+ }
- tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ }
/* make sure bottom-up buffers are properly displayed */
if (tegra_fb_is_bottom_up(fb)) {
@@ -1214,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client)
{
struct drm_device *drm = dev_get_drvdata(client->parent);
struct tegra_dc *dc = host1x_client_to_dc(client);
+ struct tegra_drm *tegra = drm->dev_private;
int err;
drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
drm_mode_crtc_set_gamma_size(&dc->base, 256);
drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
+ /*
+ * Keep track of the minimum pitch alignment across all display
+ * controllers.
+ */
+ if (dc->soc->pitch_align > tegra->pitch_align)
+ tegra->pitch_align = dc->soc->pitch_align;
+
err = tegra_dc_rgb_init(drm, dc);
if (err < 0 && err != -ENODEV) {
dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
@@ -1277,16 +1355,29 @@ static const struct host1x_client_ops dc_client_ops = {
static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
+ .supports_block_linear = false,
+ .pitch_align = 8,
};
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
+ .supports_block_linear = false,
+ .pitch_align = 8,
+};
+
+static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
+ .supports_interlacing = false,
+ .supports_cursor = false,
+ .supports_block_linear = false,
+ .pitch_align = 64,
};
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
+ .supports_block_linear = true,
+ .pitch_align = 64,
};
static const struct of_device_id tegra_dc_of_match[] = {
@@ -1303,6 +1394,7 @@ static const struct of_device_id tegra_dc_of_match[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
static int tegra_dc_parse_dt(struct tegra_dc *dc)
{
@@ -1430,6 +1522,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
return err;
}
+ reset_control_assert(dc->rst);
clk_disable_unprepare(dc->clk);
return 0;
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 78c5feff95d2..705c93b00794 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -428,6 +428,11 @@
#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
#define DC_WINBUF_UFLOW_STATUS 0x80a
+#define DC_WINBUF_SURFACE_KIND 0x80b
+#define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0)
+#define DC_WINBUF_SURFACE_KIND_TILED (1 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 3f132e356e9c..708f783ead47 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -382,6 +382,7 @@ static const struct of_device_id tegra_dpaux_of_match[] = {
{ .compatible = "nvidia,tegra124-dpaux", },
{ },
};
+MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
struct platform_driver tegra_dpaux_driver = {
.driver = {
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 3396f9f6a9f7..59736bb810cd 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -40,6 +40,12 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
drm_mode_config_init(drm);
+ err = tegra_drm_fb_prepare(drm);
+ if (err < 0)
+ return err;
+
+ drm_kms_helper_poll_init(drm);
+
err = host1x_device_init(device);
if (err < 0)
return err;
@@ -59,8 +65,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
if (err < 0)
return err;
- drm_kms_helper_poll_init(drm);
-
return 0;
}
@@ -128,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
return &bo->base;
}
+static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
+ struct drm_tegra_reloc __user *src,
+ struct drm_device *drm,
+ struct drm_file *file)
+{
+ u32 cmdbuf, target;
+ int err;
+
+ err = get_user(cmdbuf, &src->cmdbuf.handle);
+ if (err < 0)
+ return err;
+
+ err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset);
+ if (err < 0)
+ return err;
+
+ err = get_user(target, &src->target.handle);
+ if (err < 0)
+ return err;
+
+ err = get_user(dest->target.offset, &src->cmdbuf.offset);
+ if (err < 0)
+ return err;
+
+ err = get_user(dest->shift, &src->shift);
+ if (err < 0)
+ return err;
+
+ dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf);
+ if (!dest->cmdbuf.bo)
+ return -ENOENT;
+
+ dest->target.bo = host1x_bo_lookup(drm, file, target);
+ if (!dest->target.bo)
+ return -ENOENT;
+
+ return 0;
+}
+
int tegra_drm_submit(struct tegra_drm_context *context,
struct drm_tegra_submit *args, struct drm_device *drm,
struct drm_file *file)
@@ -180,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context,
cmdbufs++;
}
- if (copy_from_user(job->relocarray, relocs,
- sizeof(*relocs) * num_relocs)) {
- err = -EFAULT;
- goto fail;
- }
-
+ /* copy and resolve relocations from submit */
while (num_relocs--) {
- struct host1x_reloc *reloc = &job->relocarray[num_relocs];
- struct host1x_bo *cmdbuf, *target;
-
- cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf);
- target = host1x_bo_lookup(drm, file, (u32)reloc->target);
-
- reloc->cmdbuf = cmdbuf;
- reloc->target = target;
-
- if (!reloc->target || !reloc->cmdbuf) {
- err = -ENOENT;
+ err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
+ &relocs[num_relocs], drm,
+ file);
+ if (err < 0)
goto fail;
- }
}
if (copy_from_user(job->waitchk, waitchks,
@@ -451,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
return 0;
}
+
+static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_set_tiling *args = data;
+ enum tegra_bo_tiling_mode mode;
+ struct drm_gem_object *gem;
+ unsigned long value = 0;
+ struct tegra_bo *bo;
+
+ switch (args->mode) {
+ case DRM_TEGRA_GEM_TILING_MODE_PITCH:
+ mode = TEGRA_BO_TILING_MODE_PITCH;
+
+ if (args->value != 0)
+ return -EINVAL;
+
+ break;
+
+ case DRM_TEGRA_GEM_TILING_MODE_TILED:
+ mode = TEGRA_BO_TILING_MODE_TILED;
+
+ if (args->value != 0)
+ return -EINVAL;
+
+ break;
+
+ case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
+ mode = TEGRA_BO_TILING_MODE_BLOCK;
+
+ if (args->value > 5)
+ return -EINVAL;
+
+ value = args->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+
+ bo->tiling.mode = mode;
+ bo->tiling.value = value;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
+
+static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_get_tiling *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+ int err = 0;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+
+ switch (bo->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
+ args->value = 0;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
+ args->value = 0;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+ args->value = bo->tiling.value;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ drm_gem_object_unreference(gem);
+
+ return err;
+}
+
+static int tegra_gem_set_flags(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_set_flags *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+
+ if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
+ return -EINVAL;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+ bo->flags = 0;
+
+ if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
+ bo->flags |= TEGRA_BO_BOTTOM_UP;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
+
+static int tegra_gem_get_flags(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_get_flags *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+ args->flags = 0;
+
+ if (bo->flags & TEGRA_BO_BOTTOM_UP)
+ args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
#endif
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
@@ -465,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
#endif
};
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 6b8fe9d86ed4..e89c70fa82d5 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -19,6 +19,8 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_fixed.h>
+#include "gem.h"
+
struct reset_control;
struct tegra_fb {
@@ -43,6 +45,8 @@ struct tegra_drm {
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_fbdev *fbdev;
#endif
+
+ unsigned int pitch_align;
};
struct tegra_drm_client;
@@ -160,7 +164,8 @@ struct tegra_dc_window {
unsigned int stride[2];
unsigned long base[3];
bool bottom_up;
- bool tiled;
+
+ struct tegra_bo_tiling tiling;
};
/* from dc.c */
@@ -279,7 +284,9 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
unsigned int index);
bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+ struct tegra_bo_tiling *tiling);
+int tegra_drm_fb_prepare(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm);
#ifdef CONFIG_DRM_TEGRA_FBDEV
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index bd56f2affa78..f7874458926a 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -474,7 +474,8 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
value = tegra_dsi_readl(dsi, DSI_CONTROL);
- value |= DSI_CONTROL_HS_CLK_CTRL;
+ if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+ value |= DSI_CONTROL_HS_CLK_CTRL;
value &= ~DSI_CONTROL_TX_TRIG(3);
value &= ~DSI_CONTROL_DCS_ENABLE;
value |= DSI_CONTROL_VIDEO_ENABLE;
@@ -982,6 +983,7 @@ static const struct of_device_id tegra_dsi_of_match[] = {
{ .compatible = "nvidia,tegra114-dsi", },
{ },
};
+MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
struct platform_driver tegra_dsi_driver = {
.driver = {
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 9798a7080322..3513d12d5aa1 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
return false;
}
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+ struct tegra_bo_tiling *tiling)
{
struct tegra_fb *fb = to_tegra_fb(framebuffer);
- if (fb->planes[0]->flags & TEGRA_BO_TILED)
- return true;
+ /* TODO: handle YUV formats? */
+ *tiling = fb->planes[0]->tiling;
- return false;
+ return 0;
}
static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
@@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
+ struct tegra_drm *tegra = helper->dev->dev_private;
struct drm_device *drm = helper->dev;
struct drm_mode_fb_cmd2 cmd = { 0 };
unsigned int bytes_per_pixel;
@@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
cmd.width = sizes->surface_width;
cmd.height = sizes->surface_height;
- cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+ cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
+ tegra->pitch_align);
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
@@ -267,18 +270,13 @@ release:
return err;
}
-static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
.fb_probe = tegra_fbdev_probe,
};
-static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
- unsigned int preferred_bpp,
- unsigned int num_crtc,
- unsigned int max_connectors)
+static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm)
{
- struct drm_fb_helper *helper;
struct tegra_fbdev *fbdev;
- int err;
fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
if (!fbdev) {
@@ -286,13 +284,23 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
return ERR_PTR(-ENOMEM);
}
- fbdev->base.funcs = &tegra_fb_helper_funcs;
- helper = &fbdev->base;
+ drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
+
+ return fbdev;
+}
+
+static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
+ unsigned int preferred_bpp,
+ unsigned int num_crtc,
+ unsigned int max_connectors)
+{
+ struct drm_device *drm = fbdev->base.dev;
+ int err;
err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
if (err < 0) {
dev_err(drm->dev, "failed to initialize DRM FB helper\n");
- goto free;
+ return err;
}
err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
@@ -301,21 +309,17 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
goto fini;
}
- drm_helper_disable_unused_functions(drm);
-
err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
if (err < 0) {
dev_err(drm->dev, "failed to set initial configuration\n");
goto fini;
}
- return fbdev;
+ return 0;
fini:
drm_fb_helper_fini(&fbdev->base);
-free:
- kfree(fbdev);
- return ERR_PTR(err);
+ return err;
}
static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
@@ -366,7 +370,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
#endif
};
-int tegra_drm_fb_init(struct drm_device *drm)
+int tegra_drm_fb_prepare(struct drm_device *drm)
{
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_drm *tegra = drm->dev_private;
@@ -381,8 +385,7 @@ int tegra_drm_fb_init(struct drm_device *drm)
drm->mode_config.funcs = &tegra_drm_mode_funcs;
#ifdef CONFIG_DRM_TEGRA_FBDEV
- tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
- drm->mode_config.num_connector);
+ tegra->fbdev = tegra_fbdev_create(drm);
if (IS_ERR(tegra->fbdev))
return PTR_ERR(tegra->fbdev);
#endif
@@ -390,6 +393,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
return 0;
}
+int tegra_drm_fb_init(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_TEGRA_FBDEV
+ struct tegra_drm *tegra = drm->dev_private;
+ int err;
+
+ err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc,
+ drm->mode_config.num_connector);
+ if (err < 0)
+ return err;
+#endif
+
+ return 0;
+}
+
void tegra_drm_fb_exit(struct drm_device *drm)
{
#ifdef CONFIG_DRM_TEGRA_FBDEV
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index aa85b7b26f10..ce023fa3e8ae 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -16,6 +16,7 @@
#include <linux/dma-buf.h>
#include <drm/tegra_drm.h>
+#include "drm.h"
#include "gem.h"
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
@@ -126,7 +127,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
goto err_mmap;
if (flags & DRM_TEGRA_GEM_CREATE_TILED)
- bo->flags |= TEGRA_BO_TILED;
+ bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP;
@@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
struct drm_mode_create_dumb *args)
{
int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+ struct tegra_drm *tegra = drm->dev_private;
struct tegra_bo *bo;
+ min_pitch = round_up(min_pitch, tegra->pitch_align);
if (args->pitch < min_pitch)
args->pitch = min_pitch;
@@ -420,7 +423,7 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
int flags)
{
return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size,
- flags);
+ flags, NULL);
}
struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index 2f3fe96c5154..43a25c853357 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -16,8 +16,18 @@
#include <drm/drm.h>
#include <drm/drmP.h>
-#define TEGRA_BO_TILED (1 << 0)
-#define TEGRA_BO_BOTTOM_UP (1 << 1)
+#define TEGRA_BO_BOTTOM_UP (1 << 0)
+
+enum tegra_bo_tiling_mode {
+ TEGRA_BO_TILING_MODE_PITCH,
+ TEGRA_BO_TILING_MODE_TILED,
+ TEGRA_BO_TILING_MODE_BLOCK,
+};
+
+struct tegra_bo_tiling {
+ enum tegra_bo_tiling_mode mode;
+ unsigned long value;
+};
struct tegra_bo {
struct drm_gem_object gem;
@@ -26,6 +36,8 @@ struct tegra_bo {
struct sg_table *sgt;
dma_addr_t paddr;
void *vaddr;
+
+ struct tegra_bo_tiling tiling;
};
static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 7c53941f2a9e..02cd3e37a6ec 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -121,6 +121,7 @@ static const struct of_device_id gr2d_match[] = {
{ .compatible = "nvidia,tegra20-gr2d" },
{ },
};
+MODULE_DEVICE_TABLE(of, gr2d_match);
static const u32 gr2d_addr_regs[] = {
GR2D_UA_BASE_ADDR,
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 30f5ba9bd6d0..0b3f2b977ba0 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -12,7 +12,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
#include "drm.h"
#include "gem.h"
@@ -130,6 +131,7 @@ static const struct of_device_id tegra_gr3d_match[] = {
{ .compatible = "nvidia,tegra20-gr3d" },
{ }
};
+MODULE_DEVICE_TABLE(of, tegra_gr3d_match);
static const u32 gr3d_addr_regs[] = {
GR3D_IDX_ATTRIBUTE( 0),
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index ba067bb767e3..ffe26547328d 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1450,6 +1450,7 @@ static const struct of_device_id tegra_hdmi_of_match[] = {
{ .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
{ },
};
+MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match);
static int tegra_hdmi_probe(struct platform_device *pdev)
{
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index a3e4f1eca6f7..0c67d7eebc94 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -105,7 +105,7 @@ static void drm_connector_clear(struct drm_connector *connector)
static void tegra_connector_destroy(struct drm_connector *connector)
{
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
drm_connector_clear(connector);
}
@@ -140,7 +140,9 @@ static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
if (mode != DRM_MODE_DPMS_ON) {
drm_panel_disable(panel);
tegra_output_disable(output);
+ drm_panel_unprepare(panel);
} else {
+ drm_panel_prepare(panel);
tegra_output_enable(output);
drm_panel_enable(panel);
}
@@ -318,7 +320,7 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
- drm_sysfs_connector_add(&output->connector);
+ drm_connector_register(&output->connector);
output->encoder.possible_crtcs = 0x3;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 27c979b50111..7829e81f065d 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -11,7 +11,8 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
-#include <linux/tegra-powergate.h>
+
+#include <soc/tegra/pmc.h>
#include <drm/drm_dp_helper.h>
@@ -516,7 +517,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
if (err < 0) {
dev_err(sor->dev, "failed to probe eDP link: %d\n",
err);
- return err;
+ goto unlock;
}
}
@@ -525,7 +526,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
memset(&config, 0, sizeof(config));
- config.bits_per_pixel = 24; /* XXX: don't hardcode? */
+ config.bits_per_pixel = output->connector.display_info.bpc * 3;
err = tegra_sor_calc_config(sor, mode, &config, &link);
if (err < 0)
@@ -815,12 +816,22 @@ static int tegra_output_sor_enable(struct tegra_output *output)
* configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
* raster, associate with display controller)
*/
- value = SOR_STATE_ASY_VSYNCPOL |
- SOR_STATE_ASY_HSYNCPOL |
- SOR_STATE_ASY_PROTOCOL_DP_A |
+ value = SOR_STATE_ASY_PROTOCOL_DP_A |
SOR_STATE_ASY_CRC_MODE_COMPLETE |
SOR_STATE_ASY_OWNER(dc->pipe + 1);
+ if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+ value &= ~SOR_STATE_ASY_HSYNCPOL;
+
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ value |= SOR_STATE_ASY_HSYNCPOL;
+
+ if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+ value &= ~SOR_STATE_ASY_VSYNCPOL;
+
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ value |= SOR_STATE_ASY_VSYNCPOL;
+
switch (config.bits_per_pixel) {
case 24:
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
@@ -1455,6 +1466,7 @@ static const struct of_device_id tegra_sor_of_match[] = {
{ .compatible = "nvidia,tegra124-sor", },
{ },
};
+MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
struct platform_driver tegra_sor_driver = {
.driver = {
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index b20b69488dc9..6be623b4a86f 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -120,8 +120,8 @@ static int cpufreq_transition(struct notifier_block *nb,
static int tilcdc_unload(struct drm_device *dev)
{
struct tilcdc_drm_private *priv = dev->dev_private;
- struct tilcdc_module *mod, *cur;
+ drm_fbdev_cma_fini(priv->fbdev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
drm_vblank_cleanup(dev);
@@ -148,11 +148,6 @@ static int tilcdc_unload(struct drm_device *dev)
pm_runtime_disable(dev->dev);
- list_for_each_entry_safe(mod, cur, &module_list, list) {
- DBG("destroying module: %s", mod->name);
- mod->funcs->destroy(mod);
- }
-
kfree(priv);
return 0;
@@ -628,13 +623,13 @@ static int __init tilcdc_drm_init(void)
static void __exit tilcdc_drm_fini(void)
{
DBG("fini");
- tilcdc_tfp410_fini();
- tilcdc_slave_fini();
- tilcdc_panel_fini();
platform_driver_unregister(&tilcdc_platform_driver);
+ tilcdc_panel_fini();
+ tilcdc_slave_fini();
+ tilcdc_tfp410_fini();
}
-late_initcall(tilcdc_drm_init);
+module_init(tilcdc_drm_init);
module_exit(tilcdc_drm_fini);
MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index 093803683b25..7596c144a9fb 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -98,7 +98,6 @@ struct tilcdc_module;
struct tilcdc_module_ops {
/* create appropriate encoders/connectors: */
int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
- void (*destroy)(struct tilcdc_module *mod);
#ifdef CONFIG_DEBUG_FS
/* create debugfs nodes (can be NULL): */
int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 86c67329b605..4c7aa1d8134f 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -151,6 +151,7 @@ struct panel_connector {
static void panel_connector_destroy(struct drm_connector *connector)
{
struct panel_connector *panel_connector = to_panel_connector(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(panel_connector);
}
@@ -247,7 +248,7 @@ static struct drm_connector *panel_connector_create(struct drm_device *dev,
if (ret)
goto fail;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return connector;
@@ -281,23 +282,8 @@ static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
return 0;
}
-static void panel_destroy(struct tilcdc_module *mod)
-{
- struct panel_module *panel_mod = to_panel_module(mod);
-
- if (panel_mod->timings) {
- display_timings_release(panel_mod->timings);
- kfree(panel_mod->timings);
- }
-
- tilcdc_module_cleanup(mod);
- kfree(panel_mod->info);
- kfree(panel_mod);
-}
-
static const struct tilcdc_module_ops panel_module_ops = {
.modeset_init = panel_modeset_init,
- .destroy = panel_destroy,
};
/*
@@ -373,6 +359,7 @@ static int panel_probe(struct platform_device *pdev)
return -ENOMEM;
mod = &panel_mod->base;
+ pdev->dev.platform_data = mod;
tilcdc_module_init(mod, "panel", &panel_module_ops);
@@ -380,17 +367,16 @@ static int panel_probe(struct platform_device *pdev)
if (IS_ERR(pinctrl))
dev_warn(&pdev->dev, "pins are not configured\n");
-
panel_mod->timings = of_get_display_timings(node);
if (!panel_mod->timings) {
dev_err(&pdev->dev, "could not get panel timings\n");
- goto fail;
+ goto fail_free;
}
panel_mod->info = of_get_panel_info(node);
if (!panel_mod->info) {
dev_err(&pdev->dev, "could not get panel info\n");
- goto fail;
+ goto fail_timings;
}
mod->preferred_bpp = panel_mod->info->bpp;
@@ -401,13 +387,26 @@ static int panel_probe(struct platform_device *pdev)
return 0;
-fail:
- panel_destroy(mod);
+fail_timings:
+ display_timings_release(panel_mod->timings);
+
+fail_free:
+ kfree(panel_mod);
+ tilcdc_module_cleanup(mod);
return ret;
}
static int panel_remove(struct platform_device *pdev)
{
+ struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+ struct panel_module *panel_mod = to_panel_module(mod);
+
+ display_timings_release(panel_mod->timings);
+
+ tilcdc_module_cleanup(mod);
+ kfree(panel_mod->info);
+ kfree(panel_mod);
+
return 0;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
index 595068ba2d5e..3775fd49dac4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -166,6 +166,7 @@ struct slave_connector {
static void slave_connector_destroy(struct drm_connector *connector)
{
struct slave_connector *slave_connector = to_slave_connector(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(slave_connector);
}
@@ -261,7 +262,7 @@ static struct drm_connector *slave_connector_create(struct drm_device *dev,
if (ret)
goto fail;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return connector;
@@ -295,17 +296,8 @@ static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
return 0;
}
-static void slave_destroy(struct tilcdc_module *mod)
-{
- struct slave_module *slave_mod = to_slave_module(mod);
-
- tilcdc_module_cleanup(mod);
- kfree(slave_mod);
-}
-
static const struct tilcdc_module_ops slave_module_ops = {
.modeset_init = slave_modeset_init,
- .destroy = slave_destroy,
};
/*
@@ -355,10 +347,13 @@ static int slave_probe(struct platform_device *pdev)
}
slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
- if (!slave_mod)
- return -ENOMEM;
+ if (!slave_mod) {
+ ret = -ENOMEM;
+ goto fail_adapter;
+ }
mod = &slave_mod->base;
+ pdev->dev.platform_data = mod;
mod->preferred_bpp = slave_info.bpp;
@@ -373,10 +368,20 @@ static int slave_probe(struct platform_device *pdev)
tilcdc_slave_probedefer(false);
return 0;
+
+fail_adapter:
+ i2c_put_adapter(slavei2c);
+ return ret;
}
static int slave_remove(struct platform_device *pdev)
{
+ struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+ struct slave_module *slave_mod = to_slave_module(mod);
+
+ tilcdc_module_cleanup(mod);
+ kfree(slave_mod);
+
return 0;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
index c38b56b268ac..354c47ca6374 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -167,6 +167,7 @@ struct tfp410_connector {
static void tfp410_connector_destroy(struct drm_connector *connector)
{
struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(tfp410_connector);
}
@@ -261,7 +262,7 @@ static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
if (ret)
goto fail;
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
return connector;
@@ -295,23 +296,8 @@ static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev
return 0;
}
-static void tfp410_destroy(struct tilcdc_module *mod)
-{
- struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
-
- if (tfp410_mod->i2c)
- i2c_put_adapter(tfp410_mod->i2c);
-
- if (!IS_ERR_VALUE(tfp410_mod->gpio))
- gpio_free(tfp410_mod->gpio);
-
- tilcdc_module_cleanup(mod);
- kfree(tfp410_mod);
-}
-
static const struct tilcdc_module_ops tfp410_module_ops = {
.modeset_init = tfp410_modeset_init,
- .destroy = tfp410_destroy,
};
/*
@@ -341,6 +327,7 @@ static int tfp410_probe(struct platform_device *pdev)
return -ENOMEM;
mod = &tfp410_mod->base;
+ pdev->dev.platform_data = mod;
tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
@@ -364,6 +351,7 @@ static int tfp410_probe(struct platform_device *pdev)
tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
if (!tfp410_mod->i2c) {
dev_err(&pdev->dev, "could not get i2c\n");
+ of_node_put(i2c_node);
goto fail;
}
@@ -377,19 +365,32 @@ static int tfp410_probe(struct platform_device *pdev)
ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
if (ret) {
dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
- goto fail;
+ goto fail_adapter;
}
}
return 0;
+fail_adapter:
+ i2c_put_adapter(tfp410_mod->i2c);
+
fail:
- tfp410_destroy(mod);
+ kfree(tfp410_mod);
+ tilcdc_module_cleanup(mod);
return ret;
}
static int tfp410_remove(struct platform_device *pdev)
{
+ struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
+ struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
+
+ i2c_put_adapter(tfp410_mod->i2c);
+ gpio_free(tfp410_mod->gpio);
+
+ tilcdc_module_cleanup(mod);
+ kfree(tfp410_mod);
+
return 0;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 4ab9f7171c4f..3da89d5dab60 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -412,7 +412,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
int ret;
spin_lock(&glob->lru_lock);
- ret = __ttm_bo_reserve(bo, false, true, false, 0);
+ ret = __ttm_bo_reserve(bo, false, true, false, NULL);
spin_lock(&bdev->fence_lock);
(void) ttm_bo_wait(bo, false, false, true);
@@ -514,7 +514,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
return ret;
spin_lock(&glob->lru_lock);
- ret = __ttm_bo_reserve(bo, false, true, false, 0);
+ ret = __ttm_bo_reserve(bo, false, true, false, NULL);
/*
* We raced, and lost, someone else holds the reservation now,
@@ -577,11 +577,11 @@ static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
kref_get(&nentry->list_kref);
}
- ret = __ttm_bo_reserve(entry, false, true, false, 0);
+ ret = __ttm_bo_reserve(entry, false, true, false, NULL);
if (remove_all && ret) {
spin_unlock(&glob->lru_lock);
ret = __ttm_bo_reserve(entry, false, false,
- false, 0);
+ false, NULL);
spin_lock(&glob->lru_lock);
}
@@ -726,7 +726,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
spin_lock(&glob->lru_lock);
list_for_each_entry(bo, &man->lru, lru) {
- ret = __ttm_bo_reserve(bo, false, true, false, 0);
+ ret = __ttm_bo_reserve(bo, false, true, false, NULL);
if (!ret)
break;
}
@@ -784,7 +784,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
int ret;
do {
- ret = (*man->func->get_node)(man, bo, placement, mem);
+ ret = (*man->func->get_node)(man, bo, placement, 0, mem);
if (unlikely(ret != 0))
return ret;
if (mem->mm_node)
@@ -897,7 +897,8 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
if (man->has_type && man->use_type) {
type_found = true;
- ret = (*man->func->get_node)(man, bo, placement, mem);
+ ret = (*man->func->get_node)(man, bo, placement,
+ cur_flags, mem);
if (unlikely(ret))
return ret;
}
@@ -937,7 +938,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
ttm_flag_masked(&cur_flags, placement->busy_placement[i],
~TTM_PL_MASK_MEMTYPE);
-
if (mem_type == TTM_PL_SYSTEM) {
mem->mem_type = mem_type;
mem->placement = cur_flags;
@@ -1595,7 +1595,7 @@ int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
* Using ttm_bo_reserve makes sure the lru lists are updated.
*/
- ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
+ ret = ttm_bo_reserve(bo, true, no_wait, false, NULL);
if (unlikely(ret != 0))
return ret;
spin_lock(&bdev->fence_lock);
@@ -1630,7 +1630,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
spin_lock(&glob->lru_lock);
list_for_each_entry(bo, &glob->swap_lru, swap) {
- ret = __ttm_bo_reserve(bo, false, true, false, 0);
+ ret = __ttm_bo_reserve(bo, false, true, false, NULL);
if (!ret)
break;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c
index bd850c9f4bca..9e103a4875c8 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c
@@ -50,6 +50,7 @@ struct ttm_range_manager {
static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
+ uint32_t flags,
struct ttm_mem_reg *mem)
{
struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv;
@@ -67,7 +68,7 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man,
if (!node)
return -ENOMEM;
- if (bo->mem.placement & TTM_PL_FLAG_TOPDOWN)
+ if (flags & TTM_PL_FLAG_TOPDOWN)
aflags = DRM_MM_CREATE_TOP;
spin_lock(&rman->lock);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 1df856f78568..30e5d90cb7bc 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -500,7 +500,7 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp)
pgprot_val(tmp) |= _PAGE_GUARDED;
}
#endif
-#if defined(__ia64__)
+#if defined(__ia64__) || defined(__arm__)
if (caching_flags & TTM_PL_FLAG_WC)
tmp = pgprot_writecombine(tmp);
else
diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c
index d7f92fe9d904..66fc6395eb54 100644
--- a/drivers/gpu/drm/ttm/ttm_module.c
+++ b/drivers/gpu/drm/ttm/ttm_module.c
@@ -35,7 +35,7 @@
#include <drm/drm_sysfs.h>
static DECLARE_WAIT_QUEUE_HEAD(exit_q);
-atomic_t device_released;
+static atomic_t device_released;
static struct device_type ttm_drm_class_type = {
.name = "ttm",
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c
index d2a053352789..12c87110db3a 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/ttm/ttm_object.c
@@ -695,7 +695,7 @@ int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
}
dma_buf = dma_buf_export(prime, &tdev->ops,
- prime->size, flags);
+ prime->size, flags, NULL);
if (IS_ERR(dma_buf)) {
ret = PTR_ERR(dma_buf);
ttm_mem_global_free(tdev->mem_glob,
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 863bef9f9234..09874d695188 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
*
* @pool: to free the pages from
* @free_all: If set to true will free all pages in pool
+ * @gfp: GFP flags.
**/
-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
+static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
+ gfp_t gfp)
{
unsigned long irq_flags;
struct page *p;
@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
if (NUM_PAGES_TO_ALLOC < nr_free)
npages_to_free = NUM_PAGES_TO_ALLOC;
- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
- GFP_KERNEL);
+ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
if (!pages_to_free) {
pr_err("Failed to allocate memory for pool free operation\n");
return 0;
@@ -382,32 +383,35 @@ out:
*
* XXX: (dchinner) Deadlock warning!
*
- * ttm_page_pool_free() does memory allocation using GFP_KERNEL. that means
- * this can deadlock when called a sc->gfp_mask that is not equal to
- * GFP_KERNEL.
+ * We need to pass sc->gfp_mask to ttm_page_pool_free().
*
* This code is crying out for a shrinker per pool....
*/
static unsigned long
ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
- static atomic_t start_pool = ATOMIC_INIT(0);
+ static DEFINE_MUTEX(lock);
+ static unsigned start_pool;
unsigned i;
- unsigned pool_offset = atomic_add_return(1, &start_pool);
+ unsigned pool_offset;
struct ttm_page_pool *pool;
int shrink_pages = sc->nr_to_scan;
unsigned long freed = 0;
- pool_offset = pool_offset % NUM_POOLS;
+ if (!mutex_trylock(&lock))
+ return SHRINK_STOP;
+ pool_offset = ++start_pool % NUM_POOLS;
/* select start pool in round robin fashion */
for (i = 0; i < NUM_POOLS; ++i) {
unsigned nr_free = shrink_pages;
if (shrink_pages == 0)
break;
pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
- shrink_pages = ttm_page_pool_free(pool, nr_free);
+ shrink_pages = ttm_page_pool_free(pool, nr_free,
+ sc->gfp_mask);
freed += nr_free - shrink_pages;
}
+ mutex_unlock(&lock);
return freed;
}
@@ -706,7 +710,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
}
spin_unlock_irqrestore(&pool->lock, irq_flags);
if (npages)
- ttm_page_pool_free(pool, npages);
+ ttm_page_pool_free(pool, npages, GFP_KERNEL);
}
/*
@@ -790,7 +794,7 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
return 0;
}
-static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags,
+static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
char *name)
{
spin_lock_init(&pool->lock);
@@ -846,7 +850,8 @@ void ttm_page_alloc_fini(void)
ttm_pool_mm_shrink_fini(_manager);
for (i = 0; i < NUM_POOLS; ++i)
- ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
+ ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES,
+ GFP_KERNEL);
kobject_put(&_manager->kobj);
_manager = NULL;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index fb8259f69839..c96db433f8af 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page)
*
* @pool: to free the pages from
* @nr_free: If set to true will free all pages in pool
+ * @gfp: GFP flags.
**/
-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
+static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
+ gfp_t gfp)
{
unsigned long irq_flags;
struct dma_page *dma_p, *tmp;
@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free)
npages_to_free, nr_free);
}
#endif
- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
- GFP_KERNEL);
+ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp);
if (!pages_to_free) {
pr_err("%s: Failed to allocate memory for pool free operation\n",
@@ -530,7 +531,7 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type)
if (pool->type != type)
continue;
/* Takes a spinlock.. */
- ttm_dma_page_pool_free(pool, FREE_ALL_PAGES);
+ ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL);
WARN_ON(((pool->npages_in_use + pool->npages_free) != 0));
/* This code path is called after _all_ references to the
* struct device has been dropped - so nobody should be
@@ -847,6 +848,7 @@ static int ttm_dma_pool_get_pages(struct dma_pool *pool,
if (count) {
d_page = list_first_entry(&pool->free_list, struct dma_page, page_list);
ttm->pages[index] = d_page->p;
+ ttm_dma->cpu_address[index] = d_page->vaddr;
ttm_dma->dma_address[index] = d_page->dma;
list_move_tail(&d_page->page_list, &ttm_dma->pages_list);
r = 0;
@@ -978,12 +980,13 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
INIT_LIST_HEAD(&ttm_dma->pages_list);
for (i = 0; i < ttm->num_pages; i++) {
ttm->pages[i] = NULL;
+ ttm_dma->cpu_address[i] = 0;
ttm_dma->dma_address[i] = 0;
}
/* shrink pool if necessary (only on !is_cached pools)*/
if (npages)
- ttm_dma_page_pool_free(pool, npages);
+ ttm_dma_page_pool_free(pool, npages, GFP_KERNEL);
ttm->state = tt_unpopulated;
}
EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
@@ -993,10 +996,7 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
*
* XXX: (dchinner) Deadlock warning!
*
- * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention
- * needs to be paid to sc->gfp_mask to determine if this can be done or not.
- * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really
- * bad.
+ * We need to pass sc->gfp_mask to ttm_dma_page_pool_free().
*
* I'm getting sadder as I hear more pathetical whimpers about needing per-pool
* shrinkers
@@ -1004,9 +1004,9 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate);
static unsigned long
ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
- static atomic_t start_pool = ATOMIC_INIT(0);
+ static unsigned start_pool;
unsigned idx = 0;
- unsigned pool_offset = atomic_add_return(1, &start_pool);
+ unsigned pool_offset;
unsigned shrink_pages = sc->nr_to_scan;
struct device_pools *p;
unsigned long freed = 0;
@@ -1014,8 +1014,11 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
if (list_empty(&_manager->pools))
return SHRINK_STOP;
- mutex_lock(&_manager->lock);
- pool_offset = pool_offset % _manager->npools;
+ if (!mutex_trylock(&_manager->lock))
+ return SHRINK_STOP;
+ if (!_manager->npools)
+ goto out;
+ pool_offset = ++start_pool % _manager->npools;
list_for_each_entry(p, &_manager->pools, pools) {
unsigned nr_free;
@@ -1027,13 +1030,15 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
if (++idx < pool_offset)
continue;
nr_free = shrink_pages;
- shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free);
+ shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free,
+ sc->gfp_mask);
freed += nr_free - shrink_pages;
pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",
p->pool->dev_name, p->pool->name, current->pid,
nr_free, shrink_pages);
}
+out:
mutex_unlock(&_manager->lock);
return freed;
}
@@ -1044,7 +1049,8 @@ ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
struct device_pools *p;
unsigned long count = 0;
- mutex_lock(&_manager->lock);
+ if (!mutex_trylock(&_manager->lock))
+ return 0;
list_for_each_entry(p, &_manager->pools, pools)
count += p->pool->npages_free;
mutex_unlock(&_manager->lock);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 75f319090043..bf080abc86d1 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -55,9 +55,12 @@ static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
static void ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm)
{
- ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages, sizeof(void*));
- ttm->dma_address = drm_calloc_large(ttm->ttm.num_pages,
- sizeof(*ttm->dma_address));
+ ttm->ttm.pages = drm_calloc_large(ttm->ttm.num_pages,
+ sizeof(*ttm->ttm.pages) +
+ sizeof(*ttm->dma_address) +
+ sizeof(*ttm->cpu_address));
+ ttm->cpu_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages);
+ ttm->dma_address = (void *) (ttm->cpu_address + ttm->ttm.num_pages);
}
#ifdef CONFIG_X86
@@ -228,7 +231,7 @@ int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_bo_device *bdev,
INIT_LIST_HEAD(&ttm_dma->pages_list);
ttm_dma_tt_alloc_page_directory(ttm_dma);
- if (!ttm->pages || !ttm_dma->dma_address) {
+ if (!ttm->pages) {
ttm_tt_destroy(ttm);
pr_err("Failed allocating page table\n");
return -ENOMEM;
@@ -243,7 +246,7 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma)
drm_free_large(ttm->pages);
ttm->pages = NULL;
- drm_free_large(ttm_dma->dma_address);
+ ttm_dma->cpu_address = NULL;
ttm_dma->dma_address = NULL;
}
EXPORT_SYMBOL(ttm_dma_tt_fini);
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index b44d548c56f8..e026a9e2942a 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -105,14 +105,7 @@ static struct drm_encoder*
udl_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
- struct drm_mode_object *obj;
- struct drm_encoder *encoder;
-
- obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
- if (!obj)
- return NULL;
- encoder = obj_to_encoder(obj);
- return encoder;
+ return drm_encoder_find(connector->dev, enc_id);
}
static int udl_connector_set_property(struct drm_connector *connector,
@@ -124,7 +117,7 @@ static int udl_connector_set_property(struct drm_connector *connector,
static void udl_connector_destroy(struct drm_connector *connector)
{
- drm_sysfs_connector_remove(connector);
+ drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
@@ -154,7 +147,7 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_DVII);
drm_connector_helper_add(connector, &udl_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
+ drm_connector_register(connector);
drm_mode_connector_attach_encoder(connector, encoder);
drm_object_attach_property(&connector->base,
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 377176372da8..d1da339843ca 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -550,7 +550,7 @@ out:
return ret;
}
-static struct drm_fb_helper_funcs udl_fb_helper_funcs = {
+static const struct drm_fb_helper_funcs udl_fb_helper_funcs = {
.fb_probe = udlfb_create,
};
@@ -583,7 +583,8 @@ int udl_fbdev_init(struct drm_device *dev)
return -ENOMEM;
udl->fbdev = ufbdev;
- ufbdev->helper.funcs = &udl_fb_helper_funcs;
+
+ drm_fb_helper_prepare(dev, &ufbdev->helper, &udl_fb_helper_funcs);
ret = drm_fb_helper_init(dev, &ufbdev->helper,
1, 1);
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index c041cd73f399..8044f5fb7c49 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -107,14 +107,14 @@ int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
}
-static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
+static int udl_gem_get_pages(struct udl_gem_object *obj)
{
struct page **pages;
if (obj->pages)
return 0;
- pages = drm_gem_get_pages(&obj->base, gfpmask);
+ pages = drm_gem_get_pages(&obj->base);
if (IS_ERR(pages))
return PTR_ERR(pages);
@@ -147,7 +147,7 @@ int udl_gem_vmap(struct udl_gem_object *obj)
return 0;
}
- ret = udl_gem_get_pages(obj, GFP_KERNEL);
+ ret = udl_gem_get_pages(obj);
if (ret)
return ret;
@@ -205,7 +205,7 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev,
}
gobj = to_udl_bo(obj);
- ret = udl_gem_get_pages(gobj, GFP_KERNEL);
+ ret = udl_gem_get_pages(gobj);
if (ret)
goto out;
ret = drm_gem_create_mmap_offset(obj);
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 7094b92d1ec7..42795674bc07 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -306,10 +306,23 @@ int udl_driver_load(struct drm_device *dev, unsigned long flags)
DRM_DEBUG("\n");
ret = udl_modeset_init(dev);
+ if (ret)
+ goto err;
ret = udl_fbdev_init(dev);
+ if (ret)
+ goto err;
+
+ ret = drm_vblank_init(dev, 1);
+ if (ret)
+ goto err_fb;
+
return 0;
+err_fb:
+ udl_fbdev_cleanup(dev);
err:
+ if (udl->urbs.count)
+ udl_free_urb_list(dev);
kfree(udl);
DRM_ERROR("%d\n", ret);
return ret;
@@ -325,6 +338,8 @@ int udl_driver_unload(struct drm_device *dev)
{
struct udl_device *udl = dev->dev_private;
+ drm_vblank_cleanup(dev);
+
if (udl->urbs.count)
udl_free_urb_list(dev);
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index cddc4fcf35cf..dc145d320b25 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -363,6 +363,26 @@ static void udl_crtc_destroy(struct drm_crtc *crtc)
kfree(crtc);
}
+static int udl_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags)
+{
+ struct udl_framebuffer *ufb = to_udl_fb(fb);
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ udl_handle_damage(ufb, 0, 0, fb->width, fb->height);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (event)
+ drm_send_vblank_event(dev, 0, event);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ crtc->primary->fb = fb;
+
+ return 0;
+}
+
static void udl_crtc_prepare(struct drm_crtc *crtc)
{
}
@@ -384,6 +404,7 @@ static struct drm_crtc_helper_funcs udl_helper_funcs = {
static const struct drm_crtc_funcs udl_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
.destroy = udl_crtc_destroy,
+ .page_flip = udl_crtc_page_flip,
};
static int udl_crtc_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 458cdf6d81e8..ce0ab951f507 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -6,6 +6,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
- vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o
+ vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
+ vmwgfx_cmdbuf_res.o \
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
new file mode 100644
index 000000000000..bfeb4b1f2acf
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -0,0 +1,341 @@
+/**************************************************************************
+ *
+ * Copyright © 2014 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+
+#define VMW_CMDBUF_RES_MAN_HT_ORDER 12
+
+enum vmw_cmdbuf_res_state {
+ VMW_CMDBUF_RES_COMMITED,
+ VMW_CMDBUF_RES_ADD,
+ VMW_CMDBUF_RES_DEL
+};
+
+/**
+ * struct vmw_cmdbuf_res - Command buffer managed resource entry.
+ *
+ * @res: Refcounted pointer to a struct vmw_resource.
+ * @hash: Hash entry for the manager hash table.
+ * @head: List head used either by the staging list or the manager list
+ * of commited resources.
+ * @state: Staging state of this resource entry.
+ * @man: Pointer to a resource manager for this entry.
+ */
+struct vmw_cmdbuf_res {
+ struct vmw_resource *res;
+ struct drm_hash_item hash;
+ struct list_head head;
+ enum vmw_cmdbuf_res_state state;
+ struct vmw_cmdbuf_res_manager *man;
+};
+
+/**
+ * struct vmw_cmdbuf_res_manager - Command buffer resource manager.
+ *
+ * @resources: Hash table containing staged and commited command buffer
+ * resources
+ * @list: List of commited command buffer resources.
+ * @dev_priv: Pointer to a device private structure.
+ *
+ * @resources and @list are protected by the cmdbuf mutex for now.
+ */
+struct vmw_cmdbuf_res_manager {
+ struct drm_open_hash resources;
+ struct list_head list;
+ struct vmw_private *dev_priv;
+};
+
+
+/**
+ * vmw_cmdbuf_res_lookup - Look up a command buffer resource
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @resource_type: The resource type, that combined with the user key
+ * identifies the resource.
+ * @user_key: The user key.
+ *
+ * Returns a valid refcounted struct vmw_resource pointer on success,
+ * an error pointer on failure.
+ */
+struct vmw_resource *
+vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key)
+{
+ struct drm_hash_item *hash;
+ int ret;
+ unsigned long key = user_key | (res_type << 24);
+
+ ret = drm_ht_find_item(&man->resources, key, &hash);
+ if (unlikely(ret != 0))
+ return ERR_PTR(ret);
+
+ return vmw_resource_reference
+ (drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res);
+}
+
+/**
+ * vmw_cmdbuf_res_free - Free a command buffer resource.
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @entry: Pointer to a struct vmw_cmdbuf_res.
+ *
+ * Frees a struct vmw_cmdbuf_res entry and drops its reference to the
+ * struct vmw_resource.
+ */
+static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
+ struct vmw_cmdbuf_res *entry)
+{
+ list_del(&entry->head);
+ WARN_ON(drm_ht_remove_item(&man->resources, &entry->hash));
+ vmw_resource_unreference(&entry->res);
+ kfree(entry);
+}
+
+/**
+ * vmw_cmdbuf_res_commit - Commit a list of command buffer resource actions
+ *
+ * @list: Caller's list of command buffer resource actions.
+ *
+ * This function commits a list of command buffer resource
+ * additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions has commited the fifo contents to the device.
+ */
+void vmw_cmdbuf_res_commit(struct list_head *list)
+{
+ struct vmw_cmdbuf_res *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, head) {
+ list_del(&entry->head);
+ switch (entry->state) {
+ case VMW_CMDBUF_RES_ADD:
+ entry->state = VMW_CMDBUF_RES_COMMITED;
+ list_add_tail(&entry->head, &entry->man->list);
+ break;
+ case VMW_CMDBUF_RES_DEL:
+ vmw_resource_unreference(&entry->res);
+ kfree(entry);
+ break;
+ default:
+ BUG();
+ break;
+ }
+ }
+}
+
+/**
+ * vmw_cmdbuf_res_revert - Revert a list of command buffer resource actions
+ *
+ * @man: Pointer to the command buffer resource manager
+ * @list: Caller's list of command buffer resource action
+ *
+ * This function reverts a list of command buffer resource
+ * additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions failed for some reason, and the command stream was never
+ * submitted.
+ */
+void vmw_cmdbuf_res_revert(struct list_head *list)
+{
+ struct vmw_cmdbuf_res *entry, *next;
+ int ret;
+
+ list_for_each_entry_safe(entry, next, list, head) {
+ switch (entry->state) {
+ case VMW_CMDBUF_RES_ADD:
+ vmw_cmdbuf_res_free(entry->man, entry);
+ break;
+ case VMW_CMDBUF_RES_DEL:
+ ret = drm_ht_insert_item(&entry->man->resources,
+ &entry->hash);
+ list_del(&entry->head);
+ list_add_tail(&entry->head, &entry->man->list);
+ entry->state = VMW_CMDBUF_RES_COMMITED;
+ break;
+ default:
+ BUG();
+ break;
+ }
+ }
+}
+
+/**
+ * vmw_cmdbuf_res_add - Stage a command buffer managed resource for addition.
+ *
+ * @man: Pointer to the command buffer resource manager.
+ * @res_type: The resource type.
+ * @user_key: The user-space id of the resource.
+ * @res: Valid (refcount != 0) pointer to a struct vmw_resource.
+ * @list: The staging list.
+ *
+ * This function allocates a struct vmw_cmdbuf_res entry and adds the
+ * resource to the hash table of the manager identified by @man. The
+ * entry is then put on the staging list identified by @list.
+ */
+int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key,
+ struct vmw_resource *res,
+ struct list_head *list)
+{
+ struct vmw_cmdbuf_res *cres;
+ int ret;
+
+ cres = kzalloc(sizeof(*cres), GFP_KERNEL);
+ if (unlikely(cres == NULL))
+ return -ENOMEM;
+
+ cres->hash.key = user_key | (res_type << 24);
+ ret = drm_ht_insert_item(&man->resources, &cres->hash);
+ if (unlikely(ret != 0))
+ goto out_invalid_key;
+
+ cres->state = VMW_CMDBUF_RES_ADD;
+ cres->res = vmw_resource_reference(res);
+ cres->man = man;
+ list_add_tail(&cres->head, list);
+
+out_invalid_key:
+ return ret;
+}
+
+/**
+ * vmw_cmdbuf_res_remove - Stage a command buffer managed resource for removal.
+ *
+ * @man: Pointer to the command buffer resource manager.
+ * @res_type: The resource type.
+ * @user_key: The user-space id of the resource.
+ * @list: The staging list.
+ *
+ * This function looks up the struct vmw_cmdbuf_res entry from the manager
+ * hash table and, if it exists, removes it. Depending on its current staging
+ * state it then either removes the entry from the staging list or adds it
+ * to it with a staging state of removal.
+ */
+int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key,
+ struct list_head *list)
+{
+ struct vmw_cmdbuf_res *entry;
+ struct drm_hash_item *hash;
+ int ret;
+
+ ret = drm_ht_find_item(&man->resources, user_key, &hash);
+ if (likely(ret != 0))
+ return -EINVAL;
+
+ entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
+
+ switch (entry->state) {
+ case VMW_CMDBUF_RES_ADD:
+ vmw_cmdbuf_res_free(man, entry);
+ break;
+ case VMW_CMDBUF_RES_COMMITED:
+ (void) drm_ht_remove_item(&man->resources, &entry->hash);
+ list_del(&entry->head);
+ entry->state = VMW_CMDBUF_RES_DEL;
+ list_add_tail(&entry->head, list);
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * vmw_cmdbuf_res_man_create - Allocate a command buffer managed resource
+ * manager.
+ *
+ * @dev_priv: Pointer to a struct vmw_private
+ *
+ * Allocates and initializes a command buffer managed resource manager. Returns
+ * an error pointer on failure.
+ */
+struct vmw_cmdbuf_res_manager *
+vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
+{
+ struct vmw_cmdbuf_res_manager *man;
+ int ret;
+
+ man = kzalloc(sizeof(*man), GFP_KERNEL);
+ if (man == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ man->dev_priv = dev_priv;
+ INIT_LIST_HEAD(&man->list);
+ ret = drm_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
+ if (ret == 0)
+ return man;
+
+ kfree(man);
+ return ERR_PTR(ret);
+}
+
+/**
+ * vmw_cmdbuf_res_man_destroy - Destroy a command buffer managed resource
+ * manager.
+ *
+ * @man: Pointer to the manager to destroy.
+ *
+ * This function destroys a command buffer managed resource manager and
+ * unreferences / frees all command buffer managed resources and -entries
+ * associated with it.
+ */
+void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
+{
+ struct vmw_cmdbuf_res *entry, *next;
+
+ list_for_each_entry_safe(entry, next, &man->list, head)
+ vmw_cmdbuf_res_free(man, entry);
+
+ kfree(man);
+}
+
+/**
+ *
+ * vmw_cmdbuf_res_man_size - Return the size of a command buffer managed
+ * resource manager
+ *
+ * Returns the approximate allocation size of a command buffer managed
+ * resource manager.
+ */
+size_t vmw_cmdbuf_res_man_size(void)
+{
+ static size_t res_man_size;
+
+ if (unlikely(res_man_size == 0))
+ res_man_size =
+ ttm_round_pot(sizeof(struct vmw_cmdbuf_res_manager)) +
+ ttm_round_pot(sizeof(struct hlist_head) <<
+ VMW_CMDBUF_RES_MAN_HT_ORDER);
+
+ return res_man_size;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 8bb26dcd9eae..5ac92874404d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -33,6 +33,7 @@ struct vmw_user_context {
struct ttm_base_object base;
struct vmw_resource res;
struct vmw_ctx_binding_state cbs;
+ struct vmw_cmdbuf_res_manager *man;
};
@@ -103,7 +104,8 @@ static const vmw_scrub_func vmw_scrub_funcs[vmw_ctx_binding_max] = {
static void vmw_hw_context_destroy(struct vmw_resource *res)
{
-
+ struct vmw_user_context *uctx =
+ container_of(res, struct vmw_user_context, res);
struct vmw_private *dev_priv = res->dev_priv;
struct {
SVGA3dCmdHeader header;
@@ -113,9 +115,9 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
if (res->func->destroy == vmw_gb_context_destroy) {
mutex_lock(&dev_priv->cmdbuf_mutex);
+ vmw_cmdbuf_res_man_destroy(uctx->man);
mutex_lock(&dev_priv->binding_mutex);
- (void) vmw_context_binding_state_kill
- (&container_of(res, struct vmw_user_context, res)->cbs);
+ (void) vmw_context_binding_state_kill(&uctx->cbs);
(void) vmw_gb_context_destroy(res);
mutex_unlock(&dev_priv->binding_mutex);
if (dev_priv->pinned_bo != NULL &&
@@ -152,13 +154,16 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
ret = vmw_resource_init(dev_priv, res, true,
res_free, &vmw_gb_context_func);
res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
+ if (unlikely(ret != 0))
+ goto out_err;
- if (unlikely(ret != 0)) {
- if (res_free)
- res_free(res);
- else
- kfree(res);
- return ret;
+ if (dev_priv->has_mob) {
+ uctx->man = vmw_cmdbuf_res_man_create(dev_priv);
+ if (unlikely(IS_ERR(uctx->man))) {
+ ret = PTR_ERR(uctx->man);
+ uctx->man = NULL;
+ goto out_err;
+ }
}
memset(&uctx->cbs, 0, sizeof(uctx->cbs));
@@ -166,6 +171,13 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
vmw_resource_activate(res, vmw_hw_context_destroy);
return 0;
+
+out_err:
+ if (res_free)
+ res_free(res);
+ else
+ kfree(res);
+ return ret;
}
static int vmw_context_init(struct vmw_private *dev_priv,
@@ -471,7 +483,8 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
*/
if (unlikely(vmw_user_context_size == 0))
- vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128;
+ vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128 +
+ ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0);
ret = ttm_read_lock(&dev_priv->reservation_sem, true);
if (unlikely(ret != 0))
@@ -901,3 +914,8 @@ struct list_head *vmw_context_binding_list(struct vmw_resource *ctx)
{
return &(container_of(ctx, struct vmw_user_context, res)->cbs.list);
}
+
+struct vmw_cmdbuf_res_manager *vmw_context_res_man(struct vmw_resource *ctx)
+{
+ return container_of(ctx, struct vmw_user_context, res)->man;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index 70ddce8358b0..ed1d51006ab1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -61,7 +61,7 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
vmw_execbuf_release_pinned_bo(dev_priv);
- ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
if (unlikely(ret != 0))
goto err;
@@ -105,7 +105,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
if (pin)
vmw_execbuf_release_pinned_bo(dev_priv);
- ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
if (unlikely(ret != 0))
goto err;
@@ -212,7 +212,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
if (pin)
vmw_execbuf_release_pinned_bo(dev_priv);
- ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+ ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
if (unlikely(ret != 0))
goto err_unlock;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 246a62bab378..18b54acacfbb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -316,7 +316,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
if (unlikely(ret != 0))
return ret;
- ret = ttm_bo_reserve(bo, false, true, false, 0);
+ ret = ttm_bo_reserve(bo, false, true, false, NULL);
BUG_ON(ret != 0);
ret = ttm_bo_kmap(bo, 0, 1, &map);
@@ -946,7 +946,6 @@ static void vmw_postclose(struct drm_device *dev,
drm_master_put(&vmw_fp->locked_master);
}
- vmw_compat_shader_man_destroy(vmw_fp->shman);
ttm_object_file_release(&vmw_fp->tfile);
kfree(vmw_fp);
}
@@ -966,16 +965,10 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
if (unlikely(vmw_fp->tfile == NULL))
goto out_no_tfile;
- vmw_fp->shman = vmw_compat_shader_man_create(dev_priv);
- if (IS_ERR(vmw_fp->shman))
- goto out_no_shman;
-
file_priv->driver_priv = vmw_fp;
return 0;
-out_no_shman:
- ttm_object_file_release(&vmw_fp->tfile);
out_no_tfile:
kfree(vmw_fp);
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 6b252a887ae2..99f731757c4b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,10 +40,10 @@
#include <drm/ttm/ttm_module.h>
#include "vmwgfx_fence.h"
-#define VMWGFX_DRIVER_DATE "20140325"
+#define VMWGFX_DRIVER_DATE "20140704"
#define VMWGFX_DRIVER_MAJOR 2
#define VMWGFX_DRIVER_MINOR 6
-#define VMWGFX_DRIVER_PATCHLEVEL 0
+#define VMWGFX_DRIVER_PATCHLEVEL 1
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
@@ -75,14 +75,11 @@
#define VMW_RES_FENCE ttm_driver_type3
#define VMW_RES_SHADER ttm_driver_type4
-struct vmw_compat_shader_manager;
-
struct vmw_fpriv {
struct drm_master *locked_master;
struct ttm_object_file *tfile;
struct list_head fence_events;
bool gb_aware;
- struct vmw_compat_shader_manager *shman;
};
struct vmw_dma_buffer {
@@ -124,6 +121,10 @@ struct vmw_resource {
void (*hw_destroy) (struct vmw_resource *res);
};
+
+/*
+ * Resources that are managed using ioctls.
+ */
enum vmw_res_type {
vmw_res_context,
vmw_res_surface,
@@ -132,6 +133,15 @@ enum vmw_res_type {
vmw_res_max
};
+/*
+ * Resources that are managed using command streams.
+ */
+enum vmw_cmdbuf_res_type {
+ vmw_cmdbuf_res_compat_shader
+};
+
+struct vmw_cmdbuf_res_manager;
+
struct vmw_cursor_snooper {
struct drm_crtc *crtc;
size_t age;
@@ -159,8 +169,8 @@ struct vmw_surface {
struct vmw_marker_queue {
struct list_head head;
- struct timespec lag;
- struct timespec lag_time;
+ u64 lag;
+ u64 lag_time;
spinlock_t lock;
};
@@ -341,7 +351,7 @@ struct vmw_sw_context{
bool needs_post_query_barrier;
struct vmw_resource *error_resource;
struct vmw_ctx_binding_state staged_bindings;
- struct list_head staged_shaders;
+ struct list_head staged_cmd_res;
};
struct vmw_legacy_display;
@@ -974,7 +984,8 @@ extern void vmw_context_binding_res_list_kill(struct list_head *head);
extern void vmw_context_binding_res_list_scrub(struct list_head *head);
extern int vmw_context_rebind_all(struct vmw_resource *ctx);
extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
-
+extern struct vmw_cmdbuf_res_manager *
+vmw_context_res_man(struct vmw_resource *ctx);
/*
* Surface management - vmwgfx_surface.c
*/
@@ -1008,27 +1019,42 @@ extern int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-extern int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
- SVGA3dShaderType shader_type,
- u32 *user_key);
-extern void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
- struct list_head *list);
-extern void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
- struct list_head *list);
-extern int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
- u32 user_key,
- SVGA3dShaderType shader_type,
- struct list_head *list);
-extern int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+extern int vmw_compat_shader_add(struct vmw_private *dev_priv,
+ struct vmw_cmdbuf_res_manager *man,
u32 user_key, const void *bytecode,
SVGA3dShaderType shader_type,
size_t size,
- struct ttm_object_file *tfile,
struct list_head *list);
-extern struct vmw_compat_shader_manager *
-vmw_compat_shader_man_create(struct vmw_private *dev_priv);
-extern void
-vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man);
+extern int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man,
+ u32 user_key, SVGA3dShaderType shader_type,
+ struct list_head *list);
+extern struct vmw_resource *
+vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man,
+ u32 user_key, SVGA3dShaderType shader_type);
+
+/*
+ * Command buffer managed resources - vmwgfx_cmdbuf_res.c
+ */
+
+extern struct vmw_cmdbuf_res_manager *
+vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv);
+extern void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man);
+extern size_t vmw_cmdbuf_res_man_size(void);
+extern struct vmw_resource *
+vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key);
+extern void vmw_cmdbuf_res_revert(struct list_head *list);
+extern void vmw_cmdbuf_res_commit(struct list_head *list);
+extern int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key,
+ struct vmw_resource *res,
+ struct list_head *list);
+extern int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+ enum vmw_cmdbuf_res_type res_type,
+ u32 user_key,
+ struct list_head *list);
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 87df0b3674fd..7bfdaa163a33 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -422,28 +422,91 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context)
return 0;
}
+
+/**
+ * vmw_cmd_res_reloc_add - Add a resource to a software context's
+ * relocation- and validation lists.
+ *
+ * @dev_priv: Pointer to a struct vmw_private identifying the device.
+ * @sw_context: Pointer to the software context.
+ * @res_type: Resource type.
+ * @id_loc: Pointer to where the id that needs translation is located.
+ * @res: Valid pointer to a struct vmw_resource.
+ * @p_val: If non null, a pointer to the struct vmw_resource_validate_node
+ * used for this resource is returned here.
+ */
+static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
+ struct vmw_sw_context *sw_context,
+ enum vmw_res_type res_type,
+ uint32_t *id_loc,
+ struct vmw_resource *res,
+ struct vmw_resource_val_node **p_val)
+{
+ int ret;
+ struct vmw_resource_val_node *node;
+
+ *p_val = NULL;
+ ret = vmw_resource_relocation_add(&sw_context->res_relocations,
+ res,
+ id_loc - sw_context->buf_start);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ ret = vmw_resource_val_add(sw_context, res, &node);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ if (res_type == vmw_res_context && dev_priv->has_mob &&
+ node->first_usage) {
+
+ /*
+ * Put contexts first on the list to be able to exit
+ * list traversal for contexts early.
+ */
+ list_del(&node->head);
+ list_add(&node->head, &sw_context->resource_list);
+
+ ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
+ if (unlikely(ret != 0))
+ goto out_err;
+ node->staged_bindings =
+ kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
+ if (node->staged_bindings == NULL) {
+ DRM_ERROR("Failed to allocate context binding "
+ "information.\n");
+ goto out_err;
+ }
+ INIT_LIST_HEAD(&node->staged_bindings->list);
+ }
+
+ if (p_val)
+ *p_val = node;
+
+out_err:
+ return ret;
+}
+
+
/**
- * vmw_cmd_compat_res_check - Check that a resource is present and if so, put it
+ * vmw_cmd_res_check - Check that a resource is present and if so, put it
* on the resource validate list unless it's already there.
*
* @dev_priv: Pointer to a device private structure.
* @sw_context: Pointer to the software context.
* @res_type: Resource type.
* @converter: User-space visisble type specific information.
- * @id: user-space resource id handle.
* @id_loc: Pointer to the location in the command buffer currently being
* parsed from where the user-space resource id handle is located.
* @p_val: Pointer to pointer to resource validalidation node. Populated
* on exit.
*/
static int
-vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
- struct vmw_sw_context *sw_context,
- enum vmw_res_type res_type,
- const struct vmw_user_resource_conv *converter,
- uint32_t id,
- uint32_t *id_loc,
- struct vmw_resource_val_node **p_val)
+vmw_cmd_res_check(struct vmw_private *dev_priv,
+ struct vmw_sw_context *sw_context,
+ enum vmw_res_type res_type,
+ const struct vmw_user_resource_conv *converter,
+ uint32_t *id_loc,
+ struct vmw_resource_val_node **p_val)
{
struct vmw_res_cache_entry *rcache =
&sw_context->res_cache[res_type];
@@ -451,7 +514,7 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
struct vmw_resource_val_node *node;
int ret;
- if (id == SVGA3D_INVALID_ID) {
+ if (*id_loc == SVGA3D_INVALID_ID) {
if (p_val)
*p_val = NULL;
if (res_type == vmw_res_context) {
@@ -466,7 +529,7 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
* resource
*/
- if (likely(rcache->valid && id == rcache->handle)) {
+ if (likely(rcache->valid && *id_loc == rcache->handle)) {
const struct vmw_resource *res = rcache->res;
rcache->node->first_usage = false;
@@ -480,49 +543,28 @@ vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
ret = vmw_user_resource_lookup_handle(dev_priv,
sw_context->fp->tfile,
- id,
+ *id_loc,
converter,
&res);
if (unlikely(ret != 0)) {
DRM_ERROR("Could not find or use resource 0x%08x.\n",
- (unsigned) id);
+ (unsigned) *id_loc);
dump_stack();
return ret;
}
rcache->valid = true;
rcache->res = res;
- rcache->handle = id;
-
- ret = vmw_resource_relocation_add(&sw_context->res_relocations,
- res,
- id_loc - sw_context->buf_start);
- if (unlikely(ret != 0))
- goto out_no_reloc;
+ rcache->handle = *id_loc;
- ret = vmw_resource_val_add(sw_context, res, &node);
+ ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, res_type, id_loc,
+ res, &node);
if (unlikely(ret != 0))
goto out_no_reloc;
rcache->node = node;
if (p_val)
*p_val = node;
-
- if (dev_priv->has_mob && node->first_usage &&
- res_type == vmw_res_context) {
- ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
- if (unlikely(ret != 0))
- goto out_no_reloc;
- node->staged_bindings =
- kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
- if (node->staged_bindings == NULL) {
- DRM_ERROR("Failed to allocate context binding "
- "information.\n");
- goto out_no_reloc;
- }
- INIT_LIST_HEAD(&node->staged_bindings->list);
- }
-
vmw_resource_unreference(&res);
return 0;
@@ -534,31 +576,6 @@ out_no_reloc:
}
/**
- * vmw_cmd_res_check - Check that a resource is present and if so, put it
- * on the resource validate list unless it's already there.
- *
- * @dev_priv: Pointer to a device private structure.
- * @sw_context: Pointer to the software context.
- * @res_type: Resource type.
- * @converter: User-space visisble type specific information.
- * @id_loc: Pointer to the location in the command buffer currently being
- * parsed from where the user-space resource id handle is located.
- * @p_val: Pointer to pointer to resource validalidation node. Populated
- * on exit.
- */
-static int
-vmw_cmd_res_check(struct vmw_private *dev_priv,
- struct vmw_sw_context *sw_context,
- enum vmw_res_type res_type,
- const struct vmw_user_resource_conv *converter,
- uint32_t *id_loc,
- struct vmw_resource_val_node **p_val)
-{
- return vmw_cmd_compat_res_check(dev_priv, sw_context, res_type,
- converter, *id_loc, id_loc, p_val);
-}
-
-/**
* vmw_rebind_contexts - Rebind all resources previously bound to
* referenced contexts.
*
@@ -572,8 +589,8 @@ static int vmw_rebind_contexts(struct vmw_sw_context *sw_context)
int ret;
list_for_each_entry(val, &sw_context->resource_list, head) {
- if (likely(!val->staged_bindings))
- continue;
+ if (unlikely(!val->staged_bindings))
+ break;
ret = vmw_context_rebind_all(val->res);
if (unlikely(ret != 0)) {
@@ -1626,13 +1643,14 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
} *cmd;
int ret;
size_t size;
+ struct vmw_resource_val_node *val;
cmd = container_of(header, struct vmw_shader_define_cmd,
header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- NULL);
+ &val);
if (unlikely(ret != 0))
return ret;
@@ -1640,11 +1658,11 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
return 0;
size = cmd->header.size - sizeof(cmd->body);
- ret = vmw_compat_shader_add(sw_context->fp->shman,
+ ret = vmw_compat_shader_add(dev_priv,
+ vmw_context_res_man(val->res),
cmd->body.shid, cmd + 1,
cmd->body.type, size,
- sw_context->fp->tfile,
- &sw_context->staged_shaders);
+ &sw_context->staged_cmd_res);
if (unlikely(ret != 0))
return ret;
@@ -1672,23 +1690,24 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
SVGA3dCmdDestroyShader body;
} *cmd;
int ret;
+ struct vmw_resource_val_node *val;
cmd = container_of(header, struct vmw_shader_destroy_cmd,
header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- NULL);
+ &val);
if (unlikely(ret != 0))
return ret;
if (unlikely(!dev_priv->has_mob))
return 0;
- ret = vmw_compat_shader_remove(sw_context->fp->shman,
+ ret = vmw_compat_shader_remove(vmw_context_res_man(val->res),
cmd->body.shid,
cmd->body.type,
- &sw_context->staged_shaders);
+ &sw_context->staged_cmd_res);
if (unlikely(ret != 0))
return ret;
@@ -1715,7 +1734,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
SVGA3dCmdHeader header;
SVGA3dCmdSetShader body;
} *cmd;
- struct vmw_resource_val_node *ctx_node;
+ struct vmw_resource_val_node *ctx_node, *res_node = NULL;
+ struct vmw_ctx_bindinfo bi;
+ struct vmw_resource *res = NULL;
int ret;
cmd = container_of(header, struct vmw_set_shader_cmd,
@@ -1727,32 +1748,40 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
return ret;
- if (dev_priv->has_mob) {
- struct vmw_ctx_bindinfo bi;
- struct vmw_resource_val_node *res_node;
- u32 shid = cmd->body.shid;
-
- if (shid != SVGA3D_INVALID_ID)
- (void) vmw_compat_shader_lookup(sw_context->fp->shman,
- cmd->body.type,
- &shid);
-
- ret = vmw_cmd_compat_res_check(dev_priv, sw_context,
- vmw_res_shader,
- user_shader_converter,
- shid,
- &cmd->body.shid, &res_node);
+ if (!dev_priv->has_mob)
+ return 0;
+
+ if (cmd->body.shid != SVGA3D_INVALID_ID) {
+ res = vmw_compat_shader_lookup
+ (vmw_context_res_man(ctx_node->res),
+ cmd->body.shid,
+ cmd->body.type);
+
+ if (!IS_ERR(res)) {
+ ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
+ vmw_res_shader,
+ &cmd->body.shid, res,
+ &res_node);
+ vmw_resource_unreference(&res);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+ }
+
+ if (!res_node) {
+ ret = vmw_cmd_res_check(dev_priv, sw_context,
+ vmw_res_shader,
+ user_shader_converter,
+ &cmd->body.shid, &res_node);
if (unlikely(ret != 0))
return ret;
-
- bi.ctx = ctx_node->res;
- bi.res = res_node ? res_node->res : NULL;
- bi.bt = vmw_ctx_binding_shader;
- bi.i1.shader_type = cmd->body.type;
- return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
}
- return 0;
+ bi.ctx = ctx_node->res;
+ bi.res = res_node ? res_node->res : NULL;
+ bi.bt = vmw_ctx_binding_shader;
+ bi.i1.shader_type = cmd->body.type;
+ return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
}
/**
@@ -2394,6 +2423,8 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
}
}
+
+
int vmw_execbuf_process(struct drm_file *file_priv,
struct vmw_private *dev_priv,
void __user *user_commands,
@@ -2453,7 +2484,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
goto out_unlock;
sw_context->res_ht_initialized = true;
}
- INIT_LIST_HEAD(&sw_context->staged_shaders);
+ INIT_LIST_HEAD(&sw_context->staged_cmd_res);
INIT_LIST_HEAD(&resource_list);
ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
@@ -2548,8 +2579,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
}
list_splice_init(&sw_context->resource_list, &resource_list);
- vmw_compat_shaders_commit(sw_context->fp->shman,
- &sw_context->staged_shaders);
+ vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res);
mutex_unlock(&dev_priv->cmdbuf_mutex);
/*
@@ -2576,8 +2606,7 @@ out_unlock:
list_splice_init(&sw_context->resource_list, &resource_list);
error_resource = sw_context->error_resource;
sw_context->error_resource = NULL;
- vmw_compat_shaders_revert(sw_context->fp->shman,
- &sw_context->staged_shaders);
+ vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
mutex_unlock(&dev_priv->cmdbuf_mutex);
/*
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
index b1273e8e9a69..26f8bdde3529 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
@@ -47,6 +47,7 @@ struct vmwgfx_gmrid_man {
static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
struct ttm_buffer_object *bo,
struct ttm_placement *placement,
+ uint32_t flags,
struct ttm_mem_reg *mem)
{
struct vmwgfx_gmrid_man *gman =
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8f3edc4710f2..d2bc2b03d4c6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -75,7 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)
vmw_surface_unreference(&du->cursor_surface);
if (du->cursor_dmabuf)
vmw_dmabuf_unreference(&du->cursor_dmabuf);
- drm_sysfs_connector_remove(&du->connector);
+ drm_connector_unregister(&du->connector);
drm_crtc_cleanup(&du->crtc);
drm_encoder_cleanup(&du->encoder);
drm_connector_cleanup(&du->connector);
@@ -136,7 +136,7 @@ int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
kmap_offset = 0;
kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
- ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+ ret = ttm_bo_reserve(&dmabuf->base, true, false, false, NULL);
if (unlikely(ret != 0)) {
DRM_ERROR("reserve failed\n");
return -EINVAL;
@@ -343,7 +343,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
kmap_num = (64*64*4) >> PAGE_SHIFT;
- ret = ttm_bo_reserve(bo, true, false, false, 0);
+ ret = ttm_bo_reserve(bo, true, false, false, NULL);
if (unlikely(ret != 0)) {
DRM_ERROR("reserve failed\n");
return;
@@ -1501,7 +1501,6 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
{
struct drm_vmw_cursor_bypass_arg *arg = data;
struct vmw_display_unit *du;
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
int ret = 0;
@@ -1519,13 +1518,12 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
return 0;
}
- obj = drm_mode_object_find(dev, arg->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, arg->crtc_id);
+ if (!crtc) {
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
du = vmw_crtc_to_du(crtc);
du->hotspot_x = arg->xhot;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index b2b9bd23aeee..15e185ae4c99 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -371,7 +371,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0;
- (void) drm_sysfs_connector_add(connector);
+ (void) drm_connector_register(connector);
drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
index 8a8725c2716c..efd1ffd68185 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_marker.c
@@ -31,14 +31,14 @@
struct vmw_marker {
struct list_head head;
uint32_t seqno;
- struct timespec submitted;
+ u64 submitted;
};
void vmw_marker_queue_init(struct vmw_marker_queue *queue)
{
INIT_LIST_HEAD(&queue->head);
- queue->lag = ns_to_timespec(0);
- getrawmonotonic(&queue->lag_time);
+ queue->lag = 0;
+ queue->lag_time = ktime_get_raw_ns();
spin_lock_init(&queue->lock);
}
@@ -62,7 +62,7 @@ int vmw_marker_push(struct vmw_marker_queue *queue,
return -ENOMEM;
marker->seqno = seqno;
- getrawmonotonic(&marker->submitted);
+ marker->submitted = ktime_get_raw_ns();
spin_lock(&queue->lock);
list_add_tail(&marker->head, &queue->head);
spin_unlock(&queue->lock);
@@ -74,14 +74,14 @@ int vmw_marker_pull(struct vmw_marker_queue *queue,
uint32_t signaled_seqno)
{
struct vmw_marker *marker, *next;
- struct timespec now;
bool updated = false;
+ u64 now;
spin_lock(&queue->lock);
- getrawmonotonic(&now);
+ now = ktime_get_raw_ns();
if (list_empty(&queue->head)) {
- queue->lag = ns_to_timespec(0);
+ queue->lag = 0;
queue->lag_time = now;
updated = true;
goto out_unlock;
@@ -91,7 +91,7 @@ int vmw_marker_pull(struct vmw_marker_queue *queue,
if (signaled_seqno - marker->seqno > (1 << 30))
continue;
- queue->lag = timespec_sub(now, marker->submitted);
+ queue->lag = now - marker->submitted;
queue->lag_time = now;
updated = true;
list_del(&marker->head);
@@ -104,27 +104,13 @@ out_unlock:
return (updated) ? 0 : -EBUSY;
}
-static struct timespec vmw_timespec_add(struct timespec t1,
- struct timespec t2)
+static u64 vmw_fifo_lag(struct vmw_marker_queue *queue)
{
- t1.tv_sec += t2.tv_sec;
- t1.tv_nsec += t2.tv_nsec;
- if (t1.tv_nsec >= 1000000000L) {
- t1.tv_sec += 1;
- t1.tv_nsec -= 1000000000L;
- }
-
- return t1;
-}
-
-static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
-{
- struct timespec now;
+ u64 now;
spin_lock(&queue->lock);
- getrawmonotonic(&now);
- queue->lag = vmw_timespec_add(queue->lag,
- timespec_sub(now, queue->lag_time));
+ now = ktime_get_raw_ns();
+ queue->lag += now - queue->lag_time;
queue->lag_time = now;
spin_unlock(&queue->lock);
return queue->lag;
@@ -134,11 +120,9 @@ static struct timespec vmw_fifo_lag(struct vmw_marker_queue *queue)
static bool vmw_lag_lt(struct vmw_marker_queue *queue,
uint32_t us)
{
- struct timespec lag, cond;
+ u64 cond = (u64) us * NSEC_PER_USEC;
- cond = ns_to_timespec((s64) us * 1000);
- lag = vmw_fifo_lag(queue);
- return (timespec_compare(&lag, &cond) < 1);
+ return vmw_fifo_lag(queue) <= cond;
}
int vmw_wait_lag(struct vmw_private *dev_priv,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 01d68f0a69dc..a432c0db257c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -127,7 +127,7 @@ static void vmw_resource_release(struct kref *kref)
if (res->backup) {
struct ttm_buffer_object *bo = &res->backup->base;
- ttm_bo_reserve(bo, false, false, false, 0);
+ ttm_bo_reserve(bo, false, false, false, NULL);
if (!list_empty(&res->mob_head) &&
res->func->unbind != NULL) {
struct ttm_validate_buffer val_buf;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index a95d3a0cabe4..b295463a60b3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -467,7 +467,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0;
- (void) drm_sysfs_connector_add(connector);
+ (void) drm_connector_register(connector);
drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index c1559eeaffe9..8719fb3cccc9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -29,8 +29,6 @@
#include "vmwgfx_resource_priv.h"
#include "ttm/ttm_placement.h"
-#define VMW_COMPAT_SHADER_HT_ORDER 12
-
struct vmw_shader {
struct vmw_resource res;
SVGA3dShaderType type;
@@ -42,49 +40,8 @@ struct vmw_user_shader {
struct vmw_shader shader;
};
-/**
- * enum vmw_compat_shader_state - Staging state for compat shaders
- */
-enum vmw_compat_shader_state {
- VMW_COMPAT_COMMITED,
- VMW_COMPAT_ADD,
- VMW_COMPAT_DEL
-};
-
-/**
- * struct vmw_compat_shader - Metadata for compat shaders.
- *
- * @handle: The TTM handle of the guest backed shader.
- * @tfile: The struct ttm_object_file the guest backed shader is registered
- * with.
- * @hash: Hash item for lookup.
- * @head: List head for staging lists or the compat shader manager list.
- * @state: Staging state.
- *
- * The structure is protected by the cmdbuf lock.
- */
-struct vmw_compat_shader {
- u32 handle;
- struct ttm_object_file *tfile;
- struct drm_hash_item hash;
- struct list_head head;
- enum vmw_compat_shader_state state;
-};
-
-/**
- * struct vmw_compat_shader_manager - Compat shader manager.
- *
- * @shaders: Hash table containing staged and commited compat shaders
- * @list: List of commited shaders.
- * @dev_priv: Pointer to a device private structure.
- *
- * @shaders and @list are protected by the cmdbuf mutex for now.
- */
-struct vmw_compat_shader_manager {
- struct drm_open_hash shaders;
- struct list_head list;
- struct vmw_private *dev_priv;
-};
+static uint64_t vmw_user_shader_size;
+static uint64_t vmw_shader_size;
static void vmw_user_shader_free(struct vmw_resource *res);
static struct vmw_resource *
@@ -98,8 +55,6 @@ static int vmw_gb_shader_unbind(struct vmw_resource *res,
struct ttm_validate_buffer *val_buf);
static int vmw_gb_shader_destroy(struct vmw_resource *res);
-static uint64_t vmw_user_shader_size;
-
static const struct vmw_user_resource_conv user_shader_conv = {
.object_type = VMW_RES_SHADER,
.base_obj_to_res = vmw_user_shader_base_to_res,
@@ -347,6 +302,16 @@ static void vmw_user_shader_free(struct vmw_resource *res)
vmw_user_shader_size);
}
+static void vmw_shader_free(struct vmw_resource *res)
+{
+ struct vmw_shader *shader = vmw_res_to_shader(res);
+ struct vmw_private *dev_priv = res->dev_priv;
+
+ kfree(shader);
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_shader_size);
+}
+
/**
* This function is called when user space has no more references on the
* base object. It releases the base-object's reference on the resource object.
@@ -371,13 +336,13 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
TTM_REF_USAGE);
}
-static int vmw_shader_alloc(struct vmw_private *dev_priv,
- struct vmw_dma_buffer *buffer,
- size_t shader_size,
- size_t offset,
- SVGA3dShaderType shader_type,
- struct ttm_object_file *tfile,
- u32 *handle)
+static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buffer,
+ size_t shader_size,
+ size_t offset,
+ SVGA3dShaderType shader_type,
+ struct ttm_object_file *tfile,
+ u32 *handle)
{
struct vmw_user_shader *ushader;
struct vmw_resource *res, *tmp;
@@ -442,6 +407,56 @@ out:
}
+struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
+ struct vmw_dma_buffer *buffer,
+ size_t shader_size,
+ size_t offset,
+ SVGA3dShaderType shader_type)
+{
+ struct vmw_shader *shader;
+ struct vmw_resource *res;
+ int ret;
+
+ /*
+ * Approximate idr memory usage with 128 bytes. It will be limited
+ * by maximum number_of shaders anyway.
+ */
+ if (unlikely(vmw_shader_size == 0))
+ vmw_shader_size =
+ ttm_round_pot(sizeof(struct vmw_shader)) + 128;
+
+ ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+ vmw_shader_size,
+ false, true);
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Out of graphics memory for shader "
+ "creation.\n");
+ goto out_err;
+ }
+
+ shader = kzalloc(sizeof(*shader), GFP_KERNEL);
+ if (unlikely(shader == NULL)) {
+ ttm_mem_global_free(vmw_mem_glob(dev_priv),
+ vmw_shader_size);
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ res = &shader->res;
+
+ /*
+ * From here on, the destructor takes over resource freeing.
+ */
+ ret = vmw_gb_shader_init(dev_priv, res, shader_size,
+ offset, shader_type, buffer,
+ vmw_shader_free);
+
+out_err:
+ return ret ? ERR_PTR(ret) : res;
+}
+
+
int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -490,8 +505,8 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
if (unlikely(ret != 0))
goto out_bad_arg;
- ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
- shader_type, tfile, &arg->shader_handle);
+ ret = vmw_user_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
+ shader_type, tfile, &arg->shader_handle);
ttm_read_unlock(&dev_priv->reservation_sem);
out_bad_arg:
@@ -500,202 +515,83 @@ out_bad_arg:
}
/**
- * vmw_compat_shader_lookup - Look up a compat shader
- *
- * @man: Pointer to the compat shader manager.
- * @shader_type: The shader type, that combined with the user_key identifies
- * the shader.
- * @user_key: On entry, this should be a pointer to the user_key.
- * On successful exit, it will contain the guest-backed shader's TTM handle.
+ * vmw_compat_shader_id_ok - Check whether a compat shader user key and
+ * shader type are within valid bounds.
*
- * Returns 0 on success. Non-zero on failure, in which case the value pointed
- * to by @user_key is unmodified.
- */
-int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
- SVGA3dShaderType shader_type,
- u32 *user_key)
-{
- struct drm_hash_item *hash;
- int ret;
- unsigned long key = *user_key | (shader_type << 24);
-
- ret = drm_ht_find_item(&man->shaders, key, &hash);
- if (unlikely(ret != 0))
- return ret;
-
- *user_key = drm_hash_entry(hash, struct vmw_compat_shader,
- hash)->handle;
-
- return 0;
-}
-
-/**
- * vmw_compat_shader_free - Free a compat shader.
- *
- * @man: Pointer to the compat shader manager.
- * @entry: Pointer to a struct vmw_compat_shader.
- *
- * Frees a struct vmw_compat_shder entry and drops its reference to the
- * guest backed shader.
- */
-static void vmw_compat_shader_free(struct vmw_compat_shader_manager *man,
- struct vmw_compat_shader *entry)
-{
- list_del(&entry->head);
- WARN_ON(drm_ht_remove_item(&man->shaders, &entry->hash));
- WARN_ON(ttm_ref_object_base_unref(entry->tfile, entry->handle,
- TTM_REF_USAGE));
- kfree(entry);
-}
-
-/**
- * vmw_compat_shaders_commit - Commit a list of compat shader actions.
- *
- * @man: Pointer to the compat shader manager.
- * @list: Caller's list of compat shader actions.
+ * @user_key: User space id of the shader.
+ * @shader_type: Shader type.
*
- * This function commits a list of compat shader additions or removals.
- * It is typically called when the execbuf ioctl call triggering these
- * actions has commited the fifo contents to the device.
+ * Returns true if valid false if not.
*/
-void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
- struct list_head *list)
+static bool vmw_compat_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
{
- struct vmw_compat_shader *entry, *next;
-
- list_for_each_entry_safe(entry, next, list, head) {
- list_del(&entry->head);
- switch (entry->state) {
- case VMW_COMPAT_ADD:
- entry->state = VMW_COMPAT_COMMITED;
- list_add_tail(&entry->head, &man->list);
- break;
- case VMW_COMPAT_DEL:
- ttm_ref_object_base_unref(entry->tfile, entry->handle,
- TTM_REF_USAGE);
- kfree(entry);
- break;
- default:
- BUG();
- break;
- }
- }
+ return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
}
/**
- * vmw_compat_shaders_revert - Revert a list of compat shader actions
+ * vmw_compat_shader_key - Compute a hash key suitable for a compat shader.
*
- * @man: Pointer to the compat shader manager.
- * @list: Caller's list of compat shader actions.
+ * @user_key: User space id of the shader.
+ * @shader_type: Shader type.
*
- * This function reverts a list of compat shader additions or removals.
- * It is typically called when the execbuf ioctl call triggering these
- * actions failed for some reason, and the command stream was never
- * submitted.
+ * Returns a hash key suitable for a command buffer managed resource
+ * manager hash table.
*/
-void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
- struct list_head *list)
+static u32 vmw_compat_shader_key(u32 user_key, SVGA3dShaderType shader_type)
{
- struct vmw_compat_shader *entry, *next;
- int ret;
-
- list_for_each_entry_safe(entry, next, list, head) {
- switch (entry->state) {
- case VMW_COMPAT_ADD:
- vmw_compat_shader_free(man, entry);
- break;
- case VMW_COMPAT_DEL:
- ret = drm_ht_insert_item(&man->shaders, &entry->hash);
- list_del(&entry->head);
- list_add_tail(&entry->head, &man->list);
- entry->state = VMW_COMPAT_COMMITED;
- break;
- default:
- BUG();
- break;
- }
- }
+ return user_key | (shader_type << 20);
}
/**
* vmw_compat_shader_remove - Stage a compat shader for removal.
*
- * @man: Pointer to the compat shader manager
+ * @man: Pointer to the compat shader manager identifying the shader namespace.
* @user_key: The key that is used to identify the shader. The key is
* unique to the shader type.
* @shader_type: Shader type.
- * @list: Caller's list of staged shader actions.
- *
- * This function stages a compat shader for removal and removes the key from
- * the shader manager's hash table. If the shader was previously only staged
- * for addition it is completely removed (But the execbuf code may keep a
- * reference if it was bound to a context between addition and removal). If
- * it was previously commited to the manager, it is staged for removal.
+ * @list: Caller's list of staged command buffer resource actions.
*/
-int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
+int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man,
u32 user_key, SVGA3dShaderType shader_type,
struct list_head *list)
{
- struct vmw_compat_shader *entry;
- struct drm_hash_item *hash;
- int ret;
-
- ret = drm_ht_find_item(&man->shaders, user_key | (shader_type << 24),
- &hash);
- if (likely(ret != 0))
+ if (!vmw_compat_shader_id_ok(user_key, shader_type))
return -EINVAL;
- entry = drm_hash_entry(hash, struct vmw_compat_shader, hash);
-
- switch (entry->state) {
- case VMW_COMPAT_ADD:
- vmw_compat_shader_free(man, entry);
- break;
- case VMW_COMPAT_COMMITED:
- (void) drm_ht_remove_item(&man->shaders, &entry->hash);
- list_del(&entry->head);
- entry->state = VMW_COMPAT_DEL;
- list_add_tail(&entry->head, list);
- break;
- default:
- BUG();
- break;
- }
-
- return 0;
+ return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_compat_shader,
+ vmw_compat_shader_key(user_key,
+ shader_type),
+ list);
}
/**
- * vmw_compat_shader_add - Create a compat shader and add the
- * key to the manager
+ * vmw_compat_shader_add - Create a compat shader and stage it for addition
+ * as a command buffer managed resource.
*
- * @man: Pointer to the compat shader manager
+ * @man: Pointer to the compat shader manager identifying the shader namespace.
* @user_key: The key that is used to identify the shader. The key is
* unique to the shader type.
* @bytecode: Pointer to the bytecode of the shader.
* @shader_type: Shader type.
* @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
* to be created with.
- * @list: Caller's list of staged shader actions.
+ * @list: Caller's list of staged command buffer resource actions.
*
- * Note that only the key is added to the shader manager's hash table.
- * The shader is not yet added to the shader manager's list of shaders.
*/
-int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+int vmw_compat_shader_add(struct vmw_private *dev_priv,
+ struct vmw_cmdbuf_res_manager *man,
u32 user_key, const void *bytecode,
SVGA3dShaderType shader_type,
size_t size,
- struct ttm_object_file *tfile,
struct list_head *list)
{
struct vmw_dma_buffer *buf;
struct ttm_bo_kmap_obj map;
bool is_iomem;
- struct vmw_compat_shader *compat;
- u32 handle;
int ret;
+ struct vmw_resource *res;
- if (user_key > ((1 << 24) - 1) || (unsigned) shader_type > 16)
+ if (!vmw_compat_shader_id_ok(user_key, shader_type))
return -EINVAL;
/* Allocate and pin a DMA buffer */
@@ -703,7 +599,7 @@ int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
if (unlikely(buf == NULL))
return -ENOMEM;
- ret = vmw_dmabuf_init(man->dev_priv, buf, size, &vmw_sys_ne_placement,
+ ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement,
true, vmw_dmabuf_bo_free);
if (unlikely(ret != 0))
goto out;
@@ -728,84 +624,40 @@ int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
WARN_ON(ret != 0);
ttm_bo_unreserve(&buf->base);
- /* Create a guest-backed shader container backed by the dma buffer */
- ret = vmw_shader_alloc(man->dev_priv, buf, size, 0, shader_type,
- tfile, &handle);
- vmw_dmabuf_unreference(&buf);
+ res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
if (unlikely(ret != 0))
goto no_reserve;
- /*
- * Create a compat shader structure and stage it for insertion
- * in the manager
- */
- compat = kzalloc(sizeof(*compat), GFP_KERNEL);
- if (compat == NULL)
- goto no_compat;
-
- compat->hash.key = user_key | (shader_type << 24);
- ret = drm_ht_insert_item(&man->shaders, &compat->hash);
- if (unlikely(ret != 0))
- goto out_invalid_key;
-
- compat->state = VMW_COMPAT_ADD;
- compat->handle = handle;
- compat->tfile = tfile;
- list_add_tail(&compat->head, list);
-
- return 0;
-out_invalid_key:
- kfree(compat);
-no_compat:
- ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
+ ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_compat_shader,
+ vmw_compat_shader_key(user_key, shader_type),
+ res, list);
+ vmw_resource_unreference(&res);
no_reserve:
+ vmw_dmabuf_unreference(&buf);
out:
return ret;
}
/**
- * vmw_compat_shader_man_create - Create a compat shader manager
- *
- * @dev_priv: Pointer to a device private structure.
- *
- * Typically done at file open time. If successful returns a pointer to a
- * compat shader manager. Otherwise returns an error pointer.
- */
-struct vmw_compat_shader_manager *
-vmw_compat_shader_man_create(struct vmw_private *dev_priv)
-{
- struct vmw_compat_shader_manager *man;
- int ret;
-
- man = kzalloc(sizeof(*man), GFP_KERNEL);
- if (man == NULL)
- return ERR_PTR(-ENOMEM);
-
- man->dev_priv = dev_priv;
- INIT_LIST_HEAD(&man->list);
- ret = drm_ht_create(&man->shaders, VMW_COMPAT_SHADER_HT_ORDER);
- if (ret == 0)
- return man;
-
- kfree(man);
- return ERR_PTR(ret);
-}
-
-/**
- * vmw_compat_shader_man_destroy - Destroy a compat shader manager
+ * vmw_compat_shader_lookup - Look up a compat shader
*
- * @man: Pointer to the shader manager to destroy.
+ * @man: Pointer to the command buffer managed resource manager identifying
+ * the shader namespace.
+ * @user_key: The user space id of the shader.
+ * @shader_type: The shader type.
*
- * Typically done at file close time.
+ * Returns a refcounted pointer to a struct vmw_resource if the shader was
+ * found. An error pointer otherwise.
*/
-void vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man)
+struct vmw_resource *
+vmw_compat_shader_lookup(struct vmw_cmdbuf_res_manager *man,
+ u32 user_key,
+ SVGA3dShaderType shader_type)
{
- struct vmw_compat_shader *entry, *next;
-
- mutex_lock(&man->dev_priv->cmdbuf_mutex);
- list_for_each_entry_safe(entry, next, &man->list, head)
- vmw_compat_shader_free(man, entry);
+ if (!vmw_compat_shader_id_ok(user_key, shader_type))
+ return ERR_PTR(-EINVAL);
- mutex_unlock(&man->dev_priv->cmdbuf_mutex);
- kfree(man);
+ return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_compat_shader,
+ vmw_compat_shader_key(user_key,
+ shader_type));
}
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 112f27e51bc7..63bd63f3c7df 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -185,16 +185,16 @@ static unsigned int pin_job(struct host1x_job *job)
struct sg_table *sgt;
dma_addr_t phys_addr;
- reloc->target = host1x_bo_get(reloc->target);
- if (!reloc->target)
+ reloc->target.bo = host1x_bo_get(reloc->target.bo);
+ if (!reloc->target.bo)
goto unpin;
- phys_addr = host1x_bo_pin(reloc->target, &sgt);
+ phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
if (!phys_addr)
goto unpin;
job->addr_phys[job->num_unpins] = phys_addr;
- job->unpins[job->num_unpins].bo = reloc->target;
+ job->unpins[job->num_unpins].bo = reloc->target.bo;
job->unpins[job->num_unpins].sgt = sgt;
job->num_unpins++;
}
@@ -235,21 +235,21 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
for (i = 0; i < job->num_relocs; i++) {
struct host1x_reloc *reloc = &job->relocarray[i];
u32 reloc_addr = (job->reloc_addr_phys[i] +
- reloc->target_offset) >> reloc->shift;
+ reloc->target.offset) >> reloc->shift;
u32 *target;
/* skip all other gathers */
- if (cmdbuf != reloc->cmdbuf)
+ if (cmdbuf != reloc->cmdbuf.bo)
continue;
- if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) {
+ if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
if (cmdbuf_page_addr)
host1x_bo_kunmap(cmdbuf, last_page,
cmdbuf_page_addr);
cmdbuf_page_addr = host1x_bo_kmap(cmdbuf,
- reloc->cmdbuf_offset >> PAGE_SHIFT);
- last_page = reloc->cmdbuf_offset >> PAGE_SHIFT;
+ reloc->cmdbuf.offset >> PAGE_SHIFT);
+ last_page = reloc->cmdbuf.offset >> PAGE_SHIFT;
if (unlikely(!cmdbuf_page_addr)) {
pr_err("Could not map cmdbuf for relocation\n");
@@ -257,7 +257,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
}
}
- target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK);
+ target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
*target = reloc_addr;
}
@@ -272,7 +272,7 @@ static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
{
offset *= sizeof(u32);
- if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset)
+ if (reloc->cmdbuf.bo != cmdbuf || reloc->cmdbuf.offset != offset)
return false;
return true;
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index af0259708358..d2077f040f3e 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -237,12 +237,10 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
if (conflict->locks & lwants)
return conflict;
- /* Ok, now check if he owns the resource we want. We don't need
- * to check "decodes" since it should be impossible to own
- * own legacy resources you don't decode unless I have a bug
- * in this code...
+ /* Ok, now check if it owns the resource we want. We can
+ * lock resources that are not decoded, therefore a device
+ * can own resources it doesn't decode.
*/
- WARN_ON(conflict->owns & ~conflict->decodes);
match = lwants & conflict->owns;
if (!match)
continue;
@@ -254,13 +252,19 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
flags = 0;
pci_bits = 0;
+ /* If we can't control legacy resources via the bridge, we
+ * also need to disable normal decoding.
+ */
if (!conflict->bridge_has_one_vga) {
- vga_irq_set_state(conflict, false);
- flags |= PCI_VGA_STATE_CHANGE_DECODES;
- if (match & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
+ if ((match & conflict->decodes) & VGA_RSRC_LEGACY_MEM)
pci_bits |= PCI_COMMAND_MEMORY;
- if (match & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
+ if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO)
pci_bits |= PCI_COMMAND_IO;
+
+ if (pci_bits) {
+ vga_irq_set_state(conflict, false);
+ flags |= PCI_VGA_STATE_CHANGE_DECODES;
+ }
}
if (change_bridge)
@@ -268,18 +272,19 @@ static struct vga_device *__vga_tryget(struct vga_device *vgadev,
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
conflict->owns &= ~match;
- /* If he also owned non-legacy, that is no longer the case */
- if (match & VGA_RSRC_LEGACY_MEM)
+
+ /* If we disabled normal decoding, reflect it in owns */
+ if (pci_bits & PCI_COMMAND_MEMORY)
conflict->owns &= ~VGA_RSRC_NORMAL_MEM;
- if (match & VGA_RSRC_LEGACY_IO)
+ if (pci_bits & PCI_COMMAND_IO)
conflict->owns &= ~VGA_RSRC_NORMAL_IO;
}
enable_them:
/* ok dude, we got it, everybody conflicting has been disabled, let's
- * enable us. Make sure we don't mark a bit in "owns" that we don't
- * also have in "decodes". We can lock resources we don't decode but
- * not own them.
+ * enable us. Mark any bits in "owns" regardless of whether we
+ * decoded them. We can lock resources we don't decode, therefore
+ * we must track them via "owns".
*/
flags = 0;
pci_bits = 0;
@@ -291,7 +296,7 @@ enable_them:
if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
pci_bits |= PCI_COMMAND_IO;
}
- if (!!(wants & VGA_RSRC_LEGACY_MASK))
+ if (wants & VGA_RSRC_LEGACY_MASK)
flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
@@ -299,7 +304,7 @@ enable_them:
if (!vgadev->bridge_has_one_vga) {
vga_irq_set_state(vgadev, true);
}
- vgadev->owns |= (wants & vgadev->decodes);
+ vgadev->owns |= wants;
lock_them:
vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
if (rsrc & VGA_RSRC_LEGACY_IO)
@@ -649,7 +654,6 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev,
old_decodes = vgadev->decodes;
decodes_removed = ~new_decodes & old_decodes;
decodes_unlocked = vgadev->locks & decodes_removed;
- vgadev->owns &= ~decodes_removed;
vgadev->decodes = new_decodes;
pr_info("vgaarb: device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 5e79c6ad914f..c18d5d71062d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -261,6 +261,20 @@ config HOLTEK_FF
Say Y here if you have a Holtek On Line Grip based game controller
and want to have force feedback support for it.
+config HID_GT683R
+ tristate "MSI GT68xR LED support"
+ depends on LEDS_CLASS && USB_HID
+ ---help---
+ Say Y here if you want to enable support for the three MSI GT68xR LEDs
+
+ This driver support following modes:
+ - Normal: LEDs are fully on when enabled
+ - Audio: LEDs brightness depends on sound level
+ - Breathing: LEDs brightness varies at human breathing rate
+
+ Currently the following devices are know to be supported:
+ - MSI GT683R
+
config HID_HUION
tristate "Huion tablets"
depends on USB_HID
@@ -331,18 +345,20 @@ config HID_LCPOWER
---help---
Support for LC-Power RC1000MCE RF remote control.
-config HID_LENOVO_TPKBD
- tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
+config HID_LENOVO
+ tristate "Lenovo / Thinkpad devices"
depends on HID
select NEW_LEDS
select LEDS_CLASS
---help---
- Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
+ Support for Lenovo devices that are not fully compliant with HID standard.
- Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
- and would like to use device-specific features like changing the
- sensitivity of the trackpoint, using the microphone mute button or
- controlling the mute and microphone mute LEDs.
+ Say Y if you want support for the non-compliant features of the Lenovo
+ Thinkpad standalone keyboards, e.g:
+ - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
+ configuration)
+ - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
+ - ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
config HID_LOGITECH
tristate "Logitech devices" if EXPERT
@@ -748,12 +764,17 @@ config THRUSTMASTER_FF
Rumble Force or Force Feedback Wheel.
config HID_WACOM
- tristate "Wacom Bluetooth devices support"
+ tristate "Wacom Intuos/Graphire tablet support (USB)"
depends on HID
- depends on LEDS_CLASS
select POWER_SUPPLY
- ---help---
- Support for Wacom Graphire Bluetooth and Intuos4 WL tablets.
+ select NEW_LEDS
+ select LEDS_CLASS
+ help
+ Say Y here if you want to use the USB or BT version of the Wacom Intuos
+ or Graphire tablet.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wacom.
config HID_WIIMOTE
tristate "Nintendo Wii / Wii U peripherals"
@@ -785,7 +806,7 @@ config HID_XINMO
depends on HID
---help---
Support for Xin-Mo devices that are not fully compliant with the HID
- standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
+ standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
if you have a Xin-Mo Dual Arcade controller.
config HID_ZEROPLUS
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index a6fa6baf368e..4dbac7f8530c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
+obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
@@ -59,7 +60,7 @@ obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
-obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
+obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
@@ -115,7 +116,9 @@ obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
-obj-$(CONFIG_HID_WACOM) += hid-wacom.o
+
+wacom-objs := wacom_wac.o wacom_sys.o
+obj-$(CONFIG_HID_WACOM) += wacom.o
obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8ed66fd1ea87..12b6e67d9de0 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -783,10 +783,21 @@ static int hid_scan_report(struct hid_device *hid)
* Vendor specific handlings
*/
if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) &&
- (hid->group == HID_GROUP_GENERIC))
+ (hid->group == HID_GROUP_GENERIC) &&
+ /* only bind to the mouse interface of composite USB devices */
+ (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE))
/* hid-rmi should take care of them, not hid-generic */
hid->group = HID_GROUP_RMI;
+ /*
+ * Vendor specific handlings
+ */
+ switch (hid->vendor) {
+ case USB_VENDOR_ID_WACOM:
+ hid->group = HID_GROUP_WACOM;
+ break;
+ }
+
vfree(parser);
return 0;
}
@@ -1782,7 +1793,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
- { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
@@ -1796,8 +1807,10 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+#if IS_ENABLED(CONFIG_HID_LENOVO)
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
@@ -1845,6 +1858,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
@@ -1933,8 +1947,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
@@ -2266,6 +2278,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
@@ -2339,7 +2352,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
- { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 56be85a9a77c..a822db5a8338 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -240,8 +240,6 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
u8 buf[5];
int ret;
- cp2112_gpio_set(chip, offset, value);
-
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
sizeof(buf), HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
@@ -260,6 +258,12 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
return ret;
}
+ /*
+ * Set gpio value when output direction is already set,
+ * as specified in AN495, Rev. 0.2, cpt. 4.4
+ */
+ cp2112_gpio_set(chip, offset, value);
+
return 0;
}
@@ -425,6 +429,105 @@ static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
return data_length + 4;
}
+static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
+ u8 data_length)
+{
+ struct cp2112_write_req_report *report = buf;
+
+ if (data_length > sizeof(report->data))
+ return -EINVAL;
+
+ report->report = CP2112_DATA_WRITE_REQUEST;
+ report->slave_address = slave_address << 1;
+ report->length = data_length;
+ memcpy(report->data, data, data_length);
+ return data_length + 3;
+}
+
+static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
+ struct hid_device *hdev = dev->hdev;
+ u8 buf[64];
+ ssize_t count;
+ unsigned int retries;
+ int ret;
+
+ hid_dbg(hdev, "I2C %d messages\n", num);
+
+ if (num != 1) {
+ hid_err(hdev,
+ "Multi-message I2C transactions not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (msgs->flags & I2C_M_RD)
+ count = cp2112_read_req(buf, msgs->addr, msgs->len);
+ else
+ count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf,
+ msgs->len);
+
+ if (count < 0)
+ return count;
+
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
+ if (ret < 0) {
+ hid_err(hdev, "power management error: %d\n", ret);
+ return ret;
+ }
+
+ ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
+ if (ret < 0) {
+ hid_warn(hdev, "Error starting transaction: %d\n", ret);
+ goto power_normal;
+ }
+
+ for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
+ ret = cp2112_xfer_status(dev);
+ if (-EBUSY == ret)
+ continue;
+ if (ret < 0)
+ goto power_normal;
+ break;
+ }
+
+ if (XFER_STATUS_RETRIES <= retries) {
+ hid_warn(hdev, "Transfer timed out, cancelling.\n");
+ buf[0] = CP2112_CANCEL_TRANSFER;
+ buf[1] = 0x01;
+
+ ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
+ if (ret < 0)
+ hid_warn(hdev, "Error cancelling transaction: %d\n",
+ ret);
+
+ ret = -ETIMEDOUT;
+ goto power_normal;
+ }
+
+ if (!(msgs->flags & I2C_M_RD))
+ goto finish;
+
+ ret = cp2112_read(dev, msgs->buf, msgs->len);
+ if (ret < 0)
+ goto power_normal;
+ if (ret != msgs->len) {
+ hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len);
+ ret = -EIO;
+ goto power_normal;
+ }
+
+finish:
+ /* return the number of transferred messages */
+ ret = 1;
+
+power_normal:
+ hid_hw_power(hdev, PM_HINT_NORMAL);
+ hid_dbg(hdev, "I2C transfer finished: %d\n", ret);
+ return ret;
+}
+
static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data)
@@ -591,7 +694,8 @@ power_normal:
static u32 cp2112_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_BYTE |
+ return I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA |
@@ -601,6 +705,7 @@ static u32 cp2112_functionality(struct i2c_adapter *adap)
}
static const struct i2c_algorithm smbus_algorithm = {
+ .master_xfer = cp2112_i2c_xfer,
.smbus_xfer = cp2112_xfer,
.functionality = cp2112_functionality,
};
diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c
new file mode 100644
index 000000000000..0d6f135e266c
--- /dev/null
+++ b/drivers/hid/hid-gt683r.c
@@ -0,0 +1,321 @@
+/*
+ * MSI GT683R led driver
+ *
+ * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define GT683R_BUFFER_SIZE 8
+
+/*
+ * GT683R_LED_OFF: all LEDs are off
+ * GT683R_LED_AUDIO: LEDs brightness depends on sound level
+ * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
+ * GT683R_LED_NORMAL: LEDs are fully on when enabled
+ */
+enum gt683r_led_mode {
+ GT683R_LED_OFF = 0,
+ GT683R_LED_AUDIO = 2,
+ GT683R_LED_BREATHING = 3,
+ GT683R_LED_NORMAL = 5
+};
+
+enum gt683r_panels {
+ GT683R_LED_BACK = 0,
+ GT683R_LED_SIDE = 1,
+ GT683R_LED_FRONT = 2,
+ GT683R_LED_COUNT,
+};
+
+static const char * const gt683r_panel_names[] = {
+ "back",
+ "side",
+ "front",
+};
+
+struct gt683r_led {
+ struct hid_device *hdev;
+ struct led_classdev led_devs[GT683R_LED_COUNT];
+ struct mutex lock;
+ struct work_struct work;
+ enum led_brightness brightnesses[GT683R_LED_COUNT];
+ enum gt683r_led_mode mode;
+};
+
+static const struct hid_device_id gt683r_led_id[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+ { }
+};
+
+static void gt683r_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ int i;
+ struct device *dev = led_cdev->dev->parent;
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct gt683r_led *led = hid_get_drvdata(hdev);
+
+ for (i = 0; i < GT683R_LED_COUNT; i++) {
+ if (led_cdev == &led->led_devs[i])
+ break;
+ }
+
+ if (i < GT683R_LED_COUNT) {
+ led->brightnesses[i] = brightness;
+ schedule_work(&led->work);
+ }
+}
+
+static ssize_t mode_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ u8 sysfs_mode;
+ struct hid_device *hdev = container_of(dev->parent,
+ struct hid_device, dev);
+ struct gt683r_led *led = hid_get_drvdata(hdev);
+
+ if (led->mode == GT683R_LED_NORMAL)
+ sysfs_mode = 0;
+ else if (led->mode == GT683R_LED_AUDIO)
+ sysfs_mode = 1;
+ else
+ sysfs_mode = 2;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
+}
+
+static ssize_t mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ u8 sysfs_mode;
+ struct hid_device *hdev = container_of(dev->parent,
+ struct hid_device, dev);
+ struct gt683r_led *led = hid_get_drvdata(hdev);
+
+
+ if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
+ return -EINVAL;
+
+ mutex_lock(&led->lock);
+
+ if (sysfs_mode == 0)
+ led->mode = GT683R_LED_NORMAL;
+ else if (sysfs_mode == 1)
+ led->mode = GT683R_LED_AUDIO;
+ else
+ led->mode = GT683R_LED_BREATHING;
+
+ mutex_unlock(&led->lock);
+ schedule_work(&led->work);
+
+ return count;
+}
+
+static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
+{
+ int ret;
+
+ ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ if (ret != GT683R_BUFFER_SIZE) {
+ hid_err(led->hdev,
+ "failed to send set report request: %i\n", ret);
+ if (ret < 0)
+ return ret;
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
+{
+ int ret;
+ u8 *buffer;
+
+ buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ buffer[0] = 0x01;
+ buffer[1] = 0x02;
+ buffer[2] = 0x30;
+ buffer[3] = leds;
+ ret = gt683r_led_snd_msg(led, buffer);
+
+ kfree(buffer);
+ return ret;
+}
+
+static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
+{
+ int ret;
+ u8 *buffer;
+
+ buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ buffer[0] = 0x01;
+ buffer[1] = 0x02;
+ buffer[2] = 0x20;
+ buffer[3] = mode;
+ buffer[4] = 0x01;
+ ret = gt683r_led_snd_msg(led, buffer);
+
+ kfree(buffer);
+ return ret;
+}
+
+static void gt683r_led_work(struct work_struct *work)
+{
+ int i;
+ u8 leds = 0;
+ u8 mode;
+ struct gt683r_led *led = container_of(work, struct gt683r_led, work);
+
+ mutex_lock(&led->lock);
+
+ for (i = 0; i < GT683R_LED_COUNT; i++) {
+ if (led->brightnesses[i])
+ leds |= BIT(i);
+ }
+
+ if (gt683r_leds_set(led, leds))
+ goto fail;
+
+ if (leds)
+ mode = led->mode;
+ else
+ mode = GT683R_LED_OFF;
+
+ gt683r_mode_set(led, mode);
+fail:
+ mutex_unlock(&led->lock);
+}
+
+static DEVICE_ATTR_RW(mode);
+
+static struct attribute *gt683r_led_attrs[] = {
+ &dev_attr_mode.attr,
+ NULL
+};
+
+static const struct attribute_group gt683r_led_group = {
+ .name = "gt683r",
+ .attrs = gt683r_led_attrs,
+};
+
+static const struct attribute_group *gt683r_led_groups[] = {
+ &gt683r_led_group,
+ NULL
+};
+
+static int gt683r_led_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int i;
+ int ret;
+ int name_sz;
+ char *name;
+ struct gt683r_led *led;
+
+ led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ mutex_init(&led->lock);
+ INIT_WORK(&led->work, gt683r_led_work);
+
+ led->mode = GT683R_LED_NORMAL;
+ led->hdev = hdev;
+ hid_set_drvdata(hdev, led);
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "hid parsing failed\n");
+ return ret;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ if (ret) {
+ hid_err(hdev, "hw start failed\n");
+ return ret;
+ }
+
+ for (i = 0; i < GT683R_LED_COUNT; i++) {
+ name_sz = strlen(dev_name(&hdev->dev)) +
+ strlen(gt683r_panel_names[i]) + 3;
+
+ name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+ if (!name) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ snprintf(name, name_sz, "%s::%s",
+ dev_name(&hdev->dev), gt683r_panel_names[i]);
+ led->led_devs[i].name = name;
+ led->led_devs[i].max_brightness = 1;
+ led->led_devs[i].brightness_set = gt683r_brightness_set;
+ led->led_devs[i].groups = gt683r_led_groups;
+
+ ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
+ if (ret) {
+ hid_err(hdev, "could not register led device\n");
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ for (i = i - 1; i >= 0; i--)
+ led_classdev_unregister(&led->led_devs[i]);
+ hid_hw_stop(hdev);
+ return ret;
+}
+
+static void gt683r_led_remove(struct hid_device *hdev)
+{
+ int i;
+ struct gt683r_led *led = hid_get_drvdata(hdev);
+
+ for (i = 0; i < GT683R_LED_COUNT; i++)
+ led_classdev_unregister(&led->led_devs[i]);
+ flush_work(&led->work);
+ hid_hw_stop(hdev);
+}
+
+static struct hid_driver gt683r_led_driver = {
+ .probe = gt683r_led_probe,
+ .remove = gt683r_led_remove,
+ .name = "gt683r_led",
+ .id_table = gt683r_led_id,
+};
+
+module_hid_driver(gt683r_led_driver);
+
+MODULE_AUTHOR("Janne Kanniainen");
+MODULE_DESCRIPTION("MSI GT683R led driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-huion.c b/drivers/hid/hid-huion.c
index cbf4da4689ba..60f44cd1b0ed 100644
--- a/drivers/hid/hid-huion.c
+++ b/drivers/hid/hid-huion.c
@@ -2,6 +2,7 @@
* HID driver for Huion devices not fully compliant with HID standard
*
* Copyright (c) 2013 Martin Rusko
+ * Copyright (c) 2014 Nikolai Kondrashov
*/
/*
@@ -15,67 +16,89 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <asm/unaligned.h>
#include "usbhid/usbhid.h"
#include "hid-ids.h"
-/* Original Huion 580 report descriptor size */
-#define HUION_580_RDESC_ORIG_SIZE 177
-
-/* Fixed Huion 580 report descriptor */
-static __u8 huion_580_rdesc_fixed[] = {
- 0x05, 0x0D, /* Usage Page (Digitizer), */
- 0x09, 0x02, /* Usage (Pen), */
- 0xA1, 0x01, /* Collection (Application), */
- 0x85, 0x07, /* Report ID (7), */
- 0x09, 0x20, /* Usage (Stylus), */
- 0xA0, /* Collection (Physical), */
- 0x14, /* Logical Minimum (0), */
- 0x25, 0x01, /* Logical Maximum (1), */
- 0x75, 0x01, /* Report Size (1), */
- 0x09, 0x42, /* Usage (Tip Switch), */
- 0x09, 0x44, /* Usage (Barrel Switch), */
- 0x09, 0x46, /* Usage (Tablet Pick), */
- 0x95, 0x03, /* Report Count (3), */
- 0x81, 0x02, /* Input (Variable), */
- 0x95, 0x03, /* Report Count (3), */
- 0x81, 0x03, /* Input (Constant, Variable), */
- 0x09, 0x32, /* Usage (In Range), */
- 0x95, 0x01, /* Report Count (1), */
- 0x81, 0x02, /* Input (Variable), */
- 0x95, 0x01, /* Report Count (1), */
- 0x81, 0x03, /* Input (Constant, Variable), */
- 0x75, 0x10, /* Report Size (16), */
- 0x95, 0x01, /* Report Count (1), */
- 0xA4, /* Push, */
- 0x05, 0x01, /* Usage Page (Desktop), */
- 0x65, 0x13, /* Unit (Inch), */
- 0x55, 0xFD, /* Unit Exponent (-3), */
- 0x34, /* Physical Minimum (0), */
- 0x09, 0x30, /* Usage (X), */
- 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */
- 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */
- 0x81, 0x02, /* Input (Variable), */
- 0x09, 0x31, /* Usage (Y), */
- 0x46, 0x88, 0x13, /* Physical Maximum (5000), */
- 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
- 0x81, 0x02, /* Input (Variable), */
- 0xB4, /* Pop, */
- 0x09, 0x30, /* Usage (Tip Pressure), */
- 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */
- 0x81, 0x02, /* Input (Variable), */
- 0xC0, /* End Collection, */
- 0xC0 /* End Collection */
+/* Report descriptor template placeholder head */
+#define HUION_PH_HEAD 0xFE, 0xED, 0x1D
+
+/* Report descriptor template placeholder IDs */
+enum huion_ph_id {
+ HUION_PH_ID_X_LM,
+ HUION_PH_ID_X_PM,
+ HUION_PH_ID_Y_LM,
+ HUION_PH_ID_Y_PM,
+ HUION_PH_ID_PRESSURE_LM,
+ HUION_PH_ID_NUM
+};
+
+/* Report descriptor template placeholder */
+#define HUION_PH(_ID) HUION_PH_HEAD, HUION_PH_ID_##_ID
+
+/* Fixed report descriptor template */
+static const __u8 huion_tablet_rdesc_template[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x02, /* Usage (Pen), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x07, /* Report ID (7), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x46, /* Usage (Tablet Pick), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x34, /* Physical Minimum (0), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x27, HUION_PH(X_LM), /* Logical Maximum (PLACEHOLDER), */
+ 0x47, HUION_PH(X_PM), /* Physical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x27, HUION_PH(Y_LM), /* Logical Maximum (PLACEHOLDER), */
+ 0x47, HUION_PH(Y_PM), /* Physical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xB4, /* Pop, */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x27,
+ HUION_PH(PRESSURE_LM), /* Logical Maximum (PLACEHOLDER), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+};
+
+/* Driver data */
+struct huion_drvdata {
+ __u8 *rdesc;
+ unsigned int rsize;
};
static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
+ struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
switch (hdev->product) {
- case USB_DEVICE_ID_HUION_580:
- if (*rsize == HUION_580_RDESC_ORIG_SIZE) {
- rdesc = huion_580_rdesc_fixed;
- *rsize = sizeof(huion_580_rdesc_fixed);
+ case USB_DEVICE_ID_HUION_TABLET:
+ if (drvdata->rdesc != NULL) {
+ rdesc = drvdata->rdesc;
+ *rsize = drvdata->rsize;
}
break;
}
@@ -83,82 +106,144 @@ static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc,
}
/**
- * Enable fully-functional tablet mode by reading special string
- * descriptor.
+ * Enable fully-functional tablet mode and determine device parameters.
*
* @hdev: HID device
- *
- * The specific string descriptor and data were discovered by sniffing
- * the Windows driver traffic.
*/
static int huion_tablet_enable(struct hid_device *hdev)
{
int rc;
- char buf[22];
+ struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+ struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
+ __le16 buf[6];
- rc = usb_string(hid_to_usb_dev(hdev), 0x64, buf, sizeof(buf));
- if (rc < 0)
- return rc;
+ /*
+ * Read string descriptor containing tablet parameters. The specific
+ * string descriptor and data were discovered by sniffing the Windows
+ * driver traffic.
+ * NOTE: This enables fully-functional tablet mode.
+ */
+ rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (USB_DT_STRING << 8) + 0x64,
+ 0x0409, buf, sizeof(buf),
+ USB_CTRL_GET_TIMEOUT);
+ if (rc == -EPIPE)
+ hid_warn(hdev, "device parameters not found\n");
+ else if (rc < 0)
+ hid_warn(hdev, "failed to get device parameters: %d\n", rc);
+ else if (rc != sizeof(buf))
+ hid_warn(hdev, "invalid device parameters\n");
+ else {
+ s32 params[HUION_PH_ID_NUM];
+ s32 resolution;
+ __u8 *p;
+ s32 v;
+
+ /* Extract device parameters */
+ params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
+ params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
+ params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
+ resolution = le16_to_cpu(buf[5]);
+ if (resolution == 0) {
+ params[HUION_PH_ID_X_PM] = 0;
+ params[HUION_PH_ID_Y_PM] = 0;
+ } else {
+ params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
+ 1000 / resolution;
+ params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
+ 1000 / resolution;
+ }
+
+ /* Allocate fixed report descriptor */
+ drvdata->rdesc = devm_kmalloc(&hdev->dev,
+ sizeof(huion_tablet_rdesc_template),
+ GFP_KERNEL);
+ if (drvdata->rdesc == NULL) {
+ hid_err(hdev, "failed to allocate fixed rdesc\n");
+ return -ENOMEM;
+ }
+ drvdata->rsize = sizeof(huion_tablet_rdesc_template);
+
+ /* Format fixed report descriptor */
+ memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
+ drvdata->rsize);
+ for (p = drvdata->rdesc;
+ p <= drvdata->rdesc + drvdata->rsize - 4;) {
+ if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
+ p[3] < sizeof(params)) {
+ v = params[p[3]];
+ put_unaligned(cpu_to_le32(v), (s32 *)p);
+ p += 4;
+ } else {
+ p++;
+ }
+ }
+ }
return 0;
}
static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
- int ret;
+ int rc;
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct huion_drvdata *drvdata;
+
+ /* Allocate and assign driver data */
+ drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+ if (drvdata == NULL) {
+ hid_err(hdev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+ hid_set_drvdata(hdev, drvdata);
- /* Ignore interfaces 1 (mouse) and 2 (keyboard) for Huion 580 tablet,
- * as they are not used
- */
switch (id->product) {
- case USB_DEVICE_ID_HUION_580:
- if (intf->cur_altsetting->desc.bInterfaceNumber != 0x00)
- return -ENODEV;
+ case USB_DEVICE_ID_HUION_TABLET:
+ /* If this is the pen interface */
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+ rc = huion_tablet_enable(hdev);
+ if (rc) {
+ hid_err(hdev, "tablet enabling failed\n");
+ return rc;
+ }
+ }
break;
}
- ret = hid_parse(hdev);
- if (ret) {
+ rc = hid_parse(hdev);
+ if (rc) {
hid_err(hdev, "parse failed\n");
- goto err;
+ return rc;
}
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
+ rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (rc) {
hid_err(hdev, "hw start failed\n");
- goto err;
- }
-
- switch (id->product) {
- case USB_DEVICE_ID_HUION_580:
- ret = huion_tablet_enable(hdev);
- if (ret) {
- hid_err(hdev, "tablet enabling failed\n");
- goto enabling_err;
- }
- break;
+ return rc;
}
return 0;
-enabling_err:
- hid_hw_stop(hdev);
-err:
- return ret;
}
static int huion_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
- /* If this is a pen input report then invert the in-range bit */
- if (report->type == HID_INPUT_REPORT && report->id == 0x07 && size >= 2)
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+ /* If this is a pen input report */
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 0 &&
+ report->type == HID_INPUT_REPORT &&
+ report->id == 0x07 && size >= 2)
+ /* Invert the in-range bit */
data[1] ^= 0x40;
return 0;
}
static const struct hid_device_id huion_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
{ }
};
MODULE_DEVICE_TABLE(hid, huion_devices);
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index f52dbcb7133b..31fad641b744 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -308,6 +308,9 @@ static void mousevsc_on_receive(struct hv_device *device,
memcpy(input_dev->input_buf, input_report->buffer, len);
hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
input_dev->input_buf, len, 1);
+
+ pm_wakeup_event(&input_dev->device->device, 0);
+
break;
default:
pr_err("unsupported hid msg type - type %d len %d",
@@ -549,6 +552,8 @@ static int mousevsc_probe(struct hv_device *device,
goto probe_err2;
}
+ device_init_wakeup(&device->device, true);
+
input_dev->connected = true;
input_dev->init_complete = true;
@@ -571,6 +576,7 @@ static int mousevsc_remove(struct hv_device *dev)
{
struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
+ device_init_wakeup(&dev->device, false);
vmbus_close(dev->channel);
hid_hw_stop(input_dev->hid_device);
hid_destroy_device(input_dev->hid_device);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 48b66bbffc94..25cd674d6064 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -448,7 +448,7 @@
#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
#define USB_VENDOR_ID_HUION 0x256c
-#define USB_DEVICE_ID_HUION_580 0x006e
+#define USB_DEVICE_ID_HUION_TABLET 0x006e
#define USB_VENDOR_ID_IDEACOM 0x1cb6
#define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650
@@ -479,6 +479,7 @@
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070 0xa070
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072 0xa072
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081
+#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096 0xa096
#define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
@@ -489,6 +490,7 @@
#define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
#define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420
+#define USB_DEVICE_ID_JABRA_GN9350E 0x9350
#define USB_VENDOR_ID_JESS 0x0c45
#define USB_DEVICE_ID_JESS_YUREX 0x1010
@@ -561,6 +563,8 @@
#define USB_VENDOR_ID_LENOVO 0x17ef
#define USB_DEVICE_ID_LENOVO_TPKBD 0x6009
+#define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047
+#define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048
#define USB_VENDOR_ID_LG 0x1fd2
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
@@ -646,7 +650,7 @@
#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
#define USB_VENDOR_ID_MSI 0x1770
-#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00
+#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
#define USB_DEVICE_ID_N_S_HARMONY 0xc359
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
deleted file mode 100644
index 2d25b6cbbc05..000000000000
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
- *
- * Copyright (c) 2012 Bernhard Seibold
- */
-
-/*
- * 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/sysfs.h>
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-
-#include "hid-ids.h"
-
-/* This is only used for the trackpoint part of the driver, hence _tp */
-struct tpkbd_data_pointer {
- int led_state;
- struct led_classdev led_mute;
- struct led_classdev led_micmute;
- int press_to_select;
- int dragging;
- int release_to_select;
- int select_right;
- int sensitivity;
- int press_speed;
-};
-
-#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
-
-static int tpkbd_input_mapping(struct hid_device *hdev,
- struct hid_input *hi, struct hid_field *field,
- struct hid_usage *usage, unsigned long **bit, int *max)
-{
- if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
- /* mark the device as pointer */
- hid_set_drvdata(hdev, (void *)1);
- map_key_clear(KEY_MICMUTE);
- return 1;
- }
- return 0;
-}
-
-#undef map_key_clear
-
-static int tpkbd_features_set(struct hid_device *hdev)
-{
- struct hid_report *report;
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
-
- report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02;
- report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08;
- report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
- report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40;
- report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
- report->field[2]->value[0] = data_pointer->sensitivity;
- report->field[3]->value[0] = data_pointer->press_speed;
-
- hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
- return 0;
-}
-
-static ssize_t pointer_press_to_select_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
-}
-
-static ssize_t pointer_press_to_select_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value))
- return -EINVAL;
- if (value < 0 || value > 1)
- return -EINVAL;
-
- data_pointer->press_to_select = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static ssize_t pointer_dragging_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
-}
-
-static ssize_t pointer_dragging_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value))
- return -EINVAL;
- if (value < 0 || value > 1)
- return -EINVAL;
-
- data_pointer->dragging = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static ssize_t pointer_release_to_select_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
-}
-
-static ssize_t pointer_release_to_select_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value))
- return -EINVAL;
- if (value < 0 || value > 1)
- return -EINVAL;
-
- data_pointer->release_to_select = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static ssize_t pointer_select_right_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
-}
-
-static ssize_t pointer_select_right_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value))
- return -EINVAL;
- if (value < 0 || value > 1)
- return -EINVAL;
-
- data_pointer->select_right = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static ssize_t pointer_sensitivity_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- data_pointer->sensitivity);
-}
-
-static ssize_t pointer_sensitivity_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
- return -EINVAL;
-
- data_pointer->sensitivity = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static ssize_t pointer_press_speed_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- data_pointer->press_speed);
-}
-
-static ssize_t pointer_press_speed_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int value;
-
- if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
- return -EINVAL;
-
- data_pointer->press_speed = value;
- tpkbd_features_set(hdev);
-
- return count;
-}
-
-static struct device_attribute dev_attr_pointer_press_to_select =
- __ATTR(press_to_select, S_IWUSR | S_IRUGO,
- pointer_press_to_select_show,
- pointer_press_to_select_store);
-
-static struct device_attribute dev_attr_pointer_dragging =
- __ATTR(dragging, S_IWUSR | S_IRUGO,
- pointer_dragging_show,
- pointer_dragging_store);
-
-static struct device_attribute dev_attr_pointer_release_to_select =
- __ATTR(release_to_select, S_IWUSR | S_IRUGO,
- pointer_release_to_select_show,
- pointer_release_to_select_store);
-
-static struct device_attribute dev_attr_pointer_select_right =
- __ATTR(select_right, S_IWUSR | S_IRUGO,
- pointer_select_right_show,
- pointer_select_right_store);
-
-static struct device_attribute dev_attr_pointer_sensitivity =
- __ATTR(sensitivity, S_IWUSR | S_IRUGO,
- pointer_sensitivity_show,
- pointer_sensitivity_store);
-
-static struct device_attribute dev_attr_pointer_press_speed =
- __ATTR(press_speed, S_IWUSR | S_IRUGO,
- pointer_press_speed_show,
- pointer_press_speed_store);
-
-static struct attribute *tpkbd_attributes_pointer[] = {
- &dev_attr_pointer_press_to_select.attr,
- &dev_attr_pointer_dragging.attr,
- &dev_attr_pointer_release_to_select.attr,
- &dev_attr_pointer_select_right.attr,
- &dev_attr_pointer_sensitivity.attr,
- &dev_attr_pointer_press_speed.attr,
- NULL
-};
-
-static const struct attribute_group tpkbd_attr_group_pointer = {
- .attrs = tpkbd_attributes_pointer,
-};
-
-static enum led_brightness tpkbd_led_brightness_get(
- struct led_classdev *led_cdev)
-{
- struct device *dev = led_cdev->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- int led_nr = 0;
-
- if (led_cdev == &data_pointer->led_micmute)
- led_nr = 1;
-
- return data_pointer->led_state & (1 << led_nr)
- ? LED_FULL
- : LED_OFF;
-}
-
-static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct device *dev = led_cdev->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
- struct hid_report *report;
- int led_nr = 0;
-
- if (led_cdev == &data_pointer->led_micmute)
- led_nr = 1;
-
- if (value == LED_OFF)
- data_pointer->led_state &= ~(1 << led_nr);
- else
- data_pointer->led_state |= 1 << led_nr;
-
- report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
- report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
- report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
- hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
-}
-
-static int tpkbd_probe_tp(struct hid_device *hdev)
-{
- struct device *dev = &hdev->dev;
- struct tpkbd_data_pointer *data_pointer;
- size_t name_sz = strlen(dev_name(dev)) + 16;
- char *name_mute, *name_micmute;
- int i;
-
- /* Validate required reports. */
- for (i = 0; i < 4; i++) {
- if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
- return -ENODEV;
- }
- if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
- return -ENODEV;
-
- if (sysfs_create_group(&hdev->dev.kobj,
- &tpkbd_attr_group_pointer)) {
- hid_warn(hdev, "Could not create sysfs group\n");
- }
-
- data_pointer = devm_kzalloc(&hdev->dev,
- sizeof(struct tpkbd_data_pointer),
- GFP_KERNEL);
- if (data_pointer == NULL) {
- hid_err(hdev, "Could not allocate memory for driver data\n");
- return -ENOMEM;
- }
-
- // set same default values as windows driver
- data_pointer->sensitivity = 0xa0;
- data_pointer->press_speed = 0x38;
-
- name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
- name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
- if (name_mute == NULL || name_micmute == NULL) {
- hid_err(hdev, "Could not allocate memory for led data\n");
- return -ENOMEM;
- }
- snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
- snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
-
- hid_set_drvdata(hdev, data_pointer);
-
- data_pointer->led_mute.name = name_mute;
- data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
- data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
- data_pointer->led_mute.dev = dev;
- led_classdev_register(dev, &data_pointer->led_mute);
-
- data_pointer->led_micmute.name = name_micmute;
- data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
- data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
- data_pointer->led_micmute.dev = dev;
- led_classdev_register(dev, &data_pointer->led_micmute);
-
- tpkbd_features_set(hdev);
-
- return 0;
-}
-
-static int tpkbd_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(hdev);
- if (ret) {
- hid_err(hdev, "hid_parse failed\n");
- goto err;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- hid_err(hdev, "hid_hw_start failed\n");
- goto err;
- }
-
- if (hid_get_drvdata(hdev)) {
- hid_set_drvdata(hdev, NULL);
- ret = tpkbd_probe_tp(hdev);
- if (ret)
- goto err_hid;
- }
-
- return 0;
-err_hid:
- hid_hw_stop(hdev);
-err:
- return ret;
-}
-
-static void tpkbd_remove_tp(struct hid_device *hdev)
-{
- struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
-
- sysfs_remove_group(&hdev->dev.kobj,
- &tpkbd_attr_group_pointer);
-
- led_classdev_unregister(&data_pointer->led_micmute);
- led_classdev_unregister(&data_pointer->led_mute);
-
- hid_set_drvdata(hdev, NULL);
-}
-
-static void tpkbd_remove(struct hid_device *hdev)
-{
- if (hid_get_drvdata(hdev))
- tpkbd_remove_tp(hdev);
-
- hid_hw_stop(hdev);
-}
-
-static const struct hid_device_id tpkbd_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
- { }
-};
-
-MODULE_DEVICE_TABLE(hid, tpkbd_devices);
-
-static struct hid_driver tpkbd_driver = {
- .name = "lenovo_tpkbd",
- .id_table = tpkbd_devices,
- .input_mapping = tpkbd_input_mapping,
- .probe = tpkbd_probe,
- .remove = tpkbd_remove,
-};
-module_hid_driver(tpkbd_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
new file mode 100644
index 000000000000..bf227f7679af
--- /dev/null
+++ b/drivers/hid/hid-lenovo.c
@@ -0,0 +1,708 @@
+/*
+ * HID driver for Lenovo:
+ * - ThinkPad USB Keyboard with TrackPoint (tpkbd)
+ * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
+ * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
+ *
+ * Copyright (c) 2012 Bernhard Seibold
+ * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+
+#include "hid-ids.h"
+
+struct lenovo_drvdata_tpkbd {
+ int led_state;
+ struct led_classdev led_mute;
+ struct led_classdev led_micmute;
+ int press_to_select;
+ int dragging;
+ int release_to_select;
+ int select_right;
+ int sensitivity;
+ int press_speed;
+};
+
+struct lenovo_drvdata_cptkbd {
+ bool fn_lock;
+};
+
+#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
+
+static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
+ /* This sub-device contains trackpoint, mark it */
+ hid_set_drvdata(hdev, (void *)1);
+ map_key_clear(KEY_MICMUTE);
+ return 1;
+ }
+ return 0;
+}
+
+static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
+ (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x00f1: /* Fn-F4: Mic mute */
+ map_key_clear(KEY_MICMUTE);
+ return 1;
+ case 0x00f2: /* Fn-F5: Brightness down */
+ map_key_clear(KEY_BRIGHTNESSDOWN);
+ return 1;
+ case 0x00f3: /* Fn-F6: Brightness up */
+ map_key_clear(KEY_BRIGHTNESSUP);
+ return 1;
+ case 0x00f4: /* Fn-F7: External display (projector) */
+ map_key_clear(KEY_SWITCHVIDEOMODE);
+ return 1;
+ case 0x00f5: /* Fn-F8: Wireless */
+ map_key_clear(KEY_WLAN);
+ return 1;
+ case 0x00f6: /* Fn-F9: Control panel */
+ map_key_clear(KEY_CONFIG);
+ return 1;
+ case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
+ map_key_clear(KEY_SCALE);
+ return 1;
+ case 0x00fa: /* Fn-Esc: Fn-lock toggle */
+ map_key_clear(KEY_FN_ESC);
+ return 1;
+ case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */
+ /* NB: This mapping is invented in raw_event below */
+ map_key_clear(KEY_FILE);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int lenovo_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ switch (hdev->product) {
+ case USB_DEVICE_ID_LENOVO_TPKBD:
+ return lenovo_input_mapping_tpkbd(hdev, hi, field,
+ usage, bit, max);
+ case USB_DEVICE_ID_LENOVO_CUSBKBD:
+ case USB_DEVICE_ID_LENOVO_CBTKBD:
+ return lenovo_input_mapping_cptkbd(hdev, hi, field,
+ usage, bit, max);
+ default:
+ return 0;
+ }
+}
+
+#undef map_key_clear
+
+/* Send a config command to the keyboard */
+static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
+ unsigned char byte2, unsigned char byte3)
+{
+ int ret;
+ unsigned char buf[] = {0x18, byte2, byte3};
+
+ switch (hdev->product) {
+ case USB_DEVICE_ID_LENOVO_CUSBKBD:
+ ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf),
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ break;
+ case USB_DEVICE_ID_LENOVO_CBTKBD:
+ ret = hid_hw_output_report(hdev, buf, sizeof(buf));
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
+}
+
+static void lenovo_features_set_cptkbd(struct hid_device *hdev)
+{
+ int ret;
+ struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+
+ ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
+ if (ret)
+ hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
+}
+
+static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
+}
+
+static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ cptkbd_data->fn_lock = !!value;
+ lenovo_features_set_cptkbd(hdev);
+
+ return count;
+}
+
+static struct device_attribute dev_attr_fn_lock_cptkbd =
+ __ATTR(fn_lock, S_IWUSR | S_IRUGO,
+ attr_fn_lock_show_cptkbd,
+ attr_fn_lock_store_cptkbd);
+
+static struct attribute *lenovo_attributes_cptkbd[] = {
+ &dev_attr_fn_lock_cptkbd.attr,
+ NULL
+};
+
+static const struct attribute_group lenovo_attr_group_cptkbd = {
+ .attrs = lenovo_attributes_cptkbd,
+};
+
+static int lenovo_raw_event(struct hid_device *hdev,
+ struct hid_report *report, u8 *data, int size)
+{
+ /*
+ * Compact USB keyboard's Fn-F12 report holds down many other keys, and
+ * its own key is outside the usage page range. Remove extra
+ * keypresses and remap to inside usage page.
+ */
+ if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+ && size == 3
+ && data[0] == 0x15
+ && data[1] == 0x94
+ && data[2] == 0x01)) {
+ data[1] = 0x0;
+ data[2] = 0x4;
+ }
+
+ return 0;
+}
+
+static int lenovo_features_set_tpkbd(struct hid_device *hdev)
+{
+ struct hid_report *report;
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
+
+ report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02;
+ report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08;
+ report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
+ report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40;
+ report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
+ report->field[2]->value[0] = data_pointer->sensitivity;
+ report->field[3]->value[0] = data_pointer->press_speed;
+
+ hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+ return 0;
+}
+
+static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
+}
+
+static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ data_pointer->press_to_select = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static ssize_t attr_dragging_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
+}
+
+static ssize_t attr_dragging_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ data_pointer->dragging = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
+}
+
+static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ data_pointer->release_to_select = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static ssize_t attr_select_right_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
+}
+
+static ssize_t attr_select_right_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ data_pointer->select_right = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ data_pointer->sensitivity);
+}
+
+static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+ return -EINVAL;
+
+ data_pointer->sensitivity = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ data_pointer->press_speed);
+}
+
+static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+ return -EINVAL;
+
+ data_pointer->press_speed = value;
+ lenovo_features_set_tpkbd(hdev);
+
+ return count;
+}
+
+static struct device_attribute dev_attr_press_to_select_tpkbd =
+ __ATTR(press_to_select, S_IWUSR | S_IRUGO,
+ attr_press_to_select_show_tpkbd,
+ attr_press_to_select_store_tpkbd);
+
+static struct device_attribute dev_attr_dragging_tpkbd =
+ __ATTR(dragging, S_IWUSR | S_IRUGO,
+ attr_dragging_show_tpkbd,
+ attr_dragging_store_tpkbd);
+
+static struct device_attribute dev_attr_release_to_select_tpkbd =
+ __ATTR(release_to_select, S_IWUSR | S_IRUGO,
+ attr_release_to_select_show_tpkbd,
+ attr_release_to_select_store_tpkbd);
+
+static struct device_attribute dev_attr_select_right_tpkbd =
+ __ATTR(select_right, S_IWUSR | S_IRUGO,
+ attr_select_right_show_tpkbd,
+ attr_select_right_store_tpkbd);
+
+static struct device_attribute dev_attr_sensitivity_tpkbd =
+ __ATTR(sensitivity, S_IWUSR | S_IRUGO,
+ attr_sensitivity_show_tpkbd,
+ attr_sensitivity_store_tpkbd);
+
+static struct device_attribute dev_attr_press_speed_tpkbd =
+ __ATTR(press_speed, S_IWUSR | S_IRUGO,
+ attr_press_speed_show_tpkbd,
+ attr_press_speed_store_tpkbd);
+
+static struct attribute *lenovo_attributes_tpkbd[] = {
+ &dev_attr_press_to_select_tpkbd.attr,
+ &dev_attr_dragging_tpkbd.attr,
+ &dev_attr_release_to_select_tpkbd.attr,
+ &dev_attr_select_right_tpkbd.attr,
+ &dev_attr_sensitivity_tpkbd.attr,
+ &dev_attr_press_speed_tpkbd.attr,
+ NULL
+};
+
+static const struct attribute_group lenovo_attr_group_tpkbd = {
+ .attrs = lenovo_attributes_tpkbd,
+};
+
+static enum led_brightness lenovo_led_brightness_get_tpkbd(
+ struct led_classdev *led_cdev)
+{
+ struct device *dev = led_cdev->dev->parent;
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ int led_nr = 0;
+
+ if (led_cdev == &data_pointer->led_micmute)
+ led_nr = 1;
+
+ return data_pointer->led_state & (1 << led_nr)
+ ? LED_FULL
+ : LED_OFF;
+}
+
+static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct device *dev = led_cdev->dev->parent;
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+ struct hid_report *report;
+ int led_nr = 0;
+
+ if (led_cdev == &data_pointer->led_micmute)
+ led_nr = 1;
+
+ if (value == LED_OFF)
+ data_pointer->led_state &= ~(1 << led_nr);
+ else
+ data_pointer->led_state |= 1 << led_nr;
+
+ report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
+ report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
+ report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
+ hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+}
+
+static int lenovo_probe_tpkbd(struct hid_device *hdev)
+{
+ struct device *dev = &hdev->dev;
+ struct lenovo_drvdata_tpkbd *data_pointer;
+ size_t name_sz = strlen(dev_name(dev)) + 16;
+ char *name_mute, *name_micmute;
+ int i;
+ int ret;
+
+ /*
+ * Only register extra settings against subdevice where input_mapping
+ * set drvdata to 1, i.e. the trackpoint.
+ */
+ if (!hid_get_drvdata(hdev))
+ return 0;
+
+ hid_set_drvdata(hdev, NULL);
+
+ /* Validate required reports. */
+ for (i = 0; i < 4; i++) {
+ if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
+ return -ENODEV;
+ }
+ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
+ return -ENODEV;
+
+ ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
+ if (ret)
+ hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
+
+ data_pointer = devm_kzalloc(&hdev->dev,
+ sizeof(struct lenovo_drvdata_tpkbd),
+ GFP_KERNEL);
+ if (data_pointer == NULL) {
+ hid_err(hdev, "Could not allocate memory for driver data\n");
+ return -ENOMEM;
+ }
+
+ // set same default values as windows driver
+ data_pointer->sensitivity = 0xa0;
+ data_pointer->press_speed = 0x38;
+
+ name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+ name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+ if (name_mute == NULL || name_micmute == NULL) {
+ hid_err(hdev, "Could not allocate memory for led data\n");
+ return -ENOMEM;
+ }
+ snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
+ snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
+
+ hid_set_drvdata(hdev, data_pointer);
+
+ data_pointer->led_mute.name = name_mute;
+ data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
+ data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
+ data_pointer->led_mute.dev = dev;
+ led_classdev_register(dev, &data_pointer->led_mute);
+
+ data_pointer->led_micmute.name = name_micmute;
+ data_pointer->led_micmute.brightness_get =
+ lenovo_led_brightness_get_tpkbd;
+ data_pointer->led_micmute.brightness_set =
+ lenovo_led_brightness_set_tpkbd;
+ data_pointer->led_micmute.dev = dev;
+ led_classdev_register(dev, &data_pointer->led_micmute);
+
+ lenovo_features_set_tpkbd(hdev);
+
+ return 0;
+}
+
+static int lenovo_probe_cptkbd(struct hid_device *hdev)
+{
+ int ret;
+ struct lenovo_drvdata_cptkbd *cptkbd_data;
+
+ /* All the custom action happens on the USBMOUSE device for USB */
+ if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+ && hdev->type != HID_TYPE_USBMOUSE) {
+ hid_dbg(hdev, "Ignoring keyboard half of device\n");
+ return 0;
+ }
+
+ cptkbd_data = devm_kzalloc(&hdev->dev,
+ sizeof(*cptkbd_data),
+ GFP_KERNEL);
+ if (cptkbd_data == NULL) {
+ hid_err(hdev, "can't alloc keyboard descriptor\n");
+ return -ENOMEM;
+ }
+ hid_set_drvdata(hdev, cptkbd_data);
+
+ /*
+ * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
+ * regular keys
+ */
+ ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
+ if (ret)
+ hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
+
+ /* Turn Fn-Lock on by default */
+ cptkbd_data->fn_lock = true;
+ lenovo_features_set_cptkbd(hdev);
+
+ ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
+ if (ret)
+ hid_warn(hdev, "Could not create sysfs group: %d\n", ret);
+
+ return 0;
+}
+
+static int lenovo_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "hid_parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ hid_err(hdev, "hid_hw_start failed\n");
+ goto err;
+ }
+
+ switch (hdev->product) {
+ case USB_DEVICE_ID_LENOVO_TPKBD:
+ ret = lenovo_probe_tpkbd(hdev);
+ break;
+ case USB_DEVICE_ID_LENOVO_CUSBKBD:
+ case USB_DEVICE_ID_LENOVO_CBTKBD:
+ ret = lenovo_probe_cptkbd(hdev);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+ if (ret)
+ goto err_hid;
+
+ return 0;
+err_hid:
+ hid_hw_stop(hdev);
+err:
+ return ret;
+}
+
+static void lenovo_remove_tpkbd(struct hid_device *hdev)
+{
+ struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
+
+ /*
+ * Only the trackpoint half of the keyboard has drvdata and stuff that
+ * needs unregistering.
+ */
+ if (data_pointer == NULL)
+ return;
+
+ sysfs_remove_group(&hdev->dev.kobj,
+ &lenovo_attr_group_tpkbd);
+
+ led_classdev_unregister(&data_pointer->led_micmute);
+ led_classdev_unregister(&data_pointer->led_mute);
+
+ hid_set_drvdata(hdev, NULL);
+}
+
+static void lenovo_remove_cptkbd(struct hid_device *hdev)
+{
+ sysfs_remove_group(&hdev->dev.kobj,
+ &lenovo_attr_group_cptkbd);
+}
+
+static void lenovo_remove(struct hid_device *hdev)
+{
+ switch (hdev->product) {
+ case USB_DEVICE_ID_LENOVO_TPKBD:
+ lenovo_remove_tpkbd(hdev);
+ break;
+ case USB_DEVICE_ID_LENOVO_CUSBKBD:
+ case USB_DEVICE_ID_LENOVO_CBTKBD:
+ lenovo_remove_cptkbd(hdev);
+ break;
+ }
+
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lenovo_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(hid, lenovo_devices);
+
+static struct hid_driver lenovo_driver = {
+ .name = "lenovo",
+ .id_table = lenovo_devices,
+ .input_mapping = lenovo_input_mapping,
+ .probe = lenovo_probe,
+ .remove = lenovo_remove,
+ .raw_event = lenovo_raw_event,
+};
+module_hid_driver(lenovo_driver);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index cf1a9f1c1217..045f8ebf16b5 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
rdev->priv = data;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = picolcd_cir_open;
rdev->close = picolcd_cir_close;
rdev->input_name = data->hdev->name;
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
index 024cdf3c2297..3c13af684410 100644
--- a/drivers/hid/hid-picolcd_debugfs.c
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -883,16 +883,13 @@ void picolcd_exit_devfs(struct picolcd_data *data)
dent = data->debug_reset;
data->debug_reset = NULL;
- if (dent)
- debugfs_remove(dent);
+ debugfs_remove(dent);
dent = data->debug_eeprom;
data->debug_eeprom = NULL;
- if (dent)
- debugfs_remove(dent);
+ debugfs_remove(dent);
dent = data->debug_flash;
data->debug_flash = NULL;
- if (dent)
- debugfs_remove(dent);
+ debugfs_remove(dent);
mutex_destroy(&data->mutex_flash);
}
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 578bbe65902b..0dc25142f451 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -377,7 +377,7 @@ static int rmi_input_event(struct hid_device *hdev, u8 *data, int size)
irq_mask |= hdata->f30.irq_mask;
if (data[1] & ~irq_mask)
- hid_warn(hdev, "unknown intr source:%02lx %s:%d\n",
+ hid_dbg(hdev, "unknown intr source:%02lx %s:%d\n",
data[1] & ~irq_mask, __FILE__, __LINE__);
if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) {
@@ -400,7 +400,7 @@ static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size)
struct rmi_data *hdata = hid_get_drvdata(hdev);
if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) {
- hid_err(hdev, "no read request pending\n");
+ hid_dbg(hdev, "no read request pending\n");
return 0;
}
@@ -549,10 +549,12 @@ static int rmi_populate_f11(struct hid_device *hdev)
u8 buf[20];
int ret;
bool has_query9;
- bool has_query10;
+ bool has_query10 = false;
bool has_query11;
bool has_query12;
bool has_physical_props;
+ bool has_gestures;
+ bool has_rel;
unsigned x_size, y_size;
u16 query12_offset;
@@ -589,19 +591,32 @@ static int rmi_populate_f11(struct hid_device *hdev)
return -ENODEV;
}
- /* query 8 to find out if query 10 exists */
- ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf);
- if (ret) {
- hid_err(hdev, "can not read gesture information: %d.\n", ret);
- return ret;
+ has_rel = !!(buf[0] & BIT(3));
+ has_gestures = !!(buf[0] & BIT(5));
+
+ if (has_gestures) {
+ /* query 8 to find out if query 10 exists */
+ ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf);
+ if (ret) {
+ hid_err(hdev, "can not read gesture information: %d.\n",
+ ret);
+ return ret;
+ }
+ has_query10 = !!(buf[0] & BIT(2));
}
- has_query10 = !!(buf[0] & BIT(2));
/*
- * At least 8 queries are guaranteed to be present in F11
- * +1 for query12.
+ * At least 4 queries are guaranteed to be present in F11
+ * +1 for query 5 which is present since absolute events are
+ * reported and +1 for query 12.
*/
- query12_offset = 9;
+ query12_offset = 6;
+
+ if (has_rel)
+ ++query12_offset; /* query 6 is present */
+
+ if (has_gestures)
+ query12_offset += 2; /* query 7 and 8 are present */
if (has_query9)
++query12_offset;
@@ -833,6 +848,8 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
struct rmi_data *data = NULL;
int ret;
size_t alloc_size;
+ struct hid_report *input_report;
+ struct hid_report *output_report;
data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL);
if (!data)
@@ -851,12 +868,26 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
}
- data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT]
- .report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3)
- + 1 /* report id */;
- data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT]
- .report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3)
- + 1 /* report id */;
+ input_report = hdev->report_enum[HID_INPUT_REPORT]
+ .report_id_hash[RMI_ATTN_REPORT_ID];
+ if (!input_report) {
+ hid_err(hdev, "device does not have expected input report\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ data->input_report_size = (input_report->size >> 3) + 1 /* report id */;
+
+ output_report = hdev->report_enum[HID_OUTPUT_REPORT]
+ .report_id_hash[RMI_WRITE_REPORT_ID];
+ if (!output_report) {
+ hid_err(hdev, "device does not have expected output report\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ data->output_report_size = (output_report->size >> 3)
+ + 1 /* report id */;
alloc_size = data->output_report_size + data->input_report_size;
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
index 6adc0fa08d96..65e2e76bf2fe 100644
--- a/drivers/hid/hid-roccat-lua.c
+++ b/drivers/hid/hid-roccat-lua.c
@@ -61,7 +61,7 @@ static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
return -EINVAL;
mutex_lock(&lua->lua_lock);
- retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
+ retval = roccat_common2_send(usb_dev, command, buf, real_size);
mutex_unlock(&lua->lua_lock);
return retval ? retval : real_size;
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 2259eaa8b988..c372368e438c 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -56,32 +56,81 @@
#define MAX_LEDS 4
-static const u8 sixaxis_rdesc_fixup[] = {
- 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
- 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF,
- 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02
-};
-
-static const u8 sixaxis_rdesc_fixup2[] = {
- 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02,
- 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
- 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45,
- 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81,
- 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff,
- 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
- 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95,
- 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30,
- 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02,
- 0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81,
- 0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95,
- 0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09,
- 0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02,
- 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02,
- 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95,
- 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
- 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
- 0xb1, 0x02, 0xc0, 0xc0,
+static __u8 sixaxis_rdesc[] = {
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x04, /* Usage (Joystik), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0xA1, 0x02, /* Collection (Logical), */
+ 0x85, 0x01, /* Report ID (1), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x13, /* Report Count (19), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x35, 0x00, /* Physical Minimum (0), */
+ 0x45, 0x01, /* Physical Maximum (1), */
+ 0x05, 0x09, /* Usage Page (Button), */
+ 0x19, 0x01, /* Usage Minimum (01h), */
+ 0x29, 0x13, /* Usage Maximum (13h), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x0D, /* Report Count (13), */
+ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xA1, 0x00, /* Collection (Physical), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x04, /* Report Count (4), */
+ 0x35, 0x00, /* Physical Minimum (0), */
+ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x09, 0x32, /* Usage (Z), */
+ 0x09, 0x35, /* Usage (Rz), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x95, 0x13, /* Report Count (19), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x0C, /* Report Count (12), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x95, 0x04, /* Report Count (4), */
+ 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+ 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xA1, 0x02, /* Collection (Logical), */
+ 0x85, 0x02, /* Report ID (2), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x30, /* Report Count (48), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xB1, 0x02, /* Feature (Variable), */
+ 0xC0, /* End Collection, */
+ 0xA1, 0x02, /* Collection (Logical), */
+ 0x85, 0xEE, /* Report ID (238), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x30, /* Report Count (48), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xB1, 0x02, /* Feature (Variable), */
+ 0xC0, /* End Collection, */
+ 0xA1, 0x02, /* Collection (Logical), */
+ 0x85, 0xEF, /* Report ID (239), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x30, /* Report Count (48), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xB1, 0x02, /* Feature (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
};
/*
@@ -778,6 +827,13 @@ struct sony_sc {
__u8 led_count;
};
+static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ *rsize = sizeof(sixaxis_rdesc);
+ return sixaxis_rdesc;
+}
+
static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
@@ -819,8 +875,6 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1;
}
-
-/* Sony Vaio VGX has wrongly mouse pointer declared as constant */
static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
@@ -857,20 +911,8 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(dualshock4_bt_rdesc);
}
- /* The HID descriptor exposed over BT has a trailing zero byte */
- if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) ||
- ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) &&
- rdesc[83] == 0x75) {
- hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n");
- memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup,
- sizeof(sixaxis_rdesc_fixup));
- } else if (sc->quirks & SIXAXIS_CONTROLLER_USB &&
- *rsize > sizeof(sixaxis_rdesc_fixup2)) {
- hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n",
- *rsize, (int)sizeof(sixaxis_rdesc_fixup2));
- *rsize = sizeof(sixaxis_rdesc_fixup2);
- memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize);
- }
+ if (sc->quirks & SIXAXIS_CONTROLLER)
+ return sixaxis_fixup(hdev, rdesc, rsize);
if (sc->quirks & PS3REMOTE)
return ps3remote_fixup(hdev, rdesc, rsize);
@@ -1307,7 +1349,7 @@ static int sony_leds_init(struct sony_sc *sc)
static const char * const ds4_name_str[] = { "red", "green", "blue",
"global" };
__u8 initial_values[MAX_LEDS] = { 0 };
- __u8 max_brightness[MAX_LEDS] = { 1 };
+ __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 };
__u8 use_hw_blink[MAX_LEDS] = { 0 };
BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
@@ -1830,9 +1872,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (sc->quirks & VAIO_RDESC_CONSTANT)
connect_mask |= HID_CONNECT_HIDDEV_FORCE;
- else if (sc->quirks & SIXAXIS_CONTROLLER_USB)
- connect_mask |= HID_CONNECT_HIDDEV_FORCE;
- else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
+ else if (sc->quirks & SIXAXIS_CONTROLLER)
connect_mask |= HID_CONNECT_HIDDEV_FORCE;
ret = hid_hw_start(hdev, connect_mask);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
deleted file mode 100644
index 902013ec041b..000000000000
--- a/drivers/hid/hid-wacom.c
+++ /dev/null
@@ -1,973 +0,0 @@
-/*
- * Bluetooth Wacom Tablet support
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
- * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
- * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
- * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include <linux/power_supply.h>
-
-#include "hid-ids.h"
-
-#define PAD_DEVICE_ID 0x0F
-
-#define WAC_CMD_LED_CONTROL 0x20
-#define WAC_CMD_ICON_START_STOP 0x21
-#define WAC_CMD_ICON_TRANSFER 0x26
-
-struct wacom_data {
- __u16 tool;
- __u16 butstate;
- __u8 whlstate;
- __u8 features;
- __u32 id;
- __u32 serial;
- unsigned char high_speed;
- __u8 battery_capacity;
- __u8 power_raw;
- __u8 ps_connected;
- __u8 bat_charging;
- struct power_supply battery;
- struct power_supply ac;
- __u8 led_selector;
- struct led_classdev *leds[4];
-};
-
-/*percent of battery capacity for Graphire
- 8th value means AC online and show 100% capacity */
-static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
-/*percent of battery capacity for Intuos4 WL, AC has a separate bit*/
-static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
-
-static enum power_supply_property wacom_battery_props[] = {
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_SCOPE,
- POWER_SUPPLY_PROP_STATUS,
-};
-
-static enum power_supply_property wacom_ac_props[] = {
- POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_ONLINE,
- POWER_SUPPLY_PROP_SCOPE,
-};
-
-static void wacom_scramble(__u8 *image)
-{
- __u16 mask;
- __u16 s1;
- __u16 s2;
- __u16 r1 ;
- __u16 r2 ;
- __u16 r;
- __u8 buf[256];
- int i, w, x, y, z;
-
- for (x = 0; x < 32; x++) {
- for (y = 0; y < 8; y++)
- buf[(8 * x) + (7 - y)] = image[(8 * x) + y];
- }
-
- /* Change 76543210 into GECA6420 as required by Intuos4 WL
- * HGFEDCBA HFDB7531
- */
- for (x = 0; x < 4; x++) {
- for (y = 0; y < 4; y++) {
- for (z = 0; z < 8; z++) {
- mask = 0x0001;
- r1 = 0;
- r2 = 0;
- i = (x << 6) + (y << 4) + z;
- s1 = buf[i];
- s2 = buf[i+8];
- for (w = 0; w < 8; w++) {
- r1 |= (s1 & mask);
- r2 |= (s2 & mask);
- s1 <<= 1;
- s2 <<= 1;
- mask <<= 2;
- }
- r = r1 | (r2 << 1);
- i = (x << 6) + (y << 4) + (z << 1);
- image[i] = 0xFF & r;
- image[i+1] = (0xFF00 & r) >> 8;
- }
- }
- }
-}
-
-static void wacom_set_image(struct hid_device *hdev, const char *image,
- __u8 icon_no)
-{
- __u8 rep_data[68];
- __u8 p[256];
- int ret, i, j;
-
- for (i = 0; i < 256; i++)
- p[i] = image[i];
-
- rep_data[0] = WAC_CMD_ICON_START_STOP;
- rep_data[1] = 0;
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- if (ret < 0)
- goto err;
-
- rep_data[0] = WAC_CMD_ICON_TRANSFER;
- rep_data[1] = icon_no & 0x07;
-
- wacom_scramble(p);
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 64; j++)
- rep_data[j + 3] = p[(i << 6) + j];
-
- rep_data[2] = i;
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 67,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- }
-
- rep_data[0] = WAC_CMD_ICON_START_STOP;
- rep_data[1] = 0;
-
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
-
-err:
- return;
-}
-
-static void wacom_leds_set_brightness(struct led_classdev *led_dev,
- enum led_brightness value)
-{
- struct device *dev = led_dev->dev->parent;
- struct hid_device *hdev;
- struct wacom_data *wdata;
- unsigned char *buf;
- __u8 led = 0;
- int i;
-
- hdev = container_of(dev, struct hid_device, dev);
- wdata = hid_get_drvdata(hdev);
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i] == led_dev)
- wdata->led_selector = i;
- }
-
- led = wdata->led_selector | 0x04;
- buf = kzalloc(9, GFP_KERNEL);
- if (buf) {
- buf[0] = WAC_CMD_LED_CONTROL;
- buf[1] = led;
- buf[2] = value >> 2;
- buf[3] = value;
- /* use fixed brightness for OLEDs */
- buf[4] = 0x08;
- hid_hw_raw_request(hdev, buf[0], buf, 9, HID_FEATURE_REPORT,
- HID_REQ_SET_REPORT);
- kfree(buf);
- }
-
- return;
-}
-
-static enum led_brightness wacom_leds_get_brightness(struct led_classdev *led_dev)
-{
- struct wacom_data *wdata;
- struct device *dev = led_dev->dev->parent;
- int value = 0;
- int i;
-
- wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
-
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i] == led_dev) {
- value = wdata->leds[i]->brightness;
- break;
- }
- }
-
- return value;
-}
-
-
-static int wacom_initialize_leds(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct led_classdev *led;
- struct device *dev = &hdev->dev;
- size_t namesz = strlen(dev_name(dev)) + 12;
- char *name;
- int i, ret;
-
- wdata->led_selector = 0;
-
- for (i = 0; i < 4; i++) {
- led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL);
- if (!led) {
- hid_warn(hdev,
- "can't allocate memory for LED selector\n");
- ret = -ENOMEM;
- goto err;
- }
-
- name = (void *)&led[1];
- snprintf(name, namesz, "%s:selector:%d", dev_name(dev), i);
- led->name = name;
- led->brightness = 0;
- led->max_brightness = 127;
- led->brightness_get = wacom_leds_get_brightness;
- led->brightness_set = wacom_leds_set_brightness;
-
- wdata->leds[i] = led;
-
- ret = led_classdev_register(dev, wdata->leds[i]);
-
- if (ret) {
- wdata->leds[i] = NULL;
- kfree(led);
- hid_warn(hdev, "can't register LED\n");
- goto err;
- }
- }
-
-err:
- return ret;
-}
-
-static void wacom_destroy_leds(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct led_classdev *led;
- int i;
-
- for (i = 0; i < 4; ++i) {
- if (wdata->leds[i]) {
- led = wdata->leds[i];
- wdata->leds[i] = NULL;
- led_classdev_unregister(led);
- kfree(led);
- }
- }
-
-}
-
-static int wacom_battery_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- struct wacom_data *wdata = container_of(psy,
- struct wacom_data, battery);
- int ret = 0;
-
- switch (psp) {
- case POWER_SUPPLY_PROP_PRESENT:
- val->intval = 1;
- break;
- case POWER_SUPPLY_PROP_SCOPE:
- val->intval = POWER_SUPPLY_SCOPE_DEVICE;
- break;
- case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = wdata->battery_capacity;
- break;
- case POWER_SUPPLY_PROP_STATUS:
- if (wdata->bat_charging)
- val->intval = POWER_SUPPLY_STATUS_CHARGING;
- else
- if (wdata->battery_capacity == 100 && wdata->ps_connected)
- val->intval = POWER_SUPPLY_STATUS_FULL;
- else
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
-static int wacom_ac_get_property(struct power_supply *psy,
- enum power_supply_property psp,
- union power_supply_propval *val)
-{
- struct wacom_data *wdata = container_of(psy, struct wacom_data, ac);
- int ret = 0;
-
- switch (psp) {
- case POWER_SUPPLY_PROP_PRESENT:
- /* fall through */
- case POWER_SUPPLY_PROP_ONLINE:
- val->intval = wdata->ps_connected;
- break;
- case POWER_SUPPLY_PROP_SCOPE:
- val->intval = POWER_SUPPLY_SCOPE_DEVICE;
- break;
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
-static void wacom_set_features(struct hid_device *hdev, u8 speed)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- int limit, ret;
- __u8 rep_data[2];
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- rep_data[0] = 0x03 ; rep_data[1] = 0x00;
- limit = 3;
- do {
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- } while (ret < 0 && limit-- > 0);
-
- if (ret >= 0) {
- if (speed == 0)
- rep_data[0] = 0x05;
- else
- rep_data[0] = 0x06;
-
- rep_data[1] = 0x00;
- limit = 3;
- do {
- ret = hid_hw_raw_request(hdev, rep_data[0],
- rep_data, 2, HID_FEATURE_REPORT,
- HID_REQ_SET_REPORT);
- } while (ret < 0 && limit-- > 0);
-
- if (ret >= 0) {
- wdata->high_speed = speed;
- return;
- }
- }
-
- /*
- * Note that if the raw queries fail, it's not a hard failure
- * and it is safe to continue
- */
- hid_warn(hdev, "failed to poke device, command %d, err %d\n",
- rep_data[0], ret);
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- if (speed == 1)
- wdata->features &= ~0x20;
- else
- wdata->features |= 0x20;
-
- rep_data[0] = 0x03;
- rep_data[1] = wdata->features;
-
- ret = hid_hw_raw_request(hdev, rep_data[0], rep_data, 2,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- if (ret >= 0)
- wdata->high_speed = speed;
- break;
- }
-
- return;
-}
-
-static ssize_t wacom_show_speed(struct device *dev,
- struct device_attribute
- *attr, char *buf)
-{
- struct wacom_data *wdata = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "%i\n", wdata->high_speed);
-}
-
-static ssize_t wacom_store_speed(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- int new_speed;
-
- if (sscanf(buf, "%1d", &new_speed ) != 1)
- return -EINVAL;
-
- if (new_speed == 0 || new_speed == 1) {
- wacom_set_features(hdev, new_speed);
- return strnlen(buf, PAGE_SIZE);
- } else
- return -EINVAL;
-}
-
-static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
- wacom_show_speed, wacom_store_speed);
-
-#define WACOM_STORE(OLED_ID) \
-static ssize_t wacom_oled##OLED_ID##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct hid_device *hdev = container_of(dev, struct hid_device, \
- dev); \
- \
- if (count != 256) \
- return -EINVAL; \
- \
- wacom_set_image(hdev, buf, OLED_ID); \
- \
- return count; \
-} \
- \
-static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL, \
- wacom_oled##OLED_ID##_store)
-
-WACOM_STORE(0);
-WACOM_STORE(1);
-WACOM_STORE(2);
-WACOM_STORE(3);
-WACOM_STORE(4);
-WACOM_STORE(5);
-WACOM_STORE(6);
-WACOM_STORE(7);
-
-static int wacom_gr_parse_report(struct hid_device *hdev,
- struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- int tool, x, y, rw;
-
- tool = 0;
- /* Get X & Y positions */
- x = le16_to_cpu(*(__le16 *) &data[2]);
- y = le16_to_cpu(*(__le16 *) &data[4]);
-
- /* Get current tool identifier */
- if (data[1] & 0x90) { /* If pen is in the in/active area */
- switch ((data[1] >> 5) & 3) {
- case 0: /* Pen */
- tool = BTN_TOOL_PEN;
- break;
-
- case 1: /* Rubber */
- tool = BTN_TOOL_RUBBER;
- break;
-
- case 2: /* Mouse with wheel */
- case 3: /* Mouse without wheel */
- tool = BTN_TOOL_MOUSE;
- break;
- }
-
- /* Reset tool if out of active tablet area */
- if (!(data[1] & 0x10))
- tool = 0;
- }
-
- /* If tool changed, notify input subsystem */
- if (wdata->tool != tool) {
- if (wdata->tool) {
- /* Completely reset old tool state */
- if (wdata->tool == BTN_TOOL_MOUSE) {
- input_report_key(input, BTN_LEFT, 0);
- input_report_key(input, BTN_RIGHT, 0);
- input_report_key(input, BTN_MIDDLE, 0);
- input_report_abs(input, ABS_DISTANCE,
- input_abs_get_max(input, ABS_DISTANCE));
- } else {
- input_report_key(input, BTN_TOUCH, 0);
- input_report_key(input, BTN_STYLUS, 0);
- input_report_key(input, BTN_STYLUS2, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- }
- input_report_key(input, wdata->tool, 0);
- input_sync(input);
- }
- wdata->tool = tool;
- if (tool)
- input_report_key(input, tool, 1);
- }
-
- if (tool) {
- input_report_abs(input, ABS_X, x);
- input_report_abs(input, ABS_Y, y);
-
- switch ((data[1] >> 5) & 3) {
- case 2: /* Mouse with wheel */
- input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
- rw = (data[6] & 0x01) ? -1 :
- (data[6] & 0x02) ? 1 : 0;
- input_report_rel(input, REL_WHEEL, rw);
- /* fall through */
-
- case 3: /* Mouse without wheel */
- input_report_key(input, BTN_LEFT, data[1] & 0x01);
- input_report_key(input, BTN_RIGHT, data[1] & 0x02);
- /* Compute distance between mouse and tablet */
- rw = 44 - (data[6] >> 2);
- if (rw < 0)
- rw = 0;
- else if (rw > 31)
- rw = 31;
- input_report_abs(input, ABS_DISTANCE, rw);
- break;
-
- default:
- input_report_abs(input, ABS_PRESSURE,
- data[6] | (((__u16) (data[1] & 0x08)) << 5));
- input_report_key(input, BTN_TOUCH, data[1] & 0x01);
- input_report_key(input, BTN_STYLUS, data[1] & 0x02);
- input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
- break;
- }
-
- input_sync(input);
- }
-
- /* Report the state of the two buttons at the top of the tablet
- * as two extra fingerpad keys (buttons 4 & 5). */
- rw = data[7] & 0x03;
- if (rw != wdata->butstate) {
- wdata->butstate = rw;
- input_report_key(input, BTN_0, rw & 0x02);
- input_report_key(input, BTN_1, rw & 0x01);
- input_report_key(input, BTN_TOOL_FINGER, 0xf0);
- input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
- input_sync(input);
- }
-
- /* Store current battery capacity and power supply state*/
- rw = (data[7] >> 2 & 0x07);
- if (rw != wdata->power_raw) {
- wdata->power_raw = rw;
- wdata->battery_capacity = batcap_gr[rw];
- if (rw == 7)
- wdata->ps_connected = 1;
- else
- wdata->ps_connected = 0;
- }
- return 1;
-}
-
-static void wacom_i4_parse_button_report(struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- __u16 new_butstate;
- __u8 new_whlstate;
- __u8 sync = 0;
-
- new_whlstate = data[1];
- if (new_whlstate != wdata->whlstate) {
- wdata->whlstate = new_whlstate;
- if (new_whlstate & 0x80) {
- input_report_key(input, BTN_TOUCH, 1);
- input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f));
- input_report_key(input, BTN_TOOL_FINGER, 1);
- } else {
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_WHEEL, 0);
- input_report_key(input, BTN_TOOL_FINGER, 0);
- }
- sync = 1;
- }
-
- new_butstate = (data[3] << 1) | (data[2] & 0x01);
- if (new_butstate != wdata->butstate) {
- wdata->butstate = new_butstate;
- input_report_key(input, BTN_0, new_butstate & 0x001);
- input_report_key(input, BTN_1, new_butstate & 0x002);
- input_report_key(input, BTN_2, new_butstate & 0x004);
- input_report_key(input, BTN_3, new_butstate & 0x008);
- input_report_key(input, BTN_4, new_butstate & 0x010);
- input_report_key(input, BTN_5, new_butstate & 0x020);
- input_report_key(input, BTN_6, new_butstate & 0x040);
- input_report_key(input, BTN_7, new_butstate & 0x080);
- input_report_key(input, BTN_8, new_butstate & 0x100);
- input_report_key(input, BTN_TOOL_FINGER, 1);
- sync = 1;
- }
-
- if (sync) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
- input_sync(input);
- }
-}
-
-static void wacom_i4_parse_pen_report(struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- __u16 x, y, pressure;
- __u8 distance;
- __u8 tilt_x, tilt_y;
-
- switch (data[1]) {
- case 0x80: /* Out of proximity report */
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- input_report_key(input, BTN_STYLUS, 0);
- input_report_key(input, BTN_STYLUS2, 0);
- input_report_key(input, wdata->tool, 0);
- input_report_abs(input, ABS_MISC, 0);
- input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
- wdata->tool = 0;
- input_sync(input);
- break;
- case 0xC2: /* Tool report */
- wdata->id = ((data[2] << 4) | (data[3] >> 4) |
- ((data[7] & 0x0f) << 20) |
- ((data[8] & 0xf0) << 12));
- wdata->serial = ((data[3] & 0x0f) << 28) +
- (data[4] << 20) + (data[5] << 12) +
- (data[6] << 4) + (data[7] >> 4);
-
- switch (wdata->id) {
- case 0x100802:
- wdata->tool = BTN_TOOL_PEN;
- break;
- case 0x10080A:
- wdata->tool = BTN_TOOL_RUBBER;
- break;
- }
- break;
- default: /* Position/pressure report */
- x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1);
- y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01);
- pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5)
- | (data[1] & 0x01);
- distance = (data[9] >> 2) & 0x3f;
- tilt_x = ((data[7] << 1) & 0x7e) | (data[8] >> 7);
- tilt_y = data[8] & 0x7f;
-
- input_report_key(input, BTN_TOUCH, pressure > 1);
-
- input_report_key(input, BTN_STYLUS, data[1] & 0x02);
- input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
- input_report_key(input, wdata->tool, 1);
- input_report_abs(input, ABS_X, x);
- input_report_abs(input, ABS_Y, y);
- input_report_abs(input, ABS_PRESSURE, pressure);
- input_report_abs(input, ABS_DISTANCE, distance);
- input_report_abs(input, ABS_TILT_X, tilt_x);
- input_report_abs(input, ABS_TILT_Y, tilt_y);
- input_report_abs(input, ABS_MISC, wdata->id);
- input_event(input, EV_MSC, MSC_SERIAL, wdata->serial);
- input_report_key(input, wdata->tool, 1);
- input_sync(input);
- break;
- }
-
- return;
-}
-
-static void wacom_i4_parse_report(struct hid_device *hdev,
- struct wacom_data *wdata,
- struct input_dev *input, unsigned char *data)
-{
- switch (data[0]) {
- case 0x00: /* Empty report */
- break;
- case 0x02: /* Pen report */
- wacom_i4_parse_pen_report(wdata, input, data);
- break;
- case 0x03: /* Features Report */
- wdata->features = data[2];
- break;
- case 0x0C: /* Button report */
- wacom_i4_parse_button_report(wdata, input, data);
- break;
- default:
- hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]);
- break;
- }
-}
-
-static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
- u8 *raw_data, int size)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
- struct hid_input *hidinput;
- struct input_dev *input;
- unsigned char *data = (unsigned char *) raw_data;
- int i;
- __u8 power_raw;
-
- if (!(hdev->claimed & HID_CLAIMED_INPUT))
- return 0;
-
- hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
- input = hidinput->input;
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- if (data[0] == 0x03) {
- return wacom_gr_parse_report(hdev, wdata, input, data);
- } else {
- hid_err(hdev, "Unknown report: %d,%d size:%d\n",
- data[0], data[1], size);
- return 0;
- }
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- i = 1;
-
- switch (data[0]) {
- case 0x04:
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- i += 10;
- /* fall through */
- case 0x03:
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- i += 10;
- wacom_i4_parse_report(hdev, wdata, input, data + i);
- power_raw = data[i+10];
- if (power_raw != wdata->power_raw) {
- wdata->power_raw = power_raw;
- wdata->battery_capacity = batcap_i4[power_raw & 0x07];
- wdata->bat_charging = (power_raw & 0x08) ? 1 : 0;
- wdata->ps_connected = (power_raw & 0x10) ? 1 : 0;
- }
-
- break;
- default:
- hid_err(hdev, "Unknown report: %d,%d size:%d\n",
- data[0], data[1], size);
- return 0;
- }
- }
- return 1;
-}
-
-static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- struct hid_field *field, struct hid_usage *usage, unsigned long **bit,
- int *max)
-{
- struct input_dev *input = hi->input;
-
- __set_bit(INPUT_PROP_POINTER, input->propbit);
-
- /* Basics */
- input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
-
- __set_bit(REL_WHEEL, input->relbit);
-
- __set_bit(BTN_TOOL_PEN, input->keybit);
- __set_bit(BTN_TOUCH, input->keybit);
- __set_bit(BTN_STYLUS, input->keybit);
- __set_bit(BTN_STYLUS2, input->keybit);
- __set_bit(BTN_LEFT, input->keybit);
- __set_bit(BTN_RIGHT, input->keybit);
- __set_bit(BTN_MIDDLE, input->keybit);
-
- /* Pad */
- input_set_capability(input, EV_MSC, MSC_SERIAL);
-
- __set_bit(BTN_0, input->keybit);
- __set_bit(BTN_1, input->keybit);
- __set_bit(BTN_TOOL_FINGER, input->keybit);
-
- /* Distance, rubber and mouse */
- __set_bit(BTN_TOOL_RUBBER, input->keybit);
- __set_bit(BTN_TOOL_MOUSE, input->keybit);
-
- switch (hdev->product) {
- case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH:
- input_set_abs_params(input, ABS_X, 0, 16704, 4, 0);
- input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0);
- input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0);
- break;
- case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH:
- __set_bit(ABS_WHEEL, input->absbit);
- __set_bit(ABS_MISC, input->absbit);
- __set_bit(BTN_2, input->keybit);
- __set_bit(BTN_3, input->keybit);
- __set_bit(BTN_4, input->keybit);
- __set_bit(BTN_5, input->keybit);
- __set_bit(BTN_6, input->keybit);
- __set_bit(BTN_7, input->keybit);
- __set_bit(BTN_8, input->keybit);
- input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0);
- input_set_abs_params(input, ABS_X, 0, 40640, 4, 0);
- input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0);
- input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0);
- input_set_abs_params(input, ABS_TILT_X, 0, 127, 0, 0);
- input_set_abs_params(input, ABS_TILT_Y, 0, 127, 0, 0);
- break;
- }
-
- return 0;
-}
-
-static int wacom_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
-{
- struct wacom_data *wdata;
- int ret;
-
- wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
- if (wdata == NULL) {
- hid_err(hdev, "can't alloc wacom descriptor\n");
- return -ENOMEM;
- }
-
- hid_set_drvdata(hdev, wdata);
-
- /* Parse the HID report now */
- ret = hid_parse(hdev);
- if (ret) {
- hid_err(hdev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- hid_err(hdev, "hw start failed\n");
- goto err_free;
- }
-
- ret = device_create_file(&hdev->dev, &dev_attr_speed);
- if (ret)
- hid_warn(hdev,
- "can't create sysfs speed attribute err: %d\n", ret);
-
-#define OLED_INIT(OLED_ID) \
- do { \
- ret = device_create_file(&hdev->dev, \
- &dev_attr_oled##OLED_ID##_img); \
- if (ret) \
- hid_warn(hdev, \
- "can't create sysfs oled attribute, err: %d\n", ret);\
- } while (0)
-
-OLED_INIT(0);
-OLED_INIT(1);
-OLED_INIT(2);
-OLED_INIT(3);
-OLED_INIT(4);
-OLED_INIT(5);
-OLED_INIT(6);
-OLED_INIT(7);
-
- wdata->features = 0;
- wacom_set_features(hdev, 1);
-
- if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
- sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
- ret = wacom_initialize_leds(hdev);
- if (ret)
- hid_warn(hdev,
- "can't create led attribute, err: %d\n", ret);
- }
-
- wdata->battery.properties = wacom_battery_props;
- wdata->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
- wdata->battery.get_property = wacom_battery_get_property;
- wdata->battery.name = "wacom_battery";
- wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
- wdata->battery.use_for_apm = 0;
-
-
- ret = power_supply_register(&hdev->dev, &wdata->battery);
- if (ret) {
- hid_err(hdev, "can't create sysfs battery attribute, err: %d\n",
- ret);
- goto err_battery;
- }
-
- power_supply_powers(&wdata->battery, &hdev->dev);
-
- wdata->ac.properties = wacom_ac_props;
- wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
- wdata->ac.get_property = wacom_ac_get_property;
- wdata->ac.name = "wacom_ac";
- wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
- wdata->ac.use_for_apm = 0;
-
- ret = power_supply_register(&hdev->dev, &wdata->ac);
- if (ret) {
- hid_err(hdev,
- "can't create ac battery attribute, err: %d\n", ret);
- goto err_ac;
- }
-
- power_supply_powers(&wdata->ac, &hdev->dev);
- return 0;
-
-err_ac:
- power_supply_unregister(&wdata->battery);
-err_battery:
- wacom_destroy_leds(hdev);
- device_remove_file(&hdev->dev, &dev_attr_oled0_img);
- device_remove_file(&hdev->dev, &dev_attr_oled1_img);
- device_remove_file(&hdev->dev, &dev_attr_oled2_img);
- device_remove_file(&hdev->dev, &dev_attr_oled3_img);
- device_remove_file(&hdev->dev, &dev_attr_oled4_img);
- device_remove_file(&hdev->dev, &dev_attr_oled5_img);
- device_remove_file(&hdev->dev, &dev_attr_oled6_img);
- device_remove_file(&hdev->dev, &dev_attr_oled7_img);
- device_remove_file(&hdev->dev, &dev_attr_speed);
- hid_hw_stop(hdev);
-err_free:
- kfree(wdata);
- return ret;
-}
-
-static void wacom_remove(struct hid_device *hdev)
-{
- struct wacom_data *wdata = hid_get_drvdata(hdev);
-
- wacom_destroy_leds(hdev);
- device_remove_file(&hdev->dev, &dev_attr_oled0_img);
- device_remove_file(&hdev->dev, &dev_attr_oled1_img);
- device_remove_file(&hdev->dev, &dev_attr_oled2_img);
- device_remove_file(&hdev->dev, &dev_attr_oled3_img);
- device_remove_file(&hdev->dev, &dev_attr_oled4_img);
- device_remove_file(&hdev->dev, &dev_attr_oled5_img);
- device_remove_file(&hdev->dev, &dev_attr_oled6_img);
- device_remove_file(&hdev->dev, &dev_attr_oled7_img);
- device_remove_file(&hdev->dev, &dev_attr_speed);
- hid_hw_stop(hdev);
-
- power_supply_unregister(&wdata->battery);
- power_supply_unregister(&wdata->ac);
- kfree(hid_get_drvdata(hdev));
-}
-
-static const struct hid_device_id wacom_devices[] = {
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) },
-
- { }
-};
-MODULE_DEVICE_TABLE(hid, wacom_devices);
-
-static struct hid_driver wacom_driver = {
- .name = "wacom",
- .id_table = wacom_devices,
- .probe = wacom_probe,
- .remove = wacom_remove,
- .raw_event = wacom_raw_event,
- .input_mapped = wacom_input_mapped,
-};
-module_hid_driver(wacom_driver);
-
-MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 21aafc8f48c8..747d54421e73 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1054,21 +1054,29 @@ static int i2c_hid_remove(struct i2c_client *client)
static int i2c_hid_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ struct hid_device *hid = ihid->hid;
+ int ret = 0;
disable_irq(client->irq);
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
+ if (hid->driver && hid->driver->suspend)
+ ret = hid->driver->suspend(hid, PMSG_SUSPEND);
+
/* Save some power */
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
- return 0;
+ return ret;
}
static int i2c_hid_resume(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
+ struct hid_device *hid = ihid->hid;
enable_irq(client->irq);
ret = i2c_hid_hwreset(client);
@@ -1078,6 +1086,11 @@ static int i2c_hid_resume(struct device *dev)
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
+ if (hid->driver && hid->driver->reset_resume) {
+ ret = hid->driver->reset_resume(hid);
+ return ret;
+ }
+
return 0;
}
#endif
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 7b88f4cb9902..79cf503e37bf 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -58,7 +58,7 @@ module_param_named(ignoreled, ignoreled, uint, 0644);
MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds");
/* Quirks specified at module load time */
-static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+static char *quirks_param[MAX_USBHID_BOOT_QUIRKS];
module_param_array_named(quirks, quirks_param, charp, NULL, 0444);
MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
@@ -536,7 +536,8 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
int head;
struct usbhid_device *usbhid = hid->driver_data;
- if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+ if (((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) ||
+ test_bit(HID_DISCONNECTED, &usbhid->iofl))
return;
if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
@@ -1366,6 +1367,9 @@ static void usbhid_disconnect(struct usb_interface *intf)
return;
usbhid = hid->driver_data;
+ spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
+ set_bit(HID_DISCONNECTED, &usbhid->iofl);
+ spin_unlock_irq(&usbhid->lock);
hid_destroy_device(hid);
kfree(usbhid);
}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 31e6727cd009..15225f3eaed1 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -74,7 +74,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
- { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET },
@@ -124,6 +124,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_INPUT_REPORTS },
{ 0, 0 }
};
diff --git a/drivers/input/tablet/wacom.h b/drivers/hid/wacom.h
index 9ebf0ed3b3b3..64bc1b296d91 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/hid/wacom.h
@@ -12,6 +12,7 @@
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
* Copyright (c) 2002-2011 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@redhat.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -72,6 +73,8 @@
* v1.52 (pc) - Query Wacom data upon system resume
* - add defines for features->type
* - add new devices (0x9F, 0xE2, and 0XE3)
+ * v2.00 (bt) - conversion to a HID driver
+ * - integration of the Bluetooth devices
*/
/*
@@ -93,35 +96,30 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.53"
+#define DRIVER_VERSION "v2.00"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom tablet driver"
#define DRIVER_LICENSE "GPL"
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
#define USB_VENDOR_ID_WACOM 0x056a
#define USB_VENDOR_ID_LENOVO 0x17ef
struct wacom {
- dma_addr_t data_dma;
struct usb_device *usbdev;
struct usb_interface *intf;
- struct urb *irq;
struct wacom_wac wacom_wac;
+ struct hid_device *hdev;
struct mutex lock;
struct work_struct work;
- bool open;
- char phys[32];
struct wacom_led {
u8 select[2]; /* status led selector (0..3) */
u8 llv; /* status led brightness no button (1..127) */
u8 hlv; /* status led brightness button pressed (1..127) */
u8 img_lum; /* OLED matrix display brightness */
} led;
+ bool led_initialized;
struct power_supply battery;
+ struct power_supply ac;
};
static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
@@ -130,10 +128,19 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
schedule_work(&wacom->work);
}
-extern const struct usb_device_id wacom_ids[];
+static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
+{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+
+ power_supply_changed(&wacom->battery);
+}
+
+extern const struct hid_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features);
int wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac);
+int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
+ struct wacom_wac *wacom_wac);
#endif
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/hid/wacom_sys.c
index 2c613cd41dd6..f0db7eca9023 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -13,246 +13,106 @@
#include "wacom_wac.h"
#include "wacom.h"
+#include <linux/hid.h>
-/* defines to get HID report descriptor */
-#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
-#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
-#define HID_USAGE_UNDEFINED 0x00
-#define HID_USAGE_PAGE 0x05
-#define HID_USAGE_PAGE_DIGITIZER 0x0d
-#define HID_USAGE_PAGE_DESKTOP 0x01
-#define HID_USAGE 0x09
-#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
-#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
-#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
-#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
-#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
-#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
-#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
-#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
-#define HID_COLLECTION 0xa1
-#define HID_COLLECTION_LOGICAL 0x02
-#define HID_COLLECTION_END 0xc0
-
-struct hid_descriptor {
- struct usb_descriptor_header header;
- __le16 bcdHID;
- u8 bCountryCode;
- u8 bNumDescriptors;
- u8 bDescriptorType;
- __le16 wDescriptorLength;
-} __attribute__ ((packed));
-
-/* defines to get/set USB message */
-#define USB_REQ_GET_REPORT 0x01
-#define USB_REQ_SET_REPORT 0x09
-
-#define WAC_HID_FEATURE_REPORT 0x03
#define WAC_MSG_RETRIES 5
#define WAC_CMD_LED_CONTROL 0x20
#define WAC_CMD_ICON_START 0x21
#define WAC_CMD_ICON_XFER 0x23
+#define WAC_CMD_ICON_BT_XFER 0x26
#define WAC_CMD_RETRIES 10
-static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
void *buf, size_t size, unsigned int retries)
{
- struct usb_device *dev = interface_to_usbdev(intf);
int retval;
do {
- retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_REPORT,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- (type << 8) + id,
- intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 100);
+ retval = hid_hw_raw_request(hdev, id, buf, size, type,
+ HID_REQ_GET_REPORT);
} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
return retval;
}
-static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
- void *buf, size_t size, unsigned int retries)
+static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf,
+ size_t size, unsigned int retries)
{
- struct usb_device *dev = interface_to_usbdev(intf);
int retval;
do {
- retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id,
- intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 1000);
+ retval = hid_hw_raw_request(hdev, buf[0], buf, size, type,
+ HID_REQ_SET_REPORT);
} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
return retval;
}
-static void wacom_sys_irq(struct urb *urb)
+static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
{
- struct wacom *wacom = urb->context;
- struct device *dev = &wacom->intf->dev;
- int retval;
+ struct wacom *wacom = hid_get_drvdata(hdev);
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(dev, "%s - urb shutting down with status: %d\n",
- __func__, urb->status);
- return;
- default:
- dev_dbg(dev, "%s - nonzero urb status received: %d\n",
- __func__, urb->status);
- goto exit;
- }
+ if (size > WACOM_PKGLEN_MAX)
+ return 1;
+
+ memcpy(wacom->wacom_wac.data, raw_data, size);
- wacom_wac_irq(&wacom->wacom_wac, urb->actual_length);
+ wacom_wac_irq(&wacom->wacom_wac, size);
- exit:
- usb_mark_last_busy(wacom->usbdev);
- retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (retval)
- dev_err(dev, "%s - usb_submit_urb failed with result %d\n",
- __func__, retval);
+ return 0;
}
static int wacom_open(struct input_dev *dev)
{
struct wacom *wacom = input_get_drvdata(dev);
- int retval = 0;
-
- if (usb_autopm_get_interface(wacom->intf) < 0)
- return -EIO;
+ int retval;
mutex_lock(&wacom->lock);
-
- if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
- retval = -EIO;
- goto out;
- }
-
- wacom->open = true;
- wacom->intf->needs_remote_wakeup = 1;
-
-out:
+ retval = hid_hw_open(wacom->hdev);
mutex_unlock(&wacom->lock);
- usb_autopm_put_interface(wacom->intf);
+
return retval;
}
static void wacom_close(struct input_dev *dev)
{
struct wacom *wacom = input_get_drvdata(dev);
- int autopm_error;
-
- autopm_error = usb_autopm_get_interface(wacom->intf);
mutex_lock(&wacom->lock);
- usb_kill_urb(wacom->irq);
- wacom->open = false;
- wacom->intf->needs_remote_wakeup = 0;
+ hid_hw_close(wacom->hdev);
mutex_unlock(&wacom->lock);
-
- if (!autopm_error)
- usb_autopm_put_interface(wacom->intf);
}
/*
- * Calculate the resolution of the X or Y axis, given appropriate HID data.
- * This function is little more than hidinput_calc_abs_res stripped down.
+ * Calculate the resolution of the X or Y axis using hidinput_calc_abs_res.
*/
static int wacom_calc_hid_res(int logical_extents, int physical_extents,
- unsigned char unit, unsigned char exponent)
-{
- int prev, unit_exponent;
-
- /* Check if the extents are sane */
- if (logical_extents <= 0 || physical_extents <= 0)
- return 0;
-
- /* Get signed value of nybble-sized twos-compliment exponent */
- unit_exponent = exponent;
- if (unit_exponent > 7)
- unit_exponent -= 16;
-
- /* Convert physical_extents to millimeters */
- if (unit == 0x11) { /* If centimeters */
- unit_exponent += 1;
- } else if (unit == 0x13) { /* If inches */
- prev = physical_extents;
- physical_extents *= 254;
- if (physical_extents < prev)
- return 0;
- unit_exponent -= 1;
- } else {
- return 0;
- }
-
- /* Apply negative unit exponent */
- for (; unit_exponent < 0; unit_exponent++) {
- prev = logical_extents;
- logical_extents *= 10;
- if (logical_extents < prev)
- return 0;
- }
- /* Apply positive unit exponent */
- for (; unit_exponent > 0; unit_exponent--) {
- prev = physical_extents;
- physical_extents *= 10;
- if (physical_extents < prev)
- return 0;
- }
-
- /* Calculate resolution */
- return logical_extents / physical_extents;
-}
-
-static int wacom_parse_logical_collection(unsigned char *report,
- struct wacom_features *features)
+ unsigned unit, int exponent)
{
- int length = 0;
-
- if (features->type == BAMBOO_PT) {
-
- /* Logical collection is only used by 3rd gen Bamboo Touch */
- features->pktlen = WACOM_PKGLEN_BBTOUCH3;
- features->device_type = BTN_TOOL_FINGER;
-
- features->x_max = features->y_max =
- get_unaligned_le16(&report[10]);
-
- length = 11;
- }
- return length;
+ struct hid_field field = {
+ .logical_maximum = logical_extents,
+ .physical_maximum = physical_extents,
+ .unit = unit,
+ .unit_exponent = exponent,
+ };
+
+ return hidinput_calc_abs_res(&field, ABS_X);
}
-static void wacom_retrieve_report_data(struct usb_interface *intf,
- struct wacom_features *features)
+static void wacom_feature_mapping(struct hid_device *hdev,
+ struct hid_field *field, struct hid_usage *usage)
{
- int result = 0;
- unsigned char *rep_data;
-
- rep_data = kmalloc(2, GFP_KERNEL);
- if (rep_data) {
-
- rep_data[0] = 12;
- result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
- rep_data[0], rep_data, 2,
- WAC_MSG_RETRIES);
-
- if (result >= 0 && rep_data[1] > 2)
- features->touch_max = rep_data[1];
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
- kfree(rep_data);
+ switch (usage->hid) {
+ case HID_DG_CONTACTMAX:
+ /* leave touch_max as is if predefined */
+ if (!features->touch_max)
+ features->touch_max = field->value[0];
+ break;
}
}
@@ -285,243 +145,100 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
* interfaces haven't supported pressure or distance, this is enough
* information to override invalid values in the wacom_features table.
*
- * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
- * Collection. Instead they define a Logical Collection with a single
- * Logical Maximum for both X and Y.
- *
- * Intuos5 touch interface does not contain useful data. We deal with
- * this after returning from this function.
+ * Intuos5 touch interface and 3rd gen Bamboo Touch do not contain useful
+ * data. We deal with them after returning from this function.
*/
-static int wacom_parse_hid(struct usb_interface *intf,
- struct hid_descriptor *hid_desc,
- struct wacom_features *features)
+static void wacom_usage_mapping(struct hid_device *hdev,
+ struct hid_field *field, struct hid_usage *usage)
{
- struct usb_device *dev = interface_to_usbdev(intf);
- char limit = 0;
- /* result has to be defined as int for some devices */
- int result = 0, touch_max = 0;
- int i = 0, page = 0, finger = 0, pen = 0;
- unsigned char *report;
-
- report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
- if (!report)
- return -ENOMEM;
-
- /* retrive report descriptors */
- do {
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_DIR_IN,
- HID_DEVICET_REPORT << 8,
- intf->altsetting[0].desc.bInterfaceNumber, /* interface */
- report,
- hid_desc->wDescriptorLength,
- 5000); /* 5 secs */
- } while (result < 0 && limit++ < WAC_MSG_RETRIES);
-
- /* No need to parse the Descriptor. It isn't an error though */
- if (result < 0)
- goto out;
-
- for (i = 0; i < hid_desc->wDescriptorLength; i++) {
-
- switch (report[i]) {
- case HID_USAGE_PAGE:
- page = report[i + 1];
- i++;
- break;
-
- case HID_USAGE:
- switch (page << 16 | report[i + 1]) {
- case HID_USAGE_X:
- if (finger) {
- features->device_type = BTN_TOOL_FINGER;
- /* touch device at least supports one touch point */
- touch_max = 1;
- switch (features->type) {
- case TABLETPC2FG:
- features->pktlen = WACOM_PKGLEN_TPC2FG;
- break;
-
- case MTSCREEN:
- case WACOM_24HDT:
- features->pktlen = WACOM_PKGLEN_MTOUCH;
- break;
-
- case MTTPC:
- case MTTPC_B:
- features->pktlen = WACOM_PKGLEN_MTTPC;
- break;
-
- case BAMBOO_PT:
- features->pktlen = WACOM_PKGLEN_BBTOUCH;
- break;
-
- default:
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
- break;
- }
-
- switch (features->type) {
- case BAMBOO_PT:
- features->x_phy =
- get_unaligned_le16(&report[i + 5]);
- features->x_max =
- get_unaligned_le16(&report[i + 8]);
- i += 15;
- break;
-
- case WACOM_24HDT:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 8]);
- features->unit = report[i - 1];
- features->unitExpo = report[i - 3];
- i += 12;
- break;
-
- case MTTPC_B:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 6]);
- features->unit = report[i - 5];
- features->unitExpo = report[i - 3];
- i += 9;
- break;
-
- default:
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- features->x_phy =
- get_unaligned_le16(&report[i + 6]);
- features->unit = report[i + 9];
- features->unitExpo = report[i + 11];
- i += 12;
- break;
- }
- } else if (pen) {
- /* penabled only accepts exact bytes of data */
- if (features->type >= TABLETPC)
- features->pktlen = WACOM_PKGLEN_GRAPHIRE;
- features->device_type = BTN_TOOL_PEN;
- features->x_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
-
- case HID_USAGE_Y:
- if (finger) {
- switch (features->type) {
- case TABLETPC2FG:
- case MTSCREEN:
- case MTTPC:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i + 6]);
- i += 7;
- break;
-
- case WACOM_24HDT:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i - 2]);
- i += 7;
- break;
-
- case BAMBOO_PT:
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- features->y_max =
- get_unaligned_le16(&report[i + 6]);
- i += 12;
- break;
-
- case MTTPC_B:
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- features->y_phy =
- get_unaligned_le16(&report[i + 6]);
- i += 9;
- break;
-
- default:
- features->y_max =
- features->x_max;
- features->y_phy =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- break;
- }
- } else if (pen) {
- features->y_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
-
- case HID_USAGE_FINGER:
- finger = 1;
- i++;
- break;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ bool finger = (field->logical == HID_DG_FINGER) ||
+ (field->physical == HID_DG_FINGER);
+ bool pen = (field->logical == HID_DG_STYLUS) ||
+ (field->physical == HID_DG_STYLUS);
- /*
- * Requiring Stylus Usage will ignore boot mouse
- * X/Y values and some cases of invalid Digitizer X/Y
- * values commonly reported.
- */
- case HID_USAGE_STYLUS:
- pen = 1;
- i++;
- break;
+ /*
+ * Requiring Stylus Usage will ignore boot mouse
+ * X/Y values and some cases of invalid Digitizer X/Y
+ * values commonly reported.
+ */
+ if (!pen && !finger)
+ return;
- case HID_USAGE_CONTACTMAX:
- /* leave touch_max as is if predefined */
- if (!features->touch_max)
- wacom_retrieve_report_data(intf, features);
- i++;
- break;
+ if (finger && !features->touch_max)
+ /* touch device at least supports one touch point */
+ features->touch_max = 1;
- case HID_USAGE_PRESSURE:
- if (pen) {
- features->pressure_max =
- get_unaligned_le16(&report[i + 3]);
- i += 4;
- }
- break;
+ switch (usage->hid) {
+ case HID_GD_X:
+ features->x_max = field->logical_maximum;
+ if (finger) {
+ features->device_type = BTN_TOOL_FINGER;
+ features->x_phy = field->physical_maximum;
+ if (features->type != BAMBOO_PT) {
+ features->unit = field->unit;
+ features->unitExpo = field->unit_exponent;
}
- break;
-
- case HID_COLLECTION_END:
- /* reset UsagePage and Finger */
- finger = page = 0;
- break;
+ } else {
+ features->device_type = BTN_TOOL_PEN;
+ }
+ break;
+ case HID_GD_Y:
+ features->y_max = field->logical_maximum;
+ if (finger) {
+ features->y_phy = field->physical_maximum;
+ if (features->type != BAMBOO_PT) {
+ features->unit = field->unit;
+ features->unitExpo = field->unit_exponent;
+ }
+ }
+ break;
+ case HID_DG_TIPPRESSURE:
+ if (pen)
+ features->pressure_max = field->logical_maximum;
+ break;
+ }
+}
- case HID_COLLECTION:
- i++;
- switch (report[i]) {
- case HID_COLLECTION_LOGICAL:
- i += wacom_parse_logical_collection(&report[i],
- features);
- break;
+static void wacom_parse_hid(struct hid_device *hdev,
+ struct wacom_features *features)
+{
+ struct hid_report_enum *rep_enum;
+ struct hid_report *hreport;
+ int i, j;
+
+ /* check features first */
+ rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+ list_for_each_entry(hreport, &rep_enum->report_list, list) {
+ for (i = 0; i < hreport->maxfield; i++) {
+ /* Ignore if report count is out of bounds. */
+ if (hreport->field[i]->report_count < 1)
+ continue;
+
+ for (j = 0; j < hreport->field[i]->maxusage; j++) {
+ wacom_feature_mapping(hdev, hreport->field[i],
+ hreport->field[i]->usage + j);
}
- break;
}
}
- out:
- if (!features->touch_max && touch_max)
- features->touch_max = touch_max;
- result = 0;
- kfree(report);
- return result;
+ /* now check the input usages */
+ rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+ list_for_each_entry(hreport, &rep_enum->report_list, list) {
+
+ if (!hreport->maxfield)
+ continue;
+
+ for (i = 0; i < hreport->maxfield; i++)
+ for (j = 0; j < hreport->field[i]->maxusage; j++)
+ wacom_usage_mapping(hdev, hreport->field[i],
+ hreport->field[i]->usage + j);
+ }
}
-static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
+static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
+ int length, int mode)
{
unsigned char *rep_data;
int error = -ENOMEM, limit = 0;
@@ -534,8 +251,11 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
rep_data[0] = report_id;
rep_data[1] = mode;
- error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, length, 1);
+ error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data,
+ length, 1);
+ if (error >= 0)
+ error = wacom_get_report(hdev, HID_FEATURE_REPORT,
+ report_id, rep_data, length, 1);
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
kfree(rep_data);
@@ -543,6 +263,59 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
return error < 0 ? error : 0;
}
+static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed,
+ struct wacom_features *features)
+{
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ int ret;
+ u8 rep_data[2];
+
+ switch (features->type) {
+ case GRAPHIRE_BT:
+ rep_data[0] = 0x03;
+ rep_data[1] = 0x00;
+ ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+ 3);
+
+ if (ret >= 0) {
+ rep_data[0] = speed == 0 ? 0x05 : 0x06;
+ rep_data[1] = 0x00;
+
+ ret = wacom_set_report(hdev, HID_FEATURE_REPORT,
+ rep_data, 2, 3);
+
+ if (ret >= 0) {
+ wacom->wacom_wac.bt_high_speed = speed;
+ return 0;
+ }
+ }
+
+ /*
+ * Note that if the raw queries fail, it's not a hard failure
+ * and it is safe to continue
+ */
+ hid_warn(hdev, "failed to poke device, command %d, err %d\n",
+ rep_data[0], ret);
+ break;
+ case INTUOS4WL:
+ if (speed == 1)
+ wacom->wacom_wac.bt_features &= ~0x20;
+ else
+ wacom->wacom_wac.bt_features |= 0x20;
+
+ rep_data[0] = 0x03;
+ rep_data[1] = wacom->wacom_wac.bt_features;
+
+ ret = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, 2,
+ 1);
+ if (ret >= 0)
+ wacom->wacom_wac.bt_high_speed = speed;
+ break;
+ }
+
+ return 0;
+}
+
/*
* Switch the tablet into its most-capable mode. Wacom tablets are
* typically configured to power-up in a mode which sends mouse-like
@@ -550,31 +323,34 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
* from the tablet, it is necessary to switch the tablet out of this
* mode and into one which sends the full range of tablet data.
*/
-static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+static int wacom_query_tablet_data(struct hid_device *hdev,
+ struct wacom_features *features)
{
+ if (hdev->bus == BUS_BLUETOOTH)
+ return wacom_bt_query_tablet_data(hdev, 1, features);
+
if (features->device_type == BTN_TOOL_FINGER) {
if (features->type > TABLETPC) {
/* MT Tablet PC touch */
- return wacom_set_device_mode(intf, 3, 4, 4);
+ return wacom_set_device_mode(hdev, 3, 4, 4);
}
else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
- return wacom_set_device_mode(intf, 18, 3, 2);
+ return wacom_set_device_mode(hdev, 18, 3, 2);
}
} else if (features->device_type == BTN_TOOL_PEN) {
if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
- return wacom_set_device_mode(intf, 2, 2, 2);
+ return wacom_set_device_mode(hdev, 2, 2, 2);
}
}
return 0;
}
-static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
+static void wacom_retrieve_hid_descriptor(struct hid_device *hdev,
struct wacom_features *features)
{
- int error = 0;
- struct usb_host_interface *interface = intf->cur_altsetting;
- struct hid_descriptor *hid_desc;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct usb_interface *intf = wacom->intf;
/* default features */
features->device_type = BTN_TOOL_PEN;
@@ -599,66 +375,54 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
}
/* only devices that support touch need to retrieve the info */
- if (features->type < BAMBOO_PT) {
- goto out;
- }
-
- error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
- if (error) {
- error = usb_get_extra_descriptor(&interface->endpoint[0],
- HID_DEVICET_REPORT, &hid_desc);
- if (error) {
- dev_err(&intf->dev,
- "can not retrieve extra class descriptor\n");
- goto out;
- }
- }
- error = wacom_parse_hid(intf, hid_desc, features);
+ if (features->type < BAMBOO_PT)
+ return;
- out:
- return error;
+ wacom_parse_hid(hdev, features);
}
-struct wacom_usbdev_data {
+struct wacom_hdev_data {
struct list_head list;
struct kref kref;
- struct usb_device *dev;
+ struct hid_device *dev;
struct wacom_shared shared;
};
static LIST_HEAD(wacom_udev_list);
static DEFINE_MUTEX(wacom_udev_list_lock);
-static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+static bool wacom_are_sibling(struct hid_device *hdev,
+ struct hid_device *sibling)
{
- int port1;
- struct usb_device *sibling;
-
- if (vendor == 0 && product == 0)
- return dev;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ int vid = features->oVid;
+ int pid = features->oPid;
+ int n1,n2;
- if (dev->parent == NULL)
- return NULL;
+ if (vid == 0 && pid == 0) {
+ vid = hdev->vendor;
+ pid = hdev->product;
+ }
- usb_hub_for_each_child(dev->parent, port1, sibling) {
- struct usb_device_descriptor *d;
- if (sibling == NULL)
- continue;
+ if (vid != sibling->vendor || pid != sibling->product)
+ return false;
- d = &sibling->descriptor;
- if (d->idVendor == vendor && d->idProduct == product)
- return sibling;
- }
+ /* Compare the physical path. */
+ n1 = strrchr(hdev->phys, '.') - hdev->phys;
+ n2 = strrchr(sibling->phys, '.') - sibling->phys;
+ if (n1 != n2 || n1 <= 0 || n2 <= 0)
+ return false;
- return NULL;
+ return !strncmp(hdev->phys, sibling->phys, n1);
}
-static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
+static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
list_for_each_entry(data, &wacom_udev_list, list) {
- if (data->dev == dev) {
+ if (wacom_are_sibling(hdev, data->dev)) {
kref_get(&data->kref);
return data;
}
@@ -667,28 +431,29 @@ static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
return NULL;
}
-static int wacom_add_shared_data(struct wacom_wac *wacom,
- struct usb_device *dev)
+static int wacom_add_shared_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct wacom_hdev_data *data;
int retval = 0;
mutex_lock(&wacom_udev_list_lock);
- data = wacom_get_usbdev_data(dev);
+ data = wacom_get_hdev_data(hdev);
if (!data) {
- data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
if (!data) {
retval = -ENOMEM;
goto out;
}
kref_init(&data->kref);
- data->dev = dev;
+ data->dev = hdev;
list_add_tail(&data->list, &wacom_udev_list);
}
- wacom->shared = &data->shared;
+ wacom_wac->shared = &data->shared;
out:
mutex_unlock(&wacom_udev_list_lock);
@@ -697,8 +462,8 @@ out:
static void wacom_release_shared_data(struct kref *kref)
{
- struct wacom_usbdev_data *data =
- container_of(kref, struct wacom_usbdev_data, kref);
+ struct wacom_hdev_data *data =
+ container_of(kref, struct wacom_hdev_data, kref);
mutex_lock(&wacom_udev_list_lock);
list_del(&data->list);
@@ -709,10 +474,10 @@ static void wacom_release_shared_data(struct kref *kref)
static void wacom_remove_shared_data(struct wacom_wac *wacom)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
if (wacom->shared) {
- data = container_of(wacom->shared, struct wacom_usbdev_data, shared);
+ data = container_of(wacom->shared, struct wacom_hdev_data, shared);
kref_put(&data->kref, wacom_release_shared_data);
wacom->shared = NULL;
}
@@ -755,38 +520,40 @@ static int wacom_led_control(struct wacom *wacom)
buf[4] = wacom->led.img_lum;
}
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
- buf, 9, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9,
+ WAC_CMD_RETRIES);
kfree(buf);
return retval;
}
-static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *img)
+static int wacom_led_putimage(struct wacom *wacom, int button_id, u8 xfer_id,
+ const unsigned len, const void *img)
{
unsigned char *buf;
int i, retval;
+ const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
- buf = kzalloc(259, GFP_KERNEL);
+ buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
if (!buf)
return -ENOMEM;
/* Send 'start' command */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 1;
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
- buf, 2, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+ WAC_CMD_RETRIES);
if (retval < 0)
goto out;
- buf[0] = WAC_CMD_ICON_XFER;
+ buf[0] = xfer_id;
buf[1] = button_id & 0x07;
for (i = 0; i < 4; i++) {
buf[2] = i;
- memcpy(buf + 3, img + i * 256, 256);
+ memcpy(buf + 3, img + i * chunk_len, chunk_len);
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
- buf, 259, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
+ buf, chunk_len + 3, WAC_CMD_RETRIES);
if (retval < 0)
break;
}
@@ -794,8 +561,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
/* Send 'stop' */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 0;
- wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
- buf, 2, WAC_CMD_RETRIES);
+ wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 2,
+ WAC_CMD_RETRIES);
out:
kfree(buf);
@@ -805,7 +572,8 @@ out:
static ssize_t wacom_led_select_store(struct device *dev, int set_id,
const char *buf, size_t count)
{
- struct wacom *wacom = dev_get_drvdata(dev);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
unsigned int id;
int err;
@@ -832,7 +600,8 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
- struct wacom *wacom = dev_get_drvdata(dev); \
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+ struct wacom *wacom = hid_get_drvdata(hdev); \
return snprintf(buf, 2, "%d\n", wacom->led.select[SET_ID]); \
} \
static DEVICE_ATTR(status_led##SET_ID##_select, S_IWUSR | S_IRUSR, \
@@ -866,7 +635,8 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
static ssize_t wacom_##name##_luminance_store(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
- struct wacom *wacom = dev_get_drvdata(dev); \
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+ struct wacom *wacom = hid_get_drvdata(hdev); \
\
return wacom_luminance_store(wacom, &wacom->led.field, \
buf, count); \
@@ -881,15 +651,26 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum);
static ssize_t wacom_button_image_store(struct device *dev, int button_id,
const char *buf, size_t count)
{
- struct wacom *wacom = dev_get_drvdata(dev);
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
int err;
+ unsigned len;
+ u8 xfer_id;
+
+ if (hdev->bus == BUS_BLUETOOTH) {
+ len = 256;
+ xfer_id = WAC_CMD_ICON_BT_XFER;
+ } else {
+ len = 1024;
+ xfer_id = WAC_CMD_ICON_XFER;
+ }
- if (count != 1024)
+ if (count != len)
return -EINVAL;
mutex_lock(&wacom->lock);
- err = wacom_led_putimage(wacom, button_id, buf);
+ err = wacom_led_putimage(wacom, button_id, xfer_id, len, buf);
mutex_unlock(&wacom->lock);
@@ -965,13 +746,14 @@ static int wacom_initialize_leds(struct wacom *wacom)
switch (wacom->wacom_wac.features.type) {
case INTUOS4S:
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
wacom->led.select[0] = 0;
wacom->led.select[1] = 0;
wacom->led.llv = 10;
wacom->led.hlv = 20;
wacom->led.img_lum = 10;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&intuos4_led_attr_group);
break;
@@ -983,7 +765,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
wacom->led.hlv = 0;
wacom->led.img_lum = 0;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&cintiq_led_attr_group);
break;
@@ -1000,7 +782,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
wacom->led.hlv = 0;
wacom->led.img_lum = 0;
- error = sysfs_create_group(&wacom->intf->dev.kobj,
+ error = sysfs_create_group(&wacom->hdev->dev.kobj,
&intuos5_led_attr_group);
} else
return 0;
@@ -1011,28 +793,35 @@ static int wacom_initialize_leds(struct wacom *wacom)
}
if (error) {
- dev_err(&wacom->intf->dev,
+ hid_err(wacom->hdev,
"cannot create sysfs group err: %d\n", error);
return error;
}
wacom_led_control(wacom);
+ wacom->led_initialized = true;
return 0;
}
static void wacom_destroy_leds(struct wacom *wacom)
{
+ if (!wacom->led_initialized)
+ return;
+
+ wacom->led_initialized = false;
+
switch (wacom->wacom_wac.features.type) {
case INTUOS4S:
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&intuos4_led_attr_group);
break;
case WACOM_24HD:
case WACOM_21UX2:
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&cintiq_led_attr_group);
break;
@@ -1043,17 +832,24 @@ static void wacom_destroy_leds(struct wacom *wacom)
case INTUOSPM:
case INTUOSPL:
if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN)
- sysfs_remove_group(&wacom->intf->dev.kobj,
+ sysfs_remove_group(&wacom->hdev->dev.kobj,
&intuos5_led_attr_group);
break;
}
}
static enum power_supply_property wacom_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_CAPACITY
};
+static enum power_supply_property wacom_ac_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_SCOPE,
+};
+
static int wacom_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -1067,7 +863,16 @@ static int wacom_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval =
- wacom->wacom_wac.battery_capacity * 100 / 31;
+ wacom->wacom_wac.battery_capacity;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (wacom->wacom_wac.bat_charging)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (wacom->wacom_wac.battery_capacity == 100 &&
+ wacom->wacom_wac.ps_connected)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
default:
ret = -EINVAL;
@@ -1077,74 +882,201 @@ static int wacom_battery_get_property(struct power_supply *psy,
return ret;
}
+static int wacom_ac_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wacom *wacom = container_of(psy, struct wacom, ac);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ /* fall through */
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = wacom->wacom_wac.ps_connected;
+ break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int wacom_initialize_battery(struct wacom *wacom)
{
- int error = 0;
+ static atomic_t battery_no = ATOMIC_INIT(0);
+ int error;
+ unsigned long n;
+
+ if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) {
+ n = atomic_inc_return(&battery_no) - 1;
- if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
wacom->battery.properties = wacom_battery_props;
wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
wacom->battery.get_property = wacom_battery_get_property;
- wacom->battery.name = "wacom_battery";
+ sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n);
+ wacom->battery.name = wacom->wacom_wac.bat_name;
wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wacom->battery.use_for_apm = 0;
- error = power_supply_register(&wacom->usbdev->dev,
+ wacom->ac.properties = wacom_ac_props;
+ wacom->ac.num_properties = ARRAY_SIZE(wacom_ac_props);
+ wacom->ac.get_property = wacom_ac_get_property;
+ sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n);
+ wacom->ac.name = wacom->wacom_wac.ac_name;
+ wacom->ac.type = POWER_SUPPLY_TYPE_MAINS;
+ wacom->ac.use_for_apm = 0;
+
+ error = power_supply_register(&wacom->hdev->dev,
&wacom->battery);
+ if (error)
+ return error;
+
+ power_supply_powers(&wacom->battery, &wacom->hdev->dev);
- if (!error)
- power_supply_powers(&wacom->battery,
- &wacom->usbdev->dev);
+ error = power_supply_register(&wacom->hdev->dev, &wacom->ac);
+ if (error) {
+ power_supply_unregister(&wacom->battery);
+ return error;
+ }
+
+ power_supply_powers(&wacom->ac, &wacom->hdev->dev);
}
- return error;
+ return 0;
}
static void wacom_destroy_battery(struct wacom *wacom)
{
- if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR &&
- wacom->battery.dev) {
+ if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
+ wacom->battery.dev) {
power_supply_unregister(&wacom->battery);
wacom->battery.dev = NULL;
+ power_supply_unregister(&wacom->ac);
+ wacom->ac.dev = NULL;
}
}
-static int wacom_register_input(struct wacom *wacom)
+static ssize_t wacom_show_speed(struct device *dev,
+ struct device_attribute
+ *attr, char *buf)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%i\n", wacom->wacom_wac.bt_high_speed);
+}
+
+static ssize_t wacom_store_speed(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ u8 new_speed;
+
+ if (kstrtou8(buf, 0, &new_speed))
+ return -EINVAL;
+
+ if (new_speed != 0 && new_speed != 1)
+ return -EINVAL;
+
+ wacom_bt_query_tablet_data(hdev, new_speed, &wacom->wacom_wac.features);
+
+ return count;
+}
+
+static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
+ wacom_show_speed, wacom_store_speed);
+
+static struct input_dev *wacom_allocate_input(struct wacom *wacom)
{
struct input_dev *input_dev;
- struct usb_interface *intf = wacom->intf;
- struct usb_device *dev = interface_to_usbdev(intf);
+ struct hid_device *hdev = wacom->hdev;
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
- int error;
input_dev = input_allocate_device();
- if (!input_dev) {
- error = -ENOMEM;
- goto fail1;
- }
+ if (!input_dev)
+ return NULL;
input_dev->name = wacom_wac->name;
- input_dev->dev.parent = &intf->dev;
+ input_dev->phys = hdev->phys;
+ input_dev->dev.parent = &hdev->dev;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
- usb_to_input_id(dev, &input_dev->id);
+ input_dev->uniq = hdev->uniq;
+ input_dev->id.bustype = hdev->bus;
+ input_dev->id.vendor = hdev->vendor;
+ input_dev->id.product = hdev->product;
+ input_dev->id.version = hdev->version;
input_set_drvdata(input_dev, wacom);
+ return input_dev;
+}
+
+static void wacom_unregister_inputs(struct wacom *wacom)
+{
+ if (wacom->wacom_wac.input)
+ input_unregister_device(wacom->wacom_wac.input);
+ if (wacom->wacom_wac.pad_input)
+ input_unregister_device(wacom->wacom_wac.pad_input);
+ wacom->wacom_wac.input = NULL;
+ wacom->wacom_wac.pad_input = NULL;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
+{
+ struct input_dev *input_dev, *pad_input_dev;
+ struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+ int error;
+
+ input_dev = wacom_allocate_input(wacom);
+ pad_input_dev = wacom_allocate_input(wacom);
+ if (!input_dev || !pad_input_dev) {
+ error = -ENOMEM;
+ goto fail1;
+ }
+
wacom_wac->input = input_dev;
+ wacom_wac->pad_input = pad_input_dev;
+ wacom_wac->pad_input->name = wacom_wac->pad_name;
+
error = wacom_setup_input_capabilities(input_dev, wacom_wac);
if (error)
- goto fail1;
+ goto fail2;
error = input_register_device(input_dev);
if (error)
goto fail2;
+ error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
+ if (error) {
+ /* no pad in use on this interface */
+ input_free_device(pad_input_dev);
+ wacom_wac->pad_input = NULL;
+ pad_input_dev = NULL;
+ } else {
+ error = input_register_device(pad_input_dev);
+ if (error)
+ goto fail3;
+ }
+
return 0;
+fail3:
+ input_unregister_device(input_dev);
+ input_dev = NULL;
fail2:
- input_free_device(input_dev);
wacom_wac->input = NULL;
+ wacom_wac->pad_input = NULL;
fail1:
+ if (input_dev)
+ input_free_device(input_dev);
+ if (pad_input_dev)
+ input_free_device(pad_input_dev);
return error;
}
@@ -1153,6 +1085,7 @@ static void wacom_wireless_work(struct work_struct *work)
struct wacom *wacom = container_of(work, struct wacom, work);
struct usb_device *usbdev = wacom->usbdev;
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct hid_device *hdev1, *hdev2;
struct wacom *wacom1, *wacom2;
struct wacom_wac *wacom_wac1, *wacom_wac2;
int error;
@@ -1165,50 +1098,49 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_destroy_battery(wacom);
/* Stylus interface */
- wacom1 = usb_get_intfdata(usbdev->config->interface[1]);
+ hdev1 = usb_get_intfdata(usbdev->config->interface[1]);
+ wacom1 = hid_get_drvdata(hdev1);
wacom_wac1 = &(wacom1->wacom_wac);
- if (wacom_wac1->input)
- input_unregister_device(wacom_wac1->input);
- wacom_wac1->input = NULL;
+ wacom_unregister_inputs(wacom1);
/* Touch interface */
- wacom2 = usb_get_intfdata(usbdev->config->interface[2]);
+ hdev2 = usb_get_intfdata(usbdev->config->interface[2]);
+ wacom2 = hid_get_drvdata(hdev2);
wacom_wac2 = &(wacom2->wacom_wac);
- if (wacom_wac2->input)
- input_unregister_device(wacom_wac2->input);
- wacom_wac2->input = NULL;
+ wacom_unregister_inputs(wacom2);
if (wacom_wac->pid == 0) {
- dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
+ hid_info(wacom->hdev, "wireless tablet disconnected\n");
+ wacom_wac1->shared->type = 0;
} else {
- const struct usb_device_id *id = wacom_ids;
+ const struct hid_device_id *id = wacom_ids;
- dev_info(&wacom->intf->dev,
- "wireless tablet connected with PID %x\n",
+ hid_info(wacom->hdev, "wireless tablet connected with PID %x\n",
wacom_wac->pid);
- while (id->match_flags) {
- if (id->idVendor == USB_VENDOR_ID_WACOM &&
- id->idProduct == wacom_wac->pid)
+ while (id->bus) {
+ if (id->vendor == USB_VENDOR_ID_WACOM &&
+ id->product == wacom_wac->pid)
break;
id++;
}
- if (!id->match_flags) {
- dev_info(&wacom->intf->dev,
- "ignoring unknown PID.\n");
+ if (!id->bus) {
+ hid_info(wacom->hdev, "ignoring unknown PID.\n");
return;
}
/* Stylus interface */
wacom_wac1->features =
- *((struct wacom_features *)id->driver_info);
+ *((struct wacom_features *)id->driver_data);
wacom_wac1->features.device_type = BTN_TOOL_PEN;
snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name);
+ snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
+ wacom_wac1->features.name);
wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
wacom_wac1->shared->type = wacom_wac1->features.type;
- error = wacom_register_input(wacom1);
+ error = wacom_register_inputs(wacom1);
if (error)
goto fail;
@@ -1216,7 +1148,7 @@ static void wacom_wireless_work(struct work_struct *work)
if (wacom_wac1->features.touch_max ||
wacom_wac1->features.type == INTUOSHT) {
wacom_wac2->features =
- *((struct wacom_features *)id->driver_info);
+ *((struct wacom_features *)id->driver_data);
wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
wacom_wac2->features.device_type = BTN_TOOL_FINGER;
wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
@@ -1226,7 +1158,9 @@ static void wacom_wireless_work(struct work_struct *work)
else
snprintf(wacom_wac2->name, WACOM_NAME_MAX,
"%s (WL) Pad",wacom_wac2->features.name);
- error = wacom_register_input(wacom2);
+ snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
+ "%s (WL) Pad", wacom_wac2->features.name);
+ error = wacom_register_inputs(wacom2);
if (error)
goto fail;
@@ -1243,15 +1177,8 @@ static void wacom_wireless_work(struct work_struct *work)
return;
fail:
- if (wacom_wac2->input) {
- input_unregister_device(wacom_wac2->input);
- wacom_wac2->input = NULL;
- }
-
- if (wacom_wac1->input) {
- input_unregister_device(wacom_wac1->input);
- wacom_wac1->input = NULL;
- }
+ wacom_unregister_inputs(wacom1);
+ wacom_unregister_inputs(wacom2);
return;
}
@@ -1282,69 +1209,89 @@ static void wacom_calculate_res(struct wacom_features *features)
features->unitExpo);
}
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int wacom_hid_report_len(struct hid_report *report)
+{
+ /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
+ return ((report->size - 1) >> 3) + 1 + (report->id > 0);
+}
+
+static size_t wacom_compute_pktlen(struct hid_device *hdev)
+{
+ struct hid_report_enum *report_enum;
+ struct hid_report *report;
+ size_t size = 0;
+
+ report_enum = hdev->report_enum + HID_INPUT_REPORT;
+
+ list_for_each_entry(report, &report_enum->report_list, list) {
+ size_t report_size = wacom_hid_report_len(report);
+ if (report_size > size)
+ size = report_size;
+ }
+
+ return size;
+}
+
+static int wacom_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
struct wacom_wac *wacom_wac;
struct wacom_features *features;
int error;
- if (!id->driver_info)
+ if (!id->driver_data)
return -EINVAL;
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
if (!wacom)
return -ENOMEM;
+ hid_set_drvdata(hdev, wacom);
+ wacom->hdev = hdev;
+
+ /* ask for the report descriptor to be loaded by HID */
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "parse failed\n");
+ goto fail1;
+ }
+
wacom_wac = &wacom->wacom_wac;
- wacom_wac->features = *((struct wacom_features *)id->driver_info);
+ wacom_wac->features = *((struct wacom_features *)id->driver_data);
features = &wacom_wac->features;
+ features->pktlen = wacom_compute_pktlen(hdev);
if (features->pktlen > WACOM_PKGLEN_MAX) {
error = -EINVAL;
goto fail1;
}
- wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX,
- GFP_KERNEL, &wacom->data_dma);
- if (!wacom_wac->data) {
- error = -ENOMEM;
+ if (features->check_for_hid_type && features->hid_type != hdev->type) {
+ error = -ENODEV;
goto fail1;
}
- wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
- if (!wacom->irq) {
- error = -ENOMEM;
- goto fail2;
- }
-
wacom->usbdev = dev;
wacom->intf = intf;
mutex_init(&wacom->lock);
INIT_WORK(&wacom->work, wacom_wireless_work);
- usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
- strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
-
- endpoint = &intf->cur_altsetting->endpoint[0].desc;
/* set the default size in case we do not get them from hid */
wacom_set_default_phy(features);
/* Retrieve the physical and logical size for touch devices */
- error = wacom_retrieve_hid_descriptor(intf, features);
- if (error)
- goto fail3;
+ wacom_retrieve_hid_descriptor(hdev, features);
/*
* Intuos5 has no useful data about its touch interface in its
- * HID descriptor. If this is the touch interface (wMaxPacketSize
+ * HID descriptor. If this is the touch interface (PacketSize
* of WACOM_PKGLEN_BBTOUCH3), override the table values.
*/
if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
- if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
+ if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
features->device_type = BTN_TOOL_FINGER;
- features->pktlen = WACOM_PKGLEN_BBTOUCH3;
features->x_max = 4096;
features->y_max = 4096;
@@ -1353,20 +1300,35 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
}
}
+ /*
+ * Same thing for Bamboo 3rd gen.
+ */
+ if ((features->type == BAMBOO_PT) &&
+ (features->pktlen == WACOM_PKGLEN_BBTOUCH3) &&
+ (features->device_type == BTN_TOOL_PEN)) {
+ features->device_type = BTN_TOOL_FINGER;
+
+ features->x_max = 4096;
+ features->y_max = 4096;
+ }
+
+ if (hdev->bus == BUS_BLUETOOTH)
+ features->quirks |= WACOM_QUIRK_BATTERY;
+
wacom_setup_device_quirks(features);
/* set unit to "100th of a mm" for devices not reported by HID */
if (!features->unit) {
features->unit = 0x11;
- features->unitExpo = 16 - 3;
+ features->unitExpo = -3;
}
wacom_calculate_res(features);
strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
+ snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name),
+ "%s Pad", features->name);
if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
- struct usb_device *other_dev;
-
/* Append the device type to the name */
if (features->device_type != BTN_TOOL_FINGER)
strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
@@ -1375,43 +1337,49 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
else
strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
- other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
- if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
- other_dev = dev;
- error = wacom_add_shared_data(wacom_wac, other_dev);
+ error = wacom_add_shared_data(hdev);
if (error)
- goto fail3;
+ goto fail1;
}
- usb_fill_int_urb(wacom->irq, dev,
- usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- wacom_wac->data, features->pktlen,
- wacom_sys_irq, wacom, endpoint->bInterval);
- wacom->irq->transfer_dma = wacom->data_dma;
- wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
error = wacom_initialize_leds(wacom);
if (error)
- goto fail4;
+ goto fail2;
+
+ if (!(features->quirks & WACOM_QUIRK_MONITOR) &&
+ (features->quirks & WACOM_QUIRK_BATTERY)) {
+ error = wacom_initialize_battery(wacom);
+ if (error)
+ goto fail3;
+ }
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
- error = wacom_register_input(wacom);
+ error = wacom_register_inputs(wacom);
if (error)
- goto fail5;
+ goto fail4;
}
- /* Note that if query fails it is not a hard failure */
- wacom_query_tablet_data(intf, features);
+ if (hdev->bus == BUS_BLUETOOTH) {
+ error = device_create_file(&hdev->dev, &dev_attr_speed);
+ if (error)
+ hid_warn(hdev,
+ "can't create sysfs speed attribute err: %d\n",
+ error);
+ }
- usb_set_intfdata(intf, wacom);
+ /* Note that if query fails it is not a hard failure */
+ wacom_query_tablet_data(hdev, features);
- if (features->quirks & WACOM_QUIRK_MONITOR) {
- if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
- error = -EIO;
- goto fail5;
- }
+ /* Regular HID work starts now */
+ error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ if (error) {
+ hid_err(hdev, "hw start failed\n");
+ goto fail5;
}
+ if (features->quirks & WACOM_QUIRK_MONITOR)
+ error = hid_hw_open(hdev);
+
if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) {
if (wacom_wac->features.device_type == BTN_TOOL_FINGER)
wacom_wac->shared->touch_input = wacom_wac->input;
@@ -1419,79 +1387,72 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
return 0;
- fail5: wacom_destroy_leds(wacom);
- fail4: wacom_remove_shared_data(wacom_wac);
- fail3: usb_free_urb(wacom->irq);
- fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
+ fail5: if (hdev->bus == BUS_BLUETOOTH)
+ device_remove_file(&hdev->dev, &dev_attr_speed);
+ wacom_unregister_inputs(wacom);
+ fail4: wacom_destroy_battery(wacom);
+ fail3: wacom_destroy_leds(wacom);
+ fail2: wacom_remove_shared_data(wacom_wac);
fail1: kfree(wacom);
+ hid_set_drvdata(hdev, NULL);
return error;
}
-static void wacom_disconnect(struct usb_interface *intf)
+static void wacom_remove(struct hid_device *hdev)
{
- struct wacom *wacom = usb_get_intfdata(intf);
+ struct wacom *wacom = hid_get_drvdata(hdev);
- usb_set_intfdata(intf, NULL);
+ hid_hw_stop(hdev);
- usb_kill_urb(wacom->irq);
cancel_work_sync(&wacom->work);
- if (wacom->wacom_wac.input)
- input_unregister_device(wacom->wacom_wac.input);
+ wacom_unregister_inputs(wacom);
+ if (hdev->bus == BUS_BLUETOOTH)
+ device_remove_file(&hdev->dev, &dev_attr_speed);
wacom_destroy_battery(wacom);
wacom_destroy_leds(wacom);
- usb_free_urb(wacom->irq);
- usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
- wacom->wacom_wac.data, wacom->data_dma);
wacom_remove_shared_data(&wacom->wacom_wac);
- kfree(wacom);
-}
-
-static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct wacom *wacom = usb_get_intfdata(intf);
-
- mutex_lock(&wacom->lock);
- usb_kill_urb(wacom->irq);
- mutex_unlock(&wacom->lock);
- return 0;
+ hid_set_drvdata(hdev, NULL);
+ kfree(wacom);
}
-static int wacom_resume(struct usb_interface *intf)
+#ifdef CONFIG_PM
+static int wacom_resume(struct hid_device *hdev)
{
- struct wacom *wacom = usb_get_intfdata(intf);
+ struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_features *features = &wacom->wacom_wac.features;
- int rv = 0;
mutex_lock(&wacom->lock);
/* switch to wacom mode first */
- wacom_query_tablet_data(intf, features);
+ wacom_query_tablet_data(hdev, features);
wacom_led_control(wacom);
- if ((wacom->open || (features->quirks & WACOM_QUIRK_MONITOR)) &&
- usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
- rv = -EIO;
-
mutex_unlock(&wacom->lock);
- return rv;
+ return 0;
}
-static int wacom_reset_resume(struct usb_interface *intf)
+static int wacom_reset_resume(struct hid_device *hdev)
{
- return wacom_resume(intf);
+ return wacom_resume(hdev);
}
+#endif /* CONFIG_PM */
-static struct usb_driver wacom_driver = {
+static struct hid_driver wacom_driver = {
.name = "wacom",
.id_table = wacom_ids,
.probe = wacom_probe,
- .disconnect = wacom_disconnect,
- .suspend = wacom_suspend,
+ .remove = wacom_remove,
+#ifdef CONFIG_PM
.resume = wacom_resume,
.reset_resume = wacom_reset_resume,
- .supports_autosuspend = 1,
+#endif
+ .raw_event = wacom_raw_event,
};
+module_hid_driver(wacom_driver);
-module_usb_driver(wacom_driver);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/hid/wacom_wac.c
index e73cf2c71f35..aa6a08eb7ad6 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -25,11 +25,23 @@
#define WACOM_INTUOS_RES 100
#define WACOM_INTUOS3_RES 200
-/* Scale factor relating reported contact size to logical contact area.
+/*
+ * Scale factor relating reported contact size to logical contact area.
* 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
*/
#define WACOM_CONTACT_AREA_SCALE 2607
+/*
+ * Percent of battery capacity for Graphire.
+ * 8th value means AC online and show 100% capacity.
+ */
+static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };
+
+/*
+ * Percent of battery capacity for Intuos4 WL, AC has a separate bit.
+ */
+static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };
+
static int wacom_penpartner_irq(struct wacom_wac *wacom)
{
unsigned char *data = wacom->data;
@@ -217,17 +229,13 @@ static int wacom_dtus_irq(struct wacom_wac *wacom)
"%s: received unknown report #%d", __func__, data[0]);
return 0;
} else if (data[0] == WACOM_REPORT_DTUSPAD) {
+ input = wacom->pad_input;
input_report_key(input, BTN_0, (data[1] & 0x01));
input_report_key(input, BTN_1, (data[1] & 0x02));
input_report_key(input, BTN_2, (data[1] & 0x04));
input_report_key(input, BTN_3, (data[1] & 0x08));
input_report_abs(input, ABS_MISC,
data[1] & 0x0f ? PAD_DEVICE_ID : 0);
- /*
- * Serial number is required when expresskeys are
- * reported through pen interface.
- */
- input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
return 1;
} else {
prox = data[1] & 0x80;
@@ -257,7 +265,6 @@ static int wacom_dtus_irq(struct wacom_wac *wacom)
wacom->id[0] = 0;
input_report_key(input, wacom->tool[0], prox);
input_report_abs(input, ABS_MISC, wacom->id[0]);
- input_event(input, EV_MSC, MSC_SERIAL, 1);
return 1;
}
}
@@ -267,11 +274,20 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->input;
+ struct input_dev *pad_input = wacom->pad_input;
+ int battery_capacity, ps_connected;
int prox;
int rw = 0;
int retval = 0;
- if (data[0] != WACOM_REPORT_PENABLED) {
+ if (features->type == GRAPHIRE_BT) {
+ if (data[0] != WACOM_REPORT_PENABLED_BT) {
+ dev_dbg(input->dev.parent,
+ "%s: received unknown report #%d\n", __func__,
+ data[0]);
+ goto exit;
+ }
+ } else if (data[0] != WACOM_REPORT_PENABLED) {
dev_dbg(input->dev.parent,
"%s: received unknown report #%d\n", __func__, data[0]);
goto exit;
@@ -305,7 +321,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
if (wacom->tool[0] != BTN_TOOL_MOUSE) {
- input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8));
+ if (features->type == GRAPHIRE_BT)
+ input_report_abs(input, ABS_PRESSURE, data[6] |
+ (((__u16) (data[1] & 0x08)) << 5));
+ else
+ input_report_abs(input, ABS_PRESSURE, data[6] |
+ ((data[7] & 0x03) << 8));
input_report_key(input, BTN_TOUCH, data[1] & 0x01);
input_report_key(input, BTN_STYLUS, data[1] & 0x02);
input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
@@ -316,6 +337,20 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
features->type == WACOM_MO) {
input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
rw = (data[7] & 0x04) - (data[7] & 0x03);
+ } else if (features->type == GRAPHIRE_BT) {
+ /* Compute distance between mouse and tablet */
+ rw = 44 - (data[6] >> 2);
+ rw = clamp_val(rw, 0, 31);
+ input_report_abs(input, ABS_DISTANCE, rw);
+ if (((data[1] >> 5) & 3) == 2) {
+ /* Mouse with wheel */
+ input_report_key(input, BTN_MIDDLE,
+ data[1] & 0x04);
+ rw = (data[6] & 0x01) ? -1 :
+ (data[6] & 0x02) ? 1 : 0;
+ } else {
+ rw = 0;
+ }
} else {
input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
rw = -(signed char)data[6];
@@ -327,7 +362,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
wacom->id[0] = 0;
input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
input_report_key(input, wacom->tool[0], prox);
- input_event(input, EV_MSC, MSC_SERIAL, 1);
input_sync(input); /* sync last event */
}
@@ -337,14 +371,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = data[7] & 0xf8;
if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID;
- input_report_key(input, BTN_BACK, (data[7] & 0x40));
- input_report_key(input, BTN_FORWARD, (data[7] & 0x80));
+ input_report_key(pad_input, BTN_BACK, (data[7] & 0x40));
+ input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x80));
rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
- input_report_rel(input, REL_WHEEL, rw);
+ input_report_rel(pad_input, REL_WHEEL, rw);
if (!prox)
wacom->id[1] = 0;
- input_report_abs(input, ABS_MISC, wacom->id[1]);
- input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+ input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
retval = 1;
}
break;
@@ -353,19 +386,43 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
prox = (data[7] & 0xf8) || data[8];
if (prox || wacom->id[1]) {
wacom->id[1] = PAD_DEVICE_ID;
- input_report_key(input, BTN_BACK, (data[7] & 0x08));
- input_report_key(input, BTN_LEFT, (data[7] & 0x20));
- input_report_key(input, BTN_FORWARD, (data[7] & 0x10));
- input_report_key(input, BTN_RIGHT, (data[7] & 0x40));
- input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f));
+ input_report_key(pad_input, BTN_BACK, (data[7] & 0x08));
+ input_report_key(pad_input, BTN_LEFT, (data[7] & 0x20));
+ input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x10));
+ input_report_key(pad_input, BTN_RIGHT, (data[7] & 0x40));
+ input_report_abs(pad_input, ABS_WHEEL, (data[8] & 0x7f));
+ if (!prox)
+ wacom->id[1] = 0;
+ input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
+ retval = 1;
+ }
+ break;
+ case GRAPHIRE_BT:
+ prox = data[7] & 0x03;
+ if (prox || wacom->id[1]) {
+ wacom->id[1] = PAD_DEVICE_ID;
+ input_report_key(pad_input, BTN_0, (data[7] & 0x02));
+ input_report_key(pad_input, BTN_1, (data[7] & 0x01));
if (!prox)
wacom->id[1] = 0;
- input_report_abs(input, ABS_MISC, wacom->id[1]);
- input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
+ input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
retval = 1;
}
break;
}
+
+ /* Store current battery capacity and power supply state */
+ if (features->type == GRAPHIRE_BT) {
+ rw = (data[7] >> 2 & 0x07);
+ battery_capacity = batcap_gr[rw];
+ ps_connected = rw == 7;
+ if ((wacom->battery_capacity != battery_capacity) ||
+ (wacom->ps_connected != ps_connected)) {
+ wacom->battery_capacity = battery_capacity;
+ wacom->ps_connected = ps_connected;
+ wacom_notify_battery(wacom);
+ }
+ }
exit:
return retval;
}
@@ -584,6 +641,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
+ input = wacom->pad_input;
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
input_report_key(input, BTN_0, (data[2] & 0x01));
input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -773,7 +831,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_MISC, 0);
}
}
- input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
return 1;
}
@@ -901,6 +958,58 @@ static int int_dist(int x1, int y1, int x2, int y2)
return int_sqrt(x*x + y*y);
}
+static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
+ unsigned char *data)
+{
+ memcpy(wacom->data, data, 10);
+ wacom_intuos_irq(wacom);
+
+ input_sync(wacom->input);
+ if (wacom->pad_input)
+ input_sync(wacom->pad_input);
+}
+
+static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
+{
+ unsigned char data[WACOM_PKGLEN_MAX];
+ int i = 1;
+ unsigned power_raw, battery_capacity, bat_charging, ps_connected;
+
+ memcpy(data, wacom->data, len);
+
+ switch (data[0]) {
+ case 0x04:
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ /* fall through */
+ case 0x03:
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ wacom_intuos_bt_process_data(wacom, data + i);
+ i += 10;
+ power_raw = data[i];
+ bat_charging = (power_raw & 0x08) ? 1 : 0;
+ ps_connected = (power_raw & 0x10) ? 1 : 0;
+ battery_capacity = batcap_i4[power_raw & 0x07];
+ if ((wacom->battery_capacity != battery_capacity) ||
+ (wacom->bat_charging != bat_charging) ||
+ (wacom->ps_connected != ps_connected)) {
+ wacom->battery_capacity = battery_capacity;
+ wacom->bat_charging = bat_charging;
+ wacom->ps_connected = ps_connected;
+ wacom_notify_battery(wacom);
+ }
+
+ break;
+ default:
+ dev_dbg(wacom->input->dev.parent,
+ "Unknown report: %d,%d size:%zu\n",
+ data[0], data[1], len);
+ return 0;
+ }
+ return 0;
+}
+
static int wacom_24hdt_irq(struct wacom_wac *wacom)
{
struct input_dev *input = wacom->input;
@@ -1093,7 +1202,7 @@ static int wacom_tpc_pen(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
- input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x03) << 8) | data[6]);
+ input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x07) << 8) | data[6]);
input_report_key(input, BTN_TOUCH, data[1] & 0x05);
input_report_key(input, wacom->tool[0], prox);
return 1;
@@ -1143,6 +1252,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
struct input_dev *input = wacom->input;
+ struct input_dev *pad_input = wacom->pad_input;
unsigned char *data = wacom->data;
int i;
@@ -1177,14 +1287,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
input_mt_report_pointer_emulation(input, true);
- input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
- input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
- input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
- input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
-
- input_sync(input);
+ input_report_key(pad_input, BTN_LEFT, (data[1] & 0x08) != 0);
+ input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
+ input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
+ input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
- return 0;
+ return 1;
}
static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
@@ -1232,7 +1340,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
{
- struct input_dev *input = wacom->input;
+ struct input_dev *input = wacom->pad_input;
struct wacom_features *features = &wacom->features;
if (features->type == INTUOSHT) {
@@ -1269,9 +1377,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
}
input_mt_report_pointer_emulation(input, true);
- input_sync(input);
-
- return 0;
+ return 1;
}
static int wacom_bpt_pen(struct wacom_wac *wacom)
@@ -1375,7 +1481,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
connected = data[1] & 0x01;
if (connected) {
- int pid, battery;
+ int pid, battery, ps_connected;
if ((wacom->shared->type == INTUOSHT) &&
wacom->shared->touch_max) {
@@ -1385,17 +1491,29 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
}
pid = get_unaligned_be16(&data[6]);
- battery = data[5] & 0x3f;
+ battery = (data[5] & 0x3f) * 100 / 31;
+ ps_connected = !!(data[5] & 0x80);
if (wacom->pid != pid) {
wacom->pid = pid;
wacom_schedule_work(wacom);
}
- wacom->battery_capacity = battery;
+
+ if (wacom->shared->type &&
+ (battery != wacom->battery_capacity ||
+ ps_connected != wacom->ps_connected)) {
+ wacom->battery_capacity = battery;
+ wacom->ps_connected = ps_connected;
+ wacom->bat_charging = ps_connected &&
+ wacom->battery_capacity < 100;
+ wacom_notify_battery(wacom);
+ }
} else if (wacom->pid != 0) {
/* disconnected while previously connected */
wacom->pid = 0;
wacom_schedule_work(wacom);
wacom->battery_capacity = 0;
+ wacom->bat_charging = 0;
+ wacom->ps_connected = 0;
}
return 0;
@@ -1416,6 +1534,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case WACOM_G4:
case GRAPHIRE:
+ case GRAPHIRE_BT:
case WACOM_MO:
sync = wacom_graphire_irq(wacom_wac);
break;
@@ -1450,6 +1569,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
sync = wacom_intuos_irq(wacom_wac);
break;
+ case INTUOS4WL:
+ sync = wacom_intuos_bt_irq(wacom_wac, len);
+ break;
+
case WACOM_24HDT:
sync = wacom_24hdt_irq(wacom_wac);
break;
@@ -1489,8 +1612,11 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
break;
}
- if (sync)
+ if (sync) {
input_sync(wacom_wac->input);
+ if (wacom_wac->pad_input)
+ input_sync(wacom_wac->pad_input);
+ }
}
static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
@@ -1565,8 +1691,10 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features->quirks |= WACOM_QUIRK_NO_INPUT;
/* must be monitor interface if no device_type set */
- if (!features->device_type)
+ if (!features->device_type) {
features->quirks |= WACOM_QUIRK_MONITOR;
+ features->quirks |= WACOM_QUIRK_BATTERY;
+ }
}
}
@@ -1615,7 +1743,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac)
{
struct wacom_features *features = &wacom_wac->features;
- int i;
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
@@ -1630,10 +1757,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
/* fall through */
case WACOM_G4:
- input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-
- __set_bit(BTN_BACK, input_dev->keybit);
- __set_bit(BTN_FORWARD, input_dev->keybit);
/* fall through */
case GRAPHIRE:
@@ -1652,62 +1775,42 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
break;
- case WACOM_24HD:
- __set_bit(BTN_A, input_dev->keybit);
- __set_bit(BTN_B, input_dev->keybit);
- __set_bit(BTN_C, input_dev->keybit);
- __set_bit(BTN_X, input_dev->keybit);
- __set_bit(BTN_Y, input_dev->keybit);
- __set_bit(BTN_Z, input_dev->keybit);
+ case GRAPHIRE_BT:
+ __clear_bit(ABS_MISC, input_dev->absbit);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+ features->distance_max,
+ 0, 0);
- for (i = 6; i < 10; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
+ input_set_capability(input_dev, EV_REL, REL_WHEEL);
- __set_bit(KEY_PROG1, input_dev->keybit);
- __set_bit(KEY_PROG2, input_dev->keybit);
- __set_bit(KEY_PROG3, input_dev->keybit);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ __set_bit(BTN_MIDDLE, input_dev->keybit);
+
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+ break;
+ case WACOM_24HD:
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
/* fall through */
case DTK:
- for (i = 0; i < 6; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
wacom_setup_cintiq(wacom_wac);
break;
case WACOM_22HD:
- __set_bit(KEY_PROG1, input_dev->keybit);
- __set_bit(KEY_PROG2, input_dev->keybit);
- __set_bit(KEY_PROG3, input_dev->keybit);
- /* fall through */
-
case WACOM_21UX2:
- __set_bit(BTN_A, input_dev->keybit);
- __set_bit(BTN_B, input_dev->keybit);
- __set_bit(BTN_C, input_dev->keybit);
- __set_bit(BTN_X, input_dev->keybit);
- __set_bit(BTN_Y, input_dev->keybit);
- __set_bit(BTN_Z, input_dev->keybit);
- __set_bit(BTN_BASE, input_dev->keybit);
- __set_bit(BTN_BASE2, input_dev->keybit);
- /* fall through */
-
case WACOM_BEE:
- __set_bit(BTN_8, input_dev->keybit);
- __set_bit(BTN_9, input_dev->keybit);
- /* fall through */
-
case CINTIQ:
- for (i = 0; i < 8; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
- input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -1716,9 +1819,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case WACOM_13HD:
- for (i = 0; i < 9; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
wacom_setup_cintiq(wacom_wac);
@@ -1726,21 +1826,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS3:
case INTUOS3L:
- __set_bit(BTN_4, input_dev->keybit);
- __set_bit(BTN_5, input_dev->keybit);
- __set_bit(BTN_6, input_dev->keybit);
- __set_bit(BTN_7, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
- /* fall through */
-
case INTUOS3S:
- __set_bit(BTN_0, input_dev->keybit);
- __set_bit(BTN_1, input_dev->keybit);
- __set_bit(BTN_2, input_dev->keybit);
- __set_bit(BTN_3, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
/* fall through */
@@ -1754,20 +1840,11 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS5L:
case INTUOSPM:
case INTUOSPL:
- if (features->device_type == BTN_TOOL_PEN) {
- __set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
- }
- /* fall through */
-
case INTUOS5S:
case INTUOSPS:
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
if (features->device_type == BTN_TOOL_PEN) {
- for (i = 0; i < 7; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max,
0, 0);
@@ -1787,15 +1864,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case INTUOS4:
+ case INTUOS4WL:
case INTUOS4L:
- __set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
- /* fall through */
-
case INTUOS4S:
- for (i = 0; i < 7; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
wacom_setup_intuos(wacom_wac);
@@ -1833,11 +1904,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case DTUS:
case PL:
case DTU:
- if (features->type == DTUS) {
- input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
- for (i = 0; i < 4; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
- }
__set_bit(BTN_TOOL_PEN, input_dev->keybit);
__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
__set_bit(BTN_STYLUS, input_dev->keybit);
@@ -1871,11 +1937,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
if (features->device_type == BTN_TOOL_FINGER) {
- __set_bit(BTN_LEFT, input_dev->keybit);
- __set_bit(BTN_FORWARD, input_dev->keybit);
- __set_bit(BTN_BACK, input_dev->keybit);
- __set_bit(BTN_RIGHT, input_dev->keybit);
-
if (features->touch_max) {
if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
input_set_abs_params(input_dev,
@@ -1905,449 +1966,629 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case CINTIQ_HYBRID:
+ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ wacom_setup_cintiq(wacom_wac);
+ break;
+ }
+ return 0;
+}
+
+int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
+ struct wacom_wac *wacom_wac)
+{
+ struct wacom_features *features = &wacom_wac->features;
+ int i;
+
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+
+ /* kept for making legacy xf86-input-wacom working with the wheels */
+ __set_bit(ABS_MISC, input_dev->absbit);
+
+ /* kept for making legacy xf86-input-wacom accepting the pad */
+ input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
+
+ switch (features->type) {
+ case GRAPHIRE_BT:
+ __set_bit(BTN_0, input_dev->keybit);
__set_bit(BTN_1, input_dev->keybit);
- __set_bit(BTN_2, input_dev->keybit);
- __set_bit(BTN_3, input_dev->keybit);
- __set_bit(BTN_4, input_dev->keybit);
+ break;
+
+ case WACOM_MO:
+ __set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case WACOM_G4:
+ __set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+ input_set_capability(input_dev, EV_REL, REL_WHEEL);
+ break;
+
+ case WACOM_24HD:
+ __set_bit(BTN_A, input_dev->keybit);
+ __set_bit(BTN_B, input_dev->keybit);
+ __set_bit(BTN_C, input_dev->keybit);
+ __set_bit(BTN_X, input_dev->keybit);
+ __set_bit(BTN_Y, input_dev->keybit);
+ __set_bit(BTN_Z, input_dev->keybit);
+ for (i = 0; i < 10; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ __set_bit(KEY_PROG1, input_dev->keybit);
+ __set_bit(KEY_PROG2, input_dev->keybit);
+ __set_bit(KEY_PROG3, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+ break;
+
+ case DTK:
+ for (i = 0; i < 6; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ break;
+
+ case WACOM_22HD:
+ __set_bit(KEY_PROG1, input_dev->keybit);
+ __set_bit(KEY_PROG2, input_dev->keybit);
+ __set_bit(KEY_PROG3, input_dev->keybit);
+ /* fall through */
+
+ case WACOM_21UX2:
+ __set_bit(BTN_A, input_dev->keybit);
+ __set_bit(BTN_B, input_dev->keybit);
+ __set_bit(BTN_C, input_dev->keybit);
+ __set_bit(BTN_X, input_dev->keybit);
+ __set_bit(BTN_Y, input_dev->keybit);
+ __set_bit(BTN_Z, input_dev->keybit);
+ __set_bit(BTN_BASE, input_dev->keybit);
+ __set_bit(BTN_BASE2, input_dev->keybit);
+ /* fall through */
+
+ case WACOM_BEE:
+ __set_bit(BTN_8, input_dev->keybit);
+ __set_bit(BTN_9, input_dev->keybit);
+ /* fall through */
+
+ case CINTIQ:
+ for (i = 0; i < 8; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+ break;
+
+ case WACOM_13HD:
+ for (i = 0; i < 9; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case INTUOS3:
+ case INTUOS3L:
+ __set_bit(BTN_4, input_dev->keybit);
__set_bit(BTN_5, input_dev->keybit);
__set_bit(BTN_6, input_dev->keybit);
__set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+ /* fall through */
+
+ case INTUOS3S:
__set_bit(BTN_0, input_dev->keybit);
+ __set_bit(BTN_1, input_dev->keybit);
+ __set_bit(BTN_2, input_dev->keybit);
+ __set_bit(BTN_3, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
- __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+ break;
- wacom_setup_cintiq(wacom_wac);
+ case INTUOS5:
+ case INTUOS5L:
+ case INTUOSPM:
+ case INTUOSPL:
+ __set_bit(BTN_7, input_dev->keybit);
+ __set_bit(BTN_8, input_dev->keybit);
+ /* fall through */
+
+ case INTUOS5S:
+ case INTUOSPS:
+ /* touch interface does not have the pad device */
+ if (features->device_type != BTN_TOOL_PEN)
+ return 1;
+
+ for (i = 0; i < 7; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
break;
+
+ case INTUOS4WL:
+ /*
+ * For Bluetooth devices, the udev rule does not work correctly
+ * for pads unless we add a stylus capability, which forces
+ * ID_INPUT_TABLET to be set.
+ */
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ /* fall through */
+
+ case INTUOS4:
+ case INTUOS4L:
+ __set_bit(BTN_7, input_dev->keybit);
+ __set_bit(BTN_8, input_dev->keybit);
+ /* fall through */
+
+ case INTUOS4S:
+ for (i = 0; i < 7; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case CINTIQ_HYBRID:
+ for (i = 0; i < 9; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ break;
+
+ case DTUS:
+ for (i = 0; i < 4; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+ break;
+
+ case INTUOSHT:
+ case BAMBOO_PT:
+ /* pad device is on the touch interface */
+ if (features->device_type != BTN_TOOL_FINGER)
+ return 1;
+
+ __clear_bit(ABS_MISC, input_dev->absbit);
+
+ __set_bit(BTN_LEFT, input_dev->keybit);
+ __set_bit(BTN_FORWARD, input_dev->keybit);
+ __set_bit(BTN_BACK, input_dev->keybit);
+ __set_bit(BTN_RIGHT, input_dev->keybit);
+
+ break;
+
+ default:
+ /* no pad supported */
+ return 1;
}
return 0;
}
static const struct wacom_features wacom_features_0x00 =
- { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255,
- 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+ { "Wacom Penpartner", 5040, 3780, 255, 0,
+ PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
static const struct wacom_features wacom_features_0x10 =
- { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire", 10206, 7422, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+static const struct wacom_features wacom_features_0x81 =
+ { "Wacom Graphire BT", 16704, 12064, 511, 32,
+ GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x11 =
- { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire2 4x5", 10206, 7422, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x12 =
- { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire2 5x7", 13918, 10206, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x13 =
- { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire3", 10208, 7424, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x14 =
- { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire3 6x8", 16704, 12064, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x15 =
- { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511,
- 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire4 4x5", 10208, 7424, 511, 63,
+ WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x16 =
- { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511,
- 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Graphire4 6x8", 16704, 12064, 511, 63,
+ WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x17 =
- { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511,
- 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom BambooFun 4x5", 14760, 9225, 511, 63,
+ WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x18 =
- { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511,
- 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom BambooFun 6x8", 21648, 13530, 511, 63,
+ WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x19 =
- { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511,
- 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
+ { "Wacom Bamboo1 Medium", 16704, 12064, 511, 63,
+ GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
static const struct wacom_features wacom_features_0x60 =
- { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511,
- 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+ { "Wacom Volito", 5104, 3712, 511, 63,
+ GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
static const struct wacom_features wacom_features_0x61 =
- { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255,
- 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+ { "Wacom PenStation2", 3250, 2320, 255, 63,
+ GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
static const struct wacom_features wacom_features_0x62 =
- { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511,
- 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+ { "Wacom Volito2 4x5", 5104, 3712, 511, 63,
+ GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
static const struct wacom_features wacom_features_0x63 =
- { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511,
- 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+ { "Wacom Volito2 2x3", 3248, 2320, 511, 63,
+ GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
static const struct wacom_features wacom_features_0x64 =
- { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511,
- 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
+ { "Wacom PenPartner2", 3250, 2320, 511, 63,
+ GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
static const struct wacom_features wacom_features_0x65 =
- { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511,
- 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo", 14760, 9225, 511, 63,
+ WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x69 =
- { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511,
- 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
+ { "Wacom Bamboo1", 5104, 3712, 511, 63,
+ GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
static const struct wacom_features wacom_features_0x6A =
- { "Wacom Bamboo1 4x6", WACOM_PKGLEN_GRAPHIRE, 14760, 9225, 1023,
- 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo1 4x6", 14760, 9225, 1023, 63,
+ GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x6B =
- { "Wacom Bamboo1 5x8", WACOM_PKGLEN_GRAPHIRE, 21648, 13530, 1023,
- 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo1 5x8", 21648, 13530, 1023, 63,
+ GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x20 =
- { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos 4x5", 12700, 10600, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x21 =
- { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos 6x8", 20320, 16240, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x22 =
- { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos 9x12", 30480, 24060, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x23 =
- { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos 12x12", 30480, 31680, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x24 =
- { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos 12x18", 45720, 31680, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x30 =
- { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL400", 5408, 4056, 255, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x31 =
- { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL500", 6144, 4608, 255, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x32 =
- { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL600", 6126, 4604, 255, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x33 =
- { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL600SX", 6260, 5016, 255, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x34 =
- { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL550", 6144, 4608, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x35 =
- { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL800", 7220, 5780, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x37 =
- { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL700", 6758, 5406, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x38 =
- { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom PL510", 6282, 4762, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x39 =
- { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom DTU710", 34080, 27660, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0xC4 =
- { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom DTF521", 6282, 4762, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0xC0 =
- { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom DTF720", 6858, 5506, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0xC2 =
- { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511,
- 0, PL, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom DTF720a", 6858, 5506, 511, 0,
+ PL, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x03 =
- { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511,
- 0, PTU, WACOM_PL_RES, WACOM_PL_RES };
+ { "Wacom Cintiq Partner", 20480, 15360, 511, 0,
+ PTU, WACOM_PL_RES, WACOM_PL_RES };
static const struct wacom_features wacom_features_0x41 =
- { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 4x5", 12700, 10600, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x42 =
- { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x43 =
- { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 9x12", 30480, 24060, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x44 =
- { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 12x12", 30480, 31680, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x45 =
- { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 12x18", 45720, 31680, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xB0 =
- { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023,
- 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 4x5", 25400, 20320, 1023, 63,
+ INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB1 =
- { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023,
- 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 6x8", 40640, 30480, 1023, 63,
+ INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB2 =
- { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023,
- 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 9x12", 60960, 45720, 1023, 63,
+ INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB3 =
- { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023,
- 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 12x12", 60960, 60960, 1023, 63,
+ INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB4 =
- { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023,
- 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 12x19", 97536, 60960, 1023, 63,
+ INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB5 =
- { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023,
- 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 6x11", 54204, 31750, 1023, 63,
+ INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB7 =
- { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023,
- 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos3 4x6", 31496, 19685, 1023, 63,
+ INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB8 =
- { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
- 63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos4 4x6", 31496, 19685, 2047, 63,
+ INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xB9 =
- { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
- 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos4 6x9", 44704, 27940, 2047, 63,
+ INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xBA =
- { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
- 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos4 8x13", 65024, 40640, 2047, 63,
+ INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xBB =
- { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047,
- 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos4 12x19", 97536, 60960, 2047, 63,
+ INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xBC =
- { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40640, 25400, 2047,
- 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
+ INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xBD =
+ { "Wacom Intuos4 WL", 40640, 25400, 2047, 63,
+ INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x26 =
- { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
- 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos5 touch S", 31496, 19685, 2047, 63,
+ INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0x27 =
- { "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
- 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos5 touch M", 44704, 27940, 2047, 63,
+ INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0x28 =
- { "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
- 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos5 touch L", 65024, 40640, 2047, 63,
+ INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0x29 =
- { "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
- 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos5 S", 31496, 19685, 2047, 63,
+ INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x2A =
- { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
- 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Intuos5 M", 44704, 27940, 2047, 63,
+ INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x314 =
- { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
- 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos Pro S", 31496, 19685, 2047, 63,
+ INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x315 =
- { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
- 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos Pro M", 44704, 27940, 2047, 63,
+ INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x317 =
- { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
- 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
- .touch_max = 16 };
+ { "Wacom Intuos Pro L", 65024, 40640, 2047, 63,
+ INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0xF4 =
- { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047,
- 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+ { "Wacom Cintiq 24HD", 104280, 65400, 2047, 63,
+ WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
static const struct wacom_features wacom_features_0xF8 =
- { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104280, 65400, 2047, /* Pen */
- 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+ { "Wacom Cintiq 24HD touch", 104280, 65400, 2047, 63, /* Pen */
+ WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
static const struct wacom_features wacom_features_0xF6 =
{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x3F =
- { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023,
- 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63,
+ CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xC5 =
- { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023,
- 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Cintiq 20WSX", 86680, 54180, 1023, 63,
+ WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xC6 =
- { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023,
- 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+ { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
+ WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x304 =
- { "Wacom Cintiq 13HD", WACOM_PKGLEN_INTUOS, 59352, 33648, 1023,
- 63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+ { "Wacom Cintiq 13HD", 59352, 33648, 1023, 63,
+ WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
static const struct wacom_features wacom_features_0xC7 =
- { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511,
- 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom DTU1931", 37832, 30305, 511, 0,
+ PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xCE =
- { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511,
- 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom DTU2231", 47864, 27011, 511, 0,
+ DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE };
static const struct wacom_features wacom_features_0xF0 =
- { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511,
- 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom DTU1631", 34623, 19553, 511, 0,
+ DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xFB =
- { "Wacom DTU1031", WACOM_PKGLEN_DTUS, 22096, 13960, 511,
- 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom DTU1031", 22096, 13960, 511, 0,
+ DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x57 =
- { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047,
- 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+ { "Wacom DTK2241", 95640, 54060, 2047, 63,
+ DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
static const struct wacom_features wacom_features_0x59 = /* Pen */
- { "Wacom DTH2242", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047,
- 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+ { "Wacom DTH2242", 95640, 54060, 2047, 63,
+ DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
static const struct wacom_features wacom_features_0x5D = /* Touch */
{ "Wacom DTH2242", .type = WACOM_24HDT,
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0xCC =
- { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87000, 65400, 2047,
- 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+ { "Wacom Cintiq 21UX2", 87000, 65400, 2047, 63,
+ WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
static const struct wacom_features wacom_features_0xFA =
- { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047,
- 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
+ { "Wacom Cintiq 22HD", 95640, 54060, 2047, 63,
+ WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 };
static const struct wacom_features wacom_features_0x5B =
- { "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS, 95640, 54060, 2047,
- 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+ { "Wacom Cintiq 22HDT", 95640, 54060, 2047, 63,
+ WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
static const struct wacom_features wacom_features_0x5E =
{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x90 =
- { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 90", 26202, 16325, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x93 =
- { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 93", 26202, 16325, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x97 =
- { "Wacom ISDv4 97", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 511,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 97", 26202, 16325, 511, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x9A =
- { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 9A", 26202, 16325, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x9F =
- { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 9F", 26202, 16325, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xE2 =
- { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom ISDv4 E2", 26202, 16325, 255, 0,
+ TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xE3 =
- { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255,
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom ISDv4 E3", 26202, 16325, 255, 0,
+ TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xE5 =
- { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255,
- 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 E5", 26202, 16325, 255, 0,
+ MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xE6 =
- { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255,
- 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom ISDv4 E6", 27760, 15694, 255, 0,
+ TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xEC =
- { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 EC", 25710, 14500, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xED =
- { "Wacom ISDv4 ED", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 ED", 26202, 16325, 255, 0,
+ TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xEF =
- { "Wacom ISDv4 EF", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 EF", 26202, 16325, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x100 =
- { "Wacom ISDv4 100", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 100", 26202, 16325, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x101 =
- { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 101", 26202, 16325, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x10D =
- { "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 10D", 26202, 16325, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x10E =
- { "Wacom ISDv4 10E", WACOM_PKGLEN_MTTPC, 27760, 15694, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 10E", 27760, 15694, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x10F =
- { "Wacom ISDv4 10F", WACOM_PKGLEN_MTTPC, 27760, 15694, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 10F", 27760, 15694, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x116 =
- { "Wacom ISDv4 116", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
- 0, TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 116", 26202, 16325, 255, 0,
+ TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x12C =
+ { "Wacom ISDv4 12C", 27848, 15752, 2047, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x4001 =
- { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
- 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 4001", 26202, 16325, 255, 0,
+ MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x4004 =
- { "Wacom ISDv4 4004", WACOM_PKGLEN_MTTPC, 11060, 6220, 255,
- 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 4004", 11060, 6220, 255, 0,
+ MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x5000 =
- { "Wacom ISDv4 5000", WACOM_PKGLEN_MTTPC, 27848, 15752, 1023,
- 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 5000", 27848, 15752, 1023, 0,
+ MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x5002 =
- { "Wacom ISDv4 5002", WACOM_PKGLEN_MTTPC, 29576, 16724, 1023,
- 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom ISDv4 5002", 29576, 16724, 1023, 0,
+ MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x47 =
- { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
- 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
+ INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x84 =
- { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0,
- 0, WIRELESS, 0, 0, .touch_max = 16 };
+ { "Wacom Wireless Receiver", 0, 0, 0, 0,
+ WIRELESS, 0, 0, .touch_max = 16 };
static const struct wacom_features wacom_features_0xD0 =
- { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo 2FG", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD1 =
- { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD2 =
- { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo Craft", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD3 =
- { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo 2FG 6x8", 21648, 13700, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD4 =
- { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Pen", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD5 =
- { "Wacom Bamboo Pen 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xD6 =
- { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD7 =
- { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom BambooPT 2FG Small", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xD8 =
- { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo Comic 2FG", 21648, 13700, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xDA =
- { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo 2FG 4x5 SE", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xDB =
- { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 2 };
+ { "Wacom Bamboo 2FG 6x8 SE", 21648, 13700, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xDD =
- { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo Connect", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0xDE =
- { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ { "Wacom Bamboo 16FG 4x5", 14720, 9200, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0xDF =
- { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ { "Wacom Bamboo 16FG 6x8", 21648, 13700, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
static const struct wacom_features wacom_features_0x300 =
- { "Wacom Bamboo One S", WACOM_PKGLEN_BBPEN, 14720, 9225, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo One S", 14720, 9225, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x301 =
- { "Wacom Bamboo One M", WACOM_PKGLEN_BBPEN, 21648, 13530, 1023,
- 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Bamboo One M", 21648, 13530, 1023, 31,
+ BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x302 =
- { "Wacom Intuos PT S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
- 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ { "Wacom Intuos PT S", 15200, 9500, 1023, 31,
+ INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x303 =
- { "Wacom Intuos PT M", WACOM_PKGLEN_BBPEN, 21600, 13500, 1023,
- 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
- .touch_max = 16 };
+ { "Wacom Intuos PT M", 21600, 13500, 1023, 31,
+ INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x30E =
- { "Wacom Intuos S", WACOM_PKGLEN_BBPEN, 15200, 9500, 1023,
- 31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ { "Wacom Intuos S", 15200, 9500, 1023, 31,
+ INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x6004 =
- { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
- 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
-static const struct wacom_features wacom_features_0x0307 =
- { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59352, 33648, 2047,
- 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
+ { "ISD-V4", 12800, 8000, 255, 0,
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x307 =
+ { "Wacom ISDv5 307", 59352, 33648, 2047, 63,
+ CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200,
.oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
-static const struct wacom_features wacom_features_0x0309 =
+static const struct wacom_features wacom_features_0x309 =
{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
- .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 };
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
+ .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
-#define USB_DEVICE_WACOM(prod) \
- USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+#define USB_DEVICE_WACOM(prod) \
+ HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
-#define USB_DEVICE_DETAILED(prod, class, sub, proto) \
- USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \
- sub, proto), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+#define BT_DEVICE_WACOM(prod) \
+ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
#define USB_DEVICE_LENOVO(prod) \
- USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
- .driver_info = (kernel_ulong_t)&wacom_features_##prod
+ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \
+ .driver_data = (kernel_ulong_t)&wacom_features_##prod
-const struct usb_device_id wacom_ids[] = {
+const struct hid_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x00) },
+ { USB_DEVICE_WACOM(0x03) },
{ USB_DEVICE_WACOM(0x10) },
{ USB_DEVICE_WACOM(0x11) },
{ USB_DEVICE_WACOM(0x12) },
@@ -2358,20 +2599,16 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x17) },
{ USB_DEVICE_WACOM(0x18) },
{ USB_DEVICE_WACOM(0x19) },
- { USB_DEVICE_WACOM(0x60) },
- { USB_DEVICE_WACOM(0x61) },
- { USB_DEVICE_WACOM(0x62) },
- { USB_DEVICE_WACOM(0x63) },
- { USB_DEVICE_WACOM(0x64) },
- { USB_DEVICE_WACOM(0x65) },
- { USB_DEVICE_WACOM(0x69) },
- { USB_DEVICE_WACOM(0x6A) },
- { USB_DEVICE_WACOM(0x6B) },
{ USB_DEVICE_WACOM(0x20) },
{ USB_DEVICE_WACOM(0x21) },
{ USB_DEVICE_WACOM(0x22) },
{ USB_DEVICE_WACOM(0x23) },
{ USB_DEVICE_WACOM(0x24) },
+ { USB_DEVICE_WACOM(0x26) },
+ { USB_DEVICE_WACOM(0x27) },
+ { USB_DEVICE_WACOM(0x28) },
+ { USB_DEVICE_WACOM(0x29) },
+ { USB_DEVICE_WACOM(0x2A) },
{ USB_DEVICE_WACOM(0x30) },
{ USB_DEVICE_WACOM(0x31) },
{ USB_DEVICE_WACOM(0x32) },
@@ -2381,20 +2618,34 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x37) },
{ USB_DEVICE_WACOM(0x38) },
{ USB_DEVICE_WACOM(0x39) },
- { USB_DEVICE_WACOM(0xC4) },
- { USB_DEVICE_WACOM(0xC0) },
- { USB_DEVICE_WACOM(0xC2) },
- { USB_DEVICE_WACOM(0x03) },
+ { USB_DEVICE_WACOM(0x3F) },
{ USB_DEVICE_WACOM(0x41) },
{ USB_DEVICE_WACOM(0x42) },
{ USB_DEVICE_WACOM(0x43) },
{ USB_DEVICE_WACOM(0x44) },
{ USB_DEVICE_WACOM(0x45) },
+ { USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0x57) },
{ USB_DEVICE_WACOM(0x59) },
- { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0x5B) },
- { USB_DEVICE_DETAILED(0x5E, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x5D) },
+ { USB_DEVICE_WACOM(0x5E) },
+ { USB_DEVICE_WACOM(0x60) },
+ { USB_DEVICE_WACOM(0x61) },
+ { USB_DEVICE_WACOM(0x62) },
+ { USB_DEVICE_WACOM(0x63) },
+ { USB_DEVICE_WACOM(0x64) },
+ { USB_DEVICE_WACOM(0x65) },
+ { USB_DEVICE_WACOM(0x69) },
+ { USB_DEVICE_WACOM(0x6A) },
+ { USB_DEVICE_WACOM(0x6B) },
+ { BT_DEVICE_WACOM(0x81) },
+ { USB_DEVICE_WACOM(0x84) },
+ { USB_DEVICE_WACOM(0x90) },
+ { USB_DEVICE_WACOM(0x93) },
+ { USB_DEVICE_WACOM(0x97) },
+ { USB_DEVICE_WACOM(0x9A) },
+ { USB_DEVICE_WACOM(0x9F) },
{ USB_DEVICE_WACOM(0xB0) },
{ USB_DEVICE_WACOM(0xB1) },
{ USB_DEVICE_WACOM(0xB2) },
@@ -2407,23 +2658,15 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xBA) },
{ USB_DEVICE_WACOM(0xBB) },
{ USB_DEVICE_WACOM(0xBC) },
- { USB_DEVICE_WACOM(0x26) },
- { USB_DEVICE_WACOM(0x27) },
- { USB_DEVICE_WACOM(0x28) },
- { USB_DEVICE_WACOM(0x29) },
- { USB_DEVICE_WACOM(0x2A) },
- { USB_DEVICE_WACOM(0x3F) },
+ { BT_DEVICE_WACOM(0xBD) },
+ { USB_DEVICE_WACOM(0xC0) },
+ { USB_DEVICE_WACOM(0xC2) },
+ { USB_DEVICE_WACOM(0xC4) },
{ USB_DEVICE_WACOM(0xC5) },
{ USB_DEVICE_WACOM(0xC6) },
{ USB_DEVICE_WACOM(0xC7) },
- /*
- * DTU-2231 has two interfaces on the same configuration,
- * only one is used.
- */
- { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
- USB_INTERFACE_SUBCLASS_BOOT,
- USB_INTERFACE_PROTOCOL_MOUSE) },
- { USB_DEVICE_WACOM(0x84) },
+ { USB_DEVICE_WACOM(0xCC) },
+ { USB_DEVICE_WACOM(0xCE) },
{ USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) },
@@ -2438,13 +2681,6 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xDD) },
{ USB_DEVICE_WACOM(0xDE) },
{ USB_DEVICE_WACOM(0xDF) },
- { USB_DEVICE_WACOM(0xF0) },
- { USB_DEVICE_WACOM(0xCC) },
- { USB_DEVICE_WACOM(0x90) },
- { USB_DEVICE_WACOM(0x93) },
- { USB_DEVICE_WACOM(0x97) },
- { USB_DEVICE_WACOM(0x9A) },
- { USB_DEVICE_WACOM(0x9F) },
{ USB_DEVICE_WACOM(0xE2) },
{ USB_DEVICE_WACOM(0xE3) },
{ USB_DEVICE_WACOM(0xE5) },
@@ -2452,34 +2688,34 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0xEC) },
{ USB_DEVICE_WACOM(0xED) },
{ USB_DEVICE_WACOM(0xEF) },
+ { USB_DEVICE_WACOM(0xF0) },
+ { USB_DEVICE_WACOM(0xF4) },
+ { USB_DEVICE_WACOM(0xF6) },
+ { USB_DEVICE_WACOM(0xF8) },
+ { USB_DEVICE_WACOM(0xFA) },
+ { USB_DEVICE_WACOM(0xFB) },
{ USB_DEVICE_WACOM(0x100) },
{ USB_DEVICE_WACOM(0x101) },
{ USB_DEVICE_WACOM(0x10D) },
{ USB_DEVICE_WACOM(0x10E) },
{ USB_DEVICE_WACOM(0x10F) },
{ USB_DEVICE_WACOM(0x116) },
+ { USB_DEVICE_WACOM(0x12C) },
{ USB_DEVICE_WACOM(0x300) },
{ USB_DEVICE_WACOM(0x301) },
- { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x302) },
+ { USB_DEVICE_WACOM(0x303) },
{ USB_DEVICE_WACOM(0x304) },
- { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_WACOM(0x307) },
+ { USB_DEVICE_WACOM(0x309) },
+ { USB_DEVICE_WACOM(0x30E) },
+ { USB_DEVICE_WACOM(0x314) },
+ { USB_DEVICE_WACOM(0x315) },
+ { USB_DEVICE_WACOM(0x317) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
{ USB_DEVICE_WACOM(0x5002) },
- { USB_DEVICE_WACOM(0x47) },
- { USB_DEVICE_WACOM(0xF4) },
- { USB_DEVICE_WACOM(0xF8) },
- { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_WACOM(0xFA) },
- { USB_DEVICE_WACOM(0xFB) },
- { USB_DEVICE_WACOM(0x0307) },
- { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) },
- { USB_DEVICE_LENOVO(0x6004) },
{ }
};
-MODULE_DEVICE_TABLE(usb, wacom_ids);
+MODULE_DEVICE_TABLE(hid, wacom_ids);
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/hid/wacom_wac.h
index b2c9a9c1b551..339ab5d81a2d 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -46,6 +46,7 @@
/* wacom data packet report IDs */
#define WACOM_REPORT_PENABLED 2
+#define WACOM_REPORT_PENABLED_BT 3
#define WACOM_REPORT_INTUOSREAD 5
#define WACOM_REPORT_INTUOSWRITE 6
#define WACOM_REPORT_INTUOSPAD 12
@@ -68,10 +69,12 @@
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
#define WACOM_QUIRK_NO_INPUT 0x0004
#define WACOM_QUIRK_MONITOR 0x0008
+#define WACOM_QUIRK_BATTERY 0x0010
enum {
PENPARTNER = 0,
GRAPHIRE,
+ GRAPHIRE_BT,
WACOM_G4,
PTU,
PL,
@@ -83,6 +86,7 @@ enum {
INTUOS3L,
INTUOS4S,
INTUOS4,
+ INTUOS4WL,
INTUOS4L,
INTUOS5S,
INTUOS5,
@@ -114,7 +118,6 @@ enum {
struct wacom_features {
const char *name;
- int pktlen;
int x_max;
int y_max;
int pressure_max;
@@ -127,8 +130,8 @@ struct wacom_features {
int device_type;
int x_phy;
int y_phy;
- unsigned char unit;
- unsigned char unitExpo;
+ unsigned unit;
+ int unitExpo;
int x_fuzz;
int y_fuzz;
int pressure_fuzz;
@@ -137,6 +140,9 @@ struct wacom_features {
unsigned touch_max;
int oVid;
int oPid;
+ int pktlen;
+ bool check_for_hid_type;
+ int hid_type;
};
struct wacom_shared {
@@ -150,16 +156,24 @@ struct wacom_shared {
struct wacom_wac {
char name[WACOM_NAME_MAX];
- unsigned char *data;
+ char pad_name[WACOM_NAME_MAX];
+ char bat_name[WACOM_NAME_MAX];
+ char ac_name[WACOM_NAME_MAX];
+ unsigned char data[WACOM_PKGLEN_MAX];
int tool[2];
int id[2];
__u32 serial[2];
struct wacom_features features;
struct wacom_shared *shared;
struct input_dev *input;
+ struct input_dev *pad_input;
int pid;
int battery_capacity;
int num_contacts_left;
+ int bat_charging;
+ int ps_connected;
+ u8 bt_features;
+ u8 bt_high_speed;
};
#endif
diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c
index ce4be3738d46..e5c7a969f28b 100644
--- a/drivers/hsi/clients/ssi_protocol.c
+++ b/drivers/hsi/clients/ssi_protocol.c
@@ -901,7 +901,7 @@ out:
ssip_free_data(msg);
}
-void ssip_port_event(struct hsi_client *cl, unsigned long event)
+static void ssip_port_event(struct hsi_client *cl, unsigned long event)
{
switch (event) {
case HSI_EVENT_START_RX:
@@ -1115,7 +1115,7 @@ static int ssi_protocol_probe(struct device *dev)
goto out;
}
- ssi->netdev = alloc_netdev(0, ifname, ssip_pn_setup);
+ ssi->netdev = alloc_netdev(0, ifname, NET_NAME_UNKNOWN, ssip_pn_setup);
if (!ssi->netdev) {
dev_err(dev, "No memory for netdev\n");
err = -ENOMEM;
diff --git a/drivers/hsi/controllers/omap_ssi.c b/drivers/hsi/controllers/omap_ssi.c
index 0fc7a7fd0140..bf0eace4cb67 100644
--- a/drivers/hsi/controllers/omap_ssi.c
+++ b/drivers/hsi/controllers/omap_ssi.c
@@ -148,14 +148,14 @@ static int __init ssi_debug_add_ctrl(struct hsi_controller *ssi)
/* SSI controller */
omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
- if (IS_ERR(omap_ssi->dir))
- return PTR_ERR(omap_ssi->dir);
+ if (!omap_ssi->dir)
+ return -ENOMEM;
debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
&ssi_regs_fops);
/* SSI GDD (DMA) */
dir = debugfs_create_dir("gdd", omap_ssi->dir);
- if (IS_ERR(dir))
+ if (!dir)
goto rback;
debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
@@ -163,7 +163,7 @@ static int __init ssi_debug_add_ctrl(struct hsi_controller *ssi)
rback:
debugfs_remove_recursive(omap_ssi->dir);
- return PTR_ERR(dir);
+ return -ENOMEM;
}
static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
@@ -353,12 +353,12 @@ static int __init ssi_add_controller(struct hsi_controller *ssi,
err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
if (err < 0)
goto out_err;
- omap_ssi->gdd_irq = platform_get_irq_byname(pd, "gdd_mpu");
- if (omap_ssi->gdd_irq < 0) {
+ err = platform_get_irq_byname(pd, "gdd_mpu");
+ if (err < 0) {
dev_err(&pd->dev, "GDD IRQ resource missing\n");
- err = omap_ssi->gdd_irq;
goto out_err;
}
+ omap_ssi->gdd_irq = err;
tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
(unsigned long)ssi);
err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index 29aea0b93360..4c0b5820581e 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -177,13 +177,13 @@ static int __init ssi_debug_add_port(struct omap_ssi_port *omap_port,
struct hsi_port *port = to_hsi_port(omap_port->dev);
dir = debugfs_create_dir(dev_name(omap_port->dev), dir);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
+ if (!dir)
+ return -ENOMEM;
omap_port->dir = dir;
debugfs_create_file("regs", S_IRUGO, dir, port, &ssi_port_regs_fops);
dir = debugfs_create_dir("sst", dir);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
+ if (!dir)
+ return -ENOMEM;
debugfs_create_file("divisor", S_IRUGO | S_IWUSR, dir, port,
&ssi_sst_div_fops);
@@ -1013,11 +1013,12 @@ static int __init ssi_port_irq(struct hsi_port *port,
struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
int err;
- omap_port->irq = platform_get_irq(pd, 0);
- if (omap_port->irq < 0) {
+ err = platform_get_irq(pd, 0);
+ if (err < 0) {
dev_err(&port->device, "Port IRQ resource missing\n");
- return omap_port->irq;
+ return err;
}
+ omap_port->irq = err;
tasklet_init(&omap_port->pio_tasklet, ssi_pio_tasklet,
(unsigned long)port);
err = devm_request_irq(&port->device, omap_port->irq, ssi_pio_isr,
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 284cf66489f4..531a593912ec 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -808,12 +808,8 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
*buffer_actual_len = packetlen;
- if (packetlen > bufferlen) {
- pr_err("Buffer too small - needed %d bytes but "
- "got space for only %d bytes\n",
- packetlen, bufferlen);
+ if (packetlen > bufferlen)
return -ENOBUFS;
- }
*requestid = desc.trans_id;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 02d3d85829f3..f00d048aa583 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -554,6 +554,17 @@ config SENSORS_IBMPEX
This driver can also be built as a module. If so, the module
will be called ibmpex.
+config SENSORS_IBMPOWERNV
+ tristate "IBM POWERNV platform sensors"
+ depends on PPC_POWERNV
+ default y
+ help
+ If you say yes here you get support for the temperature/fan/power
+ sensors on your PowerNV platform.
+
+ This driver can also be built as a module. If so, the module
+ will be called ibmpowernv.
+
config SENSORS_IIO_HWMON
tristate "Hwmon driver that uses channels specified via iio maps"
depends on IIO
@@ -608,6 +619,18 @@ config SENSORS_JC42
This driver can also be built as a module. If so, the module
will be called jc42.
+config SENSORS_POWR1220
+ tristate "Lattice POWR1220 Power Monitoring"
+ depends on I2C
+ default n
+ help
+ If you say yes here you get access to the hardware monitoring
+ functions of the Lattice POWR1220 isp Power Supply Monitoring,
+ Sequencing and Margining Controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called powr1220.
+
config SENSORS_LINEAGE
tristate "Lineage Compact Power Line Power Entry Module"
depends on I2C
@@ -882,8 +905,8 @@ config SENSORS_LM75
- NXP's LM75A
- ST Microelectronics STDS75
- TelCom (now Microchip) TCN75
- - Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175,
- TMP275
+ - Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75,
+ TMP175, TMP275
This driver supports driver model based binding through board
specific I2C device tables.
@@ -1061,7 +1084,7 @@ config SENSORS_NTC_THERMISTOR
Currently, this driver supports
NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333
- from Murata.
+ from Murata and B57330V2103 from EPCOS.
This driver can also be built as a module. If so, the module
will be called ntc-thermistor.
@@ -1082,8 +1105,8 @@ config SENSORS_NCT6775
select HWMON_VID
help
If you say yes here you get support for the hardware monitoring
- functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
- and compatible Super-I/O chips. This driver replaces the
+ functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
+ NCT6791D and compatible Super-I/O chips. This driver replaces the
w83627ehf driver for NCT6775F and NCT6776F.
This driver can also be built as a module. If so, the module
@@ -1105,6 +1128,17 @@ config SENSORS_PCF8591
source drivers/hwmon/pmbus/Kconfig
+config SENSORS_PWM_FAN
+ tristate "PWM fan"
+ depends on (PWM && OF) || COMPILE_TEST
+ help
+ If you say yes here you get support for fans connected to PWM lines.
+ The driver uses the generic PWM interface, thus it will work on a
+ variety of SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called pwm-fan.
+
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB
@@ -1393,6 +1427,17 @@ config SENSORS_TMP102
This driver can also be built as a module. If so, the module
will be called tmp102.
+config SENSORS_TMP103
+ tristate "Texas Instruments TMP103"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for Texas Instruments TMP103
+ sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called tmp103.
+
config SENSORS_TMP401
tristate "Texas Instruments TMP401 and compatibles"
depends on I2C
@@ -1408,7 +1453,7 @@ config SENSORS_TMP421
depends on I2C
help
If you say yes here you get support for Texas Instruments TMP421,
- TMP422 and TMP423 temperature sensor chips.
+ TMP422, TMP423, TMP441, and TMP442 temperature sensor chips.
This driver can also be built as a module. If so, the module
will be called tmp421.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3dc0f02f71d2..be28152c9848 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
+obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o
obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
obj-$(CONFIG_SENSORS_INA209) += ina209.o
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
@@ -120,6 +121,8 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
+obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
+obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
@@ -135,6 +138,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
+obj-$(CONFIG_SENSORS_TMP103) += tmp103.o
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index 5d501adc3e54..763490acc0df 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -39,7 +39,7 @@
static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW };
struct ad7414_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock; /* atomic read data updates */
char valid; /* !=0 if following fields are valid */
unsigned long next_update; /* In jiffies */
@@ -72,8 +72,8 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value)
static struct ad7414_data *ad7414_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ad7414_data *data = i2c_get_clientdata(client);
+ struct ad7414_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->lock);
@@ -127,8 +127,8 @@ static ssize_t set_max_min(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ad7414_data *data = i2c_get_clientdata(client);
+ struct ad7414_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int index = to_sensor_dev_attr(attr)->index;
u8 reg = AD7414_REG_LIMIT[index];
long temp;
@@ -164,7 +164,7 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4);
-static struct attribute *ad7414_attributes[] = {
+static struct attribute *ad7414_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -173,27 +173,25 @@ static struct attribute *ad7414_attributes[] = {
NULL
};
-static const struct attribute_group ad7414_group = {
- .attrs = ad7414_attributes,
-};
+ATTRIBUTE_GROUPS(ad7414);
static int ad7414_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
+ struct device *dev = &client->dev;
struct ad7414_data *data;
+ struct device *hwmon_dev;
int conf;
- int err;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_READ_WORD_DATA))
return -EOPNOTSUPP;
- data = devm_kzalloc(&client->dev, sizeof(struct ad7414_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct ad7414_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->lock);
dev_info(&client->dev, "chip found\n");
@@ -201,38 +199,16 @@ static int ad7414_probe(struct i2c_client *client,
/* Make sure the chip is powered up. */
conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF);
if (conf < 0)
- dev_warn(&client->dev,
- "ad7414_probe unable to read config register.\n");
+ dev_warn(dev, "ad7414_probe unable to read config register.\n");
else {
conf &= ~(1 << 7);
i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf);
}
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &ad7414_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &ad7414_group);
- return err;
-}
-
-static int ad7414_remove(struct i2c_client *client)
-{
- struct ad7414_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ad7414_group);
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+ client->name,
+ data, ad7414_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id ad7414_id[] = {
@@ -246,7 +222,6 @@ static struct i2c_driver ad7414_driver = {
.name = "ad7414",
},
.probe = ad7414_probe,
- .remove = ad7414_remove,
.id_table = ad7414_id,
};
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 57d4a6295675..a01b731ba5d7 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -44,8 +44,7 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN,
AD7418_REG_TEMP_OS };
struct ad7418_data {
- struct device *hwmon_dev;
- struct attribute_group attrs;
+ struct i2c_client *client;
enum chips type;
struct mutex lock;
int adc_max; /* number of ADC channels */
@@ -55,48 +54,10 @@ struct ad7418_data {
u16 in[4];
};
-static int ad7418_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int ad7418_remove(struct i2c_client *client);
-
-static const struct i2c_device_id ad7418_id[] = {
- { "ad7416", ad7416 },
- { "ad7417", ad7417 },
- { "ad7418", ad7418 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ad7418_id);
-
-static struct i2c_driver ad7418_driver = {
- .driver = {
- .name = "ad7418",
- },
- .probe = ad7418_probe,
- .remove = ad7418_remove,
- .id_table = ad7418_id,
-};
-
-static void ad7418_init_client(struct i2c_client *client)
-{
- struct ad7418_data *data = i2c_get_clientdata(client);
-
- int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
- if (reg < 0) {
- dev_err(&client->dev, "cannot read configuration register\n");
- } else {
- dev_info(&client->dev, "configuring for mode 1\n");
- i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
-
- if (data->type == ad7417 || data->type == ad7418)
- i2c_smbus_write_byte_data(client,
- AD7418_REG_CONF2, 0x00);
- }
-}
-
static struct ad7418_data *ad7418_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ad7418_data *data = i2c_get_clientdata(client);
+ struct ad7418_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->lock);
@@ -165,8 +126,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct ad7418_data *data = i2c_get_clientdata(client);
+ struct ad7418_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
int ret = kstrtol(buf, 10, &temp);
@@ -193,14 +154,15 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3);
-static struct attribute *ad7416_attributes[] = {
+static struct attribute *ad7416_attrs[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL
};
+ATTRIBUTE_GROUPS(ad7416);
-static struct attribute *ad7417_attributes[] = {
+static struct attribute *ad7417_attrs[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -210,83 +172,100 @@ static struct attribute *ad7417_attributes[] = {
&sensor_dev_attr_in4_input.dev_attr.attr,
NULL
};
+ATTRIBUTE_GROUPS(ad7417);
-static struct attribute *ad7418_attributes[] = {
+static struct attribute *ad7418_attrs[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
NULL
};
+ATTRIBUTE_GROUPS(ad7418);
+
+static void ad7418_init_client(struct i2c_client *client)
+{
+ struct ad7418_data *data = i2c_get_clientdata(client);
+
+ int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+ if (reg < 0) {
+ dev_err(&client->dev, "cannot read configuration register\n");
+ } else {
+ dev_info(&client->dev, "configuring for mode 1\n");
+ i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe);
+
+ if (data->type == ad7417 || data->type == ad7418)
+ i2c_smbus_write_byte_data(client,
+ AD7418_REG_CONF2, 0x00);
+ }
+}
static int ad7418_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct i2c_adapter *adapter = client->adapter;
struct ad7418_data *data;
- int err;
+ struct device *hwmon_dev;
+ const struct attribute_group **attr_groups = NULL;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
- data = devm_kzalloc(&client->dev, sizeof(struct ad7418_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
+ data->client = client;
data->type = id->driver_data;
switch (data->type) {
case ad7416:
data->adc_max = 0;
- data->attrs.attrs = ad7416_attributes;
+ attr_groups = ad7416_groups;
break;
case ad7417:
data->adc_max = 4;
- data->attrs.attrs = ad7417_attributes;
+ attr_groups = ad7417_groups;
break;
case ad7418:
data->adc_max = 1;
- data->attrs.attrs = ad7418_attributes;
+ attr_groups = ad7418_groups;
break;
}
- dev_info(&client->dev, "%s chip found\n", client->name);
+ dev_info(dev, "%s chip found\n", client->name);
/* Initialize the AD7418 chip */
ad7418_init_client(client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &data->attrs);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+ client->name,
+ data, attr_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static int ad7418_remove(struct i2c_client *client)
-{
- struct ad7418_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- return 0;
-}
+static const struct i2c_device_id ad7418_id[] = {
+ { "ad7416", ad7416 },
+ { "ad7417", ad7417 },
+ { "ad7418", ad7418 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ad7418_id);
+
+static struct i2c_driver ad7418_driver = {
+ .driver = {
+ .name = "ad7418",
+ },
+ .probe = ad7418_probe,
+ .id_table = ad7418_id,
+};
module_i2c_driver(ad7418_driver);
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index d74241bb278c..1fdcc3e703b9 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -98,41 +98,63 @@ struct adm1021_data {
u8 remote_temp_offset_prec;
};
-static int adm1021_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm1021_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static void adm1021_init_client(struct i2c_client *client);
-static struct adm1021_data *adm1021_update_device(struct device *dev);
-
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
static bool read_only;
+static struct adm1021_data *adm1021_update_device(struct device *dev)
+{
+ struct adm1021_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
-static const struct i2c_device_id adm1021_id[] = {
- { "adm1021", adm1021 },
- { "adm1023", adm1023 },
- { "max1617", max1617 },
- { "max1617a", max1617a },
- { "thmc10", thmc10 },
- { "lm84", lm84 },
- { "gl523sm", gl523sm },
- { "mc1066", mc1066 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1021_id);
+ mutex_lock(&data->update_lock);
-/* This is the driver that will be inserted */
-static struct i2c_driver adm1021_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1021",
- },
- .probe = adm1021_probe,
- .id_table = adm1021_id,
- .detect = adm1021_detect,
- .address_list = normal_i2c,
-};
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ int i;
+
+ dev_dbg(dev, "Starting adm1021 update\n");
+
+ for (i = 0; i < 2; i++) {
+ data->temp[i] = 1000 *
+ (s8) i2c_smbus_read_byte_data(
+ client, ADM1021_REG_TEMP(i));
+ data->temp_max[i] = 1000 *
+ (s8) i2c_smbus_read_byte_data(
+ client, ADM1021_REG_TOS_R(i));
+ if (data->type != lm84) {
+ data->temp_min[i] = 1000 *
+ (s8) i2c_smbus_read_byte_data(client,
+ ADM1021_REG_THYST_R(i));
+ }
+ }
+ data->alarms = i2c_smbus_read_byte_data(client,
+ ADM1021_REG_STATUS) & 0x7c;
+ if (data->type == adm1023) {
+ /*
+ * The ADM1023 provides 3 extra bits of precision for
+ * the remote sensor in extra registers.
+ */
+ data->temp[1] += 125 * (i2c_smbus_read_byte_data(
+ client, ADM1023_REG_REM_TEMP_PREC) >> 5);
+ data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
+ client, ADM1023_REG_REM_TOS_PREC) >> 5);
+ data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
+ client, ADM1023_REG_REM_THYST_PREC) >> 5);
+ data->remote_temp_offset =
+ i2c_smbus_read_byte_data(client,
+ ADM1023_REG_REM_OFFSET);
+ data->remote_temp_offset_prec =
+ i2c_smbus_read_byte_data(client,
+ ADM1023_REG_REM_OFFSET_PREC);
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
static ssize_t show_temp(struct device *dev,
struct device_attribute *devattr, char *buf)
@@ -411,6 +433,15 @@ static int adm1021_detect(struct i2c_client *client,
return 0;
}
+static void adm1021_init_client(struct i2c_client *client)
+{
+ /* Enable ADC and disable suspend mode */
+ i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
+ i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
+ /* Set Conversion rate to 1/sec (this can be tinkered with) */
+ i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
+}
+
static int adm1021_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -440,69 +471,29 @@ static int adm1021_probe(struct i2c_client *client,
return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static void adm1021_init_client(struct i2c_client *client)
-{
- /* Enable ADC and disable suspend mode */
- i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
- i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
- /* Set Conversion rate to 1/sec (this can be tinkered with) */
- i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
-}
-
-static struct adm1021_data *adm1021_update_device(struct device *dev)
-{
- struct adm1021_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- int i;
-
- dev_dbg(dev, "Starting adm1021 update\n");
-
- for (i = 0; i < 2; i++) {
- data->temp[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(
- client, ADM1021_REG_TEMP(i));
- data->temp_max[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(
- client, ADM1021_REG_TOS_R(i));
- if (data->type != lm84) {
- data->temp_min[i] = 1000 *
- (s8) i2c_smbus_read_byte_data(client,
- ADM1021_REG_THYST_R(i));
- }
- }
- data->alarms = i2c_smbus_read_byte_data(client,
- ADM1021_REG_STATUS) & 0x7c;
- if (data->type == adm1023) {
- /*
- * The ADM1023 provides 3 extra bits of precision for
- * the remote sensor in extra registers.
- */
- data->temp[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_TEMP_PREC) >> 5);
- data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_TOS_PREC) >> 5);
- data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
- client, ADM1023_REG_REM_THYST_PREC) >> 5);
- data->remote_temp_offset =
- i2c_smbus_read_byte_data(client,
- ADM1023_REG_REM_OFFSET);
- data->remote_temp_offset_prec =
- i2c_smbus_read_byte_data(client,
- ADM1023_REG_REM_OFFSET_PREC);
- }
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1021_id[] = {
+ { "adm1021", adm1021 },
+ { "adm1023", adm1023 },
+ { "max1617", max1617 },
+ { "max1617a", max1617a },
+ { "thmc10", thmc10 },
+ { "lm84", lm84 },
+ { "gl523sm", gl523sm },
+ { "mc1066", mc1066 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm1021_id);
- return data;
-}
+static struct i2c_driver adm1021_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm1021",
+ },
+ .probe = adm1021_probe,
+ .id_table = adm1021_id,
+ .detect = adm1021_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm1021_driver);
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 9ffc4c8ca8b5..d6c767ace916 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -103,46 +103,12 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
(val) + 500) / 1000))
/*
- * Functions declaration
- */
-
-static int adm1025_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm1025_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static void adm1025_init_client(struct i2c_client *client);
-static int adm1025_remove(struct i2c_client *client);
-static struct adm1025_data *adm1025_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id adm1025_id[] = {
- { "adm1025", adm1025 },
- { "ne1619", ne1619 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1025_id);
-
-static struct i2c_driver adm1025_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1025",
- },
- .probe = adm1025_probe,
- .remove = adm1025_remove,
- .id_table = adm1025_id,
- .detect = adm1025_detect,
- .address_list = normal_i2c,
-};
-
-/*
* Client data (each client gets its own)
*/
struct adm1025_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -158,6 +124,51 @@ struct adm1025_data {
u8 vrm;
};
+static struct adm1025_data *adm1025_update_device(struct device *dev)
+{
+ struct adm1025_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
+ int i;
+
+ dev_dbg(&client->dev, "Updating data.\n");
+ for (i = 0; i < 6; i++) {
+ data->in[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_IN(i));
+ data->in_min[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_IN_MIN(i));
+ data->in_max[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_IN_MAX(i));
+ }
+ for (i = 0; i < 2; i++) {
+ data->temp[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_TEMP(i));
+ data->temp_min[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_TEMP_LOW(i));
+ data->temp_max[i] = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_TEMP_HIGH(i));
+ }
+ data->alarms = i2c_smbus_read_byte_data(client,
+ ADM1025_REG_STATUS1)
+ | (i2c_smbus_read_byte_data(client,
+ ADM1025_REG_STATUS2) << 8);
+ data->vid = (i2c_smbus_read_byte_data(client,
+ ADM1025_REG_VID) & 0x0f)
+ | ((i2c_smbus_read_byte_data(client,
+ ADM1025_REG_VID4) & 0x01) << 4);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
/*
* Sysfs stuff
*/
@@ -217,8 +228,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1025_data *data = i2c_get_clientdata(client);
+ struct adm1025_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -238,8 +249,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1025_data *data = i2c_get_clientdata(client);
+ struct adm1025_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -273,8 +284,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1025_data *data = i2c_get_clientdata(client);
+ struct adm1025_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -294,8 +305,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1025_data *data = i2c_get_clientdata(client);
+ struct adm1025_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -371,6 +382,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
@@ -470,51 +484,6 @@ static int adm1025_detect(struct i2c_client *client,
return 0;
}
-static int adm1025_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct adm1025_data *data;
- int err;
- u8 config;
-
- data = devm_kzalloc(&client->dev, sizeof(struct adm1025_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- /* Initialize the ADM1025 chip */
- adm1025_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &adm1025_group);
- if (err)
- return err;
-
- /* Pin 11 is either in4 (+12V) or VID4 */
- config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
- if (!(config & 0x20)) {
- err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4);
- if (err)
- goto exit_remove;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &adm1025_group);
- sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
- return err;
-}
-
static void adm1025_init_client(struct i2c_client *client)
{
u8 reg;
@@ -557,61 +526,54 @@ static void adm1025_init_client(struct i2c_client *client)
(reg&0x7E)|0x01);
}
-static int adm1025_remove(struct i2c_client *client)
+static int adm1025_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct adm1025_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adm1025_group);
- sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4);
-
- return 0;
-}
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1025_data *data;
+ u8 config;
-static struct adm1025_data *adm1025_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1025_data *data = i2c_get_clientdata(client);
+ data = devm_kzalloc(dev, sizeof(struct adm1025_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- mutex_lock(&data->update_lock);
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
- if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
- int i;
+ /* Initialize the ADM1025 chip */
+ adm1025_init_client(client);
- dev_dbg(&client->dev, "Updating data.\n");
- for (i = 0; i < 6; i++) {
- data->in[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_IN(i));
- data->in_min[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_IN_MIN(i));
- data->in_max[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_IN_MAX(i));
- }
- for (i = 0; i < 2; i++) {
- data->temp[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_TEMP(i));
- data->temp_min[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_TEMP_LOW(i));
- data->temp_max[i] = i2c_smbus_read_byte_data(client,
- ADM1025_REG_TEMP_HIGH(i));
- }
- data->alarms = i2c_smbus_read_byte_data(client,
- ADM1025_REG_STATUS1)
- | (i2c_smbus_read_byte_data(client,
- ADM1025_REG_STATUS2) << 8);
- data->vid = (i2c_smbus_read_byte_data(client,
- ADM1025_REG_VID) & 0x0f)
- | ((i2c_smbus_read_byte_data(client,
- ADM1025_REG_VID4) & 0x01) << 4);
+ /* sysfs hooks */
+ data->groups[0] = &adm1025_group;
+ /* Pin 11 is either in4 (+12V) or VID4 */
+ config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
+ if (!(config & 0x20))
+ data->groups[1] = &adm1025_group_in4;
- data->last_updated = jiffies;
- data->valid = 1;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1025_id[] = {
+ { "adm1025", adm1025 },
+ { "ne1619", ne1619 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm1025_id);
- return data;
-}
+static struct i2c_driver adm1025_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm1025",
+ },
+ .probe = adm1025_probe,
+ .id_table = adm1025_id,
+ .detect = adm1025_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm1025_driver);
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index b3498acb9ab4..e67b9a50ac7c 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -266,7 +266,8 @@ struct pwm_data {
};
struct adm1026_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
int valid; /* !=0 if following fields are valid */
@@ -298,37 +299,6 @@ struct adm1026_data {
u8 config3; /* Register value */
};
-static int adm1026_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm1026_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int adm1026_remove(struct i2c_client *client);
-static int adm1026_read_value(struct i2c_client *client, u8 reg);
-static int adm1026_write_value(struct i2c_client *client, u8 reg, int value);
-static void adm1026_print_gpio(struct i2c_client *client);
-static void adm1026_fixup_gpio(struct i2c_client *client);
-static struct adm1026_data *adm1026_update_device(struct device *dev);
-static void adm1026_init_client(struct i2c_client *client);
-
-
-static const struct i2c_device_id adm1026_id[] = {
- { "adm1026", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1026_id);
-
-static struct i2c_driver adm1026_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1026",
- },
- .probe = adm1026_probe,
- .remove = adm1026_remove,
- .id_table = adm1026_id,
- .detect = adm1026_detect,
- .address_list = normal_i2c,
-};
-
static int adm1026_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -357,212 +327,10 @@ static int adm1026_write_value(struct i2c_client *client, u8 reg, int value)
return res;
}
-static void adm1026_init_client(struct i2c_client *client)
-{
- int value, i;
- struct adm1026_data *data = i2c_get_clientdata(client);
-
- dev_dbg(&client->dev, "Initializing device\n");
- /* Read chip config */
- data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
- data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
- data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
-
- /* Inform user of chip config */
- dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
- data->config1);
- if ((data->config1 & CFG1_MONITOR) == 0) {
- dev_dbg(&client->dev,
- "Monitoring not currently enabled.\n");
- }
- if (data->config1 & CFG1_INT_ENABLE) {
- dev_dbg(&client->dev,
- "SMBALERT interrupts are enabled.\n");
- }
- if (data->config1 & CFG1_AIN8_9) {
- dev_dbg(&client->dev,
- "in8 and in9 enabled. temp3 disabled.\n");
- } else {
- dev_dbg(&client->dev,
- "temp3 enabled. in8 and in9 disabled.\n");
- }
- if (data->config1 & CFG1_THERM_HOT) {
- dev_dbg(&client->dev,
- "Automatic THERM, PWM, and temp limits enabled.\n");
- }
-
- if (data->config3 & CFG3_GPIO16_ENABLE) {
- dev_dbg(&client->dev,
- "GPIO16 enabled. THERM pin disabled.\n");
- } else {
- dev_dbg(&client->dev,
- "THERM pin enabled. GPIO16 disabled.\n");
- }
- if (data->config3 & CFG3_VREF_250)
- dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
- else
- dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
- /* Read and pick apart the existing GPIO configuration */
- value = 0;
- for (i = 0; i <= 15; ++i) {
- if ((i & 0x03) == 0) {
- value = adm1026_read_value(client,
- ADM1026_REG_GPIO_CFG_0_3 + i / 4);
- }
- data->gpio_config[i] = value & 0x03;
- value >>= 2;
- }
- data->gpio_config[16] = (data->config3 >> 6) & 0x03;
-
- /* ... and then print it */
- adm1026_print_gpio(client);
-
- /*
- * If the user asks us to reprogram the GPIO config, then
- * do it now.
- */
- if (gpio_input[0] != -1 || gpio_output[0] != -1
- || gpio_inverted[0] != -1 || gpio_normal[0] != -1
- || gpio_fan[0] != -1) {
- adm1026_fixup_gpio(client);
- }
-
- /*
- * WE INTENTIONALLY make no changes to the limits,
- * offsets, pwms, fans and zones. If they were
- * configured, we don't want to mess with them.
- * If they weren't, the default is 100% PWM, no
- * control and will suffice until 'sensors -s'
- * can be run by the user. We DO set the default
- * value for pwm1.auto_pwm_min to its maximum
- * so that enabling automatic pwm fan control
- * without first setting a value for pwm1.auto_pwm_min
- * will not result in potentially dangerous fan speed decrease.
- */
- data->pwm1.auto_pwm_min = 255;
- /* Start monitoring */
- value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
- /* Set MONITOR, clear interrupt acknowledge and s/w reset */
- value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
- dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
- data->config1 = value;
- adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
-
- /* initialize fan_div[] to hardware defaults */
- value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
- (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
- for (i = 0; i <= 7; ++i) {
- data->fan_div[i] = DIV_FROM_REG(value & 0x03);
- value >>= 2;
- }
-}
-
-static void adm1026_print_gpio(struct i2c_client *client)
-{
- struct adm1026_data *data = i2c_get_clientdata(client);
- int i;
-
- dev_dbg(&client->dev, "GPIO config is:\n");
- for (i = 0; i <= 7; ++i) {
- if (data->config2 & (1 << i)) {
- dev_dbg(&client->dev, "\t%sGP%s%d\n",
- data->gpio_config[i] & 0x02 ? "" : "!",
- data->gpio_config[i] & 0x01 ? "OUT" : "IN",
- i);
- } else {
- dev_dbg(&client->dev, "\tFAN%d\n", i);
- }
- }
- for (i = 8; i <= 15; ++i) {
- dev_dbg(&client->dev, "\t%sGP%s%d\n",
- data->gpio_config[i] & 0x02 ? "" : "!",
- data->gpio_config[i] & 0x01 ? "OUT" : "IN",
- i);
- }
- if (data->config3 & CFG3_GPIO16_ENABLE) {
- dev_dbg(&client->dev, "\t%sGP%s16\n",
- data->gpio_config[16] & 0x02 ? "" : "!",
- data->gpio_config[16] & 0x01 ? "OUT" : "IN");
- } else {
- /* GPIO16 is THERM */
- dev_dbg(&client->dev, "\tTHERM\n");
- }
-}
-
-static void adm1026_fixup_gpio(struct i2c_client *client)
-{
- struct adm1026_data *data = i2c_get_clientdata(client);
- int i;
- int value;
-
- /* Make the changes requested. */
- /*
- * We may need to unlock/stop monitoring or soft-reset the
- * chip before we can make changes. This hasn't been
- * tested much. FIXME
- */
-
- /* Make outputs */
- for (i = 0; i <= 16; ++i) {
- if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
- data->gpio_config[gpio_output[i]] |= 0x01;
- /* if GPIO0-7 is output, it isn't a FAN tach */
- if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
- data->config2 |= 1 << gpio_output[i];
- }
-
- /* Input overrides output */
- for (i = 0; i <= 16; ++i) {
- if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
- data->gpio_config[gpio_input[i]] &= ~0x01;
- /* if GPIO0-7 is input, it isn't a FAN tach */
- if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
- data->config2 |= 1 << gpio_input[i];
- }
-
- /* Inverted */
- for (i = 0; i <= 16; ++i) {
- if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
- data->gpio_config[gpio_inverted[i]] &= ~0x02;
- }
-
- /* Normal overrides inverted */
- for (i = 0; i <= 16; ++i) {
- if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
- data->gpio_config[gpio_normal[i]] |= 0x02;
- }
-
- /* Fan overrides input and output */
- for (i = 0; i <= 7; ++i) {
- if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
- data->config2 &= ~(1 << gpio_fan[i]);
- }
-
- /* Write new configs to registers */
- adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
- data->config3 = (data->config3 & 0x3f)
- | ((data->gpio_config[16] & 0x03) << 6);
- adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
- for (i = 15, value = 0; i >= 0; --i) {
- value <<= 2;
- value |= data->gpio_config[i] & 0x03;
- if ((i & 0x03) == 0) {
- adm1026_write_value(client,
- ADM1026_REG_GPIO_CFG_0_3 + i/4,
- value);
- value = 0;
- }
- }
-
- /* Print the new config */
- adm1026_print_gpio(client);
-}
-
-
static struct adm1026_data *adm1026_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int i;
long value, alarms, gpio;
@@ -728,8 +496,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -756,8 +524,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -815,8 +583,8 @@ static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -840,8 +608,8 @@ static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr,
static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -888,8 +656,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -923,8 +691,8 @@ fan_offset(8);
/* Adjust fan_min to account for new fan divisor */
static void fixup_fan_min(struct device *dev, int fan, int old_div)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int new_min;
int new_div = data->fan_div[fan];
@@ -952,8 +720,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int orig_div, new_div;
int err;
@@ -1024,8 +792,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1053,8 +821,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1097,8 +865,8 @@ static ssize_t set_temp_offset(struct device *dev,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1153,8 +921,8 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1192,8 +960,8 @@ static ssize_t show_temp_crit_enable(struct device *dev,
static ssize_t set_temp_crit_enable(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1233,8 +1001,8 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1268,8 +1036,8 @@ static ssize_t set_analog_out_reg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1317,6 +1085,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
@@ -1378,8 +1149,8 @@ static ssize_t show_alarm_mask(struct device *dev,
static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long mask;
long val;
int err;
@@ -1420,8 +1191,8 @@ static ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
static ssize_t set_gpio(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long gpio;
long val;
int err;
@@ -1453,8 +1224,8 @@ static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr,
static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long mask;
long val;
int err;
@@ -1487,8 +1258,8 @@ static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr,
static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
if (data->pwm1.enable == 1) {
long val;
@@ -1517,8 +1288,8 @@ static ssize_t set_auto_pwm_min(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1553,8 +1324,8 @@ static ssize_t show_pwm_enable(struct device *dev,
static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1026_data *data = i2c_get_clientdata(client);
+ struct adm1026_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int old_enable;
unsigned long val;
int err;
@@ -1829,18 +1600,220 @@ static int adm1026_detect(struct i2c_client *client,
return 0;
}
+static void adm1026_print_gpio(struct i2c_client *client)
+{
+ struct adm1026_data *data = i2c_get_clientdata(client);
+ int i;
+
+ dev_dbg(&client->dev, "GPIO config is:\n");
+ for (i = 0; i <= 7; ++i) {
+ if (data->config2 & (1 << i)) {
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
+ data->gpio_config[i] & 0x02 ? "" : "!",
+ data->gpio_config[i] & 0x01 ? "OUT" : "IN",
+ i);
+ } else {
+ dev_dbg(&client->dev, "\tFAN%d\n", i);
+ }
+ }
+ for (i = 8; i <= 15; ++i) {
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
+ data->gpio_config[i] & 0x02 ? "" : "!",
+ data->gpio_config[i] & 0x01 ? "OUT" : "IN",
+ i);
+ }
+ if (data->config3 & CFG3_GPIO16_ENABLE) {
+ dev_dbg(&client->dev, "\t%sGP%s16\n",
+ data->gpio_config[16] & 0x02 ? "" : "!",
+ data->gpio_config[16] & 0x01 ? "OUT" : "IN");
+ } else {
+ /* GPIO16 is THERM */
+ dev_dbg(&client->dev, "\tTHERM\n");
+ }
+}
+
+static void adm1026_fixup_gpio(struct i2c_client *client)
+{
+ struct adm1026_data *data = i2c_get_clientdata(client);
+ int i;
+ int value;
+
+ /* Make the changes requested. */
+ /*
+ * We may need to unlock/stop monitoring or soft-reset the
+ * chip before we can make changes. This hasn't been
+ * tested much. FIXME
+ */
+
+ /* Make outputs */
+ for (i = 0; i <= 16; ++i) {
+ if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
+ data->gpio_config[gpio_output[i]] |= 0x01;
+ /* if GPIO0-7 is output, it isn't a FAN tach */
+ if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
+ data->config2 |= 1 << gpio_output[i];
+ }
+
+ /* Input overrides output */
+ for (i = 0; i <= 16; ++i) {
+ if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
+ data->gpio_config[gpio_input[i]] &= ~0x01;
+ /* if GPIO0-7 is input, it isn't a FAN tach */
+ if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
+ data->config2 |= 1 << gpio_input[i];
+ }
+
+ /* Inverted */
+ for (i = 0; i <= 16; ++i) {
+ if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
+ data->gpio_config[gpio_inverted[i]] &= ~0x02;
+ }
+
+ /* Normal overrides inverted */
+ for (i = 0; i <= 16; ++i) {
+ if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
+ data->gpio_config[gpio_normal[i]] |= 0x02;
+ }
+
+ /* Fan overrides input and output */
+ for (i = 0; i <= 7; ++i) {
+ if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
+ data->config2 &= ~(1 << gpio_fan[i]);
+ }
+
+ /* Write new configs to registers */
+ adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2);
+ data->config3 = (data->config3 & 0x3f)
+ | ((data->gpio_config[16] & 0x03) << 6);
+ adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
+ for (i = 15, value = 0; i >= 0; --i) {
+ value <<= 2;
+ value |= data->gpio_config[i] & 0x03;
+ if ((i & 0x03) == 0) {
+ adm1026_write_value(client,
+ ADM1026_REG_GPIO_CFG_0_3 + i/4,
+ value);
+ value = 0;
+ }
+ }
+
+ /* Print the new config */
+ adm1026_print_gpio(client);
+}
+
+static void adm1026_init_client(struct i2c_client *client)
+{
+ int value, i;
+ struct adm1026_data *data = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "Initializing device\n");
+ /* Read chip config */
+ data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
+ data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
+ data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
+
+ /* Inform user of chip config */
+ dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
+ data->config1);
+ if ((data->config1 & CFG1_MONITOR) == 0) {
+ dev_dbg(&client->dev,
+ "Monitoring not currently enabled.\n");
+ }
+ if (data->config1 & CFG1_INT_ENABLE) {
+ dev_dbg(&client->dev,
+ "SMBALERT interrupts are enabled.\n");
+ }
+ if (data->config1 & CFG1_AIN8_9) {
+ dev_dbg(&client->dev,
+ "in8 and in9 enabled. temp3 disabled.\n");
+ } else {
+ dev_dbg(&client->dev,
+ "temp3 enabled. in8 and in9 disabled.\n");
+ }
+ if (data->config1 & CFG1_THERM_HOT) {
+ dev_dbg(&client->dev,
+ "Automatic THERM, PWM, and temp limits enabled.\n");
+ }
+
+ if (data->config3 & CFG3_GPIO16_ENABLE) {
+ dev_dbg(&client->dev,
+ "GPIO16 enabled. THERM pin disabled.\n");
+ } else {
+ dev_dbg(&client->dev,
+ "THERM pin enabled. GPIO16 disabled.\n");
+ }
+ if (data->config3 & CFG3_VREF_250)
+ dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
+ else
+ dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
+ /* Read and pick apart the existing GPIO configuration */
+ value = 0;
+ for (i = 0; i <= 15; ++i) {
+ if ((i & 0x03) == 0) {
+ value = adm1026_read_value(client,
+ ADM1026_REG_GPIO_CFG_0_3 + i / 4);
+ }
+ data->gpio_config[i] = value & 0x03;
+ value >>= 2;
+ }
+ data->gpio_config[16] = (data->config3 >> 6) & 0x03;
+
+ /* ... and then print it */
+ adm1026_print_gpio(client);
+
+ /*
+ * If the user asks us to reprogram the GPIO config, then
+ * do it now.
+ */
+ if (gpio_input[0] != -1 || gpio_output[0] != -1
+ || gpio_inverted[0] != -1 || gpio_normal[0] != -1
+ || gpio_fan[0] != -1) {
+ adm1026_fixup_gpio(client);
+ }
+
+ /*
+ * WE INTENTIONALLY make no changes to the limits,
+ * offsets, pwms, fans and zones. If they were
+ * configured, we don't want to mess with them.
+ * If they weren't, the default is 100% PWM, no
+ * control and will suffice until 'sensors -s'
+ * can be run by the user. We DO set the default
+ * value for pwm1.auto_pwm_min to its maximum
+ * so that enabling automatic pwm fan control
+ * without first setting a value for pwm1.auto_pwm_min
+ * will not result in potentially dangerous fan speed decrease.
+ */
+ data->pwm1.auto_pwm_min = 255;
+ /* Start monitoring */
+ value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
+ /* Set MONITOR, clear interrupt acknowledge and s/w reset */
+ value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
+ dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
+ data->config1 = value;
+ adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
+
+ /* initialize fan_div[] to hardware defaults */
+ value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
+ (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
+ for (i = 0; i <= 7; ++i) {
+ data->fan_div[i] = DIV_FROM_REG(value & 0x03);
+ value >>= 2;
+ }
+}
+
static int adm1026_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct adm1026_data *data;
- int err;
- data = devm_kzalloc(&client->dev, sizeof(struct adm1026_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Set the VRM version */
@@ -1849,48 +1822,34 @@ static int adm1026_probe(struct i2c_client *client,
/* Initialize the ADM1026 chip */
adm1026_init_client(client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &adm1026_group);
- if (err)
- return err;
+ /* sysfs hooks */
+ data->groups[0] = &adm1026_group;
if (data->config1 & CFG1_AIN8_9)
- err = sysfs_create_group(&client->dev.kobj,
- &adm1026_group_in8_9);
+ data->groups[1] = &adm1026_group_in8_9;
else
- err = sysfs_create_group(&client->dev.kobj,
- &adm1026_group_temp3);
- if (err)
- goto exitremove;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exitremove;
- }
-
- return 0;
+ data->groups[1] = &adm1026_group_temp3;
- /* Error out and cleanup code */
-exitremove:
- sysfs_remove_group(&client->dev.kobj, &adm1026_group);
- if (data->config1 & CFG1_AIN8_9)
- sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
- else
- sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static int adm1026_remove(struct i2c_client *client)
-{
- struct adm1026_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adm1026_group);
- if (data->config1 & CFG1_AIN8_9)
- sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9);
- else
- sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3);
- return 0;
-}
+static const struct i2c_device_id adm1026_id[] = {
+ { "adm1026", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm1026_id);
+
+static struct i2c_driver adm1026_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm1026",
+ },
+ .probe = adm1026_probe,
+ .id_table = adm1026_id,
+ .detect = adm1026_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm1026_driver);
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 2804571b269e..8c5cdb560258 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -106,45 +106,11 @@ static const u8 ADM1029_REG_FAN_DIV[] = {
};
/*
- * Functions declaration
- */
-
-static int adm1029_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm1029_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int adm1029_remove(struct i2c_client *client);
-static struct adm1029_data *adm1029_update_device(struct device *dev);
-static int adm1029_init_client(struct i2c_client *client);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id adm1029_id[] = {
- { "adm1029", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1029_id);
-
-static struct i2c_driver adm1029_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1029",
- },
- .probe = adm1029_probe,
- .remove = adm1029_remove,
- .id_table = adm1029_id,
- .detect = adm1029_detect,
- .address_list = normal_i2c,
-};
-
-/*
* Client data (each client gets its own)
*/
struct adm1029_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -156,6 +122,50 @@ struct adm1029_data {
};
/*
+ * function that update the status of the chips (temperature for example)
+ */
+static struct adm1029_data *adm1029_update_device(struct device *dev)
+{
+ struct adm1029_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+
+ mutex_lock(&data->update_lock);
+ /*
+ * Use the "cache" Luke, don't recheck values
+ * if there are already checked not a long time later
+ */
+ if (time_after(jiffies, data->last_updated + HZ * 2)
+ || !data->valid) {
+ int nr;
+
+ dev_dbg(&client->dev, "Updating adm1029 data\n");
+
+ for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
+ data->temp[nr] =
+ i2c_smbus_read_byte_data(client,
+ ADM1029_REG_TEMP[nr]);
+ }
+ for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
+ data->fan[nr] =
+ i2c_smbus_read_byte_data(client,
+ ADM1029_REG_FAN[nr]);
+ }
+ for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
+ data->fan_div[nr] =
+ i2c_smbus_read_byte_data(client,
+ ADM1029_REG_FAN_DIV[nr]);
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+/*
* Sysfs stuff
*/
@@ -197,8 +207,8 @@ show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
static ssize_t set_fan_div(struct device *dev,
struct device_attribute *devattr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1029_data *data = i2c_get_clientdata(client);
+ struct adm1029_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
u8 reg;
long val;
@@ -270,7 +280,7 @@ static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
show_fan_div, set_fan_div, 1);
-static struct attribute *adm1029_attributes[] = {
+static struct attribute *adm1029_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -289,9 +299,7 @@ static struct attribute *adm1029_attributes[] = {
NULL
};
-static const struct attribute_group adm1029_group = {
- .attrs = adm1029_attributes,
-};
+ATTRIBUTE_GROUPS(adm1029);
/*
* Real code
@@ -340,48 +348,10 @@ static int adm1029_detect(struct i2c_client *client,
return 0;
}
-static int adm1029_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct adm1029_data *data;
- int err;
-
- data = devm_kzalloc(&client->dev, sizeof(struct adm1029_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- /*
- * Initialize the ADM1029 chip
- * Check config register
- */
- if (adm1029_init_client(client) == 0)
- return -ENODEV;
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &adm1029_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
- exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &adm1029_group);
- return err;
-}
-
static int adm1029_init_client(struct i2c_client *client)
{
u8 config;
+
config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG);
if ((config & 0x10) == 0) {
i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG,
@@ -396,59 +366,49 @@ static int adm1029_init_client(struct i2c_client *client)
return 1;
}
-static int adm1029_remove(struct i2c_client *client)
+static int adm1029_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct adm1029_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adm1029_group);
+ struct device *dev = &client->dev;
+ struct adm1029_data *data;
+ struct device *hwmon_dev;
- return 0;
-}
+ data = devm_kzalloc(dev, sizeof(struct adm1029_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
-/*
- * function that update the status of the chips (temperature for example)
- */
-static struct adm1029_data *adm1029_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1029_data *data = i2c_get_clientdata(client);
+ data->client = client;
+ mutex_init(&data->update_lock);
- mutex_lock(&data->update_lock);
/*
- * Use the "cache" Luke, don't recheck values
- * if there are already checked not a long time later
+ * Initialize the ADM1029 chip
+ * Check config register
*/
- if (time_after(jiffies, data->last_updated + HZ * 2)
- || !data->valid) {
- int nr;
-
- dev_dbg(&client->dev, "Updating adm1029 data\n");
-
- for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) {
- data->temp[nr] =
- i2c_smbus_read_byte_data(client,
- ADM1029_REG_TEMP[nr]);
- }
- for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) {
- data->fan[nr] =
- i2c_smbus_read_byte_data(client,
- ADM1029_REG_FAN[nr]);
- }
- for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) {
- data->fan_div[nr] =
- i2c_smbus_read_byte_data(client,
- ADM1029_REG_FAN_DIV[nr]);
- }
+ if (adm1029_init_client(client) == 0)
+ return -ENODEV;
- data->last_updated = jiffies;
- data->valid = 1;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ adm1029_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1029_id[] = {
+ { "adm1029", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm1029_id);
- return data;
-}
+static struct i2c_driver adm1029_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm1029",
+ },
+ .probe = adm1029_probe,
+ .id_table = adm1029_id,
+ .detect = adm1029_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm1029_driver);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 51c1a5a165ab..a5818980dad7 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -74,7 +74,8 @@ typedef u8 auto_chan_table_t[8][2];
/* Each client has this additional data */
struct adm1031_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
int chip_type;
char valid; /* !=0 if following fields are valid */
@@ -105,34 +106,6 @@ struct adm1031_data {
s8 temp_crit[3];
};
-static int adm1031_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm1031_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static void adm1031_init_client(struct i2c_client *client);
-static int adm1031_remove(struct i2c_client *client);
-static struct adm1031_data *adm1031_update_device(struct device *dev);
-
-static const struct i2c_device_id adm1031_id[] = {
- { "adm1030", adm1030 },
- { "adm1031", adm1031 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm1031_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver adm1031_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm1031",
- },
- .probe = adm1031_probe,
- .remove = adm1031_remove,
- .id_table = adm1031_id,
- .detect = adm1031_detect,
- .address_list = normal_i2c,
-};
-
static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -144,6 +117,96 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
return i2c_smbus_write_byte_data(client, reg, value);
}
+static struct adm1031_data *adm1031_update_device(struct device *dev)
+{
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ unsigned long next_update;
+ int chan;
+
+ mutex_lock(&data->update_lock);
+
+ next_update = data->last_updated
+ + msecs_to_jiffies(data->update_interval);
+ if (time_after(jiffies, next_update) || !data->valid) {
+
+ dev_dbg(&client->dev, "Starting adm1031 update\n");
+ for (chan = 0;
+ chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
+ u8 oldh, newh;
+
+ oldh =
+ adm1031_read_value(client, ADM1031_REG_TEMP(chan));
+ data->ext_temp[chan] =
+ adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
+ newh =
+ adm1031_read_value(client, ADM1031_REG_TEMP(chan));
+ if (newh != oldh) {
+ data->ext_temp[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_EXT_TEMP);
+#ifdef DEBUG
+ oldh =
+ adm1031_read_value(client,
+ ADM1031_REG_TEMP(chan));
+
+ /* oldh is actually newer */
+ if (newh != oldh)
+ dev_warn(&client->dev,
+ "Remote temperature may be wrong.\n");
+#endif
+ }
+ data->temp[chan] = newh;
+
+ data->temp_offset[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_TEMP_OFFSET(chan));
+ data->temp_min[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_TEMP_MIN(chan));
+ data->temp_max[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_TEMP_MAX(chan));
+ data->temp_crit[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_TEMP_CRIT(chan));
+ data->auto_temp[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_AUTO_TEMP(chan));
+
+ }
+
+ data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
+ data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
+
+ data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
+ | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
+ if (data->chip_type == adm1030)
+ data->alarm &= 0xc0ff;
+
+ for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
+ chan++) {
+ data->fan_div[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_DIV(chan));
+ data->fan_min[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_MIN(chan));
+ data->fan[chan] =
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_SPEED(chan));
+ data->pwm[chan] =
+ (adm1031_read_value(client,
+ ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
#define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \
((val + 500) / 1000)))
@@ -280,8 +343,8 @@ static ssize_t
set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
u8 reg;
@@ -355,8 +418,8 @@ static ssize_t
set_auto_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -385,8 +448,8 @@ static ssize_t
set_auto_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -428,8 +491,8 @@ static ssize_t show_pwm(struct device *dev,
static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret, reg;
@@ -541,8 +604,8 @@ static ssize_t show_fan_min(struct device *dev,
static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -565,8 +628,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
u8 tmp;
@@ -667,8 +730,8 @@ static ssize_t set_temp_offset(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -688,8 +751,8 @@ static ssize_t set_temp_offset(struct device *dev,
static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -709,8 +772,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -730,8 +793,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
long val;
int ret;
@@ -807,8 +870,7 @@ static const unsigned int update_intervals[] = {
static ssize_t show_update_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", data->update_interval);
}
@@ -817,8 +879,8 @@ static ssize_t set_update_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
+ struct adm1031_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int i, err;
u8 reg;
@@ -950,64 +1012,6 @@ static int adm1031_detect(struct i2c_client *client,
return 0;
}
-static int adm1031_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct adm1031_data *data;
- int err;
-
- data = devm_kzalloc(&client->dev, sizeof(struct adm1031_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- data->chip_type = id->driver_data;
- mutex_init(&data->update_lock);
-
- if (data->chip_type == adm1030)
- data->chan_select_table = &auto_channel_select_table_adm1030;
- else
- data->chan_select_table = &auto_channel_select_table_adm1031;
-
- /* Initialize the ADM1031 chip */
- adm1031_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
- if (err)
- return err;
-
- if (data->chip_type == adm1031) {
- err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
- if (err)
- goto exit_remove;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &adm1031_group);
- sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
- return err;
-}
-
-static int adm1031_remove(struct i2c_client *client)
-{
- struct adm1031_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adm1031_group);
- sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
- return 0;
-}
-
static void adm1031_init_client(struct i2c_client *client)
{
unsigned int read_val;
@@ -1039,96 +1043,57 @@ static void adm1031_init_client(struct i2c_client *client)
data->update_interval = update_intervals[i];
}
-static struct adm1031_data *adm1031_update_device(struct device *dev)
+static int adm1031_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm1031_data *data = i2c_get_clientdata(client);
- unsigned long next_update;
- int chan;
-
- mutex_lock(&data->update_lock);
-
- next_update = data->last_updated
- + msecs_to_jiffies(data->update_interval);
- if (time_after(jiffies, next_update) || !data->valid) {
-
- dev_dbg(&client->dev, "Starting adm1031 update\n");
- for (chan = 0;
- chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
- u8 oldh, newh;
-
- oldh =
- adm1031_read_value(client, ADM1031_REG_TEMP(chan));
- data->ext_temp[chan] =
- adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
- newh =
- adm1031_read_value(client, ADM1031_REG_TEMP(chan));
- if (newh != oldh) {
- data->ext_temp[chan] =
- adm1031_read_value(client,
- ADM1031_REG_EXT_TEMP);
-#ifdef DEBUG
- oldh =
- adm1031_read_value(client,
- ADM1031_REG_TEMP(chan));
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct adm1031_data *data;
- /* oldh is actually newer */
- if (newh != oldh)
- dev_warn(&client->dev,
- "Remote temperature may be wrong.\n");
-#endif
- }
- data->temp[chan] = newh;
+ data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- data->temp_offset[chan] =
- adm1031_read_value(client,
- ADM1031_REG_TEMP_OFFSET(chan));
- data->temp_min[chan] =
- adm1031_read_value(client,
- ADM1031_REG_TEMP_MIN(chan));
- data->temp_max[chan] =
- adm1031_read_value(client,
- ADM1031_REG_TEMP_MAX(chan));
- data->temp_crit[chan] =
- adm1031_read_value(client,
- ADM1031_REG_TEMP_CRIT(chan));
- data->auto_temp[chan] =
- adm1031_read_value(client,
- ADM1031_REG_AUTO_TEMP(chan));
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ data->chip_type = id->driver_data;
+ mutex_init(&data->update_lock);
- }
+ if (data->chip_type == adm1030)
+ data->chan_select_table = &auto_channel_select_table_adm1030;
+ else
+ data->chan_select_table = &auto_channel_select_table_adm1031;
- data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
- data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
+ /* Initialize the ADM1031 chip */
+ adm1031_init_client(client);
- data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
- | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
- if (data->chip_type == adm1030)
- data->alarm &= 0xc0ff;
+ /* sysfs hooks */
+ data->groups[0] = &adm1031_group;
+ if (data->chip_type == adm1031)
+ data->groups[1] = &adm1031_group_opt;
- for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
- chan++) {
- data->fan_div[chan] =
- adm1031_read_value(client,
- ADM1031_REG_FAN_DIV(chan));
- data->fan_min[chan] =
- adm1031_read_value(client,
- ADM1031_REG_FAN_MIN(chan));
- data->fan[chan] =
- adm1031_read_value(client,
- ADM1031_REG_FAN_SPEED(chan));
- data->pwm[chan] =
- (adm1031_read_value(client,
- ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
- }
- data->last_updated = jiffies;
- data->valid = 1;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id adm1031_id[] = {
+ { "adm1030", adm1030 },
+ { "adm1031", adm1031 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm1031_id);
- return data;
-}
+static struct i2c_driver adm1031_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm1031",
+ },
+ .probe = adm1031_probe,
+ .id_table = adm1031_id,
+ .detect = adm1031_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm1031_driver);
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 086d02a9ecdc..98114cef1e43 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -130,38 +130,9 @@ static inline unsigned int AOUT_FROM_REG(u8 reg)
return SCALE(reg, 1250, 255);
}
-static int adm9240_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adm9240_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static void adm9240_init_client(struct i2c_client *client);
-static int adm9240_remove(struct i2c_client *client);
-static struct adm9240_data *adm9240_update_device(struct device *dev);
-
-/* driver data */
-static const struct i2c_device_id adm9240_id[] = {
- { "adm9240", adm9240 },
- { "ds1780", ds1780 },
- { "lm81", lm81 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adm9240_id);
-
-static struct i2c_driver adm9240_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adm9240",
- },
- .probe = adm9240_probe,
- .remove = adm9240_remove,
- .id_table = adm9240_id,
- .detect = adm9240_detect,
- .address_list = normal_i2c,
-};
-
/* per client data */
struct adm9240_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid;
unsigned long last_updated_measure;
@@ -181,6 +152,110 @@ struct adm9240_data {
u8 vrm; /* -- vrm set on startup, no accessor */
};
+/* write new fan div, callers must hold data->update_lock */
+static void adm9240_write_fan_div(struct i2c_client *client, int nr,
+ u8 fan_div)
+{
+ u8 reg, old, shift = (nr + 2) * 2;
+
+ reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
+ old = (reg >> shift) & 3;
+ reg &= ~(3 << shift);
+ reg |= (fan_div << shift);
+ i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
+ dev_dbg(&client->dev,
+ "fan%d clock divider changed from %u to %u\n",
+ nr + 1, 1 << old, 1 << fan_div);
+}
+
+static struct adm9240_data *adm9240_update_device(struct device *dev)
+{
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ /* minimum measurement cycle: 1.75 seconds */
+ if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
+ || !data->valid) {
+
+ for (i = 0; i < 6; i++) { /* read voltages */
+ data->in[i] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_IN(i));
+ }
+ data->alarms = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_INT(0)) |
+ i2c_smbus_read_byte_data(client,
+ ADM9240_REG_INT(1)) << 8;
+
+ /*
+ * read temperature: assume temperature changes less than
+ * 0.5'C per two measurement cycles thus ignore possible
+ * but unlikely aliasing error on lsb reading. --Grant
+ */
+ data->temp = ((i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP) << 8) |
+ i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_CONF)) / 128;
+
+ for (i = 0; i < 2; i++) { /* read fans */
+ data->fan[i] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_FAN(i));
+
+ /* adjust fan clock divider on overflow */
+ if (data->valid && data->fan[i] == 255 &&
+ data->fan_div[i] < 3) {
+
+ adm9240_write_fan_div(client, i,
+ ++data->fan_div[i]);
+
+ /* adjust fan_min if active, but not to 0 */
+ if (data->fan_min[i] < 255 &&
+ data->fan_min[i] >= 2)
+ data->fan_min[i] /= 2;
+ }
+ }
+ data->last_updated_measure = jiffies;
+ }
+
+ /* minimum config reading cycle: 300 seconds */
+ if (time_after(jiffies, data->last_updated_config + (HZ * 300))
+ || !data->valid) {
+
+ for (i = 0; i < 6; i++) {
+ data->in_min[i] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_IN_MIN(i));
+ data->in_max[i] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_IN_MAX(i));
+ }
+ for (i = 0; i < 2; i++) {
+ data->fan_min[i] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_FAN_MIN(i));
+ }
+ data->temp_max[0] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(0));
+ data->temp_max[1] = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_TEMP_MAX(1));
+
+ /* read fan divs and 5-bit VID */
+ i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
+ data->fan_div[0] = (i >> 4) & 3;
+ data->fan_div[1] = (i >> 6) & 3;
+ data->vid = i & 0x0f;
+ data->vid |= (i2c_smbus_read_byte_data(client,
+ ADM9240_REG_VID4) & 1) << 4;
+ /* read analog out */
+ data->aout = i2c_smbus_read_byte_data(client,
+ ADM9240_REG_ANALOG_OUT);
+
+ data->last_updated_config = jiffies;
+ data->valid = 1;
+ }
+ mutex_unlock(&data->update_lock);
+ return data;
+}
+
/*** sysfs accessors ***/
/* temperature */
@@ -203,8 +278,8 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -259,8 +334,8 @@ static ssize_t set_in_min(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -281,8 +356,8 @@ static ssize_t set_in_max(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -340,22 +415,6 @@ static ssize_t show_fan_div(struct device *dev,
return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
}
-/* write new fan div, callers must hold data->update_lock */
-static void adm9240_write_fan_div(struct i2c_client *client, int nr,
- u8 fan_div)
-{
- u8 reg, old, shift = (nr + 2) * 2;
-
- reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
- old = (reg >> shift) & 3;
- reg &= ~(3 << shift);
- reg |= (fan_div << shift);
- i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
- dev_dbg(&client->dev,
- "fan%d clock divider changed from %u to %u\n",
- nr + 1, 1 << old, 1 << fan_div);
-}
-
/*
* set fan speed low limit:
*
@@ -372,8 +431,8 @@ static ssize_t set_fan_min(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = attr->index;
u8 new_div;
unsigned long val;
@@ -485,8 +544,8 @@ static ssize_t set_aout(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -506,8 +565,8 @@ static ssize_t chassis_clear(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
+ struct adm9240_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
if (kstrtoul(buf, 10, &val) || val != 0)
@@ -524,7 +583,7 @@ static ssize_t chassis_clear(struct device *dev,
static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm,
chassis_clear, 12);
-static struct attribute *adm9240_attributes[] = {
+static struct attribute *adm9240_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -568,9 +627,7 @@ static struct attribute *adm9240_attributes[] = {
NULL
};
-static const struct attribute_group adm9240_group = {
- .attrs = adm9240_attributes,
-};
+ATTRIBUTE_GROUPS(adm9240);
/*** sensor chip detect and driver install ***/
@@ -620,49 +677,6 @@ static int adm9240_detect(struct i2c_client *new_client,
return 0;
}
-static int adm9240_probe(struct i2c_client *new_client,
- const struct i2c_device_id *id)
-{
- struct adm9240_data *data;
- int err;
-
- data = devm_kzalloc(&new_client->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(new_client, data);
- mutex_init(&data->update_lock);
-
- adm9240_init_client(new_client);
-
- /* populate sysfs filesystem */
- err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&new_client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
- return err;
-}
-
-static int adm9240_remove(struct i2c_client *client)
-{
- struct adm9240_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adm9240_group);
-
- return 0;
-}
-
static void adm9240_init_client(struct i2c_client *client)
{
struct adm9240_data *data = i2c_get_clientdata(client);
@@ -705,93 +719,48 @@ static void adm9240_init_client(struct i2c_client *client)
}
}
-static struct adm9240_data *adm9240_update_device(struct device *dev)
+static int adm9240_probe(struct i2c_client *new_client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adm9240_data *data = i2c_get_clientdata(client);
- int i;
-
- mutex_lock(&data->update_lock);
-
- /* minimum measurement cycle: 1.75 seconds */
- if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
- || !data->valid) {
-
- for (i = 0; i < 6; i++) { /* read voltages */
- data->in[i] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_IN(i));
- }
- data->alarms = i2c_smbus_read_byte_data(client,
- ADM9240_REG_INT(0)) |
- i2c_smbus_read_byte_data(client,
- ADM9240_REG_INT(1)) << 8;
-
- /*
- * read temperature: assume temperature changes less than
- * 0.5'C per two measurement cycles thus ignore possible
- * but unlikely aliasing error on lsb reading. --Grant
- */
- data->temp = ((i2c_smbus_read_byte_data(client,
- ADM9240_REG_TEMP) << 8) |
- i2c_smbus_read_byte_data(client,
- ADM9240_REG_TEMP_CONF)) / 128;
-
- for (i = 0; i < 2; i++) { /* read fans */
- data->fan[i] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_FAN(i));
-
- /* adjust fan clock divider on overflow */
- if (data->valid && data->fan[i] == 255 &&
- data->fan_div[i] < 3) {
+ struct device *dev = &new_client->dev;
+ struct device *hwmon_dev;
+ struct adm9240_data *data;
- adm9240_write_fan_div(client, i,
- ++data->fan_div[i]);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- /* adjust fan_min if active, but not to 0 */
- if (data->fan_min[i] < 255 &&
- data->fan_min[i] >= 2)
- data->fan_min[i] /= 2;
- }
- }
- data->last_updated_measure = jiffies;
- }
+ i2c_set_clientdata(new_client, data);
+ data->client = new_client;
+ mutex_init(&data->update_lock);
- /* minimum config reading cycle: 300 seconds */
- if (time_after(jiffies, data->last_updated_config + (HZ * 300))
- || !data->valid) {
+ adm9240_init_client(new_client);
- for (i = 0; i < 6; i++) {
- data->in_min[i] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_IN_MIN(i));
- data->in_max[i] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_IN_MAX(i));
- }
- for (i = 0; i < 2; i++) {
- data->fan_min[i] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_FAN_MIN(i));
- }
- data->temp_max[0] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_TEMP_MAX(0));
- data->temp_max[1] = i2c_smbus_read_byte_data(client,
- ADM9240_REG_TEMP_MAX(1));
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+ new_client->name,
+ data,
+ adm9240_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- /* read fan divs and 5-bit VID */
- i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
- data->fan_div[0] = (i >> 4) & 3;
- data->fan_div[1] = (i >> 6) & 3;
- data->vid = i & 0x0f;
- data->vid |= (i2c_smbus_read_byte_data(client,
- ADM9240_REG_VID4) & 1) << 4;
- /* read analog out */
- data->aout = i2c_smbus_read_byte_data(client,
- ADM9240_REG_ANALOG_OUT);
+static const struct i2c_device_id adm9240_id[] = {
+ { "adm9240", adm9240 },
+ { "ds1780", ds1780 },
+ { "lm81", lm81 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adm9240_id);
- data->last_updated_config = jiffies;
- data->valid = 1;
- }
- mutex_unlock(&data->update_lock);
- return data;
-}
+static struct i2c_driver adm9240_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adm9240",
+ },
+ .probe = adm9240_probe,
+ .id_table = adm9240_id,
+ .detect = adm9240_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adm9240_driver);
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index 7f9dc2f86b63..126516414c11 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -198,7 +198,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
}
channel = be32_to_cpup(property);
- if (channel > ADS1015_CHANNELS) {
+ if (channel >= ADS1015_CHANNELS) {
dev_err(&client->dev,
"invalid channel index %d on %s\n",
channel, node->full_name);
@@ -212,6 +212,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
dev_err(&client->dev,
"invalid gain on %s\n",
node->full_name);
+ return -EINVAL;
}
}
@@ -222,6 +223,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
dev_err(&client->dev,
"invalid data_rate on %s\n",
node->full_name);
+ return -EINVAL;
}
}
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 7092c78f814f..a622d40eec17 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -50,7 +50,7 @@ enum ads7828_chips { ads7828, ads7830 };
/* Client specific data */
struct ads7828_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock; /* Mutex protecting updates */
unsigned long last_updated; /* Last updated time (in jiffies) */
u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH samples */
@@ -72,8 +72,8 @@ static inline u8 ads7828_cmd_byte(u8 cmd, int ch)
/* Update data for the device (all 8 channels) */
static struct ads7828_data *ads7828_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ads7828_data *data = i2c_get_clientdata(client);
+ struct ads7828_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
@@ -116,7 +116,7 @@ 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[] = {
+static struct attribute *ads7828_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -128,29 +128,17 @@ static struct attribute *ads7828_attributes[] = {
NULL
};
-static const struct attribute_group ads7828_group = {
- .attrs = ads7828_attributes,
-};
-
-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;
-}
+ATTRIBUTE_GROUPS(ads7828);
static int ads7828_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct ads7828_platform_data *pdata = dev_get_platdata(&client->dev);
+ struct device *dev = &client->dev;
+ struct ads7828_platform_data *pdata = dev_get_platdata(dev);
struct ads7828_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&client->dev, sizeof(struct ads7828_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -182,24 +170,13 @@ static int ads7828_probe(struct i2c_client *client,
if (!data->diff_input)
data->cmd_byte |= ADS7828_CMD_SD_SE;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
- err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto error;
- }
-
- return 0;
-
-error:
- sysfs_remove_group(&client->dev.kobj, &ads7828_group);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ ads7828_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id ads7828_device_ids[] = {
@@ -216,7 +193,6 @@ static struct i2c_driver ads7828_driver = {
.id_table = ads7828_device_ids,
.probe = ads7828_probe,
- .remove = ads7828_remove,
};
module_i2c_driver(ads7828_driver);
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index d9299dee37d1..827c03703128 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -51,7 +51,7 @@ struct adt7411_data {
struct mutex update_lock;
unsigned long next_update;
int vref_cached;
- struct device *hwmon_dev;
+ struct i2c_client *client;
};
/*
@@ -111,7 +111,8 @@ static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit,
static ssize_t adt7411_show_vdd(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct adt7411_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
ADT7411_REG_VDD_MSB, 2);
@@ -121,7 +122,8 @@ static ssize_t adt7411_show_vdd(struct device *dev,
static ssize_t adt7411_show_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct adt7411_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
ADT7411_REG_INT_TEMP_MSB, 0);
@@ -137,8 +139,8 @@ static ssize_t adt7411_show_input(struct device *dev,
struct device_attribute *attr, char *buf)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7411_data *data = i2c_get_clientdata(client);
+ struct adt7411_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int val;
u8 lsb_reg, lsb_shift;
@@ -180,7 +182,8 @@ static ssize_t adt7411_show_bit(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
+ struct adt7411_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ret = i2c_smbus_read_byte_data(client, attr2->index);
return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr));
@@ -191,8 +194,8 @@ static ssize_t adt7411_set_bit(struct device *dev,
size_t count)
{
struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7411_data *data = i2c_get_clientdata(client);
+ struct adt7411_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ret;
unsigned long flag;
@@ -245,9 +248,7 @@ static struct attribute *adt7411_attrs[] = {
NULL
};
-static const struct attribute_group adt7411_attr_grp = {
- .attrs = adt7411_attrs,
-};
+ATTRIBUTE_GROUPS(adt7411);
static int adt7411_detect(struct i2c_client *client,
struct i2c_board_info *info)
@@ -281,14 +282,17 @@ static int adt7411_detect(struct i2c_client *client,
static int adt7411_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct adt7411_data *data;
+ struct device *hwmon_dev;
int ret;
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->device_lock);
mutex_init(&data->update_lock);
@@ -300,32 +304,10 @@ static int adt7411_probe(struct i2c_client *client,
/* force update on first occasion */
data->next_update = jiffies;
- ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp);
- if (ret)
- return ret;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- dev_info(&client->dev, "successfully registered\n");
-
- return 0;
-
- exit_remove:
- sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
- return ret;
-}
-
-static int adt7411_remove(struct i2c_client *client)
-{
- struct adt7411_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ adt7411_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id adt7411_id[] = {
@@ -339,7 +321,6 @@ static struct i2c_driver adt7411_driver = {
.name = "adt7411",
},
.probe = adt7411_probe,
- .remove = adt7411_remove,
.id_table = adt7411_id,
.detect = adt7411_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 562cc3881d33..5929e126da63 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -202,8 +202,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
(((value) & prefix##_MASK) >> prefix##_SHIFT)
struct adt7462_data {
- struct device *hwmon_dev;
- struct attribute_group attrs;
+ struct i2c_client *client;
struct mutex lock;
char sensors_valid;
char limits_valid;
@@ -232,30 +231,6 @@ struct adt7462_data {
u8 alarms[ADT7462_ALARM_REG_COUNT];
};
-static int adt7462_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adt7462_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int adt7462_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7462_id[] = {
- { "adt7462", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adt7462_id);
-
-static struct i2c_driver adt7462_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adt7462",
- },
- .probe = adt7462_probe,
- .remove = adt7462_remove,
- .id_table = adt7462_id,
- .detect = adt7462_detect,
- .address_list = normal_i2c,
-};
-
/*
* 16-bit registers on the ADT7462 are low-byte first. The data sheet says
* that the low byte must be read before the high byte.
@@ -705,8 +680,8 @@ static int find_trange_value(int trange)
static struct adt7462_data *adt7462_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long local_jiffies = jiffies;
int i;
@@ -828,8 +803,8 @@ static ssize_t set_temp_min(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
@@ -866,8 +841,8 @@ static ssize_t set_temp_max(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
@@ -929,8 +904,8 @@ static ssize_t set_volt_max(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int x = voltage_multiplier(data, attr->index);
long temp;
@@ -971,8 +946,8 @@ static ssize_t set_volt_min(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int x = voltage_multiplier(data, attr->index);
long temp;
@@ -1061,8 +1036,8 @@ static ssize_t set_fan_min(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp) || !temp ||
@@ -1109,8 +1084,8 @@ static ssize_t set_force_pwm_max(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
u8 reg;
@@ -1142,8 +1117,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1172,8 +1147,8 @@ static ssize_t set_pwm_max(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1204,8 +1179,8 @@ static ssize_t set_pwm_min(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1238,8 +1213,8 @@ static ssize_t set_pwm_hyst(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1283,8 +1258,8 @@ static ssize_t set_pwm_tmax(struct device *dev,
{
int temp;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int tmin, trange_value;
long trange;
@@ -1324,8 +1299,8 @@ static ssize_t set_pwm_tmin(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1381,8 +1356,8 @@ static ssize_t set_pwm_auto(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1440,8 +1415,8 @@ static ssize_t set_pwm_auto_temp(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7462_data *data = i2c_get_clientdata(client);
+ struct adt7462_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -1725,7 +1700,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
show_pwm_auto_temp, set_pwm_auto_temp, 3);
-static struct attribute *adt7462_attr[] = {
+static struct attribute *adt7462_attrs[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
@@ -1896,6 +1871,8 @@ static struct attribute *adt7462_attr[] = {
NULL
};
+ATTRIBUTE_GROUPS(adt7462);
+
/* Return 0 if detection is successful, -ENODEV otherwise */
static int adt7462_detect(struct i2c_client *client,
struct i2c_board_info *info)
@@ -1926,46 +1903,41 @@ static int adt7462_detect(struct i2c_client *client,
static int adt7462_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct adt7462_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct adt7462_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name);
- /* Register sysfs hooks */
- data->attrs.attrs = adt7462_attr;
- err = sysfs_create_group(&client->dev.kobj, &data->attrs);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ adt7462_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static int adt7462_remove(struct i2c_client *client)
-{
- struct adt7462_data *data = i2c_get_clientdata(client);
+static const struct i2c_device_id adt7462_id[] = {
+ { "adt7462", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adt7462_id);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- return 0;
-}
+static struct i2c_driver adt7462_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adt7462",
+ },
+ .probe = adt7462_probe,
+ .id_table = adt7462_id,
+ .detect = adt7462_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(adt7462_driver);
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 9ee3913850d6..f5da39a68929 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -143,8 +143,7 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
struct adt7470_data {
- struct device *hwmon_dev;
- struct attribute_group attrs;
+ struct i2c_client *client;
struct mutex lock;
char sensors_valid;
char limits_valid;
@@ -175,30 +174,6 @@ struct adt7470_data {
unsigned int auto_update_interval;
};
-static int adt7470_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adt7470_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int adt7470_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7470_id[] = {
- { "adt7470", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adt7470_id);
-
-static struct i2c_driver adt7470_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adt7470",
- },
- .probe = adt7470_probe,
- .remove = adt7470_remove,
- .id_table = adt7470_id,
- .detect = adt7470_detect,
- .address_list = normal_i2c,
-};
-
/*
* 16-bit registers on the ADT7470 are low-byte first. The data sheet says
* that the low byte must be read before the high byte.
@@ -218,18 +193,6 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg,
|| i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
}
-static void adt7470_init_client(struct i2c_client *client)
-{
- int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
-
- if (reg < 0) {
- dev_err(&client->dev, "cannot read configuration register\n");
- } else {
- /* start monitoring (and do a self-test) */
- i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);
- }
-}
-
/* Probe for temperature sensors. Assumes lock is held */
static int adt7470_read_temperatures(struct i2c_client *client,
struct adt7470_data *data)
@@ -314,8 +277,8 @@ static int adt7470_update_thread(void *p)
static struct adt7470_data *adt7470_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long local_jiffies = jiffies;
u8 cfg;
int i;
@@ -445,8 +408,7 @@ static ssize_t set_auto_update_interval(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
long temp;
if (kstrtol(buf, 10, &temp))
@@ -474,8 +436,7 @@ static ssize_t set_num_temp_sensors(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
long temp;
if (kstrtol(buf, 10, &temp))
@@ -507,8 +468,8 @@ static ssize_t set_temp_min(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -541,8 +502,8 @@ static ssize_t set_temp_max(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -596,8 +557,8 @@ static ssize_t set_fan_max(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp) || !temp)
@@ -633,8 +594,8 @@ static ssize_t set_fan_min(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp) || !temp)
@@ -677,8 +638,8 @@ static ssize_t set_force_pwm_max(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
u8 reg;
@@ -710,8 +671,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -742,8 +703,8 @@ static ssize_t set_pwm_max(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -775,8 +736,8 @@ static ssize_t set_pwm_min(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -818,8 +779,8 @@ static ssize_t set_pwm_tmin(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long temp;
if (kstrtol(buf, 10, &temp))
@@ -852,8 +813,8 @@ static ssize_t set_pwm_auto(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index);
int pwm_auto_reg_mask;
long temp;
@@ -913,8 +874,8 @@ static ssize_t set_pwm_auto_temp(struct device *dev,
size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
+ struct adt7470_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index);
long temp;
u8 reg;
@@ -1131,7 +1092,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
show_pwm_auto_temp, set_pwm_auto_temp, 3);
-static struct attribute *adt7470_attr[] = {
+static struct attribute *adt7470_attrs[] = {
&dev_attr_alarm_mask.attr,
&dev_attr_num_temp_sensors.attr,
&dev_attr_auto_update_interval.attr,
@@ -1223,6 +1184,8 @@ static struct attribute *adt7470_attr[] = {
NULL
};
+ATTRIBUTE_GROUPS(adt7470);
+
/* Return 0 if detection is successful, -ENODEV otherwise */
static int adt7470_detect(struct i2c_client *client,
struct i2c_board_info *info)
@@ -1250,14 +1213,26 @@ static int adt7470_detect(struct i2c_client *client,
return 0;
}
+static void adt7470_init_client(struct i2c_client *client)
+{
+ int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
+
+ if (reg < 0) {
+ dev_err(&client->dev, "cannot read configuration register\n");
+ } else {
+ /* start monitoring (and do a self-test) */
+ i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3);
+ }
+}
+
static int adt7470_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct adt7470_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&client->dev, sizeof(struct adt7470_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -1265,6 +1240,7 @@ static int adt7470_probe(struct i2c_client *client,
data->auto_update_interval = AUTO_UPDATE_INTERVAL;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->lock);
dev_info(&client->dev, "%s chip found\n", client->name);
@@ -1273,32 +1249,21 @@ static int adt7470_probe(struct i2c_client *client,
adt7470_init_client(client);
/* Register sysfs hooks */
- data->attrs.attrs = adt7470_attr;
- err = sysfs_create_group(&client->dev.kobj, &data->attrs);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ adt7470_groups);
+
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
init_completion(&data->auto_update_stop);
data->auto_update = kthread_run(adt7470_update_thread, client, "%s",
- dev_name(data->hwmon_dev));
+ dev_name(hwmon_dev));
if (IS_ERR(data->auto_update)) {
- err = PTR_ERR(data->auto_update);
- goto exit_unregister;
+ return PTR_ERR(data->auto_update);
}
return 0;
-
-exit_unregister:
- hwmon_device_unregister(data->hwmon_dev);
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- return err;
}
static int adt7470_remove(struct i2c_client *client)
@@ -1307,11 +1272,27 @@ static int adt7470_remove(struct i2c_client *client)
kthread_stop(data->auto_update);
wait_for_completion(&data->auto_update_stop);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
return 0;
}
+static const struct i2c_device_id adt7470_id[] = {
+ { "adt7470", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adt7470_id);
+
+static struct i2c_driver adt7470_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adt7470",
+ },
+ .probe = adt7470_probe,
+ .remove = adt7470_remove,
+ .id_table = adt7470_id,
+ .detect = adt7470_detect,
+ .address_list = normal_i2c,
+};
+
module_i2c_driver(adt7470_driver);
MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 9f2be3dd28f3..12e851a5af48 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -21,7 +21,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/module.h>
#include <linux/init.h>
@@ -33,7 +32,6 @@
#include <linux/err.h>
#include <linux/mutex.h>
-
/*
* Addresses to scan.
*/
@@ -41,8 +39,6 @@
static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
0x4c, 0x4d, 0x4e, I2C_CLIENT_END};
-
-
/*
* Insmod parameters
*/
@@ -53,7 +49,6 @@ module_param(pwminv, int, S_IRUGO);
static int init = 1; /*Power-on initialization.*/
module_param(init, int, S_IRUGO);
-
enum chips { amc6821 };
#define AMC6821_REG_DEV_ID 0x3D
@@ -152,46 +147,12 @@ static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
AMC6821_REG_TACH_LLIMITH,
AMC6821_REG_TACH_HLIMITH, };
-static int amc6821_probe(
- struct i2c_client *client,
- const struct i2c_device_id *id);
-static int amc6821_detect(
- struct i2c_client *client,
- struct i2c_board_info *info);
-static int amc6821_init_client(struct i2c_client *client);
-static int amc6821_remove(struct i2c_client *client);
-static struct amc6821_data *amc6821_update_device(struct device *dev);
-
-/*
- * Driver data (common to all clients)
- */
-
-static const struct i2c_device_id amc6821_id[] = {
- { "amc6821", amc6821 },
- { }
-};
-
-MODULE_DEVICE_TABLE(i2c, amc6821_id);
-
-static struct i2c_driver amc6821_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "amc6821",
- },
- .probe = amc6821_probe,
- .remove = amc6821_remove,
- .id_table = amc6821_id,
- .detect = amc6821_detect,
- .address_list = normal_i2c,
-};
-
-
/*
* Client data (each client gets its own)
*/
struct amc6821_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -213,6 +174,108 @@ struct amc6821_data {
u8 stat2;
};
+static struct amc6821_data *amc6821_update_device(struct device *dev)
+{
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int timeout = HZ;
+ u8 reg;
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + timeout) ||
+ !data->valid) {
+
+ for (i = 0; i < TEMP_IDX_LEN; i++)
+ data->temp[i] = i2c_smbus_read_byte_data(client,
+ temp_reg[i]);
+
+ data->stat1 = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_STAT1);
+ data->stat2 = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_STAT2);
+
+ data->pwm1 = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_DCY);
+ for (i = 0; i < FAN1_IDX_LEN; i++) {
+ data->fan[i] = i2c_smbus_read_byte_data(
+ client,
+ fan_reg_low[i]);
+ data->fan[i] += i2c_smbus_read_byte_data(
+ client,
+ fan_reg_hi[i]) << 8;
+ }
+ data->fan1_div = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_CONF4);
+ data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+
+ data->pwm1_auto_point_pwm[0] = 0;
+ data->pwm1_auto_point_pwm[2] = 255;
+ data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_DCY_LOW_TEMP);
+
+ data->temp1_auto_point_temp[0] =
+ i2c_smbus_read_byte_data(client,
+ AMC6821_REG_PSV_TEMP);
+ data->temp2_auto_point_temp[0] =
+ data->temp1_auto_point_temp[0];
+ reg = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_LTEMP_FAN_CTRL);
+ data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
+ reg &= 0x07;
+ reg = 0x20 >> reg;
+ if (reg > 0)
+ data->temp1_auto_point_temp[2] =
+ data->temp1_auto_point_temp[1] +
+ (data->pwm1_auto_point_pwm[2] -
+ data->pwm1_auto_point_pwm[1]) / reg;
+ else
+ data->temp1_auto_point_temp[2] = 255;
+
+ reg = i2c_smbus_read_byte_data(client,
+ AMC6821_REG_RTEMP_FAN_CTRL);
+ data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
+ reg &= 0x07;
+ reg = 0x20 >> reg;
+ if (reg > 0)
+ data->temp2_auto_point_temp[2] =
+ data->temp2_auto_point_temp[1] +
+ (data->pwm1_auto_point_pwm[2] -
+ data->pwm1_auto_point_pwm[1]) / reg;
+ else
+ data->temp2_auto_point_temp[2] = 255;
+
+ reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
+ reg = (reg >> 5) & 0x3;
+ switch (reg) {
+ case 0: /*open loop: software sets pwm1*/
+ data->pwm1_auto_channels_temp = 0;
+ data->pwm1_enable = 1;
+ break;
+ case 2: /*closed loop: remote T (temp2)*/
+ data->pwm1_auto_channels_temp = 2;
+ data->pwm1_enable = 2;
+ break;
+ case 3: /*closed loop: local and remote T (temp2)*/
+ data->pwm1_auto_channels_temp = 3;
+ data->pwm1_enable = 3;
+ break;
+ case 1: /*
+ * semi-open loop: software sets rpm, chip controls
+ * pwm1, currently not implemented
+ */
+ data->pwm1_auto_channels_temp = 0;
+ data->pwm1_enable = 0;
+ break;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+ mutex_unlock(&data->update_lock);
+ return data;
+}
static ssize_t get_temp(
struct device *dev,
@@ -225,16 +288,14 @@ static ssize_t get_temp(
return sprintf(buf, "%d\n", data->temp[ix] * 1000);
}
-
-
static ssize_t set_temp(
struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ix = to_sensor_dev_attr(attr)->index;
long val;
@@ -253,9 +314,6 @@ static ssize_t set_temp(
return count;
}
-
-
-
static ssize_t get_temp_alarm(
struct device *dev,
struct device_attribute *devattr,
@@ -294,9 +352,6 @@ static ssize_t get_temp_alarm(
return sprintf(buf, "0");
}
-
-
-
static ssize_t get_temp2_fault(
struct device *dev,
struct device_attribute *devattr,
@@ -324,8 +379,8 @@ static ssize_t set_pwm1(
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int ret = kstrtol(buf, 10, &val);
if (ret)
@@ -353,18 +408,20 @@ static ssize_t set_pwm1_enable(
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int config = kstrtol(buf, 10, &val);
if (config)
return config;
+ mutex_lock(&data->update_lock);
config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
if (config < 0) {
dev_err(&client->dev,
"Error reading configuration register, aborting.\n");
- return config;
+ count = config;
+ goto unlock;
}
switch (val) {
@@ -381,19 +438,19 @@ static ssize_t set_pwm1_enable(
config |= AMC6821_CONF1_FDRC1;
break;
default:
- return -EINVAL;
+ count = -EINVAL;
+ goto unlock;
}
- mutex_lock(&data->update_lock);
if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
dev_err(&client->dev,
"Configuration register write error, aborting.\n");
count = -EIO;
}
+unlock:
mutex_unlock(&data->update_lock);
return count;
}
-
static ssize_t get_pwm1_auto_channels_temp(
struct device *dev,
struct device_attribute *devattr,
@@ -403,7 +460,6 @@ static ssize_t get_pwm1_auto_channels_temp(
return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
}
-
static ssize_t get_temp_auto_point_temp(
struct device *dev,
struct device_attribute *devattr,
@@ -425,7 +481,6 @@ static ssize_t get_temp_auto_point_temp(
}
}
-
static ssize_t get_pwm1_auto_point_pwm(
struct device *dev,
struct device_attribute *devattr,
@@ -436,7 +491,6 @@ static ssize_t get_pwm1_auto_point_pwm(
return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
}
-
static inline ssize_t set_slope_register(struct i2c_client *client,
u8 reg,
u8 dpwm,
@@ -459,16 +513,14 @@ static inline ssize_t set_slope_register(struct i2c_client *client,
return 0;
}
-
-
static ssize_t set_temp_auto_point_temp(
struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct amc6821_data *data = amc6821_update_device(dev);
+ struct i2c_client *client = data->client;
int ix = to_sensor_dev_attr_2(attr)->index;
int nr = to_sensor_dev_attr_2(attr)->nr;
u8 *ptemp;
@@ -493,8 +545,9 @@ static ssize_t set_temp_auto_point_temp(
return -EINVAL;
}
- data->valid = 0;
mutex_lock(&data->update_lock);
+ data->valid = 0;
+
switch (ix) {
case 0:
ptemp[0] = clamp_val(val / 1000, 0,
@@ -533,16 +586,14 @@ EXIT:
return count;
}
-
-
static ssize_t set_pwm1_auto_point_pwm(
struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int dpwm;
long val;
int ret = kstrtol(buf, 10, &val);
@@ -587,8 +638,6 @@ static ssize_t get_fan(
return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
}
-
-
static ssize_t get_fan1_fault(
struct device *dev,
struct device_attribute *devattr,
@@ -601,15 +650,13 @@ static ssize_t get_fan1_fault(
return sprintf(buf, "0");
}
-
-
static ssize_t set_fan(
struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int ix = to_sensor_dev_attr(attr)->index;
int ret = kstrtol(buf, 10, &val);
@@ -635,8 +682,6 @@ EXIT:
return count;
}
-
-
static ssize_t get_fan1_div(
struct device *dev,
struct device_attribute *devattr,
@@ -651,20 +696,21 @@ static ssize_t set_fan1_div(
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
+ struct amc6821_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int config = kstrtol(buf, 10, &val);
if (config)
return config;
+ mutex_lock(&data->update_lock);
config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
if (config < 0) {
dev_err(&client->dev,
"Error reading configuration register, aborting.\n");
- return config;
+ count = config;
+ goto EXIT;
}
- mutex_lock(&data->update_lock);
switch (val) {
case 2:
config &= ~AMC6821_CONF4_PSPR;
@@ -688,8 +734,6 @@ EXIT:
return count;
}
-
-
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
get_temp, NULL, IDX_TEMP1_INPUT);
static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp,
@@ -754,8 +798,6 @@ static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO,
get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2);
-
-
static struct attribute *amc6821_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -792,11 +834,7 @@ static struct attribute *amc6821_attrs[] = {
NULL
};
-static struct attribute_group amc6821_attr_grp = {
- .attrs = amc6821_attrs,
-};
-
-
+ATTRIBUTE_GROUPS(amc6821);
/* Return 0 if detection is successful, -ENODEV otherwise */
static int amc6821_detect(
@@ -844,53 +882,6 @@ static int amc6821_detect(
return 0;
}
-static int amc6821_probe(
- struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct amc6821_data *data;
- int err;
-
- data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- /*
- * Initialize the amc6821 chip
- */
- err = amc6821_init_client(client);
- if (err)
- return err;
-
- err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (!IS_ERR(data->hwmon_dev))
- return 0;
-
- err = PTR_ERR(data->hwmon_dev);
- dev_err(&client->dev, "error registering hwmon device.\n");
- sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
- return err;
-}
-
-static int amc6821_remove(struct i2c_client *client)
-{
- struct amc6821_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-
- return 0;
-}
-
-
static int amc6821_init_client(struct i2c_client *client)
{
int config;
@@ -977,109 +968,51 @@ static int amc6821_init_client(struct i2c_client *client)
return 0;
}
-
-static struct amc6821_data *amc6821_update_device(struct device *dev)
+static int amc6821_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct amc6821_data *data = i2c_get_clientdata(client);
- int timeout = HZ;
- u8 reg;
- int i;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + timeout) ||
- !data->valid) {
-
- for (i = 0; i < TEMP_IDX_LEN; i++)
- data->temp[i] = i2c_smbus_read_byte_data(client,
- temp_reg[i]);
+ struct device *dev = &client->dev;
+ struct amc6821_data *data;
+ struct device *hwmon_dev;
+ int err;
- data->stat1 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_STAT1);
- data->stat2 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_STAT2);
+ data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- data->pwm1 = i2c_smbus_read_byte_data(client,
- AMC6821_REG_DCY);
- for (i = 0; i < FAN1_IDX_LEN; i++) {
- data->fan[i] = i2c_smbus_read_byte_data(
- client,
- fan_reg_low[i]);
- data->fan[i] += i2c_smbus_read_byte_data(
- client,
- fan_reg_hi[i]) << 8;
- }
- data->fan1_div = i2c_smbus_read_byte_data(client,
- AMC6821_REG_CONF4);
- data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
+ data->client = client;
+ mutex_init(&data->update_lock);
- data->pwm1_auto_point_pwm[0] = 0;
- data->pwm1_auto_point_pwm[2] = 255;
- data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
- AMC6821_REG_DCY_LOW_TEMP);
+ /*
+ * Initialize the amc6821 chip
+ */
+ err = amc6821_init_client(client);
+ if (err)
+ return err;
- data->temp1_auto_point_temp[0] =
- i2c_smbus_read_byte_data(client,
- AMC6821_REG_PSV_TEMP);
- data->temp2_auto_point_temp[0] =
- data->temp1_auto_point_temp[0];
- reg = i2c_smbus_read_byte_data(client,
- AMC6821_REG_LTEMP_FAN_CTRL);
- data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
- reg &= 0x07;
- reg = 0x20 >> reg;
- if (reg > 0)
- data->temp1_auto_point_temp[2] =
- data->temp1_auto_point_temp[1] +
- (data->pwm1_auto_point_pwm[2] -
- data->pwm1_auto_point_pwm[1]) / reg;
- else
- data->temp1_auto_point_temp[2] = 255;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ amc6821_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- reg = i2c_smbus_read_byte_data(client,
- AMC6821_REG_RTEMP_FAN_CTRL);
- data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
- reg &= 0x07;
- reg = 0x20 >> reg;
- if (reg > 0)
- data->temp2_auto_point_temp[2] =
- data->temp2_auto_point_temp[1] +
- (data->pwm1_auto_point_pwm[2] -
- data->pwm1_auto_point_pwm[1]) / reg;
- else
- data->temp2_auto_point_temp[2] = 255;
+static const struct i2c_device_id amc6821_id[] = {
+ { "amc6821", amc6821 },
+ { }
+};
- reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
- reg = (reg >> 5) & 0x3;
- switch (reg) {
- case 0: /*open loop: software sets pwm1*/
- data->pwm1_auto_channels_temp = 0;
- data->pwm1_enable = 1;
- break;
- case 2: /*closed loop: remote T (temp2)*/
- data->pwm1_auto_channels_temp = 2;
- data->pwm1_enable = 2;
- break;
- case 3: /*closed loop: local and remote T (temp2)*/
- data->pwm1_auto_channels_temp = 3;
- data->pwm1_enable = 3;
- break;
- case 1: /*
- * semi-open loop: software sets rpm, chip controls
- * pwm1, currently not implemented
- */
- data->pwm1_auto_channels_temp = 0;
- data->pwm1_enable = 0;
- break;
- }
+MODULE_DEVICE_TABLE(i2c, amc6821_id);
- data->last_updated = jiffies;
- data->valid = 1;
- }
- mutex_unlock(&data->update_lock);
- return data;
-}
+static struct i2c_driver amc6821_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "amc6821",
+ },
+ .probe = amc6821_probe,
+ .id_table = amc6821_id,
+ .detect = amc6821_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(amc6821_driver);
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index f96063680e58..272fcc837ecc 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -510,6 +510,10 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
err = kstrtoul(buf, 10, &val);
if (err)
return err;
+
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 71463689d163..c77644d45a02 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -300,7 +300,7 @@ static ssize_t store_fan16(struct device *dev,
* respectively. That doesn't mean that's what the motherboard provides. :)
*/
-static int asc7621_in_scaling[] = {
+static const int asc7621_in_scaling[] = {
2500, 2250, 3300, 5000, 12000
};
@@ -451,7 +451,7 @@ static ssize_t store_temp62(struct device *dev,
* hwmon specs, we synthesize the auto_point_2 from them.
*/
-static u32 asc7621_range_map[] = {
+static const u32 asc7621_range_map[] = {
2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000,
13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000,
};
@@ -512,7 +512,7 @@ static ssize_t show_pwm_ac(struct device *dev,
{
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 config, altbit, regval;
- u8 map[] = {
+ const u8 map[] = {
0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f
};
@@ -533,7 +533,7 @@ static ssize_t store_pwm_ac(struct device *dev,
SETUP_STORE_DATA_PARAM(dev, attr);
unsigned long reqval;
u8 currval, config, altbit, newval;
- u16 map[] = {
+ const u16 map[] = {
0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06,
0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -651,7 +651,7 @@ static ssize_t store_pwm_enable(struct device *dev,
return count;
}
-static u32 asc7621_pwm_freq_map[] = {
+static const u32 asc7621_pwm_freq_map[] = {
10, 15, 23, 30, 38, 47, 62, 94,
23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000
};
@@ -700,7 +700,7 @@ static ssize_t store_pwm_freq(struct device *dev,
return count;
}
-static u32 asc7621_pwm_auto_spinup_map[] = {
+static const u32 asc7621_pwm_auto_spinup_map[] = {
0, 100, 250, 400, 700, 1000, 2000, 4000
};
@@ -749,7 +749,7 @@ static ssize_t store_pwm_ast(struct device *dev,
return count;
}
-static u32 asc7621_temp_smoothing_time_map[] = {
+static const u32 asc7621_temp_smoothing_time_map[] = {
35000, 17600, 11800, 7000, 4400, 3000, 1600, 800
};
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index ae208f612198..cccef87963e0 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -688,7 +688,7 @@ static int atk_debugfs_gitm_get(void *p, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
atk_debugfs_gitm_get,
NULL,
- "0x%08llx\n")
+ "0x%08llx\n");
static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
{
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 2ae8a304b5ef..4c829bb2f9db 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -46,7 +46,7 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
struct atxp1_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
unsigned long last_updated;
u8 valid;
@@ -61,11 +61,8 @@ struct atxp1_data {
static struct atxp1_data *atxp1_update_device(struct device *dev)
{
- struct i2c_client *client;
- struct atxp1_data *data;
-
- client = to_i2c_client(dev);
- data = i2c_get_clientdata(client);
+ struct atxp1_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
@@ -105,15 +102,12 @@ static ssize_t atxp1_storevcore(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct atxp1_data *data;
- struct i2c_client *client;
+ struct atxp1_data *data = atxp1_update_device(dev);
+ struct i2c_client *client = data->client;
int vid, cvid;
unsigned long vcore;
int err;
- client = to_i2c_client(dev);
- data = atxp1_update_device(dev);
-
err = kstrtoul(buf, 10, &vcore);
if (err)
return err;
@@ -184,14 +178,11 @@ static ssize_t atxp1_storegpio1(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- struct atxp1_data *data;
- struct i2c_client *client;
+ struct atxp1_data *data = atxp1_update_device(dev);
+ struct i2c_client *client = data->client;
unsigned long value;
int err;
- client = to_i2c_client(dev);
- data = atxp1_update_device(dev);
-
err = kstrtoul(buf, 16, &value);
if (err)
return err;
@@ -234,7 +225,7 @@ static ssize_t atxp1_storegpio2(struct device *dev,
const char *buf, size_t count)
{
struct atxp1_data *data = atxp1_update_device(dev);
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = data->client;
unsigned long value;
int err;
@@ -260,17 +251,13 @@ static ssize_t atxp1_storegpio2(struct device *dev,
*/
static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
-static struct attribute *atxp1_attributes[] = {
+static struct attribute *atxp1_attrs[] = {
&dev_attr_gpio1.attr,
&dev_attr_gpio2.attr,
&dev_attr_cpu0_vid.attr,
NULL
};
-
-static const struct attribute_group atxp1_group = {
- .attrs = atxp1_attributes,
-};
-
+ATTRIBUTE_GROUPS(atxp1);
/* Return 0 if detection is successful, -ENODEV otherwise */
static int atxp1_detect(struct i2c_client *new_client,
@@ -314,50 +301,30 @@ static int atxp1_detect(struct i2c_client *new_client,
return 0;
}
-static int atxp1_probe(struct i2c_client *new_client,
+static int atxp1_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct atxp1_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&new_client->dev, sizeof(struct atxp1_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct atxp1_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
/* Get VRM */
data->vrm = vid_which_vrm();
- i2c_set_clientdata(new_client, data);
+ data->client = client;
mutex_init(&data->update_lock);
- /* Register sysfs hooks */
- err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&new_client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- dev_info(&new_client->dev, "Using VRM: %d.%d\n",
- data->vrm / 10, data->vrm % 10);
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
- return err;
-};
-
-static int atxp1_remove(struct i2c_client *client)
-{
- struct atxp1_data *data = i2c_get_clientdata(client);
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ atxp1_groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &atxp1_group);
+ dev_info(dev, "Using VRM: %d.%d\n", data->vrm / 10, data->vrm % 10);
return 0;
};
@@ -374,7 +341,6 @@ static struct i2c_driver atxp1_driver = {
.name = "atxp1",
},
.probe = atxp1_probe,
- .remove = atxp1_remove,
.id_table = atxp1_id,
.detect = atxp1_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 4ae3fff13f44..bea0a344fab5 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -247,8 +247,8 @@ struct dme1737_data {
u8 pwm_acz[3];
u8 pwm_freq[6];
u8 pwm_rr[2];
- u8 zone_low[3];
- u8 zone_abs[3];
+ s8 zone_low[3];
+ s8 zone_abs[3];
u8 zone_hyst[2];
u32 alarms;
};
@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res)
return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2));
}
-static inline int IN_TO_REG(int val, int nominal)
+static inline int IN_TO_REG(long val, int nominal)
{
return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255);
}
@@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res)
return (reg * 1000) >> (res - 8);
}
-static inline int TEMP_TO_REG(int val)
+static inline int TEMP_TO_REG(long val)
{
return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127);
}
@@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(int reg)
return TEMP_RANGE[(reg >> 4) & 0x0f];
}
-static int TEMP_RANGE_TO_REG(int val, int reg)
+static int TEMP_RANGE_TO_REG(long val, int reg)
{
int i;
@@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix)
return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000;
}
-static inline int TEMP_HYST_TO_REG(int val, int ix, int reg)
+static inline int TEMP_HYST_TO_REG(long val, int ix, int reg)
{
int hyst = clamp_val((val + 500) / 1000, 0, 15);
@@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg, int tpc)
return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg;
}
-static inline int FAN_TO_REG(int val, int tpc)
+static inline int FAN_TO_REG(long val, int tpc)
{
if (tpc) {
return clamp_val(val / tpc, 0, 0xffff);
@@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int reg)
return (edge > 0) ? 1 << (edge - 1) : 0;
}
-static inline int FAN_TYPE_TO_REG(int val, int reg)
+static inline int FAN_TYPE_TO_REG(long val, int reg)
{
int edge = (val == 4) ? 3 : val;
@@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg)
return 1000 + i * 500;
}
-static int FAN_MAX_TO_REG(int val)
+static int FAN_MAX_TO_REG(long val)
{
int i;
@@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int reg)
return acz[(reg >> 5) & 0x07];
}
-static inline int PWM_ACZ_TO_REG(int val, int reg)
+static inline int PWM_ACZ_TO_REG(long val, int reg)
{
int acz = (val == 4) ? 2 : val - 1;
@@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int reg)
return PWM_FREQ[reg & 0x0f];
}
-static int PWM_FREQ_TO_REG(int val, int reg)
+static int PWM_FREQ_TO_REG(long val, int reg)
{
int i;
@@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int reg, int ix)
return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0;
}
-static int PWM_RR_TO_REG(int val, int ix, int reg)
+static int PWM_RR_TO_REG(long val, int ix, int reg)
{
int i;
@@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int reg, int ix)
return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;
}
-static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg)
+static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg)
{
int en = (ix == 1) ? 0x80 : 0x08;
@@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dme1737_data *data = dev_get_drvdata(dev);
- long val;
+ unsigned long val;
int err;
- err = kstrtol(buf, 10, &val);
+ err = kstrtoul(buf, 10, &val);
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c
index 0918b9136588..edf550fc4eef 100644
--- a/drivers/hwmon/ds620.c
+++ b/drivers/hwmon/ds620.c
@@ -67,7 +67,7 @@ static const u8 DS620_REG_TEMP[3] = {
/* Each client has this additional data */
struct ds620_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -106,8 +106,8 @@ static void ds620_init_client(struct i2c_client *client)
static struct ds620_data *ds620_update_client(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds620_data *data = i2c_get_clientdata(client);
+ struct ds620_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct ds620_data *ret = data;
mutex_lock(&data->update_lock);
@@ -158,8 +158,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
long val;
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
- struct ds620_data *data = i2c_get_clientdata(client);
+ struct ds620_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
res = kstrtol(buf, 10, &val);
@@ -181,13 +181,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ds620_data *data = ds620_update_client(dev);
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client;
u16 conf, new_conf;
int res;
if (IS_ERR(data))
return PTR_ERR(data);
+ client = data->client;
+
/* reset alarms if necessary */
res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF);
if (res < 0)
@@ -213,7 +215,7 @@ static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
DS620_REG_CONFIG_THF);
-static struct attribute *ds620_attributes[] = {
+static struct attribute *ds620_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -222,55 +224,28 @@ static struct attribute *ds620_attributes[] = {
NULL
};
-static const struct attribute_group ds620_group = {
- .attrs = ds620_attributes,
-};
+ATTRIBUTE_GROUPS(ds620);
static int ds620_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct ds620_data *data;
- int err;
- data = devm_kzalloc(&client->dev, sizeof(struct ds620_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct ds620_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Initialize the DS620 chip */
ds620_init_client(client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &ds620_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- dev_info(&client->dev, "temperature sensor found\n");
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &ds620_group);
- return err;
-}
-
-static int ds620_remove(struct i2c_client *client)
-{
- struct ds620_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ds620_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, ds620_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id ds620_id[] = {
@@ -287,7 +262,6 @@ static struct i2c_driver ds620_driver = {
.name = "ds620",
},
.probe = ds620_probe,
- .remove = ds620_remove,
.id_table = ds620_id,
};
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index a37b2204a418..1ea7ca510f84 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -416,7 +416,7 @@ static bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg)
}
}
-static struct regmap_config emc1403_regmap_config = {
+static const struct regmap_config emc1403_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
index 78002de46cb6..952fe692d764 100644
--- a/drivers/hwmon/emc2103.c
+++ b/drivers/hwmon/emc2103.c
@@ -66,7 +66,8 @@ struct temperature {
};
struct emc2103_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[4];
struct mutex update_lock;
bool valid; /* registers are valid */
bool fan_rpm_control;
@@ -146,8 +147,8 @@ static void read_fan_config_from_i2c(struct i2c_client *client)
static struct emc2103_data *emc2103_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc2103_data *data = i2c_get_clientdata(client);
+ struct emc2103_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
@@ -242,8 +243,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(da)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct emc2103_data *data = i2c_get_clientdata(client);
+ struct emc2103_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int result = kstrtol(buf, 10, &val);
@@ -264,8 +265,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(da)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct emc2103_data *data = i2c_get_clientdata(client);
+ struct emc2103_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int result = kstrtol(buf, 10, &val);
@@ -310,7 +311,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct emc2103_data *data = emc2103_update_device(dev);
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = data->client;
int new_range_bits, old_div = 8 / data->fan_multiplier;
long new_div;
@@ -385,7 +386,7 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct emc2103_data *data = emc2103_update_device(dev);
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = data->client;
unsigned long rpm_target;
int result = kstrtoul(buf, 10, &rpm_target);
@@ -428,8 +429,8 @@ show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf)
static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc2103_data *data = i2c_get_clientdata(client);
+ struct emc2103_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long new_value;
u8 conf_reg;
@@ -580,7 +581,8 @@ static int
emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct emc2103_data *data;
- int status;
+ struct device *hwmon_dev;
+ int status, idx = 0;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
@@ -591,6 +593,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -ENOMEM;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */
@@ -624,60 +627,21 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &emc2103_group);
- if (status)
- return status;
-
- if (data->temp_count >= 3) {
- status = sysfs_create_group(&client->dev.kobj,
- &emc2103_temp3_group);
- if (status)
- goto exit_remove;
- }
-
- if (data->temp_count == 4) {
- status = sysfs_create_group(&client->dev.kobj,
- &emc2103_temp4_group);
- if (status)
- goto exit_remove_temp3;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove_temp4;
- }
-
- dev_info(&client->dev, "%s: sensor '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-
-exit_remove_temp4:
- if (data->temp_count == 4)
- sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
-exit_remove_temp3:
+ /* sysfs hooks */
+ data->groups[idx++] = &emc2103_group;
if (data->temp_count >= 3)
- sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &emc2103_group);
- return status;
-}
-
-static int emc2103_remove(struct i2c_client *client)
-{
- struct emc2103_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
-
+ data->groups[idx++] = &emc2103_temp3_group;
if (data->temp_count == 4)
- sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group);
+ data->groups[idx++] = &emc2103_temp4_group;
- if (data->temp_count >= 3)
- sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ data->groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &emc2103_group);
+ dev_info(&client->dev, "%s: sensor '%s'\n",
+ dev_name(hwmon_dev), client->name);
return 0;
}
@@ -717,7 +681,6 @@ static struct i2c_driver emc2103_driver = {
.name = "emc2103",
},
.probe = emc2103_probe,
- .remove = emc2103_remove,
.id_table = emc2103_ids,
.detect = emc2103_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c
index f76a74cb6dc4..ada90716448d 100644
--- a/drivers/hwmon/emc6w201.c
+++ b/drivers/hwmon/emc6w201.c
@@ -56,7 +56,7 @@ enum subfeature { input, min, max };
*/
struct emc6w201_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -134,8 +134,8 @@ static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)
static struct emc6w201_data *emc6w201_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc6w201_data *data = i2c_get_clientdata(client);
+ struct emc6w201_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr;
mutex_lock(&data->update_lock);
@@ -203,8 +203,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc6w201_data *data = i2c_get_clientdata(client);
+ struct emc6w201_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int sf = to_sensor_dev_attr_2(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int err;
@@ -240,8 +240,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc6w201_data *data = i2c_get_clientdata(client);
+ struct emc6w201_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int sf = to_sensor_dev_attr_2(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int err;
@@ -252,12 +252,12 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
if (err < 0)
return err;
- val /= 1000;
+ val = DIV_ROUND_CLOSEST(val, 1000);
reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr)
: EMC6W201_REG_TEMP_HIGH(nr);
mutex_lock(&data->update_lock);
- data->temp[sf][nr] = clamp_val(val, -127, 128);
+ data->temp[sf][nr] = clamp_val(val, -127, 127);
err = emc6w201_write8(client, reg, data->temp[sf][nr]);
mutex_unlock(&data->update_lock);
@@ -283,8 +283,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct emc6w201_data *data = i2c_get_clientdata(client);
+ struct emc6w201_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int sf = to_sensor_dev_attr_2(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int err;
@@ -388,7 +388,7 @@ static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input);
static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
4, min);
-static struct attribute *emc6w201_attributes[] = {
+static struct attribute *emc6w201_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -440,9 +440,7 @@ static struct attribute *emc6w201_attributes[] = {
NULL
};
-static const struct attribute_group emc6w201_group = {
- .attrs = emc6w201_attributes,
-};
+ATTRIBUTE_GROUPS(emc6w201);
/*
* Driver interface
@@ -488,44 +486,21 @@ static int emc6w201_detect(struct i2c_client *client,
static int emc6w201_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct emc6w201_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&client->dev, sizeof(struct emc6w201_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct emc6w201_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
- /* Create sysfs attribute */
- err = sysfs_create_group(&client->dev.kobj, &emc6w201_group);
- if (err)
- return err;
-
- /* Expose as a hwmon device */
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
- exit_remove:
- sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
- return err;
-}
-
-static int emc6w201_remove(struct i2c_client *client)
-{
- struct emc6w201_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ emc6w201_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id emc6w201_id[] = {
@@ -540,7 +515,6 @@ static struct i2c_driver emc6w201_driver = {
.name = "emc6w201",
},
.probe = emc6w201_probe,
- .remove = emc6w201_remove,
.id_table = emc6w201_id,
.detect = emc6w201_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 6040121a405a..4a7cbfad1d74 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -31,9 +31,6 @@ 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
@@ -45,7 +42,7 @@ MODULE_LICENSE("GPL");
#define REG_TDP_LIMIT3 0xe8
struct fam15h_power_data {
- struct device *hwmon_dev;
+ struct pci_dev *pdev;
unsigned int tdp_to_watts;
unsigned int base_tdp;
unsigned int processor_pwr_watts;
@@ -57,8 +54,8 @@ static ssize_t show_power(struct device *dev,
u32 val, tdp_limit, running_avg_range;
s32 running_avg_capture;
u64 curr_pwr_watts;
- struct pci_dev *f4 = to_pci_dev(dev);
struct fam15h_power_data *data = dev_get_drvdata(dev);
+ struct pci_dev *f4 = data->pdev;
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_RUNNING_AVERAGE, &val);
@@ -96,23 +93,13 @@ static ssize_t show_power_crit(struct device *dev,
}
static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL);
-static ssize_t show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "fam15h_power\n");
-}
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
static struct attribute *fam15h_power_attrs[] = {
&dev_attr_power1_input.attr,
&dev_attr_power1_crit.attr,
- &dev_attr_name.attr,
NULL
};
-static const struct attribute_group fam15h_power_attr_group = {
- .attrs = fam15h_power_attrs,
-};
+ATTRIBUTE_GROUPS(fam15h_power);
static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
{
@@ -202,7 +189,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
{
struct fam15h_power_data *data;
struct device *dev = &pdev->dev;
- int err;
+ struct device *hwmon_dev;
/*
* though we ignore every other northbridge, we still have to
@@ -219,34 +206,12 @@ static int fam15h_power_probe(struct pci_dev *pdev,
return -ENOMEM;
fam15h_power_init_data(pdev, data);
+ data->pdev = pdev;
- dev_set_drvdata(dev, data);
- err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_group;
- }
-
- return 0;
-
-exit_remove_group:
- sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
- return err;
-}
-
-static void fam15h_power_remove(struct pci_dev *pdev)
-{
- struct device *dev;
- struct fam15h_power_data *data;
-
- dev = &pdev->dev;
- data = dev_get_drvdata(dev);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power",
+ data,
+ fam15h_power_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct pci_device_id fam15h_power_id_table[] = {
@@ -260,7 +225,6 @@ static struct pci_driver fam15h_power_driver = {
.name = "fam15h_power",
.id_table = fam15h_power_id_table,
.probe = fam15h_power_probe,
- .remove = fam15h_power_remove,
.resume = fam15h_power_resume,
};
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index ea6480b80e7f..ec6a77da411a 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -24,12 +24,6 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
-static const struct i2c_device_id g760a_id[] = {
- { "g760a", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, g760a_id);
-
enum g760a_regs {
G760A_REG_SET_CNT = 0x00,
G760A_REG_ACT_CNT = 0x01,
@@ -44,7 +38,6 @@ enum g760a_regs {
struct g760a_data {
struct i2c_client *client;
- struct device *hwmon_dev;
struct mutex update_lock;
/* board specific parameters */
@@ -74,20 +67,6 @@ static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div)
return ((val == 0x00) ? 0 : ((clk*30)/(val*div)));
}
-/* new-style driver model */
-static int g760a_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int g760a_remove(struct i2c_client *client);
-
-static struct i2c_driver g760a_driver = {
- .driver = {
- .name = "g760a",
- },
- .probe = g760a_probe,
- .remove = g760a_remove,
- .id_table = g760a_id,
-};
-
/* read/write wrappers */
static int g760a_read_value(struct i2c_client *client, enum g760a_regs reg)
{
@@ -106,8 +85,8 @@ static int g760a_write_value(struct i2c_client *client, enum g760a_regs reg,
static struct g760a_data *g760a_update_client(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct g760a_data *data = i2c_get_clientdata(client);
+ struct g760a_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
@@ -163,8 +142,8 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *da,
static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g760a_data *data = g760a_update_client(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
if (kstrtoul(buf, 10, &val))
@@ -182,16 +161,14 @@ static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm);
static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL);
static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
-static struct attribute *g760a_attributes[] = {
+static struct attribute *g760a_attrs[] = {
&dev_attr_pwm1.attr,
&dev_attr_fan1_input.attr,
&dev_attr_fan1_alarm.attr,
NULL
};
-static const struct attribute_group g760a_group = {
- .attrs = g760a_attributes,
-};
+ATTRIBUTE_GROUPS(g760a);
/*
* new-style driver model code
@@ -200,20 +177,17 @@ static const struct attribute_group g760a_group = {
static int g760a_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct g760a_data *data;
- int err;
+ struct device *hwmon_dev;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA))
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
- data = devm_kzalloc(&client->dev, sizeof(struct g760a_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct g760a_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
-
data->client = client;
mutex_init(&data->update_lock);
@@ -221,31 +195,25 @@ static int g760a_probe(struct i2c_client *client,
data->fan_div = G760A_DEFAULT_FAN_DIV;
data->clk = G760A_DEFAULT_CLK;
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &g760a_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto error_hwmon_device_register;
- }
-
- return 0;
-
-error_hwmon_device_register:
- sysfs_remove_group(&client->dev.kobj, &g760a_group);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ g760a_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static int g760a_remove(struct i2c_client *client)
-{
- struct g760a_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &g760a_group);
- return 0;
-}
+static const struct i2c_device_id g760a_id[] = {
+ { "g760a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, g760a_id);
+
+static struct i2c_driver g760a_driver = {
+ .driver = {
+ .name = "g760a",
+ },
+ .probe = g760a_probe,
+ .id_table = g760a_id,
+};
module_i2c_driver(g760a_driver);
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 98a8618d8fbf..6aac695b1688 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -128,8 +128,8 @@ enum g762_regs {
G762_REG_FAN_CMD2_GEAR_MODE_1)) >> 2))
struct g762_data {
- struct i2c_client *client;
struct device *hwmon_dev;
+ struct i2c_client *client;
struct clk *clk;
/* update mutex */
@@ -206,8 +206,8 @@ static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p,
/* helper to grab and cache data, at most one time per second */
static struct g762_data *g762_update_client(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct g762_data *data = i2c_get_clientdata(client);
+ struct g762_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ret = 0;
mutex_lock(&data->update_lock);
@@ -266,8 +266,7 @@ static struct g762_data *g762_update_client(struct device *dev)
*/
static int do_set_clk_freq(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct g762_data *data = i2c_get_clientdata(client);
+ struct g762_data *data = dev_get_drvdata(dev);
if (val > 0xffffff)
return -EINVAL;
@@ -282,7 +281,6 @@ static int do_set_clk_freq(struct device *dev, unsigned long val)
/* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */
static int do_set_pwm_mode(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -301,7 +299,7 @@ static int do_set_pwm_mode(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
data->valid = false;
out:
@@ -313,7 +311,6 @@ static int do_set_pwm_mode(struct device *dev, unsigned long val)
/* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */
static int do_set_fan_div(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -342,7 +339,7 @@ static int do_set_fan_div(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
data->valid = false;
out:
@@ -354,7 +351,6 @@ static int do_set_fan_div(struct device *dev, unsigned long val)
/* Set fan gear mode. Accepts either 0, 1 or 2. */
static int do_set_fan_gear_mode(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -379,7 +375,7 @@ static int do_set_fan_gear_mode(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
data->fan_cmd2);
data->valid = false;
out:
@@ -391,7 +387,6 @@ static int do_set_fan_gear_mode(struct device *dev, unsigned long val)
/* Set number of fan pulses per revolution. Accepts either 2 or 4. */
static int do_set_fan_pulses(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -410,7 +405,7 @@ static int do_set_fan_pulses(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
data->valid = false;
out:
@@ -422,7 +417,6 @@ static int do_set_fan_pulses(struct device *dev, unsigned long val)
/* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */
static int do_set_pwm_enable(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -444,15 +438,15 @@ static int do_set_pwm_enable(struct device *dev, unsigned long val)
* value of 254 if it is 255 when switching to open-loop.
*/
if (data->set_cnt == 0xff)
- i2c_smbus_write_byte_data(client, G762_REG_SET_CNT,
- 254);
+ i2c_smbus_write_byte_data(data->client,
+ G762_REG_SET_CNT, 254);
break;
default:
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
data->valid = false;
out:
@@ -464,7 +458,6 @@ static int do_set_pwm_enable(struct device *dev, unsigned long val)
/* Set PWM polarity. Accepts either 0 (positive duty) or 1 (negative duty) */
static int do_set_pwm_polarity(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -483,7 +476,7 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
data->valid = false;
out:
@@ -498,8 +491,8 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val)
*/
static int do_set_pwm(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct g762_data *data = i2c_get_clientdata(client);
+ struct g762_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int ret;
if (val > 255)
@@ -519,7 +512,6 @@ static int do_set_pwm(struct device *dev, unsigned long val)
*/
static int do_set_fan_target(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -531,7 +523,7 @@ static int do_set_fan_target(struct device *dev, unsigned long val)
G762_PULSE_FROM_REG(data->fan_cmd1),
G762_CLKDIV_FROM_REG(data->fan_cmd1),
G762_GEARMULT_FROM_REG(data->fan_cmd2));
- ret = i2c_smbus_write_byte_data(client, G762_REG_SET_CNT,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_SET_CNT,
data->set_cnt);
data->valid = false;
mutex_unlock(&data->update_lock);
@@ -542,7 +534,6 @@ static int do_set_fan_target(struct device *dev, unsigned long val)
/* Set fan startup voltage. Accepted values are either 0, 1, 2 or 3. */
static int do_set_fan_startv(struct device *dev, unsigned long val)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
int ret;
@@ -571,7 +562,7 @@ static int do_set_fan_startv(struct device *dev, unsigned long val)
ret = -EINVAL;
goto out;
}
- ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2,
+ ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2,
data->fan_cmd2);
data->valid = false;
out:
@@ -658,15 +649,12 @@ static int g762_of_prop_import_one(struct i2c_client *client,
int (*psetter)(struct device *dev,
unsigned long val))
{
- const __be32 *prop;
- int len, ret;
+ int ret;
u32 pval;
- prop = of_get_property(client->dev.of_node, pname, &len);
- if (!prop || len != sizeof(u32))
+ if (of_property_read_u32(client->dev.of_node, pname, &pval))
return 0;
- pval = be32_to_cpu(prop[0]);
dev_dbg(&client->dev, "found %s (%d)\n", pname, pval);
ret = (*psetter)(&client->dev, pval);
if (ret)
@@ -1026,7 +1014,7 @@ static DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO,
get_fan_pulses, set_fan_pulses);
/* Driver data */
-static struct attribute *g762_attributes[] = {
+static struct attribute *g762_attrs[] = {
&dev_attr_fan1_input.attr,
&dev_attr_fan1_alarm.attr,
&dev_attr_fan1_fault.attr,
@@ -1039,9 +1027,7 @@ static struct attribute *g762_attributes[] = {
NULL
};
-static const struct attribute_group g762_group = {
- .attrs = g762_attributes,
-};
+ATTRIBUTE_GROUPS(g762);
/*
* Enable both fan failure detection and fan out of control protection. The
@@ -1050,7 +1036,6 @@ static const struct attribute_group g762_group = {
*/
static inline int g762_fan_init(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
struct g762_data *data = g762_update_client(dev);
if (IS_ERR(data))
@@ -1060,12 +1045,13 @@ static inline int g762_fan_init(struct device *dev)
data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC;
data->valid = false;
- return i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1,
+ return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1,
data->fan_cmd1);
}
static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct g762_data *data;
int ret;
@@ -1073,7 +1059,7 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
- data = devm_kzalloc(&client->dev, sizeof(struct g762_data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct g762_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -1082,7 +1068,7 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&data->update_lock);
/* Enable fan failure detection and fan out of control protection */
- ret = g762_fan_init(&client->dev);
+ ret = g762_fan_init(dev);
if (ret)
return ret;
@@ -1098,22 +1084,17 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
if (ret)
goto clock_dis;
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &g762_group);
- if (ret)
- goto clock_dis;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
+ data->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+ client->name,
+ data,
+ g762_groups);
if (IS_ERR(data->hwmon_dev)) {
ret = PTR_ERR(data->hwmon_dev);
- goto sysfs_rem;
+ goto clock_dis;
}
return 0;
- sysfs_rem:
- sysfs_remove_group(&client->dev.kobj, &g762_group);
-
clock_dis:
g762_of_clock_disable(client);
@@ -1125,7 +1106,6 @@ static int g762_remove(struct i2c_client *client)
struct g762_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &g762_group);
g762_of_clock_disable(client);
return 0;
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 1e9830513045..0212c8317bca 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -114,7 +114,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
/* Each client has this additional data */
struct gl518_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
enum chips type;
struct mutex update_lock;
@@ -137,33 +138,98 @@ struct gl518_data {
u8 beep_enable; /* Boolean */
};
-static int gl518_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info);
-static void gl518_init_client(struct i2c_client *client);
-static int gl518_remove(struct i2c_client *client);
-static int gl518_read_value(struct i2c_client *client, u8 reg);
-static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
-static struct gl518_data *gl518_update_device(struct device *dev);
+/*
+ * Registers 0x07 to 0x0c are word-sized, others are byte-sized
+ * GL518 uses a high-byte first convention, which is exactly opposite to
+ * the SMBus standard.
+ */
+static int gl518_read_value(struct i2c_client *client, u8 reg)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return i2c_smbus_read_word_swapped(client, reg);
+ else
+ return i2c_smbus_read_byte_data(client, reg);
+}
-static const struct i2c_device_id gl518_id[] = {
- { "gl518sm", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, gl518_id);
+static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return i2c_smbus_write_word_swapped(client, reg, value);
+ else
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
-/* This is the driver that will be inserted */
-static struct i2c_driver gl518_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "gl518sm",
- },
- .probe = gl518_probe,
- .remove = gl518_remove,
- .id_table = gl518_id,
- .detect = gl518_detect,
- .address_list = normal_i2c,
-};
+static struct gl518_data *gl518_update_device(struct device *dev)
+{
+ struct gl518_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int val;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ dev_dbg(&client->dev, "Starting gl518 update\n");
+
+ data->alarms = gl518_read_value(client, GL518_REG_INT);
+ data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
+
+ val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
+ data->voltage_min[0] = val & 0xff;
+ data->voltage_max[0] = (val >> 8) & 0xff;
+ val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
+ data->voltage_min[1] = val & 0xff;
+ data->voltage_max[1] = (val >> 8) & 0xff;
+ val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
+ data->voltage_min[2] = val & 0xff;
+ data->voltage_max[2] = (val >> 8) & 0xff;
+ val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
+ data->voltage_min[3] = val & 0xff;
+ data->voltage_max[3] = (val >> 8) & 0xff;
+
+ val = gl518_read_value(client, GL518_REG_FAN_COUNT);
+ data->fan_in[0] = (val >> 8) & 0xff;
+ data->fan_in[1] = val & 0xff;
+
+ val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
+ data->fan_min[0] = (val >> 8) & 0xff;
+ data->fan_min[1] = val & 0xff;
+
+ data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN);
+ data->temp_max =
+ gl518_read_value(client, GL518_REG_TEMP_MAX);
+ data->temp_hyst =
+ gl518_read_value(client, GL518_REG_TEMP_HYST);
+
+ val = gl518_read_value(client, GL518_REG_MISC);
+ data->fan_div[0] = (val >> 6) & 0x03;
+ data->fan_div[1] = (val >> 4) & 0x03;
+ data->fan_auto1 = (val >> 3) & 0x01;
+
+ data->alarms &= data->alarm_mask;
+
+ val = gl518_read_value(client, GL518_REG_CONF);
+ data->beep_enable = (val >> 2) & 1;
+
+ if (data->type != gl518sm_r00) {
+ data->voltage_in[0] =
+ gl518_read_value(client, GL518_REG_VDD);
+ data->voltage_in[1] =
+ gl518_read_value(client, GL518_REG_VIN1);
+ data->voltage_in[2] =
+ gl518_read_value(client, GL518_REG_VIN2);
+ }
+ data->voltage_in[3] =
+ gl518_read_value(client, GL518_REG_VIN3);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
/*
* Sysfs stuff
@@ -228,8 +294,8 @@ static ssize_t set_##suffix(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct gl518_data *data = i2c_get_clientdata(client); \
+ struct gl518_data *data = dev_get_drvdata(dev); \
+ struct i2c_client *client = data->client; \
long val; \
int err = kstrtol(buf, 10, &val); \
if (err) \
@@ -247,8 +313,8 @@ static ssize_t set_##suffix(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct gl518_data *data = i2c_get_clientdata(client); \
+ struct gl518_data *data = dev_get_drvdata(dev); \
+ struct i2c_client *client = data->client; \
int regvalue; \
unsigned long val; \
int err = kstrtoul(buf, 10, &val); \
@@ -286,8 +352,8 @@ set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl518_data *data = i2c_get_clientdata(client);
+ struct gl518_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
int regvalue;
unsigned long val;
@@ -319,8 +385,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl518_data *data = i2c_get_clientdata(client);
+ struct gl518_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int nr = to_sensor_dev_attr(attr)->index;
int regvalue;
unsigned long val;
@@ -420,8 +486,8 @@ static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl518_data *data = i2c_get_clientdata(client);
+ struct gl518_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int bitnr = to_sensor_dev_attr(attr)->index;
unsigned long bit;
int err;
@@ -539,52 +605,6 @@ static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
-static int gl518_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct gl518_data *data;
- int err, revision;
-
- data = devm_kzalloc(&client->dev, sizeof(struct gl518_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- revision = gl518_read_value(client, GL518_REG_REVISION);
- data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
- mutex_init(&data->update_lock);
-
- /* Initialize the GL518SM chip */
- data->alarm_mask = 0xff;
- gl518_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &gl518_group);
- if (err)
- return err;
- if (data->type == gl518sm_r80) {
- err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80);
- if (err)
- goto exit_remove_files;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &gl518_group);
- if (data->type == gl518sm_r80)
- sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
- return err;
-}
-
-
/*
* Called when we have found a new GL518SM.
* Note that we preserve D4:NoFan2 and D2:beep_enable.
@@ -605,110 +625,53 @@ static void gl518_init_client(struct i2c_client *client)
gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
}
-static int gl518_remove(struct i2c_client *client)
-{
- struct gl518_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &gl518_group);
- if (data->type == gl518sm_r80)
- sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
-
- return 0;
-}
-
-/*
- * Registers 0x07 to 0x0c are word-sized, others are byte-sized
- * GL518 uses a high-byte first convention, which is exactly opposite to
- * the SMBus standard.
- */
-static int gl518_read_value(struct i2c_client *client, u8 reg)
-{
- if ((reg >= 0x07) && (reg <= 0x0c))
- return i2c_smbus_read_word_swapped(client, reg);
- else
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
- if ((reg >= 0x07) && (reg <= 0x0c))
- return i2c_smbus_write_word_swapped(client, reg, value);
- else
- return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static struct gl518_data *gl518_update_device(struct device *dev)
+static int gl518_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl518_data *data = i2c_get_clientdata(client);
- int val;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- dev_dbg(&client->dev, "Starting gl518 update\n");
-
- data->alarms = gl518_read_value(client, GL518_REG_INT);
- data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
-
- val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
- data->voltage_min[0] = val & 0xff;
- data->voltage_max[0] = (val >> 8) & 0xff;
- val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
- data->voltage_min[1] = val & 0xff;
- data->voltage_max[1] = (val >> 8) & 0xff;
- val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
- data->voltage_min[2] = val & 0xff;
- data->voltage_max[2] = (val >> 8) & 0xff;
- val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
- data->voltage_min[3] = val & 0xff;
- data->voltage_max[3] = (val >> 8) & 0xff;
-
- val = gl518_read_value(client, GL518_REG_FAN_COUNT);
- data->fan_in[0] = (val >> 8) & 0xff;
- data->fan_in[1] = val & 0xff;
-
- val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
- data->fan_min[0] = (val >> 8) & 0xff;
- data->fan_min[1] = val & 0xff;
-
- data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN);
- data->temp_max =
- gl518_read_value(client, GL518_REG_TEMP_MAX);
- data->temp_hyst =
- gl518_read_value(client, GL518_REG_TEMP_HYST);
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct gl518_data *data;
+ int revision;
- val = gl518_read_value(client, GL518_REG_MISC);
- data->fan_div[0] = (val >> 6) & 0x03;
- data->fan_div[1] = (val >> 4) & 0x03;
- data->fan_auto1 = (val >> 3) & 0x01;
+ data = devm_kzalloc(dev, sizeof(struct gl518_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- data->alarms &= data->alarm_mask;
+ data->client = client;
+ revision = gl518_read_value(client, GL518_REG_REVISION);
+ data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
+ mutex_init(&data->update_lock);
- val = gl518_read_value(client, GL518_REG_CONF);
- data->beep_enable = (val >> 2) & 1;
+ /* Initialize the GL518SM chip */
+ data->alarm_mask = 0xff;
+ gl518_init_client(client);
- if (data->type != gl518sm_r00) {
- data->voltage_in[0] =
- gl518_read_value(client, GL518_REG_VDD);
- data->voltage_in[1] =
- gl518_read_value(client, GL518_REG_VIN1);
- data->voltage_in[2] =
- gl518_read_value(client, GL518_REG_VIN2);
- }
- data->voltage_in[3] =
- gl518_read_value(client, GL518_REG_VIN3);
+ /* sysfs hooks */
+ data->groups[0] = &gl518_group;
+ if (data->type == gl518sm_r80)
+ data->groups[1] = &gl518_group_r80;
- data->last_updated = jiffies;
- data->valid = 1;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id gl518_id[] = {
+ { "gl518sm", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, gl518_id);
- return data;
-}
+static struct i2c_driver gl518_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "gl518sm",
+ },
+ .probe = gl518_probe,
+ .id_table = gl518_id,
+ .detect = gl518_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(gl518_driver);
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index ed56e09c3dd7..dee93ec87d02 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -73,41 +73,10 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 };
#define GL520_REG_BEEP_MASK 0x10
#define GL520_REG_BEEP_ENABLE GL520_REG_CONF
-/*
- * Function declarations
- */
-
-static int gl520_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info);
-static void gl520_init_client(struct i2c_client *client);
-static int gl520_remove(struct i2c_client *client);
-static int gl520_read_value(struct i2c_client *client, u8 reg);
-static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
-static struct gl520_data *gl520_update_device(struct device *dev);
-
-/* Driver data */
-static const struct i2c_device_id gl520_id[] = {
- { "gl520sm", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, gl520_id);
-
-static struct i2c_driver gl520_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "gl520sm",
- },
- .probe = gl520_probe,
- .remove = gl520_remove,
- .id_table = gl520_id,
- .detect = gl520_detect,
- .address_list = normal_i2c,
-};
-
/* Client data */
struct gl520_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
char valid; /* zero until the following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -132,6 +101,102 @@ struct gl520_data {
};
/*
+ * Registers 0x07 to 0x0c are word-sized, others are byte-sized
+ * GL520 uses a high-byte first convention
+ */
+static int gl520_read_value(struct i2c_client *client, u8 reg)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return i2c_smbus_read_word_swapped(client, reg);
+ else
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return i2c_smbus_write_word_swapped(client, reg, value);
+ else
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static struct gl520_data *gl520_update_device(struct device *dev)
+{
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int val, i;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+
+ dev_dbg(&client->dev, "Starting gl520sm update\n");
+
+ data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
+ data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+ data->vid = gl520_read_value(client,
+ GL520_REG_VID_INPUT) & 0x1f;
+
+ for (i = 0; i < 4; i++) {
+ data->in_input[i] = gl520_read_value(client,
+ GL520_REG_IN_INPUT[i]);
+ val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]);
+ data->in_min[i] = val & 0xff;
+ data->in_max[i] = (val >> 8) & 0xff;
+ }
+
+ val = gl520_read_value(client, GL520_REG_FAN_INPUT);
+ data->fan_input[0] = (val >> 8) & 0xff;
+ data->fan_input[1] = val & 0xff;
+
+ val = gl520_read_value(client, GL520_REG_FAN_MIN);
+ data->fan_min[0] = (val >> 8) & 0xff;
+ data->fan_min[1] = val & 0xff;
+
+ data->temp_input[0] = gl520_read_value(client,
+ GL520_REG_TEMP_INPUT[0]);
+ data->temp_max[0] = gl520_read_value(client,
+ GL520_REG_TEMP_MAX[0]);
+ data->temp_max_hyst[0] = gl520_read_value(client,
+ GL520_REG_TEMP_MAX_HYST[0]);
+
+ val = gl520_read_value(client, GL520_REG_FAN_DIV);
+ data->fan_div[0] = (val >> 6) & 0x03;
+ data->fan_div[1] = (val >> 4) & 0x03;
+ data->fan_off = (val >> 2) & 0x01;
+
+ data->alarms &= data->alarm_mask;
+
+ val = gl520_read_value(client, GL520_REG_CONF);
+ data->beep_enable = !((val >> 2) & 1);
+
+ /* Temp1 and Vin4 are the same input */
+ if (data->two_temps) {
+ data->temp_input[1] = gl520_read_value(client,
+ GL520_REG_TEMP_INPUT[1]);
+ data->temp_max[1] = gl520_read_value(client,
+ GL520_REG_TEMP_MAX[1]);
+ data->temp_max_hyst[1] = gl520_read_value(client,
+ GL520_REG_TEMP_MAX_HYST[1]);
+ } else {
+ data->in_input[4] = gl520_read_value(client,
+ GL520_REG_IN_INPUT[4]);
+ data->in_min[4] = gl520_read_value(client,
+ GL520_REG_IN_MIN[4]);
+ data->in_max[4] = gl520_read_value(client,
+ GL520_REG_IN_MAX[4]);
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+/*
* Sysfs stuff
*/
@@ -191,8 +256,8 @@ static ssize_t get_in_max(struct device *dev, struct device_attribute *attr,
static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
u8 r;
long v;
@@ -225,8 +290,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
u8 r;
long v;
@@ -326,8 +391,8 @@ static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr,
static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
u8 r;
unsigned long v;
@@ -365,8 +430,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
u8 r;
unsigned long v;
@@ -414,8 +479,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 r;
unsigned long v;
int err;
@@ -482,8 +547,8 @@ static ssize_t get_temp_max_hyst(struct device *dev,
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
long v;
int err;
@@ -502,8 +567,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
*attr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int n = to_sensor_dev_attr(attr)->index;
long v;
int err;
@@ -555,8 +620,8 @@ static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr,
static ssize_t set_beep_enable(struct device *dev, struct device_attribute
*attr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 r;
unsigned long v;
int err;
@@ -579,8 +644,8 @@ static ssize_t set_beep_enable(struct device *dev, struct device_attribute
static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long r;
int err;
@@ -633,8 +698,8 @@ static ssize_t get_beep(struct device *dev, struct device_attribute *attr,
static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct gl520_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int bitnr = to_sensor_dev_attr(attr)->index;
unsigned long bit;
@@ -772,52 +837,6 @@ static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
-static int gl520_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct gl520_data *data;
- int err;
-
- data = devm_kzalloc(&client->dev, sizeof(struct gl520_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- /* Initialize the GL520SM chip */
- gl520_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &gl520_group);
- if (err)
- return err;
-
- if (data->two_temps)
- err = sysfs_create_group(&client->dev.kobj, &gl520_group_temp2);
- else
- err = sysfs_create_group(&client->dev.kobj, &gl520_group_in4);
-
- if (err)
- goto exit_remove_files;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &gl520_group);
- sysfs_remove_group(&client->dev.kobj, &gl520_group_in4);
- sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2);
- return err;
-}
-
-
/* Called when we have found a new GL520SM. */
static void gl520_init_client(struct i2c_client *client)
{
@@ -856,115 +875,53 @@ static void gl520_init_client(struct i2c_client *client)
gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
}
-static int gl520_remove(struct i2c_client *client)
+static int gl520_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct gl520_data *data = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct gl520_data *data;
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &gl520_group);
- sysfs_remove_group(&client->dev.kobj, &gl520_group_in4);
- sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2);
+ data = devm_kzalloc(dev, sizeof(struct gl520_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- return 0;
-}
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->client = client;
+ /* Initialize the GL520SM chip */
+ gl520_init_client(client);
-/*
- * Registers 0x07 to 0x0c are word-sized, others are byte-sized
- * GL520 uses a high-byte first convention
- */
-static int gl520_read_value(struct i2c_client *client, u8 reg)
-{
- if ((reg >= 0x07) && (reg <= 0x0c))
- return i2c_smbus_read_word_swapped(client, reg);
- else
- return i2c_smbus_read_byte_data(client, reg);
-}
+ /* sysfs hooks */
+ data->groups[0] = &gl520_group;
-static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
- if ((reg >= 0x07) && (reg <= 0x0c))
- return i2c_smbus_write_word_swapped(client, reg, value);
+ if (data->two_temps)
+ data->groups[1] = &gl520_group_temp2;
else
- return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-
-static struct gl520_data *gl520_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct gl520_data *data = i2c_get_clientdata(client);
- int val, i;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
-
- dev_dbg(&client->dev, "Starting gl520sm update\n");
-
- data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
- data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
- data->vid = gl520_read_value(client,
- GL520_REG_VID_INPUT) & 0x1f;
-
- for (i = 0; i < 4; i++) {
- data->in_input[i] = gl520_read_value(client,
- GL520_REG_IN_INPUT[i]);
- val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]);
- data->in_min[i] = val & 0xff;
- data->in_max[i] = (val >> 8) & 0xff;
- }
-
- val = gl520_read_value(client, GL520_REG_FAN_INPUT);
- data->fan_input[0] = (val >> 8) & 0xff;
- data->fan_input[1] = val & 0xff;
+ data->groups[1] = &gl520_group_in4;
- val = gl520_read_value(client, GL520_REG_FAN_MIN);
- data->fan_min[0] = (val >> 8) & 0xff;
- data->fan_min[1] = val & 0xff;
-
- data->temp_input[0] = gl520_read_value(client,
- GL520_REG_TEMP_INPUT[0]);
- data->temp_max[0] = gl520_read_value(client,
- GL520_REG_TEMP_MAX[0]);
- data->temp_max_hyst[0] = gl520_read_value(client,
- GL520_REG_TEMP_MAX_HYST[0]);
-
- val = gl520_read_value(client, GL520_REG_FAN_DIV);
- data->fan_div[0] = (val >> 6) & 0x03;
- data->fan_div[1] = (val >> 4) & 0x03;
- data->fan_off = (val >> 2) & 0x01;
-
- data->alarms &= data->alarm_mask;
-
- val = gl520_read_value(client, GL520_REG_CONF);
- data->beep_enable = !((val >> 2) & 1);
-
- /* Temp1 and Vin4 are the same input */
- if (data->two_temps) {
- data->temp_input[1] = gl520_read_value(client,
- GL520_REG_TEMP_INPUT[1]);
- data->temp_max[1] = gl520_read_value(client,
- GL520_REG_TEMP_MAX[1]);
- data->temp_max_hyst[1] = gl520_read_value(client,
- GL520_REG_TEMP_MAX_HYST[1]);
- } else {
- data->in_input[4] = gl520_read_value(client,
- GL520_REG_IN_INPUT[4]);
- data->in_min[4] = gl520_read_value(client,
- GL520_REG_IN_MIN[4]);
- data->in_max[4] = gl520_read_value(client,
- GL520_REG_IN_MAX[4]);
- }
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id gl520_id[] = {
+ { "gl520sm", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, gl520_id);
- return data;
-}
+static struct i2c_driver gl520_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "gl520sm",
+ },
+ .probe = gl520_probe,
+ .id_table = gl520_id,
+ .detect = gl520_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(gl520_driver);
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 2566c43dd1e9..4efa1734bdad 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -173,7 +173,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data)
return -ENODEV;
}
-static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
+static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm)
{
struct gpio_fan_speed *speed = fan_data->speed;
int i;
@@ -537,9 +537,10 @@ static int gpio_fan_probe(struct platform_device *pdev)
}
/* Make this driver part of hwmon class. */
- fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
- "gpio_fan", fan_data,
- gpio_fan_groups);
+ fan_data->hwmon_dev =
+ devm_hwmon_device_register_with_groups(&pdev->dev,
+ "gpio_fan", fan_data,
+ gpio_fan_groups);
if (IS_ERR(fan_data->hwmon_dev))
return PTR_ERR(fan_data->hwmon_dev);
@@ -548,15 +549,6 @@ static int gpio_fan_probe(struct platform_device *pdev)
return 0;
}
-static int gpio_fan_remove(struct platform_device *pdev)
-{
- struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
-
- hwmon_device_unregister(fan_data->hwmon_dev);
-
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int gpio_fan_suspend(struct device *dev)
{
@@ -588,7 +580,6 @@ 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 = gpio_fan_remove,
.driver = {
.name = "gpio-fan",
.pm = GPIO_FAN_PM,
diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
index 7d68a08baaa8..7b73d2002d3e 100644
--- a/drivers/hwmon/hih6130.c
+++ b/drivers/hwmon/hih6130.c
@@ -46,7 +46,7 @@
* @write_length: length for I2C measurement request
*/
struct hih6130 {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock;
bool valid;
unsigned long last_update;
@@ -62,7 +62,6 @@ struct hih6130 {
*/
static inline int hih6130_temp_ticks_to_millicelsius(int ticks)
{
-
ticks = ticks >> 2;
/*
* from data sheet section 5.0
@@ -78,7 +77,6 @@ static inline int hih6130_temp_ticks_to_millicelsius(int ticks)
*/
static inline int hih6130_rh_ticks_to_per_cent_mille(int ticks)
{
-
ticks &= ~0xC000; /* clear status bits */
/*
* from data sheet section 4.0
@@ -89,15 +87,16 @@ static inline int hih6130_rh_ticks_to_per_cent_mille(int ticks)
/**
* hih6130_update_measurements() - get updated measurements from device
- * @client: I2C client device
+ * @dev: device
*
* Returns 0 on success, else negative errno.
*/
-static int hih6130_update_measurements(struct i2c_client *client)
+static int hih6130_update_measurements(struct device *dev)
{
+ struct hih6130 *hih6130 = dev_get_drvdata(dev);
+ struct i2c_client *client = hih6130->client;
int ret = 0;
int t;
- struct hih6130 *hih6130 = i2c_get_clientdata(client);
unsigned char tmp[4];
struct i2c_msg msgs[1] = {
{
@@ -176,9 +175,10 @@ static ssize_t hih6130_show_temperature(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct hih6130 *hih6130 = i2c_get_clientdata(client);
- int ret = hih6130_update_measurements(client);
+ struct hih6130 *hih6130 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = hih6130_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", hih6130->temperature);
@@ -196,9 +196,10 @@ static ssize_t hih6130_show_temperature(struct device *dev,
static ssize_t hih6130_show_humidity(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct hih6130 *hih6130 = i2c_get_clientdata(client);
- int ret = hih6130_update_measurements(client);
+ struct hih6130 *hih6130 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = hih6130_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", hih6130->humidity);
@@ -210,79 +211,40 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, hih6130_show_temperature,
static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, hih6130_show_humidity,
NULL, 0);
-static struct attribute *hih6130_attributes[] = {
+static struct attribute *hih6130_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_humidity1_input.dev_attr.attr,
NULL
};
-static const struct attribute_group hih6130_attr_group = {
- .attrs = hih6130_attributes,
-};
+ATTRIBUTE_GROUPS(hih6130);
-/**
- * hih6130_probe() - probe device
- * @client: I2C client device
- * @id: device ID
- *
- * Called by the I2C core when an entry in the ID table matches a
- * device's name.
- * Returns 0 on success.
- */
static int hih6130_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct hih6130 *hih6130;
- int err;
+ struct device *hwmon_dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "adapter does not support true I2C\n");
return -ENODEV;
}
- hih6130 = devm_kzalloc(&client->dev, sizeof(*hih6130), GFP_KERNEL);
+ hih6130 = devm_kzalloc(dev, sizeof(*hih6130), GFP_KERNEL);
if (!hih6130)
return -ENOMEM;
- i2c_set_clientdata(client, hih6130);
-
+ hih6130->client = client;
mutex_init(&hih6130->lock);
- err = sysfs_create_group(&client->dev.kobj, &hih6130_attr_group);
- if (err) {
- dev_dbg(&client->dev, "could not create sysfs files\n");
- return err;
- }
-
- hih6130->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(hih6130->hwmon_dev)) {
- dev_dbg(&client->dev, "unable to register hwmon device\n");
- err = PTR_ERR(hih6130->hwmon_dev);
- goto fail_remove_sysfs;
- }
-
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
hih6130->write_length = 1;
- return 0;
-
-fail_remove_sysfs:
- sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group);
- return err;
-}
-
-/**
- * hih6130_remove() - remove device
- * @client: I2C client device
- */
-static int hih6130_remove(struct i2c_client *client)
-{
- struct hih6130 *hih6130 = i2c_get_clientdata(client);
-
- hwmon_device_unregister(hih6130->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ hih6130,
+ hih6130_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
/* Device ID table */
@@ -295,7 +257,6 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id);
static struct i2c_driver hih6130_driver = {
.driver.name = "hih6130",
.probe = hih6130_probe,
- .remove = hih6130_remove,
.id_table = hih6130_id,
};
diff --git a/drivers/hwmon/htu21.c b/drivers/hwmon/htu21.c
index 839086e0e951..4c3bbb72f82a 100644
--- a/drivers/hwmon/htu21.c
+++ b/drivers/hwmon/htu21.c
@@ -31,7 +31,7 @@
#define HTU21_RH_MEASUREMENT_HM 0xE5
struct htu21 {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock;
bool valid;
unsigned long last_update;
@@ -59,10 +59,11 @@ static inline int htu21_rh_ticks_to_per_cent_mille(int ticks)
return ((15625 * ticks) >> 13) - 6000;
}
-static int htu21_update_measurements(struct i2c_client *client)
+static int htu21_update_measurements(struct device *dev)
{
+ struct htu21 *htu21 = dev_get_drvdata(dev);
+ struct i2c_client *client = htu21->client;
int ret = 0;
- struct htu21 *htu21 = i2c_get_clientdata(client);
mutex_lock(&htu21->lock);
@@ -90,9 +91,10 @@ out:
static ssize_t htu21_show_temperature(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct htu21 *htu21 = i2c_get_clientdata(client);
- int ret = htu21_update_measurements(client);
+ struct htu21 *htu21 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = htu21_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", htu21->temperature);
@@ -101,9 +103,10 @@ static ssize_t htu21_show_temperature(struct device *dev,
static ssize_t htu21_show_humidity(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct htu21 *htu21 = i2c_get_clientdata(client);
- int ret = htu21_update_measurements(client);
+ struct htu21 *htu21 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = htu21_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", htu21->humidity);
@@ -114,21 +117,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO,
htu21_show_humidity, NULL, 0);
-static struct attribute *htu21_attributes[] = {
+static struct attribute *htu21_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_humidity1_input.dev_attr.attr,
NULL
};
-static const struct attribute_group htu21_group = {
- .attrs = htu21_attributes,
-};
+ATTRIBUTE_GROUPS(htu21);
static int htu21_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct htu21 *htu21;
- int err;
+ struct device *hwmon_dev;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA)) {
@@ -137,43 +139,17 @@ static int htu21_probe(struct i2c_client *client,
return -ENODEV;
}
- htu21 = devm_kzalloc(&client->dev, sizeof(*htu21), GFP_KERNEL);
+ htu21 = devm_kzalloc(dev, sizeof(*htu21), GFP_KERNEL);
if (!htu21)
return -ENOMEM;
- i2c_set_clientdata(client, htu21);
-
+ htu21->client = client;
mutex_init(&htu21->lock);
- err = sysfs_create_group(&client->dev.kobj, &htu21_group);
- if (err) {
- dev_dbg(&client->dev, "could not create sysfs files\n");
- return err;
- }
- htu21->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(htu21->hwmon_dev)) {
- dev_dbg(&client->dev, "unable to register hwmon device\n");
- err = PTR_ERR(htu21->hwmon_dev);
- goto error;
- }
-
- dev_info(&client->dev, "initialized\n");
-
- return 0;
-
-error:
- sysfs_remove_group(&client->dev.kobj, &htu21_group);
- return err;
-}
-
-static int htu21_remove(struct i2c_client *client)
-{
- struct htu21 *htu21 = i2c_get_clientdata(client);
-
- hwmon_device_unregister(htu21->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &htu21_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ htu21,
+ htu21_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id htu21_id[] = {
@@ -188,7 +164,6 @@ static struct i2c_driver htu21_driver = {
.name = "htu21",
},
.probe = htu21_probe,
- .remove = htu21_remove,
.id_table = htu21_id,
};
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 632f1dc0fe1f..7a8a6fbf11ff 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -842,11 +842,10 @@ static ssize_t aem_show_power(struct device *dev,
struct aem_data *data = dev_get_drvdata(dev);
u64 before, after, delta, time;
signed long leftover;
- struct timespec b, a;
mutex_lock(&data->lock);
update_aem_energy_one(data, attr->index);
- getnstimeofday(&b);
+ time = ktime_get_ns();
before = data->energy[attr->index];
leftover = schedule_timeout_interruptible(
@@ -858,11 +857,10 @@ static ssize_t aem_show_power(struct device *dev,
}
update_aem_energy_one(data, attr->index);
- getnstimeofday(&a);
+ time = ktime_get_ns() - time;
after = data->energy[attr->index];
mutex_unlock(&data->lock);
- time = timespec_to_ns(&a) - timespec_to_ns(&b);
delta = (after - before) * UJ_PER_MJ;
return sprintf(buf, "%llu\n",
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
new file mode 100644
index 000000000000..d2bf2c97ae70
--- /dev/null
+++ b/drivers/hwmon/ibmpowernv.c
@@ -0,0 +1,363 @@
+/*
+ * IBM PowerNV platform sensors for temperature/fan/voltage/power
+ * Copyright (C) 2014 IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+#define DRVNAME "ibmpowernv"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <linux/platform_device.h>
+#include <asm/opal.h>
+#include <linux/err.h>
+
+#define MAX_ATTR_LEN 32
+
+/* Sensor suffix name from DT */
+#define DT_FAULT_ATTR_SUFFIX "faulted"
+#define DT_DATA_ATTR_SUFFIX "data"
+#define DT_THRESHOLD_ATTR_SUFFIX "thrs"
+
+/*
+ * Enumerates all the types of sensors in the POWERNV platform and does index
+ * into 'struct sensor_group'
+ */
+enum sensors {
+ FAN,
+ AMBIENT_TEMP,
+ POWER_SUPPLY,
+ POWER_INPUT,
+ MAX_SENSOR_TYPE,
+};
+
+static struct sensor_group {
+ const char *name;
+ const char *compatible;
+ struct attribute_group group;
+ u32 attr_count;
+} sensor_groups[] = {
+ {"fan", "ibm,opal-sensor-cooling-fan"},
+ {"temp", "ibm,opal-sensor-amb-temp"},
+ {"in", "ibm,opal-sensor-power-supply"},
+ {"power", "ibm,opal-sensor-power"}
+};
+
+struct sensor_data {
+ u32 id; /* An opaque id of the firmware for each sensor */
+ enum sensors type;
+ char name[MAX_ATTR_LEN];
+ struct device_attribute dev_attr;
+};
+
+struct platform_data {
+ const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];
+ u32 sensors_count; /* Total count of sensors from each group */
+};
+
+/* Platform device representing all the ibmpowernv sensors */
+static struct platform_device *pdevice;
+
+static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_data *sdata = container_of(devattr, struct sensor_data,
+ dev_attr);
+ ssize_t ret;
+ u32 x;
+
+ ret = opal_get_sensor_data(sdata->id, &x);
+ if (ret)
+ return ret;
+
+ /* Convert temperature to milli-degrees */
+ if (sdata->type == AMBIENT_TEMP)
+ x *= 1000;
+ /* Convert power to micro-watts */
+ else if (sdata->type == POWER_INPUT)
+ x *= 1000000;
+
+ return sprintf(buf, "%u\n", x);
+}
+
+static int __init get_sensor_index_attr(const char *name, u32 *index,
+ char *attr)
+{
+ char *hash_pos = strchr(name, '#');
+ char buf[8] = { 0 };
+ char *dash_pos;
+ u32 copy_len;
+ int err;
+
+ if (!hash_pos)
+ return -EINVAL;
+
+ dash_pos = strchr(hash_pos, '-');
+ if (!dash_pos)
+ return -EINVAL;
+
+ copy_len = dash_pos - hash_pos - 1;
+ if (copy_len >= sizeof(buf))
+ return -EINVAL;
+
+ strncpy(buf, hash_pos + 1, copy_len);
+
+ err = kstrtou32(buf, 10, index);
+ if (err)
+ return err;
+
+ strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
+
+ return 0;
+}
+
+/*
+ * This function translates the DT node name into the 'hwmon' attribute name.
+ * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
+ * which need to be mapped as fan2_input, temp1_max respectively before
+ * populating them inside hwmon device class.
+ */
+static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
+ const char *node_name,
+ char *hwmon_attr_name)
+{
+ char attr_suffix[MAX_ATTR_LEN];
+ char *attr_name;
+ u32 index;
+ int err;
+
+ err = get_sensor_index_attr(node_name, &index, attr_suffix);
+ if (err) {
+ dev_err(dev, "Sensor device node name '%s' is invalid\n",
+ node_name);
+ return err;
+ }
+
+ if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {
+ attr_name = "fault";
+ } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {
+ attr_name = "input";
+ } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {
+ if (type == AMBIENT_TEMP)
+ attr_name = "max";
+ else if (type == FAN)
+ attr_name = "min";
+ else
+ return -ENOENT;
+ } else {
+ return -ENOENT;
+ }
+
+ snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s",
+ sensor_groups[type].name, index, attr_name);
+ return 0;
+}
+
+static int __init populate_attr_groups(struct platform_device *pdev)
+{
+ struct platform_data *pdata = platform_get_drvdata(pdev);
+ const struct attribute_group **pgroups = pdata->attr_groups;
+ struct device_node *opal, *np;
+ enum sensors type;
+
+ opal = of_find_node_by_path("/ibm,opal/sensors");
+ if (!opal) {
+ dev_err(&pdev->dev, "Opal node 'sensors' not found\n");
+ return -ENODEV;
+ }
+
+ for_each_child_of_node(opal, np) {
+ if (np->name == NULL)
+ continue;
+
+ for (type = 0; type < MAX_SENSOR_TYPE; type++)
+ if (of_device_is_compatible(np,
+ sensor_groups[type].compatible)) {
+ sensor_groups[type].attr_count++;
+ break;
+ }
+ }
+
+ of_node_put(opal);
+
+ for (type = 0; type < MAX_SENSOR_TYPE; type++) {
+ sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,
+ sizeof(struct attribute *) *
+ (sensor_groups[type].attr_count + 1),
+ GFP_KERNEL);
+ if (!sensor_groups[type].group.attrs)
+ return -ENOMEM;
+
+ pgroups[type] = &sensor_groups[type].group;
+ pdata->sensors_count += sensor_groups[type].attr_count;
+ sensor_groups[type].attr_count = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * Iterate through the device tree for each child of 'sensors' node, create
+ * a sysfs attribute file, the file is named by translating the DT node name
+ * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
+ * etc..
+ */
+static int __init create_device_attrs(struct platform_device *pdev)
+{
+ struct platform_data *pdata = platform_get_drvdata(pdev);
+ const struct attribute_group **pgroups = pdata->attr_groups;
+ struct device_node *opal, *np;
+ struct sensor_data *sdata;
+ u32 sensor_id;
+ enum sensors type;
+ u32 count = 0;
+ int err = 0;
+
+ opal = of_find_node_by_path("/ibm,opal/sensors");
+ sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),
+ GFP_KERNEL);
+ if (!sdata) {
+ err = -ENOMEM;
+ goto exit_put_node;
+ }
+
+ for_each_child_of_node(opal, np) {
+ if (np->name == NULL)
+ continue;
+
+ for (type = 0; type < MAX_SENSOR_TYPE; type++)
+ if (of_device_is_compatible(np,
+ sensor_groups[type].compatible))
+ break;
+
+ if (type == MAX_SENSOR_TYPE)
+ continue;
+
+ if (of_property_read_u32(np, "sensor-id", &sensor_id)) {
+ dev_info(&pdev->dev,
+ "'sensor-id' missing in the node '%s'\n",
+ np->name);
+ continue;
+ }
+
+ sdata[count].id = sensor_id;
+ sdata[count].type = type;
+ err = create_hwmon_attr_name(&pdev->dev, type, np->name,
+ sdata[count].name);
+ if (err)
+ goto exit_put_node;
+
+ sysfs_attr_init(&sdata[count].dev_attr.attr);
+ sdata[count].dev_attr.attr.name = sdata[count].name;
+ sdata[count].dev_attr.attr.mode = S_IRUGO;
+ sdata[count].dev_attr.show = show_sensor;
+
+ pgroups[type]->attrs[sensor_groups[type].attr_count++] =
+ &sdata[count++].dev_attr.attr;
+ }
+
+exit_put_node:
+ of_node_put(opal);
+ return err;
+}
+
+static int __init ibmpowernv_probe(struct platform_device *pdev)
+{
+ struct platform_data *pdata;
+ struct device *hwmon_dev;
+ int err;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pdata);
+ pdata->sensors_count = 0;
+ err = populate_attr_groups(pdev);
+ if (err)
+ return err;
+
+ /* Create sysfs attribute data for each sensor found in the DT */
+ err = create_device_attrs(pdev);
+ if (err)
+ return err;
+
+ /* Finally, register with hwmon */
+ hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
+ pdata,
+ pdata->attr_groups);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct platform_driver ibmpowernv_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+};
+
+static int __init ibmpowernv_init(void)
+{
+ int err;
+
+ pdevice = platform_device_alloc(DRVNAME, 0);
+ if (!pdevice) {
+ pr_err("Device allocation failed\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ err = platform_device_add(pdevice);
+ if (err) {
+ pr_err("Device addition failed (%d)\n", err);
+ goto exit_device_put;
+ }
+
+ err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
+ if (err) {
+ pr_err("Platfrom driver probe failed\n");
+ goto exit_device_del;
+ }
+
+ return 0;
+
+exit_device_del:
+ platform_device_del(pdevice);
+exit_device_put:
+ platform_device_put(pdevice);
+exit:
+ return err;
+}
+
+static void __exit ibmpowernv_exit(void)
+{
+ platform_driver_unregister(&ibmpowernv_driver);
+ platform_device_unregister(pdevice);
+}
+
+MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM POWERNV platform sensors");
+MODULE_LICENSE("GPL");
+
+module_init(ibmpowernv_init);
+module_exit(ibmpowernv_exit);
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c
index ebbb9f4f27a3..84d791bdb62d 100644
--- a/drivers/hwmon/lineage-pem.c
+++ b/drivers/hwmon/lineage-pem.c
@@ -125,7 +125,8 @@
#define FAN_SPEED_LEN 5
struct pem_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[4];
struct mutex update_lock;
bool valid;
@@ -160,8 +161,8 @@ abort:
static struct pem_data *pem_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct pem_data *data = i2c_get_clientdata(client);
+ struct pem_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct pem_data *ret = data;
mutex_lock(&data->update_lock);
@@ -444,18 +445,20 @@ static int pem_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct pem_data *data;
- int ret;
+ int ret, idx = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE))
return -ENODEV;
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/*
@@ -471,14 +474,12 @@ static int pem_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- dev_info(&client->dev, "Firmware revision %d.%d.%d\n",
+ dev_info(dev, "Firmware revision %d.%d.%d\n",
data->firmware_rev[0], data->firmware_rev[1],
data->firmware_rev[2]);
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &pem_group);
- if (ret)
- return ret;
+ /* sysfs hooks */
+ data->groups[idx++] = &pem_group;
/*
* Check if input readings are supported.
@@ -501,12 +502,9 @@ static int pem_probe(struct i2c_client *client,
data->input_string[2] || data->input_string[3]))
data->input_length = sizeof(data->input_string);
}
- ret = 0;
- if (data->input_length) {
- ret = sysfs_create_group(&client->dev.kobj, &pem_input_group);
- if (ret)
- goto out_remove_groups;
- }
+
+ if (data->input_length)
+ data->groups[idx++] = &pem_input_group;
/*
* Check if fan speed readings are supported.
@@ -520,37 +518,12 @@ static int pem_probe(struct i2c_client *client,
if (!ret && (data->fan_speed[0] || data->fan_speed[1] ||
data->fan_speed[2] || data->fan_speed[3])) {
data->fans_supported = true;
- ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group);
- if (ret)
- goto out_remove_groups;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_remove_groups;
+ data->groups[idx++] = &pem_fan_group;
}
- return 0;
-
-out_remove_groups:
- sysfs_remove_group(&client->dev.kobj, &pem_input_group);
- sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
- sysfs_remove_group(&client->dev.kobj, &pem_group);
- return ret;
-}
-
-static int pem_remove(struct i2c_client *client)
-{
- struct pem_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
-
- sysfs_remove_group(&client->dev.kobj, &pem_input_group);
- sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
- sysfs_remove_group(&client->dev.kobj, &pem_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id pem_id[] = {
@@ -564,7 +537,6 @@ static struct i2c_driver pem_driver = {
.name = "lineage_pem",
},
.probe = pem_probe,
- .remove = pem_remove,
.id_table = pem_id,
};
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 848b9611151f..33bfdb444138 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -126,24 +126,17 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
#define FAN_TO_REG(val) ((val) <= 82 ? 0xFFFC : \
(5400000 / (val)) & 0xFFFC)
#define TEMP8_FROM_REG(reg) ((reg) * 1000)
-#define TEMP8_TO_REG(val) ((val) <= -128000 ? -128 : \
- (val) >= 127000 ? 127 : \
- (val) < 0 ? ((val) - 500) / 1000 : \
- ((val) + 500) / 1000)
-#define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \
- (val) >= 255000 ? 255 : \
- ((val) + 500) / 1000)
+#define TEMP8_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+ 127000), 1000)
+#define TEMP8U_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, \
+ 255000), 1000)
#define TEMP11_FROM_REG(reg) ((reg) / 32 * 125)
-#define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \
- (val) >= 127875 ? 0x7FE0 : \
- (val) < 0 ? ((val) - 62) / 125 * 32 : \
- ((val) + 62) / 125 * 32)
-#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \
- (val) >= 255875 ? 0xFFE0 : \
- ((val) + 62) / 125 * 32)
-#define HYST_TO_REG(val) ((val) <= 0 ? 0 : \
- (val) >= 127000 ? 127 : \
- ((val) + 500) / 1000)
+#define TEMP11_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+ 127875), 125) * 32)
+#define TEMP11U_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), 0, \
+ 255875), 125) * 32)
+#define HYST_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
+ 1000)
#define UPDATE_INTERVAL(max, rate) \
((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 479ffbeed3f8..d16dbb33a531 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -52,6 +52,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
tmp100,
tmp101,
tmp105,
+ tmp112,
tmp175,
tmp275,
tmp75,
@@ -255,6 +256,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->sample_time = HZ;
clr_mask |= 1 << 7; /* not one-shot mode */
break;
+ case tmp112:
+ set_mask |= 3 << 5; /* 12-bit mode */
+ clr_mask |= 1 << 7; /* not one-shot mode */
+ data->resolution = 12;
+ data->sample_time = HZ / 4;
+ break;
case tmp105:
case tmp175:
case tmp275:
@@ -323,6 +330,7 @@ static const struct i2c_device_id lm75_ids[] = {
{ "tmp100", tmp100, },
{ "tmp101", tmp101, },
{ "tmp105", tmp105, },
+ { "tmp112", tmp112, },
{ "tmp175", tmp175, },
{ "tmp275", tmp275, },
{ "tmp75", tmp75, },
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 5ceb443b938d..69b05cc2f60e 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -80,8 +80,7 @@ struct lm77_data {
*/
static inline s16 LM77_TEMP_TO_REG(int temp)
{
- int ntemp = clamp_val(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
- return (ntemp / 500) * 8;
+ return (temp / 500) * 8;
}
static inline int LM77_TEMP_FROM_REG(s16 reg)
@@ -175,6 +174,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
if (err)
return err;
+ val = clamp_val(val, LM77_TEMP_MIN, LM77_TEMP_MAX);
mutex_lock(&data->update_lock);
data->temp[nr] = val;
lm77_write_value(client, temp_regs[nr], LM77_TEMP_TO_REG(val));
@@ -192,15 +192,16 @@ static ssize_t set_temp_hyst(struct device *dev,
{
struct lm77_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
- unsigned long val;
+ long val;
int err;
- err = kstrtoul(buf, 10, &val);
+ err = kstrtol(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
- data->temp[t_hyst] = data->temp[t_crit] - val;
+ val = clamp_val(data->temp[t_crit] - val, LM77_TEMP_MIN, LM77_TEMP_MAX);
+ data->temp[t_hyst] = val;
lm77_write_value(client, LM77_REG_TEMP_HYST,
LM77_TEMP_TO_REG(data->temp[t_hyst]));
mutex_unlock(&data->update_lock);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 9efadfc851bc..759661c7d480 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, int div)
* TEMP: mC (-128C to +127C)
* REG: 1C/bit, two's complement
*/
-static inline s8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(long val)
{
int nval = clamp_val(val, -128000, 127000) ;
return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000;
@@ -123,7 +123,6 @@ static inline int TEMP_FROM_REG(s8 val)
struct lm78_data {
struct i2c_client *client;
- struct device *hwmon_dev;
struct mutex lock;
enum chips type;
@@ -468,7 +467,7 @@ static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11);
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
-static struct attribute *lm78_attributes[] = {
+static struct attribute *lm78_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
@@ -519,9 +518,7 @@ static struct attribute *lm78_attributes[] = {
NULL
};
-static const struct attribute_group lm78_group = {
- .attrs = lm78_attributes,
-};
+ATTRIBUTE_GROUPS(lm78);
/*
* ISA related code
@@ -533,19 +530,6 @@ static struct platform_device *pdev;
static unsigned short isa_address = 0x290;
-/*
- * I2C devices get this name attribute automatically, but for ISA devices
- * we must create it by ourselves.
- */
-static ssize_t show_name(struct device *dev, struct device_attribute
- *devattr, char *buf)
-{
- struct lm78_data *data = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", data->name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
static struct lm78_data *lm78_data_if_isa(void)
{
return pdev ? platform_get_drvdata(pdev) : NULL;
@@ -661,46 +645,23 @@ static int lm78_i2c_detect(struct i2c_client *client,
static int lm78_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct lm78_data *data;
- int err;
- data = devm_kzalloc(&client->dev, sizeof(struct lm78_data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
data->client = client;
data->type = id->driver_data;
/* Initialize the LM78 chip */
lm78_init_device(data);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &lm78_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto error;
- }
-
- return 0;
-
-error:
- sysfs_remove_group(&client->dev.kobj, &lm78_group);
- return err;
-}
-
-static int lm78_i2c_remove(struct i2c_client *client)
-{
- struct lm78_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &lm78_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, lm78_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id lm78_i2c_id[] = {
@@ -716,7 +677,6 @@ static struct i2c_driver lm78_driver = {
.name = "lm78",
},
.probe = lm78_i2c_probe,
- .remove = lm78_i2c_remove,
.id_table = lm78_i2c_id,
.detect = lm78_i2c_detect,
.address_list = normal_i2c,
@@ -839,17 +799,18 @@ static struct lm78_data *lm78_update_device(struct device *dev)
#ifdef CONFIG_ISA
static int lm78_isa_probe(struct platform_device *pdev)
{
- int err;
+ struct device *dev = &pdev->dev;
+ struct device *hwmon_dev;
struct lm78_data *data;
struct resource *res;
/* Reserve the ISA region */
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (!devm_request_region(&pdev->dev, res->start + LM78_ADDR_REG_OFFSET,
+ if (!devm_request_region(dev, res->start + LM78_ADDR_REG_OFFSET,
2, "lm78"))
return -EBUSY;
- data = devm_kzalloc(&pdev->dev, sizeof(struct lm78_data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -868,37 +829,9 @@ static int lm78_isa_probe(struct platform_device *pdev)
/* Initialize the LM78 chip */
lm78_init_device(data);
- /* Register sysfs hooks */
- err = sysfs_create_group(&pdev->dev.kobj, &lm78_group);
- if (err)
- goto exit_remove_files;
- err = device_create_file(&pdev->dev, &dev_attr_name);
- if (err)
- goto exit_remove_files;
-
- data->hwmon_dev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
- exit_remove_files:
- sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
- device_remove_file(&pdev->dev, &dev_attr_name);
- return err;
-}
-
-static int lm78_isa_remove(struct platform_device *pdev)
-{
- struct lm78_data *data = platform_get_drvdata(pdev);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&pdev->dev.kobj, &lm78_group);
- device_remove_file(&pdev->dev, &dev_attr_name);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
+ data, lm78_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static struct platform_driver lm78_isa_driver = {
@@ -907,7 +840,6 @@ static struct platform_driver lm78_isa_driver = {
.name = "lm78",
},
.probe = lm78_isa_probe,
- .remove = lm78_isa_remove,
};
/* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index b0129a54e1a6..2b4b419273fe 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -121,7 +121,6 @@ enum chips {
#define EMC6D102_REG_EXTEND_ADC3 0x87
#define EMC6D102_REG_EXTEND_ADC4 0x88
-
/*
* Conversions. Rounding and limit checking is only done on the TO_REG
* variants. Note that you should be a bit careful with which arguments
@@ -155,7 +154,7 @@ static inline u16 FAN_TO_REG(unsigned long val)
/* Temperature is reported in .001 degC increments */
#define TEMP_TO_REG(val) \
- clamp_val(SCALE(val, 1000, 1), -127, 127)
+ DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000)
#define TEMPEXT_FROM_REG(val, ext) \
SCALE(((val) << 4) + (ext), 16, 1000)
#define TEMP_FROM_REG(val) ((val) * 1000)
@@ -189,7 +188,7 @@ static const int lm85_range_map[] = {
13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000
};
-static int RANGE_TO_REG(int range)
+static int RANGE_TO_REG(long range)
{
int i;
@@ -211,7 +210,7 @@ static const int adm1027_freq_map[8] = { /* 1 Hz */
11, 15, 22, 29, 35, 44, 59, 88
};
-static int FREQ_TO_REG(const int *map, int freq)
+static int FREQ_TO_REG(const int *map, unsigned long freq)
{
int i;
@@ -303,7 +302,8 @@ struct lm85_autofan {
* The structure is dynamically allocated.
*/
struct lm85_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[6];
const int *freq_map;
enum chips type;
@@ -334,44 +334,235 @@ struct lm85_data {
struct lm85_zone zone[3];
};
-static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info);
-static int lm85_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int lm85_remove(struct i2c_client *client);
+static int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+ int res;
-static int lm85_read_value(struct i2c_client *client, u8 reg);
-static void lm85_write_value(struct i2c_client *client, u8 reg, int value);
-static struct lm85_data *lm85_update_device(struct device *dev);
+ /* What size location is it? */
+ switch (reg) {
+ case LM85_REG_FAN(0): /* Read WORD data */
+ case LM85_REG_FAN(1):
+ case LM85_REG_FAN(2):
+ case LM85_REG_FAN(3):
+ case LM85_REG_FAN_MIN(0):
+ case LM85_REG_FAN_MIN(1):
+ case LM85_REG_FAN_MIN(2):
+ case LM85_REG_FAN_MIN(3):
+ case LM85_REG_ALARM1: /* Read both bytes at once */
+ res = i2c_smbus_read_byte_data(client, reg) & 0xff;
+ res |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
+ break;
+ default: /* Read BYTE data */
+ res = i2c_smbus_read_byte_data(client, reg);
+ break;
+ }
+ return res;
+}
-static const struct i2c_device_id lm85_id[] = {
- { "adm1027", adm1027 },
- { "adt7463", adt7463 },
- { "adt7468", adt7468 },
- { "lm85", lm85 },
- { "lm85b", lm85 },
- { "lm85c", lm85 },
- { "emc6d100", emc6d100 },
- { "emc6d101", emc6d100 },
- { "emc6d102", emc6d102 },
- { "emc6d103", emc6d103 },
- { "emc6d103s", emc6d103s },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, lm85_id);
+static void lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+ switch (reg) {
+ case LM85_REG_FAN(0): /* Write WORD data */
+ case LM85_REG_FAN(1):
+ case LM85_REG_FAN(2):
+ case LM85_REG_FAN(3):
+ case LM85_REG_FAN_MIN(0):
+ case LM85_REG_FAN_MIN(1):
+ case LM85_REG_FAN_MIN(2):
+ case LM85_REG_FAN_MIN(3):
+ /* NOTE: ALARM is read only, so not included here */
+ i2c_smbus_write_byte_data(client, reg, value & 0xff);
+ i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
+ break;
+ default: /* Write BYTE data */
+ i2c_smbus_write_byte_data(client, reg, value);
+ break;
+ }
+}
-static struct i2c_driver lm85_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "lm85",
- },
- .probe = lm85_probe,
- .remove = lm85_remove,
- .id_table = lm85_id,
- .detect = lm85_detect,
- .address_list = normal_i2c,
-};
+static struct lm85_data *lm85_update_device(struct device *dev)
+{
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (!data->valid ||
+ time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) {
+ /* Things that change quickly */
+ dev_dbg(&client->dev, "Reading sensor values\n");
+
+ /*
+ * Have to read extended bits first to "freeze" the
+ * more significant bits that are read later.
+ * There are 2 additional resolution bits per channel and we
+ * have room for 4, so we shift them to the left.
+ */
+ if (data->type == adm1027 || data->type == adt7463 ||
+ data->type == adt7468) {
+ int ext1 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC2);
+ int val = (ext1 << 8) + ext2;
+
+ for (i = 0; i <= 4; i++)
+ data->in_ext[i] =
+ ((val >> (i * 2)) & 0x03) << 2;
+
+ for (i = 0; i <= 2; i++)
+ data->temp_ext[i] =
+ (val >> ((i + 4) * 2)) & 0x0c;
+ }
+
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 3; ++i) {
+ data->in[i] =
+ lm85_read_value(client, LM85_REG_IN(i));
+ data->fan[i] =
+ lm85_read_value(client, LM85_REG_FAN(i));
+ }
+
+ if (!data->has_vid5)
+ data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
+
+ if (data->type == adt7468)
+ data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
+ for (i = 0; i <= 2; ++i) {
+ data->temp[i] =
+ lm85_read_value(client, LM85_REG_TEMP(i));
+ data->pwm[i] =
+ lm85_read_value(client, LM85_REG_PWM(i));
+
+ if (IS_ADT7468_OFF64(data))
+ data->temp[i] -= 64;
+ }
+
+ data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+ if (data->type == emc6d100) {
+ /* Three more voltage sensors */
+ for (i = 5; i <= 7; ++i) {
+ data->in[i] = lm85_read_value(client,
+ EMC6D100_REG_IN(i));
+ }
+ /* More alarm bits */
+ data->alarms |= lm85_read_value(client,
+ EMC6D100_REG_ALARM3) << 16;
+ } else if (data->type == emc6d102 || data->type == emc6d103 ||
+ data->type == emc6d103s) {
+ /*
+ * Have to read LSB bits after the MSB ones because
+ * the reading of the MSB bits has frozen the
+ * LSBs (backward from the ADM1027).
+ */
+ int ext1 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC2);
+ int ext3 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC3);
+ int ext4 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC4);
+ data->in_ext[0] = ext3 & 0x0f;
+ data->in_ext[1] = ext4 & 0x0f;
+ data->in_ext[2] = ext4 >> 4;
+ data->in_ext[3] = ext3 >> 4;
+ data->in_ext[4] = ext2 >> 4;
+
+ data->temp_ext[0] = ext1 & 0x0f;
+ data->temp_ext[1] = ext2 & 0x0f;
+ data->temp_ext[2] = ext1 >> 4;
+ }
+
+ data->last_reading = jiffies;
+ } /* last_reading */
+
+ if (!data->valid ||
+ time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) {
+ /* Things that don't change often */
+ dev_dbg(&client->dev, "Reading config values\n");
+
+ for (i = 0; i <= 3; ++i) {
+ data->in_min[i] =
+ lm85_read_value(client, LM85_REG_IN_MIN(i));
+ data->in_max[i] =
+ lm85_read_value(client, LM85_REG_IN_MAX(i));
+ data->fan_min[i] =
+ lm85_read_value(client, LM85_REG_FAN_MIN(i));
+ }
+
+ if (!data->has_vid5) {
+ data->in_min[4] = lm85_read_value(client,
+ LM85_REG_IN_MIN(4));
+ data->in_max[4] = lm85_read_value(client,
+ LM85_REG_IN_MAX(4));
+ }
+
+ if (data->type == emc6d100) {
+ for (i = 5; i <= 7; ++i) {
+ data->in_min[i] = lm85_read_value(client,
+ EMC6D100_REG_IN_MIN(i));
+ data->in_max[i] = lm85_read_value(client,
+ EMC6D100_REG_IN_MAX(i));
+ }
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ int val;
+
+ data->temp_min[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+ data->temp_max[i] =
+ lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+
+ data->autofan[i].config =
+ lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+ val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+ data->pwm_freq[i] = val & 0x07;
+ data->zone[i].range = val >> 4;
+ data->autofan[i].min_pwm =
+ lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+ data->zone[i].limit =
+ lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+ data->zone[i].critical =
+ lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+
+ if (IS_ADT7468_OFF64(data)) {
+ data->temp_min[i] -= 64;
+ data->temp_max[i] -= 64;
+ data->zone[i].limit -= 64;
+ data->zone[i].critical -= 64;
+ }
+ }
+
+ if (data->type != emc6d103s) {
+ i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+ data->autofan[0].min_off = (i & 0x20) != 0;
+ data->autofan[1].min_off = (i & 0x40) != 0;
+ data->autofan[2].min_off = (i & 0x80) != 0;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+ data->zone[0].hyst = i >> 4;
+ data->zone[1].hyst = i & 0x0f;
+
+ i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+ data->zone[2].hyst = i >> 4;
+ }
+
+ data->last_config = jiffies;
+ } /* last_config */
+
+ data->valid = 1;
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
/* 4 Fans */
static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
@@ -394,8 +585,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -460,6 +651,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
@@ -515,8 +709,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -557,8 +751,8 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
*attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 config;
unsigned long val;
int err;
@@ -615,8 +809,8 @@ static ssize_t set_pwm_freq(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -682,8 +876,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -710,8 +904,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -766,8 +960,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -797,8 +991,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -843,8 +1037,8 @@ static ssize_t set_pwm_auto_channels(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -873,8 +1067,8 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -902,8 +1096,8 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 tmp;
long val;
int err;
@@ -953,8 +1147,8 @@ static ssize_t set_temp_auto_temp_off(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int min;
long val;
int err;
@@ -990,8 +1184,8 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1029,8 +1223,8 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int min;
long val;
int err;
@@ -1063,8 +1257,8 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
+ struct lm85_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1355,30 +1549,18 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
-static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
-{
- sysfs_remove_group(&client->dev.kobj, &lm85_group);
- if (data->type != emc6d103s) {
- sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
- sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
- }
- if (!data->has_vid5)
- sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
- if (data->type == emc6d100)
- sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
-}
-
-static int lm85_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct lm85_data *data;
- int err;
+ int idx = 0;
- data = devm_kzalloc(&client->dev, sizeof(struct lm85_data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct lm85_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
data->type = id->driver_data;
mutex_init(&data->update_lock);
@@ -1403,20 +1585,13 @@ static int lm85_probe(struct i2c_client *client,
/* Initialize the LM85 chip */
lm85_init_client(client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &lm85_group);
- if (err)
- return err;
+ /* sysfs hooks */
+ data->groups[idx++] = &lm85_group;
/* minctl and temp_off exist on all chips except emc6d103s */
if (data->type != emc6d103s) {
- err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
- if (err)
- goto err_remove_files;
- err = sysfs_create_group(&client->dev.kobj,
- &lm85_group_temp_off);
- if (err)
- goto err_remove_files;
+ data->groups[idx++] = &lm85_group_minctl;
+ data->groups[idx++] = &lm85_group_temp_off;
}
/*
@@ -1429,271 +1604,44 @@ static int lm85_probe(struct i2c_client *client,
data->has_vid5 = true;
}
- if (!data->has_vid5) {
- err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4);
- if (err)
- goto err_remove_files;
- }
+ if (!data->has_vid5)
+ data->groups[idx++] = &lm85_group_in4;
/* The EMC6D100 has 3 additional voltage inputs */
- if (data->type == emc6d100) {
- err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567);
- if (err)
- goto err_remove_files;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto err_remove_files;
- }
-
- return 0;
-
- /* Error out and cleanup code */
- err_remove_files:
- lm85_remove_files(client, data);
- return err;
-}
-
-static int lm85_remove(struct i2c_client *client)
-{
- struct lm85_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- lm85_remove_files(client, data);
- return 0;
-}
-
-
-static int lm85_read_value(struct i2c_client *client, u8 reg)
-{
- int res;
-
- /* What size location is it? */
- switch (reg) {
- case LM85_REG_FAN(0): /* Read WORD data */
- case LM85_REG_FAN(1):
- case LM85_REG_FAN(2):
- case LM85_REG_FAN(3):
- case LM85_REG_FAN_MIN(0):
- case LM85_REG_FAN_MIN(1):
- case LM85_REG_FAN_MIN(2):
- case LM85_REG_FAN_MIN(3):
- case LM85_REG_ALARM1: /* Read both bytes at once */
- res = i2c_smbus_read_byte_data(client, reg) & 0xff;
- res |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
- break;
- default: /* Read BYTE data */
- res = i2c_smbus_read_byte_data(client, reg);
- break;
- }
-
- return res;
-}
+ if (data->type == emc6d100)
+ data->groups[idx++] = &lm85_group_in567;
-static void lm85_write_value(struct i2c_client *client, u8 reg, int value)
-{
- switch (reg) {
- case LM85_REG_FAN(0): /* Write WORD data */
- case LM85_REG_FAN(1):
- case LM85_REG_FAN(2):
- case LM85_REG_FAN(3):
- case LM85_REG_FAN_MIN(0):
- case LM85_REG_FAN_MIN(1):
- case LM85_REG_FAN_MIN(2):
- case LM85_REG_FAN_MIN(3):
- /* NOTE: ALARM is read only, so not included here */
- i2c_smbus_write_byte_data(client, reg, value & 0xff);
- i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
- break;
- default: /* Write BYTE data */
- i2c_smbus_write_byte_data(client, reg, value);
- break;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static struct lm85_data *lm85_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm85_data *data = i2c_get_clientdata(client);
- int i;
-
- mutex_lock(&data->update_lock);
-
- if (!data->valid ||
- time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) {
- /* Things that change quickly */
- dev_dbg(&client->dev, "Reading sensor values\n");
-
- /*
- * Have to read extended bits first to "freeze" the
- * more significant bits that are read later.
- * There are 2 additional resolution bits per channel and we
- * have room for 4, so we shift them to the left.
- */
- if (data->type == adm1027 || data->type == adt7463 ||
- data->type == adt7468) {
- int ext1 = lm85_read_value(client,
- ADM1027_REG_EXTEND_ADC1);
- int ext2 = lm85_read_value(client,
- ADM1027_REG_EXTEND_ADC2);
- int val = (ext1 << 8) + ext2;
-
- for (i = 0; i <= 4; i++)
- data->in_ext[i] =
- ((val >> (i * 2)) & 0x03) << 2;
-
- for (i = 0; i <= 2; i++)
- data->temp_ext[i] =
- (val >> ((i + 4) * 2)) & 0x0c;
- }
-
- data->vid = lm85_read_value(client, LM85_REG_VID);
-
- for (i = 0; i <= 3; ++i) {
- data->in[i] =
- lm85_read_value(client, LM85_REG_IN(i));
- data->fan[i] =
- lm85_read_value(client, LM85_REG_FAN(i));
- }
-
- if (!data->has_vid5)
- data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
-
- if (data->type == adt7468)
- data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
-
- for (i = 0; i <= 2; ++i) {
- data->temp[i] =
- lm85_read_value(client, LM85_REG_TEMP(i));
- data->pwm[i] =
- lm85_read_value(client, LM85_REG_PWM(i));
-
- if (IS_ADT7468_OFF64(data))
- data->temp[i] -= 64;
- }
-
- data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
-
- if (data->type == emc6d100) {
- /* Three more voltage sensors */
- for (i = 5; i <= 7; ++i) {
- data->in[i] = lm85_read_value(client,
- EMC6D100_REG_IN(i));
- }
- /* More alarm bits */
- data->alarms |= lm85_read_value(client,
- EMC6D100_REG_ALARM3) << 16;
- } else if (data->type == emc6d102 || data->type == emc6d103 ||
- data->type == emc6d103s) {
- /*
- * Have to read LSB bits after the MSB ones because
- * the reading of the MSB bits has frozen the
- * LSBs (backward from the ADM1027).
- */
- int ext1 = lm85_read_value(client,
- EMC6D102_REG_EXTEND_ADC1);
- int ext2 = lm85_read_value(client,
- EMC6D102_REG_EXTEND_ADC2);
- int ext3 = lm85_read_value(client,
- EMC6D102_REG_EXTEND_ADC3);
- int ext4 = lm85_read_value(client,
- EMC6D102_REG_EXTEND_ADC4);
- data->in_ext[0] = ext3 & 0x0f;
- data->in_ext[1] = ext4 & 0x0f;
- data->in_ext[2] = ext4 >> 4;
- data->in_ext[3] = ext3 >> 4;
- data->in_ext[4] = ext2 >> 4;
-
- data->temp_ext[0] = ext1 & 0x0f;
- data->temp_ext[1] = ext2 & 0x0f;
- data->temp_ext[2] = ext1 >> 4;
- }
-
- data->last_reading = jiffies;
- } /* last_reading */
-
- if (!data->valid ||
- time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) {
- /* Things that don't change often */
- dev_dbg(&client->dev, "Reading config values\n");
-
- for (i = 0; i <= 3; ++i) {
- data->in_min[i] =
- lm85_read_value(client, LM85_REG_IN_MIN(i));
- data->in_max[i] =
- lm85_read_value(client, LM85_REG_IN_MAX(i));
- data->fan_min[i] =
- lm85_read_value(client, LM85_REG_FAN_MIN(i));
- }
-
- if (!data->has_vid5) {
- data->in_min[4] = lm85_read_value(client,
- LM85_REG_IN_MIN(4));
- data->in_max[4] = lm85_read_value(client,
- LM85_REG_IN_MAX(4));
- }
-
- if (data->type == emc6d100) {
- for (i = 5; i <= 7; ++i) {
- data->in_min[i] = lm85_read_value(client,
- EMC6D100_REG_IN_MIN(i));
- data->in_max[i] = lm85_read_value(client,
- EMC6D100_REG_IN_MAX(i));
- }
- }
-
- for (i = 0; i <= 2; ++i) {
- int val;
-
- data->temp_min[i] =
- lm85_read_value(client, LM85_REG_TEMP_MIN(i));
- data->temp_max[i] =
- lm85_read_value(client, LM85_REG_TEMP_MAX(i));
-
- data->autofan[i].config =
- lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
- val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
- data->pwm_freq[i] = val & 0x07;
- data->zone[i].range = val >> 4;
- data->autofan[i].min_pwm =
- lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
- data->zone[i].limit =
- lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
- data->zone[i].critical =
- lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
-
- if (IS_ADT7468_OFF64(data)) {
- data->temp_min[i] -= 64;
- data->temp_max[i] -= 64;
- data->zone[i].limit -= 64;
- data->zone[i].critical -= 64;
- }
- }
-
- if (data->type != emc6d103s) {
- i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
- data->autofan[0].min_off = (i & 0x20) != 0;
- data->autofan[1].min_off = (i & 0x40) != 0;
- data->autofan[2].min_off = (i & 0x80) != 0;
-
- i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
- data->zone[0].hyst = i >> 4;
- data->zone[1].hyst = i & 0x0f;
-
- i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
- data->zone[2].hyst = i >> 4;
- }
-
- data->last_config = jiffies;
- } /* last_config */
-
- data->valid = 1;
-
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id lm85_id[] = {
+ { "adm1027", adm1027 },
+ { "adt7463", adt7463 },
+ { "adt7468", adt7468 },
+ { "lm85", lm85 },
+ { "lm85b", lm85 },
+ { "lm85c", lm85 },
+ { "emc6d100", emc6d100 },
+ { "emc6d101", emc6d100 },
+ { "emc6d102", emc6d102 },
+ { "emc6d103", emc6d103 },
+ { "emc6d103s", emc6d103s },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lm85_id);
- return data;
-}
+static struct i2c_driver lm85_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "lm85",
+ },
+ .probe = lm85_probe,
+ .id_table = lm85_id,
+ .detect = lm85_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(lm85_driver);
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index ba1d83d48056..a5e295826aea 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -617,6 +617,10 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
err = kstrtoul(buf, 10, &val);
if (err)
return err;
+
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index d2060e245ff5..cfaf70b9cba7 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -74,12 +74,9 @@ static inline int TEMP_FROM_REG(s16 reg)
return reg / 8 * 625 / 10;
}
-static inline s16 TEMP_TO_REG(int val)
+static inline s16 TEMP_TO_REG(long val)
{
- if (val <= -60000)
- return -60000 * 10 / 625 * 8;
- if (val >= 160000)
- return 160000 * 10 / 625 * 8;
+ val = clamp_val(val, -60000, 160000);
return val * 10 / 625 * 8;
}
@@ -206,10 +203,12 @@ static ssize_t set_temp_hyst(struct device *dev,
if (err)
return err;
+ val = clamp_val(val, -120000, 220000);
mutex_lock(&data->update_lock);
- data->temp[t_hyst] = TEMP_FROM_REG(data->temp[attr->index]) - val;
+ data->temp[t_hyst] =
+ TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val);
i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
- TEMP_TO_REG(data->temp[t_hyst]));
+ data->temp[t_hyst]);
mutex_unlock(&data->update_lock);
return count;
}
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 6c2df576f253..90bb04858117 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -207,7 +207,7 @@ struct block1_t {
* Client-specific data
*/
struct lm93_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
unsigned long last_updated; /* In jiffies */
@@ -919,8 +919,8 @@ static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
static struct lm93_data *lm93_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
const unsigned long interval = HZ + (HZ / 2);
mutex_lock(&data->update_lock);
@@ -1158,8 +1158,8 @@ static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int vccp = nr - 6;
long vid;
unsigned long val;
@@ -1239,8 +1239,8 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int vccp = nr - 6;
long vid;
unsigned long val;
@@ -1323,8 +1323,8 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1358,8 +1358,8 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1394,8 +1394,8 @@ static ssize_t store_temp_auto_base(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1430,8 +1430,8 @@ static ssize_t store_temp_auto_boost(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -1469,8 +1469,8 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1520,8 +1520,8 @@ static ssize_t store_temp_auto_offset(struct device *dev,
struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
int nr = s_attr->index;
int ofs = s_attr->nr;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1632,8 +1632,8 @@ static ssize_t store_temp_auto_pwm_min(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 reg, ctl4;
unsigned long val;
int err;
@@ -1680,8 +1680,8 @@ static ssize_t store_temp_auto_offset_hyst(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 reg;
unsigned long val;
int err;
@@ -1741,8 +1741,8 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1824,8 +1824,8 @@ static ssize_t store_fan_smart_tach(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -1880,8 +1880,8 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ctl2, ctl4;
unsigned long val;
int err;
@@ -1928,8 +1928,8 @@ static ssize_t store_pwm_enable(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ctl2;
unsigned long val;
int err;
@@ -2006,8 +2006,8 @@ static ssize_t store_pwm_freq(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ctl4;
unsigned long val;
int err;
@@ -2046,8 +2046,8 @@ static ssize_t store_pwm_auto_channels(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -2087,8 +2087,8 @@ static ssize_t store_pwm_auto_spinup_min(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ctl3, ctl4;
unsigned long val;
int err;
@@ -2130,8 +2130,8 @@ static ssize_t store_pwm_auto_spinup_time(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ctl3;
unsigned long val;
int err;
@@ -2168,8 +2168,8 @@ static ssize_t store_pwm_auto_prochot_ramp(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ramp;
unsigned long val;
int err;
@@ -2202,8 +2202,8 @@ static ssize_t store_pwm_auto_vrdhot_ramp(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 ramp;
unsigned long val;
int err;
@@ -2270,8 +2270,8 @@ static ssize_t store_prochot_max(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -2308,8 +2308,8 @@ static ssize_t store_prochot_override(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -2351,8 +2351,8 @@ static ssize_t store_prochot_interval(struct device *dev,
const char *buf, size_t count)
{
int nr = (to_sensor_dev_attr(attr))->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 tmp;
unsigned long val;
int err;
@@ -2390,8 +2390,8 @@ static ssize_t store_prochot_override_duty_cycle(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -2423,8 +2423,8 @@ static ssize_t store_prochot_short(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm93_data *data = i2c_get_clientdata(client);
+ struct lm93_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -2631,9 +2631,7 @@ static struct attribute *lm93_attrs[] = {
NULL
};
-static struct attribute_group lm93_attr_grp = {
- .attrs = lm93_attrs,
-};
+ATTRIBUTE_GROUPS(lm93);
static void lm93_init_client(struct i2c_client *client)
{
@@ -2726,61 +2724,42 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info)
static int lm93_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct lm93_data *data;
- int err, func;
+ struct device *hwmon_dev;
+ int func;
void (*update)(struct lm93_data *, struct i2c_client *);
/* choose update routine based on bus capabilities */
func = i2c_get_functionality(client->adapter);
if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
(!disable_block)) {
- dev_dbg(&client->dev, "using SMBus block data transactions\n");
+ dev_dbg(dev, "using SMBus block data transactions\n");
update = lm93_update_client_full;
} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
- dev_dbg(&client->dev,
- "disabled SMBus block data transactions\n");
+ dev_dbg(dev, "disabled SMBus block data transactions\n");
update = lm93_update_client_min;
} else {
- dev_dbg(&client->dev,
- "detect failed, smbus byte and/or word data not supported!\n");
+ dev_dbg(dev, "detect failed, smbus byte and/or word data not supported!\n");
return -ENODEV;
}
- data = devm_kzalloc(&client->dev, sizeof(struct lm93_data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct lm93_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
/* housekeeping */
+ data->client = client;
data->update = update;
mutex_init(&data->update_lock);
/* initialize the chip */
lm93_init_client(client);
- err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp);
- if (err)
- return err;
-
- /* Register hwmon driver class */
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (!IS_ERR(data->hwmon_dev))
- return 0;
-
- err = PTR_ERR(data->hwmon_dev);
- dev_err(&client->dev, "error registering hwmon device.\n");
- sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
- return err;
-}
-
-static int lm93_remove(struct i2c_client *client)
-{
- struct lm93_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ lm93_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id lm93_id[] = {
@@ -2796,7 +2775,6 @@ static struct i2c_driver lm93_driver = {
.name = "lm93",
},
.probe = lm93_probe,
- .remove = lm93_remove,
.id_table = lm93_id,
.detect = lm93_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index 3701b329b6ae..1b92e4f6e234 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -469,7 +469,7 @@ static struct attribute *ltc2945_attrs[] = {
};
ATTRIBUTE_GROUPS(ltc2945);
-static struct regmap_config ltc2945_regmap_config = {
+static const struct regmap_config ltc2945_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LTC2945_MIN_ADIN_THRES_L,
diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c
index 07c25653659f..88f747292816 100644
--- a/drivers/hwmon/ltc4222.c
+++ b/drivers/hwmon/ltc4222.c
@@ -186,7 +186,7 @@ static struct attribute *ltc4222_attrs[] = {
};
ATTRIBUTE_GROUPS(ltc4222);
-static struct regmap_config ltc4222_regmap_config = {
+static const struct regmap_config ltc4222_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LTC4222_ADC_CONTROL,
diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c
index 453a250d9df5..afb09574b12c 100644
--- a/drivers/hwmon/ltc4260.c
+++ b/drivers/hwmon/ltc4260.c
@@ -150,7 +150,7 @@ static struct attribute *ltc4260_attrs[] = {
};
ATTRIBUTE_GROUPS(ltc4260);
-static struct regmap_config ltc4260_regmap_config = {
+static const struct regmap_config ltc4260_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LTC4260_ADIN,
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index d4efc79d7b93..162401aaef71 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -642,10 +642,7 @@ static int max16065_probe(struct i2c_client *client,
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data, data->groups);
- if (unlikely(IS_ERR(hwmon_dev)))
- return PTR_ERR(hwmon_dev);
-
- return 0;
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id max16065_id[] = {
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index e3ed0a5b6d94..7ca889910262 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -30,7 +30,7 @@
#include <linux/mutex.h>
/* Addresses to scan */
-static unsigned short max1668_addr_list[] = {
+static const unsigned short max1668_addr_list[] = {
0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
/* max1668 registers */
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index 70650de2cbd1..dac6d85f2fd9 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -35,7 +35,7 @@
#include <linux/i2c/max6639.h>
/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
/* The MAX6639 registers, valid channel numbers: 0, 1 */
#define MAX6639_REG_TEMP(ch) (0x00 + (ch))
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index 7fd3eaf817f4..f03a71722849 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -495,15 +495,13 @@ static void max6697_get_config_of(struct device_node *node,
int len;
const __be32 *prop;
- prop = of_get_property(node, "smbus-timeout-disable", &len);
- if (prop)
- pdata->smbus_timeout_disable = true;
- prop = of_get_property(node, "extended-range-enable", &len);
- if (prop)
- pdata->extended_range_enable = true;
- prop = of_get_property(node, "beta-compensation-enable", &len);
- if (prop)
- pdata->beta_compensation = true;
+ pdata->smbus_timeout_disable =
+ of_property_read_bool(node, "smbus-timeout-disable");
+ pdata->extended_range_enable =
+ of_property_read_bool(node, "extended-range-enable");
+ pdata->beta_compensation =
+ of_property_read_bool(node, "beta-compensation-enable");
+
prop = of_get_property(node, "alert-mask", &len);
if (prop && len == sizeof(u32))
pdata->alert_mask = be32_to_cpu(prop[0]);
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 59d9a3fc96b7..504cbddbdd90 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -735,7 +735,6 @@ struct nct6775_data {
enum kinds kind;
const char *name;
- int num_attr_groups;
const struct attribute_group *groups[6];
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
@@ -3276,6 +3275,7 @@ static int nct6775_probe(struct platform_device *pdev)
u8 cr2a;
struct attribute_group *group;
struct device *hwmon_dev;
+ int num_attr_groups = 0;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
@@ -3907,29 +3907,29 @@ static int nct6775_probe(struct platform_device *pdev)
if (IS_ERR(group))
return PTR_ERR(group);
- data->groups[data->num_attr_groups++] = group;
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
fls(data->have_in));
if (IS_ERR(group))
return PTR_ERR(group);
- data->groups[data->num_attr_groups++] = group;
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
fls(data->has_fan));
if (IS_ERR(group))
return PTR_ERR(group);
- data->groups[data->num_attr_groups++] = group;
+ data->groups[num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
fls(data->have_temp));
if (IS_ERR(group))
return PTR_ERR(group);
- data->groups[data->num_attr_groups++] = group;
- data->groups[data->num_attr_groups++] = &nct6775_group_other;
+ data->groups[num_attr_groups++] = group;
+ data->groups[num_attr_groups++] = &nct6775_group_other;
hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
data, data->groups);
@@ -4221,7 +4221,7 @@ static void __exit sensors_nct6775_exit(void)
}
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
+MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D driver");
MODULE_LICENSE("GPL");
module_init(sensors_nct6775_init);
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index ae66f42c4d6d..bd410722cd4b 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -51,6 +51,7 @@ static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp21wb473", TYPE_NCPXXWB473 },
{ "ncp03wb473", TYPE_NCPXXWB473 },
{ "ncp15wl333", TYPE_NCPXXWL333 },
+ { "b57330v2103", TYPE_B57330V2103},
{ },
};
@@ -133,6 +134,47 @@ static const struct ntc_compensation ncpXXwl333[] = {
{ .temp_c = 125, .ohm = 707 },
};
+/*
+ * The following compensation table is from the specification of EPCOS NTC
+ * Thermistors Datasheet
+ */
+static const struct ntc_compensation b57330v2103[] = {
+ { .temp_c = -40, .ohm = 190030 },
+ { .temp_c = -35, .ohm = 145360 },
+ { .temp_c = -30, .ohm = 112060 },
+ { .temp_c = -25, .ohm = 87041 },
+ { .temp_c = -20, .ohm = 68104 },
+ { .temp_c = -15, .ohm = 53665 },
+ { .temp_c = -10, .ohm = 42576 },
+ { .temp_c = -5, .ohm = 34001 },
+ { .temp_c = 0, .ohm = 27326 },
+ { .temp_c = 5, .ohm = 22096 },
+ { .temp_c = 10, .ohm = 17973 },
+ { .temp_c = 15, .ohm = 14703 },
+ { .temp_c = 20, .ohm = 12090 },
+ { .temp_c = 25, .ohm = 10000 },
+ { .temp_c = 30, .ohm = 8311 },
+ { .temp_c = 35, .ohm = 6941 },
+ { .temp_c = 40, .ohm = 5825 },
+ { .temp_c = 45, .ohm = 4911 },
+ { .temp_c = 50, .ohm = 4158 },
+ { .temp_c = 55, .ohm = 3536 },
+ { .temp_c = 60, .ohm = 3019 },
+ { .temp_c = 65, .ohm = 2588 },
+ { .temp_c = 70, .ohm = 2227 },
+ { .temp_c = 75, .ohm = 1924 },
+ { .temp_c = 80, .ohm = 1668 },
+ { .temp_c = 85, .ohm = 1451 },
+ { .temp_c = 90, .ohm = 1266 },
+ { .temp_c = 95, .ohm = 1108 },
+ { .temp_c = 100, .ohm = 973 },
+ { .temp_c = 105, .ohm = 857 },
+ { .temp_c = 110, .ohm = 757 },
+ { .temp_c = 115, .ohm = 671 },
+ { .temp_c = 120, .ohm = 596 },
+ { .temp_c = 125, .ohm = 531 },
+};
+
struct ntc_data {
struct device *hwmon_dev;
struct ntc_thermistor_platform_data *pdata;
@@ -173,6 +215,8 @@ static const struct of_device_id ntc_match[] = {
.data = &ntc_thermistor_id[3] },
{ .compatible = "murata,ncp15wl333",
.data = &ntc_thermistor_id[4] },
+ { .compatible = "epcos,b57330v2103",
+ .data = &ntc_thermistor_id[5]},
/* Usage of vendor name "ntc" is deprecated */
{ .compatible = "ntc,ncp15wb473",
@@ -490,6 +534,10 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
data->comp = ncpXXwl333;
data->n_comp = ARRAY_SIZE(ncpXXwl333);
break;
+ case TYPE_B57330V2103:
+ data->comp = b57330v2103;
+ data->n_comp = ARRAY_SIZE(b57330v2103);
+ break;
default:
dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
pdev_id->driver_data, pdev_id->name);
@@ -546,7 +594,7 @@ static struct platform_driver ntc_thermistor_driver = {
module_platform_driver(ntc_thermistor_driver);
-MODULE_DESCRIPTION("NTC Thermistor Driver from Murata");
+MODULE_DESCRIPTION("NTC Thermistor Driver");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ntc-thermistor");
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 988181e4cfcd..145f674c1d87 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -615,6 +615,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 39cc63edfbb0..6e1e4935fc62 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -20,8 +20,7 @@ config SENSORS_PMBUS
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
- MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, TPS40400,
- and TPS40422.
+ MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400.
This driver can also be built as a module. If so, the module will
be called pmbus.
@@ -87,6 +86,16 @@ config SENSORS_MAX8688
This driver can also be built as a module. If so, the module will
be called max8688.
+config SENSORS_TPS40422
+ tristate "TI TPS40422"
+ default n
+ help
+ If you say yes here you get hardware monitoring support for TI
+ TPS40422.
+
+ This driver can also be built as a module. If so, the module will
+ be called tps40422.
+
config SENSORS_UCD9000
tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
default n
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 789376c85dbb..1454293e985c 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
+obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index 7e91700131a7..554d0249dcde 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -193,7 +193,6 @@ static const struct i2c_device_id pmbus_id[] = {
{"pdt012", 1},
{"pmbus", 0},
{"tps40400", 1},
- {"tps40422", 2},
{"udt020", 1},
{}
};
diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c
new file mode 100644
index 000000000000..32803825d47e
--- /dev/null
+++ b/drivers/hwmon/pmbus/tps40422.c
@@ -0,0 +1,64 @@
+/*
+ * Hardware monitoring driver for TI TPS40422
+ *
+ * Copyright (c) 2014 Nokia Solutions and Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info tps40422_info = {
+ .pages = 2,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+};
+
+static int tps40422_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return pmbus_do_probe(client, id, &tps40422_info);
+}
+
+static const struct i2c_device_id tps40422_id[] = {
+ {"tps40422", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tps40422_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver tps40422_driver = {
+ .driver = {
+ .name = "tps40422",
+ },
+ .probe = tps40422_probe,
+ .remove = pmbus_do_remove,
+ .id_table = tps40422_id,
+};
+
+module_i2c_driver(tps40422_driver);
+
+MODULE_AUTHOR("Zhu Laiwen <richard.zhu@nsn.com>");
+MODULE_DESCRIPTION("PMBus driver for TI TPS40422");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c
new file mode 100644
index 000000000000..3014e4ac741e
--- /dev/null
+++ b/drivers/hwmon/powr1220.c
@@ -0,0 +1,391 @@
+/*
+ * powr1220.c - Driver for the Lattice POWR1220 programmable power supply
+ * and monitor. Users can read all ADC inputs along with their labels
+ * using the sysfs nodes.
+ *
+ * Copyright (c) 2014 Echo360 http://www.echo360.com
+ * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#define ADC_STEP_MV 2
+#define ADC_MAX_LOW_MEASUREMENT_MV 2000
+
+enum powr1220_regs {
+ VMON_STATUS0,
+ VMON_STATUS1,
+ VMON_STATUS2,
+ OUTPUT_STATUS0,
+ OUTPUT_STATUS1,
+ OUTPUT_STATUS2,
+ INPUT_STATUS,
+ ADC_VALUE_LOW,
+ ADC_VALUE_HIGH,
+ ADC_MUX,
+ UES_BYTE0,
+ UES_BYTE1,
+ UES_BYTE2,
+ UES_BYTE3,
+ GP_OUTPUT1,
+ GP_OUTPUT2,
+ GP_OUTPUT3,
+ INPUT_VALUE,
+ RESET,
+ TRIM1_TRIM,
+ TRIM2_TRIM,
+ TRIM3_TRIM,
+ TRIM4_TRIM,
+ TRIM5_TRIM,
+ TRIM6_TRIM,
+ TRIM7_TRIM,
+ TRIM8_TRIM,
+ MAX_POWR1220_REGS
+};
+
+enum powr1220_adc_values {
+ VMON1,
+ VMON2,
+ VMON3,
+ VMON4,
+ VMON5,
+ VMON6,
+ VMON7,
+ VMON8,
+ VMON9,
+ VMON10,
+ VMON11,
+ VMON12,
+ VCCA,
+ VCCINP,
+ MAX_POWR1220_ADC_VALUES
+};
+
+struct powr1220_data {
+ struct i2c_client *client;
+ struct mutex update_lock;
+ bool adc_valid[MAX_POWR1220_ADC_VALUES];
+ /* the next value is in jiffies */
+ unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES];
+
+ /* values */
+ int adc_maxes[MAX_POWR1220_ADC_VALUES];
+ int adc_values[MAX_POWR1220_ADC_VALUES];
+};
+
+static const char * const input_names[] = {
+ [VMON1] = "vmon1",
+ [VMON2] = "vmon2",
+ [VMON3] = "vmon3",
+ [VMON4] = "vmon4",
+ [VMON5] = "vmon5",
+ [VMON6] = "vmon6",
+ [VMON7] = "vmon7",
+ [VMON8] = "vmon8",
+ [VMON9] = "vmon9",
+ [VMON10] = "vmon10",
+ [VMON11] = "vmon11",
+ [VMON12] = "vmon12",
+ [VCCA] = "vcca",
+ [VCCINP] = "vccinp",
+};
+
+/* Reads the specified ADC channel */
+static int powr1220_read_adc(struct device *dev, int ch_num)
+{
+ struct powr1220_data *data = dev_get_drvdata(dev);
+ int reading;
+ int result;
+ int adc_range = 0;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) ||
+ !data->adc_valid[ch_num]) {
+ /*
+ * figure out if we need to use the attenuator for
+ * high inputs or inputs that we don't yet have a measurement
+ * for. We dynamically set the attenuator depending on the
+ * max reading.
+ */
+ if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV ||
+ data->adc_maxes[ch_num] == 0)
+ adc_range = 1 << 4;
+
+ /* set the attenuator and mux */
+ result = i2c_smbus_write_byte_data(data->client, ADC_MUX,
+ adc_range | ch_num);
+ if (result)
+ goto exit;
+
+ /*
+ * wait at least Tconvert time (200 us) for the
+ * conversion to complete
+ */
+ udelay(200);
+
+ /* get the ADC reading */
+ result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW);
+ if (result < 0)
+ goto exit;
+
+ reading = result >> 4;
+
+ /* get the upper half of the reading */
+ result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH);
+ if (result < 0)
+ goto exit;
+
+ reading |= result << 4;
+
+ /* now convert the reading to a voltage */
+ reading *= ADC_STEP_MV;
+ data->adc_values[ch_num] = reading;
+ data->adc_valid[ch_num] = true;
+ data->adc_last_updated[ch_num] = jiffies;
+ result = reading;
+
+ if (reading > data->adc_maxes[ch_num])
+ data->adc_maxes[ch_num] = reading;
+ } else {
+ result = data->adc_values[ch_num];
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+
+ return result;
+}
+
+/* Shows the voltage associated with the specified ADC channel */
+static ssize_t powr1220_show_voltage(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+ int adc_val = powr1220_read_adc(dev, attr->index);
+
+ if (adc_val < 0)
+ return adc_val;
+
+ return sprintf(buf, "%d\n", adc_val);
+}
+
+/* Shows the maximum setting associated with the specified ADC channel */
+static ssize_t powr1220_show_max(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+ struct powr1220_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", data->adc_maxes[attr->index]);
+}
+
+/* Shows the label associated with the specified ADC channel */
+static ssize_t powr1220_show_label(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+ return sprintf(buf, "%s\n", input_names[attr->index]);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON1);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON2);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON3);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON4);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON5);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON6);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON7);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON8);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON9);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON10);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON11);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VMON12);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VCCA);
+static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL,
+ VCCINP);
+
+static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON1);
+static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON2);
+static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON3);
+static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON4);
+static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON5);
+static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON6);
+static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON7);
+static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON8);
+static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON9);
+static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON10);
+static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON11);
+static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL,
+ VMON12);
+static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL,
+ VCCA);
+static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL,
+ VCCINP);
+
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON1);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON2);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON3);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON4);
+static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON5);
+static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON6);
+static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON7);
+static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON8);
+static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON9);
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON10);
+static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON11);
+static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL,
+ VMON12);
+static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL,
+ VCCA);
+static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL,
+ VCCINP);
+
+static struct attribute *powr1220_attrs[] = {
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in11_input.dev_attr.attr,
+ &sensor_dev_attr_in12_input.dev_attr.attr,
+ &sensor_dev_attr_in13_input.dev_attr.attr,
+
+ &sensor_dev_attr_in0_highest.dev_attr.attr,
+ &sensor_dev_attr_in1_highest.dev_attr.attr,
+ &sensor_dev_attr_in2_highest.dev_attr.attr,
+ &sensor_dev_attr_in3_highest.dev_attr.attr,
+ &sensor_dev_attr_in4_highest.dev_attr.attr,
+ &sensor_dev_attr_in5_highest.dev_attr.attr,
+ &sensor_dev_attr_in6_highest.dev_attr.attr,
+ &sensor_dev_attr_in7_highest.dev_attr.attr,
+ &sensor_dev_attr_in8_highest.dev_attr.attr,
+ &sensor_dev_attr_in9_highest.dev_attr.attr,
+ &sensor_dev_attr_in10_highest.dev_attr.attr,
+ &sensor_dev_attr_in11_highest.dev_attr.attr,
+ &sensor_dev_attr_in12_highest.dev_attr.attr,
+ &sensor_dev_attr_in13_highest.dev_attr.attr,
+
+ &sensor_dev_attr_in0_label.dev_attr.attr,
+ &sensor_dev_attr_in1_label.dev_attr.attr,
+ &sensor_dev_attr_in2_label.dev_attr.attr,
+ &sensor_dev_attr_in3_label.dev_attr.attr,
+ &sensor_dev_attr_in4_label.dev_attr.attr,
+ &sensor_dev_attr_in5_label.dev_attr.attr,
+ &sensor_dev_attr_in6_label.dev_attr.attr,
+ &sensor_dev_attr_in7_label.dev_attr.attr,
+ &sensor_dev_attr_in8_label.dev_attr.attr,
+ &sensor_dev_attr_in9_label.dev_attr.attr,
+ &sensor_dev_attr_in10_label.dev_attr.attr,
+ &sensor_dev_attr_in11_label.dev_attr.attr,
+ &sensor_dev_attr_in12_label.dev_attr.attr,
+ &sensor_dev_attr_in13_label.dev_attr.attr,
+
+ NULL
+};
+
+ATTRIBUTE_GROUPS(powr1220);
+
+static int powr1220_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct powr1220_data *data;
+ struct device *hwmon_dev;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ mutex_init(&data->update_lock);
+ data->client = client;
+
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data, powr1220_groups);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id powr1220_ids[] = {
+ { "powr1220", 0, },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, powr1220_ids);
+
+static struct i2c_driver powr1220_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "powr1220",
+ },
+ .probe = powr1220_probe,
+ .id_table = powr1220_ids,
+};
+
+module_i2c_driver(powr1220_driver);
+
+MODULE_AUTHOR("Scott Kanowitz");
+MODULE_DESCRIPTION("POWR1220 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
new file mode 100644
index 000000000000..823c877a1ec0
--- /dev/null
+++ b/drivers/hwmon/pwm-fan.c
@@ -0,0 +1,193 @@
+/*
+ * pwm-fan.c - Hwmon driver for fans connected to PWM lines.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Author: Kamil Debski <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/sysfs.h>
+
+#define MAX_PWM 255
+
+struct pwm_fan_ctx {
+ struct mutex lock;
+ struct pwm_device *pwm;
+ unsigned char pwm_value;
+};
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+ unsigned long pwm, duty;
+ ssize_t ret;
+
+ if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM)
+ return -EINVAL;
+
+ mutex_lock(&ctx->lock);
+
+ if (ctx->pwm_value == pwm)
+ goto exit_set_pwm_no_change;
+
+ if (pwm == 0) {
+ pwm_disable(ctx->pwm);
+ goto exit_set_pwm;
+ }
+
+ duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
+ ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+ if (ret)
+ goto exit_set_pwm_err;
+
+ if (ctx->pwm_value == 0) {
+ ret = pwm_enable(ctx->pwm);
+ if (ret)
+ goto exit_set_pwm_err;
+ }
+
+exit_set_pwm:
+ ctx->pwm_value = pwm;
+exit_set_pwm_no_change:
+ ret = count;
+exit_set_pwm_err:
+ mutex_unlock(&ctx->lock);
+ return ret;
+}
+
+static ssize_t show_pwm(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", ctx->pwm_value);
+}
+
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
+
+static struct attribute *pwm_fan_attrs[] = {
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(pwm_fan);
+
+static int pwm_fan_probe(struct platform_device *pdev)
+{
+ struct device *hwmon;
+ struct pwm_fan_ctx *ctx;
+ int duty_cycle;
+ int ret;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ mutex_init(&ctx->lock);
+
+ ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL);
+ if (IS_ERR(ctx->pwm)) {
+ dev_err(&pdev->dev, "Could not get PWM\n");
+ return PTR_ERR(ctx->pwm);
+ }
+
+ platform_set_drvdata(pdev, ctx);
+
+ /* Set duty cycle to maximum allowed */
+ duty_cycle = ctx->pwm->period - 1;
+ ctx->pwm_value = MAX_PWM;
+
+ ret = pwm_config(ctx->pwm, duty_cycle, ctx->pwm->period);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to configure PWM\n");
+ return ret;
+ }
+
+ /* Enbale PWM output */
+ ret = pwm_enable(ctx->pwm);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable PWM\n");
+ return ret;
+ }
+
+ hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
+ ctx, pwm_fan_groups);
+ if (IS_ERR(hwmon)) {
+ dev_err(&pdev->dev, "Failed to register hwmon device\n");
+ pwm_disable(ctx->pwm);
+ return PTR_ERR(hwmon);
+ }
+ return 0;
+}
+
+static int pwm_fan_remove(struct platform_device *pdev)
+{
+ struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
+
+ if (ctx->pwm_value)
+ pwm_disable(ctx->pwm);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pwm_fan_suspend(struct device *dev)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ if (ctx->pwm_value)
+ pwm_disable(ctx->pwm);
+ return 0;
+}
+
+static int pwm_fan_resume(struct device *dev)
+{
+ struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+
+ if (ctx->pwm_value)
+ return pwm_enable(ctx->pwm);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume);
+
+static struct of_device_id of_pwm_fan_match[] = {
+ { .compatible = "pwm-fan", },
+ {},
+};
+
+static struct platform_driver pwm_fan_driver = {
+ .probe = pwm_fan_probe,
+ .remove = pwm_fan_remove,
+ .driver = {
+ .name = "pwm-fan",
+ .pm = &pwm_fan_pm,
+ .of_match_table = of_pwm_fan_match,
+ },
+};
+
+module_platform_driver(pwm_fan_driver);
+
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_ALIAS("platform:pwm-fan");
+MODULE_DESCRIPTION("PWM FAN driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 2e9f9570b6f8..84cdb1cf0fb4 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -45,7 +45,7 @@
* @humidity: cached humidity measurement value
*/
struct sht21 {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock;
char valid;
unsigned long last_update;
@@ -85,14 +85,15 @@ static inline int sht21_rh_ticks_to_per_cent_mille(int ticks)
/**
* sht21_update_measurements() - get updated measurements from device
- * @client: I2C client device
+ * @dev: device
*
* Returns 0 on success, else negative errno.
*/
-static int sht21_update_measurements(struct i2c_client *client)
+static int sht21_update_measurements(struct device *dev)
{
int ret = 0;
- struct sht21 *sht21 = i2c_get_clientdata(client);
+ struct sht21 *sht21 = dev_get_drvdata(dev);
+ struct i2c_client *client = sht21->client;
mutex_lock(&sht21->lock);
/*
@@ -133,9 +134,10 @@ static ssize_t sht21_show_temperature(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct sht21 *sht21 = i2c_get_clientdata(client);
- int ret = sht21_update_measurements(client);
+ struct sht21 *sht21 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = sht21_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", sht21->temperature);
@@ -154,9 +156,10 @@ static ssize_t sht21_show_humidity(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct sht21 *sht21 = i2c_get_clientdata(client);
- int ret = sht21_update_measurements(client);
+ struct sht21 *sht21 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = sht21_update_measurements(dev);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", sht21->humidity);
@@ -168,30 +171,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature,
static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity,
NULL, 0);
-static struct attribute *sht21_attributes[] = {
+static struct attribute *sht21_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_humidity1_input.dev_attr.attr,
NULL
};
-static const struct attribute_group sht21_attr_group = {
- .attrs = sht21_attributes,
-};
+ATTRIBUTE_GROUPS(sht21);
-/**
- * sht21_probe() - probe device
- * @client: I2C client device
- * @id: device ID
- *
- * Called by the I2C core when an entry in the ID table matches a
- * device's name.
- * Returns 0 on success.
- */
static int sht21_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct sht21 *sht21;
- int err;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -200,47 +193,17 @@ static int sht21_probe(struct i2c_client *client,
return -ENODEV;
}
- sht21 = devm_kzalloc(&client->dev, sizeof(*sht21), GFP_KERNEL);
+ sht21 = devm_kzalloc(dev, sizeof(*sht21), GFP_KERNEL);
if (!sht21)
return -ENOMEM;
- i2c_set_clientdata(client, sht21);
+ sht21->client = client;
mutex_init(&sht21->lock);
- err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
- if (err) {
- dev_dbg(&client->dev, "could not create sysfs files\n");
- return err;
- }
- sht21->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(sht21->hwmon_dev)) {
- dev_dbg(&client->dev, "unable to register hwmon device\n");
- err = PTR_ERR(sht21->hwmon_dev);
- goto fail_remove_sysfs;
- }
-
- dev_info(&client->dev, "initialized\n");
-
- return 0;
-
-fail_remove_sysfs:
- sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
- return err;
-}
-
-/**
- * sht21_remove() - remove device
- * @client: I2C client device
- */
-static int sht21_remove(struct i2c_client *client)
-{
- struct sht21 *sht21 = i2c_get_clientdata(client);
-
- hwmon_device_unregister(sht21->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ sht21, sht21_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
/* Device ID table */
@@ -253,7 +216,6 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
static struct i2c_driver sht21_driver = {
.driver.name = "sht21",
.probe = sht21_probe,
- .remove = sht21_remove,
.id_table = sht21_id,
};
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 3532026e25da..bf1d7893d51c 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val)
{
return val * 830 + 52120;
}
-static inline s8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(long val)
{
int nval = clamp_val(val, -54120, 157530) ;
return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830;
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index 4ef5802df6d8..627c9c3a8255 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -140,7 +140,7 @@ enum chips { smm465, smm665, smm665c, smm764, smm766 };
struct smm665_data {
enum chips type;
int conversion_time; /* ADC conversion time */
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
bool valid;
unsigned long last_updated; /* in jiffies */
@@ -239,8 +239,8 @@ static int smm665_read_adc(struct smm665_data *data, int adc)
static struct smm665_data *smm665_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct smm665_data *data = i2c_get_clientdata(client);
+ struct smm665_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct smm665_data *ret = data;
mutex_lock(&data->update_lock);
@@ -315,32 +315,28 @@ static int smm665_convert(u16 adcval, int index)
static int smm665_get_min(struct device *dev, int index)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct smm665_data *data = i2c_get_clientdata(client);
+ struct smm665_data *data = dev_get_drvdata(dev);
return data->alarm_min_limit[index];
}
static int smm665_get_max(struct device *dev, int index)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct smm665_data *data = i2c_get_clientdata(client);
+ struct smm665_data *data = dev_get_drvdata(dev);
return data->alarm_max_limit[index];
}
static int smm665_get_lcrit(struct device *dev, int index)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct smm665_data *data = i2c_get_clientdata(client);
+ struct smm665_data *data = dev_get_drvdata(dev);
return data->critical_min_limit[index];
}
static int smm665_get_crit(struct device *dev, int index)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct smm665_data *data = i2c_get_clientdata(client);
+ struct smm665_data *data = dev_get_drvdata(dev);
return data->critical_max_limit[index];
}
@@ -486,7 +482,7 @@ SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP);
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
-static struct attribute *smm665_attributes[] = {
+static struct attribute *smm665_attrs[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
@@ -567,15 +563,14 @@ static struct attribute *smm665_attributes[] = {
NULL,
};
-static const struct attribute_group smm665_group = {
- .attrs = smm665_attributes,
-};
+ATTRIBUTE_GROUPS(smm665);
static int smm665_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct smm665_data *data;
+ struct device *hwmon_dev;
int i, ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
@@ -592,6 +587,7 @@ static int smm665_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
+ data->client = client;
data->type = id->driver_data;
data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK)
| SMM665_CMDREG_BASE);
@@ -662,21 +658,16 @@ static int smm665_probe(struct i2c_client *client,
data->alarm_max_limit[i] = smm665_convert(val, i);
}
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &smm665_group);
- if (ret)
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ smm665_groups);
+ if (IS_ERR(hwmon_dev)) {
+ ret = PTR_ERR(hwmon_dev);
goto out_unregister;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_remove_group;
}
return 0;
-out_remove_group:
- sysfs_remove_group(&client->dev.kobj, &smm665_group);
out_unregister:
i2c_unregister_device(data->cmdreg);
return ret;
@@ -687,9 +678,6 @@ static int smm665_remove(struct i2c_client *client)
struct smm665_data *data = i2c_get_clientdata(client);
i2c_unregister_device(data->cmdreg);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &smm665_group);
-
return 0;
}
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 23a22c4eee51..d7485659acc5 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -142,11 +142,6 @@ struct smsc47m1_sio_data {
u8 activate; /* Remember initial device state */
};
-
-static int __exit smsc47m1_remove(struct platform_device *pdev);
-static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
- int init);
-
static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg)
{
return inb_p(data->addr + reg);
@@ -158,13 +153,54 @@ static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg,
outb_p(value, data->addr + reg);
}
-static struct platform_driver smsc47m1_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = DRVNAME,
- },
- .remove = __exit_p(smsc47m1_remove),
-};
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+ int init)
+{
+ struct smsc47m1_data *data = dev_get_drvdata(dev);
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
+ int i, fan_nr;
+ fan_nr = data->type == smsc47m2 ? 3 : 2;
+
+ for (i = 0; i < fan_nr; i++) {
+ data->fan[i] = smsc47m1_read_value(data,
+ SMSC47M1_REG_FAN[i]);
+ data->fan_preload[i] = smsc47m1_read_value(data,
+ SMSC47M1_REG_FAN_PRELOAD[i]);
+ data->pwm[i] = smsc47m1_read_value(data,
+ SMSC47M1_REG_PWM[i]);
+ }
+
+ i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = i >> 6;
+
+ data->alarms = smsc47m1_read_value(data,
+ SMSC47M1_REG_ALARM) >> 6;
+ /* Clear alarms if needed */
+ if (data->alarms)
+ smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
+
+ if (fan_nr >= 3) {
+ data->fan_div[2] = (smsc47m1_read_value(data,
+ SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
+ data->alarms |= (smsc47m1_read_value(data,
+ SMSC47M2_REG_ALARM6) & 0x40) >> 4;
+ /* Clear alarm if needed */
+ if (data->alarms & 0x04)
+ smsc47m1_write_value(data,
+ SMSC47M2_REG_ALARM6,
+ 0x40);
+ }
+
+ data->last_updated = jiffies;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return data;
+}
static ssize_t get_fan(struct device *dev, struct device_attribute
*devattr, char *buf)
@@ -811,54 +847,13 @@ static int __exit smsc47m1_remove(struct platform_device *pdev)
return 0;
}
-static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
- int init)
-{
- struct smsc47m1_data *data = dev_get_drvdata(dev);
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
- int i, fan_nr;
- fan_nr = data->type == smsc47m2 ? 3 : 2;
-
- for (i = 0; i < fan_nr; i++) {
- data->fan[i] = smsc47m1_read_value(data,
- SMSC47M1_REG_FAN[i]);
- data->fan_preload[i] = smsc47m1_read_value(data,
- SMSC47M1_REG_FAN_PRELOAD[i]);
- data->pwm[i] = smsc47m1_read_value(data,
- SMSC47M1_REG_PWM[i]);
- }
-
- i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
- data->fan_div[0] = (i >> 4) & 0x03;
- data->fan_div[1] = i >> 6;
-
- data->alarms = smsc47m1_read_value(data,
- SMSC47M1_REG_ALARM) >> 6;
- /* Clear alarms if needed */
- if (data->alarms)
- smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
-
- if (fan_nr >= 3) {
- data->fan_div[2] = (smsc47m1_read_value(data,
- SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
- data->alarms |= (smsc47m1_read_value(data,
- SMSC47M2_REG_ALARM6) & 0x40) >> 4;
- /* Clear alarm if needed */
- if (data->alarms & 0x04)
- smsc47m1_write_value(data,
- SMSC47M2_REG_ALARM6,
- 0x40);
- }
-
- data->last_updated = jiffies;
- }
-
- mutex_unlock(&data->update_lock);
- return data;
-}
+static struct platform_driver smsc47m1_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .remove = __exit_p(smsc47m1_remove),
+};
static int __init smsc47m1_device_add(unsigned short address,
const struct smsc47m1_sio_data *sio_data)
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index 34b9a601ad07..6ac7cda72d4c 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -95,7 +95,8 @@ static inline int TEMP_FROM_REG(s8 val)
}
struct smsc47m192_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -112,30 +113,69 @@ struct smsc47m192_data {
u8 vrm;
};
-static int smsc47m192_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int smsc47m192_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int smsc47m192_remove(struct i2c_client *client);
-static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
+{
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int i, config;
-static const struct i2c_device_id smsc47m192_id[] = {
- { "smsc47m192", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
+ mutex_lock(&data->update_lock);
-static struct i2c_driver smsc47m192_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "smsc47m192",
- },
- .probe = smsc47m192_probe,
- .remove = smsc47m192_remove,
- .id_table = smsc47m192_id,
- .detect = smsc47m192_detect,
- .address_list = normal_i2c,
-};
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+ dev_dbg(&client->dev, "Starting smsc47m192 update\n");
+
+ for (i = 0; i <= 7; i++) {
+ data->in[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_IN(i));
+ data->in_min[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_IN_MIN(i));
+ data->in_max[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_IN_MAX(i));
+ }
+ for (i = 0; i < 3; i++) {
+ data->temp[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_TEMP[i]);
+ data->temp_max[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_TEMP_MAX[i]);
+ data->temp_min[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_TEMP_MIN[i]);
+ }
+ for (i = 1; i < 3; i++)
+ data->temp_offset[i] = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_TEMP_OFFSET(i));
+ /*
+ * first offset is temp_offset[0] if SFR bit 4 is set,
+ * temp_offset[1] otherwise
+ */
+ if (sfr & 0x10) {
+ data->temp_offset[0] = data->temp_offset[1];
+ data->temp_offset[1] = 0;
+ } else
+ data->temp_offset[0] = 0;
+
+ data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
+ & 0x0f;
+ config = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_CONFIG);
+ if (config & 0x20)
+ data->vid |= (i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_VID4) & 0x01) << 4;
+ data->alarms = i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_ALARM1) |
+ (i2c_smbus_read_byte_data(client,
+ SMSC47M192_REG_ALARM2) << 8);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
/* Voltages */
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
@@ -170,8 +210,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -192,8 +232,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -259,8 +299,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -281,8 +321,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -312,8 +352,8 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
+ struct smsc47m192_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
long val;
int err;
@@ -552,124 +592,50 @@ static int smsc47m192_detect(struct i2c_client *client,
static int smsc47m192_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct smsc47m192_data *data;
int config;
- int err;
- data = devm_kzalloc(&client->dev, sizeof(struct smsc47m192_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct smsc47m192_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
data->vrm = vid_which_vrm();
mutex_init(&data->update_lock);
/* Initialize the SMSC47M192 chip */
smsc47m192_init_client(client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group);
- if (err)
- return err;
-
+ /* sysfs hooks */
+ data->groups[0] = &smsc47m192_group;
/* Pin 110 is either in4 (+12V) or VID4 */
config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
- if (!(config & 0x20)) {
- err = sysfs_create_group(&client->dev.kobj,
- &smsc47m192_group_in4);
- if (err)
- goto exit_remove_files;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
- sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
- return err;
-}
-
-static int smsc47m192_remove(struct i2c_client *client)
-{
- struct smsc47m192_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
- sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
+ if (!(config & 0x20))
+ data->groups[1] = &smsc47m192_group_in4;
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct smsc47m192_data *data = i2c_get_clientdata(client);
- int i, config;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
-
- dev_dbg(&client->dev, "Starting smsc47m192 update\n");
-
- for (i = 0; i <= 7; i++) {
- data->in[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_IN(i));
- data->in_min[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_IN_MIN(i));
- data->in_max[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_IN_MAX(i));
- }
- for (i = 0; i < 3; i++) {
- data->temp[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_TEMP[i]);
- data->temp_max[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_TEMP_MAX[i]);
- data->temp_min[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_TEMP_MIN[i]);
- }
- for (i = 1; i < 3; i++)
- data->temp_offset[i] = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_TEMP_OFFSET(i));
- /*
- * first offset is temp_offset[0] if SFR bit 4 is set,
- * temp_offset[1] otherwise
- */
- if (sfr & 0x10) {
- data->temp_offset[0] = data->temp_offset[1];
- data->temp_offset[1] = 0;
- } else
- data->temp_offset[0] = 0;
-
- data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
- & 0x0f;
- config = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_CONFIG);
- if (config & 0x20)
- data->vid |= (i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_VID4) & 0x01) << 4;
- data->alarms = i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_ALARM1) |
- (i2c_smbus_read_byte_data(client,
- SMSC47M192_REG_ALARM2) << 8);
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id smsc47m192_id[] = {
+ { "smsc47m192", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
- return data;
-}
+static struct i2c_driver smsc47m192_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "smsc47m192",
+ },
+ .probe = smsc47m192_probe,
+ .id_table = smsc47m192_id,
+ .detect = smsc47m192_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(smsc47m192_driver);
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index db288db7d3e9..6a0ee903127e 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -68,7 +68,8 @@ static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 };
/* Each client has this additional data */
struct thmc50_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
enum chips type;
@@ -85,32 +86,47 @@ struct thmc50_data {
u8 alarms;
};
-static int thmc50_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int thmc50_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int thmc50_remove(struct i2c_client *client);
-static void thmc50_init_client(struct i2c_client *client);
-static struct thmc50_data *thmc50_update_device(struct device *dev);
+static struct thmc50_data *thmc50_update_device(struct device *dev)
+{
+ struct thmc50_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
-static const struct i2c_device_id thmc50_id[] = {
- { "adm1022", adm1022 },
- { "thmc50", thmc50 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, thmc50_id);
+ mutex_lock(&data->update_lock);
-static struct i2c_driver thmc50_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "thmc50",
- },
- .probe = thmc50_probe,
- .remove = thmc50_remove,
- .id_table = thmc50_id,
- .detect = thmc50_detect,
- .address_list = normal_i2c,
-};
+ if (time_after(jiffies, data->last_updated + timeout)
+ || !data->valid) {
+
+ int temps = data->has_temp3 ? 3 : 2;
+ int i;
+ int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+
+ prog &= THMC50_REG_CONF_PROGRAMMED;
+
+ for (i = 0; i < temps; i++) {
+ data->temp_input[i] = i2c_smbus_read_byte_data(client,
+ THMC50_REG_TEMP[i]);
+ data->temp_max[i] = i2c_smbus_read_byte_data(client,
+ THMC50_REG_TEMP_MAX[i]);
+ data->temp_min[i] = i2c_smbus_read_byte_data(client,
+ THMC50_REG_TEMP_MIN[i]);
+ data->temp_critical[i] =
+ i2c_smbus_read_byte_data(client,
+ prog ? THMC50_REG_TEMP_CRITICAL[i]
+ : THMC50_REG_TEMP_DEFAULT[i]);
+ }
+ data->analog_out =
+ i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
+ data->alarms =
+ i2c_smbus_read_byte_data(client, THMC50_REG_INTR);
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
static ssize_t show_analog_out(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -123,8 +139,8 @@ static ssize_t set_analog_out(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct thmc50_data *data = i2c_get_clientdata(client);
+ struct thmc50_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
int config;
unsigned long tmp;
int err;
@@ -177,8 +193,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct thmc50_data *data = i2c_get_clientdata(client);
+ struct thmc50_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -206,8 +222,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct thmc50_data *data = i2c_get_clientdata(client);
+ struct thmc50_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -355,67 +371,9 @@ static int thmc50_detect(struct i2c_client *client,
return 0;
}
-static int thmc50_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct thmc50_data *data;
- int err;
-
- data = devm_kzalloc(&client->dev, sizeof(struct thmc50_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- data->type = id->driver_data;
- mutex_init(&data->update_lock);
-
- thmc50_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &thmc50_group);
- if (err)
- return err;
-
- /* Register ADM1022 sysfs hooks */
- if (data->has_temp3) {
- err = sysfs_create_group(&client->dev.kobj, &temp3_group);
- if (err)
- goto exit_remove_sysfs_thmc50;
- }
-
- /* Register a new directory entry with module sensors */
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_sysfs;
- }
-
- return 0;
-
-exit_remove_sysfs:
- if (data->has_temp3)
- sysfs_remove_group(&client->dev.kobj, &temp3_group);
-exit_remove_sysfs_thmc50:
- sysfs_remove_group(&client->dev.kobj, &thmc50_group);
- return err;
-}
-
-static int thmc50_remove(struct i2c_client *client)
+static void thmc50_init_client(struct thmc50_data *data)
{
- struct thmc50_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &thmc50_group);
- if (data->has_temp3)
- sysfs_remove_group(&client->dev.kobj, &temp3_group);
-
- return 0;
-}
-
-static void thmc50_init_client(struct i2c_client *client)
-{
- struct thmc50_data *data = i2c_get_clientdata(client);
+ struct i2c_client *client = data->client;
int config;
data->analog_out = i2c_smbus_read_byte_data(client,
@@ -433,48 +391,54 @@ static void thmc50_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
}
-static struct thmc50_data *thmc50_update_device(struct device *dev)
+static int thmc50_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct thmc50_data *data = i2c_get_clientdata(client);
- int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
+ struct device *dev = &client->dev;
+ struct thmc50_data *data;
+ struct device *hwmon_dev;
+ int idx = 0;
- mutex_lock(&data->update_lock);
+ data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- if (time_after(jiffies, data->last_updated + timeout)
- || !data->valid) {
+ data->client = client;
+ data->type = id->driver_data;
+ mutex_init(&data->update_lock);
- int temps = data->has_temp3 ? 3 : 2;
- int i;
- int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+ thmc50_init_client(data);
- prog &= THMC50_REG_CONF_PROGRAMMED;
+ /* sysfs hooks */
+ data->groups[idx++] = &thmc50_group;
- for (i = 0; i < temps; i++) {
- data->temp_input[i] = i2c_smbus_read_byte_data(client,
- THMC50_REG_TEMP[i]);
- data->temp_max[i] = i2c_smbus_read_byte_data(client,
- THMC50_REG_TEMP_MAX[i]);
- data->temp_min[i] = i2c_smbus_read_byte_data(client,
- THMC50_REG_TEMP_MIN[i]);
- data->temp_critical[i] =
- i2c_smbus_read_byte_data(client,
- prog ? THMC50_REG_TEMP_CRITICAL[i]
- : THMC50_REG_TEMP_DEFAULT[i]);
- }
- data->analog_out =
- i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
- data->alarms =
- i2c_smbus_read_byte_data(client, THMC50_REG_INTR);
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- mutex_unlock(&data->update_lock);
+ /* Register additional ADM1022 sysfs hooks */
+ if (data->has_temp3)
+ data->groups[idx++] = &temp3_group;
- return data;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
+static const struct i2c_device_id thmc50_id[] = {
+ { "adm1022", adm1022 },
+ { "thmc50", thmc50 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, thmc50_id);
+
+static struct i2c_driver thmc50_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "thmc50",
+ },
+ .probe = thmc50_probe,
+ .id_table = thmc50_id,
+ .detect = thmc50_detect,
+ .address_list = normal_i2c,
+};
+
module_i2c_driver(thmc50_driver);
MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c
new file mode 100644
index 000000000000..e42964f07f67
--- /dev/null
+++ b/drivers/hwmon/tmp103.c
@@ -0,0 +1,199 @@
+/*
+ * Texas Instruments TMP103 SMBus temperature sensor driver
+ * Copyright (C) 2014 Heiko Schocher <hs@denx.de>
+ *
+ * Based on:
+ * Texas Instruments TMP102 SMBus temperature sensor driver
+ *
+ * Copyright (C) 2010 Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+
+#define TMP103_TEMP_REG 0x00
+#define TMP103_CONF_REG 0x01
+#define TMP103_TLOW_REG 0x02
+#define TMP103_THIGH_REG 0x03
+
+#define TMP103_CONF_M0 0x01
+#define TMP103_CONF_M1 0x02
+#define TMP103_CONF_LC 0x04
+#define TMP103_CONF_FL 0x08
+#define TMP103_CONF_FH 0x10
+#define TMP103_CONF_CR0 0x20
+#define TMP103_CONF_CR1 0x40
+#define TMP103_CONF_ID 0x80
+#define TMP103_CONF_SD (TMP103_CONF_M1)
+#define TMP103_CONF_SD_MASK (TMP103_CONF_M0 | TMP103_CONF_M1)
+
+#define TMP103_CONFIG (TMP103_CONF_CR1 | TMP103_CONF_M1)
+#define TMP103_CONFIG_MASK (TMP103_CONF_CR0 | TMP103_CONF_CR1 | \
+ TMP103_CONF_M0 | TMP103_CONF_M1)
+
+static inline int tmp103_reg_to_mc(s8 val)
+{
+ return val * 1000;
+}
+
+static inline u8 tmp103_mc_to_reg(int val)
+{
+ return DIV_ROUND_CLOSEST(val, 1000);
+}
+
+static ssize_t tmp103_show_temp(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+ struct regmap *regmap = dev_get_drvdata(dev);
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(regmap, sda->index, &regval);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval));
+}
+
+static ssize_t tmp103_set_temp(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+ struct regmap *regmap = dev_get_drvdata(dev);
+ long val;
+ int ret;
+
+ if (kstrtol(buf, 10, &val) < 0)
+ return -EINVAL;
+
+ val = clamp_val(val, -55000, 127000);
+ ret = regmap_write(regmap, sda->index, tmp103_mc_to_reg(val));
+ return ret ? ret : count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL ,
+ TMP103_TEMP_REG);
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp,
+ tmp103_set_temp, TMP103_TLOW_REG);
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp,
+ tmp103_set_temp, TMP103_THIGH_REG);
+
+static struct attribute *tmp103_attrs[] = {
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_min.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(tmp103);
+
+static bool tmp103_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == TMP103_TEMP_REG;
+}
+
+static const struct regmap_config tmp103_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TMP103_THIGH_REG,
+ .volatile_reg = tmp103_regmap_is_volatile,
+};
+
+static int tmp103_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(client, &tmp103_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "failed to allocate register map\n");
+ return PTR_ERR(regmap);
+ }
+
+ ret = regmap_update_bits(regmap, TMP103_CONF_REG, TMP103_CONFIG_MASK,
+ TMP103_CONFIG);
+ if (ret < 0) {
+ dev_err(&client->dev, "error writing config register\n");
+ return ret;
+ }
+
+ i2c_set_clientdata(client, regmap);
+ hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+ regmap, tmp103_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+#ifdef CONFIG_PM
+static int tmp103_suspend(struct device *dev)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+
+ return regmap_update_bits(regmap, TMP103_CONF_REG,
+ TMP103_CONF_SD_MASK, 0);
+}
+
+static int tmp103_resume(struct device *dev)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+
+ return regmap_update_bits(regmap, TMP103_CONF_REG,
+ TMP103_CONF_SD_MASK, TMP103_CONF_SD);
+}
+
+static const struct dev_pm_ops tmp103_dev_pm_ops = {
+ .suspend = tmp103_suspend,
+ .resume = tmp103_resume,
+};
+
+#define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops)
+#else
+#define TMP103_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id tmp103_id[] = {
+ { "tmp103", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tmp103_id);
+
+static struct i2c_driver tmp103_driver = {
+ .driver = {
+ .name = "tmp103",
+ .pm = TMP103_DEV_PM_OPS,
+ },
+ .probe = tmp103_probe,
+ .id_table = tmp103_id,
+};
+
+module_i2c_driver(tmp103_driver);
+
+MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
+MODULE_DESCRIPTION("Texas Instruments TMP103 temperature sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 7bab7a9bedc6..85d48d80822a 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -13,15 +13,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Driver for the Texas Instruments TMP421 SMBus temperature sensor IC.
- * Supported models: TMP421, TMP422, TMP423
+ * Supported models: TMP421, TMP422, TMP423, TMP441, TMP442
*/
#include <linux/module.h>
@@ -39,9 +35,10 @@
static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f,
I2C_CLIENT_END };
-enum chips { tmp421, tmp422, tmp423 };
+enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 };
/* The TMP421 registers */
+#define TMP421_STATUS_REG 0x08
#define TMP421_CONFIG_REG_1 0x09
#define TMP421_CONVERSION_RATE_REG 0x0B
#define TMP421_MANUFACTURER_ID_REG 0xFE
@@ -59,11 +56,15 @@ static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
#define TMP421_DEVICE_ID 0x21
#define TMP422_DEVICE_ID 0x22
#define TMP423_DEVICE_ID 0x23
+#define TMP441_DEVICE_ID 0x41
+#define TMP442_DEVICE_ID 0x42
static const struct i2c_device_id tmp421_id[] = {
{ "tmp421", 2 },
{ "tmp422", 3 },
{ "tmp423", 4 },
+ { "tmp441", 2 },
+ { "tmp442", 3 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tmp421_id);
@@ -234,7 +235,9 @@ static int tmp421_detect(struct i2c_client *client,
{
enum chips kind;
struct i2c_adapter *adapter = client->adapter;
- const char *names[] = { "TMP421", "TMP422", "TMP423" };
+ const char * const names[] = { "TMP421", "TMP422", "TMP423",
+ "TMP441", "TMP442" };
+ int addr = client->addr;
u8 reg;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -244,17 +247,37 @@ static int tmp421_detect(struct i2c_client *client,
if (reg != TMP421_MANUFACTURER_ID)
return -ENODEV;
+ reg = i2c_smbus_read_byte_data(client, TMP421_CONVERSION_RATE_REG);
+ if (reg & 0xf8)
+ return -ENODEV;
+
+ reg = i2c_smbus_read_byte_data(client, TMP421_STATUS_REG);
+ if (reg & 0x7f)
+ return -ENODEV;
+
reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG);
switch (reg) {
case TMP421_DEVICE_ID:
kind = tmp421;
break;
case TMP422_DEVICE_ID:
+ if (addr == 0x2a)
+ return -ENODEV;
kind = tmp422;
break;
case TMP423_DEVICE_ID:
+ if (addr != 0x4c && addr != 0x4d)
+ return -ENODEV;
kind = tmp423;
break;
+ case TMP441_DEVICE_ID:
+ kind = tmp441;
+ break;
+ case TMP442_DEVICE_ID:
+ if (addr != 0x4c && addr != 0x4d)
+ return -ENODEV;
+ kind = tmp442;
+ break;
default:
return -ENODEV;
}
@@ -305,5 +328,5 @@ static struct i2c_driver tmp421_driver = {
module_i2c_driver(tmp421_driver);
MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
-MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver");
+MODULE_DESCRIPTION("Texas Instruments TMP421/422/423/441/442 temperature sensor driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
index 6c6d440bb2dd..9a0e2b8e8b94 100644
--- a/drivers/hwmon/twl4030-madc-hwmon.c
+++ b/drivers/hwmon/twl4030-madc-hwmon.c
@@ -74,7 +74,7 @@ static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11);
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);
-static struct attribute *twl4030_madc_attributes[] = {
+static struct attribute *twl4030_madc_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -91,46 +91,20 @@ static struct attribute *twl4030_madc_attributes[] = {
&sensor_dev_attr_in15_input.dev_attr.attr,
NULL
};
-
-static const struct attribute_group twl4030_madc_group = {
- .attrs = twl4030_madc_attributes,
-};
+ATTRIBUTE_GROUPS(twl4030_madc);
static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
{
- int ret;
struct device *hwmon;
- ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
- if (ret)
- goto err_sysfs;
- hwmon = hwmon_device_register(&pdev->dev);
- if (IS_ERR(hwmon)) {
- dev_err(&pdev->dev, "hwmon_device_register failed.\n");
- ret = PTR_ERR(hwmon);
- goto err_reg;
- }
-
- return 0;
-
-err_reg:
- sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
-err_sysfs:
-
- return ret;
-}
-
-static int twl4030_madc_hwmon_remove(struct platform_device *pdev)
-{
- hwmon_device_unregister(&pdev->dev);
- sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
-
- return 0;
+ hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
+ "twl4030_madc", NULL,
+ twl4030_madc_groups);
+ return PTR_ERR_OR_ZERO(hwmon);
}
static struct platform_driver twl4030_madc_hwmon_driver = {
.probe = twl4030_madc_hwmon_probe,
- .remove = twl4030_madc_hwmon_remove,
.driver = {
.name = "twl4030_madc_hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 344b22ec2553..3ea57c3504e2 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -879,6 +879,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index c1726be3654c..2f55973a8c4c 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -820,6 +820,9 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf
err = kstrtoul(buf, 10, &val);
if (err)
return err;
+
+ if (val > 255)
+ return -EINVAL;
data->vrm = val;
return count;
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index bdcf2dce5ec4..001df856913f 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -249,19 +249,16 @@ static u8 fan_to_reg(long rpm, int div)
* the bottom 7 bits will always be zero
*/
#define TEMP23_FROM_REG(val) ((val) / 128 * 500)
-#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \
- (val) >= 127500 ? 0x7F80 : \
- (val) < 0 ? ((val) - 250) / 500 * 128 : \
- ((val) + 250) / 500 * 128)
+#define TEMP23_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \
+ 127500), 500) * 128)
/* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */
-#define TARGET_TEMP_TO_REG(val) ((val) < 0 ? 0 : \
- (val) >= 127000 ? 127 : \
- ((val) + 500) / 1000)
+#define TARGET_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \
+ 1000)
/* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
-#define TOL_TEMP_TO_REG(val) ((val) >= 15000 ? 15 : \
- ((val) + 500) / 1000)
+#define TOL_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 15000), \
+ 1000)
#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff)
#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff)
@@ -1184,6 +1181,9 @@ static ssize_t store_vrm_reg(struct device *dev,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 9d63d71214ca..816aa6caf5d5 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -353,6 +353,9 @@ store_vrm(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ if (val > 255)
+ return -EINVAL;
+
data->vrm = val;
return count;
}
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 32487c19cbfc..330299613d38 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -124,7 +124,7 @@ DIV_TO_REG(long val)
}
struct w83l786ng_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -148,32 +148,6 @@ struct w83l786ng_data {
u8 tolerance[2];
};
-static int w83l786ng_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int w83l786ng_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int w83l786ng_remove(struct i2c_client *client);
-static void w83l786ng_init_client(struct i2c_client *client);
-static struct w83l786ng_data *w83l786ng_update_device(struct device *dev);
-
-static const struct i2c_device_id w83l786ng_id[] = {
- { "w83l786ng", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, w83l786ng_id);
-
-static struct i2c_driver w83l786ng_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "w83l786ng",
- },
- .probe = w83l786ng_probe,
- .remove = w83l786ng_remove,
- .id_table = w83l786ng_id,
- .detect = w83l786ng_detect,
- .address_list = normal_i2c,
-};
-
static u8
w83l786ng_read_value(struct i2c_client *client, u8 reg)
{
@@ -186,6 +160,77 @@ w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
+static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
+{
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int i, j;
+ u8 reg_tmp, pwmcfg;
+
+ mutex_lock(&data->update_lock);
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ dev_dbg(&client->dev, "Updating w83l786ng data.\n");
+
+ /* Update the voltages measured value and limits */
+ for (i = 0; i < 3; i++) {
+ data->in[i] = w83l786ng_read_value(client,
+ W83L786NG_REG_IN(i));
+ data->in_min[i] = w83l786ng_read_value(client,
+ W83L786NG_REG_IN_MIN(i));
+ data->in_max[i] = w83l786ng_read_value(client,
+ W83L786NG_REG_IN_MAX(i));
+ }
+
+ /* Update the fan counts and limits */
+ for (i = 0; i < 2; i++) {
+ data->fan[i] = w83l786ng_read_value(client,
+ W83L786NG_REG_FAN(i));
+ data->fan_min[i] = w83l786ng_read_value(client,
+ W83L786NG_REG_FAN_MIN(i));
+ }
+
+ /* Update the fan divisor */
+ reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
+ data->fan_div[0] = reg_tmp & 0x07;
+ data->fan_div[1] = (reg_tmp >> 4) & 0x07;
+
+ pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
+ for (i = 0; i < 2; i++) {
+ data->pwm_mode[i] =
+ ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
+ ? 0 : 1;
+ data->pwm_enable[i] =
+ ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+ data->pwm[i] =
+ (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+ & 0x0f) * 0x11;
+ }
+
+
+ /* Update the temperature sensors */
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 3; j++) {
+ data->temp[i][j] = w83l786ng_read_value(client,
+ W83L786NG_REG_TEMP[i][j]);
+ }
+ }
+
+ /* Update Smart Fan I/II tolerance */
+ reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE);
+ data->tolerance[0] = reg_tmp & 0x0f;
+ data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
/* following are the sysfs callback functions */
#define show_in_reg(reg) \
static ssize_t \
@@ -207,8 +252,8 @@ store_in_##reg(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
int nr = to_sensor_dev_attr(attr)->index; \
- struct i2c_client *client = to_i2c_client(dev); \
- struct w83l786ng_data *data = i2c_get_clientdata(client); \
+ struct w83l786ng_data *data = dev_get_drvdata(dev); \
+ struct i2c_client *client = data->client; \
unsigned long val; \
int err = kstrtoul(buf, 10, &val); \
if (err) \
@@ -260,8 +305,8 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -298,8 +343,8 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long min;
u8 tmp_fan_div;
@@ -389,8 +434,8 @@ store_temp(struct device *dev, struct device_attribute *attr,
to_sensor_dev_attr_2(attr);
int nr = sensor_attr->nr;
int index = sensor_attr->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
int err;
@@ -444,8 +489,8 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 reg;
unsigned long val;
int err;
@@ -472,8 +517,8 @@ store_pwm(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err;
@@ -496,8 +541,8 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 reg;
unsigned long val;
int err;
@@ -552,8 +597,8 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
+ struct w83l786ng_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 tol_tmp, tol_mask;
unsigned long val;
int err;
@@ -608,7 +653,7 @@ static struct sensor_device_attribute sda_tolerance[] = {
#define TOLERANCE_UNIT_ATTRS(X) \
&sda_tolerance[X].dev_attr.attr
-static struct attribute *w83l786ng_attributes[] = {
+static struct attribute *w83l786ng_attrs[] = {
IN_UNIT_ATTRS(0),
IN_UNIT_ATTRS(1),
IN_UNIT_ATTRS(2),
@@ -623,9 +668,7 @@ static struct attribute *w83l786ng_attributes[] = {
NULL
};
-static const struct attribute_group w83l786ng_group = {
- .attrs = w83l786ng_attributes,
-};
+ATTRIBUTE_GROUPS(w83l786ng);
static int
w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info)
@@ -662,20 +705,33 @@ w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
+static void w83l786ng_init_client(struct i2c_client *client)
+{
+ u8 tmp;
+
+ if (reset)
+ w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80);
+
+ /* Start monitoring */
+ tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG);
+ if (!(tmp & 0x01))
+ w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01);
+}
+
static int
w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct w83l786ng_data *data;
- int i, err = 0;
+ struct device *hwmon_dev;
+ int i;
u8 reg_tmp;
- data = devm_kzalloc(&client->dev, sizeof(struct w83l786ng_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct w83l786ng_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Initialize the chip */
@@ -692,121 +748,28 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->fan_div[0] = reg_tmp & 0x07;
data->fan_div[1] = (reg_tmp >> 4) & 0x07;
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group);
- if (err)
- goto exit_remove;
-
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
- /* Unregister sysfs hooks */
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
- return err;
-}
-
-static int
-w83l786ng_remove(struct i2c_client *client)
-{
- struct w83l786ng_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ w83l786ng_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
-static void
-w83l786ng_init_client(struct i2c_client *client)
-{
- u8 tmp;
-
- if (reset)
- w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80);
-
- /* Start monitoring */
- tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG);
- if (!(tmp & 0x01))
- w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01);
-}
-
-static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83l786ng_data *data = i2c_get_clientdata(client);
- int i, j;
- u8 reg_tmp, pwmcfg;
-
- mutex_lock(&data->update_lock);
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- dev_dbg(&client->dev, "Updating w83l786ng data.\n");
-
- /* Update the voltages measured value and limits */
- for (i = 0; i < 3; i++) {
- data->in[i] = w83l786ng_read_value(client,
- W83L786NG_REG_IN(i));
- data->in_min[i] = w83l786ng_read_value(client,
- W83L786NG_REG_IN_MIN(i));
- data->in_max[i] = w83l786ng_read_value(client,
- W83L786NG_REG_IN_MAX(i));
- }
-
- /* Update the fan counts and limits */
- for (i = 0; i < 2; i++) {
- data->fan[i] = w83l786ng_read_value(client,
- W83L786NG_REG_FAN(i));
- data->fan_min[i] = w83l786ng_read_value(client,
- W83L786NG_REG_FAN_MIN(i));
- }
-
- /* Update the fan divisor */
- reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV);
- data->fan_div[0] = reg_tmp & 0x07;
- data->fan_div[1] = (reg_tmp >> 4) & 0x07;
-
- pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
- for (i = 0; i < 2; i++) {
- data->pwm_mode[i] =
- ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
- ? 0 : 1;
- data->pwm_enable[i] =
- ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
- data->pwm[i] =
- (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
- & 0x0f) * 0x11;
- }
-
-
- /* Update the temperature sensors */
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 3; j++) {
- data->temp[i][j] = w83l786ng_read_value(client,
- W83L786NG_REG_TEMP[i][j]);
- }
- }
-
- /* Update Smart Fan I/II tolerance */
- reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE);
- data->tolerance[0] = reg_tmp & 0x0f;
- data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
-
- data->last_updated = jiffies;
- data->valid = 1;
-
- }
-
- mutex_unlock(&data->update_lock);
+static const struct i2c_device_id w83l786ng_id[] = {
+ { "w83l786ng", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, w83l786ng_id);
- return data;
-}
+static struct i2c_driver w83l786ng_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "w83l786ng",
+ },
+ .probe = w83l786ng_probe,
+ .id_table = w83l786ng_id,
+ .detect = w83l786ng_detect,
+ .address_list = normal_i2c,
+};
module_i2c_driver(w83l786ng_driver);
diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
index df6ceaf8d58a..3e6a3195cd11 100644
--- a/drivers/hwmon/wm831x-hwmon.c
+++ b/drivers/hwmon/wm831x-hwmon.c
@@ -29,17 +29,6 @@
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/auxadc.h>
-struct wm831x_hwmon {
- struct wm831x *wm831x;
- struct device *classdev;
-};
-
-static ssize_t show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "wm831x\n");
-}
-
static const char * const input_names[] = {
[WM831X_AUX_SYSVDD] = "SYSVDD",
[WM831X_AUX_USB] = "USB",
@@ -50,15 +39,14 @@ static const char * const input_names[] = {
[WM831X_AUX_BATT_TEMP] = "Battery",
};
-
static ssize_t show_voltage(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct wm831x_hwmon *hwmon = dev_get_drvdata(dev);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
int channel = to_sensor_dev_attr(attr)->index;
int ret;
- ret = wm831x_auxadc_read_uv(hwmon->wm831x, channel);
+ ret = wm831x_auxadc_read_uv(wm831x, channel);
if (ret < 0)
return ret;
@@ -68,11 +56,11 @@ static ssize_t show_voltage(struct device *dev,
static ssize_t show_chip_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct wm831x_hwmon *hwmon = dev_get_drvdata(dev);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
int channel = to_sensor_dev_attr(attr)->index;
int ret;
- ret = wm831x_auxadc_read(hwmon->wm831x, channel);
+ ret = wm831x_auxadc_read(wm831x, channel);
if (ret < 0)
return ret;
@@ -100,8 +88,6 @@ static ssize_t show_label(struct device *dev,
static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \
NULL, name)
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
WM831X_VOLTAGE(0, WM831X_AUX_AUX1);
WM831X_VOLTAGE(1, WM831X_AUX_AUX2);
WM831X_VOLTAGE(2, WM831X_AUX_AUX3);
@@ -126,9 +112,7 @@ static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_voltage, NULL,
static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL,
WM831X_AUX_BATT_TEMP);
-static struct attribute *wm831x_attributes[] = {
- &dev_attr_name.attr,
-
+static struct attribute *wm831x_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
@@ -153,55 +137,21 @@ static struct attribute *wm831x_attributes[] = {
NULL
};
-static const struct attribute_group wm831x_attr_group = {
- .attrs = wm831x_attributes,
-};
+ATTRIBUTE_GROUPS(wm831x);
static int wm831x_hwmon_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
- struct wm831x_hwmon *hwmon;
- int ret;
-
- hwmon = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_hwmon),
- GFP_KERNEL);
- if (!hwmon)
- return -ENOMEM;
-
- hwmon->wm831x = wm831x;
-
- ret = sysfs_create_group(&pdev->dev.kobj, &wm831x_attr_group);
- if (ret)
- return ret;
-
- hwmon->classdev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(hwmon->classdev)) {
- ret = PTR_ERR(hwmon->classdev);
- goto err_sysfs;
- }
-
- platform_set_drvdata(pdev, hwmon);
-
- return 0;
-
-err_sysfs:
- sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group);
- return ret;
-}
-
-static int wm831x_hwmon_remove(struct platform_device *pdev)
-{
- struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev);
-
- hwmon_device_unregister(hwmon->classdev);
- sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group);
+ struct device *hwmon_dev;
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm831x",
+ wm831x,
+ wm831x_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static struct platform_driver wm831x_hwmon_driver = {
.probe = wm831x_hwmon_probe,
- .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 64bf75c9442b..90e3d918e597 100644
--- a/drivers/hwmon/wm8350-hwmon.c
+++ b/drivers/hwmon/wm8350-hwmon.c
@@ -28,19 +28,12 @@
#include <linux/mfd/wm8350/core.h>
#include <linux/mfd/wm8350/comparator.h>
-static ssize_t show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "wm8350\n");
-}
-
static const char * const input_names[] = {
[WM8350_AUXADC_USB] = "USB",
[WM8350_AUXADC_LINE] = "Line",
[WM8350_AUXADC_BATT] = "Battery",
};
-
static ssize_t show_voltage(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -68,15 +61,11 @@ static ssize_t show_label(struct device *dev,
static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \
NULL, name)
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
WM8350_NAMED_VOLTAGE(0, WM8350_AUXADC_USB);
WM8350_NAMED_VOLTAGE(1, WM8350_AUXADC_BATT);
WM8350_NAMED_VOLTAGE(2, WM8350_AUXADC_LINE);
-static struct attribute *wm8350_attributes[] = {
- &dev_attr_name.attr,
-
+static struct attribute *wm8350_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_label.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -87,46 +76,21 @@ static struct attribute *wm8350_attributes[] = {
NULL,
};
-static const struct attribute_group wm8350_attr_group = {
- .attrs = wm8350_attributes,
-};
+ATTRIBUTE_GROUPS(wm8350);
static int wm8350_hwmon_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
- int ret;
-
- ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group);
- if (ret)
- goto err;
-
- wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(wm8350->hwmon.classdev)) {
- ret = PTR_ERR(wm8350->hwmon.classdev);
- goto err_group;
- }
-
- return 0;
-
-err_group:
- sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
-err:
- return ret;
-}
-
-static int wm8350_hwmon_remove(struct platform_device *pdev)
-{
- struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-
- hwmon_device_unregister(wm8350->hwmon.classdev);
- sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
+ struct device *hwmon_dev;
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm8350",
+ wm8350,
+ wm8350_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static struct platform_driver wm8350_hwmon_driver = {
.probe = wm8350_hwmon_probe,
- .remove = wm8350_hwmon_remove,
.driver = {
.name = "wm8350-hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
index 70637d23b1f9..3612cb5b30b2 100644
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -10,7 +10,7 @@ menu "Hardware Spinlock drivers"
config HWSPINLOCK_OMAP
tristate "OMAP Hardware Spinlock device"
- depends on ARCH_OMAP4 || SOC_OMAP5
+ depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX
select HWSPINLOCK
help
Say y here to support the OMAP Hardware Spinlock device (firstly
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 292869cc9034..c1e2cd4d85fe 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -98,10 +98,29 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
if (!io_base)
return -ENOMEM;
+ /*
+ * make sure the module is enabled and clocked before reading
+ * the module SYSSTATUS register
+ */
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&pdev->dev);
+ goto iounmap_base;
+ }
+
/* Determine number of locks */
i = readl(io_base + SYSSTATUS_OFFSET);
i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET;
+ /*
+ * runtime PM will make sure the clock of this module is
+ * enabled again iff at least one lock is requested
+ */
+ ret = pm_runtime_put(&pdev->dev);
+ if (ret < 0)
+ goto iounmap_base;
+
/* one of the four lsb's must be set, and nothing else */
if (hweight_long(i & 0xf) != 1 || i > 8) {
ret = -EINVAL;
@@ -121,12 +140,6 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
- /*
- * runtime PM will make sure the clock of this module is
- * enabled iff at least one lock is requested
- */
- pm_runtime_enable(&pdev->dev);
-
ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops,
pdata->base_id, num_locks);
if (ret)
@@ -135,9 +148,9 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
return 0;
reg_fail:
- pm_runtime_disable(&pdev->dev);
kfree(bank);
iounmap_base:
+ pm_runtime_disable(&pdev->dev);
iounmap(io_base);
return ret;
}
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 7b7ea320a258..3e3b680dc007 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -2,7 +2,9 @@
# I2C subsystem configuration
#
-menuconfig I2C
+menu "I2C support"
+
+config I2C
tristate "I2C support"
select RT_MUTEXES
---help---
@@ -21,6 +23,18 @@ menuconfig I2C
This I2C support can also be built as a module. If so, the module
will be called i2c-core.
+config I2C_ACPI
+ bool "I2C ACPI support"
+ select I2C
+ depends on ACPI
+ default y
+ help
+ Say Y here if you want to enable ACPI I2C support. This includes support
+ for automatic enumeration of I2C slave devices and support for ACPI I2C
+ Operation Regions. Operation Regions allow firmware (BIOS) code to
+ access I2C slave devices, such as smart batteries through an I2C host
+ controller driver.
+
if I2C
config I2C_BOARDINFO
@@ -124,3 +138,5 @@ config I2C_DEBUG_BUS
on.
endif # I2C
+
+endmenu
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 1722f50f2473..a1f590cbb435 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -2,8 +2,11 @@
# Makefile for the i2c core.
#
+i2ccore-y := i2c-core.o
+i2ccore-$(CONFIG_I2C_ACPI) += i2c-acpi.o
+
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
-obj-$(CONFIG_I2C) += i2c-core.o
+obj-$(CONFIG_I2C) += i2ccore.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 9f7d5859cf65..2ac87fa3058d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -109,6 +109,7 @@ config I2C_I801
Avoton (SOC)
Wellsburg (PCH)
Coleto Creek (PCH)
+ Wildcat Point (PCH)
Wildcat Point-LP (PCH)
BayTrail (SOC)
@@ -465,9 +466,9 @@ config I2C_EG20T
config I2C_EXYNOS5
tristate "Exynos5 high-speed I2C driver"
depends on ARCH_EXYNOS5 && OF
+ default y
help
- Say Y here to include support for high-speed I2C controller in the
- Exynos5 based Samsung SoCs.
+ High-speed I2C controller on Exynos5 based Samsung SoCs.
config I2C_GPIO
tristate "GPIO-based bitbanging I2C"
@@ -700,16 +701,6 @@ config I2C_S3C2410
Say Y here to include support for I2C controller in the
Samsung SoCs.
-config I2C_S6000
- tristate "S6000 I2C support"
- depends on XTENSA_VARIANT_S6000
- help
- This driver supports the on chip I2C device on the
- S6000 xtensa processor family.
-
- To compile this driver as a module, choose M here. The module
- will be called i2c-s6000.
-
config I2C_SH7760
tristate "Renesas SH7760 I2C Controller"
depends on CPU_SUBTYPE_SH7760
@@ -1018,37 +1009,6 @@ config I2C_CROS_EC_TUNNEL
connected there. This will work whatever the interface used to
talk to the EC (SPI, I2C or LPC).
-config SCx200_I2C
- tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
- depends on SCx200_GPIO
- select I2C_ALGOBIT
- help
- Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-
- If you don't know what to do here, say N.
-
- This support is also available as a module. If so, the module
- will be called scx200_i2c.
-
- This driver is deprecated and will be dropped soon. Use i2c-gpio
- (or scx200_acb) instead.
-
-config SCx200_I2C_SCL
- int "GPIO pin used for SCL"
- depends on SCx200_I2C
- default "12"
- help
- Enter the GPIO pin number used for the SCL signal. This value can
- also be specified with a module parameter.
-
-config SCx200_I2C_SDA
- int "GPIO pin used for SDA"
- depends on SCx200_I2C
- default "13"
- help
- Enter the GPIO pin number used for the SSA signal. This value can
- also be specified with a module parameter.
-
config SCx200_ACB
tristate "Geode ACCESS.bus support"
depends on X86_32 && PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index dd9a7f8e873f..49bf07e5ef4d 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_I2C_QUP) += i2c-qup.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
-obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
@@ -101,6 +100,5 @@ obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
-obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index e95f9ba96790..79a68999a696 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -210,7 +210,7 @@ static void at91_twi_write_data_dma_callback(void *data)
struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
- dev->buf_len, DMA_MEM_TO_DEV);
+ dev->buf_len, DMA_TO_DEVICE);
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
}
@@ -289,7 +289,7 @@ static void at91_twi_read_data_dma_callback(void *data)
struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
- dev->buf_len, DMA_DEV_TO_MEM);
+ dev->buf_len, DMA_FROM_DEVICE);
/* The last two bytes have to be read without using dma */
dev->buf += dev->buf_len - 2;
@@ -768,7 +768,7 @@ static int at91_twi_probe(struct platform_device *pdev)
snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
i2c_set_adapdata(&dev->adapter, dev);
dev->adapter.owner = THIS_MODULE;
- dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ dev->adapter.class = I2C_CLASS_DEPRECATED;
dev->adapter.algo = &at91_twi_algorithm;
dev->adapter.dev.parent = dev->dev;
dev->adapter.nr = pdev->id;
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index 214ff9700efe..4b8ecd0b3661 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -277,7 +277,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
adap = &i2c_dev->adapter;
i2c_set_adapdata(adap, i2c_dev);
adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
adap->algo = &bcm2835_i2c_algo;
adap->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 3e271e7558d3..067c1615e968 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -648,7 +648,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
- p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
+ p_adap->class = I2C_CLASS_DEPRECATED;
p_adap->dev.parent = &pdev->dev;
p_adap->timeout = 5 * HZ;
p_adap->retries = 3;
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
index 8e7a71487bb1..05e033c98115 100644
--- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
u8 *request = NULL;
u8 *response = NULL;
int result;
+ struct cros_ec_command msg;
request_len = ec_i2c_count_message(i2c_msgs, num);
if (request_len < 0) {
@@ -218,10 +219,16 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
}
ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
- result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
- request, request_len,
- response, response_len);
- if (result)
+
+ msg.version = 0;
+ msg.command = EC_CMD_I2C_PASSTHRU;
+ msg.outdata = request;
+ msg.outsize = request_len;
+ msg.indata = response;
+ msg.insize = response_len;
+
+ result = bus->ec->cmd_xfer(bus->ec, &msg);
+ if (result < 0)
goto exit;
result = ec_i2c_parse_response(response, i2c_msgs, &num);
@@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_device *pdev)
u32 remote_bus;
int err;
- if (!ec->command_sendrecv) {
+ if (!ec->cmd_xfer) {
dev_err(dev, "Missing sendrecv\n");
return -EINVAL;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 389bc68c55ad..4d9614719128 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -712,7 +712,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
adap->algo = &i2c_davinci_algo;
adap->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 3356f7ab9f79..d31d313ab4f7 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -188,6 +188,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.scl_sda_cfg = &hsw_config,
},
};
+
static struct i2c_algorithm i2c_dw_algo = {
.master_xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
@@ -350,6 +351,14 @@ static const struct pci_device_id i2_designware_pci_ids[] = {
/* Haswell */
{ PCI_VDEVICE(INTEL, 0x9c61), haswell },
{ PCI_VDEVICE(INTEL, 0x9c62), haswell },
+ /* Braswell / Cherrytrail */
+ { PCI_VDEVICE(INTEL, 0x22C1), baytrail,},
+ { PCI_VDEVICE(INTEL, 0x22C2), baytrail },
+ { PCI_VDEVICE(INTEL, 0x22C3), baytrail },
+ { PCI_VDEVICE(INTEL, 0x22C4), baytrail },
+ { PCI_VDEVICE(INTEL, 0x22C5), baytrail },
+ { PCI_VDEVICE(INTEL, 0x22C6), baytrail },
+ { PCI_VDEVICE(INTEL, 0x22C7), baytrail },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 402ec3970fed..bc8773333155 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -106,6 +106,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT3432", 0 },
{ "INT3433", 0 },
{ "80860F41", 0 },
+ { "808622C1", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -202,7 +203,7 @@ static int dw_i2c_probe(struct platform_device *pdev)
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
sizeof(adap->name));
adap->algo = &i2c_dw_algo;
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
index f7eccd682de9..10b8323b08d4 100644
--- a/drivers/i2c/busses/i2c-efm32.c
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -370,7 +370,13 @@ static int efm32_i2c_probe(struct platform_device *pdev)
return ret;
}
- ret = of_property_read_u32(np, "efm32,location", &location);
+
+ ret = of_property_read_u32(np, "energymicro,location", &location);
+
+ if (ret)
+ /* fall back to wrongly namespaced property */
+ ret = of_property_read_u32(np, "efm32,location", &location);
+
if (!ret) {
dev_dbg(&pdev->dev, "using location %u\n", location);
} else {
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 63d229202854..28073f1d6d47 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -405,7 +405,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
int_status = readl(i2c->regs + HSI2C_INT_STATUS);
writel(int_status, i2c->regs + HSI2C_INT_STATUS);
- fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
/* handle interrupt related to the transfer status */
if (int_status & HSI2C_INT_I2C) {
@@ -526,7 +525,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
if (i2c->msg->flags & I2C_M_RD) {
i2c_ctl |= HSI2C_RXCHON;
- i2c_auto_conf = HSI2C_READ_WRITE;
+ i2c_auto_conf |= HSI2C_READ_WRITE;
trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
(i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
@@ -549,7 +548,6 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
writel(i2c_ctl, i2c->regs + HSI2C_CTL);
-
/*
* Enable interrupts before starting the transfer so that we don't
* miss any INT_I2C interrupts.
@@ -789,8 +787,16 @@ static int exynos5_i2c_resume_noirq(struct device *dev)
}
#endif
-static SIMPLE_DEV_PM_OPS(exynos5_i2c_dev_pm_ops, exynos5_i2c_suspend_noirq,
- exynos5_i2c_resume_noirq);
+static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+ .suspend_noirq = exynos5_i2c_suspend_noirq,
+ .resume_noirq = exynos5_i2c_resume_noirq,
+ .freeze_noirq = exynos5_i2c_suspend_noirq,
+ .thaw_noirq = exynos5_i2c_resume_noirq,
+ .poweroff_noirq = exynos5_i2c_suspend_noirq,
+ .restore_noirq = exynos5_i2c_resume_noirq,
+#endif
+};
static struct platform_driver exynos5_i2c_driver = {
.probe = exynos5_i2c_probe,
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 71a45b210a24..933f1e453e41 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -238,12 +238,10 @@ static int i2c_gpio_probe(struct platform_device *pdev)
static int i2c_gpio_remove(struct platform_device *pdev)
{
struct i2c_gpio_private_data *priv;
- struct i2c_gpio_platform_data *pdata;
struct i2c_adapter *adap;
priv = platform_get_drvdata(pdev);
adap = &priv->adap;
- pdata = &priv->pdata;
i2c_del_adapter(adap);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 6777cd6f8776..2994690b26e9 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -22,57 +22,58 @@
*/
/*
- Supports the following Intel I/O Controller Hubs (ICH):
-
- I/O Block I2C
- region SMBus Block proc. block
- Chip name PCI ID size PEC buffer call read
- ----------------------------------------------------------------------
- 82801AA (ICH) 0x2413 16 no no no no
- 82801AB (ICH0) 0x2423 16 no no no no
- 82801BA (ICH2) 0x2443 16 no no no no
- 82801CA (ICH3) 0x2483 32 soft no no no
- 82801DB (ICH4) 0x24c3 32 hard yes no no
- 82801E (ICH5) 0x24d3 32 hard yes yes yes
- 6300ESB 0x25a4 32 hard yes yes yes
- 82801F (ICH6) 0x266a 32 hard yes yes yes
- 6310ESB/6320ESB 0x269b 32 hard yes yes yes
- 82801G (ICH7) 0x27da 32 hard yes yes yes
- 82801H (ICH8) 0x283e 32 hard yes yes yes
- 82801I (ICH9) 0x2930 32 hard yes yes yes
- EP80579 (Tolapai) 0x5032 32 hard yes yes yes
- ICH10 0x3a30 32 hard yes yes yes
- ICH10 0x3a60 32 hard yes yes yes
- 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
- 6 Series (PCH) 0x1c22 32 hard yes yes yes
- Patsburg (PCH) 0x1d22 32 hard yes yes yes
- Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes
- Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes
- Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes
- DH89xxCC (PCH) 0x2330 32 hard yes yes yes
- Panther Point (PCH) 0x1e22 32 hard yes yes yes
- Lynx Point (PCH) 0x8c22 32 hard yes yes yes
- Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes
- Avoton (SOC) 0x1f3c 32 hard yes yes yes
- Wellsburg (PCH) 0x8d22 32 hard yes yes yes
- Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes
- Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes
- Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes
- Coleto Creek (PCH) 0x23b0 32 hard yes yes yes
- Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes
- BayTrail (SOC) 0x0f12 32 hard yes yes yes
-
- Features supported by this driver:
- Software PEC no
- Hardware PEC yes
- Block buffer yes
- Block process call transaction no
- I2C block read transaction yes (doesn't use the block buffer)
- Slave mode no
- Interrupt processing yes
-
- See the file Documentation/i2c/busses/i2c-i801 for details.
-*/
+ * Supports the following Intel I/O Controller Hubs (ICH):
+ *
+ * I/O Block I2C
+ * region SMBus Block proc. block
+ * Chip name PCI ID size PEC buffer call read
+ * ---------------------------------------------------------------------------
+ * 82801AA (ICH) 0x2413 16 no no no no
+ * 82801AB (ICH0) 0x2423 16 no no no no
+ * 82801BA (ICH2) 0x2443 16 no no no no
+ * 82801CA (ICH3) 0x2483 32 soft no no no
+ * 82801DB (ICH4) 0x24c3 32 hard yes no no
+ * 82801E (ICH5) 0x24d3 32 hard yes yes yes
+ * 6300ESB 0x25a4 32 hard yes yes yes
+ * 82801F (ICH6) 0x266a 32 hard yes yes yes
+ * 6310ESB/6320ESB 0x269b 32 hard yes yes yes
+ * 82801G (ICH7) 0x27da 32 hard yes yes yes
+ * 82801H (ICH8) 0x283e 32 hard yes yes yes
+ * 82801I (ICH9) 0x2930 32 hard yes yes yes
+ * EP80579 (Tolapai) 0x5032 32 hard yes yes yes
+ * ICH10 0x3a30 32 hard yes yes yes
+ * ICH10 0x3a60 32 hard yes yes yes
+ * 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
+ * 6 Series (PCH) 0x1c22 32 hard yes yes yes
+ * Patsburg (PCH) 0x1d22 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes
+ * DH89xxCC (PCH) 0x2330 32 hard yes yes yes
+ * Panther Point (PCH) 0x1e22 32 hard yes yes yes
+ * Lynx Point (PCH) 0x8c22 32 hard yes yes yes
+ * Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes
+ * Avoton (SOC) 0x1f3c 32 hard yes yes yes
+ * Wellsburg (PCH) 0x8d22 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes
+ * Coleto Creek (PCH) 0x23b0 32 hard yes yes yes
+ * Wildcat Point (PCH) 0x8ca2 32 hard yes yes yes
+ * Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes
+ * BayTrail (SOC) 0x0f12 32 hard yes yes yes
+ *
+ * Features supported by this driver:
+ * Software PEC no
+ * Hardware PEC yes
+ * Block buffer yes
+ * Block process call transaction no
+ * I2C block read transaction yes (doesn't use the block buffer)
+ * Slave mode no
+ * Interrupt processing yes
+ *
+ * See the file Documentation/i2c/busses/i2c-i801 for details.
+ */
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -162,24 +163,25 @@
STATUS_ERROR_FLAGS)
/* Older devices have their ID defined in <linux/pci_ids.h> */
-#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12
-#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
+#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
-#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
-#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0 0x8d7d
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
+#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0 0x8d7d
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2
struct i801_mux_config {
@@ -823,6 +825,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) },
{ 0, }
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index aa8bc146718b..613069bc561a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -735,10 +735,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
clk_disable_unprepare(i2c_imx->clk);
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
- dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",
- res->start, res->end);
- dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",
- resource_size(res), res->start);
+ dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
i2c_imx->adapter.name);
dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 6a32aa095f83..0edf630b099a 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -341,8 +341,7 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
iounmap(reg);
}
}
- if (node)
- of_node_put(node);
+ of_node_put(node);
return val;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 9f4b775e2e39..6dc5ded86f62 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -863,7 +863,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
- drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
+ drv_data->adapter.class = I2C_CLASS_DEPRECATED;
drv_data->adapter.nr = pd->id;
drv_data->adapter.dev.of_node = pd->dev.of_node;
platform_set_drvdata(pd, drv_data);
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 0e55d85fd4ed..9ad038d223c4 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -1032,10 +1032,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
adap = &dev->adap;
adap->dev.of_node = np;
adap->dev.parent = &adev->dev;
- adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
- adap->algo = &nmk_i2c_algo;
- adap->timeout = msecs_to_jiffies(dev->timeout);
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_DEPRECATED;
+ adap->algo = &nmk_i2c_algo;
+ adap->timeout = msecs_to_jiffies(dev->timeout);
snprintf(adap->name, sizeof(adap->name),
"Nomadik I2C at %pR", &adev->res);
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 0e10cc6182f0..2a4fe0b7cfb7 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -239,15 +239,15 @@ static u32 ocores_func(struct i2c_adapter *adap)
}
static const struct i2c_algorithm ocores_algorithm = {
- .master_xfer = ocores_xfer,
- .functionality = ocores_func,
+ .master_xfer = ocores_xfer,
+ .functionality = ocores_func,
};
static struct i2c_adapter ocores_adapter = {
- .owner = THIS_MODULE,
- .name = "i2c-ocores",
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
- .algo = &ocores_algorithm,
+ .owner = THIS_MODULE,
+ .name = "i2c-ocores",
+ .class = I2C_CLASS_DEPRECATED,
+ .algo = &ocores_algorithm,
};
static const struct of_device_id ocores_i2c_match[] = {
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b182793a4051..0dffb0e62c3b 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1236,7 +1236,7 @@ omap_i2c_probe(struct platform_device *pdev)
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
adap->algo = &omap_i2c_algo;
adap->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 2a5efb5b487c..3a4d64e1dfb1 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -633,13 +633,17 @@ static int qup_i2c_probe(struct platform_device *pdev)
* associated with each byte written/received
*/
size = QUP_OUTPUT_BLOCK_SIZE(io_mode);
- if (size >= ARRAY_SIZE(blk_sizes))
- return -EIO;
+ if (size >= ARRAY_SIZE(blk_sizes)) {
+ ret = -EIO;
+ goto fail;
+ }
qup->out_blk_sz = blk_sizes[size] / 2;
size = QUP_INPUT_BLOCK_SIZE(io_mode);
- if (size >= ARRAY_SIZE(blk_sizes))
- return -EIO;
+ if (size >= ARRAY_SIZE(blk_sizes)) {
+ ret = -EIO;
+ goto fail;
+ }
qup->in_blk_sz = blk_sizes[size] / 2;
size = QUP_OUTPUT_FIFO_SIZE(io_mode);
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 899405923678..f3c7139dfa25 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -541,13 +541,13 @@ static int rcar_i2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait);
- adap = &priv->adap;
- adap->nr = pdev->id;
- adap->algo = &rcar_i2c_algo;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
- adap->retries = 3;
- adap->dev.parent = dev;
- adap->dev.of_node = dev->of_node;
+ adap = &priv->adap;
+ adap->nr = pdev->id;
+ adap->algo = &rcar_i2c_algo;
+ adap->class = I2C_CLASS_DEPRECATED;
+ adap->retries = 3;
+ adap->dev.parent = dev;
+ adap->dev.of_node = dev->of_node;
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index a9791509966a..69e11853e8bf 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -399,7 +399,7 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
}
/* is there anything left to handle? */
- if (unlikely(ipd == 0))
+ if (unlikely((ipd & REG_INT_ALL) == 0))
goto out;
switch (i2c->state) {
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index e828a1dba0e5..e086fb075f2b 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1128,11 +1128,11 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
- i2c->adap.owner = THIS_MODULE;
- i2c->adap.algo = &s3c24xx_i2c_algorithm;
+ i2c->adap.owner = THIS_MODULE;
+ i2c->adap.algo = &s3c24xx_i2c_algorithm;
i2c->adap.retries = 2;
- i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
- i2c->tx_setup = 50;
+ i2c->adap.class = I2C_CLASS_DEPRECATED;
+ i2c->tx_setup = 50;
init_waitqueue_head(&i2c->wait);
@@ -1267,7 +1267,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev)
return 0;
}
-static int s3c24xx_i2c_resume(struct device *dev)
+static int s3c24xx_i2c_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1285,7 +1285,11 @@ static int s3c24xx_i2c_resume(struct device *dev)
static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend_noirq = s3c24xx_i2c_suspend_noirq,
- .resume = s3c24xx_i2c_resume,
+ .resume_noirq = s3c24xx_i2c_resume_noirq,
+ .freeze_noirq = s3c24xx_i2c_suspend_noirq,
+ .thaw_noirq = s3c24xx_i2c_resume_noirq,
+ .poweroff_noirq = s3c24xx_i2c_suspend_noirq,
+ .restore_noirq = s3c24xx_i2c_resume_noirq,
#endif
};
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
deleted file mode 100644
index dd186a037684..000000000000
--- a/drivers/i2c/busses/i2c-s6000.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.c
- *
- * Description: Driver for S6000 Family I2C Interface
- * Copyright (c) 2008 emlix GmbH
- * Author: Oskar Schirmer <oskar@scara.com>
- *
- * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
- * Copyright (c) 2005-2007 Analog Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/i2c/s6000.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "i2c-s6000.h"
-
-#define DRV_NAME "i2c-s6000"
-
-#define POLL_TIMEOUT (2 * HZ)
-
-struct s6i2c_if {
- u8 __iomem *reg; /* memory mapped registers */
- int irq;
- spinlock_t lock;
- struct i2c_msg *msgs; /* messages currently handled */
- int msgs_num; /* nb of msgs to do */
- int msgs_push; /* nb of msgs read/written */
- int msgs_done; /* nb of msgs finally handled */
- unsigned push; /* nb of bytes read/written in msg */
- unsigned done; /* nb of bytes finally handled */
- int timeout_count; /* timeout retries left */
- struct timer_list timeout_timer;
- struct i2c_adapter adap;
- struct completion complete;
- struct clk *clk;
- struct resource *res;
-};
-
-static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n)
-{
- return readw(iface->reg + (n));
-}
-
-static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v)
-{
- writew(v, iface->reg + (n));
-}
-
-static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n)
-{
- return readl(iface->reg + (n));
-}
-
-static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v)
-{
- writel(v, iface->reg + (n));
-}
-
-static struct s6i2c_if s6i2c_if;
-
-static void s6i2c_handle_interrupt(struct s6i2c_if *iface)
-{
- if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) {
- i2c_rd16(iface, S6_I2C_CLRTXABRT);
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- complete(&iface->complete);
- return;
- }
- if (iface->msgs_done >= iface->msgs_num) {
- dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n",
- i2c_rd16(iface, S6_I2C_INTRSTAT));
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- return;
- }
- while ((iface->msgs_push < iface->msgs_num)
- && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) {
- struct i2c_msg *m = &iface->msgs[iface->msgs_push];
- if (!(m->flags & I2C_M_RD))
- i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]);
- else
- i2c_wr16(iface, S6_I2C_DATACMD,
- 1 << S6_I2C_DATACMD_READ);
- if (++iface->push >= m->len) {
- iface->push = 0;
- iface->msgs_push += 1;
- }
- }
- do {
- struct i2c_msg *m = &iface->msgs[iface->msgs_done];
- if (!(m->flags & I2C_M_RD)) {
- if (iface->msgs_done < iface->msgs_push)
- iface->msgs_done += 1;
- else
- break;
- } else if (i2c_rd16(iface, S6_I2C_STATUS)
- & (1 << S6_I2C_STATUS_RFNE)) {
- m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD);
- if (++iface->done >= m->len) {
- iface->done = 0;
- iface->msgs_done += 1;
- }
- } else{
- break;
- }
- } while (iface->msgs_done < iface->msgs_num);
- if (iface->msgs_done >= iface->msgs_num) {
- i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT);
- complete(&iface->complete);
- } else if (iface->msgs_push >= iface->msgs_num) {
- i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
- (1 << S6_I2C_INTR_RXFULL));
- } else {
- i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
- (1 << S6_I2C_INTR_TXEMPTY) |
- (1 << S6_I2C_INTR_RXFULL));
- }
-}
-
-static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id)
-{
- struct s6i2c_if *iface = dev_id;
- if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER)
- | (1 << S6_I2C_INTR_RXOVER)
- | (1 << S6_I2C_INTR_RXFULL)
- | (1 << S6_I2C_INTR_TXOVER)
- | (1 << S6_I2C_INTR_TXEMPTY)
- | (1 << S6_I2C_INTR_RDREQ)
- | (1 << S6_I2C_INTR_TXABRT)
- | (1 << S6_I2C_INTR_RXDONE)
- | (1 << S6_I2C_INTR_ACTIVITY)
- | (1 << S6_I2C_INTR_STOPDET)
- | (1 << S6_I2C_INTR_STARTDET)
- | (1 << S6_I2C_INTR_GENCALL))))
- return IRQ_NONE;
-
- spin_lock(&iface->lock);
- del_timer(&iface->timeout_timer);
- s6i2c_handle_interrupt(iface);
- spin_unlock(&iface->lock);
- return IRQ_HANDLED;
-}
-
-static void s6i2c_timeout(unsigned long data)
-{
- struct s6i2c_if *iface = (struct s6i2c_if *)data;
- unsigned long flags;
-
- spin_lock_irqsave(&iface->lock, flags);
- s6i2c_handle_interrupt(iface);
- if (--iface->timeout_count > 0) {
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- } else {
- complete(&iface->complete);
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- }
- spin_unlock_irqrestore(&iface->lock, flags);
-}
-
-static int s6i2c_master_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct s6i2c_if *iface = adap->algo_data;
- int i;
- if (num == 0)
- return 0;
- if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
- yield();
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- i2c_rd16(iface, S6_I2C_CLRINTR);
- for (i = 0; i < num; i++) {
- if (msgs[i].flags & I2C_M_TEN) {
- dev_err(&adap->dev,
- "s6i2c: 10 bits addr not supported\n");
- return -EINVAL;
- }
- if (msgs[i].len == 0) {
- dev_err(&adap->dev,
- "s6i2c: zero length message not supported\n");
- return -EINVAL;
- }
- if (msgs[i].addr != msgs[0].addr) {
- dev_err(&adap->dev,
- "s6i2c: multiple xfer cannot change target\n");
- return -EINVAL;
- }
- }
-
- iface->msgs = msgs;
- iface->msgs_num = num;
- iface->msgs_push = 0;
- iface->msgs_done = 0;
- iface->push = 0;
- iface->done = 0;
- iface->timeout_count = 10;
- i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr);
- i2c_wr16(iface, S6_I2C_ENABLE, 1);
- i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) |
- (1 << S6_I2C_INTR_TXABRT));
-
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- wait_for_completion(&iface->complete);
- del_timer_sync(&iface->timeout_timer);
- while (i2c_rd32(iface, S6_I2C_TXFLR) > 0)
- schedule();
- while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
- schedule();
-
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- i2c_wr16(iface, S6_I2C_ENABLE, 0);
- return iface->msgs_done;
-}
-
-static u32 s6i2c_functionality(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm s6i2c_algorithm = {
- .master_xfer = s6i2c_master_xfer,
- .functionality = s6i2c_functionality,
-};
-
-static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
-{
- u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
- if (dividend > 0xffff)
- return 0xffff;
- return dividend;
-}
-
-static int s6i2c_probe(struct platform_device *dev)
-{
- struct s6i2c_if *iface = &s6i2c_if;
- struct i2c_adapter *p_adap;
- const char *clock;
- int bus_num, rc;
- spin_lock_init(&iface->lock);
- init_completion(&iface->complete);
- iface->irq = platform_get_irq(dev, 0);
- if (iface->irq < 0) {
- rc = iface->irq;
- goto err_out;
- }
- iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!iface->res) {
- rc = -ENXIO;
- goto err_out;
- }
- iface->res = request_mem_region(iface->res->start,
- resource_size(iface->res),
- dev->dev.bus_id);
- if (!iface->res) {
- rc = -EBUSY;
- goto err_out;
- }
- iface->reg = ioremap_nocache(iface->res->start,
- resource_size(iface->res));
- if (!iface->reg) {
- rc = -ENOMEM;
- goto err_reg;
- }
-
- clock = 0;
- bus_num = -1;
- if (dev_get_platdata(&dev->dev)) {
- struct s6_i2c_platform_data *pdata =
- dev_get_platdata(&dev->dev);
- bus_num = pdata->bus_num;
- clock = pdata->clock;
- }
- iface->clk = clk_get(&dev->dev, clock);
- if (IS_ERR(iface->clk)) {
- rc = PTR_ERR(iface->clk);
- goto err_map;
- }
- rc = clk_enable(iface->clk);
- if (rc < 0)
- goto err_clk_put;
- init_timer(&iface->timeout_timer);
- iface->timeout_timer.function = s6i2c_timeout;
- iface->timeout_timer.data = (unsigned long)iface;
-
- p_adap = &iface->adap;
- strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
- p_adap->algo = &s6i2c_algorithm;
- p_adap->algo_data = iface;
- p_adap->nr = bus_num;
- p_adap->class = 0;
- p_adap->dev.parent = &dev->dev;
- i2c_wr16(iface, S6_I2C_INTRMASK, 0);
- rc = request_irq(iface->irq, s6i2c_interrupt_entry,
- IRQF_SHARED, dev->name, iface);
- if (rc) {
- dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq);
- goto err_clk_dis;
- }
-
- i2c_wr16(iface, S6_I2C_ENABLE, 0);
- udelay(1);
- i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST);
- i2c_wr16(iface, S6_I2C_CLRTXABRT, 1);
- i2c_wr16(iface, S6_I2C_CON,
- (1 << S6_I2C_CON_MASTER) |
- (S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) |
- (0 << S6_I2C_CON_10BITSLAVE) |
- (0 << S6_I2C_CON_10BITMASTER) |
- (1 << S6_I2C_CON_RESTARTENA) |
- (1 << S6_I2C_CON_SLAVEDISABLE));
- i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000));
- i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700));
- i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600));
- i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300));
- i2c_wr16(iface, S6_I2C_RXTL, 0);
- i2c_wr16(iface, S6_I2C_TXTL, 0);
-
- platform_set_drvdata(dev, iface);
- rc = i2c_add_numbered_adapter(p_adap);
- if (rc)
- goto err_irq_free;
- return 0;
-
-err_irq_free:
- free_irq(iface->irq, iface);
-err_clk_dis:
- clk_disable(iface->clk);
-err_clk_put:
- clk_put(iface->clk);
-err_map:
- iounmap(iface->reg);
-err_reg:
- release_mem_region(iface->res->start,
- resource_size(iface->res));
-err_out:
- return rc;
-}
-
-static int s6i2c_remove(struct platform_device *pdev)
-{
- struct s6i2c_if *iface = platform_get_drvdata(pdev);
- i2c_wr16(iface, S6_I2C_ENABLE, 0);
- i2c_del_adapter(&iface->adap);
- free_irq(iface->irq, iface);
- clk_disable(iface->clk);
- clk_put(iface->clk);
- iounmap(iface->reg);
- release_mem_region(iface->res->start,
- resource_size(iface->res));
- return 0;
-}
-
-static struct platform_driver s6i2c_driver = {
- .probe = s6i2c_probe,
- .remove = s6i2c_remove,
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s6i2c_init(void)
-{
- pr_info("I2C: S6000 I2C driver\n");
- return platform_driver_register(&s6i2c_driver);
-}
-
-static void __exit s6i2c_exit(void)
-{
- platform_driver_unregister(&s6i2c_driver);
-}
-
-MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-
-subsys_initcall(s6i2c_init);
-module_exit(s6i2c_exit);
diff --git a/drivers/i2c/busses/i2c-s6000.h b/drivers/i2c/busses/i2c-s6000.h
deleted file mode 100644
index 4936f9f2256f..000000000000
--- a/drivers/i2c/busses/i2c-s6000.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2008 Emlix GmbH <info@emlix.com>
- * Author: Oskar Schirmer <oskar@scara.com>
- */
-
-#ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H
-#define __DRIVERS_I2C_BUSSES_I2C_S6000_H
-
-#define S6_I2C_CON 0x000
-#define S6_I2C_CON_MASTER 0
-#define S6_I2C_CON_SPEED 1
-#define S6_I2C_CON_SPEED_NORMAL 1
-#define S6_I2C_CON_SPEED_FAST 2
-#define S6_I2C_CON_SPEED_MASK 3
-#define S6_I2C_CON_10BITSLAVE 3
-#define S6_I2C_CON_10BITMASTER 4
-#define S6_I2C_CON_RESTARTENA 5
-#define S6_I2C_CON_SLAVEDISABLE 6
-#define S6_I2C_TAR 0x004
-#define S6_I2C_TAR_GCORSTART 10
-#define S6_I2C_TAR_SPECIAL 11
-#define S6_I2C_SAR 0x008
-#define S6_I2C_HSMADDR 0x00C
-#define S6_I2C_DATACMD 0x010
-#define S6_I2C_DATACMD_READ 8
-#define S6_I2C_SSHCNT 0x014
-#define S6_I2C_SSLCNT 0x018
-#define S6_I2C_FSHCNT 0x01C
-#define S6_I2C_FSLCNT 0x020
-#define S6_I2C_INTRSTAT 0x02C
-#define S6_I2C_INTRMASK 0x030
-#define S6_I2C_RAWINTR 0x034
-#define S6_I2C_INTR_RXUNDER 0
-#define S6_I2C_INTR_RXOVER 1
-#define S6_I2C_INTR_RXFULL 2
-#define S6_I2C_INTR_TXOVER 3
-#define S6_I2C_INTR_TXEMPTY 4
-#define S6_I2C_INTR_RDREQ 5
-#define S6_I2C_INTR_TXABRT 6
-#define S6_I2C_INTR_RXDONE 7
-#define S6_I2C_INTR_ACTIVITY 8
-#define S6_I2C_INTR_STOPDET 9
-#define S6_I2C_INTR_STARTDET 10
-#define S6_I2C_INTR_GENCALL 11
-#define S6_I2C_RXTL 0x038
-#define S6_I2C_TXTL 0x03C
-#define S6_I2C_CLRINTR 0x040
-#define S6_I2C_CLRRXUNDER 0x044
-#define S6_I2C_CLRRXOVER 0x048
-#define S6_I2C_CLRTXOVER 0x04C
-#define S6_I2C_CLRRDREQ 0x050
-#define S6_I2C_CLRTXABRT 0x054
-#define S6_I2C_CLRRXDONE 0x058
-#define S6_I2C_CLRACTIVITY 0x05C
-#define S6_I2C_CLRSTOPDET 0x060
-#define S6_I2C_CLRSTARTDET 0x064
-#define S6_I2C_CLRGENCALL 0x068
-#define S6_I2C_ENABLE 0x06C
-#define S6_I2C_STATUS 0x070
-#define S6_I2C_STATUS_ACTIVITY 0
-#define S6_I2C_STATUS_TFNF 1
-#define S6_I2C_STATUS_TFE 2
-#define S6_I2C_STATUS_RFNE 3
-#define S6_I2C_STATUS_RFF 4
-#define S6_I2C_TXFLR 0x074
-#define S6_I2C_RXFLR 0x078
-#define S6_I2C_SRESET 0x07C
-#define S6_I2C_SRESET_IC_SRST 0
-#define S6_I2C_SRESET_IC_MASTER_SRST 1
-#define S6_I2C_SRESET_IC_SLAVE_SRST 2
-#define S6_I2C_TXABRTSOURCE 0x080
-
-#endif
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index a3216defc1d3..b1336d5f0531 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -311,7 +311,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
goto out;
}
adap = &siic->adapter;
- adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
siic->base = devm_ioremap_resource(&pdev->dev, mem_res);
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 95b947670386..2e4eccd6599a 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -206,25 +206,31 @@ static inline void st_i2c_clr_bits(void __iomem *reg, u32 mask)
writel_relaxed(readl_relaxed(reg) & ~mask, reg);
}
-/* From I2C Specifications v0.5 */
+/*
+ * From I2C Specifications v0.5.
+ *
+ * All the values below have +10% margin added to be
+ * compatible with some out-of-spec devices,
+ * like HDMI link of the Toshiba 19AV600 TV.
+ */
static struct st_i2c_timings i2c_timings[] = {
[I2C_MODE_STANDARD] = {
.rate = 100000,
- .rep_start_hold = 4000,
- .rep_start_setup = 4700,
- .start_hold = 4000,
- .data_setup_time = 250,
- .stop_setup_time = 4000,
- .bus_free_time = 4700,
+ .rep_start_hold = 4400,
+ .rep_start_setup = 5170,
+ .start_hold = 4400,
+ .data_setup_time = 275,
+ .stop_setup_time = 4400,
+ .bus_free_time = 5170,
},
[I2C_MODE_FAST] = {
.rate = 400000,
- .rep_start_hold = 600,
- .rep_start_setup = 600,
- .start_hold = 600,
- .data_setup_time = 100,
- .stop_setup_time = 600,
- .bus_free_time = 1300,
+ .rep_start_hold = 660,
+ .rep_start_setup = 660,
+ .start_hold = 660,
+ .data_setup_time = 110,
+ .stop_setup_time = 660,
+ .bus_free_time = 1430,
},
};
@@ -815,7 +821,7 @@ static int st_i2c_probe(struct platform_device *pdev)
adap = &i2c_dev->adap;
i2c_set_adapdata(adap, i2c_dev);
- snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%x)", res->start);
+ snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%pa)", &res->start);
adap->owner = THIS_MODULE;
adap->timeout = 2 * HZ;
adap->retries = 0;
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index fefb1c19ec1d..6a44f37798c8 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -909,7 +909,7 @@ static int stu300_probe(struct platform_device *pdev)
adap = &dev->adapter;
adap->owner = THIS_MODULE;
/* DDC class but actually often used for more generic I2C */
- adap->class = I2C_CLASS_DDC | I2C_CLASS_DEPRECATED;
+ adap->class = I2C_CLASS_DEPRECATED;
strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
sizeof(adap->name));
adap->nr = bus_nr;
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
index 057602683553..10855a0b7e7f 100644
--- a/drivers/i2c/busses/i2c-taos-evm.c
+++ b/drivers/i2c/busses/i2c-taos-evm.c
@@ -311,19 +311,8 @@ static struct serio_driver taos_drv = {
.interrupt = taos_interrupt,
};
-static int __init taos_init(void)
-{
- return serio_register_driver(&taos_drv);
-}
-
-static void __exit taos_exit(void)
-{
- serio_unregister_driver(&taos_drv);
-}
+module_serio_driver(taos_drv);
MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
MODULE_DESCRIPTION("TAOS evaluation module driver");
MODULE_LICENSE("GPL");
-
-module_init(taos_init);
-module_exit(taos_exit);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index f1bb2fc06791..87d0371cebb7 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -792,7 +792,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
i2c_dev->adapter.owner = THIS_MODULE;
- i2c_dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+ i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
sizeof(i2c_dev->adapter.name));
i2c_dev->adapter.algo = &tegra_i2c_algo;
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 7731f1795869..ade9223912d3 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -677,15 +677,15 @@ static u32 xiic_func(struct i2c_adapter *adap)
}
static const struct i2c_algorithm xiic_algorithm = {
- .master_xfer = xiic_xfer,
- .functionality = xiic_func,
+ .master_xfer = xiic_xfer,
+ .functionality = xiic_func,
};
static struct i2c_adapter xiic_adapter = {
- .owner = THIS_MODULE,
- .name = DRIVER_NAME,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
- .algo = &xiic_algorithm,
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .class = I2C_CLASS_DEPRECATED,
+ .algo = &xiic_algorithm,
};
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
deleted file mode 100644
index 8eadf0f47ad7..000000000000
--- a/drivers/i2c/busses/scx200_i2c.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* linux/drivers/i2c/busses/scx200_i2c.c
-
- Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
-
- National Semiconductor SCx200 I2C bus on GPIO pins
-
- Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. Vogl
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/io.h>
-
-#include <linux/scx200_gpio.h>
-
-MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
-MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
-MODULE_LICENSE("GPL");
-
-static int scl = CONFIG_SCx200_I2C_SCL;
-static int sda = CONFIG_SCx200_I2C_SDA;
-
-module_param(scl, int, 0);
-MODULE_PARM_DESC(scl, "GPIO line for SCL");
-module_param(sda, int, 0);
-MODULE_PARM_DESC(sda, "GPIO line for SDA");
-
-static void scx200_i2c_setscl(void *data, int state)
-{
- scx200_gpio_set(scl, state);
-}
-
-static void scx200_i2c_setsda(void *data, int state)
-{
- scx200_gpio_set(sda, state);
-}
-
-static int scx200_i2c_getscl(void *data)
-{
- return scx200_gpio_get(scl);
-}
-
-static int scx200_i2c_getsda(void *data)
-{
- return scx200_gpio_get(sda);
-}
-
-/* ------------------------------------------------------------------------
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
-
-static struct i2c_algo_bit_data scx200_i2c_data = {
- .setsda = scx200_i2c_setsda,
- .setscl = scx200_i2c_setscl,
- .getsda = scx200_i2c_getsda,
- .getscl = scx200_i2c_getscl,
- .udelay = 10,
- .timeout = HZ,
-};
-
-static struct i2c_adapter scx200_i2c_ops = {
- .owner = THIS_MODULE,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- .algo_data = &scx200_i2c_data,
- .name = "NatSemi SCx200 I2C",
-};
-
-static int scx200_i2c_init(void)
-{
- pr_debug("NatSemi SCx200 I2C Driver\n");
-
- if (!scx200_gpio_present()) {
- pr_err("no SCx200 gpio pins available\n");
- return -ENODEV;
- }
-
- pr_debug("SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
-
- if (scl == -1 || sda == -1 || scl == sda) {
- pr_err("scl and sda must be specified\n");
- return -EINVAL;
- }
-
- /* Configure GPIOs as open collector outputs */
- scx200_gpio_configure(scl, ~2, 5);
- scx200_gpio_configure(sda, ~2, 5);
-
- if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) {
- pr_err("adapter %s registration failed\n", scx200_i2c_ops.name);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void scx200_i2c_cleanup(void)
-{
- i2c_del_adapter(&scx200_i2c_ops);
-}
-
-module_init(scx200_i2c_init);
-module_exit(scx200_i2c_cleanup);
-
-/*
- Local variables:
- compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
- c-basic-offset: 8
- End:
-*/
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c
new file mode 100644
index 000000000000..e8b61967334b
--- /dev/null
+++ b/drivers/i2c/i2c-acpi.c
@@ -0,0 +1,362 @@
+/*
+ * I2C ACPI code
+ *
+ * Copyright (C) 2014 Intel Corp
+ *
+ * Author: Lan Tianyu <tianyu.lan@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.
+ */
+#define pr_fmt(fmt) "I2C/ACPI : " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+
+struct acpi_i2c_handler_data {
+ struct acpi_connection_info info;
+ struct i2c_adapter *adapter;
+};
+
+struct gsb_buffer {
+ u8 status;
+ u8 len;
+ union {
+ u16 wdata;
+ u8 bdata;
+ u8 data[0];
+ };
+} __packed;
+
+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.companion = adev;
+ 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;
+
+ adev->power.flags.ignore_parent = true;
+ strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+ if (!i2c_new_device(adapter, &info)) {
+ adev->power.flags.ignore_parent = false;
+ 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
+ * @adap: 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 *adap)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!adap->dev.parent)
+ return;
+
+ handle = ACPI_HANDLE(adap->dev.parent);
+ if (!handle)
+ return;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_i2c_add_device, NULL,
+ adap, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+}
+
+static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[2];
+ int ret;
+ u8 *buffer;
+
+ buffer = kzalloc(data_len, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = 1;
+ msgs[0].buf = &cmd;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags | I2C_M_RD;
+ msgs[1].len = data_len;
+ msgs[1].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c read failed\n");
+ else
+ memcpy(data, buffer, data_len);
+
+ kfree(buffer);
+ return ret;
+}
+
+static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[1];
+ u8 *buffer;
+ int ret = AE_OK;
+
+ buffer = kzalloc(data_len + 1, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ buffer[0] = cmd;
+ memcpy(buffer + 1, data, data_len);
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = data_len + 1;
+ msgs[0].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c write failed\n");
+
+ kfree(buffer);
+ return ret;
+}
+
+static acpi_status
+acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+ u32 bits, u64 *value64,
+ void *handler_context, void *region_context)
+{
+ struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
+ struct acpi_i2c_handler_data *data = handler_context;
+ struct acpi_connection_info *info = &data->info;
+ struct acpi_resource_i2c_serialbus *sb;
+ struct i2c_adapter *adapter = data->adapter;
+ struct i2c_client client;
+ struct acpi_resource *ares;
+ u32 accessor_type = function >> 16;
+ u8 action = function & ACPI_IO_MASK;
+ acpi_status ret = AE_OK;
+ int status;
+
+ ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
+ if (ACPI_FAILURE(ret))
+ return ret;
+
+ if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ memset(&client, 0, sizeof(client));
+ client.adapter = adapter;
+ client.addr = sb->slave_address;
+ client.flags = 0;
+
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ client.flags |= I2C_CLIENT_TEN;
+
+ switch (accessor_type) {
+ case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte(&client);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte(&client, gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BYTE:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte_data(&client, command);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte_data(&client, command,
+ gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_WORD:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_word_data(&client, command);
+ if (status >= 0) {
+ gsb->wdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_word_data(&client, command,
+ gsb->wdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_block_data(&client, command,
+ gsb->data);
+ if (status >= 0) {
+ gsb->len = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_block_data(&client, command,
+ gsb->len, gsb->data);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
+ if (action == ACPI_READ) {
+ status = acpi_gsb_i2c_read_bytes(&client, command,
+ gsb->data, info->access_length);
+ if (status > 0)
+ status = 0;
+ } else {
+ status = acpi_gsb_i2c_write_bytes(&client, command,
+ gsb->data, info->access_length);
+ }
+ break;
+
+ default:
+ pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ gsb->status = status;
+
+ err:
+ ACPI_FREE(ares);
+ return ret;
+}
+
+
+int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->adapter = adapter;
+ status = acpi_bus_attach_private_data(handle, (void *)data);
+ if (ACPI_FAILURE(status)) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ status = acpi_install_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler,
+ NULL,
+ data);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&adapter->dev, "Error installing i2c space handler\n");
+ acpi_bus_detach_private_data(handle);
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return;
+
+ acpi_remove_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler);
+
+ status = acpi_bus_get_private_data(handle, (void **)&data);
+ if (ACPI_SUCCESS(status))
+ kfree(data);
+
+ acpi_bus_detach_private_data(handle);
+}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7c7f4b856bad..632057a44615 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -42,6 +42,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/clk/clk-conf.h>
#include <linux/completion.h>
#include <linux/hardirq.h>
#include <linux/irqflags.h>
@@ -274,6 +275,10 @@ static int i2c_device_probe(struct device *dev)
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
+ status = of_clk_set_defaults(dev->of_node, false);
+ if (status < 0)
+ return status;
+
acpi_dev_pm_attach(&client->dev, true);
status = driver->probe(client, i2c_match_id(driver->id_table, client));
if (status)
@@ -1092,101 +1097,6 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
static void of_i2c_register_devices(struct i2c_adapter *adap) { }
#endif /* CONFIG_OF */
-/* ACPI support code */
-
-#if IS_ENABLED(CONFIG_ACPI)
-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.companion = adev;
- 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;
-
- adev->power.flags.ignore_parent = true;
- strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
- if (!i2c_new_device(adapter, &info)) {
- adev->power.flags.ignore_parent = false;
- 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
- * @adap: 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.
- */
-static void acpi_i2c_register_devices(struct i2c_adapter *adap)
-{
- acpi_handle handle;
- acpi_status status;
-
- if (!adap->dev.parent)
- return;
-
- handle = ACPI_HANDLE(adap->dev.parent);
- if (!handle)
- return;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
- acpi_i2c_add_device, NULL,
- adap, NULL);
- if (ACPI_FAILURE(status))
- dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
-}
-#else
-static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
-#endif /* CONFIG_ACPI */
-
static int i2c_do_add_adapter(struct i2c_driver *driver,
struct i2c_adapter *adap)
{
@@ -1293,6 +1203,7 @@ exit_recovery:
/* create pre-declared device nodes */
of_i2c_register_devices(adap);
acpi_i2c_register_devices(adap);
+ acpi_i2c_install_space_handler(adap);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
@@ -1466,6 +1377,7 @@ void i2c_del_adapter(struct i2c_adapter *adap)
return;
}
+ acpi_i2c_remove_space_handler(adap);
/* Tell drivers about this removal */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -2008,6 +1920,16 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
if (!driver->detect || !address_list)
return 0;
+ /* Warn that the adapter lost class based instantiation */
+ if (adapter->class == I2C_CLASS_DEPRECATED) {
+ dev_dbg(&adapter->dev,
+ "This adapter dropped support for I2C classes and "
+ "won't auto-detect %s devices anymore. If you need it, check "
+ "'Documentation/i2c/instantiating-devices' for alternatives.\n",
+ driver->driver.name);
+ return 0;
+ }
+
/* Stop here if the classes do not match */
if (!(adapter->class & driver->class))
return 0;
diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c
index 77e4849d2f2a..d241aa295d96 100644
--- a/drivers/i2c/i2c-stub.c
+++ b/drivers/i2c/i2c-stub.c
@@ -2,7 +2,7 @@
i2c-stub.c - I2C/SMBus chip emulator
Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
- Copyright (C) 2007, 2012 Jean Delvare <jdelvare@suse.de>
+ Copyright (C) 2007-2014 Jean Delvare <jdelvare@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,28 +27,109 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/i2c.h>
+#include <linux/list.h>
#define MAX_CHIPS 10
-#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
- I2C_FUNC_SMBUS_I2C_BLOCK)
+
+/*
+ * Support for I2C_FUNC_SMBUS_BLOCK_DATA is disabled by default and must
+ * be enabled explicitly by setting the I2C_FUNC_SMBUS_BLOCK_DATA bits
+ * in the 'functionality' module parameter.
+ */
+#define STUB_FUNC_DEFAULT \
+ (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
+ I2C_FUNC_SMBUS_I2C_BLOCK)
+
+#define STUB_FUNC_ALL \
+ (STUB_FUNC_DEFAULT | I2C_FUNC_SMBUS_BLOCK_DATA)
static unsigned short chip_addr[MAX_CHIPS];
module_param_array(chip_addr, ushort, NULL, S_IRUGO);
MODULE_PARM_DESC(chip_addr,
"Chip addresses (up to 10, between 0x03 and 0x77)");
-static unsigned long functionality = STUB_FUNC;
+static unsigned long functionality = STUB_FUNC_DEFAULT;
module_param(functionality, ulong, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(functionality, "Override functionality bitfield");
+/* Some chips have banked register ranges */
+
+static u8 bank_reg[MAX_CHIPS];
+module_param_array(bank_reg, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_reg, "Bank register");
+
+static u8 bank_mask[MAX_CHIPS];
+module_param_array(bank_mask, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_mask, "Bank value mask");
+
+static u8 bank_start[MAX_CHIPS];
+module_param_array(bank_start, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_start, "First banked register");
+
+static u8 bank_end[MAX_CHIPS];
+module_param_array(bank_end, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_end, "Last banked register");
+
+struct smbus_block_data {
+ struct list_head node;
+ u8 command;
+ u8 len;
+ u8 block[I2C_SMBUS_BLOCK_MAX];
+};
+
struct stub_chip {
u8 pointer;
u16 words[256]; /* Byte operations use the LSB as per SMBus
specification */
+ struct list_head smbus_blocks;
+
+ /* For chips with banks, extra registers are allocated dynamically */
+ u8 bank_reg;
+ u8 bank_shift;
+ u8 bank_mask;
+ u8 bank_sel; /* Currently selected bank */
+ u8 bank_start;
+ u8 bank_end;
+ u16 bank_size;
+ u16 *bank_words; /* Room for bank_mask * bank_size registers */
};
static struct stub_chip *stub_chips;
+static int stub_chips_nr;
+
+static struct smbus_block_data *stub_find_block(struct device *dev,
+ struct stub_chip *chip,
+ u8 command, bool create)
+{
+ struct smbus_block_data *b, *rb = NULL;
+
+ list_for_each_entry(b, &chip->smbus_blocks, node) {
+ if (b->command == command) {
+ rb = b;
+ break;
+ }
+ }
+ if (rb == NULL && create) {
+ rb = devm_kzalloc(dev, sizeof(*rb), GFP_KERNEL);
+ if (rb == NULL)
+ return rb;
+ rb->command = command;
+ list_add(&rb->node, &chip->smbus_blocks);
+ }
+ return rb;
+}
+
+static u16 *stub_get_wordp(struct stub_chip *chip, u8 offset)
+{
+ if (chip->bank_sel &&
+ offset >= chip->bank_start && offset <= chip->bank_end)
+ return chip->bank_words +
+ (chip->bank_sel - 1) * chip->bank_size +
+ offset - chip->bank_start;
+ else
+ return chip->words + offset;
+}
/* Return negative errno on error. */
static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
@@ -57,9 +138,11 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
s32 ret;
int i, len;
struct stub_chip *chip = NULL;
+ struct smbus_block_data *b;
+ u16 *wordp;
/* Search for the right chip */
- for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+ for (i = 0; i < stub_chips_nr; i++) {
if (addr == chip_addr[i]) {
chip = stub_chips + i;
break;
@@ -82,7 +165,8 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
"smbus byte - addr 0x%02x, wrote 0x%02x.\n",
addr, command);
} else {
- data->byte = chip->words[chip->pointer++] & 0xff;
+ wordp = stub_get_wordp(chip, chip->pointer++);
+ data->byte = *wordp & 0xff;
dev_dbg(&adap->dev,
"smbus byte - addr 0x%02x, read 0x%02x.\n",
addr, data->byte);
@@ -92,14 +176,25 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break;
case I2C_SMBUS_BYTE_DATA:
+ wordp = stub_get_wordp(chip, command);
if (read_write == I2C_SMBUS_WRITE) {
- chip->words[command] &= 0xff00;
- chip->words[command] |= data->byte;
+ *wordp &= 0xff00;
+ *wordp |= data->byte;
dev_dbg(&adap->dev,
"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
addr, data->byte, command);
+
+ /* Set the bank as needed */
+ if (chip->bank_words && command == chip->bank_reg) {
+ chip->bank_sel =
+ (data->byte >> chip->bank_shift)
+ & chip->bank_mask;
+ dev_dbg(&adap->dev,
+ "switching to bank %u.\n",
+ chip->bank_sel);
+ }
} else {
- data->byte = chip->words[command] & 0xff;
+ data->byte = *wordp & 0xff;
dev_dbg(&adap->dev,
"smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n",
addr, data->byte, command);
@@ -110,13 +205,14 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break;
case I2C_SMBUS_WORD_DATA:
+ wordp = stub_get_wordp(chip, command);
if (read_write == I2C_SMBUS_WRITE) {
- chip->words[command] = data->word;
+ *wordp = data->word;
dev_dbg(&adap->dev,
"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
addr, data->word, command);
} else {
- data->word = chip->words[command];
+ data->word = *wordp;
dev_dbg(&adap->dev,
"smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n",
addr, data->word, command);
@@ -126,6 +222,12 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
+ /*
+ * We ignore banks here, because banked chips don't use I2C
+ * block transfers
+ */
+ if (data->block[0] > 256 - command) /* Avoid overrun */
+ data->block[0] = 256 - command;
len = data->block[0];
if (read_write == I2C_SMBUS_WRITE) {
for (i = 0; i < len; i++) {
@@ -148,6 +250,55 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
ret = 0;
break;
+ case I2C_SMBUS_BLOCK_DATA:
+ /*
+ * We ignore banks here, because chips typically don't use both
+ * banks and SMBus block transfers
+ */
+ b = stub_find_block(&adap->dev, chip, command, false);
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
+ ret = -EINVAL;
+ break;
+ }
+ if (b == NULL) {
+ b = stub_find_block(&adap->dev, chip, command,
+ true);
+ if (b == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+ }
+ /* Largest write sets read block length */
+ if (len > b->len)
+ b->len = len;
+ for (i = 0; i < len; i++)
+ b->block[i] = data->block[i + 1];
+ /* update for byte and word commands */
+ chip->words[command] = (b->block[0] << 8) | b->len;
+ dev_dbg(&adap->dev,
+ "smbus block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+ addr, len, command);
+ } else {
+ if (b == NULL) {
+ dev_dbg(&adap->dev,
+ "SMBus block read command without prior block write not supported\n");
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ len = b->len;
+ data->block[0] = len;
+ for (i = 0; i < len; i++)
+ data->block[i + 1] = b->block[i];
+ dev_dbg(&adap->dev,
+ "smbus block data - addr 0x%02x, read %d bytes at 0x%02x.\n",
+ addr, len, command);
+ }
+
+ ret = 0;
+ break;
+
default:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
ret = -EOPNOTSUPP;
@@ -159,7 +310,7 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
static u32 stub_func(struct i2c_adapter *adapter)
{
- return STUB_FUNC & functionality;
+ return STUB_FUNC_ALL & functionality;
}
static const struct i2c_algorithm smbus_algorithm = {
@@ -174,6 +325,43 @@ static struct i2c_adapter stub_adapter = {
.name = "SMBus stub driver",
};
+static int __init i2c_stub_allocate_banks(int i)
+{
+ struct stub_chip *chip = stub_chips + i;
+
+ chip->bank_reg = bank_reg[i];
+ chip->bank_start = bank_start[i];
+ chip->bank_end = bank_end[i];
+ chip->bank_size = bank_end[i] - bank_start[i] + 1;
+
+ /* We assume that all bits in the mask are contiguous */
+ chip->bank_mask = bank_mask[i];
+ while (!(chip->bank_mask & 1)) {
+ chip->bank_shift++;
+ chip->bank_mask >>= 1;
+ }
+
+ chip->bank_words = kzalloc(chip->bank_mask * chip->bank_size *
+ sizeof(u16), GFP_KERNEL);
+ if (!chip->bank_words)
+ return -ENOMEM;
+
+ pr_debug("i2c-stub: Allocated %u banks of %u words each (registers 0x%02x to 0x%02x)\n",
+ chip->bank_mask, chip->bank_size, chip->bank_start,
+ chip->bank_end);
+
+ return 0;
+}
+
+static void i2c_stub_free(void)
+{
+ int i;
+
+ for (i = 0; i < stub_chips_nr; i++)
+ kfree(stub_chips[i].bank_words);
+ kfree(stub_chips);
+}
+
static int __init i2c_stub_init(void)
{
int i, ret;
@@ -194,22 +382,39 @@ static int __init i2c_stub_init(void)
}
/* Allocate memory for all chips at once */
- stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
+ stub_chips_nr = i;
+ stub_chips = kcalloc(stub_chips_nr, sizeof(struct stub_chip),
+ GFP_KERNEL);
if (!stub_chips) {
pr_err("i2c-stub: Out of memory\n");
return -ENOMEM;
}
+ for (i = 0; i < stub_chips_nr; i++) {
+ INIT_LIST_HEAD(&stub_chips[i].smbus_blocks);
+
+ /* Allocate extra memory for banked register ranges */
+ if (bank_mask[i]) {
+ ret = i2c_stub_allocate_banks(i);
+ if (ret)
+ goto fail_free;
+ }
+ }
ret = i2c_add_adapter(&stub_adapter);
if (ret)
- kfree(stub_chips);
+ goto fail_free;
+
+ return 0;
+
+ fail_free:
+ i2c_stub_free();
return ret;
}
static void __exit i2c_stub_exit(void)
{
i2c_del_adapter(&stub_adapter);
- kfree(stub_chips);
+ i2c_stub_free();
}
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 9bd4212782ab..ec11b404b433 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -41,6 +41,7 @@
#include <linux/i2c-mux.h>
#include <linux/i2c/pca954x.h>
#include <linux/module.h>
+#include <linux/pm.h>
#include <linux/slab.h>
#define PCA954X_MAX_NCHANS 8
@@ -273,9 +274,23 @@ static int pca954x_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int pca954x_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct pca954x *data = i2c_get_clientdata(client);
+
+ data->last_chan = 0;
+ return i2c_smbus_write_byte(client, 0);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume);
+
static struct i2c_driver pca954x_driver = {
.driver = {
.name = "pca954x",
+ .pm = &pca954x_pm,
.owner = THIS_MODULE,
},
.probe = pca954x_probe,
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 259786ca8b75..07ea58084068 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -592,18 +592,7 @@ static struct platform_driver au1200_ide_driver = {
.remove = au_ide_remove,
};
-static int __init au_ide_init(void)
-{
- return platform_driver_register(&au1200_ide_driver);
-}
-
-static void __exit au_ide_exit(void)
-{
- platform_driver_unregister(&au1200_ide_driver);
-}
+module_platform_driver(au1200_ide_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AU1200 IDE driver");
-
-module_init(au_ide_init);
-module_exit(au_ide_exit);
diff --git a/drivers/ide/ide_platform.c b/drivers/ide/ide_platform.c
index a8b4b6af80e7..d48de6de503e 100644
--- a/drivers/ide/ide_platform.c
+++ b/drivers/ide/ide_platform.c
@@ -131,19 +131,8 @@ static struct platform_driver platform_ide_driver = {
.remove = plat_ide_remove,
};
-static int __init platform_ide_init(void)
-{
- return platform_driver_register(&platform_ide_driver);
-}
-
-static void __exit platform_ide_exit(void)
-{
- platform_driver_unregister(&platform_ide_driver);
-}
+module_platform_driver(platform_ide_driver);
MODULE_DESCRIPTION("Platform IDE driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pata_platform");
-
-module_init(platform_ide_init);
-module_exit(platform_ide_exit);
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 1e120fa1e156..12addf272a61 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -77,4 +77,16 @@ config MMA8452
To compile this driver as a module, choose M here: the module
will be called mma8452.
+config KXCJK1013
+ tristate "Kionix 3-Axis Accelerometer Driver"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here if you want to build a driver for the Kionix KXCJK-1013
+ triaxial acceleration sensor.
+
+ To compile this driver as a module, choose M here: the module will
+ be called kxcjk-1013.
+
endmenu
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index dc0e379c2592..6578ca1a8e09 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
+obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
obj-$(CONFIG_MMA8452) += mma8452.o
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
new file mode 100644
index 000000000000..7941cf2d31ee
--- /dev/null
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -0,0 +1,764 @@
+/*
+ * KXCJK-1013 3-axis accelerometer driver
+ * Copyright (c) 2014, 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/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/accel/kxcjk_1013.h>
+
+#define KXCJK1013_DRV_NAME "kxcjk1013"
+#define KXCJK1013_IRQ_NAME "kxcjk1013_event"
+
+#define KXCJK1013_REG_XOUT_L 0x06
+/*
+ * From low byte X axis register, all the other addresses of Y and Z can be
+ * obtained by just applying axis offset. The following axis defines are just
+ * provide clarity, but not used.
+ */
+#define KXCJK1013_REG_XOUT_H 0x07
+#define KXCJK1013_REG_YOUT_L 0x08
+#define KXCJK1013_REG_YOUT_H 0x09
+#define KXCJK1013_REG_ZOUT_L 0x0A
+#define KXCJK1013_REG_ZOUT_H 0x0B
+
+#define KXCJK1013_REG_DCST_RESP 0x0C
+#define KXCJK1013_REG_WHO_AM_I 0x0F
+#define KXCJK1013_REG_INT_SRC1 0x16
+#define KXCJK1013_REG_INT_SRC2 0x17
+#define KXCJK1013_REG_STATUS_REG 0x18
+#define KXCJK1013_REG_INT_REL 0x1A
+#define KXCJK1013_REG_CTRL1 0x1B
+#define KXCJK1013_REG_CTRL2 0x1D
+#define KXCJK1013_REG_INT_CTRL1 0x1E
+#define KXCJK1013_REG_INT_CTRL2 0x1F
+#define KXCJK1013_REG_DATA_CTRL 0x21
+#define KXCJK1013_REG_WAKE_TIMER 0x29
+#define KXCJK1013_REG_SELF_TEST 0x3A
+#define KXCJK1013_REG_WAKE_THRES 0x6A
+
+#define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7)
+#define KXCJK1013_REG_CTRL1_BIT_RES BIT(6)
+#define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5)
+#define KXCJK1013_REG_CTRL1_BIT_GSEL1 BIT(4)
+#define KXCJK1013_REG_CTRL1_BIT_GSEL0 BIT(3)
+#define KXCJK1013_REG_CTRL1_BIT_WUFE BIT(1)
+#define KXCJK1013_REG_INT_REG1_BIT_IEA BIT(4)
+#define KXCJK1013_REG_INT_REG1_BIT_IEN BIT(5)
+
+#define KXCJK1013_DATA_MASK_12_BIT 0x0FFF
+#define KXCJK1013_MAX_STARTUP_TIME_US 100000
+
+struct kxcjk1013_data {
+ struct i2c_client *client;
+ struct iio_trigger *trig;
+ bool trig_mode;
+ struct mutex mutex;
+ s16 buffer[8];
+ int power_state;
+ u8 odr_bits;
+ bool active_high_intr;
+};
+
+enum kxcjk1013_axis {
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+};
+
+enum kxcjk1013_mode {
+ STANDBY,
+ OPERATION,
+};
+
+static const struct {
+ int val;
+ int val2;
+ int odr_bits;
+} samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09},
+ {3, 125000, 0x0A}, {6, 250000, 0x0B}, {12, 500000, 0},
+ {25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03},
+ {200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06},
+ {1600, 0, 0x07} };
+
+/* Refer to section 4 of the specification */
+static const struct {
+ int odr_bits;
+ int usec;
+} odr_start_up_times[] = { {0x08, 100000}, {0x09, 100000}, {0x0A, 100000},
+ {0x0B, 100000}, { 0, 80000}, {0x01, 41000},
+ {0x02, 21000}, {0x03, 11000}, {0x04, 6400},
+ {0x05, 3900}, {0x06, 2700}, {0x07, 2100} };
+
+static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
+ enum kxcjk1013_mode mode)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+ return ret;
+ }
+
+ if (mode == STANDBY)
+ ret &= ~KXCJK1013_REG_CTRL1_BIT_PC1;
+ else
+ ret |= KXCJK1013_REG_CTRL1_BIT_PC1;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ KXCJK1013_REG_CTRL1, ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading who_am_i\n");
+ return ret;
+ }
+
+ dev_dbg(&data->client->dev, "KXCJK1013 Chip Id %x\n", ret);
+
+ ret = kxcjk1013_set_mode(data, STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+ return ret;
+ }
+
+ /* Setting range to 4G */
+ ret |= KXCJK1013_REG_CTRL1_BIT_GSEL0;
+ ret &= ~KXCJK1013_REG_CTRL1_BIT_GSEL1;
+
+ /* Set 12 bit mode */
+ ret |= KXCJK1013_REG_CTRL1_BIT_RES;
+
+ ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL1,
+ ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_ctrl\n");
+ return ret;
+ }
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
+ return ret;
+ }
+
+ data->odr_bits = ret;
+
+ /* Set up INT polarity */
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
+ return ret;
+ }
+
+ if (data->active_high_intr)
+ ret |= KXCJK1013_REG_INT_REG1_BIT_IEA;
+ else
+ ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEA;
+
+ ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
+ ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kxcjk1013_chip_setup_interrupt(struct kxcjk1013_data *data,
+ bool status)
+{
+ int ret;
+
+ /* This is requirement by spec to change state to STANDBY */
+ ret = kxcjk1013_set_mode(data, STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_CTRL1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
+ return ret;
+ }
+
+ if (status)
+ ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
+ else
+ ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
+
+ ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
+ ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
+ return ret;
+ }
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
+ return ret;
+ }
+
+ if (status)
+ ret |= KXCJK1013_REG_CTRL1_BIT_DRDY;
+ else
+ ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ KXCJK1013_REG_CTRL1, ret);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int kxcjk1013_convert_freq_to_bit(int val, int val2)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
+ if (samp_freq_table[i].val == val &&
+ samp_freq_table[i].val2 == val2) {
+ return samp_freq_table[i].odr_bits;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
+{
+ int ret;
+ int odr_bits;
+
+ odr_bits = kxcjk1013_convert_freq_to_bit(val, val2);
+ if (odr_bits < 0)
+ return odr_bits;
+
+ /* To change ODR, the chip must be set to STANDBY as per spec */
+ ret = kxcjk1013_set_mode(data, STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL,
+ odr_bits);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing data_ctrl\n");
+ return ret;
+ }
+
+ data->odr_bits = odr_bits;
+
+ /* Check, if the ODR is changed after data enable */
+ if (data->power_state) {
+ /* Set the state back to operation */
+ ret = kxcjk1013_set_mode(data, OPERATION);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
+ if (samp_freq_table[i].odr_bits == data->odr_bits) {
+ *val = samp_freq_table[i].val;
+ *val2 = samp_freq_table[i].val2;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis)
+{
+ u8 reg = KXCJK1013_REG_XOUT_L + axis * 2;
+ int ret;
+
+ ret = i2c_smbus_read_word_data(data->client, reg);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "failed to read accel_%c registers\n", 'x' + axis);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(odr_start_up_times); ++i) {
+ if (odr_start_up_times[i].odr_bits == data->odr_bits)
+ return odr_start_up_times[i].usec;
+ }
+
+ return KXCJK1013_MAX_STARTUP_TIME_US;
+}
+
+static int kxcjk1013_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&data->mutex);
+ if (iio_buffer_enabled(indio_dev))
+ ret = -EBUSY;
+ else {
+ int sleep_val;
+
+ ret = kxcjk1013_set_mode(data, OPERATION);
+ if (ret < 0) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+ ++data->power_state;
+ sleep_val = kxcjk1013_get_startup_times(data);
+ if (sleep_val < 20000)
+ usleep_range(sleep_val, 20000);
+ else
+ msleep_interruptible(sleep_val/1000);
+ ret = kxcjk1013_get_acc_reg(data, chan->scan_index);
+ if (--data->power_state == 0)
+ kxcjk1013_set_mode(data, STANDBY);
+ }
+ mutex_unlock(&data->mutex);
+
+ if (ret < 0)
+ return ret;
+
+ *val = sign_extend32(ret >> 4, 11);
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = 19163; /* range +-4g (4/2047*9.806650) */
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ mutex_lock(&data->mutex);
+ ret = kxcjk1013_get_odr(data, val, val2);
+ mutex_unlock(&data->mutex);
+ return ret;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int kxcjk1013_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ mutex_lock(&data->mutex);
+ ret = kxcjk1013_set_odr(data, val, val2);
+ mutex_unlock(&data->mutex);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+ if (data->trig != trig)
+ return -EINVAL;
+
+ return 0;
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
+ "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600");
+
+static struct attribute *kxcjk1013_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group kxcjk1013_attrs_group = {
+ .attrs = kxcjk1013_attributes,
+};
+
+#define KXCJK1013_CHANNEL(_axis) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = AXIS_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .shift = 4, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+static const struct iio_chan_spec kxcjk1013_channels[] = {
+ KXCJK1013_CHANNEL(X),
+ KXCJK1013_CHANNEL(Y),
+ KXCJK1013_CHANNEL(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_info kxcjk1013_info = {
+ .attrs = &kxcjk1013_attrs_group,
+ .read_raw = kxcjk1013_read_raw,
+ .write_raw = kxcjk1013_write_raw,
+ .validate_trigger = kxcjk1013_validate_trigger,
+ .driver_module = THIS_MODULE,
+};
+
+static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+ int bit, ret, i = 0;
+
+ mutex_lock(&data->mutex);
+
+ for_each_set_bit(bit, indio_dev->buffer->scan_mask,
+ indio_dev->masklength) {
+ ret = kxcjk1013_get_acc_reg(data, bit);
+ if (ret < 0) {
+ mutex_unlock(&data->mutex);
+ goto err;
+ }
+ data->buffer[i++] = ret;
+ }
+ mutex_unlock(&data->mutex);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ pf->timestamp);
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int kxcjk1013_trig_try_reen(struct iio_trigger *trig)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_INT_REL);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error reading reg_int_rel\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->mutex);
+ if (state) {
+ kxcjk1013_chip_setup_interrupt(data, true);
+ kxcjk1013_set_mode(data, OPERATION);
+ ++data->power_state;
+ } else {
+ if (--data->power_state) {
+ mutex_unlock(&data->mutex);
+ return 0;
+ }
+ kxcjk1013_chip_setup_interrupt(data, false);
+ kxcjk1013_set_mode(data, STANDBY);
+ }
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
+ .set_trigger_state = kxcjk1013_data_rdy_trigger_set_state,
+ .try_reenable = kxcjk1013_trig_try_reen,
+ .owner = THIS_MODULE,
+};
+
+static int kxcjk1013_acpi_gpio_probe(struct i2c_client *client,
+ struct kxcjk1013_data *data)
+{
+ const struct acpi_device_id *id;
+ struct device *dev;
+ struct gpio_desc *gpio;
+ int ret;
+
+ if (!client)
+ return -EINVAL;
+
+ dev = &client->dev;
+ if (!ACPI_HANDLE(dev))
+ return -ENODEV;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return -ENODEV;
+
+ /* data ready gpio interrupt pin */
+ gpio = devm_gpiod_get_index(dev, "kxcjk1013_int", 0);
+ if (IS_ERR(gpio)) {
+ dev_err(dev, "acpi gpio get index failed\n");
+ return PTR_ERR(gpio);
+ }
+
+ ret = gpiod_direction_input(gpio);
+ if (ret)
+ return ret;
+
+ ret = gpiod_to_irq(gpio);
+
+ dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+ return ret;
+}
+
+static int kxcjk1013_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct kxcjk1013_data *data;
+ struct iio_dev *indio_dev;
+ struct iio_trigger *trig = NULL;
+ struct kxcjk_1013_platform_data *pdata;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ pdata = dev_get_platdata(&client->dev);
+ if (pdata)
+ data->active_high_intr = pdata->active_high_intr;
+ else
+ data->active_high_intr = true; /* default polarity */
+
+ ret = kxcjk1013_chip_init(data);
+ if (ret < 0)
+ return ret;
+
+ mutex_init(&data->mutex);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->channels = kxcjk1013_channels;
+ indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
+ indio_dev->name = KXCJK1013_DRV_NAME;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &kxcjk1013_info;
+
+ if (client->irq < 0)
+ client->irq = kxcjk1013_acpi_gpio_probe(client, data);
+
+ if (client->irq >= 0) {
+ trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+ indio_dev->id);
+ if (!trig)
+ return -ENOMEM;
+
+ data->trig_mode = true;
+
+ ret = devm_request_irq(&client->dev, client->irq,
+ iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ KXCJK1013_IRQ_NAME,
+ trig);
+ if (ret) {
+ dev_err(&client->dev, "unable to request IRQ\n");
+ goto err_trigger_free;
+ }
+
+ trig->dev.parent = &client->dev;
+ trig->ops = &kxcjk1013_trigger_ops;
+ iio_trigger_set_drvdata(trig, indio_dev);
+ data->trig = trig;
+ indio_dev->trig = trig;
+ iio_trigger_get(indio_dev->trig);
+
+ ret = iio_trigger_register(trig);
+ if (ret)
+ goto err_trigger_free;
+
+ ret = iio_triggered_buffer_setup(indio_dev,
+ &iio_pollfunc_store_time,
+ kxcjk1013_trigger_handler,
+ NULL);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "iio triggered buffer setup failed\n");
+ goto err_trigger_unregister;
+ }
+ }
+
+ ret = devm_iio_device_register(&client->dev, indio_dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "unable to register iio device\n");
+ goto err_buffer_cleanup;
+ }
+
+ return 0;
+
+err_buffer_cleanup:
+ if (data->trig_mode)
+ iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+ if (data->trig_mode)
+ iio_trigger_unregister(trig);
+err_trigger_free:
+ if (data->trig_mode)
+ iio_trigger_free(trig);
+
+ return ret;
+}
+
+static int kxcjk1013_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+ if (data->trig_mode) {
+ iio_triggered_buffer_cleanup(indio_dev);
+ iio_trigger_unregister(data->trig);
+ iio_trigger_free(data->trig);
+ }
+
+ mutex_lock(&data->mutex);
+ kxcjk1013_set_mode(data, STANDBY);
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int kxcjk1013_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->mutex);
+ kxcjk1013_set_mode(data, STANDBY);
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+static int kxcjk1013_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+ mutex_lock(&data->mutex);
+
+ if (data->power_state)
+ kxcjk1013_set_mode(data, OPERATION);
+
+ mutex_unlock(&data->mutex);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(kxcjk1013_pm_ops, kxcjk1013_suspend, kxcjk1013_resume);
+#define KXCJK1013_PM_OPS (&kxcjk1013_pm_ops)
+#else
+#define KXCJK1013_PM_OPS NULL
+#endif
+
+static const struct acpi_device_id kx_acpi_match[] = {
+ {"KXCJ1013", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
+
+static const struct i2c_device_id kxcjk1013_id[] = {
+ {"kxcjk1013", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
+
+static struct i2c_driver kxcjk1013_driver = {
+ .driver = {
+ .name = KXCJK1013_DRV_NAME,
+ .acpi_match_table = ACPI_PTR(kx_acpi_match),
+ .pm = KXCJK1013_PM_OPS,
+ },
+ .probe = kxcjk1013_probe,
+ .remove = kxcjk1013_remove,
+ .id_table = kxcjk1013_id,
+};
+module_i2c_driver(kxcjk1013_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("KXCJK1013 accelerometer driver");
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 2a5fa9a436e5..3c12d4966376 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -429,9 +429,15 @@ static const struct i2c_device_id mma8452_id[] = {
};
MODULE_DEVICE_TABLE(i2c, mma8452_id);
+static const struct of_device_id mma8452_dt_ids[] = {
+ { .compatible = "fsl,mma8452" },
+ { }
+};
+
static struct i2c_driver mma8452_driver = {
.driver = {
.name = "mma8452",
+ .of_match_table = of_match_ptr(mma8452_dt_ids),
.pm = MMA8452_PM_OPS,
},
.probe = mma8452_probe,
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index a2abf7c2ce3b..087864854c61 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -393,6 +393,9 @@ static int st_accel_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = adata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = adata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -410,6 +413,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2)
+ return -EINVAL;
+ mutex_lock(&indio_dev->mlock);
+ err = st_sensors_set_odr(indio_dev, val);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
default:
return -EINVAL;
}
@@ -417,14 +427,12 @@ static int st_accel_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
static struct attribute *st_accel_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index d7bedbdfc81d..7164aeff3ab1 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -18,6 +18,55 @@
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_accel.h"
+#ifdef CONFIG_OF
+static const struct of_device_id st_accel_of_match[] = {
+ {
+ .compatible = "st,lsm303dlh-accel",
+ .data = LSM303DLH_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm303dlhc-accel",
+ .data = LSM303DLHC_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lis3dh-accel",
+ .data = LIS3DH_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330d-accel",
+ .data = LSM330D_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330dl-accel",
+ .data = LSM330DL_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330dlc-accel",
+ .data = LSM330DLC_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lis331dlh-accel",
+ .data = LIS331DLH_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm303dl-accel",
+ .data = LSM303DL_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm303dlm-accel",
+ .data = LSM303DLM_ACCEL_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330-accel",
+ .data = LSM330_ACCEL_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_accel_of_match);
+#else
+#define st_accel_of_match NULL
+#endif
+
static int st_accel_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -31,6 +80,7 @@ static int st_accel_i2c_probe(struct i2c_client *client,
adata = iio_priv(indio_dev);
adata->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_accel_of_match);
st_sensors_i2c_configure(indio_dev, client, adata);
@@ -67,6 +117,7 @@ static struct i2c_driver st_accel_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-accel-i2c",
+ .of_match_table = of_match_ptr(st_accel_of_match),
},
.probe = st_accel_i2c_probe,
.remove = st_accel_i2c_remove,
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a80d23628f14..11b048a59fde 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -20,6 +20,16 @@ config AD7266
Say yes here to build support for Analog Devices AD7265 and AD7266
ADCs.
+config AD7291
+ tristate "Analog Devices AD7291 ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for Analog Devices AD7291
+ 8 Channel ADC with temperature sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7291.
+
config AD7298
tristate "Analog Devices AD7298 ADC driver"
depends on SPI
@@ -131,6 +141,15 @@ config LP8788_ADC
help
Say yes here to build support for TI LP8788 ADC.
+config MAX1027
+ tristate "Maxim max1027 ADC driver"
+ depends on SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for Maxim SPI ADC models
+ max1027, max1029 and max1031.
+
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 9d60f2deaaaf..ad81b512aa3d 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7298) += ad7298.o
obj-$(CONFIG_AD7923) += ad7923.o
obj-$(CONFIG_AD7476) += ad7476.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index 7194bd138762..c0eabf156702 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -6,22 +6,22 @@
* Licensed under the GPL-2 or later.
*/
-#include <linux/interrupt.h>
#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
+#include <linux/err.h>
#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
-#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
-#include "ad7291.h"
+#include <linux/platform_data/ad7291.h>
/*
* Simplified handling
@@ -31,7 +31,6 @@
* is in the read mask.
*
* The noise-delayed bit as per datasheet suggestion is always enabled.
- *
*/
/*
@@ -47,33 +46,38 @@
#define AD7291_VOLTAGE_ALERT_STATUS 0x1F
#define AD7291_T_ALERT_STATUS 0x20
+#define AD7291_BITS 12
#define AD7291_VOLTAGE_LIMIT_COUNT 8
/*
* AD7291 command
*/
-#define AD7291_AUTOCYCLE (1 << 0)
-#define AD7291_RESET (1 << 1)
-#define AD7291_ALERT_CLEAR (1 << 2)
-#define AD7291_ALERT_POLARITY (1 << 3)
-#define AD7291_EXT_REF (1 << 4)
-#define AD7291_NOISE_DELAY (1 << 5)
-#define AD7291_T_SENSE_MASK (1 << 7)
-#define AD7291_VOLTAGE_MASK 0xFF00
-#define AD7291_VOLTAGE_OFFSET 0x8
+#define AD7291_AUTOCYCLE BIT(0)
+#define AD7291_RESET BIT(1)
+#define AD7291_ALERT_CLEAR BIT(2)
+#define AD7291_ALERT_POLARITY BIT(3)
+#define AD7291_EXT_REF BIT(4)
+#define AD7291_NOISE_DELAY BIT(5)
+#define AD7291_T_SENSE_MASK BIT(7)
+#define AD7291_VOLTAGE_MASK GENMASK(15, 8)
+#define AD7291_VOLTAGE_OFFSET 8
/*
* AD7291 value masks
*/
-#define AD7291_CHANNEL_MASK 0xF000
-#define AD7291_BITS 12
-#define AD7291_VALUE_MASK 0xFFF
-#define AD7291_T_VALUE_SIGN 0x400
-#define AD7291_T_VALUE_FLOAT_OFFSET 2
-#define AD7291_T_VALUE_FLOAT_MASK 0x2
+#define AD7291_VALUE_MASK GENMASK(11, 0)
+
+/*
+ * AD7291 alert register bits
+ */
+#define AD7291_T_LOW BIT(0)
+#define AD7291_T_HIGH BIT(1)
+#define AD7291_T_AVG_LOW BIT(2)
+#define AD7291_T_AVG_HIGH BIT(3)
+#define AD7291_V_LOW(x) BIT((x) * 2)
+#define AD7291_V_HIGH(x) BIT((x) * 2 + 1)
-#define AD7291_BITS 12
struct ad7291_chip_info {
struct i2c_client *client;
@@ -129,14 +133,14 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
ad7291_i2c_write(chip, AD7291_COMMAND, command);
/* For now treat t_sense and t_sense_average the same */
- if ((t_status & (1 << 0)) || (t_status & (1 << 2)))
+ if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
- if ((t_status & (1 << 1)) || (t_status & (1 << 3)))
+ if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_TEMP,
0,
@@ -144,18 +148,18 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
IIO_EV_DIR_RISING),
timestamp);
- for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) {
- if (v_status & (1 << i))
+ for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
+ if (v_status & AD7291_V_LOW(i))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
- i/2,
+ i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
timestamp);
- if (v_status & (1 << (i + 1)))
+ if (v_status & AD7291_V_HIGH(i))
iio_push_event(indio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
- i/2,
+ i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
timestamp);
@@ -165,7 +169,8 @@ static irqreturn_t ad7291_event_handler(int irq, void *private)
}
static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
- enum iio_event_direction dir, enum iio_event_info info)
+ enum iio_event_direction dir,
+ enum iio_event_info info)
{
unsigned int offset;
@@ -174,7 +179,7 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
offset = chan->channel;
break;
case IIO_TEMP:
- offset = 8;
+ offset = AD7291_VOLTAGE_OFFSET;
break;
default:
return 0;
@@ -182,14 +187,14 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
switch (info) {
case IIO_EV_INFO_VALUE:
- if (dir == IIO_EV_DIR_FALLING)
- return AD7291_DATA_HIGH(offset);
- else
- return AD7291_DATA_LOW(offset);
+ if (dir == IIO_EV_DIR_FALLING)
+ return AD7291_DATA_HIGH(offset);
+ else
+ return AD7291_DATA_LOW(offset);
case IIO_EV_INFO_HYSTERESIS:
- return AD7291_HYST(offset);
+ return AD7291_HYST(offset);
default:
- break;
+ break;
}
return 0;
}
@@ -206,7 +211,7 @@ static int ad7291_read_event_value(struct iio_dev *indio_dev,
u16 uval;
ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
- &uval);
+ &uval);
if (ret < 0)
return ret;
@@ -237,7 +242,7 @@ static int ad7291_write_event_value(struct iio_dev *indio_dev,
}
return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
- val);
+ val);
}
static int ad7291_read_event_config(struct iio_dev *indio_dev,
@@ -246,15 +251,14 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir)
{
struct ad7291_chip_info *chip = iio_priv(indio_dev);
- /* To be enabled the channel must simply be on. If any are enabled
- we are in continuous sampling mode */
+ /*
+ * To be enabled the channel must simply be on. If any are enabled
+ * we are in continuous sampling mode
+ */
switch (chan->type) {
case IIO_VOLTAGE:
- if (chip->c_mask & (1 << (15 - chan->channel)))
- return 1;
- else
- return 0;
+ return !!(chip->c_mask & BIT(15 - chan->channel));
case IIO_TEMP:
/* always on */
return 1;
@@ -336,7 +340,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
/* Enable this channel alone */
regval = chip->command & (~AD7291_VOLTAGE_MASK);
- regval |= 1 << (15 - chan->channel);
+ regval |= BIT(15 - chan->channel);
ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
if (ret < 0) {
mutex_unlock(&chip->state_lock);
@@ -344,7 +348,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
/* Read voltage */
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_VOLTAGE);
+ AD7291_VOLTAGE);
if (ret < 0) {
mutex_unlock(&chip->state_lock);
return ret;
@@ -355,7 +359,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
case IIO_TEMP:
/* Assumes tsense bit of command register always set */
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_T_SENSE);
+ AD7291_T_SENSE);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 11);
@@ -365,7 +369,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
}
case IIO_CHAN_INFO_AVERAGE_RAW:
ret = i2c_smbus_read_word_swapped(chip->client,
- AD7291_T_AVERAGE);
+ AD7291_T_AVERAGE);
if (ret < 0)
return ret;
*val = sign_extend32(ret, 11);
@@ -375,6 +379,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev,
case IIO_VOLTAGE:
if (chip->reg) {
int vref;
+
vref = regulator_get_voltage(chip->reg);
if (vref < 0)
return vref;
@@ -460,7 +465,7 @@ static const struct iio_info ad7291_info = {
};
static int ad7291_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct ad7291_platform_data *pdata = client->dev.platform_data;
struct ad7291_chip_info *chip;
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 2a3b65c74af9..4a8c0a2f49b6 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -25,23 +26,19 @@
#include <linux/platform_data/ad7298.h>
-#define AD7298_WRITE (1 << 15) /* write to the control register */
-#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */
-#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */
-#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */
-#define AD7298_EXTREF (1 << 2) /* external reference enable */
-#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
-#define AD7298_PDD (1 << 0) /* partial power down enable */
+#define AD7298_WRITE BIT(15) /* write to the control register */
+#define AD7298_REPEAT BIT(14) /* repeated conversion enable */
+#define AD7298_CH(x) BIT(13 - (x)) /* channel select */
+#define AD7298_TSENSE BIT(5) /* temperature conversion enable */
+#define AD7298_EXTREF BIT(2) /* external reference enable */
+#define AD7298_TAVG BIT(1) /* temperature sensor averaging enable */
+#define AD7298_PDD BIT(0) /* partial power down enable */
#define AD7298_MAX_CHAN 8
-#define AD7298_BITS 12
-#define AD7298_STORAGE_BITS 16
#define AD7298_INTREF_mV 2500
#define AD7298_CH_TEMP 9
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
struct ad7298_state {
struct spi_device *spi;
struct regulator *reg;
@@ -257,7 +254,7 @@ static int ad7298_read_raw(struct iio_dev *indio_dev,
return ret;
if (chan->address != AD7298_CH_TEMP)
- *val = ret & RES_MASK(AD7298_BITS);
+ *val = ret & GENMASK(chan->scan_type.realbits - 1, 0);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index d141d452c3d1..ce400ec176f1 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -14,6 +14,7 @@
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -21,8 +22,6 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
struct ad7476_state;
struct ad7476_chip_info {
@@ -117,7 +116,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
- RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+ GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (!st->chip_info->int_vref_uv) {
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 749a6cadab8b..2fd012ee99f5 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -25,14 +26,14 @@
#include <linux/platform_data/ad7887.h>
-#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */
-#define AD7887_DUAL (1 << 4) /* dual-channel mode */
-#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */
-#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */
-#define AD7887_PM_MODE1 (0) /* CS based shutdown */
-#define AD7887_PM_MODE2 (1) /* full on */
-#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */
-#define AD7887_PM_MODE4 (3) /* standby mode */
+#define AD7887_REF_DIS BIT(5) /* on-chip reference disable */
+#define AD7887_DUAL BIT(4) /* dual-channel mode */
+#define AD7887_CH_AIN1 BIT(3) /* convert on channel 1, DUAL=1 */
+#define AD7887_CH_AIN0 0 /* convert on channel 0, DUAL=0,1 */
+#define AD7887_PM_MODE1 0 /* CS based shutdown */
+#define AD7887_PM_MODE2 1 /* full on */
+#define AD7887_PM_MODE3 2 /* auto shutdown after conversion */
+#define AD7887_PM_MODE4 3 /* standby mode */
enum ad7887_channels {
AD7887_CH0,
@@ -40,8 +41,6 @@ enum ad7887_channels {
AD7887_CH1,
};
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
/**
* struct ad7887_chip_info - chip specifc information
* @int_vref_mv: the internal reference voltage
@@ -167,7 +166,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
*val = ret >> chan->scan_type.shift;
- *val &= RES_MASK(chan->scan_type.realbits);
+ *val &= GENMASK(chan->scan_type.realbits - 1, 0);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (st->reg) {
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 6eba301ee03d..e37412da15f5 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -32,6 +32,7 @@
#include <linux/types.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -41,7 +42,7 @@
#include <linux/iio/triggered_buffer.h>
#define AD799X_CHANNEL_SHIFT 4
-#define AD799X_STORAGEBITS 16
+
/*
* AD7991, AD7995 and AD7999 defines
*/
@@ -55,10 +56,10 @@
* AD7992, AD7993, AD7994, AD7997 and AD7998 defines
*/
-#define AD7998_FLTR 0x08
-#define AD7998_ALERT_EN 0x04
-#define AD7998_BUSY_ALERT 0x02
-#define AD7998_BUSY_ALERT_POL 0x01
+#define AD7998_FLTR BIT(3)
+#define AD7998_ALERT_EN BIT(2)
+#define AD7998_BUSY_ALERT BIT(1)
+#define AD7998_BUSY_ALERT_POL BIT(0)
#define AD7998_CONV_RES_REG 0x0
#define AD7998_ALERT_STAT_REG 0x1
@@ -69,7 +70,7 @@
#define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5)
#define AD7998_HYST_REG(x) ((x) * 3 + 0x6)
-#define AD7998_CYC_MASK 0x7
+#define AD7998_CYC_MASK GENMASK(2, 0)
#define AD7998_CYC_DIS 0x0
#define AD7998_CYC_TCONF_32 0x1
#define AD7998_CYC_TCONF_64 0x2
@@ -85,10 +86,8 @@
* AD7997 and AD7997 defines
*/
-#define AD7997_8_READ_SINGLE 0x80
-#define AD7997_8_READ_SEQUENCE 0x70
-/* TODO: move this into a common header */
-#define RES_MASK(bits) ((1 << (bits)) - 1)
+#define AD7997_8_READ_SINGLE BIT(7)
+#define AD7997_8_READ_SEQUENCE (BIT(6) | BIT(5) | BIT(4))
enum {
ad7991,
@@ -102,23 +101,32 @@ enum {
};
/**
- * struct ad799x_chip_info - chip specific information
+ * struct ad799x_chip_config - chip specific information
* @channel: channel specification
- * @num_channels: number of channels
- * @monitor_mode: whether the chip supports monitor interrupts
* @default_config: device default configuration
- * @event_attrs: pointer to the monitor event attribute group
+ * @info: pointer to iio_info struct
*/
-struct ad799x_chip_info {
- struct iio_chan_spec channel[9];
- int num_channels;
+struct ad799x_chip_config {
+ const struct iio_chan_spec channel[9];
u16 default_config;
const struct iio_info *info;
};
+/**
+ * struct ad799x_chip_info - chip specific information
+ * @num_channels: number of channels
+ * @noirq_config: device configuration w/o IRQ
+ * @irq_config: device configuration w/IRQ
+ */
+struct ad799x_chip_info {
+ int num_channels;
+ const struct ad799x_chip_config noirq_config;
+ const struct ad799x_chip_config irq_config;
+};
+
struct ad799x_state {
struct i2c_client *client;
- const struct ad799x_chip_info *chip_info;
+ const struct ad799x_chip_config *chip_config;
struct regulator *reg;
struct regulator *vref;
unsigned id;
@@ -128,6 +136,30 @@ struct ad799x_state {
unsigned int transfer_size;
};
+static int ad799x_write_config(struct ad799x_state *st, u16 val)
+{
+ switch (st->id) {
+ case ad7997:
+ case ad7998:
+ return i2c_smbus_write_word_swapped(st->client, AD7998_CONF_REG,
+ val);
+ default:
+ return i2c_smbus_write_byte_data(st->client, AD7998_CONF_REG,
+ val);
+ }
+}
+
+static int ad799x_read_config(struct ad799x_state *st)
+{
+ switch (st->id) {
+ case ad7997:
+ case ad7998:
+ return i2c_smbus_read_word_swapped(st->client, AD7998_CONF_REG);
+ default:
+ return i2c_smbus_read_byte_data(st->client, AD7998_CONF_REG);
+ }
+}
+
/**
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
@@ -176,66 +208,7 @@ out:
return IRQ_HANDLED;
}
-/*
- * ad799x register access by I2C
- */
-static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
-{
- struct i2c_client *client = st->client;
- int ret = 0;
-
- ret = i2c_smbus_read_word_swapped(client, reg);
- if (ret < 0) {
- dev_err(&client->dev, "I2C read error\n");
- return ret;
- }
-
- *data = (u16)ret;
-
- return 0;
-}
-
-static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data)
-{
- struct i2c_client *client = st->client;
- int ret = 0;
-
- ret = i2c_smbus_read_byte_data(client, reg);
- if (ret < 0) {
- dev_err(&client->dev, "I2C read error\n");
- return ret;
- }
-
- *data = (u8)ret;
-
- return 0;
-}
-
-static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
-{
- struct i2c_client *client = st->client;
- int ret = 0;
-
- ret = i2c_smbus_write_word_swapped(client, reg, data);
- if (ret < 0)
- dev_err(&client->dev, "I2C write error\n");
-
- return ret;
-}
-
-static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
-{
- struct i2c_client *client = st->client;
- int ret = 0;
-
- ret = i2c_smbus_write_byte_data(client, reg, data);
- if (ret < 0)
- dev_err(&client->dev, "I2C write error\n");
-
- return ret;
-}
-
-static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
+static int ad799x_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct ad799x_state *st = iio_priv(indio_dev);
@@ -248,33 +221,33 @@ static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2;
switch (st->id) {
+ case ad7992:
+ case ad7993:
+ case ad7994:
case ad7997:
case ad7998:
- return ad799x_i2c_write16(st, AD7998_CONF_REG,
- st->config | (*scan_mask << AD799X_CHANNEL_SHIFT));
+ st->config &= ~(GENMASK(7, 0) << AD799X_CHANNEL_SHIFT);
+ st->config |= (*scan_mask << AD799X_CHANNEL_SHIFT);
+ return ad799x_write_config(st, st->config);
default:
- break;
+ return 0;
}
-
- return 0;
}
static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
{
- u16 rxbuf;
u8 cmd;
- int ret;
switch (st->id) {
case ad7991:
case ad7995:
case ad7999:
- cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT);
+ cmd = st->config | (BIT(ch) << AD799X_CHANNEL_SHIFT);
break;
case ad7992:
case ad7993:
case ad7994:
- cmd = (1 << ch) << AD799X_CHANNEL_SHIFT;
+ cmd = BIT(ch) << AD799X_CHANNEL_SHIFT;
break;
case ad7997:
case ad7998:
@@ -284,11 +257,7 @@ static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
return -EINVAL;
}
- ret = ad799x_i2c_read16(st, cmd, &rxbuf);
- if (ret < 0)
- return ret;
-
- return rxbuf;
+ return i2c_smbus_read_word_swapped(st->client, cmd);
}
static int ad799x_read_raw(struct iio_dev *indio_dev,
@@ -312,7 +281,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
*val = (ret >> chan->scan_type.shift) &
- RES_MASK(chan->scan_type.realbits);
+ GENMASK(chan->scan_type.realbits - 1, 0);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(st->vref);
@@ -333,6 +302,7 @@ static const unsigned int ad7998_frequencies[] = {
[AD7998_CYC_TCONF_1024] = 488,
[AD7998_CYC_TCONF_2048] = 244,
};
+
static ssize_t ad799x_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -340,15 +310,11 @@ static ssize_t ad799x_read_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad799x_state *st = iio_priv(indio_dev);
- int ret;
- u8 val;
- ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val);
- if (ret)
+ int ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG);
+ if (ret < 0)
return ret;
- val &= AD7998_CYC_MASK;
-
- return sprintf(buf, "%u\n", ad7998_frequencies[val]);
+ return sprintf(buf, "%u\n", ad7998_frequencies[ret & AD7998_CYC_MASK]);
}
static ssize_t ad799x_write_frequency(struct device *dev,
@@ -361,18 +327,17 @@ static ssize_t ad799x_write_frequency(struct device *dev,
long val;
int ret, i;
- u8 t;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
- ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t);
- if (ret)
+ ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG);
+ if (ret < 0)
goto error_ret_mutex;
/* Wipe the bits clean */
- t &= ~AD7998_CYC_MASK;
+ ret &= ~AD7998_CYC_MASK;
for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++)
if (val == ad7998_frequencies[i])
@@ -381,13 +346,17 @@ static ssize_t ad799x_write_frequency(struct device *dev,
ret = -EINVAL;
goto error_ret_mutex;
}
- t |= i;
- ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t);
+
+ ret = i2c_smbus_write_byte_data(st->client, AD7998_CYCLE_TMR_REG,
+ ret | i);
+ if (ret < 0)
+ goto error_ret_mutex;
+ ret = len;
error_ret_mutex:
mutex_unlock(&indio_dev->mlock);
- return ret ? ret : len;
+ return ret;
}
static int ad799x_read_event_config(struct iio_dev *indio_dev,
@@ -395,7 +364,48 @@ static int ad799x_read_event_config(struct iio_dev *indio_dev,
enum iio_event_type type,
enum iio_event_direction dir)
{
- return 1;
+ struct ad799x_state *st = iio_priv(indio_dev);
+
+ if (!(st->config & AD7998_ALERT_EN))
+ return 0;
+
+ if ((st->config >> AD799X_CHANNEL_SHIFT) & BIT(chan->scan_index))
+ return 1;
+
+ return 0;
+}
+
+static int ad799x_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ int state)
+{
+ struct ad799x_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&indio_dev->mlock);
+ if (iio_buffer_enabled(indio_dev)) {
+ ret = -EBUSY;
+ goto done;
+ }
+
+ if (state)
+ st->config |= BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT;
+ else
+ st->config &= ~(BIT(chan->scan_index) << AD799X_CHANNEL_SHIFT);
+
+ if (st->config >> AD799X_CHANNEL_SHIFT)
+ st->config |= AD7998_ALERT_EN;
+ else
+ st->config &= ~AD7998_ALERT_EN;
+
+ ret = ad799x_write_config(st, st->config);
+
+done:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
}
static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan,
@@ -427,11 +437,12 @@ static int ad799x_write_event_value(struct iio_dev *indio_dev,
int ret;
struct ad799x_state *st = iio_priv(indio_dev);
- if (val < 0 || val > RES_MASK(chan->scan_type.realbits))
+ if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0))
return -EINVAL;
mutex_lock(&indio_dev->mlock);
- ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info),
+ ret = i2c_smbus_write_word_swapped(st->client,
+ ad799x_threshold_reg(chan, dir, info),
val << chan->scan_type.shift);
mutex_unlock(&indio_dev->mlock);
@@ -447,16 +458,15 @@ static int ad799x_read_event_value(struct iio_dev *indio_dev,
{
int ret;
struct ad799x_state *st = iio_priv(indio_dev);
- u16 valin;
mutex_lock(&indio_dev->mlock);
- ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info),
- &valin);
+ ret = i2c_smbus_read_word_swapped(st->client,
+ ad799x_threshold_reg(chan, dir, info));
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
- *val = (valin >> chan->scan_type.shift) &
- RES_MASK(chan->scan_type.realbits);
+ *val = (ret >> chan->scan_type.shift) &
+ GENMASK(chan->scan_type.realbits - 1 , 0);
return IIO_VAL_INT;
}
@@ -465,20 +475,18 @@ static irqreturn_t ad799x_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct ad799x_state *st = iio_priv(private);
- u8 status;
int i, ret;
- ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status);
- if (ret)
+ ret = i2c_smbus_read_byte_data(st->client, AD7998_ALERT_STAT_REG);
+ if (ret <= 0)
goto done;
- if (!status)
+ if (i2c_smbus_write_byte_data(st->client, AD7998_ALERT_STAT_REG,
+ AD7998_ALERT_STAT_CLEAR) < 0)
goto done;
- ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR);
-
for (i = 0; i < 8; i++) {
- if (status & (1 << i))
+ if (ret & BIT(i))
iio_push_event(indio_dev,
i & 0x1 ?
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
@@ -517,14 +525,21 @@ static const struct iio_info ad7991_info = {
.driver_module = THIS_MODULE,
};
-static const struct iio_info ad7993_4_7_8_info = {
+static const struct iio_info ad7993_4_7_8_noirq_info = {
+ .read_raw = &ad799x_read_raw,
+ .driver_module = THIS_MODULE,
+ .update_scan_mode = ad799x_update_scan_mode,
+};
+
+static const struct iio_info ad7993_4_7_8_irq_info = {
.read_raw = &ad799x_read_raw,
.event_attrs = &ad799x_event_attrs_group,
.read_event_config = &ad799x_read_event_config,
+ .write_event_config = &ad799x_write_event_config,
.read_event_value = &ad799x_read_event_value,
.write_event_value = &ad799x_write_event_value,
.driver_module = THIS_MODULE,
- .update_scan_mode = ad7997_8_update_scan_mode,
+ .update_scan_mode = ad799x_update_scan_mode,
};
static const struct iio_event_spec ad799x_events[] = {
@@ -572,103 +587,175 @@ static const struct iio_event_spec ad799x_events[] = {
static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
[ad7991] = {
- .channel = {
- AD799X_CHANNEL(0, 12),
- AD799X_CHANNEL(1, 12),
- AD799X_CHANNEL(2, 12),
- AD799X_CHANNEL(3, 12),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- },
.num_channels = 5,
- .info = &ad7991_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 12),
+ AD799X_CHANNEL(1, 12),
+ AD799X_CHANNEL(2, 12),
+ AD799X_CHANNEL(3, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .info = &ad7991_info,
+ },
},
[ad7995] = {
- .channel = {
- AD799X_CHANNEL(0, 10),
- AD799X_CHANNEL(1, 10),
- AD799X_CHANNEL(2, 10),
- AD799X_CHANNEL(3, 10),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- },
.num_channels = 5,
- .info = &ad7991_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 10),
+ AD799X_CHANNEL(1, 10),
+ AD799X_CHANNEL(2, 10),
+ AD799X_CHANNEL(3, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .info = &ad7991_info,
+ },
},
[ad7999] = {
- .channel = {
- AD799X_CHANNEL(0, 8),
- AD799X_CHANNEL(1, 8),
- AD799X_CHANNEL(2, 8),
- AD799X_CHANNEL(3, 8),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- },
.num_channels = 5,
- .info = &ad7991_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 8),
+ AD799X_CHANNEL(1, 8),
+ AD799X_CHANNEL(2, 8),
+ AD799X_CHANNEL(3, 8),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .info = &ad7991_info,
+ },
},
[ad7992] = {
- .channel = {
- AD799X_CHANNEL_WITH_EVENTS(0, 12),
- AD799X_CHANNEL_WITH_EVENTS(1, 12),
- IIO_CHAN_SOFT_TIMESTAMP(3),
- },
.num_channels = 3,
- .default_config = AD7998_ALERT_EN,
- .info = &ad7993_4_7_8_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 12),
+ AD799X_CHANNEL(1, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+ },
+ .info = &ad7993_4_7_8_noirq_info,
+ },
+ .irq_config = {
+ .channel = {
+ AD799X_CHANNEL_WITH_EVENTS(0, 12),
+ AD799X_CHANNEL_WITH_EVENTS(1, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+ },
+ .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+ .info = &ad7993_4_7_8_irq_info,
+ },
},
[ad7993] = {
- .channel = {
- AD799X_CHANNEL_WITH_EVENTS(0, 10),
- AD799X_CHANNEL_WITH_EVENTS(1, 10),
- AD799X_CHANNEL_WITH_EVENTS(2, 10),
- AD799X_CHANNEL_WITH_EVENTS(3, 10),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- },
.num_channels = 5,
- .default_config = AD7998_ALERT_EN,
- .info = &ad7993_4_7_8_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 10),
+ AD799X_CHANNEL(1, 10),
+ AD799X_CHANNEL(2, 10),
+ AD799X_CHANNEL(3, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .info = &ad7993_4_7_8_noirq_info,
+ },
+ .irq_config = {
+ .channel = {
+ AD799X_CHANNEL_WITH_EVENTS(0, 10),
+ AD799X_CHANNEL_WITH_EVENTS(1, 10),
+ AD799X_CHANNEL_WITH_EVENTS(2, 10),
+ AD799X_CHANNEL_WITH_EVENTS(3, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+ .info = &ad7993_4_7_8_irq_info,
+ },
},
[ad7994] = {
- .channel = {
- AD799X_CHANNEL_WITH_EVENTS(0, 12),
- AD799X_CHANNEL_WITH_EVENTS(1, 12),
- AD799X_CHANNEL_WITH_EVENTS(2, 12),
- AD799X_CHANNEL_WITH_EVENTS(3, 12),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- },
.num_channels = 5,
- .default_config = AD7998_ALERT_EN,
- .info = &ad7993_4_7_8_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 12),
+ AD799X_CHANNEL(1, 12),
+ AD799X_CHANNEL(2, 12),
+ AD799X_CHANNEL(3, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .info = &ad7993_4_7_8_noirq_info,
+ },
+ .irq_config = {
+ .channel = {
+ AD799X_CHANNEL_WITH_EVENTS(0, 12),
+ AD799X_CHANNEL_WITH_EVENTS(1, 12),
+ AD799X_CHANNEL_WITH_EVENTS(2, 12),
+ AD799X_CHANNEL_WITH_EVENTS(3, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ },
+ .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+ .info = &ad7993_4_7_8_irq_info,
+ },
},
[ad7997] = {
- .channel = {
- AD799X_CHANNEL_WITH_EVENTS(0, 10),
- AD799X_CHANNEL_WITH_EVENTS(1, 10),
- AD799X_CHANNEL_WITH_EVENTS(2, 10),
- AD799X_CHANNEL_WITH_EVENTS(3, 10),
- AD799X_CHANNEL(4, 10),
- AD799X_CHANNEL(5, 10),
- AD799X_CHANNEL(6, 10),
- AD799X_CHANNEL(7, 10),
- IIO_CHAN_SOFT_TIMESTAMP(8),
- },
.num_channels = 9,
- .default_config = AD7998_ALERT_EN,
- .info = &ad7993_4_7_8_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 10),
+ AD799X_CHANNEL(1, 10),
+ AD799X_CHANNEL(2, 10),
+ AD799X_CHANNEL(3, 10),
+ AD799X_CHANNEL(4, 10),
+ AD799X_CHANNEL(5, 10),
+ AD799X_CHANNEL(6, 10),
+ AD799X_CHANNEL(7, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ },
+ .info = &ad7993_4_7_8_noirq_info,
+ },
+ .irq_config = {
+ .channel = {
+ AD799X_CHANNEL_WITH_EVENTS(0, 10),
+ AD799X_CHANNEL_WITH_EVENTS(1, 10),
+ AD799X_CHANNEL_WITH_EVENTS(2, 10),
+ AD799X_CHANNEL_WITH_EVENTS(3, 10),
+ AD799X_CHANNEL(4, 10),
+ AD799X_CHANNEL(5, 10),
+ AD799X_CHANNEL(6, 10),
+ AD799X_CHANNEL(7, 10),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ },
+ .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+ .info = &ad7993_4_7_8_irq_info,
+ },
},
[ad7998] = {
- .channel = {
- AD799X_CHANNEL_WITH_EVENTS(0, 12),
- AD799X_CHANNEL_WITH_EVENTS(1, 12),
- AD799X_CHANNEL_WITH_EVENTS(2, 12),
- AD799X_CHANNEL_WITH_EVENTS(3, 12),
- AD799X_CHANNEL(4, 12),
- AD799X_CHANNEL(5, 12),
- AD799X_CHANNEL(6, 12),
- AD799X_CHANNEL(7, 12),
- IIO_CHAN_SOFT_TIMESTAMP(8),
- },
.num_channels = 9,
- .default_config = AD7998_ALERT_EN,
- .info = &ad7993_4_7_8_info,
+ .noirq_config = {
+ .channel = {
+ AD799X_CHANNEL(0, 12),
+ AD799X_CHANNEL(1, 12),
+ AD799X_CHANNEL(2, 12),
+ AD799X_CHANNEL(3, 12),
+ AD799X_CHANNEL(4, 12),
+ AD799X_CHANNEL(5, 12),
+ AD799X_CHANNEL(6, 12),
+ AD799X_CHANNEL(7, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ },
+ .info = &ad7993_4_7_8_noirq_info,
+ },
+ .irq_config = {
+ .channel = {
+ AD799X_CHANNEL_WITH_EVENTS(0, 12),
+ AD799X_CHANNEL_WITH_EVENTS(1, 12),
+ AD799X_CHANNEL_WITH_EVENTS(2, 12),
+ AD799X_CHANNEL_WITH_EVENTS(3, 12),
+ AD799X_CHANNEL(4, 12),
+ AD799X_CHANNEL(5, 12),
+ AD799X_CHANNEL(6, 12),
+ AD799X_CHANNEL(7, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ },
+ .default_config = AD7998_ALERT_EN | AD7998_BUSY_ALERT,
+ .info = &ad7993_4_7_8_irq_info,
+ },
},
};
@@ -678,6 +765,8 @@ static int ad799x_probe(struct i2c_client *client,
int ret;
struct ad799x_state *st;
struct iio_dev *indio_dev;
+ const struct ad799x_chip_info *chip_info =
+ &ad799x_chip_info_tbl[id->driver_data];
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (indio_dev == NULL)
@@ -688,8 +777,10 @@ static int ad799x_probe(struct i2c_client *client,
i2c_set_clientdata(client, indio_dev);
st->id = id->driver_data;
- st->chip_info = &ad799x_chip_info_tbl[st->id];
- st->config = st->chip_info->default_config;
+ if (client->irq > 0 && chip_info->irq_config.info)
+ st->chip_config = &chip_info->irq_config;
+ else
+ st->chip_config = &chip_info->noirq_config;
/* TODO: Add pdata options for filtering and bit delay */
@@ -712,11 +803,19 @@ static int ad799x_probe(struct i2c_client *client,
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
- indio_dev->info = st->chip_info->info;
+ indio_dev->info = st->chip_config->info;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = st->chip_info->channel;
- indio_dev->num_channels = st->chip_info->num_channels;
+ indio_dev->channels = st->chip_config->channel;
+ indio_dev->num_channels = chip_info->num_channels;
+
+ ret = ad799x_write_config(st, st->chip_config->default_config);
+ if (ret < 0)
+ goto error_disable_reg;
+ ret = ad799x_read_config(st);
+ if (ret < 0)
+ goto error_disable_reg;
+ st->config = ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad799x_trigger_handler, NULL);
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 9a4e0e32a771..c55b81f7f970 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -410,7 +410,7 @@ static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
complete(&sigma_delta->completion);
disable_irq_nosync(irq);
sigma_delta->irq_dis = true;
- iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
+ iio_trigger_poll(sigma_delta->trig);
return IRQ_HANDLED;
}
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 2b6a9ce9927c..772e869c280e 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -272,7 +272,7 @@ void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
if (iio_buffer_enabled(idev)) {
disable_irq_nosync(irq);
- iio_trigger_poll(idev->trig, iio_get_time_ns());
+ iio_trigger_poll(idev->trig);
} else {
st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
st->done = true;
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 010578f1d762..fc9dfc23ecb7 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/io.h>
@@ -39,11 +40,6 @@
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
-enum adc_version {
- ADC_V1,
- ADC_V2
-};
-
/* EXYNOS4412/5250 ADC_V1 registers definitions */
#define ADC_V1_CON(x) ((x) + 0x00)
#define ADC_V1_DLY(x) ((x) + 0x08)
@@ -75,8 +71,9 @@ enum adc_version {
#define ADC_V2_CON2_ACH_SEL(x) (((x) & 0xF) << 0)
#define ADC_V2_CON2_ACH_MASK 0xF
-#define MAX_ADC_V2_CHANNELS 10
-#define MAX_ADC_V1_CHANNELS 8
+#define MAX_ADC_V2_CHANNELS 10
+#define MAX_ADC_V1_CHANNELS 8
+#define MAX_EXYNOS3250_ADC_CHANNELS 2
/* Bit definitions common for ADC_V1 and ADC_V2 */
#define ADC_CON_EN_START (1u << 0)
@@ -85,9 +82,12 @@ enum adc_version {
#define EXYNOS_ADC_TIMEOUT (msecs_to_jiffies(100))
struct exynos_adc {
+ struct exynos_adc_data *data;
+ struct device *dev;
void __iomem *regs;
void __iomem *enable_reg;
struct clk *clk;
+ struct clk *sclk;
unsigned int irq;
struct regulator *vdd;
@@ -97,43 +97,213 @@ struct exynos_adc {
unsigned int version;
};
-static const struct of_device_id exynos_adc_match[] = {
- { .compatible = "samsung,exynos-adc-v1", .data = (void *)ADC_V1 },
- { .compatible = "samsung,exynos-adc-v2", .data = (void *)ADC_V2 },
- {},
+struct exynos_adc_data {
+ int num_channels;
+ bool needs_sclk;
+
+ void (*init_hw)(struct exynos_adc *info);
+ void (*exit_hw)(struct exynos_adc *info);
+ void (*clear_irq)(struct exynos_adc *info);
+ void (*start_conv)(struct exynos_adc *info, unsigned long addr);
};
-MODULE_DEVICE_TABLE(of, exynos_adc_match);
-static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
+static void exynos_adc_unprepare_clk(struct exynos_adc *info)
{
- const struct of_device_id *match;
+ if (info->data->needs_sclk)
+ clk_unprepare(info->sclk);
+ clk_unprepare(info->clk);
+}
- match = of_match_node(exynos_adc_match, pdev->dev.of_node);
- return (unsigned int)match->data;
+static int exynos_adc_prepare_clk(struct exynos_adc *info)
+{
+ int ret;
+
+ ret = clk_prepare(info->clk);
+ if (ret) {
+ dev_err(info->dev, "failed preparing adc clock: %d\n", ret);
+ return ret;
+ }
+
+ if (info->data->needs_sclk) {
+ ret = clk_prepare(info->sclk);
+ if (ret) {
+ clk_unprepare(info->clk);
+ dev_err(info->dev,
+ "failed preparing sclk_adc clock: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void exynos_adc_disable_clk(struct exynos_adc *info)
+{
+ if (info->data->needs_sclk)
+ clk_disable(info->sclk);
+ clk_disable(info->clk);
+}
+
+static int exynos_adc_enable_clk(struct exynos_adc *info)
+{
+ int ret;
+
+ ret = clk_enable(info->clk);
+ if (ret) {
+ dev_err(info->dev, "failed enabling adc clock: %d\n", ret);
+ return ret;
+ }
+
+ if (info->data->needs_sclk) {
+ ret = clk_enable(info->sclk);
+ if (ret) {
+ clk_disable(info->clk);
+ dev_err(info->dev,
+ "failed enabling sclk_adc clock: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void exynos_adc_v1_init_hw(struct exynos_adc *info)
+{
+ u32 con1;
+
+ writel(1, info->enable_reg);
+
+ /* set default prescaler values and Enable prescaler */
+ con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+ /* Enable 12-bit ADC resolution */
+ con1 |= ADC_V1_CON_RES;
+ writel(con1, ADC_V1_CON(info->regs));
+}
+
+static void exynos_adc_v1_exit_hw(struct exynos_adc *info)
+{
+ u32 con;
+
+ writel(0, info->enable_reg);
+
+ con = readl(ADC_V1_CON(info->regs));
+ con |= ADC_V1_CON_STANDBY;
+ writel(con, ADC_V1_CON(info->regs));
+}
+
+static void exynos_adc_v1_clear_irq(struct exynos_adc *info)
+{
+ writel(1, ADC_V1_INTCLR(info->regs));
+}
+
+static void exynos_adc_v1_start_conv(struct exynos_adc *info,
+ unsigned long addr)
+{
+ u32 con1;
+
+ writel(addr, ADC_V1_MUX(info->regs));
+
+ con1 = readl(ADC_V1_CON(info->regs));
+ writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));
+}
+
+static const struct exynos_adc_data exynos_adc_v1_data = {
+ .num_channels = MAX_ADC_V1_CHANNELS,
+
+ .init_hw = exynos_adc_v1_init_hw,
+ .exit_hw = exynos_adc_v1_exit_hw,
+ .clear_irq = exynos_adc_v1_clear_irq,
+ .start_conv = exynos_adc_v1_start_conv,
+};
+
+static void exynos_adc_v2_init_hw(struct exynos_adc *info)
+{
+ u32 con1, con2;
+
+ writel(1, info->enable_reg);
+
+ con1 = ADC_V2_CON1_SOFT_RESET;
+ writel(con1, ADC_V2_CON1(info->regs));
+
+ con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+ ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+ writel(con2, ADC_V2_CON2(info->regs));
+
+ /* Enable interrupts */
+ writel(1, ADC_V2_INT_EN(info->regs));
+}
+
+static void exynos_adc_v2_exit_hw(struct exynos_adc *info)
+{
+ u32 con;
+
+ writel(0, info->enable_reg);
+
+ con = readl(ADC_V2_CON1(info->regs));
+ con &= ~ADC_CON_EN_START;
+ writel(con, ADC_V2_CON1(info->regs));
}
-static void exynos_adc_hw_init(struct exynos_adc *info)
+static void exynos_adc_v2_clear_irq(struct exynos_adc *info)
+{
+ writel(1, ADC_V2_INT_ST(info->regs));
+}
+
+static void exynos_adc_v2_start_conv(struct exynos_adc *info,
+ unsigned long addr)
{
u32 con1, con2;
- if (info->version == ADC_V2) {
- con1 = ADC_V2_CON1_SOFT_RESET;
- writel(con1, ADC_V2_CON1(info->regs));
+ con2 = readl(ADC_V2_CON2(info->regs));
+ con2 &= ~ADC_V2_CON2_ACH_MASK;
+ con2 |= ADC_V2_CON2_ACH_SEL(addr);
+ writel(con2, ADC_V2_CON2(info->regs));
- con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
- ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
- writel(con2, ADC_V2_CON2(info->regs));
+ con1 = readl(ADC_V2_CON1(info->regs));
+ writel(con1 | ADC_CON_EN_START, ADC_V2_CON1(info->regs));
+}
- /* Enable interrupts */
- writel(1, ADC_V2_INT_EN(info->regs));
- } else {
- /* set default prescaler values and Enable prescaler */
- con1 = ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+static const struct exynos_adc_data exynos_adc_v2_data = {
+ .num_channels = MAX_ADC_V2_CHANNELS,
- /* Enable 12-bit ADC resolution */
- con1 |= ADC_V1_CON_RES;
- writel(con1, ADC_V1_CON(info->regs));
- }
+ .init_hw = exynos_adc_v2_init_hw,
+ .exit_hw = exynos_adc_v2_exit_hw,
+ .clear_irq = exynos_adc_v2_clear_irq,
+ .start_conv = exynos_adc_v2_start_conv,
+};
+
+static const struct exynos_adc_data exynos3250_adc_data = {
+ .num_channels = MAX_EXYNOS3250_ADC_CHANNELS,
+ .needs_sclk = true,
+
+ .init_hw = exynos_adc_v2_init_hw,
+ .exit_hw = exynos_adc_v2_exit_hw,
+ .clear_irq = exynos_adc_v2_clear_irq,
+ .start_conv = exynos_adc_v2_start_conv,
+};
+
+static const struct of_device_id exynos_adc_match[] = {
+ {
+ .compatible = "samsung,exynos-adc-v1",
+ .data = &exynos_adc_v1_data,
+ }, {
+ .compatible = "samsung,exynos-adc-v2",
+ .data = &exynos_adc_v2_data,
+ }, {
+ .compatible = "samsung,exynos3250-adc",
+ .data = &exynos3250_adc_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_adc_match);
+
+static struct exynos_adc_data *exynos_adc_get_data(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+
+ match = of_match_node(exynos_adc_match, pdev->dev.of_node);
+ return (struct exynos_adc_data *)match->data;
}
static int exynos_read_raw(struct iio_dev *indio_dev,
@@ -144,7 +314,6 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
{
struct exynos_adc *info = iio_priv(indio_dev);
unsigned long timeout;
- u32 con1, con2;
int ret;
if (mask != IIO_CHAN_INFO_RAW)
@@ -154,28 +323,15 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
reinit_completion(&info->completion);
/* Select the channel to be used and Trigger conversion */
- if (info->version == ADC_V2) {
- con2 = readl(ADC_V2_CON2(info->regs));
- con2 &= ~ADC_V2_CON2_ACH_MASK;
- con2 |= ADC_V2_CON2_ACH_SEL(chan->address);
- writel(con2, ADC_V2_CON2(info->regs));
-
- con1 = readl(ADC_V2_CON1(info->regs));
- writel(con1 | ADC_CON_EN_START,
- ADC_V2_CON1(info->regs));
- } else {
- writel(chan->address, ADC_V1_MUX(info->regs));
-
- con1 = readl(ADC_V1_CON(info->regs));
- writel(con1 | ADC_CON_EN_START,
- ADC_V1_CON(info->regs));
- }
+ if (info->data->start_conv)
+ info->data->start_conv(info, chan->address);
timeout = wait_for_completion_timeout
(&info->completion, EXYNOS_ADC_TIMEOUT);
if (timeout == 0) {
dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
- exynos_adc_hw_init(info);
+ if (info->data->init_hw)
+ info->data->init_hw(info);
ret = -ETIMEDOUT;
} else {
*val = info->value;
@@ -193,13 +349,11 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
struct exynos_adc *info = (struct exynos_adc *)dev_id;
/* Read value */
- info->value = readl(ADC_V1_DATX(info->regs)) &
- ADC_DATX_MASK;
+ info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
+
/* clear irq */
- if (info->version == ADC_V2)
- writel(1, ADC_V2_INT_ST(info->regs));
- else
- writel(1, ADC_V1_INTCLR(info->regs));
+ if (info->data->clear_irq)
+ info->data->clear_irq(info);
complete(&info->completion);
@@ -277,6 +431,12 @@ static int exynos_adc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev);
+ info->data = exynos_adc_get_data(pdev);
+ if (!info->data) {
+ dev_err(&pdev->dev, "failed getting exynos_adc_data\n");
+ return -EINVAL;
+ }
+
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->regs))
@@ -294,6 +454,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
}
info->irq = irq;
+ info->dev = &pdev->dev;
init_completion(&info->completion);
@@ -304,6 +465,16 @@ static int exynos_adc_probe(struct platform_device *pdev)
return PTR_ERR(info->clk);
}
+ if (info->data->needs_sclk) {
+ info->sclk = devm_clk_get(&pdev->dev, "sclk");
+ if (IS_ERR(info->sclk)) {
+ dev_err(&pdev->dev,
+ "failed getting sclk clock, err = %ld\n",
+ PTR_ERR(info->sclk));
+ return PTR_ERR(info->sclk);
+ }
+ }
+
info->vdd = devm_regulator_get(&pdev->dev, "vdd");
if (IS_ERR(info->vdd)) {
dev_err(&pdev->dev, "failed getting regulator, err = %ld\n",
@@ -315,13 +486,13 @@ static int exynos_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = clk_prepare_enable(info->clk);
+ ret = exynos_adc_prepare_clk(info);
if (ret)
goto err_disable_reg;
- writel(1, info->enable_reg);
-
- info->version = exynos_adc_get_version(pdev);
+ ret = exynos_adc_enable_clk(info);
+ if (ret)
+ goto err_unprepare_clk;
platform_set_drvdata(pdev, indio_dev);
@@ -331,11 +502,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
indio_dev->info = &exynos_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = exynos_adc_iio_channels;
-
- if (info->version == ADC_V1)
- indio_dev->num_channels = MAX_ADC_V1_CHANNELS;
- else
- indio_dev->num_channels = MAX_ADC_V2_CHANNELS;
+ indio_dev->num_channels = info->data->num_channels;
ret = request_irq(info->irq, exynos_adc_isr,
0, dev_name(&pdev->dev), info);
@@ -349,7 +516,8 @@ static int exynos_adc_probe(struct platform_device *pdev)
if (ret)
goto err_irq;
- exynos_adc_hw_init(info);
+ if (info->data->init_hw)
+ info->data->init_hw(info);
ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
if (ret < 0) {
@@ -366,8 +534,11 @@ err_of_populate:
err_irq:
free_irq(info->irq, info);
err_disable_clk:
- writel(0, info->enable_reg);
- clk_disable_unprepare(info->clk);
+ if (info->data->exit_hw)
+ info->data->exit_hw(info);
+ exynos_adc_disable_clk(info);
+err_unprepare_clk:
+ exynos_adc_unprepare_clk(info);
err_disable_reg:
regulator_disable(info->vdd);
return ret;
@@ -382,8 +553,10 @@ static int exynos_adc_remove(struct platform_device *pdev)
exynos_adc_remove_devices);
iio_device_unregister(indio_dev);
free_irq(info->irq, info);
- writel(0, info->enable_reg);
- clk_disable_unprepare(info->clk);
+ if (info->data->exit_hw)
+ info->data->exit_hw(info);
+ exynos_adc_disable_clk(info);
+ exynos_adc_unprepare_clk(info);
regulator_disable(info->vdd);
return 0;
@@ -394,20 +567,10 @@ static int exynos_adc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct exynos_adc *info = iio_priv(indio_dev);
- u32 con;
- if (info->version == ADC_V2) {
- con = readl(ADC_V2_CON1(info->regs));
- con &= ~ADC_CON_EN_START;
- writel(con, ADC_V2_CON1(info->regs));
- } else {
- con = readl(ADC_V1_CON(info->regs));
- con |= ADC_V1_CON_STANDBY;
- writel(con, ADC_V1_CON(info->regs));
- }
-
- writel(0, info->enable_reg);
- clk_disable_unprepare(info->clk);
+ if (info->data->exit_hw)
+ info->data->exit_hw(info);
+ exynos_adc_disable_clk(info);
regulator_disable(info->vdd);
return 0;
@@ -423,12 +586,12 @@ static int exynos_adc_resume(struct device *dev)
if (ret)
return ret;
- ret = clk_prepare_enable(info->clk);
+ ret = exynos_adc_enable_clk(info);
if (ret)
return ret;
- writel(1, info->enable_reg);
- exynos_adc_hw_init(info);
+ if (info->data->init_hw)
+ info->data->init_hw(info);
return 0;
}
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
new file mode 100644
index 000000000000..87ee1c7d0b54
--- /dev/null
+++ b/drivers/iio/adc/max1027.c
@@ -0,0 +1,521 @@
+ /*
+ * iio/adc/max1027.c
+ * Copyright (C) 2014 Philippe Reynes
+ *
+ * based on linux/drivers/iio/ad7923.c
+ * Copyright 2011 Analog Devices Inc (from AD7923 Driver)
+ * Copyright 2012 CS Systemes d'Information
+ *
+ * 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.
+ *
+ * max1027.c
+ *
+ * Partial support for max1027 and similar chips.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define MAX1027_CONV_REG BIT(7)
+#define MAX1027_SETUP_REG BIT(6)
+#define MAX1027_AVG_REG BIT(5)
+#define MAX1027_RST_REG BIT(4)
+
+/* conversion register */
+#define MAX1027_TEMP BIT(0)
+#define MAX1027_SCAN_0_N (0x00 << 1)
+#define MAX1027_SCAN_N_M (0x01 << 1)
+#define MAX1027_SCAN_N (0x02 << 1)
+#define MAX1027_NOSCAN (0x03 << 1)
+#define MAX1027_CHAN(n) ((n) << 3)
+
+/* setup register */
+#define MAX1027_UNIPOLAR 0x02
+#define MAX1027_BIPOLAR 0x03
+#define MAX1027_REF_MODE0 (0x00 << 2)
+#define MAX1027_REF_MODE1 (0x01 << 2)
+#define MAX1027_REF_MODE2 (0x02 << 2)
+#define MAX1027_REF_MODE3 (0x03 << 2)
+#define MAX1027_CKS_MODE0 (0x00 << 4)
+#define MAX1027_CKS_MODE1 (0x01 << 4)
+#define MAX1027_CKS_MODE2 (0x02 << 4)
+#define MAX1027_CKS_MODE3 (0x03 << 4)
+
+/* averaging register */
+#define MAX1027_NSCAN_4 0x00
+#define MAX1027_NSCAN_8 0x01
+#define MAX1027_NSCAN_12 0x02
+#define MAX1027_NSCAN_16 0x03
+#define MAX1027_NAVG_4 (0x00 << 2)
+#define MAX1027_NAVG_8 (0x01 << 2)
+#define MAX1027_NAVG_16 (0x02 << 2)
+#define MAX1027_NAVG_32 (0x03 << 2)
+#define MAX1027_AVG_EN BIT(4)
+
+enum max1027_id {
+ max1027,
+ max1029,
+ max1031,
+};
+
+static const struct spi_device_id max1027_id[] = {
+ {"max1027", max1027},
+ {"max1029", max1029},
+ {"max1031", max1031},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, max1027_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id max1027_adc_dt_ids[] = {
+ { .compatible = "maxim,max1027" },
+ { .compatible = "maxim,max1029" },
+ { .compatible = "maxim,max1031" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, max1027_adc_dt_ids);
+#endif
+
+#define MAX1027_V_CHAN(index) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = index + 1, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 10, \
+ .storagebits = 16, \
+ .shift = 2, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define MAX1027_T_CHAN \
+ { \
+ .type = IIO_TEMP, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = 0, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+static const struct iio_chan_spec max1027_channels[] = {
+ MAX1027_T_CHAN,
+ MAX1027_V_CHAN(0),
+ MAX1027_V_CHAN(1),
+ MAX1027_V_CHAN(2),
+ MAX1027_V_CHAN(3),
+ MAX1027_V_CHAN(4),
+ MAX1027_V_CHAN(5),
+ MAX1027_V_CHAN(6),
+ MAX1027_V_CHAN(7)
+};
+
+static const struct iio_chan_spec max1029_channels[] = {
+ MAX1027_T_CHAN,
+ MAX1027_V_CHAN(0),
+ MAX1027_V_CHAN(1),
+ MAX1027_V_CHAN(2),
+ MAX1027_V_CHAN(3),
+ MAX1027_V_CHAN(4),
+ MAX1027_V_CHAN(5),
+ MAX1027_V_CHAN(6),
+ MAX1027_V_CHAN(7),
+ MAX1027_V_CHAN(8),
+ MAX1027_V_CHAN(9),
+ MAX1027_V_CHAN(10),
+ MAX1027_V_CHAN(11)
+};
+
+static const struct iio_chan_spec max1031_channels[] = {
+ MAX1027_T_CHAN,
+ MAX1027_V_CHAN(0),
+ MAX1027_V_CHAN(1),
+ MAX1027_V_CHAN(2),
+ MAX1027_V_CHAN(3),
+ MAX1027_V_CHAN(4),
+ MAX1027_V_CHAN(5),
+ MAX1027_V_CHAN(6),
+ MAX1027_V_CHAN(7),
+ MAX1027_V_CHAN(8),
+ MAX1027_V_CHAN(9),
+ MAX1027_V_CHAN(10),
+ MAX1027_V_CHAN(11),
+ MAX1027_V_CHAN(12),
+ MAX1027_V_CHAN(13),
+ MAX1027_V_CHAN(14),
+ MAX1027_V_CHAN(15)
+};
+
+static const unsigned long max1027_available_scan_masks[] = {
+ 0x000001ff,
+ 0x00000000,
+};
+
+static const unsigned long max1029_available_scan_masks[] = {
+ 0x00001fff,
+ 0x00000000,
+};
+
+static const unsigned long max1031_available_scan_masks[] = {
+ 0x0001ffff,
+ 0x00000000,
+};
+
+struct max1027_chip_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ const unsigned long *available_scan_masks;
+};
+
+static const struct max1027_chip_info max1027_chip_info_tbl[] = {
+ [max1027] = {
+ .channels = max1027_channels,
+ .num_channels = ARRAY_SIZE(max1027_channels),
+ .available_scan_masks = max1027_available_scan_masks,
+ },
+ [max1029] = {
+ .channels = max1029_channels,
+ .num_channels = ARRAY_SIZE(max1029_channels),
+ .available_scan_masks = max1029_available_scan_masks,
+ },
+ [max1031] = {
+ .channels = max1031_channels,
+ .num_channels = ARRAY_SIZE(max1031_channels),
+ .available_scan_masks = max1031_available_scan_masks,
+ },
+};
+
+struct max1027_state {
+ const struct max1027_chip_info *info;
+ struct spi_device *spi;
+ struct iio_trigger *trig;
+ __be16 *buffer;
+ struct mutex lock;
+
+ u8 reg ____cacheline_aligned;
+};
+
+static int max1027_read_single_value(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val)
+{
+ int ret;
+ struct max1027_state *st = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev)) {
+ dev_warn(&indio_dev->dev, "trigger mode already enabled");
+ return -EBUSY;
+ }
+
+ /* Start acquisition on conversion register write */
+ st->reg = MAX1027_SETUP_REG | MAX1027_REF_MODE2 | MAX1027_CKS_MODE2;
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev,
+ "Failed to configure setup register\n");
+ return ret;
+ }
+
+ /* Configure conversion register with the requested chan */
+ st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) |
+ MAX1027_NOSCAN | !!(chan->type == IIO_TEMP);
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev,
+ "Failed to configure conversion register\n");
+ return ret;
+ }
+
+ /*
+ * For an unknown reason, when we use the mode "10" (write
+ * conversion register), the interrupt doesn't occur every time.
+ * So we just wait 1 ms.
+ */
+ mdelay(1);
+
+ /* Read result */
+ ret = spi_read(st->spi, st->buffer, (chan->type == IIO_TEMP) ? 4 : 2);
+ if (ret < 0)
+ return ret;
+
+ *val = be16_to_cpu(st->buffer[0]);
+
+ return IIO_VAL_INT;
+}
+
+static int max1027_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret = 0;
+ struct max1027_state *st = iio_priv(indio_dev);
+
+ mutex_lock(&st->lock);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = max1027_read_single_value(indio_dev, chan, val);
+ break;
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 1;
+ *val2 = 8;
+ ret = IIO_VAL_FRACTIONAL;
+ break;
+ case IIO_VOLTAGE:
+ *val = 2500;
+ *val2 = 10;
+ ret = IIO_VAL_FRACTIONAL_LOG2;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
+static int max1027_debugfs_reg_access(struct iio_dev *indio_dev,
+ unsigned reg, unsigned writeval,
+ unsigned *readval)
+{
+ struct max1027_state *st = iio_priv(indio_dev);
+ u8 *val = (u8 *)st->buffer;
+
+ if (readval != NULL)
+ return -EINVAL;
+
+ *val = (u8)writeval;
+ return spi_write(st->spi, val, 1);
+}
+
+static int max1027_validate_trigger(struct iio_dev *indio_dev,
+ struct iio_trigger *trig)
+{
+ struct max1027_state *st = iio_priv(indio_dev);
+
+ if (st->trig != trig)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int max1027_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct max1027_state *st = iio_priv(indio_dev);
+ int ret;
+
+ if (state) {
+ /* Start acquisition on cnvst */
+ st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE0 |
+ MAX1027_REF_MODE2;
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0)
+ return ret;
+
+ /* Scan from 0 to max */
+ st->reg = MAX1027_CONV_REG | MAX1027_CHAN(0) |
+ MAX1027_SCAN_N_M | MAX1027_TEMP;
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* Start acquisition on conversion register write */
+ st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE2 |
+ MAX1027_REF_MODE2;
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max1027_validate_device(struct iio_trigger *trig,
+ struct iio_dev *indio_dev)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+
+ if (indio != indio_dev)
+ return -EINVAL;
+
+ return 0;
+}
+
+static irqreturn_t max1027_trigger_handler(int irq, void *private)
+{
+ struct iio_poll_func *pf = (struct iio_poll_func *)private;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct max1027_state *st = iio_priv(indio_dev);
+
+ pr_debug("%s(irq=%d, private=0x%p)\n", __func__, irq, private);
+
+ /* fill buffer with all channel */
+ spi_read(st->spi, st->buffer, indio_dev->masklength * 2);
+
+ iio_push_to_buffers(indio_dev, st->buffer);
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_trigger_ops max1027_trigger_ops = {
+ .owner = THIS_MODULE,
+ .validate_device = &max1027_validate_device,
+ .set_trigger_state = &max1027_set_trigger_state,
+};
+
+static const struct iio_info max1027_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = &max1027_read_raw,
+ .validate_trigger = &max1027_validate_trigger,
+ .debugfs_reg_access = &max1027_debugfs_reg_access,
+};
+
+static int max1027_probe(struct spi_device *spi)
+{
+ int ret;
+ struct iio_dev *indio_dev;
+ struct max1027_state *st;
+
+ pr_debug("%s: probe(spi = 0x%p)\n", __func__, spi);
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (indio_dev == NULL) {
+ pr_err("Can't allocate iio device\n");
+ return -ENOMEM;
+ }
+
+ spi_set_drvdata(spi, indio_dev);
+
+ st = iio_priv(indio_dev);
+ st->spi = spi;
+ st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+ mutex_init(&st->lock);
+
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &max1027_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ indio_dev->available_scan_masks = st->info->available_scan_masks;
+
+ st->buffer = devm_kmalloc(&indio_dev->dev,
+ indio_dev->num_channels * 2,
+ GFP_KERNEL);
+ if (st->buffer == NULL) {
+ dev_err(&indio_dev->dev, "Can't allocate bufffer\n");
+ return -ENOMEM;
+ }
+
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &max1027_trigger_handler, NULL);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to setup buffer\n");
+ return ret;
+ }
+
+ st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger",
+ indio_dev->name);
+ if (st->trig == NULL) {
+ ret = -ENOMEM;
+ dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n");
+ goto fail_trigger_alloc;
+ }
+
+ st->trig->ops = &max1027_trigger_ops;
+ st->trig->dev.parent = &spi->dev;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ iio_trigger_register(st->trig);
+
+ ret = devm_request_threaded_irq(&spi->dev, spi->irq,
+ iio_trigger_generic_data_rdy_poll,
+ NULL,
+ IRQF_TRIGGER_FALLING,
+ spi->dev.driver->name, st->trig);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
+ goto fail_dev_register;
+ }
+
+ /* Disable averaging */
+ st->reg = MAX1027_AVG_REG;
+ ret = spi_write(st->spi, &st->reg, 1);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to configure averaging register\n");
+ goto fail_dev_register;
+ }
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0) {
+ dev_err(&indio_dev->dev, "Failed to register iio device\n");
+ goto fail_dev_register;
+ }
+
+ return 0;
+
+fail_dev_register:
+fail_trigger_alloc:
+ iio_triggered_buffer_cleanup(indio_dev);
+
+ return ret;
+}
+
+static int max1027_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+ pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+
+ return 0;
+}
+
+static struct spi_driver max1027_driver = {
+ .driver = {
+ .name = "max1027",
+ .owner = THIS_MODULE,
+ },
+ .probe = max1027_probe,
+ .remove = max1027_remove,
+ .id_table = max1027_id,
+};
+module_spi_driver(max1027_driver);
+
+MODULE_AUTHOR("Philippe Reynes <tremyfr@yahoo.fr>");
+MODULE_DESCRIPTION("MAX1027/MAX1029/MAX1031 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index ab52be29141b..fd2745c62943 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -486,7 +486,7 @@ static irqreturn_t xadc_axi_interrupt_handler(int irq, void *devid)
return IRQ_NONE;
if ((status & XADC_AXI_INT_EOS) && xadc->trigger)
- iio_trigger_poll(xadc->trigger, 0);
+ iio_trigger_poll(xadc->trigger);
if (status & XADC_AXI_INT_ALARM_MASK) {
/*
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index 3e7f0d7a80c3..edcf3aabd70d 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -31,17 +31,11 @@ static const struct iio_chan_spec *xadc_event_to_channel(
static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
{
const struct iio_chan_spec *chan;
- unsigned int offset;
/* Temperature threshold error, we don't handle this yet */
if (event == 0)
return;
- if (event < 4)
- offset = event;
- else
- offset = event + 4;
-
chan = xadc_event_to_channel(indio_dev, event);
if (chan->type == IIO_TEMP) {
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 403dd3d8986e..25b01e156d82 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -26,12 +26,12 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-struct {
+static struct {
u32 usage_id;
int unit; /* 0 for default others from HID sensor spec */
int scale_val0; /* scale, whole number */
int scale_val1; /* scale, fraction in micros */
-} static unit_conversion[] = {
+} unit_conversion[] = {
{HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650},
{HID_USAGE_SENSOR_ACCEL_3D,
HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0},
@@ -343,6 +343,7 @@ int hid_sensor_format_scale(u32 usage_id,
}
EXPORT_SYMBOL(hid_sensor_format_scale);
+static
int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
struct hid_sensor_common *st)
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index e8b932fed70e..8a4ec00a91a0 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -14,8 +14,8 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
+#include <linux/of.h>
#include <asm/unaligned.h>
-
#include <linux/iio/common/st_sensors.h>
@@ -265,14 +265,47 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
return 0;
}
+#ifdef CONFIG_OF
+static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
+ struct st_sensors_platform_data *defdata)
+{
+ struct st_sensors_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ u32 val;
+
+ if (!np)
+ return NULL;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2))
+ pdata->drdy_int_pin = (u8) val;
+ else
+ pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 1;
+
+ return pdata;
+}
+#else
+static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev,
+ struct st_sensors_platform_data *defdata)
+{
+ return NULL;
+}
+#endif
+
int st_sensors_init_sensor(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata)
{
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ struct st_sensors_platform_data *of_pdata;
int err = 0;
mutex_init(&sdata->tb.buf_lock);
+ /* If OF/DT pdata exists, it will take precedence of anything else */
+ of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata);
+ if (of_pdata)
+ pdata = of_pdata;
+
if (pdata)
err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
@@ -463,35 +496,6 @@ read_wai_error:
}
EXPORT_SYMBOL(st_sensors_check_device_support);
-ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
-
- return sprintf(buf, "%d\n", adata->odr);
-}
-EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
-
-ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- int err;
- unsigned int odr;
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
-
- err = kstrtoint(buf, 10, &odr);
- if (err < 0)
- goto conversion_error;
-
- mutex_lock(&indio_dev->mlock);
- err = st_sensors_set_odr(indio_dev, odr);
- mutex_unlock(&indio_dev->mlock);
-
-conversion_error:
- return err < 0 ? err : size;
-}
-EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
-
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index 38af9440c103..bb6f3085f57b 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
+#include <linux/of_device.h>
#include <linux/iio/common/st_sensors_i2c.h>
@@ -76,6 +77,35 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev,
}
EXPORT_SYMBOL(st_sensors_i2c_configure);
+#ifdef CONFIG_OF
+/**
+ * st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
+ * @client: the I2C client device for the sensor
+ * @match: the OF match table for the device, containing compatible strings
+ * but also a .data field with the corresponding internal kernel name
+ * used by this sensor.
+ *
+ * In effect this function matches a compatible string to an internal kernel
+ * name for a certain sensor device, so that the rest of the autodetection can
+ * rely on that name from this point on. I2C client devices will be renamed
+ * to match the internal kernel convention.
+ */
+void st_sensors_of_i2c_probe(struct i2c_client *client,
+ const struct of_device_id *match)
+{
+ const struct of_device_id *of_id;
+
+ of_id = of_match_device(match, &client->dev);
+ if (!of_id)
+ return;
+
+ /* The name from the OF match takes precedence if present */
+ strncpy(client->name, of_id->data, sizeof(client->name));
+ client->name[sizeof(client->name) - 1] = '\0';
+}
+EXPORT_SYMBOL(st_sensors_of_i2c_probe);
+#endif
+
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index f378ca8033db..f278eff42a4c 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -163,4 +163,14 @@ config MCP4725
To compile this driver as a module, choose M here: the module
will be called mcp4725.
+config MCP4922
+ tristate "MCP4902, MCP4912, MCP4922 DAC driver"
+ depends on SPI
+ help
+ Say yes here to build the driver for the Microchip MCP4902
+ MCP4912, and MCP4922 DAC devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mcp4922.
+
endmenu
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index bb84ad64463f..10107640bb46 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MCP4725) += mcp4725.o
+obj-$(CONFIG_MCP4922) += mcp4922.o
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index 1e6449346b50..581ec141de3d 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -15,17 +15,16 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/iio/dac/ad5504.h>
-#define AD5505_BITS 12
-#define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1)
-
-#define AD5504_CMD_READ (1 << 15)
-#define AD5504_CMD_WRITE (0 << 15)
+#define AD5504_RES_MASK GENMASK(11, 0)
+#define AD5504_CMD_READ BIT(15)
+#define AD5504_CMD_WRITE 0
#define AD5504_ADDR(addr) ((addr) << 12)
/* Registers */
@@ -42,7 +41,7 @@
/**
* struct ad5446_state - driver instance specific data
- * @us: spi_device
+ * @spi: spi_device
* @reg: supply regulator
* @vref_mv: actual reference voltage used
* @pwr_down_mask power down mask
@@ -126,7 +125,6 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad5504_state *st = iio_priv(indio_dev);
- int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
@@ -135,10 +133,8 @@ static int ad5504_write_raw(struct iio_dev *indio_dev,
return ad5504_spi_write(st, chan->address, val);
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- return -EINVAL;
}
static const char * const ad5504_powerdown_modes[] = {
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index e8199cce2aea..61bb9d4239ea 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -67,7 +67,6 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad5624r_state *st = iio_priv(indio_dev);
- int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
@@ -79,10 +78,8 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev,
chan->address, val,
chan->scan_type.shift);
default:
- ret = -EINVAL;
+ return -EINVAL;
}
-
- return -EINVAL;
}
static const char * const ad5624r_powerdown_modes[] = {
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 17aca4d9bd06..f57562aa396f 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -313,7 +313,7 @@ static int ad5686_probe(struct spi_device *spi)
{
struct ad5686_state *st;
struct iio_dev *indio_dev;
- int ret, regdone = 0, voltage_uv = 0;
+ int ret, voltage_uv = 0;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
@@ -355,7 +355,6 @@ static int ad5686_probe(struct spi_device *spi)
indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = AD5686_DAC_CHANNELS;
- regdone = 1;
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 0);
if (ret)
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index ae49afe2b380..5ba785f18589 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -16,17 +16,16 @@
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/dac/ad5791.h>
-#define AD5791_RES_MASK(x) ((1 << (x)) - 1)
-#define AD5791_DAC_MASK AD5791_RES_MASK(20)
-#define AD5791_DAC_MSB (1 << 19)
+#define AD5791_DAC_MASK GENMASK(19, 0)
-#define AD5791_CMD_READ (1 << 23)
-#define AD5791_CMD_WRITE (0 << 23)
+#define AD5791_CMD_READ BIT(23)
+#define AD5791_CMD_WRITE 0
#define AD5791_ADDR(addr) ((addr) << 20)
/* Registers */
@@ -37,11 +36,11 @@
#define AD5791_ADDR_SW_CTRL 4
/* Control Register */
-#define AD5791_CTRL_RBUF (1 << 1)
-#define AD5791_CTRL_OPGND (1 << 2)
-#define AD5791_CTRL_DACTRI (1 << 3)
-#define AD5791_CTRL_BIN2SC (1 << 4)
-#define AD5791_CTRL_SDODIS (1 << 5)
+#define AD5791_CTRL_RBUF BIT(1)
+#define AD5791_CTRL_OPGND BIT(2)
+#define AD5791_CTRL_DACTRI BIT(3)
+#define AD5791_CTRL_BIN2SC BIT(4)
+#define AD5791_CTRL_SDODIS BIT(5)
#define AD5761_CTRL_LINCOMP(x) ((x) << 6)
#define AD5791_LINCOMP_0_10 0
@@ -54,9 +53,9 @@
#define AD5780_LINCOMP_10_20 12
/* Software Control Register */
-#define AD5791_SWCTRL_LDAC (1 << 0)
-#define AD5791_SWCTRL_CLR (1 << 1)
-#define AD5791_SWCTRL_RESET (1 << 2)
+#define AD5791_SWCTRL_LDAC BIT(0)
+#define AD5791_SWCTRL_CLR BIT(1)
+#define AD5791_SWCTRL_RESET BIT(2)
#define AD5791_DAC_PWRDN_6K 0
#define AD5791_DAC_PWRDN_3STATE 1
@@ -72,7 +71,7 @@ struct ad5791_chip_info {
/**
* struct ad5791_state - driver instance specific data
- * @us: spi_device
+ * @spi: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
* @chip_info: chip model specific constants
@@ -328,7 +327,7 @@ static int ad5791_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- val &= AD5791_RES_MASK(chan->scan_type.realbits);
+ val &= GENMASK(chan->scan_type.realbits - 1, 0);
val <<= chan->scan_type.shift;
return ad5791_spi_write(st, chan->address, val);
diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c
new file mode 100644
index 000000000000..92cf4ca6981d
--- /dev/null
+++ b/drivers/iio/dac/mcp4922.c
@@ -0,0 +1,216 @@
+/*
+ * mcp4922.c
+ *
+ * Driver for Microchip Digital to Analog Converters.
+ * Supports MCP4902, MCP4912, and MCP4922.
+ *
+ * Copyright (c) 2014 EMAC Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/bitops.h>
+
+#define MCP4922_NUM_CHANNELS 2
+
+enum mcp4922_supported_device_ids {
+ ID_MCP4902,
+ ID_MCP4912,
+ ID_MCP4922,
+};
+
+struct mcp4922_state {
+ struct spi_device *spi;
+ unsigned int value[MCP4922_NUM_CHANNELS];
+ unsigned int vref_mv;
+ struct regulator *vref_reg;
+ u8 mosi[2] ____cacheline_aligned;
+};
+
+#define MCP4922_CHAN(chan, bits) { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = chan, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (bits), \
+ .storagebits = 16, \
+ .shift = 12 - (bits), \
+ }, \
+}
+
+static int mcp4922_spi_write(struct mcp4922_state *state, u8 addr, u32 val)
+{
+ state->mosi[1] = val & 0xff;
+ state->mosi[0] = (addr == 0) ? 0x00 : 0x80;
+ state->mosi[0] |= 0x30 | ((val >> 8) & 0x0f);
+
+ return spi_write(state->spi, state->mosi, 2);
+}
+
+static int mcp4922_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct mcp4922_state *state = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ *val = state->value[chan->channel];
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = state->vref_mv;
+ *val2 = chan->scan_type.realbits;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp4922_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ struct mcp4922_state *state = iio_priv(indio_dev);
+
+ if (val2 != 0)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (val > GENMASK(chan->scan_type.realbits-1, 0))
+ return -EINVAL;
+ val <<= chan->scan_type.shift;
+ state->value[chan->channel] = val;
+ return mcp4922_spi_write(state, chan->channel, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_chan_spec mcp4922_channels[3][MCP4922_NUM_CHANNELS] = {
+ [ID_MCP4902] = { MCP4922_CHAN(0, 8), MCP4922_CHAN(1, 8) },
+ [ID_MCP4912] = { MCP4922_CHAN(0, 10), MCP4922_CHAN(1, 10) },
+ [ID_MCP4922] = { MCP4922_CHAN(0, 12), MCP4922_CHAN(1, 12) },
+};
+
+static const struct iio_info mcp4922_info = {
+ .read_raw = &mcp4922_read_raw,
+ .write_raw = &mcp4922_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int mcp4922_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct mcp4922_state *state;
+ const struct spi_device_id *id;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+ state->spi = spi;
+ state->vref_reg = devm_regulator_get(&spi->dev, "vref");
+ if (IS_ERR(state->vref_reg)) {
+ dev_err(&spi->dev, "Vref regulator not specified\n");
+ return PTR_ERR(state->vref_reg);
+ }
+
+ ret = regulator_enable(state->vref_reg);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable vref regulator: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regulator_get_voltage(state->vref_reg);
+ if (ret < 0) {
+ dev_err(&spi->dev, "Failed to read vref regulator: %d\n",
+ ret);
+ goto error_disable_reg;
+ }
+ state->vref_mv = ret / 1000;
+
+ spi_set_drvdata(spi, indio_dev);
+ id = spi_get_device_id(spi);
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->info = &mcp4922_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = mcp4922_channels[id->driver_data];
+ indio_dev->num_channels = MCP4922_NUM_CHANNELS;
+ indio_dev->name = id->name;
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&spi->dev, "Failed to register iio device: %d\n",
+ ret);
+ goto error_disable_reg;
+ }
+
+ return 0;
+
+error_disable_reg:
+ regulator_disable(state->vref_reg);
+
+ return ret;
+}
+
+static int mcp4922_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct mcp4922_state *state;
+
+ iio_device_unregister(indio_dev);
+ state = iio_priv(indio_dev);
+ regulator_disable(state->vref_reg);
+
+ return 0;
+}
+
+static const struct spi_device_id mcp4922_id[] = {
+ {"mcp4902", ID_MCP4902},
+ {"mcp4912", ID_MCP4912},
+ {"mcp4922", ID_MCP4922},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, mcp4922_id);
+
+static struct spi_driver mcp4922_driver = {
+ .driver = {
+ .name = "mcp4922",
+ .owner = THIS_MODULE,
+ },
+ .probe = mcp4922_probe,
+ .remove = mcp4922_remove,
+ .id_table = mcp4922_id,
+};
+module_spi_driver(mcp4922_driver);
+
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
+MODULE_DESCRIPTION("Microchip MCP4902, MCP4912, MCP4922 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 22b6fb80fa1a..75fe0edd3d0f 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -101,65 +101,6 @@
#define ADIS16260_SCAN_TEMP 3
#define ADIS16260_SCAN_ANGL 4
-static ssize_t adis16260_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis *adis = iio_priv(indio_dev);
- int ret, len = 0;
- u16 t;
- int sps;
- ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t);
- if (ret)
- return ret;
-
- if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */
- sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
- else
- sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
- sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
- len = sprintf(buf, "%d\n", sps);
- return len;
-}
-
-static ssize_t adis16260_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis *adis = iio_priv(indio_dev);
- unsigned int val;
- int ret;
- u8 t;
-
- ret = kstrtouint(buf, 10, &val);
- if (ret)
- return ret;
-
- mutex_lock(&indio_dev->mlock);
- if (spi_get_device_id(adis->spi)->driver_data)
- t = 256 / val;
- else
- t = 2048 / val;
-
- if (t > ADIS16260_SMPL_PRD_DIV_MASK)
- t = ADIS16260_SMPL_PRD_DIV_MASK;
- else if (t > 0)
- t--;
-
- if (t >= 0x0A)
- adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
- else
- adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
- ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
-
- mutex_unlock(&indio_dev->mlock);
-
- return ret ? ret : len;
-}
-
/* Power down the device */
static int adis16260_stop_device(struct iio_dev *indio_dev)
{
@@ -174,18 +115,19 @@ static int adis16260_stop_device(struct iio_dev *indio_dev)
return ret;
}
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16260_read_frequency,
- adis16260_write_frequency);
-
static const struct iio_chan_spec adis16260_channels[] = {
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
BIT(IIO_CHAN_INFO_CALIBBIAS) |
- BIT(IIO_CHAN_INFO_CALIBSCALE), 14),
- ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14),
- ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12),
- ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12),
- ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12),
+ BIT(IIO_CHAN_INFO_CALIBSCALE),
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+ ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+ ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+ ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+ ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
IIO_CHAN_SOFT_TIMESTAMP(5),
};
@@ -258,6 +200,20 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
*val = val16;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
+ if (ret)
+ return ret;
+
+ if (spi_get_device_id(adis->spi)->driver_data)
+ /* If an adis16251 */
+ *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
+ 8 : 256;
+ else
+ *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
+ 66 : 2048;
+ *val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
+ return IIO_VAL_INT;
}
return -EINVAL;
}
@@ -269,7 +225,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct adis *adis = iio_priv(indio_dev);
+ int ret;
u8 addr;
+ u8 t;
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
@@ -284,21 +242,31 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
addr = adis16260_addresses[chan->scan_index][1];
return adis_write_reg_16(adis, addr, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ mutex_lock(&indio_dev->mlock);
+ if (spi_get_device_id(adis->spi)->driver_data)
+ t = 256 / val;
+ else
+ t = 2048 / val;
+
+ if (t > ADIS16260_SMPL_PRD_DIV_MASK)
+ t = ADIS16260_SMPL_PRD_DIV_MASK;
+ else if (t > 0)
+ t--;
+
+ if (t >= 0x0A)
+ adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
+ else
+ adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
+ ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
+
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
}
return -EINVAL;
}
-static struct attribute *adis16260_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16260_attribute_group = {
- .attrs = adis16260_attributes,
-};
-
static const struct iio_info adis16260_info = {
- .attrs = &adis16260_attribute_group,
.read_raw = &adis16260_read_raw,
.write_raw = &adis16260_write_raw,
.update_scan_mode = adis_update_scan_mode,
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index 8295e318399f..6a8020d48140 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -90,6 +90,7 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
{
int ret = 0;
u8 reg;
+ u8 regval;
switch (info) {
case IIO_CHAN_INFO_RAW:
@@ -107,65 +108,60 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
/* Only the temperature channel has an offset */
*val = 23000;
return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
-}
-
-static ssize_t itg3200_read_frequency(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- int ret, sps;
- u8 val;
-
- ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &val);
- if (ret)
- return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &regval);
+ if (ret)
+ return ret;
- sps = (val & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
+ *val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000;
- ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, &val);
- if (ret)
- return ret;
+ ret = itg3200_read_reg_8(indio_dev,
+ ITG3200_REG_SAMPLE_RATE_DIV,
+ &regval);
+ if (ret)
+ return ret;
- sps /= val + 1;
+ *val /= regval + 1;
+ return IIO_VAL_INT;
- return sprintf(buf, "%d\n", sps);
+ default:
+ return -EINVAL;
+ }
}
-static ssize_t itg3200_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+static int itg3200_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned val;
int ret;
u8 t;
- ret = kstrtouint(buf, 10, &val);
- if (ret)
- return ret;
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val == 0 || val2 != 0)
+ return -EINVAL;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&indio_dev->mlock);
- ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
- if (ret)
- goto err_ret;
+ ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t);
+ if (ret) {
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
+ }
+ t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
- if (val == 0) {
- ret = -EINVAL;
- goto err_ret;
- }
- t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1;
+ ret = itg3200_write_reg_8(indio_dev,
+ ITG3200_REG_SAMPLE_RATE_DIV,
+ t);
- ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, t);
-
-err_ret:
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
- return ret ? ret : len;
+ default:
+ return -EINVAL;
+ }
}
/*
@@ -255,6 +251,7 @@ err_ret:
.channel2 = IIO_MOD_ ## _mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \
.scan_index = ITG3200_SCAN_GYRO_ ## _mod, \
.scan_type = ITG3200_ST, \
@@ -267,6 +264,7 @@ static const struct iio_chan_spec itg3200_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.address = ITG3200_REG_TEMP_OUT_H,
.scan_index = ITG3200_SCAN_TEMP,
.scan_type = ITG3200_ST,
@@ -277,22 +275,9 @@ static const struct iio_chan_spec itg3200_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ITG3200_SCAN_ELEMENTS),
};
-/* IIO device attributes */
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, itg3200_read_frequency,
- itg3200_write_frequency);
-
-static struct attribute *itg3200_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group itg3200_attribute_group = {
- .attrs = itg3200_attributes,
-};
-
static const struct iio_info itg3200_info = {
- .attrs = &itg3200_attribute_group,
.read_raw = &itg3200_read_raw,
+ .write_raw = &itg3200_write_raw,
.driver_module = THIS_MODULE,
};
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index ed74a9069989..f156fc6c5c6c 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -245,6 +245,9 @@ static int st_gyro_read_raw(struct iio_dev *indio_dev,
*val = 0;
*val2 = gdata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = gdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -262,6 +265,13 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2)
+ return -EINVAL;
+ mutex_lock(&indio_dev->mlock);
+ err = st_sensors_set_odr(indio_dev, val);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
default:
err = -EINVAL;
}
@@ -269,14 +279,12 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
static struct attribute *st_gyro_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 23c12f361b05..8fa0ad2ef4ef 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -18,6 +18,43 @@
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_gyro.h"
+#ifdef CONFIG_OF
+static const struct of_device_id st_gyro_of_match[] = {
+ {
+ .compatible = "st,l3g4200d-gyro",
+ .data = L3G4200D_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330d-gyro",
+ .data = LSM330D_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330dl-gyro",
+ .data = LSM330DL_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330dlc-gyro",
+ .data = LSM330DLC_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,l3gd20-gyro",
+ .data = L3GD20_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,l3g4is-gyro",
+ .data = L3G4IS_GYRO_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm330-gyro",
+ .data = LSM330_GYRO_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_gyro_of_match);
+#else
+#define st_gyro_of_match NULL
+#endif
+
static int st_gyro_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -31,6 +68,7 @@ static int st_gyro_i2c_probe(struct i2c_client *client,
gdata = iio_priv(indio_dev);
gdata->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_gyro_of_match);
st_sensors_i2c_configure(indio_dev, client, gdata);
@@ -65,6 +103,7 @@ static struct i2c_driver st_gyro_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-gyro-i2c",
+ .of_match_table = of_match_ptr(st_gyro_of_match),
},
.probe = st_gyro_i2c_probe,
.remove = st_gyro_i2c_remove,
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index f2cf829e5df1..6e727ffe5262 100644
--- a/drivers/iio/imu/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -18,7 +18,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
{
struct adis16400_state *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
- uint16_t *tx, *rx;
+ uint16_t *tx;
if (st->variant->flags & ADIS16400_NO_BURST)
return adis_update_scan_mode(indio_dev, scan_mask);
@@ -35,7 +35,6 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev,
if (!adis->buffer)
return -ENOMEM;
- rx = adis->buffer;
tx = adis->buffer + indio_dev->scan_bytes;
tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD);
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index 433583b6f800..b70873de04ea 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -214,21 +214,6 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
}
-static ssize_t adis16400_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis16400_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = st->variant->get_freq(st);
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d.%.3d\n", ret / 1000, ret % 1000);
-}
-
static const unsigned adis16400_3db_divisors[] = {
[0] = 2, /* Special case */
[1] = 6,
@@ -260,30 +245,6 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
return ret;
}
-static ssize_t adis16400_write_frequency(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis16400_state *st = iio_priv(indio_dev);
- int i, f, val;
- int ret;
-
- ret = iio_str_to_fixpoint(buf, 100, &i, &f);
- if (ret)
- return ret;
-
- val = i * 1000 + f;
-
- if (val <= 0)
- return -EINVAL;
-
- mutex_lock(&indio_dev->mlock);
- st->variant->set_freq(st, val);
- mutex_unlock(&indio_dev->mlock);
-
- return len;
-}
-
/* Power down the device */
static int adis16400_stop_device(struct iio_dev *indio_dev)
{
@@ -350,10 +311,6 @@ err_ret:
return ret;
}
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16400_read_frequency,
- adis16400_write_frequency);
-
static const uint8_t adis16400_addresses[] = {
[ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF,
[ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF,
@@ -394,6 +351,16 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
val * 1000 + val2 / 1000);
mutex_unlock(&indio_dev->mlock);
return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ sps = val * 1000 + val2 / 1000;
+
+ if (sps <= 0)
+ return -EINVAL;
+
+ mutex_lock(&indio_dev->mlock);
+ ret = st->variant->set_freq(st, sps);
+ mutex_unlock(&indio_dev->mlock);
+ return ret;
default:
return -EINVAL;
}
@@ -474,6 +441,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = st->variant->get_freq(st);
+ if (ret < 0)
+ return ret;
+ *val = ret / 1000;
+ *val2 = (ret % 1000) * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
@@ -486,6 +460,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.extend_name = name, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = (si), \
.scan_type = { \
@@ -511,6 +486,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = addr, \
.scan_index = ADIS16400_SCAN_GYRO_ ## mod, \
.scan_type = { \
@@ -530,6 +506,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_ACC_ ## mod, \
.scan_type = { \
@@ -548,6 +525,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16400_SCAN_MAGN_ ## mod, \
.scan_type = { \
@@ -573,6 +551,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_type = \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_ ## mod, \
.scan_type = { \
@@ -591,6 +570,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16350_SCAN_TEMP_X, \
.scan_type = { \
@@ -608,6 +588,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
.channel2 = IIO_MOD_ ## mod, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (addr), \
.scan_index = ADIS16300_SCAN_INCLI_ ## mod, \
.scan_type = { \
@@ -649,6 +630,7 @@ static const struct iio_chan_spec adis16448_channels[] = {
.type = IIO_PRESSURE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.address = ADIS16448_BARO_OUT,
.scan_index = ADIS16400_SCAN_BARO,
.scan_type = {
@@ -704,15 +686,6 @@ static const struct iio_chan_spec adis16334_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
-static struct attribute *adis16400_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16400_attribute_group = {
- .attrs = adis16400_attributes,
-};
-
static struct adis16400_chip_info adis16400_chips[] = {
[ADIS16300] = {
.channels = adis16300_channels,
@@ -813,7 +786,6 @@ static const struct iio_info adis16400_info = {
.driver_module = THIS_MODULE,
.read_raw = &adis16400_read_raw,
.write_raw = &adis16400_write_raw,
- .attrs = &adis16400_attribute_group,
.update_scan_mode = adis16400_update_scan_mode,
.debugfs_reg_access = adis_debugfs_reg_access,
};
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index dd4206cac62d..989605dd6f78 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -257,11 +257,16 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev)
#endif
-static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
+static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
{
+ struct adis16480 *st = iio_priv(indio_dev);
unsigned int t;
- t = 2460000 / freq;
+ t = val * 1000 + val2 / 1000;
+ if (t <= 0)
+ return -EINVAL;
+
+ t = 2460000 / t;
if (t > 2048)
t = 2048;
@@ -271,65 +276,24 @@ static int adis16480_set_freq(struct adis16480 *st, unsigned int freq)
return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t);
}
-static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq)
+static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
{
+ struct adis16480 *st = iio_priv(indio_dev);
uint16_t t;
int ret;
+ unsigned freq;
ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t);
if (ret < 0)
return ret;
- *freq = 2460000 / (t + 1);
+ freq = 2460000 / (t + 1);
+ *val = freq / 1000;
+ *val2 = (freq % 1000) * 1000;
- return 0;
+ return IIO_VAL_INT_PLUS_MICRO;
}
-static ssize_t adis16480_read_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis16480 *st = iio_priv(indio_dev);
- unsigned int freq;
- int ret;
-
- ret = adis16480_get_freq(st, &freq);
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000);
-}
-
-static ssize_t adis16480_write_frequency(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adis16480 *st = iio_priv(indio_dev);
- int freq_int, freq_fract;
- long val;
- int ret;
-
- ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract);
- if (ret)
- return ret;
-
- val = freq_int * 1000 + freq_fract;
-
- if (val <= 0)
- return -EINVAL;
-
- ret = adis16480_set_freq(st, val);
-
- return ret ? ret : len;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
- adis16480_read_frequency,
- adis16480_write_frequency);
-
enum {
ADIS16480_SCAN_GYRO_X,
ADIS16480_SCAN_GYRO_Y,
@@ -571,6 +535,8 @@ static int adis16480_read_raw(struct iio_dev *indio_dev,
return adis16480_get_calibscale(indio_dev, chan, val);
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return adis16480_get_filter_freq(indio_dev, chan, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return adis16480_get_freq(indio_dev, val, val2);
default:
return -EINVAL;
}
@@ -586,6 +552,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
return adis16480_set_calibscale(indio_dev, chan, val);
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return adis16480_set_filter_freq(indio_dev, chan, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return adis16480_set_freq(indio_dev, val, val2);
+
default:
return -EINVAL;
}
@@ -600,6 +569,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
_info_sep, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = (_address), \
.scan_index = (_si), \
.scan_type = { \
@@ -638,6 +608,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = ADIS16480_REG_BAROM_OUT, \
.scan_index = ADIS16480_SCAN_BARO, \
.scan_type = { \
@@ -655,6 +626,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.address = ADIS16480_REG_TEMP_OUT, \
.scan_index = ADIS16480_SCAN_TEMP, \
.scan_type = { \
@@ -717,17 +689,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
},
};
-static struct attribute *adis16480_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- NULL
-};
-
-static const struct attribute_group adis16480_attribute_group = {
- .attrs = adis16480_attributes,
-};
-
static const struct iio_info adis16480_info = {
- .attrs = &adis16480_attribute_group,
.read_raw = &adis16480_read_raw,
.write_raw = &adis16480_write_raw,
.update_scan_mode = adis_update_scan_mode,
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 9f1a14009901..0472ee268271 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -39,10 +39,7 @@ static bool iio_buffer_is_active(struct iio_buffer *buf)
static bool iio_buffer_data_available(struct iio_buffer *buf)
{
- if (buf->access->data_available)
- return buf->access->data_available(buf);
-
- return buf->stufftoread;
+ return buf->access->data_available(buf);
}
/**
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 4b1f375c5659..af3e76d652ba 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -87,6 +87,10 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_QUATERNION] = "quaternion",
[IIO_MOD_TEMP_AMBIENT] = "ambient",
[IIO_MOD_TEMP_OBJECT] = "object",
+ [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
+ [IIO_MOD_NORTH_TRUE] = "from_north_true",
+ [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
+ [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
};
/* relies on pairs of these shared then separate */
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index bfbf4d419f41..0c1e37e3120a 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -209,6 +209,7 @@ static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_ENABLE] = "en",
[IIO_EV_INFO_VALUE] = "value",
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
+ [IIO_EV_INFO_PERIOD] = "period",
};
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 3383b025f62e..d31098e0c43f 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -114,7 +114,7 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name,
return trig;
}
-void iio_trigger_poll(struct iio_trigger *trig, s64 time)
+void iio_trigger_poll(struct iio_trigger *trig)
{
int i;
@@ -133,12 +133,12 @@ EXPORT_SYMBOL(iio_trigger_poll);
irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private)
{
- iio_trigger_poll(private, iio_get_time_ns());
+ iio_trigger_poll(private);
return IRQ_HANDLED;
}
EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll);
-void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time)
+void iio_trigger_poll_chained(struct iio_trigger *trig)
{
int i;
@@ -161,7 +161,7 @@ void iio_trigger_notify_done(struct iio_trigger *trig)
trig->ops->try_reenable)
if (trig->ops->try_reenable(trig))
/* Missed an interrupt so launch new poll now */
- iio_trigger_poll(trig, 0);
+ iio_trigger_poll(trig);
}
EXPORT_SYMBOL(iio_trigger_notify_done);
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index c89740d4748f..bf05ca5b0a57 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -62,6 +62,18 @@ config GP2AP020A00F
To compile this driver as a module, choose M here: the
module will be called gp2ap020a00f.
+config ISL29125
+ tristate "Intersil ISL29125 digital color light sensor"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here if you want to build a driver for the Intersil ISL29125
+ RGB light sensor for I2C.
+
+ To compile this driver as a module, choose M here: the module will be
+ called isl29125.
+
config HID_SENSOR_ALS
depends on HID_SENSOR_HUB
select IIO_BUFFER
@@ -116,6 +128,18 @@ config LTR501
This driver can also be built as a module. If so, the module
will be called ltr501.
+config TCS3414
+ tristate "TAOS TCS3414 digital color sensor"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ If you say yes here you get support for the TAOS TCS3414
+ family of digital color sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called tcs3414.
+
config TCS3472
tristate "TAOS TCS3472 color light-to-digital converter"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 3eb36e5151fa..8b8c09f9c1f8 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -10,9 +10,11 @@ obj-$(CONFIG_CM36651) += cm36651.o
obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
+obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
+obj-$(CONFIG_TCS3414) += tcs3414.o
obj-$(CONFIG_TCS3472) += tcs3472.o
obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index d976e6ce60db..ad36b294e4d5 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -331,7 +331,7 @@ static int cm32181_probe(struct i2c_client *client,
return ret;
}
- ret = iio_device_register(indio_dev);
+ ret = devm_iio_device_register(&client->dev, indio_dev);
if (ret) {
dev_err(&client->dev,
"%s: regist device failed\n",
@@ -342,14 +342,6 @@ static int cm32181_probe(struct i2c_client *client,
return 0;
}
-static int cm32181_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
- return 0;
-}
-
static const struct i2c_device_id cm32181_id[] = {
{ "cm32181", 0 },
{ }
@@ -370,7 +362,6 @@ static struct i2c_driver cm32181_driver = {
},
.id_table = cm32181_id,
.probe = cm32181_probe,
- .remove = cm32181_remove,
};
module_i2c_driver(cm32181_driver);
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 04bdb85d2d9f..221ed16de1f7 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -827,7 +827,7 @@ static void gp2ap020a00f_iio_trigger_work(struct irq_work *work)
struct gp2ap020a00f_data *data =
container_of(work, struct gp2ap020a00f_data, work);
- iio_trigger_poll(data->trig, 0);
+ iio_trigger_poll(data->trig);
}
static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
new file mode 100644
index 000000000000..c82f4a6f8464
--- /dev/null
+++ b/drivers/iio/light/isl29125.c
@@ -0,0 +1,347 @@
+/*
+ * isl29125.c - Support for Intersil ISL29125 RGB light sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * RGB light sensor with 16-bit channels for red, green, blue);
+ * 7-bit I2C slave address 0x44
+ *
+ * TODO: interrupt support, IR compensation, thresholds, 12bit
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define ISL29125_DRV_NAME "isl29125"
+
+#define ISL29125_DEVICE_ID 0x00
+#define ISL29125_CONF1 0x01
+#define ISL29125_CONF2 0x02
+#define ISL29125_CONF3 0x03
+#define ISL29125_STATUS 0x08
+#define ISL29125_GREEN_DATA 0x09
+#define ISL29125_RED_DATA 0x0b
+#define ISL29125_BLUE_DATA 0x0d
+
+#define ISL29125_ID 0x7d
+
+#define ISL29125_MODE_MASK GENMASK(2, 0)
+#define ISL29125_MODE_PD 0x0
+#define ISL29125_MODE_G 0x1
+#define ISL29125_MODE_R 0x2
+#define ISL29125_MODE_B 0x3
+#define ISL29125_MODE_RGB 0x5
+
+#define ISL29125_MODE_RANGE BIT(3)
+
+#define ISL29125_STATUS_CONV BIT(1)
+
+struct isl29125_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ u8 conf1;
+ u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */
+};
+
+#define ISL29125_CHANNEL(_color, _si) { \
+ .type = IIO_INTENSITY, \
+ .modified = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .channel2 = IIO_MOD_LIGHT_##_color, \
+ .scan_index = _si, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+static const struct iio_chan_spec isl29125_channels[] = {
+ ISL29125_CHANNEL(GREEN, 0),
+ ISL29125_CHANNEL(RED, 1),
+ ISL29125_CHANNEL(BLUE, 2),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct {
+ u8 mode, data;
+} isl29125_regs[] = {
+ {ISL29125_MODE_G, ISL29125_GREEN_DATA},
+ {ISL29125_MODE_R, ISL29125_RED_DATA},
+ {ISL29125_MODE_B, ISL29125_BLUE_DATA},
+};
+
+static int isl29125_read_data(struct isl29125_data *data, int si)
+{
+ int tries = 5;
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1 | isl29125_regs[si].mode);
+ if (ret < 0)
+ return ret;
+
+ msleep(101);
+
+ while (tries--) {
+ ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS);
+ if (ret < 0)
+ goto fail;
+ if (ret & ISL29125_STATUS_CONV)
+ break;
+ msleep(20);
+ }
+
+ if (tries < 0) {
+ dev_err(&data->client->dev, "data not ready\n");
+ ret = -EIO;
+ goto fail;
+ }
+
+ ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data);
+
+fail:
+ i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1);
+ return ret;
+}
+
+static int isl29125_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct isl29125_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+ mutex_lock(&data->lock);
+ ret = isl29125_read_data(data, chan->scan_index);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ if (data->conf1 & ISL29125_MODE_RANGE)
+ *val2 = 152590; /* 10k lux full range */
+ else
+ *val2 = 5722; /* 375 lux full range */
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
+}
+
+static int isl29125_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct isl29125_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (val != 0)
+ return -EINVAL;
+ if (val2 == 152590)
+ data->conf1 |= ISL29125_MODE_RANGE;
+ else if (val2 == 5722)
+ data->conf1 &= ~ISL29125_MODE_RANGE;
+ else
+ return -EINVAL;
+ return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1);
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t isl29125_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct isl29125_data *data = iio_priv(indio_dev);
+ int i, j = 0;
+
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ int ret = i2c_smbus_read_word_data(data->client,
+ isl29125_regs[i].data);
+ if (ret < 0)
+ goto done;
+
+ data->buffer[j++] = ret;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_get_time_ns());
+
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_info isl29125_info = {
+ .read_raw = isl29125_read_raw,
+ .write_raw = isl29125_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct isl29125_data *data = iio_priv(indio_dev);
+
+ data->conf1 |= ISL29125_MODE_RGB;
+ return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1);
+}
+
+static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct isl29125_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_triggered_buffer_predisable(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ data->conf1 &= ~ISL29125_MODE_MASK;
+ data->conf1 |= ISL29125_MODE_PD;
+ return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1);
+}
+
+static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
+ .preenable = isl29125_buffer_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = isl29125_buffer_predisable,
+};
+
+static int isl29125_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct isl29125_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &isl29125_info;
+ indio_dev->name = ISL29125_DRV_NAME;
+ indio_dev->channels = isl29125_channels;
+ indio_dev->num_channels = ARRAY_SIZE(isl29125_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID);
+ if (ret < 0)
+ return ret;
+ if (ret != ISL29125_ID)
+ return -ENODEV;
+
+ data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE;
+ ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ isl29125_trigger_handler, &isl29125_buffer_setup_ops);
+ if (ret < 0)
+ return ret;
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ goto buffer_cleanup;
+
+ return 0;
+
+buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+ return ret;
+}
+
+static int isl29125_powerdown(struct isl29125_data *data)
+{
+ return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ (data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD);
+}
+
+static int isl29125_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ isl29125_powerdown(iio_priv(indio_dev));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int isl29125_suspend(struct device *dev)
+{
+ struct isl29125_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return isl29125_powerdown(data);
+}
+
+static int isl29125_resume(struct device *dev)
+{
+ struct isl29125_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
+ data->conf1);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume);
+
+static const struct i2c_device_id isl29125_id[] = {
+ { "isl29125", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, isl29125_id);
+
+static struct i2c_driver isl29125_driver = {
+ .driver = {
+ .name = ISL29125_DRV_NAME,
+ .pm = &isl29125_pm_ops,
+ .owner = THIS_MODULE,
+ },
+ .probe = isl29125_probe,
+ .remove = isl29125_remove,
+ .id_table = isl29125_id,
+};
+module_i2c_driver(isl29125_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("ISL29125 RGB light sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
new file mode 100644
index 000000000000..a9e449b0be0c
--- /dev/null
+++ b/drivers/iio/light/tcs3414.c
@@ -0,0 +1,405 @@
+/*
+ * tcs3414.c - Support for TAOS TCS3414 digital color sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Digital color sensor with 16-bit channels for red, green, blue, clear);
+ * 7-bit I2C slave address 0x39 (TCS3414) or 0x29, 0x49, 0x59 (TCS3413,
+ * TCS3415, TCS3416, resp.)
+ *
+ * TODO: sync, interrupt support, thresholds, prescaler
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define TCS3414_DRV_NAME "tcs3414"
+
+#define TCS3414_COMMAND BIT(7)
+#define TCS3414_COMMAND_WORD (TCS3414_COMMAND | BIT(5))
+
+#define TCS3414_CONTROL (TCS3414_COMMAND | 0x00)
+#define TCS3414_TIMING (TCS3414_COMMAND | 0x01)
+#define TCS3414_ID (TCS3414_COMMAND | 0x04)
+#define TCS3414_GAIN (TCS3414_COMMAND | 0x07)
+#define TCS3414_DATA_GREEN (TCS3414_COMMAND_WORD | 0x10)
+#define TCS3414_DATA_RED (TCS3414_COMMAND_WORD | 0x12)
+#define TCS3414_DATA_BLUE (TCS3414_COMMAND_WORD | 0x14)
+#define TCS3414_DATA_CLEAR (TCS3414_COMMAND_WORD | 0x16)
+
+#define TCS3414_CONTROL_ADC_VALID BIT(4)
+#define TCS3414_CONTROL_ADC_EN BIT(1)
+#define TCS3414_CONTROL_POWER BIT(0)
+
+#define TCS3414_INTEG_MASK GENMASK(1, 0)
+#define TCS3414_INTEG_12MS 0x0
+#define TCS3414_INTEG_100MS 0x1
+#define TCS3414_INTEG_400MS 0x2
+
+#define TCS3414_GAIN_MASK GENMASK(5, 4)
+#define TCS3414_GAIN_SHIFT 4
+
+struct tcs3414_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ u8 control;
+ u8 gain;
+ u8 timing;
+ u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */
+};
+
+#define TCS3414_CHANNEL(_color, _si, _addr) { \
+ .type = IIO_INTENSITY, \
+ .modified = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_INT_TIME), \
+ .channel2 = IIO_MOD_LIGHT_##_color, \
+ .address = _addr, \
+ .scan_index = _si, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+/* scale factors: 1/gain */
+static const int tcs3414_scales[][2] = {
+ {1, 0}, {0, 250000}, {0, 62500}, {0, 15625}
+};
+
+/* integration time in ms */
+static const int tcs3414_times[] = { 12, 100, 400 };
+
+static const struct iio_chan_spec tcs3414_channels[] = {
+ TCS3414_CHANNEL(GREEN, 0, TCS3414_DATA_GREEN),
+ TCS3414_CHANNEL(RED, 1, TCS3414_DATA_RED),
+ TCS3414_CHANNEL(BLUE, 2, TCS3414_DATA_BLUE),
+ TCS3414_CHANNEL(CLEAR, 3, TCS3414_DATA_CLEAR),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static int tcs3414_req_data(struct tcs3414_data *data)
+{
+ int tries = 25;
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control | TCS3414_CONTROL_ADC_EN);
+ if (ret < 0)
+ return ret;
+
+ while (tries--) {
+ ret = i2c_smbus_read_byte_data(data->client, TCS3414_CONTROL);
+ if (ret < 0)
+ return ret;
+ if (ret & TCS3414_CONTROL_ADC_VALID)
+ break;
+ msleep(20);
+ }
+
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control);
+ if (ret < 0)
+ return ret;
+
+ if (tries < 0) {
+ dev_err(&data->client->dev, "data not ready\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tcs3414_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct tcs3414_data *data = iio_priv(indio_dev);
+ int i, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+ mutex_lock(&data->lock);
+ ret = tcs3414_req_data(data);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+ ret = i2c_smbus_read_word_data(data->client, chan->address);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT;
+ *val = tcs3414_scales[i][0];
+ *val2 = tcs3414_scales[i][1];
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
+ *val2 = tcs3414_times[data->timing & TCS3414_INTEG_MASK] * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
+}
+
+static int tcs3414_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct tcs3414_data *data = iio_priv(indio_dev);
+ int i;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ for (i = 0; i < ARRAY_SIZE(tcs3414_scales); i++) {
+ if (val == tcs3414_scales[i][0] &&
+ val2 == tcs3414_scales[i][1]) {
+ data->gain &= ~TCS3414_GAIN_MASK;
+ data->gain |= i << TCS3414_GAIN_SHIFT;
+ return i2c_smbus_write_byte_data(
+ data->client, TCS3414_GAIN,
+ data->gain);
+ }
+ }
+ return -EINVAL;
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) {
+ if (val == tcs3414_times[i] * 1000) {
+ data->timing &= ~TCS3414_INTEG_MASK;
+ data->timing |= i;
+ return i2c_smbus_write_byte_data(
+ data->client, TCS3414_TIMING,
+ data->timing);
+ }
+ }
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t tcs3414_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct tcs3414_data *data = iio_priv(indio_dev);
+ int i, j = 0;
+
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ int ret = i2c_smbus_read_word_data(data->client,
+ TCS3414_DATA_GREEN + 2*i);
+ if (ret < 0)
+ goto done;
+
+ data->buffer[j++] = ret;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_get_time_ns());
+
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static IIO_CONST_ATTR(scale_available, "1 0.25 0.0625 0.015625");
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4");
+
+static struct attribute *tcs3414_attributes[] = {
+ &iio_const_attr_scale_available.dev_attr.attr,
+ &iio_const_attr_integration_time_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group tcs3414_attribute_group = {
+ .attrs = tcs3414_attributes,
+};
+
+static const struct iio_info tcs3414_info = {
+ .read_raw = tcs3414_read_raw,
+ .write_raw = tcs3414_write_raw,
+ .attrs = &tcs3414_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int tcs3414_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct tcs3414_data *data = iio_priv(indio_dev);
+
+ data->control |= TCS3414_CONTROL_ADC_EN;
+ return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control);
+}
+
+static int tcs3414_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct tcs3414_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_triggered_buffer_predisable(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ data->control &= ~TCS3414_CONTROL_ADC_EN;
+ return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control);
+}
+
+static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = {
+ .preenable = tcs3414_buffer_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = tcs3414_buffer_predisable,
+};
+
+static int tcs3414_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tcs3414_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &tcs3414_info;
+ indio_dev->name = TCS3414_DRV_NAME;
+ indio_dev->channels = tcs3414_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tcs3414_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3414_ID);
+ if (ret < 0)
+ return ret;
+
+ switch (ret & 0xf0) {
+ case 0x00:
+ dev_info(&client->dev, "TCS3404 found\n");
+ break;
+ case 0x10:
+ dev_info(&client->dev, "TCS3413/14/15/16 found\n");
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ data->control = TCS3414_CONTROL_POWER;
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control);
+ if (ret < 0)
+ return ret;
+
+ data->timing = TCS3414_INTEG_12MS; /* free running */
+ ret = i2c_smbus_write_byte_data(data->client, TCS3414_TIMING,
+ data->timing);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3414_GAIN);
+ if (ret < 0)
+ return ret;
+ data->gain = ret;
+
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ tcs3414_trigger_handler, &tcs3414_buffer_setup_ops);
+ if (ret < 0)
+ return ret;
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ goto buffer_cleanup;
+
+ return 0;
+
+buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+ return ret;
+}
+
+static int tcs3414_powerdown(struct tcs3414_data *data)
+{
+ return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control & ~(TCS3414_CONTROL_POWER |
+ TCS3414_CONTROL_ADC_EN));
+}
+
+static int tcs3414_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ tcs3414_powerdown(iio_priv(indio_dev));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tcs3414_suspend(struct device *dev)
+{
+ struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return tcs3414_powerdown(data);
+}
+
+static int tcs3414_resume(struct device *dev)
+{
+ struct tcs3414_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL,
+ data->control);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume);
+
+static const struct i2c_device_id tcs3414_id[] = {
+ { "tcs3414", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tcs3414_id);
+
+static struct i2c_driver tcs3414_driver = {
+ .driver = {
+ .name = TCS3414_DRV_NAME,
+ .pm = &tcs3414_pm_ops,
+ .owner = THIS_MODULE,
+ },
+ .probe = tcs3414_probe,
+ .remove = tcs3414_remove,
+ .id_table = tcs3414_id,
+};
+module_i2c_driver(tcs3414_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TCS3414 digital color sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index 05a364c543f8..b2dba9e506ab 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -17,6 +17,16 @@ config AK8975
To compile this driver as a module, choose M here: the module
will be called ak8975.
+config AK09911
+ tristate "Asahi Kasei AK09911 3-axis Compass"
+ depends on I2C
+ help
+ Say yes here to build support for Asahi Kasei AK09911 3-Axis
+ Magnetometer.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ak09911.
+
config MAG3110
tristate "Freescale MAG3110 3-Axis Magnetometer"
depends on I2C
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index 0f5d3c985799..b91315e0b826 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -3,6 +3,7 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AK09911) += ak09911.o
obj-$(CONFIG_AK8975) += ak8975.o
obj-$(CONFIG_MAG3110) += mag3110.o
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
diff --git a/drivers/iio/magnetometer/ak09911.c b/drivers/iio/magnetometer/ak09911.c
new file mode 100644
index 000000000000..b2bc942ff6b8
--- /dev/null
+++ b/drivers/iio/magnetometer/ak09911.c
@@ -0,0 +1,326 @@
+/*
+ * AK09911 3-axis compass driver
+ * Copyright (c) 2014, 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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+#include <linux/iio/iio.h>
+
+#define AK09911_REG_WIA1 0x00
+#define AK09911_REG_WIA2 0x01
+#define AK09911_WIA1_VALUE 0x48
+#define AK09911_WIA2_VALUE 0x05
+
+#define AK09911_REG_ST1 0x10
+#define AK09911_REG_HXL 0x11
+#define AK09911_REG_HXH 0x12
+#define AK09911_REG_HYL 0x13
+#define AK09911_REG_HYH 0x14
+#define AK09911_REG_HZL 0x15
+#define AK09911_REG_HZH 0x16
+
+#define AK09911_REG_ASAX 0x60
+#define AK09911_REG_ASAY 0x61
+#define AK09911_REG_ASAZ 0x62
+
+#define AK09911_REG_CNTL1 0x30
+#define AK09911_REG_CNTL2 0x31
+#define AK09911_REG_CNTL3 0x32
+
+#define AK09911_MODE_SNG_MEASURE 0x01
+#define AK09911_MODE_SELF_TEST 0x10
+#define AK09911_MODE_FUSE_ACCESS 0x1F
+#define AK09911_MODE_POWERDOWN 0x00
+#define AK09911_RESET_DATA 0x01
+
+#define AK09911_REG_CNTL1 0x30
+#define AK09911_REG_CNTL2 0x31
+#define AK09911_REG_CNTL3 0x32
+
+#define AK09911_RAW_TO_GAUSS(asa) ((((asa) + 128) * 6000) / 256)
+
+#define AK09911_MAX_CONVERSION_TIMEOUT_MS 500
+#define AK09911_CONVERSION_DONE_POLL_TIME_MS 10
+
+struct ak09911_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ u8 asa[3];
+ long raw_to_gauss[3];
+};
+
+static const int ak09911_index_to_reg[] = {
+ AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL,
+};
+
+static int ak09911_set_mode(struct i2c_client *client, u8 mode)
+{
+ int ret;
+
+ switch (mode) {
+ case AK09911_MODE_SNG_MEASURE:
+ case AK09911_MODE_SELF_TEST:
+ case AK09911_MODE_FUSE_ACCESS:
+ case AK09911_MODE_POWERDOWN:
+ ret = i2c_smbus_write_byte_data(client,
+ AK09911_REG_CNTL2, mode);
+ if (ret < 0) {
+ dev_err(&client->dev, "set_mode error\n");
+ return ret;
+ }
+ /* After mode change wait atleast 100us */
+ usleep_range(100, 500);
+ break;
+ default:
+ dev_err(&client->dev,
+ "%s: Unknown mode(%d).", __func__, mode);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/* Get Sensitivity Adjustment value */
+static int ak09911_get_asa(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak09911_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS);
+ if (ret < 0)
+ return ret;
+
+ /* Get asa data and store in the device data. */
+ ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX,
+ 3, data->asa);
+ if (ret < 0) {
+ dev_err(&client->dev, "Not able to read asa data\n");
+ return ret;
+ }
+
+ ret = ak09911_set_mode(client, AK09911_MODE_POWERDOWN);
+ if (ret < 0)
+ return ret;
+
+ data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]);
+ data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]);
+ data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]);
+
+ return 0;
+}
+
+static int ak09911_verify_chip_id(struct i2c_client *client)
+{
+ u8 wia_val[2];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1,
+ 2, wia_val);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error reading WIA\n");
+ return ret;
+ }
+
+ dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]);
+
+ if (wia_val[0] != AK09911_WIA1_VALUE ||
+ wia_val[1] != AK09911_WIA2_VALUE) {
+ dev_err(&client->dev, "Device ak09911 not found\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int wait_conversion_complete_polled(struct ak09911_data *data)
+{
+ struct i2c_client *client = data->client;
+ u8 read_status;
+ u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS;
+ int ret;
+
+ /* Wait for the conversion to complete. */
+ while (timeout_ms) {
+ msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS);
+ ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1);
+ if (ret < 0) {
+ dev_err(&client->dev, "Error in reading ST1\n");
+ return ret;
+ }
+ read_status = ret & 0x01;
+ if (read_status)
+ break;
+ timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS;
+ }
+ if (!timeout_ms) {
+ dev_err(&client->dev, "Conversion timeout happened\n");
+ return -EIO;
+ }
+
+ return read_status;
+}
+
+static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val)
+{
+ struct ak09911_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ mutex_lock(&data->lock);
+
+ ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE);
+ if (ret < 0)
+ goto fn_exit;
+
+ ret = wait_conversion_complete_polled(data);
+ if (ret < 0)
+ goto fn_exit;
+
+ /* Read data */
+ ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]);
+ if (ret < 0) {
+ dev_err(&client->dev, "Read axis data fails\n");
+ goto fn_exit;
+ }
+
+ mutex_unlock(&data->lock);
+
+ /* Clamp to valid range. */
+ *val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13);
+
+ return IIO_VAL_INT;
+
+fn_exit:
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+static int ak09911_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ struct ak09911_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ return ak09911_read_axis(indio_dev, chan->address, val);
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = data->raw_to_gauss[chan->address];
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
+ return -EINVAL;
+}
+
+#define AK09911_CHANNEL(axis, index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ }
+
+static const struct iio_chan_spec ak09911_channels[] = {
+ AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2),
+};
+
+static const struct iio_info ak09911_info = {
+ .read_raw = &ak09911_read_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct acpi_device_id ak_acpi_match[] = {
+ {"AK009911", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
+
+static int ak09911_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct iio_dev *indio_dev;
+ struct ak09911_data *data;
+ const char *name;
+ int ret;
+
+ ret = ak09911_verify_chip_id(client);
+ if (ret) {
+ dev_err(&client->dev, "AK00911 not detected\n");
+ return -ENODEV;
+ }
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+
+ data->client = client;
+ mutex_init(&data->lock);
+
+ ret = ak09911_get_asa(client);
+ if (ret)
+ return ret;
+
+ if (id)
+ name = id->name;
+ else if (ACPI_HANDLE(&client->dev))
+ name = dev_name(&client->dev);
+ else
+ return -ENODEV;
+
+ dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->channels = ak09911_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ak09911_channels);
+ indio_dev->info = &ak09911_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = name;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id ak09911_id[] = {
+ {"ak09911", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak09911_id);
+
+static struct i2c_driver ak09911_driver = {
+ .driver = {
+ .name = "ak09911",
+ .acpi_match_table = ACPI_PTR(ak_acpi_match),
+ },
+ .probe = ak09911_probe,
+ .id_table = ak09911_id,
+};
+module_i2c_driver(ak09911_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("AK09911 Compass driver");
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index ea08313af0d2..a2357921d761 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -165,7 +165,7 @@ static int ak8975_setup_irq(struct ak8975_data *data)
else
irq = gpio_to_irq(data->eoc_gpio);
- rc = request_irq(irq, ak8975_irq_handler,
+ rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
dev_name(&client->dev), data);
if (rc < 0) {
@@ -513,21 +513,21 @@ static int ak8975_probe(struct i2c_client *client,
/* We may not have a GPIO based IRQ to scan, that is fine, we will
poll if so */
if (gpio_is_valid(eoc_gpio)) {
- err = gpio_request_one(eoc_gpio, GPIOF_IN, "ak_8975");
+ err = devm_gpio_request_one(&client->dev, eoc_gpio,
+ GPIOF_IN, "ak_8975");
if (err < 0) {
dev_err(&client->dev,
"failed to request GPIO %d, error %d\n",
eoc_gpio, err);
- goto exit;
+ return err;
}
}
/* Register with IIO */
- indio_dev = iio_device_alloc(sizeof(*data));
- if (indio_dev == NULL) {
- err = -ENOMEM;
- goto exit_gpio;
- }
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
@@ -542,17 +542,16 @@ static int ak8975_probe(struct i2c_client *client,
name = (char *) id->name;
} else if (ACPI_HANDLE(&client->dev))
name = ak8975_match_acpi_device(&client->dev, &data->chipset);
- else {
- err = -ENOSYS;
- goto exit_free_iio;
- }
+ else
+ return -ENOSYS;
+
dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
/* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client);
if (err < 0) {
dev_err(&client->dev, "AK8975 initialization fails\n");
- goto exit_free_iio;
+ return err;
}
data->client = client;
@@ -564,37 +563,9 @@ static int ak8975_probe(struct i2c_client *client,
indio_dev->info = &ak8975_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = name;
- err = iio_device_register(indio_dev);
+ err = devm_iio_device_register(&client->dev, indio_dev);
if (err < 0)
- goto exit_free_iio;
-
- return 0;
-
-exit_free_iio:
- iio_device_free(indio_dev);
- if (data->eoc_irq)
- free_irq(data->eoc_irq, data);
-exit_gpio:
- if (gpio_is_valid(eoc_gpio))
- gpio_free(eoc_gpio);
-exit:
- return err;
-}
-
-static int ak8975_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct ak8975_data *data = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- if (data->eoc_irq)
- free_irq(data->eoc_irq, data);
-
- if (gpio_is_valid(data->eoc_gpio))
- gpio_free(data->eoc_gpio);
-
- iio_device_free(indio_dev);
+ return err;
return 0;
}
@@ -621,7 +592,6 @@ static struct i2c_driver ak8975_driver = {
.acpi_match_table = ACPI_PTR(ak_acpi_match),
},
.probe = ak8975_probe,
- .remove = ak8975_remove,
.id_table = ak8975_id,
};
module_i2c_driver(ak8975_driver);
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index b2b0937d5133..3ec777a8f64e 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -35,6 +35,10 @@ enum magn_3d_channel {
CHANNEL_SCAN_INDEX_X,
CHANNEL_SCAN_INDEX_Y,
CHANNEL_SCAN_INDEX_Z,
+ CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP,
+ CHANNEL_SCAN_INDEX_NORTH_TRUE_TILT_COMP,
+ CHANNEL_SCAN_INDEX_NORTH_MAGN,
+ CHANNEL_SCAN_INDEX_NORTH_TRUE,
MAGN_3D_CHANNEL_MAX,
};
@@ -42,7 +46,12 @@ struct magn_3d_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX];
- u32 magn_val[MAGN_3D_CHANNEL_MAX];
+
+ /* dynamically sized array to hold sensor values */
+ u32 *iio_vals;
+ /* array of pointers to sensor value */
+ u32 *magn_val_addr[MAGN_3D_CHANNEL_MAX];
+
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
@@ -52,7 +61,11 @@ struct magn_3d_state {
static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = {
HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS,
HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS,
- HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS
+ HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS,
+ HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH,
+ HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH,
+ HID_USAGE_SENSOR_ORIENT_MAGN_NORTH,
+ HID_USAGE_SENSOR_ORIENT_TRUE_NORTH,
};
/* Channel definitions */
@@ -66,7 +79,6 @@ static const struct iio_chan_spec magn_3d_channels[] = {
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_X,
}, {
.type = IIO_MAGN,
.modified = 1,
@@ -76,7 +88,6 @@ static const struct iio_chan_spec magn_3d_channels[] = {
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_Y,
}, {
.type = IIO_MAGN,
.modified = 1,
@@ -86,7 +97,42 @@ static const struct iio_chan_spec magn_3d_channels[] = {
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_Z,
+ }, {
+ .type = IIO_ROT,
+ .modified = 1,
+ .channel2 = IIO_MOD_NORTH_MAGN_TILT_COMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
+ }, {
+ .type = IIO_ROT,
+ .modified = 1,
+ .channel2 = IIO_MOD_NORTH_TRUE_TILT_COMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
+ }, {
+ .type = IIO_ROT,
+ .modified = 1,
+ .channel2 = IIO_MOD_NORTH_MAGN,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
+ }, {
+ .type = IIO_ROT,
+ .modified = 1,
+ .channel2 = IIO_MOD_NORTH_TRUE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
}
};
@@ -126,8 +172,8 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
msleep_interruptible(poll_value * 2);
report_id =
- magn_state->magn[chan->scan_index].report_id;
- address = magn_3d_addresses[chan->scan_index];
+ magn_state->magn[chan->address].report_id;
+ address = magn_3d_addresses[chan->address];
if (report_id >= 0)
*val = sensor_hub_input_attr_get_raw_value(
magn_state->common_attributes.hsdev,
@@ -218,8 +264,8 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev,
dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
if (atomic_read(&magn_state->common_attributes.data_ready))
hid_sensor_push_data(indio_dev,
- magn_state->magn_val,
- sizeof(magn_state->magn_val));
+ magn_state->iio_vals,
+ sizeof(magn_state->iio_vals));
return 0;
}
@@ -233,52 +279,126 @@ static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct magn_3d_state *magn_state = iio_priv(indio_dev);
int offset;
- int ret = -EINVAL;
+ int ret = 0;
+ u32 *iio_val = NULL;
switch (usage_id) {
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS:
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS:
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS:
- offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS;
- magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] =
- *(u32 *)raw_data;
- ret = 0;
+ offset = (usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS)
+ + CHANNEL_SCAN_INDEX_X;
+ break;
+ case HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH:
+ case HID_USAGE_SENSOR_ORIENT_COMP_TRUE_NORTH:
+ case HID_USAGE_SENSOR_ORIENT_MAGN_NORTH:
+ case HID_USAGE_SENSOR_ORIENT_TRUE_NORTH:
+ offset = (usage_id - HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH)
+ + CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP;
break;
default:
- break;
+ return -EINVAL;
}
+ iio_val = magn_state->magn_val_addr[offset];
+
+ if (iio_val != NULL)
+ *iio_val = *((u32 *)raw_data);
+ else
+ ret = -EINVAL;
+
return ret;
}
/* Parse report which is specific to an usage id*/
static int magn_3d_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
- struct iio_chan_spec *channels,
+ struct iio_chan_spec **channels,
+ int *chan_count,
unsigned usage_id,
struct magn_3d_state *st)
{
- int ret;
int i;
+ int attr_count = 0;
+ struct iio_chan_spec *_channels;
+
+ /* Scan for each usage attribute supported */
+ for (i = 0; i < MAGN_3D_CHANNEL_MAX; i++) {
+ int status;
+ u32 address = magn_3d_addresses[i];
+
+ /* Check if usage attribute exists in the sensor hub device */
+ status = sensor_hub_input_get_attribute_info(hsdev,
+ HID_INPUT_REPORT,
+ usage_id,
+ address,
+ &(st->magn[i]));
+ if (!status)
+ attr_count++;
+ }
- for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
- ret = sensor_hub_input_get_attribute_info(hsdev,
- HID_INPUT_REPORT,
- usage_id,
- HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i,
- &st->magn[CHANNEL_SCAN_INDEX_X + i]);
- if (ret < 0)
- break;
- magn_3d_adjust_channel_bit_mask(channels,
- CHANNEL_SCAN_INDEX_X + i,
- st->magn[CHANNEL_SCAN_INDEX_X + i].size);
+ if (attr_count <= 0) {
+ dev_err(&pdev->dev,
+ "failed to find any supported usage attributes in report\n");
+ return -EINVAL;
}
- dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n",
+
+ dev_dbg(&pdev->dev, "magn_3d Found %d usage attributes\n",
+ attr_count);
+ dev_dbg(&pdev->dev, "magn_3d X: %x:%x Y: %x:%x Z: %x:%x\n",
st->magn[0].index,
st->magn[0].report_id,
st->magn[1].index, st->magn[1].report_id,
st->magn[2].index, st->magn[2].report_id);
+ /* Setup IIO channel array */
+ _channels = devm_kcalloc(&pdev->dev, attr_count,
+ sizeof(struct iio_chan_spec),
+ GFP_KERNEL);
+ if (!_channels) {
+ dev_err(&pdev->dev,
+ "failed to allocate space for iio channels\n");
+ return -ENOMEM;
+ }
+
+ st->iio_vals = devm_kcalloc(&pdev->dev, attr_count,
+ sizeof(u32),
+ GFP_KERNEL);
+ if (!st->iio_vals) {
+ dev_err(&pdev->dev,
+ "failed to allocate space for iio values array\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0, *chan_count = 0;
+ i < MAGN_3D_CHANNEL_MAX && *chan_count < attr_count;
+ i++){
+ if (st->magn[i].index >= 0) {
+ /* Setup IIO channel struct */
+ (_channels[*chan_count]) = magn_3d_channels[i];
+ (_channels[*chan_count]).scan_index = *chan_count;
+ (_channels[*chan_count]).address = i;
+
+ /* Set magn_val_addr to iio value address */
+ st->magn_val_addr[i] = &(st->iio_vals[*chan_count]);
+ magn_3d_adjust_channel_bit_mask(_channels,
+ *chan_count,
+ st->magn[i].size);
+ (*chan_count)++;
+ }
+ }
+
+ if (*chan_count <= 0) {
+ dev_err(&pdev->dev,
+ "failed to find any magnetic channels setup\n");
+ return -EINVAL;
+ }
+
+ *channels = _channels;
+
+ dev_dbg(&pdev->dev, "magn_3d Setup %d IIO channels\n",
+ *chan_count);
+
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_COMPASS_3D,
&st->magn[CHANNEL_SCAN_INDEX_X],
@@ -296,7 +416,7 @@ static int magn_3d_parse_report(struct platform_device *pdev,
st->common_attributes.sensitivity.report_id);
}
- return ret;
+ return 0;
}
/* Function to initialize the processing for usage id */
@@ -308,6 +428,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
struct magn_3d_state *magn_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
+ int chan_count = 0;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct magn_3d_state));
@@ -328,22 +449,16 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
return ret;
}
- channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
- GFP_KERNEL);
- if (!channels) {
- dev_err(&pdev->dev, "failed to duplicate channels\n");
- return -ENOMEM;
- }
-
- ret = magn_3d_parse_report(pdev, hsdev, channels,
+ ret = magn_3d_parse_report(pdev, hsdev,
+ &channels, &chan_count,
HID_USAGE_SENSOR_COMPASS_3D, magn_state);
if (ret) {
- dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ dev_err(&pdev->dev, "failed to parse report\n");
+ return ret;
}
indio_dev->channels = channels;
- indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels);
+ indio_dev->num_channels = chan_count;
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &magn_3d_info;
indio_dev->name = name;
@@ -353,7 +468,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
NULL, NULL);
if (ret) {
dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
+ return ret;
}
atomic_set(&magn_state->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
@@ -387,8 +502,6 @@ error_remove_trigger:
hid_sensor_remove_trigger(&magn_state->common_attributes);
error_unreg_buffer_funcs:
iio_triggered_buffer_cleanup(indio_dev);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}
@@ -403,7 +516,6 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(&magn_state->common_attributes);
iio_triggered_buffer_cleanup(indio_dev);
- kfree(indio_dev->channels);
return 0;
}
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 240a21dd0c61..a4b64130ac2f 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -299,6 +299,9 @@ static int st_magn_read_raw(struct iio_dev *indio_dev,
else
*val2 = mdata->current_fullscale->gain;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = mdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -316,6 +319,13 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2)
+ return -EINVAL;
+ mutex_lock(&indio_dev->mlock);
+ err = st_sensors_set_odr(indio_dev, val);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
default:
err = -EINVAL;
}
@@ -323,14 +333,12 @@ static int st_magn_write_raw(struct iio_dev *indio_dev,
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
static struct attribute *st_magn_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 892e0feeb5c1..689250058442 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -18,6 +18,27 @@
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_magn.h"
+#ifdef CONFIG_OF
+static const struct of_device_id st_magn_of_match[] = {
+ {
+ .compatible = "st,lsm303dlhc-magn",
+ .data = LSM303DLHC_MAGN_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm303dlm-magn",
+ .data = LSM303DLM_MAGN_DEV_NAME,
+ },
+ {
+ .compatible = "st,lis3mdl-magn",
+ .data = LIS3MDL_MAGN_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_magn_of_match);
+#else
+#define st_magn_of_match NULL
+#endif
+
static int st_magn_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -31,6 +52,7 @@ static int st_magn_i2c_probe(struct i2c_client *client,
mdata = iio_priv(indio_dev);
mdata->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_magn_of_match);
st_sensors_i2c_configure(indio_dev, client, mdata);
@@ -61,6 +83,7 @@ static struct i2c_driver st_magn_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-magn-i2c",
+ .of_match_table = of_match_ptr(st_magn_of_match),
},
.probe = st_magn_i2c_probe,
.remove = st_magn_i2c_remove,
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index ffac8ac1efca..15afbc919521 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -70,4 +70,14 @@ config IIO_ST_PRESS_SPI
depends on IIO_ST_PRESS
depends on IIO_ST_SENSORS_SPI
+config T5403
+ tristate "EPCOS T5403 digital barometric pressure sensor driver"
+ depends on I2C
+ help
+ Say yes here to build support for the EPCOS T5403 pressure sensor
+ connected via I2C.
+
+ To compile this driver as a module, choose M here: the module
+ will be called t5403.
+
endmenu
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index c53d2500737a..90a37e85cf21 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MPL3115) += mpl3115.o
obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
st_pressure-y := st_pressure_core.o
st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
+obj-$(CONFIG_T5403) += t5403.o
obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index cd7e01f3a93b..473d914ef470 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -307,6 +307,27 @@ static const struct st_sensors st_press_sensors[] = {
},
};
+static int st_press_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *ch,
+ int val,
+ int val2,
+ long mask)
+{
+ int err;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2)
+ return -EINVAL;
+ mutex_lock(&indio_dev->mlock);
+ err = st_sensors_set_odr(indio_dev, val);
+ mutex_unlock(&indio_dev->mlock);
+ return err;
+ default:
+ return -EINVAL;
+ }
+}
+
static int st_press_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *ch, int *val,
int *val2, long mask)
@@ -349,6 +370,9 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
}
return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = pdata->odr;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -357,12 +381,10 @@ read_error:
return err;
}
-static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static struct attribute *st_press_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
@@ -374,6 +396,7 @@ static const struct iio_info press_info = {
.driver_module = THIS_MODULE,
.attrs = &st_press_attribute_group,
.read_raw = &st_press_read_raw,
+ .write_raw = &st_press_write_raw,
};
#ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 3cd73e39b840..acaf165260bb 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -18,6 +18,27 @@
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_pressure.h"
+#ifdef CONFIG_OF
+static const struct of_device_id st_press_of_match[] = {
+ {
+ .compatible = "st,lps001wp-press",
+ .data = LPS001WP_PRESS_DEV_NAME,
+ },
+ {
+ .compatible = "st,lps25h-press",
+ .data = LPS25H_PRESS_DEV_NAME,
+ },
+ {
+ .compatible = "st,lps331ap-press",
+ .data = LPS331AP_PRESS_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_press_of_match);
+#else
+#define st_press_of_match NULL
+#endif
+
static int st_press_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -31,6 +52,7 @@ static int st_press_i2c_probe(struct i2c_client *client,
pdata = iio_priv(indio_dev);
pdata->dev = &client->dev;
+ st_sensors_of_i2c_probe(client, st_press_of_match);
st_sensors_i2c_configure(indio_dev, client, pdata);
@@ -60,6 +82,7 @@ static struct i2c_driver st_press_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-press-i2c",
+ .of_match_table = of_match_ptr(st_press_of_match),
},
.probe = st_press_i2c_probe,
.remove = st_press_i2c_remove,
diff --git a/drivers/iio/pressure/t5403.c b/drivers/iio/pressure/t5403.c
new file mode 100644
index 000000000000..e11cd3938d67
--- /dev/null
+++ b/drivers/iio/pressure/t5403.c
@@ -0,0 +1,275 @@
+/*
+ * t5403.c - Support for EPCOS T5403 pressure/temperature sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x77)
+ *
+ * TODO: end-of-conversion irq
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+
+#define T5403_DATA 0xf5 /* data, LSB first, 16 bit */
+#define T5403_CALIB_DATA 0x8e /* 10 calibration coeff., LSB first, 16 bit */
+#define T5403_SLAVE_ADDR 0x88 /* I2C slave address, 0x77 */
+#define T5403_COMMAND 0xf1
+
+/* command bits */
+#define T5403_MODE_SHIFT 3 /* conversion time: 2, 8, 16, 66 ms */
+#define T5403_PT BIT(1) /* 0 .. pressure, 1 .. temperature measurement */
+#define T5403_SCO BIT(0) /* start conversion */
+
+#define T5403_MODE_LOW 0
+#define T5403_MODE_STANDARD 1
+#define T5403_MODE_HIGH 2
+#define T5403_MODE_ULTRA_HIGH 3
+
+#define T5403_I2C_MASK (~BIT(7))
+#define T5403_I2C_ADDR 0x77
+
+static const int t5403_pressure_conv_ms[] = {2, 8, 16, 66};
+
+struct t5403_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ int mode;
+ __le16 c[10];
+};
+
+#define T5403_C_U16(i) le16_to_cpu(data->c[(i) - 1])
+#define T5403_C(i) sign_extend32(T5403_C_U16(i), 15)
+
+static int t5403_read(struct t5403_data *data, bool pressure)
+{
+ int wait_time = 3; /* wakeup time in ms */
+
+ int ret = i2c_smbus_write_byte_data(data->client, T5403_COMMAND,
+ (pressure ? (data->mode << T5403_MODE_SHIFT) : T5403_PT) |
+ T5403_SCO);
+ if (ret < 0)
+ return ret;
+
+ wait_time += pressure ? t5403_pressure_conv_ms[data->mode] : 2;
+
+ msleep(wait_time);
+
+ return i2c_smbus_read_word_data(data->client, T5403_DATA);
+}
+
+static int t5403_comp_pressure(struct t5403_data *data, int *val, int *val2)
+{
+ int ret;
+ s16 t_r;
+ u16 p_r;
+ s32 S, O, X;
+
+ mutex_lock(&data->lock);
+
+ ret = t5403_read(data, false);
+ if (ret < 0)
+ goto done;
+ t_r = ret;
+
+ ret = t5403_read(data, true);
+ if (ret < 0)
+ goto done;
+ p_r = ret;
+
+ /* see EPCOS application note */
+ S = T5403_C_U16(3) + (s32) T5403_C_U16(4) * t_r / 0x20000 +
+ T5403_C(5) * t_r / 0x8000 * t_r / 0x80000 +
+ T5403_C(9) * t_r / 0x8000 * t_r / 0x8000 * t_r / 0x10000;
+
+ O = T5403_C(6) * 0x4000 + T5403_C(7) * t_r / 8 +
+ T5403_C(8) * t_r / 0x8000 * t_r / 16 +
+ T5403_C(9) * t_r / 0x8000 * t_r / 0x10000 * t_r;
+
+ X = (S * p_r + O) / 0x4000;
+
+ X += ((X - 75000) * (X - 75000) / 0x10000 - 9537) *
+ T5403_C(10) / 0x10000;
+
+ *val = X / 1000;
+ *val2 = (X % 1000) * 1000;
+
+done:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static int t5403_comp_temp(struct t5403_data *data, int *val)
+{
+ int ret;
+ s16 t_r;
+
+ mutex_lock(&data->lock);
+ ret = t5403_read(data, false);
+ if (ret < 0)
+ goto done;
+ t_r = ret;
+
+ /* see EPCOS application note */
+ *val = ((s32) T5403_C_U16(1) * t_r / 0x100 +
+ (s32) T5403_C_U16(2) * 0x40) * 1000 / 0x10000;
+
+done:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static int t5403_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct t5403_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ ret = t5403_comp_pressure(data, val, val2);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_TEMP:
+ ret = t5403_comp_temp(data, val);
+ if (ret < 0)
+ return ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
+ *val2 = t5403_pressure_conv_ms[data->mode] * 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int t5403_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct t5403_data *data = iio_priv(indio_dev);
+ int i;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(t5403_pressure_conv_ms); i++)
+ if (val2 == t5403_pressure_conv_ms[i] * 1000) {
+ mutex_lock(&data->lock);
+ data->mode = i;
+ mutex_unlock(&data->lock);
+ return 0;
+ }
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_chan_spec t5403_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ },
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+};
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.002 0.008 0.016 0.066");
+
+static struct attribute *t5403_attributes[] = {
+ &iio_const_attr_integration_time_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group t5403_attribute_group = {
+ .attrs = t5403_attributes,
+};
+
+static const struct iio_info t5403_info = {
+ .read_raw = &t5403_read_raw,
+ .write_raw = &t5403_write_raw,
+ .attrs = &t5403_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int t5403_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct t5403_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
+
+ ret = i2c_smbus_read_byte_data(client, T5403_SLAVE_ADDR);
+ if (ret < 0)
+ return ret;
+ if ((ret & T5403_I2C_MASK) != T5403_I2C_ADDR)
+ return -ENODEV;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+
+ i2c_set_clientdata(client, indio_dev);
+ indio_dev->info = &t5403_info;
+ indio_dev->name = id->name;
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = t5403_channels;
+ indio_dev->num_channels = ARRAY_SIZE(t5403_channels);
+
+ data->mode = T5403_MODE_STANDARD;
+
+ ret = i2c_smbus_read_i2c_block_data(data->client, T5403_CALIB_DATA,
+ sizeof(data->c), (u8 *) data->c);
+ if (ret < 0)
+ return ret;
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id t5403_id[] = {
+ { "t5403", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, t5403_id);
+
+static struct i2c_driver t5403_driver = {
+ .driver = {
+ .name = "t5403",
+ },
+ .probe = t5403_probe,
+ .id_table = t5403_id,
+};
+module_i2c_driver(t5403_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("EPCOS T5403 pressure/temperature sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index bf677bfe8eb2..5e780ef206f3 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -232,7 +232,7 @@ static void as3935_event_work(struct work_struct *work)
switch (val) {
case AS3935_EVENT_INT:
- iio_trigger_poll(st->trig, iio_get_time_ns());
+ iio_trigger_poll(st->trig);
break;
case AS3935_NOISE_INT:
dev_warn(&st->spi->dev, "noise level is too high");
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c
index 02577ec54c6b..7a149a7822bc 100644
--- a/drivers/iio/trigger/iio-trig-interrupt.c
+++ b/drivers/iio/trigger/iio-trig-interrupt.c
@@ -24,8 +24,7 @@ struct iio_interrupt_trigger_info {
static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private)
{
- /* Timestamp not currently provided */
- iio_trigger_poll(private, 0);
+ iio_trigger_poll(private);
return IRQ_HANDLED;
}
diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c
index 15e3b850f513..254c7e906127 100644
--- a/drivers/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/iio/trigger/iio-trig-sysfs.c
@@ -96,7 +96,7 @@ static void iio_sysfs_trigger_work(struct irq_work *work)
struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig,
work);
- iio_trigger_poll(trig->trig, 0);
+ iio_trigger_poll(trig->trig);
}
static ssize_t iio_sysfs_trigger_poll(struct device *dev,
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 2bc7f5af64f4..f6d29614cb01 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -94,14 +94,14 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
port_priv = ib_get_agent_port(device, port_num);
if (!port_priv) {
- printk(KERN_ERR SPFX "Unable to find port agent\n");
+ dev_err(&device->dev, "Unable to find port agent\n");
return;
}
agent = port_priv->agent[qpn];
ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
if (IS_ERR(ah)) {
- printk(KERN_ERR SPFX "ib_create_ah_from_wc error %ld\n",
+ dev_err(&device->dev, "ib_create_ah_from_wc error %ld\n",
PTR_ERR(ah));
return;
}
@@ -110,7 +110,7 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,
GFP_KERNEL);
if (IS_ERR(send_buf)) {
- printk(KERN_ERR SPFX "ib_create_send_mad error\n");
+ dev_err(&device->dev, "ib_create_send_mad error\n");
goto err1;
}
@@ -125,7 +125,7 @@ void agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
}
if (ib_post_send_mad(send_buf, NULL)) {
- printk(KERN_ERR SPFX "ib_post_send_mad error\n");
+ dev_err(&device->dev, "ib_post_send_mad error\n");
goto err2;
}
return;
@@ -151,7 +151,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
/* Create new device info */
port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
if (!port_priv) {
- printk(KERN_ERR SPFX "No memory for ib_agent_port_private\n");
+ dev_err(&device->dev, "No memory for ib_agent_port_private\n");
ret = -ENOMEM;
goto error1;
}
@@ -161,7 +161,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
port_priv->agent[0] = ib_register_mad_agent(device, port_num,
IB_QPT_SMI, NULL, 0,
&agent_send_handler,
- NULL, NULL);
+ NULL, NULL, 0);
if (IS_ERR(port_priv->agent[0])) {
ret = PTR_ERR(port_priv->agent[0]);
goto error2;
@@ -172,7 +172,7 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
port_priv->agent[1] = ib_register_mad_agent(device, port_num,
IB_QPT_GSI, NULL, 0,
&agent_send_handler,
- NULL, NULL);
+ NULL, NULL, 0);
if (IS_ERR(port_priv->agent[1])) {
ret = PTR_ERR(port_priv->agent[1]);
goto error3;
@@ -202,7 +202,7 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
port_priv = __ib_get_agent_port(device, port_num);
if (port_priv == NULL) {
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
- printk(KERN_ERR SPFX "Port %d not found\n", port_num);
+ dev_err(&device->dev, "Port %d not found\n", port_num);
return -ENODEV;
}
list_del(&port_priv->port_list);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index c3239170d8b7..e28a494e2a3a 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3753,7 +3753,7 @@ static void cm_add_one(struct ib_device *ib_device)
struct cm_port *port;
struct ib_mad_reg_req reg_req = {
.mgmt_class = IB_MGMT_CLASS_CM,
- .mgmt_class_version = IB_CM_CLASS_VERSION
+ .mgmt_class_version = IB_CM_CLASS_VERSION,
};
struct ib_port_modify port_modify = {
.set_port_cap_mask = IB_PORT_CM_SUP
@@ -3801,7 +3801,8 @@ static void cm_add_one(struct ib_device *ib_device)
0,
cm_send_handler,
cm_recv_handler,
- port);
+ port,
+ 0);
if (IS_ERR(port->mad_agent))
goto error2;
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index 3d2e489ab732..ff9163dc1596 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -46,6 +46,7 @@
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/sysctl.h>
#include <rdma/iw_cm.h>
#include <rdma/ib_addr.h>
@@ -65,6 +66,20 @@ struct iwcm_work {
struct list_head free_list;
};
+static unsigned int default_backlog = 256;
+
+static struct ctl_table_header *iwcm_ctl_table_hdr;
+static struct ctl_table iwcm_ctl_table[] = {
+ {
+ .procname = "default_backlog",
+ .data = &default_backlog,
+ .maxlen = sizeof(default_backlog),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ { }
+};
+
/*
* The following services provide a mechanism for pre-allocating iwcm_work
* elements. The design pre-allocates them based on the cm_id type:
@@ -425,6 +440,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog)
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
+ if (!backlog)
+ backlog = default_backlog;
+
ret = alloc_work_entries(cm_id_priv, backlog);
if (ret)
return ret;
@@ -1030,11 +1048,20 @@ static int __init iw_cm_init(void)
if (!iwcm_wq)
return -ENOMEM;
+ iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm",
+ iwcm_ctl_table);
+ if (!iwcm_ctl_table_hdr) {
+ pr_err("iw_cm: couldn't register sysctl paths\n");
+ destroy_workqueue(iwcm_wq);
+ return -ENOMEM;
+ }
+
return 0;
}
static void __exit iw_cm_cleanup(void)
{
+ unregister_net_sysctl_table(iwcm_ctl_table_hdr);
destroy_workqueue(iwcm_wq);
}
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index ab31f136d04b..74c30f4c557e 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -33,6 +33,9 @@
* SOFTWARE.
*
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -195,7 +198,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
u8 rmpp_version,
ib_mad_send_handler send_handler,
ib_mad_recv_handler recv_handler,
- void *context)
+ void *context,
+ u32 registration_flags)
{
struct ib_mad_port_private *port_priv;
struct ib_mad_agent *ret = ERR_PTR(-EINVAL);
@@ -211,68 +215,109 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
/* Validate parameters */
qpn = get_spl_qp_index(qp_type);
- if (qpn == -1)
+ if (qpn == -1) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: invalid QP Type %d\n",
+ qp_type);
goto error1;
+ }
- if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION)
+ if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: invalid RMPP Version %u\n",
+ rmpp_version);
goto error1;
+ }
/* Validate MAD registration request if supplied */
if (mad_reg_req) {
- if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION)
+ if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: invalid Class Version %u\n",
+ mad_reg_req->mgmt_class_version);
goto error1;
- if (!recv_handler)
+ }
+ if (!recv_handler) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: no recv_handler\n");
goto error1;
+ }
if (mad_reg_req->mgmt_class >= MAX_MGMT_CLASS) {
/*
* IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE is the only
* one in this range currently allowed
*/
if (mad_reg_req->mgmt_class !=
- IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+ IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: Invalid Mgmt Class 0x%x\n",
+ mad_reg_req->mgmt_class);
goto error1;
+ }
} else if (mad_reg_req->mgmt_class == 0) {
/*
* Class 0 is reserved in IBA and is used for
* aliasing of IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
*/
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: Invalid Mgmt Class 0\n");
goto error1;
} else if (is_vendor_class(mad_reg_req->mgmt_class)) {
/*
* If class is in "new" vendor range,
* ensure supplied OUI is not zero
*/
- if (!is_vendor_oui(mad_reg_req->oui))
+ if (!is_vendor_oui(mad_reg_req->oui)) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: No OUI specified for class 0x%x\n",
+ mad_reg_req->mgmt_class);
goto error1;
+ }
}
/* Make sure class supplied is consistent with RMPP */
if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
- if (rmpp_version)
+ if (rmpp_version) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: RMPP version for non-RMPP class 0x%x\n",
+ mad_reg_req->mgmt_class);
goto error1;
+ }
}
+
/* Make sure class supplied is consistent with QP type */
if (qp_type == IB_QPT_SMI) {
if ((mad_reg_req->mgmt_class !=
IB_MGMT_CLASS_SUBN_LID_ROUTED) &&
(mad_reg_req->mgmt_class !=
- IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))
+ IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: Invalid SM QP type: class 0x%x\n",
+ mad_reg_req->mgmt_class);
goto error1;
+ }
} else {
if ((mad_reg_req->mgmt_class ==
IB_MGMT_CLASS_SUBN_LID_ROUTED) ||
(mad_reg_req->mgmt_class ==
- IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))
+ IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: Invalid GS QP type: class 0x%x\n",
+ mad_reg_req->mgmt_class);
goto error1;
+ }
}
} else {
/* No registration request supplied */
if (!send_handler)
goto error1;
+ if (registration_flags & IB_MAD_USER_RMPP)
+ goto error1;
}
/* Validate device and port */
port_priv = ib_get_mad_port(device, port_num);
if (!port_priv) {
+ dev_notice(&device->dev, "ib_register_mad_agent: Invalid port\n");
ret = ERR_PTR(-ENODEV);
goto error1;
}
@@ -280,6 +325,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
/* Verify the QP requested is supported. For example, Ethernet devices
* will not have QP0 */
if (!port_priv->qp_info[qpn].qp) {
+ dev_notice(&device->dev,
+ "ib_register_mad_agent: QP %d not supported\n", qpn);
ret = ERR_PTR(-EPROTONOSUPPORT);
goto error1;
}
@@ -316,6 +363,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
mad_agent_priv->agent.context = context;
mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp;
mad_agent_priv->agent.port_num = port_num;
+ mad_agent_priv->agent.flags = registration_flags;
spin_lock_init(&mad_agent_priv->lock);
INIT_LIST_HEAD(&mad_agent_priv->send_list);
INIT_LIST_HEAD(&mad_agent_priv->wait_list);
@@ -706,7 +754,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
smi_handle_dr_smp_send(smp, device->node_type, port_num) ==
IB_SMI_DISCARD) {
ret = -EINVAL;
- printk(KERN_ERR PFX "Invalid directed route\n");
+ dev_err(&device->dev, "Invalid directed route\n");
goto out;
}
@@ -718,7 +766,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
local = kmalloc(sizeof *local, GFP_ATOMIC);
if (!local) {
ret = -ENOMEM;
- printk(KERN_ERR PFX "No memory for ib_mad_local_private\n");
+ dev_err(&device->dev, "No memory for ib_mad_local_private\n");
goto out;
}
local->mad_priv = NULL;
@@ -726,7 +774,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_ATOMIC);
if (!mad_priv) {
ret = -ENOMEM;
- printk(KERN_ERR PFX "No memory for local response MAD\n");
+ dev_err(&device->dev, "No memory for local response MAD\n");
kfree(local);
goto out;
}
@@ -837,9 +885,9 @@ static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr,
for (left = send_buf->data_len + pad; left > 0; left -= seg_size) {
seg = kmalloc(sizeof (*seg) + seg_size, gfp_mask);
if (!seg) {
- printk(KERN_ERR "alloc_send_rmpp_segs: RMPP mem "
- "alloc failed for len %zd, gfp %#x\n",
- sizeof (*seg) + seg_size, gfp_mask);
+ dev_err(&send_buf->mad_agent->device->dev,
+ "alloc_send_rmpp_segs: RMPP mem alloc failed for len %zd, gfp %#x\n",
+ sizeof (*seg) + seg_size, gfp_mask);
free_send_rmpp_list(send_wr);
return -ENOMEM;
}
@@ -862,6 +910,12 @@ static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr,
return 0;
}
+int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent)
+{
+ return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP);
+}
+EXPORT_SYMBOL(ib_mad_kernel_rmpp_agent);
+
struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
u32 remote_qpn, u16 pkey_index,
int rmpp_active,
@@ -878,10 +932,12 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
pad = get_pad_size(hdr_len, data_len);
message_size = hdr_len + data_len + pad;
- if ((!mad_agent->rmpp_version &&
- (rmpp_active || message_size > sizeof(struct ib_mad))) ||
- (!rmpp_active && message_size > sizeof(struct ib_mad)))
- return ERR_PTR(-EINVAL);
+ if (ib_mad_kernel_rmpp_agent(mad_agent)) {
+ if (!rmpp_active && message_size > sizeof(struct ib_mad))
+ return ERR_PTR(-EINVAL);
+ } else
+ if (rmpp_active || message_size > sizeof(struct ib_mad))
+ return ERR_PTR(-EINVAL);
size = rmpp_active ? hdr_len : sizeof(struct ib_mad);
buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask);
@@ -1135,7 +1191,7 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
&mad_agent_priv->send_list);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
- if (mad_agent_priv->agent.rmpp_version) {
+ if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
ret = ib_send_rmpp_mad(mad_send_wr);
if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED)
ret = ib_send_mad(mad_send_wr);
@@ -1199,7 +1255,8 @@ EXPORT_SYMBOL(ib_redirect_mad_qp);
int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
struct ib_wc *wc)
{
- printk(KERN_ERR PFX "ib_process_mad_wc() not implemented yet\n");
+ dev_err(&mad_agent->device->dev,
+ "ib_process_mad_wc() not implemented yet\n");
return 0;
}
EXPORT_SYMBOL(ib_process_mad_wc);
@@ -1211,7 +1268,7 @@ static int method_in_use(struct ib_mad_mgmt_method_table **method,
for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) {
if ((*method)->agent[i]) {
- printk(KERN_ERR PFX "Method %d already in use\n", i);
+ pr_err("Method %d already in use\n", i);
return -EINVAL;
}
}
@@ -1223,8 +1280,7 @@ static int allocate_method_table(struct ib_mad_mgmt_method_table **method)
/* Allocate management method table */
*method = kzalloc(sizeof **method, GFP_ATOMIC);
if (!*method) {
- printk(KERN_ERR PFX "No memory for "
- "ib_mad_mgmt_method_table\n");
+ pr_err("No memory for ib_mad_mgmt_method_table\n");
return -ENOMEM;
}
@@ -1319,8 +1375,8 @@ static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
/* Allocate management class table for "new" class version */
*class = kzalloc(sizeof **class, GFP_ATOMIC);
if (!*class) {
- printk(KERN_ERR PFX "No memory for "
- "ib_mad_mgmt_class_table\n");
+ dev_err(&agent_priv->agent.device->dev,
+ "No memory for ib_mad_mgmt_class_table\n");
ret = -ENOMEM;
goto error1;
}
@@ -1386,8 +1442,8 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,
/* Allocate mgmt vendor class table for "new" class version */
vendor = kzalloc(sizeof *vendor, GFP_ATOMIC);
if (!vendor) {
- printk(KERN_ERR PFX "No memory for "
- "ib_mad_mgmt_vendor_class_table\n");
+ dev_err(&agent_priv->agent.device->dev,
+ "No memory for ib_mad_mgmt_vendor_class_table\n");
goto error1;
}
@@ -1397,8 +1453,8 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,
/* Allocate table for this management vendor class */
vendor_class = kzalloc(sizeof *vendor_class, GFP_ATOMIC);
if (!vendor_class) {
- printk(KERN_ERR PFX "No memory for "
- "ib_mad_mgmt_vendor_class\n");
+ dev_err(&agent_priv->agent.device->dev,
+ "No memory for ib_mad_mgmt_vendor_class\n");
goto error2;
}
@@ -1429,7 +1485,7 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,
goto check_in_use;
}
}
- printk(KERN_ERR PFX "All OUI slots in use\n");
+ dev_err(&agent_priv->agent.device->dev, "All OUI slots in use\n");
goto error3;
check_in_use:
@@ -1640,9 +1696,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
if (mad_agent->agent.recv_handler)
atomic_inc(&mad_agent->refcount);
else {
- printk(KERN_NOTICE PFX "No receive handler for client "
- "%p on port %d\n",
- &mad_agent->agent, port_priv->port_num);
+ dev_notice(&port_priv->device->dev,
+ "No receive handler for client %p on port %d\n",
+ &mad_agent->agent, port_priv->port_num);
mad_agent = NULL;
}
}
@@ -1658,8 +1714,8 @@ static int validate_mad(struct ib_mad *mad, u32 qp_num)
/* Make sure MAD base version is understood */
if (mad->mad_hdr.base_version != IB_MGMT_BASE_VERSION) {
- printk(KERN_ERR PFX "MAD received with unsupported base "
- "version %d\n", mad->mad_hdr.base_version);
+ pr_err("MAD received with unsupported base version %d\n",
+ mad->mad_hdr.base_version);
goto out;
}
@@ -1685,6 +1741,7 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv,
rmpp_mad = (struct ib_rmpp_mad *)mad_hdr;
return !mad_agent_priv->agent.rmpp_version ||
+ !ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) ||
!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
IB_MGMT_RMPP_FLAG_ACTIVE) ||
(rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA);
@@ -1812,7 +1869,7 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
- if (mad_agent_priv->agent.rmpp_version) {
+ if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
mad_recv_wc);
if (!mad_recv_wc) {
@@ -1827,23 +1884,39 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
if (!mad_send_wr) {
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
- ib_free_recv_mad(mad_recv_wc);
- deref_mad_agent(mad_agent_priv);
- return;
- }
- ib_mark_mad_done(mad_send_wr);
- spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+ if (!ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)
+ && ib_is_mad_class_rmpp(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class)
+ && (ib_get_rmpp_flags(&((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr)
+ & IB_MGMT_RMPP_FLAG_ACTIVE)) {
+ /* user rmpp is in effect
+ * and this is an active RMPP MAD
+ */
+ mad_recv_wc->wc->wr_id = 0;
+ mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
+ mad_recv_wc);
+ atomic_dec(&mad_agent_priv->refcount);
+ } else {
+ /* not user rmpp, revert to normal behavior and
+ * drop the mad */
+ ib_free_recv_mad(mad_recv_wc);
+ deref_mad_agent(mad_agent_priv);
+ return;
+ }
+ } else {
+ ib_mark_mad_done(mad_send_wr);
+ spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
- /* Defined behavior is to complete response before request */
- mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
- mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
- mad_recv_wc);
- atomic_dec(&mad_agent_priv->refcount);
+ /* Defined behavior is to complete response before request */
+ mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf;
+ mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
+ mad_recv_wc);
+ atomic_dec(&mad_agent_priv->refcount);
- mad_send_wc.status = IB_WC_SUCCESS;
- mad_send_wc.vendor_err = 0;
- mad_send_wc.send_buf = &mad_send_wr->send_buf;
- ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
+ mad_send_wc.status = IB_WC_SUCCESS;
+ mad_send_wc.vendor_err = 0;
+ mad_send_wc.send_buf = &mad_send_wr->send_buf;
+ ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
+ }
} else {
mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
mad_recv_wc);
@@ -1911,8 +1984,8 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
if (!response) {
- printk(KERN_ERR PFX "ib_mad_recv_done_handler no memory "
- "for response buffer\n");
+ dev_err(&port_priv->device->dev,
+ "ib_mad_recv_done_handler no memory for response buffer\n");
goto out;
}
@@ -2083,7 +2156,7 @@ void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
mad_agent_priv = mad_send_wr->mad_agent_priv;
spin_lock_irqsave(&mad_agent_priv->lock, flags);
- if (mad_agent_priv->agent.rmpp_version) {
+ if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc);
if (ret == IB_RMPP_RESULT_CONSUMED)
goto done;
@@ -2176,7 +2249,8 @@ retry:
ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr,
&bad_send_wr);
if (ret) {
- printk(KERN_ERR PFX "ib_post_send failed: %d\n", ret);
+ dev_err(&port_priv->device->dev,
+ "ib_post_send failed: %d\n", ret);
mad_send_wr = queued_send_wr;
wc->status = IB_WC_LOC_QP_OP_ERR;
goto retry;
@@ -2248,8 +2322,9 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv,
IB_QP_STATE | IB_QP_CUR_STATE);
kfree(attr);
if (ret)
- printk(KERN_ERR PFX "mad_error_handler - "
- "ib_modify_qp to RTS : %d\n", ret);
+ dev_err(&port_priv->device->dev,
+ "mad_error_handler - ib_modify_qp to RTS : %d\n",
+ ret);
else
mark_sends_for_retry(qp_info);
}
@@ -2408,7 +2483,8 @@ static void local_completions(struct work_struct *work)
if (local->mad_priv) {
recv_mad_agent = local->recv_mad_agent;
if (!recv_mad_agent) {
- printk(KERN_ERR PFX "No receive MAD agent for local completion\n");
+ dev_err(&mad_agent_priv->agent.device->dev,
+ "No receive MAD agent for local completion\n");
free_mad = 1;
goto local_send_completion;
}
@@ -2476,7 +2552,7 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
- if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
+ if (ib_mad_kernel_rmpp_agent(&mad_send_wr->mad_agent_priv->agent)) {
ret = ib_retry_rmpp(mad_send_wr);
switch (ret) {
case IB_RMPP_RESULT_UNHANDLED:
@@ -2589,7 +2665,8 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
} else {
mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
if (!mad_priv) {
- printk(KERN_ERR PFX "No memory for receive buffer\n");
+ dev_err(&qp_info->port_priv->device->dev,
+ "No memory for receive buffer\n");
ret = -ENOMEM;
break;
}
@@ -2625,7 +2702,8 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
sizeof mad_priv->header,
DMA_FROM_DEVICE);
kmem_cache_free(ib_mad_cache, mad_priv);
- printk(KERN_ERR PFX "ib_post_recv failed: %d\n", ret);
+ dev_err(&qp_info->port_priv->device->dev,
+ "ib_post_recv failed: %d\n", ret);
break;
}
} while (post);
@@ -2681,7 +2759,8 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
attr = kmalloc(sizeof *attr, GFP_KERNEL);
if (!attr) {
- printk(KERN_ERR PFX "Couldn't kmalloc ib_qp_attr\n");
+ dev_err(&port_priv->device->dev,
+ "Couldn't kmalloc ib_qp_attr\n");
return -ENOMEM;
}
@@ -2705,16 +2784,18 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
ret = ib_modify_qp(qp, attr, IB_QP_STATE |
IB_QP_PKEY_INDEX | IB_QP_QKEY);
if (ret) {
- printk(KERN_ERR PFX "Couldn't change QP%d state to "
- "INIT: %d\n", i, ret);
+ dev_err(&port_priv->device->dev,
+ "Couldn't change QP%d state to INIT: %d\n",
+ i, ret);
goto out;
}
attr->qp_state = IB_QPS_RTR;
ret = ib_modify_qp(qp, attr, IB_QP_STATE);
if (ret) {
- printk(KERN_ERR PFX "Couldn't change QP%d state to "
- "RTR: %d\n", i, ret);
+ dev_err(&port_priv->device->dev,
+ "Couldn't change QP%d state to RTR: %d\n",
+ i, ret);
goto out;
}
@@ -2722,16 +2803,18 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
attr->sq_psn = IB_MAD_SEND_Q_PSN;
ret = ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_SQ_PSN);
if (ret) {
- printk(KERN_ERR PFX "Couldn't change QP%d state to "
- "RTS: %d\n", i, ret);
+ dev_err(&port_priv->device->dev,
+ "Couldn't change QP%d state to RTS: %d\n",
+ i, ret);
goto out;
}
}
ret = ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP);
if (ret) {
- printk(KERN_ERR PFX "Failed to request completion "
- "notification: %d\n", ret);
+ dev_err(&port_priv->device->dev,
+ "Failed to request completion notification: %d\n",
+ ret);
goto out;
}
@@ -2741,7 +2824,8 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
ret = ib_mad_post_receive_mads(&port_priv->qp_info[i], NULL);
if (ret) {
- printk(KERN_ERR PFX "Couldn't post receive WRs\n");
+ dev_err(&port_priv->device->dev,
+ "Couldn't post receive WRs\n");
goto out;
}
}
@@ -2755,7 +2839,8 @@ static void qp_event_handler(struct ib_event *event, void *qp_context)
struct ib_mad_qp_info *qp_info = qp_context;
/* It's worse than that! He's dead, Jim! */
- printk(KERN_ERR PFX "Fatal error (%d) on MAD QP (%d)\n",
+ dev_err(&qp_info->port_priv->device->dev,
+ "Fatal error (%d) on MAD QP (%d)\n",
event->event, qp_info->qp->qp_num);
}
@@ -2801,8 +2886,9 @@ static int create_mad_qp(struct ib_mad_qp_info *qp_info,
qp_init_attr.event_handler = qp_event_handler;
qp_info->qp = ib_create_qp(qp_info->port_priv->pd, &qp_init_attr);
if (IS_ERR(qp_info->qp)) {
- printk(KERN_ERR PFX "Couldn't create ib_mad QP%d\n",
- get_spl_qp_index(qp_type));
+ dev_err(&qp_info->port_priv->device->dev,
+ "Couldn't create ib_mad QP%d\n",
+ get_spl_qp_index(qp_type));
ret = PTR_ERR(qp_info->qp);
goto error;
}
@@ -2840,7 +2926,7 @@ static int ib_mad_port_open(struct ib_device *device,
/* Create new device info */
port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
if (!port_priv) {
- printk(KERN_ERR PFX "No memory for ib_mad_port_private\n");
+ dev_err(&device->dev, "No memory for ib_mad_port_private\n");
return -ENOMEM;
}
@@ -2860,21 +2946,21 @@ static int ib_mad_port_open(struct ib_device *device,
ib_mad_thread_completion_handler,
NULL, port_priv, cq_size, 0);
if (IS_ERR(port_priv->cq)) {
- printk(KERN_ERR PFX "Couldn't create ib_mad CQ\n");
+ dev_err(&device->dev, "Couldn't create ib_mad CQ\n");
ret = PTR_ERR(port_priv->cq);
goto error3;
}
port_priv->pd = ib_alloc_pd(device);
if (IS_ERR(port_priv->pd)) {
- printk(KERN_ERR PFX "Couldn't create ib_mad PD\n");
+ dev_err(&device->dev, "Couldn't create ib_mad PD\n");
ret = PTR_ERR(port_priv->pd);
goto error4;
}
port_priv->mr = ib_get_dma_mr(port_priv->pd, IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(port_priv->mr)) {
- printk(KERN_ERR PFX "Couldn't get ib_mad DMA MR\n");
+ dev_err(&device->dev, "Couldn't get ib_mad DMA MR\n");
ret = PTR_ERR(port_priv->mr);
goto error5;
}
@@ -2902,7 +2988,7 @@ static int ib_mad_port_open(struct ib_device *device,
ret = ib_mad_port_start(port_priv);
if (ret) {
- printk(KERN_ERR PFX "Couldn't start port\n");
+ dev_err(&device->dev, "Couldn't start port\n");
goto error9;
}
@@ -2946,7 +3032,7 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
port_priv = __ib_get_mad_port(device, port_num);
if (port_priv == NULL) {
spin_unlock_irqrestore(&ib_mad_port_list_lock, flags);
- printk(KERN_ERR PFX "Port %d not found\n", port_num);
+ dev_err(&device->dev, "Port %d not found\n", port_num);
return -ENODEV;
}
list_del_init(&port_priv->port_list);
@@ -2984,14 +3070,12 @@ static void ib_mad_init_device(struct ib_device *device)
for (i = start; i <= end; i++) {
if (ib_mad_port_open(device, i)) {
- printk(KERN_ERR PFX "Couldn't open %s port %d\n",
- device->name, i);
+ dev_err(&device->dev, "Couldn't open port %d\n", i);
goto error;
}
if (ib_agent_port_open(device, i)) {
- printk(KERN_ERR PFX "Couldn't open %s port %d "
- "for agents\n",
- device->name, i);
+ dev_err(&device->dev,
+ "Couldn't open port %d for agents\n", i);
goto error_agent;
}
}
@@ -2999,20 +3083,17 @@ static void ib_mad_init_device(struct ib_device *device)
error_agent:
if (ib_mad_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, i);
+ dev_err(&device->dev, "Couldn't close port %d\n", i);
error:
i--;
while (i >= start) {
if (ib_agent_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d "
- "for agents\n",
- device->name, i);
+ dev_err(&device->dev,
+ "Couldn't close port %d for agents\n", i);
if (ib_mad_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, i);
+ dev_err(&device->dev, "Couldn't close port %d\n", i);
i--;
}
}
@@ -3033,12 +3114,12 @@ static void ib_mad_remove_device(struct ib_device *device)
}
for (i = 0; i < num_ports; i++, cur_port++) {
if (ib_agent_port_close(device, cur_port))
- printk(KERN_ERR PFX "Couldn't close %s port %d "
- "for agents\n",
- device->name, cur_port);
+ dev_err(&device->dev,
+ "Couldn't close port %d for agents\n",
+ cur_port);
if (ib_mad_port_close(device, cur_port))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, cur_port);
+ dev_err(&device->dev, "Couldn't close port %d\n",
+ cur_port);
}
}
@@ -3064,7 +3145,7 @@ static int __init ib_mad_init_module(void)
SLAB_HWCACHE_ALIGN,
NULL);
if (!ib_mad_cache) {
- printk(KERN_ERR PFX "Couldn't create ib_mad cache\n");
+ pr_err("Couldn't create ib_mad cache\n");
ret = -ENOMEM;
goto error1;
}
@@ -3072,7 +3153,7 @@ static int __init ib_mad_init_module(void)
INIT_LIST_HEAD(&ib_mad_port_list);
if (ib_register_client(&mad_client)) {
- printk(KERN_ERR PFX "Couldn't register ib_mad client\n");
+ pr_err("Couldn't register ib_mad client\n");
ret = -EINVAL;
goto error2;
}
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 9430ab4969c5..d1a0b0ee9444 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -42,9 +42,6 @@
#include <rdma/ib_mad.h>
#include <rdma/ib_smi.h>
-
-#define PFX "ib_mad: "
-
#define IB_MAD_QPS_CORE 2 /* Always QP0 and QP1 as a minimum */
/* QP and CQ parameters */
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 233eaf541f55..c38f030f0dc9 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1184,7 +1184,7 @@ static void ib_sa_add_one(struct ib_device *device)
sa_dev->port[i].agent =
ib_register_mad_agent(device, i + s, IB_QPT_GSI,
NULL, 0, send_handler,
- recv_handler, sa_dev);
+ recv_handler, sa_dev, 0);
if (IS_ERR(sa_dev->port[i].agent))
goto err;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 1acb99100556..928cdd20e2d1 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -33,6 +33,8 @@
* SOFTWARE.
*/
+#define pr_fmt(fmt) "user_mad: " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
@@ -504,13 +506,15 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;
hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
- if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) {
- copy_offset = IB_MGMT_MAD_HDR;
- rmpp_active = 0;
- } else {
+
+ if (ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
+ && ib_mad_kernel_rmpp_agent(agent)) {
copy_offset = IB_MGMT_RMPP_HDR;
rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
- IB_MGMT_RMPP_FLAG_ACTIVE;
+ IB_MGMT_RMPP_FLAG_ACTIVE;
+ } else {
+ copy_offset = IB_MGMT_MAD_HDR;
+ rmpp_active = 0;
}
data_len = count - hdr_size(file) - hdr_len;
@@ -556,14 +560,22 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
rmpp_mad->mad_hdr.tid = *tid;
}
- spin_lock_irq(&file->send_lock);
- ret = is_duplicate(file, packet);
- if (!ret)
+ if (!ib_mad_kernel_rmpp_agent(agent)
+ && ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
+ && (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) {
+ spin_lock_irq(&file->send_lock);
list_add_tail(&packet->list, &file->send_list);
- spin_unlock_irq(&file->send_lock);
- if (ret) {
- ret = -EINVAL;
- goto err_msg;
+ spin_unlock_irq(&file->send_lock);
+ } else {
+ spin_lock_irq(&file->send_lock);
+ ret = is_duplicate(file, packet);
+ if (!ret)
+ list_add_tail(&packet->list, &file->send_list);
+ spin_unlock_irq(&file->send_lock);
+ if (ret) {
+ ret = -EINVAL;
+ goto err_msg;
+ }
}
ret = ib_post_send_mad(packet->msg, NULL);
@@ -614,6 +626,8 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
mutex_lock(&file->mutex);
if (!file->port->ib_dev) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent: invalid device\n");
ret = -EPIPE;
goto out;
}
@@ -624,6 +638,9 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
}
if (ureq.qpn != 0 && ureq.qpn != 1) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent: invalid QPN %d specified\n",
+ ureq.qpn);
ret = -EINVAL;
goto out;
}
@@ -632,11 +649,15 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
if (!__get_agent(file, agent_id))
goto found;
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent: Max Agents (%u) reached\n",
+ IB_UMAD_MAX_AGENTS);
ret = -ENOMEM;
goto out;
found:
if (ureq.mgmt_class) {
+ memset(&req, 0, sizeof(req));
req.mgmt_class = ureq.mgmt_class;
req.mgmt_class_version = ureq.mgmt_class_version;
memcpy(req.oui, ureq.oui, sizeof req.oui);
@@ -657,7 +678,7 @@ found:
ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
ureq.mgmt_class ? &req : NULL,
ureq.rmpp_version,
- send_handler, recv_handler, file);
+ send_handler, recv_handler, file, 0);
if (IS_ERR(agent)) {
ret = PTR_ERR(agent);
agent = NULL;
@@ -673,10 +694,11 @@ found:
if (!file->already_used) {
file->already_used = 1;
if (!file->use_pkey_index) {
- printk(KERN_WARNING "user_mad: process %s did not enable "
- "P_Key index support.\n", current->comm);
- printk(KERN_WARNING "user_mad: Documentation/infiniband/user_mad.txt "
- "has info on the new ABI.\n");
+ dev_warn(file->port->dev,
+ "process %s did not enable P_Key index support.\n",
+ current->comm);
+ dev_warn(file->port->dev,
+ " Documentation/infiniband/user_mad.txt has info on the new ABI.\n");
}
}
@@ -694,6 +716,119 @@ out:
return ret;
}
+static int ib_umad_reg_agent2(struct ib_umad_file *file, void __user *arg)
+{
+ struct ib_user_mad_reg_req2 ureq;
+ struct ib_mad_reg_req req;
+ struct ib_mad_agent *agent = NULL;
+ int agent_id;
+ int ret;
+
+ mutex_lock(&file->port->file_mutex);
+ mutex_lock(&file->mutex);
+
+ if (!file->port->ib_dev) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent2: invalid device\n");
+ ret = -EPIPE;
+ goto out;
+ }
+
+ if (copy_from_user(&ureq, arg, sizeof(ureq))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (ureq.qpn != 0 && ureq.qpn != 1) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent2: invalid QPN %d specified\n",
+ ureq.qpn);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ureq.flags & ~IB_USER_MAD_REG_FLAGS_CAP) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent2 failed: invalid registration flags specified 0x%x; supported 0x%x\n",
+ ureq.flags, IB_USER_MAD_REG_FLAGS_CAP);
+ ret = -EINVAL;
+
+ if (put_user((u32)IB_USER_MAD_REG_FLAGS_CAP,
+ (u32 __user *) (arg + offsetof(struct
+ ib_user_mad_reg_req2, flags))))
+ ret = -EFAULT;
+
+ goto out;
+ }
+
+ for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id)
+ if (!__get_agent(file, agent_id))
+ goto found;
+
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent2: Max Agents (%u) reached\n",
+ IB_UMAD_MAX_AGENTS);
+ ret = -ENOMEM;
+ goto out;
+
+found:
+ if (ureq.mgmt_class) {
+ memset(&req, 0, sizeof(req));
+ req.mgmt_class = ureq.mgmt_class;
+ req.mgmt_class_version = ureq.mgmt_class_version;
+ if (ureq.oui & 0xff000000) {
+ dev_notice(file->port->dev,
+ "ib_umad_reg_agent2 failed: oui invalid 0x%08x\n",
+ ureq.oui);
+ ret = -EINVAL;
+ goto out;
+ }
+ req.oui[2] = ureq.oui & 0x0000ff;
+ req.oui[1] = (ureq.oui & 0x00ff00) >> 8;
+ req.oui[0] = (ureq.oui & 0xff0000) >> 16;
+ memcpy(req.method_mask, ureq.method_mask,
+ sizeof(req.method_mask));
+ }
+
+ agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num,
+ ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
+ ureq.mgmt_class ? &req : NULL,
+ ureq.rmpp_version,
+ send_handler, recv_handler, file,
+ ureq.flags);
+ if (IS_ERR(agent)) {
+ ret = PTR_ERR(agent);
+ agent = NULL;
+ goto out;
+ }
+
+ if (put_user(agent_id,
+ (u32 __user *)(arg +
+ offsetof(struct ib_user_mad_reg_req2, id)))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (!file->already_used) {
+ file->already_used = 1;
+ file->use_pkey_index = 1;
+ }
+
+ file->agent[agent_id] = agent;
+ ret = 0;
+
+out:
+ mutex_unlock(&file->mutex);
+
+ if (ret && agent)
+ ib_unregister_mad_agent(agent);
+
+ mutex_unlock(&file->port->file_mutex);
+
+ return ret;
+}
+
+
static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
{
struct ib_mad_agent *agent = NULL;
@@ -749,6 +884,8 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
return ib_umad_unreg_agent(filp->private_data, (__u32 __user *) arg);
case IB_USER_MAD_ENABLE_PKEY:
return ib_umad_enable_pkey(filp->private_data);
+ case IB_USER_MAD_REGISTER_AGENT2:
+ return ib_umad_reg_agent2(filp->private_data, (void __user *) arg);
default:
return -ENOIOCTLCMD;
}
@@ -765,6 +902,8 @@ static long ib_umad_compat_ioctl(struct file *filp, unsigned int cmd,
return ib_umad_unreg_agent(filp->private_data, compat_ptr(arg));
case IB_USER_MAD_ENABLE_PKEY:
return ib_umad_enable_pkey(filp->private_data);
+ case IB_USER_MAD_REGISTER_AGENT2:
+ return ib_umad_reg_agent2(filp->private_data, compat_ptr(arg));
default:
return -ENOIOCTLCMD;
}
@@ -983,7 +1122,7 @@ static CLASS_ATTR_STRING(abi_version, S_IRUGO,
static dev_t overflow_maj;
static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
-static int find_overflow_devnum(void)
+static int find_overflow_devnum(struct ib_device *device)
{
int ret;
@@ -991,7 +1130,8 @@ static int find_overflow_devnum(void)
ret = alloc_chrdev_region(&overflow_maj, 0, IB_UMAD_MAX_PORTS * 2,
"infiniband_mad");
if (ret) {
- printk(KERN_ERR "user_mad: couldn't register dynamic device number\n");
+ dev_err(&device->dev,
+ "couldn't register dynamic device number\n");
return ret;
}
}
@@ -1014,7 +1154,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
if (devnum >= IB_UMAD_MAX_PORTS) {
spin_unlock(&port_lock);
- devnum = find_overflow_devnum();
+ devnum = find_overflow_devnum(device);
if (devnum < 0)
return -1;
@@ -1200,14 +1340,14 @@ static int __init ib_umad_init(void)
ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,
"infiniband_mad");
if (ret) {
- printk(KERN_ERR "user_mad: couldn't register device number\n");
+ pr_err("couldn't register device number\n");
goto out;
}
umad_class = class_create(THIS_MODULE, "infiniband_mad");
if (IS_ERR(umad_class)) {
ret = PTR_ERR(umad_class);
- printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");
+ pr_err("couldn't create class infiniband_mad\n");
goto out_chrdev;
}
@@ -1215,13 +1355,13 @@ static int __init ib_umad_init(void)
ret = class_create_file(umad_class, &class_attr_abi_version.attr);
if (ret) {
- printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
+ pr_err("couldn't create abi_version attribute\n");
goto out_class;
}
ret = ib_register_client(&umad_client);
if (ret) {
- printk(KERN_ERR "user_mad: couldn't register ib_umad client\n");
+ pr_err("couldn't register ib_umad client\n");
goto out_class;
}
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index a283274a5a09..643c08a025a5 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -221,6 +221,7 @@ IB_UVERBS_DECLARE_CMD(query_port);
IB_UVERBS_DECLARE_CMD(alloc_pd);
IB_UVERBS_DECLARE_CMD(dealloc_pd);
IB_UVERBS_DECLARE_CMD(reg_mr);
+IB_UVERBS_DECLARE_CMD(rereg_mr);
IB_UVERBS_DECLARE_CMD(dereg_mr);
IB_UVERBS_DECLARE_CMD(alloc_mw);
IB_UVERBS_DECLARE_CMD(dealloc_mw);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index ea6203ee7bcc..0600c50e6215 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1002,6 +1002,99 @@ err_free:
return ret;
}
+ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_rereg_mr cmd;
+ struct ib_uverbs_rereg_mr_resp resp;
+ struct ib_udata udata;
+ struct ib_pd *pd = NULL;
+ struct ib_mr *mr;
+ struct ib_pd *old_pd;
+ int ret;
+ struct ib_uobject *uobj;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(&cmd, buf, sizeof(cmd)))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof(cmd),
+ (unsigned long) cmd.response + sizeof(resp),
+ in_len - sizeof(cmd), out_len - sizeof(resp));
+
+ if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
+ return -EINVAL;
+
+ if ((cmd.flags & IB_MR_REREG_TRANS) &&
+ (!cmd.start || !cmd.hca_va || 0 >= cmd.length ||
+ (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)))
+ return -EINVAL;
+
+ uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle,
+ file->ucontext);
+
+ if (!uobj)
+ return -EINVAL;
+
+ mr = uobj->object;
+
+ if (cmd.flags & IB_MR_REREG_ACCESS) {
+ ret = ib_check_mr_access(cmd.access_flags);
+ if (ret)
+ goto put_uobjs;
+ }
+
+ if (cmd.flags & IB_MR_REREG_PD) {
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ if (!pd) {
+ ret = -EINVAL;
+ goto put_uobjs;
+ }
+ }
+
+ if (atomic_read(&mr->usecnt)) {
+ ret = -EBUSY;
+ goto put_uobj_pd;
+ }
+
+ old_pd = mr->pd;
+ ret = mr->device->rereg_user_mr(mr, cmd.flags, cmd.start,
+ cmd.length, cmd.hca_va,
+ cmd.access_flags, pd, &udata);
+ if (!ret) {
+ if (cmd.flags & IB_MR_REREG_PD) {
+ atomic_inc(&pd->usecnt);
+ mr->pd = pd;
+ atomic_dec(&old_pd->usecnt);
+ }
+ } else {
+ goto put_uobj_pd;
+ }
+
+ memset(&resp, 0, sizeof(resp));
+ resp.lkey = mr->lkey;
+ resp.rkey = mr->rkey;
+
+ if (copy_to_user((void __user *)(unsigned long)cmd.response,
+ &resp, sizeof(resp)))
+ ret = -EFAULT;
+ else
+ ret = in_len;
+
+put_uobj_pd:
+ if (cmd.flags & IB_MR_REREG_PD)
+ put_pd_read(pd);
+
+put_uobjs:
+
+ put_uobj_write(mr->uobject);
+
+ return ret;
+}
+
ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 08219fb3338b..c73b22a257fe 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -87,6 +87,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,
[IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
[IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
+ [IB_USER_VERBS_CMD_REREG_MR] = ib_uverbs_rereg_mr,
[IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
[IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw,
[IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw,
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 00400c352c1a..766a71ccefed 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -604,16 +604,14 @@ static int c2_up(struct net_device *netdev)
tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc);
c2_port->mem_size = tx_size + rx_size;
- c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size,
- &c2_port->dma);
+ c2_port->mem = pci_zalloc_consistent(c2dev->pcidev, c2_port->mem_size,
+ &c2_port->dma);
if (c2_port->mem == NULL) {
pr_debug("Unable to allocate memory for "
"host descriptor rings\n");
return -ENOMEM;
}
- memset(c2_port->mem, 0, c2_port->mem_size);
-
/* Create the Rx host descriptor ring */
if ((ret =
c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma,
diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c
index 49e0e8533f74..1b63185b4ad4 100644
--- a/drivers/infiniband/hw/amso1100/c2_cq.c
+++ b/drivers/infiniband/hw/amso1100/c2_cq.c
@@ -260,11 +260,14 @@ static void c2_free_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq)
mq->msg_pool.host, dma_unmap_addr(mq, mapping));
}
-static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, int q_size,
- int msg_size)
+static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq,
+ size_t q_size, size_t msg_size)
{
u8 *pool_start;
+ if (q_size > SIZE_MAX / msg_size)
+ return -EINVAL;
+
pool_start = dma_alloc_coherent(&c2dev->pcidev->dev, q_size * msg_size,
&mq->host_dma, GFP_KERNEL);
if (!pool_start)
diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c
index 8af33cf1fc4e..2d5cbf4363e4 100644
--- a/drivers/infiniband/hw/amso1100/c2_provider.c
+++ b/drivers/infiniband/hw/amso1100/c2_provider.c
@@ -734,7 +734,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
/* change ethxxx to iwxxx */
strcpy(name, "iw");
strcat(name, &c2dev->netdev->name[3]);
- netdev = alloc_netdev(0, name, setup);
+ netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, setup);
if (!netdev) {
printk(KERN_ERR PFX "%s - etherdev alloc failed",
__func__);
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 768a0fb67dd6..c2fb71c182a8 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -79,9 +79,10 @@ static int dack_mode = 1;
module_param(dack_mode, int, 0644);
MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
-int c4iw_max_read_depth = 8;
+uint c4iw_max_read_depth = 32;
module_param(c4iw_max_read_depth, int, 0644);
-MODULE_PARM_DESC(c4iw_max_read_depth, "Per-connection max ORD/IRD (default=8)");
+MODULE_PARM_DESC(c4iw_max_read_depth,
+ "Per-connection max ORD/IRD (default=32)");
static int enable_tcp_timestamps;
module_param(enable_tcp_timestamps, int, 0644);
@@ -474,7 +475,8 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
16)) | FW_WR_FLOWID(ep->hwtid));
flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
- flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
+ flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN
+ (ep->com.dev->rdev.lldi.pf));
flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
@@ -821,6 +823,8 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
if (mpa_rev_to_use == 2) {
mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
sizeof (struct mpa_v2_conn_params));
+ PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+ ep->ord);
mpa_v2_params.ird = htons((u16)ep->ird);
mpa_v2_params.ord = htons((u16)ep->ord);
@@ -1190,8 +1194,8 @@ static int connect_request_upcall(struct c4iw_ep *ep)
sizeof(struct mpa_v2_conn_params);
} else {
/* this means MPA_v1 is used. Send max supported */
- event.ord = c4iw_max_read_depth;
- event.ird = c4iw_max_read_depth;
+ event.ord = cur_max_read_depth(ep->com.dev);
+ event.ird = cur_max_read_depth(ep->com.dev);
event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
}
@@ -1255,6 +1259,8 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
return credits;
}
+#define RELAXED_IRD_NEGOTIATION 1
+
static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
@@ -1366,17 +1372,33 @@ static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
MPA_V2_IRD_ORD_MASK;
resp_ord = ntohs(mpa_v2_params->ord) &
MPA_V2_IRD_ORD_MASK;
+ PDBG("%s responder ird %u ord %u ep ird %u ord %u\n",
+ __func__, resp_ird, resp_ord, ep->ird, ep->ord);
/*
* This is a double-check. Ideally, below checks are
* not required since ird/ord stuff has been taken
* care of in c4iw_accept_cr
*/
- if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+ if (ep->ird < resp_ord) {
+ if (RELAXED_IRD_NEGOTIATION && resp_ord <=
+ ep->com.dev->rdev.lldi.max_ordird_qp)
+ ep->ird = resp_ord;
+ else
+ insuff_ird = 1;
+ } else if (ep->ird > resp_ord) {
+ ep->ird = resp_ord;
+ }
+ if (ep->ord > resp_ird) {
+ if (RELAXED_IRD_NEGOTIATION)
+ ep->ord = resp_ird;
+ else
+ insuff_ird = 1;
+ }
+ if (insuff_ird) {
err = -ENOMEM;
ep->ird = resp_ord;
ep->ord = resp_ird;
- insuff_ird = 1;
}
if (ntohs(mpa_v2_params->ird) &
@@ -1579,6 +1601,8 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
MPA_V2_IRD_ORD_MASK;
ep->ord = ntohs(mpa_v2_params->ord) &
MPA_V2_IRD_ORD_MASK;
+ PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+ ep->ord);
if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
if (peer2peer) {
if (ntohs(mpa_v2_params->ord) &
@@ -1798,6 +1822,20 @@ static int is_neg_adv(unsigned int status)
status == CPL_ERR_KEEPALV_NEG_ADVICE;
}
+static char *neg_adv_str(unsigned int status)
+{
+ switch (status) {
+ case CPL_ERR_RTX_NEG_ADVICE:
+ return "Retransmit timeout";
+ case CPL_ERR_PERSIST_NEG_ADVICE:
+ return "Persist timeout";
+ case CPL_ERR_KEEPALV_NEG_ADVICE:
+ return "Keepalive timeout";
+ default:
+ return "Unknown";
+ }
+}
+
static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
{
ep->snd_win = snd_win;
@@ -1996,8 +2034,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
status, status2errno(status));
if (is_neg_adv(status)) {
- printk(KERN_WARNING MOD "Connection problems for atid %u\n",
- atid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Connection problems for atid %u status %u (%s)\n",
+ atid, status, neg_adv_str(status));
return 0;
}
@@ -2472,8 +2511,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
ep = lookup_tid(t, tid);
if (is_neg_adv(req->status)) {
- PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
- ep->hwtid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Negative advice on abort - tid %u status %d (%s)\n",
+ ep->hwtid, req->status, neg_adv_str(req->status));
return 0;
}
PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
@@ -2731,8 +2771,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
BUG_ON(!qp);
set_bit(ULP_ACCEPT, &ep->com.history);
- if ((conn_param->ord > c4iw_max_read_depth) ||
- (conn_param->ird > c4iw_max_read_depth)) {
+ if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
+ (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
abort_connection(ep, NULL, GFP_KERNEL);
err = -EINVAL;
goto err;
@@ -2740,31 +2780,41 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
if (conn_param->ord > ep->ird) {
- ep->ird = conn_param->ird;
- ep->ord = conn_param->ord;
- send_mpa_reject(ep, conn_param->private_data,
- conn_param->private_data_len);
- abort_connection(ep, NULL, GFP_KERNEL);
- err = -ENOMEM;
- goto err;
+ if (RELAXED_IRD_NEGOTIATION) {
+ ep->ord = ep->ird;
+ } else {
+ ep->ird = conn_param->ird;
+ ep->ord = conn_param->ord;
+ send_mpa_reject(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
}
- if (conn_param->ird > ep->ord) {
- if (!ep->ord)
- conn_param->ird = 1;
- else {
+ if (conn_param->ird < ep->ord) {
+ if (RELAXED_IRD_NEGOTIATION &&
+ ep->ord <= h->rdev.lldi.max_ordird_qp) {
+ conn_param->ird = ep->ord;
+ } else {
abort_connection(ep, NULL, GFP_KERNEL);
err = -ENOMEM;
goto err;
}
}
-
}
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
- if (ep->mpa_attr.version != 2)
+ if (ep->mpa_attr.version == 1) {
if (peer2peer && ep->ird == 0)
ep->ird = 1;
+ } else {
+ if (peer2peer &&
+ (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
+ (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+ ep->ird = 1;
+ }
PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
@@ -2803,6 +2853,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
return 0;
err1:
ep->com.cm_id = NULL;
+ abort_connection(ep, NULL, GFP_KERNEL);
cm_id->rem_ref(cm_id);
err:
mutex_unlock(&ep->com.mutex);
@@ -2886,8 +2937,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
int iptype;
int iwpm_err = 0;
- if ((conn_param->ord > c4iw_max_read_depth) ||
- (conn_param->ird > c4iw_max_read_depth)) {
+ if ((conn_param->ord > cur_max_read_depth(dev)) ||
+ (conn_param->ird > cur_max_read_depth(dev))) {
err = -EINVAL;
goto out;
}
@@ -3867,8 +3918,9 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
return 0;
}
if (is_neg_adv(req->status)) {
- PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
- ep->hwtid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Negative advice on abort - tid %u status %d (%s)\n",
+ ep->hwtid, req->status, neg_adv_str(req->status));
kfree_skb(skb);
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index c04292c950f1..0f773e78e080 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -633,11 +633,15 @@ proc_cqe:
wq->sq.cidx = (uint16_t)idx;
PDBG("%s completing sq idx %u\n", __func__, wq->sq.cidx);
*cookie = wq->sq.sw_sq[wq->sq.cidx].wr_id;
+ if (c4iw_wr_log)
+ c4iw_log_wr_stats(wq, hw_cqe);
t4_sq_consume(wq);
} else {
PDBG("%s completing rq idx %u\n", __func__, wq->rq.cidx);
*cookie = wq->rq.sw_rq[wq->rq.cidx].wr_id;
BUG_ON(t4_rq_empty(wq));
+ if (c4iw_wr_log)
+ c4iw_log_wr_stats(wq, hw_cqe);
t4_rq_consume(wq);
goto skip_cqe;
}
@@ -895,7 +899,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
/*
* Make actual HW queue 2x to avoid cdix_inc overflows.
*/
- hwentries = min(entries * 2, T4_MAX_IQ_SIZE);
+ hwentries = min(entries * 2, rhp->rdev.hw_queue.t4_max_iq_size);
/*
* Make HW queue at least 64 entries so GTS updates aren't too
@@ -909,14 +913,8 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
/*
* memsize must be a multiple of the page size if its a user cq.
*/
- if (ucontext) {
+ if (ucontext)
memsize = roundup(memsize, PAGE_SIZE);
- hwentries = memsize / sizeof *chp->cq.queue;
- while (hwentries > T4_MAX_IQ_SIZE) {
- memsize -= PAGE_SIZE;
- hwentries = memsize / sizeof *chp->cq.queue;
- }
- }
chp->cq.size = hwentries;
chp->cq.memsize = memsize;
chp->cq.vector = vector;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 7db82b24302b..f25df5276c22 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -33,6 +33,7 @@
#include <linux/moduleparam.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
+#include <linux/math64.h>
#include <rdma/ib_verbs.h>
@@ -55,6 +56,15 @@ module_param(allow_db_coalescing_on_t5, int, 0644);
MODULE_PARM_DESC(allow_db_coalescing_on_t5,
"Allow DB Coalescing on T5 (default = 0)");
+int c4iw_wr_log = 0;
+module_param(c4iw_wr_log, int, 0444);
+MODULE_PARM_DESC(c4iw_wr_log, "Enables logging of work request timing data.");
+
+int c4iw_wr_log_size_order = 12;
+module_param(c4iw_wr_log_size_order, int, 0444);
+MODULE_PARM_DESC(c4iw_wr_log_size_order,
+ "Number of entries (log2) in the work request timing log.");
+
struct uld_ctx {
struct list_head entry;
struct cxgb4_lld_info lldi;
@@ -103,6 +113,117 @@ static ssize_t debugfs_read(struct file *file, char __user *buf, size_t count,
return simple_read_from_buffer(buf, count, ppos, d->buf, d->pos);
}
+void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe)
+{
+ struct wr_log_entry le;
+ int idx;
+
+ if (!wq->rdev->wr_log)
+ return;
+
+ idx = (atomic_inc_return(&wq->rdev->wr_log_idx) - 1) &
+ (wq->rdev->wr_log_size - 1);
+ le.poll_sge_ts = cxgb4_read_sge_timestamp(wq->rdev->lldi.ports[0]);
+ getnstimeofday(&le.poll_host_ts);
+ le.valid = 1;
+ le.cqe_sge_ts = CQE_TS(cqe);
+ if (SQ_TYPE(cqe)) {
+ le.qid = wq->sq.qid;
+ le.opcode = CQE_OPCODE(cqe);
+ le.post_host_ts = wq->sq.sw_sq[wq->sq.cidx].host_ts;
+ le.post_sge_ts = wq->sq.sw_sq[wq->sq.cidx].sge_ts;
+ le.wr_id = CQE_WRID_SQ_IDX(cqe);
+ } else {
+ le.qid = wq->rq.qid;
+ le.opcode = FW_RI_RECEIVE;
+ le.post_host_ts = wq->rq.sw_rq[wq->rq.cidx].host_ts;
+ le.post_sge_ts = wq->rq.sw_rq[wq->rq.cidx].sge_ts;
+ le.wr_id = CQE_WRID_MSN(cqe);
+ }
+ wq->rdev->wr_log[idx] = le;
+}
+
+static int wr_log_show(struct seq_file *seq, void *v)
+{
+ struct c4iw_dev *dev = seq->private;
+ struct timespec prev_ts = {0, 0};
+ struct wr_log_entry *lep;
+ int prev_ts_set = 0;
+ int idx, end;
+
+#define ts2ns(ts) div64_ul((ts) * dev->rdev.lldi.cclk_ps, 1000)
+
+ idx = atomic_read(&dev->rdev.wr_log_idx) &
+ (dev->rdev.wr_log_size - 1);
+ end = idx - 1;
+ if (end < 0)
+ end = dev->rdev.wr_log_size - 1;
+ lep = &dev->rdev.wr_log[idx];
+ while (idx != end) {
+ if (lep->valid) {
+ if (!prev_ts_set) {
+ prev_ts_set = 1;
+ prev_ts = lep->poll_host_ts;
+ }
+ seq_printf(seq, "%04u: sec %lu nsec %lu qid %u opcode "
+ "%u %s 0x%x host_wr_delta sec %lu nsec %lu "
+ "post_sge_ts 0x%llx cqe_sge_ts 0x%llx "
+ "poll_sge_ts 0x%llx post_poll_delta_ns %llu "
+ "cqe_poll_delta_ns %llu\n",
+ idx,
+ timespec_sub(lep->poll_host_ts,
+ prev_ts).tv_sec,
+ timespec_sub(lep->poll_host_ts,
+ prev_ts).tv_nsec,
+ lep->qid, lep->opcode,
+ lep->opcode == FW_RI_RECEIVE ?
+ "msn" : "wrid",
+ lep->wr_id,
+ timespec_sub(lep->poll_host_ts,
+ lep->post_host_ts).tv_sec,
+ timespec_sub(lep->poll_host_ts,
+ lep->post_host_ts).tv_nsec,
+ lep->post_sge_ts, lep->cqe_sge_ts,
+ lep->poll_sge_ts,
+ ts2ns(lep->poll_sge_ts - lep->post_sge_ts),
+ ts2ns(lep->poll_sge_ts - lep->cqe_sge_ts));
+ prev_ts = lep->poll_host_ts;
+ }
+ idx++;
+ if (idx > (dev->rdev.wr_log_size - 1))
+ idx = 0;
+ lep = &dev->rdev.wr_log[idx];
+ }
+#undef ts2ns
+ return 0;
+}
+
+static int wr_log_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wr_log_show, inode->i_private);
+}
+
+static ssize_t wr_log_clear(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct c4iw_dev *dev = ((struct seq_file *)file->private_data)->private;
+ int i;
+
+ if (dev->rdev.wr_log)
+ for (i = 0; i < dev->rdev.wr_log_size; i++)
+ dev->rdev.wr_log[i].valid = 0;
+ return count;
+}
+
+static const struct file_operations wr_log_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = wr_log_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = wr_log_clear,
+};
+
static int dump_qp(int id, void *p, void *data)
{
struct c4iw_qp *qp = p;
@@ -241,12 +362,32 @@ static int dump_stag(int id, void *p, void *data)
struct c4iw_debugfs_data *stagd = data;
int space;
int cc;
+ struct fw_ri_tpte tpte;
+ int ret;
space = stagd->bufsize - stagd->pos - 1;
if (space == 0)
return 1;
- cc = snprintf(stagd->buf + stagd->pos, space, "0x%x\n", id<<8);
+ ret = cxgb4_read_tpte(stagd->devp->rdev.lldi.ports[0], (u32)id<<8,
+ (__be32 *)&tpte);
+ if (ret) {
+ dev_err(&stagd->devp->rdev.lldi.pdev->dev,
+ "%s cxgb4_read_tpte err %d\n", __func__, ret);
+ return ret;
+ }
+ cc = snprintf(stagd->buf + stagd->pos, space,
+ "stag: idx 0x%x valid %d key 0x%x state %d pdid %d "
+ "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
+ (u32)id<<8,
+ G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
+ G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
+ ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
+ ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
if (cc < space)
stagd->pos += cc;
return 0;
@@ -259,7 +400,7 @@ static int stag_release(struct inode *inode, struct file *file)
printk(KERN_INFO "%s null stagd?\n", __func__);
return 0;
}
- kfree(stagd->buf);
+ vfree(stagd->buf);
kfree(stagd);
return 0;
}
@@ -282,8 +423,8 @@ static int stag_open(struct inode *inode, struct file *file)
idr_for_each(&stagd->devp->mmidr, count_idrs, &count);
spin_unlock_irq(&stagd->devp->lock);
- stagd->bufsize = count * sizeof("0x12345678\n");
- stagd->buf = kmalloc(stagd->bufsize, GFP_KERNEL);
+ stagd->bufsize = count * 256;
+ stagd->buf = vmalloc(stagd->bufsize);
if (!stagd->buf) {
ret = -ENOMEM;
goto err1;
@@ -348,6 +489,7 @@ static int stats_show(struct seq_file *seq, void *v)
dev->rdev.stats.act_ofld_conn_fails);
seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
dev->rdev.stats.pas_ofld_conn_fails);
+ seq_printf(seq, "AVAILABLE IRD: %10u\n", dev->avail_ird);
return 0;
}
@@ -583,6 +725,12 @@ static int setup_debugfs(struct c4iw_dev *devp)
if (de && de->d_inode)
de->d_inode->i_size = 4096;
+ if (c4iw_wr_log) {
+ de = debugfs_create_file("wr_log", S_IWUSR, devp->debugfs_root,
+ (void *)devp, &wr_log_debugfs_fops);
+ if (de && de->d_inode)
+ de->d_inode->i_size = 4096;
+ }
return 0;
}
@@ -696,7 +844,20 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
pr_err(MOD "error allocating status page\n");
goto err4;
}
+
+ if (c4iw_wr_log) {
+ rdev->wr_log = kzalloc((1 << c4iw_wr_log_size_order) *
+ sizeof(*rdev->wr_log), GFP_KERNEL);
+ if (rdev->wr_log) {
+ rdev->wr_log_size = 1 << c4iw_wr_log_size_order;
+ atomic_set(&rdev->wr_log_idx, 0);
+ } else {
+ pr_err(MOD "error allocating wr_log. Logging disabled\n");
+ }
+ }
+
rdev->status_page->db_off = 0;
+
return 0;
err4:
c4iw_rqtpool_destroy(rdev);
@@ -710,6 +871,7 @@ err1:
static void c4iw_rdev_close(struct c4iw_rdev *rdev)
{
+ kfree(rdev->wr_log);
free_page((unsigned long)rdev->status_page);
c4iw_pblpool_destroy(rdev);
c4iw_rqtpool_destroy(rdev);
@@ -768,6 +930,27 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
}
devp->rdev.lldi = *infop;
+ /* init various hw-queue params based on lld info */
+ PDBG("%s: Ing. padding boundary is %d, egrsstatuspagesize = %d\n",
+ __func__, devp->rdev.lldi.sge_ingpadboundary,
+ devp->rdev.lldi.sge_egrstatuspagesize);
+
+ devp->rdev.hw_queue.t4_eq_status_entries =
+ devp->rdev.lldi.sge_ingpadboundary > 64 ? 2 : 1;
+ devp->rdev.hw_queue.t4_max_eq_size = 65520;
+ devp->rdev.hw_queue.t4_max_iq_size = 65520;
+ devp->rdev.hw_queue.t4_max_rq_size = 8192 -
+ devp->rdev.hw_queue.t4_eq_status_entries - 1;
+ devp->rdev.hw_queue.t4_max_sq_size =
+ devp->rdev.hw_queue.t4_max_eq_size -
+ devp->rdev.hw_queue.t4_eq_status_entries - 1;
+ devp->rdev.hw_queue.t4_max_qp_depth =
+ devp->rdev.hw_queue.t4_max_rq_size;
+ devp->rdev.hw_queue.t4_max_cq_depth =
+ devp->rdev.hw_queue.t4_max_iq_size - 2;
+ devp->rdev.hw_queue.t4_stat_len =
+ devp->rdev.lldi.sge_egrstatuspagesize;
+
/*
* For T5 devices, we map all of BAR2 with WC.
* For T4 devices with onchip qp mem, we map only that part
@@ -818,6 +1001,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
mutex_init(&devp->rdev.stats.lock);
mutex_init(&devp->db_mutex);
INIT_LIST_HEAD(&devp->db_fc_list);
+ devp->avail_ird = devp->rdev.lldi.max_ird_adapter;
if (c4iw_debugfs_root) {
devp->debugfs_root = debugfs_create_dir(
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index d61d0a18f784..c9df0549f51d 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -35,6 +35,55 @@
#include "iw_cxgb4.h"
+static void print_tpte(struct c4iw_dev *dev, u32 stag)
+{
+ int ret;
+ struct fw_ri_tpte tpte;
+
+ ret = cxgb4_read_tpte(dev->rdev.lldi.ports[0], stag,
+ (__be32 *)&tpte);
+ if (ret) {
+ dev_err(&dev->rdev.lldi.pdev->dev,
+ "%s cxgb4_read_tpte err %d\n", __func__, ret);
+ return;
+ }
+ PDBG("stag idx 0x%x valid %d key 0x%x state %d pdid %d "
+ "perm 0x%x ps %d len 0x%llx va 0x%llx\n",
+ stag & 0xffffff00,
+ G_FW_RI_TPTE_VALID(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_STAGKEY(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_STAGSTATE(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_PDID(ntohl(tpte.valid_to_pdid)),
+ G_FW_RI_TPTE_PERM(ntohl(tpte.locread_to_qpid)),
+ G_FW_RI_TPTE_PS(ntohl(tpte.locread_to_qpid)),
+ ((u64)ntohl(tpte.len_hi) << 32) | ntohl(tpte.len_lo),
+ ((u64)ntohl(tpte.va_hi) << 32) | ntohl(tpte.va_lo_fbo));
+}
+
+static void dump_err_cqe(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
+{
+ __be64 *p = (void *)err_cqe;
+
+ dev_err(&dev->rdev.lldi.pdev->dev,
+ "AE qpid %d opcode %d status 0x%x "
+ "type %d len 0x%x wrid.hi 0x%x wrid.lo 0x%x\n",
+ CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
+ CQE_STATUS(err_cqe), CQE_TYPE(err_cqe), ntohl(err_cqe->len),
+ CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
+
+ PDBG("%016llx %016llx %016llx %016llx\n",
+ be64_to_cpu(p[0]), be64_to_cpu(p[1]), be64_to_cpu(p[2]),
+ be64_to_cpu(p[3]));
+
+ /*
+ * Ingress WRITE and READ_RESP errors provide
+ * the offending stag, so parse and log it.
+ */
+ if (RQ_TYPE(err_cqe) && (CQE_OPCODE(err_cqe) == FW_RI_RDMA_WRITE ||
+ CQE_OPCODE(err_cqe) == FW_RI_READ_RESP))
+ print_tpte(dev, CQE_WRID_STAG(err_cqe));
+}
+
static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
struct c4iw_qp *qhp,
struct t4_cqe *err_cqe,
@@ -44,11 +93,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
struct c4iw_qp_attributes attrs;
unsigned long flag;
- printk(KERN_ERR MOD "AE qpid 0x%x opcode %d status 0x%x "
- "type %d wrid.hi 0x%x wrid.lo 0x%x\n",
- CQE_QPID(err_cqe), CQE_OPCODE(err_cqe),
- CQE_STATUS(err_cqe), CQE_TYPE(err_cqe),
- CQE_WRID_HI(err_cqe), CQE_WRID_LOW(err_cqe));
+ dump_err_cqe(dev, err_cqe);
if (qhp->attr.state == C4IW_QP_STATE_RTS) {
attrs.next_state = C4IW_QP_STATE_TERMINATE;
@@ -182,6 +227,7 @@ int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
chp = get_chp(dev, qid);
if (chp) {
+ t4_clear_cq_armed(&chp->cq);
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 361fff7a0742..b5678ac97393 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -139,6 +139,29 @@ struct c4iw_stats {
u64 pas_ofld_conn_fails;
};
+struct c4iw_hw_queue {
+ int t4_eq_status_entries;
+ int t4_max_eq_size;
+ int t4_max_iq_size;
+ int t4_max_rq_size;
+ int t4_max_sq_size;
+ int t4_max_qp_depth;
+ int t4_max_cq_depth;
+ int t4_stat_len;
+};
+
+struct wr_log_entry {
+ struct timespec post_host_ts;
+ struct timespec poll_host_ts;
+ u64 post_sge_ts;
+ u64 cqe_sge_ts;
+ u64 poll_sge_ts;
+ u16 qid;
+ u16 wr_id;
+ u8 opcode;
+ u8 valid;
+};
+
struct c4iw_rdev {
struct c4iw_resource resource;
unsigned long qpshift;
@@ -156,7 +179,11 @@ struct c4iw_rdev {
unsigned long oc_mw_pa;
void __iomem *oc_mw_kva;
struct c4iw_stats stats;
+ struct c4iw_hw_queue hw_queue;
struct t4_dev_status_page *status_page;
+ atomic_t wr_log_idx;
+ struct wr_log_entry *wr_log;
+ int wr_log_size;
};
static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -166,7 +193,7 @@ static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
{
- return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5));
+ return (int)(rdev->lldi.vr->stag.size >> 5);
}
#define C4IW_WR_TO (30*HZ)
@@ -237,6 +264,7 @@ struct c4iw_dev {
struct idr atid_idr;
struct idr stid_idr;
struct list_head db_fc_list;
+ u32 avail_ird;
};
static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
@@ -318,6 +346,13 @@ static inline void remove_handle_nolock(struct c4iw_dev *rhp,
_remove_handle(rhp, idr, id, 0);
}
+extern uint c4iw_max_read_depth;
+
+static inline int cur_max_read_depth(struct c4iw_dev *dev)
+{
+ return min(dev->rdev.lldi.max_ordird_qp, c4iw_max_read_depth);
+}
+
struct c4iw_pd {
struct ib_pd ibpd;
u32 pdid;
@@ -991,7 +1026,8 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe);
extern struct cxgb4_client t4c_client;
extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
-extern int c4iw_max_read_depth;
+extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe);
+extern int c4iw_wr_log;
extern int db_fc_threshold;
extern int db_coalescing_threshold;
extern int use_dsgl;
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index b1d305338de6..72e3b69d1b76 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -318,14 +318,16 @@ static int c4iw_query_device(struct ib_device *ibdev,
props->vendor_id = (u32)dev->rdev.lldi.pdev->vendor;
props->vendor_part_id = (u32)dev->rdev.lldi.pdev->device;
props->max_mr_size = T4_MAX_MR_SIZE;
- props->max_qp = T4_MAX_NUM_QP;
- props->max_qp_wr = T4_MAX_QP_DEPTH;
+ props->max_qp = dev->rdev.lldi.vr->qp.size / 2;
+ props->max_qp_wr = dev->rdev.hw_queue.t4_max_qp_depth;
props->max_sge = T4_MAX_RECV_SGE;
props->max_sge_rd = 1;
- props->max_qp_rd_atom = c4iw_max_read_depth;
- props->max_qp_init_rd_atom = c4iw_max_read_depth;
- props->max_cq = T4_MAX_NUM_CQ;
- props->max_cqe = T4_MAX_CQ_DEPTH;
+ props->max_res_rd_atom = dev->rdev.lldi.max_ird_adapter;
+ props->max_qp_rd_atom = min(dev->rdev.lldi.max_ordird_qp,
+ c4iw_max_read_depth);
+ props->max_qp_init_rd_atom = props->max_qp_rd_atom;
+ props->max_cq = dev->rdev.lldi.vr->qp.size;
+ props->max_cqe = dev->rdev.hw_queue.t4_max_cq_depth;
props->max_mr = c4iw_num_stags(&dev->rdev);
props->max_pd = T4_MAX_NUM_PD;
props->local_ca_ack_delay = 0;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 086f62f5dc9e..41cd6882b648 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -58,6 +58,31 @@ static int max_fr_immd = T4_MAX_FR_IMMD;
module_param(max_fr_immd, int, 0644);
MODULE_PARM_DESC(max_fr_immd, "fastreg threshold for using DSGL instead of immedate");
+static int alloc_ird(struct c4iw_dev *dev, u32 ird)
+{
+ int ret = 0;
+
+ spin_lock_irq(&dev->lock);
+ if (ird <= dev->avail_ird)
+ dev->avail_ird -= ird;
+ else
+ ret = -ENOMEM;
+ spin_unlock_irq(&dev->lock);
+
+ if (ret)
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "device IRD resources exhausted\n");
+
+ return ret;
+}
+
+static void free_ird(struct c4iw_dev *dev, int ird)
+{
+ spin_lock_irq(&dev->lock);
+ dev->avail_ird += ird;
+ spin_unlock_irq(&dev->lock);
+}
+
static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
{
unsigned long flag;
@@ -180,9 +205,9 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
}
/*
- * RQT must be a power of 2.
+ * RQT must be a power of 2 and at least 16 deep.
*/
- wq->rq.rqt_size = roundup_pow_of_two(wq->rq.size);
+ wq->rq.rqt_size = roundup_pow_of_two(max_t(u16, wq->rq.size, 16));
wq->rq.rqt_hwaddr = c4iw_rqtpool_alloc(rdev, wq->rq.rqt_size);
if (!wq->rq.rqt_hwaddr) {
ret = -ENOMEM;
@@ -258,7 +283,8 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
/*
* eqsize is the number of 64B entries plus the status page size.
*/
- eqsize = wq->sq.size * T4_SQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+ eqsize = wq->sq.size * T4_SQ_NUM_SLOTS +
+ rdev->hw_queue.t4_eq_status_entries;
res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
V_FW_RI_RES_WR_HOSTFCMODE(0) | /* no host cidx updates */
@@ -283,7 +309,8 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
/*
* eqsize is the number of 64B entries plus the status page size.
*/
- eqsize = wq->rq.size * T4_RQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+ eqsize = wq->rq.size * T4_RQ_NUM_SLOTS +
+ rdev->hw_queue.t4_eq_status_entries;
res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
V_FW_RI_RES_WR_HOSTFCMODE(0) | /* no host cidx updates */
V_FW_RI_RES_WR_CPRIO(0) | /* don't keep in chip cache */
@@ -796,6 +823,11 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
qhp->sq_sig_all;
swsqe->flushed = 0;
swsqe->wr_id = wr->wr_id;
+ if (c4iw_wr_log) {
+ swsqe->sge_ts = cxgb4_read_sge_timestamp(
+ qhp->rhp->rdev.lldi.ports[0]);
+ getnstimeofday(&swsqe->host_ts);
+ }
init_wr_hdr(wqe, qhp->wq.sq.pidx, fw_opcode, fw_flags, len16);
@@ -859,6 +891,13 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
}
qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].wr_id = wr->wr_id;
+ if (c4iw_wr_log) {
+ qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].sge_ts =
+ cxgb4_read_sge_timestamp(
+ qhp->rhp->rdev.lldi.ports[0]);
+ getnstimeofday(
+ &qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].host_ts);
+ }
wqe->recv.opcode = FW_RI_RECV_WR;
wqe->recv.r1 = 0;
@@ -1066,7 +1105,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
struct c4iw_cq *schp)
{
int count;
- int flushed;
+ int rq_flushed, sq_flushed;
unsigned long flag;
PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
@@ -1084,27 +1123,40 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
c4iw_flush_hw_cq(rchp);
c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
- flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
+ rq_flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, flag);
- if (flushed) {
- spin_lock_irqsave(&rchp->comp_handler_lock, flag);
- (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
- spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
- }
/* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, flag);
spin_lock(&qhp->lock);
if (schp != rchp)
c4iw_flush_hw_cq(schp);
- flushed = c4iw_flush_sq(qhp);
+ sq_flushed = c4iw_flush_sq(qhp);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, flag);
- if (flushed) {
- spin_lock_irqsave(&schp->comp_handler_lock, flag);
- (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
- spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+
+ if (schp == rchp) {
+ if (t4_clear_cq_armed(&rchp->cq) &&
+ (rq_flushed || sq_flushed)) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+ (*rchp->ibcq.comp_handler)(&rchp->ibcq,
+ rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ }
+ } else {
+ if (t4_clear_cq_armed(&rchp->cq) && rq_flushed) {
+ spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+ (*rchp->ibcq.comp_handler)(&rchp->ibcq,
+ rchp->ibcq.cq_context);
+ spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+ }
+ if (t4_clear_cq_armed(&schp->cq) && sq_flushed) {
+ spin_lock_irqsave(&schp->comp_handler_lock, flag);
+ (*schp->ibcq.comp_handler)(&schp->ibcq,
+ schp->ibcq.cq_context);
+ spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+ }
}
}
@@ -1202,12 +1254,20 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
int ret;
struct sk_buff *skb;
- PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
- qhp->ep->hwtid);
+ PDBG("%s qhp %p qid 0x%x tid %u ird %u ord %u\n", __func__, qhp,
+ qhp->wq.sq.qid, qhp->ep->hwtid, qhp->ep->ird, qhp->ep->ord);
skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = alloc_ird(rhp, qhp->attr.max_ird);
+ if (ret) {
+ qhp->attr.max_ird = 0;
+ kfree_skb(skb);
+ goto out;
+ }
set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
@@ -1258,10 +1318,14 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
ret = c4iw_ofld_send(&rhp->rdev, skb);
if (ret)
- goto out;
+ goto err1;
ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
+ if (!ret)
+ goto out;
+err1:
+ free_ird(rhp, qhp->attr.max_ird);
out:
PDBG("%s ret %d\n", __func__, ret);
return ret;
@@ -1306,7 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
newattr.max_ord = attrs->max_ord;
}
if (mask & C4IW_QP_ATTR_MAX_IRD) {
- if (attrs->max_ird > c4iw_max_read_depth) {
+ if (attrs->max_ird > cur_max_read_depth(rhp)) {
ret = -EINVAL;
goto out;
}
@@ -1529,6 +1593,7 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
if (!list_empty(&qhp->db_fc_entry))
list_del_init(&qhp->db_fc_entry);
spin_unlock_irq(&rhp->lock);
+ free_ird(rhp, qhp->attr.max_ird);
ucontext = ib_qp->uobject ?
to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
@@ -1569,13 +1634,17 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
return ERR_PTR(-EINVAL);
- rqsize = roundup(attrs->cap.max_recv_wr + 1, 16);
- if (rqsize > T4_MAX_RQ_SIZE)
+ if (attrs->cap.max_recv_wr > rhp->rdev.hw_queue.t4_max_rq_size)
return ERR_PTR(-E2BIG);
+ rqsize = attrs->cap.max_recv_wr + 1;
+ if (rqsize < 8)
+ rqsize = 8;
- sqsize = roundup(attrs->cap.max_send_wr + 1, 16);
- if (sqsize > T4_MAX_SQ_SIZE)
+ if (attrs->cap.max_send_wr > rhp->rdev.hw_queue.t4_max_sq_size)
return ERR_PTR(-E2BIG);
+ sqsize = attrs->cap.max_send_wr + 1;
+ if (sqsize < 8)
+ sqsize = 8;
ucontext = pd->uobject ? to_c4iw_ucontext(pd->uobject->context) : NULL;
@@ -1583,19 +1652,20 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
if (!qhp)
return ERR_PTR(-ENOMEM);
qhp->wq.sq.size = sqsize;
- qhp->wq.sq.memsize = (sqsize + 1) * sizeof *qhp->wq.sq.queue;
+ qhp->wq.sq.memsize =
+ (sqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+ sizeof(*qhp->wq.sq.queue) + 16 * sizeof(__be64);
qhp->wq.sq.flush_cidx = -1;
qhp->wq.rq.size = rqsize;
- qhp->wq.rq.memsize = (rqsize + 1) * sizeof *qhp->wq.rq.queue;
+ qhp->wq.rq.memsize =
+ (rqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+ sizeof(*qhp->wq.rq.queue);
if (ucontext) {
qhp->wq.sq.memsize = roundup(qhp->wq.sq.memsize, PAGE_SIZE);
qhp->wq.rq.memsize = roundup(qhp->wq.rq.memsize, PAGE_SIZE);
}
- PDBG("%s sqsize %u sqmemsize %zu rqsize %u rqmemsize %zu\n",
- __func__, sqsize, qhp->wq.sq.memsize, rqsize, qhp->wq.rq.memsize);
-
ret = create_qp(&rhp->rdev, &qhp->wq, &schp->cq, &rchp->cq,
ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
if (ret)
@@ -1619,8 +1689,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
qhp->attr.enable_rdma_read = 1;
qhp->attr.enable_rdma_write = 1;
qhp->attr.enable_bind = 1;
- qhp->attr.max_ord = 1;
- qhp->attr.max_ird = 1;
+ qhp->attr.max_ord = 0;
+ qhp->attr.max_ird = 0;
qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
spin_lock_init(&qhp->lock);
mutex_init(&qhp->mutex);
@@ -1714,9 +1784,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
qhp->ibqp.qp_num = qhp->wq.sq.qid;
init_timer(&(qhp->timer));
INIT_LIST_HEAD(&qhp->db_fc_entry);
- PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n",
- __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
- qhp->wq.sq.qid);
+ PDBG("%s sq id %u size %u memsize %zu num_entries %u "
+ "rq id %u size %u memsize %zu num_entries %u\n", __func__,
+ qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
+ attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
+ qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
return &qhp->ibqp;
err8:
kfree(mm5);
@@ -1804,5 +1876,11 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
memset(attr, 0, sizeof *attr);
memset(init_attr, 0, sizeof *init_attr);
attr->qp_state = to_ib_qp_state(qhp->attr.state);
+ init_attr->cap.max_send_wr = qhp->attr.sq_num_entries;
+ init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries;
+ init_attr->cap.max_send_sge = qhp->attr.sq_max_sges;
+ init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges;
+ init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE;
+ init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
return 0;
}
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 68b0a6bf4eb0..c04e5134b30c 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -36,22 +36,11 @@
#include "t4_msg.h"
#include "t4fw_ri_api.h"
-#define T4_MAX_NUM_QP 65536
-#define T4_MAX_NUM_CQ 65536
#define T4_MAX_NUM_PD 65536
-#define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
-#define T4_MAX_EQ_SIZE (65520 - T4_EQ_STATUS_ENTRIES)
-#define T4_MAX_IQ_SIZE (65520 - 1)
-#define T4_MAX_RQ_SIZE (8192 - T4_EQ_STATUS_ENTRIES)
-#define T4_MAX_SQ_SIZE (T4_MAX_EQ_SIZE - 1)
-#define T4_MAX_QP_DEPTH (T4_MAX_RQ_SIZE - 1)
-#define T4_MAX_CQ_DEPTH (T4_MAX_IQ_SIZE - 1)
-#define T4_MAX_NUM_STAG (1<<15)
#define T4_MAX_MR_SIZE (~0ULL)
#define T4_PAGESIZE_MASK 0xffff000 /* 4KB-128MB */
#define T4_STAG_UNSET 0xffffffff
#define T4_FW_MAJ 0
-#define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
#define A_PCIE_MA_SYNC 0x30b4
struct t4_status_page {
@@ -244,8 +233,8 @@ struct t4_cqe {
#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx)
/* generic accessor macros */
-#define CQE_WRID_HI(x) ((x)->u.gen.wrid_hi)
-#define CQE_WRID_LOW(x) ((x)->u.gen.wrid_low)
+#define CQE_WRID_HI(x) (be32_to_cpu((x)->u.gen.wrid_hi))
+#define CQE_WRID_LOW(x) (be32_to_cpu((x)->u.gen.wrid_low))
/* macros for flit 3 of the cqe */
#define S_CQE_GENBIT 63
@@ -277,6 +266,8 @@ struct t4_swsqe {
int signaled;
u16 idx;
int flushed;
+ struct timespec host_ts;
+ u64 sge_ts;
};
static inline pgprot_t t4_pgprot_wc(pgprot_t prot)
@@ -314,6 +305,8 @@ struct t4_sq {
struct t4_swrqe {
u64 wr_id;
+ struct timespec host_ts;
+ u64 sge_ts;
};
struct t4_rq {
@@ -531,6 +524,10 @@ static inline int t4_wq_db_enabled(struct t4_wq *wq)
return !wq->rq.queue[wq->rq.size].status.db_off;
}
+enum t4_cq_flags {
+ CQ_ARMED = 1,
+};
+
struct t4_cq {
struct t4_cqe *queue;
dma_addr_t dma_addr;
@@ -551,12 +548,19 @@ struct t4_cq {
u16 cidx_inc;
u8 gen;
u8 error;
+ unsigned long flags;
};
+static inline int t4_clear_cq_armed(struct t4_cq *cq)
+{
+ return test_and_clear_bit(CQ_ARMED, &cq->flags);
+}
+
static inline int t4_arm_cq(struct t4_cq *cq, int se)
{
u32 val;
+ set_bit(CQ_ARMED, &cq->flags);
while (cq->cidx_inc > CIDXINC_MASK) {
val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) |
INGRESSQID(cq->cqid);
diff --git a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
index 91289a051af9..5709e77faf7c 100644
--- a/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
+++ b/drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
@@ -849,6 +849,5 @@ enum { /* TCP congestion control algorithms */
#define G_CONG_CNTRL(x) (((x) >> S_CONG_CNTRL) & M_CONG_CNTRL)
#define CONG_CNTRL_VALID (1 << 18)
-#define T5_OPT_2_VALID (1 << 31)
#endif /* _T4FW_RI_API_H_ */
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 43f2d0424d4f..e890e5ba0e01 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -726,7 +726,7 @@ bail:
* @dd: the infinipath device
* @pkeys: the PKEY table
*/
-static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys)
+static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys, u8 port)
{
struct ipath_portdata *pd;
int i;
@@ -759,6 +759,7 @@ static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys)
}
if (changed) {
u64 pkey;
+ struct ib_event event;
pkey = (u64) dd->ipath_pkeys[0] |
((u64) dd->ipath_pkeys[1] << 16) |
@@ -768,12 +769,17 @@ static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys)
(unsigned long long) pkey);
ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
pkey);
+
+ event.event = IB_EVENT_PKEY_CHANGE;
+ event.device = &dd->verbs_dev->ibdev;
+ event.element.port_num = port;
+ ib_dispatch_event(&event);
}
return 0;
}
static int recv_subn_set_pkeytable(struct ib_smp *smp,
- struct ib_device *ibdev)
+ struct ib_device *ibdev, u8 port)
{
u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
__be16 *p = (__be16 *) smp->data;
@@ -784,7 +790,7 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp,
for (i = 0; i < n; i++)
q[i] = be16_to_cpu(p[i]);
- if (startpx != 0 || set_pkeys(dev->dd, q) != 0)
+ if (startpx != 0 || set_pkeys(dev->dd, q, port) != 0)
smp->status |= IB_SMP_INVALID_FIELD;
return recv_subn_get_pkeytable(smp, ibdev);
@@ -1342,7 +1348,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
ret = recv_subn_set_portinfo(smp, ibdev, port_num);
goto bail;
case IB_SMP_ATTR_PKEY_TABLE:
- ret = recv_subn_set_pkeytable(smp, ibdev);
+ ret = recv_subn_set_pkeytable(smp, ibdev, port_num);
goto bail;
case IB_SMP_ATTR_SM_INFO:
if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 287ad0564acd..82a7dd87089b 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -891,7 +891,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
q ? IB_QPT_GSI : IB_QPT_SMI,
NULL, 0, send_handler,
- NULL, NULL);
+ NULL, NULL, 0);
if (IS_ERR(agent)) {
ret = PTR_ERR(agent);
goto err;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 0f7027e7db13..e1e558a3d692 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -910,8 +910,7 @@ static int __mlx4_ib_default_rules_match(struct ib_qp *qp,
const struct default_rules *pdefault_rules = default_table;
u8 link_layer = rdma_port_get_link_layer(qp->device, flow_attr->port);
- for (i = 0; i < sizeof(default_table)/sizeof(default_table[0]); i++,
- pdefault_rules++) {
+ for (i = 0; i < ARRAY_SIZE(default_table); i++, pdefault_rules++) {
__u32 field_types[IB_FLOW_SPEC_SUPPORT_LAYERS];
memset(&field_types, 0, sizeof(field_types));
@@ -965,8 +964,7 @@ static int __mlx4_ib_create_default_rules(
int size = 0;
int i;
- for (i = 0; i < sizeof(pdefault_rules->rules_create_list)/
- sizeof(pdefault_rules->rules_create_list[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
int ret;
union ib_flow_spec ib_spec;
switch (pdefault_rules->rules_create_list[i]) {
@@ -2007,6 +2005,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
(1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
(1ull << IB_USER_VERBS_CMD_REG_MR) |
+ (1ull << IB_USER_VERBS_CMD_REREG_MR) |
(1ull << IB_USER_VERBS_CMD_DEREG_MR) |
(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
(1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
@@ -2059,6 +2058,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq;
ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr;
ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr;
+ ibdev->ib_dev.rereg_user_mr = mlx4_ib_rereg_user_mr;
ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr;
ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 369da3ca5d64..e8cad3926bfc 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -788,5 +788,9 @@ int mlx4_ib_steer_qp_alloc(struct mlx4_ib_dev *dev, int count, int *qpn);
void mlx4_ib_steer_qp_free(struct mlx4_ib_dev *dev, u32 qpn, int count);
int mlx4_ib_steer_qp_reg(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
int is_attach);
+int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
+ u64 start, u64 length, u64 virt_addr,
+ int mr_access_flags, struct ib_pd *pd,
+ struct ib_udata *udata);
#endif /* MLX4_IB_H */
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index cb2a8727f3fb..9b0e80e59b08 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -144,8 +144,10 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (!mr)
return ERR_PTR(-ENOMEM);
+ /* Force registering the memory as writable. */
+ /* Used for memory re-registeration. HCA protects the access */
mr->umem = ib_umem_get(pd->uobject->context, start, length,
- access_flags, 0);
+ access_flags | IB_ACCESS_LOCAL_WRITE, 0);
if (IS_ERR(mr->umem)) {
err = PTR_ERR(mr->umem);
goto err_free;
@@ -183,6 +185,90 @@ err_free:
return ERR_PTR(err);
}
+int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
+ u64 start, u64 length, u64 virt_addr,
+ int mr_access_flags, struct ib_pd *pd,
+ struct ib_udata *udata)
+{
+ struct mlx4_ib_dev *dev = to_mdev(mr->device);
+ struct mlx4_ib_mr *mmr = to_mmr(mr);
+ struct mlx4_mpt_entry *mpt_entry;
+ struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
+ int err;
+
+ /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
+ * we assume that the calls can't run concurrently. Otherwise, a
+ * race exists.
+ */
+ err = mlx4_mr_hw_get_mpt(dev->dev, &mmr->mmr, &pmpt_entry);
+
+ if (err)
+ return err;
+
+ if (flags & IB_MR_REREG_PD) {
+ err = mlx4_mr_hw_change_pd(dev->dev, *pmpt_entry,
+ to_mpd(pd)->pdn);
+
+ if (err)
+ goto release_mpt_entry;
+ }
+
+ if (flags & IB_MR_REREG_ACCESS) {
+ err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry,
+ convert_access(mr_access_flags));
+
+ if (err)
+ goto release_mpt_entry;
+ }
+
+ if (flags & IB_MR_REREG_TRANS) {
+ int shift;
+ int err;
+ int n;
+
+ mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr);
+ ib_umem_release(mmr->umem);
+ mmr->umem = ib_umem_get(mr->uobject->context, start, length,
+ mr_access_flags |
+ IB_ACCESS_LOCAL_WRITE,
+ 0);
+ if (IS_ERR(mmr->umem)) {
+ err = PTR_ERR(mmr->umem);
+ mmr->umem = NULL;
+ goto release_mpt_entry;
+ }
+ n = ib_umem_page_count(mmr->umem);
+ shift = ilog2(mmr->umem->page_size);
+
+ mmr->mmr.iova = virt_addr;
+ mmr->mmr.size = length;
+ err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr,
+ virt_addr, length, n, shift,
+ *pmpt_entry);
+ if (err) {
+ ib_umem_release(mmr->umem);
+ goto release_mpt_entry;
+ }
+
+ err = mlx4_ib_umem_write_mtt(dev, &mmr->mmr.mtt, mmr->umem);
+ if (err) {
+ mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr);
+ ib_umem_release(mmr->umem);
+ goto release_mpt_entry;
+ }
+ }
+
+ /* If we couldn't transfer the MR to the HCA, just remember to
+ * return a failure. But dereg_mr will free the resources.
+ */
+ err = mlx4_mr_hw_write_mpt(dev->dev, &mmr->mmr, pmpt_entry);
+
+release_mpt_entry:
+ mlx4_mr_hw_put_mpt(dev->dev, pmpt_entry);
+
+ return err;
+}
+
int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
{
struct mlx4_ib_mr *mr = to_mmr(ibmr);
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index 8ae4f896cb41..e4056279166d 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -180,7 +180,7 @@ static void handle_responder(struct ib_wc *wc, struct mlx5_cqe64 *cqe,
struct mlx5_core_srq *msrq = NULL;
if (qp->ibqp.xrcd) {
- msrq = mlx5_core_get_srq(&dev->mdev,
+ msrq = mlx5_core_get_srq(dev->mdev,
be32_to_cpu(cqe->srqn));
srq = to_mibsrq(msrq);
} else {
@@ -348,7 +348,7 @@ static void handle_atomic(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
u16 tail, u16 head)
{
- int idx;
+ u16 idx;
do {
idx = tail & (qp->sq.wqe_cnt - 1);
@@ -364,7 +364,7 @@ static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf)
{
- mlx5_buf_free(&dev->mdev, &buf->buf);
+ mlx5_buf_free(dev->mdev, &buf->buf);
}
static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
@@ -450,7 +450,7 @@ repoll:
* because CQs will be locked while QPs are removed
* from the table.
*/
- mqp = __mlx5_qp_lookup(&dev->mdev, qpn);
+ mqp = __mlx5_qp_lookup(dev->mdev, qpn);
if (unlikely(!mqp)) {
mlx5_ib_warn(dev, "CQE@CQ %06x for unknown QPN %6x\n",
cq->mcq.cqn, qpn);
@@ -514,11 +514,11 @@ repoll:
case MLX5_CQE_SIG_ERR:
sig_err_cqe = (struct mlx5_sig_err_cqe *)cqe64;
- read_lock(&dev->mdev.priv.mr_table.lock);
- mmr = __mlx5_mr_lookup(&dev->mdev,
+ read_lock(&dev->mdev->priv.mr_table.lock);
+ mmr = __mlx5_mr_lookup(dev->mdev,
mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey)));
if (unlikely(!mmr)) {
- read_unlock(&dev->mdev.priv.mr_table.lock);
+ read_unlock(&dev->mdev->priv.mr_table.lock);
mlx5_ib_warn(dev, "CQE@CQ %06x for unknown MR %6x\n",
cq->mcq.cqn, be32_to_cpu(sig_err_cqe->mkey));
return -EINVAL;
@@ -536,7 +536,7 @@ repoll:
mr->sig->err_item.expected,
mr->sig->err_item.actual);
- read_unlock(&dev->mdev.priv.mr_table.lock);
+ read_unlock(&dev->mdev->priv.mr_table.lock);
goto repoll;
}
@@ -575,8 +575,8 @@ int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
mlx5_cq_arm(&to_mcq(ibcq)->mcq,
(flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
MLX5_CQ_DB_REQ_NOT_SOL : MLX5_CQ_DB_REQ_NOT,
- to_mdev(ibcq->device)->mdev.priv.uuari.uars[0].map,
- MLX5_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->mdev.priv.cq_uar_lock));
+ to_mdev(ibcq->device)->mdev->priv.uuari.uars[0].map,
+ MLX5_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->mdev->priv.cq_uar_lock));
return 0;
}
@@ -586,7 +586,7 @@ static int alloc_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf,
{
int err;
- err = mlx5_buf_alloc(&dev->mdev, nent * cqe_size,
+ err = mlx5_buf_alloc(dev->mdev, nent * cqe_size,
PAGE_SIZE * 2, &buf->buf);
if (err)
return err;
@@ -691,7 +691,7 @@ static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,
{
int err;
- err = mlx5_db_alloc(&dev->mdev, &cq->db);
+ err = mlx5_db_alloc(dev->mdev, &cq->db);
if (err)
return err;
@@ -716,7 +716,7 @@ static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq,
mlx5_fill_page_array(&cq->buf.buf, (*cqb)->pas);
(*cqb)->ctx.log_pg_sz = cq->buf.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT;
- *index = dev->mdev.priv.uuari.uars[0].index;
+ *index = dev->mdev->priv.uuari.uars[0].index;
return 0;
@@ -724,14 +724,14 @@ err_buf:
free_cq_buf(dev, &cq->buf);
err_db:
- mlx5_db_free(&dev->mdev, &cq->db);
+ mlx5_db_free(dev->mdev, &cq->db);
return err;
}
static void destroy_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq)
{
free_cq_buf(dev, &cq->buf);
- mlx5_db_free(&dev->mdev, &cq->db);
+ mlx5_db_free(dev->mdev, &cq->db);
}
struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
@@ -752,7 +752,7 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
return ERR_PTR(-EINVAL);
entries = roundup_pow_of_two(entries + 1);
- if (entries > dev->mdev.caps.max_cqes)
+ if (entries > dev->mdev->caps.max_cqes)
return ERR_PTR(-EINVAL);
cq = kzalloc(sizeof(*cq), GFP_KERNEL);
@@ -789,7 +789,7 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
cqb->ctx.c_eqn = cpu_to_be16(eqn);
cqb->ctx.db_record_addr = cpu_to_be64(cq->db.dma);
- err = mlx5_core_create_cq(&dev->mdev, &cq->mcq, cqb, inlen);
+ err = mlx5_core_create_cq(dev->mdev, &cq->mcq, cqb, inlen);
if (err)
goto err_cqb;
@@ -809,7 +809,7 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries,
return &cq->ibcq;
err_cmd:
- mlx5_core_destroy_cq(&dev->mdev, &cq->mcq);
+ mlx5_core_destroy_cq(dev->mdev, &cq->mcq);
err_cqb:
mlx5_vfree(cqb);
@@ -834,7 +834,7 @@ int mlx5_ib_destroy_cq(struct ib_cq *cq)
if (cq->uobject)
context = cq->uobject->context;
- mlx5_core_destroy_cq(&dev->mdev, &mcq->mcq);
+ mlx5_core_destroy_cq(dev->mdev, &mcq->mcq);
if (context)
destroy_cq_user(mcq, context);
else
@@ -919,7 +919,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
int err;
u32 fsel;
- if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_CQ_MODER))
+ if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_CQ_MODER))
return -ENOSYS;
in = kzalloc(sizeof(*in), GFP_KERNEL);
@@ -931,7 +931,7 @@ int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
in->ctx.cq_period = cpu_to_be16(cq_period);
in->ctx.cq_max_count = cpu_to_be16(cq_count);
in->field_select = cpu_to_be32(fsel);
- err = mlx5_core_modify_cq(&dev->mdev, &mcq->mcq, in, sizeof(*in));
+ err = mlx5_core_modify_cq(dev->mdev, &mcq->mcq, in, sizeof(*in));
kfree(in);
if (err)
@@ -1074,7 +1074,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
int uninitialized_var(cqe_size);
unsigned long flags;
- if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_RESIZE_CQ)) {
+ if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_RESIZE_CQ)) {
pr_info("Firmware does not support resize CQ\n");
return -ENOSYS;
}
@@ -1083,7 +1083,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
return -EINVAL;
entries = roundup_pow_of_two(entries + 1);
- if (entries > dev->mdev.caps.max_cqes + 1)
+ if (entries > dev->mdev->caps.max_cqes + 1)
return -EINVAL;
if (entries == ibcq->cqe + 1)
@@ -1128,7 +1128,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
in->hdr.opmod = cpu_to_be16(MLX5_CQ_OPMOD_RESIZE);
in->cqn = cpu_to_be32(cq->mcq.cqn);
- err = mlx5_core_modify_cq(&dev->mdev, &cq->mcq, in, inlen);
+ err = mlx5_core_modify_cq(dev->mdev, &cq->mcq, in, inlen);
if (err)
goto ex_alloc;
diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
index 5c8938be0e08..b514bbb5610f 100644
--- a/drivers/infiniband/hw/mlx5/mad.c
+++ b/drivers/infiniband/hw/mlx5/mad.c
@@ -41,7 +41,7 @@ enum {
};
int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
- int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+ u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh,
void *in_mad, void *response_mad)
{
u8 op_modifier = 0;
@@ -54,7 +54,7 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
if (ignore_bkey || !in_wc)
op_modifier |= 0x2;
- return mlx5_core_mad_ifc(&dev->mdev, in_mad, response_mad, op_modifier, port);
+ return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port);
}
int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
@@ -129,7 +129,7 @@ int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port)
packet_error = be16_to_cpu(out_mad->status);
- dev->mdev.caps.ext_port_cap[port - 1] = (!err && !packet_error) ?
+ dev->mdev->caps.ext_port_cap[port - 1] = (!err && !packet_error) ?
MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
out:
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 364d4b6937f5..d8907b20522a 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -54,96 +54,17 @@ MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(DRIVER_VERSION);
-static int prof_sel = 2;
-module_param_named(prof_sel, prof_sel, int, 0444);
-MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
+static int deprecated_prof_sel = 2;
+module_param_named(prof_sel, deprecated_prof_sel, int, 0444);
+MODULE_PARM_DESC(prof_sel, "profile selector. Deprecated here. Moved to module mlx5_core");
static char mlx5_version[] =
DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v"
DRIVER_VERSION " (" DRIVER_RELDATE ")\n";
-static struct mlx5_profile profile[] = {
- [0] = {
- .mask = 0,
- },
- [1] = {
- .mask = MLX5_PROF_MASK_QP_SIZE,
- .log_max_qp = 12,
- },
- [2] = {
- .mask = MLX5_PROF_MASK_QP_SIZE |
- MLX5_PROF_MASK_MR_CACHE,
- .log_max_qp = 17,
- .mr_cache[0] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[1] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[2] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[3] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[4] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[5] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[6] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[7] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[8] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[9] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[10] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[11] = {
- .size = 500,
- .limit = 250
- },
- .mr_cache[12] = {
- .size = 64,
- .limit = 32
- },
- .mr_cache[13] = {
- .size = 32,
- .limit = 16
- },
- .mr_cache[14] = {
- .size = 16,
- .limit = 8
- },
- .mr_cache[15] = {
- .size = 8,
- .limit = 4
- },
- },
-};
-
int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn)
{
- struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+ struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
struct mlx5_eq *eq, *n;
int err = -ENOENT;
@@ -163,7 +84,7 @@ int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn)
static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
{
- struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+ struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
char name[MLX5_MAX_EQ_NAME];
struct mlx5_eq *eq, *n;
int ncomp_vec;
@@ -182,9 +103,9 @@ static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
}
snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
- err = mlx5_create_map_eq(&dev->mdev, eq,
+ err = mlx5_create_map_eq(dev->mdev, eq,
i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
- name, &dev->mdev.priv.uuari.uars[0]);
+ name, &dev->mdev->priv.uuari.uars[0]);
if (err) {
kfree(eq);
goto clean;
@@ -204,7 +125,7 @@ clean:
list_for_each_entry_safe(eq, n, &dev->eqs_list, list) {
list_del(&eq->list);
spin_unlock(&table->lock);
- if (mlx5_destroy_unmap_eq(&dev->mdev, eq))
+ if (mlx5_destroy_unmap_eq(dev->mdev, eq))
mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn);
kfree(eq);
spin_lock(&table->lock);
@@ -215,14 +136,14 @@ clean:
static void free_comp_eqs(struct mlx5_ib_dev *dev)
{
- struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+ struct mlx5_eq_table *table = &dev->mdev->priv.eq_table;
struct mlx5_eq *eq, *n;
spin_lock(&table->lock);
list_for_each_entry_safe(eq, n, &dev->eqs_list, list) {
list_del(&eq->list);
spin_unlock(&table->lock);
- if (mlx5_destroy_unmap_eq(&dev->mdev, eq))
+ if (mlx5_destroy_unmap_eq(dev->mdev, eq))
mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn);
kfree(eq);
spin_lock(&table->lock);
@@ -255,14 +176,14 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
memset(props, 0, sizeof(*props));
- props->fw_ver = ((u64)fw_rev_maj(&dev->mdev) << 32) |
- (fw_rev_min(&dev->mdev) << 16) |
- fw_rev_sub(&dev->mdev);
+ props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) |
+ (fw_rev_min(dev->mdev) << 16) |
+ fw_rev_sub(dev->mdev);
props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
IB_DEVICE_PORT_ACTIVE_EVENT |
IB_DEVICE_SYS_IMAGE_GUID |
IB_DEVICE_RC_RNR_NAK_GEN;
- flags = dev->mdev.caps.flags;
+ flags = dev->mdev->caps.flags;
if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR)
props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
if (flags & MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR)
@@ -292,30 +213,30 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
props->max_mr_size = ~0ull;
- props->page_size_cap = dev->mdev.caps.min_page_sz;
- props->max_qp = 1 << dev->mdev.caps.log_max_qp;
- props->max_qp_wr = dev->mdev.caps.max_wqes;
- max_rq_sg = dev->mdev.caps.max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg);
- max_sq_sg = (dev->mdev.caps.max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) /
+ props->page_size_cap = dev->mdev->caps.min_page_sz;
+ props->max_qp = 1 << dev->mdev->caps.log_max_qp;
+ props->max_qp_wr = dev->mdev->caps.max_wqes;
+ max_rq_sg = dev->mdev->caps.max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg);
+ max_sq_sg = (dev->mdev->caps.max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) /
sizeof(struct mlx5_wqe_data_seg);
props->max_sge = min(max_rq_sg, max_sq_sg);
- props->max_cq = 1 << dev->mdev.caps.log_max_cq;
- props->max_cqe = dev->mdev.caps.max_cqes - 1;
- props->max_mr = 1 << dev->mdev.caps.log_max_mkey;
- props->max_pd = 1 << dev->mdev.caps.log_max_pd;
- props->max_qp_rd_atom = dev->mdev.caps.max_ra_req_qp;
- props->max_qp_init_rd_atom = dev->mdev.caps.max_ra_res_qp;
+ props->max_cq = 1 << dev->mdev->caps.log_max_cq;
+ props->max_cqe = dev->mdev->caps.max_cqes - 1;
+ props->max_mr = 1 << dev->mdev->caps.log_max_mkey;
+ props->max_pd = 1 << dev->mdev->caps.log_max_pd;
+ props->max_qp_rd_atom = dev->mdev->caps.max_ra_req_qp;
+ props->max_qp_init_rd_atom = dev->mdev->caps.max_ra_res_qp;
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
- props->max_srq = 1 << dev->mdev.caps.log_max_srq;
- props->max_srq_wr = dev->mdev.caps.max_srq_wqes - 1;
+ props->max_srq = 1 << dev->mdev->caps.log_max_srq;
+ props->max_srq_wr = dev->mdev->caps.max_srq_wqes - 1;
props->max_srq_sge = max_rq_sg - 1;
props->max_fast_reg_page_list_len = (unsigned int)-1;
- props->local_ca_ack_delay = dev->mdev.caps.local_ca_ack_delay;
+ props->local_ca_ack_delay = dev->mdev->caps.local_ca_ack_delay;
props->atomic_cap = IB_ATOMIC_NONE;
props->masked_atomic_cap = IB_ATOMIC_NONE;
props->max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
- props->max_mcast_grp = 1 << dev->mdev.caps.log_max_mcg;
- props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg;
+ props->max_mcast_grp = 1 << dev->mdev->caps.log_max_mcg;
+ props->max_mcast_qp_attach = dev->mdev->caps.max_qp_mcg;
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
props->max_mcast_grp;
props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */
@@ -336,7 +257,7 @@ int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
int ext_active_speed;
int err = -ENOMEM;
- if (port < 1 || port > dev->mdev.caps.num_ports) {
+ if (port < 1 || port > dev->mdev->caps.num_ports) {
mlx5_ib_warn(dev, "invalid port number %d\n", port);
return -EINVAL;
}
@@ -367,8 +288,8 @@ int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
props->phys_state = out_mad->data[33] >> 4;
props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20));
props->gid_tbl_len = out_mad->data[50];
- props->max_msg_sz = 1 << to_mdev(ibdev)->mdev.caps.log_max_msg;
- props->pkey_tbl_len = to_mdev(ibdev)->mdev.caps.port[port - 1].pkey_table_len;
+ props->max_msg_sz = 1 << to_mdev(ibdev)->mdev->caps.log_max_msg;
+ props->pkey_tbl_len = to_mdev(ibdev)->mdev->caps.port[port - 1].pkey_table_len;
props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48));
props->active_width = out_mad->data[31] & 0xf;
@@ -395,7 +316,7 @@ int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
/* If reported active speed is QDR, check if is FDR-10 */
if (props->active_speed == 4) {
- if (dev->mdev.caps.ext_port_cap[port - 1] &
+ if (dev->mdev->caps.ext_port_cap[port - 1] &
MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
init_query_mad(in_mad);
in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
@@ -508,7 +429,7 @@ static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,
* a 144 trap. If cmd fails, just ignore.
*/
memcpy(&in, props->node_desc, 64);
- err = mlx5_core_access_reg(&dev->mdev, &in, sizeof(in), &out,
+ err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,
sizeof(out), MLX5_REG_NODE_DESC, 0, 1);
if (err)
return err;
@@ -535,7 +456,7 @@ static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
tmp = (attr.port_cap_flags | props->set_port_cap_mask) &
~props->clr_port_cap_mask;
- err = mlx5_set_port_caps(&dev->mdev, port, tmp);
+ err = mlx5_set_port_caps(dev->mdev, port, tmp);
out:
mutex_unlock(&dev->cap_mask_mutex);
@@ -557,7 +478,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
int uuarn;
int err;
int i;
- int reqlen;
+ size_t reqlen;
if (!dev->ib_active)
return ERR_PTR(-EAGAIN);
@@ -591,14 +512,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
- resp.qp_tab_size = 1 << dev->mdev.caps.log_max_qp;
- resp.bf_reg_size = dev->mdev.caps.bf_reg_size;
+ resp.qp_tab_size = 1 << dev->mdev->caps.log_max_qp;
+ resp.bf_reg_size = dev->mdev->caps.bf_reg_size;
resp.cache_line_size = L1_CACHE_BYTES;
- resp.max_sq_desc_sz = dev->mdev.caps.max_sq_desc_sz;
- resp.max_rq_desc_sz = dev->mdev.caps.max_rq_desc_sz;
- resp.max_send_wqebb = dev->mdev.caps.max_wqes;
- resp.max_recv_wr = dev->mdev.caps.max_wqes;
- resp.max_srq_recv_wr = dev->mdev.caps.max_srq_wqes;
+ resp.max_sq_desc_sz = dev->mdev->caps.max_sq_desc_sz;
+ resp.max_rq_desc_sz = dev->mdev->caps.max_rq_desc_sz;
+ resp.max_send_wqebb = dev->mdev->caps.max_wqes;
+ resp.max_recv_wr = dev->mdev->caps.max_wqes;
+ resp.max_srq_recv_wr = dev->mdev->caps.max_srq_wqes;
context = kzalloc(sizeof(*context), GFP_KERNEL);
if (!context)
@@ -635,7 +556,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
}
for (i = 0; i < num_uars; i++) {
- err = mlx5_cmd_alloc_uar(&dev->mdev, &uars[i].index);
+ err = mlx5_cmd_alloc_uar(dev->mdev, &uars[i].index);
if (err)
goto out_count;
}
@@ -644,7 +565,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
mutex_init(&context->db_page_mutex);
resp.tot_uuars = req.total_num_uuars;
- resp.num_ports = dev->mdev.caps.num_ports;
+ resp.num_ports = dev->mdev->caps.num_ports;
err = ib_copy_to_udata(udata, &resp,
sizeof(resp) - sizeof(resp.reserved));
if (err)
@@ -658,7 +579,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
out_uars:
for (i--; i >= 0; i--)
- mlx5_cmd_free_uar(&dev->mdev, uars[i].index);
+ mlx5_cmd_free_uar(dev->mdev, uars[i].index);
out_count:
kfree(uuari->count);
@@ -681,7 +602,7 @@ static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
int i;
for (i = 0; i < uuari->num_uars; i++) {
- if (mlx5_cmd_free_uar(&dev->mdev, uuari->uars[i].index))
+ if (mlx5_cmd_free_uar(dev->mdev, uuari->uars[i].index))
mlx5_ib_warn(dev, "failed to free UAR 0x%x\n", uuari->uars[i].index);
}
@@ -695,7 +616,7 @@ static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev, int index)
{
- return (pci_resource_start(dev->mdev.pdev, 0) >> PAGE_SHIFT) + index;
+ return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + index;
}
static int get_command(unsigned long offset)
@@ -773,7 +694,7 @@ static int alloc_pa_mkey(struct mlx5_ib_dev *dev, u32 *key, u32 pdn)
seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
seg->start_addr = 0;
- err = mlx5_core_create_mkey(&dev->mdev, &mr, in, sizeof(*in),
+ err = mlx5_core_create_mkey(dev->mdev, &mr, in, sizeof(*in),
NULL, NULL, NULL);
if (err) {
mlx5_ib_warn(dev, "failed to create mkey, %d\n", err);
@@ -798,7 +719,7 @@ static void free_pa_mkey(struct mlx5_ib_dev *dev, u32 key)
memset(&mr, 0, sizeof(mr));
mr.key = key;
- err = mlx5_core_destroy_mkey(&dev->mdev, &mr);
+ err = mlx5_core_destroy_mkey(dev->mdev, &mr);
if (err)
mlx5_ib_warn(dev, "failed to destroy mkey 0x%x\n", key);
}
@@ -815,7 +736,7 @@ static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
if (!pd)
return ERR_PTR(-ENOMEM);
- err = mlx5_core_alloc_pd(&to_mdev(ibdev)->mdev, &pd->pdn);
+ err = mlx5_core_alloc_pd(to_mdev(ibdev)->mdev, &pd->pdn);
if (err) {
kfree(pd);
return ERR_PTR(err);
@@ -824,14 +745,14 @@ static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
if (context) {
resp.pdn = pd->pdn;
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
- mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn);
+ mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
kfree(pd);
return ERR_PTR(-EFAULT);
}
} else {
err = alloc_pa_mkey(to_mdev(ibdev), &pd->pa_lkey, pd->pdn);
if (err) {
- mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn);
+ mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
kfree(pd);
return ERR_PTR(err);
}
@@ -848,7 +769,7 @@ static int mlx5_ib_dealloc_pd(struct ib_pd *pd)
if (!pd->uobject)
free_pa_mkey(mdev, mpd->pa_lkey);
- mlx5_core_dealloc_pd(&mdev->mdev, mpd->pdn);
+ mlx5_core_dealloc_pd(mdev->mdev, mpd->pdn);
kfree(mpd);
return 0;
@@ -859,7 +780,7 @@ static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
int err;
- err = mlx5_core_attach_mcg(&dev->mdev, gid, ibqp->qp_num);
+ err = mlx5_core_attach_mcg(dev->mdev, gid, ibqp->qp_num);
if (err)
mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n",
ibqp->qp_num, gid->raw);
@@ -872,7 +793,7 @@ static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
int err;
- err = mlx5_core_detach_mcg(&dev->mdev, gid, ibqp->qp_num);
+ err = mlx5_core_detach_mcg(dev->mdev, gid, ibqp->qp_num);
if (err)
mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n",
ibqp->qp_num, gid->raw);
@@ -906,7 +827,7 @@ static int init_node_data(struct mlx5_ib_dev *dev)
if (err)
goto out;
- dev->mdev.rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32));
+ dev->mdev->rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32));
memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
out:
@@ -921,7 +842,7 @@ static ssize_t show_fw_pages(struct device *device, struct device_attribute *att
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "%d\n", dev->mdev.priv.fw_pages);
+ return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages);
}
static ssize_t show_reg_pages(struct device *device,
@@ -930,7 +851,7 @@ static ssize_t show_reg_pages(struct device *device,
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "%d\n", dev->mdev.priv.reg_pages);
+ return sprintf(buf, "%d\n", dev->mdev->priv.reg_pages);
}
static ssize_t show_hca(struct device *device, struct device_attribute *attr,
@@ -938,7 +859,7 @@ static ssize_t show_hca(struct device *device, struct device_attribute *attr,
{
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "MT%d\n", dev->mdev.pdev->device);
+ return sprintf(buf, "MT%d\n", dev->mdev->pdev->device);
}
static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
@@ -946,8 +867,8 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
{
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(&dev->mdev),
- fw_rev_min(&dev->mdev), fw_rev_sub(&dev->mdev));
+ return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(dev->mdev),
+ fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
}
static ssize_t show_rev(struct device *device, struct device_attribute *attr,
@@ -955,7 +876,7 @@ static ssize_t show_rev(struct device *device, struct device_attribute *attr,
{
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "%x\n", dev->mdev.rev_id);
+ return sprintf(buf, "%x\n", dev->mdev->rev_id);
}
static ssize_t show_board(struct device *device, struct device_attribute *attr,
@@ -964,7 +885,7 @@ static ssize_t show_board(struct device *device, struct device_attribute *attr,
struct mlx5_ib_dev *dev =
container_of(device, struct mlx5_ib_dev, ib_dev.dev);
return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN,
- dev->mdev.board_id);
+ dev->mdev->board_id);
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -983,11 +904,12 @@ static struct device_attribute *mlx5_class_attributes[] = {
&dev_attr_reg_pages,
};
-static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
- void *data)
+static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
+ enum mlx5_dev_event event, unsigned long param)
{
- struct mlx5_ib_dev *ibdev = container_of(dev, struct mlx5_ib_dev, mdev);
+ struct mlx5_ib_dev *ibdev = (struct mlx5_ib_dev *)context;
struct ib_event ibev;
+
u8 port = 0;
switch (event) {
@@ -998,12 +920,12 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
case MLX5_DEV_EVENT_PORT_UP:
ibev.event = IB_EVENT_PORT_ACTIVE;
- port = *(u8 *)data;
+ port = (u8)param;
break;
case MLX5_DEV_EVENT_PORT_DOWN:
ibev.event = IB_EVENT_PORT_ERR;
- port = *(u8 *)data;
+ port = (u8)param;
break;
case MLX5_DEV_EVENT_PORT_INITIALIZED:
@@ -1012,22 +934,22 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
case MLX5_DEV_EVENT_LID_CHANGE:
ibev.event = IB_EVENT_LID_CHANGE;
- port = *(u8 *)data;
+ port = (u8)param;
break;
case MLX5_DEV_EVENT_PKEY_CHANGE:
ibev.event = IB_EVENT_PKEY_CHANGE;
- port = *(u8 *)data;
+ port = (u8)param;
break;
case MLX5_DEV_EVENT_GUID_CHANGE:
ibev.event = IB_EVENT_GID_CHANGE;
- port = *(u8 *)data;
+ port = (u8)param;
break;
case MLX5_DEV_EVENT_CLIENT_REREG:
ibev.event = IB_EVENT_CLIENT_REREGISTER;
- port = *(u8 *)data;
+ port = (u8)param;
break;
}
@@ -1047,7 +969,7 @@ static void get_ext_port_caps(struct mlx5_ib_dev *dev)
{
int port;
- for (port = 1; port <= dev->mdev.caps.num_ports; port++)
+ for (port = 1; port <= dev->mdev->caps.num_ports; port++)
mlx5_query_ext_port_caps(dev, port);
}
@@ -1072,14 +994,14 @@ static int get_port_caps(struct mlx5_ib_dev *dev)
goto out;
}
- for (port = 1; port <= dev->mdev.caps.num_ports; port++) {
+ for (port = 1; port <= dev->mdev->caps.num_ports; port++) {
err = mlx5_ib_query_port(&dev->ib_dev, port, pprops);
if (err) {
mlx5_ib_warn(dev, "query_port %d failed %d\n", port, err);
break;
}
- dev->mdev.caps.port[port - 1].pkey_table_len = dprops->max_pkeys;
- dev->mdev.caps.port[port - 1].gid_table_len = pprops->gid_tbl_len;
+ dev->mdev->caps.port[port - 1].pkey_table_len = dprops->max_pkeys;
+ dev->mdev->caps.port[port - 1].gid_table_len = pprops->gid_tbl_len;
mlx5_ib_dbg(dev, "pkey_table_len %d, gid_table_len %d\n",
dprops->max_pkeys, pprops->gid_tbl_len);
}
@@ -1328,10 +1250,8 @@ static void destroy_dev_resources(struct mlx5_ib_resources *devr)
mlx5_ib_dealloc_pd(devr->p0);
}
-static int init_one(struct pci_dev *pdev,
- const struct pci_device_id *id)
+static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
{
- struct mlx5_core_dev *mdev;
struct mlx5_ib_dev *dev;
int err;
int i;
@@ -1340,28 +1260,19 @@ static int init_one(struct pci_dev *pdev,
dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
if (!dev)
- return -ENOMEM;
+ return NULL;
- mdev = &dev->mdev;
- mdev->event = mlx5_ib_event;
- if (prof_sel >= ARRAY_SIZE(profile)) {
- pr_warn("selected pofile out of range, selceting default\n");
- prof_sel = 0;
- }
- mdev->profile = &profile[prof_sel];
- err = mlx5_dev_init(mdev, pdev);
- if (err)
- goto err_free;
+ dev->mdev = mdev;
err = get_port_caps(dev);
if (err)
- goto err_cleanup;
+ goto err_dealloc;
get_ext_port_caps(dev);
err = alloc_comp_eqs(dev);
if (err)
- goto err_cleanup;
+ goto err_dealloc;
MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock);
@@ -1480,7 +1391,7 @@ static int init_one(struct pci_dev *pdev,
dev->ib_active = true;
- return 0;
+ return dev;
err_umrc:
destroy_umrc_res(dev);
@@ -1494,49 +1405,39 @@ err_rsrc:
err_eqs:
free_comp_eqs(dev);
-err_cleanup:
- mlx5_dev_cleanup(mdev);
-
-err_free:
+err_dealloc:
ib_dealloc_device((struct ib_device *)dev);
- return err;
+ return NULL;
}
-static void remove_one(struct pci_dev *pdev)
+static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
{
- struct mlx5_ib_dev *dev = mlx5_pci2ibdev(pdev);
-
+ struct mlx5_ib_dev *dev = context;
destroy_umrc_res(dev);
ib_unregister_device(&dev->ib_dev);
destroy_dev_resources(&dev->devr);
free_comp_eqs(dev);
- mlx5_dev_cleanup(&dev->mdev);
ib_dealloc_device(&dev->ib_dev);
}
-static DEFINE_PCI_DEVICE_TABLE(mlx5_ib_pci_table) = {
- { PCI_VDEVICE(MELLANOX, 4113) }, /* MT4113 Connect-IB */
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mlx5_ib_pci_table);
-
-static struct pci_driver mlx5_ib_driver = {
- .name = DRIVER_NAME,
- .id_table = mlx5_ib_pci_table,
- .probe = init_one,
- .remove = remove_one
+static struct mlx5_interface mlx5_ib_interface = {
+ .add = mlx5_ib_add,
+ .remove = mlx5_ib_remove,
+ .event = mlx5_ib_event,
};
static int __init mlx5_ib_init(void)
{
- return pci_register_driver(&mlx5_ib_driver);
+ if (deprecated_prof_sel != 2)
+ pr_warn("prof_sel is deprecated for mlx5_ib, set it for mlx5_core\n");
+
+ return mlx5_register_interface(&mlx5_ib_interface);
}
static void __exit mlx5_ib_cleanup(void)
{
- pci_unregister_driver(&mlx5_ib_driver);
+ mlx5_unregister_interface(&mlx5_ib_interface);
}
module_init(mlx5_ib_init);
diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c
index 8499aec94db6..a3e81444c825 100644
--- a/drivers/infiniband/hw/mlx5/mem.c
+++ b/drivers/infiniband/hw/mlx5/mem.c
@@ -148,7 +148,7 @@ int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset)
u64 off_mask;
u64 buf_off;
- page_size = 1 << page_shift;
+ page_size = (u64)1 << page_shift;
page_mask = page_size - 1;
buf_off = addr & page_mask;
off_size = page_size >> 6;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index f2ccf1a5a291..386780f0d1e1 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -360,7 +360,7 @@ struct mlx5_ib_resources {
struct mlx5_ib_dev {
struct ib_device ib_dev;
- struct mlx5_core_dev mdev;
+ struct mlx5_core_dev *mdev;
MLX5_DECLARE_DOORBELL_LOCK(uar_lock);
struct list_head eqs_list;
int num_ports;
@@ -454,16 +454,6 @@ static inline struct mlx5_ib_ah *to_mah(struct ib_ah *ibah)
return container_of(ibah, struct mlx5_ib_ah, ibah);
}
-static inline struct mlx5_ib_dev *mlx5_core2ibdev(struct mlx5_core_dev *dev)
-{
- return container_of(dev, struct mlx5_ib_dev, mdev);
-}
-
-static inline struct mlx5_ib_dev *mlx5_pci2ibdev(struct pci_dev *pdev)
-{
- return mlx5_core2ibdev(pci2mlx5_core_dev(pdev));
-}
-
int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
struct mlx5_db *db);
void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db);
@@ -471,7 +461,7 @@ void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq)
void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
- int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
+ u8 port, struct ib_wc *in_wc, struct ib_grh *in_grh,
void *in_mad, void *response_mad);
struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr,
struct mlx5_ib_ah *ah);
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index afa873bd028e..80b3c63eab5d 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -73,7 +73,7 @@ static void reg_mr_callback(int status, void *context)
struct mlx5_cache_ent *ent = &cache->ent[c];
u8 key;
unsigned long flags;
- struct mlx5_mr_table *table = &dev->mdev.priv.mr_table;
+ struct mlx5_mr_table *table = &dev->mdev->priv.mr_table;
int err;
spin_lock_irqsave(&ent->lock, flags);
@@ -97,9 +97,9 @@ static void reg_mr_callback(int status, void *context)
return;
}
- spin_lock_irqsave(&dev->mdev.priv.mkey_lock, flags);
- key = dev->mdev.priv.mkey_key++;
- spin_unlock_irqrestore(&dev->mdev.priv.mkey_lock, flags);
+ spin_lock_irqsave(&dev->mdev->priv.mkey_lock, flags);
+ key = dev->mdev->priv.mkey_key++;
+ spin_unlock_irqrestore(&dev->mdev->priv.mkey_lock, flags);
mr->mmr.key = mlx5_idx_to_mkey(be32_to_cpu(mr->out.mkey) & 0xffffff) | key;
cache->last_add = jiffies;
@@ -155,7 +155,7 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
spin_lock_irq(&ent->lock);
ent->pending++;
spin_unlock_irq(&ent->lock);
- err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in,
+ err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in,
sizeof(*in), reg_mr_callback,
mr, &mr->out);
if (err) {
@@ -188,7 +188,7 @@ static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
ent->cur--;
ent->size--;
spin_unlock_irq(&ent->lock);
- err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+ err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
if (err)
mlx5_ib_warn(dev, "failed destroy mkey\n");
else
@@ -479,7 +479,7 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
ent->cur--;
ent->size--;
spin_unlock_irq(&ent->lock);
- err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+ err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
if (err)
mlx5_ib_warn(dev, "failed destroy mkey\n");
else
@@ -496,7 +496,7 @@ static int mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev)
if (!mlx5_debugfs_root)
return 0;
- cache->root = debugfs_create_dir("mr_cache", dev->mdev.priv.dbg_root);
+ cache->root = debugfs_create_dir("mr_cache", dev->mdev->priv.dbg_root);
if (!cache->root)
return -ENOMEM;
@@ -571,8 +571,8 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
ent->order = i + 2;
ent->dev = dev;
- if (dev->mdev.profile->mask & MLX5_PROF_MASK_MR_CACHE)
- limit = dev->mdev.profile->mr_cache[i].limit;
+ if (dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE)
+ limit = dev->mdev->profile->mr_cache[i].limit;
else
limit = 0;
@@ -610,7 +610,7 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc)
{
struct mlx5_ib_dev *dev = to_mdev(pd->device);
- struct mlx5_core_dev *mdev = &dev->mdev;
+ struct mlx5_core_dev *mdev = dev->mdev;
struct mlx5_create_mkey_mbox_in *in;
struct mlx5_mkey_seg *seg;
struct mlx5_ib_mr *mr;
@@ -846,7 +846,7 @@ static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, u64 virt_addr,
in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
in->xlat_oct_act_size = cpu_to_be32(get_octo_len(virt_addr, length,
1 << page_shift));
- err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, inlen, NULL,
+ err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, inlen, NULL,
NULL, NULL);
if (err) {
mlx5_ib_warn(dev, "create mkey failed\n");
@@ -923,7 +923,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
mr->umem = umem;
mr->npages = npages;
spin_lock(&dev->mr_lock);
- dev->mdev.priv.reg_pages += npages;
+ dev->mdev->priv.reg_pages += npages;
spin_unlock(&dev->mr_lock);
mr->ibmr.lkey = mr->mmr.key;
mr->ibmr.rkey = mr->mmr.key;
@@ -978,7 +978,7 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
int err;
if (!umred) {
- err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+ err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
if (err) {
mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
mr->mmr.key, err);
@@ -996,7 +996,7 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
if (umem) {
ib_umem_release(umem);
spin_lock(&dev->mr_lock);
- dev->mdev.priv.reg_pages -= npages;
+ dev->mdev->priv.reg_pages -= npages;
spin_unlock(&dev->mr_lock);
}
@@ -1044,7 +1044,7 @@ struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd,
}
/* create mem & wire PSVs */
- err = mlx5_core_create_psv(&dev->mdev, to_mpd(pd)->pdn,
+ err = mlx5_core_create_psv(dev->mdev, to_mpd(pd)->pdn,
2, psv_index);
if (err)
goto err_free_sig;
@@ -1060,7 +1060,7 @@ struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd,
}
in->seg.flags = MLX5_PERM_UMR_EN | access_mode;
- err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in),
+ err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, sizeof(*in),
NULL, NULL, NULL);
if (err)
goto err_destroy_psv;
@@ -1074,11 +1074,11 @@ struct ib_mr *mlx5_ib_create_mr(struct ib_pd *pd,
err_destroy_psv:
if (mr->sig) {
- if (mlx5_core_destroy_psv(&dev->mdev,
+ if (mlx5_core_destroy_psv(dev->mdev,
mr->sig->psv_memory.psv_idx))
mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
mr->sig->psv_memory.psv_idx);
- if (mlx5_core_destroy_psv(&dev->mdev,
+ if (mlx5_core_destroy_psv(dev->mdev,
mr->sig->psv_wire.psv_idx))
mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
mr->sig->psv_wire.psv_idx);
@@ -1099,18 +1099,18 @@ int mlx5_ib_destroy_mr(struct ib_mr *ibmr)
int err;
if (mr->sig) {
- if (mlx5_core_destroy_psv(&dev->mdev,
+ if (mlx5_core_destroy_psv(dev->mdev,
mr->sig->psv_memory.psv_idx))
mlx5_ib_warn(dev, "failed to destroy mem psv %d\n",
mr->sig->psv_memory.psv_idx);
- if (mlx5_core_destroy_psv(&dev->mdev,
+ if (mlx5_core_destroy_psv(dev->mdev,
mr->sig->psv_wire.psv_idx))
mlx5_ib_warn(dev, "failed to destroy wire psv %d\n",
mr->sig->psv_wire.psv_idx);
kfree(mr->sig);
}
- err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
+ err = mlx5_core_destroy_mkey(dev->mdev, &mr->mmr);
if (err) {
mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
mr->mmr.key, err);
@@ -1149,7 +1149,7 @@ struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd,
* TBD not needed - issue 197292 */
in->seg.log2_page_size = PAGE_SHIFT;
- err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in), NULL,
+ err = mlx5_core_create_mkey(dev->mdev, &mr->mmr, in, sizeof(*in), NULL,
NULL, NULL);
kfree(in);
if (err)
@@ -1202,7 +1202,7 @@ void mlx5_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
struct mlx5_ib_dev *dev = to_mdev(page_list->device);
int size = page_list->max_page_list_len * sizeof(u64);
- dma_free_coherent(&dev->mdev.pdev->dev, size, mfrpl->mapped_page_list,
+ dma_free_coherent(&dev->mdev->pdev->dev, size, mfrpl->mapped_page_list,
mfrpl->map);
kfree(mfrpl->ibfrpl.page_list);
kfree(mfrpl);
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index bbbcf389272c..8c574b63d77b 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -162,7 +162,7 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
int wq_size;
/* Sanity check RQ size before proceeding */
- if (cap->max_recv_wr > dev->mdev.caps.max_wqes)
+ if (cap->max_recv_wr > dev->mdev->caps.max_wqes)
return -EINVAL;
if (!has_rq) {
@@ -182,10 +182,10 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size;
wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB);
qp->rq.wqe_cnt = wq_size / wqe_size;
- if (wqe_size > dev->mdev.caps.max_rq_desc_sz) {
+ if (wqe_size > dev->mdev->caps.max_rq_desc_sz) {
mlx5_ib_dbg(dev, "wqe_size %d, max %d\n",
wqe_size,
- dev->mdev.caps.max_rq_desc_sz);
+ dev->mdev->caps.max_rq_desc_sz);
return -EINVAL;
}
qp->rq.wqe_shift = ilog2(wqe_size);
@@ -277,9 +277,9 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
if (wqe_size < 0)
return wqe_size;
- if (wqe_size > dev->mdev.caps.max_sq_desc_sz) {
+ if (wqe_size > dev->mdev->caps.max_sq_desc_sz) {
mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
- wqe_size, dev->mdev.caps.max_sq_desc_sz);
+ wqe_size, dev->mdev->caps.max_sq_desc_sz);
return -EINVAL;
}
@@ -292,9 +292,9 @@ static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
- if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+ if (qp->sq.wqe_cnt > dev->mdev->caps.max_wqes) {
mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
- qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+ qp->sq.wqe_cnt, dev->mdev->caps.max_wqes);
return -ENOMEM;
}
qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
@@ -311,9 +311,9 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,
{
int desc_sz = 1 << qp->sq.wqe_shift;
- if (desc_sz > dev->mdev.caps.max_sq_desc_sz) {
+ if (desc_sz > dev->mdev->caps.max_sq_desc_sz) {
mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
- desc_sz, dev->mdev.caps.max_sq_desc_sz);
+ desc_sz, dev->mdev->caps.max_sq_desc_sz);
return -EINVAL;
}
@@ -325,9 +325,9 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,
qp->sq.wqe_cnt = ucmd->sq_wqe_count;
- if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+ if (qp->sq.wqe_cnt > dev->mdev->caps.max_wqes) {
mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n",
- qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+ qp->sq.wqe_cnt, dev->mdev->caps.max_wqes);
return -EINVAL;
}
@@ -674,7 +674,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
int uuarn;
int err;
- uuari = &dev->mdev.priv.uuari;
+ uuari = &dev->mdev->priv.uuari;
if (init_attr->create_flags & ~(IB_QP_CREATE_SIGNATURE_EN | IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK))
return -EINVAL;
@@ -700,7 +700,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
qp->buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift);
- err = mlx5_buf_alloc(&dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf);
+ err = mlx5_buf_alloc(dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf);
if (err) {
mlx5_ib_dbg(dev, "err %d\n", err);
goto err_uuar;
@@ -722,7 +722,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
mlx5_fill_page_array(&qp->buf, (*in)->pas);
- err = mlx5_db_alloc(&dev->mdev, &qp->db);
+ err = mlx5_db_alloc(dev->mdev, &qp->db);
if (err) {
mlx5_ib_dbg(dev, "err %d\n", err);
goto err_free;
@@ -747,7 +747,7 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
return 0;
err_wrid:
- mlx5_db_free(&dev->mdev, &qp->db);
+ mlx5_db_free(dev->mdev, &qp->db);
kfree(qp->sq.wqe_head);
kfree(qp->sq.w_list);
kfree(qp->sq.wrid);
@@ -758,23 +758,23 @@ err_free:
mlx5_vfree(*in);
err_buf:
- mlx5_buf_free(&dev->mdev, &qp->buf);
+ mlx5_buf_free(dev->mdev, &qp->buf);
err_uuar:
- free_uuar(&dev->mdev.priv.uuari, uuarn);
+ free_uuar(&dev->mdev->priv.uuari, uuarn);
return err;
}
static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
{
- mlx5_db_free(&dev->mdev, &qp->db);
+ mlx5_db_free(dev->mdev, &qp->db);
kfree(qp->sq.wqe_head);
kfree(qp->sq.w_list);
kfree(qp->sq.wrid);
kfree(qp->sq.wr_data);
kfree(qp->rq.wrid);
- mlx5_buf_free(&dev->mdev, &qp->buf);
- free_uuar(&dev->mdev.priv.uuari, qp->bf->uuarn);
+ mlx5_buf_free(dev->mdev, &qp->buf);
+ free_uuar(&dev->mdev->priv.uuari, qp->bf->uuarn);
}
static __be32 get_rx_type(struct mlx5_ib_qp *qp, struct ib_qp_init_attr *attr)
@@ -812,7 +812,7 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
spin_lock_init(&qp->rq.lock);
if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
- if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
+ if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) {
mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
return -EINVAL;
} else {
@@ -851,9 +851,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
mlx5_ib_dbg(dev, "invalid rq params\n");
return -EINVAL;
}
- if (ucmd.sq_wqe_count > dev->mdev.caps.max_wqes) {
+ if (ucmd.sq_wqe_count > dev->mdev->caps.max_wqes) {
mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n",
- ucmd.sq_wqe_count, dev->mdev.caps.max_wqes);
+ ucmd.sq_wqe_count, dev->mdev->caps.max_wqes);
return -EINVAL;
}
err = create_user_qp(dev, pd, qp, udata, &in, &resp, &inlen);
@@ -957,7 +957,7 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
in->ctx.db_rec_addr = cpu_to_be64(qp->db.dma);
- err = mlx5_core_create_qp(&dev->mdev, &qp->mqp, in, inlen);
+ err = mlx5_core_create_qp(dev->mdev, &qp->mqp, in, inlen);
if (err) {
mlx5_ib_dbg(dev, "create qp failed\n");
goto err_create;
@@ -1081,7 +1081,7 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
if (!in)
return;
if (qp->state != IB_QPS_RESET)
- if (mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(qp->state),
+ if (mlx5_core_qp_modify(dev->mdev, to_mlx5_state(qp->state),
MLX5_QP_STATE_RST, in, sizeof(*in), &qp->mqp))
mlx5_ib_warn(dev, "mlx5_ib: modify QP %06x to RESET failed\n",
qp->mqp.qpn);
@@ -1097,7 +1097,7 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
mlx5_ib_unlock_cqs(send_cq, recv_cq);
}
- err = mlx5_core_destroy_qp(&dev->mdev, &qp->mqp);
+ err = mlx5_core_destroy_qp(dev->mdev, &qp->mqp);
if (err)
mlx5_ib_warn(dev, "failed to destroy QP 0x%x\n", qp->mqp.qpn);
kfree(in);
@@ -1165,7 +1165,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
switch (init_attr->qp_type) {
case IB_QPT_XRC_TGT:
case IB_QPT_XRC_INI:
- if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC)) {
+ if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_XRC)) {
mlx5_ib_dbg(dev, "XRC not supported\n");
return ERR_PTR(-ENOSYS);
}
@@ -1279,7 +1279,7 @@ static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate)
} else {
while (rate != IB_RATE_2_5_GBPS &&
!(1 << (rate + MLX5_STAT_RATE_OFFSET) &
- dev->mdev.caps.stat_rate_support))
+ dev->mdev->caps.stat_rate_support))
--rate;
}
@@ -1318,9 +1318,9 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, const struct ib_ah_attr *ah,
path->port = port;
if (ah->ah_flags & IB_AH_GRH) {
- if (ah->grh.sgid_index >= dev->mdev.caps.port[port - 1].gid_table_len) {
+ if (ah->grh.sgid_index >= dev->mdev->caps.port[port - 1].gid_table_len) {
pr_err(KERN_ERR "sgid_index (%u) too large. max is %d\n",
- ah->grh.sgid_index, dev->mdev.caps.port[port - 1].gid_table_len);
+ ah->grh.sgid_index, dev->mdev->caps.port[port - 1].gid_table_len);
return -EINVAL;
}
@@ -1539,7 +1539,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
err = -EINVAL;
goto out;
}
- context->mtu_msgmax = (attr->path_mtu << 5) | dev->mdev.caps.log_max_msg;
+ context->mtu_msgmax = (attr->path_mtu << 5) | dev->mdev->caps.log_max_msg;
}
if (attr_mask & IB_QP_DEST_QPN)
@@ -1637,7 +1637,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
optpar = ib_mask_to_mlx5_opt(attr_mask);
optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st];
in->optparam = cpu_to_be32(optpar);
- err = mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(cur_state),
+ err = mlx5_core_qp_modify(dev->mdev, to_mlx5_state(cur_state),
to_mlx5_state(new_state), in, sqd_event,
&qp->mqp);
if (err)
@@ -1699,21 +1699,21 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
goto out;
if ((attr_mask & IB_QP_PORT) &&
- (attr->port_num == 0 || attr->port_num > dev->mdev.caps.num_ports))
+ (attr->port_num == 0 || attr->port_num > dev->mdev->caps.num_ports))
goto out;
if (attr_mask & IB_QP_PKEY_INDEX) {
port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
- if (attr->pkey_index >= dev->mdev.caps.port[port - 1].pkey_table_len)
+ if (attr->pkey_index >= dev->mdev->caps.port[port - 1].pkey_table_len)
goto out;
}
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
- attr->max_rd_atomic > dev->mdev.caps.max_ra_res_qp)
+ attr->max_rd_atomic > dev->mdev->caps.max_ra_res_qp)
goto out;
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
- attr->max_dest_rd_atomic > dev->mdev.caps.max_ra_req_qp)
+ attr->max_dest_rd_atomic > dev->mdev->caps.max_ra_req_qp)
goto out;
if (cur_state == new_state && cur_state == IB_QPS_RESET) {
@@ -2479,7 +2479,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
{
struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
- struct mlx5_core_dev *mdev = &dev->mdev;
+ struct mlx5_core_dev *mdev = dev->mdev;
struct mlx5_ib_qp *qp = to_mqp(ibqp);
struct mlx5_ib_mr *mr;
struct mlx5_wqe_data_seg *dpseg;
@@ -2501,7 +2501,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
spin_lock_irqsave(&qp->sq.lock, flags);
for (nreq = 0; wr; nreq++, wr = wr->next) {
- if (unlikely(wr->opcode >= sizeof(mlx5_ib_opcode) / sizeof(mlx5_ib_opcode[0]))) {
+ if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
mlx5_ib_warn(dev, "\n");
err = -EINVAL;
*bad_wr = wr;
@@ -2539,7 +2539,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_WR_RDMA_WRITE_WITH_IMM:
set_raddr_seg(seg, wr->wr.rdma.remote_addr,
wr->wr.rdma.rkey);
- seg += sizeof(struct mlx5_wqe_raddr_seg);
+ seg += sizeof(struct mlx5_wqe_raddr_seg);
size += sizeof(struct mlx5_wqe_raddr_seg) / 16;
break;
@@ -2668,7 +2668,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
case IB_QPT_SMI:
case IB_QPT_GSI:
set_datagram_seg(seg, wr);
- seg += sizeof(struct mlx5_wqe_datagram_seg);
+ seg += sizeof(struct mlx5_wqe_datagram_seg);
size += sizeof(struct mlx5_wqe_datagram_seg) / 16;
if (unlikely((seg == qend)))
seg = mlx5_get_send_wqe(qp, 0);
@@ -2888,7 +2888,7 @@ static int to_ib_qp_access_flags(int mlx5_flags)
static void to_ib_ah_attr(struct mlx5_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr,
struct mlx5_qp_path *path)
{
- struct mlx5_core_dev *dev = &ibdev->mdev;
+ struct mlx5_core_dev *dev = ibdev->mdev;
memset(ib_ah_attr, 0, sizeof(*ib_ah_attr));
ib_ah_attr->port_num = path->port;
@@ -2931,7 +2931,7 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
goto out;
}
context = &outb->ctx;
- err = mlx5_core_qp_query(&dev->mdev, &qp->mqp, outb, sizeof(*outb));
+ err = mlx5_core_qp_query(dev->mdev, &qp->mqp, outb, sizeof(*outb));
if (err)
goto out_free;
@@ -3014,14 +3014,14 @@ struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev,
struct mlx5_ib_xrcd *xrcd;
int err;
- if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC))
+ if (!(dev->mdev->caps.flags & MLX5_DEV_CAP_FLAG_XRC))
return ERR_PTR(-ENOSYS);
xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL);
if (!xrcd)
return ERR_PTR(-ENOMEM);
- err = mlx5_core_xrcd_alloc(&dev->mdev, &xrcd->xrcdn);
+ err = mlx5_core_xrcd_alloc(dev->mdev, &xrcd->xrcdn);
if (err) {
kfree(xrcd);
return ERR_PTR(-ENOMEM);
@@ -3036,7 +3036,7 @@ int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
u32 xrcdn = to_mxrcd(xrcd)->xrcdn;
int err;
- err = mlx5_core_xrcd_dealloc(&dev->mdev, xrcdn);
+ err = mlx5_core_xrcd_dealloc(dev->mdev, xrcdn);
if (err) {
mlx5_ib_warn(dev, "failed to dealloc xrcdn 0x%x\n", xrcdn);
return err;
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 384af6dec5eb..70bd131ba646 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -159,7 +159,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
int page_shift;
int npages;
- err = mlx5_db_alloc(&dev->mdev, &srq->db);
+ err = mlx5_db_alloc(dev->mdev, &srq->db);
if (err) {
mlx5_ib_warn(dev, "alloc dbell rec failed\n");
return err;
@@ -167,7 +167,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
*srq->db.db = 0;
- if (mlx5_buf_alloc(&dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) {
+ if (mlx5_buf_alloc(dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) {
mlx5_ib_dbg(dev, "buf alloc failed\n");
err = -ENOMEM;
goto err_db;
@@ -212,10 +212,10 @@ err_in:
mlx5_vfree(*in);
err_buf:
- mlx5_buf_free(&dev->mdev, &srq->buf);
+ mlx5_buf_free(dev->mdev, &srq->buf);
err_db:
- mlx5_db_free(&dev->mdev, &srq->db);
+ mlx5_db_free(dev->mdev, &srq->db);
return err;
}
@@ -229,8 +229,8 @@ static void destroy_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq)
static void destroy_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq)
{
kfree(srq->wrid);
- mlx5_buf_free(&dev->mdev, &srq->buf);
- mlx5_db_free(&dev->mdev, &srq->db);
+ mlx5_buf_free(dev->mdev, &srq->buf);
+ mlx5_db_free(dev->mdev, &srq->db);
}
struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
@@ -248,10 +248,10 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
u32 flgs, xrcdn;
/* Sanity check SRQ size before proceeding */
- if (init_attr->attr.max_wr >= dev->mdev.caps.max_srq_wqes) {
+ if (init_attr->attr.max_wr >= dev->mdev->caps.max_srq_wqes) {
mlx5_ib_dbg(dev, "max_wr %d, cap %d\n",
init_attr->attr.max_wr,
- dev->mdev.caps.max_srq_wqes);
+ dev->mdev->caps.max_srq_wqes);
return ERR_PTR(-EINVAL);
}
@@ -303,7 +303,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn);
in->ctx.db_record = cpu_to_be64(srq->db.dma);
- err = mlx5_core_create_srq(&dev->mdev, &srq->msrq, in, inlen);
+ err = mlx5_core_create_srq(dev->mdev, &srq->msrq, in, inlen);
mlx5_vfree(in);
if (err) {
mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
@@ -327,7 +327,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
return &srq->ibsrq;
err_core:
- mlx5_core_destroy_srq(&dev->mdev, &srq->msrq);
+ mlx5_core_destroy_srq(dev->mdev, &srq->msrq);
err_usr_kern_srq:
if (pd->uobject)
@@ -357,7 +357,7 @@ int mlx5_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return -EINVAL;
mutex_lock(&srq->mutex);
- ret = mlx5_core_arm_srq(&dev->mdev, &srq->msrq, attr->srq_limit, 1);
+ ret = mlx5_core_arm_srq(dev->mdev, &srq->msrq, attr->srq_limit, 1);
mutex_unlock(&srq->mutex);
if (ret)
@@ -378,7 +378,7 @@ int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
if (!out)
return -ENOMEM;
- ret = mlx5_core_query_srq(&dev->mdev, &srq->msrq, out);
+ ret = mlx5_core_query_srq(dev->mdev, &srq->msrq, out);
if (ret)
goto out_box;
@@ -396,7 +396,7 @@ int mlx5_ib_destroy_srq(struct ib_srq *srq)
struct mlx5_ib_dev *dev = to_mdev(srq->device);
struct mlx5_ib_srq *msrq = to_msrq(srq);
- mlx5_core_destroy_srq(&dev->mdev, &msrq->msrq);
+ mlx5_core_destroy_srq(dev->mdev, &msrq->msrq);
if (srq->uobject) {
mlx5_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index b6f7f457fc55..8881fa376e06 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -294,7 +294,7 @@ int mthca_create_agents(struct mthca_dev *dev)
agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
q ? IB_QPT_GSI : IB_QPT_SMI,
NULL, 0, send_handler,
- NULL, NULL);
+ NULL, NULL, 0);
if (IS_ERR(agent)) {
ret = PTR_ERR(agent);
goto err;
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 90200245c5eb..02120d340d50 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -1003,13 +1003,13 @@ int nes_init_cqp(struct nes_device *nesdev)
(sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
sizeof(struct nes_hw_cqp_qp_context);
- nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
- &nesdev->cqp_pbase);
+ nesdev->cqp_vbase = pci_zalloc_consistent(nesdev->pcidev,
+ nesdev->cqp_mem_size,
+ &nesdev->cqp_pbase);
if (!nesdev->cqp_vbase) {
nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
return -ENOMEM;
}
- memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
/* Allocate a twice the number of CQP requests as the SQ size */
nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
@@ -1691,13 +1691,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
(NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
sizeof(struct nes_hw_nic_qp_context);
- nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
- &nesvnic->nic_pbase);
+ nesvnic->nic_vbase = pci_zalloc_consistent(nesdev->pcidev,
+ nesvnic->nic_mem_size,
+ &nesvnic->nic_pbase);
if (!nesvnic->nic_vbase) {
nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
return -ENOMEM;
}
- memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 218dd3574285..fef067c959fc 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1616,8 +1616,8 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
entries, nescq->cq_mem_size, nescq->hw_cq.cq_number);
/* allocate the physical buffer space */
- mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
- &nescq->hw_cq.cq_pbase);
+ mem = pci_zalloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
+ &nescq->hw_cq.cq_pbase);
if (!mem) {
printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n");
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
@@ -1625,7 +1625,6 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
return ERR_PTR(-ENOMEM);
}
- memset(mem, 0, nescq->cq_mem_size);
nescq->hw_cq.cq_vbase = mem;
nescq->hw_cq.cq_head = 0;
nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n",
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index 19011dbb930f..b43456ae124b 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -40,7 +40,7 @@
#include <be_roce.h>
#include "ocrdma_sli.h"
-#define OCRDMA_ROCE_DRV_VERSION "10.2.145.0u"
+#define OCRDMA_ROCE_DRV_VERSION "10.2.287.0u"
#define OCRDMA_ROCE_DRV_DESC "Emulex OneConnect RoCE Driver"
#define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA"
@@ -137,6 +137,7 @@ struct mqe_ctx {
u16 cqe_status;
u16 ext_status;
bool cmd_done;
+ bool fw_error_state;
};
struct ocrdma_hw_mr {
@@ -235,7 +236,10 @@ struct ocrdma_dev {
struct list_head entry;
struct rcu_head rcu;
int id;
- u64 stag_arr[OCRDMA_MAX_STAG];
+ u64 *stag_arr;
+ u8 sl; /* service level */
+ bool pfc_state;
+ atomic_t update_sl;
u16 pvid;
u32 asic_id;
@@ -518,4 +522,22 @@ static inline u8 ocrdma_get_asic_type(struct ocrdma_dev *dev)
OCRDMA_SLI_ASIC_GEN_NUM_SHIFT;
}
+static inline u8 ocrdma_get_pfc_prio(u8 *pfc, u8 prio)
+{
+ return *(pfc + prio);
+}
+
+static inline u8 ocrdma_get_app_prio(u8 *app_prio, u8 prio)
+{
+ return *(app_prio + prio);
+}
+
+static inline u8 ocrdma_is_enabled_and_synced(u32 state)
+{ /* May also be used to interpret TC-state, QCN-state
+ * Appl-state and Logical-link-state in future.
+ */
+ return (state & OCRDMA_STATE_FLAG_ENABLED) &&
+ (state & OCRDMA_STATE_FLAG_SYNC);
+}
+
#endif
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index d4cc01f10c01..40f8536c10b0 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -35,6 +35,8 @@
#include "ocrdma_ah.h"
#include "ocrdma_hw.h"
+#define OCRDMA_VID_PCP_SHIFT 0xD
+
static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
struct ib_ah_attr *attr, int pdid)
{
@@ -55,7 +57,7 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
if (vlan_tag && (vlan_tag < 0x1000)) {
eth.eth_type = cpu_to_be16(0x8100);
eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
- vlan_tag |= (attr->sl & 7) << 13;
+ vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
eth.vlan_tag = cpu_to_be16(vlan_tag);
eth_sz = sizeof(struct ocrdma_eth_vlan);
vlan_enabled = true;
@@ -100,6 +102,8 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
if (!(attr->ah_flags & IB_AH_GRH))
return ERR_PTR(-EINVAL);
+ if (atomic_cmpxchg(&dev->update_sl, 1, 0))
+ ocrdma_init_service_level(dev);
ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
if (!ah)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 3bbf2010a821..dd35ae558ae1 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -525,7 +525,7 @@ static int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev,
cmd->ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
cmd->eqn = eq->id;
- cmd->cqe_count = cq->size / sizeof(struct ocrdma_mcqe);
+ cmd->pdid_cqecnt = cq->size / sizeof(struct ocrdma_mcqe);
ocrdma_build_q_pages(&cmd->pa[0], cq->size / OCRDMA_MIN_Q_PAGE_SIZE,
cq->dma, PAGE_SIZE_4K);
@@ -661,7 +661,7 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev,
{
struct ocrdma_qp *qp = NULL;
struct ocrdma_cq *cq = NULL;
- struct ib_event ib_evt = { 0 };
+ struct ib_event ib_evt;
int cq_event = 0;
int qp_event = 1;
int srq_event = 0;
@@ -674,6 +674,8 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev,
if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID)
cq = dev->cq_tbl[cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK];
+ memset(&ib_evt, 0, sizeof(ib_evt));
+
ib_evt.device = &dev->ibdev;
switch (type) {
@@ -771,6 +773,10 @@ static void ocrdma_process_grp5_aync(struct ocrdma_dev *dev,
OCRDMA_AE_PVID_MCQE_TAG_MASK) >>
OCRDMA_AE_PVID_MCQE_TAG_SHIFT);
break;
+
+ case OCRDMA_ASYNC_EVENT_COS_VALUE:
+ atomic_set(&dev->update_sl, 1);
+ break;
default:
/* Not interested evts. */
break;
@@ -962,8 +968,12 @@ static int ocrdma_wait_mqe_cmpl(struct ocrdma_dev *dev)
msecs_to_jiffies(30000));
if (status)
return 0;
- else
+ else {
+ dev->mqe_ctx.fw_error_state = true;
+ pr_err("%s(%d) mailbox timeout: fw not responding\n",
+ __func__, dev->id);
return -1;
+ }
}
/* issue a mailbox command on the MQ */
@@ -975,6 +985,8 @@ static int ocrdma_mbx_cmd(struct ocrdma_dev *dev, struct ocrdma_mqe *mqe)
struct ocrdma_mbx_rsp *rsp = NULL;
mutex_lock(&dev->mqe_ctx.lock);
+ if (dev->mqe_ctx.fw_error_state)
+ goto mbx_err;
ocrdma_post_mqe(dev, mqe);
status = ocrdma_wait_mqe_cmpl(dev);
if (status)
@@ -1078,7 +1090,8 @@ static void ocrdma_get_attr(struct ocrdma_dev *dev,
OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT;
attr->max_mw = rsp->max_mw;
attr->max_mr = rsp->max_mr;
- attr->max_mr_size = ~0ull;
+ attr->max_mr_size = ((u64)rsp->max_mr_size_hi << 32) |
+ rsp->max_mr_size_lo;
attr->max_fmr = 0;
attr->max_pages_per_frmr = rsp->max_pages_per_frmr;
attr->max_num_mr_pbl = rsp->max_num_mr_pbl;
@@ -1252,7 +1265,9 @@ static int ocrdma_mbx_get_ctrl_attribs(struct ocrdma_dev *dev)
ctrl_attr_rsp = (struct ocrdma_get_ctrl_attribs_rsp *)dma.va;
hba_attribs = &ctrl_attr_rsp->ctrl_attribs.hba_attribs;
- dev->hba_port_num = hba_attribs->phy_port;
+ dev->hba_port_num = (hba_attribs->ptpnum_maxdoms_hbast_cv &
+ OCRDMA_HBA_ATTRB_PTNUM_MASK)
+ >> OCRDMA_HBA_ATTRB_PTNUM_SHIFT;
strncpy(dev->model_number,
hba_attribs->controller_model_number, 31);
}
@@ -1302,7 +1317,8 @@ int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed)
goto mbx_err;
rsp = (struct ocrdma_get_link_speed_rsp *)cmd;
- *lnk_speed = rsp->phys_port_speed;
+ *lnk_speed = (rsp->pflt_pps_ld_pnum & OCRDMA_PHY_PS_MASK)
+ >> OCRDMA_PHY_PS_SHIFT;
mbx_err:
kfree(cmd);
@@ -1328,11 +1344,16 @@ static int ocrdma_mbx_get_phy_info(struct ocrdma_dev *dev)
goto mbx_err;
rsp = (struct ocrdma_get_phy_info_rsp *)cmd;
- dev->phy.phy_type = le16_to_cpu(rsp->phy_type);
+ dev->phy.phy_type =
+ (rsp->ityp_ptyp & OCRDMA_PHY_TYPE_MASK);
+ dev->phy.interface_type =
+ (rsp->ityp_ptyp & OCRDMA_IF_TYPE_MASK)
+ >> OCRDMA_IF_TYPE_SHIFT;
dev->phy.auto_speeds_supported =
- le16_to_cpu(rsp->auto_speeds_supported);
+ (rsp->fspeed_aspeed & OCRDMA_ASPEED_SUPP_MASK);
dev->phy.fixed_speeds_supported =
- le16_to_cpu(rsp->fixed_speeds_supported);
+ (rsp->fspeed_aspeed & OCRDMA_FSPEED_SUPP_MASK)
+ >> OCRDMA_FSPEED_SUPP_SHIFT;
mbx_err:
kfree(cmd);
return status;
@@ -1457,8 +1478,8 @@ static int ocrdma_mbx_create_ah_tbl(struct ocrdma_dev *dev)
pbes = (struct ocrdma_pbe *)dev->av_tbl.pbl.va;
for (i = 0; i < dev->av_tbl.size / OCRDMA_MIN_Q_PAGE_SIZE; i++) {
- pbes[i].pa_lo = (u32) (pa & 0xffffffff);
- pbes[i].pa_hi = (u32) upper_32_bits(pa);
+ pbes[i].pa_lo = (u32)cpu_to_le32(pa & 0xffffffff);
+ pbes[i].pa_hi = (u32)cpu_to_le32(upper_32_bits(pa));
pa += PAGE_SIZE;
}
cmd->tbl_addr[0].lo = (u32)(dev->av_tbl.pbl.pa & 0xFFFFFFFF);
@@ -1501,6 +1522,7 @@ static void ocrdma_mbx_delete_ah_tbl(struct ocrdma_dev *dev)
ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
dev->av_tbl.pa);
+ dev->av_tbl.va = NULL;
dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
dev->av_tbl.pbl.pa);
kfree(cmd);
@@ -1624,14 +1646,16 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
cmd->cmd.pgsz_pgcnt |= OCRDMA_CREATE_CQ_DPP <<
OCRDMA_CREATE_CQ_TYPE_SHIFT;
cq->phase_change = false;
- cmd->cmd.cqe_count = (cq->len / cqe_size);
+ cmd->cmd.pdid_cqecnt = (cq->len / cqe_size);
} else {
- cmd->cmd.cqe_count = (cq->len / cqe_size) - 1;
+ cmd->cmd.pdid_cqecnt = (cq->len / cqe_size) - 1;
cmd->cmd.ev_cnt_flags |= OCRDMA_CREATE_CQ_FLAGS_AUTO_VALID;
cq->phase_change = true;
}
- cmd->cmd.pd_id = pd_id; /* valid only for v3 */
+ /* pd_id valid only for v3 */
+ cmd->cmd.pdid_cqecnt |= (pd_id <<
+ OCRDMA_CREATE_CQ_CMD_PDID_SHIFT);
ocrdma_build_q_pages(&cmd->cmd.pa[0], hw_pages, cq->pa, page_size);
status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
if (status)
@@ -2206,7 +2230,8 @@ int ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs,
OCRDMA_CREATE_QP_REQ_RQ_CQID_MASK;
qp->rq_cq = cq;
- if (pd->dpp_enabled && pd->num_dpp_qp) {
+ if (pd->dpp_enabled && attrs->cap.max_inline_data && pd->num_dpp_qp &&
+ (attrs->cap.max_inline_data <= dev->attr.max_inline_data)) {
ocrdma_set_create_qp_dpp_cmd(cmd, pd, qp, enable_dpp_cq,
dpp_cq_id);
}
@@ -2264,6 +2289,8 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
if ((ah_attr->ah_flags & IB_AH_GRH) == 0)
return -EINVAL;
+ if (atomic_cmpxchg(&qp->dev->update_sl, 1, 0))
+ ocrdma_init_service_level(qp->dev);
cmd->params.tclass_sq_psn |=
(ah_attr->grh.traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT);
cmd->params.rnt_rc_sl_fl |=
@@ -2297,6 +2324,8 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
cmd->params.vlan_dmac_b4_to_b5 |=
vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID;
+ cmd->params.rnt_rc_sl_fl |=
+ (qp->dev->sl & 0x07) << OCRDMA_QP_PARAMS_SL_SHIFT;
}
return 0;
}
@@ -2604,6 +2633,168 @@ int ocrdma_mbx_destroy_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq)
return status;
}
+static int ocrdma_mbx_get_dcbx_config(struct ocrdma_dev *dev, u32 ptype,
+ struct ocrdma_dcbx_cfg *dcbxcfg)
+{
+ int status = 0;
+ dma_addr_t pa;
+ struct ocrdma_mqe cmd;
+
+ struct ocrdma_get_dcbx_cfg_req *req = NULL;
+ struct ocrdma_get_dcbx_cfg_rsp *rsp = NULL;
+ struct pci_dev *pdev = dev->nic_info.pdev;
+ struct ocrdma_mqe_sge *mqe_sge = cmd.u.nonemb_req.sge;
+
+ memset(&cmd, 0, sizeof(struct ocrdma_mqe));
+ cmd.hdr.pyld_len = max_t (u32, sizeof(struct ocrdma_get_dcbx_cfg_rsp),
+ sizeof(struct ocrdma_get_dcbx_cfg_req));
+ req = dma_alloc_coherent(&pdev->dev, cmd.hdr.pyld_len, &pa, GFP_KERNEL);
+ if (!req) {
+ status = -ENOMEM;
+ goto mem_err;
+ }
+
+ cmd.hdr.spcl_sge_cnt_emb |= (1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) &
+ OCRDMA_MQE_HDR_SGE_CNT_MASK;
+ mqe_sge->pa_lo = (u32) (pa & 0xFFFFFFFFUL);
+ mqe_sge->pa_hi = (u32) upper_32_bits(pa);
+ mqe_sge->len = cmd.hdr.pyld_len;
+
+ memset(req, 0, sizeof(struct ocrdma_get_dcbx_cfg_req));
+ ocrdma_init_mch(&req->hdr, OCRDMA_CMD_GET_DCBX_CONFIG,
+ OCRDMA_SUBSYS_DCBX, cmd.hdr.pyld_len);
+ req->param_type = ptype;
+
+ status = ocrdma_mbx_cmd(dev, &cmd);
+ if (status)
+ goto mbx_err;
+
+ rsp = (struct ocrdma_get_dcbx_cfg_rsp *)req;
+ ocrdma_le32_to_cpu(rsp, sizeof(struct ocrdma_get_dcbx_cfg_rsp));
+ memcpy(dcbxcfg, &rsp->cfg, sizeof(struct ocrdma_dcbx_cfg));
+
+mbx_err:
+ dma_free_coherent(&pdev->dev, cmd.hdr.pyld_len, req, pa);
+mem_err:
+ return status;
+}
+
+#define OCRDMA_MAX_SERVICE_LEVEL_INDEX 0x08
+#define OCRDMA_DEFAULT_SERVICE_LEVEL 0x05
+
+static int ocrdma_parse_dcbxcfg_rsp(struct ocrdma_dev *dev, int ptype,
+ struct ocrdma_dcbx_cfg *dcbxcfg,
+ u8 *srvc_lvl)
+{
+ int status = -EINVAL, indx, slindx;
+ int ventry_cnt;
+ struct ocrdma_app_parameter *app_param;
+ u8 valid, proto_sel;
+ u8 app_prio, pfc_prio;
+ u16 proto;
+
+ if (!(dcbxcfg->tcv_aev_opv_st & OCRDMA_DCBX_STATE_MASK)) {
+ pr_info("%s ocrdma%d DCBX is disabled\n",
+ dev_name(&dev->nic_info.pdev->dev), dev->id);
+ goto out;
+ }
+
+ if (!ocrdma_is_enabled_and_synced(dcbxcfg->pfc_state)) {
+ pr_info("%s ocrdma%d priority flow control(%s) is %s%s\n",
+ dev_name(&dev->nic_info.pdev->dev), dev->id,
+ (ptype > 0 ? "operational" : "admin"),
+ (dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_ENABLED) ?
+ "enabled" : "disabled",
+ (dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_SYNC) ?
+ "" : ", not sync'ed");
+ goto out;
+ } else {
+ pr_info("%s ocrdma%d priority flow control is enabled and sync'ed\n",
+ dev_name(&dev->nic_info.pdev->dev), dev->id);
+ }
+
+ ventry_cnt = (dcbxcfg->tcv_aev_opv_st >>
+ OCRDMA_DCBX_APP_ENTRY_SHIFT)
+ & OCRDMA_DCBX_STATE_MASK;
+
+ for (indx = 0; indx < ventry_cnt; indx++) {
+ app_param = &dcbxcfg->app_param[indx];
+ valid = (app_param->valid_proto_app >>
+ OCRDMA_APP_PARAM_VALID_SHIFT)
+ & OCRDMA_APP_PARAM_VALID_MASK;
+ proto_sel = (app_param->valid_proto_app
+ >> OCRDMA_APP_PARAM_PROTO_SEL_SHIFT)
+ & OCRDMA_APP_PARAM_PROTO_SEL_MASK;
+ proto = app_param->valid_proto_app &
+ OCRDMA_APP_PARAM_APP_PROTO_MASK;
+
+ if (
+ valid && proto == OCRDMA_APP_PROTO_ROCE &&
+ proto_sel == OCRDMA_PROTO_SELECT_L2) {
+ for (slindx = 0; slindx <
+ OCRDMA_MAX_SERVICE_LEVEL_INDEX; slindx++) {
+ app_prio = ocrdma_get_app_prio(
+ (u8 *)app_param->app_prio,
+ slindx);
+ pfc_prio = ocrdma_get_pfc_prio(
+ (u8 *)dcbxcfg->pfc_prio,
+ slindx);
+
+ if (app_prio && pfc_prio) {
+ *srvc_lvl = slindx;
+ status = 0;
+ goto out;
+ }
+ }
+ if (slindx == OCRDMA_MAX_SERVICE_LEVEL_INDEX) {
+ pr_info("%s ocrdma%d application priority not set for 0x%x protocol\n",
+ dev_name(&dev->nic_info.pdev->dev),
+ dev->id, proto);
+ }
+ }
+ }
+
+out:
+ return status;
+}
+
+void ocrdma_init_service_level(struct ocrdma_dev *dev)
+{
+ int status = 0, indx;
+ struct ocrdma_dcbx_cfg dcbxcfg;
+ u8 srvc_lvl = OCRDMA_DEFAULT_SERVICE_LEVEL;
+ int ptype = OCRDMA_PARAMETER_TYPE_OPER;
+
+ for (indx = 0; indx < 2; indx++) {
+ status = ocrdma_mbx_get_dcbx_config(dev, ptype, &dcbxcfg);
+ if (status) {
+ pr_err("%s(): status=%d\n", __func__, status);
+ ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
+ continue;
+ }
+
+ status = ocrdma_parse_dcbxcfg_rsp(dev, ptype,
+ &dcbxcfg, &srvc_lvl);
+ if (status) {
+ ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
+ continue;
+ }
+
+ break;
+ }
+
+ if (status)
+ pr_info("%s ocrdma%d service level default\n",
+ dev_name(&dev->nic_info.pdev->dev), dev->id);
+ else
+ pr_info("%s ocrdma%d service level %d\n",
+ dev_name(&dev->nic_info.pdev->dev), dev->id,
+ srvc_lvl);
+
+ dev->pfc_state = ocrdma_is_enabled_and_synced(dcbxcfg.pfc_state);
+ dev->sl = srvc_lvl;
+}
+
int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
{
int i;
@@ -2709,13 +2900,15 @@ int ocrdma_init_hw(struct ocrdma_dev *dev)
goto conf_err;
status = ocrdma_mbx_get_phy_info(dev);
if (status)
- goto conf_err;
+ goto info_attrb_err;
status = ocrdma_mbx_get_ctrl_attribs(dev);
if (status)
- goto conf_err;
+ goto info_attrb_err;
return 0;
+info_attrb_err:
+ ocrdma_mbx_delete_ah_tbl(dev);
conf_err:
ocrdma_destroy_mq(dev);
mq_err:
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
index e513f7293142..6eed8f191322 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
@@ -135,4 +135,6 @@ int ocrdma_get_irq(struct ocrdma_dev *dev, struct ocrdma_eq *eq);
int ocrdma_mbx_rdma_stats(struct ocrdma_dev *, bool reset);
char *port_speed_string(struct ocrdma_dev *dev);
+void ocrdma_init_service_level(struct ocrdma_dev *);
+
#endif /* __OCRDMA_HW_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 7c504e079744..256a06bc0b68 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -324,6 +324,11 @@ static int ocrdma_alloc_resources(struct ocrdma_dev *dev)
if (!dev->qp_tbl)
goto alloc_err;
}
+
+ dev->stag_arr = kzalloc(sizeof(u64) * OCRDMA_MAX_STAG, GFP_KERNEL);
+ if (dev->stag_arr == NULL)
+ goto alloc_err;
+
spin_lock_init(&dev->av_tbl.lock);
spin_lock_init(&dev->flush_q_lock);
return 0;
@@ -334,6 +339,7 @@ alloc_err:
static void ocrdma_free_resources(struct ocrdma_dev *dev)
{
+ kfree(dev->stag_arr);
kfree(dev->qp_tbl);
kfree(dev->cq_tbl);
kfree(dev->sgid_tbl);
@@ -353,15 +359,25 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
{
struct ocrdma_dev *dev = dev_get_drvdata(device);
- return scnprintf(buf, PAGE_SIZE, "%s", &dev->attr.fw_ver[0]);
+ return scnprintf(buf, PAGE_SIZE, "%s\n", &dev->attr.fw_ver[0]);
+}
+
+static ssize_t show_hca_type(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct ocrdma_dev *dev = dev_get_drvdata(device);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", &dev->model_number[0]);
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
+static DEVICE_ATTR(hca_type, S_IRUGO, show_hca_type, NULL);
static struct device_attribute *ocrdma_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver
+ &dev_attr_fw_ver,
+ &dev_attr_hca_type
};
static void ocrdma_remove_sysfiles(struct ocrdma_dev *dev)
@@ -372,6 +388,58 @@ static void ocrdma_remove_sysfiles(struct ocrdma_dev *dev)
device_remove_file(&dev->ibdev.dev, ocrdma_attributes[i]);
}
+static void ocrdma_init_ipv4_gids(struct ocrdma_dev *dev,
+ struct net_device *net)
+{
+ struct in_device *in_dev;
+ union ib_gid gid;
+ in_dev = in_dev_get(net);
+ if (in_dev) {
+ for_ifa(in_dev) {
+ ipv6_addr_set_v4mapped(ifa->ifa_address,
+ (struct in6_addr *)&gid);
+ ocrdma_add_sgid(dev, &gid);
+ }
+ endfor_ifa(in_dev);
+ in_dev_put(in_dev);
+ }
+}
+
+static void ocrdma_init_ipv6_gids(struct ocrdma_dev *dev,
+ struct net_device *net)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+ struct inet6_dev *in6_dev;
+ union ib_gid *pgid;
+ struct inet6_ifaddr *ifp;
+ in6_dev = in6_dev_get(net);
+ if (in6_dev) {
+ read_lock_bh(&in6_dev->lock);
+ list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
+ pgid = (union ib_gid *)&ifp->addr;
+ ocrdma_add_sgid(dev, pgid);
+ }
+ read_unlock_bh(&in6_dev->lock);
+ in6_dev_put(in6_dev);
+ }
+#endif
+}
+
+static void ocrdma_init_gid_table(struct ocrdma_dev *dev)
+{
+ struct net_device *net_dev;
+
+ for_each_netdev(&init_net, net_dev) {
+ struct net_device *real_dev = rdma_vlan_dev_real_dev(net_dev) ?
+ rdma_vlan_dev_real_dev(net_dev) : net_dev;
+
+ if (real_dev == dev->nic_info.netdev) {
+ ocrdma_init_ipv4_gids(dev, net_dev);
+ ocrdma_init_ipv6_gids(dev, net_dev);
+ }
+ }
+}
+
static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
{
int status = 0, i;
@@ -399,6 +467,8 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
if (status)
goto alloc_err;
+ ocrdma_init_service_level(dev);
+ ocrdma_init_gid_table(dev);
status = ocrdma_register_device(dev);
if (status)
goto alloc_err;
@@ -508,6 +578,12 @@ static int ocrdma_close(struct ocrdma_dev *dev)
return 0;
}
+static void ocrdma_shutdown(struct ocrdma_dev *dev)
+{
+ ocrdma_close(dev);
+ ocrdma_remove(dev);
+}
+
/* event handling via NIC driver ensures that all the NIC specific
* initialization done before RoCE driver notifies
* event to stack.
@@ -521,6 +597,9 @@ static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
case BE_DEV_DOWN:
ocrdma_close(dev);
break;
+ case BE_DEV_SHUTDOWN:
+ ocrdma_shutdown(dev);
+ break;
}
}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
index 96c9ee602ba4..904989ec5eaa 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
@@ -44,35 +44,39 @@ enum {
#define OCRDMA_SUBSYS_ROCE 10
enum {
OCRDMA_CMD_QUERY_CONFIG = 1,
- OCRDMA_CMD_ALLOC_PD,
- OCRDMA_CMD_DEALLOC_PD,
-
- OCRDMA_CMD_CREATE_AH_TBL,
- OCRDMA_CMD_DELETE_AH_TBL,
-
- OCRDMA_CMD_CREATE_QP,
- OCRDMA_CMD_QUERY_QP,
- OCRDMA_CMD_MODIFY_QP,
- OCRDMA_CMD_DELETE_QP,
-
- OCRDMA_CMD_RSVD1,
- OCRDMA_CMD_ALLOC_LKEY,
- OCRDMA_CMD_DEALLOC_LKEY,
- OCRDMA_CMD_REGISTER_NSMR,
- OCRDMA_CMD_REREGISTER_NSMR,
- OCRDMA_CMD_REGISTER_NSMR_CONT,
- OCRDMA_CMD_QUERY_NSMR,
- OCRDMA_CMD_ALLOC_MW,
- OCRDMA_CMD_QUERY_MW,
-
- OCRDMA_CMD_CREATE_SRQ,
- OCRDMA_CMD_QUERY_SRQ,
- OCRDMA_CMD_MODIFY_SRQ,
- OCRDMA_CMD_DELETE_SRQ,
-
- OCRDMA_CMD_ATTACH_MCAST,
- OCRDMA_CMD_DETACH_MCAST,
- OCRDMA_CMD_GET_RDMA_STATS,
+ OCRDMA_CMD_ALLOC_PD = 2,
+ OCRDMA_CMD_DEALLOC_PD = 3,
+
+ OCRDMA_CMD_CREATE_AH_TBL = 4,
+ OCRDMA_CMD_DELETE_AH_TBL = 5,
+
+ OCRDMA_CMD_CREATE_QP = 6,
+ OCRDMA_CMD_QUERY_QP = 7,
+ OCRDMA_CMD_MODIFY_QP = 8 ,
+ OCRDMA_CMD_DELETE_QP = 9,
+
+ OCRDMA_CMD_RSVD1 = 10,
+ OCRDMA_CMD_ALLOC_LKEY = 11,
+ OCRDMA_CMD_DEALLOC_LKEY = 12,
+ OCRDMA_CMD_REGISTER_NSMR = 13,
+ OCRDMA_CMD_REREGISTER_NSMR = 14,
+ OCRDMA_CMD_REGISTER_NSMR_CONT = 15,
+ OCRDMA_CMD_QUERY_NSMR = 16,
+ OCRDMA_CMD_ALLOC_MW = 17,
+ OCRDMA_CMD_QUERY_MW = 18,
+
+ OCRDMA_CMD_CREATE_SRQ = 19,
+ OCRDMA_CMD_QUERY_SRQ = 20,
+ OCRDMA_CMD_MODIFY_SRQ = 21,
+ OCRDMA_CMD_DELETE_SRQ = 22,
+
+ OCRDMA_CMD_ATTACH_MCAST = 23,
+ OCRDMA_CMD_DETACH_MCAST = 24,
+
+ OCRDMA_CMD_CREATE_RBQ = 25,
+ OCRDMA_CMD_DESTROY_RBQ = 26,
+
+ OCRDMA_CMD_GET_RDMA_STATS = 27,
OCRDMA_CMD_MAX
};
@@ -103,7 +107,7 @@ enum {
#define OCRDMA_MAX_QP 2048
#define OCRDMA_MAX_CQ 2048
-#define OCRDMA_MAX_STAG 8192
+#define OCRDMA_MAX_STAG 16384
enum {
OCRDMA_DB_RQ_OFFSET = 0xE0,
@@ -422,7 +426,12 @@ struct ocrdma_ae_qp_mcqe {
#define OCRDMA_ASYNC_RDMA_EVE_CODE 0x14
#define OCRDMA_ASYNC_GRP5_EVE_CODE 0x5
-#define OCRDMA_ASYNC_EVENT_PVID_STATE 0x3
+
+enum ocrdma_async_grp5_events {
+ OCRDMA_ASYNC_EVENT_QOS_VALUE = 0x01,
+ OCRDMA_ASYNC_EVENT_COS_VALUE = 0x02,
+ OCRDMA_ASYNC_EVENT_PVID_STATE = 0x03
+};
enum OCRDMA_ASYNC_EVENT_TYPE {
OCRDMA_CQ_ERROR = 0x00,
@@ -525,8 +534,8 @@ struct ocrdma_mbx_query_config {
u32 max_ird_ord_per_qp;
u32 max_shared_ird_ord;
u32 max_mr;
- u32 max_mr_size_lo;
u32 max_mr_size_hi;
+ u32 max_mr_size_lo;
u32 max_num_mr_pbl;
u32 max_mw;
u32 max_fmr;
@@ -580,17 +589,26 @@ enum {
OCRDMA_FN_MODE_RDMA = 0x4
};
+enum {
+ OCRDMA_IF_TYPE_MASK = 0xFFFF0000,
+ OCRDMA_IF_TYPE_SHIFT = 0x10,
+ OCRDMA_PHY_TYPE_MASK = 0x0000FFFF,
+ OCRDMA_FUTURE_DETAILS_MASK = 0xFFFF0000,
+ OCRDMA_FUTURE_DETAILS_SHIFT = 0x10,
+ OCRDMA_EX_PHY_DETAILS_MASK = 0x0000FFFF,
+ OCRDMA_FSPEED_SUPP_MASK = 0xFFFF0000,
+ OCRDMA_FSPEED_SUPP_SHIFT = 0x10,
+ OCRDMA_ASPEED_SUPP_MASK = 0x0000FFFF
+};
+
struct ocrdma_get_phy_info_rsp {
struct ocrdma_mqe_hdr hdr;
struct ocrdma_mbx_rsp rsp;
- u16 phy_type;
- u16 interface_type;
+ u32 ityp_ptyp;
u32 misc_params;
- u16 ext_phy_details;
- u16 rsvd;
- u16 auto_speeds_supported;
- u16 fixed_speeds_supported;
+ u32 ftrdtl_exphydtl;
+ u32 fspeed_aspeed;
u32 future_use[2];
};
@@ -603,19 +621,34 @@ enum {
OCRDMA_PHY_SPEED_40GBPS = 0x20
};
+enum {
+ OCRDMA_PORT_NUM_MASK = 0x3F,
+ OCRDMA_PT_MASK = 0xC0,
+ OCRDMA_PT_SHIFT = 0x6,
+ OCRDMA_LINK_DUP_MASK = 0x0000FF00,
+ OCRDMA_LINK_DUP_SHIFT = 0x8,
+ OCRDMA_PHY_PS_MASK = 0x00FF0000,
+ OCRDMA_PHY_PS_SHIFT = 0x10,
+ OCRDMA_PHY_PFLT_MASK = 0xFF000000,
+ OCRDMA_PHY_PFLT_SHIFT = 0x18,
+ OCRDMA_QOS_LNKSP_MASK = 0xFFFF0000,
+ OCRDMA_QOS_LNKSP_SHIFT = 0x10,
+ OCRDMA_LLST_MASK = 0xFF,
+ OCRDMA_PLFC_MASK = 0x00000400,
+ OCRDMA_PLFC_SHIFT = 0x8,
+ OCRDMA_PLRFC_MASK = 0x00000200,
+ OCRDMA_PLRFC_SHIFT = 0x8,
+ OCRDMA_PLTFC_MASK = 0x00000100,
+ OCRDMA_PLTFC_SHIFT = 0x8
+};
struct ocrdma_get_link_speed_rsp {
struct ocrdma_mqe_hdr hdr;
struct ocrdma_mbx_rsp rsp;
- u8 pt_port_num;
- u8 link_duplex;
- u8 phys_port_speed;
- u8 phys_port_fault;
- u16 rsvd1;
- u16 qos_lnk_speed;
- u8 logical_lnk_status;
- u8 rsvd2[3];
+ u32 pflt_pps_ld_pnum;
+ u32 qos_lsp;
+ u32 res_lls;
};
enum {
@@ -666,8 +699,7 @@ struct ocrdma_create_cq_cmd {
u32 pgsz_pgcnt;
u32 ev_cnt_flags;
u32 eqn;
- u16 cqe_count;
- u16 pd_id;
+ u32 pdid_cqecnt;
u32 rsvd6;
struct ocrdma_pa pa[OCRDMA_CREATE_CQ_MAX_PAGES];
};
@@ -678,6 +710,10 @@ struct ocrdma_create_cq {
};
enum {
+ OCRDMA_CREATE_CQ_CMD_PDID_SHIFT = 0x10
+};
+
+enum {
OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK = 0xFFFF
};
@@ -1231,7 +1267,6 @@ struct ocrdma_destroy_srq {
enum {
OCRDMA_ALLOC_PD_ENABLE_DPP = BIT(16),
- OCRDMA_PD_MAX_DPP_ENABLED_QP = 8,
OCRDMA_DPP_PAGE_SIZE = 4096
};
@@ -1896,12 +1931,62 @@ struct ocrdma_rdma_stats_resp {
struct ocrdma_rx_dbg_stats rx_dbg_stats;
} __packed;
+enum {
+ OCRDMA_HBA_ATTRB_EPROM_VER_LO_MASK = 0xFF,
+ OCRDMA_HBA_ATTRB_EPROM_VER_HI_MASK = 0xFF00,
+ OCRDMA_HBA_ATTRB_EPROM_VER_HI_SHIFT = 0x08,
+ OCRDMA_HBA_ATTRB_CDBLEN_MASK = 0xFFFF,
+ OCRDMA_HBA_ATTRB_ASIC_REV_MASK = 0xFF0000,
+ OCRDMA_HBA_ATTRB_ASIC_REV_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_GUID0_MASK = 0xFF000000,
+ OCRDMA_HBA_ATTRB_GUID0_SHIFT = 0x18,
+ OCRDMA_HBA_ATTRB_GUID13_MASK = 0xFF,
+ OCRDMA_HBA_ATTRB_GUID14_MASK = 0xFF00,
+ OCRDMA_HBA_ATTRB_GUID14_SHIFT = 0x08,
+ OCRDMA_HBA_ATTRB_GUID15_MASK = 0xFF0000,
+ OCRDMA_HBA_ATTRB_GUID15_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_PCNT_MASK = 0xFF000000,
+ OCRDMA_HBA_ATTRB_PCNT_SHIFT = 0x18,
+ OCRDMA_HBA_ATTRB_LDTOUT_MASK = 0xFFFF,
+ OCRDMA_HBA_ATTRB_ISCSI_VER_MASK = 0xFF0000,
+ OCRDMA_HBA_ATTRB_ISCSI_VER_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_MFUNC_DEV_MASK = 0xFF000000,
+ OCRDMA_HBA_ATTRB_MFUNC_DEV_SHIFT = 0x18,
+ OCRDMA_HBA_ATTRB_CV_MASK = 0xFF,
+ OCRDMA_HBA_ATTRB_HBA_ST_MASK = 0xFF00,
+ OCRDMA_HBA_ATTRB_HBA_ST_SHIFT = 0x08,
+ OCRDMA_HBA_ATTRB_MAX_DOMS_MASK = 0xFF0000,
+ OCRDMA_HBA_ATTRB_MAX_DOMS_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_PTNUM_MASK = 0x3F000000,
+ OCRDMA_HBA_ATTRB_PTNUM_SHIFT = 0x18,
+ OCRDMA_HBA_ATTRB_PT_MASK = 0xC0000000,
+ OCRDMA_HBA_ATTRB_PT_SHIFT = 0x1E,
+ OCRDMA_HBA_ATTRB_ISCSI_FET_MASK = 0xFF,
+ OCRDMA_HBA_ATTRB_ASIC_GEN_MASK = 0xFF00,
+ OCRDMA_HBA_ATTRB_ASIC_GEN_SHIFT = 0x08,
+ OCRDMA_HBA_ATTRB_PCI_VID_MASK = 0xFFFF,
+ OCRDMA_HBA_ATTRB_PCI_DID_MASK = 0xFFFF0000,
+ OCRDMA_HBA_ATTRB_PCI_DID_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_PCI_SVID_MASK = 0xFFFF,
+ OCRDMA_HBA_ATTRB_PCI_SSID_MASK = 0xFFFF0000,
+ OCRDMA_HBA_ATTRB_PCI_SSID_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_PCI_BUSNUM_MASK = 0xFF,
+ OCRDMA_HBA_ATTRB_PCI_DEVNUM_MASK = 0xFF00,
+ OCRDMA_HBA_ATTRB_PCI_DEVNUM_SHIFT = 0x08,
+ OCRDMA_HBA_ATTRB_PCI_FUNCNUM_MASK = 0xFF0000,
+ OCRDMA_HBA_ATTRB_PCI_FUNCNUM_SHIFT = 0x10,
+ OCRDMA_HBA_ATTRB_IF_TYPE_MASK = 0xFF000000,
+ OCRDMA_HBA_ATTRB_IF_TYPE_SHIFT = 0x18,
+ OCRDMA_HBA_ATTRB_NETFIL_MASK =0xFF
+};
struct mgmt_hba_attribs {
u8 flashrom_version_string[32];
u8 manufacturer_name[32];
u32 supported_modes;
- u32 rsvd0[3];
+ u32 rsvd_eprom_verhi_verlo;
+ u32 mbx_ds_ver;
+ u32 epfw_ds_ver;
u8 ncsi_ver_string[12];
u32 default_extended_timeout;
u8 controller_model_number[32];
@@ -1914,34 +1999,26 @@ struct mgmt_hba_attribs {
u8 driver_version_string[32];
u8 fw_on_flash_version_string[32];
u32 functionalities_supported;
- u16 max_cdblength;
- u8 asic_revision;
- u8 generational_guid[16];
- u8 hba_port_count;
- u16 default_link_down_timeout;
- u8 iscsi_ver_min_max;
- u8 multifunction_device;
- u8 cache_valid;
- u8 hba_status;
- u8 max_domains_supported;
- u8 phy_port;
+ u32 guid0_asicrev_cdblen;
+ u8 generational_guid[12];
+ u32 portcnt_guid15;
+ u32 mfuncdev_iscsi_ldtout;
+ u32 ptpnum_maxdoms_hbast_cv;
u32 firmware_post_status;
u32 hba_mtu[8];
- u32 rsvd1[4];
+ u32 res_asicgen_iscsi_feaures;
+ u32 rsvd1[3];
};
struct mgmt_controller_attrib {
struct mgmt_hba_attribs hba_attribs;
- u16 pci_vendor_id;
- u16 pci_device_id;
- u16 pci_sub_vendor_id;
- u16 pci_sub_system_id;
- u8 pci_bus_number;
- u8 pci_device_number;
- u8 pci_function_number;
- u8 interface_type;
- u64 unique_identifier;
- u32 rsvd0[5];
+ u32 pci_did_vid;
+ u32 pci_ssid_svid;
+ u32 ityp_fnum_devnum_bnum;
+ u32 uid_hi;
+ u32 uid_lo;
+ u32 res_nnetfil;
+ u32 rsvd0[4];
};
struct ocrdma_get_ctrl_attribs_rsp {
@@ -1949,5 +2026,79 @@ struct ocrdma_get_ctrl_attribs_rsp {
struct mgmt_controller_attrib ctrl_attribs;
};
+#define OCRDMA_SUBSYS_DCBX 0x10
+
+enum OCRDMA_DCBX_OPCODE {
+ OCRDMA_CMD_GET_DCBX_CONFIG = 0x01
+};
+
+enum OCRDMA_DCBX_PARAM_TYPE {
+ OCRDMA_PARAMETER_TYPE_ADMIN = 0x00,
+ OCRDMA_PARAMETER_TYPE_OPER = 0x01,
+ OCRDMA_PARAMETER_TYPE_PEER = 0x02
+};
+
+enum OCRDMA_DCBX_APP_PROTO {
+ OCRDMA_APP_PROTO_ROCE = 0x8915
+};
+
+enum OCRDMA_DCBX_PROTO {
+ OCRDMA_PROTO_SELECT_L2 = 0x00,
+ OCRDMA_PROTO_SELECT_L4 = 0x01
+};
+
+enum OCRDMA_DCBX_APP_PARAM {
+ OCRDMA_APP_PARAM_APP_PROTO_MASK = 0xFFFF,
+ OCRDMA_APP_PARAM_PROTO_SEL_MASK = 0xFF,
+ OCRDMA_APP_PARAM_PROTO_SEL_SHIFT = 0x10,
+ OCRDMA_APP_PARAM_VALID_MASK = 0xFF,
+ OCRDMA_APP_PARAM_VALID_SHIFT = 0x18
+};
+
+enum OCRDMA_DCBX_STATE_FLAGS {
+ OCRDMA_STATE_FLAG_ENABLED = 0x01,
+ OCRDMA_STATE_FLAG_ADDVERTISED = 0x02,
+ OCRDMA_STATE_FLAG_WILLING = 0x04,
+ OCRDMA_STATE_FLAG_SYNC = 0x08,
+ OCRDMA_STATE_FLAG_UNSUPPORTED = 0x40000000,
+ OCRDMA_STATE_FLAG_NEG_FAILD = 0x80000000
+};
+
+enum OCRDMA_TCV_AEV_OPV_ST {
+ OCRDMA_DCBX_TC_SUPPORT_MASK = 0xFF,
+ OCRDMA_DCBX_TC_SUPPORT_SHIFT = 0x18,
+ OCRDMA_DCBX_APP_ENTRY_SHIFT = 0x10,
+ OCRDMA_DCBX_OP_PARAM_SHIFT = 0x08,
+ OCRDMA_DCBX_STATE_MASK = 0xFF
+};
+
+struct ocrdma_app_parameter {
+ u32 valid_proto_app;
+ u32 oui;
+ u32 app_prio[2];
+};
+
+struct ocrdma_dcbx_cfg {
+ u32 tcv_aev_opv_st;
+ u32 tc_state;
+ u32 pfc_state;
+ u32 qcn_state;
+ u32 appl_state;
+ u32 ll_state;
+ u32 tc_bw[2];
+ u32 tc_prio[8];
+ u32 pfc_prio[2];
+ struct ocrdma_app_parameter app_param[15];
+};
+
+struct ocrdma_get_dcbx_cfg_req {
+ struct ocrdma_mbx_hdr hdr;
+ u32 param_type;
+} __packed;
+
+struct ocrdma_get_dcbx_cfg_rsp {
+ struct ocrdma_mbx_rsp hdr;
+ struct ocrdma_dcbx_cfg cfg;
+} __packed;
#endif /* __OCRDMA_SLI_H__ */
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index edf6211d84b8..acb434d16903 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -69,11 +69,11 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr)
memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
min(sizeof(dev->attr.fw_ver), sizeof(attr->fw_ver)));
ocrdma_get_guid(dev, (u8 *)&attr->sys_image_guid);
- attr->max_mr_size = ~0ull;
+ attr->max_mr_size = dev->attr.max_mr_size;
attr->page_size_cap = 0xffff000;
attr->vendor_id = dev->nic_info.pdev->vendor;
attr->vendor_part_id = dev->nic_info.pdev->device;
- attr->hw_ver = 0;
+ attr->hw_ver = dev->asic_id;
attr->max_qp = dev->attr.max_qp;
attr->max_ah = OCRDMA_MAX_AH;
attr->max_qp_wr = dev->attr.max_wqe;
@@ -268,7 +268,8 @@ static struct ocrdma_pd *_ocrdma_alloc_pd(struct ocrdma_dev *dev,
pd->dpp_enabled =
ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R;
pd->num_dpp_qp =
- pd->dpp_enabled ? OCRDMA_PD_MAX_DPP_ENABLED_QP : 0;
+ pd->dpp_enabled ? (dev->nic_info.db_page_size /
+ dev->attr.wqe_size) : 0;
}
retry:
@@ -328,7 +329,10 @@ static int ocrdma_dealloc_ucontext_pd(struct ocrdma_ucontext *uctx)
struct ocrdma_pd *pd = uctx->cntxt_pd;
struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
- BUG_ON(uctx->pd_in_use);
+ if (uctx->pd_in_use) {
+ pr_err("%s(%d) Freeing in use pdid=0x%x.\n",
+ __func__, dev->id, pd->id);
+ }
uctx->cntxt_pd = NULL;
status = _ocrdma_dealloc_pd(dev, pd);
return status;
@@ -843,6 +847,13 @@ int ocrdma_dereg_mr(struct ib_mr *ib_mr)
if (mr->umem)
ib_umem_release(mr->umem);
kfree(mr);
+
+ /* Don't stop cleanup, in case FW is unresponsive */
+ if (dev->mqe_ctx.fw_error_state) {
+ status = 0;
+ pr_err("%s(%d) fw not responding.\n",
+ __func__, dev->id);
+ }
return status;
}
@@ -2054,6 +2065,13 @@ int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
while (wr) {
+ if (qp->qp_type == IB_QPT_UD &&
+ (wr->opcode != IB_WR_SEND &&
+ wr->opcode != IB_WR_SEND_WITH_IMM)) {
+ *bad_wr = wr;
+ status = -EINVAL;
+ break;
+ }
if (ocrdma_hwq_free_cnt(&qp->sq) == 0 ||
wr->num_sge > qp->sq.max_sges) {
*bad_wr = wr;
@@ -2488,6 +2506,11 @@ static bool ocrdma_poll_err_scqe(struct ocrdma_qp *qp,
*stop = true;
expand = false;
}
+ } else if (is_hw_sq_empty(qp)) {
+ /* Do nothing */
+ expand = false;
+ *polled = false;
+ *stop = false;
} else {
*polled = true;
expand = ocrdma_update_err_scqe(ibwc, cqe, qp, status);
@@ -2593,6 +2616,11 @@ static bool ocrdma_poll_err_rcqe(struct ocrdma_qp *qp, struct ocrdma_cqe *cqe,
*stop = true;
expand = false;
}
+ } else if (is_hw_rq_empty(qp)) {
+ /* Do nothing */
+ expand = false;
+ *polled = false;
+ *stop = false;
} else {
*polled = true;
expand = ocrdma_update_err_rcqe(ibwc, cqe, qp, status);
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 8d3c78ddc906..729da39c49ed 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1222,7 +1222,7 @@ static int qib_init_one(struct pci_dev *, const struct pci_device_id *);
#define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: "
#define PFX QIB_DRV_NAME ": "
-static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = {
+static const struct pci_device_id qib_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_QLOGIC_IB_6120) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7220) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7322) },
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 22c720e5740d..636be117b578 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -2476,7 +2476,7 @@ int qib_create_agents(struct qib_ibdev *dev)
ibp = &dd->pport[p].ibport_data;
agent = ib_register_mad_agent(&dev->ibdev, p + 1, IB_QPT_SMI,
NULL, 0, send_handler,
- NULL, NULL);
+ NULL, NULL, 0);
if (IS_ERR(agent)) {
ret = PTR_ERR(agent);
goto err;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index fb6d026f92cd..0d0f98695d53 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -490,7 +490,7 @@ out:
/* Start of PCI section */
-static DEFINE_PCI_DEVICE_TABLE(usnic_ib_pci_ids) = {
+static const struct pci_device_id usnic_ib_pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
{0,}
};
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index c639f90cfda4..3edce617c31b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -86,7 +86,6 @@ enum {
IPOIB_FLAG_INITIALIZED = 1,
IPOIB_FLAG_ADMIN_UP = 2,
IPOIB_PKEY_ASSIGNED = 3,
- IPOIB_PKEY_STOP = 4,
IPOIB_FLAG_SUBINTERFACE = 5,
IPOIB_MCAST_RUN = 6,
IPOIB_STOP_REAPER = 7,
@@ -312,7 +311,6 @@ struct ipoib_dev_priv {
struct list_head multicast_list;
struct rb_root multicast_tree;
- struct delayed_work pkey_poll_task;
struct delayed_work mcast_task;
struct work_struct carrier_on_task;
struct work_struct flush_light;
@@ -473,10 +471,11 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work);
void ipoib_pkey_event(struct work_struct *work);
void ipoib_ib_dev_cleanup(struct net_device *dev);
-int ipoib_ib_dev_open(struct net_device *dev);
+int ipoib_ib_dev_open(struct net_device *dev, int flush);
int ipoib_ib_dev_up(struct net_device *dev);
int ipoib_ib_dev_down(struct net_device *dev, int flush);
int ipoib_ib_dev_stop(struct net_device *dev, int flush);
+void ipoib_pkey_dev_check_presence(struct net_device *dev);
int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
void ipoib_dev_cleanup(struct net_device *dev);
@@ -532,8 +531,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf);
void ipoib_setup(struct net_device *dev);
-void ipoib_pkey_poll(struct work_struct *work);
-int ipoib_pkey_dev_delay_open(struct net_device *dev);
+void ipoib_pkey_open(struct ipoib_dev_priv *priv);
void ipoib_drain_cq(struct net_device *dev);
void ipoib_set_ethtool_ops(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 50061854616e..6bd5740e2691 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -281,10 +281,8 @@ void ipoib_delete_debug_files(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- if (priv->mcg_dentry)
- debugfs_remove(priv->mcg_dentry);
- if (priv->path_dentry)
- debugfs_remove(priv->path_dentry);
+ debugfs_remove(priv->mcg_dentry);
+ debugfs_remove(priv->path_dentry);
}
int ipoib_register_debugfs(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 6a7003ddb0be..72626c348174 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -664,17 +664,18 @@ static void ipoib_ib_tx_timer_func(unsigned long ctx)
drain_tx_cq((struct net_device *)ctx);
}
-int ipoib_ib_dev_open(struct net_device *dev)
+int ipoib_ib_dev_open(struct net_device *dev, int flush)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
- if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {
- ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);
- clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
+ ipoib_pkey_dev_check_presence(dev);
+
+ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
+ ipoib_warn(priv, "P_Key 0x%04x is %s\n", priv->pkey,
+ (!(priv->pkey & 0x7fff) ? "Invalid" : "not found"));
return -1;
}
- set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
ret = ipoib_init_qp(dev);
if (ret) {
@@ -705,16 +706,17 @@ int ipoib_ib_dev_open(struct net_device *dev)
dev_stop:
if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
napi_enable(&priv->napi);
- ipoib_ib_dev_stop(dev, 1);
+ ipoib_ib_dev_stop(dev, flush);
return -1;
}
-static void ipoib_pkey_dev_check_presence(struct net_device *dev)
+void ipoib_pkey_dev_check_presence(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- u16 pkey_index = 0;
- if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index))
+ if (!(priv->pkey & 0x7fff) ||
+ ib_find_pkey(priv->ca, priv->port, priv->pkey,
+ &priv->pkey_index))
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
else
set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
@@ -745,14 +747,6 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush)
clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
netif_carrier_off(dev);
- /* Shutdown the P_Key thread if still active */
- if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- mutex_lock(&pkey_mutex);
- set_bit(IPOIB_PKEY_STOP, &priv->flags);
- cancel_delayed_work_sync(&priv->pkey_poll_task);
- mutex_unlock(&pkey_mutex);
- }
-
ipoib_mcast_stop_thread(dev, flush);
ipoib_mcast_dev_flush(dev);
@@ -924,7 +918,7 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
(unsigned long) dev);
if (dev->flags & IFF_UP) {
- if (ipoib_ib_dev_open(dev)) {
+ if (ipoib_ib_dev_open(dev, 1)) {
ipoib_transport_dev_cleanup(dev);
return -ENODEV;
}
@@ -966,13 +960,27 @@ static inline int update_parent_pkey(struct ipoib_dev_priv *priv)
return 1;
}
+/*
+ * returns 0 if pkey value was found in a different slot.
+ */
+static inline int update_child_pkey(struct ipoib_dev_priv *priv)
+{
+ u16 old_index = priv->pkey_index;
+
+ priv->pkey_index = 0;
+ ipoib_pkey_dev_check_presence(priv->dev);
+
+ if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
+ (old_index == priv->pkey_index))
+ return 1;
+ return 0;
+}
static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
enum ipoib_flush_level level)
{
struct ipoib_dev_priv *cpriv;
struct net_device *dev = priv->dev;
- u16 new_index;
int result;
down_read(&priv->vlan_rwsem);
@@ -986,16 +994,20 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
up_read(&priv->vlan_rwsem);
- if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
- /* for non-child devices must check/update the pkey value here */
- if (level == IPOIB_FLUSH_HEAVY &&
- !test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
- update_parent_pkey(priv);
+ if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) &&
+ level != IPOIB_FLUSH_HEAVY) {
ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
return;
}
if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
+ /* interface is down. update pkey and leave. */
+ if (level == IPOIB_FLUSH_HEAVY) {
+ if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
+ update_parent_pkey(priv);
+ else
+ update_child_pkey(priv);
+ }
ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_ADMIN_UP not set.\n");
return;
}
@@ -1005,20 +1017,13 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
* (parent) devices should always takes what present in pkey index 0
*/
if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
- if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
- clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
- ipoib_ib_dev_down(dev, 0);
- ipoib_ib_dev_stop(dev, 0);
- if (ipoib_pkey_dev_delay_open(dev))
- return;
- }
- /* restart QP only if P_Key index is changed */
- if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
- new_index == priv->pkey_index) {
+ result = update_child_pkey(priv);
+ if (result) {
+ /* restart QP only if P_Key index is changed */
ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
return;
}
- priv->pkey_index = new_index;
+
} else {
result = update_parent_pkey(priv);
/* restart QP only if P_Key value changed */
@@ -1038,8 +1043,12 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
ipoib_ib_dev_down(dev, 0);
if (level == IPOIB_FLUSH_HEAVY) {
- ipoib_ib_dev_stop(dev, 0);
- ipoib_ib_dev_open(dev);
+ if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
+ ipoib_ib_dev_stop(dev, 0);
+ if (ipoib_ib_dev_open(dev, 0) != 0)
+ return;
+ if (netif_queue_stopped(dev))
+ netif_start_queue(dev);
}
/*
@@ -1094,54 +1103,4 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
ipoib_transport_dev_cleanup(dev);
}
-/*
- * Delayed P_Key Assigment Interim Support
- *
- * The following is initial implementation of delayed P_Key assigment
- * mechanism. It is using the same approach implemented for the multicast
- * group join. The single goal of this implementation is to quickly address
- * Bug #2507. This implementation will probably be removed when the P_Key
- * change async notification is available.
- */
-
-void ipoib_pkey_poll(struct work_struct *work)
-{
- struct ipoib_dev_priv *priv =
- container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);
- struct net_device *dev = priv->dev;
-
- ipoib_pkey_dev_check_presence(dev);
-
- if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
- ipoib_open(dev);
- else {
- mutex_lock(&pkey_mutex);
- if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
- queue_delayed_work(ipoib_workqueue,
- &priv->pkey_poll_task,
- HZ);
- mutex_unlock(&pkey_mutex);
- }
-}
-
-int ipoib_pkey_dev_delay_open(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
-
- /* Look for the interface pkey value in the IB Port P_Key table and */
- /* set the interface pkey assigment flag */
- ipoib_pkey_dev_check_presence(dev);
- /* P_Key value not assigned yet - start polling */
- if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- mutex_lock(&pkey_mutex);
- clear_bit(IPOIB_PKEY_STOP, &priv->flags);
- queue_delayed_work(ipoib_workqueue,
- &priv->pkey_poll_task,
- HZ);
- mutex_unlock(&pkey_mutex);
- return 1;
- }
-
- return 0;
-}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 5786a78ff8bc..1310acf6bf92 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -108,11 +108,11 @@ int ipoib_open(struct net_device *dev)
set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
- if (ipoib_pkey_dev_delay_open(dev))
- return 0;
-
- if (ipoib_ib_dev_open(dev))
+ if (ipoib_ib_dev_open(dev, 1)) {
+ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
+ return 0;
goto err_disable;
+ }
if (ipoib_ib_dev_up(dev))
goto err_stop;
@@ -1379,7 +1379,6 @@ void ipoib_setup(struct net_device *dev)
INIT_LIST_HEAD(&priv->dead_ahs);
INIT_LIST_HEAD(&priv->multicast_list);
- INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task);
INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light);
@@ -1394,8 +1393,8 @@ struct ipoib_dev_priv *ipoib_intf_alloc(const char *name)
{
struct net_device *dev;
- dev = alloc_netdev((int) sizeof (struct ipoib_dev_priv), name,
- ipoib_setup);
+ dev = alloc_netdev((int)sizeof(struct ipoib_dev_priv), name,
+ NET_NAME_UNKNOWN, ipoib_setup);
if (!dev)
return NULL;
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index eb7973957a6e..61ee91d88380 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -596,20 +596,28 @@ iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
struct iser_conn *ib_conn;
struct iscsi_endpoint *ep;
- ep = iscsi_create_endpoint(sizeof(*ib_conn));
+ ep = iscsi_create_endpoint(0);
if (!ep)
return ERR_PTR(-ENOMEM);
- ib_conn = ep->dd_data;
+ ib_conn = kzalloc(sizeof(*ib_conn), GFP_KERNEL);
+ if (!ib_conn) {
+ err = -ENOMEM;
+ goto failure;
+ }
+
+ ep->dd_data = ib_conn;
ib_conn->ep = ep;
iser_conn_init(ib_conn);
- err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr,
- non_blocking);
+ err = iser_connect(ib_conn, NULL, dst_addr, non_blocking);
if (err)
- return ERR_PTR(err);
+ goto failure;
return ep;
+failure:
+ iscsi_destroy_endpoint(ep);
+ return ERR_PTR(err);
}
static int
@@ -619,15 +627,16 @@ iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
int rc;
ib_conn = ep->dd_data;
- rc = wait_event_interruptible_timeout(ib_conn->wait,
- ib_conn->state == ISER_CONN_UP,
- msecs_to_jiffies(timeout_ms));
-
+ rc = wait_for_completion_interruptible_timeout(&ib_conn->up_completion,
+ msecs_to_jiffies(timeout_ms));
/* if conn establishment failed, return error code to iscsi */
- if (!rc &&
- (ib_conn->state == ISER_CONN_TERMINATING ||
- ib_conn->state == ISER_CONN_DOWN))
- rc = -1;
+ if (rc == 0) {
+ mutex_lock(&ib_conn->state_mutex);
+ if (ib_conn->state == ISER_CONN_TERMINATING ||
+ ib_conn->state == ISER_CONN_DOWN)
+ rc = -1;
+ mutex_unlock(&ib_conn->state_mutex);
+ }
iser_info("ib conn %p rc = %d\n", ib_conn, rc);
@@ -646,19 +655,25 @@ iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep)
ib_conn = ep->dd_data;
iser_info("ep %p ib conn %p state %d\n", ep, ib_conn, ib_conn->state);
+ mutex_lock(&ib_conn->state_mutex);
iser_conn_terminate(ib_conn);
/*
- * if iser_conn and iscsi_conn are bound, we must wait iscsi_conn_stop
- * call and ISER_CONN_DOWN state before freeing the iser resources.
- * otherwise we are safe to free resources immediately.
+ * if iser_conn and iscsi_conn are bound, we must wait for
+ * iscsi_conn_stop and flush errors completion before freeing
+ * the iser resources. Otherwise we are safe to free resources
+ * immediately.
*/
if (ib_conn->iscsi_conn) {
INIT_WORK(&ib_conn->release_work, iser_release_work);
queue_work(release_wq, &ib_conn->release_work);
+ mutex_unlock(&ib_conn->state_mutex);
} else {
+ ib_conn->state = ISER_CONN_DOWN;
+ mutex_unlock(&ib_conn->state_mutex);
iser_conn_release(ib_conn);
}
+ iscsi_destroy_endpoint(ep);
}
static umode_t iser_attr_is_visible(int param_type, int param)
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 97cd385bf7f7..c877dad381cb 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -326,7 +326,6 @@ struct iser_conn {
struct iser_device *device; /* device context */
struct rdma_cm_id *cma_id; /* CMA ID */
struct ib_qp *qp; /* QP */
- wait_queue_head_t wait; /* waitq for conn/disconn */
unsigned qp_max_recv_dtos; /* num of rx buffers */
unsigned qp_max_recv_dtos_mask; /* above minus 1 */
unsigned min_posted_rx; /* qp_max_recv_dtos >> 2 */
@@ -335,6 +334,9 @@ struct iser_conn {
char name[ISER_OBJECT_NAME_SIZE];
struct work_struct release_work;
struct completion stop_completion;
+ struct mutex state_mutex;
+ struct completion flush_completion;
+ struct completion up_completion;
struct list_head conn_list; /* entry in ig conn list */
char *login_buf;
@@ -448,8 +450,8 @@ int iser_reg_rdma_mem_fastreg(struct iscsi_iser_task *task,
enum iser_data_dir cmd_dir);
int iser_connect(struct iser_conn *ib_conn,
- struct sockaddr_in *src_addr,
- struct sockaddr_in *dst_addr,
+ struct sockaddr *src_addr,
+ struct sockaddr *dst_addr,
int non_blocking);
int iser_reg_page_vec(struct iser_conn *ib_conn,
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index ea01075f9f9b..3ef167f97d6f 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -491,10 +491,9 @@ out_err:
}
/**
- * releases the QP objects, returns 0 on success,
- * -1 on failure
+ * releases the QP object
*/
-static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
+static void iser_free_ib_conn_res(struct iser_conn *ib_conn)
{
int cq_index;
BUG_ON(ib_conn == NULL);
@@ -513,8 +512,6 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
}
ib_conn->qp = NULL;
-
- return 0;
}
/**
@@ -568,31 +565,40 @@ static void iser_device_try_release(struct iser_device *device)
mutex_unlock(&ig.device_list_mutex);
}
+/**
+ * Called with state mutex held
+ **/
static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
enum iser_ib_conn_state comp,
enum iser_ib_conn_state exch)
{
int ret;
- spin_lock_bh(&ib_conn->lock);
if ((ret = (ib_conn->state == comp)))
ib_conn->state = exch;
- spin_unlock_bh(&ib_conn->lock);
return ret;
}
void iser_release_work(struct work_struct *work)
{
struct iser_conn *ib_conn;
+ int rc;
ib_conn = container_of(work, struct iser_conn, release_work);
/* wait for .conn_stop callback */
- wait_for_completion(&ib_conn->stop_completion);
+ rc = wait_for_completion_timeout(&ib_conn->stop_completion, 30 * HZ);
+ WARN_ON(rc == 0);
/* wait for the qp`s post send and post receive buffers to empty */
- wait_event_interruptible(ib_conn->wait,
- ib_conn->state == ISER_CONN_DOWN);
+ rc = wait_for_completion_timeout(&ib_conn->flush_completion, 30 * HZ);
+ WARN_ON(rc == 0);
+
+ ib_conn->state = ISER_CONN_DOWN;
+
+ mutex_lock(&ib_conn->state_mutex);
+ ib_conn->state = ISER_CONN_DOWN;
+ mutex_unlock(&ib_conn->state_mutex);
iser_conn_release(ib_conn);
}
@@ -604,23 +610,27 @@ void iser_conn_release(struct iser_conn *ib_conn)
{
struct iser_device *device = ib_conn->device;
- BUG_ON(ib_conn->state == ISER_CONN_UP);
-
mutex_lock(&ig.connlist_mutex);
list_del(&ib_conn->conn_list);
mutex_unlock(&ig.connlist_mutex);
+
+ mutex_lock(&ib_conn->state_mutex);
+ BUG_ON(ib_conn->state != ISER_CONN_DOWN);
+
iser_free_rx_descriptors(ib_conn);
iser_free_ib_conn_res(ib_conn);
ib_conn->device = NULL;
/* on EVENT_ADDR_ERROR there's no device yet for this conn */
if (device != NULL)
iser_device_try_release(device);
+ mutex_unlock(&ib_conn->state_mutex);
+
/* if cma handler context, the caller actually destroy the id */
if (ib_conn->cma_id != NULL) {
rdma_destroy_id(ib_conn->cma_id);
ib_conn->cma_id = NULL;
}
- iscsi_destroy_endpoint(ib_conn->ep);
+ kfree(ib_conn);
}
/**
@@ -642,22 +652,31 @@ void iser_conn_terminate(struct iser_conn *ib_conn)
ib_conn,err);
}
+/**
+ * Called with state mutex held
+ **/
static void iser_connect_error(struct rdma_cm_id *cma_id)
{
struct iser_conn *ib_conn;
ib_conn = (struct iser_conn *)cma_id->context;
-
ib_conn->state = ISER_CONN_DOWN;
- wake_up_interruptible(&ib_conn->wait);
}
+/**
+ * Called with state mutex held
+ **/
static void iser_addr_handler(struct rdma_cm_id *cma_id)
{
struct iser_device *device;
struct iser_conn *ib_conn;
int ret;
+ ib_conn = (struct iser_conn *)cma_id->context;
+ if (ib_conn->state != ISER_CONN_PENDING)
+ /* bailout */
+ return;
+
device = iser_device_find_by_ib_device(cma_id);
if (!device) {
iser_err("device lookup/creation failed\n");
@@ -665,7 +684,6 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
return;
}
- ib_conn = (struct iser_conn *)cma_id->context;
ib_conn->device = device;
/* connection T10-PI support */
@@ -689,18 +707,27 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
}
}
+/**
+ * Called with state mutex held
+ **/
static void iser_route_handler(struct rdma_cm_id *cma_id)
{
struct rdma_conn_param conn_param;
int ret;
struct iser_cm_hdr req_hdr;
+ struct iser_conn *ib_conn = (struct iser_conn *)cma_id->context;
+ struct iser_device *device = ib_conn->device;
+
+ if (ib_conn->state != ISER_CONN_PENDING)
+ /* bailout */
+ return;
ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context);
if (ret)
goto failure;
memset(&conn_param, 0, sizeof conn_param);
- conn_param.responder_resources = 4;
+ conn_param.responder_resources = device->dev_attr.max_qp_rd_atom;
conn_param.initiator_depth = 1;
conn_param.retry_count = 7;
conn_param.rnr_retry_count = 6;
@@ -728,12 +755,16 @@ static void iser_connected_handler(struct rdma_cm_id *cma_id)
struct ib_qp_attr attr;
struct ib_qp_init_attr init_attr;
+ ib_conn = (struct iser_conn *)cma_id->context;
+ if (ib_conn->state != ISER_CONN_PENDING)
+ /* bailout */
+ return;
+
(void)ib_query_qp(cma_id->qp, &attr, ~0, &init_attr);
iser_info("remote qpn:%x my qpn:%x\n", attr.dest_qp_num, cma_id->qp->qp_num);
- ib_conn = (struct iser_conn *)cma_id->context;
- if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_PENDING, ISER_CONN_UP))
- wake_up_interruptible(&ib_conn->wait);
+ ib_conn->state = ISER_CONN_UP;
+ complete(&ib_conn->up_completion);
}
static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
@@ -752,19 +783,25 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
iser_err("iscsi_iser connection isn't bound\n");
}
- /* Complete the termination process if no posts are pending */
+ /* Complete the termination process if no posts are pending. This code
+ * block also exists in iser_handle_comp_error(), but it is needed here
+ * for cases of no flushes at all, e.g. discovery over rdma.
+ */
if (ib_conn->post_recv_buf_count == 0 &&
(atomic_read(&ib_conn->post_send_buf_count) == 0)) {
- ib_conn->state = ISER_CONN_DOWN;
- wake_up_interruptible(&ib_conn->wait);
+ complete(&ib_conn->flush_completion);
}
}
static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
{
+ struct iser_conn *ib_conn;
+
+ ib_conn = (struct iser_conn *)cma_id->context;
iser_info("event %d status %d conn %p id %p\n",
event->event, event->status, cma_id->context, cma_id);
+ mutex_lock(&ib_conn->state_mutex);
switch (event->event) {
case RDMA_CM_EVENT_ADDR_RESOLVED:
iser_addr_handler(cma_id);
@@ -785,24 +822,28 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
case RDMA_CM_EVENT_DISCONNECTED:
case RDMA_CM_EVENT_DEVICE_REMOVAL:
case RDMA_CM_EVENT_ADDR_CHANGE:
+ case RDMA_CM_EVENT_TIMEWAIT_EXIT:
iser_disconnected_handler(cma_id);
break;
default:
iser_err("Unexpected RDMA CM event (%d)\n", event->event);
break;
}
+ mutex_unlock(&ib_conn->state_mutex);
return 0;
}
void iser_conn_init(struct iser_conn *ib_conn)
{
ib_conn->state = ISER_CONN_INIT;
- init_waitqueue_head(&ib_conn->wait);
ib_conn->post_recv_buf_count = 0;
atomic_set(&ib_conn->post_send_buf_count, 0);
init_completion(&ib_conn->stop_completion);
+ init_completion(&ib_conn->flush_completion);
+ init_completion(&ib_conn->up_completion);
INIT_LIST_HEAD(&ib_conn->conn_list);
spin_lock_init(&ib_conn->lock);
+ mutex_init(&ib_conn->state_mutex);
}
/**
@@ -810,22 +851,21 @@ void iser_conn_init(struct iser_conn *ib_conn)
* sleeps until the connection is established or rejected
*/
int iser_connect(struct iser_conn *ib_conn,
- struct sockaddr_in *src_addr,
- struct sockaddr_in *dst_addr,
+ struct sockaddr *src_addr,
+ struct sockaddr *dst_addr,
int non_blocking)
{
- struct sockaddr *src, *dst;
int err = 0;
- sprintf(ib_conn->name, "%pI4:%d",
- &dst_addr->sin_addr.s_addr, dst_addr->sin_port);
+ mutex_lock(&ib_conn->state_mutex);
+
+ sprintf(ib_conn->name, "%pISp", dst_addr);
+
+ iser_info("connecting to: %s\n", ib_conn->name);
/* the device is known only --after-- address resolution */
ib_conn->device = NULL;
- iser_info("connecting to: %pI4, port 0x%x\n",
- &dst_addr->sin_addr, dst_addr->sin_port);
-
ib_conn->state = ISER_CONN_PENDING;
ib_conn->cma_id = rdma_create_id(iser_cma_handler,
@@ -837,23 +877,21 @@ int iser_connect(struct iser_conn *ib_conn,
goto id_failure;
}
- src = (struct sockaddr *)src_addr;
- dst = (struct sockaddr *)dst_addr;
- err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000);
+ err = rdma_resolve_addr(ib_conn->cma_id, src_addr, dst_addr, 1000);
if (err) {
iser_err("rdma_resolve_addr failed: %d\n", err);
goto addr_failure;
}
if (!non_blocking) {
- wait_event_interruptible(ib_conn->wait,
- (ib_conn->state != ISER_CONN_PENDING));
+ wait_for_completion_interruptible(&ib_conn->up_completion);
if (ib_conn->state != ISER_CONN_UP) {
err = -EIO;
goto connect_failure;
}
}
+ mutex_unlock(&ib_conn->state_mutex);
mutex_lock(&ig.connlist_mutex);
list_add(&ib_conn->conn_list, &ig.connlist);
@@ -865,6 +903,7 @@ id_failure:
addr_failure:
ib_conn->state = ISER_CONN_DOWN;
connect_failure:
+ mutex_unlock(&ib_conn->state_mutex);
iser_conn_release(ib_conn);
return err;
}
@@ -1049,18 +1088,19 @@ static void iser_handle_comp_error(struct iser_tx_desc *desc,
if (ib_conn->post_recv_buf_count == 0 &&
atomic_read(&ib_conn->post_send_buf_count) == 0) {
- /* getting here when the state is UP means that the conn is *
- * being terminated asynchronously from the iSCSI layer's *
- * perspective. */
- if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
- ISER_CONN_TERMINATING))
+ /**
+ * getting here when the state is UP means that the conn is
+ * being terminated asynchronously from the iSCSI layer's
+ * perspective. It is safe to peek at the connection state
+ * since iscsi_conn_failure is allowed to be called twice.
+ **/
+ if (ib_conn->state == ISER_CONN_UP)
iscsi_conn_failure(ib_conn->iscsi_conn,
ISCSI_ERR_CONN_FAILED);
/* no more non completed posts to the QP, complete the
* termination process w.o worrying on disconnect event */
- ib_conn->state = ISER_CONN_DOWN;
- wake_up_interruptible(&ib_conn->wait);
+ complete(&ib_conn->flush_completion);
}
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index e3c2c5b4297f..62d2a18e1b41 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -130,6 +130,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
static struct scsi_transport_template *ib_srp_transport_template;
+static struct workqueue_struct *srp_remove_wq;
static struct ib_client srp_client = {
.name = "srp",
@@ -731,7 +732,7 @@ static bool srp_queue_remove_work(struct srp_target_port *target)
spin_unlock_irq(&target->lock);
if (changed)
- queue_work(system_long_wq, &target->remove_work);
+ queue_work(srp_remove_wq, &target->remove_work);
return changed;
}
@@ -1643,10 +1644,14 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
SCSI_SENSE_BUFFERSIZE));
}
- if (rsp->flags & (SRP_RSP_FLAG_DOOVER | SRP_RSP_FLAG_DOUNDER))
- scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
- else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
+ if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER))
scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
+ else if (unlikely(rsp->flags & SRP_RSP_FLAG_DIOVER))
+ scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_in_res_cnt));
+ else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER))
+ scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt));
+ else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
+ scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
srp_free_req(target, req, scmnd,
be32_to_cpu(rsp->req_lim_delta));
@@ -3261,9 +3266,10 @@ static void srp_remove_one(struct ib_device *device)
spin_unlock(&host->target_lock);
/*
- * Wait for target port removal tasks.
+ * Wait for tl_err and target port removal tasks.
*/
flush_workqueue(system_long_wq);
+ flush_workqueue(srp_remove_wq);
kfree(host);
}
@@ -3313,16 +3319,22 @@ static int __init srp_init_module(void)
indirect_sg_entries = cmd_sg_entries;
}
+ srp_remove_wq = create_workqueue("srp_remove");
+ if (!srp_remove_wq) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = -ENOMEM;
ib_srp_transport_template =
srp_attach_transport(&ib_srp_transport_functions);
if (!ib_srp_transport_template)
- return -ENOMEM;
+ goto destroy_wq;
ret = class_register(&srp_class);
if (ret) {
pr_err("couldn't register class infiniband_srp\n");
- srp_release_transport(ib_srp_transport_template);
- return ret;
+ goto release_tr;
}
ib_sa_register_client(&srp_sa_client);
@@ -3330,13 +3342,22 @@ static int __init srp_init_module(void)
ret = ib_register_client(&srp_client);
if (ret) {
pr_err("couldn't register IB client\n");
- srp_release_transport(ib_srp_transport_template);
- ib_sa_unregister_client(&srp_sa_client);
- class_unregister(&srp_class);
- return ret;
+ goto unreg_sa;
}
- return 0;
+out:
+ return ret;
+
+unreg_sa:
+ ib_sa_unregister_client(&srp_sa_client);
+ class_unregister(&srp_class);
+
+release_tr:
+ srp_release_transport(ib_srp_transport_template);
+
+destroy_wq:
+ destroy_workqueue(srp_remove_wq);
+ goto out;
}
static void __exit srp_cleanup_module(void)
@@ -3345,6 +3366,7 @@ static void __exit srp_cleanup_module(void)
ib_sa_unregister_client(&srp_sa_client);
class_unregister(&srp_class);
srp_release_transport(ib_srp_transport_template);
+ destroy_workqueue(srp_remove_wq);
}
module_init(srp_init_module);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index fe09f2788b15..d28a8c284da9 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -198,6 +198,7 @@ static void srpt_event_handler(struct ib_event_handler *handler,
case IB_EVENT_PKEY_CHANGE:
case IB_EVENT_SM_CHANGE:
case IB_EVENT_CLIENT_REREGISTER:
+ case IB_EVENT_GID_CHANGE:
/* Refresh port data asynchronously. */
if (event->element.port_num <= sdev->device->phys_port_cnt) {
sport = &sdev->port[event->element.port_num - 1];
@@ -563,7 +564,7 @@ static int srpt_refresh_port(struct srpt_port *sport)
&reg_req, 0,
srpt_mad_send_handler,
srpt_mad_recv_handler,
- sport);
+ sport, 0);
if (IS_ERR(sport->mad_agent)) {
ret = PTR_ERR(sport->mad_agent);
sport->mad_agent = NULL;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index fd325ec9f064..de055451d1af 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -108,9 +108,8 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
struct input_event ev;
ktime_t time;
- time = ktime_get();
- if (client->clkid != CLOCK_MONOTONIC)
- time = ktime_sub(time, ktime_get_monotonic_offset());
+ time = (client->clkid == CLOCK_MONOTONIC) ?
+ ktime_get() : ktime_get_real();
ev.time = ktime_to_timeval(time);
ev.type = EV_SYN;
@@ -202,7 +201,7 @@ static void evdev_events(struct input_handle *handle,
ktime_t time_mono, time_real;
time_mono = ktime_get();
- time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
+ time_real = ktime_mono_to_real(time_mono);
rcu_read_lock();
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index d398f1321f14..c30204f2fa30 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -237,6 +237,31 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
/**
+ * input_mt_drop_unused() - Inactivate slots not seen in this frame
+ * @dev: input device with allocated MT slots
+ *
+ * Lift all slots not seen since the last call to this function.
+ */
+void input_mt_drop_unused(struct input_dev *dev)
+{
+ struct input_mt *mt = dev->mt;
+ int i;
+
+ if (!mt)
+ return;
+
+ for (i = 0; i < mt->num_slots; i++) {
+ if (!input_mt_is_used(mt, &mt->slots[i])) {
+ input_mt_slot(dev, i);
+ input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ }
+ }
+
+ mt->frame++;
+}
+EXPORT_SYMBOL(input_mt_drop_unused);
+
+/**
* input_mt_sync_frame() - synchronize mt frame
* @dev: input device with allocated MT slots
*
@@ -247,27 +272,18 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation);
void input_mt_sync_frame(struct input_dev *dev)
{
struct input_mt *mt = dev->mt;
- struct input_mt_slot *s;
bool use_count = false;
if (!mt)
return;
- if (mt->flags & INPUT_MT_DROP_UNUSED) {
- for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
- if (input_mt_is_used(mt, s))
- continue;
- input_mt_slot(dev, s - mt->slots);
- input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
- }
- }
+ if (mt->flags & INPUT_MT_DROP_UNUSED)
+ input_mt_drop_unused(dev);
if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
use_count = true;
input_mt_report_pointer_emulation(dev, use_count);
-
- mt->frame++;
}
EXPORT_SYMBOL(input_mt_sync_frame);
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 9135606c8649..ab0fdcd36e18 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -158,7 +158,7 @@ static unsigned int get_time_pit(void)
#define GET_TIME(x) rdtscl(x)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "TSC"
-#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE)
+#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_TILE)
#define GET_TIME(x) do { x = get_cycles(); } while (0)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "get_cycles"
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 603fe0dd3682..177602cf7079 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -95,7 +95,8 @@
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
#define XTYPE_XBOX360W 2
-#define XTYPE_UNKNOWN 3
+#define XTYPE_XBOXONE 3
+#define XTYPE_UNKNOWN 4
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -121,6 +122,7 @@ static const struct xpad_device {
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+ { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
@@ -231,10 +233,12 @@ static const signed short xpad_abs_triggers[] = {
-1
};
-/* Xbox 360 has a vendor-specific class, so we cannot match it with only
+/*
+ * Xbox 360 has a vendor-specific class, so we cannot match it with only
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
- * wireless controllers have protocol 129. */
+ * wireless controllers have protocol 129.
+ */
#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \
.match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
.idVendor = (vend), \
@@ -245,9 +249,20 @@ static const signed short xpad_abs_triggers[] = {
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \
{ XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) }
+/* The Xbox One controller uses subclass 71 and protocol 208. */
+#define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \
+ .idVendor = (vend), \
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+ .bInterfaceSubClass = 71, \
+ .bInterfaceProtocol = (pr)
+#define XPAD_XBOXONE_VENDOR(vend) \
+ { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) }
+
static struct usb_device_id xpad_table[] = {
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
+ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
@@ -278,12 +293,10 @@ struct usb_xpad {
struct urb *bulk_out;
unsigned char *bdata;
-#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct urb *irq_out; /* urb for interrupt out report */
unsigned char *odata; /* output data */
dma_addr_t odata_dma;
struct mutex odata_mutex;
-#endif
#if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct xpad_led *led;
@@ -470,6 +483,105 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha
xpad360_process_packet(xpad, cmd, &data[4]);
}
+/*
+ * xpadone_process_buttons
+ *
+ * Process a button update packet from an Xbox one controller.
+ */
+static void xpadone_process_buttons(struct usb_xpad *xpad,
+ struct input_dev *dev,
+ unsigned char *data)
+{
+ /* menu/view buttons */
+ input_report_key(dev, BTN_START, data[4] & 0x04);
+ input_report_key(dev, BTN_SELECT, data[4] & 0x08);
+
+ /* buttons A,B,X,Y */
+ input_report_key(dev, BTN_A, data[4] & 0x10);
+ input_report_key(dev, BTN_B, data[4] & 0x20);
+ input_report_key(dev, BTN_X, data[4] & 0x40);
+ input_report_key(dev, BTN_Y, data[4] & 0x80);
+
+ /* digital pad */
+ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
+ /* dpad as buttons (left, right, up, down) */
+ input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04);
+ input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08);
+ input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01);
+ input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02);
+ } else {
+ input_report_abs(dev, ABS_HAT0X,
+ !!(data[5] & 0x08) - !!(data[5] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y,
+ !!(data[5] & 0x02) - !!(data[5] & 0x01));
+ }
+
+ /* TL/TR */
+ input_report_key(dev, BTN_TL, data[5] & 0x10);
+ input_report_key(dev, BTN_TR, data[5] & 0x20);
+
+ /* stick press left/right */
+ input_report_key(dev, BTN_THUMBL, data[5] & 0x40);
+ input_report_key(dev, BTN_THUMBR, data[5] & 0x80);
+
+ if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
+ /* left stick */
+ input_report_abs(dev, ABS_X,
+ (__s16) le16_to_cpup((__le16 *)(data + 10)));
+ input_report_abs(dev, ABS_Y,
+ ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX,
+ (__s16) le16_to_cpup((__le16 *)(data + 14)));
+ input_report_abs(dev, ABS_RY,
+ ~(__s16) le16_to_cpup((__le16 *)(data + 16)));
+ }
+
+ /* triggers left/right */
+ if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
+ input_report_key(dev, BTN_TL2,
+ (__u16) le16_to_cpup((__le16 *)(data + 6)));
+ input_report_key(dev, BTN_TR2,
+ (__u16) le16_to_cpup((__le16 *)(data + 8)));
+ } else {
+ input_report_abs(dev, ABS_Z,
+ (__u16) le16_to_cpup((__le16 *)(data + 6)));
+ input_report_abs(dev, ABS_RZ,
+ (__u16) le16_to_cpup((__le16 *)(data + 8)));
+ }
+
+ input_sync(dev);
+}
+
+/*
+ * xpadone_process_packet
+ *
+ * Completes a request by converting the data into events for the
+ * input subsystem. This version is for the Xbox One controller.
+ *
+ * The report format was gleaned from
+ * https://github.com/kylelemons/xbox/blob/master/xbox.go
+ */
+
+static void xpadone_process_packet(struct usb_xpad *xpad,
+ u16 cmd, unsigned char *data)
+{
+ struct input_dev *dev = xpad->dev;
+
+ switch (data[0]) {
+ case 0x20:
+ xpadone_process_buttons(xpad, dev, data);
+ break;
+
+ case 0x07:
+ /* the xbox button has its own special report */
+ input_report_key(dev, BTN_MODE, data[4] & 0x01);
+ input_sync(dev);
+ break;
+ }
+}
+
static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -502,6 +614,9 @@ static void xpad_irq_in(struct urb *urb)
case XTYPE_XBOX360W:
xpad360w_process_packet(xpad, 0, xpad->idata);
break;
+ case XTYPE_XBOXONE:
+ xpadone_process_packet(xpad, 0, xpad->idata);
+ break;
default:
xpad_process_packet(xpad, 0, xpad->idata);
}
@@ -535,7 +650,6 @@ static void xpad_bulk_out(struct urb *urb)
}
}
-#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
static void xpad_irq_out(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -573,6 +687,7 @@ exit:
static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
{
struct usb_endpoint_descriptor *ep_irq_out;
+ int ep_irq_out_idx;
int error;
if (xpad->xtype == XTYPE_UNKNOWN)
@@ -593,7 +708,10 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
goto fail2;
}
- ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+ /* Xbox One controller has in/out endpoints swapped. */
+ ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1;
+ ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc;
+
usb_fill_int_urb(xpad->irq_out, xpad->udev,
usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
xpad->odata, XPAD_PKT_LEN,
@@ -621,11 +739,6 @@ static void xpad_deinit_output(struct usb_xpad *xpad)
xpad->odata, xpad->odata_dma);
}
}
-#else
-static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
-static void xpad_deinit_output(struct usb_xpad *xpad) {}
-static void xpad_stop_output(struct usb_xpad *xpad) {}
-#endif
#ifdef CONFIG_JOYSTICK_XPAD_FF
static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
@@ -692,7 +805,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
static int xpad_init_ff(struct usb_xpad *xpad)
{
- if (xpad->xtype == XTYPE_UNKNOWN)
+ if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE)
return 0;
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
@@ -801,6 +914,14 @@ static int xpad_open(struct input_dev *dev)
if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
return -EIO;
+ if (xpad->xtype == XTYPE_XBOXONE) {
+ /* Xbox one controller needs to be initialized. */
+ xpad->odata[0] = 0x05;
+ xpad->odata[1] = 0x20;
+ xpad->irq_out->transfer_buffer_length = 2;
+ return usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ }
+
return 0;
}
@@ -816,6 +937,7 @@ static void xpad_close(struct input_dev *dev)
static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
{
+ struct usb_xpad *xpad = input_get_drvdata(input_dev);
set_bit(abs, input_dev->absbit);
switch (abs) {
@@ -827,7 +949,10 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
break;
case ABS_Z:
case ABS_RZ: /* the triggers (if mapped to axes) */
- input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
+ if (xpad->xtype == XTYPE_XBOXONE)
+ input_set_abs_params(input_dev, abs, 0, 1023, 0, 0);
+ else
+ input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
@@ -842,6 +967,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct usb_xpad *xpad;
struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
+ int ep_irq_in_idx;
int i, error;
for (i = 0; xpad_device[i].idVendor; i++) {
@@ -850,6 +976,16 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
break;
}
+ if (xpad_device[i].xtype == XTYPE_XBOXONE &&
+ intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+ /*
+ * The Xbox One controller lists three interfaces all with the
+ * same interface class, subclass and protocol. Differentiate by
+ * interface number.
+ */
+ return -ENODEV;
+ }
+
xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
input_dev = input_allocate_device();
if (!xpad || !input_dev) {
@@ -920,7 +1056,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit(xpad_common_btn[i], input_dev->keybit);
/* set up model-specific ones */
- if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
+ if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W ||
+ xpad->xtype == XTYPE_XBOXONE) {
for (i = 0; xpad360_btn[i] >= 0; i++)
__set_bit(xpad360_btn[i], input_dev->keybit);
} else {
@@ -933,7 +1070,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
__set_bit(xpad_btn_pad[i], input_dev->keybit);
} else {
for (i = 0; xpad_abs_pad[i] >= 0; i++)
- xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+ xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
}
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
@@ -956,7 +1093,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
if (error)
goto fail5;
- ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
+ /* Xbox One controller has in/out endpoints swapped. */
+ ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0;
+ ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;
+
usb_fill_int_urb(xpad->irq_in, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f7e79b481349..a3958c63d7d5 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
+config KEYBOARD_CAP1106
+ tristate "Microchip CAP1106 touch sensor"
+ depends on OF && I2C
+ select REGMAP_I2C
+ help
+ Say Y here to enable the CAP1106 touch sensor driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cap1106.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 7504ae19049d..0a3345634d79 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CAP1106) += cap1106.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c
new file mode 100644
index 000000000000..180b184ab90f
--- /dev/null
+++ b/drivers/input/keyboard/cap1106.c
@@ -0,0 +1,341 @@
+/*
+ * Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
+ *
+ * http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
+ *
+ * (c) 2014 Daniel Mack <linux@zonque.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+#define CAP1106_REG_MAIN_CONTROL 0x00
+#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6)
+#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
+#define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4)
+#define CAP1106_REG_GENERAL_STATUS 0x02
+#define CAP1106_REG_SENSOR_INPUT 0x03
+#define CAP1106_REG_NOISE_FLAG_STATUS 0x0a
+#define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X))
+#define CAP1106_REG_SENSITIVITY_CONTROL 0x1f
+#define CAP1106_REG_CONFIG 0x20
+#define CAP1106_REG_SENSOR_ENABLE 0x21
+#define CAP1106_REG_SENSOR_CONFIG 0x22
+#define CAP1106_REG_SENSOR_CONFIG2 0x23
+#define CAP1106_REG_SAMPLING_CONFIG 0x24
+#define CAP1106_REG_CALIBRATION 0x25
+#define CAP1106_REG_INT_ENABLE 0x26
+#define CAP1106_REG_REPEAT_RATE 0x28
+#define CAP1106_REG_MT_CONFIG 0x2a
+#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
+#define CAP1106_REG_MT_PATTERN 0x2d
+#define CAP1106_REG_RECALIB_CONFIG 0x2f
+#define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X))
+#define CAP1106_REG_SENSOR_NOISE_THRESH 0x38
+#define CAP1106_REG_STANDBY_CHANNEL 0x40
+#define CAP1106_REG_STANDBY_CONFIG 0x41
+#define CAP1106_REG_STANDBY_SENSITIVITY 0x42
+#define CAP1106_REG_STANDBY_THRESH 0x43
+#define CAP1106_REG_CONFIG2 0x44
+#define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
+#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))
+#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
+#define CAP1106_REG_SENSOR_CALIB_LSB2 0xba
+#define CAP1106_REG_PRODUCT_ID 0xfd
+#define CAP1106_REG_MANUFACTURER_ID 0xfe
+#define CAP1106_REG_REVISION 0xff
+
+#define CAP1106_NUM_CHN 6
+#define CAP1106_PRODUCT_ID 0x55
+#define CAP1106_MANUFACTURER_ID 0x5d
+
+struct cap1106_priv {
+ struct regmap *regmap;
+ struct input_dev *idev;
+
+ /* config */
+ unsigned short keycodes[CAP1106_NUM_CHN];
+};
+
+static const struct reg_default cap1106_reg_defaults[] = {
+ { CAP1106_REG_MAIN_CONTROL, 0x00 },
+ { CAP1106_REG_GENERAL_STATUS, 0x00 },
+ { CAP1106_REG_SENSOR_INPUT, 0x00 },
+ { CAP1106_REG_NOISE_FLAG_STATUS, 0x00 },
+ { CAP1106_REG_SENSITIVITY_CONTROL, 0x2f },
+ { CAP1106_REG_CONFIG, 0x20 },
+ { CAP1106_REG_SENSOR_ENABLE, 0x3f },
+ { CAP1106_REG_SENSOR_CONFIG, 0xa4 },
+ { CAP1106_REG_SENSOR_CONFIG2, 0x07 },
+ { CAP1106_REG_SAMPLING_CONFIG, 0x39 },
+ { CAP1106_REG_CALIBRATION, 0x00 },
+ { CAP1106_REG_INT_ENABLE, 0x3f },
+ { CAP1106_REG_REPEAT_RATE, 0x3f },
+ { CAP1106_REG_MT_CONFIG, 0x80 },
+ { CAP1106_REG_MT_PATTERN_CONFIG, 0x00 },
+ { CAP1106_REG_MT_PATTERN, 0x3f },
+ { CAP1106_REG_RECALIB_CONFIG, 0x8a },
+ { CAP1106_REG_SENSOR_THRESH(0), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(1), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(2), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(3), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(4), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(5), 0x40 },
+ { CAP1106_REG_SENSOR_NOISE_THRESH, 0x01 },
+ { CAP1106_REG_STANDBY_CHANNEL, 0x00 },
+ { CAP1106_REG_STANDBY_CONFIG, 0x39 },
+ { CAP1106_REG_STANDBY_SENSITIVITY, 0x02 },
+ { CAP1106_REG_STANDBY_THRESH, 0x40 },
+ { CAP1106_REG_CONFIG2, 0x40 },
+ { CAP1106_REG_SENSOR_CALIB_LSB1, 0x00 },
+ { CAP1106_REG_SENSOR_CALIB_LSB2, 0x00 },
+};
+
+static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CAP1106_REG_MAIN_CONTROL:
+ case CAP1106_REG_SENSOR_INPUT:
+ case CAP1106_REG_SENOR_DELTA(0):
+ case CAP1106_REG_SENOR_DELTA(1):
+ case CAP1106_REG_SENOR_DELTA(2):
+ case CAP1106_REG_SENOR_DELTA(3):
+ case CAP1106_REG_SENOR_DELTA(4):
+ case CAP1106_REG_SENOR_DELTA(5):
+ case CAP1106_REG_PRODUCT_ID:
+ case CAP1106_REG_MANUFACTURER_ID:
+ case CAP1106_REG_REVISION:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config cap1106_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CAP1106_REG_REVISION,
+ .reg_defaults = cap1106_reg_defaults,
+
+ .num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = cap1106_volatile_reg,
+};
+
+static irqreturn_t cap1106_thread_func(int irq_num, void *data)
+{
+ struct cap1106_priv *priv = data;
+ unsigned int status;
+ int ret, i;
+
+ /*
+ * Deassert interrupt. This needs to be done before reading the status
+ * registers, which will not carry valid values otherwise.
+ */
+ ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
+ if (ret < 0)
+ goto out;
+
+ for (i = 0; i < CAP1106_NUM_CHN; i++)
+ input_report_key(priv->idev, priv->keycodes[i],
+ status & (1 << i));
+
+ input_sync(priv->idev);
+
+out:
+ return IRQ_HANDLED;
+}
+
+static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep)
+{
+ return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+ CAP1106_REG_MAIN_CONTROL_DLSEEP,
+ sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0);
+}
+
+static int cap1106_input_open(struct input_dev *idev)
+{
+ struct cap1106_priv *priv = input_get_drvdata(idev);
+
+ return cap1106_set_sleep(priv, false);
+}
+
+static void cap1106_input_close(struct input_dev *idev)
+{
+ struct cap1106_priv *priv = input_get_drvdata(idev);
+
+ cap1106_set_sleep(priv, true);
+}
+
+static int cap1106_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c_client->dev;
+ struct cap1106_priv *priv;
+ struct device_node *node;
+ int i, error, irq, gain = 0;
+ unsigned int val, rev;
+ u32 gain32, keycodes[CAP1106_NUM_CHN];
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ error = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
+ if (error)
+ return error;
+
+ if (val != CAP1106_PRODUCT_ID) {
+ dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
+ val, CAP1106_PRODUCT_ID);
+ return -ENODEV;
+ }
+
+ error = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
+ if (error)
+ return error;
+
+ if (val != CAP1106_MANUFACTURER_ID) {
+ dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
+ val, CAP1106_MANUFACTURER_ID);
+ return -ENODEV;
+ }
+
+ error = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
+ if (error < 0)
+ return error;
+
+ dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
+ i2c_set_clientdata(i2c_client, priv);
+ node = dev->of_node;
+
+ if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
+ if (is_power_of_2(gain32) && gain32 <= 8)
+ gain = ilog2(gain32);
+ else
+ dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes));
+
+ /* Provide some useful defaults */
+ for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+ keycodes[i] = KEY_A + i;
+
+ of_property_read_u32_array(node, "linux,keycodes",
+ keycodes, ARRAY_SIZE(keycodes));
+
+ for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+ priv->keycodes[i] = keycodes[i];
+
+ error = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+ CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
+ gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
+ if (error)
+ return error;
+
+ /* Disable autorepeat. The Linux input system has its own handling. */
+ error = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
+ if (error)
+ return error;
+
+ priv->idev = devm_input_allocate_device(dev);
+ if (!priv->idev)
+ return -ENOMEM;
+
+ priv->idev->name = "CAP1106 capacitive touch sensor";
+ priv->idev->id.bustype = BUS_I2C;
+ priv->idev->evbit[0] = BIT_MASK(EV_KEY);
+
+ if (of_property_read_bool(node, "autorepeat"))
+ __set_bit(EV_REP, priv->idev->evbit);
+
+ for (i = 0; i < CAP1106_NUM_CHN; i++)
+ __set_bit(priv->keycodes[i], priv->idev->keybit);
+
+ __clear_bit(KEY_RESERVED, priv->idev->keybit);
+
+ priv->idev->keycode = priv->keycodes;
+ priv->idev->keycodesize = sizeof(priv->keycodes[0]);
+ priv->idev->keycodemax = ARRAY_SIZE(priv->keycodes);
+
+ priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
+ priv->idev->id.product = CAP1106_PRODUCT_ID;
+ priv->idev->id.version = rev;
+
+ priv->idev->open = cap1106_input_open;
+ priv->idev->close = cap1106_input_close;
+
+ input_set_drvdata(priv->idev, priv);
+
+ /*
+ * Put the device in deep sleep mode for now.
+ * ->open() will bring it back once the it is actually needed.
+ */
+ cap1106_set_sleep(priv, true);
+
+ error = input_register_device(priv->idev);
+ if (error)
+ return error;
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq) {
+ dev_err(dev, "Unable to parse or map IRQ\n");
+ return -ENXIO;
+ }
+
+ error = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
+ IRQF_ONESHOT, dev_name(dev), priv);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static const struct of_device_id cap1106_dt_ids[] = {
+ { .compatible = "microchip,cap1106", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
+
+static const struct i2c_device_id cap1106_i2c_ids[] = {
+ { "cap1106", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
+
+static struct i2c_driver cap1106_i2c_driver = {
+ .driver = {
+ .name = "cap1106",
+ .owner = THIS_MODULE,
+ .of_match_table = cap1106_dt_ids,
+ },
+ .id_table = cap1106_i2c_ids,
+ .probe = cap1106_i2c_probe,
+};
+
+module_i2c_driver(cap1106_i2c_driver);
+
+MODULE_ALIAS("platform:cap1106");
+MODULE_DESCRIPTION("Microchip CAP1106 driver");
+MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 408379669d3c..791781ade4e7 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -24,8 +24,8 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
-#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
* @dev: Device pointer
* @idev: Input device
* @ec: Top level ChromeOS device to use to talk to EC
- * @event_notifier: interrupt event notifier for transport devices
*/
struct cros_ec_keyb {
unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
- struct notifier_block notifier;
};
@@ -173,41 +171,55 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
input_sync(ckdev->idev);
}
-static int cros_ec_keyb_open(struct input_dev *dev)
-{
- struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
- return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
- &ckdev->notifier);
-}
-
-static void cros_ec_keyb_close(struct input_dev *dev)
-{
- struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
- blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
- &ckdev->notifier);
-}
-
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
{
- return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
- kb_state, ckdev->cols);
+ struct cros_ec_command msg = {
+ .version = 0,
+ .command = EC_CMD_MKBP_STATE,
+ .outdata = NULL,
+ .outsize = 0,
+ .indata = kb_state,
+ .insize = ckdev->cols,
+ };
+
+ return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
}
-static int cros_ec_keyb_work(struct notifier_block *nb,
- unsigned long state, void *_notify)
+static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
{
+ struct cros_ec_keyb *ckdev = data;
+ struct cros_ec_device *ec = ckdev->ec;
int ret;
- struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
- notifier);
uint8_t kb_state[ckdev->cols];
+ if (device_may_wakeup(ec->dev))
+ pm_wakeup_event(ec->dev, 0);
+
ret = cros_ec_keyb_get_state(ckdev, kb_state);
if (ret >= 0)
cros_ec_keyb_process(ckdev, kb_state, ret);
+ else
+ dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
- return NOTIFY_DONE;
+ return IRQ_HANDLED;
+}
+
+static int cros_ec_keyb_open(struct input_dev *dev)
+{
+ struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+ struct cros_ec_device *ec = ckdev->ec;
+
+ return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "cros_ec_keyb", ckdev);
+}
+
+static void cros_ec_keyb_close(struct input_dev *dev)
+{
+ struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+ struct cros_ec_device *ec = ckdev->ec;
+
+ free_irq(ec->irq, ckdev);
}
static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -238,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
if (!idev)
return -ENOMEM;
+ if (!ec->irq) {
+ dev_err(dev, "no EC IRQ specified\n");
+ return -EINVAL;
+ }
+
ckdev->ec = ec;
- ckdev->notifier.notifier_call = cros_ec_keyb_work;
ckdev->dev = dev;
dev_set_drvdata(&pdev->dev, ckdev);
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c
index 8280cb16260b..20a99c368d16 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -531,8 +531,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int imx_kbd_suspend(struct device *dev)
+static int __maybe_unused imx_kbd_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -552,7 +551,7 @@ static int imx_kbd_suspend(struct device *dev)
return 0;
}
-static int imx_kbd_resume(struct device *dev)
+static int __maybe_unused imx_kbd_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct imx_keypad *kbd = platform_get_drvdata(pdev);
@@ -575,7 +574,6 @@ err_clk:
return ret;
}
-#endif
static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume);
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 0b42118cbf8f..cb32e2b506b7 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -558,6 +558,12 @@ static ssize_t lm8323_pwm_store_time(struct device *dev,
}
static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time);
+static struct attribute *lm8323_pwm_attrs[] = {
+ &dev_attr_time.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lm8323_pwm);
+
static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
const char *name)
{
@@ -580,16 +586,11 @@ static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
if (name) {
pwm->cdev.name = name;
pwm->cdev.brightness_set = lm8323_pwm_set_brightness;
+ pwm->cdev.groups = lm8323_pwm_groups;
if (led_classdev_register(dev, &pwm->cdev) < 0) {
dev_err(dev, "couldn't register PWM %d\n", id);
return -1;
}
- if (device_create_file(pwm->cdev.dev,
- &dev_attr_time) < 0) {
- dev_err(dev, "couldn't register time attribute\n");
- led_classdev_unregister(&pwm->cdev);
- return -1;
- }
pwm->enabled = true;
}
@@ -753,11 +754,8 @@ fail3:
device_remove_file(&client->dev, &dev_attr_disable_kp);
fail2:
while (--pwm >= 0)
- if (lm->pwm[pwm].enabled) {
- device_remove_file(lm->pwm[pwm].cdev.dev,
- &dev_attr_time);
+ if (lm->pwm[pwm].enabled)
led_classdev_unregister(&lm->pwm[pwm].cdev);
- }
fail1:
input_free_device(idev);
kfree(lm);
@@ -777,10 +775,8 @@ static int lm8323_remove(struct i2c_client *client)
device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
for (i = 0; i < 3; i++)
- if (lm->pwm[i].enabled) {
- device_remove_file(lm->pwm[i].cdev.dev, &dev_attr_time);
+ if (lm->pwm[i].enabled)
led_classdev_unregister(&lm->pwm[i].cdev);
- }
kfree(lm);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 430b54539720..faa6da53eba8 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -203,12 +203,17 @@ static int max7359_probe(struct i2c_client *client,
dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret);
- keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!keypad || !input_dev) {
+ keypad = devm_kzalloc(&client->dev, sizeof(struct max7359_keypad),
+ GFP_KERNEL);
+ if (!keypad) {
dev_err(&client->dev, "failed to allocate memory\n");
- error = -ENOMEM;
- goto failed_free_mem;
+ return -ENOMEM;
+ }
+
+ input_dev = devm_input_allocate_device(&client->dev);
+ if (!input_dev) {
+ dev_err(&client->dev, "failed to allocate input device\n");
+ return -ENOMEM;
}
keypad->client = client;
@@ -230,19 +235,20 @@ static int max7359_probe(struct i2c_client *client,
max7359_build_keycode(keypad, keymap_data);
- error = request_threaded_irq(client->irq, NULL, max7359_interrupt,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- client->name, keypad);
+ error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ max7359_interrupt,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ client->name, keypad);
if (error) {
dev_err(&client->dev, "failed to register interrupt\n");
- goto failed_free_mem;
+ return error;
}
/* Register the input device */
error = input_register_device(input_dev);
if (error) {
dev_err(&client->dev, "failed to register input device\n");
- goto failed_free_irq;
+ return error;
}
/* Initialize MAX7359 */
@@ -252,24 +258,6 @@ static int max7359_probe(struct i2c_client *client,
device_init_wakeup(&client->dev, 1);
return 0;
-
-failed_free_irq:
- free_irq(client->irq, keypad);
-failed_free_mem:
- input_free_device(input_dev);
- kfree(keypad);
- return error;
-}
-
-static int max7359_remove(struct i2c_client *client)
-{
- struct max7359_keypad *keypad = i2c_get_clientdata(client);
-
- free_irq(client->irq, keypad);
- input_unregister_device(keypad->input_dev);
- kfree(keypad);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -313,7 +301,6 @@ static struct i2c_driver max7359_i2c_driver = {
.pm = &max7359_pm,
},
.probe = max7359_probe,
- .remove = max7359_remove,
.id_table = max7359_ids,
};
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index 01f3b5b300f3..a3fe4a990cc9 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -392,7 +392,6 @@ static void keyspan_irq_recv(struct urb *urb)
default:
goto resubmit;
- break;
}
if (debug)
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 5a6334be30b8..e34dfc29beb3 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -83,6 +83,9 @@ soc_button_device_create(struct pnp_dev *pdev,
sizeof(*gpio_keys_pdata) +
sizeof(*gpio_keys) * MAX_NBUTTONS,
GFP_KERNEL);
+ if (!gpio_keys_pdata)
+ return ERR_PTR(-ENOMEM);
+
gpio_keys = (void *)(gpio_keys_pdata + 1);
for (info = button_info; info->name; info++) {
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 65fd3150919b..179ff1cd6f6b 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -86,13 +86,13 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
spin_lock_irqsave(&state->lock, flags);
if (count) {
- outb(0x01, info->regs + 0);
- outb(0x00, info->regs + 2);
- outb((count >> 16) & 0xff, info->regs + 3);
- outb((count >> 8) & 0xff, info->regs + 4);
- outb(0x00, info->regs + 5);
+ sbus_writeb(0x01, info->regs + 0);
+ sbus_writeb(0x00, info->regs + 2);
+ sbus_writeb((count >> 16) & 0xff, info->regs + 3);
+ sbus_writeb((count >> 8) & 0xff, info->regs + 4);
+ sbus_writeb(0x00, info->regs + 5);
} else {
- outb(0x00, info->regs + 0);
+ sbus_writeb(0x00, info->regs + 0);
}
spin_unlock_irqrestore(&state->lock, flags);
@@ -123,15 +123,15 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
if (count) {
/* enable counter 2 */
- outb(inb(info->enable_reg) | 3, info->enable_reg);
+ sbus_writeb(sbus_readb(info->enable_reg) | 3, info->enable_reg);
/* set command for counter 2, 2 byte write */
- outb(0xB6, info->freq_regs + 1);
+ sbus_writeb(0xB6, info->freq_regs + 1);
/* select desired HZ */
- outb(count & 0xff, info->freq_regs + 0);
- outb((count >> 8) & 0xff, info->freq_regs + 0);
+ sbus_writeb(count & 0xff, info->freq_regs + 0);
+ sbus_writeb((count >> 8) & 0xff, info->freq_regs + 0);
} else {
/* disable counter 2 */
- outb(inb_p(info->enable_reg) & 0xFC, info->enable_reg);
+ sbus_writeb(sbus_readb(info->enable_reg) & 0xFC, info->enable_reg);
}
spin_unlock_irqrestore(&state->lock, flags);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 856936247500..421e29e4cd81 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -311,7 +311,14 @@ static int uinput_open(struct inode *inode, struct file *file)
static int uinput_validate_absbits(struct input_dev *dev)
{
unsigned int cnt;
- int retval = 0;
+ int nslot;
+
+ if (!test_bit(EV_ABS, dev->evbit))
+ return 0;
+
+ /*
+ * Check if absmin/absmax/absfuzz/absflat are sane.
+ */
for (cnt = 0; cnt < ABS_CNT; cnt++) {
int min, max;
@@ -327,8 +334,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
UINPUT_NAME, cnt,
input_abs_get_min(dev, cnt),
input_abs_get_max(dev, cnt));
- retval = -EINVAL;
- break;
+ return -EINVAL;
}
if (input_abs_get_flat(dev, cnt) >
@@ -340,11 +346,18 @@ static int uinput_validate_absbits(struct input_dev *dev)
input_abs_get_flat(dev, cnt),
input_abs_get_min(dev, cnt),
input_abs_get_max(dev, cnt));
- retval = -EINVAL;
- break;
+ return -EINVAL;
}
}
- return retval;
+
+ if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+ nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+ input_mt_init_slots(dev, nslot, 0);
+ } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+ input_set_events_per_packet(dev, 60);
+ }
+
+ return 0;
}
static int uinput_allocate_device(struct uinput_device *udev)
@@ -410,19 +423,9 @@ static int uinput_setup_device(struct uinput_device *udev,
input_abs_set_flat(dev, i, user_dev->absflat[i]);
}
- /* check if absmin/absmax/absfuzz/absflat are filled as
- * told in Documentation/input/input-programming.txt */
- if (test_bit(EV_ABS, dev->evbit)) {
- retval = uinput_validate_absbits(dev);
- if (retval < 0)
- goto exit;
- if (test_bit(ABS_MT_SLOT, dev->absbit)) {
- int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
- input_mt_init_slots(dev, nslot, 0);
- } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
- input_set_events_per_packet(dev, 60);
- }
- }
+ retval = uinput_validate_absbits(dev);
+ if (retval < 0)
+ goto exit;
udev->state = UIST_SETUP_COMPLETE;
retval = count;
@@ -720,6 +723,12 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
}
switch (cmd) {
+ case UI_GET_VERSION:
+ if (put_user(UINPUT_VERSION,
+ (unsigned int __user *)p))
+ retval = -EFAULT;
+ goto out;
+
case UI_DEV_CREATE:
retval = uinput_create_device(udev);
goto out;
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index fb15c64ffb95..a59a1a64b674 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -99,6 +99,8 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */
+#define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */
+#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -281,11 +283,10 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
*
* The bitmaps don't have enough data to track fingers, so this function
* only generates points representing a bounding box of at most two contacts.
- * These two points are returned in x1, y1, x2, and y2.
+ * These two points are returned in fields->mt.
*/
static void alps_process_bitmap_dolphin(struct alps_data *priv,
- struct alps_fields *fields,
- int *x1, int *y1, int *x2, int *y2)
+ struct alps_fields *fields)
{
int box_middle_x, box_middle_y;
unsigned int x_map, y_map;
@@ -308,8 +309,6 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
if (x_msb > priv->x_bits || y_msb > priv->y_bits)
return;
- *x1 = *y1 = *x2 = *y2 = 0;
-
if (fields->fingers > 1) {
start_bit = priv->x_bits - x_msb;
end_bit = priv->x_bits - x_lsb;
@@ -320,10 +319,35 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
end_bit = y_msb - 1;
box_middle_y = (priv->y_max * (start_bit + end_bit)) /
(2 * (priv->y_bits - 1));
- *x1 = fields->x;
- *y1 = fields->y;
- *x2 = 2 * box_middle_x - *x1;
- *y2 = 2 * box_middle_y - *y1;
+ fields->mt[0] = fields->st;
+ fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x;
+ fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y;
+ }
+}
+
+static void alps_get_bitmap_points(unsigned int map,
+ struct alps_bitmap_point *low,
+ struct alps_bitmap_point *high,
+ int *fingers)
+{
+ struct alps_bitmap_point *point;
+ int i, bit, prev_bit = 0;
+
+ point = low;
+ for (i = 0; map != 0; i++, map >>= 1) {
+ bit = map & 1;
+ if (bit) {
+ if (!prev_bit) {
+ point->start_bit = i;
+ point->num_bits = 0;
+ (*fingers)++;
+ }
+ point->num_bits++;
+ } else {
+ if (prev_bit)
+ point = high;
+ }
+ prev_bit = bit;
}
}
@@ -334,71 +358,21 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
*
* The bitmaps don't have enough data to track fingers, so this function
* only generates points representing a bounding box of all contacts.
- * These points are returned in x1, y1, x2, and y2 when the return value
+ * These points are returned in fields->mt when the return value
* is greater than 0.
*/
static int alps_process_bitmap(struct alps_data *priv,
- unsigned int x_map, unsigned int y_map,
- int *x1, int *y1, int *x2, int *y2)
+ struct alps_fields *fields)
{
- struct alps_bitmap_point {
- int start_bit;
- int num_bits;
- };
-
- int fingers_x = 0, fingers_y = 0, fingers;
- int i, bit, prev_bit;
+ int i, fingers_x = 0, fingers_y = 0, fingers;
struct alps_bitmap_point x_low = {0,}, x_high = {0,};
struct alps_bitmap_point y_low = {0,}, y_high = {0,};
- struct alps_bitmap_point *point;
- if (!x_map || !y_map)
+ if (!fields->x_map || !fields->y_map)
return 0;
- *x1 = *y1 = *x2 = *y2 = 0;
-
- prev_bit = 0;
- point = &x_low;
- for (i = 0; x_map != 0; i++, x_map >>= 1) {
- bit = x_map & 1;
- if (bit) {
- if (!prev_bit) {
- point->start_bit = i;
- fingers_x++;
- }
- point->num_bits++;
- } else {
- if (prev_bit)
- point = &x_high;
- else
- point->num_bits = 0;
- }
- prev_bit = bit;
- }
-
- /*
- * y bitmap is reversed for what we need (lower positions are in
- * higher bits), so we process from the top end.
- */
- y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits);
- prev_bit = 0;
- point = &y_low;
- for (i = 0; y_map != 0; i++, y_map <<= 1) {
- bit = y_map & (1 << (sizeof(y_map) * BITS_PER_BYTE - 1));
- if (bit) {
- if (!prev_bit) {
- point->start_bit = i;
- fingers_y++;
- }
- point->num_bits++;
- } else {
- if (prev_bit)
- point = &y_high;
- else
- point->num_bits = 0;
- }
- prev_bit = bit;
- }
+ alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
+ alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
/*
* Fingers can overlap, so we use the maximum count of fingers
@@ -407,58 +381,91 @@ static int alps_process_bitmap(struct alps_data *priv,
fingers = max(fingers_x, fingers_y);
/*
- * If total fingers is > 1 but either axis reports only a single
- * contact, we have overlapping or adjacent fingers. For the
- * purposes of creating a bounding box, divide the single contact
- * (roughly) equally between the two points.
+ * If an axis reports only a single contact, we have overlapping or
+ * adjacent fingers. Divide the single contact between the two points.
*/
- if (fingers > 1) {
- if (fingers_x == 1) {
- i = x_low.num_bits / 2;
- x_low.num_bits = x_low.num_bits - i;
- x_high.start_bit = x_low.start_bit + i;
- x_high.num_bits = max(i, 1);
- } else if (fingers_y == 1) {
- i = y_low.num_bits / 2;
- y_low.num_bits = y_low.num_bits - i;
- y_high.start_bit = y_low.start_bit + i;
- y_high.num_bits = max(i, 1);
- }
+ if (fingers_x == 1) {
+ i = (x_low.num_bits - 1) / 2;
+ x_low.num_bits = x_low.num_bits - i;
+ x_high.start_bit = x_low.start_bit + i;
+ x_high.num_bits = max(i, 1);
+ }
+ if (fingers_y == 1) {
+ i = (y_low.num_bits - 1) / 2;
+ y_low.num_bits = y_low.num_bits - i;
+ y_high.start_bit = y_low.start_bit + i;
+ y_high.num_bits = max(i, 1);
}
- *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
- (2 * (priv->x_bits - 1));
- *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
- (2 * (priv->y_bits - 1));
-
- if (fingers > 1) {
- *x2 = (priv->x_max *
- (2 * x_high.start_bit + x_high.num_bits - 1)) /
- (2 * (priv->x_bits - 1));
- *y2 = (priv->y_max *
- (2 * y_high.start_bit + y_high.num_bits - 1)) /
- (2 * (priv->y_bits - 1));
+ fields->mt[0].x =
+ (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
+ (2 * (priv->x_bits - 1));
+ fields->mt[0].y =
+ (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
+ (2 * (priv->y_bits - 1));
+
+ fields->mt[1].x =
+ (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
+ (2 * (priv->x_bits - 1));
+ fields->mt[1].y =
+ (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
+ (2 * (priv->y_bits - 1));
+
+ /* y-bitmap order is reversed, except on rushmore */
+ if (!(priv->flags & ALPS_IS_RUSHMORE)) {
+ fields->mt[0].y = priv->y_max - fields->mt[0].y;
+ fields->mt[1].y = priv->y_max - fields->mt[1].y;
}
return fingers;
}
-static void alps_set_slot(struct input_dev *dev, int slot, bool active,
- int x, int y)
+static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
{
input_mt_slot(dev, slot);
- input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
- if (active) {
- input_report_abs(dev, ABS_MT_POSITION_X, x);
- input_report_abs(dev, ABS_MT_POSITION_Y, y);
- }
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+ input_report_abs(dev, ABS_MT_POSITION_X, x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y);
}
-static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers,
- int x1, int y1, int x2, int y2)
+static void alps_report_mt_data(struct psmouse *psmouse, int n)
{
- alps_set_slot(dev, 0, num_fingers != 0, x1, y1);
- alps_set_slot(dev, 1, num_fingers == 2, x2, y2);
+ struct alps_data *priv = psmouse->private;
+ struct input_dev *dev = psmouse->dev;
+ struct alps_fields *f = &priv->f;
+ int i, slot[MAX_TOUCHES];
+
+ input_mt_assign_slots(dev, slot, f->mt, n);
+ for (i = 0; i < n; i++)
+ alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
+
+ input_mt_sync_frame(dev);
+}
+
+static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
+{
+ struct alps_data *priv = psmouse->private;
+ struct input_dev *dev = psmouse->dev;
+ struct alps_fields *f = &priv->f;
+
+ /* Use st data when we don't have mt data */
+ if (fingers < 2) {
+ f->mt[0].x = f->st.x;
+ f->mt[0].y = f->st.y;
+ fingers = f->pressure > 0 ? 1 : 0;
+ }
+
+ alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2);
+
+ input_mt_report_finger_count(dev, fingers);
+
+ input_report_key(dev, BTN_LEFT, f->left);
+ input_report_key(dev, BTN_RIGHT, f->right);
+ input_report_key(dev, BTN_MIDDLE, f->middle);
+
+ input_report_abs(dev, ABS_PRESSURE, f->pressure);
+
+ input_sync(dev);
}
static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
@@ -532,7 +539,7 @@ static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
f->ts_middle = !!(p[3] & 0x40);
}
-static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
+static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
struct psmouse *psmouse)
{
f->first_mp = !!(p[4] & 0x40);
@@ -546,24 +553,31 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
((p[2] & 0x7f) << 1) |
(p[4] & 0x01);
- f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
+ f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
((p[0] & 0x30) >> 4);
- f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
- f->z = p[5] & 0x7f;
+ f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
+ f->pressure = p[5] & 0x7f;
alps_decode_buttons_v3(f, p);
+
+ return 0;
}
-static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
+static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
struct psmouse *psmouse)
{
alps_decode_pinnacle(f, p, psmouse);
+ /* Rushmore's packet decode has a bit difference with Pinnacle's */
+ f->is_mp = !!(p[5] & 0x40);
+ f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
f->x_map |= (p[5] & 0x10) << 11;
f->y_map |= (p[5] & 0x20) << 6;
+
+ return 0;
}
-static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
+static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
struct psmouse *psmouse)
{
u64 palm_data = 0;
@@ -573,9 +587,9 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
f->is_mp = !!(p[0] & 0x20);
if (!f->is_mp) {
- f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
- f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
- f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
+ f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
+ f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
+ f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
alps_decode_buttons_v3(f, p);
} else {
f->fingers = ((p[0] & 0x6) >> 1 |
@@ -596,19 +610,21 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
f->x_map = (palm_data >> priv->y_bits) &
(BIT(priv->x_bits) - 1);
}
+
+ return 0;
}
static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
- int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- int fingers = 0, bmap_fn;
- struct alps_fields f = {0};
+ struct alps_fields *f = &priv->f;
+ int fingers = 0;
- priv->decode_fields(&f, packet, psmouse);
+ memset(f, 0, sizeof(*f));
+
+ priv->decode_fields(f, packet, psmouse);
/*
* There's no single feature of touchpad position and bitmap packets
@@ -623,22 +639,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
* packet. Check for this, and when it happens process the
* position packet as usual.
*/
- if (f.is_mp) {
- fingers = f.fingers;
+ if (f->is_mp) {
+ fingers = f->fingers;
if (priv->proto_version == ALPS_PROTO_V3) {
- bmap_fn = alps_process_bitmap(priv, f.x_map,
- f.y_map, &x1, &y1,
- &x2, &y2);
-
- /*
- * We shouldn't report more than one finger if
- * we don't have two coordinates.
- */
- if (fingers > 1 && bmap_fn < 2)
- fingers = bmap_fn;
+ if (alps_process_bitmap(priv, f) == 0)
+ fingers = 0; /* Use st data */
/* Now process position packet */
- priv->decode_fields(&f, priv->multi_data,
+ priv->decode_fields(f, priv->multi_data,
psmouse);
} else {
/*
@@ -647,15 +655,14 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
* calculate Pt2, so we need to do position
* packet decode first.
*/
- priv->decode_fields(&f, priv->multi_data,
+ priv->decode_fields(f, priv->multi_data,
psmouse);
/*
* Since Dolphin's finger number is reliable,
* there is no need to compare with bmap_fn.
*/
- alps_process_bitmap_dolphin(priv, &f, &x1, &y1,
- &x2, &y2);
+ alps_process_bitmap_dolphin(priv, f);
}
} else {
priv->multi_packet = 0;
@@ -670,10 +677,10 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
* out misidentified bitmap packets, we reject anything with this
* bit set.
*/
- if (f.is_mp)
+ if (f->is_mp)
return;
- if (!priv->multi_packet && f.first_mp) {
+ if (!priv->multi_packet && f->first_mp) {
priv->multi_packet = 1;
memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
return;
@@ -687,44 +694,15 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
* with x, y, and z all zero, so these seem to be flukes.
* Ignore them.
*/
- if (f.x && f.y && !f.z)
+ if (f->st.x && f->st.y && !f->pressure)
return;
- /*
- * If we don't have MT data or the bitmaps were empty, we have
- * to rely on ST data.
- */
- if (!fingers) {
- x1 = f.x;
- y1 = f.y;
- fingers = f.z > 0 ? 1 : 0;
- }
-
- if (f.z >= 64)
- input_report_key(dev, BTN_TOUCH, 1);
- else
- input_report_key(dev, BTN_TOUCH, 0);
-
- alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
-
- input_mt_report_finger_count(dev, fingers);
-
- input_report_key(dev, BTN_LEFT, f.left);
- input_report_key(dev, BTN_RIGHT, f.right);
- input_report_key(dev, BTN_MIDDLE, f.middle);
-
- if (f.z > 0) {
- input_report_abs(dev, ABS_X, f.x);
- input_report_abs(dev, ABS_Y, f.y);
- }
- input_report_abs(dev, ABS_PRESSURE, f.z);
-
- input_sync(dev);
+ alps_report_semi_mt_data(psmouse, fingers);
if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
- input_report_key(dev2, BTN_LEFT, f.ts_left);
- input_report_key(dev2, BTN_RIGHT, f.ts_right);
- input_report_key(dev2, BTN_MIDDLE, f.ts_middle);
+ input_report_key(dev2, BTN_LEFT, f->ts_left);
+ input_report_key(dev2, BTN_RIGHT, f->ts_right);
+ input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
input_sync(dev2);
}
}
@@ -823,13 +801,8 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
- struct input_dev *dev = psmouse->dev;
+ struct alps_fields *f = &priv->f;
int offset;
- int x, y, z;
- int left, right;
- int x1, y1, x2, y2;
- int fingers = 0;
- unsigned int x_bitmap, y_bitmap;
/*
* v4 has a 6-byte encoding for bitmap data, but this data is
@@ -851,71 +824,207 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
if (++priv->multi_packet > 2) {
priv->multi_packet = 0;
- x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) |
+ f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
((priv->multi_data[3] & 0x60) << 3) |
((priv->multi_data[0] & 0x3f) << 2) |
((priv->multi_data[1] & 0x60) >> 5);
- y_bitmap = ((priv->multi_data[5] & 0x01) << 10) |
+ f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
((priv->multi_data[3] & 0x1f) << 5) |
(priv->multi_data[1] & 0x1f);
- fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap,
- &x1, &y1, &x2, &y2);
-
- /* Store MT data.*/
- priv->fingers = fingers;
- priv->x1 = x1;
- priv->x2 = x2;
- priv->y1 = y1;
- priv->y2 = y2;
+ f->fingers = alps_process_bitmap(priv, f);
}
- left = packet[4] & 0x01;
- right = packet[4] & 0x02;
+ f->left = packet[4] & 0x01;
+ f->right = packet[4] & 0x02;
- x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
- ((packet[0] & 0x30) >> 4);
- y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
- z = packet[5] & 0x7f;
+ f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
+ ((packet[0] & 0x30) >> 4);
+ f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
+ f->pressure = packet[5] & 0x7f;
- /*
- * If there were no contacts in the bitmap, use ST
- * points in MT reports.
- * If there were two contacts or more, report MT data.
- */
- if (priv->fingers < 2) {
- x1 = x;
- y1 = y;
- fingers = z > 0 ? 1 : 0;
- } else {
- fingers = priv->fingers;
- x1 = priv->x1;
- x2 = priv->x2;
- y1 = priv->y1;
- y2 = priv->y2;
+ alps_report_semi_mt_data(psmouse, f->fingers);
+}
+
+static bool alps_is_valid_package_v7(struct psmouse *psmouse)
+{
+ switch (psmouse->pktcnt) {
+ case 3:
+ return (psmouse->packet[2] & 0x40) == 0x40;
+ case 4:
+ return (psmouse->packet[3] & 0x48) == 0x48;
+ case 6:
+ return (psmouse->packet[5] & 0x40) == 0x00;
}
+ return true;
+}
- if (z >= 64)
- input_report_key(dev, BTN_TOUCH, 1);
+static unsigned char alps_get_packet_id_v7(char *byte)
+{
+ unsigned char packet_id;
+
+ if (byte[4] & 0x40)
+ packet_id = V7_PACKET_ID_TWO;
+ else if (byte[4] & 0x01)
+ packet_id = V7_PACKET_ID_MULTI;
+ else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
+ packet_id = V7_PACKET_ID_NEW;
+ else if (byte[1] == 0x00 && byte[4] == 0x00)
+ packet_id = V7_PACKET_ID_IDLE;
else
- input_report_key(dev, BTN_TOUCH, 0);
+ packet_id = V7_PACKET_ID_UNKNOWN;
- alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2);
+ return packet_id;
+}
- input_mt_report_finger_count(dev, fingers);
+static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
+ unsigned char *pkt,
+ unsigned char pkt_id)
+{
+ mt[0].x = ((pkt[2] & 0x80) << 4);
+ mt[0].x |= ((pkt[2] & 0x3F) << 5);
+ mt[0].x |= ((pkt[3] & 0x30) >> 1);
+ mt[0].x |= (pkt[3] & 0x07);
+ mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
+
+ mt[1].x = ((pkt[3] & 0x80) << 4);
+ mt[1].x |= ((pkt[4] & 0x80) << 3);
+ mt[1].x |= ((pkt[4] & 0x3F) << 4);
+ mt[1].y = ((pkt[5] & 0x80) << 3);
+ mt[1].y |= ((pkt[5] & 0x3F) << 4);
+
+ switch (pkt_id) {
+ case V7_PACKET_ID_TWO:
+ mt[1].x &= ~0x000F;
+ mt[1].y |= 0x000F;
+ break;
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
+ case V7_PACKET_ID_MULTI:
+ mt[1].x &= ~0x003F;
+ mt[1].y &= ~0x0020;
+ mt[1].y |= ((pkt[4] & 0x02) << 4);
+ mt[1].y |= 0x001F;
+ break;
- if (z > 0) {
- input_report_abs(dev, ABS_X, x);
- input_report_abs(dev, ABS_Y, y);
+ case V7_PACKET_ID_NEW:
+ mt[1].x &= ~0x003F;
+ mt[1].x |= (pkt[0] & 0x20);
+ mt[1].y |= 0x000F;
+ break;
}
- input_report_abs(dev, ABS_PRESSURE, z);
+
+ mt[0].y = 0x7FF - mt[0].y;
+ mt[1].y = 0x7FF - mt[1].y;
+}
+
+static int alps_get_mt_count(struct input_mt_pos *mt)
+{
+ int i;
+
+ for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++)
+ /* empty */;
+
+ return i;
+}
+
+static int alps_decode_packet_v7(struct alps_fields *f,
+ unsigned char *p,
+ struct psmouse *psmouse)
+{
+ unsigned char pkt_id;
+
+ pkt_id = alps_get_packet_id_v7(p);
+ if (pkt_id == V7_PACKET_ID_IDLE)
+ return 0;
+ if (pkt_id == V7_PACKET_ID_UNKNOWN)
+ return -1;
+
+ alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
+
+ if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) {
+ f->left = (p[0] & 0x80) >> 7;
+ f->right = (p[0] & 0x20) >> 5;
+ f->middle = (p[0] & 0x10) >> 4;
+ }
+
+ if (pkt_id == V7_PACKET_ID_TWO)
+ f->fingers = alps_get_mt_count(f->mt);
+ else if (pkt_id == V7_PACKET_ID_MULTI)
+ f->fingers = 3 + (p[5] & 0x03);
+
+ return 0;
+}
+
+static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ unsigned char *packet = psmouse->packet;
+ struct input_dev *dev2 = priv->dev2;
+ int x, y, z, left, right, middle;
+
+ /*
+ * b7 b6 b5 b4 b3 b2 b1 b0
+ * Byte0 0 1 0 0 1 0 0 0
+ * Byte1 1 1 * * 1 M R L
+ * Byte2 X7 1 X5 X4 X3 X2 X1 X0
+ * Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0
+ * Byte4 Y7 0 Y5 Y4 Y3 1 1 0
+ * Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
+ * M / R / L: Middle / Right / Left button
+ */
+
+ x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
+ y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
+ ((packet[3] & 0x20) << 1);
+ z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
+
+ left = (packet[1] & 0x01);
+ right = (packet[1] & 0x02) >> 1;
+ middle = (packet[1] & 0x04) >> 2;
+
+ /* Divide 2 since trackpoint's speed is too fast */
+ input_report_rel(dev2, REL_X, (char)x / 2);
+ input_report_rel(dev2, REL_Y, -((char)y / 2));
+
+ input_report_key(dev2, BTN_LEFT, left);
+ input_report_key(dev2, BTN_RIGHT, right);
+ input_report_key(dev2, BTN_MIDDLE, middle);
+
+ input_sync(dev2);
+}
+
+static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ struct input_dev *dev = psmouse->dev;
+ struct alps_fields *f = &priv->f;
+
+ memset(f, 0, sizeof(*f));
+
+ if (priv->decode_fields(f, psmouse->packet, psmouse))
+ return;
+
+ alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
+
+ input_mt_report_finger_count(dev, f->fingers);
+
+ input_report_key(dev, BTN_LEFT, f->left);
+ input_report_key(dev, BTN_RIGHT, f->right);
+ input_report_key(dev, BTN_MIDDLE, f->middle);
input_sync(dev);
}
+static void alps_process_packet_v7(struct psmouse *psmouse)
+{
+ unsigned char *packet = psmouse->packet;
+
+ if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06)
+ alps_process_trackstick_packet_v7(psmouse);
+ else
+ alps_process_touchpad_packet_v7(psmouse);
+}
+
static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
unsigned char packet[],
bool report_buttons)
@@ -1080,6 +1189,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
return PSMOUSE_BAD_DATA;
}
+ if (priv->proto_version == ALPS_PROTO_V7 &&
+ !alps_is_valid_package_v7(psmouse)) {
+ psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
+ psmouse->pktcnt - 1,
+ psmouse->packet[psmouse->pktcnt - 1]);
+ return PSMOUSE_BAD_DATA;
+ }
+
if (psmouse->pktcnt == psmouse->pktsize) {
priv->process_packet(psmouse);
return PSMOUSE_FULL_PACKET;
@@ -1192,6 +1309,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
return 0;
}
+static bool alps_check_valid_firmware_id(unsigned char id[])
+{
+ if (id[0] == 0x73)
+ return true;
+
+ if (id[0] == 0x88 &&
+ (id[1] == 0x07 ||
+ id[1] == 0x08 ||
+ (id[1] & 0xf0) == 0xb0 ||
+ (id[1] & 0xf0) == 0xc0)) {
+ return true;
+ }
+
+ return false;
+}
+
static int alps_enter_command_mode(struct psmouse *psmouse)
{
unsigned char param[4];
@@ -1201,8 +1334,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
return -1;
}
- if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
- param[0] != 0x73) {
+ if (!alps_check_valid_firmware_id(param)) {
psmouse_dbg(psmouse,
"unknown response while entering command mode\n");
return -1;
@@ -1660,6 +1792,45 @@ error:
return -1;
}
+static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
+{
+ int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys;
+ struct alps_data *priv = psmouse->private;
+
+ reg = alps_command_mode_read_reg(psmouse, reg_pitch);
+ if (reg < 0)
+ return reg;
+
+ x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+ x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
+
+ y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
+ y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
+
+ reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
+ if (reg < 0)
+ return reg;
+
+ x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+ x_electrode = 17 + x_electrode;
+
+ y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
+ y_electrode = 13 + y_electrode;
+
+ x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
+ y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */
+
+ priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
+ priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
+
+ psmouse_dbg(psmouse,
+ "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n",
+ x_pitch, y_pitch, x_electrode, y_electrode,
+ x_phys / 10, y_phys / 10, priv->x_res, priv->y_res);
+
+ return 0;
+}
+
static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -1680,6 +1851,9 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
goto error;
+ if (alps_get_v3_v7_resolution(psmouse, 0xc2da))
+ goto error;
+
reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
if (reg_val == -1)
goto error;
@@ -1856,6 +2030,35 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
return 0;
}
+static int alps_hw_init_v7(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ int reg_val, ret = -1;
+
+ if (alps_enter_command_mode(psmouse) ||
+ alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
+ goto error;
+
+ if (alps_get_v3_v7_resolution(psmouse, 0xc397))
+ goto error;
+
+ if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
+ goto error;
+
+ reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
+ if (reg_val == -1)
+ goto error;
+ if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
+ goto error;
+
+ alps_exit_command_mode(psmouse);
+ return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+error:
+ alps_exit_command_mode(psmouse);
+ return ret;
+}
+
static void alps_set_defaults(struct alps_data *priv)
{
priv->byte0 = 0x8f;
@@ -1914,6 +2117,21 @@ static void alps_set_defaults(struct alps_data *priv)
priv->x_max = 2047;
priv->y_max = 1535;
break;
+ case ALPS_PROTO_V7:
+ priv->hw_init = alps_hw_init_v7;
+ priv->process_packet = alps_process_packet_v7;
+ priv->decode_fields = alps_decode_packet_v7;
+ priv->set_abs_params = alps_set_abs_params_mt;
+ priv->nibble_commands = alps_v3_nibble_commands;
+ priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+ priv->x_max = 0xfff;
+ priv->y_max = 0x7ff;
+ priv->byte0 = 0x48;
+ priv->mask0 = 0x48;
+
+ if (priv->fw_ver[1] != 0xba)
+ priv->flags |= ALPS_BUTTONPAD;
+ break;
}
}
@@ -1972,6 +2190,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
alps_exit_command_mode(psmouse))
return -EIO;
+ /* Save the Firmware version */
+ memcpy(priv->fw_ver, ec, 3);
+
if (alps_match_table(psmouse, priv, e7, ec) == 0) {
return 0;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
@@ -1982,6 +2203,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
return -EIO;
else
return 0;
+ } else if (ec[0] == 0x88 &&
+ ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
+ priv->proto_version = ALPS_PROTO_V7;
+ alps_set_defaults(priv);
+
+ return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
priv->proto_version = ALPS_PROTO_V3;
alps_set_defaults(priv);
@@ -1990,6 +2217,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
priv->decode_fields = alps_decode_rushmore;
priv->x_bits = 16;
priv->y_bits = 12;
+ priv->flags |= ALPS_IS_RUSHMORE;
/* hack to make addr_command, nibble_command available */
psmouse->private = priv;
@@ -2044,17 +2272,21 @@ static void alps_set_abs_params_st(struct alps_data *priv,
static void alps_set_abs_params_mt(struct alps_data *priv,
struct input_dev *dev1)
{
- set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
- input_mt_init_slots(dev1, 2, 0);
input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
- set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit);
+ input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res);
+ input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res);
+
+ input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER |
+ INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT);
+
set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
- input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
- input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
+ /* V7 is real multi-touch */
+ if (priv->proto_version == ALPS_PROTO_V7)
+ clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
}
int alps_init(struct psmouse *psmouse)
@@ -2100,7 +2332,9 @@ int alps_init(struct psmouse *psmouse)
dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
priv->set_abs_params(priv, dev1);
- input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
+ /* No pressure on V7 */
+ if (priv->proto_version != ALPS_PROTO_V7)
+ input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->flags & ALPS_WHEEL) {
dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
@@ -2117,6 +2351,9 @@ int alps_init(struct psmouse *psmouse)
dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ } else if (priv->flags & ALPS_BUTTONPAD) {
+ set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
+ clear_bit(BTN_RIGHT, dev1->keybit);
} else {
dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 03f88b6940c7..66240b47819a 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -12,17 +12,39 @@
#ifndef _ALPS_H
#define _ALPS_H
+#include <linux/input/mt.h>
+
#define ALPS_PROTO_V1 1
#define ALPS_PROTO_V2 2
#define ALPS_PROTO_V3 3
#define ALPS_PROTO_V4 4
#define ALPS_PROTO_V5 5
#define ALPS_PROTO_V6 6
+#define ALPS_PROTO_V7 7 /* t3btl t4s */
+
+#define MAX_TOUCHES 2
#define DOLPHIN_COUNT_PER_ELECTRODE 64
#define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */
#define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */
+/*
+ * enum V7_PACKET_ID - defines the packet type for V7
+ * V7_PACKET_ID_IDLE: There's no finger and no button activity.
+ * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
+ * or there's button activities.
+ * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
+ * V7_PACKET_ID_NEW: The finger position in slot is not continues from
+ * previous packet.
+*/
+enum V7_PACKET_ID {
+ V7_PACKET_ID_IDLE,
+ V7_PACKET_ID_TWO,
+ V7_PACKET_ID_MULTI,
+ V7_PACKET_ID_NEW,
+ V7_PACKET_ID_UNKNOWN,
+};
+
/**
* struct alps_model_info - touchpad ID table
* @signature: E7 response string to match.
@@ -46,7 +68,7 @@ struct alps_model_info {
unsigned char command_mode_resp;
unsigned char proto_version;
unsigned char byte0, mask0;
- unsigned char flags;
+ int flags;
};
/**
@@ -65,14 +87,19 @@ struct alps_nibble_commands {
unsigned char data;
};
+struct alps_bitmap_point {
+ int start_bit;
+ int num_bits;
+};
+
/**
* struct alps_fields - decoded version of the report packet
* @x_map: Bitmap of active X positions for MT.
* @y_map: Bitmap of active Y positions for MT.
* @fingers: Number of fingers for MT.
- * @x: X position for ST.
- * @y: Y position for ST.
- * @z: Z position for ST.
+ * @pressure: Pressure.
+ * @st: position for ST.
+ * @mt: position for MT.
* @first_mp: Packet is the first of a multi-packet report.
* @is_mp: Packet is part of a multi-packet report.
* @left: Left touchpad button is active.
@@ -86,9 +113,11 @@ struct alps_fields {
unsigned int x_map;
unsigned int y_map;
unsigned int fingers;
- unsigned int x;
- unsigned int y;
- unsigned int z;
+
+ int pressure;
+ struct input_mt_pos st;
+ struct input_mt_pos mt[MAX_TOUCHES];
+
unsigned int first_mp:1;
unsigned int is_mp:1;
@@ -113,6 +142,7 @@ struct alps_fields {
* known format for this model. The first byte of the report, ANDed with
* mask0, should match byte0.
* @mask0: The mask used to check the first byte of the report.
+ * @fw_ver: cached copy of firmware version (EC report)
* @flags: Additional device capabilities (passthrough port, trackstick, etc.).
* @x_max: Largest possible X position value.
* @y_max: Largest possible Y position value.
@@ -125,11 +155,7 @@ struct alps_fields {
* @prev_fin: Finger bit from previous packet.
* @multi_packet: Multi-packet data in progress.
* @multi_data: Saved multi-packet data.
- * @x1: First X coordinate from last MT report.
- * @x2: Second X coordinate from last MT report.
- * @y1: First Y coordinate from last MT report.
- * @y2: Second Y coordinate from last MT report.
- * @fingers: Number of fingers from last MT report.
+ * @f: Decoded packet data fields.
* @quirks: Bitmap of ALPS_QUIRK_*.
* @timer: Timer for flushing out the final report packet in the stream.
*/
@@ -142,23 +168,25 @@ struct alps_data {
int addr_command;
unsigned char proto_version;
unsigned char byte0, mask0;
- unsigned char flags;
+ unsigned char fw_ver[3];
+ int flags;
int x_max;
int y_max;
int x_bits;
int y_bits;
+ unsigned int x_res;
+ unsigned int y_res;
int (*hw_init)(struct psmouse *psmouse);
void (*process_packet)(struct psmouse *psmouse);
- void (*decode_fields)(struct alps_fields *f, unsigned char *p,
+ int (*decode_fields)(struct alps_fields *f, unsigned char *p,
struct psmouse *psmouse);
void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
int prev_fin;
int multi_packet;
unsigned char multi_data[6];
- int x1, x2, y1, y2;
- int fingers;
+ struct alps_fields f;
u8 quirks;
struct timer_list timer;
};
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index ef9e0b8a9aa7..e8573c68f77e 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse)
}
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+
+static bool cr48_profile_sensor;
+
struct min_max_quirk {
const char * const *pnp_ids;
int x_min, x_max, y_min, y_max;
@@ -1152,6 +1155,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
priv->agm_pending = false;
}
+static void synaptics_profile_sensor_process(struct psmouse *psmouse,
+ struct synaptics_hw_state *sgm,
+ int num_fingers)
+{
+ struct input_dev *dev = psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+ struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
+ struct input_mt_pos pos[2];
+ int slot[2], nsemi, i;
+
+ nsemi = clamp_val(num_fingers, 0, 2);
+
+ for (i = 0; i < nsemi; i++) {
+ pos[i].x = hw[i]->x;
+ pos[i].y = synaptics_invert_y(hw[i]->y);
+ }
+
+ input_mt_assign_slots(dev, slot, pos, nsemi);
+
+ for (i = 0; i < nsemi; i++) {
+ input_mt_slot(dev, slot[i]);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+ input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
+ input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
+ }
+
+ input_mt_drop_unused(dev);
+ input_mt_report_pointer_emulation(dev, false);
+ input_mt_report_finger_count(dev, num_fingers);
+
+ synaptics_report_buttons(psmouse, sgm);
+
+ input_sync(dev);
+}
+
/*
* called for each full received packet from the touchpad
*/
@@ -1215,6 +1254,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
finger_width = 0;
}
+ if (cr48_profile_sensor) {
+ synaptics_profile_sensor_process(psmouse, &hw, num_fingers);
+ return;
+ }
+
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
num_fingers);
@@ -1360,6 +1404,9 @@ static void set_input_params(struct psmouse *psmouse,
set_abs_position_params(dev, priv, ABS_X, ABS_Y);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
+ if (cr48_profile_sensor)
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
@@ -1371,11 +1418,16 @@ static void set_input_params(struct psmouse *psmouse,
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
- /* Non-image sensors with AGM use semi-mt */
- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
- input_mt_init_slots(dev, 2, 0);
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
ABS_MT_POSITION_Y);
+ /*
+ * Profile sensor in CR-48 tracks contacts reasonably well,
+ * other non-image sensors with AGM use semi-mt.
+ */
+ input_mt_init_slots(dev, 2,
+ INPUT_MT_POINTER |
+ (cr48_profile_sensor ?
+ INPUT_MT_TRACK : INPUT_MT_SEMI_MT));
}
if (SYN_CAP_PALMDETECT(priv->capabilities))
@@ -1577,10 +1629,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
{ }
};
+static const struct dmi_system_id __initconst cr48_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ /* Cr-48 Chromebook (Codename Mario) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
+ },
+ },
+#endif
+ { }
+};
+
void __init synaptics_module_init(void)
{
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
broken_olpc_ec = dmi_check_system(olpc_dmi_table);
+ cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
}
static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
index 613261994621..e74e5d6e5f9f 100644
--- a/drivers/input/serio/hyperv-keyboard.c
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -170,6 +170,15 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
serio_interrupt(kbd_dev->hv_serio, scan_code, 0);
}
spin_unlock_irqrestore(&kbd_dev->lock, flags);
+
+ /*
+ * Only trigger a wakeup on key down, otherwise
+ * "echo freeze > /sys/power/state" can't really enter the
+ * state because the Enter-UP can trigger a wakeup at once.
+ */
+ if (!(info & IS_BREAK))
+ pm_wakeup_event(&hv_dev->device, 0);
+
break;
default:
@@ -376,6 +385,9 @@ static int hv_kbd_probe(struct hv_device *hv_dev,
goto err_close_vmbus;
serio_register_port(kbd_dev->hv_serio);
+
+ device_init_wakeup(&hv_dev->device, true);
+
return 0;
err_close_vmbus:
@@ -390,6 +402,7 @@ static int hv_kbd_remove(struct hv_device *hv_dev)
{
struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
+ device_init_wakeup(&hv_dev->device, false);
serio_unregister_port(kbd_dev->hv_serio);
vmbus_close(hv_dev->channel);
kfree(kbd_dev);
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
index bed7cbf84cfd..623bb9e0d5a4 100644
--- a/drivers/input/tablet/Kconfig
+++ b/drivers/input/tablet/Kconfig
@@ -73,20 +73,14 @@ config TABLET_USB_KBTAB
To compile this driver as a module, choose M here: the
module will be called kbtab.
-config TABLET_USB_WACOM
- tristate "Wacom Intuos/Graphire tablet support (USB)"
- depends on USB_ARCH_HAS_HCD
- select POWER_SUPPLY
- select USB
- select NEW_LEDS
- select LEDS_CLASS
+config TABLET_SERIAL_WACOM4
+ tristate "Wacom protocol 4 serial tablet support"
+ select SERIO
help
- Say Y here if you want to use the USB version of the Wacom Intuos
- or Graphire tablet. Make sure to say Y to "Mouse support"
- (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
- (CONFIG_INPUT_EVDEV) as well.
+ Say Y here if you want to use Wacom protocol 4 serial tablets.
+ E.g. serial versions of the Cintiq, Graphire or Penpartner.
To compile this driver as a module, choose M here: the
- module will be called wacom.
+ module will be called wacom_serial4.
endif
diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile
index 3f6c25220638..2e130101cf3c 100644
--- a/drivers/input/tablet/Makefile
+++ b/drivers/input/tablet/Makefile
@@ -2,12 +2,10 @@
# Makefile for the tablet drivers
#
-# Multipart objects.
-wacom-objs := wacom_wac.o wacom_sys.o
obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o
obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o
obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
-obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o
+obj-$(CONFIG_TABLET_SERIAL_WACOM4) += wacom_serial4.o
diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c
new file mode 100644
index 000000000000..20ab802461e7
--- /dev/null
+++ b/drivers/input/tablet/wacom_serial4.c
@@ -0,0 +1,620 @@
+/*
+ * Wacom protocol 4 serial tablet driver
+ *
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ * Copyright 2011-2012 Julian Squires <julian@cipht.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version of 2 of the License, or (at your
+ * option) any later version. See the file COPYING in the main directory of
+ * this archive for more details.
+ *
+ * Many thanks to Bill Seremetis, without whom PenPartner support
+ * would not have been possible. Thanks to Patrick Mahoney.
+ *
+ * This driver was developed with reference to much code written by others,
+ * particularly:
+ * - elo, gunze drivers by Vojtech Pavlik <vojtech@ucw.cz>;
+ * - wacom_w8001 driver by Jaya Kumar <jayakumar.lkml@gmail.com>;
+ * - the USB wacom input driver, credited to many people
+ * (see drivers/input/tablet/wacom.h);
+ * - new and old versions of linuxwacom / xf86-input-wacom credited to
+ * Frederic Lepied, France. <Lepied@XFree86.org> and
+ * Ping Cheng, Wacom. <pingc@wacom.com>;
+ * - and xf86wacom.c (a presumably ancient version of the linuxwacom code),
+ * by Frederic Lepied and Raph Levien <raph@gtk.org>.
+ *
+ * To do:
+ * - support pad buttons; (requires access to a model with pad buttons)
+ * - support (protocol 4-style) tilt (requires access to a > 1.4 rom model)
+ */
+
+/*
+ * Wacom serial protocol 4 documentation taken from linuxwacom-0.9.9 code,
+ * protocol 4 uses 7 or 9 byte of data in the following format:
+ *
+ * Byte 1
+ * bit 7 Sync bit always 1
+ * bit 6 Pointing device detected
+ * bit 5 Cursor = 0 / Stylus = 1
+ * bit 4 Reserved
+ * bit 3 1 if a button on the pointing device has been pressed
+ * bit 2 P0 (optional)
+ * bit 1 X15
+ * bit 0 X14
+ *
+ * Byte 2
+ * bit 7 Always 0
+ * bits 6-0 = X13 - X7
+ *
+ * Byte 3
+ * bit 7 Always 0
+ * bits 6-0 = X6 - X0
+ *
+ * Byte 4
+ * bit 7 Always 0
+ * bit 6 B3
+ * bit 5 B2
+ * bit 4 B1
+ * bit 3 B0
+ * bit 2 P1 (optional)
+ * bit 1 Y15
+ * bit 0 Y14
+ *
+ * Byte 5
+ * bit 7 Always 0
+ * bits 6-0 = Y13 - Y7
+ *
+ * Byte 6
+ * bit 7 Always 0
+ * bits 6-0 = Y6 - Y0
+ *
+ * Byte 7
+ * bit 7 Always 0
+ * bit 6 Sign of pressure data; or wheel-rel for cursor tool
+ * bit 5 P7; or REL1 for cursor tool
+ * bit 4 P6; or REL0 for cursor tool
+ * bit 3 P5
+ * bit 2 P4
+ * bit 1 P3
+ * bit 0 P2
+ *
+ * byte 8 and 9 are optional and present only
+ * in tilt mode.
+ *
+ * Byte 8
+ * bit 7 Always 0
+ * bit 6 Sign of tilt X
+ * bit 5 Xt6
+ * bit 4 Xt5
+ * bit 3 Xt4
+ * bit 2 Xt3
+ * bit 1 Xt2
+ * bit 0 Xt1
+ *
+ * Byte 9
+ * bit 7 Always 0
+ * bit 6 Sign of tilt Y
+ * bit 5 Yt6
+ * bit 4 Yt5
+ * bit 3 Yt4
+ * bit 2 Yt3
+ * bit 1 Yt2
+ * bit 0 Yt1
+ */
+
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+MODULE_AUTHOR("Julian Squires <julian@cipht.net>, Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Wacom protocol 4 serial tablet driver");
+MODULE_LICENSE("GPL");
+
+#define REQUEST_MODEL_AND_ROM_VERSION "~#"
+#define REQUEST_MAX_COORDINATES "~C\r"
+#define REQUEST_CONFIGURATION_STRING "~R\r"
+#define REQUEST_RESET_TO_PROTOCOL_IV "\r#"
+/*
+ * Note: sending "\r$\r" causes at least the Digitizer II to send
+ * packets in ASCII instead of binary. "\r#" seems to undo that.
+ */
+
+#define COMMAND_START_SENDING_PACKETS "ST\r"
+#define COMMAND_STOP_SENDING_PACKETS "SP\r"
+#define COMMAND_MULTI_MODE_INPUT "MU1\r"
+#define COMMAND_ORIGIN_IN_UPPER_LEFT "OC1\r"
+#define COMMAND_ENABLE_ALL_MACRO_BUTTONS "~M0\r"
+#define COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS "~M1\r"
+#define COMMAND_TRANSMIT_AT_MAX_RATE "IT0\r"
+#define COMMAND_DISABLE_INCREMENTAL_MODE "IN0\r"
+#define COMMAND_ENABLE_CONTINUOUS_MODE "SR\r"
+#define COMMAND_ENABLE_PRESSURE_MODE "PH1\r"
+#define COMMAND_Z_FILTER "ZF1\r"
+
+/* Note that this is a protocol 4 packet without tilt information. */
+#define PACKET_LENGTH 7
+#define DATA_SIZE 32
+
+/* flags */
+#define F_COVERS_SCREEN 0x01
+#define F_HAS_STYLUS2 0x02
+#define F_HAS_SCROLLWHEEL 0x04
+
+/* device IDs */
+#define STYLUS_DEVICE_ID 0x02
+#define CURSOR_DEVICE_ID 0x06
+#define ERASER_DEVICE_ID 0x0A
+
+enum { STYLUS = 1, ERASER, CURSOR };
+
+static const struct {
+ int device_id;
+ int input_id;
+} tools[] = {
+ { 0, 0 },
+ { STYLUS_DEVICE_ID, BTN_TOOL_PEN },
+ { ERASER_DEVICE_ID, BTN_TOOL_RUBBER },
+ { CURSOR_DEVICE_ID, BTN_TOOL_MOUSE },
+};
+
+struct wacom {
+ struct input_dev *dev;
+ struct completion cmd_done;
+ int result;
+ u8 expect;
+ u8 eraser_mask;
+ unsigned int extra_z_bits;
+ unsigned int flags;
+ unsigned int res_x, res_y;
+ unsigned int max_x, max_y;
+ unsigned int tool;
+ unsigned int idx;
+ u8 data[DATA_SIZE];
+ char phys[32];
+};
+
+enum {
+ MODEL_CINTIQ = 0x504C, /* PL */
+ MODEL_CINTIQ2 = 0x4454, /* DT */
+ MODEL_DIGITIZER_II = 0x5544, /* UD */
+ MODEL_GRAPHIRE = 0x4554, /* ET */
+ MODEL_PENPARTNER = 0x4354, /* CT */
+};
+
+static void wacom_handle_model_response(struct wacom *wacom)
+{
+ int major_v, minor_v, r = 0;
+ char *p;
+
+ p = strrchr(wacom->data, 'V');
+ if (p)
+ r = sscanf(p + 1, "%u.%u", &major_v, &minor_v);
+ if (r != 2)
+ major_v = minor_v = 0;
+
+ switch (wacom->data[2] << 8 | wacom->data[3]) {
+ case MODEL_CINTIQ: /* UNTESTED */
+ case MODEL_CINTIQ2:
+ if ((wacom->data[2] << 8 | wacom->data[3]) == MODEL_CINTIQ) {
+ wacom->dev->name = "Wacom Cintiq";
+ wacom->dev->id.version = MODEL_CINTIQ;
+ } else {
+ wacom->dev->name = "Wacom Cintiq II";
+ wacom->dev->id.version = MODEL_CINTIQ2;
+ }
+ wacom->res_x = 508;
+ wacom->res_y = 508;
+
+ switch (wacom->data[5] << 8 | wacom->data[6]) {
+ case 0x3731: /* PL-710 */
+ wacom->res_x = 2540;
+ wacom->res_y = 2540;
+ /* fall through */
+ case 0x3535: /* PL-550 */
+ case 0x3830: /* PL-800 */
+ wacom->extra_z_bits = 2;
+ }
+
+ wacom->flags = F_COVERS_SCREEN;
+ break;
+
+ case MODEL_PENPARTNER:
+ wacom->dev->name = "Wacom Penpartner";
+ wacom->dev->id.version = MODEL_PENPARTNER;
+ wacom->res_x = 1000;
+ wacom->res_y = 1000;
+ break;
+
+ case MODEL_GRAPHIRE:
+ wacom->dev->name = "Wacom Graphire";
+ wacom->dev->id.version = MODEL_GRAPHIRE;
+ wacom->res_x = 1016;
+ wacom->res_y = 1016;
+ wacom->max_x = 5103;
+ wacom->max_y = 3711;
+ wacom->extra_z_bits = 2;
+ wacom->eraser_mask = 0x08;
+ wacom->flags = F_HAS_STYLUS2 | F_HAS_SCROLLWHEEL;
+ break;
+
+ case MODEL_DIGITIZER_II:
+ wacom->dev->name = "Wacom Digitizer II";
+ wacom->dev->id.version = MODEL_DIGITIZER_II;
+ if (major_v == 1 && minor_v <= 2)
+ wacom->extra_z_bits = 0; /* UNTESTED */
+ break;
+
+ default:
+ dev_err(&wacom->dev->dev, "Unsupported Wacom model %s\n",
+ wacom->data);
+ wacom->result = -ENODEV;
+ return;
+ }
+
+ dev_info(&wacom->dev->dev, "%s tablet, version %u.%u\n",
+ wacom->dev->name, major_v, minor_v);
+}
+
+static void wacom_handle_configuration_response(struct wacom *wacom)
+{
+ int r, skip;
+
+ dev_dbg(&wacom->dev->dev, "Configuration string: %s\n", wacom->data);
+ r = sscanf(wacom->data, "~R%x,%u,%u,%u,%u", &skip, &skip, &skip,
+ &wacom->res_x, &wacom->res_y);
+ if (r != 5)
+ dev_warn(&wacom->dev->dev, "could not get resolution\n");
+}
+
+static void wacom_handle_coordinates_response(struct wacom *wacom)
+{
+ int r;
+
+ dev_dbg(&wacom->dev->dev, "Coordinates string: %s\n", wacom->data);
+ r = sscanf(wacom->data, "~C%u,%u", &wacom->max_x, &wacom->max_y);
+ if (r != 2)
+ dev_warn(&wacom->dev->dev, "could not get max coordinates\n");
+}
+
+static void wacom_handle_response(struct wacom *wacom)
+{
+ if (wacom->data[0] != '~' || wacom->data[1] != wacom->expect) {
+ dev_err(&wacom->dev->dev,
+ "Wacom got an unexpected response: %s\n", wacom->data);
+ wacom->result = -EIO;
+ } else {
+ wacom->result = 0;
+
+ switch (wacom->data[1]) {
+ case '#':
+ wacom_handle_model_response(wacom);
+ break;
+ case 'R':
+ wacom_handle_configuration_response(wacom);
+ break;
+ case 'C':
+ wacom_handle_coordinates_response(wacom);
+ break;
+ }
+ }
+
+ complete(&wacom->cmd_done);
+}
+
+static void wacom_handle_packet(struct wacom *wacom)
+{
+ u8 in_proximity_p, stylus_p, button;
+ unsigned int tool;
+ int x, y, z;
+
+ in_proximity_p = wacom->data[0] & 0x40;
+ stylus_p = wacom->data[0] & 0x20;
+ button = (wacom->data[3] & 0x78) >> 3;
+ x = (wacom->data[0] & 3) << 14 | wacom->data[1]<<7 | wacom->data[2];
+ y = (wacom->data[3] & 3) << 14 | wacom->data[4]<<7 | wacom->data[5];
+
+ if (in_proximity_p && stylus_p) {
+ z = wacom->data[6] & 0x7f;
+ if (wacom->extra_z_bits >= 1)
+ z = z << 1 | (wacom->data[3] & 0x4) >> 2;
+ if (wacom->extra_z_bits > 1)
+ z = z << 1 | (wacom->data[0] & 0x4) >> 2;
+ z = z ^ (0x40 << wacom->extra_z_bits);
+ } else {
+ z = -1;
+ }
+
+ if (stylus_p)
+ tool = (button & wacom->eraser_mask) ? ERASER : STYLUS;
+ else
+ tool = CURSOR;
+
+ if (tool != wacom->tool && wacom->tool != 0) {
+ input_report_key(wacom->dev, tools[wacom->tool].input_id, 0);
+ input_sync(wacom->dev);
+ }
+ wacom->tool = tool;
+
+ input_report_key(wacom->dev, tools[tool].input_id, in_proximity_p);
+ input_report_abs(wacom->dev, ABS_MISC,
+ in_proximity_p ? tools[tool].device_id : 0);
+ input_report_abs(wacom->dev, ABS_X, x);
+ input_report_abs(wacom->dev, ABS_Y, y);
+ input_report_abs(wacom->dev, ABS_PRESSURE, z);
+ if (stylus_p) {
+ input_report_key(wacom->dev, BTN_TOUCH, button & 1);
+ input_report_key(wacom->dev, BTN_STYLUS, button & 2);
+ input_report_key(wacom->dev, BTN_STYLUS2, button & 4);
+ } else {
+ input_report_key(wacom->dev, BTN_LEFT, button & 1);
+ input_report_key(wacom->dev, BTN_RIGHT, button & 2);
+ input_report_key(wacom->dev, BTN_MIDDLE, button & 4);
+ /* handle relative wheel for non-stylus device */
+ z = (wacom->data[6] & 0x30) >> 4;
+ if (wacom->data[6] & 0x40)
+ z = -z;
+ input_report_rel(wacom->dev, REL_WHEEL, z);
+ }
+ input_sync(wacom->dev);
+}
+
+static void wacom_clear_data_buf(struct wacom *wacom)
+{
+ memset(wacom->data, 0, DATA_SIZE);
+ wacom->idx = 0;
+}
+
+static irqreturn_t wacom_interrupt(struct serio *serio, unsigned char data,
+ unsigned int flags)
+{
+ struct wacom *wacom = serio_get_drvdata(serio);
+
+ if (data & 0x80)
+ wacom->idx = 0;
+
+ /*
+ * We're either expecting a carriage return-terminated ASCII
+ * response string, or a seven-byte packet with the MSB set on
+ * the first byte.
+ *
+ * Note however that some tablets (the PenPartner, for
+ * example) don't send a carriage return at the end of a
+ * command. We handle these by waiting for timeout.
+ */
+ if (data == '\r' && !(wacom->data[0] & 0x80)) {
+ wacom_handle_response(wacom);
+ wacom_clear_data_buf(wacom);
+ return IRQ_HANDLED;
+ }
+
+ /* Leave place for 0 termination */
+ if (wacom->idx > (DATA_SIZE - 2)) {
+ dev_dbg(&wacom->dev->dev,
+ "throwing away %d bytes of garbage\n", wacom->idx);
+ wacom_clear_data_buf(wacom);
+ }
+ wacom->data[wacom->idx++] = data;
+
+ if (wacom->idx == PACKET_LENGTH && (wacom->data[0] & 0x80)) {
+ wacom_handle_packet(wacom);
+ wacom_clear_data_buf(wacom);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void wacom_disconnect(struct serio *serio)
+{
+ struct wacom *wacom = serio_get_drvdata(serio);
+
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ input_unregister_device(wacom->dev);
+ kfree(wacom);
+}
+
+static int wacom_send(struct serio *serio, const u8 *command)
+{
+ int err = 0;
+
+ for (; !err && *command; command++)
+ err = serio_write(serio, *command);
+
+ return err;
+}
+
+static int wacom_send_setup_string(struct wacom *wacom, struct serio *serio)
+{
+ const u8 *cmd;
+
+ switch (wacom->dev->id.version) {
+ case MODEL_CINTIQ: /* UNTESTED */
+ cmd = COMMAND_ORIGIN_IN_UPPER_LEFT
+ COMMAND_TRANSMIT_AT_MAX_RATE
+ COMMAND_ENABLE_CONTINUOUS_MODE
+ COMMAND_START_SENDING_PACKETS;
+ break;
+
+ case MODEL_PENPARTNER:
+ cmd = COMMAND_ENABLE_PRESSURE_MODE
+ COMMAND_START_SENDING_PACKETS;
+ break;
+
+ default:
+ cmd = COMMAND_MULTI_MODE_INPUT
+ COMMAND_ORIGIN_IN_UPPER_LEFT
+ COMMAND_ENABLE_ALL_MACRO_BUTTONS
+ COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS
+ COMMAND_TRANSMIT_AT_MAX_RATE
+ COMMAND_DISABLE_INCREMENTAL_MODE
+ COMMAND_ENABLE_CONTINUOUS_MODE
+ COMMAND_Z_FILTER
+ COMMAND_START_SENDING_PACKETS;
+ break;
+ }
+
+ return wacom_send(serio, cmd);
+}
+
+static int wacom_send_and_wait(struct wacom *wacom, struct serio *serio,
+ const u8 *cmd, const char *desc)
+{
+ int err;
+ unsigned long u;
+
+ wacom->expect = cmd[1];
+ init_completion(&wacom->cmd_done);
+
+ err = wacom_send(serio, cmd);
+ if (err)
+ return err;
+
+ u = wait_for_completion_timeout(&wacom->cmd_done, HZ);
+ if (u == 0) {
+ /* Timeout, process what we've received. */
+ wacom_handle_response(wacom);
+ }
+
+ wacom->expect = 0;
+ return wacom->result;
+}
+
+static int wacom_setup(struct wacom *wacom, struct serio *serio)
+{
+ int err;
+
+ /* Note that setting the link speed is the job of inputattach.
+ * We assume that reset negotiation has already happened,
+ * here. */
+ err = wacom_send_and_wait(wacom, serio, REQUEST_MODEL_AND_ROM_VERSION,
+ "model and version");
+ if (err)
+ return err;
+
+ if (!(wacom->res_x && wacom->res_y)) {
+ err = wacom_send_and_wait(wacom, serio,
+ REQUEST_CONFIGURATION_STRING,
+ "configuration string");
+ if (err)
+ return err;
+ }
+
+ if (!(wacom->max_x && wacom->max_y)) {
+ err = wacom_send_and_wait(wacom, serio,
+ REQUEST_MAX_COORDINATES,
+ "coordinates string");
+ if (err)
+ return err;
+ }
+
+ return wacom_send_setup_string(wacom, serio);
+}
+
+static int wacom_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct wacom *wacom;
+ struct input_dev *input_dev;
+ int err = -ENOMEM;
+
+ wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!wacom || !input_dev)
+ goto free_device;
+
+ wacom->dev = input_dev;
+ wacom->extra_z_bits = 1;
+ wacom->eraser_mask = 0x04;
+ wacom->tool = wacom->idx = 0;
+ snprintf(wacom->phys, sizeof(wacom->phys), "%s/input0", serio->phys);
+ input_dev->phys = wacom->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_WACOM_IV;
+ input_dev->id.product = serio->id.extra;
+ input_dev->dev.parent = &serio->dev;
+
+ input_dev->evbit[0] =
+ BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_REL);
+ set_bit(ABS_MISC, input_dev->absbit);
+ set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_STYLUS, input_dev->keybit);
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+ set_bit(BTN_MIDDLE, input_dev->keybit);
+
+ serio_set_drvdata(serio, wacom);
+
+ err = serio_open(serio, drv);
+ if (err)
+ goto free_device;
+
+ err = wacom_setup(wacom, serio);
+ if (err)
+ goto close_serio;
+
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+ if (!(wacom->flags & F_COVERS_SCREEN))
+ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+ if (wacom->flags & F_HAS_STYLUS2)
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ if (wacom->flags & F_HAS_SCROLLWHEEL)
+ __set_bit(REL_WHEEL, input_dev->relbit);
+
+ input_abs_set_res(wacom->dev, ABS_X, wacom->res_x);
+ input_abs_set_res(wacom->dev, ABS_Y, wacom->res_y);
+ input_set_abs_params(wacom->dev, ABS_X, 0, wacom->max_x, 0, 0);
+ input_set_abs_params(wacom->dev, ABS_Y, 0, wacom->max_y, 0, 0);
+ input_set_abs_params(wacom->dev, ABS_PRESSURE, -1,
+ (1 << (7 + wacom->extra_z_bits)) - 1, 0, 0);
+
+ err = input_register_device(wacom->dev);
+ if (err)
+ goto close_serio;
+
+ return 0;
+
+close_serio:
+ serio_close(serio);
+free_device:
+ serio_set_drvdata(serio, NULL);
+ input_free_device(input_dev);
+ kfree(wacom);
+ return err;
+}
+
+static struct serio_device_id wacom_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_WACOM_IV,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, wacom_serio_ids);
+
+static struct serio_driver wacom_drv = {
+ .driver = {
+ .name = "wacom_serial4",
+ },
+ .description = "Wacom protocol 4 serial tablet driver",
+ .id_table = wacom_serio_ids,
+ .interrupt = wacom_interrupt,
+ .connect = wacom_connect,
+ .disconnect = wacom_disconnect,
+};
+
+module_serio_driver(wacom_drv);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a23a94bb4bcb..6bb9a7dd23b6 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -471,6 +471,18 @@ config TOUCHSCREEN_HP7XX
To compile this driver as a module, choose M here: the
module will be called jornada720_ts.
+config TOUCHSCREEN_IPAQ_MICRO
+ tristate "HP iPAQ Atmel Micro ASIC touchscreen"
+ depends on MFD_IPAQ_MICRO
+ help
+ Say Y here to enable support for the touchscreen attached to
+ the Atmel Micro peripheral controller on iPAQ h3100/h3600/h3700
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ipaq-micro-ts.
+
config TOUCHSCREEN_HTCPEN
tristate "HTC Shift X9500 touchscreen"
depends on ISA
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 126479d8c29a..4be94fce41af 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO) += ipaq-micro-ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index da201b8e37dc..e57ba52bf484 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1302,8 +1302,10 @@ static int ads7846_probe(struct spi_device *spi)
pdata = dev_get_platdata(&spi->dev);
if (!pdata) {
pdata = ads7846_probe_dt(&spi->dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
+ if (IS_ERR(pdata)) {
+ err = PTR_ERR(pdata);
+ goto err_free_mem;
+ }
}
ts->model = pdata->model ? : 7846;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 6e0b4a2120d3..db178ed2b47e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2,6 +2,7 @@
* Atmel maXTouch Touchscreen driver
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Copyright (C) 2011-2014 Atmel Corporation
* Copyright (C) 2012 Google, Inc.
*
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
@@ -22,6 +23,7 @@
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <linux/slab.h>
/* Version */
@@ -29,8 +31,10 @@
#define MXT_VER_21 21
#define MXT_VER_22 22
-/* Firmware */
+/* Firmware files */
#define MXT_FW_NAME "maxtouch.fw"
+#define MXT_CFG_NAME "maxtouch.cfg"
+#define MXT_CFG_MAGIC "OBP_RAW V1"
/* Registers */
#define MXT_INFO 0x00
@@ -44,6 +48,8 @@
#define MXT_OBJECT_START 0x07
#define MXT_OBJECT_SIZE 6
+#define MXT_INFO_CHECKSUM_SIZE 3
+#define MXT_MAX_BLOCK_WRITE 256
/* Object types */
#define MXT_DEBUG_DIAGNOSTIC_T37 37
@@ -74,6 +80,9 @@
#define MXT_SPT_MESSAGECOUNT_T44 44
#define MXT_SPT_CTECONFIG_T46 46
+/* MXT_GEN_MESSAGE_T5 object */
+#define MXT_RPTID_NOMSG 0xff
+
/* MXT_GEN_COMMAND_T6 field */
#define MXT_COMMAND_RESET 0
#define MXT_COMMAND_BACKUPNV 1
@@ -83,11 +92,20 @@
/* Define for T6 status byte */
#define MXT_T6_STATUS_RESET (1 << 7)
+#define MXT_T6_STATUS_OFL (1 << 6)
+#define MXT_T6_STATUS_SIGERR (1 << 5)
+#define MXT_T6_STATUS_CAL (1 << 4)
+#define MXT_T6_STATUS_CFGERR (1 << 3)
+#define MXT_T6_STATUS_COMSERR (1 << 2)
/* MXT_GEN_POWER_T7 field */
-#define MXT_POWER_IDLEACQINT 0
-#define MXT_POWER_ACTVACQINT 1
-#define MXT_POWER_ACTV2IDLETO 2
+struct t7_config {
+ u8 idle;
+ u8 active;
+} __packed;
+
+#define MXT_POWER_CFG_RUN 0
+#define MXT_POWER_CFG_DEEPSLEEP 1
/* MXT_GEN_ACQUIRE_T8 field */
#define MXT_ACQUIRE_CHRGTIME 0
@@ -99,7 +117,6 @@
#define MXT_ACQUIRE_ATCHCALSTHR 7
/* MXT_TOUCH_MULTI_T9 field */
-#define MXT_TOUCH_CTRL 0
#define MXT_T9_ORIENT 9
#define MXT_T9_RANGE 18
@@ -217,11 +234,6 @@ struct mxt_object {
u8 num_report_ids;
} __packed;
-struct mxt_message {
- u8 reportid;
- u8 message[7];
-};
-
/* Each client has this additional data */
struct mxt_data {
struct i2c_client *client;
@@ -234,15 +246,28 @@ struct mxt_data {
unsigned int max_x;
unsigned int max_y;
bool in_bootloader;
+ u16 mem_size;
+ u8 max_reportid;
u32 config_crc;
+ u32 info_crc;
u8 bootloader_addr;
+ u8 *msg_buf;
+ u8 t6_status;
+ bool update_input;
+ u8 last_message_count;
+ u8 num_touchids;
+ struct t7_config t7_cfg;
/* Cached parameters from object table */
+ u16 T5_address;
+ u8 T5_msg_size;
u8 T6_reportid;
u16 T6_address;
+ u16 T7_address;
u8 T9_reportid_min;
u8 T9_reportid_max;
u8 T19_reportid;
+ u16 T44_address;
/* for fw update in bootloader */
struct completion bl_completion;
@@ -297,42 +322,10 @@ static bool mxt_object_readable(unsigned int type)
}
}
-static bool mxt_object_writable(unsigned int type)
-{
- switch (type) {
- case MXT_GEN_COMMAND_T6:
- case MXT_GEN_POWER_T7:
- case MXT_GEN_ACQUIRE_T8:
- case MXT_TOUCH_MULTI_T9:
- case MXT_TOUCH_KEYARRAY_T15:
- case MXT_TOUCH_PROXIMITY_T23:
- case MXT_TOUCH_PROXKEY_T52:
- case MXT_PROCI_GRIPFACE_T20:
- case MXT_PROCG_NOISE_T22:
- case MXT_PROCI_ONETOUCH_T24:
- case MXT_PROCI_TWOTOUCH_T27:
- case MXT_PROCI_GRIP_T40:
- case MXT_PROCI_PALM_T41:
- case MXT_PROCI_TOUCHSUPPRESSION_T42:
- case MXT_PROCI_STYLUS_T47:
- case MXT_PROCG_NOISESUPPRESSION_T48:
- case MXT_SPT_COMMSCONFIG_T18:
- case MXT_SPT_GPIOPWM_T19:
- case MXT_SPT_SELFTEST_T25:
- case MXT_SPT_CTECONFIG_T28:
- case MXT_SPT_DIGITIZER_T43:
- case MXT_SPT_CTECONFIG_T46:
- return true;
- default:
- return false;
- }
-}
-
-static void mxt_dump_message(struct device *dev,
- struct mxt_message *message)
+static void mxt_dump_message(struct mxt_data *data, u8 *message)
{
- dev_dbg(dev, "reportid: %u\tmessage: %*ph\n",
- message->reportid, 7, message->message);
+ dev_dbg(&data->client->dev, "message: %*ph\n",
+ data->T5_msg_size, message);
}
static int mxt_wait_for_completion(struct mxt_data *data,
@@ -366,7 +359,6 @@ static int mxt_bootloader_read(struct mxt_data *data,
msg.buf = val;
ret = i2c_transfer(data->client->adapter, &msg, 1);
-
if (ret == 1) {
ret = 0;
} else {
@@ -401,7 +393,7 @@ static int mxt_bootloader_write(struct mxt_data *data,
return ret;
}
-static int mxt_lookup_bootloader_address(struct mxt_data *data)
+static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
{
u8 appmode = data->client->addr;
u8 bootloader;
@@ -409,12 +401,19 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data)
switch (appmode) {
case 0x4a:
case 0x4b:
+ /* Chips after 1664S use different scheme */
+ if (retry || data->info.family_id >= 0xa2) {
+ bootloader = appmode - 0x24;
+ break;
+ }
+ /* Fall through for normal case */
case 0x4c:
case 0x4d:
case 0x5a:
case 0x5b:
bootloader = appmode - 0x26;
break;
+
default:
dev_err(&data->client->dev,
"Appmode i2c address 0x%02x not found\n",
@@ -426,6 +425,30 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data)
return 0;
}
+static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+ u8 val;
+ bool crc_failure;
+
+ error = mxt_lookup_bootloader_address(data, alt_address);
+ if (error)
+ return error;
+
+ error = mxt_bootloader_read(data, &val, 1);
+ if (error)
+ return error;
+
+ /* Check app crc fail mode */
+ crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL;
+
+ dev_err(dev, "Detected bootloader, status:%02X%s\n",
+ val, crc_failure ? ", APP_CRC_FAIL" : "");
+
+ return 0;
+}
+
static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
{
struct device *dev = &data->client->dev;
@@ -447,14 +470,15 @@ static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
}
}
-static int mxt_check_bootloader(struct mxt_data *data, unsigned int state)
+static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
+ bool wait)
{
struct device *dev = &data->client->dev;
u8 val;
int ret;
recheck:
- if (state != MXT_WAITING_BOOTLOAD_CMD) {
+ if (wait) {
/*
* In application update mode, the interrupt
* line signals state transitions. We must wait for the
@@ -485,6 +509,7 @@ recheck:
switch (state) {
case MXT_WAITING_BOOTLOAD_CMD:
case MXT_WAITING_FRAME_DATA:
+ case MXT_APP_CRC_FAIL:
val &= ~MXT_BOOT_STATUS_MASK;
break;
case MXT_FRAME_CRC_PASS:
@@ -508,13 +533,18 @@ recheck:
return 0;
}
-static int mxt_unlock_bootloader(struct mxt_data *data)
+static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
{
int ret;
u8 buf[2];
- buf[0] = MXT_UNLOCK_CMD_LSB;
- buf[1] = MXT_UNLOCK_CMD_MSB;
+ if (unlock) {
+ buf[0] = MXT_UNLOCK_CMD_LSB;
+ buf[1] = MXT_UNLOCK_CMD_MSB;
+ } else {
+ buf[0] = 0x01;
+ buf[1] = 0x01;
+ }
ret = mxt_bootloader_write(data, buf, 2);
if (ret)
@@ -605,40 +635,44 @@ mxt_get_object(struct mxt_data *data, u8 type)
return object;
}
- dev_err(&data->client->dev, "Invalid object type T%u\n", type);
+ dev_warn(&data->client->dev, "Invalid object type T%u\n", type);
return NULL;
}
-static int mxt_read_message(struct mxt_data *data,
- struct mxt_message *message)
+static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
{
- struct mxt_object *object;
- u16 reg;
-
- object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
- if (!object)
- return -EINVAL;
+ struct device *dev = &data->client->dev;
+ u8 status = msg[1];
+ u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
- reg = object->start_address;
- return __mxt_read_reg(data->client, reg,
- sizeof(struct mxt_message), message);
-}
+ complete(&data->crc_completion);
-static int mxt_write_object(struct mxt_data *data,
- u8 type, u8 offset, u8 val)
-{
- struct mxt_object *object;
- u16 reg;
-
- object = mxt_get_object(data, type);
- if (!object || offset >= mxt_obj_size(object))
- return -EINVAL;
+ if (crc != data->config_crc) {
+ data->config_crc = crc;
+ dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
+ }
- reg = object->start_address;
- return mxt_write_reg(data->client, reg + offset, val);
+ /* Detect reset */
+ if (status & MXT_T6_STATUS_RESET)
+ complete(&data->reset_completion);
+
+ /* Output debug if status has changed */
+ if (status != data->t6_status)
+ dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n",
+ status,
+ status == 0 ? " OK" : "",
+ status & MXT_T6_STATUS_RESET ? " RESET" : "",
+ status & MXT_T6_STATUS_OFL ? " OFL" : "",
+ status & MXT_T6_STATUS_SIGERR ? " SIGERR" : "",
+ status & MXT_T6_STATUS_CAL ? " CAL" : "",
+ status & MXT_T6_STATUS_CFGERR ? " CFGERR" : "",
+ status & MXT_T6_STATUS_COMSERR ? " COMSERR" : "");
+
+ /* Save current status */
+ data->t6_status = status;
}
-static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
+static void mxt_input_button(struct mxt_data *data, u8 *message)
{
struct input_dev *input = data->input_dev;
const struct mxt_platform_data *pdata = data->pdata;
@@ -649,30 +683,33 @@ static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
for (i = 0; i < pdata->t19_num_keys; i++) {
if (pdata->t19_keymap[i] == KEY_RESERVED)
continue;
- button = !(message->message[0] & (1 << i));
+ button = !(message[1] & (1 << i));
input_report_key(input, pdata->t19_keymap[i], button);
}
}
-static void mxt_input_sync(struct input_dev *input_dev)
+static void mxt_input_sync(struct mxt_data *data)
{
- input_mt_report_pointer_emulation(input_dev, false);
- input_sync(input_dev);
+ input_mt_report_pointer_emulation(data->input_dev,
+ data->pdata->t19_num_keys);
+ input_sync(data->input_dev);
}
-static void mxt_input_touchevent(struct mxt_data *data,
- struct mxt_message *message, int id)
+static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
{
struct device *dev = &data->client->dev;
- u8 status = message->message[0];
struct input_dev *input_dev = data->input_dev;
+ int id;
+ u8 status;
int x;
int y;
int area;
int amplitude;
- x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
- y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+ id = message[0] - data->T9_reportid_min;
+ status = message[1];
+ x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
+ y = (message[3] << 4) | ((message[4] & 0xf));
/* Handle 10/12 bit switching */
if (data->max_x < 1024)
@@ -680,8 +717,8 @@ static void mxt_input_touchevent(struct mxt_data *data,
if (data->max_y < 1024)
y >>= 2;
- area = message->message[4];
- amplitude = message->message[5];
+ area = message[5];
+ amplitude = message[6];
dev_dbg(dev,
"[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
@@ -707,7 +744,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
if (status & MXT_T9_RELEASE) {
input_mt_report_slot_state(input_dev,
MT_TOOL_FINGER, 0);
- mxt_input_sync(input_dev);
+ mxt_input_sync(data);
}
/* Touch active */
@@ -720,64 +757,179 @@ static void mxt_input_touchevent(struct mxt_data *data,
/* Touch no longer active, close out slot */
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
}
+
+ data->update_input = true;
}
-static u16 mxt_extract_T6_csum(const u8 *csum)
+static int mxt_proc_message(struct mxt_data *data, u8 *message)
{
- return csum[0] | (csum[1] << 8) | (csum[2] << 16);
+ u8 report_id = message[0];
+
+ if (report_id == MXT_RPTID_NOMSG)
+ return 0;
+
+ if (report_id == data->T6_reportid) {
+ mxt_proc_t6_messages(data, message);
+ } else if (!data->input_dev) {
+ /*
+ * Do not report events if input device
+ * is not yet registered.
+ */
+ mxt_dump_message(data, message);
+ } else if (report_id >= data->T9_reportid_min
+ && report_id <= data->T9_reportid_max) {
+ mxt_proc_t9_message(data, message);
+ } else if (report_id == data->T19_reportid) {
+ mxt_input_button(data, message);
+ data->update_input = true;
+ } else {
+ mxt_dump_message(data, message);
+ }
+
+ return 1;
}
-static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+static int mxt_read_and_process_messages(struct mxt_data *data, u8 count)
{
- u8 id = msg->reportid;
- return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
+ struct device *dev = &data->client->dev;
+ int ret;
+ int i;
+ u8 num_valid = 0;
+
+ /* Safety check for msg_buf */
+ if (count > data->max_reportid)
+ return -EINVAL;
+
+ /* Process remaining messages if necessary */
+ ret = __mxt_read_reg(data->client, data->T5_address,
+ data->T5_msg_size * count, data->msg_buf);
+ if (ret) {
+ dev_err(dev, "Failed to read %u messages (%d)\n", count, ret);
+ return ret;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = mxt_proc_message(data,
+ data->msg_buf + data->T5_msg_size * i);
+
+ if (ret == 1)
+ num_valid++;
+ }
+
+ /* return number of messages read */
+ return num_valid;
}
-static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
+static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
{
- struct mxt_message message;
- const u8 *payload = &message.message[0];
struct device *dev = &data->client->dev;
- u8 reportid;
- bool update_input = false;
- u32 crc;
+ int ret;
+ u8 count, num_left;
+ /* Read T44 and T5 together */
+ ret = __mxt_read_reg(data->client, data->T44_address,
+ data->T5_msg_size + 1, data->msg_buf);
+ if (ret) {
+ dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret);
+ return IRQ_NONE;
+ }
+
+ count = data->msg_buf[0];
+
+ if (count == 0) {
+ dev_warn(dev, "Interrupt triggered but zero messages\n");
+ return IRQ_NONE;
+ } else if (count > data->max_reportid) {
+ dev_err(dev, "T44 count %d exceeded max report id\n", count);
+ count = data->max_reportid;
+ }
+
+ /* Process first message */
+ ret = mxt_proc_message(data, data->msg_buf + 1);
+ if (ret < 0) {
+ dev_warn(dev, "Unexpected invalid message\n");
+ return IRQ_NONE;
+ }
+
+ num_left = count - 1;
+
+ /* Process remaining messages if necessary */
+ if (num_left) {
+ ret = mxt_read_and_process_messages(data, num_left);
+ if (ret < 0)
+ goto end;
+ else if (ret != num_left)
+ dev_warn(dev, "Unexpected invalid message\n");
+ }
+
+end:
+ if (data->update_input) {
+ mxt_input_sync(data);
+ data->update_input = false;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mxt_process_messages_until_invalid(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int count, read;
+ u8 tries = 2;
+
+ count = data->max_reportid;
+
+ /* Read messages until we force an invalid */
do {
- if (mxt_read_message(data, &message)) {
- dev_err(dev, "Failed to read message\n");
- return IRQ_NONE;
- }
+ read = mxt_read_and_process_messages(data, count);
+ if (read < count)
+ return 0;
+ } while (--tries);
- reportid = message.reportid;
+ if (data->update_input) {
+ mxt_input_sync(data);
+ data->update_input = false;
+ }
- if (reportid == data->T6_reportid) {
- u8 status = payload[0];
+ dev_err(dev, "CHG pin isn't cleared\n");
+ return -EBUSY;
+}
- crc = mxt_extract_T6_csum(&payload[1]);
- if (crc != data->config_crc) {
- data->config_crc = crc;
- complete(&data->crc_completion);
- }
+static irqreturn_t mxt_process_messages(struct mxt_data *data)
+{
+ int total_handled, num_handled;
+ u8 count = data->last_message_count;
- dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
- status, data->config_crc);
-
- if (status & MXT_T6_STATUS_RESET)
- complete(&data->reset_completion);
- } else if (mxt_is_T9_message(data, &message)) {
- int id = reportid - data->T9_reportid_min;
- mxt_input_touchevent(data, &message, id);
- update_input = true;
- } else if (message.reportid == data->T19_reportid) {
- mxt_input_button(data, &message);
- update_input = true;
- } else {
- mxt_dump_message(dev, &message);
- }
- } while (reportid != 0xff);
+ if (count < 1 || count > data->max_reportid)
+ count = 1;
+
+ /* include final invalid message */
+ total_handled = mxt_read_and_process_messages(data, count + 1);
+ if (total_handled < 0)
+ return IRQ_NONE;
+ /* if there were invalid messages, then we are done */
+ else if (total_handled <= count)
+ goto update_count;
+
+ /* keep reading two msgs until one is invalid or reportid limit */
+ do {
+ num_handled = mxt_read_and_process_messages(data, 2);
+ if (num_handled < 0)
+ return IRQ_NONE;
- if (update_input)
- mxt_input_sync(data->input_dev);
+ total_handled += num_handled;
+
+ if (num_handled < 2)
+ break;
+ } while (total_handled < data->num_touchids);
+
+update_count:
+ data->last_message_count = total_handled;
+
+ if (data->update_input) {
+ mxt_input_sync(data);
+ data->update_input = false;
+ }
return IRQ_HANDLED;
}
@@ -792,7 +944,14 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- return mxt_process_messages_until_invalid(data);
+ if (!data->object_table)
+ return IRQ_HANDLED;
+
+ if (data->T44_address) {
+ return mxt_process_messages_t44(data);
+ } else {
+ return mxt_process_messages(data);
+ }
}
static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
@@ -866,78 +1025,337 @@ static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
}
-static int mxt_check_reg_init(struct mxt_data *data)
+static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
+{
+ static const unsigned int crcpoly = 0x80001B;
+ u32 result;
+ u32 data_word;
+
+ data_word = (secondbyte << 8) | firstbyte;
+ result = ((*crc << 1) ^ data_word);
+
+ if (result & 0x1000000)
+ result ^= crcpoly;
+
+ *crc = result;
+}
+
+static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
+{
+ u32 crc = 0;
+ u8 *ptr = base + start_off;
+ u8 *last_val = base + end_off - 1;
+
+ if (end_off < start_off)
+ return -EINVAL;
+
+ while (ptr < last_val) {
+ mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
+ ptr += 2;
+ }
+
+ /* if len is odd, fill the last byte with 0 */
+ if (ptr == last_val)
+ mxt_calc_crc24(&crc, *ptr, 0);
+
+ /* Mask to 24-bit */
+ crc &= 0x00FFFFFF;
+
+ return crc;
+}
+
+static int mxt_prepare_cfg_mem(struct mxt_data *data,
+ const struct firmware *cfg,
+ unsigned int data_pos,
+ unsigned int cfg_start_ofs,
+ u8 *config_mem,
+ size_t config_mem_size)
{
- const struct mxt_platform_data *pdata = data->pdata;
- struct mxt_object *object;
struct device *dev = &data->client->dev;
- int index = 0;
- int i, size;
+ struct mxt_object *object;
+ unsigned int type, instance, size, byte_offset;
+ int offset;
int ret;
+ int i;
+ u16 reg;
+ u8 val;
- if (!pdata->config) {
- dev_dbg(dev, "No cfg data defined, skipping reg init\n");
- return 0;
+ while (data_pos < cfg->size) {
+ /* Read type, instance, length */
+ ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
+ &type, &instance, &size, &offset);
+ if (ret == 0) {
+ /* EOF */
+ break;
+ } else if (ret != 3) {
+ dev_err(dev, "Bad format: failed to parse object\n");
+ return -EINVAL;
+ }
+ data_pos += offset;
+
+ object = mxt_get_object(data, type);
+ if (!object) {
+ /* Skip object */
+ for (i = 0; i < size; i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ &val, &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format in T%d at %d\n",
+ type, i);
+ return -EINVAL;
+ }
+ data_pos += offset;
+ }
+ continue;
+ }
+
+ if (size > mxt_obj_size(object)) {
+ /*
+ * Either we are in fallback mode due to wrong
+ * config or config from a later fw version,
+ * or the file is corrupt or hand-edited.
+ */
+ dev_warn(dev, "Discarding %zu byte(s) in T%u\n",
+ size - mxt_obj_size(object), type);
+ } else if (mxt_obj_size(object) > size) {
+ /*
+ * If firmware is upgraded, new bytes may be added to
+ * end of objects. It is generally forward compatible
+ * to zero these bytes - previous behaviour will be
+ * retained. However this does invalidate the CRC and
+ * will force fallback mode until the configuration is
+ * updated. We warn here but do nothing else - the
+ * malloc has zeroed the entire configuration.
+ */
+ dev_warn(dev, "Zeroing %zu byte(s) in T%d\n",
+ mxt_obj_size(object) - size, type);
+ }
+
+ if (instance >= mxt_obj_instances(object)) {
+ dev_err(dev, "Object instances exceeded!\n");
+ return -EINVAL;
+ }
+
+ reg = object->start_address + mxt_obj_size(object) * instance;
+
+ for (i = 0; i < size; i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ &val,
+ &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format in T%d at %d\n",
+ type, i);
+ return -EINVAL;
+ }
+ data_pos += offset;
+
+ if (i > mxt_obj_size(object))
+ continue;
+
+ byte_offset = reg + i - cfg_start_ofs;
+
+ if (byte_offset >= 0 && byte_offset < config_mem_size) {
+ *(config_mem + byte_offset) = val;
+ } else {
+ dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
+ reg, object->type, byte_offset);
+ return -EINVAL;
+ }
+ }
}
- mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
+ return 0;
+}
- if (data->config_crc == pdata->config_crc) {
- dev_info(dev, "Config CRC 0x%06X: OK\n", data->config_crc);
- return 0;
+static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start,
+ u8 *config_mem, size_t config_mem_size)
+{
+ unsigned int byte_offset = 0;
+ int error;
+
+ /* Write configuration as blocks */
+ while (byte_offset < config_mem_size) {
+ unsigned int size = config_mem_size - byte_offset;
+
+ if (size > MXT_MAX_BLOCK_WRITE)
+ size = MXT_MAX_BLOCK_WRITE;
+
+ error = __mxt_write_reg(data->client,
+ cfg_start + byte_offset,
+ size, config_mem + byte_offset);
+ if (error) {
+ dev_err(&data->client->dev,
+ "Config write error, ret=%d\n", error);
+ return error;
+ }
+
+ byte_offset += size;
}
- dev_info(dev, "Config CRC 0x%06X: does not match 0x%06X\n",
- data->config_crc, pdata->config_crc);
+ return 0;
+}
- for (i = 0; i < data->info.object_num; i++) {
- object = data->object_table + i;
+/*
+ * mxt_update_cfg - download configuration to chip
+ *
+ * Atmel Raw Config File Format
+ *
+ * The first four lines of the raw config file contain:
+ * 1) Version
+ * 2) Chip ID Information (first 7 bytes of device memory)
+ * 3) Chip Information Block 24-bit CRC Checksum
+ * 4) Chip Configuration 24-bit CRC Checksum
+ *
+ * The rest of the file consists of one line per object instance:
+ * <TYPE> <INSTANCE> <SIZE> <CONTENTS>
+ *
+ * <TYPE> - 2-byte object type as hex
+ * <INSTANCE> - 2-byte object instance number as hex
+ * <SIZE> - 2-byte object size as hex
+ * <CONTENTS> - array of <SIZE> 1-byte hex values
+ */
+static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
+{
+ struct device *dev = &data->client->dev;
+ struct mxt_info cfg_info;
+ int ret;
+ int offset;
+ int data_pos;
+ int i;
+ int cfg_start_ofs;
+ u32 info_crc, config_crc, calculated_crc;
+ u8 *config_mem;
+ size_t config_mem_size;
- if (!mxt_object_writable(object->type))
- continue;
+ mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
- size = mxt_obj_size(object) * mxt_obj_instances(object);
- if (index + size > pdata->config_length) {
- dev_err(dev, "Not enough config data!\n");
+ if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
+ dev_err(dev, "Unrecognised config file\n");
+ return -EINVAL;
+ }
+
+ data_pos = strlen(MXT_CFG_MAGIC);
+
+ /* Load information block and check */
+ for (i = 0; i < sizeof(struct mxt_info); i++) {
+ ret = sscanf(cfg->data + data_pos, "%hhx%n",
+ (unsigned char *)&cfg_info + i,
+ &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format\n");
return -EINVAL;
}
- ret = __mxt_write_reg(data->client, object->start_address,
- size, &pdata->config[index]);
- if (ret)
- return ret;
- index += size;
+ data_pos += offset;
+ }
+
+ if (cfg_info.family_id != data->info.family_id) {
+ dev_err(dev, "Family ID mismatch!\n");
+ return -EINVAL;
+ }
+
+ if (cfg_info.variant_id != data->info.variant_id) {
+ dev_err(dev, "Variant ID mismatch!\n");
+ return -EINVAL;
+ }
+
+ /* Read CRCs */
+ ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format: failed to parse Info CRC\n");
+ return -EINVAL;
+ }
+ data_pos += offset;
+
+ ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
+ if (ret != 1) {
+ dev_err(dev, "Bad format: failed to parse Config CRC\n");
+ return -EINVAL;
+ }
+ data_pos += offset;
+
+ /*
+ * The Info Block CRC is calculated over mxt_info and the object
+ * table. If it does not match then we are trying to load the
+ * configuration from a different chip or firmware version, so
+ * the configuration CRC is invalid anyway.
+ */
+ if (info_crc == data->info_crc) {
+ if (config_crc == 0 || data->config_crc == 0) {
+ dev_info(dev, "CRC zero, attempting to apply config\n");
+ } else if (config_crc == data->config_crc) {
+ dev_dbg(dev, "Config CRC 0x%06X: OK\n",
+ data->config_crc);
+ return 0;
+ } else {
+ dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
+ data->config_crc, config_crc);
+ }
+ } else {
+ dev_warn(dev,
+ "Warning: Info CRC error - device=0x%06X file=0x%06X\n",
+ data->info_crc, info_crc);
+ }
+
+ /* Malloc memory to store configuration */
+ cfg_start_ofs = MXT_OBJECT_START +
+ data->info.object_num * sizeof(struct mxt_object) +
+ MXT_INFO_CHECKSUM_SIZE;
+ config_mem_size = data->mem_size - cfg_start_ofs;
+ config_mem = kzalloc(config_mem_size, GFP_KERNEL);
+ if (!config_mem) {
+ dev_err(dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,
+ config_mem, config_mem_size);
+ if (ret)
+ goto release_mem;
+
+ /* Calculate crc of the received configs (not the raw config file) */
+ if (data->T7_address < cfg_start_ofs) {
+ dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
+ data->T7_address, cfg_start_ofs);
+ ret = 0;
+ goto release_mem;
}
+ calculated_crc = mxt_calculate_crc(config_mem,
+ data->T7_address - cfg_start_ofs,
+ config_mem_size);
+
+ if (config_crc > 0 && config_crc != calculated_crc)
+ dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
+ calculated_crc, config_crc);
+
+ ret = mxt_upload_cfg_mem(data, cfg_start_ofs,
+ config_mem, config_mem_size);
+ if (ret)
+ goto release_mem;
+
mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
ret = mxt_soft_reset(data);
if (ret)
- return ret;
+ goto release_mem;
dev_info(dev, "Config successfully updated\n");
- return 0;
+release_mem:
+ kfree(config_mem);
+ return ret;
}
-static int mxt_make_highchg(struct mxt_data *data)
+static int mxt_acquire_irq(struct mxt_data *data)
{
- struct device *dev = &data->client->dev;
- struct mxt_message message;
- int count = 10;
int error;
- /* Read dummy message to make high CHG pin */
- do {
- error = mxt_read_message(data, &message);
- if (error)
- return error;
- } while (message.reportid != 0xff && --count);
+ enable_irq(data->irq);
- if (!count) {
- dev_err(dev, "CHG pin isn't cleared\n");
- return -EBUSY;
- }
+ error = mxt_process_messages_until_invalid(data);
+ if (error)
+ return error;
return 0;
}
@@ -956,24 +1374,55 @@ static int mxt_get_info(struct mxt_data *data)
return 0;
}
+static void mxt_free_object_table(struct mxt_data *data)
+{
+ input_unregister_device(data->input_dev);
+ data->input_dev = NULL;
+
+ kfree(data->object_table);
+ data->object_table = NULL;
+ kfree(data->msg_buf);
+ data->msg_buf = NULL;
+ data->T5_address = 0;
+ data->T5_msg_size = 0;
+ data->T6_reportid = 0;
+ data->T7_address = 0;
+ data->T9_reportid_min = 0;
+ data->T9_reportid_max = 0;
+ data->T19_reportid = 0;
+ data->T44_address = 0;
+ data->max_reportid = 0;
+}
+
static int mxt_get_object_table(struct mxt_data *data)
{
struct i2c_client *client = data->client;
size_t table_size;
+ struct mxt_object *object_table;
int error;
int i;
u8 reportid;
+ u16 end_address;
table_size = data->info.object_num * sizeof(struct mxt_object);
+ object_table = kzalloc(table_size, GFP_KERNEL);
+ if (!object_table) {
+ dev_err(&data->client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
- data->object_table);
- if (error)
+ object_table);
+ if (error) {
+ kfree(object_table);
return error;
+ }
/* Valid Report IDs start counting from 1 */
reportid = 1;
+ data->mem_size = 0;
for (i = 0; i < data->info.object_num; i++) {
- struct mxt_object *object = data->object_table + i;
+ struct mxt_object *object = object_table + i;
u8 min_id, max_id;
le16_to_cpus(&object->start_address);
@@ -995,31 +1444,74 @@ static int mxt_get_object_table(struct mxt_data *data)
min_id, max_id);
switch (object->type) {
+ case MXT_GEN_MESSAGE_T5:
+ if (data->info.family_id == 0x80 &&
+ data->info.version < 0x20) {
+ /*
+ * On mXT224 firmware versions prior to V2.0
+ * read and discard unused CRC byte otherwise
+ * DMA reads are misaligned.
+ */
+ data->T5_msg_size = mxt_obj_size(object);
+ } else {
+ /* CRC not enabled, so skip last byte */
+ data->T5_msg_size = mxt_obj_size(object) - 1;
+ }
+ data->T5_address = object->start_address;
+ break;
case MXT_GEN_COMMAND_T6:
data->T6_reportid = min_id;
data->T6_address = object->start_address;
break;
+ case MXT_GEN_POWER_T7:
+ data->T7_address = object->start_address;
+ break;
case MXT_TOUCH_MULTI_T9:
data->T9_reportid_min = min_id;
data->T9_reportid_max = max_id;
+ data->num_touchids = object->num_report_ids
+ * mxt_obj_instances(object);
+ break;
+ case MXT_SPT_MESSAGECOUNT_T44:
+ data->T44_address = object->start_address;
break;
case MXT_SPT_GPIOPWM_T19:
data->T19_reportid = min_id;
break;
}
+
+ end_address = object->start_address
+ + mxt_obj_size(object) * mxt_obj_instances(object) - 1;
+
+ if (end_address >= data->mem_size)
+ data->mem_size = end_address + 1;
+ }
+
+ /* Store maximum reportid */
+ data->max_reportid = reportid;
+
+ /* If T44 exists, T5 position has to be directly after */
+ if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
+ dev_err(&client->dev, "Invalid T44 position\n");
+ error = -EINVAL;
+ goto free_object_table;
}
+ data->msg_buf = kcalloc(data->max_reportid,
+ data->T5_msg_size, GFP_KERNEL);
+ if (!data->msg_buf) {
+ dev_err(&client->dev, "Failed to allocate message buffer\n");
+ error = -ENOMEM;
+ goto free_object_table;
+ }
+
+ data->object_table = object_table;
+
return 0;
-}
-static void mxt_free_object_table(struct mxt_data *data)
-{
- kfree(data->object_table);
- data->object_table = NULL;
- data->T6_reportid = 0;
- data->T9_reportid_min = 0;
- data->T9_reportid_max = 0;
- data->T19_reportid = 0;
+free_object_table:
+ mxt_free_object_table(data);
+ return error;
}
static int mxt_read_t9_resolution(struct mxt_data *data)
@@ -1070,55 +1562,259 @@ static int mxt_read_t9_resolution(struct mxt_data *data)
return 0;
}
-static int mxt_initialize(struct mxt_data *data)
+static int mxt_input_open(struct input_dev *dev);
+static void mxt_input_close(struct input_dev *dev);
+
+static int mxt_initialize_t9_input_device(struct mxt_data *data)
{
- struct i2c_client *client = data->client;
- struct mxt_info *info = &data->info;
+ struct device *dev = &data->client->dev;
+ const struct mxt_platform_data *pdata = data->pdata;
+ struct input_dev *input_dev;
int error;
+ unsigned int num_mt_slots;
+ unsigned int mt_flags = 0;
+ int i;
- error = mxt_get_info(data);
+ error = mxt_read_t9_resolution(data);
if (error)
- return error;
+ dev_warn(dev, "Failed to initialize T9 resolution\n");
- data->object_table = kcalloc(info->object_num,
- sizeof(struct mxt_object),
- GFP_KERNEL);
- if (!data->object_table) {
- dev_err(&client->dev, "Failed to allocate memory\n");
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(dev, "Failed to allocate memory\n");
return -ENOMEM;
}
+ input_dev->name = "Atmel maXTouch Touchscreen";
+ input_dev->phys = data->phys;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = dev;
+ input_dev->open = mxt_input_open;
+ input_dev->close = mxt_input_close;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+
+ if (pdata->t19_num_keys) {
+ __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
+
+ for (i = 0; i < pdata->t19_num_keys; i++)
+ if (pdata->t19_keymap[i] != KEY_RESERVED)
+ input_set_capability(input_dev, EV_KEY,
+ pdata->t19_keymap[i]);
+
+ mt_flags |= INPUT_MT_POINTER;
+
+ input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
+ input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
+ input_abs_set_res(input_dev, ABS_MT_POSITION_X,
+ MXT_PIXELS_PER_MM);
+ input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
+ MXT_PIXELS_PER_MM);
+
+ input_dev->name = "Atmel maXTouch Touchpad";
+ }
+
+ /* For single touch */
+ input_set_abs_params(input_dev, ABS_X,
+ 0, data->max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ 0, data->max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE,
+ 0, 255, 0, 0);
+
+ /* For multi touch */
+ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
+ error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
+ if (error) {
+ dev_err(dev, "Error %d initialising slots\n", error);
+ goto err_free_mem;
+ }
+
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MXT_MAX_AREA, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, data->max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, data->max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+ 0, 255, 0, 0);
+
+ input_set_drvdata(input_dev, data);
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(dev, "Error %d registering input device\n", error);
+ goto err_free_mem;
+ }
+
+ data->input_dev = input_dev;
+
+ return 0;
+
+err_free_mem:
+ input_free_device(input_dev);
+ return error;
+}
+
+static int mxt_configure_objects(struct mxt_data *data,
+ const struct firmware *cfg);
+
+static void mxt_config_cb(const struct firmware *cfg, void *ctx)
+{
+ mxt_configure_objects(ctx, cfg);
+ release_firmware(cfg);
+}
+
+static int mxt_initialize(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int recovery_attempts = 0;
+ int error;
+
+ while (1) {
+ error = mxt_get_info(data);
+ if (!error)
+ break;
+
+ /* Check bootloader state */
+ error = mxt_probe_bootloader(data, false);
+ if (error) {
+ dev_info(&client->dev, "Trying alternate bootloader address\n");
+ error = mxt_probe_bootloader(data, true);
+ if (error) {
+ /* Chip is not in appmode or bootloader mode */
+ return error;
+ }
+ }
+
+ /* OK, we are in bootloader, see if we can recover */
+ if (++recovery_attempts > 1) {
+ dev_err(&client->dev, "Could not recover from bootloader mode\n");
+ /*
+ * We can reflash from this state, so do not
+ * abort initialization.
+ */
+ data->in_bootloader = true;
+ return 0;
+ }
+
+ /* Attempt to exit bootloader into app mode */
+ mxt_send_bootloader_cmd(data, false);
+ msleep(MXT_FW_RESET_TIME);
+ }
+
/* Get object table information */
error = mxt_get_object_table(data);
if (error) {
dev_err(&client->dev, "Error %d reading object table\n", error);
- goto err_free_object_table;
+ return error;
}
- /* Check register init values */
- error = mxt_check_reg_init(data);
+ error = mxt_acquire_irq(data);
+ if (error)
+ goto err_free_object_table;
+
+ error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
+ &client->dev, GFP_KERNEL, data,
+ mxt_config_cb);
if (error) {
- dev_err(&client->dev, "Error %d initializing configuration\n",
+ dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
error);
goto err_free_object_table;
}
- error = mxt_read_t9_resolution(data);
+ return 0;
+
+err_free_object_table:
+ mxt_free_object_table(data);
+ return error;
+}
+
+static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+ struct t7_config *new_config;
+ struct t7_config deepsleep = { .active = 0, .idle = 0 };
+
+ if (sleep == MXT_POWER_CFG_DEEPSLEEP)
+ new_config = &deepsleep;
+ else
+ new_config = &data->t7_cfg;
+
+ error = __mxt_write_reg(data->client, data->T7_address,
+ sizeof(data->t7_cfg), new_config);
+ if (error)
+ return error;
+
+ dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n",
+ new_config->active, new_config->idle);
+
+ return 0;
+}
+
+static int mxt_init_t7_power_cfg(struct mxt_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+ bool retry = false;
+
+recheck:
+ error = __mxt_read_reg(data->client, data->T7_address,
+ sizeof(data->t7_cfg), &data->t7_cfg);
+ if (error)
+ return error;
+
+ if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) {
+ if (!retry) {
+ dev_dbg(dev, "T7 cfg zero, resetting\n");
+ mxt_soft_reset(data);
+ retry = true;
+ goto recheck;
+ } else {
+ dev_dbg(dev, "T7 cfg zero after reset, overriding\n");
+ data->t7_cfg.active = 20;
+ data->t7_cfg.idle = 100;
+ return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+ }
+ }
+
+ dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n",
+ data->t7_cfg.active, data->t7_cfg.idle);
+ return 0;
+}
+
+static int mxt_configure_objects(struct mxt_data *data,
+ const struct firmware *cfg)
+{
+ struct device *dev = &data->client->dev;
+ struct mxt_info *info = &data->info;
+ int error;
+
+ if (cfg) {
+ error = mxt_update_cfg(data, cfg);
+ if (error)
+ dev_warn(dev, "Error %d updating config\n", error);
+ }
+
+ error = mxt_init_t7_power_cfg(data);
if (error) {
- dev_err(&client->dev, "Failed to initialize T9 resolution\n");
- goto err_free_object_table;
+ dev_err(dev, "Failed to initialize power cfg\n");
+ return error;
}
- dev_info(&client->dev,
+ error = mxt_initialize_t9_input_device(data);
+ if (error)
+ return error;
+
+ dev_info(dev,
"Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
info->family_id, info->variant_id, info->version >> 4,
info->version & 0xf, info->build, info->object_num);
return 0;
-
-err_free_object_table:
- mxt_free_object_table(data);
- return error;
}
/* Firmware Version is returned as Major.Minor.Build */
@@ -1246,30 +1942,45 @@ static int mxt_load_fw(struct device *dev, const char *fn)
if (ret)
goto release_firmware;
- ret = mxt_lookup_bootloader_address(data);
- if (ret)
- goto release_firmware;
+ if (!data->in_bootloader) {
+ /* Change to the bootloader mode */
+ data->in_bootloader = true;
- /* Change to the bootloader mode */
- data->in_bootloader = true;
+ ret = mxt_t6_command(data, MXT_COMMAND_RESET,
+ MXT_BOOT_VALUE, false);
+ if (ret)
+ goto release_firmware;
- ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_BOOT_VALUE, false);
- if (ret)
- goto release_firmware;
+ msleep(MXT_RESET_TIME);
- msleep(MXT_RESET_TIME);
+ /* Do not need to scan since we know family ID */
+ ret = mxt_lookup_bootloader_address(data, 0);
+ if (ret)
+ goto release_firmware;
+ } else {
+ enable_irq(data->irq);
+ }
+ mxt_free_object_table(data);
reinit_completion(&data->bl_completion);
- ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD);
- if (ret)
- goto disable_irq;
+ ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
+ if (ret) {
+ /* Bootloader may still be unlocked from previous attempt */
+ ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
+ if (ret)
+ goto disable_irq;
+ } else {
+ dev_info(dev, "Unlocking bootloader\n");
- /* Unlock bootloader */
- mxt_unlock_bootloader(data);
+ /* Unlock bootloader */
+ ret = mxt_send_bootloader_cmd(data, true);
+ if (ret)
+ goto disable_irq;
+ }
while (pos < fw->size) {
- ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA);
+ ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
if (ret)
goto disable_irq;
@@ -1283,7 +1994,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
if (ret)
goto disable_irq;
- ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS);
+ ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
if (ret) {
retry++;
@@ -1343,13 +2054,7 @@ static ssize_t mxt_update_fw_store(struct device *dev,
} else {
dev_info(dev, "The firmware update succeeded\n");
- mxt_free_object_table(data);
-
- mxt_initialize(data);
-
- enable_irq(data->irq);
-
- error = mxt_make_highchg(data);
+ error = mxt_initialize(data);
if (error)
return error;
}
@@ -1376,16 +2081,15 @@ static const struct attribute_group mxt_attr_group = {
static void mxt_start(struct mxt_data *data)
{
- /* Touch enable */
- mxt_write_object(data,
- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
+
+ /* Recalibrate since chip has been in deep sleep */
+ mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
}
static void mxt_stop(struct mxt_data *data)
{
- /* Touch disable */
- mxt_write_object(data,
- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
+ mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
}
static int mxt_input_open(struct input_dev *dev)
@@ -1404,138 +2108,112 @@ static void mxt_input_close(struct input_dev *dev)
mxt_stop(data);
}
-static int mxt_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+#ifdef CONFIG_OF
+static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+{
+ struct mxt_platform_data *pdata;
+ u32 *keymap;
+ u32 keycode;
+ int proplen, i, ret;
+
+ if (!client->dev.of_node)
+ return ERR_PTR(-ENODEV);
+
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ if (of_find_property(client->dev.of_node, "linux,gpio-keymap",
+ &proplen)) {
+ pdata->t19_num_keys = proplen / sizeof(u32);
+
+ keymap = devm_kzalloc(&client->dev,
+ pdata->t19_num_keys * sizeof(keymap[0]),
+ GFP_KERNEL);
+ if (!keymap)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < pdata->t19_num_keys; i++) {
+ ret = of_property_read_u32_index(client->dev.of_node,
+ "linux,gpio-keymap", i, &keycode);
+ if (ret)
+ keycode = KEY_RESERVED;
+
+ keymap[i] = keycode;
+ }
+
+ pdata->t19_keymap = keymap;
+ }
+
+ return pdata;
+}
+#else
+static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+{
+ dev_dbg(&client->dev, "No platform data specified\n");
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
struct mxt_data *data;
- struct input_dev *input_dev;
+ const struct mxt_platform_data *pdata;
int error;
- unsigned int num_mt_slots;
- unsigned int mt_flags = 0;
- int i;
- if (!pdata)
- return -EINVAL;
+ pdata = dev_get_platdata(&client->dev);
+ if (!pdata) {
+ pdata = mxt_parse_dt(client);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ }
data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!data || !input_dev) {
+ if (!data) {
dev_err(&client->dev, "Failed to allocate memory\n");
- error = -ENOMEM;
- goto err_free_mem;
+ return -ENOMEM;
}
- input_dev->name = "Atmel maXTouch Touchscreen";
snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
client->adapter->nr, client->addr);
- input_dev->phys = data->phys;
-
- input_dev->id.bustype = BUS_I2C;
- input_dev->dev.parent = &client->dev;
- input_dev->open = mxt_input_open;
- input_dev->close = mxt_input_close;
-
data->client = client;
- data->input_dev = input_dev;
data->pdata = pdata;
data->irq = client->irq;
+ i2c_set_clientdata(client, data);
init_completion(&data->bl_completion);
init_completion(&data->reset_completion);
init_completion(&data->crc_completion);
- error = mxt_initialize(data);
- if (error)
- goto err_free_mem;
-
- __set_bit(EV_ABS, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
-
- if (pdata->t19_num_keys) {
- __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
-
- for (i = 0; i < pdata->t19_num_keys; i++)
- if (pdata->t19_keymap[i] != KEY_RESERVED)
- input_set_capability(input_dev, EV_KEY,
- pdata->t19_keymap[i]);
-
- mt_flags |= INPUT_MT_POINTER;
-
- input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
- input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
- input_abs_set_res(input_dev, ABS_MT_POSITION_X,
- MXT_PIXELS_PER_MM);
- input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
- MXT_PIXELS_PER_MM);
-
- input_dev->name = "Atmel maXTouch Touchpad";
- }
-
- /* For single touch */
- input_set_abs_params(input_dev, ABS_X,
- 0, data->max_x, 0, 0);
- input_set_abs_params(input_dev, ABS_Y,
- 0, data->max_y, 0, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE,
- 0, 255, 0, 0);
-
- /* For multi touch */
- num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
- error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
- if (error)
- goto err_free_object;
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
- 0, MXT_MAX_AREA, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X,
- 0, data->max_x, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
- 0, data->max_y, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE,
- 0, 255, 0, 0);
-
- input_set_drvdata(input_dev, data);
- i2c_set_clientdata(client, data);
-
error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
pdata->irqflags | IRQF_ONESHOT,
client->name, data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
- goto err_free_object;
+ goto err_free_mem;
}
- error = mxt_make_highchg(data);
- if (error)
- goto err_free_irq;
+ disable_irq(client->irq);
- error = input_register_device(input_dev);
- if (error) {
- dev_err(&client->dev, "Error %d registering input device\n",
- error);
+ error = mxt_initialize(data);
+ if (error)
goto err_free_irq;
- }
error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
if (error) {
dev_err(&client->dev, "Failure %d creating sysfs group\n",
error);
- goto err_unregister_device;
+ goto err_free_object;
}
return 0;
-err_unregister_device:
- input_unregister_device(input_dev);
- input_dev = NULL;
+err_free_object:
+ mxt_free_object_table(data);
err_free_irq:
free_irq(client->irq, data);
-err_free_object:
- kfree(data->object_table);
err_free_mem:
- input_free_device(input_dev);
kfree(data);
return error;
}
@@ -1547,7 +2225,7 @@ static int mxt_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
free_irq(data->irq, data);
input_unregister_device(data->input_dev);
- kfree(data->object_table);
+ mxt_free_object_table(data);
kfree(data);
return 0;
@@ -1576,8 +2254,6 @@ static int mxt_resume(struct device *dev)
struct mxt_data *data = i2c_get_clientdata(client);
struct input_dev *input_dev = data->input_dev;
- mxt_soft_reset(data);
-
mutex_lock(&input_dev->mutex);
if (input_dev->users)
@@ -1591,6 +2267,12 @@ static int mxt_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
+static const struct of_device_id mxt_of_match[] = {
+ { .compatible = "atmel,maxtouch", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mxt_of_match);
+
static const struct i2c_device_id mxt_id[] = {
{ "qt602240_ts", 0 },
{ "atmel_mxt_ts", 0 },
@@ -1604,6 +2286,7 @@ static struct i2c_driver mxt_driver = {
.driver = {
.name = "atmel_mxt_ts",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mxt_of_match),
.pm = &mxt_pm_ops,
},
.probe = mxt_probe,
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index d4f33992ad8c..8857d5b9be71 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -262,7 +262,6 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
case M06:
wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
- wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
wrbuf[2] = value;
wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
return edt_ft5x06_ts_readwrite(tsdata->client, 4,
@@ -733,8 +732,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
static void
edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
{
- if (tsdata->debug_dir)
- debugfs_remove_recursive(tsdata->debug_dir);
+ debugfs_remove_recursive(tsdata->debug_dir);
kfree(tsdata->raw_buffer);
}
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
new file mode 100644
index 000000000000..62c8976e616f
--- /dev/null
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ *
+ * h3600 atmel micro companion support, touchscreen subdevice
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Dmitry Artamonow <mad_soft@inbox.ru>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+#include <asm/byteorder.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/ipaq-micro.h>
+
+struct touchscreen_data {
+ struct input_dev *input;
+ struct ipaq_micro *micro;
+};
+
+static void micro_ts_receive(void *data, int len, unsigned char *msg)
+{
+ struct touchscreen_data *ts = data;
+
+ if (len == 4) {
+ input_report_abs(ts->input, ABS_X,
+ be16_to_cpup((__be16 *) &msg[2]));
+ input_report_abs(ts->input, ABS_Y,
+ be16_to_cpup((__be16 *) &msg[0]));
+ input_report_key(ts->input, BTN_TOUCH, 1);
+ input_sync(ts->input);
+ } else if (len == 0) {
+ input_report_abs(ts->input, ABS_X, 0);
+ input_report_abs(ts->input, ABS_Y, 0);
+ input_report_key(ts->input, BTN_TOUCH, 0);
+ input_sync(ts->input);
+ }
+}
+
+static void micro_ts_toggle_receive(struct touchscreen_data *ts, bool enable)
+{
+ struct ipaq_micro *micro = ts->micro;
+
+ spin_lock_irq(&micro->lock);
+
+ if (enable) {
+ micro->ts = micro_ts_receive;
+ micro->ts_data = ts;
+ } else {
+ micro->ts = NULL;
+ micro->ts_data = NULL;
+ }
+
+ spin_unlock_irq(&ts->micro->lock);
+}
+
+static int micro_ts_open(struct input_dev *input)
+{
+ struct touchscreen_data *ts = input_get_drvdata(input);
+
+ micro_ts_toggle_receive(ts, true);
+
+ return 0;
+}
+
+static void micro_ts_close(struct input_dev *input)
+{
+ struct touchscreen_data *ts = input_get_drvdata(input);
+
+ micro_ts_toggle_receive(ts, false);
+}
+
+static int micro_ts_probe(struct platform_device *pdev)
+{
+ struct ipaq_micro *micro = dev_get_drvdata(pdev->dev.parent);
+ struct touchscreen_data *ts;
+ int error;
+
+ ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->micro = micro;
+
+ ts->input = devm_input_allocate_device(&pdev->dev);
+ if (!ts->input) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ ts->input->name = "ipaq micro ts";
+ ts->input->open = micro_ts_open;
+ ts->input->close = micro_ts_close;
+
+ input_set_drvdata(ts->input, ts);
+
+ input_set_capability(ts->input, EV_KEY, BTN_TOUCH);
+ input_set_capability(ts->input, EV_ABS, ABS_X);
+ input_set_capability(ts->input, EV_ABS, ABS_Y);
+ input_set_abs_params(ts->input, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params(ts->input, ABS_Y, 0, 1023, 0, 0);
+
+ error = input_register_device(ts->input);
+ if (error) {
+ dev_err(&pdev->dev, "error registering touch input\n");
+ return error;
+ }
+
+ platform_set_drvdata(pdev, ts);
+
+ dev_info(&pdev->dev, "iPAQ micro touchscreen\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int micro_ts_suspend(struct device *dev)
+{
+ struct touchscreen_data *ts = dev_get_drvdata(dev);
+
+ micro_ts_toggle_receive(ts, false);
+
+ return 0;
+}
+
+static int micro_ts_resume(struct device *dev)
+{
+ struct touchscreen_data *ts = dev_get_drvdata(dev);
+ struct input_dev *input = ts->input;
+
+ mutex_lock(&input->mutex);
+
+ if (input->users)
+ micro_ts_toggle_receive(ts, true);
+
+ mutex_unlock(&input->mutex);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops micro_ts_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)
+};
+
+static struct platform_driver micro_ts_device_driver = {
+ .driver = {
+ .name = "ipaq-micro-ts",
+ .pm = &micro_ts_dev_pm_ops,
+ },
+ .probe = micro_ts_probe,
+};
+module_platform_driver(micro_ts_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro touchscreen");
+MODULE_ALIAS("platform:ipaq-micro-ts");
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c
index 7324c5c0fb86..651ec71a5c68 100644
--- a/drivers/input/touchscreen/jornada720_ts.c
+++ b/drivers/input/touchscreen/jornada720_ts.c
@@ -36,22 +36,21 @@ struct jornada_ts {
static void jornada720_ts_collect_data(struct jornada_ts *jornada_ts)
{
+ /* 3 low word X samples */
+ jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
- /* 3 low word X samples */
- jornada_ts->x_data[0] = jornada_ssp_byte(TXDUMMY);
- jornada_ts->x_data[1] = jornada_ssp_byte(TXDUMMY);
- jornada_ts->x_data[2] = jornada_ssp_byte(TXDUMMY);
+ /* 3 low word Y samples */
+ jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
+ jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
- /* 3 low word Y samples */
- jornada_ts->y_data[0] = jornada_ssp_byte(TXDUMMY);
- jornada_ts->y_data[1] = jornada_ssp_byte(TXDUMMY);
- jornada_ts->y_data[2] = jornada_ssp_byte(TXDUMMY);
+ /* combined x samples bits */
+ jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
- /* combined x samples bits */
- jornada_ts->x_data[3] = jornada_ssp_byte(TXDUMMY);
-
- /* combined y samples bits */
- jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
+ /* combined y samples bits */
+ jornada_ts->y_data[3] = jornada_ssp_byte(TXDUMMY);
}
static int jornada720_ts_average(int coords[4])
@@ -104,13 +103,13 @@ static int jornada720_ts_probe(struct platform_device *pdev)
struct input_dev *input_dev;
int error;
- jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL);
- input_dev = input_allocate_device();
+ jornada_ts = devm_kzalloc(&pdev->dev, sizeof(*jornada_ts), GFP_KERNEL);
+ if (!jornada_ts)
+ return -ENOMEM;
- if (!jornada_ts || !input_dev) {
- error = -ENOMEM;
- goto fail1;
- }
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
platform_set_drvdata(pdev, jornada_ts);
@@ -126,36 +125,18 @@ static int jornada720_ts_probe(struct platform_device *pdev)
input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0);
- error = request_irq(IRQ_GPIO9,
- jornada720_ts_interrupt,
- IRQF_TRIGGER_RISING,
- "HP7XX Touchscreen driver", pdev);
+ error = devm_request_irq(&pdev->dev, IRQ_GPIO9,
+ jornada720_ts_interrupt,
+ IRQF_TRIGGER_RISING,
+ "HP7XX Touchscreen driver", pdev);
if (error) {
- printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n");
- goto fail1;
+ dev_err(&pdev->dev, "HP7XX TS : Unable to acquire irq!\n");
+ return error;
}
error = input_register_device(jornada_ts->dev);
if (error)
- goto fail2;
-
- return 0;
-
- fail2:
- free_irq(IRQ_GPIO9, pdev);
- fail1:
- input_free_device(input_dev);
- kfree(jornada_ts);
- return error;
-}
-
-static int jornada720_ts_remove(struct platform_device *pdev)
-{
- struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
-
- free_irq(IRQ_GPIO9, pdev);
- input_unregister_device(jornada_ts->dev);
- kfree(jornada_ts);
+ return error;
return 0;
}
@@ -165,7 +146,6 @@ MODULE_ALIAS("platform:jornada_ts");
static struct platform_driver jornada720_ts_driver = {
.probe = jornada720_ts_probe,
- .remove = jornada720_ts_remove,
.driver = {
.name = "jornada_ts",
.owner = THIS_MODULE,
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index 00510a9836b3..8b47e1fecb25 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -248,8 +248,7 @@ static int mcs5000_ts_probe(struct i2c_client *client,
return 0;
}
-#ifdef CONFIG_PM
-static int mcs5000_ts_suspend(struct device *dev)
+static int __maybe_unused mcs5000_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -259,7 +258,7 @@ static int mcs5000_ts_suspend(struct device *dev)
return 0;
}
-static int mcs5000_ts_resume(struct device *dev)
+static int __maybe_unused mcs5000_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mcs5000_ts_data *data = i2c_get_clientdata(client);
@@ -269,7 +268,6 @@ static int mcs5000_ts_resume(struct device *dev)
return 0;
}
-#endif
static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume);
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index 19c6c0fdc94b..fc49c75317d1 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -23,22 +23,51 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/input/pixcir_ts.h>
#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+
+#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
struct pixcir_i2c_ts_data {
struct i2c_client *client;
struct input_dev *input;
- const struct pixcir_ts_platform_data *chip;
+ const struct pixcir_ts_platform_data *pdata;
bool running;
+ int max_fingers; /* Max fingers supported in this instance */
+};
+
+struct pixcir_touch {
+ int x;
+ int y;
+ int id;
+};
+
+struct pixcir_report_data {
+ int num_touches;
+ struct pixcir_touch touches[PIXCIR_MAX_SLOTS];
};
-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
+static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
+ struct pixcir_report_data *report)
{
- struct pixcir_i2c_ts_data *tsdata = data;
- u8 rdbuf[10], wrbuf[1] = { 0 };
+ u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
+ u8 wrbuf[1] = { 0 };
+ u8 *bufptr;
u8 touch;
- int ret;
+ int ret, i;
+ int readsize;
+ const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
+
+ memset(report, 0, sizeof(struct pixcir_report_data));
+
+ i = chip->has_hw_ids ? 1 : 0;
+ readsize = 2 + tsdata->max_fingers * (4 + i);
+ if (readsize > sizeof(rdbuf))
+ readsize = sizeof(rdbuf);
ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
if (ret != sizeof(wrbuf)) {
@@ -48,7 +77,7 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
return;
}
- ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf));
+ ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
if (ret != sizeof(rdbuf)) {
dev_err(&tsdata->client->dev,
"%s: i2c_master_recv failed(), ret=%d\n",
@@ -56,45 +85,103 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
return;
}
- touch = rdbuf[0];
- if (touch) {
- u16 posx1 = (rdbuf[3] << 8) | rdbuf[2];
- u16 posy1 = (rdbuf[5] << 8) | rdbuf[4];
- u16 posx2 = (rdbuf[7] << 8) | rdbuf[6];
- u16 posy2 = (rdbuf[9] << 8) | rdbuf[8];
-
- input_report_key(tsdata->input, BTN_TOUCH, 1);
- input_report_abs(tsdata->input, ABS_X, posx1);
- input_report_abs(tsdata->input, ABS_Y, posy1);
-
- input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1);
- input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1);
- input_mt_sync(tsdata->input);
-
- if (touch == 2) {
- input_report_abs(tsdata->input,
- ABS_MT_POSITION_X, posx2);
- input_report_abs(tsdata->input,
- ABS_MT_POSITION_Y, posy2);
- input_mt_sync(tsdata->input);
+ touch = rdbuf[0] & 0x7;
+ if (touch > tsdata->max_fingers)
+ touch = tsdata->max_fingers;
+
+ report->num_touches = touch;
+ bufptr = &rdbuf[2];
+
+ for (i = 0; i < touch; i++) {
+ report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
+ report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
+
+ if (chip->has_hw_ids) {
+ report->touches[i].id = bufptr[4];
+ bufptr = bufptr + 5;
+ } else {
+ bufptr = bufptr + 4;
+ }
+ }
+}
+
+static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
+ struct pixcir_report_data *report)
+{
+ struct input_mt_pos pos[PIXCIR_MAX_SLOTS];
+ int slots[PIXCIR_MAX_SLOTS];
+ struct pixcir_touch *touch;
+ int n, i, slot;
+ struct device *dev = &ts->client->dev;
+ const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
+
+ n = report->num_touches;
+ if (n > PIXCIR_MAX_SLOTS)
+ n = PIXCIR_MAX_SLOTS;
+
+ if (!chip->has_hw_ids) {
+ for (i = 0; i < n; i++) {
+ touch = &report->touches[i];
+ pos[i].x = touch->x;
+ pos[i].y = touch->y;
+ }
+
+ input_mt_assign_slots(ts->input, slots, pos, n);
+ }
+
+ for (i = 0; i < n; i++) {
+ touch = &report->touches[i];
+
+ if (chip->has_hw_ids) {
+ slot = input_mt_get_slot_by_key(ts->input, touch->id);
+ if (slot < 0) {
+ dev_dbg(dev, "no free slot for id 0x%x\n",
+ touch->id);
+ continue;
+ }
+ } else {
+ slot = slots[i];
}
- } else {
- input_report_key(tsdata->input, BTN_TOUCH, 0);
+
+ input_mt_slot(ts->input, slot);
+ input_mt_report_slot_state(ts->input,
+ MT_TOOL_FINGER, true);
+
+ input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x);
+ input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y);
+
+ dev_dbg(dev, "%d: slot %d, x %d, y %d\n",
+ i, slot, touch->x, touch->y);
}
- input_sync(tsdata->input);
+ input_mt_sync_frame(ts->input);
+ input_sync(ts->input);
}
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{
struct pixcir_i2c_ts_data *tsdata = dev_id;
- const struct pixcir_ts_platform_data *pdata = tsdata->chip;
+ const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
+ struct pixcir_report_data report;
while (tsdata->running) {
- pixcir_ts_poscheck(tsdata);
-
- if (gpio_get_value(pdata->gpio_attb))
+ /* parse packet */
+ pixcir_ts_parse(tsdata, &report);
+
+ /* report it */
+ pixcir_ts_report(tsdata, &report);
+
+ if (gpio_get_value(pdata->gpio_attb)) {
+ if (report.num_touches) {
+ /*
+ * Last report with no finger up?
+ * Do it now then.
+ */
+ input_mt_sync_frame(tsdata->input);
+ input_sync(tsdata->input);
+ }
break;
+ }
msleep(20);
}
@@ -323,16 +410,69 @@ unlock:
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
+#ifdef CONFIG_OF
+static const struct of_device_id pixcir_of_match[];
+
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+ struct pixcir_ts_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *match;
+
+ match = of_match_device(of_match_ptr(pixcir_of_match), dev);
+ if (!match)
+ return ERR_PTR(-EINVAL);
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data;
+
+ pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0);
+ /* gpio_attb validity is checked in probe */
+
+ if (of_property_read_u32(np, "touchscreen-size-x", &pdata->x_max)) {
+ dev_err(dev, "Failed to get touchscreen-size-x property\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pdata->x_max -= 1;
+
+ if (of_property_read_u32(np, "touchscreen-size-y", &pdata->y_max)) {
+ dev_err(dev, "Failed to get touchscreen-size-y property\n");
+ return ERR_PTR(-EINVAL);
+ }
+ pdata->y_max -= 1;
+
+ dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__,
+ pdata->x_max + 1, pdata->y_max + 1, pdata->gpio_attb);
+
+ return pdata;
+}
+#else
+static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
static int pixcir_i2c_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev);
struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input;
int error;
+ if (np && !pdata) {
+ pdata = pixcir_parse_dt(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ }
+
if (!pdata) {
dev_err(&client->dev, "platform data not defined\n");
return -EINVAL;
@@ -343,6 +483,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return -EINVAL;
}
+ if (!pdata->chip.max_fingers) {
+ dev_err(dev, "Invalid max_fingers in pdata\n");
+ return -EINVAL;
+ }
+
tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
if (!tsdata)
return -ENOMEM;
@@ -355,7 +500,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
tsdata->client = client;
tsdata->input = input;
- tsdata->chip = pdata;
+ tsdata->pdata = pdata;
input->name = client->name;
input->id.bustype = BUS_I2C;
@@ -371,6 +516,20 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
+ tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
+ if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
+ tsdata->max_fingers = PIXCIR_MAX_SLOTS;
+ dev_info(dev, "Limiting maximum fingers to %d\n",
+ tsdata->max_fingers);
+ }
+
+ error = input_mt_init_slots(input, tsdata->max_fingers,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+ if (error) {
+ dev_err(dev, "Error initializing Multi-Touch slots\n");
+ return error;
+ }
+
input_set_drvdata(input, tsdata);
error = devm_gpio_request_one(dev, pdata->gpio_attb,
@@ -419,15 +578,36 @@ static int pixcir_i2c_ts_remove(struct i2c_client *client)
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
{ "pixcir_ts", 0 },
+ { "pixcir_tangoc", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
+#ifdef CONFIG_OF
+static const struct pixcir_i2c_chip_data pixcir_ts_data = {
+ .max_fingers = 2,
+ /* no hw id support */
+};
+
+static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
+ .max_fingers = 5,
+ .has_hw_ids = true,
+};
+
+static const struct of_device_id pixcir_of_match[] = {
+ { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
+ { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pixcir_of_match);
+#endif
+
static struct i2c_driver pixcir_i2c_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "pixcir_ts",
.pm = &pixcir_dev_pm_ops,
+ .of_match_table = of_match_ptr(pixcir_of_match),
},
.probe = pixcir_i2c_ts_probe,
.remove = pixcir_i2c_ts_remove,
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 19cb247dbb86..5a69ded9b53c 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -264,7 +264,7 @@ static int s3c2410ts_probe(struct platform_device *pdev)
return -ENOENT;
}
- clk_enable(ts.clock);
+ clk_prepare_enable(ts.clock);
dev_dbg(dev, "got and enabled clocks\n");
ts.irq_tc = ret = platform_get_irq(pdev, 0);
@@ -369,7 +369,7 @@ static int s3c2410ts_remove(struct platform_device *pdev)
free_irq(ts.irq_tc, ts.input);
del_timer_sync(&touch_timer);
- clk_disable(ts.clock);
+ clk_disable_unprepare(ts.clock);
clk_put(ts.clock);
input_unregister_device(ts.input);
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index feea85b52fa8..8ba48f5eff7b 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -29,6 +29,8 @@
#include <linux/sysfs.h>
#include <linux/input/mt.h>
#include <linux/platform_data/zforce_ts.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -117,6 +119,8 @@ struct zforce_ts {
const struct zforce_ts_platdata *pdata;
char phys[32];
+ struct regulator *reg_vdd;
+
bool suspending;
bool suspended;
bool boot_complete;
@@ -690,6 +694,11 @@ static void zforce_reset(void *data)
struct zforce_ts *ts = data;
gpio_set_value(ts->pdata->gpio_rst, 0);
+
+ udelay(10);
+
+ if (!IS_ERR(ts->reg_vdd))
+ regulator_disable(ts->reg_vdd);
}
static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
@@ -765,10 +774,32 @@ static int zforce_probe(struct i2c_client *client,
return ret;
}
+ ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");
+ if (IS_ERR(ts->reg_vdd)) {
+ ret = PTR_ERR(ts->reg_vdd);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ } else {
+ ret = regulator_enable(ts->reg_vdd);
+ if (ret)
+ return ret;
+
+ /*
+ * according to datasheet add 100us grace time after regular
+ * regulator enable delay.
+ */
+ udelay(100);
+ }
+
ret = devm_add_action(&client->dev, zforce_reset, ts);
if (ret) {
dev_err(&client->dev, "failed to register reset action, %d\n",
ret);
+
+ /* hereafter the regulator will be disabled by the action */
+ if (!IS_ERR(ts->reg_vdd))
+ regulator_disable(ts->reg_vdd);
+
return ret;
}
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d260605e6d5f..dd5112265cc9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -76,7 +76,7 @@ config AMD_IOMMU_STATS
config AMD_IOMMU_V2
tristate "AMD IOMMU Version 2 driver"
- depends on AMD_IOMMU && PROFILING
+ depends on AMD_IOMMU
select MMU_NOTIFIER
---help---
This option enables support for the AMD IOMMUv2 features of the IOMMU
@@ -143,16 +143,12 @@ config OMAP_IOMMU
depends on ARCH_OMAP2PLUS
select IOMMU_API
-config OMAP_IOVMM
- tristate "OMAP IO Virtual Memory Manager Support"
- depends on OMAP_IOMMU
-
config OMAP_IOMMU_DEBUG
- tristate "Export OMAP IOMMU/IOVMM internals in DebugFS"
- depends on OMAP_IOVMM && DEBUG_FS
+ tristate "Export OMAP IOMMU internals in DebugFS"
+ depends on OMAP_IOMMU && DEBUG_FS
help
Select this to see extensive information about
- the internal state of OMAP IOMMU/IOVMM in debugfs.
+ the internal state of OMAP IOMMU in debugfs.
Say N unless you know you need this.
@@ -180,6 +176,7 @@ config EXYNOS_IOMMU
bool "Exynos IOMMU Support"
depends on ARCH_EXYNOS
select IOMMU_API
+ select ARM_DMA_USE_IOMMU
help
Support for the IOMMU (System MMU) of Samsung Exynos application
processor family. This enables H/W multimedia accelerators to see
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 8893bad048e0..16edef74b8ee 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_IOMMU_API) += iommu.o
obj-$(CONFIG_IOMMU_API) += iommu-traces.o
+obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
@@ -11,7 +12,6 @@ obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
-obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 4aec6a29e316..18405314168b 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -46,7 +46,6 @@
#include "amd_iommu_proto.h"
#include "amd_iommu_types.h"
#include "irq_remapping.h"
-#include "pci.h"
#define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
@@ -81,7 +80,7 @@ LIST_HEAD(hpet_map);
*/
static struct protection_domain *pt_domain;
-static struct iommu_ops amd_iommu_ops;
+static const struct iommu_ops amd_iommu_ops;
static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
int amd_iommu_max_glx_val = -1;
@@ -133,9 +132,6 @@ static void free_dev_data(struct iommu_dev_data *dev_data)
list_del(&dev_data->dev_data_list);
spin_unlock_irqrestore(&dev_data_list_lock, flags);
- if (dev_data->group)
- iommu_group_put(dev_data->group);
-
kfree(dev_data);
}
@@ -264,167 +260,79 @@ static bool check_device(struct device *dev)
return true;
}
-static struct pci_bus *find_hosted_bus(struct pci_bus *bus)
-{
- while (!bus->self) {
- if (!pci_is_root_bus(bus))
- bus = bus->parent;
- else
- return ERR_PTR(-ENODEV);
- }
-
- return bus;
-}
-
-#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
-static struct pci_dev *get_isolation_root(struct pci_dev *pdev)
-{
- struct pci_dev *dma_pdev = pdev;
-
- /* Account for quirked devices */
- swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
-
- /*
- * If it's a multifunction device that does not support our
- * required ACS flags, add to the same group as lowest numbered
- * function that also does not suport the required ACS flags.
- */
- if (dma_pdev->multifunction &&
- !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
- u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
- for (i = 0; i < 8; i++) {
- struct pci_dev *tmp;
-
- tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
- if (!tmp)
- continue;
-
- if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
- swap_pci_ref(&dma_pdev, tmp);
- break;
- }
- pci_dev_put(tmp);
- }
- }
-
- /*
- * Devices on the root bus go through the iommu. If that's not us,
- * find the next upstream device and test ACS up to the root bus.
- * Finding the next device may require skipping virtual buses.
- */
- while (!pci_is_root_bus(dma_pdev->bus)) {
- struct pci_bus *bus = find_hosted_bus(dma_pdev->bus);
- if (IS_ERR(bus))
- break;
-
- if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
- break;
-
- swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
- }
-
- return dma_pdev;
-}
-
-static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev)
+static int init_iommu_group(struct device *dev)
{
- struct iommu_group *group = iommu_group_get(&pdev->dev);
- int ret;
+ struct iommu_group *group;
- if (!group) {
- group = iommu_group_alloc();
- if (IS_ERR(group))
- return PTR_ERR(group);
+ group = iommu_group_get_for_dev(dev);
- WARN_ON(&pdev->dev != dev);
- }
+ if (IS_ERR(group))
+ return PTR_ERR(group);
- ret = iommu_group_add_device(group, dev);
iommu_group_put(group);
- return ret;
+ return 0;
}
-static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data,
- struct device *dev)
+static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
{
- if (!dev_data->group) {
- struct iommu_group *group = iommu_group_alloc();
- if (IS_ERR(group))
- return PTR_ERR(group);
-
- dev_data->group = group;
- }
-
- return iommu_group_add_device(dev_data->group, dev);
+ *(u16 *)data = alias;
+ return 0;
}
-static int init_iommu_group(struct device *dev)
+static u16 get_alias(struct device *dev)
{
- struct iommu_dev_data *dev_data;
- struct iommu_group *group;
- struct pci_dev *dma_pdev;
- int ret;
-
- group = iommu_group_get(dev);
- if (group) {
- iommu_group_put(group);
- return 0;
- }
-
- dev_data = find_dev_data(get_device_id(dev));
- if (!dev_data)
- return -ENOMEM;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u16 devid, ivrs_alias, pci_alias;
- if (dev_data->alias_data) {
- u16 alias;
- struct pci_bus *bus;
+ devid = get_device_id(dev);
+ ivrs_alias = amd_iommu_alias_table[devid];
+ pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
- if (dev_data->alias_data->group)
- goto use_group;
+ if (ivrs_alias == pci_alias)
+ return ivrs_alias;
- /*
- * If the alias device exists, it's effectively just a first
- * level quirk for finding the DMA source.
- */
- alias = amd_iommu_alias_table[dev_data->devid];
- dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
- if (dma_pdev) {
- dma_pdev = get_isolation_root(dma_pdev);
- goto use_pdev;
+ /*
+ * DMA alias showdown
+ *
+ * The IVRS is fairly reliable in telling us about aliases, but it
+ * can't know about every screwy device. If we don't have an IVRS
+ * reported alias, use the PCI reported alias. In that case we may
+ * still need to initialize the rlookup and dev_table entries if the
+ * alias is to a non-existent device.
+ */
+ if (ivrs_alias == devid) {
+ if (!amd_iommu_rlookup_table[pci_alias]) {
+ amd_iommu_rlookup_table[pci_alias] =
+ amd_iommu_rlookup_table[devid];
+ memcpy(amd_iommu_dev_table[pci_alias].data,
+ amd_iommu_dev_table[devid].data,
+ sizeof(amd_iommu_dev_table[pci_alias].data));
}
- /*
- * If the alias is virtual, try to find a parent device
- * and test whether the IOMMU group is actualy rooted above
- * the alias. Be careful to also test the parent device if
- * we think the alias is the root of the group.
- */
- bus = pci_find_bus(0, alias >> 8);
- if (!bus)
- goto use_group;
-
- bus = find_hosted_bus(bus);
- if (IS_ERR(bus) || !bus->self)
- goto use_group;
+ return pci_alias;
+ }
- dma_pdev = get_isolation_root(pci_dev_get(bus->self));
- if (dma_pdev != bus->self || (dma_pdev->multifunction &&
- !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)))
- goto use_pdev;
+ pr_info("AMD-Vi: Using IVRS reported alias %02x:%02x.%d "
+ "for device %s[%04x:%04x], kernel reported alias "
+ "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
+ PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device,
+ PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
+ PCI_FUNC(pci_alias));
- pci_dev_put(dma_pdev);
- goto use_group;
+ /*
+ * If we don't have a PCI DMA alias and the IVRS alias is on the same
+ * bus, then the IVRS table may know about a quirk that we don't.
+ */
+ if (pci_alias == devid &&
+ PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
+ pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
+ pdev->dma_alias_devfn = ivrs_alias & 0xff;
+ pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
+ PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
+ dev_name(dev));
}
- dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev)));
-use_pdev:
- ret = use_pdev_iommu_group(dma_pdev, dev);
- pci_dev_put(dma_pdev);
- return ret;
-use_group:
- return use_dev_data_iommu_group(dev_data->alias_data, dev);
+ return ivrs_alias;
}
static int iommu_init_device(struct device *dev)
@@ -441,7 +349,8 @@ static int iommu_init_device(struct device *dev)
if (!dev_data)
return -ENOMEM;
- alias = amd_iommu_alias_table[dev_data->devid];
+ alias = get_alias(dev);
+
if (alias != dev_data->devid) {
struct iommu_dev_data *alias_data;
@@ -470,6 +379,9 @@ static int iommu_init_device(struct device *dev)
dev->archdata.iommu = dev_data;
+ iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
+ dev);
+
return 0;
}
@@ -489,12 +401,22 @@ static void iommu_ignore_device(struct device *dev)
static void iommu_uninit_device(struct device *dev)
{
+ struct iommu_dev_data *dev_data = search_dev_data(get_device_id(dev));
+
+ if (!dev_data)
+ return;
+
+ iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
+ dev);
+
iommu_group_remove_device(dev);
+ /* Unlink from alias, it may change if another device is re-plugged */
+ dev_data->alias_data = NULL;
+
/*
- * Nothing to do here - we keep dev_data around for unplugged devices
- * and reuse it when the device is re-plugged - not doing so would
- * introduce a ton of races.
+ * We keep dev_data around for unplugged devices and reuse it when the
+ * device is re-plugged - not doing so would introduce a ton of races.
*/
}
@@ -3473,7 +3395,7 @@ static int amd_iommu_domain_has_cap(struct iommu_domain *domain,
return 0;
}
-static struct iommu_ops amd_iommu_ops = {
+static const struct iommu_ops amd_iommu_ops = {
.domain_init = amd_iommu_domain_init,
.domain_destroy = amd_iommu_domain_destroy,
.attach_dev = amd_iommu_attach_device,
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 0e08545d7298..3783e0b44df6 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -26,6 +26,7 @@
#include <linux/msi.h>
#include <linux/amd-iommu.h>
#include <linux/export.h>
+#include <linux/iommu.h>
#include <asm/pci-direct.h>
#include <asm/iommu.h>
#include <asm/gart.h>
@@ -1197,6 +1198,39 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
iommu->max_counters = (u8) ((val >> 7) & 0xf);
}
+static ssize_t amd_iommu_show_cap(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amd_iommu *iommu = dev_get_drvdata(dev);
+ return sprintf(buf, "%x\n", iommu->cap);
+}
+static DEVICE_ATTR(cap, S_IRUGO, amd_iommu_show_cap, NULL);
+
+static ssize_t amd_iommu_show_features(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amd_iommu *iommu = dev_get_drvdata(dev);
+ return sprintf(buf, "%llx\n", iommu->features);
+}
+static DEVICE_ATTR(features, S_IRUGO, amd_iommu_show_features, NULL);
+
+static struct attribute *amd_iommu_attrs[] = {
+ &dev_attr_cap.attr,
+ &dev_attr_features.attr,
+ NULL,
+};
+
+static struct attribute_group amd_iommu_group = {
+ .name = "amd-iommu",
+ .attrs = amd_iommu_attrs,
+};
+
+static const struct attribute_group *amd_iommu_groups[] = {
+ &amd_iommu_group,
+ NULL,
+};
static int iommu_init_pci(struct amd_iommu *iommu)
{
@@ -1297,6 +1331,10 @@ static int iommu_init_pci(struct amd_iommu *iommu)
amd_iommu_erratum_746_workaround(iommu);
+ iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
+ amd_iommu_groups, "ivhd%d",
+ iommu->index);
+
return pci_enable_device(iommu->dev);
}
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index f1a5abf11acf..8e43b7cba133 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -390,12 +390,6 @@ struct amd_iommu_fault {
};
-#define PPR_FAULT_EXEC (1 << 1)
-#define PPR_FAULT_READ (1 << 2)
-#define PPR_FAULT_WRITE (1 << 5)
-#define PPR_FAULT_USER (1 << 6)
-#define PPR_FAULT_RSVD (1 << 7)
-#define PPR_FAULT_GN (1 << 8)
struct iommu_domain;
@@ -432,7 +426,6 @@ struct iommu_dev_data {
struct iommu_dev_data *alias_data;/* The alias dev_data */
struct protection_domain *domain; /* Domain the device is bound to */
atomic_t bind; /* Domain attach reference count */
- struct iommu_group *group; /* IOMMU group for virtual aliases */
u16 devid; /* PCI Device ID */
bool iommu_v2; /* Device can make use of IOMMUv2 */
bool passthrough; /* Default for device is pt_domain */
@@ -578,6 +571,9 @@ struct amd_iommu {
/* default dma_ops domain for that IOMMU */
struct dma_ops_domain *default_dom;
+ /* IOMMU sysfs device */
+ struct device *iommu_dev;
+
/*
* We can't rely on the BIOS to restore all values on reinit, so we
* need to stash them
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 499b4366a98d..5f578e850fc5 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -47,12 +47,13 @@ struct pasid_state {
atomic_t count; /* Reference count */
unsigned mmu_notifier_count; /* Counting nested mmu_notifier
calls */
- struct task_struct *task; /* Task bound to this PASID */
struct mm_struct *mm; /* mm_struct for the faults */
- struct mmu_notifier mn; /* mmu_otifier handle */
+ struct mmu_notifier mn; /* mmu_notifier handle */
struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */
struct device_state *device_state; /* Link to our device_state */
int pasid; /* PASID index */
+ bool invalid; /* Used during setup and
+ teardown of the pasid */
spinlock_t lock; /* Protect pri_queues and
mmu_notifer_count */
wait_queue_head_t wq; /* To wait for count == 0 */
@@ -99,7 +100,6 @@ static struct workqueue_struct *iommu_wq;
static u64 *empty_page_table;
static void free_pasid_states(struct device_state *dev_state);
-static void unbind_pasid(struct device_state *dev_state, int pasid);
static u16 device_id(struct pci_dev *pdev)
{
@@ -297,37 +297,29 @@ static void put_pasid_state_wait(struct pasid_state *pasid_state)
schedule();
finish_wait(&pasid_state->wq, &wait);
- mmput(pasid_state->mm);
free_pasid_state(pasid_state);
}
-static void __unbind_pasid(struct pasid_state *pasid_state)
+static void unbind_pasid(struct pasid_state *pasid_state)
{
struct iommu_domain *domain;
domain = pasid_state->device_state->domain;
+ /*
+ * Mark pasid_state as invalid, no more faults will we added to the
+ * work queue after this is visible everywhere.
+ */
+ pasid_state->invalid = true;
+
+ /* Make sure this is visible */
+ smp_wmb();
+
+ /* After this the device/pasid can't access the mm anymore */
amd_iommu_domain_clear_gcr3(domain, pasid_state->pasid);
- clear_pasid_state(pasid_state->device_state, pasid_state->pasid);
/* Make sure no more pending faults are in the queue */
flush_workqueue(iommu_wq);
-
- mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
-
- put_pasid_state(pasid_state); /* Reference taken in bind() function */
-}
-
-static void unbind_pasid(struct device_state *dev_state, int pasid)
-{
- struct pasid_state *pasid_state;
-
- pasid_state = get_pasid_state(dev_state, pasid);
- if (pasid_state == NULL)
- return;
-
- __unbind_pasid(pasid_state);
- put_pasid_state_wait(pasid_state); /* Reference taken in this function */
}
static void free_pasid_states_level1(struct pasid_state **tbl)
@@ -373,6 +365,12 @@ static void free_pasid_states(struct device_state *dev_state)
* unbind the PASID
*/
mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
+
+ put_pasid_state_wait(pasid_state); /* Reference taken in
+ amd_iommu_bind_pasid */
+
+ /* Drop reference taken in amd_iommu_bind_pasid */
+ put_device_state(dev_state);
}
if (dev_state->pasid_levels == 2)
@@ -411,14 +409,6 @@ static int mn_clear_flush_young(struct mmu_notifier *mn,
return 0;
}
-static void mn_change_pte(struct mmu_notifier *mn,
- struct mm_struct *mm,
- unsigned long address,
- pte_t pte)
-{
- __mn_flush_page(mn, address);
-}
-
static void mn_invalidate_page(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long address)
@@ -472,22 +462,23 @@ static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm)
{
struct pasid_state *pasid_state;
struct device_state *dev_state;
+ bool run_inv_ctx_cb;
might_sleep();
- pasid_state = mn_to_state(mn);
- dev_state = pasid_state->device_state;
+ pasid_state = mn_to_state(mn);
+ dev_state = pasid_state->device_state;
+ run_inv_ctx_cb = !pasid_state->invalid;
- if (pasid_state->device_state->inv_ctx_cb)
+ if (run_inv_ctx_cb && pasid_state->device_state->inv_ctx_cb)
dev_state->inv_ctx_cb(dev_state->pdev, pasid_state->pasid);
- unbind_pasid(dev_state, pasid_state->pasid);
+ unbind_pasid(pasid_state);
}
static struct mmu_notifier_ops iommu_mn = {
.release = mn_release,
.clear_flush_young = mn_clear_flush_young,
- .change_pte = mn_change_pte,
.invalidate_page = mn_invalidate_page,
.invalidate_range_start = mn_invalidate_range_start,
.invalidate_range_end = mn_invalidate_range_end,
@@ -529,7 +520,7 @@ static void do_fault(struct work_struct *work)
write = !!(fault->flags & PPR_FAULT_WRITE);
down_read(&fault->state->mm->mmap_sem);
- npages = get_user_pages(fault->state->task, fault->state->mm,
+ npages = get_user_pages(NULL, fault->state->mm,
fault->address, 1, write, 0, &page, NULL);
up_read(&fault->state->mm->mmap_sem);
@@ -587,7 +578,7 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data)
goto out;
pasid_state = get_pasid_state(dev_state, iommu_fault->pasid);
- if (pasid_state == NULL) {
+ if (pasid_state == NULL || pasid_state->invalid) {
/* We know the device but not the PASID -> send INVALID */
amd_iommu_complete_ppr(dev_state->pdev, iommu_fault->pasid,
PPR_INVALID, tag);
@@ -612,6 +603,7 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data)
fault->state = pasid_state;
fault->tag = tag;
fault->finish = finish;
+ fault->pasid = iommu_fault->pasid;
fault->flags = iommu_fault->flags;
INIT_WORK(&fault->work, do_fault);
@@ -620,6 +612,10 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data)
ret = NOTIFY_OK;
out_drop_state:
+
+ if (ret != NOTIFY_OK && pasid_state)
+ put_pasid_state(pasid_state);
+
put_device_state(dev_state);
out:
@@ -635,6 +631,7 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
{
struct pasid_state *pasid_state;
struct device_state *dev_state;
+ struct mm_struct *mm;
u16 devid;
int ret;
@@ -658,20 +655,23 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
if (pasid_state == NULL)
goto out;
+
atomic_set(&pasid_state->count, 1);
init_waitqueue_head(&pasid_state->wq);
spin_lock_init(&pasid_state->lock);
- pasid_state->task = task;
- pasid_state->mm = get_task_mm(task);
+ mm = get_task_mm(task);
+ pasid_state->mm = mm;
pasid_state->device_state = dev_state;
pasid_state->pasid = pasid;
+ pasid_state->invalid = true; /* Mark as valid only if we are
+ done with setting up the pasid */
pasid_state->mn.ops = &iommu_mn;
if (pasid_state->mm == NULL)
goto out_free;
- mmu_notifier_register(&pasid_state->mn, pasid_state->mm);
+ mmu_notifier_register(&pasid_state->mn, mm);
ret = set_pasid_state(dev_state, pasid_state, pasid);
if (ret)
@@ -682,15 +682,26 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
if (ret)
goto out_clear_state;
+ /* Now we are ready to handle faults */
+ pasid_state->invalid = false;
+
+ /*
+ * Drop the reference to the mm_struct here. We rely on the
+ * mmu_notifier release call-back to inform us when the mm
+ * is going away.
+ */
+ mmput(mm);
+
return 0;
out_clear_state:
clear_pasid_state(dev_state, pasid);
out_unregister:
- mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
+ mmu_notifier_unregister(&pasid_state->mn, mm);
out_free:
+ mmput(mm);
free_pasid_state(pasid_state);
out:
@@ -728,10 +739,22 @@ void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid)
*/
put_pasid_state(pasid_state);
- /* This will call the mn_release function and unbind the PASID */
+ /* Clear the pasid state so that the pasid can be re-used */
+ clear_pasid_state(dev_state, pasid_state->pasid);
+
+ /*
+ * Call mmu_notifier_unregister to drop our reference
+ * to pasid_state->mm
+ */
mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
+ put_pasid_state_wait(pasid_state); /* Reference taken in
+ amd_iommu_bind_pasid */
out:
+ /* Drop reference taken in this function */
+ put_device_state(dev_state);
+
+ /* Drop reference taken in amd_iommu_bind_pasid */
put_device_state(dev_state);
}
EXPORT_SYMBOL(amd_iommu_unbind_pasid);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1599354e974d..ca18d6d42a9b 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -39,6 +39,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -316,9 +317,9 @@
#define FSR_AFF (1 << 2)
#define FSR_TF (1 << 1)
-#define FSR_IGN (FSR_AFF | FSR_ASF | FSR_TLBMCF | \
- FSR_TLBLKF)
-#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
+#define FSR_IGN (FSR_AFF | FSR_ASF | \
+ FSR_TLBMCF | FSR_TLBLKF)
+#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
FSR_EF | FSR_PF | FSR_TF | FSR_IGN)
#define FSYNR0_WNR (1 << 4)
@@ -329,27 +330,20 @@ struct arm_smmu_smr {
u16 id;
};
-struct arm_smmu_master {
- struct device_node *of_node;
-
- /*
- * The following is specific to the master's position in the
- * SMMU chain.
- */
- struct rb_node node;
+struct arm_smmu_master_cfg {
int num_streamids;
u16 streamids[MAX_MASTER_STREAMIDS];
-
- /*
- * We only need to allocate these on the root SMMU, as we
- * configure unmatched streams to bypass translation.
- */
struct arm_smmu_smr *smrs;
};
+struct arm_smmu_master {
+ struct device_node *of_node;
+ struct rb_node node;
+ struct arm_smmu_master_cfg cfg;
+};
+
struct arm_smmu_device {
struct device *dev;
- struct device_node *parent_of_node;
void __iomem *base;
unsigned long size;
@@ -387,7 +381,6 @@ struct arm_smmu_device {
};
struct arm_smmu_cfg {
- struct arm_smmu_device *smmu;
u8 cbndx;
u8 irptndx;
u32 cbar;
@@ -399,15 +392,8 @@ struct arm_smmu_cfg {
#define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1)
struct arm_smmu_domain {
- /*
- * A domain can span across multiple, chained SMMUs and requires
- * all devices within the domain to follow the same translation
- * path.
- */
- struct arm_smmu_device *leaf_smmu;
- struct arm_smmu_cfg root_cfg;
- phys_addr_t output_mask;
-
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_cfg cfg;
spinlock_t lock;
};
@@ -419,7 +405,7 @@ struct arm_smmu_option_prop {
const char *prop;
};
-static struct arm_smmu_option_prop arm_smmu_options [] = {
+static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
{ 0, NULL},
};
@@ -427,6 +413,7 @@ static struct arm_smmu_option_prop arm_smmu_options [] = {
static void parse_driver_options(struct arm_smmu_device *smmu)
{
int i = 0;
+
do {
if (of_property_read_bool(smmu->dev->of_node,
arm_smmu_options[i].prop)) {
@@ -437,6 +424,19 @@ static void parse_driver_options(struct arm_smmu_device *smmu)
} while (arm_smmu_options[++i].opt);
}
+static struct device *dev_get_master_dev(struct device *dev)
+{
+ if (dev_is_pci(dev)) {
+ struct pci_bus *bus = to_pci_dev(dev)->bus;
+
+ while (!pci_is_root_bus(bus))
+ bus = bus->parent;
+ return bus->bridge->parent;
+ }
+
+ return dev;
+}
+
static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
struct device_node *dev_node)
{
@@ -444,6 +444,7 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
while (node) {
struct arm_smmu_master *master;
+
master = container_of(node, struct arm_smmu_master, node);
if (dev_node < master->of_node)
@@ -457,6 +458,18 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
return NULL;
}
+static struct arm_smmu_master_cfg *
+find_smmu_master_cfg(struct arm_smmu_device *smmu, struct device *dev)
+{
+ struct arm_smmu_master *master;
+
+ if (dev_is_pci(dev))
+ return dev->archdata.iommu;
+
+ master = find_smmu_master(smmu, dev->of_node);
+ return master ? &master->cfg : NULL;
+}
+
static int insert_smmu_master(struct arm_smmu_device *smmu,
struct arm_smmu_master *master)
{
@@ -465,8 +478,8 @@ static int insert_smmu_master(struct arm_smmu_device *smmu,
new = &smmu->masters.rb_node;
parent = NULL;
while (*new) {
- struct arm_smmu_master *this;
- this = container_of(*new, struct arm_smmu_master, node);
+ struct arm_smmu_master *this
+ = container_of(*new, struct arm_smmu_master, node);
parent = *new;
if (master->of_node < this->of_node)
@@ -508,33 +521,30 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
if (!master)
return -ENOMEM;
- master->of_node = masterspec->np;
- master->num_streamids = masterspec->args_count;
+ master->of_node = masterspec->np;
+ master->cfg.num_streamids = masterspec->args_count;
- for (i = 0; i < master->num_streamids; ++i)
- master->streamids[i] = masterspec->args[i];
+ for (i = 0; i < master->cfg.num_streamids; ++i)
+ master->cfg.streamids[i] = masterspec->args[i];
return insert_smmu_master(smmu, master);
}
-static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu)
+static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
{
- struct arm_smmu_device *parent;
-
- if (!smmu->parent_of_node)
- return NULL;
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_master *master = NULL;
+ struct device_node *dev_node = dev_get_master_dev(dev)->of_node;
spin_lock(&arm_smmu_devices_lock);
- list_for_each_entry(parent, &arm_smmu_devices, list)
- if (parent->dev->of_node == smmu->parent_of_node)
- goto out_unlock;
-
- parent = NULL;
- dev_warn(smmu->dev,
- "Failed to find SMMU parent despite parent in DT\n");
-out_unlock:
+ list_for_each_entry(smmu, &arm_smmu_devices, list) {
+ master = find_smmu_master(smmu, dev_node);
+ if (master)
+ break;
+ }
spin_unlock(&arm_smmu_devices_lock);
- return parent;
+
+ return master ? smmu : NULL;
}
static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
@@ -574,9 +584,10 @@ static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
}
}
-static void arm_smmu_tlb_inv_context(struct arm_smmu_cfg *cfg)
+static void arm_smmu_tlb_inv_context(struct arm_smmu_domain *smmu_domain)
{
- struct arm_smmu_device *smmu = cfg->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
void __iomem *base = ARM_SMMU_GR0(smmu);
bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
@@ -600,11 +611,11 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
unsigned long iova;
struct iommu_domain *domain = dev;
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- struct arm_smmu_device *smmu = root_cfg->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
void __iomem *cb_base;
- cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+ cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
if (!(fsr & FSR_FAULT))
@@ -631,7 +642,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
} else {
dev_err_ratelimited(smmu->dev,
"Unhandled context fault: iova=0x%08lx, fsynr=0x%x, cb=%d\n",
- iova, fsynr, root_cfg->cbndx);
+ iova, fsynr, cfg->cbndx);
ret = IRQ_NONE;
resume = RESUME_TERMINATE;
}
@@ -696,19 +707,19 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
{
u32 reg;
bool stage1;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- struct arm_smmu_device *smmu = root_cfg->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
void __iomem *cb_base, *gr0_base, *gr1_base;
gr0_base = ARM_SMMU_GR0(smmu);
gr1_base = ARM_SMMU_GR1(smmu);
- stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS;
- cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+ stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
+ cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
/* CBAR */
- reg = root_cfg->cbar;
+ reg = cfg->cbar;
if (smmu->version == 1)
- reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
+ reg |= cfg->irptndx << CBAR_IRPTNDX_SHIFT;
/*
* Use the weakest shareability/memory types, so they are
@@ -718,9 +729,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
} else {
- reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+ reg |= ARM_SMMU_CB_VMID(cfg) << CBAR_VMID_SHIFT;
}
- writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
+ writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
if (smmu->version > 1) {
/* CBA2R */
@@ -730,7 +741,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
reg = CBA2R_RW64_32BIT;
#endif
writel_relaxed(reg,
- gr1_base + ARM_SMMU_GR1_CBA2R(root_cfg->cbndx));
+ gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
/* TTBCR2 */
switch (smmu->input_size) {
@@ -780,13 +791,13 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
}
/* TTBR0 */
- arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+ arm_smmu_flush_pgtable(smmu, cfg->pgd,
PTRS_PER_PGD * sizeof(pgd_t));
- reg = __pa(root_cfg->pgd);
+ reg = __pa(cfg->pgd);
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
- reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
+ reg = (phys_addr_t)__pa(cfg->pgd) >> 32;
if (stage1)
- reg |= ARM_SMMU_CB_ASID(root_cfg) << TTBRn_HI_ASID_SHIFT;
+ reg |= ARM_SMMU_CB_ASID(cfg) << TTBRn_HI_ASID_SHIFT;
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI);
/*
@@ -800,6 +811,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
reg = TTBCR_TG0_64K;
if (!stage1) {
+ reg |= (64 - smmu->s1_output_size) << TTBCR_T0SZ_SHIFT;
+
switch (smmu->s2_output_size) {
case 32:
reg |= (TTBCR2_ADDR_32 << TTBCR_PASIZE_SHIFT);
@@ -821,7 +834,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
break;
}
} else {
- reg |= (64 - smmu->s1_output_size) << TTBCR_T0SZ_SHIFT;
+ reg |= (64 - smmu->input_size) << TTBCR_T0SZ_SHIFT;
}
} else {
reg = 0;
@@ -853,44 +866,25 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
}
static int arm_smmu_init_domain_context(struct iommu_domain *domain,
- struct device *dev)
+ struct arm_smmu_device *smmu)
{
int irq, ret, start;
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- struct arm_smmu_device *smmu, *parent;
-
- /*
- * Walk the SMMU chain to find the root device for this chain.
- * We assume that no masters have translations which terminate
- * early, and therefore check that the root SMMU does indeed have
- * a StreamID for the master in question.
- */
- parent = dev->archdata.iommu;
- smmu_domain->output_mask = -1;
- do {
- smmu = parent;
- smmu_domain->output_mask &= (1ULL << smmu->s2_output_size) - 1;
- } while ((parent = find_parent_smmu(smmu)));
-
- if (!find_smmu_master(smmu, dev->of_node)) {
- dev_err(dev, "unable to find root SMMU for device\n");
- return -ENODEV;
- }
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
/*
* We will likely want to change this if/when KVM gets
* involved.
*/
- root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
+ cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
start = smmu->num_s2_context_banks;
- } else if (smmu->features & ARM_SMMU_FEAT_TRANS_S2) {
- root_cfg->cbar = CBAR_TYPE_S2_TRANS;
- start = 0;
- } else {
- root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
+ } else if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) {
+ cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
start = smmu->num_s2_context_banks;
+ } else {
+ cfg->cbar = CBAR_TYPE_S2_TRANS;
+ start = 0;
}
ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
@@ -898,38 +892,38 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
if (IS_ERR_VALUE(ret))
return ret;
- root_cfg->cbndx = ret;
+ cfg->cbndx = ret;
if (smmu->version == 1) {
- root_cfg->irptndx = atomic_inc_return(&smmu->irptndx);
- root_cfg->irptndx %= smmu->num_context_irqs;
+ cfg->irptndx = atomic_inc_return(&smmu->irptndx);
+ cfg->irptndx %= smmu->num_context_irqs;
} else {
- root_cfg->irptndx = root_cfg->cbndx;
+ cfg->irptndx = cfg->cbndx;
}
- irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
+ irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
"arm-smmu-context-fault", domain);
if (IS_ERR_VALUE(ret)) {
dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
- root_cfg->irptndx, irq);
- root_cfg->irptndx = INVALID_IRPTNDX;
+ cfg->irptndx, irq);
+ cfg->irptndx = INVALID_IRPTNDX;
goto out_free_context;
}
- root_cfg->smmu = smmu;
+ smmu_domain->smmu = smmu;
arm_smmu_init_context_bank(smmu_domain);
- return ret;
+ return 0;
out_free_context:
- __arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx);
+ __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
return ret;
}
static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
{
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- struct arm_smmu_device *smmu = root_cfg->smmu;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
void __iomem *cb_base;
int irq;
@@ -937,16 +931,16 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
return;
/* Disable the context bank and nuke the TLB before freeing it. */
- cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx);
+ cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
- arm_smmu_tlb_inv_context(root_cfg);
+ arm_smmu_tlb_inv_context(smmu_domain);
- if (root_cfg->irptndx != INVALID_IRPTNDX) {
- irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
+ if (cfg->irptndx != INVALID_IRPTNDX) {
+ irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
free_irq(irq, domain);
}
- __arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx);
+ __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
}
static int arm_smmu_domain_init(struct iommu_domain *domain)
@@ -963,10 +957,10 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
if (!smmu_domain)
return -ENOMEM;
- pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+ pgd = kcalloc(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL);
if (!pgd)
goto out_free_domain;
- smmu_domain->root_cfg.pgd = pgd;
+ smmu_domain->cfg.pgd = pgd;
spin_lock_init(&smmu_domain->lock);
domain->priv = smmu_domain;
@@ -980,6 +974,7 @@ out_free_domain:
static void arm_smmu_free_ptes(pmd_t *pmd)
{
pgtable_t table = pmd_pgtable(*pmd);
+
pgtable_page_dtor(table);
__free_page(table);
}
@@ -1021,8 +1016,8 @@ static void arm_smmu_free_puds(pgd_t *pgd)
static void arm_smmu_free_pgtables(struct arm_smmu_domain *smmu_domain)
{
int i;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- pgd_t *pgd, *pgd_base = root_cfg->pgd;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ pgd_t *pgd, *pgd_base = cfg->pgd;
/*
* Recursively free the page tables for this domain. We don't
@@ -1054,7 +1049,7 @@ static void arm_smmu_domain_destroy(struct iommu_domain *domain)
}
static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
- struct arm_smmu_master *master)
+ struct arm_smmu_master_cfg *cfg)
{
int i;
struct arm_smmu_smr *smrs;
@@ -1063,18 +1058,18 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH))
return 0;
- if (master->smrs)
+ if (cfg->smrs)
return -EEXIST;
- smrs = kmalloc(sizeof(*smrs) * master->num_streamids, GFP_KERNEL);
+ smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL);
if (!smrs) {
- dev_err(smmu->dev, "failed to allocate %d SMRs for master %s\n",
- master->num_streamids, master->of_node->name);
+ dev_err(smmu->dev, "failed to allocate %d SMRs\n",
+ cfg->num_streamids);
return -ENOMEM;
}
- /* Allocate the SMRs on the root SMMU */
- for (i = 0; i < master->num_streamids; ++i) {
+ /* Allocate the SMRs on the SMMU */
+ for (i = 0; i < cfg->num_streamids; ++i) {
int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
smmu->num_mapping_groups);
if (IS_ERR_VALUE(idx)) {
@@ -1085,18 +1080,18 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
smrs[i] = (struct arm_smmu_smr) {
.idx = idx,
.mask = 0, /* We don't currently share SMRs */
- .id = master->streamids[i],
+ .id = cfg->streamids[i],
};
}
/* It worked! Now, poke the actual hardware */
- for (i = 0; i < master->num_streamids; ++i) {
+ for (i = 0; i < cfg->num_streamids; ++i) {
u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
smrs[i].mask << SMR_MASK_SHIFT;
writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
}
- master->smrs = smrs;
+ cfg->smrs = smrs;
return 0;
err_free_smrs:
@@ -1107,68 +1102,55 @@ err_free_smrs:
}
static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
- struct arm_smmu_master *master)
+ struct arm_smmu_master_cfg *cfg)
{
int i;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
- struct arm_smmu_smr *smrs = master->smrs;
+ struct arm_smmu_smr *smrs = cfg->smrs;
/* Invalidate the SMRs before freeing back to the allocator */
- for (i = 0; i < master->num_streamids; ++i) {
+ for (i = 0; i < cfg->num_streamids; ++i) {
u8 idx = smrs[i].idx;
+
writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx));
__arm_smmu_free_bitmap(smmu->smr_map, idx);
}
- master->smrs = NULL;
+ cfg->smrs = NULL;
kfree(smrs);
}
static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu,
- struct arm_smmu_master *master)
+ struct arm_smmu_master_cfg *cfg)
{
int i;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
- for (i = 0; i < master->num_streamids; ++i) {
- u16 sid = master->streamids[i];
+ for (i = 0; i < cfg->num_streamids; ++i) {
+ u16 sid = cfg->streamids[i];
+
writel_relaxed(S2CR_TYPE_BYPASS,
gr0_base + ARM_SMMU_GR0_S2CR(sid));
}
}
static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
- struct arm_smmu_master *master)
+ struct arm_smmu_master_cfg *cfg)
{
int i, ret;
- struct arm_smmu_device *parent, *smmu = smmu_domain->root_cfg.smmu;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
- ret = arm_smmu_master_configure_smrs(smmu, master);
+ ret = arm_smmu_master_configure_smrs(smmu, cfg);
if (ret)
return ret;
- /* Bypass the leaves */
- smmu = smmu_domain->leaf_smmu;
- while ((parent = find_parent_smmu(smmu))) {
- /*
- * We won't have a StreamID match for anything but the root
- * smmu, so we only need to worry about StreamID indexing,
- * where we must install bypass entries in the S2CRs.
- */
- if (smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)
- continue;
-
- arm_smmu_bypass_stream_mapping(smmu, master);
- smmu = parent;
- }
-
- /* Now we're at the root, time to point at our context bank */
- for (i = 0; i < master->num_streamids; ++i) {
+ for (i = 0; i < cfg->num_streamids; ++i) {
u32 idx, s2cr;
- idx = master->smrs ? master->smrs[i].idx : master->streamids[i];
+
+ idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
s2cr = S2CR_TYPE_TRANS |
- (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT);
+ (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
}
@@ -1176,58 +1158,57 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
}
static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
- struct arm_smmu_master *master)
+ struct arm_smmu_master_cfg *cfg)
{
- struct arm_smmu_device *smmu = smmu_domain->root_cfg.smmu;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
/*
* We *must* clear the S2CR first, because freeing the SMR means
* that it can be re-allocated immediately.
*/
- arm_smmu_bypass_stream_mapping(smmu, master);
- arm_smmu_master_free_smrs(smmu, master);
+ arm_smmu_bypass_stream_mapping(smmu, cfg);
+ arm_smmu_master_free_smrs(smmu, cfg);
}
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
int ret = -EINVAL;
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_device *device_smmu = dev->archdata.iommu;
- struct arm_smmu_master *master;
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_master_cfg *cfg;
unsigned long flags;
- if (!device_smmu) {
+ smmu = dev_get_master_dev(dev)->archdata.iommu;
+ if (!smmu) {
dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
return -ENXIO;
}
/*
- * Sanity check the domain. We don't currently support domains
- * that cross between different SMMU chains.
+ * Sanity check the domain. We don't support domains across
+ * different SMMUs.
*/
spin_lock_irqsave(&smmu_domain->lock, flags);
- if (!smmu_domain->leaf_smmu) {
+ if (!smmu_domain->smmu) {
/* Now that we have a master, we can finalise the domain */
- ret = arm_smmu_init_domain_context(domain, dev);
+ ret = arm_smmu_init_domain_context(domain, smmu);
if (IS_ERR_VALUE(ret))
goto err_unlock;
-
- smmu_domain->leaf_smmu = device_smmu;
- } else if (smmu_domain->leaf_smmu != device_smmu) {
+ } else if (smmu_domain->smmu != smmu) {
dev_err(dev,
"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
- dev_name(smmu_domain->leaf_smmu->dev),
- dev_name(device_smmu->dev));
+ dev_name(smmu_domain->smmu->dev),
+ dev_name(smmu->dev));
goto err_unlock;
}
spin_unlock_irqrestore(&smmu_domain->lock, flags);
/* Looks ok, so add the device to the domain */
- master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
- if (!master)
+ cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
+ if (!cfg)
return -ENODEV;
- return arm_smmu_domain_add_master(smmu_domain, master);
+ return arm_smmu_domain_add_master(smmu_domain, cfg);
err_unlock:
spin_unlock_irqrestore(&smmu_domain->lock, flags);
@@ -1237,11 +1218,11 @@ err_unlock:
static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
{
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_master *master;
+ struct arm_smmu_master_cfg *cfg;
- master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
- if (master)
- arm_smmu_domain_remove_master(smmu_domain, master);
+ cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
+ if (cfg)
+ arm_smmu_domain_remove_master(smmu_domain, cfg);
}
static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
@@ -1261,6 +1242,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
if (pmd_none(*pmd)) {
/* Allocate a new set of tables */
pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
+
if (!table)
return -ENOMEM;
@@ -1326,6 +1308,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
*/
do {
int i = 1;
+
pteval &= ~ARM_SMMU_PTE_CONT;
if (arm_smmu_pte_is_contiguous_range(addr, end)) {
@@ -1340,7 +1323,8 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1);
cont_start = pmd_page_vaddr(*pmd) + idx;
for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j)
- pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT;
+ pte_val(*(cont_start + j)) &=
+ ~ARM_SMMU_PTE_CONT;
arm_smmu_flush_pgtable(smmu, cont_start,
sizeof(*pte) *
@@ -1429,12 +1413,12 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
int ret, stage;
unsigned long end;
phys_addr_t input_mask, output_mask;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
- pgd_t *pgd = root_cfg->pgd;
- struct arm_smmu_device *smmu = root_cfg->smmu;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+ pgd_t *pgd = cfg->pgd;
unsigned long flags;
- if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
+ if (cfg->cbar == CBAR_TYPE_S2_TRANS) {
stage = 2;
output_mask = (1ULL << smmu->s2_output_size) - 1;
} else {
@@ -1484,10 +1468,6 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
if (!smmu_domain)
return -ENODEV;
- /* Check for silent address truncation up the SMMU chain. */
- if ((phys_addr_t)iova & ~smmu_domain->output_mask)
- return -ERANGE;
-
return arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, prot);
}
@@ -1498,7 +1478,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
struct arm_smmu_domain *smmu_domain = domain->priv;
ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0);
- arm_smmu_tlb_inv_context(&smmu_domain->root_cfg);
+ arm_smmu_tlb_inv_context(smmu_domain);
return ret ? 0 : size;
}
@@ -1510,9 +1490,9 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
pmd_t pmd;
pte_t pte;
struct arm_smmu_domain *smmu_domain = domain->priv;
- struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
+ struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
- pgdp = root_cfg->pgd;
+ pgdp = cfg->pgd;
if (!pgdp)
return 0;
@@ -1538,19 +1518,29 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
static int arm_smmu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
- unsigned long caps = 0;
struct arm_smmu_domain *smmu_domain = domain->priv;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ u32 features = smmu ? smmu->features : 0;
+
+ switch (cap) {
+ case IOMMU_CAP_CACHE_COHERENCY:
+ return features & ARM_SMMU_FEAT_COHERENT_WALK;
+ case IOMMU_CAP_INTR_REMAP:
+ return 1; /* MSIs are just memory writes */
+ default:
+ return 0;
+ }
+}
- if (smmu_domain->root_cfg.smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
- caps |= IOMMU_CAP_CACHE_COHERENCY;
-
- return !!(cap & caps);
+static int __arm_smmu_get_pci_sid(struct pci_dev *pdev, u16 alias, void *data)
+{
+ *((u16 *)data) = alias;
+ return 0; /* Continue walking */
}
static int arm_smmu_add_device(struct device *dev)
{
- struct arm_smmu_device *child, *parent, *smmu;
- struct arm_smmu_master *master = NULL;
+ struct arm_smmu_device *smmu;
struct iommu_group *group;
int ret;
@@ -1559,35 +1549,8 @@ static int arm_smmu_add_device(struct device *dev)
return -EINVAL;
}
- spin_lock(&arm_smmu_devices_lock);
- list_for_each_entry(parent, &arm_smmu_devices, list) {
- smmu = parent;
-
- /* Try to find a child of the current SMMU. */
- list_for_each_entry(child, &arm_smmu_devices, list) {
- if (child->parent_of_node == parent->dev->of_node) {
- /* Does the child sit above our master? */
- master = find_smmu_master(child, dev->of_node);
- if (master) {
- smmu = NULL;
- break;
- }
- }
- }
-
- /* We found some children, so keep searching. */
- if (!smmu) {
- master = NULL;
- continue;
- }
-
- master = find_smmu_master(smmu, dev->of_node);
- if (master)
- break;
- }
- spin_unlock(&arm_smmu_devices_lock);
-
- if (!master)
+ smmu = find_smmu_for_device(dev);
+ if (!smmu)
return -ENODEV;
group = iommu_group_alloc();
@@ -1596,20 +1559,45 @@ static int arm_smmu_add_device(struct device *dev)
return PTR_ERR(group);
}
+ if (dev_is_pci(dev)) {
+ struct arm_smmu_master_cfg *cfg;
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+ if (!cfg) {
+ ret = -ENOMEM;
+ goto out_put_group;
+ }
+
+ cfg->num_streamids = 1;
+ /*
+ * Assume Stream ID == Requester ID for now.
+ * We need a way to describe the ID mappings in FDT.
+ */
+ pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
+ &cfg->streamids[0]);
+ dev->archdata.iommu = cfg;
+ } else {
+ dev->archdata.iommu = smmu;
+ }
+
ret = iommu_group_add_device(group, dev);
- iommu_group_put(group);
- dev->archdata.iommu = smmu;
+out_put_group:
+ iommu_group_put(group);
return ret;
}
static void arm_smmu_remove_device(struct device *dev)
{
+ if (dev_is_pci(dev))
+ kfree(dev->archdata.iommu);
+
dev->archdata.iommu = NULL;
iommu_group_remove_device(dev);
}
-static struct iommu_ops arm_smmu_ops = {
+static const struct iommu_ops arm_smmu_ops = {
.domain_init = arm_smmu_domain_init,
.domain_destroy = arm_smmu_domain_destroy,
.attach_dev = arm_smmu_attach_dev,
@@ -1639,7 +1627,8 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
/* Mark all SMRn as invalid and all S2CRn as bypass */
for (i = 0; i < smmu->num_mapping_groups; ++i) {
writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i));
- writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i));
+ writel_relaxed(S2CR_TYPE_BYPASS,
+ gr0_base + ARM_SMMU_GR0_S2CR(i));
}
/* Make sure all context banks are disabled and clear CB_FSR */
@@ -1779,11 +1768,13 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K;
/* Check for size mismatch of SMMU address space from mapped region */
- size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
+ size = 1 <<
+ (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
size *= (smmu->pagesize << 1);
if (smmu->size != size)
- dev_warn(smmu->dev, "SMMU address space size (0x%lx) differs "
- "from mapped region size (0x%lx)!\n", size, smmu->size);
+ dev_warn(smmu->dev,
+ "SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n",
+ size, smmu->size);
smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) &
ID1_NUMS2CB_MASK;
@@ -1804,14 +1795,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
* allocation (PTRS_PER_PGD).
*/
#ifdef CONFIG_64BIT
- smmu->s1_output_size = min((unsigned long)VA_BITS, size);
+ smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
#else
smmu->s1_output_size = min(32UL, size);
#endif
/* The stage-2 output mask is also applied for bypass */
size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
- smmu->s2_output_size = min((unsigned long)PHYS_MASK_SHIFT, size);
+ smmu->s2_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size);
if (smmu->version == 1) {
smmu->input_size = 32;
@@ -1835,7 +1826,8 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
dev_notice(smmu->dev,
"\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n",
- smmu->input_size, smmu->s1_output_size, smmu->s2_output_size);
+ smmu->input_size, smmu->s1_output_size,
+ smmu->s2_output_size);
return 0;
}
@@ -1843,7 +1835,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
{
struct resource *res;
struct arm_smmu_device *smmu;
- struct device_node *dev_node;
struct device *dev = &pdev->dev;
struct rb_node *node;
struct of_phandle_args masterspec;
@@ -1890,6 +1881,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
for (i = 0; i < num_irqs; ++i) {
int irq = platform_get_irq(pdev, i);
+
if (irq < 0) {
dev_err(dev, "failed to get irq index %d\n", i);
return -ENODEV;
@@ -1913,12 +1905,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
}
dev_notice(dev, "registered %d master devices\n", i);
- if ((dev_node = of_parse_phandle(dev->of_node, "smmu-parent", 0)))
- smmu->parent_of_node = dev_node;
-
err = arm_smmu_device_cfg_probe(smmu);
if (err)
- goto out_put_parent;
+ goto out_put_masters;
parse_driver_options(smmu);
@@ -1928,7 +1917,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
"found only %d context interrupt(s) but %d required\n",
smmu->num_context_irqs, smmu->num_context_banks);
err = -ENODEV;
- goto out_put_parent;
+ goto out_put_masters;
}
for (i = 0; i < smmu->num_global_irqs; ++i) {
@@ -1956,14 +1945,10 @@ out_free_irqs:
while (i--)
free_irq(smmu->irqs[i], smmu);
-out_put_parent:
- if (smmu->parent_of_node)
- of_node_put(smmu->parent_of_node);
-
out_put_masters:
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
- struct arm_smmu_master *master;
- master = container_of(node, struct arm_smmu_master, node);
+ struct arm_smmu_master *master
+ = container_of(node, struct arm_smmu_master, node);
of_node_put(master->of_node);
}
@@ -1990,12 +1975,9 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
if (!smmu)
return -ENODEV;
- if (smmu->parent_of_node)
- of_node_put(smmu->parent_of_node);
-
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
- struct arm_smmu_master *master;
- master = container_of(node, struct arm_smmu_master, node);
+ struct arm_smmu_master *master
+ = container_of(node, struct arm_smmu_master, node);
of_node_put(master->of_node);
}
@@ -2006,7 +1988,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
free_irq(smmu->irqs[i], smmu);
/* Turn the thing off */
- writel(sCR0_CLIENTPD,ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+ writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
return 0;
}
@@ -2048,6 +2030,11 @@ static int __init arm_smmu_init(void)
bus_set_iommu(&amba_bustype, &arm_smmu_ops);
#endif
+#ifdef CONFIG_PCI
+ if (!iommu_present(&pci_bus_type))
+ bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
+#endif
+
return 0;
}
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 9a4f05e5b23f..60ab474bfff3 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -38,6 +38,7 @@
#include <linux/tboot.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/iommu.h>
#include <asm/irq_remapping.h>
#include <asm/iommu_table.h>
@@ -84,7 +85,7 @@ void *dmar_alloc_dev_scope(void *start, void *end, int *cnt)
*cnt = 0;
while (start < end) {
scope = start;
- if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ACPI ||
+ if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_NAMESPACE ||
scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT ||
scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
(*cnt)++;
@@ -380,7 +381,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header)
struct acpi_dmar_andd *andd = (void *)header;
/* Check for NUL termination within the designated length */
- if (strnlen(andd->object_name, header->length - 8) == header->length - 8) {
+ if (strnlen(andd->device_name, header->length - 8) == header->length - 8) {
WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
"Your BIOS is broken; ANDD object name is not NUL-terminated\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
@@ -390,7 +391,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header)
return -EINVAL;
}
pr_info("ANDD device: %x name: %s\n", andd->device_number,
- andd->object_name);
+ andd->device_name);
return 0;
}
@@ -448,17 +449,17 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
(unsigned long long)rmrr->base_address,
(unsigned long long)rmrr->end_address);
break;
- case ACPI_DMAR_TYPE_ATSR:
+ case ACPI_DMAR_TYPE_ROOT_ATS:
atsr = container_of(header, struct acpi_dmar_atsr, header);
pr_info("ATSR flags: %#x\n", atsr->flags);
break;
- case ACPI_DMAR_HARDWARE_AFFINITY:
+ case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
rhsa = container_of(header, struct acpi_dmar_rhsa, header);
pr_info("RHSA base: %#016Lx proximity domain: %#x\n",
(unsigned long long)rhsa->base_address,
rhsa->proximity_domain);
break;
- case ACPI_DMAR_TYPE_ANDD:
+ case ACPI_DMAR_TYPE_NAMESPACE:
/* We don't print this here because we need to sanity-check
it first. So print it in dmar_parse_one_andd() instead. */
break;
@@ -539,15 +540,15 @@ parse_dmar_table(void)
case ACPI_DMAR_TYPE_RESERVED_MEMORY:
ret = dmar_parse_one_rmrr(entry_header);
break;
- case ACPI_DMAR_TYPE_ATSR:
+ case ACPI_DMAR_TYPE_ROOT_ATS:
ret = dmar_parse_one_atsr(entry_header);
break;
- case ACPI_DMAR_HARDWARE_AFFINITY:
+ case ACPI_DMAR_TYPE_HARDWARE_AFFINITY:
#ifdef CONFIG_ACPI_NUMA
ret = dmar_parse_one_rhsa(entry_header);
#endif
break;
- case ACPI_DMAR_TYPE_ANDD:
+ case ACPI_DMAR_TYPE_NAMESPACE:
ret = dmar_parse_one_andd(entry_header);
break;
default:
@@ -631,7 +632,7 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number,
for (scope = (void *)(drhd + 1);
(unsigned long)scope < ((unsigned long)drhd) + drhd->header.length;
scope = ((void *)scope) + scope->length) {
- if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI)
+ if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
continue;
if (scope->enumeration_id != device_number)
continue;
@@ -666,21 +667,21 @@ static int __init dmar_acpi_dev_scope_init(void)
for (andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar);
((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length;
andd = ((void *)andd) + andd->header.length) {
- if (andd->header.type == ACPI_DMAR_TYPE_ANDD) {
+ if (andd->header.type == ACPI_DMAR_TYPE_NAMESPACE) {
acpi_handle h;
struct acpi_device *adev;
if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT,
- andd->object_name,
+ andd->device_name,
&h))) {
pr_err("Failed to find handle for ACPI object %s\n",
- andd->object_name);
+ andd->device_name);
continue;
}
acpi_bus_get_device(h, &adev);
if (!adev) {
pr_err("Failed to get device for ACPI object %s\n",
- andd->object_name);
+ andd->device_name);
continue;
}
dmar_acpi_insert_dev_scope(andd->device_number, adev);
@@ -980,6 +981,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
raw_spin_lock_init(&iommu->register_lock);
drhd->iommu = iommu;
+
+ if (intel_iommu_enabled)
+ iommu->iommu_dev = iommu_device_create(NULL, iommu,
+ intel_iommu_groups,
+ iommu->name);
+
return 0;
err_unmap:
@@ -991,6 +998,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
static void free_iommu(struct intel_iommu *iommu)
{
+ iommu_device_destroy(iommu->iommu_dev);
+
if (iommu->irq) {
free_irq(iommu->irq, iommu);
irq_set_handler_data(iommu->irq, NULL);
@@ -1339,9 +1348,6 @@ int dmar_enable_qi(struct intel_iommu *iommu)
return -ENOMEM;
}
- qi->free_head = qi->free_tail = 0;
- qi->free_cnt = QI_LENGTH;
-
raw_spin_lock_init(&qi->q_lock);
__dmar_enable_qi(iommu);
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 99054d2c040d..d037e87a1fe5 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1170,7 +1170,7 @@ static void exynos_iommu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
}
-static struct iommu_ops exynos_iommu_ops = {
+static const struct iommu_ops exynos_iommu_ops = {
.domain_init = exynos_iommu_domain_init,
.domain_destroy = exynos_iommu_domain_destroy,
.attach_dev = exynos_iommu_attach_device,
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index bb446d742a2d..2b6ce9387af1 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -92,7 +92,7 @@ struct gen_pool *spaace_pool;
* subwindow count per liodn.
*
*/
-u32 pamu_get_max_subwin_cnt()
+u32 pamu_get_max_subwin_cnt(void)
{
return max_subwindow_count;
}
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index af47648301a9..61d1dafa242d 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -38,7 +38,6 @@
#include <sysdev/fsl_pci.h>
#include "fsl_pamu_domain.h"
-#include "pci.h"
/*
* Global spinlock that needs to be held while
@@ -887,8 +886,6 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain,
return ret;
}
-#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
static struct iommu_group *get_device_iommu_group(struct device *dev)
{
struct iommu_group *group;
@@ -945,74 +942,13 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
struct pci_controller *pci_ctl;
bool pci_endpt_partioning;
struct iommu_group *group = NULL;
- struct pci_dev *bridge, *dma_pdev = NULL;
pci_ctl = pci_bus_to_host(pdev->bus);
pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl);
/* We can partition PCIe devices so assign device group to the device */
if (pci_endpt_partioning) {
- bridge = pci_find_upstream_pcie_bridge(pdev);
- if (bridge) {
- if (pci_is_pcie(bridge))
- dma_pdev = pci_get_domain_bus_and_slot(
- pci_domain_nr(pdev->bus),
- bridge->subordinate->number, 0);
- if (!dma_pdev)
- dma_pdev = pci_dev_get(bridge);
- } else
- dma_pdev = pci_dev_get(pdev);
-
- /* Account for quirked devices */
- swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
-
- /*
- * If it's a multifunction device that does not support our
- * required ACS flags, add to the same group as lowest numbered
- * function that also does not suport the required ACS flags.
- */
- if (dma_pdev->multifunction &&
- !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
- u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
- for (i = 0; i < 8; i++) {
- struct pci_dev *tmp;
-
- tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
- if (!tmp)
- continue;
-
- if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
- swap_pci_ref(&dma_pdev, tmp);
- break;
- }
- pci_dev_put(tmp);
- }
- }
-
- /*
- * Devices on the root bus go through the iommu. If that's not us,
- * find the next upstream device and test ACS up to the root bus.
- * Finding the next device may require skipping virtual buses.
- */
- while (!pci_is_root_bus(dma_pdev->bus)) {
- struct pci_bus *bus = dma_pdev->bus;
-
- while (!bus->self) {
- if (!pci_is_root_bus(bus))
- bus = bus->parent;
- else
- goto root_bus;
- }
-
- if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
- break;
-
- swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
- }
+ group = iommu_group_get_for_dev(&pdev->dev);
-root_bus:
- group = get_device_iommu_group(&dma_pdev->dev);
- pci_dev_put(dma_pdev);
/*
* PCIe controller is not a paritionable entity
* free the controller device iommu_group.
@@ -1116,8 +1052,7 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
ret = pamu_set_domain_geometry(dma_domain, &domain->geometry,
((w_count > 1) ? w_count : 0));
if (!ret) {
- if (dma_domain->win_arr)
- kfree(dma_domain->win_arr);
+ kfree(dma_domain->win_arr);
dma_domain->win_arr = kzalloc(sizeof(struct dma_window) *
w_count, GFP_ATOMIC);
if (!dma_domain->win_arr) {
@@ -1138,7 +1073,7 @@ static u32 fsl_pamu_get_windows(struct iommu_domain *domain)
return dma_domain->win_cnt;
}
-static struct iommu_ops fsl_pamu_ops = {
+static const struct iommu_ops fsl_pamu_ops = {
.domain_init = fsl_pamu_domain_init,
.domain_destroy = fsl_pamu_domain_destroy,
.attach_dev = fsl_pamu_attach_device,
@@ -1155,7 +1090,7 @@ static struct iommu_ops fsl_pamu_ops = {
.remove_device = fsl_pamu_remove_device,
};
-int pamu_domain_init()
+int pamu_domain_init(void)
{
int ret = 0;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 51b6b77dc3e5..d1f5caad04f9 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -45,7 +45,6 @@
#include <asm/iommu.h>
#include "irq_remapping.h"
-#include "pci.h"
#define ROOT_SIZE VTD_PAGE_SIZE
#define CONTEXT_SIZE VTD_PAGE_SIZE
@@ -304,7 +303,7 @@ static inline bool dma_pte_present(struct dma_pte *pte)
static inline bool dma_pte_superpage(struct dma_pte *pte)
{
- return (pte->val & (1 << 7));
+ return (pte->val & DMA_PTE_LARGE_PAGE);
}
static inline int first_pte_in_page(struct dma_pte *pte)
@@ -321,16 +320,13 @@ static inline int first_pte_in_page(struct dma_pte *pte)
static struct dmar_domain *si_domain;
static int hw_pass_through = 1;
-/* devices under the same p2p bridge are owned in one domain */
-#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
-
/* domain represents a virtual machine, more than one devices
* across iommus may be owned in one domain, e.g. kvm guest.
*/
-#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1)
+#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 0)
/* si_domain contains mulitple devices */
-#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2)
+#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
/* define the limit of IOMMUs supported in each domain */
#ifdef CONFIG_X86
@@ -429,6 +425,8 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
struct device *dev);
static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
struct device *dev);
+static int domain_detach_iommu(struct dmar_domain *domain,
+ struct intel_iommu *iommu);
#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
int dmar_disabled = 0;
@@ -451,7 +449,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
static DEFINE_SPINLOCK(device_domain_lock);
static LIST_HEAD(device_domain_list);
-static struct iommu_ops intel_iommu_ops;
+static const struct iommu_ops intel_iommu_ops;
static int __init intel_iommu_setup(char *str)
{
@@ -540,6 +538,24 @@ void free_iova_mem(struct iova *iova)
kmem_cache_free(iommu_iova_cache, iova);
}
+static inline int domain_type_is_vm(struct dmar_domain *domain)
+{
+ return domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE;
+}
+
+static inline int domain_type_is_vm_or_si(struct dmar_domain *domain)
+{
+ return domain->flags & (DOMAIN_FLAG_VIRTUAL_MACHINE |
+ DOMAIN_FLAG_STATIC_IDENTITY);
+}
+
+static inline int domain_pfn_supported(struct dmar_domain *domain,
+ unsigned long pfn)
+{
+ int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+
+ return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
+}
static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
{
@@ -580,9 +596,7 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
int iommu_id;
/* si_domain and vm domain should not get here. */
- BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
- BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY);
-
+ BUG_ON(domain_type_is_vm_or_si(domain));
iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
return NULL;
@@ -619,50 +633,56 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
rcu_read_unlock();
}
-static void domain_update_iommu_snooping(struct dmar_domain *domain)
+static int domain_update_iommu_snooping(struct intel_iommu *skip)
{
- int i;
-
- domain->iommu_snooping = 1;
+ struct dmar_drhd_unit *drhd;
+ struct intel_iommu *iommu;
+ int ret = 1;
- for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
- if (!ecap_sc_support(g_iommus[i]->ecap)) {
- domain->iommu_snooping = 0;
- break;
+ rcu_read_lock();
+ for_each_active_iommu(iommu, drhd) {
+ if (iommu != skip) {
+ if (!ecap_sc_support(iommu->ecap)) {
+ ret = 0;
+ break;
+ }
}
}
+ rcu_read_unlock();
+
+ return ret;
}
-static void domain_update_iommu_superpage(struct dmar_domain *domain)
+static int domain_update_iommu_superpage(struct intel_iommu *skip)
{
struct dmar_drhd_unit *drhd;
- struct intel_iommu *iommu = NULL;
+ struct intel_iommu *iommu;
int mask = 0xf;
if (!intel_iommu_superpage) {
- domain->iommu_superpage = 0;
- return;
+ return 0;
}
/* set iommu_superpage to the smallest common denominator */
rcu_read_lock();
for_each_active_iommu(iommu, drhd) {
- mask &= cap_super_page_val(iommu->cap);
- if (!mask) {
- break;
+ if (iommu != skip) {
+ mask &= cap_super_page_val(iommu->cap);
+ if (!mask)
+ break;
}
}
rcu_read_unlock();
- domain->iommu_superpage = fls(mask);
+ return fls(mask);
}
/* Some capabilities may be different across iommus */
static void domain_update_iommu_cap(struct dmar_domain *domain)
{
domain_update_iommu_coherency(domain);
- domain_update_iommu_snooping(domain);
- domain_update_iommu_superpage(domain);
+ domain->iommu_snooping = domain_update_iommu_snooping(NULL);
+ domain->iommu_superpage = domain_update_iommu_superpage(NULL);
}
static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
@@ -671,7 +691,7 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf
struct intel_iommu *iommu;
struct device *tmp;
struct pci_dev *ptmp, *pdev = NULL;
- u16 segment;
+ u16 segment = 0;
int i;
if (dev_is_pci(dev)) {
@@ -816,14 +836,13 @@ out:
static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
unsigned long pfn, int *target_level)
{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
struct dma_pte *parent, *pte = NULL;
int level = agaw_to_level(domain->agaw);
int offset;
BUG_ON(!domain->pgd);
- if (addr_width < BITS_PER_LONG && pfn >> addr_width)
+ if (!domain_pfn_supported(domain, pfn))
/* Address beyond IOMMU's addressing capabilities. */
return NULL;
@@ -849,13 +868,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
- if (cmpxchg64(&pte->val, 0ULL, pteval)) {
+ if (cmpxchg64(&pte->val, 0ULL, pteval))
/* Someone else set it while we were thinking; use theirs. */
free_pgtable_page(tmp_page);
- } else {
- dma_pte_addr(pte);
+ else
domain_flush_cache(domain, pte, sizeof(*pte));
- }
}
if (level == 1)
break;
@@ -892,7 +909,7 @@ static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
break;
}
- if (pte->val & DMA_PTE_LARGE_PAGE) {
+ if (dma_pte_superpage(pte)) {
*large_page = total;
return pte;
}
@@ -908,12 +925,11 @@ static void dma_pte_clear_range(struct dmar_domain *domain,
unsigned long start_pfn,
unsigned long last_pfn)
{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
unsigned int large_page = 1;
struct dma_pte *first_pte, *pte;
- BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
- BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+ BUG_ON(!domain_pfn_supported(domain, start_pfn));
+ BUG_ON(!domain_pfn_supported(domain, last_pfn));
BUG_ON(start_pfn > last_pfn);
/* we don't need lock here; nobody else touches the iova range */
@@ -974,12 +990,12 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
unsigned long start_pfn,
unsigned long last_pfn)
{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
-
- BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
- BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+ BUG_ON(!domain_pfn_supported(domain, start_pfn));
+ BUG_ON(!domain_pfn_supported(domain, last_pfn));
BUG_ON(start_pfn > last_pfn);
+ dma_pte_clear_range(domain, start_pfn, last_pfn);
+
/* We don't need lock here; nobody else touches the iova range */
dma_pte_free_level(domain, agaw_to_level(domain->agaw),
domain->pgd, 0, start_pfn, last_pfn);
@@ -1077,11 +1093,10 @@ struct page *domain_unmap(struct dmar_domain *domain,
unsigned long start_pfn,
unsigned long last_pfn)
{
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
struct page *freelist = NULL;
- BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
- BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
+ BUG_ON(!domain_pfn_supported(domain, start_pfn));
+ BUG_ON(!domain_pfn_supported(domain, last_pfn));
BUG_ON(start_pfn > last_pfn);
/* we don't need lock here; nobody else touches the iova range */
@@ -1275,7 +1290,8 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
spin_lock_irqsave(&device_domain_lock, flags);
list_for_each_entry(info, &domain->devices, link)
- if (info->bus == bus && info->devfn == devfn) {
+ if (info->iommu == iommu && info->bus == bus &&
+ info->devfn == devfn) {
found = 1;
break;
}
@@ -1384,7 +1400,7 @@ static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
}
-static int iommu_enable_translation(struct intel_iommu *iommu)
+static void iommu_enable_translation(struct intel_iommu *iommu)
{
u32 sts;
unsigned long flags;
@@ -1398,10 +1414,9 @@ static int iommu_enable_translation(struct intel_iommu *iommu)
readl, (sts & DMA_GSTS_TES), sts);
raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
- return 0;
}
-static int iommu_disable_translation(struct intel_iommu *iommu)
+static void iommu_disable_translation(struct intel_iommu *iommu)
{
u32 sts;
unsigned long flag;
@@ -1415,7 +1430,6 @@ static int iommu_disable_translation(struct intel_iommu *iommu)
readl, (!(sts & DMA_GSTS_TES)), sts);
raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
- return 0;
}
@@ -1462,8 +1476,7 @@ static int iommu_init_domains(struct intel_iommu *iommu)
static void free_dmar_iommu(struct intel_iommu *iommu)
{
struct dmar_domain *domain;
- int i, count;
- unsigned long flags;
+ int i;
if ((iommu->domains) && (iommu->domain_ids)) {
for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
@@ -1476,11 +1489,8 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
domain = iommu->domains[i];
clear_bit(i, iommu->domain_ids);
-
- spin_lock_irqsave(&domain->iommu_lock, flags);
- count = --domain->iommu_count;
- spin_unlock_irqrestore(&domain->iommu_lock, flags);
- if (count == 0)
+ if (domain_detach_iommu(domain, iommu) == 0 &&
+ !domain_type_is_vm(domain))
domain_exit(domain);
}
}
@@ -1499,7 +1509,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
free_context_table(iommu);
}
-static struct dmar_domain *alloc_domain(bool vm)
+static struct dmar_domain *alloc_domain(int flags)
{
/* domain id for virtual machine, it won't be set in context */
static atomic_t vm_domid = ATOMIC_INIT(0);
@@ -1509,46 +1519,62 @@ static struct dmar_domain *alloc_domain(bool vm)
if (!domain)
return NULL;
+ memset(domain, 0, sizeof(*domain));
domain->nid = -1;
- domain->iommu_count = 0;
- memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp));
- domain->flags = 0;
+ domain->flags = flags;
spin_lock_init(&domain->iommu_lock);
INIT_LIST_HEAD(&domain->devices);
- if (vm) {
+ if (flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
domain->id = atomic_inc_return(&vm_domid);
- domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
- }
return domain;
}
-static int iommu_attach_domain(struct dmar_domain *domain,
- struct intel_iommu *iommu)
+static int __iommu_attach_domain(struct dmar_domain *domain,
+ struct intel_iommu *iommu)
{
int num;
unsigned long ndomains;
- unsigned long flags;
ndomains = cap_ndoms(iommu->cap);
-
- spin_lock_irqsave(&iommu->lock, flags);
-
num = find_first_zero_bit(iommu->domain_ids, ndomains);
- if (num >= ndomains) {
- spin_unlock_irqrestore(&iommu->lock, flags);
- printk(KERN_ERR "IOMMU: no free domain ids\n");
- return -ENOMEM;
+ if (num < ndomains) {
+ set_bit(num, iommu->domain_ids);
+ iommu->domains[num] = domain;
+ } else {
+ num = -ENOSPC;
}
- domain->id = num;
- domain->iommu_count++;
- set_bit(num, iommu->domain_ids);
- set_bit(iommu->seq_id, domain->iommu_bmp);
- iommu->domains[num] = domain;
+ return num;
+}
+
+static int iommu_attach_domain(struct dmar_domain *domain,
+ struct intel_iommu *iommu)
+{
+ int num;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ num = __iommu_attach_domain(domain, iommu);
spin_unlock_irqrestore(&iommu->lock, flags);
+ if (num < 0)
+ pr_err("IOMMU: no free domain ids\n");
- return 0;
+ return num;
+}
+
+static int iommu_attach_vm_domain(struct dmar_domain *domain,
+ struct intel_iommu *iommu)
+{
+ int num;
+ unsigned long ndomains;
+
+ ndomains = cap_ndoms(iommu->cap);
+ for_each_set_bit(num, iommu->domain_ids, ndomains)
+ if (iommu->domains[num] == domain)
+ return num;
+
+ return __iommu_attach_domain(domain, iommu);
}
static void iommu_detach_domain(struct dmar_domain *domain,
@@ -1558,17 +1584,53 @@ static void iommu_detach_domain(struct dmar_domain *domain,
int num, ndomains;
spin_lock_irqsave(&iommu->lock, flags);
- ndomains = cap_ndoms(iommu->cap);
- for_each_set_bit(num, iommu->domain_ids, ndomains) {
- if (iommu->domains[num] == domain) {
- clear_bit(num, iommu->domain_ids);
- iommu->domains[num] = NULL;
- break;
+ if (domain_type_is_vm_or_si(domain)) {
+ ndomains = cap_ndoms(iommu->cap);
+ for_each_set_bit(num, iommu->domain_ids, ndomains) {
+ if (iommu->domains[num] == domain) {
+ clear_bit(num, iommu->domain_ids);
+ iommu->domains[num] = NULL;
+ break;
+ }
}
+ } else {
+ clear_bit(domain->id, iommu->domain_ids);
+ iommu->domains[domain->id] = NULL;
}
spin_unlock_irqrestore(&iommu->lock, flags);
}
+static void domain_attach_iommu(struct dmar_domain *domain,
+ struct intel_iommu *iommu)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&domain->iommu_lock, flags);
+ if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
+ domain->iommu_count++;
+ if (domain->iommu_count == 1)
+ domain->nid = iommu->node;
+ domain_update_iommu_cap(domain);
+ }
+ spin_unlock_irqrestore(&domain->iommu_lock, flags);
+}
+
+static int domain_detach_iommu(struct dmar_domain *domain,
+ struct intel_iommu *iommu)
+{
+ unsigned long flags;
+ int count = INT_MAX;
+
+ spin_lock_irqsave(&domain->iommu_lock, flags);
+ if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
+ count = --domain->iommu_count;
+ domain_update_iommu_cap(domain);
+ }
+ spin_unlock_irqrestore(&domain->iommu_lock, flags);
+
+ return count;
+}
+
static struct iova_domain reserved_iova_list;
static struct lock_class_key reserved_rbtree_key;
@@ -1706,9 +1768,7 @@ static void domain_exit(struct dmar_domain *domain)
/* clear attached or cached domains */
rcu_read_lock();
for_each_active_iommu(iommu, drhd)
- if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
- test_bit(iommu->seq_id, domain->iommu_bmp))
- iommu_detach_domain(domain, iommu);
+ iommu_detach_domain(domain, iommu);
rcu_read_unlock();
dma_free_pagelist(freelist);
@@ -1723,8 +1783,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
struct context_entry *context;
unsigned long flags;
struct dma_pte *pgd;
- unsigned long num;
- unsigned long ndomains;
int id;
int agaw;
struct device_domain_info *info = NULL;
@@ -1748,31 +1806,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
id = domain->id;
pgd = domain->pgd;
- if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
- domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) {
- int found = 0;
-
- /* find an available domain id for this device in iommu */
- ndomains = cap_ndoms(iommu->cap);
- for_each_set_bit(num, iommu->domain_ids, ndomains) {
- if (iommu->domains[num] == domain) {
- id = num;
- found = 1;
- break;
- }
- }
-
- if (found == 0) {
- num = find_first_zero_bit(iommu->domain_ids, ndomains);
- if (num >= ndomains) {
+ if (domain_type_is_vm_or_si(domain)) {
+ if (domain_type_is_vm(domain)) {
+ id = iommu_attach_vm_domain(domain, iommu);
+ if (id < 0) {
spin_unlock_irqrestore(&iommu->lock, flags);
- printk(KERN_ERR "IOMMU: no free domain ids\n");
+ pr_err("IOMMU: no free domain ids\n");
return -EFAULT;
}
-
- set_bit(num, iommu->domain_ids);
- iommu->domains[num] = domain;
- id = num;
}
/* Skip top levels of page tables for
@@ -1824,72 +1865,68 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
(((u16)bus) << 8) | devfn,
DMA_CCMD_MASK_NOBIT,
DMA_CCMD_DEVICE_INVL);
- iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH);
+ iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH);
} else {
iommu_flush_write_buffer(iommu);
}
iommu_enable_dev_iotlb(info);
spin_unlock_irqrestore(&iommu->lock, flags);
- spin_lock_irqsave(&domain->iommu_lock, flags);
- if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
- domain->iommu_count++;
- if (domain->iommu_count == 1)
- domain->nid = iommu->node;
- domain_update_iommu_cap(domain);
- }
- spin_unlock_irqrestore(&domain->iommu_lock, flags);
+ domain_attach_iommu(domain, iommu);
+
return 0;
}
+struct domain_context_mapping_data {
+ struct dmar_domain *domain;
+ struct intel_iommu *iommu;
+ int translation;
+};
+
+static int domain_context_mapping_cb(struct pci_dev *pdev,
+ u16 alias, void *opaque)
+{
+ struct domain_context_mapping_data *data = opaque;
+
+ return domain_context_mapping_one(data->domain, data->iommu,
+ PCI_BUS_NUM(alias), alias & 0xff,
+ data->translation);
+}
+
static int
domain_context_mapping(struct dmar_domain *domain, struct device *dev,
int translation)
{
- int ret;
- struct pci_dev *pdev, *tmp, *parent;
struct intel_iommu *iommu;
u8 bus, devfn;
+ struct domain_context_mapping_data data;
iommu = device_to_iommu(dev, &bus, &devfn);
if (!iommu)
return -ENODEV;
- ret = domain_context_mapping_one(domain, iommu, bus, devfn,
- translation);
- if (ret || !dev_is_pci(dev))
- return ret;
-
- /* dependent device mapping */
- pdev = to_pci_dev(dev);
- tmp = pci_find_upstream_pcie_bridge(pdev);
- if (!tmp)
- return 0;
- /* Secondary interface's bus number and devfn 0 */
- parent = pdev->bus->self;
- while (parent != tmp) {
- ret = domain_context_mapping_one(domain, iommu,
- parent->bus->number,
- parent->devfn, translation);
- if (ret)
- return ret;
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
- return domain_context_mapping_one(domain, iommu,
- tmp->subordinate->number, 0,
- translation);
- else /* this is a legacy PCI bridge */
- return domain_context_mapping_one(domain, iommu,
- tmp->bus->number,
- tmp->devfn,
+ if (!dev_is_pci(dev))
+ return domain_context_mapping_one(domain, iommu, bus, devfn,
translation);
+
+ data.domain = domain;
+ data.iommu = iommu;
+ data.translation = translation;
+
+ return pci_for_each_dma_alias(to_pci_dev(dev),
+ &domain_context_mapping_cb, &data);
+}
+
+static int domain_context_mapped_cb(struct pci_dev *pdev,
+ u16 alias, void *opaque)
+{
+ struct intel_iommu *iommu = opaque;
+
+ return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
}
static int domain_context_mapped(struct device *dev)
{
- int ret;
- struct pci_dev *pdev, *tmp, *parent;
struct intel_iommu *iommu;
u8 bus, devfn;
@@ -1897,30 +1934,11 @@ static int domain_context_mapped(struct device *dev)
if (!iommu)
return -ENODEV;
- ret = device_context_mapped(iommu, bus, devfn);
- if (!ret || !dev_is_pci(dev))
- return ret;
+ if (!dev_is_pci(dev))
+ return device_context_mapped(iommu, bus, devfn);
- /* dependent device mapping */
- pdev = to_pci_dev(dev);
- tmp = pci_find_upstream_pcie_bridge(pdev);
- if (!tmp)
- return ret;
- /* Secondary interface's bus number and devfn 0 */
- parent = pdev->bus->self;
- while (parent != tmp) {
- ret = device_context_mapped(iommu, parent->bus->number,
- parent->devfn);
- if (!ret)
- return ret;
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp))
- return device_context_mapped(iommu, tmp->subordinate->number,
- 0);
- else
- return device_context_mapped(iommu, tmp->bus->number,
- tmp->devfn);
+ return !pci_for_each_dma_alias(to_pci_dev(dev),
+ domain_context_mapped_cb, iommu);
}
/* Returns a number of VTD pages, but aligned to MM page size */
@@ -1965,12 +1983,11 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
{
struct dma_pte *first_pte = NULL, *pte = NULL;
phys_addr_t uninitialized_var(pteval);
- int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
unsigned long sg_res;
unsigned int largepage_lvl = 0;
unsigned long lvl_pages = 0;
- BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
+ BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
return -EINVAL;
@@ -2004,12 +2021,14 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
/* It is large page*/
if (largepage_lvl > 1) {
pteval |= DMA_PTE_LARGE_PAGE;
- /* Ensure that old small page tables are removed to make room
- for superpage, if they exist. */
- dma_pte_clear_range(domain, iov_pfn,
- iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
+ lvl_pages = lvl_to_nr_pages(largepage_lvl);
+ /*
+ * Ensure that old small page tables are
+ * removed to make room for superpage,
+ * if they exist.
+ */
dma_pte_free_pagetable(domain, iov_pfn,
- iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1);
+ iov_pfn + lvl_pages - 1);
} else {
pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
}
@@ -2102,31 +2121,20 @@ static inline void unlink_domain_info(struct device_domain_info *info)
static void domain_remove_dev_info(struct dmar_domain *domain)
{
- struct device_domain_info *info;
- unsigned long flags, flags2;
+ struct device_domain_info *info, *tmp;
+ unsigned long flags;
spin_lock_irqsave(&device_domain_lock, flags);
- while (!list_empty(&domain->devices)) {
- info = list_entry(domain->devices.next,
- struct device_domain_info, link);
+ list_for_each_entry_safe(info, tmp, &domain->devices, link) {
unlink_domain_info(info);
spin_unlock_irqrestore(&device_domain_lock, flags);
iommu_disable_dev_iotlb(info);
iommu_detach_dev(info->iommu, info->bus, info->devfn);
- if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
+ if (domain_type_is_vm(domain)) {
iommu_detach_dependent_devices(info->iommu, info->dev);
- /* clear this iommu in iommu_bmp, update iommu count
- * and capabilities
- */
- spin_lock_irqsave(&domain->iommu_lock, flags2);
- if (test_and_clear_bit(info->iommu->seq_id,
- domain->iommu_bmp)) {
- domain->iommu_count--;
- domain_update_iommu_cap(domain);
- }
- spin_unlock_irqrestore(&domain->iommu_lock, flags2);
+ domain_detach_iommu(domain, info->iommu);
}
free_devinfo_mem(info);
@@ -2181,8 +2189,6 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
info->dev = dev;
info->domain = domain;
info->iommu = iommu;
- if (!dev)
- domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
spin_lock_irqsave(&device_domain_lock, flags);
if (dev)
@@ -2209,79 +2215,86 @@ static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu,
return domain;
}
+static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+ *(u16 *)opaque = alias;
+ return 0;
+}
+
/* domain is initialized */
static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
{
- struct dmar_domain *domain, *free = NULL;
- struct intel_iommu *iommu = NULL;
+ struct dmar_domain *domain, *tmp;
+ struct intel_iommu *iommu;
struct device_domain_info *info;
- struct pci_dev *dev_tmp = NULL;
+ u16 dma_alias;
unsigned long flags;
- u8 bus, devfn, bridge_bus, bridge_devfn;
+ u8 bus, devfn;
domain = find_domain(dev);
if (domain)
return domain;
+ iommu = device_to_iommu(dev, &bus, &devfn);
+ if (!iommu)
+ return NULL;
+
if (dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
- u16 segment;
- segment = pci_domain_nr(pdev->bus);
- dev_tmp = pci_find_upstream_pcie_bridge(pdev);
- if (dev_tmp) {
- if (pci_is_pcie(dev_tmp)) {
- bridge_bus = dev_tmp->subordinate->number;
- bridge_devfn = 0;
- } else {
- bridge_bus = dev_tmp->bus->number;
- bridge_devfn = dev_tmp->devfn;
- }
- spin_lock_irqsave(&device_domain_lock, flags);
- info = dmar_search_domain_by_dev_info(segment,
- bridge_bus,
- bridge_devfn);
- if (info) {
- iommu = info->iommu;
- domain = info->domain;
- }
- spin_unlock_irqrestore(&device_domain_lock, flags);
- /* pcie-pci bridge already has a domain, uses it */
- if (info)
- goto found_domain;
+ pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
+ PCI_BUS_NUM(dma_alias),
+ dma_alias & 0xff);
+ if (info) {
+ iommu = info->iommu;
+ domain = info->domain;
}
- }
+ spin_unlock_irqrestore(&device_domain_lock, flags);
- iommu = device_to_iommu(dev, &bus, &devfn);
- if (!iommu)
- goto error;
+ /* DMA alias already has a domain, uses it */
+ if (info)
+ goto found_domain;
+ }
/* Allocate and initialize new domain for the device */
- domain = alloc_domain(false);
+ domain = alloc_domain(0);
if (!domain)
- goto error;
- if (iommu_attach_domain(domain, iommu)) {
+ return NULL;
+ domain->id = iommu_attach_domain(domain, iommu);
+ if (domain->id < 0) {
free_domain_mem(domain);
- domain = NULL;
- goto error;
+ return NULL;
}
- free = domain;
- if (domain_init(domain, gaw))
- goto error;
+ domain_attach_iommu(domain, iommu);
+ if (domain_init(domain, gaw)) {
+ domain_exit(domain);
+ return NULL;
+ }
+
+ /* register PCI DMA alias device */
+ if (dev_is_pci(dev)) {
+ tmp = dmar_insert_dev_info(iommu, PCI_BUS_NUM(dma_alias),
+ dma_alias & 0xff, NULL, domain);
+
+ if (!tmp || tmp != domain) {
+ domain_exit(domain);
+ domain = tmp;
+ }
- /* register pcie-to-pci device */
- if (dev_tmp) {
- domain = dmar_insert_dev_info(iommu, bridge_bus, bridge_devfn,
- NULL, domain);
if (!domain)
- goto error;
+ return NULL;
}
found_domain:
- domain = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
-error:
- if (free != domain)
- domain_exit(free);
+ tmp = dmar_insert_dev_info(iommu, bus, devfn, dev, domain);
+
+ if (!tmp || tmp != domain) {
+ domain_exit(domain);
+ domain = tmp;
+ }
return domain;
}
@@ -2405,6 +2418,7 @@ static inline void iommu_prepare_isa(void)
printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
"floppy might not work\n");
+ pci_dev_put(pdev);
}
#else
static inline void iommu_prepare_isa(void)
@@ -2420,19 +2434,25 @@ static int __init si_domain_init(int hw)
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu;
int nid, ret = 0;
+ bool first = true;
- si_domain = alloc_domain(false);
+ si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
if (!si_domain)
return -EFAULT;
- si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
-
for_each_active_iommu(iommu, drhd) {
ret = iommu_attach_domain(si_domain, iommu);
- if (ret) {
+ if (ret < 0) {
+ domain_exit(si_domain);
+ return -EFAULT;
+ } else if (first) {
+ si_domain->id = ret;
+ first = false;
+ } else if (si_domain->id != ret) {
domain_exit(si_domain);
return -EFAULT;
}
+ domain_attach_iommu(si_domain, iommu);
}
if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
@@ -2523,22 +2543,46 @@ static bool device_has_rmrr(struct device *dev)
return false;
}
+/*
+ * There are a couple cases where we need to restrict the functionality of
+ * devices associated with RMRRs. The first is when evaluating a device for
+ * identity mapping because problems exist when devices are moved in and out
+ * of domains and their respective RMRR information is lost. This means that
+ * a device with associated RMRRs will never be in a "passthrough" domain.
+ * The second is use of the device through the IOMMU API. This interface
+ * expects to have full control of the IOVA space for the device. We cannot
+ * satisfy both the requirement that RMRR access is maintained and have an
+ * unencumbered IOVA space. We also have no ability to quiesce the device's
+ * use of the RMRR space or even inform the IOMMU API user of the restriction.
+ * We therefore prevent devices associated with an RMRR from participating in
+ * the IOMMU API, which eliminates them from device assignment.
+ *
+ * In both cases we assume that PCI USB devices with RMRRs have them largely
+ * for historical reasons and that the RMRR space is not actively used post
+ * boot. This exclusion may change if vendors begin to abuse it.
+ */
+static bool device_is_rmrr_locked(struct device *dev)
+{
+ if (!device_has_rmrr(dev))
+ return false;
+
+ if (dev_is_pci(dev)) {
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ return false;
+ }
+
+ return true;
+}
+
static int iommu_should_identity_map(struct device *dev, int startup)
{
if (dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
- /*
- * We want to prevent any device associated with an RMRR from
- * getting placed into the SI Domain. This is done because
- * problems exist when devices are moved in and out of domains
- * and their respective RMRR info is lost. We exempt USB devices
- * from this process due to their usage of RMRRs that are known
- * to not be needed after BIOS hand-off to OS.
- */
- if (device_has_rmrr(dev) &&
- (pdev->class >> 8) != PCI_CLASS_SERIAL_USB)
+ if (device_is_rmrr_locked(dev))
return 0;
if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
@@ -2850,11 +2894,7 @@ static int __init init_dmars(void)
iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
- ret = iommu_enable_translation(iommu);
- if (ret)
- goto free_iommu;
-
+ iommu_enable_translation(iommu);
iommu_disable_protect_mem_regions(iommu);
}
@@ -3091,10 +3131,10 @@ static void flush_unmaps(void)
/* On real hardware multiple invalidations are expensive */
if (cap_caching_mode(iommu->cap))
iommu_flush_iotlb_psi(iommu, domain->id,
- iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1,
+ iova->pfn_lo, iova_size(iova),
!deferred_flush[i].freelist[j], 0);
else {
- mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1));
+ mask = ilog2(mm_to_dma_pfn(iova_size(iova)));
iommu_flush_dev_iotlb(deferred_flush[i].domain[j],
(uint64_t)iova->pfn_lo << PAGE_SHIFT, mask);
}
@@ -3144,9 +3184,7 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova, struct page *f
spin_unlock_irqrestore(&async_umap_flush_lock, flags);
}
-static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+static void intel_unmap(struct device *dev, dma_addr_t dev_addr)
{
struct dmar_domain *domain;
unsigned long start_pfn, last_pfn;
@@ -3190,6 +3228,13 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
}
}
+static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ intel_unmap(dev, dev_addr);
+}
+
static void *intel_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
struct dma_attrs *attrs)
@@ -3246,7 +3291,7 @@ static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
size = PAGE_ALIGN(size);
order = get_order(size);
- intel_unmap_page(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
+ intel_unmap(dev, dma_handle);
if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
__free_pages(page, order);
}
@@ -3255,43 +3300,7 @@ static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
- struct dmar_domain *domain;
- unsigned long start_pfn, last_pfn;
- struct iova *iova;
- struct intel_iommu *iommu;
- struct page *freelist;
-
- if (iommu_no_mapping(dev))
- return;
-
- domain = find_domain(dev);
- BUG_ON(!domain);
-
- iommu = domain_get_iommu(domain);
-
- iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
- if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
- (unsigned long long)sglist[0].dma_address))
- return;
-
- start_pfn = mm_to_dma_pfn(iova->pfn_lo);
- last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
-
- freelist = domain_unmap(domain, start_pfn, last_pfn);
-
- if (intel_iommu_strict) {
- iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
- last_pfn - start_pfn + 1, !freelist, 0);
- /* free iova */
- __free_iova(&domain->iovad, iova);
- dma_free_pagelist(freelist);
- } else {
- add_unmap(domain, iova, freelist);
- /*
- * queue up the release of the unmap to save the 1/6th of the
- * cpu used up by the iotlb flush operation...
- */
- }
+ intel_unmap(dev, sglist[0].dma_address);
}
static int intel_nontranslate_map_sg(struct device *hddev,
@@ -3355,13 +3364,8 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
if (unlikely(ret)) {
- /* clear the page */
- dma_pte_clear_range(domain, start_vpfn,
- start_vpfn + size - 1);
- /* free page tables */
dma_pte_free_pagetable(domain, start_vpfn,
start_vpfn + size - 1);
- /* free iova */
__free_iova(&domain->iovad, iova);
return 0;
}
@@ -3568,10 +3572,8 @@ static int init_iommu_hw(void)
iommu->flush.flush_context(iommu, 0, 0, 0,
DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0,
- DMA_TLB_GLOBAL_FLUSH);
- if (iommu_enable_translation(iommu))
- return 1;
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+ iommu_enable_translation(iommu);
iommu_disable_protect_mem_regions(iommu);
}
@@ -3873,9 +3875,7 @@ static int device_notifier(struct notifier_block *nb,
down_read(&dmar_global_lock);
domain_remove_one_dev_info(domain, dev);
- if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
- !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
- list_empty(&domain->devices))
+ if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices))
domain_exit(domain);
up_read(&dmar_global_lock);
@@ -3935,8 +3935,7 @@ static int intel_iommu_memory_notifier(struct notifier_block *nb,
rcu_read_lock();
for_each_active_iommu(iommu, drhd)
iommu_flush_iotlb_psi(iommu, si_domain->id,
- iova->pfn_lo,
- iova->pfn_hi - iova->pfn_lo + 1,
+ iova->pfn_lo, iova_size(iova),
!freelist, 0);
rcu_read_unlock();
dma_free_pagelist(freelist);
@@ -3955,6 +3954,63 @@ static struct notifier_block intel_iommu_memory_nb = {
.priority = 0
};
+
+static ssize_t intel_iommu_show_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_iommu *iommu = dev_get_drvdata(dev);
+ u32 ver = readl(iommu->reg + DMAR_VER_REG);
+ return sprintf(buf, "%d:%d\n",
+ DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
+}
+static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
+
+static ssize_t intel_iommu_show_address(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_iommu *iommu = dev_get_drvdata(dev);
+ return sprintf(buf, "%llx\n", iommu->reg_phys);
+}
+static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
+
+static ssize_t intel_iommu_show_cap(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_iommu *iommu = dev_get_drvdata(dev);
+ return sprintf(buf, "%llx\n", iommu->cap);
+}
+static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
+
+static ssize_t intel_iommu_show_ecap(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_iommu *iommu = dev_get_drvdata(dev);
+ return sprintf(buf, "%llx\n", iommu->ecap);
+}
+static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
+
+static struct attribute *intel_iommu_attrs[] = {
+ &dev_attr_version.attr,
+ &dev_attr_address.attr,
+ &dev_attr_cap.attr,
+ &dev_attr_ecap.attr,
+ NULL,
+};
+
+static struct attribute_group intel_iommu_group = {
+ .name = "intel-iommu",
+ .attrs = intel_iommu_attrs,
+};
+
+const struct attribute_group *intel_iommu_groups[] = {
+ &intel_iommu_group,
+ NULL,
+};
+
int __init intel_iommu_init(void)
{
int ret = -ENODEV;
@@ -4026,6 +4082,11 @@ int __init intel_iommu_init(void)
init_iommu_pm_ops();
+ for_each_active_iommu(iommu, drhd)
+ iommu->iommu_dev = iommu_device_create(NULL, iommu,
+ intel_iommu_groups,
+ iommu->name);
+
bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
bus_register_notifier(&pci_bus_type, &device_nb);
if (si_domain && !hw_pass_through)
@@ -4044,33 +4105,27 @@ out_free_dmar:
return ret;
}
+static int iommu_detach_dev_cb(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+ struct intel_iommu *iommu = opaque;
+
+ iommu_detach_dev(iommu, PCI_BUS_NUM(alias), alias & 0xff);
+ return 0;
+}
+
+/*
+ * NB - intel-iommu lacks any sort of reference counting for the users of
+ * dependent devices. If multiple endpoints have intersecting dependent
+ * devices, unbinding the driver from any one of them will possibly leave
+ * the others unable to operate.
+ */
static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
struct device *dev)
{
- struct pci_dev *tmp, *parent, *pdev;
-
if (!iommu || !dev || !dev_is_pci(dev))
return;
- pdev = to_pci_dev(dev);
-
- /* dependent device detach */
- tmp = pci_find_upstream_pcie_bridge(pdev);
- /* Secondary interface's bus number and devfn 0 */
- if (tmp) {
- parent = pdev->bus->self;
- while (parent != tmp) {
- iommu_detach_dev(iommu, parent->bus->number,
- parent->devfn);
- parent = parent->bus->self;
- }
- if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */
- iommu_detach_dev(iommu,
- tmp->subordinate->number, 0);
- else /* this is a legacy PCI bridge */
- iommu_detach_dev(iommu, tmp->bus->number,
- tmp->devfn);
- }
+ pci_for_each_dma_alias(to_pci_dev(dev), &iommu_detach_dev_cb, iommu);
}
static void domain_remove_one_dev_info(struct dmar_domain *domain,
@@ -4117,20 +4172,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
spin_unlock_irqrestore(&device_domain_lock, flags);
if (found == 0) {
- unsigned long tmp_flags;
- spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
- clear_bit(iommu->seq_id, domain->iommu_bmp);
- domain->iommu_count--;
- domain_update_iommu_cap(domain);
- spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
-
- if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
- !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
- spin_lock_irqsave(&iommu->lock, tmp_flags);
- clear_bit(domain->id, iommu->domain_ids);
- iommu->domains[domain->id] = NULL;
- spin_unlock_irqrestore(&iommu->lock, tmp_flags);
- }
+ domain_detach_iommu(domain, iommu);
+ if (!domain_type_is_vm_or_si(domain))
+ iommu_detach_domain(domain, iommu);
}
}
@@ -4150,7 +4194,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
domain->iommu_snooping = 0;
domain->iommu_superpage = 0;
domain->max_addr = 0;
- domain->nid = -1;
/* always allocate the top pgd */
domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
@@ -4164,7 +4207,7 @@ static int intel_iommu_domain_init(struct iommu_domain *domain)
{
struct dmar_domain *dmar_domain;
- dmar_domain = alloc_domain(true);
+ dmar_domain = alloc_domain(DOMAIN_FLAG_VIRTUAL_MACHINE);
if (!dmar_domain) {
printk(KERN_ERR
"intel_iommu_domain_init: dmar_domain == NULL\n");
@@ -4202,14 +4245,18 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
int addr_width;
u8 bus, devfn;
+ if (device_is_rmrr_locked(dev)) {
+ dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
+ return -EPERM;
+ }
+
/* normally dev is not mapped */
if (unlikely(domain_context_mapped(dev))) {
struct dmar_domain *old_domain;
old_domain = find_domain(dev);
if (old_domain) {
- if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE ||
- dmar_domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)
+ if (domain_type_is_vm_or_si(dmar_domain))
domain_remove_one_dev_info(old_domain, dev);
else
domain_remove_dev_info(old_domain);
@@ -4373,99 +4420,42 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
return 0;
}
-#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
-
static int intel_iommu_add_device(struct device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_dev *bridge, *dma_pdev = NULL;
+ struct intel_iommu *iommu;
struct iommu_group *group;
- int ret;
u8 bus, devfn;
- if (!device_to_iommu(dev, &bus, &devfn))
+ iommu = device_to_iommu(dev, &bus, &devfn);
+ if (!iommu)
return -ENODEV;
- bridge = pci_find_upstream_pcie_bridge(pdev);
- if (bridge) {
- if (pci_is_pcie(bridge))
- dma_pdev = pci_get_domain_bus_and_slot(
- pci_domain_nr(pdev->bus),
- bridge->subordinate->number, 0);
- if (!dma_pdev)
- dma_pdev = pci_dev_get(bridge);
- } else
- dma_pdev = pci_dev_get(pdev);
-
- /* Account for quirked devices */
- swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev));
+ iommu_device_link(iommu->iommu_dev, dev);
- /*
- * If it's a multifunction device that does not support our
- * required ACS flags, add to the same group as lowest numbered
- * function that also does not suport the required ACS flags.
- */
- if (dma_pdev->multifunction &&
- !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) {
- u8 i, slot = PCI_SLOT(dma_pdev->devfn);
-
- for (i = 0; i < 8; i++) {
- struct pci_dev *tmp;
+ group = iommu_group_get_for_dev(dev);
- tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i));
- if (!tmp)
- continue;
-
- if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) {
- swap_pci_ref(&dma_pdev, tmp);
- break;
- }
- pci_dev_put(tmp);
- }
- }
-
- /*
- * Devices on the root bus go through the iommu. If that's not us,
- * find the next upstream device and test ACS up to the root bus.
- * Finding the next device may require skipping virtual buses.
- */
- while (!pci_is_root_bus(dma_pdev->bus)) {
- struct pci_bus *bus = dma_pdev->bus;
-
- while (!bus->self) {
- if (!pci_is_root_bus(bus))
- bus = bus->parent;
- else
- goto root_bus;
- }
-
- if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
- break;
-
- swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));
- }
-
-root_bus:
- group = iommu_group_get(&dma_pdev->dev);
- pci_dev_put(dma_pdev);
- if (!group) {
- group = iommu_group_alloc();
- if (IS_ERR(group))
- return PTR_ERR(group);
- }
-
- ret = iommu_group_add_device(group, dev);
+ if (IS_ERR(group))
+ return PTR_ERR(group);
iommu_group_put(group);
- return ret;
+ return 0;
}
static void intel_iommu_remove_device(struct device *dev)
{
+ struct intel_iommu *iommu;
+ u8 bus, devfn;
+
+ iommu = device_to_iommu(dev, &bus, &devfn);
+ if (!iommu)
+ return;
+
iommu_group_remove_device(dev);
+
+ iommu_device_unlink(iommu->iommu_dev, dev);
}
-static struct iommu_ops intel_iommu_ops = {
+static const struct iommu_ops intel_iommu_ops = {
.domain_init = intel_iommu_domain_init,
.domain_destroy = intel_iommu_domain_destroy,
.attach_dev = intel_iommu_attach_device,
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 9b174893f0f5..0df41f6264f5 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -70,6 +70,11 @@ static int get_irte(int irq, struct irte *entry)
raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
+ if (unlikely(!irq_iommu->iommu)) {
+ raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ return -1;
+ }
+
index = irq_iommu->irte_index + irq_iommu->sub_handle;
*entry = *(irq_iommu->iommu->ir_table->base + index);
@@ -369,29 +374,52 @@ static int set_hpet_sid(struct irte *irte, u8 id)
return 0;
}
+struct set_msi_sid_data {
+ struct pci_dev *pdev;
+ u16 alias;
+};
+
+static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+ struct set_msi_sid_data *data = opaque;
+
+ data->pdev = pdev;
+ data->alias = alias;
+
+ return 0;
+}
+
static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
{
- struct pci_dev *bridge;
+ struct set_msi_sid_data data;
if (!irte || !dev)
return -1;
- /* PCIe device or Root Complex integrated PCI device */
- if (pci_is_pcie(dev) || !dev->bus->parent) {
- set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
- (dev->bus->number << 8) | dev->devfn);
- return 0;
- }
+ pci_for_each_dma_alias(dev, set_msi_sid_cb, &data);
- bridge = pci_find_upstream_pcie_bridge(dev);
- if (bridge) {
- if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
- set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
- (bridge->bus->number << 8) | dev->bus->number);
- else /* this is a legacy PCI bridge */
- set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
- (bridge->bus->number << 8) | bridge->devfn);
- }
+ /*
+ * DMA alias provides us with a PCI device and alias. The only case
+ * where the it will return an alias on a different bus than the
+ * device is the case of a PCIe-to-PCI bridge, where the alias is for
+ * the subordinate bus. In this case we can only verify the bus.
+ *
+ * If the alias device is on a different bus than our source device
+ * then we have a topology based alias, use it.
+ *
+ * Otherwise, the alias is for a device DMA quirk and we cannot
+ * assume that MSI uses the same requester ID. Therefore use the
+ * original device.
+ */
+ if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number)
+ set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
+ PCI_DEVID(PCI_BUS_NUM(data.alias),
+ dev->bus->number));
+ else if (data.pdev->bus->number != dev->bus->number)
+ set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias);
+ else
+ set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+ PCI_DEVID(dev->bus->number, dev->devfn));
return 0;
}
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
new file mode 100644
index 000000000000..39b2d9127dbf
--- /dev/null
+++ b/drivers/iommu/iommu-sysfs.c
@@ -0,0 +1,134 @@
+/*
+ * IOMMU sysfs class support
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All rights reserved.
+ * Author: Alex Williamson <alex.williamson@redhat.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/device.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/*
+ * We provide a common class "devices" group which initially has no attributes.
+ * As devices are added to the IOMMU, we'll add links to the group.
+ */
+static struct attribute *devices_attr[] = {
+ NULL,
+};
+
+static const struct attribute_group iommu_devices_attr_group = {
+ .name = "devices",
+ .attrs = devices_attr,
+};
+
+static const struct attribute_group *iommu_dev_groups[] = {
+ &iommu_devices_attr_group,
+ NULL,
+};
+
+static void iommu_release_device(struct device *dev)
+{
+ kfree(dev);
+}
+
+static struct class iommu_class = {
+ .name = "iommu",
+ .dev_release = iommu_release_device,
+ .dev_groups = iommu_dev_groups,
+};
+
+static int __init iommu_dev_init(void)
+{
+ return class_register(&iommu_class);
+}
+postcore_initcall(iommu_dev_init);
+
+/*
+ * Create an IOMMU device and return a pointer to it. IOMMU specific
+ * attributes can be provided as an attribute group, allowing a unique
+ * namespace per IOMMU type.
+ */
+struct device *iommu_device_create(struct device *parent, void *drvdata,
+ const struct attribute_group **groups,
+ const char *fmt, ...)
+{
+ struct device *dev;
+ va_list vargs;
+ int ret;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ device_initialize(dev);
+
+ dev->class = &iommu_class;
+ dev->parent = parent;
+ dev->groups = groups;
+ dev_set_drvdata(dev, drvdata);
+
+ va_start(vargs, fmt);
+ ret = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
+ va_end(vargs);
+ if (ret)
+ goto error;
+
+ ret = device_add(dev);
+ if (ret)
+ goto error;
+
+ return dev;
+
+error:
+ put_device(dev);
+ return ERR_PTR(ret);
+}
+
+void iommu_device_destroy(struct device *dev)
+{
+ if (!dev || IS_ERR(dev))
+ return;
+
+ device_unregister(dev);
+}
+
+/*
+ * IOMMU drivers can indicate a device is managed by a given IOMMU using
+ * this interface. A link to the device will be created in the "devices"
+ * directory of the IOMMU device in sysfs and an "iommu" link will be
+ * created under the linked device, pointing back at the IOMMU device.
+ */
+int iommu_device_link(struct device *dev, struct device *link)
+{
+ int ret;
+
+ if (!dev || IS_ERR(dev))
+ return -ENODEV;
+
+ ret = sysfs_add_link_to_group(&dev->kobj, "devices",
+ &link->kobj, dev_name(link));
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_link_nowarn(&link->kobj, &dev->kobj, "iommu");
+ if (ret)
+ sysfs_remove_link_from_group(&dev->kobj, "devices",
+ dev_name(link));
+
+ return ret;
+}
+
+void iommu_device_unlink(struct device *dev, struct device *link)
+{
+ if (!dev || IS_ERR(dev))
+ return;
+
+ sysfs_remove_link(&link->kobj, "iommu");
+ sysfs_remove_link_from_group(&dev->kobj, "devices", dev_name(link));
+}
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index e5555fcfe703..169836020208 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -29,12 +29,17 @@
#include <linux/idr.h>
#include <linux/notifier.h>
#include <linux/err.h>
+#include <linux/pci.h>
#include <trace/events/iommu.h>
static struct kset *iommu_group_kset;
static struct ida iommu_group_ida;
static struct mutex iommu_group_mutex;
+struct iommu_callback_data {
+ const struct iommu_ops *ops;
+};
+
struct iommu_group {
struct kobject kobj;
struct kobject *devices_kobj;
@@ -514,9 +519,191 @@ int iommu_group_id(struct iommu_group *group)
}
EXPORT_SYMBOL_GPL(iommu_group_id);
+/*
+ * To consider a PCI device isolated, we require ACS to support Source
+ * Validation, Request Redirection, Completer Redirection, and Upstream
+ * Forwarding. This effectively means that devices cannot spoof their
+ * requester ID, requests and completions cannot be redirected, and all
+ * transactions are forwarded upstream, even as it passes through a
+ * bridge where the target device is downstream.
+ */
+#define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
+
+struct group_for_pci_data {
+ struct pci_dev *pdev;
+ struct iommu_group *group;
+};
+
+/*
+ * DMA alias iterator callback, return the last seen device. Stop and return
+ * the IOMMU group if we find one along the way.
+ */
+static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+ struct group_for_pci_data *data = opaque;
+
+ data->pdev = pdev;
+ data->group = iommu_group_get(&pdev->dev);
+
+ return data->group != NULL;
+}
+
+/*
+ * Use standard PCI bus topology, isolation features, and DMA alias quirks
+ * to find or create an IOMMU group for a device.
+ */
+static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
+{
+ struct group_for_pci_data data;
+ struct pci_bus *bus;
+ struct iommu_group *group = NULL;
+ struct pci_dev *tmp;
+
+ /*
+ * Find the upstream DMA alias for the device. A device must not
+ * be aliased due to topology in order to have its own IOMMU group.
+ * If we find an alias along the way that already belongs to a
+ * group, use it.
+ */
+ if (pci_for_each_dma_alias(pdev, get_pci_alias_or_group, &data))
+ return data.group;
+
+ pdev = data.pdev;
+
+ /*
+ * Continue upstream from the point of minimum IOMMU granularity
+ * due to aliases to the point where devices are protected from
+ * peer-to-peer DMA by PCI ACS. Again, if we find an existing
+ * group, use it.
+ */
+ for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) {
+ if (!bus->self)
+ continue;
+
+ if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))
+ break;
+
+ pdev = bus->self;
+
+ group = iommu_group_get(&pdev->dev);
+ if (group)
+ return group;
+ }
+
+ /*
+ * Next we need to consider DMA alias quirks. If one device aliases
+ * to another, they should be grouped together. It's theoretically
+ * possible that aliases could create chains of devices where each
+ * device aliases another device. If we then factor in multifunction
+ * ACS grouping requirements, each alias could incorporate a new slot
+ * with multiple functions, each with aliases. This is all extremely
+ * unlikely as DMA alias quirks are typically only used for PCIe
+ * devices where we usually have a single slot per bus. Furthermore,
+ * the alias quirk is usually to another function within the slot
+ * (and ACS multifunction is not supported) or to a different slot
+ * that doesn't physically exist. The likely scenario is therefore
+ * that everything on the bus gets grouped together. To reduce the
+ * problem space, share the IOMMU group for all devices on the bus
+ * if a DMA alias quirk is present on the bus.
+ */
+ tmp = NULL;
+ for_each_pci_dev(tmp) {
+ if (tmp->bus != pdev->bus ||
+ !(tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN))
+ continue;
+
+ pci_dev_put(tmp);
+ tmp = NULL;
+
+ /* We have an alias quirk, search for an existing group */
+ for_each_pci_dev(tmp) {
+ struct iommu_group *group_tmp;
+
+ if (tmp->bus != pdev->bus)
+ continue;
+
+ group_tmp = iommu_group_get(&tmp->dev);
+ if (!group) {
+ group = group_tmp;
+ continue;
+ }
+
+ if (group_tmp) {
+ WARN_ON(group != group_tmp);
+ iommu_group_put(group_tmp);
+ }
+ }
+
+ return group ? group : iommu_group_alloc();
+ }
+
+ /*
+ * Non-multifunction devices or multifunction devices supporting
+ * ACS get their own group.
+ */
+ if (!pdev->multifunction || pci_acs_enabled(pdev, REQ_ACS_FLAGS))
+ return iommu_group_alloc();
+
+ /*
+ * Multifunction devices not supporting ACS share a group with other
+ * similar devices in the same slot.
+ */
+ tmp = NULL;
+ for_each_pci_dev(tmp) {
+ if (tmp == pdev || tmp->bus != pdev->bus ||
+ PCI_SLOT(tmp->devfn) != PCI_SLOT(pdev->devfn) ||
+ pci_acs_enabled(tmp, REQ_ACS_FLAGS))
+ continue;
+
+ group = iommu_group_get(&tmp->dev);
+ if (group) {
+ pci_dev_put(tmp);
+ return group;
+ }
+ }
+
+ /* No shared group found, allocate new */
+ return iommu_group_alloc();
+}
+
+/**
+ * iommu_group_get_for_dev - Find or create the IOMMU group for a device
+ * @dev: target device
+ *
+ * This function is intended to be called by IOMMU drivers and extended to
+ * support common, bus-defined algorithms when determining or creating the
+ * IOMMU group for a device. On success, the caller will hold a reference
+ * to the returned IOMMU group, which will already include the provided
+ * device. The reference should be released with iommu_group_put().
+ */
+struct iommu_group *iommu_group_get_for_dev(struct device *dev)
+{
+ struct iommu_group *group = ERR_PTR(-EIO);
+ int ret;
+
+ group = iommu_group_get(dev);
+ if (group)
+ return group;
+
+ if (dev_is_pci(dev))
+ group = iommu_group_get_for_pci_dev(to_pci_dev(dev));
+
+ if (IS_ERR(group))
+ return group;
+
+ ret = iommu_group_add_device(group, dev);
+ if (ret) {
+ iommu_group_put(group);
+ return ERR_PTR(ret);
+ }
+
+ return group;
+}
+
static int add_iommu_group(struct device *dev, void *data)
{
- struct iommu_ops *ops = data;
+ struct iommu_callback_data *cb = data;
+ const struct iommu_ops *ops = cb->ops;
if (!ops->add_device)
return -ENODEV;
@@ -532,7 +719,7 @@ static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
- struct iommu_ops *ops = dev->bus->iommu_ops;
+ const struct iommu_ops *ops = dev->bus->iommu_ops;
struct iommu_group *group;
unsigned long group_action = 0;
@@ -585,10 +772,14 @@ static struct notifier_block iommu_bus_nb = {
.notifier_call = iommu_bus_notifier,
};
-static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
+static void iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
{
+ struct iommu_callback_data cb = {
+ .ops = ops,
+ };
+
bus_register_notifier(bus, &iommu_bus_nb);
- bus_for_each_dev(bus, NULL, ops, add_iommu_group);
+ bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
}
/**
@@ -604,7 +795,7 @@ static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops)
* is set up. With this function the iommu-driver can set the iommu-ops
* afterwards.
*/
-int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops)
+int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops)
{
if (bus->iommu_ops != NULL)
return -EBUSY;
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 53cde086e83b..7dab5cbcc775 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -1120,7 +1120,7 @@ static void ipmmu_remove_device(struct device *dev)
dev->archdata.iommu = NULL;
}
-static struct iommu_ops ipmmu_ops = {
+static const struct iommu_ops ipmmu_ops = {
.domain_init = ipmmu_domain_init,
.domain_destroy = ipmmu_domain_destroy,
.attach_dev = ipmmu_attach_device,
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index f5ff657f49fa..49f41d6e02f1 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -674,7 +674,7 @@ fail:
return 0;
}
-static struct iommu_ops msm_iommu_ops = {
+static const struct iommu_ops msm_iommu_ops = {
.domain_init = msm_iommu_domain_init,
.domain_destroy = msm_iommu_domain_destroy,
.attach_dev = msm_iommu_attach_dev,
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 80fffba7f12d..531658d17333 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -213,116 +213,6 @@ static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
return bytes;
}
-static ssize_t debug_read_mmap(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = file->private_data;
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- char *p, *buf;
- struct iovm_struct *tmp;
- int uninitialized_var(i);
- ssize_t bytes;
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- p = buf;
-
- p += sprintf(p, "%-3s %-8s %-8s %6s %8s\n",
- "No", "start", "end", "size", "flags");
- p += sprintf(p, "-------------------------------------------------\n");
-
- mutex_lock(&iommu_debug_lock);
-
- list_for_each_entry(tmp, &obj->mmap, list) {
- size_t len;
- const char *str = "%3d %08x-%08x %6x %8x\n";
- const int maxcol = 39;
-
- len = tmp->da_end - tmp->da_start;
- p += snprintf(p, maxcol, str,
- i, tmp->da_start, tmp->da_end, len, tmp->flags);
-
- if (PAGE_SIZE - (p - buf) < maxcol)
- break;
- i++;
- }
-
- bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-
- mutex_unlock(&iommu_debug_lock);
- free_page((unsigned long)buf);
-
- return bytes;
-}
-
-static ssize_t debug_read_mem(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = file->private_data;
- char *p, *buf;
- struct iovm_struct *area;
- ssize_t bytes;
-
- count = min_t(ssize_t, count, PAGE_SIZE);
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- p = buf;
-
- mutex_lock(&iommu_debug_lock);
-
- area = omap_find_iovm_area(dev, (u32)ppos);
- if (!area) {
- bytes = -EINVAL;
- goto err_out;
- }
- memcpy(p, area->va, count);
- p += count;
-
- bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-err_out:
- mutex_unlock(&iommu_debug_lock);
- free_page((unsigned long)buf);
-
- return bytes;
-}
-
-static ssize_t debug_write_mem(struct file *file, const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct device *dev = file->private_data;
- struct iovm_struct *area;
- char *p, *buf;
-
- count = min_t(size_t, count, PAGE_SIZE);
-
- buf = (char *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- p = buf;
-
- mutex_lock(&iommu_debug_lock);
-
- if (copy_from_user(p, userbuf, count)) {
- count = -EFAULT;
- goto err_out;
- }
-
- area = omap_find_iovm_area(dev, (u32)ppos);
- if (!area) {
- count = -EINVAL;
- goto err_out;
- }
- memcpy(area->va, p, count);
-err_out:
- mutex_unlock(&iommu_debug_lock);
- free_page((unsigned long)buf);
-
- return count;
-}
-
#define DEBUG_FOPS(name) \
static const struct file_operations debug_##name##_fops = { \
.open = simple_open, \
@@ -342,8 +232,6 @@ DEBUG_FOPS_RO(ver);
DEBUG_FOPS_RO(regs);
DEBUG_FOPS_RO(tlb);
DEBUG_FOPS(pagetable);
-DEBUG_FOPS_RO(mmap);
-DEBUG_FOPS(mem);
#define __DEBUG_ADD_FILE(attr, mode) \
{ \
@@ -389,8 +277,6 @@ static int iommu_debug_register(struct device *dev, void *data)
DEBUG_ADD_FILE_RO(regs);
DEBUG_ADD_FILE_RO(tlb);
DEBUG_ADD_FILE(pagetable);
- DEBUG_ADD_FILE_RO(mmap);
- DEBUG_ADD_FILE(mem);
return 0;
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 895af06a667f..e202b0c24120 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -959,31 +959,18 @@ static int omap_iommu_probe(struct platform_device *pdev)
return err;
if (obj->nr_tlb_entries != 32 && obj->nr_tlb_entries != 8)
return -EINVAL;
- /*
- * da_start and da_end are needed for omap-iovmm, so hardcode
- * these values as used by OMAP3 ISP - the only user for
- * omap-iovmm
- */
- obj->da_start = 0;
- obj->da_end = 0xfffff000;
if (of_find_property(of, "ti,iommu-bus-err-back", NULL))
obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN;
} else {
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
- obj->da_start = pdata->da_start;
- obj->da_end = pdata->da_end;
}
- if (obj->da_end <= obj->da_start)
- return -EINVAL;
obj->dev = &pdev->dev;
obj->ctx = (void *)obj + sizeof(*obj);
spin_lock_init(&obj->iommu_lock);
- mutex_init(&obj->mmap_lock);
spin_lock_init(&obj->page_table_lock);
- INIT_LIST_HEAD(&obj->mmap);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
obj->regbase = devm_ioremap_resource(obj->dev, res);
@@ -1291,7 +1278,7 @@ static void omap_iommu_remove_device(struct device *dev)
kfree(arch_data);
}
-static struct iommu_ops omap_iommu_ops = {
+static const struct iommu_ops omap_iommu_ops = {
.domain_init = omap_iommu_domain_init,
.domain_destroy = omap_iommu_domain_destroy,
.attach_dev = omap_iommu_attach_dev,
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index ea920c3e94ff..1275a822934b 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -46,12 +46,7 @@ struct omap_iommu {
int nr_tlb_entries;
- struct list_head mmap;
- struct mutex mmap_lock; /* protect mmap */
-
void *ctx; /* iommu context: registres saved area */
- u32 da_start;
- u32 da_end;
int has_bus_err_back;
};
@@ -154,9 +149,12 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
#define MMU_RAM_PADDR_MASK \
((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
+#define MMU_RAM_ENDIAN_SHIFT 9
#define MMU_RAM_ENDIAN_MASK (1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ENDIAN_LITTLE (0 << MMU_RAM_ENDIAN_SHIFT)
#define MMU_RAM_ENDIAN_BIG (1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ELSZ_SHIFT 7
#define MMU_RAM_ELSZ_MASK (3 << MMU_RAM_ELSZ_SHIFT)
#define MMU_RAM_ELSZ_8 (0 << MMU_RAM_ELSZ_SHIFT)
#define MMU_RAM_ELSZ_16 (1 << MMU_RAM_ELSZ_SHIFT)
diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c
deleted file mode 100644
index d14725984153..000000000000
--- a/drivers/iommu/omap-iovmm.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * omap iommu: simple virtual address space management
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/device.h>
-#include <linux/scatterlist.h>
-#include <linux/iommu.h>
-#include <linux/omap-iommu.h>
-#include <linux/platform_data/iommu-omap.h>
-
-#include <asm/cacheflush.h>
-#include <asm/mach/map.h>
-
-#include "omap-iopgtable.h"
-#include "omap-iommu.h"
-
-/*
- * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
- *
- * lower 16 bit is used for h/w and upper 16 bit is for s/w.
- */
-#define IOVMF_SW_SHIFT 16
-
-/*
- * iovma: h/w flags derived from cam and ram attribute
- */
-#define IOVMF_CAM_MASK (~((1 << 10) - 1))
-#define IOVMF_RAM_MASK (~IOVMF_CAM_MASK)
-
-#define IOVMF_PGSZ_MASK (3 << 0)
-#define IOVMF_PGSZ_1M MMU_CAM_PGSZ_1M
-#define IOVMF_PGSZ_64K MMU_CAM_PGSZ_64K
-#define IOVMF_PGSZ_4K MMU_CAM_PGSZ_4K
-#define IOVMF_PGSZ_16M MMU_CAM_PGSZ_16M
-
-#define IOVMF_ENDIAN_MASK (1 << 9)
-#define IOVMF_ENDIAN_BIG MMU_RAM_ENDIAN_BIG
-
-#define IOVMF_ELSZ_MASK (3 << 7)
-#define IOVMF_ELSZ_16 MMU_RAM_ELSZ_16
-#define IOVMF_ELSZ_32 MMU_RAM_ELSZ_32
-#define IOVMF_ELSZ_NONE MMU_RAM_ELSZ_NONE
-
-#define IOVMF_MIXED_MASK (1 << 6)
-#define IOVMF_MIXED MMU_RAM_MIXED
-
-/*
- * iovma: s/w flags, used for mapping and umapping internally.
- */
-#define IOVMF_MMIO (1 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC (2 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC_MASK (3 << IOVMF_SW_SHIFT)
-
-/* "superpages" is supported just with physically linear pages */
-#define IOVMF_DISCONT (1 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR (2 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR_MASK (3 << (2 + IOVMF_SW_SHIFT))
-
-#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT))
-
-static struct kmem_cache *iovm_area_cachep;
-
-/* return the offset of the first scatterlist entry in a sg table */
-static unsigned int sgtable_offset(const struct sg_table *sgt)
-{
- if (!sgt || !sgt->nents)
- return 0;
-
- return sgt->sgl->offset;
-}
-
-/* return total bytes of sg buffers */
-static size_t sgtable_len(const struct sg_table *sgt)
-{
- unsigned int i, total = 0;
- struct scatterlist *sg;
-
- if (!sgt)
- return 0;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- size_t bytes;
-
- bytes = sg->length + sg->offset;
-
- if (!iopgsz_ok(bytes)) {
- pr_err("%s: sg[%d] not iommu pagesize(%u %u)\n",
- __func__, i, bytes, sg->offset);
- return 0;
- }
-
- if (i && sg->offset) {
- pr_err("%s: sg[%d] offset not allowed in internal entries\n",
- __func__, i);
- return 0;
- }
-
- total += bytes;
- }
-
- return total;
-}
-#define sgtable_ok(x) (!!sgtable_len(x))
-
-static unsigned max_alignment(u32 addr)
-{
- int i;
- unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
- for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++)
- ;
- return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0;
-}
-
-/*
- * calculate the optimal number sg elements from total bytes based on
- * iommu superpages
- */
-static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
-{
- unsigned nr_entries = 0, ent_sz;
-
- if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
- pr_err("%s: wrong size %08x\n", __func__, bytes);
- return 0;
- }
-
- while (bytes) {
- ent_sz = max_alignment(da | pa);
- ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes));
- nr_entries++;
- da += ent_sz;
- pa += ent_sz;
- bytes -= ent_sz;
- }
-
- return nr_entries;
-}
-
-/* allocate and initialize sg_table header(a kind of 'superblock') */
-static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
- u32 da, u32 pa)
-{
- unsigned int nr_entries;
- int err;
- struct sg_table *sgt;
-
- if (!bytes)
- return ERR_PTR(-EINVAL);
-
- if (!IS_ALIGNED(bytes, PAGE_SIZE))
- return ERR_PTR(-EINVAL);
-
- if (flags & IOVMF_LINEAR) {
- nr_entries = sgtable_nents(bytes, da, pa);
- if (!nr_entries)
- return ERR_PTR(-EINVAL);
- } else
- nr_entries = bytes / PAGE_SIZE;
-
- sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
- if (!sgt)
- return ERR_PTR(-ENOMEM);
-
- err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
- if (err) {
- kfree(sgt);
- return ERR_PTR(err);
- }
-
- pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
-
- return sgt;
-}
-
-/* free sg_table header(a kind of superblock) */
-static void sgtable_free(struct sg_table *sgt)
-{
- if (!sgt)
- return;
-
- sg_free_table(sgt);
- kfree(sgt);
-
- pr_debug("%s: sgt:%p\n", __func__, sgt);
-}
-
-/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
-static void *vmap_sg(const struct sg_table *sgt)
-{
- u32 va;
- size_t total;
- unsigned int i;
- struct scatterlist *sg;
- struct vm_struct *new;
- const struct mem_type *mtype;
-
- mtype = get_mem_type(MT_DEVICE);
- if (!mtype)
- return ERR_PTR(-EINVAL);
-
- total = sgtable_len(sgt);
- if (!total)
- return ERR_PTR(-EINVAL);
-
- new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
- if (!new)
- return ERR_PTR(-ENOMEM);
- va = (u32)new->addr;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- size_t bytes;
- u32 pa;
- int err;
-
- pa = sg_phys(sg) - sg->offset;
- bytes = sg->length + sg->offset;
-
- BUG_ON(bytes != PAGE_SIZE);
-
- err = ioremap_page(va, pa, mtype);
- if (err)
- goto err_out;
-
- va += bytes;
- }
-
- flush_cache_vmap((unsigned long)new->addr,
- (unsigned long)(new->addr + total));
- return new->addr;
-
-err_out:
- WARN_ON(1); /* FIXME: cleanup some mpu mappings */
- vunmap(new->addr);
- return ERR_PTR(-EAGAIN);
-}
-
-static inline void vunmap_sg(const void *va)
-{
- vunmap(va);
-}
-
-static struct iovm_struct *__find_iovm_area(struct omap_iommu *obj,
- const u32 da)
-{
- struct iovm_struct *tmp;
-
- list_for_each_entry(tmp, &obj->mmap, list) {
- if ((da >= tmp->da_start) && (da < tmp->da_end)) {
- size_t len;
-
- len = tmp->da_end - tmp->da_start;
-
- dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
- __func__, tmp->da_start, da, tmp->da_end, len,
- tmp->flags);
-
- return tmp;
- }
- }
-
- return NULL;
-}
-
-/**
- * omap_find_iovm_area - find iovma which includes @da
- * @dev: client device
- * @da: iommu device virtual address
- *
- * Find the existing iovma starting at @da
- */
-struct iovm_struct *omap_find_iovm_area(struct device *dev, u32 da)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- struct iovm_struct *area;
-
- mutex_lock(&obj->mmap_lock);
- area = __find_iovm_area(obj, da);
- mutex_unlock(&obj->mmap_lock);
-
- return area;
-}
-EXPORT_SYMBOL_GPL(omap_find_iovm_area);
-
-/*
- * This finds the hole(area) which fits the requested address and len
- * in iovmas mmap, and returns the new allocated iovma.
- */
-static struct iovm_struct *alloc_iovm_area(struct omap_iommu *obj, u32 da,
- size_t bytes, u32 flags)
-{
- struct iovm_struct *new, *tmp;
- u32 start, prev_end, alignment;
-
- if (!obj || !bytes)
- return ERR_PTR(-EINVAL);
-
- start = da;
- alignment = PAGE_SIZE;
-
- if (~flags & IOVMF_DA_FIXED) {
- /* Don't map address 0 */
- start = obj->da_start ? obj->da_start : alignment;
-
- if (flags & IOVMF_LINEAR)
- alignment = iopgsz_max(bytes);
- start = roundup(start, alignment);
- } else if (start < obj->da_start || start > obj->da_end ||
- obj->da_end - start < bytes) {
- return ERR_PTR(-EINVAL);
- }
-
- tmp = NULL;
- if (list_empty(&obj->mmap))
- goto found;
-
- prev_end = 0;
- list_for_each_entry(tmp, &obj->mmap, list) {
-
- if (prev_end > start)
- break;
-
- if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
- goto found;
-
- if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
- start = roundup(tmp->da_end + 1, alignment);
-
- prev_end = tmp->da_end;
- }
-
- if ((start >= prev_end) && (obj->da_end - start >= bytes))
- goto found;
-
- dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
- __func__, da, bytes, flags);
-
- return ERR_PTR(-EINVAL);
-
-found:
- new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
- if (!new)
- return ERR_PTR(-ENOMEM);
-
- new->iommu = obj;
- new->da_start = start;
- new->da_end = start + bytes;
- new->flags = flags;
-
- /*
- * keep ascending order of iovmas
- */
- if (tmp)
- list_add_tail(&new->list, &tmp->list);
- else
- list_add(&new->list, &obj->mmap);
-
- dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
- __func__, new->da_start, start, new->da_end, bytes, flags);
-
- return new;
-}
-
-static void free_iovm_area(struct omap_iommu *obj, struct iovm_struct *area)
-{
- size_t bytes;
-
- BUG_ON(!obj || !area);
-
- bytes = area->da_end - area->da_start;
-
- dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
- __func__, area->da_start, area->da_end, bytes, area->flags);
-
- list_del(&area->list);
- kmem_cache_free(iovm_area_cachep, area);
-}
-
-/**
- * omap_da_to_va - convert (d) to (v)
- * @dev: client device
- * @da: iommu device virtual address
- * @va: mpu virtual address
- *
- * Returns mpu virtual addr which corresponds to a given device virtual addr
- */
-void *omap_da_to_va(struct device *dev, u32 da)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- void *va = NULL;
- struct iovm_struct *area;
-
- mutex_lock(&obj->mmap_lock);
-
- area = __find_iovm_area(obj, da);
- if (!area) {
- dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
- goto out;
- }
- va = area->va;
-out:
- mutex_unlock(&obj->mmap_lock);
-
- return va;
-}
-EXPORT_SYMBOL_GPL(omap_da_to_va);
-
-static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
-{
- unsigned int i;
- struct scatterlist *sg;
- void *va = _va;
- void *va_end;
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- struct page *pg;
- const size_t bytes = PAGE_SIZE;
-
- /*
- * iommu 'superpage' isn't supported with 'omap_iommu_vmalloc()'
- */
- pg = vmalloc_to_page(va);
- BUG_ON(!pg);
- sg_set_page(sg, pg, bytes, 0);
-
- va += bytes;
- }
-
- va_end = _va + PAGE_SIZE * i;
-}
-
-static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
-{
- /*
- * Actually this is not necessary at all, just exists for
- * consistency of the code readability.
- */
- BUG_ON(!sgt);
-}
-
-/* create 'da' <-> 'pa' mapping from 'sgt' */
-static int map_iovm_area(struct iommu_domain *domain, struct iovm_struct *new,
- const struct sg_table *sgt, u32 flags)
-{
- int err;
- unsigned int i, j;
- struct scatterlist *sg;
- u32 da = new->da_start;
-
- if (!domain || !sgt)
- return -EINVAL;
-
- BUG_ON(!sgtable_ok(sgt));
-
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- u32 pa;
- size_t bytes;
-
- pa = sg_phys(sg) - sg->offset;
- bytes = sg->length + sg->offset;
-
- flags &= ~IOVMF_PGSZ_MASK;
-
- if (bytes_to_iopgsz(bytes) < 0)
- goto err_out;
-
- pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
- i, da, pa, bytes);
-
- err = iommu_map(domain, da, pa, bytes, flags);
- if (err)
- goto err_out;
-
- da += bytes;
- }
- return 0;
-
-err_out:
- da = new->da_start;
-
- for_each_sg(sgt->sgl, sg, i, j) {
- size_t bytes;
-
- bytes = sg->length + sg->offset;
-
- /* ignore failures.. we're already handling one */
- iommu_unmap(domain, da, bytes);
-
- da += bytes;
- }
- return err;
-}
-
-/* release 'da' <-> 'pa' mapping */
-static void unmap_iovm_area(struct iommu_domain *domain, struct omap_iommu *obj,
- struct iovm_struct *area)
-{
- u32 start;
- size_t total = area->da_end - area->da_start;
- const struct sg_table *sgt = area->sgt;
- struct scatterlist *sg;
- int i;
- size_t unmapped;
-
- BUG_ON(!sgtable_ok(sgt));
- BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
-
- start = area->da_start;
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- size_t bytes;
-
- bytes = sg->length + sg->offset;
-
- unmapped = iommu_unmap(domain, start, bytes);
- if (unmapped < bytes)
- break;
-
- dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
- __func__, start, bytes, area->flags);
-
- BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
- total -= bytes;
- start += bytes;
- }
- BUG_ON(total);
-}
-
-/* template function for all unmapping */
-static struct sg_table *unmap_vm_area(struct iommu_domain *domain,
- struct omap_iommu *obj, const u32 da,
- void (*fn)(const void *), u32 flags)
-{
- struct sg_table *sgt = NULL;
- struct iovm_struct *area;
-
- if (!IS_ALIGNED(da, PAGE_SIZE)) {
- dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
- return NULL;
- }
-
- mutex_lock(&obj->mmap_lock);
-
- area = __find_iovm_area(obj, da);
- if (!area) {
- dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da);
- goto out;
- }
-
- if ((area->flags & flags) != flags) {
- dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
- area->flags);
- goto out;
- }
- sgt = (struct sg_table *)area->sgt;
-
- unmap_iovm_area(domain, obj, area);
-
- fn(area->va);
-
- dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
- area->da_start, da, area->da_end,
- area->da_end - area->da_start, area->flags);
-
- free_iovm_area(obj, area);
-out:
- mutex_unlock(&obj->mmap_lock);
-
- return sgt;
-}
-
-static u32 map_iommu_region(struct iommu_domain *domain, struct omap_iommu *obj,
- u32 da, const struct sg_table *sgt, void *va,
- size_t bytes, u32 flags)
-{
- int err = -ENOMEM;
- struct iovm_struct *new;
-
- mutex_lock(&obj->mmap_lock);
-
- new = alloc_iovm_area(obj, da, bytes, flags);
- if (IS_ERR(new)) {
- err = PTR_ERR(new);
- goto err_alloc_iovma;
- }
- new->va = va;
- new->sgt = sgt;
-
- if (map_iovm_area(domain, new, sgt, new->flags))
- goto err_map;
-
- mutex_unlock(&obj->mmap_lock);
-
- dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
- __func__, new->da_start, bytes, new->flags, va);
-
- return new->da_start;
-
-err_map:
- free_iovm_area(obj, new);
-err_alloc_iovma:
- mutex_unlock(&obj->mmap_lock);
- return err;
-}
-
-static inline u32
-__iommu_vmap(struct iommu_domain *domain, struct omap_iommu *obj,
- u32 da, const struct sg_table *sgt,
- void *va, size_t bytes, u32 flags)
-{
- return map_iommu_region(domain, obj, da, sgt, va, bytes, flags);
-}
-
-/**
- * omap_iommu_vmap - (d)-(p)-(v) address mapper
- * @domain: iommu domain
- * @dev: client device
- * @sgt: address of scatter gather table
- * @flags: iovma and page property
- *
- * Creates 1-n-1 mapping with given @sgt and returns @da.
- * All @sgt element must be io page size aligned.
- */
-u32 omap_iommu_vmap(struct iommu_domain *domain, struct device *dev, u32 da,
- const struct sg_table *sgt, u32 flags)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- size_t bytes;
- void *va = NULL;
-
- if (!obj || !obj->dev || !sgt)
- return -EINVAL;
-
- bytes = sgtable_len(sgt);
- if (!bytes)
- return -EINVAL;
- bytes = PAGE_ALIGN(bytes);
-
- if (flags & IOVMF_MMIO) {
- va = vmap_sg(sgt);
- if (IS_ERR(va))
- return PTR_ERR(va);
- }
-
- flags |= IOVMF_DISCONT;
- flags |= IOVMF_MMIO;
-
- da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
- if (IS_ERR_VALUE(da))
- vunmap_sg(va);
-
- return da + sgtable_offset(sgt);
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vmap);
-
-/**
- * omap_iommu_vunmap - release virtual mapping obtained by 'omap_iommu_vmap()'
- * @domain: iommu domain
- * @dev: client device
- * @da: iommu device virtual address
- *
- * Free the iommu virtually contiguous memory area starting at
- * @da, which was returned by 'omap_iommu_vmap()'.
- */
-struct sg_table *
-omap_iommu_vunmap(struct iommu_domain *domain, struct device *dev, u32 da)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- struct sg_table *sgt;
- /*
- * 'sgt' is allocated before 'omap_iommu_vmalloc()' is called.
- * Just returns 'sgt' to the caller to free
- */
- da &= PAGE_MASK;
- sgt = unmap_vm_area(domain, obj, da, vunmap_sg,
- IOVMF_DISCONT | IOVMF_MMIO);
- if (!sgt)
- dev_dbg(obj->dev, "%s: No sgt\n", __func__);
- return sgt;
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vunmap);
-
-/**
- * omap_iommu_vmalloc - (d)-(p)-(v) address allocator and mapper
- * @dev: client device
- * @da: contiguous iommu virtual memory
- * @bytes: allocation size
- * @flags: iovma and page property
- *
- * Allocate @bytes linearly and creates 1-n-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
- */
-u32
-omap_iommu_vmalloc(struct iommu_domain *domain, struct device *dev, u32 da,
- size_t bytes, u32 flags)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- void *va;
- struct sg_table *sgt;
-
- if (!obj || !obj->dev || !bytes)
- return -EINVAL;
-
- bytes = PAGE_ALIGN(bytes);
-
- va = vmalloc(bytes);
- if (!va)
- return -ENOMEM;
-
- flags |= IOVMF_DISCONT;
- flags |= IOVMF_ALLOC;
-
- sgt = sgtable_alloc(bytes, flags, da, 0);
- if (IS_ERR(sgt)) {
- da = PTR_ERR(sgt);
- goto err_sgt_alloc;
- }
- sgtable_fill_vmalloc(sgt, va);
-
- da = __iommu_vmap(domain, obj, da, sgt, va, bytes, flags);
- if (IS_ERR_VALUE(da))
- goto err_iommu_vmap;
-
- return da;
-
-err_iommu_vmap:
- sgtable_drain_vmalloc(sgt);
- sgtable_free(sgt);
-err_sgt_alloc:
- vfree(va);
- return da;
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vmalloc);
-
-/**
- * omap_iommu_vfree - release memory allocated by 'omap_iommu_vmalloc()'
- * @dev: client device
- * @da: iommu device virtual address
- *
- * Frees the iommu virtually continuous memory area starting at
- * @da, as obtained from 'omap_iommu_vmalloc()'.
- */
-void omap_iommu_vfree(struct iommu_domain *domain, struct device *dev,
- const u32 da)
-{
- struct omap_iommu *obj = dev_to_omap_iommu(dev);
- struct sg_table *sgt;
-
- sgt = unmap_vm_area(domain, obj, da, vfree,
- IOVMF_DISCONT | IOVMF_ALLOC);
- if (!sgt)
- dev_dbg(obj->dev, "%s: No sgt\n", __func__);
- sgtable_free(sgt);
-}
-EXPORT_SYMBOL_GPL(omap_iommu_vfree);
-
-static int __init iovmm_init(void)
-{
- const unsigned long flags = SLAB_HWCACHE_ALIGN;
- struct kmem_cache *p;
-
- p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
- flags, NULL);
- if (!p)
- return -ENOMEM;
- iovm_area_cachep = p;
-
- return 0;
-}
-module_init(iovmm_init);
-
-static void __exit iovmm_exit(void)
-{
- kmem_cache_destroy(iovm_area_cachep);
-}
-module_exit(iovmm_exit);
-
-MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/pci.h b/drivers/iommu/pci.h
deleted file mode 100644
index 352d80ae7443..000000000000
--- a/drivers/iommu/pci.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright (C) 2013 Red Hat, Inc.
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- */
-#ifndef __IOMMU_PCI_H
-#define __IOMMU_PCI_H
-
-/* Helper function for swapping pci device reference */
-static inline void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
-{
- pci_dev_put(*from);
- *from = to;
-}
-
-#endif /* __IOMMU_PCI_H */
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c
index 464acda0bbc4..1333e6fb3405 100644
--- a/drivers/iommu/shmobile-iommu.c
+++ b/drivers/iommu/shmobile-iommu.c
@@ -354,7 +354,7 @@ static int shmobile_iommu_add_device(struct device *dev)
return 0;
}
-static struct iommu_ops shmobile_iommu_ops = {
+static const struct iommu_ops shmobile_iommu_ops = {
.domain_init = shmobile_iommu_domain_init,
.domain_destroy = shmobile_iommu_domain_destroy,
.attach_dev = shmobile_iommu_attach_device,
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index dba1a9fd5070..b10a8ecede8e 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -309,7 +309,7 @@ static int gart_iommu_domain_has_cap(struct iommu_domain *domain,
return 0;
}
-static struct iommu_ops gart_iommu_ops = {
+static const struct iommu_ops gart_iommu_ops = {
.domain_init = gart_iommu_domain_init,
.domain_destroy = gart_iommu_domain_destroy,
.attach_dev = gart_iommu_attach_dev,
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 605b5b46a903..3ded3894623c 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -35,7 +35,8 @@
#include <linux/of_iommu.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#include <linux/tegra-ahb.h>
+
+#include <soc/tegra/ahb.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
@@ -947,7 +948,7 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain)
dev_dbg(smmu->dev, "smmu_as@%p\n", as);
}
-static struct iommu_ops smmu_iommu_ops = {
+static const struct iommu_ops smmu_iommu_ops = {
.domain_init = smmu_iommu_domain_init,
.domain_destroy = smmu_iommu_domain_destroy,
.attach_dev = smmu_iommu_attach_dev,
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
index c276fde318e5..de5e32151a1e 100644
--- a/drivers/ipack/carriers/tpci200.c
+++ b/drivers/ipack/carriers/tpci200.c
@@ -618,7 +618,7 @@ static void tpci200_pci_remove(struct pci_dev *dev)
__tpci200_pci_remove(tpci200);
}
-static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
+static const struct pci_device_id tpci200_idtable[] = {
{ TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
TPCI200_SUBDEVICE_ID },
{ 0, },
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index 141094e7c06e..e41bef048c23 100644
--- a/drivers/ipack/devices/ipoctal.c
+++ b/drivers/ipack/devices/ipoctal.c
@@ -177,19 +177,20 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel)
if (channel->nb_bytes == 0)
return;
+ spin_lock(&channel->lock);
value = channel->tty_port.xmit_buf[*pointer_write];
iowrite8(value, &channel->regs->w.thr);
channel->stats.tx++;
(*pointer_write)++;
*pointer_write = *pointer_write % PAGE_SIZE;
channel->nb_bytes--;
+ spin_unlock(&channel->lock);
}
static void ipoctal_irq_channel(struct ipoctal_channel *channel)
{
u8 isr, sr;
- spin_lock(&channel->lock);
/* The HW is organized in pair of channels. See which register we need
* to read from */
isr = ioread8(&channel->block_regs->r.isr);
@@ -213,8 +214,6 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel)
/* TX of each character */
if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
ipoctal_irq_tx(channel);
-
- spin_unlock(&channel->lock);
}
static irqreturn_t ipoctal_irq_handler(void *arg)
@@ -324,13 +323,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
&block_regs[i].w.imr);
}
- /*
- * IP-OCTAL has different addresses to copy its IRQ vector.
- * Depending of the carrier these addresses are accesible or not.
- * More info in the datasheet.
- */
- ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
- ipoctal_irq_handler, ipoctal);
/* Dummy write */
iowrite8(1, ipoctal->mem8_space + 1);
@@ -391,6 +383,14 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
dev_set_drvdata(tty_dev, channel);
}
+ /*
+ * IP-OCTAL has different addresses to copy its IRQ vector.
+ * Depending of the carrier these addresses are accesible or not.
+ * More info in the datasheet.
+ */
+ ipoctal->dev->bus->ops->request_irq(ipoctal->dev,
+ ipoctal_irq_handler, ipoctal);
+
return 0;
}
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index bbb746e35500..b8632bf9a7f3 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -10,6 +10,11 @@ config ARM_GIC
config GIC_NON_BANKED
bool
+config ARM_GIC_V3
+ bool
+ select IRQ_DOMAIN
+ select MULTI_IRQ_HANDLER
+
config ARM_NVIC
bool
select IRQ_DOMAIN
@@ -23,13 +28,26 @@ config ARM_VIC
config ARM_VIC_NR
int
default 4 if ARCH_S5PV210
- default 3 if ARCH_S5PC100
default 2
depends on ARM_VIC
help
The maximum number of VICs available in the system, for
power management.
+config ATMEL_AIC_IRQ
+ bool
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN
+ select MULTI_IRQ_HANDLER
+ select SPARSE_IRQ
+
+config ATMEL_AIC5_IRQ
+ bool
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN
+ select MULTI_IRQ_HANDLER
+ select SPARSE_IRQ
+
config BRCMSTB_L2_IRQ
bool
depends on ARM
@@ -53,6 +71,10 @@ config CLPS711X_IRQCHIP
select SPARSE_IRQ
default y
+config OR1K_PIC
+ bool
+ select IRQ_DOMAIN
+
config ORION_IRQCHIP
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 62a13e5ef98f..73052ba9ca62 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -11,13 +11,17 @@ obj-$(CONFIG_METAG) += irq-metag-ext.o
obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o
obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o
+obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o
obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
-obj-$(CONFIG_ARM_GIC) += irq-gic.o
+obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
+obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
+obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
+obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o
obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
new file mode 100644
index 000000000000..6ae3cdee0681
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -0,0 +1,254 @@
+/*
+ * Atmel AT91 common AIC (Advanced Interrupt Controller) code shared by
+ * irq-atmel-aic and irq-atmel-aic5 drivers
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "irq-atmel-aic-common.h"
+
+#define AT91_AIC_PRIOR GENMASK(2, 0)
+#define AT91_AIC_IRQ_MIN_PRIORITY 0
+#define AT91_AIC_IRQ_MAX_PRIORITY 7
+
+#define AT91_AIC_SRCTYPE GENMASK(7, 6)
+#define AT91_AIC_SRCTYPE_LOW (0 << 5)
+#define AT91_AIC_SRCTYPE_FALLING (1 << 5)
+#define AT91_AIC_SRCTYPE_HIGH (2 << 5)
+#define AT91_AIC_SRCTYPE_RISING (3 << 5)
+
+struct aic_chip_data {
+ u32 ext_irqs;
+};
+
+static void aic_common_shutdown(struct irq_data *d)
+{
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
+ ct->chip.irq_mask(d);
+}
+
+int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct aic_chip_data *aic = gc->private;
+ unsigned aic_type;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ aic_type = AT91_AIC_SRCTYPE_HIGH;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ aic_type = AT91_AIC_SRCTYPE_RISING;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ if (!(d->mask & aic->ext_irqs))
+ return -EINVAL;
+
+ aic_type = AT91_AIC_SRCTYPE_LOW;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ if (!(d->mask & aic->ext_irqs))
+ return -EINVAL;
+
+ aic_type = AT91_AIC_SRCTYPE_FALLING;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val &= AT91_AIC_SRCTYPE;
+ *val |= aic_type;
+
+ return 0;
+}
+
+int aic_common_set_priority(int priority, unsigned *val)
+{
+ if (priority < AT91_AIC_IRQ_MIN_PRIORITY ||
+ priority > AT91_AIC_IRQ_MAX_PRIORITY)
+ return -EINVAL;
+
+ *val &= AT91_AIC_PRIOR;
+ *val |= priority;
+
+ return 0;
+}
+
+int aic_common_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec,
+ unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ if (WARN_ON(intsize < 3))
+ return -EINVAL;
+
+ if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) ||
+ (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
+ return -EINVAL;
+
+ *out_hwirq = intspec[0];
+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
+{
+ struct device_node *node = domain->of_node;
+ struct irq_chip_generic *gc;
+ struct aic_chip_data *aic;
+ struct property *prop;
+ const __be32 *p;
+ u32 hwirq;
+
+ gc = irq_get_domain_generic_chip(domain, 0);
+
+ aic = gc->private;
+ aic->ext_irqs |= 1;
+
+ of_property_for_each_u32(node, "atmel,external-irqs", prop, p, hwirq) {
+ gc = irq_get_domain_generic_chip(domain, hwirq);
+ if (!gc) {
+ pr_warn("AIC: external irq %d >= %d skip it\n",
+ hwirq, domain->revmap_size);
+ continue;
+ }
+
+ aic = gc->private;
+ aic->ext_irqs |= (1 << (hwirq % 32));
+ }
+}
+
+#define AT91_RTC_IDR 0x24
+#define AT91_RTC_IMR 0x28
+#define AT91_RTC_IRQ_MASK 0x1f
+
+void __init aic_common_rtc_irq_fixup(struct device_node *root)
+{
+ struct device_node *np;
+ void __iomem *regs;
+
+ np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc");
+ if (!np)
+ np = of_find_compatible_node(root, NULL,
+ "atmel,at91sam9x5-rtc");
+
+ if (!np)
+ return;
+
+ regs = of_iomap(np, 0);
+ of_node_put(np);
+
+ if (!regs)
+ return;
+
+ writel(AT91_RTC_IRQ_MASK, regs + AT91_RTC_IDR);
+
+ iounmap(regs);
+}
+
+void __init aic_common_irq_fixup(const struct of_device_id *matches)
+{
+ struct device_node *root = of_find_node_by_path("/");
+ const struct of_device_id *match;
+
+ if (!root)
+ return;
+
+ match = of_match_node(matches, root);
+ of_node_put(root);
+
+ if (match) {
+ void (*fixup)(struct device_node *) = match->data;
+ fixup(root);
+ }
+
+ of_node_put(root);
+}
+
+struct irq_domain *__init aic_common_of_init(struct device_node *node,
+ const struct irq_domain_ops *ops,
+ const char *name, int nirqs)
+{
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+ struct aic_chip_data *aic;
+ void __iomem *reg_base;
+ int nchips;
+ int ret;
+ int i;
+
+ nchips = DIV_ROUND_UP(nirqs, 32);
+
+ reg_base = of_iomap(node, 0);
+ if (!reg_base)
+ return ERR_PTR(-ENOMEM);
+
+ aic = kcalloc(nchips, sizeof(*aic), GFP_KERNEL);
+ if (!aic) {
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ domain = irq_domain_add_linear(node, nchips * 32, ops, aic);
+ if (!domain) {
+ ret = -ENOMEM;
+ goto err_free_aic;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
+ handle_level_irq, 0, 0,
+ IRQCHIP_SKIP_SET_WAKE);
+ if (ret)
+ goto err_domain_remove;
+
+ for (i = 0; i < nchips; i++) {
+ gc = irq_get_domain_generic_chip(domain, i * 32);
+
+ gc->reg_base = reg_base;
+
+ gc->unused = 0;
+ gc->wake_enabled = ~0;
+ gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
+ gc->chip_types[0].handler = handle_fasteoi_irq;
+ gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
+ gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
+ gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
+ gc->private = &aic[i];
+ }
+
+ aic_common_ext_irq_of_init(domain);
+
+ return domain;
+
+err_domain_remove:
+ irq_domain_remove(domain);
+
+err_free_aic:
+ kfree(aic);
+
+err_iounmap:
+ iounmap(reg_base);
+
+ return ERR_PTR(ret);
+}
diff --git a/drivers/irqchip/irq-atmel-aic-common.h b/drivers/irqchip/irq-atmel-aic-common.h
new file mode 100644
index 000000000000..90aa00e918d6
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -0,0 +1,39 @@
+/*
+ * Atmel AT91 common AIC (Advanced Interrupt Controller) header file
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __IRQ_ATMEL_AIC_COMMON_H
+#define __IRQ_ATMEL_AIC_COMMON_H
+
+
+int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
+
+int aic_common_set_priority(int priority, unsigned *val);
+
+int aic_common_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 irq_domain *__init aic_common_of_init(struct device_node *node,
+ const struct irq_domain_ops *ops,
+ const char *name, int nirqs);
+
+void __init aic_common_rtc_irq_fixup(struct device_node *root);
+
+void __init aic_common_irq_fixup(const struct of_device_id *matches);
+
+#endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
new file mode 100644
index 000000000000..a82869e9fb26
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -0,0 +1,262 @@
+/*
+ * Atmel AT91 AIC (Advanced Interrupt Controller) driver
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bitmap.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irq-atmel-aic-common.h"
+#include "irqchip.h"
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC_IRQS 32
+
+#define AT91_AIC_SMR(n) ((n) * 4)
+
+#define AT91_AIC_SVR(n) (0x80 + ((n) * 4))
+#define AT91_AIC_IVR 0x100
+#define AT91_AIC_FVR 0x104
+#define AT91_AIC_ISR 0x108
+
+#define AT91_AIC_IPR 0x10c
+#define AT91_AIC_IMR 0x110
+#define AT91_AIC_CISR 0x114
+
+#define AT91_AIC_IECR 0x120
+#define AT91_AIC_IDCR 0x124
+#define AT91_AIC_ICCR 0x128
+#define AT91_AIC_ISCR 0x12c
+#define AT91_AIC_EOICR 0x130
+#define AT91_AIC_SPU 0x134
+#define AT91_AIC_DCR 0x138
+
+static struct irq_domain *aic_domain;
+
+static asmlinkage void __exception_irq_entry
+aic_handle(struct pt_regs *regs)
+{
+ struct irq_domain_chip_generic *dgc = aic_domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ u32 irqnr;
+ u32 irqstat;
+
+ irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
+ irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
+
+ irqnr = irq_find_mapping(aic_domain, irqnr);
+
+ if (!irqstat)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+ else
+ handle_IRQ(irqnr, regs);
+}
+
+static int aic_retrigger(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int aic_set_type(struct irq_data *d, unsigned type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ unsigned int smr;
+ int ret;
+
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq));
+ ret = aic_common_set_type(d, type, &smr);
+ if (ret)
+ return ret;
+
+ irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static void aic_suspend(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR);
+ irq_gc_unlock(gc);
+}
+
+static void aic_resume(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR);
+ irq_gc_unlock(gc);
+}
+
+static void aic_pm_shutdown(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+ irq_gc_unlock(gc);
+}
+#else
+#define aic_suspend NULL
+#define aic_resume NULL
+#define aic_pm_shutdown NULL
+#endif /* CONFIG_PM */
+
+static void __init aic_hw_init(struct irq_domain *domain)
+{
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+ int i;
+
+ /*
+ * Perform 8 End Of Interrupt Command to make sure AIC
+ * will not Lock out nIRQ
+ */
+ for (i = 0; i < 8; i++)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register.
+ * When there is no current interrupt, the IRQ Vector Register
+ * reads the value stored in AIC_SPU
+ */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR);
+
+ /* Disable and clear all interrupts initially */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+
+ for (i = 0; i < 32; i++)
+ irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i));
+}
+
+static int aic_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ struct irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ unsigned smr;
+ int idx;
+ int ret;
+
+ if (!dgc)
+ return -EINVAL;
+
+ ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+ out_hwirq, out_type);
+ if (ret)
+ return ret;
+
+ idx = intspec[0] / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return -EINVAL;
+
+ gc = dgc->gc[idx];
+
+ irq_gc_lock(gc);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq));
+ ret = aic_common_set_priority(intspec[2], &smr);
+ if (!ret)
+ irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq));
+ irq_gc_unlock(gc);
+
+ return ret;
+}
+
+static const struct irq_domain_ops aic_irq_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = aic_irq_domain_xlate,
+};
+
+static void __init at91sam9_aic_irq_fixup(struct device_node *root)
+{
+ aic_common_rtc_irq_fixup(root);
+}
+
+static const struct of_device_id __initdata aic_irq_fixups[] = {
+ { .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup },
+ { .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup },
+ { .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup },
+ { .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup },
+ { /* sentinel */ },
+};
+
+static int __init aic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+
+ if (aic_domain)
+ return -EEXIST;
+
+ domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
+ NR_AIC_IRQS);
+ if (IS_ERR(domain))
+ return PTR_ERR(domain);
+
+ aic_common_irq_fixup(aic_irq_fixups);
+
+ aic_domain = domain;
+ gc = irq_get_domain_generic_chip(domain, 0);
+
+ gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
+ gc->chip_types[0].regs.enable = AT91_AIC_IECR;
+ gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+ gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+ gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
+ gc->chip_types[0].chip.irq_set_type = aic_set_type;
+ gc->chip_types[0].chip.irq_suspend = aic_suspend;
+ gc->chip_types[0].chip.irq_resume = aic_resume;
+ gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;
+
+ aic_hw_init(domain);
+ set_handle_irq(aic_handle);
+
+ return 0;
+}
+IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
new file mode 100644
index 000000000000..edb227081524
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -0,0 +1,353 @@
+/*
+ * Atmel AT91 AIC5 (Advanced Interrupt Controller) driver
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bitmap.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irq-atmel-aic-common.h"
+#include "irqchip.h"
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC5_IRQS 128
+
+#define AT91_AIC5_SSR 0x0
+#define AT91_AIC5_INTSEL_MSK (0x7f << 0)
+
+#define AT91_AIC5_SMR 0x4
+
+#define AT91_AIC5_SVR 0x8
+#define AT91_AIC5_IVR 0x10
+#define AT91_AIC5_FVR 0x14
+#define AT91_AIC5_ISR 0x18
+
+#define AT91_AIC5_IPR0 0x20
+#define AT91_AIC5_IPR1 0x24
+#define AT91_AIC5_IPR2 0x28
+#define AT91_AIC5_IPR3 0x2c
+#define AT91_AIC5_IMR 0x30
+#define AT91_AIC5_CISR 0x34
+
+#define AT91_AIC5_IECR 0x40
+#define AT91_AIC5_IDCR 0x44
+#define AT91_AIC5_ICCR 0x48
+#define AT91_AIC5_ISCR 0x4c
+#define AT91_AIC5_EOICR 0x38
+#define AT91_AIC5_SPU 0x3c
+#define AT91_AIC5_DCR 0x6c
+
+#define AT91_AIC5_FFER 0x50
+#define AT91_AIC5_FFDR 0x54
+#define AT91_AIC5_FFSR 0x58
+
+static struct irq_domain *aic5_domain;
+
+static asmlinkage void __exception_irq_entry
+aic5_handle(struct pt_regs *regs)
+{
+ struct irq_domain_chip_generic *dgc = aic5_domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ u32 irqnr;
+ u32 irqstat;
+
+ irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR);
+ irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR);
+
+ irqnr = irq_find_mapping(aic5_domain, irqnr);
+
+ if (!irqstat)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+ else
+ handle_IRQ(irqnr, regs);
+}
+
+static void aic5_mask(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Disable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+ gc->mask_cache &= ~d->mask;
+ irq_gc_unlock(gc);
+}
+
+static void aic5_unmask(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IECR);
+ gc->mask_cache |= d->mask;
+ irq_gc_unlock(gc);
+}
+
+static int aic5_retrigger(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_ISCR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int aic5_set_type(struct irq_data *d, unsigned type)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ unsigned int smr;
+ int ret;
+
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
+ ret = aic_common_set_type(d, type, &smr);
+ if (!ret)
+ irq_reg_writel(smr, gc->reg_base + AT91_AIC5_SMR);
+ irq_gc_unlock(gc);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static void aic5_suspend(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+ u32 mask;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ mask = 1 << i;
+ if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+ continue;
+
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ if (mask & gc->wake_active)
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+ else
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ }
+ irq_gc_unlock(bgc);
+}
+
+static void aic5_resume(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+ u32 mask;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ mask = 1 << i;
+ if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+ continue;
+
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ if (mask & gc->mask_cache)
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+ else
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ }
+ irq_gc_unlock(bgc);
+}
+
+static void aic5_pm_shutdown(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_ICCR);
+ }
+ irq_gc_unlock(bgc);
+}
+#else
+#define aic5_suspend NULL
+#define aic5_resume NULL
+#define aic5_pm_shutdown NULL
+#endif /* CONFIG_PM */
+
+static void __init aic5_hw_init(struct irq_domain *domain)
+{
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+ int i;
+
+ /*
+ * Perform 8 End Of Interrupt Command to make sure AIC
+ * will not Lock out nIRQ
+ */
+ for (i = 0; i < 8; i++)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register.
+ * When there is no current interrupt, the IRQ Vector Register
+ * reads the value stored in AIC_SPU
+ */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC5_SPU);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_DCR);
+
+ /* Disable and clear all interrupts initially */
+ for (i = 0; i < domain->revmap_size; i++) {
+ irq_reg_writel(i, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(i, gc->reg_base + AT91_AIC5_SVR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_ICCR);
+ }
+}
+
+static int aic5_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 irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ unsigned smr;
+ int ret;
+
+ if (!dgc)
+ return -EINVAL;
+
+ ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+ out_hwirq, out_type);
+ if (ret)
+ return ret;
+
+ gc = dgc->gc[0];
+
+ irq_gc_lock(gc);
+ irq_reg_writel(*out_hwirq, gc->reg_base + AT91_AIC5_SSR);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
+ ret = aic_common_set_priority(intspec[2], &smr);
+ if (!ret)
+ irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR);
+ irq_gc_unlock(gc);
+
+ return ret;
+}
+
+static const struct irq_domain_ops aic5_irq_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = aic5_irq_domain_xlate,
+};
+
+static void __init sama5d3_aic_irq_fixup(struct device_node *root)
+{
+ aic_common_rtc_irq_fixup(root);
+}
+
+static const struct of_device_id __initdata aic5_irq_fixups[] = {
+ { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
+ { /* sentinel */ },
+};
+
+static int __init aic5_of_init(struct device_node *node,
+ struct device_node *parent,
+ int nirqs)
+{
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+ int nchips;
+ int i;
+
+ if (nirqs > NR_AIC5_IRQS)
+ return -EINVAL;
+
+ if (aic5_domain)
+ return -EEXIST;
+
+ domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
+ nirqs);
+ if (IS_ERR(domain))
+ return PTR_ERR(domain);
+
+ aic_common_irq_fixup(aic5_irq_fixups);
+
+ aic5_domain = domain;
+ nchips = aic5_domain->revmap_size / 32;
+ for (i = 0; i < nchips; i++) {
+ gc = irq_get_domain_generic_chip(domain, i * 32);
+
+ gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
+ gc->chip_types[0].chip.irq_mask = aic5_mask;
+ gc->chip_types[0].chip.irq_unmask = aic5_unmask;
+ gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
+ gc->chip_types[0].chip.irq_set_type = aic5_set_type;
+ gc->chip_types[0].chip.irq_suspend = aic5_suspend;
+ gc->chip_types[0].chip.irq_resume = aic5_resume;
+ gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
+ }
+
+ aic5_hw_init(domain);
+ set_handle_irq(aic5_handle);
+
+ return 0;
+}
+
+#define NR_SAMA5D3_IRQS 50
+
+static int __init sama5d3_aic5_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return aic5_of_init(node, parent, NR_SAMA5D3_IRQS);
+}
+IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", sama5d3_aic5_of_init);
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index 3d15d16a7088..85c2985d8bcb 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -15,22 +15,31 @@
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/irq-crossbar.h>
#define IRQ_FREE -1
+#define IRQ_RESERVED -2
+#define IRQ_SKIP -3
#define GIC_IRQ_START 32
-/*
+/**
+ * struct crossbar_device - crossbar device description
* @int_max: maximum number of supported interrupts
+ * @safe_map: safe default value to initialize the crossbar
+ * @max_crossbar_sources: Maximum number of crossbar sources
* @irq_map: array of interrupts to crossbar number mapping
* @crossbar_base: crossbar base address
* @register_offsets: offsets for each irq number
+ * @write: register write function pointer
*/
struct crossbar_device {
uint int_max;
+ uint safe_map;
+ uint max_crossbar_sources;
uint *irq_map;
void __iomem *crossbar_base;
int *register_offsets;
- void (*write) (int, int);
+ void (*write)(int, int);
};
static struct crossbar_device *cb;
@@ -50,11 +59,22 @@ static inline void crossbar_writeb(int irq_no, int cb_no)
writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
}
+static inline int get_prev_map_irq(int cb_no)
+{
+ int i;
+
+ for (i = cb->int_max - 1; i >= 0; i--)
+ if (cb->irq_map[i] == cb_no)
+ return i;
+
+ return -ENODEV;
+}
+
static inline int allocate_free_irq(int cb_no)
{
int i;
- for (i = 0; i < cb->int_max; i++) {
+ for (i = cb->int_max - 1; i >= 0; i--) {
if (cb->irq_map[i] == IRQ_FREE) {
cb->irq_map[i] = cb_no;
return i;
@@ -64,19 +84,47 @@ static inline int allocate_free_irq(int cb_no)
return -ENODEV;
}
+static inline bool needs_crossbar_write(irq_hw_number_t hw)
+{
+ int cb_no;
+
+ if (hw > GIC_IRQ_START) {
+ cb_no = cb->irq_map[hw - GIC_IRQ_START];
+ if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
+ return true;
+ }
+
+ return false;
+}
+
static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
- cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+ if (needs_crossbar_write(hw))
+ cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+
return 0;
}
+/**
+ * crossbar_domain_unmap - unmap a crossbar<->irq connection
+ * @d: domain of irq to unmap
+ * @irq: virq number
+ *
+ * We do not maintain a use count of total number of map/unmap
+ * calls for a particular irq to find out if a irq can be really
+ * unmapped. This is because unmap is called during irq_dispose_mapping(irq),
+ * after which irq is anyways unusable. So an explicit map has to be called
+ * after that.
+ */
static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
{
irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
- if (hw > GIC_IRQ_START)
+ if (needs_crossbar_write(hw)) {
cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
+ cb->write(hw - GIC_IRQ_START, cb->safe_map);
+ }
}
static int crossbar_domain_xlate(struct irq_domain *d,
@@ -85,18 +133,41 @@ static int crossbar_domain_xlate(struct irq_domain *d,
unsigned long *out_hwirq,
unsigned int *out_type)
{
- unsigned long ret;
+ int ret;
+ int req_num = intspec[1];
+ int direct_map_num;
+
+ if (req_num >= cb->max_crossbar_sources) {
+ direct_map_num = req_num - cb->max_crossbar_sources;
+ if (direct_map_num < cb->int_max) {
+ ret = cb->irq_map[direct_map_num];
+ if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
+ /* We use the interrupt num as h/w irq num */
+ ret = direct_map_num;
+ goto found;
+ }
+ }
+
+ pr_err("%s: requested crossbar number %d > max %d\n",
+ __func__, req_num, cb->max_crossbar_sources);
+ return -EINVAL;
+ }
- ret = allocate_free_irq(intspec[1]);
+ ret = get_prev_map_irq(req_num);
+ if (ret >= 0)
+ goto found;
- if (IS_ERR_VALUE(ret))
+ ret = allocate_free_irq(req_num);
+
+ if (ret < 0)
return ret;
+found:
*out_hwirq = ret + GIC_IRQ_START;
return 0;
}
-const struct irq_domain_ops routable_irq_domain_ops = {
+static const struct irq_domain_ops routable_irq_domain_ops = {
.map = crossbar_domain_map,
.unmap = crossbar_domain_unmap,
.xlate = crossbar_domain_xlate
@@ -104,22 +175,36 @@ const struct irq_domain_ops routable_irq_domain_ops = {
static int __init crossbar_of_init(struct device_node *node)
{
- int i, size, max, reserved = 0, entry;
+ int i, size, max = 0, reserved = 0, entry;
const __be32 *irqsr;
+ int ret = -ENOMEM;
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
- return -ENOMEM;
+ return ret;
cb->crossbar_base = of_iomap(node, 0);
if (!cb->crossbar_base)
- goto err1;
+ goto err_cb;
+
+ of_property_read_u32(node, "ti,max-crossbar-sources",
+ &cb->max_crossbar_sources);
+ if (!cb->max_crossbar_sources) {
+ pr_err("missing 'ti,max-crossbar-sources' property\n");
+ ret = -EINVAL;
+ goto err_base;
+ }
of_property_read_u32(node, "ti,max-irqs", &max);
- cb->irq_map = kzalloc(max * sizeof(int), GFP_KERNEL);
+ if (!max) {
+ pr_err("missing 'ti,max-irqs' property\n");
+ ret = -EINVAL;
+ goto err_base;
+ }
+ cb->irq_map = kcalloc(max, sizeof(int), GFP_KERNEL);
if (!cb->irq_map)
- goto err2;
+ goto err_base;
cb->int_max = max;
@@ -137,15 +222,35 @@ static int __init crossbar_of_init(struct device_node *node)
i, &entry);
if (entry > max) {
pr_err("Invalid reserved entry\n");
- goto err3;
+ ret = -EINVAL;
+ goto err_irq_map;
+ }
+ cb->irq_map[entry] = IRQ_RESERVED;
+ }
+ }
+
+ /* Skip irqs hardwired to bypass the crossbar */
+ irqsr = of_get_property(node, "ti,irqs-skip", &size);
+ if (irqsr) {
+ size /= sizeof(__be32);
+
+ for (i = 0; i < size; i++) {
+ of_property_read_u32_index(node,
+ "ti,irqs-skip",
+ i, &entry);
+ if (entry > max) {
+ pr_err("Invalid skip entry\n");
+ ret = -EINVAL;
+ goto err_irq_map;
}
- cb->irq_map[entry] = 0;
+ cb->irq_map[entry] = IRQ_SKIP;
}
}
- cb->register_offsets = kzalloc(max * sizeof(int), GFP_KERNEL);
+
+ cb->register_offsets = kcalloc(max, sizeof(int), GFP_KERNEL);
if (!cb->register_offsets)
- goto err3;
+ goto err_irq_map;
of_property_read_u32(node, "ti,reg-size", &size);
@@ -161,7 +266,8 @@ static int __init crossbar_of_init(struct device_node *node)
break;
default:
pr_err("Invalid reg-size property\n");
- goto err4;
+ ret = -EINVAL;
+ goto err_reg_offset;
break;
}
@@ -170,25 +276,37 @@ static int __init crossbar_of_init(struct device_node *node)
* reserved irqs. so find and store the offsets once.
*/
for (i = 0; i < max; i++) {
- if (!cb->irq_map[i])
+ if (cb->irq_map[i] == IRQ_RESERVED)
continue;
cb->register_offsets[i] = reserved;
reserved += size;
}
+ of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map);
+ /* Initialize the crossbar with safe map to start with */
+ for (i = 0; i < max; i++) {
+ if (cb->irq_map[i] == IRQ_RESERVED ||
+ cb->irq_map[i] == IRQ_SKIP)
+ continue;
+
+ cb->write(i, cb->safe_map);
+ }
+
register_routable_domain_ops(&routable_irq_domain_ops);
return 0;
-err4:
+err_reg_offset:
kfree(cb->register_offsets);
-err3:
+err_irq_map:
kfree(cb->irq_map);
-err2:
+err_base:
iounmap(cb->crossbar_base);
-err1:
+err_cb:
kfree(cb);
- return -ENOMEM;
+
+ cb = NULL;
+ return ret;
}
static const struct of_device_id crossbar_match[] __initconst = {
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
new file mode 100644
index 000000000000..60ac704d2090
--- /dev/null
+++ b/drivers/irqchip/irq-gic-common.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2002 ARM Limited, 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include "irq-gic-common.h"
+
+void gic_configure_irq(unsigned int irq, unsigned int type,
+ void __iomem *base, void (*sync_access)(void))
+{
+ u32 enablemask = 1 << (irq % 32);
+ u32 enableoff = (irq / 32) * 4;
+ u32 confmask = 0x2 << ((irq % 16) * 2);
+ u32 confoff = (irq / 16) * 4;
+ bool enabled = false;
+ u32 val;
+
+ /*
+ * Read current configuration register, and insert the config
+ * for "irq", depending on "type".
+ */
+ val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
+ if (type == IRQ_TYPE_LEVEL_HIGH)
+ val &= ~confmask;
+ else if (type == IRQ_TYPE_EDGE_RISING)
+ val |= confmask;
+
+ /*
+ * As recommended by the spec, disable the interrupt before changing
+ * the configuration
+ */
+ if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
+ writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
+ if (sync_access)
+ sync_access();
+ enabled = true;
+ }
+
+ /*
+ * Write back the new configuration, and possibly re-enable
+ * the interrupt.
+ */
+ writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
+
+ if (enabled)
+ writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
+
+ if (sync_access)
+ sync_access();
+}
+
+void __init gic_dist_config(void __iomem *base, int gic_irqs,
+ void (*sync_access)(void))
+{
+ unsigned int i;
+
+ /*
+ * Set all global interrupts to be level triggered, active low.
+ */
+ for (i = 32; i < gic_irqs; i += 16)
+ writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4);
+
+ /*
+ * Set priority on all global interrupts.
+ */
+ for (i = 32; i < gic_irqs; i += 4)
+ writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i);
+
+ /*
+ * Disable all interrupts. Leave the PPI and SGIs alone
+ * as they are enabled by redistributor registers.
+ */
+ for (i = 32; i < gic_irqs; i += 32)
+ writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8);
+
+ if (sync_access)
+ sync_access();
+}
+
+void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
+{
+ int i;
+
+ /*
+ * Deal with the banked PPI and SGI interrupts - disable all
+ * PPI interrupts, ensure all SGI interrupts are enabled.
+ */
+ writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR);
+ writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET);
+
+ /*
+ * Set priority on PPI and SGI interrupts
+ */
+ for (i = 0; i < 32; i += 4)
+ writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
+
+ if (sync_access)
+ sync_access();
+}
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
new file mode 100644
index 000000000000..b41f02481c3a
--- /dev/null
+++ b/drivers/irqchip/irq-gic-common.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2002 ARM Limited, 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _IRQ_GIC_COMMON_H
+#define _IRQ_GIC_COMMON_H
+
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+
+void gic_configure_irq(unsigned int irq, unsigned int type,
+ void __iomem *base, void (*sync_access)(void));
+void gic_dist_config(void __iomem *base, int gic_irqs,
+ void (*sync_access)(void));
+void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+
+#endif /* _IRQ_GIC_COMMON_H */
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
new file mode 100644
index 000000000000..57eaa5a0b1e3
--- /dev/null
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/percpu.h>
+#include <linux/slab.h>
+
+#include <linux/irqchip/arm-gic-v3.h>
+
+#include <asm/cputype.h>
+#include <asm/exception.h>
+#include <asm/smp_plat.h>
+
+#include "irq-gic-common.h"
+#include "irqchip.h"
+
+struct gic_chip_data {
+ void __iomem *dist_base;
+ void __iomem **redist_base;
+ void __percpu __iomem **rdist;
+ struct irq_domain *domain;
+ u64 redist_stride;
+ u32 redist_regions;
+ unsigned int irq_nr;
+};
+
+static struct gic_chip_data gic_data __read_mostly;
+
+#define gic_data_rdist() (this_cpu_ptr(gic_data.rdist))
+#define gic_data_rdist_rd_base() (*gic_data_rdist())
+#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K)
+
+/* Our default, arbitrary priority value. Linux only uses one anyway. */
+#define DEFAULT_PMR_VALUE 0xf0
+
+static inline unsigned int gic_irq(struct irq_data *d)
+{
+ return d->hwirq;
+}
+
+static inline int gic_irq_in_rdist(struct irq_data *d)
+{
+ return gic_irq(d) < 32;
+}
+
+static inline void __iomem *gic_dist_base(struct irq_data *d)
+{
+ if (gic_irq_in_rdist(d)) /* SGI+PPI -> SGI_base for this CPU */
+ return gic_data_rdist_sgi_base();
+
+ if (d->hwirq <= 1023) /* SPI -> dist_base */
+ return gic_data.dist_base;
+
+ if (d->hwirq >= 8192)
+ BUG(); /* LPI Detected!!! */
+
+ return NULL;
+}
+
+static void gic_do_wait_for_rwp(void __iomem *base)
+{
+ u32 count = 1000000; /* 1s! */
+
+ while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
+ count--;
+ if (!count) {
+ pr_err_ratelimited("RWP timeout, gone fishing\n");
+ return;
+ }
+ cpu_relax();
+ udelay(1);
+ };
+}
+
+/* Wait for completion of a distributor change */
+static void gic_dist_wait_for_rwp(void)
+{
+ gic_do_wait_for_rwp(gic_data.dist_base);
+}
+
+/* Wait for completion of a redistributor change */
+static void gic_redist_wait_for_rwp(void)
+{
+ gic_do_wait_for_rwp(gic_data_rdist_rd_base());
+}
+
+/* Low level accessors */
+static u64 gic_read_iar(void)
+{
+ u64 irqstat;
+
+ asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+ return irqstat;
+}
+
+static void gic_write_pmr(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
+}
+
+static void gic_write_ctlr(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
+ isb();
+}
+
+static void gic_write_grpen1(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val));
+ isb();
+}
+
+static void gic_write_sgi1r(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+}
+
+static void gic_enable_sre(void)
+{
+ u64 val;
+
+ asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
+ val |= ICC_SRE_EL1_SRE;
+ asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val));
+ isb();
+
+ /*
+ * Need to check that the SRE bit has actually been set. If
+ * not, it means that SRE is disabled at EL2. We're going to
+ * die painfully, and there is nothing we can do about it.
+ *
+ * Kindly inform the luser.
+ */
+ asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
+ if (!(val & ICC_SRE_EL1_SRE))
+ pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
+}
+
+static void gic_enable_redist(void)
+{
+ void __iomem *rbase;
+ u32 count = 1000000; /* 1s! */
+ u32 val;
+
+ rbase = gic_data_rdist_rd_base();
+
+ /* Wake up this CPU redistributor */
+ val = readl_relaxed(rbase + GICR_WAKER);
+ val &= ~GICR_WAKER_ProcessorSleep;
+ writel_relaxed(val, rbase + GICR_WAKER);
+
+ while (readl_relaxed(rbase + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) {
+ count--;
+ if (!count) {
+ pr_err_ratelimited("redist didn't wake up...\n");
+ return;
+ }
+ cpu_relax();
+ udelay(1);
+ };
+}
+
+/*
+ * Routines to disable, enable, EOI and route interrupts
+ */
+static void gic_poke_irq(struct irq_data *d, u32 offset)
+{
+ u32 mask = 1 << (gic_irq(d) % 32);
+ void (*rwp_wait)(void);
+ void __iomem *base;
+
+ if (gic_irq_in_rdist(d)) {
+ base = gic_data_rdist_sgi_base();
+ rwp_wait = gic_redist_wait_for_rwp;
+ } else {
+ base = gic_data.dist_base;
+ rwp_wait = gic_dist_wait_for_rwp;
+ }
+
+ writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
+ rwp_wait();
+}
+
+static int gic_peek_irq(struct irq_data *d, u32 offset)
+{
+ u32 mask = 1 << (gic_irq(d) % 32);
+ void __iomem *base;
+
+ if (gic_irq_in_rdist(d))
+ base = gic_data_rdist_sgi_base();
+ else
+ base = gic_data.dist_base;
+
+ return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+}
+
+static void gic_mask_irq(struct irq_data *d)
+{
+ gic_poke_irq(d, GICD_ICENABLER);
+}
+
+static void gic_unmask_irq(struct irq_data *d)
+{
+ gic_poke_irq(d, GICD_ISENABLER);
+}
+
+static void gic_eoi_irq(struct irq_data *d)
+{
+ gic_write_eoir(gic_irq(d));
+}
+
+static int gic_set_type(struct irq_data *d, unsigned int type)
+{
+ unsigned int irq = gic_irq(d);
+ void (*rwp_wait)(void);
+ void __iomem *base;
+
+ /* Interrupt configuration for SGIs can't be changed */
+ if (irq < 16)
+ return -EINVAL;
+
+ if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
+ return -EINVAL;
+
+ if (gic_irq_in_rdist(d)) {
+ base = gic_data_rdist_sgi_base();
+ rwp_wait = gic_redist_wait_for_rwp;
+ } else {
+ base = gic_data.dist_base;
+ rwp_wait = gic_dist_wait_for_rwp;
+ }
+
+ gic_configure_irq(irq, type, base, rwp_wait);
+
+ return 0;
+}
+
+static u64 gic_mpidr_to_affinity(u64 mpidr)
+{
+ u64 aff;
+
+ aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+ return aff;
+}
+
+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+ u64 irqnr;
+
+ do {
+ irqnr = gic_read_iar();
+
+ if (likely(irqnr > 15 && irqnr < 1020)) {
+ u64 irq = irq_find_mapping(gic_data.domain, irqnr);
+ if (likely(irq)) {
+ handle_IRQ(irq, regs);
+ continue;
+ }
+
+ WARN_ONCE(true, "Unexpected SPI received!\n");
+ gic_write_eoir(irqnr);
+ }
+ if (irqnr < 16) {
+ gic_write_eoir(irqnr);
+#ifdef CONFIG_SMP
+ handle_IPI(irqnr, regs);
+#else
+ WARN_ONCE(true, "Unexpected SGI received!\n");
+#endif
+ continue;
+ }
+ } while (irqnr != ICC_IAR1_EL1_SPURIOUS);
+}
+
+static void __init gic_dist_init(void)
+{
+ unsigned int i;
+ u64 affinity;
+ void __iomem *base = gic_data.dist_base;
+
+ /* Disable the distributor */
+ writel_relaxed(0, base + GICD_CTLR);
+ gic_dist_wait_for_rwp();
+
+ gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
+
+ /* Enable distributor with ARE, Group1 */
+ writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
+ base + GICD_CTLR);
+
+ /*
+ * Set all global interrupts to the boot CPU only. ARE must be
+ * enabled.
+ */
+ affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
+ for (i = 32; i < gic_data.irq_nr; i++)
+ writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
+}
+
+static int gic_populate_rdist(void)
+{
+ u64 mpidr = cpu_logical_map(smp_processor_id());
+ u64 typer;
+ u32 aff;
+ int i;
+
+ /*
+ * Convert affinity to a 32bit value that can be matched to
+ * GICR_TYPER bits [63:32].
+ */
+ aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+ for (i = 0; i < gic_data.redist_regions; i++) {
+ void __iomem *ptr = gic_data.redist_base[i];
+ u32 reg;
+
+ reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
+ if (reg != GIC_PIDR2_ARCH_GICv3 &&
+ reg != GIC_PIDR2_ARCH_GICv4) { /* We're in trouble... */
+ pr_warn("No redistributor present @%p\n", ptr);
+ break;
+ }
+
+ do {
+ typer = readq_relaxed(ptr + GICR_TYPER);
+ if ((typer >> 32) == aff) {
+ gic_data_rdist_rd_base() = ptr;
+ pr_info("CPU%d: found redistributor %llx @%p\n",
+ smp_processor_id(),
+ (unsigned long long)mpidr, ptr);
+ return 0;
+ }
+
+ if (gic_data.redist_stride) {
+ ptr += gic_data.redist_stride;
+ } else {
+ ptr += SZ_64K * 2; /* Skip RD_base + SGI_base */
+ if (typer & GICR_TYPER_VLPIS)
+ ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
+ }
+ } while (!(typer & GICR_TYPER_LAST));
+ }
+
+ /* We couldn't even deal with ourselves... */
+ WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
+ smp_processor_id(), (unsigned long long)mpidr);
+ return -ENODEV;
+}
+
+static void gic_cpu_init(void)
+{
+ void __iomem *rbase;
+
+ /* Register ourselves with the rest of the world */
+ if (gic_populate_rdist())
+ return;
+
+ gic_enable_redist();
+
+ rbase = gic_data_rdist_sgi_base();
+
+ gic_cpu_config(rbase, gic_redist_wait_for_rwp);
+
+ /* Enable system registers */
+ gic_enable_sre();
+
+ /* Set priority mask register */
+ gic_write_pmr(DEFAULT_PMR_VALUE);
+
+ /* EOI deactivates interrupt too (mode 0) */
+ gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
+
+ /* ... and let's hit the road... */
+ gic_write_grpen1(1);
+}
+
+#ifdef CONFIG_SMP
+static int gic_secondary_init(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+ gic_cpu_init();
+ return NOTIFY_OK;
+}
+
+/*
+ * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
+ * priority because the GIC needs to be up before the ARM generic timers.
+ */
+static struct notifier_block gic_cpu_notifier = {
+ .notifier_call = gic_secondary_init,
+ .priority = 100,
+};
+
+static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
+ u64 cluster_id)
+{
+ int cpu = *base_cpu;
+ u64 mpidr = cpu_logical_map(cpu);
+ u16 tlist = 0;
+
+ while (cpu < nr_cpu_ids) {
+ /*
+ * If we ever get a cluster of more than 16 CPUs, just
+ * scream and skip that CPU.
+ */
+ if (WARN_ON((mpidr & 0xff) >= 16))
+ goto out;
+
+ tlist |= 1 << (mpidr & 0xf);
+
+ cpu = cpumask_next(cpu, mask);
+ if (cpu == nr_cpu_ids)
+ goto out;
+
+ mpidr = cpu_logical_map(cpu);
+
+ if (cluster_id != (mpidr & ~0xffUL)) {
+ cpu--;
+ goto out;
+ }
+ }
+out:
+ *base_cpu = cpu;
+ return tlist;
+}
+
+static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
+{
+ u64 val;
+
+ val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48 |
+ MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32 |
+ irq << 24 |
+ MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16 |
+ tlist);
+
+ pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
+ gic_write_sgi1r(val);
+}
+
+static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+{
+ int cpu;
+
+ if (WARN_ON(irq >= 16))
+ return;
+
+ /*
+ * Ensure that stores to Normal memory are visible to the
+ * other CPUs before issuing the IPI.
+ */
+ smp_wmb();
+
+ for_each_cpu_mask(cpu, *mask) {
+ u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
+ u16 tlist;
+
+ tlist = gic_compute_target_list(&cpu, mask, cluster_id);
+ gic_send_sgi(cluster_id, tlist, irq);
+ }
+
+ /* Force the above writes to ICC_SGI1R_EL1 to be executed */
+ isb();
+}
+
+static void gic_smp_init(void)
+{
+ set_smp_cross_call(gic_raise_softirq);
+ register_cpu_notifier(&gic_cpu_notifier);
+}
+
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+ bool force)
+{
+ unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+ void __iomem *reg;
+ int enabled;
+ u64 val;
+
+ if (gic_irq_in_rdist(d))
+ return -EINVAL;
+
+ /* If interrupt was enabled, disable it first */
+ enabled = gic_peek_irq(d, GICD_ISENABLER);
+ if (enabled)
+ gic_mask_irq(d);
+
+ reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
+ val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
+
+ writeq_relaxed(val, reg);
+
+ /*
+ * If the interrupt was enabled, enabled it again. Otherwise,
+ * just wait for the distributor to have digested our changes.
+ */
+ if (enabled)
+ gic_unmask_irq(d);
+ else
+ gic_dist_wait_for_rwp();
+
+ return IRQ_SET_MASK_OK;
+}
+#else
+#define gic_set_affinity NULL
+#define gic_smp_init() do { } while(0)
+#endif
+
+static struct irq_chip gic_chip = {
+ .name = "GICv3",
+ .irq_mask = gic_mask_irq,
+ .irq_unmask = gic_unmask_irq,
+ .irq_eoi = gic_eoi_irq,
+ .irq_set_type = gic_set_type,
+ .irq_set_affinity = gic_set_affinity,
+};
+
+static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ /* SGIs are private to the core kernel */
+ if (hw < 16)
+ return -EPERM;
+ /* PPIs */
+ if (hw < 32) {
+ irq_set_percpu_devid(irq);
+ irq_set_chip_and_handler(irq, &gic_chip,
+ handle_percpu_devid_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+ }
+ /* SPIs */
+ if (hw >= 32 && hw < gic_data.irq_nr) {
+ irq_set_chip_and_handler(irq, &gic_chip,
+ handle_fasteoi_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ irq_set_chip_data(irq, d->host_data);
+ return 0;
+}
+
+static int gic_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize < 3)
+ return -EINVAL;
+
+ switch(intspec[0]) {
+ case 0: /* SPI */
+ *out_hwirq = intspec[1] + 32;
+ break;
+ case 1: /* PPI */
+ *out_hwirq = intspec[1] + 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+}
+
+static const struct irq_domain_ops gic_irq_domain_ops = {
+ .map = gic_irq_domain_map,
+ .xlate = gic_irq_domain_xlate,
+};
+
+static int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+ void __iomem *dist_base;
+ void __iomem **redist_base;
+ u64 redist_stride;
+ u32 redist_regions;
+ u32 reg;
+ int gic_irqs;
+ int err;
+ int i;
+
+ dist_base = of_iomap(node, 0);
+ if (!dist_base) {
+ pr_err("%s: unable to map gic dist registers\n",
+ node->full_name);
+ return -ENXIO;
+ }
+
+ reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+ if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+ pr_err("%s: no distributor detected, giving up\n",
+ node->full_name);
+ err = -ENODEV;
+ goto out_unmap_dist;
+ }
+
+ if (of_property_read_u32(node, "#redistributor-regions", &redist_regions))
+ redist_regions = 1;
+
+ redist_base = kzalloc(sizeof(*redist_base) * redist_regions, GFP_KERNEL);
+ if (!redist_base) {
+ err = -ENOMEM;
+ goto out_unmap_dist;
+ }
+
+ for (i = 0; i < redist_regions; i++) {
+ redist_base[i] = of_iomap(node, 1 + i);
+ if (!redist_base[i]) {
+ pr_err("%s: couldn't map region %d\n",
+ node->full_name, i);
+ err = -ENODEV;
+ goto out_unmap_rdist;
+ }
+ }
+
+ if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
+ redist_stride = 0;
+
+ gic_data.dist_base = dist_base;
+ gic_data.redist_base = redist_base;
+ gic_data.redist_regions = redist_regions;
+ gic_data.redist_stride = redist_stride;
+
+ /*
+ * Find out how many interrupts are supported.
+ * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+ */
+ gic_irqs = readl_relaxed(gic_data.dist_base + GICD_TYPER) & 0x1f;
+ gic_irqs = (gic_irqs + 1) * 32;
+ if (gic_irqs > 1020)
+ gic_irqs = 1020;
+ gic_data.irq_nr = gic_irqs;
+
+ gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
+ &gic_data);
+ gic_data.rdist = alloc_percpu(typeof(*gic_data.rdist));
+
+ if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdist)) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ set_handle_irq(gic_handle_irq);
+
+ gic_smp_init();
+ gic_dist_init();
+ gic_cpu_init();
+
+ return 0;
+
+out_free:
+ if (gic_data.domain)
+ irq_domain_remove(gic_data.domain);
+ free_percpu(gic_data.rdist);
+out_unmap_rdist:
+ for (i = 0; i < redist_regions; i++)
+ if (redist_base[i])
+ iounmap(redist_base[i]);
+ kfree(redist_base);
+out_unmap_dist:
+ iounmap(dist_base);
+ return err;
+}
+
+IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7c131cf7cc13..4b959e606fe8 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1,6 +1,4 @@
/*
- * linux/arch/arm/common/gic.c
- *
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -47,6 +45,7 @@
#include <asm/exception.h>
#include <asm/smp_plat.h>
+#include "irq-gic-common.h"
#include "irqchip.h"
union gic_base {
@@ -189,12 +188,6 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
- u32 enablemask = 1 << (gicirq % 32);
- u32 enableoff = (gicirq / 32) * 4;
- u32 confmask = 0x2 << ((gicirq % 16) * 2);
- u32 confoff = (gicirq / 16) * 4;
- bool enabled = false;
- u32 val;
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
@@ -208,25 +201,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
if (gic_arch_extn.irq_set_type)
gic_arch_extn.irq_set_type(d, type);
- val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
- if (type == IRQ_TYPE_LEVEL_HIGH)
- val &= ~confmask;
- else if (type == IRQ_TYPE_EDGE_RISING)
- val |= confmask;
-
- /*
- * As recommended by the spec, disable the interrupt before changing
- * the configuration
- */
- if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
- writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
- enabled = true;
- }
-
- writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
-
- if (enabled)
- writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
+ gic_configure_irq(gicirq, type, base, NULL);
raw_spin_unlock(&irq_controller_lock);
@@ -388,12 +363,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
writel_relaxed(0, base + GIC_DIST_CTRL);
/*
- * Set all global interrupts to be level triggered, active low.
- */
- for (i = 32; i < gic_irqs; i += 16)
- writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
-
- /*
* Set all global interrupts to this CPU only.
*/
cpumask = gic_get_cpumask(gic);
@@ -402,18 +371,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
- /*
- * Set priority on all global interrupts.
- */
- for (i = 32; i < gic_irqs; i += 4)
- writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
-
- /*
- * Disable all interrupts. Leave the PPI and SGIs alone
- * as these enables are banked registers.
- */
- for (i = 32; i < gic_irqs; i += 32)
- writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
+ gic_dist_config(base, gic_irqs, NULL);
writel_relaxed(1, base + GIC_DIST_CTRL);
}
@@ -440,18 +398,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
if (i != cpu)
gic_cpu_map[i] &= ~cpu_mask;
- /*
- * Deal with the banked PPI and SGI interrupts - disable all
- * PPI interrupts, ensure all SGI interrupts are enabled.
- */
- writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
- writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
-
- /*
- * Set priority on PPI and SGI interrupts
- */
- for (i = 0; i < 32; i += 4)
- writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
+ gic_cpu_config(dist_base, NULL);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c
index 70bdf6edb7bb..4ff0805fca01 100644
--- a/drivers/irqchip/irq-nvic.c
+++ b/drivers/irqchip/irq-nvic.c
@@ -49,14 +49,6 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
handle_IRQ(irq, regs);
}
-static void nvic_eoi(struct irq_data *d)
-{
- /*
- * This is a no-op as end of interrupt is signaled by the exception
- * return sequence.
- */
-}
-
static int __init nvic_of_init(struct device_node *node,
struct device_node *parent)
{
@@ -102,7 +94,10 @@ static int __init nvic_of_init(struct device_node *node,
gc->chip_types[0].regs.disable = NVIC_ICER;
gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
- gc->chip_types[0].chip.irq_eoi = nvic_eoi;
+ /* This is a no-op as end of interrupt is signaled by the
+ * exception return sequence.
+ */
+ gc->chip_types[0].chip.irq_eoi = irq_gc_noop;
/* disable interrupts */
writel_relaxed(~0, gc->reg_base + NVIC_ICER);
diff --git a/drivers/irqchip/irq-or1k-pic.c b/drivers/irqchip/irq-or1k-pic.c
new file mode 100644
index 000000000000..17ff033d9925
--- /dev/null
+++ b/drivers/irqchip/irq-or1k-pic.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi>
+ *
+ * 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/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include "irqchip.h"
+
+/* OR1K PIC implementation */
+
+struct or1k_pic_dev {
+ struct irq_chip chip;
+ irq_flow_handler_t handle;
+ unsigned long flags;
+};
+
+/*
+ * We're a couple of cycles faster than the generic implementations with
+ * these 'fast' versions.
+ */
+
+static void or1k_pic_mask(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+}
+
+static void or1k_pic_unmask(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
+}
+
+static void or1k_pic_ack(struct irq_data *data)
+{
+ mtspr(SPR_PICSR, (1UL << data->hwirq));
+}
+
+static void or1k_pic_mask_ack(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+ mtspr(SPR_PICSR, (1UL << data->hwirq));
+}
+
+/*
+ * There are two oddities with the OR1200 PIC implementation:
+ * i) LEVEL-triggered interrupts are latched and need to be cleared
+ * ii) the interrupt latch is cleared by writing a 0 to the bit,
+ * as opposed to a 1 as mandated by the spec
+ */
+static void or1k_pic_or1200_ack(struct irq_data *data)
+{
+ mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
+}
+
+static void or1k_pic_or1200_mask_ack(struct irq_data *data)
+{
+ mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+ mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
+}
+
+static struct or1k_pic_dev or1k_pic_level = {
+ .chip = {
+ .name = "or1k-PIC-level",
+ .irq_unmask = or1k_pic_unmask,
+ .irq_mask = or1k_pic_mask,
+ .irq_mask_ack = or1k_pic_mask,
+ },
+ .handle = handle_level_irq,
+ .flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct or1k_pic_dev or1k_pic_edge = {
+ .chip = {
+ .name = "or1k-PIC-edge",
+ .irq_unmask = or1k_pic_unmask,
+ .irq_mask = or1k_pic_mask,
+ .irq_ack = or1k_pic_ack,
+ .irq_mask_ack = or1k_pic_mask_ack,
+ },
+ .handle = handle_edge_irq,
+ .flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct or1k_pic_dev or1k_pic_or1200 = {
+ .chip = {
+ .name = "or1200-PIC",
+ .irq_unmask = or1k_pic_unmask,
+ .irq_mask = or1k_pic_mask,
+ .irq_ack = or1k_pic_or1200_ack,
+ .irq_mask_ack = or1k_pic_or1200_mask_ack,
+ },
+ .handle = handle_level_irq,
+ .flags = IRQ_LEVEL | IRQ_NOPROBE,
+};
+
+static struct irq_domain *root_domain;
+
+static inline int pic_get_irq(int first)
+{
+ int hwirq;
+
+ hwirq = ffs(mfspr(SPR_PICSR) >> first);
+ if (!hwirq)
+ return NO_IRQ;
+ else
+ hwirq = hwirq + first - 1;
+
+ return irq_find_mapping(root_domain, hwirq);
+}
+
+static void or1k_pic_handle_irq(struct pt_regs *regs)
+{
+ int irq = -1;
+
+ while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
+ handle_IRQ(irq, regs);
+}
+
+static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ struct or1k_pic_dev *pic = d->host_data;
+
+ irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
+ irq_set_status_flags(irq, pic->flags);
+
+ return 0;
+}
+
+static const struct irq_domain_ops or1k_irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = or1k_map,
+};
+
+/*
+ * This sets up the IRQ domain for the PIC built in to the OpenRISC
+ * 1000 CPU. This is the "root" domain as these are the interrupts
+ * that directly trigger an exception in the CPU.
+ */
+static int __init or1k_pic_init(struct device_node *node,
+ struct or1k_pic_dev *pic)
+{
+ /* Disable all interrupts until explicitly requested */
+ mtspr(SPR_PICMR, (0UL));
+
+ root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
+ pic);
+
+ set_handle_irq(or1k_pic_handle_irq);
+
+ return 0;
+}
+
+static int __init or1k_pic_or1200_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return or1k_pic_init(node, &or1k_pic_or1200);
+}
+IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic", or1k_pic_or1200_init);
+IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic", or1k_pic_or1200_init);
+
+static int __init or1k_pic_level_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return or1k_pic_init(node, &or1k_pic_level);
+}
+IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level",
+ or1k_pic_level_init);
+
+static int __init or1k_pic_edge_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return or1k_pic_init(node, &or1k_pic_edge);
+}
+IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge", or1k_pic_edge_init);
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 3ae2bb8d9cf2..ccf58548b161 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -14,6 +14,8 @@
#include <asm/exception.h>
#include <asm/mach/irq.h>
+#include "irqchip.h"
+
#define IRQ_STATUS 0x00
#define IRQ_RAW_STATUS 0x04
#define IRQ_ENABLE_SET 0x08
@@ -26,6 +28,8 @@
#define FIQ_ENABLE_SET 0x28
#define FIQ_ENABLE_CLEAR 0x2C
+#define PIC_ENABLES 0x20 /* set interrupt pass through bits */
+
/**
* struct fpga_irq_data - irq data container for the FPGA IRQ controller
* @base: memory offset in virtual memory
@@ -201,14 +205,26 @@ int __init fpga_irq_of_init(struct device_node *node,
/* Some chips are cascaded from a parent IRQ */
parent_irq = irq_of_parse_and_map(node, 0);
- if (!parent_irq)
+ if (!parent_irq) {
+ set_handle_irq(fpga_handle_irq);
parent_irq = -1;
+ }
fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
writel(clear_mask, base + IRQ_ENABLE_CLEAR);
writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+ /*
+ * On Versatile AB/PB, some secondary interrupts have a direct
+ * pass-thru to the primary controller for IRQs 20 and 22-31 which need
+ * to be enabled. See section 3.10 of the Versatile AB user guide.
+ */
+ if (of_device_is_compatible(node, "arm,versatile-sic"))
+ writel(0xffd00000, base + PIC_ENABLES);
+
return 0;
}
+IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
+IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
#endif
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 6ce6bd3441bf..9c145a7cb056 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
-#include <linux/irqchip/spear-shirq.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@@ -27,20 +26,73 @@
#include "irqchip.h"
-static DEFINE_SPINLOCK(lock);
+/*
+ * struct spear_shirq: shared irq structure
+ *
+ * base: Base register address
+ * status_reg: Status register offset for chained interrupt handler
+ * mask_reg: Mask register offset for irq chip
+ * mask: Mask to apply to the status register
+ * virq_base: Base virtual interrupt number
+ * nr_irqs: Number of interrupts handled by this block
+ * offset: Bit offset of the first interrupt
+ * irq_chip: Interrupt controller chip used for this instance,
+ * if NULL group is disabled, but accounted
+ */
+struct spear_shirq {
+ void __iomem *base;
+ u32 status_reg;
+ u32 mask_reg;
+ u32 mask;
+ u32 virq_base;
+ u32 nr_irqs;
+ u32 offset;
+ struct irq_chip *irq_chip;
+};
/* spear300 shared irq registers offsets and masks */
#define SPEAR300_INT_ENB_MASK_REG 0x54
#define SPEAR300_INT_STS_MASK_REG 0x58
+static DEFINE_RAW_SPINLOCK(shirq_lock);
+
+static void shirq_irq_mask(struct irq_data *d)
+{
+ struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+ u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
+ u32 __iomem *reg = shirq->base + shirq->mask_reg;
+
+ raw_spin_lock(&shirq_lock);
+ val = readl(reg) & ~(0x1 << shift);
+ writel(val, reg);
+ raw_spin_unlock(&shirq_lock);
+}
+
+static void shirq_irq_unmask(struct irq_data *d)
+{
+ struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
+ u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
+ u32 __iomem *reg = shirq->base + shirq->mask_reg;
+
+ raw_spin_lock(&shirq_lock);
+ val = readl(reg) | (0x1 << shift);
+ writel(val, reg);
+ raw_spin_unlock(&shirq_lock);
+}
+
+static struct irq_chip shirq_chip = {
+ .name = "spear-shirq",
+ .irq_mask = shirq_irq_mask,
+ .irq_unmask = shirq_irq_unmask,
+};
+
static struct spear_shirq spear300_shirq_ras1 = {
- .irq_nr = 9,
- .irq_bit_off = 0,
- .regs = {
- .enb_reg = SPEAR300_INT_ENB_MASK_REG,
- .status_reg = SPEAR300_INT_STS_MASK_REG,
- .clear_reg = -1,
- },
+ .offset = 0,
+ .nr_irqs = 9,
+ .mask = ((0x1 << 9) - 1) << 0,
+ .irq_chip = &shirq_chip,
+ .status_reg = SPEAR300_INT_STS_MASK_REG,
+ .mask_reg = SPEAR300_INT_ENB_MASK_REG,
};
static struct spear_shirq *spear300_shirq_blocks[] = {
@@ -51,43 +103,35 @@ static struct spear_shirq *spear300_shirq_blocks[] = {
#define SPEAR310_INT_STS_MASK_REG 0x04
static struct spear_shirq spear310_shirq_ras1 = {
- .irq_nr = 8,
- .irq_bit_off = 0,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR310_INT_STS_MASK_REG,
- .clear_reg = -1,
- },
+ .offset = 0,
+ .nr_irqs = 8,
+ .mask = ((0x1 << 8) - 1) << 0,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR310_INT_STS_MASK_REG,
};
static struct spear_shirq spear310_shirq_ras2 = {
- .irq_nr = 5,
- .irq_bit_off = 8,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR310_INT_STS_MASK_REG,
- .clear_reg = -1,
- },
+ .offset = 8,
+ .nr_irqs = 5,
+ .mask = ((0x1 << 5) - 1) << 8,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR310_INT_STS_MASK_REG,
};
static struct spear_shirq spear310_shirq_ras3 = {
- .irq_nr = 1,
- .irq_bit_off = 13,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR310_INT_STS_MASK_REG,
- .clear_reg = -1,
- },
+ .offset = 13,
+ .nr_irqs = 1,
+ .mask = ((0x1 << 1) - 1) << 13,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR310_INT_STS_MASK_REG,
};
static struct spear_shirq spear310_shirq_intrcomm_ras = {
- .irq_nr = 3,
- .irq_bit_off = 14,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR310_INT_STS_MASK_REG,
- .clear_reg = -1,
- },
+ .offset = 14,
+ .nr_irqs = 3,
+ .mask = ((0x1 << 3) - 1) << 14,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR310_INT_STS_MASK_REG,
};
static struct spear_shirq *spear310_shirq_blocks[] = {
@@ -102,50 +146,34 @@ static struct spear_shirq *spear310_shirq_blocks[] = {
#define SPEAR320_INT_CLR_MASK_REG 0x04
#define SPEAR320_INT_ENB_MASK_REG 0x08
-static struct spear_shirq spear320_shirq_ras1 = {
- .irq_nr = 3,
- .irq_bit_off = 7,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR320_INT_STS_MASK_REG,
- .clear_reg = SPEAR320_INT_CLR_MASK_REG,
- .reset_to_clear = 1,
- },
+static struct spear_shirq spear320_shirq_ras3 = {
+ .offset = 0,
+ .nr_irqs = 7,
+ .mask = ((0x1 << 7) - 1) << 0,
};
-static struct spear_shirq spear320_shirq_ras2 = {
- .irq_nr = 1,
- .irq_bit_off = 10,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR320_INT_STS_MASK_REG,
- .clear_reg = SPEAR320_INT_CLR_MASK_REG,
- .reset_to_clear = 1,
- },
+static struct spear_shirq spear320_shirq_ras1 = {
+ .offset = 7,
+ .nr_irqs = 3,
+ .mask = ((0x1 << 3) - 1) << 7,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR320_INT_STS_MASK_REG,
};
-static struct spear_shirq spear320_shirq_ras3 = {
- .irq_nr = 7,
- .irq_bit_off = 0,
- .invalid_irq = 1,
- .regs = {
- .enb_reg = SPEAR320_INT_ENB_MASK_REG,
- .reset_to_enb = 1,
- .status_reg = SPEAR320_INT_STS_MASK_REG,
- .clear_reg = SPEAR320_INT_CLR_MASK_REG,
- .reset_to_clear = 1,
- },
+static struct spear_shirq spear320_shirq_ras2 = {
+ .offset = 10,
+ .nr_irqs = 1,
+ .mask = ((0x1 << 1) - 1) << 10,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR320_INT_STS_MASK_REG,
};
static struct spear_shirq spear320_shirq_intrcomm_ras = {
- .irq_nr = 11,
- .irq_bit_off = 11,
- .regs = {
- .enb_reg = -1,
- .status_reg = SPEAR320_INT_STS_MASK_REG,
- .clear_reg = SPEAR320_INT_CLR_MASK_REG,
- .reset_to_clear = 1,
- },
+ .offset = 11,
+ .nr_irqs = 11,
+ .mask = ((0x1 << 11) - 1) << 11,
+ .irq_chip = &dummy_irq_chip,
+ .status_reg = SPEAR320_INT_STS_MASK_REG,
};
static struct spear_shirq *spear320_shirq_blocks[] = {
@@ -155,104 +183,46 @@ static struct spear_shirq *spear320_shirq_blocks[] = {
&spear320_shirq_intrcomm_ras,
};
-static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
-{
- struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
- u32 val, offset = d->irq - shirq->irq_base;
- unsigned long flags;
-
- if (shirq->regs.enb_reg == -1)
- return;
-
- spin_lock_irqsave(&lock, flags);
- val = readl(shirq->base + shirq->regs.enb_reg);
-
- if (mask ^ shirq->regs.reset_to_enb)
- val &= ~(0x1 << shirq->irq_bit_off << offset);
- else
- val |= 0x1 << shirq->irq_bit_off << offset;
-
- writel(val, shirq->base + shirq->regs.enb_reg);
- spin_unlock_irqrestore(&lock, flags);
-
-}
-
-static void shirq_irq_mask(struct irq_data *d)
-{
- shirq_irq_mask_unmask(d, 1);
-}
-
-static void shirq_irq_unmask(struct irq_data *d)
-{
- shirq_irq_mask_unmask(d, 0);
-}
-
-static struct irq_chip shirq_chip = {
- .name = "spear-shirq",
- .irq_ack = shirq_irq_mask,
- .irq_mask = shirq_irq_mask,
- .irq_unmask = shirq_irq_unmask,
-};
-
static void shirq_handler(unsigned irq, struct irq_desc *desc)
{
- u32 i, j, val, mask, tmp;
- struct irq_chip *chip;
struct spear_shirq *shirq = irq_get_handler_data(irq);
+ u32 pend;
- chip = irq_get_chip(irq);
- chip->irq_ack(&desc->irq_data);
-
- mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
- while ((val = readl(shirq->base + shirq->regs.status_reg) &
- mask)) {
-
- val >>= shirq->irq_bit_off;
- for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
-
- if (!(j & val))
- continue;
+ pend = readl(shirq->base + shirq->status_reg) & shirq->mask;
+ pend >>= shirq->offset;
- generic_handle_irq(shirq->irq_base + i);
+ while (pend) {
+ int irq = __ffs(pend);
- /* clear interrupt */
- if (shirq->regs.clear_reg == -1)
- continue;
-
- tmp = readl(shirq->base + shirq->regs.clear_reg);
- if (shirq->regs.reset_to_clear)
- tmp &= ~(j << shirq->irq_bit_off);
- else
- tmp |= (j << shirq->irq_bit_off);
- writel(tmp, shirq->base + shirq->regs.clear_reg);
- }
+ pend &= ~(0x1 << irq);
+ generic_handle_irq(shirq->virq_base + irq);
}
- chip->irq_unmask(&desc->irq_data);
}
-static void __init spear_shirq_register(struct spear_shirq *shirq)
+static void __init spear_shirq_register(struct spear_shirq *shirq,
+ int parent_irq)
{
int i;
- if (shirq->invalid_irq)
+ if (!shirq->irq_chip)
return;
- irq_set_chained_handler(shirq->irq, shirq_handler);
- for (i = 0; i < shirq->irq_nr; i++) {
- irq_set_chip_and_handler(shirq->irq_base + i,
- &shirq_chip, handle_simple_irq);
- set_irq_flags(shirq->irq_base + i, IRQF_VALID);
- irq_set_chip_data(shirq->irq_base + i, shirq);
- }
+ irq_set_chained_handler(parent_irq, shirq_handler);
+ irq_set_handler_data(parent_irq, shirq);
- irq_set_handler_data(shirq->irq, shirq);
+ for (i = 0; i < shirq->nr_irqs; i++) {
+ irq_set_chip_and_handler(shirq->virq_base + i,
+ shirq->irq_chip, handle_simple_irq);
+ set_irq_flags(shirq->virq_base + i, IRQF_VALID);
+ irq_set_chip_data(shirq->virq_base + i, shirq);
+ }
}
static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
struct device_node *np)
{
- int i, irq_base, hwirq = 0, irq_nr = 0;
- static struct irq_domain *shirq_domain;
+ int i, parent_irq, virq_base, hwirq = 0, nr_irqs = 0;
+ struct irq_domain *shirq_domain;
void __iomem *base;
base = of_iomap(np, 0);
@@ -262,15 +232,15 @@ static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
}
for (i = 0; i < block_nr; i++)
- irq_nr += shirq_blocks[i]->irq_nr;
+ nr_irqs += shirq_blocks[i]->nr_irqs;
- irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
- if (IS_ERR_VALUE(irq_base)) {
+ virq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
+ if (IS_ERR_VALUE(virq_base)) {
pr_err("%s: irq desc alloc failed\n", __func__);
goto err_unmap;
}
- shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
+ shirq_domain = irq_domain_add_legacy(np, nr_irqs, virq_base, 0,
&irq_domain_simple_ops, NULL);
if (WARN_ON(!shirq_domain)) {
pr_warn("%s: irq domain init failed\n", __func__);
@@ -279,41 +249,41 @@ static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
for (i = 0; i < block_nr; i++) {
shirq_blocks[i]->base = base;
- shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
+ shirq_blocks[i]->virq_base = irq_find_mapping(shirq_domain,
hwirq);
- shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
- spear_shirq_register(shirq_blocks[i]);
- hwirq += shirq_blocks[i]->irq_nr;
+ parent_irq = irq_of_parse_and_map(np, i);
+ spear_shirq_register(shirq_blocks[i], parent_irq);
+ hwirq += shirq_blocks[i]->nr_irqs;
}
return 0;
err_free_desc:
- irq_free_descs(irq_base, irq_nr);
+ irq_free_descs(virq_base, nr_irqs);
err_unmap:
iounmap(base);
return -ENXIO;
}
-int __init spear300_shirq_of_init(struct device_node *np,
- struct device_node *parent)
+static int __init spear300_shirq_of_init(struct device_node *np,
+ struct device_node *parent)
{
return shirq_init(spear300_shirq_blocks,
ARRAY_SIZE(spear300_shirq_blocks), np);
}
IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init);
-int __init spear310_shirq_of_init(struct device_node *np,
- struct device_node *parent)
+static int __init spear310_shirq_of_init(struct device_node *np,
+ struct device_node *parent)
{
return shirq_init(spear310_shirq_blocks,
ARRAY_SIZE(spear310_shirq_blocks), np);
}
IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init);
-int __init spear320_shirq_of_init(struct device_node *np,
- struct device_node *parent)
+static int __init spear320_shirq_of_init(struct device_node *np,
+ struct device_node *parent)
{
return shirq_init(spear320_shirq_blocks,
ARRAY_SIZE(spear320_shirq_blocks), np);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index f9a87ed2392b..6a2df3297e77 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1260,7 +1260,7 @@ static int __init capinc_tty_init(void)
if (capi_ttyminors <= 0)
capi_ttyminors = CAPINC_NR_PORTS;
- capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors,
+ capiminors = kzalloc(sizeof(struct capiminor *) * capi_ttyminors,
GFP_KERNEL);
if (!capiminors)
return -ENOMEM;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index d9aebbc510cc..94affa5e6f28 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2588,7 +2588,8 @@ isdn_net_new(char *name, struct net_device *master)
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
return NULL;
}
- netdev->dev = alloc_netdev(sizeof(isdn_net_local), name, _isdn_setup);
+ netdev->dev = alloc_netdev(sizeof(isdn_net_local), name,
+ NET_NAME_UNKNOWN, _isdn_setup);
if (!netdev->dev) {
printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
kfree(netdev);
@@ -2917,8 +2918,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
cfg->callback = 2;
cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
- cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
- cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
+ cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
+ cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
cfg->cbdelay = lp->cbdelay;
cfg->dialmax = lp->dialmax;
cfg->triggercps = lp->triggercps;
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 62f0688d45a5..c4198fa490bf 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -379,12 +379,12 @@ isdn_ppp_release(int min, struct file *file)
#endif
#ifdef CONFIG_IPPP_FILTER
if (is->pass_filter) {
- sk_unattached_filter_destroy(is->pass_filter);
+ bpf_prog_destroy(is->pass_filter);
is->pass_filter = NULL;
}
if (is->active_filter) {
- sk_unattached_filter_destroy(is->active_filter);
+ bpf_prog_destroy(is->active_filter);
is->active_filter = NULL;
}
#endif
@@ -639,12 +639,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
fprog.filter = code;
if (is->pass_filter) {
- sk_unattached_filter_destroy(is->pass_filter);
+ bpf_prog_destroy(is->pass_filter);
is->pass_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&is->pass_filter,
- &fprog);
+ err = bpf_prog_create(&is->pass_filter, &fprog);
else
err = 0;
kfree(code);
@@ -664,12 +663,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
fprog.filter = code;
if (is->active_filter) {
- sk_unattached_filter_destroy(is->active_filter);
+ bpf_prog_destroy(is->active_filter);
is->active_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&is->active_filter,
- &fprog);
+ err = bpf_prog_create(&is->active_filter, &fprog);
else
err = 0;
kfree(code);
@@ -1174,14 +1172,14 @@ isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *
}
if (is->pass_filter
- && SK_RUN_FILTER(is->pass_filter, skb) == 0) {
+ && BPF_PROG_RUN(is->pass_filter, skb) == 0) {
if (is->debug & 0x2)
printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
kfree_skb(skb);
return;
}
if (!(is->active_filter
- && SK_RUN_FILTER(is->active_filter, skb) == 0)) {
+ && BPF_PROG_RUN(is->active_filter, skb) == 0)) {
if (is->debug & 0x2)
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
lp->huptimer = 0;
@@ -1320,14 +1318,14 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
}
if (ipt->pass_filter
- && SK_RUN_FILTER(ipt->pass_filter, skb) == 0) {
+ && BPF_PROG_RUN(ipt->pass_filter, skb) == 0) {
if (ipt->debug & 0x4)
printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
kfree_skb(skb);
goto unlock;
}
if (!(ipt->active_filter
- && SK_RUN_FILTER(ipt->active_filter, skb) == 0)) {
+ && BPF_PROG_RUN(ipt->active_filter, skb) == 0)) {
if (ipt->debug & 0x4)
printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
lp->huptimer = 0;
@@ -1517,9 +1515,9 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
}
drop |= is->pass_filter
- && SK_RUN_FILTER(is->pass_filter, skb) == 0;
+ && BPF_PROG_RUN(is->pass_filter, skb) == 0;
drop |= is->active_filter
- && SK_RUN_FILTER(is->active_filter, skb) == 0;
+ && BPF_PROG_RUN(is->active_filter, skb) == 0;
skb_push(skb, IPPP_MAX_HEADER - 4);
return drop;
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index f02cc506fbfa..4172e22ae7ed 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -1035,14 +1035,14 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list)
}
ptr->next = NULL;
- ptr->msn = kmalloc(len, GFP_ATOMIC);
+ ptr->msn = kmalloc(len + 1, GFP_ATOMIC);
if (!ptr->msn) {
printk(KERN_WARNING "kmalloc failed\n");
kfree(ptr);
return;
}
- memcpy(ptr->msn, sp, len - 1);
+ memcpy(ptr->msn, sp, len);
ptr->msn[len] = 0;
#ifdef DEBUG
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a1b044e7eaad..8c96e2ddf43b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -32,14 +32,6 @@ config LEDS_88PM860X
This option enables support for on-chip LED drivers found on Marvell
Semiconductor 88PM8606 PMIC.
-config LEDS_ATMEL_PWM
- tristate "LED Support using Atmel PWM outputs"
- depends on LEDS_CLASS
- depends on ATMEL_PWM
- help
- This option enables support for LEDs driven using outputs
- of the dedicated PWM controller found on newer Atmel SOCs.
-
config LEDS_LM3530
tristate "LCD Backlight driver for LM3530"
depends on LEDS_CLASS
@@ -143,6 +135,13 @@ config LEDS_SUNFIRE
This option enables support for the Left, Middle, and Right
LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
+config LEDS_IPAQ_MICRO
+ tristate "LED Support for the Compaq iPAQ h3xxx"
+ depends on MFD_IPAQ_MICRO
+ help
+ Choose this option if you want to use the notification LED on
+ Compaq/HP iPAQ h3100 and h3600.
+
config LEDS_HP6XX
tristate "LED Support for the HP Jornada 6xx"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 79c5155199a7..d8cc5f2777de 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
# LED Platform Drivers
obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
-obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
@@ -31,6 +30,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o
obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o
obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
+obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_OT200) += leds-ot200.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index f37d63cf726b..129729d35478 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -15,10 +15,10 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
-#include <linux/timer.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/leds.h>
+#include <linux/workqueue.h>
#include "leds.h"
static struct class *leds_class;
@@ -97,9 +97,10 @@ static const struct attribute_group *led_groups[] = {
NULL,
};
-static void led_timer_function(unsigned long data)
+static void led_work_function(struct work_struct *ws)
{
- struct led_classdev *led_cdev = (void *)data;
+ struct led_classdev *led_cdev =
+ container_of(ws, struct led_classdev, blink_work.work);
unsigned long brightness;
unsigned long delay;
@@ -143,7 +144,8 @@ static void led_timer_function(unsigned long data)
}
}
- mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
+ queue_delayed_work(system_wq, &led_cdev->blink_work,
+ msecs_to_jiffies(delay));
}
static void set_brightness_delayed(struct work_struct *ws)
@@ -210,8 +212,9 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
*/
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
- led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
- "%s", led_cdev->name);
+ led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
+ led_cdev, led_cdev->groups,
+ "%s", led_cdev->name);
if (IS_ERR(led_cdev->dev))
return PTR_ERR(led_cdev->dev);
@@ -230,9 +233,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
- init_timer(&led_cdev->blink_timer);
- led_cdev->blink_timer.function = led_timer_function;
- led_cdev->blink_timer.data = (unsigned long)led_cdev;
+ INIT_DELAYED_WORK(&led_cdev->blink_work, led_work_function);
#ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 71b40d3bf776..4bb116867b88 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/leds.h>
+#include <linux/workqueue.h>
#include "leds.h"
DECLARE_RWSEM(leds_list_lock);
@@ -51,7 +52,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
return;
}
- mod_timer(&led_cdev->blink_timer, jiffies + 1);
+ queue_delayed_work(system_wq, &led_cdev->blink_work, 1);
}
@@ -75,7 +76,7 @@ void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
- del_timer_sync(&led_cdev->blink_timer);
+ cancel_delayed_work_sync(&led_cdev->blink_work);
led_cdev->flags &= ~LED_BLINK_ONESHOT;
led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
@@ -90,7 +91,7 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
int invert)
{
if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
- timer_pending(&led_cdev->blink_timer))
+ delayed_work_pending(&led_cdev->blink_work))
return;
led_cdev->flags |= LED_BLINK_ONESHOT;
@@ -107,7 +108,7 @@ EXPORT_SYMBOL(led_blink_set_oneshot);
void led_stop_software_blink(struct led_classdev *led_cdev)
{
- del_timer_sync(&led_cdev->blink_timer);
+ cancel_delayed_work_sync(&led_cdev->blink_work);
led_cdev->blink_delay_on = 0;
led_cdev->blink_delay_off = 0;
}
@@ -116,7 +117,7 @@ EXPORT_SYMBOL_GPL(led_stop_software_blink);
void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
- /* delay brightness setting if need to stop soft-blink timer */
+ /* delay brightness setting if need to stop soft-blink work */
if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
led_cdev->delayed_set_value = brightness;
schedule_work(&led_cdev->set_brightness_work);
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
deleted file mode 100644
index 56cec8d6a2ac..000000000000
--- a/drivers/leds/leds-atmel-pwm.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/io.h>
-#include <linux/atmel_pwm.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-
-struct pwmled {
- struct led_classdev cdev;
- struct pwm_channel pwmc;
- struct gpio_led *desc;
- u32 mult;
- u8 active_low;
-};
-
-
-/*
- * For simplicity, we use "brightness" as if it were a linear function
- * of PWM duty cycle. However, a logarithmic function of duty cycle is
- * probably a better match for perceived brightness: two is half as bright
- * as four, four is half as bright as eight, etc
- */
-static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
-{
- struct pwmled *led;
-
- /* update the duty cycle for the *next* period */
- led = container_of(cdev, struct pwmled, cdev);
- pwm_channel_writel(&led->pwmc, PWM_CUPD, led->mult * (unsigned) b);
-}
-
-/*
- * NOTE: we reuse the platform_data structure of GPIO leds,
- * but repurpose its "gpio" number as a PWM channel number.
- */
-static int pwmled_probe(struct platform_device *pdev)
-{
- const struct gpio_led_platform_data *pdata;
- struct pwmled *leds;
- int i;
- int status;
-
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata || pdata->num_leds < 1)
- return -ENODEV;
-
- leds = devm_kzalloc(&pdev->dev, pdata->num_leds * sizeof(*leds),
- GFP_KERNEL);
- if (!leds)
- return -ENOMEM;
-
- for (i = 0; i < pdata->num_leds; i++) {
- struct pwmled *led = leds + i;
- const struct gpio_led *dat = pdata->leds + i;
- u32 tmp;
-
- led->cdev.name = dat->name;
- led->cdev.brightness = LED_OFF;
- led->cdev.brightness_set = pwmled_brightness;
- led->cdev.default_trigger = dat->default_trigger;
-
- led->active_low = dat->active_low;
-
- status = pwm_channel_alloc(dat->gpio, &led->pwmc);
- if (status < 0)
- goto err;
-
- /*
- * Prescale clock by 2^x, so PWM counts in low MHz.
- * Start each cycle with the LED active, so increasing
- * the duty cycle gives us more time on (== brighter).
- */
- tmp = 5;
- if (!led->active_low)
- tmp |= PWM_CPR_CPOL;
- pwm_channel_writel(&led->pwmc, PWM_CMR, tmp);
-
- /*
- * Pick a period so PWM cycles at 100+ Hz; and a multiplier
- * for scaling duty cycle: brightness * mult.
- */
- tmp = (led->pwmc.mck / (1 << 5)) / 100;
- tmp /= 255;
- led->mult = tmp;
- pwm_channel_writel(&led->pwmc, PWM_CDTY,
- led->cdev.brightness * 255);
- pwm_channel_writel(&led->pwmc, PWM_CPRD,
- LED_FULL * tmp);
-
- pwm_channel_enable(&led->pwmc);
-
- /* Hand it over to the LED framework */
- status = led_classdev_register(&pdev->dev, &led->cdev);
- if (status < 0) {
- pwm_channel_free(&led->pwmc);
- goto err;
- }
- }
-
- platform_set_drvdata(pdev, leds);
- return 0;
-
-err:
- if (i > 0) {
- for (i = i - 1; i >= 0; i--) {
- led_classdev_unregister(&leds[i].cdev);
- pwm_channel_free(&leds[i].pwmc);
- }
- }
-
- return status;
-}
-
-static int pwmled_remove(struct platform_device *pdev)
-{
- const struct gpio_led_platform_data *pdata;
- struct pwmled *leds;
- unsigned i;
-
- pdata = dev_get_platdata(&pdev->dev);
- leds = platform_get_drvdata(pdev);
-
- for (i = 0; i < pdata->num_leds; i++) {
- struct pwmled *led = leds + i;
-
- led_classdev_unregister(&led->cdev);
- pwm_channel_free(&led->pwmc);
- }
-
- return 0;
-}
-
-static struct platform_driver pwmled_driver = {
- .driver = {
- .name = "leds-atmel-pwm",
- .owner = THIS_MODULE,
- },
- /* REVISIT add suspend() and resume() methods */
- .probe = pwmled_probe,
- .remove = pwmled_remove,
-};
-
-module_platform_driver(pwmled_driver);
-
-MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:leds-atmel-pwm");
diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c
new file mode 100644
index 000000000000..3776f516cd88
--- /dev/null
+++ b/drivers/leds/leds-ipaq-micro.c
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * h3xxx atmel micro companion support, notification LED subdevice
+ *
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ipaq-micro.h>
+#include <linux/leds.h>
+
+#define LED_YELLOW 0x00
+#define LED_GREEN 0x01
+
+#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
+#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
+#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
+
+static void micro_leds_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
+ /*
+ * In this message:
+ * Byte 0 = LED color: 0 = yellow, 1 = green
+ * yellow LED is always ~30 blinks per minute
+ * Byte 1 = duration (flags?) appears to be ignored
+ * Byte 2 = green ontime in 1/10 sec (deciseconds)
+ * 1 = 1/10 second
+ * 0 = 256/10 second
+ * Byte 3 = green offtime in 1/10 sec (deciseconds)
+ * 1 = 1/10 second
+ * 0 = 256/10 seconds
+ */
+ struct ipaq_micro_msg msg = {
+ .id = MSG_NOTIFY_LED,
+ .tx_len = 4,
+ };
+
+ msg.tx_data[0] = LED_GREEN;
+ msg.tx_data[1] = 0;
+ if (value) {
+ msg.tx_data[2] = 0; /* Duty cycle 256 */
+ msg.tx_data[3] = 1;
+ } else {
+ msg.tx_data[2] = 1;
+ msg.tx_data[3] = 0; /* Duty cycle 256 */
+ }
+ ipaq_micro_tx_msg_sync(micro, &msg);
+}
+
+/* Maximum duty cycle in ms 256/10 sec = 25600 ms */
+#define IPAQ_LED_MAX_DUTY 25600
+
+static int micro_leds_blink_set(struct led_classdev *led_cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
+ /*
+ * In this message:
+ * Byte 0 = LED color: 0 = yellow, 1 = green
+ * yellow LED is always ~30 blinks per minute
+ * Byte 1 = duration (flags?) appears to be ignored
+ * Byte 2 = green ontime in 1/10 sec (deciseconds)
+ * 1 = 1/10 second
+ * 0 = 256/10 second
+ * Byte 3 = green offtime in 1/10 sec (deciseconds)
+ * 1 = 1/10 second
+ * 0 = 256/10 seconds
+ */
+ struct ipaq_micro_msg msg = {
+ .id = MSG_NOTIFY_LED,
+ .tx_len = 4,
+ };
+
+ msg.tx_data[0] = LED_GREEN;
+ if (*delay_on > IPAQ_LED_MAX_DUTY ||
+ *delay_off > IPAQ_LED_MAX_DUTY)
+ return -EINVAL;
+
+ if (*delay_on == 0 && *delay_off == 0) {
+ *delay_on = 100;
+ *delay_off = 100;
+ }
+
+ msg.tx_data[1] = 0;
+ if (*delay_on >= IPAQ_LED_MAX_DUTY)
+ msg.tx_data[2] = 0;
+ else
+ msg.tx_data[2] = (u8) DIV_ROUND_CLOSEST(*delay_on, 100);
+ if (*delay_off >= IPAQ_LED_MAX_DUTY)
+ msg.tx_data[3] = 0;
+ else
+ msg.tx_data[3] = (u8) DIV_ROUND_CLOSEST(*delay_off, 100);
+ return ipaq_micro_tx_msg_sync(micro, &msg);
+}
+
+static struct led_classdev micro_led = {
+ .name = "led-ipaq-micro",
+ .brightness_set = micro_leds_brightness_set,
+ .blink_set = micro_leds_blink_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static int micro_leds_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &micro_led);
+ if (ret) {
+ dev_err(&pdev->dev, "registering led failed: %d\n", ret);
+ return ret;
+ }
+ dev_info(&pdev->dev, "iPAQ micro notification LED driver\n");
+
+ return 0;
+}
+
+static int micro_leds_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&micro_led);
+ return 0;
+}
+
+static struct platform_driver micro_leds_device_driver = {
+ .driver = {
+ .name = "ipaq-micro-leds",
+ },
+ .probe = micro_leds_probe,
+ .remove = micro_leds_remove,
+};
+module_platform_driver(micro_leds_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro leds");
+MODULE_ALIAS("platform:ipaq-micro-leds");
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 652368c2ea9a..91325de3cd33 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -400,6 +400,12 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
+static struct attribute *lm3530_attrs[] = {
+ &dev_attr_mode.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lm3530);
+
static int lm3530_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -436,6 +442,7 @@ static int lm3530_probe(struct i2c_client *client,
drvdata->led_dev.name = LM3530_LED_DEV;
drvdata->led_dev.brightness_set = lm3530_brightness_set;
drvdata->led_dev.max_brightness = MAX_BRIGHTNESS;
+ drvdata->led_dev.groups = lm3530_groups;
i2c_set_clientdata(client, drvdata);
@@ -461,26 +468,13 @@ static int lm3530_probe(struct i2c_client *client,
return err;
}
- err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
- if (err < 0) {
- dev_err(&client->dev, "File device creation failed: %d\n", err);
- err = -ENODEV;
- goto err_create_file;
- }
-
return 0;
-
-err_create_file:
- led_classdev_unregister(&drvdata->led_dev);
- return err;
}
static int lm3530_remove(struct i2c_client *client)
{
struct lm3530_data *drvdata = i2c_get_clientdata(client);
- device_remove_file(drvdata->led_dev.dev, &dev_attr_mode);
-
lm3530_led_disable(drvdata);
led_classdev_unregister(&drvdata->led_dev);
return 0;
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index e2c642c1169b..cbf61a40137d 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -645,6 +645,11 @@ static struct attribute_group lm3533_led_attribute_group = {
.attrs = lm3533_led_attributes
};
+static const struct attribute_group *lm3533_led_attribute_groups[] = {
+ &lm3533_led_attribute_group,
+ NULL
+};
+
static int lm3533_led_setup(struct lm3533_led *led,
struct lm3533_led_platform_data *pdata)
{
@@ -692,6 +697,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->cdev.brightness_get = lm3533_led_get;
led->cdev.blink_set = lm3533_led_blink_set;
led->cdev.brightness = LED_OFF;
+ led->cdev.groups = lm3533_led_attribute_groups,
led->id = pdev->id;
mutex_init(&led->mutex);
@@ -715,25 +721,16 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->cb.dev = led->cdev.dev;
- ret = sysfs_create_group(&led->cdev.dev->kobj,
- &lm3533_led_attribute_group);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create sysfs attributes\n");
- goto err_unregister;
- }
-
ret = lm3533_led_setup(led, pdata);
if (ret)
- goto err_sysfs_remove;
+ goto err_unregister;
ret = lm3533_ctrlbank_enable(&led->cb);
if (ret)
- goto err_sysfs_remove;
+ goto err_unregister;
return 0;
-err_sysfs_remove:
- sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
err_unregister:
led_classdev_unregister(&led->cdev);
flush_work(&led->work);
@@ -748,7 +745,6 @@ static int lm3533_led_remove(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s\n", __func__);
lm3533_ctrlbank_disable(&led->cb);
- sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
led_classdev_unregister(&led->cdev);
flush_work(&led->work);
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 591eb5e58ae3..f5112cb2d991 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -413,6 +413,12 @@ out:
static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
+static struct attribute *lm355x_indicator_attrs[] = {
+ &dev_attr_pattern.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lm355x_indicator);
+
static const struct regmap_config lm355x_regmap = {
.reg_bits = 8,
.val_bits = 8,
@@ -501,25 +507,18 @@ static int lm355x_probe(struct i2c_client *client,
else
chip->cdev_indicator.max_brightness = 8;
chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+ /* indicator pattern control only for LM3556 */
+ if (id->driver_data == CHIP_LM3556)
+ chip->cdev_indicator.groups = lm355x_indicator_groups;
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_indicator);
if (err < 0)
goto err_create_indicator_file;
- /* indicator pattern control only for LM3554 */
- if (id->driver_data == CHIP_LM3556) {
- err =
- device_create_file(chip->cdev_indicator.dev,
- &dev_attr_pattern);
- if (err < 0)
- goto err_create_pattern_file;
- }
dev_info(&client->dev, "%s is initialized\n",
lm355x_name[id->driver_data]);
return 0;
-err_create_pattern_file:
- led_classdev_unregister(&chip->cdev_indicator);
err_create_indicator_file:
led_classdev_unregister(&chip->cdev_torch);
err_create_torch_file:
@@ -534,8 +533,6 @@ static int lm355x_remove(struct i2c_client *client)
struct lm355x_reg_data *preg = chip->regs;
regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
- if (chip->type == CHIP_LM3556)
- device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
led_classdev_unregister(&chip->cdev_indicator);
flush_work(&chip->work_indicator);
led_classdev_unregister(&chip->cdev_torch);
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index ceb6b3cde6fe..d3dec0132769 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -313,6 +313,18 @@ static const struct regmap_config lm3642_regmap = {
.max_register = REG_MAX,
};
+static struct attribute *lm3642_flash_attrs[] = {
+ &dev_attr_strobe_pin.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lm3642_flash);
+
+static struct attribute *lm3642_torch_attrs[] = {
+ &dev_attr_torch_pin.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lm3642_torch);
+
static int lm3642_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -364,17 +376,13 @@ static int lm3642_probe(struct i2c_client *client,
chip->cdev_flash.max_brightness = 16;
chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
chip->cdev_flash.default_trigger = "flash";
+ chip->cdev_flash.groups = lm3642_flash_groups,
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_flash);
if (err < 0) {
dev_err(chip->dev, "failed to register flash\n");
goto err_out;
}
- err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
- if (err < 0) {
- dev_err(chip->dev, "failed to create strobe-pin file\n");
- goto err_create_flash_pin_file;
- }
/* torch */
INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
@@ -382,17 +390,13 @@ static int lm3642_probe(struct i2c_client *client,
chip->cdev_torch.max_brightness = 8;
chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
chip->cdev_torch.default_trigger = "torch";
+ chip->cdev_torch.groups = lm3642_torch_groups,
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_torch);
if (err < 0) {
dev_err(chip->dev, "failed to register torch\n");
goto err_create_torch_file;
}
- err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
- if (err < 0) {
- dev_err(chip->dev, "failed to create torch-pin file\n");
- goto err_create_torch_pin_file;
- }
/* indicator */
INIT_WORK(&chip->work_indicator,
@@ -411,12 +415,8 @@ static int lm3642_probe(struct i2c_client *client,
return 0;
err_create_indicator_file:
- device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
-err_create_torch_pin_file:
led_classdev_unregister(&chip->cdev_torch);
err_create_torch_file:
- device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
-err_create_flash_pin_file:
led_classdev_unregister(&chip->cdev_flash);
err_out:
return err;
@@ -428,10 +428,8 @@ static int lm3642_remove(struct i2c_client *client)
led_classdev_unregister(&chip->cdev_indicator);
flush_work(&chip->work_indicator);
- device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
led_classdev_unregister(&chip->cdev_torch);
flush_work(&chip->work_torch);
- device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
led_classdev_unregister(&chip->cdev_flash);
flush_work(&chip->work_flash);
regmap_write(chip->regmap, REG_ENABLE, 0);
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 88317b4f7bf3..77c26bc32eed 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -127,15 +127,12 @@ static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current,
lp55xx_store_current);
static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL);
-static struct attribute *lp55xx_led_attributes[] = {
+static struct attribute *lp55xx_led_attrs[] = {
&dev_attr_led_current.attr,
&dev_attr_max_current.attr,
NULL,
};
-
-static struct attribute_group lp55xx_led_attr_group = {
- .attrs = lp55xx_led_attributes
-};
+ATTRIBUTE_GROUPS(lp55xx_led);
static void lp55xx_set_brightness(struct led_classdev *cdev,
enum led_brightness brightness)
@@ -176,6 +173,7 @@ static int lp55xx_init_led(struct lp55xx_led *led,
}
led->cdev.brightness_set = lp55xx_set_brightness;
+ led->cdev.groups = lp55xx_led_groups;
if (pdata->led_config[chan].name) {
led->cdev.name = pdata->led_config[chan].name;
@@ -185,24 +183,12 @@ static int lp55xx_init_led(struct lp55xx_led *led,
led->cdev.name = name;
}
- /*
- * register led class device for each channel and
- * add device attributes
- */
-
ret = led_classdev_register(dev, &led->cdev);
if (ret) {
dev_err(dev, "led register err: %d\n", ret);
return ret;
}
- ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group);
- if (ret) {
- dev_err(dev, "led sysfs err: %d\n", ret);
- led_classdev_unregister(&led->cdev);
- return ret;
- }
-
return 0;
}
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index f449a8bdddc7..607bc2755aba 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -229,6 +229,12 @@ static ssize_t max8997_led_store_mode(struct device *dev,
static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
+static struct attribute *max8997_attrs[] = {
+ &dev_attr_mode.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(max8997);
+
static int max8997_led_probe(struct platform_device *pdev)
{
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -253,6 +259,7 @@ static int max8997_led_probe(struct platform_device *pdev)
led->cdev.brightness_set = max8997_led_brightness_set;
led->cdev.flags |= LED_CORE_SUSPENDRESUME;
led->cdev.brightness = 0;
+ led->cdev.groups = max8997_groups;
led->iodev = iodev;
/* initialize mode and brightness according to platform_data */
@@ -281,14 +288,6 @@ static int max8997_led_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- ret = device_create_file(led->cdev.dev, &dev_attr_mode);
- if (ret != 0) {
- dev_err(&pdev->dev,
- "failed to create file: %d\n", ret);
- led_classdev_unregister(&led->cdev);
- return ret;
- }
-
return 0;
}
@@ -296,7 +295,6 @@ static int max8997_led_remove(struct platform_device *pdev)
{
struct max8997_led *led = platform_get_drvdata(pdev);
- device_remove_file(led->cdev.dev, &dev_attr_mode);
led_classdev_unregister(&led->cdev);
return 0;
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index e97f443a6e07..64fde485dcaa 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -293,10 +293,14 @@ static ssize_t netxbig_led_sata_show(struct device *dev,
static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
+static struct attribute *netxbig_led_attrs[] = {
+ &dev_attr_sata.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(netxbig_led);
+
static void delete_netxbig_led(struct netxbig_led_data *led_dat)
{
- if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
- device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
led_classdev_unregister(&led_dat->cdev);
}
@@ -306,7 +310,6 @@ create_netxbig_led(struct platform_device *pdev,
const struct netxbig_led *template)
{
struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
- int ret;
spin_lock_init(&led_dat->lock);
led_dat->gpio_ext = pdata->gpio_ext;
@@ -327,6 +330,12 @@ create_netxbig_led(struct platform_device *pdev,
led_dat->sata = 0;
led_dat->cdev.brightness = LED_OFF;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ /*
+ * If available, expose the SATA activity blink capability through
+ * a "sata" sysfs attribute.
+ */
+ if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
+ led_dat->cdev.groups = netxbig_led_groups;
led_dat->mode_addr = template->mode_addr;
led_dat->mode_val = template->mode_val;
led_dat->bright_addr = template->bright_addr;
@@ -334,21 +343,7 @@ create_netxbig_led(struct platform_device *pdev,
led_dat->timer = pdata->timer;
led_dat->num_timer = pdata->num_timer;
- ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
- if (ret < 0)
- return ret;
-
- /*
- * If available, expose the SATA activity blink capability through
- * a "sata" sysfs attribute.
- */
- if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
- ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
- if (ret)
- led_classdev_unregister(&led_dat->cdev);
- }
-
- return ret;
+ return led_classdev_register(&pdev->dev, &led_dat->cdev);
}
static int netxbig_led_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index efa625883c83..231993d1fe21 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -185,6 +185,12 @@ static ssize_t ns2_led_sata_show(struct device *dev,
static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
+static struct attribute *ns2_led_attrs[] = {
+ &dev_attr_sata.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(ns2_led);
+
static int
create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
const struct ns2_led *template)
@@ -219,6 +225,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
led_dat->cdev.blink_set = NULL;
led_dat->cdev.brightness_set = ns2_led_set;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led_dat->cdev.groups = ns2_led_groups;
led_dat->cmd = template->cmd;
led_dat->slow = template->slow;
@@ -235,20 +242,11 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
if (ret < 0)
return ret;
- ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
- if (ret < 0)
- goto err_free_cdev;
-
return 0;
-
-err_free_cdev:
- led_classdev_unregister(&led_dat->cdev);
- return ret;
}
static void delete_ns2_led(struct ns2_led_data *led_dat)
{
- device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
led_classdev_unregister(&led_dat->cdev);
}
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 82589c0a5689..f110b4c456ba 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -12,7 +12,7 @@
* directory of this archive for more details.
*
* LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
- * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.)
+ * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.)
*
* Note that hardware blinking violates the leds infrastructure driver
* interface since the hardware only supports blinking all LEDs with the
@@ -52,6 +52,7 @@
enum pca963x_type {
pca9633,
pca9634,
+ pca9635,
};
struct pca963x_chipdef {
@@ -74,6 +75,12 @@ static struct pca963x_chipdef pca963x_chipdefs[] = {
.ledout_base = 0xc,
.n_leds = 8,
},
+ [pca9635] = {
+ .grppwm = 0x12,
+ .grpfreq = 0x13,
+ .ledout_base = 0x14,
+ .n_leds = 16,
+ },
};
/* Total blink period in milliseconds */
@@ -84,6 +91,7 @@ static const struct i2c_device_id pca963x_id[] = {
{ "pca9632", pca9633 },
{ "pca9633", pca9633 },
{ "pca9634", pca9634 },
+ { "pca9635", pca9635 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca963x_id);
@@ -107,7 +115,7 @@ struct pca963x_led {
struct work_struct work;
enum led_brightness brightness;
struct led_classdev led_cdev;
- int led_num; /* 0 .. 7 potentially */
+ int led_num; /* 0 .. 15 potentially */
enum pca963x_cmd cmd;
char name[32];
u8 gdc;
@@ -321,6 +329,7 @@ static const struct of_device_id of_pca963x_match[] = {
{ .compatible = "nxp,pca9632", },
{ .compatible = "nxp,pca9633", },
{ .compatible = "nxp,pca9634", },
+ { .compatible = "nxp,pca9635", },
{},
};
#else
@@ -375,9 +384,8 @@ static int pca963x_probe(struct i2c_client *client,
pca963x_chip->leds = pca963x;
/* Turn off LEDs by default*/
- i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00);
- if (chip->n_leds > 4)
- i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00);
+ for (i = 0; i < chip->n_leds / 4; i++)
+ i2c_smbus_write_byte_data(client, chip->ledout_base + i, 0x00);
for (i = 0; i < chip->n_leds; i++) {
pca963x[i].led_num = i;
@@ -415,9 +423,13 @@ static int pca963x_probe(struct i2c_client *client,
/* Disable LED all-call address and set normal mode */
i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
- /* Configure output: open-drain or totem pole (push-pull) */
- if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN)
- i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
+ if (pdata) {
+ /* Configure output: open-drain or totem pole (push-pull) */
+ if (pdata->outdrv == PCA963X_OPEN_DRAIN)
+ i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
+ else
+ i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x05);
+ }
return 0;
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 2eb3ef62962b..046cb7008745 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -469,6 +469,12 @@ static ssize_t nas_led_blink_store(struct device *dev,
static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
+static struct attribute *nasgpio_led_attrs[] = {
+ &dev_attr_blink.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(nasgpio_led);
+
static int register_nasgpio_led(int led_nr)
{
int ret;
@@ -481,20 +487,18 @@ static int register_nasgpio_led(int led_nr)
led->brightness = LED_FULL;
led->brightness_set = nasgpio_led_set_brightness;
led->blink_set = nasgpio_led_set_blink;
+ led->groups = nasgpio_led_groups;
ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
if (ret)
return ret;
- ret = device_create_file(led->dev, &dev_attr_blink);
- if (ret)
- led_classdev_unregister(led);
- return ret;
+
+ return 0;
}
static void unregister_nasgpio_led(int led_nr)
{
struct led_classdev *led = get_classdev_for_led_nr(led_nr);
led_classdev_unregister(led);
- device_remove_file(led->dev, &dev_attr_blink);
}
/*
* module load/initialization
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index e72c974142d0..1b71e0701002 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -219,6 +219,12 @@ static ssize_t wm831x_status_src_store(struct device *dev,
static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
+static struct attribute *wm831x_status_attrs[] = {
+ &dev_attr_src.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(wm831x_status);
+
static int wm831x_status_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -232,8 +238,7 @@ static int wm831x_status_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_REG, 0);
if (res == NULL) {
dev_err(&pdev->dev, "No register resource\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
@@ -284,31 +289,21 @@ static int wm831x_status_probe(struct platform_device *pdev)
drvdata->cdev.default_trigger = pdata.default_trigger;
drvdata->cdev.brightness_set = wm831x_status_set;
drvdata->cdev.blink_set = wm831x_status_blink_set;
+ drvdata->cdev.groups = wm831x_status_groups;
ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
- goto err_led;
+ return ret;
}
- ret = device_create_file(drvdata->cdev.dev, &dev_attr_src);
- if (ret != 0)
- dev_err(&pdev->dev,
- "No source control for LED: %d\n", ret);
-
return 0;
-
-err_led:
- led_classdev_unregister(&drvdata->cdev);
-err:
- return ret;
}
static int wm831x_status_remove(struct platform_device *pdev)
{
struct wm831x_status *drvdata = platform_get_drvdata(pdev);
- device_remove_file(drvdata->cdev.dev, &dev_attr_src);
led_classdev_unregister(&drvdata->cdev);
return 0;
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 0bf1e4edf04d..6590558d1d31 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -42,7 +42,6 @@ DEFINE_MUTEX(lguest_lock);
static __init int map_switcher(void)
{
int i, err;
- struct page **pagep;
/*
* Map the Switcher in to high memory.
@@ -110,11 +109,9 @@ static __init int map_switcher(void)
* This code actually sets up the pages we've allocated to appear at
* switcher_addr. map_vm_area() takes the vma we allocated above, the
* kind of pages we're mapping (kernel pages), and a pointer to our
- * array of struct pages. It increments that pointer, but we don't
- * care.
+ * array of struct pages.
*/
- pagep = lg_switcher_pages;
- err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, &pagep);
+ err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);
if (err) {
printk("lguest: map_vm_area failed: %i\n", err);
goto free_vma;
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index b1d91170ded0..6f68537c93ce 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -110,13 +110,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
}
-static int pmu_backlight_get_brightness(struct backlight_device *bd)
-{
- return bd->props.brightness;
-}
-
static const struct backlight_ops pmu_backlight_data = {
- .get_brightness = pmu_backlight_get_brightness,
.update_status = pmu_backlight_update_status,
};
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index c8b5c13bcd05..9fd9c6717e0c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -16,26 +16,9 @@ config PL320_MBOX
Management Engine, primarily for cpufreq. Say Y here if you want
to use the PL320 IPCM support.
-config OMAP_MBOX
- tristate
- help
- This option is selected by any OMAP architecture specific mailbox
- driver such as CONFIG_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This
- enables the common OMAP mailbox framework code.
-
-config OMAP1_MBOX
- tristate "OMAP1 Mailbox framework support"
- depends on ARCH_OMAP1
- select OMAP_MBOX
- help
- Mailbox implementation for OMAP chips with hardware for
- interprocessor communication involving DSP in OMAP1. Say Y here
- if you want to use OMAP1 Mailbox framework support.
-
config OMAP2PLUS_MBOX
tristate "OMAP2+ Mailbox framework support"
depends on ARCH_OMAP2PLUS
- select OMAP_MBOX
help
Mailbox implementation for OMAP family chips with hardware for
interprocessor communication involving DSP, IVA1.0 and IVA2 in
@@ -44,7 +27,7 @@ config OMAP2PLUS_MBOX
config OMAP_MBOX_KFIFO_SIZE
int "Mailbox kfifo default buffer size (bytes)"
- depends on OMAP2PLUS_MBOX || OMAP1_MBOX
+ depends on OMAP2PLUS_MBOX
default 256
help
Specify the default size of mailbox's kfifo buffers (bytes).
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index e0facb34084a..6d184dbcaca8 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -1,7 +1,3 @@
obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
-obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o
-obj-$(CONFIG_OMAP1_MBOX) += mailbox_omap1.o
-mailbox_omap1-objs := mailbox-omap1.o
-obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox_omap2.o
-mailbox_omap2-objs := mailbox-omap2.o
+obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
diff --git a/drivers/mailbox/mailbox-omap1.c b/drivers/mailbox/mailbox-omap1.c
deleted file mode 100644
index 9001b7633f10..000000000000
--- a/drivers/mailbox/mailbox-omap1.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP1
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_ARM2DSP1 0x00
-#define MAILBOX_ARM2DSP1b 0x04
-#define MAILBOX_DSP2ARM1 0x08
-#define MAILBOX_DSP2ARM1b 0x0c
-#define MAILBOX_DSP2ARM2 0x10
-#define MAILBOX_DSP2ARM2b 0x14
-#define MAILBOX_ARM2DSP1_Flag 0x18
-#define MAILBOX_DSP2ARM1_Flag 0x1c
-#define MAILBOX_DSP2ARM2_Flag 0x20
-
-static void __iomem *mbox_base;
-
-struct omap_mbox1_fifo {
- unsigned long cmd;
- unsigned long data;
- unsigned long flag;
-};
-
-struct omap_mbox1_priv {
- struct omap_mbox1_fifo tx_fifo;
- struct omap_mbox1_fifo rx_fifo;
-};
-
-static inline int mbox_read_reg(size_t ofs)
-{
- return __raw_readw(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
- __raw_writew(val, mbox_base + ofs);
-}
-
-/* msg */
-static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
-{
- struct omap_mbox1_fifo *fifo =
- &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
- mbox_msg_t msg;
-
- msg = mbox_read_reg(fifo->data);
- msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
-
- return msg;
-}
-
-static void
-omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
- struct omap_mbox1_fifo *fifo =
- &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
-
- mbox_write_reg(msg & 0xffff, fifo->data);
- mbox_write_reg(msg >> 16, fifo->cmd);
-}
-
-static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
-{
- return 0;
-}
-
-static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
-{
- struct omap_mbox1_fifo *fifo =
- &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-
- return mbox_read_reg(fifo->flag);
-}
-
-/* irq */
-static void
-omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- if (irq == IRQ_RX)
- enable_irq(mbox->irq);
-}
-
-static void
-omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- if (irq == IRQ_RX)
- disable_irq(mbox->irq);
-}
-
-static int
-omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- if (irq == IRQ_TX)
- return 0;
- return 1;
-}
-
-static struct omap_mbox_ops omap1_mbox_ops = {
- .type = OMAP_MBOX_TYPE1,
- .fifo_read = omap1_mbox_fifo_read,
- .fifo_write = omap1_mbox_fifo_write,
- .fifo_empty = omap1_mbox_fifo_empty,
- .fifo_full = omap1_mbox_fifo_full,
- .enable_irq = omap1_mbox_enable_irq,
- .disable_irq = omap1_mbox_disable_irq,
- .is_irq = omap1_mbox_is_irq,
-};
-
-/* FIXME: the following struct should be created automatically by the user id */
-
-/* DSP */
-static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
- .tx_fifo = {
- .cmd = MAILBOX_ARM2DSP1b,
- .data = MAILBOX_ARM2DSP1,
- .flag = MAILBOX_ARM2DSP1_Flag,
- },
- .rx_fifo = {
- .cmd = MAILBOX_DSP2ARM1b,
- .data = MAILBOX_DSP2ARM1,
- .flag = MAILBOX_DSP2ARM1_Flag,
- },
-};
-
-static struct omap_mbox mbox_dsp_info = {
- .name = "dsp",
- .ops = &omap1_mbox_ops,
- .priv = &omap1_mbox_dsp_priv,
-};
-
-static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
-
-static int omap1_mbox_probe(struct platform_device *pdev)
-{
- struct resource *mem;
- int ret;
- struct omap_mbox **list;
-
- list = omap1_mboxes;
- list[0]->irq = platform_get_irq_byname(pdev, "dsp");
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem)
- return -ENOENT;
-
- mbox_base = ioremap(mem->start, resource_size(mem));
- if (!mbox_base)
- return -ENOMEM;
-
- ret = omap_mbox_register(&pdev->dev, list);
- if (ret) {
- iounmap(mbox_base);
- return ret;
- }
-
- return 0;
-}
-
-static int omap1_mbox_remove(struct platform_device *pdev)
-{
- omap_mbox_unregister();
- iounmap(mbox_base);
- return 0;
-}
-
-static struct platform_driver omap1_mbox_driver = {
- .probe = omap1_mbox_probe,
- .remove = omap1_mbox_remove,
- .driver = {
- .name = "omap-mailbox",
- },
-};
-
-static int __init omap1_mbox_init(void)
-{
- return platform_driver_register(&omap1_mbox_driver);
-}
-
-static void __exit omap1_mbox_exit(void)
-{
- platform_driver_unregister(&omap1_mbox_driver);
-}
-
-module_init(omap1_mbox_init);
-module_exit(omap1_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/drivers/mailbox/mailbox-omap2.c b/drivers/mailbox/mailbox-omap2.c
deleted file mode 100644
index 42d2b893ea67..000000000000
--- a/drivers/mailbox/mailbox-omap2.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP2/3
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- * and Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_data/mailbox-omap.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_REVISION 0x000
-#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
-#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
-#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
-#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
-#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
-
-#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
-
-#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
-#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
-
-#define MBOX_REG_SIZE 0x120
-
-#define OMAP4_MBOX_REG_SIZE 0x130
-
-#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
-#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
-
-static void __iomem *mbox_base;
-
-struct omap_mbox2_fifo {
- unsigned long msg;
- unsigned long fifo_stat;
- unsigned long msg_stat;
-};
-
-struct omap_mbox2_priv {
- struct omap_mbox2_fifo tx_fifo;
- struct omap_mbox2_fifo rx_fifo;
- unsigned long irqenable;
- unsigned long irqstatus;
- u32 newmsg_bit;
- u32 notfull_bit;
- u32 ctx[OMAP4_MBOX_NR_REGS];
- unsigned long irqdisable;
- u32 intr_type;
-};
-
-static inline unsigned int mbox_read_reg(size_t ofs)
-{
- return __raw_readl(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
- __raw_writel(val, mbox_base + ofs);
-}
-
-/* Mailbox H/W preparations */
-static int omap2_mbox_startup(struct omap_mbox *mbox)
-{
- u32 l;
-
- pm_runtime_enable(mbox->dev->parent);
- pm_runtime_get_sync(mbox->dev->parent);
-
- l = mbox_read_reg(MAILBOX_REVISION);
- pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
- return 0;
-}
-
-static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
- pm_runtime_put_sync(mbox->dev->parent);
- pm_runtime_disable(mbox->dev->parent);
-}
-
-/* Mailbox FIFO handle functions */
-static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
-{
- struct omap_mbox2_fifo *fifo =
- &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
- return (mbox_msg_t) mbox_read_reg(fifo->msg);
-}
-
-static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
- struct omap_mbox2_fifo *fifo =
- &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
- mbox_write_reg(msg, fifo->msg);
-}
-
-static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
-{
- struct omap_mbox2_fifo *fifo =
- &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
- return (mbox_read_reg(fifo->msg_stat) == 0);
-}
-
-static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
-{
- struct omap_mbox2_fifo *fifo =
- &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
- return mbox_read_reg(fifo->fifo_stat);
-}
-
-/* Mailbox IRQ handle functions */
-static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- struct omap_mbox2_priv *p = mbox->priv;
- u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
- l = mbox_read_reg(p->irqenable);
- l |= bit;
- mbox_write_reg(l, p->irqenable);
-}
-
-static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- struct omap_mbox2_priv *p = mbox->priv;
- u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
- /*
- * Read and update the interrupt configuration register for pre-OMAP4.
- * OMAP4 and later SoCs have a dedicated interrupt disabling register.
- */
- if (!p->intr_type)
- bit = mbox_read_reg(p->irqdisable) & ~bit;
-
- mbox_write_reg(bit, p->irqdisable);
-}
-
-static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- struct omap_mbox2_priv *p = mbox->priv;
- u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
- mbox_write_reg(bit, p->irqstatus);
-
- /* Flush posted write for irq status to avoid spurious interrupts */
- mbox_read_reg(p->irqstatus);
-}
-
-static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
- struct omap_mbox2_priv *p = mbox->priv;
- u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
- u32 enable = mbox_read_reg(p->irqenable);
- u32 status = mbox_read_reg(p->irqstatus);
-
- return (int)(enable & status & bit);
-}
-
-static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
-{
- int i;
- struct omap_mbox2_priv *p = mbox->priv;
- int nr_regs;
-
- if (p->intr_type)
- nr_regs = OMAP4_MBOX_NR_REGS;
- else
- nr_regs = MBOX_NR_REGS;
- for (i = 0; i < nr_regs; i++) {
- p->ctx[i] = mbox_read_reg(i * sizeof(u32));
-
- dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
- }
-}
-
-static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
-{
- int i;
- struct omap_mbox2_priv *p = mbox->priv;
- int nr_regs;
-
- if (p->intr_type)
- nr_regs = OMAP4_MBOX_NR_REGS;
- else
- nr_regs = MBOX_NR_REGS;
- for (i = 0; i < nr_regs; i++) {
- mbox_write_reg(p->ctx[i], i * sizeof(u32));
-
- dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
- }
-}
-
-static struct omap_mbox_ops omap2_mbox_ops = {
- .type = OMAP_MBOX_TYPE2,
- .startup = omap2_mbox_startup,
- .shutdown = omap2_mbox_shutdown,
- .fifo_read = omap2_mbox_fifo_read,
- .fifo_write = omap2_mbox_fifo_write,
- .fifo_empty = omap2_mbox_fifo_empty,
- .fifo_full = omap2_mbox_fifo_full,
- .enable_irq = omap2_mbox_enable_irq,
- .disable_irq = omap2_mbox_disable_irq,
- .ack_irq = omap2_mbox_ack_irq,
- .is_irq = omap2_mbox_is_irq,
- .save_ctx = omap2_mbox_save_ctx,
- .restore_ctx = omap2_mbox_restore_ctx,
-};
-
-static int omap2_mbox_probe(struct platform_device *pdev)
-{
- struct resource *mem;
- int ret;
- struct omap_mbox **list, *mbox, *mboxblk;
- struct omap_mbox2_priv *priv, *privblk;
- struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
- struct omap_mbox_dev_info *info;
- int i;
-
- if (!pdata || !pdata->info_cnt || !pdata->info) {
- pr_err("%s: platform not supported\n", __func__);
- return -ENODEV;
- }
-
- /* allocate one extra for marking end of list */
- list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
- if (!list)
- return -ENOMEM;
-
- mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
- if (!mboxblk) {
- ret = -ENOMEM;
- goto free_list;
- }
-
- privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
- if (!privblk) {
- ret = -ENOMEM;
- goto free_mboxblk;
- }
-
- info = pdata->info;
- for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
- priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
- priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
- priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id);
- priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
- priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
- priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
- if (pdata->intr_type) {
- priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
- priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
- priv->irqdisable =
- OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
- } else {
- priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
- priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
- priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
- }
- priv->intr_type = pdata->intr_type;
-
- mbox->priv = priv;
- mbox->name = info->name;
- mbox->ops = &omap2_mbox_ops;
- mbox->irq = platform_get_irq(pdev, info->irq_id);
- if (mbox->irq < 0) {
- ret = mbox->irq;
- goto free_privblk;
- }
- list[i] = mbox++;
- }
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- ret = -ENOENT;
- goto free_privblk;
- }
-
- mbox_base = ioremap(mem->start, resource_size(mem));
- if (!mbox_base) {
- ret = -ENOMEM;
- goto free_privblk;
- }
-
- ret = omap_mbox_register(&pdev->dev, list);
- if (ret)
- goto unmap_mbox;
- platform_set_drvdata(pdev, list);
-
- return 0;
-
-unmap_mbox:
- iounmap(mbox_base);
-free_privblk:
- kfree(privblk);
-free_mboxblk:
- kfree(mboxblk);
-free_list:
- kfree(list);
- return ret;
-}
-
-static int omap2_mbox_remove(struct platform_device *pdev)
-{
- struct omap_mbox2_priv *privblk;
- struct omap_mbox **list = platform_get_drvdata(pdev);
- struct omap_mbox *mboxblk = list[0];
-
- privblk = mboxblk->priv;
- omap_mbox_unregister();
- iounmap(mbox_base);
- kfree(privblk);
- kfree(mboxblk);
- kfree(list);
-
- return 0;
-}
-
-static struct platform_driver omap2_mbox_driver = {
- .probe = omap2_mbox_probe,
- .remove = omap2_mbox_remove,
- .driver = {
- .name = "omap-mailbox",
- },
-};
-
-static int __init omap2_mbox_init(void)
-{
- return platform_driver_register(&omap2_mbox_driver);
-}
-
-static void __exit omap2_mbox_exit(void)
-{
- platform_driver_unregister(&omap2_mbox_driver);
-}
-
-module_init(omap2_mbox_init);
-module_exit(omap2_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_AUTHOR("Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index d79a646b9042..a27e00e63a8a 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -2,8 +2,10 @@
* OMAP mailbox driver
*
* Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2013-2014 Texas Instruments Inc.
*
* Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ * Suman Anna <s-anna@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,70 +26,164 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/err.h>
#include <linux/notifier.h>
#include <linux/module.h>
-
-#include "omap-mbox.h"
-
-static struct omap_mbox **mboxes;
-
-static int mbox_configured;
-static DEFINE_MUTEX(mbox_configured_lock);
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/mailbox-omap.h>
+#include <linux/omap-mailbox.h>
+
+#define MAILBOX_REVISION 0x000
+#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
+#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
+#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
+
+#define OMAP2_MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
+#define OMAP2_MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
+
+#define OMAP4_MAILBOX_IRQSTATUS(u) (0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u) (0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u) (0x10c + 0x10 * (u))
+
+#define MAILBOX_IRQSTATUS(type, u) (type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
+ OMAP2_MAILBOX_IRQSTATUS(u))
+#define MAILBOX_IRQENABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE(u) : \
+ OMAP2_MAILBOX_IRQENABLE(u))
+#define MAILBOX_IRQDISABLE(type, u) (type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
+ : OMAP2_MAILBOX_IRQENABLE(u))
+
+#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
+
+#define MBOX_REG_SIZE 0x120
+
+#define OMAP4_MBOX_REG_SIZE 0x130
+
+#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
+#define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
+
+struct omap_mbox_fifo {
+ unsigned long msg;
+ unsigned long fifo_stat;
+ unsigned long msg_stat;
+ unsigned long irqenable;
+ unsigned long irqstatus;
+ unsigned long irqdisable;
+ u32 intr_bit;
+};
+
+struct omap_mbox_queue {
+ spinlock_t lock;
+ struct kfifo fifo;
+ struct work_struct work;
+ struct tasklet_struct tasklet;
+ struct omap_mbox *mbox;
+ bool full;
+};
+
+struct omap_mbox_device {
+ struct device *dev;
+ struct mutex cfg_lock;
+ void __iomem *mbox_base;
+ u32 num_users;
+ u32 num_fifos;
+ struct omap_mbox **mboxes;
+ struct list_head elem;
+};
+
+struct omap_mbox {
+ const char *name;
+ int irq;
+ struct omap_mbox_queue *txq, *rxq;
+ struct device *dev;
+ struct omap_mbox_device *parent;
+ struct omap_mbox_fifo tx_fifo;
+ struct omap_mbox_fifo rx_fifo;
+ u32 ctx[OMAP4_MBOX_NR_REGS];
+ u32 intr_type;
+ int use_count;
+ struct blocking_notifier_head notifier;
+};
+
+/* global variables for the mailbox devices */
+static DEFINE_MUTEX(omap_mbox_devices_lock);
+static LIST_HEAD(omap_mbox_devices);
static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
module_param(mbox_kfifo_size, uint, S_IRUGO);
MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
+static inline
+unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
+{
+ return __raw_readl(mdev->mbox_base + ofs);
+}
+
+static inline
+void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
+{
+ __raw_writel(val, mdev->mbox_base + ofs);
+}
+
/* Mailbox FIFO handle functions */
-static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
{
- return mbox->ops->fifo_read(mbox);
+ struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
+ return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg);
}
-static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+
+static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
- mbox->ops->fifo_write(mbox, msg);
+ struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
+ mbox_write_reg(mbox->parent, msg, fifo->msg);
}
-static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+
+static int mbox_fifo_empty(struct omap_mbox *mbox)
{
- return mbox->ops->fifo_empty(mbox);
+ struct omap_mbox_fifo *fifo = &mbox->rx_fifo;
+ return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0);
}
-static inline int mbox_fifo_full(struct omap_mbox *mbox)
+
+static int mbox_fifo_full(struct omap_mbox *mbox)
{
- return mbox->ops->fifo_full(mbox);
+ struct omap_mbox_fifo *fifo = &mbox->tx_fifo;
+ return mbox_read_reg(mbox->parent, fifo->fifo_stat);
}
/* Mailbox IRQ handle functions */
-static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
- if (mbox->ops->ack_irq)
- mbox->ops->ack_irq(mbox, irq);
+ struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+ &mbox->tx_fifo : &mbox->rx_fifo;
+ u32 bit = fifo->intr_bit;
+ u32 irqstatus = fifo->irqstatus;
+
+ mbox_write_reg(mbox->parent, bit, irqstatus);
+
+ /* Flush posted write for irq status to avoid spurious interrupts */
+ mbox_read_reg(mbox->parent, irqstatus);
}
-static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+
+static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
- return mbox->ops->is_irq(mbox, irq);
+ struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+ &mbox->tx_fifo : &mbox->rx_fifo;
+ u32 bit = fifo->intr_bit;
+ u32 irqenable = fifo->irqenable;
+ u32 irqstatus = fifo->irqstatus;
+
+ u32 enable = mbox_read_reg(mbox->parent, irqenable);
+ u32 status = mbox_read_reg(mbox->parent, irqstatus);
+
+ return (int)(enable & status & bit);
}
/*
* message sender
*/
-static int __mbox_poll_for_space(struct omap_mbox *mbox)
-{
- int ret = 0, i = 1000;
-
- while (mbox_fifo_full(mbox)) {
- if (mbox->ops->type == OMAP_MBOX_TYPE2)
- return -1;
- if (--i == 0)
- return -1;
- udelay(1);
- }
- return ret;
-}
-
int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{
struct omap_mbox_queue *mq = mbox->txq;
@@ -100,7 +196,7 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
goto out;
}
- if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+ if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
mbox_fifo_write(mbox, msg);
goto out;
}
@@ -118,35 +214,69 @@ EXPORT_SYMBOL(omap_mbox_msg_send);
void omap_mbox_save_ctx(struct omap_mbox *mbox)
{
- if (!mbox->ops->save_ctx) {
- dev_err(mbox->dev, "%s:\tno save\n", __func__);
- return;
- }
+ int i;
+ int nr_regs;
+
+ if (mbox->intr_type)
+ nr_regs = OMAP4_MBOX_NR_REGS;
+ else
+ nr_regs = MBOX_NR_REGS;
+ for (i = 0; i < nr_regs; i++) {
+ mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));
- mbox->ops->save_ctx(mbox);
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+ i, mbox->ctx[i]);
+ }
}
EXPORT_SYMBOL(omap_mbox_save_ctx);
void omap_mbox_restore_ctx(struct omap_mbox *mbox)
{
- if (!mbox->ops->restore_ctx) {
- dev_err(mbox->dev, "%s:\tno restore\n", __func__);
- return;
- }
+ int i;
+ int nr_regs;
- mbox->ops->restore_ctx(mbox);
+ if (mbox->intr_type)
+ nr_regs = OMAP4_MBOX_NR_REGS;
+ else
+ nr_regs = MBOX_NR_REGS;
+ for (i = 0; i < nr_regs; i++) {
+ mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
+
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+ i, mbox->ctx[i]);
+ }
}
EXPORT_SYMBOL(omap_mbox_restore_ctx);
void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
- mbox->ops->enable_irq(mbox, irq);
+ u32 l;
+ struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+ &mbox->tx_fifo : &mbox->rx_fifo;
+ u32 bit = fifo->intr_bit;
+ u32 irqenable = fifo->irqenable;
+
+ l = mbox_read_reg(mbox->parent, irqenable);
+ l |= bit;
+ mbox_write_reg(mbox->parent, l, irqenable);
}
EXPORT_SYMBOL(omap_mbox_enable_irq);
void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
{
- mbox->ops->disable_irq(mbox, irq);
+ struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+ &mbox->tx_fifo : &mbox->rx_fifo;
+ u32 bit = fifo->intr_bit;
+ u32 irqdisable = fifo->irqdisable;
+
+ /*
+ * Read and update the interrupt configuration register for pre-OMAP4.
+ * OMAP4 and later SoCs have a dedicated interrupt disabling register.
+ */
+ if (!mbox->intr_type)
+ bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
+
+ mbox_write_reg(mbox->parent, bit, irqdisable);
}
EXPORT_SYMBOL(omap_mbox_disable_irq);
@@ -158,7 +288,7 @@ static void mbox_tx_tasklet(unsigned long tx_data)
int ret;
while (kfifo_len(&mq->fifo)) {
- if (__mbox_poll_for_space(mbox)) {
+ if (mbox_fifo_full(mbox)) {
omap_mbox_enable_irq(mbox, IRQ_TX);
break;
}
@@ -223,9 +353,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
WARN_ON(len != sizeof(msg));
-
- if (mbox->ops->type == OMAP_MBOX_TYPE1)
- break;
}
/* no more messages in the fifo. clear IRQ source. */
@@ -283,16 +410,12 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
{
int ret = 0;
struct omap_mbox_queue *mq;
+ struct omap_mbox_device *mdev = mbox->parent;
- mutex_lock(&mbox_configured_lock);
- if (!mbox_configured++) {
- if (likely(mbox->ops->startup)) {
- ret = mbox->ops->startup(mbox);
- if (unlikely(ret))
- goto fail_startup;
- } else
- goto fail_startup;
- }
+ mutex_lock(&mdev->cfg_lock);
+ ret = pm_runtime_get_sync(mdev->dev);
+ if (unlikely(ret < 0))
+ goto fail_startup;
if (!mbox->use_count++) {
mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
@@ -319,7 +442,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
omap_mbox_enable_irq(mbox, IRQ_RX);
}
- mutex_unlock(&mbox_configured_lock);
+ mutex_unlock(&mdev->cfg_lock);
return 0;
fail_request_irq:
@@ -327,18 +450,18 @@ fail_request_irq:
fail_alloc_rxq:
mbox_queue_free(mbox->txq);
fail_alloc_txq:
- if (mbox->ops->shutdown)
- mbox->ops->shutdown(mbox);
+ pm_runtime_put_sync(mdev->dev);
mbox->use_count--;
fail_startup:
- mbox_configured--;
- mutex_unlock(&mbox_configured_lock);
+ mutex_unlock(&mdev->cfg_lock);
return ret;
}
static void omap_mbox_fini(struct omap_mbox *mbox)
{
- mutex_lock(&mbox_configured_lock);
+ struct omap_mbox_device *mdev = mbox->parent;
+
+ mutex_lock(&mdev->cfg_lock);
if (!--mbox->use_count) {
omap_mbox_disable_irq(mbox, IRQ_RX);
@@ -349,28 +472,43 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
mbox_queue_free(mbox->rxq);
}
- if (likely(mbox->ops->shutdown)) {
- if (!--mbox_configured)
- mbox->ops->shutdown(mbox);
- }
+ pm_runtime_put_sync(mdev->dev);
- mutex_unlock(&mbox_configured_lock);
+ mutex_unlock(&mdev->cfg_lock);
}
-struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
+ const char *mbox_name)
{
struct omap_mbox *_mbox, *mbox = NULL;
- int i, ret;
+ struct omap_mbox **mboxes = mdev->mboxes;
+ int i;
if (!mboxes)
- return ERR_PTR(-EINVAL);
+ return NULL;
for (i = 0; (_mbox = mboxes[i]); i++) {
- if (!strcmp(_mbox->name, name)) {
+ if (!strcmp(_mbox->name, mbox_name)) {
mbox = _mbox;
break;
}
}
+ return mbox;
+}
+
+struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+{
+ struct omap_mbox *mbox = NULL;
+ struct omap_mbox_device *mdev;
+ int ret;
+
+ mutex_lock(&omap_mbox_devices_lock);
+ list_for_each_entry(mdev, &omap_mbox_devices, elem) {
+ mbox = omap_mbox_device_find(mdev, name);
+ if (mbox)
+ break;
+ }
+ mutex_unlock(&omap_mbox_devices_lock);
if (!mbox)
return ERR_PTR(-ENOENT);
@@ -397,19 +535,20 @@ EXPORT_SYMBOL(omap_mbox_put);
static struct class omap_mbox_class = { .name = "mbox", };
-int omap_mbox_register(struct device *parent, struct omap_mbox **list)
+static int omap_mbox_register(struct omap_mbox_device *mdev)
{
int ret;
int i;
+ struct omap_mbox **mboxes;
- mboxes = list;
- if (!mboxes)
+ if (!mdev || !mdev->mboxes)
return -EINVAL;
+ mboxes = mdev->mboxes;
for (i = 0; mboxes[i]; i++) {
struct omap_mbox *mbox = mboxes[i];
mbox->dev = device_create(&omap_mbox_class,
- parent, 0, mbox, "%s", mbox->name);
+ mdev->dev, 0, mbox, "%s", mbox->name);
if (IS_ERR(mbox->dev)) {
ret = PTR_ERR(mbox->dev);
goto err_out;
@@ -417,6 +556,11 @@ int omap_mbox_register(struct device *parent, struct omap_mbox **list)
BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
}
+
+ mutex_lock(&omap_mbox_devices_lock);
+ list_add(&mdev->elem, &omap_mbox_devices);
+ mutex_unlock(&omap_mbox_devices_lock);
+
return 0;
err_out:
@@ -424,21 +568,148 @@ err_out:
device_unregister(mboxes[i]->dev);
return ret;
}
-EXPORT_SYMBOL(omap_mbox_register);
-int omap_mbox_unregister(void)
+static int omap_mbox_unregister(struct omap_mbox_device *mdev)
{
int i;
+ struct omap_mbox **mboxes;
- if (!mboxes)
+ if (!mdev || !mdev->mboxes)
return -EINVAL;
+ mutex_lock(&omap_mbox_devices_lock);
+ list_del(&mdev->elem);
+ mutex_unlock(&omap_mbox_devices_lock);
+
+ mboxes = mdev->mboxes;
for (i = 0; mboxes[i]; i++)
device_unregister(mboxes[i]->dev);
- mboxes = NULL;
return 0;
}
-EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int omap_mbox_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ int ret;
+ struct omap_mbox **list, *mbox, *mboxblk;
+ struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
+ struct omap_mbox_dev_info *info;
+ struct omap_mbox_device *mdev;
+ struct omap_mbox_fifo *fifo;
+ u32 intr_type;
+ u32 l;
+ int i;
+
+ if (!pdata || !pdata->info_cnt || !pdata->info) {
+ pr_err("%s: platform not supported\n", __func__);
+ return -ENODEV;
+ }
+
+ mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ return -ENOMEM;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(mdev->mbox_base))
+ return PTR_ERR(mdev->mbox_base);
+
+ /* allocate one extra for marking end of list */
+ list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
+ GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+
+ mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
+ GFP_KERNEL);
+ if (!mboxblk)
+ return -ENOMEM;
+
+ info = pdata->info;
+ intr_type = pdata->intr_type;
+ mbox = mboxblk;
+ for (i = 0; i < pdata->info_cnt; i++, info++) {
+ fifo = &mbox->tx_fifo;
+ fifo->msg = MAILBOX_MESSAGE(info->tx_id);
+ fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
+ fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
+ fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+ fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+ fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+ fifo = &mbox->rx_fifo;
+ fifo->msg = MAILBOX_MESSAGE(info->rx_id);
+ fifo->msg_stat = MAILBOX_MSGSTATUS(info->rx_id);
+ fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
+ fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+ fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+ fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+ mbox->intr_type = intr_type;
+
+ mbox->parent = mdev;
+ mbox->name = info->name;
+ mbox->irq = platform_get_irq(pdev, info->irq_id);
+ if (mbox->irq < 0)
+ return mbox->irq;
+ list[i] = mbox++;
+ }
+
+ mutex_init(&mdev->cfg_lock);
+ mdev->dev = &pdev->dev;
+ mdev->num_users = pdata->num_users;
+ mdev->num_fifos = pdata->num_fifos;
+ mdev->mboxes = list;
+ ret = omap_mbox_register(mdev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, mdev);
+ pm_runtime_enable(mdev->dev);
+
+ ret = pm_runtime_get_sync(mdev->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(mdev->dev);
+ goto unregister;
+ }
+
+ /*
+ * just print the raw revision register, the format is not
+ * uniform across all SoCs
+ */
+ l = mbox_read_reg(mdev, MAILBOX_REVISION);
+ dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
+
+ ret = pm_runtime_put_sync(mdev->dev);
+ if (ret < 0)
+ goto unregister;
+
+ return 0;
+
+unregister:
+ pm_runtime_disable(mdev->dev);
+ omap_mbox_unregister(mdev);
+ return ret;
+}
+
+static int omap_mbox_remove(struct platform_device *pdev)
+{
+ struct omap_mbox_device *mdev = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(mdev->dev);
+ omap_mbox_unregister(mdev);
+
+ return 0;
+}
+
+static struct platform_driver omap_mbox_driver = {
+ .probe = omap_mbox_probe,
+ .remove = omap_mbox_remove,
+ .driver = {
+ .name = "omap-mailbox",
+ .owner = THIS_MODULE,
+ },
+};
static int __init omap_mbox_init(void)
{
@@ -453,12 +724,13 @@ static int __init omap_mbox_init(void)
mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
sizeof(mbox_msg_t));
- return 0;
+ return platform_driver_register(&omap_mbox_driver);
}
subsys_initcall(omap_mbox_init);
static void __exit omap_mbox_exit(void)
{
+ platform_driver_unregister(&omap_mbox_driver);
class_unregister(&omap_mbox_class);
}
module_exit(omap_mbox_exit);
diff --git a/drivers/mailbox/omap-mbox.h b/drivers/mailbox/omap-mbox.h
deleted file mode 100644
index 86d7518cd13b..000000000000
--- a/drivers/mailbox/omap-mbox.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * omap-mbox.h: OMAP mailbox internal definitions
- *
- * 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 OMAP_MBOX_H
-#define OMAP_MBOX_H
-
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/omap-mailbox.h>
-
-typedef int __bitwise omap_mbox_type_t;
-#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
-#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
-
-struct omap_mbox_ops {
- omap_mbox_type_t type;
- int (*startup)(struct omap_mbox *mbox);
- void (*shutdown)(struct omap_mbox *mbox);
- /* fifo */
- mbox_msg_t (*fifo_read)(struct omap_mbox *mbox);
- void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
- int (*fifo_empty)(struct omap_mbox *mbox);
- int (*fifo_full)(struct omap_mbox *mbox);
- /* irq */
- void (*enable_irq)(struct omap_mbox *mbox,
- omap_mbox_irq_t irq);
- void (*disable_irq)(struct omap_mbox *mbox,
- omap_mbox_irq_t irq);
- void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
- int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
- /* ctx */
- void (*save_ctx)(struct omap_mbox *mbox);
- void (*restore_ctx)(struct omap_mbox *mbox);
-};
-
-struct omap_mbox_queue {
- spinlock_t lock;
- struct kfifo fifo;
- struct work_struct work;
- struct tasklet_struct tasklet;
- struct omap_mbox *mbox;
- bool full;
-};
-
-struct omap_mbox {
- const char *name;
- int irq;
- struct omap_mbox_queue *txq, *rxq;
- struct omap_mbox_ops *ops;
- struct device *dev;
- void *priv;
- int use_count;
- struct blocking_notifier_head notifier;
-};
-
-int omap_mbox_register(struct device *parent, struct omap_mbox **);
-int omap_mbox_unregister(void);
-
-#endif /* OMAP_MBOX_H */
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index 443d03fbac47..8eeab72b93e2 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -331,7 +331,7 @@ static int bch_allocator_thread(void *arg)
mutex_unlock(&ca->set->bucket_lock);
blkdev_issue_discard(ca->bdev,
bucket_to_sector(ca->set, bucket),
- ca->sb.block_size, GFP_KERNEL, 0);
+ ca->sb.bucket_size, GFP_KERNEL, 0);
mutex_lock(&ca->set->bucket_lock);
}
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index d2ebcf323094..04f7bc28ef83 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -477,9 +477,13 @@ struct gc_stat {
* CACHE_SET_STOPPING always gets set first when we're closing down a cache set;
* we'll continue to run normally for awhile with CACHE_SET_STOPPING set (i.e.
* flushing dirty data).
+ *
+ * CACHE_SET_RUNNING means all cache devices have been registered and journal
+ * replay is complete.
*/
#define CACHE_SET_UNREGISTERING 0
#define CACHE_SET_STOPPING 1
+#define CACHE_SET_RUNNING 2
struct cache_set {
struct closure cl;
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 545416415305..646fe85261c1 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -1182,7 +1182,7 @@ static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
{
uint64_t start_time;
bool used_mempool = false;
- struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO,
+ struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOWAIT,
order);
if (!out) {
struct page *outp;
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index 5f6728d5d4dd..ae964624efb2 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -453,7 +453,7 @@ static inline bool bch_bkey_equal_header(const struct bkey *l,
{
return (KEY_DIRTY(l) == KEY_DIRTY(r) &&
KEY_PTRS(l) == KEY_PTRS(r) &&
- KEY_CSUM(l) == KEY_CSUM(l));
+ KEY_CSUM(l) == KEY_CSUM(r));
}
/* Keylists */
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 7347b6100961..00cde40db572 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -117,9 +117,9 @@
({ \
int _r, l = (b)->level - 1; \
bool _w = l <= (op)->lock; \
- struct btree *_child = bch_btree_node_get((b)->c, op, key, l, _w);\
+ struct btree *_child = bch_btree_node_get((b)->c, op, key, l, \
+ _w, b); \
if (!IS_ERR(_child)) { \
- _child->parent = (b); \
_r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \
rw_unlock(_w, _child); \
} else \
@@ -142,7 +142,6 @@
rw_lock(_w, _b, _b->level); \
if (_b == (c)->root && \
_w == insert_lock(op, _b)) { \
- _b->parent = NULL; \
_r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \
} \
rw_unlock(_w, _b); \
@@ -202,7 +201,7 @@ void bch_btree_node_read_done(struct btree *b)
struct bset *i = btree_bset_first(b);
struct btree_iter *iter;
- iter = mempool_alloc(b->c->fill_iter, GFP_NOWAIT);
+ iter = mempool_alloc(b->c->fill_iter, GFP_NOIO);
iter->size = b->c->sb.bucket_size / b->c->sb.block_size;
iter->used = 0;
@@ -421,7 +420,7 @@ static void do_btree_node_write(struct btree *b)
SET_PTR_OFFSET(&k.key, 0, PTR_OFFSET(&k.key, 0) +
bset_sector_offset(&b->keys, i));
- if (!bio_alloc_pages(b->bio, GFP_NOIO)) {
+ if (!bio_alloc_pages(b->bio, __GFP_NOWARN|GFP_NOWAIT)) {
int j;
struct bio_vec *bv;
void *base = (void *) ((unsigned long) i & ~(PAGE_SIZE - 1));
@@ -967,7 +966,8 @@ err:
* level and op->lock.
*/
struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
- struct bkey *k, int level, bool write)
+ struct bkey *k, int level, bool write,
+ struct btree *parent)
{
int i = 0;
struct btree *b;
@@ -1002,6 +1002,7 @@ retry:
BUG_ON(b->level != level);
}
+ b->parent = parent;
b->accessed = 1;
for (; i <= b->keys.nsets && b->keys.set[i].size; i++) {
@@ -1022,15 +1023,16 @@ retry:
return b;
}
-static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level)
+static void btree_node_prefetch(struct btree *parent, struct bkey *k)
{
struct btree *b;
- mutex_lock(&c->bucket_lock);
- b = mca_alloc(c, NULL, k, level);
- mutex_unlock(&c->bucket_lock);
+ mutex_lock(&parent->c->bucket_lock);
+ b = mca_alloc(parent->c, NULL, k, parent->level - 1);
+ mutex_unlock(&parent->c->bucket_lock);
if (!IS_ERR_OR_NULL(b)) {
+ b->parent = parent;
bch_btree_node_read(b);
rw_unlock(true, b);
}
@@ -1060,15 +1062,16 @@ static void btree_node_free(struct btree *b)
mutex_unlock(&b->c->bucket_lock);
}
-struct btree *bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
- int level)
+struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
+ int level, bool wait,
+ struct btree *parent)
{
BKEY_PADDED(key) k;
struct btree *b = ERR_PTR(-EAGAIN);
mutex_lock(&c->bucket_lock);
retry:
- if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, op != NULL))
+ if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, wait))
goto err;
bkey_put(c, &k.key);
@@ -1085,6 +1088,7 @@ retry:
}
b->accessed = 1;
+ b->parent = parent;
bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb));
mutex_unlock(&c->bucket_lock);
@@ -1096,14 +1100,21 @@ err_free:
err:
mutex_unlock(&c->bucket_lock);
- trace_bcache_btree_node_alloc_fail(b);
+ trace_bcache_btree_node_alloc_fail(c);
return b;
}
+static struct btree *bch_btree_node_alloc(struct cache_set *c,
+ struct btree_op *op, int level,
+ struct btree *parent)
+{
+ return __bch_btree_node_alloc(c, op, level, op != NULL, parent);
+}
+
static struct btree *btree_node_alloc_replacement(struct btree *b,
struct btree_op *op)
{
- struct btree *n = bch_btree_node_alloc(b->c, op, b->level);
+ struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
if (!IS_ERR_OR_NULL(n)) {
mutex_lock(&n->write_lock);
bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
@@ -1403,6 +1414,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
BUG_ON(btree_bset_first(new_nodes[0])->keys);
btree_node_free(new_nodes[0]);
rw_unlock(true, new_nodes[0]);
+ new_nodes[0] = NULL;
for (i = 0; i < nodes; i++) {
if (__bch_keylist_realloc(&keylist, bkey_u64s(&r[i].b->key)))
@@ -1516,7 +1528,7 @@ static int btree_gc_recurse(struct btree *b, struct btree_op *op,
k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad);
if (k) {
r->b = bch_btree_node_get(b->c, op, k, b->level - 1,
- true);
+ true, b);
if (IS_ERR(r->b)) {
ret = PTR_ERR(r->b);
break;
@@ -1811,7 +1823,7 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op)
k = bch_btree_iter_next_filter(&iter, &b->keys,
bch_ptr_bad);
if (k)
- btree_node_prefetch(b->c, k, b->level - 1);
+ btree_node_prefetch(b, k);
if (p)
ret = btree(check_recurse, p, b, op);
@@ -1976,12 +1988,12 @@ static int btree_split(struct btree *b, struct btree_op *op,
trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys);
- n2 = bch_btree_node_alloc(b->c, op, b->level);
+ n2 = bch_btree_node_alloc(b->c, op, b->level, b->parent);
if (IS_ERR(n2))
goto err_free1;
if (!b->parent) {
- n3 = bch_btree_node_alloc(b->c, op, b->level + 1);
+ n3 = bch_btree_node_alloc(b->c, op, b->level + 1, NULL);
if (IS_ERR(n3))
goto err_free2;
}
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 91dfa5e69685..5c391fa01bed 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -242,9 +242,10 @@ void __bch_btree_node_write(struct btree *, struct closure *);
void bch_btree_node_write(struct btree *, struct closure *);
void bch_btree_set_root(struct btree *);
-struct btree *bch_btree_node_alloc(struct cache_set *, struct btree_op *, int);
+struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *,
+ int, bool, struct btree *);
struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *,
- struct bkey *, int, bool);
+ struct bkey *, int, bool, struct btree *);
int bch_btree_insert_check_key(struct btree *, struct btree_op *,
struct bkey *);
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index 3a0de4cf9771..243de0bf15cd 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -474,9 +474,8 @@ out:
return false;
}
-static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k)
{
- struct btree *b = container_of(bk, struct btree, keys);
char buf[80];
if (!KEY_SIZE(k))
@@ -485,16 +484,22 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
if (KEY_SIZE(k) > KEY_OFFSET(k))
goto bad;
- if (__ptr_invalid(b->c, k))
+ if (__ptr_invalid(c, k))
goto bad;
return false;
bad:
bch_extent_to_text(buf, sizeof(buf), k);
- cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k));
+ cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
return true;
}
+static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
+{
+ struct btree *b = container_of(bk, struct btree, keys);
+ return __bch_extent_invalid(b->c, k);
+}
+
static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
unsigned ptr)
{
diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h
index e4e23409782d..e2ed54054e7a 100644
--- a/drivers/md/bcache/extents.h
+++ b/drivers/md/bcache/extents.h
@@ -9,5 +9,6 @@ struct cache_set;
void bch_extent_to_text(char *, size_t, const struct bkey *);
bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
+bool __bch_extent_invalid(struct cache_set *, const struct bkey *);
#endif /* _BCACHE_EXTENTS_H */
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 59e82021b5bb..fe080ad0e558 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -7,6 +7,7 @@
#include "bcache.h"
#include "btree.h"
#include "debug.h"
+#include "extents.h"
#include <trace/events/bcache.h>
@@ -189,11 +190,15 @@ int bch_journal_read(struct cache_set *c, struct list_head *list)
if (read_bucket(l))
goto bsearch;
- if (list_empty(list))
+ /* no journal entries on this device? */
+ if (l == ca->sb.njournal_buckets)
continue;
bsearch:
+ BUG_ON(list_empty(list));
+
/* Binary search */
- m = r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
+ m = l;
+ r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
pr_debug("starting binary search, l %u r %u", l, r);
while (l + 1 < r) {
@@ -291,15 +296,16 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
for (k = i->j.start;
k < bset_bkey_last(&i->j);
- k = bkey_next(k)) {
- unsigned j;
+ k = bkey_next(k))
+ if (!__bch_extent_invalid(c, k)) {
+ unsigned j;
- for (j = 0; j < KEY_PTRS(k); j++)
- if (ptr_available(c, k, j))
- atomic_inc(&PTR_BUCKET(c, k, j)->pin);
+ for (j = 0; j < KEY_PTRS(k); j++)
+ if (ptr_available(c, k, j))
+ atomic_inc(&PTR_BUCKET(c, k, j)->pin);
- bch_initial_mark_key(c, 0, k);
- }
+ bch_initial_mark_key(c, 0, k);
+ }
}
}
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 15fff4f68a7c..62e6e98186b5 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -311,7 +311,8 @@ void bch_data_insert(struct closure *cl)
{
struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
- trace_bcache_write(op->bio, op->writeback, op->bypass);
+ trace_bcache_write(op->c, op->inode, op->bio,
+ op->writeback, op->bypass);
bch_keylist_init(&op->insert_keys);
bio_get(op->bio);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 926ded8ccbf5..d4713d098a39 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -733,8 +733,6 @@ static void bcache_device_detach(struct bcache_device *d)
static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
unsigned id)
{
- BUG_ON(test_bit(CACHE_SET_STOPPING, &c->flags));
-
d->id = id;
d->c = c;
c->devices[id] = d;
@@ -927,6 +925,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
list_move(&dc->list, &uncached_devices);
clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
+ clear_bit(BCACHE_DEV_UNLINK_DONE, &dc->disk.flags);
mutex_unlock(&bch_register_lock);
@@ -1041,6 +1040,9 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
*/
atomic_set(&dc->count, 1);
+ if (bch_cached_dev_writeback_start(dc))
+ return -ENOMEM;
+
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
bch_sectors_dirty_init(dc);
atomic_set(&dc->has_dirty, 1);
@@ -1070,7 +1072,8 @@ static void cached_dev_free(struct closure *cl)
struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
cancel_delayed_work_sync(&dc->writeback_rate_update);
- kthread_stop(dc->writeback_thread);
+ if (!IS_ERR_OR_NULL(dc->writeback_thread))
+ kthread_stop(dc->writeback_thread);
mutex_lock(&bch_register_lock);
@@ -1081,12 +1084,8 @@ static void cached_dev_free(struct closure *cl)
mutex_unlock(&bch_register_lock);
- if (!IS_ERR_OR_NULL(dc->bdev)) {
- if (dc->bdev->bd_disk)
- blk_sync_queue(bdev_get_queue(dc->bdev));
-
+ if (!IS_ERR_OR_NULL(dc->bdev))
blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
- }
wake_up(&unregister_wait);
@@ -1213,7 +1212,9 @@ void bch_flash_dev_release(struct kobject *kobj)
static void flash_dev_free(struct closure *cl)
{
struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+ mutex_lock(&bch_register_lock);
bcache_device_free(d);
+ mutex_unlock(&bch_register_lock);
kobject_put(&d->kobj);
}
@@ -1221,7 +1222,9 @@ static void flash_dev_flush(struct closure *cl)
{
struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+ mutex_lock(&bch_register_lock);
bcache_device_unlink(d);
+ mutex_unlock(&bch_register_lock);
kobject_del(&d->kobj);
continue_at(cl, flash_dev_free, system_wq);
}
@@ -1277,6 +1280,9 @@ int bch_flash_dev_create(struct cache_set *c, uint64_t size)
if (test_bit(CACHE_SET_STOPPING, &c->flags))
return -EINTR;
+ if (!test_bit(CACHE_SET_RUNNING, &c->flags))
+ return -EPERM;
+
u = uuid_find_empty(c);
if (!u) {
pr_err("Can't create volume, no room for UUID");
@@ -1346,8 +1352,11 @@ static void cache_set_free(struct closure *cl)
bch_journal_free(c);
for_each_cache(ca, c, i)
- if (ca)
+ if (ca) {
+ ca->set = NULL;
+ c->cache[ca->sb.nr_this_dev] = NULL;
kobject_put(&ca->kobj);
+ }
bch_bset_sort_state_free(&c->sort);
free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c)));
@@ -1405,9 +1414,11 @@ static void cache_set_flush(struct closure *cl)
if (ca->alloc_thread)
kthread_stop(ca->alloc_thread);
- cancel_delayed_work_sync(&c->journal.work);
- /* flush last journal entry if needed */
- c->journal.work.work.func(&c->journal.work.work);
+ if (c->journal.cur) {
+ cancel_delayed_work_sync(&c->journal.work);
+ /* flush last journal entry if needed */
+ c->journal.work.work.func(&c->journal.work.work);
+ }
closure_return(cl);
}
@@ -1586,7 +1597,7 @@ static void run_cache_set(struct cache_set *c)
goto err;
err = "error reading btree root";
- c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true);
+ c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL);
if (IS_ERR_OR_NULL(c->root))
goto err;
@@ -1661,7 +1672,7 @@ static void run_cache_set(struct cache_set *c)
goto err;
err = "cannot allocate new btree root";
- c->root = bch_btree_node_alloc(c, NULL, 0);
+ c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
if (IS_ERR_OR_NULL(c->root))
goto err;
@@ -1697,6 +1708,7 @@ static void run_cache_set(struct cache_set *c)
flash_devs_run(c);
+ set_bit(CACHE_SET_RUNNING, &c->flags);
return;
err:
closure_sync(&cl);
@@ -1760,6 +1772,7 @@ found:
pr_debug("set version = %llu", c->sb.version);
}
+ kobject_get(&ca->kobj);
ca->set = c;
ca->set->cache[ca->sb.nr_this_dev] = ca;
c->cache_by_alloc[c->caches_loaded++] = ca;
@@ -1780,8 +1793,10 @@ void bch_cache_release(struct kobject *kobj)
struct cache *ca = container_of(kobj, struct cache, kobj);
unsigned i;
- if (ca->set)
+ if (ca->set) {
+ BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
ca->set->cache[ca->sb.nr_this_dev] = NULL;
+ }
bio_split_pool_free(&ca->bio_split_hook);
@@ -1798,10 +1813,8 @@ void bch_cache_release(struct kobject *kobj)
if (ca->sb_bio.bi_inline_vecs[0].bv_page)
put_page(ca->sb_bio.bi_io_vec[0].bv_page);
- if (!IS_ERR_OR_NULL(ca->bdev)) {
- blk_sync_queue(bdev_get_queue(ca->bdev));
+ if (!IS_ERR_OR_NULL(ca->bdev))
blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
- }
kfree(ca);
module_put(THIS_MODULE);
@@ -1844,7 +1857,7 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
}
static void register_cache(struct cache_sb *sb, struct page *sb_page,
- struct block_device *bdev, struct cache *ca)
+ struct block_device *bdev, struct cache *ca)
{
char name[BDEVNAME_SIZE];
const char *err = "cannot allocate memory";
@@ -1877,10 +1890,12 @@ static void register_cache(struct cache_sb *sb, struct page *sb_page,
goto err;
pr_info("registered cache device %s", bdevname(bdev, name));
+out:
+ kobject_put(&ca->kobj);
return;
err:
pr_notice("error opening %s: %s", bdevname(bdev, name), err);
- kobject_put(&ca->kobj);
+ goto out;
}
/* Global interfaces/init */
@@ -1945,10 +1960,12 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
if (IS_ERR(bdev)) {
if (bdev == ERR_PTR(-EBUSY)) {
bdev = lookup_bdev(strim(path));
+ mutex_lock(&bch_register_lock);
if (!IS_ERR(bdev) && bch_is_open(bdev))
err = "device already registered";
else
err = "device busy";
+ mutex_unlock(&bch_register_lock);
}
goto err;
}
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index ac7d0d1f70d7..98df7572b5f7 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -416,8 +416,8 @@ do { \
average_frequency, frequency_units); \
__print_time_stat(stats, name, \
average_duration, duration_units); \
- __print_time_stat(stats, name, \
- max_duration, duration_units); \
+ sysfs_print(name ## _ ##max_duration ## _ ## duration_units, \
+ div_u64((stats)->max_duration, NSEC_PER_ ## duration_units));\
\
sysfs_print(name ## _last_ ## frequency_units, (stats)->last \
? div_s64(local_clock() - (stats)->last, \
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index f4300e4c0114..f1986bcd1bf0 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -239,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
if (KEY_START(&w->key) != dc->last_read ||
jiffies_to_msecs(delay) > 50)
while (!kthread_should_stop() && delay)
- delay = schedule_timeout_uninterruptible(delay);
+ delay = schedule_timeout_interruptible(delay);
dc->last_read = KEY_OFFSET(&w->key);
@@ -436,7 +436,7 @@ static int bch_writeback_thread(void *arg)
while (delay &&
!kthread_should_stop() &&
!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
- delay = schedule_timeout_uninterruptible(delay);
+ delay = schedule_timeout_interruptible(delay);
}
}
@@ -478,7 +478,7 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
}
-int bch_cached_dev_writeback_init(struct cached_dev *dc)
+void bch_cached_dev_writeback_init(struct cached_dev *dc)
{
sema_init(&dc->in_flight, 64);
init_rwsem(&dc->writeback_lock);
@@ -494,14 +494,20 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
dc->writeback_rate_d_term = 30;
dc->writeback_rate_p_term_inverse = 6000;
+ INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
+}
+
+int bch_cached_dev_writeback_start(struct cached_dev *dc)
+{
dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
"bcache_writeback");
if (IS_ERR(dc->writeback_thread))
return PTR_ERR(dc->writeback_thread);
- INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
schedule_delayed_work(&dc->writeback_rate_update,
dc->writeback_rate_update_seconds * HZ);
+ bch_writeback_queue(dc);
+
return 0;
}
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index e2f8598937ac..0a9dab187b79 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -85,6 +85,7 @@ static inline void bch_writeback_add(struct cached_dev *dc)
void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
void bch_sectors_dirty_init(struct cached_dev *dc);
-int bch_cached_dev_writeback_init(struct cached_dev *);
+void bch_cached_dev_writeback_init(struct cached_dev *);
+int bch_cached_dev_writeback_start(struct cached_dev *);
#endif
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index d724459860d9..ab472c557d18 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -615,16 +615,6 @@ static void write_endio(struct bio *bio, int error)
}
/*
- * This function is called when wait_on_bit is actually waiting.
- */
-static int do_io_schedule(void *word)
-{
- io_schedule();
-
- return 0;
-}
-
-/*
* Initiate a write on a dirty buffer, but don't wait for it.
*
* - If the buffer is not dirty, exit.
@@ -640,8 +630,7 @@ static void __write_dirty_buffer(struct dm_buffer *b,
return;
clear_bit(B_DIRTY, &b->state);
- wait_on_bit_lock(&b->state, B_WRITING,
- do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_lock_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);
if (!write_list)
submit_io(b, WRITE, b->block, write_endio);
@@ -675,9 +664,9 @@ static void __make_buffer_clean(struct dm_buffer *b)
if (!b->state) /* fast case */
return;
- wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
__write_dirty_buffer(b, NULL);
- wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);
}
/*
@@ -1030,7 +1019,7 @@ static void *new_read(struct dm_bufio_client *c, sector_t block,
if (need_submit)
submit_io(b, READ, b->block, read_endio);
- wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
if (b->read_error) {
int error = b->read_error;
@@ -1209,15 +1198,13 @@ again:
dropped_lock = 1;
b->hold_count++;
dm_bufio_unlock(c);
- wait_on_bit(&b->state, B_WRITING,
- do_io_schedule,
- TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_WRITING,
+ TASK_UNINTERRUPTIBLE);
dm_bufio_lock(c);
b->hold_count--;
} else
- wait_on_bit(&b->state, B_WRITING,
- do_io_schedule,
- TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_WRITING,
+ TASK_UNINTERRUPTIBLE);
}
if (!test_bit(B_DIRTY, &b->state) &&
@@ -1321,15 +1308,15 @@ retry:
__write_dirty_buffer(b, NULL);
if (b->hold_count == 1) {
- wait_on_bit(&b->state, B_WRITING,
- do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_WRITING,
+ TASK_UNINTERRUPTIBLE);
set_bit(B_DIRTY, &b->state);
__unlink_buffer(b);
__link_buffer(b, new_block, LIST_DIRTY);
} else {
sector_t old_block;
- wait_on_bit_lock(&b->state, B_WRITING,
- do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_lock_io(&b->state, B_WRITING,
+ TASK_UNINTERRUPTIBLE);
/*
* Relink buffer to "new_block" so that write_callback
* sees "new_block" as a block number.
@@ -1341,8 +1328,8 @@ retry:
__unlink_buffer(b);
__link_buffer(b, new_block, b->list_mode);
submit_io(b, WRITE, new_block, write_endio);
- wait_on_bit(&b->state, B_WRITING,
- do_io_schedule, TASK_UNINTERRUPTIBLE);
+ wait_on_bit_io(&b->state, B_WRITING,
+ TASK_UNINTERRUPTIBLE);
__unlink_buffer(b);
__link_buffer(b, old_block, b->list_mode);
}
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index d2899e7eb3aa..06709257adde 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -330,7 +330,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
disk_super->discard_root = cpu_to_le64(cmd->discard_root);
disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size);
disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks));
- disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+ disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE);
disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
disk_super->cache_blocks = cpu_to_le32(0);
@@ -478,7 +478,7 @@ static int __create_persistent_data_objects(struct dm_cache_metadata *cmd,
bool may_format_device)
{
int r;
- cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE,
+ cmd->bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
CACHE_METADATA_CACHE_SIZE,
CACHE_MAX_CONCURRENT_LOCKS);
if (IS_ERR(cmd->bm)) {
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h
index cd70a78623a3..7383c90ccdb8 100644
--- a/drivers/md/dm-cache-metadata.h
+++ b/drivers/md/dm-cache-metadata.h
@@ -9,19 +9,17 @@
#include "dm-cache-block-types.h"
#include "dm-cache-policy-internal.h"
+#include "persistent-data/dm-space-map-metadata.h"
/*----------------------------------------------------------------*/
-#define DM_CACHE_METADATA_BLOCK_SIZE 4096
+#define DM_CACHE_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
/* FIXME: remove this restriction */
/*
* The metadata device is currently limited in size.
- *
- * We have one block of index, which can hold 255 index entries. Each
- * index entry contains allocation info about 16k metadata blocks.
*/
-#define DM_CACHE_METADATA_MAX_SECTORS (255 * (1 << 14) * (DM_CACHE_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+#define DM_CACHE_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
/*
* A metadata device larger than 16GB triggers a warning.
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 2c63326638b6..1af40ee209e2 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -718,6 +718,22 @@ static int bio_triggers_commit(struct cache *cache, struct bio *bio)
return bio->bi_rw & (REQ_FLUSH | REQ_FUA);
}
+/*
+ * You must increment the deferred set whilst the prison cell is held. To
+ * encourage this, we ask for 'cell' to be passed in.
+ */
+static void inc_ds(struct cache *cache, struct bio *bio,
+ struct dm_bio_prison_cell *cell)
+{
+ size_t pb_data_size = get_per_bio_data_size(cache);
+ struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
+
+ BUG_ON(!cell);
+ BUG_ON(pb->all_io_entry);
+
+ pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
+}
+
static void issue(struct cache *cache, struct bio *bio)
{
unsigned long flags;
@@ -737,6 +753,12 @@ static void issue(struct cache *cache, struct bio *bio)
spin_unlock_irqrestore(&cache->lock, flags);
}
+static void inc_and_issue(struct cache *cache, struct bio *bio, struct dm_bio_prison_cell *cell)
+{
+ inc_ds(cache, bio, cell);
+ issue(cache, bio);
+}
+
static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
{
unsigned long flags;
@@ -1015,6 +1037,11 @@ static void issue_overwrite(struct dm_cache_migration *mg, struct bio *bio)
dm_hook_bio(&pb->hook_info, bio, overwrite_endio, mg);
remap_to_cache_dirty(mg->cache, bio, mg->new_oblock, mg->cblock);
+
+ /*
+ * No need to inc_ds() here, since the cell will be held for the
+ * duration of the io.
+ */
generic_make_request(bio);
}
@@ -1115,8 +1142,7 @@ static void check_for_quiesced_migrations(struct cache *cache,
return;
INIT_LIST_HEAD(&work);
- if (pb->all_io_entry)
- dm_deferred_entry_dec(pb->all_io_entry, &work);
+ dm_deferred_entry_dec(pb->all_io_entry, &work);
if (!list_empty(&work))
queue_quiesced_migrations(cache, &work);
@@ -1252,6 +1278,11 @@ static void process_flush_bio(struct cache *cache, struct bio *bio)
else
remap_to_cache(cache, bio, 0);
+ /*
+ * REQ_FLUSH is not directed at any particular block so we don't
+ * need to inc_ds(). REQ_FUA's are split into a write + REQ_FLUSH
+ * by dm-core.
+ */
issue(cache, bio);
}
@@ -1301,15 +1332,6 @@ static void inc_miss_counter(struct cache *cache, struct bio *bio)
&cache->stats.read_miss : &cache->stats.write_miss);
}
-static void issue_cache_bio(struct cache *cache, struct bio *bio,
- struct per_bio_data *pb,
- dm_oblock_t oblock, dm_cblock_t cblock)
-{
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
- remap_to_cache_dirty(cache, bio, oblock, cblock);
- issue(cache, bio);
-}
-
static void process_bio(struct cache *cache, struct prealloc *structs,
struct bio *bio)
{
@@ -1318,8 +1340,6 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
dm_oblock_t block = get_bio_block(cache, bio);
struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
struct policy_result lookup_result;
- size_t pb_data_size = get_per_bio_data_size(cache);
- struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
bool discarded_block = is_discarded_oblock(cache, block);
bool passthrough = passthrough_mode(&cache->features);
bool can_migrate = !passthrough && (discarded_block || spare_migration_bandwidth(cache));
@@ -1359,9 +1379,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
} else {
/* FIXME: factor out issue_origin() */
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
remap_to_origin_clear_discard(cache, bio, block);
- issue(cache, bio);
+ inc_and_issue(cache, bio, new_ocell);
}
} else {
inc_hit_counter(cache, bio);
@@ -1369,20 +1388,21 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
if (bio_data_dir(bio) == WRITE &&
writethrough_mode(&cache->features) &&
!is_dirty(cache, lookup_result.cblock)) {
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
- issue(cache, bio);
- } else
- issue_cache_bio(cache, bio, pb, block, lookup_result.cblock);
+ inc_and_issue(cache, bio, new_ocell);
+
+ } else {
+ remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
+ inc_and_issue(cache, bio, new_ocell);
+ }
}
break;
case POLICY_MISS:
inc_miss_counter(cache, bio);
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
remap_to_origin_clear_discard(cache, bio, block);
- issue(cache, bio);
+ inc_and_issue(cache, bio, new_ocell);
break;
case POLICY_NEW:
@@ -1501,6 +1521,9 @@ static void process_deferred_flush_bios(struct cache *cache, bool submit_bios)
bio_list_init(&cache->deferred_flush_bios);
spin_unlock_irqrestore(&cache->lock, flags);
+ /*
+ * These bios have already been through inc_ds()
+ */
while ((bio = bio_list_pop(&bios)))
submit_bios ? generic_make_request(bio) : bio_io_error(bio);
}
@@ -1518,6 +1541,9 @@ static void process_deferred_writethrough_bios(struct cache *cache)
bio_list_init(&cache->deferred_writethrough_bios);
spin_unlock_irqrestore(&cache->lock, flags);
+ /*
+ * These bios have already been through inc_ds()
+ */
while ((bio = bio_list_pop(&bios)))
generic_make_request(bio);
}
@@ -1694,6 +1720,7 @@ static void do_worker(struct work_struct *ws)
if (commit_if_needed(cache)) {
process_deferred_flush_bios(cache, false);
+ process_migrations(cache, &cache->need_commit_migrations, migration_failure);
/*
* FIXME: rollback metadata or just go into a
@@ -2406,16 +2433,13 @@ out:
return r;
}
-static int cache_map(struct dm_target *ti, struct bio *bio)
+static int __cache_map(struct cache *cache, struct bio *bio, struct dm_bio_prison_cell **cell)
{
- struct cache *cache = ti->private;
-
int r;
dm_oblock_t block = get_bio_block(cache, bio);
size_t pb_data_size = get_per_bio_data_size(cache);
bool can_migrate = false;
bool discarded_block;
- struct dm_bio_prison_cell *cell;
struct policy_result lookup_result;
struct per_bio_data *pb = init_per_bio_data(bio, pb_data_size);
@@ -2437,15 +2461,15 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
/*
* Check to see if that block is currently migrating.
*/
- cell = alloc_prison_cell(cache);
- if (!cell) {
+ *cell = alloc_prison_cell(cache);
+ if (!*cell) {
defer_bio(cache, bio);
return DM_MAPIO_SUBMITTED;
}
- r = bio_detain(cache, block, bio, cell,
+ r = bio_detain(cache, block, bio, *cell,
(cell_free_fn) free_prison_cell,
- cache, &cell);
+ cache, cell);
if (r) {
if (r < 0)
defer_bio(cache, bio);
@@ -2458,11 +2482,12 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
r = policy_map(cache->policy, block, false, can_migrate, discarded_block,
bio, &lookup_result);
if (r == -EWOULDBLOCK) {
- cell_defer(cache, cell, true);
+ cell_defer(cache, *cell, true);
return DM_MAPIO_SUBMITTED;
} else if (r) {
DMERR_LIMIT("Unexpected return from cache replacement policy: %d", r);
+ cell_defer(cache, *cell, false);
bio_io_error(bio);
return DM_MAPIO_SUBMITTED;
}
@@ -2476,52 +2501,44 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
* We need to invalidate this block, so
* defer for the worker thread.
*/
- cell_defer(cache, cell, true);
+ cell_defer(cache, *cell, true);
r = DM_MAPIO_SUBMITTED;
} else {
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
inc_miss_counter(cache, bio);
remap_to_origin_clear_discard(cache, bio, block);
-
- cell_defer(cache, cell, false);
}
} else {
inc_hit_counter(cache, bio);
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-
if (bio_data_dir(bio) == WRITE && writethrough_mode(&cache->features) &&
!is_dirty(cache, lookup_result.cblock))
remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
else
remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
-
- cell_defer(cache, cell, false);
}
break;
case POLICY_MISS:
inc_miss_counter(cache, bio);
- pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-
if (pb->req_nr != 0) {
/*
* This is a duplicate writethrough io that is no
* longer needed because the block has been demoted.
*/
bio_endio(bio, 0);
- cell_defer(cache, cell, false);
- return DM_MAPIO_SUBMITTED;
- } else {
+ cell_defer(cache, *cell, false);
+ r = DM_MAPIO_SUBMITTED;
+
+ } else
remap_to_origin_clear_discard(cache, bio, block);
- cell_defer(cache, cell, false);
- }
+
break;
default:
DMERR_LIMIT("%s: erroring bio: unknown policy op: %u", __func__,
(unsigned) lookup_result.op);
+ cell_defer(cache, *cell, false);
bio_io_error(bio);
r = DM_MAPIO_SUBMITTED;
}
@@ -2529,6 +2546,21 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
return r;
}
+static int cache_map(struct dm_target *ti, struct bio *bio)
+{
+ int r;
+ struct dm_bio_prison_cell *cell;
+ struct cache *cache = ti->private;
+
+ r = __cache_map(cache, bio, &cell);
+ if (r == DM_MAPIO_REMAPPED) {
+ inc_ds(cache, bio, cell);
+ cell_defer(cache, cell, false);
+ }
+
+ return r;
+}
+
static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
{
struct cache *cache = ti->private;
@@ -2808,7 +2840,7 @@ static void cache_status(struct dm_target *ti, status_type_t type,
residency = policy_residency(cache->policy);
DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ",
- (unsigned)(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT),
+ (unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
(unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
(unsigned long long)nr_blocks_metadata,
cache->sectors_per_block,
@@ -3062,7 +3094,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
*/
if (io_opt_sectors < cache->sectors_per_block ||
do_div(io_opt_sectors, cache->sectors_per_block)) {
- blk_limits_io_min(limits, 0);
+ blk_limits_io_min(limits, cache->sectors_per_block << SECTOR_SHIFT);
blk_limits_io_opt(limits, cache->sectors_per_block << SECTOR_SHIFT);
}
set_discard_limits(cache, limits);
@@ -3072,7 +3104,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
static struct target_type cache_target = {
.name = "cache",
- .version = {1, 4, 0},
+ .version = {1, 5, 0},
.module = THIS_MODULE,
.ctr = cache_ctr,
.dtr = cache_dtr,
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 4cba2d808afb..2785007e0e46 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -59,7 +59,7 @@ struct dm_crypt_io {
int error;
sector_t sector;
struct dm_crypt_io *base_io;
-};
+} CRYPTO_MINALIGN_ATTR;
struct dm_crypt_request {
struct convert_context *ctx;
@@ -162,6 +162,8 @@ struct crypt_config {
*/
unsigned int dmreq_start;
+ unsigned int per_bio_data_size;
+
unsigned long flags;
unsigned int key_size;
unsigned int key_parts; /* independent parts in key buffer */
@@ -895,6 +897,15 @@ static void crypt_alloc_req(struct crypt_config *cc,
kcryptd_async_done, dmreq_of_req(cc, ctx->req));
}
+static void crypt_free_req(struct crypt_config *cc,
+ struct ablkcipher_request *req, struct bio *base_bio)
+{
+ struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size);
+
+ if ((struct ablkcipher_request *)(io + 1) != req)
+ mempool_free(req, cc->req_pool);
+}
+
/*
* Encrypt / decrypt data from one bio to another one (can be the same one)
*/
@@ -1008,12 +1019,9 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
}
}
-static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc,
- struct bio *bio, sector_t sector)
+static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
+ struct bio *bio, sector_t sector)
{
- struct dm_crypt_io *io;
-
- io = mempool_alloc(cc->io_pool, GFP_NOIO);
io->cc = cc;
io->base_bio = bio;
io->sector = sector;
@@ -1021,8 +1029,6 @@ static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc,
io->base_io = NULL;
io->ctx.req = NULL;
atomic_set(&io->io_pending, 0);
-
- return io;
}
static void crypt_inc_pending(struct dm_crypt_io *io)
@@ -1046,8 +1052,9 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
return;
if (io->ctx.req)
- mempool_free(io->ctx.req, cc->req_pool);
- mempool_free(io, cc->io_pool);
+ crypt_free_req(cc, io->ctx.req, base_bio);
+ if (io != dm_per_bio_data(base_bio, cc->per_bio_data_size))
+ mempool_free(io, cc->io_pool);
if (likely(!base_io))
bio_endio(base_bio, error);
@@ -1255,8 +1262,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
* between fragments, so switch to a new dm_crypt_io structure.
*/
if (unlikely(!crypt_finished && remaining)) {
- new_io = crypt_io_alloc(io->cc, io->base_bio,
- sector);
+ new_io = mempool_alloc(cc->io_pool, GFP_NOIO);
+ crypt_io_init(new_io, io->cc, io->base_bio, sector);
crypt_inc_pending(new_io);
crypt_convert_init(cc, &new_io->ctx, NULL,
io->base_bio, sector);
@@ -1325,7 +1332,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
if (error < 0)
io->error = -EIO;
- mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
+ crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
if (!atomic_dec_and_test(&ctx->cc_pending))
return;
@@ -1728,6 +1735,10 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
+ cc->per_bio_data_size = ti->per_bio_data_size =
+ sizeof(struct dm_crypt_io) + cc->dmreq_start +
+ sizeof(struct dm_crypt_request) + cc->iv_size;
+
cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
if (!cc->page_pool) {
ti->error = "Cannot allocate page mempool";
@@ -1824,7 +1835,9 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
}
- io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+ io = dm_per_bio_data(bio, cc->per_bio_data_size);
+ crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
+ io->ctx.req = (struct ablkcipher_request *)(io + 1);
if (bio_data_dir(io->base_bio) == READ) {
if (kcryptd_io_read(io, GFP_NOWAIT))
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index db404a0f7e2c..c09359db3a90 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -33,7 +33,6 @@ struct dm_io_client {
struct io {
unsigned long error_bits;
atomic_t count;
- struct completion *wait;
struct dm_io_client *client;
io_notify_fn callback;
void *context;
@@ -112,28 +111,27 @@ static void retrieve_io_and_region_from_bio(struct bio *bio, struct io **io,
* We need an io object to keep track of the number of bios that
* have been dispatched for a particular io.
*---------------------------------------------------------------*/
-static void dec_count(struct io *io, unsigned int region, int error)
+static void complete_io(struct io *io)
{
- if (error)
- set_bit(region, &io->error_bits);
+ unsigned long error_bits = io->error_bits;
+ io_notify_fn fn = io->callback;
+ void *context = io->context;
- if (atomic_dec_and_test(&io->count)) {
- if (io->vma_invalidate_size)
- invalidate_kernel_vmap_range(io->vma_invalidate_address,
- io->vma_invalidate_size);
+ if (io->vma_invalidate_size)
+ invalidate_kernel_vmap_range(io->vma_invalidate_address,
+ io->vma_invalidate_size);
- if (io->wait)
- complete(io->wait);
+ mempool_free(io, io->client->pool);
+ fn(error_bits, context);
+}
- else {
- unsigned long r = io->error_bits;
- io_notify_fn fn = io->callback;
- void *context = io->context;
+static void dec_count(struct io *io, unsigned int region, int error)
+{
+ if (error)
+ set_bit(region, &io->error_bits);
- mempool_free(io, io->client->pool);
- fn(r, context);
- }
- }
+ if (atomic_dec_and_test(&io->count))
+ complete_io(io);
}
static void endio(struct bio *bio, int error)
@@ -376,41 +374,51 @@ static void dispatch_io(int rw, unsigned int num_regions,
dec_count(io, 0, 0);
}
+struct sync_io {
+ unsigned long error_bits;
+ struct completion wait;
+};
+
+static void sync_io_complete(unsigned long error, void *context)
+{
+ struct sync_io *sio = context;
+
+ sio->error_bits = error;
+ complete(&sio->wait);
+}
+
static int sync_io(struct dm_io_client *client, unsigned int num_regions,
struct dm_io_region *where, int rw, struct dpages *dp,
unsigned long *error_bits)
{
- /*
- * gcc <= 4.3 can't do the alignment for stack variables, so we must
- * align it on our own.
- * volatile prevents the optimizer from removing or reusing
- * "io_" field from the stack frame (allowed in ANSI C).
- */
- volatile char io_[sizeof(struct io) + __alignof__(struct io) - 1];
- struct io *io = (struct io *)PTR_ALIGN(&io_, __alignof__(struct io));
- DECLARE_COMPLETION_ONSTACK(wait);
+ struct io *io;
+ struct sync_io sio;
if (num_regions > 1 && (rw & RW_MASK) != WRITE) {
WARN_ON(1);
return -EIO;
}
+ init_completion(&sio.wait);
+
+ io = mempool_alloc(client->pool, GFP_NOIO);
io->error_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
- io->wait = &wait;
io->client = client;
+ io->callback = sync_io_complete;
+ io->context = &sio;
io->vma_invalidate_address = dp->vma_invalidate_address;
io->vma_invalidate_size = dp->vma_invalidate_size;
dispatch_io(rw, num_regions, where, dp, io, 1);
- wait_for_completion_io(&wait);
+ wait_for_completion_io(&sio.wait);
if (error_bits)
- *error_bits = io->error_bits;
+ *error_bits = sio.error_bits;
- return io->error_bits ? -EIO : 0;
+ return sio.error_bits ? -EIO : 0;
}
static int async_io(struct dm_io_client *client, unsigned int num_regions,
@@ -428,7 +436,6 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
io = mempool_alloc(client->pool, GFP_NOIO);
io->error_bits = 0;
atomic_set(&io->count, 1); /* see dispatch_io() */
- io->wait = NULL;
io->client = client;
io->callback = fn;
io->context = context;
@@ -481,9 +488,9 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
* New collapsed (a)synchronous interface.
*
* If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
- * the queue with blk_unplug() some time later or set REQ_SYNC in
-io_req->bi_rw. If you fail to do one of these, the IO will be submitted to
- * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
+ * the queue with blk_unplug() some time later or set REQ_SYNC in io_req->bi_rw.
+ * If you fail to do one of these, the IO will be submitted to the disk after
+ * q->unplug_delay, which defaults to 3ms in blk-settings.c.
*/
int dm_io(struct dm_io_request *io_req, unsigned num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index f4167b013d99..833d7e752f06 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -373,8 +373,6 @@ static int __must_push_back(struct multipath *m)
dm_noflush_suspending(m->ti)));
}
-#define pg_ready(m) (!(m)->queue_io && !(m)->pg_init_required)
-
/*
* Map cloned requests
*/
@@ -402,11 +400,11 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
if (!__must_push_back(m))
r = -EIO; /* Failed */
goto out_unlock;
- }
- if (!pg_ready(m)) {
+ } else if (m->queue_io || m->pg_init_required) {
__pg_init_all_paths(m);
goto out_unlock;
}
+
if (set_mapinfo(m, map_context) < 0)
/* ENOMEM, requeue */
goto out_unlock;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 5bd2290cfb1e..864b03f47727 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1032,21 +1032,13 @@ static void start_merge(struct dm_snapshot *s)
snapshot_merge_next_chunks(s);
}
-static int wait_schedule(void *ptr)
-{
- schedule();
-
- return 0;
-}
-
/*
* Stop the merging process and wait until it finishes.
*/
static void stop_merge(struct dm_snapshot *s)
{
set_bit(SHUTDOWN_MERGE, &s->state_bits);
- wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
- TASK_UNINTERRUPTIBLE);
+ wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE);
clear_bit(SHUTDOWN_MERGE, &s->state_bits);
}
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 09a688b3d48c..50fca469cafd 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -137,13 +137,23 @@ static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr
*bit *= sctx->region_table_entry_bits;
}
+static unsigned switch_region_table_read(struct switch_ctx *sctx, unsigned long region_nr)
+{
+ unsigned long region_index;
+ unsigned bit;
+
+ switch_get_position(sctx, region_nr, &region_index, &bit);
+
+ return (ACCESS_ONCE(sctx->region_table[region_index]) >> bit) &
+ ((1 << sctx->region_table_entry_bits) - 1);
+}
+
/*
* Find which path to use at given offset.
*/
static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
{
- unsigned long region_index;
- unsigned bit, path_nr;
+ unsigned path_nr;
sector_t p;
p = offset;
@@ -152,9 +162,7 @@ static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset)
else
sector_div(p, sctx->region_size);
- switch_get_position(sctx, p, &region_index, &bit);
- path_nr = (ACCESS_ONCE(sctx->region_table[region_index]) >> bit) &
- ((1 << sctx->region_table_entry_bits) - 1);
+ path_nr = switch_region_table_read(sctx, p);
/* This can only happen if the processor uses non-atomic stores. */
if (unlikely(path_nr >= sctx->nr_paths))
@@ -363,7 +371,7 @@ static __always_inline unsigned long parse_hex(const char **string)
}
static int process_set_region_mappings(struct switch_ctx *sctx,
- unsigned argc, char **argv)
+ unsigned argc, char **argv)
{
unsigned i;
unsigned long region_index = 0;
@@ -372,6 +380,51 @@ static int process_set_region_mappings(struct switch_ctx *sctx,
unsigned long path_nr;
const char *string = argv[i];
+ if ((*string & 0xdf) == 'R') {
+ unsigned long cycle_length, num_write;
+
+ string++;
+ if (unlikely(*string == ',')) {
+ DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+ return -EINVAL;
+ }
+ cycle_length = parse_hex(&string);
+ if (unlikely(*string != ',')) {
+ DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+ return -EINVAL;
+ }
+ string++;
+ if (unlikely(!*string)) {
+ DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+ return -EINVAL;
+ }
+ num_write = parse_hex(&string);
+ if (unlikely(*string)) {
+ DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
+ return -EINVAL;
+ }
+
+ if (unlikely(!cycle_length) || unlikely(cycle_length - 1 > region_index)) {
+ DMWARN("invalid set_region_mappings cycle length: %lu > %lu",
+ cycle_length - 1, region_index);
+ return -EINVAL;
+ }
+ if (unlikely(region_index + num_write < region_index) ||
+ unlikely(region_index + num_write >= sctx->nr_regions)) {
+ DMWARN("invalid set_region_mappings region number: %lu + %lu >= %lu",
+ region_index, num_write, sctx->nr_regions);
+ return -EINVAL;
+ }
+
+ while (num_write--) {
+ region_index++;
+ path_nr = switch_region_table_read(sctx, region_index - cycle_length);
+ switch_region_table_write(sctx, region_index, path_nr);
+ }
+
+ continue;
+ }
+
if (*string == ':')
region_index++;
else {
@@ -500,7 +553,7 @@ static int switch_iterate_devices(struct dm_target *ti,
static struct target_type switch_target = {
.name = "switch",
- .version = {1, 0, 0},
+ .version = {1, 1, 0},
.module = THIS_MODULE,
.ctr = switch_ctr,
.dtr = switch_dtr,
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 5f59f1e3e5b1..f9c6cb8dbcf8 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1386,6 +1386,14 @@ static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
return q && !blk_queue_add_random(q);
}
+static int queue_supports_sg_merge(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return q && !test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags);
+}
+
static bool dm_table_all_devices_attribute(struct dm_table *t,
iterate_devices_callout_fn func)
{
@@ -1430,6 +1438,43 @@ static bool dm_table_supports_write_same(struct dm_table *t)
return true;
}
+static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return q && blk_queue_discard(q);
+}
+
+static bool dm_table_supports_discards(struct dm_table *t)
+{
+ struct dm_target *ti;
+ unsigned i = 0;
+
+ /*
+ * Unless any target used by the table set discards_supported,
+ * require at least one underlying device to support discards.
+ * t->devices includes internal dm devices such as mirror logs
+ * so we need to use iterate_devices here, which targets
+ * supporting discard selectively must provide.
+ */
+ while (i < dm_table_get_num_targets(t)) {
+ ti = dm_table_get_target(t, i++);
+
+ if (!ti->num_discard_bios)
+ continue;
+
+ if (ti->discards_supported)
+ return 1;
+
+ if (ti->type->iterate_devices &&
+ ti->type->iterate_devices(ti, device_discard_capable, NULL))
+ return 1;
+ }
+
+ return 0;
+}
+
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *limits)
{
@@ -1464,6 +1509,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (!dm_table_supports_write_same(t))
q->limits.max_write_same_sectors = 0;
+ if (dm_table_all_devices_attribute(t, queue_supports_sg_merge))
+ queue_flag_clear_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
+ else
+ queue_flag_set_unlocked(QUEUE_FLAG_NO_SG_MERGE, q);
+
dm_table_set_integrity(t);
/*
@@ -1636,39 +1686,3 @@ void dm_table_run_md_queue_async(struct dm_table *t)
}
EXPORT_SYMBOL(dm_table_run_md_queue_async);
-static int device_discard_capable(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- struct request_queue *q = bdev_get_queue(dev->bdev);
-
- return q && blk_queue_discard(q);
-}
-
-bool dm_table_supports_discards(struct dm_table *t)
-{
- struct dm_target *ti;
- unsigned i = 0;
-
- /*
- * Unless any target used by the table set discards_supported,
- * require at least one underlying device to support discards.
- * t->devices includes internal dm devices such as mirror logs
- * so we need to use iterate_devices here, which targets
- * supporting discard selectively must provide.
- */
- while (i < dm_table_get_num_targets(t)) {
- ti = dm_table_get_target(t, i++);
-
- if (!ti->num_discard_bios)
- continue;
-
- if (ti->discards_supported)
- return 1;
-
- if (ti->type->iterate_devices &&
- ti->type->iterate_devices(ti, device_discard_capable, NULL))
- return 1;
- }
-
- return 0;
-}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index fc9c848a60c9..4843801173fe 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -227,6 +227,7 @@ struct thin_c {
struct list_head list;
struct dm_dev *pool_dev;
struct dm_dev *origin_dev;
+ sector_t origin_size;
dm_thin_id dev_id;
struct pool *pool;
@@ -554,11 +555,16 @@ static void remap_and_issue(struct thin_c *tc, struct bio *bio,
struct dm_thin_new_mapping {
struct list_head list;
- bool quiesced:1;
- bool prepared:1;
bool pass_discard:1;
bool definitely_not_shared:1;
+ /*
+ * Track quiescing, copying and zeroing preparation actions. When this
+ * counter hits zero the block is prepared and can be inserted into the
+ * btree.
+ */
+ atomic_t prepare_actions;
+
int err;
struct thin_c *tc;
dm_block_t virt_block;
@@ -575,43 +581,41 @@ struct dm_thin_new_mapping {
bio_end_io_t *saved_bi_end_io;
};
-static void __maybe_add_mapping(struct dm_thin_new_mapping *m)
+static void __complete_mapping_preparation(struct dm_thin_new_mapping *m)
{
struct pool *pool = m->tc->pool;
- if (m->quiesced && m->prepared) {
+ if (atomic_dec_and_test(&m->prepare_actions)) {
list_add_tail(&m->list, &pool->prepared_mappings);
wake_worker(pool);
}
}
-static void copy_complete(int read_err, unsigned long write_err, void *context)
+static void complete_mapping_preparation(struct dm_thin_new_mapping *m)
{
unsigned long flags;
- struct dm_thin_new_mapping *m = context;
struct pool *pool = m->tc->pool;
- m->err = read_err || write_err ? -EIO : 0;
-
spin_lock_irqsave(&pool->lock, flags);
- m->prepared = true;
- __maybe_add_mapping(m);
+ __complete_mapping_preparation(m);
spin_unlock_irqrestore(&pool->lock, flags);
}
+static void copy_complete(int read_err, unsigned long write_err, void *context)
+{
+ struct dm_thin_new_mapping *m = context;
+
+ m->err = read_err || write_err ? -EIO : 0;
+ complete_mapping_preparation(m);
+}
+
static void overwrite_endio(struct bio *bio, int err)
{
- unsigned long flags;
struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
struct dm_thin_new_mapping *m = h->overwrite_mapping;
- struct pool *pool = m->tc->pool;
m->err = err;
-
- spin_lock_irqsave(&pool->lock, flags);
- m->prepared = true;
- __maybe_add_mapping(m);
- spin_unlock_irqrestore(&pool->lock, flags);
+ complete_mapping_preparation(m);
}
/*----------------------------------------------------------------*/
@@ -821,10 +825,31 @@ static struct dm_thin_new_mapping *get_next_mapping(struct pool *pool)
return m;
}
+static void ll_zero(struct thin_c *tc, struct dm_thin_new_mapping *m,
+ sector_t begin, sector_t end)
+{
+ int r;
+ struct dm_io_region to;
+
+ to.bdev = tc->pool_dev->bdev;
+ to.sector = begin;
+ to.count = end - begin;
+
+ r = dm_kcopyd_zero(tc->pool->copier, 1, &to, 0, copy_complete, m);
+ if (r < 0) {
+ DMERR_LIMIT("dm_kcopyd_zero() failed");
+ copy_complete(1, 1, m);
+ }
+}
+
+/*
+ * A partial copy also needs to zero the uncopied region.
+ */
static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
struct dm_dev *origin, dm_block_t data_origin,
dm_block_t data_dest,
- struct dm_bio_prison_cell *cell, struct bio *bio)
+ struct dm_bio_prison_cell *cell, struct bio *bio,
+ sector_t len)
{
int r;
struct pool *pool = tc->pool;
@@ -835,8 +860,15 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
m->data_block = data_dest;
m->cell = cell;
+ /*
+ * quiesce action + copy action + an extra reference held for the
+ * duration of this function (we may need to inc later for a
+ * partial zero).
+ */
+ atomic_set(&m->prepare_actions, 3);
+
if (!dm_deferred_set_add_work(pool->shared_read_ds, &m->list))
- m->quiesced = true;
+ complete_mapping_preparation(m); /* already quiesced */
/*
* IO to pool_dev remaps to the pool target's data_dev.
@@ -857,20 +889,38 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
from.bdev = origin->bdev;
from.sector = data_origin * pool->sectors_per_block;
- from.count = pool->sectors_per_block;
+ from.count = len;
to.bdev = tc->pool_dev->bdev;
to.sector = data_dest * pool->sectors_per_block;
- to.count = pool->sectors_per_block;
+ to.count = len;
r = dm_kcopyd_copy(pool->copier, &from, 1, &to,
0, copy_complete, m);
if (r < 0) {
- mempool_free(m, pool->mapping_pool);
DMERR_LIMIT("dm_kcopyd_copy() failed");
- cell_error(pool, cell);
+ copy_complete(1, 1, m);
+
+ /*
+ * We allow the zero to be issued, to simplify the
+ * error path. Otherwise we'd need to start
+ * worrying about decrementing the prepare_actions
+ * counter.
+ */
+ }
+
+ /*
+ * Do we need to zero a tail region?
+ */
+ if (len < pool->sectors_per_block && pool->pf.zero_new_blocks) {
+ atomic_inc(&m->prepare_actions);
+ ll_zero(tc, m,
+ data_dest * pool->sectors_per_block + len,
+ (data_dest + 1) * pool->sectors_per_block);
}
}
+
+ complete_mapping_preparation(m); /* drop our ref */
}
static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block,
@@ -878,15 +928,8 @@ static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block,
struct dm_bio_prison_cell *cell, struct bio *bio)
{
schedule_copy(tc, virt_block, tc->pool_dev,
- data_origin, data_dest, cell, bio);
-}
-
-static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
- dm_block_t data_dest,
- struct dm_bio_prison_cell *cell, struct bio *bio)
-{
- schedule_copy(tc, virt_block, tc->origin_dev,
- virt_block, data_dest, cell, bio);
+ data_origin, data_dest, cell, bio,
+ tc->pool->sectors_per_block);
}
static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
@@ -896,8 +939,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
struct pool *pool = tc->pool;
struct dm_thin_new_mapping *m = get_next_mapping(pool);
- m->quiesced = true;
- m->prepared = false;
+ atomic_set(&m->prepare_actions, 1); /* no need to quiesce */
m->tc = tc;
m->virt_block = virt_block;
m->data_block = data_block;
@@ -919,21 +961,33 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
inc_all_io_entry(pool, bio);
remap_and_issue(tc, bio, data_block);
- } else {
- int r;
- struct dm_io_region to;
- to.bdev = tc->pool_dev->bdev;
- to.sector = data_block * pool->sectors_per_block;
- to.count = pool->sectors_per_block;
+ } else
+ ll_zero(tc, m,
+ data_block * pool->sectors_per_block,
+ (data_block + 1) * pool->sectors_per_block);
+}
- r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m);
- if (r < 0) {
- mempool_free(m, pool->mapping_pool);
- DMERR_LIMIT("dm_kcopyd_zero() failed");
- cell_error(pool, cell);
- }
- }
+static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block,
+ dm_block_t data_dest,
+ struct dm_bio_prison_cell *cell, struct bio *bio)
+{
+ struct pool *pool = tc->pool;
+ sector_t virt_block_begin = virt_block * pool->sectors_per_block;
+ sector_t virt_block_end = (virt_block + 1) * pool->sectors_per_block;
+
+ if (virt_block_end <= tc->origin_size)
+ schedule_copy(tc, virt_block, tc->origin_dev,
+ virt_block, data_dest, cell, bio,
+ pool->sectors_per_block);
+
+ else if (virt_block_begin < tc->origin_size)
+ schedule_copy(tc, virt_block, tc->origin_dev,
+ virt_block, data_dest, cell, bio,
+ tc->origin_size - virt_block_begin);
+
+ else
+ schedule_zero(tc, virt_block, data_dest, cell, bio);
}
/*
@@ -1315,7 +1369,18 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
inc_all_io_entry(pool, bio);
cell_defer_no_holder(tc, cell);
- remap_to_origin_and_issue(tc, bio);
+ if (bio_end_sector(bio) <= tc->origin_size)
+ remap_to_origin_and_issue(tc, bio);
+
+ else if (bio->bi_iter.bi_sector < tc->origin_size) {
+ zero_fill_bio(bio);
+ bio->bi_iter.bi_size = (tc->origin_size - bio->bi_iter.bi_sector) << SECTOR_SHIFT;
+ remap_to_origin_and_issue(tc, bio);
+
+ } else {
+ zero_fill_bio(bio);
+ bio_endio(bio, 0);
+ }
} else
provision_block(tc, bio, block, cell);
break;
@@ -3112,7 +3177,7 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
*/
if (io_opt_sectors < pool->sectors_per_block ||
do_div(io_opt_sectors, pool->sectors_per_block)) {
- blk_limits_io_min(limits, 0);
+ blk_limits_io_min(limits, pool->sectors_per_block << SECTOR_SHIFT);
blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
}
@@ -3141,7 +3206,7 @@ static struct target_type pool_target = {
.name = "thin-pool",
.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
DM_TARGET_IMMUTABLE,
- .version = {1, 12, 0},
+ .version = {1, 13, 0},
.module = THIS_MODULE,
.ctr = pool_ctr,
.dtr = pool_dtr,
@@ -3361,8 +3426,7 @@ static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
spin_lock_irqsave(&pool->lock, flags);
list_for_each_entry_safe(m, tmp, &work, list) {
list_del(&m->list);
- m->quiesced = true;
- __maybe_add_mapping(m);
+ __complete_mapping_preparation(m);
}
spin_unlock_irqrestore(&pool->lock, flags);
}
@@ -3401,6 +3465,16 @@ static void thin_postsuspend(struct dm_target *ti)
noflush_work(tc, do_noflush_stop);
}
+static int thin_preresume(struct dm_target *ti)
+{
+ struct thin_c *tc = ti->private;
+
+ if (tc->origin_dev)
+ tc->origin_size = get_dev_size(tc->origin_dev->bdev);
+
+ return 0;
+}
+
/*
* <nr mapped sectors> <highest mapped sector>
*/
@@ -3483,12 +3557,13 @@ static int thin_iterate_devices(struct dm_target *ti,
static struct target_type thin_target = {
.name = "thin",
- .version = {1, 12, 0},
+ .version = {1, 13, 0},
.module = THIS_MODULE,
.ctr = thin_ctr,
.dtr = thin_dtr,
.map = thin_map,
.end_io = thin_endio,
+ .preresume = thin_preresume,
.presuspend = thin_presuspend,
.postsuspend = thin_postsuspend,
.status = thin_status,
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index ed76126aac54..e81d2152fa68 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -72,7 +72,6 @@ int dm_table_any_busy_target(struct dm_table *t);
unsigned dm_table_get_type(struct dm_table *t);
struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
bool dm_table_request_based(struct dm_table *t);
-bool dm_table_supports_discards(struct dm_table *t);
void dm_table_free_md_mempools(struct dm_table *t);
struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 32fc19c540d4..1294238610df 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5961,7 +5961,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
int err = 0;
if (mddev->pers) {
- if (!mddev->pers->quiesce)
+ if (!mddev->pers->quiesce || !mddev->thread)
return -EBUSY;
if (mddev->recovery || mddev->sync_thread)
return -EBUSY;
@@ -6263,7 +6263,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
rv = update_raid_disks(mddev, info->raid_disks);
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
- if (mddev->pers->quiesce == NULL)
+ if (mddev->pers->quiesce == NULL || mddev->thread == NULL)
return -EINVAL;
if (mddev->recovery || mddev->sync_thread)
return -EBUSY;
@@ -7376,7 +7376,7 @@ void md_do_sync(struct md_thread *thread)
struct mddev *mddev2;
unsigned int currspeed = 0,
window;
- sector_t max_sectors,j, io_sectors;
+ sector_t max_sectors,j, io_sectors, recovery_done;
unsigned long mark[SYNC_MARKS];
unsigned long update_time;
sector_t mark_cnt[SYNC_MARKS];
@@ -7652,7 +7652,8 @@ void md_do_sync(struct md_thread *thread)
*/
cond_resched();
- currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+ recovery_done = io_sectors - atomic_read(&mddev->recovery_active);
+ currspeed = ((unsigned long)(recovery_done - mddev->resync_mark_cnt))/2
/((jiffies-mddev->resync_mark)/HZ +1) +1;
if (currspeed > speed_min(mddev)) {
@@ -8592,7 +8593,7 @@ static int __init md_init(void)
goto err_mdp;
mdp_major = ret;
- blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE,
+ blk_register_region(MKDEV(MD_MAJOR, 0), 512, THIS_MODULE,
md_probe, NULL, NULL);
blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE,
md_probe, NULL, NULL);
@@ -8687,7 +8688,7 @@ static __exit void md_exit(void)
struct list_head *tmp;
int delay = 1;
- blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
+ blk_unregister_region(MKDEV(MD_MAJOR,0), 512);
blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS);
unregister_blkdev(MD_MAJOR,"md");
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 407a99e46f69..cf91f5910c7c 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -685,6 +685,12 @@ static void *raid0_takeover(struct mddev *mddev)
* raid10 - assuming we have all necessary active disks
* raid1 - with (N -1) mirror drives faulty
*/
+
+ if (mddev->bitmap) {
+ printk(KERN_ERR "md/raid0: %s: cannot takeover array with bitmap\n",
+ mdname(mddev));
+ return ERR_PTR(-EBUSY);
+ }
if (mddev->level == 4)
return raid0_takeover_raid45(mddev);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 56e24c072b62..d7690f86fdb9 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1501,12 +1501,12 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
mddev->degraded++;
set_bit(Faulty, &rdev->flags);
spin_unlock_irqrestore(&conf->device_lock, flags);
- /*
- * if recovery is running, make sure it aborts.
- */
- set_bit(MD_RECOVERY_INTR, &mddev->recovery);
} else
set_bit(Faulty, &rdev->flags);
+ /*
+ * if recovery is running, make sure it aborts.
+ */
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_CHANGE_DEVS, &mddev->flags);
printk(KERN_ALERT
"md/raid1:%s: Disk failure on %s, disabling device.\n"
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index cb882aae9e20..b08c18871323 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1684,13 +1684,12 @@ static void error(struct mddev *mddev, struct md_rdev *rdev)
spin_unlock_irqrestore(&conf->device_lock, flags);
return;
}
- if (test_and_clear_bit(In_sync, &rdev->flags)) {
+ if (test_and_clear_bit(In_sync, &rdev->flags))
mddev->degraded++;
- /*
- * if recovery is running, make sure it aborts.
- */
- set_bit(MD_RECOVERY_INTR, &mddev->recovery);
- }
+ /*
+ * If recovery is running, make sure it aborts.
+ */
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(Blocked, &rdev->flags);
set_bit(Faulty, &rdev->flags);
set_bit(MD_CHANGE_DEVS, &mddev->flags);
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 1d0758aeb8e4..f60bad491eb6 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -59,6 +59,13 @@ config MEDIA_RADIO_SUPPORT
support radio reception. Disabling this option will
disable support for them.
+config MEDIA_SDR_SUPPORT
+ bool "Software defined radio support"
+ ---help---
+ Enable software defined radio support.
+
+ Say Y when you have a software defined radio device.
+
config MEDIA_RC_SUPPORT
bool "Remote Controller support"
depends on INPUT
@@ -95,7 +102,7 @@ config MEDIA_CONTROLLER
config VIDEO_DEV
tristate
depends on MEDIA_SUPPORT
- depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
+ depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
default y
config VIDEO_V4L2_SUBDEV_API
@@ -171,10 +178,11 @@ comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
config MEDIA_SUBDRV_AUTOSELECT
bool "Autoselect ancillary drivers (tuners, sensors, i2c, frontends)"
- depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
+ depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT || MEDIA_SDR_SUPPORT
depends on HAS_IOMEM
select I2C
select I2C_MUX
+ select SPI
default y
help
By default, a media driver auto-selects all possible ancillary
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c
index 34b0d0ddeef3..97afee672d07 100644
--- a/drivers/media/common/saa7146/saa7146_core.c
+++ b/drivers/media/common/saa7146/saa7146_core.c
@@ -421,23 +421,20 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
err = -ENOMEM;
/* get memory for various stuff */
- dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
- &dev->d_rps0.dma_handle);
+ dev->d_rps0.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_rps0.dma_handle);
if (!dev->d_rps0.cpu_addr)
goto err_free_irq;
- memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
- dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
- &dev->d_rps1.dma_handle);
+ dev->d_rps1.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_rps1.dma_handle);
if (!dev->d_rps1.cpu_addr)
goto err_free_rps0;
- memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
- dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
- &dev->d_i2c.dma_handle);
+ dev->d_i2c.cpu_addr = pci_zalloc_consistent(pci, SAA7146_RPS_MEM,
+ &dev->d_i2c.dma_handle);
if (!dev->d_i2c.cpu_addr)
goto err_free_rps1;
- memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
/* the rest + print status message */
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
index eda01bc68ab2..6c47f3fe9b0f 100644
--- a/drivers/media/common/saa7146/saa7146_fops.c
+++ b/drivers/media/common/saa7146/saa7146_fops.c
@@ -520,26 +520,26 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
configuration data) */
dev->ext_vv_data = ext_vv;
- vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
+ vv->d_clipping.cpu_addr =
+ pci_zalloc_consistent(dev->pci, SAA7146_CLIPPING_MEM,
+ &vv->d_clipping.dma_handle);
if( NULL == vv->d_clipping.cpu_addr ) {
ERR("out of memory. aborting.\n");
kfree(vv);
v4l2_ctrl_handler_free(hdl);
return -1;
}
- memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
saa7146_video_uops.init(dev,vv);
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.init(dev,vv);
- fmt = &vv->ov_fb.fmt;
- fmt->width = vv->standard->h_max_out;
- fmt->height = vv->standard->v_max_out;
- fmt->pixelformat = V4L2_PIX_FMT_RGB565;
- fmt->bytesperline = 2 * fmt->width;
- fmt->sizeimage = fmt->bytesperline * fmt->height;
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ vv->ov_fb.fmt.width = vv->standard->h_max_out;
+ vv->ov_fb.fmt.height = vv->standard->v_max_out;
+ vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+ vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
+ vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
+ vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
fmt = &vv->video_fmt;
fmt->width = 384;
@@ -613,7 +613,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
vfd->lock = &dev->v4l2_lock;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->tvnorms = 0;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
strlcpy(vfd->name, name, sizeof(vfd->name));
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig
index f953d33ee151..4bfbd5f463d1 100644
--- a/drivers/media/common/siano/Kconfig
+++ b/drivers/media/common/siano/Kconfig
@@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS
bool "Enable debugfs for smsdvb"
depends on SMS_SIANO_MDTV
depends on DEBUG_FS
- depends on SMS_USB_DRV
- depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV
+ depends on SMS_USB_DRV = SMS_SDIO_DRV
---help---
Choose Y to enable visualizing a dump of the frontend
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 6d7c0c858bd0..273043ea8f47 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
dev->priv = coredev;
dev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(dev, RC_BIT_ALL);
+ dev->allowed_protocols = RC_BIT_ALL;
dev->map_name = sms_get_board(board_id)->rc_codes;
dev->driver_name = MODULE_NAME;
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 11d2bea23b02..5135a096bfa6 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -244,6 +244,7 @@
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
+#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
@@ -363,6 +364,7 @@
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
#define USB_PID_SVEON_STV20_RTL2832U 0xd39d
+#define USB_PID_SVEON_STV21 0xd3b0
#define USB_PID_SVEON_STV22 0xe401
#define USB_PID_SVEON_STV22_IT9137 0xe411
#define USB_PID_AZUREWAVE_AZ6027 0x3275
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 6ce435ac866f..c2a6a0a85813 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -96,10 +96,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
*/
-#define DVB_FE_NO_EXIT 0
-#define DVB_FE_NORMAL_EXIT 1
-#define DVB_FE_DEVICE_REMOVED 2
-
static DEFINE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
@@ -113,7 +109,6 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
struct task_struct *thread;
unsigned long release_jiffies;
- unsigned int exit;
unsigned int wakeup;
fe_status_t status;
unsigned long tune_mode_flags;
@@ -565,7 +560,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- if (fepriv->exit != DVB_FE_NO_EXIT)
+ if (fe->exit != DVB_FE_NO_EXIT)
return 1;
if (fepriv->dvbdev->writers == 1)
@@ -629,7 +624,7 @@ restart:
/* got signal or quitting */
if (!down_interruptible(&fepriv->sem))
semheld = true;
- fepriv->exit = DVB_FE_NORMAL_EXIT;
+ fe->exit = DVB_FE_NORMAL_EXIT;
break;
}
@@ -739,9 +734,9 @@ restart:
fepriv->thread = NULL;
if (kthread_should_stop())
- fepriv->exit = DVB_FE_DEVICE_REMOVED;
+ fe->exit = DVB_FE_DEVICE_REMOVED;
else
- fepriv->exit = DVB_FE_NO_EXIT;
+ fe->exit = DVB_FE_NO_EXIT;
mb();
if (semheld)
@@ -756,7 +751,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s:\n", __func__);
- fepriv->exit = DVB_FE_NORMAL_EXIT;
+ if (fe->exit != DVB_FE_DEVICE_REMOVED)
+ fe->exit = DVB_FE_NORMAL_EXIT;
mb();
if (!fepriv->thread)
@@ -826,7 +822,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if (fepriv->thread) {
- if (fepriv->exit == DVB_FE_NO_EXIT)
+ if (fe->exit == DVB_FE_NO_EXIT)
return 0;
else
dvb_frontend_stop (fe);
@@ -838,7 +834,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
return -EINTR;
fepriv->state = FESTATE_IDLE;
- fepriv->exit = DVB_FE_NO_EXIT;
+ fe->exit = DVB_FE_NO_EXIT;
fepriv->thread = NULL;
mb();
@@ -1906,7 +1902,7 @@ static int dvb_frontend_ioctl(struct file *file,
if (down_interruptible(&fepriv->sem))
return -ERESTARTSYS;
- if (fepriv->exit != DVB_FE_NO_EXIT) {
+ if (fe->exit != DVB_FE_NO_EXIT) {
up(&fepriv->sem);
return -ENODEV;
}
@@ -2424,7 +2420,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
int ret;
dev_dbg(fe->dvb->device, "%s:\n", __func__);
- if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
+ if (fe->exit == DVB_FE_DEVICE_REMOVED)
return -ENODEV;
if (adapter->mfe_shared) {
@@ -2529,7 +2525,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
if (dvbdev->users == -1) {
wake_up(&fepriv->wait_queue);
- if (fepriv->exit != DVB_FE_NO_EXIT)
+ if (fe->exit != DVB_FE_NO_EXIT)
wake_up(&dvbdev->wait_queue);
if (fe->ops.ts_bus_ctrl)
fe->ops.ts_bus_ctrl(fe, 0);
@@ -2572,12 +2568,14 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
+ fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init)
ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.init)
ret = fe->ops.tuner_ops.init(fe);
+ fe->exit = DVB_FE_NO_EXIT;
fepriv->state = FESTATE_RETUNE;
dvb_frontend_wakeup(fe);
@@ -2666,20 +2664,20 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
if (fe->ops.release_sec) {
fe->ops.release_sec(fe);
- symbol_put_addr(fe->ops.release_sec);
+ dvb_detach(fe->ops.release_sec);
}
if (fe->ops.tuner_ops.release) {
fe->ops.tuner_ops.release(fe);
- symbol_put_addr(fe->ops.tuner_ops.release);
+ dvb_detach(fe->ops.tuner_ops.release);
}
if (fe->ops.analog_ops.release) {
fe->ops.analog_ops.release(fe);
- symbol_put_addr(fe->ops.analog_ops.release);
+ dvb_detach(fe->ops.analog_ops.release);
}
ptr = (void*)fe->ops.release;
if (ptr) {
fe->ops.release(fe);
- symbol_put_addr(ptr);
+ dvb_detach(ptr);
}
}
#else
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 371b6caf486c..d398de4b6ef4 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -405,6 +405,11 @@ struct dtv_frontend_properties {
struct dtv_fe_stats block_count;
};
+#define DVB_FE_NO_EXIT 0
+#define DVB_FE_NORMAL_EXIT 1
+#define DVB_FE_DEVICE_REMOVED 2
+#define DVB_FE_DEVICE_RESUME 3
+
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
@@ -418,6 +423,7 @@ struct dvb_frontend {
#define DVB_FRONTEND_COMPONENT_DEMOD 1
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
+ unsigned int exit;
};
extern int dvb_register_frontend(struct dvb_adapter *dvb,
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index 8a86b3025637..059e6117f22b 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -1276,7 +1276,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
if ((if_num = get_if(dvbnet)) < 0)
return -EINVAL;
- net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);
+ net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb",
+ NET_NAME_UNKNOWN, dvb_net_setup);
if (!net)
return -ENOMEM;
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 93a9470d3f0c..f96b28e7fc95 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -136,11 +136,15 @@ extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
__r; \
})
+#define dvb_detach(FUNC) symbol_put_addr(FUNC)
+
#else
#define dvb_attach(FUNCTION, ARGS...) ({ \
FUNCTION(ARGS); \
})
+#define dvb_detach(FUNC) {}
+
#endif
#endif /* #ifndef _DVBDEV_H_ */
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 1469d44acb22..fe0ddcca192c 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -63,6 +63,15 @@ config DVB_TDA18271C2DD
Say Y when you want to support this tuner.
+config DVB_SI2165
+ tristate "Silicon Labs si2165 based"
+ depends on DVB_CORE && I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A DVB-C/T demodulator.
+
+ Say Y when you want to support this frontend.
+
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
@@ -446,6 +455,15 @@ config DVB_RTL2832
help
Say Y when you want to support this frontend.
+config DVB_RTL2832_SDR
+ tristate "Realtek RTL2832 SDR"
+ depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT && USB
+ select DVB_RTL2832
+ select VIDEOBUF2_VMALLOC
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ Say Y when you want to support this SDR module.
+
config DVB_SI2168
tristate "Silicon Labs Si2168"
depends on DVB_CORE && I2C && I2C_MUX
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index dda0bee36f29..edf103d45920 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -5,6 +5,11 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/
+# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
+ifdef CONFIG_DVB_RTL2832_SDR
+ ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
+endif
+
stb0899-objs := stb0899_drv.o stb0899_algo.o
stv0900-objs := stv0900_core.o stv0900_sw.o
drxd-objs := drxd_firm.o drxd_hard.o
@@ -100,10 +105,12 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
obj-$(CONFIG_DVB_DRXK) += drxk.o
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_SI2165) += si2165.o
obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
+obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
obj-$(CONFIG_DVB_AF9033) += af9033.o
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
index fb504f1e9125..ecf6388d2200 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -470,7 +470,6 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
break;
default:
goto err;
- break;
}
for (i = 0; i < len; i++) {
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 23a0d05ba426..33aa9410b624 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -220,7 +220,7 @@ static void setup_vbi(struct au8522_state *state, int aud_input)
}
-static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
+static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
{
int i;
int filter_coef_type;
@@ -237,13 +237,10 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
/* Other decoder registers */
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
- if (input_mode == 0x23) {
- /* S-Video input mapping */
+ if (is_svideo)
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
- } else {
- /* All other modes (CVBS/ATVRF etc.) */
+ else
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
- }
au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
AU8522_TVDEC_PGA_REG012H_CVBS);
@@ -251,12 +248,23 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
AU8522_TVDED_DBG_MODE_REG060H_CVBS);
- au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
- au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
- AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+
+ if (state->std == V4L2_STD_PAL_M) {
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO);
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+ AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M);
+ } else {
+ /* NTSC */
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+ AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+ }
au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
@@ -275,8 +283,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
- if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
- input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+ if (is_svideo) {
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
@@ -317,8 +324,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
setup_vbi(state, 0);
- if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
- input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+ if (is_svideo) {
/* Despite what the table says, for the HVR-950q we still need
to be in CVBS mode for the S-Video input (reason unknown). */
/* filter_coef_type = 3; */
@@ -346,7 +352,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
au8522_writereg(state, AU8522_REG436H, 0x3c);
}
-static void au8522_setup_cvbs_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_mode(struct au8522_state *state, u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -358,16 +364,16 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
- setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+ setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
-static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state,
+ u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -384,24 +390,22 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
- setup_decoder_defaults(state,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+ setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
-static void au8522_setup_svideo_mode(struct au8522_state *state)
+static void au8522_setup_svideo_mode(struct au8522_state *state,
+ u8 input_mode)
{
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
/* Set input to Y on Channe1, C on Channel 3 */
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
/* PGA in automatic mode */
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
@@ -409,8 +413,7 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
- setup_decoder_defaults(state,
- AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+ setup_decoder_defaults(state, true);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
@@ -432,8 +435,9 @@ static void disable_audio_input(struct au8522_state *state)
}
/* 0=disable, 1=SIF */
-static void set_audio_input(struct au8522_state *state, int aud_input)
+static void set_audio_input(struct au8522_state *state)
{
+ int aud_input = state->aud_input;
int i;
/* Note that this function needs to be used in conjunction with setting
@@ -465,8 +469,9 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
msleep(150);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
- msleep(1);
- au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
+ msleep(10);
+ au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+ AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
msleep(50);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
@@ -539,58 +544,109 @@ static int au8522_s_register(struct v4l2_subdev *sd,
}
#endif
+static void au8522_video_set(struct au8522_state *state)
+{
+ u8 input_mode;
+
+ au8522_writereg(state, 0xa4, 1 << 5);
+
+ switch (state->vid_input) {
+ case AU8522_COMPOSITE_CH1:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH1;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH2:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH2;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH3:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH3;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH4:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_SVIDEO_CH13:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13;
+ au8522_setup_svideo_mode(state, input_mode);
+ break;
+ case AU8522_SVIDEO_CH24:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24;
+ au8522_setup_svideo_mode(state, input_mode);
+ break;
+ default:
+ case AU8522_COMPOSITE_CH4_SIF:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF;
+ au8522_setup_cvbs_tuner_mode(state, input_mode);
+ break;
+ }
+}
+
static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
{
struct au8522_state *state = to_state(sd);
if (enable) {
+ /*
+ * Clear out any state associated with the digital side of the
+ * chip, so that when it gets powered back up it won't think
+ * that it is already tuned
+ */
+ state->current_frequency = 0;
+
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
0x01);
- msleep(1);
- au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
- AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+ msleep(10);
+
+ au8522_video_set(state);
+ set_audio_input(state);
+
+ state->operational_mode = AU8522_ANALOG_MODE;
} else {
/* This does not completely power down the device
(it only reduces it from around 140ma to 80ma) */
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
1 << 5);
+ state->operational_mode = AU8522_SUSPEND_MODE;
}
return 0;
}
-static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+ u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
- state->operational_mode = AU8522_ANALOG_MODE;
-
- /* Clear out any state associated with the digital side of the
- chip, so that when it gets powered back up it won't think
- that it is already tuned */
- state->current_frequency = 0;
+ switch(input) {
+ case AU8522_COMPOSITE_CH1:
+ case AU8522_SVIDEO_CH13:
+ case AU8522_COMPOSITE_CH4_SIF:
+ state->vid_input = input;
+ break;
+ default:
+ printk(KERN_ERR "au8522 mode not currently supported\n");
+ return -EINVAL;
+ }
- au8522_writereg(state, 0xa4, 1 << 5);
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ au8522_video_set(state);
return 0;
}
-static int au8522_s_video_routing(struct v4l2_subdev *sd,
- u32 input, u32 output, u32 config)
+static int au8522_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct au8522_state *state = to_state(sd);
- au8522_reset(sd, 0);
-
- if (input == AU8522_COMPOSITE_CH1) {
- au8522_setup_cvbs_mode(state);
- } else if (input == AU8522_SVIDEO_CH13) {
- au8522_setup_svideo_mode(state);
- } else if (input == AU8522_COMPOSITE_CH4_SIF) {
- au8522_setup_cvbs_tuner_mode(state);
- } else {
- printk(KERN_ERR "au8522 mode not currently supported\n");
+ if ((std & (V4L2_STD_PAL_M | V4L2_STD_NTSC_M)) == 0)
return -EINVAL;
- }
+
+ state->std = std;
+
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ au8522_video_set(state);
+
return 0;
}
@@ -598,7 +654,12 @@ static int au8522_s_audio_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
- set_audio_input(state, input);
+
+ state->aud_input = input;
+
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ set_audio_input(state);
+
return 0;
}
@@ -629,7 +690,6 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register,
.s_register = au8522_s_register,
@@ -647,6 +707,7 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing,
.s_stream = au8522_s_stream,
+ .s_std = au8522_s_std,
};
static const struct v4l2_subdev_ops au8522_ops = {
@@ -729,6 +790,7 @@ static int au8522_probe(struct i2c_client *client,
}
state->c = client;
+ state->std = V4L2_STD_NTSC_M;
state->vid_input = AU8522_COMPOSITE_CH1;
state->aud_input = AU8522_AUDIO_NONE;
state->id = 8522;
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index aa0f16d6b610..b8aca1c84786 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -37,6 +37,7 @@
#define AU8522_ANALOG_MODE 0
#define AU8522_DIGITAL_MODE 1
+#define AU8522_SUSPEND_MODE 2
struct au8522_state {
struct i2c_client *c;
@@ -347,6 +348,7 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
/* Format control 2 */
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT 0x00
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC 0x01
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M 0x02
#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4
diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h
index 82b3d93718f8..6095dbcf7850 100644
--- a/drivers/media/dvb-frontends/cxd2820r.h
+++ b/drivers/media/dvb-frontends/cxd2820r.h
@@ -52,6 +52,12 @@ struct cxd2820r_config {
*/
u8 ts_mode;
+ /* TS clock inverted.
+ * Default: 0
+ * Values: 0, 1
+ */
+ bool ts_clock_inv;
+
/* IF AGC polarity.
* Default: 0
* Values: 0, 1
diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c
index 5c6ab4921bf1..0f4657e01cde 100644
--- a/drivers/media/dvb-frontends/cxd2820r_c.c
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -45,6 +45,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
{ 0x1008b, 0x07, 0xff },
{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
{ 0x10070, priv->cfg.ts_mode, 0xff },
+ { 0x10071, !priv->cfg.ts_clock_inv << 4, 0x10 },
};
dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c
index fa184ca2dd68..9b5a45b907bc 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -46,6 +46,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
{ 0x00088, 0x01, 0xff },
{ 0x00070, priv->cfg.ts_mode, 0xff },
+ { 0x00071, !priv->cfg.ts_clock_inv << 4, 0x10 },
{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
{ 0x000a5, 0x00, 0x01 },
{ 0x00082, 0x20, 0x60 },
diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c
index 2ba130e245b6..9c0c4f42175c 100644
--- a/drivers/media/dvb-frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb-frontends/cxd2820r_t2.c
@@ -47,6 +47,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
{ 0x02083, 0x0a, 0xff },
{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
{ 0x02070, priv->cfg.ts_mode, 0xff },
+ { 0x02071, !priv->cfg.ts_clock_inv << 6, 0x40 },
{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
{ 0x02567, 0x07, 0x0f },
{ 0x02569, 0x03, 0x03 },
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
index 3ee22ff76315..68e2af2650d3 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -2557,10 +2557,19 @@ static int dib0090_set_params(struct dvb_frontend *fe)
do {
ret = dib0090_tune(fe);
- if (ret != FE_CALLBACK_TIME_NEVER)
- msleep(ret / 10);
- else
+ if (ret == FE_CALLBACK_TIME_NEVER)
break;
+
+ /*
+ * Despite dib0090_tune returns time at a 0.1 ms range,
+ * the actual sleep time depends on CONFIG_HZ. The worse case
+ * is when CONFIG_HZ=100. In such case, the minimum granularity
+ * is 10ms. On some real field tests, the tuner sometimes don't
+ * lock when this timer is lower than 10ms. So, enforce a 10ms
+ * granularity and use usleep_range() instead of msleep().
+ */
+ ret = 10 * (ret + 99)/100;
+ usleep_range(ret * 1000, (ret + 1) * 1000);
} while (state->tune_state != CT_TUNER_STOP);
return 0;
diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c
index 148bf79236fb..dcb9a15ef0c2 100644
--- a/drivers/media/dvb-frontends/dib7000m.c
+++ b/drivers/media/dvb-frontends/dib7000m.c
@@ -1041,10 +1041,7 @@ static int dib7000m_tune(struct dvb_frontend *demod)
u16 value;
// we are already tuned - just resuming from suspend
- if (ch != NULL)
- dib7000m_set_channel(state, ch, 0);
- else
- return -EINVAL;
+ dib7000m_set_channel(state, ch, 0);
// restart demod
ret |= dib7000m_write_word(state, 898, 0x4000);
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index effb87f773b0..661760d60232 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
+#include <asm/div64.h>
#include "dvb_math.h"
#include "dvb_frontend.h"
@@ -72,6 +73,12 @@ struct dib7000p_state {
struct mutex i2c_buffer_lock;
u8 input_mode_mpeg;
+
+ /* for DVBv5 stats */
+ s64 old_ucb;
+ unsigned long per_jiffies_stats;
+ unsigned long ber_jiffies_stats;
+ unsigned long get_stats_time;
};
enum dib7000p_power_mode {
@@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
return 0;
}
-int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
+static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
{
struct dib7000p_state *state = demod->demodulator_priv;
if (value > 4095)
@@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
state->wbd_ref = value;
return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
}
-EXPORT_SYMBOL(dib7000p_set_wbd_ref);
-int dib7000p_get_agc_values(struct dvb_frontend *fe,
+static int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
struct dib7000p_state *state = fe->demodulator_priv;
@@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
return 0;
}
-EXPORT_SYMBOL(dib7000p_get_agc_values);
-int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
+static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
struct dib7000p_state *state = fe->demodulator_priv;
return dib7000p_write_word(state, 108, v);
}
-EXPORT_SYMBOL(dib7000p_set_agc1_min);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
@@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
return internal;
}
-int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
@@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config
}
return -EIO;
}
-EXPORT_SYMBOL(dib7000p_update_pll);
static int dib7000p_reset_gpio(struct dib7000p_state *st)
{
@@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
return 0;
}
-int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
+static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
{
struct dib7000p_state *state = demod->demodulator_priv;
return dib7000p_cfg_gpio(state, num, dir, val);
}
-EXPORT_SYMBOL(dib7000p_set_gpio);
static u16 dib7000p_defaults[] = {
// auto search configuration
@@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = {
0,
};
+static void dib7000p_reset_stats(struct dvb_frontend *fe);
+
static int dib7000p_demod_reset(struct dib7000p_state *state)
{
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
@@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state)
}
-u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
struct dib7000p_state *state = fe->demodulator_priv;
switch (op) {
@@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
dib7000p_set_bandwidth(state, state->current_bandwidth);
return state->timf;
}
-EXPORT_SYMBOL(dib7000p_ctrl_timf);
static void dib7000p_set_channel(struct dib7000p_state *state,
struct dtv_frontend_properties *ch, u8 seq)
@@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_frontend *demod)
dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+ dib7000p_reset_stats(demod);
+
return 0;
}
@@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
return ret;
}
+static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
+
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
{
struct dib7000p_state *state = fe->demodulator_priv;
@@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
if ((lock & 0x0038) == 0x38)
*stat |= FE_HAS_LOCK;
+ dib7000p_get_stats(fe, *stat);
+
return 0;
}
@@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength
return 0;
}
-static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
+static u32 dib7000p_get_snr(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val;
@@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
else
result -= intlog10(2) * 10 * noise_exp - 100;
+ return result;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ u32 result;
+
+ result = dib7000p_get_snr(fe);
+
*snr = result / ((1 << 24) / 10);
return 0;
}
+static void dib7000p_reset_stats(struct dvb_frontend *demod)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ u32 ucb;
+
+ memset(&c->strength, 0, sizeof(c->strength));
+ memset(&c->cnr, 0, sizeof(c->cnr));
+ memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
+ memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
+ memset(&c->block_error, 0, sizeof(c->block_error));
+
+ c->strength.len = 1;
+ c->cnr.len = 1;
+ c->block_error.len = 1;
+ c->block_count.len = 1;
+ c->post_bit_error.len = 1;
+ c->post_bit_count.len = 1;
+
+ c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+ c->strength.stat[0].uvalue = 0;
+
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ dib7000p_read_unc_blocks(demod, &ucb);
+
+ state->old_ucb = ucb;
+ state->ber_jiffies_stats = 0;
+ state->per_jiffies_stats = 0;
+}
+
+struct linear_segments {
+ unsigned x;
+ signed y;
+};
+
+/*
+ * Table to estimate signal strength in dBm.
+ * This table should be empirically determinated by measuring the signal
+ * strength generated by a RF generator directly connected into
+ * a device.
+ * This table was determinated by measuring the signal strength generated
+ * by a DTA-2111 RF generator directly connected into a dib7000p device
+ * (a Hauppauge Nova-TD stick), using a good quality 3 meters length
+ * RC6 cable and good RC6 connectors, connected directly to antenna 1.
+ * As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
+ * were used, for the lower power values.
+ * The real value can actually be on other devices, or even at the
+ * second antena input, depending on several factors, like if LNA
+ * is enabled or not, if diversity is enabled, type of connectors, etc.
+ * Yet, it is better to use this measure in dB than a random non-linear
+ * percentage value, especially for antenna adjustments.
+ * On my tests, the precision of the measure using this table is about
+ * 0.5 dB, with sounds reasonable enough to adjust antennas.
+ */
+#define DB_OFFSET 131000
+
+static struct linear_segments strength_to_db_table[] = {
+ { 63630, DB_OFFSET - 20500},
+ { 62273, DB_OFFSET - 21000},
+ { 60162, DB_OFFSET - 22000},
+ { 58730, DB_OFFSET - 23000},
+ { 58294, DB_OFFSET - 24000},
+ { 57778, DB_OFFSET - 25000},
+ { 57320, DB_OFFSET - 26000},
+ { 56779, DB_OFFSET - 27000},
+ { 56293, DB_OFFSET - 28000},
+ { 55724, DB_OFFSET - 29000},
+ { 55145, DB_OFFSET - 30000},
+ { 54680, DB_OFFSET - 31000},
+ { 54293, DB_OFFSET - 32000},
+ { 53813, DB_OFFSET - 33000},
+ { 53427, DB_OFFSET - 34000},
+ { 52981, DB_OFFSET - 35000},
+
+ { 52636, DB_OFFSET - 36000},
+ { 52014, DB_OFFSET - 37000},
+ { 51674, DB_OFFSET - 38000},
+ { 50692, DB_OFFSET - 39000},
+ { 49824, DB_OFFSET - 40000},
+ { 49052, DB_OFFSET - 41000},
+ { 48436, DB_OFFSET - 42000},
+ { 47836, DB_OFFSET - 43000},
+ { 47368, DB_OFFSET - 44000},
+ { 46468, DB_OFFSET - 45000},
+ { 45597, DB_OFFSET - 46000},
+ { 44586, DB_OFFSET - 47000},
+ { 43667, DB_OFFSET - 48000},
+ { 42673, DB_OFFSET - 49000},
+ { 41816, DB_OFFSET - 50000},
+ { 40876, DB_OFFSET - 51000},
+ { 0, 0},
+};
+
+static u32 interpolate_value(u32 value, struct linear_segments *segments,
+ unsigned len)
+{
+ u64 tmp64;
+ u32 dx;
+ s32 dy;
+ int i, ret;
+
+ if (value >= segments[0].x)
+ return segments[0].y;
+ if (value < segments[len-1].x)
+ return segments[len-1].y;
+
+ for (i = 1; i < len - 1; i++) {
+ /* If value is identical, no need to interpolate */
+ if (value == segments[i].x)
+ return segments[i].y;
+ if (value > segments[i].x)
+ break;
+ }
+
+ /* Linear interpolation between the two (x,y) points */
+ dy = segments[i - 1].y - segments[i].y;
+ dx = segments[i - 1].x - segments[i].x;
+
+ tmp64 = value - segments[i].x;
+ tmp64 *= dy;
+ do_div(tmp64, dx);
+ ret = segments[i].y + tmp64;
+
+ return ret;
+}
+
+/* FIXME: may require changes - this one was borrowed from dib8000 */
+static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
+{
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ u64 time_us, tmp64;
+ u32 tmp, denom;
+ int guard, rate_num, rate_denum = 1, bits_per_symbol;
+ int interleaving = 0, fft_div;
+
+ switch (c->guard_interval) {
+ case GUARD_INTERVAL_1_4:
+ guard = 4;
+ break;
+ case GUARD_INTERVAL_1_8:
+ guard = 8;
+ break;
+ case GUARD_INTERVAL_1_16:
+ guard = 16;
+ break;
+ default:
+ case GUARD_INTERVAL_1_32:
+ guard = 32;
+ break;
+ }
+
+ switch (c->transmission_mode) {
+ case TRANSMISSION_MODE_2K:
+ fft_div = 4;
+ break;
+ case TRANSMISSION_MODE_4K:
+ fft_div = 2;
+ break;
+ default:
+ case TRANSMISSION_MODE_8K:
+ fft_div = 1;
+ break;
+ }
+
+ switch (c->modulation) {
+ case DQPSK:
+ case QPSK:
+ bits_per_symbol = 2;
+ break;
+ case QAM_16:
+ bits_per_symbol = 4;
+ break;
+ default:
+ case QAM_64:
+ bits_per_symbol = 6;
+ break;
+ }
+
+ switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
+ case FEC_1_2:
+ rate_num = 1;
+ rate_denum = 2;
+ break;
+ case FEC_2_3:
+ rate_num = 2;
+ rate_denum = 3;
+ break;
+ case FEC_3_4:
+ rate_num = 3;
+ rate_denum = 4;
+ break;
+ case FEC_5_6:
+ rate_num = 5;
+ rate_denum = 6;
+ break;
+ default:
+ case FEC_7_8:
+ rate_num = 7;
+ rate_denum = 8;
+ break;
+ }
+
+ interleaving = interleaving;
+
+ denom = bits_per_symbol * rate_num * fft_div * 384;
+
+ /* If calculus gets wrong, wait for 1s for the next stats */
+ if (!denom)
+ return 0;
+
+ /* Estimate the period for the total bit rate */
+ time_us = rate_denum * (1008 * 1562500L);
+ tmp64 = time_us;
+ do_div(tmp64, guard);
+ time_us = time_us + tmp64;
+ time_us += denom / 2;
+ do_div(time_us, denom);
+
+ tmp = 1008 * 96 * interleaving;
+ time_us += tmp + tmp / guard;
+
+ return time_us;
+}
+
+static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ int i;
+ int show_per_stats = 0;
+ u32 time_us = 0, val, snr;
+ u64 blocks, ucb;
+ s32 db;
+ u16 strength;
+
+ /* Get Signal strength */
+ dib7000p_read_signal_strength(demod, &strength);
+ val = strength;
+ db = interpolate_value(val,
+ strength_to_db_table,
+ ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
+ c->strength.stat[0].svalue = db;
+
+ /* UCB/BER/CNR measures require lock */
+ if (!(stat & FE_HAS_LOCK)) {
+ c->cnr.len = 1;
+ c->block_count.len = 1;
+ c->block_error.len = 1;
+ c->post_bit_error.len = 1;
+ c->post_bit_count.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ return 0;
+ }
+
+ /* Check if time for stats was elapsed */
+ if (time_after(jiffies, state->per_jiffies_stats)) {
+ state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
+
+ /* Get SNR */
+ snr = dib7000p_get_snr(demod);
+ if (snr)
+ snr = (1000L * snr) >> 24;
+ else
+ snr = 0;
+ c->cnr.stat[0].svalue = snr;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
+ /* Get UCB measures */
+ dib7000p_read_unc_blocks(demod, &val);
+ ucb = val - state->old_ucb;
+ if (val < state->old_ucb)
+ ucb += 0x100000000LL;
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue = ucb;
+
+ /* Estimate the number of packets based on bitrate */
+ if (!time_us)
+ time_us = dib7000p_get_time_us(demod, -1);
+
+ if (time_us) {
+ blocks = 1250000ULL * 1000000ULL;
+ do_div(blocks, time_us * 8 * 204);
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].uvalue += blocks;
+ }
+
+ show_per_stats = 1;
+ }
+
+ /* Get post-BER measures */
+ if (time_after(jiffies, state->ber_jiffies_stats)) {
+ time_us = dib7000p_get_time_us(demod, -1);
+ state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
+
+ dprintk("Next all layers stats available in %u us.", time_us);
+
+ dib7000p_read_ber(demod, &val);
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue += val;
+
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue += 100000000;
+ }
+
+ /* Get PER measures */
+ if (show_per_stats) {
+ dib7000p_read_unc_blocks(demod, &val);
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue += val;
+
+ time_us = dib7000p_get_time_us(demod, i);
+ if (time_us) {
+ blocks = 1250000ULL * 1000000ULL;
+ do_div(blocks, time_us * 8 * 204);
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].uvalue += blocks;
+ }
+ }
+ return 0;
+}
+
static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
@@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_frontend *demod)
kfree(st);
}
-int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
u8 *tx, *rx;
struct i2c_msg msg[2] = {
@@ -1688,16 +2039,14 @@ rx_memory_error:
kfree(tx);
return ret;
}
-EXPORT_SYMBOL(dib7000pc_detection);
-struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
{
struct dib7000p_state *st = demod->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
-EXPORT_SYMBOL(dib7000p_get_i2c_master);
-int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val = dib7000p_read_word(state, 235) & 0xffef;
@@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("PID filter enabled %d", onoff);
return dib7000p_write_word(state, 235, val);
}
-EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
-int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
}
-EXPORT_SYMBOL(dib7000p_pid_filter);
-int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
struct dib7000p_state *dpst;
int k = 0;
@@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
kfree(dpst);
return 0;
}
-EXPORT_SYMBOL(dib7000p_i2c_enumeration);
static const s32 lut_1000ln_mant[] = {
6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
@@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = {
.functionality = dib7000p_i2c_func,
};
-struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib7000p_state *st = fe->demodulator_priv;
return &st->dib7090_tuner_adap;
}
-EXPORT_SYMBOL(dib7090_get_i2c_tuner);
static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
{
@@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
return ret;
}
-int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 en_cur_state;
@@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
-EXPORT_SYMBOL(dib7090_tuner_sleep);
-int dib7090_get_adc_power(struct dvb_frontend *fe)
+static int dib7090_get_adc_power(struct dvb_frontend *fe)
{
return dib7000p_get_adc_power(fe);
}
-EXPORT_SYMBOL(dib7090_get_adc_power);
-int dib7090_slave_reset(struct dvb_frontend *fe)
+static int dib7090_slave_reset(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg;
@@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe)
dib7000p_write_word(state, 1032, 0xffff);
return 0;
}
-EXPORT_SYMBOL(dib7090_slave_reset);
static struct dvb_frontend_ops dib7000p_ops;
-struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
struct dvb_frontend *demod;
struct dib7000p_state *st;
@@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
dib7000p_demod_reset(st);
+ dib7000p_reset_stats(demod);
+
if (st->version == SOC7090) {
dib7090_set_output_mode(demod, st->cfg.output_mode);
dib7090_set_diversity_in(demod, 0);
@@ -2434,6 +2778,31 @@ error:
kfree(st);
return NULL;
}
+
+void *dib7000p_attach(struct dib7000p_ops *ops)
+{
+ if (!ops)
+ return NULL;
+
+ ops->slave_reset = dib7090_slave_reset;
+ ops->get_adc_power = dib7090_get_adc_power;
+ ops->dib7000pc_detection = dib7000pc_detection;
+ ops->get_i2c_tuner = dib7090_get_i2c_tuner;
+ ops->tuner_sleep = dib7090_tuner_sleep;
+ ops->init = dib7000p_init;
+ ops->set_agc1_min = dib7000p_set_agc1_min;
+ ops->set_gpio = dib7000p_set_gpio;
+ ops->i2c_enumeration = dib7000p_i2c_enumeration;
+ ops->pid_filter = dib7000p_pid_filter;
+ ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
+ ops->get_i2c_master = dib7000p_get_i2c_master;
+ ops->update_pll = dib7000p_update_pll;
+ ops->ctrl_timf = dib7000p_ctrl_timf;
+ ops->get_agc_values = dib7000p_get_agc_values;
+ ops->set_wbd_ref = dib7000p_set_wbd_ref;
+
+ return ops;
+}
EXPORT_SYMBOL(dib7000p_attach);
static struct dvb_frontend_ops dib7000p_ops = {
diff --git a/drivers/media/dvb-frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h
index d08cdff59bdf..1fea0e972654 100644
--- a/drivers/media/dvb-frontends/dib7000p.h
+++ b/drivers/media/dvb-frontends/dib7000p.h
@@ -46,121 +46,34 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-#if IS_ENABLED(CONFIG_DVB_DIB7000P)
-extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
-extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
-extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
-extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib7090_get_adc_power(struct dvb_frontend *fe);
-extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib7090_slave_reset(struct dvb_frontend *fe);
-extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+struct dib7000p_ops {
+ int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
+ int (*get_agc_values)(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
-extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
-#else
-static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-
-static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
+ int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
+ int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
+ int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
+ u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
+ int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
+ struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
+ int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+ int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+ int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+ struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+ int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+ int (*get_adc_power)(struct dvb_frontend *fe);
+ int (*slave_reset)(struct dvb_frontend *fe);
+ struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+};
-static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+#if IS_ENABLED(CONFIG_DVB_DIB7000P)
+void *dib7000p_attach(struct dib7000p_ops *ops);
+#else
+static inline void *dib7000p_attach(struct dib7000p_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-
-static inline int dib7090_slave_reset(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
- u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
#endif
#endif
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 1632d78a5479..61e31f2d2f71 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -115,7 +115,7 @@ struct dib8000_state {
u16 found_guard;
u8 subchannel;
u8 symbol_duration;
- u32 timeout;
+ unsigned long timeout;
u8 longest_intlv_layer;
u16 output_mode;
@@ -588,8 +588,8 @@ static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_s
break;
case DIBX000_ADC_OFF: // leave the VBG voltage on
- reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
- reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+ reg_907 = (1 << 13) | (1 << 12);
+ reg_908 = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1);
break;
case DIBX000_VBG_ENABLE:
@@ -656,7 +656,7 @@ static int dib8000_sad_calib(struct dib8000_state *state)
return 0;
}
-int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
struct dib8000_state *state = fe->demodulator_priv;
if (value > 4095)
@@ -664,7 +664,6 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
state->wbd_ref = value;
return dib8000_write_word(state, 106, value);
}
-EXPORT_SYMBOL(dib8000_set_wbd_ref);
static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
{
@@ -739,7 +738,7 @@ static void dib8000_reset_pll(struct dib8000_state *state)
dib8000_reset_pll_common(state, pll);
}
-int dib8000_update_pll(struct dvb_frontend *fe,
+static int dib8000_update_pll(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -815,8 +814,6 @@ int dib8000_update_pll(struct dvb_frontend *fe,
return 0;
}
-EXPORT_SYMBOL(dib8000_update_pll);
-
static int dib8000_reset_gpio(struct dib8000_state *st)
{
@@ -849,13 +846,12 @@ static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
return 0;
}
-int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
struct dib8000_state *state = fe->demodulator_priv;
return dib8000_cfg_gpio(state, num, dir, val);
}
-EXPORT_SYMBOL(dib8000_set_gpio);
static const u16 dib8000_defaults[] = {
/* auto search configuration - lock0 by default waiting
* for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
@@ -1054,6 +1050,7 @@ static int dib8000_reset(struct dvb_frontend *fe)
dib8000_write_word(state, 770, 0xffff);
dib8000_write_word(state, 771, 0xffff);
dib8000_write_word(state, 772, 0xfffc);
+ dib8000_write_word(state, 898, 0x000c); /* restart sad */
if (state->revision == 0x8090)
dib8000_write_word(state, 1280, 0x0045);
else
@@ -1228,20 +1225,19 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
return 0;
}
-void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+static void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
dib8000_set_adc_state(state, DIBX000_ADC_ON);
dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
}
-EXPORT_SYMBOL(dib8000_pwm_agc_reset);
static int dib8000_agc_soft_split(struct dib8000_state *state)
{
u16 agc, split_offset;
if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
- return FE_CALLBACK_TIME_NEVER;
+ return 0;
// n_agc_global
agc = dib8000_read_word(state, 390);
@@ -1881,14 +1877,13 @@ static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
.functionality = dib8096p_i2c_func,
};
-struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib8000_state *st = fe->demodulator_priv;
return &st->dib8096p_tuner_adap;
}
-EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
-int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 en_cur_state;
@@ -1912,14 +1907,13 @@ int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
-EXPORT_SYMBOL(dib8096p_tuner_sleep);
static const s32 lut_1000ln_mant[] =
{
908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
};
-s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+static s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
struct dib8000_state *state = fe->demodulator_priv;
u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
@@ -1937,9 +1931,8 @@ s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
}
return val;
}
-EXPORT_SYMBOL(dib8000_get_adc_power);
-int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+static int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
{
struct dib8000_state *state = fe->demodulator_priv;
int val = 0;
@@ -1957,7 +1950,6 @@ int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
return val;
}
-EXPORT_SYMBOL(dib8090p_get_dc_power);
static void dib8000_update_timf(struct dib8000_state *state)
{
@@ -1968,7 +1960,7 @@ static void dib8000_update_timf(struct dib8000_state *state)
dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
}
-u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+static u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -1986,21 +1978,11 @@ u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
return state->timf;
}
-EXPORT_SYMBOL(dib8000_ctrl_timf);
static const u16 adc_target_16dB[11] = {
- (1 << 13) - 825 - 117,
- (1 << 13) - 837 - 117,
- (1 << 13) - 811 - 117,
- (1 << 13) - 766 - 117,
- (1 << 13) - 737 - 117,
- (1 << 13) - 693 - 117,
- (1 << 13) - 648 - 117,
- (1 << 13) - 619 - 117,
- (1 << 13) - 575 - 117,
- (1 << 13) - 531 - 117,
- (1 << 13) - 501 - 117
+ 7250, 7238, 7264, 7309, 7338, 7382, 7427, 7456, 7500, 7544, 7574
};
+
static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
@@ -2043,9 +2025,8 @@ static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 ma
break;
}
- if ((c->layer[layer_index].interleaving > 0) && ((c->layer[layer_index].interleaving <= 3) || (c->layer[layer_index].interleaving == 4 && c->isdbt_sb_mode == 1)))
- time_intlv = c->layer[layer_index].interleaving;
- else
+ time_intlv = fls(c->layer[layer_index].interleaving);
+ if (time_intlv > 3 && !(time_intlv == 4 && c->isdbt_sb_mode == 1))
time_intlv = 0;
dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
@@ -2362,6 +2343,9 @@ static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq
int init_prbs;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+ if (autosearching)
+ c->isdbt_partial_reception = 1;
+
/* P_mode */
dib8000_write_word(state, 10, (seq << 4));
@@ -2856,12 +2840,12 @@ static void dib8000_set_sync_wait(struct dib8000_state *state)
dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
}
-static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
+static unsigned long dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
{
if (mode == SYMBOL_DEPENDENT_ON)
- return systime() + (delay * state->symbol_duration);
- else
- return systime() + delay;
+ delay *= state->symbol_duration;
+
+ return jiffies + usecs_to_jiffies(delay * 100);
}
static s32 dib8000_get_status(struct dvb_frontend *fe)
@@ -2870,21 +2854,19 @@ static s32 dib8000_get_status(struct dvb_frontend *fe)
return state->status;
}
-enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+static enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
return state->tune_state;
}
-EXPORT_SYMBOL(dib8000_get_tune_state);
-int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+static int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
struct dib8000_state *state = fe->demodulator_priv;
state->tune_state = tune_state;
return 0;
}
-EXPORT_SYMBOL(dib8000_set_tune_state);
static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
{
@@ -3015,8 +2997,8 @@ static int dib8000_tune(struct dvb_frontend *fe)
u16 locks, deeper_interleaver = 0, i;
int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
- u32 *timeout = &state->timeout;
- u32 now = systime();
+ unsigned long *timeout = &state->timeout;
+ unsigned long now = jiffies;
#ifdef DIB8000_AGC_FREEZE
u16 agc1, agc2;
#endif
@@ -3026,318 +3008,327 @@ static int dib8000_tune(struct dvb_frontend *fe)
#if 0
if (*tune_state < CT_DEMOD_STOP)
- dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
+ dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu",
+ state->channel_parameters_set, *tune_state, state->autosearch_state, now);
#endif
switch (*tune_state) {
case CT_DEMOD_START: /* 30 */
- dib8000_reset_stats(fe);
+ dib8000_reset_stats(fe);
- if (state->revision == 0x8090)
- dib8090p_init_sdram(state);
- state->status = FE_STATUS_TUNE_PENDING;
- state->channel_parameters_set = is_manual_mode(c);
+ if (state->revision == 0x8090)
+ dib8090p_init_sdram(state);
+ state->status = FE_STATUS_TUNE_PENDING;
+ state->channel_parameters_set = is_manual_mode(c);
- dprintk("Tuning channel on %s search mode",
- state->channel_parameters_set ? "manual" : "auto");
+ dprintk("Tuning channel on %s search mode",
+ state->channel_parameters_set ? "manual" : "auto");
- dib8000_viterbi_state(state, 0); /* force chan dec in restart */
+ dib8000_viterbi_state(state, 0); /* force chan dec in restart */
- /* Layer monitor */
- dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
+ /* Layer monitor */
+ dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
- dib8000_set_frequency_offset(state);
- dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
+ dib8000_set_frequency_offset(state);
+ dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
- if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
+ if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
#ifdef DIB8000_AGC_FREEZE
- if (state->revision != 0x8090) {
- state->agc1_max = dib8000_read_word(state, 108);
- state->agc1_min = dib8000_read_word(state, 109);
- state->agc2_max = dib8000_read_word(state, 110);
- state->agc2_min = dib8000_read_word(state, 111);
- agc1 = dib8000_read_word(state, 388);
- agc2 = dib8000_read_word(state, 389);
- dib8000_write_word(state, 108, agc1);
- dib8000_write_word(state, 109, agc1);
- dib8000_write_word(state, 110, agc2);
- dib8000_write_word(state, 111, agc2);
- }
-#endif
- state->autosearch_state = AS_SEARCHING_FFT;
- state->found_nfft = TRANSMISSION_MODE_AUTO;
- state->found_guard = GUARD_INTERVAL_AUTO;
- *tune_state = CT_DEMOD_SEARCH_NEXT;
- } else { /* we already know the channel struct so TUNE only ! */
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STEP_3;
+ if (state->revision != 0x8090) {
+ state->agc1_max = dib8000_read_word(state, 108);
+ state->agc1_min = dib8000_read_word(state, 109);
+ state->agc2_max = dib8000_read_word(state, 110);
+ state->agc2_min = dib8000_read_word(state, 111);
+ agc1 = dib8000_read_word(state, 388);
+ agc2 = dib8000_read_word(state, 389);
+ dib8000_write_word(state, 108, agc1);
+ dib8000_write_word(state, 109, agc1);
+ dib8000_write_word(state, 110, agc2);
+ dib8000_write_word(state, 111, agc2);
}
- state->symbol_duration = dib8000_get_symbol_duration(state);
- break;
+#endif
+ state->autosearch_state = AS_SEARCHING_FFT;
+ state->found_nfft = TRANSMISSION_MODE_AUTO;
+ state->found_guard = GUARD_INTERVAL_AUTO;
+ *tune_state = CT_DEMOD_SEARCH_NEXT;
+ } else { /* we already know the channel struct so TUNE only ! */
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STEP_3;
+ }
+ state->symbol_duration = dib8000_get_symbol_duration(state);
+ break;
case CT_DEMOD_SEARCH_NEXT: /* 51 */
- dib8000_autosearch_start(fe);
- if (state->revision == 0x8090)
- ret = 50;
- else
- ret = 15;
- *tune_state = CT_DEMOD_STEP_1;
- break;
+ dib8000_autosearch_start(fe);
+ if (state->revision == 0x8090)
+ ret = 50;
+ else
+ ret = 15;
+ *tune_state = CT_DEMOD_STEP_1;
+ break;
case CT_DEMOD_STEP_1: /* 31 */
- switch (dib8000_autosearch_irq(fe)) {
- case 1: /* fail */
- state->status = FE_STATUS_TUNE_FAILED;
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STOP; /* else we are done here */
- break;
- case 2: /* Succes */
- state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
- *tune_state = CT_DEMOD_STEP_3;
- if (state->autosearch_state == AS_SEARCHING_GUARD)
- *tune_state = CT_DEMOD_STEP_2;
- else
- state->autosearch_state = AS_DONE;
- break;
- case 3: /* Autosearch FFT max correlation endded */
- *tune_state = CT_DEMOD_STEP_2;
- break;
- }
+ switch (dib8000_autosearch_irq(fe)) {
+ case 1: /* fail */
+ state->status = FE_STATUS_TUNE_FAILED;
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STOP; /* else we are done here */
+ break;
+ case 2: /* Succes */
+ state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
+ *tune_state = CT_DEMOD_STEP_3;
+ if (state->autosearch_state == AS_SEARCHING_GUARD)
+ *tune_state = CT_DEMOD_STEP_2;
+ else
+ state->autosearch_state = AS_DONE;
break;
+ case 3: /* Autosearch FFT max correlation endded */
+ *tune_state = CT_DEMOD_STEP_2;
+ break;
+ }
+ break;
case CT_DEMOD_STEP_2:
- switch (state->autosearch_state) {
- case AS_SEARCHING_FFT:
- /* searching for the correct FFT */
- if (state->revision == 0x8090) {
- corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
- corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
- corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
- } else {
- corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
- corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
- corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
- }
- /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
+ switch (state->autosearch_state) {
+ case AS_SEARCHING_FFT:
+ /* searching for the correct FFT */
+ if (state->revision == 0x8090) {
+ corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+ corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+ corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
+ } else {
+ corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
+ corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+ corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+ }
+ /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
- max_value = 0;
- for (find_index = 1 ; find_index < 3 ; find_index++) {
- if (corm[max_value] < corm[find_index])
- max_value = find_index ;
- }
+ max_value = 0;
+ for (find_index = 1 ; find_index < 3 ; find_index++) {
+ if (corm[max_value] < corm[find_index])
+ max_value = find_index ;
+ }
- switch (max_value) {
- case 0:
- state->found_nfft = TRANSMISSION_MODE_2K;
- break;
- case 1:
- state->found_nfft = TRANSMISSION_MODE_4K;
- break;
- case 2:
- default:
- state->found_nfft = TRANSMISSION_MODE_8K;
- break;
- }
- /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
-
- *tune_state = CT_DEMOD_SEARCH_NEXT;
- state->autosearch_state = AS_SEARCHING_GUARD;
- if (state->revision == 0x8090)
- ret = 50;
- else
- ret = 10;
- break;
- case AS_SEARCHING_GUARD:
- /* searching for the correct guard interval */
- if (state->revision == 0x8090)
- state->found_guard = dib8000_read_word(state, 572) & 0x3;
- else
- state->found_guard = dib8000_read_word(state, 570) & 0x3;
- /* dprintk("guard interval found=%i", state->found_guard); */
-
- *tune_state = CT_DEMOD_STEP_3;
- break;
+ switch (max_value) {
+ case 0:
+ state->found_nfft = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ state->found_nfft = TRANSMISSION_MODE_4K;
+ break;
+ case 2:
default:
- /* the demod should never be in this state */
- state->status = FE_STATUS_TUNE_FAILED;
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STOP; /* else we are done here */
- break;
+ state->found_nfft = TRANSMISSION_MODE_8K;
+ break;
}
+ /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+
+ *tune_state = CT_DEMOD_SEARCH_NEXT;
+ state->autosearch_state = AS_SEARCHING_GUARD;
+ if (state->revision == 0x8090)
+ ret = 50;
+ else
+ ret = 10;
break;
+ case AS_SEARCHING_GUARD:
+ /* searching for the correct guard interval */
+ if (state->revision == 0x8090)
+ state->found_guard = dib8000_read_word(state, 572) & 0x3;
+ else
+ state->found_guard = dib8000_read_word(state, 570) & 0x3;
+ /* dprintk("guard interval found=%i", state->found_guard); */
- case CT_DEMOD_STEP_3: /* 33 */
- state->symbol_duration = dib8000_get_symbol_duration(state);
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
- dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
- *tune_state = CT_DEMOD_STEP_4;
+ *tune_state = CT_DEMOD_STEP_3;
break;
+ default:
+ /* the demod should never be in this state */
+ state->status = FE_STATUS_TUNE_FAILED;
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STOP; /* else we are done here */
+ break;
+ }
+ break;
+
+ case CT_DEMOD_STEP_3: /* 33 */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
+ dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
+ *tune_state = CT_DEMOD_STEP_4;
+ break;
case CT_DEMOD_STEP_4: /* (34) */
- dib8000_demod_restart(state);
+ dib8000_demod_restart(state);
- dib8000_set_sync_wait(state);
- dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+ dib8000_set_sync_wait(state);
+ dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
- locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
- /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
- *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
- *tune_state = CT_DEMOD_STEP_5;
- break;
+ locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
+ /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
+ *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
+ *tune_state = CT_DEMOD_STEP_5;
+ break;
case CT_DEMOD_STEP_5: /* (35) */
- locks = dib8000_read_lock(fe);
- if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
- dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
- if (!state->differential_constellation) {
- /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
- *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
- *tune_state = CT_DEMOD_STEP_7;
- } else {
- *tune_state = CT_DEMOD_STEP_8;
- }
- } else if (now > *timeout) {
- *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ locks = dib8000_read_lock(fe);
+ if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
+ dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
+ if (!state->differential_constellation) {
+ /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
+ *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
+ *tune_state = CT_DEMOD_STEP_7;
+ } else {
+ *tune_state = CT_DEMOD_STEP_8;
}
- break;
+ } else if (time_after(now, *timeout)) {
+ *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ }
+ break;
case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
- if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
- /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
- if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
- *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
- else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
- *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
- dib8000_viterbi_state(state, 1); /* start viterbi chandec */
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
- state->status = FE_STATUS_TUNE_FAILED;
- }
- } else {
+ if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
+ /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
+ if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
+ *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
+ else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
+ *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
dib8000_viterbi_state(state, 1); /* start viterbi chandec */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
- *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
state->status = FE_STATUS_TUNE_FAILED;
}
- break;
+ } else {
+ dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+ *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
+ state->status = FE_STATUS_TUNE_FAILED;
+ }
+ break;
case CT_DEMOD_STEP_7: /* 37 */
- locks = dib8000_read_lock(fe);
- if (locks & (1<<10)) { /* lmod4_lock */
- ret = 14; /* wait for 14 symbols */
- *tune_state = CT_DEMOD_STEP_8;
- } else if (now > *timeout)
- *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
- break;
+ locks = dib8000_read_lock(fe);
+ if (locks & (1<<10)) { /* lmod4_lock */
+ ret = 14; /* wait for 14 symbols */
+ *tune_state = CT_DEMOD_STEP_8;
+ } else if (time_after(now, *timeout))
+ *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ break;
case CT_DEMOD_STEP_8: /* 38 */
- dib8000_viterbi_state(state, 1); /* start viterbi chandec */
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
-
- /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation) {
- state->subchannel = 0;
- *tune_state = CT_DEMOD_STEP_11;
- } else {
- *tune_state = CT_DEMOD_STEP_9;
- state->status = FE_STATUS_LOCKED;
- }
- break;
+ dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+
+ /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation) {
+ state->subchannel = 0;
+ *tune_state = CT_DEMOD_STEP_11;
+ } else {
+ *tune_state = CT_DEMOD_STEP_9;
+ state->status = FE_STATUS_LOCKED;
+ }
+ break;
case CT_DEMOD_STEP_9: /* 39 */
- if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
- /* defines timeout for mpeg lock depending on interleaver length of longest layer */
- for (i = 0; i < 3; i++) {
- if (c->layer[i].interleaving >= deeper_interleaver) {
- dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
- if (c->layer[i].segment_count > 0) { /* valid layer */
- deeper_interleaver = c->layer[0].interleaving;
- state->longest_intlv_layer = i;
- }
+ if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
+ /* defines timeout for mpeg lock depending on interleaver length of longest layer */
+ for (i = 0; i < 3; i++) {
+ if (c->layer[i].interleaving >= deeper_interleaver) {
+ dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
+ if (c->layer[i].segment_count > 0) { /* valid layer */
+ deeper_interleaver = c->layer[0].interleaving;
+ state->longest_intlv_layer = i;
}
}
+ }
- if (deeper_interleaver == 0)
- locks = 2; /* locks is the tmp local variable name */
- else if (deeper_interleaver == 3)
- locks = 8;
- else
- locks = 2 * deeper_interleaver;
+ if (deeper_interleaver == 0)
+ locks = 2; /* locks is the tmp local variable name */
+ else if (deeper_interleaver == 3)
+ locks = 8;
+ else
+ locks = 2 * deeper_interleaver;
- if (state->diversity_onoff != 0) /* because of diversity sync */
- locks *= 2;
+ if (state->diversity_onoff != 0) /* because of diversity sync */
+ locks *= 2;
- *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */
- dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
+ *timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */
+ dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld",
+ deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
- *tune_state = CT_DEMOD_STEP_10;
- } else
- *tune_state = CT_DEMOD_STOP;
- break;
+ *tune_state = CT_DEMOD_STEP_10;
+ } else
+ *tune_state = CT_DEMOD_STOP;
+ break;
case CT_DEMOD_STEP_10: /* 40 */
- locks = dib8000_read_lock(fe);
- if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
- dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation)
- /* signal to the upper layer, that there was a channel found and the parameters can be read */
- state->status = FE_STATUS_DEMOD_SUCCESS;
- else
+ locks = dib8000_read_lock(fe);
+ if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
+ dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s",
+ c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation)
+ /* signal to the upper layer, that there was a channel found and the parameters can be read */
+ state->status = FE_STATUS_DEMOD_SUCCESS;
+ else
+ state->status = FE_STATUS_DATA_LOCKED;
+ *tune_state = CT_DEMOD_STOP;
+ } else if (time_after(now, *timeout)) {
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation) { /* continue to try init prbs autosearch */
+ state->subchannel += 3;
+ *tune_state = CT_DEMOD_STEP_11;
+ } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
+ if (locks & (0x7 << 5)) {
+ dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s",
+ jiffies_to_msecs(now - *timeout),
+ c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
+
state->status = FE_STATUS_DATA_LOCKED;
+ } else
+ state->status = FE_STATUS_TUNE_FAILED;
*tune_state = CT_DEMOD_STOP;
- } else if (now > *timeout) {
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation) { /* continue to try init prbs autosearch */
- state->subchannel += 3;
- *tune_state = CT_DEMOD_STEP_11;
- } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
- if (locks & (0x7<<5)) {
- dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
- state->status = FE_STATUS_DATA_LOCKED;
- } else
- state->status = FE_STATUS_TUNE_FAILED;
- *tune_state = CT_DEMOD_STOP;
- }
}
- break;
+ }
+ break;
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
- if (state->subchannel <= 41) {
- dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
- *tune_state = CT_DEMOD_STEP_9;
- } else {
- *tune_state = CT_DEMOD_STOP;
- state->status = FE_STATUS_TUNE_FAILED;
- }
- break;
+ if (state->subchannel <= 41) {
+ dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+ *tune_state = CT_DEMOD_STEP_9;
+ } else {
+ *tune_state = CT_DEMOD_STOP;
+ state->status = FE_STATUS_TUNE_FAILED;
+ }
+ break;
default:
- break;
+ break;
}
/* tuning is finished - cleanup the demod */
switch (*tune_state) {
case CT_DEMOD_STOP: /* (42) */
#ifdef DIB8000_AGC_FREEZE
- if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
- dib8000_write_word(state, 108, state->agc1_max);
- dib8000_write_word(state, 109, state->agc1_min);
- dib8000_write_word(state, 110, state->agc2_max);
- dib8000_write_word(state, 111, state->agc2_min);
- state->agc1_max = 0;
- state->agc1_min = 0;
- state->agc2_max = 0;
- state->agc2_min = 0;
- }
+ if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
+ dib8000_write_word(state, 108, state->agc1_max);
+ dib8000_write_word(state, 109, state->agc1_min);
+ dib8000_write_word(state, 110, state->agc2_max);
+ dib8000_write_word(state, 111, state->agc2_min);
+ state->agc1_max = 0;
+ state->agc1_min = 0;
+ state->agc2_max = 0;
+ state->agc2_min = 0;
+ }
#endif
- ret = FE_CALLBACK_TIME_NEVER;
- break;
+ ret = 0;
+ break;
default:
- break;
+ break;
}
if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
@@ -3408,7 +3399,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
if (!(stat & FE_HAS_SYNC))
return 0;
- dprintk("TMCC lock");
+ dprintk("dib8000_get_frontend: TMCC lock");
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
if (stat&FE_HAS_SYNC) {
@@ -3444,91 +3435,117 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
switch ((val & 0x30) >> 4) {
case 1:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+ dprintk("dib8000_get_frontend: transmission mode 2K");
+ break;
+ case 2:
+ fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
+ dprintk("dib8000_get_frontend: transmission mode 4K");
break;
case 3:
default:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+ dprintk("dib8000_get_frontend: transmission mode 8K");
break;
}
switch (val & 0x3) {
case 0:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
- dprintk("dib8000_get_frontend GI = 1/32 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/32 ");
break;
case 1:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
- dprintk("dib8000_get_frontend GI = 1/16 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/16 ");
break;
case 2:
- dprintk("dib8000_get_frontend GI = 1/8 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/8 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- dprintk("dib8000_get_frontend GI = 1/4 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/4 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
break;
}
val = dib8000_read_word(state, 505);
fe->dtv_property_cache.isdbt_partial_reception = val & 1;
- dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
+ dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
for (i = 0; i < 3; i++) {
- val = dib8000_read_word(state, 493 + i);
- fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
- dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
+ int show;
+
+ val = dib8000_read_word(state, 493 + i) & 0x0f;
+ fe->dtv_property_cache.layer[i].segment_count = val;
+
+ if (val == 0 || val > 13)
+ show = 0;
+ else
+ show = 1;
+
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d segments = %d ",
+ i, fe->dtv_property_cache.layer[i].segment_count);
val = dib8000_read_word(state, 499 + i) & 0x3;
/* Interleaving can be 0, 1, 2 or 4 */
if (val == 3)
val = 4;
fe->dtv_property_cache.layer[i].interleaving = val;
- dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ",
- i, fe->dtv_property_cache.layer[i].interleaving);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ",
+ i, fe->dtv_property_cache.layer[i].interleaving);
val = dib8000_read_word(state, 481 + i);
switch (val & 0x7) {
case 1:
fe->dtv_property_cache.layer[i].fec = FEC_1_2;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].fec = FEC_2_3;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i);
break;
case 3:
fe->dtv_property_cache.layer[i].fec = FEC_3_4;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i);
break;
case 5:
fe->dtv_property_cache.layer[i].fec = FEC_5_6;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i);
break;
default:
fe->dtv_property_cache.layer[i].fec = FEC_7_8;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i);
break;
}
val = dib8000_read_word(state, 487 + i);
switch (val & 0x3) {
case 0:
- dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
fe->dtv_property_cache.layer[i].modulation = DQPSK;
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d DQPSK ", i);
break;
case 1:
fe->dtv_property_cache.layer[i].modulation = QPSK;
- dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QPSK ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].modulation = QAM_16;
- dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QAM16 ", i);
break;
case 3:
default:
- dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
fe->dtv_property_cache.layer[i].modulation = QAM_64;
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QAM64 ", i);
break;
}
}
@@ -3554,9 +3571,9 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
- int l, i, active, time, time_slave = FE_CALLBACK_TIME_NEVER;
+ int l, i, active, time, time_slave = 0;
u8 exit_condition, index_frontend;
- u32 delay, callback_time;
+ unsigned long delay, callback_time;
if (c->frequency == 0) {
dprintk("dib8000: must at least specify frequency ");
@@ -3608,15 +3625,24 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
time = dib8000_agc_startup(state->fe[0]);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
time_slave = dib8000_agc_startup(state->fe[index_frontend]);
- if (time == FE_CALLBACK_TIME_NEVER)
+ if (time == 0)
time = time_slave;
- else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
+ else if ((time_slave != 0) && (time_slave > time))
time = time_slave;
}
- if (time != FE_CALLBACK_TIME_NEVER)
- msleep(time / 10);
- else
+ if (time == 0)
break;
+
+ /*
+ * Despite dib8000_agc_startup returns time at a 0.1 ms range,
+ * the actual sleep time depends on CONFIG_HZ. The worse case
+ * is when CONFIG_HZ=100. In such case, the minimum granularity
+ * is 10ms. On some real field tests, the tuner sometimes don't
+ * lock when this timer is lower than 10ms. So, enforce a 10ms
+ * granularity.
+ */
+ time = 10 * (time + 99)/100;
+ usleep_range(time * 1000, (time + 1) * 1000);
exit_condition = 1;
for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
@@ -3631,11 +3657,14 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
active = 1;
do {
- callback_time = FE_CALLBACK_TIME_NEVER;
+ callback_time = 0;
for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
delay = dib8000_tune(state->fe[index_frontend]);
- if (delay != FE_CALLBACK_TIME_NEVER)
- delay += systime();
+ if (delay != 0) {
+ delay = jiffies + usecs_to_jiffies(100 * delay);
+ if (!callback_time || delay < callback_time)
+ callback_time = delay;
+ }
/* we are in autosearch */
if (state->channel_parameters_set == 0) { /* searching */
@@ -3646,6 +3675,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
if (l != index_frontend) { /* and for all frontend except the successful one */
+ dprintk("Restarting frontend %d\n", l);
dib8000_tune_restart_from_demod(state->fe[l]);
state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@@ -3664,8 +3694,6 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
}
}
}
- if (delay < callback_time)
- callback_time = delay;
}
/* tuning is done when the master frontend is done (failed or success) */
if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
@@ -3681,12 +3709,12 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
}
- if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
+ if ((active == 1) && (callback_time == 0)) {
dprintk("strange callback time something went wrong");
active = 0;
}
- while ((active == 1) && (systime() < callback_time))
+ while ((active == 1) && (time_before(jiffies, callback_time)))
msleep(100);
} while (active);
@@ -4201,7 +4229,7 @@ static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
return 0;
}
-int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+static int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
{
struct dib8000_state *state = fe->demodulator_priv;
u8 index_frontend = 1;
@@ -4217,9 +4245,8 @@ int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_
dprintk("too many slave frontend");
return -ENOMEM;
}
-EXPORT_SYMBOL(dib8000_set_slave_frontend);
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+static int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
u8 index_frontend = 1;
@@ -4235,9 +4262,8 @@ int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
dprintk("no frontend to be removed");
return -ENODEV;
}
-EXPORT_SYMBOL(dib8000_remove_slave_frontend);
-struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -4245,10 +4271,8 @@ struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int sla
return NULL;
return state->fe[slave_index];
}
-EXPORT_SYMBOL(dib8000_get_slave_frontend);
-
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p)
{
int k = 0, ret = 0;
@@ -4325,7 +4349,6 @@ error_memory_read:
return ret;
}
-EXPORT_SYMBOL(dib8000_i2c_enumeration);
static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
@@ -4348,15 +4371,13 @@ static void dib8000_release(struct dvb_frontend *fe)
kfree(st);
}
-struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
{
struct dib8000_state *st = fe->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
-EXPORT_SYMBOL(dib8000_get_i2c_master);
-
-int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib8000_state *st = fe->demodulator_priv;
u16 val = dib8000_read_word(st, 299) & 0xffef;
@@ -4365,15 +4386,13 @@ int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("pid filter enabled %d", onoff);
return dib8000_write_word(st, 299, val);
}
-EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
-int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+static int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib8000_state *st = fe->demodulator_priv;
dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
}
-EXPORT_SYMBOL(dib8000_pid_filter);
static const struct dvb_frontend_ops dib8000_ops = {
.delsys = { SYS_ISDBT },
@@ -4405,12 +4424,12 @@ static const struct dvb_frontend_ops dib8000_ops = {
.read_ucblocks = dib8000_read_unc_blocks,
};
-struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
+static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
{
struct dvb_frontend *fe;
struct dib8000_state *state;
- dprintk("dib8000_attach");
+ dprintk("dib8000_init");
state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
if (state == NULL)
@@ -4467,6 +4486,33 @@ error:
return NULL;
}
+void *dib8000_attach(struct dib8000_ops *ops)
+{
+ if (!ops)
+ return NULL;
+
+ ops->pwm_agc_reset = dib8000_pwm_agc_reset;
+ ops->get_dc_power = dib8090p_get_dc_power;
+ ops->set_gpio = dib8000_set_gpio;
+ ops->get_slave_frontend = dib8000_get_slave_frontend;
+ ops->set_tune_state = dib8000_set_tune_state;
+ ops->pid_filter_ctrl = dib8000_pid_filter_ctrl;
+ ops->remove_slave_frontend = dib8000_remove_slave_frontend;
+ ops->get_adc_power = dib8000_get_adc_power;
+ ops->update_pll = dib8000_update_pll;
+ ops->tuner_sleep = dib8096p_tuner_sleep;
+ ops->get_tune_state = dib8000_get_tune_state;
+ ops->get_i2c_tuner = dib8096p_get_i2c_tuner;
+ ops->set_slave_frontend = dib8000_set_slave_frontend;
+ ops->pid_filter = dib8000_pid_filter;
+ ops->ctrl_timf = dib8000_ctrl_timf;
+ ops->init = dib8000_init;
+ ops->get_i2c_master = dib8000_get_i2c_master;
+ ops->i2c_enumeration = dib8000_i2c_enumeration;
+ ops->set_wbd_ref = dib8000_set_wbd_ref;
+
+ return ops;
+}
EXPORT_SYMBOL(dib8000_attach);
MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h
index b8c11e52c512..84cc10383dcd 100644
--- a/drivers/media/dvb-frontends/dib8000.h
+++ b/drivers/media/dvb-frontends/dib8000.h
@@ -39,134 +39,34 @@ struct dib8000_config {
#define DEFAULT_DIB8000_I2C_ADDRESS 18
-#if IS_ENABLED(CONFIG_DVB_DIB8000)
-extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
-extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+struct dib8000_ops {
+ int (*set_wbd_ref)(struct dvb_frontend *fe, u16 value);
+ int (*update_pll)(struct dvb_frontend *fe,
+ struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
+ int (*set_gpio)(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
+ void (*pwm_agc_reset)(struct dvb_frontend *fe);
+ struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+ int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+ s32 (*get_adc_power)(struct dvb_frontend *fe, u8 mode);
+ int (*get_dc_power)(struct dvb_frontend *fe, u8 IQ);
+ u32 (*ctrl_timf)(struct dvb_frontend *fe, uint8_t op, uint32_t timf);
+ enum frontend_tune_state (*get_tune_state)(struct dvb_frontend *fe);
+ int (*set_tune_state)(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+ int (*set_slave_frontend)(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+ int (*remove_slave_frontend)(struct dvb_frontend *fe);
+ struct dvb_frontend *(*get_slave_frontend)(struct dvb_frontend *fe, int slave_index);
+ int (*i2c_enumeration)(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p);
+ struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
+ int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+ int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+ struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
+};
-extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
-extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
-extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
-extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
-extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
-extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
-extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
- uint8_t op, uint32_t timf);
-extern int dib8000_update_pll(struct dvb_frontend *fe,
- struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
-extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
-extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
-extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+#if IS_ENABLED(CONFIG_DVB_DIB8000)
+void *dib8000_attach(struct dib8000_ops *ops);
#else
-static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
- int no_of_demods, u8 default_addr, u8 first_addr,
- u8 is_dib8096p)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return CT_SHUTDOWN;
-}
-static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
- uint8_t op, uint32_t timf)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline int dib8000_update_pll(struct dvb_frontend *fe,
- struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static inline int dib8000_attach(struct dib8000_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c
index e540cfb13bac..f75dec443783 100644
--- a/drivers/media/dvb-frontends/dib9000.c
+++ b/drivers/media/dvb-frontends/dib9000.c
@@ -1040,13 +1040,18 @@ static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 addres
if (address >= 1024 || !state->platform.risc.fw_is_running)
return -EINVAL;
+ if (len > 18)
+ return -EINVAL;
+
/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
- mb[0] = (unsigned short)address;
- for (i = 0; i < len && i < 20; i += 2)
- mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
+ mb[0] = (u16)address;
+ for (i = 0; i + 1 < len; i += 2)
+ mb[1 + i / 2] = b[i] << 8 | b[i + 1];
+ if (len & 1)
+ mb[1 + len / 2] = b[len - 1] << 8;
- dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
+ dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, (3 + len) / 2, attribute);
return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
}
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index 9482954fd453..7ca7a21df183 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -2159,7 +2159,7 @@ int drxj_dap_atomic_read_write_block(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
@@ -2252,7 +2252,7 @@ static int hi_cfg_command(const struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -2363,7 +2363,7 @@ hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16
/* if ( powerdown_cmd == true ) */
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -2434,7 +2434,7 @@ static int init_hi(const struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -2650,7 +2650,7 @@ static int get_device_capabilities(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -3338,7 +3338,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*----------------------------------------------------------------------------*/
@@ -3421,7 +3421,7 @@ static int set_mpegtei_handling(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*----------------------------------------------------------------------------*/
@@ -3464,7 +3464,7 @@ static int bit_reverse_mpeg_output(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*----------------------------------------------------------------------------*/
@@ -3508,7 +3508,7 @@ static int set_mpeg_start_width(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*----------------------------------------------------------------------------*/
@@ -3652,7 +3652,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -3854,7 +3854,7 @@ ctrl_uio_write(struct drx_demod_instance *demod, struct drxuio_data *uio_data)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*---------------------------------------------------------------------------*/
@@ -3969,7 +3969,7 @@ static int smart_ant_init(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
@@ -4109,7 +4109,7 @@ static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -4178,7 +4178,7 @@ int drxj_dap_scu_atomic_read_write_block(struct i2c_device_addr *dev_addr, u32 a
return 0;
rw_error:
- return -EIO;
+ return rc;
}
@@ -4290,7 +4290,7 @@ static int adc_sync_measurement(struct drx_demod_instance *demod, u16 *count)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -4349,7 +4349,7 @@ static int adc_synchronization(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -4734,7 +4734,7 @@ static int init_agc(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -4831,7 +4831,7 @@ set_frequency(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -4879,7 +4879,7 @@ static int get_acc_pkt_err(struct drx_demod_instance *demod, u16 *packet_err)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
#endif
@@ -5097,7 +5097,7 @@ set_agc_rf(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -5326,7 +5326,7 @@ set_agc_if(struct drx_demod_instance *demod, struct drxj_cfg_agc *agc_settings,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -5362,7 +5362,7 @@ static int set_iqm_af(struct drx_demod_instance *demod, bool active)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -5470,7 +5470,7 @@ static int power_down_vsb(struct drx_demod_instance *demod, bool primary)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -5686,7 +5686,7 @@ static int set_vsb_leak_n_gain(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -6192,7 +6192,7 @@ static int set_vsb(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -6231,7 +6231,7 @@ static int get_vsb_post_rs_pck_err(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -6276,7 +6276,7 @@ static int get_vs_bpost_viterbi_ber(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -6321,7 +6321,7 @@ static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
@@ -6434,7 +6434,7 @@ static int power_down_qam(struct drx_demod_instance *demod, bool primary)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -6646,7 +6646,7 @@ set_qam_measurement(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -6881,7 +6881,7 @@ static int set_qam16(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -7116,7 +7116,7 @@ static int set_qam32(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -7351,7 +7351,7 @@ static int set_qam64(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -7586,7 +7586,7 @@ static int set_qam128(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -7821,7 +7821,7 @@ static int set_qam256(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -8650,7 +8650,7 @@ set_qam(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -8831,7 +8831,7 @@ static int qam_flip_spec(struct drx_demod_instance *demod, struct drx_channel *c
return 0;
rw_error:
- return -EIO;
+ return rc;
}
@@ -8984,7 +8984,7 @@ qam64auto(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -9068,7 +9068,7 @@ qam256auto(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -9273,7 +9273,7 @@ rw_error:
/* restore starting value */
if (auto_flag)
channel->constellation = DRX_CONSTELLATION_AUTO;
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -9344,7 +9344,7 @@ get_qamrs_err_count(struct i2c_device_addr *dev_addr,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -9425,8 +9425,8 @@ static int get_sig_strength(struct drx_demod_instance *demod, u16 *sig_strength)
*sig_strength = 0;
return 0;
- rw_error:
- return -EIO;
+rw_error:
+ return rc;
}
/**
@@ -9643,7 +9643,7 @@ rw_error:
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
- return -EIO;
+ return rc;
}
#endif /* #ifndef DRXJ_VSB_ONLY */
@@ -9810,7 +9810,7 @@ power_down_atv(struct drx_demod_instance *demod, enum drx_standard standard, boo
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -9840,7 +9840,7 @@ static int power_down_aud(struct drx_demod_instance *demod)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -9874,7 +9874,7 @@ static int set_orx_nsu_aox(struct drx_demod_instance *demod, bool active)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/**
@@ -10398,7 +10398,7 @@ static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_par
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -10638,7 +10638,7 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel)
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*=============================================================================
@@ -10756,7 +10756,7 @@ ctrl_sig_quality(struct drx_demod_instance *demod,
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -10844,7 +10844,7 @@ ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_st
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -10941,7 +10941,7 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
rw_error:
/* Don't know what the standard is now ... try again */
ext_attr->standard = DRX_STANDARD_UNKNOWN;
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -11222,7 +11222,7 @@ ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -11303,7 +11303,7 @@ ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain
return 0;
rw_error:
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -11315,6 +11315,7 @@ rw_error:
static int drx_ctrl_u_code(struct drx_demod_instance *demod,
struct drxu_code_info *mc_info,
enum drxu_code_action action);
+static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state);
/**
* \fn drxj_open()
@@ -11527,10 +11528,11 @@ static int drxj_open(struct drx_demod_instance *demod)
ext_attr->aud_data = drxj_default_aud_data_g;
demod->my_common_attr->is_opened = true;
+ drxj_set_lna_state(demod, false);
return 0;
rw_error:
common_attr->is_opened = false;
- return -EIO;
+ return rc;
}
/*============================================================================*/
@@ -11578,7 +11580,7 @@ static int drxj_close(struct drx_demod_instance *demod)
rw_error:
DRX_ATTR_ISOPENED(demod) = false;
- return -EIO;
+ return rc;
}
/*
@@ -11890,6 +11892,33 @@ release:
return rc;
}
+/* caller is expeced to check if lna is supported before enabling */
+static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
+{
+ struct drxuio_cfg uio_cfg;
+ struct drxuio_data uio_data;
+ int result;
+
+ uio_cfg.uio = DRX_UIO1;
+ uio_cfg.mode = DRX_UIO_MODE_READWRITE;
+ /* Configure user-I/O #3: enable read/write */
+ result = ctrl_set_uio_cfg(demod, &uio_cfg);
+ if (result) {
+ pr_err("Failed to setup LNA GPIO!\n");
+ return result;
+ }
+
+ uio_data.uio = DRX_UIO1;
+ uio_data.value = state;
+ result = ctrl_uio_write(demod, &uio_data);
+ if (result != 0) {
+ pr_err("Failed to %sable LNA!\n",
+ state ? "en" : "dis");
+ return result;
+ }
+ return 0;
+}
+
/*
* The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
*
@@ -12040,7 +12069,6 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
enum drx_standard standard = DRX_STANDARD_8VSB;
struct drx_channel channel;
int result;
- struct drxuio_data uio_data;
static const struct drx_channel def_channel = {
/* frequency */ 0,
/* bandwidth */ DRX_BANDWIDTH_6MHZ,
@@ -12125,13 +12153,7 @@ static int drx39xxj_set_frontend(struct dvb_frontend *fe)
return -EINVAL;
}
/* Just for giggles, let's shut off the LNA again.... */
- uio_data.uio = DRX_UIO1;
- uio_data.value = false;
- result = ctrl_uio_write(demod, &uio_data);
- if (result != 0) {
- pr_err("Failed to disable LNA!\n");
- return 0;
- }
+ drxj_set_lna_state(demod, false);
/* After set_frontend, except for strength, stats aren't available */
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
@@ -12180,21 +12202,28 @@ static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
static int drx39xxj_init(struct dvb_frontend *fe)
{
- /* Bring the demod out of sleep */
- drx39xxj_set_powerstate(fe, 1);
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int rc = 0;
- return 0;
+ if (fe->exit == DVB_FE_DEVICE_RESUME) {
+ /* so drxj_open() does what it needs to do */
+ demod->my_common_attr->is_opened = false;
+ rc = drxj_open(demod);
+ if (rc != 0)
+ pr_err("drx39xxj_init(): DRX open failed rc=%d!\n", rc);
+ } else
+ drx39xxj_set_powerstate(fe, 1);
+
+ return rc;
}
static int drx39xxj_set_lna(struct dvb_frontend *fe)
{
- int result;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
struct drxj_data *ext_attr = demod->my_ext_attr;
- struct drxuio_cfg uio_cfg;
- struct drxuio_data uio_data;
if (c->lna) {
if (!ext_attr->has_lna) {
@@ -12204,26 +12233,7 @@ static int drx39xxj_set_lna(struct dvb_frontend *fe)
}
}
- /* Turn off the LNA */
- uio_cfg.uio = DRX_UIO1;
- uio_cfg.mode = DRX_UIO_MODE_READWRITE;
- /* Configure user-I/O #3: enable read/write */
- result = ctrl_set_uio_cfg(demod, &uio_cfg);
- if (result) {
- pr_err("Failed to setup LNA GPIO!\n");
- return result;
- }
-
- uio_data.uio = DRX_UIO1;
- uio_data.value = c->lna;
- result = ctrl_uio_write(demod, &uio_data);
- if (result != 0) {
- pr_err("Failed to %sable LNA!\n",
- c->lna ? "en" : "dis");
- return result;
- }
-
- return 0;
+ return drxj_set_lna_state(demod, c->lna);
}
static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
@@ -12238,7 +12248,9 @@ static void drx39xxj_release(struct dvb_frontend *fe)
struct drx39xxj_state *state = fe->demodulator_priv;
struct drx_demod_instance *demod = state->demod;
- drxj_close(demod);
+ /* if device is removed don't access it */
+ if (fe->exit != DVB_FE_DEVICE_REMOVED)
+ drxj_close(demod);
kfree(demod->my_ext_attr);
kfree(demod->my_common_attr);
@@ -12259,8 +12271,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
struct drxj_data *demod_ext_attr = NULL;
struct drx_demod_instance *demod = NULL;
struct dtv_frontend_properties *p;
- struct drxuio_cfg uio_cfg;
- struct drxuio_data uio_data;
int result;
/* allocate memory for the internal state */
@@ -12272,22 +12282,20 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
if (demod == NULL)
goto error;
- demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
+ demod_addr = kmemdup(&drxj_default_addr_g,
+ sizeof(struct i2c_device_addr), GFP_KERNEL);
if (demod_addr == NULL)
goto error;
- memcpy(demod_addr, &drxj_default_addr_g,
- sizeof(struct i2c_device_addr));
- demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
+ demod_comm_attr = kmemdup(&drxj_default_comm_attr_g,
+ sizeof(struct drx_common_attr), GFP_KERNEL);
if (demod_comm_attr == NULL)
goto error;
- memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
- sizeof(struct drx_common_attr));
- demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
+ demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data),
+ GFP_KERNEL);
if (demod_ext_attr == NULL)
goto error;
- memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
/* setup the state */
state->i2c = i2c;
@@ -12313,24 +12321,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
goto error;
}
- /* Turn off the LNA */
- uio_cfg.uio = DRX_UIO1;
- uio_cfg.mode = DRX_UIO_MODE_READWRITE;
- /* Configure user-I/O #3: enable read/write */
- result = ctrl_set_uio_cfg(demod, &uio_cfg);
- if (result) {
- pr_err("Failed to setup LNA GPIO!\n");
- goto error;
- }
-
- uio_data.uio = DRX_UIO1;
- uio_data.value = false;
- result = ctrl_uio_write(demod, &uio_data);
- if (result != 0) {
- pr_err("Failed to disable LNA!\n");
- goto error;
- }
-
/* create dvb_frontend */
memcpy(&state->frontend.ops, &drx39xxj_ops,
sizeof(struct dvb_frontend_ops));
diff --git a/drivers/media/dvb-frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h
index 5f1d6b5f1685..d998e4d5a7fc 100644
--- a/drivers/media/dvb-frontends/drxd.h
+++ b/drivers/media/dvb-frontends/drxd.h
@@ -69,5 +69,4 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
}
#endif
-extern int drxd_config_i2c(struct dvb_frontend *, int);
#endif
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 5b87ece69414..ae2276db77bc 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -2840,7 +2840,7 @@ static int drxd_init(struct dvb_frontend *fe)
return err;
}
-int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
+static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
{
struct drxd_state *state = fe->demodulator_priv;
@@ -2849,7 +2849,6 @@ int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
return DRX_ConfigureI2CBridge(state, onoff);
}
-EXPORT_SYMBOL(drxd_config_i2c);
static int drxd_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *sets)
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index 2ef8ce13fb60..dfe0c2f7f1ef 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -879,7 +879,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
/* SNR(X) dB = 10 * ln(X) / ln(10) dB */
tmp = DIV_ROUND_CLOSEST(tmp, 8 * M88DS3103_SNR_ITERATIONS);
if (tmp)
- *snr = 100ul * intlog2(tmp) / intlog2(10);
+ *snr = div_u64((u64) 100 * intlog2(tmp), intlog2(10));
else
*snr = 0;
break;
@@ -908,7 +908,7 @@ static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *snr)
/* SNR(X) dB = 10 * log10(X) dB */
if (signal > noise) {
tmp = signal / noise;
- *snr = 100ul * intlog10(tmp) / (1 << 24);
+ *snr = div_u64((u64) 100 * intlog10(tmp), (1 << 24));
} else {
*snr = 0;
}
@@ -926,6 +926,86 @@ err:
return ret;
}
+static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct m88ds3103_priv *priv = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret;
+ unsigned int utmp;
+ u8 buf[3], u8tmp;
+ dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
+ if (ret)
+ goto err;
+
+ if (!(u8tmp & 0x10)) {
+ u8tmp |= 0x10;
+
+ ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
+ if (ret)
+ goto err;
+
+ priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+ /* restart counters */
+ ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
+ if (ret)
+ goto err;
+ }
+ break;
+ case SYS_DVBS2:
+ ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
+ if (ret)
+ goto err;
+
+ utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
+
+ if (utmp > 3000) {
+ ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
+ if (ret)
+ goto err;
+
+ priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+ /* restart counters */
+ ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
+ if (ret)
+ goto err;
+ }
+ break;
+ default:
+ dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
+ __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ *ber = priv->ber;
+
+ return 0;
+err:
+ dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
+}
static int m88ds3103_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t fe_sec_tone_mode)
@@ -1284,6 +1364,7 @@ static struct dvb_frontend_ops m88ds3103_ops = {
.read_status = m88ds3103_read_status,
.read_snr = m88ds3103_read_snr,
+ .read_ber = m88ds3103_read_ber,
.diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
.diseqc_send_burst = m88ds3103_diseqc_send_burst,
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index 84c3c06df622..9169fdd143cf 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -22,6 +22,7 @@
#include "dvb_math.h"
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
+#include <linux/math64.h>
#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
#define M88DS3103_MCLK_KHZ 96000
@@ -34,6 +35,7 @@ struct m88ds3103_priv {
struct dvb_frontend fe;
fe_delivery_system_t delivery_system;
fe_status_t fe_status;
+ u32 ber;
bool warm; /* FW running */
struct i2c_adapter *i2c_adapter;
};
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index 2f458bb188c7..b931179c70a4 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -459,6 +459,9 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
unsigned layer)
{
int rc;
+ int interleaving[] = {
+ 0, 1, 2, 4, 8
+ };
static unsigned char reg[] = {
[0] = 0x88, /* Layer A */
@@ -475,20 +478,7 @@ static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
if (rc < 0)
return rc;
- switch ((rc >> 4) & 0x07) {
- case 1:
- return GUARD_INTERVAL_1_4;
- case 2:
- return GUARD_INTERVAL_1_8;
- case 3:
- return GUARD_INTERVAL_1_16;
- case 4:
- return GUARD_INTERVAL_1_32;
-
- default:
- case 0:
- return GUARD_INTERVAL_AUTO;
- }
+ return interleaving[(rc >> 4) & 0x07];
}
static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
@@ -566,7 +556,7 @@ static u32 isdbt_rate[3][5][4] = {
static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
u32 modulation, u32 forward_error_correction,
- u32 interleaving,
+ u32 guard_interval,
u32 segment)
{
struct mb86a20s_state *state = fe->demodulator_priv;
@@ -574,7 +564,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
int mod, fec, guard;
/*
- * If modulation/fec/interleaving is not detected, the default is
+ * If modulation/fec/guard is not detected, the default is
* to consider the lowest bit rate, to avoid taking too long time
* to get BER.
*/
@@ -612,7 +602,7 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
break;
}
- switch (interleaving) {
+ switch (guard_interval) {
default:
case GUARD_INTERVAL_1_4:
guard = 0;
@@ -703,7 +693,7 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
c->layer[layer].interleaving = rc;
mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation,
c->layer[layer].fec,
- c->layer[layer].interleaving,
+ c->guard_interval,
c->layer[layer].segment_count);
}
@@ -721,11 +711,10 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
rc = mb86a20s_readreg(state, 0x07);
if (rc < 0)
return rc;
+ c->transmission_mode = TRANSMISSION_MODE_AUTO;
if ((rc & 0x60) == 0x20) {
- switch (rc & 0x0c >> 2) {
- case 0:
- c->transmission_mode = TRANSMISSION_MODE_2K;
- break;
+ /* Only modes 2 and 3 are supported */
+ switch ((rc >> 2) & 0x03) {
case 1:
c->transmission_mode = TRANSMISSION_MODE_4K;
break;
@@ -734,7 +723,9 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
break;
}
}
+ c->guard_interval = GUARD_INTERVAL_AUTO;
if (!(rc & 0x10)) {
+ /* Guard interval 1/32 is not supported */
switch (rc & 0x3) {
case 0:
c->guard_interval = GUARD_INTERVAL_1_4;
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 093df6b6ae35..023e0f49c786 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -35,6 +35,10 @@
#include <linux/jiffies.h>
#include <linux/math64.h>
+static bool rtl2832_sdr_emulated_fmt;
+module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
#define MAX_BULK_BUFS (10)
#define BULK_BUFFER_SIZE (128 * 512)
@@ -80,15 +84,18 @@ static const struct v4l2_frequency_band bands_fm[] = {
struct rtl2832_sdr_format {
char *name;
u32 pixelformat;
+ u32 buffersize;
};
static struct rtl2832_sdr_format formats[] = {
{
- .name = "IQ U8",
- .pixelformat = V4L2_SDR_FMT_CU8,
+ .name = "Complex U8",
+ .pixelformat = V4L2_SDR_FMT_CU8,
+ .buffersize = BULK_BUFFER_SIZE,
}, {
- .name = "IQ U16LE (emulated)",
+ .name = "Complex U16LE (emulated)",
.pixelformat = V4L2_SDR_FMT_CU16LE,
+ .buffersize = BULK_BUFFER_SIZE * 2,
},
};
@@ -139,6 +146,8 @@ struct rtl2832_sdr_state {
unsigned int f_adc, f_tuner;
u32 pixelformat;
+ u32 buffersize;
+ unsigned int num_formats;
/* Controls */
struct v4l2_ctrl_handler hdl;
@@ -348,6 +357,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
/* convert u8 to u16 */
unsigned int i;
u16 *u16dst = dst;
+
for (i = 0; i < src_len; i++)
*u16dst++ = (src[i] << 8) | (src[i] >> 0);
dst_len = 2 * src_len;
@@ -359,6 +369,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
#define MSECS 10000UL
unsigned int samples = s->sample - s->sample_measured;
+
s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
s->sample_measured = s->sample;
dev_dbg(&s->udev->dev,
@@ -560,11 +571,13 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
{
unsigned long flags = 0;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
spin_lock_irqsave(&s->queued_bufs_lock, flags);
while (!list_empty(&s->queued_bufs)) {
struct rtl2832_sdr_frame_buf *buf;
+
buf = list_entry(s->queued_bufs.next,
struct rtl2832_sdr_frame_buf, list);
list_del(&buf->list);
@@ -577,6 +590,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
{
struct rtl2832_sdr_state *s = fe->sec_priv;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->vb_queue_lock);
@@ -598,6 +612,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
@@ -615,14 +630,14 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
/* Need at least 8 buffers */
if (vq->num_buffers + *nbuffers < 8)
*nbuffers = 8 - vq->num_buffers;
*nplanes = 1;
- /* 2 = max 16-bit sample returned */
- sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2);
+ sizes[0] = PAGE_ALIGN(s->buffersize);
dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
__func__, *nbuffers, sizes[0]);
return 0;
@@ -665,6 +680,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
u8 buf[4], u8tmp1, u8tmp2;
u64 u64tmp;
u32 u32tmp;
+
dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
if (!test_bit(POWER_ON, &s->flags))
@@ -935,7 +951,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
/*
* bandwidth (Hz)
*/
- bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
+ bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
c->bandwidth_hz = s->f_adc;
@@ -987,6 +1004,7 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
int ret;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
if (!s->udev)
@@ -1035,6 +1053,7 @@ err:
static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->v4l2_lock);
@@ -1068,6 +1087,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
__func__, v->index, v->type);
@@ -1094,6 +1114,7 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
if (v->index > 1)
@@ -1105,6 +1126,7 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
__func__, band->tuner, band->type, band->index);
@@ -1130,6 +1152,7 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
{
struct rtl2832_sdr_state *s = video_drvdata(file);
int ret = 0;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
__func__, f->tuner, f->type);
@@ -1193,9 +1216,10 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
- if (f->index >= NUM_FORMATS)
+ if (f->index >= s->num_formats)
return -EINVAL;
strlcpy(f->description, formats[f->index].name, sizeof(f->description));
@@ -1208,9 +1232,12 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
return 0;
@@ -1222,6 +1249,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
struct rtl2832_sdr_state *s = video_drvdata(file);
struct vb2_queue *q = &s->vb_queue;
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
@@ -1229,15 +1257,19 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
return -EBUSY;
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
+ for (i = 0; i < s->num_formats; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- s->pixelformat = f->fmt.sdr.pixelformat;
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
}
}
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1247,16 +1279,20 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
{
struct rtl2832_sdr_state *s = video_drvdata(file);
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
+ for (i = 0; i < s->num_formats; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
+ }
}
f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1316,8 +1352,9 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
struct dvb_frontend *fe = s->fe;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
+
dev_dbg(&s->udev->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
__func__, ctrl->id, ctrl->name, ctrl->val,
ctrl->minimum, ctrl->maximum, ctrl->step);
@@ -1327,14 +1364,16 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
/* TODO: these controls should be moved to tuner drivers */
if (s->bandwidth_auto->val) {
/* Round towards the closest legal value */
- s32 val = s->f_adc + s->bandwidth->step / 2;
+ s32 val = s->f_adc + div_u64(s->bandwidth->step, 2);
u32 offset;
- val = clamp(val, s->bandwidth->minimum, s->bandwidth->maximum);
+
+ val = clamp_t(s32, val, s->bandwidth->minimum,
+ s->bandwidth->maximum);
offset = val - s->bandwidth->minimum;
- offset = s->bandwidth->step * (offset / s->bandwidth->step);
+ offset = s->bandwidth->step *
+ div_u64(offset, s->bandwidth->step);
s->bandwidth->val = s->bandwidth->minimum + offset;
}
-
c->bandwidth_hz = s->bandwidth->val;
if (!test_bit(POWER_ON, &s->flags))
@@ -1390,7 +1429,11 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->cfg = cfg;
s->f_adc = bands_adc[0].rangelow;
s->f_tuner = bands_fm[0].rangelow;
- s->pixelformat = V4L2_SDR_FMT_CU8;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ s->num_formats = NUM_FORMATS;
+ if (rtl2832_sdr_emulated_fmt == false)
+ s->num_formats -= 1;
mutex_init(&s->v4l2_lock);
mutex_init(&s->vb_queue_lock);
@@ -1420,15 +1463,24 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
break;
case RTL2832_TUNER_R820T:
v4l2_ctrl_handler_init(&s->hdl, 2);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH,
+ 0, 8000000, 100000, 0);
v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
break;
case RTL2832_TUNER_FC0012:
case RTL2832_TUNER_FC0013:
v4l2_ctrl_handler_init(&s->hdl, 2);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH,
+ 6000000, 8000000, 1000000,
+ 6000000);
v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
break;
default:
@@ -1448,7 +1500,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->vdev = rtl2832_sdr_template;
s->vdev.queue = &s->vb_queue;
s->vdev.queue->lock = &s->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
video_set_drvdata(&s->vdev, s);
/* Register the v4l2_device structure */
@@ -1480,6 +1531,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
KBUILD_MODNAME);
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
return fe;
err_unregister_v4l2_dev:
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h
index b865fadf184f..b865fadf184f 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.h
diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c
new file mode 100644
index 000000000000..3a2d6c5aded6
--- /dev/null
+++ b/drivers/media/dvb-frontends/si2165.c
@@ -0,0 +1,1040 @@
+/*
+ Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+ Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ References:
+ http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "si2165_priv.h"
+#include "si2165.h"
+
+/* Hauppauge WinTV-HVR-930C-HD B130 / PCTV QuatroStick 521e 1113xx
+ * uses 16 MHz xtal */
+
+/* Hauppauge WinTV-HVR-930C-HD B131 / PCTV QuatroStick 522e 1114xx
+ * uses 24 MHz clock provided by tuner */
+
+struct si2165_state {
+ struct i2c_adapter *i2c;
+
+ struct dvb_frontend frontend;
+
+ struct si2165_config config;
+
+ /* chip revision */
+ u8 revcode;
+ /* chip type */
+ u8 chip_type;
+
+ /* calculated by xtal and div settings */
+ u32 fvco_hz;
+ u32 sys_clk;
+ u32 adc_clk;
+
+ bool has_dvbc;
+ bool has_dvbt;
+ bool firmware_loaded;
+};
+
+#define DEBUG_OTHER 0x01
+#define DEBUG_I2C_WRITE 0x02
+#define DEBUG_I2C_READ 0x04
+#define DEBUG_REG_READ 0x08
+#define DEBUG_REG_WRITE 0x10
+#define DEBUG_FW_LOAD 0x20
+
+static int debug = 0x00;
+
+#define dprintk(args...) \
+ do { \
+ if (debug & DEBUG_OTHER) \
+ printk(KERN_DEBUG "si2165: " args); \
+ } while (0)
+
+#define deb_i2c_write(args...) \
+ do { \
+ if (debug & DEBUG_I2C_WRITE) \
+ printk(KERN_DEBUG "si2165: i2c write: " args); \
+ } while (0)
+
+#define deb_i2c_read(args...) \
+ do { \
+ if (debug & DEBUG_I2C_READ) \
+ printk(KERN_DEBUG "si2165: i2c read: " args); \
+ } while (0)
+
+#define deb_readreg(args...) \
+ do { \
+ if (debug & DEBUG_REG_READ) \
+ printk(KERN_DEBUG "si2165: reg read: " args); \
+ } while (0)
+
+#define deb_writereg(args...) \
+ do { \
+ if (debug & DEBUG_REG_WRITE) \
+ printk(KERN_DEBUG "si2165: reg write: " args); \
+ } while (0)
+
+#define deb_fw_load(args...) \
+ do { \
+ if (debug & DEBUG_FW_LOAD) \
+ printk(KERN_DEBUG "si2165: fw load: " args); \
+ } while (0)
+
+static int si2165_write(struct si2165_state *state, const u16 reg,
+ const u8 *src, const int count)
+{
+ int ret;
+ struct i2c_msg msg;
+ u8 buf[2 + 4]; /* write a maximum of 4 bytes of data */
+
+ if (count + 2 > sizeof(buf)) {
+ dev_warn(&state->i2c->dev,
+ "%s: i2c wr reg=%04x: count=%d is too big!\n",
+ KBUILD_MODNAME, reg, count);
+ return -EINVAL;
+ }
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xff;
+ memcpy(buf + 2, src, count);
+
+ msg.addr = state->config.i2c_addr;
+ msg.flags = 0;
+ msg.buf = buf;
+ msg.len = count + 2;
+
+ if (debug & DEBUG_I2C_WRITE)
+ deb_i2c_write("reg: 0x%04x, data: %*ph\n", reg, count, src);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+
+ if (ret != 1) {
+ dev_err(&state->i2c->dev, "%s: ret == %d\n", __func__, ret);
+ if (ret < 0)
+ return ret;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int si2165_read(struct si2165_state *state,
+ const u16 reg, u8 *val, const int count)
+{
+ int ret;
+ u8 reg_buf[] = { reg >> 8, reg & 0xff };
+ struct i2c_msg msg[] = {
+ { .addr = state->config.i2c_addr,
+ .flags = 0, .buf = reg_buf, .len = 2 },
+ { .addr = state->config.i2c_addr,
+ .flags = I2C_M_RD, .buf = val, .len = count },
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+ dev_err(&state->i2c->dev, "%s: error (addr %02x reg %04x error (ret == %i)\n",
+ __func__, state->config.i2c_addr, reg, ret);
+ if (ret < 0)
+ return ret;
+ else
+ return -EREMOTEIO;
+ }
+
+ if (debug & DEBUG_I2C_READ)
+ deb_i2c_read("reg: 0x%04x, data: %*ph\n", reg, count, val);
+
+ return 0;
+}
+
+static int si2165_readreg8(struct si2165_state *state,
+ const u16 reg, u8 *val)
+{
+ int ret;
+
+ ret = si2165_read(state, reg, val, 1);
+ deb_readreg("R(0x%04x)=0x%02x\n", reg, *val);
+ return ret;
+}
+
+static int si2165_readreg16(struct si2165_state *state,
+ const u16 reg, u16 *val)
+{
+ u8 buf[2];
+
+ int ret = si2165_read(state, reg, buf, 2);
+ *val = buf[0] | buf[1] << 8;
+ deb_readreg("R(0x%04x)=0x%04x\n", reg, *val);
+ return ret;
+}
+
+static int si2165_writereg8(struct si2165_state *state, const u16 reg, u8 val)
+{
+ return si2165_write(state, reg, &val, 1);
+}
+
+static int si2165_writereg16(struct si2165_state *state, const u16 reg, u16 val)
+{
+ u8 buf[2] = { val & 0xff, (val >> 8) & 0xff };
+
+ return si2165_write(state, reg, buf, 2);
+}
+
+static int si2165_writereg24(struct si2165_state *state, const u16 reg, u32 val)
+{
+ u8 buf[3] = { val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff };
+
+ return si2165_write(state, reg, buf, 3);
+}
+
+static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val)
+{
+ u8 buf[4] = {
+ val & 0xff,
+ (val >> 8) & 0xff,
+ (val >> 16) & 0xff,
+ (val >> 24) & 0xff
+ };
+ return si2165_write(state, reg, buf, 4);
+}
+
+static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg,
+ u8 val, u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ if (mask != 0xff) {
+ ret = si2165_readreg8(state, reg, &tmp);
+ if (ret < 0)
+ goto err;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ ret = si2165_writereg8(state, reg, val);
+err:
+ return ret;
+}
+
+static int si2165_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *s)
+{
+ s->min_delay_ms = 1000;
+ return 0;
+}
+
+static int si2165_init_pll(struct si2165_state *state)
+{
+ u32 ref_freq_Hz = state->config.ref_freq_Hz;
+ u8 divr = 1; /* 1..7 */
+ u8 divp = 1; /* only 1 or 4 */
+ u8 divn = 56; /* 1..63 */
+ u8 divm = 8;
+ u8 divl = 12;
+ u8 buf[4];
+
+ /* hardcoded values can be deleted if calculation is verified
+ * or it yields the same values as the windows driver */
+ switch (ref_freq_Hz) {
+ case 16000000u:
+ divn = 56;
+ break;
+ case 24000000u:
+ divr = 2;
+ divp = 4;
+ divn = 19;
+ break;
+ default:
+ /* ref_freq / divr must be between 4 and 16 MHz */
+ if (ref_freq_Hz > 16000000u)
+ divr = 2;
+
+ /* now select divn and divp such that
+ * fvco is in 1624..1824 MHz */
+ if (1624000000u * divr > ref_freq_Hz * 2u * 63u)
+ divp = 4;
+
+ /* is this already correct regarding rounding? */
+ divn = 1624000000u * divr / (ref_freq_Hz * 2u * divp);
+ break;
+ }
+
+ /* adc_clk and sys_clk depend on xtal and pll settings */
+ state->fvco_hz = ref_freq_Hz / divr
+ * 2u * divn * divp;
+ state->adc_clk = state->fvco_hz / (divm * 4u);
+ state->sys_clk = state->fvco_hz / (divl * 2u);
+
+ /* write pll registers 0x00a0..0x00a3 at once */
+ buf[0] = divl;
+ buf[1] = divm;
+ buf[2] = (divn & 0x3f) | ((divp == 1) ? 0x40 : 0x00) | 0x80;
+ buf[3] = divr;
+ return si2165_write(state, 0x00a0, buf, 4);
+}
+
+static int si2165_adjust_pll_divl(struct si2165_state *state, u8 divl)
+{
+ state->sys_clk = state->fvco_hz / (divl * 2u);
+ return si2165_writereg8(state, 0x00a0, divl); /* pll_divl */
+}
+
+static u32 si2165_get_fe_clk(struct si2165_state *state)
+{
+ /* assume Oversampling mode Ovr4 is used */
+ return state->adc_clk;
+}
+
+static bool si2165_wait_init_done(struct si2165_state *state)
+{
+ int ret = -EINVAL;
+ u8 val = 0;
+ int i;
+
+ for (i = 0; i < 3; ++i) {
+ si2165_readreg8(state, 0x0054, &val);
+ if (val == 0x01)
+ return 0;
+ usleep_range(1000, 50000);
+ }
+ dev_err(&state->i2c->dev, "%s: init_done was not set\n",
+ KBUILD_MODNAME);
+ return ret;
+}
+
+static int si2165_upload_firmware_block(struct si2165_state *state,
+ const u8 *data, u32 len, u32 *poffset, u32 block_count)
+{
+ int ret;
+ u8 buf_ctrl[4] = { 0x00, 0x00, 0x00, 0xc0 };
+ u8 wordcount;
+ u32 cur_block = 0;
+ u32 offset = poffset ? *poffset : 0;
+
+ if (len < 4)
+ return -EINVAL;
+ if (len % 4 != 0)
+ return -EINVAL;
+
+ deb_fw_load("si2165_upload_firmware_block called with len=0x%x offset=0x%x blockcount=0x%x\n",
+ len, offset, block_count);
+ while (offset+12 <= len && cur_block < block_count) {
+ deb_fw_load("si2165_upload_firmware_block in while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
+ len, offset, cur_block, block_count);
+ wordcount = data[offset];
+ if (wordcount < 1 || data[offset+1] ||
+ data[offset+2] || data[offset+3]) {
+ dev_warn(&state->i2c->dev,
+ "%s: bad fw data[0..3] = %*ph\n",
+ KBUILD_MODNAME, 4, data);
+ return -EINVAL;
+ }
+
+ if (offset + 8 + wordcount * 4 > len) {
+ dev_warn(&state->i2c->dev,
+ "%s: len is too small for block len=%d, wordcount=%d\n",
+ KBUILD_MODNAME, len, wordcount);
+ return -EINVAL;
+ }
+
+ buf_ctrl[0] = wordcount - 1;
+
+ ret = si2165_write(state, 0x0364, buf_ctrl, 4);
+ if (ret < 0)
+ goto error;
+ ret = si2165_write(state, 0x0368, data+offset+4, 4);
+ if (ret < 0)
+ goto error;
+
+ offset += 8;
+
+ while (wordcount > 0) {
+ ret = si2165_write(state, 0x36c, data+offset, 4);
+ if (ret < 0)
+ goto error;
+ wordcount--;
+ offset += 4;
+ }
+ cur_block++;
+ }
+
+ deb_fw_load("si2165_upload_firmware_block after while len=0x%x offset=0x%x cur_block=0x%x blockcount=0x%x\n",
+ len, offset, cur_block, block_count);
+
+ if (poffset)
+ *poffset = offset;
+
+ deb_fw_load("si2165_upload_firmware_block returned offset=0x%x\n",
+ offset);
+
+ return 0;
+error:
+ return ret;
+}
+
+static int si2165_upload_firmware(struct si2165_state *state)
+{
+ /* int ret; */
+ u8 val[3];
+ u16 val16;
+ int ret;
+
+ const struct firmware *fw = NULL;
+ u8 *fw_file = SI2165_FIRMWARE;
+ const u8 *data;
+ u32 len;
+ u32 offset;
+ u8 patch_version;
+ u8 block_count;
+ u16 crc_expected;
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
+ if (ret) {
+ dev_warn(&state->i2c->dev, "%s: firmare file '%s' not found\n",
+ KBUILD_MODNAME, fw_file);
+ goto error;
+ }
+
+ data = fw->data;
+ len = fw->size;
+
+ dev_info(&state->i2c->dev, "%s: downloading firmware from file '%s' size=%d\n",
+ KBUILD_MODNAME, fw_file, len);
+
+ if (len % 4 != 0) {
+ dev_warn(&state->i2c->dev, "%s: firmware size is not multiple of 4\n",
+ KBUILD_MODNAME);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* check header (8 bytes) */
+ if (len < 8) {
+ dev_warn(&state->i2c->dev, "%s: firmware header is missing\n",
+ KBUILD_MODNAME);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (data[0] != 1 || data[1] != 0) {
+ dev_warn(&state->i2c->dev, "%s: firmware file version is wrong\n",
+ KBUILD_MODNAME);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ patch_version = data[2];
+ block_count = data[4];
+ crc_expected = data[7] << 8 | data[6];
+
+ /* start uploading fw */
+ /* boot/wdog status */
+ ret = si2165_writereg8(state, 0x0341, 0x00);
+ if (ret < 0)
+ goto error;
+ /* reset */
+ ret = si2165_writereg8(state, 0x00c0, 0x00);
+ if (ret < 0)
+ goto error;
+ /* boot/wdog status */
+ ret = si2165_readreg8(state, 0x0341, val);
+ if (ret < 0)
+ goto error;
+
+ /* enable reset on error */
+ ret = si2165_readreg8(state, 0x035c, val);
+ if (ret < 0)
+ goto error;
+ ret = si2165_readreg8(state, 0x035c, val);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x035c, 0x02);
+ if (ret < 0)
+ goto error;
+
+ /* start right after the header */
+ offset = 8;
+
+ dev_info(&state->i2c->dev, "%s: si2165_upload_firmware extracted patch_version=0x%02x, block_count=0x%02x, crc_expected=0x%04x\n",
+ KBUILD_MODNAME, patch_version, block_count, crc_expected);
+
+ ret = si2165_upload_firmware_block(state, data, len, &offset, 1);
+ if (ret < 0)
+ goto error;
+
+ ret = si2165_writereg8(state, 0x0344, patch_version);
+ if (ret < 0)
+ goto error;
+
+ /* reset crc */
+ ret = si2165_writereg8(state, 0x0379, 0x01);
+ if (ret)
+ return ret;
+
+ ret = si2165_upload_firmware_block(state, data, len,
+ &offset, block_count);
+ if (ret < 0) {
+ dev_err(&state->i2c->dev,
+ "%s: firmare could not be uploaded\n",
+ KBUILD_MODNAME);
+ goto error;
+ }
+
+ /* read crc */
+ ret = si2165_readreg16(state, 0x037a, &val16);
+ if (ret)
+ goto error;
+
+ if (val16 != crc_expected) {
+ dev_err(&state->i2c->dev,
+ "%s: firmware crc mismatch %04x != %04x\n",
+ KBUILD_MODNAME, val16, crc_expected);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ ret = si2165_upload_firmware_block(state, data, len, &offset, 5);
+ if (ret)
+ goto error;
+
+ if (len != offset) {
+ dev_err(&state->i2c->dev,
+ "%s: firmare len mismatch %04x != %04x\n",
+ KBUILD_MODNAME, len, offset);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /* reset watchdog error register */
+ ret = si2165_writereg_mask8(state, 0x0341, 0x02, 0x02);
+ if (ret < 0)
+ goto error;
+
+ /* enable reset on error */
+ ret = si2165_writereg_mask8(state, 0x035c, 0x01, 0x01);
+ if (ret < 0)
+ goto error;
+
+ dev_info(&state->i2c->dev, "%s: fw load finished\n", KBUILD_MODNAME);
+
+ ret = 0;
+ state->firmware_loaded = true;
+error:
+ if (fw) {
+ release_firmware(fw);
+ fw = NULL;
+ }
+
+ return ret;
+}
+
+static int si2165_init(struct dvb_frontend *fe)
+{
+ int ret = 0;
+ struct si2165_state *state = fe->demodulator_priv;
+ u8 val;
+ u8 patch_version = 0x00;
+
+ dprintk("%s: called\n", __func__);
+
+ /* powerup */
+ ret = si2165_writereg8(state, 0x0000, state->config.chip_mode);
+ if (ret < 0)
+ goto error;
+ /* dsp_clock_enable */
+ ret = si2165_writereg8(state, 0x0104, 0x01);
+ if (ret < 0)
+ goto error;
+ ret = si2165_readreg8(state, 0x0000, &val); /* verify chip_mode */
+ if (ret < 0)
+ goto error;
+ if (val != state->config.chip_mode) {
+ dev_err(&state->i2c->dev, "%s: could not set chip_mode\n",
+ KBUILD_MODNAME);
+ return -EINVAL;
+ }
+
+ /* agc */
+ ret = si2165_writereg8(state, 0x018b, 0x00);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x0190, 0x01);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x0170, 0x00);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x0171, 0x07);
+ if (ret < 0)
+ goto error;
+ /* rssi pad */
+ ret = si2165_writereg8(state, 0x0646, 0x00);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x0641, 0x00);
+ if (ret < 0)
+ goto error;
+
+ ret = si2165_init_pll(state);
+ if (ret < 0)
+ goto error;
+
+ /* enable chip_init */
+ ret = si2165_writereg8(state, 0x0050, 0x01);
+ if (ret < 0)
+ goto error;
+ /* set start_init */
+ ret = si2165_writereg8(state, 0x0096, 0x01);
+ if (ret < 0)
+ goto error;
+ ret = si2165_wait_init_done(state);
+ if (ret < 0)
+ goto error;
+
+ /* disable chip_init */
+ ret = si2165_writereg8(state, 0x0050, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* ber_pkt */
+ ret = si2165_writereg16(state, 0x0470 , 0x7530);
+ if (ret < 0)
+ goto error;
+
+ ret = si2165_readreg8(state, 0x0344, &patch_version);
+ if (ret < 0)
+ goto error;
+
+ ret = si2165_writereg8(state, 0x00cb, 0x00);
+ if (ret < 0)
+ goto error;
+
+ /* dsp_addr_jump */
+ ret = si2165_writereg32(state, 0x0348, 0xf4000000);
+ if (ret < 0)
+ goto error;
+ /* boot/wdog status */
+ ret = si2165_readreg8(state, 0x0341, &val);
+ if (ret < 0)
+ goto error;
+
+ if (patch_version == 0x00) {
+ ret = si2165_upload_firmware(state);
+ if (ret < 0)
+ goto error;
+ }
+
+ /* write adc values after each reset*/
+ ret = si2165_writereg8(state, 0x012a, 0x46);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x012c, 0x00);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x012e, 0x0a);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x012f, 0xff);
+ if (ret < 0)
+ goto error;
+ ret = si2165_writereg8(state, 0x0123, 0x70);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+error:
+ return ret;
+}
+
+static int si2165_sleep(struct dvb_frontend *fe)
+{
+ int ret;
+ struct si2165_state *state = fe->demodulator_priv;
+
+ /* dsp clock disable */
+ ret = si2165_writereg8(state, 0x0104, 0x00);
+ if (ret < 0)
+ return ret;
+ /* chip mode */
+ ret = si2165_writereg8(state, 0x0000, SI2165_MODE_OFF);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int si2165_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ int ret;
+ u8 fec_lock = 0;
+ struct si2165_state *state = fe->demodulator_priv;
+
+ if (!state->has_dvbt)
+ return -EINVAL;
+
+ /* check fec_lock */
+ ret = si2165_readreg8(state, 0x4e0, &fec_lock);
+ if (ret < 0)
+ return ret;
+ *status = 0;
+ if (fec_lock & 0x01) {
+ *status |= FE_HAS_SIGNAL;
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_LOCK;
+ }
+
+ return 0;
+}
+
+static int si2165_set_oversamp(struct si2165_state *state, u32 dvb_rate)
+{
+ u64 oversamp;
+ u32 reg_value;
+
+ oversamp = si2165_get_fe_clk(state);
+ oversamp <<= 23;
+ do_div(oversamp, dvb_rate);
+ reg_value = oversamp & 0x3fffffff;
+
+ /* oversamp, usbdump contained 0x03100000; */
+ return si2165_writereg32(state, 0x00e4, reg_value);
+}
+
+static int si2165_set_if_freq_shift(struct si2165_state *state, u32 IF)
+{
+ u64 if_freq_shift;
+ s32 reg_value = 0;
+ u32 fe_clk = si2165_get_fe_clk(state);
+
+ if_freq_shift = IF;
+ if_freq_shift <<= 29;
+
+ do_div(if_freq_shift, fe_clk);
+ reg_value = (s32)if_freq_shift;
+
+ if (state->config.inversion)
+ reg_value = -reg_value;
+
+ reg_value = reg_value & 0x1fffffff;
+
+ /* if_freq_shift, usbdump contained 0x023ee08f; */
+ return si2165_writereg32(state, 0x00e8, reg_value);
+}
+
+static int si2165_set_parameters(struct dvb_frontend *fe)
+{
+ int ret;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct si2165_state *state = fe->demodulator_priv;
+ u8 val[3];
+ u32 IF;
+ u32 dvb_rate = 0;
+ u16 bw10k;
+
+ dprintk("%s: called\n", __func__);
+
+ if (!fe->ops.tuner_ops.get_if_frequency) {
+ dev_err(&state->i2c->dev,
+ "%s: Error: get_if_frequency() not defined at tuner. Can't work without it!\n",
+ KBUILD_MODNAME);
+ return -EINVAL;
+ }
+
+ if (!state->has_dvbt)
+ return -EINVAL;
+
+ if (p->bandwidth_hz > 0) {
+ dvb_rate = p->bandwidth_hz * 8 / 7;
+ bw10k = p->bandwidth_hz / 10000;
+ } else {
+ dvb_rate = 8 * 8 / 7;
+ bw10k = 800;
+ }
+
+ /* standard = DVB-T */
+ ret = si2165_writereg8(state, 0x00ec, 0x01);
+ if (ret < 0)
+ return ret;
+ ret = si2165_adjust_pll_divl(state, 12);
+ if (ret < 0)
+ return ret;
+
+ fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+ ret = si2165_set_if_freq_shift(state, IF);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x08f8, 0x00);
+ if (ret < 0)
+ return ret;
+ /* ts output config */
+ ret = si2165_writereg8(state, 0x04e4, 0x20);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg16(state, 0x04ef, 0x00fe);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg24(state, 0x04f4, 0x555555);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x04e5, 0x01);
+ if (ret < 0)
+ return ret;
+ /* bandwidth in 10KHz steps */
+ ret = si2165_writereg16(state, 0x0308, bw10k);
+ if (ret < 0)
+ return ret;
+ ret = si2165_set_oversamp(state, dvb_rate);
+ if (ret < 0)
+ return ret;
+ /* impulsive_noise_remover */
+ ret = si2165_writereg8(state, 0x031c, 0x01);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x00cb, 0x00);
+ if (ret < 0)
+ return ret;
+ /* agc2 */
+ ret = si2165_writereg8(state, 0x016e, 0x41);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x016c, 0x0e);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x016d, 0x10);
+ if (ret < 0)
+ return ret;
+ /* agc */
+ ret = si2165_writereg8(state, 0x015b, 0x03);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x0150, 0x78);
+ if (ret < 0)
+ return ret;
+ /* agc */
+ ret = si2165_writereg8(state, 0x01a0, 0x78);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x01c8, 0x68);
+ if (ret < 0)
+ return ret;
+ /* freq_sync_range */
+ ret = si2165_writereg16(state, 0x030c, 0x0064);
+ if (ret < 0)
+ return ret;
+ /* gp_reg0 */
+ ret = si2165_readreg8(state, 0x0387, val);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x0387, 0x00);
+ if (ret < 0)
+ return ret;
+ /* dsp_addr_jump */
+ ret = si2165_writereg32(state, 0x0348, 0xf4000000);
+ if (ret < 0)
+ return ret;
+
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+
+ /* recalc if_freq_shift if IF might has changed */
+ fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+ ret = si2165_set_if_freq_shift(state, IF);
+ if (ret < 0)
+ return ret;
+
+ /* boot/wdog status */
+ ret = si2165_readreg8(state, 0x0341, val);
+ if (ret < 0)
+ return ret;
+ ret = si2165_writereg8(state, 0x0341, 0x00);
+ if (ret < 0)
+ return ret;
+ /* reset all */
+ ret = si2165_writereg8(state, 0x00c0, 0x00);
+ if (ret < 0)
+ return ret;
+ /* gp_reg0 */
+ ret = si2165_writereg32(state, 0x0384, 0x00000000);
+ if (ret < 0)
+ return ret;
+ /* start_synchro */
+ ret = si2165_writereg8(state, 0x02e0, 0x01);
+ if (ret < 0)
+ return ret;
+ /* boot/wdog status */
+ ret = si2165_readreg8(state, 0x0341, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void si2165_release(struct dvb_frontend *fe)
+{
+ struct si2165_state *state = fe->demodulator_priv;
+
+ dprintk("%s: called\n", __func__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops si2165_ops = {
+ .info = {
+ .name = "Silicon Labs Si2165",
+ .caps = FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 |
+ FE_CAN_QAM_256 |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_MUTE_TS |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_RECOVER
+ },
+
+ .get_tune_settings = si2165_get_tune_settings,
+
+ .init = si2165_init,
+ .sleep = si2165_sleep,
+
+ .set_frontend = si2165_set_parameters,
+ .read_status = si2165_read_status,
+
+ .release = si2165_release,
+};
+
+struct dvb_frontend *si2165_attach(const struct si2165_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct si2165_state *state = NULL;
+ int n;
+ int io_ret;
+ u8 val;
+
+ if (config == NULL || i2c == NULL)
+ goto error;
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct si2165_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* setup the state */
+ state->i2c = i2c;
+ state->config = *config;
+
+ if (state->config.ref_freq_Hz < 4000000
+ || state->config.ref_freq_Hz > 27000000) {
+ dev_err(&state->i2c->dev, "%s: ref_freq of %d Hz not supported by this driver\n",
+ KBUILD_MODNAME, state->config.ref_freq_Hz);
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &si2165_ops,
+ sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
+ /* powerup */
+ io_ret = si2165_writereg8(state, 0x0000, state->config.chip_mode);
+ if (io_ret < 0)
+ goto error;
+
+ io_ret = si2165_readreg8(state, 0x0000, &val);
+ if (io_ret < 0)
+ goto error;
+ if (val != state->config.chip_mode)
+ goto error;
+
+ io_ret = si2165_readreg8(state, 0x0023 , &state->revcode);
+ if (io_ret < 0)
+ goto error;
+
+ io_ret = si2165_readreg8(state, 0x0118, &state->chip_type);
+ if (io_ret < 0)
+ goto error;
+
+ /* powerdown */
+ io_ret = si2165_writereg8(state, 0x0000, SI2165_MODE_OFF);
+ if (io_ret < 0)
+ goto error;
+
+ dev_info(&state->i2c->dev, "%s: hardware revision 0x%02x, chip type 0x%02x\n",
+ KBUILD_MODNAME, state->revcode, state->chip_type);
+
+ /* It is a guess that register 0x0118 (chip type?) can be used to
+ * differ between si2161, si2163 and si2165
+ * Only si2165 has been tested.
+ */
+ if (state->revcode == 0x03 && state->chip_type == 0x07) {
+ state->has_dvbt = true;
+ state->has_dvbc = true;
+ } else {
+ dev_err(&state->i2c->dev, "%s: Unsupported chip.\n",
+ KBUILD_MODNAME);
+ goto error;
+ }
+
+ n = 0;
+ if (state->has_dvbt) {
+ state->frontend.ops.delsys[n++] = SYS_DVBT;
+ strlcat(state->frontend.ops.info.name, " DVB-T",
+ sizeof(state->frontend.ops.info.name));
+ }
+ if (state->has_dvbc)
+ dev_warn(&state->i2c->dev, "%s: DVB-C is not yet supported.\n",
+ KBUILD_MODNAME);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(si2165_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Silicon Labs Si2165 DVB-C/-T Demodulator driver");
+MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(SI2165_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/si2165.h b/drivers/media/dvb-frontends/si2165.h
new file mode 100644
index 000000000000..efaa08123b92
--- /dev/null
+++ b/drivers/media/dvb-frontends/si2165.h
@@ -0,0 +1,62 @@
+/*
+ Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+ Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ References:
+ http://www.silabs.com/Support%20Documents/TechnicalDocs/Si2165-short.pdf
+*/
+
+#ifndef _DVB_SI2165_H
+#define _DVB_SI2165_H
+
+#include <linux/dvb/frontend.h>
+
+enum {
+ SI2165_MODE_OFF = 0x00,
+ SI2165_MODE_PLL_EXT = 0x20,
+ SI2165_MODE_PLL_XTAL = 0x21
+};
+
+struct si2165_config {
+ /* i2c addr
+ * possible values: 0x64,0x65,0x66,0x67 */
+ u8 i2c_addr;
+
+ /* external clock or XTAL */
+ u8 chip_mode;
+
+ /* frequency of external clock or xtal in Hz
+ * possible values: 4000000, 16000000, 20000000, 240000000, 27000000
+ */
+ u32 ref_freq_Hz;
+
+ /* invert the spectrum */
+ bool inversion;
+};
+
+#if IS_ENABLED(CONFIG_DVB_SI2165)
+struct dvb_frontend *si2165_attach(
+ const struct si2165_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *si2165_attach(
+ const struct si2165_config *config,
+ struct i2c_adapter *i2c)
+{
+ pr_warn("%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_SI2165 */
+
+#endif /* _DVB_SI2165_H */
diff --git a/drivers/media/dvb-frontends/si2165_priv.h b/drivers/media/dvb-frontends/si2165_priv.h
new file mode 100644
index 000000000000..d4cc93fe1096
--- /dev/null
+++ b/drivers/media/dvb-frontends/si2165_priv.h
@@ -0,0 +1,23 @@
+/*
+ Driver for Silicon Labs SI2165 DVB-C/-T Demodulator
+
+ Copyright (C) 2013-2014 Matthias Schwarzott <zzam@gentoo.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef _DVB_SI2165_PRIV
+#define _DVB_SI2165_PRIV
+
+#define SI2165_FIRMWARE "dvb-demod-si2165.fw"
+
+#endif /* _DVB_SI2165_PRIV */
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 2e3cdcfa0a67..8f81d979de30 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -95,20 +95,17 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
switch (c->delivery_system) {
case SYS_DVBT:
- cmd.args[0] = 0xa0;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\xa0\x01", 2);
cmd.wlen = 2;
cmd.rlen = 13;
break;
case SYS_DVBC_ANNEX_A:
- cmd.args[0] = 0x90;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x90\x01", 2);
cmd.wlen = 2;
cmd.rlen = 9;
break;
case SYS_DVBT2:
- cmd.args[0] = 0x50;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x50\x01", 2);
cmd.wlen = 2;
cmd.rlen = 14;
break;
@@ -144,6 +141,15 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
s->fe_status = *status;
+ if (*status & FE_HAS_LOCK) {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
+ } else {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
__func__, *status, cmd.rlen, cmd.args);
@@ -243,51 +249,23 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
@@ -295,124 +273,66 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
cmd.args[4] = delivery_system | bandwidth;
cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
+ /* set DVB-C symbol rate */
+ if (c->delivery_system == SYS_DVBC_ANNEX_A) {
+ memcpy(cmd.args, "\x14\x00\x02\x11", 4);
+ cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
+ cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+ cmd.wlen = 6;
+ cmd.rlen = 4;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+ }
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0x85;
+ memcpy(cmd.args, "\x85", 1);
cmd.wlen = 1;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@@ -432,59 +352,61 @@ static int si2168_init(struct dvb_frontend *fe)
struct si2168 *s = fe->demodulator_priv;
int ret, len, remaining;
const struct firmware *fw = NULL;
- u8 *fw_file = SI2168_FIRMWARE;
+ u8 *fw_file;
const unsigned int i2c_wr_max = 8;
struct si2168_cmd cmd;
+ unsigned int chip_id;
dev_dbg(&s->client->dev, "%s:\n", __func__);
- cmd.args[0] = 0x13;
- cmd.wlen = 1;
- cmd.rlen = 0;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x12;
- cmd.args[2] = 0x00;
- cmd.args[3] = 0x0c;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x0d;
- cmd.args[6] = 0x16;
- cmd.args[7] = 0x00;
- cmd.args[8] = 0x00;
- cmd.args[9] = 0x00;
- cmd.args[10] = 0x00;
- cmd.args[11] = 0x00;
- cmd.args[12] = 0x00;
+ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
cmd.wlen = 13;
cmd.rlen = 0;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x06;
- cmd.args[2] = 0x01;
- cmd.args[3] = 0x0f;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x20;
- cmd.args[6] = 0x20;
- cmd.args[7] = 0x01;
+ memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
cmd.wlen = 8;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0x02;
+ /* query chip revision */
+ memcpy(cmd.args, "\x02", 1);
cmd.wlen = 1;
cmd.rlen = 13;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
+ chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+ cmd.args[4] << 0;
+
+ #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
+ #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
+ #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
+
+ switch (chip_id) {
+ case SI2168_A20:
+ fw_file = SI2168_A20_FIRMWARE;
+ break;
+ case SI2168_A30:
+ fw_file = SI2168_A30_FIRMWARE;
+ break;
+ case SI2168_B40:
+ fw_file = SI2168_B40_FIRMWARE;
+ break;
+ default:
+ dev_err(&s->client->dev,
+ "%s: unkown chip version Si21%d-%c%c%c\n",
+ KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+ cmd.args[3], cmd.args[4]);
+ ret = -EINVAL;
+ goto err;
+ }
+
/* cold state - try to download firmware */
dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
KBUILD_MODNAME, si2168_ops.info.name);
@@ -492,9 +414,22 @@ static int si2168_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, &s->client->dev);
if (ret) {
- dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
- KBUILD_MODNAME, fw_file);
- goto err;
+ /* fallback mechanism to handle old name for Si2168 B40 fw */
+ if (chip_id == SI2168_B40) {
+ fw_file = SI2168_B40_FIRMWARE_FALLBACK;
+ ret = request_firmware(&fw, fw_file, &s->client->dev);
+ }
+
+ if (ret == 0) {
+ dev_notice(&s->client->dev,
+ "%s: please install firmware file '%s'\n",
+ KBUILD_MODNAME, SI2168_B40_FIRMWARE);
+ } else {
+ dev_err(&s->client->dev,
+ "%s: firmware file '%s' not found\n",
+ KBUILD_MODNAME, fw_file);
+ goto err;
+ }
}
dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
@@ -520,8 +455,7 @@ static int si2168_init(struct dvb_frontend *fe)
release_firmware(fw);
fw = NULL;
- cmd.args[0] = 0x01;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x01\x01", 2);
cmd.wlen = 2;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@@ -545,12 +479,24 @@ err:
static int si2168_sleep(struct dvb_frontend *fe)
{
struct si2168 *s = fe->demodulator_priv;
+ int ret;
+ struct si2168_cmd cmd;
dev_dbg(&s->client->dev, "%s:\n", __func__);
s->active = false;
+ memcpy(cmd.args, "\x13", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 0;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
return 0;
+err:
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2168_get_tune_settings(struct dvb_frontend *fe,
@@ -660,7 +606,6 @@ static int si2168_probe(struct i2c_client *client,
struct si2168_config *config = client->dev.platform_data;
struct si2168 *s;
int ret;
- struct si2168_cmd cmd;
dev_dbg(&client->dev, "%s:\n", __func__);
@@ -674,18 +619,13 @@ static int si2168_probe(struct i2c_client *client,
s->client = client;
mutex_init(&s->i2c_mutex);
- /* check if the demod is there */
- cmd.wlen = 0;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
/* create mux i2c adapter for tuner */
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
0, 0, 0, si2168_select, si2168_deselect);
- if (s->adapter == NULL)
+ if (s->adapter == NULL) {
+ ret = -ENODEV;
goto err;
+ }
/* create dvb_frontend */
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
@@ -743,4 +683,6 @@ module_i2c_driver(si2168_driver);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(SI2168_FIRMWARE);
+MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
+MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
+MODULE_FIRMWARE(SI2168_B40_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index 53f7f06ae343..ebbf502ec313 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -22,7 +22,10 @@
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
-#define SI2168_FIRMWARE "dvb-demod-si2168-02.fw"
+#define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw"
+#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
+#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
+#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
/* state struct */
struct si2168 {
@@ -36,9 +39,9 @@ struct si2168 {
};
/* firmare command struct */
-#define SI2157_ARGLEN 30
+#define SI2168_ARGLEN 30
struct si2168_cmd {
- u8 args[SI2157_ARGLEN];
+ u8 args[SI2168_ARGLEN];
unsigned wlen;
unsigned rlen;
};
diff --git a/drivers/media/dvb-frontends/stb6100_cfg.h b/drivers/media/dvb-frontends/stb6100_cfg.h
index 6314d18c797a..6edc15365847 100644
--- a/drivers/media/dvb-frontends/stb6100_cfg.h
+++ b/drivers/media/dvb-frontends/stb6100_cfg.h
@@ -21,17 +21,14 @@
static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
- if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@@ -42,18 +39,16 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.frequency = frequency;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
+
if (tuner_ops->set_state) {
- if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@@ -68,12 +63,9 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
struct tuner_state t_state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
- if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@@ -84,18 +76,16 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.bandwidth = bandwidth;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
+
if (tuner_ops->set_state) {
- if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
diff --git a/drivers/media/dvb-frontends/stb6100_proc.h b/drivers/media/dvb-frontends/stb6100_proc.h
index 112163a48622..bd8a0ec9e2cc 100644
--- a/drivers/media/dvb-frontends/stb6100_proc.h
+++ b/drivers/media/dvb-frontends/stb6100_proc.h
@@ -19,15 +19,11 @@
static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -49,16 +45,13 @@ static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
state.frequency = frequency;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
+
if (tuner_ops->set_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -79,15 +72,11 @@ static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
@@ -109,16 +98,13 @@ static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state state;
int err = 0;
state.bandwidth = bandwidth;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
+
if (tuner_ops->set_state) {
if (frontend_ops->i2c_gate_ctrl)
frontend_ops->i2c_gate_ctrl(fe, 1);
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index 458772739423..59b6e661acc0 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -922,18 +922,13 @@ static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
u32 freq = 0;
int err = 0;
dprintk("%s:\n", __func__);
-
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_frequency) {
err = tuner_ops->get_frequency(fe, &freq);
if (err < 0) {
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c
index 2c54586ac07f..de0a1c110972 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd.c
+++ b/drivers/media/dvb-frontends/tda18271c2dd.c
@@ -1030,7 +1030,7 @@ static int ChannelConfiguration(struct tda_state *state,
state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
if ((Standard == HF_FM_Radio) && state->m_bFMInput)
- state->m_Regs[EP4] |= 80;
+ state->m_Regs[EP4] |= 0x80;
state->m_Regs[MPD] &= ~0x80;
if (Standard > HF_AnalogMax)
diff --git a/drivers/media/dvb-frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
index b87661b9df14..f3bca5c237d7 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd_maps.h
+++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
@@ -5,7 +5,7 @@ enum HF_S {
HF_DVBC_8MHZ, HF_DVBC
};
-struct SStandardParam m_StandardTable[] = {
+static struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_None */
{ 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */
{ 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */
@@ -27,7 +27,7 @@ struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */
};
-struct SMap m_BP_Filter_Map[] = {
+static struct SMap m_BP_Filter_Map[] = {
{ 62000000, 0x00 },
{ 84000000, 0x01 },
{ 100000000, 0x02 },
@@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = {
{ 865000000, 489500000, 697500000, 842000000},
};
-u8 m_Thermometer_Map_1[16] = {
+static u8 m_Thermometer_Map_1[16] = {
60, 62, 66, 64,
74, 72, 68, 70,
90, 88, 84, 86,
76, 78, 82, 80,
};
-u8 m_Thermometer_Map_2[16] = {
+static u8 m_Thermometer_Map_2[16] = {
92, 94, 98, 96,
106, 104, 100, 102,
122, 120, 116, 118,
diff --git a/drivers/media/dvb-frontends/tda8261_cfg.h b/drivers/media/dvb-frontends/tda8261_cfg.h
index 46710744173b..04a19e14ee5a 100644
--- a/drivers/media/dvb-frontends/tda8261_cfg.h
+++ b/drivers/media/dvb-frontends/tda8261_cfg.h
@@ -19,17 +19,14 @@
static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
- if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@@ -41,18 +38,16 @@ static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
- struct dvb_frontend_ops *frontend_ops = NULL;
- struct dvb_tuner_ops *tuner_ops = NULL;
+ struct dvb_frontend_ops *frontend_ops = &fe->ops;
+ struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
struct tuner_state t_state;
int err = 0;
t_state.frequency = frequency;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
+
if (tuner_ops->set_state) {
- if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+ err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
@@ -68,12 +63,9 @@ static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
struct tuner_state t_state;
int err = 0;
- if (&fe->ops)
- frontend_ops = &fe->ops;
- if (&frontend_ops->tuner_ops)
- tuner_ops = &frontend_ops->tuner_ops;
if (tuner_ops->get_state) {
- if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+ err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state);
+ if (err < 0) {
printk("%s: Invalid parameter\n", __func__);
return err;
}
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 441053be7f55..f40b4cf6107a 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -551,6 +551,7 @@ config VIDEO_MT9V032
tristate "Micron MT9V032 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
+ select REGMAP_I2C
---help---
This is a Video4Linux2 sensor-level driver for the Micron
MT9V032 752x480 CMOS sensor.
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index ac1cdbe251a3..821178dcb08e 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -663,7 +663,6 @@ static int adv7180_remove(struct i2c_client *client)
if (state->irq > 0)
free_irq(client->irq, state);
- v4l2_device_unregister_subdev(sd);
adv7180_exit_controls(state);
mutex_destroy(&state->mutex);
return 0;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 1778d320272e..d4fa213ba74a 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2588,8 +2588,11 @@ static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
};
static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+ /* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
- { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index c8fe1358ec9e..8311f1a9a38e 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -62,8 +62,8 @@ module_param(debug, int, 0644); /* debug level (0,1,2) */
/* ----------------------------------------------------------------------- */
-static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
- int size, int offset)
+static int get_key_haup_common(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *ptoggle, int size, int offset)
{
unsigned char buf[6];
int start, range, toggle, dev, code, ircode;
@@ -86,19 +86,10 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
if (!start)
/* no key pressed */
return 0;
- /*
- * Hauppauge remotes (black/silver) always use
- * specific device ids. If we do not filter the
- * device ids then messages destined for devices
- * such as TVs (id=0) will get through causing
- * mis-fired events.
- *
- * We also filter out invalid key presses which
- * produce annoying debug log entries.
- */
- ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
- if ((ircode & 0x1fff)==0x1fff)
- /* invalid key press */
+
+ /* filter out invalid key presses */
+ ircode = (start << 12) | (toggle << 11) | (dev << 6) | code;
+ if ((ircode & 0x1fff) == 0x1fff)
return 0;
if (!range)
@@ -107,18 +98,20 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
start, range, toggle, dev, code);
- /* return key */
- *ir_key = (dev << 8) | code;
- *ir_raw = ircode;
+ *protocol = RC_TYPE_RC5;
+ *scancode = RC_SCANCODE_RC5(dev, code);
+ *ptoggle = toggle;
return 1;
}
-static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
- return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+ return get_key_haup_common (ir, protocol, scancode, toggle, 3, 0);
}
-static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_haup_xvr(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
int ret;
unsigned char buf[1] = { 0 };
@@ -133,10 +126,11 @@ static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (ret != 1)
return (ret < 0) ? ret : -EINVAL;
- return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+ return get_key_haup_common(ir, protocol, scancode, toggle, 6, 3);
}
-static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pixelview(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
@@ -145,12 +139,15 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
dprintk(1,"read error\n");
return -EIO;
}
- *ir_key = b;
- *ir_raw = b;
+
+ *protocol = RC_TYPE_OTHER;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_fusionhdtv(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char buf[4];
@@ -168,13 +165,14 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if(buf[0] != 0x1 || buf[1] != 0xfe)
return 0;
- *ir_key = buf[2];
- *ir_raw = (buf[2] << 8) | buf[3];
-
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = buf[2];
+ *toggle = 0;
return 1;
}
-static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_knc1(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
@@ -197,13 +195,14 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
/* keep old data */
return 1;
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_avermedia_cardbus(struct IR_i2c *ir,
- u32 *ir_key, u32 *ir_raw)
+static int get_key_avermedia_cardbus(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char subaddr, key, keygroup;
struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
@@ -237,12 +236,11 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
}
key |= (keygroup & 1) << 6;
- *ir_key = key;
- *ir_raw = key;
- if (!strcmp(ir->ir_codes, RC_MAP_AVERMEDIA_M733A_RM_K6)) {
- *ir_key |= keygroup << 8;
- *ir_raw |= keygroup << 8;
- }
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = key;
+ if (ir->c->addr == 0x41) /* AVerMedia EM78P153 */
+ *scancode |= keygroup << 8;
+ *toggle = 0;
return 1;
}
@@ -250,19 +248,22 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
static int ir_key_poll(struct IR_i2c *ir)
{
- static u32 ir_key, ir_raw;
+ enum rc_type protocol;
+ u32 scancode;
+ u8 toggle;
int rc;
dprintk(3, "%s\n", __func__);
- rc = ir->get_key(ir, &ir_key, &ir_raw);
+ rc = ir->get_key(ir, &protocol, &scancode, &toggle);
if (rc < 0) {
dprintk(2,"error\n");
return rc;
}
if (rc) {
- dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
- rc_keydown(ir->rc, ir_key, 0);
+ dprintk(1, "%s: proto = 0x%04x, scancode = 0x%08x\n",
+ __func__, protocol, scancode);
+ rc_keydown(ir->rc, protocol, scancode, toggle);
}
return 0;
}
@@ -327,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
case 0x6b:
name = "FusionHDTV";
ir->get_key = get_key_fusionhdtv;
- rc_type = RC_BIT_RC5;
+ rc_type = RC_BIT_UNKNOWN;
ir_codes = RC_MAP_FUSIONHDTV_MCE;
break;
case 0x40:
@@ -431,8 +432,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
* Initialize the other fields of rc_dev
*/
rc->map_name = ir->ir_codes;
- rc_set_allowed_protocols(rc, rc_type);
- rc_set_enabled_protocols(rc, rc_type);
+ rc->allowed_protocols = rc_type;
+ rc->enabled_protocols = rc_type;
if (!rc->driver_name)
rc->driver_name = MODULE_NAME;
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 40172b8d8ea2..d044bce312e0 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -1,5 +1,5 @@
/*
- * Driver for MT9V032 CMOS Image Sensor from Micron
+ * Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
*
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
@@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/mutex.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
@@ -87,6 +88,7 @@
#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
+#define MT9V032_READ_MODE_RESERVED 0x0300
#define MT9V032_PIXEL_OPERATION_MODE 0x0f
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
@@ -133,8 +135,12 @@
#define MT9V032_THERMAL_INFO 0xc1
enum mt9v032_model {
- MT9V032_MODEL_V032_COLOR,
- MT9V032_MODEL_V032_MONO,
+ MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
+ MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
+ MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
+ MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
+ MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
+ MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
MT9V032_MODEL_V034_COLOR,
MT9V032_MODEL_V034_MONO,
};
@@ -160,14 +166,14 @@ struct mt9v032_model_info {
};
static const struct mt9v032_model_version mt9v032_versions[] = {
- { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
- { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
- { MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
+ { MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
+ { MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
+ { MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
};
static const struct mt9v032_model_data mt9v032_model_data[] = {
{
- /* MT9V032 revisions 1/2/3 */
+ /* MT9V022, MT9V032 revisions 1/2/3 */
.min_row_time = 660,
.min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
@@ -176,7 +182,7 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
.max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
.pclk_reg = MT9V032_PIXEL_CLOCK,
}, {
- /* MT9V034 */
+ /* MT9V024, MT9V034 */
.min_row_time = 690,
.min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
@@ -188,6 +194,22 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
};
static const struct mt9v032_model_info mt9v032_models[] = {
+ [MT9V032_MODEL_V022_COLOR] = {
+ .data = &mt9v032_model_data[0],
+ .color = true,
+ },
+ [MT9V032_MODEL_V022_MONO] = {
+ .data = &mt9v032_model_data[0],
+ .color = false,
+ },
+ [MT9V032_MODEL_V024_COLOR] = {
+ .data = &mt9v032_model_data[1],
+ .color = true,
+ },
+ [MT9V032_MODEL_V024_MONO] = {
+ .data = &mt9v032_model_data[1],
+ .color = false,
+ },
[MT9V032_MODEL_V032_COLOR] = {
.data = &mt9v032_model_data[0],
.color = true,
@@ -224,6 +246,7 @@ struct mt9v032 {
struct mutex power_lock;
int power_count;
+ struct regmap *regmap;
struct clk *clk;
struct mt9v032_platform_data *pdata;
@@ -231,7 +254,6 @@ struct mt9v032 {
const struct mt9v032_model_version *version;
u32 sysclk;
- u16 chip_control;
u16 aec_agc;
u16 hblank;
struct {
@@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
return container_of(sd, struct mt9v032, subdev);
}
-static int mt9v032_read(struct i2c_client *client, const u8 reg)
-{
- s32 data = i2c_smbus_read_word_swapped(client, reg);
- dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
- data, reg);
- return data;
-}
-
-static int mt9v032_write(struct i2c_client *client, const u8 reg,
- const u16 data)
-{
- dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
- data, reg);
- return i2c_smbus_write_word_swapped(client, reg, data);
-}
-
-static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
- u16 value = (mt9v032->chip_control & ~clear) | set;
- int ret;
-
- ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
- if (ret < 0)
- return ret;
-
- mt9v032->chip_control = value;
- return 0;
-}
-
static int
mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
u16 value = mt9v032->aec_agc;
int ret;
@@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
else
value &= ~which;
- ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
+ ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
if (ret < 0)
return ret;
@@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
static int
mt9v032_update_hblank(struct mt9v032 *mt9v032)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct v4l2_rect *crop = &mt9v032->crop;
unsigned int min_hblank = mt9v032->model->data->min_hblank;
unsigned int hblank;
if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
min_hblank += (mt9v032->hratio - 1) * 10;
- min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
- (int)min_hblank);
+ min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
+ min_hblank);
hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
- return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
+ return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
+ hblank);
}
static int mt9v032_power_on(struct mt9v032 *mt9v032)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
int ret;
ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
@@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
udelay(1);
/* Reset the chip and stop data read out */
- ret = mt9v032_write(client, MT9V032_RESET, 1);
+ ret = regmap_write(map, MT9V032_RESET, 1);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_RESET, 0);
+ ret = regmap_write(map, MT9V032_RESET, 0);
if (ret < 0)
return ret;
- return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
+ return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
}
static void mt9v032_power_off(struct mt9v032 *mt9v032)
@@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032)
static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
int ret;
if (!on) {
@@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
/* Configure the pixel clock polarity */
if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
- ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
+ ret = regmap_write(map, mt9v032->model->data->pclk_reg,
MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
if (ret < 0)
return ret;
}
/* Disable the noise correction algorithm and restore the controls. */
- ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
+ ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
if (ret < 0)
return ret;
@@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
| MT9V032_CHIP_CONTROL_DOUT_ENABLE
| MT9V032_CHIP_CONTROL_SEQUENTIAL;
- struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
struct v4l2_rect *crop = &mt9v032->crop;
+ struct regmap *map = mt9v032->regmap;
unsigned int hbin;
unsigned int vbin;
int ret;
if (!enable)
- return mt9v032_set_chip_control(mt9v032, mode, 0);
+ return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
/* Configure the window size and row/column bin */
hbin = fls(mt9v032->hratio) - 1;
vbin = fls(mt9v032->vratio) - 1;
- ret = mt9v032_write(client, MT9V032_READ_MODE,
- hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
- vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
+ ret = regmap_update_bits(map, MT9V032_READ_MODE,
+ ~MT9V032_READ_MODE_RESERVED,
+ hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
+ vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
+ ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
+ ret = regmap_write(map, MT9V032_ROW_START, crop->top);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
+ ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
+ ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
if (ret < 0)
return ret;
@@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
return ret;
/* Switch to master "normal" mode */
- return mt9v032_set_chip_control(mt9v032, 0, mode);
+ return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
}
static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct mt9v032 *mt9v032 =
container_of(ctrl->handler, struct mt9v032, ctrls);
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
u32 freq;
u16 data;
@@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
case V4L2_CID_GAIN:
- return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
+ return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
case V4L2_CID_EXPOSURE_AUTO:
return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
!ctrl->val);
case V4L2_CID_EXPOSURE:
- return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
- ctrl->val);
+ return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
+ ctrl->val);
case V4L2_CID_HBLANK:
mt9v032->hblank = ctrl->val;
return mt9v032_update_hblank(mt9v032);
case V4L2_CID_VBLANK:
- return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
- ctrl->val);
+ return regmap_write(map, MT9V032_VERTICAL_BLANKING,
+ ctrl->val);
case V4L2_CID_PIXEL_RATE:
case V4L2_CID_LINK_FREQ:
@@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
break;
freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
- mt9v032->pixel_rate->val64 = freq;
+ *mt9v032->pixel_rate->p_new.p_s64 = freq;
mt9v032->sysclk = freq;
break;
@@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
| MT9V032_TEST_PATTERN_FLIP;
break;
}
- return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
+ return regmap_write(map, MT9V032_TEST_PATTERN, data);
}
return 0;
@@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
unsigned int i;
- s32 version;
+ u32 version;
int ret;
dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
}
/* Read and check the sensor version */
- version = mt9v032_read(client, MT9V032_CHIP_VERSION);
- if (version < 0) {
+ ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
+ if (ret < 0) {
dev_err(&client->dev, "Failed reading chip version\n");
- return version;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
@@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
.close = mt9v032_close,
};
+static const struct regmap_config mt9v032_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0xff,
+ .cache_type = REGCACHE_RBTREE,
+};
+
/* -----------------------------------------------------------------------------
* Driver initialization and probing
*/
@@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_client *client,
if (!mt9v032)
return -ENOMEM;
+ mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
+ if (IS_ERR(mt9v032->regmap))
+ return PTR_ERR(mt9v032->regmap);
+
mt9v032->clk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(mt9v032->clk))
return PTR_ERR(mt9v032->clk);
@@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pixel_rate =
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (pdata && pdata->link_freqs) {
unsigned int def = 0;
@@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
+ if (ret < 0)
+ goto err;
+ mt9v032->subdev.dev = &client->dev;
+ ret = v4l2_async_register_subdev(&mt9v032->subdev);
if (ret < 0)
- v4l2_ctrl_handler_free(&mt9v032->ctrls);
+ goto err;
+ return 0;
+
+err:
+ media_entity_cleanup(&mt9v032->subdev.entity);
+ v4l2_ctrl_handler_free(&mt9v032->ctrls);
return ret;
}
@@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_client *client)
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+ v4l2_async_unregister_subdev(subdev);
v4l2_ctrl_handler_free(&mt9v032->ctrls);
v4l2_device_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity);
@@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_client *client)
}
static const struct i2c_device_id mt9v032_id[] = {
+ { "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
+ { "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
+ { "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
+ { "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
{ "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
{ "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
{ "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
index 271d0b7967a6..7eae48766e2b 100644
--- a/drivers/media/i2c/noon010pc30.c
+++ b/drivers/media/i2c/noon010pc30.c
@@ -554,6 +554,7 @@ static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
nf = noon010_try_fmt(sd, &fmt->format);
noon010_try_frame_size(&fmt->format, &size);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+ fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index 2750de634270..1fcc76fd1bbf 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -594,6 +594,7 @@ static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
pf = s5k4ecgx_try_fmt(sd, &fmt->format);
s5k4ecgx_try_frame_size(&fmt->format, &fsize);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+ fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 2d768ef67cc5..564f05f2c9ef 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -1313,6 +1313,8 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
const struct s5k5baf_pixfmt *pixfmt;
int ret = 0;
+ mf->field = V4L2_FIELD_NONE;
+
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
return 0;
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index 7bc2271ca009..c11a40850ed1 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -115,6 +115,7 @@ static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
fmt = find_sensor_format(mf);
mf->code = fmt->code;
+ mf->field = V4L2_FIELD_NONE;
v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
S5K6A3_SENSOR_MAX_WIDTH, 0,
&mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 06fb03291d59..1eaf975d3612 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
if (rval < 0)
return rval;
- sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
- sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
+ *sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz;
+ *sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi;
return 0;
}
@@ -533,7 +533,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_parray = v4l2_ctrl_new_std(
&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->pixel_array->ctrl_handler.error) {
dev_err(&client->dev,
@@ -562,7 +562,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->src->ctrl_handler.error) {
dev_err(&client->dev,
@@ -1554,6 +1554,7 @@ static int __smiapp_get_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width = r->width;
fmt->format.height = r->height;
+ fmt->format.field = V4L2_FIELD_NONE;
}
return 0;
@@ -1687,6 +1688,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width &= ~1;
fmt->format.height &= ~1;
+ fmt->format.field = V4L2_FIELD_NONE;
fmt->format.width =
clamp(fmt->format.width,
@@ -2544,9 +2546,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
}
snprintf(this->sd.name,
- sizeof(this->sd.name), "%s %d-%4.4x %s",
- sensor->minfo.name, i2c_adapter_id(client->adapter),
- client->addr, _this->name);
+ sizeof(this->sd.name), "%s %s %d-%4.4x",
+ sensor->minfo.name, _this->name,
+ i2c_adapter_id(client->adapter), client->addr);
this->sink_fmt.width =
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@@ -2674,6 +2676,7 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
try_fmt->code = mbus_code;
+ try_fmt->field = V4L2_FIELD_NONE;
try_crop->top = 0;
try_crop->left = 0;
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index df97033fa6ef..dbd8c142d6ef 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -403,7 +403,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
- data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+ data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -413,7 +413,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
/* Pack it into 1.125..15 variable step, register values 9..67 */
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
- unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+ unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
111 + range / 2) / range + 9;
if (gain <= 32)
@@ -434,7 +434,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned long range = exp->maximum - exp->minimum;
- unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
+ unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
dev_dbg(&client->dev,
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index ccf59406a172..b51e8562e775 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -931,6 +931,12 @@ static int mt9m111_probe(struct i2c_client *client,
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret;
+ if (client->dev.of_node) {
+ ssdd = devm_kzalloc(&client->dev, sizeof(*ssdd), GFP_KERNEL);
+ if (!ssdd)
+ return -ENOMEM;
+ client->dev.platform_data = ssdd;
+ }
if (!ssdd) {
dev_err(&client->dev, "mt9m111: driver needs platform data\n");
return -EINVAL;
@@ -1015,6 +1021,11 @@ static int mt9m111_remove(struct i2c_client *client)
return 0;
}
+static const struct of_device_id mt9m111_of_match[] = {
+ { .compatible = "micron,mt9m111", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt9m111_of_match);
static const struct i2c_device_id mt9m111_id[] = {
{ "mt9m111", 0 },
@@ -1025,6 +1036,7 @@ MODULE_DEVICE_TABLE(i2c, mt9m111_id);
static struct i2c_driver mt9m111_i2c_driver = {
.driver = {
.name = "mt9m111",
+ .of_match_table = of_match_ptr(mt9m111_of_match),
},
.probe = mt9m111_probe,
.remove = mt9m111_remove,
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index ee7bb0ffcecb..f8358c4071a9 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -474,7 +474,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
- data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+ data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@@ -485,7 +485,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
/* calculated gain: map 65..127 to 9..1024 step 0.125 */
- unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+ unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
1015 + range / 2) / range + 9;
if (gain <= 32) /* calculated gain 9..32 -> 9..32 */
@@ -507,7 +507,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned int range = exp->maximum - exp->minimum;
- unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+ unsigned int shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
u32 old;
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index f9f95f815b1a..99022c8d76eb 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -583,7 +583,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
/* mt9v022 has minimum == default */
unsigned long range = gain->maximum - gain->minimum;
/* Valid values 16 to 64, 32 to 64 must be even. */
- unsigned long gain_val = ((gain->val - gain->minimum) *
+ unsigned long gain_val = ((gain->val - (s32)gain->minimum) *
48 + range / 2) / range + 16;
if (gain_val >= 32)
@@ -608,7 +608,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
} else {
struct v4l2_ctrl *exp = mt9v022->exposure;
unsigned long range = exp->maximum - exp->minimum;
- unsigned long shutter = ((exp->val - exp->minimum) *
+ unsigned long shutter = ((exp->val - (s32)exp->minimum) *
479 + range / 2) / range + 1;
/*
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index a9121254e37a..193e7d6c29c8 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -56,38 +56,29 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
{
struct i2c_client *c = v4l2_get_subdevdata(sd);
- unsigned char buffer[1];
int rc;
- struct i2c_msg msg[] = {
- { .addr = c->addr, .flags = 0,
- .buf = &addr, .len = 1 },
- { .addr = c->addr, .flags = I2C_M_RD,
- .buf = buffer, .len = 1 }
- };
-
- rc = i2c_transfer(c->adapter, msg, 2);
- if (rc < 0 || rc != 2) {
- v4l2_err(sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
- return rc < 0 ? rc : -EIO;
+
+ rc = i2c_smbus_read_byte_data(c, addr);
+ if (rc < 0) {
+ v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
+ return rc;
}
- v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
+ v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, rc);
- return (buffer[0]);
+ return rc;
}
static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
unsigned char value)
{
struct i2c_client *c = v4l2_get_subdevdata(sd);
- unsigned char buffer[2];
int rc;
- buffer[0] = addr;
- buffer[1] = value;
- v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
- if (2 != (rc = i2c_master_send(c, buffer, 2)))
- v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
+ v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
+ rc = i2c_smbus_write_byte_data(c, addr, value);
+ if (rc < 0)
+ v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d\n", rc);
}
static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
@@ -1148,10 +1139,10 @@ static int tvp5150_probe(struct i2c_client *c,
/* Is TVP5150A */
if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
v4l2_info(sd, "tvp%02x%02xa detected.\n",
- tvp5150_id[2], tvp5150_id[3]);
+ tvp5150_id[0], tvp5150_id[1]);
} else {
v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
- tvp5150_id[2], tvp5150_id[3]);
+ tvp5150_id[0], tvp5150_id[1]);
v4l2_info(sd, "*** Rom ver is %d.%d\n",
tvp5150_id[2], tvp5150_id[3]);
}
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 88b97c9e64ac..73a432934bd8 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev,
if (ent->name) {
strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
u_ent.name[sizeof(u_ent.name) - 1] = '\0';
- } else {
- memset(u_ent.name, 0, sizeof(u_ent.name));
}
u_ent.type = ent->type;
u_ent.revision = ent->revision;
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
index 416507a83668..67b9da1dc43f 100644
--- a/drivers/media/parport/bw-qcam.c
+++ b/drivers/media/parport/bw-qcam.c
@@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
- pix->priv = 0;
return 0;
}
@@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
- pix->priv = 0;
return 0;
}
@@ -990,7 +988,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.fops = &qcam_fops;
qcam->vdev.lock = &qcam->lock;
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
- set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
qcam->vdev.release = video_device_release_empty;
video_set_drvdata(&qcam->vdev, qcam);
diff --git a/drivers/media/parport/c-qcam.c b/drivers/media/parport/c-qcam.c
index ec51e1f12e82..b9010bd3ed3e 100644
--- a/drivers/media/parport/c-qcam.c
+++ b/drivers/media/parport/c-qcam.c
@@ -761,7 +761,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
qcam->vdev.release = video_device_release_empty;
qcam->vdev.ctrl_handler = &qcam->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
video_set_drvdata(&qcam->vdev, qcam);
mutex_init(&qcam->lock);
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
index 66c957a02ba7..9bc105b3db1b 100644
--- a/drivers/media/parport/pms.c
+++ b/drivers/media/parport/pms.c
@@ -1091,7 +1091,6 @@ static int pms_probe(struct device *pdev, unsigned int card)
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
dev->std = V4L2_STD_NTSC_M;
dev->height = 240;
diff --git a/drivers/media/parport/w9966.c b/drivers/media/parport/w9966.c
index db2a6003a1c3..f7502f3a6a3c 100644
--- a/drivers/media/parport/w9966.c
+++ b/drivers/media/parport/w9966.c
@@ -883,7 +883,6 @@ static int w9966_init(struct w9966 *cam, struct parport *port)
cam->vdev.ioctl_ops = &w9966_ioctl_ops;
cam->vdev.release = video_device_release_empty;
cam->vdev.ctrl_handler = &cam->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
video_set_drvdata(&cam->vdev, cam);
mutex_init(&cam->lock);
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 53196f1366f3..5c16c9c2203e 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -19,6 +19,7 @@ if MEDIA_ANALOG_TV_SUPPORT
source "drivers/media/pci/ivtv/Kconfig"
source "drivers/media/pci/zoran/Kconfig"
source "drivers/media/pci/saa7146/Kconfig"
+source "drivers/media/pci/solo6x10/Kconfig"
endif
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 35cc57862c01..e5b53fb569ef 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
obj-$(CONFIG_VIDEO_MEYE) += meye/
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
+obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c
index d0c281f41a0a..11765835d7b2 100644
--- a/drivers/media/pci/bt8xx/bt878.c
+++ b/drivers/media/pci/bt8xx/bt878.c
@@ -101,28 +101,20 @@ static int bt878_mem_alloc(struct bt878 *bt)
if (!bt->buf_cpu) {
bt->buf_size = 128 * 1024;
- bt->buf_cpu =
- pci_alloc_consistent(bt->dev, bt->buf_size,
- &bt->buf_dma);
-
+ bt->buf_cpu = pci_zalloc_consistent(bt->dev, bt->buf_size,
+ &bt->buf_dma);
if (!bt->buf_cpu)
return -ENOMEM;
-
- memset(bt->buf_cpu, 0, bt->buf_size);
}
if (!bt->risc_cpu) {
bt->risc_size = PAGE_SIZE;
- bt->risc_cpu =
- pci_alloc_consistent(bt->dev, bt->risc_size,
- &bt->risc_dma);
-
+ bt->risc_cpu = pci_zalloc_consistent(bt->dev, bt->risc_size,
+ &bt->risc_dma);
if (!bt->risc_cpu) {
bt878_mem_free(bt);
return -ENOMEM;
}
-
- memset(bt->risc_cpu, 0, bt->risc_size);
}
return 0;
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index da780f42b121..970e542d3a51 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3886,7 +3886,6 @@ static struct video_device *vdev_init(struct bttv *btv,
vfd->v4l2_dev = &btv->c.v4l2_dev;
vfd->release = video_device_release;
vfd->debug = bttv_debug;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, btv);
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 5930bce16658..67c8d6b2c335 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv)
if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
(ir->mask_keyup && !(gpio & ir->mask_keyup))) {
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else {
/* HACK: Probably, ir->mask_keydown is missing
for this board */
if (btv->c.type == BTTV_BOARD_WINFAST2000)
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
@@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
gpio, data,
(gpio & ir->mask_keyup) ? " up" : "up/down");
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
if (keyup)
rc_keyup(ir->dev);
} else {
@@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
if (keyup)
rc_keyup(ir->dev);
else
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
}
ir->last_gpio = data | keyup;
@@ -154,10 +154,10 @@ static void bttv_input_timer(unsigned long data)
* testing.
*/
-#define RC5_START(x) (((x) >> 12) & 3)
-#define RC5_TOGGLE(x) (((x) >> 11) & 1)
-#define RC5_ADDR(x) (((x) >> 6) & 31)
-#define RC5_INSTR(x) ((x) & 63)
+#define RC5_START(x) (((x) >> 12) & 0x03)
+#define RC5_TOGGLE(x) (((x) >> 11) & 0x01)
+#define RC5_ADDR(x) (((x) >> 6) & 0x1f)
+#define RC5_INSTR(x) (((x) >> 0) & 0x3f)
/* decode raw bit pattern to RC5 code */
static u32 bttv_rc5_decode(unsigned int code)
@@ -195,8 +195,8 @@ static void bttv_rc5_timer_end(unsigned long data)
{
struct bttv_ir *ir = (struct bttv_ir *)data;
struct timeval tv;
- u32 gap;
- u32 rc5 = 0;
+ u32 gap, rc5, scancode;
+ u8 toggle, command, system;
/* get time */
do_gettimeofday(&tv);
@@ -221,26 +221,29 @@ static void bttv_rc5_timer_end(unsigned long data)
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
dprintk("short code: %x\n", ir->code);
- } else {
- ir->code = (ir->code << ir->shift_by) | 1;
- rc5 = bttv_rc5_decode(ir->code);
-
- /* two start bits? */
- if (RC5_START(rc5) != ir->start) {
- pr_info(DEVNAME ":"
- " rc5 start bits invalid: %u\n", RC5_START(rc5));
-
- /* right address? */
- } else if (RC5_ADDR(rc5) == ir->addr) {
- u32 toggle = RC5_TOGGLE(rc5);
- u32 instr = RC5_INSTR(rc5);
-
- /* Good code */
- rc_keydown(ir->dev, instr, toggle);
- dprintk("instruction %x, toggle %x\n",
- instr, toggle);
- }
+ return;
}
+
+ ir->code = (ir->code << ir->shift_by) | 1;
+ rc5 = bttv_rc5_decode(ir->code);
+
+ toggle = RC5_TOGGLE(rc5);
+ system = RC5_ADDR(rc5);
+ command = RC5_INSTR(rc5);
+
+ switch (RC5_START(rc5)) {
+ case 0x3:
+ break;
+ case 0x2:
+ command += 0x40;
+ break;
+ default:
+ return;
+ }
+
+ scancode = RC_SCANCODE_RC5(system, command);
+ rc_keydown(ir->dev, RC_TYPE_RC5, scancode, toggle);
+ dprintk("scancode %x, toggle %x\n", scancode, toggle);
}
static int bttv_rc5_irq(struct bttv *btv)
@@ -310,8 +313,6 @@ static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
/* set timer_end for code completion */
setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
ir->shift_by = 1;
- ir->start = 3;
- ir->addr = 0x0;
ir->rc5_remote_gap = ir_rc5_remote_gap;
}
}
@@ -335,7 +336,8 @@ static void bttv_ir_stop(struct bttv *btv)
* Get_key functions used by I2C remotes
*/
-static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pv951(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
@@ -362,8 +364,9 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* the device is bound to the vendor-provided RC.
*/
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
@@ -490,8 +493,8 @@ int bttv_input_init(struct bttv *btv)
ir->polling = 50; // ms
break;
case BTTV_BOARD_NEBULA_DIGITV:
- ir_codes = RC_MAP_NEBULA;
- ir->rc5_gpio = true;
+ ir_codes = RC_MAP_NEBULA;
+ ir->rc5_gpio = true;
break;
case BTTV_BOARD_MACHTV_MAGICTV:
ir_codes = RC_MAP_APAC_VIEWCOMP;
@@ -514,7 +517,8 @@ int bttv_input_init(struct bttv *btv)
ir->mask_keycode);
break;
}
- if (NULL == ir_codes) {
+
+ if (!ir_codes) {
dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
err = -ENODEV;
goto err_out_free;
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
index 6eefb595d0fa..9fe19488b30b 100644
--- a/drivers/media/pci/bt8xx/bttvp.h
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -133,8 +133,6 @@ struct bttv_ir {
u32 polling;
u32 last_gpio;
int shift_by;
- int start; // What should RC5_START() be
- int addr; // What RC5_ADDR() should be.
int rc5_remote_gap;
/* RC5 gpio */
diff --git a/drivers/media/pci/cx18/cx18-alsa.h b/drivers/media/pci/cx18/cx18-alsa.h
index 447da374c9e8..2718be28bf5f 100644
--- a/drivers/media/pci/cx18/cx18-alsa.h
+++ b/drivers/media/pci/cx18/cx18-alsa.h
@@ -49,7 +49,6 @@ static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
}
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
-#define CX18_ALSA_DBGFLG_WARN (1 << 0)
#define CX18_ALSA_DBGFLG_INFO (1 << 1)
#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index fefb2cd35838..6f2b59042b73 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
pixfmt->height = cx->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = s->pixelformat;
pixfmt->sizeimage = s->vb_bytes_per_frame;
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index 843c62b2f482..f3541b5156ce 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -375,7 +375,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
s->video_dev->release = video_device_release;
s->video_dev->tvnorms = V4L2_STD_ALL;
s->video_dev->lock = &cx->serialize_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
cx18_set_funcs(s->video_dev);
return 0;
}
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
index d1dcb1d2e087..e12c006e6e2d 100644
--- a/drivers/media/pci/cx23885/Kconfig
+++ b/drivers/media/pci/cx23885/Kconfig
@@ -31,12 +31,14 @@ config VIDEO_CX23885
select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
---help---
This is a video4linux driver for Conexant 23885 based
TV cards.
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 95666eee7b27..bf89fc88692e 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1266,7 +1266,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
- if (UNSET == dev->tuner_type)
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1284,7 +1284,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
- if (UNSET == dev->tuner_type)
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
/* Update the A/V core */
@@ -1299,7 +1299,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
- if (UNSET == dev->tuner_type)
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = dev->freq;
@@ -1347,7 +1347,7 @@ static int vidioc_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
0;
- if (UNSET != dev->tuner_type)
+ if (dev->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 79f20c8c842e..c2b608007190 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -619,7 +619,12 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR4400] = {
.name = "Hauppauge WinTV-HVR4400",
+ .porta = CX23885_ANALOG_VIDEO,
.portb = CX23885_MPEG_DVB,
+ .portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_NXP_TDA18271,
+ .tuner_addr = 0x60, /* 0xc0 >> 1 */
+ .tuner_bus = 1,
},
[CX23885_BOARD_AVERMEDIA_HC81R] = {
.name = "AVerTV Hybrid Express Slim HC81R",
@@ -649,7 +654,31 @@ struct cx23885_board cx23885_boards[] = {
CX25840_NONE1_CH3,
.amux = CX25840_AUDIO6,
} },
- }
+ },
+ [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2] = {
+ .name = "DViCO FusionHDTV DVB-T Dual Express2",
+ .portb = CX23885_MPEG_DVB,
+ .portc = CX23885_MPEG_DVB,
+ },
+ [CX23885_BOARD_HAUPPAUGE_IMPACTVCBE] = {
+ .name = "Hauppauge ImpactVCB-e",
+ .tuner_type = TUNER_ABSENT,
+ .porta = CX23885_ANALOG_VIDEO,
+ .input = {{
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN6_CH1,
+ .amux = CX25840_AUDIO7,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN8_CH1 |
+ CX25840_SVIDEO_ON,
+ .amux = CX25840_AUDIO7,
+ } },
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -897,6 +926,14 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x1461,
.subdevice = 0xd939,
.card = CX23885_BOARD_AVERMEDIA_HC81R,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x7133,
+ .card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE,
+ }, {
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb98,
+ .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -977,6 +1014,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 71009:
/* WinTV-HVR1200 (PCIe, Retail, full height)
* DVB-T and basic analog */
+ case 71100:
+ /* WinTV-ImpactVCB-e (PCIe, Retail, half height)
+ * Basic analog */
case 71359:
/* WinTV-HVR1200 (PCIe, OEM, half height)
* DVB-T and basic analog */
@@ -1137,6 +1177,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
/* Two identical tuners on two different i2c buses,
* we need to reset the correct gpio. */
if (port->nr == 1)
@@ -1280,6 +1321,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
cx_set(GP0_IO, 0x000f000f);
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
/* GPIO-0 portb xc3028 reset */
/* GPIO-1 portb zl10353 reset */
/* GPIO-2 portc xc3028 reset */
@@ -1449,13 +1491,16 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_HAUPPAUGE_HVR4400:
/* GPIO-8 tda10071 demod reset */
+ /* GPIO-9 si2165 demod reset */
/* Put the parts into reset and back */
- cx23885_gpio_enable(dev, GPIO_8, 1);
- cx23885_gpio_clear(dev, GPIO_8);
+ cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
+
+ cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
mdelay(100);
- cx23885_gpio_set(dev, GPIO_8);
+ cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
mdelay(100);
+
break;
case CX23885_BOARD_AVERMEDIA_HC81R:
cx_clear(MC417_CTL, 1);
@@ -1585,6 +1630,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
request_module("ir-kbd-i2c");
break;
}
@@ -1701,6 +1747,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR4400:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xc0);
break;
@@ -1720,6 +1767,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2:
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1799,6 +1847,9 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+ ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
@@ -1807,6 +1858,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
@@ -1835,6 +1887,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 4be01b3bd4f5..968fecc32f9c 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -44,6 +44,7 @@
#include "tuner-xc2028.h"
#include "tuner-simple.h"
#include "dib7000p.h"
+#include "dib0070.h"
#include "dibx000_common.h"
#include "zl10353.h"
#include "stv0900.h"
@@ -71,6 +72,7 @@
#include "tda10071.h"
#include "a8293.h"
#include "mb86a20s.h"
+#include "si2165.h"
static unsigned int debug;
@@ -302,6 +304,11 @@ static struct tda18271_config hauppauge_hvr1210_tuner_config = {
.output_opt = TDA18271_OUTPUT_LT_OFF,
};
+static struct tda18271_config hauppauge_hvr4400_tuner_config = {
+ .gate = TDA18271_GATE_DIGITAL,
+ .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
static struct tda18271_std_map hauppauge_hvr127x_std_map = {
.atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 4,
.if_lvl = 1, .rfagc_top = 0x58 },
@@ -702,6 +709,12 @@ static const struct a8293_config hauppauge_a8293_config = {
.i2c_addr = 0x0b,
};
+static const struct si2165_config hauppauge_hvr4400_si2165_config = {
+ .i2c_addr = 0x64,
+ .chip_mode = SI2165_MODE_PLL_XTAL,
+ .ref_freq_Hz = 16000000,
+};
+
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
{
struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -746,8 +759,108 @@ static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
return 0;
};
+static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+ struct dib7000p_ops *dib7000p_ops = fe->sec_priv;
+
+ return dib7000p_ops->set_gpio(fe, 8, 0, !onoff);
+}
+
+static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+ return 0;
+}
+
+static struct dib0070_config dib7070p_dib0070_config = {
+ .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+ .reset = dib7070_tuner_reset,
+ .sleep = dib7070_tuner_sleep,
+ .clock_khz = 12000,
+ .freq_offset_khz_vhf = 550,
+ /* .flip_chip = 1, */
+};
+
+/* DIB7070 generic */
+static struct dibx000_agc_config dib7070_agc_config = {
+ .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+
+ /*
+ * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
+ * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+ * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
+ */
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
+ (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+ .inv_gain = 600,
+ .time_stabiliz = 10,
+ .alpha_level = 0,
+ .thlock = 118,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
+ .agc1_max = 65535,
+ .agc1_min = 0,
+ .agc2_max = 65535,
+ .agc2_min = 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 40,
+ .agc1_pt3 = 183,
+ .agc1_slope1 = 206,
+ .agc1_slope2 = 255,
+ .agc2_pt1 = 72,
+ .agc2_pt2 = 152,
+ .agc2_slope1 = 88,
+ .agc2_slope2 = 90,
+ .alpha_mant = 17,
+ .alpha_exp = 27,
+ .beta_mant = 23,
+ .beta_exp = 51,
+ .perform_agc_softsplit = 0,
+};
+
+static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
+ .internal = 60000,
+ .sampling = 15000,
+ .pll_prediv = 1,
+ .pll_ratio = 20,
+ .pll_range = 3,
+ .pll_reset = 1,
+ .pll_bypass = 0,
+ .enable_refdiv = 0,
+ .bypclk_div = 0,
+ .IO_CLK_en_core = 1,
+ .ADClkSrc = 1,
+ .modulo = 2,
+ /* refsel, sel, freq_15k */
+ .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
+ .ifreq = (0 << 25) | 0,
+ .timf = 20452225,
+ .xtal_hz = 12000000,
+};
+
+static struct dib7000p_config dib7070p_dib7000p_config = {
+ /* .output_mode = OUTMODE_MPEG2_FIFO, */
+ .output_mode = OUTMODE_MPEG2_SERIAL,
+ /* .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, */
+ .output_mpeg2_in_188_bytes = 1,
+
+ .agc_config_count = 1,
+ .agc = &dib7070_agc_config,
+ .bw = &dib7070_bw_config_12_mhz,
+ .tuner_is_baseband = 1,
+ .spur_protect = 1,
+
+ .gpio_dir = 0xfcef, /* DIB7000P_GPIO_DEFAULT_DIRECTIONS, */
+ .gpio_val = 0x0110, /* DIB7000P_GPIO_DEFAULT_VALUES, */
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .hostbus_diversity = 1,
+};
+
static int dvb_register(struct cx23885_tsport *port)
{
+ struct dib7000p_ops dib7000p_ops;
struct cx23885_dev *dev = port->dev;
struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
@@ -925,8 +1038,11 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1400:
i2c_bus = &dev->i2c_bus[0];
- fe0->dvb.frontend = dvb_attach(dib7000p_attach,
- &i2c_bus->i2c_adap,
+
+ if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
+ return -ENODEV;
+
+ fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
0x12, &hauppauge_hvr1400_dib7000_config);
if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
@@ -989,6 +1105,30 @@ static int dvb_register(struct cx23885_tsport *port)
}
break;
}
+ case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2: {
+ i2c_bus = &dev->i2c_bus[port->nr - 1];
+ /* cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); */
+ /* cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); */
+
+ if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
+ return -ENODEV;
+
+ if (dib7000p_ops.i2c_enumeration(&i2c_bus->i2c_adap, 1, 0x12, &dib7070p_dib7000p_config) < 0) {
+ printk(KERN_WARNING "Unable to enumerate dib7000p\n");
+ return -ENODEV;
+ }
+ fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap, 0x80, &dib7070p_dib7000p_config);
+ if (fe0->dvb.frontend != NULL) {
+ struct i2c_adapter *tun_i2c;
+
+ fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL);
+ memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops));
+ tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1);
+ if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config))
+ return -ENODEV;
+ }
+ break;
+ }
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
@@ -1331,13 +1471,34 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR4400:
i2c_bus = &dev->i2c_bus[0];
- fe0->dvb.frontend = dvb_attach(tda10071_attach,
+ i2c_bus2 = &dev->i2c_bus[1];
+ switch (port->nr) {
+ /* port b */
+ case 1:
+ fe0->dvb.frontend = dvb_attach(tda10071_attach,
&hauppauge_tda10071_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend != NULL) {
- dvb_attach(a8293_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_a8293_config);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_a8293_config))
+ goto frontend_detach;
+ }
+ break;
+ /* port c */
+ case 2:
+ fe0->dvb.frontend = dvb_attach(si2165_attach,
+ &hauppauge_hvr4400_si2165_config,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = 0;
+ if (!dvb_attach(tda18271_attach,
+ fe0->dvb.frontend,
+ 0x60, &i2c_bus2->i2c_adap,
+ &hauppauge_hvr4400_tuner_config))
+ goto frontend_detach;
+ }
+ break;
}
break;
default:
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index 097d0a0b5f57..1940c18e186c 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
}
rc->dev.parent = &dev->pci->dev;
rc->driver_type = driver_type;
- rc_set_allowed_protocols(rc, allowed_protos);
+ rc->allowed_protocols = allowed_protos;
rc->priv = kernel_ir;
rc->open = cx23885_input_ir_open;
rc->close = cx23885_input_ir_close;
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index e0a59523cf3c..91e4cb457296 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -507,6 +507,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
(dev->board == CX23885_BOARD_MPX885) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+ (dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
@@ -1156,7 +1157,7 @@ static int vidioc_querycap(struct file *file, void *priv,
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE;
- if (UNSET != dev->tuner_type)
+ if (dev->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
@@ -1474,7 +1475,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- if (unlikely(UNSET == dev->tuner_type))
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1490,7 +1491,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- if (UNSET == dev->tuner_type)
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
@@ -1506,7 +1507,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = fh->dev;
- if (unlikely(UNSET == dev->tuner_type))
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
@@ -1522,7 +1523,7 @@ static int cx23885_set_freq(struct cx23885_dev *dev, const struct v4l2_frequency
{
struct v4l2_control ctrl;
- if (unlikely(UNSET == dev->tuner_type))
+ if (dev->tuner_type == TUNER_ABSENT)
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 0fa4048ab872..0e086c03da67 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -96,6 +96,8 @@
#define CX23885_BOARD_TBS_6981 40
#define CX23885_BOARD_TBS_6980 41
#define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
+#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE 43
+#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index d270819fd875..3a419f134584 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1109,7 +1106,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
else
vdev->vfl_dir = VFL_DIR_TX;
vdev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
video_set_drvdata(vdev, chan);
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index e061c88b697e..71630238027b 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -1045,7 +1045,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
return vfd;
}
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index f991696a6c59..3f1342c98b46 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -130,25 +130,41 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
data = (data << 4) | ((gpio_key & 0xf0) >> 4);
- rc_keydown(ir->dev, data, 0);
+ rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
+
+ } else if (ir->core->boardnr == CX88_BOARD_PROLINK_PLAYTVPVR ||
+ ir->core->boardnr == CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO) {
+ /* bit cleared on keydown, NEC scancode, 0xAAAACC, A = 0x866b */
+ u16 addr;
+ u8 cmd;
+ u32 scancode;
+
+ addr = (data >> 8) & 0xffff;
+ cmd = (data >> 0) & 0x00ff;
+ scancode = RC_SCANCODE_NECX(addr, cmd);
+
+ if (0 == (gpio & ir->mask_keyup))
+ rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
+ else
+ rc_keyup(ir->dev);
} else if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown)
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
else
rc_keyup(ir->dev);
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup))
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
else
rc_keyup(ir->dev);
} else {
/* can't distinguish keydown/up :-/ */
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
}
@@ -329,6 +345,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
* 002-T mini RC, provided with newer PV hardware
*/
ir_codes = RC_MAP_PIXELVIEW_MK12;
+ rc_type = RC_BIT_NEC;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keyup = 0x80;
ir->polling = 10; /* ms */
@@ -416,7 +433,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
break;
case CX88_BOARD_TWINHAN_VP1027_DVBS:
ir_codes = RC_MAP_TWINHAN_VP1027_DVBS;
- rc_type = RC_BIT_NEC;
ir->sampling = 0xff00; /* address */
break;
}
@@ -462,14 +478,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
dev->priv = core;
dev->open = cx88_ir_open;
dev->close = cx88_ir_close;
- dev->scanmask = hardware_mask;
+ dev->scancode_mask = hardware_mask;
if (ir->sampling) {
dev->driver_type = RC_DRIVER_IR_RAW;
dev->timeout = 10 * 1000 * 1000; /* 10 ms */
} else {
dev->driver_type = RC_DRIVER_SCANCODE;
- rc_set_allowed_protocols(dev, rc_type);
+ dev->allowed_protocols = rc_type;
}
ir->core = core;
@@ -539,7 +555,8 @@ void cx88_ir_irq(struct cx88_core *core)
ir_raw_event_handle(ir->dev);
}
-static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
int flags, code;
@@ -563,8 +580,9 @@ static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
code & 0xff, flags & 0xff);
- *ir_key = code & 0xff;
- *ir_raw = code;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = code & 0xff;
+ *toggle = 0;
return 1;
}
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index fb52bda8d45f..da8f848be3b8 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1663,11 +1663,40 @@ static struct ddb_info ddb_octopus_le = {
.port_num = 2,
};
+static struct ddb_info ddb_octopus_mini = {
+ .type = DDB_OCTOPUS,
+ .name = "Digital Devices Octopus Mini",
+ .port_num = 4,
+};
+
static struct ddb_info ddb_v6 = {
.type = DDB_OCTOPUS,
.name = "Digital Devices Cine S2 V6 DVB adapter",
.port_num = 3,
};
+static struct ddb_info ddb_v6_5 = {
+ .type = DDB_OCTOPUS,
+ .name = "Digital Devices Cine S2 V6.5 DVB adapter",
+ .port_num = 4,
+};
+
+static struct ddb_info ddb_dvbct = {
+ .type = DDB_OCTOPUS,
+ .name = "Digital Devices DVBCT V6.1 DVB adapter",
+ .port_num = 3,
+};
+
+static struct ddb_info ddb_satixS2v3 = {
+ .type = DDB_OCTOPUS,
+ .name = "Mystique SaTiX-S2 V3 DVB adapter",
+ .port_num = 3,
+};
+
+static struct ddb_info ddb_octopusv3 = {
+ .type = DDB_OCTOPUS,
+ .name = "Digital Devices Octopus V3 DVB adapter",
+ .port_num = 4,
+};
#define DDVID 0xdd01 /* Digital Devices Vendor ID */
@@ -1680,8 +1709,12 @@ static const struct pci_device_id ddb_id_tbl[] = {
DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
+ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
+ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
+ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
/* in case sub-ids got deleted in flash */
DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
{0}
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index e60ac35fc10c..e8826c535ccd 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -678,7 +678,8 @@ static void dm1105_emit_key(struct work_struct *work)
data = (ircom >> 8) & 0x7f;
- rc_keydown(ir->dev, data, 0);
+ /* FIXME: UNKNOWN because we don't generate a full NEC scancode (yet?) */
+ rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
}
/* work handler */
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
index c60424601cb9..2b0ab26e11e8 100644
--- a/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -135,8 +135,8 @@ static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
control cluster */
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
- return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
- &itv->ctrl_frame->val64);
+ return ivtv_g_pts_frame(itv, itv->ctrl_pts->p_new.p_s64,
+ itv->ctrl_frame->p_new.p_s64);
}
return 0;
}
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index ceed2d87abfd..1a41ba5c7d30 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -148,7 +148,8 @@ static const char * const hw_devicenames[] = {
"ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */
};
-static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_adaptec(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char keybuf[4];
@@ -167,9 +168,9 @@ static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
keybuf[2] &= 0x7f;
keybuf[3] |= 0x80;
- *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
- *ir_raw = *ir_key;
-
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
+ *toggle = 0;
return 1;
}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index b3667a00db3a..3e0cb77d5930 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->main_rect.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
case IVTV_YUV_MODE_INTERLACED:
@@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
fb->fmt.bytesperline = fb->fmt.width;
fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
fb->fmt.field = V4L2_FIELD_INTERLACED;
- fb->fmt.priv = 0;
if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
fb->fmt.bytesperline *= 2;
if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
index 70dad588a677..f0a1cc472313 100644
--- a/drivers/media/pci/ivtv/ivtv-streams.c
+++ b/drivers/media/pci/ivtv/ivtv-streams.c
@@ -251,7 +251,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
}
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;
}
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 54d5c821007c..aeae54708811 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1749,7 +1747,6 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
v4l2_ctrl_handler_setup(&meye.hdl);
meye.vdev->ctrl_handler = &meye.hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
video_nr) < 0) {
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index 970e83308525..4930b55fd5f4 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -910,7 +910,6 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
{
dma_addr_t tmp;
u32 i, j;
- int status = 0;
u32 SCListMemSize = pRingBuffer->NumBuffers
* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
NUM_SCATTER_GATHER_ENTRIES)
@@ -1010,14 +1009,12 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
}
- return status;
+ return 0;
}
static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
struct SRingBufferDescriptor *pRingBuffer)
{
- int status = 0;
-
/* Copy pointer to scatter gather list in TSRingbuffer
structure for buffer 2
Load number of buffer
@@ -1038,7 +1035,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
Cur = Cur->Next;
}
- return status;
+ return 0;
}
static u32 RingBufferSizes[MAX_STREAM] = {
@@ -1078,12 +1075,11 @@ static int AllocCommonBuffers(struct ngene *dev)
dev->ngenetohost = dev->FWInterfaceBuffer + 256;
dev->EventBuffer = dev->FWInterfaceBuffer + 512;
- dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev,
- OVERFLOW_BUFFER_SIZE,
- &dev->PAOverflowBuffer);
+ dev->OverflowBuffer = pci_zalloc_consistent(dev->pci_dev,
+ OVERFLOW_BUFFER_SIZE,
+ &dev->PAOverflowBuffer);
if (!dev->OverflowBuffer)
return -ENOMEM;
- memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE);
for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
int type = dev->card_info->io_type[i];
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index be19a051a492..9ff03a69ced4 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -811,7 +811,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
dev->name, type, saa7134_boards[dev->board].name);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, dev);
return vfd;
}
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 0006d6bf8c18..e4ea85fd1b23 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -270,7 +267,6 @@ static int empress_init(struct saa7134_dev *dev)
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
v4l2_ctrl_handler_init(hdl, 21);
v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
if (dev->empress_sd)
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 6f4312663bdf..dc3d6516edf7 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -83,14 +83,14 @@ static int build_key(struct saa7134_dev *dev)
if (data == ir->mask_keycode)
rc_keyup(ir->dev);
else
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
return 0;
}
if (ir->polling) {
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
} else {
rc_keyup(ir->dev);
}
@@ -98,7 +98,7 @@ static int build_key(struct saa7134_dev *dev)
else { /* IRQ driven mode - handle key press and release in one go */
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- rc_keydown_notimeout(ir->dev, data, 0);
+ rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
rc_keyup(ir->dev);
}
}
@@ -108,7 +108,8 @@ static int build_key(struct saa7134_dev *dev)
/* --------------------- Chip specific I2C key builders ----------------- */
-static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_flydvb_trio(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
int gpio;
int attempt = 0;
@@ -132,10 +133,6 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (0x40000 & ~gpio)
return 0; /* No button press */
- /* No button press - only before first key pressed */
- if (b == 0xFF)
- return 0;
-
/* poll IR chip */
/* weak up the IR chip */
b = 0;
@@ -158,13 +155,14 @@ static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return -EIO;
}
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
- u32 *ir_raw)
+static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
int gpio;
@@ -205,14 +203,15 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
/* Button pressed */
dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
/* copied and modified from get_key_msi_tvanywhere_plus() */
-static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
- u32 *ir_raw)
+static int get_key_kworld_pc150u(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
unsigned int gpio;
@@ -253,12 +252,14 @@ static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
/* Button pressed */
dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_purpletv(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char b;
@@ -276,12 +277,14 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (b & 0x80)
return 1;
- *ir_key = b;
- *ir_raw = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
+ *toggle = 0;
return 1;
}
-static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_hvr1110(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char buf[5];
@@ -299,14 +302,20 @@ static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* by preserving it into two separate readings
* buf[4] bits 0 and 1, and buf[1] and buf[2] are always
* zero.
+ *
+ * Note that the keymap which the hvr1110 uses is RC5.
+ *
+ * FIXME: start bits could maybe be used...?
*/
- *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
- *ir_raw = *ir_key;
+ *protocol = RC_TYPE_RC5;
+ *scancode = RC_SCANCODE_RC5(buf[3] & 0x1f, buf[4] >> 2);
+ *toggle = !!(buf[3] & 0x40);
return 1;
}
-static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_beholdm6xx(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
unsigned char data[12];
u32 gpio;
@@ -332,17 +341,18 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (data[9] != (unsigned char)(~data[8]))
return 0;
- *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
- *ir_key = *ir_raw;
-
+ *protocol = RC_TYPE_NEC;
+ *scancode = RC_SCANCODE_NECX(data[11] << 8 | data[10], data[9]);
+ *toggle = 0;
return 1;
}
/* Common (grey or coloured) pinnacle PCTV remote handling
*
*/
-static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
- int parity_offset, int marker, int code_modulo)
+static int get_key_pinnacle(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle, int parity_offset,
+ int marker, int code_modulo)
{
unsigned char b[4];
unsigned int start = 0,parity = 0,code = 0;
@@ -377,11 +387,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
code %= code_modulo;
- *ir_raw = code;
- *ir_key = code;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = code;
+ *toggle = 0;
i2cdprintk("Pinnacle PCTV key %02x\n", code);
-
return 1;
}
@@ -394,10 +404,11 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
*
* Sylvain Pasche <sylvain.pasche@gmail.com>
*/
-static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_grey(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
- return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
+ return get_key_pinnacle(ir, protocol, scancode, toggle, 1, 0xfe, 0xff);
}
@@ -405,7 +416,8 @@ static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
*
* Ricardo Cerqueira <v4l@cerqueira.org>
*/
-static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_color(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *scancode, u8 *toggle)
{
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
*
@@ -413,7 +425,7 @@ static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
* codes < 128
*/
- return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
+ return get_key_pinnacle(ir, protocol, scancode, toggle, 2, 0x80, 0x88);
}
void saa7134_input_irq(struct saa7134_dev *dev)
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index d37599980768..0cfa2ca6a32a 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
index 5c5cc3ebf9bd..16ae71592e8c 100644
--- a/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/drivers/media/pci/saa7164/saa7164-dvb.c
@@ -242,16 +242,14 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
- if (dvb) {
- mutex_lock(&dvb->lock);
- if (dvb->feeding++ == 0) {
- /* Start transport */
- ret = saa7164_dvb_start_port(port);
- }
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
+ mutex_lock(&dvb->lock);
+ if (dvb->feeding++ == 0) {
+ /* Start transport */
+ ret = saa7164_dvb_start_port(port);
}
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
return ret;
}
@@ -266,16 +264,14 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
- if (dvb) {
- mutex_lock(&dvb->lock);
- if (--dvb->feeding == 0) {
- /* Stop transport */
- ret = saa7164_dvb_stop_streaming(port);
- }
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
+ mutex_lock(&dvb->lock);
+ if (--dvb->feeding == 0) {
+ /* Stop transport */
+ ret = saa7164_dvb_stop_streaming(port);
}
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
return ret;
}
diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/media/pci/solo6x10/Kconfig
index 6a1906fa1117..d9e06a6bf1eb 100644
--- a/drivers/staging/media/solo6x10/Kconfig
+++ b/drivers/media/pci/solo6x10/Kconfig
@@ -1,6 +1,7 @@
-config SOLO6X10
+config VIDEO_SOLO6X10
tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
depends on PCI && VIDEO_DEV && SND && I2C
+ select BITREVERSE
select FONT_SUPPORT
select FONT_8x16
select VIDEOBUF2_DMA_SG
diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/media/pci/solo6x10/Makefile
index 7aae118947b2..f4742266ef7c 100644
--- a/drivers/staging/media/solo6x10/Makefile
+++ b/drivers/media/pci/solo6x10/Makefile
@@ -2,4 +2,4 @@ solo6x10-y := solo6x10-core.o solo6x10-i2c.o solo6x10-p2m.o solo6x10-v4l2.o \
solo6x10-tw28.o solo6x10-gpio.o solo6x10-disp.o solo6x10-enc.o \
solo6x10-v4l2-enc.o solo6x10-g723.o solo6x10-eeprom.o
-obj-$(CONFIG_SOLO6X10) += solo6x10.o
+obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10.o
diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c
index f67046955ef6..172583d736fe 100644
--- a/drivers/staging/media/solo6x10/solo6x10-core.c
+++ b/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -307,8 +303,8 @@ static ssize_t p2m_timeout_store(struct device *dev,
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned long ms;
-
int ret = kstrtoul(buf, 10, &ms);
+
if (ret < 0 || ms > 200)
return -EINVAL;
solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
diff --git a/drivers/staging/media/solo6x10/solo6x10-disp.c b/drivers/media/pci/solo6x10/solo6x10-disp.c
index 145295a5db72..5ea9cac03968 100644
--- a/drivers/staging/media/solo6x10/solo6x10-disp.c
+++ b/drivers/media/pci/solo6x10/solo6x10-disp.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -211,21 +207,25 @@ int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
}
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
- const struct solo_motion_thresholds *thresholds)
+ const u16 *thresholds)
{
+ const unsigned size = sizeof(u16) * 64;
u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
- u16 buf[64];
+ u16 *buf;
int x, y;
int ret = 0;
- memset(buf, 0, sizeof(buf));
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
for (y = 0; y < SOLO_MOTION_SZ; y++) {
for (x = 0; x < SOLO_MOTION_SZ; x++)
- buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
+ buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
ret |= solo_p2m_dma(solo_dev, 1, buf,
- SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
- sizeof(buf), 0, 0);
+ SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
+ size, 0, 0);
}
+ kfree(buf);
return ret;
}
diff --git a/drivers/staging/media/solo6x10/solo6x10-eeprom.c b/drivers/media/pci/solo6x10/solo6x10-eeprom.c
index 9d1c9bb53d6b..af40b3aba410 100644
--- a/drivers/staging/media/solo6x10/solo6x10-eeprom.c
+++ b/drivers/media/pci/solo6x10/solo6x10-eeprom.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-enc.c b/drivers/media/pci/solo6x10/solo6x10-enc.c
index 2db53b68c62f..d19c0aef5abc 100644
--- a/drivers/staging/media/solo6x10/solo6x10-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-enc.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 74f037b6166c..c7141f2e63bd 100644
--- a/drivers/staging/media/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-gpio.c b/drivers/media/pci/solo6x10/solo6x10-gpio.c
index 73276dc92875..6d3b4a36bc11 100644
--- a/drivers/staging/media/solo6x10/solo6x10-gpio.c
+++ b/drivers/media/pci/solo6x10/solo6x10-gpio.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-i2c.c b/drivers/media/pci/solo6x10/solo6x10-i2c.c
index 01aa417c9258..c908672b2c40 100644
--- a/drivers/staging/media/solo6x10/solo6x10-i2c.c
+++ b/drivers/media/pci/solo6x10/solo6x10-i2c.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/media/pci/solo6x10/solo6x10-jpeg.h
index c5218ceeabca..1c66a46da514 100644
--- a/drivers/staging/media/solo6x10/solo6x10-jpeg.h
+++ b/drivers/media/pci/solo6x10/solo6x10-jpeg.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_JPEG_H
@@ -110,7 +106,7 @@ static const unsigned char jpeg_header[] = {
/* This is the byte marker for the start of the DQT */
#define DQT_START 17
#define DQT_LEN 138
-const unsigned char jpeg_dqt[4][DQT_LEN] = {
+static const unsigned char jpeg_dqt[4][DQT_LEN] = {
{
0xff, 0xdb, 0x00, 0x43, 0x00,
0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
diff --git a/drivers/staging/media/solo6x10/solo6x10-offsets.h b/drivers/media/pci/solo6x10/solo6x10-offsets.h
index 13eeb4470dcf..d6aea7c2a676 100644
--- a/drivers/staging/media/solo6x10/solo6x10-offsets.h
+++ b/drivers/media/pci/solo6x10/solo6x10-offsets.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_OFFSETS_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-p2m.c b/drivers/media/pci/solo6x10/solo6x10-p2m.c
index 7f2f2472655b..8c8484674d2f 100644
--- a/drivers/staging/media/solo6x10/solo6x10-p2m.c
+++ b/drivers/media/pci/solo6x10/solo6x10-p2m.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-regs.h b/drivers/media/pci/solo6x10/solo6x10-regs.h
index 428f6c951180..e34ac56ab101 100644
--- a/drivers/staging/media/solo6x10/solo6x10-regs.h
+++ b/drivers/media/pci/solo6x10/solo6x10-regs.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_REGISTERS_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/media/pci/solo6x10/solo6x10-tw28.c
index 36daa1720b54..edd0781ee4b5 100644
--- a/drivers/staging/media/solo6x10/solo6x10-tw28.c
+++ b/drivers/media/pci/solo6x10/solo6x10-tw28.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -214,6 +210,7 @@ static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
for (i = 0; i < 5; i++) {
u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
+
if (rval == val)
return;
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.h b/drivers/media/pci/solo6x10/solo6x10-tw28.h
index 1a02c87d4cf0..0966b45057a3 100644
--- a/drivers/staging/media/solo6x10/solo6x10-tw28.h
+++ b/drivers/media/pci/solo6x10/solo6x10-tw28.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_TW28_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index b8ff113c20f4..28023f9f1dc7 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -243,6 +239,8 @@ static int solo_enc_on(struct solo_enc_dev *solo_enc)
if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
return -EBUSY;
solo_enc->sequence = 0;
+ solo_enc->motion_last_state = false;
+ solo_enc->frames_since_last_motion = 0;
solo_dev->enc_bw_remain -= solo_enc->bw_weight;
if (solo_enc->type == SOLO_ENC_TYPE_EXT)
@@ -476,8 +474,9 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
/* may discard all previous data in vbuf->sgl */
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
- DMA_FROM_DEVICE);
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
@@ -523,8 +522,9 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
/* may discard all previous data in vbuf->sgl */
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
- DMA_FROM_DEVICE);
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
@@ -544,15 +544,6 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
const vop_header *vh = enc_buf->vh;
int ret;
- /* Check for motion flags */
- vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON |
- V4L2_BUF_FLAG_MOTION_DETECTED);
- if (solo_is_motion_on(solo_enc)) {
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON;
- if (enc_buf->motion)
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
- }
-
switch (solo_enc->fmt) {
case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_H264:
@@ -564,9 +555,49 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
}
if (!ret) {
+ bool send_event = false;
+
vb->v4l2_buf.sequence = solo_enc->sequence++;
vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
+
+ /* Check for motion flags */
+ if (solo_is_motion_on(solo_enc)) {
+ /* It takes a few frames for the hardware to detect
+ * motion. Once it does it clears the motion detection
+ * register and it takes again a few frames before
+ * motion is seen. This means in practice that when the
+ * motion field is 1, it will go back to 0 for the next
+ * frame. This leads to motion detection event being
+ * sent all the time, which is not what we want.
+ * Instead wait a few frames before deciding that the
+ * motion has halted. After some experimentation it
+ * turns out that waiting for 5 frames works well.
+ */
+ if (enc_buf->motion == 0 &&
+ solo_enc->motion_last_state &&
+ solo_enc->frames_since_last_motion++ > 5)
+ send_event = true;
+ else if (enc_buf->motion) {
+ solo_enc->frames_since_last_motion = 0;
+ send_event = !solo_enc->motion_last_state;
+ }
+ }
+
+ if (send_event) {
+ struct v4l2_event ev = {
+ .type = V4L2_EVENT_MOTION_DET,
+ .u.motion_det = {
+ .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vb->v4l2_buf.sequence,
+ .region_mask = enc_buf->motion ? 1 : 0,
+ },
+ };
+
+ solo_enc->motion_last_state = enc_buf->motion;
+ solo_enc->frames_since_last_motion = 0;
+ v4l2_event_queue(solo_enc->vfd, &ev);
+ }
}
vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
@@ -669,6 +700,7 @@ static int solo_ring_thread(void *data)
for (;;) {
long timeout = schedule_timeout_interruptible(HZ);
+
if (timeout == -ERESTARTSYS || kthread_should_stop())
break;
solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
@@ -715,6 +747,7 @@ static int solo_ring_start(struct solo_dev *solo_dev)
SOLO6X10_NAME "_ring");
if (IS_ERR(solo_dev->ring_thread)) {
int err = PTR_ERR(solo_dev->ring_thread);
+
solo_dev->ring_thread = NULL;
return err;
}
@@ -1068,31 +1101,6 @@ static int solo_s_parm(struct file *file, void *priv,
return solo_g_parm(file, priv, sp);
}
-static long solo_enc_default(struct file *file, void *fh,
- bool valid_prio, unsigned int cmd, void *arg)
-{
- struct solo_enc_dev *solo_enc = video_drvdata(file);
- struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct solo_motion_thresholds *thresholds = arg;
-
- switch (cmd) {
- case SOLO_IOC_G_MOTION_THRESHOLDS:
- *thresholds = solo_enc->motion_thresholds;
- return 0;
-
- case SOLO_IOC_S_MOTION_THRESHOLDS:
- if (!valid_prio)
- return -EBUSY;
- solo_enc->motion_thresholds = *thresholds;
- if (solo_enc->motion_enabled && !solo_enc->motion_global)
- return solo_set_motion_block(solo_dev, solo_enc->ch,
- &solo_enc->motion_thresholds);
- return 0;
- default:
- return -ENOTTY;
- }
-}
-
static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct solo_enc_dev *solo_enc =
@@ -1110,30 +1118,43 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
solo_enc->gop = ctrl->val;
+ solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
+ solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
return 0;
- case V4L2_CID_MOTION_THRESHOLD:
- solo_enc->motion_thresh = ctrl->val;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ solo_enc->qp = ctrl->val;
+ solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
+ solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
+ return 0;
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
+ solo_enc->motion_thresh = ctrl->val << 8;
if (!solo_enc->motion_global || !solo_enc->motion_enabled)
return 0;
return solo_set_motion_threshold(solo_dev, solo_enc->ch,
- ctrl->val);
- case V4L2_CID_MOTION_MODE:
- solo_enc->motion_global = ctrl->val == 1;
- solo_enc->motion_enabled = ctrl->val > 0;
+ solo_enc->motion_thresh);
+ case V4L2_CID_DETECT_MD_MODE:
+ solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
+ solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
if (ctrl->val) {
if (solo_enc->motion_global)
- solo_set_motion_threshold(solo_dev,
- solo_enc->ch, solo_enc->motion_thresh);
+ err = solo_set_motion_threshold(solo_dev, solo_enc->ch,
+ solo_enc->motion_thresh);
else
- solo_set_motion_block(solo_dev, solo_enc->ch,
- &solo_enc->motion_thresholds);
+ err = solo_set_motion_block(solo_dev, solo_enc->ch,
+ solo_enc->md_thresholds->p_cur.p_u16);
+ if (err)
+ return err;
}
solo_motion_toggle(solo_enc, ctrl->val);
return 0;
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+ if (solo_enc->motion_enabled && !solo_enc->motion_global)
+ return solo_set_motion_block(solo_dev, solo_enc->ch,
+ solo_enc->md_thresholds->p_new.p_u16);
+ break;
case V4L2_CID_OSD_TEXT:
- strcpy(solo_enc->osd_text, ctrl->string);
- err = solo_osd_print(solo_enc);
- return err;
+ strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
+ return solo_osd_print(solo_enc);
default:
return -EINVAL;
}
@@ -1141,6 +1162,21 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
+static int solo_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(fh, sub);
+ case V4L2_EVENT_MOTION_DET:
+ /* Allow for up to 30 events (1 second for NTSC) to be
+ * stored. */
+ return v4l2_event_subscribe(fh, sub, 30, NULL);
+ }
+ return -EINVAL;
+}
+
static const struct v4l2_file_operations solo_enc_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
@@ -1179,9 +1215,8 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
.vidioc_g_parm = solo_g_parm,
/* Logging and events */
.vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_subscribe_event = solo_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
- .vidioc_default = solo_enc_default,
};
static const struct video_device solo_enc_template = {
@@ -1197,33 +1232,6 @@ static const struct v4l2_ctrl_ops solo_ctrl_ops = {
.s_ctrl = solo_s_ctrl,
};
-static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
- .ops = &solo_ctrl_ops,
- .id = V4L2_CID_MOTION_THRESHOLD,
- .name = "Motion Detection Threshold",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .max = 0xffff,
- .def = SOLO_DEF_MOT_THRESH,
- .step = 1,
- .flags = V4L2_CTRL_FLAG_SLIDER,
-};
-
-static const char * const solo_motion_mode_menu[] = {
- "Disabled",
- "Global Threshold",
- "Regional Threshold",
- NULL
-};
-
-static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
- .ops = &solo_ctrl_ops,
- .id = V4L2_CID_MOTION_MODE,
- .name = "Motion Detection Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .qmenu = solo_motion_mode_menu,
- .max = 2,
-};
-
static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
.ops = &solo_ctrl_ops,
.id = V4L2_CID_OSD_TEXT,
@@ -1233,13 +1241,22 @@ static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
.step = 1,
};
+/* Motion Detection Threshold matrix */
+static const struct v4l2_ctrl_config solo_md_thresholds = {
+ .ops = &solo_ctrl_ops,
+ .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
+ .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
+ .def = SOLO_DEF_MOT_THRESH,
+ .max = 65535,
+ .step = 1,
+};
+
static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
u8 ch, unsigned nr)
{
struct solo_enc_dev *solo_enc;
struct v4l2_ctrl_handler *hdl;
int ret;
- int x, y;
solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
if (!solo_enc)
@@ -1260,9 +1277,18 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
V4L2_CID_SHARPNESS, 0, 15, 1, 0);
v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
- v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
- v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
+ v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
+ v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
+ V4L2_CID_DETECT_MD_MODE,
+ V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
+ V4L2_DETECT_MD_MODE_DISABLED);
+ v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+ V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
+ SOLO_DEF_MOT_THRESH >> 8);
v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+ solo_enc->md_thresholds =
+ v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
if (hdl->error) {
ret = hdl->error;
goto hdl_free;
@@ -1283,11 +1309,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->mode = SOLO_ENC_MODE_CIF;
solo_enc->motion_global = true;
solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
- for (y = 0; y < SOLO_MOTION_SZ; y++)
- for (x = 0; x < SOLO_MOTION_SZ; x++)
- solo_enc->motion_thresholds.thresholds[y][x] =
- SOLO_DEF_MOT_THRESH;
-
solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
solo_enc->vidq.ops = &solo_enc_video_qops;
@@ -1326,7 +1347,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->vfd->ctrl_handler = hdl;
solo_enc->vfd->queue = &solo_enc->vidq;
solo_enc->vfd->lock = &solo_enc->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
video_set_drvdata(solo_enc->vfd, solo_enc);
ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
if (ret < 0)
@@ -1381,6 +1401,7 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
if (i != solo_dev->nr_chans) {
int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
+
while (i--)
solo_enc_free(solo_dev->v4l2_enc[i]);
pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 5d0100eb38e6..63ae8a61f603 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -98,6 +94,7 @@ static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
if (!on) {
u8 i;
+
for (i = ch; i < ch + 4; i++)
solo_win_setup(solo_dev, i, solo_dev->video_hsize,
solo_vlines(solo_dev),
@@ -206,6 +203,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
if (erase_off(solo_dev)) {
void *p = vb2_plane_vaddr(vb, 0);
int image_size = solo_image_size(solo_dev);
+
for (i = 0; i < image_size; i += 2) {
((u8 *)p)[i] = 0x80;
((u8 *)p)[i + 1] = 0x00;
@@ -275,6 +273,7 @@ static int solo_thread(void *data)
for (;;) {
long timeout = schedule_timeout_interruptible(HZ);
+
if (timeout == -ERESTARTSYS || kthread_should_stop())
break;
solo_thread_try(solo_dev);
@@ -414,6 +413,7 @@ static int solo_enum_input(struct file *file, void *priv,
if (input->index >= solo_dev->nr_chans) {
int ret = solo_enum_ext_input(solo_dev, input);
+
if (ret < 0)
return ret;
} else {
@@ -666,7 +666,6 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
goto fail;
}
solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
video_set_drvdata(solo_dev->vfd, solo_dev);
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 8964f8be158e..c6154b00fcbd 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_H
@@ -96,14 +92,7 @@
#define SOLO_DEFAULT_QP 3
-#ifndef V4L2_BUF_FLAG_MOTION_ON
-#define V4L2_BUF_FLAG_MOTION_ON 0x10000
-#define V4L2_BUF_FLAG_MOTION_DETECTED 0x20000
-#endif
-
#define SOLO_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
-#define V4L2_CID_MOTION_MODE (SOLO_CID_CUSTOM_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD (SOLO_CID_CUSTOM_BASE+1)
#define V4L2_CID_MOTION_TRACE (SOLO_CID_CUSTOM_BASE+2)
#define V4L2_CID_OSD_TEXT (SOLO_CID_CUSTOM_BASE+3)
@@ -113,19 +102,10 @@
* effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
* The 5th sample on the 10th row is (10*64)+5 = 645.
*
- * Using a 64x64 array will result in a problem on some architectures like
- * the powerpc where the size of the argument is limited to 13 bits.
- * Since both PAL and NTSC do not use the full table anyway I've chosen
- * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC
- * width).
+ * Internally it is stored as a 45x45 array (45*16 = 720, which is the
+ * maximum PAL/NTSC width).
*/
#define SOLO_MOTION_SZ (45)
-struct solo_motion_thresholds {
- __u16 thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
-};
-
-#define SOLO_IOC_G_MOTION_THRESHOLDS _IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
-#define SOLO_IOC_S_MOTION_THRESHOLDS _IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
enum SOLO_I2C_STATE {
IIC_STATE_IDLE,
@@ -168,6 +148,7 @@ struct solo_enc_dev {
struct solo_dev *solo_dev;
/* V4L2 Items */
struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *md_thresholds;
struct video_device *vfd;
/* General accounting */
struct mutex lock;
@@ -176,9 +157,10 @@ struct solo_enc_dev {
u8 mode, gop, qp, interlaced, interval;
u8 bw_weight;
u16 motion_thresh;
- struct solo_motion_thresholds motion_thresholds;
bool motion_global;
bool motion_enabled;
+ bool motion_last_state;
+ u8 frames_since_last_motion;
u16 width;
u16 height;
@@ -404,7 +386,7 @@ void solo_update_mode(struct solo_enc_dev *solo_enc);
/* Set the threshold for motion detection */
int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
- const struct solo_motion_thresholds *thresholds);
+ const u16 *thresholds);
#define SOLO_DEF_MOT_THRESH 0x0300
/* Write text on OSD */
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index d2abd3b5c2bf..365bd21301ba 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -640,7 +640,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1093,7 +1092,6 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev,
vip->video_dev = &video_dev_template;
vip->video_dev->v4l2_dev = &vip->v4l2_dev;
vip->video_dev->queue = &vip->vb_vidq;
- set_bit(V4L2_FL_USE_FH_PRIO, &vip->video_dev->flags);
video_set_drvdata(vip->video_dev, vip);
ret = video_register_device(vip->video_dev, VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
index 0acf9202103d..1feeeff3681b 100644
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ b/drivers/media/pci/ttpci/budget-ci.c
@@ -161,14 +161,14 @@ static void msp430_ir_interrupt(unsigned long data)
return;
if (budget_ci->ir.full_rc5) {
- rc_keydown(dev,
- budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
- (command & 0x20) ? 1 : 0);
+ rc_keydown(dev, RC_TYPE_RC5,
+ RC_SCANCODE_RC5(budget_ci->ir.rc5_device, budget_ci->ir.ir_key),
+ !!(command & 0x20));
return;
}
/* FIXME: We should generate complete scancodes for all devices */
- rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
+ rc_keydown(dev, RC_TYPE_UNKNOWN, budget_ci->ir.ir_key, !!(command & 0x20));
}
static int msp430_ir_init(struct budget_ci *budget_ci)
@@ -234,7 +234,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
break;
}
if (!budget_ci->ir.full_rc5)
- dev->scanmask = 0xff;
+ dev->scancode_mask = 0xff;
error = rc_register_device(dev);
if (error) {
diff --git a/drivers/media/pci/zoran/zr36050.h b/drivers/media/pci/zoran/zr36050.h
index 9f52f0cdde50..ea083adda045 100644
--- a/drivers/media/pci/zoran/zr36050.h
+++ b/drivers/media/pci/zoran/zr36050.h
@@ -126,7 +126,6 @@ struct zr36050 {
/* zr36050 mode register bits */
#define ZR050_MO_COMP 0x80
-#define ZR050_MO_COMP 0x80
#define ZR050_MO_ATP 0x40
#define ZR050_MO_PASS2 0x20
#define ZR050_MO_TLM 0x10
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 8108c698b548..6d86646d9743 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -96,6 +96,7 @@ config VIDEO_OMAP3
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
select ARM_DMA_USE_IOMMU
select OMAP_IOMMU
+ select VIDEOBUF2_DMA_CONTIG
---help---
Driver for an OMAP 3 camera controller.
@@ -142,6 +143,7 @@ config VIDEO_CODA
select SRAM
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
+ select GENERIC_ALLOCATOR
---help---
Coda is a range of video codec IPs that supports
H.264, MPEG-4, and other video formats.
@@ -165,12 +167,13 @@ config VIDEO_SAMSUNG_S5P_G2D
2d graphics accelerator.
config VIDEO_SAMSUNG_S5P_JPEG
- tristate "Samsung S5P/Exynos4 JPEG codec driver"
+ tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
depends on VIDEO_DEV && VIDEO_V4L2 && (PLAT_S5P || ARCH_EXYNOS)
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
---help---
- This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
+ This is a v4l2 driver for Samsung S5P, EXYNOS3250
+ and EXYNOS4 JPEG codec
config VIDEO_SAMSUNG_S5P_MFC
tristate "Samsung S5P MFC Video Codec"
diff --git a/drivers/media/platform/arv.c b/drivers/media/platform/arv.c
index e9410e41ae0c..03c5098499c4 100644
--- a/drivers/media/platform/arv.c
+++ b/drivers/media/platform/arv.c
@@ -773,7 +773,6 @@ static int __init ar_init(void)
ar->vdev.fops = &ar_fops;
ar->vdev.ioctl_ops = &ar_ioctl_ops;
ar->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &ar->vdev.flags);
video_set_drvdata(&ar->vdev, ar);
if (vga) {
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 16e4b1c525c4..9b5daa65841c 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -446,7 +446,7 @@ static void bcap_stop_streaming(struct vb2_queue *vq)
while (!list_empty(&bcap_dev->dma_queue)) {
bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
struct bcap_buffer, list);
- list_del(&bcap_dev->cur_frm->list);
+ list_del_init(&bcap_dev->cur_frm->list);
vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
}
}
@@ -533,7 +533,7 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
}
bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
struct bcap_buffer, list);
- list_del(&bcap_dev->cur_frm->list);
+ list_del_init(&bcap_dev->cur_frm->list);
} else {
/* clear error flag, we will get a new frame */
if (ppi->err)
@@ -583,7 +583,7 @@ static int bcap_streamon(struct file *file, void *priv,
bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
struct bcap_buffer, list);
/* remove buffer from the dma queue */
- list_del(&bcap_dev->cur_frm->list);
+ list_del_init(&bcap_dev->cur_frm->list);
addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
/* update DMA address */
ppi->ops->update_addr(ppi, (unsigned long)addr);
@@ -939,7 +939,7 @@ static int bcap_probe(struct platform_device *pdev)
bcap_dev->cfg = config;
- bcap_dev->ppi = ppi_create_instance(config->ppi_info);
+ bcap_dev->ppi = ppi_create_instance(pdev, config->ppi_info);
if (!bcap_dev->ppi) {
v4l2_err(pdev->dev.driver, "Unable to create ppi\n");
ret = -ENODEV;
@@ -966,7 +966,6 @@ static int bcap_probe(struct platform_device *pdev)
vfd->ioctl_ops = &bcap_ioctl_ops;
vfd->tvnorms = 0;
vfd->v4l2_dev = &bcap_dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name));
bcap_dev->video_dev = vfd;
diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c
index 15e9c2bac2b1..cff63e511e6d 100644
--- a/drivers/media/platform/blackfin/ppi.c
+++ b/drivers/media/platform/blackfin/ppi.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/platform_device.h>
#include <asm/bfin_ppi.h>
#include <asm/blackfin.h>
@@ -205,6 +206,20 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
int dma_config, bytes_per_line;
int hcount, hdelay, samples_per_line;
+#ifdef CONFIG_PINCTRL
+ static const char * const pin_state[] = {"8bit", "16bit", "24bit"};
+ struct pinctrl *pctrl;
+ struct pinctrl_state *pstate;
+
+ if (params->dlen > 24 || params->dlen <= 0)
+ return -EINVAL;
+ pctrl = devm_pinctrl_get(ppi->dev);
+ pstate = pinctrl_lookup_state(pctrl,
+ pin_state[(params->dlen + 7) / 8 - 1]);
+ if (pinctrl_select_state(pctrl, pstate))
+ return -EINVAL;
+#endif
+
bytes_per_line = params->width * params->bpp / 8;
/* convert parameters unit from pixels to samples */
hcount = params->width * params->bpp / params->dlen;
@@ -307,26 +322,30 @@ static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr)
set_dma_start_addr(ppi->info->dma_ch, addr);
}
-struct ppi_if *ppi_create_instance(const struct ppi_info *info)
+struct ppi_if *ppi_create_instance(struct platform_device *pdev,
+ const struct ppi_info *info)
{
struct ppi_if *ppi;
if (!info || !info->pin_req)
return NULL;
+#ifndef CONFIG_PINCTRL
if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) {
- pr_err("request peripheral failed\n");
+ dev_err(&pdev->dev, "request peripheral failed\n");
return NULL;
}
+#endif
ppi = kzalloc(sizeof(*ppi), GFP_KERNEL);
if (!ppi) {
peripheral_free_list(info->pin_req);
- pr_err("unable to allocate memory for ppi handle\n");
+ dev_err(&pdev->dev, "unable to allocate memory for ppi handle\n");
return NULL;
}
ppi->ops = &ppi_ops;
ppi->info = info;
+ ppi->dev = &pdev->dev;
pr_info("ppi probe success\n");
return ppi;
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
index b1783791d426..3a6d1d2b429e 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda.c
@@ -12,6 +12,7 @@
*/
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/genalloc.h>
@@ -22,10 +23,12 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/of.h>
#include <linux/platform_data/coda.h>
+#include <linux/reset.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -41,22 +44,18 @@
#define CODADX6_MAX_INSTANCES 4
-#define CODA_FMO_BUF_SIZE 32
-#define CODADX6_WORK_BUF_SIZE (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
-#define CODA7_WORK_BUF_SIZE (128 * 1024)
-#define CODA7_TEMP_BUF_SIZE (304 * 1024)
#define CODA_PARA_BUF_SIZE (10 * 1024)
#define CODA_ISRAM_SIZE (2048 * 2)
-#define CODADX6_IRAM_SIZE 0xb000
-#define CODA7_IRAM_SIZE 0x14000
#define CODA7_PS_BUF_SIZE 0x28000
+#define CODA9_PS_SAVE_SIZE (512 * 1024)
#define CODA_MAX_FRAMEBUFFERS 8
#define CODA_MAX_FRAME_SIZE 0x100000
#define FMO_SLICE_SAVE_BUF_SIZE (32)
#define CODA_DEFAULT_GAMMA 4096
+#define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */
#define MIN_W 176
#define MIN_H 144
@@ -84,6 +83,7 @@ enum coda_inst_type {
enum coda_product {
CODA_DX6 = 0xf001,
CODA_7541 = 0xf012,
+ CODA_960 = 0xf020,
};
struct coda_fmt {
@@ -105,20 +105,26 @@ struct coda_devtype {
struct coda_codec *codecs;
unsigned int num_codecs;
size_t workbuf_size;
+ size_t tempbuf_size;
+ size_t iram_size;
};
/* Per-queue, driver-specific private data */
struct coda_q_data {
unsigned int width;
unsigned int height;
+ unsigned int bytesperline;
unsigned int sizeimage;
unsigned int fourcc;
+ struct v4l2_rect rect;
};
struct coda_aux_buf {
void *vaddr;
dma_addr_t paddr;
u32 size;
+ struct debugfs_blob_wrapper blob;
+ struct dentry *dentry;
};
struct coda_dev {
@@ -130,32 +136,38 @@ struct coda_dev {
void __iomem *regs_base;
struct clk *clk_per;
struct clk *clk_ahb;
+ struct reset_control *rstc;
struct coda_aux_buf codebuf;
struct coda_aux_buf tempbuf;
struct coda_aux_buf workbuf;
struct gen_pool *iram_pool;
- long unsigned int iram_vaddr;
- long unsigned int iram_paddr;
- unsigned long iram_size;
+ struct coda_aux_buf iram;
spinlock_t irqlock;
struct mutex dev_mutex;
struct mutex coda_mutex;
+ struct workqueue_struct *workqueue;
struct v4l2_m2m_dev *m2m_dev;
struct vb2_alloc_ctx *alloc_ctx;
struct list_head instances;
unsigned long instance_mask;
- struct delayed_work timeout;
+ struct dentry *debugfs_root;
};
struct coda_params {
u8 rot_mode;
u8 h264_intra_qp;
u8 h264_inter_qp;
+ u8 h264_min_qp;
+ u8 h264_max_qp;
+ u8 h264_deblk_enabled;
+ u8 h264_deblk_alpha;
+ u8 h264_deblk_beta;
u8 mpeg4_intra_qp;
u8 mpeg4_inter_qp;
u8 gop_size;
+ int intra_refresh;
int codec_mode;
int codec_mode_aux;
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
@@ -175,13 +187,34 @@ struct coda_iram_info {
phys_addr_t buf_btp_use;
phys_addr_t search_ram_paddr;
int search_ram_size;
+ int remaining;
+ phys_addr_t next_paddr;
+};
+
+struct gdi_tiled_map {
+ int xy2ca_map[16];
+ int xy2ba_map[16];
+ int xy2ra_map[16];
+ int rbc2axi_map[32];
+ int xy2rbc_config;
+ int map_type;
+#define GDI_LINEAR_FRAME_MAP 0
+};
+
+struct coda_timestamp {
+ struct list_head list;
+ u32 sequence;
+ struct v4l2_timecode timecode;
+ struct timeval timestamp;
};
struct coda_ctx {
struct coda_dev *dev;
struct mutex buffer_mutex;
struct list_head list;
- struct work_struct skip_run;
+ struct work_struct pic_run_work;
+ struct work_struct seq_end_work;
+ struct completion completion;
int aborting;
int initialized;
int streamon_out;
@@ -189,12 +222,12 @@ struct coda_ctx {
u32 isequence;
u32 qsequence;
u32 osequence;
+ u32 sequence_offset;
struct coda_q_data q_data[2];
enum coda_inst_type inst_type;
struct coda_codec *codec;
enum v4l2_colorspace colorspace;
struct coda_params params;
- struct v4l2_m2m_ctx *m2m_ctx;
struct v4l2_ctrl_handler ctrls;
struct v4l2_fh fh;
int gopcounter;
@@ -204,19 +237,26 @@ struct coda_ctx {
struct kfifo bitstream_fifo;
struct mutex bitstream_mutex;
struct coda_aux_buf bitstream;
- bool prescan_failed;
+ bool hold;
struct coda_aux_buf parabuf;
struct coda_aux_buf psbuf;
struct coda_aux_buf slicebuf;
struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS];
+ u32 frame_types[CODA_MAX_FRAMEBUFFERS];
+ struct coda_timestamp frame_timestamps[CODA_MAX_FRAMEBUFFERS];
+ u32 frame_errors[CODA_MAX_FRAMEBUFFERS];
+ struct list_head timestamp_list;
struct coda_aux_buf workbuf;
int num_internal_frames;
int idx;
int reg_idx;
struct coda_iram_info iram_info;
+ struct gdi_tiled_map tiled_map;
u32 bit_stream_param;
u32 frm_dis_flg;
+ u32 frame_mem_ctrl;
int display_idx;
+ struct dentry *debugfs_entry;
};
static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
@@ -264,15 +304,23 @@ static void coda_command_async(struct coda_ctx *ctx, int cmd)
{
struct coda_dev *dev = ctx->dev;
- if (dev->devtype->product == CODA_7541) {
+ if (dev->devtype->product == CODA_960 ||
+ dev->devtype->product == CODA_7541) {
/* Restore context related registers to CODA */
coda_write(dev, ctx->bit_stream_param,
CODA_REG_BIT_BIT_STREAM_PARAM);
coda_write(dev, ctx->frm_dis_flg,
CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+ coda_write(dev, ctx->frame_mem_ctrl,
+ CODA_REG_BIT_FRAME_MEM_CTRL);
coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR);
}
+ if (dev->devtype->product == CODA_960) {
+ coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
+ coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+ }
+
coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
@@ -290,6 +338,39 @@ static int coda_command_sync(struct coda_ctx *ctx, int cmd)
return coda_wait_timeout(dev);
}
+static int coda_hw_reset(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ unsigned long timeout;
+ unsigned int idx;
+ int ret;
+
+ if (!dev->rstc)
+ return -ENOENT;
+
+ idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+ coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
+ while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
+ if (time_after(jiffies, timeout))
+ return -ETIME;
+ cpu_relax();
+ }
+
+ ret = reset_control_reset(dev->rstc);
+ if (ret < 0)
+ return ret;
+
+ coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
+ coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+ coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
+ ret = coda_wait_timeout(dev);
+ coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
+
+ return ret;
+}
+
static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
enum v4l2_buf_type type)
{
@@ -299,9 +380,8 @@ static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
return &(ctx->q_data[V4L2_M2M_DST]);
default:
- BUG();
+ return NULL;
}
- return NULL;
}
/*
@@ -348,6 +428,13 @@ static struct coda_codec coda7_codecs[] = {
CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080),
};
+static struct coda_codec coda9_codecs[] = {
+ CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1080),
+ CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1080),
+ CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1080),
+ CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1080),
+};
+
static bool coda_format_is_yuv(u32 fourcc)
{
switch (fourcc) {
@@ -426,6 +513,8 @@ static char *coda_product_name(int product)
return "CodaDx6";
case CODA_7541:
return "CODA7541";
+ case CODA_960:
+ return "CODA960";
default:
snprintf(buf, sizeof(buf), "(0x%04x)", product);
return buf;
@@ -515,7 +604,7 @@ static int coda_enum_fmt_vid_cap(struct file *file, void *priv,
struct coda_q_data *q_data_src;
/* If the source format is already fixed, only list matching formats */
- src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) {
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
@@ -535,24 +624,18 @@ static int coda_enum_fmt_vid_out(struct file *file, void *priv,
static int coda_g_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct vb2_queue *vq;
struct coda_q_data *q_data;
struct coda_ctx *ctx = fh_to_ctx(priv);
- vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
- if (!vq)
- return -EINVAL;
-
q_data = get_q_data(ctx, f->type);
+ if (!q_data)
+ return -EINVAL;
f->fmt.pix.field = V4L2_FIELD_NONE;
f->fmt.pix.pixelformat = q_data->fourcc;
f->fmt.pix.width = q_data->width;
f->fmt.pix.height = q_data->height;
- if (coda_format_is_yuv(f->fmt.pix.pixelformat))
- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2);
- else /* encoded formats h.264/mpeg4 */
- f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.bytesperline = q_data->bytesperline;
f->fmt.pix.sizeimage = q_data->sizeimage;
f->fmt.pix.colorspace = ctx->colorspace;
@@ -592,14 +675,16 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec,
break;
default:
q_data = get_q_data(ctx, f->type);
+ if (!q_data)
+ return -EINVAL;
f->fmt.pix.pixelformat = q_data->fourcc;
}
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- /* Frame stride must be multiple of 8 */
- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8);
+ /* Frame stride must be multiple of 8, but 16 for h.264 */
+ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
f->fmt.pix.height * 3 / 2;
break;
@@ -613,8 +698,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec,
BUG();
}
- f->fmt.pix.priv = 0;
-
return 0;
}
@@ -630,7 +713,7 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
* If the source format is already fixed, try to find a codec that
* converts to the given destination format
*/
- src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) {
struct coda_q_data *q_data_src;
@@ -653,9 +736,9 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
/* The h.264 decoder only returns complete 16x16 macroblocks */
if (codec && codec->src_fourcc == V4L2_PIX_FMT_H264) {
- f->fmt.pix.width = round_up(f->fmt.pix.width, 16);
+ f->fmt.pix.width = f->fmt.pix.width;
f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
- f->fmt.pix.bytesperline = f->fmt.pix.width;
+ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
f->fmt.pix.height * 3 / 2;
}
@@ -684,7 +767,7 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
struct coda_q_data *q_data;
struct vb2_queue *vq;
- vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
if (!vq)
return -EINVAL;
@@ -700,7 +783,12 @@ static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
q_data->fourcc = f->fmt.pix.pixelformat;
q_data->width = f->fmt.pix.width;
q_data->height = f->fmt.pix.height;
+ q_data->bytesperline = f->fmt.pix.bytesperline;
q_data->sizeimage = f->fmt.pix.sizeimage;
+ q_data->rect.left = 0;
+ q_data->rect.top = 0;
+ q_data->rect.width = f->fmt.pix.width;
+ q_data->rect.height = f->fmt.pix.height;
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
@@ -739,36 +827,12 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv,
return ret;
}
-static int coda_reqbufs(struct file *file, void *priv,
- struct v4l2_requestbuffers *reqbufs)
-{
- struct coda_ctx *ctx = fh_to_ctx(priv);
-
- return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int coda_querybuf(struct file *file, void *priv,
- struct v4l2_buffer *buf)
-{
- struct coda_ctx *ctx = fh_to_ctx(priv);
-
- return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
static int coda_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct coda_ctx *ctx = fh_to_ctx(priv);
- return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int coda_expbuf(struct file *file, void *priv,
- struct v4l2_exportbuffer *eb)
-{
- struct coda_ctx *ctx = fh_to_ctx(priv);
-
- return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
+ return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf);
}
static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
@@ -776,7 +840,7 @@ static bool coda_buf_is_end_of_stream(struct coda_ctx *ctx,
{
struct vb2_queue *src_vq;
- src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
return ((ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) &&
(buf->sequence == (ctx->qsequence - 1)));
@@ -788,7 +852,7 @@ static int coda_dqbuf(struct file *file, void *priv,
struct coda_ctx *ctx = fh_to_ctx(priv);
int ret;
- ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf);
/* If this is the last capture buffer, emit an end-of-stream event */
if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
@@ -803,38 +867,48 @@ static int coda_dqbuf(struct file *file, void *priv,
return ret;
}
-static int coda_create_bufs(struct file *file, void *priv,
- struct v4l2_create_buffers *create)
+static int coda_g_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
{
- struct coda_ctx *ctx = fh_to_ctx(priv);
-
- return v4l2_m2m_create_bufs(file, ctx->m2m_ctx, create);
-}
-
-static int coda_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct coda_ctx *ctx = fh_to_ctx(priv);
+ struct coda_ctx *ctx = fh_to_ctx(fh);
+ struct coda_q_data *q_data;
+ struct v4l2_rect r, *rsel;
- return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
+ q_data = get_q_data(ctx, s->type);
+ if (!q_data)
+ return -EINVAL;
-static int coda_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct coda_ctx *ctx = fh_to_ctx(priv);
- int ret;
+ r.left = 0;
+ r.top = 0;
+ r.width = q_data->width;
+ r.height = q_data->height;
+ rsel = &q_data->rect;
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ rsel = &r;
+ /* fallthrough */
+ case V4L2_SEL_TGT_CROP:
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+ break;
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
+ rsel = &r;
+ /* fallthrough */
+ case V4L2_SEL_TGT_COMPOSE:
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
- /*
- * This indirectly calls __vb2_queue_cancel, which dequeues all buffers.
- * We therefore have to lock it against running hardware in this context,
- * which still needs the buffers.
- */
- mutex_lock(&ctx->buffer_mutex);
- ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
- mutex_unlock(&ctx->buffer_mutex);
+ s->r = *rsel;
- return ret;
+ return 0;
}
static int coda_try_decoder_cmd(struct file *file, void *fh,
@@ -856,6 +930,7 @@ static int coda_decoder_cmd(struct file *file, void *fh,
struct v4l2_decoder_cmd *dc)
{
struct coda_ctx *ctx = fh_to_ctx(fh);
+ struct coda_dev *dev = ctx->dev;
int ret;
ret = coda_try_decoder_cmd(file, fh, dc);
@@ -869,6 +944,15 @@ static int coda_decoder_cmd(struct file *file, void *fh,
/* Set the strem-end flag on this context */
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+ if ((dev->devtype->product == CODA_960) &&
+ coda_isbusy(dev) &&
+ (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
+ /* If this context is currently running, update the hardware flag */
+ coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+ }
+ ctx->hold = false;
+ v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
+
return 0;
}
@@ -896,16 +980,18 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
.vidioc_try_fmt_vid_out = coda_try_fmt_vid_out,
.vidioc_s_fmt_vid_out = coda_s_fmt_vid_out,
- .vidioc_reqbufs = coda_reqbufs,
- .vidioc_querybuf = coda_querybuf,
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_qbuf = coda_qbuf,
- .vidioc_expbuf = coda_expbuf,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
.vidioc_dqbuf = coda_dqbuf,
- .vidioc_create_bufs = coda_create_bufs,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
- .vidioc_streamon = coda_streamon,
- .vidioc_streamoff = coda_streamoff,
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+ .vidioc_g_selection = coda_g_selection,
.vidioc_try_decoder_cmd = coda_try_decoder_cmd,
.vidioc_decoder_cmd = coda_decoder_cmd,
@@ -916,13 +1002,6 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
static int coda_start_decoding(struct coda_ctx *ctx);
-static void coda_skip_run(struct work_struct *work)
-{
- struct coda_ctx *ctx = container_of(work, struct coda_ctx, skip_run);
-
- v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
-}
-
static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
{
return kfifo_len(&ctx->bitstream_fifo);
@@ -975,7 +1054,7 @@ static int coda_bitstream_queue(struct coda_ctx *ctx, struct vb2_buffer *src_buf
dma_sync_single_for_device(&ctx->dev->plat_dev->dev, ctx->bitstream.paddr,
ctx->bitstream.size, DMA_TO_DEVICE);
- ctx->qsequence++;
+ src_buf->v4l2_buf.sequence = ctx->qsequence++;
return 0;
}
@@ -1003,7 +1082,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
coda_kfifo_sync_to_device_write(ctx);
- ctx->prescan_failed = false;
+ ctx->hold = false;
return true;
}
@@ -1011,12 +1090,26 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
static void coda_fill_bitstream(struct coda_ctx *ctx)
{
struct vb2_buffer *src_buf;
+ struct coda_timestamp *ts;
- while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) {
- src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
if (coda_bitstream_try_queue(ctx, src_buf)) {
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ /*
+ * Source buffer is queued in the bitstream ringbuffer;
+ * queue the timestamp and mark source buffer as done
+ */
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+
+ ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+ if (ts) {
+ ts->sequence = src_buf->v4l2_buf.sequence;
+ ts->timecode = src_buf->v4l2_buf.timecode;
+ ts->timestamp = src_buf->v4l2_buf.timestamp;
+ list_add_tail(&ts->list, &ctx->timestamp_list);
+ }
+
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
} else {
break;
@@ -1024,6 +1117,27 @@ static void coda_fill_bitstream(struct coda_ctx *ctx)
}
}
+static void coda_set_gdi_regs(struct coda_ctx *ctx)
+{
+ struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
+ struct coda_dev *dev = ctx->dev;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ coda_write(dev, tiled_map->xy2ca_map[i],
+ CODA9_GDI_XY2_CAS_0 + 4 * i);
+ for (i = 0; i < 4; i++)
+ coda_write(dev, tiled_map->xy2ba_map[i],
+ CODA9_GDI_XY2_BA_0 + 4 * i);
+ for (i = 0; i < 16; i++)
+ coda_write(dev, tiled_map->xy2ra_map[i],
+ CODA9_GDI_XY2_RAS_0 + 4 * i);
+ coda_write(dev, tiled_map->xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
+ for (i = 0; i < 32; i++)
+ coda_write(dev, tiled_map->rbc2axi_map[i],
+ CODA9_GDI_RBC2_AXI_0 + 4 * i);
+}
+
/*
* Mem-to-mem operations.
*/
@@ -1035,7 +1149,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
u32 stridey, height;
u32 picture_y, picture_cb, picture_cr;
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
if (ctx->params.rot_mode & CODA_ROT_90) {
@@ -1056,7 +1170,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
"bitstream payload: %d, skipping\n",
coda_get_bitstream_payload(ctx));
- schedule_work(&ctx->skip_run);
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
return -EAGAIN;
}
@@ -1065,13 +1179,16 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
int ret = coda_start_decoding(ctx);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
- schedule_work(&ctx->skip_run);
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
return -EAGAIN;
} else {
ctx->initialized = 1;
}
}
+ if (dev->devtype->product == CODA_960)
+ coda_set_gdi_regs(ctx);
+
/* Set rotator output */
picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
@@ -1082,10 +1199,26 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
picture_cb = picture_y + stridey * height;
picture_cr = picture_cb + stridey / 2 * height / 2;
}
- coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
- coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
- coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
- coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
+
+ if (dev->devtype->product == CODA_960) {
+ /*
+ * The CODA960 seems to have an internal list of buffers with
+ * 64 entries that includes the registered frame buffers as
+ * well as the rotator buffer output.
+ * ROT_INDEX needs to be < 0x40, but > ctx->num_internal_frames.
+ */
+ coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index,
+ CODA9_CMD_DEC_PIC_ROT_INDEX);
+ coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
+ coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
+ coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
+ coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
+ } else {
+ coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
+ coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
+ coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
+ coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
+ }
coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
CODA_CMD_DEC_PIC_ROT_MODE);
@@ -1095,6 +1228,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
case CODA_7541:
coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
break;
+ case CODA_960:
+ coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); /* 'hardcode to use interrupt disable mode'? */
+ break;
}
coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
@@ -1116,8 +1252,8 @@ static void coda_prepare_encode(struct coda_ctx *ctx)
u32 pic_stream_buffer_addr, pic_stream_buffer_size;
u32 dst_fourcc;
- src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
dst_fourcc = q_data_dst->fourcc;
@@ -1139,6 +1275,9 @@ static void coda_prepare_encode(struct coda_ctx *ctx)
src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
}
+ if (dev->devtype->product == CODA_960)
+ coda_set_gdi_regs(ctx);
+
/*
* Copy headers at the beginning of the first frame for H.264 only.
* In MPEG4 they are already copied by the coda.
@@ -1205,51 +1344,93 @@ static void coda_prepare_encode(struct coda_ctx *ctx)
switch (q_data_src->fourcc) {
case V4L2_PIX_FMT_YVU420:
/* Switch Cb and Cr for YVU420 format */
- picture_cr = picture_y + q_data_src->width * q_data_src->height;
- picture_cb = picture_cr + q_data_src->width / 2 *
+ picture_cr = picture_y + q_data_src->bytesperline *
+ q_data_src->height;
+ picture_cb = picture_cr + q_data_src->bytesperline / 2 *
q_data_src->height / 2;
break;
case V4L2_PIX_FMT_YUV420:
default:
- picture_cb = picture_y + q_data_src->width * q_data_src->height;
- picture_cr = picture_cb + q_data_src->width / 2 *
+ picture_cb = picture_y + q_data_src->bytesperline *
+ q_data_src->height;
+ picture_cr = picture_cb + q_data_src->bytesperline / 2 *
q_data_src->height / 2;
break;
}
- coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
- coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
- coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
+ if (dev->devtype->product == CODA_960) {
+ coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
+ coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE);
+ coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
+
+ coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
+ coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
+ coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
+ } else {
+ coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
+ coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
+ coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
+ }
coda_write(dev, force_ipicture << 1 & 0x2,
CODA_CMD_ENC_PIC_OPTION);
coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
coda_write(dev, pic_stream_buffer_size / 1024,
CODA_CMD_ENC_PIC_BB_SIZE);
+
+ if (!ctx->streamon_out) {
+ /* After streamoff on the output side, set the stream end flag */
+ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+ coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+ }
}
static void coda_device_run(void *m2m_priv)
{
struct coda_ctx *ctx = m2m_priv;
struct coda_dev *dev = ctx->dev;
- int ret;
+
+ queue_work(dev->workqueue, &ctx->pic_run_work);
+}
+
+static void coda_free_framebuffers(struct coda_ctx *ctx);
+static void coda_free_context_buffers(struct coda_ctx *ctx);
+
+static void coda_seq_end_work(struct work_struct *work)
+{
+ struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work);
+ struct coda_dev *dev = ctx->dev;
mutex_lock(&ctx->buffer_mutex);
+ mutex_lock(&dev->coda_mutex);
- /*
- * If streamoff dequeued all buffers before we could get the lock,
- * just bail out immediately.
- */
- if ((!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
- ctx->inst_type != CODA_INST_DECODER) ||
- !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
- v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
- "%d: device_run without buffers\n", ctx->idx);
- mutex_unlock(&ctx->buffer_mutex);
- schedule_work(&ctx->skip_run);
- return;
+ v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+ "%d: %s: sent command 'SEQ_END' to coda\n", ctx->idx, __func__);
+ if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+ v4l2_err(&dev->v4l2_dev,
+ "CODA_COMMAND_SEQ_END failed\n");
}
+ kfifo_init(&ctx->bitstream_fifo,
+ ctx->bitstream.vaddr, ctx->bitstream.size);
+
+ coda_free_framebuffers(ctx);
+ coda_free_context_buffers(ctx);
+
+ mutex_unlock(&dev->coda_mutex);
+ mutex_unlock(&ctx->buffer_mutex);
+}
+
+static void coda_finish_decode(struct coda_ctx *ctx);
+static void coda_finish_encode(struct coda_ctx *ctx);
+
+static void coda_pic_run_work(struct work_struct *work)
+{
+ struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work);
+ struct coda_dev *dev = ctx->dev;
+ int ret;
+
+ mutex_lock(&ctx->buffer_mutex);
mutex_lock(&dev->coda_mutex);
if (ctx->inst_type == CODA_INST_DECODER) {
@@ -1268,12 +1449,30 @@ static void coda_device_run(void *m2m_priv)
coda_write(dev, ctx->iram_info.axi_sram_use,
CODA7_REG_BIT_AXI_SRAM_USE);
- /* 1 second timeout in case CODA locks up */
- schedule_delayed_work(&dev->timeout, HZ);
-
if (ctx->inst_type == CODA_INST_DECODER)
coda_kfifo_sync_to_device_full(ctx);
coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
+
+ if (!wait_for_completion_timeout(&ctx->completion, msecs_to_jiffies(1000))) {
+ dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout\n");
+
+ ctx->hold = true;
+
+ coda_hw_reset(ctx);
+ } else if (!ctx->aborting) {
+ if (ctx->inst_type == CODA_INST_DECODER)
+ coda_finish_decode(ctx);
+ else
+ coda_finish_encode(ctx);
+ }
+
+ if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
+ queue_work(dev->workqueue, &ctx->seq_end_work);
+
+ mutex_unlock(&dev->coda_mutex);
+ mutex_unlock(&ctx->buffer_mutex);
+
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
}
static int coda_job_ready(void *m2m_priv)
@@ -1285,20 +1484,20 @@ static int coda_job_ready(void *m2m_priv)
* and 1 frame are needed. In the decoder case,
* the compressed frame can be in the bitstream.
*/
- if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) &&
+ if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
ctx->inst_type != CODA_INST_DECODER) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"not ready: not enough video buffers.\n");
return 0;
}
- if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+ if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"not ready: not enough video capture buffers.\n");
return 0;
}
- if (ctx->prescan_failed ||
+ if (ctx->hold ||
((ctx->inst_type == CODA_INST_DECODER) &&
(coda_get_bitstream_payload(ctx) < 512) &&
!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
@@ -1351,6 +1550,32 @@ static struct v4l2_m2m_ops coda_m2m_ops = {
.unlock = coda_unlock,
};
+static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
+{
+ struct gdi_tiled_map *tiled_map = &ctx->tiled_map;
+ int luma_map, chro_map, i;
+
+ memset(tiled_map, 0, sizeof(*tiled_map));
+
+ luma_map = 64;
+ chro_map = 64;
+ tiled_map->map_type = tiled_map_type;
+ for (i = 0; i < 16; i++)
+ tiled_map->xy2ca_map[i] = luma_map << 8 | chro_map;
+ for (i = 0; i < 4; i++)
+ tiled_map->xy2ba_map[i] = luma_map << 8 | chro_map;
+ for (i = 0; i < 16; i++)
+ tiled_map->xy2ra_map[i] = luma_map << 8 | chro_map;
+
+ if (tiled_map_type == GDI_LINEAR_FRAME_MAP) {
+ tiled_map->xy2rbc_config = 0;
+ } else {
+ dev_err(&ctx->dev->plat_dev->dev, "invalid map type: %d\n",
+ tiled_map_type);
+ return;
+ }
+}
+
static void set_default_params(struct coda_ctx *ctx)
{
int max_w;
@@ -1370,10 +1595,19 @@ static void set_default_params(struct coda_ctx *ctx)
ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc;
ctx->q_data[V4L2_M2M_SRC].width = max_w;
ctx->q_data[V4L2_M2M_SRC].height = max_h;
+ ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2;
ctx->q_data[V4L2_M2M_DST].width = max_w;
ctx->q_data[V4L2_M2M_DST].height = max_h;
+ ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE;
+ ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
+ ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
+ ctx->q_data[V4L2_M2M_DST].rect.width = max_w;
+ ctx->q_data[V4L2_M2M_DST].rect.height = max_h;
+
+ if (ctx->dev->devtype->product == CODA_960)
+ coda_set_tiled_map_type(ctx, GDI_LINEAR_FRAME_MAP);
}
/*
@@ -1423,6 +1657,7 @@ static int coda_buf_prepare(struct vb2_buffer *vb)
static void coda_buf_queue(struct vb2_buffer *vb)
{
struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data;
q_data = get_q_data(ctx, vb->vb2_queue->type);
@@ -1437,29 +1672,24 @@ static void coda_buf_queue(struct vb2_buffer *vb)
* For backwards compatibility, queuing an empty buffer marks
* the stream end
*/
- if (vb2_get_plane_payload(vb, 0) == 0)
+ if (vb2_get_plane_payload(vb, 0) == 0) {
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+ if ((dev->devtype->product == CODA_960) &&
+ coda_isbusy(dev) &&
+ (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
+ /* if this decoder instance is running, set the stream end flag */
+ coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
+ }
+ }
mutex_lock(&ctx->bitstream_mutex);
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
coda_fill_bitstream(ctx);
mutex_unlock(&ctx->bitstream_mutex);
} else {
- v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
}
}
-static void coda_wait_prepare(struct vb2_queue *q)
-{
- struct coda_ctx *ctx = vb2_get_drv_priv(q);
- coda_unlock(ctx);
-}
-
-static void coda_wait_finish(struct vb2_queue *q)
-{
- struct coda_ctx *ctx = vb2_get_drv_priv(q);
- coda_lock(ctx);
-}
-
static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
{
struct coda_dev *dev = ctx->dev;
@@ -1472,7 +1702,8 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
}
static int coda_alloc_aux_buf(struct coda_dev *dev,
- struct coda_aux_buf *buf, size_t size)
+ struct coda_aux_buf *buf, size_t size,
+ const char *name, struct dentry *parent)
{
buf->vaddr = dma_alloc_coherent(&dev->plat_dev->dev, size, &buf->paddr,
GFP_KERNEL);
@@ -1481,13 +1712,23 @@ static int coda_alloc_aux_buf(struct coda_dev *dev,
buf->size = size;
+ if (name && parent) {
+ buf->blob.data = buf->vaddr;
+ buf->blob.size = size;
+ buf->dentry = debugfs_create_blob(name, 0644, parent, &buf->blob);
+ if (!buf->dentry)
+ dev_warn(&dev->plat_dev->dev,
+ "failed to create debugfs entry %s\n", name);
+ }
+
return 0;
}
static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
- struct coda_aux_buf *buf, size_t size)
+ struct coda_aux_buf *buf, size_t size,
+ const char *name)
{
- return coda_alloc_aux_buf(ctx->dev, buf, size);
+ return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
}
static void coda_free_aux_buf(struct coda_dev *dev,
@@ -1499,6 +1740,7 @@ static void coda_free_aux_buf(struct coda_dev *dev,
buf->vaddr = NULL;
buf->size = 0;
}
+ debugfs_remove(buf->dentry);
}
static void coda_free_framebuffers(struct coda_ctx *ctx)
@@ -1512,25 +1754,35 @@ static void coda_free_framebuffers(struct coda_ctx *ctx)
static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc)
{
struct coda_dev *dev = ctx->dev;
- int height = q_data->height;
+ int width, height;
dma_addr_t paddr;
int ysize;
int ret;
int i;
- if (ctx->codec && ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
- height = round_up(height, 16);
- ysize = round_up(q_data->width, 8) * height;
+ if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
+ ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) {
+ width = round_up(q_data->width, 16);
+ height = round_up(q_data->height, 16);
+ } else {
+ width = round_up(q_data->width, 8);
+ height = q_data->height;
+ }
+ ysize = width * height;
/* Allocate frame buffers */
for (i = 0; i < ctx->num_internal_frames; i++) {
size_t size;
+ char *name;
- size = q_data->sizeimage;
+ size = ysize + ysize / 2;
if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
dev->devtype->product != CODA_DX6)
- ctx->internal_frames[i].size += ysize/4;
- ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size);
+ size += ysize / 4;
+ name = kasprintf(GFP_KERNEL, "fb%d", i);
+ ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i],
+ size, name);
+ kfree(name);
if (ret < 0) {
coda_free_framebuffers(ctx);
return ret;
@@ -1579,23 +1831,48 @@ static int coda_h264_padding(int size, char *p)
return nal_size;
}
+static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
+{
+ phys_addr_t ret;
+
+ size = round_up(size, 1024);
+ if (size > iram->remaining)
+ return 0;
+ iram->remaining -= size;
+
+ ret = iram->next_paddr;
+ iram->next_paddr += size;
+
+ return ret;
+}
+
static void coda_setup_iram(struct coda_ctx *ctx)
{
struct coda_iram_info *iram_info = &ctx->iram_info;
struct coda_dev *dev = ctx->dev;
- int ipacdc_size;
- int bitram_size;
- int dbk_size;
- int ovl_size;
int mb_width;
- int me_size;
- int size;
+ int dbk_bits;
+ int bit_bits;
+ int ip_bits;
memset(iram_info, 0, sizeof(*iram_info));
- size = dev->iram_size;
+ iram_info->next_paddr = dev->iram.paddr;
+ iram_info->remaining = dev->iram.size;
- if (dev->devtype->product == CODA_DX6)
+ switch (dev->devtype->product) {
+ case CODA_7541:
+ dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE;
+ bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+ ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+ break;
+ case CODA_960:
+ dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE;
+ bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+ ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+ break;
+ default: /* CODA_DX6 */
return;
+ }
if (ctx->inst_type == CODA_INST_ENCODER) {
struct coda_q_data *q_data_src;
@@ -1604,111 +1881,63 @@ static void coda_setup_iram(struct coda_ctx *ctx)
mb_width = DIV_ROUND_UP(q_data_src->width, 16);
/* Prioritize in case IRAM is too small for everything */
- me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048,
- 1024);
- iram_info->search_ram_size = me_size;
- if (size >= iram_info->search_ram_size) {
- if (dev->devtype->product == CODA_7541)
- iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE;
- iram_info->search_ram_paddr = dev->iram_paddr;
- size -= iram_info->search_ram_size;
- } else {
- pr_err("IRAM is smaller than the search ram size\n");
- goto out;
+ if (dev->devtype->product == CODA_7541) {
+ iram_info->search_ram_size = round_up(mb_width * 16 *
+ 36 + 2048, 1024);
+ iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
+ iram_info->search_ram_size);
+ if (!iram_info->search_ram_paddr) {
+ pr_err("IRAM is smaller than the search ram size\n");
+ goto out;
+ }
+ iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE |
+ CODA7_USE_ME_ENABLE;
}
/* Only H.264BP and H.263P3 are considered */
- dbk_size = round_up(128 * mb_width, 1024);
- if (size >= dbk_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
- iram_info->buf_dbk_y_use = dev->iram_paddr +
- iram_info->search_ram_size;
- iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use +
- dbk_size / 2;
- size -= dbk_size;
- } else {
+ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * mb_width);
+ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * mb_width);
+ if (!iram_info->buf_dbk_c_use)
goto out;
- }
+ iram_info->axi_sram_use |= dbk_bits;
- bitram_size = round_up(128 * mb_width, 1024);
- if (size >= bitram_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
- iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
- dbk_size / 2;
- size -= bitram_size;
- } else {
+ iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_bit_use)
goto out;
- }
+ iram_info->axi_sram_use |= bit_bits;
- ipacdc_size = round_up(128 * mb_width, 1024);
- if (size >= ipacdc_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
- iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
- bitram_size;
- size -= ipacdc_size;
- }
+ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_ip_ac_dc_use)
+ goto out;
+ iram_info->axi_sram_use |= ip_bits;
/* OVL and BTP disabled for encoder */
} else if (ctx->inst_type == CODA_INST_DECODER) {
struct coda_q_data *q_data_dst;
- int mb_height;
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
- mb_height = DIV_ROUND_UP(q_data_dst->height, 16);
-
- dbk_size = round_up(256 * mb_width, 1024);
- if (size >= dbk_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
- iram_info->buf_dbk_y_use = dev->iram_paddr;
- iram_info->buf_dbk_c_use = dev->iram_paddr +
- dbk_size / 2;
- size -= dbk_size;
- } else {
+
+ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_dbk_c_use)
goto out;
- }
+ iram_info->axi_sram_use |= dbk_bits;
- bitram_size = round_up(128 * mb_width, 1024);
- if (size >= bitram_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
- iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
- dbk_size / 2;
- size -= bitram_size;
- } else {
+ iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_bit_use)
goto out;
- }
+ iram_info->axi_sram_use |= bit_bits;
- ipacdc_size = round_up(128 * mb_width, 1024);
- if (size >= ipacdc_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
- iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
- bitram_size;
- size -= ipacdc_size;
- } else {
+ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_ip_ac_dc_use)
goto out;
- }
+ iram_info->axi_sram_use |= ip_bits;
- ovl_size = round_up(80 * mb_width, 1024);
+ /* OVL and BTP unused as there is no VC1 support yet */
}
out:
- switch (dev->devtype->product) {
- case CODA_DX6:
- break;
- case CODA_7541:
- /* i.MX53 uses secondary AXI for IRAM access */
- if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE;
- }
-
if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"IRAM smaller than needed\n");
@@ -1746,13 +1975,8 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx,
size_t size;
int ret;
- switch (dev->devtype->product) {
- case CODA_7541:
- size = CODA7_WORK_BUF_SIZE;
- break;
- default:
+ if (dev->devtype->product == CODA_DX6)
return 0;
- }
if (ctx->psbuf.vaddr) {
v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
@@ -1772,7 +1996,7 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx,
/* worst case slice size */
size = (DIV_ROUND_UP(q_data->width, 16) *
DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
- ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size);
+ ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, "slicebuf");
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte slice buffer",
ctx->slicebuf.size);
@@ -1781,14 +2005,18 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx,
}
if (dev->devtype->product == CODA_7541) {
- ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE);
+ ret = coda_alloc_context_buf(ctx, &ctx->psbuf, CODA7_PS_BUF_SIZE, "psbuf");
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate psmem buffer");
goto err;
}
}
- ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size);
+ size = dev->devtype->workbuf_size;
+ if (dev->devtype->product == CODA_960 &&
+ q_data->fourcc == V4L2_PIX_FMT_H264)
+ size += CODA9_PS_SAVE_SIZE;
+ ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, "workbuf");
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate %d byte context buffer",
ctx->workbuf.size);
@@ -1834,12 +2062,17 @@ static int coda_start_decoding(struct coda_ctx *ctx)
coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
val = 0;
- if (dev->devtype->product == CODA_7541)
+ if ((dev->devtype->product == CODA_7541) ||
+ (dev->devtype->product == CODA_960))
val |= CODA_REORDER_ENABLE;
coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
ctx->params.codec_mode = ctx->codec->mode;
- ctx->params.codec_mode_aux = 0;
+ if (dev->devtype->product == CODA_960 &&
+ src_fourcc == V4L2_PIX_FMT_MPEG4)
+ ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
+ else
+ ctx->params.codec_mode_aux = 0;
if (src_fourcc == V4L2_PIX_FMT_H264) {
if (dev->devtype->product == CODA_7541) {
coda_write(dev, ctx->psbuf.paddr,
@@ -1847,6 +2080,13 @@ static int coda_start_decoding(struct coda_ctx *ctx)
coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
CODA_CMD_DEC_SEQ_PS_BB_SIZE);
}
+ if (dev->devtype->product == CODA_960) {
+ coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
+ coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
+ }
+ }
+ if (dev->devtype->product != CODA_960) {
+ coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
}
if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
@@ -1888,7 +2128,7 @@ static int coda_start_decoding(struct coda_ctx *ctx)
v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n",
__func__, ctx->idx, width, height);
- ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1;
+ ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED);
if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
v4l2_err(&dev->v4l2_dev,
"not enough framebuffers to decode (%d < %d)\n",
@@ -1896,6 +2136,21 @@ static int coda_start_decoding(struct coda_ctx *ctx)
return -EINVAL;
}
+ if (src_fourcc == V4L2_PIX_FMT_H264) {
+ u32 left_right;
+ u32 top_bottom;
+
+ left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
+ top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
+
+ q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
+ q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
+ q_data_dst->rect.width = width - q_data_dst->rect.left -
+ (left_right & 0x3ff);
+ q_data_dst->rect.height = height - q_data_dst->rect.top -
+ (top_bottom & 0x3ff);
+ }
+
ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
if (ret < 0)
return ret;
@@ -1918,6 +2173,20 @@ static int coda_start_decoding(struct coda_ctx *ctx)
CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
coda_write(dev, ctx->iram_info.buf_ovl_use,
CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+ if (dev->devtype->product == CODA_960)
+ coda_write(dev, ctx->iram_info.buf_btp_use,
+ CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+ }
+
+ if (dev->devtype->product == CODA_960) {
+ coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
+
+ coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
+ coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
+ 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
+ 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
+ 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
+ CODA9_CMD_SET_FRAME_CACHE_CONFIG);
}
if (src_fourcc == V4L2_PIX_FMT_H264) {
@@ -1931,8 +2200,16 @@ static int coda_start_decoding(struct coda_ctx *ctx)
int max_mb_x = 1920 / 16;
int max_mb_y = 1088 / 16;
int max_mb_num = max_mb_x * max_mb_y;
+
coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
+ } else if (dev->devtype->product == CODA_960) {
+ int max_mb_x = 1920 / 16;
+ int max_mb_y = 1088 / 16;
+ int max_mb_num = max_mb_x * max_mb_y;
+
+ coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
+ CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
}
if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
@@ -1948,34 +2225,49 @@ static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
int header_code, u8 *header, int *size)
{
struct coda_dev *dev = ctx->dev;
+ size_t bufsize;
int ret;
+ int i;
+
+ if (dev->devtype->product == CODA_960)
+ memset(vb2_plane_vaddr(buf, 0), 0, 64);
coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0),
CODA_CMD_ENC_HEADER_BB_START);
- coda_write(dev, vb2_plane_size(buf, 0), CODA_CMD_ENC_HEADER_BB_SIZE);
+ bufsize = vb2_plane_size(buf, 0);
+ if (dev->devtype->product == CODA_960)
+ bufsize /= 1024;
+ coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
return ret;
}
- *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
- coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+
+ if (dev->devtype->product == CODA_960) {
+ for (i = 63; i > 0; i--)
+ if (((char *)vb2_plane_vaddr(buf, 0))[i] != 0)
+ break;
+ *size = i + 1;
+ } else {
+ *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
+ coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+ }
memcpy(header, vb2_plane_vaddr(buf, 0), *size);
return 0;
}
+static int coda_start_encoding(struct coda_ctx *ctx);
+
static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct coda_ctx *ctx = vb2_get_drv_priv(q);
struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
- u32 bitstream_buf, bitstream_size;
struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data_src, *q_data_dst;
- struct vb2_buffer *buf;
u32 dst_fourcc;
- u32 value;
int ret = 0;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
@@ -2007,13 +2299,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
/* Allow decoder device_run with no new buffers queued */
if (ctx->inst_type == CODA_INST_DECODER)
- v4l2_m2m_set_src_buffered(ctx->m2m_ctx, true);
+ v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
ctx->gopcounter = ctx->params.gop_size - 1;
- buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
- bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- bitstream_size = q_data_dst->sizeimage;
dst_fourcc = q_data_dst->fourcc;
ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
@@ -2032,16 +2321,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
mutex_lock(&dev->coda_mutex);
ret = coda_start_decoding(ctx);
mutex_unlock(&dev->coda_mutex);
- if (ret == -EAGAIN) {
+ if (ret == -EAGAIN)
return 0;
- } else if (ret < 0) {
+ else if (ret < 0)
return ret;
- } else {
- ctx->initialized = 1;
- return 0;
- }
+ } else {
+ ret = coda_start_encoding(ctx);
}
+ ctx->initialized = 1;
+ return ret;
+}
+
+static int coda_start_encoding(struct coda_ctx *ctx)
+{
+ struct coda_dev *dev = ctx->dev;
+ struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+ struct coda_q_data *q_data_src, *q_data_dst;
+ u32 bitstream_buf, bitstream_size;
+ struct vb2_buffer *buf;
+ int gamma, ret, value;
+ u32 dst_fourcc;
+
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ dst_fourcc = q_data_dst->fourcc;
+
+ buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
+ bitstream_size = q_data_dst->sizeimage;
+
if (!coda_is_initialized(dev)) {
v4l2_err(v4l2_dev, "coda is not initialized.\n");
return -EFAULT;
@@ -2057,14 +2366,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
break;
- default:
+ case CODA_960:
+ coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+ /* fallthrough */
+ case CODA_7541:
coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+ break;
}
+ value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
+ value &= ~(1 << 2 | 0x7 << 9);
+ ctx->frame_mem_ctrl = value;
+ coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
+
if (dev->devtype->product == CODA_DX6) {
/* Configure the coda */
- coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
+ coda_write(dev, dev->iram.paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
}
/* Could set rotation here if needed */
@@ -2073,7 +2391,16 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET;
value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
break;
- default:
+ case CODA_7541:
+ if (dst_fourcc == V4L2_PIX_FMT_H264) {
+ value = (round_up(q_data_src->width, 16) &
+ CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
+ value |= (round_up(q_data_src->height, 16) &
+ CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
+ break;
+ }
+ /* fallthrough */
+ case CODA_960:
value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
}
@@ -2084,12 +2411,28 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
ctx->params.codec_mode = ctx->codec->mode;
switch (dst_fourcc) {
case V4L2_PIX_FMT_MPEG4:
- coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
+ if (dev->devtype->product == CODA_960)
+ coda_write(dev, CODA9_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
+ else
+ coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
break;
case V4L2_PIX_FMT_H264:
- coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA);
+ if (dev->devtype->product == CODA_960)
+ coda_write(dev, CODA9_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
+ else
+ coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
+ if (ctx->params.h264_deblk_enabled) {
+ value = ((ctx->params.h264_deblk_alpha &
+ CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
+ CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
+ ((ctx->params.h264_deblk_beta &
+ CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
+ CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET);
+ } else {
+ value = 1 << CODA_264PARAM_DISABLEDEBLK_OFFSET;
+ }
+ coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
break;
default:
v4l2_err(v4l2_dev,
@@ -2121,42 +2464,75 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
/* Rate control enabled */
value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET;
value |= 1 & CODA_RATECONTROL_ENABLE_MASK;
+ if (dev->devtype->product == CODA_960)
+ value |= BIT(31); /* disable autoskip */
} else {
value = 0;
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH);
+ coda_write(dev, ctx->params.intra_refresh,
+ CODA_CMD_ENC_SEQ_INTRA_REFRESH);
coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
- /* set default gamma */
- value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET;
- coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA);
- if (CODA_DEFAULT_GAMMA > 0) {
- if (dev->devtype->product == CODA_DX6)
- value = 1 << CODADX6_OPTION_GAMMA_OFFSET;
- else
- value = 1 << CODA7_OPTION_GAMMA_OFFSET;
+ value = 0;
+ if (dev->devtype->product == CODA_960)
+ gamma = CODA9_DEFAULT_GAMMA;
+ else
+ gamma = CODA_DEFAULT_GAMMA;
+ if (gamma > 0) {
+ coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET,
+ CODA_CMD_ENC_SEQ_RC_GAMMA);
+ }
+
+ if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
+ coda_write(dev,
+ ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
+ ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
+ CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
+ }
+ if (dev->devtype->product == CODA_960) {
+ if (ctx->params.h264_max_qp)
+ value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
+ if (CODA_DEFAULT_GAMMA > 0)
+ value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
} else {
- value = 0;
+ if (CODA_DEFAULT_GAMMA > 0) {
+ if (dev->devtype->product == CODA_DX6)
+ value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
+ else
+ value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
+ }
+ if (ctx->params.h264_min_qp)
+ value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
+ if (ctx->params.h264_max_qp)
+ value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
+ coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
+
coda_setup_iram(ctx);
if (dst_fourcc == V4L2_PIX_FMT_H264) {
- if (dev->devtype->product == CODA_DX6) {
+ switch (dev->devtype->product) {
+ case CODA_DX6:
value = FMO_SLICE_SAVE_BUF_SIZE << 7;
coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
- } else {
+ break;
+ case CODA_7541:
coda_write(dev, ctx->iram_info.search_ram_paddr,
CODA7_CMD_ENC_SEQ_SEARCH_BASE);
coda_write(dev, ctx->iram_info.search_ram_size,
CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
+ break;
+ case CODA_960:
+ coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
+ coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
}
}
@@ -2172,7 +2548,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
goto out;
}
- ctx->num_internal_frames = 2;
+ if (dev->devtype->product == CODA_960)
+ ctx->num_internal_frames = 4;
+ else
+ ctx->num_internal_frames = 2;
ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
if (ret < 0) {
v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
@@ -2180,10 +2559,12 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
}
coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
- coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE);
- if (dev->devtype->product == CODA_7541)
- coda_write(dev, round_up(q_data_src->width, 8),
+ coda_write(dev, q_data_src->bytesperline,
+ CODA_CMD_SET_FRAME_BUF_STRIDE);
+ if (dev->devtype->product == CODA_7541) {
+ coda_write(dev, q_data_src->bytesperline,
CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
+ }
if (dev->devtype->product != CODA_DX6) {
coda_write(dev, ctx->iram_info.buf_bit_use,
CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
@@ -2195,7 +2576,16 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
coda_write(dev, ctx->iram_info.buf_ovl_use,
CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+ if (dev->devtype->product == CODA_960) {
+ coda_write(dev, ctx->iram_info.buf_btp_use,
+ CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+
+ /* FIXME */
+ coda_write(dev, ctx->internal_frames[2].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_A);
+ coda_write(dev, ctx->internal_frames[3].paddr, CODA9_CMD_SET_FRAME_SUBSAMP_B);
+ }
}
+
ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
if (ret < 0) {
v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
@@ -2203,7 +2593,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
}
/* Save stream headers */
- buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
switch (dst_fourcc) {
case V4L2_PIX_FMT_H264:
/*
@@ -2279,6 +2669,17 @@ static void coda_stop_streaming(struct vb2_queue *q)
"%s: output\n", __func__);
ctx->streamon_out = 0;
+ if (ctx->inst_type == CODA_INST_DECODER &&
+ coda_isbusy(dev) && ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX)) {
+ /* if this decoder instance is running, set the stream end flag */
+ if (dev->devtype->product == CODA_960) {
+ u32 val = coda_read(dev, CODA_REG_BIT_BIT_STREAM_PARAM);
+
+ val |= CODA_BIT_STREAM_END_FLAG;
+ coda_write(dev, val, CODA_REG_BIT_BIT_STREAM_PARAM);
+ ctx->bit_stream_param = val;
+ }
+ }
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
ctx->isequence = 0;
@@ -2288,9 +2689,18 @@ static void coda_stop_streaming(struct vb2_queue *q)
ctx->streamon_cap = 0;
ctx->osequence = 0;
+ ctx->sequence_offset = 0;
}
if (!ctx->streamon_out && !ctx->streamon_cap) {
+ struct coda_timestamp *ts;
+
+ while (!list_empty(&ctx->timestamp_list)) {
+ ts = list_first_entry(&ctx->timestamp_list,
+ struct coda_timestamp, list);
+ list_del(&ts->list);
+ kfree(ts);
+ }
kfifo_init(&ctx->bitstream_fifo,
ctx->bitstream.vaddr, ctx->bitstream.size);
ctx->runcounter = 0;
@@ -2301,10 +2711,10 @@ static struct vb2_ops coda_qops = {
.queue_setup = coda_queue_setup,
.buf_prepare = coda_buf_prepare,
.buf_queue = coda_buf_queue,
- .wait_prepare = coda_wait_prepare,
- .wait_finish = coda_wait_finish,
.start_streaming = coda_start_streaming,
.stop_streaming = coda_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
};
static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -2340,6 +2750,22 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
ctx->params.h264_inter_qp = ctrl->val;
break;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ ctx->params.h264_min_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ ctx->params.h264_max_qp = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+ ctx->params.h264_deblk_alpha = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+ ctx->params.h264_deblk_beta = ctrl->val;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+ ctx->params.h264_deblk_enabled = (ctrl->val ==
+ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+ break;
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
ctx->params.mpeg4_intra_qp = ctrl->val;
break;
@@ -2357,6 +2783,9 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
break;
case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
break;
+ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+ ctx->params.intra_refresh = ctrl->val;
+ break;
default:
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"Invalid control, id=%d, val=%d\n",
@@ -2384,9 +2813,23 @@ static int coda_ctrls_setup(struct coda_ctx *ctx)
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25);
+ V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25);
+ if (ctx->dev->devtype->product != CODA_960) {
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12);
+ }
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25);
+ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, 0, 15, 1, 0);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, 0, 15, 1, 0);
+ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED, 0x0,
+ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -2404,6 +2847,8 @@ static int coda_ctrls_setup(struct coda_ctx *ctx)
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
(1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE),
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, 1920 * 1088 / 256, 1, 0);
if (ctx->ctrls.error) {
v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)",
@@ -2427,6 +2872,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->ops = &coda_qops;
src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->dev->dev_mutex;
ret = vb2_queue_init(src_vq);
if (ret)
@@ -2439,6 +2885,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->ops = &coda_qops;
dst_vq->mem_ops = &vb2_dma_contig_memops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->lock = &ctx->dev->dev_mutex;
return vb2_queue_init(dst_vq);
}
@@ -2458,6 +2905,7 @@ static int coda_open(struct file *file)
{
struct coda_dev *dev = video_drvdata(file);
struct coda_ctx *ctx = NULL;
+ char *name;
int ret;
int idx;
@@ -2472,7 +2920,13 @@ static int coda_open(struct file *file)
}
set_bit(idx, &dev->instance_mask);
- INIT_WORK(&ctx->skip_run, coda_skip_run);
+ name = kasprintf(GFP_KERNEL, "context%d", idx);
+ ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
+ kfree(name);
+
+ init_completion(&ctx->completion);
+ INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
+ INIT_WORK(&ctx->seq_end_work, coda_seq_end_work);
v4l2_fh_init(&ctx->fh, video_devdata(file));
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
@@ -2480,12 +2934,20 @@ static int coda_open(struct file *file)
ctx->idx = idx;
switch (dev->devtype->product) {
case CODA_7541:
+ case CODA_960:
ctx->reg_idx = 0;
break;
default:
ctx->reg_idx = idx;
}
+ /* Power up and upload firmware if necessary */
+ ret = pm_runtime_get_sync(&dev->plat_dev->dev);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret);
+ goto err_pm_get;
+ }
+
ret = clk_prepare_enable(dev->clk_per);
if (ret)
goto err_clk_per;
@@ -2495,15 +2957,16 @@ static int coda_open(struct file *file)
goto err_clk_ahb;
set_default_params(ctx);
- ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
&coda_queue_init);
- if (IS_ERR(ctx->m2m_ctx)) {
- ret = PTR_ERR(ctx->m2m_ctx);
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ ret = PTR_ERR(ctx->fh.m2m_ctx);
v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n",
__func__, ret);
goto err_ctx_init;
}
+
ret = coda_ctrls_setup(ctx);
if (ret) {
v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n");
@@ -2512,7 +2975,8 @@ static int coda_open(struct file *file)
ctx->fh.ctrl_handler = &ctx->ctrls;
- ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE);
+ ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE,
+ "parabuf");
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
goto err_dma_alloc;
@@ -2530,6 +2994,7 @@ static int coda_open(struct file *file)
ctx->bitstream.vaddr, ctx->bitstream.size);
mutex_init(&ctx->bitstream_mutex);
mutex_init(&ctx->buffer_mutex);
+ INIT_LIST_HEAD(&ctx->timestamp_list);
coda_lock(ctx);
list_add(&ctx->list, &dev->instances);
@@ -2548,12 +3013,14 @@ err_dma_writecombine:
err_dma_alloc:
v4l2_ctrl_handler_free(&ctx->ctrls);
err_ctrls_setup:
- v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
err_ctx_init:
clk_disable_unprepare(dev->clk_ahb);
err_clk_ahb:
clk_disable_unprepare(dev->clk_per);
err_clk_per:
+ pm_runtime_put_sync(&dev->plat_dev->dev);
+err_pm_get:
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
clear_bit(ctx->idx, &dev->instance_mask);
@@ -2570,20 +3037,16 @@ static int coda_release(struct file *file)
v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
ctx);
+ debugfs_remove_recursive(ctx->debugfs_entry);
+
/* If this instance is running, call .job_abort and wait for it to end */
- v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
/* In case the instance was not running, we still need to call SEQ_END */
- mutex_lock(&dev->coda_mutex);
- v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
- "%s: sent command 'SEQ_END' to coda\n", __func__);
- if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
- v4l2_err(&dev->v4l2_dev,
- "CODA_COMMAND_SEQ_END failed\n");
- mutex_unlock(&dev->coda_mutex);
- return -ETIMEDOUT;
+ if (ctx->initialized) {
+ queue_work(dev->workqueue, &ctx->seq_end_work);
+ flush_work(&ctx->seq_end_work);
}
- mutex_unlock(&dev->coda_mutex);
coda_free_framebuffers(ctx);
@@ -2601,6 +3064,7 @@ static int coda_release(struct file *file)
v4l2_ctrl_handler_free(&ctx->ctrls);
clk_disable_unprepare(dev->clk_ahb);
clk_disable_unprepare(dev->clk_per);
+ pm_runtime_put_sync(&dev->plat_dev->dev);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
clear_bit(ctx->idx, &dev->instance_mask);
@@ -2609,32 +3073,13 @@ static int coda_release(struct file *file)
return 0;
}
-static unsigned int coda_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct coda_ctx *ctx = fh_to_ctx(file->private_data);
- int ret;
-
- coda_lock(ctx);
- ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
- coda_unlock(ctx);
- return ret;
-}
-
-static int coda_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct coda_ctx *ctx = fh_to_ctx(file->private_data);
-
- return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-}
-
static const struct v4l2_file_operations coda_fops = {
.owner = THIS_MODULE,
.open = coda_open,
.release = coda_release,
- .poll = coda_poll,
+ .poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
- .mmap = coda_mmap,
+ .mmap = v4l2_m2m_fop_mmap,
};
static void coda_finish_decode(struct coda_ctx *ctx)
@@ -2643,14 +3088,16 @@ static void coda_finish_decode(struct coda_ctx *ctx)
struct coda_q_data *q_data_src;
struct coda_q_data *q_data_dst;
struct vb2_buffer *dst_buf;
+ struct coda_timestamp *ts;
int width, height;
int decoded_idx;
int display_idx;
u32 src_fourcc;
int success;
+ u32 err_mb;
u32 val;
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
/* Update kfifo out pointer from coda bitstream read pointer */
coda_kfifo_sync_from_device(ctx);
@@ -2693,19 +3140,34 @@ static void coda_finish_decode(struct coda_ctx *ctx)
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- val = coda_read(dev, CODA_RET_DEC_PIC_TYPE);
- if ((val & 0x7) == 0) {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+ /* frame crop information */
+ if (src_fourcc == V4L2_PIX_FMT_H264) {
+ u32 left_right;
+ u32 top_bottom;
+
+ left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
+ top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
+
+ if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
+ /* Keep current crop information */
+ } else {
+ struct v4l2_rect *rect = &q_data_dst->rect;
+
+ rect->left = left_right >> 16 & 0xffff;
+ rect->top = top_bottom >> 16 & 0xffff;
+ rect->width = width - rect->left -
+ (left_right & 0xffff);
+ rect->height = height - rect->top -
+ (top_bottom & 0xffff);
+ }
} else {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+ /* no cropping */
}
- val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
- if (val > 0)
+ err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
+ if (err_mb > 0)
v4l2_err(&dev->v4l2_dev,
- "errors in %d macroblocks\n", val);
+ "errors in %d macroblocks\n", err_mb);
if (dev->devtype->product == CODA_7541) {
val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
@@ -2713,7 +3175,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
/* not enough bitstream data */
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
"prescan failed: %d\n", val);
- ctx->prescan_failed = true;
+ ctx->hold = true;
return;
}
}
@@ -2741,13 +3203,38 @@ static void coda_finish_decode(struct coda_ctx *ctx)
if (decoded_idx == -1) {
/* no frame was decoded, but we might have a display frame */
- if (display_idx < 0 && ctx->display_idx < 0)
- ctx->prescan_failed = true;
+ if (display_idx >= 0 && display_idx < ctx->num_internal_frames)
+ ctx->sequence_offset++;
+ else if (ctx->display_idx < 0)
+ ctx->hold = true;
} else if (decoded_idx == -2) {
/* no frame was decoded, we still return the remaining buffers */
} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
v4l2_err(&dev->v4l2_dev,
"decoded frame index out of range: %d\n", decoded_idx);
+ } else {
+ ts = list_first_entry(&ctx->timestamp_list,
+ struct coda_timestamp, list);
+ list_del(&ts->list);
+ val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
+ val -= ctx->sequence_offset;
+ if (val != (ts->sequence & 0xffff)) {
+ v4l2_err(&dev->v4l2_dev,
+ "sequence number mismatch (%d(%d) != %d)\n",
+ val, ctx->sequence_offset, ts->sequence);
+ }
+ ctx->frame_timestamps[decoded_idx] = *ts;
+ kfree(ts);
+
+ val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
+ if (val == 0)
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME;
+ else if (val == 1)
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME;
+ else
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME;
+
+ ctx->frame_errors[decoded_idx] = err_mb;
}
if (display_idx == -1) {
@@ -2755,7 +3242,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
* no more frames to be decoded, but there could still
* be rotator output to dequeue
*/
- ctx->prescan_failed = true;
+ ctx->hold = true;
} else if (display_idx == -3) {
/* possibly prescan failure */
} else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
@@ -2767,13 +3254,21 @@ static void coda_finish_decode(struct coda_ctx *ctx)
/* If a frame was copied out, return it */
if (ctx->display_idx >= 0 &&
ctx->display_idx < ctx->num_internal_frames) {
- dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
dst_buf->v4l2_buf.sequence = ctx->osequence++;
+ dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME |
+ V4L2_BUF_FLAG_BFRAME);
+ dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
+ ts = &ctx->frame_timestamps[ctx->display_idx];
+ dst_buf->v4l2_buf.timecode = ts->timecode;
+ dst_buf->v4l2_buf.timestamp = ts->timestamp;
+
vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
- v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE :
- VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
+ VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
"job finished: decoding frame (%d) (%s)\n",
@@ -2795,8 +3290,8 @@ static void coda_finish_encode(struct coda_ctx *ctx)
struct coda_dev *dev = ctx->dev;
u32 wr_ptr, start_ptr;
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
/* Get results from the coda */
start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
@@ -2833,6 +3328,8 @@ static void coda_finish_encode(struct coda_ctx *ctx)
dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+
+ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
ctx->gopcounter--;
@@ -2851,8 +3348,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
struct coda_dev *dev = data;
struct coda_ctx *ctx;
- cancel_delayed_work(&dev->timeout);
-
/* read status register to attend the IRQ */
coda_read(dev, CODA_REG_BIT_INT_STATUS);
coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
@@ -2868,7 +3363,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
if (ctx->aborting) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"task has been aborted\n");
- goto out;
}
if (coda_isbusy(ctx->dev)) {
@@ -2877,60 +3371,15 @@ static irqreturn_t coda_irq_handler(int irq, void *data)
return IRQ_NONE;
}
- if (ctx->inst_type == CODA_INST_DECODER)
- coda_finish_decode(ctx);
- else
- coda_finish_encode(ctx);
-
-out:
- if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) {
- v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
- "%s: sent command 'SEQ_END' to coda\n", __func__);
- if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
- v4l2_err(&dev->v4l2_dev,
- "CODA_COMMAND_SEQ_END failed\n");
- }
-
- kfifo_init(&ctx->bitstream_fifo,
- ctx->bitstream.vaddr, ctx->bitstream.size);
-
- coda_free_framebuffers(ctx);
- coda_free_context_buffers(ctx);
- }
-
- mutex_unlock(&dev->coda_mutex);
- mutex_unlock(&ctx->buffer_mutex);
-
- v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
+ complete(&ctx->completion);
return IRQ_HANDLED;
}
-static void coda_timeout(struct work_struct *work)
-{
- struct coda_ctx *ctx;
- struct coda_dev *dev = container_of(to_delayed_work(work),
- struct coda_dev, timeout);
-
- dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n");
-
- mutex_lock(&dev->dev_mutex);
- list_for_each_entry(ctx, &dev->instances, list) {
- if (mutex_is_locked(&ctx->buffer_mutex))
- mutex_unlock(&ctx->buffer_mutex);
- v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- }
- mutex_unlock(&dev->dev_mutex);
-
- mutex_unlock(&dev->coda_mutex);
- ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
- v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
-}
-
static u32 coda_supported_firmwares[] = {
CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
+ CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
};
static bool coda_firmware_supported(u32 vernum)
@@ -2945,19 +3394,21 @@ static bool coda_firmware_supported(u32 vernum)
static int coda_hw_init(struct coda_dev *dev)
{
- u16 product, major, minor, release;
u32 data;
u16 *p;
int i, ret;
ret = clk_prepare_enable(dev->clk_per);
if (ret)
- return ret;
+ goto err_clk_per;
ret = clk_prepare_enable(dev->clk_ahb);
if (ret)
goto err_clk_ahb;
+ if (dev->rstc)
+ reset_control_reset(dev->rstc);
+
/*
* Copy the first CODA_ISRAM_SIZE in the internal SRAM.
* The 16-bit chars in the code buffer are in memory access
@@ -2985,7 +3436,8 @@ static int coda_hw_init(struct coda_dev *dev)
coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
/* Tell the BIT where to find everything it needs */
- if (dev->devtype->product == CODA_7541) {
+ if (dev->devtype->product == CODA_960 ||
+ dev->devtype->product == CODA_7541) {
coda_write(dev, dev->tempbuf.paddr,
CODA_REG_BIT_TEMP_BUF_ADDR);
coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
@@ -3005,7 +3457,10 @@ static int coda_hw_init(struct coda_dev *dev)
default:
coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL);
}
- coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
+ if (dev->devtype->product == CODA_960)
+ coda_write(dev, 1 << 12, CODA_REG_BIT_FRAME_MEM_CTRL);
+ else
+ coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
if (dev->devtype->product != CODA_DX6)
coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
@@ -3022,17 +3477,46 @@ static int coda_hw_init(struct coda_dev *dev)
coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
- /* Load firmware */
+ clk_disable_unprepare(dev->clk_ahb);
+ clk_disable_unprepare(dev->clk_per);
+
+ return 0;
+
+err_clk_ahb:
+ clk_disable_unprepare(dev->clk_per);
+err_clk_per:
+ return ret;
+}
+
+static int coda_check_firmware(struct coda_dev *dev)
+{
+ u16 product, major, minor, release;
+ u32 data;
+ int ret;
+
+ ret = clk_prepare_enable(dev->clk_per);
+ if (ret)
+ goto err_clk_per;
+
+ ret = clk_prepare_enable(dev->clk_ahb);
+ if (ret)
+ goto err_clk_ahb;
+
coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND);
if (coda_wait_timeout(dev)) {
- clk_disable_unprepare(dev->clk_per);
- clk_disable_unprepare(dev->clk_ahb);
v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
- return -EIO;
+ ret = -EIO;
+ goto err_run_cmd;
+ }
+
+ if (dev->devtype->product == CODA_960) {
+ data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
+ v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
+ data);
}
/* Check we are compatible with the loaded firmware */
@@ -3066,8 +3550,11 @@ static int coda_hw_init(struct coda_dev *dev)
return 0;
+err_run_cmd:
+ clk_disable_unprepare(dev->clk_ahb);
err_clk_ahb:
clk_disable_unprepare(dev->clk_per);
+err_clk_per:
return ret;
}
@@ -3083,7 +3570,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
}
/* allocate auxiliary per-device code buffer for the BIT processor */
- ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size);
+ ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
+ dev->debugfs_root);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate code buffer\n");
return;
@@ -3093,10 +3581,37 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
memcpy(dev->codebuf.vaddr, fw->data, fw->size);
release_firmware(fw);
- ret = coda_hw_init(dev);
- if (ret) {
- v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
- return;
+ if (pm_runtime_enabled(&pdev->dev) && pdev->dev.pm_domain) {
+ /*
+ * Enabling power temporarily will cause coda_hw_init to be
+ * called via coda_runtime_resume by the pm domain.
+ */
+ ret = pm_runtime_get_sync(&dev->plat_dev->dev);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "failed to power on: %d\n",
+ ret);
+ return;
+ }
+
+ ret = coda_check_firmware(dev);
+ if (ret < 0)
+ return;
+
+ pm_runtime_put_sync(&dev->plat_dev->dev);
+ } else {
+ /*
+ * If runtime pm is disabled or pm_domain is not set,
+ * initialize once manually.
+ */
+ ret = coda_hw_init(dev);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
+ return;
+ }
+
+ ret = coda_check_firmware(dev);
+ if (ret < 0)
+ return;
}
dev->vfd.fops = &coda_fops,
@@ -3150,20 +3665,45 @@ static int coda_firmware_request(struct coda_dev *dev)
enum coda_platform {
CODA_IMX27,
CODA_IMX53,
+ CODA_IMX6Q,
+ CODA_IMX6DL,
};
static const struct coda_devtype coda_devdata[] = {
[CODA_IMX27] = {
- .firmware = "v4l-codadx6-imx27.bin",
- .product = CODA_DX6,
- .codecs = codadx6_codecs,
- .num_codecs = ARRAY_SIZE(codadx6_codecs),
+ .firmware = "v4l-codadx6-imx27.bin",
+ .product = CODA_DX6,
+ .codecs = codadx6_codecs,
+ .num_codecs = ARRAY_SIZE(codadx6_codecs),
+ .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
+ .iram_size = 0xb000,
},
[CODA_IMX53] = {
- .firmware = "v4l-coda7541-imx53.bin",
- .product = CODA_7541,
- .codecs = coda7_codecs,
- .num_codecs = ARRAY_SIZE(coda7_codecs),
+ .firmware = "v4l-coda7541-imx53.bin",
+ .product = CODA_7541,
+ .codecs = coda7_codecs,
+ .num_codecs = ARRAY_SIZE(coda7_codecs),
+ .workbuf_size = 128 * 1024,
+ .tempbuf_size = 304 * 1024,
+ .iram_size = 0x14000,
+ },
+ [CODA_IMX6Q] = {
+ .firmware = "v4l-coda960-imx6q.bin",
+ .product = CODA_960,
+ .codecs = coda9_codecs,
+ .num_codecs = ARRAY_SIZE(coda9_codecs),
+ .workbuf_size = 80 * 1024,
+ .tempbuf_size = 204 * 1024,
+ .iram_size = 0x21000,
+ },
+ [CODA_IMX6DL] = {
+ .firmware = "v4l-coda960-imx6dl.bin",
+ .product = CODA_960,
+ .codecs = coda9_codecs,
+ .num_codecs = ARRAY_SIZE(coda9_codecs),
+ .workbuf_size = 80 * 1024,
+ .tempbuf_size = 204 * 1024,
+ .iram_size = 0x20000,
},
};
@@ -3178,6 +3718,8 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids);
static const struct of_device_id coda_dt_ids[] = {
{ .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
{ .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
+ { .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] },
+ { .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, coda_dt_ids);
@@ -3204,7 +3746,6 @@ static int coda_probe(struct platform_device *pdev)
spin_lock_init(&dev->irqlock);
INIT_LIST_HEAD(&dev->instances);
- INIT_DELAYED_WORK(&dev->timeout, coda_timeout);
dev->plat_dev = pdev;
dev->clk_per = devm_clk_get(&pdev->dev, "per");
@@ -3229,13 +3770,25 @@ static int coda_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get irq resource\n");
- return -ENOENT;
+ return irq;
}
- if (devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler,
- IRQF_ONESHOT, dev_name(&pdev->dev), dev) < 0) {
- dev_err(&pdev->dev, "failed to request irq\n");
- return -ENOENT;
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, coda_irq_handler,
+ IRQF_ONESHOT, dev_name(&pdev->dev), dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+ return ret;
+ }
+
+ dev->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(dev->rstc)) {
+ ret = PTR_ERR(dev->rstc);
+ if (ret == -ENOENT || ret == -ENOSYS) {
+ dev->rstc = NULL;
+ } else {
+ dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
+ return ret;
+ }
}
/* Get IRAM pool from device tree or platform data */
@@ -3266,24 +3819,26 @@ static int coda_probe(struct platform_device *pdev)
return -EINVAL;
}
+ dev->debugfs_root = debugfs_create_dir("coda", NULL);
+ if (!dev->debugfs_root)
+ dev_warn(&pdev->dev, "failed to create debugfs root\n");
+
/* allocate auxiliary per-device buffers for the BIT processor */
- switch (dev->devtype->product) {
- case CODA_DX6:
+ if (dev->devtype->product == CODA_DX6) {
ret = coda_alloc_aux_buf(dev, &dev->workbuf,
- CODADX6_WORK_BUF_SIZE);
+ dev->devtype->workbuf_size, "workbuf",
+ dev->debugfs_root);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate work buffer\n");
v4l2_device_unregister(&dev->v4l2_dev);
return ret;
}
- break;
- case CODA_7541:
- dev->tempbuf.size = CODA7_TEMP_BUF_SIZE;
- break;
}
- if (dev->tempbuf.size) {
+
+ if (dev->devtype->tempbuf_size) {
ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
- dev->tempbuf.size);
+ dev->devtype->tempbuf_size, "tempbuf",
+ dev->debugfs_root);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate temp buffer\n");
v4l2_device_unregister(&dev->v4l2_dev);
@@ -3291,23 +3846,29 @@ static int coda_probe(struct platform_device *pdev)
}
}
- switch (dev->devtype->product) {
- case CODA_DX6:
- dev->iram_size = CODADX6_IRAM_SIZE;
- break;
- case CODA_7541:
- dev->iram_size = CODA7_IRAM_SIZE;
- break;
- }
- dev->iram_vaddr = (unsigned long)gen_pool_dma_alloc(dev->iram_pool,
- dev->iram_size, (dma_addr_t *)&dev->iram_paddr);
- if (!dev->iram_vaddr) {
+ dev->iram.size = dev->devtype->iram_size;
+ dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size,
+ &dev->iram.paddr);
+ if (!dev->iram.vaddr) {
dev_err(&pdev->dev, "unable to alloc iram\n");
return -ENOMEM;
}
+ dev->iram.blob.data = dev->iram.vaddr;
+ dev->iram.blob.size = dev->iram.size;
+ dev->iram.dentry = debugfs_create_blob("iram", 0644, dev->debugfs_root,
+ &dev->iram.blob);
+
+ dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!dev->workqueue) {
+ dev_err(&pdev->dev, "unable to alloc workqueue\n");
+ return -ENOMEM;
+ }
+
platform_set_drvdata(pdev, dev);
+ pm_runtime_enable(&pdev->dev);
+
return coda_firmware_request(dev);
}
@@ -3318,17 +3879,41 @@ static int coda_remove(struct platform_device *pdev)
video_unregister_device(&dev->vfd);
if (dev->m2m_dev)
v4l2_m2m_release(dev->m2m_dev);
+ pm_runtime_disable(&pdev->dev);
if (dev->alloc_ctx)
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
v4l2_device_unregister(&dev->v4l2_dev);
- if (dev->iram_vaddr)
- gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size);
+ destroy_workqueue(dev->workqueue);
+ if (dev->iram.vaddr)
+ gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr,
+ dev->iram.size);
coda_free_aux_buf(dev, &dev->codebuf);
coda_free_aux_buf(dev, &dev->tempbuf);
coda_free_aux_buf(dev, &dev->workbuf);
+ debugfs_remove_recursive(dev->debugfs_root);
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int coda_runtime_resume(struct device *dev)
+{
+ struct coda_dev *cdev = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (dev->pm_domain) {
+ ret = coda_hw_init(cdev);
+ if (ret)
+ v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n");
+ }
+
+ return ret;
+}
+#endif
+
+static const struct dev_pm_ops coda_pm_ops = {
+ SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL)
+};
+
static struct platform_driver coda_driver = {
.probe = coda_probe,
.remove = coda_remove,
@@ -3336,6 +3921,7 @@ static struct platform_driver coda_driver = {
.name = CODA_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(coda_dt_ids),
+ .pm = &coda_pm_ops,
},
.id_table = coda_platform_ids,
};
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h
index 4e32e2edea62..c791275e307b 100644
--- a/drivers/media/platform/coda.h
+++ b/drivers/media/platform/coda.h
@@ -27,6 +27,14 @@
#define CODA_REG_BIT_CODE_RESET 0x014
#define CODA_REG_RESET_ENABLE (1 << 0)
#define CODA_REG_BIT_CUR_PC 0x018
+#define CODA9_REG_BIT_SW_RESET 0x024
+#define CODA9_SW_RESET_BPU_CORE 0x008
+#define CODA9_SW_RESET_BPU_BUS 0x010
+#define CODA9_SW_RESET_VCE_CORE 0x020
+#define CODA9_SW_RESET_VCE_BUS 0x040
+#define CODA9_SW_RESET_GDI_CORE 0x080
+#define CODA9_SW_RESET_GDI_BUS 0x100
+#define CODA9_REG_BIT_SW_RESET_STATUS 0x034
/* Static SW registers */
#define CODA_REG_BIT_CODE_BUF_ADDR 0x100
@@ -39,9 +47,11 @@
#define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2)
#define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5)
#define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4)
-#define CODA_STREAM_CHKDIS_OFFSET (1 << 1)
+#define CODADX6_STREAM_CHKDIS_OFFSET (1 << 1)
+#define CODA7_STREAM_SEL_64BITS_ENDIAN (1 << 1)
#define CODA_STREAM_ENDIAN_SELECT (1 << 0)
#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110
+#define CODA_FRAME_CHROMA_INTERLEAVE (1 << 2)
#define CODA_IMAGE_ENDIAN_SELECT (1 << 0)
#define CODA_REG_BIT_BIT_STREAM_PARAM 0x114
#define CODA_BIT_STREAM_END_FLAG (1 << 2)
@@ -52,13 +62,21 @@
#define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x))
#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140
#define CODA7_REG_BIT_AXI_SRAM_USE 0x140
+#define CODA9_USE_HOST_BTP_ENABLE (1 << 13)
+#define CODA9_USE_HOST_OVL_ENABLE (1 << 12)
#define CODA7_USE_HOST_ME_ENABLE (1 << 11)
+#define CODA9_USE_HOST_DBK_ENABLE (3 << 10)
#define CODA7_USE_HOST_OVL_ENABLE (1 << 10)
#define CODA7_USE_HOST_DBK_ENABLE (1 << 9)
+#define CODA9_USE_HOST_IP_ENABLE (1 << 9)
#define CODA7_USE_HOST_IP_ENABLE (1 << 8)
+#define CODA9_USE_HOST_BIT_ENABLE (1 << 8)
#define CODA7_USE_HOST_BIT_ENABLE (1 << 7)
+#define CODA9_USE_BTP_ENABLE (1 << 5)
#define CODA7_USE_ME_ENABLE (1 << 4)
+#define CODA9_USE_OVL_ENABLE (1 << 4)
#define CODA7_USE_OVL_ENABLE (1 << 3)
+#define CODA9_USE_DBK_ENABLE (3 << 2)
#define CODA7_USE_DBK_ENABLE (1 << 2)
#define CODA7_USE_IP_ENABLE (1 << 1)
#define CODA7_USE_BIT_ENABLE (1 << 0)
@@ -93,6 +111,18 @@
#define CODA7_MODE_ENCODE_H264 8
#define CODA7_MODE_ENCODE_MP4 11
#define CODA7_MODE_ENCODE_MJPG 13
+#define CODA9_MODE_DECODE_H264 0
+#define CODA9_MODE_DECODE_VC1 1
+#define CODA9_MODE_DECODE_MP2 2
+#define CODA9_MODE_DECODE_MP4 3
+#define CODA9_MODE_DECODE_DV3 3
+#define CODA9_MODE_DECODE_RV 4
+#define CODA9_MODE_DECODE_AVS 5
+#define CODA9_MODE_DECODE_MJPG 6
+#define CODA9_MODE_DECODE_VPX 7
+#define CODA9_MODE_ENCODE_H264 8
+#define CODA9_MODE_ENCODE_MP4 11
+#define CODA9_MODE_ENCODE_MJPG 13
#define CODA_MODE_INVALID 0xffff
#define CODA_REG_BIT_INT_ENABLE 0x170
#define CODA_INT_INTERRUPT_ENABLE (1 << 3)
@@ -129,6 +159,7 @@
#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0
#define CODA7_RET_DEC_SEQ_ASPECT 0x1b0
+#define CODA9_RET_DEC_SEQ_BITRATE 0x1b4
#define CODA_RET_DEC_SEQ_SUCCESS 0x1c0
#define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */
#define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4
@@ -145,13 +176,19 @@
#define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8
#define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4
#define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8
+#define CODA9_RET_DEC_SEQ_HEADER_REPORT 0x1ec
/* Decoder Picture Run */
#define CODA_CMD_DEC_PIC_ROT_MODE 0x180
#define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184
+#define CODA9_CMD_DEC_PIC_ROT_INDEX 0x184
#define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y 0x188
#define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB 0x18c
#define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR 0x190
+#define CODA9_CMD_DEC_PIC_ROT_STRIDE 0x1b8
#define CODA_CMD_DEC_PIC_OPTION 0x194
#define CODA_PRE_SCAN_EN (1 << 0)
@@ -183,25 +220,39 @@
#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4
#define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec
+#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT 0x1e8
+#define CODA9_RET_DEC_PIC_ASPECT 0x1f0
+#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO 0x1f0
+#define CODA9_RET_DEC_PIC_FRATE_NR 0x1f4
+#define CODA9_RET_DEC_PIC_FRATE_DR 0x1f8
+
/* Encoder Sequence Initialization */
#define CODA_CMD_ENC_SEQ_BB_START 0x180
#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184
#define CODA_CMD_ENC_SEQ_OPTION 0x188
#define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9
+#define CODA9_OPTION_MVC_PREFIX_NAL_OFFSET 9
#define CODA7_OPTION_GAMMA_OFFSET 8
+#define CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET 8
#define CODA7_OPTION_RCQPMAX_OFFSET 7
+#define CODA9_OPTION_GAMMA_OFFSET 7
#define CODADX6_OPTION_GAMMA_OFFSET 7
#define CODA7_OPTION_RCQPMIN_OFFSET 6
+#define CODA9_OPTION_RCQPMAX_OFFSET 6
#define CODA_OPTION_LIMITQP_OFFSET 6
#define CODA_OPTION_RCINTRAQP_OFFSET 5
#define CODA_OPTION_FMO_OFFSET 4
+#define CODA9_OPTION_MVC_INTERVIEW_OFFSET 4
#define CODA_OPTION_AVC_AUD_OFFSET 2
#define CODA_OPTION_SLICEREPORT_OFFSET 1
#define CODA_CMD_ENC_SEQ_COD_STD 0x18c
#define CODA_STD_MPEG4 0
+#define CODA9_STD_H264 0
#define CODA_STD_H263 1
#define CODA_STD_H264 2
#define CODA_STD_MJPG 3
+#define CODA9_STD_MPEG4 3
+
#define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190
#define CODA7_PICWIDTH_OFFSET 16
#define CODA7_PICWIDTH_MASK 0xffff
@@ -268,15 +319,26 @@
#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8
#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc
#define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4
-#define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8
+#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX 0x1c8
+#define CODA_QPMIN_OFFSET 8
+#define CODA_QPMIN_MASK 0x3f
#define CODA_QPMAX_OFFSET 0
#define CODA_QPMAX_MASK 0x3f
#define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc
#define CODA_GAMMA_OFFSET 0
#define CODA_GAMMA_MASK 0xffff
+#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE 0x1d0
+#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT 0x1d4
+#define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8
#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0
/* Encoder Picture Run */
+#define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180
+#define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184
+#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC 0x1a4
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y 0x1a8
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB 0x1ac
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR 0x1b0
#define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180
#define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184
#define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188
@@ -291,7 +353,11 @@
#define CODA_MIR_VER (0x1 << 2)
#define CODA_MIR_HOR (0x2 << 2)
#define CODA_MIR_VER_HOR (0x3 << 2)
-#define CODA_CMD_ENC_PIC_OPTION 0x194
+#define CODA_CMD_ENC_PIC_OPTION 0x194
+#define CODA_FORCE_IPICTURE BIT(1)
+#define CODA_REPORT_MB_INFO BIT(3)
+#define CODA_REPORT_MV_INFO BIT(4)
+#define CODA_REPORT_SLICE_INFO BIT(5)
#define CODA_CMD_ENC_PIC_BB_START 0x198
#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c
#define CODA_RET_ENC_FRAME_NUM 0x1c0
@@ -306,13 +372,30 @@
#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184
#define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188
#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A 0x188
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B 0x18c
#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190
#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194
#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198
#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c
#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0
#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4
+#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR 0x1a4
#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_SIZE 0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_CONFIG 0x1ac
+#define CODA9_CACHE_BYPASS_OFFSET 28
+#define CODA9_CACHE_DUALCONF_OFFSET 26
+#define CODA9_CACHE_PAGEMERGE_OFFSET 24
+#define CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET 16
+#define CODA9_CACHE_CB_BUFFER_SIZE_OFFSET 8
+#define CODA9_CACHE_CR_BUFFER_SIZE_OFFSET 0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC 0x1b0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC 0x1b4
+#define CODA9_CMD_SET_FRAME_DP_BUF_BASE 0x1b0
+#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE 0x1b4
+#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE 0x1b8
+#define CODA9_CMD_SET_FRAME_DELAY 0x1bc
/* Encoder Header */
#define CODA_CMD_ENC_HEADER_CODE 0x180
@@ -322,8 +405,11 @@
#define CODA_HEADER_MP4V_VOL 0
#define CODA_HEADER_MP4V_VOS 1
#define CODA_HEADER_MP4V_VIS 2
+#define CODA9_HEADER_FRAME_CROP (1 << 3)
#define CODA_CMD_ENC_HEADER_BB_START 0x184
#define CODA_CMD_ENC_HEADER_BB_SIZE 0x188
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H 0x18c
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V 0x190
/* Get Version */
#define CODA_CMD_FIRMWARE_VERNUM 0x1c0
@@ -334,5 +420,28 @@
#define CODA_FIRMWARE_VERNUM(product, major, minor, release) \
((product) << 16 | ((major) << 12) | \
((minor) << 8) | (release))
+#define CODA9_CMD_FIRMWARE_CODE_REV 0x1c4
+
+#define CODA9_GDMA_BASE 0x1000
+#define CODA9_GDI_WPROT_ERR_CLR (CODA9_GDMA_BASE + 0x0a0)
+#define CODA9_GDI_WPROT_RGN_EN (CODA9_GDMA_BASE + 0x0ac)
+
+#define CODA9_GDI_BUS_CTRL (CODA9_GDMA_BASE + 0x0f0)
+#define CODA9_GDI_BUS_STATUS (CODA9_GDMA_BASE + 0x0f4)
+
+#define CODA9_GDI_XY2_CAS_0 (CODA9_GDMA_BASE + 0x800)
+#define CODA9_GDI_XY2_CAS_F (CODA9_GDMA_BASE + 0x83c)
+
+#define CODA9_GDI_XY2_BA_0 (CODA9_GDMA_BASE + 0x840)
+#define CODA9_GDI_XY2_BA_1 (CODA9_GDMA_BASE + 0x844)
+#define CODA9_GDI_XY2_BA_2 (CODA9_GDMA_BASE + 0x848)
+#define CODA9_GDI_XY2_BA_3 (CODA9_GDMA_BASE + 0x84c)
+
+#define CODA9_GDI_XY2_RAS_0 (CODA9_GDMA_BASE + 0x850)
+#define CODA9_GDI_XY2_RAS_F (CODA9_GDMA_BASE + 0x88c)
+
+#define CODA9_GDI_XY2_RBC_CONFIG (CODA9_GDMA_BASE + 0x890)
+#define CODA9_GDI_RBC2_AXI_0 (CODA9_GDMA_BASE + 0x8a0)
+#define CODA9_GDI_RBC2_AXI_1F (CODA9_GDMA_BASE + 0x91c)
#endif
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index 30fa08405d61..07e98df3d867 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -581,13 +581,8 @@ void ccdc_config_raw(void)
config_params->alaw.enable)
syn_mode |= CCDC_DATA_PACK_ENABLE;
-#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
- /* enable video port */
- val = CCDC_ENABLE_VIDEO_PORT;
-#else
/* disable video port */
val = CCDC_DISABLE_VIDEO_PORT;
-#endif
if (config_params->data_sz == CCDC_DATA_8BITS)
val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index bf5eff99452b..73496d953ba0 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -1709,7 +1709,6 @@ static int register_device(struct vpbe_layer *vpbe_display_layer,
vpbe_display_layer->disp_dev = disp_dev;
/* set the driver data in platform device */
platform_set_drvdata(pdev, disp_dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags);
video_set_drvdata(&vpbe_display_layer->video_dev,
vpbe_display_layer);
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index a51bda2fb637..ea7661a27479 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -1916,7 +1916,6 @@ static int vpfe_probe(struct platform_device *pdev)
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
"video_dev=%x\n", (int)&vpfe_dev->video_dev);
vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags);
ret = video_register_device(vpfe_dev->video_dev,
VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 1e4ec697fb10..b054b7eec53d 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -39,32 +39,10 @@ MODULE_VERSION(VPIF_CAPTURE_VERSION);
v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
static int debug = 1;
-static u32 ch0_numbuffers = 3;
-static u32 ch1_numbuffers = 3;
-static u32 ch0_bufsize = 1920 * 1080 * 2;
-static u32 ch1_bufsize = 720 * 576 * 2;
module_param(debug, int, 0644);
-module_param(ch0_numbuffers, uint, S_IRUGO);
-module_param(ch1_numbuffers, uint, S_IRUGO);
-module_param(ch0_bufsize, uint, S_IRUGO);
-module_param(ch1_bufsize, uint, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level 0-1");
-MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)");
-MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)");
-MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)");
-MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)");
-
-static struct vpif_config_params config_params = {
- .min_numbuffers = 3,
- .numbuffers[0] = 3,
- .numbuffers[1] = 3,
- .min_bufsize[0] = 720 * 480 * 2,
- .min_bufsize[1] = 720 * 480 * 2,
- .channel_bufsize[0] = 1920 * 1080 * 2,
- .channel_bufsize[1] = 720 * 576 * 2,
-};
#define VPIF_DRIVER_NAME "vpif_capture"
@@ -521,10 +499,28 @@ static int vpif_update_std_info(struct channel_obj *ch)
common->width = std_info->width;
common->fmt.fmt.pix.height = std_info->height;
common->height = std_info->height;
+ common->fmt.fmt.pix.sizeimage = common->height * common->width * 2;
common->fmt.fmt.pix.bytesperline = std_info->width;
vpifparams->video_params.hpitch = std_info->width;
vpifparams->video_params.storage_mode = std_info->frm_fmt;
+ if (vid_ch->stdid)
+ common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+ if (ch->vpifparams.std_info.frm_fmt)
+ common->fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ else
+ common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
+ common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ else
+ common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
+
+ common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
return 0;
}
@@ -601,27 +597,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch)
}
/**
- * vpif_config_format: configure default frame format in the device
- * ch : ptr to channel object
- */
-static void vpif_config_format(struct channel_obj *ch)
-{
- struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-
- vpif_dbg(2, debug, "vpif_config_format\n");
-
- common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
- common->fmt.fmt.pix.sizeimage
- = config_params.channel_bufsize[ch->channel_id];
-
- if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
- common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
- else
- common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
- common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-}
-
-/**
* vpif_get_default_field() - Get default field type based on interface
* @vpif_params - ptr to vpif params
*/
@@ -633,112 +608,6 @@ static inline enum v4l2_field vpif_get_default_field(
}
/**
- * vpif_check_format() - check given pixel format for compatibility
- * @ch - channel ptr
- * @pixfmt - Given pixel format
- * @update - update the values as per hardware requirement
- *
- * Check the application pixel format for S_FMT and update the input
- * values as per hardware limits for TRY_FMT. The default pixel and
- * field format is selected based on interface type.
- */
-static int vpif_check_format(struct channel_obj *ch,
- struct v4l2_pix_format *pixfmt,
- int update)
-{
- struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
- struct vpif_params *vpif_params = &ch->vpifparams;
- enum v4l2_field field = pixfmt->field;
- u32 sizeimage, hpitch, vpitch;
- int ret = -EINVAL;
-
- vpif_dbg(2, debug, "vpif_check_format\n");
- /**
- * first check for the pixel format. If if_type is Raw bayer,
- * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only
- * V4L2_PIX_FMT_YUV422P is supported
- */
- if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
- if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pix format\n");
- goto exit;
- }
- pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
- }
- } else {
- if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pixel format\n");
- goto exit;
- }
- pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
- }
- }
-
- if (!(VPIF_VALID_FIELD(field))) {
- if (!update) {
- vpif_dbg(2, debug, "invalid field format\n");
- goto exit;
- }
- /**
- * By default use FIELD_NONE for RAW Bayer capture
- * and FIELD_INTERLACED for other interfaces
- */
- field = vpif_get_default_field(&vpif_params->iface);
- } else if (field == V4L2_FIELD_ANY)
- /* unsupported field. Use default */
- field = vpif_get_default_field(&vpif_params->iface);
-
- /* validate the hpitch */
- hpitch = pixfmt->bytesperline;
- if (hpitch < vpif_params->std_info.width) {
- if (!update) {
- vpif_dbg(2, debug, "invalid hpitch\n");
- goto exit;
- }
- hpitch = vpif_params->std_info.width;
- }
-
- sizeimage = pixfmt->sizeimage;
-
- vpitch = sizeimage / (hpitch * 2);
-
- /* validate the vpitch */
- if (vpitch < vpif_params->std_info.height) {
- if (!update) {
- vpif_dbg(2, debug, "Invalid vpitch\n");
- goto exit;
- }
- vpitch = vpif_params->std_info.height;
- }
-
- /* Check for 8 byte alignment */
- if (!ALIGN(hpitch, 8)) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pitch alignment\n");
- goto exit;
- }
- /* adjust to next 8 byte boundary */
- hpitch = (((hpitch + 7) / 8) * 8);
- }
- /* if update is set, modify the bytesperline and sizeimage */
- if (update) {
- pixfmt->bytesperline = hpitch;
- pixfmt->sizeimage = hpitch * vpitch * 2;
- }
- /**
- * Image width and height is always based on current standard width and
- * height
- */
- pixfmt->width = common->fmt.fmt.pix.width;
- pixfmt->height = common->fmt.fmt.pix.height;
- return 0;
-exit:
- return ret;
-}
-
-/**
* vpif_config_addr() - function to configure buffer address in vpif
* @ch - channel ptr
* @muxmode - channel mux mode
@@ -948,9 +817,6 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)
return -EINVAL;
}
- /* Configure the default format information */
- vpif_config_format(ch);
-
/* set standard in the sub device */
ret = v4l2_subdev_call(ch->sd, video, s_std, std_id);
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
@@ -977,10 +843,8 @@ static int vpif_enum_input(struct file *file, void *priv,
chan_cfg = &config->chan_config[ch->channel_id];
- if (input->index >= chan_cfg->input_count) {
- vpif_dbg(1, debug, "Invalid input index\n");
+ if (input->index >= chan_cfg->input_count)
return -EINVAL;
- }
memcpy(input, &chan_cfg->inputs[input->index].input,
sizeof(*input));
@@ -1069,8 +933,34 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
struct channel_obj *ch = video_get_drvdata(vdev);
struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+ struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+ struct vpif_params *vpif_params = &ch->vpifparams;
- return vpif_check_format(ch, pixfmt, 1);
+ /*
+ * to supress v4l-compliance warnings silently correct
+ * the pixelformat
+ */
+ if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
+ if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
+ } else {
+ if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P)
+ pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
+ }
+
+ common->fmt.fmt.pix.pixelformat = pixfmt->pixelformat;
+
+ vpif_update_std_info(ch);
+
+ pixfmt->field = common->fmt.fmt.pix.field;
+ pixfmt->colorspace = common->fmt.fmt.pix.colorspace;
+ pixfmt->bytesperline = common->fmt.fmt.pix.width;
+ pixfmt->width = common->fmt.fmt.pix.width;
+ pixfmt->height = common->fmt.fmt.pix.height;
+ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
+ pixfmt->priv = 0;
+
+ return 0;
}
@@ -1108,20 +998,17 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
struct channel_obj *ch = video_get_drvdata(vdev);
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
- struct v4l2_pix_format *pixfmt;
- int ret = 0;
+ int ret;
vpif_dbg(2, debug, "%s\n", __func__);
if (vb2_is_busy(&common->buffer_queue))
return -EBUSY;
- pixfmt = &fmt->fmt.pix;
- /* Check for valid field format */
- ret = vpif_check_format(ch, pixfmt, 0);
-
+ ret = vpif_try_fmt_vid_cap(file, priv, fmt);
if (ret)
return ret;
+
/* store the format in the channel object */
common->fmt = *fmt;
return 0;
@@ -1411,36 +1298,9 @@ static struct v4l2_file_operations vpif_fops = {
*/
static int initialize_vpif(void)
{
- int err = 0, i, j;
+ int err, i, j;
int free_channel_objects_index;
- /* Default number of buffers should be 3 */
- if ((ch0_numbuffers > 0) &&
- (ch0_numbuffers < config_params.min_numbuffers))
- ch0_numbuffers = config_params.min_numbuffers;
- if ((ch1_numbuffers > 0) &&
- (ch1_numbuffers < config_params.min_numbuffers))
- ch1_numbuffers = config_params.min_numbuffers;
-
- /* Set buffer size to min buffers size if it is invalid */
- if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
- ch0_bufsize =
- config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
- if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
- ch1_bufsize =
- config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
-
- config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers;
- config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers;
- if (ch0_numbuffers) {
- config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
- = ch0_bufsize;
- }
- if (ch1_numbuffers) {
- config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
- = ch1_bufsize;
- }
-
/* Allocate memory for six channel objects */
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
vpif_obj.dev[i] =
@@ -1496,6 +1356,11 @@ static int vpif_probe_complete(void)
if (err)
goto probe_out;
+ /* set initial format */
+ ch->video.stdid = V4L2_STD_525_60;
+ memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
+ vpif_update_std_info(ch);
+
/* Initialize vb2 queue */
q = &common->buffer_queue;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1533,7 +1398,6 @@ static int vpif_probe_complete(void)
vdev->vfl_dir = VFL_DIR_RX;
vdev->queue = q;
vdev->lock = &common->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(ch->video_dev, ch);
err = video_register_device(vdev,
VFL_TYPE_GRABBER, (j ? 1 : 0));
@@ -1714,7 +1578,7 @@ static int vpif_remove(struct platform_device *device)
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[i];
- common = &ch->common[i];
+ common = &ch->common[VPIF_VIDEO_INDEX];
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
/* Unregister video device */
video_unregister_device(ch->video_dev);
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 1ee17824f484..f65d28d38e66 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -119,15 +119,4 @@ struct vpif_device {
struct vpif_capture_config *config;
};
-struct vpif_config_params {
- u8 min_numbuffers;
- u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS];
- s8 device_type;
- u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
- u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
- u8 default_device[VPIF_CAPTURE_NUM_CHANNELS];
- u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
- u8 max_device_type;
-};
-
#endif /* VPIF_CAPTURE_H */
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index b431b58f39e3..a03ec7381cfe 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -649,7 +649,6 @@ static int vpif_try_fmt_vid_out(struct file *file, void *priv,
pixfmt->width = common->fmt.fmt.pix.width;
pixfmt->height = common->fmt.fmt.pix.height;
pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
- pixfmt->priv = 0;
return 0;
}
@@ -1224,7 +1223,6 @@ static int vpif_probe_complete(void)
vdev->vfl_dir = VFL_DIR_TX;
vdev->queue = q;
vdev->lock = &common->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(ch->video_dev, ch);
err = video_register_device(vdev, VFL_TYPE_GRABBER,
(j ? 3 : 2));
@@ -1388,7 +1386,7 @@ static int vpif_remove(struct platform_device *device)
for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[i];
- common = &ch->common[i];
+ common = &ch->common[VPIF_VIDEO_INDEX];
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
/* Unregister video device */
video_unregister_device(ch->video_dev);
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index c21d14fd61db..d36c507a0ba2 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -1002,7 +1002,7 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_mask_t mask;
int ret = 0;
- pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+ pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
if (!pcdev)
return -ENOMEM;
@@ -1012,7 +1012,7 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_set(DMA_INTERLEAVE, mask);
pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
if (!pcdev->dma_chan)
- goto free_dev;
+ return -ENODEV;
if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
@@ -1078,8 +1078,6 @@ unreg_dev:
v4l2_device_unregister(&pcdev->v4l2_dev);
rel_dma:
dma_release_channel(pcdev->dma_chan);
-free_dev:
- kfree(pcdev);
return ret;
}
@@ -1094,7 +1092,6 @@ static int deinterlace_remove(struct platform_device *pdev)
v4l2_device_unregister(&pcdev->v4l2_dev);
vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
dma_release_channel(pcdev->dma_chan);
- kfree(pcdev);
return 0;
}
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c
index 0714070ed7fa..c1b03cfd6ded 100644
--- a/drivers/media/platform/mem2mem_testdev.c
+++ b/drivers/media/platform/mem2mem_testdev.c
@@ -532,7 +532,6 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.priv = 0;
return 0;
}
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 9a726eacb29b..2d177fa58471 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
pix->pixelformat = omap_formats[ifmt].pixelformat;
pix->field = V4L2_FIELD_ANY;
- pix->priv = 0;
switch (pix->pixelformat) {
case V4L2_PIX_FMT_YUYV:
@@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
pix->field = V4L2_FIELD_ANY;
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
- pix->priv = 0;
pix->colorspace = V4L2_COLORSPACE_JPEG;
vout->bpp = RGB565_BPP;
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index deba425e3d8f..f33641384e15 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1172,7 +1172,6 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
goto err_vd_rel;
video_set_drvdata(vfd, vp);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
v4l2_ctrl_handler_init(&vp->ctrl_handler, 1);
ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops,
@@ -1271,6 +1270,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
}
mutex_unlock(&camif->lock);
+ mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_JPEG;
return 0;
}
@@ -1319,6 +1319,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n",
fmt->pad, mf->code, mf->width, mf->height);
+ mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_JPEG;
mutex_lock(&camif->lock);
diff --git a/drivers/media/platform/s5p-jpeg/Makefile b/drivers/media/platform/s5p-jpeg/Makefile
index a1a9169254c3..9e5f214c4667 100644
--- a/drivers/media/platform/s5p-jpeg/Makefile
+++ b/drivers/media/platform/s5p-jpeg/Makefile
@@ -1,2 +1,2 @@
-s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
+s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos3250.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 0dcb796ecad9..e66acbc2a82d 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1,6 +1,6 @@
/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
*
- * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
@@ -32,6 +32,7 @@
#include "jpeg-core.h"
#include "jpeg-hw-s5p.h"
#include "jpeg-hw-exynos4.h"
+#include "jpeg-hw-exynos3250.h"
#include "jpeg-regs.h"
static struct s5p_jpeg_fmt sjpeg_formats[] = {
@@ -41,6 +42,7 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.flags = SJPEG_FMT_FLAG_ENC_CAPTURE |
SJPEG_FMT_FLAG_DEC_OUTPUT |
SJPEG_FMT_FLAG_S5P |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
SJPEG_FMT_FLAG_EXYNOS4,
},
{
@@ -70,6 +72,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
},
{
+ .name = "YUV 4:2:2 packed, YCbYCr",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+ },
+ {
.name = "YUV 4:2:2 packed, YCrYCb",
.fourcc = V4L2_PIX_FMT_YVYU,
.depth = 16,
@@ -83,6 +98,45 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
},
{
+ .name = "YUV 4:2:2 packed, YCrYCb",
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+ },
+ {
+ .name = "YUV 4:2:2 packed, YCrYCb",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+ },
+ {
+ .name = "YUV 4:2:2 packed, YCrYCb",
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+ },
+ {
.name = "RGB565",
.fourcc = V4L2_PIX_FMT_RGB565,
.depth = 16,
@@ -100,6 +154,32 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.fourcc = V4L2_PIX_FMT_RGB565,
.depth = 16,
.colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+ },
+ {
+ .name = "RGB565X",
+ .fourcc = V4L2_PIX_FMT_RGB565X,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+ },
+ {
+ .name = "RGB565",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .depth = 16,
+ .colplanes = 1,
.h_align = 0,
.v_align = 0,
.flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
@@ -121,6 +201,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
},
{
+ .name = "ARGB8888, 32 bpp",
+ .fourcc = V4L2_PIX_FMT_RGB32,
+ .depth = 32,
+ .colplanes = 1,
+ .h_align = 2,
+ .v_align = 0,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+ },
+ {
.name = "YUV 4:4:4 planar, Y/CbCr",
.fourcc = V4L2_PIX_FMT_NV24,
.depth = 24,
@@ -190,9 +283,23 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.fourcc = V4L2_PIX_FMT_NV12,
.depth = 12,
.colplanes = 2,
+ .h_align = 3,
+ .v_align = 3,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+ },
+ {
+ .name = "YUV 4:2:0 planar, Y/CbCr",
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .depth = 12,
+ .colplanes = 2,
.h_align = 4,
.v_align = 4,
- .flags = SJPEG_FMT_FLAG_DEC_CAPTURE |
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
SJPEG_FMT_FLAG_S5P |
SJPEG_FMT_NON_RGB,
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
@@ -202,10 +309,24 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.fourcc = V4L2_PIX_FMT_NV21,
.depth = 12,
.colplanes = 2,
+ .h_align = 3,
+ .v_align = 3,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+ },
+ {
+ .name = "YUV 4:2:0 planar, Y/CrCb",
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .depth = 12,
+ .colplanes = 2,
.h_align = 1,
.v_align = 1,
.flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
SJPEG_FMT_FLAG_EXYNOS4 |
SJPEG_FMT_NON_RGB,
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
@@ -224,6 +345,19 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
},
{
+ .name = "YUV 4:2:0 contiguous 3-planar, Y/Cb/Cr",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .colplanes = 3,
+ .h_align = 4,
+ .v_align = 4,
+ .flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
+ SJPEG_FMT_FLAG_DEC_CAPTURE |
+ SJPEG_FMT_FLAG_EXYNOS3250 |
+ SJPEG_FMT_NON_RGB,
+ .subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+ },
+ {
.name = "Gray",
.fourcc = V4L2_PIX_FMT_GREY,
.depth = 8,
@@ -457,6 +591,16 @@ static int exynos4x12_decoded_subsampling[] = {
V4L2_JPEG_CHROMA_SUBSAMPLING_420,
};
+static int exynos3250_decoded_subsampling[] = {
+ V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+ -1,
+ -1,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_411,
+};
+
static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
{
return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
@@ -471,14 +615,21 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
{
WARN_ON(ctx->subsampling > 3);
- if (ctx->jpeg->variant->version == SJPEG_S5P) {
+ switch (ctx->jpeg->variant->version) {
+ case SJPEG_S5P:
if (ctx->subsampling > 2)
return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
return ctx->subsampling;
- } else {
+ case SJPEG_EXYNOS3250:
+ if (ctx->subsampling > 3)
+ return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
+ return exynos3250_decoded_subsampling[ctx->subsampling];
+ case SJPEG_EXYNOS4:
if (ctx->subsampling > 2)
return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
return exynos4x12_decoded_subsampling[ctx->subsampling];
+ default:
+ return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
}
}
@@ -646,6 +797,7 @@ static int s5p_jpeg_open(struct file *file)
FMT_TYPE_OUTPUT);
cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
FMT_TYPE_CAPTURE);
+ ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
}
ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
@@ -754,14 +906,14 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
while (notfound) {
c = get_byte(&jpeg_buffer);
if (c == -1)
- break;
+ return false;
if (c != 0xff)
continue;
do
c = get_byte(&jpeg_buffer);
while (c == 0xff);
if (c == -1)
- break;
+ return false;
if (c == 0)
continue;
length = 0;
@@ -981,7 +1133,8 @@ static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
return NULL;
}
-static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
+ u32 *w, unsigned int wmin, unsigned int wmax,
unsigned int walign,
u32 *h, unsigned int hmin, unsigned int hmax,
unsigned int halign)
@@ -993,13 +1146,27 @@ static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
w_step = 1 << walign;
h_step = 1 << halign;
+
+ if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) {
+ /*
+ * Rightmost and bottommost pixels are cropped by the
+ * Exynos3250 JPEG IP for RGB formats, for the specific
+ * width and height values respectively. This assignment
+ * will result in v4l_bound_align_image returning dimensions
+ * reduced by 1 for the aforementioned cases.
+ */
+ if (w_step == 4 && ((width & 3) == 1)) {
+ wmax = width;
+ hmax = height;
+ }
+ }
+
v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
if (*w < width && (*w + w_step) < wmax)
*w += w_step;
if (*h < height && (*h + h_step) < hmax)
*h += h_step;
-
}
static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
@@ -1015,12 +1182,12 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
/* V4L2 specification suggests the driver corrects the format struct
* if any of the dimensions is unsupported */
if (q_type == FMT_TYPE_OUTPUT)
- jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+ jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
S5P_JPEG_MAX_WIDTH, 0,
&pix->height, S5P_JPEG_MIN_HEIGHT,
S5P_JPEG_MAX_HEIGHT, 0);
else
- jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+ jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
S5P_JPEG_MAX_WIDTH, fmt->h_align,
&pix->height, S5P_JPEG_MIN_HEIGHT,
S5P_JPEG_MAX_HEIGHT, fmt->v_align);
@@ -1142,7 +1309,7 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
else
wh_align = 1;
- jpeg_bound_align_image(&w, S5P_JPEG_MIN_WIDTH,
+ jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
S5P_JPEG_MAX_WIDTH, wh_align,
&h, S5P_JPEG_MIN_HEIGHT,
S5P_JPEG_MAX_HEIGHT, wh_align);
@@ -1150,12 +1317,16 @@ static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
return w * h * fmt_depth >> 3;
}
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+ struct v4l2_rect *r);
+
static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
{
struct vb2_queue *vq;
struct s5p_jpeg_q_data *q_data = NULL;
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_ctrl *ctrl_subs;
+ struct v4l2_rect scale_rect;
unsigned int f_type;
vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
@@ -1200,6 +1371,35 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
if (ctrl_subs)
v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
+ ct->crop_altered = false;
+ }
+
+ /*
+ * For decoding init crop_rect with capture buffer dimmensions which
+ * contain aligned dimensions of the input JPEG image and do it only
+ * if crop rectangle hasn't been altered by the user space e.g. with
+ * S_SELECTION ioctl. For encoding assign output buffer dimensions.
+ */
+ if (!ct->crop_altered &&
+ ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
+ (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
+ ct->crop_rect.width = pix->width;
+ ct->crop_rect.height = pix->height;
+ }
+
+ /*
+ * Prevent downscaling to YUV420 format by more than 2
+ * for Exynos3250 SoC as it produces broken raw image
+ * in such cases.
+ */
+ if (ct->mode == S5P_JPEG_DECODE &&
+ f_type == FMT_TYPE_CAPTURE &&
+ ct->jpeg->variant->version == SJPEG_EXYNOS3250 &&
+ pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
+ ct->scale_factor > 2) {
+ scale_rect.width = ct->out_q.w / 2;
+ scale_rect.height = ct->out_q.h / 2;
+ exynos3250_jpeg_try_downscale(ct, &scale_rect);
}
return 0;
@@ -1229,6 +1429,101 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
}
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+ struct v4l2_rect *r)
+{
+ int w_ratio, h_ratio, scale_factor, cur_ratio, i;
+
+ w_ratio = ctx->out_q.w / r->width;
+ h_ratio = ctx->out_q.h / r->height;
+
+ scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
+ scale_factor = clamp_val(scale_factor, 1, 8);
+
+ /* Align scale ratio to the nearest power of 2 */
+ for (i = 0; i <= 3; ++i) {
+ cur_ratio = 1 << i;
+ if (scale_factor <= cur_ratio) {
+ ctx->scale_factor = cur_ratio;
+ break;
+ }
+ }
+
+ r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
+ r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
+
+ ctx->crop_rect.width = r->width;
+ ctx->crop_rect.height = r->height;
+ ctx->crop_rect.left = 0;
+ ctx->crop_rect.top = 0;
+
+ ctx->crop_altered = true;
+
+ return 0;
+}
+
+/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
+static int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+ if (a->left < b->left || a->top < b->top)
+ return 0;
+ if (a->left + a->width > b->left + b->width)
+ return 0;
+ if (a->top + a->height > b->top + b->height)
+ return 0;
+
+ return 1;
+}
+
+static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
+ struct v4l2_rect *r)
+{
+ struct v4l2_rect base_rect;
+ int w_step, h_step;
+
+ switch (ctx->cap_q.fmt->fourcc) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ w_step = 1;
+ h_step = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ w_step = 2;
+ h_step = 2;
+ break;
+ default:
+ w_step = 1;
+ h_step = 1;
+ break;
+ }
+
+ base_rect.top = 0;
+ base_rect.left = 0;
+ base_rect.width = ctx->out_q.w;
+ base_rect.height = ctx->out_q.h;
+
+ r->width = round_down(r->width, w_step);
+ r->height = round_down(r->height, h_step);
+ r->left = round_down(r->left, 2);
+ r->top = round_down(r->top, 2);
+
+ if (!enclosed_rectangle(r, &base_rect))
+ return -EINVAL;
+
+ ctx->crop_rect.left = r->left;
+ ctx->crop_rect.top = r->top;
+ ctx->crop_rect.width = r->width;
+ ctx->crop_rect.height = r->height;
+
+ ctx->crop_altered = true;
+
+ return 0;
+}
+
+/*
+ * V4L2 controls
+ */
+
static int s5p_jpeg_g_selection(struct file *file, void *priv,
struct v4l2_selection *s)
{
@@ -1243,27 +1538,53 @@ static int s5p_jpeg_g_selection(struct file *file, void *priv,
case V4L2_SEL_TGT_CROP:
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_COMPOSE:
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
s->r.width = ctx->out_q.w;
s->r.height = ctx->out_q.h;
+ s->r.left = 0;
+ s->r.top = 0;
break;
+ case V4L2_SEL_TGT_COMPOSE:
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
case V4L2_SEL_TGT_COMPOSE_PADDED:
- s->r.width = ctx->cap_q.w;
- s->r.height = ctx->cap_q.h;
+ s->r.width = ctx->crop_rect.width;
+ s->r.height = ctx->crop_rect.height;
+ s->r.left = ctx->crop_rect.left;
+ s->r.top = ctx->crop_rect.top;
break;
default:
return -EINVAL;
}
- s->r.left = 0;
- s->r.top = 0;
return 0;
}
/*
* V4L2 controls
*/
+static int s5p_jpeg_s_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
+{
+ struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+ struct v4l2_rect *rect = &s->r;
+ int ret = -EINVAL;
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ if (s->target == V4L2_SEL_TGT_COMPOSE) {
+ if (ctx->mode != S5P_JPEG_DECODE)
+ return -EINVAL;
+ if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+ ret = exynos3250_jpeg_try_downscale(ctx, rect);
+ } else if (s->target == V4L2_SEL_TGT_CROP) {
+ if (ctx->mode != S5P_JPEG_ENCODE)
+ return -EINVAL;
+ if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+ ret = exynos3250_jpeg_try_crop(ctx, rect);
+ }
+
+ return ret;
+}
static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
@@ -1282,36 +1603,53 @@ static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
-static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
+static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
{
- struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
- if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING) {
- if (ctx->jpeg->variant->version == SJPEG_S5P)
- goto error_free;
+ switch (ctx->jpeg->variant->version) {
+ case SJPEG_S5P:
+ return 0;
+ case SJPEG_EXYNOS3250:
+ /*
+ * The exynos3250 device can produce JPEG image only
+ * of 4:4:4 subsampling when given RGB32 source image.
+ */
+ if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+ *ctrl_val = 0;
+ break;
+ case SJPEG_EXYNOS4:
/*
* The exynos4x12 device requires input raw image fourcc
* to be V4L2_PIX_FMT_GREY if gray jpeg format
* is to be set.
*/
if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
- ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
- ret = -EINVAL;
- goto error_free;
- }
- /*
- * The exynos4x12 device requires resulting jpeg subsampling
- * not to be lower than the input raw image subsampling.
- */
- if (ctx->out_q.fmt->subsampling > ctrl->val)
- ctrl->val = ctx->out_q.fmt->subsampling;
+ *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
+ return -EINVAL;
+ break;
}
-error_free:
+ /*
+ * The exynos4x12 and exynos3250 devices require resulting
+ * jpeg subsampling not to be lower than the input raw image
+ * subsampling.
+ */
+ if (ctx->out_q.fmt->subsampling > *ctrl_val)
+ *ctrl_val = ctx->out_q.fmt->subsampling;
+
+ return 0;
+}
+
+static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+ if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
+ ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
+
spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
return ret;
}
@@ -1414,6 +1752,7 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
.vidioc_g_selection = s5p_jpeg_g_selection,
+ .vidioc_s_selection = s5p_jpeg_s_selection,
};
/*
@@ -1604,6 +1943,135 @@ static void exynos4_jpeg_device_run(void *priv)
spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
}
+static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct s5p_jpeg_fmt *fmt;
+ struct vb2_buffer *vb;
+ struct s5p_jpeg_addr jpeg_addr;
+ u32 pix_size;
+
+ pix_size = ctx->cap_q.w * ctx->cap_q.h;
+
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ fmt = ctx->out_q.fmt;
+ } else {
+ vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ fmt = ctx->cap_q.fmt;
+ }
+
+ jpeg_addr.y = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+ if (fmt->colplanes == 2) {
+ jpeg_addr.cb = jpeg_addr.y + pix_size;
+ } else if (fmt->colplanes == 3) {
+ jpeg_addr.cb = jpeg_addr.y + pix_size;
+ if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
+ jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
+ else
+ jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
+ }
+
+ exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
+}
+
+static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
+{
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *vb;
+ unsigned int jpeg_addr = 0;
+
+ if (ctx->mode == S5P_JPEG_ENCODE)
+ vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+ else
+ vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+
+ jpeg_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
+}
+
+static void exynos3250_jpeg_device_run(void *priv)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+ exynos3250_jpeg_reset(jpeg->regs);
+ exynos3250_jpeg_set_dma_num(jpeg->regs);
+ exynos3250_jpeg_poweron(jpeg->regs);
+ exynos3250_jpeg_clk_set(jpeg->regs);
+ exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
+
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ exynos3250_jpeg_input_raw_fmt(jpeg->regs,
+ ctx->out_q.fmt->fourcc);
+ exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
+
+ /*
+ * JPEG IP allows storing 4 quantization tables
+ * We fill table 0 for luma and table 1 for chroma
+ */
+ s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+ s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+ /* use table 0 for Y */
+ exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
+ /* use table 1 for Cb and Cr*/
+ exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
+ exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
+
+ /* Y, Cb, Cr use Huffman table 0 */
+ exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
+ exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
+ exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
+ exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
+ exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
+ exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
+
+ exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
+ exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
+ exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
+ ctx->out_q.w);
+ exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
+ ctx->crop_rect.top);
+ exynos3250_jpeg_set_img_addr(ctx);
+ exynos3250_jpeg_set_jpeg_addr(ctx);
+ exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
+
+ /* ultimately comes from sizeimage from userspace */
+ exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
+
+ if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
+ ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
+ ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+ exynos3250_jpeg_set_y16(jpeg->regs, true);
+ } else {
+ exynos3250_jpeg_set_img_addr(ctx);
+ exynos3250_jpeg_set_jpeg_addr(ctx);
+ exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
+ ctx->cap_q.w);
+ exynos3250_jpeg_offset(jpeg->regs, 0, 0);
+ exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
+ ctx->scale_factor);
+ exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
+ exynos3250_jpeg_output_raw_fmt(jpeg->regs,
+ ctx->cap_q.fmt->fourcc);
+ }
+
+ exynos3250_jpeg_interrupts_enable(jpeg->regs);
+
+ /* JPEG RGB to YCbCr conversion matrix */
+ exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
+
+ exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
+ jpeg->irq_status = 0;
+ exynos3250_jpeg_start(jpeg->regs);
+
+ spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+}
+
static int s5p_jpeg_job_ready(void *priv)
{
struct s5p_jpeg_ctx *ctx = priv;
@@ -1621,8 +2089,14 @@ static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
.device_run = s5p_jpeg_device_run,
.job_ready = s5p_jpeg_job_ready,
.job_abort = s5p_jpeg_job_abort,
-}
-;
+};
+
+static struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
+ .device_run = exynos3250_jpeg_device_run,
+ .job_ready = s5p_jpeg_job_ready,
+ .job_abort = s5p_jpeg_job_abort,
+};
+
static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
.device_run = exynos4_jpeg_device_run,
.job_ready = s5p_jpeg_job_ready,
@@ -1895,6 +2369,70 @@ static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
return IRQ_HANDLED;
}
+static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
+{
+ struct s5p_jpeg *jpeg = dev_id;
+ struct s5p_jpeg_ctx *curr_ctx;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long payload_size = 0;
+ enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+ bool interrupt_timeout = false;
+ u32 irq_status;
+
+ spin_lock(&jpeg->slock);
+
+ irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
+ if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
+ exynos3250_jpeg_clear_timer_status(jpeg->regs);
+ interrupt_timeout = true;
+ dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
+ }
+
+ irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
+ exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
+
+ jpeg->irq_status |= irq_status;
+
+ curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+ if (!curr_ctx)
+ goto exit_unlock;
+
+ if ((irq_status & EXYNOS3250_HEADER_STAT) &&
+ (curr_ctx->mode == S5P_JPEG_DECODE)) {
+ exynos3250_jpeg_rstart(jpeg->regs);
+ goto exit_unlock;
+ }
+
+ if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
+ EXYNOS3250_WDMA_DONE |
+ EXYNOS3250_RDMA_DONE |
+ EXYNOS3250_RESULT_STAT))
+ payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
+ else if (interrupt_timeout)
+ state = VB2_BUF_STATE_ERROR;
+ else
+ goto exit_unlock;
+
+ src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+ dst_buf->v4l2_buf.timecode = src_buf->v4l2_buf.timecode;
+ dst_buf->v4l2_buf.timestamp = src_buf->v4l2_buf.timestamp;
+
+ v4l2_m2m_buf_done(src_buf, state);
+ if (curr_ctx->mode == S5P_JPEG_ENCODE)
+ vb2_set_plane_payload(dst_buf, 0, payload_size);
+ v4l2_m2m_buf_done(dst_buf, state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
+
+ curr_ctx->subsampling =
+ exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
+exit_unlock:
+ spin_unlock(&jpeg->slock);
+ return IRQ_HANDLED;
+}
+
static void *jpeg_get_drv_data(struct device *dev);
/*
@@ -1950,6 +2488,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
}
dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
+ jpeg->sclk = clk_get(&pdev->dev, "sclk");
+ if (IS_ERR(jpeg->sclk))
+ dev_info(&pdev->dev, "sclk clock not available\n");
+
/* v4l2 device */
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
if (ret) {
@@ -2057,6 +2599,8 @@ device_register_rollback:
clk_get_rollback:
clk_put(jpeg->clk);
+ if (!IS_ERR(jpeg->sclk))
+ clk_put(jpeg->sclk);
return ret;
}
@@ -2075,10 +2619,15 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
v4l2_m2m_release(jpeg->m2m_dev);
v4l2_device_unregister(&jpeg->v4l2_dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
+ if (!pm_runtime_status_suspended(&pdev->dev)) {
clk_disable_unprepare(jpeg->clk);
+ if (!IS_ERR(jpeg->sclk))
+ clk_disable_unprepare(jpeg->sclk);
+ }
clk_put(jpeg->clk);
+ if (!IS_ERR(jpeg->sclk))
+ clk_put(jpeg->sclk);
return 0;
}
@@ -2088,6 +2637,8 @@ static int s5p_jpeg_runtime_suspend(struct device *dev)
struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
clk_disable_unprepare(jpeg->clk);
+ if (!IS_ERR(jpeg->sclk))
+ clk_disable_unprepare(jpeg->sclk);
return 0;
}
@@ -2102,15 +2653,24 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
if (ret < 0)
return ret;
+ if (!IS_ERR(jpeg->sclk)) {
+ ret = clk_prepare_enable(jpeg->sclk);
+ if (ret < 0)
+ return ret;
+ }
+
spin_lock_irqsave(&jpeg->slock, flags);
/*
- * JPEG IP allows storing two Huffman tables for each component
+ * JPEG IP allows storing two Huffman tables for each component.
* We fill table 0 for each component and do this here only
- * for S5PC210 device as Exynos4x12 requires programming its
- * Huffman tables each time the encoding process is initialized.
+ * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires
+ * programming its Huffman tables each time the encoding process
+ * is initialized, and thus it is accomplished in the device_run
+ * callback of m2m_ops.
*/
- if (jpeg->variant->version == SJPEG_S5P) {
+ if (jpeg->variant->version == SJPEG_S5P ||
+ jpeg->variant->version == SJPEG_EXYNOS3250) {
s5p_jpeg_set_hdctbl(jpeg->regs);
s5p_jpeg_set_hdctblg(jpeg->regs);
s5p_jpeg_set_hactbl(jpeg->regs);
@@ -2150,6 +2710,13 @@ static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
.fmt_ver_flag = SJPEG_FMT_FLAG_S5P,
};
+static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
+ .version = SJPEG_EXYNOS3250,
+ .jpeg_irq = exynos3250_jpeg_irq,
+ .m2m_ops = &exynos3250_jpeg_m2m_ops,
+ .fmt_ver_flag = SJPEG_FMT_FLAG_EXYNOS3250,
+};
+
static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
.version = SJPEG_EXYNOS4,
.jpeg_irq = exynos4_jpeg_irq,
@@ -2162,8 +2729,11 @@ static const struct of_device_id samsung_jpeg_match[] = {
.compatible = "samsung,s5pv210-jpeg",
.data = &s5p_jpeg_drvdata,
}, {
+ .compatible = "samsung,exynos3250-jpeg",
+ .data = &exynos3250_jpeg_drvdata,
+ }, {
.compatible = "samsung,exynos4210-jpeg",
- .data = &s5p_jpeg_drvdata,
+ .data = &exynos4_jpeg_drvdata,
}, {
.compatible = "samsung,exynos4212-jpeg",
.data = &exynos4_jpeg_drvdata,
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h
index 3e4786329727..764b32de326b 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.h
@@ -35,6 +35,8 @@
#define S5P_JPEG_COEF32 0x6e
#define S5P_JPEG_COEF33 0x13
+#define EXYNOS3250_IRQ_TIMEOUT 0x10000000
+
/* a selection of JPEG markers */
#define TEM 0x01
#define SOF0 0xc0
@@ -49,9 +51,10 @@
#define SJPEG_FMT_FLAG_DEC_CAPTURE (1 << 2)
#define SJPEG_FMT_FLAG_DEC_OUTPUT (1 << 3)
#define SJPEG_FMT_FLAG_S5P (1 << 4)
-#define SJPEG_FMT_FLAG_EXYNOS4 (1 << 5)
-#define SJPEG_FMT_RGB (1 << 6)
-#define SJPEG_FMT_NON_RGB (1 << 7)
+#define SJPEG_FMT_FLAG_EXYNOS3250 (1 << 5)
+#define SJPEG_FMT_FLAG_EXYNOS4 (1 << 6)
+#define SJPEG_FMT_RGB (1 << 7)
+#define SJPEG_FMT_NON_RGB (1 << 8)
#define S5P_JPEG_ENCODE 0
#define S5P_JPEG_DECODE 1
@@ -65,8 +68,9 @@
/* Version numbers */
-#define SJPEG_S5P 1
-#define SJPEG_EXYNOS4 2
+#define SJPEG_S5P 1
+#define SJPEG_EXYNOS3250 2
+#define SJPEG_EXYNOS4 3
enum exynos4_jpeg_result {
OK_ENC_OR_DEC,
@@ -95,8 +99,13 @@ enum exynos4_jpeg_img_quality_level {
* @regs: JPEG IP registers mapping
* @irq: JPEG IP irq
* @clk: JPEG IP clock
+ * @sclk: Exynos3250 JPEG IP special clock
* @dev: JPEG IP struct device
* @alloc_ctx: videobuf2 memory allocator's context
+ * @variant: driver variant to be used
+ * @irq_status interrupt flags set during single encode/decode
+ operation
+
*/
struct s5p_jpeg {
struct mutex lock;
@@ -111,9 +120,11 @@ struct s5p_jpeg {
unsigned int irq;
enum exynos4_jpeg_result irq_ret;
struct clk *clk;
+ struct clk *sclk;
struct device *dev;
void *alloc_ctx;
struct s5p_jpeg_variant *variant;
+ u32 irq_status;
};
struct s5p_jpeg_variant {
@@ -164,9 +175,15 @@ struct s5p_jpeg_q_data {
* @jpeg: JPEG IP device for this context
* @mode: compression (encode) operation or decompression (decode)
* @compr_quality: destination image quality in compression (encode) mode
+ * @restart_interval: JPEG restart interval for JPEG encoding
+ * @subsampling: subsampling of a raw format or a JPEG
* @out_q: source (output) queue information
- * @cap_fmt: destination (capture) queue queue information
+ * @cap_q: destination (capture) queue queue information
+ * @scale_factor: scale factor for JPEG decoding
+ * @crop_rect: a rectangle representing crop area of the output buffer
+ * @fh: V4L2 file handle
* @hdr_parsed: set if header has been parsed during decompression
+ * @crop_altered: set if crop rectangle has been altered by the user space
* @ctrl_handler: controls handler
*/
struct s5p_jpeg_ctx {
@@ -177,8 +194,11 @@ struct s5p_jpeg_ctx {
unsigned short subsampling;
struct s5p_jpeg_q_data out_q;
struct s5p_jpeg_q_data cap_q;
+ unsigned int scale_factor;
+ struct v4l2_rect crop_rect;
struct v4l2_fh fh;
bool hdr_parsed;
+ bool crop_altered;
struct v4l2_ctrl_handler ctrl_handler;
};
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
new file mode 100644
index 000000000000..d26e1f846553
--- /dev/null
+++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
@@ -0,0 +1,487 @@
+/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+
+#include "jpeg-core.h"
+#include "jpeg-regs.h"
+#include "jpeg-hw-exynos3250.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs)
+{
+ u32 reg = 0;
+ int count = 1000;
+
+ writel(1, regs + EXYNOS3250_SW_RESET);
+ /* no other way but polling for when JPEG IP becomes operational */
+ while (reg != 0 && --count > 0) {
+ udelay(1);
+ cpu_relax();
+ reg = readl(regs + EXYNOS3250_SW_RESET);
+ }
+
+ reg = 0;
+ count = 1000;
+
+ while (reg != 1 && --count > 0) {
+ writel(1, regs + EXYNOS3250_JPGDRI);
+ udelay(1);
+ cpu_relax();
+ reg = readl(regs + EXYNOS3250_JPGDRI);
+ }
+
+ writel(0, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_poweron(void __iomem *regs)
+{
+ writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
+}
+
+void exynos3250_jpeg_set_dma_num(void __iomem *regs)
+{
+ writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &
+ EXYNOS3250_WDMA_ISSUE_NUM_MASK) |
+ ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &
+ EXYNOS3250_RDMA_ISSUE_NUM_MASK) |
+ ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &
+ EXYNOS3250_ISSUE_GATHER_NUM_MASK),
+ regs + EXYNOS3250_DMA_ISSUE_NUM);
+}
+
+void exynos3250_jpeg_clk_set(void __iomem *base)
+{
+ u32 reg;
+
+ reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;
+
+ writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+ u32 reg;
+
+ reg = readl(regs + EXYNOS3250_JPGCMOD) &
+ EXYNOS3250_MODE_Y16_MASK;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_RGB32:
+ reg |= EXYNOS3250_MODE_SEL_ARGB8888;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ reg |= EXYNOS3250_MODE_SEL_RGB565;
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
+ EXYNOS3250_SRC_SWAP_UV;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
+ EXYNOS3250_SRC_SWAP_UV;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ reg |= EXYNOS3250_MODE_SEL_420_3P;
+ break;
+ default:
+ break;
+
+ }
+
+ writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)
+{
+ u32 reg;
+
+ reg = readl(regs + EXYNOS3250_JPGCMOD);
+ if (y16)
+ reg |= EXYNOS3250_MODE_Y16;
+ else
+ reg &= ~EXYNOS3250_MODE_Y16_MASK;
+ writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)
+{
+ u32 reg, m;
+
+ if (mode == S5P_JPEG_ENCODE)
+ m = EXYNOS3250_PROC_MODE_COMPR;
+ else
+ m = EXYNOS3250_PROC_MODE_DECOMPR;
+ reg = readl(regs + EXYNOS3250_JPGMOD);
+ reg &= ~EXYNOS3250_PROC_MODE_MASK;
+ reg |= m;
+ writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
+{
+ u32 reg, m = 0;
+
+ switch (mode) {
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+ m = EXYNOS3250_SUBSAMPLING_MODE_444;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+ m = EXYNOS3250_SUBSAMPLING_MODE_422;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+ m = EXYNOS3250_SUBSAMPLING_MODE_420;
+ break;
+ }
+
+ reg = readl(regs + EXYNOS3250_JPGMOD);
+ reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;
+ reg |= m;
+ writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_JPGMOD) &
+ EXYNOS3250_SUBSAMPLING_MODE_MASK;
+}
+
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+ u32 reg;
+
+ reg = dri & EXYNOS3250_JPGDRI_MASK;
+ writel(reg, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+ unsigned long reg;
+
+ reg = readl(regs + EXYNOS3250_QHTBL);
+ reg &= ~EXYNOS3250_QT_NUM_MASK(t);
+ reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &
+ EXYNOS3250_QT_NUM_MASK(t);
+ writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+ unsigned long reg;
+
+ reg = readl(regs + EXYNOS3250_QHTBL);
+ reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);
+ /* this driver uses table 0 for all color components */
+ reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &
+ EXYNOS3250_HT_NUM_AC_MASK(t);
+ writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+ unsigned long reg;
+
+ reg = readl(regs + EXYNOS3250_QHTBL);
+ reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);
+ /* this driver uses table 0 for all color components */
+ reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &
+ EXYNOS3250_HT_NUM_DC_MASK(t);
+ writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)
+{
+ u32 reg;
+
+ reg = y & EXYNOS3250_JPGY_MASK;
+ writel(reg, regs + EXYNOS3250_JPGY);
+}
+
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)
+{
+ u32 reg;
+
+ reg = x & EXYNOS3250_JPGX_MASK;
+ writel(reg, regs + EXYNOS3250_JPGX);
+}
+
+unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_JPGY);
+}
+
+unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_JPGX);
+}
+
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs)
+{
+ u32 reg;
+
+ reg = readl(regs + EXYNOS3250_JPGINTSE);
+ reg |= (EXYNOS3250_JPEG_DONE_EN |
+ EXYNOS3250_WDMA_DONE_EN |
+ EXYNOS3250_RDMA_DONE_EN |
+ EXYNOS3250_ENC_STREAM_INT_EN |
+ EXYNOS3250_CORE_DONE_EN |
+ EXYNOS3250_ERR_INT_EN |
+ EXYNOS3250_HEAD_INT_EN);
+ writel(reg, regs + EXYNOS3250_JPGINTSE);
+}
+
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)
+{
+ u32 reg;
+
+ reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;
+ writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);
+}
+
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+ u32 reg;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_RGB32:
+ reg = EXYNOS3250_OUT_FMT_ARGB8888;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ reg = EXYNOS3250_OUT_FMT_RGB565;
+ break;
+ case V4L2_PIX_FMT_RGB565X:
+ reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
+ EXYNOS3250_OUT_SWAP_UV;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
+ EXYNOS3250_OUT_SWAP_UV;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ reg = EXYNOS3250_OUT_FMT_420_3P;
+ break;
+ default:
+ reg = 0;
+ break;
+ }
+
+ writel(reg, regs + EXYNOS3250_OUTFORM);
+}
+
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
+{
+ writel(addr, regs + EXYNOS3250_JPG_JPGADR);
+}
+
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)
+{
+ writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);
+ writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);
+ writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);
+}
+
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+ unsigned int width)
+{
+ u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;
+
+ switch (img_fmt) {
+ case V4L2_PIX_FMT_RGB32:
+ reg_luma = 4 * width;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ reg_luma = 2 * width;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ reg_luma = width;
+ reg_cb = reg_luma;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ reg_luma = width;
+ reg_cb = reg_cr = reg_luma / 2;
+ break;
+ default:
+ break;
+ }
+
+ writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);
+ writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);
+ writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);
+}
+
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+ unsigned int y_offset)
+{
+ u32 reg;
+
+ reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &
+ EXYNOS3250_LUMA_YY_OFFSET_MASK;
+ reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &
+ EXYNOS3250_LUMA_YX_OFFSET_MASK;
+
+ writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);
+
+ reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &
+ EXYNOS3250_CHROMA_YY_OFFSET_MASK;
+ reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &
+ EXYNOS3250_CHROMA_YX_OFFSET_MASK;
+
+ writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);
+
+ reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &
+ EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;
+ reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &
+ EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;
+
+ writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);
+}
+
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)
+{
+ if (mode == S5P_JPEG_ENCODE) {
+ writel(EXYNOS3250_JPEG_ENC_COEF1,
+ base + EXYNOS3250_JPG_COEF(1));
+ writel(EXYNOS3250_JPEG_ENC_COEF2,
+ base + EXYNOS3250_JPG_COEF(2));
+ writel(EXYNOS3250_JPEG_ENC_COEF3,
+ base + EXYNOS3250_JPG_COEF(3));
+ } else {
+ writel(EXYNOS3250_JPEG_DEC_COEF1,
+ base + EXYNOS3250_JPG_COEF(1));
+ writel(EXYNOS3250_JPEG_DEC_COEF2,
+ base + EXYNOS3250_JPG_COEF(2));
+ writel(EXYNOS3250_JPEG_DEC_COEF3,
+ base + EXYNOS3250_JPG_COEF(3));
+ }
+}
+
+void exynos3250_jpeg_start(void __iomem *regs)
+{
+ writel(1, regs + EXYNOS3250_JSTART);
+}
+
+void exynos3250_jpeg_rstart(void __iomem *regs)
+{
+ writel(1, regs + EXYNOS3250_JRSTART);
+}
+
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_JPGINTST);
+}
+
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+ unsigned int value)
+{
+ return writel(value, regs + EXYNOS3250_JPGINTST);
+}
+
+unsigned int exynos3250_jpeg_operating(void __iomem *regs)
+{
+ return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
+}
+
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
+}
+
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs,
+ unsigned int size)
+{
+ writel(size & EXYNOS3250_DEC_STREAM_MASK,
+ regs + EXYNOS3250_DEC_STREAM_SIZE);
+}
+
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,
+ unsigned int sratio)
+{
+ switch (sratio) {
+ case 1:
+ default:
+ sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
+ break;
+ case 2:
+ sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;
+ break;
+ case 4:
+ sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;
+ break;
+ case 8:
+ sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;
+ break;
+ }
+
+ writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,
+ regs + EXYNOS3250_DEC_SCALING_RATIO);
+}
+
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)
+{
+ time_value &= EXYNOS3250_TIMER_INIT_MASK;
+
+ writel(EXYNOS3250_TIMER_INT_STAT | time_value,
+ regs + EXYNOS3250_TIMER_SE);
+}
+
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
+{
+ return readl(regs + EXYNOS3250_TIMER_ST);
+}
+
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
+{
+ writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
+}
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
new file mode 100644
index 000000000000..b6e3be8b5008
--- /dev/null
+++ b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
@@ -0,0 +1,60 @@
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef JPEG_HW_EXYNOS3250_H_
+#define JPEG_HW_EXYNOS3250_H_
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+
+#include "jpeg-regs.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs);
+void exynos3250_jpeg_poweron(void __iomem *regs);
+void exynos3250_jpeg_set_dma_num(void __iomem *regs);
+void exynos3250_jpeg_clk_set(void __iomem *base);
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16);
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode);
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs);
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri);
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y);
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x);
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs);
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_outform_raw(void __iomem *regs, unsigned long format);
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr);
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr);
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+ unsigned int width);
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+ unsigned int y_offset);
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode);
+void exynos3250_jpeg_start(void __iomem *regs);
+void exynos3250_jpeg_rstart(void __iomem *regs);
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs);
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+ unsigned int value);
+unsigned int exynos3250_jpeg_operating(void __iomem *regs);
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs);
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio);
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value);
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs);
+void exynos3250_jpeg_set_timer_status(void __iomem *regs);
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs);
+
+#endif /* JPEG_HW_EXYNOS3250_H_ */
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
index 57fb05bb8c77..050fc440248f 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-regs.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
@@ -2,7 +2,7 @@
*
* Register definition file for Samsung JPEG codec driver
*
- * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
@@ -373,5 +373,250 @@
/* JPEG AC chrominance (values) Huffman table register */
#define EXYNOS4_HUFF_TBL_HACCV 0x310
+/* Register and bit definitions for Exynos 3250 */
+
+/* JPEG mode register */
+#define EXYNOS3250_JPGMOD 0x00
+#define EXYNOS3250_PROC_MODE_MASK (0x1 << 3)
+#define EXYNOS3250_PROC_MODE_DECOMPR (0x1 << 3)
+#define EXYNOS3250_PROC_MODE_COMPR (0x0 << 3)
+#define EXYNOS3250_SUBSAMPLING_MODE_MASK (0x7 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_444 (0x0 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_422 (0x1 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_420 (0x2 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_411 (0x6 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_GRAY (0x3 << 0)
+
+/* JPEG operation status register */
+#define EXYNOS3250_JPGOPR 0x04
+#define EXYNOS3250_JPGOPR_MASK 0x01
+
+/* Quantization and Huffman tables register */
+#define EXYNOS3250_QHTBL 0x08
+#define EXYNOS3250_QT_NUM_SHIFT(t) ((((t) - 1) << 1) + 8)
+#define EXYNOS3250_QT_NUM_MASK(t) (0x3 << EXYNOS3250_QT_NUM_SHIFT(t))
+
+/* Huffman tables */
+#define EXYNOS3250_HT_NUM_AC_SHIFT(t) (((t) << 1) - 1)
+#define EXYNOS3250_HT_NUM_AC_MASK(t) (0x1 << EXYNOS3250_HT_NUM_AC_SHIFT(t))
+
+#define EXYNOS3250_HT_NUM_DC_SHIFT(t) (((t) - 1) << 1)
+#define EXYNOS3250_HT_NUM_DC_MASK(t) (0x1 << EXYNOS3250_HT_NUM_DC_SHIFT(t))
+
+/* JPEG restart interval register */
+#define EXYNOS3250_JPGDRI 0x0c
+#define EXYNOS3250_JPGDRI_MASK 0xffff
+
+/* JPEG vertical resolution register */
+#define EXYNOS3250_JPGY 0x10
+#define EXYNOS3250_JPGY_MASK 0xffff
+
+/* JPEG horizontal resolution register */
+#define EXYNOS3250_JPGX 0x14
+#define EXYNOS3250_JPGX_MASK 0xffff
+
+/* JPEG byte count register */
+#define EXYNOS3250_JPGCNT 0x18
+#define EXYNOS3250_JPGCNT_MASK 0xffffff
+
+/* JPEG interrupt mask register */
+#define EXYNOS3250_JPGINTSE 0x1c
+#define EXYNOS3250_JPEG_DONE_EN (1 << 11)
+#define EXYNOS3250_WDMA_DONE_EN (1 << 10)
+#define EXYNOS3250_RDMA_DONE_EN (1 << 9)
+#define EXYNOS3250_ENC_STREAM_INT_EN (1 << 8)
+#define EXYNOS3250_CORE_DONE_EN (1 << 5)
+#define EXYNOS3250_ERR_INT_EN (1 << 4)
+#define EXYNOS3250_HEAD_INT_EN (1 << 3)
+
+/* JPEG interrupt status register */
+#define EXYNOS3250_JPGINTST 0x20
+#define EXYNOS3250_JPEG_DONE (1 << 11)
+#define EXYNOS3250_WDMA_DONE (1 << 10)
+#define EXYNOS3250_RDMA_DONE (1 << 9)
+#define EXYNOS3250_ENC_STREAM_STAT (1 << 8)
+#define EXYNOS3250_RESULT_STAT (1 << 5)
+#define EXYNOS3250_STREAM_STAT (1 << 4)
+#define EXYNOS3250_HEADER_STAT (1 << 3)
+
+/*
+ * Base address of the luma component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_LUMA_BASE 0x100
+#define EXYNOS3250_SRC_TILE_EN_MASK 0x100
+
+/* Stride of source or destination luma raw image buffer */
+#define EXYNOS3250_LUMA_STRIDE 0x104
+
+/* Horizontal/vertical offset of active region in luma raw image buffer */
+#define EXYNOS3250_LUMA_XY_OFFSET 0x108
+#define EXYNOS3250_LUMA_YY_OFFSET_SHIFT 18
+#define EXYNOS3250_LUMA_YY_OFFSET_MASK (0x1fff << EXYNOS3250_LUMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_LUMA_YX_OFFSET_SHIFT 2
+#define EXYNOS3250_LUMA_YX_OFFSET_MASK (0x1fff << EXYNOS3250_LUMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cb) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_BASE 0x10c
+
+/* Stride of source or destination chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_STRIDE 0x110
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_XY_OFFSET 0x114
+#define EXYNOS3250_CHROMA_YY_OFFSET_SHIFT 18
+#define EXYNOS3250_CHROMA_YY_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_YX_OFFSET_SHIFT 2
+#define EXYNOS3250_CHROMA_YX_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cr) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_CR_BASE 0x118
+
+/* Stride of source or destination chroma(Cr) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_STRIDE 0x11c
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_XY_OFFSET 0x120
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT 18
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT 2
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK (0x1fff << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT)
+
+/* Raw image data r/w address register */
+#define EXYNOS3250_JPG_IMGADR 0x50
+
+/* Source or destination JPEG file DMA buffer address */
+#define EXYNOS3250_JPG_JPGADR 0x124
+
+/* Coefficients for RGB-to-YCbCr converter register */
+#define EXYNOS3250_JPG_COEF(n) (0x128 + (((n) - 1) << 2))
+#define EXYNOS3250_COEF_SHIFT(j) ((3 - (j)) << 3)
+#define EXYNOS3250_COEF_MASK(j) (0xff << EXYNOS3250_COEF_SHIFT(j))
+
+/* Raw input format setting */
+#define EXYNOS3250_JPGCMOD 0x134
+#define EXYNOS3250_SRC_TILE_EN (0x1 << 10)
+#define EXYNOS3250_SRC_NV_MASK (0x1 << 9)
+#define EXYNOS3250_SRC_NV12 (0x0 << 9)
+#define EXYNOS3250_SRC_NV21 (0x1 << 9)
+#define EXYNOS3250_SRC_BIG_ENDIAN_MASK (0x1 << 8)
+#define EXYNOS3250_SRC_BIG_ENDIAN (0x1 << 8)
+#define EXYNOS3250_MODE_SEL_MASK (0x7 << 5)
+#define EXYNOS3250_MODE_SEL_420_2P (0x0 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_LUM_CHR (0x1 << 5)
+#define EXYNOS3250_MODE_SEL_RGB565 (0x2 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_CHR_LUM (0x3 << 5)
+#define EXYNOS3250_MODE_SEL_ARGB8888 (0x4 << 5)
+#define EXYNOS3250_MODE_SEL_420_3P (0x5 << 5)
+#define EXYNOS3250_SRC_SWAP_RGB (0x1 << 3)
+#define EXYNOS3250_SRC_SWAP_UV (0x1 << 2)
+#define EXYNOS3250_MODE_Y16_MASK (0x1 << 1)
+#define EXYNOS3250_MODE_Y16 (0x1 << 1)
+#define EXYNOS3250_HALF_EN_MASK (0x1 << 0)
+#define EXYNOS3250_HALF_EN (0x1 << 0)
+
+/* Power on/off and clock down control */
+#define EXYNOS3250_JPGCLKCON 0x138
+#define EXYNOS3250_CLK_DOWN_READY (0x1 << 1)
+#define EXYNOS3250_POWER_ON (0x1 << 0)
+
+/* Start compression or decompression */
+#define EXYNOS3250_JSTART 0x13c
+
+/* Restart decompression after header analysis */
+#define EXYNOS3250_JRSTART 0x140
+
+/* JPEG SW reset register */
+#define EXYNOS3250_SW_RESET 0x144
+
+/* JPEG timer setting register */
+#define EXYNOS3250_TIMER_SE 0x148
+#define EXYNOS3250_TIMER_INT_EN_SHIFT 31
+#define EXYNOS3250_TIMER_INT_EN (1 << EXYNOS3250_TIMER_INT_EN_SHIFT)
+#define EXYNOS3250_TIMER_INIT_MASK 0x7fffffff
+
+/* JPEG timer status register */
+#define EXYNOS3250_TIMER_ST 0x14c
+#define EXYNOS3250_TIMER_INT_STAT_SHIFT 31
+#define EXYNOS3250_TIMER_INT_STAT (1 << EXYNOS3250_TIMER_INT_STAT_SHIFT)
+#define EXYNOS3250_TIMER_CNT_SHIFT 0
+#define EXYNOS3250_TIMER_CNT_MASK 0x7fffffff
+
+/* Command status register */
+#define EXYNOS3250_COMSTAT 0x150
+#define EXYNOS3250_CUR_PROC_MODE (0x1 << 1)
+#define EXYNOS3250_CUR_COM_MODE (0x1 << 0)
+
+/* JPEG decompression output format register */
+#define EXYNOS3250_OUTFORM 0x154
+#define EXYNOS3250_OUT_ALPHA_MASK (0xff << 24)
+#define EXYNOS3250_OUT_TILE_EN (0x1 << 10)
+#define EXYNOS3250_OUT_NV_MASK (0x1 << 9)
+#define EXYNOS3250_OUT_NV12 (0x0 << 9)
+#define EXYNOS3250_OUT_NV21 (0x1 << 9)
+#define EXYNOS3250_OUT_BIG_ENDIAN_MASK (0x1 << 8)
+#define EXYNOS3250_OUT_BIG_ENDIAN (0x1 << 8)
+#define EXYNOS3250_OUT_SWAP_RGB (0x1 << 7)
+#define EXYNOS3250_OUT_SWAP_UV (0x1 << 6)
+#define EXYNOS3250_OUT_FMT_MASK (0x7 << 0)
+#define EXYNOS3250_OUT_FMT_420_2P (0x0 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_LUM_CHR (0x1 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_CHR_LUM (0x3 << 0)
+#define EXYNOS3250_OUT_FMT_420_3P (0x4 << 0)
+#define EXYNOS3250_OUT_FMT_RGB565 (0x5 << 0)
+#define EXYNOS3250_OUT_FMT_ARGB8888 (0x6 << 0)
+
+/* Input JPEG stream byte size for decompression */
+#define EXYNOS3250_DEC_STREAM_SIZE 0x158
+#define EXYNOS3250_DEC_STREAM_MASK 0x1fffffff
+
+/* The upper bound of the byte size of output compressed stream */
+#define EXYNOS3250_ENC_STREAM_BOUND 0x15c
+#define EXYNOS3250_ENC_STREAM_BOUND_MASK 0xffffc0
+
+/* Scale-down ratio when decoding */
+#define EXYNOS3250_DEC_SCALING_RATIO 0x160
+#define EXYNOS3250_DEC_SCALE_FACTOR_MASK 0x3
+#define EXYNOS3250_DEC_SCALE_FACTOR_8_8 0x0
+#define EXYNOS3250_DEC_SCALE_FACTOR_4_8 0x1
+#define EXYNOS3250_DEC_SCALE_FACTOR_2_8 0x2
+#define EXYNOS3250_DEC_SCALE_FACTOR_1_8 0x3
+
+/* Error check */
+#define EXYNOS3250_CRC_RESULT 0x164
+
+/* RDMA and WDMA operation status register */
+#define EXYNOS3250_DMA_OPER_STATUS 0x168
+#define EXYNOS3250_WDMA_OPER_STATUS (0x1 << 1)
+#define EXYNOS3250_RDMA_OPER_STATUS (0x1 << 0)
+
+/* DMA issue gathering number and issue number settings */
+#define EXYNOS3250_DMA_ISSUE_NUM 0x16c
+#define EXYNOS3250_WDMA_ISSUE_NUM_SHIFT 16
+#define EXYNOS3250_WDMA_ISSUE_NUM_MASK (0x7 << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_RDMA_ISSUE_NUM_SHIFT 8
+#define EXYNOS3250_RDMA_ISSUE_NUM_MASK (0x7 << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_ISSUE_GATHER_NUM_SHIFT 0
+#define EXYNOS3250_ISSUE_GATHER_NUM_MASK (0x7 << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT)
+#define EXYNOS3250_DMA_MO_COUNT 0x7
+
+/* Version register */
+#define EXYNOS3250_VERSION 0x1fc
+
+/* RGB <-> YUV conversion coefficients */
+#define EXYNOS3250_JPEG_ENC_COEF1 0x01352e1e
+#define EXYNOS3250_JPEG_ENC_COEF2 0x00b0ae83
+#define EXYNOS3250_JPEG_ENC_COEF3 0x020cdc13
+
+#define EXYNOS3250_JPEG_DEC_COEF1 0x04a80199
+#define EXYNOS3250_JPEG_DEC_COEF2 0x04a9a064
+#define EXYNOS3250_JPEG_DEC_COEF3 0x04a80102
+
#endif /* JPEG_REGS_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 41723180d10c..d35b0418ab37 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -162,7 +162,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work)
/* Double check if there is at least one instance running.
* If no instance is in memory than no firmware should be present */
if (dev->num_inst > 0) {
- ret = s5p_mfc_reload_firmware(dev);
+ ret = s5p_mfc_load_firmware(dev);
if (ret) {
mfc_err("Failed to reload FW\n");
goto unlock;
@@ -724,7 +724,7 @@ static int s5p_mfc_open(struct file *file)
ret = -ENOMEM;
goto err_alloc;
}
- v4l2_fh_init(&ctx->fh, video_devdata(file));
+ v4l2_fh_init(&ctx->fh, vdev);
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
ctx->dev = dev;
@@ -1351,7 +1351,7 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
.port_num = MFC_NUM_PORTS,
.buf_size = &buf_size_v5,
.buf_align = &mfc_buf_align_v5,
- .fw_name = "s5p-mfc.fw",
+ .fw_name[0] = "s5p-mfc.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
@@ -1378,7 +1378,12 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = {
.port_num = MFC_NUM_PORTS_V6,
.buf_size = &buf_size_v6,
.buf_align = &mfc_buf_align_v6,
- .fw_name = "s5p-mfc-v6.fw",
+ .fw_name[0] = "s5p-mfc-v6.fw",
+ /*
+ * v6-v2 firmware contains bug fixes and interface change
+ * for init buffer command
+ */
+ .fw_name[1] = "s5p-mfc-v6-v2.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
@@ -1405,7 +1410,7 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = {
.port_num = MFC_NUM_PORTS_V7,
.buf_size = &buf_size_v7,
.buf_align = &mfc_buf_align_v7,
- .fw_name = "s5p-mfc-v7.fw",
+ .fw_name[0] = "s5p-mfc-v7.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
@@ -1432,7 +1437,7 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = {
.port_num = MFC_NUM_PORTS_V8,
.buf_size = &buf_size_v8,
.buf_align = &mfc_buf_align_v8,
- .fw_name = "s5p-mfc-v8.fw",
+ .fw_name[0] = "s5p-mfc-v8.fw",
};
static struct platform_device_id mfc_driver_ids[] = {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index b04360cd34f0..01816ffb384b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -38,6 +38,8 @@
#define MFC_BANK2_ALIGN_ORDER 13
#define MFC_BASE_ALIGN_ORDER 17
+#define MFC_FW_MAX_VERSIONS 2
+
#include <media/videobuf2-dma-contig.h>
static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
@@ -163,6 +165,11 @@ enum s5p_mfc_decode_arg {
MFC_DEC_RES_CHANGE,
};
+enum s5p_mfc_fw_ver {
+ MFC_FW_V1,
+ MFC_FW_V2,
+};
+
#define MFC_BUF_FLAG_USED (1 << 0)
#define MFC_BUF_FLAG_EOS (1 << 1)
@@ -225,7 +232,7 @@ struct s5p_mfc_variant {
u32 version_bit;
struct s5p_mfc_buf_size *buf_size;
struct s5p_mfc_buf_align *buf_align;
- char *fw_name;
+ char *fw_name[MFC_FW_MAX_VERSIONS];
};
/**
@@ -287,6 +294,7 @@ struct s5p_mfc_priv_buf {
* @warn_start: hardware error code from which warnings start
* @mfc_ops: ops structure holding HW operation function pointers
* @mfc_cmds: cmd structure holding HW commands function pointers
+ * @fw_ver: loaded firmware sub-version
*
*/
struct s5p_mfc_dev {
@@ -331,6 +339,7 @@ struct s5p_mfc_dev {
struct s5p_mfc_hw_ops *mfc_ops;
struct s5p_mfc_hw_cmds *mfc_cmds;
const struct s5p_mfc_regs *mfc_regs;
+ enum s5p_mfc_fw_ver fw_ver;
};
/**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 6c3f8f743900..ca9f78922832 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -38,8 +38,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size,
&dev->bank1, GFP_KERNEL);
- if (IS_ERR_OR_NULL(dev->fw_virt_addr)) {
- dev->fw_virt_addr = NULL;
+ if (!dev->fw_virt_addr) {
mfc_err("Allocating bitprocessor buffer failed\n");
return -ENOMEM;
}
@@ -48,7 +47,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
&bank2_dma_addr, GFP_KERNEL);
- if (IS_ERR(dev->fw_virt_addr)) {
+ if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
dma_free_coherent(dev->mem_dev_l, dev->fw_size,
dev->fw_virt_addr, dev->bank1);
@@ -78,47 +77,23 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
{
struct firmware *fw_blob;
- int err;
+ int i, err = -EINVAL;
/* Firmare has to be present as a separate file or compiled
* into kernel. */
mfc_debug_enter();
- err = request_firmware((const struct firmware **)&fw_blob,
- dev->variant->fw_name, dev->v4l2_dev.dev);
- if (err != 0) {
- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
- return -EINVAL;
- }
- if (fw_blob->size > dev->fw_size) {
- mfc_err("MFC firmware is too big to be loaded\n");
- release_firmware(fw_blob);
- return -ENOMEM;
- }
- if (!dev->fw_virt_addr) {
- mfc_err("MFC firmware is not allocated\n");
- release_firmware(fw_blob);
- return -EINVAL;
+ for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
+ if (!dev->variant->fw_name[i])
+ continue;
+ err = request_firmware((const struct firmware **)&fw_blob,
+ dev->variant->fw_name[i], dev->v4l2_dev.dev);
+ if (!err) {
+ dev->fw_ver = (enum s5p_mfc_fw_ver) i;
+ break;
+ }
}
- memcpy(dev->fw_virt_addr, fw_blob->data, fw_blob->size);
- wmb();
- release_firmware(fw_blob);
- mfc_debug_leave();
- return 0;
-}
-
-/* Reload firmware to MFC */
-int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
-{
- struct firmware *fw_blob;
- int err;
-
- /* Firmare has to be present as a separate file or compiled
- * into kernel. */
- mfc_debug_enter();
- err = request_firmware((const struct firmware **)&fw_blob,
- dev->variant->fw_name, dev->v4l2_dev.dev);
if (err != 0) {
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
return -EINVAL;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 4d93835dec9d..9103258b7df3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -436,6 +436,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret = 0;
struct v4l2_pix_format_mplane *pix_mp;
+ struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
mfc_debug_enter();
ret = vidioc_try_fmt(file, priv, f);
@@ -459,11 +460,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
pix_mp->height = 0;
pix_mp->width = 0;
- if (pix_mp->plane_fmt[0].sizeimage)
- ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
- else
+ if (pix_mp->plane_fmt[0].sizeimage == 0)
pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
DEF_CPB_SIZE;
+ else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)
+ ctx->dec_src_buf_size = buf_size->cpb;
+ else
+ ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
pix_mp->plane_fmt[0].bytesperline = 0;
ctx->state = MFCINST_INIT;
ret = 0;
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 4f5e0ead90c6..c1c12f8d8f68 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -48,6 +48,8 @@
#define WRITEL(data, reg) \
(WARN_ON_ONCE(!(reg)) ? 0 : writel((data), (reg)))
+#define IS_MFCV6_V2(dev) (!IS_MFCV7_PLUS(dev) && dev->fw_ver == MFC_FW_V2)
+
/* Allocate temporary buffers for decoding */
static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
{
@@ -1352,7 +1354,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
WRITEL(ctx->display_delay, mfc_regs->d_display_delay);
}
- if (IS_MFCV7_PLUS(dev)) {
+ if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) {
WRITEL(reg, mfc_regs->d_dec_options);
reg = 0;
}
@@ -1367,7 +1369,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
- if (IS_MFCV7_PLUS(dev))
+ if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev))
WRITEL(reg, mfc_regs->d_init_buffer_options);
else
WRITEL(reg, mfc_regs->d_dec_options);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 11d5f1dada32..b6a8be97a96c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -21,6 +21,8 @@
#include "s5p_mfc_pm.h"
#define MFC_GATE_CLK_NAME "mfc"
+#define MFC_SCLK_NAME "sclk-mfc"
+#define MFC_SCLK_RATE (200 * 1000000)
#define CLK_DEBUG
@@ -50,6 +52,20 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
goto err_p_ip_clk;
}
+ if (dev->variant->version != MFC_VERSION_V6) {
+ pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
+ if (IS_ERR(pm->clock)) {
+ mfc_info("Failed to get MFC special clock control\n");
+ } else {
+ clk_set_rate(pm->clock, MFC_SCLK_RATE);
+ ret = clk_prepare_enable(pm->clock);
+ if (ret) {
+ mfc_err("Failed to enable MFC special clock\n");
+ goto err_s_clk;
+ }
+ }
+ }
+
atomic_set(&pm->power, 0);
#ifdef CONFIG_PM_RUNTIME
pm->device = &dev->plat_dev->dev;
@@ -59,6 +75,9 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
atomic_set(&clk_ref, 0);
#endif
return 0;
+
+err_s_clk:
+ clk_put(pm->clock);
err_p_ip_clk:
clk_put(pm->clock_gate);
err_g_ip_clk:
@@ -67,6 +86,11 @@ err_g_ip_clk:
void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
{
+ if (dev->variant->version != MFC_VERSION_V6 &&
+ pm->clock) {
+ clk_disable_unprepare(pm->clock);
+ clk_put(pm->clock);
+ }
clk_unprepare(pm->clock_gate);
clk_put(pm->clock_gate);
#ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 8a8dbc8fdfde..b4d2696501e4 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -1109,8 +1109,6 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
.ioctl_ops = &mxr_ioctl_ops,
};
strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
- /* let framework control PRIORITY */
- set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
video_set_drvdata(&layer->vfd, layer);
layer->vfd.lock = &layer->mutex;
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index 744e43b480bc..8dc279d4d561 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
pix->bytesperline = vfmt->bytesperline;
pix->sizeimage = vfmt->bytesperline * pix->height *
vfmt->fmt->depth / vfmt->fmt->ydepth;
- pix->priv = 0;
dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
@@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt
pix->pixelformat = fmt->fourcc;
pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat);
- pix->priv = 0;
pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index af39c4665554..6540847f4e1d 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -17,19 +17,6 @@ config SOC_CAMERA_PLATFORM
help
This is a generic SoC camera platform driver, useful for testing
-config MX1_VIDEO
- bool
-
-config VIDEO_MX1
- tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
- depends on BROKEN
- depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA
- select FIQ
- select VIDEOBUF_DMA_CONTIG
- select MX1_VIDEO
- ---help---
- This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface
-
config VIDEO_MX3
tristate "i.MX3x Camera Sensor Interface driver"
depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
@@ -47,6 +34,7 @@ config VIDEO_PXA27x
config VIDEO_RCAR_VIN
tristate "R-Car Video Input (VIN) support"
depends on VIDEO_DEV && SOC_CAMERA
+ depends on ARCH_SHMOBILE || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select SOC_CAMERA_SCALE_CROP
---help---
@@ -55,12 +43,14 @@ config VIDEO_RCAR_VIN
config VIDEO_SH_MOBILE_CSI2
tristate "SuperH Mobile MIPI CSI-2 Interface driver"
depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+ depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
---help---
This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
config VIDEO_SH_MOBILE_CEU
tristate "SuperH Mobile CEU Interface driver"
depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
+ depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select SOC_CAMERA_SCALE_CROP
---help---
@@ -76,7 +66,7 @@ config VIDEO_OMAP1
config VIDEO_MX2
tristate "i.MX27 Camera Sensor Interface driver"
- depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27
+ depends on VIDEO_DEV && SOC_CAMERA && SOC_IMX27
select VIDEOBUF2_DMA_CONTIG
---help---
This is a v4l2 driver for the i.MX27 Camera Sensor Interface
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
index 8aed26d7a64d..2826382dc9f8 100644
--- a/drivers/media/platform/soc_camera/Makefile
+++ b/drivers/media/platform/soc_camera/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
# soc-camera host drivers have to be linked after camera drivers
obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o
-obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 38c723aca438..3408b045b3f1 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -25,6 +25,7 @@
#include <media/atmel-isi.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
+#include <media/v4l2-of.h>
#include <media/videobuf2-dma-contig.h>
#define MAX_BUFFER_NUM 32
@@ -33,6 +34,7 @@
#define VID_LIMIT_BYTES (16 * 1024 * 1024)
#define MIN_FRAME_RATE 15
#define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE)
+#define ISI_DEFAULT_MCLK_FREQ 25000000
/* Frame buffer descriptor */
struct fbd {
@@ -84,7 +86,7 @@ struct atmel_isi {
struct clk *mck;
unsigned int irq;
- struct isi_platform_data *pdata;
+ struct isi_platform_data pdata;
u16 width_flags; /* max 12 bits */
struct list_head video_buffer_list;
@@ -350,7 +352,7 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer)
cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK;
/* Enable linked list */
- cfg1 |= isi->pdata->frate | ISI_CFG1_DISCR;
+ cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR;
/* Enable codec path and ISI */
ctrl = ISI_CTRL_CDC | ISI_CTRL_EN;
@@ -795,7 +797,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
/* Make choises, based on platform preferences */
if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
- if (isi->pdata->hsync_act_low)
+ if (isi->pdata.hsync_act_low)
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
@@ -803,7 +805,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (isi->pdata->vsync_act_low)
+ if (isi->pdata.vsync_act_low)
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
@@ -811,7 +813,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
(common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (isi->pdata->pclk_act_falling)
+ if (isi->pdata.pclk_act_falling)
common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
else
common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
@@ -833,9 +835,9 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd)
if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
- if (isi->pdata->has_emb_sync)
+ if (isi->pdata.has_emb_sync)
cfg1 |= ISI_CFG1_EMB_SYNC;
- if (isi->pdata->full_mode)
+ if (isi->pdata.full_mode)
cfg1 |= ISI_CFG1_FULL_MODE;
isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -876,6 +878,51 @@ static int atmel_isi_remove(struct platform_device *pdev)
return 0;
}
+static int atmel_isi_probe_dt(struct atmel_isi *isi,
+ struct platform_device *pdev)
+{
+ struct device_node *np= pdev->dev.of_node;
+ struct v4l2_of_endpoint ep;
+ int err;
+
+ /* Default settings for ISI */
+ isi->pdata.full_mode = 1;
+ isi->pdata.mck_hz = ISI_DEFAULT_MCLK_FREQ;
+ isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL;
+
+ np = of_graph_get_next_endpoint(np, NULL);
+ if (!np) {
+ dev_err(&pdev->dev, "Could not find the endpoint\n");
+ return -EINVAL;
+ }
+
+ err = v4l2_of_parse_endpoint(np, &ep);
+ if (err) {
+ dev_err(&pdev->dev, "Could not parse the endpoint\n");
+ goto err_probe_dt;
+ }
+
+ switch (ep.bus.parallel.bus_width) {
+ case 8:
+ isi->pdata.data_width_flags = ISI_DATAWIDTH_8;
+ break;
+ case 10:
+ isi->pdata.data_width_flags =
+ ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unsupported bus width: %d\n",
+ ep.bus.parallel.bus_width);
+ err = -EINVAL;
+ goto err_probe_dt;
+ }
+
+err_probe_dt:
+ of_node_put(np);
+
+ return err;
+}
+
static int atmel_isi_probe(struct platform_device *pdev)
{
unsigned int irq;
@@ -887,7 +934,7 @@ static int atmel_isi_probe(struct platform_device *pdev)
struct isi_platform_data *pdata;
pdata = dev->platform_data;
- if (!pdata || !pdata->data_width_flags) {
+ if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) {
dev_err(&pdev->dev,
"No config available for Atmel ISI\n");
return -EINVAL;
@@ -903,7 +950,14 @@ static int atmel_isi_probe(struct platform_device *pdev)
if (IS_ERR(isi->pclk))
return PTR_ERR(isi->pclk);
- isi->pdata = pdata;
+ if (pdata) {
+ memcpy(&isi->pdata, pdata, sizeof(isi->pdata));
+ } else {
+ ret = atmel_isi_probe_dt(isi, pdev);
+ if (ret)
+ return ret;
+ }
+
isi->active = NULL;
spin_lock_init(&isi->lock);
INIT_LIST_HEAD(&isi->video_buffer_list);
@@ -919,7 +973,7 @@ static int atmel_isi_probe(struct platform_device *pdev)
/* Set ISI_MCK's frequency, it should be faster than pixel
* clock.
*/
- ret = clk_set_rate(isi->mck, pdata->mck_hz);
+ ret = clk_set_rate(isi->mck, isi->pdata.mck_hz);
if (ret < 0)
return ret;
}
@@ -953,9 +1007,9 @@ static int atmel_isi_probe(struct platform_device *pdev)
goto err_ioremap;
}
- if (pdata->data_width_flags & ISI_DATAWIDTH_8)
+ if (isi->pdata.data_width_flags & ISI_DATAWIDTH_8)
isi->width_flags = 1 << 7;
- if (pdata->data_width_flags & ISI_DATAWIDTH_10)
+ if (isi->pdata.data_width_flags & ISI_DATAWIDTH_10)
isi->width_flags |= 1 << 9;
isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -980,6 +1034,11 @@ static int atmel_isi_probe(struct platform_device *pdev)
soc_host->v4l2_dev.dev = &pdev->dev;
soc_host->nr = pdev->id;
+ if (isi->pdata.asd_sizes) {
+ soc_host->asd = isi->pdata.asd;
+ soc_host->asd_sizes = isi->pdata.asd_sizes;
+ }
+
ret = soc_camera_host_register(soc_host);
if (ret) {
dev_err(&pdev->dev, "Unable to register soc camera host\n");
@@ -1000,11 +1059,18 @@ err_alloc_ctx:
return ret;
}
+static const struct of_device_id atmel_isi_of_match[] = {
+ { .compatible = "atmel,at91sam9g45-isi" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, atmel_isi_of_match);
+
static struct platform_driver atmel_isi_driver = {
.remove = atmel_isi_remove,
.driver = {
.name = "atmel_isi",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(atmel_isi_of_match),
},
};
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c
deleted file mode 100644
index fea3e61476ae..000000000000
--- a/drivers/media/platform/soc_camera/mx1_camera.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * V4L2 Driver for i.MXL/i.MXL camera (CSI) host
- *
- * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com>
- *
- * Based on PXA SoC camera driver
- * Copyright (C) 2006, Sascha Hauer, Pengutronix
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/videodev2.h>
-
-#include <media/soc_camera.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf-dma-contig.h>
-#include <media/soc_mediabus.h>
-
-#include <asm/dma.h>
-#include <asm/fiq.h>
-#include <mach/dma-mx1-mx2.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <linux/platform_data/camera-mx1.h>
-
-/*
- * CSI registers
- */
-#define CSICR1 0x00 /* CSI Control Register 1 */
-#define CSISR 0x08 /* CSI Status Register */
-#define CSIRXR 0x10 /* CSI RxFIFO Register */
-
-#define CSICR1_RXFF_LEVEL(x) (((x) & 0x3) << 19)
-#define CSICR1_SOF_POL (1 << 17)
-#define CSICR1_SOF_INTEN (1 << 16)
-#define CSICR1_MCLKDIV(x) (((x) & 0xf) << 12)
-#define CSICR1_MCLKEN (1 << 9)
-#define CSICR1_FCC (1 << 8)
-#define CSICR1_BIG_ENDIAN (1 << 7)
-#define CSICR1_CLR_RXFIFO (1 << 5)
-#define CSICR1_GCLK_MODE (1 << 4)
-#define CSICR1_DATA_POL (1 << 2)
-#define CSICR1_REDGE (1 << 1)
-#define CSICR1_EN (1 << 0)
-
-#define CSISR_SFF_OR_INT (1 << 25)
-#define CSISR_RFF_OR_INT (1 << 24)
-#define CSISR_STATFF_INT (1 << 21)
-#define CSISR_RXFF_INT (1 << 18)
-#define CSISR_SOF_INT (1 << 16)
-#define CSISR_DRDY (1 << 0)
-
-#define DRIVER_VERSION "0.0.2"
-#define DRIVER_NAME "mx1-camera"
-
-#define CSI_IRQ_MASK (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
- CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT)
-
-#define CSI_BUS_FLAGS (V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \
- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
- V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW)
-
-#define MAX_VIDEO_MEM 16 /* Video memory limit in megabytes */
-
-/*
- * Structures
- */
-
-/* buffer for one video frame */
-struct mx1_buffer {
- /* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
- enum v4l2_mbus_pixelcode code;
- int inwork;
-};
-
-/*
- * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor
- * Interface. If anyone ever builds hardware to enable more than
- * one camera, they will have to modify this driver too
- */
-struct mx1_camera_dev {
- struct soc_camera_host soc_host;
- struct mx1_camera_pdata *pdata;
- struct mx1_buffer *active;
- struct resource *res;
- struct clk *clk;
- struct list_head capture;
-
- void __iomem *base;
- int dma_chan;
- unsigned int irq;
- unsigned long mclk;
-
- spinlock_t lock;
-};
-
-/*
- * Videobuf operations
- */
-static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
- unsigned int *size)
-{
- struct soc_camera_device *icd = vq->priv_data;
-
- *size = icd->sizeimage;
-
- if (!*count)
- *count = 32;
-
- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
-
- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
-
- return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct videobuf_buffer *vb = &buf->vb;
-
- BUG_ON(in_interrupt());
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- /*
- * This waits until this buffer is out of danger, i.e., until it is no
- * longer in STATE_QUEUED or STATE_ACTIVE
- */
- videobuf_waiton(vq, vb, 0, 0);
- videobuf_dma_contig_free(vq, vb);
-
- vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int mx1_videobuf_prepare(struct videobuf_queue *vq,
- struct videobuf_buffer *vb, enum v4l2_field field)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
- int ret;
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- /* Added list head initialization on alloc */
- WARN_ON(!list_empty(&vb->queue));
-
- BUG_ON(NULL == icd->current_fmt);
-
- /*
- * I think, in buf_prepare you only have to protect global data,
- * the actual buffer is yours
- */
- buf->inwork = 1;
-
- if (buf->code != icd->current_fmt->code ||
- vb->width != icd->user_width ||
- vb->height != icd->user_height ||
- vb->field != field) {
- buf->code = icd->current_fmt->code;
- vb->width = icd->user_width;
- vb->height = icd->user_height;
- vb->field = field;
- vb->state = VIDEOBUF_NEEDS_INIT;
- }
-
- vb->size = icd->sizeimage;
- if (0 != vb->baddr && vb->bsize < vb->size) {
- ret = -EINVAL;
- goto out;
- }
-
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- ret = videobuf_iolock(vq, vb, NULL);
- if (ret)
- goto fail;
-
- vb->state = VIDEOBUF_PREPARED;
- }
-
- buf->inwork = 0;
-
- return 0;
-
-fail:
- free_buffer(vq, buf);
-out:
- buf->inwork = 0;
- return ret;
-}
-
-static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
-{
- struct videobuf_buffer *vbuf = &pcdev->active->vb;
- struct device *dev = pcdev->soc_host.icd->parent;
- int ret;
-
- if (unlikely(!pcdev->active)) {
- dev_err(dev, "DMA End IRQ with no active buffer\n");
- return -EFAULT;
- }
-
- /* setup sg list for future DMA */
- ret = imx_dma_setup_single(pcdev->dma_chan,
- videobuf_to_dma_contig(vbuf),
- vbuf->size, pcdev->res->start +
- CSIRXR, DMA_MODE_READ);
- if (unlikely(ret))
- dev_err(dev, "Failed to setup DMA sg list\n");
-
- return ret;
-}
-
-/* Called under spinlock_irqsave(&pcdev->lock, ...) */
-static void mx1_videobuf_queue(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- list_add_tail(&vb->queue, &pcdev->capture);
-
- vb->state = VIDEOBUF_ACTIVE;
-
- if (!pcdev->active) {
- pcdev->active = buf;
-
- /* setup sg list for future DMA */
- if (!mx1_camera_setup_dma(pcdev)) {
- unsigned int temp;
- /* enable SOF irq */
- temp = __raw_readl(pcdev->base + CSICR1) |
- CSICR1_SOF_INTEN;
- __raw_writel(temp, pcdev->base + CSICR1);
- }
- }
-}
-
-static void mx1_videobuf_release(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-#ifdef DEBUG
- struct soc_camera_device *icd = vq->priv_data;
- struct device *dev = icd->parent;
-
- dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- switch (vb->state) {
- case VIDEOBUF_ACTIVE:
- dev_dbg(dev, "%s (active)\n", __func__);
- break;
- case VIDEOBUF_QUEUED:
- dev_dbg(dev, "%s (queued)\n", __func__);
- break;
- case VIDEOBUF_PREPARED:
- dev_dbg(dev, "%s (prepared)\n", __func__);
- break;
- default:
- dev_dbg(dev, "%s (unknown)\n", __func__);
- break;
- }
-#endif
-
- free_buffer(vq, buf);
-}
-
-static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev,
- struct videobuf_buffer *vb,
- struct mx1_buffer *buf)
-{
- /* _init is used to debug races, see comment in mx1_camera_reqbufs() */
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_DONE;
- v4l2_get_timestamp(&vb->ts);
- vb->field_count++;
- wake_up(&vb->done);
-
- if (list_empty(&pcdev->capture)) {
- pcdev->active = NULL;
- return;
- }
-
- pcdev->active = list_entry(pcdev->capture.next,
- struct mx1_buffer, vb.queue);
-
- /* setup sg list for future DMA */
- if (likely(!mx1_camera_setup_dma(pcdev))) {
- unsigned int temp;
-
- /* enable SOF irq */
- temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN;
- __raw_writel(temp, pcdev->base + CSICR1);
- }
-}
-
-static void mx1_camera_dma_irq(int channel, void *data)
-{
- struct mx1_camera_dev *pcdev = data;
- struct device *dev = pcdev->soc_host.icd->parent;
- struct mx1_buffer *buf;
- struct videobuf_buffer *vb;
- unsigned long flags;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- imx_dma_disable(channel);
-
- if (unlikely(!pcdev->active)) {
- dev_err(dev, "DMA End IRQ with no active buffer\n");
- goto out;
- }
-
- vb = &pcdev->active->vb;
- buf = container_of(vb, struct mx1_buffer, vb);
- WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- mx1_camera_wakeup(pcdev, vb, buf);
-out:
- spin_unlock_irqrestore(&pcdev->lock, flags);
-}
-
-static struct videobuf_queue_ops mx1_videobuf_ops = {
- .buf_setup = mx1_videobuf_setup,
- .buf_prepare = mx1_videobuf_prepare,
- .buf_queue = mx1_videobuf_queue,
- .buf_release = mx1_videobuf_release,
-};
-
-static void mx1_camera_init_videobuf(struct videobuf_queue *q,
- struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
-
- videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent,
- &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_NONE,
- sizeof(struct mx1_buffer), icd, &ici->host_lock);
-}
-
-static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
-{
- unsigned int mclk = pcdev->mclk;
- unsigned long div;
- unsigned long lcdclk;
-
- lcdclk = clk_get_rate(pcdev->clk);
-
- /*
- * We verify platform_mclk_10khz != 0, so if anyone breaks it, here
- * they get a nice Oops
- */
- div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
-
- dev_dbg(pcdev->soc_host.icd->parent,
- "System clock %lukHz, target freq %dkHz, divisor %lu\n",
- lcdclk / 1000, mclk / 1000, div);
-
- return div;
-}
-
-static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
-{
- unsigned int csicr1 = CSICR1_EN;
-
- dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n");
-
- clk_prepare_enable(pcdev->clk);
-
- /* enable CSI before doing anything else */
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- csicr1 |= CSICR1_MCLKEN | CSICR1_FCC | CSICR1_GCLK_MODE;
- csicr1 |= CSICR1_MCLKDIV(mclk_get_divisor(pcdev));
- csicr1 |= CSICR1_RXFF_LEVEL(2); /* 16 words */
-
- __raw_writel(csicr1, pcdev->base + CSICR1);
-}
-
-static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
-{
- dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n");
-
- /* Disable all CSI interface */
- __raw_writel(0x00, pcdev->base + CSICR1);
-
- clk_disable_unprepare(pcdev->clk);
-}
-
-static int mx1_camera_add_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n",
- icd->devnum);
-
- return 0;
-}
-
-static void mx1_camera_remove_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n",
- icd->devnum);
-}
-
-/*
- * The following two functions absolutely depend on the fact, that
- * there can be only one camera on i.MX1/i.MXL camera sensor interface
- */
-static int mx1_camera_clock_start(struct soc_camera_host *ici)
-{
- struct mx1_camera_dev *pcdev = ici->priv;
-
- mx1_camera_activate(pcdev);
-
- return 0;
-}
-
-static void mx1_camera_clock_stop(struct soc_camera_host *ici)
-{
- struct mx1_camera_dev *pcdev = ici->priv;
- unsigned int csicr1;
-
- /* disable interrupts */
- csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK;
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- /* Stop DMA engine */
- imx_dma_disable(pcdev->dma_chan);
-
- mx1_camera_deactivate(pcdev);
-}
-
-static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- unsigned long common_flags;
- unsigned int csicr1;
- int ret;
-
- /* MX1 supports only 8bit buswidth */
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS);
- if (!common_flags) {
- dev_warn(icd->parent,
- "Flags incompatible: camera 0x%x, host 0x%x\n",
- cfg.flags, CSI_BUS_FLAGS);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- } else {
- common_flags = CSI_BUS_FLAGS;
- }
-
- /* Make choises, based on platform choice */
- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
- else
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
- }
-
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
- else
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
- }
-
- if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
- else
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
- }
-
- cfg.flags = common_flags;
- ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
- common_flags, ret);
- return ret;
- }
-
- csicr1 = __raw_readl(pcdev->base + CSICR1);
-
- if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
- csicr1 |= CSICR1_REDGE;
- if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
- csicr1 |= CSICR1_SOF_POL;
- if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
- csicr1 |= CSICR1_DATA_POL;
-
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- return 0;
-}
-
-static int mx1_camera_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
- int ret, buswidth;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- buswidth = xlate->host_fmt->bits_per_sample;
- if (buswidth > 8) {
- dev_warn(icd->parent,
- "bits-per-sample %d for format %x unsupported\n",
- buswidth, pix->pixelformat);
- return -EINVAL;
- }
-
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
-
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
-
- if (mf.code != xlate->code)
- return -EINVAL;
-
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
- icd->current_fmt = xlate;
-
- return ret;
-}
-
-static int mx1_camera_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
- int ret;
- /* TODO: limit to mx1 hardware capabilities */
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
-
- /* limit to sensor capabilities */
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
-
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
-
- return 0;
-}
-
-static int mx1_camera_reqbufs(struct soc_camera_device *icd,
- struct v4l2_requestbuffers *p)
-{
- int i;
-
- /*
- * This is for locking debugging only. I removed spinlocks and now I
- * check whether .prepare is ever called on a linked buffer, or whether
- * a dma IRQ can occur for an in-work or unlinked buffer. Until now
- * it hadn't triggered
- */
- for (i = 0; i < p->count; i++) {
- struct mx1_buffer *buf = container_of(icd->vb_vidq.bufs[i],
- struct mx1_buffer, vb);
- buf->inwork = 0;
- INIT_LIST_HEAD(&buf->vb.queue);
- }
-
- return 0;
-}
-
-static unsigned int mx1_camera_poll(struct file *file, poll_table *pt)
-{
- struct soc_camera_device *icd = file->private_data;
- struct mx1_buffer *buf;
-
- buf = list_entry(icd->vb_vidq.stream.next, struct mx1_buffer,
- vb.stream);
-
- poll_wait(file, &buf->vb.done, pt);
-
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
-
-static int mx1_camera_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
-{
- /* cap->name is set by the friendly caller:-> */
- strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card));
- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-
- return 0;
-}
-
-static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .add = mx1_camera_add_device,
- .remove = mx1_camera_remove_device,
- .clock_start = mx1_camera_clock_start,
- .clock_stop = mx1_camera_clock_stop,
- .set_bus_param = mx1_camera_set_bus_param,
- .set_fmt = mx1_camera_set_fmt,
- .try_fmt = mx1_camera_try_fmt,
- .init_videobuf = mx1_camera_init_videobuf,
- .reqbufs = mx1_camera_reqbufs,
- .poll = mx1_camera_poll,
- .querycap = mx1_camera_querycap,
-};
-
-static struct fiq_handler fh = {
- .name = "csi_sof"
-};
-
-static int __init mx1_camera_probe(struct platform_device *pdev)
-{
- struct mx1_camera_dev *pcdev;
- struct resource *res;
- struct pt_regs regs;
- struct clk *clk;
- void __iomem *base;
- unsigned int irq;
- int err = 0;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (!res || (int)irq <= 0) {
- err = -ENODEV;
- goto exit;
- }
-
- clk = clk_get(&pdev->dev, "csi_clk");
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- goto exit;
- }
-
- pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
- if (!pcdev) {
- dev_err(&pdev->dev, "Could not allocate pcdev\n");
- err = -ENOMEM;
- goto exit_put_clk;
- }
-
- pcdev->res = res;
- pcdev->clk = clk;
-
- pcdev->pdata = pdev->dev.platform_data;
-
- if (pcdev->pdata)
- pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
-
- if (!pcdev->mclk) {
- dev_warn(&pdev->dev,
- "mclk_10khz == 0! Please, fix your platform data. "
- "Using default 20MHz\n");
- pcdev->mclk = 20000000;
- }
-
- INIT_LIST_HEAD(&pcdev->capture);
- spin_lock_init(&pcdev->lock);
-
- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) {
- err = -EBUSY;
- goto exit_kfree;
- }
-
- base = ioremap(res->start, resource_size(res));
- if (!base) {
- err = -ENOMEM;
- goto exit_release;
- }
- pcdev->irq = irq;
- pcdev->base = base;
-
- /* request dma */
- pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
- if (pcdev->dma_chan < 0) {
- dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
- err = -EBUSY;
- goto exit_iounmap;
- }
- dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
-
- imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
- pcdev);
-
- imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO,
- IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0);
- /* burst length : 16 words = 64 bytes */
- imx_dma_config_burstlen(pcdev->dma_chan, 0);
-
- /* request irq */
- err = claim_fiq(&fh);
- if (err) {
- dev_err(&pdev->dev, "Camera interrupt register failed\n");
- goto exit_free_dma;
- }
-
- set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end -
- &mx1_camera_sof_fiq_start);
-
- regs.ARM_r8 = (long)MX1_DMA_DIMR;
- regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan);
- regs.ARM_r10 = (long)pcdev->base + CSICR1;
- regs.ARM_fp = (long)pcdev->base + CSISR;
- regs.ARM_sp = 1 << pcdev->dma_chan;
- set_fiq_regs(&regs);
-
- mxc_set_irq_fiq(irq, 1);
- enable_fiq(irq);
-
- pcdev->soc_host.drv_name = DRIVER_NAME;
- pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
- pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
- pcdev->soc_host.nr = pdev->id;
- err = soc_camera_host_register(&pcdev->soc_host);
- if (err)
- goto exit_free_irq;
-
- dev_info(&pdev->dev, "MX1 Camera driver loaded\n");
-
- return 0;
-
-exit_free_irq:
- disable_fiq(irq);
- mxc_set_irq_fiq(irq, 0);
- release_fiq(&fh);
-exit_free_dma:
- imx_dma_free(pcdev->dma_chan);
-exit_iounmap:
- iounmap(base);
-exit_release:
- release_mem_region(res->start, resource_size(res));
-exit_kfree:
- kfree(pcdev);
-exit_put_clk:
- clk_put(clk);
-exit:
- return err;
-}
-
-static int __exit mx1_camera_remove(struct platform_device *pdev)
-{
- struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
- struct mx1_camera_dev *pcdev = container_of(soc_host,
- struct mx1_camera_dev, soc_host);
- struct resource *res;
-
- imx_dma_free(pcdev->dma_chan);
- disable_fiq(pcdev->irq);
- mxc_set_irq_fiq(pcdev->irq, 0);
- release_fiq(&fh);
-
- clk_put(pcdev->clk);
-
- soc_camera_host_unregister(soc_host);
-
- iounmap(pcdev->base);
-
- res = pcdev->res;
- release_mem_region(res->start, resource_size(res));
-
- kfree(pcdev);
-
- dev_info(&pdev->dev, "MX1 Camera driver unloaded\n");
-
- return 0;
-}
-
-static struct platform_driver mx1_camera_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .remove = __exit_p(mx1_camera_remove),
-};
-
-module_platform_driver_probe(mx1_camera_driver, mx1_camera_probe);
-
-MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver");
-MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index d4df305fcc18..64dc80ccd6f9 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -34,6 +34,7 @@
#include <media/videobuf-dma-sg.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
+#include <media/v4l2-of.h>
#include <linux/videodev2.h>
@@ -1650,6 +1651,68 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.set_bus_param = pxa_camera_set_bus_param,
};
+static int pxa_camera_pdata_from_dt(struct device *dev,
+ struct pxa_camera_dev *pcdev)
+{
+ u32 mclk_rate;
+ struct device_node *np = dev->of_node;
+ struct v4l2_of_endpoint ep;
+ int err = of_property_read_u32(np, "clock-frequency",
+ &mclk_rate);
+ if (!err) {
+ pcdev->platform_flags |= PXA_CAMERA_MCLK_EN;
+ pcdev->mclk = mclk_rate;
+ }
+
+ np = of_graph_get_next_endpoint(np, NULL);
+ if (!np) {
+ dev_err(dev, "could not find endpoint\n");
+ return -EINVAL;
+ }
+
+ err = v4l2_of_parse_endpoint(np, &ep);
+ if (err) {
+ dev_err(dev, "could not parse endpoint\n");
+ goto out;
+ }
+
+ switch (ep.bus.parallel.bus_width) {
+ case 4:
+ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_4;
+ break;
+ case 5:
+ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_5;
+ break;
+ case 8:
+ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_8;
+ break;
+ case 9:
+ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_9;
+ break;
+ case 10:
+ pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
+ break;
+ default:
+ break;
+ };
+
+ if (ep.bus.parallel.flags & V4L2_MBUS_MASTER)
+ pcdev->platform_flags |= PXA_CAMERA_MASTER;
+ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+ pcdev->platform_flags |= PXA_CAMERA_HSP;
+ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+ pcdev->platform_flags |= PXA_CAMERA_VSP;
+ if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+ pcdev->platform_flags |= PXA_CAMERA_PCLK_EN | PXA_CAMERA_PCP;
+ if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+ pcdev->platform_flags |= PXA_CAMERA_PCLK_EN;
+
+out:
+ of_node_put(np);
+
+ return err;
+}
+
static int pxa_camera_probe(struct platform_device *pdev)
{
struct pxa_camera_dev *pcdev;
@@ -1676,7 +1739,15 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
- pcdev->platform_flags = pcdev->pdata->flags;
+ if (&pdev->dev.of_node && !pcdev->pdata) {
+ err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
+ } else {
+ pcdev->platform_flags = pcdev->pdata->flags;
+ pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
+ }
+ if (err < 0)
+ return err;
+
if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
/*
@@ -1693,7 +1764,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->width_flags |= 1 << 8;
if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)
pcdev->width_flags |= 1 << 9;
- pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
if (!pcdev->mclk) {
dev_warn(&pdev->dev,
"mclk == 0! Please, fix your platform data. "
@@ -1799,10 +1869,17 @@ static const struct dev_pm_ops pxa_camera_pm = {
.resume = pxa_camera_resume,
};
+static const struct of_device_id pxa_camera_of_match[] = {
+ { .compatible = "marvell,pxa270-qci", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, pxa_camera_of_match);
+
static struct platform_driver pxa_camera_driver = {
.driver = {
.name = PXA_CAM_DRV_NAME,
.pm = &pxa_camera_pm,
+ .of_match_table = of_match_ptr(pxa_camera_of_match),
},
.probe = pxa_camera_probe,
.remove = pxa_camera_remove,
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index e594230e84d3..85d579f65f52 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -19,6 +19,8 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_data/camera-rcar.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -31,6 +33,7 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
+#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
@@ -126,13 +129,13 @@ struct rcar_vin_priv {
int sequence;
/* State of the VIN module in capturing mode */
enum rcar_vin_state state;
- struct rcar_vin_platform_data *pdata;
struct soc_camera_host ici;
struct list_head capture;
#define MAX_BUFFER_NUM 3
struct vb2_buffer *queue_buf[MAX_BUFFER_NUM];
struct vb2_alloc_ctx *alloc_ctx;
enum v4l2_field field;
+ unsigned int pdata_flags;
unsigned int vb_count;
unsigned int nr_hw_slots;
bool request_to_stop;
@@ -275,12 +278,12 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
break;
case V4L2_MBUS_FMT_YUYV8_2X8:
/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
- vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
break;
case V4L2_MBUS_FMT_YUYV10_2X10:
/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
- vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
break;
default:
@@ -797,7 +800,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
/* Make choises, based on platform preferences */
if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
- if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
+ if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
@@ -805,7 +808,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
+ if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
@@ -1390,6 +1393,17 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
.init_videobuf2 = rcar_vin_init_videobuf2,
};
+#ifdef CONFIG_OF
+static struct of_device_id rcar_vin_of_table[] = {
+ { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
+ { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
+ { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
+ { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
+#endif
+
static struct platform_device_id rcar_vin_id_table[] = {
{ "r8a7791-vin", RCAR_GEN2 },
{ "r8a7790-vin", RCAR_GEN2 },
@@ -1402,15 +1416,52 @@ MODULE_DEVICE_TABLE(platform, rcar_vin_id_table);
static int rcar_vin_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match = NULL;
struct rcar_vin_priv *priv;
struct resource *mem;
struct rcar_vin_platform_data *pdata;
+ unsigned int pdata_flags;
int irq, ret;
- pdata = pdev->dev.platform_data;
- if (!pdata || !pdata->flags) {
- dev_err(&pdev->dev, "platform data not set\n");
- return -EINVAL;
+ if (pdev->dev.of_node) {
+ struct v4l2_of_endpoint ep;
+ struct device_node *np;
+
+ match = of_match_device(of_match_ptr(rcar_vin_of_table),
+ &pdev->dev);
+
+ np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
+ if (!np) {
+ dev_err(&pdev->dev, "could not find endpoint\n");
+ return -EINVAL;
+ }
+
+ ret = v4l2_of_parse_endpoint(np, &ep);
+ if (ret) {
+ dev_err(&pdev->dev, "could not parse endpoint\n");
+ return ret;
+ }
+
+ if (ep.bus_type == V4L2_MBUS_BT656)
+ pdata_flags = RCAR_VIN_BT656;
+ else {
+ pdata_flags = 0;
+ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+ pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
+ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+ pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
+ }
+
+ of_node_put(np);
+
+ dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
+ } else {
+ pdata = pdev->dev.platform_data;
+ if (!pdata || !pdata->flags) {
+ dev_err(&pdev->dev, "platform data not set\n");
+ return -EINVAL;
+ }
+ pdata_flags = pdata->flags;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1441,12 +1492,18 @@ static int rcar_vin_probe(struct platform_device *pdev)
priv->ici.priv = priv;
priv->ici.v4l2_dev.dev = &pdev->dev;
- priv->ici.nr = pdev->id;
priv->ici.drv_name = dev_name(&pdev->dev);
priv->ici.ops = &rcar_vin_host_ops;
- priv->pdata = pdata;
- priv->chip = pdev->id_entry->driver_data;
+ priv->pdata_flags = pdata_flags;
+ if (!match) {
+ priv->ici.nr = pdev->id;
+ priv->chip = pdev->id_entry->driver_data;
+ } else {
+ priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
+ priv->chip = (enum chip_id)match->data;
+ };
+
spin_lock_init(&priv->lock);
INIT_LIST_HEAD(&priv->capture);
@@ -1487,6 +1544,7 @@ static struct platform_driver rcar_vin_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(rcar_vin_of_table),
},
.id_table = rcar_vin_id_table,
};
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 7fec8cdaf095..f4308fed5431 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -36,6 +36,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
+#include <media/v4l2-of.h>
#include <media/videobuf-core.h>
#include <media/videobuf2-core.h>
@@ -1524,14 +1525,14 @@ static int scan_async_group(struct soc_camera_host *ici,
ret = soc_camera_dyn_pdev(&sdesc, sasc);
if (ret < 0)
- return ret;
+ goto eallocpdev;
sasc->sensor = &sasd->asd;
icd = soc_camera_add_pdev(sasc);
if (!icd) {
- platform_device_put(sasc->pdev);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto eaddpdev;
}
sasc->notifier.subdevs = asd;
@@ -1559,7 +1560,11 @@ static int scan_async_group(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
- platform_device_unregister(sasc->pdev);
+ platform_device_del(sasc->pdev);
+eaddpdev:
+ platform_device_put(sasc->pdev);
+eallocpdev:
+ devm_kfree(ici->v4l2_dev.dev, sasc);
dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
return ret;
@@ -1581,6 +1586,130 @@ static void scan_async_host(struct soc_camera_host *ici)
#define scan_async_host(ici) do {} while (0)
#endif
+#ifdef CONFIG_OF
+
+struct soc_of_info {
+ struct soc_camera_async_subdev sasd;
+ struct soc_camera_async_client sasc;
+ struct v4l2_async_subdev *subdev;
+};
+
+static int soc_of_bind(struct soc_camera_host *ici,
+ struct device_node *ep,
+ struct device_node *remote)
+{
+ struct soc_camera_device *icd;
+ struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,};
+ struct soc_camera_async_client *sasc;
+ struct soc_of_info *info;
+ struct i2c_client *client;
+ char clk_name[V4L2_SUBDEV_NAME_SIZE];
+ int ret;
+
+ /* allocate a new subdev and add match info to it */
+ info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->sasd.asd.match.of.node = remote;
+ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF;
+ info->subdev = &info->sasd.asd;
+
+ /* Or shall this be managed by the soc-camera device? */
+ sasc = &info->sasc;
+
+ /* HACK: just need a != NULL */
+ sdesc.host_desc.board_info = ERR_PTR(-ENODATA);
+
+ ret = soc_camera_dyn_pdev(&sdesc, sasc);
+ if (ret < 0)
+ goto eallocpdev;
+
+ sasc->sensor = &info->sasd.asd;
+
+ icd = soc_camera_add_pdev(sasc);
+ if (!icd) {
+ ret = -ENOMEM;
+ goto eaddpdev;
+ }
+
+ sasc->notifier.subdevs = &info->subdev;
+ sasc->notifier.num_subdevs = 1;
+ sasc->notifier.bound = soc_camera_async_bound;
+ sasc->notifier.unbind = soc_camera_async_unbind;
+ sasc->notifier.complete = soc_camera_async_complete;
+
+ icd->sasc = sasc;
+ icd->parent = ici->v4l2_dev.dev;
+
+ client = of_find_i2c_device_by_node(remote);
+
+ if (client)
+ snprintf(clk_name, sizeof(clk_name), "%d-%04x",
+ client->adapter->nr, client->addr);
+ else
+ snprintf(clk_name, sizeof(clk_name), "of-%s",
+ of_node_full_name(remote));
+
+ icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd);
+ if (IS_ERR(icd->clk)) {
+ ret = PTR_ERR(icd->clk);
+ goto eclkreg;
+ }
+
+ ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier);
+ if (!ret)
+ return 0;
+eclkreg:
+ icd->clk = NULL;
+ platform_device_del(sasc->pdev);
+eaddpdev:
+ platform_device_put(sasc->pdev);
+eallocpdev:
+ devm_kfree(ici->v4l2_dev.dev, sasc);
+ dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
+
+ return ret;
+}
+
+static void scan_of_host(struct soc_camera_host *ici)
+{
+ struct device *dev = ici->v4l2_dev.dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *epn = NULL, *ren;
+ unsigned int i;
+
+ for (i = 0; ; i++) {
+ epn = of_graph_get_next_endpoint(np, epn);
+ if (!epn)
+ break;
+
+ ren = of_graph_get_remote_port(epn);
+ if (!ren) {
+ dev_notice(dev, "no remote for %s\n",
+ of_node_full_name(epn));
+ continue;
+ }
+
+ /* so we now have a remote node to connect */
+ if (!i)
+ soc_of_bind(ici, epn, ren->parent);
+
+ of_node_put(epn);
+ of_node_put(ren);
+
+ if (i) {
+ dev_err(dev, "multiple subdevices aren't supported yet!\n");
+ break;
+ }
+ }
+}
+
+#else
+static inline void scan_of_host(struct soc_camera_host *ici) { }
+#endif
+
/* Called during host-driver probe */
static int soc_camera_probe(struct soc_camera_host *ici,
struct soc_camera_device *icd)
@@ -1832,7 +1961,9 @@ int soc_camera_host_register(struct soc_camera_host *ici)
mutex_init(&ici->host_lock);
mutex_init(&ici->clk_lock);
- if (ici->asd_sizes)
+ if (ici->v4l2_dev.dev->of_node)
+ scan_of_host(ici);
+ else if (ici->asd_sizes)
/*
* No OF, host with a list of subdevices. Don't try to mix
* modes by initialising some groups statically and some
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c
index 470d35336119..91d44ea16f27 100644
--- a/drivers/media/platform/vino.c
+++ b/drivers/media/platform/vino.c
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[tempvcs.data_format].colorspace;
- pf->priv = 0;
return 0;
}
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[vcs->data_format].colorspace;
- pf->priv = 0;
-
spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[vcs->data_format].colorspace;
- pf->priv = 0;
-
spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index d00bf3df0f8a..80333714ffa7 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -648,13 +648,13 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
dev->int32->cur.val,
- dev->int64->cur.val64,
+ *dev->int64->p_cur.p_s64,
dev->bitmask->cur.val);
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
dev->boolean->cur.val,
dev->menu->qmenu[dev->menu->cur.val],
- dev->string->cur.string);
+ dev->string->p_cur.p_char);
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
dev->int_menu->qmenu_int[dev->int_menu->cur.val],
@@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
else
f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1236,7 +1235,7 @@ static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
.id = VIVI_CID_CUSTOM_BASE + 2,
.name = "Integer 32 Bits",
.type = V4L2_CTRL_TYPE_INTEGER,
- .min = 0x80000000,
+ .min = -0x80000000LL,
.max = 0x7fffffff,
.step = 1,
};
@@ -1246,6 +1245,9 @@ static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
.id = VIVI_CID_CUSTOM_BASE + 3,
.name = "Integer 64 Bits",
.type = V4L2_CTRL_TYPE_INTEGER64,
+ .min = LLONG_MIN,
+ .max = LLONG_MAX,
+ .step = 1,
};
static const char * const vivi_ctrl_menu_strings[] = {
@@ -1459,7 +1461,6 @@ static int __init vivi_create_instance(int inst)
vfd->debug = debug;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->queue = q;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
/*
* Provide a mutex to v4l2 core. It will be used to protect
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 6ca2cf20d545..12467191dff4 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -36,9 +36,9 @@ struct vsp1_rwpf;
struct vsp1_sru;
struct vsp1_uds;
-#define VPS1_MAX_RPF 5
-#define VPS1_MAX_UDS 3
-#define VPS1_MAX_WPF 4
+#define VSP1_MAX_RPF 5
+#define VSP1_MAX_UDS 3
+#define VSP1_MAX_WPF 4
struct vsp1_device {
struct device *dev;
@@ -55,10 +55,10 @@ struct vsp1_device {
struct vsp1_hsit *hst;
struct vsp1_lif *lif;
struct vsp1_lut *lut;
- struct vsp1_rwpf *rpf[VPS1_MAX_RPF];
+ struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
struct vsp1_sru *sru;
- struct vsp1_uds *uds[VPS1_MAX_UDS];
- struct vsp1_rwpf *wpf[VPS1_MAX_WPF];
+ struct vsp1_uds *uds[VSP1_MAX_UDS];
+ struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
struct list_head entities;
@@ -66,7 +66,7 @@ struct vsp1_device {
struct media_device media_dev;
};
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1);
+int vsp1_device_get(struct vsp1_device *vsp1);
void vsp1_device_put(struct vsp1_device *vsp1);
static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg)
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index f80695480060..a0c1984c733e 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -18,6 +18,7 @@
#include "vsp1.h"
#include "vsp1_bru.h"
+#include "vsp1_rwpf.h"
#define BRU_MIN_SIZE 4U
#define BRU_MAX_SIZE 8190U
@@ -37,19 +38,47 @@ static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
+ * Controls
*/
-static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input)
+static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
{
- return media_entity_remote_pad(&bru->entity.pads[input]) != NULL;
+ struct vsp1_bru *bru =
+ container_of(ctrl->handler, struct vsp1_bru, ctrls);
+
+ if (!vsp1_entity_is_streaming(&bru->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BG_COLOR:
+ vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val |
+ (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
+ break;
+ }
+
+ return 0;
}
+static const struct v4l2_ctrl_ops bru_ctrl_ops = {
+ .s_ctrl = bru_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
{
+ struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
struct vsp1_bru *bru = to_bru(subdev);
struct v4l2_mbus_framefmt *format;
+ unsigned int flags;
unsigned int i;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&bru->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
@@ -62,18 +91,19 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
* to sane default values for now.
*/
- /* Disable both color data normalization and dithering. */
- vsp1_bru_write(bru, VI6_BRU_INCTRL, 0);
-
- /* Set the background position to cover the whole output image and
- * set its color to opaque black.
+ /* Disable dithering and enable color data normalization unless the
+ * format at the pipeline output is premultiplied.
*/
+ flags = pipe->output ? pipe->output->video.format.flags : 0;
+ vsp1_bru_write(bru, VI6_BRU_INCTRL,
+ flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
+ 0 : VI6_BRU_INCTRL_NRM);
+
+ /* Set the background position to cover the whole output image. */
vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE,
(format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
(format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0);
- vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL,
- 0xff << VI6_BRU_VIRRPF_COL_A_SHIFT);
/* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
* unit with a NOP operation to make BRU input 1 available as the
@@ -84,6 +114,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
VI6_BRU_ROP_AROP(VI6_ROP_NOP));
for (i = 0; i < 4; ++i) {
+ bool premultiplied = false;
u32 ctrl = 0;
/* Configure all Blend/ROP units corresponding to an enabled BRU
@@ -91,11 +122,15 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
* disabled BRU inputs are used in ROP NOP mode to ignore the
* SRC input.
*/
- if (bru_is_input_enabled(bru, i))
+ if (bru->inputs[i].rpf) {
ctrl |= VI6_BRU_CTRL_RBC;
- else
+
+ premultiplied = bru->inputs[i].rpf->video.format.flags
+ & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
+ } else {
ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
| VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
+ }
/* Select the virtual RPF as the Blend/ROP unit A DST input to
* serve as a background color.
@@ -117,10 +152,18 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
*
* DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
* DSTa = DSTa * (1 - SRCa) + SRCa
+ *
+ * when the SRC input isn't premultiplied, and to
+ *
+ * DSTc = DSTc * (1 - SRCa) + SRCc
+ * DSTa = DSTa * (1 - SRCa) + SRCa
+ *
+ * otherwise.
*/
vsp1_bru_write(bru, VI6_BRU_BLD(i),
VI6_BRU_BLD_CCMDX_255_SRC_A |
- VI6_BRU_BLD_CCMDY_SRC_A |
+ (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
+ VI6_BRU_BLD_CCMDY_SRC_A) |
VI6_BRU_BLD_ACMDX_255_SRC_A |
VI6_BRU_BLD_ACMDY_COEFY |
(0xff << VI6_BRU_BLD_COEFY_SHIFT));
@@ -192,7 +235,7 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_get_try_crop(fh, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &bru->compose[pad];
+ return &bru->inputs[pad].compose;
default:
return NULL;
}
@@ -391,5 +434,19 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&bru->ctrls, 1);
+ v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+ 0, 0xffffff, 1, 0);
+
+ bru->entity.subdev.ctrl_handler = &bru->ctrls;
+
+ if (bru->ctrls.error) {
+ dev_err(vsp1->dev, "bru: failed to initialize controls\n");
+ ret = bru->ctrls.error;
+ vsp1_entity_destroy(&bru->entity);
+ return ERR_PTR(ret);
+ }
+
return bru;
}
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h
index 37062704dbf6..16b1c6554911 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_bru.h
@@ -14,11 +14,13 @@
#define __VSP1_BRU_H__
#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include "vsp1_entity.h"
struct vsp1_device;
+struct vsp1_rwpf;
#define BRU_PAD_SINK(n) (n)
#define BRU_PAD_SOURCE 4
@@ -26,7 +28,12 @@ struct vsp1_device;
struct vsp1_bru {
struct vsp1_entity entity;
- struct v4l2_rect compose[4];
+ struct v4l2_ctrl_handler ctrls;
+
+ struct {
+ struct vsp1_rwpf *rpf;
+ struct v4l2_rect compose;
+ } inputs[4];
};
static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index c69ee0657f75..3e6601b5b4de 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -345,36 +345,32 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
* Increment the VSP1 reference count and initialize the device if the first
* reference is taken.
*
- * Return a pointer to the VSP1 device or NULL if an error occurred.
+ * Return 0 on success or a negative error code otherwise.
*/
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
+int vsp1_device_get(struct vsp1_device *vsp1)
{
- struct vsp1_device *__vsp1 = vsp1;
- int ret;
+ int ret = 0;
mutex_lock(&vsp1->lock);
if (vsp1->ref_count > 0)
goto done;
ret = clk_prepare_enable(vsp1->clock);
- if (ret < 0) {
- __vsp1 = NULL;
+ if (ret < 0)
goto done;
- }
ret = vsp1_device_init(vsp1);
if (ret < 0) {
clk_disable_unprepare(vsp1->clock);
- __vsp1 = NULL;
goto done;
}
done:
- if (__vsp1)
+ if (!ret)
vsp1->ref_count++;
mutex_unlock(&vsp1->lock);
- return __vsp1;
+ return ret;
}
/*
@@ -440,19 +436,19 @@ static int vsp1_validate_platform_data(struct platform_device *pdev,
return -EINVAL;
}
- if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) {
+ if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) {
dev_err(&pdev->dev, "invalid number of RPF (%u)\n",
pdata->rpf_count);
return -EINVAL;
}
- if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) {
+ if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) {
dev_err(&pdev->dev, "invalid number of UDS (%u)\n",
pdata->uds_count);
return -EINVAL;
}
- if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) {
+ if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) {
dev_err(&pdev->dev, "invalid number of WPF (%u)\n",
pdata->wpf_count);
return -EINVAL;
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 44167834285d..79af71d5e270 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -20,6 +20,42 @@
#include "vsp1.h"
#include "vsp1_entity.h"
+#include "vsp1_video.h"
+
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity)
+{
+ bool streaming;
+
+ mutex_lock(&entity->lock);
+ streaming = entity->streaming;
+ mutex_unlock(&entity->lock);
+
+ return streaming;
+}
+
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
+{
+ int ret;
+
+ mutex_lock(&entity->lock);
+ entity->streaming = streaming;
+ mutex_unlock(&entity->lock);
+
+ if (!streaming)
+ return 0;
+
+ if (!entity->subdev.ctrl_handler)
+ return 0;
+
+ ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
+ if (ret < 0) {
+ mutex_lock(&entity->lock);
+ entity->streaming = false;
+ mutex_unlock(&entity->lock);
+ }
+
+ return ret;
+}
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
@@ -157,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
if (i == ARRAY_SIZE(vsp1_routes))
return -EINVAL;
+ mutex_init(&entity->lock);
+
entity->vsp1 = vsp1;
entity->source_pad = num_pads - 1;
@@ -185,7 +223,11 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
void vsp1_entity_destroy(struct vsp1_entity *entity)
{
+ if (entity->video)
+ vsp1_video_cleanup(entity->video);
if (entity->subdev.ctrl_handler)
v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
media_entity_cleanup(&entity->subdev.entity);
+
+ mutex_destroy(&entity->lock);
}
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 7afbd8a7ba66..aa20aaa58208 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -14,10 +14,12 @@
#define __VSP1_ENTITY_H__
#include <linux/list.h>
+#include <linux/mutex.h>
#include <media/v4l2-subdev.h>
struct vsp1_device;
+struct vsp1_video;
enum vsp1_entity_type {
VSP1_ENTITY_BRU,
@@ -68,6 +70,11 @@ struct vsp1_entity {
struct v4l2_subdev subdev;
struct v4l2_mbus_framefmt *formats;
+
+ struct vsp1_video *video;
+
+ struct mutex lock; /* Protects the streaming field */
+ bool streaming;
};
static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
@@ -89,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity,
void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
struct v4l2_subdev_fh *fh);
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity);
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming);
+
#endif /* __VSP1_ENTITY_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 3e74b44286f6..55f163d32d15 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -336,7 +336,9 @@
*/
#define VI6_SRU_CTRL0 0x2200
+#define VI6_SRU_CTRL0_PARAM0_MASK (0x1ff << 16)
#define VI6_SRU_CTRL0_PARAM0_SHIFT 16
+#define VI6_SRU_CTRL0_PARAM1_MASK (0x1f << 8)
#define VI6_SRU_CTRL0_PARAM1_SHIFT 8
#define VI6_SRU_CTRL0_MODE_UPSCALE (4 << 4)
#define VI6_SRU_CTRL0_PARAM2 (1 << 3)
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index c3d98642a4aa..d14d26b718ef 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -39,6 +39,36 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int rpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_rwpf *rpf =
+ container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+ struct vsp1_pipeline *pipe;
+
+ if (!vsp1_entity_is_streaming(&rpf->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ALPHA_COMPONENT:
+ vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
+ ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+
+ pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity);
+ vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
+ .s_ctrl = rpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
@@ -50,6 +80,11 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
const struct v4l2_rect *crop = &rpf->crop;
u32 pstride;
u32 infmt;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&rpf->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
@@ -101,12 +136,13 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
(rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) |
(rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT));
- /* Disable alpha, mask and color key. Set the alpha channel to a fixed
- * value of 255.
+ /* Use the alpha channel (extended to 8 bits) when available or an
+ * alpha value set through the V4L2_CID_ALPHA_COMPONENT control
+ * otherwise. Disable color keying.
*/
- vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED);
- vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
- 255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+ vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
+ (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
+ : VI6_RPF_ALPH_SEL_ASEL_FIXED));
vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);
vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0);
@@ -196,6 +232,20 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&rpf->ctrls, 1);
+ v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 255);
+
+ rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
+
+ if (rpf->ctrls.error) {
+ dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
+ index);
+ ret = rpf->ctrls.error;
+ goto error;
+ }
+
/* Initialize the video device. */
video = &rpf->video;
@@ -205,7 +255,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
ret = vsp1_video_init(video, &rpf->entity);
if (ret < 0)
- goto error_video;
+ goto error;
+
+ rpf->entity.video = video;
/* Connect the video device to the RPF. */
ret = media_entity_create_link(&rpf->video.video.entity, 0,
@@ -214,13 +266,11 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE);
if (ret < 0)
- goto error_link;
+ goto error;
return rpf;
-error_link:
- vsp1_video_cleanup(video);
-error_video:
- media_entity_cleanup(&rpf->entity.subdev.entity);
+error:
+ vsp1_entity_destroy(&rpf->entity);
return ERR_PTR(ret);
}
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index b4fb65e58770..28dd9e7b3838 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -14,6 +14,7 @@
#define __VSP1_RWPF_H__
#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include "vsp1.h"
@@ -26,6 +27,7 @@
struct vsp1_rwpf {
struct vsp1_entity entity;
struct vsp1_video video;
+ struct v4l2_ctrl_handler ctrls;
unsigned int max_width;
unsigned int max_height;
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index aa0e04c56f3f..b7d3c8b9f189 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -42,38 +42,6 @@ static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data)
#define V4L2_CID_VSP1_SRU_INTENSITY (V4L2_CID_USER_BASE + 1)
-static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vsp1_sru *sru =
- container_of(ctrl->handler, struct vsp1_sru, ctrls);
-
- switch (ctrl->id) {
- case V4L2_CID_VSP1_SRU_INTENSITY:
- sru->intensity = ctrl->val;
- break;
- }
-
- return 0;
-}
-
-static const struct v4l2_ctrl_ops sru_ctrl_ops = {
- .s_ctrl = sru_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config sru_intensity_control = {
- .ops = &sru_ctrl_ops,
- .id = V4L2_CID_VSP1_SRU_INTENSITY,
- .name = "Intensity",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 6,
- .step = 1,
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
- */
-
struct vsp1_sru_param {
u32 ctrl0;
u32 ctrl2;
@@ -110,22 +78,66 @@ static const struct vsp1_sru_param vsp1_sru_params[] = {
},
};
+static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_sru *sru =
+ container_of(ctrl->handler, struct vsp1_sru, ctrls);
+ const struct vsp1_sru_param *param;
+ u32 value;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VSP1_SRU_INTENSITY:
+ param = &vsp1_sru_params[ctrl->val - 1];
+
+ value = vsp1_sru_read(sru, VI6_SRU_CTRL0);
+ value &= ~(VI6_SRU_CTRL0_PARAM0_MASK |
+ VI6_SRU_CTRL0_PARAM1_MASK);
+ value |= param->ctrl0;
+ vsp1_sru_write(sru, VI6_SRU_CTRL0, value);
+
+ vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops sru_ctrl_ops = {
+ .s_ctrl = sru_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config sru_intensity_control = {
+ .ops = &sru_ctrl_ops,
+ .id = V4L2_CID_VSP1_SRU_INTENSITY,
+ .name = "Intensity",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 1,
+ .max = 6,
+ .def = 1,
+ .step = 1,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
{
struct vsp1_sru *sru = to_sru(subdev);
- const struct vsp1_sru_param *param;
struct v4l2_mbus_framefmt *input;
struct v4l2_mbus_framefmt *output;
- bool upscale;
u32 ctrl0;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&sru->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
input = &sru->entity.formats[SRU_PAD_SINK];
output = &sru->entity.formats[SRU_PAD_SOURCE];
- upscale = input->width != output->width;
- param = &vsp1_sru_params[sru->intensity];
if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32)
ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
@@ -133,10 +145,18 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
else
ctrl0 = VI6_SRU_CTRL0_PARAM3;
- vsp1_sru_write(sru, VI6_SRU_CTRL0, param->ctrl0 | ctrl0 |
- (upscale ? VI6_SRU_CTRL0_MODE_UPSCALE : 0));
+ if (input->width != output->width)
+ ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE;
+
+ /* Take the control handler lock to ensure that the CTRL0 value won't be
+ * changed behind our back by a set control operation.
+ */
+ mutex_lock(sru->ctrls.lock);
+ ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
+ & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
+ mutex_unlock(sru->ctrls.lock);
+
vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
- vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
return 0;
}
@@ -348,8 +368,15 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&sru->ctrls, 1);
v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL);
- v4l2_ctrl_handler_setup(&sru->ctrls);
+
sru->entity.subdev.ctrl_handler = &sru->ctrls;
+ if (sru->ctrls.error) {
+ dev_err(vsp1->dev, "sru: failed to initialize controls\n");
+ ret = sru->ctrls.error;
+ vsp1_entity_destroy(&sru->entity);
+ return ERR_PTR(ret);
+ }
+
return sru;
}
diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h
index 381870b74780..b6768bf3dc47 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.h
+++ b/drivers/media/platform/vsp1/vsp1_sru.h
@@ -28,7 +28,6 @@ struct vsp1_sru {
struct vsp1_entity entity;
struct v4l2_ctrl_handler ctrls;
- unsigned int intensity;
};
static inline struct vsp1_sru *to_sru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index 0293bdbb4401..de92ef4944b3 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -45,6 +45,11 @@ static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data)
* Scaling Computation
*/
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha)
+{
+ vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
+}
+
/*
* uds_output_size - Return the output size for an input size and scaling ratio
* @input: input size in pixels
@@ -105,49 +110,56 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output)
return (input - 1) * 4096 / (output - 1);
}
-static void uds_compute_ratios(struct vsp1_uds *uds)
-{
- struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK];
- struct v4l2_mbus_framefmt *output =
- &uds->entity.formats[UDS_PAD_SOURCE];
-
- uds->hscale = uds_compute_ratio(input->width, output->width);
- uds->vscale = uds_compute_ratio(input->height, output->height);
-
- dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n",
- uds->hscale, uds->vscale);
-}
-
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
{
- const struct v4l2_mbus_framefmt *format;
struct vsp1_uds *uds = to_uds(subdev);
+ const struct v4l2_mbus_framefmt *output;
+ const struct v4l2_mbus_framefmt *input;
+ unsigned int hscale;
+ unsigned int vscale;
+ bool multitap;
if (!enable)
return 0;
- /* Enable multi-tap scaling. */
- vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_AON | VI6_UDS_CTRL_BC);
+ input = &uds->entity.formats[UDS_PAD_SINK];
+ output = &uds->entity.formats[UDS_PAD_SOURCE];
+
+ hscale = uds_compute_ratio(input->width, output->width);
+ vscale = uds_compute_ratio(input->height, output->height);
+
+ dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
+
+ /* Multi-tap scaling can't be enabled along with alpha scaling when
+ * scaling down with a factor lower than or equal to 1/2 in either
+ * direction.
+ */
+ if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
+ multitap = false;
+ else
+ multitap = true;
+
+ vsp1_uds_write(uds, VI6_UDS_CTRL,
+ (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
+ (multitap ? VI6_UDS_CTRL_BC : 0));
vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
- (uds_passband_width(uds->hscale)
+ (uds_passband_width(hscale)
<< VI6_UDS_PASS_BWIDTH_H_SHIFT) |
- (uds_passband_width(uds->vscale)
+ (uds_passband_width(vscale)
<< VI6_UDS_PASS_BWIDTH_V_SHIFT));
/* Set the scaling ratios and the output size. */
- format = &uds->entity.formats[UDS_PAD_SOURCE];
-
vsp1_uds_write(uds, VI6_UDS_SCALE,
- (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
- (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
+ (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
+ (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
- (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
- (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
+ (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
+ (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
return 0;
}
@@ -280,9 +292,6 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which);
}
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- uds_compute_ratios(uds);
-
return 0;
}
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h
index 479d12df1180..031ac0da1b66 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.h
+++ b/drivers/media/platform/vsp1/vsp1_uds.h
@@ -25,9 +25,7 @@ struct vsp1_device;
struct vsp1_uds {
struct vsp1_entity entity;
-
- unsigned int hscale;
- unsigned int vscale;
+ bool scale_alpha;
};
static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
@@ -37,4 +35,6 @@ static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index);
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha);
+
#endif /* __VSP1_UDS_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 8a1253e51f04..915a20eb003e 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -31,6 +31,7 @@
#include "vsp1_bru.h"
#include "vsp1_entity.h"
#include "vsp1_rwpf.h"
+#include "vsp1_uds.h"
#include "vsp1_video.h"
#define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV
@@ -50,70 +51,85 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
{ V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 8, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 8, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
+ 1, { 16, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
+ 1, { 16, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 24, 0, 0 }, false, false, 1, 1 },
+ 1, { 24, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 24, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 24, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
+ 1, { 32, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
- 1, { 32, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 32, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+ 1, { 32, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 32, 0, 0 }, false, false, 1, 1 },
+ 1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, false, false, 2, 1 },
+ 1, { 16, 0, 0 }, false, false, 2, 1, false },
{ V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, false, true, 2, 1 },
+ 1, { 16, 0, 0 }, false, true, 2, 1, false },
{ V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, true, false, 2, 1 },
+ 1, { 16, 0, 0 }, true, false, 2, 1, false },
{ V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, true, true, 2, 1 },
+ 1, { 16, 0, 0 }, true, true, 2, 1, false },
{ V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, false, 2, 2 },
+ 2, { 8, 16, 0 }, false, false, 2, 2, false },
{ V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, true, 2, 2 },
+ 2, { 8, 16, 0 }, false, true, 2, 2, false },
{ V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, false, 2, 1 },
+ 2, { 8, 16, 0 }, false, false, 2, 1, false },
{ V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, true, 2, 1 },
+ 2, { 8, 16, 0 }, false, true, 2, 1, false },
{ V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 3, { 8, 8, 8 }, false, false, 2, 2 },
+ 3, { 8, 8, 8 }, false, false, 2, 2, false },
};
/*
@@ -181,11 +197,29 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
struct v4l2_pix_format_mplane *pix,
const struct vsp1_format_info **fmtinfo)
{
+ static const u32 xrgb_formats[][2] = {
+ { V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_XRGB444 },
+ { V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_XRGB555 },
+ { V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_XBGR32 },
+ { V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_XRGB32 },
+ };
+
const struct vsp1_format_info *info;
unsigned int width = pix->width;
unsigned int height = pix->height;
unsigned int i;
+ /* Backward compatibility: replace deprecated RGB formats by their XRGB
+ * equivalent. This selects the format older userspace applications want
+ * while still exposing the new format.
+ */
+ for (i = 0; i < ARRAY_SIZE(xrgb_formats); ++i) {
+ if (xrgb_formats[i][0] == pix->pixelformat) {
+ pix->pixelformat = xrgb_formats[i][1];
+ break;
+ }
+ }
+
/* Retrieve format information and select the default format if the
* requested format isn't supported.
*/
@@ -273,13 +307,14 @@ vsp1_video_format_adjust(struct vsp1_video *video,
* Pipeline Management
*/
-static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
+static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
+ struct vsp1_rwpf *input,
struct vsp1_rwpf *output)
{
struct vsp1_entity *entity;
unsigned int entities = 0;
struct media_pad *pad;
- bool uds_found = false;
+ bool bru_found = false;
input->location.left = 0;
input->location.top = 0;
@@ -301,10 +336,15 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
*/
if (entity->type == VSP1_ENTITY_BRU) {
struct vsp1_bru *bru = to_bru(&entity->subdev);
- struct v4l2_rect *rect = &bru->compose[pad->index];
+ struct v4l2_rect *rect =
+ &bru->inputs[pad->index].compose;
+
+ bru->inputs[pad->index].rpf = input;
input->location.left = rect->left;
input->location.top = rect->top;
+
+ bru_found = true;
}
/* We've reached the WPF, we're done. */
@@ -319,9 +359,12 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
/* UDS can't be chained. */
if (entity->type == VSP1_ENTITY_UDS) {
- if (uds_found)
+ if (pipe->uds)
return -EPIPE;
- uds_found = true;
+
+ pipe->uds = entity;
+ pipe->uds_input = bru_found ? pipe->bru
+ : &input->entity;
}
/* Follow the source link. The link setup operations ensure
@@ -340,6 +383,27 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
return 0;
}
+static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
+{
+ if (pipe->bru) {
+ struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
+ bru->inputs[i].rpf = NULL;
+ }
+
+ INIT_LIST_HEAD(&pipe->entities);
+ pipe->state = VSP1_PIPELINE_STOPPED;
+ pipe->buffers_ready = 0;
+ pipe->num_video = 0;
+ pipe->num_inputs = 0;
+ pipe->output = NULL;
+ pipe->bru = NULL;
+ pipe->lif = NULL;
+ pipe->uds = NULL;
+}
+
static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
struct vsp1_video *video)
{
@@ -395,7 +459,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
* contains no loop and that all branches end at the output WPF.
*/
for (i = 0; i < pipe->num_inputs; ++i) {
- ret = vsp1_pipeline_validate_branch(pipe->inputs[i],
+ ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i],
pipe->output);
if (ret < 0)
goto error;
@@ -404,13 +468,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
return 0;
error:
- INIT_LIST_HEAD(&pipe->entities);
- pipe->buffers_ready = 0;
- pipe->num_video = 0;
- pipe->num_inputs = 0;
- pipe->output = NULL;
- pipe->bru = NULL;
- pipe->lif = NULL;
+ __vsp1_pipeline_cleanup(pipe);
return ret;
}
@@ -441,16 +499,8 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
mutex_lock(&pipe->lock);
/* If we're the last user clean up the pipeline. */
- if (--pipe->use_count == 0) {
- INIT_LIST_HEAD(&pipe->entities);
- pipe->state = VSP1_PIPELINE_STOPPED;
- pipe->buffers_ready = 0;
- pipe->num_video = 0;
- pipe->num_inputs = 0;
- pipe->output = NULL;
- pipe->bru = NULL;
- pipe->lif = NULL;
- }
+ if (--pipe->use_count == 0)
+ __vsp1_pipeline_cleanup(pipe);
mutex_unlock(&pipe->lock);
}
@@ -471,7 +521,8 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
int ret;
spin_lock_irqsave(&pipe->irqlock, flags);
- pipe->state = VSP1_PIPELINE_STOPPING;
+ if (pipe->state == VSP1_PIPELINE_RUNNING)
+ pipe->state = VSP1_PIPELINE_STOPPING;
spin_unlock_irqrestore(&pipe->irqlock, flags);
ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED,
@@ -479,7 +530,7 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
ret = ret == 0 ? -ETIMEDOUT : 0;
list_for_each_entry(entity, &pipe->entities, list_pipe) {
- if (entity->route)
+ if (entity->route && entity->route->reg)
vsp1_write(entity->vsp1, entity->route->reg,
VI6_DPR_NODE_UNUSED);
@@ -576,6 +627,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
{
+ enum vsp1_pipeline_state state;
unsigned long flags;
unsigned int i;
@@ -591,11 +643,13 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
spin_lock_irqsave(&pipe->irqlock, flags);
+ state = pipe->state;
+ pipe->state = VSP1_PIPELINE_STOPPED;
+
/* If a stop has been requested, mark the pipeline as stopped and
* return.
*/
- if (pipe->state == VSP1_PIPELINE_STOPPING) {
- pipe->state = VSP1_PIPELINE_STOPPED;
+ if (state == VSP1_PIPELINE_STOPPING) {
wake_up(&pipe->wq);
goto done;
}
@@ -608,6 +662,47 @@ done:
spin_unlock_irqrestore(&pipe->irqlock, flags);
}
+/*
+ * Propagate the alpha value through the pipeline.
+ *
+ * As the UDS has restricted scaling capabilities when the alpha component needs
+ * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
+ * value. The UDS then outputs a fixed alpha value which needs to be programmed
+ * from the input RPF alpha.
+ */
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+ struct vsp1_entity *input,
+ unsigned int alpha)
+{
+ struct vsp1_entity *entity;
+ struct media_pad *pad;
+
+ pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
+
+ while (pad) {
+ if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ break;
+
+ entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
+
+ /* The BRU background color has a fixed alpha value set to 255,
+ * the output alpha value is thus always equal to 255.
+ */
+ if (entity->type == VSP1_ENTITY_BRU)
+ alpha = 255;
+
+ if (entity->type == VSP1_ENTITY_UDS) {
+ struct vsp1_uds *uds = to_uds(&entity->subdev);
+
+ vsp1_uds_set_alpha(uds, alpha);
+ break;
+ }
+
+ pad = &entity->pads[entity->source_pad];
+ pad = media_entity_remote_pad(pad);
+ }
+}
+
/* -----------------------------------------------------------------------------
* videobuf2 Queue Operations
*/
@@ -654,8 +749,6 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
if (vb->num_planes < format->num_planes)
return -EINVAL;
- buf->video = video;
-
for (i = 0; i < vb->num_planes; ++i) {
buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
buf->length[i] = vb2_plane_size(vb, i);
@@ -717,6 +810,25 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
mutex_lock(&pipe->lock);
if (pipe->stream_count == pipe->num_video - 1) {
+ if (pipe->uds) {
+ struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
+
+ /* If a BRU is present in the pipeline before the UDS,
+ * the alpha component doesn't need to be scaled as the
+ * BRU output alpha value is fixed to 255. Otherwise we
+ * need to scale the alpha component only when available
+ * at the input RPF.
+ */
+ if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
+ uds->scale_alpha = false;
+ } else {
+ struct vsp1_rwpf *rpf =
+ to_rwpf(&pipe->uds_input->subdev);
+
+ uds->scale_alpha = rpf->video.fmtinfo->alpha;
+ }
+ }
+
list_for_each_entry(entity, &pipe->entities, list_pipe) {
vsp1_entity_route_setup(entity);
@@ -744,6 +856,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
{
struct vsp1_video *video = vb2_get_drv_priv(vq);
struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
+ struct vsp1_video_buffer *buffer;
unsigned long flags;
int ret;
@@ -761,6 +874,8 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
/* Remove all buffers from the IRQ queue. */
spin_lock_irqsave(&video->irqlock, flags);
+ list_for_each_entry(buffer, &video->irqqueue, queue)
+ vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR);
INIT_LIST_HEAD(&video->irqqueue);
spin_unlock_irqrestore(&video->irqlock, flags);
}
@@ -950,8 +1065,8 @@ static int vsp1_video_open(struct file *file)
file->private_data = vfh;
- if (!vsp1_device_get(video->vsp1)) {
- ret = -EBUSY;
+ ret = vsp1_device_get(video->vsp1);
+ if (ret < 0) {
v4l2_fh_del(vfh);
kfree(vfh);
}
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index c04d48fa2999..fd2851a82e00 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -33,6 +33,7 @@ struct vsp1_video;
* @swap_uv: the U and V components are swapped (V comes before U)
* @hsub: horizontal subsampling factor
* @vsub: vertical subsampling factor
+ * @alpha: has an alpha channel
*/
struct vsp1_format_info {
u32 fourcc;
@@ -45,6 +46,7 @@ struct vsp1_format_info {
bool swap_uv;
unsigned int hsub;
unsigned int vsub;
+ bool alpha;
};
enum vsp1_pipeline_state {
@@ -73,10 +75,12 @@ struct vsp1_pipeline {
unsigned int num_video;
unsigned int num_inputs;
- struct vsp1_rwpf *inputs[VPS1_MAX_RPF];
+ struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
struct vsp1_rwpf *output;
struct vsp1_entity *bru;
struct vsp1_entity *lif;
+ struct vsp1_entity *uds;
+ struct vsp1_entity *uds_input;
struct list_head entities;
};
@@ -90,7 +94,6 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
}
struct vsp1_video_buffer {
- struct vsp1_video *video;
struct vb2_buffer buf;
struct list_head queue;
@@ -142,4 +145,8 @@ void vsp1_video_cleanup(struct vsp1_video *video);
void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+ struct vsp1_entity *input,
+ unsigned int alpha);
+
#endif /* __VSP1_VIDEO_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 1294340dcb36..6e057762c933 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -39,22 +39,56 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int wpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_rwpf *wpf =
+ container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+ u32 value;
+
+ if (!vsp1_entity_is_streaming(&wpf->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ALPHA_COMPONENT:
+ value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT);
+ value &= ~VI6_WPF_OUTFMT_PDV_MASK;
+ value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT;
+ vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops wpf_ctrl_ops = {
+ .s_ctrl = wpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
{
+ struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
struct vsp1_rwpf *wpf = to_rwpf(subdev);
- struct vsp1_pipeline *pipe =
- to_vsp1_pipeline(&wpf->entity.subdev.entity);
struct vsp1_device *vsp1 = wpf->entity.vsp1;
const struct v4l2_rect *crop = &wpf->crop;
unsigned int i;
u32 srcrpf = 0;
u32 outfmt = 0;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&wpf->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable) {
vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
+ vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0);
return 0;
}
@@ -99,6 +133,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
+ if (fmtinfo->alpha)
+ outfmt |= VI6_WPF_OUTFMT_PXA;
if (fmtinfo->swap_yc)
outfmt |= VI6_WPF_OUTFMT_SPYCS;
if (fmtinfo->swap_uv)
@@ -111,7 +147,13 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
wpf->entity.formats[RWPF_PAD_SOURCE].code)
outfmt |= VI6_WPF_OUTFMT_CSC;
+ /* Take the control handler lock to ensure that the PDV value won't be
+ * changed behind our back by a set control operation.
+ */
+ mutex_lock(wpf->ctrls.lock);
+ outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK;
vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
+ mutex_unlock(wpf->ctrls.lock);
vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index),
VI6_DPR_WPF_FPORCH_FP_WPFN);
@@ -207,6 +249,20 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&wpf->ctrls, 1);
+ v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 255);
+
+ wpf->entity.subdev.ctrl_handler = &wpf->ctrls;
+
+ if (wpf->ctrls.error) {
+ dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
+ index);
+ ret = wpf->ctrls.error;
+ goto error;
+ }
+
/* Initialize the video device. */
video = &wpf->video;
@@ -216,7 +272,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
ret = vsp1_video_init(video, &wpf->entity);
if (ret < 0)
- goto error_video;
+ goto error;
+
+ wpf->entity.video = video;
/* Connect the video device to the WPF. All connections are immutable
* except for the WPF0 source link if a LIF is present.
@@ -229,15 +287,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
RWPF_PAD_SOURCE,
&wpf->video.video.entity, 0, flags);
if (ret < 0)
- goto error_link;
+ goto error;
wpf->entity.sink = &wpf->video.video.entity;
return wpf;
-error_link:
- vsp1_video_cleanup(video);
-error_video:
- media_entity_cleanup(&wpf->entity.subdev.entity);
+error:
+ vsp1_entity_destroy(&wpf->entity);
return ERR_PTR(ret);
}
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 142c2ee64d31..2262b8139ca1 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -390,7 +390,6 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->videodev.release = video_device_release_empty;
radio->videodev.lock = &radio->v4l2_lock;
radio->videodev.ctrl_handler = &radio->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->curfreq = FREQ_MIN * FREQ_MUL;
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index d719e59e2179..82affaedf067 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -650,7 +650,6 @@ static int __init cadet_init(void)
dev->vdev.ioctl_ops = &cadet_ioctl_ops;
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
res = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 6ff350831d56..c309ee45a08e 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -253,7 +253,6 @@ static int radio_isa_common_probe(struct radio_isa_card *isa,
isa->vdev.fops = &radio_isa_fops;
isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
isa->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags);
video_set_drvdata(&isa->vdev, isa);
isa->freq = FREQ_LOW;
isa->stereo = drv->has_stereo;
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index 3d127825eceb..0c5d2db3b828 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -265,7 +265,7 @@ static int keene_s_ctrl(struct v4l2_ctrl *ctrl)
return keene_cmd_set(radio);
case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step];
+ radio->tx = db2tx[(ctrl->val - (s32)ctrl->minimum) / (s32)ctrl->step];
return keene_cmd_set(radio);
}
return -EINVAL;
@@ -380,7 +380,6 @@ static int usb_keene_probe(struct usb_interface *intf,
usb_set_intfdata(intf, &radio->v4l2_dev);
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
/* at least 11ms is needed in order to settle hardware */
msleep(20);
diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c
index a85b064cb7be..b3000ef85ee7 100644
--- a/drivers/media/radio/radio-ma901.c
+++ b/drivers/media/radio/radio-ma901.c
@@ -411,7 +411,6 @@ static int usb_ma901radio_probe(struct usb_interface *intf,
radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
radio->vdev.release = video_device_release_empty;
radio->vdev.lock = &radio->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index a7e93d7477dd..998919e97dfe 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -1,20 +1,35 @@
-/* Miro PCM20 radio driver for Linux radio support
+/*
+ * Miro PCM20 radio driver for Linux radio support
* (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
* Thanks to Norberto Pellici for the ACI device interface specification
* The API part is based on the radiotrack driver by M. Kirkwood
* This driver relies on the aci mixer provided by the snd-miro
* ALSA driver.
* Look there for further info...
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions... Robert
+ *
+ * From the original miro RDS sources:
+ *
+ * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
+ *
+ * Many thanks to Fred Seidel <seidel@metabox.de>, the
+ * designer of the RDS decoder hardware. With his help
+ * I was able to code this driver.
+ * Thanks also to Norberto Pellicci, Dominic Mounteney
+ * <DMounteney@pinnaclesys.com> and www.teleauskunft.de
+ * for good hints on finding Fred. It was somewhat hard
+ * to locate him here in Germany... [:
+ *
+ * This code has been reintroduced and converted to use
+ * the new V4L2 RDS API by:
+ *
+ * Hans Verkuil <hans.verkuil@cisco.com>
*/
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/videodev2.h>
+#include <linux/kthread.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
@@ -22,6 +37,22 @@
#include <media/v4l2-event.h>
#include <sound/aci.h>
+#define RDS_DATASHIFT 2 /* Bit 2 */
+#define RDS_DATAMASK (1 << RDS_DATASHIFT)
+#define RDS_BUSYMASK 0x10 /* Bit 4 */
+#define RDS_CLOCKMASK 0x08 /* Bit 3 */
+#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1)
+
+#define RDS_STATUS 0x01
+#define RDS_STATIONNAME 0x02
+#define RDS_TEXT 0x03
+#define RDS_ALTFREQ 0x04
+#define RDS_TIMEDATE 0x05
+#define RDS_PI_CODE 0x06
+#define RDS_PTYTATP 0x07
+#define RDS_RESET 0x08
+#define RDS_RXVALUE 0x09
+
static int radio_nr = -1;
module_param(radio_nr, int, 0);
MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)");
@@ -30,6 +61,14 @@ struct pcm20 {
struct v4l2_device v4l2_dev;
struct video_device vdev;
struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *rds_pty;
+ struct v4l2_ctrl *rds_ps_name;
+ struct v4l2_ctrl *rds_radio_test;
+ struct v4l2_ctrl *rds_ta;
+ struct v4l2_ctrl *rds_tp;
+ struct v4l2_ctrl *rds_ms;
+ /* thread for periodic RDS status checking */
+ struct task_struct *kthread;
unsigned long freq;
u32 audmode;
struct snd_miro_aci *aci;
@@ -41,6 +80,103 @@ static struct pcm20 pcm20_card = {
.audmode = V4L2_TUNER_MODE_STEREO,
};
+
+static int rds_waitread(struct snd_miro_aci *aci)
+{
+ u8 byte;
+ int i = 2000;
+
+ do {
+ byte = inb(aci->aci_port + ACI_REG_RDS);
+ i--;
+ } while ((byte & RDS_BUSYMASK) && i);
+
+ /*
+ * It's magic, but without this the data that you read later on
+ * is unreliable and full of bit errors. With this 1 usec delay
+ * everything is fine.
+ */
+ udelay(1);
+ return i ? byte : -1;
+}
+
+static int rds_rawwrite(struct snd_miro_aci *aci, u8 byte)
+{
+ if (rds_waitread(aci) >= 0) {
+ outb(byte, aci->aci_port + ACI_REG_RDS);
+ return 0;
+ }
+ return -1;
+}
+
+static int rds_write(struct snd_miro_aci *aci, u8 byte)
+{
+ u8 sendbuffer[8];
+ int i;
+
+ for (i = 7; i >= 0; i--)
+ sendbuffer[7 - i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
+ sendbuffer[0] |= RDS_CLOCKMASK;
+
+ for (i = 0; i < 8; i++)
+ rds_rawwrite(aci, sendbuffer[i]);
+ return 0;
+}
+
+static int rds_readcycle_nowait(struct snd_miro_aci *aci)
+{
+ outb(0, aci->aci_port + ACI_REG_RDS);
+ return rds_waitread(aci);
+}
+
+static int rds_readcycle(struct snd_miro_aci *aci)
+{
+ if (rds_rawwrite(aci, 0) < 0)
+ return -1;
+ return rds_waitread(aci);
+}
+
+static int rds_ack(struct snd_miro_aci *aci)
+{
+ int i = rds_readcycle(aci);
+
+ if (i < 0)
+ return -1;
+ if (i & RDS_DATAMASK)
+ return 0; /* ACK */
+ return 1; /* NACK */
+}
+
+static int rds_cmd(struct snd_miro_aci *aci, u8 cmd, u8 databuffer[], u8 datasize)
+{
+ int i, j;
+
+ rds_write(aci, cmd);
+
+ /* RDS_RESET doesn't need further processing */
+ if (cmd == RDS_RESET)
+ return 0;
+ if (rds_ack(aci))
+ return -EIO;
+ if (datasize == 0)
+ return 0;
+
+ /* to be able to use rds_readcycle_nowait()
+ I have to waitread() here */
+ if (rds_waitread(aci) < 0)
+ return -1;
+
+ memset(databuffer, 0, datasize);
+
+ for (i = 0; i < 8 * datasize; i++) {
+ j = rds_readcycle_nowait(aci);
+ if (j < 0)
+ return -EIO;
+ databuffer[i / 8] |= RDS_DATA(j) << (7 - (i % 8));
+ }
+ return 0;
+}
+
static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
{
unsigned char freql;
@@ -54,17 +190,10 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
freql = freq & 0xff;
freqh = freq >> 8;
+ rds_cmd(aci, RDS_RESET, NULL, 0);
return snd_aci_cmd(aci, ACI_WRITE_TUNE, freql, freqh);
}
-static const struct v4l2_file_operations pcm20_fops = {
- .owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .poll = v4l2_ctrl_poll,
- .release = v4l2_fh_release,
- .unlocked_ioctl = video_ioctl2,
-};
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
{
@@ -73,16 +202,31 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->driver, "Miro PCM20", sizeof(v->driver));
strlcpy(v->card, "Miro PCM20", sizeof(v->card));
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev->v4l2_dev.name);
- v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
+static bool sanitize(char *p, int size)
+{
+ int i;
+ bool ret = true;
+
+ for (i = 0; i < size; i++) {
+ if (p[i] < 32) {
+ p[i] = ' ';
+ ret = false;
+ }
+ }
+ return ret;
+}
+
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
struct pcm20 *dev = video_drvdata(file);
int res;
+ u8 buf;
if (v->index)
return -EINVAL;
@@ -97,8 +241,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
res = snd_aci_cmd(dev->aci, ACI_READ_TUNERSTEREO, -1, -1);
v->rxsubchans = (res & 0x40) ? V4L2_TUNER_SUB_MONO :
V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
v->audmode = dev->audmode;
+ res = rds_cmd(dev->aci, RDS_RXVALUE, &buf, 1);
+ if (res >= 0 && buf)
+ v->rxsubchans |= V4L2_TUNER_SUB_RDS;
return 0;
}
@@ -157,6 +305,115 @@ static int pcm20_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
+static int pcm20_thread(void *data)
+{
+ struct pcm20 *dev = data;
+ const unsigned no_rds_start_counter = 5;
+ const unsigned sleep_msecs = 2000;
+ unsigned no_rds_counter = no_rds_start_counter;
+
+ for (;;) {
+ char text_buffer[66];
+ u8 buf;
+ int res;
+
+ msleep_interruptible(sleep_msecs);
+
+ if (kthread_should_stop())
+ break;
+
+ res = rds_cmd(dev->aci, RDS_RXVALUE, &buf, 1);
+ if (res)
+ continue;
+ if (buf == 0) {
+ if (no_rds_counter == 0)
+ continue;
+ no_rds_counter--;
+ if (no_rds_counter)
+ continue;
+
+ /*
+ * No RDS seen for no_rds_start_counter * sleep_msecs
+ * milliseconds, clear all RDS controls to their
+ * default values.
+ */
+ v4l2_ctrl_s_ctrl_string(dev->rds_ps_name, "");
+ v4l2_ctrl_s_ctrl(dev->rds_ms, 1);
+ v4l2_ctrl_s_ctrl(dev->rds_ta, 0);
+ v4l2_ctrl_s_ctrl(dev->rds_tp, 0);
+ v4l2_ctrl_s_ctrl(dev->rds_pty, 0);
+ v4l2_ctrl_s_ctrl_string(dev->rds_radio_test, "");
+ continue;
+ }
+ no_rds_counter = no_rds_start_counter;
+
+ res = rds_cmd(dev->aci, RDS_STATUS, &buf, 1);
+ if (res)
+ continue;
+ if ((buf >> 3) & 1) {
+ res = rds_cmd(dev->aci, RDS_STATIONNAME, text_buffer, 8);
+ text_buffer[8] = 0;
+ if (!res && sanitize(text_buffer, 8))
+ v4l2_ctrl_s_ctrl_string(dev->rds_ps_name, text_buffer);
+ }
+ if ((buf >> 6) & 1) {
+ u8 pty;
+
+ res = rds_cmd(dev->aci, RDS_PTYTATP, &pty, 1);
+ if (!res) {
+ v4l2_ctrl_s_ctrl(dev->rds_ms, !!(pty & 0x01));
+ v4l2_ctrl_s_ctrl(dev->rds_ta, !!(pty & 0x02));
+ v4l2_ctrl_s_ctrl(dev->rds_tp, !!(pty & 0x80));
+ v4l2_ctrl_s_ctrl(dev->rds_pty, (pty >> 2) & 0x1f);
+ }
+ }
+ if ((buf >> 4) & 1) {
+ res = rds_cmd(dev->aci, RDS_TEXT, text_buffer, 65);
+ text_buffer[65] = 0;
+ if (!res && sanitize(text_buffer + 1, 64))
+ v4l2_ctrl_s_ctrl_string(dev->rds_radio_test, text_buffer + 1);
+ }
+ }
+ return 0;
+}
+
+static int pcm20_open(struct file *file)
+{
+ struct pcm20 *dev = video_drvdata(file);
+ int res = v4l2_fh_open(file);
+
+ if (!res && v4l2_fh_is_singular_file(file) &&
+ IS_ERR_OR_NULL(dev->kthread)) {
+ dev->kthread = kthread_run(pcm20_thread, dev, "%s",
+ dev->v4l2_dev.name);
+ if (IS_ERR(dev->kthread)) {
+ v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
+ v4l2_fh_release(file);
+ return PTR_ERR(dev->kthread);
+ }
+ }
+ return res;
+}
+
+static int pcm20_release(struct file *file)
+{
+ struct pcm20 *dev = video_drvdata(file);
+
+ if (v4l2_fh_is_singular_file(file) && !IS_ERR_OR_NULL(dev->kthread)) {
+ kthread_stop(dev->kthread);
+ dev->kthread = NULL;
+ }
+ return v4l2_fh_release(file);
+}
+
+static const struct v4l2_file_operations pcm20_fops = {
+ .owner = THIS_MODULE,
+ .open = pcm20_open,
+ .poll = v4l2_ctrl_poll,
+ .release = pcm20_release,
+ .unlocked_ioctl = video_ioctl2,
+};
+
static const struct v4l2_ioctl_ops pcm20_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
@@ -195,9 +452,21 @@ static int __init pcm20_init(void)
}
hdl = &dev->ctrl_handler;
- v4l2_ctrl_handler_init(hdl, 1);
+ v4l2_ctrl_handler_init(hdl, 7);
v4l2_ctrl_new_std(hdl, &pcm20_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+ dev->rds_pty = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_PTY, 0, 0x1f, 1, 0);
+ dev->rds_ps_name = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_PS_NAME, 0, 8, 8, 0);
+ dev->rds_radio_test = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_RADIO_TEXT, 0, 64, 64, 0);
+ dev->rds_ta = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
+ dev->rds_tp = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
+ dev->rds_ms = v4l2_ctrl_new_std(hdl, NULL,
+ V4L2_CID_RDS_RX_MUSIC_SPEECH, 0, 1, 1, 1);
v4l2_dev->ctrl_handler = hdl;
if (hdl->error) {
res = hdl->error;
@@ -210,7 +479,6 @@ static int __init pcm20_init(void)
dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO,
dev->audmode == V4L2_TUNER_MODE_MONO, -1);
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index a360227ca3ab..c2927fd12615 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -32,7 +32,7 @@
* achievements (specifications given).
* Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
* in 2007. He allowed to use his driver to improve current mr800 radio driver.
- * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
+ * http://www.spinics.net/lists/linux-usb-devel/msg10109.html
*
* Version 0.01: First working version.
* It's required to blacklist AverMedia USB Radio
@@ -558,7 +558,6 @@ static int usb_amradio_probe(struct usb_interface *intf,
radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
radio->vdev.release = video_device_release_empty;
radio->vdev.lock = &radio->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c
index 7b3bdbb1be73..bfb3a6d051ba 100644
--- a/drivers/media/radio/radio-raremono.c
+++ b/drivers/media/radio/radio-raremono.c
@@ -361,7 +361,6 @@ static int usb_raremono_probe(struct usb_interface *intf,
usb_set_intfdata(intf, &radio->v4l2_dev);
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
raremono_cmd_main(radio, BAND_FM, 95160);
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 6f4318ff0db3..d7ce8fe6b5ae 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -344,7 +344,6 @@ static int __init fmi_init(void)
fmi->vdev.fops = &fmi_fops;
fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
fmi->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags);
video_set_drvdata(&fmi->vdev, fmi);
mutex_init(&fmi->lock);
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index 2fd9009f8663..633022b45f33 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1470,7 +1470,6 @@ static int si476x_radio_probe(struct platform_device *pdev)
video_set_drvdata(&radio->videodev, radio);
platform_set_drvdata(pdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
v4l2_ctrl_handler_init(&radio->ctrl_handler,
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 3ed1f5669f79..925049654c5b 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -478,7 +478,6 @@ static int tea5764_i2c_probe(struct i2c_client *client,
video_set_drvdata(&radio->vdev, radio);
radio->vdev.lock = &radio->mutex;
radio->vdev.v4l2_dev = v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
/* initialize and power off the chip */
tea5764_i2c_read(radio);
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index e2455970725a..83fe7ab358df 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -570,7 +570,6 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner)
tea->fops = tea575x_fops;
tea->fops.owner = owner;
tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
tea->vd.ctrl_handler = &tea->ctrl_handler;
v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 0817964d9172..b9285e6584af 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -126,7 +126,6 @@ static int timbradio_probe(struct platform_device *pdev)
tr->video_dev.release = video_device_release_empty;
tr->video_dev.minor = -1;
tr->video_dev.lock = &tr->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags);
strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
err = v4l2_device_register(NULL, &tr->v4l2_dev);
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index 07ef40595efd..494fac061306 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -680,7 +680,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
radio->videodev.lock = &radio->lock;
radio->videodev.v4l2_dev = &radio->v4l2_dev;
radio->videodev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
video_set_drvdata(&radio->videodev, radio);
/* get device and chip versions */
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index ba4cfc946868..a47502a330f0 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -196,7 +196,6 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
rsdev->radio_dev = radio_si4713_vdev_template;
rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
- set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
/* Serialize all access to the si4713 */
rsdev->radio_dev.lock = &rsdev->lock;
video_set_drvdata(&rsdev->radio_dev, rsdev);
diff --git a/drivers/media/radio/si4713/radio-usb-si4713.c b/drivers/media/radio/si4713/radio-usb-si4713.c
index 86502b2786d0..a77319dcba05 100644
--- a/drivers/media/radio/si4713/radio-usb-si4713.c
+++ b/drivers/media/radio/si4713/radio-usb-si4713.c
@@ -492,7 +492,6 @@ static int usb_si4713_probe(struct usb_interface *intf,
radio->vdev.vfl_dir = VFL_DIR_TX;
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
if (retval < 0) {
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index 07d5153811e8..b5765557ea3d 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -957,6 +957,41 @@ static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
*bit = 5;
*mask = 0x1F << 5;
break;
+ case V4L2_CID_RDS_TX_DYNAMIC_PTY:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 15;
+ *mask = 1 << 15;
+ break;
+ case V4L2_CID_RDS_TX_COMPRESSED:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 14;
+ *mask = 1 << 14;
+ break;
+ case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 13;
+ *mask = 1 << 13;
+ break;
+ case V4L2_CID_RDS_TX_MONO_STEREO:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 12;
+ *mask = 1 << 12;
+ break;
+ case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 10;
+ *mask = 1 << 10;
+ break;
+ case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 4;
+ *mask = 1 << 4;
+ break;
+ case V4L2_CID_RDS_TX_MUSIC_SPEECH:
+ *property = SI4713_TX_RDS_PS_MISC;
+ *bit = 3;
+ *mask = 1 << 3;
+ break;
case V4L2_CID_AUDIO_LIMITER_ENABLED:
*property = SI4713_TX_ACOMP_ENABLE;
*bit = 1;
@@ -1098,11 +1133,11 @@ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_RDS_TX_PS_NAME:
- ret = si4713_set_rds_ps_name(sdev, ctrl->string);
+ ret = si4713_set_rds_ps_name(sdev, ctrl->p_new.p_char);
break;
case V4L2_CID_RDS_TX_RADIO_TEXT:
- ret = si4713_set_rds_radio_text(sdev, ctrl->string);
+ ret = si4713_set_rds_radio_text(sdev, ctrl->p_new.p_char);
break;
case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
@@ -1122,6 +1157,17 @@ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
}
break;
+ case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
+ case V4L2_CID_RDS_TX_ALT_FREQS:
+ if (sdev->rds_alt_freqs_enable->val) {
+ val = sdev->rds_alt_freqs->p_new.p_u32[0];
+ val = val / 100 - 876 + 0xe101;
+ } else {
+ val = 0xe0e0;
+ }
+ ret = si4713_write_property(sdev, SI4713_TX_RDS_PS_AF, val);
+ break;
+
default:
ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
&mask, &property, &mul, &table, &size);
@@ -1355,6 +1401,17 @@ static const struct v4l2_subdev_ops si4713_subdev_ops = {
.tuner = &si4713_subdev_tuner_ops,
};
+static const struct v4l2_ctrl_config si4713_alt_freqs_ctrl = {
+ .id = V4L2_CID_RDS_TX_ALT_FREQS,
+ .type = V4L2_CTRL_TYPE_U32,
+ .min = 87600,
+ .max = 107900,
+ .step = 100,
+ .def = 87600,
+ .dims = { 1 },
+ .elem_size = sizeof(u32),
+};
+
/*
* I2C driver interface
*/
@@ -1410,6 +1467,23 @@ static int si4713_probe(struct i2c_client *client,
V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
+ sdev->rds_compressed = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_COMPRESSED, 0, 1, 1, 0);
+ sdev->rds_art_head = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, 0, 1, 1, 0);
+ sdev->rds_stereo = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_MONO_STEREO, 0, 1, 1, 1);
+ sdev->rds_tp = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, 0, 1, 1, 0);
+ sdev->rds_ta = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, 0, 1, 1, 0);
+ sdev->rds_ms = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_MUSIC_SPEECH, 0, 1, 1, 1);
+ sdev->rds_dyn_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_DYNAMIC_PTY, 0, 1, 1, 0);
+ sdev->rds_alt_freqs_enable = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
+ V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, 0, 1, 1, 0);
+ sdev->rds_alt_freqs = v4l2_ctrl_new_custom(hdl, &si4713_alt_freqs_ctrl, NULL);
sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
10, DEFAULT_RDS_DEVIATION);
@@ -1476,7 +1550,7 @@ static int si4713_probe(struct i2c_client *client,
rval = hdl->error;
goto free_ctrls;
}
- v4l2_ctrl_cluster(20, &sdev->mute);
+ v4l2_ctrl_cluster(29, &sdev->mute);
sdev->sd.ctrl_handler = hdl;
if (client->irq) {
diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h
index 4837cf6e0e1b..ed700e387605 100644
--- a/drivers/media/radio/si4713/si4713.h
+++ b/drivers/media/radio/si4713/si4713.h
@@ -211,6 +211,15 @@ struct si4713_device {
struct v4l2_ctrl *rds_pi;
struct v4l2_ctrl *rds_deviation;
struct v4l2_ctrl *rds_pty;
+ struct v4l2_ctrl *rds_compressed;
+ struct v4l2_ctrl *rds_art_head;
+ struct v4l2_ctrl *rds_stereo;
+ struct v4l2_ctrl *rds_ta;
+ struct v4l2_ctrl *rds_tp;
+ struct v4l2_ctrl *rds_ms;
+ struct v4l2_ctrl *rds_dyn_pty;
+ struct v4l2_ctrl *rds_alt_freqs_enable;
+ struct v4l2_ctrl *rds_alt_freqs;
struct v4l2_ctrl *compression_enabled;
struct v4l2_ctrl *compression_threshold;
struct v4l2_ctrl *compression_gain;
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c
index 7c14060a40b8..f1a0867789fe 100644
--- a/drivers/media/radio/tea575x.c
+++ b/drivers/media/radio/tea575x.c
@@ -523,7 +523,6 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
tea->fops = tea575x_fops;
tea->fops.owner = owner;
tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
/* disable hw_freq_seek if we can't use it */
if (tea->cannot_read_data)
v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 8fbd377e6311..5e626af8e313 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -84,18 +84,6 @@ config IR_SONY_DECODER
Enable this option if you have an infrared remote control which
uses the Sony protocol, and you need software decoding support.
-config IR_RC5_SZ_DECODER
- tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
- depends on RC_CORE
- select BITREVERSE
- default y
-
- ---help---
- Enable this option if you have IR with RC-5 (streamzap) protocol,
- and if the IR is decoded in software. (The Streamzap PC Remote
- uses an IR protocol that is almost standard RC-5, but not quite,
- as it uses an additional bit).
-
config IR_SANYO_DECODER
tristate "Enable IR raw decoder for the Sanyo protocol"
depends on RC_CORE
@@ -125,6 +113,16 @@ config IR_MCE_KBD_DECODER
Enable this option if you have a Microsoft Remote Keyboard for
Windows Media Center Edition, which you would like to use with
a raw IR receiver in your system.
+
+config IR_XMP_DECODER
+ tristate "Enable IR raw decoder for the XMP protocol"
+ depends on RC_CORE
+ select BITREVERSE
+ default y
+
+ ---help---
+ Enable this option if you have IR with XMP protocol, and
+ if the IR is decoded in software
endif #RC_DECODERS
menuconfig RC_DEVICES
@@ -343,4 +341,14 @@ config RC_ST
If you're not sure, select N here.
+config IR_SUNXI
+ tristate "SUNXI IR remote control"
+ depends on RC_CORE
+ depends on ARCH_SUNXI
+ ---help---
+ Say Y if you want to use sunXi internal IR Controller
+
+ To compile this driver as a module, choose M here: the module will
+ be called sunxi-ir.
+
endif #RC_DEVICES
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index f8b54ff46601..9f9843a1af5f 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -1,4 +1,4 @@
-rc-core-objs := rc-main.o ir-raw.o
+rc-core-objs := rc-main.o rc-ir-raw.o
obj-y += keymaps/
@@ -9,11 +9,11 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
-obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
+obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
# stand-alone IR receivers/transmitters
obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
@@ -32,4 +32,5 @@ obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
obj-$(CONFIG_IR_IGUANA) += iguanair.o
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
obj-$(CONFIG_RC_ST) += st_rc.o
+obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
obj-$(CONFIG_IR_IMG) += img-ir/
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 2df7c5516013..a35631891cc0 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -279,46 +279,42 @@ struct ati_remote {
/* "Kinds" of messages sent from the hardware to the driver. */
#define KIND_END 0
-#define KIND_LITERAL 1 /* Simply pass to input system */
+#define KIND_LITERAL 1 /* Simply pass to input system as EV_KEY */
#define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */
-#define KIND_LU 3 /* Directional keypad diagonals - left up, */
-#define KIND_RU 4 /* right up, */
-#define KIND_LD 5 /* left down, */
-#define KIND_RD 6 /* right down */
-#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
+#define KIND_ACCEL 3 /* Translate to EV_REL mouse-move events */
/* Translation table from hardware messages to input events. */
static const struct {
- short kind;
- unsigned char data;
- int type;
- unsigned int code;
- int value;
+ unsigned char kind;
+ unsigned char data; /* Raw key code from remote */
+ unsigned short code; /* Input layer translation */
} ati_remote_tbl[] = {
- /* Directional control pad axes */
- {KIND_ACCEL, 0x70, EV_REL, REL_X, -1}, /* left */
- {KIND_ACCEL, 0x71, EV_REL, REL_X, 1}, /* right */
- {KIND_ACCEL, 0x72, EV_REL, REL_Y, -1}, /* up */
- {KIND_ACCEL, 0x73, EV_REL, REL_Y, 1}, /* down */
- /* Directional control pad diagonals */
- {KIND_LU, 0x74, EV_REL, 0, 0}, /* left up */
- {KIND_RU, 0x75, EV_REL, 0, 0}, /* right up */
- {KIND_LD, 0x77, EV_REL, 0, 0}, /* left down */
- {KIND_RD, 0x76, EV_REL, 0, 0}, /* right down */
+ /* Directional control pad axes. Code is xxyy */
+ {KIND_ACCEL, 0x70, 0xff00}, /* left */
+ {KIND_ACCEL, 0x71, 0x0100}, /* right */
+ {KIND_ACCEL, 0x72, 0x00ff}, /* up */
+ {KIND_ACCEL, 0x73, 0x0001}, /* down */
- /* "Mouse button" buttons */
- {KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
- {KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
- {KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
- {KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+ /* Directional control pad diagonals */
+ {KIND_ACCEL, 0x74, 0xffff}, /* left up */
+ {KIND_ACCEL, 0x75, 0x01ff}, /* right up */
+ {KIND_ACCEL, 0x77, 0xff01}, /* left down */
+ {KIND_ACCEL, 0x76, 0x0101}, /* right down */
+
+ /* "Mouse button" buttons. The code below uses the fact that the
+ * lsbit of the raw code is a down/up indicator. */
+ {KIND_LITERAL, 0x78, BTN_LEFT}, /* left btn down */
+ {KIND_LITERAL, 0x79, BTN_LEFT}, /* left btn up */
+ {KIND_LITERAL, 0x7c, BTN_RIGHT},/* right btn down */
+ {KIND_LITERAL, 0x7d, BTN_RIGHT},/* right btn up */
/* Artificial "doubleclick" events are generated by the hardware.
* They are mapped to the "side" and "extra" mouse buttons here. */
- {KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
- {KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+ {KIND_FILTERED, 0x7a, BTN_SIDE}, /* left dblclick */
+ {KIND_FILTERED, 0x7e, BTN_EXTRA},/* right dblclick */
/* Non-mouse events are handled by rc-core */
- {KIND_END, 0x00, EV_MAX + 1, 0, 0}
+ {KIND_END, 0x00, 0}
};
/*
@@ -493,7 +489,6 @@ static void ati_remote_input_report(struct urb *urb)
unsigned char *data= ati_remote->inbuf;
struct input_dev *dev = ati_remote->idev;
int index = -1;
- int acc;
int remote_num;
unsigned char scancode;
u32 wheel_keycode = KEY_RESERVED;
@@ -507,8 +502,9 @@ static void ati_remote_input_report(struct urb *urb)
*/
/* Deal with strange looking inputs */
- if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
- ((data[3] & 0x0f) != 0x00) ) {
+ if ( urb->actual_length != 4 || data[0] != 0x14 ||
+ data[1] != (unsigned char)(data[2] + data[3] + 0xD5) ||
+ (data[3] & 0x0f) != 0x00) {
ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
return;
}
@@ -524,9 +520,9 @@ static void ati_remote_input_report(struct urb *urb)
remote_num = (data[3] >> 4) & 0x0f;
if (channel_mask & (1 << (remote_num + 1))) {
dbginfo(&ati_remote->interface->dev,
- "Masked input from channel 0x%02x: data %02x,%02x, "
+ "Masked input from channel 0x%02x: data %02x, "
"mask= 0x%02lx\n",
- remote_num, data[1], data[2], channel_mask);
+ remote_num, data[2], channel_mask);
return;
}
@@ -566,16 +562,16 @@ static void ati_remote_input_report(struct urb *urb)
}
if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code,
- ati_remote_tbl[index].value);
- input_sync(dev);
+ /*
+ * The lsbit of the raw key code is a down/up flag.
+ * Invert it to match the input layer's conventions.
+ */
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code,
+ !(data[2] & 1));
ati_remote->old_jiffies = jiffies;
- return;
- }
- if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
+ } else if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
unsigned long now = jiffies;
/* Filter duplicate events which happen "too close" together. */
@@ -588,12 +584,11 @@ static void ati_remote_input_report(struct urb *urb)
ati_remote->first_jiffies = now;
}
- ati_remote->old_data = data[2];
ati_remote->old_jiffies = now;
- /* Ensure we skip at least the 4 first duplicate events (generated
- * by a single keypress), and continue skipping until repeat_delay
- * msecs have passed
+ /* Ensure we skip at least the 4 first duplicate events
+ * (generated by a single keypress), and continue skipping
+ * until repeat_delay msecs have passed.
*/
if (ati_remote->repeat_count > 0 &&
(ati_remote->repeat_count < 5 ||
@@ -601,7 +596,10 @@ static void ati_remote_input_report(struct urb *urb)
msecs_to_jiffies(repeat_delay))))
return;
- if (index < 0) {
+ if (index >= 0) {
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code, 1);
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code, 0);
+ } else {
/* Not a mouse event, hand it to rc-core. */
int count = 1;
@@ -622,61 +620,37 @@ static void ati_remote_input_report(struct urb *urb)
* it would cause ghost repeats which would be a
* regression for this driver.
*/
- rc_keydown_notimeout(ati_remote->rdev, scancode,
- data[2]);
+ rc_keydown_notimeout(ati_remote->rdev, RC_TYPE_OTHER,
+ scancode, data[2]);
rc_keyup(ati_remote->rdev);
}
- return;
+ goto nosync;
}
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code, 1);
- input_sync(dev);
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code, 0);
- input_sync(dev);
-
- } else {
+ } else if (ati_remote_tbl[index].kind == KIND_ACCEL) {
+ signed char dx = ati_remote_tbl[index].code >> 8;
+ signed char dy = ati_remote_tbl[index].code & 255;
/*
* Other event kinds are from the directional control pad, and
* have an acceleration factor applied to them. Without this
* acceleration, the control pad is mostly unusable.
*/
- acc = ati_remote_compute_accel(ati_remote);
-
- switch (ati_remote_tbl[index].kind) {
- case KIND_ACCEL:
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code,
- ati_remote_tbl[index].value * acc);
- break;
- case KIND_LU:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_RU:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_LD:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- case KIND_RD:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- default:
- dev_dbg(&ati_remote->interface->dev,
- "ati_remote kind=%d\n",
- ati_remote_tbl[index].kind);
- }
- input_sync(dev);
-
+ int acc = ati_remote_compute_accel(ati_remote);
+ if (dx)
+ input_report_rel(dev, REL_X, dx * acc);
+ if (dy)
+ input_report_rel(dev, REL_Y, dy * acc);
ati_remote->old_jiffies = jiffies;
- ati_remote->old_data = data[2];
+
+ } else {
+ dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+ ati_remote_tbl[index].kind);
+ return;
}
+ input_sync(dev);
+nosync:
+ ati_remote->old_data = data[2];
}
/*
@@ -763,8 +737,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
- if (ati_remote_tbl[i].type == EV_KEY)
- set_bit(ati_remote_tbl[i].code, idev->keybit);
+ if (ati_remote_tbl[i].kind == KIND_LITERAL ||
+ ati_remote_tbl[i].kind == KIND_FILTERED)
+ __set_bit(ati_remote_tbl[i].code, idev->keybit);
input_set_drvdata(idev, ati_remote);
@@ -784,7 +759,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
rdev->priv = ati_remote;
rdev->driver_type = RC_DRIVER_SCANCODE;
- rc_set_allowed_protocols(rdev, RC_BIT_OTHER);
+ rdev->allowed_protocols = RC_BIT_OTHER;
rdev->driver_name = "ati_remote";
rdev->open = ati_remote_rc_open;
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index fc9d23f2ed3f..d16d9b496b92 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
learning_mode_force = false;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->priv = dev;
rdev->open = ene_open;
rdev->close = ene_close;
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 46b66e59438f..f0a1f7d31ee6 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
/* Set up the rc device */
rdev->priv = fintek;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = fintek_open;
rdev->close = fintek_close;
rdev->input_name = FINTEK_DESCRIPTION;
@@ -686,12 +686,12 @@ static struct pnp_driver fintek_driver = {
.shutdown = fintek_shutdown,
};
-static int fintek_init(void)
+static int __init fintek_init(void)
{
return pnp_register_driver(&fintek_driver);
}
-static void fintek_exit(void)
+static void __exit fintek_exit(void)
{
pnp_unregister_driver(&fintek_driver);
}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 29b5f89813b4..59853085bc88 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
rcdev->dev.parent = &pdev->dev;
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
if (pdata->allowed_protos)
- rc_set_allowed_protocols(rcdev, pdata->allowed_protos);
+ rcdev->allowed_protocols = pdata->allowed_protos;
else
- rc_set_allowed_protocols(rcdev, RC_BIT_ALL);
+ rcdev->allowed_protocols = RC_BIT_ALL;
rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
gpio_dev->rcdev = rcdev;
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 627ddfd61980..ee60e17fba05 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -495,7 +495,7 @@ static int iguanair_probe(struct usb_interface *intf,
usb_to_input_id(ir->udev, &rc->input_id);
rc->dev.parent = &intf->dev;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->priv = ir;
rc->open = iguanair_open;
rc->close = iguanair_close;
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index 6b7834834fb8..a0cac2f09109 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This contains core img-ir code for setting up the driver. The two interfaces
* (raw and hardware decode) are handled separately.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 0127dd257a57..bfb282a714e8 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core. Protocol support is
* provided in separate modules which provide the parameters and scancode
* translation functions to set up the hardware decoder and interpret the
@@ -507,7 +512,7 @@ unlock:
static int img_ir_set_normal_filter(struct rc_dev *dev,
struct rc_scancode_filter *sc_filter)
{
- return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter);
+ return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter);
}
static int img_ir_set_wakeup_filter(struct rc_dev *dev,
@@ -551,8 +556,8 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
hw->mode = IMG_IR_M_NORMAL;
/* clear the wakeup scancode filter */
- rdev->scancode_filters[RC_FILTER_WAKEUP].data = 0;
- rdev->scancode_filters[RC_FILTER_WAKEUP].mask = 0;
+ rdev->scancode_wakeup_filter.data = 0;
+ rdev->scancode_wakeup_filter.mask = 0;
/* clear raw filters */
_img_ir_set_filter(priv, NULL);
@@ -656,8 +661,8 @@ success:
wakeup_protocols = *ir_type;
if (!hw->decoder || !hw->decoder->filter)
wakeup_protocols = 0;
- rc_set_allowed_wakeup_protocols(rdev, wakeup_protocols);
- rc_set_enabled_wakeup_protocols(rdev, wakeup_protocols);
+ rdev->allowed_wakeup_protocols = wakeup_protocols;
+ rdev->enabled_wakeup_protocols = wakeup_protocols;
return 0;
}
@@ -671,9 +676,9 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, u64 proto)
spin_unlock_irq(&rdev->rc_map.lock);
mutex_lock(&rdev->lock);
- rc_set_enabled_protocols(rdev, proto);
- rc_set_allowed_wakeup_protocols(rdev, proto);
- rc_set_enabled_wakeup_protocols(rdev, proto);
+ rdev->enabled_protocols = proto;
+ rdev->allowed_wakeup_protocols = proto;
+ rdev->enabled_wakeup_protocols = proto;
mutex_unlock(&rdev->lock);
}
@@ -790,9 +795,11 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw)
struct img_ir_priv_hw *hw = &priv->hw;
const struct img_ir_decoder *dec = hw->decoder;
int ret = IMG_IR_SCANCODE;
- int scancode;
+ u32 scancode;
+ enum rc_type protocol = RC_TYPE_UNKNOWN;
+
if (dec->scancode)
- ret = dec->scancode(len, raw, &scancode, hw->enabled_protocols);
+ ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols);
else if (len >= 32)
scancode = (u32)raw;
else if (len < 32)
@@ -801,7 +808,7 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw)
len, (unsigned long long)raw);
if (ret == IMG_IR_SCANCODE) {
dev_dbg(priv->dev, "decoded scan code %#x\n", scancode);
- rc_keydown(hw->rdev, scancode, 0);
+ rc_keydown(hw->rdev, protocol, scancode, 0);
img_ir_end_repeat(priv);
} else if (ret == IMG_IR_REPEATCODE) {
if (hw->mode == IMG_IR_M_REPEATING) {
@@ -996,7 +1003,7 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
}
rdev->priv = priv;
rdev->map_name = RC_MAP_EMPTY;
- rc_set_allowed_protocols(rdev, img_ir_allowed_protos(priv));
+ rdev->allowed_protocols = img_ir_allowed_protos(priv);
rdev->input_name = "IMG Infrared Decoder";
rdev->s_filter = img_ir_set_normal_filter;
rdev->s_wakeup_filter = img_ir_set_wakeup_filter;
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 6c9a94a81190..3e40ce87b898 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -2,6 +2,11 @@
* ImgTec IR Hardware Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_HW_H_
@@ -157,7 +162,8 @@ struct img_ir_decoder {
struct img_ir_control control;
/* scancode logic */
- int (*scancode)(int len, u64 raw, int *scancode, u64 protocols);
+ int (*scancode)(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols);
int (*filter)(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols);
};
diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c
index 10209d200efb..a60dda8bf706 100644
--- a/drivers/media/rc/img-ir/img-ir-jvc.c
+++ b/drivers/media/rc/img-ir/img-ir-jvc.c
@@ -2,12 +2,18 @@
* ImgTec IR Decoder setup for JVC protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert JVC data to a scancode */
-static int img_ir_jvc_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int cust, data;
@@ -17,6 +23,7 @@ static int img_ir_jvc_scancode(int len, u64 raw, int *scancode, u64 protocols)
cust = (raw >> 0) & 0xff;
data = (raw >> 8) & 0xff;
+ *protocol = RC_TYPE_JVC;
*scancode = cust << 8 | data;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c
index 751d9d945269..739897549b5b 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -2,13 +2,19 @@
* ImgTec IR Decoder setup for NEC protocol.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
#include <linux/bitrev.h>
/* Convert NEC data to a scancode */
-static int img_ir_nec_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -40,6 +46,7 @@ static int img_ir_nec_scancode(int len, u64 raw, int *scancode, u64 protocols)
*scancode = addr << 8 |
data;
}
+ *protocol = RC_TYPE_NEC;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
index cfb01d9e571a..33f37ed87ad2 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.c
+++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core in raw mode. Raw IR
* signal edges are reported and decoded by generic software decoders.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-raw.h b/drivers/media/rc/img-ir/img-ir-raw.h
index 9802ffd51b9a..4c9b7676e6fc 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.h
+++ b/drivers/media/rc/img-ir/img-ir-raw.h
@@ -2,6 +2,11 @@
* ImgTec IR Raw Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_RAW_H_
diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c
index c2c763e08a41..6b0653ecdf5a 100644
--- a/drivers/media/rc/img-ir/img-ir-sanyo.c
+++ b/drivers/media/rc/img-ir/img-ir-sanyo.c
@@ -3,6 +3,11 @@
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* From ir-sanyo-decoder.c:
*
* This protocol uses the NEC protocol timings. However, data is formatted as:
@@ -18,7 +23,8 @@
#include "img-ir-hw.h"
/* Convert Sanyo data to a scancode */
-static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -38,6 +44,7 @@ static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
return -EINVAL;
/* Normal Sanyo */
+ *protocol = RC_TYPE_SANYO;
*scancode = addr << 8 | data;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c
index 3397cc5a6794..3300a38802ac 100644
--- a/drivers/media/rc/img-ir/img-ir-sharp.c
+++ b/drivers/media/rc/img-ir/img-ir-sharp.c
@@ -2,12 +2,18 @@
* ImgTec IR Decoder setup for Sharp protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sharp data to a scancode */
-static int img_ir_sharp_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, cmd, exp, chk;
@@ -26,6 +32,7 @@ static int img_ir_sharp_scancode(int len, u64 raw, int *scancode, u64 protocols)
/* probably the second half of the message */
return -EINVAL;
+ *protocol = RC_TYPE_SHARP;
*scancode = addr << 8 | cmd;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c
index 993409a51a71..3a0f17b0752c 100644
--- a/drivers/media/rc/img-ir/img-ir-sony.c
+++ b/drivers/media/rc/img-ir/img-ir-sony.c
@@ -2,40 +2,49 @@
* ImgTec IR Decoder setup for Sony (SIRC) protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sony data to a scancode */
-static int img_ir_sony_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int dev, subdev, func;
switch (len) {
case 12:
- if (!(protocols & RC_BIT_SONY12))
+ if (!(enabled_protocols & RC_BIT_SONY12))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
subdev = 0;
+ *protocol = RC_TYPE_SONY12;
break;
case 15:
- if (!(protocols & RC_BIT_SONY15))
+ if (!(enabled_protocols & RC_BIT_SONY15))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0xff; /* next 8 bits */
subdev = 0;
+ *protocol = RC_TYPE_SONY15;
break;
case 20:
- if (!(protocols & RC_BIT_SONY20))
+ if (!(enabled_protocols & RC_BIT_SONY20))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
raw >>= 5;
subdev = raw & 0xff; /* next 8 bits */
+ *protocol = RC_TYPE_SONY20;
break;
default:
return -EINVAL;
diff --git a/drivers/media/rc/img-ir/img-ir.h b/drivers/media/rc/img-ir/img-ir.h
index afb189394af9..2ddf56083182 100644
--- a/drivers/media/rc/img-ir/img-ir.h
+++ b/drivers/media/rc/img-ir/img-ir.h
@@ -2,6 +2,11 @@
* ImgTec IR Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_H_
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 6f24e77b1488..7115e68ba697 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -78,11 +78,11 @@ static int display_open(struct inode *inode, struct file *file);
static int display_close(struct inode *inode, struct file *file);
/* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos);
/* LCD file_operations override function prototypes */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos);
/*** G L O B A L S ***/
@@ -825,7 +825,7 @@ static struct attribute_group imon_rf_attr_group = {
* than 32 bytes are provided spaces will be appended to
* generate a full screen.
*/
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos)
{
int i;
@@ -912,7 +912,7 @@ exit:
* display whatever diacritics you need, and so on), but it's also
* a lot more complicated than most LCDs...
*/
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos)
{
int retval = 0;
@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
unsigned char ir_proto_packet[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
- if (*rc_type && !rc_protocols_allowed(rc, *rc_type))
+ if (*rc_type && !(*rc_type & rc->allowed_protocols))
dev_warn(dev, "Looks like you're trying to use an IR protocol "
"this device does not support\n");
@@ -1579,7 +1579,10 @@ static void imon_incoming_packet(struct imon_context *ictx,
if (press_type == 0)
rc_keyup(ictx->rdev);
else {
- rc_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle);
+ if (ictx->rc_type == RC_BIT_RC6_MCE)
+ rc_keydown(ictx->rdev,
+ ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
+ ictx->rc_scancode, ictx->rc_toggle);
spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->last_keycode = ictx->kc;
spin_unlock_irqrestore(&ictx->kc_lock, flags);
@@ -1867,8 +1870,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
rdev->priv = ictx;
rdev->driver_type = RC_DRIVER_SCANCODE;
- /* iMON PAD or MCE */
- rc_set_allowed_protocols(rdev, RC_BIT_OTHER | RC_BIT_RC6_MCE);
+ rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
rdev->change_protocol = imon_ir_change_protocol;
rdev->driver_name = MOD_NAME;
@@ -1881,7 +1883,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
if (ictx->product == 0xffdc) {
imon_get_ffdc_type(ictx);
- rc_set_allowed_protocols(rdev, ictx->rc_type);
+ rdev->allowed_protocols = ictx->rc_type;
}
imon_set_display_type(ictx);
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 4ea62a1dcfda..30bcf188d377 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct jvc_dec *data = &dev->raw->jvc;
- if (!rc_protocols_enabled(dev, RC_BIT_JVC))
+ if (!(dev->enabled_protocols & RC_BIT_JVC))
return 0;
if (!is_timing_event(ev)) {
@@ -140,7 +140,7 @@ again:
scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
(bitrev8((data->bits >> 0) & 0xff) << 0);
IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
- rc_keydown(dev, scancode, data->toggle);
+ rc_keydown(dev, RC_TYPE_JVC, scancode, data->toggle);
data->first = false;
data->old_bits = data->bits;
} else if (data->bits == data->old_bits) {
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index d731da6c414d..ed2c8a1ed8ca 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct lirc_codec *lirc = &dev->raw->lirc;
int sample;
- if (!rc_protocols_enabled(dev, RC_BIT_LIRC))
+ if (!(dev->enabled_protocols & RC_BIT_LIRC))
return 0;
if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 0c55f794c8cf..9f3c9b59f30c 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
u32 scancode;
unsigned long delay;
- if (!rc_protocols_enabled(dev, RC_BIT_MCE_KBD))
+ if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
return 0;
if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 35c42e5e270b..7b81fec0820f 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
u8 address, not_address, command, not_command;
bool send_32bits = false;
- if (!rc_protocols_enabled(dev, RC_BIT_NEC))
+ if (!(dev->enabled_protocols & RC_BIT_NEC))
return 0;
if (!is_timing_event(ev)) {
@@ -189,7 +189,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
if (data->is_nec_x)
data->necx_repeat = true;
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, RC_TYPE_NEC, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 4295d9b250c8..2ef763928ca4 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -1,6 +1,7 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,23 +14,22 @@
*/
/*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
+ * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
+ * and 20 bit RC5x protocol.
*/
#include "rc-core-priv.h"
#include <linux/module.h>
#define RC5_NBITS 14
+#define RC5_SZ_NBITS 15
#define RC5X_NBITS 20
#define CHECK_RC5X_NBITS 8
#define RC5_UNIT 888888 /* ns */
#define RC5_BIT_START (1 * RC5_UNIT)
#define RC5_BIT_END (1 * RC5_UNIT)
#define RC5X_SPACE (4 * RC5_UNIT)
+#define RC5_TRAILER (10 * RC5_UNIT) /* In reality, approx 100 */
enum rc5_state {
STATE_INACTIVE,
@@ -51,8 +51,9 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct rc5_dec *data = &dev->raw->rc5;
u8 toggle;
u32 scancode;
+ enum rc_type protocol;
- if (!rc_protocols_enabled(dev, RC_BIT_RC5 | RC_BIT_RC5X))
+ if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
return 0;
if (!is_timing_event(ev)) {
@@ -65,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
goto out;
again:
- IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+ IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
@@ -79,12 +80,15 @@ again:
data->state = STATE_BIT_START;
data->count = 1;
- /* We just need enough bits to get to STATE_CHECK_RC5X */
- data->wanted_bits = RC5X_NBITS;
decrease_duration(&ev, RC5_BIT_START);
goto again;
case STATE_BIT_START:
+ if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
+ data->state = STATE_FINISHED;
+ goto again;
+ }
+
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
break;
@@ -99,9 +103,7 @@ again:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
- if (data->count == data->wanted_bits)
- data->state = STATE_FINISHED;
- else if (data->count == CHECK_RC5X_NBITS)
+ if (data->count == CHECK_RC5X_NBITS)
data->state = STATE_CHECK_RC5X;
else
data->state = STATE_BIT_START;
@@ -111,13 +113,10 @@ again:
case STATE_CHECK_RC5X:
if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
- /* RC5X */
- data->wanted_bits = RC5X_NBITS;
+ data->is_rc5x = true;
decrease_duration(&ev, RC5X_SPACE);
- } else {
- /* RC5 */
- data->wanted_bits = RC5_NBITS;
- }
+ } else
+ data->is_rc5x = false;
data->state = STATE_BIT_START;
goto again;
@@ -125,10 +124,10 @@ again:
if (ev.pulse)
break;
- if (data->wanted_bits == RC5X_NBITS) {
+ if (data->is_rc5x && data->count == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
- if (!rc_protocols_enabled(dev, RC_BIT_RC5X)) {
+ if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
data->state = STATE_INACTIVE;
return 0;
}
@@ -138,14 +137,12 @@ again:
toggle = (data->bits & 0x20000) ? 1 : 0;
command += (data->bits & 0x01000) ? 0 : 0x40;
scancode = system << 16 | command << 8 | xdata;
+ protocol = RC_TYPE_RC5X;
- IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
- scancode, toggle);
-
- } else {
+ } else if (!data->is_rc5x && data->count == RC5_NBITS) {
/* RC5 */
u8 command, system;
- if (!rc_protocols_enabled(dev, RC_BIT_RC5)) {
+ if (!(dev->enabled_protocols & RC_BIT_RC5)) {
data->state = STATE_INACTIVE;
return 0;
}
@@ -154,25 +151,41 @@ again:
toggle = (data->bits & 0x00800) ? 1 : 0;
command += (data->bits & 0x01000) ? 0 : 0x40;
scancode = system << 8 | command;
+ protocol = RC_TYPE_RC5;
- IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
- scancode, toggle);
- }
+ } else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
+ /* RC5 StreamZap */
+ u8 command, system;
+ if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+ command = (data->bits & 0x0003F) >> 0;
+ system = (data->bits & 0x02FC0) >> 6;
+ toggle = (data->bits & 0x01000) ? 1 : 0;
+ scancode = system << 6 | command;
+ protocol = RC_TYPE_RC5_SZ;
- rc_keydown(dev, scancode, toggle);
+ } else
+ break;
+
+ IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
+ scancode, protocol, toggle);
+
+ rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
return 0;
}
out:
- IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ IR_dprintk(1, "RC5(x/sz) decode failed at state %i count %d (%uus %s)\n",
+ data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler rc5_handler = {
- .protocols = RC_BIT_RC5 | RC_BIT_RC5X,
+ .protocols = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
.decode = ir_rc5_decode,
};
@@ -180,7 +193,7 @@ static int __init ir_rc5_decode_init(void)
{
ir_raw_handler_register(&rc5_handler);
- printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
+ printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
return 0;
}
@@ -193,6 +206,6 @@ module_init(ir_rc5_decode_init);
module_exit(ir_rc5_decode_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
+MODULE_DESCRIPTION("RC5(x/sz) IR protocol decoder");
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
deleted file mode 100644
index dc18b7434db8..000000000000
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab
- * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/*
- * This code handles the 15 bit RC5-ish protocol used by the Streamzap
- * PC Remote.
- * It considers a carrier of 36 kHz, with a total of 15 bits, where
- * the first two bits are start bits, and a third one is a filing bit
- */
-
-#include "rc-core-priv.h"
-#include <linux/module.h>
-
-#define RC5_SZ_NBITS 15
-#define RC5_UNIT 888888 /* ns */
-#define RC5_BIT_START (1 * RC5_UNIT)
-#define RC5_BIT_END (1 * RC5_UNIT)
-
-enum rc5_sz_state {
- STATE_INACTIVE,
- STATE_BIT_START,
- STATE_BIT_END,
- STATE_FINISHED,
-};
-
-/**
- * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
- * @dev: the struct rc_dev descriptor of the device
- * @ev: the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
-{
- struct rc5_sz_dec *data = &dev->raw->rc5_sz;
- u8 toggle, command, system;
- u32 scancode;
-
- if (!rc_protocols_enabled(dev, RC_BIT_RC5_SZ))
- return 0;
-
- if (!is_timing_event(ev)) {
- if (ev.reset)
- data->state = STATE_INACTIVE;
- return 0;
- }
-
- if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
- goto out;
-
-again:
- IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
- if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
- return 0;
-
- switch (data->state) {
-
- case STATE_INACTIVE:
- if (!ev.pulse)
- break;
-
- data->state = STATE_BIT_START;
- data->count = 1;
- data->wanted_bits = RC5_SZ_NBITS;
- decrease_duration(&ev, RC5_BIT_START);
- goto again;
-
- case STATE_BIT_START:
- if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
- break;
-
- data->bits <<= 1;
- if (!ev.pulse)
- data->bits |= 1;
- data->count++;
- data->state = STATE_BIT_END;
- return 0;
-
- case STATE_BIT_END:
- if (!is_transition(&ev, &dev->raw->prev_ev))
- break;
-
- if (data->count == data->wanted_bits)
- data->state = STATE_FINISHED;
- else
- data->state = STATE_BIT_START;
-
- decrease_duration(&ev, RC5_BIT_END);
- goto again;
-
- case STATE_FINISHED:
- if (ev.pulse)
- break;
-
- /* RC5-sz */
- command = (data->bits & 0x0003F) >> 0;
- system = (data->bits & 0x02FC0) >> 6;
- toggle = (data->bits & 0x01000) ? 1 : 0;
- scancode = system << 6 | command;
-
- IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
- scancode, toggle);
-
- rc_keydown(dev, scancode, toggle);
- data->state = STATE_INACTIVE;
- return 0;
- }
-
-out:
- IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
- data->state = STATE_INACTIVE;
- return -EINVAL;
-}
-
-static struct ir_raw_handler rc5_sz_handler = {
- .protocols = RC_BIT_RC5_SZ,
- .decode = ir_rc5_sz_decode,
-};
-
-static int __init ir_rc5_sz_decode_init(void)
-{
- ir_raw_handler_register(&rc5_sz_handler);
-
- printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
- return 0;
-}
-
-static void __exit ir_rc5_sz_decode_exit(void)
-{
- ir_raw_handler_unregister(&rc5_sz_handler);
-}
-
-module_init(ir_rc5_sz_decode_init);
-module_exit(ir_rc5_sz_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index cfbd64e3999c..f1f098e22f7e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -88,10 +88,11 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct rc6_dec *data = &dev->raw->rc6;
u32 scancode;
u8 toggle;
+ enum rc_type protocol;
- if (!rc_protocols_enabled(dev, RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
- RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
- RC_BIT_RC6_MCE))
+ if (!(dev->enabled_protocols &
+ (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
+ RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
return 0;
if (!is_timing_event(ev)) {
@@ -233,9 +234,11 @@ again:
case RC6_MODE_0:
scancode = data->body;
toggle = data->toggle;
+ protocol = RC_TYPE_RC6_0;
IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
scancode, toggle);
break;
+
case RC6_MODE_6A:
if (data->count > CHAR_BIT * sizeof data->body) {
IR_dprintk(1, "RC6 too many (%u) data bits\n",
@@ -244,23 +247,39 @@ again:
}
scancode = data->body;
- if (data->count == RC6_6A_32_NBITS &&
- (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
- /* MCE RC */
- toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
- scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
- } else {
+ switch (data->count) {
+ case 20:
+ protocol = RC_TYPE_RC6_6A_20;
+ toggle = 0;
+ break;
+ case 24:
+ protocol = RC_BIT_RC6_6A_24;
toggle = 0;
+ break;
+ case 32:
+ if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+ protocol = RC_TYPE_RC6_MCE;
+ scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
+ } else {
+ protocol = RC_BIT_RC6_6A_32;
+ toggle = 0;
+ }
+ break;
+ default:
+ IR_dprintk(1, "RC6(6A) unsupported length\n");
+ goto out;
}
- IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
- scancode, toggle);
+
+ IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
+ protocol, scancode, toggle);
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
goto out;
}
- rc_keydown(dev, scancode, toggle);
+ rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index eb715f04dc27..ad1dc6ae21fc 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
u32 scancode;
u8 address, command, not_command;
- if (!rc_protocols_enabled(dev, RC_BIT_SANYO))
+ if (!(dev->enabled_protocols & RC_BIT_SANYO))
return 0;
if (!is_timing_event(ev)) {
@@ -167,7 +167,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
scancode = address << 8 | command;
IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, RC_TYPE_SANYO, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index 66d20394ceaa..b7acdbae8159 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -48,7 +48,7 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct sharp_dec *data = &dev->raw->sharp;
u32 msg, echo, address, command, scancode;
- if (!rc_protocols_enabled(dev, RC_BIT_SHARP))
+ if (!(dev->enabled_protocols & RC_BIT_SHARP))
return 0;
if (!is_timing_event(ev)) {
@@ -162,7 +162,7 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
scancode = address << 8 | command;
IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode);
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, RC_TYPE_SHARP, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index 599c19a73360..d12dc3da5931 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -42,11 +42,12 @@ enum sony_state {
static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sony_dec *data = &dev->raw->sony;
+ enum rc_type protocol;
u32 scancode;
u8 device, subdevice, function;
- if (!rc_protocols_enabled(dev, RC_BIT_SONY12 | RC_BIT_SONY15 |
- RC_BIT_SONY20))
+ if (!(dev->enabled_protocols &
+ (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
return 0;
if (!is_timing_event(ev)) {
@@ -124,31 +125,34 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
switch (data->count) {
case 12:
- if (!rc_protocols_enabled(dev, RC_BIT_SONY12)) {
+ if (!(dev->enabled_protocols & RC_BIT_SONY12)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits << 3) & 0xF8);
subdevice = 0;
function = bitrev8((data->bits >> 4) & 0xFE);
+ protocol = RC_TYPE_SONY12;
break;
case 15:
- if (!rc_protocols_enabled(dev, RC_BIT_SONY15)) {
+ if (!(dev->enabled_protocols & RC_BIT_SONY15)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits >> 0) & 0xFF);
subdevice = 0;
function = bitrev8((data->bits >> 7) & 0xFE);
+ protocol = RC_TYPE_SONY15;
break;
case 20:
- if (!rc_protocols_enabled(dev, RC_BIT_SONY20)) {
+ if (!(dev->enabled_protocols & RC_BIT_SONY20)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits >> 5) & 0xF8);
subdevice = bitrev8((data->bits >> 0) & 0xFF);
function = bitrev8((data->bits >> 12) & 0xFE);
+ protocol = RC_TYPE_SONY20;
break;
default:
IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
@@ -157,7 +161,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
scancode = device << 16 | subdevice << 8 | function;
IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, protocol, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c
new file mode 100644
index 000000000000..1017d4816e8d
--- /dev/null
+++ b/drivers/media/rc/ir-xmp-decoder.c
@@ -0,0 +1,225 @@
+/* ir-xmp-decoder.c - handle XMP IR Pulse/Space protocol
+ *
+ * Copyright (C) 2014 by Marcel Mol
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * - Based on info from http://www.hifi-remote.com
+ * - Ignore Toggle=9 frames
+ * - Ignore XMP-1 XMP-2 difference, always store 16 bit OBC
+ */
+
+#include <linux/bitrev.h>
+#include <linux/module.h>
+#include "rc-core-priv.h"
+
+#define XMP_UNIT 136000 /* ns */
+#define XMP_LEADER 210000 /* ns */
+#define XMP_NIBBLE_PREFIX 760000 /* ns */
+#define XMP_HALFFRAME_SPACE 13800000 /* ns */
+#define XMP_TRAILER_SPACE 20000000 /* should be 80ms but not all dureation supliers can go that high */
+
+enum xmp_state {
+ STATE_INACTIVE,
+ STATE_LEADER_PULSE,
+ STATE_NIBBLE_SPACE,
+};
+
+/**
+ * ir_xmp_decode() - Decode one XMP pulse or space
+ * @dev: the struct rc_dev descriptor of the device
+ * @duration: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+ struct xmp_dec *data = &dev->raw->xmp;
+
+ if (!(dev->enabled_protocols & RC_BIT_XMP))
+ return 0;
+
+ if (!is_timing_event(ev)) {
+ if (ev.reset)
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ IR_dprintk(2, "XMP decode started at state %d %d (%uus %s)\n",
+ data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
+
+ switch (data->state) {
+
+ case STATE_INACTIVE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2)) {
+ data->count = 0;
+ data->state = STATE_NIBBLE_SPACE;
+ }
+
+ return 0;
+
+ case STATE_LEADER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2))
+ data->state = STATE_NIBBLE_SPACE;
+
+ return 0;
+
+ case STATE_NIBBLE_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (geq_margin(ev.duration, XMP_TRAILER_SPACE, XMP_NIBBLE_PREFIX)) {
+ int divider, i;
+ u8 addr, subaddr, subaddr2, toggle, oem, obc1, obc2, sum1, sum2;
+ u32 *n;
+ u32 scancode;
+
+ if (data->count != 16) {
+ IR_dprintk(2, "received TRAILER period at index %d: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ n = data->durations;
+ /*
+ * the 4th nibble should be 15 so base the divider on this
+ * to transform durations into nibbles. Substract 2000 from
+ * the divider to compensate for fluctuations in the signal
+ */
+ divider = (n[3] - XMP_NIBBLE_PREFIX) / 15 - 2000;
+ if (divider < 50) {
+ IR_dprintk(2, "divider to small %d.\n", divider);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ /* convert to nibbles and do some sanity checks */
+ for (i = 0; i < 16; i++)
+ n[i] = (n[i] - XMP_NIBBLE_PREFIX) / divider;
+ sum1 = (15 + n[0] + n[1] + n[2] + n[3] +
+ n[4] + n[5] + n[6] + n[7]) % 16;
+ sum2 = (15 + n[8] + n[9] + n[10] + n[11] +
+ n[12] + n[13] + n[14] + n[15]) % 16;
+
+ if (sum1 != 15 || sum2 != 15) {
+ IR_dprintk(2, "checksum errors sum1=0x%X sum2=0x%X\n",
+ sum1, sum2);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ subaddr = n[0] << 4 | n[2];
+ subaddr2 = n[8] << 4 | n[11];
+ oem = n[4] << 4 | n[5];
+ addr = n[6] << 4 | n[7];
+ toggle = n[10];
+ obc1 = n[12] << 4 | n[13];
+ obc2 = n[14] << 4 | n[15];
+ if (subaddr != subaddr2) {
+ IR_dprintk(2, "subaddress nibbles mismatch 0x%02X != 0x%02X\n",
+ subaddr, subaddr2);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+ if (oem != 0x44)
+ IR_dprintk(1, "Warning: OEM nibbles 0x%02X. Expected 0x44\n",
+ oem);
+
+ scancode = addr << 24 | subaddr << 16 |
+ obc1 << 8 | obc2;
+ IR_dprintk(1, "XMP scancode 0x%06x\n", scancode);
+
+ if (toggle == 0) {
+ rc_keydown(dev, RC_TYPE_XMP, scancode, 0);
+ } else {
+ rc_repeat(dev);
+ IR_dprintk(1, "Repeat last key\n");
+ }
+ data->state = STATE_INACTIVE;
+
+ return 0;
+
+ } else if (geq_margin(ev.duration, XMP_HALFFRAME_SPACE, XMP_NIBBLE_PREFIX)) {
+ /* Expect 8 or 16 nibble pulses. 16 in case of 'final' frame */
+ if (data->count == 16) {
+ IR_dprintk(2, "received half frame pulse at index %d. Probably a final frame key-up event: %u\n",
+ data->count, ev.duration);
+ /*
+ * TODO: for now go back to half frame position
+ * so trailer can be found and key press
+ * can be handled.
+ */
+ data->count = 8;
+ }
+
+ else if (data->count != 8)
+ IR_dprintk(2, "received half frame pulse at index %d: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_LEADER_PULSE;
+
+ return 0;
+
+ } else if (geq_margin(ev.duration, XMP_NIBBLE_PREFIX, XMP_UNIT)) {
+ /* store nibble raw data, decode after trailer */
+ if (data->count == 16) {
+ IR_dprintk(2, "to many pulses (%d) ignoring: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+ data->durations[data->count] = ev.duration;
+ data->count++;
+ data->state = STATE_LEADER_PULSE;
+
+ return 0;
+
+ }
+
+ break;
+ }
+
+ IR_dprintk(1, "XMP decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static struct ir_raw_handler xmp_handler = {
+ .protocols = RC_BIT_XMP,
+ .decode = ir_xmp_decode,
+};
+
+static int __init ir_xmp_decode_init(void)
+{
+ ir_raw_handler_register(&xmp_handler);
+
+ printk(KERN_INFO "IR XMP protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_xmp_decode_exit(void)
+{
+ ir_raw_handler_unregister(&xmp_handler);
+}
+
+module_init(ir_xmp_decode_init);
+module_exit(ir_xmp_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marcel Mol <marcel@mesa.nl>");
+MODULE_AUTHOR("MESA Consulting (http://www.mesa.nl)");
+MODULE_DESCRIPTION("XMP IR protocol decoder");
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ab24cc6d3655..447fe35862dc 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
/* set up ir-core props */
rdev->priv = itdev;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = ite_open;
rdev->close = ite_close;
rdev->s_idle = ite_s_idle;
@@ -1709,12 +1709,12 @@ static struct pnp_driver ite_driver = {
.shutdown = ite_shutdown,
};
-static int ite_init(void)
+static int __init ite_init(void)
{
return pnp_register_driver(&ite_driver);
}
-static void ite_exit(void)
+static void __exit ite_exit(void)
{
pnp_unregister_driver(&ite_driver);
}
diff --git a/drivers/media/rc/keymaps/rc-ati-x10.c b/drivers/media/rc/keymaps/rc-ati-x10.c
index 81506440eded..4bdc709ec54d 100644
--- a/drivers/media/rc/keymaps/rc-ati-x10.c
+++ b/drivers/media/rc/keymaps/rc-ati-x10.c
@@ -26,7 +26,42 @@
#include <linux/module.h>
#include <media/rc-map.h>
+/*
+ * Intended usage comments below are from vendor-supplied
+ * Source: ATI REMOTE WONDER™ Installation Guide
+ * http://www2.ati.com/manuals/remctrl.pdf
+ *
+ * Scancodes were in strict left-right, top-bottom order on the
+ * original ATI Remote Wonder, but were moved on later models.
+ *
+ * Keys A-F are intended to be user-programmable.
+ */
+
static struct rc_map_table ati_x10[] = {
+ /* keyboard - Above the cursor pad */
+ { 0x00, KEY_A },
+ { 0x01, KEY_B },
+ { 0x02, KEY_POWER }, /* Power */
+
+ { 0x03, KEY_TV }, /* TV */
+ { 0x04, KEY_DVD }, /* DVD */
+ { 0x05, KEY_WWW }, /* WEB */
+ { 0x06, KEY_BOOKMARKS }, /* "book": Open Media Library */
+ { 0x07, KEY_EDIT }, /* "hand": Toggle left mouse button (grab) */
+
+ /* Mouse emulation pad goes here, handled by driver separately */
+
+ { 0x09, KEY_VOLUMEDOWN }, /* VOL + */
+ { 0x08, KEY_VOLUMEUP }, /* VOL - */
+ { 0x0a, KEY_MUTE }, /* MUTE */
+ { 0x0b, KEY_CHANNELUP }, /* CH + */
+ { 0x0c, KEY_CHANNELDOWN },/* CH - */
+
+ /*
+ * We could use KEY_NUMERIC_x for these, but the X11 protocol
+ * has problems with keycodes greater than 255, so avoid those high
+ * keycodes in default maps.
+ */
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
@@ -36,46 +71,45 @@ static struct rc_map_table ati_x10[] = {
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
+ { 0x16, KEY_MENU }, /* "menu": DVD root menu */
+ /* KEY_NUMERIC_STAR? */
{ 0x17, KEY_0 },
- { 0x00, KEY_A },
- { 0x01, KEY_B },
+ { 0x18, KEY_SETUP }, /* "check": DVD setup menu */
+ /* KEY_NUMERIC_POUND? */
+
+ /* DVD navigation buttons */
{ 0x19, KEY_C },
+ { 0x1a, KEY_UP }, /* up */
{ 0x1b, KEY_D },
- { 0x21, KEY_E },
- { 0x23, KEY_F },
- { 0x18, KEY_KPENTER }, /* "check" */
- { 0x16, KEY_MENU }, /* "menu" */
- { 0x02, KEY_POWER }, /* Power */
- { 0x03, KEY_TV }, /* TV */
- { 0x04, KEY_DVD }, /* DVD */
- { 0x05, KEY_WWW }, /* WEB */
- { 0x06, KEY_BOOKMARKS }, /* "book" */
- { 0x07, KEY_EDIT }, /* "hand" */
- { 0x1c, KEY_COFFEE }, /* "timer" */
- { 0x20, KEY_FRONT }, /* "max" */
+ { 0x1c, KEY_PROPS }, /* "timer" Should be Data On Screen */
+ /* Symbol is "circle nailed to box" */
{ 0x1d, KEY_LEFT }, /* left */
+ { 0x1e, KEY_OK }, /* "OK" */
{ 0x1f, KEY_RIGHT }, /* right */
+ { 0x20, KEY_SCREEN }, /* "max" (X11 warning: 0x177) */
+ /* Should be AC View Toggle, but
+ that's not in <input/input.h>.
+ KEY_ZOOM (0x174)? */
+ { 0x21, KEY_E },
{ 0x22, KEY_DOWN }, /* down */
- { 0x1a, KEY_UP }, /* up */
- { 0x1e, KEY_OK }, /* "OK" */
- { 0x09, KEY_VOLUMEDOWN }, /* VOL + */
- { 0x08, KEY_VOLUMEUP }, /* VOL - */
- { 0x0a, KEY_MUTE }, /* MUTE */
- { 0x0b, KEY_CHANNELUP }, /* CH + */
- { 0x0c, KEY_CHANNELDOWN },/* CH - */
+ { 0x23, KEY_F },
+ /* Play/stop/pause buttons */
+ { 0x24, KEY_REWIND }, /* (<<) Rewind */
+ { 0x25, KEY_PLAY }, /* ( >) Play (KEY_PLAYCD?) */
+ { 0x26, KEY_FASTFORWARD }, /* (>>) Fast forward */
+
{ 0x27, KEY_RECORD }, /* ( o) red */
- { 0x25, KEY_PLAY }, /* ( >) */
- { 0x24, KEY_REWIND }, /* (<<) */
- { 0x26, KEY_FORWARD }, /* (>>) */
- { 0x28, KEY_STOP }, /* ([]) */
- { 0x29, KEY_PAUSE }, /* ('') */
- { 0x2b, KEY_PREVIOUS }, /* (<-) */
+ { 0x28, KEY_STOPCD }, /* ([]) Stop (KEY_STOP is something else!) */
+ { 0x29, KEY_PAUSE }, /* ('') Pause (KEY_PAUSECD?) */
+
+ /* Extra keys, not on the original ATI remote */
{ 0x2a, KEY_NEXT }, /* (>+) */
- { 0x2d, KEY_INFO }, /* PLAYING */
+ { 0x2b, KEY_PREVIOUS }, /* (<-) */
+ { 0x2d, KEY_INFO }, /* PLAYING (X11 warning: 0x166) */
{ 0x2e, KEY_HOME }, /* TOP */
{ 0x2f, KEY_END }, /* END */
- { 0x30, KEY_SELECT }, /* SELECT */
+ { 0x30, KEY_SELECT }, /* SELECT (X11 warning: 0x161) */
};
static struct rc_map_list ati_x10_map = {
diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
index d6519f8ac95a..520a96f2ff86 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -30,8 +30,8 @@ static struct rc_map_table behold[] = {
/* 0x1c 0x12 *
* TV/FM POWER *
* */
- { 0x6b861c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
- { 0x6b8612, KEY_POWER },
+ { 0x866b1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
+ { 0x866b12, KEY_POWER },
/* 0x01 0x02 0x03 *
* 1 2 3 *
@@ -42,28 +42,28 @@ static struct rc_map_table behold[] = {
* 0x07 0x08 0x09 *
* 7 8 9 *
* */
- { 0x6b8601, KEY_1 },
- { 0x6b8602, KEY_2 },
- { 0x6b8603, KEY_3 },
- { 0x6b8604, KEY_4 },
- { 0x6b8605, KEY_5 },
- { 0x6b8606, KEY_6 },
- { 0x6b8607, KEY_7 },
- { 0x6b8608, KEY_8 },
- { 0x6b8609, KEY_9 },
+ { 0x866b01, KEY_1 },
+ { 0x866b02, KEY_2 },
+ { 0x866b03, KEY_3 },
+ { 0x866b04, KEY_4 },
+ { 0x866b05, KEY_5 },
+ { 0x866b06, KEY_6 },
+ { 0x866b07, KEY_7 },
+ { 0x866b08, KEY_8 },
+ { 0x866b09, KEY_9 },
/* 0x0a 0x00 0x17 *
* RECALL 0 MODE *
* */
- { 0x6b860a, KEY_AGAIN },
- { 0x6b8600, KEY_0 },
- { 0x6b8617, KEY_MODE },
+ { 0x866b0a, KEY_AGAIN },
+ { 0x866b00, KEY_0 },
+ { 0x866b17, KEY_MODE },
/* 0x14 0x10 *
* ASPECT FULLSCREEN *
* */
- { 0x6b8614, KEY_SCREEN },
- { 0x6b8610, KEY_ZOOM },
+ { 0x866b14, KEY_SCREEN },
+ { 0x866b10, KEY_ZOOM },
/* 0x0b *
* Up *
@@ -74,17 +74,17 @@ static struct rc_map_table behold[] = {
* 0x015 *
* Down *
* */
- { 0x6b860b, KEY_CHANNELUP },
- { 0x6b8618, KEY_VOLUMEDOWN },
- { 0x6b8616, KEY_OK }, /* XXX KEY_ENTER */
- { 0x6b860c, KEY_VOLUMEUP },
- { 0x6b8615, KEY_CHANNELDOWN },
+ { 0x866b0b, KEY_CHANNELUP },
+ { 0x866b18, KEY_VOLUMEDOWN },
+ { 0x866b16, KEY_OK }, /* XXX KEY_ENTER */
+ { 0x866b0c, KEY_VOLUMEUP },
+ { 0x866b15, KEY_CHANNELDOWN },
/* 0x11 0x0d *
* MUTE INFO *
* */
- { 0x6b8611, KEY_MUTE },
- { 0x6b860d, KEY_INFO },
+ { 0x866b11, KEY_MUTE },
+ { 0x866b0d, KEY_INFO },
/* 0x0f 0x1b 0x1a *
* RECORD PLAY/PAUSE STOP *
@@ -93,26 +93,26 @@ static struct rc_map_table behold[] = {
*TELETEXT AUDIO SOURCE *
* RED YELLOW *
* */
- { 0x6b860f, KEY_RECORD },
- { 0x6b861b, KEY_PLAYPAUSE },
- { 0x6b861a, KEY_STOP },
- { 0x6b860e, KEY_TEXT },
- { 0x6b861f, KEY_RED }, /*XXX KEY_AUDIO */
- { 0x6b861e, KEY_VIDEO },
+ { 0x866b0f, KEY_RECORD },
+ { 0x866b1b, KEY_PLAYPAUSE },
+ { 0x866b1a, KEY_STOP },
+ { 0x866b0e, KEY_TEXT },
+ { 0x866b1f, KEY_RED }, /*XXX KEY_AUDIO */
+ { 0x866b1e, KEY_VIDEO },
/* 0x1d 0x13 0x19 *
* SLEEP PREVIEW DVB *
* GREEN BLUE *
* */
- { 0x6b861d, KEY_SLEEP },
- { 0x6b8613, KEY_GREEN },
- { 0x6b8619, KEY_BLUE }, /* XXX KEY_SAT */
+ { 0x866b1d, KEY_SLEEP },
+ { 0x866b13, KEY_GREEN },
+ { 0x866b19, KEY_BLUE }, /* XXX KEY_SAT */
/* 0x58 0x5c *
* FREEZE SNAPSHOT *
* */
- { 0x6b8658, KEY_SLOW },
- { 0x6b865c, KEY_CAMERA },
+ { 0x866b58, KEY_SLOW },
+ { 0x866b5c, KEY_CAMERA },
};
diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c
index 8ec881adb7cf..4c50f33c7c41 100644
--- a/drivers/media/rc/keymaps/rc-nebula.c
+++ b/drivers/media/rc/keymaps/rc-nebula.c
@@ -14,68 +14,68 @@
#include <linux/module.h>
static struct rc_map_table nebula[] = {
- { 0x00, KEY_0 },
- { 0x01, KEY_1 },
- { 0x02, KEY_2 },
- { 0x03, KEY_3 },
- { 0x04, KEY_4 },
- { 0x05, KEY_5 },
- { 0x06, KEY_6 },
- { 0x07, KEY_7 },
- { 0x08, KEY_8 },
- { 0x09, KEY_9 },
- { 0x0a, KEY_TV },
- { 0x0b, KEY_AUX },
- { 0x0c, KEY_DVD },
- { 0x0d, KEY_POWER },
- { 0x0e, KEY_CAMERA }, /* labelled 'Picture' */
- { 0x0f, KEY_AUDIO },
- { 0x10, KEY_INFO },
- { 0x11, KEY_F13 }, /* 16:9 */
- { 0x12, KEY_F14 }, /* 14:9 */
- { 0x13, KEY_EPG },
- { 0x14, KEY_EXIT },
- { 0x15, KEY_MENU },
- { 0x16, KEY_UP },
- { 0x17, KEY_DOWN },
- { 0x18, KEY_LEFT },
- { 0x19, KEY_RIGHT },
- { 0x1a, KEY_ENTER },
- { 0x1b, KEY_CHANNELUP },
- { 0x1c, KEY_CHANNELDOWN },
- { 0x1d, KEY_VOLUMEUP },
- { 0x1e, KEY_VOLUMEDOWN },
- { 0x1f, KEY_RED },
- { 0x20, KEY_GREEN },
- { 0x21, KEY_YELLOW },
- { 0x22, KEY_BLUE },
- { 0x23, KEY_SUBTITLE },
- { 0x24, KEY_F15 }, /* AD */
- { 0x25, KEY_TEXT },
- { 0x26, KEY_MUTE },
- { 0x27, KEY_REWIND },
- { 0x28, KEY_STOP },
- { 0x29, KEY_PLAY },
- { 0x2a, KEY_FASTFORWARD },
- { 0x2b, KEY_F16 }, /* chapter */
- { 0x2c, KEY_PAUSE },
- { 0x2d, KEY_PLAY },
- { 0x2e, KEY_RECORD },
- { 0x2f, KEY_F17 }, /* picture in picture */
- { 0x30, KEY_KPPLUS }, /* zoom in */
- { 0x31, KEY_KPMINUS }, /* zoom out */
- { 0x32, KEY_F18 }, /* capture */
- { 0x33, KEY_F19 }, /* web */
- { 0x34, KEY_EMAIL },
- { 0x35, KEY_PHONE },
- { 0x36, KEY_PC },
+ { 0x0000, KEY_0 },
+ { 0x0001, KEY_1 },
+ { 0x0002, KEY_2 },
+ { 0x0003, KEY_3 },
+ { 0x0004, KEY_4 },
+ { 0x0005, KEY_5 },
+ { 0x0006, KEY_6 },
+ { 0x0007, KEY_7 },
+ { 0x0008, KEY_8 },
+ { 0x0009, KEY_9 },
+ { 0x000a, KEY_TV },
+ { 0x000b, KEY_AUX },
+ { 0x000c, KEY_DVD },
+ { 0x000d, KEY_POWER },
+ { 0x000e, KEY_CAMERA }, /* labelled 'Picture' */
+ { 0x000f, KEY_AUDIO },
+ { 0x0010, KEY_INFO },
+ { 0x0011, KEY_F13 }, /* 16:9 */
+ { 0x0012, KEY_F14 }, /* 14:9 */
+ { 0x0013, KEY_EPG },
+ { 0x0014, KEY_EXIT },
+ { 0x0015, KEY_MENU },
+ { 0x0016, KEY_UP },
+ { 0x0017, KEY_DOWN },
+ { 0x0018, KEY_LEFT },
+ { 0x0019, KEY_RIGHT },
+ { 0x001a, KEY_ENTER },
+ { 0x001b, KEY_CHANNELUP },
+ { 0x001c, KEY_CHANNELDOWN },
+ { 0x001d, KEY_VOLUMEUP },
+ { 0x001e, KEY_VOLUMEDOWN },
+ { 0x001f, KEY_RED },
+ { 0x0020, KEY_GREEN },
+ { 0x0021, KEY_YELLOW },
+ { 0x0022, KEY_BLUE },
+ { 0x0023, KEY_SUBTITLE },
+ { 0x0024, KEY_F15 }, /* AD */
+ { 0x0025, KEY_TEXT },
+ { 0x0026, KEY_MUTE },
+ { 0x0027, KEY_REWIND },
+ { 0x0028, KEY_STOP },
+ { 0x0029, KEY_PLAY },
+ { 0x002a, KEY_FASTFORWARD },
+ { 0x002b, KEY_F16 }, /* chapter */
+ { 0x002c, KEY_PAUSE },
+ { 0x002d, KEY_PLAY },
+ { 0x002e, KEY_RECORD },
+ { 0x002f, KEY_F17 }, /* picture in picture */
+ { 0x0030, KEY_KPPLUS }, /* zoom in */
+ { 0x0031, KEY_KPMINUS }, /* zoom out */
+ { 0x0032, KEY_F18 }, /* capture */
+ { 0x0033, KEY_F19 }, /* web */
+ { 0x0034, KEY_EMAIL },
+ { 0x0035, KEY_PHONE },
+ { 0x0036, KEY_PC },
};
static struct rc_map_list nebula_map = {
.map = {
.scan = nebula,
.size = ARRAY_SIZE(nebula),
- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
+ .rc_type = RC_TYPE_RC5,
.name = RC_MAP_NEBULA,
}
};
diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
index f9a07578d985..23c061174ed7 100644
--- a/drivers/media/rc/keymaps/rc-streamzap.c
+++ b/drivers/media/rc/keymaps/rc-streamzap.c
@@ -15,9 +15,7 @@
static struct rc_map_table streamzap[] = {
/*
* The Streamzap remote is almost, but not quite, RC-5, as it has an extra
- * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
- * an additional RC-5-sz decoder is being deployed to support it, but it
- * may be possible to merge it back with the standard RC-5 decoder.
+ * bit in it.
*/
{ 0x28c0, KEY_NUMERIC_0 },
{ 0x28c1, KEY_NUMERIC_1 },
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index d5c1df3c9db1..45b0894288e5 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -187,6 +187,7 @@
#define VENDOR_CONEXANT 0x0572
#define VENDOR_TWISTEDMELON 0x2596
#define VENDOR_HAUPPAUGE 0x2040
+#define VENDOR_PCTV 0x2013
enum mceusb_model_type {
MCE_GEN2 = 0, /* Most boards */
@@ -240,7 +241,6 @@ static const struct mceusb_model mceusb_model[] = {
* remotes, but we should have something handy,
* to allow testing it
*/
- .rc_map = RC_MAP_HAUPPAUGE,
.name = "Conexant Hybrid TV (cx231xx) MCE IR",
},
[CX_HYBRID_TV] = {
@@ -248,7 +248,6 @@ static const struct mceusb_model mceusb_model[] = {
.name = "Conexant Hybrid TV (cx231xx) MCE IR",
},
[HAUPPAUGE_CX_HYBRID_TV] = {
- .rc_map = RC_MAP_HAUPPAUGE,
.no_tx = 1, /* eeprom says it has no tx */
.name = "Conexant Hybrid TV (cx231xx) MCE IR no TX",
},
@@ -396,6 +395,13 @@ static struct usb_device_id mceusb_dev_table[] = {
/* Hauppauge WINTV-HVR-HVR 930C-HD - based on cx231xx */
{ USB_DEVICE(VENDOR_HAUPPAUGE, 0xb130),
.driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_HAUPPAUGE, 0xb131),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_PCTV, 0x0259),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_PCTV, 0x025e),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+
/* Terminating entry */
{ }
};
@@ -1192,8 +1198,10 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
}
-static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
+static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir,
+ struct usb_interface *intf)
{
+ struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
struct device *dev = ir->dev;
struct rc_dev *rc;
int ret;
@@ -1219,7 +1227,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->dev.parent = dev;
rc->priv = ir;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->timeout = MS_TO_NS(100);
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
@@ -1227,8 +1235,19 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->tx_ir = mceusb_tx_ir;
}
rc->driver_name = DRIVER_NAME;
- rc->map_name = mceusb_model[ir->model].rc_map ?
- mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE;
+
+ switch (le16_to_cpu(udev->descriptor.idVendor)) {
+ case VENDOR_HAUPPAUGE:
+ rc->map_name = RC_MAP_HAUPPAUGE;
+ break;
+ case VENDOR_PCTV:
+ rc->map_name = RC_MAP_PINNACLE_PCTV_HD;
+ break;
+ default:
+ rc->map_name = RC_MAP_RC6_MCE;
+ }
+ if (mceusb_model[ir->model].rc_map)
+ rc->map_name = mceusb_model[ir->model].rc_map;
ret = rc_register_device(rc);
if (ret < 0) {
@@ -1343,7 +1362,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
snprintf(name + strlen(name), sizeof(name) - strlen(name),
" %s", buf);
- ir->rc = mceusb_init_rc_dev(ir);
+ ir->rc = mceusb_init_rc_dev(ir, intf);
if (!ir->rc)
goto rc_dev_fail;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index d244e1a83f43..7f4fd859bba5 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1044,7 +1044,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
/* Set up the rc device */
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
@@ -1221,12 +1221,12 @@ static struct pnp_driver nvt_driver = {
.shutdown = nvt_shutdown,
};
-static int nvt_init(void)
+static int __init nvt_init(void)
{
return pnp_register_driver(&nvt_driver);
}
-static void nvt_exit(void)
+static void __exit nvt_exit(void)
{
pnp_unregister_driver(&nvt_driver);
}
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index da536c93c978..b68d4f762734 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -54,7 +54,7 @@ struct ir_raw_event_ctrl {
int state;
u32 bits;
unsigned count;
- unsigned wanted_bits;
+ bool is_rc5x;
} rc5;
struct rc6_dec {
int state;
@@ -77,12 +77,6 @@ struct ir_raw_event_ctrl {
bool first;
bool toggle;
} jvc;
- struct rc5_sz_dec {
- int state;
- u32 bits;
- unsigned count;
- unsigned wanted_bits;
- } rc5_sz;
struct sanyo_dec {
int state;
unsigned count;
@@ -116,6 +110,11 @@ struct ir_raw_event_ctrl {
bool send_timeout_reports;
} lirc;
+ struct xmp_dec {
+ int state;
+ unsigned count;
+ u32 durations[16];
+ } xmp;
};
/* macros for IR decoders */
@@ -231,5 +230,12 @@ static inline void load_mce_kbd_decode(void) { }
static inline void load_lirc_codec(void) { }
#endif
+/* from ir-xmp-decoder.c */
+#ifdef CONFIG_IR_XMP_DECODER_MODULE
+#define load_xmp_decode() request_module_nowait("ir-xmp-decoder")
+#else
+static inline void load_xmp_decode(void) { }
+#endif
+
#endif /* _RC_CORE_PRIV */
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 763c9d131d0f..e8fff2add265 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -1,4 +1,4 @@
-/* ir-raw.c - handle IR pulse/space events
+/* rc-ir-raw.c - handle IR pulse/space events
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
*
@@ -240,6 +240,12 @@ ir_raw_get_allowed_protocols(void)
return protocols;
}
+static int change_protocol(struct rc_dev *dev, u64 *rc_type)
+{
+ /* the caller will update dev->enabled_protocols */
+ return 0;
+}
+
/*
* Used to (un)register raw event clients
*/
@@ -256,7 +262,8 @@ int ir_raw_event_register(struct rc_dev *dev)
return -ENOMEM;
dev->raw->dev = dev;
- rc_set_enabled_protocols(dev, ~0);
+ dev->enabled_protocols = ~0;
+ dev->change_protocol = change_protocol;
rc = kfifo_alloc(&dev->raw->kfifo,
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
GFP_KERNEL);
@@ -355,6 +362,7 @@ void ir_raw_init(void)
load_sharp_decode();
load_mce_kbd_decode();
load_lirc_codec();
+ load_xmp_decode();
/* If needed, we may later add some init code. In this case,
it is needed to change the CONFIG_MODULE test at rc-core.h
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 0a88e0cf964f..63dace8198b0 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -195,7 +195,7 @@ static int __init loop_init(void)
rc->map_name = RC_MAP_EMPTY;
rc->priv = &loopdev;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->timeout = 100 * 1000 * 1000; /* 100 ms */
rc->min_timeout = 1;
rc->max_timeout = UINT_MAX;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 970b93d6f399..a7991c7d010a 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -285,8 +285,8 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev,
* IR tables from other remotes. So, we support specifying a mask to
* indicate the valid bits of the scancodes.
*/
- if (dev->scanmask)
- scancode &= dev->scanmask;
+ if (dev->scancode_mask)
+ scancode &= dev->scancode_mask;
/* First check if we already have a mapping for this ir command */
for (i = 0; i < rc_map->len; i++) {
@@ -623,6 +623,7 @@ EXPORT_SYMBOL_GPL(rc_repeat);
/**
* ir_do_keydown() - internal function to process a keypress
* @dev: the struct rc_dev descriptor of the device
+ * @protocol: the protocol of the keypress
* @scancode: the scancode of the keypress
* @keycode: the keycode of the keypress
* @toggle: the toggle value of the keypress
@@ -630,12 +631,13 @@ EXPORT_SYMBOL_GPL(rc_repeat);
* This function is used internally to register a keypress, it must be
* called with keylock held.
*/
-static void ir_do_keydown(struct rc_dev *dev, int scancode,
- u32 keycode, u8 toggle)
+static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
+ u32 scancode, u32 keycode, u8 toggle)
{
bool new_event = (!dev->keypressed ||
+ dev->last_protocol != protocol ||
dev->last_scancode != scancode ||
- dev->last_toggle != toggle);
+ dev->last_toggle != toggle);
if (new_event && dev->keypressed)
ir_do_keyup(dev, false);
@@ -645,13 +647,14 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode,
if (new_event && keycode != KEY_RESERVED) {
/* Register a keypress */
dev->keypressed = true;
+ dev->last_protocol = protocol;
dev->last_scancode = scancode;
dev->last_toggle = toggle;
dev->last_keycode = keycode;
IR_dprintk(1, "%s: key down event, "
- "key 0x%04x, scancode 0x%04x\n",
- dev->input_name, keycode, scancode);
+ "key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
+ dev->input_name, keycode, protocol, scancode);
input_report_key(dev->input_dev, keycode, 1);
led_trigger_event(led_feedback, LED_FULL);
@@ -663,20 +666,21 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode,
/**
* rc_keydown() - generates input event for a key press
* @dev: the struct rc_dev descriptor of the device
- * @scancode: the scancode that we're seeking
+ * @protocol: the protocol for the keypress
+ * @scancode: the scancode for the keypress
* @toggle: the toggle value (protocol dependent, if the protocol doesn't
* support toggle values, this should be set to zero)
*
* This routine is used to signal that a key has been pressed on the
* remote control.
*/
-void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown(struct rc_dev *dev, enum rc_type protocol, u32 scancode, u8 toggle)
{
unsigned long flags;
u32 keycode = rc_g_keycode_from_table(dev, scancode);
spin_lock_irqsave(&dev->keylock, flags);
- ir_do_keydown(dev, scancode, keycode, toggle);
+ ir_do_keydown(dev, protocol, scancode, keycode, toggle);
if (dev->keypressed) {
dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
@@ -690,20 +694,22 @@ EXPORT_SYMBOL_GPL(rc_keydown);
* rc_keydown_notimeout() - generates input event for a key press without
* an automatic keyup event at a later time
* @dev: the struct rc_dev descriptor of the device
- * @scancode: the scancode that we're seeking
+ * @protocol: the protocol for the keypress
+ * @scancode: the scancode for the keypress
* @toggle: the toggle value (protocol dependent, if the protocol doesn't
* support toggle values, this should be set to zero)
*
* This routine is used to signal that a key has been pressed on the
* remote control. The driver must manually call rc_keyup() at a later stage.
*/
-void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol,
+ u32 scancode, u8 toggle)
{
unsigned long flags;
u32 keycode = rc_g_keycode_from_table(dev, scancode);
spin_lock_irqsave(&dev->keylock, flags);
- ir_do_keydown(dev, scancode, keycode, toggle);
+ ir_do_keydown(dev, protocol, scancode, keycode, toggle);
spin_unlock_irqrestore(&dev->keylock, flags);
}
EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
@@ -794,6 +800,7 @@ static struct {
{ RC_BIT_SHARP, "sharp" },
{ RC_BIT_MCE_KBD, "mce_kbd" },
{ RC_BIT_LIRC, "lirc" },
+ { RC_BIT_XMP, "xmp" },
};
/**
@@ -824,7 +831,7 @@ struct rc_filter_attribute {
/**
* show_protocols() - shows the current/wakeup IR protocol(s)
* @device: the device descriptor
- * @mattr: the device attribute struct (unused)
+ * @mattr: the device attribute struct
* @buf: a pointer to the output buffer
*
* This routine is a callback routine for input read the IR protocol type(s).
@@ -850,20 +857,20 @@ static ssize_t show_protocols(struct device *device,
mutex_lock(&dev->lock);
- enabled = dev->enabled_protocols[fattr->type];
- if (dev->driver_type == RC_DRIVER_SCANCODE ||
- fattr->type == RC_FILTER_WAKEUP)
- allowed = dev->allowed_protocols[fattr->type];
- else if (dev->raw)
- allowed = ir_raw_get_allowed_protocols();
- else {
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ if (fattr->type == RC_FILTER_NORMAL) {
+ enabled = dev->enabled_protocols;
+ allowed = dev->allowed_protocols;
+ if (dev->raw && !allowed)
+ allowed = ir_raw_get_allowed_protocols();
+ } else {
+ enabled = dev->enabled_wakeup_protocols;
+ allowed = dev->allowed_wakeup_protocols;
}
- IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
- (long long)allowed,
- (long long)enabled);
+ mutex_unlock(&dev->lock);
+
+ IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
+ __func__, (long long)allowed, (long long)enabled);
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
if (allowed & enabled & proto_names[i].type)
@@ -879,62 +886,29 @@ static ssize_t show_protocols(struct device *device,
tmp--;
*tmp = '\n';
- mutex_unlock(&dev->lock);
-
return tmp + 1 - buf;
}
/**
- * store_protocols() - changes the current/wakeup IR protocol(s)
- * @device: the device descriptor
- * @mattr: the device attribute struct (unused)
- * @buf: a pointer to the input buffer
- * @len: length of the input buffer
+ * parse_protocol_change() - parses a protocol change request
+ * @protocols: pointer to the bitmask of current protocols
+ * @buf: pointer to the buffer with a list of changes
*
- * This routine is for changing the IR protocol type.
- * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
- * Writing "+proto" will add a protocol to the list of enabled protocols.
- * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "+proto" will add a protocol to the protocol mask.
+ * Writing "-proto" will remove a protocol from protocol mask.
* Writing "proto" will enable only "proto".
* Writing "none" will disable all protocols.
- * Returns -EINVAL if an invalid protocol combination or unknown protocol name
- * is used, otherwise @len.
- *
- * dev->lock is taken to guard against races between device
- * registration, store_protocols and show_protocols.
+ * Returns the number of changes performed or a negative error code.
*/
-static ssize_t store_protocols(struct device *device,
- struct device_attribute *mattr,
- const char *data,
- size_t len)
+static int parse_protocol_change(u64 *protocols, const char *buf)
{
- struct rc_dev *dev = to_rc_dev(device);
- struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
- bool enable, disable;
const char *tmp;
- u64 old_type, type;
+ unsigned count = 0;
+ bool enable, disable;
u64 mask;
- int rc, i, count = 0;
- ssize_t ret;
- int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
- int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
- struct rc_scancode_filter local_filter, *filter;
-
- /* Device is being removed */
- if (!dev)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
- IR_dprintk(1, "Protocol switching not supported\n");
- ret = -EINVAL;
- goto out;
- }
- old_type = dev->enabled_protocols[fattr->type];
- type = old_type;
+ int i;
- while ((tmp = strsep((char **) &data, " \n")) != NULL) {
+ while ((tmp = strsep((char **)&buf, " \n")) != NULL) {
if (!*tmp)
break;
@@ -960,76 +934,124 @@ static ssize_t store_protocols(struct device *device,
if (i == ARRAY_SIZE(proto_names)) {
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
count++;
if (enable)
- type |= mask;
+ *protocols |= mask;
else if (disable)
- type &= ~mask;
+ *protocols &= ~mask;
else
- type = mask;
+ *protocols = mask;
}
if (!count) {
IR_dprintk(1, "Protocol not specified\n");
- ret = -EINVAL;
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+/**
+ * store_protocols() - changes the current/wakeup IR protocol(s)
+ * @device: the device descriptor
+ * @mattr: the device attribute struct
+ * @buf: a pointer to the input buffer
+ * @len: length of the input buffer
+ *
+ * This routine is for changing the IR protocol type.
+ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
+ * See parse_protocol_change() for the valid commands.
+ * Returns @len on success or a negative error code.
+ *
+ * dev->lock is taken to guard against races between device
+ * registration, store_protocols and show_protocols.
+ */
+static ssize_t store_protocols(struct device *device,
+ struct device_attribute *mattr,
+ const char *buf, size_t len)
+{
+ struct rc_dev *dev = to_rc_dev(device);
+ struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
+ u64 *current_protocols;
+ int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
+ struct rc_scancode_filter *filter;
+ int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+ u64 old_protocols, new_protocols;
+ ssize_t rc;
+
+ /* Device is being removed */
+ if (!dev)
+ return -EINVAL;
+
+ if (fattr->type == RC_FILTER_NORMAL) {
+ IR_dprintk(1, "Normal protocol change requested\n");
+ current_protocols = &dev->enabled_protocols;
+ change_protocol = dev->change_protocol;
+ filter = &dev->scancode_filter;
+ set_filter = dev->s_filter;
+ } else {
+ IR_dprintk(1, "Wakeup protocol change requested\n");
+ current_protocols = &dev->enabled_wakeup_protocols;
+ change_protocol = dev->change_wakeup_protocol;
+ filter = &dev->scancode_wakeup_filter;
+ set_filter = dev->s_wakeup_filter;
+ }
+
+ if (!change_protocol) {
+ IR_dprintk(1, "Protocol switching not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+
+ old_protocols = *current_protocols;
+ new_protocols = old_protocols;
+ rc = parse_protocol_change(&new_protocols, buf);
+ if (rc < 0)
+ goto out;
+
+ rc = change_protocol(dev, &new_protocols);
+ if (rc < 0) {
+ IR_dprintk(1, "Error setting protocols to 0x%llx\n",
+ (long long)new_protocols);
goto out;
}
- change_protocol = (fattr->type == RC_FILTER_NORMAL)
- ? dev->change_protocol : dev->change_wakeup_protocol;
- if (change_protocol) {
- rc = change_protocol(dev, &type);
- if (rc < 0) {
- IR_dprintk(1, "Error setting protocols to 0x%llx\n",
- (long long)type);
- ret = -EINVAL;
- goto out;
- }
+ if (new_protocols == old_protocols) {
+ rc = len;
+ goto out;
}
- dev->enabled_protocols[fattr->type] = type;
- IR_dprintk(1, "Current protocol(s): 0x%llx\n",
- (long long)type);
+ *current_protocols = new_protocols;
+ IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);
/*
* If the protocol is changed the filter needs updating.
* Try setting the same filter with the new protocol (if any).
* Fall back to clearing the filter.
*/
- filter = &dev->scancode_filters[fattr->type];
- set_filter = (fattr->type == RC_FILTER_NORMAL)
- ? dev->s_filter : dev->s_wakeup_filter;
-
- if (set_filter && old_type != type && filter->mask) {
- local_filter = *filter;
- if (!type) {
- /* no protocol => clear filter */
- ret = -1;
- } else {
- /* hardware filtering => try setting, otherwise clear */
- ret = set_filter(dev, &local_filter);
- }
- if (ret < 0) {
- /* clear the filter */
- local_filter.data = 0;
- local_filter.mask = 0;
- set_filter(dev, &local_filter);
- }
+ if (set_filter && filter->mask) {
+ if (new_protocols)
+ rc = set_filter(dev, filter);
+ else
+ rc = -1;
- /* commit the new filter */
- *filter = local_filter;
+ if (rc < 0) {
+ filter->data = 0;
+ filter->mask = 0;
+ set_filter(dev, filter);
+ }
}
- ret = len;
+ rc = len;
out:
mutex_unlock(&dev->lock);
- return ret;
+ return rc;
}
/**
@@ -1055,20 +1077,23 @@ static ssize_t show_filter(struct device *device,
{
struct rc_dev *dev = to_rc_dev(device);
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
+ struct rc_scancode_filter *filter;
u32 val;
/* Device is being removed */
if (!dev)
return -EINVAL;
+ if (fattr->type == RC_FILTER_NORMAL)
+ filter = &dev->scancode_filter;
+ else
+ filter = &dev->scancode_wakeup_filter;
+
mutex_lock(&dev->lock);
- if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
- (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
- val = 0;
- else if (fattr->mask)
- val = dev->scancode_filters[fattr->type].mask;
+ if (fattr->mask)
+ val = filter->mask;
else
- val = dev->scancode_filters[fattr->type].data;
+ val = filter->data;
mutex_unlock(&dev->lock);
return sprintf(buf, "%#x\n", val);
@@ -1095,15 +1120,15 @@ static ssize_t show_filter(struct device *device,
*/
static ssize_t store_filter(struct device *device,
struct device_attribute *attr,
- const char *buf,
- size_t count)
+ const char *buf, size_t len)
{
struct rc_dev *dev = to_rc_dev(device);
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
- struct rc_scancode_filter local_filter, *filter;
+ struct rc_scancode_filter new_filter, *filter;
int ret;
unsigned long val;
int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+ u64 *enabled_protocols;
/* Device is being removed */
if (!dev)
@@ -1113,38 +1138,42 @@ static ssize_t store_filter(struct device *device,
if (ret < 0)
return ret;
- /* Can the scancode filter be set? */
- set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter :
- dev->s_wakeup_filter;
+ if (fattr->type == RC_FILTER_NORMAL) {
+ set_filter = dev->s_filter;
+ enabled_protocols = &dev->enabled_protocols;
+ filter = &dev->scancode_filter;
+ } else {
+ set_filter = dev->s_wakeup_filter;
+ enabled_protocols = &dev->enabled_wakeup_protocols;
+ filter = &dev->scancode_wakeup_filter;
+ }
+
if (!set_filter)
return -EINVAL;
mutex_lock(&dev->lock);
- /* Tell the driver about the new filter */
- filter = &dev->scancode_filters[fattr->type];
- local_filter = *filter;
+ new_filter = *filter;
if (fattr->mask)
- local_filter.mask = val;
+ new_filter.mask = val;
else
- local_filter.data = val;
+ new_filter.data = val;
- if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
+ if (!*enabled_protocols && val) {
/* refuse to set a filter unless a protocol is enabled */
ret = -EINVAL;
goto unlock;
}
- ret = set_filter(dev, &local_filter);
+ ret = set_filter(dev, &new_filter);
if (ret < 0)
goto unlock;
- /* Success, commit the new filter */
- *filter = local_filter;
+ *filter = new_filter;
unlock:
mutex_unlock(&dev->lock);
- return (ret < 0) ? ret : count;
+ return (ret < 0) ? ret : len;
}
static void rc_dev_release(struct device *device)
@@ -1315,7 +1344,7 @@ int rc_register_device(struct rc_dev *dev)
dev->dev.groups = dev->sysfs_groups;
dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp;
if (dev->s_filter)
- dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
+ dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
if (dev->s_wakeup_filter)
dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
if (dev->change_wakeup_protocol)
@@ -1395,7 +1424,7 @@ int rc_register_device(struct rc_dev *dev)
rc = dev->change_protocol(dev, &rc_type);
if (rc < 0)
goto out_raw;
- dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type;
+ dev->enabled_protocols = rc_type;
}
mutex_unlock(&dev->lock);
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 79abbc8d9600..795b394a5d84 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -878,7 +878,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
rc->dev.parent = dev;
rc->priv = rr3;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->timeout = US_TO_NS(2750);
rc->tx_ir = redrat3_transmit_ir;
rc->s_tx_carrier = redrat3_set_tx_carrier;
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index 22e4c1f28ab4..5c151351afa4 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_device *pdev)
st_rc_hardware_init(rc_dev);
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
/* rx sampling rate is 10Mhz */
rdev->rx_resolution = 100;
rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index bd5e4ff9e0ba..80c4feeb01ea 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -63,13 +63,6 @@ MODULE_DEVICE_TABLE(usb, streamzap_table);
/* number of samples buffered */
#define SZ_BUF_LEN 128
-/* from ir-rc5-sz-decoder.c */
-#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
-#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
-#else
-#define load_rc5_sz_decode() {}
-#endif
-
enum StreamzapDecoderState {
PulseSpace,
FullPulse,
@@ -316,7 +309,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
rdev->dev.parent = dev;
rdev->priv = sz;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->driver_name = DRIVER_NAME;
rdev->map_name = RC_MAP_STREAMZAP;
@@ -452,9 +445,6 @@ static int streamzap_probe(struct usb_interface *intf,
dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
usbdev->bus->busnum, usbdev->devnum);
- /* Load the streamzap not-quite-rc5 decoder too */
- load_rc5_sz_decode();
-
return 0;
rc_dev_fail:
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
new file mode 100644
index 000000000000..bcee8e1a4e9e
--- /dev/null
+++ b/drivers/media/rc/sunxi-cir.c
@@ -0,0 +1,318 @@
+/*
+ * Driver for Allwinner sunXi IR controller
+ *
+ * Copyright (C) 2014 Alexsey Shestacov <wingrime@linux-sunxi.org>
+ * Copyright (C) 2014 Alexander Bersenev <bay@hackerdom.ru>
+ *
+ * Based on sun5i-ir.c:
+ * Copyright (C) 2007-2012 Daniel Wang
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <media/rc-core.h>
+
+#define SUNXI_IR_DEV "sunxi-ir"
+
+/* Registers */
+/* IR Control */
+#define SUNXI_IR_CTL_REG 0x00
+/* Global Enable */
+#define REG_CTL_GEN BIT(0)
+/* RX block enable */
+#define REG_CTL_RXEN BIT(1)
+/* CIR mode */
+#define REG_CTL_MD (BIT(4) | BIT(5))
+
+/* Rx Config */
+#define SUNXI_IR_RXCTL_REG 0x10
+/* Pulse Polarity Invert flag */
+#define REG_RXCTL_RPPI BIT(2)
+
+/* Rx Data */
+#define SUNXI_IR_RXFIFO_REG 0x20
+
+/* Rx Interrupt Enable */
+#define SUNXI_IR_RXINT_REG 0x2C
+/* Rx FIFO Overflow */
+#define REG_RXINT_ROI_EN BIT(0)
+/* Rx Packet End */
+#define REG_RXINT_RPEI_EN BIT(1)
+/* Rx FIFO Data Available */
+#define REG_RXINT_RAI_EN BIT(4)
+
+/* Rx FIFO available byte level */
+#define REG_RXINT_RAL(val) (((val) << 8) & (GENMASK(11, 8)))
+
+/* Rx Interrupt Status */
+#define SUNXI_IR_RXSTA_REG 0x30
+/* RX FIFO Get Available Counter */
+#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0)))
+/* Clear all interrupt status value */
+#define REG_RXSTA_CLEARALL 0xff
+
+/* IR Sample Config */
+#define SUNXI_IR_CIR_REG 0x34
+/* CIR_REG register noise threshold */
+#define REG_CIR_NTHR(val) (((val) << 2) & (GENMASK(7, 2)))
+/* CIR_REG register idle threshold */
+#define REG_CIR_ITHR(val) (((val) << 8) & (GENMASK(15, 8)))
+
+/* Hardware supported fifo size */
+#define SUNXI_IR_FIFO_SIZE 16
+/* How many messages in FIFO trigger IRQ */
+#define TRIGGER_LEVEL 8
+/* Required frequency for IR0 or IR1 clock in CIR mode */
+#define SUNXI_IR_BASE_CLK 8000000
+/* Frequency after IR internal divider */
+#define SUNXI_IR_CLK (SUNXI_IR_BASE_CLK / 64)
+/* Sample period in ns */
+#define SUNXI_IR_SAMPLE (1000000000ul / SUNXI_IR_CLK)
+/* Noise threshold in samples */
+#define SUNXI_IR_RXNOISE 1
+/* Idle Threshold in samples */
+#define SUNXI_IR_RXIDLE 20
+/* Time after which device stops sending data in ms */
+#define SUNXI_IR_TIMEOUT 120
+
+struct sunxi_ir {
+ spinlock_t ir_lock;
+ struct rc_dev *rc;
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+ struct clk *apb_clk;
+ const char *map_name;
+};
+
+static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
+{
+ unsigned long status;
+ unsigned char dt;
+ unsigned int cnt, rc;
+ struct sunxi_ir *ir = dev_id;
+ DEFINE_IR_RAW_EVENT(rawir);
+
+ spin_lock(&ir->ir_lock);
+
+ status = readl(ir->base + SUNXI_IR_RXSTA_REG);
+
+ /* clean all pending statuses */
+ writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ if (status & REG_RXINT_RAI_EN) {
+ /* How many messages in fifo */
+ rc = REG_RXSTA_GET_AC(status);
+ /* Sanity check */
+ rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc;
+ /* If we have data */
+ for (cnt = 0; cnt < rc; cnt++) {
+ /* for each bit in fifo */
+ dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
+ rawir.pulse = (dt & 0x80) != 0;
+ rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
+ ir_raw_event_store_with_filter(ir->rc, &rawir);
+ }
+ }
+
+ if (status & REG_RXINT_ROI_EN) {
+ ir_raw_event_reset(ir->rc);
+ } else if (status & REG_RXINT_RPEI_EN) {
+ ir_raw_event_set_idle(ir->rc, true);
+ ir_raw_event_handle(ir->rc);
+ }
+
+ spin_unlock(&ir->ir_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int sunxi_ir_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ unsigned long tmp = 0;
+
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node;
+ struct resource *res;
+ struct sunxi_ir *ir;
+
+ ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+
+ /* Clock */
+ ir->apb_clk = devm_clk_get(dev, "apb");
+ if (IS_ERR(ir->apb_clk)) {
+ dev_err(dev, "failed to get a apb clock.\n");
+ return PTR_ERR(ir->apb_clk);
+ }
+ ir->clk = devm_clk_get(dev, "ir");
+ if (IS_ERR(ir->clk)) {
+ dev_err(dev, "failed to get a ir clock.\n");
+ return PTR_ERR(ir->clk);
+ }
+
+ ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
+ if (ret) {
+ dev_err(dev, "set ir base clock failed!\n");
+ return ret;
+ }
+
+ if (clk_prepare_enable(ir->apb_clk)) {
+ dev_err(dev, "try to enable apb_ir_clk failed\n");
+ return -EINVAL;
+ }
+
+ if (clk_prepare_enable(ir->clk)) {
+ dev_err(dev, "try to enable ir_clk failed\n");
+ ret = -EINVAL;
+ goto exit_clkdisable_apb_clk;
+ }
+
+ /* IO */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ir->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ir->base)) {
+ dev_err(dev, "failed to map registers\n");
+ ret = PTR_ERR(ir->base);
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc = rc_allocate_device();
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ ret = -ENOMEM;
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc->priv = ir;
+ ir->rc->input_name = SUNXI_IR_DEV;
+ ir->rc->input_phys = "sunxi-ir/input0";
+ ir->rc->input_id.bustype = BUS_HOST;
+ ir->rc->input_id.vendor = 0x0001;
+ ir->rc->input_id.product = 0x0001;
+ ir->rc->input_id.version = 0x0100;
+ ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);
+ ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
+ ir->rc->dev.parent = dev;
+ ir->rc->driver_type = RC_DRIVER_IR_RAW;
+ ir->rc->allowed_protocols = RC_BIT_ALL;
+ ir->rc->rx_resolution = SUNXI_IR_SAMPLE;
+ ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
+ ir->rc->driver_name = SUNXI_IR_DEV;
+
+ ret = rc_register_device(ir->rc);
+ if (ret) {
+ dev_err(dev, "failed to register rc device\n");
+ goto exit_free_dev;
+ }
+
+ platform_set_drvdata(pdev, ir);
+
+ /* IRQ */
+ ir->irq = platform_get_irq(pdev, 0);
+ if (ir->irq < 0) {
+ dev_err(dev, "no irq resource\n");
+ ret = ir->irq;
+ goto exit_free_dev;
+ }
+
+ ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir);
+ if (ret) {
+ dev_err(dev, "failed request irq\n");
+ goto exit_free_dev;
+ }
+
+ /* Enable CIR Mode */
+ writel(REG_CTL_MD, ir->base+SUNXI_IR_CTL_REG);
+
+ /* Set noise threshold and idle threshold */
+ writel(REG_CIR_NTHR(SUNXI_IR_RXNOISE)|REG_CIR_ITHR(SUNXI_IR_RXIDLE),
+ ir->base + SUNXI_IR_CIR_REG);
+
+ /* Invert Input Signal */
+ writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG);
+
+ /* Clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ /*
+ * Enable IRQ on overflow, packet end, FIFO available with trigger
+ * level
+ */
+ writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN |
+ REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1),
+ ir->base + SUNXI_IR_RXINT_REG);
+
+ /* Enable IR Module */
+ tmp = readl(ir->base + SUNXI_IR_CTL_REG);
+ writel(tmp | REG_CTL_GEN | REG_CTL_RXEN, ir->base + SUNXI_IR_CTL_REG);
+
+ dev_info(dev, "initialized sunXi IR driver\n");
+ return 0;
+
+exit_free_dev:
+ rc_free_device(ir->rc);
+exit_clkdisable_clk:
+ clk_disable_unprepare(ir->clk);
+exit_clkdisable_apb_clk:
+ clk_disable_unprepare(ir->apb_clk);
+
+ return ret;
+}
+
+static int sunxi_ir_remove(struct platform_device *pdev)
+{
+ unsigned long flags;
+ struct sunxi_ir *ir = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ir->clk);
+ clk_disable_unprepare(ir->apb_clk);
+
+ spin_lock_irqsave(&ir->ir_lock, flags);
+ /* disable IR IRQ */
+ writel(0, ir->base + SUNXI_IR_RXINT_REG);
+ /* clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+ /* disable IR */
+ writel(0, ir->base + SUNXI_IR_CTL_REG);
+ spin_unlock_irqrestore(&ir->ir_lock, flags);
+
+ rc_unregister_device(ir->rc);
+ return 0;
+}
+
+static const struct of_device_id sunxi_ir_match[] = {
+ { .compatible = "allwinner,sun4i-a10-ir", },
+ {},
+};
+
+static struct platform_driver sunxi_ir_driver = {
+ .probe = sunxi_ir_probe,
+ .remove = sunxi_ir_remove,
+ .driver = {
+ .name = SUNXI_IR_DEV,
+ .owner = THIS_MODULE,
+ .of_match_table = sunxi_ir_match,
+ },
+};
+
+module_platform_driver(sunxi_ir_driver);
+
+MODULE_DESCRIPTION("Allwinner sunXi IR controller driver");
+MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index c5be38e2a2fe..bc214e2b3a36 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_interface *intf,
usb_to_input_id(tt->udev, &rc->input_id);
rc->dev.parent = &intf->dev;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->priv = tt;
rc->driver_name = DRIVER_NAME;
rc->map_name = RC_MAP_TT_1500;
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index a8b981f5ce2e..d839f73f6a05 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
data->dev->dev.parent = &device->dev;
data->dev->timeout = MS_TO_NS(100);
data->dev->rx_resolution = US_TO_NS(2);
- rc_set_allowed_protocols(data->dev, RC_BIT_ALL);
+ data->dev->allowed_protocols = RC_BIT_ALL;
err = rc_register_device(data->dev);
if (err)
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 22b6b8bb1d93..d79fd1ce5a18 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -1,7 +1,7 @@
# Analog TV tuners, auto-loaded via tuner.ko
config MEDIA_TUNER
tristate
- depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
+ depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT) && I2C
default y
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
@@ -16,7 +16,7 @@ config MEDIA_TUNER
menu "Customize TV tuners"
visible if !MEDIA_SUBDRV_AUTOSELECT
- depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
+ depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
config MEDIA_TUNER_SIMPLE
tristate "Simple tuner support"
@@ -71,6 +71,13 @@ config MEDIA_TUNER_TEA5767
help
Say Y here to include support for the Philips TEA5767 radio tuner.
+config MEDIA_TUNER_MSI001
+ tristate "Mirics MSi001"
+ depends on MEDIA_SUPPORT && SPI && VIDEO_V4L2
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ Mirics MSi001 silicon tuner driver.
+
config MEDIA_TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners"
depends on MEDIA_SUPPORT && I2C
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index a6ff0c628dfa..5591699755ba 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
+obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o
obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
diff --git a/drivers/staging/media/msi3101/msi001.c b/drivers/media/tuners/msi001.c
index bd0b93cb6c53..ee99e372c943 100644
--- a/drivers/staging/media/msi3101/msi001.c
+++ b/drivers/media/tuners/msi001.c
@@ -381,7 +381,7 @@ static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
int ret;
dev_dbg(&s->spi->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
__func__, ctrl->id, ctrl->name, ctrl->val,
ctrl->minimum, ctrl->maximum, ctrl->step);
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 96ccfebce7ca..a759742cae7b 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -1545,7 +1545,7 @@ static int r820t_imr_cross(struct r820t_priv *priv,
cross[i].value = rc;
if (cross[i].value < tmp.value)
- memcpy(&tmp, &cross[i], sizeof(tmp));
+ tmp = cross[i];
}
if ((tmp.phase_y & 0x1f) == 1) { /* y-direction */
@@ -2300,7 +2300,6 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
case 0:
/* memory allocation failure */
goto err_no_gate;
- break;
case 1:
/* new tuner instance */
priv->cfg = cfg;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index fa4cc7b880aa..6c53edb73a63 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -16,54 +16,58 @@
#include "si2157_priv.h"
+static const struct dvb_tuner_ops si2157_ops;
+
/* execute firmware command */
static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
{
int ret;
- u8 buf[1];
unsigned long timeout;
mutex_lock(&s->i2c_mutex);
- if (cmd->len) {
+ if (cmd->wlen) {
/* write cmd and args for firmware */
- ret = i2c_master_send(s->client, cmd->args, cmd->len);
+ ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
if (ret < 0) {
goto err_mutex_unlock;
- } else if (ret != cmd->len) {
+ } else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
goto err_mutex_unlock;
}
}
- /* wait cmd execution terminate */
- #define TIMEOUT 80
- timeout = jiffies + msecs_to_jiffies(TIMEOUT);
- while (!time_after(jiffies, timeout)) {
- ret = i2c_master_recv(s->client, buf, 1);
- if (ret < 0) {
- goto err_mutex_unlock;
- } else if (ret != 1) {
- ret = -EREMOTEIO;
- goto err_mutex_unlock;
+ if (cmd->rlen) {
+ /* wait cmd execution terminate */
+ #define TIMEOUT 80
+ timeout = jiffies + msecs_to_jiffies(TIMEOUT);
+ while (!time_after(jiffies, timeout)) {
+ ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
+ if (ret < 0) {
+ goto err_mutex_unlock;
+ } else if (ret != cmd->rlen) {
+ ret = -EREMOTEIO;
+ goto err_mutex_unlock;
+ }
+
+ /* firmware ready? */
+ if ((cmd->args[0] >> 7) & 0x01)
+ break;
}
- /* firmware ready? */
- if ((buf[0] >> 7) & 0x01)
- break;
- }
+ dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n",
+ __func__,
+ jiffies_to_msecs(jiffies) -
+ (jiffies_to_msecs(timeout) - TIMEOUT));
- dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", __func__,
- jiffies_to_msecs(jiffies) -
- (jiffies_to_msecs(timeout) - TIMEOUT));
-
- if (!((buf[0] >> 7) & 0x01)) {
- ret = -ETIMEDOUT;
- goto err_mutex_unlock;
- } else {
- ret = 0;
+ if (!((cmd->args[0] >> 7) & 0x01)) {
+ ret = -ETIMEDOUT;
+ goto err_mutex_unlock;
+ }
}
+ ret = 0;
+
err_mutex_unlock:
mutex_unlock(&s->i2c_mutex);
if (ret)
@@ -78,23 +82,133 @@ err:
static int si2157_init(struct dvb_frontend *fe)
{
struct si2157 *s = fe->tuner_priv;
+ int ret, len, remaining;
+ struct si2157_cmd cmd;
+ const struct firmware *fw = NULL;
+ u8 *fw_file;
+ unsigned int chip_id;
dev_dbg(&s->client->dev, "%s:\n", __func__);
+ /* configure? */
+ memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
+ cmd.wlen = 15;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
+ /* query chip revision */
+ memcpy(cmd.args, "\x02", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 13;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
+ chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+ cmd.args[4] << 0;
+
+ #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
+ #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
+
+ switch (chip_id) {
+ case SI2158_A20:
+ fw_file = SI2158_A20_FIRMWARE;
+ break;
+ case SI2157_A30:
+ goto skip_fw_download;
+ break;
+ default:
+ dev_err(&s->client->dev,
+ "%s: unkown chip version Si21%d-%c%c%c\n",
+ KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+ cmd.args[3], cmd.args[4]);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* cold state - try to download firmware */
+ dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
+ KBUILD_MODNAME, si2157_ops.info.name);
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, &s->client->dev);
+ if (ret) {
+ dev_err(&s->client->dev, "%s: firmware file '%s' not found\n",
+ KBUILD_MODNAME, fw_file);
+ goto err;
+ }
+
+ /* firmware should be n chunks of 17 bytes */
+ if (fw->size % 17 != 0) {
+ dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n",
+ KBUILD_MODNAME, fw_file);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
+ KBUILD_MODNAME, fw_file);
+
+ for (remaining = fw->size; remaining > 0; remaining -= 17) {
+ len = fw->data[fw->size - remaining];
+ memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
+ cmd.wlen = len;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret) {
+ dev_err(&s->client->dev,
+ "%s: firmware download failed=%d\n",
+ KBUILD_MODNAME, ret);
+ goto err;
+ }
+ }
+
+ release_firmware(fw);
+ fw = NULL;
+
+skip_fw_download:
+ /* reboot the tuner with new firmware? */
+ memcpy(cmd.args, "\x01\x01", 2);
+ cmd.wlen = 2;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
s->active = true;
return 0;
+err:
+ if (fw)
+ release_firmware(fw);
+
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2157_sleep(struct dvb_frontend *fe)
{
struct si2157 *s = fe->tuner_priv;
+ int ret;
+ struct si2157_cmd cmd;
dev_dbg(&s->client->dev, "%s:\n", __func__);
s->active = false;
+ memcpy(cmd.args, "\x13", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 0;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
return 0;
+err:
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2157_set_params(struct dvb_frontend *fe)
@@ -103,6 +217,7 @@ static int si2157_set_params(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
struct si2157_cmd cmd;
+ u8 bandwidth, delivery_system;
dev_dbg(&s->client->dev,
"%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
@@ -114,50 +229,46 @@ static int si2157_set_params(struct dvb_frontend *fe)
goto err;
}
- /* configure? */
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x00;
- cmd.args[2] = 0x0c;
- cmd.args[3] = 0x00;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x01;
- cmd.args[6] = 0x01;
- cmd.args[7] = 0x01;
- cmd.args[8] = 0x01;
- cmd.args[9] = 0x01;
- cmd.args[10] = 0x01;
- cmd.args[11] = 0x02;
- cmd.args[12] = 0x00;
- cmd.args[13] = 0x00;
- cmd.args[14] = 0x01;
- cmd.len = 15;
- ret = si2157_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- cmd.args[0] = 0x02;
- cmd.len = 1;
- ret = si2157_cmd_execute(s, &cmd);
- if (ret)
- goto err;
+ if (c->bandwidth_hz <= 6000000)
+ bandwidth = 0x06;
+ else if (c->bandwidth_hz <= 7000000)
+ bandwidth = 0x07;
+ else if (c->bandwidth_hz <= 8000000)
+ bandwidth = 0x08;
+ else
+ bandwidth = 0x0f;
+
+ switch (c->delivery_system) {
+ case SYS_DVBT:
+ case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
+ delivery_system = 0x20;
+ break;
+ case SYS_DVBC_ANNEX_A:
+ delivery_system = 0x30;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
- cmd.args[0] = 0x01;
- cmd.args[1] = 0x01;
- cmd.len = 2;
+ memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
+ cmd.args[4] = delivery_system | bandwidth;
+ if (s->inversion)
+ cmd.args[5] = 0x01;
+ cmd.wlen = 6;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
/* set frequency */
- cmd.args[0] = 0x41;
- cmd.args[1] = 0x00;
- cmd.args[2] = 0x00;
- cmd.args[3] = 0x00;
+ memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
cmd.args[4] = (c->frequency >> 0) & 0xff;
cmd.args[5] = (c->frequency >> 8) & 0xff;
cmd.args[6] = (c->frequency >> 16) & 0xff;
cmd.args[7] = (c->frequency >> 24) & 0xff;
- cmd.len = 8;
+ cmd.wlen = 8;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
@@ -168,9 +279,15 @@ err:
return ret;
}
-static const struct dvb_tuner_ops si2157_tuner_ops = {
+static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ *frequency = 5000000; /* default value of property 0x0706 */
+ return 0;
+}
+
+static const struct dvb_tuner_ops si2157_ops = {
.info = {
- .name = "Silicon Labs Si2157",
+ .name = "Silicon Labs Si2157/Si2158",
.frequency_min = 110000000,
.frequency_max = 862000000,
},
@@ -178,6 +295,7 @@ static const struct dvb_tuner_ops si2157_tuner_ops = {
.init = si2157_init,
.sleep = si2157_sleep,
.set_params = si2157_set_params,
+ .get_if_frequency = si2157_get_if_frequency,
};
static int si2157_probe(struct i2c_client *client,
@@ -198,22 +316,24 @@ static int si2157_probe(struct i2c_client *client,
s->client = client;
s->fe = cfg->fe;
+ s->inversion = cfg->inversion;
mutex_init(&s->i2c_mutex);
/* check if the tuner is there */
- cmd.len = 0;
+ cmd.wlen = 0;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
fe->tuner_priv = s;
- memcpy(&fe->ops.tuner_ops, &si2157_tuner_ops,
+ memcpy(&fe->ops.tuner_ops, &si2157_ops,
sizeof(struct dvb_tuner_ops));
i2c_set_clientdata(client, s);
dev_info(&s->client->dev,
- "%s: Silicon Labs Si2157 successfully attached\n",
+ "%s: Silicon Labs Si2157/Si2158 successfully attached\n",
KBUILD_MODNAME);
return 0;
err:
@@ -255,6 +375,7 @@ static struct i2c_driver si2157_driver = {
module_i2c_driver(si2157_driver);
-MODULE_DESCRIPTION("Silicon Labs Si2157 silicon tuner driver");
+MODULE_DESCRIPTION("Silicon Labs Si2157/Si2158 silicon tuner driver");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index f469a092b66b..6da4d5d1c817 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -29,6 +29,11 @@ struct si2157_config {
* frontend
*/
struct dvb_frontend *fe;
+
+ /*
+ * Spectral Inversion
+ */
+ bool inversion;
};
#endif
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index 6cc6c6fdab7a..3ddab5e6b500 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -17,6 +17,7 @@
#ifndef SI2157_PRIV_H
#define SI2157_PRIV_H
+#include <linux/firmware.h>
#include "si2157.h"
/* state struct */
@@ -25,13 +26,17 @@ struct si2157 {
struct i2c_client *client;
struct dvb_frontend *fe;
bool active;
+ bool inversion;
};
/* firmare command struct */
#define SI2157_ARGLEN 30
struct si2157_cmd {
u8 args[SI2157_ARGLEN];
- unsigned len;
+ unsigned wlen;
+ unsigned rlen;
};
+#define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw"
+
#endif
diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c
index 6ef93ee1fdcb..565eeebb3aeb 100644
--- a/drivers/media/tuners/tuner-xc2028.c
+++ b/drivers/media/tuners/tuner-xc2028.c
@@ -1489,7 +1489,6 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
case 0:
/* memory allocation failure */
goto fail;
- break;
case 1:
/* new tuner instance */
priv->ctrl.max_len = 13;
diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c
index 2018befabb5a..f9ab79e3432d 100644
--- a/drivers/media/tuners/xc4000.c
+++ b/drivers/media/tuners/xc4000.c
@@ -93,7 +93,7 @@ struct xc4000_priv {
struct firmware_description *firm;
int firm_size;
u32 if_khz;
- u32 freq_hz;
+ u32 freq_hz, freq_offset;
u32 bandwidth;
u8 video_standard;
u8 rf_mode;
@@ -116,6 +116,7 @@ struct xc4000_priv {
#define XC4000_AUDIO_STD_MONO 32
#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw"
+#define XC4000_DEFAULT_FIRMWARE_NEW "dvb-fe-xc4000-1.4.1.fw"
/* Misc Defines */
#define MAX_TV_STANDARD 24
@@ -730,13 +731,25 @@ static int xc4000_fwupload(struct dvb_frontend *fe)
char name[33];
const char *fname;
- if (firmware_name[0] != '\0')
+ if (firmware_name[0] != '\0') {
fname = firmware_name;
- else
- fname = XC4000_DEFAULT_FIRMWARE;
- dprintk(1, "Reading firmware %s\n", fname);
- rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
+ dprintk(1, "Reading custom firmware %s\n", fname);
+ rc = request_firmware(&fw, fname,
+ priv->i2c_props.adap->dev.parent);
+ } else {
+ fname = XC4000_DEFAULT_FIRMWARE_NEW;
+ dprintk(1, "Trying to read firmware %s\n", fname);
+ rc = request_firmware(&fw, fname,
+ priv->i2c_props.adap->dev.parent);
+ if (rc == -ENOENT) {
+ fname = XC4000_DEFAULT_FIRMWARE;
+ dprintk(1, "Trying to read firmware %s\n", fname);
+ rc = request_firmware(&fw, fname,
+ priv->i2c_props.adap->dev.parent);
+ }
+ }
+
if (rc < 0) {
if (rc == -ENOENT)
printk(KERN_ERR "Error: firmware %s not found.\n", fname);
@@ -746,6 +759,8 @@ static int xc4000_fwupload(struct dvb_frontend *fe)
return rc;
}
+ dprintk(1, "Loading Firmware: %s\n", fname);
+
p = fw->data;
endp = p + fw->size;
@@ -1157,14 +1172,14 @@ static int xc4000_set_params(struct dvb_frontend *fe)
case SYS_ATSC:
dprintk(1, "%s() VSB modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_AIR;
- priv->freq_hz = c->frequency - 1750000;
+ priv->freq_offset = 1750000;
priv->video_standard = XC4000_DTV6;
type = DTV6;
break;
case SYS_DVBC_ANNEX_B:
dprintk(1, "%s() QAM modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_CABLE;
- priv->freq_hz = c->frequency - 1750000;
+ priv->freq_offset = 1750000;
priv->video_standard = XC4000_DTV6;
type = DTV6;
break;
@@ -1173,23 +1188,23 @@ static int xc4000_set_params(struct dvb_frontend *fe)
dprintk(1, "%s() OFDM\n", __func__);
if (bw == 0) {
if (c->frequency < 400000000) {
- priv->freq_hz = c->frequency - 2250000;
+ priv->freq_offset = 2250000;
} else {
- priv->freq_hz = c->frequency - 2750000;
+ priv->freq_offset = 2750000;
}
priv->video_standard = XC4000_DTV7_8;
type = DTV78;
} else if (bw <= 6000000) {
priv->video_standard = XC4000_DTV6;
- priv->freq_hz = c->frequency - 1750000;
+ priv->freq_offset = 1750000;
type = DTV6;
} else if (bw <= 7000000) {
priv->video_standard = XC4000_DTV7;
- priv->freq_hz = c->frequency - 2250000;
+ priv->freq_offset = 2250000;
type = DTV7;
} else {
priv->video_standard = XC4000_DTV8;
- priv->freq_hz = c->frequency - 2750000;
+ priv->freq_offset = 2750000;
type = DTV8;
}
priv->rf_mode = XC_RF_MODE_AIR;
@@ -1200,6 +1215,8 @@ static int xc4000_set_params(struct dvb_frontend *fe)
goto fail;
}
+ priv->freq_hz = c->frequency - priv->freq_offset;
+
dprintk(1, "%s() frequency=%d (compensated)\n",
__func__, priv->freq_hz);
@@ -1520,7 +1537,7 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc4000_priv *priv = fe->tuner_priv;
- *freq = priv->freq_hz;
+ *freq = priv->freq_hz + priv->freq_offset;
if (debug) {
mutex_lock(&priv->lock);
@@ -1668,7 +1685,6 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
switch (instance) {
case 0:
goto fail;
- break;
case 1:
/* new tuner instance */
priv->bandwidth = 6000000;
@@ -1755,3 +1771,5 @@ EXPORT_SYMBOL(xc4000_attach);
MODULE_AUTHOR("Steven Toth, Davide Ferri");
MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(XC4000_DEFAULT_FIRMWARE_NEW);
+MODULE_FIRMWARE(XC4000_DEFAULT_FIRMWARE);
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c
index 2b3d514be672..e135760f7d48 100644
--- a/drivers/media/tuners/xc5000.c
+++ b/drivers/media/tuners/xc5000.c
@@ -56,7 +56,7 @@ struct xc5000_priv {
u32 if_khz;
u16 xtal_khz;
- u32 freq_hz;
+ u32 freq_hz, freq_offset;
u32 bandwidth;
u8 video_standard;
u8 rf_mode;
@@ -625,48 +625,30 @@ static int xc_set_xtal(struct dvb_frontend *fe)
return ret;
}
-static int xc5000_fwupload(struct dvb_frontend *fe)
+static int xc5000_fwupload(struct dvb_frontend *fe,
+ const struct xc5000_fw_cfg *desired_fw,
+ const struct firmware *fw)
{
struct xc5000_priv *priv = fe->tuner_priv;
- const struct firmware *fw;
int ret;
- const struct xc5000_fw_cfg *desired_fw =
- xc5000_assign_firmware(priv->chip_id);
- priv->pll_register_no = desired_fw->pll_reg;
- priv->init_status_supported = desired_fw->init_status_supported;
- priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
/* request the firmware, this will block and timeout */
- printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
+ dprintk(1, "waiting for firmware upload (%s)...\n",
desired_fw->name);
- ret = request_firmware(&fw, desired_fw->name,
- priv->i2c_props.adap->dev.parent);
- if (ret) {
- printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
- goto out;
- } else {
- printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
- fw->size);
- ret = 0;
- }
+ priv->pll_register_no = desired_fw->pll_reg;
+ priv->init_status_supported = desired_fw->init_status_supported;
+ priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
- if (fw->size != desired_fw->size) {
- printk(KERN_ERR "xc5000: firmware incorrect size\n");
- ret = -EINVAL;
- } else {
- printk(KERN_INFO "xc5000: firmware uploading...\n");
- ret = xc_load_i2c_sequence(fe, fw->data);
- if (0 == ret)
- ret = xc_set_xtal(fe);
- if (0 == ret)
- printk(KERN_INFO "xc5000: firmware upload complete...\n");
- else
- printk(KERN_ERR "xc5000: firmware upload failed...\n");
- }
-out:
- release_firmware(fw);
+ dprintk(1, "firmware uploading...\n");
+ ret = xc_load_i2c_sequence(fe, fw->data);
+ if (!ret) {
+ ret = xc_set_xtal(fe);
+ dprintk(1, "Firmware upload complete...\n");
+ } else
+ printk(KERN_ERR "xc5000: firmware upload failed...\n");
+
return ret;
}
@@ -749,13 +731,13 @@ static int xc5000_set_params(struct dvb_frontend *fe)
case SYS_ATSC:
dprintk(1, "%s() VSB modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_AIR;
- priv->freq_hz = freq - 1750000;
+ priv->freq_offset = 1750000;
priv->video_standard = DTV6;
break;
case SYS_DVBC_ANNEX_B:
dprintk(1, "%s() QAM modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_CABLE;
- priv->freq_hz = freq - 1750000;
+ priv->freq_offset = 1750000;
priv->video_standard = DTV6;
break;
case SYS_ISDBT:
@@ -770,15 +752,15 @@ static int xc5000_set_params(struct dvb_frontend *fe)
switch (bw) {
case 6000000:
priv->video_standard = DTV6;
- priv->freq_hz = freq - 1750000;
+ priv->freq_offset = 1750000;
break;
case 7000000:
priv->video_standard = DTV7;
- priv->freq_hz = freq - 2250000;
+ priv->freq_offset = 2250000;
break;
case 8000000:
priv->video_standard = DTV8;
- priv->freq_hz = freq - 2750000;
+ priv->freq_offset = 2750000;
break;
default:
printk(KERN_ERR "xc5000 bandwidth not set!\n");
@@ -792,15 +774,15 @@ static int xc5000_set_params(struct dvb_frontend *fe)
priv->rf_mode = XC_RF_MODE_CABLE;
if (bw <= 6000000) {
priv->video_standard = DTV6;
- priv->freq_hz = freq - 1750000;
+ priv->freq_offset = 1750000;
b = 6;
} else if (bw <= 7000000) {
priv->video_standard = DTV7;
- priv->freq_hz = freq - 2250000;
+ priv->freq_offset = 2250000;
b = 7;
} else {
priv->video_standard = DTV7_8;
- priv->freq_hz = freq - 2750000;
+ priv->freq_offset = 2750000;
b = 8;
}
dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
@@ -811,6 +793,8 @@ static int xc5000_set_params(struct dvb_frontend *fe)
return -EINVAL;
}
+ priv->freq_hz = freq - priv->freq_offset;
+
dprintk(1, "%s() frequency=%d (compensated to %d)\n",
__func__, freq, priv->freq_hz);
@@ -1061,7 +1045,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc5000_priv *priv = fe->tuner_priv;
dprintk(1, "%s()\n", __func__);
- *freq = priv->freq_hz;
+ *freq = priv->freq_hz + priv->freq_offset;
return 0;
}
@@ -1099,42 +1083,65 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
{
struct xc5000_priv *priv = fe->tuner_priv;
- int ret = 0;
+ const struct xc5000_fw_cfg *desired_fw = xc5000_assign_firmware(priv->chip_id);
+ const struct firmware *fw;
+ int ret, i;
u16 pll_lock_status;
u16 fw_ck;
cancel_delayed_work(&priv->timer_sleep);
- if (force || xc5000_is_firmware_loaded(fe) != 0) {
+ if (!force && xc5000_is_firmware_loaded(fe) == 0)
+ return 0;
-fw_retry:
+ ret = request_firmware(&fw, desired_fw->name,
+ priv->i2c_props.adap->dev.parent);
+ if (ret) {
+ printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
+ return ret;
+ }
+
+ dprintk(1, "firmware read %Zu bytes.\n", fw->size);
+
+ if (fw->size != desired_fw->size) {
+ printk(KERN_ERR "xc5000: Firmware file with incorrect size\n");
+ ret = -EINVAL;
+ goto err;
+ }
- ret = xc5000_fwupload(fe);
+ /* Try up to 5 times to load firmware */
+ for (i = 0; i < 5; i++) {
+ if (i)
+ printk(KERN_CONT " - retrying to upload firmware.\n");
+
+ ret = xc5000_fwupload(fe, desired_fw, fw);
if (ret != 0)
- return ret;
+ goto err;
msleep(20);
if (priv->fw_checksum_supported) {
- if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
- != 0) {
- dprintk(1, "%s() FW checksum reading failed.\n",
- __func__);
- goto fw_retry;
+ if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)) {
+ printk(KERN_ERR
+ "xc5000: FW checksum reading failed.");
+ continue;
}
- if (fw_ck == 0) {
- dprintk(1, "%s() FW checksum failed = 0x%04x\n",
- __func__, fw_ck);
- goto fw_retry;
+ if (!fw_ck) {
+ printk(KERN_ERR
+ "xc5000: FW checksum failed = 0x%04x.",
+ fw_ck);
+ continue;
}
}
/* Start the tuner self-calibration process */
- ret |= xc_initialize(priv);
-
- if (ret != 0)
- goto fw_retry;
+ ret = xc_initialize(priv);
+ if (ret) {
+ printk(KERN_ERR
+ "xc5000: Can't request Self-callibration.");
+ continue;
+ }
/* Wait for calibration to complete.
* We could continue but XC5000 will clock stretch subsequent
@@ -1144,15 +1151,17 @@ fw_retry:
msleep(100);
if (priv->init_status_supported) {
- if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != 0) {
- dprintk(1, "%s() FW failed reading init status.\n",
- __func__);
- goto fw_retry;
+ if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck)) {
+ printk(KERN_ERR
+ "xc5000: FW failed reading init status.");
+ continue;
}
- if (fw_ck == 0) {
- dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
- goto fw_retry;
+ if (!fw_ck) {
+ printk(KERN_ERR
+ "xc5000: FW init status failed = 0x%04x.",
+ fw_ck);
+ continue;
}
}
@@ -1161,15 +1170,27 @@ fw_retry:
&pll_lock_status);
if (pll_lock_status > 63) {
/* PLL is unlocked, force reload of the firmware */
- printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
- goto fw_retry;
+ printk(KERN_ERR
+ "xc5000: PLL not running after fwload.");
+ continue;
}
}
/* Default to "CABLE" mode */
- ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+ ret = xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+ if (!ret)
+ break;
+ printk(KERN_ERR "xc5000: can't set to cable mode.");
}
+err:
+ if (!ret)
+ printk(KERN_INFO "xc5000: Firmware %s loaded and running.\n",
+ desired_fw->name);
+ else
+ printk(KERN_CONT " - too many retries. Giving up\n");
+
+ release_firmware(fw);
return ret;
}
@@ -1302,7 +1323,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
switch (instance) {
case 0:
goto fail;
- break;
case 1:
/* new tuner instance */
priv->bandwidth = 6000000;
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index 39d824e2bb69..94d51e092db3 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -27,6 +27,7 @@ source "drivers/media/usb/hdpvr/Kconfig"
source "drivers/media/usb/tlg2300/Kconfig"
source "drivers/media/usb/usbvision/Kconfig"
source "drivers/media/usb/stk1160/Kconfig"
+source "drivers/media/usb/go7007/Kconfig"
endif
if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
@@ -52,5 +53,11 @@ if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
source "drivers/media/usb/em28xx/Kconfig"
endif
+if MEDIA_SDR_SUPPORT
+ comment "Software defined radio USB devices"
+source "drivers/media/usb/msi2500/Kconfig"
+source "drivers/media/usb/airspy/Kconfig"
+endif
+
endif #MEDIA_USB_SUPPORT
endif #USB
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 7ac4b143dce8..f438efffefc5 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -9,6 +9,8 @@ obj-y += zr364xx/ stkwebcam/ s2255/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
obj-$(CONFIG_USB_GSPCA) += gspca/
obj-$(CONFIG_USB_PWC) += pwc/
+obj-$(CONFIG_USB_MSI2500) += msi2500/
+obj-$(CONFIG_USB_AIRSPY) += airspy/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_AU0828) += au0828/
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
@@ -20,3 +22,4 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
obj-$(CONFIG_VIDEO_TM6000) += tm6000/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
obj-$(CONFIG_VIDEO_USBTV) += usbtv/
+obj-$(CONFIG_VIDEO_GO7007) += go7007/
diff --git a/drivers/media/usb/airspy/Kconfig b/drivers/media/usb/airspy/Kconfig
new file mode 100644
index 000000000000..10b204cf4dbc
--- /dev/null
+++ b/drivers/media/usb/airspy/Kconfig
@@ -0,0 +1,10 @@
+config USB_AIRSPY
+ tristate "AirSpy"
+ depends on VIDEO_V4L2
+ select VIDEOBUF2_VMALLOC
+ ---help---
+ This is a video4linux2 driver for AirSpy SDR device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called airspy
+
diff --git a/drivers/media/usb/airspy/Makefile b/drivers/media/usb/airspy/Makefile
new file mode 100644
index 000000000000..8d8e61c1a349
--- /dev/null
+++ b/drivers/media/usb/airspy/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_AIRSPY) += airspy.o
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
new file mode 100644
index 000000000000..cb0e515d80ae
--- /dev/null
+++ b/drivers/media/usb/airspy/airspy.c
@@ -0,0 +1,1132 @@
+/*
+ * AirSpy SDR driver
+ *
+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* AirSpy USB API commands (from AirSpy Library) */
+enum {
+ CMD_INVALID = 0x00,
+ CMD_RECEIVER_MODE = 0x01,
+ CMD_SI5351C_WRITE = 0x02,
+ CMD_SI5351C_READ = 0x03,
+ CMD_R820T_WRITE = 0x04,
+ CMD_R820T_READ = 0x05,
+ CMD_SPIFLASH_ERASE = 0x06,
+ CMD_SPIFLASH_WRITE = 0x07,
+ CMD_SPIFLASH_READ = 0x08,
+ CMD_BOARD_ID_READ = 0x09,
+ CMD_VERSION_STRING_READ = 0x0a,
+ CMD_BOARD_PARTID_SERIALNO_READ = 0x0b,
+ CMD_SET_SAMPLE_RATE = 0x0c,
+ CMD_SET_FREQ = 0x0d,
+ CMD_SET_LNA_GAIN = 0x0e,
+ CMD_SET_MIXER_GAIN = 0x0f,
+ CMD_SET_VGA_GAIN = 0x10,
+ CMD_SET_LNA_AGC = 0x11,
+ CMD_SET_MIXER_AGC = 0x12,
+ CMD_SET_PACKING = 0x13,
+};
+
+/*
+ * bEndpointAddress 0x81 EP 1 IN
+ * Transfer Type Bulk
+ * wMaxPacketSize 0x0200 1x 512 bytes
+ */
+#define MAX_BULK_BUFS (6)
+#define BULK_BUFFER_SIZE (128 * 512)
+
+static const struct v4l2_frequency_band bands[] = {
+ {
+ .tuner = 0,
+ .type = V4L2_TUNER_ADC,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 20000000,
+ .rangehigh = 20000000,
+ },
+};
+
+static const struct v4l2_frequency_band bands_rf[] = {
+ {
+ .tuner = 1,
+ .type = V4L2_TUNER_RF,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 24000000,
+ .rangehigh = 1750000000,
+ },
+};
+
+/* stream formats */
+struct airspy_format {
+ char *name;
+ u32 pixelformat;
+ u32 buffersize;
+};
+
+/* format descriptions for capture and preview */
+static struct airspy_format formats[] = {
+ {
+ .name = "Real U12LE",
+ .pixelformat = V4L2_SDR_FMT_RU12LE,
+ .buffersize = BULK_BUFFER_SIZE,
+ },
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct airspy_frame_buf {
+ struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ struct list_head list;
+};
+
+struct airspy {
+#define POWER_ON (1 << 1)
+#define URB_BUF (1 << 2)
+#define USB_STATE_URB_BUF (1 << 3)
+ unsigned long flags;
+
+ struct usb_device *udev;
+ struct video_device vdev;
+ struct v4l2_device v4l2_dev;
+
+ /* videobuf2 queue and queued buffers list */
+ struct vb2_queue vb_queue;
+ struct list_head queued_bufs;
+ spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+ unsigned sequence; /* Buffer sequence counter */
+ unsigned int vb_full; /* vb is full and packets dropped */
+
+ /* Note if taking both locks v4l2_lock must always be locked first! */
+ struct mutex v4l2_lock; /* Protects everything else */
+ struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */
+
+ struct urb *urb_list[MAX_BULK_BUFS];
+ int buf_num;
+ unsigned long buf_size;
+ u8 *buf_list[MAX_BULK_BUFS];
+ dma_addr_t dma_addr[MAX_BULK_BUFS];
+ int urbs_initialized;
+ int urbs_submitted;
+
+ /* USB control message buffer */
+ #define BUF_SIZE 24
+ u8 buf[BUF_SIZE];
+
+ /* Current configuration */
+ unsigned int f_adc;
+ unsigned int f_rf;
+ u32 pixelformat;
+ u32 buffersize;
+
+ /* Controls */
+ struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *lna_gain_auto;
+ struct v4l2_ctrl *lna_gain;
+ struct v4l2_ctrl *mixer_gain_auto;
+ struct v4l2_ctrl *mixer_gain;
+ struct v4l2_ctrl *if_gain;
+
+ /* Sample rate calc */
+ unsigned long jiffies_next;
+ unsigned int sample;
+ unsigned int sample_measured;
+};
+
+#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+ char *_direction; \
+ if (_t & USB_DIR_IN) \
+ _direction = "<<<"; \
+ else \
+ _direction = ">>>"; \
+ dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \
+ _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+ _l, _b); \
+}
+
+/* execute firmware command */
+static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
+ u8 *data, u16 size)
+{
+ int ret;
+ unsigned int pipe;
+ u8 requesttype;
+
+ switch (request) {
+ case CMD_RECEIVER_MODE:
+ case CMD_SET_FREQ:
+ pipe = usb_sndctrlpipe(s->udev, 0);
+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
+ break;
+ case CMD_BOARD_ID_READ:
+ case CMD_VERSION_STRING_READ:
+ case CMD_BOARD_PARTID_SERIALNO_READ:
+ case CMD_SET_LNA_GAIN:
+ case CMD_SET_MIXER_GAIN:
+ case CMD_SET_VGA_GAIN:
+ case CMD_SET_LNA_AGC:
+ case CMD_SET_MIXER_AGC:
+ pipe = usb_rcvctrlpipe(s->udev, 0);
+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
+ break;
+ default:
+ dev_err(&s->udev->dev, "Unknown command %02x\n", request);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* write request */
+ if (!(requesttype & USB_DIR_IN))
+ memcpy(s->buf, data, size);
+
+ ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
+ index, s->buf, size, 1000);
+ airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
+ index, s->buf, size);
+ if (ret < 0) {
+ dev_err(&s->udev->dev,
+ "usb_control_msg() failed %d request %02x\n",
+ ret, request);
+ goto err;
+ }
+
+ /* read request */
+ if (requesttype & USB_DIR_IN)
+ memcpy(data, s->buf, size);
+
+ return 0;
+err:
+ return ret;
+}
+
+/* Private functions */
+static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
+{
+ unsigned long flags = 0;
+ struct airspy_frame_buf *buf = NULL;
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ if (list_empty(&s->queued_bufs))
+ goto leave;
+
+ buf = list_entry(s->queued_bufs.next,
+ struct airspy_frame_buf, list);
+ list_del(&buf->list);
+leave:
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+ return buf;
+}
+
+static unsigned int airspy_convert_stream(struct airspy *s,
+ void *dst, void *src, unsigned int src_len)
+{
+ unsigned int dst_len;
+
+ if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
+ memcpy(dst, src, src_len);
+ dst_len = src_len;
+ } else {
+ dst_len = 0;
+ }
+
+ /* calculate samping rate and output it in 10 seconds intervals */
+ if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+ #define MSECS 10000UL
+ unsigned int samples = s->sample - s->sample_measured;
+ s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+ s->sample_measured = s->sample;
+ dev_dbg(&s->udev->dev,
+ "slen=%d samples=%u msecs=%lu sample rate=%lu\n",
+ src_len, samples, MSECS,
+ samples * 1000UL / MSECS);
+ }
+
+ /* total number of samples */
+ s->sample += src_len / 2;
+
+ return dst_len;
+}
+
+/*
+ * This gets called for the bulk stream pipe. This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void airspy_urb_complete(struct urb *urb)
+{
+ struct airspy *s = urb->context;
+ struct airspy_frame_buf *fbuf;
+
+ dev_dbg_ratelimited(&s->udev->dev,
+ "%s: status=%d length=%d/%d errors=%d\n",
+ __func__, urb->status, urb->actual_length,
+ urb->transfer_buffer_length, urb->error_count);
+
+ switch (urb->status) {
+ case 0: /* success */
+ case -ETIMEDOUT: /* NAK */
+ break;
+ case -ECONNRESET: /* kill */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* error */
+ dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
+ urb->status);
+ break;
+ }
+
+ if (likely(urb->actual_length > 0)) {
+ void *ptr;
+ unsigned int len;
+ /* get free framebuffer */
+ fbuf = airspy_get_next_fill_buf(s);
+ if (unlikely(fbuf == NULL)) {
+ s->vb_full++;
+ dev_notice_ratelimited(&s->udev->dev,
+ "videobuf is full, %d packets dropped\n",
+ s->vb_full);
+ goto skip;
+ }
+
+ /* fill framebuffer */
+ ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+ len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
+ urb->actual_length);
+ vb2_set_plane_payload(&fbuf->vb, 0, len);
+ v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
+ fbuf->vb.v4l2_buf.sequence = s->sequence++;
+ vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ }
+skip:
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int airspy_kill_urbs(struct airspy *s)
+{
+ int i;
+
+ for (i = s->urbs_submitted - 1; i >= 0; i--) {
+ dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
+ /* stop the URB */
+ usb_kill_urb(s->urb_list[i]);
+ }
+ s->urbs_submitted = 0;
+
+ return 0;
+}
+
+static int airspy_submit_urbs(struct airspy *s)
+{
+ int i, ret;
+
+ for (i = 0; i < s->urbs_initialized; i++) {
+ dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
+ ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Could not submit URB no. %d - get them all back\n",
+ i);
+ airspy_kill_urbs(s);
+ return ret;
+ }
+ s->urbs_submitted++;
+ }
+
+ return 0;
+}
+
+static int airspy_free_stream_bufs(struct airspy *s)
+{
+ if (s->flags & USB_STATE_URB_BUF) {
+ while (s->buf_num) {
+ s->buf_num--;
+ dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
+ __func__, s->buf_num);
+ usb_free_coherent(s->udev, s->buf_size,
+ s->buf_list[s->buf_num],
+ s->dma_addr[s->buf_num]);
+ }
+ }
+ s->flags &= ~USB_STATE_URB_BUF;
+
+ return 0;
+}
+
+static int airspy_alloc_stream_bufs(struct airspy *s)
+{
+ s->buf_num = 0;
+ s->buf_size = BULK_BUFFER_SIZE;
+
+ dev_dbg(&s->udev->dev,
+ "%s: all in all I will use %u bytes for streaming\n",
+ __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+ for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
+ s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+ BULK_BUFFER_SIZE, GFP_ATOMIC,
+ &s->dma_addr[s->buf_num]);
+ if (!s->buf_list[s->buf_num]) {
+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
+ __func__, s->buf_num);
+ airspy_free_stream_bufs(s);
+ return -ENOMEM;
+ }
+
+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+ __func__, s->buf_num,
+ s->buf_list[s->buf_num],
+ (long long)s->dma_addr[s->buf_num]);
+ s->flags |= USB_STATE_URB_BUF;
+ }
+
+ return 0;
+}
+
+static int airspy_free_urbs(struct airspy *s)
+{
+ int i;
+
+ airspy_kill_urbs(s);
+
+ for (i = s->urbs_initialized - 1; i >= 0; i--) {
+ if (s->urb_list[i]) {
+ dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
+ __func__, i);
+ /* free the URBs */
+ usb_free_urb(s->urb_list[i]);
+ }
+ }
+ s->urbs_initialized = 0;
+
+ return 0;
+}
+
+static int airspy_alloc_urbs(struct airspy *s)
+{
+ int i, j;
+
+ /* allocate the URBs */
+ for (i = 0; i < MAX_BULK_BUFS; i++) {
+ dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+ s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!s->urb_list[i]) {
+ dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
+ for (j = 0; j < i; j++)
+ usb_free_urb(s->urb_list[j]);
+ return -ENOMEM;
+ }
+ usb_fill_bulk_urb(s->urb_list[i],
+ s->udev,
+ usb_rcvbulkpipe(s->udev, 0x81),
+ s->buf_list[i],
+ BULK_BUFFER_SIZE,
+ airspy_urb_complete, s);
+
+ s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+ s->urb_list[i]->transfer_dma = s->dma_addr[i];
+ s->urbs_initialized++;
+ }
+
+ return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void airspy_cleanup_queued_bufs(struct airspy *s)
+{
+ unsigned long flags = 0;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ while (!list_empty(&s->queued_bufs)) {
+ struct airspy_frame_buf *buf;
+ buf = list_entry(s->queued_bufs.next,
+ struct airspy_frame_buf, list);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void airspy_disconnect(struct usb_interface *intf)
+{
+ struct v4l2_device *v = usb_get_intfdata(intf);
+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ mutex_lock(&s->vb_queue_lock);
+ mutex_lock(&s->v4l2_lock);
+ /* No need to keep the urbs around after disconnection */
+ s->udev = NULL;
+ v4l2_device_disconnect(&s->v4l2_dev);
+ video_unregister_device(&s->vdev);
+ mutex_unlock(&s->v4l2_lock);
+ mutex_unlock(&s->vb_queue_lock);
+
+ v4l2_device_put(&s->v4l2_dev);
+}
+
+/* Videobuf2 operations */
+static int airspy_queue_setup(struct vb2_queue *vq,
+ const struct v4l2_format *fmt, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+
+ dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+ /* Need at least 8 buffers */
+ if (vq->num_buffers + *nbuffers < 8)
+ *nbuffers = 8 - vq->num_buffers;
+ *nplanes = 1;
+ sizes[0] = PAGE_ALIGN(s->buffersize);
+
+ dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+ __func__, *nbuffers, sizes[0]);
+ return 0;
+}
+
+static void airspy_buf_queue(struct vb2_buffer *vb)
+{
+ struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
+ struct airspy_frame_buf *buf =
+ container_of(vb, struct airspy_frame_buf, vb);
+ unsigned long flags = 0;
+
+ /* Check the device has not disconnected between prep and queuing */
+ if (unlikely(!s->udev)) {
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ return;
+ }
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ list_add_tail(&buf->list, &s->queued_bufs);
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (!s->udev)
+ return -ENODEV;
+
+ mutex_lock(&s->v4l2_lock);
+
+ set_bit(POWER_ON, &s->flags);
+
+ s->sequence = 0;
+
+ ret = airspy_alloc_stream_bufs(s);
+ if (ret)
+ goto err;
+
+ ret = airspy_alloc_urbs(s);
+ if (ret)
+ goto err;
+
+ ret = airspy_submit_urbs(s);
+ if (ret)
+ goto err;
+
+ /* start hardware streaming */
+ ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
+ if (ret)
+ goto err;
+err:
+ mutex_unlock(&s->v4l2_lock);
+
+ return ret;
+}
+
+static void airspy_stop_streaming(struct vb2_queue *vq)
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ mutex_lock(&s->v4l2_lock);
+
+ /* stop hardware streaming */
+ airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
+
+ airspy_kill_urbs(s);
+ airspy_free_urbs(s);
+ airspy_free_stream_bufs(s);
+
+ airspy_cleanup_queued_bufs(s);
+
+ clear_bit(POWER_ON, &s->flags);
+
+ mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops airspy_vb2_ops = {
+ .queue_setup = airspy_queue_setup,
+ .buf_queue = airspy_buf_queue,
+ .start_streaming = airspy_start_streaming,
+ .stop_streaming = airspy_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+static int airspy_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+ usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+ cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+ return 0;
+}
+
+static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
+
+ if (f->index >= NUM_FORMATS)
+ return -EINVAL;
+
+ strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+ f->pixelformat = formats[f->index].pixelformat;
+
+ return 0;
+}
+
+static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&s->pixelformat);
+
+ f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+
+ return 0;
+}
+
+static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+ struct vb2_queue *q = &s->vb_queue;
+ int i;
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.sdr.pixelformat);
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
+
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
+ return 0;
+ }
+ }
+
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
+
+ return 0;
+}
+
+static int airspy_try_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int i;
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.sdr.pixelformat);
+
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
+ return 0;
+ }
+ }
+
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
+
+ return 0;
+}
+
+static int airspy_s_tuner(struct file *file, void *priv,
+ const struct v4l2_tuner *v)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+ if (v->index == 0)
+ ret = 0;
+ else if (v->index == 1)
+ ret = 0;
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+ if (v->index == 0) {
+ strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
+ v->type = V4L2_TUNER_ADC;
+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ v->rangelow = bands[0].rangelow;
+ v->rangehigh = bands[0].rangehigh;
+ ret = 0;
+ } else if (v->index == 1) {
+ strlcpy(v->name, "AirSpy RF", sizeof(v->name));
+ v->type = V4L2_TUNER_RF;
+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ v->rangelow = bands_rf[0].rangelow;
+ v->rangehigh = bands_rf[0].rangehigh;
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret = 0;
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+ __func__, f->tuner, f->type);
+
+ if (f->tuner == 0) {
+ f->type = V4L2_TUNER_ADC;
+ f->frequency = s->f_adc;
+ ret = 0;
+ } else if (f->tuner == 1) {
+ f->type = V4L2_TUNER_RF;
+ f->frequency = s->f_rf;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_s_frequency(struct file *file, void *priv,
+ const struct v4l2_frequency *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+ u8 buf[4];
+
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+ __func__, f->tuner, f->type, f->frequency);
+
+ if (f->tuner == 0) {
+ s->f_adc = clamp_t(unsigned int, f->frequency,
+ bands[0].rangelow,
+ bands[0].rangehigh);
+ dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+ __func__, s->f_adc);
+ ret = 0;
+ } else if (f->tuner == 1) {
+ s->f_rf = clamp_t(unsigned int, f->frequency,
+ bands_rf[0].rangelow,
+ bands_rf[0].rangehigh);
+ dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+ __func__, s->f_rf);
+ buf[0] = (s->f_rf >> 0) & 0xff;
+ buf[1] = (s->f_rf >> 8) & 0xff;
+ buf[2] = (s->f_rf >> 16) & 0xff;
+ buf[3] = (s->f_rf >> 24) & 0xff;
+ ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_enum_freq_bands(struct file *file, void *priv,
+ struct v4l2_frequency_band *band)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+ __func__, band->tuner, band->type, band->index);
+
+ if (band->tuner == 0) {
+ if (band->index >= ARRAY_SIZE(bands)) {
+ ret = -EINVAL;
+ } else {
+ *band = bands[band->index];
+ ret = 0;
+ }
+ } else if (band->tuner == 1) {
+ if (band->index >= ARRAY_SIZE(bands_rf)) {
+ ret = -EINVAL;
+ } else {
+ *band = bands_rf[band->index];
+ ret = 0;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
+ .vidioc_querycap = airspy_querycap,
+
+ .vidioc_enum_fmt_sdr_cap = airspy_enum_fmt_sdr_cap,
+ .vidioc_g_fmt_sdr_cap = airspy_g_fmt_sdr_cap,
+ .vidioc_s_fmt_sdr_cap = airspy_s_fmt_sdr_cap,
+ .vidioc_try_fmt_sdr_cap = airspy_try_fmt_sdr_cap,
+
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+
+ .vidioc_g_tuner = airspy_g_tuner,
+ .vidioc_s_tuner = airspy_s_tuner,
+
+ .vidioc_g_frequency = airspy_g_frequency,
+ .vidioc_s_frequency = airspy_s_frequency,
+ .vidioc_enum_freq_bands = airspy_enum_freq_bands,
+
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations airspy_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .unlocked_ioctl = video_ioctl2,
+};
+
+static struct video_device airspy_template = {
+ .name = "AirSpy SDR",
+ .release = video_device_release_empty,
+ .fops = &airspy_fops,
+ .ioctl_ops = &airspy_ioctl_ops,
+};
+
+static void airspy_video_release(struct v4l2_device *v)
+{
+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+ v4l2_ctrl_handler_free(&s->hdl);
+ v4l2_device_unregister(&s->v4l2_dev);
+ kfree(s);
+}
+
+static int airspy_set_lna_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+ __func__, s->lna_gain_auto->cur.val,
+ s->lna_gain_auto->val, s->lna_gain->cur.val,
+ s->lna_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+
+ if (s->lna_gain_auto->val == false) {
+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_set_mixer_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+ __func__, s->mixer_gain_auto->cur.val,
+ s->mixer_gain_auto->val, s->mixer_gain->cur.val,
+ s->mixer_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+
+ if (s->mixer_gain_auto->val == false) {
+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
+ s->mixer_gain->val, &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_set_if_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
+ __func__, s->if_gain->cur.val, s->if_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
+ case V4L2_CID_RF_TUNER_LNA_GAIN:
+ ret = airspy_set_lna_gain(s);
+ break;
+ case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
+ case V4L2_CID_RF_TUNER_MIXER_GAIN:
+ ret = airspy_set_mixer_gain(s);
+ break;
+ case V4L2_CID_RF_TUNER_IF_GAIN:
+ ret = airspy_set_if_gain(s);
+ break;
+ default:
+ dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
+ __func__, ctrl->id, ctrl->name);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
+ .s_ctrl = airspy_s_ctrl,
+};
+
+static int airspy_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct airspy *s = NULL;
+ int ret;
+ u8 u8tmp, buf[BUF_SIZE];
+
+ s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
+ if (s == NULL) {
+ dev_err(&udev->dev,
+ "Could not allocate memory for airspy state\n");
+ return -ENOMEM;
+ }
+
+ mutex_init(&s->v4l2_lock);
+ mutex_init(&s->vb_queue_lock);
+ spin_lock_init(&s->queued_bufs_lock);
+ INIT_LIST_HEAD(&s->queued_bufs);
+ s->udev = udev;
+ s->f_adc = bands[0].rangelow;
+ s->f_rf = bands_rf[0].rangelow;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+
+ /* Detect device */
+ ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
+ if (ret == 0)
+ ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
+ buf, BUF_SIZE);
+ if (ret) {
+ dev_err(&s->udev->dev, "Could not detect board\n");
+ goto err_free_mem;
+ }
+
+ buf[BUF_SIZE - 1] = '\0';
+
+ dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
+ dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
+
+ /* Init videobuf2 queue structure */
+ s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+ s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+ s->vb_queue.drv_priv = s;
+ s->vb_queue.buf_struct_size = sizeof(struct airspy_frame_buf);
+ s->vb_queue.ops = &airspy_vb2_ops;
+ s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+ s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ ret = vb2_queue_init(&s->vb_queue);
+ if (ret) {
+ dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+ goto err_free_mem;
+ }
+
+ /* Init video_device structure */
+ s->vdev = airspy_template;
+ s->vdev.queue = &s->vb_queue;
+ s->vdev.queue->lock = &s->vb_queue_lock;
+ video_set_drvdata(&s->vdev, s);
+
+ /* Register the v4l2_device structure */
+ s->v4l2_dev.release = airspy_video_release;
+ ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Failed to register v4l2-device (%d)\n", ret);
+ goto err_free_mem;
+ }
+
+ /* Register controls */
+ v4l2_ctrl_handler_init(&s->hdl, 5);
+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
+ dev_err(&s->udev->dev, "Could not initialize controls\n");
+ goto err_free_controls;
+ }
+
+ v4l2_ctrl_handler_setup(&s->hdl);
+
+ s->v4l2_dev.ctrl_handler = &s->hdl;
+ s->vdev.v4l2_dev = &s->v4l2_dev;
+ s->vdev.lock = &s->v4l2_lock;
+
+ ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Failed to register as video device (%d)\n",
+ ret);
+ goto err_unregister_v4l2_dev;
+ }
+ dev_info(&s->udev->dev, "Registered as %s\n",
+ video_device_node_name(&s->vdev));
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
+ return 0;
+
+err_free_controls:
+ v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&s->v4l2_dev);
+err_free_mem:
+ kfree(s);
+ return ret;
+}
+
+/* USB device ID list */
+static struct usb_device_id airspy_id_table[] = {
+ { USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
+ { }
+};
+MODULE_DEVICE_TABLE(usb, airspy_id_table);
+
+/* USB subsystem interface */
+static struct usb_driver airspy_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = airspy_probe,
+ .disconnect = airspy_disconnect,
+ .id_table = airspy_id_table,
+};
+
+module_usb_driver(airspy_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("AirSpy SDR");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig
index 953a37c613b1..1d410ac8f9a8 100644
--- a/drivers/media/usb/au0828/Kconfig
+++ b/drivers/media/usb/au0828/Kconfig
@@ -20,9 +20,17 @@ config VIDEO_AU0828_V4L2
bool "Auvitek AU0828 v4l2 analog video support"
depends on VIDEO_AU0828 && VIDEO_V4L2
select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
+ select VIDEO_TUNER
default y
---help---
This is a video4linux driver for Auvitek's USB device.
Choose Y here to include support for v4l2 analog video
capture within the au0828 driver.
+
+config VIDEO_AU0828_RC
+ bool "AU0828 Remote Controller support"
+ depends on RC_CORE
+ depends on VIDEO_AU0828
+ ---help---
+ Enables Remote Controller support on au0828 driver.
diff --git a/drivers/media/usb/au0828/Makefile b/drivers/media/usb/au0828/Makefile
index be3bdf698022..3dc7539a5c4e 100644
--- a/drivers/media/usb/au0828/Makefile
+++ b/drivers/media/usb/au0828/Makefile
@@ -4,6 +4,10 @@ ifeq ($(CONFIG_VIDEO_AU0828_V4L2),y)
au0828-objs += au0828-video.o au0828-vbi.o
endif
+ifeq ($(CONFIG_VIDEO_AU0828_RC),y)
+ au0828-objs += au0828-input.o
+endif
+
obj-$(CONFIG_VIDEO_AU0828) += au0828.o
ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index 7fdadf9bc90b..2c6b7da137ed 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = {
.name = "Hauppauge HVR850",
.tuner_type = TUNER_XC5000,
.tuner_addr = 0x61,
- .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+ .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
.input = {
{
.type = AU0828_VMUX_TELEVISION,
@@ -71,13 +71,14 @@ struct au0828_board au0828_boards[] = {
.name = "Hauppauge HVR950Q",
.tuner_type = TUNER_XC5000,
.tuner_addr = 0x61,
+ .has_ir_i2c = 1,
/* The au0828 hardware i2c implementation does not properly
support the xc5000's i2c clock stretching. So we need to
lower the clock frequency enough where the 15us clock
stretch fits inside of a normal clock cycle, or else the
au0828 fails to set the STOP bit. A 30 KHz clock puts the
clock pulse width at 18us */
- .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+ .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
.input = {
{
.type = AU0828_VMUX_TELEVISION,
@@ -108,7 +109,7 @@ struct au0828_board au0828_boards[] = {
.name = "DViCO FusionHDTV USB",
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
- .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+ .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
},
[AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
.name = "Hauppauge Woodbury",
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index ab45a6f9dcc9..56025e689442 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -32,10 +32,12 @@
* 2 = USB handling
* 4 = I2C related
* 8 = Bridge related
+ * 16 = IR related
*/
int au0828_debug;
module_param_named(debug, au0828_debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
+MODULE_PARM_DESC(debug,
+ "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");
static unsigned int disable_usb_speed_check;
module_param(disable_usb_speed_check, int, 0444);
@@ -151,6 +153,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface)
dprintk(1, "%s()\n", __func__);
+#ifdef CONFIG_VIDEO_AU0828_RC
+ au0828_rc_unregister(dev);
+#endif
/* Digital TV */
au0828_dvb_unregister(dev);
@@ -261,9 +266,15 @@ static int au0828_usb_probe(struct usb_interface *interface,
pr_err("%s() au0282_dev_register failed\n",
__func__);
+#ifdef CONFIG_VIDEO_AU0828_RC
+ /* Remote controller */
+ au0828_rc_register(dev);
+#endif
- /* Store the pointer to the au0828_dev so it can be accessed in
- au0828_usb_disconnect */
+ /*
+ * Store the pointer to the au0828_dev so it can be accessed in
+ * au0828_usb_disconnect
+ */
usb_set_intfdata(interface, dev);
printk(KERN_INFO "Registered device AU0828 [%s]\n",
@@ -279,6 +290,8 @@ static struct usb_driver au0828_usb_driver = {
.probe = au0828_usb_probe,
.disconnect = au0828_usb_disconnect,
.id_table = au0828_usb_id_table,
+
+ /* FIXME: Add suspend and resume functions */
};
static int __init au0828_init(void)
@@ -298,6 +311,10 @@ static int __init au0828_init(void)
printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
__func__);
+ if (au0828_debug & 16)
+ printk(KERN_INFO "%s() IR Debugging is enabled\n",
+ __func__);
+
printk(KERN_INFO "au0828 driver loaded\n");
ret = usb_register(&au0828_usb_driver);
@@ -318,4 +335,4 @@ module_exit(au0828_exit);
MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.2");
+MODULE_VERSION("0.0.3");
diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c
index 17ec3651b10e..daaeaf1b089c 100644
--- a/drivers/media/usb/au0828/au0828-i2c.c
+++ b/drivers/media/usb/au0828/au0828-i2c.c
@@ -141,25 +141,27 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
{
int i, strobe = 0;
struct au0828_dev *dev = i2c_adap->algo_data;
+ u8 i2c_speed = dev->board.i2c_clk_divider;
dprintk(4, "%s()\n", __func__);
au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
- /* Set the I2C clock */
if (((dev->board.tuner_type == TUNER_XC5000) ||
(dev->board.tuner_type == TUNER_XC5000C)) &&
- (dev->board.tuner_addr == msg->addr) &&
- (msg->len == 64)) {
- /* Hack to speed up firmware load. The xc5000 lets us do up
- to 400 KHz when in firmware download mode */
- au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
- AU0828_I2C_CLK_250KHZ);
- } else {
- /* Use the i2c clock speed in the board configuration */
- au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
- dev->board.i2c_clk_divider);
+ (dev->board.tuner_addr == msg->addr)) {
+ /*
+ * Due to I2C clock stretch, we need to use a lower speed
+ * on xc5000 for commands. However, firmware transfer can
+ * speed up to 400 KHz.
+ */
+ if (msg->len == 64)
+ i2c_speed = AU0828_I2C_CLK_250KHZ;
+ else
+ i2c_speed = AU0828_I2C_CLK_20KHZ;
}
+ /* Set the I2C clock */
+ au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
/* Hardware needs 8 bit addresses */
au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
@@ -228,15 +230,24 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
const struct i2c_msg *msg, int joined)
{
struct au0828_dev *dev = i2c_adap->algo_data;
+ u8 i2c_speed = dev->board.i2c_clk_divider;
int i;
dprintk(4, "%s()\n", __func__);
au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
+ /*
+ * Due to xc5000c clock stretch, we cannot use full speed at
+ * readings from xc5000, as otherwise they'll fail.
+ */
+ if (((dev->board.tuner_type == TUNER_XC5000) ||
+ (dev->board.tuner_type == TUNER_XC5000C)) &&
+ (dev->board.tuner_addr == msg->addr))
+ i2c_speed = AU0828_I2C_CLK_20KHZ;
+
/* Set the I2C clock */
- au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
- dev->board.i2c_clk_divider);
+ au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
/* Hardware needs 8 bit addresses */
au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
new file mode 100644
index 000000000000..fd0d3a90ce7d
--- /dev/null
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -0,0 +1,386 @@
+/*
+ handle au0828 IR remotes via linux kernel input layer.
+
+ Copyright (C) 2014 Mauro Carvalho Chehab <mchehab@samsung.com>
+ Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+ Based on em28xx-input.c.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+
+#include "au0828.h"
+
+struct au0828_rc {
+ struct au0828_dev *dev;
+ struct rc_dev *rc;
+ char name[32];
+ char phys[32];
+
+ /* poll decoder */
+ int polling;
+ struct delayed_work work;
+
+ /* i2c slave address of external device (if used) */
+ u16 i2c_dev_addr;
+
+ int (*get_key_i2c)(struct au0828_rc *ir);
+};
+
+/*
+ * AU8522 has a builtin IR receiver. Add functions to get IR from it
+ */
+
+static int au8522_rc_write(struct au0828_rc *ir, u16 reg, u8 data)
+{
+ int rc;
+ char buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
+ struct i2c_msg msg = { .addr = ir->i2c_dev_addr, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
+
+ rc = i2c_transfer(ir->dev->i2c_client.adapter, &msg, 1);
+
+ if (rc < 0)
+ return rc;
+
+ return (rc == 1) ? 0 : -EIO;
+}
+
+static int au8522_rc_read(struct au0828_rc *ir, u16 reg, int val,
+ char *buf, int size)
+{
+ int rc;
+ char obuf[3];
+ struct i2c_msg msg[2] = { { .addr = ir->i2c_dev_addr, .flags = 0,
+ .buf = obuf, .len = 2 },
+ { .addr = ir->i2c_dev_addr, .flags = I2C_M_RD,
+ .buf = buf, .len = size } };
+
+ obuf[0] = 0x40 | reg >> 8;
+ obuf[1] = reg & 0xff;
+ if (val >= 0) {
+ obuf[2] = val;
+ msg[0].len++;
+ }
+
+ rc = i2c_transfer(ir->dev->i2c_client.adapter, msg, 2);
+
+ if (rc < 0)
+ return rc;
+
+ return (rc == 2) ? 0 : -EIO;
+}
+
+static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value)
+{
+ int rc;
+ char buf;
+
+ rc = au8522_rc_read(ir, reg, -1, &buf, 1);
+ if (rc < 0)
+ return rc;
+
+ buf = (buf & ~mask) | (value & mask);
+
+ return au8522_rc_write(ir, reg, buf);
+}
+
+#define au8522_rc_set(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), (bit))
+#define au8522_rc_clear(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), 0)
+
+/* Remote Controller time units */
+
+#define AU8522_UNIT 200000 /* ns */
+#define NEC_START_SPACE (4500000 / AU8522_UNIT)
+#define NEC_START_PULSE (562500 * 16)
+#define RC5_START_SPACE (4 * AU8522_UNIT)
+#define RC5_START_PULSE 888888
+
+static int au0828_get_key_au8522(struct au0828_rc *ir)
+{
+ unsigned char buf[40];
+ DEFINE_IR_RAW_EVENT(rawir);
+ int i, j, rc;
+ int prv_bit, bit, width;
+ bool first = true;
+
+ /* Check IR int */
+ rc = au8522_rc_read(ir, 0xe1, -1, buf, 1);
+ if (rc < 0 || !(buf[0] & (1 << 4)))
+ return 0;
+
+ /* Something arrived. Get the data */
+ rc = au8522_rc_read(ir, 0xe3, 0x11, buf, sizeof(buf));
+
+
+ if (rc < 0)
+ return rc;
+
+ /* Disable IR */
+ au8522_rc_clear(ir, 0xe0, 1 << 4);
+
+ usleep_range(45000, 46000);
+
+ /* Enable IR */
+ au8522_rc_set(ir, 0xe0, 1 << 4);
+
+ dprintk(16, "RC data received: %*ph\n", 40, buf);
+
+ prv_bit = (buf[0] >> 7) & 0x01;
+ width = 0;
+ for (i = 0; i < sizeof(buf); i++) {
+ for (j = 7; j >= 0; j--) {
+ bit = (buf[i] >> j) & 0x01;
+ if (bit == prv_bit) {
+ width++;
+ continue;
+ }
+
+ /*
+ * Fix an au8522 bug: the first pulse event
+ * is lost. So, we need to fake it, based on the
+ * protocol. That means that not all raw decoders
+ * will work, as we need to add a hack for each
+ * protocol, based on the first space.
+ * So, we only support RC5 and NEC.
+ */
+
+ if (first) {
+ first = false;
+
+ init_ir_raw_event(&rawir);
+ rawir.pulse = true;
+ if (width > NEC_START_SPACE - 2 &&
+ width < NEC_START_SPACE + 2) {
+ /* NEC protocol */
+ rawir.duration = NEC_START_PULSE;
+ dprintk(16, "Storing NEC start %s with duration %d",
+ rawir.pulse ? "pulse" : "space",
+ rawir.duration);
+ } else {
+ /* RC5 protocol */
+ rawir.duration = RC5_START_PULSE;
+ dprintk(16, "Storing RC5 start %s with duration %d",
+ rawir.pulse ? "pulse" : "space",
+ rawir.duration);
+ }
+ ir_raw_event_store(ir->rc, &rawir);
+ }
+
+ init_ir_raw_event(&rawir);
+ rawir.pulse = prv_bit ? false : true;
+ rawir.duration = AU8522_UNIT * width;
+ dprintk(16, "Storing %s with duration %d",
+ rawir.pulse ? "pulse" : "space",
+ rawir.duration);
+ ir_raw_event_store(ir->rc, &rawir);
+
+ width = 1;
+ prv_bit = bit;
+ }
+ }
+
+ init_ir_raw_event(&rawir);
+ rawir.pulse = prv_bit ? false : true;
+ rawir.duration = AU8522_UNIT * width;
+ dprintk(16, "Storing end %s with duration %d",
+ rawir.pulse ? "pulse" : "space",
+ rawir.duration);
+ ir_raw_event_store(ir->rc, &rawir);
+
+ ir_raw_event_handle(ir->rc);
+
+ return 1;
+}
+
+/*
+ * Generic IR code
+ */
+
+static void au0828_rc_work(struct work_struct *work)
+{
+ struct au0828_rc *ir = container_of(work, struct au0828_rc, work.work);
+ int rc;
+
+ rc = ir->get_key_i2c(ir);
+ if (rc < 0)
+ pr_info("Error while getting RC scancode\n");
+
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static int au0828_rc_start(struct rc_dev *rc)
+{
+ struct au0828_rc *ir = rc->priv;
+
+ INIT_DELAYED_WORK(&ir->work, au0828_rc_work);
+
+ /* Enable IR */
+ au8522_rc_set(ir, 0xe0, 1 << 4);
+
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+
+ return 0;
+}
+
+static void au0828_rc_stop(struct rc_dev *rc)
+{
+ struct au0828_rc *ir = rc->priv;
+
+ /* Disable IR */
+ au8522_rc_clear(ir, 0xe0, 1 << 4);
+
+ cancel_delayed_work_sync(&ir->work);
+}
+
+static int au0828_probe_i2c_ir(struct au0828_dev *dev)
+{
+ int i = 0;
+ const unsigned short addr_list[] = {
+ 0x47, I2C_CLIENT_END
+ };
+
+ while (addr_list[i] != I2C_CLIENT_END) {
+ if (i2c_probe_func_quick_read(dev->i2c_client.adapter,
+ addr_list[i]) == 1)
+ return addr_list[i];
+ i++;
+ }
+
+ return -ENODEV;
+}
+
+int au0828_rc_register(struct au0828_dev *dev)
+{
+ struct au0828_rc *ir;
+ struct rc_dev *rc;
+ int err = -ENOMEM;
+ u16 i2c_rc_dev_addr = 0;
+
+ if (!dev->board.has_ir_i2c)
+ return 0;
+
+ i2c_rc_dev_addr = au0828_probe_i2c_ir(dev);
+ if (!i2c_rc_dev_addr)
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ rc = rc_allocate_device();
+ if (!ir || !rc)
+ goto error;
+
+ /* record handles to ourself */
+ ir->dev = dev;
+ dev->ir = ir;
+ ir->rc = rc;
+
+ rc->priv = ir;
+ rc->open = au0828_rc_start;
+ rc->close = au0828_rc_stop;
+
+ if (dev->board.has_ir_i2c) { /* external i2c device */
+ switch (dev->boardnr) {
+ case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+ rc->map_name = RC_MAP_HAUPPAUGE;
+ ir->get_key_i2c = au0828_get_key_au8522;
+ break;
+ default:
+ err = -ENODEV;
+ goto error;
+ }
+
+ ir->i2c_dev_addr = i2c_rc_dev_addr;
+ }
+
+ /* This is how often we ask the chip for IR information */
+ ir->polling = 100; /* ms */
+
+ /* init input device */
+ snprintf(ir->name, sizeof(ir->name), "au0828 IR (%s)",
+ dev->board.name);
+
+ usb_make_path(dev->usbdev, ir->phys, sizeof(ir->phys));
+ strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+ rc->input_name = ir->name;
+ rc->input_phys = ir->phys;
+ rc->input_id.bustype = BUS_USB;
+ rc->input_id.version = 1;
+ rc->input_id.vendor = le16_to_cpu(dev->usbdev->descriptor.idVendor);
+ rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct);
+ rc->dev.parent = &dev->usbdev->dev;
+ rc->driver_name = "au0828-input";
+ rc->driver_type = RC_DRIVER_IR_RAW;
+ rc->allowed_protocols = RC_BIT_NEC | RC_BIT_RC5;
+
+ /* all done */
+ err = rc_register_device(rc);
+ if (err)
+ goto error;
+
+ pr_info("Remote controller %s initalized\n", ir->name);
+
+ return 0;
+
+error:
+ dev->ir = NULL;
+ rc_free_device(rc);
+ kfree(ir);
+ return err;
+}
+
+void au0828_rc_unregister(struct au0828_dev *dev)
+{
+ struct au0828_rc *ir = dev->ir;
+
+ /* skip detach on non attached boards */
+ if (!ir)
+ return;
+
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
+
+ /* done */
+ kfree(ir);
+ dev->ir = NULL;
+}
+
+int au0828_rc_suspend(struct au0828_dev *dev)
+{
+ struct au0828_rc *ir = dev->ir;
+
+ if (!ir)
+ return 0;
+
+ cancel_delayed_work_sync(&ir->work);
+
+ return 0;
+}
+
+int au0828_rc_resume(struct au0828_dev *dev)
+{
+ struct au0828_rc *ir = dev->ir;
+
+ if (!ir)
+ return 0;
+
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+
+ return 0;
+}
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 9038194513c5..98f7ea1d6d63 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -787,23 +787,40 @@ static int au0828_i2s_init(struct au0828_dev *dev)
/*
* Auvitek au0828 analog stream enable
- * Please set interface0 to AS5 before enable the stream
*/
static int au0828_analog_stream_enable(struct au0828_dev *d)
{
+ struct usb_interface *iface;
+ int ret, h, w;
+
dprintk(1, "au0828_analog_stream_enable called\n");
+
+ iface = usb_ifnum_to_if(d->usbdev, 0);
+ if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) {
+ dprintk(1, "Changing intf#0 to alt 5\n");
+ /* set au0828 interface0 to AS5 here again */
+ ret = usb_set_interface(d->usbdev, 0, 5);
+ if (ret < 0) {
+ printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
+ return -EBUSY;
+ }
+ }
+
+ h = d->height / 2 + 2;
+ w = d->width * 2;
+
au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
au0828_writereg(d, 0x106, 0x00);
/* set x position */
au0828_writereg(d, 0x110, 0x00);
au0828_writereg(d, 0x111, 0x00);
- au0828_writereg(d, 0x114, 0xa0);
- au0828_writereg(d, 0x115, 0x05);
+ au0828_writereg(d, 0x114, w & 0xff);
+ au0828_writereg(d, 0x115, w >> 8);
/* set y position */
au0828_writereg(d, 0x112, 0x00);
au0828_writereg(d, 0x113, 0x00);
- au0828_writereg(d, 0x116, 0xf2);
- au0828_writereg(d, 0x117, 0x00);
+ au0828_writereg(d, 0x116, h & 0xff);
+ au0828_writereg(d, 0x117, h >> 8);
au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
return 0;
@@ -1002,15 +1019,6 @@ static int au0828_v4l2_open(struct file *filp)
return -ERESTARTSYS;
}
if (dev->users == 0) {
- /* set au0828 interface0 to AS5 here again */
- ret = usb_set_interface(dev->usbdev, 0, 5);
- if (ret < 0) {
- mutex_unlock(&dev->lock);
- printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
- kfree(fh);
- return -EBUSY;
- }
-
au0828_analog_stream_enable(dev);
au0828_analog_stream_reset(dev);
@@ -1252,13 +1260,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
}
}
- /* set au0828 interface0 to AS5 here again */
- ret = usb_set_interface(dev->usbdev, 0, 5);
- if (ret < 0) {
- printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
- return -EBUSY;
- }
-
au0828_analog_stream_enable(dev);
return 0;
@@ -1364,9 +1365,11 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
i2c_gate_ctrl(dev, 1);
- /* FIXME: when we support something other than NTSC, we are going to
- have to make the au0828 bridge adjust the size of its capture
- buffer, which is currently hardcoded at 720x480 */
+ /*
+ * FIXME: when we support something other than 60Hz standards,
+ * we are going to have to make the au0828 bridge adjust the size
+ * of its capture buffer, which is currently hardcoded at 720x480
+ */
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm);
@@ -1723,6 +1726,7 @@ static int vidioc_streamoff(struct file *file, void *priv,
dev->vid_timeout_running = 0;
del_timer_sync(&dev->vid_timeout);
+ au0828_analog_stream_disable(dev);
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
rc = au0828_stream_interrupt(dev);
if (rc != 0)
@@ -1915,7 +1919,7 @@ static const struct video_device au0828_video_template = {
.fops = &au0828_v4l_fops,
.release = video_device_release,
.ioctl_ops = &video_ioctl_ops,
- .tvnorms = V4L2_STD_NTSC_M,
+ .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
};
/**************************************************************************/
@@ -1928,7 +1932,8 @@ int au0828_analog_register(struct au0828_dev *dev,
struct usb_endpoint_descriptor *endpoint;
int i, ret;
- dprintk(1, "au0828_analog_register called!\n");
+ dprintk(1, "au0828_analog_register called for intf#%d!\n",
+ interface->cur_altsetting->desc.bInterfaceNumber);
/* set au0828 usb interface0 to as5 */
retval = usb_set_interface(dev->usbdev,
@@ -1952,6 +1957,9 @@ int au0828_analog_register(struct au0828_dev *dev,
dev->max_pkt_size = (tmp & 0x07ff) *
(((tmp & 0x1800) >> 11) + 1);
dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
+ dprintk(1,
+ "Found isoc endpoint 0x%02x, max size = %d\n",
+ dev->isoc_in_endpointaddr, dev->max_pkt_size);
}
}
if (!(dev->isoc_in_endpointaddr)) {
@@ -2008,14 +2016,12 @@ int au0828_analog_register(struct au0828_dev *dev,
*dev->vdev = au0828_video_template;
dev->vdev->v4l2_dev = &dev->v4l2_dev;
dev->vdev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags);
strcpy(dev->vdev->name, "au0828a video");
/* Setup the VBI device */
*dev->vbi_dev = au0828_video_template;
dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
dev->vbi_dev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags);
strcpy(dev->vbi_dev->name, "au0828a vbi");
/* Register the v4l2 device */
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 7112b9d956fa..96bec05d7dac 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -88,6 +88,7 @@ struct au0828_board {
unsigned int tuner_type;
unsigned char tuner_addr;
unsigned char i2c_clk_divider;
+ unsigned char has_ir_i2c:1;
struct au0828_input input[AU0828_MAX_INPUT];
};
@@ -213,6 +214,10 @@ struct au0828_dev {
struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler v4l2_ctrl_hdl;
#endif
+#ifdef CONFIG_VIDEO_AU0828_RC
+ struct au0828_rc *ir;
+#endif
+
int users;
unsigned int resources; /* resources in use */
struct video_device *vdev;
@@ -319,3 +324,9 @@ extern struct videobuf_queue_ops au0828_vbi_qops;
do { if (au0828_debug & level)\
printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
} while (0)
+
+/* au0828-input.c */
+int au0828_rc_register(struct au0828_dev *dev);
+void au0828_rc_unregister(struct au0828_dev *dev);
+int au0828_rc_suspend(struct au0828_dev *dev);
+int au0828_rc_resume(struct au0828_dev *dev);
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index d5d42b6e94be..9caea8344547 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -1169,7 +1169,6 @@ int cpia2_register_camera(struct camera_data *cam)
cam->vdev.lock = &cam->v4l2_lock;
cam->vdev.ctrl_handler = hdl;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
reset_camera_struct_v4l(cam);
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig
index f14c5e89a567..569aa298c03f 100644
--- a/drivers/media/usb/cx231xx/Kconfig
+++ b/drivers/media/usb/cx231xx/Kconfig
@@ -47,6 +47,8 @@ config VIDEO_CX231XX_DVB
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
---help---
This adds support for DVB cards based on the
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 30a0c69fb42f..459bb0e98971 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.width = dev->ts1.width;
f->fmt.pix.height = dev->ts1.height;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
dev->ts1.width, dev->ts1.height);
dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
@@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
dev->ts1.width, dev->ts1.height);
dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
@@ -1923,7 +1921,6 @@ static struct video_device *cx231xx_video_dev_alloc(
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->lock = &dev->lock;
vfd->release = video_device_release;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
video_set_drvdata(vfd, dev);
if (dev->tuner_type == TUNER_ABSENT) {
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 89de00bf4f82..a428c10e1a16 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -352,6 +352,7 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev,
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
case CX231XX_BOARD_HAUPPAUGE_EXETER:
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index 2ee03e4ddd86..8039b769f258 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -704,6 +704,84 @@ struct cx231xx_board cx231xx_boards[] = {
}
},
},
+ [CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx] = {
+ .name = "Hauppauge WinTV 930C-HD (1113xx) / PCTV QuatroStick 521e",
+ .tuner_type = TUNER_NXP_TDA18271,
+ .tuner_addr = 0x60,
+ .tuner_gpio = RDE250_XCV_TUNER,
+ .tuner_sif_gpio = 0x05,
+ .tuner_scl_gpio = 0x1a,
+ .tuner_sda_gpio = 0x1b,
+ .decoder = CX231XX_AVDECODER,
+ .output_mode = OUT_MODE_VIP11,
+ .demod_xfer_mode = 0,
+ .ctl_pin_status_mask = 0xFFFFFFC4,
+ .agc_analog_digital_select_gpio = 0x0c,
+ .gpio_pin_status_mask = 0x4001000,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
+ .has_dvb = 1,
+ .demod_addr = 0x0e,
+ .norm = V4L2_STD_PAL,
+
+ .input = {{
+ .type = CX231XX_VMUX_TELEVISION,
+ .vmux = CX231XX_VIN_3_1,
+ .amux = CX231XX_AMUX_VIDEO,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_COMPOSITE1,
+ .vmux = CX231XX_VIN_2_1,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_SVIDEO,
+ .vmux = CX231XX_VIN_1_1 |
+ (CX231XX_VIN_1_2 << 8) |
+ CX25840_SVIDEO_ON,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ } },
+ },
+ [CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx] = {
+ .name = "Hauppauge WinTV 930C-HD (1114xx) / PCTV QuatroStick 522e",
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = 0x60,
+ .tuner_gpio = RDE250_XCV_TUNER,
+ .tuner_sif_gpio = 0x05,
+ .tuner_scl_gpio = 0x1a,
+ .tuner_sda_gpio = 0x1b,
+ .decoder = CX231XX_AVDECODER,
+ .output_mode = OUT_MODE_VIP11,
+ .demod_xfer_mode = 0,
+ .ctl_pin_status_mask = 0xFFFFFFC4,
+ .agc_analog_digital_select_gpio = 0x0c,
+ .gpio_pin_status_mask = 0x4001000,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
+ .has_dvb = 1,
+ .demod_addr = 0x0e,
+ .norm = V4L2_STD_PAL,
+
+ .input = {{
+ .type = CX231XX_VMUX_TELEVISION,
+ .vmux = CX231XX_VIN_3_1,
+ .amux = CX231XX_AMUX_VIDEO,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_COMPOSITE1,
+ .vmux = CX231XX_VIN_2_1,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ }, {
+ .type = CX231XX_VMUX_SVIDEO,
+ .vmux = CX231XX_VIN_1_1 |
+ (CX231XX_VIN_1_2 << 8) |
+ CX25840_SVIDEO_ON,
+ .amux = CX231XX_AMUX_LINE_IN,
+ .gpio = NULL,
+ } },
+ },
};
const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
@@ -733,10 +811,20 @@ struct usb_device_id cx231xx_id_table[] = {
.driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
{USB_DEVICE(0x2040, 0xb120),
.driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
+ {USB_DEVICE(0x2040, 0xb130),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
+ {USB_DEVICE(0x2040, 0xb131),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
{USB_DEVICE(0x2040, 0xb140),
.driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
{USB_DEVICE(0x2040, 0xc200),
.driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
+ /* PCTV QuatroStick 521e */
+ {USB_DEVICE(0x2013, 0x0259),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
+ /* PCTV QuatroStick 522e */
+ {USB_DEVICE(0x2013, 0x025e),
+ .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx},
{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
.driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
@@ -886,6 +974,50 @@ static void cx231xx_config_tuner(struct cx231xx *dev)
}
+static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
+{
+ int ret = 0;
+ u8 addr = 0xa0 >> 1;
+ u8 start_offset = 0;
+ int len_todo = len;
+ u8 *eedata_cur = eedata;
+ int i;
+ struct i2c_msg msg_write = { .addr = addr, .flags = 0,
+ .buf = &start_offset, .len = 1 };
+ struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
+
+ /* mutex_lock(&dev->i2c_lock); */
+ cx231xx_enable_i2c_port_3(dev, false);
+
+ /* start reading at offset 0 */
+ ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
+ if (ret < 0) {
+ cx231xx_err("Can't read eeprom\n");
+ return ret;
+ }
+
+ while (len_todo > 0) {
+ msg_read.len = (len_todo > 64) ? 64 : len_todo;
+ msg_read.buf = eedata_cur;
+
+ ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
+ if (ret < 0) {
+ cx231xx_err("Can't read eeprom\n");
+ return ret;
+ }
+ eedata_cur += msg_read.len;
+ len_todo -= msg_read.len;
+ }
+
+ cx231xx_enable_i2c_port_3(dev, true);
+ /* mutex_unlock(&dev->i2c_lock); */
+
+ for (i = 0; i + 15 < len; i += 16)
+ cx231xx_info("i2c eeprom %02x: %*ph\n", i, 16, &eedata[i]);
+
+ return 0;
+}
+
void cx231xx_card_setup(struct cx231xx *dev)
{
@@ -917,6 +1049,21 @@ void cx231xx_card_setup(struct cx231xx *dev)
else
cx231xx_config_tuner(dev);
}
+
+ switch (dev->model) {
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+ {
+ struct tveeprom tvee;
+ static u8 eeprom[256];
+
+ read_eeprom(dev, eeprom, sizeof(eeprom));
+ tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
+ &tvee, eeprom + 0xc0);
+ break;
+ }
+ }
+
}
/*
@@ -964,12 +1111,6 @@ void cx231xx_release_resources(struct cx231xx *dev)
/* Mark device as unused */
clear_bit(dev->devno, &cx231xx_devused);
-
- kfree(dev->video_mode.alt_max_pkt_size);
- kfree(dev->vbi_mode.alt_max_pkt_size);
- kfree(dev->sliced_cc_mode.alt_max_pkt_size);
- kfree(dev->ts1_mode.alt_max_pkt_size);
- kfree(dev);
}
/*
@@ -1003,7 +1144,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
/* Query cx231xx to find what pcb config it is related to */
- initialize_cx231xx(dev);
+ retval = initialize_cx231xx(dev);
+ if (retval < 0) {
+ cx231xx_errdev("Failed to read PCB config\n");
+ return retval;
+ }
/*To workaround error number=-71 on EP0 for VideoGrabber,
need set alt here.*/
@@ -1121,6 +1266,117 @@ static void flush_request_modules(struct cx231xx *dev)
#define flush_request_modules(dev)
#endif /* CONFIG_MODULES */
+static int cx231xx_init_v4l2(struct cx231xx *dev,
+ struct usb_device *udev,
+ struct usb_interface *interface,
+ int isoc_pipe)
+{
+ struct usb_interface *uif;
+ int i, idx;
+
+ /* Video Init */
+
+ /* compute alternate max packet sizes for video */
+ idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
+ if (idx >= dev->max_iad_interface_count) {
+ cx231xx_errdev("Video PCB interface #%d doesn't exist\n", idx);
+ return -ENODEV;
+ }
+
+ uif = udev->actconfig->interface[idx];
+
+ dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
+ dev->video_mode.num_alt = uif->num_altsetting;
+
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->video_mode.end_point_addr,
+ dev->video_mode.num_alt);
+
+ dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
+ if (dev->video_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dev->video_mode.num_alt; i++) {
+ u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+ dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->video_mode.alt_max_pkt_size[i]);
+ }
+
+ /* VBI Init */
+
+ idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
+ if (idx >= dev->max_iad_interface_count) {
+ cx231xx_errdev("VBI PCB interface #%d doesn't exist\n", idx);
+ return -ENODEV;
+ }
+ uif = udev->actconfig->interface[idx];
+
+ dev->vbi_mode.end_point_addr =
+ uif->altsetting[0].endpoint[isoc_pipe].desc.
+ bEndpointAddress;
+
+ dev->vbi_mode.num_alt = uif->num_altsetting;
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->vbi_mode.end_point_addr,
+ dev->vbi_mode.num_alt);
+
+ /* compute alternate max packet sizes for vbi */
+ dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
+ if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dev->vbi_mode.num_alt; i++) {
+ u16 tmp =
+ le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+ desc.wMaxPacketSize);
+ dev->vbi_mode.alt_max_pkt_size[i] =
+ (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->vbi_mode.alt_max_pkt_size[i]);
+ }
+
+ /* Sliced CC VBI init */
+
+ /* compute alternate max packet sizes for sliced CC */
+ idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
+ if (idx >= dev->max_iad_interface_count) {
+ cx231xx_errdev("Sliced CC PCB interface #%d doesn't exist\n", idx);
+ return -ENODEV;
+ }
+ uif = udev->actconfig->interface[idx];
+
+ dev->sliced_cc_mode.end_point_addr =
+ uif->altsetting[0].endpoint[isoc_pipe].desc.
+ bEndpointAddress;
+
+ dev->sliced_cc_mode.num_alt = uif->num_altsetting;
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->sliced_cc_mode.end_point_addr,
+ dev->sliced_cc_mode.num_alt);
+ dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
+
+ if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
+ u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+ desc.wMaxPacketSize);
+ dev->sliced_cc_mode.alt_max_pkt_size[i] =
+ (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->sliced_cc_mode.alt_max_pkt_size[i]);
+ }
+
+ return 0;
+}
+
/*
* cx231xx_usb_probe()
* checks for supported devices
@@ -1135,6 +1391,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
int nr = 0, ifnum;
int i, isoc_pipe = 0;
char *speed;
+ u8 idx;
struct usb_interface_assoc_descriptor *assoc_desc;
ifnum = interface->altsetting[0].desc.bInterfaceNumber;
@@ -1157,16 +1414,16 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
}
} while (test_and_set_bit(nr, &cx231xx_devused));
+ udev = usb_get_dev(interface_to_usbdev(interface));
+
/* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
cx231xx_err(DRIVER_NAME ": out of memory!\n");
clear_bit(nr, &cx231xx_devused);
return -ENOMEM;
}
- udev = usb_get_dev(interface_to_usbdev(interface));
-
snprintf(dev->name, 29, "cx231xx #%d", nr);
dev->devno = nr;
dev->model = id->driver_info;
@@ -1185,8 +1442,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
dev->vbi_or_sliced_cc_mode = 0;
/* get maximum no.of IAD interfaces */
- assoc_desc = udev->actconfig->intf_assoc[0];
- dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
+ dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
/* init CIR module TBD */
@@ -1238,120 +1494,31 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
- /*
- * AV device initialization - only done at the last interface
- */
-
/* Create v4l2 device */
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
if (retval) {
cx231xx_errdev("v4l2_device_register failed\n");
- retval = -EIO;
goto err_v4l2;
}
+
/* allocate device struct */
retval = cx231xx_init_dev(dev, udev, nr);
if (retval)
goto err_init;
- /* compute alternate max packet sizes for video */
- uif = udev->actconfig->interface[dev->current_pcb_config.
- hs_config_info[0].interface_info.video_index + 1];
-
- dev->video_mode.end_point_addr = uif->altsetting[0].
- endpoint[isoc_pipe].desc.bEndpointAddress;
-
- dev->video_mode.num_alt = uif->num_altsetting;
- cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->video_mode.end_point_addr,
- dev->video_mode.num_alt);
- dev->video_mode.alt_max_pkt_size =
- kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL);
-
- if (dev->video_mode.alt_max_pkt_size == NULL) {
- cx231xx_errdev("out of memory!\n");
- retval = -ENOMEM;
- goto err_video_alt;
- }
-
- for (i = 0; i < dev->video_mode.num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
- desc.wMaxPacketSize);
- dev->video_mode.alt_max_pkt_size[i] =
- (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- cx231xx_info("Alternate setting %i, max size= %i\n", i,
- dev->video_mode.alt_max_pkt_size[i]);
- }
-
- /* compute alternate max packet sizes for vbi */
- uif = udev->actconfig->interface[dev->current_pcb_config.
- hs_config_info[0].interface_info.
- vanc_index + 1];
-
- dev->vbi_mode.end_point_addr =
- uif->altsetting[0].endpoint[isoc_pipe].desc.
- bEndpointAddress;
-
- dev->vbi_mode.num_alt = uif->num_altsetting;
- cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->vbi_mode.end_point_addr,
- dev->vbi_mode.num_alt);
- dev->vbi_mode.alt_max_pkt_size =
- kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL);
-
- if (dev->vbi_mode.alt_max_pkt_size == NULL) {
- cx231xx_errdev("out of memory!\n");
- retval = -ENOMEM;
- goto err_vbi_alt;
- }
-
- for (i = 0; i < dev->vbi_mode.num_alt; i++) {
- u16 tmp =
- le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
- desc.wMaxPacketSize);
- dev->vbi_mode.alt_max_pkt_size[i] =
- (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- cx231xx_info("Alternate setting %i, max size= %i\n", i,
- dev->vbi_mode.alt_max_pkt_size[i]);
- }
-
- /* compute alternate max packet sizes for sliced CC */
- uif = udev->actconfig->interface[dev->current_pcb_config.
- hs_config_info[0].interface_info.
- hanc_index + 1];
-
- dev->sliced_cc_mode.end_point_addr =
- uif->altsetting[0].endpoint[isoc_pipe].desc.
- bEndpointAddress;
-
- dev->sliced_cc_mode.num_alt = uif->num_altsetting;
- cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->sliced_cc_mode.end_point_addr,
- dev->sliced_cc_mode.num_alt);
- dev->sliced_cc_mode.alt_max_pkt_size =
- kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL);
-
- if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
- cx231xx_errdev("out of memory!\n");
- retval = -ENOMEM;
- goto err_sliced_cc_alt;
- }
-
- for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
- desc.wMaxPacketSize);
- dev->sliced_cc_mode.alt_max_pkt_size[i] =
- (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- cx231xx_info("Alternate setting %i, max size= %i\n", i,
- dev->sliced_cc_mode.alt_max_pkt_size[i]);
- }
+ retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
+ if (retval)
+ goto err_init;
if (dev->current_pcb_config.ts1_source != 0xff) {
/* compute alternate max packet sizes for TS1 */
- uif = udev->actconfig->interface[dev->current_pcb_config.
- hs_config_info[0].
- interface_info.
- ts1_index + 1];
+ idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
+ if (idx >= dev->max_iad_interface_count) {
+ cx231xx_errdev("TS1 PCB interface #%d doesn't exist\n", idx);
+ retval = -ENODEV;
+ goto err_video_alt;
+ }
+ uif = udev->actconfig->interface[idx];
dev->ts1_mode.end_point_addr =
uif->altsetting[0].endpoint[isoc_pipe].
@@ -1361,13 +1528,12 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
dev->ts1_mode.end_point_addr,
dev->ts1_mode.num_alt);
- dev->ts1_mode.alt_max_pkt_size =
- kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL);
+ dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
if (dev->ts1_mode.alt_max_pkt_size == NULL) {
cx231xx_errdev("out of memory!\n");
retval = -ENOMEM;
- goto err_ts1_alt;
+ goto err_video_alt;
}
for (i = 0; i < dev->ts1_mode.num_alt; i++) {
@@ -1394,12 +1560,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
request_modules(dev);
return 0;
-err_ts1_alt:
- kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-err_sliced_cc_alt:
- kfree(dev->vbi_mode.alt_max_pkt_size);
-err_vbi_alt:
- kfree(dev->video_mode.alt_max_pkt_size);
err_video_alt:
/* cx231xx_uninit_dev: */
cx231xx_close_extension(dev);
@@ -1415,7 +1575,6 @@ err_v4l2:
err_if:
usb_put_dev(udev);
clear_bit(dev->devno, &cx231xx_devused);
- kfree(dev);
return retval;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index 4ba3ce09b713..513194aa6561 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -726,6 +726,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
break;
case CX231XX_BOARD_HAUPPAUGE_EXETER:
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_DIGITAL);
break;
@@ -744,6 +745,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_HAUPPAUGE_EXETER:
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
@@ -1379,6 +1381,7 @@ int cx231xx_dev_init(struct cx231xx *dev)
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_HAUPPAUGE_EXETER:
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index 4504bc6a700b..1fa79741d199 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -32,7 +32,9 @@
#include "tda18271.h"
#include "s5h1411.h"
#include "lgdt3305.h"
+#include "si2165.h"
#include "mb86a20s.h"
+#include "si2157.h"
MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
@@ -67,6 +69,7 @@ struct cx231xx_dvb {
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
struct dvb_net net;
+ struct i2c_client *i2c_client_tuner;
};
static struct s5h1432_config dvico_s5h1432_config = {
@@ -151,6 +154,18 @@ static struct tda18271_config pv_tda18271_config = {
.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
};
+static const struct si2165_config hauppauge_930C_HD_1113xx_si2165_config = {
+ .i2c_addr = 0x64,
+ .chip_mode = SI2165_MODE_PLL_XTAL,
+ .ref_freq_Hz = 16000000,
+};
+
+static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = {
+ .i2c_addr = 0x64,
+ .chip_mode = SI2165_MODE_PLL_EXT,
+ .ref_freq_Hz = 24000000,
+};
+
static inline void print_err_status(struct cx231xx *dev, int packet, int status)
{
char *errmsg = "Unknown";
@@ -549,11 +564,18 @@ fail_adapter:
static void unregister_dvb(struct cx231xx_dvb *dvb)
{
+ struct i2c_client *client;
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
dvb_dmxdev_release(&dvb->dmxdev);
dvb_dmx_release(&dvb->demux);
+ client = dvb->i2c_client_tuner;
+ /* remove I2C tuner */
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
dvb_unregister_frontend(dvb->frontend);
dvb_frontend_detach(dvb->frontend);
dvb_unregister_adapter(&dvb->adapter);
@@ -704,6 +726,89 @@ static int dvb_init(struct cx231xx *dev)
&hcw_tda18271_config);
break;
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
+
+ dev->dvb->frontend = dvb_attach(si2165_attach,
+ &hauppauge_930C_HD_1113xx_si2165_config,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
+ );
+
+ if (dev->dvb->frontend == NULL) {
+ printk(DRIVER_NAME
+ ": Failed to attach SI2165 front end\n");
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ dev->dvb->frontend->ops.i2c_gate_ctrl = 0;
+
+ /* define general-purpose callback pointer */
+ dvb->frontend->callback = cx231xx_tuner_callback;
+
+ dvb_attach(tda18271_attach, dev->dvb->frontend,
+ 0x60,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+ &hcw_tda18271_config);
+
+ dev->cx231xx_reset_analog_tuner = NULL;
+ break;
+
+ case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+ {
+ struct i2c_client *client;
+ struct i2c_board_info info;
+ struct si2157_config si2157_config;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+
+ dev->dvb->frontend = dvb_attach(si2165_attach,
+ &pctv_quatro_stick_1114xx_si2165_config,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
+ );
+
+ if (dev->dvb->frontend == NULL) {
+ printk(DRIVER_NAME
+ ": Failed to attach SI2165 front end\n");
+ result = -EINVAL;
+ goto out_free;
+ }
+
+ dev->dvb->frontend->ops.i2c_gate_ctrl = 0;
+
+ /* define general-purpose callback pointer */
+ dvb->frontend->callback = cx231xx_tuner_callback;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = dev->dvb->frontend;
+ si2157_config.inversion = true;
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module("si2157");
+
+ client = i2c_new_device(
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+ &info);
+ if (client == NULL || client->dev.driver == NULL) {
+ dvb_frontend_detach(dev->dvb->frontend);
+ result = -ENODEV;
+ goto out_free;
+ }
+
+ if (!try_module_get(client->dev.driver->owner)) {
+ i2c_unregister_device(client);
+ dvb_frontend_detach(dev->dvb->frontend);
+ result = -ENODEV;
+ goto out_free;
+ }
+
+ dev->cx231xx_reset_analog_tuner = NULL;
+
+ dev->dvb->i2c_client_tuner = client;
+ break;
+ }
+
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 46d52fac8680..05f0434919d4 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -21,11 +21,12 @@
#include "cx231xx.h"
#include <linux/usb.h>
#include <linux/slab.h>
+#include <linux/bitrev.h>
#define MODULE_NAME "cx231xx-input"
-static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
- u32 *ir_raw)
+static int get_key_isdbt(struct IR_i2c *ir, enum rc_type *protocol,
+ u32 *pscancode, u8 *toggle)
{
int rc;
u8 cmd, scancode;
@@ -46,21 +47,14 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
if (cmd == 0xff)
return 0;
- scancode =
- ((cmd & 0x01) ? 0x80 : 0) |
- ((cmd & 0x02) ? 0x40 : 0) |
- ((cmd & 0x04) ? 0x20 : 0) |
- ((cmd & 0x08) ? 0x10 : 0) |
- ((cmd & 0x10) ? 0x08 : 0) |
- ((cmd & 0x20) ? 0x04 : 0) |
- ((cmd & 0x40) ? 0x02 : 0) |
- ((cmd & 0x80) ? 0x01 : 0);
+ scancode = bitrev8(cmd);
dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n",
cmd, scancode);
- *ir_key = scancode;
- *ir_raw = scancode;
+ *protocol = RC_TYPE_OTHER;
+ *pscancode = scancode;
+ *toggle = 0;
return 1;
}
@@ -97,7 +91,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
dev->init_data.get_key = get_key_isdbt;
dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
/* The i2c micro-controller only outputs the cmd part of NEC protocol */
- dev->init_data.rc_dev->scanmask = 0xff;
+ dev->init_data.rc_dev->scancode_mask = 0xff;
dev->init_data.rc_dev->driver_name = "cx231xx";
dev->init_data.type = RC_BIT_NEC;
info.addr = 0x30;
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
index 2a34ceee4802..3052c4c20229 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
@@ -654,8 +654,9 @@ static struct pcb_config cx231xx_Scenario[] = {
/*****************************************************************/
-u32 initialize_cx231xx(struct cx231xx *dev)
+int initialize_cx231xx(struct cx231xx *dev)
{
+ int retval;
u32 config_info = 0;
struct pcb_config *p_pcb_info;
u8 usb_speed = 1; /* from register,1--HS, 0--FS */
@@ -670,7 +671,10 @@ u32 initialize_cx231xx(struct cx231xx *dev)
/* read board config register to find out which
pcb config it is related to */
- cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
+ retval = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
+ data, 4);
+ if (retval < 0)
+ return retval;
config_info = le32_to_cpu(*((__le32 *)data));
usb_speed = (u8) (config_info & 0x1);
@@ -767,7 +771,7 @@ u32 initialize_cx231xx(struct cx231xx *dev)
cx231xx_info("bad senario!!!!!\n");
cx231xx_info("config_info=%x\n",
(config_info & SELFPOWER_MASK));
- return 1;
+ return -ENODEV;
}
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
index b3c6190e0c69..4511dc5d199c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
@@ -221,6 +221,6 @@ enum INDEX_PCB_CONFIG{
/***************************************************************************/
struct cx231xx;
-u32 initialize_cx231xx(struct cx231xx *p_dev);
+int initialize_cx231xx(struct cx231xx *p_dev);
#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 1f8751379e24..3b3ada6562ca 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -208,7 +208,7 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
- int i, rc = 1;
+ int i;
unsigned char *p_buffer;
u32 bytes_parsed = 0, buffer_size = 0;
u8 sav_eav = 0;
@@ -299,13 +299,12 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
bytes_parsed = 0;
}
- return rc;
+ return 1;
}
static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
- int rc = 1;
unsigned char *p_buffer;
u32 bytes_parsed = 0, buffer_size = 0;
u8 sav_eav = 0;
@@ -379,7 +378,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
bytes_parsed = 0;
}
- return rc;
+ return 1;
}
@@ -886,7 +885,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -931,7 +929,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1620,7 +1617,7 @@ static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner
*/
static int cx231xx_v4l2_open(struct file *filp)
{
- int errCode = 0, radio = 0;
+ int radio = 0;
struct video_device *vdev = video_devdata(filp);
struct cx231xx *dev = video_drvdata(filp);
struct cx231xx_fh *fh;
@@ -1718,7 +1715,7 @@ static int cx231xx_v4l2_open(struct file *filp)
mutex_unlock(&dev->lock);
v4l2_fh_add(&fh->fh);
- return errCode;
+ return 0;
}
/*
@@ -2066,7 +2063,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
vfd->release = video_device_release;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index babca7fb85e2..aeb1bf42b88d 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -73,6 +73,8 @@
#define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16
#define CX231XX_BOARD_OTG102 17
#define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18
+#define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19
+#define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20
/* Limits minimum and default number of buffers */
#define CX231XX_MIN_BUF 4
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 037e519bbaa2..66645b02c854 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -129,6 +129,7 @@ config DVB_USB_RTL28XXU
depends on DVB_USB_V2 && I2C_MUX
select DVB_RTL2830
select DVB_RTL2832
+ select DVB_RTL2832_SDR if (MEDIA_SUBDRV_AUTOSELECT && MEDIA_SDR_SUPPORT)
select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index da47d2392f2a..5ca738ab44e0 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1213,7 +1213,7 @@ static int af9015_rc_query(struct dvb_usb_device *d)
if ((state->rc_repeat != buf[6] || buf[0]) &&
!memcmp(&buf[12], state->rc_last, 4)) {
dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__);
- rc_keydown(d->rc_dev, state->rc_keycode, 0);
+ rc_repeat(d->rc_dev);
state->rc_repeat = buf[6];
return ret;
}
@@ -1233,18 +1233,22 @@ static int af9015_rc_query(struct dvb_usb_device *d)
if (buf[14] == (u8) ~buf[15]) {
if (buf[12] == (u8) ~buf[13]) {
/* NEC */
- state->rc_keycode = buf[12] << 8 | buf[14];
+ state->rc_keycode = RC_SCANCODE_NEC(buf[12],
+ buf[14]);
} else {
/* NEC extended*/
- state->rc_keycode = buf[12] << 16 |
- buf[13] << 8 | buf[14];
+ state->rc_keycode = RC_SCANCODE_NECX(buf[12] << 8 |
+ buf[13],
+ buf[14]);
}
} else {
/* 32 bit NEC */
- state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
- buf[14] << 8 | buf[15];
+ state->rc_keycode = RC_SCANCODE_NEC32(buf[12] << 24 |
+ buf[13] << 16 |
+ buf[14] << 8 |
+ buf[15]);
}
- rc_keydown(d->rc_dev, state->rc_keycode, 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0);
} else {
dev_dbg(&d->udev->dev, "%s: no key press\n", __func__);
/* Invalidate last keypress */
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 7b9b75f60774..75ec1c659fdd 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -799,6 +799,25 @@ static int af9035_read_config(struct dvb_usb_device *d)
addr += 0x10; /* shift for the 2nd tuner params */
}
+ /*
+ * These AVerMedia devices has a bad EEPROM content :-(
+ * Override some wrong values here.
+ */
+ if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) {
+ switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
+ case USB_PID_AVERMEDIA_A835B_1835:
+ case USB_PID_AVERMEDIA_A835B_2835:
+ case USB_PID_AVERMEDIA_A835B_3835:
+ dev_info(&d->udev->dev,
+ "%s: overriding tuner from %02x to %02x\n",
+ KBUILD_MODNAME, state->af9033_config[0].tuner,
+ AF9033_TUNER_IT9135_60);
+
+ state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60;
+ break;
+ }
+ }
+
skip_eeprom:
/* get demod clock */
ret = af9035_rd_reg(d, 0x00d800, &tmp);
@@ -1313,19 +1332,20 @@ static int af9035_rc_query(struct dvb_usb_device *d)
if ((buf[2] + buf[3]) == 0xff) {
if ((buf[0] + buf[1]) == 0xff) {
/* NEC standard 16bit */
- key = buf[0] << 8 | buf[2];
+ key = RC_SCANCODE_NEC(buf[0], buf[2]);
} else {
/* NEC extended 24bit */
- key = buf[0] << 16 | buf[1] << 8 | buf[2];
+ key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]);
}
} else {
/* NEC full code 32bit */
- key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+ key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
+ buf[2] << 8 | buf[3]);
}
dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf);
- rc_keydown(d->rc_dev, key, 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC, key, 0);
return 0;
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index eeab79bdd2aa..e4a2382196f0 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -1038,7 +1038,8 @@ static int anysee_rc_query(struct dvb_usb_device *d)
if (ircode[0]) {
dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__,
ircode[1]);
- rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC,
+ RC_SCANCODE_NEC(0x08, ircode[1]), 0);
}
return 0;
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index c3c4b98733bf..935dbaa80ef0 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -207,24 +207,27 @@ static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff)
static int az6007_rc_query(struct dvb_usb_device *d)
{
struct az6007_device_state *st = d_to_priv(d);
- unsigned code = 0;
+ unsigned code;
az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
if (st->data[1] == 0x44)
return 0;
- if ((st->data[1] ^ st->data[2]) == 0xff)
- code = st->data[1];
- else
- code = st->data[1] << 8 | st->data[2];
-
- if ((st->data[3] ^ st->data[4]) == 0xff)
- code = code << 8 | st->data[3];
- else
- code = code << 16 | st->data[3] << 8 | st->data[4];
+ if ((st->data[3] ^ st->data[4]) == 0xff) {
+ if ((st->data[1] ^ st->data[2]) == 0xff)
+ code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
+ else
+ code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
+ st->data[3]);
+ } else {
+ code = RC_SCANCODE_NEC32(st->data[1] << 24 |
+ st->data[2] << 16 |
+ st->data[3] << 8 |
+ st->data[4]);
+ }
- rc_keydown(d->rc_dev, code, st->data[5]);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC, code, st->data[5]);
return 0;
}
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 e35580618936..2e90310be2af 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d)
dev->driver_name = (char *) d->props->driver_name;
dev->map_name = d->rc.map_name;
dev->driver_type = d->rc.driver_type;
- rc_set_allowed_protocols(dev, d->rc.allowed_protos);
+ dev->allowed_protocols = d->rc.allowed_protos;
dev->change_protocol = d->rc.change_protocol;
dev->priv = d;
@@ -253,13 +253,6 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
return usb_urb_exitv2(&adap->stream);
}
-static int wait_schedule(void *ptr)
-{
- schedule();
-
- return 0;
-}
-
static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
@@ -273,8 +266,7 @@ static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
dvbdmxfeed->pid, dvbdmxfeed->index);
/* wait init is done */
- wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
- TASK_UNINTERRUPTIBLE);
+ wait_on_bit(&adap->state_bits, ADAP_INIT, TASK_UNINTERRUPTIBLE);
if (adap->active_fe == -1)
return -EINVAL;
@@ -568,7 +560,7 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
if (!adap->suspend_resume_active) {
set_bit(ADAP_SLEEP, &adap->state_bits);
- wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule,
+ wait_on_bit(&adap->state_bits, ADAP_STREAMING,
TASK_UNINTERRUPTIBLE);
}
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index f674dc024d06..e332af731187 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -125,14 +125,13 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define TUNER_RS2000 0x4
struct lme2510_state {
+ unsigned long int_urb_due;
u8 id;
u8 tuner_config;
u8 signal_lock;
u8 signal_level;
u8 signal_sn;
u8 time_key;
- u8 last_key;
- u8 key_timeout;
u8 i2c_talk_onoff;
u8 i2c_gate;
u8 i2c_tuner_gate_w;
@@ -287,14 +286,13 @@ static void lme2510_int_response(struct urb *lme_urb)
case 0xaa:
debug_data_snipet(1, "INT Remote data snipet", ibuf);
if ((ibuf[4] + ibuf[5]) == 0xff) {
- key = ibuf[5];
- key += (ibuf[3] > 0)
- ? (ibuf[3] ^ 0xff) << 8 : 0;
- key += (ibuf[2] ^ 0xff) << 16;
+ key = RC_SCANCODE_NECX((ibuf[2] ^ 0xff) << 8 |
+ (ibuf[3] > 0) ? (ibuf[3] ^ 0xff) : 0,
+ ibuf[5]);
deb_info(1, "INT Key =%08x", key);
if (adap_to_d(adap)->rc_dev != NULL)
rc_keydown(adap_to_d(adap)->rc_dev,
- key, 0);
+ RC_TYPE_NEC, key, 0);
}
break;
case 0xbb:
@@ -323,7 +321,7 @@ static void lme2510_int_response(struct urb *lme_urb)
}
break;
case TUNER_RS2000:
- if (ibuf[1] == 0x3 && ibuf[6] == 0xff)
+ if (ibuf[2] & 0x1)
st->signal_lock = 0xff;
else
st->signal_lock = 0x00;
@@ -343,7 +341,12 @@ static void lme2510_int_response(struct urb *lme_urb)
break;
}
}
+
usb_submit_urb(lme_urb, GFP_ATOMIC);
+
+ /* interrupt urb is due every 48 msecs while streaming
+ * add 12msecs for system lag */
+ st->int_urb_due = jiffies + msecs_to_jiffies(60);
}
static int lme2510_int_read(struct dvb_usb_adapter *adap)
@@ -584,14 +587,13 @@ static int lme2510_msg(struct dvb_usb_device *d,
switch (wbuf[3]) {
case 0x8c:
rbuf[0] = 0x55;
- rbuf[1] = 0xff;
- if (st->last_key == st->time_key) {
- st->key_timeout++;
- if (st->key_timeout > 5)
- rbuf[1] = 0;
- } else
- st->key_timeout = 0;
- st->last_key = st->time_key;
+ rbuf[1] = st->signal_lock;
+
+ /* If int_urb_due overdue
+ * set rbuf[1] to 0 to clear lock */
+ if (time_after(jiffies, st->int_urb_due))
+ rbuf[1] = 0;
+
break;
default:
lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index c7304fa8ab73..b8a707e57b99 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -129,7 +129,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
u8 addr, u8 mask, u8 data)
{
int ret;
- u8 val;
+ u8 val = 0;
if (mask != 0xff) {
ret = mxl111sf_read_reg(state, addr, &val);
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index a676e4452847..27b1e0397e71 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1287,19 +1287,19 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
if (buf[2] == (u8) ~buf[3]) {
if (buf[0] == (u8) ~buf[1]) {
/* NEC standard (16 bit) */
- rc_code = buf[0] << 8 | buf[2];
+ rc_code = RC_SCANCODE_NEC(buf[0], buf[2]);
} else {
/* NEC extended (24 bit) */
- rc_code = buf[0] << 16 |
- buf[1] << 8 | buf[2];
+ rc_code = RC_SCANCODE_NECX(buf[0] << 8 | buf[1],
+ buf[2]);
}
} else {
/* NEC full (32 bit) */
- rc_code = buf[0] << 24 | buf[1] << 16 |
- buf[2] << 8 | buf[3];
+ rc_code = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 |
+ buf[2] << 8 | buf[3]);
}
- rc_keydown(d->rc_dev, rc_code, 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
if (ret)
@@ -1541,6 +1541,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
&rtl2832u_props, "Peak DVB-T USB", NULL) },
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U,
&rtl2832u_props, "Sveon STV20", NULL) },
+ { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21,
+ &rtl2832u_props, "Sveon STV21", NULL) },
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27,
&rtl2832u_props, "Sveon STV27", NULL) },
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index c5d95662e2e1..10aef2188fbe 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -117,10 +117,12 @@ config DVB_USB_CXUSB
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT
select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -128,6 +130,7 @@ config DVB_USB_CXUSB
Medion MD95700 hybrid USB2.0 device.
DViCO FusionHDTV (Bluebird) USB2.0 devices
+ TechnoTrend TVStick CT2-4400
config DVB_USB_M920X
tristate "Uli m920x DVB-T USB2.0 support"
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index a1c641e18362..16bc579d1404 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -42,9 +42,11 @@
#include "dib0070.h"
#include "lgs8gxx.h"
#include "atbm8830.h"
+#include "si2168.h"
+#include "si2157.h"
/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE 64
+#define MAX_XFER_SIZE 80
/* debug */
static int dvb_usb_cxusb_debug;
@@ -144,6 +146,22 @@ static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
}
}
+static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff)
+{
+ u8 o[2], i;
+ int rc;
+
+ o[0] = 0x83;
+ o[1] = onoff;
+ rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+ if (rc) {
+ deb_info("gpio_write failed.\n");
+ return -EIO;
+ }
+ return 0;
+}
+
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@@ -505,6 +523,30 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
return 0;
}
+static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d)
+{
+ u8 i[2];
+ int ret;
+ u32 cmd, keycode;
+ u8 rc5_cmd, rc5_addr, rc5_toggle;
+
+ ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2);
+ if (ret)
+ return ret;
+
+ cmd = (i[0] << 8) | i[1];
+
+ if (cmd != 0xffff) {
+ rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */
+ rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */
+ rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */
+ keycode = (rc5_addr << 8) | rc5_cmd;
+ rc_keydown(d->rc_dev, RC_BIT_RC5, keycode, rc5_toggle);
+ }
+
+ return 0;
+}
+
static struct rc_map_table rc_map_dvico_mce_table[] = {
{ 0xfe02, KEY_TV },
{ 0xfe0e, KEY_MP3 },
@@ -1070,8 +1112,15 @@ static struct dib7000p_config cxusb_dualdig4_rev2_config = {
.hostbus_diversity = 1,
};
+struct dib0700_adapter_state {
+ int (*set_param_save)(struct dvb_frontend *);
+ struct dib7000p_ops dib7000p_ops;
+};
+
static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
err("set interface failed");
@@ -1079,14 +1128,17 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
- &cxusb_dualdig4_rev2_config) < 0) {
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ &cxusb_dualdig4_rev2_config) < 0) {
printk(KERN_WARNING "Unable to enumerate dib7000p\n");
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
- &cxusb_dualdig4_rev2_config);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
+ &cxusb_dualdig4_rev2_config);
if (adap->fe_adap[0].fe == NULL)
return -EIO;
@@ -1095,7 +1147,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
{
- return dib7000p_set_gpio(fe, 8, 0, !onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
}
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
@@ -1110,10 +1165,6 @@ static struct dib0070_config dib7070p_dib0070_config = {
.clock_khz = 12000,
};
-struct dib0700_adapter_state {
- int (*set_param_save) (struct dvb_frontend *);
-};
-
static int dib7070_set_param_override(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -1128,7 +1179,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
case BAND_UHF: offset = 550; break;
}
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
@@ -1136,8 +1187,14 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c =
- dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ struct i2c_adapter *tun_i2c;
+
+ /*
+ * No need to call dvb7000p_attach here, as it was called
+ * already, as frontend_attach method is called first, and
+ * tuner_attach is only called on sucess.
+ */
+ tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
@@ -1286,6 +1343,74 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct cxusb_state *st = d->priv;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
+ struct i2c_board_info info;
+ struct si2168_config si2168_config;
+ struct si2157_config si2157_config;
+
+ /* reset the tuner */
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) {
+ err("clear tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) {
+ err("set tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+
+ /* attach frontend */
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &adap->fe_adap[0].fe;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&d->i2c_adap, &info);
+ if (client_demod == NULL || client_demod->dev.driver == NULL)
+ return -ENODEV;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = adap->fe_adap[0].fe;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(adapter, &info);
+ if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_tuner = client_tuner;
+
+ return 0;
+}
+
/*
* DViCO has shipped two devices with the same USB ID, but only one of them
* needs a firmware download. Check the device class details to see if they
@@ -1367,6 +1492,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -1397,12 +1523,37 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
0)
return 0;
return -EINVAL;
}
+static void cxusb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+ struct cxusb_state *st = d->priv;
+ struct i2c_client *client;
+
+ /* remove I2C client for tuner */
+ client = st->i2c_client_tuner;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ /* remove I2C client for demodulator */
+ client = st->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ dvb_usb_device_exit(intf);
+}
+
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
@@ -1424,6 +1575,7 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
+ { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2070,10 +2222,63 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
}
};
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ /* both frontend and tuner attached in the
+ same function */
+ .frontend_attach = cxusb_tt_ct2_4400_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ } },
+ },
+ },
+
+ .i2c_algo = &cxusb_i2c_algo,
+ .generic_bulk_ctrl_endpoint = 0x01,
+ .generic_bulk_ctrl_endpoint_response = 0x81,
+
+ .rc.core = {
+ .rc_codes = RC_MAP_TT_1500,
+ .allowed_protos = RC_BIT_RC5,
+ .rc_query = cxusb_tt_ct2_4400_rc_query,
+ .rc_interval = 150,
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ "TechnoTrend TVStick CT2-4400",
+ { NULL },
+ { &cxusb_table[20], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = cxusb_disconnect,
.id_table = cxusb_table,
};
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h
index 1a51eafd31b9..527ff7905e15 100644
--- a/drivers/media/usb/dvb-usb/cxusb.h
+++ b/drivers/media/usb/dvb-usb/cxusb.h
@@ -30,6 +30,8 @@
struct cxusb_state {
u8 gpio_write_state[3];
+ struct i2c_client *i2c_client_demod;
+ struct i2c_client *i2c_client_tuner;
};
#endif
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index c14285fa8271..50856dbf5496 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -658,13 +658,8 @@ out:
struct dib0700_rc_response {
u8 report_id;
u8 data_state;
- union {
- u16 system16;
- struct {
- u8 not_system;
- u8 system;
- };
- };
+ u8 system;
+ u8 not_system;
u8 data;
u8 not_data;
};
@@ -674,6 +669,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
{
struct dvb_usb_device *d = purb->context;
struct dib0700_rc_response *poll_reply;
+ enum rc_type protocol;
u32 uninitialized_var(keycode);
u8 toggle;
@@ -707,44 +703,55 @@ static void dib0700_rc_urb_completion(struct urb *purb)
switch (d->props.rc.core.protocol) {
case RC_BIT_NEC:
+ protocol = RC_TYPE_NEC;
toggle = 0;
/* NEC protocol sends repeat code as 0 0 0 FF */
- if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
- && (poll_reply->not_data == 0xff)) {
+ if (poll_reply->system == 0x00 &&
+ poll_reply->not_system == 0x00 &&
+ poll_reply->data == 0x00 &&
+ poll_reply->not_data == 0xff) {
poll_reply->data_state = 2;
break;
}
- if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
+ if ((poll_reply->data ^ poll_reply->not_data) != 0xff) {
+ deb_data("NEC32 protocol\n");
+ keycode = RC_SCANCODE_NEC32(poll_reply->system << 24 |
+ poll_reply->not_system << 16 |
+ poll_reply->data << 8 |
+ poll_reply->not_data);
+ } else if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
deb_data("NEC extended protocol\n");
- /* NEC extended code - 24 bits */
- keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data;
+ keycode = RC_SCANCODE_NECX(poll_reply->system << 8 |
+ poll_reply->not_system,
+ poll_reply->data);
+
} else {
deb_data("NEC normal protocol\n");
- /* normal NEC code - 16 bits */
- keycode = poll_reply->system << 8 | poll_reply->data;
+ keycode = RC_SCANCODE_NEC(poll_reply->system,
+ poll_reply->data);
}
break;
default:
deb_data("RC5 protocol\n");
- /* RC5 Protocol */
+ protocol = RC_TYPE_RC5;
toggle = poll_reply->report_id;
- keycode = poll_reply->system << 8 | poll_reply->data;
+ keycode = RC_SCANCODE_RC5(poll_reply->system, poll_reply->data);
break;
}
if ((poll_reply->data + poll_reply->not_data) != 0xff) {
/* Key failed integrity check */
- err("key failed integrity check: %04x %02x %02x",
- poll_reply->system,
+ err("key failed integrity check: %02x %02x %02x %02x",
+ poll_reply->system, poll_reply->not_system,
poll_reply->data, poll_reply->not_data);
goto resubmit;
}
- rc_keydown(d->rc_dev, keycode, toggle);
+ rc_keydown(d->rc_dev, protocol, keycode, toggle);
resubmit:
/* Clean the buffer before we requeue */
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 10e0db8d1850..ce47d3f1c850 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -32,6 +32,8 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif
struct dib0700_adapter_state {
int (*set_param_save) (struct dvb_frontend *);
const struct firmware *frontend_firmware;
+ struct dib7000p_ops dib7000p_ops;
+ struct dib8000_ops dib8000_ops;
};
/* Hauppauge Nova-T 500 (aka Bristol)
@@ -262,6 +264,11 @@ static struct mt2266_config stk7700d_mt2266_config[2] = {
static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (adap->id == 0) {
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
@@ -272,16 +279,16 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe =
- dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80 + (adap->id << 1),
&stk7700d_dib7000p_mt2266_config[adap->id]);
@@ -290,6 +297,11 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (adap->id == 0) {
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
@@ -301,16 +313,16 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe =
- dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80 + (adap->id << 1),
&stk7700d_dib7000p_mt2266_config[adap->id]);
@@ -320,7 +332,10 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct dib0700_adapter_state *state = adap->priv;
+
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
+ DIBX000_I2C_INTERFACE_TUNER, 1);
return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
}
@@ -397,12 +412,14 @@ static int stk7700ph_xc3028_callback(void *ptr, int component,
int command, int arg)
{
struct dvb_usb_adapter *adap = ptr;
+ struct dib0700_adapter_state *state = adap->priv;
switch (command) {
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+ msleep(10);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
break;
case XC2028_RESET_CLK:
break;
@@ -428,12 +445,16 @@ static struct xc2028_config stk7700ph_xc3028_config = {
static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(20);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
@@ -445,14 +466,15 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
msleep(10);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&stk7700ph_dib7700_xc3028_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&stk7700ph_dib7700_xc3028_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -461,8 +483,9 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
stk7700ph_xc3028_config.i2c_adap = tun_i2c;
@@ -489,7 +512,8 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
{
u8 key[4];
- u32 keycode;
+ enum rc_type protocol;
+ u32 scancode;
u8 toggle;
int i;
struct dib0700_state *st = d->priv;
@@ -516,28 +540,29 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */
- d->last_event = 0;
switch (d->props.rc.core.protocol) {
case RC_BIT_NEC:
/* NEC protocol sends repeat code as 0 0 0 FF */
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
- (key[3] == 0xff))
- keycode = d->last_event;
- else {
- keycode = key[3-2] << 8 | key[3-3];
- d->last_event = keycode;
+ (key[3] == 0xff)) {
+ rc_repeat(d->rc_dev);
+ return 0;
}
- rc_keydown(d->rc_dev, keycode, 0);
+ protocol = RC_TYPE_NEC;
+ scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]);
+ toggle = 0;
break;
+
default:
/* RC-5 protocol changes toggle bit on new keypress */
- keycode = key[3-2] << 8 | key[3-3];
+ protocol = RC_TYPE_RC5;
+ scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]);
toggle = key[3-1];
- rc_keydown(d->rc_dev, keycode, toggle);
-
break;
}
+
+ rc_keydown(d->rc_dev, protocol, scancode, toggle);
return 0;
}
@@ -673,6 +698,11 @@ static struct dib7000p_config stk7700p_dib7000p_config = {
static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
@@ -689,11 +719,13 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[0] = 1220;
- if (dib7000pc_detection(&adap->dev->i2c_adap)) {
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+ if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap)) {
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
st->is_dib7000pc = 1;
- } else
+ } else {
+ memset(&state->dib7000p_ops, 0, sizeof(state->dib7000p_ops));
adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+ }
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -707,14 +739,16 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
s8 a;
int if1=1220;
+
if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
@@ -767,14 +801,20 @@ static struct dibx000_agc_config dib7070_agc_config = {
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("reset: %d", onoff);
- return dib7000p_set_gpio(fe, 8, 0, !onoff);
+ return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
}
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("sleep: %d", onoff);
- return dib7000p_set_gpio(fe, 9, 0, onoff);
+ return state->dib7000p_ops.set_gpio(fe, 9, 0, onoff);
}
static struct dib0070_config dib7070p_dib0070_config[2] = {
@@ -818,7 +858,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
default: offset = 550; break;
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
@@ -832,39 +872,39 @@ static int dib7770_set_param_override(struct dvb_frontend *fe)
u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF:
- dib7000p_set_gpio(fe, 0, 0, 1);
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 1);
offset = 850;
break;
case BAND_UHF:
default:
- dib7000p_set_gpio(fe, 0, 0, 0);
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 0);
offset = 250;
break;
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
{
- struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
- &dib7770p_dib0070_config) == NULL)
- return -ENODEV;
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+ &dib7770p_dib0070_config) == NULL)
+ return -ENODEV;
- st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
- adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
- return 0;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+ return 0;
}
static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
@@ -882,28 +922,33 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
+ struct dib0700_adapter_state *state = adapter->priv;
struct dib0700_state *st = adapter->dev->priv;
+
if (st->is_dib7000pc)
- return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
struct dib0700_state *st = adapter->dev->priv;
+ struct dib0700_adapter_state *state = adapter->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+ return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+ return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -936,6 +981,11 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -954,14 +1004,15 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&dib7070p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&dib7070p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -988,6 +1039,11 @@ static struct dib7000p_config dib7770p_dib7000p_config = {
static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -1006,14 +1062,15 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&dib7770p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&dib7770p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -1161,12 +1218,18 @@ static struct dib8000_config dib807x_dib8000_config[2] = {
static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
{
- return dib8000_set_gpio(fe, 5, 0, !onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.set_gpio(fe, 5, 0, !onoff);
}
static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
- return dib8000_set_gpio(fe, 0, 0, onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.set_gpio(fe, 0, 0, onoff);
}
static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
@@ -1223,7 +1286,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe)
offset += 250; break;
}
deb_info("WBD for DiB8000: %d\n", offset);
- dib8000_set_wbd_ref(fe, offset);
+ state->dib8000_ops.set_wbd_ref(fe, offset);
return state->set_param_save(fe);
}
@@ -1231,7 +1294,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe)
static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
@@ -1252,18 +1315,27 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
- return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+
+ return state->dib8000_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff)
{
- return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+
+ return state->dib8000_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
/* STK807x */
static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1279,10 +1351,10 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1291,6 +1363,11 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
/* STK807xPVR */
static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(30);
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -1309,9 +1386,9 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1319,10 +1396,15 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
/* initialize IC 1 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1331,104 +1413,121 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
/* STK8096GP */
static struct dibx000_agc_config dib8090_agc_config[2] = {
{
- BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+ .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
- (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
- 787,
- 10,
-
- 0,
- 118,
-
- 0,
- 3530,
- 1,
- 5,
+ .inv_gain = 787,
+ .time_stabiliz = 10,
- 65535,
- 0,
+ .alpha_level = 0,
+ .thlock = 118,
- 65535,
- 0,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
- 0,
- 32,
- 114,
- 143,
- 144,
- 114,
- 227,
- 116,
- 117,
+ .agc1_max = 65535,
+ .agc1_min = 0,
- 28,
- 26,
- 31,
- 51,
+ .agc2_max = 65535,
+ .agc2_min = 0,
- 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 32,
+ .agc1_pt3 = 114,
+ .agc1_slope1 = 143,
+ .agc1_slope2 = 144,
+ .agc2_pt1 = 114,
+ .agc2_pt2 = 227,
+ .agc2_slope1 = 116,
+ .agc2_slope2 = 117,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
},
{
- BAND_CBAND,
+ .band_caps = BAND_CBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
- (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
- 787,
- 10,
+ .inv_gain = 787,
+ .time_stabiliz = 10,
- 0,
- 118,
+ .alpha_level = 0,
+ .thlock = 118,
- 0,
- 3530,
- 1,
- 5,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
- 0,
- 0,
+ .agc1_max = 0,
+ .agc1_min = 0,
- 65535,
- 0,
-
- 0,
- 32,
- 114,
- 143,
- 144,
- 114,
- 227,
- 116,
- 117,
-
- 28,
- 26,
- 31,
- 51,
+ .agc2_max = 65535,
+ .agc2_min = 0,
- 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 32,
+ .agc1_pt3 = 114,
+ .agc1_slope1 = 143,
+ .agc1_slope2 = 144,
+ .agc2_pt1 = 114,
+ .agc2_pt2 = 227,
+ .agc2_slope1 = 116,
+ .agc2_slope2 = 117,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
}
};
static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
- 54000, 13500,
- 1, 18, 3, 1, 0,
- 0, 0, 1, 1, 2,
- (3 << 14) | (1 << 12) | (599 << 0),
- (0 << 25) | 0,
- 20199727,
- 12000000,
+ .internal = 54000,
+ .sampling = 13500,
+
+ .pll_prediv = 1,
+ .pll_ratio = 18,
+ .pll_range = 3,
+ .pll_reset = 1,
+ .pll_bypass = 0,
+
+ .enable_refdiv = 0,
+ .bypclk_div = 0,
+ .IO_CLK_en_core = 1,
+ .ADClkSrc = 1,
+ .modulo = 2,
+
+ .sad_cfg = (3 << 14) | (1 << 12) | (599 << 0),
+
+ .ifreq = (0 << 25) | 0,
+ .timf = 20199727,
+
+ .xtal_hz = 12000000,
};
static int dib8090_get_adc_power(struct dvb_frontend *fe)
{
- return dib8000_get_adc_power(fe, 1);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.get_adc_power(fe, 1);
}
static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart)
@@ -1551,10 +1650,10 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
default:
deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency);
case BAND_VHF:
- dib8000_set_gpio(fe, 3, 0, 1);
+ state->dib8000_ops.set_gpio(fe, 3, 0, 1);
break;
case BAND_UHF:
- dib8000_set_gpio(fe, 3, 0, 0);
+ state->dib8000_ops.set_gpio(fe, 3, 0, 0);
break;
}
@@ -1568,7 +1667,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
}
/** Update PLL if needed ratio **/
- dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
/** Get optimize PLL ratio to remove spurious **/
pll_ratio = dib8090_compute_pll_parameters(fe);
@@ -1582,14 +1681,14 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
timf = 18179756;
/** Update ratio **/
- dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
+ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
- dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, timf);
+ state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, timf);
if (band != BAND_CBAND) {
/* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */
target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
- dib8000_set_wbd_ref(fe, target);
+ state->dib8000_ops.set_wbd_ref(fe, target);
}
if (band == BAND_CBAND) {
@@ -1601,18 +1700,18 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
msleep(ret);
tune_state = dib0090_get_tune_state(fe);
if (tune_state == CT_AGC_STEP_0)
- dib8000_set_gpio(fe, 6, 0, 1);
+ state->dib8000_ops.set_gpio(fe, 6, 0, 1);
else if (tune_state == CT_AGC_STEP_1) {
dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */
- dib8000_set_gpio(fe, 6, 0, 0);
+ state->dib8000_ops.set_gpio(fe, 6, 0, 0);
}
} while (tune_state < CT_AGC_STOP);
deb_info("switching to PWM AGC\n");
dib0090_pwm_gain_reset(fe);
- dib8000_pwm_agc_reset(fe);
- dib8000_set_tune_state(fe, CT_DEMOD_START);
+ state->dib8000_ops.pwm_agc_reset(fe);
+ state->dib8000_ops.set_tune_state(fe, CT_DEMOD_START);
} else {
/* for everything else than CBAND we are using standard AGC */
deb_info("not tuning in CBAND - standard AGC startup\n");
@@ -1625,7 +1724,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
@@ -1637,6 +1736,11 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1652,9 +1756,9 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -1663,16 +1767,16 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c;
- struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
+ struct dvb_frontend *fe_slave = st->dib8000_ops.get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave) {
- tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = st->dib8000_ops.get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
fe_slave->dvb = adap->fe_adap[0].fe->dvb;
fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
}
- tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
@@ -1685,6 +1789,10 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe_slave;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(20);
@@ -1703,14 +1811,18 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
- dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
+ /* Needed to increment refcount */
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
+ fe_slave = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
+ state->dib8000_ops.set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1845,7 +1957,7 @@ static struct dib0090_wbd_slope dib8096p_wbd_table[] = {
{ 0xFFFF, 0, 0, 0, 0, 0},
};
-static const struct dib0090_config tfe8096p_dib0090_config = {
+static struct dib0090_config tfe8096p_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -1853,8 +1965,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib8096p_tuner_sleep,
- .sleep = dib8096p_tuner_sleep,
.freq_offset_khz_uhf = -143,
.freq_offset_khz_vhf = -143,
@@ -1871,8 +1981,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = {
.fref_clock_ratio = 1,
- .wbd = dib8096p_wbd_table,
-
.ls_cfg_pad_drv = 0,
.data_tx_drv = 0,
.low_if = NULL,
@@ -1983,15 +2091,15 @@ static int dib8096p_agc_startup(struct dvb_frontend *fe)
/* dib0090_get_wbd_target is returning any possible
temperature compensated wbd-target */
target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
- dib8000_set_wbd_ref(fe, target);
+ state->dib8000_ops.set_wbd_ref(fe, target);
if (dib8096p_get_best_sampling(fe, &adc) == 0) {
pll.pll_ratio = adc.pll_loopdiv;
pll.pll_prediv = adc.pll_prediv;
dib0700_set_i2c_speed(adap->dev, 200);
- dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
- dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+ state->dib8000_ops.update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+ state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
dib0700_set_i2c_speed(adap->dev, 1000);
}
return 0;
@@ -2001,6 +2109,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
u32 fw_version;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
if (fw_version >= 0x10200)
@@ -2021,10 +2133,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
- &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap,
+ 0x80, &tfe8096p_dib8000_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -2032,13 +2144,17 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe8096p_dib0090_config.reset = st->dib8000_ops.tuner_sleep;
+ tfe8096p_dib0090_config.sleep = st->dib8000_ops.tuner_sleep;
+ tfe8096p_dib0090_config.wbd = dib8096p_wbd_table;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
&tfe8096p_dib0090_config) == NULL)
return -ENODEV;
- dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib8000_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
@@ -2479,14 +2595,14 @@ static int dib7090_agc_startup(struct dvb_frontend *fe)
memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
dib0090_pwm_gain_reset(fe);
target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
- dib7000p_set_wbd_ref(fe, target);
+ state->dib7000p_ops.set_wbd_ref(fe, target);
if (dib7090p_get_best_sampling(fe, &adc) == 0) {
pll.pll_ratio = adc.pll_loopdiv;
pll.pll_prediv = adc.pll_prediv;
- dib7000p_update_pll(fe, &pll);
- dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+ state->dib7000p_ops.update_pll(fe, &pll);
+ state->dib7000p_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
}
return 0;
}
@@ -2501,14 +2617,17 @@ static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
static int tfe7790p_update_lna(struct dvb_frontend *fe, u16 agc_global)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("update LNA: agc global=%i", agc_global);
if (agc_global < 25000) {
- dib7000p_set_gpio(fe, 8, 0, 0);
- dib7000p_set_agc1_min(fe, 0);
+ state->dib7000p_ops.set_gpio(fe, 8, 0, 0);
+ state->dib7000p_ops.set_agc1_min(fe, 0);
} else {
- dib7000p_set_gpio(fe, 8, 0, 1);
- dib7000p_set_agc1_min(fe, 32768);
+ state->dib7000p_ops.set_gpio(fe, 8, 0, 1);
+ state->dib7000p_ops.set_agc1_min(fe, 32768);
}
return 0;
@@ -2644,13 +2763,16 @@ static struct dib7000p_config nim7090_dib7000p_config = {
static int tfe7090p_pvr_update_lna(struct dvb_frontend *fe, u16 agc_global)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("TFE7090P-PVR update LNA: agc global=%i", agc_global);
if (agc_global < 25000) {
- dib7000p_set_gpio(fe, 5, 0, 0);
- dib7000p_set_agc1_min(fe, 0);
+ state->dib7000p_ops.set_gpio(fe, 5, 0, 0);
+ state->dib7000p_ops.set_agc1_min(fe, 0);
} else {
- dib7000p_set_gpio(fe, 5, 0, 1);
- dib7000p_set_agc1_min(fe, 32768);
+ state->dib7000p_ops.set_gpio(fe, 5, 0, 1);
+ state->dib7000p_ops.set_agc1_min(fe, 32768);
}
return 0;
@@ -2714,7 +2836,7 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
}
};
-static const struct dib0090_config nim7090_dib0090_config = {
+static struct dib0090_config nim7090_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -2722,14 +2844,10 @@ static const struct dib0090_config nim7090_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2776,7 +2894,7 @@ static struct dib7000p_config tfe7790p_dib7000p_config = {
.enMpegOutput = 1,
};
-static const struct dib0090_config tfe7790p_dib0090_config = {
+static struct dib0090_config tfe7790p_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -2784,14 +2902,10 @@ static const struct dib0090_config tfe7790p_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2813,7 +2927,7 @@ static const struct dib0090_config tfe7790p_dib0090_config = {
.force_crystal_mode = 1,
};
-static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
+static struct dib0090_config tfe7090pvr_dib0090_config[2] = {
{
.io.clock_khz = 12000,
.io.pll_bypass = 0,
@@ -2822,14 +2936,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 50,
.freq_offset_khz_vhf = 70,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2854,14 +2964,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = -50,
.freq_offset_khz_vhf = -70,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2883,6 +2989,11 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(20);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -2895,11 +3006,12 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -2907,12 +3019,16 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ nim7090_dib0090_config.reset = st->dib7000p_ops.tuner_sleep,
+ nim7090_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep,
+ nim7090_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2922,6 +3038,10 @@ static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* The TFE7090 requires the dib0700 to not be in master mode */
st->disable_streaming_master_mode = 1;
@@ -2939,17 +3059,18 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
dib0700_set_i2c_speed(adap->dev, 340);
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- dib7090_slave_reset(adap->fe_adap[0].fe);
+ state->dib7000p_ops.slave_reset(adap->fe_adap[0].fe);
return 0;
}
@@ -2957,19 +3078,24 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *i2c;
+ struct dib0700_adapter_state *state = adap->priv;
if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
err("the master dib7090 has to be initialized first");
return -ENODEV; /* the master device has not been initialized */
}
- i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
- if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+ if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
dib0700_set_i2c_speed(adap->dev, 200);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -2978,12 +3104,16 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe7090pvr_dib0090_config[0].reset = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[0].sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[0].get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2993,12 +3123,16 @@ static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe7090pvr_dib0090_config[1].reset = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[1].sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[1].get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3008,6 +3142,10 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* The TFE7790P requires the dib0700 to not be in master mode */
st->disable_streaming_master_mode = 1;
@@ -3024,13 +3162,14 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap,
1, 0x10, &tfe7790p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80, &tfe7790p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -3040,13 +3179,18 @@ static int tfe7790p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c =
- dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+
+ tfe7790p_dib0090_config.reset = st->dib7000p_ops.tuner_sleep;
+ tfe7790p_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7790p_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
&tfe7790p_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3103,25 +3247,36 @@ static void stk7070pd_init(struct dvb_usb_device *dev)
static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
stk7070pd_init(adap->dev);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
{
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -3164,6 +3319,10 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *dev = adap->dev;
struct dib0700_state *st = dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
if (adap->id == 0) {
stk7070pd_init(dev);
@@ -3173,15 +3332,16 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&dev->i2c_adap,
adap->id == 0 ? 0x80 : 0x82,
&stk7070pd_dib7000p_config[adap->id]);
@@ -3291,12 +3451,13 @@ static int dib0700_xc4000_tuner_callback(void *priv, int component,
int command, int arg)
{
struct dvb_usb_adapter *adap = priv;
+ struct dib0700_adapter_state *state = adap->priv;
if (command == XC4000_TUNER_RESET) {
/* Reset the tuner */
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
msleep(10);
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
} else {
err("xc4000: unknown tuner callback command: %d\n", command);
return -EINVAL;
@@ -3374,6 +3535,10 @@ static struct dib7000p_config pctv_340e_config = {
static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* Power Supply on */
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -3397,12 +3562,13 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
msleep(500);
- if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
+ if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
/* Demodulator not found for some reason? */
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x12,
&pctv_340e_config);
st->is_dib7000pc = 1;
@@ -3420,9 +3586,10 @@ static struct xc4000_config dib7000p_xc4000_tunerconfig = {
static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
/* The xc4000 is not on the main i2c bus */
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (tun_i2c == NULL) {
printk(KERN_ERR "Could not reach tuner i2c bus\n");
@@ -3636,6 +3803,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
}},
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
},
},
diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h
index e47c321b3ffc..32ab1392313f 100644
--- a/drivers/media/usb/dvb-usb/dibusb.h
+++ b/drivers/media/usb/dvb-usb/dibusb.h
@@ -36,7 +36,7 @@
/*
* i2c read
- * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
+ * bulk write: 0x02 ((7bit i2c_addr << 1) | 0x01) register_bytes length_word
* bulk read: byte_buffer (length_word bytes)
*/
#define DIBUSB_REQ_I2C_READ 0x02
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
index 4058aea9272f..7b5dae3077f6 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
dev->driver_name = d->props.rc.core.module_name;
dev->map_name = d->props.rc.core.rc_codes;
dev->change_protocol = d->props.rc.core.change_protocol;
- rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos);
+ dev->allowed_protocols = d->props.rc.core.allowed_protos;
dev->driver_type = d->props.rc.core.driver_type;
usb_to_input_id(d->udev, &dev->input_id);
dev->input_name = "IR-receiver inside an USB DVB receiver";
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index ae0f56a32e4d..2add8c507ec9 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -1109,6 +1109,7 @@ static struct ds3000_config su3000_ds3000_config = {
static struct cxd2820r_config cxd2820r_config = {
.i2c_address = 0x6c, /* (0xd8 >> 1) */
.ts_mode = 0x38,
+ .ts_clock_inv = 1,
};
static struct tda18271_config tda18271_config = {
@@ -1387,20 +1388,27 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
static int t220_frontend_attach(struct dvb_usb_adapter *d)
{
- u8 obuf[3] = { 0xe, 0x80, 0 };
+ u8 obuf[3] = { 0xe, 0x87, 0 };
u8 ibuf[] = { 0 };
if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");
obuf[0] = 0xe;
- obuf[1] = 0x83;
+ obuf[1] = 0x86;
+ obuf[2] = 1;
+
+ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+ err("command 0x0e transfer failed.");
+
+ obuf[0] = 0xe;
+ obuf[1] = 0x80;
obuf[2] = 0;
if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");
- msleep(100);
+ msleep(50);
obuf[0] = 0xe;
obuf[1] = 0x80;
@@ -1482,7 +1490,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d)
if (msg.buf[0] != 0xff) {
deb_rc("%s: rc code: %x, %x\n",
__func__, key[0], key[1]);
- rc_keydown(d->rc_dev, key[0], 1);
+ rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0], 0);
}
}
@@ -1503,7 +1511,7 @@ static int prof_rc_query(struct dvb_usb_device *d)
if (msg.buf[0] != 0xff) {
deb_rc("%s: rc code: %x, %x\n",
__func__, key[0], key[1]);
- rc_keydown(d->rc_dev, key[0]^0xff, 1);
+ rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0]^0xff, 0);
}
}
@@ -1524,7 +1532,8 @@ static int su3000_rc_query(struct dvb_usb_device *d)
if (msg.buf[0] != 0xff) {
deb_rc("%s: rc code: %x, %x\n",
__func__, key[0], key[1]);
- rc_keydown(d->rc_dev, key[1] << 8 | key[0], 1);
+ rc_keydown(d->rc_dev, RC_TYPE_RC5,
+ RC_SCANCODE_RC5(key[1], key[0]), 0);
}
}
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c
index 0306cb778df4..abf8ab2e02e5 100644
--- a/drivers/media/usb/dvb-usb/m920x.c
+++ b/drivers/media/usb/dvb-usb/m920x.c
@@ -245,7 +245,7 @@ static int m920x_rc_core_query(struct dvb_usb_device *d)
else if (state == REMOTE_KEY_REPEAT)
rc_repeat(d->rc_dev);
else
- rc_keydown(d->rc_dev, rc_state[1], 0);
+ rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, rc_state[1], 0);
out:
kfree(rc_state);
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index 449a99605a87..bdfe8963591c 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -565,12 +565,12 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
if ((rx[3] == 9) && (rx[12] & 0x01)) {
/* got a "press" event */
- state->last_rc_key = (rx[7] << 8) | rx[6];
+ state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
if (debug > 2)
info("%s: cmd=0x%02x sys=0x%02x\n",
__func__, rx[6], rx[7]);
- rc_keydown(d->rc_dev, state->last_rc_key, 0);
+ rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
} else if (state->last_rc_key) {
rc_keyup(d->rc_dev);
state->last_rc_key = 0;
@@ -927,7 +927,7 @@ static struct dvb_usb_device_properties pctv452e_properties = {
.rc.core = {
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_RC5,
.rc_query = pctv452e_rc_query,
.rc_interval = 100,
},
@@ -980,7 +980,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
.rc.core = {
.rc_codes = RC_MAP_TT_1500,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_RC5,
.rc_query = pctv452e_rc_query,
.rc_interval = 100,
},
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index d947e0379008..6b0b8b6b9e2a 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -710,7 +710,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
.isoc = {
.framesperurb = 32,
.framesize = 2048,
- .interval = 3,
+ .interval = 1,
}
}
},
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index 2ce3d19c58ef..f10717311e05 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -438,9 +438,9 @@ static int tt3650_rc_query(struct dvb_usb_device *d)
if (rx[8] & 0x01) {
/* got a "press" event */
- st->last_rc_key = (rx[3] << 8) | rx[2];
+ st->last_rc_key = RC_SCANCODE_RC5(rx[3], rx[2]);
deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
- rc_keydown(d->rc_dev, st->last_rc_key, rx[1]);
+ rc_keydown(d->rc_dev, RC_TYPE_RC5, st->last_rc_key, rx[1]);
} else if (st->last_rc_key) {
rc_keyup(d->rc_dev);
st->last_rc_key = 0;
@@ -747,7 +747,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
.rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */
.rc_codes = RC_MAP_TT_1500,
.rc_query = tt3650_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_RC5,
},
.num_adapters = 1,
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 12d4c0326e31..6d2ea9afd57b 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -366,7 +366,7 @@ int em28xx_init_camera(struct em28xx *dev)
v4l2->sensor_xtal = 4300000;
pdata.xtal = v4l2->sensor_xtal;
if (NULL ==
- v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
+ v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
&mt9v011_info, NULL)) {
ret = -ENODEV;
break;
@@ -423,7 +423,7 @@ int em28xx_init_camera(struct em28xx *dev)
v4l2->sensor_yres = 480;
subdev =
- v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap,
+ v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
&ov2640_info, NULL);
if (NULL == subdev) {
ret = -ENODEV;
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 15ad47045553..a7e24848f6c8 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2280,6 +2280,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2820_BOARD_UNKNOWN },
{ USB_DEVICE(0xeb1a, 0x2875),
.driver_info = EM2820_BOARD_UNKNOWN },
+ { USB_DEVICE(0xeb1a, 0x2885), /* MSI Digivox Trio */
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
{ USB_DEVICE(0xeb1a, 0xe300),
.driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
{ USB_DEVICE(0xeb1a, 0xe303),
@@ -3522,7 +3524,6 @@ static struct usb_driver em28xx_usb_driver = {
.disconnect = em28xx_usb_disconnect,
.suspend = em28xx_usb_suspend,
.resume = em28xx_usb_resume,
- .reset_resume = em28xx_usb_resume,
.id_table = em28xx_id_table,
};
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index a121ed9561fd..3a3e243edf89 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1213,9 +1213,17 @@ static int em28xx_dvb_init(struct em28xx *dev)
dvb->fe[0] = dvb_attach(lgdt3305_attach,
&em2870_lgdt3304_dev,
&dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL)
- dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
- &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config);
+ if (!dvb->fe[0]) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ &kworld_a340_config)) {
+ dvb_frontend_detach(dvb->fe[0]);
+ result = -EINVAL;
+ goto out_free;
+ }
break;
case EM28174_BOARD_PCTV_290E:
/* set default GPIO0 for LNA, used if GPIOLIB is undefined */
@@ -1545,6 +1553,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
dvb->i2c_client_demod = client;
/* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dvb->fe[0];
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
@@ -1645,10 +1654,14 @@ static int em28xx_dvb_fini(struct em28xx *dev)
if (dev->disconnected) {
/* We cannot tell the device to sleep
* once it has been unplugged. */
- if (dvb->fe[0])
+ if (dvb->fe[0]) {
prevent_sleep(&dvb->fe[0]->ops);
- if (dvb->fe[1])
+ dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED;
+ }
+ if (dvb->fe[1]) {
prevent_sleep(&dvb->fe[1]->ops);
+ dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED;
+ }
}
/* remove I2C tuner */
@@ -1712,7 +1725,6 @@ static int em28xx_dvb_resume(struct em28xx *dev)
em28xx_info("Resuming DVB extension");
if (dev->dvb) {
struct em28xx_dvb *dvb = dev->dvb;
- struct i2c_client *client = dvb->i2c_client_tuner;
if (dvb->fe[0]) {
ret = dvb_frontend_resume(dvb->fe[0]);
@@ -1723,22 +1735,6 @@ static int em28xx_dvb_resume(struct em28xx *dev)
ret = dvb_frontend_resume(dvb->fe[1]);
em28xx_info("fe1 resume %d", ret);
}
- /* remove I2C tuner */
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C demod */
- client = dvb->i2c_client_demod;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- em28xx_unregister_dvb(dvb);
- kfree(dvb);
- dev->dvb = NULL;
}
return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index b58d4ebf6419..1048c1a23fb6 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -501,6 +501,12 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
int addr, rc, i;
u8 reg;
+ /* prevent i2c xfer attempts after device is disconnected
+ some fe's try to do i2c writes/reads from their release
+ interfaces when called in disconnect path */
+ if (dev->disconnected)
+ return -ENODEV;
+
rc = rt_mutex_trylock(&dev->i2c_bus_lock);
if (rc < 0)
return rc;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 56ef49df4f8d..ed843bd221ea 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/slab.h>
+#include <linux/bitrev.h>
#include "em28xx.h"
@@ -53,6 +54,7 @@ struct em28xx_ir_poll_result {
unsigned int toggle_bit:1;
unsigned int read_count:7;
+ enum rc_type protocol;
u32 scancode;
};
@@ -72,7 +74,7 @@ struct em28xx_IR {
/* i2c slave address of external device (if used) */
u16 i2c_dev_addr;
- int (*get_key_i2c)(struct i2c_client *, u32 *);
+ int (*get_key_i2c)(struct i2c_client *ir, enum rc_type *protocol, u32 *scancode);
int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
};
@@ -80,7 +82,8 @@ struct em28xx_IR {
I2C IR based get keycodes - should be used with ir-kbd-i2c
**********************************************************/
-static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, u32 *ir_key)
+static int em28xx_get_key_terratec(struct i2c_client *i2c_dev,
+ enum rc_type *protocol, u32 *scancode)
{
unsigned char b;
@@ -98,14 +101,15 @@ static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, u32 *ir_key)
/* keep old data */
return 1;
- *ir_key = b;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = b;
return 1;
}
-static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, u32 *ir_key)
+static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev,
+ enum rc_type *protocol, u32 *scancode)
{
unsigned char buf[2];
- u16 code;
int size;
/* poll IR chip */
@@ -127,26 +131,13 @@ static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, u32 *ir_key)
* So, the code translation is not complete. Yet, it is enough to
* work with the provided RC5 IR.
*/
- code =
- ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */
- ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */
- ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */
- ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */
- ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */
- ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */
- ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */
- ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */
- ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */
- ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */
- ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */
-
- /* return key */
- *ir_key = code;
+ *protocol = RC_TYPE_RC5;
+ *scancode = (bitrev8(buf[1]) & 0x1f) << 8 | bitrev8(buf[0]) >> 2;
return 1;
}
static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev,
- u32 *ir_key)
+ enum rc_type *protocol, u32 *scancode)
{
unsigned char buf[3];
@@ -158,13 +149,13 @@ static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev,
if (buf[0] != 0x00)
return 0;
- *ir_key = buf[2]&0x3f;
-
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = buf[2] & 0x3f;
return 1;
}
static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev,
- u32 *ir_key)
+ enum rc_type *protocol, u32 *scancode)
{
unsigned char subaddr, keydetect, key;
@@ -184,7 +175,8 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev,
if (key == 0x00)
return 0;
- *ir_key = key;
+ *protocol = RC_TYPE_UNKNOWN;
+ *scancode = key;
return 1;
}
@@ -215,7 +207,22 @@ static int default_polling_getkey(struct em28xx_IR *ir,
poll_result->read_count = (msg[0] & 0x7f);
/* Remote Control Address/Data (Regs 0x46/0x47) */
- poll_result->scancode = msg[1] << 8 | msg[2];
+ switch (ir->rc_type) {
+ case RC_BIT_RC5:
+ poll_result->protocol = RC_TYPE_RC5;
+ poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]);
+ break;
+
+ case RC_BIT_NEC:
+ poll_result->protocol = RC_TYPE_NEC;
+ poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[2]);
+ break;
+
+ default:
+ poll_result->protocol = RC_TYPE_UNKNOWN;
+ poll_result->scancode = msg[1] << 8 | msg[2];
+ break;
+ }
return 0;
}
@@ -247,25 +254,32 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
*/
switch (ir->rc_type) {
case RC_BIT_RC5:
- poll_result->scancode = msg[1] << 8 | msg[2];
+ poll_result->protocol = RC_TYPE_RC5;
+ poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]);
break;
+
case RC_BIT_NEC:
+ poll_result->protocol = RC_TYPE_RC5;
+ poll_result->scancode = msg[1] << 8 | msg[2];
if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */
- poll_result->scancode = (msg[1] << 24) |
- (msg[2] << 16) |
- (msg[3] << 8) |
- msg[4];
+ poll_result->scancode = RC_SCANCODE_NEC32((msg[1] << 24) |
+ (msg[2] << 16) |
+ (msg[3] << 8) |
+ (msg[4]));
else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */
- poll_result->scancode = (msg[1] << 16) |
- (msg[2] << 8) |
- msg[3];
+ poll_result->scancode = RC_SCANCODE_NECX(msg[1] << 8 |
+ msg[2], msg[3]);
else /* Normal NEC */
- poll_result->scancode = msg[1] << 8 | msg[3];
+ poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[3]);
break;
+
case RC_BIT_RC6_0:
- poll_result->scancode = msg[1] << 8 | msg[2];
+ poll_result->protocol = RC_TYPE_RC6_0;
+ poll_result->scancode = RC_SCANCODE_RC6_0(msg[1], msg[2]);
break;
+
default:
+ poll_result->protocol = RC_TYPE_UNKNOWN;
poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) |
(msg[3] << 8) | msg[4];
break;
@@ -281,22 +295,24 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir)
{
struct em28xx *dev = ir->dev;
- static u32 ir_key;
+ static u32 scancode;
+ enum rc_type protocol;
int rc;
struct i2c_client client;
client.adapter = &ir->dev->i2c_adap[dev->def_i2c_bus];
client.addr = ir->i2c_dev_addr;
- rc = ir->get_key_i2c(&client, &ir_key);
+ rc = ir->get_key_i2c(&client, &protocol, &scancode);
if (rc < 0) {
dprintk("ir->get_key_i2c() failed: %d\n", rc);
return rc;
}
if (rc) {
- dprintk("%s: keycode = 0x%04x\n", __func__, ir_key);
- rc_keydown(ir->rc, ir_key, 0);
+ dprintk("%s: proto = 0x%04x, scancode = 0x%04x\n",
+ __func__, protocol, scancode);
+ rc_keydown(ir->rc, protocol, scancode, 0);
}
return 0;
}
@@ -319,10 +335,12 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
poll_result.scancode);
if (ir->full_code)
rc_keydown(ir->rc,
+ poll_result.protocol,
poll_result.scancode,
poll_result.toggle_bit);
else
rc_keydown(ir->rc,
+ RC_TYPE_UNKNOWN,
poll_result.scancode & 0xff,
poll_result.toggle_bit);
@@ -727,7 +745,7 @@ static int em28xx_ir_init(struct em28xx *dev)
case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
rc->map_name = RC_MAP_HAUPPAUGE;
ir->get_key_i2c = em28xx_get_key_em_haup;
- rc_set_allowed_protocols(rc, RC_BIT_RC5);
+ rc->allowed_protocols = RC_BIT_RC5;
break;
case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
rc->map_name = RC_MAP_WINFAST_USBII_DELUXE;
@@ -743,7 +761,7 @@ static int em28xx_ir_init(struct em28xx *dev)
switch (dev->chip_id) {
case CHIP_ID_EM2860:
case CHIP_ID_EM2883:
- rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+ rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC;
ir->get_key = default_polling_getkey;
break;
case CHIP_ID_EM2884:
@@ -751,8 +769,8 @@ static int em28xx_ir_init(struct em28xx *dev)
case CHIP_ID_EM28174:
case CHIP_ID_EM28178:
ir->get_key = em2874_polling_getkey;
- rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC |
- RC_BIT_RC6_0);
+ rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC |
+ RC_BIT_RC6_0;
break;
default:
err = -ENODEV;
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index f6b49c98e2c9..90dec2955f1c 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1227,8 +1227,7 @@ static void scale_to_size(struct em28xx *dev,
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
f->fmt.pix.width = v4l2->width;
@@ -1261,8 +1260,7 @@ static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
unsigned int width = f->fmt.pix.width;
unsigned int height = f->fmt.pix.height;
@@ -1355,8 +1353,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
*norm = dev->v4l2->norm;
@@ -1365,8 +1362,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm);
@@ -1375,8 +1371,7 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
struct v4l2_format f;
@@ -1408,8 +1403,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
static int vidioc_g_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
int rc = 0;
@@ -1427,8 +1421,7 @@ static int vidioc_g_parm(struct file *file, void *priv,
static int vidioc_s_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
p->parm.capture.readbuffers = EM28XX_MIN_BUF;
return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
@@ -1450,8 +1443,7 @@ static const char *iname[] = {
static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
unsigned int n;
n = i->index;
@@ -1479,8 +1471,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
*i = dev->ctl_input;
@@ -1489,8 +1480,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
if (i >= MAX_EM28XX_INPUT)
return -EINVAL;
@@ -1503,8 +1493,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
switch (a->index) {
case EM28XX_AMUX_VIDEO:
@@ -1543,8 +1532,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
if (a->index >= MAX_EM28XX_INPUT)
return -EINVAL;
@@ -1563,8 +1551,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
if (0 != t->index)
return -EINVAL;
@@ -1578,8 +1565,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
static int vidioc_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
if (0 != t->index)
return -EINVAL;
@@ -1591,8 +1577,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
if (0 != f->tuner)
@@ -1606,8 +1591,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
struct v4l2_frequency new_freq = *f;
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
if (0 != f->tuner)
@@ -1624,8 +1608,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_chip_info(struct file *file, void *priv,
struct v4l2_dbg_chip_info *chip)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
if (chip->match.addr > 1)
return -EINVAL;
@@ -1652,8 +1635,7 @@ static int em28xx_reg_len(int reg)
static int vidioc_g_register(struct file *file, void *priv,
struct v4l2_dbg_register *reg)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
int ret;
if (reg->match.addr > 1)
@@ -1693,8 +1675,7 @@ static int vidioc_g_register(struct file *file, void *priv,
static int vidioc_s_register(struct file *file, void *priv,
const struct v4l2_dbg_register *reg)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
__le16 buf;
if (reg->match.addr > 1)
@@ -1715,8 +1696,7 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct video_device *vdev = video_devdata(file);
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
@@ -1761,8 +1741,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_enum_framesizes(struct file *file, void *priv,
struct v4l2_frmsizeenum *fsize)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_fmt *fmt;
unsigned int maxw = norm_maxw(dev);
unsigned int maxh = norm_maxh(dev);
@@ -1806,8 +1785,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
struct v4l2_format *format)
{
- struct em28xx_fh *fh = priv;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
format->fmt.vbi.samples_per_line = v4l2->vbi_width;
@@ -1840,7 +1818,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
static int radio_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+ struct em28xx *dev = video_drvdata(file);
if (unlikely(t->index > 0))
return -EINVAL;
@@ -1855,7 +1833,7 @@ static int radio_g_tuner(struct file *file, void *priv,
static int radio_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+ struct em28xx *dev = video_drvdata(file);
if (0 != t->index)
return -EINVAL;
@@ -1890,7 +1868,7 @@ static int em28xx_v4l2_open(struct file *filp)
struct em28xx *dev = video_drvdata(filp);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
enum v4l2_buf_type fh_type = 0;
- struct em28xx_fh *fh;
+ int ret;
switch (vdev->vfl_type) {
case VFL_TYPE_GRABBER:
@@ -1905,24 +1883,23 @@ static int em28xx_v4l2_open(struct file *filp)
return -EINVAL;
}
- em28xx_videodbg("open dev=%s type=%s users=%d\n",
- video_device_node_name(vdev), v4l2_type_names[fh_type],
- v4l2->users);
+ em28xx_videodbg("open dev=%s type=%s\n",
+ video_device_node_name(vdev), v4l2_type_names[fh_type]);
if (mutex_lock_interruptible(&dev->lock))
return -ERESTARTSYS;
- fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
- if (!fh) {
- em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+
+ ret = v4l2_fh_open(filp);
+ if (ret) {
+ em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
+ __func__, ret);
mutex_unlock(&dev->lock);
- return -ENOMEM;
+ return ret;
}
- v4l2_fh_init(&fh->fh, vdev);
- fh->dev = dev;
- fh->type = fh_type;
- filp->private_data = fh;
- if (v4l2->users == 0) {
+ if (v4l2_fh_is_singular_file(filp)) {
+ em28xx_videodbg("first opened filehandle, initializing device\n");
+
em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
if (vdev->vfl_type != VFL_TYPE_RADIO)
@@ -1933,6 +1910,8 @@ static int em28xx_v4l2_open(struct file *filp)
* of some i2c devices
*/
em28xx_wake_i2c(dev);
+ } else {
+ em28xx_videodbg("further filehandles are already opened\n");
}
if (vdev->vfl_type == VFL_TYPE_RADIO) {
@@ -1942,10 +1921,8 @@ static int em28xx_v4l2_open(struct file *filp)
kref_get(&dev->ref);
kref_get(&v4l2->ref);
- v4l2->users++;
mutex_unlock(&dev->lock);
- v4l2_fh_add(&fh->fh);
return 0;
}
@@ -2046,17 +2023,15 @@ static int em28xx_v4l2_resume(struct em28xx *dev)
*/
static int em28xx_v4l2_close(struct file *filp)
{
- struct em28xx_fh *fh = filp->private_data;
- struct em28xx *dev = fh->dev;
+ struct em28xx *dev = video_drvdata(filp);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
int errCode;
- em28xx_videodbg("users=%d\n", v4l2->users);
-
- vb2_fop_release(filp);
mutex_lock(&dev->lock);
- if (v4l2->users == 1) {
+ if (v4l2_fh_is_singular_file(filp)) {
+ em28xx_videodbg("last opened filehandle, shutting down device\n");
+
/* No sense to try to write to the device */
if (dev->disconnected)
goto exit;
@@ -2075,10 +2050,12 @@ static int em28xx_v4l2_close(struct file *filp)
em28xx_errdev("cannot change alternate number to "
"0 (error=%i)\n", errCode);
}
+ } else {
+ em28xx_videodbg("further opened filehandles left\n");
}
exit:
- v4l2->users--;
+ vb2_fop_release(filp);
kref_put(&v4l2->ref, em28xx_free_v4l2);
mutex_unlock(&dev->lock);
kref_put(&dev->ref, em28xx_free_device);
@@ -2208,7 +2185,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
if (dev->board.is_webcam)
vfd->tvnorms = 0;
@@ -2552,7 +2528,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
/* disable inapplicable ioctls */
- v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
+ v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM);
if (dev->tuner_type == TUNER_ABSENT) {
v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index b4c837d77e5d..84ef8efdb148 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -524,7 +524,6 @@ struct em28xx_v4l2 {
int sensor_yres;
int sensor_xtal;
- int users; /* user count for exclusive use */
int streaming_users; /* number of actively streaming users */
u32 frequency; /* selected tuner frequency */
@@ -576,13 +575,6 @@ struct em28xx_audio {
struct em28xx;
-struct em28xx_fh {
- struct v4l2_fh fh;
- struct em28xx *dev;
-
- enum v4l2_buf_type type;
-};
-
enum em28xx_i2c_algo_type {
EM28XX_I2C_ALGO_EM28XX = 0,
EM28XX_I2C_ALGO_EM2800,
diff --git a/drivers/staging/media/go7007/Kconfig b/drivers/media/usb/go7007/Kconfig
index 95a3af644a92..95a3af644a92 100644
--- a/drivers/staging/media/go7007/Kconfig
+++ b/drivers/media/usb/go7007/Kconfig
diff --git a/drivers/staging/media/go7007/Makefile b/drivers/media/usb/go7007/Makefile
index 9c6ad4a263ec..e99287c3b828 100644
--- a/drivers/staging/media/go7007/Makefile
+++ b/drivers/media/usb/go7007/Makefile
@@ -8,8 +8,4 @@ go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
s2250-y := s2250-board.o
-# Uncomment when the saa7134 patches get into upstream
-#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
-#ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/pci/saa7134
-
ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index 6f1beca86b2b..95cffb771a62 100644
--- a/drivers/staging/media/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -32,6 +28,7 @@
#include <linux/videodev2.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
#include "go7007-priv.h"
@@ -224,7 +221,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *con
return 0;
}
- printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type);
+ pr_info("go7007: probing for module i2c:%s failed\n", i2c->type);
return -EINVAL;
}
@@ -332,20 +329,33 @@ EXPORT_SYMBOL(go7007_register_encoder);
int go7007_start_encoder(struct go7007 *go)
{
u8 *fw;
- int fw_len, rv = 0, i;
+ int fw_len, rv = 0, i, x, y;
u16 intr_val, intr_data;
go->modet_enable = 0;
- if (!go->dvd_mode)
- for (i = 0; i < 4; ++i) {
- if (go->modet[i].enable) {
- go->modet_enable = 1;
- continue;
+ for (i = 0; i < 4; i++)
+ go->modet[i].enable = 0;
+
+ switch (v4l2_ctrl_g_ctrl(go->modet_mode)) {
+ case V4L2_DETECT_MD_MODE_GLOBAL:
+ memset(go->modet_map, 0, sizeof(go->modet_map));
+ go->modet[0].enable = 1;
+ go->modet_enable = 1;
+ break;
+ case V4L2_DETECT_MD_MODE_REGION_GRID:
+ for (y = 0; y < go->height / 16; y++) {
+ for (x = 0; x < go->width / 16; x++) {
+ int idx = y * go->width / 16 + x;
+
+ go->modet[go->modet_map[idx]].enable = 1;
}
- go->modet[i].pixel_threshold = 32767;
- go->modet[i].motion_threshold = 32767;
- go->modet[i].mb_threshold = 32767;
}
+ go->modet_enable = 1;
+ break;
+ }
+
+ if (go->dvd_mode)
+ go->modet_enable = 0;
if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
return -1;
@@ -383,44 +393,89 @@ static inline void store_byte(struct go7007_buffer *vb, u8 byte)
}
}
+static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb,
+ u32 motion_regions)
+{
+ if (motion_regions != go->modet_event_status) {
+ struct v4l2_event ev = {
+ .type = V4L2_EVENT_MOTION_DET,
+ .u.motion_det = {
+ .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vb->vb.v4l2_buf.sequence,
+ .region_mask = motion_regions,
+ },
+ };
+
+ v4l2_event_queue(&go->vdev, &ev);
+ go->modet_event_status = motion_regions;
+ }
+}
+
/*
- * Deliver the last video buffer and get a new one to start writing to.
+ * Determine regions with motion and send a motion detection event
+ * in case of changes.
*/
-static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
+static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
{
- struct go7007_buffer *vb_tmp = NULL;
u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ unsigned motion[4] = { 0, 0, 0, 0 };
+ u32 motion_regions = 0;
+ unsigned stride = (go->width + 7) >> 3;
+ unsigned x, y;
int i;
- if (vb) {
- if (vb->modet_active) {
- if (*bytesused + 216 < GO7007_BUF_SIZE) {
- for (i = 0; i < 216; ++i)
- store_byte(vb, go->active_map[i]);
- *bytesused -= 216;
- } else
- vb->modet_active = 0;
+ for (i = 0; i < 216; ++i)
+ store_byte(vb, go->active_map[i]);
+ for (y = 0; y < go->height / 16; y++) {
+ for (x = 0; x < go->width / 16; x++) {
+ if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7))))
+ continue;
+ motion[go->modet_map[y * (go->width / 16) + x]]++;
}
- vb->vb.v4l2_buf.sequence = go->next_seq++;
- v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
- vb_tmp = vb;
+ }
+ motion_regions = ((motion[0] > 0) << 0) |
+ ((motion[1] > 0) << 1) |
+ ((motion[2] > 0) << 2) |
+ ((motion[3] > 0) << 3);
+ *bytesused -= 216;
+ go7007_set_motion_regions(go, vb, motion_regions);
+}
+
+/*
+ * Deliver the last video buffer and get a new one to start writing to.
+ */
+static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
+{
+ u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ struct go7007_buffer *vb_tmp = NULL;
+
+ if (vb == NULL) {
spin_lock(&go->spinlock);
- list_del(&vb->list);
- if (list_empty(&go->vidq_active))
- vb = NULL;
- else
- vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
- go->active_buf = vb;
+ if (!list_empty(&go->vidq_active))
+ vb = go->active_buf =
+ list_first_entry(&go->vidq_active, struct go7007_buffer, list);
spin_unlock(&go->spinlock);
- vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+ go->next_seq++;
return vb;
}
+
+ vb->vb.v4l2_buf.sequence = go->next_seq++;
+ if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
+ go7007_motion_regions(go, vb);
+ else
+ go7007_set_motion_regions(go, vb, 0);
+
+ v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+ vb_tmp = vb;
spin_lock(&go->spinlock);
- if (!list_empty(&go->vidq_active))
- vb = go->active_buf =
- list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+ list_del(&vb->list);
+ if (list_empty(&go->vidq_active))
+ vb = NULL;
+ else
+ vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+ go->active_buf = vb;
spin_unlock(&go->spinlock);
- go->next_seq++;
+ vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
return vb;
}
diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c
index 814ce08bc44d..5f4c9b9e899a 100644
--- a/drivers/staging/media/go7007/go7007-fw.c
+++ b/drivers/media/usb/go7007/go7007-fw.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
/*
@@ -1432,22 +1428,26 @@ static int audio_to_package(struct go7007 *go, __le16 *code, int space)
static int modet_to_package(struct go7007 *go, __le16 *code, int space)
{
+ bool has_modet0 = go->modet[0].enable;
+ bool has_modet1 = go->modet[1].enable;
+ bool has_modet2 = go->modet[2].enable;
+ bool has_modet3 = go->modet[3].enable;
int ret, mb, i, addr, cnt = 0;
u16 pack[32];
u16 thresholds[] = {
0x200e, 0,
- 0xbf82, go->modet[0].pixel_threshold,
- 0xbf83, go->modet[1].pixel_threshold,
- 0xbf84, go->modet[2].pixel_threshold,
- 0xbf85, go->modet[3].pixel_threshold,
- 0xbf86, go->modet[0].motion_threshold,
- 0xbf87, go->modet[1].motion_threshold,
- 0xbf88, go->modet[2].motion_threshold,
- 0xbf89, go->modet[3].motion_threshold,
- 0xbf8a, go->modet[0].mb_threshold,
- 0xbf8b, go->modet[1].mb_threshold,
- 0xbf8c, go->modet[2].mb_threshold,
- 0xbf8d, go->modet[3].mb_threshold,
+ 0xbf82, has_modet0 ? go->modet[0].pixel_threshold : 32767,
+ 0xbf83, has_modet1 ? go->modet[1].pixel_threshold : 32767,
+ 0xbf84, has_modet2 ? go->modet[2].pixel_threshold : 32767,
+ 0xbf85, has_modet3 ? go->modet[3].pixel_threshold : 32767,
+ 0xbf86, has_modet0 ? go->modet[0].motion_threshold : 32767,
+ 0xbf87, has_modet1 ? go->modet[1].motion_threshold : 32767,
+ 0xbf88, has_modet2 ? go->modet[2].motion_threshold : 32767,
+ 0xbf89, has_modet3 ? go->modet[3].motion_threshold : 32767,
+ 0xbf8a, has_modet0 ? go->modet[0].mb_threshold : 32767,
+ 0xbf8b, has_modet1 ? go->modet[1].mb_threshold : 32767,
+ 0xbf8c, has_modet2 ? go->modet[2].mb_threshold : 32767,
+ 0xbf8d, has_modet3 ? go->modet[3].mb_threshold : 32767,
0xbf8e, 0,
0xbf8f, 0,
0, 0,
diff --git a/drivers/staging/media/go7007/go7007-i2c.c b/drivers/media/usb/go7007/go7007-i2c.c
index 4cf4c0d65085..55addfa855d4 100644
--- a/drivers/staging/media/go7007/go7007-i2c.c
+++ b/drivers/media/usb/go7007/go7007-i2c.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
diff --git a/drivers/staging/media/go7007/go7007-loader.c b/drivers/media/usb/go7007/go7007-loader.c
index 491d0e697f5a..042f78a31283 100644
--- a/drivers/staging/media/go7007/go7007-loader.c
+++ b/drivers/media/usb/go7007/go7007-loader.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
index 6e16af720504..2251c3f99d1d 100644
--- a/drivers/staging/media/go7007/go7007-priv.h
+++ b/drivers/media/usb/go7007/go7007-priv.h
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
/*
@@ -75,6 +71,20 @@ struct go7007;
#define GO7007_AUDIO_I2S_MASTER (1<<16)
#define GO7007_AUDIO_OKI_MODE (1<<17)
+#define GO7007_CID_CUSTOM_BASE (V4L2_CID_DETECT_CLASS_BASE + 0x1000)
+#define V4L2_CID_PIXEL_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+1)
+#define V4L2_CID_MOTION_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+2)
+#define V4L2_CID_MB_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+3)
+#define V4L2_CID_PIXEL_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+4)
+#define V4L2_CID_MOTION_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+5)
+#define V4L2_CID_MB_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+6)
+#define V4L2_CID_PIXEL_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+7)
+#define V4L2_CID_MOTION_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+8)
+#define V4L2_CID_MB_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+9)
+#define V4L2_CID_PIXEL_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+10)
+#define V4L2_CID_MOTION_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+11)
+#define V4L2_CID_MB_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+12)
+
struct go7007_board_info {
unsigned int flags;
int hpi_buffer_cap;
@@ -168,6 +178,7 @@ struct go7007 {
struct v4l2_ctrl *mpeg_video_aspect_ratio;
struct v4l2_ctrl *mpeg_video_b_frames;
struct v4l2_ctrl *mpeg_video_rep_seqheader;
+ struct v4l2_ctrl *modet_mode;
enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
spinlock_t spinlock;
struct mutex hw_lock;
@@ -216,6 +227,7 @@ struct go7007 {
} modet[4];
unsigned char modet_map[1624];
unsigned char active_map[216];
+ u32 modet_event_status;
/* Video streaming */
struct mutex queue_lock;
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c
index 2f62be905cd1..ece27ece8115 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/media/usb/go7007/go7007-usb.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index da7b5493e13e..ec799b4d88be 100644
--- a/drivers/staging/media/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -36,7 +32,6 @@
#include <media/videobuf2-vmalloc.h>
#include <media/saa7115.h>
-#include "go7007.h"
#include "go7007-priv.h"
#define call_all(dev, o, f, args...) \
@@ -189,7 +184,7 @@ static void set_formatting(struct go7007 *go)
static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
{
int sensor_height = 0, sensor_width = 0;
- int width, height, i;
+ int width, height;
if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
return -EINVAL;
@@ -253,10 +248,6 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
go->height = height;
go->encoder_h_offset = go->board_info->sensor_h_offset;
go->encoder_v_offset = go->board_info->sensor_v_offset;
- for (i = 0; i < 4; ++i)
- go->modet[i].enable = 0;
- for (i = 0; i < 1624; ++i)
- go->modet_map[i] = 0;
if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
struct v4l2_mbus_framefmt mbus_fmt;
@@ -286,64 +277,6 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
return 0;
}
-#if 0
-static int clip_to_modet_map(struct go7007 *go, int region,
- struct v4l2_clip *clip_list)
-{
- struct v4l2_clip clip, *clip_ptr;
- int x, y, mbnum;
-
- /* Check if coordinates are OK and if any macroblocks are already
- * used by other regions (besides 0) */
- clip_ptr = clip_list;
- while (clip_ptr) {
- if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
- return -EFAULT;
- if (clip.c.left < 0 || (clip.c.left & 0xF) ||
- clip.c.width <= 0 || (clip.c.width & 0xF))
- return -EINVAL;
- if (clip.c.left + clip.c.width > go->width)
- return -EINVAL;
- if (clip.c.top < 0 || (clip.c.top & 0xF) ||
- clip.c.height <= 0 || (clip.c.height & 0xF))
- return -EINVAL;
- if (clip.c.top + clip.c.height > go->height)
- return -EINVAL;
- for (y = 0; y < clip.c.height; y += 16)
- for (x = 0; x < clip.c.width; x += 16) {
- mbnum = (go->width >> 4) *
- ((clip.c.top + y) >> 4) +
- ((clip.c.left + x) >> 4);
- if (go->modet_map[mbnum] != 0 &&
- go->modet_map[mbnum] != region)
- return -EBUSY;
- }
- clip_ptr = clip.next;
- }
-
- /* Clear old region macroblocks */
- for (mbnum = 0; mbnum < 1624; ++mbnum)
- if (go->modet_map[mbnum] == region)
- go->modet_map[mbnum] = 0;
-
- /* Claim macroblocks in this list */
- clip_ptr = clip_list;
- while (clip_ptr) {
- if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
- return -EFAULT;
- for (y = 0; y < clip.c.height; y += 16)
- for (x = 0; x < clip.c.width; x += 16) {
- mbnum = (go->width >> 4) *
- ((clip.c.top + y) >> 4) +
- ((clip.c.left + x) >> 4);
- go->modet_map[mbnum] = region;
- }
- clip_ptr = clip.next;
- }
- return 0;
-}
-#endif
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -495,6 +428,7 @@ static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
mutex_lock(&go->hw_lock);
go->next_seq = 0;
go->active_buf = NULL;
+ go->modet_event_status = 0;
q->streaming = 1;
if (go7007_start_encoder(go) < 0)
ret = -EIO;
@@ -850,41 +784,76 @@ static int vidioc_log_status(struct file *file, void *priv)
return call_all(&go->v4l2_dev, core, log_status);
}
-/* FIXME:
- Those ioctls are private, and not needed, since several standard
- extended controls already provide streaming control.
- So, those ioctls should be converted into vidioc_g_ext_ctrls()
- and vidioc_s_ext_ctrls()
- */
-
-#if 0
- case GO7007IOC_S_MD_PARAMS:
- {
- struct go7007_md_params *mdp = arg;
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
- if (mdp->region > 3)
- return -EINVAL;
- if (mdp->trigger > 0) {
- go->modet[mdp->region].pixel_threshold =
- mdp->pixel_threshold >> 1;
- go->modet[mdp->region].motion_threshold =
- mdp->motion_threshold >> 1;
- go->modet[mdp->region].mb_threshold =
- mdp->trigger >> 1;
- go->modet[mdp->region].enable = 1;
- } else
- go->modet[mdp->region].enable = 0;
- /* fall-through */
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(fh, sub);
+ case V4L2_EVENT_MOTION_DET:
+ /* Allow for up to 30 events (1 second for NTSC) to be
+ * stored. */
+ return v4l2_event_subscribe(fh, sub, 30, NULL);
}
- case GO7007IOC_S_MD_REGION:
- {
- struct go7007_md_region *region = arg;
+ return -EINVAL;
+}
- if (region->region < 1 || region->region > 3)
- return -EINVAL;
- return clip_to_modet_map(go, region->region, region->clips);
+
+static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct go7007 *go =
+ container_of(ctrl->handler, struct go7007, hdl);
+ unsigned y;
+ u8 *mt;
+
+ switch (ctrl->id) {
+ case V4L2_CID_PIXEL_THRESHOLD0:
+ go->modet[0].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD0:
+ go->modet[0].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD0:
+ go->modet[0].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD1:
+ go->modet[1].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD1:
+ go->modet[1].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD1:
+ go->modet[1].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD2:
+ go->modet[2].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD2:
+ go->modet[2].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD2:
+ go->modet[2].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD3:
+ go->modet[3].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD3:
+ go->modet[3].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD3:
+ go->modet[3].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_DETECT_MD_REGION_GRID:
+ mt = go->modet_map;
+ for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
+ memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
+ break;
+ default:
+ return -EINVAL;
}
-#endif
+ return 0;
+}
static struct v4l2_file_operations go7007_fops = {
.owner = THIS_MODULE,
@@ -926,7 +895,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
.vidioc_log_status = vidioc_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_subscribe_event = vidioc_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
@@ -938,12 +907,144 @@ static struct video_device go7007_template = {
.tvnorms = V4L2_STD_ALL,
};
+static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
+ .s_ctrl = go7007_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD0,
+ .name = "Pixel Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD0,
+ .name = "Motion Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD0,
+ .name = "MB Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD1,
+ .name = "Pixel Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD1,
+ .name = "Motion Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD1,
+ .name = "MB Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD2,
+ .name = "Pixel Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD2,
+ .name = "Motion Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD2,
+ .name = "MB Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD3,
+ .name = "Pixel Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD3,
+ .name = "Motion Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD3,
+ .name = "MB Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_DETECT_MD_REGION_GRID,
+ .dims = { 576 / 16, 720 / 16 },
+ .max = 3,
+ .step = 1,
+};
+
int go7007_v4l2_ctrl_init(struct go7007 *go)
{
struct v4l2_ctrl_handler *hdl = &go->hdl;
struct v4l2_ctrl *ctrl;
- v4l2_ctrl_handler_init(hdl, 13);
+ v4l2_ctrl_handler_init(hdl, 22);
go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
@@ -968,6 +1069,24 @@ int go7007_v4l2_ctrl_init(struct go7007 *go)
V4L2_JPEG_ACTIVE_MARKER_DHT);
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL);
+ go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
+ V4L2_CID_DETECT_MD_MODE,
+ V4L2_DETECT_MD_MODE_REGION_GRID,
+ 1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
+ V4L2_DETECT_MD_MODE_DISABLED);
if (hdl->error) {
int rv = hdl->error;
@@ -1001,7 +1120,6 @@ int go7007_v4l2_init(struct go7007 *go)
*vdev = go7007_template;
vdev->lock = &go->serialize_lock;
vdev->queue = &go->vidq;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(vdev, go);
vdev->v4l2_dev = &go->v4l2_dev;
if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
diff --git a/drivers/staging/media/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c
index eaa2b0990a1b..bb846680bcd4 100644
--- a/drivers/staging/media/go7007/s2250-board.c
+++ b/drivers/media/usb/go7007/s2250-board.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -573,11 +569,12 @@ static int s2250_probe(struct i2c_client *client,
if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
data = kzalloc(16, GFP_KERNEL);
if (data != NULL) {
- int rc;
- rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
+ int rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
data, 16, 1);
+
if (rc > 0) {
u8 mask;
+
data[0] = 0;
mask = 1<<5;
data[0] &= ~mask;
diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c
index 9eb2a20ae40a..d22d7d574672 100644
--- a/drivers/staging/media/go7007/snd-go7007.c
+++ b/drivers/media/usb/go7007/snd-go7007.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/media/usb/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c
index 67db674bb044..0e9ee8b50bb7 100644
--- a/drivers/media/usb/gspca/autogain_functions.c
+++ b/drivers/media/usb/gspca/autogain_functions.c
@@ -121,9 +121,9 @@ int gspca_coarse_grained_expo_autogain(
orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
- gain_low = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+ gain_low = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
5 * 2 + gspca_dev->gain->minimum;
- gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+ gain_high = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
5 * 4 + gspca_dev->gain->minimum;
/* If we are of a multiple of deadzone, do multiple steps to reach the
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index f3a7ace0fac9..e8cf23c91cef 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -603,10 +603,13 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
}
/*
- * look for an input transfer endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting.
+ *
+ * If xfer_ep is invalid, return the first valid ep found, otherwise
+ * look for exactly the ep with address equal to xfer_ep.
*/
static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
- int xfer)
+ int xfer, int xfer_ep)
{
struct usb_host_endpoint *ep;
int i, attr;
@@ -616,7 +619,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (attr == xfer
&& ep->desc.wMaxPacketSize != 0
- && usb_endpoint_dir_in(&ep->desc))
+ && usb_endpoint_dir_in(&ep->desc)
+ && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep))
return ep;
}
return NULL;
@@ -689,7 +693,8 @@ static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
found = 0;
for (j = 0; j < nbalt; j++) {
ep = alt_xfer(&intf->altsetting[j],
- USB_ENDPOINT_XFER_ISOC);
+ USB_ENDPOINT_XFER_ISOC,
+ gspca_dev->xfer_ep);
if (ep == NULL)
continue;
if (ep->desc.bInterval == 0) {
@@ -862,7 +867,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* if bulk or the subdriver forced an altsetting, get the endpoint */
if (gspca_dev->alt != 0) {
gspca_dev->alt--; /* (previous version compatibility) */
- ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+ ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer,
+ gspca_dev->xfer_ep);
if (ep == NULL) {
pr_err("bad altsetting %d\n", gspca_dev->alt);
return -EIO;
@@ -904,7 +910,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (!gspca_dev->cam.no_urb_create) {
PDEBUG(D_STREAM, "init transfer alt %d", alt);
ret = create_urbs(gspca_dev,
- alt_xfer(&intf->altsetting[alt], xfer));
+ alt_xfer(&intf->altsetting[alt], xfer,
+ gspca_dev->xfer_ep));
if (ret < 0) {
destroy_urbs(gspca_dev);
goto out;
@@ -1102,8 +1109,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct gspca_dev *gspca_dev = video_drvdata(file);
fmt->fmt.pix = gspca_dev->pixfmt;
- /* some drivers use priv internally, zero it before giving it to
- userspace */
+ /* some drivers use priv internally, zero it before giving it back to
+ the core */
fmt->fmt.pix.priv = 0;
return 0;
}
@@ -1139,8 +1146,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
fmt->fmt.pix.height = h;
gspca_dev->sd_desc->try_fmt(gspca_dev, fmt);
}
- /* some drivers use priv internally, zero it before giving it to
- userspace */
+ /* some drivers use priv internally, zero it before giving it back to
+ the core */
fmt->fmt.pix.priv = 0;
return mode; /* used when s_fmt */
}
@@ -2030,6 +2037,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
}
gspca_dev->dev = dev;
gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
+ gspca_dev->xfer_ep = -1;
/* check if any audio device */
if (dev->actconfig->desc.bNumInterfaces != 1) {
@@ -2058,7 +2066,6 @@ int gspca_dev_probe2(struct usb_interface *intf,
gspca_dev->vdev = gspca_template;
gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
video_set_drvdata(&gspca_dev->vdev, gspca_dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
gspca_dev->module = module;
gspca_dev->present = 1;
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index 300642dc1a17..f06253cd7469 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -205,6 +205,7 @@ struct gspca_dev {
char memory; /* memory type (V4L2_MEMORY_xxx) */
__u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */
+ int xfer_ep; /* USB transfer endpoint address */
u8 audio; /* presence of audio device */
/* (*) These variables are proteced by both usb_lock and queue_lock,
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c
index 081f05162809..45bc1f51c5d8 100644
--- a/drivers/media/usb/gspca/kinect.c
+++ b/drivers/media/usb/gspca/kinect.c
@@ -36,6 +36,8 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
MODULE_LICENSE("GPL");
+static bool depth_mode;
+
struct pkt_hdr {
uint8_t magic[2];
uint8_t pad;
@@ -73,6 +75,14 @@ struct sd {
#define FPS_HIGH 0x0100
+static const struct v4l2_pix_format depth_camera_mode[] = {
+ {640, 480, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
+ .bytesperline = 640 * 10 / 8,
+ .sizeimage = 640 * 480 * 10 / 8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = MODE_640x488 | FORMAT_Y10B},
+};
+
static const struct v4l2_pix_format video_camera_mode[] = {
{640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 640,
@@ -219,7 +229,7 @@ static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
}
/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
+static int sd_config_video(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -227,8 +237,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->cam_tag = 0;
- /* Only video stream is supported for now,
- * which has stream flag = 0x80 */
sd->stream_flag = 0x80;
cam = &gspca_dev->cam;
@@ -236,6 +244,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = video_camera_mode;
cam->nmodes = ARRAY_SIZE(video_camera_mode);
+ gspca_dev->xfer_ep = 0x81;
+
#if 0
/* Setting those values is not needed for video stream */
cam->npkt = 15;
@@ -245,6 +255,26 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
+static int sd_config_depth(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct cam *cam;
+
+ sd->cam_tag = 0;
+
+ sd->stream_flag = 0x70;
+
+ cam = &gspca_dev->cam;
+
+ cam->cam_mode = depth_camera_mode;
+ cam->nmodes = ARRAY_SIZE(depth_camera_mode);
+
+ gspca_dev->xfer_ep = 0x82;
+
+ return 0;
+}
+
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
@@ -253,7 +283,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
-static int sd_start(struct gspca_dev *gspca_dev)
+static int sd_start_video(struct gspca_dev *gspca_dev)
{
int mode;
uint8_t fmt_reg, fmt_val;
@@ -325,12 +355,39 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_stopN(struct gspca_dev *gspca_dev)
+static int sd_start_depth(struct gspca_dev *gspca_dev)
+{
+ /* turn off IR-reset function */
+ write_register(gspca_dev, 0x105, 0x00);
+
+ /* reset depth stream */
+ write_register(gspca_dev, 0x06, 0x00);
+ /* Depth Stream Format 0x03: 11 bit stream | 0x02: 10 bit */
+ write_register(gspca_dev, 0x12, 0x02);
+ /* Depth Stream Resolution 1: standard (640x480) */
+ write_register(gspca_dev, 0x13, 0x01);
+ /* Depth Framerate / 0x1e (30): 30 fps */
+ write_register(gspca_dev, 0x14, 0x1e);
+ /* Depth Stream Control / 2: Open Depth Stream */
+ write_register(gspca_dev, 0x06, 0x02);
+ /* disable depth hflip / LSB = 0: Smoothing Disabled */
+ write_register(gspca_dev, 0x17, 0x00);
+
+ return 0;
+}
+
+static void sd_stopN_video(struct gspca_dev *gspca_dev)
{
/* reset video stream */
write_register(gspca_dev, 0x05, 0x00);
}
+static void sd_stopN_depth(struct gspca_dev *gspca_dev)
+{
+ /* reset depth stream */
+ write_register(gspca_dev, 0x06, 0x00);
+}
+
static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -366,12 +423,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
}
/* sub-driver description */
-static const struct sd_desc sd_desc = {
+static const struct sd_desc sd_desc_video = {
.name = MODULE_NAME,
- .config = sd_config,
+ .config = sd_config_video,
.init = sd_init,
- .start = sd_start,
- .stopN = sd_stopN,
+ .start = sd_start_video,
+ .stopN = sd_stopN_video,
+ .pkt_scan = sd_pkt_scan,
+ /*
+ .get_streamparm = sd_get_streamparm,
+ .set_streamparm = sd_set_streamparm,
+ */
+};
+static const struct sd_desc sd_desc_depth = {
+ .name = MODULE_NAME,
+ .config = sd_config_depth,
+ .init = sd_init,
+ .start = sd_start_depth,
+ .stopN = sd_stopN_depth,
.pkt_scan = sd_pkt_scan,
/*
.get_streamparm = sd_get_streamparm,
@@ -391,8 +460,12 @@ MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
- THIS_MODULE);
+ if (depth_mode)
+ return gspca_dev_probe(intf, id, &sd_desc_depth,
+ sizeof(struct sd), THIS_MODULE);
+ else
+ return gspca_dev_probe(intf, id, &sd_desc_video,
+ sizeof(struct sd), THIS_MODULE);
}
static struct usb_driver sd_driver = {
@@ -408,3 +481,6 @@ static struct usb_driver sd_driver = {
};
module_usb_driver(sd_driver);
+
+module_param(depth_mode, bool, 0644);
+MODULE_PARM_DESC(depth_mode, "0=video 1=depth");
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
index 339adce7c7a5..8b08bd0172f4 100644
--- a/drivers/media/usb/gspca/pac7302.c
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -394,9 +394,9 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 10; i++) {
v = max[i];
- v += (sd->brightness->val - sd->brightness->maximum)
- * 150 / sd->brightness->maximum; /* 200 ? */
- v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
+ v += (sd->brightness->val - (s32)sd->brightness->maximum)
+ * 150 / (s32)sd->brightness->maximum; /* 200 ? */
+ v -= delta[i] * sd->contrast->val / (s32)sd->contrast->maximum;
if (v < 0)
v = 0;
else if (v > 0xff)
@@ -419,7 +419,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x11, 0x01);
reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 9; i++) {
- v = a[i] * sd->saturation->val / sd->saturation->maximum;
+ v = a[i] * sd->saturation->val / (s32)sd->saturation->maximum;
v += b[i];
reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index ecbcb39feb71..6696b2ec34e9 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -913,7 +913,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
desired_avg_lum, deadzone))
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
} else {
- int gain_knee = gspca_dev->gain->maximum * 9 / 10;
+ int gain_knee = (s32)gspca_dev->gain->maximum * 9 / 10;
if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
deadzone, gain_knee, sd->exposure_knee))
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 6bce01a674f9..59d15fd242ba 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -1022,14 +1022,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = dev->bulk_in_size;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
if (f->fmt.pix.width == 720) {
/* SDTV formats */
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
} else {
/* HDTV formats */
- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE240M;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
f->fmt.pix.field = V4L2_FIELD_NONE;
}
return 0;
@@ -1240,7 +1239,6 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
strcpy(dev->video_dev->name, "Hauppauge HD PVR");
dev->video_dev->v4l2_dev = &dev->v4l2_dev;
video_set_drvdata(dev->video_dev, dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->video_dev->flags);
res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
if (res < 0) {
diff --git a/drivers/media/usb/msi2500/Kconfig b/drivers/media/usb/msi2500/Kconfig
new file mode 100644
index 000000000000..9eff8a76ff0e
--- /dev/null
+++ b/drivers/media/usb/msi2500/Kconfig
@@ -0,0 +1,5 @@
+config USB_MSI2500
+ tristate "Mirics MSi2500"
+ depends on VIDEO_V4L2 && SPI
+ select VIDEOBUF2_VMALLOC
+ select MEDIA_TUNER_MSI001
diff --git a/drivers/media/usb/msi2500/Makefile b/drivers/media/usb/msi2500/Makefile
new file mode 100644
index 000000000000..b3bc2e53707f
--- /dev/null
+++ b/drivers/media/usb/msi2500/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_MSI2500) += msi2500.o
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/media/usb/msi2500/msi2500.c
index 08d0d096b881..26b133414032 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -34,6 +34,10 @@
#include <media/videobuf2-vmalloc.h>
#include <linux/spi/spi.h>
+static bool msi2500_emulated_fmt;
+module_param_named(emulated_formats, msi2500_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
/*
* iConfiguration 0
* bInterfaceNumber 0
@@ -51,11 +55,14 @@
#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
#define MAX_ISOC_ERRORS 20
-/* TODO: These should be moved to V4L2 API */
-#define V4L2_PIX_FMT_SDR_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
-#define V4L2_PIX_FMT_SDR_S12 v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */
-#define V4L2_PIX_FMT_SDR_S14 v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */
-#define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
+/*
+ * TODO: These formats should be moved to V4L2 API. Formats are currently
+ * disabled from formats[] table, not visible to userspace.
+ */
+ /* signed 12-bit */
+#define MSI2500_PIX_FMT_SDR_S12 v4l2_fourcc('D', 'S', '1', '2')
+/* Mirics MSi2500 format 384 */
+#define MSI2500_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4')
static const struct v4l2_frequency_band bands[] = {
{
@@ -69,45 +76,50 @@ static const struct v4l2_frequency_band bands[] = {
};
/* stream formats */
-struct msi3101_format {
+struct msi2500_format {
char *name;
u32 pixelformat;
+ u32 buffersize;
};
/* format descriptions for capture and preview */
-static struct msi3101_format formats[] = {
+static struct msi2500_format formats[] = {
{
- .name = "IQ U8",
- .pixelformat = V4L2_SDR_FMT_CU8,
- }, {
- .name = "IQ U16LE",
- .pixelformat = V4L2_SDR_FMT_CU16LE,
+ .name = "Complex S8",
+ .pixelformat = V4L2_SDR_FMT_CS8,
+ .buffersize = 3 * 1008,
#if 0
}, {
- .name = "8-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_S8,
- }, {
.name = "10+2-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_MSI2500_384,
+ .pixelformat = MSI2500_PIX_FMT_SDR_MSI2500_384,
}, {
.name = "12-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_S12,
- }, {
- .name = "14-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_S14,
+ .pixelformat = MSI2500_PIX_FMT_SDR_S12,
#endif
+ }, {
+ .name = "Complex S14LE",
+ .pixelformat = V4L2_SDR_FMT_CS14LE,
+ .buffersize = 3 * 1008,
+ }, {
+ .name = "Complex U8 (emulated)",
+ .pixelformat = V4L2_SDR_FMT_CU8,
+ .buffersize = 3 * 1008,
+ }, {
+ .name = "Complex U16LE (emulated)",
+ .pixelformat = V4L2_SDR_FMT_CU16LE,
+ .buffersize = 3 * 1008,
},
};
static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
/* intermediate buffers with raw data from the USB device */
-struct msi3101_frame_buf {
+struct msi2500_frame_buf {
struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
struct list_head list;
};
-struct msi3101_state {
+struct msi2500_state {
struct video_device vdev;
struct v4l2_device v4l2_dev;
struct v4l2_subdev *v4l2_subdev;
@@ -127,13 +139,13 @@ struct msi3101_state {
unsigned int f_adc;
u32 pixelformat;
+ u32 buffersize;
+ unsigned int num_formats;
unsigned int isoc_errors; /* number of contiguous ISOC errors */
unsigned int vb_full; /* vb is full and packets dropped */
struct urb *urbs[MAX_ISO_BUFS];
- int (*convert_stream)(struct msi3101_state *s, u8 *dst, u8 *src,
- unsigned int src_len);
/* Controls */
struct v4l2_ctrl_handler hdl;
@@ -145,17 +157,17 @@ struct msi3101_state {
};
/* Private functions */
-static struct msi3101_frame_buf *msi3101_get_next_fill_buf(
- struct msi3101_state *s)
+static struct msi2500_frame_buf *msi2500_get_next_fill_buf(
+ struct msi2500_state *s)
{
unsigned long flags = 0;
- struct msi3101_frame_buf *buf = NULL;
+ struct msi2500_frame_buf *buf = NULL;
spin_lock_irqsave(&s->queued_bufs_lock, flags);
if (list_empty(&s->queued_bufs))
goto leave;
- buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf, list);
+ buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf, list);
list_del(&buf->list);
leave:
spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
@@ -174,116 +186,8 @@ leave:
* +---------------------------------------------------------------------------
* signed 8-bit sample
* 504 * 2 = 1008 samples
- */
-static int msi3101_convert_stream_504(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
-{
- int i, i_max, dst_len = 0;
- u32 sample_num[3];
-
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
-
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
- dev_dbg_ratelimited(&s->udev->dev,
- "%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
- }
-
- /*
- * Dump all unknown 'garbage' data - maybe we will discover
- * someday if there is something rational...
- */
- dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
- /* 504 x I+Q samples */
- src += 16;
- memcpy(dst, src, 1008);
- src += 1008;
- dst += 1008;
- dst_len += 1008;
- }
-
- /* calculate samping rate and output it in 10 seconds intervals */
- if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
- unsigned long jiffies_now = jiffies;
- unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
- unsigned int samples = sample_num[i_max - 1] - s->sample;
- s->jiffies_next = jiffies_now;
- s->sample = sample_num[i_max - 1];
- dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
- src_len, samples, msecs,
- samples * 1000UL / msecs);
- }
-
- /* next sample (sample = sample + i * 504) */
- s->next_sample = sample_num[i_max - 1] + 504;
-
- return dst_len;
-}
-
-static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
-{
- int i, j, i_max, dst_len = 0;
- u32 sample_num[3];
- s8 *s8src;
- u8 *u8dst;
-
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
- u8dst = (u8 *) dst;
-
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
- dev_dbg_ratelimited(&s->udev->dev,
- "%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
- }
-
- /*
- * Dump all unknown 'garbage' data - maybe we will discover
- * someday if there is something rational...
- */
- dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
- /* 504 x I+Q samples */
- src += 16;
-
- s8src = (s8 *) src;
- for (j = 0; j < 1008; j++)
- *u8dst++ = *s8src++ + 128;
-
- src += 1008;
- dst += 1008;
- dst_len += 1008;
- }
-
- /* calculate samping rate and output it in 10 seconds intervals */
- if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
-#define MSECS 10000UL
- unsigned int samples = sample_num[i_max - 1] - s->sample;
- s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
- s->sample = sample_num[i_max - 1];
- dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
- src_len, samples, MSECS,
- samples * 1000UL / MSECS);
- }
-
- /* next sample (sample = sample + i * 504) */
- s->next_sample = sample_num[i_max - 1] + 504;
-
- return dst_len;
-}
-
-/*
+ *
+ *
* +===========================================================================
* | 00-1023 | USB packet type '384'
* +===========================================================================
@@ -326,61 +230,8 @@ static int msi3101_convert_stream_504_u8(struct msi3101_state *s, u8 *dst,
* Number 2 (0b10) was never seen.
*
* 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes
- */
-static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
-{
- int i, i_max, dst_len = 0;
- u32 sample_num[3];
-
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
- dev_dbg_ratelimited(&s->udev->dev,
- "%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
- }
-
- /*
- * Dump all unknown 'garbage' data - maybe we will discover
- * someday if there is something rational...
- */
- dev_dbg_ratelimited(&s->udev->dev,
- "%*ph %*ph\n", 12, &src[4], 24, &src[1000]);
-
- /* 384 x I+Q samples */
- src += 16;
- memcpy(dst, src, 984);
- src += 984 + 24;
- dst += 984;
- dst_len += 984;
- }
-
- /* calculate samping rate and output it in 10 seconds intervals */
- if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
- unsigned long jiffies_now = jiffies;
- unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
- unsigned int samples = sample_num[i_max - 1] - s->sample;
- s->jiffies_next = jiffies_now;
- s->sample = sample_num[i_max - 1];
- dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu bits=%d.%d.%d.%d\n",
- src_len, samples, msecs,
- samples * 1000UL / msecs,
- s->sample_ctrl_bit[0], s->sample_ctrl_bit[1],
- s->sample_ctrl_bit[2], s->sample_ctrl_bit[3]);
- }
-
- /* next sample (sample = sample + i * 384) */
- s->next_sample = sample_num[i_max - 1] + 384;
-
- return dst_len;
-}
-
-/*
+ *
+ *
* +===========================================================================
* | 00-1023 | USB packet type '336'
* +===========================================================================
@@ -391,59 +242,8 @@ static int msi3101_convert_stream_384(struct msi3101_state *s, u8 *dst,
* | 16-1023 | samples
* +---------------------------------------------------------------------------
* signed 12-bit sample
- */
-static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
-{
- int i, i_max, dst_len = 0;
- u32 sample_num[3];
-
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
-
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
- dev_dbg_ratelimited(&s->udev->dev,
- "%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
- }
-
- /*
- * Dump all unknown 'garbage' data - maybe we will discover
- * someday if there is something rational...
- */
- dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
- /* 336 x I+Q samples */
- src += 16;
- memcpy(dst, src, 1008);
- src += 1008;
- dst += 1008;
- dst_len += 1008;
- }
-
- /* calculate samping rate and output it in 10 seconds intervals */
- if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
- unsigned long jiffies_now = jiffies;
- unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
- unsigned int samples = sample_num[i_max - 1] - s->sample;
- s->jiffies_next = jiffies_now;
- s->sample = sample_num[i_max - 1];
- dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
- src_len, samples, msecs,
- samples * 1000UL / msecs);
- }
-
- /* next sample (sample = sample + i * 336) */
- s->next_sample = sample_num[i_max - 1] + 336;
-
- return dst_len;
-}
-
-/*
+ *
+ *
* +===========================================================================
* | 00-1023 | USB packet type '252'
* +===========================================================================
@@ -455,75 +255,24 @@ static int msi3101_convert_stream_336(struct msi3101_state *s, u8 *dst,
* +---------------------------------------------------------------------------
* signed 14-bit sample
*/
-static int msi3101_convert_stream_252(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
-{
- int i, i_max, dst_len = 0;
- u32 sample_num[3];
-
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
-
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
- dev_dbg_ratelimited(&s->udev->dev,
- "%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
- }
- /*
- * Dump all unknown 'garbage' data - maybe we will discover
- * someday if there is something rational...
- */
- dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
-
- /* 252 x I+Q samples */
- src += 16;
- memcpy(dst, src, 1008);
- src += 1008;
- dst += 1008;
- dst_len += 1008;
- }
-
- /* calculate samping rate and output it in 10 seconds intervals */
- if ((s->jiffies_next + msecs_to_jiffies(10000)) <= jiffies) {
- unsigned long jiffies_now = jiffies;
- unsigned long msecs = jiffies_to_msecs(jiffies_now) - jiffies_to_msecs(s->jiffies_next);
- unsigned int samples = sample_num[i_max - 1] - s->sample;
- s->jiffies_next = jiffies_now;
- s->sample = sample_num[i_max - 1];
- dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
- src_len, samples, msecs,
- samples * 1000UL / msecs);
- }
-
- /* next sample (sample = sample + i * 252) */
- s->next_sample = sample_num[i_max - 1] + 252;
-
- return dst_len;
-}
-
-static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst,
- u8 *src, unsigned int src_len)
+static int msi2500_convert_stream(struct msi2500_state *s, u8 *dst, u8 *src,
+ unsigned int src_len)
{
- int i, j, i_max, dst_len = 0;
- u32 sample_num[3];
- u16 *u16dst = (u16 *) dst;
- struct {signed int x:14;} se;
+ unsigned int i, j, transactions, dst_len = 0;
+ u32 sample[3];
- /* There could be 1-3 1024 bytes URB frames */
- i_max = src_len / 1024;
+ /* There could be 1-3 1024 byte transactions per packet */
+ transactions = src_len / 1024;
- for (i = 0; i < i_max; i++) {
- sample_num[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0] << 0;
- if (i == 0 && s->next_sample != sample_num[0]) {
+ for (i = 0; i < transactions; i++) {
+ sample[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 |
+ src[0] << 0;
+ if (i == 0 && s->next_sample != sample[0]) {
dev_dbg_ratelimited(&s->udev->dev,
"%d samples lost, %d %08x:%08x\n",
- sample_num[0] - s->next_sample,
- src_len, s->next_sample, sample_num[0]);
+ sample[0] - s->next_sample,
+ src_len, s->next_sample, sample[0]);
}
/*
@@ -532,49 +281,96 @@ static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst,
*/
dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]);
- /* 252 x I+Q samples */
- src += 16;
-
- for (j = 0; j < 1008; j += 4) {
- unsigned int usample[2];
- int ssample[2];
+ src += 16; /* skip header */
- usample[0] = src[j + 0] >> 0 | src[j + 1] << 8;
- usample[1] = src[j + 2] >> 0 | src[j + 3] << 8;
+ switch (s->pixelformat) {
+ case V4L2_SDR_FMT_CU8: /* 504 x IQ samples */
+ {
+ s8 *s8src = (s8 *) src;
+ u8 *u8dst = (u8 *) dst;
- /* sign extension from 14-bit to signed int */
- ssample[0] = se.x = usample[0];
- ssample[1] = se.x = usample[1];
+ for (j = 0; j < 1008; j++)
+ *u8dst++ = *s8src++ + 128;
- /* from signed to unsigned */
- usample[0] = ssample[0] + 8192;
- usample[1] = ssample[1] + 8192;
-
- /* from 14-bit to 16-bit */
- *u16dst++ = (usample[0] << 2) | (usample[0] >> 12);
- *u16dst++ = (usample[1] << 2) | (usample[1] >> 12);
+ src += 1008;
+ dst += 1008;
+ dst_len += 1008;
+ s->next_sample = sample[i] + 504;
+ break;
}
+ case V4L2_SDR_FMT_CU16LE: /* 252 x IQ samples */
+ {
+ s16 *s16src = (s16 *) src;
+ u16 *u16dst = (u16 *) dst;
+ struct {signed int x:14; } se; /* sign extension */
+ unsigned int utmp;
+
+ for (j = 0; j < 1008; j += 2) {
+ /* sign extension from 14-bit to signed int */
+ se.x = *s16src++;
+ /* from signed int to unsigned int */
+ utmp = se.x + 8192;
+ /* from 14-bit to 16-bit */
+ *u16dst++ = utmp << 2 | utmp >> 12;
+ }
- src += 1008;
- dst += 1008;
- dst_len += 1008;
+ src += 1008;
+ dst += 1008;
+ dst_len += 1008;
+ s->next_sample = sample[i] + 252;
+ break;
+ }
+ case MSI2500_PIX_FMT_SDR_MSI2500_384: /* 384 x IQ samples */
+ /* Dump unknown 'garbage' data */
+ dev_dbg_ratelimited(&s->udev->dev,
+ "%*ph\n", 24, &src[1000]);
+ memcpy(dst, src, 984);
+ src += 984 + 24;
+ dst += 984;
+ dst_len += 984;
+ s->next_sample = sample[i] + 384;
+ break;
+ case V4L2_SDR_FMT_CS8: /* 504 x IQ samples */
+ memcpy(dst, src, 1008);
+ src += 1008;
+ dst += 1008;
+ dst_len += 1008;
+ s->next_sample = sample[i] + 504;
+ break;
+ case MSI2500_PIX_FMT_SDR_S12: /* 336 x IQ samples */
+ memcpy(dst, src, 1008);
+ src += 1008;
+ dst += 1008;
+ dst_len += 1008;
+ s->next_sample = sample[i] + 336;
+ break;
+ case V4L2_SDR_FMT_CS14LE: /* 252 x IQ samples */
+ memcpy(dst, src, 1008);
+ src += 1008;
+ dst += 1008;
+ dst_len += 1008;
+ s->next_sample = sample[i] + 252;
+ break;
+ default:
+ break;
+ }
}
- /* calculate samping rate and output it in 10 seconds intervals */
+ /* calculate sample rate and output it in 10 seconds intervals */
if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
-#define MSECS 10000UL
- unsigned int samples = sample_num[i_max - 1] - s->sample;
+ #define MSECS 10000UL
+ unsigned int msecs = jiffies_to_msecs(jiffies -
+ s->jiffies_next + msecs_to_jiffies(MSECS));
+ unsigned int samples = s->next_sample - s->sample;
+
s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
- s->sample = sample_num[i_max - 1];
+ s->sample = s->next_sample;
dev_dbg(&s->udev->dev,
- "slen=%d samples=%u msecs=%lu sampling rate=%lu\n",
- src_len, samples, MSECS,
- samples * 1000UL / MSECS);
+ "size=%u samples=%u msecs=%u sample rate=%lu\n",
+ src_len, samples, msecs,
+ samples * 1000UL / msecs);
}
- /* next sample (sample = sample + i * 252) */
- s->next_sample = sample_num[i_max - 1] + 252;
-
return dst_len;
}
@@ -582,12 +378,12 @@ static int msi3101_convert_stream_252_u16(struct msi3101_state *s, u8 *dst,
* This gets called for the Isochronous pipe (stream). This is done in interrupt
* time, so it has to be fast, not crash, and not stall. Neat.
*/
-static void msi3101_isoc_handler(struct urb *urb)
+static void msi2500_isoc_handler(struct urb *urb)
{
- struct msi3101_state *s = (struct msi3101_state *)urb->context;
+ struct msi2500_state *s = (struct msi2500_state *)urb->context;
int i, flen, fstatus;
unsigned char *iso_buf = NULL;
- struct msi3101_frame_buf *fbuf;
+ struct msi2500_frame_buf *fbuf;
if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN)) {
@@ -598,7 +394,7 @@ static void msi3101_isoc_handler(struct urb *urb)
if (unlikely(urb->status != 0)) {
dev_dbg(&s->udev->dev,
- "msi3101_isoc_handler() called with status %d\n",
+ "msi2500_isoc_handler() called with status %d\n",
urb->status);
/* Give up after a number of contiguous errors */
if (++s->isoc_errors > MAX_ISOC_ERRORS)
@@ -631,7 +427,7 @@ static void msi3101_isoc_handler(struct urb *urb)
iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
/* Get free framebuffer */
- fbuf = msi3101_get_next_fill_buf(s);
+ fbuf = msi2500_get_next_fill_buf(s);
if (unlikely(fbuf == NULL)) {
s->vb_full++;
dev_dbg_ratelimited(&s->udev->dev,
@@ -642,7 +438,7 @@ static void msi3101_isoc_handler(struct urb *urb)
/* fill framebuffer */
ptr = vb2_plane_vaddr(&fbuf->vb, 0);
- flen = s->convert_stream(s, ptr, iso_buf, flen);
+ flen = msi2500_convert_stream(s, ptr, iso_buf, flen);
vb2_set_plane_payload(&fbuf->vb, 0, flen);
vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
}
@@ -651,13 +447,14 @@ handler_end:
i = usb_submit_urb(urb, GFP_ATOMIC);
if (unlikely(i != 0))
dev_dbg(&s->udev->dev,
- "Error (%d) re-submitting urb in msi3101_isoc_handler\n",
+ "Error (%d) re-submitting urb in msi2500_isoc_handler\n",
i);
}
-static void msi3101_iso_stop(struct msi3101_state *s)
+static void msi2500_iso_stop(struct msi2500_state *s)
{
int i;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
/* Unlinking ISOC buffers one by one */
@@ -670,9 +467,10 @@ static void msi3101_iso_stop(struct msi3101_state *s)
}
}
-static void msi3101_iso_free(struct msi3101_state *s)
+static void msi2500_iso_free(struct msi2500_state *s)
{
int i;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
/* Freeing ISOC buffers one by one */
@@ -692,20 +490,21 @@ static void msi3101_iso_free(struct msi3101_state *s)
}
/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static void msi3101_isoc_cleanup(struct msi3101_state *s)
+static void msi2500_isoc_cleanup(struct msi2500_state *s)
{
dev_dbg(&s->udev->dev, "%s:\n", __func__);
- msi3101_iso_stop(s);
- msi3101_iso_free(s);
+ msi2500_iso_stop(s);
+ msi2500_iso_free(s);
}
/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static int msi3101_isoc_init(struct msi3101_state *s)
+static int msi2500_isoc_init(struct msi2500_state *s)
{
struct usb_device *udev;
struct urb *urb;
int i, j, ret;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
s->isoc_errors = 0;
@@ -721,7 +520,7 @@ static int msi3101_isoc_init(struct msi3101_state *s)
if (urb == NULL) {
dev_err(&s->udev->dev,
"Failed to allocate urb %d\n", i);
- msi3101_isoc_cleanup(s);
+ msi2500_isoc_cleanup(s);
return -ENOMEM;
}
s->urbs[i] = urb;
@@ -737,11 +536,11 @@ static int msi3101_isoc_init(struct msi3101_state *s)
dev_err(&s->udev->dev,
"Failed to allocate urb buffer %d\n",
i);
- msi3101_isoc_cleanup(s);
+ msi2500_isoc_cleanup(s);
return -ENOMEM;
}
urb->transfer_buffer_length = ISO_BUFFER_SIZE;
- urb->complete = msi3101_isoc_handler;
+ urb->complete = msi2500_isoc_handler;
urb->context = s;
urb->start_frame = 0;
urb->number_of_packets = ISO_FRAMES_PER_DESC;
@@ -758,7 +557,7 @@ static int msi3101_isoc_init(struct msi3101_state *s)
dev_err(&s->udev->dev,
"isoc_init() submit_urb %d failed with error %d\n",
i, ret);
- msi3101_isoc_cleanup(s);
+ msi2500_isoc_cleanup(s);
return ret;
}
dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]);
@@ -769,16 +568,17 @@ static int msi3101_isoc_init(struct msi3101_state *s)
}
/* Must be called with vb_queue_lock hold */
-static void msi3101_cleanup_queued_bufs(struct msi3101_state *s)
+static void msi2500_cleanup_queued_bufs(struct msi2500_state *s)
{
unsigned long flags = 0;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
spin_lock_irqsave(&s->queued_bufs_lock, flags);
while (!list_empty(&s->queued_bufs)) {
- struct msi3101_frame_buf *buf;
+ struct msi2500_frame_buf *buf;
- buf = list_entry(s->queued_bufs.next, struct msi3101_frame_buf,
+ buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf,
list);
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
@@ -787,11 +587,12 @@ static void msi3101_cleanup_queued_bufs(struct msi3101_state *s)
}
/* The user yanked out the cable... */
-static void msi3101_disconnect(struct usb_interface *intf)
+static void msi2500_disconnect(struct usb_interface *intf)
{
struct v4l2_device *v = usb_get_intfdata(intf);
- struct msi3101_state *s =
- container_of(v, struct msi3101_state, v4l2_dev);
+ struct msi2500_state *s =
+ container_of(v, struct msi2500_state, v4l2_dev);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->vb_queue_lock);
@@ -807,10 +608,11 @@ static void msi3101_disconnect(struct usb_interface *intf)
v4l2_device_put(&s->v4l2_dev);
}
-static int msi3101_querycap(struct file *file, void *fh,
+static int msi2500_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
@@ -823,33 +625,28 @@ static int msi3101_querycap(struct file *file, void *fh,
}
/* Videobuf2 operations */
-static int msi3101_queue_setup(struct vb2_queue *vq,
+static int msi2500_queue_setup(struct vb2_queue *vq,
const struct v4l2_format *fmt, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
- struct msi3101_state *s = vb2_get_drv_priv(vq);
+ struct msi2500_state *s = vb2_get_drv_priv(vq);
+
dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
/* Absolute min and max number of buffers available for mmap() */
*nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32);
*nplanes = 1;
- /*
- * 3, wMaxPacketSize 3x 1024 bytes
- * 504, max IQ sample pairs per 1024 frame
- * 2, two samples, I and Q
- * 2, 16-bit is enough for single sample
- */
- sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 2);
+ sizes[0] = PAGE_ALIGN(s->buffersize);
dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
__func__, *nbuffers, sizes[0]);
return 0;
}
-static void msi3101_buf_queue(struct vb2_buffer *vb)
+static void msi2500_buf_queue(struct vb2_buffer *vb)
{
- struct msi3101_state *s = vb2_get_drv_priv(vb->vb2_queue);
- struct msi3101_frame_buf *buf =
- container_of(vb, struct msi3101_frame_buf, vb);
+ struct msi2500_state *s = vb2_get_drv_priv(vb->vb2_queue);
+ struct msi2500_frame_buf *buf =
+ container_of(vb, struct msi2500_frame_buf, vb);
unsigned long flags = 0;
/* Check the device has not disconnected between prep and queuing */
@@ -868,18 +665,19 @@ static void msi3101_buf_queue(struct vb2_buffer *vb)
#define CMD_STOP_STREAMING 0x45
#define CMD_READ_UNKNOW 0x48
-#define msi3101_dbg_usb_control_msg(udev, r, t, v, _i, b, l) { \
- char *direction; \
- if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
- direction = ">>>"; \
+#define msi2500_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+ char *_direction; \
+ if (_t & USB_DIR_IN) \
+ _direction = "<<<"; \
else \
- direction = "<<<"; \
- dev_dbg(&udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
- "%s %*ph\n", __func__, t, r, v & 0xff, v >> 8, \
- _i & 0xff, _i >> 8, l & 0xff, l >> 8, direction, l, b); \
+ _direction = ">>>"; \
+ dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \
+ _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+ _l, _b); \
}
-static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data)
+static int msi2500_ctrl_msg(struct msi2500_state *s, u8 cmd, u32 data)
{
int ret;
u8 request = cmd;
@@ -887,7 +685,7 @@ static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data)
u16 value = (data >> 0) & 0xffff;
u16 index = (data >> 16) & 0xffff;
- msi3101_dbg_usb_control_msg(s->udev,
+ msi2500_dbg_usb_control_msg(s->udev,
request, requesttype, value, index, NULL, 0);
ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0),
@@ -902,7 +700,7 @@ static int msi3101_ctrl_msg(struct msi3101_state *s, u8 cmd, u32 data)
#define F_REF 24000000
#define DIV_R_IN 2
-static int msi3101_set_usb_adc(struct msi3101_state *s)
+static int msi2500_set_usb_adc(struct msi2500_state *s)
{
int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract;
u32 reg3, reg4, reg7;
@@ -912,41 +710,36 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
f_sr = s->f_adc;
/* set tuner, subdev, filters according to sampling rate */
- bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
+ bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
- bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
+ bandwidth = v4l2_ctrl_find(&s->hdl,
+ V4L2_CID_RF_TUNER_BANDWIDTH);
v4l2_ctrl_s_ctrl(bandwidth, s->f_adc);
}
/* select stream format */
switch (s->pixelformat) {
case V4L2_SDR_FMT_CU8:
- s->convert_stream = msi3101_convert_stream_504_u8;
- reg7 = 0x000c9407;
+ reg7 = 0x000c9407; /* 504 */
break;
case V4L2_SDR_FMT_CU16LE:
- s->convert_stream = msi3101_convert_stream_252_u16;
- reg7 = 0x00009407;
+ reg7 = 0x00009407; /* 252 */
break;
- case V4L2_PIX_FMT_SDR_S8:
- s->convert_stream = msi3101_convert_stream_504;
- reg7 = 0x000c9407;
+ case V4L2_SDR_FMT_CS8:
+ reg7 = 0x000c9407; /* 504 */
break;
- case V4L2_PIX_FMT_SDR_MSI2500_384:
- s->convert_stream = msi3101_convert_stream_384;
- reg7 = 0x0000a507;
+ case MSI2500_PIX_FMT_SDR_MSI2500_384:
+ reg7 = 0x0000a507; /* 384 */
break;
- case V4L2_PIX_FMT_SDR_S12:
- s->convert_stream = msi3101_convert_stream_336;
- reg7 = 0x00008507;
+ case MSI2500_PIX_FMT_SDR_S12:
+ reg7 = 0x00008507; /* 336 */
break;
- case V4L2_PIX_FMT_SDR_S14:
- s->convert_stream = msi3101_convert_stream_252;
- reg7 = 0x00009407;
+ case V4L2_SDR_FMT_CS14LE:
+ reg7 = 0x00009407; /* 252 */
break;
default:
- s->convert_stream = msi3101_convert_stream_504_u8;
- reg7 = 0x000c9407;
+ reg7 = 0x000c9407; /* 504 */
break;
}
@@ -1009,47 +802,49 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
dev_dbg(&s->udev->dev,
"%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n",
- __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3, reg4);
+ __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3,
+ reg4);
- ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00608008);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00608008);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00000c05);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00000c05);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00020000);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00020000);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00480102);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00480102);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, 0x00f38008);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00f38008);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, reg7);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, reg7);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, reg4);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, reg4);
if (ret)
goto err;
- ret = msi3101_ctrl_msg(s, CMD_WREG, reg3);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, reg3);
if (ret)
goto err;
err:
return ret;
};
-static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count)
+static int msi2500_start_streaming(struct vb2_queue *vq, unsigned int count)
{
- struct msi3101_state *s = vb2_get_drv_priv(vq);
+ struct msi2500_state *s = vb2_get_drv_priv(vq);
int ret;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
if (!s->udev)
@@ -1061,37 +856,37 @@ static int msi3101_start_streaming(struct vb2_queue *vq, unsigned int count)
/* wake-up tuner */
v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1);
- ret = msi3101_set_usb_adc(s);
+ ret = msi2500_set_usb_adc(s);
- ret = msi3101_isoc_init(s);
+ ret = msi2500_isoc_init(s);
if (ret)
- msi3101_cleanup_queued_bufs(s);
+ msi2500_cleanup_queued_bufs(s);
- ret = msi3101_ctrl_msg(s, CMD_START_STREAMING, 0);
+ ret = msi2500_ctrl_msg(s, CMD_START_STREAMING, 0);
mutex_unlock(&s->v4l2_lock);
return ret;
}
-static void msi3101_stop_streaming(struct vb2_queue *vq)
+static void msi2500_stop_streaming(struct vb2_queue *vq)
{
- struct msi3101_state *s = vb2_get_drv_priv(vq);
+ struct msi2500_state *s = vb2_get_drv_priv(vq);
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->v4l2_lock);
if (s->udev)
- msi3101_isoc_cleanup(s);
+ msi2500_isoc_cleanup(s);
- msi3101_cleanup_queued_bufs(s);
+ msi2500_cleanup_queued_bufs(s);
/* according to tests, at least 700us delay is required */
msleep(20);
- if (!msi3101_ctrl_msg(s, CMD_STOP_STREAMING, 0)) {
+ if (!msi2500_ctrl_msg(s, CMD_STOP_STREAMING, 0)) {
/* sleep USB IF / ADC */
- msi3101_ctrl_msg(s, CMD_WREG, 0x01000003);
+ msi2500_ctrl_msg(s, CMD_WREG, 0x01000003);
}
/* sleep tuner */
@@ -1100,22 +895,23 @@ static void msi3101_stop_streaming(struct vb2_queue *vq)
mutex_unlock(&s->v4l2_lock);
}
-static struct vb2_ops msi3101_vb2_ops = {
- .queue_setup = msi3101_queue_setup,
- .buf_queue = msi3101_buf_queue,
- .start_streaming = msi3101_start_streaming,
- .stop_streaming = msi3101_stop_streaming,
+static struct vb2_ops msi2500_vb2_ops = {
+ .queue_setup = msi2500_queue_setup,
+ .buf_queue = msi2500_buf_queue,
+ .start_streaming = msi2500_start_streaming,
+ .stop_streaming = msi2500_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
-static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
+static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
- if (f->index >= NUM_FORMATS)
+ if (f->index >= s->num_formats)
return -EINVAL;
strlcpy(f->description, formats[f->index].name, sizeof(f->description));
@@ -1124,25 +920,28 @@ static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
return 0;
}
-static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv,
+static int msi2500_g_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&s->pixelformat);
- memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
return 0;
}
-static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
+static int msi2500_s_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
struct vb2_queue *q = &s->vb_queue;
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
@@ -1150,43 +949,52 @@ static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
return -EBUSY;
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
+ for (i = 0; i < s->num_formats; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- s->pixelformat = f->fmt.sdr.pixelformat;
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
}
}
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
-static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv,
+static int msi2500_try_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
+ for (i = 0; i < s->num_formats; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
+ }
}
f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
-static int msi3101_s_tuner(struct file *file, void *priv,
+static int msi2500_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int ret;
+
dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
if (v->index == 0)
@@ -1199,10 +1007,11 @@ static int msi3101_s_tuner(struct file *file, void *priv,
return ret;
}
-static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+static int msi2500_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int ret;
+
dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
if (v->index == 0) {
@@ -1221,11 +1030,12 @@ static int msi3101_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
return ret;
}
-static int msi3101_g_frequency(struct file *file, void *priv,
+static int msi2500_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int ret = 0;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
__func__, f->tuner, f->type);
@@ -1242,11 +1052,12 @@ static int msi3101_g_frequency(struct file *file, void *priv,
return ret;
}
-static int msi3101_s_frequency(struct file *file, void *priv,
+static int msi2500_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int ret;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
__func__, f->tuner, f->type, f->frequency);
@@ -1256,7 +1067,7 @@ static int msi3101_s_frequency(struct file *file, void *priv,
bands[0].rangehigh);
dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
__func__, s->f_adc);
- ret = msi3101_set_usb_adc(s);
+ ret = msi2500_set_usb_adc(s);
} else if (f->tuner == 1) {
ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f);
} else {
@@ -1266,11 +1077,12 @@ static int msi3101_s_frequency(struct file *file, void *priv,
return ret;
}
-static int msi3101_enum_freq_bands(struct file *file, void *priv,
+static int msi2500_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
{
- struct msi3101_state *s = video_drvdata(file);
+ struct msi2500_state *s = video_drvdata(file);
int ret;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
__func__, band->tuner, band->type, band->index);
@@ -1291,13 +1103,13 @@ static int msi3101_enum_freq_bands(struct file *file, void *priv,
return ret;
}
-static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
- .vidioc_querycap = msi3101_querycap,
+static const struct v4l2_ioctl_ops msi2500_ioctl_ops = {
+ .vidioc_querycap = msi2500_querycap,
- .vidioc_enum_fmt_sdr_cap = msi3101_enum_fmt_sdr_cap,
- .vidioc_g_fmt_sdr_cap = msi3101_g_fmt_sdr_cap,
- .vidioc_s_fmt_sdr_cap = msi3101_s_fmt_sdr_cap,
- .vidioc_try_fmt_sdr_cap = msi3101_try_fmt_sdr_cap,
+ .vidioc_enum_fmt_sdr_cap = msi2500_enum_fmt_sdr_cap,
+ .vidioc_g_fmt_sdr_cap = msi2500_g_fmt_sdr_cap,
+ .vidioc_s_fmt_sdr_cap = msi2500_s_fmt_sdr_cap,
+ .vidioc_try_fmt_sdr_cap = msi2500_try_fmt_sdr_cap,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
@@ -1309,19 +1121,19 @@ static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
- .vidioc_g_tuner = msi3101_g_tuner,
- .vidioc_s_tuner = msi3101_s_tuner,
+ .vidioc_g_tuner = msi2500_g_tuner,
+ .vidioc_s_tuner = msi2500_s_tuner,
- .vidioc_g_frequency = msi3101_g_frequency,
- .vidioc_s_frequency = msi3101_s_frequency,
- .vidioc_enum_freq_bands = msi3101_enum_freq_bands,
+ .vidioc_g_frequency = msi2500_g_frequency,
+ .vidioc_s_frequency = msi2500_s_frequency,
+ .vidioc_enum_freq_bands = msi2500_enum_freq_bands,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
.vidioc_log_status = v4l2_ctrl_log_status,
};
-static const struct v4l2_file_operations msi3101_fops = {
+static const struct v4l2_file_operations msi2500_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
.release = vb2_fop_release,
@@ -1331,27 +1143,27 @@ static const struct v4l2_file_operations msi3101_fops = {
.unlocked_ioctl = video_ioctl2,
};
-static struct video_device msi3101_template = {
+static struct video_device msi2500_template = {
.name = "Mirics MSi3101 SDR Dongle",
.release = video_device_release_empty,
- .fops = &msi3101_fops,
- .ioctl_ops = &msi3101_ioctl_ops,
+ .fops = &msi2500_fops,
+ .ioctl_ops = &msi2500_ioctl_ops,
};
-static void msi3101_video_release(struct v4l2_device *v)
+static void msi2500_video_release(struct v4l2_device *v)
{
- struct msi3101_state *s =
- container_of(v, struct msi3101_state, v4l2_dev);
+ struct msi2500_state *s =
+ container_of(v, struct msi2500_state, v4l2_dev);
v4l2_ctrl_handler_free(&s->hdl);
v4l2_device_unregister(&s->v4l2_dev);
kfree(s);
}
-static int msi3101_transfer_one_message(struct spi_master *master,
+static int msi2500_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
- struct msi3101_state *s = spi_master_get_devdata(master);
+ struct msi2500_state *s = spi_master_get_devdata(master);
struct spi_transfer *t;
int ret = 0;
u32 data;
@@ -1363,7 +1175,7 @@ static int msi3101_transfer_one_message(struct spi_master *master,
data |= ((u8 *)t->tx_buf)[0] << 8;
data |= ((u8 *)t->tx_buf)[1] << 16;
data |= ((u8 *)t->tx_buf)[2] << 24;
- ret = msi3101_ctrl_msg(s, CMD_WREG, data);
+ ret = msi2500_ctrl_msg(s, CMD_WREG, data);
}
m->status = ret;
@@ -1371,11 +1183,11 @@ static int msi3101_transfer_one_message(struct spi_master *master,
return ret;
}
-static int msi3101_probe(struct usb_interface *intf,
+static int msi2500_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
- struct msi3101_state *s = NULL;
+ struct msi2500_state *s = NULL;
struct v4l2_subdev *sd;
struct spi_master *master;
int ret;
@@ -1386,9 +1198,9 @@ static int msi3101_probe(struct usb_interface *intf,
.max_speed_hz = 12000000,
};
- s = kzalloc(sizeof(struct msi3101_state), GFP_KERNEL);
+ s = kzalloc(sizeof(struct msi2500_state), GFP_KERNEL);
if (s == NULL) {
- pr_err("Could not allocate memory for msi3101_state\n");
+ pr_err("Could not allocate memory for msi2500_state\n");
return -ENOMEM;
}
@@ -1398,14 +1210,18 @@ static int msi3101_probe(struct usb_interface *intf,
INIT_LIST_HEAD(&s->queued_bufs);
s->udev = udev;
s->f_adc = bands[0].rangelow;
- s->pixelformat = V4L2_SDR_FMT_CU8;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ s->num_formats = NUM_FORMATS;
+ if (msi2500_emulated_fmt == false)
+ s->num_formats -= 2;
/* Init videobuf2 queue structure */
s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
s->vb_queue.drv_priv = s;
- s->vb_queue.buf_struct_size = sizeof(struct msi3101_frame_buf);
- s->vb_queue.ops = &msi3101_vb2_ops;
+ s->vb_queue.buf_struct_size = sizeof(struct msi2500_frame_buf);
+ s->vb_queue.ops = &msi2500_vb2_ops;
s->vb_queue.mem_ops = &vb2_vmalloc_memops;
s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
ret = vb2_queue_init(&s->vb_queue);
@@ -1415,14 +1231,13 @@ static int msi3101_probe(struct usb_interface *intf,
}
/* Init video_device structure */
- s->vdev = msi3101_template;
+ s->vdev = msi2500_template;
s->vdev.queue = &s->vb_queue;
s->vdev.queue->lock = &s->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
video_set_drvdata(&s->vdev, s);
/* Register the v4l2_device structure */
- s->v4l2_dev.release = msi3101_video_release;
+ s->v4l2_dev.release = msi2500_video_release;
ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
if (ret) {
dev_err(&s->udev->dev,
@@ -1440,7 +1255,7 @@ static int msi3101_probe(struct usb_interface *intf,
s->master = master;
master->bus_num = 0;
master->num_chipselect = 1;
- master->transfer_one_message = msi3101_transfer_one_message;
+ master->transfer_one_message = msi2500_transfer_one_message;
spi_master_set_devdata(master, s);
ret = spi_register_master(master);
if (ret) {
@@ -1481,6 +1296,9 @@ static int msi3101_probe(struct usb_interface *intf,
}
dev_info(&s->udev->dev, "Registered as %s\n",
video_device_node_name(&s->vdev));
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
return 0;
@@ -1496,22 +1314,22 @@ err_free_mem:
}
/* USB device ID list */
-static struct usb_device_id msi3101_id_table[] = {
+static struct usb_device_id msi2500_id_table[] = {
{ USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */
{ USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */
{ }
};
-MODULE_DEVICE_TABLE(usb, msi3101_id_table);
+MODULE_DEVICE_TABLE(usb, msi2500_id_table);
/* USB subsystem interface */
-static struct usb_driver msi3101_driver = {
+static struct usb_driver msi2500_driver = {
.name = KBUILD_MODNAME,
- .probe = msi3101_probe,
- .disconnect = msi3101_disconnect,
- .id_table = msi3101_id_table,
+ .probe = msi2500_probe,
+ .disconnect = msi2500_disconnect,
+ .id_table = msi2500_id_table,
};
-module_usb_driver(msi3101_driver);
+module_usb_driver(msi2500_driver);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle");
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index 7c280f35eea9..1b158f1167ed 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -951,15 +951,9 @@ static long pvr2_v4l2_ioctl(struct file *file,
if (ret < 0) {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
- } else {
- if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
- pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%ld"
- " command was:", ret);
- v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
- cmd);
- }
+ "pvr2_v4l2_do_ioctl failure, ret=%ld"
+ " command was:", ret);
+ v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
}
} else {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index a73b0bced96f..15b754da4a2c 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -1013,7 +1013,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
strcpy(pdev->vdev.name, name);
pdev->vdev.queue = &pdev->vb_queue;
pdev->vdev.queue->lock = &pdev->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
video_set_drvdata(&pdev->vdev, pdev);
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index a44466bc7b86..2c901861034a 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -1676,7 +1676,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
vc->vdev.ctrl_handler = &vc->hdl;
vc->vdev.lock = &dev->lock;
vc->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &vc->vdev.flags);
video_set_drvdata(&vc->vdev, vc);
if (video_nr == -1)
ret = video_register_device(&vc->vdev,
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 5461341a31cb..233054311a62 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -671,7 +671,6 @@ int stk1160_video_register(struct stk1160 *dev)
/* This will be used to set video_device parent */
dev->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
/* NTSC is default */
dev->norm = V4L2_STD_NTSC_M;
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index be77482c3070..3588dc38db87 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
pix_format->bytesperline = 2 * pix_format->width;
pix_format->sizeimage = pix_format->bytesperline
* pix_format->height;
- pix_format->priv = 0;
return 0;
}
@@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct file *filp,
fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
* fmtd->fmt.pix.height;
- fmtd->fmt.pix.priv = 0;
return 0;
}
@@ -1266,7 +1264,6 @@ static int stk_register_video_device(struct stk_camera *dev)
dev->vdev.lock = &dev->lock;
dev->vdev.debug = debug;
dev->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
if (err)
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
index 3316caa4733b..b31f4791b8ff 100644
--- a/drivers/media/usb/tlg2300/pd-main.c
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -476,6 +476,8 @@ err_audio:
err_video:
v4l2_device_unregister(&pd->v4l2_dev);
err_v4l2:
+ usb_put_intf(pd->interface);
+ usb_put_dev(pd->udev);
kfree(pd);
return ret;
}
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
index ea6070ba835e..b391194a840c 100644
--- a/drivers/media/usb/tlg2300/pd-radio.c
+++ b/drivers/media/usb/tlg2300/pd-radio.c
@@ -327,7 +327,6 @@ int poseidon_fm_init(struct poseidon *p)
}
vfd->v4l2_dev = &p->v4l2_dev;
vfd->ctrl_handler = hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, p);
return video_register_device(vfd, VFL_TYPE_RADIO, -1);
}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
index 8df668d06552..8cd7f02fcf9f 100644
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context)
.bytesperline = 720 * 2,
.sizeimage = 720 * 576 * 2,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
- .priv = 0
};
}
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
index d1af5438c168..26b2ebb62547 100644
--- a/drivers/media/usb/tm6000/tm6000-input.c
+++ b/drivers/media/usb/tm6000/tm6000-input.c
@@ -162,11 +162,42 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
return 0;
}
+static void tm6000_ir_keydown(struct tm6000_IR *ir,
+ const char *buf, unsigned int len)
+{
+ u8 device, command;
+ u32 scancode;
+ enum rc_type protocol;
+
+ if (len < 1)
+ return;
+
+ command = buf[0];
+ device = (len > 1 ? buf[1] : 0x0);
+ switch (ir->rc_type) {
+ case RC_BIT_RC5:
+ protocol = RC_TYPE_RC5;
+ scancode = RC_SCANCODE_RC5(device, command);
+ break;
+ case RC_BIT_NEC:
+ protocol = RC_TYPE_NEC;
+ scancode = RC_SCANCODE_NEC(device, command);
+ break;
+ default:
+ protocol = RC_TYPE_OTHER;
+ scancode = RC_SCANCODE_OTHER(device << 8 | command);
+ break;
+ }
+
+ dprintk(1, "%s, protocol: 0x%04x, scancode: 0x%08x\n",
+ __func__, protocol, scancode);
+ rc_keydown(ir->rc, protocol, scancode, 0);
+}
+
static void tm6000_ir_urb_received(struct urb *urb)
{
struct tm6000_core *dev = urb->context;
struct tm6000_IR *ir = dev->ir;
- struct tm6000_ir_poll_result poll_result;
char *buf;
dprintk(2, "%s\n",__func__);
@@ -184,12 +215,7 @@ static void tm6000_ir_urb_received(struct urb *urb)
DUMP_PREFIX_OFFSET,16, 1,
buf, urb->actual_length, false);
- poll_result.rc_data = buf[0];
- if (urb->actual_length > 1)
- poll_result.rc_data |= buf[1] << 8;
-
- dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
- rc_keydown(ir->rc, poll_result.rc_data, 0);
+ tm6000_ir_keydown(ir, urb->transfer_buffer, urb->actual_length);
usb_submit_urb(urb, GFP_ATOMIC);
/*
@@ -204,7 +230,6 @@ static void tm6000_ir_handle_key(struct work_struct *work)
{
struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
struct tm6000_core *dev = ir->dev;
- struct tm6000_ir_poll_result poll_result;
int rc;
u8 buf[2];
@@ -219,13 +244,8 @@ static void tm6000_ir_handle_key(struct work_struct *work)
if (rc < 0)
return;
- if (rc > 1)
- poll_result.rc_data = buf[0] | buf[1] << 8;
- else
- poll_result.rc_data = buf[0];
-
/* Check if something was read */
- if ((poll_result.rc_data & 0xff) == 0xff) {
+ if ((buf[0] & 0xff) == 0xff) {
if (!ir->pwled) {
tm6000_flash_led(dev, 1);
ir->pwled = 1;
@@ -233,8 +253,7 @@ static void tm6000_ir_handle_key(struct work_struct *work)
return;
}
- dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
- rc_keydown(ir->rc, poll_result.rc_data, 0);
+ tm6000_ir_keydown(ir, buf, rc);
tm6000_flash_led(dev, 0);
ir->pwled = 0;
@@ -422,9 +441,9 @@ int tm6000_ir_init(struct tm6000_core *dev)
ir->rc = rc;
/* input setup */
- rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+ rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC;
/* Neded, in order to support NEC remotes with 24 or 32 bits */
- rc->scanmask = 0xffff;
+ rc->scancode_mask = 0xffff;
rc->priv = ir;
rc->change_protocol = tm6000_ir_change_protocol;
if (dev->int_in.endp) {
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index e6b3d5d83d43..793577fc4633 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
(f->fmt.pix.width * fh->fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.width &= ~0x01;
f->fmt.pix.field = field;
- f->fmt.pix.priv = 0;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
@@ -1626,7 +1624,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
vfd->release = video_device_release;
vfd->debug = tm6000_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
index f8a60c197534..cef7a00099ea 100644
--- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
@@ -791,8 +791,7 @@ static void ttusb_free_iso_urbs(struct ttusb *ttusb)
int i;
for (i = 0; i < ISO_BUF_COUNT; i++)
- if (ttusb->iso_urb[i])
- usb_free_urb(ttusb->iso_urb[i]);
+ usb_free_urb(ttusb->iso_urb[i]);
pci_free_consistent(NULL,
ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *
@@ -804,11 +803,9 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
{
int i;
- ttusb->iso_buffer = pci_alloc_consistent(NULL,
- ISO_FRAME_SIZE *
- FRAMES_PER_ISO_BUF *
- ISO_BUF_COUNT,
- &ttusb->iso_dma_handle);
+ ttusb->iso_buffer = pci_zalloc_consistent(NULL,
+ ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT,
+ &ttusb->iso_dma_handle);
if (!ttusb->iso_buffer) {
dprintk("%s: pci_alloc_consistent - not enough memory\n",
@@ -816,9 +813,6 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
return -ENOMEM;
}
- memset(ttusb->iso_buffer, 0,
- ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
-
for (i = 0; i < ISO_BUF_COUNT; i++) {
struct urb *urb;
diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c
index 29724af9b9ab..15ab584cf265 100644
--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -1151,11 +1151,9 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
dprintk("%s\n", __func__);
- dec->iso_buffer = pci_alloc_consistent(NULL,
- ISO_FRAME_SIZE *
- (FRAMES_PER_ISO_BUF *
- ISO_BUF_COUNT),
- &dec->iso_dma_handle);
+ dec->iso_buffer = pci_zalloc_consistent(NULL,
+ ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT),
+ &dec->iso_dma_handle);
if (!dec->iso_buffer) {
dprintk("%s: pci_alloc_consistent - not enough memory\n",
@@ -1163,9 +1161,6 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
return -ENOMEM;
}
- memset(dec->iso_buffer, 0,
- ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
-
for (i = 0; i < ISO_BUF_COUNT; i++) {
struct urb *urb;
diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c
index 2f87ddfa469f..473fab81b602 100644
--- a/drivers/media/usb/usbtv/usbtv-core.c
+++ b/drivers/media/usb/usbtv/usbtv-core.c
@@ -91,6 +91,8 @@ static int usbtv_probe(struct usb_interface *intf,
return 0;
usbtv_video_fail:
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(usbtv->udev);
kfree(usbtv);
return ret;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 2967e808408b..030c5854b4b3 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -701,7 +701,6 @@ int usbtv_video_init(struct usbtv *usbtv)
usbtv->vdev.tvnorms = USBTV_TV_STD;
usbtv->vdev.queue = &usbtv->vb2q;
usbtv->vdev.lock = &usbtv->v4l2_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
video_set_drvdata(&usbtv->vdev, usbtv);
ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
index 816b1cffab7d..302aa07c458f 100644
--- a/drivers/media/usb/usbvision/usbvision-core.c
+++ b/drivers/media/usb/usbvision/usbvision-core.c
@@ -1463,8 +1463,6 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address,
static int usbvision_init_compression(struct usb_usbvision *usbvision)
{
- int err_code = 0;
-
usbvision->last_isoc_frame_num = -1;
usbvision->isoc_data_count = 0;
usbvision->isoc_packet_count = 0;
@@ -1475,7 +1473,7 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision)
usbvision->request_intra = 1;
usbvision->isoc_measure_bandwidth_count = 0;
- return err_code;
+ return 0;
}
/* this function measures the used bandwidth since last call
@@ -1484,11 +1482,9 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision)
*/
static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
{
- int err_code = 0;
-
if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
usbvision->isoc_measure_bandwidth_count++;
- return err_code;
+ return 0;
}
if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
usbvision->used_bandwidth = usbvision->isoc_data_count /
@@ -1499,7 +1495,7 @@ static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
usbvision->isoc_data_count = 0;
usbvision->isoc_packet_count = 0;
usbvision->isoc_skip_count = 0;
- return err_code;
+ return 0;
}
static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
@@ -1546,26 +1542,24 @@ static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
static int usbvision_request_intra(struct usb_usbvision *usbvision)
{
- int err_code = 0;
unsigned char buffer[1];
PDEBUG(DBG_IRQ, "");
usbvision->request_intra = 1;
buffer[0] = 1;
usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
- return err_code;
+ return 0;
}
static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
{
- int err_code = 0;
unsigned char buffer[1];
PDEBUG(DBG_IRQ, "");
usbvision->request_intra = 0;
buffer[0] = 0;
usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
- return err_code;
+ return 0;
}
/*******************************
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index ad47c5cb539a..f8135f4e3b52 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1746,7 +1746,6 @@ static int uvc_register_video(struct uvc_device *dev,
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
vdev->prio = &stream->chain->prio;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
vdev->vfl_dir = VFL_DIR_TX;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index 74d56df3347f..5c006277b8b1 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
f->fmt.pix.field);
@@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
cam->vb_vidq.field = f->fmt.pix.field;
if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
@@ -1456,7 +1453,6 @@ static int zr364xx_probe(struct usb_interface *intf,
cam->vdev.lock = &cam->lock;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
cam->vdev.ctrl_handler = &cam->ctrl_handler;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
video_set_drvdata(&cam->vdev, cam);
if (debug)
cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 433d6d77942e..ccaa38f65cf1 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -111,9 +111,13 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
EXPORT_SYMBOL(v4l2_ctrl_check);
/* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
{
const char *name;
+ s64 min = _min;
+ s64 max = _max;
+ u64 step = _step;
+ s64 def = _def;
v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
&min, &max, &step, &def, &qctrl->flags);
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 7e2411c36419..cca6c2f76b3a 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -540,7 +540,16 @@ struct v4l2_framebuffer32 {
__u32 capability;
__u32 flags;
compat_caddr_t base;
- struct v4l2_pix_format fmt;
+ struct {
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ __u32 field;
+ __u32 bytesperline;
+ __u32 sizeimage;
+ __u32 colorspace;
+ __u32 priv;
+ } fmt;
};
static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
@@ -550,10 +559,10 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
get_user(tmp, &up->base) ||
get_user(kp->capability, &up->capability) ||
- get_user(kp->flags, &up->flags))
+ get_user(kp->flags, &up->flags) ||
+ copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
return -EFAULT;
kp->base = compat_ptr(tmp);
- get_v4l2_pix_format(&kp->fmt, &up->fmt);
return 0;
}
@@ -564,9 +573,9 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
put_user(tmp, &up->base) ||
put_user(kp->capability, &up->capability) ||
- put_user(kp->flags, &up->flags))
+ put_user(kp->flags, &up->flags) ||
+ copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
return -EFAULT;
- put_v4l2_pix_format(&kp->fmt, &up->fmt);
return 0;
}
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 55c683254102..f030d6a9e044 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -462,6 +462,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
"RGB full range (0-255)",
NULL,
};
+ static const char * const detect_md_mode[] = {
+ "Disabled",
+ "Global",
+ "Threshold Grid",
+ "Region Grid",
+ NULL,
+ };
switch (id) {
@@ -553,6 +560,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
case V4L2_CID_DV_TX_RGB_RANGE:
case V4L2_CID_DV_RX_RGB_RANGE:
return dv_rgb_range;
+ case V4L2_CID_DETECT_MD_MODE:
+ return detect_md_mode;
default:
return NULL;
@@ -592,7 +601,7 @@ const char *v4l2_ctrl_get_name(u32 id)
{
switch (id) {
/* USER controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_USER_CLASS: return "User Controls";
case V4L2_CID_BRIGHTNESS: return "Brightness";
case V4L2_CID_CONTRAST: return "Contrast";
@@ -754,7 +763,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
/* CAMERA controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure";
case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute";
@@ -788,14 +797,23 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_AUTO_FOCUS_STATUS: return "Auto Focus, Status";
case V4L2_CID_AUTO_FOCUS_RANGE: return "Auto Focus, Range";
- /* FM Radio Modulator control */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* FM Radio Modulator controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls";
case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation";
case V4L2_CID_RDS_TX_PI: return "RDS Program ID";
case V4L2_CID_RDS_TX_PTY: return "RDS Program Type";
case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name";
case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text";
+ case V4L2_CID_RDS_TX_MONO_STEREO: return "RDS Stereo";
+ case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD: return "RDS Artificial Head";
+ case V4L2_CID_RDS_TX_COMPRESSED: return "RDS Compressed";
+ case V4L2_CID_RDS_TX_DYNAMIC_PTY: return "RDS Dynamic PTY";
+ case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
+ case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM: return "RDS Traffic Program";
+ case V4L2_CID_RDS_TX_MUSIC_SPEECH: return "RDS Music";
+ case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE: return "RDS Enable Alt Frequencies";
+ case V4L2_CID_RDS_TX_ALT_FREQS: return "RDS Alternate Frequencies";
case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
@@ -812,6 +830,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
/* Flash controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_FLASH_CLASS: return "Flash Controls";
case V4L2_CID_FLASH_LED_MODE: return "LED Mode";
case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source";
@@ -827,7 +846,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_FLASH_READY: return "Ready to Strobe";
/* JPEG encoder controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls";
case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling";
case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval";
@@ -835,18 +854,21 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers";
/* Image source controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_IMAGE_SOURCE_CLASS: return "Image Source Controls";
case V4L2_CID_VBLANK: return "Vertical Blanking";
case V4L2_CID_HBLANK: return "Horizontal Blanking";
case V4L2_CID_ANALOGUE_GAIN: return "Analogue Gain";
/* Image processing controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_IMAGE_PROC_CLASS: return "Image Processing Controls";
case V4L2_CID_LINK_FREQ: return "Link Frequency";
case V4L2_CID_PIXEL_RATE: return "Pixel Rate";
case V4L2_CID_TEST_PATTERN: return "Test Pattern";
/* DV controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_DV_CLASS: return "Digital Video Controls";
case V4L2_CID_DV_TX_HOTPLUG: return "Hotplug Present";
case V4L2_CID_DV_TX_RXSENSE: return "RxSense Present";
@@ -859,7 +881,6 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_FM_RX_CLASS: return "FM Radio Receiver Controls";
case V4L2_CID_TUNE_DEEMPHASIS: return "De-Emphasis";
case V4L2_CID_RDS_RECEPTION: return "RDS Reception";
-
case V4L2_CID_RF_TUNER_CLASS: return "RF Tuner Controls";
case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: return "LNA Gain, Auto";
case V4L2_CID_RF_TUNER_LNA_GAIN: return "LNA Gain";
@@ -870,6 +891,20 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: return "Bandwidth, Auto";
case V4L2_CID_RF_TUNER_BANDWIDTH: return "Bandwidth";
case V4L2_CID_RF_TUNER_PLL_LOCK: return "PLL Lock";
+ case V4L2_CID_RDS_RX_PTY: return "RDS Program Type";
+ case V4L2_CID_RDS_RX_PS_NAME: return "RDS PS Name";
+ case V4L2_CID_RDS_RX_RADIO_TEXT: return "RDS Radio Text";
+ case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT: return "RDS Traffic Announcement";
+ case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM: return "RDS Traffic Program";
+ case V4L2_CID_RDS_RX_MUSIC_SPEECH: return "RDS Music";
+
+ /* Detection controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
+ case V4L2_CID_DETECT_CLASS: return "Detection Controls";
+ case V4L2_CID_DETECT_MD_MODE: return "Motion Detection Mode";
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold";
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID: return "MD Threshold Grid";
+ case V4L2_CID_DETECT_MD_REGION_GRID: return "MD Region Grid";
default:
return NULL;
}
@@ -877,7 +912,7 @@ const char *v4l2_ctrl_get_name(u32 id)
EXPORT_SYMBOL(v4l2_ctrl_get_name);
void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
- s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
+ s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
{
*name = v4l2_ctrl_get_name(id);
*flags = 0;
@@ -924,6 +959,17 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_RF_TUNER_IF_GAIN_AUTO:
case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO:
case V4L2_CID_RF_TUNER_PLL_LOCK:
+ case V4L2_CID_RDS_TX_MONO_STEREO:
+ case V4L2_CID_RDS_TX_ARTIFICIAL_HEAD:
+ case V4L2_CID_RDS_TX_COMPRESSED:
+ case V4L2_CID_RDS_TX_DYNAMIC_PTY:
+ case V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT:
+ case V4L2_CID_RDS_TX_TRAFFIC_PROGRAM:
+ case V4L2_CID_RDS_TX_MUSIC_SPEECH:
+ case V4L2_CID_RDS_TX_ALT_FREQS_ENABLE:
+ case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
+ case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
+ case V4L2_CID_RDS_RX_MUSIC_SPEECH:
*type = V4L2_CTRL_TYPE_BOOLEAN;
*min = 0;
*max = *step = 1;
@@ -988,6 +1034,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_TEST_PATTERN:
case V4L2_CID_TUNE_DEEMPHASIS:
case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
+ case V4L2_CID_DETECT_MD_MODE:
*type = V4L2_CTRL_TYPE_MENU;
break;
case V4L2_CID_LINK_FREQ:
@@ -995,6 +1042,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
break;
case V4L2_CID_RDS_TX_PS_NAME:
case V4L2_CID_RDS_TX_RADIO_TEXT:
+ case V4L2_CID_RDS_RX_PS_NAME:
+ case V4L2_CID_RDS_RX_RADIO_TEXT:
*type = V4L2_CTRL_TYPE_STRING;
break;
case V4L2_CID_ISO_SENSITIVITY:
@@ -1014,6 +1063,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_DV_CLASS:
case V4L2_CID_FM_RX_CLASS:
case V4L2_CID_RF_TUNER_CLASS:
+ case V4L2_CID_DETECT_CLASS:
*type = V4L2_CTRL_TYPE_CTRL_CLASS;
/* You can neither read not write these */
*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1041,14 +1091,32 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
*type = V4L2_CTRL_TYPE_INTEGER;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
break;
- case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
- *flags |= V4L2_CTRL_FLAG_VOLATILE;
- /* Fall through */
+ *type = V4L2_CTRL_TYPE_INTEGER64;
+ *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+ *min = *def = 0;
+ *max = 0x1ffffffffLL;
+ *step = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
+ *type = V4L2_CTRL_TYPE_INTEGER64;
+ *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+ *min = *def = 0;
+ *max = 0x7fffffffffffffffLL;
+ *step = 1;
+ break;
case V4L2_CID_PIXEL_RATE:
*type = V4L2_CTRL_TYPE_INTEGER64;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
- *min = *max = *step = *def = 0;
+ break;
+ case V4L2_CID_DETECT_MD_REGION_GRID:
+ *type = V4L2_CTRL_TYPE_U8;
+ break;
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+ *type = V4L2_CTRL_TYPE_U16;
+ break;
+ case V4L2_CID_RDS_TX_ALT_FREQS:
+ *type = V4L2_CTRL_TYPE_U32;
break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
@@ -1090,6 +1158,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_RF_TUNER_MIXER_GAIN:
case V4L2_CID_RF_TUNER_IF_GAIN:
case V4L2_CID_RF_TUNER_BANDWIDTH:
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
*flags |= V4L2_CTRL_FLAG_SLIDER;
break;
case V4L2_CID_PAN_RELATIVE:
@@ -1106,6 +1175,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_DV_TX_RXSENSE:
case V4L2_CID_DV_TX_EDID_PRESENT:
case V4L2_CID_DV_RX_POWER_PRESENT:
+ case V4L2_CID_RDS_RX_PTY:
+ case V4L2_CID_RDS_RX_PS_NAME:
+ case V4L2_CID_RDS_RX_RADIO_TEXT:
+ case V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT:
+ case V4L2_CID_RDS_RX_TRAFFIC_PROGRAM:
+ case V4L2_CID_RDS_RX_MUSIC_SPEECH:
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
break;
case V4L2_CID_RF_TUNER_PLL_LOCK:
@@ -1115,20 +1190,6 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
}
EXPORT_SYMBOL(v4l2_ctrl_fill);
-/* Helper function to determine whether the control type is compatible with
- VIDIOC_G/S_CTRL. */
-static bool type_is_int(const struct v4l2_ctrl *ctrl)
-{
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER64:
- case V4L2_CTRL_TYPE_STRING:
- /* Nope, these need v4l2_ext_control */
- return false;
- default:
- return true;
- }
-}
-
static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
{
memset(ev->reserved, 0, sizeof(ev->reserved));
@@ -1137,10 +1198,10 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
ev->u.ctrl.changes = changes;
ev->u.ctrl.type = ctrl->type;
ev->u.ctrl.flags = ctrl->flags;
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+ if (ctrl->is_ptr)
ev->u.ctrl.value64 = 0;
else
- ev->u.ctrl.value64 = ctrl->cur.val64;
+ ev->u.ctrl.value64 = *ctrl->p_cur.p_s64;
ev->u.ctrl.minimum = ctrl->minimum;
ev->u.ctrl.maximum = ctrl->maximum;
if (ctrl->type == V4L2_CTRL_TYPE_MENU
@@ -1166,42 +1227,283 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
v4l2_event_queue_fh(sev->fh, &ev);
}
-/* Helper function: copy the current control value back to the caller */
-static int cur_to_user(struct v4l2_ext_control *c,
- struct v4l2_ctrl *ctrl)
+static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr1,
+ union v4l2_ctrl_ptr ptr2)
+{
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_BUTTON:
+ return false;
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ /* strings are always 0-terminated */
+ return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
+ case V4L2_CTRL_TYPE_INTEGER64:
+ return ptr1.p_s64[idx] == ptr2.p_s64[idx];
+ case V4L2_CTRL_TYPE_U8:
+ return ptr1.p_u8[idx] == ptr2.p_u8[idx];
+ case V4L2_CTRL_TYPE_U16:
+ return ptr1.p_u16[idx] == ptr2.p_u16[idx];
+ case V4L2_CTRL_TYPE_U32:
+ return ptr1.p_u32[idx] == ptr2.p_u32[idx];
+ default:
+ if (ctrl->is_int)
+ return ptr1.p_s32[idx] == ptr2.p_s32[idx];
+ idx *= ctrl->elem_size;
+ return !memcmp(ptr1.p + idx, ptr2.p + idx, ctrl->elem_size);
+ }
+}
+
+static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ memset(ptr.p_char + idx, ' ', ctrl->minimum);
+ ptr.p_char[idx + ctrl->minimum] = '\0';
+ break;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ ptr.p_s64[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ ptr.p_s32[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ ptr.p_u8[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ ptr.p_u16[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_U32:
+ ptr.p_u32[idx] = ctrl->default_value;
+ break;
+ default:
+ idx *= ctrl->elem_size;
+ memset(ptr.p + idx, 0, ctrl->elem_size);
+ break;
+ }
+}
+
+static void std_log(const struct v4l2_ctrl *ctrl)
+{
+ union v4l2_ctrl_ptr ptr = ctrl->p_cur;
+
+ if (ctrl->is_array) {
+ unsigned i;
+
+ for (i = 0; i < ctrl->nr_of_dims; i++)
+ pr_cont("[%u]", ctrl->dims[i]);
+ pr_cont(" ");
+ }
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ pr_cont("%d", *ptr.p_s32);
+ break;
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ pr_cont("%s", *ptr.p_s32 ? "true" : "false");
+ break;
+ case V4L2_CTRL_TYPE_MENU:
+ pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
+ break;
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
+ break;
+ case V4L2_CTRL_TYPE_BITMASK:
+ pr_cont("0x%08x", *ptr.p_s32);
+ break;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ pr_cont("%lld", *ptr.p_s64);
+ break;
+ case V4L2_CTRL_TYPE_STRING:
+ pr_cont("%s", ptr.p_char);
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ pr_cont("%u", (unsigned)*ptr.p_u8);
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ pr_cont("%u", (unsigned)*ptr.p_u16);
+ break;
+ case V4L2_CTRL_TYPE_U32:
+ pr_cont("%u", (unsigned)*ptr.p_u32);
+ break;
+ default:
+ pr_cont("unknown type %d", ctrl->type);
+ break;
+ }
+}
+
+/*
+ * Round towards the closest legal value. Be careful when we are
+ * close to the maximum range of the control type to prevent
+ * wrap-arounds.
+ */
+#define ROUND_TO_RANGE(val, offset_type, ctrl) \
+({ \
+ offset_type offset; \
+ if ((ctrl)->maximum >= 0 && \
+ val >= (ctrl)->maximum - (s32)((ctrl)->step / 2)) \
+ val = (ctrl)->maximum; \
+ else \
+ val += (s32)((ctrl)->step / 2); \
+ val = clamp_t(typeof(val), val, \
+ (ctrl)->minimum, (ctrl)->maximum); \
+ offset = (val) - (ctrl)->minimum; \
+ offset = (ctrl)->step * (offset / (u32)(ctrl)->step); \
+ val = (ctrl)->minimum + offset; \
+ 0; \
+})
+
+/* Validate a new control */
+static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ size_t len;
+ u64 offset;
+ s64 val;
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
+ case V4L2_CTRL_TYPE_INTEGER64:
+ /*
+ * We can't use the ROUND_TO_RANGE define here due to
+ * the u64 divide that needs special care.
+ */
+ val = ptr.p_s64[idx];
+ if (ctrl->maximum >= 0 && val >= ctrl->maximum - (s64)(ctrl->step / 2))
+ val = ctrl->maximum;
+ else
+ val += (s64)(ctrl->step / 2);
+ val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
+ offset = val - ctrl->minimum;
+ do_div(offset, ctrl->step);
+ ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step;
+ return 0;
+ case V4L2_CTRL_TYPE_U8:
+ return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
+ case V4L2_CTRL_TYPE_U16:
+ return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl);
+ case V4L2_CTRL_TYPE_U32:
+ return ROUND_TO_RANGE(ptr.p_u32[idx], u32, ctrl);
+
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ ptr.p_s32[idx] = !!ptr.p_s32[idx];
+ return 0;
+
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
+ return -ERANGE;
+ if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx]))
+ return -EINVAL;
+ if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
+ ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
+ return -EINVAL;
+ return 0;
+
+ case V4L2_CTRL_TYPE_BITMASK:
+ ptr.p_s32[idx] &= ctrl->maximum;
+ return 0;
+
+ case V4L2_CTRL_TYPE_BUTTON:
+ case V4L2_CTRL_TYPE_CTRL_CLASS:
+ ptr.p_s32[idx] = 0;
+ return 0;
+
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ len = strlen(ptr.p_char + idx);
+ if (len < ctrl->minimum)
+ return -ERANGE;
+ if ((len - (u32)ctrl->minimum) % (u32)ctrl->step)
+ return -ERANGE;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct v4l2_ctrl_type_ops std_type_ops = {
+ .equal = std_equal,
+ .init = std_init,
+ .log = std_log,
+ .validate = std_validate,
+};
+
+/* Helper function: copy the given control value back to the caller */
+static int ptr_to_user(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr ptr)
{
u32 len;
+ if (ctrl->is_ptr && !ctrl->is_string)
+ return copy_to_user(c->ptr, ptr.p, c->size) ?
+ -EFAULT : 0;
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
- len = strlen(ctrl->cur.string);
+ len = strlen(ptr.p_char);
if (c->size < len + 1) {
- c->size = len + 1;
+ c->size = ctrl->elem_size;
return -ENOSPC;
}
- return copy_to_user(c->string, ctrl->cur.string,
- len + 1) ? -EFAULT : 0;
+ return copy_to_user(c->string, ptr.p_char, len + 1) ?
+ -EFAULT : 0;
case V4L2_CTRL_TYPE_INTEGER64:
- c->value64 = ctrl->cur.val64;
+ c->value64 = *ptr.p_s64;
break;
default:
- c->value = ctrl->cur.val;
+ c->value = *ptr.p_s32;
break;
}
return 0;
}
-/* Helper function: copy the caller-provider value as the new control value */
-static int user_to_new(struct v4l2_ext_control *c,
+/* Helper function: copy the current control value back to the caller */
+static int cur_to_user(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
+ return ptr_to_user(c, ctrl, ctrl->p_cur);
+}
+
+/* Helper function: copy the new control value back to the caller */
+static int new_to_user(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl)
+{
+ return ptr_to_user(c, ctrl, ctrl->p_new);
+}
+
+/* Helper function: copy the caller-provider value to the given control value */
+static int user_to_ptr(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr ptr)
+{
int ret;
u32 size;
ctrl->is_new = 1;
+ if (ctrl->is_ptr && !ctrl->is_string) {
+ unsigned idx;
+
+ ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
+ if (ret || !ctrl->is_array)
+ return ret;
+ for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
+ ctrl->type_ops->init(ctrl, idx, ptr);
+ return 0;
+ }
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER64:
- ctrl->val64 = c->value64;
+ *ptr.p_s64 = c->value64;
break;
case V4L2_CTRL_TYPE_STRING:
size = c->size;
@@ -1209,74 +1511,53 @@ static int user_to_new(struct v4l2_ext_control *c,
return -ERANGE;
if (size > ctrl->maximum + 1)
size = ctrl->maximum + 1;
- ret = copy_from_user(ctrl->string, c->string, size);
+ ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
if (!ret) {
- char last = ctrl->string[size - 1];
+ char last = ptr.p_char[size - 1];
- ctrl->string[size - 1] = 0;
+ ptr.p_char[size - 1] = 0;
/* If the string was longer than ctrl->maximum,
then return an error. */
- if (strlen(ctrl->string) == ctrl->maximum && last)
+ if (strlen(ptr.p_char) == ctrl->maximum && last)
return -ERANGE;
}
- return ret ? -EFAULT : 0;
+ return ret;
default:
- ctrl->val = c->value;
+ *ptr.p_s32 = c->value;
break;
}
return 0;
}
-/* Helper function: copy the new control value back to the caller */
-static int new_to_user(struct v4l2_ext_control *c,
+/* Helper function: copy the caller-provider value as the new control value */
+static int user_to_new(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
- u32 len;
+ return user_to_ptr(c, ctrl, ctrl->p_new);
+}
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_STRING:
- len = strlen(ctrl->string);
- if (c->size < len + 1) {
- c->size = ctrl->maximum + 1;
- return -ENOSPC;
- }
- return copy_to_user(c->string, ctrl->string,
- len + 1) ? -EFAULT : 0;
- case V4L2_CTRL_TYPE_INTEGER64:
- c->value64 = ctrl->val64;
- break;
- default:
- c->value = ctrl->val;
- break;
- }
- return 0;
+/* Copy the one value to another. */
+static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
+{
+ if (ctrl == NULL)
+ return;
+ memcpy(to.p, from.p, ctrl->elems * ctrl->elem_size);
}
/* Copy the new value to the current value. */
static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
{
- bool changed = false;
+ bool changed;
if (ctrl == NULL)
return;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BUTTON:
- changed = true;
- break;
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- changed = strcmp(ctrl->string, ctrl->cur.string);
- strcpy(ctrl->cur.string, ctrl->string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- changed = ctrl->val64 != ctrl->cur.val64;
- ctrl->cur.val64 = ctrl->val64;
- break;
- default:
- changed = ctrl->val != ctrl->cur.val;
- ctrl->cur.val = ctrl->val;
- break;
- }
+
+ /* has_changed is set by cluster_changed */
+ changed = ctrl->has_changed;
+ if (changed)
+ ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
+
if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
/* Note: CH_FLAGS is only set for auto clusters. */
ctrl->flags &=
@@ -1305,62 +1586,47 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
{
if (ctrl == NULL)
return;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- strcpy(ctrl->string, ctrl->cur.string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- ctrl->val64 = ctrl->cur.val64;
- break;
- default:
- ctrl->val = ctrl->cur.val;
- break;
- }
+ ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
}
/* Return non-zero if one or more of the controls in the cluster has a new
value that differs from the current value. */
static int cluster_changed(struct v4l2_ctrl *master)
{
- int diff = 0;
+ bool changed = false;
+ unsigned idx;
int i;
- for (i = 0; !diff && i < master->ncontrols; i++) {
+ for (i = 0; i < master->ncontrols; i++) {
struct v4l2_ctrl *ctrl = master->cluster[i];
+ bool ctrl_changed = false;
if (ctrl == NULL)
continue;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BUTTON:
- /* Button controls are always 'different' */
- return 1;
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- diff = strcmp(ctrl->string, ctrl->cur.string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- diff = ctrl->val64 != ctrl->cur.val64;
- break;
- default:
- diff = ctrl->val != ctrl->cur.val;
- break;
- }
+ for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
+ ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
+ ctrl->p_cur, ctrl->p_new);
+ ctrl->has_changed = ctrl_changed;
+ changed |= ctrl->has_changed;
}
- return diff;
+ return changed;
}
/* Control range checking */
static int check_range(enum v4l2_ctrl_type type,
- s32 min, s32 max, u32 step, s32 def)
+ s64 min, s64 max, u64 step, s64 def)
{
switch (type) {
case V4L2_CTRL_TYPE_BOOLEAN:
if (step != 1 || max > 1 || min < 0)
return -ERANGE;
/* fall through */
+ case V4L2_CTRL_TYPE_U8:
+ case V4L2_CTRL_TYPE_U16:
+ case V4L2_CTRL_TYPE_U32:
case V4L2_CTRL_TYPE_INTEGER:
- if (step <= 0 || min > max || def < min || def > max)
+ case V4L2_CTRL_TYPE_INTEGER64:
+ if (step == 0 || min > max || def < min || def > max)
return -ERANGE;
return 0;
case V4L2_CTRL_TYPE_BITMASK:
@@ -1389,58 +1655,33 @@ static int check_range(enum v4l2_ctrl_type type,
static int validate_new(const struct v4l2_ctrl *ctrl,
struct v4l2_ext_control *c)
{
- size_t len;
- u32 offset;
- s32 val;
-
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- /* Round towards the closest legal value */
- val = c->value + ctrl->step / 2;
- val = clamp(val, ctrl->minimum, ctrl->maximum);
- offset = val - ctrl->minimum;
- offset = ctrl->step * (offset / ctrl->step);
- c->value = ctrl->minimum + offset;
- return 0;
-
- case V4L2_CTRL_TYPE_BOOLEAN:
- c->value = !!c->value;
- return 0;
-
- case V4L2_CTRL_TYPE_MENU:
- case V4L2_CTRL_TYPE_INTEGER_MENU:
- if (c->value < ctrl->minimum || c->value > ctrl->maximum)
- return -ERANGE;
- if (ctrl->menu_skip_mask & (1 << c->value))
- return -EINVAL;
- if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
- ctrl->qmenu[c->value][0] == '\0')
- return -EINVAL;
- return 0;
-
- case V4L2_CTRL_TYPE_BITMASK:
- c->value &= ctrl->maximum;
- return 0;
-
- case V4L2_CTRL_TYPE_BUTTON:
- case V4L2_CTRL_TYPE_CTRL_CLASS:
- c->value = 0;
- return 0;
-
- case V4L2_CTRL_TYPE_INTEGER64:
- return 0;
+ union v4l2_ctrl_ptr ptr;
+ unsigned idx;
+ int err = 0;
- case V4L2_CTRL_TYPE_STRING:
- len = strlen(c->string);
- if (len < ctrl->minimum)
- return -ERANGE;
- if ((len - ctrl->minimum) % ctrl->step)
- return -ERANGE;
- return 0;
+ if (!ctrl->is_ptr) {
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_BUTTON:
+ case V4L2_CTRL_TYPE_CTRL_CLASS:
+ ptr.p_s32 = &c->value;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
- default:
- return -EINVAL;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ ptr.p_s64 = &c->value64;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
+ default:
+ break;
+ }
}
+ ptr.p = c->ptr;
+ for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+ err = ctrl->type_ops->validate(ctrl, idx, ptr);
+ return err;
}
static inline u32 node2id(struct list_head *node)
@@ -1522,7 +1763,7 @@ static struct v4l2_ctrl_ref *find_private_ref(
VIDIOC_G/S_CTRL. */
if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
- if (!type_is_int(ref->ctrl))
+ if (!ref->ctrl->is_int)
continue;
if (id == 0)
return ref;
@@ -1592,8 +1833,12 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
int bucket = id % hdl->nr_of_buckets; /* which bucket to use */
- /* Automatically add the control class if it is not yet present. */
- if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
+ /*
+ * Automatically add the control class if it is not yet present and
+ * the new control is not a compound control.
+ */
+ if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES &&
+ id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
return hdl->error;
@@ -1652,20 +1897,61 @@ unlock:
/* Add a new control */
static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
+ const struct v4l2_ctrl_type_ops *type_ops,
u32 id, const char *name, enum v4l2_ctrl_type type,
- s32 min, s32 max, u32 step, s32 def,
+ s64 min, s64 max, u64 step, s64 def,
+ const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
u32 flags, const char * const *qmenu,
const s64 *qmenu_int, void *priv)
{
struct v4l2_ctrl *ctrl;
- unsigned sz_extra = 0;
+ unsigned sz_extra;
+ unsigned nr_of_dims = 0;
+ unsigned elems = 1;
+ bool is_array;
+ unsigned tot_ctrl_size;
+ unsigned idx;
+ void *data;
int err;
if (hdl->error)
return NULL;
+ while (dims && dims[nr_of_dims]) {
+ elems *= dims[nr_of_dims];
+ nr_of_dims++;
+ if (nr_of_dims == V4L2_CTRL_MAX_DIMS)
+ break;
+ }
+ is_array = nr_of_dims > 0;
+
+ /* Prefill elem_size for all types handled by std_type_ops */
+ switch (type) {
+ case V4L2_CTRL_TYPE_INTEGER64:
+ elem_size = sizeof(s64);
+ break;
+ case V4L2_CTRL_TYPE_STRING:
+ elem_size = max + 1;
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ elem_size = sizeof(u8);
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ elem_size = sizeof(u16);
+ break;
+ case V4L2_CTRL_TYPE_U32:
+ elem_size = sizeof(u32);
+ break;
+ default:
+ if (type < V4L2_CTRL_COMPOUND_TYPES)
+ elem_size = sizeof(s32);
+ break;
+ }
+ tot_ctrl_size = elem_size * elems;
+
/* Sanity checks */
- if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
+ if (id == 0 || name == NULL || !elem_size ||
+ id >= V4L2_CID_PRIVATE_BASE ||
(type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
(type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
handler_set_err(hdl, -ERANGE);
@@ -1680,13 +1966,23 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -ERANGE);
return NULL;
}
+ if (is_array &&
+ (type == V4L2_CTRL_TYPE_BUTTON ||
+ type == V4L2_CTRL_TYPE_CTRL_CLASS)) {
+ handler_set_err(hdl, -EINVAL);
+ return NULL;
+ }
+ sz_extra = 0;
if (type == V4L2_CTRL_TYPE_BUTTON)
flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
flags |= V4L2_CTRL_FLAG_READ_ONLY;
- else if (type == V4L2_CTRL_TYPE_STRING)
- sz_extra += 2 * (max + 1);
+ else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
+ type == V4L2_CTRL_TYPE_STRING ||
+ type >= V4L2_CTRL_COMPOUND_TYPES ||
+ is_array)
+ sz_extra += 2 * tot_ctrl_size;
ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
if (ctrl == NULL) {
@@ -1698,6 +1994,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
INIT_LIST_HEAD(&ctrl->ev_subs);
ctrl->handler = hdl;
ctrl->ops = ops;
+ ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
ctrl->id = id;
ctrl->name = name;
ctrl->type = type;
@@ -1705,19 +2002,36 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
ctrl->minimum = min;
ctrl->maximum = max;
ctrl->step = step;
+ ctrl->default_value = def;
+ ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING;
+ ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string;
+ ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+ ctrl->is_array = is_array;
+ ctrl->elems = elems;
+ ctrl->nr_of_dims = nr_of_dims;
+ if (nr_of_dims)
+ memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0]));
+ ctrl->elem_size = elem_size;
if (type == V4L2_CTRL_TYPE_MENU)
ctrl->qmenu = qmenu;
else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
ctrl->qmenu_int = qmenu_int;
ctrl->priv = priv;
- ctrl->cur.val = ctrl->val = ctrl->default_value = def;
+ ctrl->cur.val = ctrl->val = def;
+ data = &ctrl[1];
- if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
- ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1);
- ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1);
- if (ctrl->minimum)
- memset(ctrl->cur.string, ' ', ctrl->minimum);
+ if (!ctrl->is_int) {
+ ctrl->p_new.p = data;
+ ctrl->p_cur.p = data + tot_ctrl_size;
+ } else {
+ ctrl->p_new.p = &ctrl->val;
+ ctrl->p_cur.p = &ctrl->cur.val;
}
+ for (idx = 0; idx < elems; idx++) {
+ ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
+ ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
+ }
+
if (handler_new_ref(hdl, ctrl)) {
kfree(ctrl);
return NULL;
@@ -1738,10 +2052,10 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
const s64 *qmenu_int = cfg->qmenu_int;
enum v4l2_ctrl_type type = cfg->type;
u32 flags = cfg->flags;
- s32 min = cfg->min;
- s32 max = cfg->max;
- u32 step = cfg->step;
- s32 def = cfg->def;
+ s64 min = cfg->min;
+ s64 max = cfg->max;
+ u64 step = cfg->step;
+ s64 def = cfg->def;
if (name == NULL)
v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
@@ -1761,10 +2075,11 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
return NULL;
}
- ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
+ ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name,
type, min, max,
- is_menu ? cfg->menu_skip_mask : step,
- def, flags, qmenu, qmenu_int, priv);
+ is_menu ? cfg->menu_skip_mask : step, def,
+ cfg->dims, cfg->elem_size,
+ flags, qmenu, qmenu_int, priv);
if (ctrl)
ctrl->is_private = cfg->is_private;
return ctrl;
@@ -1774,35 +2089,39 @@ EXPORT_SYMBOL(v4l2_ctrl_new_custom);
/* Helper function for standard non-menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 min, s32 max, u32 step, s32 def)
+ u32 id, s64 min, s64 max, u64 step, s64 def)
{
const char *name;
enum v4l2_ctrl_type type;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
- if (type == V4L2_CTRL_TYPE_MENU
- || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
+ if (type == V4L2_CTRL_TYPE_MENU ||
+ type == V4L2_CTRL_TYPE_INTEGER_MENU ||
+ type >= V4L2_CTRL_COMPOUND_TYPES) {
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- min, max, step, def, flags, NULL, NULL, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ min, max, step, def, NULL, 0,
+ flags, NULL, NULL, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std);
/* Helper function for standard menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 mask, s32 def)
+ u32 id, u8 _max, u64 mask, u8 _def)
{
const char * const *qmenu = NULL;
const s64 *qmenu_int = NULL;
unsigned int qmenu_int_len = 0;
const char *name;
enum v4l2_ctrl_type type;
- s32 min;
- s32 step;
+ s64 min;
+ s64 max = _max;
+ s64 def = _def;
+ u64 step;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1816,21 +2135,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- 0, max, mask, def, flags, qmenu, qmenu_int, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, mask, def, NULL, 0,
+ flags, qmenu, qmenu_int, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
/* Helper function for standard menu controls with driver defined menu */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
- const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
- s32 mask, s32 def, const char * const *qmenu)
+ const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
+ u64 mask, u8 _def, const char * const *qmenu)
{
enum v4l2_ctrl_type type;
const char *name;
u32 flags;
- s32 step;
- s32 min;
+ u64 step;
+ s64 min;
+ s64 max = _max;
+ s64 def = _def;
/* v4l2_ctrl_new_std_menu_items() should only be called for
* standard controls without a standard menu.
@@ -1845,7 +2167,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, mask, def, NULL, 0,
flags, qmenu, NULL, NULL);
}
@@ -1854,12 +2177,14 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
/* Helper function for standard integer menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 def, const s64 *qmenu_int)
+ u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
{
const char *name;
enum v4l2_ctrl_type type;
- s32 min;
- s32 step;
+ s64 min;
+ u64 step;
+ s64 max = _max;
+ s64 def = _def;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1867,8 +2192,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- 0, max, 0, def, flags, NULL, qmenu_int, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, 0, def, NULL, 0,
+ flags, NULL, qmenu_int, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
@@ -2048,45 +2374,21 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
return;
- printk(KERN_INFO "%s%s%s: ", prefix, colon, ctrl->name);
+ pr_info("%s%s%s: ", prefix, colon, ctrl->name);
+
+ ctrl->type_ops->log(ctrl);
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- printk(KERN_CONT "%d", ctrl->cur.val);
- break;
- case V4L2_CTRL_TYPE_BOOLEAN:
- printk(KERN_CONT "%s", ctrl->cur.val ? "true" : "false");
- break;
- case V4L2_CTRL_TYPE_MENU:
- printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
- break;
- case V4L2_CTRL_TYPE_INTEGER_MENU:
- printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
- break;
- case V4L2_CTRL_TYPE_BITMASK:
- printk(KERN_CONT "0x%08x", ctrl->cur.val);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- printk(KERN_CONT "%lld", ctrl->cur.val64);
- break;
- case V4L2_CTRL_TYPE_STRING:
- printk(KERN_CONT "%s", ctrl->cur.string);
- break;
- default:
- printk(KERN_CONT "unknown type %d", ctrl->type);
- break;
- }
if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
V4L2_CTRL_FLAG_GRABBED |
V4L2_CTRL_FLAG_VOLATILE)) {
if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
- printk(KERN_CONT " inactive");
+ pr_cont(" inactive");
if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
- printk(KERN_CONT " grabbed");
+ pr_cont(" grabbed");
if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
- printk(KERN_CONT " volatile");
+ pr_cont(" volatile");
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
}
/* Log all controls owned by the handler */
@@ -2157,9 +2459,10 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
}
EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
-/* Implement VIDIOC_QUERYCTRL */
-int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+/* Implement VIDIOC_QUERY_EXT_CTRL */
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
{
+ const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
u32 id = qc->id & V4L2_CTRL_ID_MASK;
struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl *ctrl;
@@ -2172,7 +2475,20 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
/* Try to find it */
ref = find_ref(hdl, id);
- if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
+ if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
+ bool is_compound;
+ /* Match any control that is not hidden */
+ unsigned mask = 1;
+ bool match = false;
+
+ if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
+ /* Match any hidden control */
+ match = true;
+ } else if ((qc->id & next_flags) == next_flags) {
+ /* Match any control, compound or not */
+ mask = 0;
+ }
+
/* Find the next control with ID > qc->id */
/* Did we reach the end of the control list? */
@@ -2180,19 +2496,34 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
ref = NULL; /* Yes, so there is no next control */
} else if (ref) {
/* We found a control with the given ID, so just get
- the next one in the list. */
- ref = list_entry(ref->node.next, typeof(*ref), node);
+ the next valid one in the list. */
+ list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
+ is_compound =
+ ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+ if (id < ref->ctrl->id &&
+ (is_compound & mask) == match)
+ break;
+ }
+ if (&ref->node == &hdl->ctrl_refs)
+ ref = NULL;
} else {
/* No control with the given ID exists, so start
searching for the next largest ID. We know there
is one, otherwise the first 'if' above would have
been true. */
- list_for_each_entry(ref, &hdl->ctrl_refs, node)
- if (id < ref->ctrl->id)
+ list_for_each_entry(ref, &hdl->ctrl_refs, node) {
+ is_compound =
+ ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+ if (id < ref->ctrl->id &&
+ (is_compound & mask) == match)
break;
+ }
+ if (&ref->node == &hdl->ctrl_refs)
+ ref = NULL;
}
}
mutex_unlock(hdl->lock);
+
if (!ref)
return -EINVAL;
@@ -2203,6 +2534,14 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
else
qc->id = ctrl->id;
strlcpy(qc->name, ctrl->name, sizeof(qc->name));
+ qc->flags = ctrl->flags;
+ qc->type = ctrl->type;
+ if (ctrl->is_ptr)
+ qc->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD;
+ qc->elem_size = ctrl->elem_size;
+ qc->elems = ctrl->elems;
+ qc->nr_of_dims = ctrl->nr_of_dims;
+ memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
qc->minimum = ctrl->minimum;
qc->maximum = ctrl->maximum;
qc->default_value = ctrl->default_value;
@@ -2211,15 +2550,50 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
qc->step = 1;
else
qc->step = ctrl->step;
- qc->flags = ctrl->flags;
- qc->type = ctrl->type;
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_query_ext_ctrl);
+
+/* Implement VIDIOC_QUERYCTRL */
+int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+{
+ struct v4l2_query_ext_ctrl qec = { qc->id };
+ int rc;
+
+ rc = v4l2_query_ext_ctrl(hdl, &qec);
+ if (rc)
+ return rc;
+
+ qc->id = qec.id;
+ qc->type = qec.type;
+ qc->flags = qec.flags;
+ strlcpy(qc->name, qec.name, sizeof(qc->name));
+ switch (qc->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_STRING:
+ case V4L2_CTRL_TYPE_BITMASK:
+ qc->minimum = qec.minimum;
+ qc->maximum = qec.maximum;
+ qc->step = qec.step;
+ qc->default_value = qec.default_value;
+ break;
+ default:
+ qc->minimum = 0;
+ qc->maximum = 0;
+ qc->step = 0;
+ qc->default_value = 0;
+ break;
+ }
return 0;
}
EXPORT_SYMBOL(v4l2_queryctrl);
int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
- if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+ if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND))
return -EINVAL;
return v4l2_queryctrl(sd->ctrl_handler, qc);
}
@@ -2319,7 +2693,8 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
Find the controls in the control array and do some basic checks. */
static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
- struct v4l2_ctrl_helper *helpers)
+ struct v4l2_ctrl_helper *helpers,
+ bool get)
{
struct v4l2_ctrl_helper *h;
bool have_clusters = false;
@@ -2351,6 +2726,18 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
have_clusters = true;
if (ctrl->cluster[0] != ctrl)
ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
+ if (ctrl->is_ptr && !ctrl->is_string) {
+ unsigned tot_size = ctrl->elems * ctrl->elem_size;
+
+ if (c->size < tot_size) {
+ if (get) {
+ c->size = tot_size;
+ return -ENOSPC;
+ }
+ return -EFAULT;
+ }
+ c->size = tot_size;
+ }
/* Store the ref to the master control of the cluster */
h->mref = ref;
h->ctrl = ctrl;
@@ -2431,7 +2818,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
+ ret = prepare_ext_ctrls(hdl, cs, helpers, true);
cs->error_idx = cs->count;
for (i = 0; !ret && i < cs->count; i++)
@@ -2493,11 +2880,11 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
int ret = 0;
int i;
- /* String controls are not supported. The new_to_user() and
+ /* Compound controls are not supported. The new_to_user() and
* cur_to_user() calls below would need to be modified not to access
* userspace memory when called from get_ctrl().
*/
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+ if (!ctrl->is_int)
return -EINVAL;
if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
@@ -2523,7 +2910,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
struct v4l2_ext_control c;
int ret;
- if (ctrl == NULL || !type_is_int(ctrl))
+ if (ctrl == NULL || !ctrl->is_int)
return -EINVAL;
ret = get_ctrl(ctrl, &c);
control->value = c.value;
@@ -2542,7 +2929,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
struct v4l2_ext_control c;
/* It's a driver bug if this happens. */
- WARN_ON(!type_is_int(ctrl));
+ WARN_ON(!ctrl->is_int);
c.value = 0;
get_ctrl(ctrl, &c);
return c.value;
@@ -2554,7 +2941,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
struct v4l2_ext_control c;
/* It's a driver bug if this happens. */
- WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
c.value = 0;
get_ctrl(ctrl, &c);
return c.value;
@@ -2678,7 +3065,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
if (!helpers)
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
+ ret = prepare_ext_ctrls(hdl, cs, helpers, false);
if (!ret)
ret = validate_ctrls(cs, helpers, set);
if (ret && set)
@@ -2783,26 +3170,22 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
struct v4l2_ctrl *master = ctrl->cluster[0];
int i;
- /* String controls are not supported. The user_to_new() and
- * cur_to_user() calls below would need to be modified not to access
- * userspace memory when called from set_ctrl().
- */
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
- return -EINVAL;
-
/* Reset the 'is_new' flags of the cluster */
for (i = 0; i < master->ncontrols; i++)
if (master->cluster[i])
master->cluster[i]->is_new = 0;
+ if (c)
+ user_to_new(c, ctrl);
+
/* For autoclusters with volatiles that are switched from auto to
manual mode we have to update the current volatile values since
those will become the initial manual values after such a switch. */
if (master->is_auto && master->has_volatiles && ctrl == master &&
- !is_cur_manual(master) && c->value == master->manual_mode_value)
+ !is_cur_manual(master) && ctrl->val == master->manual_mode_value)
update_from_auto_cluster(master);
- user_to_new(c, ctrl);
+ ctrl->is_new = 1;
return try_or_set_cluster(fh, master, true, ch_flags);
}
@@ -2829,7 +3212,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_control c;
int ret;
- if (ctrl == NULL || !type_is_int(ctrl))
+ if (ctrl == NULL || !ctrl->is_int)
return -EINVAL;
if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
@@ -2848,27 +3231,38 @@ int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
}
EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
-int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
+int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
{
- struct v4l2_ext_control c;
+ lockdep_assert_held(ctrl->handler->lock);
/* It's a driver bug if this happens. */
- WARN_ON(!type_is_int(ctrl));
- c.value = val;
- return set_ctrl_lock(NULL, ctrl, &c);
+ WARN_ON(!ctrl->is_int);
+ ctrl->val = val;
+ return set_ctrl(NULL, ctrl, NULL, 0);
}
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
-int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
+int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
{
- struct v4l2_ext_control c;
+ lockdep_assert_held(ctrl->handler->lock);
/* It's a driver bug if this happens. */
- WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
- c.value64 = val;
- return set_ctrl_lock(NULL, ctrl, &c);
+ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+ *ctrl->p_new.p_s64 = val;
+ return set_ctrl(NULL, ctrl, NULL, 0);
}
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
+
+int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s)
+{
+ lockdep_assert_held(ctrl->handler->lock);
+
+ /* It's a driver bug if this happens. */
+ WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
+ strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
+ return set_ctrl(NULL, ctrl, NULL, 0);
+}
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
{
@@ -2886,40 +3280,47 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void
}
EXPORT_SYMBOL(v4l2_ctrl_notify);
-int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
- s32 min, s32 max, u32 step, s32 def)
+int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
+ s64 min, s64 max, u64 step, s64 def)
{
- int ret = check_range(ctrl->type, min, max, step, def);
+ int ret;
struct v4l2_ext_control c;
+ lockdep_assert_held(ctrl->handler->lock);
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER64:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_INTEGER_MENU:
case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_U8:
+ case V4L2_CTRL_TYPE_U16:
+ case V4L2_CTRL_TYPE_U32:
+ if (ctrl->is_array)
+ return -EINVAL;
+ ret = check_range(ctrl->type, min, max, step, def);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
- v4l2_ctrl_lock(ctrl);
ctrl->minimum = min;
ctrl->maximum = max;
ctrl->step = step;
ctrl->default_value = def;
- c.value = ctrl->cur.val;
+ c.value = *ctrl->p_cur.p_s32;
if (validate_new(ctrl, &c))
c.value = def;
- if (c.value != ctrl->cur.val)
+ if (c.value != *ctrl->p_cur.p_s32)
ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
else
send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
- v4l2_ctrl_unlock(ctrl);
return ret;
}
-EXPORT_SYMBOL(v4l2_ctrl_modify_range);
+EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
{
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 634d863c05b4..33617c365acc 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -335,7 +335,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
return DEFAULT_POLLMASK;
if (video_is_registered(vdev))
res = vdev->fops->poll(filp, poll);
- if (vdev->debug)
+ if (vdev->debug > 2)
printk(KERN_DEBUG "%s: poll: %08x\n",
video_device_node_name(vdev), res);
return res;
@@ -563,20 +563,18 @@ static void determine_valid_ioctls(struct video_device *vdev)
/* vfl_type and vfl_dir independent ioctls */
SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
- if (ops->vidioc_g_priority ||
- test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ if (ops->vidioc_g_priority)
set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
- if (ops->vidioc_s_priority ||
- test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ if (ops->vidioc_s_priority)
set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
- SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
- SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
/* Note: the control handler can also be passed through the filehandle,
and that can't be tested here. If the bit for these control ioctls
is set, then the ioctl is valid. But if it is 0, then it can still
be valid if the filehandle passed the control handler. */
if (vdev->ctrl_handler || ops->vidioc_queryctrl)
set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_query_ext_ctrl)
+ set_bit(_IOC_NR(VIDIOC_QUERY_EXT_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
@@ -684,6 +682,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
}
if (is_vid || is_vbi) {
diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
index e57c002b4150..c97067a25bd2 100644
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -37,6 +37,13 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
fh->ctrl_handler = vdev->ctrl_handler;
INIT_LIST_HEAD(&fh->list);
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
+ /*
+ * determine_valid_ioctls() does not know if struct v4l2_fh
+ * is used by this driver, but here we do. So enable the
+ * prio ioctls here.
+ */
+ set_bit(_IOC_NR(VIDIOC_G_PRIORITY), vdev->valid_ioctls);
+ set_bit(_IOC_NR(VIDIOC_S_PRIORITY), vdev->valid_ioctls);
fh->prio = V4L2_PRIORITY_UNSET;
init_waitqueue_head(&fh->wait);
INIT_LIST_HEAD(&fh->available);
@@ -49,8 +56,7 @@ void v4l2_fh_add(struct v4l2_fh *fh)
{
unsigned long flags;
- if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
- v4l2_prio_open(fh->vdev->prio, &fh->prio);
+ v4l2_prio_open(fh->vdev->prio, &fh->prio);
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_add(&fh->list, &fh->vdev->fh_list);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
@@ -78,8 +84,7 @@ void v4l2_fh_del(struct v4l2_fh *fh)
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_del_init(&fh->list);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
- v4l2_prio_close(fh->vdev->prio, fh->prio);
+ v4l2_prio_close(fh->vdev->prio, fh->prio);
}
EXPORT_SYMBOL_GPL(v4l2_fh_del);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 16bffd851bf9..d15e16737eef 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -256,7 +256,8 @@ static void v4l_print_format(const void *arg, bool write_only)
pix = &p->fmt.pix;
pr_cont(", width=%u, height=%u, "
"pixelformat=%c%c%c%c, field=%s, "
- "bytesperline=%u, sizeimage=%u, colorspace=%d\n",
+ "bytesperline=%u, sizeimage=%u, colorspace=%d, "
+ "flags %u\n",
pix->width, pix->height,
(pix->pixelformat & 0xff),
(pix->pixelformat >> 8) & 0xff,
@@ -264,7 +265,7 @@ static void v4l_print_format(const void *arg, bool write_only)
(pix->pixelformat >> 24) & 0xff,
prt_names(pix->field, v4l2_field_names),
pix->bytesperline, pix->sizeimage,
- pix->colorspace);
+ pix->colorspace, pix->flags);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
@@ -525,6 +526,20 @@ static void v4l_print_queryctrl(const void *arg, bool write_only)
p->step, p->default_value, p->flags);
}
+static void v4l_print_query_ext_ctrl(const void *arg, bool write_only)
+{
+ const struct v4l2_query_ext_ctrl *p = arg;
+
+ pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, "
+ "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, "
+ "nr_of_dims=%u, dims=%u,%u,%u,%u\n",
+ p->id, p->type, (int)sizeof(p->name), p->name,
+ p->minimum, p->maximum,
+ p->step, p->default_value, p->flags,
+ p->elem_size, p->elems, p->nr_of_dims,
+ p->dims[0], p->dims[1], p->dims[2], p->dims[3]);
+}
+
static void v4l_print_querymenu(const void *arg, bool write_only)
{
const struct v4l2_querymenu *p = arg;
@@ -959,13 +974,49 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
return -EINVAL;
}
+static void v4l_sanitize_format(struct v4l2_format *fmt)
+{
+ unsigned int offset;
+
+ /*
+ * The v4l2_pix_format structure has been extended with fields that were
+ * not previously required to be set to zero by applications. The priv
+ * field, when set to a magic value, indicates the the extended fields
+ * are valid. Otherwise they will contain undefined values. To simplify
+ * the API towards drivers zero the extended fields and set the priv
+ * field to the magic value when the extended pixel format structure
+ * isn't used by applications.
+ */
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return;
+
+ if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
+ return;
+
+ fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+ offset = offsetof(struct v4l2_pix_format, priv)
+ + sizeof(fmt->fmt.pix.priv);
+ memset(((void *)&fmt->fmt.pix) + offset, 0,
+ sizeof(fmt->fmt.pix) - offset);
+}
+
static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+ int ret;
cap->version = LINUX_VERSION_CODE;
- return ops->vidioc_querycap(file, fh, cap);
+
+ ret = ops->vidioc_querycap(file, fh, cap);
+
+ cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
+ cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
+
+ return ret;
}
static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1048,32 +1099,34 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
{
struct v4l2_fmtdesc *p = arg;
struct video_device *vfd = video_devdata(file);
+ bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+ bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap))
break;
return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane))
break;
return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay))
break;
return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out))
+ if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out))
break;
return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
+ if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane))
break;
return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
case V4L2_BUF_TYPE_SDR_CAPTURE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
+ if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap))
break;
return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
}
@@ -1089,12 +1142,41 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ /*
+ * fmt can't be cleared for these overlay types due to the 'clips'
+ * 'clipcount' and 'bitmap' pointers in struct v4l2_window.
+ * Those are provided by the user. So handle these two overlay types
+ * first, and then just do a simple memset for the other types.
+ */
+ switch (p->type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+ struct v4l2_clip *clips = p->fmt.win.clips;
+ u32 clipcount = p->fmt.win.clipcount;
+ void *bitmap = p->fmt.win.bitmap;
+
+ memset(&p->fmt, 0, sizeof(p->fmt));
+ p->fmt.win.clips = clips;
+ p->fmt.win.clipcount = clipcount;
+ p->fmt.win.bitmap = bitmap;
+ break;
+ }
+ default:
+ memset(&p->fmt, 0, sizeof(p->fmt));
+ break;
+ }
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
break;
- return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
break;
@@ -1114,7 +1196,11 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
break;
- return ops->vidioc_g_fmt_vid_out(file, fh, arg);
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
break;
@@ -1148,13 +1234,19 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ v4l_sanitize_format(p);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+ ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
break;
@@ -1179,7 +1271,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_s_fmt_vid_out(file, fh, arg);
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
break;
@@ -1218,13 +1313,19 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ v4l_sanitize_format(p);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+ ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
break;
@@ -1249,7 +1350,10 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_try_fmt_vid_out(file, fh, arg);
+ ret = ops->vidioc_try_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
break;
@@ -1502,7 +1606,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
struct v4l2_create_buffers *create = arg;
int ret = check_fmt(file, create->format.type);
- return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
+ if (ret)
+ return ret;
+
+ v4l_sanitize_format(&create->format);
+
+ ret = ops->vidioc_create_bufs(file, fh, create);
+
+ if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+ return ret;
}
static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
@@ -1561,6 +1676,23 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
return -ENOTTY;
}
+static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ struct v4l2_query_ext_ctrl *p = arg;
+ struct v4l2_fh *vfh =
+ test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
+
+ if (vfh && vfh->ctrl_handler)
+ return v4l2_query_ext_ctrl(vfh->ctrl_handler, p);
+ if (vfd->ctrl_handler)
+ return v4l2_query_ext_ctrl(vfd->ctrl_handler, p);
+ if (ops->vidioc_query_ext_ctrl)
+ return ops->vidioc_query_ext_ctrl(file, fh, p);
+ return -ENOTTY;
+}
+
static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
@@ -1751,37 +1883,41 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_cropcap *p = arg;
- struct v4l2_selection s = { .type = p->type };
- int ret;
- if (ops->vidioc_cropcap)
- return ops->vidioc_cropcap(file, fh, p);
+ if (ops->vidioc_g_selection) {
+ struct v4l2_selection s = { .type = p->type };
+ int ret;
- /* obtaining bounds */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
- else
- s.target = V4L2_SEL_TGT_CROP_BOUNDS;
+ /* obtaining bounds */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+ else
+ s.target = V4L2_SEL_TGT_CROP_BOUNDS;
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- return ret;
- p->bounds = s.r;
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ return ret;
+ p->bounds = s.r;
- /* obtaining defrect */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
- else
- s.target = V4L2_SEL_TGT_CROP_DEFAULT;
+ /* obtaining defrect */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+ else
+ s.target = V4L2_SEL_TGT_CROP_DEFAULT;
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- return ret;
- p->defrect = s.r;
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ return ret;
+ p->defrect = s.r;
+ }
/* setting trivial pixelaspect */
p->pixelaspect.numerator = 1;
p->pixelaspect.denominator = 1;
+
+ if (ops->vidioc_cropcap)
+ return ops->vidioc_cropcap(file, fh, p);
+
return 0;
}
@@ -1951,8 +2087,11 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
if (type != p->type)
return -EINVAL;
}
- if (ops->vidioc_enum_freq_bands)
- return ops->vidioc_enum_freq_bands(file, fh, p);
+ if (ops->vidioc_enum_freq_bands) {
+ err = ops->vidioc_enum_freq_bands(file, fh, p);
+ if (err != -ENOTTY)
+ return err;
+ }
if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
struct v4l2_tuner t = {
.index = p->tuner,
@@ -2042,7 +2181,7 @@ struct v4l2_ioctl_info {
static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
- IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)),
+ IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0),
IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
@@ -2070,8 +2209,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
- IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)),
- IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)),
+ IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0),
+ IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO),
IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
@@ -2084,8 +2223,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
- IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0),
- IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO),
+ IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)),
+ IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)),
IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
@@ -2121,6 +2260,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
+ IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -2190,7 +2330,6 @@ static long __video_do_ioctl(struct file *file,
const struct v4l2_ioctl_info *info;
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
- int use_fh_prio = 0;
int debug = vfd->debug;
long ret = -ENOTTY;
@@ -2200,10 +2339,8 @@ static long __video_do_ioctl(struct file *file,
return ret;
}
- if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
- use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
- }
if (v4l2_is_known_ioctl(cmd)) {
info = &v4l2_ioctls[_IOC_NR(cmd)];
@@ -2212,7 +2349,7 @@ static long __video_do_ioctl(struct file *file,
!((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
goto done;
- if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
+ if (vfh && (info->flags & INFO_FL_PRIO)) {
ret = v4l2_prio_check(vfd->prio, vfh->prio);
if (ret)
goto done;
@@ -2237,7 +2374,7 @@ static long __video_do_ioctl(struct file *file,
ret = -ENOTTY;
} else {
ret = ops->vidioc_default(file, fh,
- use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
+ vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
cmd, arg);
}
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 178ce96556c6..80c588f4e429 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -208,7 +208,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
* An example of the above could be an instance that requires more than one
* src/dst buffer per transaction.
*/
-static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
+void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
{
struct v4l2_m2m_dev *m2m_dev;
unsigned long flags_job, flags_out, flags_cap;
@@ -274,6 +274,7 @@ static void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
v4l2_m2m_try_run(m2m_dev);
}
+EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule);
/**
* v4l2_m2m_cancel_job() - cancel pending jobs for the context
@@ -568,8 +569,12 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
if (m2m_ctx->m2m_dev->m2m_ops->lock)
m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock)
- mutex_lock(m2m_ctx->q_lock);
+ else if (m2m_ctx->q_lock) {
+ if (mutex_lock_interruptible(m2m_ctx->q_lock)) {
+ rc |= POLLERR;
+ goto end;
+ }
+ }
spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list))
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 058c1a6e8392..b4d235c13fbf 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -126,6 +126,57 @@ static int subdev_close(struct file *file)
return 0;
}
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+static int check_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_format *format)
+{
+ if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+ format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (format->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop)
+{
+ if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
+ crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (crop->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_selection *sel)
+{
+ if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
+ sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (sel->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+ if (edid->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ if (edid->blocks && edid->edid == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
@@ -133,12 +184,16 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_fh *vfh = file->private_data;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+ int rval;
#endif
switch (cmd) {
case VIDIOC_QUERYCTRL:
return v4l2_queryctrl(vfh->ctrl_handler, arg);
+ case VIDIOC_QUERY_EXT_CTRL:
+ return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg);
+
case VIDIOC_QUERYMENU:
return v4l2_querymenu(vfh->ctrl_handler, arg);
@@ -203,12 +258,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_FMT: {
struct v4l2_subdev_format *format = arg;
- if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
- format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (format->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_format(sd, format);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
}
@@ -216,12 +268,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_FMT: {
struct v4l2_subdev_format *format = arg;
- if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
- format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (format->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_format(sd, format);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
}
@@ -229,14 +278,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_CROP: {
struct v4l2_subdev_crop *crop = arg;
struct v4l2_subdev_selection sel;
- int rval;
-
- if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
- crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
- if (crop->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_crop(sd, crop);
+ if (rval)
+ return rval;
rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
if (rval != -ENOIOCTLCMD)
@@ -258,14 +303,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_CROP: {
struct v4l2_subdev_crop *crop = arg;
struct v4l2_subdev_selection sel;
- int rval;
-
- if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
- crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
- if (crop->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_crop(sd, crop);
+ if (rval)
+ return rval;
rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
if (rval != -ENOIOCTLCMD)
@@ -336,12 +377,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_SELECTION: {
struct v4l2_subdev_selection *sel = arg;
- if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
- sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (sel->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_selection(sd, sel);
+ if (rval)
+ return rval;
return v4l2_subdev_call(
sd, pad, get_selection, subdev_fh, sel);
@@ -350,12 +388,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_SELECTION: {
struct v4l2_subdev_selection *sel = arg;
- if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
- sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (sel->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_selection(sd, sel);
+ if (rval)
+ return rval;
return v4l2_subdev_call(
sd, pad, set_selection, subdev_fh, sel);
@@ -364,10 +399,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_G_EDID: {
struct v4l2_subdev_edid *edid = arg;
- if (edid->pad >= sd->entity.num_pads)
- return -EINVAL;
- if (edid->blocks && edid->edid == NULL)
- return -EINVAL;
+ rval = check_edid(sd, edid);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, get_edid, edid);
}
@@ -375,10 +409,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_S_EDID: {
struct v4l2_subdev_edid *edid = arg;
- if (edid->pad >= sd->entity.num_pads)
- return -EINVAL;
- if (edid->blocks && edid->edid == NULL)
- return -EINVAL;
+ rval = check_edid(sd, edid);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, set_edid, edid);
}
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 828e7c10bd70..3c8cc023a5a5 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -211,13 +211,36 @@ EXPORT_SYMBOL_GPL(videobuf_dma_init_user);
int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
int nr_pages)
{
+ int i;
+
dprintk(1, "init kernel [%d pages]\n", nr_pages);
dma->direction = direction;
- dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ dma->vaddr_pages = kcalloc(nr_pages, sizeof(*dma->vaddr_pages),
+ GFP_KERNEL);
+ if (!dma->vaddr_pages)
+ return -ENOMEM;
+
+ dma->dma_addr = kcalloc(nr_pages, sizeof(*dma->dma_addr), GFP_KERNEL);
+ if (!dma->dma_addr) {
+ kfree(dma->vaddr_pages);
+ return -ENOMEM;
+ }
+ for (i = 0; i < nr_pages; i++) {
+ void *addr;
+
+ addr = dma_alloc_coherent(dma->dev, PAGE_SIZE,
+ &(dma->dma_addr[i]), GFP_KERNEL);
+ if (addr == NULL)
+ goto out_free_pages;
+
+ dma->vaddr_pages[i] = virt_to_page(addr);
+ }
+ dma->vaddr = vmap(dma->vaddr_pages, nr_pages, VM_MAP | VM_IOREMAP,
+ PAGE_KERNEL);
if (NULL == dma->vaddr) {
dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
- return -ENOMEM;
+ goto out_free_pages;
}
dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
@@ -228,6 +251,19 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
dma->nr_pages = nr_pages;
return 0;
+out_free_pages:
+ while (i > 0) {
+ void *addr = page_address(dma->vaddr_pages[i]);
+ dma_free_coherent(dma->dev, PAGE_SIZE, addr, dma->dma_addr[i]);
+ i--;
+ }
+ kfree(dma->dma_addr);
+ dma->dma_addr = NULL;
+ kfree(dma->vaddr_pages);
+ dma->vaddr_pages = NULL;
+
+ return -ENOMEM;
+
}
EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel);
@@ -322,8 +358,21 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
dma->pages = NULL;
}
- vfree(dma->vaddr);
- dma->vaddr = NULL;
+ if (dma->dma_addr) {
+ for (i = 0; i < dma->nr_pages; i++) {
+ void *addr;
+
+ addr = page_address(dma->vaddr_pages[i]);
+ dma_free_coherent(dma->dev, PAGE_SIZE, addr,
+ dma->dma_addr[i]);
+ }
+ kfree(dma->dma_addr);
+ dma->dma_addr = NULL;
+ kfree(dma->vaddr_pages);
+ dma->vaddr_pages = NULL;
+ vunmap(dma->vaddr);
+ dma->vaddr = NULL;
+ }
if (dma->bus_addr)
dma->bus_addr = 0;
@@ -461,6 +510,11 @@ static int __videobuf_iolock(struct videobuf_queue *q,
MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+ if (!mem->dma.dev)
+ mem->dma.dev = q->dev;
+ else
+ WARN_ON(mem->dma.dev != q->dev);
+
switch (vb->memory) {
case V4L2_MEMORY_MMAP:
case V4L2_MEMORY_USERPTR:
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 7c4489c42365..c359006074a8 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -576,6 +576,7 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer
static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
{
unsigned int length;
+ unsigned int bytesused;
unsigned int plane;
if (!V4L2_TYPE_IS_OUTPUT(b->type))
@@ -583,21 +584,24 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
for (plane = 0; plane < vb->num_planes; ++plane) {
- length = (b->memory == V4L2_MEMORY_USERPTR)
+ length = (b->memory == V4L2_MEMORY_USERPTR ||
+ b->memory == V4L2_MEMORY_DMABUF)
? b->m.planes[plane].length
: vb->v4l2_planes[plane].length;
+ bytesused = b->m.planes[plane].bytesused
+ ? b->m.planes[plane].bytesused : length;
if (b->m.planes[plane].bytesused > length)
return -EINVAL;
if (b->m.planes[plane].data_offset > 0 &&
- b->m.planes[plane].data_offset >=
- b->m.planes[plane].bytesused)
+ b->m.planes[plane].data_offset >= bytesused)
return -EINVAL;
}
} else {
length = (b->memory == V4L2_MEMORY_USERPTR)
? b->length : vb->v4l2_planes[0].length;
+ bytesused = b->bytesused ? b->bytesused : length;
if (b->bytesused > length)
return -EINVAL;
@@ -1234,35 +1238,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
unsigned int plane;
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- /* Fill in driver-provided information for OUTPUT types */
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- bool bytesused_is_used;
-
- /* Check if bytesused == 0 for all planes */
- for (plane = 0; plane < vb->num_planes; ++plane)
- if (b->m.planes[plane].bytesused)
- break;
- bytesused_is_used = plane < vb->num_planes;
-
- /*
- * Will have to go up to b->length when API starts
- * accepting variable number of planes.
- *
- * If bytesused_is_used is false, then fall back to the
- * full buffer size. In that case userspace clearly
- * never bothered to set it and it's a safe assumption
- * that they really meant to use the full plane sizes.
- */
- for (plane = 0; plane < vb->num_planes; ++plane) {
- struct v4l2_plane *pdst = &v4l2_planes[plane];
- struct v4l2_plane *psrc = &b->m.planes[plane];
-
- pdst->bytesused = bytesused_is_used ?
- psrc->bytesused : psrc->length;
- pdst->data_offset = psrc->data_offset;
- }
- }
-
if (b->memory == V4L2_MEMORY_USERPTR) {
for (plane = 0; plane < vb->num_planes; ++plane) {
v4l2_planes[plane].m.userptr =
@@ -1279,6 +1254,28 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
b->m.planes[plane].length;
}
}
+
+ /* Fill in driver-provided information for OUTPUT types */
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ /*
+ * Will have to go up to b->length when API starts
+ * accepting variable number of planes.
+ *
+ * If bytesused == 0 for the output buffer, then fall
+ * back to the full buffer size. In that case
+ * userspace clearly never bothered to set it and
+ * it's a safe assumption that they really meant to
+ * use the full plane sizes.
+ */
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct v4l2_plane *pdst = &v4l2_planes[plane];
+ struct v4l2_plane *psrc = &b->m.planes[plane];
+
+ pdst->bytesused = psrc->bytesused ?
+ psrc->bytesused : pdst->length;
+ pdst->data_offset = psrc->data_offset;
+ }
+ }
} else {
/*
* Single-planar buffers do not use planes array,
@@ -1286,15 +1283,9 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
* In videobuf we use our internal V4l2_planes struct for
* single-planar buffers as well, for simplicity.
*
- * If bytesused == 0, then fall back to the full buffer size
- * as that's a sensible default.
+ * If bytesused == 0 for the output buffer, then fall back
+ * to the full buffer size as that's a sensible default.
*/
- if (V4L2_TYPE_IS_OUTPUT(b->type))
- v4l2_planes[0].bytesused =
- b->bytesused ? b->bytesused : b->length;
- else
- v4l2_planes[0].bytesused = 0;
-
if (b->memory == V4L2_MEMORY_USERPTR) {
v4l2_planes[0].m.userptr = b->m.userptr;
v4l2_planes[0].length = b->length;
@@ -1304,6 +1295,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
v4l2_planes[0].m.fd = b->m.fd;
v4l2_planes[0].length = b->length;
}
+
+ if (V4L2_TYPE_IS_OUTPUT(b->type))
+ v4l2_planes[0].bytesused = b->bytesused ?
+ b->bytesused : v4l2_planes[0].length;
+ else
+ v4l2_planes[0].bytesused = 0;
+
}
/* Zero flags that the vb2 core handles */
@@ -1606,6 +1604,11 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
return -EINVAL;
}
+ if (q->error) {
+ dprintk(1, "fatal error occurred on queue\n");
+ return -EIO;
+ }
+
vb->state = VB2_BUF_STATE_PREPARING;
vb->v4l2_buf.timestamp.tv_sec = 0;
vb->v4l2_buf.timestamp.tv_usec = 0;
@@ -1750,12 +1753,14 @@ static int vb2_start_streaming(struct vb2_queue *q)
__enqueue_in_driver(vb);
/* Tell the driver to start streaming */
+ q->start_streaming_called = 1;
ret = call_qop(q, start_streaming, q,
atomic_read(&q->owned_by_drv_count));
- q->start_streaming_called = ret == 0;
if (!ret)
return 0;
+ q->start_streaming_called = 0;
+
dprintk(1, "driver refused to start streaming\n");
if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
unsigned i;
@@ -1901,6 +1906,11 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
return -EINVAL;
}
+ if (q->error) {
+ dprintk(1, "Queue in error state, will not wait for buffers\n");
+ return -EIO;
+ }
+
if (!list_empty(&q->done_list)) {
/*
* Found a buffer that we were waiting for.
@@ -1926,7 +1936,8 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
*/
dprintk(3, "will sleep waiting for buffers\n");
ret = wait_event_interruptible(q->done_wq,
- !list_empty(&q->done_list) || !q->streaming);
+ !list_empty(&q->done_list) || !q->streaming ||
+ q->error);
/*
* We need to reevaluate both conditions again after reacquiring
@@ -2123,6 +2134,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
q->streaming = 0;
q->start_streaming_called = 0;
q->queued_count = 0;
+ q->error = 0;
/*
* Remove all buffers from videobuf's list...
@@ -2200,6 +2212,27 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
}
/**
+ * vb2_queue_error() - signal a fatal error on the queue
+ * @q: videobuf2 queue
+ *
+ * Flag that a fatal unrecoverable error has occurred and wake up all processes
+ * waiting on the queue. Polling will now set POLLERR and queuing and dequeuing
+ * buffers will return -EIO.
+ *
+ * The error flag will be cleared when cancelling the queue, either from
+ * vb2_streamoff or vb2_queue_release. Drivers should thus not call this
+ * function before starting the stream, otherwise the error flag will remain set
+ * until the queue is released when closing the device node.
+ */
+void vb2_queue_error(struct vb2_queue *q)
+{
+ q->error = 1;
+
+ wake_up_all(&q->done_wq);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_error);
+
+/**
* vb2_streamon - start streaming
* @q: videobuf2 queue
* @type: type argument passed from userspace to vidioc_streamon handler
@@ -2557,11 +2590,19 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
}
/*
- * There is nothing to wait for if no buffers have already been queued.
+ * There is nothing to wait for if no buffer has been queued and the
+ * queue isn't streaming, or if the error flag is set.
*/
- if (list_empty(&q->queued_list))
+ if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error)
return res | POLLERR;
+ /*
+ * For output streams you can write as long as there are fewer buffers
+ * queued than there are buffers available.
+ */
+ if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
+ return res | POLLOUT | POLLWRNORM;
+
if (list_empty(&q->done_list))
poll_wait(file, &q->done_wq, wait);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 880be0782dd9..4a02ade14b4f 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -98,6 +98,9 @@ static void *vb2_dc_vaddr(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
+ if (!buf->vaddr && buf->db_attach)
+ buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+
return buf->vaddr;
}
@@ -404,7 +407,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
if (WARN_ON(!buf->sgt_base))
return NULL;
- dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags);
+ dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags, NULL);
if (IS_ERR(dbuf))
return NULL;
@@ -735,6 +738,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
buf->dma_addr = sg_dma_address(sgt->sgl);
buf->dma_sgt = sgt;
+ buf->vaddr = NULL;
return 0;
}
@@ -754,6 +758,10 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv)
return;
}
+ if (buf->vaddr) {
+ dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+ buf->vaddr = NULL;
+ }
dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
buf->dma_addr = 0;
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c59e9c96e86d..fab81a143bd7 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -61,6 +61,16 @@ config TEGRA30_MC
analysis, especially for IOMMU/SMMU(System Memory Management
Unit) module.
+config FSL_CORENET_CF
+ tristate "Freescale CoreNet Error Reporting"
+ depends on FSL_SOC_BOOKE
+ help
+ Say Y for reporting of errors from the Freescale CoreNet
+ Coherency Fabric. Errors reported include accesses to
+ physical addresses that mapped by no local access window
+ (LAW) or an invalid LAW, as well as bad cache state that
+ represents a coherency violation.
+
config FSL_IFC
bool
depends on FSL_SOC
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 71160a2b7313..4055c47f45ab 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF) += of_memory.o
endif
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
obj-$(CONFIG_TI_EMIF) += emif.o
+obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c
new file mode 100644
index 000000000000..c9443fc136db
--- /dev/null
+++ b/drivers/memory/fsl-corenet-cf.c
@@ -0,0 +1,251 @@
+/*
+ * CoreNet Coherency Fabric error reporting
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+enum ccf_version {
+ CCF1,
+ CCF2,
+};
+
+struct ccf_info {
+ enum ccf_version version;
+ int err_reg_offs;
+};
+
+static const struct ccf_info ccf1_info = {
+ .version = CCF1,
+ .err_reg_offs = 0xa00,
+};
+
+static const struct ccf_info ccf2_info = {
+ .version = CCF2,
+ .err_reg_offs = 0xe40,
+};
+
+static const struct of_device_id ccf_matches[] = {
+ {
+ .compatible = "fsl,corenet1-cf",
+ .data = &ccf1_info,
+ },
+ {
+ .compatible = "fsl,corenet2-cf",
+ .data = &ccf2_info,
+ },
+ {}
+};
+
+struct ccf_err_regs {
+ u32 errdet; /* 0x00 Error Detect Register */
+ /* 0x04 Error Enable (ccf1)/Disable (ccf2) Register */
+ u32 errdis;
+ /* 0x08 Error Interrupt Enable Register (ccf2 only) */
+ u32 errinten;
+ u32 cecar; /* 0x0c Error Capture Attribute Register */
+ u32 cecaddrh; /* 0x10 Error Capture Address High */
+ u32 cecaddrl; /* 0x14 Error Capture Address Low */
+ u32 cecar2; /* 0x18 Error Capture Attribute Register 2 */
+};
+
+/* LAE/CV also valid for errdis and errinten */
+#define ERRDET_LAE (1 << 0) /* Local Access Error */
+#define ERRDET_CV (1 << 1) /* Coherency Violation */
+#define ERRDET_CTYPE_SHIFT 26 /* Capture Type (ccf2 only) */
+#define ERRDET_CTYPE_MASK (0x1f << ERRDET_CTYPE_SHIFT)
+#define ERRDET_CAP (1 << 31) /* Capture Valid (ccf2 only) */
+
+#define CECAR_VAL (1 << 0) /* Valid (ccf1 only) */
+#define CECAR_UVT (1 << 15) /* Unavailable target ID (ccf1) */
+#define CECAR_SRCID_SHIFT_CCF1 24
+#define CECAR_SRCID_MASK_CCF1 (0xff << CECAR_SRCID_SHIFT_CCF1)
+#define CECAR_SRCID_SHIFT_CCF2 18
+#define CECAR_SRCID_MASK_CCF2 (0xff << CECAR_SRCID_SHIFT_CCF2)
+
+#define CECADDRH_ADDRH 0xff
+
+struct ccf_private {
+ const struct ccf_info *info;
+ struct device *dev;
+ void __iomem *regs;
+ struct ccf_err_regs __iomem *err_regs;
+};
+
+static irqreturn_t ccf_irq(int irq, void *dev_id)
+{
+ struct ccf_private *ccf = dev_id;
+ static DEFINE_RATELIMIT_STATE(ratelimit, DEFAULT_RATELIMIT_INTERVAL,
+ DEFAULT_RATELIMIT_BURST);
+ u32 errdet, cecar, cecar2;
+ u64 addr;
+ u32 src_id;
+ bool uvt = false;
+ bool cap_valid = false;
+
+ errdet = ioread32be(&ccf->err_regs->errdet);
+ cecar = ioread32be(&ccf->err_regs->cecar);
+ cecar2 = ioread32be(&ccf->err_regs->cecar2);
+ addr = ioread32be(&ccf->err_regs->cecaddrl);
+ addr |= ((u64)(ioread32be(&ccf->err_regs->cecaddrh) &
+ CECADDRH_ADDRH)) << 32;
+
+ if (!__ratelimit(&ratelimit))
+ goto out;
+
+ switch (ccf->info->version) {
+ case CCF1:
+ if (cecar & CECAR_VAL) {
+ if (cecar & CECAR_UVT)
+ uvt = true;
+
+ src_id = (cecar & CECAR_SRCID_MASK_CCF1) >>
+ CECAR_SRCID_SHIFT_CCF1;
+ cap_valid = true;
+ }
+
+ break;
+ case CCF2:
+ if (errdet & ERRDET_CAP) {
+ src_id = (cecar & CECAR_SRCID_MASK_CCF2) >>
+ CECAR_SRCID_SHIFT_CCF2;
+ cap_valid = true;
+ }
+
+ break;
+ }
+
+ dev_crit(ccf->dev, "errdet 0x%08x cecar 0x%08x cecar2 0x%08x\n",
+ errdet, cecar, cecar2);
+
+ if (errdet & ERRDET_LAE) {
+ if (uvt)
+ dev_crit(ccf->dev, "LAW Unavailable Target ID\n");
+ else
+ dev_crit(ccf->dev, "Local Access Window Error\n");
+ }
+
+ if (errdet & ERRDET_CV)
+ dev_crit(ccf->dev, "Coherency Violation\n");
+
+ if (cap_valid) {
+ dev_crit(ccf->dev, "address 0x%09llx, src id 0x%x\n",
+ addr, src_id);
+ }
+
+out:
+ iowrite32be(errdet, &ccf->err_regs->errdet);
+ return errdet ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int ccf_probe(struct platform_device *pdev)
+{
+ struct ccf_private *ccf;
+ struct resource *r;
+ const struct of_device_id *match;
+ int ret, irq;
+
+ match = of_match_device(ccf_matches, &pdev->dev);
+ if (WARN_ON(!match))
+ return -ENODEV;
+
+ ccf = devm_kzalloc(&pdev->dev, sizeof(*ccf), GFP_KERNEL);
+ if (!ccf)
+ return -ENOMEM;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+ return -ENXIO;
+ }
+
+ ccf->regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(ccf->regs)) {
+ dev_err(&pdev->dev, "%s: can't map mem resource\n", __func__);
+ return PTR_ERR(ccf->regs);
+ }
+
+ ccf->dev = &pdev->dev;
+ ccf->info = match->data;
+ ccf->err_regs = ccf->regs + ccf->info->err_reg_offs;
+
+ dev_set_drvdata(&pdev->dev, ccf);
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "%s: no irq\n", __func__);
+ return -ENXIO;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: can't request irq\n", __func__);
+ return ret;
+ }
+
+ switch (ccf->info->version) {
+ case CCF1:
+ /* On CCF1 this register enables rather than disables. */
+ iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errdis);
+ break;
+
+ case CCF2:
+ iowrite32be(0, &ccf->err_regs->errdis);
+ iowrite32be(ERRDET_LAE | ERRDET_CV, &ccf->err_regs->errinten);
+ break;
+ }
+
+ return 0;
+}
+
+static int ccf_remove(struct platform_device *pdev)
+{
+ struct ccf_private *ccf = dev_get_drvdata(&pdev->dev);
+
+ switch (ccf->info->version) {
+ case CCF1:
+ iowrite32be(0, &ccf->err_regs->errdis);
+ break;
+
+ case CCF2:
+ /*
+ * We clear errdis on ccf1 because that's the only way to
+ * disable interrupts, but on ccf2 there's no need to disable
+ * detection.
+ */
+ iowrite32be(0, &ccf->err_regs->errinten);
+ break;
+ }
+
+ return 0;
+}
+
+static struct platform_driver ccf_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = ccf_matches,
+ },
+ .probe = ccf_probe,
+ .remove = ccf_remove,
+};
+
+module_platform_driver(ccf_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale CoreNet Coherency Fabric error reporting");
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index ebc0af7d769c..a896d948b79e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -649,12 +649,10 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
case MPI_FUNCTION_CONFIG:
case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
- if (reply) {
- ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
- memcpy(ioc->mptbase_cmds.reply, reply,
- min(MPT_DEFAULT_FRAME_SIZE,
- 4 * reply->u.reply.MsgLength));
- }
+ ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
+ memcpy(ioc->mptbase_cmds.reply, reply,
+ min(MPT_DEFAULT_FRAME_SIZE,
+ 4 * reply->u.reply.MsgLength));
if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) {
ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
complete(&ioc->mptbase_cmds.done);
@@ -1408,8 +1406,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
* in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
*
**/
-static void
-mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
+static const char*
+mpt_get_product_name(u16 vendor, u16 device, u8 revision)
{
char *product_str = NULL;
@@ -1635,8 +1633,7 @@ mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
}
out:
- if (product_str)
- sprintf(prod_name, "%s", product_str);
+ return product_str;
}
/**
@@ -1887,8 +1884,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
ioc->name, &ioc->facts, &ioc->pfacts[0]));
- mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision,
- ioc->prod_name);
+ ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device,
+ pdev->revision);
switch (pdev->device)
{
@@ -7007,7 +7004,7 @@ EXPORT_SYMBOL(mpt_halt_firmware);
* IOC doesn't reply to any outstanding request. This will transfer IOC
* to READY state.
**/
-int
+static int
mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
{
int rc;
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 76c05bc24cb7..8f14090b8b71 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -405,7 +405,7 @@ typedef struct _VirtTarget {
typedef struct _VirtDevice {
VirtTarget *vtarget;
u8 configured_lun;
- int lun;
+ u64 lun;
} VirtDevice;
/*
@@ -605,7 +605,7 @@ typedef struct _MPT_ADAPTER
int id; /* Unique adapter id N {0,1,2,...} */
int pci_irq; /* This irq */
char name[MPT_NAME_LENGTH]; /* "iocN" */
- char prod_name[MPT_NAME_LENGTH]; /* "LSIFC9x9" */
+ const char *prod_name; /* "LSIFC9x9" */
#ifdef CONFIG_FUSION_LOGGING
/* used in mpt_display_event_info */
char evStr[EVENT_DESCR_STR_SZ];
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 8a050e885688..b0a892a2bf1b 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1261,19 +1261,11 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
else
return -EFAULT;
- karg = kmalloc(data_size, GFP_KERNEL);
- if (karg == NULL) {
- printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
- __FILE__, __LINE__);
- return -ENOMEM;
- }
-
- if (copy_from_user(karg, uarg, data_size)) {
- printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - "
- "Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
- __FILE__, __LINE__, uarg);
- kfree(karg);
- return -EFAULT;
+ karg = memdup_user(uarg, data_size);
+ if (IS_ERR(karg)) {
+ printk(KERN_ERR MYNAM "%s@%d::mpt_ioctl_iocinfo() - memdup_user returned error [%ld]\n",
+ __FILE__, __LINE__, PTR_ERR(karg));
+ return PTR_ERR(karg);
}
if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 02a3eefd6931..d8bf84aef602 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -204,7 +204,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
|| (loops > 0 && ioc->active == 0)) {
spin_unlock_irqrestore(shost->host_lock, flags);
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "mptfc_block_error_handler.%d: %d:%d, port status is "
+ "mptfc_block_error_handler.%d: %d:%llu, port status is "
"%x, active flag %d, deferring %s recovery.\n",
ioc->name, ioc->sh->host_no,
SCpnt->device->id, SCpnt->device->lun,
@@ -218,7 +218,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
|| ioc->active == 0) {
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%d, failing recovery, "
+ "%s.%d: %d:%llu, failing recovery, "
"port state %x, active %d, vdevice %p.\n", caller,
ioc->name, ioc->sh->host_no,
SCpnt->device->id, SCpnt->device->lun, ready,
@@ -226,7 +226,7 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
return FAILED;
}
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%d, executing recovery.\n", caller,
+ "%s.%d: %d:%llu, executing recovery.\n", caller,
ioc->name, ioc->sh->host_no,
SCpnt->device->id, SCpnt->device->lun));
return (*func)(SCpnt);
@@ -525,8 +525,7 @@ mptfc_target_destroy(struct scsi_target *starget)
if (ri) /* better be! */
ri->starget = NULL;
}
- if (starget->hostdata)
- kfree(starget->hostdata);
+ kfree(starget->hostdata);
starget->hostdata = NULL;
}
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 711fcb5cec87..0707fa2c701b 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -990,11 +990,10 @@ mptsas_queue_device_delete(MPT_ADAPTER *ioc,
MpiEventDataSasDeviceStatusChange_t *sas_event_data)
{
struct fw_event_work *fw_event;
- int sz;
- sz = offsetof(struct fw_event_work, event_data) +
- sizeof(MpiEventDataSasDeviceStatusChange_t);
- fw_event = kzalloc(sz, GFP_ATOMIC);
+ fw_event = kzalloc(sizeof(*fw_event) +
+ sizeof(MpiEventDataSasDeviceStatusChange_t),
+ GFP_ATOMIC);
if (!fw_event) {
printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
ioc->name, __func__, __LINE__);
@@ -1011,10 +1010,8 @@ static void
mptsas_queue_rescan(MPT_ADAPTER *ioc)
{
struct fw_event_work *fw_event;
- int sz;
- sz = offsetof(struct fw_event_work, event_data);
- fw_event = kzalloc(sz, GFP_ATOMIC);
+ fw_event = kzalloc(sizeof(*fw_event), GFP_ATOMIC);
if (!fw_event) {
printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
ioc->name, __func__, __LINE__);
@@ -1206,27 +1203,28 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
"(mf = %p, mr = %p)\n", ioc->name, mf, mr));
pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
- if (pScsiTmReply) {
- dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
- "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
- "\ttask_type = 0x%02X, iocstatus = 0x%04X "
- "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
- "term_cmnds = %d\n", ioc->name,
- pScsiTmReply->Bus, pScsiTmReply->TargetID,
- pScsiTmReply->TaskType,
- le16_to_cpu(pScsiTmReply->IOCStatus),
- le32_to_cpu(pScsiTmReply->IOCLogInfo),
- pScsiTmReply->ResponseCode,
- le32_to_cpu(pScsiTmReply->TerminationCount)));
-
- if (pScsiTmReply->ResponseCode)
- mptscsih_taskmgmt_response_code(ioc,
- pScsiTmReply->ResponseCode);
- }
-
- if (pScsiTmReply && (pScsiTmReply->TaskType ==
+ if (!pScsiTmReply)
+ return 0;
+
+ dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+ "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
+ "\ttask_type = 0x%02X, iocstatus = 0x%04X "
+ "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
+ "term_cmnds = %d\n", ioc->name,
+ pScsiTmReply->Bus, pScsiTmReply->TargetID,
+ pScsiTmReply->TaskType,
+ le16_to_cpu(pScsiTmReply->IOCStatus),
+ le32_to_cpu(pScsiTmReply->IOCLogInfo),
+ pScsiTmReply->ResponseCode,
+ le32_to_cpu(pScsiTmReply->TerminationCount)));
+
+ if (pScsiTmReply->ResponseCode)
+ mptscsih_taskmgmt_response_code(ioc,
+ pScsiTmReply->ResponseCode);
+
+ if (pScsiTmReply->TaskType ==
MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
- MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
+ MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {
ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
memcpy(ioc->taskmgmt_cmds.reply, mr,
@@ -1575,7 +1573,7 @@ mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
mptsas_port_delete(ioc, phy_info->port_details);
}
-struct mptsas_phyinfo *
+static struct mptsas_phyinfo *
mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
struct mptsas_devinfo *sas_device)
{
@@ -3648,7 +3646,7 @@ mptsas_send_expander_event(struct fw_event_work *fw_event)
* @handle:
*
*/
-struct mptsas_portinfo *
+static struct mptsas_portinfo *
mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
{
struct mptsas_portinfo buffer, *port_info;
@@ -3763,7 +3761,7 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
printk(MYIOC_s_DEBUG_FMT
"SDEV OUTSTANDING CMDS"
"%d\n", ioc->name,
- sdev->device_busy));
+ atomic_read(&sdev->device_busy)));
}
}
@@ -3856,10 +3854,8 @@ retry_page:
phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
sas_info->sas_address);
- if (phy_info) {
- mptsas_del_end_device(ioc, phy_info);
- goto redo_device_scan;
- }
+ mptsas_del_end_device(ioc, phy_info);
+ goto redo_device_scan;
} else
mptsas_volume_delete(ioc, sas_info->fw.id);
}
@@ -3870,9 +3866,8 @@ retry_page:
redo_expander_scan:
list_for_each_entry(port_info, &ioc->sas_topology, list) {
- if (port_info->phy_info &&
- (!(port_info->phy_info[0].identify.device_info &
- MPI_SAS_DEVICE_INFO_SMP_TARGET)))
+ if (!(port_info->phy_info[0].identify.device_info &
+ MPI_SAS_DEVICE_INFO_SMP_TARGET))
continue;
found_expander = 0;
handle = 0xFFFF;
@@ -4983,7 +4978,7 @@ static int
mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
{
u32 event = le32_to_cpu(reply->Event);
- int sz, event_data_sz;
+ int event_data_sz;
struct fw_event_work *fw_event;
unsigned long delay;
@@ -5093,8 +5088,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
event_data_sz = ((reply->MsgLength * 4) -
offsetof(EventNotificationReply_t, Data));
- sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
- fw_event = kzalloc(sz, GFP_ATOMIC);
+ fw_event = kzalloc(sizeof(*fw_event) + event_data_sz, GFP_ATOMIC);
if (!fw_event) {
printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
__func__, __LINE__);
@@ -5321,7 +5315,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return error;
}
-void
+static void
mptsas_shutdown(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h
index 57e86ab77661..c396483d3624 100644
--- a/drivers/message/fusion/mptsas.h
+++ b/drivers/message/fusion/mptsas.h
@@ -110,7 +110,7 @@ struct fw_event_work {
MPT_ADAPTER *ioc;
u32 event;
u8 retries;
- u8 __attribute__((aligned(4))) event_data[1];
+ char event_data[0] __aligned(4);
};
struct mptsas_discovery_event {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2a1c6f21af27..e7dcb2583369 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -95,7 +95,7 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id,
- int lun, int ctx2abort, ulong timeout);
+ u64 lun, int ctx2abort, ulong timeout);
int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
@@ -536,7 +536,7 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc
}
scsi_print_command(sc);
- printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n",
+ printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %llu\n",
ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun);
printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
"resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
@@ -692,7 +692,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
*/
if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
pScsiReply->ResponseInfo) {
- printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
+ printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%llu] "
"FCP_ResponseInfo=%08xh\n", ioc->name,
sc->device->host->host_no, sc->device->channel,
sc->device->id, sc->device->lun,
@@ -1155,7 +1155,7 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI
return;
ioc = hd->ioc;
if (time - hd->last_queue_full > 10 * HZ) {
- dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
+ dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%llu) reported QUEUE_FULL!\n",
ioc->name, 0, sc->device->id, sc->device->lun));
hd->last_queue_full = time;
}
@@ -1271,15 +1271,13 @@ mptscsih_info(struct Scsi_Host *SChost)
h = shost_priv(SChost);
- if (h) {
- if (h->info_kbuf == NULL)
- if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
- return h->info_kbuf;
- h->info_kbuf[0] = '\0';
+ if (h->info_kbuf == NULL)
+ if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+ return h->info_kbuf;
+ h->info_kbuf[0] = '\0';
- mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
- h->info_kbuf[size-1] = '\0';
- }
+ mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+ h->info_kbuf[size-1] = '\0';
return h->info_kbuf;
}
@@ -1368,8 +1366,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt)
/* Default to untagged. Once a target structure has been allocated,
* use the Inquiry data to determine if device supports tagged.
*/
- if (vdevice
- && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+ if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
if (SCpnt->request && SCpnt->request->ioprio) {
@@ -1518,7 +1515,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
*
**/
int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u64 lun,
int ctx2abort, ulong timeout)
{
MPT_FRAME_HDR *mf;
@@ -2380,7 +2377,7 @@ mptscsih_slave_configure(struct scsi_device *sdev)
vdevice = sdev->hostdata;
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
- "device @ %p, channel=%d, id=%d, lun=%d\n",
+ "device @ %p, channel=%d, id=%d, lun=%llu\n",
ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
if (ioc->bus_type == SPI)
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
@@ -2971,7 +2968,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
+ (my_idx * MPT_SENSE_BUFFER_ALLOC));
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
- "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
+ "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%llu\n",
ioc->name, __func__, cmd, io->channel, io->id, io->lun));
if (dir == MPI_SCSIIO_CONTROL_READ)
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 99e3390807f3..e1b1a198a62a 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -98,7 +98,7 @@ typedef struct _internal_cmd {
u8 cmd; /* SCSI Op Code */
u8 channel; /* bus number */
u8 id; /* SCSI ID (virtual) */
- int lun;
+ u64 lun;
u8 flags; /* Bit Field - See above */
u8 physDiskNum; /* Phys disk number, -1 else */
u8 rsvd2;
@@ -115,7 +115,7 @@ extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt);
extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
- u8 id, int lun, int ctx2abort, ulong timeout);
+ u8 id, u64 lun, int ctx2abort, ulong timeout);
extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 49d11338294b..787933d43d32 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -461,8 +461,7 @@ static int mptspi_target_alloc(struct scsi_target *starget)
static void
mptspi_target_destroy(struct scsi_target *starget)
{
- if (starget->hostdata)
- kfree(starget->hostdata);
+ kfree(starget->hostdata);
starget->hostdata = NULL;
}
@@ -620,7 +619,7 @@ static void mptspi_read_parameters(struct scsi_target *starget)
spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
}
-int
+static int
mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id)
{
MPT_ADAPTER *ioc = hd->ioc;
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 1d31d7284cbd..8152e9fa9d95 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -78,7 +78,7 @@ static unsigned int i2o_scsi_max_lun = 255;
struct i2o_scsi_host {
struct Scsi_Host *scsi_host; /* pointer to the SCSI host */
struct i2o_controller *iop; /* pointer to the I2O controller */
- unsigned int lun; /* lun's used for block devices */
+ u64 lun; /* lun's used for block devices */
struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */
};
@@ -287,9 +287,8 @@ static int i2o_scsi_probe(struct device *dev)
}
if (le64_to_cpu(lun) >= scsi_host->max_lun) {
- osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)",
- (long unsigned int)le64_to_cpu(lun),
- scsi_host->max_lun);
+ osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)",
+ le64_to_cpu(lun), scsi_host->max_lun);
return -EFAULT;
}
@@ -308,9 +307,9 @@ static int i2o_scsi_probe(struct device *dev)
if (rc)
goto err;
- osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
+ osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n",
i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
- (long unsigned int)le64_to_cpu(lun));
+ le64_to_cpu(lun));
return 0;
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 64751c2a1ace..e9d50644660c 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -158,7 +158,7 @@ static int device_irq_init_805(struct pm80x_chip *chip)
* PM805_INT_STATUS is under 32K clock domain, so need to
* add proper delay before the next I2C register access.
*/
- msleep(1);
+ usleep_range(1000, 3000);
if (ret < 0)
goto out;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index bcfc9e85b4a0..3a2604580164 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -2,7 +2,8 @@
* Base driver for Marvell 88PM8607
*
* Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -140,7 +141,8 @@ static struct resource codec_resources[] = {
/* Headset insertion or removal */
{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
/* Audio short */
- {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
+ {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short",
+ IORESOURCE_IRQ,},
};
static struct resource battery_resources[] = {
@@ -150,10 +152,14 @@ static struct resource battery_resources[] = {
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,},
- {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault", IORESOURCE_IRQ,},
- {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", 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,},
+ {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",
+ IORESOURCE_IRQ,},
+ {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature",
+ IORESOURCE_IRQ,},
{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
};
@@ -568,8 +574,8 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
static int device_irq_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
- struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
- : chip->companion;
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ?
+ chip->client : chip->companion;
unsigned char status_buf[INT_STATUS_NUM];
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
int data, mask, ret = -EINVAL;
@@ -631,8 +637,8 @@ static int device_irq_init(struct pm860x_chip *chip,
if (!chip->core_irq)
goto out;
- ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
- "88pm860x", chip);
+ ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq,
+ flags | IRQF_ONESHOT, "88pm860x", chip);
if (ret) {
dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
chip->core_irq = 0;
@@ -871,7 +877,7 @@ static void device_rtc_init(struct pm860x_chip *chip,
{
int ret;
- if ((pdata == NULL))
+ if (!pdata)
return;
rtc_devs[0].platform_data = pdata->rtc;
@@ -997,8 +1003,9 @@ static void device_8607_init(struct pm860x_chip *chip,
ret);
break;
default:
- dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
- "Chip ID: %02x\n", ret);
+ dev_err(chip->dev,
+ "Failed to detect Marvell 88PM8607. Chip ID: %02x\n",
+ ret);
goto out;
}
@@ -1120,8 +1127,8 @@ static int pm860x_dt_init(struct device_node *np,
ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
&pdata->companion_addr);
if (ret) {
- dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
- "property\n");
+ dev_err(dev,
+ "Not found \"marvell,88pm860x-slave-addr\" property\n");
pdata->companion_addr = 0;
}
return 0;
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index ff8f803ce833..a93b4d0134a2 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -2,7 +2,8 @@
* I2C driver for Marvell 88PM860x
*
* Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6cc4b6acc22a..de5abf244746 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -13,7 +13,7 @@ config MFD_CORE
config MFD_CS5535
tristate "AMD CS5535 and CS5536 southbridge core functions"
select MFD_CORE
- depends on PCI && X86
+ depends on PCI && (X86_32 || (X86 && COMPILE_TEST))
---help---
This is the core driver for CS5535/CS5536 MFD functions. This is
necessary for using the board's GPIO and MFGPT functionality.
@@ -187,6 +187,7 @@ config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
select MFD_CORE
+ select REGMAP_IRQ
help
Enable support for the Freescale MC13783 and MC13892 PMICs.
This driver provides common support for accessing the device,
@@ -253,6 +254,18 @@ config LPC_SCH
LPC bridge function of the Intel SCH provides support for
System Management Bus and General Purpose I/O.
+config INTEL_SOC_PMIC
+ bool "Support for Intel Atom SoC PMIC"
+ depends on I2C=y
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Select this option to enable support for the PMIC device
+ on some Intel SoC systems. The PMIC provides ADC, GPIO,
+ thermal, charger and related power management functions
+ on these systems.
+
config MFD_INTEL_MSIC
bool "Intel MSIC"
depends on INTEL_SCU_IPC
@@ -367,14 +380,15 @@ config MFD_MAX14577
of the device.
config MFD_MAX77686
- bool "Maxim Semiconductor MAX77686 PMIC Support"
+ bool "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
select IRQ_DOMAIN
help
- Say yes here to add support for Maxim Semiconductor MAX77686.
- This is a Power Management IC with RTC on chip.
+ Say yes here to add support for Maxim Semiconductor MAX77686 and
+ MAX77802 which are Power Management IC with an RTC on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
@@ -384,6 +398,7 @@ config MFD_MAX77693
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
help
Say yes here to add support for Maxim Semiconductor MAX77693.
This is a companion Power Management IC with Flash, Haptic, Charger,
@@ -573,6 +588,7 @@ config MFD_SEC_CORE
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
+ select REGULATOR
help
Support for the Samsung Electronics MFD series.
This driver provides common support for accessing the device,
@@ -1056,7 +1072,7 @@ config MFD_LM3533
config MFD_TIMBERDALE
tristate "Timberdale FPGA"
select MFD_CORE
- depends on PCI && GPIOLIB
+ depends on PCI && GPIOLIB && (X86_32 || COMPILE_TEST)
---help---
This is the core driver for the timberdale FPGA. This device is a
multifunction device which exposes numerous platform devices.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8afedba535c7..f00148782d9b 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -115,8 +115,8 @@ da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o
obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
-obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
-obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
+obj-$(CONFIG_MFD_MAX77686) += max77686.o
+obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o
@@ -169,3 +169,6 @@ obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
obj-$(CONFIG_MFD_STW481X) += stw481x.o
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
+
+intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 14d9542a4eed..4e6e03d63e12 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -303,7 +303,10 @@ static ssize_t aat2870_reg_write_file(struct file *file,
while (*start == ' ')
start++;
- addr = simple_strtoul(start, &start, 16);
+ ret = kstrtoul(start, 16, &addr);
+ if (ret)
+ return ret;
+
if (addr >= AAT2870_REG_NUM) {
dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
return -EINVAL;
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index b348ae520629..4659ac1db039 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -91,8 +91,8 @@ static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
@@ -135,8 +135,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write test register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write test register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
@@ -171,8 +171,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (send register address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (send register address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
@@ -189,8 +189,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (read register) "
- "%d bytes transferred (expected 1)\n",
+ "write error (read register)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
@@ -237,8 +237,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (send first register address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (send first register address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_page_out_unlock;
@@ -252,8 +252,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != numregs) {
dev_err(ab3100->dev,
- "write error (read register page) "
- "%d bytes transferred (expected %d)\n",
+ "write error (read register page)\n"
+ " %d bytes transferred (expected %d)\n",
err, numregs);
err = -EIO;
goto get_reg_page_out_unlock;
@@ -295,8 +295,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (maskset send address) "
- "%d bytes transferred (expected 1)\n",
+ "write error (maskset send address)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -310,8 +310,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
- "write error (maskset read register) "
- "%d bytes transferred (expected 1)\n",
+ "write error (maskset read register)\n"
+ " %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -330,8 +330,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 2) {
dev_err(ab3100->dev,
- "write error (write register) "
- "%d bytes transferred (expected 2)\n",
+ "write error (write register)\n"
+ " %d bytes transferred (expected 2)\n",
err);
err = -EIO;
goto get_maskset_unlock;
@@ -371,7 +371,7 @@ EXPORT_SYMBOL(ab3100_event_register);
int ab3100_event_unregister(struct ab3100 *ab3100,
struct notifier_block *nb)
{
- return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
+ return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
nb);
}
EXPORT_SYMBOL(ab3100_event_unregister);
@@ -455,7 +455,7 @@ static int ab3100_registers_print(struct seq_file *s, void *p)
u8 value;
u8 reg;
- seq_printf(s, "AB3100 registers:\n");
+ seq_puts(s, "AB3100 registers:\n");
for (reg = 0; reg < 0xff; reg++) {
ab3100_get_register_interruptible(ab3100, reg, &value);
@@ -560,8 +560,8 @@ static ssize_t ab3100_get_set_reg(struct file *file,
ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
dev_info(ab3100->dev,
- "debug write reg[0x%02x] with 0x%02x, "
- "after readback: 0x%02x\n",
+ "debug write reg[0x%02x]\n"
+ " with 0x%02x, after readback: 0x%02x\n",
user_reg, user_value, regvalue);
}
return buf_size;
@@ -719,8 +719,7 @@ static int ab3100_setup(struct ab3100 *ab3100)
*/
if (ab3100->chip_id == 0xc4) {
dev_warn(ab3100->dev,
- "AB3100 P1E variant detected, "
- "forcing chip to 32KHz\n");
+ "AB3100 P1E variant detected forcing chip to 32KHz\n");
err = ab3100_set_test_register_interruptible(ab3100,
0x02, 0x08);
}
@@ -878,8 +877,7 @@ static int ab3100_probe(struct i2c_client *client,
&ab3100->chip_id);
if (err) {
dev_err(&client->dev,
- "could not communicate with the AB3100 analog "
- "baseband chip\n");
+ "failed to communicate with AB3100 chip\n");
goto exit_no_detect;
}
@@ -902,8 +900,8 @@ static int ab3100_probe(struct i2c_client *client,
if (ids[i].id == 0x0) {
dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
ab3100->chip_id);
- dev_err(&client->dev, "accepting it anyway. Please update "
- "the driver.\n");
+ dev_err(&client->dev,
+ "accepting it anyway. Please update the driver.\n");
goto exit_no_detect;
}
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index cf2e6a198c6b..ce48aa72bb42 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -148,8 +148,8 @@ static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
/* AB8540 support */
static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
- 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
- 25, 26, 27, 28, 29, 30, 31,
+ 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
+ 23, 25, 26, 27, 28, 29, 30, 31,
};
static const char ab8500_version_str[][7] = {
@@ -322,7 +322,7 @@ static int ab8500_mask_and_set_register(struct device *dev,
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
atomic_inc(&ab8500->transfer_ongoing);
- ret= mask_and_set_register_interruptible(ab8500, bank, reg,
+ ret = mask_and_set_register_interruptible(ab8500, bank, reg,
bitmask, bitvalues);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
@@ -415,9 +415,11 @@ static void ab8500_irq_unmask(struct irq_data *data)
if (type & IRQ_TYPE_EDGE_FALLING) {
if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
ab8500->mask[index + 2] &= ~mask;
- else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
+ else if (offset >= AB9540_INT_GPIO50R &&
+ offset <= AB9540_INT_GPIO54R)
ab8500->mask[index + 1] &= ~mask;
- else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
+ else if (offset == AB8540_INT_GPIO43R ||
+ offset == AB8540_INT_GPIO44R)
/* Here the falling IRQ is one bit lower */
ab8500->mask[index] &= ~(mask << 1);
else
@@ -451,7 +453,7 @@ static void update_latch_offset(u8 *offset, int i)
/* Fix inconsistent ab8540 bit mapping... */
if (unlikely(*offset == 16))
*offset = 25;
- if ((i==3) && (*offset >= 24))
+ if ((i == 3) && (*offset >= 24))
*offset += 2;
}
@@ -573,8 +575,8 @@ static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
}
static struct irq_domain_ops ab8500_irq_ops = {
- .map = ab8500_irq_map,
- .xlate = irq_domain_xlate_twocell,
+ .map = ab8500_irq_map,
+ .xlate = irq_domain_xlate_twocell,
};
static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
@@ -607,8 +609,8 @@ int ab8500_suspend(struct ab8500 *ab8500)
{
if (atomic_read(&ab8500->transfer_ongoing))
return -EINVAL;
- else
- return 0;
+
+ return 0;
}
static struct resource ab8500_gpadc_resources[] = {
@@ -1551,7 +1553,7 @@ static struct attribute_group ab9540_attr_group = {
static int ab8500_probe(struct platform_device *pdev)
{
- static char *switch_off_status[] = {
+ static const char *switch_off_status[] = {
"Swoff bit programming",
"Thermal protection activation",
"Vbat lower then BattOk falling threshold",
@@ -1560,7 +1562,7 @@ static int ab8500_probe(struct platform_device *pdev)
"Battery level lower than power on reset threshold",
"Power on key 1 pressed longer than 10 seconds",
"DB8500 thermal shutdown"};
- static char *turn_on_status[] = {
+ static const char *turn_on_status[] = {
"Battery rising (Vbat)",
"Power On Key 1 dbF",
"Power On Key 2 dbF",
@@ -1579,7 +1581,7 @@ static int ab8500_probe(struct platform_device *pdev)
int i;
u8 value;
- ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
+ ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
@@ -1636,7 +1638,7 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->mask_size = AB8540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab8540_irq_regoffset;
ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
- }/* Configure AB8500 or AB9540 IRQ */
+ } /* Configure AB8500 or AB9540 IRQ */
else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
ab8500->mask_size = AB9540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab9540_irq_regoffset;
@@ -1646,10 +1648,12 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->irq_reg_offset = ab8500_irq_regoffset;
ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
}
- ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+ ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+ GFP_KERNEL);
if (!ab8500->mask)
return -ENOMEM;
- ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
+ ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
+ GFP_KERNEL);
if (!ab8500->oldmask)
return -ENOMEM;
@@ -1674,14 +1678,13 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
if (value & 1)
- printk(KERN_CONT " \"%s\"",
- switch_off_status[i]);
+ pr_cont(" \"%s\"", switch_off_status[i]);
value = value >> 1;
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
} else {
- printk(KERN_CONT " None\n");
+ pr_cont(" None\n");
}
ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
AB8500_TURN_ON_STATUS, &value);
@@ -1692,12 +1695,12 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
if (value & 1)
- printk("\"%s\" ", turn_on_status[i]);
+ pr_cont("\"%s\" ", turn_on_status[i]);
value = value >> 1;
}
- printk("\n");
+ pr_cont("\n");
} else {
- printk("None\n");
+ pr_cont("None\n");
}
if (plat && plat->init)
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index d1a22aae2df5..b2c7e3b1edfa 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -135,10 +135,10 @@ struct ab8500_prcmu_ranges {
/* hwreg- "mask" and "shift" entries ressources */
struct hwreg_cfg {
u32 bank; /* target bank */
- u32 addr; /* target address */
+ unsigned long addr; /* target address */
uint fmt; /* format */
- uint mask; /* read/write mask, applied before any bit shift */
- int shift; /* bit shift (read:right shift, write:left shift */
+ unsigned long mask; /* read/write mask, applied before any bit shift */
+ long shift; /* bit shift (read:right shift, write:left shift */
};
/* fmt bit #0: 0=hexa, 1=dec */
#define REG_FMT_DEC(c) ((c)->fmt & 0x1)
@@ -1304,16 +1304,17 @@ static int ab8500_registers_print(struct device *dev, u32 bank,
}
if (s) {
- err = seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
- bank, reg, value);
+ err = seq_printf(s,
+ " [0x%02X/0x%02X]: 0x%02X\n",
+ bank, reg, value);
if (err < 0) {
/* Error is not returned here since
* the output is wanted in any case */
return 0;
}
} else {
- printk(KERN_INFO" [0x%02X/0x%02X]: 0x%02X\n",
- bank, reg, value);
+ dev_info(dev, " [0x%02X/0x%02X]: 0x%02X\n",
+ bank, reg, value);
}
}
}
@@ -1325,7 +1326,7 @@ static int ab8500_print_bank_registers(struct seq_file *s, void *p)
struct device *dev = s->private;
u32 bank = debug_bank;
- seq_printf(s, AB8500_NAME_STRING " register values:\n");
+ seq_puts(s, AB8500_NAME_STRING " register values:\n");
seq_printf(s, " bank 0x%02X:\n", bank);
@@ -1350,12 +1351,11 @@ static int ab8500_print_all_banks(struct seq_file *s, void *p)
{
struct device *dev = s->private;
unsigned int i;
- int err;
- seq_printf(s, AB8500_NAME_STRING " register values:\n");
+ seq_puts(s, AB8500_NAME_STRING " register values:\n");
for (i = 0; i < AB8500_NUM_BANKS; i++) {
- err = seq_printf(s, " bank 0x%02X:\n", i);
+ seq_printf(s, " bank 0x%02X:\n", i);
ab8500_registers_print(dev, i, s);
}
@@ -1367,10 +1367,10 @@ void ab8500_dump_all_banks(struct device *dev)
{
unsigned int i;
- printk(KERN_INFO"ab8500 register values:\n");
+ dev_info(dev, "ab8500 register values:\n");
for (i = 1; i < AB8500_NUM_BANKS; i++) {
- printk(KERN_INFO" bank 0x%02X:\n", i);
+ dev_info(dev, " bank 0x%02X:\n", i);
ab8500_registers_print(dev, i, NULL);
}
}
@@ -1384,8 +1384,6 @@ static struct ab8500_register_dump
u8 value;
} ab8500_complete_register_dump[DUMP_MAX_REGS];
-extern int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-
/* This shall only be called upon kernel panic! */
void ab8500_dump_all_banks_to_mem(void)
{
@@ -1393,8 +1391,7 @@ void ab8500_dump_all_banks_to_mem(void)
u8 bank;
int err = 0;
- pr_info("Saving all ABB registers at \"ab8500_complete_register_dump\" "
- "for crash analyze.\n");
+ pr_info("Saving all ABB registers for crash analysis.\n");
for (bank = 0; bank < AB8500_NUM_BANKS; bank++) {
for (i = 0; i < debug_ranges[bank].num_ranges; i++) {
@@ -1564,7 +1561,7 @@ static ssize_t ab8500_val_write(struct file *file,
err = abx500_set_register_interruptible(dev,
(u8)debug_bank, debug_address, (u8)user_val);
if (err < 0) {
- printk(KERN_ERR "abx500_set_reg failed %d, %d", err, __LINE__);
+ pr_err("abx500_set_reg failed %d, %d", err, __LINE__);
return -EINVAL;
}
@@ -1596,7 +1593,7 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
{
int line;
- seq_printf(s, "name: number: number of: wake:\n");
+ seq_puts(s, "name: number: number of: wake:\n");
for (line = 0; line < num_interrupt_lines; line++) {
struct irq_desc *desc = irq_to_desc(line + irq_first);
@@ -1722,7 +1719,8 @@ static int ab8500_print_modem_registers(struct seq_file *s, void *p)
static int ab8500_modem_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_print_modem_registers, inode->i_private);
+ return single_open(file, ab8500_print_modem_registers,
+ inode->i_private);
}
static const struct file_operations ab8500_modem_fops = {
@@ -1751,7 +1749,8 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_bat_ctrl_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_bat_ctrl_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
@@ -1781,7 +1780,8 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
struct file *file)
{
- return single_open(file, ab8500_gpadc_btemp_ball_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_btemp_ball_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
@@ -1962,7 +1962,8 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
struct file *file)
{
- return single_open(file, ab8500_gpadc_main_bat_v_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_main_bat_v_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
@@ -2082,7 +2083,8 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_bk_bat_v_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_bk_bat_v_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
@@ -2111,7 +2113,8 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab8500_gpadc_die_temp_print, inode->i_private);
+ return single_open(file, ab8500_gpadc_die_temp_print,
+ inode->i_private);
}
static const struct file_operations ab8500_gpadc_die_temp_fops = {
@@ -2190,8 +2193,9 @@ static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS,
avg_sample, trig_edge, trig_timer, conv_type);
- vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
- vbat_true_meas_raw);
+ vbat_true_meas_convert =
+ ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS,
+ vbat_true_meas_raw);
return seq_printf(s, "%d,0x%X\n",
vbat_true_meas_convert, vbat_true_meas_raw);
@@ -2285,7 +2289,8 @@ static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
.owner = THIS_MODULE,
};
-static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
+ void *p)
{
int vbat_true_meas_raw;
int vbat_true_meas_convert;
@@ -2314,7 +2319,8 @@ static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
inode->i_private);
}
-static const struct file_operations ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
+static const struct file_operations
+ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
.open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -2368,14 +2374,15 @@ static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h,
&vbat_l, &vbat_h, &ibat_l, &ibat_h);
return seq_printf(s, "VMAIN_L:0x%X\n"
- "VMAIN_H:0x%X\n"
- "BTEMP_L:0x%X\n"
- "BTEMP_H:0x%X\n"
- "VBAT_L:0x%X\n"
- "VBAT_H:0x%X\n"
- "IBAT_L:0x%X\n"
- "IBAT_H:0x%X\n",
- vmain_l, vmain_h, btemp_l, btemp_h, vbat_l, vbat_h, ibat_l, ibat_h);
+ "VMAIN_H:0x%X\n"
+ "BTEMP_L:0x%X\n"
+ "BTEMP_H:0x%X\n"
+ "VBAT_L:0x%X\n"
+ "VBAT_H:0x%X\n"
+ "IBAT_L:0x%X\n"
+ "IBAT_H:0x%X\n",
+ vmain_l, vmain_h, btemp_l, btemp_h,
+ vbat_l, vbat_h, ibat_l, ibat_h);
}
static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
@@ -2419,8 +2426,8 @@ static ssize_t ab8500_gpadc_avg_sample_write(struct file *file,
|| (user_avg_sample == SAMPLE_16)) {
avg_sample = (u8) user_avg_sample;
} else {
- dev_err(dev, "debugfs error input: "
- "should be egal to 1, 4, 8 or 16\n");
+ dev_err(dev,
+ "debugfs err input: should be egal to 1, 4, 8 or 16\n");
return -EINVAL;
}
@@ -2504,14 +2511,14 @@ static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
if (err)
return err;
- if ((user_trig_timer >= 0) && (user_trig_timer <= 255)) {
- trig_timer = (u8) user_trig_timer;
- } else {
- dev_err(dev, "debugfs error input: "
- "should be beetween 0 to 255\n");
+ if (user_trig_timer & ~0xFF) {
+ dev_err(dev,
+ "debugfs error input: should be beetween 0 to 255\n");
return -EINVAL;
}
+ trig_timer = (u8) user_trig_timer;
+
return count;
}
@@ -2579,6 +2586,7 @@ static const struct file_operations ab8500_gpadc_conv_type_fops = {
static int strval_len(char *b)
{
char *s = b;
+
if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) {
s += 2;
for (; *s && (*s != ' ') && (*s != '\n'); s++) {
@@ -2643,13 +2651,17 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
b += (*(b+2) == ' ') ? 3 : 6;
if (strval_len(b) == 0)
return -EINVAL;
- loc.mask = simple_strtoul(b, &b, 0);
+ ret = kstrtoul(b, 0, &loc.mask);
+ if (ret)
+ return ret;
} else if ((!strncmp(b, "-s ", 3)) ||
(!strncmp(b, "-shift ", 7))) {
b += (*(b+2) == ' ') ? 3 : 7;
if (strval_len(b) == 0)
return -EINVAL;
- loc.shift = simple_strtol(b, &b, 0);
+ ret = kstrtol(b, 0, &loc.shift);
+ if (ret)
+ return ret;
} else {
return -EINVAL;
}
@@ -2657,29 +2669,36 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
/* get arg BANK and ADDRESS */
if (strval_len(b) == 0)
return -EINVAL;
- loc.bank = simple_strtoul(b, &b, 0);
+ ret = kstrtouint(b, 0, &loc.bank);
+ if (ret)
+ return ret;
while (*b == ' ')
b++;
if (strval_len(b) == 0)
return -EINVAL;
- loc.addr = simple_strtoul(b, &b, 0);
+ ret = kstrtoul(b, 0, &loc.addr);
+ if (ret)
+ return ret;
if (write) {
while (*b == ' ')
b++;
if (strval_len(b) == 0)
return -EINVAL;
- val = simple_strtoul(b, &b, 0);
+ ret = kstrtouint(b, 0, &val);
+ if (ret)
+ return ret;
}
/* args are ok, update target cfg (mainly for read) */
*cfg = loc;
#ifdef ABB_HWREG_DEBUG
- pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d"
- "value=0x%X\n", (write) ? "write" : "read",
- REG_FMT_DEC(cfg) ? "decimal" : "hexa",
- cfg->addr, cfg->mask, cfg->shift, val);
+ pr_warn("HWREG request: %s, %s,\n"
+ " addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n",
+ (write) ? "write" : "read",
+ REG_FMT_DEC(cfg) ? "decimal" : "hexa",
+ cfg->addr, cfg->mask, cfg->shift, val);
#endif
if (!write)
@@ -2765,8 +2784,8 @@ static ssize_t show_irq(struct device *dev,
irq_index = name - irq_first;
if (irq_index >= num_irqs)
return -EINVAL;
- else
- return sprintf(buf, "%u\n", irq_count[irq_index]);
+
+ return sprintf(buf, "%u\n", irq_count[irq_index]);
}
static ssize_t ab8500_subscribe_write(struct file *file,
@@ -2815,7 +2834,7 @@ static ssize_t ab8500_subscribe_write(struct file *file,
dev_attr[irq_index]->attr.mode = S_IRUGO;
err = sysfs_create_file(&dev->kobj, &dev_attr[irq_index]->attr);
if (err < 0) {
- printk(KERN_ERR "sysfs_create_file failed %d\n", err);
+ pr_info("sysfs_create_file failed %d\n", err);
return err;
}
@@ -2823,8 +2842,8 @@ static ssize_t ab8500_subscribe_write(struct file *file,
IRQF_SHARED | IRQF_NO_SUSPEND,
"ab8500-debug", &dev->kobj);
if (err < 0) {
- printk(KERN_ERR "request_threaded_irq failed %d, %lu\n",
- err, user_val);
+ pr_info("request_threaded_irq failed %d, %lu\n",
+ err, user_val);
sysfs_remove_file(&dev->kobj, &dev_attr[irq_index]->attr);
return err;
}
@@ -2946,6 +2965,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
struct dentry *file;
struct ab8500 *ab8500;
struct resource *res;
+
debug_bank = AB8500_MISC;
debug_address = AB8500_REV_REG & 0x00FF;
@@ -2958,7 +2978,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
return -ENOMEM;
dev_attr = devm_kzalloc(&plf->dev,
- sizeof(*dev_attr)*num_irqs,GFP_KERNEL);
+ sizeof(*dev_attr)*num_irqs, GFP_KERNEL);
if (!dev_attr)
return -ENOMEM;
@@ -2969,23 +2989,20 @@ static int ab8500_debug_probe(struct platform_device *plf)
res = platform_get_resource_byname(plf, 0, "IRQ_AB8500");
if (!res) {
- dev_err(&plf->dev, "AB8500 irq not found, err %d\n",
- irq_first);
- return ENXIO;
+ dev_err(&plf->dev, "AB8500 irq not found, err %d\n", irq_first);
+ return -ENXIO;
}
irq_ab8500 = res->start;
irq_first = platform_get_irq_byname(plf, "IRQ_FIRST");
if (irq_first < 0) {
- dev_err(&plf->dev, "First irq not found, err %d\n",
- irq_first);
+ dev_err(&plf->dev, "First irq not found, err %d\n", irq_first);
return irq_first;
}
irq_last = platform_get_irq_byname(plf, "IRQ_LAST");
if (irq_last < 0) {
- dev_err(&plf->dev, "Last irq not found, err %d\n",
- irq_last);
+ dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last);
return irq_last;
}
@@ -2994,37 +3011,41 @@ static int ab8500_debug_probe(struct platform_device *plf)
goto err;
ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING,
- ab8500_dir);
+ ab8500_dir);
if (!ab8500_gpadc_dir)
goto err;
- file = debugfs_create_file("all-bank-registers", S_IRUGO,
- ab8500_dir, &plf->dev, &ab8500_registers_fops);
+ file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir,
+ &plf->dev, &ab8500_registers_fops);
if (!file)
goto err;
- file = debugfs_create_file("all-banks", S_IRUGO,
- ab8500_dir, &plf->dev, &ab8500_all_banks_fops);
+ file = debugfs_create_file("all-banks", S_IRUGO, ab8500_dir,
+ &plf->dev, &ab8500_all_banks_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-bank", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_bank_fops);
+ file = debugfs_create_file("register-bank",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_bank_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-address", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_address_fops);
+ file = debugfs_create_file("register-address",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_address_fops);
if (!file)
goto err;
- file = debugfs_create_file("register-value", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_val_fops);
+ file = debugfs_create_file("register-value",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_val_fops);
if (!file)
goto err;
- file = debugfs_create_file("irq-subscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_subscribe_fops);
+ file = debugfs_create_file("irq-subscribe",
+ (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+ &plf->dev, &ab8500_subscribe_fops);
if (!file)
goto err;
@@ -3042,158 +3063,191 @@ static int ab8500_debug_probe(struct platform_device *plf)
num_interrupt_lines = AB8540_NR_IRQS;
}
- file = debugfs_create_file("interrupts", (S_IRUGO),
- ab8500_dir, &plf->dev, &ab8500_interrupts_fops);
+ file = debugfs_create_file("interrupts", (S_IRUGO), ab8500_dir,
+ &plf->dev, &ab8500_interrupts_fops);
if (!file)
goto err;
- file = debugfs_create_file("irq-unsubscribe", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_unsubscribe_fops);
+ file = debugfs_create_file("irq-unsubscribe",
+ (S_IRUGO | S_IWUSR | S_IWGRP), ab8500_dir,
+ &plf->dev, &ab8500_unsubscribe_fops);
if (!file)
goto err;
file = debugfs_create_file("hwreg", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
+ ab8500_dir, &plf->dev, &ab8500_hwreg_fops);
if (!file)
goto err;
- file = debugfs_create_file("all-modem-registers", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_dir, &plf->dev, &ab8500_modem_fops);
+ file = debugfs_create_file("all-modem-registers",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_dir, &plf->dev, &ab8500_modem_fops);
if (!file)
goto err;
file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bat_ctrl_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_bat_ctrl_fops);
if (!file)
goto err;
file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_btemp_ball_fops);
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8500_gpadc_btemp_ball_fops);
if (!file)
goto err;
- file = debugfs_create_file("main_charger_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_v_fops);
+ file = debugfs_create_file("main_charger_v",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_charger_v_fops);
if (!file)
goto err;
- file = debugfs_create_file("acc_detect1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect1_fops);
+ file = debugfs_create_file("acc_detect1",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_acc_detect1_fops);
if (!file)
goto err;
- file = debugfs_create_file("acc_detect2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_acc_detect2_fops);
+ file = debugfs_create_file("acc_detect2",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_acc_detect2_fops);
if (!file)
goto err;
file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux1_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_aux1_fops);
if (!file)
goto err;
file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_aux2_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_aux2_fops);
if (!file)
goto err;
file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_bat_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_bat_v_fops);
if (!file)
goto err;
file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_vbus_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_vbus_v_fops);
if (!file)
goto err;
- file = debugfs_create_file("main_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_main_charger_c_fops);
+ file = debugfs_create_file("main_charger_c",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_main_charger_c_fops);
if (!file)
goto err;
- file = debugfs_create_file("usb_charger_c", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
+ file = debugfs_create_file("usb_charger_c",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8500_gpadc_usb_charger_c_fops);
if (!file)
goto err;
file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_bk_bat_v_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_bk_bat_v_fops);
if (!file)
goto err;
file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_die_temp_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_die_temp_fops);
if (!file)
goto err;
file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_usb_id_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_usb_id_fops);
if (!file)
goto err;
if (is_ab8540(ab8500)) {
- file = debugfs_create_file("xtal_temp", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_xtal_temp_fops);
+ file = debugfs_create_file("xtal_temp",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_xtal_temp_fops);
if (!file)
goto err;
- file = debugfs_create_file("vbattruemeas", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev,
- &ab8540_gpadc_vbat_true_meas_fops);
+ file = debugfs_create_file("vbattruemeas",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_vbat_true_meas_fops);
if (!file)
goto err;
file = debugfs_create_file("batctrl_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev, &ab8540_gpadc_bat_ctrl_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
+ &plf->dev,
+ &ab8540_gpadc_bat_ctrl_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("vbatmeas_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev,
- &ab8540_gpadc_vbat_meas_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8540_gpadc_vbat_meas_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("vbattruemeas_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
- &plf->dev,
- &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
+ &plf->dev,
+ &ab8540_gpadc_vbat_true_meas_and_ibat_fops);
if (!file)
goto err;
file = debugfs_create_file("battemp_and_ibat",
- (S_IRUGO | S_IWUGO), ab8500_gpadc_dir,
+ (S_IRUGO | S_IWUGO),
+ ab8500_gpadc_dir,
&plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops);
if (!file)
goto err;
- file = debugfs_create_file("otp_calib", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8540_gpadc_otp_calib_fops);
+ file = debugfs_create_file("otp_calib",
+ (S_IRUGO | S_IWUSR | S_IWGRP),
+ ab8500_gpadc_dir,
+ &plf->dev, &ab8540_gpadc_otp_calib_fops);
if (!file)
goto err;
}
file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_avg_sample_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_avg_sample_fops);
if (!file)
goto err;
file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_edge_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_trig_edge_fops);
if (!file)
goto err;
file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_trig_timer_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_trig_timer_fops);
if (!file)
goto err;
file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP),
- ab8500_gpadc_dir, &plf->dev, &ab8500_gpadc_conv_type_fops);
+ ab8500_gpadc_dir, &plf->dev,
+ &ab8500_gpadc_conv_type_fops);
if (!file)
goto err;
return 0;
err:
- if (ab8500_dir)
- debugfs_remove_recursive(ab8500_dir);
+ debugfs_remove_recursive(ab8500_dir);
dev_err(&plf->dev, "failed to create debugfs entries.\n");
return -ENOMEM;
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index cfc191abae4a..10a0cb90619a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -123,6 +123,8 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
dev_err(arizona->dev, "AIF2 underclocked\n");
if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
dev_err(arizona->dev, "AIF1 underclocked\n");
+ if (val & ARIZONA_ISRC3_UNDERCLOCKED_STS)
+ dev_err(arizona->dev, "ISRC3 underclocked\n");
if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 underclocked\n");
if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS)
@@ -192,6 +194,8 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
dev_err(arizona->dev, "ASRC sync WARP overclocked\n");
if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS)
dev_err(arizona->dev, "DSP1 overclocked\n");
+ if (val[1] & ARIZONA_ISRC3_OVERCLOCKED_STS)
+ dev_err(arizona->dev, "ISRC3 overclocked\n");
if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 overclocked\n");
if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
@@ -497,12 +501,12 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev)
+unsigned long arizona_of_get_type(struct device *dev)
{
const struct of_device_id *id = of_match_device(arizona_of_match, dev);
if (id)
- return (int)id->data;
+ return (unsigned long)id->data;
else
return 0;
}
@@ -578,17 +582,21 @@ static const struct mfd_cell early_devs[] = {
};
static const char *wm5102_supplies[] = {
+ "MICVDD",
"DBVDD2",
"DBVDD3",
"CPVDD",
"SPKVDDL",
"SPKVDDR",
- "MICVDD",
};
static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm5102_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -601,7 +609,11 @@ static const struct mfd_cell wm5102_devs[] = {
static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm5102_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -613,6 +625,7 @@ static const struct mfd_cell wm5110_devs[] = {
};
static const char *wm8997_supplies[] = {
+ "MICVDD",
"DBVDD2",
"CPVDD",
"SPKVDD",
@@ -620,7 +633,11 @@ static const char *wm8997_supplies[] = {
static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
- { .name = "arizona-extcon" },
+ {
+ .name = "arizona-extcon",
+ .parent_supplies = wm8997_supplies,
+ .num_parent_supplies = 1, /* We only need MICVDD */
+ },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
@@ -683,7 +700,13 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early;
}
- arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
+ /**
+ * Don't use devres here because the only device we have to get
+ * against is the MFD device and DCVDD will likely be supplied by
+ * one of its children. Meaning that the regulator will be
+ * destroyed by the time devres calls regulator put.
+ */
+ arizona->dcvdd = regulator_get(arizona->dev, "DCVDD");
if (IS_ERR(arizona->dcvdd)) {
ret = PTR_ERR(arizona->dcvdd);
dev_err(dev, "Failed to request DCVDD: %d\n", ret);
@@ -697,7 +720,7 @@ int arizona_dev_init(struct arizona *arizona)
"arizona /RESET");
if (ret != 0) {
dev_err(dev, "Failed to request /RESET: %d\n", ret);
- goto err_early;
+ goto err_dcvdd;
}
}
@@ -706,7 +729,7 @@ int arizona_dev_init(struct arizona *arizona)
if (ret != 0) {
dev_err(dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_early;
+ goto err_dcvdd;
}
ret = regulator_enable(arizona->dcvdd);
@@ -1015,6 +1038,8 @@ err_reset:
err_enable:
regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
+err_dcvdd:
+ regulator_put(arizona->dcvdd);
err_early:
mfd_remove_devices(dev);
return ret;
@@ -1023,16 +1048,20 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
int arizona_dev_exit(struct arizona *arizona)
{
+ pm_runtime_disable(arizona->dev);
+
+ regulator_disable(arizona->dcvdd);
+ regulator_put(arizona->dcvdd);
+
mfd_remove_devices(arizona->dev);
arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
- pm_runtime_disable(arizona->dev);
arizona_irq_exit(arizona);
if (arizona->pdata.reset)
gpio_set_value_cansleep(arizona->pdata.reset, 0);
- regulator_disable(arizona->dcvdd);
- regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies),
+
+ regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
return 0;
}
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index beccb790c9ba..9d4156fb082a 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -24,11 +24,12 @@
#include "arizona.h"
static int arizona_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct arizona *arizona;
const struct regmap_config *regmap_config;
- int ret, type;
+ unsigned long type;
+ int ret;
if (i2c->dev.of_node)
type = arizona_of_get_type(&i2c->dev);
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 17102f589100..d420dbc0e2b0 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -188,24 +188,33 @@ int arizona_irq_init(struct arizona *arizona)
int flags = IRQF_ONESHOT;
int ret, i;
const struct regmap_irq_chip *aod, *irq;
- bool ctrlif_error = true;
struct irq_data *irq_data;
+ arizona->ctrlif_error = true;
+
switch (arizona->type) {
#ifdef CONFIG_MFD_WM5102
case WM5102:
aod = &wm5102_aod;
irq = &wm5102_irq;
- ctrlif_error = false;
+ arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
aod = &wm5110_aod;
- irq = &wm5110_irq;
- ctrlif_error = false;
+ switch (arizona->rev) {
+ case 0 ... 2:
+ irq = &wm5110_irq;
+ break;
+ default:
+ irq = &wm5110_revd_irq;
+ break;
+ }
+
+ arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM8997
@@ -213,7 +222,7 @@ int arizona_irq_init(struct arizona *arizona)
aod = &wm8997_aod;
irq = &wm8997_irq;
- ctrlif_error = false;
+ arizona->ctrlif_error = false;
break;
#endif
default:
@@ -300,7 +309,7 @@ int arizona_irq_init(struct arizona *arizona)
}
/* Handle control interface errors in the core */
- if (ctrlif_error) {
+ if (arizona->ctrlif_error) {
i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
IRQF_ONESHOT,
@@ -345,7 +354,9 @@ int arizona_irq_init(struct arizona *arizona)
return 0;
err_main_irq:
- free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+ if (arizona->ctrlif_error)
+ free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
+ arizona);
err_ctrlif:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
err_boot_done:
@@ -361,7 +372,9 @@ err:
int arizona_irq_exit(struct arizona *arizona)
{
- free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
+ if (arizona->ctrlif_error)
+ free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
+ arizona);
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
arizona->irq_chip);
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index 1ca554b18bef..5145d78bf07e 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -28,7 +28,8 @@ static int arizona_spi_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona;
const struct regmap_config *regmap_config;
- int ret, type;
+ unsigned long type;
+ int ret;
if (spi->dev.of_node)
type = arizona_of_get_type(&spi->dev);
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
index b4cef777df73..fbe2843271c5 100644
--- a/drivers/mfd/arizona.h
+++ b/drivers/mfd/arizona.h
@@ -36,6 +36,7 @@ extern const struct regmap_irq_chip wm5102_irq;
extern const struct regmap_irq_chip wm5110_aod;
extern const struct regmap_irq_chip wm5110_irq;
+extern const struct regmap_irq_chip wm5110_revd_irq;
extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq;
@@ -46,9 +47,9 @@ int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
#ifdef CONFIG_OF
-int arizona_of_get_type(struct device *dev);
+unsigned long arizona_of_get_type(struct device *dev);
#else
-static inline int arizona_of_get_type(struct device *dev)
+static inline unsigned long arizona_of_get_type(struct device *dev)
{
return 0;
}
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 9f6294f2a070..9fc4186d4132 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -899,13 +899,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].end >>= asic->bus_shift;
/* MMC */
- asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
+ if (mem_sdio) {
+ asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start,
ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
- if (!asic->tmio_cnf) {
- ret = -ENOMEM;
- dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
- goto out;
+ if (!asic->tmio_cnf) {
+ ret = -ENOMEM;
+ dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
+ goto out;
+ }
}
asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift;
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 38fe9bf0d169..4873f9c50452 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -25,64 +25,42 @@
#include <linux/mfd/cros_ec_commands.h>
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+ struct cros_ec_command *msg)
{
uint8_t *out;
int csum, i;
- BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
+ BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
out = ec_dev->dout;
out[0] = EC_CMD_VERSION0 + msg->version;
- out[1] = msg->cmd;
- out[2] = msg->out_len;
+ out[1] = msg->command;
+ out[2] = msg->outsize;
csum = out[0] + out[1] + out[2];
- for (i = 0; i < msg->out_len; i++)
- csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
- out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
+ for (i = 0; i < msg->outsize; i++)
+ csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
+ out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
- return EC_MSG_TX_PROTO_BYTES + msg->out_len;
+ return EC_MSG_TX_PROTO_BYTES + msg->outsize;
}
EXPORT_SYMBOL(cros_ec_prepare_tx);
-static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *out_buf, int out_len,
- void *in_buf, int in_len)
+int cros_ec_check_result(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
{
- struct cros_ec_msg msg;
-
- msg.version = cmd >> 8;
- msg.cmd = cmd & 0xff;
- msg.out_buf = out_buf;
- msg.out_len = out_len;
- msg.in_buf = in_buf;
- msg.in_len = in_len;
-
- return ec_dev->command_xfer(ec_dev, &msg);
-}
-
-static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
-}
-
-static int cros_ec_command_send(struct cros_ec_device *ec_dev,
- uint16_t cmd, void *buf, int buf_len)
-{
- return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
-}
-
-static irqreturn_t ec_irq_thread(int irq, void *data)
-{
- struct cros_ec_device *ec_dev = data;
-
- if (device_may_wakeup(ec_dev->dev))
- pm_wakeup_event(ec_dev->dev, 0);
-
- blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
-
- return IRQ_HANDLED;
+ switch (msg->result) {
+ case EC_RES_SUCCESS:
+ return 0;
+ case EC_RES_IN_PROGRESS:
+ dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
+ msg->command);
+ return -EAGAIN;
+ default:
+ dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
+ msg->command, msg->result);
+ return 0;
+ }
}
+EXPORT_SYMBOL(cros_ec_check_result);
static const struct mfd_cell cros_devs[] = {
{
@@ -102,12 +80,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
struct device *dev = ec_dev->dev;
int err = 0;
- BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
-
- ec_dev->command_send = cros_ec_command_send;
- ec_dev->command_recv = cros_ec_command_recv;
- ec_dev->command_sendrecv = cros_ec_command_sendrecv;
-
if (ec_dev->din_size) {
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
@@ -119,42 +91,23 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return -ENOMEM;
}
- if (!ec_dev->irq) {
- dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
- return err;
- }
-
- err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "chromeos-ec", ec_dev);
- if (err) {
- dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
- return err;
- }
-
err = mfd_add_devices(dev, 0, cros_devs,
ARRAY_SIZE(cros_devs),
NULL, ec_dev->irq, NULL);
if (err) {
dev_err(dev, "failed to add mfd devices\n");
- goto fail_mfd;
+ return err;
}
- dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
+ dev_info(dev, "Chrome EC device registered\n");
return 0;
-
-fail_mfd:
- free_irq(ec_dev->irq, ec_dev);
-
- return err;
}
EXPORT_SYMBOL(cros_ec_register);
int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
- free_irq(ec_dev->irq, ec_dev);
return 0;
}
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 4f71be99a183..c0c30f4f946f 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -29,12 +29,13 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
return i2c_get_clientdata(client);
}
-static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *msg)
+static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
{
struct i2c_client *client = ec_dev->priv;
int ret = -ENOMEM;
int i;
+ int len;
int packet_len;
u8 *out_buf = NULL;
u8 *in_buf = NULL;
@@ -50,7 +51,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one byte for
* length, and one for result code)
*/
- packet_len = msg->in_len + 3;
+ packet_len = msg->insize + 3;
in_buf = kzalloc(packet_len, GFP_KERNEL);
if (!in_buf)
goto done;
@@ -61,7 +62,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one for
* command code, one for length, and one for command version)
*/
- packet_len = msg->out_len + 4;
+ packet_len = msg->outsize + 4;
out_buf = kzalloc(packet_len, GFP_KERNEL);
if (!out_buf)
goto done;
@@ -69,16 +70,16 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
i2c_msg[0].buf = (char *)out_buf;
out_buf[0] = EC_CMD_VERSION0 + msg->version;
- out_buf[1] = msg->cmd;
- out_buf[2] = msg->out_len;
+ out_buf[1] = msg->command;
+ out_buf[2] = msg->outsize;
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2];
- for (i = 0; i < msg->out_len; i++) {
- out_buf[3 + i] = msg->out_buf[i];
+ for (i = 0; i < msg->outsize; i++) {
+ out_buf[3 + i] = msg->outdata[i];
sum += out_buf[3 + i];
}
- out_buf[3 + msg->out_len] = sum;
+ out_buf[3 + msg->outsize] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2);
@@ -92,28 +93,34 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
}
/* check response error code */
- if (i2c_msg[1].buf[0]) {
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- msg->cmd, i2c_msg[1].buf[0]);
- ret = -EINVAL;
+ msg->result = i2c_msg[1].buf[0];
+ ret = cros_ec_check_result(ec_dev, msg);
+ if (ret)
+ goto done;
+
+ len = in_buf[1];
+ if (len > msg->insize) {
+ dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
+ len, msg->insize);
+ ret = -ENOSPC;
goto done;
}
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1];
- for (i = 0; i < msg->in_len; i++) {
- msg->in_buf[i] = in_buf[2 + i];
+ for (i = 0; i < len; i++) {
+ msg->indata[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
i2c_msg[1].len, in_buf, sum);
- if (sum != in_buf[2 + msg->in_len]) {
+ if (sum != in_buf[2 + len]) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG;
goto done;
}
- ret = 0;
+ ret = len;
done:
kfree(in_buf);
kfree(out_buf);
@@ -132,11 +139,10 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, ec_dev);
- ec_dev->name = "I2C";
ec_dev->dev = dev;
ec_dev->priv = client;
ec_dev->irq = client->irq;
- ec_dev->command_xfer = cros_ec_command_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
ec_dev->ec_name = client->name;
ec_dev->phys_name = client->adapter->name;
ec_dev->parent = &client->dev;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 0b8d32829166..588c700af39c 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -73,7 +73,7 @@
* if no record
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn off CS at the end of a transaction.
- * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
+ * @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
*/
struct cros_ec_spi {
struct spi_device *spi;
@@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
}
/**
- * cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
+ * cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
*
* @ec_dev: ChromeOS EC device
* @ec_msg: Message to transfer
*/
-static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
- struct cros_ec_msg *ec_msg)
+static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)
{
struct cros_ec_spi *ec_spi = ec_dev->priv;
struct spi_transfer trans;
@@ -225,7 +225,6 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
u8 *ptr;
int sum;
int ret = 0, final_ret;
- struct timespec ts;
/*
* We have the shared ec_dev buffer plus we do lots of separate spi_sync
@@ -239,11 +238,9 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* If it's too soon to do another transaction, wait */
if (ec_spi->last_transfer_ns) {
- struct timespec ts;
unsigned long delay; /* The delay completed so far */
- ktime_get_ts(&ts);
- delay = timespec_to_ns(&ts) - ec_spi->last_transfer_ns;
+ delay = ktime_get_ns() - ec_spi->last_transfer_ns;
if (delay < EC_SPI_RECOVERY_TIME_NS)
ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
}
@@ -261,27 +258,22 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* Get the response */
if (!ret) {
ret = cros_ec_spi_receive_response(ec_dev,
- ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
+ ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
} else {
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
}
- /* turn off CS */
+ /*
+ * Turn off CS, possibly adding a delay to ensure the rising edge
+ * doesn't come too soon after the end of the data.
+ */
spi_message_init(&msg);
-
- if (ec_spi->end_of_msg_delay) {
- /*
- * Add delay for last transaction, to ensure the rising edge
- * doesn't come too soon after the end of the data.
- */
- memset(&trans, 0, sizeof(trans));
- trans.delay_usecs = ec_spi->end_of_msg_delay;
- spi_message_add_tail(&trans, &msg);
- }
+ memset(&trans, 0, sizeof(trans));
+ trans.delay_usecs = ec_spi->end_of_msg_delay;
+ spi_message_add_tail(&trans, &msg);
final_ret = spi_sync(ec_spi->spi, &msg);
- ktime_get_ts(&ts);
- ec_spi->last_transfer_ns = timespec_to_ns(&ts);
+ ec_spi->last_transfer_ns = ktime_get_ns();
if (!ret)
ret = final_ret;
if (ret < 0) {
@@ -289,20 +281,19 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
- /* check response error code */
ptr = ec_dev->din;
- if (ptr[0]) {
- dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
- ec_msg->cmd, ptr[0]);
- debug_packet(ec_dev->dev, "in_err", ptr, len);
- ret = -EINVAL;
+
+ /* check response error code */
+ ec_msg->result = ptr[0];
+ ret = cros_ec_check_result(ec_dev, ec_msg);
+ if (ret)
goto exit;
- }
+
len = ptr[1];
sum = ptr[0] + ptr[1];
- if (len > ec_msg->in_len) {
+ if (len > ec_msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
- len, ec_msg->in_len);
+ len, ec_msg->insize);
ret = -ENOSPC;
goto exit;
}
@@ -310,8 +301,8 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* copy response packet payload and compute checksum */
for (i = 0; i < len; i++) {
sum += ptr[i + 2];
- if (ec_msg->in_len)
- ec_msg->in_buf[i] = ptr[i + 2];
+ if (ec_msg->insize)
+ ec_msg->indata[i] = ptr[i + 2];
}
sum &= 0xff;
@@ -325,7 +316,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
- ret = 0;
+ ret = len;
exit:
mutex_unlock(&ec_spi->lock);
return ret;
@@ -368,11 +359,10 @@ static int cros_ec_spi_probe(struct spi_device *spi)
cros_ec_spi_dt_probe(ec_spi, dev);
spi_set_drvdata(spi, ec_dev);
- ec_dev->name = "SPI";
ec_dev->dev = dev;
ec_dev->priv = ec_spi;
ec_dev->irq = spi->irq;
- ec_dev->command_xfer = cros_ec_command_spi_xfer;
+ ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
ec_dev->ec_name = ec_spi->spi->modalias;
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
ec_dev->parent = &ec_spi->spi->dev;
@@ -385,6 +375,8 @@ static int cros_ec_spi_probe(struct spi_device *spi)
return err;
}
+ device_init_wakeup(&spi->dev, true);
+
return 0;
}
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
index e70ae315abc7..93db8bb8c8f0 100644
--- a/drivers/mfd/da9063-core.c
+++ b/drivers/mfd/da9063-core.c
@@ -153,9 +153,9 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
model, variant_id);
- if (variant_code != PMIC_DA9063_BB) {
- dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
- variant_code);
+ if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
+ dev_err(da9063->dev,
+ "Cannot support variant code: 0x%02X\n", variant_code);
return -ENODEV;
}
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c
index 8db5c805c64f..21fd8d9a217b 100644
--- a/drivers/mfd/da9063-i2c.c
+++ b/drivers/mfd/da9063-i2c.c
@@ -25,10 +25,10 @@
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
-static const struct regmap_range da9063_readable_ranges[] = {
+static const struct regmap_range da9063_ad_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_SECOND_D,
+ .range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
@@ -37,14 +37,14 @@ static const struct regmap_range da9063_readable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
- .range_max = DA9063_REG_GP_ID_19,
+ .range_max = DA9063_AD_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};
-static const struct regmap_range da9063_writeable_ranges[] = {
+static const struct regmap_range da9063_ad_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
@@ -53,7 +53,7 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
- .range_max = DA9063_REG_ALARM_Y,
+ .range_max = DA9063_AD_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
@@ -62,14 +62,14 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
- .range_max = DA9063_REG_MON_REG_4,
+ .range_max = DA9063_AD_REG_MON_REG_4,
}, {
- .range_min = DA9063_REG_GP_ID_0,
- .range_max = DA9063_REG_GP_ID_19,
+ .range_min = DA9063_AD_REG_GP_ID_0,
+ .range_max = DA9063_AD_REG_GP_ID_19,
},
};
-static const struct regmap_range da9063_volatile_ranges[] = {
+static const struct regmap_range da9063_ad_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
@@ -81,26 +81,104 @@ static const struct regmap_range da9063_volatile_ranges[] = {
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
- .range_max = DA9063_REG_SECOND_D,
+ .range_max = DA9063_AD_REG_SECOND_D,
}, {
- .range_min = DA9063_REG_MON_REG_5,
- .range_max = DA9063_REG_MON_REG_6,
+ .range_min = DA9063_AD_REG_MON_REG_5,
+ .range_max = DA9063_AD_REG_MON_REG_6,
},
};
-static const struct regmap_access_table da9063_readable_table = {
- .yes_ranges = da9063_readable_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
+static const struct regmap_access_table da9063_ad_readable_table = {
+ .yes_ranges = da9063_ad_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
};
-static const struct regmap_access_table da9063_writeable_table = {
- .yes_ranges = da9063_writeable_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
+static const struct regmap_access_table da9063_ad_writeable_table = {
+ .yes_ranges = da9063_ad_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
};
-static const struct regmap_access_table da9063_volatile_table = {
- .yes_ranges = da9063_volatile_ranges,
- .n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
+static const struct regmap_access_table da9063_ad_volatile_table = {
+ .yes_ranges = da9063_ad_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
+};
+
+static const struct regmap_range da9063_bb_readable_ranges[] = {
+ {
+ .range_min = DA9063_REG_PAGE_CON,
+ .range_max = DA9063_BB_REG_SECOND_D,
+ }, {
+ .range_min = DA9063_REG_SEQ,
+ .range_max = DA9063_REG_ID_32_31,
+ }, {
+ .range_min = DA9063_REG_SEQ_A,
+ .range_max = DA9063_REG_AUTO3_LOW,
+ }, {
+ .range_min = DA9063_REG_T_OFFSET,
+ .range_max = DA9063_BB_REG_GP_ID_19,
+ }, {
+ .range_min = DA9063_REG_CHIP_ID,
+ .range_max = DA9063_REG_CHIP_VARIANT,
+ },
+};
+
+static const struct regmap_range da9063_bb_writeable_ranges[] = {
+ {
+ .range_min = DA9063_REG_PAGE_CON,
+ .range_max = DA9063_REG_PAGE_CON,
+ }, {
+ .range_min = DA9063_REG_FAULT_LOG,
+ .range_max = DA9063_REG_VSYS_MON,
+ }, {
+ .range_min = DA9063_REG_COUNT_S,
+ .range_max = DA9063_BB_REG_ALARM_Y,
+ }, {
+ .range_min = DA9063_REG_SEQ,
+ .range_max = DA9063_REG_ID_32_31,
+ }, {
+ .range_min = DA9063_REG_SEQ_A,
+ .range_max = DA9063_REG_AUTO3_LOW,
+ }, {
+ .range_min = DA9063_REG_CONFIG_I,
+ .range_max = DA9063_BB_REG_MON_REG_4,
+ }, {
+ .range_min = DA9063_BB_REG_GP_ID_0,
+ .range_max = DA9063_BB_REG_GP_ID_19,
+ },
+};
+
+static const struct regmap_range da9063_bb_volatile_ranges[] = {
+ {
+ .range_min = DA9063_REG_STATUS_A,
+ .range_max = DA9063_REG_EVENT_D,
+ }, {
+ .range_min = DA9063_REG_CONTROL_F,
+ .range_max = DA9063_REG_CONTROL_F,
+ }, {
+ .range_min = DA9063_REG_ADC_MAN,
+ .range_max = DA9063_REG_ADC_MAN,
+ }, {
+ .range_min = DA9063_REG_ADC_RES_L,
+ .range_max = DA9063_BB_REG_SECOND_D,
+ }, {
+ .range_min = DA9063_BB_REG_MON_REG_5,
+ .range_max = DA9063_BB_REG_MON_REG_6,
+ },
+};
+
+static const struct regmap_access_table da9063_bb_readable_table = {
+ .yes_ranges = da9063_bb_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_writeable_table = {
+ .yes_ranges = da9063_bb_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
+};
+
+static const struct regmap_access_table da9063_bb_volatile_table = {
+ .yes_ranges = da9063_bb_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
};
static const struct regmap_range_cfg da9063_range_cfg[] = {
@@ -123,10 +201,6 @@ static struct regmap_config da9063_regmap_config = {
.max_register = DA9063_REG_CHIP_VARIANT,
.cache_type = REGCACHE_RBTREE,
-
- .rd_table = &da9063_readable_table,
- .wr_table = &da9063_writeable_table,
- .volatile_table = &da9063_volatile_table,
};
static int da9063_i2c_probe(struct i2c_client *i2c,
@@ -143,6 +217,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
da9063->dev = &i2c->dev;
da9063->chip_irq = i2c->irq;
+ if (da9063->variant_code == PMIC_DA9063_AD) {
+ da9063_regmap_config.rd_table = &da9063_ad_readable_table;
+ da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
+ da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
+ } else {
+ da9063_regmap_config.rd_table = &da9063_bb_readable_table;
+ da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
+ da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
+ }
+
da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
if (IS_ERR(da9063->regmap)) {
ret = PTR_ERR(da9063->regmap);
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 7a55c0071fa8..4c826f78acd0 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(dm355evm_msp_read);
* Many of the msp430 pins are just used as fixed-direction GPIOs.
* We could export a few more of them this way, if we wanted.
*/
-#define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
+#define MSP_GPIO(bit, reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
static const u8 msp_gpios[] = {
/* eight leds */
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 2ed774e7d342..5991faddd3c6 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -62,7 +62,7 @@ static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data)
struct spi_message m;
int status;
- memset(&t, 0, sizeof t);
+ memset(&t, 0, sizeof(t));
spi_message_init(&m);
t.len = sizeof(u32);
spi_message_add_tail(&t, &m);
@@ -211,7 +211,6 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
desc->irq_data.chip->irq_ack(&desc->irq_data);
queue_work(pcap->workqueue, &pcap->isr_work);
- return;
}
/* ADC */
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index d7b2a75aca3e..b44f0203983b 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -332,18 +332,13 @@ static int htcpld_setup_chip_irq(
int chip_index)
{
struct htcpld_data *htcpld;
- struct device *dev = &pdev->dev;
- struct htcpld_core_platform_data *pdata;
struct htcpld_chip *chip;
- struct htcpld_chip_platform_data *plat_chip_data;
unsigned int irq, irq_end;
int ret = 0;
/* Get the platform and driver data */
- pdata = dev_get_platdata(dev);
htcpld = platform_get_drvdata(pdev);
chip = &htcpld->chip[chip_index];
- plat_chip_data = &pdata->chip[chip_index];
/* Setup irq handlers */
irq_end = chip->irq_start + chip->nirqs;
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 049fd23af54a..443e7cddff28 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -27,7 +27,7 @@
/*
* MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
- * Since IRQ block starts from address 0x002 we need to substract that from
+ * Since IRQ block starts from address 0x002 we need to subtract that from
* the actual IRQ status register address.
*/
#define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
new file mode 100644
index 000000000000..2720922f90b4
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -0,0 +1,170 @@
+/*
+ * intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as 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.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+/*
+ * On some boards the PMIC interrupt may come from a GPIO line.
+ * Try to lookup the ACPI table and see if such connection exists. If not,
+ * return -ENOENT and use the IRQ provided by I2C.
+ */
+static int intel_soc_pmic_find_gpio_irq(struct device *dev)
+{
+ struct gpio_desc *desc;
+ int irq;
+
+ desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
+ if (IS_ERR(desc))
+ return -ENOENT;
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0)
+ dev_warn(dev, "Can't get irq: %d\n", irq);
+
+ return irq;
+}
+
+static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *i2c_id)
+{
+ struct device *dev = &i2c->dev;
+ const struct acpi_device_id *id;
+ struct intel_soc_pmic_config *config;
+ struct intel_soc_pmic *pmic;
+ int ret;
+ int irq;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id || !id->driver_data)
+ return -ENODEV;
+
+ config = (struct intel_soc_pmic_config *)id->driver_data;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ dev_set_drvdata(dev, pmic);
+
+ pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
+
+ irq = intel_soc_pmic_find_gpio_irq(dev);
+ pmic->irq = (irq < 0) ? i2c->irq : irq;
+
+ ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+ config->irq_flags | IRQF_ONESHOT,
+ 0, config->irq_chip,
+ &pmic->irq_chip_data);
+ if (ret)
+ return ret;
+
+ ret = enable_irq_wake(pmic->irq);
+ if (ret)
+ dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
+
+ ret = mfd_add_devices(dev, -1, config->cell_dev,
+ config->n_cell_devs, NULL, 0,
+ regmap_irq_get_domain(pmic->irq_chip_data));
+ if (ret)
+ goto err_del_irq_chip;
+
+ return 0;
+
+err_del_irq_chip:
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+ return ret;
+}
+
+static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+ regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
+
+ mfd_remove_devices(&i2c->dev);
+
+ return 0;
+}
+
+static void intel_soc_pmic_shutdown(struct i2c_client *i2c)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
+
+ disable_irq(pmic->irq);
+
+ return;
+}
+
+static int intel_soc_pmic_suspend(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ disable_irq(pmic->irq);
+
+ return 0;
+}
+
+static int intel_soc_pmic_resume(struct device *dev)
+{
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+ enable_irq(pmic->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
+ intel_soc_pmic_resume);
+
+static const struct i2c_device_id intel_soc_pmic_i2c_id[] = {
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
+
+#if defined(CONFIG_ACPI)
+static struct acpi_device_id intel_soc_pmic_acpi_match[] = {
+ {"INT33FD", (kernel_ulong_t)&intel_soc_pmic_config_crc},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
+#endif
+
+static struct i2c_driver intel_soc_pmic_i2c_driver = {
+ .driver = {
+ .name = "intel_soc_pmic_i2c",
+ .owner = THIS_MODULE,
+ .pm = &intel_soc_pmic_pm_ops,
+ .acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match),
+ },
+ .probe = intel_soc_pmic_i2c_probe,
+ .remove = intel_soc_pmic_i2c_remove,
+ .id_table = intel_soc_pmic_i2c_id,
+ .shutdown = intel_soc_pmic_shutdown,
+};
+
+module_i2c_driver(intel_soc_pmic_i2c_driver);
+
+MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
+MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
diff --git a/drivers/mfd/intel_soc_pmic_core.h b/drivers/mfd/intel_soc_pmic_core.h
new file mode 100644
index 000000000000..33aacd9baddc
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_core.h
@@ -0,0 +1,32 @@
+/*
+ * intel_soc_pmic_core.h - Intel SoC PMIC MFD Driver
+ *
+ * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as 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.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#ifndef __INTEL_SOC_PMIC_CORE_H__
+#define __INTEL_SOC_PMIC_CORE_H__
+
+struct intel_soc_pmic_config {
+ unsigned long irq_flags;
+ struct mfd_cell *cell_dev;
+ int n_cell_devs;
+ struct regmap_config *regmap_config;
+ struct regmap_irq_chip *irq_chip;
+};
+
+extern struct intel_soc_pmic_config intel_soc_pmic_config_crc;
+
+#endif /* __INTEL_SOC_PMIC_CORE_H__ */
diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c
new file mode 100644
index 000000000000..7107cab832e6
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_crc.c
@@ -0,0 +1,158 @@
+/*
+ * intel_soc_pmic_crc.c - Device access for Crystal Cove PMIC
+ *
+ * Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as 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.
+ *
+ * Author: Yang, Bin <bin.yang@intel.com>
+ * Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include "intel_soc_pmic_core.h"
+
+#define CRYSTAL_COVE_MAX_REGISTER 0xC6
+
+#define CRYSTAL_COVE_REG_IRQLVL1 0x02
+#define CRYSTAL_COVE_REG_MIRQLVL1 0x0E
+
+#define CRYSTAL_COVE_IRQ_PWRSRC 0
+#define CRYSTAL_COVE_IRQ_THRM 1
+#define CRYSTAL_COVE_IRQ_BCU 2
+#define CRYSTAL_COVE_IRQ_ADC 3
+#define CRYSTAL_COVE_IRQ_CHGR 4
+#define CRYSTAL_COVE_IRQ_GPIO 5
+#define CRYSTAL_COVE_IRQ_VHDMIOCP 6
+
+static struct resource gpio_resources[] = {
+ {
+ .name = "GPIO",
+ .start = CRYSTAL_COVE_IRQ_GPIO,
+ .end = CRYSTAL_COVE_IRQ_GPIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource pwrsrc_resources[] = {
+ {
+ .name = "PWRSRC",
+ .start = CRYSTAL_COVE_IRQ_PWRSRC,
+ .end = CRYSTAL_COVE_IRQ_PWRSRC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource adc_resources[] = {
+ {
+ .name = "ADC",
+ .start = CRYSTAL_COVE_IRQ_ADC,
+ .end = CRYSTAL_COVE_IRQ_ADC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource thermal_resources[] = {
+ {
+ .name = "THERMAL",
+ .start = CRYSTAL_COVE_IRQ_THRM,
+ .end = CRYSTAL_COVE_IRQ_THRM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource bcu_resources[] = {
+ {
+ .name = "BCU",
+ .start = CRYSTAL_COVE_IRQ_BCU,
+ .end = CRYSTAL_COVE_IRQ_BCU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell crystal_cove_dev[] = {
+ {
+ .name = "crystal_cove_pwrsrc",
+ .num_resources = ARRAY_SIZE(pwrsrc_resources),
+ .resources = pwrsrc_resources,
+ },
+ {
+ .name = "crystal_cove_adc",
+ .num_resources = ARRAY_SIZE(adc_resources),
+ .resources = adc_resources,
+ },
+ {
+ .name = "crystal_cove_thermal",
+ .num_resources = ARRAY_SIZE(thermal_resources),
+ .resources = thermal_resources,
+ },
+ {
+ .name = "crystal_cove_bcu",
+ .num_resources = ARRAY_SIZE(bcu_resources),
+ .resources = bcu_resources,
+ },
+ {
+ .name = "crystal_cove_gpio",
+ .num_resources = ARRAY_SIZE(gpio_resources),
+ .resources = gpio_resources,
+ },
+};
+
+static struct regmap_config crystal_cove_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CRYSTAL_COVE_MAX_REGISTER,
+ .cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_irq crystal_cove_irqs[] = {
+ [CRYSTAL_COVE_IRQ_PWRSRC] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_PWRSRC),
+ },
+ [CRYSTAL_COVE_IRQ_THRM] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_THRM),
+ },
+ [CRYSTAL_COVE_IRQ_BCU] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_BCU),
+ },
+ [CRYSTAL_COVE_IRQ_ADC] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_ADC),
+ },
+ [CRYSTAL_COVE_IRQ_CHGR] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_CHGR),
+ },
+ [CRYSTAL_COVE_IRQ_GPIO] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_GPIO),
+ },
+ [CRYSTAL_COVE_IRQ_VHDMIOCP] = {
+ .mask = BIT(CRYSTAL_COVE_IRQ_VHDMIOCP),
+ },
+};
+
+static struct regmap_irq_chip crystal_cove_irq_chip = {
+ .name = "Crystal Cove",
+ .irqs = crystal_cove_irqs,
+ .num_irqs = ARRAY_SIZE(crystal_cove_irqs),
+ .num_regs = 1,
+ .status_base = CRYSTAL_COVE_REG_IRQLVL1,
+ .mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
+};
+
+struct intel_soc_pmic_config intel_soc_pmic_config_crc = {
+ .irq_flags = IRQF_TRIGGER_RISING,
+ .cell_dev = crystal_cove_dev,
+ .n_cell_devs = ARRAY_SIZE(crystal_cove_dev),
+ .regmap_config = &crystal_cove_regmap_config,
+ .irq_chip = &crystal_cove_irq_chip,
+};
diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c
index 7e50fe0118e3..8df3266064e4 100644
--- a/drivers/mfd/ipaq-micro.c
+++ b/drivers/mfd/ipaq-micro.c
@@ -115,7 +115,7 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
} else {
dev_err(micro->dev,
"out of band RX message 0x%02x\n", id);
- if(!micro->msg)
+ if (!micro->msg)
dev_info(micro->dev, "no message queued\n");
else
dev_info(micro->dev, "expected message %02x\n",
@@ -126,13 +126,13 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
if (micro->key)
micro->key(micro->key_data, len, data);
else
- dev_dbg(micro->dev, "key message ignored, no handle \n");
+ dev_dbg(micro->dev, "key message ignored, no handle\n");
break;
case MSG_TOUCHSCREEN:
if (micro->ts)
micro->ts(micro->ts_data, len, data);
else
- dev_dbg(micro->dev, "touchscreen message ignored, no handle \n");
+ dev_dbg(micro->dev, "touchscreen message ignored, no handle\n");
break;
default:
dev_err(micro->dev,
@@ -154,7 +154,7 @@ static void micro_process_char(struct ipaq_micro *micro, u8 ch)
rx->state = STATE_ID; /* Next byte is the id and len */
break;
case STATE_ID: /* Looking for id and len byte */
- rx->id = (ch & 0xf0) >> 4 ;
+ rx->id = (ch & 0xf0) >> 4;
rx->len = (ch & 0x0f);
rx->index = 0;
rx->chksum = ch;
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index f7ff0188603d..bd2696136eee 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -24,7 +24,8 @@
#define MAX_ID_LEN 4
static char force_device_id[MAX_ID_LEN + 1] = "";
-module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
+module_param_string(force_device_id, force_device_id,
+ sizeof(force_device_id), 0);
MODULE_PARM_DESC(force_device_id, "Override detected product");
/*
@@ -36,7 +37,7 @@ static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
{
/* The mutex bit will read 1 until access has been granted */
while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
- msleep(1);
+ usleep_range(1000, 3000);
}
static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
@@ -499,7 +500,7 @@ static struct platform_driver kempld_driver = {
.remove = kempld_remove,
};
-static struct dmi_system_id __initdata kempld_dmi_table[] = {
+static struct dmi_system_id kempld_dmi_table[] __initdata = {
{
.ident = "BHL6",
.matches = {
@@ -736,7 +737,8 @@ static int __init kempld_init(void)
int ret;
if (force_device_id[0]) {
- for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
+ for (id = kempld_dmi_table;
+ id->matches[0].slot != DMI_NONE; id++)
if (strstr(id->ident, force_device_id))
if (id->callback && id->callback(id))
break;
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
index c84ded5f8ece..23982dbf014d 100644
--- a/drivers/mfd/lp8788-irq.c
+++ b/drivers/mfd/lp8788-irq.c
@@ -66,12 +66,14 @@ static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
static void lp8788_irq_enable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
irqd->enabled[data->hwirq] = 1;
}
static void lp8788_irq_disable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
irqd->enabled[data->hwirq] = 0;
}
diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c
deleted file mode 100644
index cdc3280e2ec7..000000000000
--- a/drivers/mfd/max77686-irq.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * max77686-irq.c - Interrupt controller support for MAX77686
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Chiwoong Byun <woong.byun@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mfd/max77686.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-enum {
- MAX77686_DEBUG_IRQ_INFO = 1 << 0,
- MAX77686_DEBUG_IRQ_MASK = 1 << 1,
- MAX77686_DEBUG_IRQ_INT = 1 << 2,
-};
-
-static int debug_mask = 0;
-module_param(debug_mask, int, 0);
-MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)");
-
-static const u8 max77686_mask_reg[] = {
- [PMIC_INT1] = MAX77686_REG_INT1MSK,
- [PMIC_INT2] = MAX77686_REG_INT2MSK,
- [RTC_INT] = MAX77686_RTC_INTM,
-};
-
-static struct regmap *max77686_get_regmap(struct max77686_dev *max77686,
- enum max77686_irq_source src)
-{
- switch (src) {
- case PMIC_INT1 ... PMIC_INT2:
- return max77686->regmap;
- case RTC_INT:
- return max77686->rtc_regmap;
- default:
- return ERR_PTR(-EINVAL);
- }
-}
-
-struct max77686_irq_data {
- int mask;
- enum max77686_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask) \
- [(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77686_irq_data max77686_irqs[] = {
- DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0),
- DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1),
- DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2),
- DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3),
- DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4),
- DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5),
- DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6),
- DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7),
- DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0),
- DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2),
- DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3),
- DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4),
- DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5),
-};
-
-static void max77686_irq_lock(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s\n", __func__);
-
- mutex_lock(&max77686->irqlock);
-}
-
-static void max77686_irq_sync_unlock(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- int i;
-
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
- u8 mask_reg = max77686_mask_reg[i];
- struct regmap *map = max77686_get_regmap(max77686, i);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n",
- __func__, i, mask_reg, max77686->irq_masks_cur[i]);
-
- if (mask_reg == MAX77686_REG_INVALID ||
- IS_ERR_OR_NULL(map))
- continue;
-
- max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i];
-
- regmap_write(map, max77686_mask_reg[i],
- max77686->irq_masks_cur[i]);
- }
-
- mutex_unlock(&max77686->irqlock);
-}
-
-static const inline struct max77686_irq_data *to_max77686_irq(int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- return &max77686_irqs[data->hwirq];
-}
-
-static void max77686_irq_mask(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
- max77686->irq_masks_cur[irq_data->group] |= irq_data->mask;
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s: group=%d, cur=0x%x\n",
- __func__, irq_data->group,
- max77686->irq_masks_cur[irq_data->group]);
-}
-
-static void max77686_irq_unmask(struct irq_data *data)
-{
- struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
- const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
-
- max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-
- if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
- pr_info("%s: group=%d, cur=0x%x\n",
- __func__, irq_data->group,
- max77686->irq_masks_cur[irq_data->group]);
-}
-
-static struct irq_chip max77686_irq_chip = {
- .name = "max77686",
- .irq_bus_lock = max77686_irq_lock,
- .irq_bus_sync_unlock = max77686_irq_sync_unlock,
- .irq_mask = max77686_irq_mask,
- .irq_unmask = max77686_irq_unmask,
-};
-
-static irqreturn_t max77686_irq_thread(int irq, void *data)
-{
- struct max77686_dev *max77686 = data;
- unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {};
- unsigned int irq_src;
- int ret;
- int i, cur_irq;
-
- ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: irq_src=0x%x\n", __func__, irq_src);
-
- if (irq_src == MAX77686_IRQSRC_PMIC) {
- ret = regmap_bulk_read(max77686->regmap,
- MAX77686_REG_INT1, irq_reg, 2);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: int1=0x%x, int2=0x%x\n", __func__,
- irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]);
- }
-
- if (irq_src & MAX77686_IRQSRC_RTC) {
- ret = regmap_read(max77686->rtc_regmap,
- MAX77686_RTC_INT, &irq_reg[RTC_INT]);
- if (ret < 0) {
- dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT)
- pr_info("%s: rtc int=0x%x\n", __func__,
- irq_reg[RTC_INT]);
-
- }
-
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++)
- irq_reg[i] &= ~max77686->irq_masks_cur[i];
-
- for (i = 0; i < MAX77686_IRQ_NR; i++) {
- if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) {
- cur_irq = irq_find_mapping(max77686->irq_domain, i);
- if (cur_irq)
- handle_nested_irq(cur_irq);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- struct max77686_dev *max77686 = d->host_data;
-
- irq_set_chip_data(irq, max77686);
- irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
- return 0;
-}
-
-static struct irq_domain_ops max77686_irq_domain_ops = {
- .map = max77686_irq_domain_map,
-};
-
-int max77686_irq_init(struct max77686_dev *max77686)
-{
- struct irq_domain *domain;
- int i;
- int ret;
- int val;
- struct regmap *map;
-
- mutex_init(&max77686->irqlock);
-
- if (max77686->irq_gpio && !max77686->irq) {
- max77686->irq = gpio_to_irq(max77686->irq_gpio);
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INT) {
- ret = gpio_request(max77686->irq_gpio, "pmic_irq");
- if (ret < 0) {
- dev_err(max77686->dev,
- "Failed to request gpio %d with ret:"
- "%d\n", max77686->irq_gpio, ret);
- return IRQ_NONE;
- }
-
- gpio_direction_input(max77686->irq_gpio);
- val = gpio_get_value(max77686->irq_gpio);
- gpio_free(max77686->irq_gpio);
- pr_info("%s: gpio_irq=%x\n", __func__, val);
- }
- }
-
- if (!max77686->irq) {
- dev_err(max77686->dev, "irq is not specified\n");
- return -ENODEV;
- }
-
- /* Mask individual interrupt sources */
- for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
- max77686->irq_masks_cur[i] = 0xff;
- max77686->irq_masks_cache[i] = 0xff;
- map = max77686_get_regmap(max77686, i);
-
- if (IS_ERR_OR_NULL(map))
- continue;
- if (max77686_mask_reg[i] == MAX77686_REG_INVALID)
- continue;
-
- regmap_write(map, max77686_mask_reg[i], 0xff);
- }
- domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR,
- &max77686_irq_domain_ops, max77686);
- if (!domain) {
- dev_err(max77686->dev, "could not create irq domain\n");
- return -ENODEV;
- }
- max77686->irq_domain = domain;
-
- ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "max77686-irq", max77686);
-
- if (ret)
- dev_err(max77686->dev, "Failed to request IRQ %d: %d\n",
- max77686->irq, ret);
-
-
- if (debug_mask & MAX77686_DEBUG_IRQ_INFO)
- pr_info("%s-\n", __func__);
-
- return 0;
-}
-
-void max77686_irq_exit(struct max77686_dev *max77686)
-{
- if (max77686->irq)
- free_irq(max77686->irq, max77686);
-}
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index ce869acf27ae..86e552348db4 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -1,5 +1,5 @@
/*
- * max77686.c - mfd core driver for the Maxim 77686
+ * max77686.c - mfd core driver for the Maxim 77686/802
*
* Copyright (C) 2012 Samsung Electronics
* Chiwoong Byun <woong.byun@smasung.com>
@@ -25,6 +25,8 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/mfd/core.h>
@@ -41,15 +43,166 @@ static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-clk", },
};
+static const struct mfd_cell max77802_devs[] = {
+ { .name = "max77802-pmic", },
+ { .name = "max77802-clk", },
+ { .name = "max77802-rtc", },
+};
+
+static bool max77802_pmic_is_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ return (reg >= MAX77802_REG_DEVICE_ID && reg < MAX77802_REG_PMIC_END);
+}
+
+static bool max77802_rtc_is_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ return (reg >= MAX77802_RTC_INT && reg < MAX77802_RTC_END);
+}
+
+static bool max77802_is_accessible_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_accessible_reg(dev, reg) ||
+ max77802_rtc_is_accessible_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (reg == MAX77802_REG_INTSRC || reg == MAX77802_REG_INT1 ||
+ reg == MAX77802_REG_INT2);
+}
+
+static bool max77802_rtc_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (reg == MAX77802_RTC_INT ||
+ reg == MAX77802_RTC_UPDATE0 ||
+ reg == MAX77802_RTC_UPDATE1);
+}
+
+static bool max77802_is_precious_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_precious_reg(dev, reg) ||
+ max77802_rtc_is_precious_reg(dev, reg));
+}
+
+static bool max77802_pmic_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_is_precious_reg(dev, reg) ||
+ reg == MAX77802_REG_STATUS1 || reg == MAX77802_REG_STATUS2 ||
+ reg == MAX77802_REG_PWRON);
+}
+
+static bool max77802_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_rtc_is_precious_reg(dev, reg) ||
+ reg == MAX77802_RTC_SEC ||
+ reg == MAX77802_RTC_MIN ||
+ reg == MAX77802_RTC_HOUR ||
+ reg == MAX77802_RTC_WEEKDAY ||
+ reg == MAX77802_RTC_MONTH ||
+ reg == MAX77802_RTC_YEAR ||
+ reg == MAX77802_RTC_DATE);
+}
+
+static bool max77802_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return (max77802_pmic_is_volatile_reg(dev, reg) ||
+ max77802_rtc_is_volatile_reg(dev, reg));
+}
+
static struct regmap_config max77686_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
-#ifdef CONFIG_OF
+static struct regmap_config max77686_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static struct regmap_config max77802_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = max77802_is_accessible_reg,
+ .readable_reg = max77802_is_accessible_reg,
+ .precious_reg = max77802_is_precious_reg,
+ .volatile_reg = max77802_is_volatile_reg,
+ .name = "max77802-pmic",
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq max77686_irqs[] = {
+ /* INT1 interrupts */
+ { .reg_offset = 0, .mask = MAX77686_INT1_PWRONF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_PWRONR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_JIGONBF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_JIGONBR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ACOKBF_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ACOKBR_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_ONKEY1S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_INT1_MRSTB_MSK, },
+ /* INT2 interrupts */
+ { .reg_offset = 1, .mask = MAX77686_INT2_140C_MSK, },
+ { .reg_offset = 1, .mask = MAX77686_INT2_120C_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_irq_chip = {
+ .name = "max77686-pmic",
+ .status_base = MAX77686_REG_INT1,
+ .mask_base = MAX77686_REG_INT1MSK,
+ .num_regs = 2,
+ .irqs = max77686_irqs,
+ .num_irqs = ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq max77686_rtc_irqs[] = {
+ /* RTC interrupts */
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
+ { .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
+};
+
+static const struct regmap_irq_chip max77686_rtc_irq_chip = {
+ .name = "max77686-rtc",
+ .status_base = MAX77686_RTC_INT,
+ .mask_base = MAX77686_RTC_INTM,
+ .num_regs = 1,
+ .irqs = max77686_rtc_irqs,
+ .num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct regmap_irq_chip max77802_irq_chip = {
+ .name = "max77802-pmic",
+ .status_base = MAX77802_REG_INT1,
+ .mask_base = MAX77802_REG_INT1MSK,
+ .num_regs = 2,
+ .irqs = max77686_irqs, /* same masks as 77686 */
+ .num_irqs = ARRAY_SIZE(max77686_irqs),
+};
+
+static const struct regmap_irq_chip max77802_rtc_irq_chip = {
+ .name = "max77802-rtc",
+ .status_base = MAX77802_RTC_INT,
+ .mask_base = MAX77802_RTC_INTM,
+ .num_regs = 1,
+ .irqs = max77686_rtc_irqs, /* same masks as 77686 */
+ .num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
static const struct of_device_id max77686_pmic_dt_match[] = {
- {.compatible = "maxim,max77686", .data = NULL},
- {},
+ {
+ .compatible = "maxim,max77686",
+ .data = (void *)TYPE_MAX77686,
+ },
+ {
+ .compatible = "maxim,max77802",
+ .data = (void *)TYPE_MAX77802,
+ },
+ { },
};
static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
@@ -58,53 +211,74 @@ static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
struct max77686_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- dev_err(dev, "could not allocate memory for pdata\n");
+ if (!pd)
return NULL;
- }
dev->platform_data = pd;
return pd;
}
-#else
-static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device
- *dev)
-{
- return 0;
-}
-#endif
static int max77686_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max77686_dev *max77686 = NULL;
struct max77686_platform_data *pdata = dev_get_platdata(&i2c->dev);
+ const struct of_device_id *match;
unsigned int data;
int ret = 0;
+ const struct regmap_config *config;
+ const struct regmap_irq_chip *irq_chip;
+ const struct regmap_irq_chip *rtc_irq_chip;
+ struct regmap **rtc_regmap;
+ const struct mfd_cell *cells;
+ int n_devs;
- if (i2c->dev.of_node)
+ if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node && !pdata)
pdata = max77686_i2c_parse_dt_pdata(&i2c->dev);
if (!pdata) {
dev_err(&i2c->dev, "No platform data found.\n");
- return -EIO;
+ return -EINVAL;
}
max77686 = devm_kzalloc(&i2c->dev,
sizeof(struct max77686_dev), GFP_KERNEL);
- if (max77686 == NULL)
+ if (!max77686)
return -ENOMEM;
+ if (i2c->dev.of_node) {
+ match = of_match_node(max77686_pmic_dt_match, i2c->dev.of_node);
+ if (!match)
+ return -EINVAL;
+
+ max77686->type = (unsigned long)match->data;
+ } else
+ max77686->type = id->driver_data;
+
i2c_set_clientdata(i2c, max77686);
max77686->dev = &i2c->dev;
max77686->i2c = i2c;
- max77686->type = id->driver_data;
max77686->wakeup = pdata->wakeup;
- max77686->irq_gpio = pdata->irq_gpio;
max77686->irq = i2c->irq;
- max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config);
+ if (max77686->type == TYPE_MAX77686) {
+ config = &max77686_regmap_config;
+ irq_chip = &max77686_irq_chip;
+ rtc_irq_chip = &max77686_rtc_irq_chip;
+ rtc_regmap = &max77686->rtc_regmap;
+ cells = max77686_devs;
+ n_devs = ARRAY_SIZE(max77686_devs);
+ } else {
+ config = &max77802_regmap_config;
+ irq_chip = &max77802_irq_chip;
+ rtc_irq_chip = &max77802_rtc_irq_chip;
+ rtc_regmap = &max77686->regmap;
+ cells = max77802_devs;
+ n_devs = ARRAY_SIZE(max77802_devs);
+ }
+
+ max77686->regmap = devm_regmap_init_i2c(i2c, config);
if (IS_ERR(max77686->regmap)) {
ret = PTR_ERR(max77686->regmap);
dev_err(max77686->dev, "Failed to allocate register map: %d\n",
@@ -112,30 +286,68 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return ret;
}
- if (regmap_read(max77686->regmap,
- MAX77686_REG_DEVICE_ID, &data) < 0) {
+ ret = regmap_read(max77686->regmap, MAX77686_REG_DEVICE_ID, &data);
+ if (ret < 0) {
dev_err(max77686->dev,
"device not found on this channel (this is not an error)\n");
return -ENODEV;
- } else
- dev_info(max77686->dev, "device found\n");
+ }
- max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
- if (!max77686->rtc) {
- dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n");
- return -ENODEV;
+ if (max77686->type == TYPE_MAX77686) {
+ max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+ if (!max77686->rtc) {
+ dev_err(max77686->dev,
+ "Failed to allocate I2C device for RTC\n");
+ return -ENODEV;
+ }
+ i2c_set_clientdata(max77686->rtc, max77686);
+
+ max77686->rtc_regmap =
+ devm_regmap_init_i2c(max77686->rtc,
+ &max77686_rtc_regmap_config);
+ if (IS_ERR(max77686->rtc_regmap)) {
+ ret = PTR_ERR(max77686->rtc_regmap);
+ dev_err(max77686->dev,
+ "failed to allocate RTC regmap: %d\n",
+ ret);
+ goto err_unregister_i2c;
+ }
+ }
+
+ ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+ IRQF_SHARED, 0, irq_chip,
+ &max77686->irq_data);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
+ goto err_unregister_i2c;
}
- i2c_set_clientdata(max77686->rtc, max77686);
- max77686_irq_init(max77686);
+ ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+ IRQF_SHARED, 0, rtc_irq_chip,
+ &max77686->rtc_irq_data);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
+ goto err_del_irqc;
+ }
- ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
- ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
+ ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret < 0) {
- mfd_remove_devices(max77686->dev);
- i2c_unregister_device(max77686->rtc);
+ dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
+ goto err_del_rtc_irqc;
}
+ return 0;
+
+err_del_rtc_irqc:
+ regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+err_del_irqc:
+ regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+err_unregister_i2c:
+ if (max77686->type == TYPE_MAX77686)
+ i2c_unregister_device(max77686->rtc);
+
return ret;
}
@@ -144,7 +356,12 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
mfd_remove_devices(max77686->dev);
- i2c_unregister_device(max77686->rtc);
+
+ regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
+ regmap_del_irq_chip(max77686->irq, max77686->irq_data);
+
+ if (max77686->type == TYPE_MAX77686)
+ i2c_unregister_device(max77686->rtc);
return 0;
}
@@ -155,10 +372,50 @@ static const struct i2c_device_id max77686_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
+#ifdef CONFIG_PM_SLEEP
+static int max77686_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(max77686->irq);
+
+ /*
+ * IRQ must be disabled during suspend because if it happens
+ * while suspended it will be handled before resuming I2C.
+ *
+ * When device is woken up from suspend (e.g. by RTC wake alarm),
+ * an interrupt occurs before resuming I2C bus controller.
+ * Interrupt handler tries to read registers but this read
+ * will fail because I2C is still suspended.
+ */
+ disable_irq(max77686->irq);
+
+ return 0;
+}
+
+static int max77686_resume(struct device *dev)
+{
+ struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(max77686->irq);
+
+ enable_irq(max77686->irq);
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(max77686_pm, max77686_suspend, max77686_resume);
+
static struct i2c_driver max77686_i2c_driver = {
.driver = {
.name = "max77686",
.owner = THIS_MODULE,
+ .pm = &max77686_pm,
.of_match_table = of_match_ptr(max77686_pmic_dt_match),
},
.probe = max77686_i2c_probe,
@@ -179,6 +436,6 @@ static void __exit max77686_i2c_exit(void)
}
module_exit(max77686_i2c_exit);
-MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver");
+MODULE_DESCRIPTION("MAXIM 77686/802 multi-function core driver");
MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max77693-irq.c b/drivers/mfd/max77693-irq.c
deleted file mode 100644
index 66b58fe77094..000000000000
--- a/drivers/mfd/max77693-irq.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * max77693-irq.c - Interrupt controller support for MAX77693
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * SangYoung Son <hello.son@samsung.com>
- *
- * This program is not provided / owned by Maxim Integrated Products.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This driver is based on max8997-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/irqdomain.h>
-#include <linux/mfd/max77693.h>
-#include <linux/mfd/max77693-private.h>
-
-static const u8 max77693_mask_reg[] = {
- [LED_INT] = MAX77693_LED_REG_FLASH_INT_MASK,
- [TOPSYS_INT] = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
- [CHG_INT] = MAX77693_CHG_REG_CHG_INT_MASK,
- [MUIC_INT1] = MAX77693_MUIC_REG_INTMASK1,
- [MUIC_INT2] = MAX77693_MUIC_REG_INTMASK2,
- [MUIC_INT3] = MAX77693_MUIC_REG_INTMASK3,
-};
-
-static struct regmap *max77693_get_regmap(struct max77693_dev *max77693,
- enum max77693_irq_source src)
-{
- switch (src) {
- case LED_INT ... CHG_INT:
- return max77693->regmap;
- case MUIC_INT1 ... MUIC_INT3:
- return max77693->regmap_muic;
- default:
- return ERR_PTR(-EINVAL);
- }
-}
-
-struct max77693_irq_data {
- int mask;
- enum max77693_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask) \
- [(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max77693_irq_data max77693_irqs[] = {
- DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_OPEN, LED_INT, 1 << 0),
- DECLARE_IRQ(MAX77693_LED_IRQ_FLED2_SHORT, LED_INT, 1 << 1),
- DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_OPEN, LED_INT, 1 << 2),
- DECLARE_IRQ(MAX77693_LED_IRQ_FLED1_SHORT, LED_INT, 1 << 3),
- DECLARE_IRQ(MAX77693_LED_IRQ_MAX_FLASH, LED_INT, 1 << 4),
-
- DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T120C_INT, TOPSYS_INT, 1 << 0),
- DECLARE_IRQ(MAX77693_TOPSYS_IRQ_T140C_INT, TOPSYS_INT, 1 << 1),
- DECLARE_IRQ(MAX77693_TOPSYS_IRQ_LOWSYS_INT, TOPSYS_INT, 1 << 3),
-
- DECLARE_IRQ(MAX77693_CHG_IRQ_BYP_I, CHG_INT, 1 << 0),
- DECLARE_IRQ(MAX77693_CHG_IRQ_THM_I, CHG_INT, 1 << 2),
- DECLARE_IRQ(MAX77693_CHG_IRQ_BAT_I, CHG_INT, 1 << 3),
- DECLARE_IRQ(MAX77693_CHG_IRQ_CHG_I, CHG_INT, 1 << 4),
- DECLARE_IRQ(MAX77693_CHG_IRQ_CHGIN_I, CHG_INT, 1 << 6),
-
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC, MUIC_INT1, 1 << 0),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_LOW, MUIC_INT1, 1 << 1),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC_ERR, MUIC_INT1, 1 << 2),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT1_ADC1K, MUIC_INT1, 1 << 3),
-
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGTYP, MUIC_INT2, 1 << 0),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_CHGDETREUN, MUIC_INT2, 1 << 1),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DCDTMR, MUIC_INT2, 1 << 2),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_DXOVP, MUIC_INT2, 1 << 3),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VBVOLT, MUIC_INT2, 1 << 4),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT2_VIDRM, MUIC_INT2, 1 << 5),
-
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_EOC, MUIC_INT3, 1 << 0),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CGMBC, MUIC_INT3, 1 << 1),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_OVP, MUIC_INT3, 1 << 2),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_MBCCHG_ERR, MUIC_INT3, 1 << 3),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_CHG_ENABLED, MUIC_INT3, 1 << 4),
- DECLARE_IRQ(MAX77693_MUIC_IRQ_INT3_BAT_DET, MUIC_INT3, 1 << 5),
-};
-
-static void max77693_irq_lock(struct irq_data *data)
-{
- struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
-
- mutex_lock(&max77693->irqlock);
-}
-
-static void max77693_irq_sync_unlock(struct irq_data *data)
-{
- struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
- int i;
-
- for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
- u8 mask_reg = max77693_mask_reg[i];
- struct regmap *map = max77693_get_regmap(max77693, i);
-
- if (mask_reg == MAX77693_REG_INVALID ||
- IS_ERR_OR_NULL(map))
- continue;
- max77693->irq_masks_cache[i] = max77693->irq_masks_cur[i];
-
- max77693_write_reg(map, max77693_mask_reg[i],
- max77693->irq_masks_cur[i]);
- }
-
- mutex_unlock(&max77693->irqlock);
-}
-
-static const inline struct max77693_irq_data *
-irq_to_max77693_irq(struct max77693_dev *max77693, int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- return &max77693_irqs[data->hwirq];
-}
-
-static void max77693_irq_mask(struct irq_data *data)
-{
- struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
- const struct max77693_irq_data *irq_data =
- irq_to_max77693_irq(max77693, data->irq);
-
- if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
- return;
-
- if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
- max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
- else
- max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
-}
-
-static void max77693_irq_unmask(struct irq_data *data)
-{
- struct max77693_dev *max77693 = irq_get_chip_data(data->irq);
- const struct max77693_irq_data *irq_data =
- irq_to_max77693_irq(max77693, data->irq);
-
- if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
- return;
-
- if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
- max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
- else
- max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-}
-
-static struct irq_chip max77693_irq_chip = {
- .name = "max77693",
- .irq_bus_lock = max77693_irq_lock,
- .irq_bus_sync_unlock = max77693_irq_sync_unlock,
- .irq_mask = max77693_irq_mask,
- .irq_unmask = max77693_irq_unmask,
-};
-
-#define MAX77693_IRQSRC_CHG (1 << 0)
-#define MAX77693_IRQSRC_TOP (1 << 1)
-#define MAX77693_IRQSRC_FLASH (1 << 2)
-#define MAX77693_IRQSRC_MUIC (1 << 3)
-static irqreturn_t max77693_irq_thread(int irq, void *data)
-{
- struct max77693_dev *max77693 = data;
- u8 irq_reg[MAX77693_IRQ_GROUP_NR] = {};
- u8 irq_src;
- int ret;
- int i, cur_irq;
-
- ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_INTSRC,
- &irq_src);
- if (ret < 0) {
- dev_err(max77693->dev, "Failed to read interrupt source: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- if (irq_src & MAX77693_IRQSRC_CHG)
- /* CHG_INT */
- ret = max77693_read_reg(max77693->regmap, MAX77693_CHG_REG_CHG_INT,
- &irq_reg[CHG_INT]);
-
- if (irq_src & MAX77693_IRQSRC_TOP)
- /* TOPSYS_INT */
- ret = max77693_read_reg(max77693->regmap,
- MAX77693_PMIC_REG_TOPSYS_INT, &irq_reg[TOPSYS_INT]);
-
- if (irq_src & MAX77693_IRQSRC_FLASH)
- /* LED_INT */
- ret = max77693_read_reg(max77693->regmap,
- MAX77693_LED_REG_FLASH_INT, &irq_reg[LED_INT]);
-
- if (irq_src & MAX77693_IRQSRC_MUIC)
- /* MUIC INT1 ~ INT3 */
- max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
- MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);
-
- /* Apply masking */
- for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
- if (i >= MUIC_INT1 && i <= MUIC_INT3)
- irq_reg[i] &= max77693->irq_masks_cur[i];
- else
- irq_reg[i] &= ~max77693->irq_masks_cur[i];
- }
-
- /* Report */
- for (i = 0; i < MAX77693_IRQ_NR; i++) {
- if (irq_reg[max77693_irqs[i].group] & max77693_irqs[i].mask) {
- cur_irq = irq_find_mapping(max77693->irq_domain, i);
- if (cur_irq)
- handle_nested_irq(cur_irq);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-int max77693_irq_resume(struct max77693_dev *max77693)
-{
- if (max77693->irq)
- max77693_irq_thread(0, max77693);
-
- return 0;
-}
-
-static int max77693_irq_domain_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hw)
-{
- struct max77693_dev *max77693 = d->host_data;
-
- irq_set_chip_data(irq, max77693);
- irq_set_chip_and_handler(irq, &max77693_irq_chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
-#else
- irq_set_noprobe(irq);
-#endif
- return 0;
-}
-
-static struct irq_domain_ops max77693_irq_domain_ops = {
- .map = max77693_irq_domain_map,
-};
-
-int max77693_irq_init(struct max77693_dev *max77693)
-{
- struct irq_domain *domain;
- int i;
- int ret = 0;
- u8 intsrc_mask;
-
- mutex_init(&max77693->irqlock);
-
- /* Mask individual interrupt sources */
- for (i = 0; i < MAX77693_IRQ_GROUP_NR; i++) {
- struct regmap *map;
- /* MUIC IRQ 0:MASK 1:NOT MASK */
- /* Other IRQ 1:MASK 0:NOT MASK */
- if (i >= MUIC_INT1 && i <= MUIC_INT3) {
- max77693->irq_masks_cur[i] = 0x00;
- max77693->irq_masks_cache[i] = 0x00;
- } else {
- max77693->irq_masks_cur[i] = 0xff;
- max77693->irq_masks_cache[i] = 0xff;
- }
- map = max77693_get_regmap(max77693, i);
-
- if (IS_ERR_OR_NULL(map))
- continue;
- if (max77693_mask_reg[i] == MAX77693_REG_INVALID)
- continue;
- if (i >= MUIC_INT1 && i <= MUIC_INT3)
- max77693_write_reg(map, max77693_mask_reg[i], 0x00);
- else
- max77693_write_reg(map, max77693_mask_reg[i], 0xff);
- }
-
- domain = irq_domain_add_linear(NULL, MAX77693_IRQ_NR,
- &max77693_irq_domain_ops, max77693);
- if (!domain) {
- dev_err(max77693->dev, "could not create irq domain\n");
- ret = -ENODEV;
- goto err_irq;
- }
- max77693->irq_domain = domain;
-
- /* Unmask max77693 interrupt */
- ret = max77693_read_reg(max77693->regmap,
- MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
- if (ret < 0) {
- dev_err(max77693->dev, "fail to read PMIC register\n");
- goto err_irq;
- }
-
- intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
- intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
- intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
- ret = max77693_write_reg(max77693->regmap,
- MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
- if (ret < 0) {
- dev_err(max77693->dev, "fail to write PMIC register\n");
- goto err_irq;
- }
-
- ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "max77693-irq", max77693);
- if (ret)
- dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
- max77693->irq, ret);
-
-err_irq:
- return ret;
-}
-
-void max77693_irq_exit(struct max77693_dev *max77693)
-{
- if (max77693->irq)
- free_irq(max77693->irq, max77693);
-}
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 7e05428c756d..249c139ef04a 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -49,62 +49,62 @@ static const struct mfd_cell max77693_devs[] = {
{ .name = "max77693-haptic", },
};
-int max77693_read_reg(struct regmap *map, u8 reg, u8 *dest)
-{
- unsigned int val;
- int ret;
-
- ret = regmap_read(map, reg, &val);
- *dest = val;
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_read_reg);
-
-int max77693_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf)
-{
- int ret;
-
- ret = regmap_bulk_read(map, reg, buf, count);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_bulk_read);
-
-int max77693_write_reg(struct regmap *map, u8 reg, u8 value)
-{
- int ret;
-
- ret = regmap_write(map, reg, value);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_write_reg);
-
-int max77693_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf)
-{
- int ret;
+static const struct regmap_config max77693_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MAX77693_PMIC_REG_END,
+};
- ret = regmap_bulk_write(map, reg, buf, count);
+static const struct regmap_irq max77693_led_irqs[] = {
+ { .mask = LED_IRQ_FLED2_OPEN, },
+ { .mask = LED_IRQ_FLED2_SHORT, },
+ { .mask = LED_IRQ_FLED1_OPEN, },
+ { .mask = LED_IRQ_FLED1_SHORT, },
+ { .mask = LED_IRQ_MAX_FLASH, },
+};
- return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_bulk_write);
+static const struct regmap_irq_chip max77693_led_irq_chip = {
+ .name = "max77693-led",
+ .status_base = MAX77693_LED_REG_FLASH_INT,
+ .mask_base = MAX77693_LED_REG_FLASH_INT_MASK,
+ .mask_invert = false,
+ .num_regs = 1,
+ .irqs = max77693_led_irqs,
+ .num_irqs = ARRAY_SIZE(max77693_led_irqs),
+};
-int max77693_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask)
-{
- int ret;
+static const struct regmap_irq max77693_topsys_irqs[] = {
+ { .mask = TOPSYS_IRQ_T120C_INT, },
+ { .mask = TOPSYS_IRQ_T140C_INT, },
+ { .mask = TOPSYS_IRQ_LOWSYS_INT, },
+};
- ret = regmap_update_bits(map, reg, mask, val);
+static const struct regmap_irq_chip max77693_topsys_irq_chip = {
+ .name = "max77693-topsys",
+ .status_base = MAX77693_PMIC_REG_TOPSYS_INT,
+ .mask_base = MAX77693_PMIC_REG_TOPSYS_INT_MASK,
+ .mask_invert = false,
+ .num_regs = 1,
+ .irqs = max77693_topsys_irqs,
+ .num_irqs = ARRAY_SIZE(max77693_topsys_irqs),
+};
- return ret;
-}
-EXPORT_SYMBOL_GPL(max77693_update_reg);
+static const struct regmap_irq max77693_charger_irqs[] = {
+ { .mask = CHG_IRQ_BYP_I, },
+ { .mask = CHG_IRQ_THM_I, },
+ { .mask = CHG_IRQ_BAT_I, },
+ { .mask = CHG_IRQ_CHG_I, },
+ { .mask = CHG_IRQ_CHGIN_I, },
+};
-static const struct regmap_config max77693_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = MAX77693_PMIC_REG_END,
+static const struct regmap_irq_chip max77693_charger_irq_chip = {
+ .name = "max77693-charger",
+ .status_base = MAX77693_CHG_REG_CHG_INT,
+ .mask_base = MAX77693_CHG_REG_CHG_INT_MASK,
+ .mask_invert = false,
+ .num_regs = 1,
+ .irqs = max77693_charger_irqs,
+ .num_irqs = ARRAY_SIZE(max77693_charger_irqs),
};
static const struct regmap_config max77693_regmap_muic_config = {
@@ -113,11 +113,42 @@ static const struct regmap_config max77693_regmap_muic_config = {
.max_register = MAX77693_MUIC_REG_END,
};
+static const struct regmap_irq max77693_muic_irqs[] = {
+ { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC, },
+ { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_LOW, },
+ { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC_ERR, },
+ { .reg_offset = 0, .mask = MUIC_IRQ_INT1_ADC1K, },
+
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGTYP, },
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_CHGDETREUN, },
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DCDTMR, },
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_DXOVP, },
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VBVOLT, },
+ { .reg_offset = 1, .mask = MUIC_IRQ_INT2_VIDRM, },
+
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_EOC, },
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CGMBC, },
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_OVP, },
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_MBCCHG_ERR, },
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_CHG_ENABLED, },
+ { .reg_offset = 2, .mask = MUIC_IRQ_INT3_BAT_DET, },
+};
+
+static const struct regmap_irq_chip max77693_muic_irq_chip = {
+ .name = "max77693-muic",
+ .status_base = MAX77693_MUIC_REG_INT1,
+ .mask_base = MAX77693_MUIC_REG_INTMASK1,
+ .mask_invert = true,
+ .num_regs = 3,
+ .irqs = max77693_muic_irqs,
+ .num_irqs = ARRAY_SIZE(max77693_muic_irqs),
+};
+
static int max77693_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max77693_dev *max77693;
- u8 reg_data;
+ unsigned int reg_data;
int ret = 0;
max77693 = devm_kzalloc(&i2c->dev,
@@ -139,7 +170,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
return ret;
}
- ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
+ ret = regmap_read(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
&reg_data);
if (ret < 0) {
dev_err(max77693->dev, "device not found on this channel\n");
@@ -176,9 +207,45 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
goto err_regmap_muic;
}
- ret = max77693_irq_init(max77693);
- if (ret < 0)
- goto err_irq;
+ ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max77693_led_irq_chip,
+ &max77693->irq_data_led);
+ if (ret) {
+ dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+ goto err_regmap_muic;
+ }
+
+ ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max77693_topsys_irq_chip,
+ &max77693->irq_data_topsys);
+ if (ret) {
+ dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+ goto err_irq_topsys;
+ }
+
+ ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max77693_charger_irq_chip,
+ &max77693->irq_data_charger);
+ if (ret) {
+ dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+ goto err_irq_charger;
+ }
+
+ ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+ IRQF_ONESHOT | IRQF_SHARED |
+ IRQF_TRIGGER_FALLING, 0,
+ &max77693_muic_irq_chip,
+ &max77693->irq_data_muic);
+ if (ret) {
+ dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
+ goto err_irq_muic;
+ }
pm_runtime_set_active(max77693->dev);
@@ -190,8 +257,14 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
return ret;
err_mfd:
- max77693_irq_exit(max77693);
-err_irq:
+ mfd_remove_devices(max77693->dev);
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+err_irq_muic:
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+err_irq_charger:
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+err_irq_topsys:
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
err_regmap_muic:
i2c_unregister_device(max77693->haptic);
err_i2c_haptic:
@@ -204,7 +277,12 @@ static int max77693_i2c_remove(struct i2c_client *i2c)
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
mfd_remove_devices(max77693->dev);
- max77693_irq_exit(max77693);
+
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
+ regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
+
i2c_unregister_device(max77693->muic);
i2c_unregister_device(max77693->haptic);
@@ -222,8 +300,11 @@ static int max77693_suspend(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev))
- irq_set_irq_wake(max77693->irq, 1);
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(max77693->irq);
+ disable_irq(max77693->irq);
+ }
+
return 0;
}
@@ -232,9 +313,12 @@ static int max77693_resume(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev))
- irq_set_irq_wake(max77693->irq, 0);
- return max77693_irq_resume(max77693);
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(max77693->irq);
+ enable_irq(max77693->irq);
+ }
+
+ return 0;
}
static const struct dev_pm_ops max77693_pm = {
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index f3faf0c45ddd..97a787ab3d51 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -624,6 +624,7 @@ static void max8925_irq_sync_unlock(struct irq_data *data)
static void max8925_irq_enable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
max8925_irqs[data->irq - chip->irq_base].enable
= max8925_irqs[data->irq - chip->irq_base].offs;
}
@@ -631,6 +632,7 @@ static void max8925_irq_enable(struct irq_data *data)
static void max8925_irq_disable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
+
max8925_irqs[data->irq - chip->irq_base].enable = 0;
}
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index a83eed5c15ca..ecbe78ead3b6 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -257,9 +257,11 @@ static struct i2c_driver max8925_driver = {
static int __init max8925_i2c_init(void)
{
int ret;
+
ret = i2c_add_driver(&max8925_driver);
if (ret != 0)
pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
+
return ret;
}
subsys_initcall(max8925_i2c_init);
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index acf5dd712eb2..2b6bc868cd3d 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -10,106 +10,18 @@
* Free Software Foundation.
*/
-#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/mc13xxx.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
#include "mc13xxx.h"
#define MC13XXX_IRQSTAT0 0
-#define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0)
-#define MC13XXX_IRQSTAT0_ADCBISDONEI (1 << 1)
-#define MC13XXX_IRQSTAT0_TSI (1 << 2)
-#define MC13783_IRQSTAT0_WHIGHI (1 << 3)
-#define MC13783_IRQSTAT0_WLOWI (1 << 4)
-#define MC13XXX_IRQSTAT0_CHGDETI (1 << 6)
-#define MC13783_IRQSTAT0_CHGOVI (1 << 7)
-#define MC13XXX_IRQSTAT0_CHGREVI (1 << 8)
-#define MC13XXX_IRQSTAT0_CHGSHORTI (1 << 9)
-#define MC13XXX_IRQSTAT0_CCCVI (1 << 10)
-#define MC13XXX_IRQSTAT0_CHGCURRI (1 << 11)
-#define MC13XXX_IRQSTAT0_BPONI (1 << 12)
-#define MC13XXX_IRQSTAT0_LOBATLI (1 << 13)
-#define MC13XXX_IRQSTAT0_LOBATHI (1 << 14)
-#define MC13783_IRQSTAT0_UDPI (1 << 15)
-#define MC13783_IRQSTAT0_USBI (1 << 16)
-#define MC13783_IRQSTAT0_IDI (1 << 19)
-#define MC13783_IRQSTAT0_SE1I (1 << 21)
-#define MC13783_IRQSTAT0_CKDETI (1 << 22)
-#define MC13783_IRQSTAT0_UDMI (1 << 23)
-
#define MC13XXX_IRQMASK0 1
-#define MC13XXX_IRQMASK0_ADCDONEM MC13XXX_IRQSTAT0_ADCDONEI
-#define MC13XXX_IRQMASK0_ADCBISDONEM MC13XXX_IRQSTAT0_ADCBISDONEI
-#define MC13XXX_IRQMASK0_TSM MC13XXX_IRQSTAT0_TSI
-#define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI
-#define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI
-#define MC13XXX_IRQMASK0_CHGDETM MC13XXX_IRQSTAT0_CHGDETI
-#define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI
-#define MC13XXX_IRQMASK0_CHGREVM MC13XXX_IRQSTAT0_CHGREVI
-#define MC13XXX_IRQMASK0_CHGSHORTM MC13XXX_IRQSTAT0_CHGSHORTI
-#define MC13XXX_IRQMASK0_CCCVM MC13XXX_IRQSTAT0_CCCVI
-#define MC13XXX_IRQMASK0_CHGCURRM MC13XXX_IRQSTAT0_CHGCURRI
-#define MC13XXX_IRQMASK0_BPONM MC13XXX_IRQSTAT0_BPONI
-#define MC13XXX_IRQMASK0_LOBATLM MC13XXX_IRQSTAT0_LOBATLI
-#define MC13XXX_IRQMASK0_LOBATHM MC13XXX_IRQSTAT0_LOBATHI
-#define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI
-#define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI
-#define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI
-#define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I
-#define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI
-#define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI
-
#define MC13XXX_IRQSTAT1 3
-#define MC13XXX_IRQSTAT1_1HZI (1 << 0)
-#define MC13XXX_IRQSTAT1_TODAI (1 << 1)
-#define MC13783_IRQSTAT1_ONOFD1I (1 << 3)
-#define MC13783_IRQSTAT1_ONOFD2I (1 << 4)
-#define MC13783_IRQSTAT1_ONOFD3I (1 << 5)
-#define MC13XXX_IRQSTAT1_SYSRSTI (1 << 6)
-#define MC13XXX_IRQSTAT1_RTCRSTI (1 << 7)
-#define MC13XXX_IRQSTAT1_PCI (1 << 8)
-#define MC13XXX_IRQSTAT1_WARMI (1 << 9)
-#define MC13XXX_IRQSTAT1_MEMHLDI (1 << 10)
-#define MC13783_IRQSTAT1_PWRRDYI (1 << 11)
-#define MC13XXX_IRQSTAT1_THWARNLI (1 << 12)
-#define MC13XXX_IRQSTAT1_THWARNHI (1 << 13)
-#define MC13XXX_IRQSTAT1_CLKI (1 << 14)
-#define MC13783_IRQSTAT1_SEMAFI (1 << 15)
-#define MC13783_IRQSTAT1_MC2BI (1 << 17)
-#define MC13783_IRQSTAT1_HSDETI (1 << 18)
-#define MC13783_IRQSTAT1_HSLI (1 << 19)
-#define MC13783_IRQSTAT1_ALSPTHI (1 << 20)
-#define MC13783_IRQSTAT1_AHSSHORTI (1 << 21)
-
#define MC13XXX_IRQMASK1 4
-#define MC13XXX_IRQMASK1_1HZM MC13XXX_IRQSTAT1_1HZI
-#define MC13XXX_IRQMASK1_TODAM MC13XXX_IRQSTAT1_TODAI
-#define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I
-#define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I
-#define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I
-#define MC13XXX_IRQMASK1_SYSRSTM MC13XXX_IRQSTAT1_SYSRSTI
-#define MC13XXX_IRQMASK1_RTCRSTM MC13XXX_IRQSTAT1_RTCRSTI
-#define MC13XXX_IRQMASK1_PCM MC13XXX_IRQSTAT1_PCI
-#define MC13XXX_IRQMASK1_WARMM MC13XXX_IRQSTAT1_WARMI
-#define MC13XXX_IRQMASK1_MEMHLDM MC13XXX_IRQSTAT1_MEMHLDI
-#define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI
-#define MC13XXX_IRQMASK1_THWARNLM MC13XXX_IRQSTAT1_THWARNLI
-#define MC13XXX_IRQMASK1_THWARNHM MC13XXX_IRQSTAT1_THWARNHI
-#define MC13XXX_IRQMASK1_CLKM MC13XXX_IRQSTAT1_CLKI
-#define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI
-#define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI
-#define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI
-#define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI
-#define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI
-#define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI
#define MC13XXX_REVISION 7
#define MC13XXX_REVISION_REVMETAL (0x07 << 0)
@@ -189,45 +101,21 @@ EXPORT_SYMBOL(mc13xxx_reg_rmw);
int mc13xxx_irq_mask(struct mc13xxx *mc13xxx, int irq)
{
- int ret;
- unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
- u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- u32 mask;
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
-
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- if (mask & irqbit)
- /* already masked */
- return 0;
+ disable_irq_nosync(virq);
- return mc13xxx_reg_write(mc13xxx, offmask, mask | irqbit);
+ return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_mask);
int mc13xxx_irq_unmask(struct mc13xxx *mc13xxx, int irq)
{
- int ret;
- unsigned int offmask = irq < 24 ? MC13XXX_IRQMASK0 : MC13XXX_IRQMASK1;
- u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- u32 mask;
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
+ enable_irq(virq);
- if (!(mask & irqbit))
- /* already unmasked */
- return 0;
-
- return mc13xxx_reg_write(mc13xxx, offmask, mask & ~irqbit);
+ return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_unmask);
@@ -239,7 +127,7 @@ int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq,
unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
+ if (irq < 0 || irq >= ARRAY_SIZE(mc13xxx->irqs))
return -EINVAL;
if (enabled) {
@@ -266,147 +154,26 @@ int mc13xxx_irq_status(struct mc13xxx *mc13xxx, int irq,
}
EXPORT_SYMBOL(mc13xxx_irq_status);
-int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq)
-{
- unsigned int offstat = irq < 24 ? MC13XXX_IRQSTAT0 : MC13XXX_IRQSTAT1;
- unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
-
- BUG_ON(irq < 0 || irq >= MC13XXX_NUM_IRQ);
-
- return mc13xxx_reg_write(mc13xxx, offstat, val);
-}
-EXPORT_SYMBOL(mc13xxx_irq_ack);
-
-int mc13xxx_irq_request_nounmask(struct mc13xxx *mc13xxx, int irq,
- irq_handler_t handler, const char *name, void *dev)
-{
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
- BUG_ON(!handler);
-
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ)
- return -EINVAL;
-
- if (mc13xxx->irqhandler[irq])
- return -EBUSY;
-
- mc13xxx->irqhandler[irq] = handler;
- mc13xxx->irqdata[irq] = dev;
-
- return 0;
-}
-EXPORT_SYMBOL(mc13xxx_irq_request_nounmask);
-
int mc13xxx_irq_request(struct mc13xxx *mc13xxx, int irq,
irq_handler_t handler, const char *name, void *dev)
{
- int ret;
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- ret = mc13xxx_irq_request_nounmask(mc13xxx, irq, handler, name, dev);
- if (ret)
- return ret;
-
- ret = mc13xxx_irq_unmask(mc13xxx, irq);
- if (ret) {
- mc13xxx->irqhandler[irq] = NULL;
- mc13xxx->irqdata[irq] = NULL;
- return ret;
- }
-
- return 0;
+ return devm_request_threaded_irq(mc13xxx->dev, virq, NULL, handler,
+ 0, name, dev);
}
EXPORT_SYMBOL(mc13xxx_irq_request);
int mc13xxx_irq_free(struct mc13xxx *mc13xxx, int irq, void *dev)
{
- int ret;
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
+ int virq = regmap_irq_get_virq(mc13xxx->irq_data, irq);
- if (irq < 0 || irq >= MC13XXX_NUM_IRQ || !mc13xxx->irqhandler[irq] ||
- mc13xxx->irqdata[irq] != dev)
- return -EINVAL;
-
- ret = mc13xxx_irq_mask(mc13xxx, irq);
- if (ret)
- return ret;
-
- mc13xxx->irqhandler[irq] = NULL;
- mc13xxx->irqdata[irq] = NULL;
+ devm_free_irq(mc13xxx->dev, virq, dev);
return 0;
}
EXPORT_SYMBOL(mc13xxx_irq_free);
-static inline irqreturn_t mc13xxx_irqhandler(struct mc13xxx *mc13xxx, int irq)
-{
- return mc13xxx->irqhandler[irq](irq, mc13xxx->irqdata[irq]);
-}
-
-/*
- * returns: number of handled irqs or negative error
- * locking: holds mc13xxx->lock
- */
-static int mc13xxx_irq_handle(struct mc13xxx *mc13xxx,
- unsigned int offstat, unsigned int offmask, int baseirq)
-{
- u32 stat, mask;
- int ret = mc13xxx_reg_read(mc13xxx, offstat, &stat);
- int num_handled = 0;
-
- if (ret)
- return ret;
-
- ret = mc13xxx_reg_read(mc13xxx, offmask, &mask);
- if (ret)
- return ret;
-
- while (stat & ~mask) {
- int irq = __ffs(stat & ~mask);
-
- stat &= ~(1 << irq);
-
- if (likely(mc13xxx->irqhandler[baseirq + irq])) {
- irqreturn_t handled;
-
- handled = mc13xxx_irqhandler(mc13xxx, baseirq + irq);
- if (handled == IRQ_HANDLED)
- num_handled++;
- } else {
- dev_err(mc13xxx->dev,
- "BUG: irq %u but no handler\n",
- baseirq + irq);
-
- mask |= 1 << irq;
-
- ret = mc13xxx_reg_write(mc13xxx, offmask, mask);
- }
- }
-
- return num_handled;
-}
-
-static irqreturn_t mc13xxx_irq_thread(int irq, void *data)
-{
- struct mc13xxx *mc13xxx = data;
- irqreturn_t ret;
- int handled = 0;
-
- mc13xxx_lock(mc13xxx);
-
- ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT0,
- MC13XXX_IRQMASK0, 0);
- if (ret > 0)
- handled = 1;
-
- ret = mc13xxx_irq_handle(mc13xxx, MC13XXX_IRQSTAT1,
- MC13XXX_IRQMASK1, 24);
- if (ret > 0)
- handled = 1;
-
- mc13xxx_unlock(mc13xxx);
-
- return IRQ_RETVAL(handled);
-}
-
#define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask))
static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision)
{
@@ -475,8 +242,6 @@ static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
{
struct mc13xxx_adcdone_data *adcdone_data = data;
- mc13xxx_irq_ack(adcdone_data->mc13xxx, irq);
-
complete_all(&adcdone_data->done);
return IRQ_HANDLED;
@@ -544,7 +309,6 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
mc13xxx_handler_adcdone, __func__, &adcdone_data);
- mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE);
mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
@@ -599,7 +363,8 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
if (!cell.name)
return -ENOMEM;
- return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);
+ return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0,
+ regmap_irq_get_domain(mc13xxx->irq_data));
}
static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
@@ -640,8 +405,8 @@ int mc13xxx_common_init(struct device *dev)
{
struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
- int ret;
u32 revision;
+ int i, ret;
mc13xxx->dev = dev;
@@ -651,31 +416,32 @@ int mc13xxx_common_init(struct device *dev)
mc13xxx->variant->print_revision(mc13xxx, revision);
- /* mask all irqs */
- ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
- if (ret)
- return ret;
+ for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) {
+ mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG;
+ mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG);
+ }
- ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff);
+ mc13xxx->irq_chip.name = dev_name(dev);
+ mc13xxx->irq_chip.status_base = MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.mask_base = MC13XXX_IRQMASK0;
+ mc13xxx->irq_chip.ack_base = MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0;
+ mc13xxx->irq_chip.init_ack_masked = true;
+ mc13xxx->irq_chip.use_ack = true;
+ mc13xxx->irq_chip.num_regs = MC13XXX_IRQ_REG_CNT;
+ mc13xxx->irq_chip.irqs = mc13xxx->irqs;
+ mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);
+
+ ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
+ 0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
if (ret)
return ret;
mutex_init(&mc13xxx->lock);
- ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
- IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
- if (ret)
- return ret;
-
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
mc13xxx->flags = pdata->flags;
- if (mc13xxx->flags & MC13XXX_USE_ADC)
- mc13xxx_add_subdevice(mc13xxx, "%s-adc");
-
- if (mc13xxx->flags & MC13XXX_USE_RTC)
- mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
-
if (pdata) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators, sizeof(pdata->regulators));
@@ -699,6 +465,12 @@ int mc13xxx_common_init(struct device *dev)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
}
+ if (mc13xxx->flags & MC13XXX_USE_ADC)
+ mc13xxx_add_subdevice(mc13xxx, "%s-adc");
+
+ if (mc13xxx->flags & MC13XXX_USE_RTC)
+ mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
+
return 0;
}
EXPORT_SYMBOL_GPL(mc13xxx_common_init);
@@ -707,8 +479,8 @@ int mc13xxx_common_exit(struct device *dev)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
- free_irq(mc13xxx->irq, mc13xxx);
mfd_remove_devices(dev);
+ regmap_del_irq_chip(mc13xxx->irq, mc13xxx->irq_data);
mutex_destroy(&mc13xxx->lock);
return 0;
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h
index ae7f1659f5d1..33677d1dcf66 100644
--- a/drivers/mfd/mc13xxx.h
+++ b/drivers/mfd/mc13xxx.h
@@ -13,7 +13,9 @@
#include <linux/regmap.h>
#include <linux/mfd/mc13xxx.h>
-#define MC13XXX_NUMREGS 0x3f
+#define MC13XXX_NUMREGS 0x3f
+#define MC13XXX_IRQ_REG_CNT 2
+#define MC13XXX_IRQ_PER_REG 24
struct mc13xxx;
@@ -33,13 +35,14 @@ struct mc13xxx {
struct device *dev;
const struct mc13xxx_variant *variant;
+ struct regmap_irq irqs[MC13XXX_IRQ_PER_REG * MC13XXX_IRQ_REG_CNT];
+ struct regmap_irq_chip irq_chip;
+ struct regmap_irq_chip_data *irq_data;
+
struct mutex lock;
int irq;
int flags;
- irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
- void *irqdata[MC13XXX_NUM_IRQ];
-
int adcflags;
};
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 62e5e3617eb0..7f5066e39752 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -137,6 +137,7 @@ EXPORT_SYMBOL(mcp_reg_read);
void mcp_enable(struct mcp *mcp)
{
unsigned long flags;
+
spin_lock_irqsave(&mcp->lock, flags);
if (mcp->use_count++ == 0)
mcp->ops->enable(mcp);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index b48d80c367f9..33a9234b701c 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
for (i = 0; i < omap->nports; i++) {
if (is_ehci_phy_mode(pdata->port_mode[i])) {
- reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
break;
}
}
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index d280d789e55a..28cb048f4760 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -25,52 +25,6 @@
#include <linux/mfd/palmas.h>
#include <linux/of_device.h>
-#define PALMAS_EXT_REQ (PALMAS_EXT_CONTROL_ENABLE1 | \
- PALMAS_EXT_CONTROL_ENABLE2 | \
- PALMAS_EXT_CONTROL_NSLEEP)
-
-struct palmas_sleep_requestor_info {
- int id;
- int reg_offset;
- int bit_pos;
-};
-
-#define EXTERNAL_REQUESTOR(_id, _offset, _pos) \
- [PALMAS_EXTERNAL_REQSTR_ID_##_id] = { \
- .id = PALMAS_EXTERNAL_REQSTR_ID_##_id, \
- .reg_offset = _offset, \
- .bit_pos = _pos, \
- }
-
-static struct palmas_sleep_requestor_info sleep_req_info[] = {
- EXTERNAL_REQUESTOR(REGEN1, 0, 0),
- EXTERNAL_REQUESTOR(REGEN2, 0, 1),
- EXTERNAL_REQUESTOR(SYSEN1, 0, 2),
- EXTERNAL_REQUESTOR(SYSEN2, 0, 3),
- EXTERNAL_REQUESTOR(CLK32KG, 0, 4),
- EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5),
- EXTERNAL_REQUESTOR(REGEN3, 0, 6),
- EXTERNAL_REQUESTOR(SMPS12, 1, 0),
- EXTERNAL_REQUESTOR(SMPS3, 1, 1),
- EXTERNAL_REQUESTOR(SMPS45, 1, 2),
- EXTERNAL_REQUESTOR(SMPS6, 1, 3),
- EXTERNAL_REQUESTOR(SMPS7, 1, 4),
- EXTERNAL_REQUESTOR(SMPS8, 1, 5),
- EXTERNAL_REQUESTOR(SMPS9, 1, 6),
- EXTERNAL_REQUESTOR(SMPS10, 1, 7),
- EXTERNAL_REQUESTOR(LDO1, 2, 0),
- EXTERNAL_REQUESTOR(LDO2, 2, 1),
- EXTERNAL_REQUESTOR(LDO3, 2, 2),
- EXTERNAL_REQUESTOR(LDO4, 2, 3),
- EXTERNAL_REQUESTOR(LDO5, 2, 4),
- EXTERNAL_REQUESTOR(LDO6, 2, 5),
- EXTERNAL_REQUESTOR(LDO7, 2, 6),
- EXTERNAL_REQUESTOR(LDO8, 2, 7),
- EXTERNAL_REQUESTOR(LDO9, 3, 0),
- EXTERNAL_REQUESTOR(LDOLN, 3, 1),
- EXTERNAL_REQUESTOR(LDOUSB, 3, 2),
-};
-
static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
{
.reg_bits = 8,
@@ -92,6 +46,133 @@ static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
},
};
+static const struct regmap_irq tps65917_irqs[] = {
+ /* INT1 IRQs */
+ [TPS65917_RESERVED1] = {
+ .mask = TPS65917_RESERVED,
+ },
+ [TPS65917_PWRON_IRQ] = {
+ .mask = TPS65917_INT1_STATUS_PWRON,
+ },
+ [TPS65917_LONG_PRESS_KEY_IRQ] = {
+ .mask = TPS65917_INT1_STATUS_LONG_PRESS_KEY,
+ },
+ [TPS65917_RESERVED2] = {
+ .mask = TPS65917_RESERVED,
+ },
+ [TPS65917_PWRDOWN_IRQ] = {
+ .mask = TPS65917_INT1_STATUS_PWRDOWN,
+ },
+ [TPS65917_HOTDIE_IRQ] = {
+ .mask = TPS65917_INT1_STATUS_HOTDIE,
+ },
+ [TPS65917_VSYS_MON_IRQ] = {
+ .mask = TPS65917_INT1_STATUS_VSYS_MON,
+ },
+ [TPS65917_RESERVED3] = {
+ .mask = TPS65917_RESERVED,
+ },
+ /* INT2 IRQs*/
+ [TPS65917_RESERVED4] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 1,
+ },
+ [TPS65917_OTP_ERROR_IRQ] = {
+ .mask = TPS65917_INT2_STATUS_OTP_ERROR,
+ .reg_offset = 1,
+ },
+ [TPS65917_WDT_IRQ] = {
+ .mask = TPS65917_INT2_STATUS_WDT,
+ .reg_offset = 1,
+ },
+ [TPS65917_RESERVED5] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 1,
+ },
+ [TPS65917_RESET_IN_IRQ] = {
+ .mask = TPS65917_INT2_STATUS_RESET_IN,
+ .reg_offset = 1,
+ },
+ [TPS65917_FSD_IRQ] = {
+ .mask = TPS65917_INT2_STATUS_FSD,
+ .reg_offset = 1,
+ },
+ [TPS65917_SHORT_IRQ] = {
+ .mask = TPS65917_INT2_STATUS_SHORT,
+ .reg_offset = 1,
+ },
+ [TPS65917_RESERVED6] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 1,
+ },
+ /* INT3 IRQs */
+ [TPS65917_GPADC_AUTO_0_IRQ] = {
+ .mask = TPS65917_INT3_STATUS_GPADC_AUTO_0,
+ .reg_offset = 2,
+ },
+ [TPS65917_GPADC_AUTO_1_IRQ] = {
+ .mask = TPS65917_INT3_STATUS_GPADC_AUTO_1,
+ .reg_offset = 2,
+ },
+ [TPS65917_GPADC_EOC_SW_IRQ] = {
+ .mask = TPS65917_INT3_STATUS_GPADC_EOC_SW,
+ .reg_offset = 2,
+ },
+ [TPS65917_RESREVED6] = {
+ .mask = TPS65917_RESERVED6,
+ .reg_offset = 2,
+ },
+ [TPS65917_RESERVED7] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 2,
+ },
+ [TPS65917_RESERVED8] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 2,
+ },
+ [TPS65917_RESERVED9] = {
+ .mask = TPS65917_RESERVED,
+ .reg_offset = 2,
+ },
+ [TPS65917_VBUS_IRQ] = {
+ .mask = TPS65917_INT3_STATUS_VBUS,
+ .reg_offset = 2,
+ },
+ /* INT4 IRQs */
+ [TPS65917_GPIO_0_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_0,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_1_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_1,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_2_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_2,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_3_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_3,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_4_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_4,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_5_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_5,
+ .reg_offset = 3,
+ },
+ [TPS65917_GPIO_6_IRQ] = {
+ .mask = TPS65917_INT4_STATUS_GPIO_6,
+ .reg_offset = 3,
+ },
+ [TPS65917_RESERVED10] = {
+ .mask = TPS65917_RESERVED10,
+ .reg_offset = 3,
+ },
+};
+
static const struct regmap_irq palmas_irqs[] = {
/* INT1 IRQs */
[PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = {
@@ -232,13 +313,26 @@ static struct regmap_irq_chip palmas_irq_chip = {
PALMAS_INT1_MASK),
};
+static struct regmap_irq_chip tps65917_irq_chip = {
+ .name = "tps65917",
+ .irqs = tps65917_irqs,
+ .num_irqs = ARRAY_SIZE(tps65917_irqs),
+
+ .num_regs = 4,
+ .irq_reg_stride = 5,
+ .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+ PALMAS_INT1_STATUS),
+ .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE,
+ PALMAS_INT1_MASK),
+};
+
int palmas_ext_control_req_config(struct palmas *palmas,
enum palmas_external_requestor_id id, int ext_ctrl, bool enable)
{
+ struct palmas_pmic_driver_data *pmic_ddata = palmas->pmic_ddata;
int preq_mask_bit = 0;
int reg_add = 0;
- int bit_pos;
- int ret;
+ int bit_pos, ret;
if (!(ext_ctrl & PALMAS_EXT_REQ))
return 0;
@@ -257,8 +351,8 @@ int palmas_ext_control_req_config(struct palmas *palmas,
preq_mask_bit = 2;
}
- bit_pos = sleep_req_info[id].bit_pos;
- reg_add += sleep_req_info[id].reg_offset;
+ bit_pos = pmic_ddata->sleep_req_info[id].bit_pos;
+ reg_add += pmic_ddata->sleep_req_info[id].reg_offset;
if (enable)
ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
reg_add, BIT(bit_pos), BIT(bit_pos));
@@ -357,14 +451,38 @@ static void palmas_power_off(void)
static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
static unsigned int tps659038_features;
+struct palmas_driver_data {
+ unsigned int *features;
+ struct regmap_irq_chip *irq_chip;
+};
+
+static struct palmas_driver_data palmas_data = {
+ .features = &palmas_features,
+ .irq_chip = &palmas_irq_chip,
+};
+
+static struct palmas_driver_data tps659038_data = {
+ .features = &tps659038_features,
+ .irq_chip = &palmas_irq_chip,
+};
+
+static struct palmas_driver_data tps65917_data = {
+ .features = &tps659038_features,
+ .irq_chip = &tps65917_irq_chip,
+};
+
static const struct of_device_id of_palmas_match_tbl[] = {
{
.compatible = "ti,palmas",
- .data = &palmas_features,
+ .data = &palmas_data,
},
{
.compatible = "ti,tps659038",
- .data = &tps659038_features,
+ .data = &tps659038_data,
+ },
+ {
+ .compatible = "ti,tps65917",
+ .data = &tps65917_data,
},
{ },
};
@@ -375,9 +493,10 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
{
struct palmas *palmas;
struct palmas_platform_data *pdata;
+ struct palmas_driver_data *driver_data;
struct device_node *node = i2c->dev.of_node;
int ret = 0, i;
- unsigned int reg, addr, *features;
+ unsigned int reg, addr;
int slave;
const struct of_device_id *match;
@@ -408,8 +527,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
if (!match)
return -ENODATA;
- features = (unsigned int *)match->data;
- palmas->features = *features;
+ driver_data = (struct palmas_driver_data *)match->data;
+ palmas->features = *driver_data->features;
for (i = 0; i < PALMAS_NUM_CLIENTS; i++) {
if (i == 0)
@@ -463,8 +582,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
regmap_write(palmas->regmap[slave], addr, reg);
ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
- IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip,
- &palmas->irq_data);
+ IRQF_ONESHOT | pdata->irq_flags, 0,
+ driver_data->irq_chip, &palmas->irq_data);
if (ret < 0)
goto err_i2c;
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 41ab5e34d2ac..c87f7a0a53f8 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -244,20 +244,20 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
struct platform_device *pdev;
+ int j;
pdev = platform_device_alloc("pcf50633-regulator", i);
- if (!pdev) {
- dev_err(pcf->dev, "Cannot create regulator %d\n", i);
- continue;
- }
+ if (!pdev)
+ return -ENOMEM;
pdev->dev.parent = pcf->dev;
- if (platform_device_add_data(pdev, &pdata->reg_init_data[i],
- sizeof(pdata->reg_init_data[i])) < 0) {
+ ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
+ sizeof(pdata->reg_init_data[i]));
+ if (ret) {
platform_device_put(pdev);
- dev_err(pcf->dev, "Out of memory for regulator parameters %d\n",
- i);
- continue;
+ for (j = 0; j < i; j++)
+ platform_device_put(pcf->regulator_pdev[j]);
+ return ret;
}
pcf->regulator_pdev[i] = pdev;
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 959513803542..39904f77c049 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -186,11 +186,9 @@ static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
- int irq_bit;
u8 block, config;
block = pmirq / 8;
- irq_bit = pmirq % 8;
config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
pm8xxx_config_irq(chip, block, config);
@@ -200,11 +198,9 @@ static void pm8xxx_irq_unmask(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
- int irq_bit;
u8 block, config;
block = pmirq / 8;
- irq_bit = pmirq % 8;
config = chip->config[pmirq];
pm8xxx_config_irq(chip, block, config);
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 1d15735f9ef9..d01b8c249231 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -337,40 +337,64 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
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;
+ int err = 0, count;
dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+ count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
+ if (count < 1)
+ return -EINVAL;
+ dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+
+ err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
+
+ rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read)
+{
+ enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- /* 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;
- }
+ return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
- count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
- if (count < 1) {
- dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
+void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read)
+{
+ enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
+
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int count, bool read, int timeout)
+{
+ struct completion trans_done;
+ struct scatterlist *sg;
+ dma_addr_t addr;
+ long timeleft;
+ unsigned long flags;
+ unsigned int len;
+ int i, err = 0;
+ u32 val;
+ u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
+
+ if (pcr->remove_pci)
+ return -ENODEV;
+
+ if ((sglist == NULL) || (count < 1))
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;
@@ -400,12 +424,10 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
}
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:
@@ -413,8 +435,6 @@ out:
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);
@@ -423,7 +443,7 @@ out:
return err;
}
-EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
{
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
index 6352bec8419a..71f387ce8cbd 100644
--- a/drivers/mfd/rtsx_usb.c
+++ b/drivers/mfd/rtsx_usb.c
@@ -744,6 +744,7 @@ static struct usb_device_id rtsx_usb_usb_ids[] = {
{ USB_DEVICE(0x0BDA, 0x0140) },
{ }
};
+MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
static struct usb_driver rtsx_usb_driver = {
.name = "rtsx_usb",
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index be06d0abbf19..dba7e2b6f8e9 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -28,8 +28,10 @@
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
+#include <linux/regulator/machine.h>
#include <linux/regmap.h>
static const struct mfd_cell s5m8751_devs[] = {
@@ -89,6 +91,15 @@ static const struct mfd_cell s2mpa01_devs[] = {
},
};
+static const struct mfd_cell s2mpu02_devs[] = {
+ { .name = "s2mpu02-pmic", },
+ { .name = "s2mpu02-rtc", },
+ {
+ .name = "s2mpu02-clk",
+ .of_compatible = "samsung,s2mpu02-clk",
+ }
+};
+
#ifdef CONFIG_OF
static const struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic",
@@ -103,6 +114,9 @@ static const struct of_device_id sec_dt_match[] = {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
+ .compatible = "samsung,s2mpu02-pmic",
+ .data = (void *)S2MPU02,
+ }, {
/* Sentinel */
},
};
@@ -132,6 +146,18 @@ static bool s2mps11_volatile(struct device *dev, unsigned int reg)
}
}
+static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case S2MPU02_REG_INT1M:
+ case S2MPU02_REG_INT2M:
+ case S2MPU02_REG_INT3M:
+ return false;
+ default:
+ return true;
+ }
+}
+
static bool s5m8763_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -177,6 +203,15 @@ static const struct regmap_config s2mps14_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config s2mpu02_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S2MPU02_REG_DVSDATA,
+ .volatile_reg = s2mpu02_volatile,
+ .cache_type = REGCACHE_FLAT,
+};
+
static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -238,6 +273,7 @@ static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c,
#ifdef CONFIG_OF
if (i2c->dev.of_node) {
const struct of_device_id *match;
+
match = of_match_node(sec_dt_match, i2c->dev.of_node);
return (unsigned long)match->data;
}
@@ -250,9 +286,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
{
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
const struct regmap_config *regmap;
+ const struct mfd_cell *sec_devs;
struct sec_pmic_dev *sec_pmic;
unsigned long device_type;
- int ret;
+ int ret, num_sec_devs;
sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
GFP_KERNEL);
@@ -297,6 +334,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
+ case S2MPU02:
+ regmap = &s2mpu02_regmap_config;
+ break;
default:
regmap = &sec_regmap_config;
break;
@@ -319,34 +359,39 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S5M8751X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
- ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
+ sec_devs = s5m8751_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8751_devs);
break;
case S5M8763X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
- ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
+ sec_devs = s5m8763_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8763_devs);
break;
case S5M8767X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
- ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
+ sec_devs = s5m8767_devs;
+ num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
case S2MPA01:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
- ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
+ sec_devs = s2mpa01_devs;
+ num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
break;
case S2MPS11X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
- ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
+ sec_devs = s2mps11_devs;
+ num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS14X:
- ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
- ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
+ sec_devs = s2mps14_devs;
+ num_sec_devs = ARRAY_SIZE(s2mps14_devs);
+ break;
+ case S2MPU02:
+ sec_devs = s2mpu02_devs;
+ num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
break;
default:
/* If this happens the probe function is problem */
BUG();
}
-
+ ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
+ 0, NULL);
if (ret)
goto err_mfd;
@@ -387,6 +432,15 @@ static int sec_pmic_suspend(struct device *dev)
*/
disable_irq(sec_pmic->irq);
+ switch (sec_pmic->device_type) {
+ case S2MPS14X:
+ case S2MPU02:
+ regulator_suspend_prepare(PM_SUSPEND_MEM);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 654e2c1dbf7a..f9a57869e3ec 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -20,6 +20,7 @@
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
@@ -161,6 +162,77 @@ static const struct regmap_irq s2mps14_irqs[] = {
},
};
+static const struct regmap_irq s2mpu02_irqs[] = {
+ [S2MPU02_IRQ_PWRONF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRONF_MASK,
+ },
+ [S2MPU02_IRQ_PWRONR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRONR_MASK,
+ },
+ [S2MPU02_IRQ_JIGONBF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_JIGONBF_MASK,
+ },
+ [S2MPU02_IRQ_JIGONBR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_JIGONBR_MASK,
+ },
+ [S2MPU02_IRQ_ACOKBF] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_ACOKBF_MASK,
+ },
+ [S2MPU02_IRQ_ACOKBR] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_ACOKBR_MASK,
+ },
+ [S2MPU02_IRQ_PWRON1S] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_PWRON1S_MASK,
+ },
+ [S2MPU02_IRQ_MRB] = {
+ .reg_offset = 0,
+ .mask = S2MPS11_IRQ_MRB_MASK,
+ },
+ [S2MPU02_IRQ_RTC60S] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTC60S_MASK,
+ },
+ [S2MPU02_IRQ_RTCA1] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTCA1_MASK,
+ },
+ [S2MPU02_IRQ_RTCA0] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTCA0_MASK,
+ },
+ [S2MPU02_IRQ_SMPL] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_SMPL_MASK,
+ },
+ [S2MPU02_IRQ_RTC1S] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_RTC1S_MASK,
+ },
+ [S2MPU02_IRQ_WTSR] = {
+ .reg_offset = 1,
+ .mask = S2MPS11_IRQ_WTSR_MASK,
+ },
+ [S2MPU02_IRQ_INT120C] = {
+ .reg_offset = 2,
+ .mask = S2MPS11_IRQ_INT120C_MASK,
+ },
+ [S2MPU02_IRQ_INT140C] = {
+ .reg_offset = 2,
+ .mask = S2MPS11_IRQ_INT140C_MASK,
+ },
+ [S2MPU02_IRQ_TSD] = {
+ .reg_offset = 2,
+ .mask = S2MPS14_IRQ_TSD_MASK,
+ },
+};
+
static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
@@ -327,6 +399,16 @@ static const struct regmap_irq_chip s2mps14_irq_chip = {
.ack_base = S2MPS14_REG_INT1,
};
+static const struct regmap_irq_chip s2mpu02_irq_chip = {
+ .name = "s2mpu02",
+ .irqs = s2mpu02_irqs,
+ .num_irqs = ARRAY_SIZE(s2mpu02_irqs),
+ .num_regs = 3,
+ .status_base = S2MPU02_REG_INT1,
+ .mask_base = S2MPU02_REG_INT1M,
+ .ack_base = S2MPU02_REG_INT1,
+};
+
static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irqs = s5m8767_irqs,
@@ -351,6 +433,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
int type = sec_pmic->device_type;
+ const struct regmap_irq_chip *sec_irq_chip;
if (!sec_pmic->irq) {
dev_warn(sec_pmic->dev,
@@ -361,28 +444,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
switch (type) {
case S5M8763X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s5m8763_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s5m8763_irq_chip;
break;
case S5M8767X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s5m8767_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s5m8767_irq_chip;
break;
case S2MPS11X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s2mps11_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s2mps11_irq_chip;
break;
case S2MPS14X:
- ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- sec_pmic->irq_base, &s2mps14_irq_chip,
- &sec_pmic->irq_data);
+ sec_irq_chip = &s2mps14_irq_chip;
+ break;
+ case S2MPU02:
+ sec_irq_chip = &s2mpu02_irq_chip;
break;
default:
dev_err(sec_pmic->dev, "Unknown device type %lu\n",
@@ -390,6 +464,10 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return -EINVAL;
}
+ ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ sec_pmic->irq_base, sec_irq_chip,
+ &sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
diff --git a/drivers/mfd/si476x-cmd.c b/drivers/mfd/si476x-cmd.c
index 6f1ef63086c9..2086b4665288 100644
--- a/drivers/mfd/si476x-cmd.c
+++ b/drivers/mfd/si476x-cmd.c
@@ -1228,8 +1228,8 @@ static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
}
static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
- struct si476x_rsq_status_args *rsqargs,
- struct si476x_rsq_status_report *report)
+ struct si476x_rsq_status_args *rsqargs,
+ struct si476x_rsq_status_report *report)
{
int err;
u8 resp[CMD_FM_RSQ_STATUS_A10_NRESP];
@@ -1434,10 +1434,10 @@ typedef int (*tune_freq_func_t) (struct si476x_core *core,
struct si476x_tune_freq_args *tuneargs);
static struct {
- int (*power_up) (struct si476x_core *,
- struct si476x_power_up_args *);
- int (*power_down) (struct si476x_core *,
- struct si476x_power_down_args *);
+ int (*power_up)(struct si476x_core *,
+ struct si476x_power_up_args *);
+ int (*power_down)(struct si476x_core *,
+ struct si476x_power_down_args *);
tune_freq_func_t fm_tune_freq;
tune_freq_func_t am_tune_freq;
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index a45f9c0a330a..5c054031c3f8 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(of, stmpe_of_match);
static int
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
- int partnum;
+ enum stmpe_partnum partnum;
const struct of_device_id *of_id;
i2c_ci.data = (void *)id;
@@ -85,7 +85,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
dev_info(&i2c->dev, "matching on node name, compatible is preferred\n");
partnum = id->driver_data;
} else
- partnum = (int)of_id->data;
+ partnum = (enum stmpe_partnum)of_id->data;
return stmpe_probe(&i2c_ci, partnum);
}
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 3b6bfa7184ad..02a17c388e87 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1147,7 +1147,7 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
}
/* Called from client specific probe routines */
-int stmpe_probe(struct stmpe_client_info *ci, int partnum)
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
{
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
struct device_node *np = ci->dev->of_node;
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index 9e4d21d37a11..2d045f26f193 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -97,7 +97,7 @@ struct stmpe_client_info {
void (*init)(struct stmpe *stmpe);
};
-int stmpe_probe(struct stmpe_client_info *ci, int partnum);
+int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum);
int stmpe_remove(struct stmpe *stmpe);
#define STMPE_ICR_LSB_HIGH (1 << 2)
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
index 718fc4d2adc0..283ab8d197e4 100644
--- a/drivers/mfd/sun6i-prcm.c
+++ b/drivers/mfd/sun6i-prcm.c
@@ -76,16 +76,46 @@ static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
},
};
+static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
+ {
+ .name = "sun8i-a23-apb0-clk",
+ .of_compatible = "allwinner,sun8i-a23-apb0-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
+ .resources = sun6i_a31_apb0_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-gates-clk",
+ .of_compatible = "allwinner,sun8i-a23-apb0-gates-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
+ .resources = sun6i_a31_apb0_gates_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-clock-reset",
+ .of_compatible = "allwinner,sun6i-a31-clock-reset",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
+ .resources = sun6i_a31_apb0_rstc_res,
+ },
+};
+
static const struct prcm_data sun6i_a31_prcm_data = {
.nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
.subdevs = sun6i_a31_prcm_subdevs,
};
+static const struct prcm_data sun8i_a23_prcm_data = {
+ .nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs),
+ .subdevs = sun8i_a23_prcm_subdevs,
+};
+
static const struct of_device_id sun6i_prcm_dt_ids[] = {
{
.compatible = "allwinner,sun6i-a31-prcm",
.data = &sun6i_a31_prcm_data,
},
+ {
+ .compatible = "allwinner,sun8i-a23-prcm",
+ .data = &sun8i_a23_prcm_data,
+ },
{ /* sentinel */ },
};
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index bd83accc0f6d..0072e668c208 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -236,7 +236,7 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
static struct irq_domain_ops tc3589x_irq_ops = {
.map = tc3589x_irq_map,
.unmap = tc3589x_irq_unmap,
- .xlate = irq_domain_xlate_twocell,
+ .xlate = irq_domain_xlate_onecell,
};
static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 591a331d8d83..e71f88000ae5 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -147,11 +147,10 @@ static int tc6387xb_probe(struct platform_device *dev)
int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!iomem) {
+ if (!iomem)
return -EINVAL;
- }
- tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
+ tc6387xb = kzalloc(sizeof(*tc6387xb), GFP_KERNEL);
if (!tc6387xb)
return -ENOMEM;
@@ -189,7 +188,7 @@ static int tc6387xb_probe(struct platform_device *dev)
if (pdata && pdata->enable)
pdata->enable(dev);
- printk(KERN_INFO "Toshiba tc6387xb initialised\n");
+ dev_info(&dev->dev, "Toshiba tc6387xb initialised\n");
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index b5dfa6e4e692..5de95c265c1a 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -141,7 +141,7 @@ static int tps6105x_probe(struct i2c_client *client,
int ret;
int i;
- tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
+ tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
if (!tps6105x)
return -ENOMEM;
@@ -154,7 +154,7 @@ static int tps6105x_probe(struct i2c_client *client,
ret = tps6105x_startup(tps6105x);
if (ret) {
dev_err(&client->dev, "chip initialization failed\n");
- goto fail;
+ return ret;
}
/* Remove warning texts when you implement new cell drivers */
@@ -187,16 +187,8 @@ static int tps6105x_probe(struct i2c_client *client,
tps6105x_cells[i].pdata_size = sizeof(*tps6105x);
}
- ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
- ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
- if (ret)
- goto fail;
-
- return 0;
-
-fail:
- kfree(tps6105x);
- return ret;
+ return mfd_add_devices(&client->dev, 0, tps6105x_cells,
+ ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
}
static int tps6105x_remove(struct i2c_client *client)
@@ -210,7 +202,6 @@ static int tps6105x_remove(struct i2c_client *client)
TPS6105X_REG0_MODE_MASK,
TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
- kfree(tps6105x);
return 0;
}
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index f9e42ea1cb1a..f243e75d28f3 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -387,7 +387,7 @@ static const struct of_device_id tps65910_of_match[] = {
MODULE_DEVICE_TABLE(of, tps65910_of_match);
static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
- int *chip_id)
+ unsigned long *chip_id)
{
struct device_node *np = client->dev.of_node;
struct tps65910_board *board_info;
@@ -401,7 +401,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
return NULL;
}
- *chip_id = (int)match->data;
+ *chip_id = (unsigned long)match->data;
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL);
@@ -431,7 +431,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
#else
static inline
struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
- int *chip_id)
+ unsigned long *chip_id)
{
return NULL;
}
@@ -453,14 +453,14 @@ static void tps65910_power_off(void)
}
static int tps65910_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct tps65910 *tps65910;
struct tps65910_board *pmic_plat_data;
struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data;
+ unsigned long chip_id = id->driver_data;
int ret = 0;
- int chip_id = id->driver_data;
pmic_plat_data = dev_get_platdata(&i2c->dev);
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index 69a5178bf152..de60ad98bd9f 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -32,10 +32,9 @@ static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
unsigned long spi_data = 1 << 23 | addr << 15 | *data;
struct spi_transfer xfer;
struct spi_message msg;
- u32 tx_buf, rx_buf;
+ u32 tx_buf;
tx_buf = spi_data;
- rx_buf = 0;
xfer.tx_buf = &tx_buf;
xfer.rx_buf = NULL;
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 596b1f657e21..b1dabba763cf 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -297,7 +297,7 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
REG_PIH_ISR_P1);
if (ret) {
- pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
+ pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret);
return IRQ_NONE;
}
@@ -338,7 +338,7 @@ static int twl4030_init_sih_modules(unsigned line)
irq_line = line;
/* disable all interrupts on our line */
- memset(buf, 0xff, sizeof buf);
+ memset(buf, 0xff, sizeof(buf));
sih = sih_modules;
for (i = 0; i < nr_sih_modules; i++, sih++) {
/* skip USB -- it's funky */
@@ -646,7 +646,7 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
if (status < 0)
return status;
- agent = kzalloc(sizeof *agent, GFP_KERNEL);
+ agent = kzalloc(sizeof(*agent), GFP_KERNEL);
if (!agent)
return -ENOMEM;
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index a6bb17d908b8..2807e1a95663 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -70,7 +70,7 @@ static int twl6030_interrupt_mapping[24] = {
BATDETECT_INTR_OFFSET, /* Bit 9 BAT */
SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */
MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
- RSV_INTR_OFFSET, /* Bit 12 Reserved */
+ RSV_INTR_OFFSET, /* Bit 12 Reserved */
MADC_INTR_OFFSET, /* Bit 13 GPADC_RT_EOC */
MADC_INTR_OFFSET, /* Bit 14 GPADC_SW_EOC */
GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
@@ -245,6 +245,7 @@ int twl6030_interrupt_unmask(u8 bit_mask, u8 offset)
{
int ret;
u8 unmask_value;
+
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &unmask_value,
REG_INT_STS_A + offset);
unmask_value &= (~(bit_mask));
@@ -258,6 +259,7 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset)
{
int ret;
u8 mask_value;
+
ret = twl_i2c_read_u8(TWL_MODULE_PIH, &mask_value,
REG_INT_STS_A + offset);
mask_value |= (bit_mask);
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index ae26d84b3a59..f9c06c542a41 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -700,7 +700,7 @@ static int twl6040_probe(struct i2c_client *client,
}
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
- 0, &twl6040_irq_chip,&twl6040->irq_data);
+ 0, &twl6040_irq_chip, &twl6040->irq_data);
if (ret < 0)
goto gpio_err;
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index c8a993bd17ae..fb4d4bb0f47d 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -138,11 +138,11 @@ static const struct regmap_irq wm5102_irqs[ARIZONA_NUM_IRQ] = {
.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 41a7f6fb7802..9b98ee559188 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -340,11 +340,11 @@ static const struct regmap_irq wm5110_irqs[ARIZONA_NUM_IRQ] = {
.reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -416,16 +416,28 @@ static const struct regmap_irq wm5110_irqs[ARIZONA_NUM_IRQ] = {
[ARIZONA_IRQ_ISRC2_CFG_ERR] = {
.reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1
},
+ [ARIZONA_IRQ_HP3R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+ },
[ARIZONA_IRQ_BOOT_DONE] = {
.reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
},
- [ARIZONA_IRQ_DCS_DAC_DONE] = {
- .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1
- },
- [ARIZONA_IRQ_DCS_HP_DONE] = {
- .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1
- },
[ARIZONA_IRQ_FLL2_CLOCK_OK] = {
.reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
},
@@ -445,6 +457,209 @@ const struct regmap_irq_chip wm5110_irq = {
};
EXPORT_SYMBOL_GPL(wm5110_irq);
+static const struct regmap_irq wm5110_revd_irqs[ARIZONA_NUM_IRQ] = {
+ [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 },
+ [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 },
+ [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
+ [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
+
+ [ARIZONA_IRQ_DSP4_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP4_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP3_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP3_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP2_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP2_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP1_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP1_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ8] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ8_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ7] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ7_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ6] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ6_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ5] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ5_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ4] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ4_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ3] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ3_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ2] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ1] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
+ },
+
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
+ },
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
+ },
+ [ARIZONA_IRQ_HPDET] = {
+ .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
+ },
+ [ARIZONA_IRQ_MICDET] = {
+ .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1
+ },
+ [ARIZONA_IRQ_WSEQ_DONE] = {
+ .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1
+ },
+ [ARIZONA_IRQ_DRC2_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_DRC1_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_ASRC2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_ASRC1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_UNDERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_OVERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1
+ },
+
+ [ARIZONA_IRQ_CTRLIF_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_CTRLIF_ERR_EINT1
+ },
+ [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_MIXER_DROPPED_SAMPLE_EINT1
+ },
+ [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ASYNC_CLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_SYSCLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_SYSCLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_ISRC1_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC1_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC2_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC2_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC3_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC3_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP3L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP2L_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+ },
+
+ [ARIZONA_IRQ_BOOT_DONE] = {
+ .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
+ },
+ [ARIZONA_IRQ_ASRC_CFG_ERR] = {
+ .reg_offset = 4, .mask = ARIZONA_V2_ASRC_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1
+ },
+
+ [ARIZONA_IRQ_DSP_SHARED_WR_COLL] = {
+ .reg_offset = 5, .mask = ARIZONA_DSP_SHARED_WR_COLL_EINT1
+ },
+ [ARIZONA_IRQ_SPK_SHUTDOWN] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ },
+ [ARIZONA_IRQ_SPK1R_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1R_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_SPK1L_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1L_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP3R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP3L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP3L_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP2R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP2L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP2L_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1R_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_SC_NEG] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1L_SC_NEG_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1L_SC_POS_EINT1
+ },
+};
+
+const struct regmap_irq_chip wm5110_revd_irq = {
+ .name = "wm5110 IRQ",
+ .status_base = ARIZONA_INTERRUPT_STATUS_1,
+ .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK,
+ .ack_base = ARIZONA_INTERRUPT_STATUS_1,
+ .num_regs = 6,
+ .irqs = wm5110_revd_irqs,
+ .num_irqs = ARRAY_SIZE(wm5110_revd_irqs),
+};
+EXPORT_SYMBOL_GPL(wm5110_revd_irq);
+
static const struct reg_default wm5110_reg_default[] = {
{ 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */
{ 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */
@@ -1274,12 +1489,14 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */
{ 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */
{ 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */
+ { 0x00000D0D, 0xFFFF }, /* R3341 - Interrupt Status 6 Mask */
{ 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */
{ 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */
{ 0x00000D19, 0xFFFF }, /* R3353 - IRQ2 Status 2 Mask */
{ 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */
{ 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */
{ 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */
+ { 0x00000D1D, 0xFFFF }, /* R3357 - IRQ2 Status 6 Mask */
{ 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */
{ 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */
{ 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */
@@ -2311,22 +2528,26 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_STATUS_3:
case ARIZONA_INTERRUPT_STATUS_4:
case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
case ARIZONA_INTERRUPT_STATUS_1_MASK:
case ARIZONA_INTERRUPT_STATUS_2_MASK:
case ARIZONA_INTERRUPT_STATUS_3_MASK:
case ARIZONA_INTERRUPT_STATUS_4_MASK:
case ARIZONA_INTERRUPT_STATUS_5_MASK:
+ case ARIZONA_INTERRUPT_STATUS_6_MASK:
case ARIZONA_INTERRUPT_CONTROL:
case ARIZONA_IRQ2_STATUS_1:
case ARIZONA_IRQ2_STATUS_2:
case ARIZONA_IRQ2_STATUS_3:
case ARIZONA_IRQ2_STATUS_4:
case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
case ARIZONA_IRQ2_STATUS_1_MASK:
case ARIZONA_IRQ2_STATUS_2_MASK:
case ARIZONA_IRQ2_STATUS_3_MASK:
case ARIZONA_IRQ2_STATUS_4_MASK:
case ARIZONA_IRQ2_STATUS_5_MASK:
+ case ARIZONA_IRQ2_STATUS_6_MASK:
case ARIZONA_IRQ2_CONTROL:
case ARIZONA_INTERRUPT_RAW_STATUS_2:
case ARIZONA_INTERRUPT_RAW_STATUS_3:
@@ -2335,6 +2556,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_RAW_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_7:
case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
case ARIZONA_IRQ_PIN_STATUS:
case ARIZONA_AOD_WKUP_AND_TRIG:
case ARIZONA_AOD_IRQ1:
@@ -2610,11 +2832,13 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_STATUS_3:
case ARIZONA_INTERRUPT_STATUS_4:
case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
case ARIZONA_IRQ2_STATUS_1:
case ARIZONA_IRQ2_STATUS_2:
case ARIZONA_IRQ2_STATUS_3:
case ARIZONA_IRQ2_STATUS_4:
case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_2:
case ARIZONA_INTERRUPT_RAW_STATUS_3:
case ARIZONA_INTERRUPT_RAW_STATUS_4:
@@ -2622,6 +2846,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_RAW_STATUS_6:
case ARIZONA_INTERRUPT_RAW_STATUS_7:
case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
case ARIZONA_IRQ_PIN_STATUS:
case ARIZONA_AOD_WKUP_AND_TRIG:
case ARIZONA_AOD_IRQ1:
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index f919def05e24..6a16a8a6f9fa 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -58,10 +58,10 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8350_i2c_id[] = {
- { "wm8350", 0 },
- { "wm8351", 0 },
- { "wm8352", 0 },
- { }
+ { "wm8350", 0 },
+ { "wm8351", 0 },
+ { "wm8352", 0 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index cd01f7962dfd..813ff50f95b6 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -497,7 +497,8 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
if (pdata && pdata->irq_base > 0)
irq_base = pdata->irq_base;
- wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
+ wm8350->irq_base =
+ irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
if (wm8350->irq_base < 0) {
dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
wm8350->irq_base);
diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c
index 2fbce9c5950b..770a25696468 100644
--- a/drivers/mfd/wm8994-regmap.c
+++ b/drivers/mfd/wm8994-regmap.c
@@ -123,14 +123,23 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
{ 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
{ 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
{ 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
{ 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
{ 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0431, 0x0068 }, /* R1073 - AIF1 DAC2 Noise Gate */
{ 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
{ 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
{ 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
{ 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
{ 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
{ 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
{ 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
{ 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
@@ -152,6 +161,27 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
{ 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
{ 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x04B4, 0x0000 }, /* R1204 - AIF1 DAC2 EQ Band 1 C */
{ 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
{ 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
{ 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
@@ -194,6 +224,8 @@ static struct reg_default wm1811_defaults[] = {
{ 0x0605, 0x0000 }, /* R1541 - AIF2ADC Right Mixer Routing */
{ 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
{ 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right Mixer Routing */
{ 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
{ 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
{ 0x0612, 0x02C0 }, /* R1554 - AIF2TX Left Volume */
@@ -846,14 +878,23 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_AIF1_DAC1_LEFT_VOLUME:
case WM8994_AIF1_DAC1_RIGHT_VOLUME:
case WM8994_AIF1_ADC1_FILTERS:
+ case WM8994_AIF1_ADC2_FILTERS:
case WM8994_AIF1_DAC1_FILTERS_1:
case WM8994_AIF1_DAC1_FILTERS_2:
+ case WM8994_AIF1_DAC2_FILTERS_1:
+ case WM8994_AIF1_DAC2_FILTERS_2:
case WM8958_AIF1_DAC1_NOISE_GATE:
+ case WM8958_AIF1_DAC2_NOISE_GATE:
case WM8994_AIF1_DRC1_1:
case WM8994_AIF1_DRC1_2:
case WM8994_AIF1_DRC1_3:
case WM8994_AIF1_DRC1_4:
case WM8994_AIF1_DRC1_5:
+ case WM8994_AIF1_DRC2_1:
+ case WM8994_AIF1_DRC2_2:
+ case WM8994_AIF1_DRC2_3:
+ case WM8994_AIF1_DRC2_4:
+ case WM8994_AIF1_DRC2_5:
case WM8994_AIF1_DAC1_EQ_GAINS_1:
case WM8994_AIF1_DAC1_EQ_GAINS_2:
case WM8994_AIF1_DAC1_EQ_BAND_1_A:
@@ -875,6 +916,27 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_AIF1_DAC1_EQ_BAND_5_B:
case WM8994_AIF1_DAC1_EQ_BAND_5_PG:
case WM8994_AIF1_DAC1_EQ_BAND_1_C:
+ case WM8994_AIF1_DAC2_EQ_GAINS_1:
+ case WM8994_AIF1_DAC2_EQ_GAINS_2:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_C:
case WM8994_AIF2_ADC_LEFT_VOLUME:
case WM8994_AIF2_ADC_RIGHT_VOLUME:
case WM8994_AIF2_DAC_LEFT_VOLUME:
@@ -917,6 +979,8 @@ static bool wm1811_readable_register(struct device *dev, unsigned int reg)
case WM8994_DAC2_RIGHT_MIXER_ROUTING:
case WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING:
case WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING:
case WM8994_DAC1_LEFT_VOLUME:
case WM8994_DAC1_RIGHT_VOLUME:
case WM8994_DAC2_LEFT_VOLUME:
diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c
index c7a81da64ee1..510da3b52324 100644
--- a/drivers/mfd/wm8997-tables.c
+++ b/drivers/mfd/wm8997-tables.c
@@ -65,11 +65,11 @@ static const struct regmap_irq wm8997_irqs[ARIZONA_NUM_IRQ] = {
[ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
[ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
- [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
},
- [ARIZONA_IRQ_SPK_SHUTDOWN] = {
- .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
},
[ARIZONA_IRQ_HPDET] = {
.reg_offset = 2, .mask = ARIZONA_HPDET_EINT1
@@ -174,10 +174,10 @@ static const struct reg_default wm8997_reg_default[] = {
{ 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */
{ 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */
{ 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */
- { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 3 */
- { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
- { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
- { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
+ { 0x00000068, 0x01FF }, /* R104 - AlwaysOn Triggers Seq Select 3 */
+ { 0x00000069, 0x01FF }, /* R105 - AlwaysOn Triggers Seq Select 4 */
+ { 0x0000006A, 0x01FF }, /* R106 - AlwaysOn Triggers Seq Select 5 */
+ { 0x0000006B, 0x01FF }, /* R107 - AlwaysOn Triggers Seq Select 6 */
{ 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ee9402324a23..b841180c7c74 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -51,16 +51,6 @@ config AD525X_DPOT_SPI
To compile this driver as a module, choose M here: the
module will be called ad525x_dpot-spi.
-config ATMEL_PWM
- tristate "Atmel AT32/AT91 PWM support"
- depends on HAVE_CLK
- depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
- help
- This option enables device driver support for the PWM channels
- on certain Atmel processors. Pulse Width Modulation is used for
- purposes including software controlled power-efficient backlights
- on LCD displays, motor control, and waveform generation.
-
config ATMEL_TCLIB
bool "Atmel AT32/AT91 Timer/Counter Library"
depends on (AVR32 || ARCH_AT91)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d59ce1261b38..5497d026e651 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
obj-$(CONFIG_INTEL_MID_PTI) += pti.o
-obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
obj-$(CONFIG_BMP085) += bmp085.o
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 22de13727641..60843a275abd 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -83,10 +83,17 @@ EXPORT_SYMBOL(ssc_free);
static struct atmel_ssc_platform_data at91rm9200_config = {
.use_dma = 0,
+ .has_fslen_ext = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9rl_config = {
+ .use_dma = 0,
+ .has_fslen_ext = 1,
};
static struct atmel_ssc_platform_data at91sam9g45_config = {
.use_dma = 1,
+ .has_fslen_ext = 1,
};
static const struct platform_device_id atmel_ssc_devtypes[] = {
@@ -94,6 +101,9 @@ static const struct platform_device_id atmel_ssc_devtypes[] = {
.name = "at91rm9200_ssc",
.driver_data = (unsigned long) &at91rm9200_config,
}, {
+ .name = "at91sam9rl_ssc",
+ .driver_data = (unsigned long) &at91sam9rl_config,
+ }, {
.name = "at91sam9g45_ssc",
.driver_data = (unsigned long) &at91sam9g45_config,
}, {
@@ -107,6 +117,9 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
.compatible = "atmel,at91rm9200-ssc",
.data = &at91rm9200_config,
}, {
+ .compatible = "atmel,at91sam9rl-ssc",
+ .data = &at91sam9rl_config,
+ }, {
.compatible = "atmel,at91sam9g45-ssc",
.data = &at91sam9g45_config,
}, {
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
deleted file mode 100644
index a6dc56e1bc58..000000000000
--- a/drivers/misc/atmel_pwm.c
+++ /dev/null
@@ -1,402 +0,0 @@
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/atmel_pwm.h>
-
-
-/*
- * This is a simple driver for the PWM controller found in various newer
- * Atmel SOCs, including the AVR32 series and the AT91sam9263.
- *
- * Chips with current Linux ports have only 4 PWM channels, out of max 32.
- * AT32UC3A and AT32UC3B chips have 7 channels (but currently no Linux).
- * Docs are inconsistent about the width of the channel counter registers;
- * it's at least 16 bits, but several places say 20 bits.
- */
-#define PWM_NCHAN 4 /* max 32 */
-
-struct pwm {
- spinlock_t lock;
- struct platform_device *pdev;
- u32 mask;
- int irq;
- void __iomem *base;
- struct clk *clk;
- struct pwm_channel *channel[PWM_NCHAN];
- void (*handler[PWM_NCHAN])(struct pwm_channel *);
-};
-
-
-/* global PWM controller registers */
-#define PWM_MR 0x00
-#define PWM_ENA 0x04
-#define PWM_DIS 0x08
-#define PWM_SR 0x0c
-#define PWM_IER 0x10
-#define PWM_IDR 0x14
-#define PWM_IMR 0x18
-#define PWM_ISR 0x1c
-
-static inline void pwm_writel(const struct pwm *p, unsigned offset, u32 val)
-{
- __raw_writel(val, p->base + offset);
-}
-
-static inline u32 pwm_readl(const struct pwm *p, unsigned offset)
-{
- return __raw_readl(p->base + offset);
-}
-
-static inline void __iomem *pwmc_regs(const struct pwm *p, int index)
-{
- return p->base + 0x200 + index * 0x20;
-}
-
-static struct pwm *pwm;
-
-static void pwm_dumpregs(struct pwm_channel *ch, char *tag)
-{
- struct device *dev = &pwm->pdev->dev;
-
- dev_dbg(dev, "%s: mr %08x, sr %08x, imr %08x\n",
- tag,
- pwm_readl(pwm, PWM_MR),
- pwm_readl(pwm, PWM_SR),
- pwm_readl(pwm, PWM_IMR));
- dev_dbg(dev,
- "pwm ch%d - mr %08x, dty %u, prd %u, cnt %u\n",
- ch->index,
- pwm_channel_readl(ch, PWM_CMR),
- pwm_channel_readl(ch, PWM_CDTY),
- pwm_channel_readl(ch, PWM_CPRD),
- pwm_channel_readl(ch, PWM_CCNT));
-}
-
-
-/**
- * pwm_channel_alloc - allocate an unused PWM channel
- * @index: identifies the channel
- * @ch: structure to be initialized
- *
- * Drivers allocate PWM channels according to the board's wiring, and
- * matching board-specific setup code. Returns zero or negative errno.
- */
-int pwm_channel_alloc(int index, struct pwm_channel *ch)
-{
- unsigned long flags;
- int status = 0;
-
- if (!pwm)
- return -EPROBE_DEFER;
-
- if (!(pwm->mask & 1 << index))
- return -ENODEV;
-
- if (index < 0 || index >= PWM_NCHAN || !ch)
- return -EINVAL;
- memset(ch, 0, sizeof *ch);
-
- spin_lock_irqsave(&pwm->lock, flags);
- if (pwm->channel[index])
- status = -EBUSY;
- else {
- clk_enable(pwm->clk);
-
- ch->regs = pwmc_regs(pwm, index);
- ch->index = index;
-
- /* REVISIT: ap7000 seems to go 2x as fast as we expect!! */
- ch->mck = clk_get_rate(pwm->clk);
-
- pwm->channel[index] = ch;
- pwm->handler[index] = NULL;
-
- /* channel and irq are always disabled when we return */
- pwm_writel(pwm, PWM_DIS, 1 << index);
- pwm_writel(pwm, PWM_IDR, 1 << index);
- }
- spin_unlock_irqrestore(&pwm->lock, flags);
- return status;
-}
-EXPORT_SYMBOL(pwm_channel_alloc);
-
-static int pwmcheck(struct pwm_channel *ch)
-{
- int index;
-
- if (!pwm)
- return -ENODEV;
- if (!ch)
- return -EINVAL;
- index = ch->index;
- if (index < 0 || index >= PWM_NCHAN || pwm->channel[index] != ch)
- return -EINVAL;
-
- return index;
-}
-
-/**
- * pwm_channel_free - release a previously allocated channel
- * @ch: the channel being released
- *
- * The channel is completely shut down (counter and IRQ disabled),
- * and made available for re-use. Returns zero, or negative errno.
- */
-int pwm_channel_free(struct pwm_channel *ch)
-{
- unsigned long flags;
- int t;
-
- spin_lock_irqsave(&pwm->lock, flags);
- t = pwmcheck(ch);
- if (t >= 0) {
- pwm->channel[t] = NULL;
- pwm->handler[t] = NULL;
-
- /* channel and irq are always disabled when we return */
- pwm_writel(pwm, PWM_DIS, 1 << t);
- pwm_writel(pwm, PWM_IDR, 1 << t);
-
- clk_disable(pwm->clk);
- t = 0;
- }
- spin_unlock_irqrestore(&pwm->lock, flags);
- return t;
-}
-EXPORT_SYMBOL(pwm_channel_free);
-
-int __pwm_channel_onoff(struct pwm_channel *ch, int enabled)
-{
- unsigned long flags;
- int t;
-
- /* OMITTED FUNCTIONALITY: starting several channels in synch */
-
- spin_lock_irqsave(&pwm->lock, flags);
- t = pwmcheck(ch);
- if (t >= 0) {
- pwm_writel(pwm, enabled ? PWM_ENA : PWM_DIS, 1 << t);
- t = 0;
- pwm_dumpregs(ch, enabled ? "enable" : "disable");
- }
- spin_unlock_irqrestore(&pwm->lock, flags);
-
- return t;
-}
-EXPORT_SYMBOL(__pwm_channel_onoff);
-
-/**
- * pwm_clk_alloc - allocate and configure CLKA or CLKB
- * @prescale: from 0..10, the power of two used to divide MCK
- * @div: from 1..255, the linear divisor to use
- *
- * Returns PWM_CPR_CLKA, PWM_CPR_CLKB, or negative errno. The allocated
- * clock will run with a period of (2^prescale * div) / MCK, or twice as
- * long if center aligned PWM output is used. The clock must later be
- * deconfigured using pwm_clk_free().
- */
-int pwm_clk_alloc(unsigned prescale, unsigned div)
-{
- unsigned long flags;
- u32 mr;
- u32 val = (prescale << 8) | div;
- int ret = -EBUSY;
-
- if (prescale >= 10 || div == 0 || div > 255)
- return -EINVAL;
-
- spin_lock_irqsave(&pwm->lock, flags);
- mr = pwm_readl(pwm, PWM_MR);
- if ((mr & 0xffff) == 0) {
- mr |= val;
- ret = PWM_CPR_CLKA;
- } else if ((mr & (0xffff << 16)) == 0) {
- mr |= val << 16;
- ret = PWM_CPR_CLKB;
- }
- if (ret > 0)
- pwm_writel(pwm, PWM_MR, mr);
- spin_unlock_irqrestore(&pwm->lock, flags);
- return ret;
-}
-EXPORT_SYMBOL(pwm_clk_alloc);
-
-/**
- * pwm_clk_free - deconfigure and release CLKA or CLKB
- *
- * Reverses the effect of pwm_clk_alloc().
- */
-void pwm_clk_free(unsigned clk)
-{
- unsigned long flags;
- u32 mr;
-
- spin_lock_irqsave(&pwm->lock, flags);
- mr = pwm_readl(pwm, PWM_MR);
- if (clk == PWM_CPR_CLKA)
- pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 0));
- if (clk == PWM_CPR_CLKB)
- pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 16));
- spin_unlock_irqrestore(&pwm->lock, flags);
-}
-EXPORT_SYMBOL(pwm_clk_free);
-
-/**
- * pwm_channel_handler - manage channel's IRQ handler
- * @ch: the channel
- * @handler: the handler to use, possibly NULL
- *
- * If the handler is non-null, the handler will be called after every
- * period of this PWM channel. If the handler is null, this channel
- * won't generate an IRQ.
- */
-int pwm_channel_handler(struct pwm_channel *ch,
- void (*handler)(struct pwm_channel *ch))
-{
- unsigned long flags;
- int t;
-
- spin_lock_irqsave(&pwm->lock, flags);
- t = pwmcheck(ch);
- if (t >= 0) {
- pwm->handler[t] = handler;
- pwm_writel(pwm, handler ? PWM_IER : PWM_IDR, 1 << t);
- t = 0;
- }
- spin_unlock_irqrestore(&pwm->lock, flags);
-
- return t;
-}
-EXPORT_SYMBOL(pwm_channel_handler);
-
-static irqreturn_t pwm_irq(int id, void *_pwm)
-{
- struct pwm *p = _pwm;
- irqreturn_t handled = IRQ_NONE;
- u32 irqstat;
- int index;
-
- spin_lock(&p->lock);
-
- /* ack irqs, then handle them */
- irqstat = pwm_readl(pwm, PWM_ISR);
-
- while (irqstat) {
- struct pwm_channel *ch;
- void (*handler)(struct pwm_channel *ch);
-
- index = ffs(irqstat) - 1;
- irqstat &= ~(1 << index);
- ch = pwm->channel[index];
- handler = pwm->handler[index];
- if (handler && ch) {
- spin_unlock(&p->lock);
- handler(ch);
- spin_lock(&p->lock);
- handled = IRQ_HANDLED;
- }
- }
-
- spin_unlock(&p->lock);
- return handled;
-}
-
-static int __init pwm_probe(struct platform_device *pdev)
-{
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- int irq = platform_get_irq(pdev, 0);
- u32 *mp = pdev->dev.platform_data;
- struct pwm *p;
- int status = -EIO;
-
- if (pwm)
- return -EBUSY;
- if (!r || irq < 0 || !mp || !*mp)
- return -ENODEV;
- if (*mp & ~((1<<PWM_NCHAN)-1)) {
- dev_warn(&pdev->dev, "mask 0x%x ... more than %d channels\n",
- *mp, PWM_NCHAN);
- return -EINVAL;
- }
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
-
- spin_lock_init(&p->lock);
- p->pdev = pdev;
- p->mask = *mp;
- p->irq = irq;
- p->base = ioremap(r->start, resource_size(r));
- if (!p->base)
- goto fail;
- p->clk = clk_get(&pdev->dev, "pwm_clk");
- if (IS_ERR(p->clk)) {
- status = PTR_ERR(p->clk);
- p->clk = NULL;
- goto fail;
- }
-
- status = request_irq(irq, pwm_irq, 0, pdev->name, p);
- if (status < 0)
- goto fail;
-
- pwm = p;
- platform_set_drvdata(pdev, p);
-
- return 0;
-
-fail:
- if (p->clk)
- clk_put(p->clk);
- if (p->base)
- iounmap(p->base);
-
- kfree(p);
- return status;
-}
-
-static int __exit pwm_remove(struct platform_device *pdev)
-{
- struct pwm *p = platform_get_drvdata(pdev);
-
- if (p != pwm)
- return -EINVAL;
-
- clk_enable(pwm->clk);
- pwm_writel(pwm, PWM_DIS, (1 << PWM_NCHAN) - 1);
- pwm_writel(pwm, PWM_IDR, (1 << PWM_NCHAN) - 1);
- clk_disable(pwm->clk);
-
- pwm = NULL;
-
- free_irq(p->irq, p);
- clk_put(p->clk);
- iounmap(p->base);
- kfree(p);
-
- return 0;
-}
-
-static struct platform_driver atmel_pwm_driver = {
- .driver = {
- .name = "atmel_pwm",
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(pwm_remove),
-
- /* NOTE: PWM can keep running in AVR32 "idle" and "frozen" states;
- * and all AT91sam9263 states, albeit at reduced clock rate if
- * MCK becomes the slow clock (i.e. what Linux labels STR).
- */
-};
-
-module_platform_driver_probe(atmel_pwm_driver, pwm_probe);
-
-MODULE_DESCRIPTION("Driver for AT32/AT91 PWM module");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:atmel_pwm");
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 99a04686e45f..7b55f8a152d4 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1185,7 +1185,7 @@ static int bh1770_probe(struct i2c_client *client,
struct bh1770_chip *chip;
int err;
- chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ chip = devm_kzalloc(&client->dev, sizeof *chip, GFP_KERNEL);
if (!chip)
return -ENOMEM;
@@ -1198,8 +1198,7 @@ static int bh1770_probe(struct i2c_client *client,
if (client->dev.platform_data == NULL) {
dev_err(&client->dev, "platform data is mandatory\n");
- err = -EINVAL;
- goto fail1;
+ return -EINVAL;
}
chip->pdata = client->dev.platform_data;
@@ -1224,24 +1223,24 @@ static int bh1770_probe(struct i2c_client *client,
chip->regs[0].supply = reg_vcc;
chip->regs[1].supply = reg_vleds;
- err = regulator_bulk_get(&client->dev,
- ARRAY_SIZE(chip->regs), chip->regs);
+ err = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(chip->regs), chip->regs);
if (err < 0) {
dev_err(&client->dev, "Cannot get regulators\n");
- goto fail1;
+ return err;
}
err = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
chip->regs);
if (err < 0) {
dev_err(&client->dev, "Cannot enable regulators\n");
- goto fail2;
+ return err;
}
usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
err = bh1770_detect(chip);
if (err < 0)
- goto fail3;
+ goto fail0;
/* Start chip */
bh1770_chip_on(chip);
@@ -1252,14 +1251,14 @@ static int bh1770_probe(struct i2c_client *client,
if (chip->lux_corr == 0) {
dev_err(&client->dev, "Improper correction values\n");
err = -EINVAL;
- goto fail3;
+ goto fail0;
}
if (chip->pdata->setup_resources) {
err = chip->pdata->setup_resources();
if (err) {
err = -EINVAL;
- goto fail3;
+ goto fail0;
}
}
@@ -1267,7 +1266,7 @@ static int bh1770_probe(struct i2c_client *client,
&bh1770_attribute_group);
if (err < 0) {
dev_err(&chip->client->dev, "Sysfs registration failed\n");
- goto fail4;
+ goto fail1;
}
/*
@@ -1283,22 +1282,18 @@ static int bh1770_probe(struct i2c_client *client,
if (err) {
dev_err(&client->dev, "could not get IRQ %d\n",
client->irq);
- goto fail5;
+ goto fail2;
}
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
return err;
-fail5:
+fail2:
sysfs_remove_group(&chip->client->dev.kobj,
&bh1770_attribute_group);
-fail4:
+fail1:
if (chip->pdata->release_resources)
chip->pdata->release_resources();
-fail3:
+fail0:
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
-fail2:
- regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
-fail1:
- kfree(chip);
return err;
}
@@ -1322,8 +1317,6 @@ static int bh1770_remove(struct i2c_client *client)
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
- regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
- kfree(chip);
return 0;
}
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 48ea33d15a79..4c4a59b25537 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -149,50 +149,35 @@ static int bh1780_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
- struct bh1780_data *ddata = NULL;
+ struct bh1780_data *ddata;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
- ret = -EIO;
- goto err_op_failed;
- }
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+ return -EIO;
- ddata = kzalloc(sizeof(struct bh1780_data), GFP_KERNEL);
- if (ddata == NULL) {
- ret = -ENOMEM;
- goto err_op_failed;
- }
+ ddata = devm_kzalloc(&client->dev, sizeof(struct bh1780_data),
+ GFP_KERNEL);
+ if (ddata == NULL)
+ return -ENOMEM;
ddata->client = client;
i2c_set_clientdata(client, ddata);
ret = bh1780_read(ddata, BH1780_REG_PARTID, "PART ID");
if (ret < 0)
- goto err_op_failed;
+ return ret;
dev_info(&client->dev, "Ambient Light Sensor, Rev : %d\n",
(ret & BH1780_REVMASK));
mutex_init(&ddata->lock);
- ret = sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
- if (ret)
- goto err_op_failed;
-
- return 0;
-
-err_op_failed:
- kfree(ddata);
- return ret;
+ return sysfs_create_group(&client->dev.kobj, &bh1780_attr_group);
}
static int bh1780_remove(struct i2c_client *client)
{
- struct bh1780_data *ddata;
-
- ddata = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group);
- kfree(ddata);
return 0;
}
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 14d90eae605b..55e913b7eb11 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -954,10 +954,7 @@ static int data_debugfs_init(struct fpga_device *priv)
{
priv->dbg_entry = debugfs_create_file(drv_name, S_IRUGO, NULL, priv,
&data_debug_fops);
- if (IS_ERR(priv->dbg_entry))
- return PTR_ERR(priv->dbg_entry);
-
- return 0;
+ return PTR_ERR_OR_ZERO(priv->dbg_entry);
}
static void data_debugfs_exit(struct fpga_device *priv)
diff --git a/drivers/misc/dummy-irq.c b/drivers/misc/dummy-irq.c
index 4d0db15df115..acbbe0390be4 100644
--- a/drivers/misc/dummy-irq.c
+++ b/drivers/misc/dummy-irq.c
@@ -61,3 +61,4 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiri Kosina");
module_param(irq, uint, 0444);
MODULE_PARM_DESC(irq, "The IRQ to register for");
+MODULE_DESCRIPTION("Dummy IRQ handler driver");
diff --git a/drivers/misc/fuse/Makefile b/drivers/misc/fuse/Makefile
new file mode 100644
index 000000000000..0679c4febc89
--- /dev/null
+++ b/drivers/misc/fuse/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/misc/genwqe/Kconfig b/drivers/misc/genwqe/Kconfig
index 6069d8cd79d7..4c0a033cbfdb 100644
--- a/drivers/misc/genwqe/Kconfig
+++ b/drivers/misc/genwqe/Kconfig
@@ -11,3 +11,9 @@ menuconfig GENWQE
Enables PCIe card driver for IBM GenWQE accelerators.
The user-space interface is described in
include/linux/genwqe/genwqe_card.h.
+
+config GENWQE_PLATFORM_ERROR_RECOVERY
+ int "Use platform recovery procedures (0=off, 1=on)"
+ depends on GENWQE
+ default 1 if PPC64
+ default 0
diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c
index 74d51c9bb858..43bbabc96b6c 100644
--- a/drivers/misc/genwqe/card_base.c
+++ b/drivers/misc/genwqe/card_base.c
@@ -38,7 +38,6 @@
#include <linux/notifier.h>
#include <linux/device.h>
#include <linux/log2.h>
-#include <linux/genwqe/genwqe_card.h>
#include "card_base.h"
#include "card_ddcb.h"
@@ -58,7 +57,7 @@ static struct dentry *debugfs_genwqe;
static struct genwqe_dev *genwqe_devices[GENWQE_CARD_NO_MAX];
/* PCI structure for identifying device by PCI vendor and device ID */
-static DEFINE_PCI_DEVICE_TABLE(genwqe_device_table) = {
+static const struct pci_device_id genwqe_device_table[] = {
{ .vendor = PCI_VENDOR_ID_IBM,
.device = PCI_DEVICE_GENWQE,
.subvendor = PCI_SUBVENDOR_ID_IBM,
@@ -140,6 +139,12 @@ static struct genwqe_dev *genwqe_dev_alloc(void)
cd->class_genwqe = class_genwqe;
cd->debugfs_genwqe = debugfs_genwqe;
+ /*
+ * This comes from kernel config option and can be overritten via
+ * debugfs.
+ */
+ cd->use_platform_recovery = CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY;
+
init_waitqueue_head(&cd->queue_waitq);
spin_lock_init(&cd->file_lock);
@@ -761,6 +766,124 @@ static u64 genwqe_fir_checking(struct genwqe_dev *cd)
}
/**
+ * genwqe_pci_fundamental_reset() - trigger a PCIe fundamental reset on the slot
+ *
+ * Note: pci_set_pcie_reset_state() is not implemented on all archs, so this
+ * reset method will not work in all cases.
+ *
+ * Return: 0 on success or error code from pci_set_pcie_reset_state()
+ */
+static int genwqe_pci_fundamental_reset(struct pci_dev *pci_dev)
+{
+ int rc;
+
+ /*
+ * lock pci config space access from userspace,
+ * save state and issue PCIe fundamental reset
+ */
+ pci_cfg_access_lock(pci_dev);
+ pci_save_state(pci_dev);
+ rc = pci_set_pcie_reset_state(pci_dev, pcie_warm_reset);
+ if (!rc) {
+ /* keep PCIe reset asserted for 250ms */
+ msleep(250);
+ pci_set_pcie_reset_state(pci_dev, pcie_deassert_reset);
+ /* Wait for 2s to reload flash and train the link */
+ msleep(2000);
+ }
+ pci_restore_state(pci_dev);
+ pci_cfg_access_unlock(pci_dev);
+ return rc;
+}
+
+
+static int genwqe_platform_recovery(struct genwqe_dev *cd)
+{
+ struct pci_dev *pci_dev = cd->pci_dev;
+ int rc;
+
+ dev_info(&pci_dev->dev,
+ "[%s] resetting card for error recovery\n", __func__);
+
+ /* Clear out error injection flags */
+ cd->err_inject &= ~(GENWQE_INJECT_HARDWARE_FAILURE |
+ GENWQE_INJECT_GFIR_FATAL |
+ GENWQE_INJECT_GFIR_INFO);
+
+ genwqe_stop(cd);
+
+ /* Try recoverying the card with fundamental reset */
+ rc = genwqe_pci_fundamental_reset(pci_dev);
+ if (!rc) {
+ rc = genwqe_start(cd);
+ if (!rc)
+ dev_info(&pci_dev->dev,
+ "[%s] card recovered\n", __func__);
+ else
+ dev_err(&pci_dev->dev,
+ "[%s] err: cannot start card services! (err=%d)\n",
+ __func__, rc);
+ } else {
+ dev_err(&pci_dev->dev,
+ "[%s] card reset failed\n", __func__);
+ }
+
+ return rc;
+}
+
+/*
+ * genwqe_reload_bistream() - reload card bitstream
+ *
+ * Set the appropriate register and call fundamental reset to reaload the card
+ * bitstream.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+static int genwqe_reload_bistream(struct genwqe_dev *cd)
+{
+ struct pci_dev *pci_dev = cd->pci_dev;
+ int rc;
+
+ dev_info(&pci_dev->dev,
+ "[%s] resetting card for bitstream reload\n",
+ __func__);
+
+ genwqe_stop(cd);
+
+ /*
+ * Cause a CPLD reprogram with the 'next_bitstream'
+ * partition on PCIe hot or fundamental reset
+ */
+ __genwqe_writeq(cd, IO_SLC_CFGREG_SOFTRESET,
+ (cd->softreset & 0xcull) | 0x70ull);
+
+ rc = genwqe_pci_fundamental_reset(pci_dev);
+ if (rc) {
+ /*
+ * A fundamental reset failure can be caused
+ * by lack of support on the arch, so we just
+ * log the error and try to start the card
+ * again.
+ */
+ dev_err(&pci_dev->dev,
+ "[%s] err: failed to reset card for bitstream reload\n",
+ __func__);
+ }
+
+ rc = genwqe_start(cd);
+ if (rc) {
+ dev_err(&pci_dev->dev,
+ "[%s] err: cannot start card services! (err=%d)\n",
+ __func__, rc);
+ return rc;
+ }
+ dev_info(&pci_dev->dev,
+ "[%s] card reloaded\n", __func__);
+ return 0;
+}
+
+
+/**
* genwqe_health_thread() - Health checking thread
*
* This thread is only started for the PF of the card.
@@ -786,6 +909,7 @@ static int genwqe_health_thread(void *data)
struct pci_dev *pci_dev = cd->pci_dev;
u64 gfir, gfir_masked, slu_unitcfg, app_unitcfg;
+ health_thread_begin:
while (!kthread_should_stop()) {
rc = wait_event_interruptible_timeout(cd->health_waitq,
(genwqe_health_check_cond(cd, &gfir) ||
@@ -846,6 +970,13 @@ static int genwqe_health_thread(void *data)
}
}
+ if (cd->card_state == GENWQE_CARD_RELOAD_BITSTREAM) {
+ /* Userspace requested card bitstream reload */
+ rc = genwqe_reload_bistream(cd);
+ if (rc)
+ goto fatal_error;
+ }
+
cd->last_gfir = gfir;
cond_resched();
}
@@ -853,6 +984,28 @@ static int genwqe_health_thread(void *data)
return 0;
fatal_error:
+ if (cd->use_platform_recovery) {
+ /*
+ * Since we use raw accessors, EEH errors won't be detected
+ * by the platform until we do a non-raw MMIO or config space
+ * read
+ */
+ readq(cd->mmio + IO_SLC_CFGREG_GFIR);
+
+ /* We do nothing if the card is going over PCI recovery */
+ if (pci_channel_offline(pci_dev))
+ return -EIO;
+
+ /*
+ * If it's supported by the platform, we try a fundamental reset
+ * to recover from a fatal error. Otherwise, we continue to wait
+ * for an external recovery procedure to take care of it.
+ */
+ rc = genwqe_platform_recovery(cd);
+ if (!rc)
+ goto health_thread_begin;
+ }
+
dev_err(&pci_dev->dev,
"[%s] card unusable. Please trigger unbind!\n", __func__);
@@ -958,6 +1111,9 @@ static int genwqe_pci_setup(struct genwqe_dev *cd)
pci_set_master(pci_dev);
pci_enable_pcie_error_reporting(pci_dev);
+ /* EEH recovery requires PCIe fundamental reset */
+ pci_dev->needs_freset = 1;
+
/* request complete BAR-0 space (length = 0) */
cd->mmio_len = pci_resource_len(pci_dev, 0);
cd->mmio = pci_iomap(pci_dev, 0, 0);
@@ -1096,23 +1252,40 @@ static pci_ers_result_t genwqe_err_error_detected(struct pci_dev *pci_dev,
dev_err(&pci_dev->dev, "[%s] state=%d\n", __func__, state);
- if (pci_dev == NULL)
- return PCI_ERS_RESULT_NEED_RESET;
-
cd = dev_get_drvdata(&pci_dev->dev);
if (cd == NULL)
- return PCI_ERS_RESULT_NEED_RESET;
+ return PCI_ERS_RESULT_DISCONNECT;
- switch (state) {
- case pci_channel_io_normal:
- return PCI_ERS_RESULT_CAN_RECOVER;
- case pci_channel_io_frozen:
- return PCI_ERS_RESULT_NEED_RESET;
- case pci_channel_io_perm_failure:
+ /* Stop the card */
+ genwqe_health_check_stop(cd);
+ genwqe_stop(cd);
+
+ /*
+ * On permanent failure, the PCI code will call device remove
+ * after the return of this function.
+ * genwqe_stop() can be called twice.
+ */
+ if (state == pci_channel_io_perm_failure) {
return PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ genwqe_pci_remove(cd);
+ return PCI_ERS_RESULT_NEED_RESET;
}
+}
+
+static pci_ers_result_t genwqe_err_slot_reset(struct pci_dev *pci_dev)
+{
+ int rc;
+ struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev);
- return PCI_ERS_RESULT_NEED_RESET;
+ rc = genwqe_pci_setup(cd);
+ if (!rc) {
+ return PCI_ERS_RESULT_RECOVERED;
+ } else {
+ dev_err(&pci_dev->dev,
+ "err: problems with PCI setup (err=%d)\n", rc);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
}
static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev)
@@ -1120,8 +1293,22 @@ static pci_ers_result_t genwqe_err_result_none(struct pci_dev *dev)
return PCI_ERS_RESULT_NONE;
}
-static void genwqe_err_resume(struct pci_dev *dev)
+static void genwqe_err_resume(struct pci_dev *pci_dev)
{
+ int rc;
+ struct genwqe_dev *cd = dev_get_drvdata(&pci_dev->dev);
+
+ rc = genwqe_start(cd);
+ if (!rc) {
+ rc = genwqe_health_check_start(cd);
+ if (rc)
+ dev_err(&pci_dev->dev,
+ "err: cannot start health checking! (err=%d)\n",
+ rc);
+ } else {
+ dev_err(&pci_dev->dev,
+ "err: cannot start card services! (err=%d)\n", rc);
+ }
}
static int genwqe_sriov_configure(struct pci_dev *dev, int numvfs)
@@ -1144,7 +1331,7 @@ static struct pci_error_handlers genwqe_err_handler = {
.error_detected = genwqe_err_error_detected,
.mmio_enabled = genwqe_err_result_none,
.link_reset = genwqe_err_result_none,
- .slot_reset = genwqe_err_result_none,
+ .slot_reset = genwqe_err_slot_reset,
.resume = genwqe_err_resume,
};
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h
index 0e608a288603..67abd8cb2247 100644
--- a/drivers/misc/genwqe/card_base.h
+++ b/drivers/misc/genwqe/card_base.h
@@ -291,6 +291,8 @@ struct genwqe_dev {
struct task_struct *health_thread;
wait_queue_head_t health_waitq;
+ int use_platform_recovery; /* use platform recovery mechanisms */
+
/* char device */
dev_t devnum_genwqe; /* major/minor num card */
struct class *class_genwqe; /* reference to class object */
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c
index c8046db2d5a2..dc9851a5540e 100644
--- a/drivers/misc/genwqe/card_ddcb.c
+++ b/drivers/misc/genwqe/card_ddcb.c
@@ -1118,7 +1118,21 @@ static irqreturn_t genwqe_pf_isr(int irq, void *dev_id)
* safer, but slower for the good-case ... See above.
*/
gfir = __genwqe_readq(cd, IO_SLC_CFGREG_GFIR);
- if ((gfir & GFIR_ERR_TRIGGER) != 0x0) {
+ if (((gfir & GFIR_ERR_TRIGGER) != 0x0) &&
+ !pci_channel_offline(pci_dev)) {
+
+ if (cd->use_platform_recovery) {
+ /*
+ * Since we use raw accessors, EEH errors won't be
+ * detected by the platform until we do a non-raw
+ * MMIO or config space read
+ */
+ readq(cd->mmio + IO_SLC_CFGREG_GFIR);
+
+ /* Don't do anything if the PCI channel is frozen */
+ if (pci_channel_offline(pci_dev))
+ goto exit;
+ }
wake_up_interruptible(&cd->health_waitq);
@@ -1126,12 +1140,12 @@ static irqreturn_t genwqe_pf_isr(int irq, void *dev_id)
* By default GFIRs causes recovery actions. This
* count is just for debug when recovery is masked.
*/
- printk_ratelimited(KERN_ERR
- "%s %s: [%s] GFIR=%016llx\n",
- GENWQE_DEVNAME, dev_name(&pci_dev->dev),
- __func__, gfir);
+ dev_err_ratelimited(&pci_dev->dev,
+ "[%s] GFIR=%016llx\n",
+ __func__, gfir);
}
+ exit:
return IRQ_HANDLED;
}
@@ -1237,9 +1251,7 @@ int genwqe_setup_service_layer(struct genwqe_dev *cd)
}
rc = genwqe_set_interrupt_capability(cd, GENWQE_MSI_IRQS);
- if (rc > 0)
- rc = genwqe_set_interrupt_capability(cd, rc);
- if (rc != 0) {
+ if (rc) {
rc = -ENODEV;
goto stop_kthread;
}
diff --git a/drivers/misc/genwqe/card_debugfs.c b/drivers/misc/genwqe/card_debugfs.c
index 0a33ade64109..c9b4d6d0eb99 100644
--- a/drivers/misc/genwqe/card_debugfs.c
+++ b/drivers/misc/genwqe/card_debugfs.c
@@ -485,6 +485,13 @@ int genwqe_init_debugfs(struct genwqe_dev *cd)
goto err1;
}
+ file = debugfs_create_u32("use_platform_recovery", 0666, root,
+ &cd->use_platform_recovery);
+ if (!file) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+
cd->debugfs_root = root;
return 0;
err1:
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 1d2f163a1906..aae42555e2ca 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -1048,10 +1048,15 @@ static long genwqe_ioctl(struct file *filp, unsigned int cmd,
int rc = 0;
struct genwqe_file *cfile = (struct genwqe_file *)filp->private_data;
struct genwqe_dev *cd = cfile->cd;
+ struct pci_dev *pci_dev = cd->pci_dev;
struct genwqe_reg_io __user *io;
u64 val;
u32 reg_offs;
+ /* Return -EIO if card hit EEH */
+ if (pci_channel_offline(pci_dev))
+ return -EIO;
+
if (_IOC_TYPE(cmd) != GENWQE_IOC_CODE)
return -EINVAL;
diff --git a/drivers/misc/genwqe/card_sysfs.c b/drivers/misc/genwqe/card_sysfs.c
index a72a99266c3c..7232e40a3ad9 100644
--- a/drivers/misc/genwqe/card_sysfs.c
+++ b/drivers/misc/genwqe/card_sysfs.c
@@ -223,6 +223,30 @@ static ssize_t next_bitstream_store(struct device *dev,
}
static DEVICE_ATTR_RW(next_bitstream);
+static ssize_t reload_bitstream_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int reload;
+ struct genwqe_dev *cd = dev_get_drvdata(dev);
+
+ if (kstrtoint(buf, 0, &reload) < 0)
+ return -EINVAL;
+
+ if (reload == 0x1) {
+ if (cd->card_state == GENWQE_CARD_UNUSED ||
+ cd->card_state == GENWQE_CARD_USED)
+ cd->card_state = GENWQE_CARD_RELOAD_BITSTREAM;
+ else
+ return -EIO;
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(reload_bitstream);
+
/*
* Create device_attribute structures / params: name, mode, show, store
* additional flag if valid in VF
@@ -239,6 +263,7 @@ static struct attribute *genwqe_attributes[] = {
&dev_attr_status.attr,
&dev_attr_freerunning_timer.attr,
&dev_attr_queue_working_time.attr,
+ &dev_attr_reload_bitstream.attr,
NULL,
};
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 62cc6bb3f62e..a6400f09229c 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -53,12 +53,17 @@
*/
int __genwqe_writeq(struct genwqe_dev *cd, u64 byte_offs, u64 val)
{
+ struct pci_dev *pci_dev = cd->pci_dev;
+
if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE)
return -EIO;
if (cd->mmio == NULL)
return -EIO;
+ if (pci_channel_offline(pci_dev))
+ return -EIO;
+
__raw_writeq((__force u64)cpu_to_be64(val), cd->mmio + byte_offs);
return 0;
}
@@ -99,12 +104,17 @@ u64 __genwqe_readq(struct genwqe_dev *cd, u64 byte_offs)
*/
int __genwqe_writel(struct genwqe_dev *cd, u64 byte_offs, u32 val)
{
+ struct pci_dev *pci_dev = cd->pci_dev;
+
if (cd->err_inject & GENWQE_INJECT_HARDWARE_FAILURE)
return -EIO;
if (cd->mmio == NULL)
return -EIO;
+ if (pci_channel_offline(pci_dev))
+ return -EIO;
+
__raw_writel((__force u32)cpu_to_be32(val), cd->mmio + byte_offs);
return 0;
}
@@ -718,10 +728,12 @@ int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count)
int rc;
struct pci_dev *pci_dev = cd->pci_dev;
- rc = pci_enable_msi_exact(pci_dev, count);
- if (rc == 0)
- cd->flags |= GENWQE_FLAG_MSI_ENABLED;
- return rc;
+ rc = pci_enable_msi_range(pci_dev, 1, count);
+ if (rc < 0)
+ return rc;
+
+ cd->flags |= GENWQE_FLAG_MSI_ENABLED;
+ return 0;
}
/**
diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h
index cd5263163a6e..a506e9aa2d57 100644
--- a/drivers/misc/genwqe/genwqe_driver.h
+++ b/drivers/misc/genwqe/genwqe_driver.h
@@ -36,7 +36,7 @@
#include <asm/byteorder.h>
#include <linux/genwqe/genwqe_card.h>
-#define DRV_VERS_STRING "2.0.15"
+#define DRV_VERS_STRING "2.0.21"
/*
* Static minor number assignement, until we decide/implement
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 06f6ad29ceff..3336ddca45ac 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -145,7 +145,6 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
union ioc4_int_out int_out;
union ioc4_gpcr gpcr;
unsigned int state, last_state = 1;
- struct timespec start_ts, end_ts;
uint64_t start, end, period;
unsigned int count = 0;
@@ -174,10 +173,10 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
if (!last_state && state) {
count++;
if (count == IOC4_CALIBRATE_END) {
- ktime_get_ts(&end_ts);
+ end = ktime_get_ns();
break;
} else if (count == IOC4_CALIBRATE_DISCARD)
- ktime_get_ts(&start_ts);
+ start = ktime_get_ns();
}
last_state = state;
} while (1);
@@ -192,8 +191,6 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
* by which the IOC4 generates the square wave, to get the
* period of an IOC4 INT_OUT count.
*/
- end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec;
- start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec;
period = (end - start) /
(IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1));
diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c
index 0a1565e63c71..7ffdb589841e 100644
--- a/drivers/misc/lattice-ecp3-config.c
+++ b/drivers/misc/lattice-ecp3-config.c
@@ -15,6 +15,7 @@
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
+#include <asm/unaligned.h>
#define FIRMWARE_NAME "lattice-ecp3.bit"
@@ -91,8 +92,8 @@ static void firmware_load(const struct firmware *fw, void *context)
/* Trying to speak with the FPGA via SPI... */
txbuf[0] = FPGA_CMD_READ_ID;
ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
- dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", *(u32 *)&rxbuf[4]);
- jedec_id = *(u32 *)&rxbuf[4];
+ jedec_id = get_unaligned_be32(&rxbuf[4]);
+ dev_dbg(&spi->dev, "FPGA JTAG ID=%08x\n", jedec_id);
for (i = 0; i < ARRAY_SIZE(ecp3_dev); i++) {
if (jedec_id == ecp3_dev[i].jedec_id)
@@ -109,7 +110,8 @@ static void firmware_load(const struct firmware *fw, void *context)
txbuf[0] = FPGA_CMD_READ_STATUS;
ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
- dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]);
+ status = get_unaligned_be32(&rxbuf[4]);
+ dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);
buffer = kzalloc(fw->size + 8, GFP_KERNEL);
if (!buffer) {
@@ -141,7 +143,7 @@ static void firmware_load(const struct firmware *fw, void *context)
for (i = 0; i < FPGA_CLEAR_LOOP_COUNT; i++) {
txbuf[0] = FPGA_CMD_READ_STATUS;
ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
- status = *(u32 *)&rxbuf[4];
+ status = get_unaligned_be32(&rxbuf[4]);
if (status == FPGA_STATUS_CLEARED)
break;
@@ -164,8 +166,8 @@ static void firmware_load(const struct firmware *fw, void *context)
txbuf[0] = FPGA_CMD_READ_STATUS;
ret = spi_write_then_read(spi, txbuf, 8, rxbuf, rx_len);
- dev_dbg(&spi->dev, "FPGA Status=%08x\n", *(u32 *)&rxbuf[4]);
- status = *(u32 *)&rxbuf[4];
+ status = get_unaligned_be32(&rxbuf[4]);
+ dev_dbg(&spi->dev, "FPGA Status=%08x\n", status);
/* Check result */
if (status & FPGA_STATUS_DONE)
@@ -196,7 +198,7 @@ static int lattice_ecp3_probe(struct spi_device *spi)
spi_set_drvdata(spi, data);
init_completion(&data->fw_loaded);
- err = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+ err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
FIRMWARE_NAME, &spi->dev,
GFP_KERNEL, spi, firmware_load);
if (err) {
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index d66a2f24f6b3..b5abe34120b8 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -870,3 +870,4 @@ module_init(lkdtm_module_init);
module_exit(lkdtm_module_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Kprobe module for testing crash dumps");
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 59d20c599b16..324e1de93687 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -459,7 +459,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
{
struct mei_device *dev;
struct mei_cl_cb *cb;
- int rets, err;
+ int rets;
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
@@ -491,6 +491,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
cl_err(dev, cl, "failed to disconnect.\n");
goto free;
}
+ cl->timer_count = MEI_CONNECT_TIMEOUT;
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
@@ -500,23 +501,18 @@ int mei_cl_disconnect(struct mei_cl *cl)
}
mutex_unlock(&dev->device_lock);
- err = wait_event_timeout(dev->wait_recvd_msg,
+ wait_event_timeout(dev->wait_recvd_msg,
MEI_FILE_DISCONNECTED == cl->state,
mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(&dev->device_lock);
+
if (MEI_FILE_DISCONNECTED == cl->state) {
rets = 0;
cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
} else {
- rets = -ENODEV;
- if (MEI_FILE_DISCONNECTED != cl->state)
- cl_err(dev, cl, "wrong status client disconnect.\n");
-
- if (err)
- cl_dbg(dev, cl, "wait failed disconnect err=%d\n", err);
-
- cl_err(dev, cl, "failed to disconnect from FW client.\n");
+ cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");
+ rets = -ETIME;
}
mei_io_list_flush(&dev->ctrl_rd_list, cl);
@@ -616,6 +612,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
mutex_lock(&dev->device_lock);
if (cl->state != MEI_FILE_CONNECTED) {
+ cl->state = MEI_FILE_DISCONNECTED;
/* something went really wrong */
if (!cl->status)
cl->status = -EFAULT;
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index a7856c0ac576..c5feafdd58a8 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -115,6 +115,7 @@
#define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */
#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
+#define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
/* Host Firmware Status Registers in PCI Config Space */
#define PCI_CFG_HFS_1 0x40
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 6a2d272cea43..a9a0d08f758e 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -710,64 +710,10 @@ end:
return IRQ_HANDLED;
}
-/**
- * mei_me_fw_status - retrieve fw status from the pci config space
- *
- * @dev: the device structure
- * @fw_status: fw status registers storage
- *
- * returns 0 on success an error code otherwise
- */
-static int mei_me_fw_status(struct mei_device *dev,
- struct mei_fw_status *fw_status)
-{
- const u32 pci_cfg_reg[] = {PCI_CFG_HFS_1, PCI_CFG_HFS_2};
- int i;
-
- if (!fw_status)
- return -EINVAL;
-
- switch (dev->pdev->device) {
- case MEI_DEV_ID_IBXPK_1:
- case MEI_DEV_ID_IBXPK_2:
- case MEI_DEV_ID_CPT_1:
- case MEI_DEV_ID_PBG_1:
- case MEI_DEV_ID_PPT_1:
- case MEI_DEV_ID_PPT_2:
- case MEI_DEV_ID_PPT_3:
- case MEI_DEV_ID_LPT_H:
- case MEI_DEV_ID_LPT_W:
- case MEI_DEV_ID_LPT_LP:
- case MEI_DEV_ID_LPT_HR:
- case MEI_DEV_ID_WPT_LP:
- fw_status->count = 2;
- break;
- case MEI_DEV_ID_ICH10_1:
- case MEI_DEV_ID_ICH10_2:
- case MEI_DEV_ID_ICH10_3:
- case MEI_DEV_ID_ICH10_4:
- fw_status->count = 1;
- break;
- default:
- fw_status->count = 0;
- break;
- }
-
- for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) {
- int ret;
- ret = pci_read_config_dword(dev->pdev,
- pci_cfg_reg[i], &fw_status->status[i]);
- if (ret)
- return ret;
- }
- return 0;
-}
-
static const struct mei_hw_ops mei_me_hw_ops = {
.pg_state = mei_me_pg_state,
- .fw_status = mei_me_fw_status,
.host_is_ready = mei_me_host_is_ready,
.hw_is_ready = mei_me_hw_is_ready,
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index 93273783dec5..f1cd166094f2 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -1042,40 +1042,8 @@ end:
return IRQ_HANDLED;
}
-
-/**
- * mei_txe_fw_status - retrieve fw status from the pci config space
- *
- * @dev: the device structure
- * @fw_status: fw status registers storage
- *
- * returns: 0 on success an error code otherwise
- */
-static int mei_txe_fw_status(struct mei_device *dev,
- struct mei_fw_status *fw_status)
-{
- const u32 pci_cfg_reg[] = {PCI_CFG_TXE_FW_STS0, PCI_CFG_TXE_FW_STS1};
- int i;
-
- if (!fw_status)
- return -EINVAL;
-
- fw_status->count = 2;
-
- for (i = 0; i < fw_status->count && i < MEI_FW_STATUS_MAX; i++) {
- int ret;
- ret = pci_read_config_dword(dev->pdev,
- pci_cfg_reg[i], &fw_status->status[i]);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static const struct mei_hw_ops mei_txe_hw_ops = {
- .fw_status = mei_txe_fw_status,
.host_is_ready = mei_txe_host_is_ready,
.pg_state = mei_txe_pg_state,
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 66f0a1a06451..401a3d526cd0 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -32,7 +32,6 @@
#include <linux/compat.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
-#include <linux/miscdevice.h>
#include <linux/mei.h>
@@ -49,19 +48,12 @@
*/
static int mei_open(struct inode *inode, struct file *file)
{
- struct miscdevice *misc = file->private_data;
- struct pci_dev *pdev;
- struct mei_cl *cl;
struct mei_device *dev;
+ struct mei_cl *cl;
int err;
- if (!misc->parent)
- return -ENODEV;
-
- pdev = container_of(misc->parent, struct pci_dev, dev);
-
- dev = pci_get_drvdata(pdev);
+ dev = container_of(inode->i_cdev, struct mei_device, cdev);
if (!dev)
return -ENODEV;
@@ -667,46 +659,148 @@ static const struct file_operations mei_fops = {
.llseek = no_llseek
};
-/*
- * Misc Device Struct
+static struct class *mei_class;
+static dev_t mei_devt;
+#define MEI_MAX_DEVS MINORMASK
+static DEFINE_MUTEX(mei_minor_lock);
+static DEFINE_IDR(mei_idr);
+
+/**
+ * mei_minor_get - obtain next free device minor number
+ *
+ * @dev: device pointer
+ *
+ * returns allocated minor, or -ENOSPC if no free minor left
*/
-static struct miscdevice mei_misc_device = {
- .name = "mei",
- .fops = &mei_fops,
- .minor = MISC_DYNAMIC_MINOR,
-};
+static int mei_minor_get(struct mei_device *dev)
+{
+ int ret;
+
+ mutex_lock(&mei_minor_lock);
+ ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL);
+ if (ret >= 0)
+ dev->minor = ret;
+ else if (ret == -ENOSPC)
+ dev_err(&dev->pdev->dev, "too many mei devices\n");
+ mutex_unlock(&mei_minor_lock);
+ return ret;
+}
-int mei_register(struct mei_device *dev)
+/**
+ * mei_minor_free - mark device minor number as free
+ *
+ * @dev: device pointer
+ */
+static void mei_minor_free(struct mei_device *dev)
{
- int ret;
- mei_misc_device.parent = &dev->pdev->dev;
- ret = misc_register(&mei_misc_device);
- if (ret)
+ mutex_lock(&mei_minor_lock);
+ idr_remove(&mei_idr, dev->minor);
+ mutex_unlock(&mei_minor_lock);
+}
+
+int mei_register(struct mei_device *dev, struct device *parent)
+{
+ struct device *clsdev; /* class device */
+ int ret, devno;
+
+ ret = mei_minor_get(dev);
+ if (ret < 0)
return ret;
- if (mei_dbgfs_register(dev, mei_misc_device.name))
- dev_err(&dev->pdev->dev, "cannot register debugfs\n");
+ /* Fill in the data structures */
+ devno = MKDEV(MAJOR(mei_devt), dev->minor);
+ cdev_init(&dev->cdev, &mei_fops);
+ dev->cdev.owner = mei_fops.owner;
+
+ /* Add the device */
+ ret = cdev_add(&dev->cdev, devno, 1);
+ if (ret) {
+ dev_err(parent, "unable to add device %d:%d\n",
+ MAJOR(mei_devt), dev->minor);
+ goto err_dev_add;
+ }
+
+ clsdev = device_create(mei_class, parent, devno,
+ NULL, "mei%d", dev->minor);
+
+ if (IS_ERR(clsdev)) {
+ dev_err(parent, "unable to create device %d:%d\n",
+ MAJOR(mei_devt), dev->minor);
+ ret = PTR_ERR(clsdev);
+ goto err_dev_create;
+ }
+
+ ret = mei_dbgfs_register(dev, dev_name(clsdev));
+ if (ret) {
+ dev_err(clsdev, "cannot register debugfs ret = %d\n", ret);
+ goto err_dev_dbgfs;
+ }
return 0;
+
+err_dev_dbgfs:
+ device_destroy(mei_class, devno);
+err_dev_create:
+ cdev_del(&dev->cdev);
+err_dev_add:
+ mei_minor_free(dev);
+ return ret;
}
EXPORT_SYMBOL_GPL(mei_register);
void mei_deregister(struct mei_device *dev)
{
+ int devno;
+
+ devno = dev->cdev.dev;
+ cdev_del(&dev->cdev);
+
mei_dbgfs_deregister(dev);
- misc_deregister(&mei_misc_device);
- mei_misc_device.parent = NULL;
+
+ device_destroy(mei_class, devno);
+
+ mei_minor_free(dev);
}
EXPORT_SYMBOL_GPL(mei_deregister);
static int __init mei_init(void)
{
- return mei_cl_bus_init();
+ int ret;
+
+ mei_class = class_create(THIS_MODULE, "mei");
+ if (IS_ERR(mei_class)) {
+ pr_err("couldn't create class\n");
+ ret = PTR_ERR(mei_class);
+ goto err;
+ }
+
+ ret = alloc_chrdev_region(&mei_devt, 0, MEI_MAX_DEVS, "mei");
+ if (ret < 0) {
+ pr_err("unable to allocate char dev region\n");
+ goto err_class;
+ }
+
+ ret = mei_cl_bus_init();
+ if (ret < 0) {
+ pr_err("unable to initialize bus\n");
+ goto err_chrdev;
+ }
+
+ return 0;
+
+err_chrdev:
+ unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
+err_class:
+ class_destroy(mei_class);
+err:
+ return ret;
}
static void __exit mei_exit(void)
{
+ unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
+ class_destroy(mei_class);
mei_cl_bus_exit();
}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 5c7e990e2f22..0b0d6135543b 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -227,7 +227,6 @@ struct mei_cl {
/** struct mei_hw_ops
*
- * @fw_status - read FW status from PCI config space
* @host_is_ready - query for host readiness
* @hw_is_ready - query if hw is ready
@@ -255,8 +254,6 @@ struct mei_cl {
*/
struct mei_hw_ops {
- int (*fw_status)(struct mei_device *dev,
- struct mei_fw_status *fw_status);
bool (*host_is_ready)(struct mei_device *dev);
bool (*hw_is_ready)(struct mei_device *dev);
@@ -400,6 +397,10 @@ struct mei_cfg {
/**
* struct mei_device - MEI private device struct
+ * @pdev - pointer to pci device struct
+ * @cdev - character device
+ * @minor - minor number allocated for device
+ *
* @reset_count - limits the number of consecutive resets
* @hbm_state - state of host bus message protocol
* @pg_event - power gating event
@@ -412,6 +413,9 @@ struct mei_cfg {
*/
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
+ struct cdev cdev;
+ int minor;
+
/*
* lists of queues
*/
@@ -741,7 +745,7 @@ static inline int mei_dbgfs_register(struct mei_device *dev, const char *name)
static inline void mei_dbgfs_deregister(struct mei_device *dev) {}
#endif /* CONFIG_DEBUG_FS */
-int mei_register(struct mei_device *dev);
+int mei_register(struct mei_device *dev, struct device *parent);
void mei_deregister(struct mei_device *dev);
#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d"
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1b46c64a649f..a0e9422b55a2 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -31,7 +31,6 @@
#include <linux/compat.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
-#include <linux/miscdevice.h>
#include <linux/pm_runtime.h>
@@ -82,6 +81,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)},
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)},
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch_cfg)},
/* required last entry */
{0, }
@@ -207,7 +207,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
- err = mei_register(dev);
+ err = mei_register(dev, &pdev->dev);
if (err)
goto release_irq;
@@ -369,7 +369,7 @@ static int mei_me_pm_runtime_idle(struct device *device)
if (!dev)
return -ENODEV;
if (mei_write_is_idle(dev))
- pm_schedule_suspend(device, MEI_ME_RPM_TIMEOUT * 2);
+ pm_runtime_autosuspend(device);
return -EBUSY;
}
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index 2343c6236df9..19de57368b7a 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -149,7 +149,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
- err = mei_register(dev);
+ err = mei_register(dev, &pdev->dev);
if (err)
goto release_irq;
@@ -306,7 +306,7 @@ static int mei_txe_pm_runtime_idle(struct device *device)
if (!dev)
return -ENODEV;
if (mei_write_is_idle(dev))
- pm_schedule_suspend(device, MEI_TXI_RPM_TIMEOUT * 2);
+ pm_runtime_autosuspend(device);
return -EBUSY;
}
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index 462a5b1d8651..cc4eef040c14 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -1,8 +1,25 @@
+comment "Intel MIC Bus Driver"
+
+config INTEL_MIC_BUS
+ tristate "Intel MIC Bus Driver"
+ depends on 64BIT && PCI && X86 && X86_DEV_DMA_OPS
+ help
+ This option is selected by any driver which registers a
+ device or driver on the MIC Bus, such as CONFIG_INTEL_MIC_HOST,
+ CONFIG_INTEL_MIC_CARD, CONFIG_INTEL_MIC_X100_DMA etc.
+
+ If you are building a host/card kernel with an Intel MIC device
+ then say M (recommended) or Y, else say N. If unsure say N.
+
+ More information about the Intel MIC family as well as the Linux
+ OS and tools for MIC to use with this driver are available from
+ <http://software.intel.com/en-us/mic-developer>.
+
comment "Intel MIC Host Driver"
config INTEL_MIC_HOST
tristate "Intel MIC Host Driver"
- depends on 64BIT && PCI && X86
+ depends on 64BIT && PCI && X86 && INTEL_MIC_BUS
select VHOST_RING
help
This enables Host Driver support for the Intel Many Integrated
@@ -22,7 +39,7 @@ comment "Intel MIC Card Driver"
config INTEL_MIC_CARD
tristate "Intel MIC Card Driver"
- depends on 64BIT && X86
+ depends on 64BIT && X86 && INTEL_MIC_BUS
select VIRTIO
help
This enables card driver support for the Intel Many Integrated
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
index 05b34d683a58..e9bf148755e2 100644
--- a/drivers/misc/mic/Makefile
+++ b/drivers/misc/mic/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_INTEL_MIC_HOST) += host/
obj-$(CONFIG_INTEL_MIC_CARD) += card/
+obj-$(CONFIG_INTEL_MIC_BUS) += bus/
diff --git a/drivers/misc/mic/bus/Makefile b/drivers/misc/mic/bus/Makefile
new file mode 100644
index 000000000000..d85c7f2a0af4
--- /dev/null
+++ b/drivers/misc/mic/bus/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2014, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_BUS) += mic_bus.o
diff --git a/drivers/misc/mic/bus/mic_bus.c b/drivers/misc/mic/bus/mic_bus.c
new file mode 100644
index 000000000000..961ae90aae47
--- /dev/null
+++ b/drivers/misc/mic/bus/mic_bus.c
@@ -0,0 +1,218 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Bus driver.
+ *
+ * This implementation is very similar to the the virtio bus driver
+ * implementation @ drivers/virtio/virtio.c
+ */
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/idr.h>
+#include <linux/mic_bus.h>
+
+/* Unique numbering for mbus devices. */
+static DEFINE_IDA(mbus_index_ida);
+
+static ssize_t device_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct mbus_device *dev = dev_to_mbus(d);
+ return sprintf(buf, "0x%04x\n", dev->id.device);
+}
+static DEVICE_ATTR_RO(device);
+
+static ssize_t vendor_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct mbus_device *dev = dev_to_mbus(d);
+ return sprintf(buf, "0x%04x\n", dev->id.vendor);
+}
+static DEVICE_ATTR_RO(vendor);
+
+static ssize_t modalias_show(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct mbus_device *dev = dev_to_mbus(d);
+ return sprintf(buf, "mbus:d%08Xv%08X\n",
+ dev->id.device, dev->id.vendor);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *mbus_dev_attrs[] = {
+ &dev_attr_device.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_modalias.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(mbus_dev);
+
+static inline int mbus_id_match(const struct mbus_device *dev,
+ const struct mbus_device_id *id)
+{
+ if (id->device != dev->id.device && id->device != MBUS_DEV_ANY_ID)
+ return 0;
+
+ return id->vendor == MBUS_DEV_ANY_ID || id->vendor == dev->id.vendor;
+}
+
+/*
+ * This looks through all the IDs a driver claims to support. If any of them
+ * match, we return 1 and the kernel will call mbus_dev_probe().
+ */
+static int mbus_dev_match(struct device *dv, struct device_driver *dr)
+{
+ unsigned int i;
+ struct mbus_device *dev = dev_to_mbus(dv);
+ const struct mbus_device_id *ids;
+
+ ids = drv_to_mbus(dr)->id_table;
+ for (i = 0; ids[i].device; i++)
+ if (mbus_id_match(dev, &ids[i]))
+ return 1;
+ return 0;
+}
+
+static int mbus_uevent(struct device *dv, struct kobj_uevent_env *env)
+{
+ struct mbus_device *dev = dev_to_mbus(dv);
+
+ return add_uevent_var(env, "MODALIAS=mbus:d%08Xv%08X",
+ dev->id.device, dev->id.vendor);
+}
+
+static int mbus_dev_probe(struct device *d)
+{
+ int err;
+ struct mbus_device *dev = dev_to_mbus(d);
+ struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
+
+ err = drv->probe(dev);
+ if (!err)
+ if (drv->scan)
+ drv->scan(dev);
+ return err;
+}
+
+static int mbus_dev_remove(struct device *d)
+{
+ struct mbus_device *dev = dev_to_mbus(d);
+ struct mbus_driver *drv = drv_to_mbus(dev->dev.driver);
+
+ drv->remove(dev);
+ return 0;
+}
+
+static struct bus_type mic_bus = {
+ .name = "mic_bus",
+ .match = mbus_dev_match,
+ .dev_groups = mbus_dev_groups,
+ .uevent = mbus_uevent,
+ .probe = mbus_dev_probe,
+ .remove = mbus_dev_remove,
+};
+
+int mbus_register_driver(struct mbus_driver *driver)
+{
+ driver->driver.bus = &mic_bus;
+ return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(mbus_register_driver);
+
+void mbus_unregister_driver(struct mbus_driver *driver)
+{
+ driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(mbus_unregister_driver);
+
+static void mbus_release_dev(struct device *d)
+{
+ struct mbus_device *mbdev = dev_to_mbus(d);
+ kfree(mbdev);
+}
+
+struct mbus_device *
+mbus_register_device(struct device *pdev, int id, struct dma_map_ops *dma_ops,
+ struct mbus_hw_ops *hw_ops, void __iomem *mmio_va)
+{
+ int ret;
+ struct mbus_device *mbdev;
+
+ mbdev = kzalloc(sizeof(*mbdev), GFP_KERNEL);
+ if (!mbdev)
+ return ERR_PTR(-ENOMEM);
+
+ mbdev->mmio_va = mmio_va;
+ mbdev->dev.parent = pdev;
+ mbdev->id.device = id;
+ mbdev->id.vendor = MBUS_DEV_ANY_ID;
+ mbdev->dev.archdata.dma_ops = dma_ops;
+ mbdev->dev.dma_mask = &mbdev->dev.coherent_dma_mask;
+ dma_set_mask(&mbdev->dev, DMA_BIT_MASK(64));
+ mbdev->dev.release = mbus_release_dev;
+ mbdev->hw_ops = hw_ops;
+ mbdev->dev.bus = &mic_bus;
+
+ /* Assign a unique device index and hence name. */
+ ret = ida_simple_get(&mbus_index_ida, 0, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_mbdev;
+
+ mbdev->index = ret;
+ dev_set_name(&mbdev->dev, "mbus-dev%u", mbdev->index);
+ /*
+ * device_register() causes the bus infrastructure to look for a
+ * matching driver.
+ */
+ ret = device_register(&mbdev->dev);
+ if (ret)
+ goto ida_remove;
+ return mbdev;
+ida_remove:
+ ida_simple_remove(&mbus_index_ida, mbdev->index);
+free_mbdev:
+ kfree(mbdev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(mbus_register_device);
+
+void mbus_unregister_device(struct mbus_device *mbdev)
+{
+ int index = mbdev->index; /* save for after device release */
+
+ device_unregister(&mbdev->dev);
+ ida_simple_remove(&mbus_index_ida, index);
+}
+EXPORT_SYMBOL_GPL(mbus_unregister_device);
+
+static int __init mbus_init(void)
+{
+ return bus_register(&mic_bus);
+}
+
+static void __exit mbus_exit(void)
+{
+ bus_unregister(&mic_bus);
+ ida_destroy(&mbus_index_ida);
+}
+
+core_initcall(mbus_init);
+module_exit(mbus_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC Bus driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
index d0980ff96833..83819eee553b 100644
--- a/drivers/misc/mic/card/mic_device.c
+++ b/drivers/misc/mic/card/mic_device.c
@@ -83,8 +83,8 @@ static int mic_shutdown_init(void)
int shutdown_db;
shutdown_db = mic_next_card_db();
- shutdown_cookie = mic_request_card_irq(mic_shutdown_isr,
- "Shutdown", mdrv, shutdown_db);
+ shutdown_cookie = mic_request_card_irq(mic_shutdown_isr, NULL,
+ "Shutdown", mdrv, shutdown_db);
if (IS_ERR(shutdown_cookie))
rc = PTR_ERR(shutdown_cookie);
else
@@ -136,7 +136,8 @@ static void mic_dp_uninit(void)
/**
* mic_request_card_irq - request an irq.
*
- * @func: The callback function that handles the interrupt.
+ * @handler: interrupt handler passed to request_threaded_irq.
+ * @thread_fn: thread fn. passed to request_threaded_irq.
* @name: The ASCII name of the callee requesting the irq.
* @data: private data that is returned back when calling the
* function handler.
@@ -149,17 +150,19 @@ static void mic_dp_uninit(void)
* error code.
*
*/
-struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
- const char *name, void *data, int index)
+struct mic_irq *
+mic_request_card_irq(irq_handler_t handler,
+ irq_handler_t thread_fn, const char *name,
+ void *data, int index)
{
int rc = 0;
unsigned long cookie;
struct mic_driver *mdrv = g_drv;
- rc = request_irq(mic_db_to_irq(mdrv, index), func,
- 0, name, data);
+ rc = request_threaded_irq(mic_db_to_irq(mdrv, index), handler,
+ thread_fn, 0, name, data);
if (rc) {
- dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc);
+ dev_err(mdrv->dev, "request_threaded_irq failed rc = %d\n", rc);
goto err;
}
mdrv->irq_info.irq_usage_count[index]++;
@@ -172,9 +175,9 @@ err:
/**
* mic_free_card_irq - free irq.
*
- * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
* @data: private data specified by the calling function during the
- * mic_request_irq
+ * mic_request_threaded_irq
*
* returns: none.
*/
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
index 306f502be95e..844be8fc9b22 100644
--- a/drivers/misc/mic/card/mic_device.h
+++ b/drivers/misc/mic/card/mic_device.h
@@ -30,6 +30,8 @@
#include <linux/workqueue.h>
#include <linux/io.h>
#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#include <linux/mic_bus.h>
/**
* struct mic_intr_info - Contains h/w specific interrupt sources info
@@ -70,6 +72,7 @@ struct mic_device {
* @hotplug_work: Hot plug work for adding/removing virtio devices.
* @irq_info: The OS specific irq information
* @intr_info: H/W specific interrupt information.
+ * @dma_mbdev: dma device on the MIC virtual bus.
*/
struct mic_driver {
char name[20];
@@ -80,6 +83,7 @@ struct mic_driver {
struct work_struct hotplug_work;
struct mic_irq_info irq_info;
struct mic_intr_info intr_info;
+ struct mbus_device *dma_mbdev;
};
/**
@@ -116,8 +120,9 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
int mic_driver_init(struct mic_driver *mdrv);
void mic_driver_uninit(struct mic_driver *mdrv);
int mic_next_card_db(void);
-struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
- const char *name, void *data, int intr_src);
+struct mic_irq *
+mic_request_card_irq(irq_handler_t handler, irq_handler_t thread_fn,
+ const char *name, void *data, int intr_src);
void mic_free_card_irq(struct mic_irq *cookie, void *data);
u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
void mic_send_intr(struct mic_device *mdev, int doorbell);
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c
index 653799b96bfa..f14b60080c21 100644
--- a/drivers/misc/mic/card/mic_virtio.c
+++ b/drivers/misc/mic/card/mic_virtio.c
@@ -417,7 +417,7 @@ static int mic_add_device(struct mic_device_desc __iomem *d,
virtio_db = mic_next_card_db();
mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler,
- "virtio intr", mvdev, virtio_db);
+ NULL, "virtio intr", mvdev, virtio_db);
if (IS_ERR(mvdev->virtio_cookie)) {
ret = PTR_ERR(mvdev->virtio_cookie);
goto kfree;
@@ -606,8 +606,9 @@ int mic_devices_init(struct mic_driver *mdrv)
mic_scan_devices(mdrv, !REMOVE_DEVICES);
config_db = mic_next_card_db();
- virtio_config_cookie = mic_request_card_irq(mic_extint_handler,
- "virtio_config_intr", mdrv, config_db);
+ virtio_config_cookie = mic_request_card_irq(mic_extint_handler, NULL,
+ "virtio_config_intr", mdrv,
+ config_db);
if (IS_ERR(virtio_config_cookie)) {
rc = PTR_ERR(virtio_config_cookie);
goto exit;
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
index 2868945c9a4d..9d57545d64f6 100644
--- a/drivers/misc/mic/card/mic_x100.c
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -148,6 +148,47 @@ void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
iounmap(addr);
}
+static inline struct mic_driver *mbdev_to_mdrv(struct mbus_device *mbdev)
+{
+ return dev_get_drvdata(mbdev->dev.parent);
+}
+
+static struct mic_irq *
+_mic_request_threaded_irq(struct mbus_device *mbdev,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ const char *name, void *data, int intr_src)
+{
+ int rc = 0;
+ unsigned int irq = intr_src;
+ unsigned long cookie = irq;
+
+ rc = request_threaded_irq(irq, handler, thread_fn, 0, name, data);
+ if (rc) {
+ dev_err(mbdev_to_mdrv(mbdev)->dev,
+ "request_threaded_irq failed rc = %d\n", rc);
+ return ERR_PTR(rc);
+ }
+ return (struct mic_irq *)cookie;
+}
+
+static void _mic_free_irq(struct mbus_device *mbdev,
+ struct mic_irq *cookie, void *data)
+{
+ unsigned long irq = (unsigned long)cookie;
+ free_irq(irq, data);
+}
+
+static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
+{
+ mic_ack_interrupt(&mbdev_to_mdrv(mbdev)->mdev);
+}
+
+static struct mbus_hw_ops mbus_hw_ops = {
+ .request_threaded_irq = _mic_request_threaded_irq,
+ .free_irq = _mic_free_irq,
+ .ack_interrupt = _mic_ack_interrupt,
+};
+
static int __init mic_probe(struct platform_device *pdev)
{
struct mic_driver *mdrv = &g_drv;
@@ -159,32 +200,41 @@ static int __init mic_probe(struct platform_device *pdev)
mdev->mmio.pa = MIC_X100_MMIO_BASE;
mdev->mmio.len = MIC_X100_MMIO_LEN;
- mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN);
+ mdev->mmio.va = devm_ioremap(&pdev->dev, MIC_X100_MMIO_BASE,
+ MIC_X100_MMIO_LEN);
if (!mdev->mmio.va) {
dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
rc = -EIO;
goto done;
}
mic_hw_intr_init(mdrv);
+ platform_set_drvdata(pdev, mdrv);
+ mdrv->dma_mbdev = mbus_register_device(mdrv->dev, MBUS_DEV_DMA_MIC,
+ NULL, &mbus_hw_ops,
+ mdrv->mdev.mmio.va);
+ if (IS_ERR(mdrv->dma_mbdev)) {
+ rc = PTR_ERR(mdrv->dma_mbdev);
+ dev_err(&pdev->dev, "mbus_add_device failed rc %d\n", rc);
+ goto done;
+ }
rc = mic_driver_init(mdrv);
if (rc) {
dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
- goto iounmap;
+ goto remove_dma;
}
done:
return rc;
-iounmap:
- iounmap(mdev->mmio.va);
+remove_dma:
+ mbus_unregister_device(mdrv->dma_mbdev);
return rc;
}
static int mic_remove(struct platform_device *pdev)
{
struct mic_driver *mdrv = &g_drv;
- struct mic_device *mdev = &mdrv->mdev;
mic_driver_uninit(mdrv);
- iounmap(mdev->mmio.va);
+ mbus_unregister_device(mdrv->dma_mbdev);
return 0;
}
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index b75c6b5cc20f..ff2b0fb1a6be 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -23,11 +23,70 @@
#include <linux/pci.h>
#include <linux/mic_common.h>
+#include <linux/mic_bus.h>
#include "../common/mic_dev.h"
#include "mic_device.h"
#include "mic_smpt.h"
#include "mic_virtio.h"
+static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
+{
+ return dev_get_drvdata(mbdev->dev.parent);
+}
+
+static dma_addr_t
+mic_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ void *va = phys_to_virt(page_to_phys(page)) + offset;
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ return mic_map_single(mdev, va, size);
+}
+
+static void
+mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ mic_unmap_single(mdev, dma_addr, size);
+}
+
+static struct dma_map_ops mic_dma_ops = {
+ .map_page = mic_dma_map_page,
+ .unmap_page = mic_dma_unmap_page,
+};
+
+static struct mic_irq *
+_mic_request_threaded_irq(struct mbus_device *mbdev,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ const char *name, void *data, int intr_src)
+{
+ return mic_request_threaded_irq(mbdev_to_mdev(mbdev), handler,
+ thread_fn, name, data,
+ intr_src, MIC_INTR_DMA);
+}
+
+static void _mic_free_irq(struct mbus_device *mbdev,
+ struct mic_irq *cookie, void *data)
+{
+ return mic_free_irq(mbdev_to_mdev(mbdev), cookie, data);
+}
+
+static void _mic_ack_interrupt(struct mbus_device *mbdev, int num)
+{
+ struct mic_device *mdev = mbdev_to_mdev(mbdev);
+ mdev->ops->intr_workarounds(mdev);
+}
+
+static struct mbus_hw_ops mbus_hw_ops = {
+ .request_threaded_irq = _mic_request_threaded_irq,
+ .free_irq = _mic_free_irq,
+ .ack_interrupt = _mic_ack_interrupt,
+};
+
/**
* mic_reset - Reset the MIC device.
* @mdev: pointer to mic_device instance
@@ -95,9 +154,21 @@ retry:
*/
goto retry;
}
+ mdev->dma_mbdev = mbus_register_device(mdev->sdev->parent,
+ MBUS_DEV_DMA_HOST, &mic_dma_ops,
+ &mbus_hw_ops, mdev->mmio.va);
+ if (IS_ERR(mdev->dma_mbdev)) {
+ rc = PTR_ERR(mdev->dma_mbdev);
+ goto unlock_ret;
+ }
+ mdev->dma_ch = mic_request_dma_chan(mdev);
+ if (!mdev->dma_ch) {
+ rc = -ENXIO;
+ goto dma_remove;
+ }
rc = mdev->ops->load_mic_fw(mdev, buf);
if (rc)
- goto unlock_ret;
+ goto dma_release;
mic_smpt_restore(mdev);
mic_intr_restore(mdev);
mdev->intr_ops->enable_interrupts(mdev);
@@ -105,6 +176,11 @@ retry:
mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
mdev->ops->send_firmware_intr(mdev);
mic_set_state(mdev, MIC_ONLINE);
+ goto unlock_ret;
+dma_release:
+ dma_release_channel(mdev->dma_ch);
+dma_remove:
+ mbus_unregister_device(mdev->dma_mbdev);
unlock_ret:
mutex_unlock(&mdev->mic_mutex);
return rc;
@@ -122,6 +198,11 @@ void mic_stop(struct mic_device *mdev, bool force)
mutex_lock(&mdev->mic_mutex);
if (MIC_OFFLINE != mdev->state || force) {
mic_virtio_reset_devices(mdev);
+ if (mdev->dma_ch) {
+ dma_release_channel(mdev->dma_ch);
+ mdev->dma_ch = NULL;
+ }
+ mbus_unregister_device(mdev->dma_mbdev);
mic_bootparam_init(mdev);
mic_reset(mdev);
if (MIC_RESET_FAILED == mdev->state)
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 0398c696d257..016bd15a7bd1 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -25,6 +25,8 @@
#include <linux/idr.h>
#include <linux/notifier.h>
#include <linux/irqreturn.h>
+#include <linux/dmaengine.h>
+#include <linux/mic_bus.h>
#include "mic_intr.h"
@@ -87,6 +89,8 @@ enum mic_stepping {
* @cdev: Character device for MIC.
* @vdev_list: list of virtio devices.
* @pm_notifier: Handles PM notifications from the OS.
+ * @dma_mbdev: MIC BUS DMA device.
+ * @dma_ch: DMA channel reserved by this driver for use by virtio devices.
*/
struct mic_device {
struct mic_mw mmio;
@@ -124,6 +128,8 @@ struct mic_device {
struct cdev cdev;
struct list_head vdev_list;
struct notifier_block pm_notifier;
+ struct mbus_device *dma_mbdev;
+ struct dma_chan *dma_ch;
};
/**
@@ -144,6 +150,7 @@ struct mic_device {
* @load_mic_fw: Load firmware segments required to boot the card
* into card memory. This includes the kernel, command line, ramdisk etc.
* @get_postcode: Get post code status from firmware.
+ * @dma_filter: DMA filter function to be used.
*/
struct mic_hw_ops {
u8 aper_bar;
@@ -159,6 +166,7 @@ struct mic_hw_ops {
void (*send_firmware_intr)(struct mic_device *mdev);
int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
u32 (*get_postcode)(struct mic_device *mdev);
+ bool (*dma_filter)(struct dma_chan *chan, void *param);
};
/**
@@ -187,6 +195,22 @@ mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
iowrite32(val, mw->va + offset);
}
+static inline struct dma_chan *mic_request_dma_chan(struct mic_device *mdev)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+ chan = dma_request_channel(mask, mdev->ops->dma_filter,
+ mdev->sdev->parent);
+ if (chan)
+ return chan;
+ dev_err(mdev->sdev->parent, "%s %d unable to acquire channel\n",
+ __func__, __LINE__);
+ return NULL;
+}
+
void mic_sysfs_init(struct mic_device *mdev);
int mic_start(struct mic_device *mdev, const char *buf);
void mic_stop(struct mic_device *mdev, bool force);
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
index dbc5afde1392..d686f2846ac7 100644
--- a/drivers/misc/mic/host/mic_intr.c
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -24,28 +24,29 @@
#include "../common/mic_dev.h"
#include "mic_device.h"
-/*
- * mic_invoke_callback - Invoke callback functions registered for
- * the corresponding source id.
- *
- * @mdev: pointer to the mic_device instance
- * @idx: The interrupt source id.
- *
- * Returns none.
- */
-static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
+static irqreturn_t mic_thread_fn(int irq, void *dev)
{
+ struct mic_device *mdev = dev;
+ struct mic_intr_info *intr_info = mdev->intr_info;
+ struct mic_irq_info *irq_info = &mdev->irq_info;
struct mic_intr_cb *intr_cb;
struct pci_dev *pdev = container_of(mdev->sdev->parent,
- struct pci_dev, dev);
+ struct pci_dev, dev);
+ int i;
- spin_lock(&mdev->irq_info.mic_intr_lock);
- list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
- if (intr_cb->func)
- intr_cb->func(pdev->irq, intr_cb->data);
- spin_unlock(&mdev->irq_info.mic_intr_lock);
+ spin_lock(&irq_info->mic_thread_lock);
+ for (i = intr_info->intr_start_idx[MIC_INTR_DB];
+ i < intr_info->intr_len[MIC_INTR_DB]; i++)
+ if (test_and_clear_bit(i, &irq_info->mask)) {
+ list_for_each_entry(intr_cb, &irq_info->cb_list[i],
+ list)
+ if (intr_cb->thread_fn)
+ intr_cb->thread_fn(pdev->irq,
+ intr_cb->data);
+ }
+ spin_unlock(&irq_info->mic_thread_lock);
+ return IRQ_HANDLED;
}
-
/**
* mic_interrupt - Generic interrupt handler for
* MSI and INTx based interrupts.
@@ -53,7 +54,11 @@ static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
static irqreturn_t mic_interrupt(int irq, void *dev)
{
struct mic_device *mdev = dev;
- struct mic_intr_info *info = mdev->intr_info;
+ struct mic_intr_info *intr_info = mdev->intr_info;
+ struct mic_irq_info *irq_info = &mdev->irq_info;
+ struct mic_intr_cb *intr_cb;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
u32 mask;
int i;
@@ -61,12 +66,19 @@ static irqreturn_t mic_interrupt(int irq, void *dev)
if (!mask)
return IRQ_NONE;
- for (i = info->intr_start_idx[MIC_INTR_DB];
- i < info->intr_len[MIC_INTR_DB]; i++)
- if (mask & BIT(i))
- mic_invoke_callback(mdev, i);
-
- return IRQ_HANDLED;
+ spin_lock(&irq_info->mic_intr_lock);
+ for (i = intr_info->intr_start_idx[MIC_INTR_DB];
+ i < intr_info->intr_len[MIC_INTR_DB]; i++)
+ if (mask & BIT(i)) {
+ list_for_each_entry(intr_cb, &irq_info->cb_list[i],
+ list)
+ if (intr_cb->handler)
+ intr_cb->handler(pdev->irq,
+ intr_cb->data);
+ set_bit(i, &irq_info->mask);
+ }
+ spin_unlock(&irq_info->mic_intr_lock);
+ return IRQ_WAKE_THREAD;
}
/* Return the interrupt offset from the index. Index is 0 based. */
@@ -99,14 +111,15 @@ static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
*
* @mdev: pointer to the mic_device instance
* @idx: The source id to be registered.
- * @func: The function to be called when the source id receives
+ * @handler: The function to be called when the source id receives
* the interrupt.
+ * @thread_fn: thread fn. corresponding to the handler
* @data: Private data of the requester.
* Return the callback structure that was registered or an
* appropriate error on failure.
*/
static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
- u8 idx, irqreturn_t (*func) (int irq, void *dev),
+ u8 idx, irq_handler_t handler, irq_handler_t thread_fn,
void *data)
{
struct mic_intr_cb *intr_cb;
@@ -117,7 +130,8 @@ static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
if (!intr_cb)
return ERR_PTR(-ENOMEM);
- intr_cb->func = func;
+ intr_cb->handler = handler;
+ intr_cb->thread_fn = thread_fn;
intr_cb->data = data;
intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
0, 0, GFP_KERNEL);
@@ -126,9 +140,11 @@ static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
goto ida_fail;
}
+ spin_lock(&mdev->irq_info.mic_thread_lock);
spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+ spin_unlock(&mdev->irq_info.mic_thread_lock);
return intr_cb;
ida_fail:
@@ -152,8 +168,9 @@ static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
unsigned long flags;
int i;
+ spin_lock(&mdev->irq_info.mic_thread_lock);
+ spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
for (i = 0; i < MIC_NUM_OFFSETS; i++) {
- spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
intr_cb = list_entry(pos, struct mic_intr_cb, list);
if (intr_cb->cb_id == idx) {
@@ -163,11 +180,13 @@ static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
kfree(intr_cb);
spin_unlock_irqrestore(
&mdev->irq_info.mic_intr_lock, flags);
+ spin_unlock(&mdev->irq_info.mic_thread_lock);
return i;
}
}
- spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
}
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+ spin_unlock(&mdev->irq_info.mic_thread_lock);
return MIC_NUM_OFFSETS;
}
@@ -242,6 +261,7 @@ static int mic_setup_callbacks(struct mic_device *mdev)
INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
ida_init(&mdev->irq_info.cb_ida);
spin_lock_init(&mdev->irq_info.mic_intr_lock);
+ spin_lock_init(&mdev->irq_info.mic_thread_lock);
return 0;
}
@@ -258,14 +278,12 @@ static void mic_release_callbacks(struct mic_device *mdev)
struct mic_intr_cb *intr_cb;
int i;
+ spin_lock(&mdev->irq_info.mic_thread_lock);
+ spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
for (i = 0; i < MIC_NUM_OFFSETS; i++) {
- spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
- if (list_empty(&mdev->irq_info.cb_list[i])) {
- spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
- flags);
+ if (list_empty(&mdev->irq_info.cb_list[i]))
break;
- }
list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
intr_cb = list_entry(pos, struct mic_intr_cb, list);
@@ -274,8 +292,9 @@ static void mic_release_callbacks(struct mic_device *mdev)
intr_cb->cb_id);
kfree(intr_cb);
}
- spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
}
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+ spin_unlock(&mdev->irq_info.mic_thread_lock);
ida_destroy(&mdev->irq_info.cb_ida);
kfree(mdev->irq_info.cb_list);
}
@@ -313,7 +332,8 @@ static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
goto err_nomem2;
}
- rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
+ rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
+ 0, "mic-msi", mdev);
if (rc) {
dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
goto err_irq_req_fail;
@@ -353,8 +373,8 @@ static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
goto err_nomem;
}
- rc = request_irq(pdev->irq, mic_interrupt,
- IRQF_SHARED, "mic-intx", mdev);
+ rc = request_threaded_irq(pdev->irq, mic_interrupt, mic_thread_fn,
+ IRQF_SHARED, "mic-intx", mdev);
if (rc)
goto err;
@@ -391,13 +411,14 @@ int mic_next_db(struct mic_device *mdev)
#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
/**
- * mic_request_irq - request an irq. mic_mutex needs
+ * mic_request_threaded_irq - request an irq. mic_mutex needs
* to be held before calling this function.
*
* @mdev: pointer to mic_device instance
- * @func: The callback function that handles the interrupt.
+ * @handler: The callback function that handles the interrupt.
* The function needs to call ack_interrupts
* (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
+ * @thread_fn: thread fn required by request_threaded_irq.
* @name: The ASCII name of the callee requesting the irq.
* @data: private data that is returned back when calling the
* function handler.
@@ -412,10 +433,11 @@ int mic_next_db(struct mic_device *mdev)
* error code.
*
*/
-struct mic_irq *mic_request_irq(struct mic_device *mdev,
- irqreturn_t (*func)(int irq, void *dev),
- const char *name, void *data, int intr_src,
- enum mic_intr_type type)
+struct mic_irq *
+mic_request_threaded_irq(struct mic_device *mdev,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ const char *name, void *data, int intr_src,
+ enum mic_intr_type type)
{
u16 offset;
int rc = 0;
@@ -444,7 +466,8 @@ struct mic_irq *mic_request_irq(struct mic_device *mdev,
goto err;
}
- rc = request_irq(msix->vector, func, 0, name, data);
+ rc = request_threaded_irq(msix->vector, handler, thread_fn,
+ 0, name, data);
if (rc) {
dev_dbg(mdev->sdev->parent,
"request irq failed rc = %d\n", rc);
@@ -458,8 +481,8 @@ struct mic_irq *mic_request_irq(struct mic_device *mdev,
dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
msix->vector, intr_src);
} else {
- intr_cb = mic_register_intr_callback(mdev,
- offset, func, data);
+ intr_cb = mic_register_intr_callback(mdev, offset, handler,
+ thread_fn, data);
if (IS_ERR(intr_cb)) {
dev_err(mdev->sdev->parent,
"No available callback entries for use\n");
@@ -487,9 +510,9 @@ err:
* needs to be held before calling this function.
*
* @mdev: pointer to mic_device instance
- * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @cookie: cookie obtained during a successful call to mic_request_threaded_irq
* @data: private data specified by the calling function during the
- * mic_request_irq
+ * mic_request_threaded_irq
*
* returns: none.
*/
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
index 6091aa97e116..9f783d4ad7f1 100644
--- a/drivers/misc/mic/host/mic_intr.h
+++ b/drivers/misc/mic/host/mic_intr.h
@@ -21,12 +21,15 @@
#ifndef _MIC_INTR_H_
#define _MIC_INTR_H_
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
/*
* The minimum number of msix vectors required for normal operation.
* 3 for virtio network, console and block devices.
* 1 for card shutdown notifications.
+ * 4 for host owned DMA channels.
*/
-#define MIC_MIN_MSIX 4
+#define MIC_MIN_MSIX 8
#define MIC_NUM_OFFSETS 32
/**
@@ -68,7 +71,11 @@ struct mic_intr_info {
* @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
* @cb_ida: callback ID allocator to track the callbacks registered.
* @mic_intr_lock: spinlock to protect the interrupt callback list.
+ * @mic_thread_lock: spinlock to protect the thread callback list.
+ * This lock is used to protect against thread_fn while
+ * mic_intr_lock is used to protect against interrupt handler.
* @cb_list: Array of callback lists one for each source.
+ * @mask: Mask used by the main thread fn to call the underlying thread fns.
*/
struct mic_irq_info {
int next_avail_src;
@@ -77,19 +84,23 @@ struct mic_irq_info {
u16 num_vectors;
struct ida cb_ida;
spinlock_t mic_intr_lock;
+ spinlock_t mic_thread_lock;
struct list_head *cb_list;
+ unsigned long mask;
};
/**
* struct mic_intr_cb - Interrupt callback structure.
*
- * @func: The callback function
+ * @handler: The callback function
+ * @thread_fn: The thread_fn.
* @data: Private data of the requester.
* @cb_id: The callback id. Identifies this callback.
* @list: list head pointing to the next callback structure.
*/
struct mic_intr_cb {
- irqreturn_t (*func) (int irq, void *data);
+ irq_handler_t handler;
+ irq_handler_t thread_fn;
void *data;
int cb_id;
struct list_head list;
@@ -124,11 +135,11 @@ struct mic_hw_intr_ops {
};
int mic_next_db(struct mic_device *mdev);
-struct mic_irq *mic_request_irq(struct mic_device *mdev,
- irqreturn_t (*func)(int irq, void *data),
- const char *name, void *data, int intr_src,
- enum mic_intr_type type);
-
+struct mic_irq *
+mic_request_threaded_irq(struct mic_device *mdev,
+ irq_handler_t handler, irq_handler_t thread_fn,
+ const char *name, void *data, int intr_src,
+ enum mic_intr_type type);
void mic_free_irq(struct mic_device *mdev,
struct mic_irq *cookie, void *data);
int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
index c04a021e20c7..ab37a3117d23 100644
--- a/drivers/misc/mic/host/mic_main.c
+++ b/drivers/misc/mic/host/mic_main.c
@@ -38,7 +38,7 @@
static const char mic_driver_name[] = "mic";
-static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = {
+static const struct pci_device_id mic_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
@@ -389,8 +389,9 @@ static int mic_probe(struct pci_dev *pdev,
mutex_lock(&mdev->mic_mutex);
mdev->shutdown_db = mic_next_db(mdev);
- mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db,
- "shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB);
+ mdev->shutdown_cookie = mic_request_threaded_irq(mdev, mic_shutdown_db,
+ NULL, "shutdown-interrupt", mdev,
+ mdev->shutdown_db, MIC_INTR_DB);
if (IS_ERR(mdev->shutdown_cookie)) {
rc = PTR_ERR(mdev->shutdown_cookie);
mutex_unlock(&mdev->mic_mutex);
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
index 7e1ef0ebbb80..a020e4eb435a 100644
--- a/drivers/misc/mic/host/mic_virtio.c
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -21,60 +21,157 @@
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
-
+#include <linux/dmaengine.h>
#include <linux/mic_common.h>
+
#include "../common/mic_dev.h"
#include "mic_device.h"
#include "mic_smpt.h"
#include "mic_virtio.h"
/*
- * Initiates the copies across the PCIe bus from card memory to
- * a user space buffer.
+ * Size of the internal buffer used during DMA's as an intermediate buffer
+ * for copy to/from user.
*/
-static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
- void __user *ubuf, size_t len, u64 addr)
+#define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
+
+static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
+ dma_addr_t src, size_t len)
{
- int err;
- void __iomem *dbuf = mvdev->mdev->aper.va + addr;
- /*
- * We are copying from IO below an should ideally use something
- * like copy_to_user_fromio(..) if it existed.
- */
- if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
- err = -EFAULT;
- dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ int err = 0;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_chan *mic_ch = mdev->dma_ch;
+
+ if (!mic_ch) {
+ err = -EBUSY;
+ goto error;
+ }
+
+ tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len,
+ DMA_PREP_FENCE);
+ if (!tx) {
+ err = -ENOMEM;
+ goto error;
+ } else {
+ dma_cookie_t cookie = tx->tx_submit(tx);
+
+ err = dma_submit_error(cookie);
+ if (err)
+ goto error;
+ err = dma_sync_wait(mic_ch, cookie);
+ }
+error:
+ if (err)
+ dev_err(mdev->sdev->parent, "%s %d err %d\n",
__func__, __LINE__, err);
- goto err;
+ return err;
+}
+
+/*
+ * Initiates the copies across the PCIe bus from card memory to a user
+ * space buffer. When transfers are done using DMA, source/destination
+ * addresses and transfer length must follow the alignment requirements of
+ * the MIC DMA engine.
+ */
+static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf,
+ size_t len, u64 daddr, size_t dlen,
+ int vr_idx)
+{
+ struct mic_device *mdev = mvdev->mdev;
+ void __iomem *dbuf = mdev->aper.va + daddr;
+ struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
+ size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
+ size_t dma_offset;
+ size_t partlen;
+ int err;
+
+ dma_offset = daddr - round_down(daddr, dma_alignment);
+ daddr -= dma_offset;
+ len += dma_offset;
+
+ while (len) {
+ partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
+
+ err = mic_sync_dma(mdev, mvr->buf_da, daddr,
+ ALIGN(partlen, dma_alignment));
+ if (err)
+ goto err;
+
+ if (copy_to_user(ubuf, mvr->buf + dma_offset,
+ partlen - dma_offset)) {
+ err = -EFAULT;
+ goto err;
+ }
+ daddr += partlen;
+ ubuf += partlen;
+ dbuf += partlen;
+ mvdev->in_bytes_dma += partlen;
+ mvdev->in_bytes += partlen;
+ len -= partlen;
+ dma_offset = 0;
}
- mvdev->in_bytes += len;
- err = 0;
+ return 0;
err:
+ dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
return err;
}
/*
- * Initiates copies across the PCIe bus from a user space
- * buffer to card memory.
+ * Initiates copies across the PCIe bus from a user space buffer to card
+ * memory. When transfers are done using DMA, source/destination addresses
+ * and transfer length must follow the alignment requirements of the MIC
+ * DMA engine.
*/
-static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
- void __user *ubuf, size_t len, u64 addr)
+static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf,
+ size_t len, u64 daddr, size_t dlen,
+ int vr_idx)
{
+ struct mic_device *mdev = mvdev->mdev;
+ void __iomem *dbuf = mdev->aper.va + daddr;
+ struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
+ size_t dma_alignment = 1 << mdev->dma_ch->device->copy_align;
+ size_t partlen;
int err;
- void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+
+ if (daddr & (dma_alignment - 1)) {
+ mvdev->tx_dst_unaligned += len;
+ goto memcpy;
+ } else if (ALIGN(len, dma_alignment) > dlen) {
+ mvdev->tx_len_unaligned += len;
+ goto memcpy;
+ }
+
+ while (len) {
+ partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
+
+ if (copy_from_user(mvr->buf, ubuf, partlen)) {
+ err = -EFAULT;
+ goto err;
+ }
+ err = mic_sync_dma(mdev, daddr, mvr->buf_da,
+ ALIGN(partlen, dma_alignment));
+ if (err)
+ goto err;
+ daddr += partlen;
+ ubuf += partlen;
+ dbuf += partlen;
+ mvdev->out_bytes_dma += partlen;
+ mvdev->out_bytes += partlen;
+ len -= partlen;
+ }
+memcpy:
/*
* We are copying to IO below and should ideally use something
* like copy_from_user_toio(..) if it existed.
*/
if (copy_from_user((void __force *)dbuf, ubuf, len)) {
err = -EFAULT;
- dev_err(mic_dev(mvdev), "%s %d err %d\n",
- __func__, __LINE__, err);
goto err;
}
mvdev->out_bytes += len;
- err = 0;
+ return 0;
err:
+ dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
return err;
}
@@ -110,7 +207,8 @@ static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
* way to override the VRINGH xfer(..) routines as of v3.10.
*/
static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
- void __user *ubuf, size_t len, bool read, size_t *out_len)
+ void __user *ubuf, size_t len, bool read, int vr_idx,
+ size_t *out_len)
{
int ret = 0;
size_t partlen, tot_len = 0;
@@ -118,13 +216,15 @@ static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
while (len && iov->i < iov->used) {
partlen = min(iov->iov[iov->i].iov_len, len);
if (read)
- ret = mic_virtio_copy_to_user(mvdev,
- ubuf, partlen,
- (u64)iov->iov[iov->i].iov_base);
+ ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen,
+ (u64)iov->iov[iov->i].iov_base,
+ iov->iov[iov->i].iov_len,
+ vr_idx);
else
- ret = mic_virtio_copy_from_user(mvdev,
- ubuf, partlen,
- (u64)iov->iov[iov->i].iov_base);
+ ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen,
+ (u64)iov->iov[iov->i].iov_base,
+ iov->iov[iov->i].iov_len,
+ vr_idx);
if (ret) {
dev_err(mic_dev(mvdev), "%s %d err %d\n",
__func__, __LINE__, ret);
@@ -192,8 +292,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev,
ubuf = iov.iov_base;
}
/* Issue all the read descriptors first */
- ret = mic_vringh_copy(mvdev, riov, ubuf, len,
- MIC_VRINGH_READ, &out_len);
+ ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ,
+ copy->vr_idx, &out_len);
if (ret) {
dev_err(mic_dev(mvdev), "%s %d err %d\n",
__func__, __LINE__, ret);
@@ -203,8 +303,8 @@ static int _mic_virtio_copy(struct mic_vdev *mvdev,
ubuf += out_len;
copy->out_len += out_len;
/* Issue the write descriptors next */
- ret = mic_vringh_copy(mvdev, wiov, ubuf, len,
- !MIC_VRINGH_READ, &out_len);
+ ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ,
+ copy->vr_idx, &out_len);
if (ret) {
dev_err(mic_dev(mvdev), "%s %d err %d\n",
__func__, __LINE__, ret);
@@ -589,13 +689,19 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
dev_dbg(mdev->sdev->parent,
"%s %d index %d va %p info %p vr_size 0x%x\n",
__func__, __LINE__, i, vr->va, vr->info, vr_size);
+ mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
+ get_order(MIC_INT_DMA_BUF_SIZE));
+ mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf,
+ MIC_INT_DMA_BUF_SIZE);
}
snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
mvdev->virtio_id);
mvdev->virtio_db = mic_next_db(mdev);
- mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler,
- irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB);
+ mvdev->virtio_cookie = mic_request_threaded_irq(mdev,
+ mic_virtio_intr_handler,
+ NULL, irqname, mvdev,
+ mvdev->virtio_db, MIC_INTR_DB);
if (IS_ERR(mvdev->virtio_cookie)) {
ret = PTR_ERR(mvdev->virtio_cookie);
dev_dbg(mdev->sdev->parent, "request irq failed\n");
@@ -671,6 +777,11 @@ skip_hot_remove:
vqconfig = mic_vq_config(mvdev->dd);
for (i = 0; i < mvdev->dd->num_vq; i++) {
struct mic_vringh *mvr = &mvdev->mvr[i];
+
+ mic_unmap_single(mvdev->mdev, mvr->buf_da,
+ MIC_INT_DMA_BUF_SIZE);
+ free_pages((unsigned long)mvr->buf,
+ get_order(MIC_INT_DMA_BUF_SIZE));
vringh_kiov_cleanup(&mvr->riov);
vringh_kiov_cleanup(&mvr->wiov);
mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
index 184f3c84805b..d574efb853d9 100644
--- a/drivers/misc/mic/host/mic_virtio.h
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -46,18 +46,23 @@
* @vrh: The host VRINGH used for accessing the card vrings.
* @riov: The VRINGH read kernel IOV.
* @wiov: The VRINGH write kernel IOV.
- * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
* @vr_mutex: Mutex for synchronizing access to the VRING.
+ * @buf: Temporary kernel buffer used to copy in/out data
+ * from/to the card via DMA.
+ * @buf_da: dma address of buf.
* @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
+ * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
*/
struct mic_vringh {
struct mic_vring vring;
struct vringh vrh;
struct vringh_kiov riov;
struct vringh_kiov wiov;
- u16 head;
struct mutex vr_mutex;
+ void *buf;
+ dma_addr_t buf_da;
struct mic_vdev *mvdev;
+ u16 head;
};
/**
@@ -69,6 +74,14 @@ struct mic_vringh {
* @poll_wake - Used for waking up threads blocked in poll.
* @out_bytes - Debug stats for number of bytes copied from host to card.
* @in_bytes - Debug stats for number of bytes copied from card to host.
+ * @out_bytes_dma - Debug stats for number of bytes copied from host to card
+ * using DMA.
+ * @in_bytes_dma - Debug stats for number of bytes copied from card to host
+ * using DMA.
+ * @tx_len_unaligned - Debug stats for number of bytes copied to the card where
+ * the transfer length did not have the required DMA alignment.
+ * @tx_dst_unaligned - Debug stats for number of bytes copied where the
+ * destination address on the card did not have the required DMA alignment.
* @mvr - Store per VRING data structures.
* @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
* @dd - Virtio device descriptor.
@@ -84,6 +97,10 @@ struct mic_vdev {
int poll_wake;
unsigned long out_bytes;
unsigned long in_bytes;
+ unsigned long out_bytes_dma;
+ unsigned long in_bytes_dma;
+ unsigned long tx_len_unaligned;
+ unsigned long tx_dst_unaligned;
struct mic_vringh mvr[MIC_MAX_VRINGS];
struct work_struct virtio_bh_work;
struct mic_device_desc *dd;
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
index 5562fdd3ef4e..b7a21e11dcdf 100644
--- a/drivers/misc/mic/host/mic_x100.c
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -549,6 +549,13 @@ struct mic_smpt_ops mic_x100_smpt_ops = {
.set = mic_x100_smpt_set,
};
+static bool mic_x100_dma_filter(struct dma_chan *chan, void *param)
+{
+ if (chan->device->dev->parent == (struct device *)param)
+ return true;
+ return false;
+}
+
struct mic_hw_ops mic_x100_ops = {
.aper_bar = MIC_X100_APER_BAR,
.mmio_bar = MIC_X100_MMIO_BAR,
@@ -563,6 +570,7 @@ struct mic_hw_ops mic_x100_ops = {
.send_firmware_intr = mic_x100_send_firmware_intr,
.load_mic_fw = mic_x100_load_firmware,
.get_postcode = mic_x100_get_postcode,
+ .dma_filter = mic_x100_dma_filter,
};
struct mic_hw_intr_ops mic_x100_intr_ops = {
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 3fac67a5204c..557f9782c53c 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -544,7 +544,8 @@ xpnet_init(void)
* use ether_setup() to init the majority of our device
* structure and then override the necessary pieces.
*/
- xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, ether_setup);
+ xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, NET_NAME_UNKNOWN,
+ ether_setup);
if (xpnet_device == NULL) {
kfree(xpnet_broadcast_partitions);
return -ENOMEM;
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 9d3dbb28734b..21c2337bad68 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -244,7 +244,8 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
if (version & 0x8000)
maj_ver |= 0x0008;
- sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+ sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts",
+ chip, maj_ver, min_ver);
/* to be accessed later via sysfs entry */
kim_gdata->version.full = version;
@@ -287,7 +288,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
long len = 0;
unsigned char *ptr = NULL;
unsigned char *action_ptr = NULL;
- unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */
+ unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */
int wr_room_space;
int cmd_size;
unsigned long timeout;
@@ -778,7 +779,7 @@ static int kim_probe(struct platform_device *pdev)
pr_info("sysfs entries created\n");
kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
- if (IS_ERR(kim_debugfs_dir)) {
+ if (!kim_debugfs_dir) {
pr_err(" debugfs entries creation failed ");
err = -EIO;
goto err_debugfs_dir;
@@ -788,7 +789,6 @@ static int kim_probe(struct platform_device *pdev)
kim_gdata, &version_debugfs_fops);
debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir,
kim_gdata, &list_debugfs_fops);
- pr_info(" debugfs entries created ");
return 0;
err_debugfs_dir:
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
index 3250fc1df0aa..b3a812384a6f 100644
--- a/drivers/misc/vexpress-syscfg.c
+++ b/drivers/misc/vexpress-syscfg.c
@@ -130,7 +130,7 @@ static int vexpress_syscfg_write(void *context, unsigned int index,
return vexpress_syscfg_exec(func, index, true, &val);
}
-struct regmap_config vexpress_syscfg_regmap_config = {
+static struct regmap_config vexpress_syscfg_regmap_config = {
.lock = vexpress_config_lock,
.unlock = vexpress_config_unlock,
.reg_bits = 32,
@@ -276,7 +276,7 @@ int vexpress_syscfg_device_register(struct platform_device *pdev)
}
-int vexpress_syscfg_probe(struct platform_device *pdev)
+static int vexpress_syscfg_probe(struct platform_device *pdev)
{
struct vexpress_syscfg *syscfg;
struct resource *res;
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
index e0d5017785e5..248399a881af 100644
--- a/drivers/misc/vmw_vmci/vmci_guest.c
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -748,7 +748,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev)
/* The rest are managed resources and will be freed by PCI core */
}
-static DEFINE_PCI_DEVICE_TABLE(vmci_ids) = {
+static const struct pci_device_id vmci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_VMCI), },
{ 0 },
};
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 452782bffebc..ede41f05c392 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2028,8 +2028,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
/* complete ongoing async transfer before issuing discard */
if (card->host->areq)
mmc_blk_issue_rw_rq(mq, NULL);
- if (req->cmd_flags & REQ_SECURE &&
- !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
+ if (req->cmd_flags & REQ_SECURE)
ret = mmc_blk_issue_secdiscard_rq(mq, req);
else
ret = mmc_blk_issue_discard_rq(mq, req);
@@ -2432,6 +2431,8 @@ static int mmc_blk_probe(struct mmc_card *card)
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
+ mmc_fixup_device(card, blk_fixups);
+
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
@@ -2446,7 +2447,6 @@ static int mmc_blk_probe(struct mmc_card *card)
goto out;
mmc_set_drvdata(card, md);
- mmc_fixup_device(card, blk_fixups);
if (mmc_add_disk(md))
goto out;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index d2dbf02022bd..8a1f1240e058 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -180,7 +180,6 @@ static int mmc_bus_resume(struct device *dev)
#endif
#ifdef CONFIG_PM_RUNTIME
-
static int mmc_runtime_suspend(struct device *dev)
{
struct mmc_card *card = mmc_dev_to_card(dev);
@@ -196,17 +195,10 @@ static int mmc_runtime_resume(struct device *dev)
return host->bus_ops->runtime_resume(host);
}
-
-static int mmc_runtime_idle(struct device *dev)
-{
- return 0;
-}
-
#endif /* !CONFIG_PM_RUNTIME */
static const struct dev_pm_ops mmc_bus_pm_ops = {
- SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
- mmc_runtime_idle)
+ SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
};
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7dc0c85fdb60..d03a080fb9cd 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2102,7 +2102,8 @@ EXPORT_SYMBOL(mmc_can_sanitize);
int mmc_can_secure_erase_trim(struct mmc_card *card)
{
- if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)
+ if ((card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) &&
+ !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
return 1;
return 0;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 793c6f7ddb04..1eda8dd8c867 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -324,13 +324,12 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
}
}
+ /*
+ * The EXT_CSD format is meant to be forward compatible. As long
+ * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
+ * are authorized, see JEDEC JESD84-B50 section B.8.
+ */
card->ext_csd.rev = ext_csd[EXT_CSD_REV];
- if (card->ext_csd.rev > 7) {
- pr_err("%s: unrecognised EXT_CSD revision %d\n",
- mmc_hostname(card->host), card->ext_csd.rev);
- err = -EINVAL;
- goto out;
- }
card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index 6c36fccaa1ec..dd1d1e0fe322 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -91,7 +91,7 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
(f->cis_device == card->cis.device ||
f->cis_device == (u16) SDIO_ANY_ID) &&
rev >= f->rev_start && rev <= f->rev_end) {
- dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
+ dev_dbg(&card->dev, "calling %pf\n", f->vendor_fixup);
f->vendor_fixup(card, f->data);
}
}
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 274ef00b4463..48d0c93ba25a 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -184,6 +184,9 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
mmc_delay(10);
}
+ if (!i)
+ pr_err("%s: card never left busy state\n", mmc_hostname(host));
+
if (rocr && !mmc_host_is_spi(host))
*rocr = cmd.resp[0];
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index a5652548230a..451135822464 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -290,6 +290,18 @@ config MMC_MOXART
be found on some embedded hardware such as UC-7112-LX.
If you have a controller with this interface, say Y here.
+config MMC_SDHCI_ST
+ tristate "SDHCI support on STMicroelectronics SoC"
+ depends on ARCH_STI
+ depends on MMC_SDHCI_PLTFM
+ select MMC_SDHCI_IO_ACCESSORS
+ help
+ This selects the Secure Digital Host Controller Interface in
+ STMicroelectronics SoCs.
+
+ If you have a controller with this interface, say Y or M here.
+ If unsure, say N.
+
config MMC_OMAP
tristate "TI OMAP Multimedia Card Interface support"
depends on ARCH_OMAP
@@ -303,6 +315,7 @@ config MMC_OMAP
config MMC_OMAP_HS
tristate "TI OMAP High Speed Multimedia Card Interface support"
+ depends on HAS_DMA
depends on ARCH_OMAP2PLUS || COMPILE_TEST
help
This selects the TI OMAP High Speed Multimedia card Interface.
@@ -343,7 +356,7 @@ config MMC_ATMELMCI
config MMC_SDHCI_MSM
tristate "Qualcomm SDHCI Controller Support"
- depends on ARCH_QCOM
+ depends on ARCH_QCOM || (ARM && COMPILE_TEST)
depends on MMC_SDHCI_PLTFM
help
This selects the Secure Digital Host Controller Interface (SDHCI)
@@ -440,6 +453,7 @@ config MMC_SPI
config MMC_S3C
tristate "Samsung S3C SD/MMC Card Interface support"
depends on ARCH_S3C24XX
+ depends on S3C24XX_DMAC
help
This selects a driver for the MCI interface found in
Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@@ -477,15 +491,6 @@ config MMC_S3C_DMA
working properly and needs to be debugged before this
option is useful.
-config MMC_S3C_PIODMA
- bool "Support for both PIO and DMA"
- help
- Compile both the PIO and DMA transfer routines into the
- driver and let the platform select at run-time which one
- is best.
-
- See notes for the DMA option.
-
endchoice
config MMC_SDRICOH_CS
@@ -623,7 +628,7 @@ config MMC_DW_PCI
config MMC_SH_MMCIF
tristate "SuperH Internal MMCIF support"
- depends on MMC_BLOCK
+ depends on MMC_BLOCK && HAS_DMA
depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
help
This selects the MMC Host Interface controller (MMCIF).
@@ -697,6 +702,7 @@ config MMC_WMT
config MMC_USDHI6ROL0
tristate "Renesas USDHI6ROL0 SD/SDIO Host Controller support"
+ depends on HAS_DMA
help
This selects support for the Renesas USDHI6ROL0 SD/SDIO
Host Controller
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 7f81ddf1dd2c..f211eede8db5 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o
obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o
obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o
+obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f5443a6c4915..9c9f6af29251 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -32,6 +32,7 @@
* (the low to high transition will not occur).
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
@@ -90,7 +91,7 @@ struct au1xmmc_host {
struct mmc_request *mrq;
u32 flags;
- u32 iobase;
+ void __iomem *iobase;
u32 clock;
u32 bus_width;
u32 power_mode;
@@ -118,6 +119,7 @@ struct au1xmmc_host {
struct au1xmmc_platform_data *platdata;
struct platform_device *pdev;
struct resource *ioarea;
+ struct clk *clk;
};
/* Status flags used by the host structure */
@@ -162,32 +164,33 @@ static inline int has_dbdma(void)
static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
{
- u32 val = au_readl(HOST_CONFIG(host));
+ u32 val = __raw_readl(HOST_CONFIG(host));
val |= mask;
- au_writel(val, HOST_CONFIG(host));
- au_sync();
+ __raw_writel(val, HOST_CONFIG(host));
+ wmb(); /* drain writebuffer */
}
static inline void FLUSH_FIFO(struct au1xmmc_host *host)
{
- u32 val = au_readl(HOST_CONFIG2(host));
+ u32 val = __raw_readl(HOST_CONFIG2(host));
- au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
- au_sync_delay(1);
+ __raw_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
+ mdelay(1);
/* SEND_STOP will turn off clock control - this re-enables it */
val &= ~SD_CONFIG2_DF;
- au_writel(val, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(val, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
}
static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
{
- u32 val = au_readl(HOST_CONFIG(host));
+ u32 val = __raw_readl(HOST_CONFIG(host));
val &= ~mask;
- au_writel(val, HOST_CONFIG(host));
- au_sync();
+ __raw_writel(val, HOST_CONFIG(host));
+ wmb(); /* drain writebuffer */
}
static inline void SEND_STOP(struct au1xmmc_host *host)
@@ -197,12 +200,13 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
WARN_ON(host->status != HOST_S_DATA);
host->status = HOST_S_STOP;
- config2 = au_readl(HOST_CONFIG2(host));
- au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
- au_sync();
+ config2 = __raw_readl(HOST_CONFIG2(host));
+ __raw_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
/* Send the stop command */
- au_writel(STOP_CMD, HOST_CMD(host));
+ __raw_writel(STOP_CMD, HOST_CMD(host));
+ wmb(); /* drain writebuffer */
}
static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
@@ -296,28 +300,28 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
}
}
- au_writel(cmd->arg, HOST_CMDARG(host));
- au_sync();
+ __raw_writel(cmd->arg, HOST_CMDARG(host));
+ wmb(); /* drain writebuffer */
if (wait)
IRQ_OFF(host, SD_CONFIG_CR);
- au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
- au_sync();
+ __raw_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+ wmb(); /* drain writebuffer */
/* Wait for the command to go on the line */
- while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
+ while (__raw_readl(HOST_CMD(host)) & SD_CMD_GO)
/* nop */;
/* Wait for the command to come back */
if (wait) {
- u32 status = au_readl(HOST_STATUS(host));
+ u32 status = __raw_readl(HOST_STATUS(host));
while (!(status & SD_STATUS_CR))
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
/* Clear the CR status */
- au_writel(SD_STATUS_CR, HOST_STATUS(host));
+ __raw_writel(SD_STATUS_CR, HOST_STATUS(host));
IRQ_ON(host, SD_CONFIG_CR);
}
@@ -339,11 +343,11 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
data = mrq->cmd->data;
if (status == 0)
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
/* The transaction is really over when the SD_STATUS_DB bit is clear */
while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
data->error = 0;
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
@@ -357,7 +361,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
data->error = -EILSEQ;
/* Clear the CRC bits */
- au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+ __raw_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
data->bytes_xfered = 0;
@@ -380,7 +384,7 @@ static void au1xmmc_tasklet_data(unsigned long param)
{
struct au1xmmc_host *host = (struct au1xmmc_host *)param;
- u32 status = au_readl(HOST_STATUS(host));
+ u32 status = __raw_readl(HOST_STATUS(host));
au1xmmc_data_complete(host, status);
}
@@ -412,15 +416,15 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host)
max = AU1XMMC_MAX_TRANSFER;
for (count = 0; count < max; count++) {
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
if (!(status & SD_STATUS_TH))
break;
val = *sg_ptr++;
- au_writel((unsigned long)val, HOST_TXPORT(host));
- au_sync();
+ __raw_writel((unsigned long)val, HOST_TXPORT(host));
+ wmb(); /* drain writebuffer */
}
host->pio.len -= count;
@@ -472,7 +476,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
max = AU1XMMC_MAX_TRANSFER;
for (count = 0; count < max; count++) {
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
if (!(status & SD_STATUS_NE))
break;
@@ -494,7 +498,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
break;
}
- val = au_readl(HOST_RXPORT(host));
+ val = __raw_readl(HOST_RXPORT(host));
if (sg_ptr)
*sg_ptr++ = (unsigned char)(val & 0xFF);
@@ -537,10 +541,10 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
if (cmd->flags & MMC_RSP_PRESENT) {
if (cmd->flags & MMC_RSP_136) {
- r[0] = au_readl(host->iobase + SD_RESP3);
- r[1] = au_readl(host->iobase + SD_RESP2);
- r[2] = au_readl(host->iobase + SD_RESP1);
- r[3] = au_readl(host->iobase + SD_RESP0);
+ r[0] = __raw_readl(host->iobase + SD_RESP3);
+ r[1] = __raw_readl(host->iobase + SD_RESP2);
+ r[2] = __raw_readl(host->iobase + SD_RESP1);
+ r[3] = __raw_readl(host->iobase + SD_RESP0);
/* The CRC is omitted from the response, so really
* we only got 120 bytes, but the engine expects
@@ -559,7 +563,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
* that means that the OSR data starts at bit 31,
* so we can just read RESP0 and return that.
*/
- cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+ cmd->resp[0] = __raw_readl(host->iobase + SD_RESP0);
}
}
@@ -586,7 +590,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
u32 mask = SD_STATUS_DB | SD_STATUS_NE;
while((status & mask) != mask)
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
}
au1xxx_dbdma_start(channel);
@@ -595,24 +599,17 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
{
- unsigned int pbus = get_au1x00_speed();
- unsigned int divisor;
+ unsigned int pbus = clk_get_rate(host->clk);
+ unsigned int divisor = ((pbus / rate) / 2) - 1;
u32 config;
- /* From databook:
- * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
- */
- pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
- pbus /= 2;
- divisor = ((pbus / rate) / 2) - 1;
-
- config = au_readl(HOST_CONFIG(host));
+ config = __raw_readl(HOST_CONFIG(host));
config &= ~(SD_CONFIG_DIV);
config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
- au_writel(config, HOST_CONFIG(host));
- au_sync();
+ __raw_writel(config, HOST_CONFIG(host));
+ wmb(); /* drain writebuffer */
}
static int au1xmmc_prepare_data(struct au1xmmc_host *host,
@@ -636,7 +633,7 @@ static int au1xmmc_prepare_data(struct au1xmmc_host *host,
if (host->dma.len == 0)
return -ETIMEDOUT;
- au_writel(data->blksz - 1, HOST_BLKSIZE(host));
+ __raw_writel(data->blksz - 1, HOST_BLKSIZE(host));
if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
int i;
@@ -723,31 +720,34 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
static void au1xmmc_reset_controller(struct au1xmmc_host *host)
{
/* Apply the clock */
- au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
- au_sync_delay(1);
+ __raw_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+ wmb(); /* drain writebuffer */
+ mdelay(1);
- au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
- au_sync_delay(5);
+ __raw_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+ wmb(); /* drain writebuffer */
+ mdelay(5);
- au_writel(~0, HOST_STATUS(host));
- au_sync();
+ __raw_writel(~0, HOST_STATUS(host));
+ wmb(); /* drain writebuffer */
- au_writel(0, HOST_BLKSIZE(host));
- au_writel(0x001fffff, HOST_TIMEOUT(host));
- au_sync();
+ __raw_writel(0, HOST_BLKSIZE(host));
+ __raw_writel(0x001fffff, HOST_TIMEOUT(host));
+ wmb(); /* drain writebuffer */
- au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
- au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
- au_sync_delay(1);
+ __raw_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
+ mdelay(1);
- au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
/* Configure interrupts */
- au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
- au_sync();
+ __raw_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+ wmb(); /* drain writebuffer */
}
@@ -767,7 +767,7 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->clock = ios->clock;
}
- config2 = au_readl(HOST_CONFIG2(host));
+ config2 = __raw_readl(HOST_CONFIG2(host));
switch (ios->bus_width) {
case MMC_BUS_WIDTH_8:
config2 |= SD_CONFIG2_BB;
@@ -780,8 +780,8 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
break;
}
- au_writel(config2, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(config2, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
}
#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
@@ -793,7 +793,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
struct au1xmmc_host *host = dev_id;
u32 status;
- status = au_readl(HOST_STATUS(host));
+ status = __raw_readl(HOST_STATUS(host));
if (!(status & SD_STATUS_I))
return IRQ_NONE; /* not ours */
@@ -839,8 +839,8 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
status);
}
- au_writel(status, HOST_STATUS(host));
- au_sync();
+ __raw_writel(status, HOST_STATUS(host));
+ wmb(); /* drain writebuffer */
return IRQ_HANDLED;
}
@@ -976,7 +976,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
goto out1;
}
- host->iobase = (unsigned long)ioremap(r->start, 0x3c);
+ host->iobase = ioremap(r->start, 0x3c);
if (!host->iobase) {
dev_err(&pdev->dev, "cannot remap mmio\n");
goto out2;
@@ -1025,6 +1025,16 @@ static int au1xmmc_probe(struct platform_device *pdev)
goto out3;
}
+ host->clk = clk_get(&pdev->dev, ALCHEMY_PERIPH_CLK);
+ if (IS_ERR(host->clk)) {
+ dev_err(&pdev->dev, "cannot find clock\n");
+ goto out_irq;
+ }
+ if (clk_prepare_enable(host->clk)) {
+ dev_err(&pdev->dev, "cannot enable clock\n");
+ goto out_clk;
+ }
+
host->status = HOST_S_IDLE;
/* board-specific carddetect setup, if any */
@@ -1075,7 +1085,7 @@ static int au1xmmc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
- pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+ pr_info(DRIVER_NAME ": MMC Controller %d set up at %p"
" (mode=%s)\n", pdev->id, host->iobase,
host->flags & HOST_F_DMA ? "dma" : "pio");
@@ -1087,10 +1097,10 @@ out6:
led_classdev_unregister(host->platdata->led);
out5:
#endif
- au_writel(0, HOST_ENABLE(host));
- au_writel(0, HOST_CONFIG(host));
- au_writel(0, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(0, HOST_ENABLE(host));
+ __raw_writel(0, HOST_CONFIG(host));
+ __raw_writel(0, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
if (host->flags & HOST_F_DBDMA)
au1xmmc_dbdma_shutdown(host);
@@ -1101,7 +1111,10 @@ out5:
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0);
-
+out_clk:
+ clk_disable_unprepare(host->clk);
+ clk_put(host->clk);
+out_irq:
free_irq(host->irq, host);
out3:
iounmap((void *)host->iobase);
@@ -1130,10 +1143,10 @@ static int au1xmmc_remove(struct platform_device *pdev)
!(host->mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(host->mmc, 0);
- au_writel(0, HOST_ENABLE(host));
- au_writel(0, HOST_CONFIG(host));
- au_writel(0, HOST_CONFIG2(host));
- au_sync();
+ __raw_writel(0, HOST_ENABLE(host));
+ __raw_writel(0, HOST_CONFIG(host));
+ __raw_writel(0, HOST_CONFIG2(host));
+ wmb(); /* drain writebuffer */
tasklet_kill(&host->data_task);
tasklet_kill(&host->finish_task);
@@ -1143,6 +1156,9 @@ static int au1xmmc_remove(struct platform_device *pdev)
au1xmmc_set_power(host, 0);
+ clk_disable_unprepare(host->clk);
+ clk_put(host->clk);
+
free_irq(host->irq, host);
iounmap((void *)host->iobase);
release_resource(host->ioarea);
@@ -1158,11 +1174,11 @@ static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct au1xmmc_host *host = platform_get_drvdata(pdev);
- au_writel(0, HOST_CONFIG2(host));
- au_writel(0, HOST_CONFIG(host));
- au_writel(0xffffffff, HOST_STATUS(host));
- au_writel(0, HOST_ENABLE(host));
- au_sync();
+ __raw_writel(0, HOST_CONFIG2(host));
+ __raw_writel(0, HOST_CONFIG(host));
+ __raw_writel(0xffffffff, HOST_STATUS(host));
+ __raw_writel(0, HOST_ENABLE(host));
+ wmb(); /* drain writebuffer */
return 0;
}
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
index f70546a3a7cc..6ada1b36685b 100644
--- a/drivers/mmc/host/dw_mmc-pci.c
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -102,7 +102,7 @@ static int dw_mci_pci_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
-static DEFINE_PCI_DEVICE_TABLE(dw_mci_pci_id) = {
+static const struct pci_device_id dw_mci_pci_id[] = {
{ PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
{}
};
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 1ac227c603b7..8f216edbdf08 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = {
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};
-static inline bool dw_mci_fifo_reset(struct dw_mci *host);
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
+static bool dw_mci_reset(struct dw_mci *host);
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -997,7 +996,8 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
int gpio_ro = mmc_gpio_get_ro(mmc);
/* Use platform get_ro function, else try on board write protect */
- if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
+ if ((slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) ||
+ (slot->host->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT))
read_only = 0;
else if (!IS_ERR_VALUE(gpio_ro))
read_only = gpio_ro;
@@ -1235,7 +1235,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
* After an error, there may be data lingering
* in the FIFO
*/
- dw_mci_fifo_reset(host);
+ dw_mci_reset(host);
} else {
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
@@ -1352,7 +1352,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
/* CMD error in data command */
if (mrq->cmd->error && mrq->data)
- dw_mci_fifo_reset(host);
+ dw_mci_reset(host);
host->cmd = NULL;
host->data = NULL;
@@ -1963,14 +1963,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
}
/* Power down slot */
- if (present == 0) {
- /* Clear down the FIFO */
- dw_mci_fifo_reset(host);
-#ifdef CONFIG_MMC_DW_IDMAC
- dw_mci_idmac_reset(host);
-#endif
-
- }
+ if (present == 0)
+ dw_mci_reset(host);
spin_unlock_bh(&host->lock);
@@ -2021,8 +2015,11 @@ static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
/* get quirks */
for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++)
- if (of_get_property(np, of_slot_quirks[idx].quirk, NULL))
+ if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) {
+ dev_warn(dev, "Slot quirk %s is deprecated\n",
+ of_slot_quirks[idx].quirk);
quirks |= of_slot_quirks[idx].id;
+ }
return quirks;
}
@@ -2208,8 +2205,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
return false;
}
-static inline bool dw_mci_fifo_reset(struct dw_mci *host)
+static bool dw_mci_reset(struct dw_mci *host)
{
+ u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET;
+ bool ret = false;
+
/*
* Reseting generates a block interrupt, hence setting
* the scatter-gather pointer to NULL.
@@ -2219,15 +2219,60 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host)
host->sg = NULL;
}
- return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
-}
+ if (host->use_dma)
+ flags |= SDMMC_CTRL_DMA_RESET;
-static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
-{
- return dw_mci_ctrl_reset(host,
- SDMMC_CTRL_FIFO_RESET |
- SDMMC_CTRL_RESET |
- SDMMC_CTRL_DMA_RESET);
+ if (dw_mci_ctrl_reset(host, flags)) {
+ /*
+ * In all cases we clear the RAWINTS register to clear any
+ * interrupts.
+ */
+ mci_writel(host, RINTSTS, 0xFFFFFFFF);
+
+ /* if using dma we wait for dma_req to clear */
+ if (host->use_dma) {
+ unsigned long timeout = jiffies + msecs_to_jiffies(500);
+ u32 status;
+ do {
+ status = mci_readl(host, STATUS);
+ if (!(status & SDMMC_STATUS_DMA_REQ))
+ break;
+ cpu_relax();
+ } while (time_before(jiffies, timeout));
+
+ if (status & SDMMC_STATUS_DMA_REQ) {
+ dev_err(host->dev,
+ "%s: Timeout waiting for dma_req to "
+ "clear during reset\n", __func__);
+ goto ciu_out;
+ }
+
+ /* when using DMA next we reset the fifo again */
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET))
+ goto ciu_out;
+ }
+ } else {
+ /* if the controller reset bit did clear, then set clock regs */
+ if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) {
+ dev_err(host->dev, "%s: fifo/dma reset bits didn't "
+ "clear but ciu was reset, doing clock update\n",
+ __func__);
+ goto ciu_out;
+ }
+ }
+
+#if IS_ENABLED(CONFIG_MMC_DW_IDMAC)
+ /* It is also recommended that we reset and reprogram idmac */
+ dw_mci_idmac_reset(host);
+#endif
+
+ ret = true;
+
+ciu_out:
+ /* After a CTRL reset we need to have CIU set clock registers */
+ mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0);
+
+ return ret;
}
#ifdef CONFIG_OF
@@ -2238,6 +2283,9 @@ static struct dw_mci_of_quirks {
{
.quirk = "broken-cd",
.id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
+ }, {
+ .quirk = "disable-wp",
+ .id = DW_MCI_QUIRK_NO_WRITE_PROTECT,
},
};
@@ -2425,7 +2473,7 @@ int dw_mci_probe(struct dw_mci *host)
}
/* Reset all blocks */
- if (!dw_mci_ctrl_all_reset(host))
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
return -ENODEV;
host->dma_ops = host->pdata->dma_ops;
@@ -2612,7 +2660,7 @@ int dw_mci_resume(struct dw_mci *host)
}
}
- if (!dw_mci_ctrl_all_reset(host)) {
+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
ret = -ENODEV;
return ret;
}
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 738fa241d058..08fd956d81f3 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -129,6 +129,7 @@
#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
/* Status register defines */
#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF)
+#define SDMMC_STATUS_DMA_REQ BIT(31)
/* FIFOTH register defines */
#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \
((r) & 0xFFF) << 16 | \
@@ -150,6 +151,10 @@
/* Card read threshold */
#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x))
+/* All ctrl reset bits */
+#define SDMMC_CTRL_ALL_RESET_FLAGS \
+ (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)
+
/* Register access macros */
#define mci_readl(dev, reg) \
__raw_readl((dev)->regs + SDMMC_##reg)
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 7ad463e9741c..e4d470704150 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -52,34 +52,53 @@ static unsigned int fmax = 515633;
* struct variant_data - MMCI variant-specific quirks
* @clkreg: default value for MCICLOCK register
* @clkreg_enable: enable value for MMCICLOCK register
+ * @clkreg_8bit_bus_enable: enable value for 8 bit bus
+ * @clkreg_neg_edge_enable: enable value for inverted data/cmd output
* @datalength_bits: number of bits in the MMCIDATALENGTH register
* @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
* is asserted (likewise for RX)
* @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
* is asserted (likewise for RX)
+ * @data_cmd_enable: enable value for data commands.
* @sdio: variant supports SDIO
* @st_clkdiv: true if using a ST-specific clock divider algorithm
+ * @datactrl_mask_ddrmode: ddr mode mask in datactrl register.
* @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
+ * @blksz_datactrl4: true if Block size is at b4..b16 position in datactrl
+ * register
* @pwrreg_powerup: power up value for MMCIPOWER register
+ * @f_max: maximum clk frequency supported by the controller.
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
* @busy_detect: true if busy detection on dat0 is supported
* @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
+ * @explicit_mclk_control: enable explicit mclk control in driver.
+ * @qcom_fifo: enables qcom specific fifo pio read logic.
+ * @reversed_irq_handling: handle data irq before cmd irq.
*/
struct variant_data {
unsigned int clkreg;
unsigned int clkreg_enable;
+ unsigned int clkreg_8bit_bus_enable;
+ unsigned int clkreg_neg_edge_enable;
unsigned int datalength_bits;
unsigned int fifosize;
unsigned int fifohalfsize;
+ unsigned int data_cmd_enable;
+ unsigned int datactrl_mask_ddrmode;
bool sdio;
bool st_clkdiv;
bool blksz_datactrl16;
+ bool blksz_datactrl4;
u32 pwrreg_powerup;
+ u32 f_max;
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
bool pwrreg_nopower;
+ bool explicit_mclk_control;
+ bool qcom_fifo;
+ bool reversed_irq_handling;
};
static struct variant_data variant_arm = {
@@ -87,6 +106,8 @@ static struct variant_data variant_arm = {
.fifohalfsize = 8 * 4,
.datalength_bits = 16,
.pwrreg_powerup = MCI_PWR_UP,
+ .f_max = 100000000,
+ .reversed_irq_handling = true,
};
static struct variant_data variant_arm_extended_fifo = {
@@ -94,6 +115,7 @@ static struct variant_data variant_arm_extended_fifo = {
.fifohalfsize = 64 * 4,
.datalength_bits = 16,
.pwrreg_powerup = MCI_PWR_UP,
+ .f_max = 100000000,
};
static struct variant_data variant_arm_extended_fifo_hwfc = {
@@ -102,15 +124,18 @@ static struct variant_data variant_arm_extended_fifo_hwfc = {
.clkreg_enable = MCI_ARM_HWFCEN,
.datalength_bits = 16,
.pwrreg_powerup = MCI_PWR_UP,
+ .f_max = 100000000,
};
static struct variant_data variant_u300 = {
.fifosize = 16 * 4,
.fifohalfsize = 8 * 4,
.clkreg_enable = MCI_ST_U300_HWFCEN,
+ .clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
.datalength_bits = 16,
.sdio = true,
.pwrreg_powerup = MCI_PWR_ON,
+ .f_max = 100000000,
.signal_direction = true,
.pwrreg_clkgate = true,
.pwrreg_nopower = true,
@@ -124,6 +149,7 @@ static struct variant_data variant_nomadik = {
.sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
+ .f_max = 100000000,
.signal_direction = true,
.pwrreg_clkgate = true,
.pwrreg_nopower = true,
@@ -134,10 +160,13 @@ static struct variant_data variant_ux500 = {
.fifohalfsize = 8 * 4,
.clkreg = MCI_CLK_ENABLE,
.clkreg_enable = MCI_ST_UX500_HWFCEN,
+ .clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
+ .clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
.datalength_bits = 24,
.sdio = true,
.st_clkdiv = true,
.pwrreg_powerup = MCI_PWR_ON,
+ .f_max = 100000000,
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
@@ -149,17 +178,38 @@ static struct variant_data variant_ux500v2 = {
.fifohalfsize = 8 * 4,
.clkreg = MCI_CLK_ENABLE,
.clkreg_enable = MCI_ST_UX500_HWFCEN,
+ .clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
+ .clkreg_neg_edge_enable = MCI_ST_UX500_NEG_EDGE,
+ .datactrl_mask_ddrmode = MCI_ST_DPSM_DDRMODE,
.datalength_bits = 24,
.sdio = true,
.st_clkdiv = true,
.blksz_datactrl16 = true,
.pwrreg_powerup = MCI_PWR_ON,
+ .f_max = 100000000,
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
.pwrreg_nopower = true,
};
+static struct variant_data variant_qcom = {
+ .fifosize = 16 * 4,
+ .fifohalfsize = 8 * 4,
+ .clkreg = MCI_CLK_ENABLE,
+ .clkreg_enable = MCI_QCOM_CLK_FLOWENA |
+ MCI_QCOM_CLK_SELECT_IN_FBCLK,
+ .clkreg_8bit_bus_enable = MCI_QCOM_CLK_WIDEBUS_8,
+ .datactrl_mask_ddrmode = MCI_QCOM_CLK_SELECT_IN_DDR_MODE,
+ .data_cmd_enable = MCI_QCOM_CSPM_DATCMD,
+ .blksz_datactrl4 = true,
+ .datalength_bits = 24,
+ .pwrreg_powerup = MCI_PWR_UP,
+ .f_max = 208000000,
+ .explicit_mclk_control = true,
+ .qcom_fifo = true,
+};
+
static int mmci_card_busy(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
@@ -260,7 +310,9 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
host->cclk = 0;
if (desired) {
- if (desired >= host->mclk) {
+ if (variant->explicit_mclk_control) {
+ host->cclk = host->mclk;
+ } else if (desired >= host->mclk) {
clk = MCI_CLK_BYPASS;
if (variant->st_clkdiv)
clk |= MCI_ST_UX500_NEG_EDGE;
@@ -299,11 +351,11 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4)
clk |= MCI_4BIT_BUS;
if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8)
- clk |= MCI_ST_8BIT_BUS;
+ clk |= variant->clkreg_8bit_bus_enable;
if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
- clk |= MCI_ST_UX500_NEG_EDGE;
+ clk |= variant->clkreg_neg_edge_enable;
mmci_write_clkreg(host, clk);
}
@@ -719,7 +771,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
data->bytes_xfered = 0;
clks = (unsigned long long)data->timeout_ns * host->cclk;
- do_div(clks, 1000000000UL);
+ do_div(clks, NSEC_PER_SEC);
timeout = data->timeout_clks + (unsigned int)clks;
@@ -732,6 +784,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
if (variant->blksz_datactrl16)
datactrl = MCI_DPSM_ENABLE | (data->blksz << 16);
+ else if (variant->blksz_datactrl4)
+ datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
else
datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
@@ -767,7 +821,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
if (host->mmc->ios.timing == MMC_TIMING_UHS_DDR50 ||
host->mmc->ios.timing == MMC_TIMING_MMC_DDR52)
- datactrl |= MCI_ST_DPSM_DDRMODE;
+ datactrl |= variant->datactrl_mask_ddrmode;
/*
* Attempt to use DMA operation mode, if this
@@ -812,7 +866,7 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
writel(0, base + MMCICOMMAND);
- udelay(1);
+ mmci_reg_delay(host);
}
c |= cmd->opcode | MCI_CPSM_ENABLE;
@@ -824,6 +878,9 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
if (/*interrupt*/0)
c |= MCI_CPSM_INTERRUPT;
+ if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
+ c |= host->variant->data_cmd_enable;
+
host->cmd = cmd;
writel(cmd->arg, base + MMCIARGUMENT);
@@ -834,6 +891,10 @@ static void
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
unsigned int status)
{
+ /* Make sure we have data to handle */
+ if (!data)
+ return;
+
/* First check for errors */
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
@@ -902,9 +963,17 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
unsigned int status)
{
void __iomem *base = host->base;
- bool sbc = (cmd == host->mrq->sbc);
- bool busy_resp = host->variant->busy_detect &&
- (cmd->flags & MMC_RSP_BUSY);
+ bool sbc, busy_resp;
+
+ if (!cmd)
+ return;
+
+ sbc = (cmd == host->mrq->sbc);
+ busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
+
+ if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
+ MCI_CMDSENT|MCI_CMDRESPEND)))
+ return;
/* Check if we need to wait for busy completion. */
if (host->busy_status && (status & MCI_ST_CARDBUSY))
@@ -957,15 +1026,34 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
}
+static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain)
+{
+ return remain - (readl(host->base + MMCIFIFOCNT) << 2);
+}
+
+static int mmci_qcom_get_rx_fifocnt(struct mmci_host *host, u32 status, int r)
+{
+ /*
+ * on qcom SDCC4 only 8 words are used in each burst so only 8 addresses
+ * from the fifo range should be used
+ */
+ if (status & MCI_RXFIFOHALFFULL)
+ return host->variant->fifohalfsize;
+ else if (status & MCI_RXDATAAVLBL)
+ return 4;
+
+ return 0;
+}
+
static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
{
void __iomem *base = host->base;
char *ptr = buffer;
- u32 status;
+ u32 status = readl(host->base + MMCISTATUS);
int host_remain = host->size;
do {
- int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
+ int count = host->get_rx_fifocnt(host, status, host_remain);
if (count > remain)
count = remain;
@@ -1132,9 +1220,6 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
spin_lock(&host->lock);
do {
- struct mmc_command *cmd;
- struct mmc_data *data;
-
status = readl(host->base + MMCISTATUS);
if (host->singleirq) {
@@ -1154,16 +1239,13 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
- cmd = host->cmd;
- if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
- MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
- mmci_cmd_irq(host, cmd, status);
-
- data = host->data;
- if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
- MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
- MCI_DATABLOCKEND) && data)
- mmci_data_irq(host, data, status);
+ if (host->variant->reversed_irq_handling) {
+ mmci_data_irq(host, host->data, status);
+ mmci_cmd_irq(host, host->cmd, status);
+ } else {
+ mmci_cmd_irq(host, host->cmd, status);
+ mmci_data_irq(host, host->data, status);
+ }
/* Don't poll for busy completion in irq context. */
if (host->busy_status)
@@ -1296,6 +1378,17 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (!ios->clock && variant->pwrreg_clkgate)
pwr &= ~MCI_PWR_ON;
+ if (host->variant->explicit_mclk_control &&
+ ios->clock != host->clock_cache) {
+ ret = clk_set_rate(host->clk, ios->clock);
+ if (ret < 0)
+ dev_err(mmc_dev(host->mmc),
+ "Error setting clock rate (%d)\n", ret);
+ else
+ host->mclk = clk_get_rate(host->clk);
+ }
+ host->clock_cache = ios->clock;
+
spin_lock_irqsave(&host->lock, flags);
mmci_set_clkreg(host, ios->clock);
@@ -1443,6 +1536,11 @@ static int mmci_probe(struct amba_device *dev,
if (ret)
goto host_free;
+ if (variant->qcom_fifo)
+ host->get_rx_fifocnt = mmci_qcom_get_rx_fifocnt;
+ else
+ host->get_rx_fifocnt = mmci_get_rx_fifocnt;
+
host->plat = plat;
host->variant = variant;
host->mclk = clk_get_rate(host->clk);
@@ -1451,8 +1549,8 @@ static int mmci_probe(struct amba_device *dev,
* so we try to adjust the clock down to this,
* (if possible).
*/
- if (host->mclk > 100000000) {
- ret = clk_set_rate(host->clk, 100000000);
+ if (host->mclk > variant->f_max) {
+ ret = clk_set_rate(host->clk, variant->f_max);
if (ret < 0)
goto clk_disable;
host->mclk = clk_get_rate(host->clk);
@@ -1471,9 +1569,12 @@ static int mmci_probe(struct amba_device *dev,
* The ARM and ST versions of the block have slightly different
* clock divider equations which means that the minimum divider
* differs too.
+ * on Qualcomm like controllers get the nearest minimum clock to 100Khz
*/
if (variant->st_clkdiv)
mmc->f_min = DIV_ROUND_UP(host->mclk, 257);
+ else if (variant->explicit_mclk_control)
+ mmc->f_min = clk_round_rate(host->clk, 100000);
else
mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
/*
@@ -1483,9 +1584,14 @@ static int mmci_probe(struct amba_device *dev,
* the block, of course.
*/
if (mmc->f_max)
- mmc->f_max = min(host->mclk, mmc->f_max);
+ mmc->f_max = variant->explicit_mclk_control ?
+ min(variant->f_max, mmc->f_max) :
+ min(host->mclk, mmc->f_max);
else
- mmc->f_max = min(host->mclk, fmax);
+ mmc->f_max = variant->explicit_mclk_control ?
+ fmax : min(host->mclk, fmax);
+
+
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
/* Get regulators and the supported OCR mask */
@@ -1752,6 +1858,12 @@ static struct amba_id mmci_ids[] = {
.mask = 0xf0ffffff,
.data = &variant_ux500v2,
},
+ /* Qualcomm variants */
+ {
+ .id = 0x00051180,
+ .mask = 0x000fffff,
+ .data = &variant_qcom,
+ },
{ 0, 0 },
};
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 347d942d740b..a1f5e4f49e2a 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -41,6 +41,15 @@
/* Modified PL180 on Versatile Express platform */
#define MCI_ARM_HWFCEN (1 << 12)
+/* Modified on Qualcomm Integrations */
+#define MCI_QCOM_CLK_WIDEBUS_8 (BIT(10) | BIT(11))
+#define MCI_QCOM_CLK_FLOWENA BIT(12)
+#define MCI_QCOM_CLK_INVERTOUT BIT(13)
+
+/* select in latch data and command in */
+#define MCI_QCOM_CLK_SELECT_IN_FBCLK BIT(15)
+#define MCI_QCOM_CLK_SELECT_IN_DDR_MODE (BIT(14) | BIT(15))
+
#define MMCIARGUMENT 0x008
#define MMCICOMMAND 0x00c
#define MCI_CPSM_RESPONSE (1 << 6)
@@ -54,6 +63,14 @@
#define MCI_ST_NIEN (1 << 13)
#define MCI_ST_CE_ATACMD (1 << 14)
+/* Modified on Qualcomm Integrations */
+#define MCI_QCOM_CSPM_DATCMD BIT(12)
+#define MCI_QCOM_CSPM_MCIABORT BIT(13)
+#define MCI_QCOM_CSPM_CCSENABLE BIT(14)
+#define MCI_QCOM_CSPM_CCSDISABLE BIT(15)
+#define MCI_QCOM_CSPM_AUTO_CMD19 BIT(16)
+#define MCI_QCOM_CSPM_AUTO_CMD21 BIT(21)
+
#define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014
#define MMCIRESPONSE1 0x018
@@ -191,6 +208,8 @@ struct mmci_host {
spinlock_t lock;
unsigned int mclk;
+ /* cached value of requested clk in set_ios */
+ unsigned int clock_cache;
unsigned int cclk;
u32 pwr_reg;
u32 pwr_reg_add;
@@ -210,6 +229,7 @@ struct mmci_host {
/* pio stuff */
struct sg_mapping_iter sg_miter;
unsigned int size;
+ int (*get_rx_fifocnt)(struct mmci_host *h, u32 status, int remain);
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
index 74924a04026e..b4b1efbf6c16 100644
--- a/drivers/mmc/host/moxart-mmc.c
+++ b/drivers/mmc/host/moxart-mmc.c
@@ -13,7 +13,6 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index babfea03ba8a..140885a5a4e7 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -86,7 +86,8 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc)
if (ret >= 0)
return ret;
- present = !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
+ present = mmc->caps & MMC_CAP_NEEDS_POLL ||
+ !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
BM_SSP_STATUS_CARD_DETECT);
if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 6b7b75585926..965672663ef0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -29,6 +29,7 @@
#include <linux/timer.h>
#include <linux/clk.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/omap-dmaengine.h>
@@ -36,6 +37,7 @@
#include <linux/mmc/core.h>
#include <linux/mmc/mmc.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
@@ -54,6 +56,7 @@
#define OMAP_HSMMC_RSP54 0x0118
#define OMAP_HSMMC_RSP76 0x011C
#define OMAP_HSMMC_DATA 0x0120
+#define OMAP_HSMMC_PSTATE 0x0124
#define OMAP_HSMMC_HCTL 0x0128
#define OMAP_HSMMC_SYSCTL 0x012C
#define OMAP_HSMMC_STAT 0x0130
@@ -91,7 +94,10 @@
#define BCE (1 << 1)
#define FOUR_BIT (1 << 1)
#define HSPE (1 << 2)
+#define IWE (1 << 24)
#define DDR (1 << 19)
+#define CLKEXTFREE (1 << 16)
+#define CTPL (1 << 11)
#define DW8 (1 << 5)
#define OD 0x1
#define STAT_CLEAR 0xFFFFFFFF
@@ -101,11 +107,15 @@
#define SRD (1 << 26)
#define SOFTRESET (1 << 1)
+/* PSTATE */
+#define DLEV_DAT(x) (1 << (20 + (x)))
+
/* 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 CIRQ_EN (1 << 8)
#define ERR_EN (1 << 15)
#define CTO_EN (1 << 16)
#define CCRC_EN (1 << 17)
@@ -140,7 +150,6 @@
#define VDD_3V0 3000000 /* 300000 uV */
#define VDD_165_195 (ffs(MMC_VDD_165_195) - 1)
-#define AUTO_CMD23 (1 << 1) /* Auto CMD23 support */
/*
* One controller can have multiple slots, like on some omap boards using
* omap.c controller driver. Luckily this is not currently done on any known
@@ -194,6 +203,7 @@ struct omap_hsmmc_host {
u32 sysctl;
u32 capa;
int irq;
+ int wake_irq;
int use_dma, dma_ch;
struct dma_chan *tx_chan;
struct dma_chan *rx_chan;
@@ -206,6 +216,9 @@ struct omap_hsmmc_host {
int req_in_progress;
unsigned long clk_rate;
unsigned int flags;
+#define AUTO_CMD23 (1 << 0) /* Auto CMD23 support */
+#define HSMMC_SDIO_IRQ_ENABLED (1 << 1) /* SDIO irq enabled */
+#define HSMMC_WAKE_IRQ_ENABLED (1 << 2)
struct omap_hsmmc_next next_data;
struct omap_mmc_platform_data *pdata;
};
@@ -510,27 +523,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
struct mmc_command *cmd)
{
- unsigned int irq_mask;
+ u32 irq_mask = INT_EN_MASK;
+ unsigned long flags;
if (host->use_dma)
- irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
- else
- irq_mask = INT_EN_MASK;
+ irq_mask &= ~(BRR_EN | BWR_EN);
/* Disable timeout for erases */
if (cmd->opcode == MMC_ERASE)
irq_mask &= ~DTO_EN;
+ spin_lock_irqsave(&host->irq_lock, flags);
OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+ /* latch pending CIRQ, but don't signal MMC core */
+ if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+ irq_mask |= CIRQ_EN;
OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+ spin_unlock_irqrestore(&host->irq_lock, flags);
}
static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
{
- OMAP_HSMMC_WRITE(host->base, ISE, 0);
- OMAP_HSMMC_WRITE(host->base, IE, 0);
+ u32 irq_mask = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->irq_lock, flags);
+ /* no transfer running but need to keep cirq if enabled */
+ if (host->flags & HSMMC_SDIO_IRQ_ENABLED)
+ irq_mask |= CIRQ_EN;
+ OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+ OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+ spin_unlock_irqrestore(&host->irq_lock, flags);
}
/* Calculate divisor for the given clock frequency */
@@ -667,6 +693,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
capa = VS18;
}
+ if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
+ hctl |= IWE;
+
OMAP_HSMMC_WRITE(host->base, HCTL,
OMAP_HSMMC_READ(host->base, HCTL) | hctl);
@@ -681,7 +710,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
&& time_before(jiffies, timeout))
;
- omap_hsmmc_disable_irq(host);
+ OMAP_HSMMC_WRITE(host->base, ISE, 0);
+ OMAP_HSMMC_WRITE(host->base, IE, 0);
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
/* Do not initialize card-specific things if the power is off */
if (host->power_mode == MMC_POWER_OFF)
@@ -1118,8 +1149,12 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
int status;
status = OMAP_HSMMC_READ(host->base, STAT);
- while (status & INT_EN_MASK && host->req_in_progress) {
- omap_hsmmc_do_irq(host, status);
+ while (status & (INT_EN_MASK | CIRQ_EN)) {
+ if (host->req_in_progress)
+ omap_hsmmc_do_irq(host, status);
+
+ if (status & CIRQ_EN)
+ mmc_signal_sdio_irq(host->mmc);
/* Flush posted write */
status = OMAP_HSMMC_READ(host->base, STAT);
@@ -1128,6 +1163,22 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t omap_hsmmc_wake_irq(int irq, void *dev_id)
+{
+ struct omap_hsmmc_host *host = dev_id;
+
+ /* cirq is level triggered, disable to avoid infinite loop */
+ spin_lock(&host->irq_lock);
+ if (host->flags & HSMMC_WAKE_IRQ_ENABLED) {
+ disable_irq_nosync(host->wake_irq);
+ host->flags &= ~HSMMC_WAKE_IRQ_ENABLED;
+ }
+ spin_unlock(&host->irq_lock);
+ pm_request_resume(host->dev); /* no use counter */
+
+ return IRQ_HANDLED;
+}
+
static void set_sd_bus_power(struct omap_hsmmc_host *host)
{
unsigned long i;
@@ -1639,6 +1690,103 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
mmc_slot(host).init_card(card);
}
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct omap_hsmmc_host *host = mmc_priv(mmc);
+ u32 irq_mask, con;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->irq_lock, flags);
+
+ con = OMAP_HSMMC_READ(host->base, CON);
+ irq_mask = OMAP_HSMMC_READ(host->base, ISE);
+ if (enable) {
+ host->flags |= HSMMC_SDIO_IRQ_ENABLED;
+ irq_mask |= CIRQ_EN;
+ con |= CTPL | CLKEXTFREE;
+ } else {
+ host->flags &= ~HSMMC_SDIO_IRQ_ENABLED;
+ irq_mask &= ~CIRQ_EN;
+ con &= ~(CTPL | CLKEXTFREE);
+ }
+ OMAP_HSMMC_WRITE(host->base, CON, con);
+ OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
+
+ /*
+ * if enable, piggy back detection on current request
+ * but always disable immediately
+ */
+ if (!host->req_in_progress || !enable)
+ OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
+
+ /* flush posted write */
+ OMAP_HSMMC_READ(host->base, IE);
+
+ spin_unlock_irqrestore(&host->irq_lock, flags);
+}
+
+static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+ int ret;
+
+ /*
+ * For omaps with wake-up path, wakeirq will be irq from pinctrl and
+ * for other omaps, wakeirq will be from GPIO (dat line remuxed to
+ * gpio). wakeirq is needed to detect sdio irq in runtime suspend state
+ * with functional clock disabled.
+ */
+ if (!host->dev->of_node || !host->wake_irq)
+ return -ENODEV;
+
+ /* Prevent auto-enabling of IRQ */
+ irq_set_status_flags(host->wake_irq, IRQ_NOAUTOEN);
+ ret = devm_request_irq(host->dev, host->wake_irq, omap_hsmmc_wake_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ mmc_hostname(mmc), host);
+ if (ret) {
+ dev_err(mmc_dev(host->mmc), "Unable to request wake IRQ\n");
+ goto err;
+ }
+
+ /*
+ * Some omaps don't have wake-up path from deeper idle states
+ * and need to remux SDIO DAT1 to GPIO for wake-up from idle.
+ */
+ if (host->pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
+ struct pinctrl *p = devm_pinctrl_get(host->dev);
+ if (!p) {
+ ret = -ENODEV;
+ goto err_free_irq;
+ }
+ if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_DEFAULT))) {
+ dev_info(host->dev, "missing default pinctrl state\n");
+ devm_pinctrl_put(p);
+ ret = -EINVAL;
+ goto err_free_irq;
+ }
+
+ if (IS_ERR(pinctrl_lookup_state(p, PINCTRL_STATE_IDLE))) {
+ dev_info(host->dev, "missing idle pinctrl state\n");
+ devm_pinctrl_put(p);
+ ret = -EINVAL;
+ goto err_free_irq;
+ }
+ devm_pinctrl_put(p);
+ }
+
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | IWE);
+ return 0;
+
+err_free_irq:
+ devm_free_irq(host->dev, host->wake_irq, host);
+err:
+ dev_warn(host->dev, "no SDIO IRQ support, falling back to polling\n");
+ host->wake_irq = 0;
+ return ret;
+}
+
static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
{
u32 hctl, capa, value;
@@ -1691,7 +1839,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
.get_cd = omap_hsmmc_get_cd,
.get_ro = omap_hsmmc_get_ro,
.init_card = omap_hsmmc_init_card,
- /* NYET -- enable_sdio_irq */
+ .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
};
#ifdef CONFIG_DEBUG_FS
@@ -1701,13 +1849,23 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
struct mmc_host *mmc = s->private;
struct omap_hsmmc_host *host = mmc_priv(mmc);
- seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n",
- mmc->index, host->context_loss);
+ seq_printf(s, "mmc%d:\n", mmc->index);
+ seq_printf(s, "sdio irq mode\t%s\n",
+ (mmc->caps & MMC_CAP_SDIO_IRQ) ? "interrupt" : "polling");
- pm_runtime_get_sync(host->dev);
+ if (mmc->caps & MMC_CAP_SDIO_IRQ) {
+ seq_printf(s, "sdio irq \t%s\n",
+ (host->flags & HSMMC_SDIO_IRQ_ENABLED) ? "enabled"
+ : "disabled");
+ }
+ seq_printf(s, "ctx_loss:\t%d\n", host->context_loss);
+ pm_runtime_get_sync(host->dev);
+ seq_puts(s, "\nregs:\n");
seq_printf(s, "CON:\t\t0x%08x\n",
OMAP_HSMMC_READ(host->base, CON));
+ seq_printf(s, "PSTATE:\t\t0x%08x\n",
+ OMAP_HSMMC_READ(host->base, PSTATE));
seq_printf(s, "HCTL:\t\t0x%08x\n",
OMAP_HSMMC_READ(host->base, HCTL));
seq_printf(s, "SYSCTL:\t\t0x%08x\n",
@@ -1761,6 +1919,10 @@ static const struct omap_mmc_of_data omap3_pre_es3_mmc_of_data = {
static const struct omap_mmc_of_data omap4_mmc_of_data = {
.reg_offset = 0x100,
};
+static const struct omap_mmc_of_data am33xx_mmc_of_data = {
+ .reg_offset = 0x100,
+ .controller_flags = OMAP_HSMMC_SWAKEUP_MISSING,
+};
static const struct of_device_id omap_mmc_of_match[] = {
{
@@ -1777,6 +1939,10 @@ static const struct of_device_id omap_mmc_of_match[] = {
.compatible = "ti,omap4-hsmmc",
.data = &omap4_mmc_of_data,
},
+ {
+ .compatible = "ti,am33xx-hsmmc",
+ .data = &am33xx_mmc_of_data,
+ },
{},
};
MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
@@ -1850,7 +2016,6 @@ static int 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;
const struct omap_mmc_of_data *data;
void __iomem *base;
@@ -1913,6 +2078,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
+ if (pdev->dev.of_node)
+ host->wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
mmc->ops = &omap_hsmmc_ops;
mmc->f_min = OMAP_MMC_MIN_CLOCK;
@@ -2061,10 +2229,17 @@ static int 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");
+ /*
+ * For now, only support SDIO interrupt if we have a separate
+ * wake-up interrupt configured from device tree. This is because
+ * the wake-up interrupt is needed for idle state and some
+ * platforms need special quirks. And we don't want to add new
+ * legacy mux platform init code callbacks any longer as we
+ * are moving to DT based booting anyways.
+ */
+ ret = omap_hsmmc_configure_wake_irq(host);
+ if (!ret)
+ mmc->caps |= MMC_CAP_SDIO_IRQ;
omap_hsmmc_protect_card(host);
@@ -2170,11 +2345,18 @@ static int omap_hsmmc_suspend(struct device *dev)
pm_runtime_get_sync(host->dev);
if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
- omap_hsmmc_disable_irq(host);
+ OMAP_HSMMC_WRITE(host->base, ISE, 0);
+ OMAP_HSMMC_WRITE(host->base, IE, 0);
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
OMAP_HSMMC_WRITE(host->base, HCTL,
OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
}
+ /* do not wake up due to sdio irq */
+ if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+ !(host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
+ disable_irq(host->wake_irq);
+
if (host->dbclk)
clk_disable_unprepare(host->dbclk);
@@ -2200,6 +2382,10 @@ static int omap_hsmmc_resume(struct device *dev)
omap_hsmmc_protect_card(host);
+ if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+ !(host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ))
+ enable_irq(host->wake_irq);
+
pm_runtime_mark_last_busy(host->dev);
pm_runtime_put_autosuspend(host->dev);
return 0;
@@ -2215,22 +2401,77 @@ static int omap_hsmmc_resume(struct device *dev)
static int omap_hsmmc_runtime_suspend(struct device *dev)
{
struct omap_hsmmc_host *host;
+ unsigned long flags;
+ int ret = 0;
host = platform_get_drvdata(to_platform_device(dev));
omap_hsmmc_context_save(host);
dev_dbg(dev, "disabled\n");
- return 0;
+ spin_lock_irqsave(&host->irq_lock, flags);
+ if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+ (host->flags & HSMMC_SDIO_IRQ_ENABLED)) {
+ /* disable sdio irq handling to prevent race */
+ OMAP_HSMMC_WRITE(host->base, ISE, 0);
+ OMAP_HSMMC_WRITE(host->base, IE, 0);
+
+ if (!(OMAP_HSMMC_READ(host->base, PSTATE) & DLEV_DAT(1))) {
+ /*
+ * dat1 line low, pending sdio irq
+ * race condition: possible irq handler running on
+ * multi-core, abort
+ */
+ dev_dbg(dev, "pending sdio irq, abort suspend\n");
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+ OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+ OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+ pm_runtime_mark_last_busy(dev);
+ ret = -EBUSY;
+ goto abort;
+ }
+
+ pinctrl_pm_select_idle_state(dev);
+
+ WARN_ON(host->flags & HSMMC_WAKE_IRQ_ENABLED);
+ enable_irq(host->wake_irq);
+ host->flags |= HSMMC_WAKE_IRQ_ENABLED;
+ } else {
+ pinctrl_pm_select_idle_state(dev);
+ }
+
+abort:
+ spin_unlock_irqrestore(&host->irq_lock, flags);
+ return ret;
}
static int omap_hsmmc_runtime_resume(struct device *dev)
{
struct omap_hsmmc_host *host;
+ unsigned long flags;
host = platform_get_drvdata(to_platform_device(dev));
omap_hsmmc_context_restore(host);
dev_dbg(dev, "enabled\n");
+ spin_lock_irqsave(&host->irq_lock, flags);
+ if ((host->mmc->caps & MMC_CAP_SDIO_IRQ) &&
+ (host->flags & HSMMC_SDIO_IRQ_ENABLED)) {
+ /* sdio irq flag can't change while in runtime suspend */
+ if (host->flags & HSMMC_WAKE_IRQ_ENABLED) {
+ disable_irq_nosync(host->wake_irq);
+ host->flags &= ~HSMMC_WAKE_IRQ_ENABLED;
+ }
+
+ pinctrl_pm_select_default_state(host->dev);
+
+ /* irq lost, if pinmux incorrect */
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+ OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
+ OMAP_HSMMC_WRITE(host->base, IE, CIRQ_EN);
+ } else {
+ pinctrl_pm_select_default_state(host->dev);
+ }
+ spin_unlock_irqrestore(&host->irq_lock, flags);
return 0;
}
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 0d519649b575..dfde4a210238 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -24,6 +24,7 @@
#include <linux/highmem.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <linux/workqueue.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
@@ -36,7 +37,10 @@ struct realtek_pci_sdmmc {
struct rtsx_pcr *pcr;
struct mmc_host *mmc;
struct mmc_request *mrq;
+ struct workqueue_struct *workq;
+#define SDMMC_WORKQ_NAME "rtsx_pci_sdmmc_workq"
+ struct work_struct work;
struct mutex host_mutex;
u8 ssc_depth;
@@ -48,6 +52,11 @@ struct realtek_pci_sdmmc {
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
+
+ unsigned int sg_count;
+ s32 cookie;
+ unsigned int cookie_sg_count;
+ bool using_cookie;
};
static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
@@ -86,6 +95,77 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
#define sd_print_debug_regs(host)
#endif /* DEBUG */
+/*
+ * sd_pre_dma_transfer - do dma_map_sg() or using cookie
+ *
+ * @pre: if called in pre_req()
+ * return:
+ * 0 - do dma_map_sg()
+ * 1 - using cookie
+ */
+static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
+ struct mmc_data *data, bool pre)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int read = data->flags & MMC_DATA_READ;
+ int count = 0;
+ int using_cookie = 0;
+
+ if (!pre && data->host_cookie && data->host_cookie != host->cookie) {
+ dev_err(sdmmc_dev(host),
+ "error: data->host_cookie = %d, host->cookie = %d\n",
+ data->host_cookie, host->cookie);
+ data->host_cookie = 0;
+ }
+
+ if (pre || data->host_cookie != host->cookie) {
+ count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read);
+ } else {
+ count = host->cookie_sg_count;
+ using_cookie = 1;
+ }
+
+ if (pre) {
+ host->cookie_sg_count = count;
+ if (++host->cookie < 0)
+ host->cookie = 1;
+ data->host_cookie = host->cookie;
+ } else {
+ host->sg_count = count;
+ }
+
+ return using_cookie;
+}
+
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+
+ if (data->host_cookie) {
+ dev_err(sdmmc_dev(host),
+ "error: reset data->host_cookie = %d\n",
+ data->host_cookie);
+ data->host_cookie = 0;
+ }
+
+ sd_pre_dma_transfer(host, data, true);
+ dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count);
+}
+
+static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ int err)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ struct mmc_data *data = mrq->data;
+ int read = data->flags & MMC_DATA_READ;
+
+ rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
+ data->host_cookie = 0;
+}
+
static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
u8 *buf, int buf_len, int timeout)
{
@@ -415,7 +495,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
rtsx_pci_send_cmd_no_wait(pcr);
- err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+ err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000);
if (err < 0) {
sd_clear_error(host);
return err;
@@ -640,12 +720,24 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
return 0;
}
-static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+static inline int sd_rw_cmd(struct mmc_command *cmd)
{
- struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ return mmc_op_multi(cmd->opcode) ||
+ (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+ (cmd->opcode == MMC_WRITE_BLOCK);
+}
+
+static void sd_request(struct work_struct *work)
+{
+ struct realtek_pci_sdmmc *host = container_of(work,
+ struct realtek_pci_sdmmc, work);
struct rtsx_pcr *pcr = host->pcr;
+
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_request *mrq = host->mrq;
struct mmc_command *cmd = mrq->cmd;
struct mmc_data *data = mrq->data;
+
unsigned int data_size = 0;
int err;
@@ -677,13 +769,13 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
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)) {
+ if (!data_size || sd_rw_cmd(cmd)) {
sd_send_cmd_get_rsp(host, cmd);
if (!cmd->error && data_size) {
sd_rw_multi(host, mrq);
+ if (!host->using_cookie)
+ sdmmc_post_req(host->mmc, host->mrq, 0);
if (mmc_op_multi(cmd->opcode) && mrq->stop)
sd_send_cmd_get_rsp(host, mrq->stop);
@@ -712,6 +804,21 @@ finish:
mmc_request_done(mmc, mrq);
}
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct mmc_data *data = mrq->data;
+
+ mutex_lock(&host->host_mutex);
+ host->mrq = mrq;
+ mutex_unlock(&host->host_mutex);
+
+ if (sd_rw_cmd(mrq->cmd))
+ host->using_cookie = sd_pre_dma_transfer(host, data, false);
+
+ queue_work(host->workq, &host->work);
+}
+
static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
unsigned char bus_width)
{
@@ -1146,6 +1253,8 @@ out:
}
static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+ .pre_req = sdmmc_pre_req,
+ .post_req = sdmmc_post_req,
.request = sdmmc_request,
.set_ios = sdmmc_set_ios,
.get_ro = sdmmc_get_ro,
@@ -1224,10 +1333,16 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
return -ENOMEM;
host = mmc_priv(mmc);
+ host->workq = create_singlethread_workqueue(SDMMC_WORKQ_NAME);
+ if (!host->workq) {
+ mmc_free_host(mmc);
+ return -ENOMEM;
+ }
host->pcr = pcr;
host->mmc = mmc;
host->pdev = pdev;
host->power_state = SDMMC_POWER_OFF;
+ INIT_WORK(&host->work, sd_request);
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;
@@ -1255,6 +1370,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
pcr->slots[RTSX_SD_CARD].card_event = NULL;
mmc = host->mmc;
+ cancel_work_sync(&host->work);
+
mutex_lock(&host->host_mutex);
if (host->mrq) {
dev_dbg(&(pdev->dev),
@@ -1273,6 +1390,10 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
mmc_remove_host(mmc);
host->eject = true;
+ flush_workqueue(host->workq);
+ destroy_workqueue(host->workq);
+ host->workq = NULL;
+
mmc_free_host(mmc);
dev_dbg(&(pdev->dev),
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index f23782683a7c..e5516a226362 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -12,6 +12,7 @@
*/
#include <linux/module.h>
+#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/mmc/host.h>
@@ -27,6 +28,7 @@
#include <mach/dma.h>
#include <mach/gpio-samsung.h>
+#include <linux/platform_data/dma-s3c24xx.h>
#include <linux/platform_data/mmc-s3cmci.h>
#include "s3cmci.h"
@@ -140,10 +142,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug;
dev_dbg(&host->pdev->dev, args); \
} while (0)
-static struct s3c2410_dma_client s3cmci_dma_client = {
- .name = "s3c-mci",
-};
-
static void finalize_request(struct s3cmci_host *host);
static void s3cmci_send_request(struct mmc_host *mmc);
static void s3cmci_reset(struct s3cmci_host *host);
@@ -256,25 +254,8 @@ static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
{
#ifdef CONFIG_MMC_S3C_PIO
return false;
-#elif defined(CONFIG_MMC_S3C_DMA)
+#else /* CONFIG_MMC_S3C_DMA */
return true;
-#else
- return host->dodma;
-#endif
-}
-
-/**
- * s3cmci_host_canpio - return true if host has pio code available
- *
- * Return true if the driver has been compiled with the PIO support code
- * available.
- */
-static inline bool s3cmci_host_canpio(void)
-{
-#ifdef CONFIG_MMC_S3C_PIO
- return true;
-#else
- return false;
#endif
}
@@ -841,60 +822,24 @@ static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
- void *buf_id, int size,
- enum s3c2410_dma_buffresult result)
+static void s3cmci_dma_done_callback(void *arg)
{
- struct s3cmci_host *host = buf_id;
+ struct s3cmci_host *host = arg;
unsigned long iflags;
- u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
-
- mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
- mci_dsta = readl(host->base + S3C2410_SDIDSTA);
- mci_fsta = readl(host->base + S3C2410_SDIFSTA);
- mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
BUG_ON(!host->mrq);
BUG_ON(!host->mrq->data);
- BUG_ON(!host->dmatogo);
spin_lock_irqsave(&host->complete_lock, iflags);
- if (result != S3C2410_RES_OK) {
- dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
- "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
- mci_csta, mci_dsta, mci_fsta,
- mci_dcnt, result, host->dmatogo);
-
- goto fail_request;
- }
-
- host->dmatogo--;
- if (host->dmatogo) {
- dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] "
- "DCNT:[%08x] toGo:%u\n",
- size, mci_dsta, mci_dcnt, host->dmatogo);
-
- goto out;
- }
-
- dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
- size, mci_dsta, mci_dcnt);
+ dbg(host, dbg_dma, "DMA FINISHED\n");
host->dma_complete = 1;
host->complete_what = COMPLETION_FINALIZE;
-out:
tasklet_schedule(&host->pio_tasklet);
spin_unlock_irqrestore(&host->complete_lock, iflags);
- return;
-fail_request:
- host->mrq->data->error = -EINVAL;
- host->complete_what = COMPLETION_FINALIZE;
- clear_imask(host);
-
- goto out;
}
static void finalize_request(struct s3cmci_host *host)
@@ -966,7 +911,7 @@ static void finalize_request(struct s3cmci_host *host)
* DMA channel and the fifo to clear out any garbage. */
if (mrq->data->error != 0) {
if (s3cmci_host_usedma(host))
- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+ dmaengine_terminate_all(host->dma);
if (host->is2440) {
/* Clear failure register and reset fifo. */
@@ -992,29 +937,6 @@ request_done:
mmc_request_done(host->mmc, mrq);
}
-static void s3cmci_dma_setup(struct s3cmci_host *host,
- enum dma_data_direction source)
-{
- static enum dma_data_direction last_source = -1;
- static int setup_ok;
-
- if (last_source == source)
- return;
-
- last_source = source;
-
- s3c2410_dma_devconfig(host->dma, source,
- host->mem->start + host->sdidata);
-
- if (!setup_ok) {
- s3c2410_dma_config(host->dma, 4);
- s3c2410_dma_set_buffdone_fn(host->dma,
- s3cmci_dma_done_callback);
- s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
- setup_ok = 1;
- }
-}
-
static void s3cmci_send_command(struct s3cmci_host *host,
struct mmc_command *cmd)
{
@@ -1162,43 +1084,45 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
{
- int dma_len, i;
int rw = data->flags & MMC_DATA_WRITE;
+ struct dma_async_tx_descriptor *desc;
+ struct dma_slave_config conf = {
+ .src_addr = host->mem->start + host->sdidata,
+ .dst_addr = host->mem->start + host->sdidata,
+ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ };
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
- s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
-
- dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-
- if (dma_len == 0)
- return -ENOMEM;
-
- host->dma_complete = 0;
- host->dmatogo = dma_len;
-
- for (i = 0; i < dma_len; i++) {
- int res;
-
- dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
- sg_dma_address(&data->sg[i]),
- sg_dma_len(&data->sg[i]));
+ /* Restore prescaler value */
+ writel(host->prescaler, host->base + S3C2410_SDIPRE);
- res = s3c2410_dma_enqueue(host->dma, host,
- sg_dma_address(&data->sg[i]),
- sg_dma_len(&data->sg[i]));
+ if (!rw)
+ conf.direction = DMA_DEV_TO_MEM;
+ else
+ conf.direction = DMA_MEM_TO_DEV;
- if (res) {
- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
- return -EBUSY;
- }
- }
+ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
+ dmaengine_slave_config(host->dma, &conf);
+ desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len,
+ conf.direction,
+ DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+ if (!desc)
+ goto unmap_exit;
+ desc->callback = s3cmci_dma_done_callback;
+ desc->callback_param = host;
+ dmaengine_submit(desc);
+ dma_async_issue_pending(host->dma);
return 0;
+
+unmap_exit:
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ return -ENOMEM;
}
static void s3cmci_send_request(struct mmc_host *mmc)
@@ -1676,10 +1600,6 @@ static int s3cmci_probe(struct platform_device *pdev)
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;
-#ifdef CONFIG_MMC_S3C_PIODMA
- host->dodma = host->pdata->use_dma;
-#endif
-
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
dev_err(&pdev->dev,
@@ -1765,17 +1685,17 @@ static int s3cmci_probe(struct platform_device *pdev)
/* depending on the dma state, get a dma channel to use. */
if (s3cmci_host_usedma(host)) {
- host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
- host);
- if (host->dma < 0) {
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ host->dma = dma_request_slave_channel_compat(mask,
+ s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx");
+ if (!host->dma) {
dev_err(&pdev->dev, "cannot get DMA channel.\n");
- if (!s3cmci_host_canpio()) {
- ret = -EBUSY;
- goto probe_free_gpio_wp;
- } else {
- dev_warn(&pdev->dev, "falling back to PIO.\n");
- host->dodma = 0;
- }
+ ret = -EBUSY;
+ goto probe_free_gpio_wp;
}
}
@@ -1787,7 +1707,7 @@ static int s3cmci_probe(struct platform_device *pdev)
goto probe_free_dma;
}
- ret = clk_enable(host->clk);
+ ret = clk_prepare_enable(host->clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable clock source.\n");
goto clk_free;
@@ -1816,7 +1736,7 @@ static int s3cmci_probe(struct platform_device *pdev)
mmc->max_segs = 128;
dbg(host, dbg_debug,
- "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
+ "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
(host->is2440?"2440":""),
host->base, host->irq, host->irq_cd, host->dma);
@@ -1845,14 +1765,14 @@ static int s3cmci_probe(struct platform_device *pdev)
s3cmci_cpufreq_deregister(host);
free_dmabuf:
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
clk_free:
clk_put(host->clk);
probe_free_dma:
if (s3cmci_host_usedma(host))
- s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+ dma_release_channel(host->dma);
probe_free_gpio_wp:
if (!host->pdata->no_wprotect)
@@ -1897,7 +1817,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
s3cmci_debugfs_remove(host);
s3cmci_cpufreq_deregister(host);
mmc_remove_host(mmc);
- clk_disable(host->clk);
+ clk_disable_unprepare(host->clk);
}
static int s3cmci_remove(struct platform_device *pdev)
@@ -1914,7 +1834,7 @@ static int s3cmci_remove(struct platform_device *pdev)
tasklet_disable(&host->pio_tasklet);
if (s3cmci_host_usedma(host))
- s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+ dma_release_channel(host->dma);
free_irq(host->irq, host);
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index c76b53dbeb61..cc2e46cb5c64 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -26,7 +26,7 @@ struct s3cmci_host {
void __iomem *base;
int irq;
int irq_cd;
- int dma;
+ struct dma_chan *dma;
unsigned long clk_rate;
unsigned long clk_div;
@@ -36,8 +36,6 @@ struct s3cmci_host {
int is2440;
unsigned sdiimsk;
unsigned sdidata;
- int dodma;
- int dmatogo;
bool irq_disabled;
bool irq_enabled;
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 8ce3c28cb76e..8c5337002c51 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -124,9 +124,11 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
.chip = &sdhci_acpi_chip_int,
- .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET,
+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
+ MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR,
.caps2 = MMC_CAP2_HC_ERASE_SZ,
.flags = SDHCI_ACPI_RUNTIME_PM,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
};
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 40573a58486a..1a6661ed6205 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -16,7 +16,6 @@
#include <linux/module.h>
#include <linux/of_device.h>
-#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
#include <linux/slab.h>
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 52c42fcc284c..c3a1debc9289 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -103,6 +103,10 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
};
+static const struct sdhci_pci_fixes sdhci_intel_qrk = {
+ .quirks = SDHCI_QUIRK_NO_HISPD_BIT,
+};
+
static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -264,7 +268,7 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
- MMC_CAP_HW_RESET;
+ MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
slot->hw_reset = sdhci_pci_int_hw_reset;
return 0;
@@ -279,6 +283,7 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.allow_runtime_pm = true,
.probe_slot = byt_emmc_probe_slot,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
@@ -753,6 +758,14 @@ static const struct pci_device_id pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_QRK_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_qrk,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_MRST_SD0,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
@@ -1130,18 +1143,13 @@ static int sdhci_pci_suspend(struct device *dev)
goto err_pci_suspend;
}
- pci_save_state(pdev);
if (pm_flags & MMC_PM_KEEP_POWER) {
- if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
- pci_pme_active(pdev, true);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- }
- pci_set_power_state(pdev, PCI_D3hot);
- } else {
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
- }
+ if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+ device_init_wakeup(dev, true);
+ else
+ device_init_wakeup(dev, false);
+ } else
+ device_init_wakeup(dev, false);
return 0;
@@ -1162,12 +1170,6 @@ static int sdhci_pci_resume(struct device *dev)
if (!chip)
return 0;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- ret = pci_enable_device(pdev);
- if (ret)
- return ret;
-
if (chip->fixes && chip->fixes->resume) {
ret = chip->fixes->resume(chip);
if (ret)
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 6d718719659e..c101477ef3be 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -17,6 +17,7 @@
#define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb
#define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5
#define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6
+#define PCI_DEVICE_ID_INTEL_QRK_SD 0x08A7
/*
* PCI registers
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index f4f128947561..6f842fb8e6b8 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -288,15 +288,13 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
int ret;
struct clk *clk;
- pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+ pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL);
if (!pxa)
return -ENOMEM;
host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0);
- if (IS_ERR(host)) {
- kfree(pxa);
+ if (IS_ERR(host))
return PTR_ERR(host);
- }
if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
@@ -308,7 +306,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
pltfm_host->priv = pxa;
- clk = clk_get(dev, NULL);
+ clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) {
dev_err(dev, "failed to get io clock\n");
ret = PTR_ERR(clk);
@@ -389,11 +387,9 @@ err_add_host:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(clk);
- clk_put(clk);
err_clk_get:
err_mbus_win:
sdhci_pltfm_free(pdev);
- kfree(pxa);
return ret;
}
@@ -401,17 +397,14 @@ 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);
- struct sdhci_pxa *pxa = pltfm_host->priv;
pm_runtime_get_sync(&pdev->dev);
sdhci_remove_host(host, 1);
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(pltfm_host->clk);
- clk_put(pltfm_host->clk);
sdhci_pltfm_free(pdev);
- kfree(pxa);
return 0;
}
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
new file mode 100644
index 000000000000..328f348c7243
--- /dev/null
+++ b/drivers/mmc/host/sdhci-st.c
@@ -0,0 +1,176 @@
+/*
+ * Support for SDHCI on STMicroelectronics SoCs
+ *
+ * Copyright (C) 2014 STMicroelectronics Ltd
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ * Contributors: Peter Griffin <peter.griffin@linaro.org>
+ *
+ * Based on sdhci-cns3xxx.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci-pltfm.h"
+
+static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
+{
+ u32 ret;
+
+ switch (reg) {
+ case SDHCI_CAPABILITIES:
+ ret = readl_relaxed(host->ioaddr + reg);
+ /* Support 3.3V and 1.8V */
+ ret &= ~SDHCI_CAN_VDD_300;
+ break;
+ default:
+ ret = readl_relaxed(host->ioaddr + reg);
+ }
+ return ret;
+}
+
+static const struct sdhci_ops sdhci_st_ops = {
+ .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .set_clock = sdhci_set_clock,
+ .set_bus_width = sdhci_set_bus_width,
+ .read_l = sdhci_st_readl,
+ .reset = sdhci_reset,
+};
+
+static const struct sdhci_pltfm_data sdhci_st_pdata = {
+ .ops = &sdhci_st_ops,
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+};
+
+
+static int sdhci_st_probe(struct platform_device *pdev)
+{
+ struct sdhci_host *host;
+ struct sdhci_pltfm_host *pltfm_host;
+ struct clk *clk;
+ int ret = 0;
+ u16 host_version;
+
+ clk = devm_clk_get(&pdev->dev, "mmc");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Peripheral clk not found\n");
+ return PTR_ERR(clk);
+ }
+
+ host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
+ if (IS_ERR(host)) {
+ dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
+ return PTR_ERR(host);
+ }
+
+ ret = mmc_of_parse(host->mmc);
+
+ if (ret) {
+ dev_err(&pdev->dev, "Failed mmc_of_parse\n");
+ return ret;
+ }
+
+ clk_prepare_enable(clk);
+
+ pltfm_host = sdhci_priv(host);
+ pltfm_host->clk = clk;
+
+ ret = sdhci_add_host(host);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed sdhci_add_host\n");
+ goto err_out;
+ }
+
+ platform_set_drvdata(pdev, host);
+
+ host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
+
+ dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
+ ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
+ ((host_version & SDHCI_VENDOR_VER_MASK) >>
+ SDHCI_VENDOR_VER_SHIFT));
+
+ return 0;
+
+err_out:
+ clk_disable_unprepare(clk);
+ sdhci_pltfm_free(pdev);
+
+ return ret;
+}
+
+static int sdhci_st_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ clk_disable_unprepare(pltfm_host->clk);
+
+ return sdhci_pltfm_unregister(pdev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_st_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ int ret = sdhci_suspend_host(host);
+
+ if (ret)
+ goto out;
+
+ clk_disable_unprepare(pltfm_host->clk);
+out:
+ return ret;
+}
+
+static int sdhci_st_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ clk_prepare_enable(pltfm_host->clk);
+
+ return sdhci_resume_host(host);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
+
+static const struct of_device_id st_sdhci_match[] = {
+ { .compatible = "st,sdhci" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, st_sdhci_match);
+
+static struct platform_driver sdhci_st_driver = {
+ .probe = sdhci_st_probe,
+ .remove = sdhci_st_remove,
+ .driver = {
+ .name = "sdhci-st",
+ .pm = &sdhci_st_pmops,
+ .of_match_table = of_match_ptr(st_sdhci_match),
+ },
+};
+
+module_platform_driver(sdhci_st_driver);
+
+MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:st-sdhci");
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index d93a063a36f3..33100d10d176 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -26,8 +26,6 @@
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
-#include <asm/gpio.h>
-
#include "sdhci-pltfm.h"
/* Tegra SDHOST controller vendor register definitions */
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 47055f3f01b8..37b2a9ae52ef 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1223,8 +1223,16 @@ EXPORT_SYMBOL_GPL(sdhci_set_clock);
static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
unsigned short vdd)
{
+ struct mmc_host *mmc = host->mmc;
u8 pwr = 0;
+ if (!IS_ERR(mmc->supply.vmmc)) {
+ spin_unlock_irq(&host->lock);
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ spin_lock_irq(&host->lock);
+ return;
+ }
+
if (mode != MMC_POWER_OFF) {
switch (1 << vdd) {
case MMC_VDD_165_195:
@@ -1283,12 +1291,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
mdelay(10);
}
-
- if (host->vmmc) {
- spin_unlock_irq(&host->lock);
- mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
- spin_lock_irq(&host->lock);
- }
}
/*****************************************************************************\
@@ -1440,13 +1442,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
{
unsigned long flags;
u8 ctrl;
+ struct mmc_host *mmc = host->mmc;
spin_lock_irqsave(&host->lock, flags);
if (host->flags & SDHCI_DEVICE_DEAD) {
spin_unlock_irqrestore(&host->lock, flags);
- if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
- mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+ if (!IS_ERR(mmc->supply.vmmc) &&
+ ios->power_mode == MMC_POWER_OFF)
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
return;
}
@@ -1530,7 +1534,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
host->ops->set_clock(host, host->clock);
}
-
/* Reset SD Clock Enable */
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
clk &= ~SDHCI_CLOCK_CARD_EN;
@@ -1707,6 +1710,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
struct mmc_ios *ios)
{
+ struct mmc_host *mmc = host->mmc;
u16 ctrl;
int ret;
@@ -1725,11 +1729,12 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
ctrl &= ~SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- if (host->vqmmc) {
- ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = regulator_set_voltage(mmc->supply.vqmmc, 2700000,
+ 3600000);
if (ret) {
pr_warning("%s: Switching to 3.3V signalling voltage "
- " failed\n", mmc_hostname(host->mmc));
+ " failed\n", mmc_hostname(mmc));
return -EIO;
}
}
@@ -1742,16 +1747,16 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
return 0;
pr_warning("%s: 3.3V regulator output did not became stable\n",
- mmc_hostname(host->mmc));
+ mmc_hostname(mmc));
return -EAGAIN;
case MMC_SIGNAL_VOLTAGE_180:
- if (host->vqmmc) {
- ret = regulator_set_voltage(host->vqmmc,
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = regulator_set_voltage(mmc->supply.vqmmc,
1700000, 1950000);
if (ret) {
pr_warning("%s: Switching to 1.8V signalling voltage "
- " failed\n", mmc_hostname(host->mmc));
+ " failed\n", mmc_hostname(mmc));
return -EIO;
}
}
@@ -1763,24 +1768,22 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
ctrl |= SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- /* Wait for 5ms */
- usleep_range(5000, 5500);
-
/* 1.8V regulator output should be stable within 5 ms */
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (ctrl & SDHCI_CTRL_VDD_180)
return 0;
pr_warning("%s: 1.8V regulator output did not became stable\n",
- mmc_hostname(host->mmc));
+ mmc_hostname(mmc));
return -EAGAIN;
case MMC_SIGNAL_VOLTAGE_120:
- if (host->vqmmc) {
- ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000);
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = regulator_set_voltage(mmc->supply.vqmmc, 1100000,
+ 1300000);
if (ret) {
pr_warning("%s: Switching to 1.2V signalling voltage "
- " failed\n", mmc_hostname(host->mmc));
+ " failed\n", mmc_hostname(mmc));
return -EIO;
}
}
@@ -2643,7 +2646,6 @@ static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
int sdhci_runtime_suspend_host(struct sdhci_host *host)
{
unsigned long flags;
- int ret = 0;
/* Disable tuning since we are suspending */
if (host->flags & SDHCI_USING_RETUNING_TIMER) {
@@ -2663,14 +2665,14 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
host->runtime_suspended = true;
spin_unlock_irqrestore(&host->lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(sdhci_runtime_suspend_host);
int sdhci_runtime_resume_host(struct sdhci_host *host)
{
unsigned long flags;
- int ret = 0, host_flags = host->flags;
+ int host_flags = host->flags;
if (host_flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
@@ -2709,7 +2711,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
spin_unlock_irqrestore(&host->lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(sdhci_runtime_resume_host);
@@ -2820,12 +2822,12 @@ int sdhci_add_host(struct sdhci_host *host)
* (128) and potentially one alignment transfer for
* each of those entries.
*/
- host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
+ host->adma_desc = dma_alloc_coherent(mmc_dev(mmc),
ADMA_SIZE, &host->adma_addr,
GFP_KERNEL);
host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
if (!host->adma_desc || !host->align_buffer) {
- dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+ dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
host->adma_desc, host->adma_addr);
kfree(host->align_buffer);
pr_warning("%s: Unable to allocate ADMA "
@@ -2838,7 +2840,7 @@ int sdhci_add_host(struct sdhci_host *host)
pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
mmc_hostname(mmc));
host->flags &= ~SDHCI_USE_ADMA;
- dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+ dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
host->adma_desc, host->adma_addr);
kfree(host->align_buffer);
host->adma_desc = NULL;
@@ -2853,7 +2855,7 @@ int sdhci_add_host(struct sdhci_host *host)
*/
if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
host->dma_mask = DMA_BIT_MASK(64);
- mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+ mmc_dev(mmc)->dma_mask = &host->dma_mask;
}
if (host->version >= SDHCI_SPEC_300)
@@ -2959,28 +2961,25 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
- !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
+ !(mmc->caps & MMC_CAP_NONREMOVABLE))
mmc->caps |= MMC_CAP_NEEDS_POLL;
+ /* If there are external regulators, get them */
+ if (mmc_regulator_get_supply(mmc) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
- host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc");
- if (IS_ERR_OR_NULL(host->vqmmc)) {
- if (PTR_ERR(host->vqmmc) < 0) {
- pr_info("%s: no vqmmc regulator found\n",
- mmc_hostname(mmc));
- host->vqmmc = NULL;
- }
- } else {
- ret = regulator_enable(host->vqmmc);
- if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
- 1950000))
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = regulator_enable(mmc->supply.vqmmc);
+ if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
+ 1950000))
caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
SDHCI_SUPPORT_SDR50 |
SDHCI_SUPPORT_DDR50);
if (ret) {
pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
mmc_hostname(mmc), ret);
- host->vqmmc = NULL;
+ mmc->supply.vqmmc = NULL;
}
}
@@ -3041,34 +3040,6 @@ int sdhci_add_host(struct sdhci_host *host)
ocr_avail = 0;
- host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc");
- if (IS_ERR_OR_NULL(host->vmmc)) {
- if (PTR_ERR(host->vmmc) < 0) {
- pr_info("%s: no vmmc regulator found\n",
- mmc_hostname(mmc));
- host->vmmc = NULL;
- }
- }
-
-#ifdef CONFIG_REGULATOR
- /*
- * Voltage range check makes sense only if regulator reports
- * any voltage value.
- */
- if (host->vmmc && regulator_get_voltage(host->vmmc) > 0) {
- ret = regulator_is_supported_voltage(host->vmmc, 2700000,
- 3600000);
- if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
- caps[0] &= ~SDHCI_CAN_VDD_330;
- if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
- caps[0] &= ~SDHCI_CAN_VDD_300;
- ret = regulator_is_supported_voltage(host->vmmc, 1700000,
- 1950000);
- if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
- caps[0] &= ~SDHCI_CAN_VDD_180;
- }
-#endif /* CONFIG_REGULATOR */
-
/*
* According to SD Host Controller spec v3.00, if the Host System
* can afford more than 150mA, Host Driver should set XPC to 1. Also
@@ -3077,8 +3048,8 @@ int sdhci_add_host(struct sdhci_host *host)
* value.
*/
max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
- if (!max_current_caps && host->vmmc) {
- u32 curr = regulator_get_current_limit(host->vmmc);
+ if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
+ u32 curr = regulator_get_current_limit(mmc->supply.vmmc);
if (curr > 0) {
/* convert to SDHCI_MAX_CURRENT format */
@@ -3118,8 +3089,12 @@ int sdhci_add_host(struct sdhci_host *host)
SDHCI_MAX_CURRENT_MULTIPLIER;
}
+ /* If OCR set by external regulators, use it instead */
+ if (mmc->ocr_avail)
+ ocr_avail = mmc->ocr_avail;
+
if (host->ocr_mask)
- ocr_avail = host->ocr_mask;
+ ocr_avail &= host->ocr_mask;
mmc->ocr_avail = ocr_avail;
mmc->ocr_avail_sdio = ocr_avail;
@@ -3273,6 +3248,7 @@ EXPORT_SYMBOL_GPL(sdhci_add_host);
void sdhci_remove_host(struct sdhci_host *host, int dead)
{
+ struct mmc_host *mmc = host->mmc;
unsigned long flags;
if (dead) {
@@ -3282,7 +3258,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
if (host->mrq) {
pr_err("%s: Controller removed during "
- " transfer!\n", mmc_hostname(host->mmc));
+ " transfer!\n", mmc_hostname(mmc));
host->mrq->cmd->error = -ENOMEDIUM;
tasklet_schedule(&host->finish_tasklet);
@@ -3293,7 +3269,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
sdhci_disable_card_detection(host);
- mmc_remove_host(host->mmc);
+ mmc_remove_host(mmc);
#ifdef SDHCI_USE_LEDS_CLASS
led_classdev_unregister(&host->led);
@@ -3310,18 +3286,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
tasklet_kill(&host->finish_tasklet);
- if (host->vmmc) {
- regulator_disable(host->vmmc);
- regulator_put(host->vmmc);
- }
+ if (!IS_ERR(mmc->supply.vmmc))
+ regulator_disable(mmc->supply.vmmc);
- if (host->vqmmc) {
- regulator_disable(host->vqmmc);
- regulator_put(host->vqmmc);
- }
+ if (!IS_ERR(mmc->supply.vqmmc))
+ regulator_disable(mmc->supply.vqmmc);
if (host->adma_desc)
- dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
+ dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
host->adma_desc, host->adma_addr);
kfree(host->align_buffer);
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 656fbba4c422..d11708c815d7 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -386,7 +386,7 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
struct sh_mmcif_plat_data *pdata,
enum dma_transfer_direction direction)
{
- struct dma_slave_config cfg;
+ struct dma_slave_config cfg = { 0, };
struct dma_chan *chan;
unsigned int slave_id;
struct resource *res;
@@ -417,8 +417,15 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
/* In the OF case the driver will get the slave ID from the DT */
cfg.slave_id = slave_id;
cfg.direction = direction;
- cfg.dst_addr = res->start + MMCIF_CE_DATA;
- cfg.src_addr = 0;
+
+ if (direction == DMA_DEV_TO_MEM) {
+ cfg.src_addr = res->start + MMCIF_CE_DATA;
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ } else {
+ cfg.dst_addr = res->start + MMCIF_CE_DATA;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ }
+
ret = dmaengine_slave_config(chan, &cfg);
if (ret < 0) {
dma_release_channel(chan);
@@ -1378,26 +1385,19 @@ static int sh_mmcif_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Get irq error\n");
return -ENXIO;
}
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "platform_get_resource error.\n");
- return -ENXIO;
- }
- reg = ioremap(res->start, resource_size(res));
- if (!reg) {
- dev_err(&pdev->dev, "ioremap error.\n");
- return -ENOMEM;
- }
+ reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- goto ealloch;
- }
+ if (!mmc)
+ return -ENOMEM;
ret = mmc_of_parse(mmc);
if (ret < 0)
- goto eofparse;
+ goto err_host;
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -1427,19 +1427,19 @@ static int sh_mmcif_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
host->power = false;
- host->hclk = clk_get(&pdev->dev, NULL);
+ host->hclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(host->hclk)) {
ret = PTR_ERR(host->hclk);
dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
- goto eclkget;
+ goto err_pm;
}
ret = sh_mmcif_clk_update(host);
if (ret < 0)
- goto eclkupdate;
+ goto err_pm;
ret = pm_runtime_resume(&pdev->dev);
if (ret < 0)
- goto eresume;
+ goto err_clk;
INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
@@ -1447,65 +1447,55 @@ static int sh_mmcif_probe(struct platform_device *pdev)
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error";
- ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host);
+ ret = devm_request_threaded_irq(&pdev->dev, irq[0], sh_mmcif_intr,
+ sh_mmcif_irqt, 0, name, host);
if (ret) {
dev_err(&pdev->dev, "request_irq error (%s)\n", name);
- goto ereqirq0;
+ goto err_clk;
}
if (irq[1] >= 0) {
- ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt,
- 0, "sh_mmc:int", host);
+ ret = devm_request_threaded_irq(&pdev->dev, irq[1],
+ sh_mmcif_intr, sh_mmcif_irqt,
+ 0, "sh_mmc:int", host);
if (ret) {
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
- goto ereqirq1;
+ goto err_clk;
}
}
if (pd && pd->use_cd_gpio) {
ret = mmc_gpio_request_cd(mmc, pd->cd_gpio, 0);
if (ret < 0)
- goto erqcd;
+ goto err_clk;
}
mutex_init(&host->thread_lock);
- clk_disable_unprepare(host->hclk);
ret = mmc_add_host(mmc);
if (ret < 0)
- goto emmcaddh;
+ goto err_clk;
dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
- dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
- dev_dbg(&pdev->dev, "chip ver H'%04x\n",
- sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
+ dev_info(&pdev->dev, "Chip version 0x%04x, clock rate %luMHz\n",
+ sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0xffff,
+ clk_get_rate(host->hclk) / 1000000UL);
+
+ clk_disable_unprepare(host->hclk);
return ret;
-emmcaddh:
-erqcd:
- if (irq[1] >= 0)
- free_irq(irq[1], host);
-ereqirq1:
- free_irq(irq[0], host);
-ereqirq0:
- pm_runtime_suspend(&pdev->dev);
-eresume:
+err_clk:
clk_disable_unprepare(host->hclk);
-eclkupdate:
- clk_put(host->hclk);
-eclkget:
+err_pm:
pm_runtime_disable(&pdev->dev);
-eofparse:
+err_host:
mmc_free_host(mmc);
-ealloch:
- iounmap(reg);
return ret;
}
static int sh_mmcif_remove(struct platform_device *pdev)
{
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
- int irq[2];
host->dying = true;
clk_prepare_enable(host->hclk);
@@ -1523,16 +1513,6 @@ static int sh_mmcif_remove(struct platform_device *pdev)
*/
cancel_delayed_work_sync(&host->timeout_work);
- if (host->addr)
- iounmap(host->addr);
-
- irq[0] = platform_get_irq(pdev, 0);
- irq[1] = platform_get_irq(pdev, 1);
-
- free_irq(irq[0], host);
- if (irq[1] >= 0)
- free_irq(irq[1], host);
-
clk_disable_unprepare(host->hclk);
mmc_free_host(host->mmc);
pm_runtime_put_sync(&pdev->dev);
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 03e7b280cb4c..eb8f1d5c34b1 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -294,6 +294,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
cfg.slave_id = pdata->dma->slave_id_tx;
cfg.direction = DMA_MEM_TO_DEV;
cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift);
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
cfg.src_addr = 0;
ret = dmaengine_slave_config(host->chan_tx, &cfg);
if (ret < 0)
@@ -312,6 +313,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
cfg.slave_id = pdata->dma->slave_id_rx;
cfg.direction = DMA_DEV_TO_MEM;
cfg.src_addr = cfg.dst_addr;
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
cfg.dst_addr = 0;
ret = dmaengine_slave_config(host->chan_rx, &cfg);
if (ret < 0)
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
index 282891a8e451..54181b4f6e9e 100644
--- a/drivers/mmc/host/wmt-sdmmc.c
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -72,7 +72,6 @@
#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
@@ -120,6 +119,8 @@
#define STS2_DATARSP_BUSY 0x20
#define STS2_DIS_FORCECLK 0x80
+/* SDMMC_EXTCTRL bit fields */
+#define EXT_EIGHTBIT 0x04
/* MMC/SD DMA Controller Registers */
#define SDDMA_GCR 0x100
@@ -672,7 +673,7 @@ static void wmt_mci_request(struct mmc_host *mmc, struct mmc_request *req)
static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct wmt_mci_priv *priv;
- u32 reg_tmp;
+ u32 busmode, extctrl;
priv = mmc_priv(mmc);
@@ -687,28 +688,26 @@ static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (ios->clock != 0)
clk_set_rate(priv->clk_sdmmc, ios->clock);
+ busmode = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ extctrl = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+
+ busmode &= ~(BM_EIGHTBIT_MODE | BM_FOURBIT_MODE);
+ extctrl &= ~EXT_EIGHTBIT;
+
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);
+ busmode |= BM_EIGHTBIT_MODE;
+ extctrl |= EXT_EIGHTBIT;
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);
+ busmode |= BM_FOURBIT_MODE;
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;
}
+
+ writeb(busmode, priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(extctrl, priv->sdmmc_base + SDMMC_EXTCTRL);
}
static int wmt_mci_get_ro(struct mmc_host *mmc)
@@ -830,7 +829,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
goto fail3;
}
- ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv);
+ ret = request_irq(dma_irq, wmt_mci_dma_isr, 0, "sdmmc", priv);
if (ret) {
dev_err(&pdev->dev, "Register DMA IRQ fail\n");
goto fail4;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index e21fde9d4d7e..5a4bfe33112a 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -58,7 +58,18 @@ static void cfi_amdstd_sync (struct mtd_info *);
static int cfi_amdstd_suspend (struct mtd_info *);
static void cfi_amdstd_resume (struct mtd_info *);
static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
+static int cfi_amdstd_get_fact_prot_info(struct mtd_info *, size_t,
+ size_t *, struct otp_info *);
+static int cfi_amdstd_get_user_prot_info(struct mtd_info *, size_t,
+ size_t *, struct otp_info *);
static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *, loff_t, size_t,
+ size_t *, u_char *);
+static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t,
+ size_t *, u_char *);
+static int cfi_amdstd_write_user_prot_reg(struct mtd_info *, loff_t, size_t,
+ size_t *, u_char *);
+static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *, loff_t, size_t);
static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
@@ -518,6 +529,12 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
mtd->_sync = cfi_amdstd_sync;
mtd->_suspend = cfi_amdstd_suspend;
mtd->_resume = cfi_amdstd_resume;
+ mtd->_read_user_prot_reg = cfi_amdstd_read_user_prot_reg;
+ mtd->_read_fact_prot_reg = cfi_amdstd_read_fact_prot_reg;
+ mtd->_get_fact_prot_info = cfi_amdstd_get_fact_prot_info;
+ mtd->_get_user_prot_info = cfi_amdstd_get_user_prot_info;
+ mtd->_write_user_prot_reg = cfi_amdstd_write_user_prot_reg;
+ mtd->_lock_user_prot_reg = cfi_amdstd_lock_user_prot_reg;
mtd->flags = MTD_CAP_NORFLASH;
mtd->name = map->name;
mtd->writesize = 1;
@@ -628,6 +645,23 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+ /*
+ * First calculate the timeout max according to timeout field
+ * of struct cfi_ident that probed from chip's CFI aera, if
+ * available. Specify a minimum of 2000us, in case the CFI data
+ * is wrong.
+ */
+ if (cfi->cfiq->BufWriteTimeoutTyp &&
+ cfi->cfiq->BufWriteTimeoutMax)
+ cfi->chips[i].buffer_write_time_max =
+ 1 << (cfi->cfiq->BufWriteTimeoutTyp +
+ cfi->cfiq->BufWriteTimeoutMax);
+ else
+ cfi->chips[i].buffer_write_time_max = 0;
+
+ cfi->chips[i].buffer_write_time_max =
+ max(cfi->chips[i].buffer_write_time_max, 2000);
+
cfi->chips[i].ref_point_counter = 0;
init_waitqueue_head(&(cfi->chips[i].wq));
}
@@ -1137,12 +1171,48 @@ static int cfi_amdstd_read (struct mtd_info *mtd, loff_t from, size_t len, size_
return ret;
}
+typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,
+ loff_t adr, size_t len, u_char *buf, size_t grouplen);
+
+static inline void otp_enter(struct map_info *map, struct flchip *chip,
+ loff_t adr, size_t len)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+
+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+
+ INVALIDATE_CACHED_RANGE(map, chip->start + adr, len);
+}
+
+static inline void otp_exit(struct map_info *map, struct flchip *chip,
+ loff_t adr, size_t len)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+
+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+
+ INVALIDATE_CACHED_RANGE(map, chip->start + adr, len);
+}
-static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
+static inline int do_read_secsi_onechip(struct map_info *map,
+ struct flchip *chip, loff_t adr,
+ size_t len, u_char *buf,
+ size_t grouplen)
{
DECLARE_WAITQUEUE(wait, current);
unsigned long timeo = jiffies + HZ;
- struct cfi_private *cfi = map->fldrv_priv;
retry:
mutex_lock(&chip->mutex);
@@ -1164,16 +1234,9 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
chip->state = FL_READY;
- cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-
+ otp_enter(map, chip, adr, len);
map_copy_from(map, buf, adr, len);
-
- cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+ otp_exit(map, chip, adr, len);
wake_up(&chip->wq);
mutex_unlock(&chip->mutex);
@@ -1205,7 +1268,8 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len,
else
thislen = len;
- ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+ ret = do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs,
+ thislen, buf, 0);
if (ret)
break;
@@ -1219,8 +1283,267 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len,
return ret;
}
+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
+ unsigned long adr, map_word datum,
+ int mode);
+
+static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr,
+ size_t len, u_char *buf, size_t grouplen)
+{
+ int ret;
+ while (len) {
+ unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1);
+ int gap = adr - bus_ofs;
+ int n = min_t(int, len, map_bankwidth(map) - gap);
+ map_word datum;
+
+ if (n != map_bankwidth(map)) {
+ /* partial write of a word, load old contents */
+ otp_enter(map, chip, bus_ofs, map_bankwidth(map));
+ datum = map_read(map, bus_ofs);
+ otp_exit(map, chip, bus_ofs, map_bankwidth(map));
+ }
+
+ datum = map_word_load_partial(map, datum, buf, gap, n);
+ ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
+ if (ret)
+ return ret;
+
+ adr += n;
+ buf += n;
+ len -= n;
+ }
+
+ return 0;
+}
+
+static int do_otp_lock(struct map_info *map, struct flchip *chip, loff_t adr,
+ size_t len, u_char *buf, size_t grouplen)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ uint8_t lockreg;
+ unsigned long timeo;
+ int ret;
+
+ /* make sure area matches group boundaries */
+ if ((adr != 0) || (len != grouplen))
+ return -EINVAL;
+
+ mutex_lock(&chip->mutex);
+ ret = get_chip(map, chip, chip->start, FL_LOCKING);
+ if (ret) {
+ mutex_unlock(&chip->mutex);
+ return ret;
+ }
+ chip->state = FL_LOCKING;
+
+ /* Enter lock register command */
+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x40, cfi->addr_unlock1, chip->start, map, cfi,
+ cfi->device_type, NULL);
+
+ /* read lock register */
+ lockreg = cfi_read_query(map, 0);
+
+ /* set bit 0 to protect extended memory block */
+ lockreg &= ~0x01;
+
+ /* set bit 0 to protect extended memory block */
+ /* write lock register */
+ map_write(map, CMD(0xA0), chip->start);
+ map_write(map, CMD(lockreg), chip->start);
+
+ /* wait for chip to become ready */
+ timeo = jiffies + msecs_to_jiffies(2);
+ for (;;) {
+ if (chip_ready(map, adr))
+ break;
+
+ if (time_after(jiffies, timeo)) {
+ pr_err("Waiting for chip to be ready timed out.\n");
+ ret = -EIO;
+ break;
+ }
+ UDELAY(map, chip, 0, 1);
+ }
+
+ /* exit protection commands */
+ map_write(map, CMD(0x90), chip->start);
+ map_write(map, CMD(0x00), chip->start);
+
+ chip->state = FL_READY;
+ put_chip(map, chip, chip->start);
+ mutex_unlock(&chip->mutex);
+
+ return ret;
+}
+
+static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf,
+ otp_op_t action, int user_regs)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int ofs_factor = cfi->interleave * cfi->device_type;
+ unsigned long base;
+ int chipnum;
+ struct flchip *chip;
+ uint8_t otp, lockreg;
+ int ret;
+
+ size_t user_size, factory_size, otpsize;
+ loff_t user_offset, factory_offset, otpoffset;
+ int user_locked = 0, otplocked;
+
+ *retlen = 0;
+
+ for (chipnum = 0; chipnum < cfi->numchips; chipnum++) {
+ chip = &cfi->chips[chipnum];
+ factory_size = 0;
+ user_size = 0;
-static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum)
+ /* Micron M29EW family */
+ if (is_m29ew(cfi)) {
+ base = chip->start;
+
+ /* check whether secsi area is factory locked
+ or user lockable */
+ mutex_lock(&chip->mutex);
+ ret = get_chip(map, chip, base, FL_CFI_QUERY);
+ if (ret) {
+ mutex_unlock(&chip->mutex);
+ return ret;
+ }
+ cfi_qry_mode_on(base, map, cfi);
+ otp = cfi_read_query(map, base + 0x3 * ofs_factor);
+ cfi_qry_mode_off(base, map, cfi);
+ put_chip(map, chip, base);
+ mutex_unlock(&chip->mutex);
+
+ if (otp & 0x80) {
+ /* factory locked */
+ factory_offset = 0;
+ factory_size = 0x100;
+ } else {
+ /* customer lockable */
+ user_offset = 0;
+ user_size = 0x100;
+
+ mutex_lock(&chip->mutex);
+ ret = get_chip(map, chip, base, FL_LOCKING);
+
+ /* Enter lock register command */
+ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1,
+ chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2,
+ chip->start, map, cfi,
+ cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x40, cfi->addr_unlock1,
+ chip->start, map, cfi,
+ cfi->device_type, NULL);
+ /* read lock register */
+ lockreg = cfi_read_query(map, 0);
+ /* exit protection commands */
+ map_write(map, CMD(0x90), chip->start);
+ map_write(map, CMD(0x00), chip->start);
+ put_chip(map, chip, chip->start);
+ mutex_unlock(&chip->mutex);
+
+ user_locked = ((lockreg & 0x01) == 0x00);
+ }
+ }
+
+ otpsize = user_regs ? user_size : factory_size;
+ if (!otpsize)
+ continue;
+ otpoffset = user_regs ? user_offset : factory_offset;
+ otplocked = user_regs ? user_locked : 1;
+
+ if (!action) {
+ /* return otpinfo */
+ struct otp_info *otpinfo;
+ len -= sizeof(*otpinfo);
+ if (len <= 0)
+ return -ENOSPC;
+ otpinfo = (struct otp_info *)buf;
+ otpinfo->start = from;
+ otpinfo->length = otpsize;
+ otpinfo->locked = otplocked;
+ buf += sizeof(*otpinfo);
+ *retlen += sizeof(*otpinfo);
+ from += otpsize;
+ } else if ((from < otpsize) && (len > 0)) {
+ size_t size;
+ size = (len < otpsize - from) ? len : otpsize - from;
+ ret = action(map, chip, otpoffset + from, size, buf,
+ otpsize);
+ if (ret < 0)
+ return ret;
+
+ buf += size;
+ len -= size;
+ *retlen += size;
+ from = 0;
+ } else {
+ from -= otpsize;
+ }
+ }
+ return 0;
+}
+
+static int cfi_amdstd_get_fact_prot_info(struct mtd_info *mtd, size_t len,
+ size_t *retlen, struct otp_info *buf)
+{
+ return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
+ NULL, 0);
+}
+
+static int cfi_amdstd_get_user_prot_info(struct mtd_info *mtd, size_t len,
+ size_t *retlen, struct otp_info *buf)
+{
+ return cfi_amdstd_otp_walk(mtd, 0, len, retlen, (u_char *)buf,
+ NULL, 1);
+}
+
+static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen,
+ u_char *buf)
+{
+ return cfi_amdstd_otp_walk(mtd, from, len, retlen,
+ buf, do_read_secsi_onechip, 0);
+}
+
+static int cfi_amdstd_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen,
+ u_char *buf)
+{
+ return cfi_amdstd_otp_walk(mtd, from, len, retlen,
+ buf, do_read_secsi_onechip, 1);
+}
+
+static int cfi_amdstd_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len, size_t *retlen,
+ u_char *buf)
+{
+ return cfi_amdstd_otp_walk(mtd, from, len, retlen, buf,
+ do_otp_write, 1);
+}
+
+static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+ size_t len)
+{
+ size_t retlen;
+ return cfi_amdstd_otp_walk(mtd, from, len, &retlen, NULL,
+ do_otp_lock, 1);
+}
+
+static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
+ unsigned long adr, map_word datum,
+ int mode)
{
struct cfi_private *cfi = map->fldrv_priv;
unsigned long timeo = jiffies + HZ;
@@ -1241,7 +1564,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
adr += chip->start;
mutex_lock(&chip->mutex);
- ret = get_chip(map, chip, adr, FL_WRITING);
+ ret = get_chip(map, chip, adr, mode);
if (ret) {
mutex_unlock(&chip->mutex);
return ret;
@@ -1250,6 +1573,9 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
__func__, adr, datum.x[0] );
+ if (mode == FL_OTP_WRITE)
+ otp_enter(map, chip, adr, map_bankwidth(map));
+
/*
* Check for a NOP for the case when the datum to write is already
* present - it saves time and works around buggy chips that corrupt
@@ -1266,12 +1592,13 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
ENABLE_VPP(map);
xip_disable(map, chip, adr);
+
retry:
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
map_write(map, datum, adr);
- chip->state = FL_WRITING;
+ chip->state = mode;
INVALIDATE_CACHE_UDELAY(map, chip,
adr, map_bankwidth(map),
@@ -1280,7 +1607,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
/* See comment above for timeout value. */
timeo = jiffies + uWriteTimeout;
for (;;) {
- if (chip->state != FL_WRITING) {
+ if (chip->state != mode) {
/* Someone's suspended the write. Sleep */
DECLARE_WAITQUEUE(wait, current);
@@ -1320,6 +1647,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
}
xip_enable(map, chip, adr);
op_done:
+ if (mode == FL_OTP_WRITE)
+ otp_exit(map, chip, adr, map_bankwidth(map));
chip->state = FL_READY;
DISABLE_VPP(map);
put_chip(map, chip, adr);
@@ -1375,7 +1704,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
ret = do_write_oneword(map, &cfi->chips[chipnum],
- bus_ofs, tmp_buf);
+ bus_ofs, tmp_buf, FL_WRITING);
if (ret)
return ret;
@@ -1399,7 +1728,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
datum = map_word_load(map, buf);
ret = do_write_oneword(map, &cfi->chips[chipnum],
- ofs, datum);
+ ofs, datum, FL_WRITING);
if (ret)
return ret;
@@ -1442,7 +1771,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
ret = do_write_oneword(map, &cfi->chips[chipnum],
- ofs, tmp_buf);
+ ofs, tmp_buf, FL_WRITING);
if (ret)
return ret;
@@ -1462,8 +1791,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
{
struct cfi_private *cfi = map->fldrv_priv;
unsigned long timeo = jiffies + HZ;
- /* see comments in do_write_oneword() regarding uWriteTimeo. */
- unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
+ /*
+ * Timeout is calculated according to CFI data, if available.
+ * See more comments in cfi_cmdset_0002().
+ */
+ unsigned long uWriteTimeout =
+ usecs_to_jiffies(chip->buffer_write_time_max);
int ret = -EIO;
unsigned long cmd_adr;
int z, words;
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index 3e829b37af8d..c8503006f17a 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -26,7 +26,7 @@
* <mtd-id> := unique name used in mapping driver/device (mtd->name)
* <size> := standard linux memsize OR "-" to denote all remaining space
* size is automatically truncated at end of device
- * if specified or trucated size is 0 the part is skipped
+ * if specified or truncated size is 0 the part is skipped
* <offset> := standard linux memsize
* if omitted the part will immediately follow the previous part
* or 0 if the first part
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 2cceebfb251e..effd9a4ef7ee 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -181,12 +181,10 @@ static int parse_name(char **pname, const char *token)
if (len > 64)
return -ENOSPC;
- name = kmalloc(len, GFP_KERNEL);
+ name = kstrdup(token, GFP_KERNEL);
if (!name)
return -ENOMEM;
- strcpy(name, token);
-
*pname = name;
return 0;
}
@@ -195,6 +193,7 @@ static int parse_name(char **pname, const char *token)
static inline void kill_final_newline(char *str)
{
char *newline = strrchr(str, '\n');
+
if (newline && !newline[1])
*newline = 0;
}
@@ -233,7 +232,7 @@ static int phram_setup(const char *val)
strcpy(str, val);
kill_final_newline(str);
- for (i=0; i<3; i++)
+ for (i = 0; i < 3; i++)
token[i] = strsep(&str, ",");
if (str)
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 19d637266fcd..dabf08450d0b 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -111,7 +111,6 @@ typedef struct partition_t {
struct mtd_blktrans_dev mbd;
uint32_t state;
uint32_t *VirtualBlockMap;
- uint32_t *VirtualPageMap;
uint32_t FreeTotal;
struct eun_info_t {
uint32_t Offset;
@@ -1035,8 +1034,6 @@ static void ftl_freepart(partition_t *part)
{
vfree(part->VirtualBlockMap);
part->VirtualBlockMap = NULL;
- kfree(part->VirtualPageMap);
- part->VirtualPageMap = NULL;
kfree(part->EUNInfo);
part->EUNInfo = NULL;
kfree(part->XferInfo);
@@ -1075,7 +1072,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
return;
}
- ftl_freepart(partition);
kfree(partition);
}
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 146b6047ed2b..a84fdfb10518 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -35,8 +35,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
return 0;
if (info->mtd) {
- struct rbtx4939_flash_data *pdata = dev_get_platdata(&dev->dev);
-
mtd_device_unregister(info->mtd);
map_destroy(info->mtd);
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index d201feeb3ca6..e4831b4159db 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -298,6 +298,47 @@ static ssize_t mtd_ecc_step_size_show(struct device *dev,
}
static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL);
+static ssize_t mtd_ecc_stats_corrected_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->corrected);
+}
+static DEVICE_ATTR(corrected_bits, S_IRUGO,
+ mtd_ecc_stats_corrected_show, NULL);
+
+static ssize_t mtd_ecc_stats_errors_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->failed);
+}
+static DEVICE_ATTR(ecc_failures, S_IRUGO, mtd_ecc_stats_errors_show, NULL);
+
+static ssize_t mtd_badblocks_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->badblocks);
+}
+static DEVICE_ATTR(bad_blocks, S_IRUGO, mtd_badblocks_show, NULL);
+
+static ssize_t mtd_bbtblocks_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->bbtblocks);
+}
+static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL);
+
static struct attribute *mtd_attrs[] = {
&dev_attr_type.attr,
&dev_attr_flags.attr,
@@ -310,6 +351,10 @@ static struct attribute *mtd_attrs[] = {
&dev_attr_name.attr,
&dev_attr_ecc_strength.attr,
&dev_attr_ecc_step_size.attr,
+ &dev_attr_corrected_bits.attr,
+ &dev_attr_ecc_failures.attr,
+ &dev_attr_bad_blocks.attr,
+ &dev_attr_bbt_blocks.attr,
&dev_attr_bitflip_threshold.attr,
NULL,
};
@@ -998,12 +1043,22 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
}
EXPORT_SYMBOL_GPL(mtd_is_locked);
-int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
+int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
{
- if (!mtd->_block_isbad)
+ if (ofs < 0 || ofs > mtd->size)
+ return -EINVAL;
+ if (!mtd->_block_isreserved)
return 0;
+ return mtd->_block_isreserved(mtd, ofs);
+}
+EXPORT_SYMBOL_GPL(mtd_block_isreserved);
+
+int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
if (ofs < 0 || ofs > mtd->size)
return -EINVAL;
+ if (!mtd->_block_isbad)
+ return 0;
return mtd->_block_isbad(mtd, ofs);
}
EXPORT_SYMBOL_GPL(mtd_block_isbad);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 1ca9aec141ff..a3e3a7d074d5 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -290,6 +290,13 @@ static void part_resume(struct mtd_info *mtd)
part->master->_resume(part->master);
}
+static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_part *part = PART(mtd);
+ ofs += part->offset;
+ return part->master->_block_isreserved(part->master, ofs);
+}
+
static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
struct mtd_part *part = PART(mtd);
@@ -422,6 +429,8 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
slave->mtd._unlock = part_unlock;
if (master->_is_locked)
slave->mtd._is_locked = part_is_locked;
+ if (master->_block_isreserved)
+ slave->mtd._block_isreserved = part_block_isreserved;
if (master->_block_isbad)
slave->mtd._block_isbad = part_block_isbad;
if (master->_block_markbad)
@@ -526,7 +535,9 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
uint64_t offs = 0;
while (offs < slave->mtd.size) {
- if (mtd_block_isbad(master, offs + slave->offset))
+ if (mtd_block_isreserved(master, offs + slave->offset))
+ slave->mtd.ecc_stats.bbtblocks++;
+ else if (mtd_block_isbad(master, offs + slave->offset))
slave->mtd.ecc_stats.badblocks++;
offs += slave->mtd.erasesize;
}
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 542b5689eb63..a035e7cc6d46 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -50,4 +50,4 @@ obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
-nand-objs := nand_base.o nand_bbt.o
+nand-objs := nand_base.o nand_bbt.o nand_timings.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4ce181a35bcd..e321c564ff05 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -97,7 +97,9 @@ struct atmel_nfc {
bool write_by_sram;
bool is_initialized;
- struct completion comp_nfc;
+ struct completion comp_ready;
+ struct completion comp_cmd_done;
+ struct completion comp_xfer_done;
/* Point to the sram bank which include readed data via NFC */
void __iomem *data_in_sram;
@@ -861,12 +863,11 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
{
struct nand_chip *nand_chip = mtd->priv;
struct atmel_nand_host *host = nand_chip->priv;
- int i, err_nbr, eccbytes;
+ int i, err_nbr;
uint8_t *buf_pos;
int total_err = 0;
- eccbytes = nand_chip->ecc.bytes;
- for (i = 0; i < eccbytes; i++)
+ for (i = 0; i < nand_chip->ecc.total; i++)
if (ecc[i] != 0xff)
goto normal_check;
/* Erased page, return OK */
@@ -928,7 +929,7 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{
struct atmel_nand_host *host = chip->priv;
- int eccsize = chip->ecc.size;
+ int eccsize = chip->ecc.size * chip->ecc.steps;
uint8_t *oob = chip->oob_poi;
uint32_t *eccpos = chip->ecc.layout->eccpos;
uint32_t stat;
@@ -1169,8 +1170,7 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
goto err;
}
- /* ECC is calculated for the whole page (1 step) */
- nand_chip->ecc.size = mtd->writesize;
+ nand_chip->ecc.size = sector_size;
/* set ECC page size and oob layout */
switch (mtd->writesize) {
@@ -1185,18 +1185,20 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
host->pmecc_index_of = host->pmecc_rom_base +
host->pmecc_lookup_table_offset;
- nand_chip->ecc.steps = 1;
+ nand_chip->ecc.steps = host->pmecc_sector_number;
nand_chip->ecc.strength = cap;
- nand_chip->ecc.bytes = host->pmecc_bytes_per_sector *
+ nand_chip->ecc.bytes = host->pmecc_bytes_per_sector;
+ nand_chip->ecc.total = host->pmecc_bytes_per_sector *
host->pmecc_sector_number;
- if (nand_chip->ecc.bytes > mtd->oobsize - 2) {
+ if (nand_chip->ecc.total > mtd->oobsize - 2) {
dev_err(host->dev, "No room for ECC bytes\n");
err_no = -EINVAL;
goto err;
}
pmecc_config_ecc_layout(&atmel_pmecc_oobinfo,
mtd->oobsize,
- nand_chip->ecc.bytes);
+ nand_chip->ecc.total);
+
nand_chip->ecc.layout = &atmel_pmecc_oobinfo;
break;
case 512:
@@ -1572,49 +1574,104 @@ static int atmel_hw_nand_init_params(struct platform_device *pdev,
return 0;
}
+static inline u32 nfc_read_status(struct atmel_nand_host *host)
+{
+ u32 err_flags = NFC_SR_DTOE | NFC_SR_UNDEF | NFC_SR_AWB | NFC_SR_ASE;
+ u32 nfc_status = nfc_readl(host->nfc->hsmc_regs, SR);
+
+ if (unlikely(nfc_status & err_flags)) {
+ if (nfc_status & NFC_SR_DTOE)
+ dev_err(host->dev, "NFC: Waiting Nand R/B Timeout Error\n");
+ else if (nfc_status & NFC_SR_UNDEF)
+ dev_err(host->dev, "NFC: Access Undefined Area Error\n");
+ else if (nfc_status & NFC_SR_AWB)
+ dev_err(host->dev, "NFC: Access memory While NFC is busy\n");
+ else if (nfc_status & NFC_SR_ASE)
+ dev_err(host->dev, "NFC: Access memory Size Error\n");
+ }
+
+ return nfc_status;
+}
+
/* SMC interrupt service routine */
static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
{
struct atmel_nand_host *host = dev_id;
u32 status, mask, pending;
- irqreturn_t ret = IRQ_HANDLED;
+ irqreturn_t ret = IRQ_NONE;
- status = nfc_readl(host->nfc->hsmc_regs, SR);
+ status = nfc_read_status(host);
mask = nfc_readl(host->nfc->hsmc_regs, IMR);
pending = status & mask;
if (pending & NFC_SR_XFR_DONE) {
- complete(&host->nfc->comp_nfc);
+ complete(&host->nfc->comp_xfer_done);
nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
- } else if (pending & NFC_SR_RB_EDGE) {
- complete(&host->nfc->comp_nfc);
+ ret = IRQ_HANDLED;
+ }
+ if (pending & NFC_SR_RB_EDGE) {
+ complete(&host->nfc->comp_ready);
nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
- } else if (pending & NFC_SR_CMD_DONE) {
- complete(&host->nfc->comp_nfc);
+ ret = IRQ_HANDLED;
+ }
+ if (pending & NFC_SR_CMD_DONE) {
+ complete(&host->nfc->comp_cmd_done);
nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE);
- } else {
- ret = IRQ_NONE;
+ ret = IRQ_HANDLED;
}
return ret;
}
/* NFC(Nand Flash Controller) related functions */
-static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
+static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
{
- unsigned long timeout;
- init_completion(&host->nfc->comp_nfc);
+ if (flag & NFC_SR_XFR_DONE)
+ init_completion(&host->nfc->comp_xfer_done);
+
+ if (flag & NFC_SR_RB_EDGE)
+ init_completion(&host->nfc->comp_ready);
+
+ if (flag & NFC_SR_CMD_DONE)
+ init_completion(&host->nfc->comp_cmd_done);
/* Enable interrupt that need to wait for */
nfc_writel(host->nfc->hsmc_regs, IER, flag);
+}
- timeout = wait_for_completion_timeout(&host->nfc->comp_nfc,
- msecs_to_jiffies(NFC_TIME_OUT_MS));
- if (timeout)
- return 0;
+static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
+{
+ int i, index = 0;
+ struct completion *comp[3]; /* Support 3 interrupt completion */
- /* Time out to wait for the interrupt */
+ if (flag & NFC_SR_XFR_DONE)
+ comp[index++] = &host->nfc->comp_xfer_done;
+
+ if (flag & NFC_SR_RB_EDGE)
+ comp[index++] = &host->nfc->comp_ready;
+
+ if (flag & NFC_SR_CMD_DONE)
+ comp[index++] = &host->nfc->comp_cmd_done;
+
+ if (index == 0) {
+ dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < index; i++) {
+ if (wait_for_completion_timeout(comp[i],
+ msecs_to_jiffies(NFC_TIME_OUT_MS)))
+ continue; /* wait for next completion */
+ else
+ goto err_timeout;
+ }
+
+ return 0;
+
+err_timeout:
dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag);
+ /* Disable the interrupt as it is not handled by interrupt handler */
+ nfc_writel(host->nfc->hsmc_regs, IDR, flag);
return -ETIMEDOUT;
}
@@ -1622,6 +1679,9 @@ static int nfc_send_command(struct atmel_nand_host *host,
unsigned int cmd, unsigned int addr, unsigned char cycle0)
{
unsigned long timeout;
+ u32 flag = NFC_SR_CMD_DONE;
+ flag |= cmd & NFCADDR_CMD_DATAEN ? NFC_SR_XFR_DONE : 0;
+
dev_dbg(host->dev,
"nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n",
cmd, addr, cycle0);
@@ -1635,18 +1695,28 @@ static int nfc_send_command(struct atmel_nand_host *host,
return -ETIMEDOUT;
}
}
+
+ nfc_prepare_interrupt(host, flag);
nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0);
nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs);
- return nfc_wait_interrupt(host, NFC_SR_CMD_DONE);
+ return nfc_wait_interrupt(host, flag);
}
static int nfc_device_ready(struct mtd_info *mtd)
{
+ u32 status, mask;
struct nand_chip *nand_chip = mtd->priv;
struct atmel_nand_host *host = nand_chip->priv;
- if (!nfc_wait_interrupt(host, NFC_SR_RB_EDGE))
- return 1;
- return 0;
+
+ status = nfc_read_status(host);
+ mask = nfc_readl(host->nfc->hsmc_regs, IMR);
+
+ /* The mask should be 0. If not we may lost interrupts */
+ if (unlikely(mask & status))
+ dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
+ mask & status);
+
+ return status & NFC_SR_RB_EDGE;
}
static void nfc_select_chip(struct mtd_info *mtd, int chip)
@@ -1795,10 +1865,6 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
- if (dataen == NFCADDR_CMD_DATAEN)
- if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE))
- dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n");
-
/*
* Program and erase have their own busy handlers status, sequential
* in, and deplete1 need no delay.
@@ -1823,6 +1889,7 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
}
/* fall through */
default:
+ nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
}
}
@@ -2209,6 +2276,9 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
}
}
+ nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
+ nfc_readl(nfc->hsmc_regs, SR); /* clear the NFC_SR */
+
nfc->is_initialized = true;
dev_info(&pdev->dev, "NFC is probed.\n");
return 0;
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
index 4efd117cd3a3..85b8ca6af7d2 100644
--- a/drivers/mtd/nand/atmel_nand_nfc.h
+++ b/drivers/mtd/nand/atmel_nand_nfc.h
@@ -37,6 +37,10 @@
#define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */
#define NFC_SR_XFR_DONE (1 << 16)
#define NFC_SR_CMD_DONE (1 << 17)
+#define NFC_SR_DTOE (1 << 20)
+#define NFC_SR_UNDEF (1 << 21)
+#define NFC_SR_AWB (1 << 22)
+#define NFC_SR_ASE (1 << 23)
#define NFC_SR_RB_EDGE (1 << 24)
#define ATMEL_HSMC_NFC_IER 0x0c
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index bc5c518828d2..77d6c17b38c2 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -41,7 +41,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u_char ret = readb(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -56,7 +56,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd->priv;
writeb(byte, this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
/**
@@ -69,7 +69,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -84,7 +84,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd->priv;
writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
/**
@@ -97,7 +97,7 @@ static u16 au_read_word(struct mtd_info *mtd)
{
struct nand_chip *this = mtd->priv;
u16 ret = readw(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
return ret;
}
@@ -116,7 +116,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
for (i = 0; i < len; i++) {
writeb(buf[i], this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -135,7 +135,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
for (i = 0; i < len; i++) {
buf[i] = readb(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -156,7 +156,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
for (i = 0; i < len; i++) {
writew(p[i], this->IO_ADDR_W);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -178,7 +178,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
for (i = 0; i < len; i++) {
p[i] = readw(this->IO_ADDR_R);
- au_sync();
+ wmb(); /* drain writebuffer */
}
}
@@ -223,26 +223,23 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
case NAND_CTL_SETNCE:
/* assert (force assert) chip enable */
- au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
+ alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
break;
case NAND_CTL_CLRNCE:
/* deassert chip enable */
- au_writel(0, MEM_STNDCTL);
+ alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
break;
}
this->IO_ADDR_R = this->IO_ADDR_W;
- /* Drain the writebuffer */
- au_sync();
+ wmb(); /* Drain the writebuffer */
}
int au1550_device_ready(struct mtd_info *mtd)
{
- int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
- au_sync();
- return ret;
+ return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
}
/**
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 722898aea7a6..871c4f712654 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -830,34 +830,10 @@ out_err:
return err;
}
-/* PM Support */
-#ifdef CONFIG_PM
-
-static int bf5xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
-{
- struct bf5xx_nand_info *info = platform_get_drvdata(dev);
-
- return 0;
-}
-
-static int bf5xx_nand_resume(struct platform_device *dev)
-{
- struct bf5xx_nand_info *info = platform_get_drvdata(dev);
-
- return 0;
-}
-
-#else
-#define bf5xx_nand_suspend NULL
-#define bf5xx_nand_resume NULL
-#endif
-
/* driver device registration */
static struct platform_driver bf5xx_nand_driver = {
.probe = bf5xx_nand_probe,
.remove = bf5xx_nand_remove,
- .suspend = bf5xx_nand_suspend,
- .resume = bf5xx_nand_resume,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 9f2012a3e764..0b071a3136a2 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -473,7 +473,7 @@ static void detect_partition_feature(struct denali_nand_info *denali)
static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
{
uint16_t status = PASS;
- uint32_t id_bytes[5], addr;
+ uint32_t id_bytes[8], addr;
uint8_t i, maf_id, device_id;
dev_dbg(denali->dev,
@@ -488,7 +488,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
index_addr(denali, (uint32_t)addr | 0, 0x90);
index_addr(denali, (uint32_t)addr | 1, 0);
- for (i = 0; i < 5; i++)
+ for (i = 0; i < 8; i++)
index_addr_read_data(denali, addr | 2, &id_bytes[i]);
maf_id = id_bytes[0];
device_id = id_bytes[1];
@@ -1276,7 +1276,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
index_addr(denali, (uint32_t)addr | 0, 0x90);
index_addr(denali, (uint32_t)addr | 1, 0);
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 8; i++) {
index_addr_read_data(denali,
(uint32_t)addr | 2,
&id);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index f638cd8077ca..959cb9b70310 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -285,9 +285,8 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
geo->ecc_strength = get_ecc_strength(this);
if (!gpmi_check_ecc(this)) {
dev_err(this->dev,
- "We can not support this nand chip."
- " Its required ecc strength(%d) is beyond our"
- " capability(%d).\n", geo->ecc_strength,
+ "required ecc strength of the NAND chip: %d is not supported by the GPMI controller (%d)\n",
+ geo->ecc_strength,
this->devdata->bch_max_ecc_strength);
return -EINVAL;
}
@@ -1082,6 +1081,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
int first, last, marker_pos;
int ecc_parity_size;
int col = 0;
+ int old_swap_block_mark = this->swap_block_mark;
/* The size of ECC parity */
ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
@@ -1090,17 +1090,21 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
first = offs / size;
last = (offs + len - 1) / size;
- /*
- * Find the chunk which contains the Block Marker. If this chunk is
- * in the range of [first, last], we have to read out the whole page.
- * Why? since we had swapped the data at the position of Block Marker
- * to the metadata which is bound with the chunk 0.
- */
- marker_pos = geo->block_mark_byte_offset / size;
- if (last >= marker_pos && first <= marker_pos) {
- dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n",
+ if (this->swap_block_mark) {
+ /*
+ * Find the chunk which contains the Block Marker.
+ * If this chunk is in the range of [first, last],
+ * we have to read out the whole page.
+ * Why? since we had swapped the data at the position of Block
+ * Marker to the metadata which is bound with the chunk 0.
+ */
+ marker_pos = geo->block_mark_byte_offset / size;
+ if (last >= marker_pos && first <= marker_pos) {
+ dev_dbg(this->dev,
+ "page:%d, first:%d, last:%d, marker at:%d\n",
page, first, last, marker_pos);
- return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
+ return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
+ }
}
meta = geo->metadata_size;
@@ -1146,7 +1150,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0);
writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1);
this->bch_geometry = old_geo;
- this->swap_block_mark = true;
+ this->swap_block_mark = old_swap_block_mark;
return max_bitflips;
}
@@ -1180,7 +1184,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
/* Handle block mark swapping. */
block_mark_swapping(this,
- (void *) payload_virt, (void *) auxiliary_virt);
+ (void *)payload_virt, (void *)auxiliary_virt);
} else {
/*
* If control arrives here, we're not doing block mark swapping,
@@ -1310,10 +1314,10 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
/*
* Now, we want to make sure the block mark is correct. In the
- * Swapping/Raw case, we already have it. Otherwise, we need to
- * explicitly read it.
+ * non-transcribing case (!GPMI_IS_MX23()), we already have it.
+ * Otherwise, we need to explicitly read it.
*/
- if (!this->swap_block_mark) {
+ if (GPMI_IS_MX23(this)) {
/* Read the block mark into the first byte of the OOB buffer. */
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
chip->oob_poi[0] = chip->read_byte(mtd);
@@ -1354,7 +1358,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
chipnr = (int)(ofs >> chip->chip_shift);
chip->select_chip(mtd, chipnr);
- column = this->swap_block_mark ? mtd->writesize : 0;
+ column = !GPMI_IS_MX23(this) ? mtd->writesize : 0;
/* Write the block mark. */
block_mark = this->data_buffer_dma;
@@ -1597,8 +1601,9 @@ static int mx23_boot_init(struct gpmi_nand_data *this)
dev_dbg(dev, "Transcribing mark in block %u\n", block);
ret = chip->block_markbad(mtd, byte);
if (ret)
- dev_err(dev, "Failed to mark block bad with "
- "ret %d\n", ret);
+ dev_err(dev,
+ "Failed to mark block bad with ret %d\n",
+ ret);
}
}
@@ -1649,9 +1654,6 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
struct bch_geometry *bch_geo = &this->bch_geometry;
int ret;
- /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
- this->swap_block_mark = !GPMI_IS_MX23(this);
-
/* Set up the medium geometry */
ret = gpmi_set_geometry(this);
if (ret)
@@ -1715,9 +1717,20 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
chip->badblock_pattern = &gpmi_bbt_descr;
chip->block_markbad = gpmi_block_markbad;
chip->options |= NAND_NO_SUBPAGE_WRITE;
- if (of_get_nand_on_flash_bbt(this->dev->of_node))
+
+ /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+ this->swap_block_mark = !GPMI_IS_MX23(this);
+
+ if (of_get_nand_on_flash_bbt(this->dev->of_node)) {
chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
+ if (of_property_read_bool(this->dev->of_node,
+ "fsl,no-blockmark-swap"))
+ this->swap_block_mark = false;
+ }
+ dev_dbg(this->dev, "Blockmark swapping %sabled\n",
+ this->swap_block_mark ? "en" : "dis");
+
/*
* Allocate a temporary DMA buffer for reading ID in the
* nand_scan_ident().
@@ -1760,16 +1773,16 @@ err_out:
static const struct of_device_id gpmi_nand_id_table[] = {
{
.compatible = "fsl,imx23-gpmi-nand",
- .data = (void *)&gpmi_devdata_imx23,
+ .data = &gpmi_devdata_imx23,
}, {
.compatible = "fsl,imx28-gpmi-nand",
- .data = (void *)&gpmi_devdata_imx28,
+ .data = &gpmi_devdata_imx28,
}, {
.compatible = "fsl,imx6q-gpmi-nand",
- .data = (void *)&gpmi_devdata_imx6q,
+ .data = &gpmi_devdata_imx6q,
}, {
.compatible = "fsl,imx6sx-gpmi-nand",
- .data = (void *)&gpmi_devdata_imx6sx,
+ .data = &gpmi_devdata_imx6sx,
}, {}
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 687478c9f09c..7335346dc126 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -721,12 +721,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
nand_chip->bbt_td = &lpc32xx_nand_bbt;
nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror;
- /* bitflip_threshold's default is defined as ecc_strength anyway.
- * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
- * being 0, it causes bad block table scanning errors in
- * nand_scan_tail(), so preparing it here. */
- mtd->bitflip_threshold = nand_chip->ecc.strength;
-
if (use_dma) {
res = lpc32xx_dma_setup(host);
if (res) {
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index 53a6742e3da3..8caef28e0756 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -840,12 +840,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
chip->ecc.strength = 1;
chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
- /* bitflip_threshold's default is defined as ecc_strength anyway.
- * Unfortunately, it is set only later at add_mtd_device(). Meanwhile
- * being 0, it causes bad block table scanning errors in
- * nand_scan_tail(), so preparing it here already. */
- mtd->bitflip_threshold = chip->ecc.strength;
-
/*
* Allocate a large enough buffer for a single huge page plus
* extra space for the spare area and ECC storage area
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 4f3e80c68a26..d8cdf06343fb 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -488,6 +488,23 @@ static int nand_check_wp(struct mtd_info *mtd)
* nand_block_checkbad - [GENERIC] Check if a block is marked bad
* @mtd: MTD device structure
* @ofs: offset from device start
+ *
+ * Check if the block is mark as reserved.
+ */
+static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ if (!chip->bbt)
+ return 0;
+ /* Return info from the table */
+ return nand_isreserved_bbt(mtd, ofs);
+}
+
+/**
+ * nand_block_checkbad - [GENERIC] Check if a block is marked bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
* @getchip: 0, if the chip is already selected
* @allowbbt: 1, if its allowed to access the bbt area
*
@@ -4113,6 +4130,7 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->_unlock = NULL;
mtd->_suspend = nand_suspend;
mtd->_resume = nand_resume;
+ mtd->_block_isreserved = nand_block_isreserved;
mtd->_block_isbad = nand_block_isbad;
mtd->_block_markbad = nand_block_markbad;
mtd->writebufsize = mtd->writesize;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 7f0c3b4c2a4f..443fa82cde6a 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1311,6 +1311,20 @@ int nand_default_bbt(struct mtd_info *mtd)
}
/**
+ * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
+ * @mtd: MTD device structure
+ * @offs: offset in the device
+ */
+int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
+{
+ struct nand_chip *this = mtd->priv;
+ int block;
+
+ block = (int)(offs >> this->bbt_erase_shift);
+ return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED;
+}
+
+/**
* nand_isbad_bbt - [NAND Interface] Check if a block is bad
* @mtd: MTD device structure
* @offs: offset in the device
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
new file mode 100644
index 000000000000..8b36253420fa
--- /dev/null
+++ b/drivers/mtd/nand/nand_timings.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/mtd/nand.h>
+
+static const struct nand_sdr_timings onfi_sdr_timings[] = {
+ /* Mode 0 */
+ {
+ .tADL_min = 200000,
+ .tALH_min = 20000,
+ .tALS_min = 50000,
+ .tAR_min = 25000,
+ .tCEA_max = 100000,
+ .tCEH_min = 20000,
+ .tCH_min = 20000,
+ .tCHZ_max = 100000,
+ .tCLH_min = 20000,
+ .tCLR_min = 20000,
+ .tCLS_min = 50000,
+ .tCOH_min = 0,
+ .tCS_min = 70000,
+ .tDH_min = 20000,
+ .tDS_min = 40000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 10000,
+ .tITC_max = 1000000,
+ .tRC_min = 100000,
+ .tREA_max = 40000,
+ .tREH_min = 30000,
+ .tRHOH_min = 0,
+ .tRHW_min = 200000,
+ .tRHZ_max = 200000,
+ .tRLOH_min = 0,
+ .tRP_min = 50000,
+ .tRST_max = 250000000000,
+ .tWB_max = 200000,
+ .tRR_min = 40000,
+ .tWC_min = 100000,
+ .tWH_min = 30000,
+ .tWHR_min = 120000,
+ .tWP_min = 50000,
+ .tWW_min = 100000,
+ },
+ /* Mode 1 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 10000,
+ .tALS_min = 25000,
+ .tAR_min = 10000,
+ .tCEA_max = 45000,
+ .tCEH_min = 20000,
+ .tCH_min = 10000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 10000,
+ .tCLR_min = 10000,
+ .tCLS_min = 25000,
+ .tCOH_min = 15000,
+ .tCS_min = 35000,
+ .tDH_min = 10000,
+ .tDS_min = 20000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 50000,
+ .tREA_max = 30000,
+ .tREH_min = 15000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRP_min = 25000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 45000,
+ .tWH_min = 15000,
+ .tWHR_min = 80000,
+ .tWP_min = 25000,
+ .tWW_min = 100000,
+ },
+ /* Mode 2 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 10000,
+ .tALS_min = 15000,
+ .tAR_min = 10000,
+ .tCEA_max = 30000,
+ .tCEH_min = 20000,
+ .tCH_min = 10000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 10000,
+ .tCLR_min = 10000,
+ .tCLS_min = 15000,
+ .tCOH_min = 15000,
+ .tCS_min = 25000,
+ .tDH_min = 5000,
+ .tDS_min = 15000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 35000,
+ .tREA_max = 25000,
+ .tREH_min = 15000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tRP_min = 17000,
+ .tWC_min = 35000,
+ .tWH_min = 15000,
+ .tWHR_min = 80000,
+ .tWP_min = 17000,
+ .tWW_min = 100000,
+ },
+ /* Mode 3 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 25000,
+ .tDH_min = 5000,
+ .tDS_min = 10000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 30000,
+ .tREA_max = 20000,
+ .tREH_min = 10000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRP_min = 15000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 30000,
+ .tWH_min = 10000,
+ .tWHR_min = 80000,
+ .tWP_min = 15000,
+ .tWW_min = 100000,
+ },
+ /* Mode 4 */
+ {
+ .tADL_min = 70000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 30000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 20000,
+ .tDH_min = 5000,
+ .tDS_min = 10000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 25000,
+ .tREA_max = 20000,
+ .tREH_min = 10000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 5000,
+ .tRP_min = 12000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 25000,
+ .tWH_min = 10000,
+ .tWHR_min = 80000,
+ .tWP_min = 12000,
+ .tWW_min = 100000,
+ },
+ /* Mode 5 */
+ {
+ .tADL_min = 70000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 30000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 15000,
+ .tDH_min = 5000,
+ .tDS_min = 7000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 20000,
+ .tREA_max = 16000,
+ .tREH_min = 7000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 5000,
+ .tRP_min = 10000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 20000,
+ .tWH_min = 7000,
+ .tWHR_min = 80000,
+ .tWP_min = 10000,
+ .tWW_min = 100000,
+ },
+};
+
+/**
+ * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
+ * timings according to the given ONFI timing mode
+ * @mode: ONFI timing mode
+ */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
+{
+ if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
+ return ERR_PTR(-EINVAL);
+
+ return &onfi_sdr_timings[mode];
+}
+EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 79acbb8691b5..6b97bf17ce5d 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -208,10 +208,10 @@ static void s3c2410_nand_clk_set_state(struct s3c2410_nand_info *info,
if (info->clk_state == CLOCK_ENABLE) {
if (new_state != CLOCK_ENABLE)
- clk_disable(info->clk);
+ clk_disable_unprepare(info->clk);
} else {
if (new_state == CLOCK_ENABLE)
- clk_enable(info->clk);
+ clk_prepare_enable(info->clk);
}
info->clk_state = new_state;
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index ab2607273e80..dcae2f6a2b11 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -32,10 +32,10 @@ config MTD_ONENAND_OMAP2
config MTD_ONENAND_SAMSUNG
tristate "OneNAND on Samsung SOC controller support"
- depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4
+ depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4
help
Support for a OneNAND flash device connected to an Samsung SOC.
- S3C64XX/S5PC100 use command mapping method.
+ S3C64XX uses command mapping method.
S5PC110/S5PC210 use generic OneNAND method.
config MTD_ONENAND_OTP
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index efb819c3df2f..19cfb97adbc0 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -10,7 +10,7 @@
* published by the Free Software Foundation.
*
* Implementation:
- * S3C64XX and S5PC100: emulate the pseudo BufferRAM
+ * S3C64XX: emulate the pseudo BufferRAM
* S5PC110: use DMA
*/
@@ -32,7 +32,6 @@
enum soc_type {
TYPE_S3C6400,
TYPE_S3C6410,
- TYPE_S5PC100,
TYPE_S5PC110,
};
@@ -59,7 +58,6 @@ enum soc_type {
#define MAP_11 (0x3)
#define S3C64XX_CMD_MAP_SHIFT 24
-#define S5PC100_CMD_MAP_SHIFT 26
#define S3C6400_FBA_SHIFT 10
#define S3C6400_FPA_SHIFT 4
@@ -69,10 +67,6 @@ enum soc_type {
#define S3C6410_FPA_SHIFT 6
#define S3C6410_FSA_SHIFT 4
-#define S5PC100_FBA_SHIFT 13
-#define S5PC100_FPA_SHIFT 7
-#define S5PC100_FSA_SHIFT 5
-
/* S5PC110 specific definitions */
#define S5PC110_DMA_SRC_ADDR 0x400
#define S5PC110_DMA_SRC_CFG 0x404
@@ -195,11 +189,6 @@ static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
return (type << S3C64XX_CMD_MAP_SHIFT) | val;
}
-static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val)
-{
- return (type << S5PC100_CMD_MAP_SHIFT) | val;
-}
-
static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa)
{
return (fba << S3C6400_FBA_SHIFT) | (fpa << S3C6400_FPA_SHIFT) |
@@ -212,12 +201,6 @@ static unsigned int s3c6410_mem_addr(int fba, int fpa, int fsa)
(fsa << S3C6410_FSA_SHIFT);
}
-static unsigned int s5pc100_mem_addr(int fba, int fpa, int fsa)
-{
- return (fba << S5PC100_FBA_SHIFT) | (fpa << S5PC100_FPA_SHIFT) |
- (fsa << S5PC100_FSA_SHIFT);
-}
-
static void s3c_onenand_reset(void)
{
unsigned long timeout = 0x10000;
@@ -835,9 +818,6 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
} else if (onenand->type == TYPE_S3C6410) {
onenand->mem_addr = s3c6410_mem_addr;
onenand->cmd_map = s3c64xx_cmd_map;
- } else if (onenand->type == TYPE_S5PC100) {
- onenand->mem_addr = s5pc100_mem_addr;
- onenand->cmd_map = s5pc1xx_cmd_map;
} else if (onenand->type == TYPE_S5PC110) {
/* Use generic onenand functions */
this->read_bufferram = s5pc110_read_bufferram;
@@ -1111,9 +1091,6 @@ static struct platform_device_id s3c_onenand_driver_ids[] = {
.name = "s3c6410-onenand",
.driver_data = TYPE_S3C6410,
}, {
- .name = "s5pc100-onenand",
- .driver_data = TYPE_S5PC100,
- }, {
.name = "s5pc110-onenand",
.driver_data = TYPE_S5PC110,
}, { },
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index c713c8656710..b5ad6bebf5e7 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -48,6 +48,25 @@ static int read_sr(struct spi_nor *nor)
}
/*
+ * Read the flag status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_fsr(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
+ if (ret < 0) {
+ pr_err("error %d reading FSR\n", ret);
+ return ret;
+ }
+
+ return val;
+}
+
+/*
* Read configuration register, returning its value in the
* location. Return the configuration register value.
* Returns negative if error occured.
@@ -165,6 +184,32 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
return -ETIMEDOUT;
}
+static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor)
+{
+ unsigned long deadline;
+ int sr;
+ int fsr;
+
+ deadline = jiffies + MAX_READY_WAIT_JIFFIES;
+
+ do {
+ cond_resched();
+
+ sr = read_sr(nor);
+ if (sr < 0) {
+ break;
+ } else if (!(sr & SR_WIP)) {
+ fsr = read_fsr(nor);
+ if (fsr < 0)
+ break;
+ if (fsr & FSR_READY)
+ return 0;
+ }
+ } while (!time_after_eq(jiffies, deadline));
+
+ return -ETIMEDOUT;
+}
+
/*
* Service routine to read status register until ready, or timeout occurs.
* Returns non-zero if error.
@@ -402,6 +447,7 @@ struct flash_info {
#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
+#define USE_FSR 0x80 /* use flag status register */
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -449,6 +495,7 @@ const struct spi_device_id spi_nor_ids[] = {
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
/* ESMT */
@@ -488,6 +535,8 @@ const struct spi_device_id spi_nor_ids[] = {
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
{ "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
{ "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) },
/* PMC */
{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
@@ -965,6 +1014,10 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
else
mtd->_write = spi_nor_write;
+ if ((info->flags & USE_FSR) &&
+ nor->wait_till_ready == spi_nor_wait_till_ready)
+ nor->wait_till_ready = spi_nor_wait_till_fsr_ready;
+
/* prefer "small sector" erase if possible */
if (info->flags & SECT_4K) {
nor->erase_opcode = SPINOR_OP_BE_4K;
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 8457df7ec5af..33c64955d4d7 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -378,9 +378,11 @@ int ubiblock_create(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
struct gendisk *gd;
- int disk_capacity;
+ u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
int ret;
+ if ((sector_t)disk_capacity != disk_capacity)
+ return -EFBIG;
/* Check that the volume isn't already handled */
mutex_lock(&devices_mutex);
if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
@@ -412,7 +414,6 @@ int ubiblock_create(struct ubi_volume_info *vi)
gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
gd->private_data = dev;
sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
- disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
set_capacity(gd, disk_capacity);
dev->gd = gd;
@@ -498,11 +499,16 @@ int ubiblock_remove(struct ubi_volume_info *vi)
return 0;
}
-static void ubiblock_resize(struct ubi_volume_info *vi)
+static int ubiblock_resize(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
- int disk_capacity;
+ u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9;
+ if ((sector_t)disk_capacity != disk_capacity) {
+ ubi_warn("%s: the volume is too big, cannot resize (%d LEBs)",
+ dev->gd->disk_name, vi->size);
+ return -EFBIG;
+ }
/*
* Need to lock the device list until we stop using the device,
* otherwise the device struct might get released in
@@ -512,15 +518,15 @@ static void ubiblock_resize(struct ubi_volume_info *vi)
dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
if (!dev) {
mutex_unlock(&devices_mutex);
- return;
+ return -ENODEV;
}
mutex_lock(&dev->dev_mutex);
- disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
set_capacity(dev->gd, disk_capacity);
ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
mutex_unlock(&dev->dev_mutex);
mutex_unlock(&devices_mutex);
+ return 0;
}
static int ubiblock_notify(struct notifier_block *nb,
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index d77b1c1d7c72..07cac5f9ffb8 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -591,7 +591,7 @@ static int init_volumes(struct ubi_device *ubi,
/* Static volumes only */
av = ubi_find_av(ai, i);
- if (!av) {
+ if (!av || !av->leb_count) {
/*
* No eraseblocks belonging to this volume found. We
* don't actually know whether this static volume is
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 0f3425dac910..20f491713145 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1718,12 +1718,12 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
vol_id, lnum, ubi->works_count);
while (found) {
- struct ubi_work *wrk;
+ struct ubi_work *wrk, *tmp;
found = 0;
down_read(&ubi->work_sem);
spin_lock(&ubi->wl_lock);
- list_for_each_entry(wrk, &ubi->works, list) {
+ list_for_each_entry_safe(wrk, tmp, &ubi->works, list) {
if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
(lnum == UBI_ALL || wrk->lnum == lnum)) {
list_del(&wrk->list);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 89402c3b64f8..c6f6f69f8961 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -148,6 +148,7 @@ config VXLAN
tristate "Virtual eXtensible Local Area Network (VXLAN)"
depends on INET
select NET_IP_TUNNEL
+ select NET_UDP_TUNNEL
---help---
This allows one to create vxlan virtual interfaces that provide
Layer 2 Networks over Layer 3 Networks. VXLAN is often used
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3fef8a81c0f6..61aefdd1e173 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -61,15 +61,7 @@ obj-$(CONFIG_VMXNET3) += vmxnet3/
obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
-obj-$(CONFIG_USB_CATC) += usb/
-obj-$(CONFIG_USB_KAWETH) += usb/
-obj-$(CONFIG_USB_PEGASUS) += usb/
-obj-$(CONFIG_USB_RTL8150) += usb/
-obj-$(CONFIG_USB_HSO) += usb/
-obj-$(CONFIG_USB_USBNET) += usb/
-obj-$(CONFIG_USB_ZD1201) += usb/
-obj-$(CONFIG_USB_IPHETH) += usb/
-obj-$(CONFIG_USB_CDC_PHONET) += usb/
+obj-$(CONFIG_USB_NET_DRIVERS) += usb/
obj-$(CONFIG_HYPERV_NET) += hyperv/
obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index a956053608f9..3b790de6c976 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -346,7 +346,8 @@ struct net_device *alloc_arcdev(const char *name)
struct net_device *dev;
dev = alloc_netdev(sizeof(struct arcnet_local),
- name && *name ? name : "arc%d", arcdev_setup);
+ name && *name ? name : "arc%d", NET_NAME_UNKNOWN,
+ arcdev_setup);
if(dev) {
struct arcnet_local *lp = netdev_priv(dev);
spin_lock_init(&lp->lock);
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index cbc44f53755a..7bb292e59559 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -144,7 +144,7 @@ static void com20020pci_remove(struct pci_dev *pdev)
free_netdev(dev);
}
-static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = {
+static const struct pci_device_id com20020pci_id_table[] = {
{ 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
index 326a612a2730..1a790a20210d 100644
--- a/drivers/net/arcnet/com20020_cs.c
+++ b/drivers/net/arcnet/com20020_cs.c
@@ -112,20 +112,20 @@ static void com20020_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
-typedef struct com20020_dev_t {
+struct com20020_dev {
struct net_device *dev;
-} com20020_dev_t;
+};
static int com20020_probe(struct pcmcia_device *p_dev)
{
- com20020_dev_t *info;
+ struct com20020_dev *info;
struct net_device *dev;
struct arcnet_local *lp;
dev_dbg(&p_dev->dev, "com20020_attach()\n");
/* Create new network device */
- info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto fail_alloc_info;
@@ -160,7 +160,7 @@ fail_alloc_info:
static void com20020_detach(struct pcmcia_device *link)
{
- struct com20020_dev_t *info = link->priv;
+ struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
dev_dbg(&link->dev, "detach...\n");
@@ -199,7 +199,7 @@ static void com20020_detach(struct pcmcia_device *link)
static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
- com20020_dev_t *info;
+ struct com20020_dev *info;
struct net_device *dev;
int i, ret;
int ioaddr;
@@ -291,7 +291,7 @@ static void com20020_release(struct pcmcia_device *link)
static int com20020_suspend(struct pcmcia_device *link)
{
- com20020_dev_t *info = link->priv;
+ struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
if (link->open)
@@ -302,7 +302,7 @@ static int com20020_suspend(struct pcmcia_device *link)
static int com20020_resume(struct pcmcia_device *link)
{
- com20020_dev_t *info = link->priv;
+ struct com20020_dev *info = link->priv;
struct net_device *dev = info->dev;
if (link->open) {
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0dfeaf5da3f2..ee2c73a9de39 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -20,8 +20,6 @@
*
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
@@ -301,8 +299,8 @@ static u16 __get_link_speed(struct port *port)
}
}
- pr_debug("Port %d Received link speed %d update from adapter\n",
- port->actor_port_number, speed);
+ netdev_dbg(slave->bond->dev, "Port %d Received link speed %d update from adapter\n",
+ port->actor_port_number, speed);
return speed;
}
@@ -329,14 +327,14 @@ static u8 __get_duplex(struct port *port)
switch (slave->duplex) {
case DUPLEX_FULL:
retval = 0x1;
- pr_debug("Port %d Received status full duplex update from adapter\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Port %d Received status full duplex update from adapter\n",
+ port->actor_port_number);
break;
case DUPLEX_HALF:
default:
retval = 0x0;
- pr_debug("Port %d Received status NOT full duplex update from adapter\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Port %d Received status NOT full duplex update from adapter\n",
+ port->actor_port_number);
break;
}
}
@@ -1079,9 +1077,8 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
/* detect loopback situation */
if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
&(port->actor_system))) {
- pr_err("%s: An illegal loopback occurred on adapter (%s)\n"
+ netdev_err(port->slave->bond->dev, "An illegal loopback occurred on adapter (%s)\n"
"Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
- port->slave->bond->dev->name,
port->slave->dev->name);
return;
}
@@ -1269,9 +1266,9 @@ static void ad_port_selection_logic(struct port *port)
port->next_port_in_aggregator = NULL;
port->actor_port_aggregator_identifier = 0;
- pr_debug("Port %d left LAG %d\n",
- port->actor_port_number,
- temp_aggregator->aggregator_identifier);
+ netdev_dbg(bond->dev, "Port %d left LAG %d\n",
+ port->actor_port_number,
+ temp_aggregator->aggregator_identifier);
/* if the aggregator is empty, clear its
* parameters, and set it ready to be attached
*/
@@ -1284,11 +1281,11 @@ static void ad_port_selection_logic(struct port *port)
/* meaning: the port was related to an aggregator
* but was not on the aggregator port list
*/
- pr_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
- port->slave->bond->dev->name,
- port->actor_port_number,
- port->slave->dev->name,
- port->aggregator->aggregator_identifier);
+ net_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
+ port->slave->bond->dev->name,
+ port->actor_port_number,
+ port->slave->dev->name,
+ port->aggregator->aggregator_identifier);
}
}
/* search on all aggregators for a suitable aggregator for this port */
@@ -1318,9 +1315,9 @@ static void ad_port_selection_logic(struct port *port)
port->next_port_in_aggregator = aggregator->lag_ports;
port->aggregator->num_of_ports++;
aggregator->lag_ports = port;
- pr_debug("Port %d joined LAG %d(existing LAG)\n",
- port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ netdev_dbg(bond->dev, "Port %d joined LAG %d(existing LAG)\n",
+ port->actor_port_number,
+ port->aggregator->aggregator_identifier);
/* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
@@ -1363,12 +1360,11 @@ static void ad_port_selection_logic(struct port *port)
/* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
- pr_debug("Port %d joined LAG %d(new LAG)\n",
- port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ netdev_dbg(bond->dev, "Port %d joined LAG %d(new LAG)\n",
+ port->actor_port_number,
+ port->aggregator->aggregator_identifier);
} else {
- pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n",
- port->slave->bond->dev->name,
+ netdev_err(bond->dev, "Port %d (on %s) did not find a suitable aggregator\n",
port->actor_port_number, port->slave->dev->name);
}
}
@@ -1445,9 +1441,9 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
break;
default:
- pr_warn_ratelimited("%s: Impossible agg select mode %d\n",
- curr->slave->bond->dev->name,
- __get_agg_selection_mode(curr->lag_ports));
+ net_warn_ratelimited("%s: Impossible agg select mode %d\n",
+ curr->slave->bond->dev->name,
+ __get_agg_selection_mode(curr->lag_ports));
break;
}
@@ -1539,40 +1535,40 @@ static void ad_agg_selection_logic(struct aggregator *agg)
/* if there is new best aggregator, activate it */
if (best) {
- pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
- best->aggregator_identifier, best->num_of_ports,
- best->actor_oper_aggregator_key,
- best->partner_oper_aggregator_key,
- best->is_individual, best->is_active);
- pr_debug("best ports %p slave %p %s\n",
- best->lag_ports, best->slave,
- best->slave ? best->slave->dev->name : "NULL");
+ netdev_dbg(bond->dev, "best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ best->aggregator_identifier, best->num_of_ports,
+ best->actor_oper_aggregator_key,
+ best->partner_oper_aggregator_key,
+ best->is_individual, best->is_active);
+ netdev_dbg(bond->dev, "best ports %p slave %p %s\n",
+ best->lag_ports, best->slave,
+ best->slave ? best->slave->dev->name : "NULL");
bond_for_each_slave_rcu(bond, slave, iter) {
agg = &(SLAVE_AD_INFO(slave)->aggregator);
- pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
- agg->aggregator_identifier, agg->num_of_ports,
- agg->actor_oper_aggregator_key,
- agg->partner_oper_aggregator_key,
- agg->is_individual, agg->is_active);
+ netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ agg->aggregator_identifier, agg->num_of_ports,
+ agg->actor_oper_aggregator_key,
+ agg->partner_oper_aggregator_key,
+ agg->is_individual, agg->is_active);
}
/* check if any partner replys */
if (best->is_individual) {
- pr_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
- best->slave ?
- best->slave->bond->dev->name : "NULL");
+ net_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
+ best->slave ?
+ best->slave->bond->dev->name : "NULL");
}
best->is_active = 1;
- pr_debug("LAG %d chosen as the active LAG\n",
- best->aggregator_identifier);
- pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
- best->aggregator_identifier, best->num_of_ports,
- best->actor_oper_aggregator_key,
- best->partner_oper_aggregator_key,
- best->is_individual, best->is_active);
+ netdev_dbg(bond->dev, "LAG %d chosen as the active LAG\n",
+ best->aggregator_identifier);
+ netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ best->aggregator_identifier, best->num_of_ports,
+ best->actor_oper_aggregator_key,
+ best->partner_oper_aggregator_key,
+ best->is_individual, best->is_active);
/* disable the ports that were related to the former
* active_aggregator
@@ -1908,13 +1904,13 @@ void bond_3ad_unbind_slave(struct slave *slave)
/* if slave is null, the whole port is not initialized */
if (!port->slave) {
- pr_warn("Warning: %s: Trying to unbind an uninitialized port on %s\n",
- slave->bond->dev->name, slave->dev->name);
+ netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n",
+ slave->dev->name);
return;
}
- pr_debug("Unbinding Link Aggregation Group %d\n",
- aggregator->aggregator_identifier);
+ netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n",
+ aggregator->aggregator_identifier);
/* Tell the partner that this port is not suitable for aggregation */
port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -1949,14 +1945,13 @@ void bond_3ad_unbind_slave(struct slave *slave)
* new aggregator
*/
if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
- pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n",
- aggregator->aggregator_identifier,
- new_aggregator->aggregator_identifier);
+ netdev_dbg(bond->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n",
+ aggregator->aggregator_identifier,
+ new_aggregator->aggregator_identifier);
if ((new_aggregator->lag_ports == port) &&
new_aggregator->is_active) {
- pr_info("%s: Removing an active aggregator\n",
- aggregator->slave->bond->dev->name);
+ netdev_info(bond->dev, "Removing an active aggregator\n");
select_new_active_agg = 1;
}
@@ -1986,8 +1981,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
if (select_new_active_agg)
ad_agg_selection_logic(__get_first_agg(port));
} else {
- pr_warn("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
- slave->bond->dev->name);
+ netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
}
} else {
/* in case that the only port related to this
@@ -1996,8 +1990,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
select_new_active_agg = aggregator->is_active;
ad_clear_agg(aggregator);
if (select_new_active_agg) {
- pr_info("%s: Removing an active aggregator\n",
- slave->bond->dev->name);
+ netdev_info(bond->dev, "Removing an active aggregator\n");
/* select new active aggregator */
temp_aggregator = __get_first_agg(port);
if (temp_aggregator)
@@ -2006,7 +1999,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
}
}
- pr_debug("Unbinding port %d\n", port->actor_port_number);
+ netdev_dbg(bond->dev, "Unbinding port %d\n", port->actor_port_number);
/* find the aggregator that this port is connected to */
bond_for_each_slave(bond, slave_iter, iter) {
@@ -2029,8 +2022,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
select_new_active_agg = temp_aggregator->is_active;
ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
- pr_info("%s: Removing an active aggregator\n",
- slave->bond->dev->name);
+ netdev_info(bond->dev, "Removing an active aggregator\n");
/* select new active aggregator */
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2081,8 +2073,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
/* select the active aggregator for the bond */
if (port) {
if (!port->slave) {
- pr_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n",
- bond->dev->name);
+ net_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n",
+ bond->dev->name);
goto re_arm;
}
@@ -2096,7 +2088,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
bond_for_each_slave_rcu(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave)->port);
if (!port->slave) {
- pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
+ net_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
bond->dev->name);
goto re_arm;
}
@@ -2158,16 +2150,16 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
port = &(SLAVE_AD_INFO(slave)->port);
if (!port->slave) {
- pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
- slave->dev->name, slave->bond->dev->name);
+ net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
+ slave->dev->name, slave->bond->dev->name);
return ret;
}
switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
ret = RX_HANDLER_CONSUMED;
- pr_debug("Received LACPDU on port %d\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n",
+ port->actor_port_number);
/* Protect against concurrent state machines */
__get_state_machine_lock(port);
ad_rx_machine(lacpdu, port);
@@ -2182,20 +2174,20 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
switch (((struct bond_marker *)lacpdu)->tlv_type) {
case AD_MARKER_INFORMATION_SUBTYPE:
- pr_debug("Received Marker Information on port %d\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
+ port->actor_port_number);
ad_marker_info_received((struct bond_marker *)lacpdu, port);
break;
case AD_MARKER_RESPONSE_SUBTYPE:
- pr_debug("Received Marker Response on port %d\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
+ port->actor_port_number);
ad_marker_response_received((struct bond_marker *)lacpdu, port);
break;
default:
- pr_debug("Received an unknown Marker subtype on slot %d\n",
- port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
+ port->actor_port_number);
}
}
}
@@ -2216,8 +2208,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
/* if slave is null, the whole port is not initialized */
if (!port->slave) {
- pr_warn("Warning: %s: speed changed for uninitialized port on %s\n",
- slave->bond->dev->name, slave->dev->name);
+ netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n",
+ slave->dev->name);
return;
}
@@ -2226,7 +2218,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
(__get_link_speed(port) << 1);
- pr_debug("Port %d changed speed\n", port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
/* there is no need to reselect a new aggregator, just signal the
* state machines to reinitialize
*/
@@ -2249,8 +2241,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
/* if slave is null, the whole port is not initialized */
if (!port->slave) {
- pr_warn("%s: Warning: duplex changed for uninitialized port on %s\n",
- slave->bond->dev->name, slave->dev->name);
+ netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n",
+ slave->dev->name);
return;
}
@@ -2259,7 +2251,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
__get_duplex(port);
- pr_debug("Port %d changed duplex\n", port->actor_port_number);
+ netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number);
/* there is no need to reselect a new aggregator, just signal the
* state machines to reinitialize
*/
@@ -2283,8 +2275,8 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
/* if slave is null, the whole port is not initialized */
if (!port->slave) {
- pr_warn("Warning: %s: link status changed for uninitialized port on %s\n",
- slave->bond->dev->name, slave->dev->name);
+ netdev_warn(slave->bond->dev, "link status changed for uninitialized port on %s\n",
+ slave->dev->name);
return;
}
@@ -2311,9 +2303,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port->actor_oper_port_key = (port->actor_admin_port_key &=
~AD_SPEED_KEY_BITS);
}
- pr_debug("Port %d changed link status to %s\n",
- port->actor_port_number,
- link == BOND_LINK_UP ? "UP" : "DOWN");
+ netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
+ port->actor_port_number,
+ link == BOND_LINK_UP ? "UP" : "DOWN");
/* there is no need to reselect a new aggregator, just signal the
* state machines to reinitialize
*/
@@ -2427,8 +2419,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
int agg_id;
if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
- pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
- dev->name);
+ netdev_dbg(dev, "__bond_3ad_get_active_agg_info failed\n");
goto err_free;
}
@@ -2436,7 +2427,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
agg_id = ad_info.aggregator_id;
if (slaves_in_agg == 0) {
- pr_debug("%s: Error: active aggregator is empty\n", dev->name);
+ netdev_dbg(dev, "active aggregator is empty\n");
goto err_free;
}
@@ -2462,8 +2453,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
}
if (slave_agg_no >= 0) {
- pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
- dev->name, agg_id);
+ netdev_err(dev, "Couldn't find a slave to tx on for aggregator ID %d\n",
+ agg_id);
goto err_free;
}
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 76c0dade233f..95dd1f58c260 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -19,8 +19,6 @@
*
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -202,6 +200,7 @@ static int tlb_initialize(struct bonding *bond)
static void tlb_deinitialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct tlb_up_slave *arr;
_lock_tx_hashtbl_bh(bond);
@@ -209,6 +208,10 @@ static void tlb_deinitialize(struct bonding *bond)
bond_info->tx_hashtbl = NULL;
_unlock_tx_hashtbl_bh(bond);
+
+ arr = rtnl_dereference(bond_info->slave_arr);
+ if (arr)
+ kfree_rcu(arr, rcu);
}
static long long compute_gap(struct slave *slave)
@@ -369,7 +372,7 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
if (arp->op_code == htons(ARPOP_REPLY)) {
/* update rx hash table for this ARP */
rlb_update_entry_from_arp(bond, arp);
- pr_debug("Server received an ARP Reply from client\n");
+ netdev_dbg(bond->dev, "Server received an ARP Reply from client\n");
}
out:
return RX_HANDLER_ANOTHER;
@@ -448,11 +451,13 @@ static struct slave *__rlb_next_rx_slave(struct bonding *bond)
*/
static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
{
- if (!bond->curr_active_slave)
+ struct slave *curr_active = bond_deref_active_protected(bond);
+
+ if (!curr_active)
return;
if (!bond->alb_info.primary_is_promisc) {
- if (!dev_set_promiscuity(bond->curr_active_slave->dev, 1))
+ if (!dev_set_promiscuity(curr_active->dev, 1))
bond->alb_info.primary_is_promisc = 1;
else
bond->alb_info.primary_is_promisc = 0;
@@ -460,7 +465,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
bond->alb_info.rlb_promisc_timeout_counter = 0;
- alb_send_learning_packets(bond->curr_active_slave, addr, true);
+ alb_send_learning_packets(curr_active, addr, true);
}
/* slave being removed should not be active at this point
@@ -509,7 +514,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
write_lock_bh(&bond->curr_slave_lock);
- if (slave != bond->curr_active_slave)
+ if (slave != bond_deref_active_protected(bond))
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
write_unlock_bh(&bond->curr_slave_lock);
@@ -533,8 +538,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
client_info->slave->dev->dev_addr,
client_info->mac_dst);
if (!skb) {
- pr_err("%s: Error: failed to create an ARP packet\n",
- client_info->slave->bond->dev->name);
+ netdev_err(client_info->slave->bond->dev,
+ "failed to create an ARP packet\n");
continue;
}
@@ -543,8 +548,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
if (client_info->vlan_id) {
skb = vlan_put_tag(skb, htons(ETH_P_8021Q), client_info->vlan_id);
if (!skb) {
- pr_err("%s: Error: failed to insert VLAN tag\n",
- client_info->slave->bond->dev->name);
+ netdev_err(client_info->slave->bond->dev,
+ "failed to insert VLAN tag\n");
continue;
}
}
@@ -628,8 +633,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (!client_info->slave) {
- pr_err("%s: Error: found a client with no channel in the client's hash table\n",
- bond->dev->name);
+ netdev_err(bond->dev, "found a client with no channel in the client's hash table\n");
continue;
}
/*update all clients using this src_ip, that are not assigned
@@ -684,7 +688,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
* move the old client to primary (curr_active_slave) so
* that the new client can be assigned to this entry.
*/
- if (bond->curr_active_slave &&
+ if (curr_active_slave &&
client_info->slave != curr_active_slave) {
client_info->slave = curr_active_slave;
rlb_update_client(client_info);
@@ -765,7 +769,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
tx_slave = rlb_choose_channel(skb, bond);
if (tx_slave)
ether_addr_copy(arp->mac_src, tx_slave->dev->dev_addr);
- pr_debug("Server sent ARP Reply packet\n");
+ netdev_dbg(bond->dev, "Server sent ARP Reply packet\n");
} else if (arp->op_code == htons(ARPOP_REQUEST)) {
/* Create an entry in the rx_hashtbl for this client as a
* place holder.
@@ -785,7 +789,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
* updated with their assigned mac.
*/
rlb_req_update_subnet_clients(bond, arp->ip_src);
- pr_debug("Server sent ARP Request packet\n");
+ netdev_dbg(bond->dev, "Server sent ARP Request packet\n");
}
return tx_slave;
@@ -1024,8 +1028,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
if (vid) {
skb = vlan_put_tag(skb, vlan_proto, vid);
if (!skb) {
- pr_err("%s: Error: failed to insert VLAN tag\n",
- slave->bond->dev->name);
+ netdev_err(slave->bond->dev, "failed to insert VLAN tag\n");
return;
}
}
@@ -1039,7 +1042,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
struct bonding *bond = bond_get_bond_by_slave(slave);
struct net_device *upper;
struct list_head *iter;
- struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
+ struct bond_vlan_tag *tags;
/* send untagged */
alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -1067,10 +1070,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
* when strict_match is turned off.
*/
if (netif_is_macvlan(upper) && !strict_match) {
- memset(tags, 0, sizeof(tags));
- bond_verify_device_path(bond->dev, upper, tags);
+ tags = bond_verify_device_path(bond->dev, upper, 0);
+ if (IS_ERR_OR_NULL(tags))
+ BUG();
alb_send_lp_vid(slave, upper->dev_addr,
tags[0].vlan_proto, tags[0].vlan_id);
+ kfree(tags);
}
}
rcu_read_unlock();
@@ -1091,9 +1096,8 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
memcpy(s_addr.sa_data, addr, dev->addr_len);
s_addr.sa_family = dev->type;
if (dev_set_mac_address(dev, &s_addr)) {
- pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n"
- "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
- slave->bond->dev->name, dev->name);
+ netdev_err(slave->bond->dev, "dev_set_mac_address of dev %s failed! ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
+ dev->name);
return -EOPNOTSUPP;
}
return 0;
@@ -1221,7 +1225,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
*/
static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
{
- struct slave *has_bond_addr = bond->curr_active_slave;
+ struct slave *has_bond_addr = rcu_access_pointer(bond->curr_active_slave);
struct slave *tmp_slave1, *free_mac_slave = NULL;
struct list_head *iter;
@@ -1267,13 +1271,12 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
if (free_mac_slave) {
alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
- pr_warn("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
- bond->dev->name, slave->dev->name,
- free_mac_slave->dev->name);
+ netdev_warn(bond->dev, "the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
+ slave->dev->name, free_mac_slave->dev->name);
} else if (has_bond_addr) {
- pr_err("%s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
- bond->dev->name, slave->dev->name);
+ netdev_err(bond->dev, "the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
+ slave->dev->name);
return -EFAULT;
}
@@ -1406,9 +1409,39 @@ out:
return NETDEV_TX_OK;
}
+static int bond_tlb_update_slave_arr(struct bonding *bond,
+ struct slave *skipslave)
+{
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct slave *tx_slave;
+ struct list_head *iter;
+ struct tlb_up_slave *new_arr, *old_arr;
+
+ new_arr = kzalloc(offsetof(struct tlb_up_slave, arr[bond->slave_cnt]),
+ GFP_ATOMIC);
+ if (!new_arr)
+ return -ENOMEM;
+
+ bond_for_each_slave(bond, tx_slave, iter) {
+ if (!bond_slave_can_tx(tx_slave))
+ continue;
+ if (skipslave == tx_slave)
+ continue;
+ new_arr->arr[new_arr->count++] = tx_slave;
+ }
+
+ old_arr = rtnl_dereference(bond_info->slave_arr);
+ rcu_assign_pointer(bond_info->slave_arr, new_arr);
+ if (old_arr)
+ kfree_rcu(old_arr, rcu);
+
+ return 0;
+}
+
int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct ethhdr *eth_data;
struct slave *tx_slave = NULL;
u32 hash_index;
@@ -1429,12 +1462,12 @@ int bond_tlb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
hash_index & 0xFF,
skb->len);
} else {
- struct list_head *iter;
- int idx = hash_index % bond->slave_cnt;
+ struct tlb_up_slave *slaves;
- bond_for_each_slave_rcu(bond, tx_slave, iter)
- if (--idx < 0)
- break;
+ slaves = rcu_dereference(bond_info->slave_arr);
+ if (slaves && slaves->count)
+ tx_slave = slaves->arr[hash_index %
+ slaves->count];
}
break;
}
@@ -1575,7 +1608,7 @@ void bond_alb_monitor(struct work_struct *work)
* use mac of the slave device.
* In RLB mode, we always use strict matches.
*/
- strict_match = (slave != bond->curr_active_slave ||
+ strict_match = (slave != rcu_access_pointer(bond->curr_active_slave) ||
bond_info->rlb_enabled);
alb_send_learning_packets(slave, slave->dev->dev_addr,
strict_match);
@@ -1593,7 +1626,7 @@ void bond_alb_monitor(struct work_struct *work)
bond_for_each_slave_rcu(bond, slave, iter) {
tlb_clear_slave(bond, slave, 1);
- if (slave == bond->curr_active_slave) {
+ if (slave == rcu_access_pointer(bond->curr_active_slave)) {
SLAVE_TLB_INFO(slave).load =
bond_info->unbalanced_load /
BOND_TLB_REBALANCE_INTERVAL;
@@ -1625,7 +1658,8 @@ void bond_alb_monitor(struct work_struct *work)
* because a slave was disabled then
* it can now leave promiscuous mode.
*/
- dev_set_promiscuity(bond->curr_active_slave->dev, -1);
+ dev_set_promiscuity(rtnl_dereference(bond->curr_active_slave)->dev,
+ -1);
bond_info->primary_is_promisc = 0;
rtnl_unlock();
@@ -1698,6 +1732,11 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
bond->alb_info.rx_slave = NULL;
rlb_clear_slave(bond, slave);
}
+
+ if (bond_is_nondyn_tlb(bond))
+ if (bond_tlb_update_slave_arr(bond, slave))
+ pr_err("Failed to build slave-array for TLB mode.\n");
+
}
/* Caller must hold bond lock for read */
@@ -1721,6 +1760,11 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
*/
}
}
+
+ if (bond_is_nondyn_tlb(bond)) {
+ if (bond_tlb_update_slave_arr(bond, NULL))
+ pr_err("Failed to build slave-array for TLB mode.\n");
+ }
}
/**
@@ -1742,17 +1786,21 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
__acquires(&bond->curr_slave_lock)
{
struct slave *swap_slave;
+ struct slave *curr_active;
- if (bond->curr_active_slave == new_slave)
+ curr_active = rcu_dereference_protected(bond->curr_active_slave,
+ !new_slave ||
+ lockdep_is_held(&bond->curr_slave_lock));
+ if (curr_active == new_slave)
return;
- if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
- dev_set_promiscuity(bond->curr_active_slave->dev, -1);
+ if (curr_active && bond->alb_info.primary_is_promisc) {
+ dev_set_promiscuity(curr_active->dev, -1);
bond->alb_info.primary_is_promisc = 0;
bond->alb_info.rlb_promisc_timeout_counter = 0;
}
- swap_slave = bond->curr_active_slave;
+ swap_slave = curr_active;
rcu_assign_pointer(bond->curr_active_slave, new_slave);
if (!new_slave || !bond_has_slaves(bond))
@@ -1818,6 +1866,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
{
struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr;
+ struct slave *curr_active;
struct slave *swap_slave;
int res;
@@ -1834,23 +1883,24 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
* Otherwise we'll need to pass the new address to it and handle
* duplications.
*/
- if (!bond->curr_active_slave)
+ curr_active = rtnl_dereference(bond->curr_active_slave);
+ if (!curr_active)
return 0;
swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr);
if (swap_slave) {
- alb_swap_mac_addr(swap_slave, bond->curr_active_slave);
- alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
+ alb_swap_mac_addr(swap_slave, curr_active);
+ alb_fasten_mac_swap(bond, swap_slave, curr_active);
} else {
- alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
+ alb_set_slave_mac_addr(curr_active, bond_dev->dev_addr);
read_lock(&bond->lock);
- alb_send_learning_packets(bond->curr_active_slave,
+ alb_send_learning_packets(curr_active,
bond_dev->dev_addr, false);
if (bond->alb_info.rlb_enabled) {
/* inform clients mac address has changed */
- rlb_req_update_slave_clients(bond, bond->curr_active_slave);
+ rlb_req_update_slave_clients(bond, curr_active);
}
read_unlock(&bond->lock);
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index 5fc76c01636c..aaeac61d03cf 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -139,12 +139,20 @@ struct tlb_slave_info {
*/
};
+struct tlb_up_slave {
+ unsigned int count;
+ struct rcu_head rcu;
+ struct slave *arr[0];
+};
+
struct alb_bond_info {
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
spinlock_t tx_hashtbl_lock;
u32 unbalanced_load;
int tx_rebalance_counter;
int lp_counter;
+ /* -------- non-dynamic tlb mode only ---------*/
+ struct tlb_up_slave __rcu *slave_arr; /* Up slaves */
/* -------- rlb parameters -------- */
int rlb_enabled;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c
index 658e761c4568..280971b227ea 100644
--- a/drivers/net/bonding/bond_debugfs.c
+++ b/drivers/net/bonding/bond_debugfs.c
@@ -69,8 +69,7 @@ void bond_debug_register(struct bonding *bond)
debugfs_create_dir(bond->dev->name, bonding_debug_root);
if (!bond->debug_dir) {
- pr_warn("%s: Warning: failed to register to debugfs\n",
- bond->dev->name);
+ netdev_warn(bond->dev, "failed to register to debugfs\n");
return;
}
@@ -98,8 +97,7 @@ void bond_debug_reregister(struct bonding *bond)
if (d) {
bond->debug_dir = d;
} else {
- pr_warn("%s: Warning: failed to reregister, so just unregister old one\n",
- bond->dev->name);
+ netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n");
bond_debug_unregister(bond);
}
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 701f86cd5993..f0f5eab0fab1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -31,8 +31,6 @@
*
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -498,11 +496,10 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
int err = 0;
if (bond_uses_primary(bond)) {
- /* write lock already acquired */
- if (bond->curr_active_slave) {
- err = dev_set_promiscuity(bond->curr_active_slave->dev,
- inc);
- }
+ struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
+
+ if (curr_active)
+ err = dev_set_promiscuity(curr_active->dev, inc);
} else {
struct slave *slave;
@@ -524,11 +521,10 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
int err = 0;
if (bond_uses_primary(bond)) {
- /* write lock already acquired */
- if (bond->curr_active_slave) {
- err = dev_set_allmulti(bond->curr_active_slave->dev,
- inc);
- }
+ struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
+
+ if (curr_active)
+ err = dev_set_allmulti(curr_active->dev, inc);
} else {
struct slave *slave;
@@ -629,8 +625,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
static void bond_set_dev_addr(struct net_device *bond_dev,
struct net_device *slave_dev)
{
- pr_debug("bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n",
- bond_dev, slave_dev, slave_dev->addr_len);
+ netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n",
+ bond_dev, slave_dev, slave_dev->addr_len);
memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
bond_dev->addr_assign_type = NET_ADDR_STOLEN;
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev);
@@ -684,8 +680,8 @@ static void bond_do_fail_over_mac(struct bonding *bond,
rv = dev_set_mac_address(new_active->dev, &saddr);
if (rv) {
- pr_err("%s: Error %d setting MAC of slave %s\n",
- bond->dev->name, -rv, new_active->dev->name);
+ netdev_err(bond->dev, "Error %d setting MAC of slave %s\n",
+ -rv, new_active->dev->name);
goto out;
}
@@ -697,14 +693,14 @@ static void bond_do_fail_over_mac(struct bonding *bond,
rv = dev_set_mac_address(old_active->dev, &saddr);
if (rv)
- pr_err("%s: Error %d setting MAC of slave %s\n",
- bond->dev->name, -rv, new_active->dev->name);
+ netdev_err(bond->dev, "Error %d setting MAC of slave %s\n",
+ -rv, new_active->dev->name);
out:
write_lock_bh(&bond->curr_slave_lock);
break;
default:
- pr_err("%s: bond_do_fail_over_mac impossible: bad policy %d\n",
- bond->dev->name, bond->params.fail_over_mac);
+ netdev_err(bond->dev, "bond_do_fail_over_mac impossible: bad policy %d\n",
+ bond->params.fail_over_mac);
break;
}
@@ -713,7 +709,7 @@ out:
static bool bond_should_change_active(struct bonding *bond)
{
struct slave *prim = bond->primary_slave;
- struct slave *curr = bond->curr_active_slave;
+ struct slave *curr = bond_deref_active_protected(bond);
if (!prim || !curr || curr->link != BOND_LINK_UP)
return true;
@@ -765,8 +761,8 @@ static bool bond_should_notify_peers(struct bonding *bond)
slave = rcu_dereference(bond->curr_active_slave);
rcu_read_unlock();
- pr_debug("bond_should_notify_peers: bond %s slave %s\n",
- bond->dev->name, slave ? slave->dev->name : "NULL");
+ netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n",
+ slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_peer_notif ||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
@@ -792,7 +788,11 @@ static bool bond_should_notify_peers(struct bonding *bond)
*/
void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
{
- struct slave *old_active = bond->curr_active_slave;
+ struct slave *old_active;
+
+ old_active = rcu_dereference_protected(bond->curr_active_slave,
+ !new_active ||
+ lockdep_is_held(&bond->curr_slave_lock));
if (old_active == new_active)
return;
@@ -802,9 +802,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (new_active->link == BOND_LINK_BACK) {
if (bond_uses_primary(bond)) {
- pr_info("%s: making interface %s the new active one %d ms earlier\n",
- bond->dev->name, new_active->dev->name,
- (bond->params.updelay - new_active->delay) * bond->params.miimon);
+ netdev_info(bond->dev, "making interface %s the new active one %d ms earlier\n",
+ new_active->dev->name,
+ (bond->params.updelay - new_active->delay) * bond->params.miimon);
}
new_active->delay = 0;
@@ -817,8 +817,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
} else {
if (bond_uses_primary(bond)) {
- pr_info("%s: making interface %s the new active one\n",
- bond->dev->name, new_active->dev->name);
+ netdev_info(bond->dev, "making interface %s the new active one\n",
+ new_active->dev->name);
}
}
}
@@ -900,18 +900,16 @@ void bond_select_active_slave(struct bonding *bond)
int rv;
best_slave = bond_find_best_slave(bond);
- if (best_slave != bond->curr_active_slave) {
+ if (best_slave != bond_deref_active_protected(bond)) {
bond_change_active_slave(bond, best_slave);
rv = bond_set_carrier(bond);
if (!rv)
return;
if (netif_carrier_ok(bond->dev)) {
- pr_info("%s: first active interface up!\n",
- bond->dev->name);
+ netdev_info(bond->dev, "first active interface up!\n");
} else {
- pr_info("%s: now running without any active interface!\n",
- bond->dev->name);
+ netdev_info(bond->dev, "now running without any active interface!\n");
}
}
}
@@ -1001,12 +999,6 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
netdev_features_t mask;
struct slave *slave;
- if (!bond_has_slaves(bond)) {
- /* Disable adding VLANs to empty bond. But why? --mq */
- features |= NETIF_F_VLAN_CHALLENGED;
- return features;
- }
-
mask = features;
features &= ~NETIF_F_ONE_FOR_ALL;
features |= NETIF_F_ALL_FOR_ALL;
@@ -1214,36 +1206,38 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (!bond->params.use_carrier &&
slave_dev->ethtool_ops->get_link == NULL &&
slave_ops->ndo_do_ioctl == NULL) {
- pr_warn("%s: Warning: no link monitoring support for %s\n",
- bond_dev->name, slave_dev->name);
+ netdev_warn(bond_dev, "no link monitoring support for %s\n",
+ slave_dev->name);
}
/* already enslaved */
if (slave_dev->flags & IFF_SLAVE) {
- pr_debug("Error: Device was already enslaved\n");
+ netdev_dbg(bond_dev, "Error: Device was already enslaved\n");
return -EBUSY;
}
if (bond_dev == slave_dev) {
- pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name);
+ netdev_err(bond_dev, "cannot enslave bond to itself.\n");
return -EPERM;
}
/* vlan challenged mutual exclusion */
/* no need to lock since we're protected by rtnl_lock */
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
- pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+ netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n",
+ slave_dev->name);
if (vlan_uses_dev(bond_dev)) {
- pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
- bond_dev->name, slave_dev->name, bond_dev->name);
+ netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
+ slave_dev->name, bond_dev->name);
return -EPERM;
} else {
- pr_warn("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
- bond_dev->name, slave_dev->name,
- slave_dev->name, bond_dev->name);
+ netdev_warn(bond_dev, "enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
+ slave_dev->name, slave_dev->name,
+ bond_dev->name);
}
} else {
- pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+ netdev_dbg(bond_dev, "%s is !NETIF_F_VLAN_CHALLENGED\n",
+ slave_dev->name);
}
/*
@@ -1253,8 +1247,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* enslaving it; the old ifenslave will not.
*/
if ((slave_dev->flags & IFF_UP)) {
- pr_err("%s is up - this may be due to an out of date ifenslave\n",
- slave_dev->name);
+ netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n",
+ slave_dev->name);
res = -EPERM;
goto err_undo_flags;
}
@@ -1268,16 +1262,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
*/
if (!bond_has_slaves(bond)) {
if (bond_dev->type != slave_dev->type) {
- pr_debug("%s: change device type from %d to %d\n",
- bond_dev->name,
- bond_dev->type, slave_dev->type);
+ netdev_dbg(bond_dev, "change device type from %d to %d\n",
+ bond_dev->type, slave_dev->type);
res = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE,
bond_dev);
res = notifier_to_errno(res);
if (res) {
- pr_err("%s: refused to change device type\n",
- bond_dev->name);
+ netdev_err(bond_dev, "refused to change device type\n");
res = -EBUSY;
goto err_undo_flags;
}
@@ -1297,26 +1289,24 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_dev);
}
} else if (bond_dev->type != slave_dev->type) {
- pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
- slave_dev->name, slave_dev->type, bond_dev->type);
+ netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
+ slave_dev->name, slave_dev->type, bond_dev->type);
res = -EINVAL;
goto err_undo_flags;
}
if (slave_ops->ndo_set_mac_address == NULL) {
- if (!bond_has_slaves(bond)) {
- pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n",
- bond_dev->name);
- if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) {
+ netdev_warn(bond_dev, "The slave device specified does not support setting the MAC address\n");
+ if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP &&
+ bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
+ if (!bond_has_slaves(bond)) {
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
- pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n",
- bond_dev->name);
+ netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n");
+ } else {
+ netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n");
+ res = -EOPNOTSUPP;
+ goto err_undo_flags;
}
- } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
- pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n",
- bond_dev->name);
- res = -EOPNOTSUPP;
- goto err_undo_flags;
}
}
@@ -1346,7 +1336,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
new_slave->original_mtu = slave_dev->mtu;
res = dev_set_mtu(slave_dev, bond->dev->mtu);
if (res) {
- pr_debug("Error %d calling dev_set_mtu\n", res);
+ netdev_dbg(bond_dev, "Error %d calling dev_set_mtu\n", res);
goto err_free;
}
@@ -1367,7 +1357,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
addr.sa_family = slave_dev->type;
res = dev_set_mac_address(slave_dev, &addr);
if (res) {
- pr_debug("Error %d calling set_mac_address\n", res);
+ netdev_dbg(bond_dev, "Error %d calling set_mac_address\n", res);
goto err_restore_mtu;
}
}
@@ -1375,7 +1365,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
- pr_debug("Opening slave %s failed\n", slave_dev->name);
+ netdev_dbg(bond_dev, "Opening slave %s failed\n", slave_dev->name);
goto err_restore_mac;
}
@@ -1425,8 +1415,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
res = vlan_vids_add_by_dev(slave_dev, bond_dev);
if (res) {
- pr_err("%s: Error: Couldn't add bond vlan ids to %s\n",
- bond_dev->name, slave_dev->name);
+ netdev_err(bond_dev, "Couldn't add bond vlan ids to %s\n",
+ slave_dev->name);
goto err_close;
}
@@ -1455,12 +1445,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* supported); thus, we don't need to change
* the messages for netif_carrier.
*/
- pr_warn("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
- bond_dev->name, slave_dev->name);
+ netdev_warn(bond_dev, "MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
+ slave_dev->name);
} else if (link_reporting == -1) {
/* unable get link status using mii/ethtool */
- pr_warn("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
- bond_dev->name, slave_dev->name);
+ netdev_warn(bond_dev, "can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
+ slave_dev->name);
}
}
@@ -1485,9 +1475,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (new_slave->link != BOND_LINK_DOWN)
new_slave->last_link_up = jiffies;
- pr_debug("Initial state of slave_dev is BOND_LINK_%s\n",
- new_slave->link == BOND_LINK_DOWN ? "DOWN" :
- (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
+ netdev_dbg(bond_dev, "Initial state of slave_dev is BOND_LINK_%s\n",
+ new_slave->link == BOND_LINK_DOWN ? "DOWN" :
+ (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
if (bond_uses_primary(bond) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */
@@ -1528,7 +1518,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
break;
default:
- pr_debug("This slave is always active in trunk mode\n");
+ netdev_dbg(bond_dev, "This slave is always active in trunk mode\n");
/* always active in trunk mode */
bond_set_active_slave(new_slave);
@@ -1537,7 +1527,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* anyway (it holds no special properties of the bond device),
* so we can change it without calling change_active_interface()
*/
- if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
+ if (!rcu_access_pointer(bond->curr_active_slave) &&
+ new_slave->link == BOND_LINK_UP)
rcu_assign_pointer(bond->curr_active_slave, new_slave);
break;
@@ -1547,8 +1538,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
slave_dev->npinfo = bond->dev->npinfo;
if (slave_dev->npinfo) {
if (slave_enable_netpoll(new_slave)) {
- pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n",
- bond_dev->name);
+ netdev_info(bond_dev, "master_dev is using netpoll, but new slave device does not support netpoll\n");
res = -EBUSY;
goto err_detach;
}
@@ -1558,19 +1548,19 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
new_slave);
if (res) {
- pr_debug("Error %d calling netdev_rx_handler_register\n", res);
+ netdev_dbg(bond_dev, "Error %d calling netdev_rx_handler_register\n", res);
goto err_detach;
}
res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
if (res) {
- pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
+ netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res);
goto err_unregister;
}
res = bond_sysfs_slave_add(new_slave);
if (res) {
- pr_debug("Error %d calling bond_sysfs_slave_add\n", res);
+ netdev_dbg(bond_dev, "Error %d calling bond_sysfs_slave_add\n", res);
goto err_upper_unlink;
}
@@ -1586,10 +1576,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
unblock_netpoll_tx();
}
- pr_info("%s: Enslaving %s as %s interface with %s link\n",
- bond_dev->name, slave_dev->name,
- bond_is_active_slave(new_slave) ? "an active" : "a backup",
- new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
+ netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
+ slave_dev->name,
+ bond_is_active_slave(new_slave) ? "an active" : "a backup",
+ new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
/* enslave is successful */
return 0;
@@ -1608,7 +1598,7 @@ err_detach:
vlan_vids_del_by_dev(slave_dev, bond_dev);
if (bond->primary_slave == new_slave)
bond->primary_slave = NULL;
- if (bond->curr_active_slave == new_slave) {
+ if (rcu_access_pointer(bond->curr_active_slave) == new_slave) {
block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, NULL);
@@ -1674,8 +1664,8 @@ static int __bond_release_one(struct net_device *bond_dev,
/* slave is not a slave or master is not master of this slave */
if (!(slave_dev->flags & IFF_SLAVE) ||
!netdev_has_upper_dev(slave_dev, bond_dev)) {
- pr_err("%s: Error: cannot release %s\n",
- bond_dev->name, slave_dev->name);
+ netdev_err(bond_dev, "cannot release %s\n",
+ slave_dev->name);
return -EINVAL;
}
@@ -1684,8 +1674,8 @@ static int __bond_release_one(struct net_device *bond_dev,
slave = bond_get_slave_by_dev(bond, slave_dev);
if (!slave) {
/* not a slave of this bond */
- pr_info("%s: %s not enslaved\n",
- bond_dev->name, slave_dev->name);
+ netdev_info(bond_dev, "%s not enslaved\n",
+ slave_dev->name);
unblock_netpoll_tx();
return -EINVAL;
}
@@ -1705,23 +1695,21 @@ static int __bond_release_one(struct net_device *bond_dev,
write_unlock_bh(&bond->lock);
- pr_info("%s: Releasing %s interface %s\n",
- bond_dev->name,
- bond_is_active_slave(slave) ? "active" : "backup",
- slave_dev->name);
+ netdev_info(bond_dev, "Releasing %s interface %s\n",
+ bond_is_active_slave(slave) ? "active" : "backup",
+ slave_dev->name);
- oldcurrent = bond->curr_active_slave;
+ oldcurrent = rcu_access_pointer(bond->curr_active_slave);
- bond->current_arp_slave = NULL;
+ RCU_INIT_POINTER(bond->current_arp_slave, NULL);
if (!all && (!bond->params.fail_over_mac ||
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)) {
if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
bond_has_slaves(bond))
- pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
- bond_dev->name, slave_dev->name,
- slave->perm_hwaddr,
- bond_dev->name, slave_dev->name);
+ netdev_warn(bond_dev, "the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
+ slave_dev->name, slave->perm_hwaddr,
+ bond_dev->name, slave_dev->name);
}
if (bond->primary_slave == slave)
@@ -1760,13 +1748,6 @@ static int __bond_release_one(struct net_device *bond_dev,
if (!bond_has_slaves(bond)) {
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
-
- if (vlan_uses_dev(bond_dev)) {
- pr_warn("%s: Warning: clearing HW address of %s while it still has VLANs\n",
- bond_dev->name, bond_dev->name);
- pr_warn("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs\n",
- bond_dev->name);
- }
}
unblock_netpoll_tx();
@@ -1781,8 +1762,8 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_compute_features(bond);
if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
(old_features & NETIF_F_VLAN_CHALLENGED))
- pr_info("%s: last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
- bond_dev->name, slave_dev->name, bond_dev->name);
+ netdev_info(bond_dev, "last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
+ slave_dev->name, bond_dev->name);
/* must do this from outside any spinlocks */
vlan_vids_del_by_dev(slave_dev, bond_dev);
@@ -1849,8 +1830,8 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
ret = bond_release(bond_dev, slave_dev);
if (ret == 0 && !bond_has_slaves(bond)) {
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
- pr_info("%s: Destroying bond %s\n",
- bond_dev->name, bond_dev->name);
+ netdev_info(bond_dev, "Destroying bond %s\n",
+ bond_dev->name);
unregister_netdevice(bond_dev);
}
return ret;
@@ -1891,7 +1872,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
/*-------------------------------- Monitoring -------------------------------*/
-
+/* called with rcu_read_lock() */
static int bond_miimon_inspect(struct bonding *bond)
{
int link_state, commit = 0;
@@ -1899,7 +1880,7 @@ static int bond_miimon_inspect(struct bonding *bond)
struct slave *slave;
bool ignore_updelay;
- ignore_updelay = !bond->curr_active_slave ? true : false;
+ ignore_updelay = !rcu_dereference(bond->curr_active_slave);
bond_for_each_slave_rcu(bond, slave, iter) {
slave->new_link = BOND_LINK_NOCHANGE;
@@ -1914,14 +1895,13 @@ static int bond_miimon_inspect(struct bonding *bond)
slave->link = BOND_LINK_FAIL;
slave->delay = bond->params.downdelay;
if (slave->delay) {
- pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n",
- bond->dev->name,
- (BOND_MODE(bond) ==
- BOND_MODE_ACTIVEBACKUP) ?
- (bond_is_active_slave(slave) ?
- "active " : "backup ") : "",
- slave->dev->name,
- bond->params.downdelay * bond->params.miimon);
+ netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n",
+ (BOND_MODE(bond) ==
+ BOND_MODE_ACTIVEBACKUP) ?
+ (bond_is_active_slave(slave) ?
+ "active " : "backup ") : "",
+ slave->dev->name,
+ bond->params.downdelay * bond->params.miimon);
}
/*FALLTHRU*/
case BOND_LINK_FAIL:
@@ -1931,11 +1911,10 @@ static int bond_miimon_inspect(struct bonding *bond)
*/
slave->link = BOND_LINK_UP;
slave->last_link_up = jiffies;
- pr_info("%s: link status up again after %d ms for interface %s\n",
- bond->dev->name,
- (bond->params.downdelay - slave->delay) *
- bond->params.miimon,
- slave->dev->name);
+ netdev_info(bond->dev, "link status up again after %d ms for interface %s\n",
+ (bond->params.downdelay - slave->delay) *
+ bond->params.miimon,
+ slave->dev->name);
continue;
}
@@ -1956,21 +1935,20 @@ static int bond_miimon_inspect(struct bonding *bond)
slave->delay = bond->params.updelay;
if (slave->delay) {
- pr_info("%s: link status up for interface %s, enabling it in %d ms\n",
- bond->dev->name, slave->dev->name,
- ignore_updelay ? 0 :
- bond->params.updelay *
- bond->params.miimon);
+ netdev_info(bond->dev, "link status up for interface %s, enabling it in %d ms\n",
+ slave->dev->name,
+ ignore_updelay ? 0 :
+ bond->params.updelay *
+ bond->params.miimon);
}
/*FALLTHRU*/
case BOND_LINK_BACK:
if (!link_state) {
slave->link = BOND_LINK_DOWN;
- pr_info("%s: link status down again after %d ms for interface %s\n",
- bond->dev->name,
- (bond->params.updelay - slave->delay) *
- bond->params.miimon,
- slave->dev->name);
+ netdev_info(bond->dev, "link status down again after %d ms for interface %s\n",
+ (bond->params.updelay - slave->delay) *
+ bond->params.miimon,
+ slave->dev->name);
continue;
}
@@ -2018,10 +1996,10 @@ static void bond_miimon_commit(struct bonding *bond)
bond_set_backup_slave(slave);
}
- pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex\n",
- bond->dev->name, slave->dev->name,
- slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
- slave->duplex ? "full" : "half");
+ netdev_info(bond->dev, "link status definitely up for interface %s, %u Mbps %s duplex\n",
+ slave->dev->name,
+ slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
+ slave->duplex ? "full" : "half");
/* notify ad that the link status has changed */
if (BOND_MODE(bond) == BOND_MODE_8023AD)
@@ -2048,8 +2026,8 @@ static void bond_miimon_commit(struct bonding *bond)
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
- pr_info("%s: link status definitely down for interface %s, disabling it\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n",
+ slave->dev->name);
if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_handle_link_change(slave,
@@ -2059,15 +2037,14 @@ static void bond_miimon_commit(struct bonding *bond)
bond_alb_handle_link_change(bond, slave,
BOND_LINK_DOWN);
- if (slave == bond->curr_active_slave)
+ if (slave == rcu_access_pointer(bond->curr_active_slave))
goto do_failover;
continue;
default:
- pr_err("%s: invalid new link %d on slave %s\n",
- bond->dev->name, slave->new_link,
- slave->dev->name);
+ netdev_err(bond->dev, "invalid new link %d on slave %s\n",
+ slave->new_link, slave->dev->name);
slave->new_link = BOND_LINK_NOCHANGE;
continue;
@@ -2168,10 +2145,10 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
struct bond_vlan_tag *tags)
{
struct sk_buff *skb;
- int i;
+ struct bond_vlan_tag *outer_tag = tags;
- pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n",
- arp_op, slave_dev->name, &dest_ip, &src_ip);
+ netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n",
+ arp_op, slave_dev->name, &dest_ip, &src_ip);
skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
NULL, slave_dev->dev_addr, NULL);
@@ -2181,30 +2158,42 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
return;
}
+ if (!tags || tags->vlan_proto == VLAN_N_VID)
+ goto xmit;
+
+ tags++;
+
/* Go through all the tags backwards and add them to the packet */
- for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) {
- if (!tags[i].vlan_id)
+ while (tags->vlan_proto != VLAN_N_VID) {
+ if (!tags->vlan_id) {
+ tags++;
continue;
+ }
- pr_debug("inner tag: proto %X vid %X\n",
- ntohs(tags[i].vlan_proto), tags[i].vlan_id);
- skb = __vlan_put_tag(skb, tags[i].vlan_proto,
- tags[i].vlan_id);
+ netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n",
+ ntohs(outer_tag->vlan_proto), tags->vlan_id);
+ skb = __vlan_put_tag(skb, tags->vlan_proto,
+ tags->vlan_id);
if (!skb) {
net_err_ratelimited("failed to insert inner VLAN tag\n");
return;
}
+
+ tags++;
}
/* Set the outer tag */
- if (tags[0].vlan_id) {
- pr_debug("outer tag: proto %X vid %X\n",
- ntohs(tags[0].vlan_proto), tags[0].vlan_id);
- skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id);
+ if (outer_tag->vlan_id) {
+ netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n",
+ ntohs(outer_tag->vlan_proto), outer_tag->vlan_id);
+ skb = vlan_put_tag(skb, outer_tag->vlan_proto,
+ outer_tag->vlan_id);
if (!skb) {
net_err_ratelimited("failed to insert outer VLAN tag\n");
return;
}
}
+
+xmit:
arp_xmit(skb);
}
@@ -2214,46 +2203,50 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
* When the path is validated, collect any vlan information in the
* path.
*/
-bool bond_verify_device_path(struct net_device *start_dev,
- struct net_device *end_dev,
- struct bond_vlan_tag *tags)
+struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
+ struct net_device *end_dev,
+ int level)
{
+ struct bond_vlan_tag *tags;
struct net_device *upper;
struct list_head *iter;
- int idx;
- if (start_dev == end_dev)
- return true;
+ if (start_dev == end_dev) {
+ tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC);
+ if (!tags)
+ return ERR_PTR(-ENOMEM);
+ tags[level].vlan_proto = VLAN_N_VID;
+ return tags;
+ }
netdev_for_each_upper_dev_rcu(start_dev, upper, iter) {
- if (bond_verify_device_path(upper, end_dev, tags)) {
- if (is_vlan_dev(upper)) {
- idx = vlan_get_encap_level(upper);
- if (idx >= BOND_MAX_VLAN_ENCAP)
- return false;
-
- tags[idx].vlan_proto =
- vlan_dev_vlan_proto(upper);
- tags[idx].vlan_id = vlan_dev_vlan_id(upper);
- }
- return true;
+ tags = bond_verify_device_path(upper, end_dev, level + 1);
+ if (IS_ERR_OR_NULL(tags)) {
+ if (IS_ERR(tags))
+ return tags;
+ continue;
}
+ if (is_vlan_dev(upper)) {
+ tags[level].vlan_proto = vlan_dev_vlan_proto(upper);
+ tags[level].vlan_id = vlan_dev_vlan_id(upper);
+ }
+
+ return tags;
}
- return false;
+ return NULL;
}
static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
{
struct rtable *rt;
- struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
+ struct bond_vlan_tag *tags;
__be32 *targets = bond->params.arp_targets, addr;
int i;
- bool ret;
for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
- pr_debug("basa: target %pI4\n", &targets[i]);
- memset(tags, 0, sizeof(tags));
+ netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]);
+ tags = NULL;
/* Find out through which dev should the packet go */
rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
@@ -2276,16 +2269,15 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
goto found;
rcu_read_lock();
- ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags);
+ tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0);
rcu_read_unlock();
- if (ret)
+ if (!IS_ERR_OR_NULL(tags))
goto found;
/* Not our device - skip */
- pr_debug("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
- bond->dev->name, &targets[i],
- rt->dst.dev ? rt->dst.dev->name : "NULL");
+ netdev_dbg(bond->dev, "no path to arp_ip_target %pI4 via rt.dev %s\n",
+ &targets[i], rt->dst.dev ? rt->dst.dev->name : "NULL");
ip_rt_put(rt);
continue;
@@ -2295,6 +2287,7 @@ found:
ip_rt_put(rt);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
addr, tags);
+ kfree(tags);
}
}
@@ -2303,13 +2296,15 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
int i;
if (!sip || !bond_has_this_ip(bond, tip)) {
- pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip);
+ netdev_dbg(bond->dev, "bva: sip %pI4 tip %pI4 not found\n",
+ &sip, &tip);
return;
}
i = bond_get_targets_ip(bond->params.arp_targets, sip);
if (i == -1) {
- pr_debug("bva: sip %pI4 not found in targets\n", &sip);
+ netdev_dbg(bond->dev, "bva: sip %pI4 not found in targets\n",
+ &sip);
return;
}
slave->last_rx = jiffies;
@@ -2336,8 +2331,8 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
alen = arp_hdr_len(bond->dev);
- pr_debug("bond_arp_rcv: bond %s skb->dev %s\n",
- bond->dev->name, skb->dev->name);
+ netdev_dbg(bond->dev, "bond_arp_rcv: skb->dev %s\n",
+ skb->dev->name);
if (alen > skb_headlen(skb)) {
arp = kmalloc(alen, GFP_ATOMIC);
@@ -2361,10 +2356,10 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
arp_ptr += 4 + bond->dev->addr_len;
memcpy(&tip, arp_ptr, 4);
- pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
- bond->dev->name, slave->dev->name, bond_slave_state(slave),
- bond->params.arp_validate, slave_do_arp_validate(bond, slave),
- &sip, &tip);
+ netdev_dbg(bond->dev, "bond_arp_rcv: %s/%d av %d sv %d sip %pI4 tip %pI4\n",
+ slave->dev->name, bond_slave_state(slave),
+ bond->params.arp_validate, slave_do_arp_validate(bond, slave),
+ &sip, &tip);
curr_active_slave = rcu_dereference(bond->curr_active_slave);
@@ -2429,7 +2424,7 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
rcu_read_lock();
- oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
+ oldcurrent = rcu_dereference(bond->curr_active_slave);
/* see if any of the previous devices are up now (i.e. they have
* xmt and rcv traffic). the curr_active_slave does not come into
* the picture unless it is null. also, slave->last_link_up is not
@@ -2454,14 +2449,12 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
* is closed.
*/
if (!oldcurrent) {
- pr_info("%s: link status definitely up for interface %s\n",
- bond->dev->name,
- slave->dev->name);
+ netdev_info(bond->dev, "link status definitely up for interface %s\n",
+ slave->dev->name);
do_failover = 1;
} else {
- pr_info("%s: interface %s is now up\n",
- bond->dev->name,
- slave->dev->name);
+ netdev_info(bond->dev, "interface %s is now up\n",
+ slave->dev->name);
}
}
} else {
@@ -2480,8 +2473,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
if (slave->link_failure_count < UINT_MAX)
slave->link_failure_count++;
- pr_info("%s: interface %s is now down\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "interface %s is now down\n",
+ slave->dev->name);
if (slave == oldcurrent)
do_failover = 1;
@@ -2577,7 +2570,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
* before being taken out
*/
if (!bond_is_active_slave(slave) &&
- !bond->current_arp_slave &&
+ !rcu_access_pointer(bond->current_arp_slave) &&
!bond_time_in_interval(bond, last_rx, 3)) {
slave->new_link = BOND_LINK_DOWN;
commit++;
@@ -2620,21 +2613,24 @@ static void bond_ab_arp_commit(struct bonding *bond)
case BOND_LINK_UP:
trans_start = dev_trans_start(slave->dev);
- if (bond->curr_active_slave != slave ||
- (!bond->curr_active_slave &&
+ if (rtnl_dereference(bond->curr_active_slave) != slave ||
+ (!rtnl_dereference(bond->curr_active_slave) &&
bond_time_in_interval(bond, trans_start, 1))) {
+ struct slave *current_arp_slave;
+
+ current_arp_slave = rtnl_dereference(bond->current_arp_slave);
slave->link = BOND_LINK_UP;
- if (bond->current_arp_slave) {
+ if (current_arp_slave) {
bond_set_slave_inactive_flags(
- bond->current_arp_slave,
+ current_arp_slave,
BOND_SLAVE_NOTIFY_NOW);
- bond->current_arp_slave = NULL;
+ RCU_INIT_POINTER(bond->current_arp_slave, NULL);
}
- pr_info("%s: link status definitely up for interface %s\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "link status definitely up for interface %s\n",
+ slave->dev->name);
- if (!bond->curr_active_slave ||
+ if (!rtnl_dereference(bond->curr_active_slave) ||
(slave == bond->primary_slave))
goto do_failover;
@@ -2650,20 +2646,19 @@ static void bond_ab_arp_commit(struct bonding *bond)
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
- pr_info("%s: link status definitely down for interface %s, disabling it\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "link status definitely down for interface %s, disabling it\n",
+ slave->dev->name);
- if (slave == bond->curr_active_slave) {
- bond->current_arp_slave = NULL;
+ if (slave == rtnl_dereference(bond->curr_active_slave)) {
+ RCU_INIT_POINTER(bond->current_arp_slave, NULL);
goto do_failover;
}
continue;
default:
- pr_err("%s: impossible: new_link %d on slave %s\n",
- bond->dev->name, slave->new_link,
- slave->dev->name);
+ netdev_err(bond->dev, "impossible: new_link %d on slave %s\n",
+ slave->new_link, slave->dev->name);
continue;
}
@@ -2694,9 +2689,9 @@ static bool bond_ab_arp_probe(struct bonding *bond)
bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
if (curr_arp_slave && curr_active_slave)
- pr_info("PROBE: c_arp %s && cas %s BAD\n",
- curr_arp_slave->dev->name,
- curr_active_slave->dev->name);
+ netdev_info(bond->dev, "PROBE: c_arp %s && cas %s BAD\n",
+ curr_arp_slave->dev->name,
+ curr_active_slave->dev->name);
if (curr_active_slave) {
bond_arp_send_all(bond, curr_active_slave);
@@ -2737,8 +2732,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_LATER);
- pr_info("%s: backup interface %s is now down\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "backup interface %s is now down\n",
+ slave->dev->name);
}
if (slave == curr_arp_slave)
found = true;
@@ -2934,9 +2929,8 @@ static int bond_slave_netdev_event(unsigned long event,
break;
}
- pr_info("%s: Primary slave changed to %s, reselecting active slave\n",
- bond->dev->name,
- bond->primary_slave ? slave_dev->name : "none");
+ netdev_info(bond->dev, "Primary slave changed to %s, reselecting active slave\n",
+ bond->primary_slave ? slave_dev->name : "none");
block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock);
@@ -2971,19 +2965,18 @@ static int bond_netdev_event(struct notifier_block *this,
{
struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
- pr_debug("event_dev: %s, event: %lx\n",
- event_dev ? event_dev->name : "None", event);
+ netdev_dbg(event_dev, "event: %lx\n", event);
if (!(event_dev->priv_flags & IFF_BONDING))
return NOTIFY_DONE;
if (event_dev->flags & IFF_MASTER) {
- pr_debug("IFF_MASTER\n");
+ netdev_dbg(event_dev, "IFF_MASTER\n");
return bond_master_netdev_event(event, event_dev);
}
if (event_dev->flags & IFF_SLAVE) {
- pr_debug("IFF_SLAVE\n");
+ netdev_dbg(event_dev, "IFF_SLAVE\n");
return bond_slave_netdev_event(event, event_dev);
}
@@ -2999,11 +2992,11 @@ static struct notifier_block bond_netdev_notifier = {
/* L2 hash helper */
static inline u32 bond_eth_hash(struct sk_buff *skb)
{
- struct ethhdr *data = (struct ethhdr *)skb->data;
-
- if (skb_headlen(skb) >= offsetof(struct ethhdr, h_proto))
- return data->h_dest[5] ^ data->h_source[5];
+ struct ethhdr *ep, hdr_tmp;
+ ep = skb_header_pointer(skb, 0, sizeof(hdr_tmp), &hdr_tmp);
+ if (ep)
+ return ep->h_dest[5] ^ ep->h_source[5] ^ ep->h_proto;
return 0;
}
@@ -3110,8 +3103,8 @@ static int bond_open(struct net_device *bond_dev)
if (bond_has_slaves(bond)) {
read_lock(&bond->curr_slave_lock);
bond_for_each_slave(bond, slave, iter) {
- if (bond_uses_primary(bond)
- && (slave != bond->curr_active_slave)) {
+ if (bond_uses_primary(bond) &&
+ slave != rcu_access_pointer(bond->curr_active_slave)) {
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
} else {
@@ -3225,7 +3218,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
struct net *net;
int res = 0;
- pr_debug("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd);
+ netdev_dbg(bond_dev, "bond_ioctl: cmd=%d\n", cmd);
switch (cmd) {
case SIOCGMIIPHY:
@@ -3295,12 +3288,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
slave_dev = __dev_get_by_name(net, ifr->ifr_slave);
- pr_debug("slave_dev=%p:\n", slave_dev);
+ netdev_dbg(bond_dev, "slave_dev=%p:\n", slave_dev);
if (!slave_dev)
return -ENODEV;
- pr_debug("slave_dev->name=%s:\n", slave_dev->name);
+ netdev_dbg(bond_dev, "slave_dev->name=%s:\n", slave_dev->name);
switch (cmd) {
case BOND_ENSLAVE_OLD:
case SIOCBONDENSLAVE:
@@ -3427,8 +3420,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
struct list_head *iter;
int res = 0;
- pr_debug("bond=%p, name=%s, new_mtu=%d\n",
- bond, bond_dev ? bond_dev->name : "None", new_mtu);
+ netdev_dbg(bond_dev, "bond=%p, new_mtu=%d\n", bond, new_mtu);
/* Can't hold bond->lock with bh disabled here since
* some base drivers panic. On the other hand we can't
@@ -3446,8 +3438,8 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
*/
bond_for_each_slave(bond, slave, iter) {
- pr_debug("s %p c_m %p\n",
- slave, slave->dev->netdev_ops->ndo_change_mtu);
+ netdev_dbg(bond_dev, "s %p c_m %p\n",
+ slave, slave->dev->netdev_ops->ndo_change_mtu);
res = dev_set_mtu(slave->dev, new_mtu);
@@ -3460,7 +3452,8 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
* means changing their mtu from timer context, which
* is probably not a good idea.
*/
- pr_debug("err %d %s\n", res, slave->dev->name);
+ netdev_dbg(bond_dev, "err %d %s\n", res,
+ slave->dev->name);
goto unwind;
}
}
@@ -3479,8 +3472,8 @@ unwind:
tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu);
if (tmp_res) {
- pr_debug("unwind err %d dev %s\n",
- tmp_res, rollback_slave->dev->name);
+ netdev_dbg(bond_dev, "unwind err %d dev %s\n",
+ tmp_res, rollback_slave->dev->name);
}
}
@@ -3506,8 +3499,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
return bond_alb_set_mac_address(bond_dev, addr);
- pr_debug("bond=%p, name=%s\n",
- bond, bond_dev ? bond_dev->name : "None");
+ netdev_dbg(bond_dev, "bond=%p\n", bond);
/* If fail_over_mac is enabled, do nothing and return success.
* Returning an error causes ifenslave to fail.
@@ -3535,7 +3527,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
*/
bond_for_each_slave(bond, slave, iter) {
- pr_debug("slave %p %s\n", slave, slave->dev->name);
+ netdev_dbg(bond_dev, "slave %p %s\n", slave, slave->dev->name);
res = dev_set_mac_address(slave->dev, addr);
if (res) {
/* TODO: consider downing the slave
@@ -3544,7 +3536,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
* breakage anyway until ARP finish
* updating, so...
*/
- pr_debug("err %d %s\n", res, slave->dev->name);
+ netdev_dbg(bond_dev, "err %d %s\n", res, slave->dev->name);
goto unwind;
}
}
@@ -3566,8 +3558,8 @@ unwind:
tmp_res = dev_set_mac_address(rollback_slave->dev, &tmp_sa);
if (tmp_res) {
- pr_debug("unwind err %d dev %s\n",
- tmp_res, rollback_slave->dev->name);
+ netdev_dbg(bond_dev, "unwind err %d dev %s\n",
+ tmp_res, rollback_slave->dev->name);
}
}
@@ -3814,8 +3806,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
return bond_tlb_xmit(skb, dev);
default:
/* Should never happen, mode already checked */
- pr_err("%s: Error: Unknown bonding mode %d\n",
- dev->name, BOND_MODE(bond));
+ netdev_err(dev, "Unknown bonding mode %d\n", BOND_MODE(bond));
WARN_ON_ONCE(1);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
@@ -3956,13 +3947,6 @@ void bond_setup(struct net_device *bond_dev)
bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT;
bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
- /* At first, we block adding VLANs. That's the only way to
- * prevent problems that occur when adding VLANs over an
- * empty bond. The block will be removed once non-challenged
- * slaves are enslaved.
- */
- bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
-
/* don't acquire bond device's netif_tx_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;
@@ -4002,7 +3986,7 @@ static void bond_uninit(struct net_device *bond_dev)
/* Release the bonded slaves */
bond_for_each_slave(bond, slave, iter)
__bond_release_one(bond_dev, slave->dev, true);
- pr_info("%s: Released all slaves\n", bond_dev->name);
+ netdev_info(bond_dev, "Released all slaves\n");
list_del(&bond->bond_list);
@@ -4391,7 +4375,7 @@ static int bond_init(struct net_device *bond_dev)
struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- pr_debug("Begin bond_init for %s\n", bond_dev->name);
+ netdev_dbg(bond_dev, "Begin bond_init\n");
/*
* Initialize locks that may be required during
@@ -4440,7 +4424,7 @@ int bond_create(struct net *net, const char *name)
rtnl_lock();
bond_dev = alloc_netdev_mq(sizeof(struct bonding),
- name ? name : "bond%d",
+ name ? name : "bond%d", NET_NAME_UNKNOWN,
bond_setup, tx_queues);
if (!bond_dev) {
pr_err("%s: eek! can't alloc netdev!\n", name);
@@ -4481,7 +4465,6 @@ static void __net_exit bond_net_exit(struct net *net)
LIST_HEAD(list);
bond_destroy_sysfs(bn);
- bond_destroy_proc_dir(bn);
/* Kill off any bonds created after unregistering bond rtnl ops */
rtnl_lock();
@@ -4489,6 +4472,8 @@ static void __net_exit bond_net_exit(struct net *net)
unregister_netdevice_queue(bond->dev, &list);
unregister_netdevice_many(&list);
rtnl_unlock();
+
+ bond_destroy_proc_dir(bn);
}
static struct pernet_operations bond_net_ops = {
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 5ab3c1847e67..d163e112f04c 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -9,8 +9,6 @@
* (at your option) any later version.
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
@@ -181,8 +179,7 @@ static int bond_changelink(struct net_device *bond_dev,
int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);
if (arp_interval && miimon) {
- pr_err("%s: ARP monitoring cannot be used with MII monitoring\n",
- bond->dev->name);
+ netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n");
return -EINVAL;
}
@@ -207,8 +204,7 @@ static int bond_changelink(struct net_device *bond_dev,
i++;
}
if (i == 0 && bond->params.arp_interval)
- pr_warn("%s: Removing last arp target with arp_interval on\n",
- bond->dev->name);
+ netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
if (err)
return err;
}
@@ -216,8 +212,7 @@ static int bond_changelink(struct net_device *bond_dev,
int arp_validate = nla_get_u32(data[IFLA_BOND_ARP_VALIDATE]);
if (arp_validate && miimon) {
- pr_err("%s: ARP validating cannot be used with MII monitoring\n",
- bond->dev->name);
+ netdev_err(bond->dev, "ARP validating cannot be used with MII monitoring\n");
return -EINVAL;
}
@@ -398,20 +393,31 @@ static size_t bond_get_size(const struct net_device *bond_dev)
0;
}
+static int bond_option_active_slave_get_ifindex(struct bonding *bond)
+{
+ const struct net_device *slave;
+ int ifindex;
+
+ rcu_read_lock();
+ slave = bond_option_active_slave_get_rcu(bond);
+ ifindex = slave ? slave->ifindex : 0;
+ rcu_read_unlock();
+ return ifindex;
+}
+
static int bond_fill_info(struct sk_buff *skb,
const struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct net_device *slave_dev = bond_option_active_slave_get(bond);
- struct nlattr *targets;
unsigned int packets_per_slave;
- int i, targets_added;
+ int ifindex, i, targets_added;
+ struct nlattr *targets;
if (nla_put_u8(skb, IFLA_BOND_MODE, BOND_MODE(bond)))
goto nla_put_failure;
- if (slave_dev &&
- nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
+ ifindex = bond_option_active_slave_get_ifindex(bond);
+ if (ifindex && nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, ifindex))
goto nla_put_failure;
if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 540e0167bf24..dc73463c2c23 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -9,8 +9,6 @@
* (at your option) any later version.
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <linux/errno.h>
#include <linux/if.h>
#include <linux/netdevice.h>
@@ -544,9 +542,8 @@ static void bond_opt_dep_print(struct bonding *bond,
params = &bond->params;
modeval = bond_opt_get_val(BOND_OPT_MODE, params->mode);
if (test_bit(params->mode, &opt->unsuppmodes))
- pr_err("%s: option %s: mode dependency failed, not supported in mode %s(%llu)\n",
- bond->dev->name, opt->name,
- modeval->string, modeval->value);
+ netdev_err(bond->dev, "option %s: mode dependency failed, not supported in mode %s(%llu)\n",
+ opt->name, modeval->string, modeval->value);
}
static void bond_opt_error_interpret(struct bonding *bond,
@@ -564,31 +561,30 @@ static void bond_opt_error_interpret(struct bonding *bond,
p = strchr(val->string, '\n');
if (p)
*p = '\0';
- pr_err("%s: option %s: invalid value (%s)\n",
- bond->dev->name, opt->name, val->string);
+ netdev_err(bond->dev, "option %s: invalid value (%s)\n",
+ opt->name, val->string);
} else {
- pr_err("%s: option %s: invalid value (%llu)\n",
- bond->dev->name, opt->name, val->value);
+ netdev_err(bond->dev, "option %s: invalid value (%llu)\n",
+ opt->name, val->value);
}
}
minval = bond_opt_get_flags(opt, BOND_VALFLAG_MIN);
maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX);
if (!maxval)
break;
- pr_err("%s: option %s: allowed values %llu - %llu\n",
- bond->dev->name, opt->name, minval ? minval->value : 0,
- maxval->value);
+ netdev_err(bond->dev, "option %s: allowed values %llu - %llu\n",
+ opt->name, minval ? minval->value : 0, maxval->value);
break;
case -EACCES:
bond_opt_dep_print(bond, opt);
break;
case -ENOTEMPTY:
- pr_err("%s: option %s: unable to set because the bond device has slaves\n",
- bond->dev->name, opt->name);
+ netdev_err(bond->dev, "option %s: unable to set because the bond device has slaves\n",
+ opt->name);
break;
case -EBUSY:
- pr_err("%s: option %s: unable to set because the bond device is up\n",
- bond->dev->name, opt->name);
+ netdev_err(bond->dev, "option %s: unable to set because the bond device is up\n",
+ opt->name);
break;
default:
break;
@@ -671,17 +667,18 @@ const struct bond_option *bond_opt_get(unsigned int option)
return &bond_opts[option];
}
-int bond_option_mode_set(struct bonding *bond, const struct bond_opt_value *newval)
+static int bond_option_mode_set(struct bonding *bond,
+ const struct bond_opt_value *newval)
{
if (!bond_mode_uses_arp(newval->value) && bond->params.arp_interval) {
- pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
- bond->dev->name, newval->string);
+ netdev_info(bond->dev, "%s mode is incompatible with arp monitoring, start mii monitoring\n",
+ newval->string);
/* disable arp monitoring */
bond->params.arp_interval = 0;
/* set miimon to default value */
bond->params.miimon = BOND_DEFAULT_MIIMON;
- pr_info("%s: Setting MII monitoring interval to %d\n",
- bond->dev->name, bond->params.miimon);
+ netdev_info(bond->dev, "Setting MII monitoring interval to %d\n",
+ bond->params.miimon);
}
/* don't cache arp_validate between modes */
@@ -704,11 +701,6 @@ struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond)
return __bond_option_active_slave_get(bond, slave);
}
-struct net_device *bond_option_active_slave_get(struct bonding *bond)
-{
- return __bond_option_active_slave_get(bond, bond->curr_active_slave);
-}
-
static int bond_option_active_slave_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
@@ -727,14 +719,14 @@ static int bond_option_active_slave_set(struct bonding *bond,
if (slave_dev) {
if (!netif_is_bond_slave(slave_dev)) {
- pr_err("Device %s is not bonding slave\n",
- slave_dev->name);
+ netdev_err(bond->dev, "Device %s is not bonding slave\n",
+ slave_dev->name);
return -EINVAL;
}
if (bond->dev != netdev_master_upper_dev_get(slave_dev)) {
- pr_err("%s: Device %s is not our slave\n",
- bond->dev->name, slave_dev->name);
+ netdev_err(bond->dev, "Device %s is not our slave\n",
+ slave_dev->name);
return -EINVAL;
}
}
@@ -744,29 +736,29 @@ static int bond_option_active_slave_set(struct bonding *bond,
/* check to see if we are clearing active */
if (!slave_dev) {
- pr_info("%s: Clearing current active slave\n", bond->dev->name);
+ netdev_info(bond->dev, "Clearing current active slave\n");
RCU_INIT_POINTER(bond->curr_active_slave, NULL);
bond_select_active_slave(bond);
} else {
- struct slave *old_active = bond->curr_active_slave;
+ struct slave *old_active = bond_deref_active_protected(bond);
struct slave *new_active = bond_slave_get_rtnl(slave_dev);
BUG_ON(!new_active);
if (new_active == old_active) {
/* do nothing */
- pr_info("%s: %s is already the current active slave\n",
- bond->dev->name, new_active->dev->name);
+ netdev_info(bond->dev, "%s is already the current active slave\n",
+ new_active->dev->name);
} else {
if (old_active && (new_active->link == BOND_LINK_UP) &&
bond_slave_is_up(new_active)) {
- pr_info("%s: Setting %s as active slave\n",
- bond->dev->name, new_active->dev->name);
+ netdev_info(bond->dev, "Setting %s as active slave\n",
+ new_active->dev->name);
bond_change_active_slave(bond, new_active);
} else {
- pr_err("%s: Could not set %s as active slave; either %s is down or the link is down\n",
- bond->dev->name, new_active->dev->name,
- new_active->dev->name);
+ netdev_err(bond->dev, "Could not set %s as active slave; either %s is down or the link is down\n",
+ new_active->dev->name,
+ new_active->dev->name);
ret = -EINVAL;
}
}
@@ -785,20 +777,17 @@ static int bond_option_active_slave_set(struct bonding *bond,
static int bond_option_miimon_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting MII monitoring interval to %llu\n",
- bond->dev->name, newval->value);
+ netdev_info(bond->dev, "Setting MII monitoring interval to %llu\n",
+ newval->value);
bond->params.miimon = newval->value;
if (bond->params.updelay)
- pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
- bond->dev->name,
+ netdev_info(bond->dev, "Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
bond->params.updelay * bond->params.miimon);
if (bond->params.downdelay)
- pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
- bond->dev->name,
- bond->params.downdelay * bond->params.miimon);
+ netdev_info(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
+ bond->params.downdelay * bond->params.miimon);
if (newval->value && bond->params.arp_interval) {
- pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n",
- bond->dev->name);
+ netdev_info(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n");
bond->params.arp_interval = 0;
if (bond->params.arp_validate)
bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
@@ -830,20 +819,18 @@ static int bond_option_updelay_set(struct bonding *bond,
int value = newval->value;
if (!bond->params.miimon) {
- pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
- bond->dev->name);
+ netdev_err(bond->dev, "Unable to set up delay as MII monitoring is disabled\n");
return -EPERM;
}
if ((value % bond->params.miimon) != 0) {
- pr_warn("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
- bond->dev->name, value,
- bond->params.miimon,
- (value / bond->params.miimon) *
- bond->params.miimon);
+ netdev_warn(bond->dev, "up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
+ value, bond->params.miimon,
+ (value / bond->params.miimon) *
+ bond->params.miimon);
}
bond->params.updelay = value / bond->params.miimon;
- pr_info("%s: Setting up delay to %d\n",
- bond->dev->name, bond->params.updelay * bond->params.miimon);
+ netdev_info(bond->dev, "Setting up delay to %d\n",
+ bond->params.updelay * bond->params.miimon);
return 0;
}
@@ -854,20 +841,18 @@ static int bond_option_downdelay_set(struct bonding *bond,
int value = newval->value;
if (!bond->params.miimon) {
- pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
- bond->dev->name);
+ netdev_err(bond->dev, "Unable to set down delay as MII monitoring is disabled\n");
return -EPERM;
}
if ((value % bond->params.miimon) != 0) {
- pr_warn("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
- bond->dev->name, value,
- bond->params.miimon,
- (value / bond->params.miimon) *
- bond->params.miimon);
+ netdev_warn(bond->dev, "down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
+ value, bond->params.miimon,
+ (value / bond->params.miimon) *
+ bond->params.miimon);
}
bond->params.downdelay = value / bond->params.miimon;
- pr_info("%s: Setting down delay to %d\n",
- bond->dev->name, bond->params.downdelay * bond->params.miimon);
+ netdev_info(bond->dev, "Setting down delay to %d\n",
+ bond->params.downdelay * bond->params.miimon);
return 0;
}
@@ -875,8 +860,8 @@ static int bond_option_downdelay_set(struct bonding *bond,
static int bond_option_use_carrier_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting use_carrier to %llu\n",
- bond->dev->name, newval->value);
+ netdev_info(bond->dev, "Setting use_carrier to %llu\n",
+ newval->value);
bond->params.use_carrier = newval->value;
return 0;
@@ -889,18 +874,16 @@ static int bond_option_use_carrier_set(struct bonding *bond,
static int bond_option_arp_interval_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting ARP monitoring interval to %llu\n",
- bond->dev->name, newval->value);
+ netdev_info(bond->dev, "Setting ARP monitoring interval to %llu\n",
+ newval->value);
bond->params.arp_interval = newval->value;
if (newval->value) {
if (bond->params.miimon) {
- pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n",
- bond->dev->name, bond->dev->name);
+ netdev_info(bond->dev, "ARP monitoring cannot be used with MII monitoring. Disabling MII monitoring\n");
bond->params.miimon = 0;
}
if (!bond->params.arp_targets[0])
- pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n",
- bond->dev->name);
+ netdev_info(bond->dev, "ARP monitoring has been set up, but no ARP targets have been specified\n");
}
if (bond->dev->flags & IFF_UP) {
/* If the interface is up, we may need to fire off
@@ -944,24 +927,24 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
int ind;
if (!bond_is_ip_target_ok(target)) {
- pr_err("%s: invalid ARP target %pI4 specified for addition\n",
- bond->dev->name, &target);
+ netdev_err(bond->dev, "invalid ARP target %pI4 specified for addition\n",
+ &target);
return -EINVAL;
}
if (bond_get_targets_ip(targets, target) != -1) { /* dup */
- pr_err("%s: ARP target %pI4 is already present\n",
- bond->dev->name, &target);
+ netdev_err(bond->dev, "ARP target %pI4 is already present\n",
+ &target);
return -EINVAL;
}
ind = bond_get_targets_ip(targets, 0); /* first free slot */
if (ind == -1) {
- pr_err("%s: ARP target table is full!\n", bond->dev->name);
+ netdev_err(bond->dev, "ARP target table is full!\n");
return -EINVAL;
}
- pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target);
+ netdev_info(bond->dev, "Adding ARP target %pI4\n", &target);
_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
@@ -989,23 +972,22 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
int ind, i;
if (!bond_is_ip_target_ok(target)) {
- pr_err("%s: invalid ARP target %pI4 specified for removal\n",
- bond->dev->name, &target);
+ netdev_err(bond->dev, "invalid ARP target %pI4 specified for removal\n",
+ &target);
return -EINVAL;
}
ind = bond_get_targets_ip(targets, target);
if (ind == -1) {
- pr_err("%s: unable to remove nonexistent ARP target %pI4\n",
- bond->dev->name, &target);
+ netdev_err(bond->dev, "unable to remove nonexistent ARP target %pI4\n",
+ &target);
return -EINVAL;
}
if (ind == 0 && !targets[1] && bond->params.arp_interval)
- pr_warn("%s: Removing last arp target with arp_interval on\n",
- bond->dev->name);
+ netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
- pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);
+ netdev_info(bond->dev, "Removing ARP target %pI4\n", &target);
/* not to race with bond_arp_rcv */
write_lock_bh(&bond->lock);
@@ -1044,8 +1026,8 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
if (newval->string) {
if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
- pr_err("%s: invalid ARP target %pI4 specified\n",
- bond->dev->name, &target);
+ netdev_err(bond->dev, "invalid ARP target %pI4 specified\n",
+ &target);
return ret;
}
if (newval->string[0] == '+')
@@ -1053,8 +1035,7 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
else if (newval->string[0] == '-')
ret = bond_option_arp_ip_target_rem(bond, target);
else
- pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n",
- bond->dev->name);
+ netdev_err(bond->dev, "no command found in arp_ip_targets file - use +<addr> or -<addr>\n");
} else {
target = newval->value;
ret = bond_option_arp_ip_target_add(bond, target);
@@ -1066,8 +1047,8 @@ static int bond_option_arp_ip_targets_set(struct bonding *bond,
static int bond_option_arp_validate_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting arp_validate to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting arp_validate to %s (%llu)\n",
+ newval->string, newval->value);
if (bond->dev->flags & IFF_UP) {
if (!newval->value)
@@ -1083,8 +1064,8 @@ static int bond_option_arp_validate_set(struct bonding *bond,
static int bond_option_arp_all_targets_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting arp_all_targets to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting arp_all_targets to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.arp_all_targets = newval->value;
return 0;
@@ -1106,7 +1087,7 @@ static int bond_option_primary_set(struct bonding *bond,
*p = '\0';
/* check to see if we are clearing primary */
if (!strlen(primary)) {
- pr_info("%s: Setting primary slave to None\n", bond->dev->name);
+ netdev_info(bond->dev, "Setting primary slave to None\n");
bond->primary_slave = NULL;
memset(bond->params.primary, 0, sizeof(bond->params.primary));
bond_select_active_slave(bond);
@@ -1115,8 +1096,8 @@ static int bond_option_primary_set(struct bonding *bond,
bond_for_each_slave(bond, slave, iter) {
if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) {
- pr_info("%s: Setting %s as primary slave\n",
- bond->dev->name, slave->dev->name);
+ netdev_info(bond->dev, "Setting %s as primary slave\n",
+ slave->dev->name);
bond->primary_slave = slave;
strcpy(bond->params.primary, slave->dev->name);
bond_select_active_slave(bond);
@@ -1125,15 +1106,15 @@ static int bond_option_primary_set(struct bonding *bond,
}
if (bond->primary_slave) {
- pr_info("%s: Setting primary slave to None\n", bond->dev->name);
+ netdev_info(bond->dev, "Setting primary slave to None\n");
bond->primary_slave = NULL;
bond_select_active_slave(bond);
}
strncpy(bond->params.primary, primary, IFNAMSIZ);
bond->params.primary[IFNAMSIZ - 1] = 0;
- pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n",
- bond->dev->name, primary, bond->dev->name);
+ netdev_info(bond->dev, "Recording %s as primary, but it has not been enslaved to %s yet\n",
+ primary, bond->dev->name);
out:
write_unlock_bh(&bond->curr_slave_lock);
@@ -1146,8 +1127,8 @@ out:
static int bond_option_primary_reselect_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting primary_reselect to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting primary_reselect to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.primary_reselect = newval->value;
block_netpoll_tx();
@@ -1162,8 +1143,8 @@ static int bond_option_primary_reselect_set(struct bonding *bond,
static int bond_option_fail_over_mac_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting fail_over_mac to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting fail_over_mac to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.fail_over_mac = newval->value;
return 0;
@@ -1172,8 +1153,8 @@ static int bond_option_fail_over_mac_set(struct bonding *bond,
static int bond_option_xmit_hash_policy_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting xmit hash policy to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting xmit hash policy to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.xmit_policy = newval->value;
return 0;
@@ -1182,8 +1163,8 @@ static int bond_option_xmit_hash_policy_set(struct bonding *bond,
static int bond_option_resend_igmp_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting resend_igmp to %llu\n",
- bond->dev->name, newval->value);
+ netdev_info(bond->dev, "Setting resend_igmp to %llu\n",
+ newval->value);
bond->params.resend_igmp = newval->value;
return 0;
@@ -1221,8 +1202,8 @@ static int bond_option_all_slaves_active_set(struct bonding *bond,
static int bond_option_min_links_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting min links value to %llu\n",
- bond->dev->name, newval->value);
+ netdev_info(bond->dev, "Setting min links value to %llu\n",
+ newval->value);
bond->params.min_links = newval->value;
return 0;
@@ -1257,8 +1238,8 @@ static int bond_option_pps_set(struct bonding *bond,
static int bond_option_lacp_rate_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting LACP rate to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting LACP rate to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.lacp_fast = newval->value;
bond_3ad_update_lacp_rate(bond);
@@ -1268,8 +1249,8 @@ static int bond_option_lacp_rate_set(struct bonding *bond,
static int bond_option_ad_select_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting ad_select to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting ad_select to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.ad_select = newval->value;
return 0;
@@ -1330,7 +1311,7 @@ out:
return ret;
err_no_cmd:
- pr_info("invalid input for queue_id set for %s\n", bond->dev->name);
+ netdev_info(bond->dev, "invalid input for queue_id set\n");
ret = -EPERM;
goto out;
@@ -1352,20 +1333,20 @@ static int bond_option_slaves_set(struct bonding *bond,
dev = __dev_get_by_name(dev_net(bond->dev), ifname);
if (!dev) {
- pr_info("%s: interface %s does not exist!\n",
- bond->dev->name, ifname);
+ netdev_info(bond->dev, "interface %s does not exist!\n",
+ ifname);
ret = -ENODEV;
goto out;
}
switch (command[0]) {
case '+':
- pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name);
+ netdev_info(bond->dev, "Adding slave %s\n", dev->name);
ret = bond_enslave(bond->dev, dev);
break;
case '-':
- pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name);
+ netdev_info(bond->dev, "Removing slave %s\n", dev->name);
ret = bond_release(bond->dev, dev);
break;
@@ -1377,8 +1358,7 @@ out:
return ret;
err_no_cmd:
- pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n",
- bond->dev->name);
+ netdev_err(bond->dev, "no command found in slaves file - use +ifname or -ifname\n");
ret = -EPERM;
goto out;
}
@@ -1386,8 +1366,8 @@ err_no_cmd:
static int bond_option_tlb_dynamic_lb_set(struct bonding *bond,
const struct bond_opt_value *newval)
{
- pr_info("%s: Setting dynamic-lb to %s (%llu)\n",
- bond->dev->name, newval->string, newval->value);
+ netdev_info(bond->dev, "Setting dynamic-lb to %s (%llu)\n",
+ newval->string, newval->value);
bond->params.tlb_dynamic_lb = newval->value;
return 0;
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index b215b479bb3a..de62c0385dfb 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -252,8 +252,8 @@ void bond_create_proc_entry(struct bonding *bond)
S_IRUGO, bn->proc_dir,
&bond_info_fops, bond);
if (bond->proc_entry == NULL)
- pr_warn("Warning: Cannot create /proc/net/%s/%s\n",
- DRV_NAME, bond_dev->name);
+ netdev_warn(bond_dev, "Cannot create /proc/net/%s/%s\n",
+ DRV_NAME, bond_dev->name);
else
memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index daed52f68ce1..98db8edd9c75 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -492,8 +492,9 @@ static ssize_t bonding_show_mii_status(struct device *d,
char *buf)
{
struct bonding *bond = to_bond(d);
+ bool active = !!rcu_access_pointer(bond->curr_active_slave);
- return sprintf(buf, "%s\n", bond->curr_active_slave ? "up" : "down");
+ return sprintf(buf, "%s\n", active ? "up" : "down");
}
static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c
index 198677f58ce0..5cd532ca1cfe 100644
--- a/drivers/net/bonding/bond_sysfs_slave.c
+++ b/drivers/net/bonding/bond_sysfs_slave.c
@@ -125,7 +125,7 @@ int bond_sysfs_slave_add(struct slave *slave)
for (a = slave_attrs; *a; ++a) {
err = sysfs_create_file(&slave->kobj, &((*a)->attr));
if (err) {
- kobject_del(&slave->kobj);
+ kobject_put(&slave->kobj);
return err;
}
}
@@ -140,5 +140,5 @@ void bond_sysfs_slave_del(struct slave *slave)
for (a = slave_attrs; *a; ++a)
sysfs_remove_file(&slave->kobj, &((*a)->attr));
- kobject_del(&slave->kobj);
+ kobject_put(&slave->kobj);
}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 0b4d9cde0b05..aace510d08d1 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -36,7 +36,6 @@
#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
-#define BOND_MAX_VLAN_ENCAP 2
#define BOND_MAX_ARP_TARGETS 16
#define BOND_DEFAULT_MIIMON 100
@@ -194,8 +193,8 @@ struct slave {
*/
struct bonding {
struct net_device *dev; /* first - useful for panic debug */
- struct slave *curr_active_slave;
- struct slave *current_arp_slave;
+ struct slave __rcu *curr_active_slave;
+ struct slave __rcu *current_arp_slave;
struct slave *primary_slave;
bool force_primary;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
@@ -232,6 +231,10 @@ struct bonding {
#define bond_slave_get_rtnl(dev) \
((struct slave *) rtnl_dereference(dev->rx_handler_data))
+#define bond_deref_active_protected(bond) \
+ rcu_dereference_protected(bond->curr_active_slave, \
+ lockdep_is_held(&bond->curr_slave_lock))
+
struct bond_vlan_tag {
__be16 vlan_proto;
unsigned short vlan_id;
@@ -265,6 +268,12 @@ static inline bool bond_is_lb(const struct bonding *bond)
BOND_MODE(bond) == BOND_MODE_ALB;
}
+static inline bool bond_is_nondyn_tlb(const struct bonding *bond)
+{
+ return (BOND_MODE(bond) == BOND_MODE_TLB) &&
+ (bond->params.tlb_dynamic_lb == 0);
+}
+
static inline bool bond_mode_uses_arp(int mode)
{
return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB &&
@@ -514,11 +523,10 @@ unsigned int bond_get_num_tx_queues(void);
int bond_netlink_init(void);
void bond_netlink_fini(void);
struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
-struct net_device *bond_option_active_slave_get(struct bonding *bond);
const char *bond_slave_link_status(s8 link);
-bool bond_verify_device_path(struct net_device *start_dev,
- struct net_device *end_dev,
- struct bond_vlan_tag *tags);
+struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
+ struct net_device *end_dev,
+ int level);
#ifdef CONFIG_PROC_FS
void bond_create_proc_entry(struct bonding *bond);
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index fc73865bb83a..27bbc56de15f 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -349,7 +349,8 @@ static int ldisc_open(struct tty_struct *tty)
result = snprintf(name, sizeof(name), "cf%s", tty->name);
if (result >= IFNAMSIZ)
return -EINVAL;
- dev = alloc_netdev(sizeof(*ser), name, caifdev_setup);
+ dev = alloc_netdev(sizeof(*ser), name, NET_NAME_UNKNOWN,
+ caifdev_setup);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index ff54c0eb2052..72ea9ff9bb9c 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -730,8 +730,8 @@ int cfspi_spi_probe(struct platform_device *pdev)
int res;
dev = (struct cfspi_dev *)pdev->dev.platform_data;
- ndev = alloc_netdev(sizeof(struct cfspi),
- "cfspi%d", cfspi_setup);
+ ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d",
+ NET_NAME_UNKNOWN, cfspi_setup);
if (!dev)
return -ENODEV;
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 985608634f8c..a5fefb9059c5 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -661,7 +661,7 @@ static int cfv_probe(struct virtio_device *vdev)
int err = -EINVAL;
netdev = alloc_netdev(sizeof(struct cfv_info), cfv_netdev_name,
- cfv_netdev_setup);
+ NET_NAME_UNKNOWN, cfv_netdev_setup);
if (!netdev)
return -ENOMEM;
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 5d11e0e4225b..7be393c96b1a 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -270,7 +270,8 @@ static struct c_can_pci_data c_can_pch = {
PCI_DEVICE(_vend, _dev), \
.driver_data = (unsigned long)&_driverdata, \
}
-static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
+
+static const struct pci_device_id c_can_pci_tbl[] = {
C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
c_can_sta2x11),
C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 12430be6448a..5dede6e64376 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -208,40 +208,31 @@ static int c_can_plat_probe(struct platform_device *pdev)
}
/* get the appropriate clk */
- clk = clk_get(&pdev->dev, NULL);
+ clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "no clock defined\n");
- ret = -ENODEV;
+ ret = PTR_ERR(clk);
goto exit;
}
/* get the platform data */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
- if (!mem || irq <= 0) {
+ if (irq <= 0) {
ret = -ENODEV;
- goto exit_free_clk;
- }
-
- if (!request_mem_region(mem->start, resource_size(mem),
- KBUILD_MODNAME)) {
- dev_err(&pdev->dev, "resource unavailable\n");
- ret = -ENODEV;
- goto exit_free_clk;
+ goto exit;
}
- addr = ioremap(mem->start, resource_size(mem));
- if (!addr) {
- dev_err(&pdev->dev, "failed to map can port\n");
- ret = -ENOMEM;
- goto exit_release_mem;
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ addr = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(addr)) {
+ ret = PTR_ERR(addr);
+ goto exit;
}
/* allocate the c_can device */
dev = alloc_c_can_dev();
if (!dev) {
ret = -ENOMEM;
- goto exit_iounmap;
+ goto exit;
}
priv = netdev_priv(dev);
@@ -322,12 +313,6 @@ static int c_can_plat_probe(struct platform_device *pdev)
exit_free_device:
free_c_can_dev(dev);
-exit_iounmap:
- iounmap(addr);
-exit_release_mem:
- release_mem_region(mem->start, resource_size(mem));
-exit_free_clk:
- clk_put(clk);
exit:
dev_err(&pdev->dev, "probe failed\n");
@@ -337,18 +322,10 @@ exit:
static int c_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
- struct c_can_priv *priv = netdev_priv(dev);
- struct resource *mem;
unregister_c_can_dev(dev);
free_c_can_dev(dev);
- iounmap(priv->base);
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
-
- clk_put(priv->priv);
return 0;
}
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index e318e87e2bfc..9f91fcba43f8 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -565,7 +565,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
else
size = sizeof_priv;
- dev = alloc_netdev(size, "can%d", can_setup);
+ dev = alloc_netdev(size, "can%d", NET_NAME_UNKNOWN, can_setup);
if (!dev)
return NULL;
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 6472562efedc..a67eb01f3028 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -194,7 +194,7 @@ static const struct can_bittiming_const pch_can_bittiming_const = {
.brp_inc = 1,
};
-static DEFINE_PCI_DEVICE_TABLE(pch_pci_tbl) = {
+static const struct pci_device_id pch_pci_tbl[] = {
{PCI_VENDOR_ID_INTEL, 0x8818, PCI_ANY_ID, PCI_ANY_ID,},
{0,}
};
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c
index fd13dbf07d9c..7481c324a476 100644
--- a/drivers/net/can/sja1000/ems_pci.c
+++ b/drivers/net/can/sja1000/ems_pci.c
@@ -101,7 +101,7 @@ struct ems_pci_card {
#define EMS_PCI_BASE_SIZE 4096 /* size of controller area */
-static DEFINE_PCI_DEVICE_TABLE(ems_pci_tbl) = {
+static const struct pci_device_id ems_pci_tbl[] = {
/* CPC-PCI v1 */
{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
/* CPC-PCI v2 */
diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c
index 23b8e1324e25..8ff3424d5147 100644
--- a/drivers/net/can/sja1000/kvaser_pci.c
+++ b/drivers/net/can/sja1000/kvaser_pci.c
@@ -107,7 +107,7 @@ struct kvaser_pci {
#define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */
#define KVASER_PCI_DEVICE_ID2 0x0008
-static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = {
+static const struct pci_device_id kvaser_pci_tbl[] = {
{KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,},
{KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,},
{ 0,}
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c
index 564933ae218c..7a85590fefb9 100644
--- a/drivers/net/can/sja1000/peak_pci.c
+++ b/drivers/net/can/sja1000/peak_pci.c
@@ -77,7 +77,7 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = {
0x02, 0x01, 0x40, 0x80
};
-static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
+static const struct pci_device_id peak_pci_tbl[] = {
{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index ec39b7cb2287..8836a7485c81 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -247,7 +247,7 @@ static struct plx_pci_card_info plx_pci_card_info_elcus = {
/* based on PLX9030 */
};
-static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
+static const struct pci_device_id plx_pci_tbl[] = {
{
/* Adlink PCI-7841/cPCI-7841 */
ADLINK_PCI_VENDOR_ID, ADLINK_PCI_DEVICE_ID,
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index f31499a32d7d..d1692154ed1b 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -141,6 +141,7 @@ static void set_normal_mode(struct net_device *dev)
{
struct sja1000_priv *priv = netdev_priv(dev);
unsigned char status = priv->read_reg(priv, SJA1000_MOD);
+ u8 mod_reg_val = 0x00;
int i;
for (i = 0; i < 100; i++) {
@@ -158,9 +159,10 @@ static void set_normal_mode(struct net_device *dev)
/* set chip to normal mode */
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- priv->write_reg(priv, SJA1000_MOD, MOD_LOM);
- else
- priv->write_reg(priv, SJA1000_MOD, 0x00);
+ mod_reg_val |= MOD_LOM;
+ if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+ mod_reg_val |= MOD_STM;
+ priv->write_reg(priv, SJA1000_MOD, mod_reg_val);
udelay(10);
@@ -278,6 +280,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
uint8_t dlc;
canid_t id;
uint8_t dreg;
+ u8 cmd_reg_val = 0x00;
int i;
if (can_dropped_invalid_skb(dev, skb))
@@ -312,9 +315,14 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
can_put_echo_skb(skb, dev, 0);
if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
- sja1000_write_cmdreg(priv, CMD_TR | CMD_AT);
+ cmd_reg_val |= CMD_AT;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+ cmd_reg_val |= CMD_SRR;
else
- sja1000_write_cmdreg(priv, CMD_TR);
+ cmd_reg_val |= CMD_TR;
+
+ sja1000_write_cmdreg(priv, cmd_reg_val);
return NETDEV_TX_OK;
}
@@ -622,9 +630,12 @@ struct net_device *alloc_sja1000dev(int sizeof_priv)
priv->can.do_set_bittiming = sja1000_set_bittiming;
priv->can.do_set_mode = sja1000_set_mode;
priv->can.do_get_berr_counter = sja1000_get_berr_counter;
- priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_ONE_SHOT;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
+ CAN_CTRLMODE_LISTENONLY |
+ CAN_CTRLMODE_3_SAMPLES |
+ CAN_CTRLMODE_ONE_SHOT |
+ CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_PRESUME_ACK;
spin_lock_init(&priv->cmdreg_lock);
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index ea4d4f1a6411..acb5b92ace92 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -529,7 +529,7 @@ static struct slcan *slc_alloc(dev_t line)
return NULL;
sprintf(name, "slcan%d", i);
- dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+ dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, slc_setup);
if (!dev)
return NULL;
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 29e272cc7a98..64c016a99af8 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -1496,7 +1496,6 @@ e100_set_config(struct net_device *dev, struct ifmap *map)
case IF_PORT_AUI:
spin_unlock(&np->lock);
return -EOPNOTSUPP;
- break;
default:
printk(KERN_ERR "%s: Invalid media selected", dev->name);
spin_unlock(&np->lock);
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 0932ffbf381b..ff435fbd1ad0 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -164,7 +164,7 @@ static int __init dummy_init_one(void)
struct net_device *dev_dummy;
int err;
- dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
+ dev_dummy = alloc_netdev(0, "dummy%d", NET_NAME_UNKNOWN, dummy_setup);
if (!dev_dummy)
return -ENOMEM;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 7a79b6046879..957e5c0cede3 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -585,7 +585,8 @@ static int __init eql_init_module(void)
pr_info("%s\n", version);
- dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
+ dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", NET_NAME_UNKNOWN,
+ eql_setup);
if (!dev_eql)
return -ENOMEM;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 61477b8e8d24..059c7414e303 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -375,7 +375,7 @@ static struct vortex_chip_info {
};
-static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = {
+static const struct pci_device_id vortex_pci_tbl[] = {
{ 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 },
{ 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 },
{ 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 },
diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c
index e13b04624ded..48775b88bac7 100644
--- a/drivers/net/ethernet/3com/typhoon.c
+++ b/drivers/net/ethernet/3com/typhoon.c
@@ -203,7 +203,7 @@ static struct typhoon_card_info typhoon_card_info[] = {
* bit 8 indicates if this is a (0) copper or (1) fiber card
* bits 12-16 indicate card type: (0) client and (1) server
*/
-static DEFINE_PCI_DEVICE_TABLE(typhoon_pci_tbl) = {
+static const struct pci_device_id typhoon_pci_tbl[] = {
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,TYPHOON_TX },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_95,
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index 0988811f4e40..2d89bd00de61 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -91,7 +91,8 @@ config MCF8390
config NE2000
tristate "NE2000/NE1000 support"
- depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+ depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX || \
+ ATARI_ETHERNEC)
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
index 73c57a4a7b9e..7769c05543f1 100644
--- a/drivers/net/ethernet/8390/axnet_cs.c
+++ b/drivers/net/ethernet/8390/axnet_cs.c
@@ -108,7 +108,7 @@ static u32 axnet_msg_enable;
/*====================================================================*/
-typedef struct axnet_dev_t {
+struct axnet_dev {
struct pcmcia_device *p_dev;
caddr_t base;
struct timer_list watchdog;
@@ -118,9 +118,9 @@ typedef struct axnet_dev_t {
int phy_id;
int flags;
int active_low;
-} axnet_dev_t;
+};
-static inline axnet_dev_t *PRIV(struct net_device *dev)
+static inline struct axnet_dev *PRIV(struct net_device *dev)
{
void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
return p;
@@ -141,13 +141,13 @@ static const struct net_device_ops axnet_netdev_ops = {
static int axnet_probe(struct pcmcia_device *link)
{
- axnet_dev_t *info;
+ struct axnet_dev *info;
struct net_device *dev;
struct ei_device *ei_local;
dev_dbg(&link->dev, "axnet_attach()\n");
- dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
+ dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(struct axnet_dev));
if (!dev)
return -ENOMEM;
@@ -274,7 +274,7 @@ static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
static int axnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
int i, j, j2, ret;
dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
@@ -389,7 +389,7 @@ static int axnet_suspend(struct pcmcia_device *link)
static int axnet_resume(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
if (link->open) {
if (info->active_low == 1)
@@ -467,7 +467,7 @@ static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
int ret;
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
unsigned int nic_base = dev->base_addr;
@@ -497,7 +497,7 @@ static int axnet_open(struct net_device *dev)
static int axnet_close(struct net_device *dev)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
@@ -554,7 +554,7 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
static void ei_watchdog(u_long arg)
{
struct net_device *dev = (struct net_device *)(arg);
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
unsigned int nic_base = dev->base_addr;
unsigned int mii_addr = nic_base + AXNET_MII_EEP;
u_short link;
@@ -610,7 +610,7 @@ reschedule:
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
struct mii_ioctl_data *data = if_mii(rq);
unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
switch (cmd) {
@@ -1452,7 +1452,7 @@ static void ei_receive(struct net_device *dev)
static void ei_rx_overrun(struct net_device *dev)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
long e8390_base = dev->base_addr;
unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = netdev_priv(dev);
@@ -1624,7 +1624,7 @@ static void set_multicast_list(struct net_device *dev)
static void AX88190_init(struct net_device *dev, int startp)
{
- axnet_dev_t *info = PRIV(dev);
+ struct axnet_dev *info = PRIV(dev);
long e8390_base = dev->base_addr;
struct ei_device *ei_local = netdev_priv(dev);
int i;
diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
index 599311f0e05c..b96e8852b2d1 100644
--- a/drivers/net/ethernet/8390/lib8390.c
+++ b/drivers/net/ethernet/8390/lib8390.c
@@ -986,7 +986,7 @@ static void ethdev_setup(struct net_device *dev)
static struct net_device *____alloc_ei_netdev(int size)
{
return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
- ethdev_setup);
+ NET_NAME_UNKNOWN, ethdev_setup);
}
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 90e825e8abfe..65cf60f6718c 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -178,10 +178,8 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
case NUBUS_DRHW_APPLE_SONIC_LC:
case NUBUS_DRHW_SONNET:
return MAC8390_NONE;
- break;
default:
return MAC8390_APPLE;
- break;
}
break;
@@ -189,13 +187,10 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
switch (dev->dr_hw) {
case NUBUS_DRHW_ASANTE_LC:
return MAC8390_NONE;
- break;
case NUBUS_DRHW_CABLETRON:
return MAC8390_CABLETRON;
- break;
default:
return MAC8390_APPLE;
- break;
}
break;
@@ -220,10 +215,8 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
switch (dev->dr_hw) {
case NUBUS_DRHW_INTERLAN:
return MAC8390_INTERLAN;
- break;
default:
return MAC8390_KINETICS;
- break;
}
break;
@@ -563,7 +556,6 @@ static int __init mac8390_initdev(struct net_device *dev,
case ACCESS_UNKNOWN:
pr_err("Don't know how to access card memory!\n");
return -ENODEV;
- break;
case ACCESS_16:
/* 16 bit card, register map is reversed */
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index 58eaa8f34942..de566fb6e0f7 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -169,6 +169,8 @@ bad_clone_list[] __initdata = {
#elif defined(CONFIG_PLAT_OAKS32R) || \
defined(CONFIG_MACH_TX49XX)
# define DCR_VAL 0x48 /* 8-bit mode */
+#elif defined(CONFIG_ATARI) /* 8-bit mode on Atari, normal on Q40 */
+# define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49)
#else
# define DCR_VAL 0x49
#endif
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
index f395c967262e..89c8d9fc97de 100644
--- a/drivers/net/ethernet/8390/ne2k-pci.c
+++ b/drivers/net/ethernet/8390/ne2k-pci.c
@@ -135,7 +135,7 @@ static struct {
};
-static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = {
+static const struct pci_device_id ne2k_pci_tbl[] = {
{ 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 },
{ 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 },
{ 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 },
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
index ca3c2b921cf6..9fb7b9d4fd6c 100644
--- a/drivers/net/ethernet/8390/pcnet_cs.c
+++ b/drivers/net/ethernet/8390/pcnet_cs.c
@@ -111,11 +111,11 @@ static void pcnet_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
-typedef struct hw_info_t {
+struct hw_info {
u_int offset;
u_char a0, a1, a2;
u_int flags;
-} hw_info_t;
+};
#define DELAY_OUTPUT 0x01
#define HAS_MISC_REG 0x02
@@ -132,7 +132,7 @@ typedef struct hw_info_t {
#define MII_PHYID_REG1 0x02
#define MII_PHYID_REG2 0x03
-static hw_info_t hw_info[] = {
+static struct hw_info hw_info[] = {
{ /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
{ /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
{ /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
@@ -196,11 +196,11 @@ static hw_info_t hw_info[] = {
#define NR_INFO ARRAY_SIZE(hw_info)
-static hw_info_t default_info = { 0, 0, 0, 0, 0 };
-static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
-static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
+static struct hw_info default_info = { 0, 0, 0, 0, 0 };
+static struct hw_info dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
+static struct hw_info dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
-typedef struct pcnet_dev_t {
+struct pcnet_dev {
struct pcmcia_device *p_dev;
u_int flags;
void __iomem *base;
@@ -210,12 +210,12 @@ typedef struct pcnet_dev_t {
u_char eth_phy, pna_phy;
u_short link_status;
u_long mii_reset;
-} pcnet_dev_t;
+};
-static inline pcnet_dev_t *PRIV(struct net_device *dev)
+static inline struct pcnet_dev *PRIV(struct net_device *dev)
{
char *p = netdev_priv(dev);
- return (pcnet_dev_t *)(p + sizeof(struct ei_device));
+ return (struct pcnet_dev *)(p + sizeof(struct ei_device));
}
static const struct net_device_ops pcnet_netdev_ops = {
@@ -237,13 +237,13 @@ static const struct net_device_ops pcnet_netdev_ops = {
static int pcnet_probe(struct pcmcia_device *link)
{
- pcnet_dev_t *info;
+ struct pcnet_dev *info;
struct net_device *dev;
dev_dbg(&link->dev, "pcnet_attach()\n");
/* Create new ethernet device */
- dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
+ dev = __alloc_ei_netdev(sizeof(struct pcnet_dev));
if (!dev) return -ENOMEM;
info = PRIV(dev);
info->p_dev = link;
@@ -276,7 +276,7 @@ static void pcnet_detach(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+static struct hw_info *get_hwinfo(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
u_char __iomem *base, *virt;
@@ -317,7 +317,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_prom(struct pcmcia_device *link)
+static struct hw_info *get_prom(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
unsigned int ioaddr = dev->base_addr;
@@ -371,7 +371,7 @@ static hw_info_t *get_prom(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_dl10019(struct pcmcia_device *link)
+static struct hw_info *get_dl10019(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -393,7 +393,7 @@ static hw_info_t *get_dl10019(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_ax88190(struct pcmcia_device *link)
+static struct hw_info *get_ax88190(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
unsigned int ioaddr = dev->base_addr;
@@ -424,7 +424,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
======================================================================*/
-static hw_info_t *get_hwired(struct pcmcia_device *link)
+static struct hw_info *get_hwired(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
int i;
@@ -489,12 +489,12 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
return try_io_port(p_dev);
}
-static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
- int *has_shmem, int try)
+static struct hw_info *pcnet_try_config(struct pcmcia_device *link,
+ int *has_shmem, int try)
{
struct net_device *dev = link->priv;
- hw_info_t *local_hw_info;
- pcnet_dev_t *info = PRIV(dev);
+ struct hw_info *local_hw_info;
+ struct pcnet_dev *info = PRIV(dev);
int priv = try;
int ret;
@@ -553,10 +553,10 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
static int pcnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
int start_pg, stop_pg, cm_offset;
int has_shmem = 0;
- hw_info_t *local_hw_info;
+ struct hw_info *local_hw_info;
struct ei_device *ei_local;
dev_dbg(&link->dev, "pcnet_config\n");
@@ -639,7 +639,7 @@ failed:
static void pcnet_release(struct pcmcia_device *link)
{
- pcnet_dev_t *info = PRIV(link->priv);
+ struct pcnet_dev *info = PRIV(link->priv);
dev_dbg(&link->dev, "pcnet_release\n");
@@ -836,7 +836,7 @@ static void write_asic(unsigned int ioaddr, int location, short asic_data)
static void set_misc_reg(struct net_device *dev)
{
unsigned int nic_base = dev->base_addr;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
u_char tmp;
if (info->flags & HAS_MISC_REG) {
@@ -873,7 +873,7 @@ static void set_misc_reg(struct net_device *dev)
static void mii_phy_probe(struct net_device *dev)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
int i;
u_int tmp, phyid;
@@ -898,7 +898,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
int ret;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
unsigned int nic_base = dev->base_addr;
@@ -931,7 +931,7 @@ static int pcnet_open(struct net_device *dev)
static int pcnet_close(struct net_device *dev)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
@@ -982,7 +982,7 @@ static void pcnet_reset_8390(struct net_device *dev)
static int set_config(struct net_device *dev, struct ifmap *map)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
if (!(info->flags & HAS_MISC_REG))
return -EOPNOTSUPP;
@@ -1000,7 +1000,7 @@ static int set_config(struct net_device *dev, struct ifmap *map)
static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- pcnet_dev_t *info;
+ struct pcnet_dev *info;
irqreturn_t ret = ei_interrupt(irq, dev_id);
if (ret == IRQ_HANDLED) {
@@ -1013,7 +1013,7 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
static void ei_watchdog(u_long arg)
{
struct net_device *dev = (struct net_device *)arg;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
unsigned int nic_base = dev->base_addr;
unsigned int mii_addr = nic_base + DLINK_GPIO;
u_short link;
@@ -1101,7 +1101,7 @@ reschedule:
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
struct mii_ioctl_data *data = if_mii(rq);
unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
@@ -1214,7 +1214,7 @@ static void dma_block_output(struct net_device *dev, int count,
const u_char *buf, const int start_page)
{
unsigned int nic_base = dev->base_addr;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
#ifdef PCMCIA_DEBUG
int retries = 0;
struct ei_device *ei_local = netdev_priv(dev);
@@ -1403,7 +1403,7 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
int stop_pg, int cm_offset)
{
struct net_device *dev = link->priv;
- pcnet_dev_t *info = PRIV(dev);
+ struct pcnet_dev *info = PRIV(dev);
int i, window_size, offset, ret;
window_size = (stop_pg - start_pg) << 8;
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index edb718661850..dc7406c81c45 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
source "drivers/net/ethernet/altera/Kconfig"
source "drivers/net/ethernet/amd/Kconfig"
+source "drivers/net/ethernet/apm/Kconfig"
source "drivers/net/ethernet/apple/Kconfig"
source "drivers/net/ethernet/arc/Kconfig"
source "drivers/net/ethernet/atheros/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 58de3339ab3c..224a01877149 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
obj-$(CONFIG_ALTERA_TSE) += altera/
obj-$(CONFIG_NET_VENDOR_AMD) += amd/
+obj-$(CONFIG_NET_XGENE) += apm/
obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
obj-$(CONFIG_NET_VENDOR_ARC) += arc/
obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c
index 40dbbf740331..ac7288240d55 100644
--- a/drivers/net/ethernet/adaptec/starfire.c
+++ b/drivers/net/ethernet/adaptec/starfire.c
@@ -285,7 +285,7 @@ enum chipset {
CH_6915 = 0,
};
-static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = {
+static const struct pci_device_id starfire_pci_tbl[] = {
{ PCI_VDEVICE(ADAPTEC, 0x6915), CH_6915 },
{ 0, }
};
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index f952fff6a9a9..c9cd3592ab73 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -52,8 +52,7 @@ config BFIN_TX_DESC_NUM
config BFIN_RX_DESC_NUM
int "Number of receive buffer packets"
depends on BFIN_MAC
- range 20 100 if BFIN_MAC_USE_L1
- range 20 800
+ range 20 64
default "20"
---help---
Set the number of buffer packets used in driver.
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index 7ae74d450e8f..afa66847e10b 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -1218,11 +1218,11 @@ out:
#define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \
RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE)
-static void bfin_mac_rx(struct net_device *dev)
+static void bfin_mac_rx(struct bfin_mac_local *lp)
{
+ struct net_device *dev = lp->ndev;
struct sk_buff *skb, *new_skb;
unsigned short len;
- struct bfin_mac_local *lp __maybe_unused = netdev_priv(dev);
#if defined(BFIN_MAC_CSUM_OFFLOAD)
unsigned int i;
unsigned char fcs[ETH_FCS_LEN + 1];
@@ -1256,7 +1256,7 @@ static void bfin_mac_rx(struct net_device *dev)
current_rx_ptr->skb = new_skb;
current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
- len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN);
+ len = (unsigned short)(current_rx_ptr->status.status_word & RX_FRLEN);
/* Deduce Ethernet FCS length from Ethernet payload length */
len -= ETH_FCS_LEN;
skb_put(skb, len);
@@ -1294,7 +1294,8 @@ static void bfin_mac_rx(struct net_device *dev)
}
#endif
- netif_rx(skb);
+ napi_gro_receive(&lp->napi, skb);
+
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
out:
@@ -1302,41 +1303,52 @@ out:
current_rx_ptr = current_rx_ptr->next;
}
+static int bfin_mac_poll(struct napi_struct *napi, int budget)
+{
+ int i = 0;
+ struct bfin_mac_local *lp = container_of(napi,
+ struct bfin_mac_local,
+ napi);
+
+ while (current_rx_ptr->status.status_word != 0 && i < budget) {
+ bfin_mac_rx(lp);
+ i++;
+ }
+
+ if (i < budget) {
+ napi_complete(napi);
+ if (test_and_clear_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags))
+ enable_irq(IRQ_MAC_RX);
+ }
+
+ return i;
+}
+
/* interrupt routine to handle rx and error signal */
static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = dev_id;
- int number = 0;
-
-get_one_packet:
- if (current_rx_ptr->status.status_word == 0) {
- /* no more new packet received */
- if (number == 0) {
- if (current_rx_ptr->next->status.status_word != 0) {
- current_rx_ptr = current_rx_ptr->next;
- goto real_rx;
- }
- }
- bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() |
- DMA_DONE | DMA_ERR);
- return IRQ_HANDLED;
+ struct bfin_mac_local *lp = netdev_priv(dev_id);
+ u32 status;
+
+ status = bfin_read_DMA1_IRQ_STATUS();
+
+ bfin_write_DMA1_IRQ_STATUS(status | DMA_DONE | DMA_ERR);
+ if (status & DMA_DONE) {
+ disable_irq_nosync(IRQ_MAC_RX);
+ set_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags);
+ napi_schedule(&lp->napi);
}
-real_rx:
- bfin_mac_rx(dev);
- number++;
- goto get_one_packet;
+ return IRQ_HANDLED;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
-static void bfin_mac_poll(struct net_device *dev)
+static void bfin_mac_poll_controller(struct net_device *dev)
{
struct bfin_mac_local *lp = netdev_priv(dev);
- disable_irq(IRQ_MAC_RX);
bfin_mac_interrupt(IRQ_MAC_RX, dev);
tx_reclaim_skb(lp);
- enable_irq(IRQ_MAC_RX);
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -1428,14 +1440,13 @@ static void bfin_mac_timeout(struct net_device *dev)
tx_list_head = tx_list_head->next;
}
- if (netif_queue_stopped(lp->ndev))
- netif_wake_queue(lp->ndev);
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
bfin_mac_enable(lp->phydev);
/* We can accept TX packets again */
dev->trans_start = jiffies; /* prevent tx timeout */
- netif_wake_queue(dev);
}
static void bfin_mac_multicast_hash(struct net_device *dev)
@@ -1562,6 +1573,7 @@ static int bfin_mac_open(struct net_device *dev)
return ret;
pr_debug("hardware init finished\n");
+ napi_enable(&lp->napi);
netif_start_queue(dev);
netif_carrier_on(dev);
@@ -1579,6 +1591,7 @@ static int bfin_mac_close(struct net_device *dev)
pr_debug("%s: %s\n", dev->name, __func__);
netif_stop_queue(dev);
+ napi_disable(&lp->napi);
netif_carrier_off(dev);
phy_stop(lp->phydev);
@@ -1604,7 +1617,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = bfin_mac_poll,
+ .ndo_poll_controller = bfin_mac_poll_controller,
#endif
};
@@ -1689,6 +1702,9 @@ static int bfin_mac_probe(struct platform_device *pdev)
lp->tx_reclaim_timer.data = (unsigned long)lp;
lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout;
+ lp->flags = 0;
+ netif_napi_add(ndev, &lp->napi, bfin_mac_poll, CONFIG_BFIN_RX_DESC_NUM);
+
spin_lock_init(&lp->lock);
/* now, enable interrupts */
@@ -1723,6 +1739,7 @@ out_err_phc:
out_err_reg_ndev:
free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
+ netif_napi_del(&lp->napi);
out_err_mii_probe:
mdiobus_unregister(lp->mii_bus);
mdiobus_free(lp->mii_bus);
@@ -1743,6 +1760,8 @@ static int bfin_mac_remove(struct platform_device *pdev)
unregister_netdev(ndev);
+ netif_napi_del(&lp->napi);
+
free_irq(IRQ_MAC_RX, ndev);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index 6dec86ac97cd..d1217db70db4 100644
--- a/drivers/net/ethernet/adi/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
@@ -26,6 +26,7 @@
#endif
#define TX_RECLAIM_JIFFIES (HZ / 5)
+#define BFIN_MAC_RX_IRQ_DISABLED 1
struct dma_descriptor {
struct dma_descriptor *next_dma_desc;
@@ -80,6 +81,8 @@ struct bfin_mac_local {
int irq_wake_requested;
struct timer_list tx_reclaim_timer;
struct net_device *ndev;
+ struct napi_struct napi;
+ unsigned long flags;
/* Data for EMAC_VLAN1 regs */
u16 vlan1_mask, vlan2_mask;
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
index d81e7167a8b5..29b9f082475d 100644
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -633,8 +633,10 @@ static void emac_rx(struct net_device *dev)
}
/* Move data from EMAC */
- skb = dev_alloc_skb(rxlen + 4);
- if (good_packet && skb) {
+ if (good_packet) {
+ skb = netdev_alloc_skb(dev, rxlen + 4);
+ if (!skb)
+ continue;
skb_reserve(skb, 2);
rdptr = (u8 *) skb_put(skb, rxlen - 4);
diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c
index 9a6991be9749..b68074803de3 100644
--- a/drivers/net/ethernet/alteon/acenic.c
+++ b/drivers/net/ethernet/alteon/acenic.c
@@ -131,7 +131,7 @@
#define PCI_DEVICE_ID_SGI_ACENIC 0x0009
#endif
-static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = {
+static const struct pci_device_id acenic_pci_tbl[] = {
{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, },
{ PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER,
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index bbaf36d9f5e1..8319c99331b0 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -182,6 +182,9 @@ config AMD_XGBE
depends on OF_NET
select PHYLIB
select AMD_XGBE_PHY
+ select BITREVERSE
+ select CRC32
+ select PTP_1588_CLOCK
---help---
This driver supports the AMD 10GbE Ethernet device found on an
AMD SoC.
@@ -189,4 +192,14 @@ config AMD_XGBE
To compile this driver as a module, choose M here: the module
will be called amd-xgbe.
+config AMD_XGBE_DCB
+ bool "Data Center Bridging (DCB) support"
+ default n
+ depends on AMD_XGBE && DCB
+ ---help---
+ Say Y here to enable Data Center Bridging (DCB) support in the
+ driver.
+
+ If unsure, say N.
+
endif # NET_VENDOR_AMD
diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c
index 068dc7cad5fa..841e6558db68 100644
--- a/drivers/net/ethernet/amd/amd8111e.c
+++ b/drivers/net/ethernet/amd/amd8111e.c
@@ -101,7 +101,6 @@ Revision History:
MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "MODULE_VERS);
MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
module_param_array(speed_duplex, int, NULL, 0);
MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
module_param_array(coalesce, bool, NULL, 0);
@@ -109,17 +108,9 @@ MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0
module_param_array(dynamic_ipg, bool, NULL, 0);
MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable");
-static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = {
-
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
- { 0, }
-
-};
-/*
-This function will read the PHY registers.
-*/
-static int amd8111e_read_phy(struct amd8111e_priv* lp, int phy_id, int reg, u32* val)
+/* This function will read the PHY registers. */
+static int amd8111e_read_phy(struct amd8111e_priv *lp,
+ int phy_id, int reg, u32 *val)
{
void __iomem *mmio = lp->mmio;
unsigned int reg_val;
@@ -146,10 +137,9 @@ err_phy_read:
}
-/*
-This function will write into PHY registers.
-*/
-static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
+/* This function will write into PHY registers. */
+static int amd8111e_write_phy(struct amd8111e_priv *lp,
+ int phy_id, int reg, u32 val)
{
unsigned int repeat = REPEAT_CNT;
void __iomem *mmio = lp->mmio;
@@ -176,12 +166,11 @@ err_phy_write:
return -EINVAL;
}
-/*
-This is the mii register read function provided to the mii interface.
-*/
-static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
+
+/* This is the mii register read function provided to the mii interface. */
+static int amd8111e_mdio_read(struct net_device *dev, int phy_id, int reg_num)
{
- struct amd8111e_priv* lp = netdev_priv(dev);
+ struct amd8111e_priv *lp = netdev_priv(dev);
unsigned int reg_val;
amd8111e_read_phy(lp,phy_id,reg_num,&reg_val);
@@ -189,19 +178,18 @@ static int amd8111e_mdio_read(struct net_device * dev, int phy_id, int reg_num)
}
-/*
-This is the mii register write function provided to the mii interface.
-*/
-static void amd8111e_mdio_write(struct net_device * dev, int phy_id, int reg_num, int val)
+/* This is the mii register write function provided to the mii interface. */
+static void amd8111e_mdio_write(struct net_device *dev,
+ int phy_id, int reg_num, int val)
{
- struct amd8111e_priv* lp = netdev_priv(dev);
+ struct amd8111e_priv *lp = netdev_priv(dev);
amd8111e_write_phy(lp, phy_id, reg_num, val);
}
-/*
-This function will set PHY speed. During initialization sets the original speed to 100 full.
-*/
+/* This function will set PHY speed. During initialization sets
+ * the original speed to 100 full
+ */
static void amd8111e_set_ext_phy(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
@@ -240,14 +228,13 @@ static void amd8111e_set_ext_phy(struct net_device *dev)
}
-/*
-This function will unmap skb->data space and will free
-all transmit and receive skbuffs.
-*/
+/* This function will unmap skb->data space and will free
+ * all transmit and receive skbuffs.
+ */
static int amd8111e_free_skbs(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
- struct sk_buff* rx_skbuff;
+ struct sk_buff *rx_skbuff;
int i;
/* Freeing transmit skbs */
@@ -274,18 +261,18 @@ static int amd8111e_free_skbs(struct net_device *dev)
return 0;
}
-/*
-This will set the receive buffer length corresponding to the mtu size of networkinterface.
-*/
-static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
+/* This will set the receive buffer length corresponding
+ * to the mtu size of networkinterface.
+ */
+static inline void amd8111e_set_rx_buff_len(struct net_device *dev)
{
- struct amd8111e_priv* lp = netdev_priv(dev);
+ struct amd8111e_priv *lp = netdev_priv(dev);
unsigned int mtu = dev->mtu;
if (mtu > ETH_DATA_LEN){
/* MTU + ethernet header + FCS
- + optional VLAN tag + skb reserve space 2 */
-
+ * + optional VLAN tag + skb reserve space 2
+ */
lp->rx_buff_len = mtu + ETH_HLEN + 10;
lp->options |= OPTION_JUMBO_ENABLE;
} else{
@@ -294,8 +281,10 @@ static inline void amd8111e_set_rx_buff_len(struct net_device* dev)
}
}
-/*
-This function will free all the previously allocated buffers, determine new receive buffer length and will allocate new receive buffers. This function also allocates and initializes both the transmitter and receive hardware descriptors.
+/* This function will free all the previously allocated buffers,
+ * determine new receive buffer length and will allocate new receive buffers.
+ * This function also allocates and initializes both the transmitter
+ * and receive hardware descriptors.
*/
static int amd8111e_init_ring(struct net_device *dev)
{
@@ -376,15 +365,18 @@ err_free_tx_ring:
err_no_mem:
return -ENOMEM;
}
-/* This function will set the interrupt coalescing according to the input arguments */
-static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
+
+/* This function will set the interrupt coalescing according
+ * to the input arguments
+ */
+static int amd8111e_set_coalesce(struct net_device *dev, enum coal_mode cmod)
{
unsigned int timeout;
unsigned int event_count;
struct amd8111e_priv *lp = netdev_priv(dev);
void __iomem *mmio = lp->mmio;
- struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+ struct amd8111e_coalesce_conf *coal_conf = &lp->coal_conf;
switch(cmod)
@@ -435,9 +427,7 @@ static int amd8111e_set_coalesce(struct net_device * dev, enum coal_mode cmod)
}
-/*
-This function initializes the device registers and starts the device.
-*/
+/* This function initializes the device registers and starts the device. */
static int amd8111e_restart(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
@@ -501,8 +491,7 @@ static int amd8111e_restart(struct net_device *dev)
/* Enable interrupt coalesce */
if(lp->options & OPTION_INTR_COAL_ENABLE){
- printk(KERN_INFO "%s: Interrupt Coalescing Enabled.\n",
- dev->name);
+ netdev_info(dev, "Interrupt Coalescing Enabled.\n");
amd8111e_set_coalesce(dev,ENABLE_COAL);
}
@@ -514,10 +503,9 @@ static int amd8111e_restart(struct net_device *dev)
readl(mmio+CMD0);
return 0;
}
-/*
-This function clears necessary the device registers.
-*/
-static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
+
+/* This function clears necessary the device registers. */
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
{
unsigned int reg_val;
unsigned int logic_filter[2] ={0,};
@@ -587,7 +575,7 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
writew(MIB_CLEAR, mmio + MIB_ADDR);
/* Clear LARF */
- amd8111e_writeq(*(u64*)logic_filter,mmio+LADRF);
+ amd8111e_writeq(*(u64 *)logic_filter, mmio + LADRF);
/* SRAM_SIZE register */
reg_val = readl(mmio + SRAM_SIZE);
@@ -605,11 +593,10 @@ static void amd8111e_init_hw_default( struct amd8111e_priv* lp)
}
-/*
-This function disables the interrupt and clears all the pending
-interrupts in INT0
+/* This function disables the interrupt and clears all the pending
+ * interrupts in INT0
*/
-static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
{
u32 intr0;
@@ -625,10 +612,8 @@ static void amd8111e_disable_interrupt(struct amd8111e_priv* lp)
}
-/*
-This function stops the chip.
-*/
-static void amd8111e_stop_chip(struct amd8111e_priv* lp)
+/* This function stops the chip. */
+static void amd8111e_stop_chip(struct amd8111e_priv *lp)
{
writel(RUN, lp->mmio + CMD0);
@@ -636,10 +621,8 @@ static void amd8111e_stop_chip(struct amd8111e_priv* lp)
readl(lp->mmio + CMD0);
}
-/*
-This function frees the transmiter and receiver descriptor rings.
-*/
-static void amd8111e_free_ring(struct amd8111e_priv* lp)
+/* This function frees the transmiter and receiver descriptor rings. */
+static void amd8111e_free_ring(struct amd8111e_priv *lp)
{
/* Free transmit and receive descriptor rings */
if(lp->rx_ring){
@@ -659,12 +642,13 @@ static void amd8111e_free_ring(struct amd8111e_priv* lp)
}
-/*
-This function will free all the transmit skbs that are actually transmitted by the device. It will check the ownership of the skb before freeing the skb.
-*/
+/* This function will free all the transmit skbs that are actually
+ * transmitted by the device. It will check the ownership of the
+ * skb before freeing the skb.
+ */
static int amd8111e_tx(struct net_device *dev)
{
- struct amd8111e_priv* lp = netdev_priv(dev);
+ struct amd8111e_priv *lp = netdev_priv(dev);
int tx_index = lp->tx_complete_idx & TX_RING_DR_MOD_MASK;
int status;
/* Complete all the transmit packet */
@@ -724,21 +708,20 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
goto rx_not_empty;
do{
- /* process receive packets until we use the quota*/
- /* If we own the next entry, it's a new packet. Send it up. */
+ /* process receive packets until we use the quota.
+ * If we own the next entry, it's a new packet. Send it up.
+ */
while(1) {
status = le16_to_cpu(lp->rx_ring[rx_index].rx_flags);
if (status & OWN_BIT)
break;
- /*
- * There is a tricky error noted by John Murphy,
+ /* There is a tricky error noted by John Murphy,
* <murf@perftech.com> to Russ Nelson: Even with
* full-sized * buffers it's possible for a
* jabber packet to use two buffers, with only
* the last correctly noting the error.
*/
-
if(status & ERR_BIT) {
/* reseting flags */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
@@ -771,7 +754,8 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
new_skb = netdev_alloc_skb(dev, lp->rx_buff_len);
if (!new_skb) {
/* if allocation fail,
- ignore that pkt and go to next one */
+ * ignore that pkt and go to next one
+ */
lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
lp->drv_rx_errors++;
goto err_next_pkt;
@@ -812,8 +796,8 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
rx_index = (++lp->rx_idx) & RX_RING_DR_MOD_MASK;
}
/* Check the interrupt status register for more packets in the
- mean time. Process them since we have not used up our quota.*/
-
+ * mean time. Process them since we have not used up our quota.
+ */
intr0 = readl(mmio + INT0);
/*Ack receive packets */
writel(intr0 & RINT0,mmio + INT0);
@@ -833,10 +817,8 @@ rx_not_empty:
return num_rx_pkt;
}
-/*
-This function will indicate the link status to the kernel.
-*/
-static int amd8111e_link_change(struct net_device* dev)
+/* This function will indicate the link status to the kernel. */
+static int amd8111e_link_change(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
int status0,speed;
@@ -860,24 +842,26 @@ static int amd8111e_link_change(struct net_device* dev)
else if(speed == PHY_SPEED_100)
lp->link_config.speed = SPEED_100;
- printk(KERN_INFO "%s: Link is Up. Speed is %s Mbps %s Duplex\n", dev->name,
- (lp->link_config.speed == SPEED_100) ? "100": "10",
- (lp->link_config.duplex == DUPLEX_FULL)? "Full": "Half");
+ netdev_info(dev, "Link is Up. Speed is %s Mbps %s Duplex\n",
+ (lp->link_config.speed == SPEED_100) ?
+ "100" : "10",
+ (lp->link_config.duplex == DUPLEX_FULL) ?
+ "Full" : "Half");
+
netif_carrier_on(dev);
}
else{
lp->link_config.speed = SPEED_INVALID;
lp->link_config.duplex = DUPLEX_INVALID;
lp->link_config.autoneg = AUTONEG_INVALID;
- printk(KERN_INFO "%s: Link is Down.\n",dev->name);
+ netdev_info(dev, "Link is Down.\n");
netif_carrier_off(dev);
}
return 0;
}
-/*
-This function reads the mib counters.
-*/
+
+/* This function reads the mib counters. */
static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
{
unsigned int status;
@@ -895,8 +879,7 @@ static int amd8111e_read_mib(void __iomem *mmio, u8 MIB_COUNTER)
return data;
}
-/*
- * This function reads the mib registers and returns the hardware statistics.
+/* This function reads the mib registers and returns the hardware statistics.
* It updates previous internal driver statistics with new values.
*/
static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
@@ -992,13 +975,14 @@ static struct net_device_stats *amd8111e_get_stats(struct net_device *dev)
return new_stats;
}
+
/* This function recalculate the interrupt coalescing mode on every interrupt
-according to the datarate and the packet rate.
-*/
+ * according to the datarate and the packet rate.
+ */
static int amd8111e_calc_coalesce(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
- struct amd8111e_coalesce_conf * coal_conf = &lp->coal_conf;
+ struct amd8111e_coalesce_conf *coal_conf = &lp->coal_conf;
int tx_pkt_rate;
int rx_pkt_rate;
int tx_data_rate;
@@ -1126,13 +1110,14 @@ static int amd8111e_calc_coalesce(struct net_device *dev)
return 0;
}
-/*
-This is device interrupt function. It handles transmit, receive,link change and hardware timer interrupts.
-*/
+
+/* This is device interrupt function. It handles transmit,
+ * receive,link change and hardware timer interrupts.
+ */
static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
{
- struct net_device * dev = (struct net_device *) dev_id;
+ struct net_device *dev = (struct net_device *)dev_id;
struct amd8111e_priv *lp = netdev_priv(dev);
void __iomem *mmio = lp->mmio;
unsigned int intr0, intren0;
@@ -1168,7 +1153,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
/* Schedule a polling routine */
__napi_schedule(&lp->napi);
} else if (intren0 & RINTEN0) {
- printk("************Driver bug! interrupt while in poll\n");
+ netdev_dbg(dev, "************Driver bug! interrupt while in poll\n");
/* Fix by disable receive interrupts */
writel(RINTEN0, mmio + INTEN0);
}
@@ -1205,10 +1190,11 @@ static void amd8111e_poll(struct net_device *dev)
#endif
-/*
-This function closes the network interface and updates the statistics so that most recent statistics will be available after the interface is down.
-*/
-static int amd8111e_close(struct net_device * dev)
+/* This function closes the network interface and updates
+ * the statistics so that most recent statistics will be
+ * available after the interface is down.
+ */
+static int amd8111e_close(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
netif_stop_queue(dev);
@@ -1238,9 +1224,11 @@ static int amd8111e_close(struct net_device * dev)
lp->opened = 0;
return 0;
}
-/* This function opens new interface.It requests irq for the device, initializes the device,buffers and descriptors, and starts the device.
-*/
-static int amd8111e_open(struct net_device * dev )
+
+/* This function opens new interface.It requests irq for the device,
+ * initializes the device,buffers and descriptors, and starts the device.
+ */
+static int amd8111e_open(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
@@ -1264,7 +1252,7 @@ static int amd8111e_open(struct net_device * dev )
/* Start ipg timer */
if(lp->options & OPTION_DYN_IPG_ENABLE){
add_timer(&lp->ipg_data.ipg_timer);
- printk(KERN_INFO "%s: Dynamic IPG Enabled.\n",dev->name);
+ netdev_info(dev, "Dynamic IPG Enabled\n");
}
lp->opened = 1;
@@ -1275,10 +1263,11 @@ static int amd8111e_open(struct net_device * dev )
return 0;
}
-/*
-This function checks if there is any transmit descriptors available to queue more packet.
-*/
-static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
+
+/* This function checks if there is any transmit descriptors
+ * available to queue more packet.
+ */
+static int amd8111e_tx_queue_avail(struct amd8111e_priv *lp)
{
int tx_index = lp->tx_idx & TX_BUFF_MOD_MASK;
if (lp->tx_skbuff[tx_index])
@@ -1287,12 +1276,14 @@ static int amd8111e_tx_queue_avail(struct amd8111e_priv* lp )
return 0;
}
-/*
-This function will queue the transmit packets to the descriptors and will trigger the send operation. It also initializes the transmit descriptors with buffer physical address, byte count, ownership to hardware etc.
-*/
+/* This function will queue the transmit packets to the
+ * descriptors and will trigger the send operation. It also
+ * initializes the transmit descriptors with buffer physical address,
+ * byte count, ownership to hardware etc.
+ */
static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
- struct net_device * dev)
+ struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
int tx_index;
@@ -1338,9 +1329,7 @@ static netdev_tx_t amd8111e_start_xmit(struct sk_buff *skb,
spin_unlock_irqrestore(&lp->lock, flags);
return NETDEV_TX_OK;
}
-/*
-This function returns all the memory mapped registers of the device.
-*/
+/* This function returns all the memory mapped registers of the device. */
static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
{
void __iomem *mmio = lp->mmio;
@@ -1361,10 +1350,9 @@ static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
}
-/*
-This function sets promiscuos mode, all-multi mode or the multicast address
-list to the device.
-*/
+/* This function sets promiscuos mode, all-multi mode or the multicast address
+ * list to the device.
+ */
static void amd8111e_set_multicast_list(struct net_device *dev)
{
struct netdev_hw_addr *ha;
@@ -1383,14 +1371,14 @@ static void amd8111e_set_multicast_list(struct net_device *dev)
/* get all multicast packet */
mc_filter[1] = mc_filter[0] = 0xffffffff;
lp->options |= OPTION_MULTICAST_ENABLE;
- amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+ amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
return;
}
if (netdev_mc_empty(dev)) {
/* get only own packets */
mc_filter[1] = mc_filter[0] = 0;
lp->options &= ~OPTION_MULTICAST_ENABLE;
- amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
+ amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
/* disable promiscuous mode */
writel(PROM, lp->mmio + CMD2);
return;
@@ -1402,14 +1390,15 @@ static void amd8111e_set_multicast_list(struct net_device *dev)
bit_num = (ether_crc_le(ETH_ALEN, ha->addr) >> 26) & 0x3f;
mc_filter[bit_num >> 5] |= 1 << (bit_num & 31);
}
- amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF);
+ amd8111e_writeq(*(u64 *)mc_filter, lp->mmio + LADRF);
/* To eliminate PCI posting bug */
readl(lp->mmio + CMD2);
}
-static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info)
+static void amd8111e_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
struct amd8111e_priv *lp = netdev_priv(dev);
struct pci_dev *pci_dev = lp->pci_dev;
@@ -1501,11 +1490,11 @@ static const struct ethtool_ops ops = {
.set_wol = amd8111e_set_wol,
};
-/*
-This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application.
-*/
-
-static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd)
+/* This function handles all the ethtool ioctls. It gives driver info,
+ * gets/sets driver speed, gets memory mapped register values, forces
+ * auto negotiation, sets/gets WOL options for ethtool application.
+ */
+static int amd8111e_ioctl(struct net_device *dev , struct ifreq *ifr, int cmd)
{
struct mii_ioctl_data *data = if_mii(ifr);
struct amd8111e_priv *lp = netdev_priv(dev);
@@ -1559,9 +1548,9 @@ static int amd8111e_set_mac_address(struct net_device *dev, void *p)
return 0;
}
-/*
-This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers.
-*/
+/* This function changes the mtu of the device. It restarts the device to
+ * initialize the descriptor with new receive buffers.
+ */
static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
{
struct amd8111e_priv *lp = netdev_priv(dev);
@@ -1572,7 +1561,8 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
if (!netif_running(dev)) {
/* new_mtu will be used
- when device starts netxt time */
+ * when device starts netxt time
+ */
dev->mtu = new_mtu;
return 0;
}
@@ -1591,7 +1581,7 @@ static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
return err;
}
-static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
+static int amd8111e_enable_magicpkt(struct amd8111e_priv *lp)
{
writel( VAL1|MPPLBA, lp->mmio + CMD3);
writel( VAL0|MPEN_SW, lp->mmio + CMD7);
@@ -1601,7 +1591,7 @@ static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
return 0;
}
-static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
+static int amd8111e_enable_link_change(struct amd8111e_priv *lp)
{
/* Adapter is already stoped/suspended/interrupt-disabled */
@@ -1612,19 +1602,18 @@ static int amd8111e_enable_link_change(struct amd8111e_priv* lp)
return 0;
}
-/*
- * This function is called when a packet transmission fails to complete
+/* This function is called when a packet transmission fails to complete
* within a reasonable period, on the assumption that an interrupt have
* failed or the interface is locked up. This function will reinitialize
* the hardware.
*/
static void amd8111e_tx_timeout(struct net_device *dev)
{
- struct amd8111e_priv* lp = netdev_priv(dev);
+ struct amd8111e_priv *lp = netdev_priv(dev);
int err;
- printk(KERN_ERR "%s: transmit timed out, resetting\n",
- dev->name);
+ netdev_err(dev, "transmit timed out, resetting\n");
+
spin_lock_irq(&lp->lock);
err = amd8111e_restart(dev);
spin_unlock_irq(&lp->lock);
@@ -1701,22 +1690,10 @@ static int amd8111e_resume(struct pci_dev *pci_dev)
return 0;
}
-
-static void amd8111e_remove_one(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- if (dev) {
- unregister_netdev(dev);
- iounmap(((struct amd8111e_priv *)netdev_priv(dev))->mmio);
- free_netdev(dev);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- }
-}
-static void amd8111e_config_ipg(struct net_device* dev)
+static void amd8111e_config_ipg(struct net_device *dev)
{
struct amd8111e_priv *lp = netdev_priv(dev);
- struct ipg_info* ipg_data = &lp->ipg_data;
+ struct ipg_info *ipg_data = &lp->ipg_data;
void __iomem *mmio = lp->mmio;
unsigned int prev_col_cnt = ipg_data->col_cnt;
unsigned int total_col_cnt;
@@ -1814,27 +1791,24 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
{
int err, i;
unsigned long reg_addr,reg_len;
- struct amd8111e_priv* lp;
- struct net_device* dev;
+ struct amd8111e_priv *lp;
+ struct net_device *dev;
err = pci_enable_device(pdev);
if(err){
- printk(KERN_ERR "amd8111e: Cannot enable new PCI device, "
- "exiting.\n");
+ dev_err(&pdev->dev, "Cannot enable new PCI device\n");
return err;
}
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)){
- printk(KERN_ERR "amd8111e: Cannot find PCI base address, "
- "exiting.\n");
+ dev_err(&pdev->dev, "Cannot find PCI base address\n");
err = -ENODEV;
goto err_disable_pdev;
}
err = pci_request_regions(pdev, MODULE_NAME);
if(err){
- printk(KERN_ERR "amd8111e: Cannot obtain PCI resources, "
- "exiting.\n");
+ dev_err(&pdev->dev, "Cannot obtain PCI resources\n");
goto err_disable_pdev;
}
@@ -1842,16 +1816,14 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
/* Find power-management capability. */
if (!pdev->pm_cap) {
- printk(KERN_ERR "amd8111e: No Power Management capability, "
- "exiting.\n");
+ dev_err(&pdev->dev, "No Power Management capability\n");
err = -ENODEV;
goto err_free_reg;
}
/* Initialize DMA */
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) < 0) {
- printk(KERN_ERR "amd8111e: DMA not supported,"
- "exiting.\n");
+ dev_err(&pdev->dev, "DMA not supported\n");
err = -ENODEV;
goto err_free_reg;
}
@@ -1878,10 +1850,9 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
spin_lock_init(&lp->lock);
- lp->mmio = ioremap(reg_addr, reg_len);
+ lp->mmio = devm_ioremap(&pdev->dev, reg_addr, reg_len);
if (!lp->mmio) {
- printk(KERN_ERR "amd8111e: Cannot map device registers, "
- "exiting\n");
+ dev_err(&pdev->dev, "Cannot map device registers\n");
err = -ENOMEM;
goto err_free_dev;
}
@@ -1923,9 +1894,8 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
err = register_netdev(dev);
if (err) {
- printk(KERN_ERR "amd8111e: Cannot register net device, "
- "exiting.\n");
- goto err_iounmap;
+ dev_err(&pdev->dev, "Cannot register net device\n");
+ goto err_free_dev;
}
pci_set_drvdata(pdev, dev);
@@ -1942,21 +1912,17 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
}
/* display driver and device information */
-
chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
- printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
- dev->name,MODULE_VERS);
- printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
- dev->name, chip_version, dev->dev_addr);
+ dev_info(&pdev->dev, "AMD-8111e Driver Version: %s\n", MODULE_VERS);
+ dev_info(&pdev->dev, "[ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
+ chip_version, dev->dev_addr);
if (lp->ext_phy_id)
- printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
- dev->name, lp->ext_phy_id, lp->ext_phy_addr);
+ dev_info(&pdev->dev, "Found MII PHY ID 0x%08x at address 0x%02x\n",
+ lp->ext_phy_id, lp->ext_phy_addr);
else
- printk(KERN_INFO "%s: Couldn't detect MII PHY, assuming address 0x01\n",
- dev->name);
+ dev_info(&pdev->dev, "Couldn't detect MII PHY, assuming address 0x01\n");
+
return 0;
-err_iounmap:
- iounmap(lp->mmio);
err_free_dev:
free_netdev(dev);
@@ -1970,6 +1936,29 @@ err_disable_pdev:
}
+static void amd8111e_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (dev) {
+ unregister_netdev(dev);
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ }
+}
+
+static const struct pci_device_id amd8111e_pci_tbl[] = {
+ {
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = PCI_DEVICE_ID_AMD8111E_7462,
+ },
+ {
+ .vendor = 0,
+ }
+};
+MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
+
static struct pci_driver amd8111e_driver = {
.name = MODULE_NAME,
.id_table = amd8111e_pci_tbl,
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index a78e4c136959..31c48a7ac2b6 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -89,6 +89,124 @@ MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+/* AU1000 MAC registers and bits */
+#define MAC_CONTROL 0x0
+# define MAC_RX_ENABLE (1 << 2)
+# define MAC_TX_ENABLE (1 << 3)
+# define MAC_DEF_CHECK (1 << 5)
+# define MAC_SET_BL(X) (((X) & 0x3) << 6)
+# define MAC_AUTO_PAD (1 << 8)
+# define MAC_DISABLE_RETRY (1 << 10)
+# define MAC_DISABLE_BCAST (1 << 11)
+# define MAC_LATE_COL (1 << 12)
+# define MAC_HASH_MODE (1 << 13)
+# define MAC_HASH_ONLY (1 << 15)
+# define MAC_PASS_ALL (1 << 16)
+# define MAC_INVERSE_FILTER (1 << 17)
+# define MAC_PROMISCUOUS (1 << 18)
+# define MAC_PASS_ALL_MULTI (1 << 19)
+# define MAC_FULL_DUPLEX (1 << 20)
+# define MAC_NORMAL_MODE 0
+# define MAC_INT_LOOPBACK (1 << 21)
+# define MAC_EXT_LOOPBACK (1 << 22)
+# define MAC_DISABLE_RX_OWN (1 << 23)
+# define MAC_BIG_ENDIAN (1 << 30)
+# define MAC_RX_ALL (1 << 31)
+#define MAC_ADDRESS_HIGH 0x4
+#define MAC_ADDRESS_LOW 0x8
+#define MAC_MCAST_HIGH 0xC
+#define MAC_MCAST_LOW 0x10
+#define MAC_MII_CNTRL 0x14
+# define MAC_MII_BUSY (1 << 0)
+# define MAC_MII_READ 0
+# define MAC_MII_WRITE (1 << 1)
+# define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
+# define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
+#define MAC_MII_DATA 0x18
+#define MAC_FLOW_CNTRL 0x1C
+# define MAC_FLOW_CNTRL_BUSY (1 << 0)
+# define MAC_FLOW_CNTRL_ENABLE (1 << 1)
+# define MAC_PASS_CONTROL (1 << 2)
+# define MAC_SET_PAUSE(X) (((X) & 0xffff) << 16)
+#define MAC_VLAN1_TAG 0x20
+#define MAC_VLAN2_TAG 0x24
+
+/* Ethernet Controller Enable */
+# define MAC_EN_CLOCK_ENABLE (1 << 0)
+# define MAC_EN_RESET0 (1 << 1)
+# define MAC_EN_TOSS (0 << 2)
+# define MAC_EN_CACHEABLE (1 << 3)
+# define MAC_EN_RESET1 (1 << 4)
+# define MAC_EN_RESET2 (1 << 5)
+# define MAC_DMA_RESET (1 << 6)
+
+/* Ethernet Controller DMA Channels */
+/* offsets from MAC_TX_RING_ADDR address */
+#define MAC_TX_BUFF0_STATUS 0x0
+# define TX_FRAME_ABORTED (1 << 0)
+# define TX_JAB_TIMEOUT (1 << 1)
+# define TX_NO_CARRIER (1 << 2)
+# define TX_LOSS_CARRIER (1 << 3)
+# define TX_EXC_DEF (1 << 4)
+# define TX_LATE_COLL_ABORT (1 << 5)
+# define TX_EXC_COLL (1 << 6)
+# define TX_UNDERRUN (1 << 7)
+# define TX_DEFERRED (1 << 8)
+# define TX_LATE_COLL (1 << 9)
+# define TX_COLL_CNT_MASK (0xF << 10)
+# define TX_PKT_RETRY (1 << 31)
+#define MAC_TX_BUFF0_ADDR 0x4
+# define TX_DMA_ENABLE (1 << 0)
+# define TX_T_DONE (1 << 1)
+# define TX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
+#define MAC_TX_BUFF0_LEN 0x8
+#define MAC_TX_BUFF1_STATUS 0x10
+#define MAC_TX_BUFF1_ADDR 0x14
+#define MAC_TX_BUFF1_LEN 0x18
+#define MAC_TX_BUFF2_STATUS 0x20
+#define MAC_TX_BUFF2_ADDR 0x24
+#define MAC_TX_BUFF2_LEN 0x28
+#define MAC_TX_BUFF3_STATUS 0x30
+#define MAC_TX_BUFF3_ADDR 0x34
+#define MAC_TX_BUFF3_LEN 0x38
+
+/* offsets from MAC_RX_RING_ADDR */
+#define MAC_RX_BUFF0_STATUS 0x0
+# define RX_FRAME_LEN_MASK 0x3fff
+# define RX_WDOG_TIMER (1 << 14)
+# define RX_RUNT (1 << 15)
+# define RX_OVERLEN (1 << 16)
+# define RX_COLL (1 << 17)
+# define RX_ETHER (1 << 18)
+# define RX_MII_ERROR (1 << 19)
+# define RX_DRIBBLING (1 << 20)
+# define RX_CRC_ERROR (1 << 21)
+# define RX_VLAN1 (1 << 22)
+# define RX_VLAN2 (1 << 23)
+# define RX_LEN_ERROR (1 << 24)
+# define RX_CNTRL_FRAME (1 << 25)
+# define RX_U_CNTRL_FRAME (1 << 26)
+# define RX_MCAST_FRAME (1 << 27)
+# define RX_BCAST_FRAME (1 << 28)
+# define RX_FILTER_FAIL (1 << 29)
+# define RX_PACKET_FILTER (1 << 30)
+# define RX_MISSED_FRAME (1 << 31)
+
+# define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN | \
+ RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
+ RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
+#define MAC_RX_BUFF0_ADDR 0x4
+# define RX_DMA_ENABLE (1 << 0)
+# define RX_T_DONE (1 << 1)
+# define RX_GET_DMA_BUFFER(X) (((X) >> 2) & 0x3)
+# define RX_SET_BUFF_ADDR(X) ((X) & 0xffffffc0)
+#define MAC_RX_BUFF1_STATUS 0x10
+#define MAC_RX_BUFF1_ADDR 0x14
+#define MAC_RX_BUFF2_STATUS 0x20
+#define MAC_RX_BUFF2_ADDR 0x24
+#define MAC_RX_BUFF3_STATUS 0x30
+#define MAC_RX_BUFF3_ADDR 0x34
+
/*
* Theory of operation
*
@@ -152,10 +270,12 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
if (force_reset || (!aup->mac_enabled)) {
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
- au_sync_delay(2);
+ wmb(); /* drain writebuffer */
+ mdelay(2);
writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
| MAC_EN_CLOCK_ENABLE), aup->enable);
- au_sync_delay(2);
+ wmb(); /* drain writebuffer */
+ mdelay(2);
aup->mac_enabled = 1;
}
@@ -273,7 +393,8 @@ static void au1000_hard_stop(struct net_device *dev)
reg = readl(&aup->mac->control);
reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
writel(reg, &aup->mac->control);
- au_sync_delay(10);
+ wmb(); /* drain writebuffer */
+ mdelay(10);
}
static void au1000_enable_rx_tx(struct net_device *dev)
@@ -286,7 +407,8 @@ static void au1000_enable_rx_tx(struct net_device *dev)
reg = readl(&aup->mac->control);
reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
writel(reg, &aup->mac->control);
- au_sync_delay(10);
+ wmb(); /* drain writebuffer */
+ mdelay(10);
}
static void
@@ -336,7 +458,8 @@ au1000_adjust_link(struct net_device *dev)
reg |= MAC_DISABLE_RX_OWN;
}
writel(reg, &aup->mac->control);
- au_sync_delay(1);
+ wmb(); /* drain writebuffer */
+ mdelay(1);
au1000_enable_rx_tx(dev);
aup->old_duplex = phydev->duplex;
@@ -500,9 +623,11 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
au1000_hard_stop(dev);
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
- au_sync_delay(2);
+ wmb(); /* drain writebuffer */
+ mdelay(2);
writel(0, aup->enable);
- au_sync_delay(2);
+ wmb(); /* drain writebuffer */
+ mdelay(2);
aup->tx_full = 0;
for (i = 0; i < NUM_RX_DMA; i++) {
@@ -652,7 +777,7 @@ static int au1000_init(struct net_device *dev)
for (i = 0; i < NUM_RX_DMA; i++)
aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
- au_sync();
+ wmb(); /* drain writebuffer */
control = MAC_RX_ENABLE | MAC_TX_ENABLE;
#ifndef CONFIG_CPU_LITTLE_ENDIAN
@@ -669,7 +794,7 @@ static int au1000_init(struct net_device *dev)
writel(control, &aup->mac->control);
writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
- au_sync();
+ wmb(); /* drain writebuffer */
spin_unlock_irqrestore(&aup->lock, flags);
return 0;
@@ -760,7 +885,7 @@ static int au1000_rx(struct net_device *dev)
}
prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
- au_sync();
+ wmb(); /* drain writebuffer */
/* next descriptor */
prxd = aup->rx_dma_ring[aup->rx_head];
@@ -808,7 +933,7 @@ static void au1000_tx_ack(struct net_device *dev)
au1000_update_tx_stats(dev, ptxd->status);
ptxd->buff_stat &= ~TX_T_DONE;
ptxd->len = 0;
- au_sync();
+ wmb(); /* drain writebuffer */
aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -939,7 +1064,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev)
ps->tx_bytes += ptxd->len;
ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
- au_sync();
+ wmb(); /* drain writebuffer */
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
return NETDEV_TX_OK;
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 57397295887c..b584b78237df 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -475,7 +475,7 @@ static void lance_init_ring(struct net_device *dev)
*lib_ptr(ib, rx_ptr, lp->type) = leptr;
if (ZERO)
printk("RX ptr: %8.8x(%8.8x)\n",
- leptr, lib_off(brx_ring, lp->type));
+ leptr, (uint)lib_off(brx_ring, lp->type));
/* Setup tx descriptor pointer */
leptr = offsetof(struct lance_init_block, btx_ring);
@@ -484,7 +484,7 @@ static void lance_init_ring(struct net_device *dev)
*lib_ptr(ib, tx_ptr, lp->type) = leptr;
if (ZERO)
printk("TX ptr: %8.8x(%8.8x)\n",
- leptr, lib_off(btx_ring, lp->type));
+ leptr, (uint)lib_off(btx_ring, lp->type));
if (ZERO)
printk("TX rings:\n");
@@ -499,8 +499,8 @@ static void lance_init_ring(struct net_device *dev)
/* The ones required by tmd2 */
*lib_ptr(ib, btx_ring[i].misc, lp->type) = 0;
if (i < 3 && ZERO)
- printk("%d: 0x%8.8x(0x%8.8x)\n",
- i, leptr, (uint)lp->tx_buf_ptr_cpu[i]);
+ printk("%d: %8.8x(%p)\n",
+ i, leptr, lp->tx_buf_ptr_cpu[i]);
}
/* Setup the Rx ring entries */
@@ -516,8 +516,8 @@ static void lance_init_ring(struct net_device *dev)
0xf000;
*lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0;
if (i < 3 && ZERO)
- printk("%d: 0x%8.8x(0x%8.8x)\n",
- i, leptr, (uint)lp->rx_buf_ptr_cpu[i]);
+ printk("%d: %8.8x(%p)\n",
+ i, leptr, lp->rx_buf_ptr_cpu[i]);
}
iob();
}
diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c
index e7cc9174e364..e2e3aaf501a2 100644
--- a/drivers/net/ethernet/amd/pcnet32.c
+++ b/drivers/net/ethernet/amd/pcnet32.c
@@ -61,7 +61,7 @@ static const char *const version =
/*
* PCI device identifiers for "new style" Linux PCI Device Drivers
*/
-static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = {
+static const struct pci_device_id pcnet32_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
@@ -481,37 +481,32 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev,
dma_addr_t *new_dma_addr_list;
struct pcnet32_tx_head *new_tx_ring;
struct sk_buff **new_skb_list;
+ unsigned int entries = BIT(size);
pcnet32_purge_tx_ring(dev);
- new_tx_ring = pci_alloc_consistent(lp->pci_dev,
- sizeof(struct pcnet32_tx_head) *
- (1 << size),
- &new_ring_dma_addr);
- if (new_tx_ring == NULL) {
- netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+ new_tx_ring =
+ pci_zalloc_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_tx_head) * entries,
+ &new_ring_dma_addr);
+ if (new_tx_ring == NULL)
return;
- }
- memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
- new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t),
- GFP_ATOMIC);
+ new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
if (!new_dma_addr_list)
goto free_new_tx_ring;
- new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *),
- GFP_ATOMIC);
+ new_skb_list = kcalloc(entries, sizeof(struct sk_buff *), GFP_ATOMIC);
if (!new_skb_list)
goto free_new_lists;
kfree(lp->tx_skbuff);
kfree(lp->tx_dma_addr);
pci_free_consistent(lp->pci_dev,
- sizeof(struct pcnet32_tx_head) *
- lp->tx_ring_size, lp->tx_ring,
- lp->tx_ring_dma_addr);
+ sizeof(struct pcnet32_tx_head) * lp->tx_ring_size,
+ lp->tx_ring, lp->tx_ring_dma_addr);
- lp->tx_ring_size = (1 << size);
+ lp->tx_ring_size = entries;
lp->tx_mod_mask = lp->tx_ring_size - 1;
lp->tx_len_bits = (size << 12);
lp->tx_ring = new_tx_ring;
@@ -524,8 +519,7 @@ free_new_lists:
kfree(new_dma_addr_list);
free_new_tx_ring:
pci_free_consistent(lp->pci_dev,
- sizeof(struct pcnet32_tx_head) *
- (1 << size),
+ sizeof(struct pcnet32_tx_head) * entries,
new_tx_ring,
new_ring_dma_addr);
}
@@ -549,17 +543,14 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
struct pcnet32_rx_head *new_rx_ring;
struct sk_buff **new_skb_list;
int new, overlap;
- unsigned int entries = 1 << size;
+ unsigned int entries = BIT(size);
- new_rx_ring = pci_alloc_consistent(lp->pci_dev,
- sizeof(struct pcnet32_rx_head) *
- entries,
- &new_ring_dma_addr);
- if (new_rx_ring == NULL) {
- netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
+ new_rx_ring =
+ pci_zalloc_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_rx_head) * entries,
+ &new_ring_dma_addr);
+ if (new_rx_ring == NULL)
return;
- }
- memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * entries);
new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
if (!new_dma_addr_list)
diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile
index 26cf9af1642f..171a7e68048d 100644
--- a/drivers/net/ethernet/amd/xgbe/Makefile
+++ b/drivers/net/ethernet/amd/xgbe/Makefile
@@ -1,6 +1,8 @@
obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
- xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o
+ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
+ xgbe-ptp.o
+amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index bf462ee86f5c..cc25a3a9e7cf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -170,6 +170,8 @@
#define DMA_MR_SWR_WIDTH 1
#define DMA_SBMR_EAME_INDEX 11
#define DMA_SBMR_EAME_WIDTH 1
+#define DMA_SBMR_BLEN_256_INDEX 7
+#define DMA_SBMR_BLEN_256_WIDTH 1
#define DMA_SBMR_UNDEF_INDEX 0
#define DMA_SBMR_UNDEF_WIDTH 1
@@ -276,13 +278,6 @@
#define MAC_PFR 0x0008
#define MAC_WTR 0x000c
#define MAC_HTR0 0x0010
-#define MAC_HTR1 0x0014
-#define MAC_HTR2 0x0018
-#define MAC_HTR3 0x001c
-#define MAC_HTR4 0x0020
-#define MAC_HTR5 0x0024
-#define MAC_HTR6 0x0028
-#define MAC_HTR7 0x002c
#define MAC_VLANTR 0x0050
#define MAC_VLANHTR 0x0058
#define MAC_VLANIR 0x0060
@@ -312,9 +307,23 @@
#define MAC_MACA0LR 0x0304
#define MAC_MACA1HR 0x0308
#define MAC_MACA1LR 0x030c
+#define MAC_TSCR 0x0d00
+#define MAC_SSIR 0x0d04
+#define MAC_STSR 0x0d08
+#define MAC_STNR 0x0d0c
+#define MAC_STSUR 0x0d10
+#define MAC_STNUR 0x0d14
+#define MAC_TSAR 0x0d18
+#define MAC_TSSR 0x0d20
+#define MAC_TXSNR 0x0d30
+#define MAC_TXSSR 0x0d34
#define MAC_QTFCR_INC 4
#define MAC_MACA_INC 4
+#define MAC_HTR_INC 4
+
+#define MAC_RQC2_INC 4
+#define MAC_RQC2_Q_PER_REG 4
/* MAC register entry bit positions and sizes */
#define MAC_HWF0R_ADDMACADRSEL_INDEX 18
@@ -355,6 +364,8 @@
#define MAC_HWF1R_HASHTBLSZ_WIDTH 3
#define MAC_HWF1R_L3L4FNUM_INDEX 27
#define MAC_HWF1R_L3L4FNUM_WIDTH 4
+#define MAC_HWF1R_NUMTC_INDEX 21
+#define MAC_HWF1R_NUMTC_WIDTH 3
#define MAC_HWF1R_RSSEN_INDEX 20
#define MAC_HWF1R_RSSEN_WIDTH 1
#define MAC_HWF1R_RXFIFOSIZE_INDEX 0
@@ -377,22 +388,30 @@
#define MAC_HWF2R_TXCHCNT_WIDTH 4
#define MAC_HWF2R_TXQCNT_INDEX 6
#define MAC_HWF2R_TXQCNT_WIDTH 4
+#define MAC_IER_TSIE_INDEX 12
+#define MAC_IER_TSIE_WIDTH 1
#define MAC_ISR_MMCRXIS_INDEX 9
#define MAC_ISR_MMCRXIS_WIDTH 1
#define MAC_ISR_MMCTXIS_INDEX 10
#define MAC_ISR_MMCTXIS_WIDTH 1
#define MAC_ISR_PMTIS_INDEX 4
#define MAC_ISR_PMTIS_WIDTH 1
+#define MAC_ISR_TSIS_INDEX 12
+#define MAC_ISR_TSIS_WIDTH 1
#define MAC_MACA1HR_AE_INDEX 31
#define MAC_MACA1HR_AE_WIDTH 1
#define MAC_PFR_HMC_INDEX 2
#define MAC_PFR_HMC_WIDTH 1
+#define MAC_PFR_HPF_INDEX 10
+#define MAC_PFR_HPF_WIDTH 1
#define MAC_PFR_HUC_INDEX 1
#define MAC_PFR_HUC_WIDTH 1
#define MAC_PFR_PM_INDEX 4
#define MAC_PFR_PM_WIDTH 1
#define MAC_PFR_PR_INDEX 0
#define MAC_PFR_PR_WIDTH 1
+#define MAC_PFR_VTFE_INDEX 16
+#define MAC_PFR_VTFE_WIDTH 1
#define MAC_PMTCSR_MGKPKTEN_INDEX 1
#define MAC_PMTCSR_MGKPKTEN_WIDTH 1
#define MAC_PMTCSR_PWRDWN_INDEX 0
@@ -419,24 +438,80 @@
#define MAC_RCR_LM_WIDTH 1
#define MAC_RCR_RE_INDEX 0
#define MAC_RCR_RE_WIDTH 1
+#define MAC_RFCR_PFCE_INDEX 8
+#define MAC_RFCR_PFCE_WIDTH 1
#define MAC_RFCR_RFE_INDEX 0
#define MAC_RFCR_RFE_WIDTH 1
+#define MAC_RFCR_UP_INDEX 1
+#define MAC_RFCR_UP_WIDTH 1
#define MAC_RQC0R_RXQ0EN_INDEX 0
#define MAC_RQC0R_RXQ0EN_WIDTH 2
+#define MAC_SSIR_SNSINC_INDEX 8
+#define MAC_SSIR_SNSINC_WIDTH 8
+#define MAC_SSIR_SSINC_INDEX 16
+#define MAC_SSIR_SSINC_WIDTH 8
#define MAC_TCR_SS_INDEX 29
#define MAC_TCR_SS_WIDTH 2
#define MAC_TCR_TE_INDEX 0
#define MAC_TCR_TE_WIDTH 1
+#define MAC_TSCR_AV8021ASMEN_INDEX 28
+#define MAC_TSCR_AV8021ASMEN_WIDTH 1
+#define MAC_TSCR_SNAPTYPSEL_INDEX 16
+#define MAC_TSCR_SNAPTYPSEL_WIDTH 2
+#define MAC_TSCR_TSADDREG_INDEX 5
+#define MAC_TSCR_TSADDREG_WIDTH 1
+#define MAC_TSCR_TSCFUPDT_INDEX 1
+#define MAC_TSCR_TSCFUPDT_WIDTH 1
+#define MAC_TSCR_TSCTRLSSR_INDEX 9
+#define MAC_TSCR_TSCTRLSSR_WIDTH 1
+#define MAC_TSCR_TSENA_INDEX 0
+#define MAC_TSCR_TSENA_WIDTH 1
+#define MAC_TSCR_TSENALL_INDEX 8
+#define MAC_TSCR_TSENALL_WIDTH 1
+#define MAC_TSCR_TSEVNTENA_INDEX 14
+#define MAC_TSCR_TSEVNTENA_WIDTH 1
+#define MAC_TSCR_TSINIT_INDEX 2
+#define MAC_TSCR_TSINIT_WIDTH 1
+#define MAC_TSCR_TSIPENA_INDEX 11
+#define MAC_TSCR_TSIPENA_WIDTH 1
+#define MAC_TSCR_TSIPV4ENA_INDEX 13
+#define MAC_TSCR_TSIPV4ENA_WIDTH 1
+#define MAC_TSCR_TSIPV6ENA_INDEX 12
+#define MAC_TSCR_TSIPV6ENA_WIDTH 1
+#define MAC_TSCR_TSMSTRENA_INDEX 15
+#define MAC_TSCR_TSMSTRENA_WIDTH 1
+#define MAC_TSCR_TSVER2ENA_INDEX 10
+#define MAC_TSCR_TSVER2ENA_WIDTH 1
+#define MAC_TSCR_TXTSSTSM_INDEX 24
+#define MAC_TSCR_TXTSSTSM_WIDTH 1
+#define MAC_TSSR_TXTSC_INDEX 15
+#define MAC_TSSR_TXTSC_WIDTH 1
+#define MAC_TXSNR_TXTSSTSMIS_INDEX 31
+#define MAC_TXSNR_TXTSSTSMIS_WIDTH 1
+#define MAC_VLANHTR_VLHT_INDEX 0
+#define MAC_VLANHTR_VLHT_WIDTH 16
+#define MAC_VLANIR_VLTI_INDEX 20
+#define MAC_VLANIR_VLTI_WIDTH 1
+#define MAC_VLANIR_CSVL_INDEX 19
+#define MAC_VLANIR_CSVL_WIDTH 1
#define MAC_VLANTR_DOVLTC_INDEX 20
#define MAC_VLANTR_DOVLTC_WIDTH 1
#define MAC_VLANTR_ERSVLM_INDEX 19
#define MAC_VLANTR_ERSVLM_WIDTH 1
#define MAC_VLANTR_ESVL_INDEX 18
#define MAC_VLANTR_ESVL_WIDTH 1
+#define MAC_VLANTR_ETV_INDEX 16
+#define MAC_VLANTR_ETV_WIDTH 1
#define MAC_VLANTR_EVLS_INDEX 21
#define MAC_VLANTR_EVLS_WIDTH 2
#define MAC_VLANTR_EVLRXS_INDEX 24
#define MAC_VLANTR_EVLRXS_WIDTH 1
+#define MAC_VLANTR_VL_INDEX 0
+#define MAC_VLANTR_VL_WIDTH 16
+#define MAC_VLANTR_VTHM_INDEX 25
+#define MAC_VLANTR_VTHM_WIDTH 1
+#define MAC_VLANTR_VTIM_INDEX 17
+#define MAC_VLANTR_VTIM_WIDTH 1
#define MAC_VR_DEVID_INDEX 8
#define MAC_VR_DEVID_WIDTH 8
#define MAC_VR_SNPSVER_INDEX 0
@@ -638,6 +713,8 @@
#define MTL_RQDCM_INC 4
#define MTL_RQDCM_Q_PER_REG 4
+#define MTL_TCPM_INC 4
+#define MTL_TCPM_TC_PER_REG 4
/* MTL register entry bit positions and sizes */
#define MTL_OMR_ETSALG_INDEX 5
@@ -656,9 +733,6 @@
#define MTL_Q_TQOMR 0x00
#define MTL_Q_TQUR 0x04
#define MTL_Q_TQDR 0x08
-#define MTL_Q_TCECR 0x10
-#define MTL_Q_TCESR 0x14
-#define MTL_Q_TCQWR 0x18
#define MTL_Q_RQOMR 0x40
#define MTL_Q_RQMPOCR 0x44
#define MTL_Q_RQDR 0x4c
@@ -666,8 +740,6 @@
#define MTL_Q_ISR 0x74
/* MTL queue register entry bit positions and sizes */
-#define MTL_Q_TCQWR_QW_INDEX 0
-#define MTL_Q_TCQWR_QW_WIDTH 21
#define MTL_Q_RQOMR_EHFC_INDEX 7
#define MTL_Q_RQOMR_EHFC_WIDTH 1
#define MTL_Q_RQOMR_RFA_INDEX 8
@@ -682,6 +754,8 @@
#define MTL_Q_RQOMR_RTC_WIDTH 2
#define MTL_Q_TQOMR_FTQ_INDEX 0
#define MTL_Q_TQOMR_FTQ_WIDTH 1
+#define MTL_Q_TQOMR_Q2TCMAP_INDEX 8
+#define MTL_Q_TQOMR_Q2TCMAP_WIDTH 3
#define MTL_Q_TQOMR_TQS_INDEX 16
#define MTL_Q_TQOMR_TQS_WIDTH 10
#define MTL_Q_TQOMR_TSF_INDEX 1
@@ -728,10 +802,14 @@
#define MTL_TC_INC MTL_Q_INC
#define MTL_TC_ETSCR 0x10
+#define MTL_TC_ETSSR 0x14
+#define MTL_TC_QWR 0x18
/* MTL traffic class register entry bit positions and sizes */
#define MTL_TC_ETSCR_TSA_INDEX 0
#define MTL_TC_ETSCR_TSA_WIDTH 2
+#define MTL_TC_QWR_QW_INDEX 0
+#define MTL_TC_QWR_QW_WIDTH 21
/* MTL traffic class register value */
#define MTL_TSA_SP 0x00
@@ -764,9 +842,19 @@
#define RX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_INDEX 2
#define RX_PACKET_ATTRIBUTES_INCOMPLETE_WIDTH 1
+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_INDEX 3
+#define RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_WIDTH 1
+#define RX_PACKET_ATTRIBUTES_CONTEXT_INDEX 4
+#define RX_PACKET_ATTRIBUTES_CONTEXT_WIDTH 1
+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_INDEX 5
+#define RX_PACKET_ATTRIBUTES_RX_TSTAMP_WIDTH 1
#define RX_NORMAL_DESC0_OVT_INDEX 0
#define RX_NORMAL_DESC0_OVT_WIDTH 16
+#define RX_NORMAL_DESC3_CDA_INDEX 27
+#define RX_NORMAL_DESC3_CDA_WIDTH 1
+#define RX_NORMAL_DESC3_CTXT_INDEX 30
+#define RX_NORMAL_DESC3_CTXT_WIDTH 1
#define RX_NORMAL_DESC3_ES_INDEX 15
#define RX_NORMAL_DESC3_ES_WIDTH 1
#define RX_NORMAL_DESC3_ETLT_INDEX 16
@@ -780,12 +868,19 @@
#define RX_NORMAL_DESC3_PL_INDEX 0
#define RX_NORMAL_DESC3_PL_WIDTH 14
+#define RX_CONTEXT_DESC3_TSA_INDEX 4
+#define RX_CONTEXT_DESC3_TSA_WIDTH 1
+#define RX_CONTEXT_DESC3_TSD_INDEX 6
+#define RX_CONTEXT_DESC3_TSD_WIDTH 1
+
#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_INDEX 0
#define TX_PACKET_ATTRIBUTES_CSUM_ENABLE_WIDTH 1
#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_INDEX 1
#define TX_PACKET_ATTRIBUTES_TSO_ENABLE_WIDTH 1
#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_INDEX 2
#define TX_PACKET_ATTRIBUTES_VLAN_CTAG_WIDTH 1
+#define TX_PACKET_ATTRIBUTES_PTP_INDEX 3
+#define TX_PACKET_ATTRIBUTES_PTP_WIDTH 1
#define TX_CONTEXT_DESC2_MSS_INDEX 0
#define TX_CONTEXT_DESC2_MSS_WIDTH 15
@@ -802,6 +897,8 @@
#define TX_NORMAL_DESC2_HL_B1L_WIDTH 14
#define TX_NORMAL_DESC2_IC_INDEX 31
#define TX_NORMAL_DESC2_IC_WIDTH 1
+#define TX_NORMAL_DESC2_TTSE_INDEX 30
+#define TX_NORMAL_DESC2_TTSE_WIDTH 1
#define TX_NORMAL_DESC2_VTIR_INDEX 14
#define TX_NORMAL_DESC2_VTIR_WIDTH 2
#define TX_NORMAL_DESC3_CIC_INDEX 16
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c b/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c
new file mode 100644
index 000000000000..7d6a49b24321
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dcb.c
@@ -0,0 +1,270 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file 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/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and the Software, to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and the Software, to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/netdevice.h>
+#include <net/dcbnl.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+
+static int xgbe_dcb_ieee_getets(struct net_device *netdev,
+ struct ieee_ets *ets)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ /* Set number of supported traffic classes */
+ ets->ets_cap = pdata->hw_feat.tc_cnt;
+
+ if (pdata->ets) {
+ ets->cbs = pdata->ets->cbs;
+ memcpy(ets->tc_tx_bw, pdata->ets->tc_tx_bw,
+ sizeof(ets->tc_tx_bw));
+ memcpy(ets->tc_tsa, pdata->ets->tc_tsa,
+ sizeof(ets->tc_tsa));
+ memcpy(ets->prio_tc, pdata->ets->prio_tc,
+ sizeof(ets->prio_tc));
+ }
+
+ return 0;
+}
+
+static int xgbe_dcb_ieee_setets(struct net_device *netdev,
+ struct ieee_ets *ets)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ unsigned int i, tc_ets, tc_ets_weight;
+
+ tc_ets = 0;
+ tc_ets_weight = 0;
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ DBGPR(" TC%u: tx_bw=%hhu, rx_bw=%hhu, tsa=%hhu\n", i,
+ ets->tc_tx_bw[i], ets->tc_rx_bw[i], ets->tc_tsa[i]);
+ DBGPR(" PRIO%u: TC=%hhu\n", i, ets->prio_tc[i]);
+
+ if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) &&
+ (i >= pdata->hw_feat.tc_cnt))
+ return -EINVAL;
+
+ if (ets->prio_tc[i] >= pdata->hw_feat.tc_cnt)
+ return -EINVAL;
+
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ tc_ets = 1;
+ tc_ets_weight += ets->tc_tx_bw[i];
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* Weights must add up to 100% */
+ if (tc_ets && (tc_ets_weight != 100))
+ return -EINVAL;
+
+ if (!pdata->ets) {
+ pdata->ets = devm_kzalloc(pdata->dev, sizeof(*pdata->ets),
+ GFP_KERNEL);
+ if (!pdata->ets)
+ return -ENOMEM;
+ }
+
+ memcpy(pdata->ets, ets, sizeof(*pdata->ets));
+
+ pdata->hw_if.config_dcb_tc(pdata);
+
+ return 0;
+}
+
+static int xgbe_dcb_ieee_getpfc(struct net_device *netdev,
+ struct ieee_pfc *pfc)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ /* Set number of supported PFC traffic classes */
+ pfc->pfc_cap = pdata->hw_feat.tc_cnt;
+
+ if (pdata->pfc) {
+ pfc->pfc_en = pdata->pfc->pfc_en;
+ pfc->mbc = pdata->pfc->mbc;
+ pfc->delay = pdata->pfc->delay;
+ }
+
+ return 0;
+}
+
+static int xgbe_dcb_ieee_setpfc(struct net_device *netdev,
+ struct ieee_pfc *pfc)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ DBGPR(" cap=%hhu, en=%hhx, mbc=%hhu, delay=%hhu\n",
+ pfc->pfc_cap, pfc->pfc_en, pfc->mbc, pfc->delay);
+
+ if (!pdata->pfc) {
+ pdata->pfc = devm_kzalloc(pdata->dev, sizeof(*pdata->pfc),
+ GFP_KERNEL);
+ if (!pdata->pfc)
+ return -ENOMEM;
+ }
+
+ memcpy(pdata->pfc, pfc, sizeof(*pdata->pfc));
+
+ pdata->hw_if.config_dcb_pfc(pdata);
+
+ return 0;
+}
+
+static u8 xgbe_dcb_getdcbx(struct net_device *netdev)
+{
+ return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+}
+
+static u8 xgbe_dcb_setdcbx(struct net_device *netdev, u8 dcbx)
+{
+ u8 support = xgbe_dcb_getdcbx(netdev);
+
+ DBGPR(" DCBX=%#hhx\n", dcbx);
+
+ if (dcbx & ~support)
+ return 1;
+
+ if ((dcbx & support) != support)
+ return 1;
+
+ return 0;
+}
+
+static const struct dcbnl_rtnl_ops xgbe_dcbnl_ops = {
+ /* IEEE 802.1Qaz std */
+ .ieee_getets = xgbe_dcb_ieee_getets,
+ .ieee_setets = xgbe_dcb_ieee_setets,
+ .ieee_getpfc = xgbe_dcb_ieee_getpfc,
+ .ieee_setpfc = xgbe_dcb_ieee_setpfc,
+
+ /* DCBX configuration */
+ .getdcbx = xgbe_dcb_getdcbx,
+ .setdcbx = xgbe_dcb_setdcbx,
+};
+
+const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void)
+{
+ return &xgbe_dcbnl_ops;
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
index 6bb76d5c817b..346592dca33c 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
@@ -151,7 +151,7 @@ static ssize_t xgbe_common_write(const char __user *buffer, size_t count,
{
char workarea[32];
ssize_t len;
- unsigned int scan_value;
+ int ret;
if (*ppos != 0)
return 0;
@@ -165,9 +165,8 @@ static ssize_t xgbe_common_write(const char __user *buffer, size_t count,
return len;
workarea[len] = '\0';
- if (sscanf(workarea, "%x", &scan_value) == 1)
- *value = scan_value;
- else
+ ret = kstrtouint(workarea, 16, value);
+ if (ret)
return -EIO;
return len;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 6f1c85956d50..1c5d62e8dab6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -131,7 +131,7 @@ static void xgbe_free_ring(struct xgbe_prv_data *pdata,
if (ring->rdata) {
for (i = 0; i < ring->rdesc_count; i++) {
- rdata = GET_DESC_DATA(ring, i);
+ rdata = XGBE_GET_DESC_DATA(ring, i);
xgbe_unmap_skb(pdata, rdata);
}
@@ -256,7 +256,7 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
rdesc_dma = ring->rdesc_dma;
for (j = 0; j < ring->rdesc_count; j++) {
- rdata = GET_DESC_DATA(ring, j);
+ rdata = XGBE_GET_DESC_DATA(ring, j);
rdata->rdesc = rdesc;
rdata->rdesc_dma = rdesc_dma;
@@ -298,7 +298,7 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
rdesc_dma = ring->rdesc_dma;
for (j = 0; j < ring->rdesc_count; j++) {
- rdata = GET_DESC_DATA(ring, j);
+ rdata = XGBE_GET_DESC_DATA(ring, j);
rdata->rdesc = rdesc;
rdata->rdesc_dma = rdesc_dma;
@@ -359,6 +359,15 @@ static void xgbe_unmap_skb(struct xgbe_prv_data *pdata,
rdata->len = 0;
rdata->interrupt = 0;
rdata->mapped_as_page = 0;
+
+ if (rdata->state_saved) {
+ rdata->state_saved = 0;
+ rdata->state.incomplete = 0;
+ rdata->state.context_next = 0;
+ rdata->state.skb = NULL;
+ rdata->state.len = 0;
+ rdata->state.error = 0;
+ }
}
static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
@@ -392,7 +401,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
if ((tso && (packet->mss != ring->tx.cur_mss)) ||
(vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag)))
cur_index++;
- rdata = GET_DESC_DATA(ring, cur_index);
+ rdata = XGBE_GET_DESC_DATA(ring, cur_index);
if (tso) {
DBGPR(" TSO packet\n");
@@ -413,12 +422,12 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
packet->length += packet->header_len;
cur_index++;
- rdata = GET_DESC_DATA(ring, cur_index);
+ rdata = XGBE_GET_DESC_DATA(ring, cur_index);
}
/* Map the (remainder of the) packet */
for (datalen = skb_headlen(skb) - offset; datalen; ) {
- len = min_t(unsigned int, datalen, TX_MAX_BUF_SIZE);
+ len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE);
skb_dma = dma_map_single(pdata->dev, skb->data + offset, len,
DMA_TO_DEVICE);
@@ -437,7 +446,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
packet->length += len;
cur_index++;
- rdata = GET_DESC_DATA(ring, cur_index);
+ rdata = XGBE_GET_DESC_DATA(ring, cur_index);
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -447,7 +456,8 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
offset = 0;
for (datalen = skb_frag_size(frag); datalen; ) {
- len = min_t(unsigned int, datalen, TX_MAX_BUF_SIZE);
+ len = min_t(unsigned int, datalen,
+ XGBE_TX_MAX_BUF_SIZE);
skb_dma = skb_frag_dma_map(pdata->dev, frag, offset,
len, DMA_TO_DEVICE);
@@ -468,7 +478,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
packet->length += len;
cur_index++;
- rdata = GET_DESC_DATA(ring, cur_index);
+ rdata = XGBE_GET_DESC_DATA(ring, cur_index);
}
}
@@ -484,7 +494,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
err_out:
while (start_index < cur_index) {
- rdata = GET_DESC_DATA(ring, start_index++);
+ rdata = XGBE_GET_DESC_DATA(ring, start_index++);
xgbe_unmap_skb(pdata, rdata);
}
@@ -507,7 +517,7 @@ static void xgbe_realloc_skb(struct xgbe_channel *channel)
ring->rx.realloc_index);
for (i = 0; i < ring->dirty; i++) {
- rdata = GET_DESC_DATA(ring, ring->rx.realloc_index);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index);
/* Reset rdata values */
xgbe_unmap_skb(pdata, rdata);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 002293b0819d..edaca4496264 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -116,6 +116,8 @@
#include <linux/phy.h>
#include <linux/clk.h>
+#include <linux/bitrev.h>
+#include <linux/crc32.h>
#include "xgbe.h"
#include "xgbe-common.h"
@@ -129,7 +131,7 @@ static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata,
DBGPR("-->xgbe_usec_to_riwt\n");
- rate = clk_get_rate(pdata->sysclock);
+ rate = clk_get_rate(pdata->sysclk);
/*
* Convert the input usec value to the watchdog timer value. Each
@@ -152,7 +154,7 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata,
DBGPR("-->xgbe_riwt_to_usec\n");
- rate = clk_get_rate(pdata->sysclock);
+ rate = clk_get_rate(pdata->sysclk);
/*
* Convert the input watchdog timer value to the usec value. Each
@@ -245,7 +247,7 @@ static int xgbe_config_rsf_mode(struct xgbe_prv_data *pdata, unsigned int val)
{
unsigned int i;
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RSF, val);
return 0;
@@ -255,7 +257,7 @@ static int xgbe_config_tsf_mode(struct xgbe_prv_data *pdata, unsigned int val)
{
unsigned int i;
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TSF, val);
return 0;
@@ -266,7 +268,7 @@ static int xgbe_config_rx_threshold(struct xgbe_prv_data *pdata,
{
unsigned int i;
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RTC, val);
return 0;
@@ -277,7 +279,7 @@ static int xgbe_config_tx_threshold(struct xgbe_prv_data *pdata,
{
unsigned int i;
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TTC, val);
return 0;
@@ -341,12 +343,12 @@ static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
unsigned int i;
/* Clear MTL flow control */
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
/* Clear MAC flow control */
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
- q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt, max_q_count);
+ q_count = min_t(unsigned int, pdata->rx_q_count, max_q_count);
reg = MAC_Q0TFCR;
for (i = 0; i < q_count; i++) {
reg_val = XGMAC_IOREAD(pdata, reg);
@@ -366,12 +368,12 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
unsigned int i;
/* Set MTL flow control */
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 1);
/* Set MAC flow control */
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
- q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt, max_q_count);
+ q_count = min_t(unsigned int, pdata->rx_q_count, max_q_count);
reg = MAC_Q0TFCR;
for (i = 0; i < q_count; i++) {
reg_val = XGMAC_IOREAD(pdata, reg);
@@ -405,7 +407,9 @@ static int xgbe_enable_rx_flow_control(struct xgbe_prv_data *pdata)
static int xgbe_config_tx_flow_control(struct xgbe_prv_data *pdata)
{
- if (pdata->tx_pause)
+ struct ieee_pfc *pfc = pdata->pfc;
+
+ if (pdata->tx_pause || (pfc && pfc->pfc_en))
xgbe_enable_tx_flow_control(pdata);
else
xgbe_disable_tx_flow_control(pdata);
@@ -415,7 +419,9 @@ static int xgbe_config_tx_flow_control(struct xgbe_prv_data *pdata)
static int xgbe_config_rx_flow_control(struct xgbe_prv_data *pdata)
{
- if (pdata->rx_pause)
+ struct ieee_pfc *pfc = pdata->pfc;
+
+ if (pdata->rx_pause || (pfc && pfc->pfc_en))
xgbe_enable_rx_flow_control(pdata);
else
xgbe_disable_rx_flow_control(pdata);
@@ -425,8 +431,13 @@ static int xgbe_config_rx_flow_control(struct xgbe_prv_data *pdata)
static void xgbe_config_flow_control(struct xgbe_prv_data *pdata)
{
+ struct ieee_pfc *pfc = pdata->pfc;
+
xgbe_config_tx_flow_control(pdata);
xgbe_config_rx_flow_control(pdata);
+
+ XGMAC_IOWRITE_BITS(pdata, MAC_RFCR, PFCE,
+ (pfc && pfc->pfc_en) ? 1 : 0);
}
static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
@@ -484,14 +495,18 @@ static void xgbe_enable_mtl_interrupts(struct xgbe_prv_data *pdata)
XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, mtl_q_isr);
/* No MTL interrupts to be enabled */
- XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_ISR, 0);
+ XGMAC_MTL_IOWRITE(pdata, i, MTL_Q_IER, 0);
}
}
static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
{
- /* No MAC interrupts to be enabled */
- XGMAC_IOWRITE(pdata, MAC_IER, 0);
+ unsigned int mac_ier = 0;
+
+ /* Enable Timestamp interrupt */
+ XGMAC_SET_BITS(mac_ier, MAC_IER, TSIE, 1);
+
+ XGMAC_IOWRITE(pdata, MAC_IER, mac_ier);
/* Enable all counter interrupts */
XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xff);
@@ -547,24 +562,16 @@ static int xgbe_set_all_multicast_mode(struct xgbe_prv_data *pdata,
return 0;
}
-static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata,
- unsigned int am_mode)
+static void xgbe_set_mac_reg(struct xgbe_prv_data *pdata,
+ struct netdev_hw_addr *ha, unsigned int *mac_reg)
{
- struct netdev_hw_addr *ha;
- unsigned int mac_reg;
unsigned int mac_addr_hi, mac_addr_lo;
u8 *mac_addr;
- unsigned int i;
-
- XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 0);
- XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 0);
- i = 0;
- mac_reg = MAC_MACA1HR;
+ mac_addr_lo = 0;
+ mac_addr_hi = 0;
- netdev_for_each_uc_addr(ha, pdata->netdev) {
- mac_addr_lo = 0;
- mac_addr_hi = 0;
+ if (ha) {
mac_addr = (u8 *)&mac_addr_lo;
mac_addr[0] = ha->addr[0];
mac_addr[1] = ha->addr[1];
@@ -574,54 +581,93 @@ static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata,
mac_addr[0] = ha->addr[4];
mac_addr[1] = ha->addr[5];
- DBGPR(" adding unicast address %pM at 0x%04x\n",
- ha->addr, mac_reg);
+ DBGPR(" adding mac address %pM at 0x%04x\n", ha->addr,
+ *mac_reg);
XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
+ }
- XGMAC_IOWRITE(pdata, mac_reg, mac_addr_hi);
- mac_reg += MAC_MACA_INC;
- XGMAC_IOWRITE(pdata, mac_reg, mac_addr_lo);
- mac_reg += MAC_MACA_INC;
+ XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_hi);
+ *mac_reg += MAC_MACA_INC;
+ XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_lo);
+ *mac_reg += MAC_MACA_INC;
+}
- i++;
- }
+static void xgbe_set_mac_addn_addrs(struct xgbe_prv_data *pdata)
+{
+ struct net_device *netdev = pdata->netdev;
+ struct netdev_hw_addr *ha;
+ unsigned int mac_reg;
+ unsigned int addn_macs;
+
+ mac_reg = MAC_MACA1HR;
+ addn_macs = pdata->hw_feat.addn_mac;
- if (!am_mode) {
- netdev_for_each_mc_addr(ha, pdata->netdev) {
- mac_addr_lo = 0;
- mac_addr_hi = 0;
- mac_addr = (u8 *)&mac_addr_lo;
- mac_addr[0] = ha->addr[0];
- mac_addr[1] = ha->addr[1];
- mac_addr[2] = ha->addr[2];
- mac_addr[3] = ha->addr[3];
- mac_addr = (u8 *)&mac_addr_hi;
- mac_addr[0] = ha->addr[4];
- mac_addr[1] = ha->addr[5];
-
- DBGPR(" adding multicast address %pM at 0x%04x\n",
- ha->addr, mac_reg);
-
- XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
-
- XGMAC_IOWRITE(pdata, mac_reg, mac_addr_hi);
- mac_reg += MAC_MACA_INC;
- XGMAC_IOWRITE(pdata, mac_reg, mac_addr_lo);
- mac_reg += MAC_MACA_INC;
-
- i++;
+ if (netdev_uc_count(netdev) > addn_macs) {
+ xgbe_set_promiscuous_mode(pdata, 1);
+ } else {
+ netdev_for_each_uc_addr(ha, netdev) {
+ xgbe_set_mac_reg(pdata, ha, &mac_reg);
+ addn_macs--;
+ }
+
+ if (netdev_mc_count(netdev) > addn_macs) {
+ xgbe_set_all_multicast_mode(pdata, 1);
+ } else {
+ netdev_for_each_mc_addr(ha, netdev) {
+ xgbe_set_mac_reg(pdata, ha, &mac_reg);
+ addn_macs--;
+ }
}
}
/* Clear remaining additional MAC address entries */
- for (; i < pdata->hw_feat.addn_mac; i++) {
- XGMAC_IOWRITE(pdata, mac_reg, 0);
- mac_reg += MAC_MACA_INC;
- XGMAC_IOWRITE(pdata, mac_reg, 0);
- mac_reg += MAC_MACA_INC;
+ while (addn_macs--)
+ xgbe_set_mac_reg(pdata, NULL, &mac_reg);
+}
+
+static void xgbe_set_mac_hash_table(struct xgbe_prv_data *pdata)
+{
+ struct net_device *netdev = pdata->netdev;
+ struct netdev_hw_addr *ha;
+ unsigned int hash_reg;
+ unsigned int hash_table_shift, hash_table_count;
+ u32 hash_table[XGBE_MAC_HASH_TABLE_SIZE];
+ u32 crc;
+ unsigned int i;
+
+ hash_table_shift = 26 - (pdata->hw_feat.hash_table_size >> 7);
+ hash_table_count = pdata->hw_feat.hash_table_size / 32;
+ memset(hash_table, 0, sizeof(hash_table));
+
+ /* Build the MAC Hash Table register values */
+ netdev_for_each_uc_addr(ha, netdev) {
+ crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
+ crc >>= hash_table_shift;
+ hash_table[crc >> 5] |= (1 << (crc & 0x1f));
+ }
+
+ netdev_for_each_mc_addr(ha, netdev) {
+ crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
+ crc >>= hash_table_shift;
+ hash_table[crc >> 5] |= (1 << (crc & 0x1f));
}
+ /* Set the MAC Hash Table registers */
+ hash_reg = MAC_HTR0;
+ for (i = 0; i < hash_table_count; i++) {
+ XGMAC_IOWRITE(pdata, hash_reg, hash_table[i]);
+ hash_reg += MAC_HTR_INC;
+ }
+}
+
+static int xgbe_add_mac_addresses(struct xgbe_prv_data *pdata)
+{
+ if (pdata->hw_feat.hash_table_size)
+ xgbe_set_mac_hash_table(pdata);
+ else
+ xgbe_set_mac_addn_addrs(pdata);
+
return 0;
}
@@ -738,6 +784,89 @@ static int xgbe_disable_rx_vlan_stripping(struct xgbe_prv_data *pdata)
return 0;
}
+static int xgbe_enable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+{
+ /* Enable VLAN filtering */
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 1);
+
+ /* Enable VLAN Hash Table filtering */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTHM, 1);
+
+ /* Disable VLAN tag inverse matching */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VTIM, 0);
+
+ /* Only filter on the lower 12-bits of the VLAN tag */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, ETV, 1);
+
+ /* In order for the VLAN Hash Table filtering to be effective,
+ * the VLAN tag identifier in the VLAN Tag Register must not
+ * be zero. Set the VLAN tag identifier to "1" to enable the
+ * VLAN Hash Table filtering. This implies that a VLAN tag of
+ * 1 will always pass filtering.
+ */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANTR, VL, 1);
+
+ return 0;
+}
+
+static int xgbe_disable_rx_vlan_filtering(struct xgbe_prv_data *pdata)
+{
+ /* Disable VLAN filtering */
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, VTFE, 0);
+
+ return 0;
+}
+
+#ifndef CRCPOLY_LE
+#define CRCPOLY_LE 0xedb88320
+#endif
+static u32 xgbe_vid_crc32_le(__le16 vid_le)
+{
+ u32 poly = CRCPOLY_LE;
+ u32 crc = ~0;
+ u32 temp = 0;
+ unsigned char *data = (unsigned char *)&vid_le;
+ unsigned char data_byte = 0;
+ int i, bits;
+
+ bits = get_bitmask_order(VLAN_VID_MASK);
+ for (i = 0; i < bits; i++) {
+ if ((i % 8) == 0)
+ data_byte = data[i / 8];
+
+ temp = ((crc & 1) ^ data_byte) & 1;
+ crc >>= 1;
+ data_byte >>= 1;
+
+ if (temp)
+ crc ^= poly;
+ }
+
+ return crc;
+}
+
+static int xgbe_update_vlan_hash_table(struct xgbe_prv_data *pdata)
+{
+ u32 crc;
+ u16 vid;
+ __le16 vid_le;
+ u16 vlan_hash_table = 0;
+
+ /* Generate the VLAN Hash Table value */
+ for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) {
+ /* Get the CRC32 value of the VLAN ID */
+ vid_le = cpu_to_le16(vid);
+ crc = bitrev32(~xgbe_vid_crc32_le(vid_le)) >> 28;
+
+ vlan_hash_table |= (1 << crc);
+ }
+
+ /* Set the VLAN Hash Table filtering register */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANHTR, VLHT, vlan_hash_table);
+
+ return 0;
+}
+
static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata)
{
struct xgbe_ring_desc *rdesc = rdata->rdesc;
@@ -766,7 +895,7 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel)
/* Initialze all descriptors */
for (i = 0; i < ring->rdesc_count; i++) {
- rdata = GET_DESC_DATA(ring, i);
+ rdata = XGBE_GET_DESC_DATA(ring, i);
rdesc = rdata->rdesc;
/* Initialize Tx descriptor
@@ -791,7 +920,7 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel)
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDRLR, ring->rdesc_count - 1);
/* Update the starting address of descriptor ring */
- rdata = GET_DESC_DATA(ring, start_index);
+ rdata = XGBE_GET_DESC_DATA(ring, start_index);
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_HI,
upper_32_bits(rdata->rdesc_dma));
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDLR_LO,
@@ -848,7 +977,7 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
/* Initialize all descriptors */
for (i = 0; i < ring->rdesc_count; i++) {
- rdata = GET_DESC_DATA(ring, i);
+ rdata = XGBE_GET_DESC_DATA(ring, i);
rdesc = rdata->rdesc;
/* Initialize Rx descriptor
@@ -882,20 +1011,194 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel)
XGMAC_DMA_IOWRITE(channel, DMA_CH_RDRLR, ring->rdesc_count - 1);
/* Update the starting address of descriptor ring */
- rdata = GET_DESC_DATA(ring, start_index);
+ rdata = XGBE_GET_DESC_DATA(ring, start_index);
XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_HI,
upper_32_bits(rdata->rdesc_dma));
XGMAC_DMA_IOWRITE(channel, DMA_CH_RDLR_LO,
lower_32_bits(rdata->rdesc_dma));
/* Update the Rx Descriptor Tail Pointer */
- rdata = GET_DESC_DATA(ring, start_index + ring->rdesc_count - 1);
+ rdata = XGBE_GET_DESC_DATA(ring, start_index + ring->rdesc_count - 1);
XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
lower_32_bits(rdata->rdesc_dma));
DBGPR("<--rx_desc_init\n");
}
+static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata,
+ unsigned int addend)
+{
+ /* Set the addend register value and tell the device */
+ XGMAC_IOWRITE(pdata, MAC_TSAR, addend);
+ XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1);
+
+ /* Wait for addend update to complete */
+ while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG))
+ udelay(5);
+}
+
+static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec,
+ unsigned int nsec)
+{
+ /* Set the time values and tell the device */
+ XGMAC_IOWRITE(pdata, MAC_STSUR, sec);
+ XGMAC_IOWRITE(pdata, MAC_STNUR, nsec);
+ XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1);
+
+ /* Wait for time update to complete */
+ while (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT))
+ udelay(5);
+}
+
+static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata)
+{
+ u64 nsec;
+
+ nsec = XGMAC_IOREAD(pdata, MAC_STSR);
+ nsec *= NSEC_PER_SEC;
+ nsec += XGMAC_IOREAD(pdata, MAC_STNR);
+
+ return nsec;
+}
+
+static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
+{
+ unsigned int tx_snr;
+ u64 nsec;
+
+ tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+ if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS))
+ return 0;
+
+ nsec = XGMAC_IOREAD(pdata, MAC_TXSSR);
+ nsec *= NSEC_PER_SEC;
+ nsec += tx_snr;
+
+ return nsec;
+}
+
+static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet,
+ struct xgbe_ring_desc *rdesc)
+{
+ u64 nsec;
+
+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) &&
+ !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) {
+ nsec = le32_to_cpu(rdesc->desc1);
+ nsec <<= 32;
+ nsec |= le32_to_cpu(rdesc->desc0);
+ if (nsec != 0xffffffffffffffffULL) {
+ packet->rx_tstamp = nsec;
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+ RX_TSTAMP, 1);
+ }
+ }
+}
+
+static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
+ unsigned int mac_tscr)
+{
+ /* Set one nano-second accuracy */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1);
+
+ /* Set fine timestamp update */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1);
+
+ /* Overwrite earlier timestamps */
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1);
+
+ XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr);
+
+ /* Exit if timestamping is not enabled */
+ if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA))
+ return 0;
+
+ /* Initialize time registers */
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC);
+ XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC);
+ xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend);
+ xgbe_set_tstamp_time(pdata, 0, 0);
+
+ /* Initialize the timecounter */
+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+ ktime_to_ns(ktime_get_real()));
+
+ return 0;
+}
+
+static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+{
+ struct ieee_ets *ets = pdata->ets;
+ unsigned int total_weight, min_weight, weight;
+ unsigned int i;
+
+ if (!ets)
+ return;
+
+ /* Set Tx to deficit weighted round robin scheduling algorithm (when
+ * traffic class is using ETS algorithm)
+ */
+ XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR);
+
+ /* Set Traffic Class algorithms */
+ total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt;
+ min_weight = total_weight / 100;
+ if (!min_weight)
+ min_weight = 1;
+
+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
+ switch (ets->tc_tsa[i]) {
+ case IEEE_8021QAZ_TSA_STRICT:
+ DBGPR(" TC%u using SP\n", i);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+ MTL_TSA_SP);
+ break;
+ case IEEE_8021QAZ_TSA_ETS:
+ weight = total_weight * ets->tc_tx_bw[i] / 100;
+ weight = clamp(weight, min_weight, total_weight);
+
+ DBGPR(" TC%u using DWRR (weight %u)\n", i, weight);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+ MTL_TSA_ETS);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW,
+ weight);
+ break;
+ }
+ }
+}
+
+static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
+{
+ struct ieee_pfc *pfc = pdata->pfc;
+ struct ieee_ets *ets = pdata->ets;
+ unsigned int mask, reg, reg_val;
+ unsigned int tc, prio;
+
+ if (!pfc || !ets)
+ return;
+
+ for (tc = 0; tc < pdata->hw_feat.tc_cnt; tc++) {
+ mask = 0;
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+ if ((pfc->pfc_en & (1 << prio)) &&
+ (ets->prio_tc[prio] == tc))
+ mask |= (1 << prio);
+ }
+ mask &= 0xff;
+
+ DBGPR(" TC%u PFC mask=%#x\n", tc, mask);
+ reg = MTL_TCPM0R + (MTL_TCPM_INC * (tc / MTL_TCPM_TC_PER_REG));
+ reg_val = XGMAC_IOREAD(pdata, reg);
+
+ reg_val &= ~(0xff << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+ reg_val |= (mask << ((tc % MTL_TCPM_TC_PER_REG) << 3));
+
+ XGMAC_IOWRITE(pdata, reg, reg_val);
+ }
+
+ xgbe_config_flow_control(pdata);
+}
+
static void xgbe_pre_xmit(struct xgbe_channel *channel)
{
struct xgbe_prv_data *pdata = channel->pdata;
@@ -933,7 +1236,7 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
if (tx_coalesce && !channel->tx_timer_active)
ring->coalesce_count = 0;
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc;
/* Create a context descriptor if this is a TSO packet */
@@ -977,7 +1280,7 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
}
ring->cur++;
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc;
}
@@ -994,6 +1297,10 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, VTIR,
TX_NORMAL_DESC2_VLAN_INSERT);
+ /* Timestamp enablement check */
+ if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
+
/* Set IC bit based on Tx coalescing settings */
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
if (tx_coalesce && (!tx_frames ||
@@ -1034,7 +1341,7 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
for (i = ring->cur - start_index + 1; i < packet->rdesc_count; i++) {
ring->cur++;
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc;
/* Update buffer address */
@@ -1074,7 +1381,7 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
wmb();
/* Set OWN bit for the first descriptor */
- rdata = GET_DESC_DATA(ring, start_index);
+ rdata = XGBE_GET_DESC_DATA(ring, start_index);
rdesc = rdata->rdesc;
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
@@ -1088,7 +1395,7 @@ static void xgbe_pre_xmit(struct xgbe_channel *channel)
/* Issue a poll command to Tx DMA by writing address
* of next immediate free descriptor */
ring->cur++;
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
lower_32_bits(rdata->rdesc_dma));
@@ -1113,11 +1420,12 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
struct xgbe_ring_data *rdata;
struct xgbe_ring_desc *rdesc;
struct xgbe_packet_data *packet = &ring->packet_data;
+ struct net_device *netdev = channel->pdata->netdev;
unsigned int err, etlt;
DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur);
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc;
/* Check for data availability */
@@ -1128,6 +1436,25 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
#endif
+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CTXT)) {
+ /* Timestamp Context Descriptor */
+ xgbe_get_rx_tstamp(packet, rdesc);
+
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+ CONTEXT, 1);
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+ CONTEXT_NEXT, 0);
+ return 0;
+ }
+
+ /* Normal Descriptor, be sure Context Descriptor bit is off */
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, CONTEXT, 0);
+
+ /* Indicate if a Context Descriptor is next */
+ if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, CDA))
+ XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
+ CONTEXT_NEXT, 1);
+
/* Get the packet length */
rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
@@ -1153,7 +1480,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
DBGPR(" err=%u, etlt=%#x\n", err, etlt);
if (!err || (err && !etlt)) {
- if (etlt == 0x09) {
+ if ((etlt == 0x09) &&
+ (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
VLAN_CTAG, 1);
packet->vlan_ctag = XGMAC_GET_BITS_LE(rdesc->desc0,
@@ -1188,56 +1516,48 @@ static int xgbe_is_last_desc(struct xgbe_ring_desc *rdesc)
return XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD);
}
-static void xgbe_save_interrupt_status(struct xgbe_channel *channel,
- enum xgbe_int_state int_state)
+static int xgbe_enable_int(struct xgbe_channel *channel,
+ enum xgbe_int int_id)
{
unsigned int dma_ch_ier;
- if (int_state == XGMAC_INT_STATE_SAVE) {
- channel->saved_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
- channel->saved_ier &= DMA_INTERRUPT_MASK;
- } else {
- dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
- dma_ch_ier |= channel->saved_ier;
- XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
- }
-}
+ dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
-static int xgbe_enable_int(struct xgbe_channel *channel,
- enum xgbe_int int_id)
-{
switch (int_id) {
- case XGMAC_INT_DMA_ISR_DC0IS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 1);
- break;
case XGMAC_INT_DMA_CH_SR_TI:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TPS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TXSE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 1);
break;
case XGMAC_INT_DMA_CH_SR_TBU:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TBUE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 1);
break;
case XGMAC_INT_DMA_CH_SR_RI:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RIE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
break;
case XGMAC_INT_DMA_CH_SR_RBU:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RBUE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
break;
case XGMAC_INT_DMA_CH_SR_RPS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RSE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 1);
+ break;
+ case XGMAC_INT_DMA_CH_SR_TI_RI:
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
break;
case XGMAC_INT_DMA_CH_SR_FBE:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, FBEE, 1);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 1);
break;
case XGMAC_INT_DMA_ALL:
- xgbe_save_interrupt_status(channel, XGMAC_INT_STATE_RESTORE);
+ dma_ch_ier |= channel->saved_ier;
break;
default:
return -1;
}
+ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+
return 0;
}
@@ -1246,42 +1566,44 @@ static int xgbe_disable_int(struct xgbe_channel *channel,
{
unsigned int dma_ch_ier;
+ dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
+
switch (int_id) {
- case XGMAC_INT_DMA_ISR_DC0IS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 0);
- break;
case XGMAC_INT_DMA_CH_SR_TI:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TIE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0);
break;
case XGMAC_INT_DMA_CH_SR_TPS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TXSE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TXSE, 0);
break;
case XGMAC_INT_DMA_CH_SR_TBU:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, TBUE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TBUE, 0);
break;
case XGMAC_INT_DMA_CH_SR_RI:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RIE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0);
break;
case XGMAC_INT_DMA_CH_SR_RBU:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RBUE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 0);
break;
case XGMAC_INT_DMA_CH_SR_RPS:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, RSE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RSE, 0);
+ break;
+ case XGMAC_INT_DMA_CH_SR_TI_RI:
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 0);
break;
case XGMAC_INT_DMA_CH_SR_FBE:
- XGMAC_DMA_IOWRITE_BITS(channel, DMA_CH_IER, FBEE, 0);
+ XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, FBEE, 0);
break;
case XGMAC_INT_DMA_ALL:
- xgbe_save_interrupt_status(channel, XGMAC_INT_STATE_SAVE);
-
- dma_ch_ier = XGMAC_DMA_IOREAD(channel, DMA_CH_IER);
- dma_ch_ier &= ~DMA_INTERRUPT_MASK;
- XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+ channel->saved_ier = dma_ch_ier & XGBE_DMA_INTERRUPT_MASK;
+ dma_ch_ier &= ~XGBE_DMA_INTERRUPT_MASK;
break;
default:
return -1;
}
+ XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
+
return 0;
}
@@ -1311,11 +1633,11 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata)
{
unsigned int i, count;
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, FTQ, 1);
/* Poll Until Poll Condition */
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++) {
+ for (i = 0; i < pdata->tx_q_count; i++) {
count = 2000;
while (count-- && XGMAC_MTL_IOREAD_BITS(pdata, i,
MTL_Q_TQOMR, FTQ))
@@ -1335,6 +1657,7 @@ static void xgbe_config_dma_bus(struct xgbe_prv_data *pdata)
/* Set the System Bus mode */
XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, UNDEF, 1);
+ XGMAC_IOWRITE_BITS(pdata, DMA_SBMR, BLEN_256, 1);
}
static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
@@ -1342,23 +1665,23 @@ static void xgbe_config_dma_cache(struct xgbe_prv_data *pdata)
unsigned int arcache, awcache;
arcache = 0;
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, DMA_ARCACHE_SETTING);
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, DMA_ARDOMAIN_SETTING);
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, DMA_ARCACHE_SETTING);
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, DMA_ARDOMAIN_SETTING);
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, DMA_ARCACHE_SETTING);
- XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, DMA_ARDOMAIN_SETTING);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRC, pdata->arcache);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, DRD, pdata->axdomain);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, TEC, pdata->arcache);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, TED, pdata->axdomain);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, THC, pdata->arcache);
+ XGMAC_SET_BITS(arcache, DMA_AXIARCR, THD, pdata->axdomain);
XGMAC_IOWRITE(pdata, DMA_AXIARCR, arcache);
awcache = 0;
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, DMA_AWCACHE_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, DMA_AWDOMAIN_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, DMA_AWCACHE_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, DMA_AWDOMAIN_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, DMA_AWCACHE_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, DMA_AWDOMAIN_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, DMA_AWCACHE_SETTING);
- XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, DMA_AWDOMAIN_SETTING);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWC, pdata->awcache);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, DWD, pdata->axdomain);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPC, pdata->awcache);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RPD, pdata->axdomain);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHC, pdata->awcache);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, RHD, pdata->axdomain);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDC, pdata->awcache);
+ XGMAC_SET_BITS(awcache, DMA_AXIAWCR, TDD, pdata->axdomain);
XGMAC_IOWRITE(pdata, DMA_AXIAWCR, awcache);
}
@@ -1366,14 +1689,15 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
{
unsigned int i;
- /* Set Tx to weighted round robin scheduling algorithm (when
- * traffic class is using ETS algorithm)
- */
+ /* Set Tx to weighted round robin scheduling algorithm */
XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_WRR);
- /* Set Tx traffic classes to strict priority algorithm */
- for (i = 0; i < XGBE_TC_CNT; i++)
- XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA, MTL_TSA_SP);
+ /* Set Tx traffic classes to use WRR algorithm with equal weights */
+ for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+ MTL_TSA_ETS);
+ XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW, 1);
+ }
/* Set Rx to strict priority algorithm */
XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
@@ -1388,66 +1712,66 @@ static unsigned int xgbe_calculate_per_queue_fifo(unsigned long fifo_size,
/* Calculate Tx/Rx fifo share per queue */
switch (fifo_size) {
case 0:
- q_fifo_size = FIFO_SIZE_B(128);
+ q_fifo_size = XGBE_FIFO_SIZE_B(128);
break;
case 1:
- q_fifo_size = FIFO_SIZE_B(256);
+ q_fifo_size = XGBE_FIFO_SIZE_B(256);
break;
case 2:
- q_fifo_size = FIFO_SIZE_B(512);
+ q_fifo_size = XGBE_FIFO_SIZE_B(512);
break;
case 3:
- q_fifo_size = FIFO_SIZE_KB(1);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(1);
break;
case 4:
- q_fifo_size = FIFO_SIZE_KB(2);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(2);
break;
case 5:
- q_fifo_size = FIFO_SIZE_KB(4);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(4);
break;
case 6:
- q_fifo_size = FIFO_SIZE_KB(8);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(8);
break;
case 7:
- q_fifo_size = FIFO_SIZE_KB(16);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(16);
break;
case 8:
- q_fifo_size = FIFO_SIZE_KB(32);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(32);
break;
case 9:
- q_fifo_size = FIFO_SIZE_KB(64);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(64);
break;
case 10:
- q_fifo_size = FIFO_SIZE_KB(128);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(128);
break;
case 11:
- q_fifo_size = FIFO_SIZE_KB(256);
+ q_fifo_size = XGBE_FIFO_SIZE_KB(256);
break;
}
q_fifo_size = q_fifo_size / queue_count;
/* Set the queue fifo size programmable value */
- if (q_fifo_size >= FIFO_SIZE_KB(256))
+ if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256))
p_fifo = XGMAC_MTL_FIFO_SIZE_256K;
- else if (q_fifo_size >= FIFO_SIZE_KB(128))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128))
p_fifo = XGMAC_MTL_FIFO_SIZE_128K;
- else if (q_fifo_size >= FIFO_SIZE_KB(64))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64))
p_fifo = XGMAC_MTL_FIFO_SIZE_64K;
- else if (q_fifo_size >= FIFO_SIZE_KB(32))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32))
p_fifo = XGMAC_MTL_FIFO_SIZE_32K;
- else if (q_fifo_size >= FIFO_SIZE_KB(16))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16))
p_fifo = XGMAC_MTL_FIFO_SIZE_16K;
- else if (q_fifo_size >= FIFO_SIZE_KB(8))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8))
p_fifo = XGMAC_MTL_FIFO_SIZE_8K;
- else if (q_fifo_size >= FIFO_SIZE_KB(4))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4))
p_fifo = XGMAC_MTL_FIFO_SIZE_4K;
- else if (q_fifo_size >= FIFO_SIZE_KB(2))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2))
p_fifo = XGMAC_MTL_FIFO_SIZE_2K;
- else if (q_fifo_size >= FIFO_SIZE_KB(1))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1))
p_fifo = XGMAC_MTL_FIFO_SIZE_1K;
- else if (q_fifo_size >= FIFO_SIZE_B(512))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512))
p_fifo = XGMAC_MTL_FIFO_SIZE_512;
- else if (q_fifo_size >= FIFO_SIZE_B(256))
+ else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256))
p_fifo = XGMAC_MTL_FIFO_SIZE_256;
return p_fifo;
@@ -1459,13 +1783,13 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
unsigned int i;
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
- pdata->hw_feat.tx_q_cnt);
+ pdata->tx_q_count);
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size);
netdev_notice(pdata->netdev, "%d Tx queues, %d byte fifo per queue\n",
- pdata->hw_feat.tx_q_cnt, ((fifo_size + 1) * 256));
+ pdata->tx_q_count, ((fifo_size + 1) * 256));
}
static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
@@ -1474,27 +1798,84 @@ static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
unsigned int i;
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
- pdata->hw_feat.rx_q_cnt);
+ pdata->rx_q_count);
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size);
netdev_notice(pdata->netdev, "%d Rx queues, %d byte fifo per queue\n",
- pdata->hw_feat.rx_q_cnt, ((fifo_size + 1) * 256));
+ pdata->rx_q_count, ((fifo_size + 1) * 256));
}
-static void xgbe_config_rx_queue_mapping(struct xgbe_prv_data *pdata)
+static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
{
- unsigned int i, reg, reg_val;
- unsigned int q_count = pdata->hw_feat.rx_q_cnt;
+ unsigned int qptc, qptc_extra, queue;
+ unsigned int prio_queues;
+ unsigned int ppq, ppq_extra, prio;
+ unsigned int mask;
+ unsigned int i, j, reg, reg_val;
+
+ /* Map the MTL Tx Queues to Traffic Classes
+ * Note: Tx Queues >= Traffic Classes
+ */
+ qptc = pdata->tx_q_count / pdata->hw_feat.tc_cnt;
+ qptc_extra = pdata->tx_q_count % pdata->hw_feat.tc_cnt;
+
+ for (i = 0, queue = 0; i < pdata->hw_feat.tc_cnt; i++) {
+ for (j = 0; j < qptc; j++) {
+ DBGPR(" TXq%u mapped to TC%u\n", queue, i);
+ XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
+ Q2TCMAP, i);
+ pdata->q2tc_map[queue++] = i;
+ }
+
+ if (i < qptc_extra) {
+ DBGPR(" TXq%u mapped to TC%u\n", queue, i);
+ XGMAC_MTL_IOWRITE_BITS(pdata, queue, MTL_Q_TQOMR,
+ Q2TCMAP, i);
+ pdata->q2tc_map[queue++] = i;
+ }
+ }
+
+ /* Map the 8 VLAN priority values to available MTL Rx queues */
+ prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
+ pdata->rx_q_count);
+ ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
+ ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;
+
+ reg = MAC_RQC2R;
+ reg_val = 0;
+ for (i = 0, prio = 0; i < prio_queues;) {
+ mask = 0;
+ for (j = 0; j < ppq; j++) {
+ DBGPR(" PRIO%u mapped to RXq%u\n", prio, i);
+ mask |= (1 << prio);
+ pdata->prio2q_map[prio++] = i;
+ }
+
+ if (i < ppq_extra) {
+ DBGPR(" PRIO%u mapped to RXq%u\n", prio, i);
+ mask |= (1 << prio);
+ pdata->prio2q_map[prio++] = i;
+ }
+
+ reg_val |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3));
+
+ if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues))
+ continue;
+
+ XGMAC_IOWRITE(pdata, reg, reg_val);
+ reg += MAC_RQC2_INC;
+ reg_val = 0;
+ }
/* Select dynamic mapping of MTL Rx queue to DMA Rx channel */
reg = MTL_RQDCM0R;
reg_val = 0;
- for (i = 0; i < q_count;) {
+ for (i = 0; i < pdata->rx_q_count;) {
reg_val |= (0x80 << ((i++ % MTL_RQDCM_Q_PER_REG) << 3));
- if ((i % MTL_RQDCM_Q_PER_REG) && (i != q_count))
+ if ((i % MTL_RQDCM_Q_PER_REG) && (i != pdata->rx_q_count))
continue;
XGMAC_IOWRITE(pdata, reg, reg_val);
@@ -1508,7 +1889,7 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
{
unsigned int i;
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++) {
+ for (i = 0; i < pdata->rx_q_count; i++) {
/* Activate flow control when less than 4k left in fifo */
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RFA, 2);
@@ -1520,6 +1901,13 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
static void xgbe_config_mac_address(struct xgbe_prv_data *pdata)
{
xgbe_set_mac_address(pdata, pdata->netdev->dev_addr);
+
+ /* Filtering is done using perfect filtering and hash filtering */
+ if (pdata->hw_feat.hash_table_size) {
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1);
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 1);
+ XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 1);
+ }
}
static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata)
@@ -1541,6 +1929,18 @@ static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
static void xgbe_config_vlan_support(struct xgbe_prv_data *pdata)
{
+ /* Indicate that VLAN Tx CTAGs come from context descriptors */
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, CSVL, 0);
+ XGMAC_IOWRITE_BITS(pdata, MAC_VLANIR, VLTI, 1);
+
+ /* Set the current VLAN Hash Table register value */
+ xgbe_update_vlan_hash_table(pdata);
+
+ if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+ xgbe_enable_rx_vlan_filtering(pdata);
+ else
+ xgbe_disable_rx_vlan_filtering(pdata);
+
if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
xgbe_enable_rx_vlan_stripping(pdata);
else
@@ -1881,7 +2281,7 @@ static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
}
/* Enable each Tx queue */
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN,
MTL_Q_ENABLED);
@@ -1898,7 +2298,7 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
/* Disable each Tx queue */
- for (i = 0; i < pdata->hw_feat.tx_q_cnt; i++)
+ for (i = 0; i < pdata->tx_q_count; i++)
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TXQEN, 0);
/* Disable each Tx DMA channel */
@@ -1927,7 +2327,7 @@ static void xgbe_enable_rx(struct xgbe_prv_data *pdata)
/* Enable each Rx queue */
reg_val = 0;
- for (i = 0; i < pdata->hw_feat.rx_q_cnt; i++)
+ for (i = 0; i < pdata->rx_q_count; i++)
reg_val |= (0x02 << (i << 1));
XGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val);
@@ -2061,9 +2461,7 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
* Initialize MTL related features
*/
xgbe_config_mtl_mode(pdata);
- xgbe_config_rx_queue_mapping(pdata);
- /*TODO: Program the priorities mapped to the Selected Traffic Classes
- in MTL_TC_Prty_Map0-3 registers */
+ xgbe_config_queue_mapping(pdata);
xgbe_config_tsf_mode(pdata, pdata->tx_sf_mode);
xgbe_config_rsf_mode(pdata, pdata->rx_sf_mode);
xgbe_config_tx_threshold(pdata, pdata->tx_threshold);
@@ -2071,15 +2469,13 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
xgbe_config_tx_fifo_size(pdata);
xgbe_config_rx_fifo_size(pdata);
xgbe_config_flow_control_threshold(pdata);
- /*TODO: Queue to Traffic Class Mapping (Q2TCMAP) */
/*TODO: Error Packet and undersized good Packet forwarding enable
(FEP and FUP)
*/
+ xgbe_config_dcb_tc(pdata);
+ xgbe_config_dcb_pfc(pdata);
xgbe_enable_mtl_interrupts(pdata);
- /* Transmit Class Weight */
- XGMAC_IOWRITE_BITS(pdata, MTL_Q_TCQWR, QW, 0x10);
-
/*
* Initialize MAC related features
*/
@@ -2104,7 +2500,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode;
hw_if->set_all_multicast_mode = xgbe_set_all_multicast_mode;
- hw_if->set_addn_mac_addrs = xgbe_set_addn_mac_addrs;
+ hw_if->add_mac_addresses = xgbe_add_mac_addresses;
hw_if->set_mac_address = xgbe_set_mac_address;
hw_if->enable_rx_csum = xgbe_enable_rx_csum;
@@ -2112,6 +2508,9 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->enable_rx_vlan_stripping = xgbe_enable_rx_vlan_stripping;
hw_if->disable_rx_vlan_stripping = xgbe_disable_rx_vlan_stripping;
+ hw_if->enable_rx_vlan_filtering = xgbe_enable_rx_vlan_filtering;
+ hw_if->disable_rx_vlan_filtering = xgbe_disable_rx_vlan_filtering;
+ hw_if->update_vlan_hash_table = xgbe_update_vlan_hash_table;
hw_if->read_mmd_regs = xgbe_read_mmd_regs;
hw_if->write_mmd_regs = xgbe_write_mmd_regs;
@@ -2178,5 +2577,16 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->rx_mmc_int = xgbe_rx_mmc_int;
hw_if->read_mmc_stats = xgbe_read_mmc_stats;
+ /* For PTP config */
+ hw_if->config_tstamp = xgbe_config_tstamp;
+ hw_if->update_tstamp_addend = xgbe_update_tstamp_addend;
+ hw_if->set_tstamp_time = xgbe_set_tstamp_time;
+ hw_if->get_tstamp_time = xgbe_get_tstamp_time;
+ hw_if->get_tx_tstamp = xgbe_get_tx_tstamp;
+
+ /* For Data Center Bridging config */
+ hw_if->config_dcb_tc = xgbe_config_dcb_tc;
+ hw_if->config_dcb_pfc = xgbe_config_dcb_pfc;
+
DBGPR("<--xgbe_init_function_ptrs\n");
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index cfe3d93b5f52..dc84f7193c2d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -117,10 +117,11 @@
#include <linux/spinlock.h>
#include <linux/tcp.h>
#include <linux/if_vlan.h>
-#include <linux/phy.h>
#include <net/busy_poll.h>
#include <linux/clk.h>
#include <linux/if_ether.h>
+#include <linux/net_tstamp.h>
+#include <linux/phy.h>
#include "xgbe.h"
#include "xgbe-common.h"
@@ -144,9 +145,10 @@ static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
}
rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
- if (rx_buf_size < RX_MIN_BUF_SIZE)
- rx_buf_size = RX_MIN_BUF_SIZE;
- rx_buf_size = (rx_buf_size + RX_BUF_ALIGN - 1) & ~(RX_BUF_ALIGN - 1);
+ if (rx_buf_size < XGBE_RX_MIN_BUF_SIZE)
+ rx_buf_size = XGBE_RX_MIN_BUF_SIZE;
+ rx_buf_size = (rx_buf_size + XGBE_RX_BUF_ALIGN - 1) &
+ ~(XGBE_RX_BUF_ALIGN - 1);
return rx_buf_size;
}
@@ -155,16 +157,21 @@ static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
{
struct xgbe_hw_if *hw_if = &pdata->hw_if;
struct xgbe_channel *channel;
+ enum xgbe_int int_id;
unsigned int i;
channel = pdata->channel;
for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (channel->tx_ring)
- hw_if->enable_int(channel,
- XGMAC_INT_DMA_CH_SR_TI);
- if (channel->rx_ring)
- hw_if->enable_int(channel,
- XGMAC_INT_DMA_CH_SR_RI);
+ if (channel->tx_ring && channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+ else if (channel->tx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI;
+ else if (channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_RI;
+ else
+ continue;
+
+ hw_if->enable_int(channel, int_id);
}
}
@@ -172,16 +179,21 @@ static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata)
{
struct xgbe_hw_if *hw_if = &pdata->hw_if;
struct xgbe_channel *channel;
+ enum xgbe_int int_id;
unsigned int i;
channel = pdata->channel;
for (i = 0; i < pdata->channel_count; i++, channel++) {
- if (channel->tx_ring)
- hw_if->disable_int(channel,
- XGMAC_INT_DMA_CH_SR_TI);
- if (channel->rx_ring)
- hw_if->disable_int(channel,
- XGMAC_INT_DMA_CH_SR_RI);
+ if (channel->tx_ring && channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+ else if (channel->tx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_TI;
+ else if (channel->rx_ring)
+ int_id = XGMAC_INT_DMA_CH_SR_RI;
+ else
+ continue;
+
+ hw_if->disable_int(channel, int_id);
}
}
@@ -191,7 +203,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
struct xgbe_hw_if *hw_if = &pdata->hw_if;
struct xgbe_channel *channel;
unsigned int dma_isr, dma_ch_isr;
- unsigned int mac_isr;
+ unsigned int mac_isr, mac_tssr;
unsigned int i;
/* The DMA interrupt status register also reports MAC and MTL
@@ -244,6 +256,17 @@ static irqreturn_t xgbe_isr(int irq, void *data)
if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCRXIS))
hw_if->rx_mmc_int(pdata);
+
+ if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) {
+ mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR);
+
+ if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
+ /* Read Tx Timestamp to clear interrupt */
+ pdata->tx_tstamp =
+ hw_if->get_tx_tstamp(pdata);
+ schedule_work(&pdata->tx_tstamp_work);
+ }
+ }
}
DBGPR(" DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR));
@@ -364,6 +387,7 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN);
hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN);
hw_feat->dma_debug = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DBGMEMA);
+ hw_feat->tc_cnt = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, NUMTC);
hw_feat->hash_table_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
HASHTBLSZ);
hw_feat->l3l4_filter_num = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
@@ -377,6 +401,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM);
hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM);
+ /* Translate the Hash Table size into actual number */
+ switch (hw_feat->hash_table_size) {
+ case 0:
+ break;
+ case 1:
+ hw_feat->hash_table_size = 64;
+ break;
+ case 2:
+ hw_feat->hash_table_size = 128;
+ break;
+ case 3:
+ hw_feat->hash_table_size = 256;
+ break;
+ }
+
/* The Queue and Channel counts are zero based so increment them
* to get the actual number
*/
@@ -396,9 +435,12 @@ static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add)
napi_enable(&pdata->napi);
}
-static void xgbe_napi_disable(struct xgbe_prv_data *pdata)
+static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del)
{
napi_disable(&pdata->napi);
+
+ if (del)
+ netif_napi_del(&pdata->napi);
}
void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata)
@@ -446,7 +488,7 @@ static void xgbe_free_tx_skbuff(struct xgbe_prv_data *pdata)
break;
for (j = 0; j < ring->rdesc_count; j++) {
- rdata = GET_DESC_DATA(ring, j);
+ rdata = XGBE_GET_DESC_DATA(ring, j);
desc_if->unmap_skb(pdata, rdata);
}
}
@@ -471,7 +513,7 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata)
break;
for (j = 0; j < ring->rdesc_count; j++) {
- rdata = GET_DESC_DATA(ring, j);
+ rdata = XGBE_GET_DESC_DATA(ring, j);
desc_if->unmap_skb(pdata, rdata);
}
}
@@ -479,6 +521,114 @@ static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata)
DBGPR("<--xgbe_free_rx_skbuff\n");
}
+static void xgbe_adjust_link(struct net_device *netdev)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ struct xgbe_hw_if *hw_if = &pdata->hw_if;
+ struct phy_device *phydev = pdata->phydev;
+ int new_state = 0;
+
+ if (phydev == NULL)
+ return;
+
+ if (phydev->link) {
+ /* Flow control support */
+ if (pdata->pause_autoneg) {
+ if (phydev->pause || phydev->asym_pause) {
+ pdata->tx_pause = 1;
+ pdata->rx_pause = 1;
+ } else {
+ pdata->tx_pause = 0;
+ pdata->rx_pause = 0;
+ }
+ }
+
+ if (pdata->tx_pause != pdata->phy_tx_pause) {
+ hw_if->config_tx_flow_control(pdata);
+ pdata->phy_tx_pause = pdata->tx_pause;
+ }
+
+ if (pdata->rx_pause != pdata->phy_rx_pause) {
+ hw_if->config_rx_flow_control(pdata);
+ pdata->phy_rx_pause = pdata->rx_pause;
+ }
+
+ /* Speed support */
+ if (phydev->speed != pdata->phy_speed) {
+ new_state = 1;
+
+ switch (phydev->speed) {
+ case SPEED_10000:
+ hw_if->set_xgmii_speed(pdata);
+ break;
+
+ case SPEED_2500:
+ hw_if->set_gmii_2500_speed(pdata);
+ break;
+
+ case SPEED_1000:
+ hw_if->set_gmii_speed(pdata);
+ break;
+ }
+ pdata->phy_speed = phydev->speed;
+ }
+
+ if (phydev->link != pdata->phy_link) {
+ new_state = 1;
+ pdata->phy_link = 1;
+ }
+ } else if (pdata->phy_link) {
+ new_state = 1;
+ pdata->phy_link = 0;
+ pdata->phy_speed = SPEED_UNKNOWN;
+ }
+
+ if (new_state)
+ phy_print_status(phydev);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+ struct net_device *netdev = pdata->netdev;
+ struct phy_device *phydev = pdata->phydev;
+ int ret;
+
+ pdata->phy_link = -1;
+ pdata->phy_speed = SPEED_UNKNOWN;
+ pdata->phy_tx_pause = pdata->tx_pause;
+ pdata->phy_rx_pause = pdata->rx_pause;
+
+ ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
+ pdata->phy_mode);
+ if (ret) {
+ netdev_err(netdev, "phy_connect_direct failed\n");
+ return ret;
+ }
+
+ if (!phydev->drv || (phydev->drv->phy_id == 0)) {
+ netdev_err(netdev, "phy_id not valid\n");
+ ret = -ENODEV;
+ goto err_phy_connect;
+ }
+ DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n",
+ dev_name(&phydev->dev), phydev->link);
+
+ return 0;
+
+err_phy_connect:
+ phy_disconnect(phydev);
+
+ return ret;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+ if (!pdata->phydev)
+ return;
+
+ phy_disconnect(pdata->phydev);
+}
+
int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
@@ -502,7 +652,7 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
netif_device_detach(netdev);
netif_tx_stop_all_queues(netdev);
- xgbe_napi_disable(pdata);
+ xgbe_napi_disable(pdata, 0);
/* Powerdown Tx/Rx */
hw_if->powerdown_tx(pdata);
@@ -591,7 +741,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
phy_stop(pdata->phydev);
netif_tx_stop_all_queues(netdev);
- xgbe_napi_disable(pdata);
+ xgbe_napi_disable(pdata, 1);
xgbe_stop_tx_timers(pdata);
@@ -639,6 +789,197 @@ static void xgbe_restart(struct work_struct *work)
rtnl_unlock();
}
+static void xgbe_tx_tstamp(struct work_struct *work)
+{
+ struct xgbe_prv_data *pdata = container_of(work,
+ struct xgbe_prv_data,
+ tx_tstamp_work);
+ struct skb_shared_hwtstamps hwtstamps;
+ u64 nsec;
+ unsigned long flags;
+
+ if (pdata->tx_tstamp) {
+ nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+ pdata->tx_tstamp);
+
+ memset(&hwtstamps, 0, sizeof(hwtstamps));
+ hwtstamps.hwtstamp = ns_to_ktime(nsec);
+ skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps);
+ }
+
+ dev_kfree_skb_any(pdata->tx_tstamp_skb);
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+ pdata->tx_tstamp_skb = NULL;
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+}
+
+static int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata,
+ struct ifreq *ifreq)
+{
+ if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config,
+ sizeof(pdata->tstamp_config)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata,
+ struct ifreq *ifreq)
+{
+ struct hwtstamp_config config;
+ unsigned int mac_tscr;
+
+ if (copy_from_user(&config, ifreq->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ if (config.flags)
+ return -EINVAL;
+
+ mac_tscr = 0;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ break;
+
+ case HWTSTAMP_TX_ON:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ default:
+ return -ERANGE;
+ }
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ break;
+
+ case HWTSTAMP_FILTER_ALL:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2, UDP, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ /* PTP v1, UDP, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2, UDP, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ /* PTP v1, UDP, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2, UDP, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ /* PTP v1, UDP, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* 802.AS1, Ethernet, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* 802.AS1, Ethernet, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* 802.AS1, Ethernet, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2/802.AS1, any layer, any kind of event packet */
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2/802.AS1, any layer, Sync packet */
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ /* PTP v2/802.AS1, any layer, Delay_req packet */
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1);
+ XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1);
+ break;
+
+ default:
+ return -ERANGE;
+ }
+
+ pdata->hw_if.config_tstamp(pdata, mac_tscr);
+
+ memcpy(&pdata->tstamp_config, &config, sizeof(config));
+
+ return 0;
+}
+
+static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata,
+ struct sk_buff *skb,
+ struct xgbe_packet_data *packet)
+{
+ unsigned long flags;
+
+ if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) {
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+ if (pdata->tx_tstamp_skb) {
+ /* Another timestamp in progress, ignore this one */
+ XGMAC_SET_BITS(packet->attributes,
+ TX_PACKET_ATTRIBUTES, PTP, 0);
+ } else {
+ pdata->tx_tstamp_skb = skb_get(skb);
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ }
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+ }
+
+ if (!XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
+ skb_tx_timestamp(skb);
+}
+
static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet)
{
if (vlan_tx_tag_present(skb))
@@ -682,7 +1023,8 @@ static int xgbe_is_tso(struct sk_buff *skb)
return 1;
}
-static void xgbe_packet_info(struct xgbe_ring *ring, struct sk_buff *skb,
+static void xgbe_packet_info(struct xgbe_prv_data *pdata,
+ struct xgbe_ring *ring, struct sk_buff *skb,
struct xgbe_packet_data *packet)
{
struct skb_frag_struct *frag;
@@ -724,16 +1066,21 @@ static void xgbe_packet_info(struct xgbe_ring *ring, struct sk_buff *skb,
VLAN_CTAG, 1);
}
+ if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+ (pdata->tstamp_config.tx_type == HWTSTAMP_TX_ON))
+ XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
+ PTP, 1);
+
for (len = skb_headlen(skb); len;) {
packet->rdesc_count++;
- len -= min_t(unsigned int, len, TX_MAX_BUF_SIZE);
+ len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE);
}
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
frag = &skb_shinfo(skb)->frags[i];
for (len = skb_frag_size(frag); len; ) {
packet->rdesc_count++;
- len -= min_t(unsigned int, len, TX_MAX_BUF_SIZE);
+ len -= min_t(unsigned int, len, XGBE_TX_MAX_BUF_SIZE);
}
}
}
@@ -747,26 +1094,38 @@ static int xgbe_open(struct net_device *netdev)
DBGPR("-->xgbe_open\n");
- /* Enable the clock */
- ret = clk_prepare_enable(pdata->sysclock);
- if (ret) {
- netdev_alert(netdev, "clk_prepare_enable failed\n");
+ /* Initialize the phy */
+ ret = xgbe_phy_init(pdata);
+ if (ret)
return ret;
+
+ /* Enable the clocks */
+ ret = clk_prepare_enable(pdata->sysclk);
+ if (ret) {
+ netdev_alert(netdev, "dma clk_prepare_enable failed\n");
+ goto err_phy_init;
+ }
+
+ ret = clk_prepare_enable(pdata->ptpclk);
+ if (ret) {
+ netdev_alert(netdev, "ptp clk_prepare_enable failed\n");
+ goto err_sysclk;
}
/* Calculate the Rx buffer size before allocating rings */
ret = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
if (ret < 0)
- goto err_clk;
+ goto err_ptpclk;
pdata->rx_buf_size = ret;
/* Allocate the ring descriptors and buffers */
ret = desc_if->alloc_ring_resources(pdata);
if (ret)
- goto err_clk;
+ goto err_ptpclk;
- /* Initialize the device restart work struct */
+ /* Initialize the device restart and Tx timestamp work struct */
INIT_WORK(&pdata->restart_work, xgbe_restart);
+ INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
/* Request interrupts */
ret = devm_request_irq(pdata->dev, netdev->irq, xgbe_isr, 0,
@@ -795,8 +1154,14 @@ err_start:
err_irq:
desc_if->free_ring_resources(pdata);
-err_clk:
- clk_disable_unprepare(pdata->sysclock);
+err_ptpclk:
+ clk_disable_unprepare(pdata->ptpclk);
+
+err_sysclk:
+ clk_disable_unprepare(pdata->sysclk);
+
+err_phy_init:
+ xgbe_phy_exit(pdata);
return ret;
}
@@ -824,8 +1189,12 @@ static int xgbe_close(struct net_device *netdev)
pdata->irq_number = 0;
}
- /* Disable the clock */
- clk_disable_unprepare(pdata->sysclock);
+ /* Disable the clocks */
+ clk_disable_unprepare(pdata->ptpclk);
+ clk_disable_unprepare(pdata->sysclk);
+
+ /* Release the phy */
+ xgbe_phy_exit(pdata);
DBGPR("<--xgbe_close\n");
@@ -861,7 +1230,7 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Calculate preliminary packet info */
memset(packet, 0, sizeof(*packet));
- xgbe_packet_info(ring, skb, packet);
+ xgbe_packet_info(pdata, ring, skb, packet);
/* Check that there are enough descriptors available */
if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) {
@@ -885,6 +1254,8 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
goto tx_netdev_return;
}
+ xgbe_prep_tx_tstamp(pdata, skb, packet);
+
/* Configure required descriptor fields for transmission */
hw_if->pre_xmit(channel);
@@ -911,18 +1282,10 @@ static void xgbe_set_rx_mode(struct net_device *netdev)
pr_mode = ((netdev->flags & IFF_PROMISC) != 0);
am_mode = ((netdev->flags & IFF_ALLMULTI) != 0);
- if (netdev_uc_count(netdev) > pdata->hw_feat.addn_mac)
- pr_mode = 1;
- if (netdev_mc_count(netdev) > pdata->hw_feat.addn_mac)
- am_mode = 1;
- if ((netdev_uc_count(netdev) + netdev_mc_count(netdev)) >
- pdata->hw_feat.addn_mac)
- pr_mode = 1;
-
hw_if->set_promiscuous_mode(pdata, pr_mode);
hw_if->set_all_multicast_mode(pdata, am_mode);
- if (!pr_mode)
- hw_if->set_addn_mac_addrs(pdata, am_mode);
+
+ hw_if->add_mac_addresses(pdata);
DBGPR("<--xgbe_set_rx_mode\n");
}
@@ -947,6 +1310,27 @@ static int xgbe_set_mac_address(struct net_device *netdev, void *addr)
return 0;
}
+static int xgbe_ioctl(struct net_device *netdev, struct ifreq *ifreq, int cmd)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ int ret;
+
+ switch (cmd) {
+ case SIOCGHWTSTAMP:
+ ret = xgbe_get_hwtstamp_settings(pdata, ifreq);
+ break;
+
+ case SIOCSHWTSTAMP:
+ ret = xgbe_set_hwtstamp_settings(pdata, ifreq);
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
static int xgbe_change_mtu(struct net_device *netdev, int mtu)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
@@ -999,6 +1383,38 @@ static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev,
return s;
}
+static int xgbe_vlan_rx_add_vid(struct net_device *netdev, __be16 proto,
+ u16 vid)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ struct xgbe_hw_if *hw_if = &pdata->hw_if;
+
+ DBGPR("-->%s\n", __func__);
+
+ set_bit(vid, pdata->active_vlans);
+ hw_if->update_vlan_hash_table(pdata);
+
+ DBGPR("<--%s\n", __func__);
+
+ return 0;
+}
+
+static int xgbe_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
+ u16 vid)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ struct xgbe_hw_if *hw_if = &pdata->hw_if;
+
+ DBGPR("-->%s\n", __func__);
+
+ clear_bit(vid, pdata->active_vlans);
+ hw_if->update_vlan_hash_table(pdata);
+
+ DBGPR("<--%s\n", __func__);
+
+ return 0;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void xgbe_poll_controller(struct net_device *netdev)
{
@@ -1016,31 +1432,58 @@ static void xgbe_poll_controller(struct net_device *netdev)
}
#endif /* End CONFIG_NET_POLL_CONTROLLER */
+static int xgbe_setup_tc(struct net_device *netdev, u8 tc)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+ unsigned int offset, queue;
+ u8 i;
+
+ if (tc && (tc != pdata->hw_feat.tc_cnt))
+ return -EINVAL;
+
+ if (tc) {
+ netdev_set_num_tc(netdev, tc);
+ for (i = 0, queue = 0, offset = 0; i < tc; i++) {
+ while ((queue < pdata->tx_q_count) &&
+ (pdata->q2tc_map[queue] == i))
+ queue++;
+
+ DBGPR(" TC%u using TXq%u-%u\n", i, offset, queue - 1);
+ netdev_set_tc_queue(netdev, i, queue - offset, offset);
+ offset = queue;
+ }
+ } else {
+ netdev_reset_tc(netdev);
+ }
+
+ return 0;
+}
+
static int xgbe_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
struct xgbe_hw_if *hw_if = &pdata->hw_if;
- unsigned int rxcsum_enabled, rxvlan_enabled;
+ unsigned int rxcsum, rxvlan, rxvlan_filter;
- rxcsum_enabled = !!(pdata->netdev_features & NETIF_F_RXCSUM);
- rxvlan_enabled = !!(pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX);
+ rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
+ rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
+ rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER;
- if ((features & NETIF_F_RXCSUM) && !rxcsum_enabled) {
+ if ((features & NETIF_F_RXCSUM) && !rxcsum)
hw_if->enable_rx_csum(pdata);
- netdev_alert(netdev, "state change - rxcsum enabled\n");
- } else if (!(features & NETIF_F_RXCSUM) && rxcsum_enabled) {
+ else if (!(features & NETIF_F_RXCSUM) && rxcsum)
hw_if->disable_rx_csum(pdata);
- netdev_alert(netdev, "state change - rxcsum disabled\n");
- }
- if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan_enabled) {
+ if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !rxvlan)
hw_if->enable_rx_vlan_stripping(pdata);
- netdev_alert(netdev, "state change - rxvlan enabled\n");
- } else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan_enabled) {
+ else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && rxvlan)
hw_if->disable_rx_vlan_stripping(pdata);
- netdev_alert(netdev, "state change - rxvlan disabled\n");
- }
+
+ if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !rxvlan_filter)
+ hw_if->enable_rx_vlan_filtering(pdata);
+ else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter)
+ hw_if->disable_rx_vlan_filtering(pdata);
pdata->netdev_features = features;
@@ -1056,11 +1499,15 @@ static const struct net_device_ops xgbe_netdev_ops = {
.ndo_set_rx_mode = xgbe_set_rx_mode,
.ndo_set_mac_address = xgbe_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = xgbe_ioctl,
.ndo_change_mtu = xgbe_change_mtu,
.ndo_get_stats64 = xgbe_get_stats64,
+ .ndo_vlan_rx_add_vid = xgbe_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = xgbe_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = xgbe_poll_controller,
#endif
+ .ndo_setup_tc = xgbe_setup_tc,
.ndo_set_features = xgbe_set_features,
};
@@ -1069,6 +1516,22 @@ struct net_device_ops *xgbe_get_netdev_ops(void)
return (struct net_device_ops *)&xgbe_netdev_ops;
}
+static void xgbe_rx_refresh(struct xgbe_channel *channel)
+{
+ struct xgbe_prv_data *pdata = channel->pdata;
+ struct xgbe_desc_if *desc_if = &pdata->desc_if;
+ struct xgbe_ring *ring = channel->rx_ring;
+ struct xgbe_ring_data *rdata;
+
+ desc_if->realloc_skb(channel);
+
+ /* Update the Rx Tail Pointer Register with address of
+ * the last cleaned entry */
+ rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
+ XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
+ lower_32_bits(rdata->rdesc_dma));
+}
+
static int xgbe_tx_poll(struct xgbe_channel *channel)
{
struct xgbe_prv_data *pdata = channel->pdata;
@@ -1089,8 +1552,9 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
spin_lock_irqsave(&ring->lock, flags);
- while ((processed < TX_DESC_MAX_PROC) && (ring->dirty < ring->cur)) {
- rdata = GET_DESC_DATA(ring, ring->dirty);
+ while ((processed < XGBE_TX_DESC_MAX_PROC) &&
+ (ring->dirty < ring->cur)) {
+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
rdesc = rdata->rdesc;
if (!hw_if->tx_complete(rdesc))
@@ -1109,7 +1573,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
}
if ((ring->tx.queue_stopped == 1) &&
- (xgbe_tx_avail_desc(ring) > TX_DESC_MIN_FREE)) {
+ (xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
ring->tx.queue_stopped = 0;
netif_wake_subqueue(netdev, channel->queue_index);
}
@@ -1125,14 +1589,14 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
{
struct xgbe_prv_data *pdata = channel->pdata;
struct xgbe_hw_if *hw_if = &pdata->hw_if;
- struct xgbe_desc_if *desc_if = &pdata->desc_if;
struct xgbe_ring *ring = channel->rx_ring;
struct xgbe_ring_data *rdata;
struct xgbe_packet_data *packet;
struct net_device *netdev = pdata->netdev;
struct sk_buff *skb;
- unsigned int incomplete, error;
- unsigned int cur_len, put_len, max_len;
+ struct skb_shared_hwtstamps *hwtstamps;
+ unsigned int incomplete, error, context_next, context;
+ unsigned int len, put_len, max_len;
int received = 0;
DBGPR("-->xgbe_rx_poll: budget=%d\n", budget);
@@ -1141,18 +1605,32 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
if (!ring)
return 0;
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
packet = &ring->packet_data;
while (received < budget) {
DBGPR(" cur = %d\n", ring->cur);
- /* Clear the packet data information */
- memset(packet, 0, sizeof(*packet));
- skb = NULL;
- error = 0;
- cur_len = 0;
+ /* First time in loop see if we need to restore state */
+ if (!received && rdata->state_saved) {
+ incomplete = rdata->state.incomplete;
+ context_next = rdata->state.context_next;
+ skb = rdata->state.skb;
+ error = rdata->state.error;
+ len = rdata->state.len;
+ } else {
+ memset(packet, 0, sizeof(*packet));
+ incomplete = 0;
+ context_next = 0;
+ skb = NULL;
+ error = 0;
+ len = 0;
+ }
read_again:
- rdata = GET_DESC_DATA(ring, ring->cur);
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
+
+ if (ring->dirty > (XGBE_RX_DESC_CNT >> 3))
+ xgbe_rx_refresh(channel);
if (hw_if->dev_read(channel))
break;
@@ -1168,9 +1646,15 @@ read_again:
incomplete = XGMAC_GET_BITS(packet->attributes,
RX_PACKET_ATTRIBUTES,
INCOMPLETE);
+ context_next = XGMAC_GET_BITS(packet->attributes,
+ RX_PACKET_ATTRIBUTES,
+ CONTEXT_NEXT);
+ context = XGMAC_GET_BITS(packet->attributes,
+ RX_PACKET_ATTRIBUTES,
+ CONTEXT);
/* Earlier error, just drain the remaining data */
- if (incomplete && error)
+ if ((incomplete || context_next) && error)
goto read_again;
if (error || packet->errors) {
@@ -1180,30 +1664,37 @@ read_again:
continue;
}
- put_len = rdata->len - cur_len;
- if (skb) {
- if (pskb_expand_head(skb, 0, put_len, GFP_ATOMIC)) {
- DBGPR("pskb_expand_head error\n");
- if (incomplete) {
- error = 1;
- goto read_again;
+ if (!context) {
+ put_len = rdata->len - len;
+ if (skb) {
+ if (pskb_expand_head(skb, 0, put_len,
+ GFP_ATOMIC)) {
+ DBGPR("pskb_expand_head error\n");
+ if (incomplete) {
+ error = 1;
+ goto read_again;
+ }
+
+ dev_kfree_skb(skb);
+ continue;
}
-
- dev_kfree_skb(skb);
- continue;
+ memcpy(skb_tail_pointer(skb), rdata->skb->data,
+ put_len);
+ } else {
+ skb = rdata->skb;
+ rdata->skb = NULL;
}
- memcpy(skb_tail_pointer(skb), rdata->skb->data,
- put_len);
- } else {
- skb = rdata->skb;
- rdata->skb = NULL;
+ skb_put(skb, put_len);
+ len += put_len;
}
- skb_put(skb, put_len);
- cur_len += put_len;
- if (incomplete)
+ if (incomplete || context_next)
goto read_again;
+ /* Stray Context Descriptor? */
+ if (!skb)
+ continue;
+
/* Be sure we don't exceed the configured MTU */
max_len = netdev->mtu + ETH_HLEN;
if (!(netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
@@ -1230,6 +1721,16 @@ read_again:
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
packet->vlan_ctag);
+ if (XGMAC_GET_BITS(packet->attributes,
+ RX_PACKET_ATTRIBUTES, RX_TSTAMP)) {
+ u64 nsec;
+
+ nsec = timecounter_cyc2time(&pdata->tstamp_tc,
+ packet->rx_tstamp);
+ hwtstamps = skb_hwtstamps(skb);
+ hwtstamps->hwtstamp = ns_to_ktime(nsec);
+ }
+
skb->dev = netdev;
skb->protocol = eth_type_trans(skb, netdev);
skb_record_rx_queue(skb, channel->queue_index);
@@ -1239,14 +1740,15 @@ read_again:
napi_gro_receive(&pdata->napi, skb);
}
- if (received) {
- desc_if->realloc_skb(channel);
-
- /* Update the Rx Tail Pointer Register with address of
- * the last cleaned entry */
- rdata = GET_DESC_DATA(ring, ring->rx.realloc_index - 1);
- XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO,
- lower_32_bits(rdata->rdesc_dma));
+ /* Check if we need to save state before leaving */
+ if (received && (incomplete || context_next)) {
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
+ rdata->state_saved = 1;
+ rdata->state.incomplete = incomplete;
+ rdata->state.context_next = context_next;
+ rdata->state.skb = skb;
+ rdata->state.len = len;
+ rdata->state.error = error;
}
DBGPR("<--xgbe_rx_poll: received = %d\n", received);
@@ -1259,21 +1761,28 @@ static int xgbe_poll(struct napi_struct *napi, int budget)
struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data,
napi);
struct xgbe_channel *channel;
- int processed;
+ int ring_budget;
+ int processed, last_processed;
unsigned int i;
DBGPR("-->xgbe_poll: budget=%d\n", budget);
- /* Cleanup Tx ring first */
- channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++)
- xgbe_tx_poll(channel);
-
- /* Process Rx ring next */
processed = 0;
- channel = pdata->channel;
- for (i = 0; i < pdata->channel_count; i++, channel++)
- processed += xgbe_rx_poll(channel, budget - processed);
+ ring_budget = budget / pdata->rx_ring_count;
+ do {
+ last_processed = processed;
+
+ channel = pdata->channel;
+ for (i = 0; i < pdata->channel_count; i++, channel++) {
+ /* Cleanup Tx ring first */
+ xgbe_tx_poll(channel);
+
+ /* Process Rx ring next */
+ if (ring_budget > (budget - processed))
+ ring_budget = budget - processed;
+ processed += xgbe_rx_poll(channel, ring_budget);
+ }
+ } while ((processed < budget) && (processed != last_processed));
/* If we processed everything, we are done */
if (processed < budget) {
@@ -1296,7 +1805,7 @@ void xgbe_dump_tx_desc(struct xgbe_ring *ring, unsigned int idx,
struct xgbe_ring_desc *rdesc;
while (count--) {
- rdata = GET_DESC_DATA(ring, idx);
+ rdata = XGBE_GET_DESC_DATA(ring, idx);
rdesc = rdata->rdesc;
DBGPR("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx,
(flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE",
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 8909f2b51af1..a076aca138a1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -116,6 +116,7 @@
#include <linux/spinlock.h>
#include <linux/phy.h>
+#include <linux/net_tstamp.h>
#include "xgbe.h"
#include "xgbe-common.h"
@@ -289,13 +290,9 @@ static int xgbe_get_settings(struct net_device *netdev,
if (!pdata->phydev)
return -ENODEV;
- spin_lock_irq(&pdata->lock);
-
ret = phy_ethtool_gset(pdata->phydev, cmd);
cmd->transceiver = XCVR_EXTERNAL;
- spin_unlock_irq(&pdata->lock);
-
DBGPR("<--xgbe_get_settings\n");
return ret;
@@ -314,36 +311,32 @@ static int xgbe_set_settings(struct net_device *netdev,
if (!pdata->phydev)
return -ENODEV;
- spin_lock_irq(&pdata->lock);
-
speed = ethtool_cmd_speed(cmd);
- ret = -EINVAL;
if (cmd->phy_address != phydev->addr)
- goto unlock;
+ return -EINVAL;
if ((cmd->autoneg != AUTONEG_ENABLE) &&
(cmd->autoneg != AUTONEG_DISABLE))
- goto unlock;
+ return -EINVAL;
- if ((cmd->autoneg == AUTONEG_DISABLE) &&
- (((speed != SPEED_10000) && (speed != SPEED_1000)) ||
- (cmd->duplex != DUPLEX_FULL)))
- goto unlock;
+ if (cmd->autoneg == AUTONEG_DISABLE) {
+ switch (speed) {
+ case SPEED_10000:
+ case SPEED_2500:
+ case SPEED_1000:
+ break;
+ default:
+ return -EINVAL;
+ }
- if (cmd->autoneg == AUTONEG_ENABLE) {
- /* Clear settings needed to force speeds */
- phydev->supported &= ~SUPPORTED_1000baseT_Full;
- phydev->supported &= ~SUPPORTED_10000baseT_Full;
- } else {
- /* Add settings needed to force speed */
- phydev->supported |= SUPPORTED_1000baseT_Full;
- phydev->supported |= SUPPORTED_10000baseT_Full;
+ if (cmd->duplex != DUPLEX_FULL)
+ return -EINVAL;
}
cmd->advertising &= phydev->supported;
if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
- goto unlock;
+ return -EINVAL;
ret = 0;
phydev->autoneg = cmd->autoneg;
@@ -359,9 +352,6 @@ static int xgbe_set_settings(struct net_device *netdev,
if (netif_running(netdev))
ret = phy_start_aneg(phydev);
-unlock:
- spin_unlock_irq(&pdata->lock);
-
DBGPR("<--xgbe_set_settings\n");
return ret;
@@ -490,6 +480,39 @@ static int xgbe_set_coalesce(struct net_device *netdev,
return 0;
}
+static int xgbe_get_ts_info(struct net_device *netdev,
+ struct ethtool_ts_info *ts_info)
+{
+ struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+ ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ if (pdata->ptp_clock)
+ ts_info->phc_index = ptp_clock_index(pdata->ptp_clock);
+ else
+ ts_info->phc_index = -1;
+
+ ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+ ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+ (1 << HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static const struct ethtool_ops xgbe_ethtool_ops = {
.get_settings = xgbe_get_settings,
.set_settings = xgbe_set_settings,
@@ -502,6 +525,7 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
.get_strings = xgbe_get_strings,
.get_ethtool_stats = xgbe_get_ethtool_stats,
.get_sset_count = xgbe_get_sset_count,
+ .get_ts_info = xgbe_get_ts_info,
};
struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 5a1891faba8a..8aa6a9353f7b 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -245,18 +245,19 @@ static int xgbe_probe(struct platform_device *pdev)
spin_lock_init(&pdata->lock);
mutex_init(&pdata->xpcs_mutex);
+ spin_lock_init(&pdata->tstamp_lock);
/* Set and validate the number of descriptors for a ring */
- BUILD_BUG_ON_NOT_POWER_OF_2(TX_DESC_CNT);
- pdata->tx_desc_count = TX_DESC_CNT;
+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
+ pdata->tx_desc_count = XGBE_TX_DESC_CNT;
if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) {
dev_err(dev, "tx descriptor count (%d) is not valid\n",
pdata->tx_desc_count);
ret = -EINVAL;
goto err_io;
}
- BUILD_BUG_ON_NOT_POWER_OF_2(RX_DESC_CNT);
- pdata->rx_desc_count = RX_DESC_CNT;
+ BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
+ pdata->rx_desc_count = XGBE_RX_DESC_CNT;
if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) {
dev_err(dev, "rx descriptor count (%d) is not valid\n",
pdata->rx_desc_count);
@@ -265,10 +266,18 @@ static int xgbe_probe(struct platform_device *pdev)
}
/* Obtain the system clock setting */
- pdata->sysclock = devm_clk_get(dev, NULL);
- if (IS_ERR(pdata->sysclock)) {
- dev_err(dev, "devm_clk_get failed\n");
- ret = PTR_ERR(pdata->sysclock);
+ pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
+ if (IS_ERR(pdata->sysclk)) {
+ dev_err(dev, "dma devm_clk_get failed\n");
+ ret = PTR_ERR(pdata->sysclk);
+ goto err_io;
+ }
+
+ /* Obtain the PTP clock setting */
+ pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
+ if (IS_ERR(pdata->ptpclk)) {
+ dev_err(dev, "ptp devm_clk_get failed\n");
+ ret = PTR_ERR(pdata->ptpclk);
goto err_io;
}
@@ -294,8 +303,21 @@ static int xgbe_probe(struct platform_device *pdev)
/* Set the DMA mask */
if (!dev->dma_mask)
dev->dma_mask = &dev->coherent_dma_mask;
- *(dev->dma_mask) = DMA_BIT_MASK(40);
- dev->coherent_dma_mask = DMA_BIT_MASK(40);
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ if (ret) {
+ dev_err(dev, "dma_set_mask_and_coherent failed\n");
+ goto err_io;
+ }
+
+ if (of_property_read_bool(dev->of_node, "dma-coherent")) {
+ pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+ pdata->arcache = XGBE_DMA_OS_ARCACHE;
+ pdata->awcache = XGBE_DMA_OS_AWCACHE;
+ } else {
+ pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
+ pdata->arcache = XGBE_DMA_SYS_ARCACHE;
+ pdata->awcache = XGBE_DMA_SYS_AWCACHE;
+ }
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
@@ -336,9 +358,16 @@ static int xgbe_probe(struct platform_device *pdev)
/* Set default configuration data */
xgbe_default_config(pdata);
- /* Calculate the number of Tx and Rx rings to be created */
+ /* Calculate the number of Tx and Rx rings to be created
+ * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
+ * the number of Tx queues to the number of Tx channels
+ * enabled
+ * -Rx (DMA) Channels do not map 1-to-1 so use the actual
+ * number of Rx queues
+ */
pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
pdata->hw_feat.tx_ch_cnt);
+ pdata->tx_q_count = pdata->tx_ring_count;
ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
if (ret) {
dev_err(dev, "error setting real tx queue count\n");
@@ -348,6 +377,7 @@ static int xgbe_probe(struct platform_device *pdev)
pdata->rx_ring_count = min_t(unsigned int,
netif_get_num_default_rss_queues(),
pdata->hw_feat.rx_ch_cnt);
+ pdata->rx_q_count = pdata->hw_feat.rx_q_cnt;
ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
if (ret) {
dev_err(dev, "error setting real rx queue count\n");
@@ -373,9 +403,12 @@ static int xgbe_probe(struct platform_device *pdev)
if (ret)
goto err_bus_id;
- /* Set network and ethtool operations */
+ /* Set device operations */
netdev->netdev_ops = xgbe_get_netdev_ops();
netdev->ethtool_ops = xgbe_get_ethtool_ops();
+#ifdef CONFIG_AMD_XGBE_DCB
+ netdev->dcbnl_ops = xgbe_get_dcbnl_ops();
+#endif
/* Set device features */
netdev->hw_features = NETIF_F_SG |
@@ -386,7 +419,8 @@ static int xgbe_probe(struct platform_device *pdev)
NETIF_F_TSO6 |
NETIF_F_GRO |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_VLAN_CTAG_TX;
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_FILTER;
netdev->vlan_features |= NETIF_F_SG |
NETIF_F_IP_CSUM |
@@ -397,6 +431,8 @@ static int xgbe_probe(struct platform_device *pdev)
netdev->features |= netdev->hw_features;
pdata->netdev_features = netdev->features;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
xgbe_init_rx_coalesce(pdata);
xgbe_init_tx_coalesce(pdata);
@@ -407,6 +443,8 @@ static int xgbe_probe(struct platform_device *pdev)
goto err_reg_netdev;
}
+ xgbe_ptp_register(pdata);
+
xgbe_debugfs_init(pdata);
netdev_notice(netdev, "net device enabled\n");
@@ -439,6 +477,8 @@ static int xgbe_remove(struct platform_device *pdev)
xgbe_debugfs_exit(pdata);
+ xgbe_ptp_unregister(pdata);
+
unregister_netdev(netdev);
xgbe_mdio_unregister(pdata);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index ea7a5d6750ea..6d2221e023f4 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -116,7 +116,6 @@
#include <linux/module.h>
#include <linux/kmod.h>
-#include <linux/spinlock.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/of.h>
@@ -158,82 +157,6 @@ static int xgbe_mdio_write(struct mii_bus *mii, int prtad, int mmd_reg,
return 0;
}
-static void xgbe_adjust_link(struct net_device *netdev)
-{
- struct xgbe_prv_data *pdata = netdev_priv(netdev);
- struct xgbe_hw_if *hw_if = &pdata->hw_if;
- struct phy_device *phydev = pdata->phydev;
- unsigned long flags;
- int new_state = 0;
-
- if (phydev == NULL)
- return;
-
- DBGPR_MDIO("-->xgbe_adjust_link: address=%d, newlink=%d, curlink=%d\n",
- phydev->addr, phydev->link, pdata->phy_link);
-
- spin_lock_irqsave(&pdata->lock, flags);
-
- if (phydev->link) {
- /* Flow control support */
- if (pdata->pause_autoneg) {
- if (phydev->pause || phydev->asym_pause) {
- pdata->tx_pause = 1;
- pdata->rx_pause = 1;
- } else {
- pdata->tx_pause = 0;
- pdata->rx_pause = 0;
- }
- }
-
- if (pdata->tx_pause != pdata->phy_tx_pause) {
- hw_if->config_tx_flow_control(pdata);
- pdata->phy_tx_pause = pdata->tx_pause;
- }
-
- if (pdata->rx_pause != pdata->phy_rx_pause) {
- hw_if->config_rx_flow_control(pdata);
- pdata->phy_rx_pause = pdata->rx_pause;
- }
-
- /* Speed support */
- if (phydev->speed != pdata->phy_speed) {
- new_state = 1;
-
- switch (phydev->speed) {
- case SPEED_10000:
- hw_if->set_xgmii_speed(pdata);
- break;
-
- case SPEED_2500:
- hw_if->set_gmii_2500_speed(pdata);
- break;
-
- case SPEED_1000:
- hw_if->set_gmii_speed(pdata);
- break;
- }
- pdata->phy_speed = phydev->speed;
- }
-
- if (phydev->link != pdata->phy_link) {
- new_state = 1;
- pdata->phy_link = 1;
- }
- } else if (pdata->phy_link) {
- new_state = 1;
- pdata->phy_link = 0;
- pdata->phy_speed = SPEED_UNKNOWN;
- }
-
- if (new_state)
- phy_print_status(phydev);
-
- spin_unlock_irqrestore(&pdata->lock, flags);
-
- DBGPR_MDIO("<--xgbe_adjust_link\n");
-}
-
void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
{
struct device *dev = pdata->dev;
@@ -283,7 +206,6 @@ void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
int xgbe_mdio_register(struct xgbe_prv_data *pdata)
{
- struct net_device *netdev = pdata->netdev;
struct device_node *phy_node;
struct mii_bus *mii;
struct phy_device *phydev;
@@ -298,7 +220,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
return -EINVAL;
}
- /* Register with the MDIO bus */
mii = mdiobus_alloc();
if (mii == NULL) {
dev_err(pdata->dev, "mdiobus_alloc failed\n");
@@ -353,32 +274,8 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
pdata->mii = mii;
pdata->mdio_mmd = MDIO_MMD_PCS;
- pdata->phy_link = -1;
- pdata->phy_speed = SPEED_UNKNOWN;
- pdata->phy_tx_pause = pdata->tx_pause;
- pdata->phy_rx_pause = pdata->rx_pause;
-
- ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
- pdata->phy_mode);
- if (ret) {
- netdev_err(netdev, "phy_connect_direct failed\n");
- goto err_phy_device;
- }
-
- if (!phydev->drv || (phydev->drv->phy_id == 0)) {
- netdev_err(netdev, "phy_id not valid\n");
- ret = -ENODEV;
- goto err_phy_connect;
- }
- DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n",
- dev_name(&phydev->dev), phydev->link);
-
phydev->autoneg = pdata->default_autoneg;
if (phydev->autoneg == AUTONEG_DISABLE) {
- /* Add settings needed to force speed */
- phydev->supported |= SUPPORTED_1000baseT_Full;
- phydev->supported |= SUPPORTED_10000baseT_Full;
-
phydev->speed = pdata->default_speed;
phydev->duplex = DUPLEX_FULL;
@@ -395,9 +292,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata)
return 0;
-err_phy_connect:
- phy_disconnect(phydev);
-
err_phy_device:
phy_device_free(phydev);
@@ -417,7 +311,6 @@ void xgbe_mdio_unregister(struct xgbe_prv_data *pdata)
{
DBGPR("-->xgbe_mdio_unregister\n");
- phy_disconnect(pdata->phydev);
pdata->phydev = NULL;
module_put(pdata->phy_module);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
new file mode 100644
index 000000000000..37e64cfa5718
--- /dev/null
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
@@ -0,0 +1,285 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file 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/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and the Software, to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ * The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ * Inc. unless otherwise expressly agreed to in writing between Synopsys
+ * and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product
+ * under any End User Software License Agreement or Agreement for Licensed
+ * Product with Synopsys or any supplement thereto. Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software
+ * annotated with this license and the Software, to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/net_tstamp.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+
+static cycle_t xgbe_cc_read(const struct cyclecounter *cc)
+{
+ struct xgbe_prv_data *pdata = container_of(cc,
+ struct xgbe_prv_data,
+ tstamp_cc);
+ u64 nsec;
+
+ nsec = pdata->hw_if.get_tstamp_time(pdata);
+
+ return nsec;
+}
+
+static int xgbe_adjfreq(struct ptp_clock_info *info, s32 delta)
+{
+ struct xgbe_prv_data *pdata = container_of(info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+ u64 adjust;
+ u32 addend, diff;
+ unsigned int neg_adjust = 0;
+
+ if (delta < 0) {
+ neg_adjust = 1;
+ delta = -delta;
+ }
+
+ adjust = pdata->tstamp_addend;
+ adjust *= delta;
+ diff = div_u64(adjust, 1000000000UL);
+
+ addend = (neg_adjust) ? pdata->tstamp_addend - diff :
+ pdata->tstamp_addend + diff;
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+ pdata->hw_if.update_tstamp_addend(pdata, addend);
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+ return 0;
+}
+
+static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
+{
+ struct xgbe_prv_data *pdata = container_of(info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+ u64 nsec;
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+ nsec = timecounter_read(&pdata->tstamp_tc);
+
+ nsec += delta;
+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+ return 0;
+}
+
+static int xgbe_gettime(struct ptp_clock_info *info, struct timespec *ts)
+{
+ struct xgbe_prv_data *pdata = container_of(info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+ u64 nsec;
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+ nsec = timecounter_read(&pdata->tstamp_tc);
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+ *ts = ns_to_timespec(nsec);
+
+ return 0;
+}
+
+static int xgbe_settime(struct ptp_clock_info *info, const struct timespec *ts)
+{
+ struct xgbe_prv_data *pdata = container_of(info,
+ struct xgbe_prv_data,
+ ptp_clock_info);
+ unsigned long flags;
+ u64 nsec;
+
+ nsec = timespec_to_ns(ts);
+
+ spin_lock_irqsave(&pdata->tstamp_lock, flags);
+
+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+
+ spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
+
+ return 0;
+}
+
+static int xgbe_enable(struct ptp_clock_info *info,
+ struct ptp_clock_request *request, int on)
+{
+ return -EOPNOTSUPP;
+}
+
+void xgbe_ptp_register(struct xgbe_prv_data *pdata)
+{
+ struct ptp_clock_info *info = &pdata->ptp_clock_info;
+ struct ptp_clock *clock;
+ struct cyclecounter *cc = &pdata->tstamp_cc;
+ u64 dividend;
+
+ snprintf(info->name, sizeof(info->name), "%s",
+ netdev_name(pdata->netdev));
+ info->owner = THIS_MODULE;
+ info->max_adj = clk_get_rate(pdata->ptpclk);
+ info->adjfreq = xgbe_adjfreq;
+ info->adjtime = xgbe_adjtime;
+ info->gettime = xgbe_gettime;
+ info->settime = xgbe_settime;
+ info->enable = xgbe_enable;
+
+ clock = ptp_clock_register(info, pdata->dev);
+ if (IS_ERR(clock)) {
+ dev_err(pdata->dev, "ptp_clock_register failed\n");
+ return;
+ }
+
+ pdata->ptp_clock = clock;
+
+ /* Calculate the addend:
+ * addend = 2^32 / (PTP ref clock / 50Mhz)
+ * = (2^32 * 50Mhz) / PTP ref clock
+ */
+ dividend = 50000000;
+ dividend <<= 32;
+ pdata->tstamp_addend = div_u64(dividend, clk_get_rate(pdata->ptpclk));
+
+ /* Setup the timecounter */
+ cc->read = xgbe_cc_read;
+ cc->mask = CLOCKSOURCE_MASK(64);
+ cc->mult = 1;
+ cc->shift = 0;
+
+ timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
+ ktime_to_ns(ktime_get_real()));
+
+ /* Disable all timestamping to start */
+ XGMAC_IOWRITE(pdata, MAC_TCR, 0);
+ pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+ pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+}
+
+void xgbe_ptp_unregister(struct xgbe_prv_data *pdata)
+{
+ if (pdata->ptp_clock)
+ ptp_clock_unregister(pdata->ptp_clock);
+}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ab0627162c01..07bf70a82908 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -121,6 +121,12 @@
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/phy.h>
+#include <linux/if_vlan.h>
+#include <linux/bitops.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <net/dcbnl.h>
#define XGBE_DRV_NAME "amd-xgbe"
@@ -128,22 +134,30 @@
#define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver"
/* Descriptor related defines */
-#define TX_DESC_CNT 512
-#define TX_DESC_MIN_FREE (TX_DESC_CNT >> 3)
-#define TX_DESC_MAX_PROC (TX_DESC_CNT >> 1)
-#define RX_DESC_CNT 512
+#define XGBE_TX_DESC_CNT 512
+#define XGBE_TX_DESC_MIN_FREE (XGBE_TX_DESC_CNT >> 3)
+#define XGBE_TX_DESC_MAX_PROC (XGBE_TX_DESC_CNT >> 1)
+#define XGBE_RX_DESC_CNT 512
-#define TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
+#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
-#define RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
-#define RX_BUF_ALIGN 64
+#define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
+#define XGBE_RX_BUF_ALIGN 64
#define XGBE_MAX_DMA_CHANNELS 16
-#define DMA_ARDOMAIN_SETTING 0x2
-#define DMA_ARCACHE_SETTING 0xb
-#define DMA_AWDOMAIN_SETTING 0x2
-#define DMA_AWCACHE_SETTING 0x7
-#define DMA_INTERRUPT_MASK 0x31c7
+#define XGBE_MAX_QUEUES 16
+
+/* DMA cache settings - Outer sharable, write-back, write-allocate */
+#define XGBE_DMA_OS_AXDOMAIN 0x2
+#define XGBE_DMA_OS_ARCACHE 0xb
+#define XGBE_DMA_OS_AWCACHE 0xf
+
+/* DMA cache settings - System, no caches used */
+#define XGBE_DMA_SYS_AXDOMAIN 0x3
+#define XGBE_DMA_SYS_ARCACHE 0x0
+#define XGBE_DMA_SYS_AWCACHE 0x0
+
+#define XGBE_DMA_INTERRUPT_MASK 0x31c7
#define XGMAC_MIN_PACKET 60
#define XGMAC_STD_PACKET_MTU 1500
@@ -151,45 +165,53 @@
#define XGMAC_JUMBO_PACKET_MTU 9000
#define XGMAC_MAX_JUMBO_PACKET 9018
-#define MAX_MULTICAST_LIST 14
-#define TX_FLAGS_IP_PKT 0x00000001
-#define TX_FLAGS_TCP_PKT 0x00000002
-
/* MDIO bus phy name */
#define XGBE_PHY_NAME "amd_xgbe_phy"
#define XGBE_PRTAD 0
+/* Device-tree clock names */
+#define XGBE_DMA_CLOCK "dma_clk"
+#define XGBE_PTP_CLOCK "ptp_clk"
+
+/* Timestamp support - values based on 50MHz PTP clock
+ * 50MHz => 20 nsec
+ */
+#define XGBE_TSTAMP_SSINC 20
+#define XGBE_TSTAMP_SNSINC 0
+
/* Driver PMT macros */
#define XGMAC_DRIVER_CONTEXT 1
#define XGMAC_IOCTL_CONTEXT 2
-#define FIFO_SIZE_B(x) (x)
-#define FIFO_SIZE_KB(x) (x * 1024)
+#define XGBE_FIFO_SIZE_B(x) (x)
+#define XGBE_FIFO_SIZE_KB(x) (x * 1024)
-#define XGBE_TC_CNT 2
+#define XGBE_TC_MIN_QUANTUM 10
/* Helper macro for descriptor handling
- * Always use GET_DESC_DATA to access the descriptor data
+ * Always use XGBE_GET_DESC_DATA to access the descriptor data
* since the index is free-running and needs to be and-ed
* with the descriptor count value of the ring to index to
* the proper descriptor data.
*/
-#define GET_DESC_DATA(_ring, _idx) \
+#define XGBE_GET_DESC_DATA(_ring, _idx) \
((_ring)->rdata + \
((_idx) & ((_ring)->rdesc_count - 1)))
/* Default coalescing parameters */
-#define XGMAC_INIT_DMA_TX_USECS 100
-#define XGMAC_INIT_DMA_TX_FRAMES 16
+#define XGMAC_INIT_DMA_TX_USECS 50
+#define XGMAC_INIT_DMA_TX_FRAMES 25
#define XGMAC_MAX_DMA_RIWT 0xff
-#define XGMAC_INIT_DMA_RX_USECS 100
-#define XGMAC_INIT_DMA_RX_FRAMES 16
+#define XGMAC_INIT_DMA_RX_USECS 30
+#define XGMAC_INIT_DMA_RX_FRAMES 25
/* Flow control queue count */
#define XGMAC_MAX_FLOW_CONTROL_QUEUES 8
+/* Maximum MAC address hash table size (256 bits = 8 bytes) */
+#define XGBE_MAC_HASH_TABLE_SIZE 8
struct xgbe_prv_data;
@@ -207,6 +229,8 @@ struct xgbe_packet_data {
unsigned short mss;
unsigned short vlan_ctag;
+
+ u64 rx_tstamp;
};
/* Common Rx and Tx descriptor mapping */
@@ -219,7 +243,7 @@ struct xgbe_ring_desc {
/* Structure used to hold information related to the descriptor
* and the packet associated with the descriptor (always use
- * use the GET_DESC_DATA macro to access this data from the ring)
+ * use the XGBE_GET_DESC_DATA macro to access this data from the ring)
*/
struct xgbe_ring_data {
struct xgbe_ring_desc *rdesc; /* Virtual address of descriptor */
@@ -235,6 +259,20 @@ struct xgbe_ring_data {
unsigned int interrupt; /* Interrupt indicator */
unsigned int mapped_as_page;
+
+ /* Incomplete receive save location. If the budget is exhausted
+ * or the last descriptor (last normal descriptor or a following
+ * context descriptor) has not been DMA'd yet the current state
+ * of the receive processing needs to be saved.
+ */
+ unsigned int state_saved;
+ struct {
+ unsigned int incomplete;
+ unsigned int context_next;
+ struct sk_buff *skb;
+ unsigned int len;
+ unsigned int error;
+ } state;
};
struct xgbe_ring {
@@ -250,7 +288,7 @@ struct xgbe_ring {
unsigned int rdesc_count;
/* Array of descriptor data corresponding the descriptor memory
- * (always use the GET_DESC_DATA macro to access this data)
+ * (always use the XGBE_GET_DESC_DATA macro to access this data)
*/
struct xgbe_ring_data *rdata;
@@ -304,13 +342,13 @@ struct xgbe_channel {
} ____cacheline_aligned;
enum xgbe_int {
- XGMAC_INT_DMA_ISR_DC0IS,
XGMAC_INT_DMA_CH_SR_TI,
XGMAC_INT_DMA_CH_SR_TPS,
XGMAC_INT_DMA_CH_SR_TBU,
XGMAC_INT_DMA_CH_SR_RI,
XGMAC_INT_DMA_CH_SR_RBU,
XGMAC_INT_DMA_CH_SR_RPS,
+ XGMAC_INT_DMA_CH_SR_TI_RI,
XGMAC_INT_DMA_CH_SR_FBE,
XGMAC_INT_DMA_ALL,
};
@@ -386,7 +424,7 @@ struct xgbe_hw_if {
int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int);
int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int);
- int (*set_addn_mac_addrs)(struct xgbe_prv_data *, unsigned int);
+ int (*add_mac_addresses)(struct xgbe_prv_data *);
int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr);
int (*enable_rx_csum)(struct xgbe_prv_data *);
@@ -394,6 +432,9 @@ struct xgbe_hw_if {
int (*enable_rx_vlan_stripping)(struct xgbe_prv_data *);
int (*disable_rx_vlan_stripping)(struct xgbe_prv_data *);
+ int (*enable_rx_vlan_filtering)(struct xgbe_prv_data *);
+ int (*disable_rx_vlan_filtering)(struct xgbe_prv_data *);
+ int (*update_vlan_hash_table)(struct xgbe_prv_data *);
int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
@@ -457,6 +498,18 @@ struct xgbe_hw_if {
void (*rx_mmc_int)(struct xgbe_prv_data *);
void (*tx_mmc_int)(struct xgbe_prv_data *);
void (*read_mmc_stats)(struct xgbe_prv_data *);
+
+ /* For Timestamp config */
+ int (*config_tstamp)(struct xgbe_prv_data *, unsigned int);
+ void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int);
+ void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec,
+ unsigned int nsec);
+ u64 (*get_tstamp_time)(struct xgbe_prv_data *);
+ u64 (*get_tx_tstamp)(struct xgbe_prv_data *);
+
+ /* For Data Center Bridging config */
+ void (*config_dcb_tc)(struct xgbe_prv_data *);
+ void (*config_dcb_pfc)(struct xgbe_prv_data *);
};
struct xgbe_desc_if {
@@ -498,6 +551,7 @@ struct xgbe_hw_features {
unsigned int tso; /* TCP Segmentation Offload */
unsigned int dma_debug; /* DMA Debug Registers */
unsigned int rss; /* Receive Side Scaling */
+ unsigned int tc_cnt; /* Number of Traffic Classes */
unsigned int hash_table_size; /* Hash Table Size */
unsigned int l3l4_filter_num; /* Number of L3-L4 Filters */
@@ -530,6 +584,11 @@ struct xgbe_prv_data {
struct xgbe_hw_if hw_if;
struct xgbe_desc_if desc_if;
+ /* AXI DMA settings */
+ unsigned int axdomain;
+ unsigned int arcache;
+ unsigned int awcache;
+
/* Rings for Tx/Rx on a DMA channel */
struct xgbe_channel *channel;
unsigned int channel_count;
@@ -538,6 +597,9 @@ struct xgbe_prv_data {
unsigned int rx_ring_count;
unsigned int rx_desc_count;
+ unsigned int tx_q_count;
+ unsigned int rx_q_count;
+
/* Tx/Rx common settings */
unsigned int pblx8;
@@ -589,8 +651,30 @@ struct xgbe_prv_data {
struct napi_struct napi;
struct xgbe_mmc_stats mmc_stats;
- /* System clock value used for Rx watchdog */
- struct clk *sysclock;
+ /* Filtering support */
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
+
+ /* Device clocks */
+ struct clk *sysclk;
+ struct clk *ptpclk;
+
+ /* Timestamp support */
+ spinlock_t tstamp_lock;
+ struct ptp_clock_info ptp_clock_info;
+ struct ptp_clock *ptp_clock;
+ struct hwtstamp_config tstamp_config;
+ struct cyclecounter tstamp_cc;
+ struct timecounter tstamp_tc;
+ unsigned int tstamp_addend;
+ struct work_struct tx_tstamp_work;
+ struct sk_buff *tx_tstamp_skb;
+ u64 tx_tstamp;
+
+ /* DCB support */
+ struct ieee_ets *ets;
+ struct ieee_pfc *pfc;
+ unsigned int q2tc_map[XGBE_MAX_QUEUES];
+ unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS];
/* Hardware features of the device */
struct xgbe_hw_features hw_feat;
@@ -617,10 +701,15 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
struct net_device_ops *xgbe_get_netdev_ops(void);
struct ethtool_ops *xgbe_get_ethtool_ops(void);
+#ifdef CONFIG_AMD_XGBE_DCB
+const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void);
+#endif
int xgbe_mdio_register(struct xgbe_prv_data *);
void xgbe_mdio_unregister(struct xgbe_prv_data *);
void xgbe_dump_phy_registers(struct xgbe_prv_data *);
+void xgbe_ptp_register(struct xgbe_prv_data *);
+void xgbe_ptp_unregister(struct xgbe_prv_data *);
void xgbe_dump_tx_desc(struct xgbe_ring *, unsigned int, unsigned int,
unsigned int);
void xgbe_dump_rx_desc(struct xgbe_ring *, struct xgbe_ring_desc *,
diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig
new file mode 100644
index 000000000000..ec63d706d464
--- /dev/null
+++ b/drivers/net/ethernet/apm/Kconfig
@@ -0,0 +1 @@
+source "drivers/net/ethernet/apm/xgene/Kconfig"
diff --git a/drivers/net/ethernet/apm/Makefile b/drivers/net/ethernet/apm/Makefile
new file mode 100644
index 000000000000..65ce32ad1b2c
--- /dev/null
+++ b/drivers/net/ethernet/apm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for APM X-GENE Ethernet driver.
+#
+
+obj-$(CONFIG_NET_XGENE) += xgene/
diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
new file mode 100644
index 000000000000..616dff6d3f5f
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Kconfig
@@ -0,0 +1,9 @@
+config NET_XGENE
+ tristate "APM X-Gene SoC Ethernet Driver"
+ select PHYLIB
+ help
+ This is the Ethernet driver for the on-chip ethernet interface on the
+ APM X-Gene SoC.
+
+ To compile this driver as a module, choose M here. This module will
+ be called xgene_enet.
diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile
new file mode 100644
index 000000000000..c643e8a0a0dc
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for APM X-Gene Ethernet Driver.
+#
+
+xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o
+obj-$(CONFIG_NET_XGENE) += xgene-enet.o
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
new file mode 100644
index 000000000000..63f2aa54a594
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
@@ -0,0 +1,125 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/ethtool.h>
+#include "xgene_enet_main.h"
+
+struct xgene_gstrings_stats {
+ char name[ETH_GSTRING_LEN];
+ int offset;
+};
+
+#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) }
+
+static const struct xgene_gstrings_stats gstrings_stats[] = {
+ XGENE_STAT(rx_packets),
+ XGENE_STAT(tx_packets),
+ XGENE_STAT(rx_bytes),
+ XGENE_STAT(tx_bytes),
+ XGENE_STAT(rx_errors),
+ XGENE_STAT(tx_errors),
+ XGENE_STAT(rx_length_errors),
+ XGENE_STAT(rx_crc_errors),
+ XGENE_STAT(rx_frame_errors),
+ XGENE_STAT(rx_fifo_errors)
+};
+
+#define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats)
+
+static void xgene_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct platform_device *pdev = pdata->pdev;
+
+ strcpy(info->driver, "xgene_enet");
+ strcpy(info->version, XGENE_DRV_VERSION);
+ snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
+ sprintf(info->bus_info, "%s", pdev->name);
+}
+
+static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_gset(phydev, cmd);
+}
+
+static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev == NULL)
+ return -ENODEV;
+
+ return phy_ethtool_sset(phydev, cmd);
+}
+
+static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ int i;
+ u8 *p = data;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < XGENE_STATS_LEN; i++) {
+ memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+}
+
+static int xgene_get_sset_count(struct net_device *ndev, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return -EINVAL;
+
+ return XGENE_STATS_LEN;
+}
+
+static void xgene_get_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *dummy,
+ u64 *data)
+{
+ void *pdata = netdev_priv(ndev);
+ int i;
+
+ for (i = 0; i < XGENE_STATS_LEN; i++)
+ *data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
+}
+
+static const struct ethtool_ops xgene_ethtool_ops = {
+ .get_drvinfo = xgene_get_drvinfo,
+ .get_settings = xgene_get_settings,
+ .set_settings = xgene_set_settings,
+ .get_link = ethtool_op_get_link,
+ .get_strings = xgene_get_strings,
+ .get_sset_count = xgene_get_sset_count,
+ .get_ethtool_stats = xgene_get_ethtool_stats
+};
+
+void xgene_enet_set_ethtool_ops(struct net_device *ndev)
+{
+ ndev->ethtool_ops = &xgene_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
new file mode 100644
index 000000000000..812d8d65159b
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -0,0 +1,728 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+ u64 addr = ring->dma;
+ enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize;
+
+ ring_cfg[4] |= (1 << SELTHRSH_POS) &
+ CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN);
+ ring_cfg[3] |= ACCEPTLERR;
+ ring_cfg[2] |= QCOHERENT;
+
+ addr >>= 8;
+ ring_cfg[2] |= (addr << RINGADDRL_POS) &
+ CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN);
+ addr >>= RINGADDRL_LEN;
+ ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN);
+ ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) &
+ CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN);
+}
+
+static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+ bool is_bufpool;
+ u32 val;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR;
+ ring_cfg[4] |= (val << RINGTYPE_POS) &
+ CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN);
+
+ if (is_bufpool) {
+ ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) &
+ CREATE_MASK(RINGMODE_POS, RINGMODE_LEN);
+ }
+}
+
+static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring)
+{
+ u32 *ring_cfg = ring->state;
+
+ ring_cfg[3] |= RECOMBBUF;
+ ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) &
+ CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN);
+ ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN);
+}
+
+static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring,
+ u32 offset, u32 data)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ iowrite32(data, pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
+ u32 offset, u32 *data)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ *data = ioread32(pdata->ring_csr_addr + offset);
+}
+
+static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ int i;
+
+ xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
+ for (i = 0; i < NUM_RING_CONFIG; i++) {
+ xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
+ ring->state[i]);
+ }
+}
+
+static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG);
+ xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
+{
+ xgene_enet_ring_set_type(ring);
+
+ if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
+ xgene_enet_ring_set_recombbuf(ring);
+
+ xgene_enet_ring_init(ring);
+ xgene_enet_write_ring_state(ring);
+}
+
+static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring)
+{
+ u32 ring_id_val, ring_id_buf;
+ bool is_bufpool;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+
+ ring_id_val = ring->id & GENMASK(9, 0);
+ ring_id_val |= OVERWRITE;
+
+ ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
+ ring_id_buf |= PREFETCH_BUF_EN;
+ if (is_bufpool)
+ ring_id_buf |= IS_BUFFER_POOL;
+
+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val);
+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf);
+}
+
+static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
+{
+ u32 ring_id;
+
+ ring_id = ring->id | OVERWRITE;
+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id);
+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+ struct xgene_enet_desc_ring *ring)
+{
+ u32 size = ring->size;
+ u32 i, data;
+ bool is_bufpool;
+
+ xgene_enet_clr_ring_state(ring);
+ xgene_enet_set_ring_state(ring);
+ xgene_enet_set_ring_id(ring);
+
+ ring->slots = xgene_enet_get_numslots(ring->id, size);
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+ return ring;
+
+ for (i = 0; i < ring->slots; i++)
+ xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]);
+
+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+ data |= BIT(31 - xgene_enet_ring_bufnum(ring->id));
+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+ return ring;
+}
+
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
+{
+ u32 data;
+ bool is_bufpool;
+
+ is_bufpool = xgene_enet_is_bufpool(ring->id);
+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU)
+ goto out;
+
+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data);
+ data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id));
+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data);
+
+out:
+ xgene_enet_clr_desc_ring_id(ring);
+ xgene_enet_clr_ring_state(ring);
+}
+
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status)
+{
+ struct rtnl_link_stats64 *stats = &pdata->stats;
+
+ switch (status) {
+ case INGRESS_CRC:
+ stats->rx_crc_errors++;
+ break;
+ case INGRESS_CHECKSUM:
+ case INGRESS_CHECKSUM_COMPUTE:
+ stats->rx_errors++;
+ break;
+ case INGRESS_TRUNC_FRAME:
+ stats->rx_frame_errors++;
+ break;
+ case INGRESS_PKT_LEN:
+ stats->rx_length_errors++;
+ break;
+ case INGRESS_PKT_UNDER:
+ stats->rx_frame_errors++;
+ break;
+ case INGRESS_FIFO_OVERRUN:
+ stats->rx_fifo_errors++;
+ break;
+ default:
+ break;
+ }
+}
+
+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_ring_if_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ iowrite32(val, addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 wr_addr, u32 wr_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(wr_addr, addr);
+ iowrite32(wr_data, wr);
+ iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+ /* wait for write command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata,
+ u32 wr_addr, u32 wr_data)
+{
+ void __iomem *addr, *wr, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+ netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n",
+ wr_addr);
+}
+
+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->eth_diag_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
+ u32 offset, u32 *val)
+{
+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+ *val = ioread32(addr);
+}
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+ void __iomem *cmd, void __iomem *cmd_done,
+ u32 rd_addr, u32 *rd_data)
+{
+ u32 done;
+ u8 wait = 10;
+
+ iowrite32(rd_addr, addr);
+ iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+ /* wait for read command to complete */
+ while (!(done = ioread32(cmd_done)) && wait--)
+ udelay(1);
+
+ if (!done)
+ return false;
+
+ *rd_data = ioread32(rd);
+ iowrite32(0, cmd);
+
+ return true;
+}
+
+static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata,
+ u32 rd_addr, u32 *rd_data)
+{
+ void __iomem *addr, *rd, *cmd, *cmd_done;
+
+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET;
+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET;
+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET;
+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+ if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+ netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n",
+ rd_addr);
+}
+
+static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id,
+ u32 reg, u16 data)
+{
+ u32 addr = 0, wr_data = 0;
+ u32 done;
+ u8 wait = 10;
+
+ PHY_ADDR_SET(&addr, phy_id);
+ REG_ADDR_SET(&addr, reg);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+
+ PHY_CONTROL_SET(&wr_data, data);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data);
+ do {
+ usleep_range(5, 10);
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+ } while ((done & BUSY_MASK) && wait--);
+
+ if (done & BUSY_MASK) {
+ netdev_err(pdata->ndev, "MII_MGMT write failed\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata,
+ u8 phy_id, u32 reg)
+{
+ u32 addr = 0;
+ u32 data, done;
+ u8 wait = 10;
+
+ PHY_ADDR_SET(&addr, phy_id);
+ REG_ADDR_SET(&addr, reg);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+ do {
+ usleep_range(5, 10);
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+ } while ((done & BUSY_MASK) && wait--);
+
+ if (done & BUSY_MASK) {
+ netdev_err(pdata->ndev, "MII_MGMT read failed\n");
+ return -EBUSY;
+ }
+
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
+
+ return data;
+}
+
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+{
+ u32 addr0, addr1;
+ u8 *dev_addr = pdata->ndev->dev_addr;
+
+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+ addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
+ addr1 |= pdata->phy_addr & 0xFFFF;
+
+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0);
+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1);
+}
+
+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ u32 data;
+ u8 wait = 10;
+
+ xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+ do {
+ usleep_range(100, 110);
+ xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data);
+ } while ((data != 0xffffffff) && wait--);
+
+ if (data != 0xffffffff) {
+ netdev_err(ndev, "Failed to release memory from shutdown\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
+{
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
+}
+
+void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed)
+{
+ u32 value, mc2;
+ u32 intf_ctl, rgmii;
+ u32 icm0, icm2;
+
+ xgene_gmac_reset(pdata);
+
+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2);
+ xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl);
+ xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
+
+ switch (speed) {
+ case SPEED_10:
+ ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ CFG_MACMODE_SET(&icm0, 0);
+ CFG_WAITASYNCRD_SET(&icm2, 500);
+ rgmii &= ~CFG_SPEED_1250;
+ break;
+ case SPEED_100:
+ ENET_INTERFACE_MODE2_SET(&mc2, 1);
+ intf_ctl |= ENET_LHD_MODE;
+ CFG_MACMODE_SET(&icm0, 1);
+ CFG_WAITASYNCRD_SET(&icm2, 80);
+ rgmii &= ~CFG_SPEED_1250;
+ break;
+ default:
+ ENET_INTERFACE_MODE2_SET(&mc2, 2);
+ intf_ctl |= ENET_GHD_MODE;
+ CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
+ xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
+ value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+ xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
+ break;
+ }
+
+ mc2 |= FULL_DUPLEX2;
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
+ xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
+
+ xgene_gmac_set_mac_addr(pdata);
+
+ /* Adjust MDC clock frequency */
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value);
+ MGMT_CLOCK_SEL_SET(&value, 7);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value);
+
+ /* Enable drop if bufpool not available */
+ xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
+ value |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+ xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value);
+
+ /* Rtype should be copied from FP */
+ xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
+ xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+
+ /* Rx-Tx traffic resume */
+ xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
+
+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
+
+ xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
+ value &= ~TX_DV_GATE_EN0;
+ value &= ~RX_DV_GATE_EN0;
+ value |= RESUME_RX0;
+ xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value);
+
+ xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX);
+}
+
+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
+{
+ u32 val = 0xffffffff;
+
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val);
+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val);
+}
+
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id)
+{
+ u32 cb;
+ u32 fpsel;
+
+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+
+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
+ cb |= CFG_CLE_BYPASS_EN0;
+ CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb);
+
+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
+ CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
+ CFG_CLE_FPSEL0_SET(&cb, fpsel);
+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
+}
+
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
+}
+
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
+}
+
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
+}
+
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
+{
+ u32 data;
+
+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
+}
+
+void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+{
+ u32 val;
+
+ clk_prepare_enable(pdata->clk);
+ clk_disable_unprepare(pdata->clk);
+ clk_prepare_enable(pdata->clk);
+ xgene_enet_ecc_init(pdata);
+ xgene_enet_config_ring_if_assoc(pdata);
+
+ /* Enable auto-incr for scanning */
+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
+ val |= SCAN_AUTO_INCR;
+ MGMT_CLOCK_SEL_SET(&val, 1);
+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
+}
+
+void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
+{
+ clk_disable_unprepare(pdata->clk);
+}
+
+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct xgene_enet_pdata *pdata = bus->priv;
+ u32 val;
+
+ val = xgene_mii_phy_read(pdata, mii_id, regnum);
+ netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n",
+ mii_id, regnum, val);
+
+ return val;
+}
+
+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 val)
+{
+ struct xgene_enet_pdata *pdata = bus->priv;
+
+ netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n",
+ mii_id, regnum, val);
+ return xgene_mii_phy_write(pdata, mii_id, regnum, val);
+}
+
+static void xgene_enet_adjust_link(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct phy_device *phydev = pdata->phy_dev;
+
+ if (phydev->link) {
+ if (pdata->phy_speed != phydev->speed) {
+ xgene_gmac_init(pdata, phydev->speed);
+ xgene_gmac_rx_enable(pdata);
+ xgene_gmac_tx_enable(pdata);
+ pdata->phy_speed = phydev->speed;
+ phy_print_status(phydev);
+ }
+ } else {
+ xgene_gmac_rx_disable(pdata);
+ xgene_gmac_tx_disable(pdata);
+ pdata->phy_speed = SPEED_UNKNOWN;
+ phy_print_status(phydev);
+ }
+}
+
+static int xgene_enet_phy_connect(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device_node *phy_np;
+ struct phy_device *phy_dev;
+ struct device *dev = &pdata->pdev->dev;
+
+ phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0);
+ if (!phy_np) {
+ netdev_dbg(ndev, "No phy-handle found\n");
+ return -ENODEV;
+ }
+
+ phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+ 0, pdata->phy_mode);
+ if (!phy_dev) {
+ netdev_err(ndev, "Could not connect to PHY\n");
+ return -ENODEV;
+ }
+
+ pdata->phy_speed = SPEED_UNKNOWN;
+ phy_dev->supported &= ~SUPPORTED_10baseT_Half &
+ ~SUPPORTED_100baseT_Half &
+ ~SUPPORTED_1000baseT_Half;
+ phy_dev->advertising = phy_dev->supported;
+ pdata->phy_dev = phy_dev;
+
+ return 0;
+}
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ struct device *dev = &pdata->pdev->dev;
+ struct device_node *child_np;
+ struct device_node *mdio_np = NULL;
+ struct mii_bus *mdio_bus;
+ int ret;
+
+ for_each_child_of_node(dev->of_node, child_np) {
+ if (of_device_is_compatible(child_np, "apm,xgene-mdio")) {
+ mdio_np = child_np;
+ break;
+ }
+ }
+
+ if (!mdio_np) {
+ netdev_dbg(ndev, "No mdio node in the dts\n");
+ return -ENXIO;
+ }
+
+ mdio_bus = mdiobus_alloc();
+ if (!mdio_bus)
+ return -ENOMEM;
+
+ mdio_bus->name = "APM X-Gene MDIO bus";
+ mdio_bus->read = xgene_enet_mdio_read;
+ mdio_bus->write = xgene_enet_mdio_write;
+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii",
+ ndev->name);
+
+ mdio_bus->priv = pdata;
+ mdio_bus->parent = &ndev->dev;
+
+ ret = of_mdiobus_register(mdio_bus, mdio_np);
+ if (ret) {
+ netdev_err(ndev, "Failed to register MDIO bus\n");
+ mdiobus_free(mdio_bus);
+ return ret;
+ }
+ pdata->mdio_bus = mdio_bus;
+
+ ret = xgene_enet_phy_connect(ndev);
+ if (ret)
+ xgene_enet_mdio_remove(pdata);
+
+ return ret;
+}
+
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
+{
+ mdiobus_unregister(pdata->mdio_bus);
+ mdiobus_free(pdata->mdio_bus);
+ pdata->mdio_bus = NULL;
+}
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
new file mode 100644
index 000000000000..371e7a5b2507
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -0,0 +1,337 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_HW_H__
+#define __XGENE_ENET_HW_H__
+
+#include "xgene_enet_main.h"
+
+struct xgene_enet_pdata;
+struct xgene_enet_stats;
+
+/* clears and then set bits */
+static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len)
+{
+ u32 end = start + len - 1;
+ u32 mask = GENMASK(end, start);
+
+ *dst &= ~mask;
+ *dst |= (val << start) & mask;
+}
+
+static inline u32 xgene_get_bits(u32 val, u32 start, u32 end)
+{
+ return (val & GENMASK(end, start)) >> start;
+}
+
+#define CSR_RING_ID 0x0008
+#define OVERWRITE BIT(31)
+#define IS_BUFFER_POOL BIT(20)
+#define PREFETCH_BUF_EN BIT(21)
+#define CSR_RING_ID_BUF 0x000c
+#define CSR_RING_NE_INT_MODE 0x017c
+#define CSR_RING_CONFIG 0x006c
+#define CSR_RING_WR_BASE 0x0070
+#define NUM_RING_CONFIG 5
+#define BUFPOOL_MODE 3
+#define RM3 3
+#define INC_DEC_CMD_ADDR 0x002c
+#define UDP_HDR_SIZE 2
+#define BUF_LEN_CODE_2K 0x5000
+
+#define CREATE_MASK(pos, len) GENMASK((pos)+(len)-1, (pos))
+#define CREATE_MASK_ULL(pos, len) GENMASK_ULL((pos)+(len)-1, (pos))
+
+/* Empty slot soft signature */
+#define EMPTY_SLOT_INDEX 1
+#define EMPTY_SLOT ~0ULL
+
+#define WORK_DESC_SIZE 32
+#define BUFPOOL_DESC_SIZE 16
+
+#define RING_OWNER_MASK GENMASK(9, 6)
+#define RING_BUFNUM_MASK GENMASK(5, 0)
+
+#define SELTHRSH_POS 3
+#define SELTHRSH_LEN 3
+#define RINGADDRL_POS 5
+#define RINGADDRL_LEN 27
+#define RINGADDRH_POS 0
+#define RINGADDRH_LEN 6
+#define RINGSIZE_POS 23
+#define RINGSIZE_LEN 3
+#define RINGTYPE_POS 19
+#define RINGTYPE_LEN 2
+#define RINGMODE_POS 20
+#define RINGMODE_LEN 3
+#define RECOMTIMEOUTL_POS 28
+#define RECOMTIMEOUTL_LEN 3
+#define RECOMTIMEOUTH_POS 0
+#define RECOMTIMEOUTH_LEN 2
+#define NUMMSGSINQ_POS 1
+#define NUMMSGSINQ_LEN 16
+#define ACCEPTLERR BIT(19)
+#define QCOHERENT BIT(4)
+#define RECOMBBUF BIT(27)
+
+#define BLOCK_ETH_CSR_OFFSET 0x2000
+#define BLOCK_ETH_RING_IF_OFFSET 0x9000
+#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000
+#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
+
+#define BLOCK_ETH_MAC_OFFSET 0x0000
+#define BLOCK_ETH_STATS_OFFSET 0x0014
+#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
+
+#define MAC_ADDR_REG_OFFSET 0x00
+#define MAC_COMMAND_REG_OFFSET 0x04
+#define MAC_WRITE_REG_OFFSET 0x08
+#define MAC_READ_REG_OFFSET 0x0c
+#define MAC_COMMAND_DONE_REG_OFFSET 0x10
+
+#define STAT_ADDR_REG_OFFSET 0x00
+#define STAT_COMMAND_REG_OFFSET 0x04
+#define STAT_WRITE_REG_OFFSET 0x08
+#define STAT_READ_REG_OFFSET 0x0c
+#define STAT_COMMAND_DONE_REG_OFFSET 0x10
+
+#define MII_MGMT_CONFIG_ADDR 0x20
+#define MII_MGMT_COMMAND_ADDR 0x24
+#define MII_MGMT_ADDRESS_ADDR 0x28
+#define MII_MGMT_CONTROL_ADDR 0x2c
+#define MII_MGMT_STATUS_ADDR 0x30
+#define MII_MGMT_INDICATORS_ADDR 0x34
+
+#define BUSY_MASK BIT(0)
+#define READ_CYCLE_MASK BIT(0)
+#define PHY_CONTROL_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
+
+#define ENET_SPARE_CFG_REG_ADDR 0x0750
+#define RSIF_CONFIG_REG_ADDR 0x0010
+#define RSIF_RAM_DBG_REG0_ADDR 0x0048
+#define RGMII_REG_0_ADDR 0x07e0
+#define CFG_LINK_AGGR_RESUME_0_ADDR 0x07c8
+#define DEBUG_REG_ADDR 0x0700
+#define CFG_BYPASS_ADDR 0x0294
+#define CLE_BYPASS_REG0_0_ADDR 0x0490
+#define CLE_BYPASS_REG1_0_ADDR 0x0494
+#define CFG_RSIF_FPBUFF_TIMEOUT_EN BIT(31)
+#define RESUME_TX BIT(0)
+#define CFG_SPEED_1250 BIT(24)
+#define TX_PORT0 BIT(0)
+#define CFG_BYPASS_UNISEC_TX BIT(2)
+#define CFG_BYPASS_UNISEC_RX BIT(1)
+#define CFG_CLE_BYPASS_EN0 BIT(31)
+#define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3)
+
+#define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2)
+#define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12)
+#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4)
+#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2)
+#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16)
+#define ICM_CONFIG0_REG_0_ADDR 0x0400
+#define ICM_CONFIG2_REG_0_ADDR 0x0410
+#define RX_DV_GATE_REG_0_ADDR 0x05fc
+#define TX_DV_GATE_EN0 BIT(2)
+#define RX_DV_GATE_EN0 BIT(1)
+#define RESUME_RX0 BIT(0)
+#define ENET_CFGSSQMIWQASSOC_ADDR 0xe0
+#define ENET_CFGSSQMIFPQASSOC_ADDR 0xdc
+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR 0xf0
+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR 0xf4
+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR 0x70
+#define ENET_BLOCK_MEM_RDY_ADDR 0x74
+#define MAC_CONFIG_1_ADDR 0x00
+#define MAC_CONFIG_2_ADDR 0x04
+#define MAX_FRAME_LEN_ADDR 0x10
+#define INTERFACE_CONTROL_ADDR 0x38
+#define STATION_ADDR0_ADDR 0x40
+#define STATION_ADDR1_ADDR 0x44
+#define PHY_ADDR_SET(dst, val) xgene_set_bits(dst, val, 8, 5)
+#define REG_ADDR_SET(dst, val) xgene_set_bits(dst, val, 0, 5)
+#define ENET_INTERFACE_MODE2_SET(dst, val) xgene_set_bits(dst, val, 8, 2)
+#define MGMT_CLOCK_SEL_SET(dst, val) xgene_set_bits(dst, val, 0, 3)
+#define SOFT_RESET1 BIT(31)
+#define TX_EN BIT(0)
+#define RX_EN BIT(2)
+#define ENET_LHD_MODE BIT(25)
+#define ENET_GHD_MODE BIT(26)
+#define FULL_DUPLEX2 BIT(0)
+#define SCAN_AUTO_INCR BIT(5)
+#define TBYT_ADDR 0x38
+#define TPKT_ADDR 0x39
+#define TDRP_ADDR 0x45
+#define TFCS_ADDR 0x47
+#define TUND_ADDR 0x4a
+
+#define TSO_IPPROTO_TCP 1
+#define FULL_DUPLEX 2
+
+#define USERINFO_POS 0
+#define USERINFO_LEN 32
+#define FPQNUM_POS 32
+#define FPQNUM_LEN 12
+#define LERR_POS 60
+#define LERR_LEN 3
+#define STASH_POS 52
+#define STASH_LEN 2
+#define BUFDATALEN_POS 48
+#define BUFDATALEN_LEN 12
+#define DATAADDR_POS 0
+#define DATAADDR_LEN 42
+#define COHERENT_POS 63
+#define HENQNUM_POS 48
+#define HENQNUM_LEN 12
+#define TYPESEL_POS 44
+#define TYPESEL_LEN 4
+#define ETHHDR_POS 12
+#define ETHHDR_LEN 8
+#define IC_POS 35 /* Insert CRC */
+#define TCPHDR_POS 0
+#define TCPHDR_LEN 6
+#define IPHDR_POS 6
+#define IPHDR_LEN 6
+#define EC_POS 22 /* Enable checksum */
+#define EC_LEN 1
+#define IS_POS 24 /* IP protocol select */
+#define IS_LEN 1
+#define TYPE_ETH_WORK_MESSAGE_POS 44
+
+struct xgene_enet_raw_desc {
+ __le64 m0;
+ __le64 m1;
+ __le64 m2;
+ __le64 m3;
+};
+
+struct xgene_enet_raw_desc16 {
+ __le64 m0;
+ __le64 m1;
+};
+
+static inline void xgene_enet_mark_desc_slot_empty(void *desc_slot_ptr)
+{
+ __le64 *desc_slot = desc_slot_ptr;
+
+ desc_slot[EMPTY_SLOT_INDEX] = cpu_to_le64(EMPTY_SLOT);
+}
+
+static inline bool xgene_enet_is_desc_slot_empty(void *desc_slot_ptr)
+{
+ __le64 *desc_slot = desc_slot_ptr;
+
+ return (desc_slot[EMPTY_SLOT_INDEX] == cpu_to_le64(EMPTY_SLOT));
+}
+
+enum xgene_enet_ring_cfgsize {
+ RING_CFGSIZE_512B,
+ RING_CFGSIZE_2KB,
+ RING_CFGSIZE_16KB,
+ RING_CFGSIZE_64KB,
+ RING_CFGSIZE_512KB,
+ RING_CFGSIZE_INVALID
+};
+
+enum xgene_enet_ring_type {
+ RING_DISABLED,
+ RING_REGULAR,
+ RING_BUFPOOL
+};
+
+enum xgene_ring_owner {
+ RING_OWNER_ETH0,
+ RING_OWNER_CPU = 15,
+ RING_OWNER_INVALID
+};
+
+enum xgene_enet_ring_bufnum {
+ RING_BUFNUM_REGULAR = 0x0,
+ RING_BUFNUM_BUFPOOL = 0x20,
+ RING_BUFNUM_INVALID
+};
+
+enum xgene_enet_cmd {
+ XGENE_ENET_WR_CMD = BIT(31),
+ XGENE_ENET_RD_CMD = BIT(30)
+};
+
+enum xgene_enet_err_code {
+ HBF_READ_DATA = 3,
+ HBF_LL_READ = 4,
+ BAD_WORK_MSG = 6,
+ BUFPOOL_TIMEOUT = 15,
+ INGRESS_CRC = 16,
+ INGRESS_CHECKSUM = 17,
+ INGRESS_TRUNC_FRAME = 18,
+ INGRESS_PKT_LEN = 19,
+ INGRESS_PKT_UNDER = 20,
+ INGRESS_FIFO_OVERRUN = 21,
+ INGRESS_CHECKSUM_COMPUTE = 26,
+ ERR_CODE_INVALID
+};
+
+static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id)
+{
+ return (id & RING_OWNER_MASK) >> 6;
+}
+
+static inline u8 xgene_enet_ring_bufnum(u16 id)
+{
+ return id & RING_BUFNUM_MASK;
+}
+
+static inline bool xgene_enet_is_bufpool(u16 id)
+{
+ return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
+}
+
+static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
+{
+ bool is_bufpool = xgene_enet_is_bufpool(id);
+
+ return (is_bufpool) ? size / BUFPOOL_DESC_SIZE :
+ size / WORK_DESC_SIZE;
+}
+
+struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+ struct xgene_enet_desc_ring *ring);
+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring);
+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status);
+
+void xgene_enet_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_reset(struct xgene_enet_pdata *priv);
+void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed);
+void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv);
+void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv);
+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata);
+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
+ u32 dst_ring_num, u16 bufpool_id);
+void xgene_gport_shutdown(struct xgene_enet_pdata *priv);
+void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata);
+
+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+
+#endif /* __XGENE_ENET_HW_H__ */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
new file mode 100644
index 000000000000..e1a8f4e19983
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -0,0 +1,954 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xgene_enet_main.h"
+#include "xgene_enet_hw.h"
+
+static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ int i;
+
+ for (i = 0; i < buf_pool->slots; i++) {
+ raw_desc = &buf_pool->raw_desc16[i];
+
+ /* Hardware expects descriptor in little endian format */
+ raw_desc->m0 = cpu_to_le64(i |
+ SET_VAL(FPQNUM, buf_pool->dst_ring_num) |
+ SET_VAL(STASH, 3));
+ }
+}
+
+static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
+ u32 nbuf)
+{
+ struct sk_buff *skb;
+ struct xgene_enet_raw_desc16 *raw_desc;
+ struct net_device *ndev;
+ struct device *dev;
+ dma_addr_t dma_addr;
+ u32 tail = buf_pool->tail;
+ u32 slots = buf_pool->slots - 1;
+ u16 bufdatalen, len;
+ int i;
+
+ ndev = buf_pool->ndev;
+ dev = ndev_to_dev(buf_pool->ndev);
+ bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
+ len = XGENE_ENET_MAX_MTU;
+
+ for (i = 0; i < nbuf; i++) {
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ skb = netdev_alloc_skb_ip_align(ndev, len);
+ if (unlikely(!skb))
+ return -ENOMEM;
+ buf_pool->rx_skb[tail] = skb;
+
+ dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma_addr)) {
+ netdev_err(ndev, "DMA mapping error\n");
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, bufdatalen) |
+ SET_BIT(COHERENT));
+ tail = (tail + 1) & slots;
+ }
+
+ iowrite32(nbuf, buf_pool->cmd);
+ buf_pool->tail = tail;
+
+ return 0;
+}
+
+static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+
+ return ((u16)pdata->rm << 10) | ring->num;
+}
+
+static u8 xgene_enet_hdr_len(const void *data)
+{
+ const struct ethhdr *eth = data;
+
+ return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN;
+}
+
+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+{
+ u32 __iomem *cmd_base = ring->cmd_base;
+ u32 ring_state, num_msgs;
+
+ ring_state = ioread32(&cmd_base[1]);
+ num_msgs = ring_state & CREATE_MASK(NUMMSGSINQ_POS, NUMMSGSINQ_LEN);
+
+ return num_msgs >> NUMMSGSINQ_POS;
+}
+
+static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
+{
+ struct xgene_enet_raw_desc16 *raw_desc;
+ u32 slots = buf_pool->slots - 1;
+ u32 tail = buf_pool->tail;
+ u32 userinfo;
+ int i, len;
+
+ len = xgene_enet_ring_len(buf_pool);
+ for (i = 0; i < len; i++) {
+ tail = (tail - 1) & slots;
+ raw_desc = &buf_pool->raw_desc16[tail];
+
+ /* Hardware stores descriptor in little endian format */
+ userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
+ }
+
+ iowrite32(-len, buf_pool->cmd);
+ buf_pool->tail = tail;
+}
+
+static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
+{
+ struct xgene_enet_desc_ring *rx_ring = data;
+
+ if (napi_schedule_prep(&rx_ring->napi)) {
+ disable_irq_nosync(irq);
+ __napi_schedule(&rx_ring->napi);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ struct xgene_enet_raw_desc *raw_desc)
+{
+ struct sk_buff *skb;
+ struct device *dev;
+ u16 skb_index;
+ u8 status;
+ int ret = 0;
+
+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ skb = cp_ring->cp_skb[skb_index];
+
+ dev = ndev_to_dev(cp_ring->ndev);
+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+ GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)),
+ DMA_TO_DEVICE);
+
+ /* Checking for error */
+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+ if (unlikely(status > 2)) {
+ xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev),
+ status);
+ ret = -EIO;
+ }
+
+ if (likely(skb)) {
+ dev_kfree_skb_any(skb);
+ } else {
+ netdev_err(cp_ring->ndev, "completion skb is NULL\n");
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static u64 xgene_enet_work_msg(struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ u8 l3hlen, l4hlen = 0;
+ u8 csum_enable = 0;
+ u8 proto = 0;
+ u8 ethhdr;
+ u64 hopinfo;
+
+ if (unlikely(skb->protocol != htons(ETH_P_IP)) &&
+ unlikely(skb->protocol != htons(ETH_P_8021Q)))
+ goto out;
+
+ if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM)))
+ goto out;
+
+ iph = ip_hdr(skb);
+ if (unlikely(ip_is_fragment(iph)))
+ goto out;
+
+ if (likely(iph->protocol == IPPROTO_TCP)) {
+ l4hlen = tcp_hdrlen(skb) >> 2;
+ csum_enable = 1;
+ proto = TSO_IPPROTO_TCP;
+ } else if (iph->protocol == IPPROTO_UDP) {
+ l4hlen = UDP_HDR_SIZE;
+ csum_enable = 1;
+ }
+out:
+ l3hlen = ip_hdrlen(skb) >> 2;
+ ethhdr = xgene_enet_hdr_len(skb->data);
+ hopinfo = SET_VAL(TCPHDR, l4hlen) |
+ SET_VAL(IPHDR, l3hlen) |
+ SET_VAL(ETHHDR, ethhdr) |
+ SET_VAL(EC, csum_enable) |
+ SET_VAL(IS, proto) |
+ SET_BIT(IC) |
+ SET_BIT(TYPE_ETH_WORK_MESSAGE);
+
+ return hopinfo;
+}
+
+static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
+ struct sk_buff *skb)
+{
+ struct device *dev = ndev_to_dev(tx_ring->ndev);
+ struct xgene_enet_raw_desc *raw_desc;
+ dma_addr_t dma_addr;
+ u16 tail = tx_ring->tail;
+ u64 hopinfo;
+
+ raw_desc = &tx_ring->raw_desc[tail];
+ memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
+
+ dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma_addr)) {
+ netdev_err(tx_ring->ndev, "DMA mapping error\n");
+ return -EINVAL;
+ }
+
+ /* Hardware expects descriptor in little endian format */
+ raw_desc->m0 = cpu_to_le64(tail);
+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+ SET_VAL(BUFDATALEN, skb->len) |
+ SET_BIT(COHERENT));
+ hopinfo = xgene_enet_work_msg(skb);
+ raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
+ hopinfo);
+ tx_ring->cp_ring->cp_skb[tail] = skb;
+
+ return 0;
+}
+
+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+ struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
+ struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
+ u32 tx_level, cq_level;
+
+ tx_level = xgene_enet_ring_len(tx_ring);
+ cq_level = xgene_enet_ring_len(cp_ring);
+ if (unlikely(tx_level > pdata->tx_qcnt_hi ||
+ cq_level > pdata->cp_qcnt_hi)) {
+ netif_stop_queue(ndev);
+ return NETDEV_TX_BUSY;
+ }
+
+ if (xgene_enet_setup_tx_desc(tx_ring, skb)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ iowrite32(1, tx_ring->cmd);
+ skb_tx_timestamp(skb);
+ tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1);
+
+ pdata->stats.tx_packets++;
+ pdata->stats.tx_bytes += skb->len;
+
+ return NETDEV_TX_OK;
+}
+
+static void xgene_enet_skip_csum(struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ if (!ip_is_fragment(iph) ||
+ (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+}
+
+static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
+ struct xgene_enet_raw_desc *raw_desc)
+{
+ struct net_device *ndev;
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u32 datalen, skb_index;
+ struct sk_buff *skb;
+ u8 status;
+ int ret = 0;
+
+ ndev = rx_ring->ndev;
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(rx_ring->ndev);
+ buf_pool = rx_ring->buf_pool;
+
+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
+ XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ skb = buf_pool->rx_skb[skb_index];
+
+ /* checking for error */
+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+ if (unlikely(status > 2)) {
+ dev_kfree_skb_any(skb);
+ xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
+ status);
+ pdata->stats.rx_dropped++;
+ ret = -EIO;
+ goto out;
+ }
+
+ /* strip off CRC as HW isn't doing this */
+ datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
+ datalen -= 4;
+ prefetch(skb->data - NET_IP_ALIGN);
+ skb_put(skb, datalen);
+
+ skb_checksum_none_assert(skb);
+ skb->protocol = eth_type_trans(skb, ndev);
+ if (likely((ndev->features & NETIF_F_IP_CSUM) &&
+ skb->protocol == htons(ETH_P_IP))) {
+ xgene_enet_skip_csum(skb);
+ }
+
+ pdata->stats.rx_packets++;
+ pdata->stats.rx_bytes += datalen;
+ napi_gro_receive(&rx_ring->napi, skb);
+out:
+ if (--rx_ring->nbufpool == 0) {
+ ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
+ rx_ring->nbufpool = NUM_BUFPOOL;
+ }
+
+ return ret;
+}
+
+static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc)
+{
+ return GET_VAL(FPQNUM, le64_to_cpu(raw_desc->m0)) ? true : false;
+}
+
+static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
+ int budget)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
+ struct xgene_enet_raw_desc *raw_desc;
+ u16 head = ring->head;
+ u16 slots = ring->slots - 1;
+ int ret, count = 0;
+
+ do {
+ raw_desc = &ring->raw_desc[head];
+ if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
+ break;
+
+ if (is_rx_desc(raw_desc))
+ ret = xgene_enet_rx_frame(ring, raw_desc);
+ else
+ ret = xgene_enet_tx_completion(ring, raw_desc);
+ xgene_enet_mark_desc_slot_empty(raw_desc);
+
+ head = (head + 1) & slots;
+ count++;
+
+ if (ret)
+ break;
+ } while (--budget);
+
+ if (likely(count)) {
+ iowrite32(-count, ring->cmd);
+ ring->head = head;
+
+ if (netif_queue_stopped(ring->ndev)) {
+ if (xgene_enet_ring_len(ring) < pdata->cp_qcnt_low)
+ netif_wake_queue(ring->ndev);
+ }
+ }
+
+ return budget;
+}
+
+static int xgene_enet_napi(struct napi_struct *napi, const int budget)
+{
+ struct xgene_enet_desc_ring *ring;
+ int processed;
+
+ ring = container_of(napi, struct xgene_enet_desc_ring, napi);
+ processed = xgene_enet_process_ring(ring, budget);
+
+ if (processed != budget) {
+ napi_complete(napi);
+ enable_irq(ring->irq);
+ }
+
+ return processed;
+}
+
+static void xgene_enet_timeout(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+ xgene_gmac_reset(pdata);
+}
+
+static int xgene_enet_register_irq(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ int ret;
+
+ ret = devm_request_irq(dev, pdata->rx_ring->irq, xgene_enet_rx_irq,
+ IRQF_SHARED, ndev->name, pdata->rx_ring);
+ if (ret) {
+ netdev_err(ndev, "rx%d interrupt request failed\n",
+ pdata->rx_ring->irq);
+ }
+
+ return ret;
+}
+
+static void xgene_enet_free_irq(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+
+ pdata = netdev_priv(ndev);
+ dev = ndev_to_dev(ndev);
+ devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring);
+}
+
+static int xgene_enet_open(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int ret;
+
+ xgene_gmac_tx_enable(pdata);
+ xgene_gmac_rx_enable(pdata);
+
+ ret = xgene_enet_register_irq(ndev);
+ if (ret)
+ return ret;
+ napi_enable(&pdata->rx_ring->napi);
+
+ if (pdata->phy_dev)
+ phy_start(pdata->phy_dev);
+
+ netif_start_queue(ndev);
+
+ return ret;
+}
+
+static int xgene_enet_close(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+
+ if (pdata->phy_dev)
+ phy_stop(pdata->phy_dev);
+
+ napi_disable(&pdata->rx_ring->napi);
+ xgene_enet_free_irq(ndev);
+ xgene_enet_process_ring(pdata->rx_ring, -1);
+
+ xgene_gmac_tx_disable(pdata);
+ xgene_gmac_rx_disable(pdata);
+
+ return 0;
+}
+
+static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
+{
+ struct xgene_enet_pdata *pdata;
+ struct device *dev;
+
+ pdata = netdev_priv(ring->ndev);
+ dev = ndev_to_dev(ring->ndev);
+
+ xgene_enet_clear_ring(ring);
+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+}
+
+static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
+{
+ struct xgene_enet_desc_ring *buf_pool;
+
+ if (pdata->tx_ring) {
+ xgene_enet_delete_ring(pdata->tx_ring);
+ pdata->tx_ring = NULL;
+ }
+
+ if (pdata->rx_ring) {
+ buf_pool = pdata->rx_ring->buf_pool;
+ xgene_enet_delete_bufpool(buf_pool);
+ xgene_enet_delete_ring(buf_pool);
+ xgene_enet_delete_ring(pdata->rx_ring);
+ pdata->rx_ring = NULL;
+ }
+}
+
+static int xgene_enet_get_ring_size(struct device *dev,
+ enum xgene_enet_ring_cfgsize cfgsize)
+{
+ int size = -EINVAL;
+
+ switch (cfgsize) {
+ case RING_CFGSIZE_512B:
+ size = 0x200;
+ break;
+ case RING_CFGSIZE_2KB:
+ size = 0x800;
+ break;
+ case RING_CFGSIZE_16KB:
+ size = 0x4000;
+ break;
+ case RING_CFGSIZE_64KB:
+ size = 0x10000;
+ break;
+ case RING_CFGSIZE_512KB:
+ size = 0x80000;
+ break;
+ default:
+ dev_err(dev, "Unsupported cfg ring size %d\n", cfgsize);
+ break;
+ }
+
+ return size;
+}
+
+static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
+{
+ struct device *dev;
+
+ if (!ring)
+ return;
+
+ dev = ndev_to_dev(ring->ndev);
+
+ if (ring->desc_addr) {
+ xgene_enet_clear_ring(ring);
+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+ }
+ devm_kfree(dev, ring);
+}
+
+static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
+{
+ struct device *dev = &pdata->pdev->dev;
+ struct xgene_enet_desc_ring *ring;
+
+ ring = pdata->tx_ring;
+ if (ring && ring->cp_ring && ring->cp_ring->cp_skb)
+ devm_kfree(dev, ring->cp_ring->cp_skb);
+ xgene_enet_free_desc_ring(ring);
+
+ ring = pdata->rx_ring;
+ if (ring && ring->buf_pool && ring->buf_pool->rx_skb)
+ devm_kfree(dev, ring->buf_pool->rx_skb);
+ xgene_enet_free_desc_ring(ring->buf_pool);
+ xgene_enet_free_desc_ring(ring);
+}
+
+static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
+ struct net_device *ndev, u32 ring_num,
+ enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
+{
+ struct xgene_enet_desc_ring *ring;
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ int size;
+
+ size = xgene_enet_get_ring_size(dev, cfgsize);
+ if (size < 0)
+ return NULL;
+
+ ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring),
+ GFP_KERNEL);
+ if (!ring)
+ return NULL;
+
+ ring->ndev = ndev;
+ ring->num = ring_num;
+ ring->cfgsize = cfgsize;
+ ring->id = ring_id;
+
+ ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
+ GFP_KERNEL);
+ if (!ring->desc_addr) {
+ devm_kfree(dev, ring);
+ return NULL;
+ }
+ ring->size = size;
+
+ ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
+ ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
+ pdata->rm = RM3;
+ ring = xgene_enet_setup_ring(ring);
+ netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n",
+ ring->num, ring->size, ring->id, ring->slots);
+
+ return ring;
+}
+
+static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum)
+{
+ return (owner << 6) | (bufnum & GENMASK(5, 0));
+}
+
+static int xgene_enet_create_desc_rings(struct net_device *ndev)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct device *dev = ndev_to_dev(ndev);
+ struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
+ struct xgene_enet_desc_ring *buf_pool = NULL;
+ u8 cpu_bufnum = 0, eth_bufnum = 0;
+ u8 bp_bufnum = 0x20;
+ u16 ring_id, ring_num = 0;
+ int ret;
+
+ /* allocate rx descriptor ring */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
+ rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB, ring_id);
+ if (!rx_ring) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* allocate buffer pool for receiving packets */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++);
+ buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_2KB, ring_id);
+ if (!buf_pool) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ rx_ring->nbufpool = NUM_BUFPOOL;
+ rx_ring->buf_pool = buf_pool;
+ rx_ring->irq = pdata->rx_irq;
+ buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
+ sizeof(struct sk_buff *), GFP_KERNEL);
+ if (!buf_pool->rx_skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
+ rx_ring->buf_pool = buf_pool;
+ pdata->rx_ring = rx_ring;
+
+ /* allocate tx descriptor ring */
+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++);
+ tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
+ RING_CFGSIZE_16KB, ring_id);
+ if (!tx_ring) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ pdata->tx_ring = tx_ring;
+
+ cp_ring = pdata->rx_ring;
+ cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
+ sizeof(struct sk_buff *), GFP_KERNEL);
+ if (!cp_ring->cp_skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ pdata->tx_ring->cp_ring = cp_ring;
+ pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
+
+ pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
+ pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
+ pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
+
+ return 0;
+
+err:
+ xgene_enet_free_desc_rings(pdata);
+ return ret;
+}
+
+static struct rtnl_link_stats64 *xgene_enet_get_stats64(
+ struct net_device *ndev,
+ struct rtnl_link_stats64 *storage)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ struct rtnl_link_stats64 *stats = &pdata->stats;
+
+ stats->rx_errors += stats->rx_length_errors +
+ stats->rx_crc_errors +
+ stats->rx_frame_errors +
+ stats->rx_fifo_errors;
+ memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
+
+ return storage;
+}
+
+static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr)
+{
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ int ret;
+
+ ret = eth_mac_addr(ndev, addr);
+ if (ret)
+ return ret;
+ xgene_gmac_set_mac_addr(pdata);
+
+ return ret;
+}
+
+static const struct net_device_ops xgene_ndev_ops = {
+ .ndo_open = xgene_enet_open,
+ .ndo_stop = xgene_enet_close,
+ .ndo_start_xmit = xgene_enet_start_xmit,
+ .ndo_tx_timeout = xgene_enet_timeout,
+ .ndo_get_stats64 = xgene_enet_get_stats64,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = xgene_enet_set_mac_address,
+};
+
+static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
+{
+ struct platform_device *pdev;
+ struct net_device *ndev;
+ struct device *dev;
+ struct resource *res;
+ void __iomem *base_addr;
+ const char *mac;
+ int ret;
+
+ pdev = pdata->pdev;
+ dev = &pdev->dev;
+ ndev = pdata->ndev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr");
+ if (!res) {
+ dev_err(dev, "Resource enet_csr not defined\n");
+ return -ENODEV;
+ }
+ pdata->base_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->base_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
+ return PTR_ERR(pdata->base_addr);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr");
+ if (!res) {
+ dev_err(dev, "Resource ring_csr not defined\n");
+ return -ENODEV;
+ }
+ pdata->ring_csr_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->ring_csr_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Ring CSR region\n");
+ return PTR_ERR(pdata->ring_csr_addr);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd");
+ if (!res) {
+ dev_err(dev, "Resource ring_cmd not defined\n");
+ return -ENODEV;
+ }
+ pdata->ring_cmd_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pdata->ring_cmd_addr)) {
+ dev_err(dev, "Unable to retrieve ENET Ring command region\n");
+ return PTR_ERR(pdata->ring_cmd_addr);
+ }
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_err(dev, "Unable to get ENET Rx IRQ\n");
+ ret = ret ? : -ENXIO;
+ return ret;
+ }
+ pdata->rx_irq = ret;
+
+ mac = of_get_mac_address(dev->of_node);
+ if (mac)
+ memcpy(ndev->dev_addr, mac, ndev->addr_len);
+ else
+ eth_hw_addr_random(ndev);
+ memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+ pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node);
+ if (pdata->phy_mode < 0) {
+ dev_err(dev, "Incorrect phy-connection-type in DTS\n");
+ return -EINVAL;
+ }
+
+ pdata->clk = devm_clk_get(&pdev->dev, NULL);
+ ret = IS_ERR(pdata->clk);
+ if (IS_ERR(pdata->clk)) {
+ dev_err(&pdev->dev, "can't get clock\n");
+ ret = PTR_ERR(pdata->clk);
+ return ret;
+ }
+
+ base_addr = pdata->base_addr;
+ pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
+ pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
+ pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
+ pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET;
+ pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET;
+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET;
+ pdata->rx_buff_cnt = NUM_PKT_BUF;
+
+ return ret;
+}
+
+static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
+{
+ struct net_device *ndev = pdata->ndev;
+ struct xgene_enet_desc_ring *buf_pool;
+ u16 dst_ring_num;
+ int ret;
+
+ xgene_gmac_tx_disable(pdata);
+ xgene_gmac_rx_disable(pdata);
+
+ ret = xgene_enet_create_desc_rings(ndev);
+ if (ret) {
+ netdev_err(ndev, "Error in ring configuration\n");
+ return ret;
+ }
+
+ /* setup buffer pool */
+ buf_pool = pdata->rx_ring->buf_pool;
+ xgene_enet_init_bufpool(buf_pool);
+ ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+ if (ret) {
+ xgene_enet_delete_desc_rings(pdata);
+ return ret;
+ }
+
+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring);
+ xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id);
+
+ return ret;
+}
+
+static int xgene_enet_probe(struct platform_device *pdev)
+{
+ struct net_device *ndev;
+ struct xgene_enet_pdata *pdata;
+ struct device *dev = &pdev->dev;
+ struct napi_struct *napi;
+ int ret;
+
+ ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
+ if (!ndev)
+ return -ENOMEM;
+
+ pdata = netdev_priv(ndev);
+
+ pdata->pdev = pdev;
+ pdata->ndev = ndev;
+ SET_NETDEV_DEV(ndev, dev);
+ platform_set_drvdata(pdev, pdata);
+ ndev->netdev_ops = &xgene_ndev_ops;
+ xgene_enet_set_ethtool_ops(ndev);
+ ndev->features |= NETIF_F_IP_CSUM |
+ NETIF_F_GSO |
+ NETIF_F_GRO;
+
+ ret = xgene_enet_get_resources(pdata);
+ if (ret)
+ goto err;
+
+ xgene_enet_reset(pdata);
+ xgene_gmac_init(pdata, SPEED_1000);
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ netdev_err(ndev, "Failed to register netdev\n");
+ goto err;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (ret) {
+ netdev_err(ndev, "No usable DMA configuration\n");
+ goto err;
+ }
+
+ ret = xgene_enet_init_hw(pdata);
+ if (ret)
+ goto err;
+
+ napi = &pdata->rx_ring->napi;
+ netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT);
+ ret = xgene_enet_mdio_config(pdata);
+
+ return ret;
+err:
+ free_netdev(ndev);
+ return ret;
+}
+
+static int xgene_enet_remove(struct platform_device *pdev)
+{
+ struct xgene_enet_pdata *pdata;
+ struct net_device *ndev;
+
+ pdata = platform_get_drvdata(pdev);
+ ndev = pdata->ndev;
+
+ xgene_gmac_rx_disable(pdata);
+ xgene_gmac_tx_disable(pdata);
+
+ netif_napi_del(&pdata->rx_ring->napi);
+ xgene_enet_mdio_remove(pdata);
+ xgene_enet_delete_desc_rings(pdata);
+ unregister_netdev(ndev);
+ xgene_gport_shutdown(pdata);
+ free_netdev(ndev);
+
+ return 0;
+}
+
+static struct of_device_id xgene_enet_match[] = {
+ {.compatible = "apm,xgene-enet",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_enet_match);
+
+static struct platform_driver xgene_enet_driver = {
+ .driver = {
+ .name = "xgene-enet",
+ .of_match_table = xgene_enet_match,
+ },
+ .probe = xgene_enet_probe,
+ .remove = xgene_enet_remove,
+};
+
+module_platform_driver(xgene_enet_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver");
+MODULE_VERSION(XGENE_DRV_VERSION);
+MODULE_AUTHOR("Keyur Chudgar <kchudgar@apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
new file mode 100644
index 000000000000..0815866986b0
--- /dev/null
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -0,0 +1,135 @@
+/* Applied Micro X-Gene SoC Ethernet Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Authors: Iyappan Subramanian <isubramanian@apm.com>
+ * Ravi Patel <rapatel@apm.com>
+ * Keyur Chudgar <kchudgar@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __XGENE_ENET_MAIN_H__
+#define __XGENE_ENET_MAIN_H__
+
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/prefetch.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include "xgene_enet_hw.h"
+
+#define XGENE_DRV_VERSION "v1.0"
+#define XGENE_ENET_MAX_MTU 1536
+#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
+#define NUM_PKT_BUF 64
+#define NUM_BUFPOOL 32
+
+/* software context of a descriptor ring */
+struct xgene_enet_desc_ring {
+ struct net_device *ndev;
+ u16 id;
+ u16 num;
+ u16 head;
+ u16 tail;
+ u16 slots;
+ u16 irq;
+ u32 size;
+ u32 state[NUM_RING_CONFIG];
+ void __iomem *cmd_base;
+ void __iomem *cmd;
+ dma_addr_t dma;
+ u16 dst_ring_num;
+ u8 nbufpool;
+ struct sk_buff *(*rx_skb);
+ struct sk_buff *(*cp_skb);
+ enum xgene_enet_ring_cfgsize cfgsize;
+ struct xgene_enet_desc_ring *cp_ring;
+ struct xgene_enet_desc_ring *buf_pool;
+ struct napi_struct napi;
+ union {
+ void *desc_addr;
+ struct xgene_enet_raw_desc *raw_desc;
+ struct xgene_enet_raw_desc16 *raw_desc16;
+ };
+};
+
+/* ethernet private data */
+struct xgene_enet_pdata {
+ struct net_device *ndev;
+ struct mii_bus *mdio_bus;
+ struct phy_device *phy_dev;
+ int phy_speed;
+ struct clk *clk;
+ struct platform_device *pdev;
+ struct xgene_enet_desc_ring *tx_ring;
+ struct xgene_enet_desc_ring *rx_ring;
+ char *dev_name;
+ u32 rx_buff_cnt;
+ u32 tx_qcnt_hi;
+ u32 cp_qcnt_hi;
+ u32 cp_qcnt_low;
+ u32 rx_irq;
+ void __iomem *eth_csr_addr;
+ void __iomem *eth_ring_if_addr;
+ void __iomem *eth_diag_csr_addr;
+ void __iomem *mcx_mac_addr;
+ void __iomem *mcx_stats_addr;
+ void __iomem *mcx_mac_csr_addr;
+ void __iomem *base_addr;
+ void __iomem *ring_csr_addr;
+ void __iomem *ring_cmd_addr;
+ u32 phy_addr;
+ int phy_mode;
+ u32 speed;
+ u16 rm;
+ struct rtnl_link_stats64 stats;
+};
+
+/* Set the specified value into a bit-field defined by its starting position
+ * and length within a single u64.
+ */
+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
+{
+ return (val & ((1ULL << len) - 1)) << pos;
+}
+
+#define SET_VAL(field, val) \
+ xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
+
+#define SET_BIT(field) \
+ xgene_enet_set_field_value(field ## _POS, 1, 1)
+
+/* Get the value from a bit-field defined by its starting position
+ * and length within the specified u64.
+ */
+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
+{
+ return (src >> pos) & ((1ULL << len) - 1);
+}
+
+#define GET_VAL(field, src) \
+ xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
+
+static inline struct device *ndev_to_dev(struct net_device *ndev)
+{
+ return ndev->dev.parent;
+}
+
+void xgene_enet_set_ethtool_ops(struct net_device *netdev);
+
+#endif /* __XGENE_ENET_MAIN_H__ */
diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h
index 53f85bf71526..36cc9bd07c47 100644
--- a/drivers/net/ethernet/arc/emac.h
+++ b/drivers/net/ethernet/arc/emac.h
@@ -105,12 +105,10 @@ struct buffer_state {
/**
* struct arc_emac_priv - Storage of EMAC's private information.
* @dev: Pointer to the current device.
- * @ndev: Pointer to the current network device.
* @phy_dev: Pointer to attached PHY device.
* @bus: Pointer to the current MII bus.
* @regs: Base address of EMAC memory-mapped control registers.
* @napi: Structure for NAPI.
- * @stats: Network device statistics.
* @rxbd: Pointer to Rx BD ring.
* @txbd: Pointer to Tx BD ring.
* @rxbd_dma: DMA handle for Rx BD ring.
@@ -127,7 +125,6 @@ struct buffer_state {
struct arc_emac_priv {
/* Devices */
struct device *dev;
- struct net_device *ndev;
struct phy_device *phy_dev;
struct mii_bus *bus;
@@ -135,7 +132,6 @@ struct arc_emac_priv {
struct clk *clk;
struct napi_struct napi;
- struct net_device_stats stats;
struct arc_emac_bd *rxbd;
struct arc_emac_bd *txbd;
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index 18e2faccebb0..fe5cfeace6e3 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -140,7 +140,7 @@ static const struct ethtool_ops arc_emac_ethtool_ops = {
static void arc_emac_tx_clean(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &ndev->stats;
unsigned int i;
for (i = 0; i < TX_BD_NUM; i++) {
@@ -202,7 +202,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
for (work_done = 0; work_done < budget; work_done++) {
unsigned int *last_rx_bd = &priv->last_rx_bd;
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &ndev->stats;
struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd];
struct arc_emac_bd *rxbd = &priv->rxbd[*last_rx_bd];
unsigned int pktlen, info = le32_to_cpu(rxbd->info);
@@ -318,7 +318,7 @@ static irqreturn_t arc_emac_intr(int irq, void *dev_instance)
{
struct net_device *ndev = dev_instance;
struct arc_emac_priv *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &ndev->stats;
unsigned int status;
status = arc_reg_get(priv, R_STATUS);
@@ -529,7 +529,7 @@ static int arc_emac_stop(struct net_device *ndev)
static struct net_device_stats *arc_emac_stats(struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &ndev->stats;
unsigned long miss, rxerr;
u8 rxcrc, rxfram, rxoflow;
@@ -565,7 +565,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
{
struct arc_emac_priv *priv = netdev_priv(ndev);
unsigned int len, *txbd_curr = &priv->txbd_curr;
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &ndev->stats;
__le32 *info = &priv->txbd[*txbd_curr].info;
dma_addr_t addr;
@@ -720,7 +720,6 @@ static int arc_emac_probe(struct platform_device *pdev)
priv = netdev_priv(ndev);
priv->dev = &pdev->dev;
- priv->ndev = ndev;
priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs);
if (IS_ERR(priv->regs)) {
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 49faa97a30c3..e398eda07298 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -1527,7 +1527,7 @@ static const struct pci_error_handlers alx_err_handlers = {
.resume = alx_pci_error_resume,
};
-static DEFINE_PCI_DEVICE_TABLE(alx_pci_tbl) = {
+static const struct pci_device_id alx_pci_tbl[] = {
{ PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_AR8161),
.driver_data = ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG },
{ PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_E2200),
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 1cda49a28f7f..52fdfe225978 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -639,7 +639,6 @@ int atl1c_phy_init(struct atl1c_hw *hw)
dev_err(&pdev->dev, "Wrong Media type %d\n",
hw->media_type);
return -1;
- break;
}
ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
@@ -682,7 +681,6 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
break;
default:
return -1;
- break;
}
if (phy_data & GIGA_PSSR_DPLX)
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index e11bf18fbbd1..72fb86b9aa24 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -34,7 +34,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION;
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = {
+static const struct pci_device_id atl1c_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)},
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
index 923063d2e5bb..113565da155f 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_hw.c
@@ -618,7 +618,6 @@ int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
break;
default:
return AT_ERR_PHY_SPEED;
- break;
}
if (phy_data & MII_AT001_PSSR_DPLX)
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 4345332533ad..2326579f9454 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -35,7 +35,7 @@ char atl1e_driver_version[] = DRV_VERSION;
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = {
+static const struct pci_device_id atl1e_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)},
/* required last entry */
@@ -831,17 +831,14 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
/* real ring DMA buffer */
size = adapter->ring_size;
- adapter->ring_vir_addr = pci_alloc_consistent(pdev,
- adapter->ring_size, &adapter->ring_dma);
-
+ adapter->ring_vir_addr = pci_zalloc_consistent(pdev, adapter->ring_size,
+ &adapter->ring_dma);
if (adapter->ring_vir_addr == NULL) {
netdev_err(adapter->netdev,
"pci_alloc_consistent failed, size = D%d\n", size);
return -ENOMEM;
}
- memset(adapter->ring_vir_addr, 0, adapter->ring_size);
-
rx_page_desc = rx_ring->rx_page_desc;
/* Init TPD Ring */
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index b460db7919a2..2c8f398aeda9 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -235,7 +235,7 @@ static void atl1_check_options(struct atl1_adapter *adapter)
/*
* atl1_pci_tbl - PCI Device ID Table
*/
-static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = {
+static const struct pci_device_id atl1_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)},
/* required last entry */
{0,}
@@ -910,7 +910,6 @@ static s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex
if (netif_msg_hw(adapter))
dev_dbg(&pdev->dev, "error getting speed\n");
return ATLX_ERR_PHY_SPEED;
- break;
}
if (phy_data & MII_ATLX_PSSR_DPLX)
*duplex = FULL_DUPLEX;
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index 6746bd717146..84a09e8ddd9c 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -65,7 +65,7 @@ MODULE_VERSION(ATL2_DRV_VERSION);
/*
* atl2_pci_tbl - PCI Device ID Table
*/
-static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = {
+static const struct pci_device_id atl2_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)},
/* required last entry */
{0,}
@@ -2493,7 +2493,6 @@ static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed,
break;
default:
return ATLX_ERR_PHY_SPEED;
- break;
}
if (phy_data & MII_ATLX_PSSR_DPLX)
@@ -2933,11 +2932,9 @@ static int atl2_validate_option(int *value, struct atl2_option *opt)
case OPTION_ENABLED:
printk(KERN_INFO "%s Enabled\n", opt->name);
return 0;
- break;
case OPTION_DISABLED:
printk(KERN_INFO "%s Disabled\n", opt->name);
return 0;
- break;
}
break;
case range_option:
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 3e488094b073..7dcfb19a31c8 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -72,23 +72,23 @@ config BCMGENET
Broadcom BCM7xxx Set Top Box family chipset.
config BNX2
- tristate "Broadcom NetXtremeII support"
+ tristate "QLogic NetXtremeII support"
depends on PCI
select CRC32
select FW_LOADER
---help---
- This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
+ This driver supports QLogic NetXtremeII gigabit Ethernet cards.
To compile this driver as a module, choose M here: the module
will be called bnx2. This is recommended.
config CNIC
- tristate "Broadcom CNIC support"
+ tristate "QLogic CNIC support"
depends on PCI
select BNX2
select UIO
---help---
- This driver supports offload features of Broadcom NetXtremeII
+ This driver supports offload features of QLogic NetXtremeII
gigabit Ethernet cards.
To compile this driver as a module, choose M here: the module
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index ca5a20a48b14..4a7028d65912 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -105,7 +105,7 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
#ifdef CONFIG_B44_PCI
-static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = {
+static const struct pci_device_id b44_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) },
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 5776e503e4c5..6f4e18644bd4 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -81,14 +81,14 @@ static inline void dma_desc_set_addr(struct bcm_sysport_priv *priv,
{
#ifdef CONFIG_PHYS_ADDR_T_64BIT
__raw_writel(upper_32_bits(addr) & DESC_ADDR_HI_MASK,
- d + DESC_ADDR_HI_STATUS_LEN);
+ d + DESC_ADDR_HI_STATUS_LEN);
#endif
__raw_writel(lower_32_bits(addr), d + DESC_ADDR_LO);
}
static inline void tdma_port_write_desc_addr(struct bcm_sysport_priv *priv,
- struct dma_desc *desc,
- unsigned int port)
+ struct dma_desc *desc,
+ unsigned int port)
{
/* Ports are latched, so write upper address first */
tdma_writel(priv, desc->addr_status_len, TDMA_WRITE_PORT_HI(port));
@@ -108,7 +108,7 @@ static int bcm_sysport_set_settings(struct net_device *dev,
}
static int bcm_sysport_get_settings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+ struct ethtool_cmd *cmd)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
@@ -119,14 +119,14 @@ static int bcm_sysport_get_settings(struct net_device *dev,
}
static int bcm_sysport_set_rx_csum(struct net_device *dev,
- netdev_features_t wanted)
+ netdev_features_t wanted)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
u32 reg;
- priv->rx_csum_en = !!(wanted & NETIF_F_RXCSUM);
+ priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
reg = rxchk_readl(priv, RXCHK_CONTROL);
- if (priv->rx_csum_en)
+ if (priv->rx_chk_en)
reg |= RXCHK_EN;
else
reg &= ~RXCHK_EN;
@@ -134,7 +134,7 @@ static int bcm_sysport_set_rx_csum(struct net_device *dev,
/* If UniMAC forwards CRC, we need to skip over it to get
* a valid CHK bit to be set in the per-packet status word
*/
- if (priv->rx_csum_en && priv->crc_fwd)
+ if (priv->rx_chk_en && priv->crc_fwd)
reg |= RXCHK_SKIP_FCS;
else
reg &= ~RXCHK_SKIP_FCS;
@@ -145,7 +145,7 @@ static int bcm_sysport_set_rx_csum(struct net_device *dev,
}
static int bcm_sysport_set_tx_csum(struct net_device *dev,
- netdev_features_t wanted)
+ netdev_features_t wanted)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
u32 reg;
@@ -165,7 +165,7 @@ static int bcm_sysport_set_tx_csum(struct net_device *dev,
}
static int bcm_sysport_set_features(struct net_device *dev,
- netdev_features_t features)
+ netdev_features_t features)
{
netdev_features_t changed = features ^ dev->features;
netdev_features_t wanted = dev->wanted_features;
@@ -261,7 +261,7 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = {
/* RXCHK misc statistics */
STAT_RXCHK("rxchk_bad_csum", mib.rxchk_bad_csum, RXCHK_BAD_CSUM_CNTR),
STAT_RXCHK("rxchk_other_pkt_disc", mib.rxchk_other_pkt_disc,
- RXCHK_OTHER_DISC_CNTR),
+ RXCHK_OTHER_DISC_CNTR),
/* RBUF misc statistics */
STAT_RBUF("rbuf_ovflow_cnt", mib.rbuf_ovflow_cnt, RBUF_OVFL_DISC_CNTR),
STAT_RBUF("rbuf_err_cnt", mib.rbuf_err_cnt, RBUF_ERR_PKT_CNTR),
@@ -270,7 +270,7 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = {
#define BCM_SYSPORT_STATS_LEN ARRAY_SIZE(bcm_sysport_gstrings_stats)
static void bcm_sysport_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
+ struct ethtool_drvinfo *info)
{
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, "0.1", sizeof(info->version));
@@ -303,7 +303,7 @@ static int bcm_sysport_get_sset_count(struct net_device *dev, int string_set)
}
static void bcm_sysport_get_strings(struct net_device *dev,
- u32 stringset, u8 *data)
+ u32 stringset, u8 *data)
{
int i;
@@ -311,8 +311,8 @@ static void bcm_sysport_get_strings(struct net_device *dev,
case ETH_SS_STATS:
for (i = 0; i < BCM_SYSPORT_STATS_LEN; i++) {
memcpy(data + i * ETH_GSTRING_LEN,
- bcm_sysport_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ bcm_sysport_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
}
break;
default:
@@ -362,7 +362,7 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)
}
static void bcm_sysport_get_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
+ struct ethtool_stats *stats, u64 *data)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
int i;
@@ -384,6 +384,64 @@ static void bcm_sysport_get_stats(struct net_device *dev,
}
}
+static void bcm_sysport_get_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+ u32 reg;
+
+ wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+ wol->wolopts = priv->wolopts;
+
+ if (!(priv->wolopts & WAKE_MAGICSECURE))
+ return;
+
+ /* Return the programmed SecureOn password */
+ reg = umac_readl(priv, UMAC_PSW_MS);
+ put_unaligned_be16(reg, &wol->sopass[0]);
+ reg = umac_readl(priv, UMAC_PSW_LS);
+ put_unaligned_be32(reg, &wol->sopass[2]);
+}
+
+static int bcm_sysport_set_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+ struct device *kdev = &priv->pdev->dev;
+ u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+
+ if (!device_can_wakeup(kdev))
+ return -ENOTSUPP;
+
+ if (wol->wolopts & ~supported)
+ return -EINVAL;
+
+ /* Program the SecureOn password */
+ if (wol->wolopts & WAKE_MAGICSECURE) {
+ umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
+ UMAC_PSW_MS);
+ umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
+ UMAC_PSW_LS);
+ }
+
+ /* Flag the device and relevant IRQ as wakeup capable */
+ if (wol->wolopts) {
+ device_set_wakeup_enable(kdev, 1);
+ enable_irq_wake(priv->wol_irq);
+ priv->wol_irq_disabled = 0;
+ } else {
+ device_set_wakeup_enable(kdev, 0);
+ /* Avoid unbalanced disable_irq_wake calls */
+ if (!priv->wol_irq_disabled)
+ disable_irq_wake(priv->wol_irq);
+ priv->wol_irq_disabled = 1;
+ }
+
+ priv->wolopts = wol->wolopts;
+
+ return 0;
+}
+
static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb)
{
dev_kfree_skb_any(cb->skb);
@@ -406,7 +464,7 @@ static int bcm_sysport_rx_refill(struct bcm_sysport_priv *priv,
}
mapping = dma_map_single(kdev, cb->skb->data,
- RX_BUF_LENGTH, DMA_FROM_DEVICE);
+ RX_BUF_LENGTH, DMA_FROM_DEVICE);
ret = dma_mapping_error(kdev, mapping);
if (ret) {
bcm_sysport_free_cb(cb);
@@ -470,22 +528,20 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
to_process = p_index - priv->rx_c_index;
netif_dbg(priv, rx_status, ndev,
- "p_index=%d rx_c_index=%d to_process=%d\n",
- p_index, priv->rx_c_index, to_process);
-
- while ((processed < to_process) &&
- (processed < budget)) {
+ "p_index=%d rx_c_index=%d to_process=%d\n",
+ p_index, priv->rx_c_index, to_process);
+ while ((processed < to_process) && (processed < budget)) {
cb = &priv->rx_cbs[priv->rx_read_ptr];
skb = cb->skb;
dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
- RX_BUF_LENGTH, DMA_FROM_DEVICE);
+ RX_BUF_LENGTH, DMA_FROM_DEVICE);
/* Extract the Receive Status Block prepended */
rsb = (struct bcm_rsb *)skb->data;
len = (rsb->rx_status_len >> DESC_LEN_SHIFT) & DESC_LEN_MASK;
status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) &
- DESC_STATUS_MASK;
+ DESC_STATUS_MASK;
processed++;
priv->rx_read_ptr++;
@@ -493,9 +549,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
priv->rx_read_ptr = 0;
netif_dbg(priv, rx_status, ndev,
- "p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
- p_index, priv->rx_c_index, priv->rx_read_ptr,
- len, status);
+ "p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
+ p_index, priv->rx_c_index, priv->rx_read_ptr,
+ len, status);
if (unlikely(!skb)) {
netif_err(priv, rx_err, ndev, "out of memory!\n");
@@ -554,9 +610,9 @@ refill:
}
static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_priv *priv,
- struct bcm_sysport_cb *cb,
- unsigned int *bytes_compl,
- unsigned int *pkts_compl)
+ struct bcm_sysport_cb *cb,
+ unsigned int *bytes_compl,
+ unsigned int *pkts_compl)
{
struct device *kdev = &priv->pdev->dev;
struct net_device *ndev = priv->netdev;
@@ -565,8 +621,8 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_priv *priv,
ndev->stats.tx_bytes += cb->skb->len;
*bytes_compl += cb->skb->len;
dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
- dma_unmap_len(cb, dma_len),
- DMA_TO_DEVICE);
+ dma_unmap_len(cb, dma_len),
+ DMA_TO_DEVICE);
ndev->stats.tx_packets++;
(*pkts_compl)++;
bcm_sysport_free_cb(cb);
@@ -574,7 +630,7 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_priv *priv,
} else if (dma_unmap_addr(cb, dma_addr)) {
ndev->stats.tx_bytes += dma_unmap_len(cb, dma_len);
dma_unmap_page(kdev, dma_unmap_addr(cb, dma_addr),
- dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
+ dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
dma_unmap_addr_set(cb, dma_addr, 0);
}
}
@@ -608,8 +664,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
last_tx_cn = num_tx_cbs - last_c_index + c_index;
netif_dbg(priv, tx_done, ndev,
- "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n",
- ring->index, c_index, last_tx_cn, last_c_index);
+ "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n",
+ ring->index, c_index, last_tx_cn, last_c_index);
while (last_tx_cn-- > 0) {
cb = ring->cbs + last_c_index;
@@ -626,8 +682,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
netif_tx_wake_queue(txq);
netif_dbg(priv, tx_done, ndev,
- "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
- ring->index, ring->c_index, pkts_compl, bytes_compl);
+ "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
+ ring->index, ring->c_index, pkts_compl, bytes_compl);
return pkts_compl;
}
@@ -692,6 +748,20 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
return work_done;
}
+static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
+{
+ u32 reg;
+
+ /* Stop monitoring MPD interrupt */
+ intrl2_0_mask_set(priv, INTRL2_0_MPD);
+
+ /* Clear the MagicPacket detection logic */
+ reg = umac_readl(priv, UMAC_MPD_CTRL);
+ reg &= ~MPD_EN;
+ umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+ netif_dbg(priv, wol, priv->netdev, "resumed from WOL\n");
+}
/* RX and misc interrupt routine */
static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
@@ -722,6 +792,11 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
if (priv->irq0_stat & INTRL2_0_TX_RING_FULL)
bcm_sysport_tx_reclaim_all(priv);
+ if (priv->irq0_stat & INTRL2_0_MPD) {
+ netdev_info(priv->netdev, "Wake-on-LAN interrupt!\n");
+ bcm_sysport_resume_from_wol(priv);
+ }
+
return IRQ_HANDLED;
}
@@ -757,6 +832,15 @@ static irqreturn_t bcm_sysport_tx_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t bcm_sysport_wol_isr(int irq, void *dev_id)
+{
+ struct bcm_sysport_priv *priv = dev_id;
+
+ pm_wakeup_event(&priv->pdev->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
{
struct sk_buff *nskb;
@@ -804,8 +888,9 @@ static int bcm_sysport_insert_tsb(struct sk_buff *skb, struct net_device *dev)
csum_info |= L4_LENGTH_VALID;
if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP)
csum_info |= L4_UDP;
- } else
+ } else {
csum_info = 0;
+ }
tsb->l4_ptr_dest_map = csum_info;
}
@@ -869,7 +954,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
if (dma_mapping_error(kdev, mapping)) {
netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
- skb->data, skb_len);
+ skb->data, skb_len);
ret = NETDEV_TX_OK;
goto out;
}
@@ -887,7 +972,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
len_status = upper_32_bits(mapping) & DESC_ADDR_HI_MASK;
len_status |= (skb_len << DESC_LEN_SHIFT);
len_status |= (DESC_SOP | DESC_EOP | TX_STATUS_APP_CRC) <<
- DESC_STATUS_SHIFT;
+ DESC_STATUS_SHIFT;
if (skb->ip_summed == CHECKSUM_PARTIAL)
len_status |= (DESC_L4_CSUM << DESC_STATUS_SHIFT);
@@ -912,7 +997,7 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb,
netif_tx_stop_queue(txq);
netif_dbg(priv, tx_queued, dev, "ring=%d desc_count=%d, curr_desc=%d\n",
- ring->index, ring->desc_count, ring->curr_desc);
+ ring->index, ring->desc_count, ring->curr_desc);
ret = NETDEV_TX_OK;
out:
@@ -1010,7 +1095,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
return -ENOMEM;
}
- ring->cbs = kzalloc(sizeof(struct bcm_sysport_cb) * size, GFP_KERNEL);
+ ring->cbs = kcalloc(size, sizeof(struct bcm_sysport_cb), GFP_KERNEL);
if (!ring->cbs) {
netif_err(priv, hw, priv->netdev, "CB allocation failed\n");
return -ENOMEM;
@@ -1050,14 +1135,14 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
napi_enable(&ring->napi);
netif_dbg(priv, hw, priv->netdev,
- "TDMA cfg, size=%d, desc_cpu=%p\n",
- ring->size, ring->desc_cpu);
+ "TDMA cfg, size=%d, desc_cpu=%p\n",
+ ring->size, ring->desc_cpu);
return 0;
}
static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
- unsigned int index)
+ unsigned int index)
{
struct bcm_sysport_tx_ring *ring = &priv->tx_rings[index];
struct device *kdev = &priv->pdev->dev;
@@ -1088,7 +1173,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
/* RDMA helper */
static inline int rdma_enable_set(struct bcm_sysport_priv *priv,
- unsigned int enable)
+ unsigned int enable)
{
unsigned int timeout = 1000;
u32 reg;
@@ -1115,7 +1200,7 @@ static inline int rdma_enable_set(struct bcm_sysport_priv *priv,
/* TDMA helper */
static inline int tdma_enable_set(struct bcm_sysport_priv *priv,
- unsigned int enable)
+ unsigned int enable)
{
unsigned int timeout = 1000;
u32 reg;
@@ -1153,8 +1238,8 @@ static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv)
priv->rx_bd_assign_index = 0;
priv->rx_c_index = 0;
priv->rx_read_ptr = 0;
- priv->rx_cbs = kzalloc(priv->num_rx_bds *
- sizeof(struct bcm_sysport_cb), GFP_KERNEL);
+ priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct bcm_sysport_cb),
+ GFP_KERNEL);
if (!priv->rx_cbs) {
netif_err(priv, hw, priv->netdev, "CB allocation failed\n");
return -ENOMEM;
@@ -1186,8 +1271,8 @@ static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv)
rdma_writel(priv, 1, RDMA_MBDONE_INTR);
netif_dbg(priv, hw, priv->netdev,
- "RDMA cfg, num_rx_bds=%d, rx_bds=%p\n",
- priv->num_rx_bds, priv->rx_bds);
+ "RDMA cfg, num_rx_bds=%d, rx_bds=%p\n",
+ priv->num_rx_bds, priv->rx_bds);
return 0;
}
@@ -1207,8 +1292,8 @@ static void bcm_sysport_fini_rx_ring(struct bcm_sysport_priv *priv)
cb = &priv->rx_cbs[i];
if (dma_unmap_addr(cb, dma_addr))
dma_unmap_single(&priv->pdev->dev,
- dma_unmap_addr(cb, dma_addr),
- RX_BUF_LENGTH, DMA_FROM_DEVICE);
+ dma_unmap_addr(cb, dma_addr),
+ RX_BUF_LENGTH, DMA_FROM_DEVICE);
bcm_sysport_free_cb(cb);
}
@@ -1236,15 +1321,15 @@ static void bcm_sysport_set_rx_mode(struct net_device *dev)
}
static inline void umac_enable_set(struct bcm_sysport_priv *priv,
- unsigned int enable)
+ u32 mask, unsigned int enable)
{
u32 reg;
reg = umac_readl(priv, UMAC_CMD);
if (enable)
- reg |= CMD_RX_EN | CMD_TX_EN;
+ reg |= mask;
else
- reg &= ~(CMD_RX_EN | CMD_TX_EN);
+ reg &= ~mask;
umac_writel(priv, reg, UMAC_CMD);
/* UniMAC stops on a packet boundary, wait for a full-sized packet
@@ -1268,7 +1353,7 @@ static inline void umac_reset(struct bcm_sysport_priv *priv)
}
static void umac_set_hw_addr(struct bcm_sysport_priv *priv,
- unsigned char *addr)
+ unsigned char *addr)
{
umac_writel(priv, (addr[0] << 24) | (addr[1] << 16) |
(addr[2] << 8) | addr[3], UMAC_MAC0);
@@ -1284,11 +1369,35 @@ static void topctrl_flush(struct bcm_sysport_priv *priv)
topctrl_writel(priv, 0, TX_FLUSH_CNTL);
}
+static void bcm_sysport_netif_start(struct net_device *dev)
+{
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+
+ /* Enable NAPI */
+ napi_enable(&priv->napi);
+
+ phy_start(priv->phydev);
+
+ /* Enable TX interrupts for the 32 TXQs */
+ intrl2_1_mask_clear(priv, 0xffffffff);
+
+ /* Last call before we start the real business */
+ netif_tx_start_all_queues(dev);
+}
+
+static void rbuf_init(struct bcm_sysport_priv *priv)
+{
+ u32 reg;
+
+ reg = rbuf_readl(priv, RBUF_CONTROL);
+ reg |= RBUF_4B_ALGN | RBUF_RSB_EN;
+ rbuf_writel(priv, reg, RBUF_CONTROL);
+}
+
static int bcm_sysport_open(struct net_device *dev)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
unsigned int i;
- u32 reg;
int ret;
/* Reset UniMAC */
@@ -1298,12 +1407,10 @@ static int bcm_sysport_open(struct net_device *dev)
topctrl_flush(priv);
/* Disable the UniMAC RX/TX */
- umac_enable_set(priv, 0);
+ umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 0);
/* Enable RBUF 2bytes alignment and Receive Status Block */
- reg = rbuf_readl(priv, RBUF_CONTROL);
- reg |= RBUF_4B_ALGN | RBUF_RSB_EN;
- rbuf_writel(priv, reg, RBUF_CONTROL);
+ rbuf_init(priv);
/* Set maximum frame length */
umac_writel(priv, UMAC_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
@@ -1351,7 +1458,7 @@ static int bcm_sysport_open(struct net_device *dev)
ret = bcm_sysport_init_tx_ring(priv, i);
if (ret) {
netdev_err(dev, "failed to initialize TX ring %d\n",
- i);
+ i);
goto out_free_tx_ring;
}
}
@@ -1379,19 +1486,10 @@ static int bcm_sysport_open(struct net_device *dev)
if (ret)
goto out_clear_rx_int;
- /* Enable NAPI */
- napi_enable(&priv->napi);
-
/* Turn on UniMAC TX/RX */
- umac_enable_set(priv, 1);
+ umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 1);
- phy_start(priv->phydev);
-
- /* Enable TX interrupts for the 32 TXQs */
- intrl2_1_mask_clear(priv, 0xffffffff);
-
- /* Last call before we start the real business */
- netif_tx_start_all_queues(dev);
+ bcm_sysport_netif_start(dev);
return 0;
@@ -1410,12 +1508,9 @@ out_phy_disconnect:
return ret;
}
-static int bcm_sysport_stop(struct net_device *dev)
+static void bcm_sysport_netif_stop(struct net_device *dev)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
- unsigned int i;
- u32 reg;
- int ret;
/* stop all software from updating hardware */
netif_tx_stop_all_queues(dev);
@@ -1427,11 +1522,18 @@ static int bcm_sysport_stop(struct net_device *dev)
intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
intrl2_1_mask_set(priv, 0xffffffff);
intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
+}
+
+static int bcm_sysport_stop(struct net_device *dev)
+{
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+ unsigned int i;
+ int ret;
+
+ bcm_sysport_netif_stop(dev);
/* Disable UniMAC RX */
- reg = umac_readl(priv, UMAC_CMD);
- reg &= ~CMD_RX_EN;
- umac_writel(priv, reg, UMAC_CMD);
+ umac_enable_set(priv, CMD_RX_EN, 0);
ret = tdma_enable_set(priv, 0);
if (ret) {
@@ -1449,9 +1551,7 @@ static int bcm_sysport_stop(struct net_device *dev)
}
/* Disable UniMAC TX */
- reg = umac_readl(priv, UMAC_CMD);
- reg &= ~CMD_TX_EN;
- umac_writel(priv, reg, UMAC_CMD);
+ umac_enable_set(priv, CMD_TX_EN, 0);
/* Free RX/TX rings SW structures */
for (i = 0; i < dev->num_tx_queues; i++)
@@ -1477,6 +1577,8 @@ static struct ethtool_ops bcm_sysport_ethtool_ops = {
.get_strings = bcm_sysport_get_strings,
.get_ethtool_stats = bcm_sysport_get_stats,
.get_sset_count = bcm_sysport_get_sset_count,
+ .get_wol = bcm_sysport_get_wol,
+ .set_wol = bcm_sysport_set_wol,
};
static const struct net_device_ops bcm_sysport_netdev_ops = {
@@ -1518,6 +1620,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
priv->irq0 = platform_get_irq(pdev, 0);
priv->irq1 = platform_get_irq(pdev, 1);
+ priv->wol_irq = platform_get_irq(pdev, 2);
if (priv->irq0 <= 0 || priv->irq1 <= 0) {
dev_err(&pdev->dev, "invalid interrupts\n");
ret = -EINVAL;
@@ -1570,6 +1673,13 @@ static int bcm_sysport_probe(struct platform_device *pdev)
dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ /* Request the WOL interrupt and advertise suspend if available */
+ priv->wol_irq_disabled = 1;
+ ret = devm_request_irq(&pdev->dev, priv->wol_irq,
+ bcm_sysport_wol_isr, 0, dev->name, priv);
+ if (!ret)
+ device_set_wakeup_capable(&pdev->dev, 1);
+
/* Set the needed headroom once and for all */
BUILD_BUG_ON(sizeof(struct bcm_tsb) != 8);
dev->needed_headroom += sizeof(struct bcm_tsb);
@@ -1585,10 +1695,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
dev_info(&pdev->dev,
- "Broadcom SYSTEMPORT" REV_FMT
- " at 0x%p (irqs: %d, %d, TXQs: %d, RXQs: %d)\n",
- (priv->rev >> 8) & 0xff, priv->rev & 0xff,
- priv->base, priv->irq0, priv->irq1, txq, rxq);
+ "Broadcom SYSTEMPORT" REV_FMT
+ " at 0x%p (irqs: %d, %d, TXQs: %d, RXQs: %d)\n",
+ (priv->rev >> 8) & 0xff, priv->rev & 0xff,
+ priv->base, priv->irq0, priv->irq1, txq, rxq);
return 0;
err:
@@ -1610,6 +1720,208 @@ static int bcm_sysport_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
+{
+ struct net_device *ndev = priv->netdev;
+ unsigned int timeout = 1000;
+ u32 reg;
+
+ /* Password has already been programmed */
+ reg = umac_readl(priv, UMAC_MPD_CTRL);
+ reg |= MPD_EN;
+ reg &= ~PSW_EN;
+ if (priv->wolopts & WAKE_MAGICSECURE)
+ reg |= PSW_EN;
+ umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+ /* Make sure RBUF entered WoL mode as result */
+ do {
+ reg = rbuf_readl(priv, RBUF_STATUS);
+ if (reg & RBUF_WOL_MODE)
+ break;
+
+ udelay(10);
+ } while (timeout-- > 0);
+
+ /* Do not leave the UniMAC RBUF matching only MPD packets */
+ if (!timeout) {
+ reg = umac_readl(priv, UMAC_MPD_CTRL);
+ reg &= ~MPD_EN;
+ umac_writel(priv, reg, UMAC_MPD_CTRL);
+ netif_err(priv, wol, ndev, "failed to enter WOL mode\n");
+ return -ETIMEDOUT;
+ }
+
+ /* UniMAC receive needs to be turned on */
+ umac_enable_set(priv, CMD_RX_EN, 1);
+
+ /* Enable the interrupt wake-up source */
+ intrl2_0_mask_clear(priv, INTRL2_0_MPD);
+
+ netif_dbg(priv, wol, ndev, "entered WOL mode\n");
+
+ return 0;
+}
+
+static int bcm_sysport_suspend(struct device *d)
+{
+ struct net_device *dev = dev_get_drvdata(d);
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+ unsigned int i;
+ int ret = 0;
+ u32 reg;
+
+ if (!netif_running(dev))
+ return 0;
+
+ bcm_sysport_netif_stop(dev);
+
+ phy_suspend(priv->phydev);
+
+ netif_device_detach(dev);
+
+ /* Disable UniMAC RX */
+ umac_enable_set(priv, CMD_RX_EN, 0);
+
+ ret = rdma_enable_set(priv, 0);
+ if (ret) {
+ netdev_err(dev, "RDMA timeout!\n");
+ return ret;
+ }
+
+ /* Disable RXCHK if enabled */
+ if (priv->rx_chk_en) {
+ reg = rxchk_readl(priv, RXCHK_CONTROL);
+ reg &= ~RXCHK_EN;
+ rxchk_writel(priv, reg, RXCHK_CONTROL);
+ }
+
+ /* Flush RX pipe */
+ if (!priv->wolopts)
+ topctrl_writel(priv, RX_FLUSH, RX_FLUSH_CNTL);
+
+ ret = tdma_enable_set(priv, 0);
+ if (ret) {
+ netdev_err(dev, "TDMA timeout!\n");
+ return ret;
+ }
+
+ /* Wait for a packet boundary */
+ usleep_range(2000, 3000);
+
+ umac_enable_set(priv, CMD_TX_EN, 0);
+
+ topctrl_writel(priv, TX_FLUSH, TX_FLUSH_CNTL);
+
+ /* Free RX/TX rings SW structures */
+ for (i = 0; i < dev->num_tx_queues; i++)
+ bcm_sysport_fini_tx_ring(priv, i);
+ bcm_sysport_fini_rx_ring(priv);
+
+ /* Get prepared for Wake-on-LAN */
+ if (device_may_wakeup(d) && priv->wolopts)
+ ret = bcm_sysport_suspend_to_wol(priv);
+
+ return ret;
+}
+
+static int bcm_sysport_resume(struct device *d)
+{
+ struct net_device *dev = dev_get_drvdata(d);
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
+ unsigned int i;
+ u32 reg;
+ int ret;
+
+ if (!netif_running(dev))
+ return 0;
+
+ /* We may have been suspended and never received a WOL event that
+ * would turn off MPD detection, take care of that now
+ */
+ bcm_sysport_resume_from_wol(priv);
+
+ /* Initialize both hardware and software ring */
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ ret = bcm_sysport_init_tx_ring(priv, i);
+ if (ret) {
+ netdev_err(dev, "failed to initialize TX ring %d\n",
+ i);
+ goto out_free_tx_rings;
+ }
+ }
+
+ /* Initialize linked-list */
+ tdma_writel(priv, TDMA_LL_RAM_INIT_BUSY, TDMA_STATUS);
+
+ /* Initialize RX ring */
+ ret = bcm_sysport_init_rx_ring(priv);
+ if (ret) {
+ netdev_err(dev, "failed to initialize RX ring\n");
+ goto out_free_rx_ring;
+ }
+
+ netif_device_attach(dev);
+
+ /* Enable RX interrupt and TX ring full interrupt */
+ intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE | INTRL2_0_TX_RING_FULL);
+
+ /* RX pipe enable */
+ topctrl_writel(priv, 0, RX_FLUSH_CNTL);
+
+ ret = rdma_enable_set(priv, 1);
+ if (ret) {
+ netdev_err(dev, "failed to enable RDMA\n");
+ goto out_free_rx_ring;
+ }
+
+ /* Enable rxhck */
+ if (priv->rx_chk_en) {
+ reg = rxchk_readl(priv, RXCHK_CONTROL);
+ reg |= RXCHK_EN;
+ rxchk_writel(priv, reg, RXCHK_CONTROL);
+ }
+
+ rbuf_init(priv);
+
+ /* Set maximum frame length */
+ umac_writel(priv, UMAC_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
+
+ /* Set MAC address */
+ umac_set_hw_addr(priv, dev->dev_addr);
+
+ umac_enable_set(priv, CMD_RX_EN, 1);
+
+ /* TX pipe enable */
+ topctrl_writel(priv, 0, TX_FLUSH_CNTL);
+
+ umac_enable_set(priv, CMD_TX_EN, 1);
+
+ ret = tdma_enable_set(priv, 1);
+ if (ret) {
+ netdev_err(dev, "TDMA timeout!\n");
+ goto out_free_rx_ring;
+ }
+
+ phy_resume(priv->phydev);
+
+ bcm_sysport_netif_start(dev);
+
+ return 0;
+
+out_free_rx_ring:
+ bcm_sysport_fini_rx_ring(priv);
+out_free_tx_rings:
+ for (i = 0; i < dev->num_tx_queues; i++)
+ bcm_sysport_fini_tx_ring(priv, i);
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bcm_sysport_pm_ops,
+ bcm_sysport_suspend, bcm_sysport_resume);
+
static const struct of_device_id bcm_sysport_of_match[] = {
{ .compatible = "brcm,systemport-v1.00" },
{ .compatible = "brcm,systemport" },
@@ -1623,6 +1935,7 @@ static struct platform_driver bcm_sysport_driver = {
.name = "brcm-systemport",
.owner = THIS_MODULE,
.of_match_table = bcm_sysport_of_match,
+ .pm = &bcm_sysport_pm_ops,
},
};
module_platform_driver(bcm_sysport_driver);
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 281c08246037..b08dab828101 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -246,6 +246,15 @@ struct bcm_rsb {
#define MIB_RX_CNT_RST (1 << 0)
#define MIB_RUNT_CNT_RST (1 << 1)
#define MIB_TX_CNT_RST (1 << 2)
+
+#define UMAC_MPD_CTRL 0x620
+#define MPD_EN (1 << 0)
+#define MSEQ_LEN_SHIFT 16
+#define MSEQ_LEN_MASK 0xff
+#define PSW_EN (1 << 27)
+
+#define UMAC_PSW_MS 0x624
+#define UMAC_PSW_LS 0x628
#define UMAC_MDF_CTRL 0x650
#define UMAC_MDF_ADDR 0x654
@@ -642,6 +651,7 @@ struct bcm_sysport_priv {
struct platform_device *pdev;
int irq0;
int irq1;
+ int wol_irq;
/* Transmit rings */
struct bcm_sysport_tx_ring tx_rings[TDMA_NUM_RINGS];
@@ -664,10 +674,12 @@ struct bcm_sysport_priv {
int old_duplex;
/* Misc fields */
- unsigned int rx_csum_en:1;
+ unsigned int rx_chk_en:1;
unsigned int tsb_en:1;
unsigned int crc_fwd:1;
u16 rev;
+ u32 wolopts;
+ unsigned int wol_irq_disabled:1;
/* MIB related fields */
struct bcm_sysport_mib mib;
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 67d2b0047371..2fee73b878c2 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -1,6 +1,7 @@
-/* bnx2.c: Broadcom NX2 network driver.
+/* bnx2.c: QLogic NX2 network driver.
*
- * Copyright (c) 2004-2013 Broadcom Corporation
+ * Copyright (c) 2004-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,10 +72,10 @@
#define TX_TIMEOUT (5*HZ)
static char version[] =
- "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ "QLogic NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/5716 Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_FIRMWARE(FW_MIPS_FILE_06);
@@ -119,7 +120,7 @@ static struct {
{ "Broadcom NetXtreme II BCM5716 1000Base-SX" },
};
-static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
+static const struct pci_device_id bnx2_pci_tbl[] = {
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h
index e341bc366fa5..28df35d35893 100644
--- a/drivers/net/ethernet/broadcom/bnx2.h
+++ b/drivers/net/ethernet/broadcom/bnx2.h
@@ -1,6 +1,7 @@
-/* bnx2.h: Broadcom NX2 network driver.
+/* bnx2.h: QLogic NX2 network driver.
*
- * Copyright (c) 2004-2013 Broadcom Corporation
+ * Copyright (c) 2004-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2_fw.h b/drivers/net/ethernet/broadcom/bnx2_fw.h
index 940eb91f209d..7db79c28b5ff 100644
--- a/drivers/net/ethernet/broadcom/bnx2_fw.h
+++ b/drivers/net/ethernet/broadcom/bnx2_fw.h
@@ -1,6 +1,7 @@
-/* bnx2_fw.h: Broadcom NX2 network driver.
+/* bnx2_fw.h: QLogic NX2 network driver.
*
* Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8206a293e6b4..d777fae86988 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1483,6 +1483,7 @@ struct bnx2x {
union pf_vf_bulletin *pf2vf_bulletin;
dma_addr_t pf2vf_bulletin_mapping;
+ union pf_vf_bulletin shadow_bulletin;
struct pf_vf_bulletin_content old_bulletin;
u16 requested_nr_virtfn;
@@ -1508,8 +1509,10 @@ struct bnx2x {
/* TCP with Timestamp Option (32) + IPv6 (40) */
#define ETH_MAX_TPA_HEADER_SIZE 72
- /* Max supported alignment is 256 (8 shift) */
-#define BNX2X_RX_ALIGN_SHIFT min(8, L1_CACHE_SHIFT)
+ /* Max supported alignment is 256 (8 shift)
+ * minimal alignment shift 6 is optimal for 57xxx HW performance
+ */
+#define BNX2X_RX_ALIGN_SHIFT max(6, min(8, L1_CACHE_SHIFT))
/* FW uses 2 Cache lines Alignment for start packet and size
*
@@ -1929,6 +1932,8 @@ struct bnx2x {
struct semaphore stats_sema;
u8 phys_port_id[ETH_ALEN];
+
+ struct bnx2x_link_report_data vf_link_vars;
};
/* Tx queues may be less or equal to Rx queues */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index c43e7238de21..4e6c82e20224 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1192,29 +1192,38 @@ u16 bnx2x_get_mf_speed(struct bnx2x *bp)
static void bnx2x_fill_report_data(struct bnx2x *bp,
struct bnx2x_link_report_data *data)
{
- u16 line_speed = bnx2x_get_mf_speed(bp);
-
memset(data, 0, sizeof(*data));
- /* Fill the report data: effective line speed */
- data->line_speed = line_speed;
-
- /* Link is down */
- if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
- __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
- &data->link_report_flags);
-
- /* Full DUPLEX */
- if (bp->link_vars.duplex == DUPLEX_FULL)
- __set_bit(BNX2X_LINK_REPORT_FD, &data->link_report_flags);
-
- /* Rx Flow Control is ON */
- if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
- __set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags);
-
- /* Tx Flow Control is ON */
- if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
- __set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags);
+ if (IS_PF(bp)) {
+ /* Fill the report data: effective line speed */
+ data->line_speed = bnx2x_get_mf_speed(bp);
+
+ /* Link is down */
+ if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
+ __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+ &data->link_report_flags);
+
+ if (!BNX2X_NUM_ETH_QUEUES(bp))
+ __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+ &data->link_report_flags);
+
+ /* Full DUPLEX */
+ if (bp->link_vars.duplex == DUPLEX_FULL)
+ __set_bit(BNX2X_LINK_REPORT_FD,
+ &data->link_report_flags);
+
+ /* Rx Flow Control is ON */
+ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
+ __set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+ &data->link_report_flags);
+
+ /* Tx Flow Control is ON */
+ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+ __set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+ &data->link_report_flags);
+ } else { /* VF */
+ *data = bp->vf_link_vars;
+ }
}
/**
@@ -1268,6 +1277,10 @@ void __bnx2x_link_report(struct bnx2x *bp)
*/
memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data));
+ /* propagate status to VFs */
+ if (IS_PF(bp))
+ bnx2x_iov_link_update(bp);
+
if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&cur_data.link_report_flags)) {
netif_carrier_off(bp->dev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
index 51a952c51cb1..fb26bc4c42a1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
@@ -2303,8 +2303,8 @@ static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
return 0;
}
-static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
- u16 idval, u8 up)
+static int bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
+ u16 idval, u8 up)
{
struct bnx2x *bp = netdev_priv(netdev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 25eddd90f482..92fee842f954 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -216,6 +216,43 @@ static int bnx2x_get_port_type(struct bnx2x *bp)
return port_type;
}
+static int bnx2x_get_vf_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+
+ if (bp->state == BNX2X_STATE_OPEN) {
+ if (test_bit(BNX2X_LINK_REPORT_FD,
+ &bp->vf_link_vars.link_report_flags))
+ cmd->duplex = DUPLEX_FULL;
+ else
+ cmd->duplex = DUPLEX_HALF;
+
+ ethtool_cmd_speed_set(cmd, bp->vf_link_vars.line_speed);
+ } else {
+ cmd->duplex = DUPLEX_UNKNOWN;
+ ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+ }
+
+ cmd->port = PORT_OTHER;
+ cmd->phy_address = 0;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+
+ DP(BNX2X_MSG_ETHTOOL, "ethtool_cmd: cmd %d\n"
+ " supported 0x%x advertising 0x%x speed %u\n"
+ " duplex %d port %d phy_address %d transceiver %d\n"
+ " autoneg %d maxtxpkt %d maxrxpkt %d\n",
+ cmd->cmd, cmd->supported, cmd->advertising,
+ ethtool_cmd_speed(cmd),
+ cmd->duplex, cmd->port, cmd->phy_address, cmd->transceiver,
+ cmd->autoneg, cmd->maxtxpkt, cmd->maxrxpkt);
+
+ return 0;
+}
+
static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -1111,6 +1148,10 @@ static u32 bnx2x_get_link(struct net_device *dev)
if (bp->flags & MF_FUNC_DIS || (bp->state != BNX2X_STATE_OPEN))
return 0;
+ if (IS_VF(bp))
+ return !test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+ &bp->vf_link_vars.link_report_flags);
+
return bp->link_vars.link_up;
}
@@ -3485,8 +3526,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
};
static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
- .get_settings = bnx2x_get_settings,
- .set_settings = bnx2x_set_settings,
+ .get_settings = bnx2x_get_vf_settings,
.get_drvinfo = bnx2x_get_drvinfo,
.get_msglevel = bnx2x_get_msglevel,
.set_msglevel = bnx2x_set_msglevel,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 6a8b1453a1b9..c13364b6cc19 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -249,7 +249,7 @@ static struct {
#define PCI_DEVICE_ID_NX2_57811_VF CHIP_NUM_57811_VF
#endif
-static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
+static const struct pci_device_id bnx2x_pci_tbl[] = {
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
@@ -2698,6 +2698,14 @@ void bnx2x__link_status_update(struct bnx2x *bp)
bp->link_vars.duplex = DUPLEX_FULL;
bp->link_vars.flow_ctrl = BNX2X_FLOW_CTRL_NONE;
__bnx2x_link_report(bp);
+
+ bnx2x_sample_bulletin(bp);
+
+ /* if bulletin board did not have an update for link status
+ * __bnx2x_link_report will report current status
+ * but it will NOT duplicate report in case of already reported
+ * during sampling bulletin board.
+ */
bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
}
}
@@ -12424,6 +12432,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_busy_poll = bnx2x_low_latency_recv,
#endif
.ndo_get_phys_port_id = bnx2x_get_phys_port_id,
+ .ndo_set_vf_link_state = bnx2x_set_vf_link_state,
};
static int bnx2x_set_coherency_mask(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index eda8583f6fc0..662310c5f4e9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -24,6 +24,11 @@
#include <linux/crc32.h>
#include <linux/if_vlan.h>
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+ struct bnx2x_virtf **vf,
+ struct pf_vf_bulletin_content **bulletin,
+ bool test_queue);
+
/* General service functions */
static void storm_memset_vf_to_pf(struct bnx2x *bp, u16 abs_fid,
u16 pf_id)
@@ -597,8 +602,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_DEL);
if (rc) {
BNX2X_ERR("Failed to remove multicasts\n");
- if (mc)
- kfree(mc);
+ kfree(mc);
return rc;
}
@@ -1328,6 +1332,8 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
/* Prepare the VFs event synchronization mechanism */
mutex_init(&bp->vfdb->event_mutex);
+ mutex_init(&bp->vfdb->bulletin_mutex);
+
return 0;
failed:
DP(BNX2X_MSG_IOV, "Failed err=%d\n", err);
@@ -1473,6 +1479,107 @@ static void bnx2x_vfq_init(struct bnx2x *bp, struct bnx2x_virtf *vf,
vf->abs_vfid, q->sp_obj.func_id, q->cid);
}
+static int bnx2x_max_speed_cap(struct bnx2x *bp)
+{
+ u32 supported = bp->port.supported[bnx2x_get_link_cfg_idx(bp)];
+
+ if (supported &
+ (SUPPORTED_20000baseMLD2_Full | SUPPORTED_20000baseKR2_Full))
+ return 20000;
+
+ return 10000; /* assume lowest supported speed is 10G */
+}
+
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx)
+{
+ struct bnx2x_link_report_data *state = &bp->last_reported_link;
+ struct pf_vf_bulletin_content *bulletin;
+ struct bnx2x_virtf *vf;
+ bool update = true;
+ int rc = 0;
+
+ /* sanity and init */
+ rc = bnx2x_vf_op_prep(bp, idx, &vf, &bulletin, false);
+ if (rc)
+ return rc;
+
+ mutex_lock(&bp->vfdb->bulletin_mutex);
+
+ if (vf->link_cfg == IFLA_VF_LINK_STATE_AUTO) {
+ bulletin->valid_bitmap |= 1 << LINK_VALID;
+
+ bulletin->link_speed = state->line_speed;
+ bulletin->link_flags = 0;
+ if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+ &state->link_report_flags))
+ bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+ if (test_bit(BNX2X_LINK_REPORT_FD,
+ &state->link_report_flags))
+ bulletin->link_flags |= VFPF_LINK_REPORT_FULL_DUPLEX;
+ if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+ &state->link_report_flags))
+ bulletin->link_flags |= VFPF_LINK_REPORT_RX_FC_ON;
+ if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+ &state->link_report_flags))
+ bulletin->link_flags |= VFPF_LINK_REPORT_TX_FC_ON;
+ } else if (vf->link_cfg == IFLA_VF_LINK_STATE_DISABLE &&
+ !(bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+ bulletin->valid_bitmap |= 1 << LINK_VALID;
+ bulletin->link_flags |= VFPF_LINK_REPORT_LINK_DOWN;
+ } else if (vf->link_cfg == IFLA_VF_LINK_STATE_ENABLE &&
+ (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)) {
+ bulletin->valid_bitmap |= 1 << LINK_VALID;
+ bulletin->link_speed = bnx2x_max_speed_cap(bp);
+ bulletin->link_flags &= ~VFPF_LINK_REPORT_LINK_DOWN;
+ } else {
+ update = false;
+ }
+
+ if (update) {
+ DP(NETIF_MSG_LINK | BNX2X_MSG_IOV,
+ "vf %d mode %u speed %d flags %x\n", idx,
+ vf->link_cfg, bulletin->link_speed, bulletin->link_flags);
+
+ /* Post update on VF's bulletin board */
+ rc = bnx2x_post_vf_bulletin(bp, idx);
+ if (rc) {
+ BNX2X_ERR("failed to update VF[%d] bulletin\n", idx);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&bp->vfdb->bulletin_mutex);
+ return rc;
+}
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int idx, int link_state)
+{
+ struct bnx2x *bp = netdev_priv(dev);
+ struct bnx2x_virtf *vf = BP_VF(bp, idx);
+
+ if (!vf)
+ return -EINVAL;
+
+ if (vf->link_cfg == link_state)
+ return 0; /* nothing todo */
+
+ vf->link_cfg = link_state;
+
+ return bnx2x_iov_link_update_vf(bp, idx);
+}
+
+void bnx2x_iov_link_update(struct bnx2x *bp)
+{
+ int vfid;
+
+ if (!IS_SRIOV(bp))
+ return;
+
+ for_each_vf(bp, vfid)
+ bnx2x_iov_link_update_vf(bp, vfid);
+}
+
/* called by bnx2x_nic_load */
int bnx2x_iov_nic_init(struct bnx2x *bp)
{
@@ -2510,22 +2617,23 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
pci_disable_sriov(bp->pdev);
}
-static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
- struct bnx2x_virtf **vf,
- struct pf_vf_bulletin_content **bulletin)
+static int bnx2x_vf_op_prep(struct bnx2x *bp, int vfidx,
+ struct bnx2x_virtf **vf,
+ struct pf_vf_bulletin_content **bulletin,
+ bool test_queue)
{
if (bp->state != BNX2X_STATE_OPEN) {
- BNX2X_ERR("vf ndo called though PF is down\n");
+ BNX2X_ERR("PF is down - can't utilize iov-related functionality\n");
return -EINVAL;
}
if (!IS_SRIOV(bp)) {
- BNX2X_ERR("vf ndo called though sriov is disabled\n");
+ BNX2X_ERR("sriov is disabled - can't utilize iov-realted functionality\n");
return -EINVAL;
}
if (vfidx >= BNX2X_NR_VIRTFN(bp)) {
- BNX2X_ERR("vf ndo called for uninitialized VF. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
+ BNX2X_ERR("VF is uninitialized - can't utilize iov-related functionality. vfidx was %d BNX2X_NR_VIRTFN was %d\n",
vfidx, BNX2X_NR_VIRTFN(bp));
return -EINVAL;
}
@@ -2535,19 +2643,18 @@ static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
*bulletin = BP_VF_BULLETIN(bp, vfidx);
if (!*vf) {
- BNX2X_ERR("vf ndo called but vf struct is null. vfidx was %d\n",
- vfidx);
+ BNX2X_ERR("Unable to get VF structure for vfidx %d\n", vfidx);
return -EINVAL;
}
- if (!(*vf)->vfqs) {
- BNX2X_ERR("vf ndo called but vfqs struct is null. Was ndo invoked before dynamically enabling SR-IOV? vfidx was %d\n",
+ if (test_queue && !(*vf)->vfqs) {
+ BNX2X_ERR("vfqs struct is null. Was this invoked before dynamically enabling SR-IOV? vfidx was %d\n",
vfidx);
return -EINVAL;
}
if (!*bulletin) {
- BNX2X_ERR("vf ndo called but Bulletin Board struct is null. vfidx was %d\n",
+ BNX2X_ERR("Bulletin Board struct is null for vfidx %d\n",
vfidx);
return -EINVAL;
}
@@ -2566,9 +2673,10 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
int rc;
/* sanity and init */
- rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
+ rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
if (rc)
return rc;
+
mac_obj = &bnx2x_leading_vfq(vf, mac_obj);
vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
if (!mac_obj || !vlan_obj) {
@@ -2591,6 +2699,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
VLAN_HLEN);
}
} else {
+ mutex_lock(&bp->vfdb->bulletin_mutex);
/* mac */
if (bulletin->valid_bitmap & (1 << MAC_ADDR_VALID))
/* mac configured by ndo so its in bulletin board */
@@ -2606,6 +2715,8 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx,
else
/* function has not been loaded yet. Show vlans as 0s */
memset(&ivi->vlan, 0, VLAN_HLEN);
+
+ mutex_unlock(&bp->vfdb->bulletin_mutex);
}
return 0;
@@ -2635,15 +2746,18 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
struct bnx2x_virtf *vf = NULL;
struct pf_vf_bulletin_content *bulletin = NULL;
- /* sanity and init */
- rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
- if (rc)
- return rc;
if (!is_valid_ether_addr(mac)) {
BNX2X_ERR("mac address invalid\n");
return -EINVAL;
}
+ /* sanity and init */
+ rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+ if (rc)
+ return rc;
+
+ mutex_lock(&bp->vfdb->bulletin_mutex);
+
/* update PF's copy of the VF's bulletin. Will no longer accept mac
* configuration requests from vf unless match this mac
*/
@@ -2652,6 +2766,10 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac)
/* Post update on VF's bulletin board */
rc = bnx2x_post_vf_bulletin(bp, vfidx);
+
+ /* release lock before checking return code */
+ mutex_unlock(&bp->vfdb->bulletin_mutex);
+
if (rc) {
BNX2X_ERR("failed to update VF[%d] bulletin\n", vfidx);
return rc;
@@ -2716,11 +2834,6 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
unsigned long accept_flags;
int rc;
- /* sanity and init */
- rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
- if (rc)
- return rc;
-
if (vlan > 4095) {
BNX2X_ERR("illegal vlan value %d\n", vlan);
return -EINVAL;
@@ -2729,18 +2842,27 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
DP(BNX2X_MSG_IOV, "configuring VF %d with VLAN %d qos %d\n",
vfidx, vlan, 0);
+ /* sanity and init */
+ rc = bnx2x_vf_op_prep(bp, vfidx, &vf, &bulletin, true);
+ if (rc)
+ return rc;
+
/* update PF's copy of the VF's bulletin. No point in posting the vlan
* to the VF since it doesn't have anything to do with it. But it useful
* to store it here in case the VF is not up yet and we can only
* configure the vlan later when it does. Treat vlan id 0 as remove the
* Host tag.
*/
+ mutex_lock(&bp->vfdb->bulletin_mutex);
+
if (vlan > 0)
bulletin->valid_bitmap |= 1 << VLAN_VALID;
else
bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
bulletin->vlan = vlan;
+ mutex_unlock(&bp->vfdb->bulletin_mutex);
+
/* is vf initialized and queue set up? */
if (vf->state != VF_ENABLED ||
bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
@@ -2850,10 +2972,9 @@ out:
* entire bulletin board excluding the crc field itself. Use the length field
* as the Bulletin Board was posted by a PF with possibly a different version
* from the vf which will sample it. Therefore, the length is computed by the
- * PF and the used blindly by the VF.
+ * PF and then used blindly by the VF.
*/
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
- struct pf_vf_bulletin_content *bulletin)
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin)
{
return crc32(BULLETIN_CRC_SEED,
((u8 *)bulletin) + sizeof(bulletin->crc),
@@ -2863,47 +2984,74 @@ u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
/* Check for new posts on the bulletin board */
enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp)
{
- struct pf_vf_bulletin_content bulletin = bp->pf2vf_bulletin->content;
+ struct pf_vf_bulletin_content *bulletin;
int attempts;
- /* bulletin board hasn't changed since last sample */
- if (bp->old_bulletin.version == bulletin.version)
- return PFVF_BULLETIN_UNCHANGED;
+ /* sampling structure in mid post may result with corrupted data
+ * validate crc to ensure coherency.
+ */
+ for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
+ u32 crc;
- /* validate crc of new bulletin board */
- if (bp->old_bulletin.version != bp->pf2vf_bulletin->content.version) {
- /* sampling structure in mid post may result with corrupted data
- * validate crc to ensure coherency.
- */
- for (attempts = 0; attempts < BULLETIN_ATTEMPTS; attempts++) {
- bulletin = bp->pf2vf_bulletin->content;
- if (bulletin.crc == bnx2x_crc_vf_bulletin(bp,
- &bulletin))
- break;
- BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
- bulletin.crc,
- bnx2x_crc_vf_bulletin(bp, &bulletin));
- }
- if (attempts >= BULLETIN_ATTEMPTS) {
- BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
- attempts);
- return PFVF_BULLETIN_CRC_ERR;
- }
+ /* sample the bulletin board */
+ memcpy(&bp->shadow_bulletin, bp->pf2vf_bulletin,
+ sizeof(union pf_vf_bulletin));
+
+ crc = bnx2x_crc_vf_bulletin(&bp->shadow_bulletin.content);
+
+ if (bp->shadow_bulletin.content.crc == crc)
+ break;
+
+ BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n",
+ bp->shadow_bulletin.content.crc, crc);
+ }
+
+ if (attempts >= BULLETIN_ATTEMPTS) {
+ BNX2X_ERR("pf to vf bulletin board crc was wrong %d consecutive times. Aborting\n",
+ attempts);
+ return PFVF_BULLETIN_CRC_ERR;
}
+ bulletin = &bp->shadow_bulletin.content;
+
+ /* bulletin board hasn't changed since last sample */
+ if (bp->old_bulletin.version == bulletin->version)
+ return PFVF_BULLETIN_UNCHANGED;
/* the mac address in bulletin board is valid and is new */
- if (bulletin.valid_bitmap & 1 << MAC_ADDR_VALID &&
- !ether_addr_equal(bulletin.mac, bp->old_bulletin.mac)) {
+ if (bulletin->valid_bitmap & 1 << MAC_ADDR_VALID &&
+ !ether_addr_equal(bulletin->mac, bp->old_bulletin.mac)) {
/* update new mac to net device */
- memcpy(bp->dev->dev_addr, bulletin.mac, ETH_ALEN);
+ memcpy(bp->dev->dev_addr, bulletin->mac, ETH_ALEN);
+ }
+
+ if (bulletin->valid_bitmap & (1 << LINK_VALID)) {
+ DP(BNX2X_MSG_IOV, "link update speed %d flags %x\n",
+ bulletin->link_speed, bulletin->link_flags);
+
+ bp->vf_link_vars.line_speed = bulletin->link_speed;
+ bp->vf_link_vars.link_report_flags = 0;
+ /* Link is down */
+ if (bulletin->link_flags & VFPF_LINK_REPORT_LINK_DOWN)
+ __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
+ &bp->vf_link_vars.link_report_flags);
+ /* Full DUPLEX */
+ if (bulletin->link_flags & VFPF_LINK_REPORT_FULL_DUPLEX)
+ __set_bit(BNX2X_LINK_REPORT_FD,
+ &bp->vf_link_vars.link_report_flags);
+ /* Rx Flow Control is ON */
+ if (bulletin->link_flags & VFPF_LINK_REPORT_RX_FC_ON)
+ __set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
+ &bp->vf_link_vars.link_report_flags);
+ /* Tx Flow Control is ON */
+ if (bulletin->link_flags & VFPF_LINK_REPORT_TX_FC_ON)
+ __set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
+ &bp->vf_link_vars.link_report_flags);
+ __bnx2x_link_report(bp);
}
- /* the vlan in bulletin board is valid and is new */
- if (bulletin.valid_bitmap & 1 << VLAN_VALID)
- memcpy(&bulletin.vlan, &bp->old_bulletin.vlan, VLAN_HLEN);
-
/* copy new bulletin board to bp */
- bp->old_bulletin = bulletin;
+ memcpy(&bp->old_bulletin, bulletin,
+ sizeof(struct pf_vf_bulletin_content));
return PFVF_BULLETIN_UPDATED;
}
@@ -2948,6 +3096,8 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
if (!bp->pf2vf_bulletin)
goto alloc_mem_err;
+ bnx2x_vf_bulletin_finalize(&bp->pf2vf_bulletin->content, true);
+
return 0;
alloc_mem_err:
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index 96c575e147a5..ca1055f3d8af 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -126,7 +126,11 @@ struct bnx2x_virtf {
#define VF_CACHE_LINE 0x0010
#define VF_CFG_VLAN 0x0020
#define VF_CFG_STATS_COALESCE 0x0040
-
+#define VF_CFG_EXT_BULLETIN 0x0080
+ u8 link_cfg; /* IFLA_VF_LINK_STATE_AUTO
+ * IFLA_VF_LINK_STATE_ENABLE
+ * IFLA_VF_LINK_STATE_DISABLE
+ */
u8 state;
#define VF_FREE 0 /* VF ready to be acquired holds no resc */
#define VF_ACQUIRED 1 /* VF acquired, but not initialized */
@@ -295,22 +299,22 @@ struct bnx2x_vfdb {
#define BP_VFDB(bp) ((bp)->vfdb)
/* vf array */
struct bnx2x_virtf *vfs;
-#define BP_VF(bp, idx) (&((bp)->vfdb->vfs[(idx)]))
-#define bnx2x_vf(bp, idx, var) ((bp)->vfdb->vfs[(idx)].var)
+#define BP_VF(bp, idx) (&((bp)->vfdb->vfs[idx]))
+#define bnx2x_vf(bp, idx, var) ((bp)->vfdb->vfs[idx].var)
/* queue array - for all vfs */
struct bnx2x_vf_queue *vfqs;
/* vf HW contexts */
struct hw_dma context[BNX2X_VF_CIDS/ILT_PAGE_CIDS];
-#define BP_VF_CXT_PAGE(bp, i) (&(bp)->vfdb->context[(i)])
+#define BP_VF_CXT_PAGE(bp, i) (&(bp)->vfdb->context[i])
/* SR-IOV information */
struct bnx2x_sriov sriov;
struct hw_dma mbx_dma;
#define BP_VF_MBX_DMA(bp) (&((bp)->vfdb->mbx_dma))
struct bnx2x_vf_mbx mbxs[BNX2X_MAX_NUM_OF_VFS];
-#define BP_VF_MBX(bp, vfid) (&((bp)->vfdb->mbxs[(vfid)]))
+#define BP_VF_MBX(bp, vfid) (&((bp)->vfdb->mbxs[vfid]))
struct hw_dma bulletin_dma;
#define BP_VF_BULLETIN_DMA(bp) (&((bp)->vfdb->bulletin_dma))
@@ -336,6 +340,9 @@ struct bnx2x_vfdb {
/* sp_rtnl synchronization */
struct mutex event_mutex;
u64 event_occur;
+
+ /* bulletin board update synchronization */
+ struct mutex bulletin_mutex;
};
/* queue access */
@@ -467,9 +474,10 @@ void bnx2x_vf_handle_flr_event(struct bnx2x *bp);
bool bnx2x_tlv_supported(u16 tlvtype);
-u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp,
- struct pf_vf_bulletin_content *bulletin);
+u32 bnx2x_crc_vf_bulletin(struct pf_vf_bulletin_content *bulletin);
int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf);
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+ bool support_long);
enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
@@ -520,6 +528,11 @@ void bnx2x_iov_task(struct work_struct *work);
void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag);
+void bnx2x_iov_link_update(struct bnx2x *bp);
+int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx);
+
+int bnx2x_set_vf_link_state(struct net_device *dev, int vf, int link_state);
+
#else /* CONFIG_BNX2X_SRIOV */
static inline void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
@@ -579,6 +592,14 @@ static inline void bnx2x_iov_channel_down(struct bnx2x *bp) {}
static inline void bnx2x_iov_task(struct work_struct *work) {}
static inline void bnx2x_schedule_iov_task(struct bnx2x *bp, enum bnx2x_iov_flag flag) {}
+static inline void bnx2x_iov_link_update(struct bnx2x *bp) {}
+static inline int bnx2x_iov_link_update_vf(struct bnx2x *bp, int idx) {return 0; }
+
+static inline int bnx2x_set_vf_link_state(struct net_device *dev, int vf,
+ int link_state) {return 0; }
+struct pf_vf_bulletin_content;
+static inline void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+ bool support_long) {}
#endif /* CONFIG_BNX2X_SRIOV */
#endif /* bnx2x_sriov.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index d712d0ddd719..54e0427a9ee6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -251,6 +251,9 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));
+ /* Bulletin support for bulletin board with length > legacy length */
+ req->vfdev_info.caps |= VF_CAP_SUPPORT_EXT_BULLETIN;
+
/* add list termination tlv */
bnx2x_add_tlv(bp, req,
req->first_tlv.tl.length + sizeof(struct channel_tlv),
@@ -1232,6 +1235,41 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
bnx2x_vf_mbx_resp_send_msg(bp, vf, vfop_status);
}
+static bool bnx2x_vf_mbx_is_windows_vm(struct bnx2x *bp,
+ struct vfpf_acquire_tlv *acquire)
+{
+ /* Windows driver does one of three things:
+ * 1. Old driver doesn't have bulletin board address set.
+ * 2. 'Middle' driver sends mc_num == 32.
+ * 3. New driver sets the OS field.
+ */
+ if (!acquire->bulletin_addr ||
+ acquire->resc_request.num_mc_filters == 32 ||
+ ((acquire->vfdev_info.vf_os & VF_OS_MASK) ==
+ VF_OS_WINDOWS))
+ return true;
+
+ return false;
+}
+
+static int bnx2x_vf_mbx_acquire_chk_dorq(struct bnx2x *bp,
+ struct bnx2x_virtf *vf,
+ struct bnx2x_vf_mbx *mbx)
+{
+ /* Linux drivers which correctly set the doorbell size also
+ * send a physical port request
+ */
+ if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
+ CHANNEL_TLV_PHYS_PORT_ID))
+ return 0;
+
+ /* Issue does not exist in windows VMs */
+ if (bnx2x_vf_mbx_is_windows_vm(bp, &mbx->msg->req.acquire))
+ return 0;
+
+ return -EOPNOTSUPP;
+}
+
static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct bnx2x_vf_mbx *mbx)
{
@@ -1247,12 +1285,32 @@ static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
acquire->resc_request.num_vlan_filters,
acquire->resc_request.num_mc_filters);
+ /* Prevent VFs with old drivers from loading, since they calculate
+ * CIDs incorrectly requiring a VF-flr [VM reboot] in order to recover
+ * while being upgraded.
+ */
+ rc = bnx2x_vf_mbx_acquire_chk_dorq(bp, vf, mbx);
+ if (rc) {
+ DP(BNX2X_MSG_IOV,
+ "VF [%d] - Can't support acquire request due to doorbell mismatch. Please update VM driver\n",
+ vf->abs_vfid);
+ goto out;
+ }
+
/* acquire the resources */
rc = bnx2x_vf_acquire(bp, vf, &acquire->resc_request);
/* store address of vf's bulletin board */
vf->bulletin_map = acquire->bulletin_addr;
+ if (acquire->vfdev_info.caps & VF_CAP_SUPPORT_EXT_BULLETIN) {
+ DP(BNX2X_MSG_IOV, "VF[%d] supports long bulletin boards\n",
+ vf->abs_vfid);
+ vf->cfg_flags |= VF_CFG_EXT_BULLETIN;
+ } else {
+ vf->cfg_flags &= ~VF_CFG_EXT_BULLETIN;
+ }
+out:
/* response */
bnx2x_vf_mbx_acquire_resp(bp, vf, mbx, rc);
}
@@ -1273,6 +1331,10 @@ static void bnx2x_vf_mbx_init_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
if (init->flags & VFPF_INIT_FLG_STATS_COALESCE)
vf->cfg_flags |= VF_CFG_STATS_COALESCE;
+ /* Update VF's view of link state */
+ if (vf->cfg_flags & VF_CFG_EXT_BULLETIN)
+ bnx2x_iov_link_update_vf(bp, vf->index);
+
/* response */
bnx2x_vf_mbx_resp(bp, vf, rc);
}
@@ -2007,6 +2069,17 @@ void bnx2x_vf_mbx(struct bnx2x *bp)
}
}
+void bnx2x_vf_bulletin_finalize(struct pf_vf_bulletin_content *bulletin,
+ bool support_long)
+{
+ /* Older VFs contain a bug where they can't check CRC for bulletin
+ * boards of length greater than legacy size.
+ */
+ bulletin->length = support_long ? BULLETIN_CONTENT_SIZE :
+ BULLETIN_CONTENT_LEGACY_SIZE;
+ bulletin->crc = bnx2x_crc_vf_bulletin(bulletin);
+}
+
/* propagate local bulletin board to vf */
int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
{
@@ -2023,8 +2096,9 @@ int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf)
/* increment bulletin board version and compute crc */
bulletin->version++;
- bulletin->length = BULLETIN_CONTENT_SIZE;
- bulletin->crc = bnx2x_crc_vf_bulletin(bp, bulletin);
+ bnx2x_vf_bulletin_finalize(bulletin,
+ (bnx2x_vf(bp, vf, cfg_flags) &
+ VF_CFG_EXT_BULLETIN) ? true : false);
/* propagate bulletin board via dmae to vm memory */
rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index e21e706762c9..15670c499a20 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -65,6 +65,7 @@ struct hw_sb_info {
#define VFPF_RX_MASK_ACCEPT_ALL_MULTICAST 0x00000008
#define VFPF_RX_MASK_ACCEPT_BROADCAST 0x00000010
#define BULLETIN_CONTENT_SIZE (sizeof(struct pf_vf_bulletin_content))
+#define BULLETIN_CONTENT_LEGACY_SIZE (32)
#define BULLETIN_ATTEMPTS 5 /* crc failures before throwing towel */
#define BULLETIN_CRC_SEED 0
@@ -117,7 +118,15 @@ struct vfpf_acquire_tlv {
/* the following fields are for debug purposes */
u8 vf_id; /* ME register value */
u8 vf_os; /* e.g. Linux, W2K8 */
- u8 padding[2];
+#define VF_OS_SUBVERSION_MASK (0x1f)
+#define VF_OS_MASK (0xe0)
+#define VF_OS_SHIFT (5)
+#define VF_OS_UNDEFINED (0 << VF_OS_SHIFT)
+#define VF_OS_WINDOWS (1 << VF_OS_SHIFT)
+
+ u8 padding;
+ u8 caps;
+#define VF_CAP_SUPPORT_EXT_BULLETIN (1 << 0)
} vfdev_info;
struct vf_pf_resc_request resc_request;
@@ -393,11 +402,23 @@ struct pf_vf_bulletin_content {
* to attempt to send messages on the
* channel after this bit is set
*/
+#define LINK_VALID 3 /* alert the VF thet a new link status
+ * update is available for it
+ */
u8 mac[ETH_ALEN];
u8 mac_padding[2];
u16 vlan;
u8 vlan_padding[6];
+
+ u16 link_speed; /* Effective line speed */
+ u8 link_speed_padding[6];
+ u32 link_flags; /* VFPF_LINK_REPORT_XXX flags */
+#define VFPF_LINK_REPORT_LINK_DOWN (1 << 0)
+#define VFPF_LINK_REPORT_FULL_DUPLEX (1 << 1)
+#define VFPF_LINK_REPORT_RX_FC_ON (1 << 2)
+#define VFPF_LINK_REPORT_TX_FC_ON (1 << 3)
+ u8 link_flags_padding[4];
};
union pf_vf_bulletin {
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 8244e2b14bb4..27861a6c7ca5 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -1,13 +1,15 @@
-/* cnic.c: Broadcom CNIC core network driver.
+/* cnic.c: QLogic CNIC core network driver.
*
* Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Original skeleton written by: John(Zongxi) Chen (zongxi@broadcom.com)
- * Modified and maintained by: Michael Chan <mchan@broadcom.com>
+ * Previously modified and maintained by: Michael Chan <mchan@broadcom.com>
+ * Maintained By: Dept-HSGLinuxNICDev@qlogic.com
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -56,11 +58,11 @@
#define CNIC_MODULE_NAME "cnic"
static char version[] =
- "Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+ "QLogic NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
"Chen (zongxi@broadcom.com");
-MODULE_DESCRIPTION("Broadcom NetXtreme II CNIC Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II CNIC Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(CNIC_MODULE_VERSION);
diff --git a/drivers/net/ethernet/broadcom/cnic.h b/drivers/net/ethernet/broadcom/cnic.h
index d535ae4228b4..4baea81bae7a 100644
--- a/drivers/net/ethernet/broadcom/cnic.h
+++ b/drivers/net/ethernet/broadcom/cnic.h
@@ -1,6 +1,7 @@
-/* cnic.h: Broadcom CNIC core network driver.
+/* cnic.h: QLogic CNIC core network driver.
*
* Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/cnic_defs.h b/drivers/net/ethernet/broadcom/cnic_defs.h
index dcbca6997e8f..b38499774071 100644
--- a/drivers/net/ethernet/broadcom/cnic_defs.h
+++ b/drivers/net/ethernet/broadcom/cnic_defs.h
@@ -1,7 +1,8 @@
-/* cnic.c: Broadcom CNIC core network driver.
+/* cnic.c: QLogic CNIC core network driver.
*
* Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 5f4d5573a73d..8bb36c1c4d68 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -1,6 +1,7 @@
-/* cnic_if.h: Broadcom CNIC core network driver.
+/* cnic_if.h: QLogic CNIC core network driver.
*
* Copyright (c) 2006-2014 Broadcom Corporation
+ * Copyright (c) 2014 QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/net/ethernet/broadcom/genet/Makefile b/drivers/net/ethernet/broadcom/genet/Makefile
index 31f55a90a197..9b6885efa9e7 100644
--- a/drivers/net/ethernet/broadcom/genet/Makefile
+++ b/drivers/net/ethernet/broadcom/genet/Makefile
@@ -1,2 +1,2 @@
obj-$(CONFIG_BCMGENET) += genet.o
-genet-objs := bcmgenet.o bcmmii.o
+genet-objs := bcmgenet.o bcmmii.o bcmgenet_wol.o
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 4e615debe472..3f9d4de8173c 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -6,15 +6,6 @@
* 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.
*/
#define pr_fmt(fmt) "bcmgenet: " fmt
@@ -79,13 +70,13 @@
TOTAL_DESC * DMA_DESC_SIZE)
static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
- void __iomem *d, u32 value)
+ void __iomem *d, u32 value)
{
__raw_writel(value, d + DMA_DESC_LENGTH_STATUS);
}
static inline u32 dmadesc_get_length_status(struct bcmgenet_priv *priv,
- void __iomem *d)
+ void __iomem *d)
{
return __raw_readl(d + DMA_DESC_LENGTH_STATUS);
}
@@ -98,7 +89,7 @@ static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,
/* Register writes to GISB bus can take couple hundred nanoseconds
* and are done for each packet, save these expensive writes unless
- * the platform is explicitely configured for 64-bits/LPAE.
+ * the platform is explicitly configured for 64-bits/LPAE.
*/
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (priv->hw_params->flags & GENET_HAS_40BITS)
@@ -108,7 +99,7 @@ static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,
/* Combined address + length/status setter */
static inline void dmadesc_set(struct bcmgenet_priv *priv,
- void __iomem *d, dma_addr_t addr, u32 val)
+ void __iomem *d, dma_addr_t addr, u32 val)
{
dmadesc_set_length_status(priv, d, val);
dmadesc_set_addr(priv, d, addr);
@@ -123,7 +114,7 @@ static inline dma_addr_t dmadesc_get_addr(struct bcmgenet_priv *priv,
/* Register writes to GISB bus can take couple hundred nanoseconds
* and are done for each packet, save these expensive writes unless
- * the platform is explicitely configured for 64-bits/LPAE.
+ * the platform is explicitly configured for 64-bits/LPAE.
*/
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (priv->hw_params->flags & GENET_HAS_40BITS)
@@ -242,7 +233,7 @@ static inline struct bcmgenet_priv *dev_to_priv(struct device *dev)
}
static inline u32 bcmgenet_tdma_readl(struct bcmgenet_priv *priv,
- enum dma_reg r)
+ enum dma_reg r)
{
return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
@@ -256,7 +247,7 @@ static inline void bcmgenet_tdma_writel(struct bcmgenet_priv *priv,
}
static inline u32 bcmgenet_rdma_readl(struct bcmgenet_priv *priv,
- enum dma_reg r)
+ enum dma_reg r)
{
return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
@@ -333,8 +324,8 @@ static const u8 genet_dma_ring_regs_v123[] = {
static const u8 *genet_dma_ring_regs;
static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,
- unsigned int ring,
- enum dma_ring_reg r)
+ unsigned int ring,
+ enum dma_ring_reg r)
{
return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
(DMA_RING_SIZE * ring) +
@@ -342,9 +333,8 @@ static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,
}
static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,
- unsigned int ring,
- u32 val,
- enum dma_ring_reg r)
+ unsigned int ring, u32 val,
+ enum dma_ring_reg r)
{
__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
(DMA_RING_SIZE * ring) +
@@ -352,8 +342,8 @@ static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,
}
static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,
- unsigned int ring,
- enum dma_ring_reg r)
+ unsigned int ring,
+ enum dma_ring_reg r)
{
return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
(DMA_RING_SIZE * ring) +
@@ -361,9 +351,8 @@ static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,
}
static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
- unsigned int ring,
- u32 val,
- enum dma_ring_reg r)
+ unsigned int ring, u32 val,
+ enum dma_ring_reg r)
{
__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
(DMA_RING_SIZE * ring) +
@@ -371,7 +360,7 @@ static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
}
static int bcmgenet_get_settings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+ struct ethtool_cmd *cmd)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -385,7 +374,7 @@ static int bcmgenet_get_settings(struct net_device *dev,
}
static int bcmgenet_set_settings(struct net_device *dev,
- struct ethtool_cmd *cmd)
+ struct ethtool_cmd *cmd)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -458,7 +447,7 @@ static int bcmgenet_set_tx_csum(struct net_device *dev,
}
static int bcmgenet_set_features(struct net_device *dev,
- netdev_features_t features)
+ netdev_features_t features)
{
netdev_features_t changed = features ^ dev->features;
netdev_features_t wanted = dev->wanted_features;
@@ -625,12 +614,11 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
#define BCMGENET_STATS_LEN ARRAY_SIZE(bcmgenet_gstrings_stats)
static void bcmgenet_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *info)
+ struct ethtool_drvinfo *info)
{
strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
strlcpy(info->version, "v2.0", sizeof(info->version));
info->n_stats = BCMGENET_STATS_LEN;
-
}
static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
@@ -643,8 +631,8 @@ static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
}
}
-static void bcmgenet_get_strings(struct net_device *dev,
- u32 stringset, u8 *data)
+static void bcmgenet_get_strings(struct net_device *dev, u32 stringset,
+ u8 *data)
{
int i;
@@ -652,8 +640,8 @@ static void bcmgenet_get_strings(struct net_device *dev,
case ETH_SS_STATS:
for (i = 0; i < BCMGENET_STATS_LEN; i++) {
memcpy(data + i * ETH_GSTRING_LEN,
- bcmgenet_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ bcmgenet_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
}
break;
}
@@ -678,8 +666,8 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
case BCMGENET_STAT_RUNT:
if (s->type != BCMGENET_STAT_MIB_RX)
offset = BCMGENET_STAT_OFFSET;
- val = bcmgenet_umac_readl(priv, UMAC_MIB_START +
- j + offset);
+ val = bcmgenet_umac_readl(priv,
+ UMAC_MIB_START + j + offset);
break;
case BCMGENET_STAT_MISC:
val = bcmgenet_umac_readl(priv, s->reg_offset);
@@ -696,8 +684,8 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv)
}
static void bcmgenet_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats,
- u64 *data)
+ struct ethtool_stats *stats,
+ u64 *data)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
int i;
@@ -730,6 +718,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_msglevel = bcmgenet_get_msglevel,
.set_msglevel = bcmgenet_set_msglevel,
+ .get_wol = bcmgenet_get_wol,
+ .set_wol = bcmgenet_set_wol,
};
/* Power down the unimac, based on mode. */
@@ -743,9 +733,12 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv,
phy_detach(priv->phydev);
break;
+ case GENET_POWER_WOL_MAGIC:
+ bcmgenet_wol_power_down_cfg(priv, mode);
+ break;
+
case GENET_POWER_PASSIVE:
/* Power down LED */
- bcmgenet_mii_reset(priv->dev);
if (priv->hw_params->flags & GENET_HAS_EXT) {
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= (EXT_PWR_DOWN_PHY |
@@ -759,7 +752,7 @@ static void bcmgenet_power_down(struct bcmgenet_priv *priv,
}
static void bcmgenet_power_up(struct bcmgenet_priv *priv,
- enum bcmgenet_power_mode mode)
+ enum bcmgenet_power_mode mode)
{
u32 reg;
@@ -777,12 +770,17 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv,
/* enable APD */
reg |= EXT_PWR_DN_EN_LD;
break;
+ case GENET_POWER_WOL_MAGIC:
+ bcmgenet_wol_power_up_cfg(priv, mode);
+ return;
default:
break;
}
bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
- bcmgenet_mii_reset(priv->dev);
+
+ if (mode == GENET_POWER_PASSIVE)
+ bcmgenet_mii_reset(priv->dev);
}
/* ioctl handle special commands that are not present in ethtool. */
@@ -841,37 +839,37 @@ static inline void bcmgenet_tx_ring16_int_disable(struct bcmgenet_priv *priv,
struct bcmgenet_tx_ring *ring)
{
bcmgenet_intrl2_0_writel(priv,
- UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
- INTRL2_CPU_MASK_SET);
+ UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+ INTRL2_CPU_MASK_SET);
}
static inline void bcmgenet_tx_ring16_int_enable(struct bcmgenet_priv *priv,
struct bcmgenet_tx_ring *ring)
{
bcmgenet_intrl2_0_writel(priv,
- UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
- INTRL2_CPU_MASK_CLEAR);
+ UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE,
+ INTRL2_CPU_MASK_CLEAR);
}
static inline void bcmgenet_tx_ring_int_enable(struct bcmgenet_priv *priv,
- struct bcmgenet_tx_ring *ring)
+ struct bcmgenet_tx_ring *ring)
{
- bcmgenet_intrl2_1_writel(priv,
- (1 << ring->index), INTRL2_CPU_MASK_CLEAR);
+ bcmgenet_intrl2_1_writel(priv, (1 << ring->index),
+ INTRL2_CPU_MASK_CLEAR);
priv->int1_mask &= ~(1 << ring->index);
}
static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv,
struct bcmgenet_tx_ring *ring)
{
- bcmgenet_intrl2_1_writel(priv,
- (1 << ring->index), INTRL2_CPU_MASK_SET);
+ bcmgenet_intrl2_1_writel(priv, (1 << ring->index),
+ INTRL2_CPU_MASK_SET);
priv->int1_mask |= (1 << ring->index);
}
/* Unlocked version of the reclaim routine */
static void __bcmgenet_tx_reclaim(struct net_device *dev,
- struct bcmgenet_tx_ring *ring)
+ struct bcmgenet_tx_ring *ring)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
int last_tx_cn, last_c_index, num_tx_bds;
@@ -879,7 +877,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
struct netdev_queue *txq;
unsigned int c_index;
- /* Compute how many buffers are transmited since last xmit call */
+ /* Compute how many buffers are transmitted since last xmit call */
c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX);
txq = netdev_get_tx_queue(dev, ring->queue);
@@ -894,9 +892,9 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
last_tx_cn = num_tx_bds - last_c_index + c_index;
netif_dbg(priv, tx_done, dev,
- "%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
- __func__, ring->index,
- c_index, last_tx_cn, last_c_index);
+ "%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
+ __func__, ring->index,
+ c_index, last_tx_cn, last_c_index);
/* Reclaim transmitted buffers */
while (last_tx_cn-- > 0) {
@@ -904,17 +902,17 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
if (tx_cb_ptr->skb) {
dev->stats.tx_bytes += tx_cb_ptr->skb->len;
dma_unmap_single(&dev->dev,
- dma_unmap_addr(tx_cb_ptr, dma_addr),
- tx_cb_ptr->skb->len,
- DMA_TO_DEVICE);
+ dma_unmap_addr(tx_cb_ptr, dma_addr),
+ tx_cb_ptr->skb->len,
+ DMA_TO_DEVICE);
bcmgenet_free_cb(tx_cb_ptr);
} else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
dev->stats.tx_bytes +=
dma_unmap_len(tx_cb_ptr, dma_len);
dma_unmap_page(&dev->dev,
- dma_unmap_addr(tx_cb_ptr, dma_addr),
- dma_unmap_len(tx_cb_ptr, dma_len),
- DMA_TO_DEVICE);
+ dma_unmap_addr(tx_cb_ptr, dma_addr),
+ dma_unmap_len(tx_cb_ptr, dma_len),
+ DMA_TO_DEVICE);
dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0);
}
dev->stats.tx_packets++;
@@ -934,7 +932,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev,
}
static void bcmgenet_tx_reclaim(struct net_device *dev,
- struct bcmgenet_tx_ring *ring)
+ struct bcmgenet_tx_ring *ring)
{
unsigned long flags;
@@ -1008,11 +1006,11 @@ static int bcmgenet_xmit_single(struct net_device *dev,
return 0;
}
-/* Transmit a SKB fragement */
+/* Transmit a SKB fragment */
static int bcmgenet_xmit_frag(struct net_device *dev,
- skb_frag_t *frag,
- u16 dma_desc_flags,
- struct bcmgenet_tx_ring *ring)
+ skb_frag_t *frag,
+ u16 dma_desc_flags,
+ struct bcmgenet_tx_ring *ring)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
@@ -1027,11 +1025,11 @@ static int bcmgenet_xmit_frag(struct net_device *dev,
tx_cb_ptr->skb = NULL;
mapping = skb_frag_dma_map(kdev, frag, 0,
- skb_frag_size(frag), DMA_TO_DEVICE);
+ skb_frag_size(frag), DMA_TO_DEVICE);
ret = dma_mapping_error(kdev, mapping);
if (ret) {
netif_err(priv, tx_err, dev, "%s: Tx DMA map failed\n",
- __func__);
+ __func__);
return ret;
}
@@ -1039,8 +1037,8 @@ static int bcmgenet_xmit_frag(struct net_device *dev,
dma_unmap_len_set(tx_cb_ptr, dma_len, frag->size);
dmadesc_set(priv, tx_cb_ptr->bd_addr, mapping,
- (frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
- (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT));
+ (frag->size << DMA_BUFLENGTH_SHIFT) | dma_desc_flags |
+ (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT));
ring->free_bds -= 1;
@@ -1103,8 +1101,9 @@ static int bcmgenet_put_tx_csum(struct net_device *dev, struct sk_buff *skb)
tx_csum_info |= STATUS_TX_CSUM_LV;
if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP)
tx_csum_info |= STATUS_TX_CSUM_PROTO_UDP;
- } else
+ } else {
tx_csum_info = 0;
+ }
status->tx_csum_info = tx_csum_info;
}
@@ -1144,7 +1143,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
if (ring->free_bds <= nr_frags + 1) {
netif_tx_stop_queue(txq);
netdev_err(dev, "%s: tx ring %d full when queue %d awake\n",
- __func__, index, ring->queue);
+ __func__, index, ring->queue);
ret = NETDEV_TX_BUSY;
goto out;
}
@@ -1177,8 +1176,9 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
/* xmit fragment */
for (i = 0; i < nr_frags; i++) {
ret = bcmgenet_xmit_frag(dev,
- &skb_shinfo(skb)->frags[i],
- (i == nr_frags - 1) ? DMA_EOP : 0, ring);
+ &skb_shinfo(skb)->frags[i],
+ (i == nr_frags - 1) ? DMA_EOP : 0,
+ ring);
if (ret) {
ret = NETDEV_TX_OK;
goto out;
@@ -1191,7 +1191,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
* producer index, now write it down to the hardware
*/
bcmgenet_tdma_ring_writel(priv, ring->index,
- ring->prod_index, TDMA_PROD_INDEX);
+ ring->prod_index, TDMA_PROD_INDEX);
if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) {
netif_tx_stop_queue(txq);
@@ -1205,16 +1205,14 @@ out:
}
-static int bcmgenet_rx_refill(struct bcmgenet_priv *priv,
- struct enet_cb *cb)
+static int bcmgenet_rx_refill(struct bcmgenet_priv *priv, struct enet_cb *cb)
{
struct device *kdev = &priv->pdev->dev;
struct sk_buff *skb;
dma_addr_t mapping;
int ret;
- skb = netdev_alloc_skb(priv->dev,
- priv->rx_buf_len + SKB_ALIGNMENT);
+ skb = netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT);
if (!skb)
return -ENOMEM;
@@ -1222,12 +1220,12 @@ static int bcmgenet_rx_refill(struct bcmgenet_priv *priv,
WARN_ON(cb->skb != NULL);
cb->skb = skb;
mapping = dma_map_single(kdev, skb->data,
- priv->rx_buf_len, DMA_FROM_DEVICE);
+ priv->rx_buf_len, DMA_FROM_DEVICE);
ret = dma_mapping_error(kdev, mapping);
if (ret) {
bcmgenet_free_cb(cb);
netif_err(priv, rx_err, priv->dev,
- "%s DMA map failed\n", __func__);
+ "%s DMA map failed\n", __func__);
return ret;
}
@@ -1262,8 +1260,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
unsigned int p_index;
unsigned int chksum_ok = 0;
- p_index = bcmgenet_rdma_ring_readl(priv,
- DESC_INDEX, RDMA_PROD_INDEX);
+ p_index = bcmgenet_rdma_ring_readl(priv, DESC_INDEX, RDMA_PROD_INDEX);
p_index &= DMA_P_INDEX_MASK;
if (p_index < priv->rx_c_index)
@@ -1273,11 +1270,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
rxpkttoprocess = p_index - priv->rx_c_index;
netif_dbg(priv, rx_status, dev,
- "RDMA: rxpkttoprocess=%d\n", rxpkttoprocess);
+ "RDMA: rxpkttoprocess=%d\n", rxpkttoprocess);
while ((rxpktprocessed < rxpkttoprocess) &&
- (rxpktprocessed < budget)) {
-
+ (rxpktprocessed < budget)) {
/* Unmap the packet contents such that we can use the
* RSV from the 64 bytes descriptor when enabled and save
* a 32-bits register read
@@ -1285,15 +1281,17 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
cb = &priv->rx_cbs[priv->rx_read_ptr];
skb = cb->skb;
dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr),
- priv->rx_buf_len, DMA_FROM_DEVICE);
+ priv->rx_buf_len, DMA_FROM_DEVICE);
if (!priv->desc_64b_en) {
- dma_length_status = dmadesc_get_length_status(priv,
- priv->rx_bds +
- (priv->rx_read_ptr *
- DMA_DESC_SIZE));
+ dma_length_status =
+ dmadesc_get_length_status(priv,
+ priv->rx_bds +
+ (priv->rx_read_ptr *
+ DMA_DESC_SIZE));
} else {
struct status_64 *status;
+
status = (struct status_64 *)skb->data;
dma_length_status = status->length_status;
}
@@ -1305,9 +1303,9 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
len = dma_length_status >> DMA_BUFLENGTH_SHIFT;
netif_dbg(priv, rx_status, dev,
- "%s: p_ind=%d c_ind=%d read_ptr=%d len_stat=0x%08x\n",
- __func__, p_index, priv->rx_c_index, priv->rx_read_ptr,
- dma_length_status);
+ "%s:p_ind=%d c_ind=%d read_ptr=%d len_stat=0x%08x\n",
+ __func__, p_index, priv->rx_c_index,
+ priv->rx_read_ptr, dma_length_status);
rxpktprocessed++;
@@ -1323,7 +1321,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
netif_err(priv, rx_status, dev,
- "Droping fragmented packet!\n");
+ "dropping fragmented packet!\n");
dev->stats.rx_dropped++;
dev->stats.rx_errors++;
dev_kfree_skb_any(cb->skb);
@@ -1337,7 +1335,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
DMA_RX_LG |
DMA_RX_RXER))) {
netif_err(priv, rx_status, dev, "dma_flag=0x%x\n",
- (unsigned int)dma_flag);
+ (unsigned int)dma_flag);
if (dma_flag & DMA_RX_CRC_ERROR)
dev->stats.rx_crc_errors++;
if (dma_flag & DMA_RX_OV)
@@ -1356,7 +1354,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
} /* error packet */
chksum_ok = (dma_flag & priv->dma_rx_chk_bit) &&
- priv->desc_rxchk_en;
+ priv->desc_rxchk_en;
skb_put(skb, len);
if (priv->desc_64b_en) {
@@ -1416,7 +1414,6 @@ static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv)
ret = bcmgenet_rx_refill(priv, cb);
if (ret)
break;
-
}
return ret;
@@ -1432,8 +1429,8 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
if (dma_unmap_addr(cb, dma_addr)) {
dma_unmap_single(&priv->dev->dev,
- dma_unmap_addr(cb, dma_addr),
- priv->rx_buf_len, DMA_FROM_DEVICE);
+ dma_unmap_addr(cb, dma_addr),
+ priv->rx_buf_len, DMA_FROM_DEVICE);
dma_unmap_addr_set(cb, dma_addr, 0);
}
@@ -1442,6 +1439,24 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
}
}
+static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
+{
+ u32 reg;
+
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+ /* UniMAC stops on a packet boundary, wait for a full-size packet
+ * to be processed
+ */
+ if (enable == 0)
+ usleep_range(1000, 2000);
+}
+
static int reset_umac(struct bcmgenet_priv *priv)
{
struct device *kdev = &priv->pdev->dev;
@@ -1467,13 +1482,24 @@ static int reset_umac(struct bcmgenet_priv *priv)
if (timeout == 1000) {
dev_err(kdev,
- "timeout waiting for MAC to come out of resetn\n");
+ "timeout waiting for MAC to come out of reset\n");
return -ETIMEDOUT;
}
return 0;
}
+static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
+{
+ /* Mask all interrupts.*/
+ bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
+ bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
+ bcmgenet_intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+ bcmgenet_intrl2_1_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
+ bcmgenet_intrl2_1_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
+ bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+}
+
static int init_umac(struct bcmgenet_priv *priv)
{
struct device *kdev = &priv->pdev->dev;
@@ -1489,7 +1515,8 @@ static int init_umac(struct bcmgenet_priv *priv)
bcmgenet_umac_writel(priv, 0, UMAC_CMD);
/* clear tx/rx counter */
bcmgenet_umac_writel(priv,
- MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT, UMAC_MIB_CTRL);
+ MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT,
+ UMAC_MIB_CTRL);
bcmgenet_umac_writel(priv, 0, UMAC_MIB_CTRL);
bcmgenet_umac_writel(priv, ENET_MAX_MTU_SIZE, UMAC_MAX_FRAME_LEN);
@@ -1502,21 +1529,18 @@ static int init_umac(struct bcmgenet_priv *priv)
if (!GENET_IS_V1(priv) && !GENET_IS_V2(priv))
bcmgenet_rbuf_writel(priv, 1, RBUF_TBUF_SIZE_CTRL);
- /* Mask all interrupts.*/
- bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_MASK_SET);
- bcmgenet_intrl2_0_writel(priv, 0xFFFFFFFF, INTRL2_CPU_CLEAR);
- bcmgenet_intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
+ bcmgenet_intr_disable(priv);
cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE;
dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__);
- /* Monitor cable plug/unpluged event for internal PHY */
- if (phy_is_internal(priv->phydev))
+ /* Monitor cable plug/unplugged event for internal PHY */
+ if (phy_is_internal(priv->phydev)) {
cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
- else if (priv->ext_phy)
+ } else if (priv->ext_phy) {
cpu_mask_clear |= (UMAC_IRQ_LINK_DOWN | UMAC_IRQ_LINK_UP);
- else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+ } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
reg = bcmgenet_bp_mc_get(priv);
reg |= BIT(priv->hw_params->bp_in_en_shift);
@@ -1532,8 +1556,7 @@ static int init_umac(struct bcmgenet_priv *priv)
if (priv->hw_params->flags & GENET_HAS_MDIO_INTR)
cpu_mask_clear |= UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR;
- bcmgenet_intrl2_0_writel(priv, cpu_mask_clear,
- INTRL2_CPU_MASK_CLEAR);
+ bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR);
/* Enable rx/tx engine.*/
dev_dbg(kdev, "done init umac\n");
@@ -1582,28 +1605,28 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
bcmgenet_tdma_ring_writel(priv, index, 1, DMA_MBUF_DONE_THRESH);
/* Disable rate control for now */
bcmgenet_tdma_ring_writel(priv, index, flow_period_val,
- TDMA_FLOW_PERIOD);
+ TDMA_FLOW_PERIOD);
/* Unclassified traffic goes to ring 16 */
bcmgenet_tdma_ring_writel(priv, index,
- ((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
- DMA_RING_BUF_SIZE);
+ ((size << DMA_RING_SIZE_SHIFT) |
+ RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
first_bd = write_ptr;
/* Set start and end address, read and write pointers */
bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
- DMA_START_ADDR);
+ DMA_START_ADDR);
bcmgenet_tdma_ring_writel(priv, index, first_bd * words_per_bd,
- TDMA_READ_PTR);
+ TDMA_READ_PTR);
bcmgenet_tdma_ring_writel(priv, index, first_bd,
- TDMA_WRITE_PTR);
+ TDMA_WRITE_PTR);
bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1,
- DMA_END_ADDR);
+ DMA_END_ADDR);
}
/* Initialize a RDMA ring */
static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
- unsigned int index, unsigned int size)
+ unsigned int index, unsigned int size)
{
u32 words_per_bd = WORDS_PER_BD(priv);
int ret;
@@ -1614,8 +1637,8 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
priv->rx_bd_assign_index = 0;
priv->rx_c_index = 0;
priv->rx_read_ptr = 0;
- priv->rx_cbs = kzalloc(priv->num_rx_bds * sizeof(struct enet_cb),
- GFP_KERNEL);
+ priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct enet_cb),
+ GFP_KERNEL);
if (!priv->rx_cbs)
return -ENOMEM;
@@ -1629,14 +1652,15 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_CONS_INDEX);
bcmgenet_rdma_ring_writel(priv, index,
- ((size << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH),
- DMA_RING_BUF_SIZE);
+ ((size << DMA_RING_SIZE_SHIFT) |
+ RX_BUF_LENGTH), DMA_RING_BUF_SIZE);
bcmgenet_rdma_ring_writel(priv, index, 0, DMA_START_ADDR);
bcmgenet_rdma_ring_writel(priv, index,
- words_per_bd * size - 1, DMA_END_ADDR);
+ words_per_bd * size - 1, DMA_END_ADDR);
bcmgenet_rdma_ring_writel(priv, index,
- (DMA_FC_THRESH_LO << DMA_XOFF_THRESHOLD_SHIFT) |
- DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
+ (DMA_FC_THRESH_LO <<
+ DMA_XOFF_THRESHOLD_SHIFT) |
+ DMA_FC_THRESH_HI, RDMA_XON_XOFF_THRESH);
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_READ_PTR);
return ret;
@@ -1683,10 +1707,10 @@ static void bcmgenet_init_multiq(struct net_device *dev)
* (ring 16)
*/
bcmgenet_init_tx_ring(priv, i, priv->hw_params->bds_cnt,
- i * priv->hw_params->bds_cnt,
- (i + 1) * priv->hw_params->bds_cnt);
+ i * priv->hw_params->bds_cnt,
+ (i + 1) * priv->hw_params->bds_cnt);
- /* Configure ring as decriptor ring and setup priority */
+ /* Configure ring as descriptor ring and setup priority */
ring_cfg |= 1 << i;
dma_priority |= ((GENET_Q0_PRIORITY + i) <<
(GENET_MAX_MQ_CNT + 1) * i);
@@ -1752,11 +1776,11 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
/* Init tDma */
bcmgenet_tdma_writel(priv, DMA_MAX_BURST_LENGTH, DMA_SCB_BURST_SIZE);
- /* Initialize commont TX ring structures */
+ /* Initialize common TX ring structures */
priv->tx_bds = priv->base + priv->hw_params->tdma_offset;
priv->num_tx_bds = TOTAL_DESC;
- priv->tx_cbs = kzalloc(priv->num_tx_bds * sizeof(struct enet_cb),
- GFP_KERNEL);
+ priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb),
+ GFP_KERNEL);
if (!priv->tx_cbs) {
bcmgenet_fini_dma(priv);
return -ENOMEM;
@@ -1767,8 +1791,9 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv)
/* initialize special ring 16 */
bcmgenet_init_tx_ring(priv, DESC_INDEX, GENET_DEFAULT_BD_CNT,
- priv->hw_params->tx_queues * priv->hw_params->bds_cnt,
- TOTAL_DESC);
+ priv->hw_params->tx_queues *
+ priv->hw_params->bds_cnt,
+ TOTAL_DESC);
return 0;
}
@@ -1789,11 +1814,11 @@ static int bcmgenet_poll(struct napi_struct *napi, int budget)
priv->rx_c_index += work_done;
priv->rx_c_index &= DMA_C_INDEX_MASK;
bcmgenet_rdma_ring_writel(priv, DESC_INDEX,
- priv->rx_c_index, RDMA_CONS_INDEX);
+ priv->rx_c_index, RDMA_CONS_INDEX);
if (work_done < budget) {
napi_complete(napi);
- bcmgenet_intrl2_0_writel(priv,
- UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_CLEAR);
+ bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
+ INTRL2_CPU_MASK_CLEAR);
}
return work_done;
@@ -1807,11 +1832,18 @@ static void bcmgenet_irq_task(struct work_struct *work)
netif_dbg(priv, intr, priv->dev, "%s\n", __func__);
+ if (priv->irq0_stat & UMAC_IRQ_MPD_R) {
+ priv->irq0_stat &= ~UMAC_IRQ_MPD_R;
+ netif_dbg(priv, wol, priv->dev,
+ "magic packet detected, waking up\n");
+ bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+ }
+
/* Link UP/DOWN event */
if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
- (priv->irq0_stat & (UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN))) {
+ (priv->irq0_stat & (UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN))) {
phy_mac_interrupt(priv->phydev,
- priv->irq0_stat & UMAC_IRQ_LINK_UP);
+ priv->irq0_stat & UMAC_IRQ_LINK_UP);
priv->irq0_stat &= ~(UMAC_IRQ_LINK_UP|UMAC_IRQ_LINK_DOWN);
}
}
@@ -1826,11 +1858,11 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
priv->irq1_stat =
bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) &
~priv->int1_mask;
- /* clear inerrupts*/
+ /* clear interrupts */
bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
netif_dbg(priv, intr, priv->dev,
- "%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
+ "%s: IRQ=0x%x\n", __func__, priv->irq1_stat);
/* Check the MBDONE interrupts.
* packet is done, reclaim descriptors
*/
@@ -1839,7 +1871,7 @@ static irqreturn_t bcmgenet_isr1(int irq, void *dev_id)
for (index = 0; index < 16; index++) {
if (priv->irq1_stat & (1 << index))
bcmgenet_tx_reclaim(priv->dev,
- &priv->tx_rings[index]);
+ &priv->tx_rings[index]);
}
}
return IRQ_HANDLED;
@@ -1854,11 +1886,11 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
priv->irq0_stat =
bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_STAT) &
~bcmgenet_intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
- /* clear inerrupts*/
+ /* clear interrupts */
bcmgenet_intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
netif_dbg(priv, intr, priv->dev,
- "IRQ=0x%x\n", priv->irq0_stat);
+ "IRQ=0x%x\n", priv->irq0_stat);
if (priv->irq0_stat & (UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_RXDMA_PDONE)) {
/* We use NAPI(software interrupt throttling, if
@@ -1866,8 +1898,8 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
* Disable interrupt, will be enabled in the poll method.
*/
if (likely(napi_schedule_prep(&priv->napi))) {
- bcmgenet_intrl2_0_writel(priv,
- UMAC_IRQ_RXDMA_BDONE, INTRL2_CPU_MASK_SET);
+ bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_BDONE,
+ INTRL2_CPU_MASK_SET);
__napi_schedule(&priv->napi);
}
}
@@ -1888,7 +1920,7 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
}
if ((priv->hw_params->flags & GENET_HAS_MDIO_INTR) &&
- priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
+ priv->irq0_stat & (UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR)) {
priv->irq0_stat &= ~(UMAC_IRQ_MDIO_DONE | UMAC_IRQ_MDIO_ERROR);
wake_up(&priv->wq);
}
@@ -1896,6 +1928,15 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t bcmgenet_wol_isr(int irq, void *dev_id)
+{
+ struct bcmgenet_priv *priv = dev_id;
+
+ pm_wakeup_event(&priv->pdev->dev, 0);
+
+ return IRQ_HANDLED;
+}
+
static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
{
u32 reg;
@@ -1911,7 +1952,7 @@ static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
}
static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
- unsigned char *addr)
+ unsigned char *addr)
{
bcmgenet_umac_writel(priv, (addr[0] << 24) | (addr[1] << 16) |
(addr[2] << 8) | addr[3], UMAC_MAC0);
@@ -1920,14 +1961,9 @@ static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
static int bcmgenet_wol_resume(struct bcmgenet_priv *priv)
{
- int ret;
-
/* From WOL-enabled suspend, switch to regular clock */
- clk_disable(priv->clk_wol);
- /* init umac registers to synchronize s/w with h/w */
- ret = init_umac(priv);
- if (ret)
- return ret;
+ if (priv->wolopts)
+ clk_disable_unprepare(priv->clk_wol);
phy_init_hw(priv->phydev);
/* Speed settings must be restored */
@@ -1972,6 +2008,23 @@ static void bcmgenet_enable_dma(struct bcmgenet_priv *priv, u32 dma_ctrl)
bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
}
+static void bcmgenet_netif_start(struct net_device *dev)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+
+ /* Start the network engine */
+ napi_enable(&priv->napi);
+
+ umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
+
+ if (phy_is_internal(priv->phydev))
+ bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
+
+ netif_tx_start_all_queues(dev);
+
+ phy_start(priv->phydev);
+}
+
static int bcmgenet_open(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -1993,18 +2046,14 @@ static int bcmgenet_open(struct net_device *dev)
goto err_clk_disable;
/* disable ethernet MAC while updating its registers */
+ umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
+
+ /* Make sure we reflect the value of CRC_CMD_FWD */
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
- reg &= ~(CMD_TX_EN | CMD_RX_EN);
- bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+ priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
bcmgenet_set_hw_addr(priv, dev->dev_addr);
- if (priv->wol_enabled) {
- ret = bcmgenet_wol_resume(priv);
- if (ret)
- return ret;
- }
-
if (phy_is_internal(priv->phydev)) {
reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
reg |= EXT_ENERGY_DET_MASK;
@@ -2025,37 +2074,20 @@ static int bcmgenet_open(struct net_device *dev)
bcmgenet_enable_dma(priv, dma_ctrl);
ret = request_irq(priv->irq0, bcmgenet_isr0, IRQF_SHARED,
- dev->name, priv);
+ dev->name, priv);
if (ret < 0) {
netdev_err(dev, "can't request IRQ %d\n", priv->irq0);
goto err_fini_dma;
}
ret = request_irq(priv->irq1, bcmgenet_isr1, IRQF_SHARED,
- dev->name, priv);
+ dev->name, priv);
if (ret < 0) {
netdev_err(dev, "can't request IRQ %d\n", priv->irq1);
goto err_irq0;
}
- /* Start the network engine */
- napi_enable(&priv->napi);
-
- reg = bcmgenet_umac_readl(priv, UMAC_CMD);
- reg |= (CMD_TX_EN | CMD_RX_EN);
- bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
- /* Make sure we reflect the value of CRC_CMD_FWD */
- priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
-
- device_set_wakeup_capable(&dev->dev, 1);
-
- if (phy_is_internal(priv->phydev))
- bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
-
- netif_tx_start_all_queues(dev);
-
- phy_start(priv->phydev);
+ bcmgenet_netif_start(dev);
return 0;
@@ -2090,8 +2122,7 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
}
if (timeout == DMA_TIMEOUT_VAL) {
- netdev_warn(priv->dev,
- "Timed out while disabling TX DMA\n");
+ netdev_warn(priv->dev, "Timed out while disabling TX DMA\n");
ret = -ETIMEDOUT;
}
@@ -2114,41 +2145,51 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv)
}
if (timeout == DMA_TIMEOUT_VAL) {
- netdev_warn(priv->dev,
- "Timed out while disabling RX DMA\n");
- ret = -ETIMEDOUT;
+ netdev_warn(priv->dev, "Timed out while disabling RX DMA\n");
+ ret = -ETIMEDOUT;
}
return ret;
}
+static void bcmgenet_netif_stop(struct net_device *dev)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+
+ netif_tx_stop_all_queues(dev);
+ napi_disable(&priv->napi);
+ phy_stop(priv->phydev);
+
+ bcmgenet_intr_disable(priv);
+
+ /* Wait for pending work items to complete. Since interrupts are
+ * disabled no new work will be scheduled.
+ */
+ cancel_work_sync(&priv->bcmgenet_irq_work);
+
+ priv->old_pause = -1;
+ priv->old_link = -1;
+ priv->old_duplex = -1;
+}
+
static int bcmgenet_close(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
int ret;
- u32 reg;
netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
- phy_stop(priv->phydev);
+ bcmgenet_netif_stop(dev);
/* Disable MAC receive */
- reg = bcmgenet_umac_readl(priv, UMAC_CMD);
- reg &= ~CMD_RX_EN;
- bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
- netif_tx_stop_all_queues(dev);
+ umac_enable_set(priv, CMD_RX_EN, false);
ret = bcmgenet_dma_teardown(priv);
if (ret)
return ret;
/* Disable MAC transmit. TX DMA disabled have to done before this */
- reg = bcmgenet_umac_readl(priv, UMAC_CMD);
- reg &= ~CMD_TX_EN;
- bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
- napi_disable(&priv->napi);
+ umac_enable_set(priv, CMD_TX_EN, false);
/* tx reclaim */
bcmgenet_tx_reclaim_all(dev);
@@ -2157,18 +2198,9 @@ static int bcmgenet_close(struct net_device *dev)
free_irq(priv->irq0, priv);
free_irq(priv->irq1, priv);
- /* Wait for pending work items to complete - we are stopping
- * the clock now. Since interrupts are disabled, no new work
- * will be scheduled.
- */
- cancel_work_sync(&priv->bcmgenet_irq_work);
-
if (phy_is_internal(priv->phydev))
bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
- if (priv->wol_enabled)
- clk_enable(priv->clk_wol);
-
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
@@ -2197,12 +2229,11 @@ static inline void bcmgenet_set_mdf_addr(struct bcmgenet_priv *priv,
{
u32 reg;
- bcmgenet_umac_writel(priv,
- addr[0] << 8 | addr[1], UMAC_MDF_ADDR + (*i * 4));
- bcmgenet_umac_writel(priv,
- addr[2] << 24 | addr[3] << 16 |
- addr[4] << 8 | addr[5],
- UMAC_MDF_ADDR + ((*i + 1) * 4));
+ bcmgenet_umac_writel(priv, addr[0] << 8 | addr[1],
+ UMAC_MDF_ADDR + (*i * 4));
+ bcmgenet_umac_writel(priv, addr[2] << 24 | addr[3] << 16 |
+ addr[4] << 8 | addr[5],
+ UMAC_MDF_ADDR + ((*i + 1) * 4));
reg = bcmgenet_umac_readl(priv, UMAC_MDF_CTRL);
reg |= (1 << (MAX_MC_COUNT - *mc));
bcmgenet_umac_writel(priv, reg, UMAC_MDF_CTRL);
@@ -2219,7 +2250,7 @@ static void bcmgenet_set_rx_mode(struct net_device *dev)
netif_dbg(priv, hw, dev, "%s: %08X\n", __func__, dev->flags);
- /* Promiscous mode */
+ /* Promiscuous mode */
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
if (dev->flags & IFF_PROMISC) {
reg |= CMD_PROMISC;
@@ -2399,7 +2430,7 @@ static void bcmgenet_set_hw_params(struct bcmgenet_priv *priv)
/* Print the GENET core version */
dev_info(&priv->pdev->dev, "GENET " GENET_VER_FMT,
- major, (reg >> 16) & 0x0f, reg & 0xffff);
+ major, (reg >> 16) & 0x0f, reg & 0xffff);
#ifdef CONFIG_PHYS_ADDR_T_64BIT
if (!(params->flags & GENET_HAS_40BITS))
@@ -2455,6 +2486,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->irq0 = platform_get_irq(pdev, 0);
priv->irq1 = platform_get_irq(pdev, 1);
+ priv->wol_irq = platform_get_irq(pdev, 2);
if (!priv->irq0 || !priv->irq1) {
dev_err(&pdev->dev, "can't find IRQs\n");
err = -EINVAL;
@@ -2489,6 +2521,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
+ /* Request the WOL interrupt and advertise suspend if available */
+ priv->wol_irq_disabled = true;
+ err = devm_request_irq(&pdev->dev, priv->wol_irq, bcmgenet_wol_isr, 0,
+ dev->name, priv);
+ if (!err)
+ device_set_wakeup_capable(&pdev->dev, 1);
+
/* Set the needed headroom to account for any possible
* features enabling/disabling at runtime
*/
@@ -2500,6 +2539,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv->pdev = pdev;
priv->version = (enum bcmgenet_version)of_id->data;
+ priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
+ if (IS_ERR(priv->clk))
+ dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
+
+ if (!IS_ERR(priv->clk))
+ clk_prepare_enable(priv->clk);
+
bcmgenet_set_hw_params(priv);
/* Mii wait queue */
@@ -2508,17 +2554,10 @@ static int bcmgenet_probe(struct platform_device *pdev)
priv->rx_buf_len = RX_BUF_LENGTH;
INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task);
- priv->clk = devm_clk_get(&priv->pdev->dev, "enet");
- if (IS_ERR(priv->clk))
- dev_warn(&priv->pdev->dev, "failed to get enet clock\n");
-
priv->clk_wol = devm_clk_get(&priv->pdev->dev, "enet-wol");
if (IS_ERR(priv->clk_wol))
dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
- if (!IS_ERR(priv->clk))
- clk_prepare_enable(priv->clk);
-
err = reset_umac(priv);
if (err)
goto err_clk_disable;
@@ -2566,6 +2605,116 @@ static int bcmgenet_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int bcmgenet_suspend(struct device *d)
+{
+ struct net_device *dev = dev_get_drvdata(d);
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ int ret;
+
+ if (!netif_running(dev))
+ return 0;
+
+ bcmgenet_netif_stop(dev);
+
+ phy_suspend(priv->phydev);
+
+ netif_device_detach(dev);
+
+ /* Disable MAC receive */
+ umac_enable_set(priv, CMD_RX_EN, false);
+
+ ret = bcmgenet_dma_teardown(priv);
+ if (ret)
+ return ret;
+
+ /* Disable MAC transmit. TX DMA disabled have to done before this */
+ umac_enable_set(priv, CMD_TX_EN, false);
+
+ /* tx reclaim */
+ bcmgenet_tx_reclaim_all(dev);
+ bcmgenet_fini_dma(priv);
+
+ /* Prepare the device for Wake-on-LAN and switch to the slow clock */
+ if (device_may_wakeup(d) && priv->wolopts) {
+ bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC);
+ clk_prepare_enable(priv->clk_wol);
+ }
+
+ /* Turn off the clocks */
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int bcmgenet_resume(struct device *d)
+{
+ struct net_device *dev = dev_get_drvdata(d);
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ unsigned long dma_ctrl;
+ int ret;
+ u32 reg;
+
+ if (!netif_running(dev))
+ return 0;
+
+ /* Turn on the clock */
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ bcmgenet_umac_reset(priv);
+
+ ret = init_umac(priv);
+ if (ret)
+ goto out_clk_disable;
+
+ ret = bcmgenet_wol_resume(priv);
+ if (ret)
+ goto out_clk_disable;
+
+ /* disable ethernet MAC while updating its registers */
+ umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
+
+ bcmgenet_set_hw_addr(priv, dev->dev_addr);
+
+ if (phy_is_internal(priv->phydev)) {
+ reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+ reg |= EXT_ENERGY_DET_MASK;
+ bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+ }
+
+ if (priv->wolopts)
+ bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
+
+ /* Disable RX/TX DMA and flush TX queues */
+ dma_ctrl = bcmgenet_dma_disable(priv);
+
+ /* Reinitialize TDMA and RDMA and SW housekeeping */
+ ret = bcmgenet_init_dma(priv);
+ if (ret) {
+ netdev_err(dev, "failed to initialize DMA\n");
+ goto out_clk_disable;
+ }
+
+ /* Always enable ring 16 - descriptor ring */
+ bcmgenet_enable_dma(priv, dma_ctrl);
+
+ netif_device_attach(dev);
+
+ phy_resume(priv->phydev);
+
+ bcmgenet_netif_start(dev);
+
+ return 0;
+
+out_clk_disable:
+ clk_disable_unprepare(priv->clk);
+ return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(bcmgenet_pm_ops, bcmgenet_suspend, bcmgenet_resume);
static struct platform_driver bcmgenet_driver = {
.probe = bcmgenet_probe,
@@ -2574,6 +2723,7 @@ static struct platform_driver bcmgenet_driver = {
.name = "bcmgenet",
.owner = THIS_MODULE,
.of_match_table = bcmgenet_match,
+ .pm = &bcmgenet_pm_ops,
},
};
module_platform_driver(bcmgenet_driver);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index e23c993b1362..c862d0666771 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -4,18 +4,8 @@
* 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.
- *
- *
-*/
+ */
+
#ifndef __BCMGENET_H__
#define __BCMGENET_H__
@@ -456,6 +446,7 @@ struct enet_cb {
enum bcmgenet_power_mode {
GENET_POWER_CABLE_SENSE = 0,
GENET_POWER_PASSIVE,
+ GENET_POWER_WOL_MAGIC,
};
struct bcmgenet_priv;
@@ -513,9 +504,9 @@ struct bcmgenet_tx_ring {
unsigned int cb_ptr; /* Tx ring initial CB ptr */
unsigned int end_ptr; /* Tx ring end CB ptr */
void (*int_enable)(struct bcmgenet_priv *priv,
- struct bcmgenet_tx_ring *);
+ struct bcmgenet_tx_ring *);
void (*int_disable)(struct bcmgenet_priv *priv,
- struct bcmgenet_tx_ring *);
+ struct bcmgenet_tx_ring *);
};
/* device context */
@@ -569,6 +560,8 @@ struct bcmgenet_priv {
int irq1;
unsigned int irq0_stat;
unsigned int irq1_stat;
+ int wol_irq;
+ bool wol_irq_disabled;
/* HW descriptors/checksum variables */
bool desc_64b_en;
@@ -583,7 +576,6 @@ struct bcmgenet_priv {
struct platform_device *pdev;
/* WOL */
- unsigned long wol_enabled;
struct clk *clk_wol;
u32 wolopts;
@@ -625,4 +617,12 @@ int bcmgenet_mii_config(struct net_device *dev);
void bcmgenet_mii_exit(struct net_device *dev);
void bcmgenet_mii_reset(struct net_device *dev);
+/* Wake-on-LAN routines */
+void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
+int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
+int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ enum bcmgenet_power_mode mode);
+void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
+ enum bcmgenet_power_mode mode);
+
#endif /* __BCMGENET_H__ */
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
new file mode 100644
index 000000000000..b82b7e4e06b2
--- /dev/null
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -0,0 +1,206 @@
+/*
+ * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
+ *
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "bcmgenet_wol: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/clk.h>
+#include <linux/version.h>
+#include <linux/platform_device.h>
+#include <net/arp.h>
+
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/phy.h>
+
+#include "bcmgenet.h"
+
+/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
+ * Detection is supported through ethtool
+ */
+void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ u32 reg;
+
+ wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
+ wol->wolopts = priv->wolopts;
+ memset(wol->sopass, 0, sizeof(wol->sopass));
+
+ if (wol->wolopts & WAKE_MAGICSECURE) {
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_MS);
+ put_unaligned_be16(reg, &wol->sopass[0]);
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_LS);
+ put_unaligned_be32(reg, &wol->sopass[2]);
+ }
+}
+
+/* ethtool function - set WOL (Wake on LAN) settings.
+ * Only for magic packet detection mode.
+ */
+int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+ struct device *kdev = &priv->pdev->dev;
+ u32 reg;
+
+ if (!device_can_wakeup(kdev))
+ return -ENOTSUPP;
+
+ if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE))
+ return -EINVAL;
+
+ if (wol->wolopts & WAKE_MAGICSECURE) {
+ bcmgenet_umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
+ UMAC_MPD_PW_MS);
+ bcmgenet_umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
+ UMAC_MPD_PW_LS);
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+ reg |= MPD_PW_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+ }
+
+ /* Flag the device and relevant IRQ as wakeup capable */
+ if (wol->wolopts) {
+ device_set_wakeup_enable(kdev, 1);
+ enable_irq_wake(priv->wol_irq);
+ priv->wol_irq_disabled = false;
+ } else {
+ device_set_wakeup_enable(kdev, 0);
+ /* Avoid unbalanced disable_irq_wake calls */
+ if (!priv->wol_irq_disabled)
+ disable_irq_wake(priv->wol_irq);
+ priv->wol_irq_disabled = true;
+ }
+
+ priv->wolopts = wol->wolopts;
+
+ return 0;
+}
+
+static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
+{
+ struct net_device *dev = priv->dev;
+ int retries = 0;
+
+ while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
+ & RBUF_STATUS_WOL)) {
+ retries++;
+ if (retries > 5) {
+ netdev_crit(dev, "polling wol mode timeout\n");
+ return -ETIMEDOUT;
+ }
+ mdelay(1);
+ }
+
+ return retries;
+}
+
+int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ enum bcmgenet_power_mode mode)
+{
+ struct net_device *dev = priv->dev;
+ u32 cpu_mask_clear;
+ int retries = 0;
+ u32 reg;
+
+ if (mode != GENET_POWER_WOL_MAGIC) {
+ netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ /* disable RX */
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ reg &= ~CMD_RX_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+ mdelay(10);
+
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+ reg |= MPD_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+ /* Do not leave UniMAC in MPD mode only */
+ retries = bcmgenet_poll_wol_status(priv);
+ if (retries < 0) {
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+ reg &= ~MPD_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+ return retries;
+ }
+
+ netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
+ retries);
+
+ /* Enable CRC forward */
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ priv->crc_fwd_en = 1;
+ reg |= CMD_CRC_FWD;
+
+ /* Receiver must be enabled for WOL MP detection */
+ reg |= CMD_RX_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
+ if (priv->hw_params->flags & GENET_HAS_EXT) {
+ reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
+ reg &= ~EXT_ENERGY_DET_MASK;
+ bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
+ }
+
+ /* Enable the MPD interrupt */
+ cpu_mask_clear = UMAC_IRQ_MPD_R;
+
+ bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR);
+
+ return 0;
+}
+
+void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
+ enum bcmgenet_power_mode mode)
+{
+ u32 cpu_mask_set;
+ u32 reg;
+
+ if (mode != GENET_POWER_WOL_MAGIC) {
+ netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
+ return;
+ }
+
+ reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
+ reg &= ~MPD_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+
+ /* Disable CRC Forward */
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ reg &= ~CMD_CRC_FWD;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+ priv->crc_fwd_en = 0;
+
+ /* Stop monitoring magic packet IRQ */
+ cpu_mask_set = UMAC_IRQ_MPD_R;
+
+ /* Stop monitoring magic packet IRQ */
+ bcmgenet_intrl2_0_writel(priv, cpu_mask_set, INTRL2_CPU_MASK_SET);
+}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index add8d8596084..c88f7ae99636 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -6,15 +6,6 @@
* 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.
*/
@@ -44,15 +35,15 @@ static int bcmgenet_mii_read(struct mii_bus *bus, int phy_id, int location)
u32 reg;
bcmgenet_umac_writel(priv, (MDIO_RD | (phy_id << MDIO_PMD_SHIFT) |
- (location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
+ (location << MDIO_REG_SHIFT)), UMAC_MDIO_CMD);
/* Start MDIO transaction*/
reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
reg |= MDIO_START_BUSY;
bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
wait_event_timeout(priv->wq,
- !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
- & MDIO_START_BUSY),
- HZ / 100);
+ !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
+ & MDIO_START_BUSY),
+ HZ / 100);
ret = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
if (ret & MDIO_READ_FAIL)
@@ -63,22 +54,22 @@ static int bcmgenet_mii_read(struct mii_bus *bus, int phy_id, int location)
/* write a value to the MII */
static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
- int location, u16 val)
+ int location, u16 val)
{
struct net_device *dev = bus->priv;
struct bcmgenet_priv *priv = netdev_priv(dev);
u32 reg;
bcmgenet_umac_writel(priv, (MDIO_WR | (phy_id << MDIO_PMD_SHIFT) |
- (location << MDIO_REG_SHIFT) | (0xffff & val)),
- UMAC_MDIO_CMD);
+ (location << MDIO_REG_SHIFT) | (0xffff & val)),
+ UMAC_MDIO_CMD);
reg = bcmgenet_umac_readl(priv, UMAC_MDIO_CMD);
reg |= MDIO_START_BUSY;
bcmgenet_umac_writel(priv, reg, UMAC_MDIO_CMD);
wait_event_timeout(priv->wq,
- !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
- MDIO_START_BUSY),
- HZ / 100);
+ !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD) &
+ MDIO_START_BUSY),
+ HZ / 100);
return 0;
}
@@ -136,17 +127,22 @@ static void bcmgenet_mii_setup(struct net_device *dev)
/* pause capability */
if (!phydev->pause)
cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
+ }
+ if (!status_changed)
+ return;
+
+ if (phydev->link) {
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
CMD_HD_EN |
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
reg |= cmd_bits;
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+
}
- if (status_changed)
- phy_print_status(phydev);
+ phy_print_status(phydev);
}
void bcmgenet_mii_reset(struct net_device *dev)
@@ -247,7 +243,7 @@ int bcmgenet_mii_config(struct net_device *dev)
phy_name = "external MII";
phydev->supported &= PHY_BASIC_FEATURES;
bcmgenet_sys_writel(priv,
- PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
+ PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
break;
case PHY_INTERFACE_MODE_REVMII:
@@ -283,7 +279,7 @@ int bcmgenet_mii_config(struct net_device *dev)
reg |= RGMII_MODE_EN | id_mode_dis;
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
bcmgenet_sys_writel(priv,
- PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
+ PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
break;
default:
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
@@ -311,12 +307,12 @@ static int bcmgenet_mii_probe(struct net_device *dev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(dn)) {
+ if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
ret = of_phy_register_fixed_link(dn);
if (ret)
return ret;
- priv->phy_dn = dn;
+ priv->phy_dn = of_node_get(dn);
}
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0,
@@ -362,7 +358,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
priv->mii_bus->irq[phydev->addr] = PHY_POLL;
pr_info("attached PHY at address %d [%s]\n",
- phydev->addr, phydev->drv->name);
+ phydev->addr, phydev->drv->name);
return 0;
}
@@ -387,9 +383,9 @@ static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
bus->read = bcmgenet_mii_read;
bus->write = bcmgenet_mii_write;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
- priv->pdev->name, priv->pdev->id);
+ priv->pdev->name, priv->pdev->id);
- bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
if (!bus->irq) {
mdiobus_free(priv->mii_bus);
return -ENOMEM;
@@ -452,6 +448,7 @@ int bcmgenet_mii_init(struct net_device *dev)
return 0;
out:
+ of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus);
out_free:
kfree(priv->mii_bus->irq);
@@ -463,6 +460,7 @@ void bcmgenet_mii_exit(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
+ of_node_put(priv->phy_dn);
mdiobus_unregister(priv->mii_bus);
kfree(priv->mii_bus->irq);
mdiobus_free(priv->mii_bus);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 8afa579e7c40..3ac5d23454a8 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -237,7 +237,7 @@ MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
#define TG3_DRV_DATA_FLAG_10_100_ONLY 0x0001
#define TG3_DRV_DATA_FLAG_5705_10_100 0x0002
-static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
+static const struct pci_device_id tg3_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
@@ -7830,17 +7830,18 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
-/* Use GSO to workaround a rare TSO bug that may be triggered when the
- * TSO header is greater than 80 bytes.
+/* Use GSO to workaround all TSO packets that meet HW bug conditions
+ * indicated in tg3_tx_frag_set()
*/
-static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
+static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi,
+ struct netdev_queue *txq, struct sk_buff *skb)
{
struct sk_buff *segs, *nskb;
u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
/* Estimate the number of fragments in the worst case */
- if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) {
- netif_stop_queue(tp->dev);
+ if (unlikely(tg3_tx_avail(tnapi) <= frag_cnt_est)) {
+ netif_tx_stop_queue(txq);
/* netif_tx_stop_queue() must be done before checking
* checking tx index in tg3_tx_avail() below, because in
@@ -7848,13 +7849,14 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
* netif_tx_queue_stopped().
*/
smp_mb();
- if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)
+ if (tg3_tx_avail(tnapi) <= frag_cnt_est)
return NETDEV_TX_BUSY;
- netif_wake_queue(tp->dev);
+ netif_tx_wake_queue(txq);
}
- segs = skb_gso_segment(skb, tp->dev->features & ~(NETIF_F_TSO | NETIF_F_TSO6));
+ segs = skb_gso_segment(skb, tp->dev->features &
+ ~(NETIF_F_TSO | NETIF_F_TSO6));
if (IS_ERR(segs) || !segs)
goto tg3_tso_bug_end;
@@ -7930,7 +7932,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!skb_is_gso_v6(skb)) {
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
tg3_flag(tp, TSO_BUG))
- return tg3_tso_bug(tp, skb);
+ return tg3_tso_bug(tp, tnapi, txq, skb);
ip_csum = iph->check;
ip_tot_len = iph->tot_len;
@@ -8061,7 +8063,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
iph->tot_len = ip_tot_len;
}
tcph->check = tcp_csum;
- return tg3_tso_bug(tp, skb);
+ return tg3_tso_bug(tp, tnapi, txq, skb);
}
/* If the workaround fails due to memory/mapping
@@ -14091,8 +14093,9 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
spin_lock_bh(&tp->lock);
if (!tp->hw_stats) {
+ *stats = tp->net_stats_prev;
spin_unlock_bh(&tp->lock);
- return &tp->net_stats_prev;
+ return stats;
}
tg3_get_nstats(tp, stats);
@@ -15924,7 +15927,7 @@ static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
return TG3_RX_RET_MAX_SIZE_5705;
}
-static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
+static const struct pci_device_id tg3_write_reorder_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) },
@@ -17183,7 +17186,7 @@ static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
#define TEST_BUFFER_SIZE 0x2000
-static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
+static const struct pci_device_id tg3_dma_wait_state_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
{ },
};
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 3a77f9ead004..ff8cae5e2535 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -600,9 +600,9 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
prefetch(bnad->netdev);
cq = ccb->sw_q;
- cmpl = &cq[ccb->producer_index];
while (packets < budget) {
+ cmpl = &cq[ccb->producer_index];
if (!cmpl->valid)
break;
/* The 'valid' field is set by the adapter, only after writing
@@ -3836,7 +3836,7 @@ bnad_pci_remove(struct pci_dev *pdev)
free_netdev(netdev);
}
-static DEFINE_PCI_DEVICE_TABLE(bnad_pci_id_table) = {
+static const struct pci_device_id bnad_pci_id_table[] = {
{
PCI_DEVICE(PCI_VENDOR_ID_BROCADE,
PCI_DEVICE_ID_BROCADE_CT),
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 882cad71ad62..d26adac6ab99 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -997,10 +997,8 @@ bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
unsigned long flags = 0;
int ret = 0;
- /* Check if the flash read request is valid */
- if (eeprom->magic != (bnad->pcidev->vendor |
- (bnad->pcidev->device << 16)))
- return -EFAULT;
+ /* Fill the magic value */
+ eeprom->magic = bnad->pcidev->vendor | (bnad->pcidev->device << 16);
/* Query the flash partition based on the offset */
flash_part = bnad_get_flash_partition_by_offset(bnad,
diff --git a/drivers/net/ethernet/brocade/bna/cna_fwimg.c b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
index 6a68e8d93309..6f72771caea6 100644
--- a/drivers/net/ethernet/brocade/bna/cna_fwimg.c
+++ b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
@@ -68,10 +68,8 @@ bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off)
switch (asic_gen) {
case BFI_ASIC_GEN_CT:
return (bfi_image_ct_cna + off);
- break;
case BFI_ASIC_GEN_CT2:
return (bfi_image_ct2_cna + off);
- break;
default:
return NULL;
}
@@ -83,10 +81,8 @@ bfa_cb_image_get_size(enum bfi_asic_gen asic_gen)
switch (asic_gen) {
case BFI_ASIC_GEN_CT:
return bfi_image_ct_cna_size;
- break;
case BFI_ASIC_GEN_CT2:
return bfi_image_ct2_cna_size;
- break;
default:
return 0;
}
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index e9daa072ebb4..ca5d7798b265 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -52,6 +52,9 @@
| MACB_BIT(TXERR))
#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
+#define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
+#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
+
/*
* Graceful stop timeouts in us. We should allow up to
* 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
@@ -264,7 +267,8 @@ static void macb_handle_link_change(struct net_device *dev)
reg |= MACB_BIT(FD);
if (phydev->speed == SPEED_100)
reg |= MACB_BIT(SPD);
- if (phydev->speed == SPEED_1000)
+ if (phydev->speed == SPEED_1000 &&
+ bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
reg |= GEM_BIT(GBE);
macb_or_gem_writel(bp, NCFGR, reg);
@@ -337,7 +341,7 @@ static int macb_mii_probe(struct net_device *dev)
}
/* mask with MAC supported features */
- if (macb_is_gem(bp))
+ if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
phydev->supported &= PHY_GBIT_FEATURES;
else
phydev->supported &= PHY_BASIC_FEATURES;
@@ -467,6 +471,24 @@ static int macb_halt_tx(struct macb *bp)
return -ETIMEDOUT;
}
+static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
+{
+ if (tx_skb->mapping) {
+ if (tx_skb->mapped_as_page)
+ dma_unmap_page(&bp->pdev->dev, tx_skb->mapping,
+ tx_skb->size, DMA_TO_DEVICE);
+ else
+ dma_unmap_single(&bp->pdev->dev, tx_skb->mapping,
+ tx_skb->size, DMA_TO_DEVICE);
+ tx_skb->mapping = 0;
+ }
+
+ if (tx_skb->skb) {
+ dev_kfree_skb_any(tx_skb->skb);
+ tx_skb->skb = NULL;
+ }
+}
+
static void macb_tx_error_task(struct work_struct *work)
{
struct macb *bp = container_of(work, struct macb, tx_error_task);
@@ -504,10 +526,23 @@ static void macb_tx_error_task(struct work_struct *work)
skb = tx_skb->skb;
if (ctrl & MACB_BIT(TX_USED)) {
- netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
- bp->stats.tx_packets++;
- bp->stats.tx_bytes += skb->len;
+ /* skb is set for the last buffer of the frame */
+ while (!skb) {
+ macb_tx_unmap(bp, tx_skb);
+ tail++;
+ tx_skb = macb_tx_skb(bp, tail);
+ skb = tx_skb->skb;
+ }
+
+ /* ctrl still refers to the first buffer descriptor
+ * since it's the only one written back by the hardware
+ */
+ if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
+ netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
+ macb_tx_ring_wrap(tail), skb->data);
+ bp->stats.tx_packets++;
+ bp->stats.tx_bytes += skb->len;
+ }
} else {
/*
* "Buffers exhausted mid-frame" errors may only happen
@@ -521,10 +556,7 @@ static void macb_tx_error_task(struct work_struct *work)
desc->ctrl = ctrl | MACB_BIT(TX_USED);
}
- dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
- DMA_TO_DEVICE);
- tx_skb->skb = NULL;
- dev_kfree_skb(skb);
+ macb_tx_unmap(bp, tx_skb);
}
/* Make descriptor updates visible to hardware */
@@ -572,20 +604,35 @@ static void macb_tx_interrupt(struct macb *bp)
ctrl = desc->ctrl;
+ /* TX_USED bit is only set by hardware on the very first buffer
+ * descriptor of the transmitted frame.
+ */
if (!(ctrl & MACB_BIT(TX_USED)))
break;
- tx_skb = macb_tx_skb(bp, tail);
- skb = tx_skb->skb;
+ /* Process all buffers of the current transmitted frame */
+ for (;; tail++) {
+ tx_skb = macb_tx_skb(bp, tail);
+ skb = tx_skb->skb;
+
+ /* First, update TX stats if needed */
+ if (skb) {
+ netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
+ macb_tx_ring_wrap(tail), skb->data);
+ bp->stats.tx_packets++;
+ bp->stats.tx_bytes += skb->len;
+ }
- netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
- macb_tx_ring_wrap(tail), skb->data);
- dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
- DMA_TO_DEVICE);
- bp->stats.tx_packets++;
- bp->stats.tx_bytes += skb->len;
- tx_skb->skb = NULL;
- dev_kfree_skb_irq(skb);
+ /* Now we can safely release resources */
+ macb_tx_unmap(bp, tx_skb);
+
+ /* skb is set only for the last buffer of the frame.
+ * WARNING: at this point skb has been freed by
+ * macb_tx_unmap().
+ */
+ if (skb)
+ break;
+ }
}
bp->tx_tail = tail;
@@ -718,6 +765,10 @@ static int gem_rx(struct macb *bp, int budget)
skb->protocol = eth_type_trans(skb, bp->dev);
skb_checksum_none_assert(skb);
+ if (bp->dev->features & NETIF_F_RXCSUM &&
+ !(bp->dev->flags & IFF_PROMISC) &&
+ GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
bp->stats.rx_packets++;
bp->stats.rx_bytes += skb->len;
@@ -1001,15 +1052,145 @@ static void macb_poll_controller(struct net_device *dev)
}
#endif
-static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static inline unsigned int macb_count_tx_descriptors(struct macb *bp,
+ unsigned int len)
+{
+ return (len + bp->max_tx_length - 1) / bp->max_tx_length;
+}
+
+static unsigned int macb_tx_map(struct macb *bp,
+ struct sk_buff *skb)
{
- struct macb *bp = netdev_priv(dev);
dma_addr_t mapping;
- unsigned int len, entry;
+ unsigned int len, entry, i, tx_head = bp->tx_head;
+ struct macb_tx_skb *tx_skb = NULL;
struct macb_dma_desc *desc;
- struct macb_tx_skb *tx_skb;
+ unsigned int offset, size, count = 0;
+ unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
+ unsigned int eof = 1;
u32 ctrl;
+
+ /* First, map non-paged data */
+ len = skb_headlen(skb);
+ offset = 0;
+ while (len) {
+ size = min(len, bp->max_tx_length);
+ entry = macb_tx_ring_wrap(tx_head);
+ tx_skb = &bp->tx_skb[entry];
+
+ mapping = dma_map_single(&bp->pdev->dev,
+ skb->data + offset,
+ size, DMA_TO_DEVICE);
+ if (dma_mapping_error(&bp->pdev->dev, mapping))
+ goto dma_error;
+
+ /* Save info to properly release resources */
+ tx_skb->skb = NULL;
+ tx_skb->mapping = mapping;
+ tx_skb->size = size;
+ tx_skb->mapped_as_page = false;
+
+ len -= size;
+ offset += size;
+ count++;
+ tx_head++;
+ }
+
+ /* Then, map paged data from fragments */
+ for (f = 0; f < nr_frags; f++) {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+ len = skb_frag_size(frag);
+ offset = 0;
+ while (len) {
+ size = min(len, bp->max_tx_length);
+ entry = macb_tx_ring_wrap(tx_head);
+ tx_skb = &bp->tx_skb[entry];
+
+ mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
+ offset, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(&bp->pdev->dev, mapping))
+ goto dma_error;
+
+ /* Save info to properly release resources */
+ tx_skb->skb = NULL;
+ tx_skb->mapping = mapping;
+ tx_skb->size = size;
+ tx_skb->mapped_as_page = true;
+
+ len -= size;
+ offset += size;
+ count++;
+ tx_head++;
+ }
+ }
+
+ /* Should never happen */
+ if (unlikely(tx_skb == NULL)) {
+ netdev_err(bp->dev, "BUG! empty skb!\n");
+ return 0;
+ }
+
+ /* This is the last buffer of the frame: save socket buffer */
+ tx_skb->skb = skb;
+
+ /* Update TX ring: update buffer descriptors in reverse order
+ * to avoid race condition
+ */
+
+ /* Set 'TX_USED' bit in buffer descriptor at tx_head position
+ * to set the end of TX queue
+ */
+ i = tx_head;
+ entry = macb_tx_ring_wrap(i);
+ ctrl = MACB_BIT(TX_USED);
+ desc = &bp->tx_ring[entry];
+ desc->ctrl = ctrl;
+
+ do {
+ i--;
+ entry = macb_tx_ring_wrap(i);
+ tx_skb = &bp->tx_skb[entry];
+ desc = &bp->tx_ring[entry];
+
+ ctrl = (u32)tx_skb->size;
+ if (eof) {
+ ctrl |= MACB_BIT(TX_LAST);
+ eof = 0;
+ }
+ if (unlikely(entry == (TX_RING_SIZE - 1)))
+ ctrl |= MACB_BIT(TX_WRAP);
+
+ /* Set TX buffer descriptor */
+ desc->addr = tx_skb->mapping;
+ /* desc->addr must be visible to hardware before clearing
+ * 'TX_USED' bit in desc->ctrl.
+ */
+ wmb();
+ desc->ctrl = ctrl;
+ } while (i != bp->tx_head);
+
+ bp->tx_head = tx_head;
+
+ return count;
+
+dma_error:
+ netdev_err(bp->dev, "TX DMA map failed\n");
+
+ for (i = bp->tx_head; i != tx_head; i++) {
+ tx_skb = macb_tx_skb(bp, i);
+
+ macb_tx_unmap(bp, tx_skb);
+ }
+
+ return 0;
+}
+
+static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct macb *bp = netdev_priv(dev);
unsigned long flags;
+ unsigned int count, nr_frags, frag_size, f;
#if defined(DEBUG) && defined(VERBOSE_DEBUG)
netdev_vdbg(bp->dev,
@@ -1020,44 +1201,34 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->data, 16, true);
#endif
- len = skb->len;
+ /* Count how many TX buffer descriptors are needed to send this
+ * socket buffer: skb fragments of jumbo frames may need to be
+ * splitted into many buffer descriptors.
+ */
+ count = macb_count_tx_descriptors(bp, skb_headlen(skb));
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ for (f = 0; f < nr_frags; f++) {
+ frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
+ count += macb_count_tx_descriptors(bp, frag_size);
+ }
+
spin_lock_irqsave(&bp->lock, flags);
/* This is a hard error, log it. */
- if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
+ if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < count) {
netif_stop_queue(dev);
spin_unlock_irqrestore(&bp->lock, flags);
- netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
bp->tx_head, bp->tx_tail);
return NETDEV_TX_BUSY;
}
- entry = macb_tx_ring_wrap(bp->tx_head);
- netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
- mapping = dma_map_single(&bp->pdev->dev, skb->data,
- len, DMA_TO_DEVICE);
- if (dma_mapping_error(&bp->pdev->dev, mapping)) {
+ /* Map socket buffer for DMA transfer */
+ if (!macb_tx_map(bp, skb)) {
dev_kfree_skb_any(skb);
goto unlock;
}
- bp->tx_head++;
- tx_skb = &bp->tx_skb[entry];
- tx_skb->skb = skb;
- tx_skb->mapping = mapping;
- netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
- skb->data, (unsigned long)mapping);
-
- ctrl = MACB_BF(TX_FRMLEN, len);
- ctrl |= MACB_BIT(TX_LAST);
- if (entry == (TX_RING_SIZE - 1))
- ctrl |= MACB_BIT(TX_WRAP);
-
- desc = &bp->tx_ring[entry];
- desc->addr = mapping;
- desc->ctrl = ctrl;
-
/* Make newly initialized descriptor visible to hardware */
wmb();
@@ -1342,7 +1513,7 @@ static u32 macb_dbw(struct macb *bp)
/*
* Configure the receive DMA engine
* - use the correct receive buffer size
- * - set the possibility to use INCR16 bursts
+ * - set best burst length for DMA operations
* (if not supported by FIFO, it will fallback to default)
* - set both rx/tx packet buffers to full memory size
* These are configurable parameters for GEM.
@@ -1354,24 +1525,20 @@ static void macb_configure_dma(struct macb *bp)
if (macb_is_gem(bp)) {
dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
- dmacfg |= GEM_BF(FBLDO, 16);
+ if (bp->dma_burst_length)
+ dmacfg = GEM_BFINS(FBLDO, bp->dma_burst_length, dmacfg);
dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
dmacfg &= ~GEM_BIT(ENDIA);
+ if (bp->dev->features & NETIF_F_HW_CSUM)
+ dmacfg |= GEM_BIT(TXCOEN);
+ else
+ dmacfg &= ~GEM_BIT(TXCOEN);
+ netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
+ dmacfg);
gem_writel(bp, DMACFG, dmacfg);
}
}
-/*
- * Configure peripheral capacities according to integration options used
- */
-static void macb_configure_caps(struct macb *bp)
-{
- if (macb_is_gem(bp)) {
- if (GEM_BFEXT(IRQCOR, gem_readl(bp, DCFG1)) == 0)
- bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
- }
-}
-
static void macb_init_hw(struct macb *bp)
{
u32 config;
@@ -1386,6 +1553,8 @@ static void macb_init_hw(struct macb *bp)
config |= MACB_BIT(BIG); /* Receive oversized frames */
if (bp->dev->flags & IFF_PROMISC)
config |= MACB_BIT(CAF); /* Copy All Frames */
+ else if (macb_is_gem(bp) && bp->dev->features & NETIF_F_RXCSUM)
+ config |= GEM_BIT(RXCOEN);
if (!(bp->dev->flags & IFF_BROADCAST))
config |= MACB_BIT(NBC); /* No BroadCast */
config |= macb_dbw(bp);
@@ -1394,7 +1563,6 @@ static void macb_init_hw(struct macb *bp)
bp->duplex = DUPLEX_HALF;
macb_configure_dma(bp);
- macb_configure_caps(bp);
/* Initialize TX and RX buffers */
macb_writel(bp, RBQP, bp->rx_ring_dma);
@@ -1500,13 +1668,22 @@ void macb_set_rx_mode(struct net_device *dev)
cfg = macb_readl(bp, NCFGR);
- if (dev->flags & IFF_PROMISC)
+ if (dev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
cfg |= MACB_BIT(CAF);
- else if (dev->flags & (~IFF_PROMISC))
- /* Disable promiscuous mode */
+
+ /* Disable RX checksum offload */
+ if (macb_is_gem(bp))
+ cfg &= ~GEM_BIT(RXCOEN);
+ } else {
+ /* Disable promiscuous mode */
cfg &= ~MACB_BIT(CAF);
+ /* Enable RX checksum offload only if requested */
+ if (macb_is_gem(bp) && dev->features & NETIF_F_RXCSUM)
+ cfg |= GEM_BIT(RXCOEN);
+ }
+
if (dev->flags & IFF_ALLMULTI) {
/* Enable all multicast mode */
macb_or_gem_writel(bp, HRB, -1);
@@ -1767,6 +1944,40 @@ int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
EXPORT_SYMBOL_GPL(macb_ioctl);
+static int macb_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct macb *bp = netdev_priv(netdev);
+ netdev_features_t changed = features ^ netdev->features;
+
+ /* TX checksum offload */
+ if ((changed & NETIF_F_HW_CSUM) && macb_is_gem(bp)) {
+ u32 dmacfg;
+
+ dmacfg = gem_readl(bp, DMACFG);
+ if (features & NETIF_F_HW_CSUM)
+ dmacfg |= GEM_BIT(TXCOEN);
+ else
+ dmacfg &= ~GEM_BIT(TXCOEN);
+ gem_writel(bp, DMACFG, dmacfg);
+ }
+
+ /* RX checksum offload */
+ if ((changed & NETIF_F_RXCSUM) && macb_is_gem(bp)) {
+ u32 netcfg;
+
+ netcfg = gem_readl(bp, NCFGR);
+ if (features & NETIF_F_RXCSUM &&
+ !(netdev->flags & IFF_PROMISC))
+ netcfg |= GEM_BIT(RXCOEN);
+ else
+ netcfg &= ~GEM_BIT(RXCOEN);
+ gem_writel(bp, NCFGR, netcfg);
+ }
+
+ return 0;
+}
+
static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
.ndo_stop = macb_close,
@@ -1780,20 +1991,77 @@ static const struct net_device_ops macb_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = macb_poll_controller,
#endif
+ .ndo_set_features = macb_set_features,
};
#if defined(CONFIG_OF)
+static struct macb_config pc302gem_config = {
+ .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+ .dma_burst_length = 16,
+};
+
+static struct macb_config sama5d3_config = {
+ .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+ .dma_burst_length = 16,
+};
+
+static struct macb_config sama5d4_config = {
+ .caps = 0,
+ .dma_burst_length = 4,
+};
+
static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,at32ap7000-macb" },
{ .compatible = "cdns,at91sam9260-macb" },
{ .compatible = "cdns,macb" },
- { .compatible = "cdns,pc302-gem" },
- { .compatible = "cdns,gem" },
+ { .compatible = "cdns,pc302-gem", .data = &pc302gem_config },
+ { .compatible = "cdns,gem", .data = &pc302gem_config },
+ { .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config },
+ { .compatible = "atmel,sama5d4-gem", .data = &sama5d4_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
#endif
+/*
+ * Configure peripheral capacities according to device tree
+ * and integration options used
+ */
+static void macb_configure_caps(struct macb *bp)
+{
+ u32 dcfg;
+ const struct of_device_id *match;
+ const struct macb_config *config;
+
+ if (bp->pdev->dev.of_node) {
+ match = of_match_node(macb_dt_ids, bp->pdev->dev.of_node);
+ if (match && match->data) {
+ config = (const struct macb_config *)match->data;
+
+ bp->caps = config->caps;
+ /*
+ * As we have access to the matching node, configure
+ * DMA burst length as well
+ */
+ bp->dma_burst_length = config->dma_burst_length;
+ }
+ }
+
+ if (MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2)
+ bp->caps |= MACB_CAPS_MACB_IS_GEM;
+
+ if (macb_is_gem(bp)) {
+ dcfg = gem_readl(bp, DCFG1);
+ if (GEM_BFEXT(IRQCOR, dcfg) == 0)
+ bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+ dcfg = gem_readl(bp, DCFG2);
+ if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
+ bp->caps |= MACB_CAPS_FIFO_MODE;
+ }
+
+ netdev_dbg(bp->dev, "Cadence caps 0x%08x\n", bp->caps);
+}
+
static int __init macb_probe(struct platform_device *pdev)
{
struct macb_platform_data *pdata;
@@ -1828,9 +2096,6 @@ static int __init macb_probe(struct platform_device *pdev)
SET_NETDEV_DEV(dev, &pdev->dev);
- /* TODO: Actually, we have some interesting features... */
- dev->features |= 0;
-
bp = netdev_priv(dev);
bp->pdev = pdev;
bp->dev = dev;
@@ -1897,19 +2162,33 @@ static int __init macb_probe(struct platform_device *pdev)
dev->base_addr = regs->start;
+ /* setup capacities */
+ macb_configure_caps(bp);
+
/* setup appropriated routines according to adapter type */
if (macb_is_gem(bp)) {
+ bp->max_tx_length = GEM_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = gem_init_rings;
bp->macbgem_ops.mog_rx = gem_rx;
} else {
+ bp->max_tx_length = MACB_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = macb_init_rings;
bp->macbgem_ops.mog_rx = macb_rx;
}
+ /* Set features */
+ dev->hw_features = NETIF_F_SG;
+ /* Checksum offload is only available on gem with packet buffer */
+ if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
+ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+ if (bp->caps & MACB_CAPS_SG_DISABLED)
+ dev->hw_features &= ~NETIF_F_SG;
+ dev->features = dev->hw_features;
+
/* Set MII management clock divider */
config = macb_mdc_clk_div(bp);
config |= macb_dbw(bp);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 51c02442160a..517c09d72c4a 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -164,6 +164,8 @@
#define GEM_CLK_SIZE 3
#define GEM_DBW_OFFSET 21
#define GEM_DBW_SIZE 2
+#define GEM_RXCOEN_OFFSET 24
+#define GEM_RXCOEN_SIZE 1
/* Constants for data bus width. */
#define GEM_DBW32 0
@@ -305,6 +307,12 @@
#define GEM_DBWDEF_OFFSET 25
#define GEM_DBWDEF_SIZE 3
+/* Bitfields in DCFG2. */
+#define GEM_RX_PKT_BUFF_OFFSET 20
+#define GEM_RX_PKT_BUFF_SIZE 1
+#define GEM_TX_PKT_BUFF_OFFSET 21
+#define GEM_TX_PKT_BUFF_SIZE 1
+
/* Constants for CLK */
#define MACB_CLK_DIV8 0
#define MACB_CLK_DIV16 1
@@ -326,7 +334,11 @@
#define MACB_MAN_CODE 2
/* Capability mask bits */
-#define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x1
+#define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001
+#define MACB_CAPS_FIFO_MODE 0x10000000
+#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
+#define MACB_CAPS_SG_DISABLED 0x40000000
+#define MACB_CAPS_MACB_IS_GEM 0x80000000
/* Bit manipulation macros */
#define MACB_BIT(name) \
@@ -442,6 +454,14 @@ struct macb_dma_desc {
#define MACB_RX_BROADCAST_OFFSET 31
#define MACB_RX_BROADCAST_SIZE 1
+/* RX checksum offload disabled: bit 24 clear in NCFGR */
+#define GEM_RX_TYPEID_MATCH_OFFSET 22
+#define GEM_RX_TYPEID_MATCH_SIZE 2
+
+/* RX checksum offload enabled: bit 24 set in NCFGR */
+#define GEM_RX_CSUM_OFFSET 22
+#define GEM_RX_CSUM_SIZE 2
+
#define MACB_TX_FRMLEN_OFFSET 0
#define MACB_TX_FRMLEN_SIZE 11
#define MACB_TX_LAST_OFFSET 15
@@ -459,14 +479,32 @@ struct macb_dma_desc {
#define MACB_TX_USED_OFFSET 31
#define MACB_TX_USED_SIZE 1
+#define GEM_TX_FRMLEN_OFFSET 0
+#define GEM_TX_FRMLEN_SIZE 14
+
+/* Buffer descriptor constants */
+#define GEM_RX_CSUM_NONE 0
+#define GEM_RX_CSUM_IP_ONLY 1
+#define GEM_RX_CSUM_IP_TCP 2
+#define GEM_RX_CSUM_IP_UDP 3
+
+/* limit RX checksum offload to TCP and UDP packets */
+#define GEM_RX_CSUM_CHECKED_MASK 2
+
/**
* struct macb_tx_skb - data about an skb which is being transmitted
- * @skb: skb currently being transmitted
- * @mapping: DMA address of the skb's data buffer
+ * @skb: skb currently being transmitted, only set for the last buffer
+ * of the frame
+ * @mapping: DMA address of the skb's fragment buffer
+ * @size: size of the DMA mapped buffer
+ * @mapped_as_page: true when buffer was mapped with skb_frag_dma_map(),
+ * false when buffer was mapped with dma_map_single()
*/
struct macb_tx_skb {
struct sk_buff *skb;
dma_addr_t mapping;
+ size_t size;
+ bool mapped_as_page;
};
/*
@@ -554,6 +592,11 @@ struct macb_or_gem_ops {
int (*mog_rx)(struct macb *bp, int budget);
};
+struct macb_config {
+ u32 caps;
+ unsigned int dma_burst_length;
+};
+
struct macb {
void __iomem *regs;
@@ -595,6 +638,7 @@ struct macb {
unsigned int duplex;
u32 caps;
+ unsigned int dma_burst_length;
phy_interface_t phy_interface;
@@ -602,6 +646,7 @@ struct macb {
struct sk_buff *skb; /* holds skb until xmit interrupt completes */
dma_addr_t skb_physaddr; /* phys addr from pci_map_single */
int skb_length; /* saved skb length for pci_unmap_single */
+ unsigned int max_tx_length;
};
extern const struct ethtool_ops macb_ethtool_ops;
@@ -615,7 +660,7 @@ void macb_get_hwaddr(struct macb *bp);
static inline bool macb_is_gem(struct macb *bp)
{
- return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
+ return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
}
#endif /* _MACB_H */
diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig
index 570222c33410..c3ce9df0041a 100644
--- a/drivers/net/ethernet/chelsio/Kconfig
+++ b/drivers/net/ethernet/chelsio/Kconfig
@@ -86,6 +86,17 @@ config CHELSIO_T4
To compile this driver as a module choose M here; the module
will be called cxgb4.
+config CHELSIO_T4_DCB
+ bool "Data Center Bridging (DCB) Support for Chelsio T4/T5 cards"
+ default n
+ depends on CHELSIO_T4 && DCB
+ ---help---
+ Enable DCB support through rtNetlink interface.
+ Say Y here if you want to enable Data Center Bridging (DCB) support
+ in the driver.
+
+ If unsure, say N.
+
config CHELSIO_T4VF
tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support"
depends on PCI
diff --git a/drivers/net/ethernet/chelsio/cxgb/subr.c b/drivers/net/ethernet/chelsio/cxgb/subr.c
index 816719314cc8..ea0f8741d7cf 100644
--- a/drivers/net/ethernet/chelsio/cxgb/subr.c
+++ b/drivers/net/ethernet/chelsio/cxgb/subr.c
@@ -522,7 +522,7 @@ static const struct board_info t1_board[] = {
};
-DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = {
+const struct pci_device_id t1_pci_tbl[] = {
CH_DEVICE(8, 0, CH_BRD_T110_1CU),
CH_DEVICE(8, 1, CH_BRD_T110_1CU),
CH_DEVICE(7, 0, CH_BRD_N110_1F),
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 5d9cce053cc9..db76f7040455 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -85,7 +85,7 @@ enum {
#define CH_DEVICE(devid, idx) \
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
-static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = {
+static const struct pci_device_id cxgb3_pci_tbl[] = {
CH_DEVICE(0x20, 0), /* PE9000 */
CH_DEVICE(0x21, 1), /* T302E */
CH_DEVICE(0x22, 2), /* T310E */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index 498667487f52..1df65c915b99 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o
+cxgb4-$(CONFIG_CHELSIO_T4_DCB) += cxgb4_dcb.o
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index f503dce4ab17..d57282172ea5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -50,13 +50,13 @@
#include "cxgb4_uld.h"
#define T4FW_VERSION_MAJOR 0x01
-#define T4FW_VERSION_MINOR 0x09
-#define T4FW_VERSION_MICRO 0x17
+#define T4FW_VERSION_MINOR 0x0B
+#define T4FW_VERSION_MICRO 0x1B
#define T4FW_VERSION_BUILD 0x00
#define T5FW_VERSION_MAJOR 0x01
-#define T5FW_VERSION_MINOR 0x09
-#define T5FW_VERSION_MICRO 0x17
+#define T5FW_VERSION_MINOR 0x0B
+#define T5FW_VERSION_MICRO 0x1B
#define T5FW_VERSION_BUILD 0x00
#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@ -85,7 +85,8 @@ enum {
MEMWIN1_BASE_T5 = 0x52000,
MEMWIN2_APERTURE = 65536,
MEMWIN2_BASE = 0x30000,
- MEMWIN2_BASE_T5 = 0x54000,
+ MEMWIN2_APERTURE_T5 = 131072,
+ MEMWIN2_BASE_T5 = 0x60000,
};
enum dev_master {
@@ -309,6 +310,9 @@ struct adapter_params {
unsigned int ofldq_wr_cred;
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
+
+ unsigned int max_ordird_qp; /* Max read depth per RDMA QP */
+ unsigned int max_ird_adapter; /* Max read depth per adapter */
};
#include "t4fw_api.h"
@@ -373,6 +377,8 @@ enum {
struct adapter;
struct sge_rspq;
+#include "cxgb4_dcb.h"
+
struct port_info {
struct adapter *adapter;
u16 viid;
@@ -389,6 +395,9 @@ struct port_info {
u8 rss_mode;
struct link_config link_cfg;
u16 *rss;
+#ifdef CONFIG_CHELSIO_T4_DCB
+ struct port_dcb_info dcb; /* Data Center Bridging support */
+#endif
};
struct dentry;
@@ -513,6 +522,9 @@ struct sge_txq {
struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
struct sge_txq q;
struct netdev_queue *txq; /* associated netdev TX queue */
+#ifdef CONFIG_CHELSIO_T4_DCB
+ u8 dcb_prio; /* DCB Priority bound to queue */
+#endif
unsigned long tso; /* # of TSO requests */
unsigned long tx_cso; /* # of Tx checksum offloads */
unsigned long vlan_ins; /* # of Tx VLAN insertions */
@@ -603,6 +615,7 @@ struct l2t_data;
struct adapter {
void __iomem *regs;
void __iomem *bar2;
+ u32 t4_bar0;
struct pci_dev *pdev;
struct device *pdev_dev;
unsigned int mbox;
@@ -647,6 +660,7 @@ struct adapter {
struct dentry *debugfs_root;
spinlock_t stats_lock;
+ spinlock_t win0_lock ____cacheline_aligned_in_smp;
};
/* Defined bit width of user definable filter tuples
@@ -855,6 +869,7 @@ void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
void *t4_alloc_mem(size_t size);
void t4_free_sge_resources(struct adapter *adap);
+void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q);
irq_handler_t t4_intr_handler(struct adapter *adap);
netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev);
int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
@@ -941,6 +956,7 @@ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
void t4_read_indirect(struct adapter *adap, unsigned int addr_reg,
unsigned int data_reg, u32 *vals, unsigned int nregs,
unsigned int start_idx);
+void t4_hw_pci_read_cfg4(struct adapter *adapter, int reg, u32 *val);
struct fw_filter_wr;
@@ -952,8 +968,17 @@ int t4_wait_dev_ready(struct adapter *adap);
int t4_link_start(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc);
int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
-int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
- __be32 *buf);
+
+#define T4_MEMORY_WRITE 0
+#define T4_MEMORY_READ 1
+int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr, u32 len,
+ __be32 *buf, int dir);
+static inline int t4_memory_write(struct adapter *adap, int mtype, u32 addr,
+ u32 len, __be32 *buf)
+{
+ return t4_memory_rw(adap, 0, mtype, addr, len, buf, 0);
+}
+
int t4_seeprom_wp(struct adapter *adapter, bool enable);
int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
@@ -1007,6 +1032,10 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int nparams, const u32 *params,
const u32 *val);
+int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
+ unsigned int pf, unsigned int vf,
+ unsigned int nparams, const u32 *params,
+ const u32 *val);
int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
unsigned int rxqi, unsigned int rxq, unsigned int tc,
@@ -1025,6 +1054,8 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
int idx, const u8 *addr, bool persist, bool add_smt);
int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool ucast, u64 vec, bool sleep_ok);
+int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
+ unsigned int viid, bool rx_en, bool tx_en, bool dcb_en);
int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool rx_en, bool tx_en);
int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
@@ -1045,7 +1076,6 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
void t4_db_full(struct adapter *adapter);
void t4_db_dropped(struct adapter *adapter);
-int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
u32 addr, u32 val);
void t4_sge_decode_idma_state(struct adapter *adapter, int state);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
new file mode 100644
index 000000000000..8edf0f5bd679
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
@@ -0,0 +1,1091 @@
+/*
+ * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved.
+ *
+ * Written by Anish Bhatt (anish@chelsio.com)
+ * Casey Leedom (leedom@chelsio.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#include "cxgb4.h"
+
+/* DCBx version control
+ */
+char *dcb_ver_array[] = {
+ "Unknown",
+ "DCBx-CIN",
+ "DCBx-CEE 1.01",
+ "DCBx-IEEE",
+ "", "", "",
+ "Auto Negotiated"
+};
+
+/* Initialize a port's Data Center Bridging state. Typically used after a
+ * Link Down event.
+ */
+void cxgb4_dcb_state_init(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+ int version_temp = dcb->dcb_version;
+
+ memset(dcb, 0, sizeof(struct port_dcb_info));
+ dcb->state = CXGB4_DCB_STATE_START;
+ if (version_temp)
+ dcb->dcb_version = version_temp;
+
+ netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
+ __func__, pi->port_id);
+}
+
+void cxgb4_dcb_version_init(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+
+ /* Any writes here are only done on kernels that exlicitly need
+ * a specific version, say < 2.6.38 which only support CEE
+ */
+ dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
+}
+
+/* Finite State machine for Data Center Bridging.
+ */
+void cxgb4_dcb_state_fsm(struct net_device *dev,
+ enum cxgb4_dcb_state_input transition_to)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+ struct adapter *adap = pi->adapter;
+ enum cxgb4_dcb_state current_state = dcb->state;
+
+ netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
+ __func__, dcb->state, transition_to, dev->name);
+
+ switch (current_state) {
+ case CXGB4_DCB_STATE_START: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_DISABLED: {
+ /* we're going to use Host DCB */
+ dcb->state = CXGB4_DCB_STATE_HOST;
+ dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
+ dcb->enabled = 1;
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're going to use Firmware DCB */
+ dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
+ dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+ /* expected transition */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+ break;
+ }
+
+ default:
+ goto bad_state_input;
+ }
+ break;
+ }
+
+ case CXGB4_DCB_STATE_FW_INCOMPLETE: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're alreaady in firmware DCB mode */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+ /* we're already incomplete */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
+ dcb->enabled = 1;
+ linkwatch_fire_event(dev);
+ break;
+ }
+
+ default:
+ goto bad_state_input;
+ }
+ break;
+ }
+
+ case CXGB4_DCB_STATE_FW_ALLSYNCED: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_ENABLED: {
+ /* we're alreaady in firmware DCB mode */
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
+ /* We were successfully running with firmware DCB but
+ * now it's telling us that it's in an "incomplete
+ * state. We need to reset back to a ground state
+ * of incomplete.
+ */
+ cxgb4_dcb_state_init(dev);
+ dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
+ dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+ linkwatch_fire_event(dev);
+ break;
+ }
+
+ case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
+ /* we're already all sync'ed
+ * this is only applicable for IEEE or
+ * when another VI already completed negotiaton
+ */
+ dcb->enabled = 1;
+ linkwatch_fire_event(dev);
+ break;
+ }
+
+ default:
+ goto bad_state_input;
+ }
+ break;
+ }
+
+ case CXGB4_DCB_STATE_HOST: {
+ switch (transition_to) {
+ case CXGB4_DCB_INPUT_FW_DISABLED: {
+ /* we're alreaady in Host DCB mode */
+ break;
+ }
+
+ default:
+ goto bad_state_input;
+ }
+ break;
+ }
+
+ default:
+ goto bad_state_transition;
+ }
+ return;
+
+bad_state_input:
+ dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
+ transition_to);
+ return;
+
+bad_state_transition:
+ dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
+ current_state, transition_to);
+}
+
+/* Handle a DCB/DCBX update message from the firmware.
+ */
+void cxgb4_dcb_handle_fw_update(struct adapter *adap,
+ const struct fw_port_cmd *pcmd)
+{
+ const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
+ int port = FW_PORT_CMD_PORTID_GET(be32_to_cpu(pcmd->op_to_portid));
+ struct net_device *dev = adap->port[port];
+ struct port_info *pi = netdev_priv(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+ int dcb_type = pcmd->u.dcb.pgid.type;
+ int dcb_running_version;
+
+ /* Handle Firmware DCB Control messages separately since they drive
+ * our state machine.
+ */
+ if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
+ enum cxgb4_dcb_state_input input =
+ ((pcmd->u.dcb.control.all_syncd_pkd &
+ FW_PORT_CMD_ALL_SYNCD)
+ ? CXGB4_DCB_STATE_FW_ALLSYNCED
+ : CXGB4_DCB_STATE_FW_INCOMPLETE);
+
+ if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
+ dcb_running_version = FW_PORT_CMD_DCB_VERSION_GET(
+ be16_to_cpu(
+ pcmd->u.dcb.control.dcb_version_to_app_state));
+ if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
+ dcb_running_version == FW_PORT_DCB_VER_IEEE) {
+ dcb->dcb_version = dcb_running_version;
+ dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
+ dev->name,
+ dcb_ver_array[dcb->dcb_version]);
+ } else {
+ dev_warn(adap->pdev_dev,
+ "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
+ dcb_ver_array[dcb->dcb_version],
+ dcb_ver_array[dcb_running_version]);
+ dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
+ }
+ }
+
+ cxgb4_dcb_state_fsm(dev, input);
+ return;
+ }
+
+ /* It's weird, and almost certainly an error, to get Firmware DCB
+ * messages when we either haven't been told whether we're going to be
+ * doing Host or Firmware DCB; and even worse when we've been told
+ * that we're doing Host DCB!
+ */
+ if (dcb->state == CXGB4_DCB_STATE_START ||
+ dcb->state == CXGB4_DCB_STATE_HOST) {
+ dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
+ dcb->state);
+ return;
+ }
+
+ /* Now handle the general Firmware DCB update messages ...
+ */
+ switch (dcb_type) {
+ case FW_PORT_DCB_TYPE_PGID:
+ dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
+ dcb->msgs |= CXGB4_DCB_FW_PGID;
+ break;
+
+ case FW_PORT_DCB_TYPE_PGRATE:
+ dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
+ memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
+ sizeof(dcb->pgrate));
+ memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
+ sizeof(dcb->tsa));
+ dcb->msgs |= CXGB4_DCB_FW_PGRATE;
+ if (dcb->msgs & CXGB4_DCB_FW_PGID)
+ IEEE_FAUX_SYNC(dev, dcb);
+ break;
+
+ case FW_PORT_DCB_TYPE_PRIORATE:
+ memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
+ sizeof(dcb->priorate));
+ dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
+ break;
+
+ case FW_PORT_DCB_TYPE_PFC:
+ dcb->pfcen = fwdcb->pfc.pfcen;
+ dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
+ dcb->msgs |= CXGB4_DCB_FW_PFC;
+ IEEE_FAUX_SYNC(dev, dcb);
+ break;
+
+ case FW_PORT_DCB_TYPE_APP_ID: {
+ const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
+ int idx = fwap->idx;
+ struct app_priority *ap = &dcb->app_priority[idx];
+
+ struct dcb_app app = {
+ .protocol = be16_to_cpu(fwap->protocolid),
+ };
+ int err;
+
+ /* Convert from firmware format to relevant format
+ * when using app selector
+ */
+ if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
+ app.selector = (fwap->sel_field + 1);
+ app.priority = ffs(fwap->user_prio_map) - 1;
+ err = dcb_ieee_setapp(dev, &app);
+ IEEE_FAUX_SYNC(dev, dcb);
+ } else {
+ /* Default is CEE */
+ app.selector = !!(fwap->sel_field);
+ app.priority = fwap->user_prio_map;
+ err = dcb_setapp(dev, &app);
+ }
+
+ if (err)
+ dev_err(adap->pdev_dev,
+ "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
+ app.selector, app.protocol, app.priority, -err);
+
+ ap->user_prio_map = fwap->user_prio_map;
+ ap->sel_field = fwap->sel_field;
+ ap->protocolid = be16_to_cpu(fwap->protocolid);
+ dcb->msgs |= CXGB4_DCB_FW_APP_ID;
+ break;
+ }
+
+ default:
+ dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
+ dcb_type);
+ break;
+ }
+}
+
+/* Data Center Bridging netlink operations.
+ */
+
+
+/* Get current DCB enabled/disabled state.
+ */
+static u8 cxgb4_getstate(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ return pi->dcb.enabled;
+}
+
+/* Set DCB enabled/disabled.
+ */
+static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ /* Firmware doesn't provide any mechanism to control the DCB state.
+ */
+ if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
+ return 1;
+
+ return 0;
+}
+
+static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
+ u8 *prio_type, u8 *pgid, u8 *bw_per,
+ u8 *up_tc_map, int local)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int err;
+
+ *prio_type = *pgid = *bw_per = *up_tc_map = 0;
+
+ if (local)
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ else
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+
+ pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+ return;
+ }
+ *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
+
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+ -err);
+ return;
+ }
+
+ *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
+ *up_tc_map = (1 << tc);
+
+ /* prio_type is link strict */
+ *prio_type = 0x2;
+}
+
+static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
+ u8 *prio_type, u8 *pgid, u8 *bw_per,
+ u8 *up_tc_map)
+{
+ return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 1);
+}
+
+
+static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
+ u8 *prio_type, u8 *pgid, u8 *bw_per,
+ u8 *up_tc_map)
+{
+ return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 0);
+}
+
+static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
+ u8 prio_type, u8 pgid, u8 bw_per,
+ u8 up_tc_map)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ u32 _pgid;
+ int err;
+
+ if (pgid == DCB_ATTR_VALUE_UNDEFINED)
+ return;
+ if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
+ return;
+
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+ return;
+ }
+
+ _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
+ _pgid &= ~(0xF << (tc * 4));
+ _pgid |= pgid << (tc * 4);
+ pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
+
+ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
+ -err);
+ return;
+ }
+
+ memset(&pcmd, 0, sizeof(struct fw_port_cmd));
+
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+ -err);
+ return;
+ }
+
+ pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
+
+ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+ if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+ pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS)
+ dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
+ -err);
+}
+
+static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
+ int local)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int err;
+
+ if (local)
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ else
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+
+ pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+ -err);
+ return;
+ }
+
+ *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
+}
+
+static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
+{
+ return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
+}
+
+static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
+{
+ return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
+}
+
+static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
+ u8 bw_per)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int err;
+
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+ -err);
+ return;
+ }
+
+ pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
+
+ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+ if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+ pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+ if (err != FW_PORT_DCB_CFG_SUCCESS)
+ dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
+ -err);
+}
+
+/* Return whether the specified Traffic Class Priority has Priority Pause
+ * Frames enabled.
+ */
+static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+
+ if (dcb->state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
+ priority >= CXGB4_MAX_PRIORITY)
+ *pfccfg = 0;
+ else
+ *pfccfg = (pi->dcb.pfcen >> priority) & 1;
+}
+
+/* Enable/disable Priority Pause Frames for the specified Traffic Class
+ * Priority.
+ */
+static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int err;
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED ||
+ priority >= CXGB4_MAX_PRIORITY)
+ return;
+
+ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+ if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+ pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+ pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
+ pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
+
+ if (pfccfg)
+ pcmd.u.dcb.pfc.pfcen |= (1 << priority);
+ else
+ pcmd.u.dcb.pfc.pfcen &= (~(1 << priority));
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
+ return;
+ }
+
+ pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
+}
+
+static u8 cxgb4_setall(struct net_device *dev)
+{
+ return 0;
+}
+
+/* Return DCB capabilities.
+ */
+static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ switch (cap_id) {
+ case DCB_CAP_ATTR_PG:
+ case DCB_CAP_ATTR_PFC:
+ *caps = true;
+ break;
+
+ case DCB_CAP_ATTR_PG_TCS:
+ /* 8 priorities for PG represented by bitmap */
+ *caps = 0x80;
+ break;
+
+ case DCB_CAP_ATTR_PFC_TCS:
+ /* 8 priorities for PFC represented by bitmap */
+ *caps = 0x80;
+ break;
+
+ case DCB_CAP_ATTR_GSP:
+ *caps = true;
+ break;
+
+ case DCB_CAP_ATTR_UP2TC:
+ case DCB_CAP_ATTR_BCN:
+ *caps = false;
+ break;
+
+ case DCB_CAP_ATTR_DCBX:
+ *caps = pi->dcb.supported;
+ break;
+
+ default:
+ *caps = false;
+ }
+
+ return 0;
+}
+
+/* Return the number of Traffic Classes for the indicated Traffic Class ID.
+ */
+static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ switch (tcs_id) {
+ case DCB_NUMTCS_ATTR_PG:
+ if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
+ *num = pi->dcb.pg_num_tcs_supported;
+ else
+ *num = 0x8;
+ break;
+
+ case DCB_NUMTCS_ATTR_PFC:
+ *num = 0x8;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Set the number of Traffic Classes supported for the indicated Traffic Class
+ * ID.
+ */
+static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
+{
+ /* Setting the number of Traffic Classes isn't supported.
+ */
+ return -ENOSYS;
+}
+
+/* Return whether Priority Flow Control is enabled. */
+static u8 cxgb4_getpfcstate(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return false;
+
+ return pi->dcb.pfcen != 0;
+}
+
+/* Enable/disable Priority Flow Control. */
+static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
+{
+ /* We can't enable/disable Priority Flow Control but we also can't
+ * return an error ...
+ */
+}
+
+/* Return the Application User Priority Map associated with the specified
+ * Application ID.
+ */
+static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+ int peer)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int i;
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return 0;
+
+ for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+ struct fw_port_cmd pcmd;
+ int err;
+
+ if (peer)
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ else
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+
+ pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+ pcmd.u.dcb.app_priority.idx = i;
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
+ -err);
+ return err;
+ }
+ if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
+ if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
+ return pcmd.u.dcb.app_priority.user_prio_map;
+
+ /* exhausted app list */
+ if (!pcmd.u.dcb.app_priority.protocolid)
+ break;
+ }
+
+ return -EEXIST;
+}
+
+/* Return the Application User Priority Map associated with the specified
+ * Application ID.
+ */
+static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
+{
+ return __cxgb4_getapp(dev, app_idtype, app_id, 0);
+}
+
+/* Write a new Application User Priority Map for the specified Application ID
+ */
+static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+ u8 app_prio)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int i, err;
+
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return -EINVAL;
+
+ /* DCB info gets thrown away on link up */
+ if (!netif_carrier_ok(dev))
+ return -ENOLINK;
+
+ for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+ INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+ pcmd.u.dcb.app_priority.idx = i;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+ -err);
+ return err;
+ }
+ if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
+ /* overwrite existing app table */
+ pcmd.u.dcb.app_priority.protocolid = 0;
+ break;
+ }
+ /* find first empty slot */
+ if (!pcmd.u.dcb.app_priority.protocolid)
+ break;
+ }
+
+ if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
+ /* no empty slots available */
+ dev_err(adap->pdev_dev, "DCB app table full\n");
+ return -EBUSY;
+ }
+
+ /* write out new app table entry */
+ INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
+ if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
+ pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY);
+
+ pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+ pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
+ pcmd.u.dcb.app_priority.sel_field = app_idtype;
+ pcmd.u.dcb.app_priority.user_prio_map = app_prio;
+ pcmd.u.dcb.app_priority.idx = i;
+
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
+ -err);
+ return err;
+ }
+
+ return 0;
+}
+
+/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
+static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
+ u8 app_prio)
+{
+ int ret;
+ struct dcb_app app = {
+ .selector = app_idtype,
+ .protocol = app_id,
+ .priority = app_prio,
+ };
+
+ if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
+ app_idtype != DCB_APP_IDTYPE_PORTNUM)
+ return -EINVAL;
+
+ /* Convert app_idtype to a format that firmware understands */
+ ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
+ app_idtype : 3, app_id, app_prio);
+ if (ret)
+ return ret;
+
+ return dcb_setapp(dev, &app);
+}
+
+/* Return whether IEEE Data Center Bridging has been negotiated.
+ */
+static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+ struct port_dcb_info *dcb = &pi->dcb;
+
+ return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
+ (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
+}
+
+/* Fill in the Application User Priority Map associated with the
+ * specified Application.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
+ */
+static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
+{
+ int prio;
+
+ if (!cxgb4_ieee_negotiation_complete(dev))
+ return -EINVAL;
+ if (!(app->selector && app->protocol))
+ return -EINVAL;
+
+ /* Try querying firmware first, use firmware format */
+ prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
+
+ if (prio < 0)
+ prio = dcb_ieee_getapp_mask(dev, app);
+
+ app->priority = ffs(prio) - 1;
+ return 0;
+}
+
+/* Write a new Application User Priority Map for the specified Application ID.
+ * Priority for IEEE dcb_app is an integer, with 0 being a valid value
+ */
+static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+ int ret;
+
+ if (!cxgb4_ieee_negotiation_complete(dev))
+ return -EINVAL;
+ if (!(app->selector && app->protocol))
+ return -EINVAL;
+
+ if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app->selector < IEEE_8021QAZ_APP_SEL_ANY))
+ return -EINVAL;
+
+ /* change selector to a format that firmware understands */
+ ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
+ (1 << app->priority));
+ if (ret)
+ return ret;
+
+ return dcb_ieee_setapp(dev, app);
+}
+
+/* Return our DCBX parameters.
+ */
+static u8 cxgb4_getdcbx(struct net_device *dev)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ /* This is already set by cxgb4_set_dcb_caps, so just return it */
+ return pi->dcb.supported;
+}
+
+/* Set our DCBX parameters.
+ */
+static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ /* Filter out requests which exceed our capabilities.
+ */
+ if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
+ != dcb_request)
+ return 1;
+
+ /* Can't enable DCB if we haven't successfully negotiated it.
+ */
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return 1;
+
+ /* There's currently no mechanism to allow for the firmware DCBX
+ * negotiation to be changed from the Host Driver. If the caller
+ * requests exactly the same parameters that we already have then
+ * we'll allow them to be successfully "set" ...
+ */
+ if (dcb_request != pi->dcb.supported)
+ return 1;
+
+ pi->dcb.supported = dcb_request;
+ return 0;
+}
+
+static int cxgb4_getpeer_app(struct net_device *dev,
+ struct dcb_peer_app_info *info, u16 *app_count)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int i, err = 0;
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return 1;
+
+ info->willing = 0;
+ info->error = 0;
+
+ *app_count = 0;
+ for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+ pcmd.u.dcb.app_priority.idx = *app_count;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+ -err);
+ return err;
+ }
+
+ /* find first empty slot */
+ if (!pcmd.u.dcb.app_priority.protocolid)
+ break;
+ }
+ *app_count = i;
+ return err;
+}
+
+static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ int i, err = 0;
+
+ if (pi->dcb.state != CXGB4_DCB_STATE_FW_ALLSYNCED)
+ return 1;
+
+ for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
+ pcmd.u.dcb.app_priority.idx = i;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
+ -err);
+ return err;
+ }
+
+ /* find first empty slot */
+ if (!pcmd.u.dcb.app_priority.protocolid)
+ break;
+
+ table[i].selector = pcmd.u.dcb.app_priority.sel_field;
+ table[i].protocol =
+ be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
+ table[i].priority =
+ ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
+ }
+ return err;
+}
+
+/* Return Priority Group information.
+ */
+static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
+{
+ struct fw_port_cmd pcmd;
+ struct port_info *pi = netdev2pinfo(dev);
+ struct adapter *adap = pi->adapter;
+ u32 pgid;
+ int i, err;
+
+ /* We're always "willing" -- the Switch Fabric always dictates the
+ * DCBX parameters to us.
+ */
+ pg->willing = true;
+
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
+ return err;
+ }
+ pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
+
+ for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
+ pg->prio_pg[i] = (pgid >> (i * 4)) & 0xF;
+
+ INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
+ pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
+ err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
+ if (err != FW_PORT_DCB_CFG_SUCCESS) {
+ dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
+ -err);
+ return err;
+ }
+
+ for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
+ pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
+
+ return 0;
+}
+
+/* Return Priority Flow Control information.
+ */
+static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
+ pfc->pfc_en = pi->dcb.pfcen;
+
+ return 0;
+}
+
+const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
+ .ieee_getapp = cxgb4_ieee_getapp,
+ .ieee_setapp = cxgb4_ieee_setapp,
+
+ /* CEE std */
+ .getstate = cxgb4_getstate,
+ .setstate = cxgb4_setstate,
+ .getpgtccfgtx = cxgb4_getpgtccfg_tx,
+ .getpgbwgcfgtx = cxgb4_getpgbwgcfg_tx,
+ .getpgtccfgrx = cxgb4_getpgtccfg_rx,
+ .getpgbwgcfgrx = cxgb4_getpgbwgcfg_rx,
+ .setpgtccfgtx = cxgb4_setpgtccfg_tx,
+ .setpgbwgcfgtx = cxgb4_setpgbwgcfg_tx,
+ .setpfccfg = cxgb4_setpfccfg,
+ .getpfccfg = cxgb4_getpfccfg,
+ .setall = cxgb4_setall,
+ .getcap = cxgb4_getcap,
+ .getnumtcs = cxgb4_getnumtcs,
+ .setnumtcs = cxgb4_setnumtcs,
+ .getpfcstate = cxgb4_getpfcstate,
+ .setpfcstate = cxgb4_setpfcstate,
+ .getapp = cxgb4_getapp,
+ .setapp = cxgb4_setapp,
+
+ /* DCBX configuration */
+ .getdcbx = cxgb4_getdcbx,
+ .setdcbx = cxgb4_setdcbx,
+
+ /* peer apps */
+ .peer_getappinfo = cxgb4_getpeer_app,
+ .peer_getapptable = cxgb4_getpeerapp_tbl,
+
+ /* CEE peer */
+ .cee_peer_getpg = cxgb4_cee_peer_getpg,
+ .cee_peer_getpfc = cxgb4_cee_peer_getpfc,
+};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
new file mode 100644
index 000000000000..2a6aa88984f4
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved.
+ *
+ * Written by Anish Bhatt (anish@chelsio.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ */
+
+#ifndef __CXGB4_DCB_H
+#define __CXGB4_DCB_H
+
+#include <linux/netdevice.h>
+#include <linux/dcbnl.h>
+#include <net/dcbnl.h>
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+
+#define CXGB4_DCBX_FW_SUPPORT \
+ (DCB_CAP_DCBX_VER_CEE | \
+ DCB_CAP_DCBX_VER_IEEE | \
+ DCB_CAP_DCBX_LLD_MANAGED)
+#define CXGB4_DCBX_HOST_SUPPORT \
+ (DCB_CAP_DCBX_VER_CEE | \
+ DCB_CAP_DCBX_VER_IEEE | \
+ DCB_CAP_DCBX_HOST)
+
+#define CXGB4_MAX_PRIORITY CXGB4_MAX_DCBX_APP_SUPPORTED
+#define CXGB4_MAX_TCS CXGB4_MAX_DCBX_APP_SUPPORTED
+
+#define INIT_PORT_DCB_CMD(__pcmd, __port, __op, __action) \
+ do { \
+ memset(&(__pcmd), 0, sizeof(__pcmd)); \
+ (__pcmd).op_to_portid = \
+ cpu_to_be32(FW_CMD_OP(FW_PORT_CMD) | \
+ FW_CMD_REQUEST | \
+ FW_CMD_##__op | \
+ FW_PORT_CMD_PORTID(__port)); \
+ (__pcmd).action_to_len16 = \
+ cpu_to_be32(FW_PORT_CMD_ACTION(__action) | \
+ FW_LEN16(pcmd)); \
+ } while (0)
+
+#define INIT_PORT_DCB_READ_PEER_CMD(__pcmd, __port) \
+ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_RECV)
+
+#define INIT_PORT_DCB_READ_LOCAL_CMD(__pcmd, __port) \
+ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_TRANS)
+
+#define INIT_PORT_DCB_READ_SYNC_CMD(__pcmd, __port) \
+ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_DET)
+
+#define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \
+ INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG)
+
+#define IEEE_FAUX_SYNC(__dev, __dcb) \
+ do { \
+ if ((__dcb)->dcb_version == FW_PORT_DCB_VER_IEEE) \
+ cxgb4_dcb_state_fsm((__dev), \
+ CXGB4_DCB_STATE_FW_ALLSYNCED); \
+ } while (0)
+
+/* States we can be in for a port's Data Center Bridging.
+ */
+enum cxgb4_dcb_state {
+ CXGB4_DCB_STATE_START, /* initial unknown state */
+ CXGB4_DCB_STATE_HOST, /* we're using Host DCB (if at all) */
+ CXGB4_DCB_STATE_FW_INCOMPLETE, /* using firmware DCB, incomplete */
+ CXGB4_DCB_STATE_FW_ALLSYNCED, /* using firmware DCB, all sync'ed */
+};
+
+/* Data Center Bridging state input for the Finite State Machine.
+ */
+enum cxgb4_dcb_state_input {
+ /* Input from the firmware.
+ */
+ CXGB4_DCB_INPUT_FW_DISABLED, /* firmware DCB disabled */
+ CXGB4_DCB_INPUT_FW_ENABLED, /* firmware DCB enabled */
+ CXGB4_DCB_INPUT_FW_INCOMPLETE, /* firmware reports incomplete DCB */
+ CXGB4_DCB_INPUT_FW_ALLSYNCED, /* firmware reports all sync'ed */
+
+};
+
+/* Firmware DCB messages that we've received so far ...
+ */
+enum cxgb4_dcb_fw_msgs {
+ CXGB4_DCB_FW_PGID = 0x01,
+ CXGB4_DCB_FW_PGRATE = 0x02,
+ CXGB4_DCB_FW_PRIORATE = 0x04,
+ CXGB4_DCB_FW_PFC = 0x08,
+ CXGB4_DCB_FW_APP_ID = 0x10,
+};
+
+#define CXGB4_MAX_DCBX_APP_SUPPORTED 8
+
+/* Data Center Bridging support;
+ */
+struct port_dcb_info {
+ enum cxgb4_dcb_state state; /* DCB State Machine */
+ enum cxgb4_dcb_fw_msgs msgs; /* DCB Firmware messages received */
+ unsigned int supported; /* OS DCB capabilities supported */
+ bool enabled; /* OS Enabled state */
+
+ /* Cached copies of DCB information sent by the firmware (in Host
+ * Native Endian format).
+ */
+ u32 pgid; /* Priority Group[0..7] */
+ u8 dcb_version; /* Running DCBx version */
+ u8 pfcen; /* Priority Flow Control[0..7] */
+ u8 pg_num_tcs_supported; /* max PG Traffic Classes */
+ u8 pfc_num_tcs_supported; /* max PFC Traffic Classes */
+ u8 pgrate[8]; /* Priority Group Rate[0..7] */
+ u8 priorate[8]; /* Priority Rate[0..7] */
+ u8 tsa[8]; /* TSA Algorithm[0..7] */
+ struct app_priority { /* Application Information */
+ u8 user_prio_map; /* Priority Map bitfield */
+ u8 sel_field; /* Protocol ID interpretation */
+ u16 protocolid; /* Protocol ID */
+ } app_priority[CXGB4_MAX_DCBX_APP_SUPPORTED];
+};
+
+void cxgb4_dcb_state_init(struct net_device *);
+void cxgb4_dcb_version_init(struct net_device *);
+void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input);
+void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *);
+void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *);
+extern const struct dcbnl_rtnl_ops cxgb4_dcb_ops;
+
+#define CXGB4_DCB_ENABLED true
+
+#else /* !CONFIG_CHELSIO_T4_DCB */
+
+static inline void cxgb4_dcb_state_init(struct net_device *dev)
+{
+}
+
+#define CXGB4_DCB_ENABLED false
+
+#endif /* !CONFIG_CHELSIO_T4_DCB */
+
+#endif /* __CXGB4_DCB_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index a83271cf17c3..1afee70ce856 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -67,6 +67,7 @@
#include "t4_regs.h"
#include "t4_msg.h"
#include "t4fw_api.h"
+#include "cxgb4_dcb.h"
#include "l2t.h"
#include <../drivers/net/bonding/bonding.h>
@@ -211,7 +212,7 @@ struct filter_entry {
#define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) }
-static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
+static const struct pci_device_id cxgb4_pci_tbl[] = {
CH_DEVICE(0xa000, 0), /* PE10K */
CH_DEVICE(0x4001, -1),
CH_DEVICE(0x4002, -1),
@@ -223,6 +224,17 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x4008, -1),
CH_DEVICE(0x4009, -1),
CH_DEVICE(0x400a, -1),
+ CH_DEVICE(0x400d, -1),
+ CH_DEVICE(0x400e, -1),
+ CH_DEVICE(0x4080, -1),
+ CH_DEVICE(0x4081, -1),
+ CH_DEVICE(0x4082, -1),
+ CH_DEVICE(0x4083, -1),
+ CH_DEVICE(0x4084, -1),
+ CH_DEVICE(0x4085, -1),
+ CH_DEVICE(0x4086, -1),
+ CH_DEVICE(0x4087, -1),
+ CH_DEVICE(0x4088, -1),
CH_DEVICE(0x4401, 4),
CH_DEVICE(0x4402, 4),
CH_DEVICE(0x4403, 4),
@@ -235,6 +247,15 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x440a, 4),
CH_DEVICE(0x440d, 4),
CH_DEVICE(0x440e, 4),
+ CH_DEVICE(0x4480, 4),
+ CH_DEVICE(0x4481, 4),
+ CH_DEVICE(0x4482, 4),
+ CH_DEVICE(0x4483, 4),
+ CH_DEVICE(0x4484, 4),
+ CH_DEVICE(0x4485, 4),
+ CH_DEVICE(0x4486, 4),
+ CH_DEVICE(0x4487, 4),
+ CH_DEVICE(0x4488, 4),
CH_DEVICE(0x5001, 4),
CH_DEVICE(0x5002, 4),
CH_DEVICE(0x5003, 4),
@@ -391,6 +412,17 @@ module_param_array(num_vf, uint, NULL, 0644);
MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
#endif
+/* TX Queue select used to determine what algorithm to use for selecting TX
+ * queue. Select between the kernel provided function (select_queue=0) or user
+ * cxgb_select_queue function (select_queue=1)
+ *
+ * Default: select_queue=0
+ */
+static int select_queue;
+module_param(select_queue, int, 0644);
+MODULE_PARM_DESC(select_queue,
+ "Select between kernel provided method of selecting or driver method of selecting TX queue. Default is kernel method.");
+
/*
* The filter TCAM has a fixed portion and a variable portion. The fixed
* portion can match on source/destination IP IPv4/IPv6 addresses and TCP/UDP
@@ -458,6 +490,44 @@ static void link_report(struct net_device *dev)
}
}
+#ifdef CONFIG_CHELSIO_T4_DCB
+/* Set up/tear down Data Center Bridging Priority mapping for a net device. */
+static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adap = pi->adapter;
+ struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset];
+ int i;
+
+ /* We use a simple mapping of Port TX Queue Index to DCB
+ * Priority when we're enabling DCB.
+ */
+ for (i = 0; i < pi->nqsets; i++, txq++) {
+ u32 name, value;
+ int err;
+
+ name = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
+ FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) |
+ FW_PARAMS_PARAM_YZ(txq->q.cntxt_id));
+ value = enable ? i : 0xffffffff;
+
+ /* Since we can be called while atomic (from "interrupt
+ * level") we need to issue the Set Parameters Commannd
+ * without sleeping (timeout < 0).
+ */
+ err = t4_set_params_nosleep(adap, adap->mbox, adap->fn, 0, 1,
+ &name, &value);
+
+ if (err)
+ dev_err(adap->pdev_dev,
+ "Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n",
+ enable ? "set" : "unset", pi->port_id, i, -err);
+ else
+ txq->dcb_prio = value;
+ }
+}
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
{
struct net_device *dev = adapter->port[port_id];
@@ -466,8 +536,13 @@ void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) {
if (link_stat)
netif_carrier_on(dev);
- else
+ else {
+#ifdef CONFIG_CHELSIO_T4_DCB
+ cxgb4_dcb_state_init(dev);
+ dcb_tx_queue_prio_enable(dev, false);
+#endif /* CONFIG_CHELSIO_T4_DCB */
netif_carrier_off(dev);
+ }
link_report(dev);
}
@@ -600,11 +675,49 @@ static int link_start(struct net_device *dev)
if (ret == 0)
ret = t4_link_start(pi->adapter, mb, pi->tx_chan,
&pi->link_cfg);
- if (ret == 0)
- ret = t4_enable_vi(pi->adapter, mb, pi->viid, true, true);
+ if (ret == 0) {
+ local_bh_disable();
+ ret = t4_enable_vi_params(pi->adapter, mb, pi->viid, true,
+ true, CXGB4_DCB_ENABLED);
+ local_bh_enable();
+ }
+
return ret;
}
+int cxgb4_dcb_enabled(const struct net_device *dev)
+{
+#ifdef CONFIG_CHELSIO_T4_DCB
+ struct port_info *pi = netdev_priv(dev);
+
+ return pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED;
+#else
+ return 0;
+#endif
+}
+EXPORT_SYMBOL(cxgb4_dcb_enabled);
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+/* Handle a Data Center Bridging update message from the firmware. */
+static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd)
+{
+ int port = FW_PORT_CMD_PORTID_GET(ntohl(pcmd->op_to_portid));
+ struct net_device *dev = adap->port[port];
+ int old_dcb_enabled = cxgb4_dcb_enabled(dev);
+ int new_dcb_enabled;
+
+ cxgb4_dcb_handle_fw_update(adap, pcmd);
+ new_dcb_enabled = cxgb4_dcb_enabled(dev);
+
+ /* If the DCB has become enabled or disabled on the port then we're
+ * going to need to set up/tear down DCB Priority parameters for the
+ * TX Queues associated with the port.
+ */
+ if (new_dcb_enabled != old_dcb_enabled)
+ dcb_tx_queue_prio_enable(dev, new_dcb_enabled);
+}
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
/* Clear a filter and release any of its resources that we own. This also
* clears the filter's "pending" status.
*/
@@ -709,8 +822,32 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
const struct cpl_fw6_msg *p = (void *)rsp;
- if (p->type == 0)
- t4_handle_fw_rpl(q->adap, p->data);
+#ifdef CONFIG_CHELSIO_T4_DCB
+ const struct fw_port_cmd *pcmd = (const void *)p->data;
+ unsigned int cmd = FW_CMD_OP_GET(ntohl(pcmd->op_to_portid));
+ unsigned int action =
+ FW_PORT_CMD_ACTION_GET(ntohl(pcmd->action_to_len16));
+
+ if (cmd == FW_PORT_CMD &&
+ action == FW_PORT_ACTION_GET_PORT_INFO) {
+ int port = FW_PORT_CMD_PORTID_GET(
+ be32_to_cpu(pcmd->op_to_portid));
+ struct net_device *dev = q->adap->port[port];
+ int state_input = ((pcmd->u.info.dcbxdis_pkd &
+ FW_PORT_CMD_DCBXDIS)
+ ? CXGB4_DCB_INPUT_FW_DISABLED
+ : CXGB4_DCB_INPUT_FW_ENABLED);
+
+ cxgb4_dcb_state_fsm(dev, state_input);
+ }
+
+ if (cmd == FW_PORT_CMD &&
+ action == FW_PORT_ACTION_L2_DCB_CFG)
+ dcb_rpl(q->adap, pcmd);
+ else
+#endif
+ if (p->type == 0)
+ t4_handle_fw_rpl(q->adap, p->data);
} else if (opcode == CPL_L2T_WRITE_RPL) {
const struct cpl_l2t_write_rpl *p = (void *)rsp;
@@ -1290,6 +1427,48 @@ static int del_filter_wr(struct adapter *adapter, int fidx)
return 0;
}
+static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ int txq;
+
+#ifdef CONFIG_CHELSIO_T4_DCB
+ /* If a Data Center Bridging has been successfully negotiated on this
+ * link then we'll use the skb's priority to map it to a TX Queue.
+ * The skb's priority is determined via the VLAN Tag Priority Code
+ * Point field.
+ */
+ if (cxgb4_dcb_enabled(dev)) {
+ u16 vlan_tci;
+ int err;
+
+ err = vlan_get_tag(skb, &vlan_tci);
+ if (unlikely(err)) {
+ if (net_ratelimit())
+ netdev_warn(dev,
+ "TX Packet without VLAN Tag on DCB Link\n");
+ txq = 0;
+ } else {
+ txq = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ }
+ return txq;
+ }
+#endif /* CONFIG_CHELSIO_T4_DCB */
+
+ if (select_queue) {
+ txq = (skb_rx_queue_recorded(skb)
+ ? skb_get_rx_queue(skb)
+ : smp_processor_id());
+
+ while (unlikely(txq >= dev->real_num_tx_queues))
+ txq -= dev->real_num_tx_queues;
+
+ return txq;
+ }
+
+ return fallback(dev, skb) % dev->real_num_tx_queues;
+}
+
static inline int is_offload(const struct adapter *adap)
{
return adap->params.offload;
@@ -2912,6 +3091,8 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
loff_t avail = file_inode(file)->i_size;
unsigned int mem = (uintptr_t)file->private_data & 3;
struct adapter *adap = file->private_data - mem;
+ __be32 *data;
+ int ret;
if (pos < 0)
return -EINVAL;
@@ -2920,29 +3101,24 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
if (count > avail - pos)
count = avail - pos;
- while (count) {
- size_t len;
- int ret, ofst;
- __be32 data[16];
+ data = t4_alloc_mem(count);
+ if (!data)
+ return -ENOMEM;
- if ((mem == MEM_MC) || (mem == MEM_MC1))
- ret = t4_mc_read(adap, mem % MEM_MC, pos, data, NULL);
- else
- ret = t4_edc_read(adap, mem, pos, data, NULL);
- if (ret)
- return ret;
+ spin_lock(&adap->win0_lock);
+ ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ);
+ spin_unlock(&adap->win0_lock);
+ if (ret) {
+ t4_free_mem(data);
+ return ret;
+ }
+ ret = copy_to_user(buf, data, count);
- ofst = pos % sizeof(data);
- len = min(count, sizeof(data) - ofst);
- if (copy_to_user(buf, (u8 *)data + ofst, len))
- return -EFAULT;
+ t4_free_mem(data);
+ if (ret)
+ return -EFAULT;
- buf += len;
- pos += len;
- count -= len;
- }
- count = pos - *ppos;
- *ppos = pos;
+ *ppos = pos + count;
return count;
}
@@ -3274,8 +3450,8 @@ static int tid_init(struct tid_info *t)
return 0;
}
-static int cxgb4_clip_get(const struct net_device *dev,
- const struct in6_addr *lip)
+int cxgb4_clip_get(const struct net_device *dev,
+ const struct in6_addr *lip)
{
struct adapter *adap;
struct fw_clip_cmd c;
@@ -3289,9 +3465,10 @@ static int cxgb4_clip_get(const struct net_device *dev,
c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
}
+EXPORT_SYMBOL(cxgb4_clip_get);
-static int cxgb4_clip_release(const struct net_device *dev,
- const struct in6_addr *lip)
+int cxgb4_clip_release(const struct net_device *dev,
+ const struct in6_addr *lip)
{
struct adapter *adap;
struct fw_clip_cmd c;
@@ -3305,6 +3482,7 @@ static int cxgb4_clip_release(const struct net_device *dev,
c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
}
+EXPORT_SYMBOL(cxgb4_clip_release);
/**
* cxgb4_create_server - create an IP server
@@ -3603,7 +3781,11 @@ static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
__be64 indices;
int ret;
- ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
+ spin_lock(&adap->win0_lock);
+ ret = t4_memory_rw(adap, 0, MEM_EDC0, addr,
+ sizeof(indices), (__be32 *)&indices,
+ T4_MEMORY_READ);
+ spin_unlock(&adap->win0_lock);
if (!ret) {
*cidx = (be64_to_cpu(indices) >> 25) & 0xffff;
*pidx = (be64_to_cpu(indices) >> 9) & 0xffff;
@@ -3657,6 +3839,85 @@ void cxgb4_enable_db_coalescing(struct net_device *dev)
}
EXPORT_SYMBOL(cxgb4_enable_db_coalescing);
+int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte)
+{
+ struct adapter *adap;
+ u32 offset, memtype, memaddr;
+ u32 edc0_size, edc1_size, mc0_size, mc1_size;
+ u32 edc0_end, edc1_end, mc0_end, mc1_end;
+ int ret;
+
+ adap = netdev2adap(dev);
+
+ offset = ((stag >> 8) * 32) + adap->vres.stag.start;
+
+ /* Figure out where the offset lands in the Memory Type/Address scheme.
+ * This code assumes that the memory is laid out starting at offset 0
+ * with no breaks as: EDC0, EDC1, MC0, MC1. All cards have both EDC0
+ * and EDC1. Some cards will have neither MC0 nor MC1, most cards have
+ * MC0, and some have both MC0 and MC1.
+ */
+ edc0_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)) << 20;
+ edc1_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM1_BAR)) << 20;
+ mc0_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)) << 20;
+
+ edc0_end = edc0_size;
+ edc1_end = edc0_end + edc1_size;
+ mc0_end = edc1_end + mc0_size;
+
+ if (offset < edc0_end) {
+ memtype = MEM_EDC0;
+ memaddr = offset;
+ } else if (offset < edc1_end) {
+ memtype = MEM_EDC1;
+ memaddr = offset - edc0_end;
+ } else {
+ if (offset < mc0_end) {
+ memtype = MEM_MC0;
+ memaddr = offset - edc1_end;
+ } else if (is_t4(adap->params.chip)) {
+ /* T4 only has a single memory channel */
+ goto err;
+ } else {
+ mc1_size = EXT_MEM_SIZE_GET(
+ t4_read_reg(adap,
+ MA_EXT_MEMORY1_BAR)) << 20;
+ mc1_end = mc0_end + mc1_size;
+ if (offset < mc1_end) {
+ memtype = MEM_MC1;
+ memaddr = offset - mc0_end;
+ } else {
+ /* offset beyond the end of any memory */
+ goto err;
+ }
+ }
+ }
+
+ spin_lock(&adap->win0_lock);
+ ret = t4_memory_rw(adap, 0, memtype, memaddr, 32, tpte, T4_MEMORY_READ);
+ spin_unlock(&adap->win0_lock);
+ return ret;
+
+err:
+ dev_err(adap->pdev_dev, "stag %#x, offset %#x out of range\n",
+ stag, offset);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(cxgb4_read_tpte);
+
+u64 cxgb4_read_sge_timestamp(struct net_device *dev)
+{
+ u32 hi, lo;
+ struct adapter *adap;
+
+ adap = netdev2adap(dev);
+ lo = t4_read_reg(adap, SGE_TIMESTAMP_LO);
+ hi = GET_TSVAL(t4_read_reg(adap, SGE_TIMESTAMP_HI));
+
+ return ((u64)hi << 32) | (u64)lo;
+}
+EXPORT_SYMBOL(cxgb4_read_sge_timestamp);
+
static struct pci_driver cxgb4_driver;
static void check_neigh_update(struct neighbour *neigh)
@@ -3899,6 +4160,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
unsigned short i;
lli.pdev = adap->pdev;
+ lli.pf = adap->fn;
lli.l2t = adap->l2t;
lli.tids = &adap->tids;
lli.ports = adap->port;
@@ -3919,6 +4181,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.wr_cred = adap->params.ofldq_wr_cred;
lli.adapter_type = adap->params.chip;
lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
+ lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
(adap->fn * 4));
@@ -3933,8 +4196,12 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
lli.fw_vers = adap->params.fw_vers;
lli.dbfifo_int_thresh = dbfifo_int_thresh;
+ lli.sge_ingpadboundary = adap->sge.fl_align;
+ lli.sge_egrstatuspagesize = adap->sge.stat_len;
lli.sge_pktshift = adap->sge.pktshift;
lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
+ lli.max_ordird_qp = adap->params.max_ordird_qp;
+ lli.max_ird_adapter = adap->params.max_ird_adapter;
lli.ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl;
handle = ulds[uld].add(&lli);
@@ -4598,6 +4865,7 @@ static const struct net_device_ops cxgb4_netdev_ops = {
.ndo_open = cxgb_open,
.ndo_stop = cxgb_close,
.ndo_start_xmit = t4_eth_xmit,
+ .ndo_select_queue = cxgb_select_queue,
.ndo_get_stats64 = cxgb_get_stats,
.ndo_set_rx_mode = cxgb_set_rxmode,
.ndo_set_mac_address = cxgb_set_mac_addr,
@@ -4617,20 +4885,75 @@ void t4_fatal_err(struct adapter *adap)
dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
}
+/* Return the specified PCI-E Configuration Space register from our Physical
+ * Function. We try first via a Firmware LDST Command since we prefer to let
+ * the firmware own all of these registers, but if that fails we go for it
+ * directly ourselves.
+ */
+static u32 t4_read_pcie_cfg4(struct adapter *adap, int reg)
+{
+ struct fw_ldst_cmd ldst_cmd;
+ u32 val;
+ int ret;
+
+ /* Construct and send the Firmware LDST Command to retrieve the
+ * specified PCI-E Configuration Space register.
+ */
+ memset(&ldst_cmd, 0, sizeof(ldst_cmd));
+ ldst_cmd.op_to_addrspace =
+ htonl(FW_CMD_OP(FW_LDST_CMD) |
+ FW_CMD_REQUEST |
+ FW_CMD_READ |
+ FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
+ ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
+ ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
+ ldst_cmd.u.pcie.ctrl_to_fn =
+ (FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn));
+ ldst_cmd.u.pcie.r = reg;
+ ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
+ &ldst_cmd);
+
+ /* If the LDST Command suucceeded, exctract the returned register
+ * value. Otherwise read it directly ourself.
+ */
+ if (ret == 0)
+ val = ntohl(ldst_cmd.u.pcie.data[0]);
+ else
+ t4_hw_pci_read_cfg4(adap, reg, &val);
+
+ return val;
+}
+
static void setup_memwin(struct adapter *adap)
{
- u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
+ u32 mem_win0_base, mem_win1_base, mem_win2_base, mem_win2_aperture;
- bar0 = pci_resource_start(adap->pdev, 0); /* truncation intentional */
if (is_t4(adap->params.chip)) {
+ u32 bar0;
+
+ /* Truncation intentional: we only read the bottom 32-bits of
+ * the 64-bit BAR0/BAR1 ... We use the hardware backdoor
+ * mechanism to read BAR0 instead of using
+ * pci_resource_start() because we could be operating from
+ * within a Virtual Machine which is trapping our accesses to
+ * our Configuration Space and we need to set up the PCI-E
+ * Memory Window decoders with the actual addresses which will
+ * be coming across the PCI-E link.
+ */
+ bar0 = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_0);
+ bar0 &= PCI_BASE_ADDRESS_MEM_MASK;
+ adap->t4_bar0 = bar0;
+
mem_win0_base = bar0 + MEMWIN0_BASE;
mem_win1_base = bar0 + MEMWIN1_BASE;
mem_win2_base = bar0 + MEMWIN2_BASE;
+ mem_win2_aperture = MEMWIN2_APERTURE;
} else {
/* For T5, only relative offset inside the PCIe BAR is passed */
mem_win0_base = MEMWIN0_BASE;
- mem_win1_base = MEMWIN1_BASE_T5;
+ mem_win1_base = MEMWIN1_BASE;
mem_win2_base = MEMWIN2_BASE_T5;
+ mem_win2_aperture = MEMWIN2_APERTURE_T5;
}
t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
mem_win0_base | BIR(0) |
@@ -4640,16 +4963,19 @@ static void setup_memwin(struct adapter *adap)
WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
mem_win2_base | BIR(0) |
- WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
+ WINDOW(ilog2(mem_win2_aperture) - 10));
+ t4_read_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2));
}
static void setup_memwin_rdma(struct adapter *adap)
{
if (adap->vres.ocq.size) {
- unsigned int start, sz_kb;
+ u32 start;
+ unsigned int sz_kb;
- start = pci_resource_start(adap->pdev, 2) +
- OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
+ start = t4_read_pcie_cfg4(adap, PCI_BASE_ADDRESS_2);
+ start &= PCI_BASE_ADDRESS_MEM_MASK;
+ start += OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
t4_write_reg(adap,
PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
@@ -4862,7 +5188,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
adapter->fn, 0, 1, params, val);
if (ret == 0) {
/*
- * For t4_memory_write() below addresses and
+ * For t4_memory_rw() below addresses and
* sizes have to be in terms of multiples of 4
* bytes. So, if the Configuration File isn't
* a multiple of 4 bytes in length we'll have
@@ -4878,8 +5204,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
mtype = FW_PARAMS_PARAM_Y_GET(val[0]);
maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16;
- ret = t4_memory_write(adapter, mtype, maddr,
- size, data);
+ spin_lock(&adapter->win0_lock);
+ ret = t4_memory_rw(adapter, 0, mtype, maddr,
+ size, data, T4_MEMORY_WRITE);
if (ret == 0 && resid != 0) {
union {
__be32 word;
@@ -4890,10 +5217,12 @@ static int adap_init0_config(struct adapter *adapter, int reset)
last.word = data[size >> 2];
for (i = resid; i < 4; i++)
last.buf[i] = 0;
- ret = t4_memory_write(adapter, mtype,
- maddr + size,
- 4, &last.word);
+ ret = t4_memory_rw(adapter, 0, mtype,
+ maddr + size,
+ 4, &last.word,
+ T4_MEMORY_WRITE);
}
+ spin_unlock(&adapter->win0_lock);
}
}
@@ -5637,6 +5966,22 @@ static int adap_init0(struct adapter *adap)
adap->vres.cq.size = val[3] - val[2] + 1;
adap->vres.ocq.start = val[4];
adap->vres.ocq.size = val[5] - val[4] + 1;
+
+ params[0] = FW_PARAM_DEV(MAXORDIRD_QP);
+ params[1] = FW_PARAM_DEV(MAXIRD_ADAPTER);
+ ret = t4_query_params(adap, 0, 0, 0, 2, params, val);
+ if (ret < 0) {
+ adap->params.max_ordird_qp = 8;
+ adap->params.max_ird_adapter = 32 * adap->tids.ntids;
+ ret = 0;
+ } else {
+ adap->params.max_ordird_qp = val[0];
+ adap->params.max_ird_adapter = val[1];
+ }
+ dev_info(adap->pdev_dev,
+ "max_ordird_qp %d max_ird_adapter %d\n",
+ adap->params.max_ordird_qp,
+ adap->params.max_ird_adapter);
}
if (caps_cmd.iscsicaps) {
params[0] = FW_PARAM_PFVF(ISCSI_START);
@@ -5838,12 +6183,33 @@ static inline void init_rspq(struct adapter *adap, struct sge_rspq *q,
static void cfg_queues(struct adapter *adap)
{
struct sge *s = &adap->sge;
- int i, q10g = 0, n10g = 0, qidx = 0;
+ int i, n10g = 0, qidx = 0;
+#ifndef CONFIG_CHELSIO_T4_DCB
+ int q10g = 0;
+#endif
int ciq_size;
for_each_port(adap, i)
n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
+#ifdef CONFIG_CHELSIO_T4_DCB
+ /* For Data Center Bridging support we need to be able to support up
+ * to 8 Traffic Priorities; each of which will be assigned to its
+ * own TX Queue in order to prevent Head-Of-Line Blocking.
+ */
+ if (adap->params.nports * 8 > MAX_ETH_QSETS) {
+ dev_err(adap->pdev_dev, "MAX_ETH_QSETS=%d < %d!\n",
+ MAX_ETH_QSETS, adap->params.nports * 8);
+ BUG_ON(1);
+ }
+
+ for_each_port(adap, i) {
+ struct port_info *pi = adap2pinfo(adap, i);
+ pi->first_qset = qidx;
+ pi->nqsets = 8;
+ qidx += pi->nqsets;
+ }
+#else /* !CONFIG_CHELSIO_T4_DCB */
/*
* We default to 1 queue per non-10G port and up to # of cores queues
* per 10G port.
@@ -5860,6 +6226,7 @@ static void cfg_queues(struct adapter *adap)
pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
qidx += pi->nqsets;
}
+#endif /* !CONFIG_CHELSIO_T4_DCB */
s->ethqsets = qidx;
s->max_ethqsets = qidx; /* MSI-X may lower it later */
@@ -5978,8 +6345,14 @@ static int enable_msix(struct adapter *adap)
/* need nchan for each possible ULD */
ofld_need = 3 * nchan;
}
+#ifdef CONFIG_CHELSIO_T4_DCB
+ /* For Data Center Bridging we need 8 Ethernet TX Priority Queues for
+ * each port.
+ */
+ need = 8 * adap->params.nports + EXTRA_VECS + ofld_need;
+#else
need = adap->params.nports + EXTRA_VECS + ofld_need;
-
+#endif
want = pci_enable_msix_range(adap->pdev, entries, need, want);
if (want < 0)
return want;
@@ -6111,13 +6484,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
- /* We control everything through one PF */
- func = PCI_FUNC(pdev->devfn);
- if (func != ent->driver_data) {
- pci_save_state(pdev); /* to restore SR-IOV later */
- goto sriov;
- }
-
err = pci_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "cannot enable PCI device\n");
@@ -6161,6 +6527,13 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_free_adapter;
}
+ /* We control everything through one PF */
+ func = SOURCEPF_GET(readl(adapter->regs + PL_WHOAMI));
+ if (func != ent->driver_data) {
+ pci_save_state(pdev); /* to restore SR-IOV later */
+ goto sriov;
+ }
+
adapter->pdev = pdev;
adapter->pdev_dev = &pdev->dev;
adapter->mbox = func;
@@ -6242,6 +6615,10 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->netdev_ops = &cxgb4_netdev_ops;
+#ifdef CONFIG_CHELSIO_T4_DCB
+ netdev->dcbnl_ops = &cxgb4_dcb_ops;
+ cxgb4_dcb_state_init(netdev);
+#endif
netdev->ethtool_ops = &cxgb_ethtool_ops;
}
@@ -6366,8 +6743,7 @@ static void remove_one(struct pci_dev *pdev)
if (adapter->port[i]->reg_state == NETREG_REGISTERED)
unregister_netdev(adapter->port[i]);
- if (adapter->debugfs_root)
- debugfs_remove_recursive(adapter->debugfs_root);
+ debugfs_remove_recursive(adapter->debugfs_root);
/* If we allocated filters, free up state associated with any
* valid filters ...
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 55e9daf7f9d4..1366ba620c87 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -172,6 +172,10 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
unsigned char port, unsigned char mask);
int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
unsigned int queue, bool ipv6);
+int cxgb4_clip_get(const struct net_device *dev, const struct in6_addr *lip);
+int cxgb4_clip_release(const struct net_device *dev,
+ const struct in6_addr *lip);
+
static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
{
skb_set_queue_mapping(skb, (queue << 1) | prio);
@@ -243,6 +247,7 @@ struct cxgb4_lld_info {
unsigned char fw_api_ver; /* FW API version */
unsigned int fw_vers; /* FW version */
unsigned int iscsi_iolen; /* iSCSI max I/O length */
+ unsigned int cclk_ps; /* Core clock period in psec */
unsigned short udb_density; /* # of user DB/page */
unsigned short ucq_density; /* # of user CQs/page */
unsigned short filt_mode; /* filter optional components */
@@ -251,10 +256,15 @@ struct cxgb4_lld_info {
void __iomem *gts_reg; /* address of GTS register */
void __iomem *db_reg; /* address of kernel doorbell */
int dbfifo_int_thresh; /* doorbell fifo int threshold */
+ unsigned int sge_ingpadboundary; /* SGE ingress padding boundary */
+ unsigned int sge_egrstatuspagesize; /* SGE egress status page size */
unsigned int sge_pktshift; /* Padding between CPL and */
/* packet data */
+ unsigned int pf; /* Physical Function we're using */
bool enable_fw_ofld_conn; /* Enable connection through fw */
/* WR */
+ unsigned int max_ordird_qp; /* Max ORD/IRD depth per RDMA QP */
+ unsigned int max_ird_adapter; /* Max IRD memory per adapter */
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
};
@@ -291,5 +301,7 @@ int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
int cxgb4_flush_eq_cache(struct net_device *dev);
void cxgb4_disable_db_coalescing(struct net_device *dev);
void cxgb4_enable_db_coalescing(struct net_device *dev);
+int cxgb4_read_tpte(struct net_device *dev, u32 stag, __be32 *tpte);
+u64 cxgb4_read_sge_timestamp(struct net_device *dev);
#endif /* !__CXGB4_OFLD_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index 8a96572fdde0..96041397ee15 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
index 85eb5c71358d..a30126ce90cb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index dd4355d248e4..b0bba32d69d5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -2480,6 +2480,22 @@ static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq,
}
/**
+ * t4_free_ofld_rxqs - free a block of consecutive Rx queues
+ * @adap: the adapter
+ * @n: number of queues
+ * @q: pointer to first queue
+ *
+ * Release the resources of a consecutive block of offload Rx queues.
+ */
+void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q)
+{
+ for ( ; n; n--, q++)
+ if (q->rspq.desc)
+ free_rspq_fl(adap, &q->rspq,
+ q->fl.size ? &q->fl : NULL);
+}
+
+/**
* t4_free_sge_resources - free SGE resources
* @adap: the adapter
*
@@ -2490,12 +2506,12 @@ void t4_free_sge_resources(struct adapter *adap)
int i;
struct sge_eth_rxq *eq = adap->sge.ethrxq;
struct sge_eth_txq *etq = adap->sge.ethtxq;
- struct sge_ofld_rxq *oq = adap->sge.ofldrxq;
/* clean up Ethernet Tx/Rx queues */
for (i = 0; i < adap->sge.ethqsets; i++, eq++, etq++) {
if (eq->rspq.desc)
- free_rspq_fl(adap, &eq->rspq, &eq->fl);
+ free_rspq_fl(adap, &eq->rspq,
+ eq->fl.size ? &eq->fl : NULL);
if (etq->q.desc) {
t4_eth_eq_free(adap, adap->fn, adap->fn, 0,
etq->q.cntxt_id);
@@ -2506,18 +2522,9 @@ void t4_free_sge_resources(struct adapter *adap)
}
/* clean up RDMA and iSCSI Rx queues */
- for (i = 0; i < adap->sge.ofldqsets; i++, oq++) {
- if (oq->rspq.desc)
- free_rspq_fl(adap, &oq->rspq, &oq->fl);
- }
- for (i = 0, oq = adap->sge.rdmarxq; i < adap->sge.rdmaqs; i++, oq++) {
- if (oq->rspq.desc)
- free_rspq_fl(adap, &oq->rspq, &oq->fl);
- }
- for (i = 0, oq = adap->sge.rdmaciq; i < adap->sge.rdmaciqs; i++, oq++) {
- if (oq->rspq.desc)
- free_rspq_fl(adap, &oq->rspq, &oq->fl);
- }
+ t4_free_ofld_rxqs(adap, adap->sge.ofldqsets, adap->sge.ofldrxq);
+ t4_free_ofld_rxqs(adap, adap->sge.rdmaqs, adap->sge.rdmarxq);
+ t4_free_ofld_rxqs(adap, adap->sge.rdmaciqs, adap->sge.rdmaciq);
/* clean up offload Tx queues */
for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 931478e7bd28..a853133d8db8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -144,6 +144,30 @@ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg,
}
/*
+ * Read a 32-bit PCI Configuration Space register via the PCI-E backdoor
+ * mechanism. This guarantees that we get the real value even if we're
+ * operating within a Virtual Machine and the Hypervisor is trapping our
+ * Configuration Space accesses.
+ */
+void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
+{
+ u32 req = ENABLE | FUNCTION(adap->fn) | reg;
+
+ if (is_t4(adap->params.chip))
+ req |= F_LOCALCFG;
+
+ t4_write_reg(adap, PCIE_CFG_SPACE_REQ, req);
+ *val = t4_read_reg(adap, PCIE_CFG_SPACE_DATA);
+
+ /* Reset ENABLE to 0 so reads of PCIE_CFG_SPACE_DATA won't cause a
+ * Configuration Space read. (None of the other fields matter when
+ * ENABLE is 0 so a simple register write is easier than a
+ * read-modify-write via t4_set_reg_field().)
+ */
+ t4_write_reg(adap, PCIE_CFG_SPACE_REQ, 0);
+}
+
+/*
* Get the reply to a mailbox command and store it in @rpl in big-endian order.
*/
static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit,
@@ -389,78 +413,41 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
return 0;
}
-/*
- * t4_mem_win_rw - read/write memory through PCIE memory window
- * @adap: the adapter
- * @addr: address of first byte requested
- * @data: MEMWIN0_APERTURE bytes of data containing the requested address
- * @dir: direction of transfer 1 => read, 0 => write
- *
- * Read/write MEMWIN0_APERTURE bytes of data from MC starting at a
- * MEMWIN0_APERTURE-byte-aligned address that covers the requested
- * address @addr.
- */
-static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
-{
- int i;
- u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
-
- /*
- * Setup offset into PCIE memory window. Address must be a
- * MEMWIN0_APERTURE-byte-aligned address. (Read back MA register to
- * ensure that changes propagate before we attempt to use the new
- * values.)
- */
- t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
- (addr & ~(MEMWIN0_APERTURE - 1)) | win_pf);
- t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
-
- /* Collecting data 4 bytes at a time upto MEMWIN0_APERTURE */
- for (i = 0; i < MEMWIN0_APERTURE; i = i+0x4) {
- if (dir)
- *data++ = (__force __be32) t4_read_reg(adap,
- (MEMWIN0_BASE + i));
- else
- t4_write_reg(adap, (MEMWIN0_BASE + i),
- (__force u32) *data++);
- }
-
- return 0;
-}
-
/**
* t4_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window
* @adap: the adapter
+ * @win: PCI-E Memory Window to use
* @mtype: memory type: MEM_EDC0, MEM_EDC1 or MEM_MC
* @addr: address within indicated memory type
* @len: amount of memory to transfer
* @buf: host memory buffer
- * @dir: direction of transfer 1 => read, 0 => write
+ * @dir: direction of transfer T4_MEMORY_READ (1) or T4_MEMORY_WRITE (0)
*
* Reads/writes an [almost] arbitrary memory region in the firmware: the
- * firmware memory address, length and host buffer must be aligned on
- * 32-bit boudaries. The memory is transferred as a raw byte sequence
- * from/to the firmware's memory. If this memory contains data
- * structures which contain multi-byte integers, it's the callers
- * responsibility to perform appropriate byte order conversions.
+ * firmware memory address and host buffer must be aligned on 32-bit
+ * boudaries; the length may be arbitrary. The memory is transferred as
+ * a raw byte sequence from/to the firmware's memory. If this memory
+ * contains data structures which contain multi-byte integers, it's the
+ * caller's responsibility to perform appropriate byte order conversions.
*/
-static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
- __be32 *buf, int dir)
+int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
+ u32 len, __be32 *buf, int dir)
{
- u32 pos, start, end, offset, memoffset;
- u32 edc_size, mc_size;
- int ret = 0;
- __be32 *data;
+ u32 pos, offset, resid, memoffset;
+ u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base;
- /*
- * Argument sanity checks ...
+ /* Argument sanity checks ...
*/
- if ((addr & 0x3) || (len & 0x3))
+ if (addr & 0x3)
return -EINVAL;
- data = vmalloc(MEMWIN0_APERTURE);
- if (!data)
- return -ENOMEM;
+ /* It's convenient to be able to handle lengths which aren't a
+ * multiple of 32-bits because we often end up transferring files to
+ * the firmware. So we'll handle that by normalizing the length here
+ * and then handling any residual transfer at the end.
+ */
+ resid = len & 0x3;
+ len -= resid;
/* Offset into the region of memory which is being accessed
* MEM_EDC0 = 0
@@ -481,66 +468,98 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
/* Determine the PCIE_MEM_ACCESS_OFFSET */
addr = addr + memoffset;
- /*
- * The underlaying EDC/MC read routines read MEMWIN0_APERTURE bytes
- * at a time so we need to round down the start and round up the end.
- * We'll start copying out of the first line at (addr - start) a word
- * at a time.
+ /* Each PCI-E Memory Window is programmed with a window size -- or
+ * "aperture" -- which controls the granularity of its mapping onto
+ * adapter memory. We need to grab that aperture in order to know
+ * how to use the specified window. The window is also programmed
+ * with the base address of the Memory Window in BAR0's address
+ * space. For T4 this is an absolute PCI-E Bus Address. For T5
+ * the address is relative to BAR0.
*/
- start = addr & ~(MEMWIN0_APERTURE-1);
- end = (addr + len + MEMWIN0_APERTURE-1) & ~(MEMWIN0_APERTURE-1);
- offset = (addr - start)/sizeof(__be32);
+ mem_reg = t4_read_reg(adap,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN,
+ win));
+ mem_aperture = 1 << (GET_WINDOW(mem_reg) + 10);
+ mem_base = GET_PCIEOFST(mem_reg) << 10;
+ if (is_t4(adap->params.chip))
+ mem_base -= adap->t4_bar0;
+ win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
- for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
+ /* Calculate our initial PCI-E Memory Window Position and Offset into
+ * that Window.
+ */
+ pos = addr & ~(mem_aperture-1);
+ offset = addr - pos;
- /*
- * If we're writing, copy the data from the caller's memory
- * buffer
+ /* Set up initial PCI-E Memory Window to cover the start of our
+ * transfer. (Read it back to ensure that changes propagate before we
+ * attempt to use the new value.)
+ */
+ t4_write_reg(adap,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win),
+ pos | win_pf);
+ t4_read_reg(adap,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win));
+
+ /* Transfer data to/from the adapter as long as there's an integral
+ * number of 32-bit transfers to complete.
+ */
+ while (len > 0) {
+ if (dir == T4_MEMORY_READ)
+ *buf++ = (__force __be32) t4_read_reg(adap,
+ mem_base + offset);
+ else
+ t4_write_reg(adap, mem_base + offset,
+ (__force u32) *buf++);
+ offset += sizeof(__be32);
+ len -= sizeof(__be32);
+
+ /* If we've reached the end of our current window aperture,
+ * move the PCI-E Memory Window on to the next. Note that
+ * doing this here after "len" may be 0 allows us to set up
+ * the PCI-E Memory Window for a possible final residual
+ * transfer below ...
*/
- if (!dir) {
- /*
- * If we're doing a partial write, then we need to do
- * a read-modify-write ...
- */
- if (offset || len < MEMWIN0_APERTURE) {
- ret = t4_mem_win_rw(adap, pos, data, 1);
- if (ret)
- break;
- }
- while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
- len > 0) {
- data[offset++] = *buf++;
- len -= sizeof(__be32);
- }
+ if (offset == mem_aperture) {
+ pos += mem_aperture;
+ offset = 0;
+ t4_write_reg(adap,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET,
+ win), pos | win_pf);
+ t4_read_reg(adap,
+ PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET,
+ win));
}
-
- /*
- * Transfer a block of memory and bail if there's an error.
- */
- ret = t4_mem_win_rw(adap, pos, data, dir);
- if (ret)
- break;
-
- /*
- * If we're reading, copy the data into the caller's memory
- * buffer.
- */
- if (dir)
- while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
- len > 0) {
- *buf++ = data[offset++];
- len -= sizeof(__be32);
- }
}
- vfree(data);
- return ret;
-}
+ /* If the original transfer had a length which wasn't a multiple of
+ * 32-bits, now's where we need to finish off the transfer of the
+ * residual amount. The PCI-E Memory Window has already been moved
+ * above (if necessary) to cover this final transfer.
+ */
+ if (resid) {
+ union {
+ __be32 word;
+ char byte[4];
+ } last;
+ unsigned char *bp;
+ int i;
+
+ if (dir == T4_MEMORY_READ) {
+ last.word = (__force __be32) t4_read_reg(adap,
+ mem_base + offset);
+ for (bp = (unsigned char *)buf, i = resid; i < 4; i++)
+ bp[i] = last.byte[i];
+ } else {
+ last.word = *buf;
+ for (i = resid; i < 4; i++)
+ last.byte[i] = 0;
+ t4_write_reg(adap, mem_base + offset,
+ (__force u32) last.word);
+ }
+ }
-int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
- __be32 *buf)
-{
- return t4_memory_rw(adap, mtype, addr, len, buf, 0);
+ return 0;
}
#define EEPROM_STAT_ADDR 0x7bfc
@@ -1700,16 +1719,24 @@ static void mps_intr_handler(struct adapter *adapter)
*/
static void mem_intr_handler(struct adapter *adapter, int idx)
{
- static const char name[3][5] = { "EDC0", "EDC1", "MC" };
+ static const char name[4][7] = { "EDC0", "EDC1", "MC/MC0", "MC1" };
unsigned int addr, cnt_addr, v;
if (idx <= MEM_EDC1) {
addr = EDC_REG(EDC_INT_CAUSE, idx);
cnt_addr = EDC_REG(EDC_ECC_STATUS, idx);
+ } else if (idx == MEM_MC) {
+ if (is_t4(adapter->params.chip)) {
+ addr = MC_INT_CAUSE;
+ cnt_addr = MC_ECC_STATUS;
+ } else {
+ addr = MC_P_INT_CAUSE;
+ cnt_addr = MC_P_ECC_STATUS;
+ }
} else {
- addr = MC_INT_CAUSE;
- cnt_addr = MC_ECC_STATUS;
+ addr = MC_REG(MC_P_INT_CAUSE, 1);
+ cnt_addr = MC_REG(MC_P_ECC_STATUS, 1);
}
v = t4_read_reg(adapter, addr) & MEM_INT_MASK;
@@ -1873,6 +1900,8 @@ int t4_slow_intr_handler(struct adapter *adapter)
pcie_intr_handler(adapter);
if (cause & MC)
mem_intr_handler(adapter, MEM_MC);
+ if (!is_t4(adapter->params.chip) && (cause & MC1))
+ mem_intr_handler(adapter, MEM_MC1);
if (cause & EDC0)
mem_intr_handler(adapter, MEM_EDC0);
if (cause & EDC1)
@@ -2505,39 +2534,6 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
}
/**
- * t4_mem_win_read_len - read memory through PCIE memory window
- * @adap: the adapter
- * @addr: address of first byte requested aligned on 32b.
- * @data: len bytes to hold the data read
- * @len: amount of data to read from window. Must be <=
- * MEMWIN0_APERATURE after adjusting for 16B for T4 and
- * 128B for T5 alignment requirements of the the memory window.
- *
- * Read len bytes of data from MC starting at @addr.
- */
-int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
-{
- int i, off;
- u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
-
- /* Align on a 2KB boundary.
- */
- off = addr & MEMWIN0_APERTURE;
- if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
- return -EINVAL;
-
- t4_write_reg(adap, PCIE_MEM_ACCESS_OFFSET,
- (addr & ~MEMWIN0_APERTURE) | win_pf);
- t4_read_reg(adap, PCIE_MEM_ACCESS_OFFSET);
-
- for (i = 0; i < len; i += 4)
- *data++ = (__force __be32) t4_read_reg(adap,
- (MEMWIN0_BASE + off + i));
-
- return 0;
-}
-
-/**
* t4_mdio_rd - read a PHY register through MDIO
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -3175,6 +3171,46 @@ int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
}
/**
+ * t4_set_params_nosleep - sets FW or device parameters
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @pf: the PF
+ * @vf: the VF
+ * @nparams: the number of parameters
+ * @params: the parameter names
+ * @val: the parameter values
+ *
+ * Does not ever sleep
+ * Sets the value of FW or device parameters. Up to 7 parameters can be
+ * specified at once.
+ */
+int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
+ unsigned int pf, unsigned int vf,
+ unsigned int nparams, const u32 *params,
+ const u32 *val)
+{
+ struct fw_params_cmd c;
+ __be32 *p = &c.param[0].mnem;
+
+ if (nparams > 7)
+ return -EINVAL;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
+ FW_CMD_REQUEST | FW_CMD_WRITE |
+ FW_PARAMS_CMD_PFN(pf) |
+ FW_PARAMS_CMD_VFN(vf));
+ c.retval_len16 = cpu_to_be32(FW_LEN16(c));
+
+ while (nparams--) {
+ *p++ = cpu_to_be32(*params++);
+ *p++ = cpu_to_be32(*val++);
+ }
+
+ return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/**
* t4_set_params - sets FW or device parameters
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -3499,6 +3535,33 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
}
/**
+ * t4_enable_vi_params - enable/disable a virtual interface
+ * @adap: the adapter
+ * @mbox: mailbox to use for the FW command
+ * @viid: the VI id
+ * @rx_en: 1=enable Rx, 0=disable Rx
+ * @tx_en: 1=enable Tx, 0=disable Tx
+ * @dcb_en: 1=enable delivery of Data Center Bridging messages.
+ *
+ * Enables/disables a virtual interface. Note that setting DCB Enable
+ * only makes sense when enabling a Virtual Interface ...
+ */
+int t4_enable_vi_params(struct adapter *adap, unsigned int mbox,
+ unsigned int viid, bool rx_en, bool tx_en, bool dcb_en)
+{
+ struct fw_vi_enable_cmd c;
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
+ FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
+
+ c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
+ FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c) |
+ FW_VI_ENABLE_CMD_DCB_INFO(dcb_en));
+ return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
+}
+
+/**
* t4_enable_vi - enable/disable a virtual interface
* @adap: the adapter
* @mbox: mailbox to use for the FW command
@@ -3511,14 +3574,7 @@ int t4_set_addr_hash(struct adapter *adap, unsigned int mbox, unsigned int viid,
int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid,
bool rx_en, bool tx_en)
{
- struct fw_vi_enable_cmd c;
-
- memset(&c, 0, sizeof(c));
- c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
- FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
- c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
- FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c));
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
+ return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0);
}
/**
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 71b799b5b0f4..35e3d8e32881 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 973eb11aa98a..52e08103f221 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -75,6 +75,7 @@ enum {
CPL_RX_DATA_DDP = 0x42,
CPL_PASS_ACCEPT_REQ = 0x44,
CPL_TRACE_PKT_T5 = 0x48,
+ CPL_RX_ISCSI_DDP = 0x49,
CPL_RDMA_READ_REQ = 0x60,
@@ -86,6 +87,7 @@ enum {
CPL_SGE_EGR_UPDATE = 0xA5,
CPL_TRACE_PKT = 0xB0,
+ CPL_ISCSI_DATA = 0xB2,
CPL_FW4_MSG = 0xC0,
CPL_FW4_PLD = 0xC1,
@@ -270,12 +272,15 @@ struct cpl_pass_accept_rpl {
#define RX_COALESCE_VALID(x) ((x) << 11)
#define RX_COALESCE(x) ((x) << 12)
#define PACE(x) ((x) << 16)
+#define RX_FC_VALID ((1U) << 19)
+#define RX_FC_DISABLE ((1U) << 20)
#define TX_QUEUE(x) ((x) << 23)
#define RX_CHANNEL(x) ((x) << 26)
#define CCTRL_ECN(x) ((x) << 27)
#define WND_SCALE_EN(x) ((x) << 28)
#define TSTAMPS_EN(x) ((x) << 29)
#define SACK_EN(x) ((x) << 30)
+#define T5_OPT_2_VALID ((1U) << 31)
__be64 opt0;
};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 225ad8a5722d..e3146e83df20 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -251,6 +251,12 @@
#define V_NOCOALESCE(x) ((x) << S_NOCOALESCE)
#define F_NOCOALESCE V_NOCOALESCE(1U)
+#define SGE_TIMESTAMP_LO 0x1098
+#define SGE_TIMESTAMP_HI 0x109c
+#define S_TSVAL 0
+#define M_TSVAL 0xfffffffU
+#define GET_TSVAL(x) (((x) >> S_TSVAL) & M_TSVAL)
+
#define SGE_TIMER_VALUE_0_AND_1 0x10b8
#define TIMERVALUE0_MASK 0xffff0000U
#define TIMERVALUE0_SHIFT 16
@@ -387,6 +393,8 @@
#define MSTGRPPERR 0x00000001U
#define PCIE_NONFAT_ERR 0x3010
+#define PCIE_CFG_SPACE_REQ 0x3060
+#define PCIE_CFG_SPACE_DATA 0x3064
#define PCIE_MEM_ACCESS_BASE_WIN 0x3068
#define S_PCIEOFST 10
#define M_PCIEOFST 0x3fffffU
@@ -398,7 +406,11 @@
#define WINDOW_MASK 0x000000ffU
#define WINDOW_SHIFT 0
#define WINDOW(x) ((x) << WINDOW_SHIFT)
+#define GET_WINDOW(x) (((x) >> WINDOW_SHIFT) & WINDOW_MASK)
#define PCIE_MEM_ACCESS_OFFSET 0x306c
+#define ENABLE (1U << 30)
+#define FUNCTION(x) ((x) << 12)
+#define F_LOCALCFG (1U << 28)
#define S_PFNUM 0
#define V_PFNUM(x) ((x) << S_PFNUM)
@@ -436,11 +448,13 @@
#define TDUE 0x00010000U
#define MC_INT_CAUSE 0x7518
+#define MC_P_INT_CAUSE 0x41318
#define ECC_UE_INT_CAUSE 0x00000004U
#define ECC_CE_INT_CAUSE 0x00000002U
#define PERR_INT_CAUSE 0x00000001U
#define MC_ECC_STATUS 0x751c
+#define MC_P_ECC_STATUS 0x4131c
#define ECC_CECNT_MASK 0xffff0000U
#define ECC_CECNT_SHIFT 16
#define ECC_CECNT(x) ((x) << ECC_CECNT_SHIFT)
@@ -1089,6 +1103,7 @@
#define I2CM 0x00000002U
#define CIM 0x00000001U
+#define MC1 0x31
#define PL_INT_ENABLE 0x19410
#define PL_INT_MAP0 0x19414
#define PL_RST 0x19428
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 9cc973fbcf26..0549170d7e2e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Chelsio T4 Ethernet driver for Linux.
*
- * Copyright (c) 2009-2010 Chelsio Communications, Inc. All rights reserved.
+ * Copyright (c) 2009-2014 Chelsio Communications, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -46,9 +46,11 @@ enum fw_retval {
FW_EFAULT = 14, /* bad address; fw bad */
FW_EBUSY = 16, /* resource busy */
FW_EEXIST = 17, /* file exists */
+ FW_ENODEV = 19, /* no such device */
FW_EINVAL = 22, /* invalid argument */
FW_ENOSPC = 28, /* no space left on device */
FW_ENOSYS = 38, /* functionality not implemented */
+ FW_ENODATA = 61, /* no data available */
FW_EPROTO = 71, /* protocol error */
FW_EADDRINUSE = 98, /* address already in use */
FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */
@@ -932,6 +934,8 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
FW_PARAMS_PARAM_DEV_CF = 0x0D,
+ FW_PARAMS_PARAM_DEV_MAXORDIRD_QP = 0x13, /* max supported QP IRD/ORD */
+ FW_PARAMS_PARAM_DEV_MAXIRD_ADAPTER = 0x14, /* max supported adap IRD */
FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
};
@@ -989,6 +993,7 @@ enum fw_params_param_dmaq {
FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10,
FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11,
FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12,
+ FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13,
};
#define FW_PARAMS_MNEM(x) ((x) << 24)
@@ -1422,6 +1427,7 @@ struct fw_vi_enable_cmd {
#define FW_VI_ENABLE_CMD_VIID(x) ((x) << 0)
#define FW_VI_ENABLE_CMD_IEN(x) ((x) << 31)
#define FW_VI_ENABLE_CMD_EEN(x) ((x) << 30)
+#define FW_VI_ENABLE_CMD_DCB_INFO(x) ((x) << 28)
#define FW_VI_ENABLE_CMD_LED (1U << 29)
/* VI VF stats offset definitions */
@@ -1594,6 +1600,9 @@ enum fw_port_action {
FW_PORT_ACTION_GET_PORT_INFO = 0x0003,
FW_PORT_ACTION_L2_PPP_CFG = 0x0004,
FW_PORT_ACTION_L2_DCB_CFG = 0x0005,
+ FW_PORT_ACTION_DCB_READ_TRANS = 0x0006,
+ FW_PORT_ACTION_DCB_READ_RECV = 0x0007,
+ FW_PORT_ACTION_DCB_READ_DET = 0x0008,
FW_PORT_ACTION_LOW_PWR_TO_NORMAL = 0x0010,
FW_PORT_ACTION_L1_LOW_PWR_EN = 0x0011,
FW_PORT_ACTION_L2_WOL_MODE_EN = 0x0012,
@@ -1620,6 +1629,14 @@ enum fw_port_l2cfg_ctlbf {
FW_PORT_L2_CTLBF_TXIPG = 0x20
};
+enum fw_port_dcb_versions {
+ FW_PORT_DCB_VER_UNKNOWN,
+ FW_PORT_DCB_VER_CEE1D0,
+ FW_PORT_DCB_VER_CEE1D01,
+ FW_PORT_DCB_VER_IEEE,
+ FW_PORT_DCB_VER_AUTO = 7
+};
+
enum fw_port_dcb_cfg {
FW_PORT_DCB_CFG_PG = 0x01,
FW_PORT_DCB_CFG_PFC = 0x02,
@@ -1637,6 +1654,14 @@ enum fw_port_dcb_type {
FW_PORT_DCB_TYPE_PRIORATE = 0x02,
FW_PORT_DCB_TYPE_PFC = 0x03,
FW_PORT_DCB_TYPE_APP_ID = 0x04,
+ FW_PORT_DCB_TYPE_CONTROL = 0x05,
+};
+
+enum fw_port_dcb_feature_state {
+ FW_PORT_DCB_FEATURE_STATE_PENDING = 0x0,
+ FW_PORT_DCB_FEATURE_STATE_SUCCESS = 0x1,
+ FW_PORT_DCB_FEATURE_STATE_ERROR = 0x2,
+ FW_PORT_DCB_FEATURE_STATE_TIMEOUT = 0x3,
};
struct fw_port_cmd {
@@ -1648,9 +1673,11 @@ struct fw_port_cmd {
__be32 r;
} l1cfg;
struct fw_port_l2cfg {
- __be16 ctlbf_to_ivlan0;
+ __u8 ctlbf;
+ __u8 ovlan3_to_ivlan0;
__be16 ivlantype;
- __be32 txipg_pkd;
+ __be16 txipg_force_pinfo;
+ __be16 mtu;
__be16 ovlan0mask;
__be16 ovlan0type;
__be16 ovlan1mask;
@@ -1666,24 +1693,61 @@ struct fw_port_cmd {
__be16 acap;
__be16 mtu;
__u8 cbllen;
- __u8 r9;
- __be32 r10;
- __be64 r11;
+ __u8 auxlinfo;
+ __u8 dcbxdis_pkd;
+ __u8 r8_lo[3];
+ __be64 r9;
} info;
- struct fw_port_ppp {
- __be32 pppen_to_ncsich;
- __be32 r11;
- } ppp;
- struct fw_port_dcb {
- __be16 cfg;
- u8 up_map;
- u8 sf_cfgrc;
- __be16 prot_ix;
- u8 pe7_to_pe0;
- u8 numTCPFCs;
- __be32 pgid0_to_pgid7;
- __be32 numTCs_oui;
- u8 pgpc[8];
+ struct fw_port_diags {
+ __u8 diagop;
+ __u8 r[3];
+ __be32 diagval;
+ } diags;
+ union fw_port_dcb {
+ struct fw_port_dcb_pgid {
+ __u8 type;
+ __u8 apply_pkd;
+ __u8 r10_lo[2];
+ __be32 pgid;
+ __be64 r11;
+ } pgid;
+ struct fw_port_dcb_pgrate {
+ __u8 type;
+ __u8 apply_pkd;
+ __u8 r10_lo[5];
+ __u8 num_tcs_supported;
+ __u8 pgrate[8];
+ __u8 tsa[8];
+ } pgrate;
+ struct fw_port_dcb_priorate {
+ __u8 type;
+ __u8 apply_pkd;
+ __u8 r10_lo[6];
+ __u8 strict_priorate[8];
+ } priorate;
+ struct fw_port_dcb_pfc {
+ __u8 type;
+ __u8 pfcen;
+ __u8 r10[5];
+ __u8 max_pfc_tcs;
+ __be64 r11;
+ } pfc;
+ struct fw_port_app_priority {
+ __u8 type;
+ __u8 r10[2];
+ __u8 idx;
+ __u8 user_prio_map;
+ __u8 sel_field;
+ __be16 protocolid;
+ __be64 r12;
+ } app_priority;
+ struct fw_port_dcb_control {
+ __u8 type;
+ __u8 all_syncd_pkd;
+ __be16 dcb_version_to_app_state;
+ __be32 r11;
+ __be64 r12;
+ } control;
} dcb;
} u;
};
@@ -1720,6 +1784,11 @@ struct fw_port_cmd {
#define FW_PORT_CMD_MODTYPE_MASK 0x1f
#define FW_PORT_CMD_MODTYPE_GET(x) (((x) >> 0) & FW_PORT_CMD_MODTYPE_MASK)
+#define FW_PORT_CMD_DCBXDIS (1U << 7)
+#define FW_PORT_CMD_APPLY (1U << 7)
+#define FW_PORT_CMD_ALL_SYNCD (1U << 7)
+#define FW_PORT_CMD_DCB_VERSION_GET(x) (((x) >> 8) & 0xf)
+
#define FW_PORT_CMD_PPPEN(x) ((x) << 31)
#define FW_PORT_CMD_TPSRC(x) ((x) << 28)
#define FW_PORT_CMD_NCSISRC(x) ((x) << 24)
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
index ff1cdd1788b5..2102a4c91737 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -2876,24 +2876,24 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
if (!adapter)
return;
- /*
- * Disable all Virtual Interfaces. This will shut down the
+ /* Disable all Virtual Interfaces. This will shut down the
* delivery of all ingress packets into the chip for these
* Virtual Interfaces.
*/
- for_each_port(adapter, pidx) {
- struct net_device *netdev;
- struct port_info *pi;
-
- if (!test_bit(pidx, &adapter->registered_device_map))
- continue;
-
- netdev = adapter->port[pidx];
- if (!netdev)
- continue;
+ for_each_port(adapter, pidx)
+ if (test_bit(pidx, &adapter->registered_device_map))
+ unregister_netdev(adapter->port[pidx]);
- pi = netdev_priv(netdev);
- t4vf_enable_vi(adapter, pi->viid, false, false);
+ /* Free up all Queues which will prevent further DMA and
+ * Interrupts allowing various internal pathways to drain.
+ */
+ t4vf_sge_stop(adapter);
+ if (adapter->flags & USING_MSIX) {
+ pci_disable_msix(adapter->pdev);
+ adapter->flags &= ~USING_MSIX;
+ } else if (adapter->flags & USING_MSI) {
+ pci_disable_msi(adapter->pdev);
+ adapter->flags &= ~USING_MSI;
}
/*
@@ -2901,6 +2901,7 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
* Interrupts allowing various internal pathways to drain.
*/
t4vf_free_sge_resources(adapter);
+ pci_set_drvdata(pdev, NULL);
}
/*
@@ -2909,7 +2910,7 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
#define CH_DEVICE(devid, idx) \
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx }
-static DEFINE_PCI_DEVICE_TABLE(cxgb4vf_pci_tbl) = {
+static const struct pci_device_id cxgb4vf_pci_tbl[] = {
CH_DEVICE(0xb000, 0), /* PE10K FPGA */
CH_DEVICE(0x4800, 0), /* T440-dbg */
CH_DEVICE(0x4801, 0), /* T420-cr */
@@ -2924,6 +2925,15 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4vf_pci_tbl) = {
CH_DEVICE(0x480a, 0), /* T404-bt */
CH_DEVICE(0x480d, 0), /* T480-cr */
CH_DEVICE(0x480e, 0), /* T440-lp-cr */
+ CH_DEVICE(0x4880, 0),
+ CH_DEVICE(0x4880, 1),
+ CH_DEVICE(0x4880, 2),
+ CH_DEVICE(0x4880, 3),
+ CH_DEVICE(0x4880, 4),
+ CH_DEVICE(0x4880, 5),
+ CH_DEVICE(0x4880, 6),
+ CH_DEVICE(0x4880, 7),
+ CH_DEVICE(0x4880, 8),
CH_DEVICE(0x5800, 0), /* T580-dbg */
CH_DEVICE(0x5801, 0), /* T520-cr */
CH_DEVICE(0x5802, 0), /* T522-cr */
diff --git a/drivers/net/ethernet/cirrus/cs89x0.c b/drivers/net/ethernet/cirrus/cs89x0.c
index fe84fbabc0d4..9823a0ea7937 100644
--- a/drivers/net/ethernet/cirrus/cs89x0.c
+++ b/drivers/net/ethernet/cirrus/cs89x0.c
@@ -145,7 +145,6 @@ struct net_local {
int force; /* force various values; see FORCE* above. */
spinlock_t lock;
void __iomem *virt_addr;/* CS89x0 virtual address. */
- unsigned long size; /* Length of CS89x0 memory region. */
#if ALLOW_DMA
int use_dma; /* Flag: we're using dma */
int dma; /* DMA channel */
@@ -1854,41 +1853,29 @@ static int __init cs89x0_platform_probe(struct platform_device *pdev)
lp = netdev_priv(dev);
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->irq = platform_get_irq(pdev, 0);
- if (mem_res == NULL || dev->irq <= 0) {
- dev_warn(&dev->dev, "memory/interrupt resource missing\n");
+ if (dev->irq <= 0) {
+ dev_warn(&dev->dev, "interrupt resource missing\n");
err = -ENXIO;
goto free;
}
- lp->size = resource_size(mem_res);
- if (!request_mem_region(mem_res->start, lp->size, DRV_NAME)) {
- dev_warn(&dev->dev, "request_mem_region() failed\n");
- err = -EBUSY;
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ virt_addr = devm_ioremap_resource(&pdev->dev, mem_res);
+ if (IS_ERR(virt_addr)) {
+ err = PTR_ERR(virt_addr);
goto free;
}
- virt_addr = ioremap(mem_res->start, lp->size);
- if (!virt_addr) {
- dev_warn(&dev->dev, "ioremap() failed\n");
- err = -ENOMEM;
- goto release;
- }
-
err = cs89x0_probe1(dev, virt_addr, 0);
if (err) {
dev_warn(&dev->dev, "no cs8900 or cs8920 detected\n");
- goto unmap;
+ goto free;
}
platform_set_drvdata(pdev, dev);
return 0;
-unmap:
- iounmap(virt_addr);
-release:
- release_mem_region(mem_res->start, lp->size);
free:
free_netdev(dev);
return err;
@@ -1897,17 +1884,12 @@ free:
static int cs89x0_platform_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
- struct net_local *lp = netdev_priv(dev);
- struct resource *mem_res;
/* This platform_get_resource() call will not return NULL, because
* the same call in cs89x0_platform_probe() has returned a non NULL
* value.
*/
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
unregister_netdev(dev);
- iounmap(lp->virt_addr);
- release_mem_region(mem_res->start, lp->size);
free_netdev(dev);
return 0;
}
diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/ethernet/cisco/enic/Makefile
index 239e1e46545d..aadcaf7876ce 100644
--- a/drivers/net/ethernet/cisco/enic/Makefile
+++ b/drivers/net/ethernet/cisco/enic/Makefile
@@ -2,5 +2,5 @@ obj-$(CONFIG_ENIC) := enic.o
enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \
- enic_ethtool.o enic_api.o
+ enic_ethtool.o enic_api.o enic_clsf.o
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 14f465f239d6..962510f391df 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -33,7 +33,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.50"
+#define DRV_VERSION "2.1.1.67"
#define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
@@ -99,6 +99,41 @@ struct enic_port_profile {
u8 mac_addr[ETH_ALEN];
};
+/* enic_rfs_fltr_node - rfs filter node in hash table
+ * @@keys: IPv4 5 tuple
+ * @flow_id: flow_id of clsf filter provided by kernel
+ * @fltr_id: filter id of clsf filter returned by adaptor
+ * @rq_id: desired rq index
+ * @node: hlist_node
+ */
+struct enic_rfs_fltr_node {
+ struct flow_keys keys;
+ u32 flow_id;
+ u16 fltr_id;
+ u16 rq_id;
+ struct hlist_node node;
+};
+
+/* enic_rfs_flw_tbl - rfs flow table
+ * @max: Maximum number of filters vNIC supports
+ * @free: Number of free filters available
+ * @toclean: hash table index to clean next
+ * @ht_head: hash table list head
+ * @lock: spin lock
+ * @rfs_may_expire: timer function for enic_rps_may_expire_flow
+ */
+struct enic_rfs_flw_tbl {
+ u16 max;
+ int free;
+
+#define ENIC_RFS_FLW_BITSHIFT (10)
+#define ENIC_RFS_FLW_MASK ((1 << ENIC_RFS_FLW_BITSHIFT) - 1)
+ u16 toclean:ENIC_RFS_FLW_BITSHIFT;
+ struct hlist_head ht_head[1 << ENIC_RFS_FLW_BITSHIFT];
+ spinlock_t lock;
+ struct timer_list rfs_may_expire;
+};
+
/* Per-instance private data structure */
struct enic {
struct net_device *netdev;
@@ -140,7 +175,7 @@ struct enic {
unsigned int rq_count;
u64 rq_truncated_pkts;
u64 rq_bad_fcs;
- struct napi_struct napi[ENIC_RQ_MAX];
+ struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX];
/* interrupt resource cache line section */
____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
@@ -150,6 +185,7 @@ struct enic {
/* completion queue cache line section */
____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX];
unsigned int cq_count;
+ struct enic_rfs_flw_tbl rfs_h;
};
static inline struct device *enic_get_dev(struct enic *enic)
diff --git a/drivers/net/ethernet/cisco/enic/enic_api.c b/drivers/net/ethernet/cisco/enic/enic_api.c
index e13efbdaa2ed..b161f24522b8 100644
--- a/drivers/net/ethernet/cisco/enic/enic_api.c
+++ b/drivers/net/ethernet/cisco/enic/enic_api.c
@@ -34,13 +34,13 @@ int enic_api_devcmd_proxy_by_index(struct net_device *netdev, int vf,
struct vnic_dev *vdev = enic->vdev;
spin_lock(&enic->enic_api_lock);
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
vnic_dev_cmd_proxy_by_index_start(vdev, vf);
err = vnic_dev_cmd(vdev, cmd, a0, a1, wait);
vnic_dev_cmd_proxy_end(vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
spin_unlock(&enic->enic_api_lock);
return err;
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c
new file mode 100644
index 000000000000..69dfd3c9e529
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c
@@ -0,0 +1,284 @@
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_link.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <net/flow_keys.h>
+#include "enic_res.h"
+#include "enic_clsf.h"
+
+/* enic_addfltr_5t - Add ipv4 5tuple filter
+ * @enic: enic struct of vnic
+ * @keys: flow_keys of ipv4 5tuple
+ * @rq: rq number to steer to
+ *
+ * This function returns filter_id(hardware_id) of the filter
+ * added. In case of error it returns an negative number.
+ */
+int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
+{
+ int res;
+ struct filter data;
+
+ switch (keys->ip_proto) {
+ case IPPROTO_TCP:
+ data.u.ipv4.protocol = PROTO_TCP;
+ break;
+ case IPPROTO_UDP:
+ data.u.ipv4.protocol = PROTO_UDP;
+ break;
+ default:
+ return -EPROTONOSUPPORT;
+ };
+ data.type = FILTER_IPV4_5TUPLE;
+ data.u.ipv4.src_addr = ntohl(keys->src);
+ data.u.ipv4.dst_addr = ntohl(keys->dst);
+ data.u.ipv4.src_port = ntohs(keys->port16[0]);
+ data.u.ipv4.dst_port = ntohs(keys->port16[1]);
+ data.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
+
+ spin_lock_bh(&enic->devcmd_lock);
+ res = vnic_dev_classifier(enic->vdev, CLSF_ADD, &rq, &data);
+ spin_unlock_bh(&enic->devcmd_lock);
+ res = (res == 0) ? rq : res;
+
+ return res;
+}
+
+/* enic_delfltr - Delete clsf filter
+ * @enic: enic struct of vnic
+ * @filter_id: filter_is(hardware_id) of filter to be deleted
+ *
+ * This function returns zero in case of success, negative number incase of
+ * error.
+ */
+int enic_delfltr(struct enic *enic, u16 filter_id)
+{
+ int ret;
+
+ spin_lock_bh(&enic->devcmd_lock);
+ ret = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL);
+ spin_unlock_bh(&enic->devcmd_lock);
+
+ return ret;
+}
+
+/* enic_rfs_flw_tbl_init - initialize enic->rfs_h members
+ * @enic: enic data
+ */
+void enic_rfs_flw_tbl_init(struct enic *enic)
+{
+ int i;
+
+ spin_lock_init(&enic->rfs_h.lock);
+ for (i = 0; i <= ENIC_RFS_FLW_MASK; i++)
+ INIT_HLIST_HEAD(&enic->rfs_h.ht_head[i]);
+ enic->rfs_h.max = enic->config.num_arfs;
+ enic->rfs_h.free = enic->rfs_h.max;
+ enic->rfs_h.toclean = 0;
+ enic_rfs_timer_start(enic);
+}
+
+void enic_rfs_flw_tbl_free(struct enic *enic)
+{
+ int i;
+
+ enic_rfs_timer_stop(enic);
+ spin_lock(&enic->rfs_h.lock);
+ enic->rfs_h.free = 0;
+ for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
+ struct hlist_head *hhead;
+ struct hlist_node *tmp;
+ struct enic_rfs_fltr_node *n;
+
+ hhead = &enic->rfs_h.ht_head[i];
+ hlist_for_each_entry_safe(n, tmp, hhead, node) {
+ enic_delfltr(enic, n->fltr_id);
+ hlist_del(&n->node);
+ kfree(n);
+ }
+ }
+ spin_unlock(&enic->rfs_h.lock);
+}
+
+struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id)
+{
+ int i;
+
+ for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
+ struct hlist_head *hhead;
+ struct hlist_node *tmp;
+ struct enic_rfs_fltr_node *n;
+
+ hhead = &enic->rfs_h.ht_head[i];
+ hlist_for_each_entry_safe(n, tmp, hhead, node)
+ if (n->fltr_id == fltr_id)
+ return n;
+ }
+
+ return NULL;
+}
+
+#ifdef CONFIG_RFS_ACCEL
+void enic_flow_may_expire(unsigned long data)
+{
+ struct enic *enic = (struct enic *)data;
+ bool res;
+ int j;
+
+ spin_lock(&enic->rfs_h.lock);
+ for (j = 0; j < ENIC_CLSF_EXPIRE_COUNT; j++) {
+ struct hlist_head *hhead;
+ struct hlist_node *tmp;
+ struct enic_rfs_fltr_node *n;
+
+ hhead = &enic->rfs_h.ht_head[enic->rfs_h.toclean++];
+ hlist_for_each_entry_safe(n, tmp, hhead, node) {
+ res = rps_may_expire_flow(enic->netdev, n->rq_id,
+ n->flow_id, n->fltr_id);
+ if (res) {
+ res = enic_delfltr(enic, n->fltr_id);
+ if (unlikely(res))
+ continue;
+ hlist_del(&n->node);
+ kfree(n);
+ enic->rfs_h.free++;
+ }
+ }
+ }
+ spin_unlock(&enic->rfs_h.lock);
+ mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
+}
+
+static struct enic_rfs_fltr_node *htbl_key_search(struct hlist_head *h,
+ struct flow_keys *k)
+{
+ struct enic_rfs_fltr_node *tpos;
+
+ hlist_for_each_entry(tpos, h, node)
+ if (tpos->keys.src == k->src &&
+ tpos->keys.dst == k->dst &&
+ tpos->keys.ports == k->ports &&
+ tpos->keys.ip_proto == k->ip_proto &&
+ tpos->keys.n_proto == k->n_proto)
+ return tpos;
+ return NULL;
+}
+
+int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id)
+{
+ struct flow_keys keys;
+ struct enic_rfs_fltr_node *n;
+ struct enic *enic;
+ u16 tbl_idx;
+ int res, i;
+
+ enic = netdev_priv(dev);
+ res = skb_flow_dissect(skb, &keys);
+ if (!res || keys.n_proto != htons(ETH_P_IP) ||
+ (keys.ip_proto != IPPROTO_TCP && keys.ip_proto != IPPROTO_UDP))
+ return -EPROTONOSUPPORT;
+
+ tbl_idx = skb_get_hash_raw(skb) & ENIC_RFS_FLW_MASK;
+ spin_lock(&enic->rfs_h.lock);
+ n = htbl_key_search(&enic->rfs_h.ht_head[tbl_idx], &keys);
+
+ if (n) { /* entry already present */
+ if (rxq_index == n->rq_id) {
+ res = -EEXIST;
+ goto ret_unlock;
+ }
+
+ /* desired rq changed for the flow, we need to delete
+ * old fltr and add new one
+ *
+ * The moment we delete the fltr, the upcoming pkts
+ * are put it default rq based on rss. When we add
+ * new filter, upcoming pkts are put in desired queue.
+ * This could cause ooo pkts.
+ *
+ * Lets 1st try adding new fltr and then del old one.
+ */
+ i = --enic->rfs_h.free;
+ /* clsf tbl is full, we have to del old fltr first*/
+ if (unlikely(i < 0)) {
+ enic->rfs_h.free++;
+ res = enic_delfltr(enic, n->fltr_id);
+ if (unlikely(res < 0))
+ goto ret_unlock;
+ res = enic_addfltr_5t(enic, &keys, rxq_index);
+ if (res < 0) {
+ hlist_del(&n->node);
+ enic->rfs_h.free++;
+ goto ret_unlock;
+ }
+ /* add new fltr 1st then del old fltr */
+ } else {
+ int ret;
+
+ res = enic_addfltr_5t(enic, &keys, rxq_index);
+ if (res < 0) {
+ enic->rfs_h.free++;
+ goto ret_unlock;
+ }
+ ret = enic_delfltr(enic, n->fltr_id);
+ /* deleting old fltr failed. Add old fltr to list.
+ * enic_flow_may_expire() will try to delete it later.
+ */
+ if (unlikely(ret < 0)) {
+ struct enic_rfs_fltr_node *d;
+ struct hlist_head *head;
+
+ head = &enic->rfs_h.ht_head[tbl_idx];
+ d = kmalloc(sizeof(*d), GFP_ATOMIC);
+ if (d) {
+ d->fltr_id = n->fltr_id;
+ INIT_HLIST_NODE(&d->node);
+ hlist_add_head(&d->node, head);
+ }
+ } else {
+ enic->rfs_h.free++;
+ }
+ }
+ n->rq_id = rxq_index;
+ n->fltr_id = res;
+ n->flow_id = flow_id;
+ /* entry not present */
+ } else {
+ i = --enic->rfs_h.free;
+ if (i <= 0) {
+ enic->rfs_h.free++;
+ res = -EBUSY;
+ goto ret_unlock;
+ }
+
+ n = kmalloc(sizeof(*n), GFP_ATOMIC);
+ if (!n) {
+ res = -ENOMEM;
+ enic->rfs_h.free++;
+ goto ret_unlock;
+ }
+
+ res = enic_addfltr_5t(enic, &keys, rxq_index);
+ if (res < 0) {
+ kfree(n);
+ enic->rfs_h.free++;
+ goto ret_unlock;
+ }
+ n->rq_id = rxq_index;
+ n->fltr_id = res;
+ n->flow_id = flow_id;
+ n->keys = keys;
+ INIT_HLIST_NODE(&n->node);
+ hlist_add_head(&n->node, &enic->rfs_h.ht_head[tbl_idx]);
+ }
+
+ret_unlock:
+ spin_unlock(&enic->rfs_h.lock);
+ return res;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.h b/drivers/net/ethernet/cisco/enic/enic_clsf.h
new file mode 100644
index 000000000000..6aa9f89d073b
--- /dev/null
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.h
@@ -0,0 +1,37 @@
+#ifndef _ENIC_CLSF_H_
+#define _ENIC_CLSF_H_
+
+#include "vnic_dev.h"
+#include "enic.h"
+
+#define ENIC_CLSF_EXPIRE_COUNT 128
+
+int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq);
+int enic_delfltr(struct enic *enic, u16 filter_id);
+void enic_rfs_flw_tbl_init(struct enic *enic);
+void enic_rfs_flw_tbl_free(struct enic *enic);
+struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id);
+
+#ifdef CONFIG_RFS_ACCEL
+int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id);
+void enic_flow_may_expire(unsigned long data);
+
+static inline void enic_rfs_timer_start(struct enic *enic)
+{
+ init_timer(&enic->rfs_h.rfs_may_expire);
+ enic->rfs_h.rfs_may_expire.function = enic_flow_may_expire;
+ enic->rfs_h.rfs_may_expire.data = (unsigned long)enic;
+ mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
+}
+
+static inline void enic_rfs_timer_stop(struct enic *enic)
+{
+ del_timer_sync(&enic->rfs_h.rfs_may_expire);
+}
+#else
+static inline void enic_rfs_timer_start(struct enic *enic) {}
+static inline void enic_rfs_timer_stop(struct enic *enic) {}
+#endif /* CONFIG_RFS_ACCEL */
+
+#endif /* _ENIC_CLSF_H_ */
diff --git a/drivers/net/ethernet/cisco/enic/enic_dev.c b/drivers/net/ethernet/cisco/enic/enic_dev.c
index 3e27df522847..87ddc44b590e 100644
--- a/drivers/net/ethernet/cisco/enic/enic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/enic_dev.c
@@ -29,9 +29,9 @@ int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_fw_info(enic->vdev, fw_info);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -40,9 +40,9 @@ int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_stats_dump(enic->vdev, vstats);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -54,9 +54,9 @@ int enic_dev_add_station_addr(struct enic *enic)
if (!is_valid_ether_addr(enic->netdev->dev_addr))
return -EADDRNOTAVAIL;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -68,9 +68,9 @@ int enic_dev_del_station_addr(struct enic *enic)
if (!is_valid_ether_addr(enic->netdev->dev_addr))
return -EADDRNOTAVAIL;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -80,10 +80,10 @@ int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_packet_filter(enic->vdev, directed,
multicast, broadcast, promisc, allmulti);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -92,9 +92,9 @@ int enic_dev_add_addr(struct enic *enic, const u8 *addr)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_add_addr(enic->vdev, addr);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -103,9 +103,9 @@ int enic_dev_del_addr(struct enic *enic, const u8 *addr)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_del_addr(enic->vdev, addr);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -114,9 +114,9 @@ int enic_dev_notify_unset(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_notify_unset(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -125,9 +125,9 @@ int enic_dev_hang_notify(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_hang_notify(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -136,10 +136,10 @@ int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -148,9 +148,9 @@ int enic_dev_enable(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable_wait(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -159,9 +159,9 @@ int enic_dev_disable(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_disable(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -170,9 +170,9 @@ int enic_dev_intr_coal_timer_info(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_intr_coal_timer_info(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -181,9 +181,9 @@ int enic_vnic_dev_deinit(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_deinit(enic->vdev);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -192,10 +192,10 @@ int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_init_prov2(enic->vdev,
(u8 *)vp, vic_provinfo_size(vp));
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -204,9 +204,9 @@ int enic_dev_deinit_done(struct enic *enic, int *status)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_deinit_done(enic->vdev, status);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -217,9 +217,9 @@ int enic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
struct enic *enic = netdev_priv(netdev);
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = enic_add_vlan(enic, vid);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -230,9 +230,9 @@ int enic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
struct enic *enic = netdev_priv(netdev);
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = enic_del_vlan(enic, vid);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -241,9 +241,9 @@ int enic_dev_enable2(struct enic *enic, int active)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable2(enic->vdev, active);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -252,9 +252,9 @@ int enic_dev_enable2_done(struct enic *enic, int *status)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = vnic_dev_enable2_done(enic->vdev, status);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
diff --git a/drivers/net/ethernet/cisco/enic/enic_dev.h b/drivers/net/ethernet/cisco/enic/enic_dev.h
index 36ea1ab25f6a..10bb970b2f35 100644
--- a/drivers/net/ethernet/cisco/enic/enic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/enic_dev.h
@@ -28,7 +28,7 @@
*/
#define ENIC_DEVCMD_PROXY_BY_INDEX(vf, err, enic, vnicdevcmdfn, ...) \
do { \
- spin_lock(&enic->devcmd_lock); \
+ spin_lock_bh(&enic->devcmd_lock); \
if (enic_is_valid_vf(enic, vf)) { \
vnic_dev_cmd_proxy_by_index_start(enic->vdev, vf); \
err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
@@ -36,7 +36,7 @@
} else { \
err = vnicdevcmdfn(enic->vdev, ##__VA_ARGS__); \
} \
- spin_unlock(&enic->devcmd_lock); \
+ spin_unlock_bh(&enic->devcmd_lock); \
} while (0)
int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
index 2e50b5489d20..523c9ceb04c0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -22,6 +22,7 @@
#include "enic_res.h"
#include "enic.h"
#include "enic_dev.h"
+#include "enic_clsf.h"
struct enic_stat {
char name[ETH_GSTRING_LEN];
@@ -231,7 +232,7 @@ static int enic_set_coalesce(struct net_device *netdev,
if (ecmd->use_adaptive_rx_coalesce ||
ecmd->rx_coalesce_usecs_low ||
ecmd->rx_coalesce_usecs_high)
- return -EOPNOTSUPP;
+ return -EINVAL;
intr = enic_legacy_io_intr();
vnic_intr_coalescing_timer_set(&enic->intr[intr],
@@ -243,34 +244,29 @@ static int enic_set_coalesce(struct net_device *netdev,
if (ecmd->use_adaptive_rx_coalesce ||
ecmd->rx_coalesce_usecs_low ||
ecmd->rx_coalesce_usecs_high)
- return -EOPNOTSUPP;
+ return -EINVAL;
vnic_intr_coalescing_timer_set(&enic->intr[0],
tx_coalesce_usecs);
break;
case VNIC_DEV_INTR_MODE_MSIX:
+ if (ecmd->rx_coalesce_usecs_high &&
+ (rx_coalesce_usecs_high <
+ rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
+ return -EINVAL;
+
for (i = 0; i < enic->wq_count; i++) {
intr = enic_msix_wq_intr(enic, i);
vnic_intr_coalescing_timer_set(&enic->intr[intr],
tx_coalesce_usecs);
}
- if (rxcoal->use_adaptive_rx_coalesce) {
- if (!ecmd->use_adaptive_rx_coalesce) {
- rxcoal->use_adaptive_rx_coalesce = 0;
- enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
- }
- } else {
- if (ecmd->use_adaptive_rx_coalesce)
- rxcoal->use_adaptive_rx_coalesce = 1;
- else
- enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
- }
+ rxcoal->use_adaptive_rx_coalesce =
+ !!ecmd->use_adaptive_rx_coalesce;
+ if (!rxcoal->use_adaptive_rx_coalesce)
+ enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
if (ecmd->rx_coalesce_usecs_high) {
- if (rx_coalesce_usecs_high <
- (rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
- return -EINVAL;
rxcoal->range_end = rx_coalesce_usecs_high;
rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
@@ -287,6 +283,102 @@ static int enic_set_coalesce(struct net_device *netdev,
return 0;
}
+static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ int j, ret = 0, cnt = 0;
+
+ cmd->data = enic->rfs_h.max - enic->rfs_h.free;
+ for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) {
+ struct hlist_head *hhead;
+ struct hlist_node *tmp;
+ struct enic_rfs_fltr_node *n;
+
+ hhead = &enic->rfs_h.ht_head[j];
+ hlist_for_each_entry_safe(n, tmp, hhead, node) {
+ if (cnt == cmd->rule_cnt)
+ return -EMSGSIZE;
+ rule_locs[cnt] = n->fltr_id;
+ cnt++;
+ }
+ }
+ cmd->rule_cnt = cnt;
+
+ return ret;
+}
+
+static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct enic_rfs_fltr_node *n;
+
+ n = htbl_fltr_search(enic, (u16)fsp->location);
+ if (!n)
+ return -EINVAL;
+ switch (n->keys.ip_proto) {
+ case IPPROTO_TCP:
+ fsp->flow_type = TCP_V4_FLOW;
+ break;
+ case IPPROTO_UDP:
+ fsp->flow_type = UDP_V4_FLOW;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src;
+ fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
+
+ fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst;
+ fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
+
+ fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0];
+ fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
+
+ fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1];
+ fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
+
+ fsp->ring_cookie = n->rq_id;
+
+ return 0;
+}
+
+static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct enic *enic = netdev_priv(dev);
+ int ret = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = enic->rq_count;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ spin_lock_bh(&enic->rfs_h.lock);
+ cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free;
+ cmd->data = enic->rfs_h.max;
+ spin_unlock_bh(&enic->rfs_h.lock);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ spin_lock_bh(&enic->rfs_h.lock);
+ ret = enic_grxclsrlall(enic, cmd, rule_locs);
+ spin_unlock_bh(&enic->rfs_h.lock);
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ spin_lock_bh(&enic->rfs_h.lock);
+ ret = enic_grxclsrule(enic, cmd);
+ spin_unlock_bh(&enic->rfs_h.lock);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
static const struct ethtool_ops enic_ethtool_ops = {
.get_settings = enic_get_settings,
.get_drvinfo = enic_get_drvinfo,
@@ -298,6 +390,7 @@ static const struct ethtool_ops enic_ethtool_ops = {
.get_ethtool_stats = enic_get_ethtool_stats,
.get_coalesce = enic_get_coalesce,
.set_coalesce = enic_set_coalesce,
+ .get_rxnfc = enic_get_rxnfc,
};
void enic_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index f32f828b7f3d..c8832bc1c5f7 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -39,6 +39,12 @@
#include <linux/prefetch.h>
#include <net/ip6_checksum.h>
#include <linux/ktime.h>
+#ifdef CONFIG_RFS_ACCEL
+#include <linux/cpu_rmap.h>
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#include <net/busy_poll.h>
+#endif
#include "cq_enet_desc.h"
#include "vnic_dev.h"
@@ -49,6 +55,7 @@
#include "enic.h"
#include "enic_dev.h"
#include "enic_pp.h"
+#include "enic_clsf.h"
#define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ)
#define WQ_ENET_MAX_DESC_LEN (1 << WQ_ENET_LEN_BITS)
@@ -60,7 +67,7 @@
#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */
/* Supported devices */
-static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
+static const struct pci_device_id enic_id_table[] = {
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
@@ -309,40 +316,15 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t enic_isr_msix_rq(int irq, void *data)
+static irqreturn_t enic_isr_msix(int irq, void *data)
{
struct napi_struct *napi = data;
- /* schedule NAPI polling for RQ cleanup */
napi_schedule(napi);
return IRQ_HANDLED;
}
-static irqreturn_t enic_isr_msix_wq(int irq, void *data)
-{
- struct enic *enic = data;
- unsigned int cq;
- unsigned int intr;
- unsigned int wq_work_to_do = -1; /* no limit */
- unsigned int wq_work_done;
- unsigned int wq_irq;
-
- wq_irq = (u32)irq - enic->msix_entry[enic_msix_wq_intr(enic, 0)].vector;
- cq = enic_cq_wq(enic, wq_irq);
- intr = enic_msix_wq_intr(enic, wq_irq);
-
- wq_work_done = vnic_cq_service(&enic->cq[cq],
- wq_work_to_do, enic_wq_service, NULL);
-
- vnic_intr_return_credits(&enic->intr[intr],
- wq_work_done,
- 1 /* unmask intr */,
- 1 /* reset intr timer */);
-
- return IRQ_HANDLED;
-}
-
static irqreturn_t enic_isr_msix_err(int irq, void *data)
{
struct enic *enic = data;
@@ -1049,10 +1031,12 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
if (vlan_stripped)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
- if (netdev->features & NETIF_F_GRO)
- napi_gro_receive(&enic->napi[q_number], skb);
- else
+ skb_mark_napi_id(skb, &enic->napi[rq->index]);
+ if (enic_poll_busy_polling(rq) ||
+ !(netdev->features & NETIF_F_GRO))
netif_receive_skb(skb);
+ else
+ napi_gro_receive(&enic->napi[q_number], skb);
if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
enic_intr_update_pkt_size(&cq->pkt_size_counter,
bytes_written);
@@ -1089,16 +1073,22 @@ static int enic_poll(struct napi_struct *napi, int budget)
unsigned int work_done, rq_work_done = 0, wq_work_done;
int err;
- /* Service RQ (first) and WQ
- */
+ wq_work_done = vnic_cq_service(&enic->cq[cq_wq], wq_work_to_do,
+ enic_wq_service, NULL);
+
+ if (!enic_poll_lock_napi(&enic->rq[cq_rq])) {
+ if (wq_work_done > 0)
+ vnic_intr_return_credits(&enic->intr[intr],
+ wq_work_done,
+ 0 /* dont unmask intr */,
+ 0 /* dont reset intr timer */);
+ return rq_work_done;
+ }
if (budget > 0)
rq_work_done = vnic_cq_service(&enic->cq[cq_rq],
rq_work_to_do, enic_rq_service, NULL);
- wq_work_done = vnic_cq_service(&enic->cq[cq_wq],
- wq_work_to_do, enic_wq_service, NULL);
-
/* Accumulate intr event credits for this polling
* cycle. An intr event is the completion of a
* a WQ or RQ packet.
@@ -1130,6 +1120,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
napi_complete(napi);
vnic_intr_unmask(&enic->intr[intr]);
}
+ enic_poll_unlock_napi(&enic->rq[cq_rq]);
return rq_work_done;
}
@@ -1192,7 +1183,102 @@ static void enic_calc_int_moderation(struct enic *enic, struct vnic_rq *rq)
pkt_size_counter->small_pkt_bytes_cnt = 0;
}
-static int enic_poll_msix(struct napi_struct *napi, int budget)
+#ifdef CONFIG_RFS_ACCEL
+static void enic_free_rx_cpu_rmap(struct enic *enic)
+{
+ free_irq_cpu_rmap(enic->netdev->rx_cpu_rmap);
+ enic->netdev->rx_cpu_rmap = NULL;
+}
+
+static void enic_set_rx_cpu_rmap(struct enic *enic)
+{
+ int i, res;
+
+ if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) {
+ enic->netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(enic->rq_count);
+ if (unlikely(!enic->netdev->rx_cpu_rmap))
+ return;
+ for (i = 0; i < enic->rq_count; i++) {
+ res = irq_cpu_rmap_add(enic->netdev->rx_cpu_rmap,
+ enic->msix_entry[i].vector);
+ if (unlikely(res)) {
+ enic_free_rx_cpu_rmap(enic);
+ return;
+ }
+ }
+ }
+}
+
+#else
+
+static void enic_free_rx_cpu_rmap(struct enic *enic)
+{
+}
+
+static void enic_set_rx_cpu_rmap(struct enic *enic)
+{
+}
+
+#endif /* CONFIG_RFS_ACCEL */
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+int enic_busy_poll(struct napi_struct *napi)
+{
+ struct net_device *netdev = napi->dev;
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int rq = (napi - &enic->napi[0]);
+ unsigned int cq = enic_cq_rq(enic, rq);
+ unsigned int intr = enic_msix_rq_intr(enic, rq);
+ unsigned int work_to_do = -1; /* clean all pkts possible */
+ unsigned int work_done;
+
+ if (!enic_poll_lock_poll(&enic->rq[rq]))
+ return LL_FLUSH_BUSY;
+ work_done = vnic_cq_service(&enic->cq[cq], work_to_do,
+ enic_rq_service, NULL);
+
+ if (work_done > 0)
+ vnic_intr_return_credits(&enic->intr[intr],
+ work_done, 0, 0);
+ vnic_rq_fill(&enic->rq[rq], enic_rq_alloc_buf);
+ if (enic->rx_coalesce_setting.use_adaptive_rx_coalesce)
+ enic_calc_int_moderation(enic, &enic->rq[rq]);
+ enic_poll_unlock_poll(&enic->rq[rq]);
+
+ return work_done;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
+{
+ struct net_device *netdev = napi->dev;
+ struct enic *enic = netdev_priv(netdev);
+ unsigned int wq_index = (napi - &enic->napi[0]) - enic->rq_count;
+ struct vnic_wq *wq = &enic->wq[wq_index];
+ unsigned int cq;
+ unsigned int intr;
+ unsigned int wq_work_to_do = -1; /* clean all desc possible */
+ unsigned int wq_work_done;
+ unsigned int wq_irq;
+
+ wq_irq = wq->index;
+ cq = enic_cq_wq(enic, wq_irq);
+ intr = enic_msix_wq_intr(enic, wq_irq);
+ wq_work_done = vnic_cq_service(&enic->cq[cq], wq_work_to_do,
+ enic_wq_service, NULL);
+
+ vnic_intr_return_credits(&enic->intr[intr], wq_work_done,
+ 0 /* don't unmask intr */,
+ 1 /* reset intr timer */);
+ if (!wq_work_done) {
+ napi_complete(napi);
+ vnic_intr_unmask(&enic->intr[intr]);
+ }
+
+ return 0;
+}
+
+static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
{
struct net_device *netdev = napi->dev;
struct enic *enic = netdev_priv(netdev);
@@ -1203,6 +1289,8 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
unsigned int work_done = 0;
int err;
+ if (!enic_poll_lock_napi(&enic->rq[rq]))
+ return work_done;
/* Service RQ
*/
@@ -1248,6 +1336,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
enic_set_int_moderation(enic, &enic->rq[rq]);
vnic_intr_unmask(&enic->intr[intr]);
}
+ enic_poll_unlock_napi(&enic->rq[rq]);
return work_done;
}
@@ -1267,6 +1356,7 @@ static void enic_free_intr(struct enic *enic)
struct net_device *netdev = enic->netdev;
unsigned int i;
+ enic_free_rx_cpu_rmap(enic);
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
free_irq(enic->pdev->irq, netdev);
@@ -1291,6 +1381,7 @@ static int enic_request_intr(struct enic *enic)
unsigned int i, intr;
int err = 0;
+ enic_set_rx_cpu_rmap(enic);
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
@@ -1312,17 +1403,19 @@ static int enic_request_intr(struct enic *enic)
snprintf(enic->msix[intr].devname,
sizeof(enic->msix[intr].devname),
"%.11s-rx-%d", netdev->name, i);
- enic->msix[intr].isr = enic_isr_msix_rq;
+ enic->msix[intr].isr = enic_isr_msix;
enic->msix[intr].devid = &enic->napi[i];
}
for (i = 0; i < enic->wq_count; i++) {
+ int wq = enic_cq_wq(enic, i);
+
intr = enic_msix_wq_intr(enic, i);
snprintf(enic->msix[intr].devname,
sizeof(enic->msix[intr].devname),
"%.11s-tx-%d", netdev->name, i);
- enic->msix[intr].isr = enic_isr_msix_wq;
- enic->msix[intr].devid = enic;
+ enic->msix[intr].isr = enic_isr_msix;
+ enic->msix[intr].devid = &enic->napi[wq];
}
intr = enic_msix_err_intr(enic);
@@ -1421,7 +1514,7 @@ static int enic_dev_notify_set(struct enic *enic)
{
int err;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
switch (vnic_dev_get_intr_mode(enic->vdev)) {
case VNIC_DEV_INTR_MODE_INTX:
err = vnic_dev_notify_set(enic->vdev,
@@ -1435,7 +1528,7 @@ static int enic_dev_notify_set(struct enic *enic)
err = vnic_dev_notify_set(enic->vdev, -1 /* no intr */);
break;
}
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -1494,15 +1587,20 @@ static int enic_open(struct net_device *netdev)
netif_tx_wake_all_queues(netdev);
- for (i = 0; i < enic->rq_count; i++)
+ for (i = 0; i < enic->rq_count; i++) {
+ enic_busy_poll_init_lock(&enic->rq[i]);
napi_enable(&enic->napi[i]);
-
+ }
+ if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+ for (i = 0; i < enic->wq_count; i++)
+ napi_enable(&enic->napi[enic_cq_wq(enic, i)]);
enic_dev_enable(enic);
for (i = 0; i < enic->intr_count; i++)
vnic_intr_unmask(&enic->intr[i]);
enic_notify_timer_start(enic);
+ enic_rfs_flw_tbl_init(enic);
return 0;
@@ -1529,14 +1627,23 @@ static int enic_stop(struct net_device *netdev)
enic_synchronize_irqs(enic);
del_timer_sync(&enic->notify_timer);
+ enic_rfs_flw_tbl_free(enic);
enic_dev_disable(enic);
- for (i = 0; i < enic->rq_count; i++)
+ local_bh_disable();
+ for (i = 0; i < enic->rq_count; i++) {
napi_disable(&enic->napi[i]);
+ while (!enic_poll_lock_napi(&enic->rq[i]))
+ mdelay(1);
+ }
+ local_bh_enable();
netif_carrier_off(netdev);
netif_tx_disable(netdev);
+ if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+ for (i = 0; i < enic->wq_count; i++)
+ napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_del_station_addr(enic);
@@ -1656,13 +1763,14 @@ static void enic_poll_controller(struct net_device *netdev)
case VNIC_DEV_INTR_MODE_MSIX:
for (i = 0; i < enic->rq_count; i++) {
intr = enic_msix_rq_intr(enic, i);
- enic_isr_msix_rq(enic->msix_entry[intr].vector,
- &enic->napi[i]);
+ enic_isr_msix(enic->msix_entry[intr].vector,
+ &enic->napi[i]);
}
for (i = 0; i < enic->wq_count; i++) {
intr = enic_msix_wq_intr(enic, i);
- enic_isr_msix_wq(enic->msix_entry[intr].vector, enic);
+ enic_isr_msix(enic->msix_entry[intr].vector,
+ &enic->napi[enic_cq_wq(enic, i)]);
}
break;
@@ -1758,11 +1866,11 @@ static int enic_set_rsskey(struct enic *enic)
memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = enic_set_rss_key(enic,
rss_key_buf_pa,
sizeof(union vnic_rss_key));
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
pci_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
rss_key_buf_va, rss_key_buf_pa);
@@ -1785,11 +1893,11 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
for (i = 0; i < (1 << rss_hash_bits); i++)
(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = enic_set_rss_cpu(enic,
rss_cpu_buf_pa,
sizeof(union vnic_rss_cpu));
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
pci_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
rss_cpu_buf_va, rss_cpu_buf_pa);
@@ -1807,13 +1915,13 @@ static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
/* Enable VLAN tag stripping.
*/
- spin_lock(&enic->devcmd_lock);
+ spin_lock_bh(&enic->devcmd_lock);
err = enic_set_nic_cfg(enic,
rss_default_cpu, rss_hash_type,
rss_hash_bits, rss_base_cpu,
rss_enable, tso_ipid_split_en,
ig_vlan_strip_en);
- spin_unlock(&enic->devcmd_lock);
+ spin_unlock_bh(&enic->devcmd_lock);
return err;
}
@@ -2021,6 +2129,12 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = enic_poll_controller,
#endif
+#ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = enic_rx_flow_steer,
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = enic_busy_poll,
+#endif
};
static const struct net_device_ops enic_netdev_ops = {
@@ -2041,14 +2155,25 @@ static const struct net_device_ops enic_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = enic_poll_controller,
#endif
+#ifdef CONFIG_RFS_ACCEL
+ .ndo_rx_flow_steer = enic_rx_flow_steer,
+#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = enic_busy_poll,
+#endif
};
static void enic_dev_deinit(struct enic *enic)
{
unsigned int i;
- for (i = 0; i < enic->rq_count; i++)
+ for (i = 0; i < enic->rq_count; i++) {
+ napi_hash_del(&enic->napi[i]);
netif_napi_del(&enic->napi[i]);
+ }
+ if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
+ for (i = 0; i < enic->wq_count; i++)
+ netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);
enic_free_vnic_resources(enic);
enic_clear_intr_mode(enic);
@@ -2114,11 +2239,17 @@ static int enic_dev_init(struct enic *enic)
switch (vnic_dev_get_intr_mode(enic->vdev)) {
default:
netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
+ napi_hash_add(&enic->napi[0]);
break;
case VNIC_DEV_INTR_MODE_MSIX:
- for (i = 0; i < enic->rq_count; i++)
+ for (i = 0; i < enic->rq_count; i++) {
netif_napi_add(netdev, &enic->napi[i],
- enic_poll_msix, 64);
+ enic_poll_msix_rq, NAPI_POLL_WEIGHT);
+ napi_hash_add(&enic->napi[i]);
+ }
+ for (i = 0; i < enic->wq_count; i++)
+ netif_napi_add(netdev, &enic->napi[enic_cq_wq(enic, i)],
+ enic_poll_msix_wq, NAPI_POLL_WEIGHT);
break;
}
@@ -2386,6 +2517,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features |= netdev->hw_features;
+#ifdef CONFIG_RFS_ACCEL
+ netdev->hw_features |= NETIF_F_NTUPLE;
+#endif
+
if (using_dac)
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ethernet/cisco/enic/enic_res.c
index 31d658880c3c..9c96911fb2c8 100644
--- a/drivers/net/ethernet/cisco/enic/enic_res.c
+++ b/drivers/net/ethernet/cisco/enic/enic_res.c
@@ -71,6 +71,7 @@ int enic_get_vnic_config(struct enic *enic)
GET_CONFIG(intr_mode);
GET_CONFIG(intr_timer_usec);
GET_CONFIG(loop_tag);
+ GET_CONFIG(num_arfs);
c->wq_desc_count =
min_t(u32, ENIC_MAX_WQ_DESCS,
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index e86a45cb9e68..37472ce4fac3 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -312,12 +312,12 @@ static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
err = (int)readq(&devcmd->args[0]);
if (err == ERR_EINVAL &&
cmd == CMD_CAPABILITY)
- return err;
+ return -err;
if (err != ERR_ECMDUNKNOWN ||
cmd != CMD_CAPABILITY)
pr_err("Error %d devcmd %d\n",
err, _CMD_N(cmd));
- return err;
+ return -err;
}
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
@@ -432,14 +432,12 @@ int vnic_dev_fw_info(struct vnic_dev *vdev,
int err = 0;
if (!vdev->fw_info) {
- vdev->fw_info = pci_alloc_consistent(vdev->pdev,
- sizeof(struct vnic_devcmd_fw_info),
- &vdev->fw_info_pa);
+ vdev->fw_info = pci_zalloc_consistent(vdev->pdev,
+ sizeof(struct vnic_devcmd_fw_info),
+ &vdev->fw_info_pa);
if (!vdev->fw_info)
return -ENOMEM;
- memset(vdev->fw_info, 0, sizeof(struct vnic_devcmd_fw_info));
-
a0 = vdev->fw_info_pa;
a1 = sizeof(struct vnic_devcmd_fw_info);
@@ -1048,3 +1046,64 @@ int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait);
}
+
+/* vnic_dev_classifier: Add/Delete classifier entries
+ * @vdev: vdev of the device
+ * @cmd: CLSF_ADD for Add filter
+ * CLSF_DEL for Delete filter
+ * @entry: In case of ADD filter, the caller passes the RQ number in this
+ * variable.
+ *
+ * This function stores the filter_id returned by the firmware in the
+ * same variable before return;
+ *
+ * In case of DEL filter, the caller passes the RQ number. Return
+ * value is irrelevant.
+ * @data: filter data
+ */
+int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
+ struct filter *data)
+{
+ u64 a0, a1;
+ int wait = 1000;
+ dma_addr_t tlv_pa;
+ int ret = -EINVAL;
+ struct filter_tlv *tlv, *tlv_va;
+ struct filter_action *action;
+ u64 tlv_size;
+
+ if (cmd == CLSF_ADD) {
+ tlv_size = sizeof(struct filter) +
+ sizeof(struct filter_action) +
+ 2 * sizeof(struct filter_tlv);
+ tlv_va = pci_alloc_consistent(vdev->pdev, tlv_size, &tlv_pa);
+ if (!tlv_va)
+ return -ENOMEM;
+ tlv = tlv_va;
+ a0 = tlv_pa;
+ a1 = tlv_size;
+ memset(tlv, 0, tlv_size);
+ tlv->type = CLSF_TLV_FILTER;
+ tlv->length = sizeof(struct filter);
+ *(struct filter *)&tlv->val = *data;
+
+ tlv = (struct filter_tlv *)((char *)tlv +
+ sizeof(struct filter_tlv) +
+ sizeof(struct filter));
+
+ tlv->type = CLSF_TLV_ACTION;
+ tlv->length = sizeof(struct filter_action);
+ action = (struct filter_action *)&tlv->val;
+ action->type = FILTER_ACTION_RQ_STEERING;
+ action->u.rq_idx = *entry;
+
+ ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait);
+ *entry = (u16)a0;
+ pci_free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa);
+ } else if (cmd == CLSF_DEL) {
+ a0 = *entry;
+ ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait);
+ }
+
+ return ret;
+}
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index 1f3b301f8225..1fb214efceba 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -133,5 +133,7 @@ int vnic_dev_enable2(struct vnic_dev *vdev, int active);
int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status);
int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
+int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
+ struct filter *data);
#endif /* _VNIC_DEV_H_ */
diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
index b9a0d78fd639..435d0cd96c22 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h
@@ -603,6 +603,11 @@ struct filter_tlv {
u_int32_t val[0];
};
+enum {
+ CLSF_ADD = 0,
+ CLSF_DEL = 1,
+};
+
/*
* Writing cmd register causes STAT_BUSY to get set in status register.
* When cmd completes, STAT_BUSY will be cleared.
diff --git a/drivers/net/ethernet/cisco/enic/vnic_enet.h b/drivers/net/ethernet/cisco/enic/vnic_enet.h
index 609542848e02..75aced2de869 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_enet.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_enet.h
@@ -32,6 +32,8 @@ struct vnic_enet_config {
char devname[16];
u32 intr_timer_usec;
u16 loop_tag;
+ u16 vf_rq_count;
+ u16 num_arfs;
};
#define VENETF_TSO 0x1 /* TSO enabled */
diff --git a/drivers/net/ethernet/cisco/enic/vnic_rq.h b/drivers/net/ethernet/cisco/enic/vnic_rq.h
index ee7bc95af278..8111d5202df2 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_rq.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_rq.h
@@ -85,6 +85,21 @@ struct vnic_rq {
struct vnic_rq_buf *to_clean;
void *os_buf_head;
unsigned int pkts_outstanding;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#define ENIC_POLL_STATE_IDLE 0
+#define ENIC_POLL_STATE_NAPI (1 << 0) /* NAPI owns this poll */
+#define ENIC_POLL_STATE_POLL (1 << 1) /* poll owns this poll */
+#define ENIC_POLL_STATE_NAPI_YIELD (1 << 2) /* NAPI yielded this poll */
+#define ENIC_POLL_STATE_POLL_YIELD (1 << 3) /* poll yielded this poll */
+#define ENIC_POLL_YIELD (ENIC_POLL_STATE_NAPI_YIELD | \
+ ENIC_POLL_STATE_POLL_YIELD)
+#define ENIC_POLL_LOCKED (ENIC_POLL_STATE_NAPI | \
+ ENIC_POLL_STATE_POLL)
+#define ENIC_POLL_USER_PEND (ENIC_POLL_STATE_POLL | \
+ ENIC_POLL_STATE_POLL_YIELD)
+ unsigned int bpoll_state;
+ spinlock_t bpoll_lock;
+#endif /* CONFIG_NET_RX_BUSY_POLL */
};
static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
@@ -197,6 +212,113 @@ static inline int vnic_rq_fill(struct vnic_rq *rq,
return 0;
}
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void enic_busy_poll_init_lock(struct vnic_rq *rq)
+{
+ spin_lock_init(&rq->bpoll_lock);
+ rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+}
+
+static inline bool enic_poll_lock_napi(struct vnic_rq *rq)
+{
+ bool rc = true;
+
+ spin_lock(&rq->bpoll_lock);
+ if (rq->bpoll_state & ENIC_POLL_LOCKED) {
+ WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI);
+ rq->bpoll_state |= ENIC_POLL_STATE_NAPI_YIELD;
+ rc = false;
+ } else {
+ rq->bpoll_state = ENIC_POLL_STATE_NAPI;
+ }
+ spin_unlock(&rq->bpoll_lock);
+
+ return rc;
+}
+
+static inline bool enic_poll_unlock_napi(struct vnic_rq *rq)
+{
+ bool rc = false;
+
+ spin_lock(&rq->bpoll_lock);
+ WARN_ON(rq->bpoll_state &
+ (ENIC_POLL_STATE_POLL | ENIC_POLL_STATE_NAPI_YIELD));
+ if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD)
+ rc = true;
+ rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+ spin_unlock(&rq->bpoll_lock);
+
+ return rc;
+}
+
+static inline bool enic_poll_lock_poll(struct vnic_rq *rq)
+{
+ bool rc = true;
+
+ spin_lock_bh(&rq->bpoll_lock);
+ if (rq->bpoll_state & ENIC_POLL_LOCKED) {
+ rq->bpoll_state |= ENIC_POLL_STATE_POLL_YIELD;
+ rc = false;
+ } else {
+ rq->bpoll_state |= ENIC_POLL_STATE_POLL;
+ }
+ spin_unlock_bh(&rq->bpoll_lock);
+
+ return rc;
+}
+
+static inline bool enic_poll_unlock_poll(struct vnic_rq *rq)
+{
+ bool rc = false;
+
+ spin_lock_bh(&rq->bpoll_lock);
+ WARN_ON(rq->bpoll_state & ENIC_POLL_STATE_NAPI);
+ if (rq->bpoll_state & ENIC_POLL_STATE_POLL_YIELD)
+ rc = true;
+ rq->bpoll_state = ENIC_POLL_STATE_IDLE;
+ spin_unlock_bh(&rq->bpoll_lock);
+
+ return rc;
+}
+
+static inline bool enic_poll_busy_polling(struct vnic_rq *rq)
+{
+ WARN_ON(!(rq->bpoll_state & ENIC_POLL_LOCKED));
+ return rq->bpoll_state & ENIC_POLL_USER_PEND;
+}
+
+#else
+
+static inline void enic_busy_poll_init_lock(struct vnic_rq *rq)
+{
+}
+
+static inline bool enic_poll_lock_napi(struct vnic_rq *rq)
+{
+ return true;
+}
+
+static inline bool enic_poll_unlock_napi(struct vnic_rq *rq)
+{
+ return false;
+}
+
+static inline bool enic_poll_lock_poll(struct vnic_rq *rq)
+{
+ return false;
+}
+
+static inline bool enic_poll_unlock_poll(struct vnic_rq *rq)
+{
+ return false;
+}
+
+static inline bool enic_poll_ll_polling(struct vnic_rq *rq)
+{
+ return false;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
void vnic_rq_free(struct vnic_rq *rq);
int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
unsigned int desc_count, unsigned int desc_size);
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 13723c96d1a2..9b33057a9477 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -93,7 +93,7 @@ enum dm9000_type {
};
/* Structure/enum declaration ------------------------------- */
-typedef struct board_info {
+struct board_info {
void __iomem *io_addr; /* Register I/O base address */
void __iomem *io_data; /* Data I/O address */
@@ -141,7 +141,7 @@ typedef struct board_info {
u32 wake_state;
int ip_summed;
-} board_info_t;
+};
/* debug code */
@@ -151,7 +151,7 @@ typedef struct board_info {
} \
} while (0)
-static inline board_info_t *to_dm9000_board(struct net_device *dev)
+static inline struct board_info *to_dm9000_board(struct net_device *dev)
{
return netdev_priv(dev);
}
@@ -162,7 +162,7 @@ static inline board_info_t *to_dm9000_board(struct net_device *dev)
* Read a byte from I/O port
*/
static u8
-ior(board_info_t *db, int reg)
+ior(struct board_info *db, int reg)
{
writeb(reg, db->io_addr);
return readb(db->io_data);
@@ -173,14 +173,14 @@ ior(board_info_t *db, int reg)
*/
static void
-iow(board_info_t *db, int reg, int value)
+iow(struct board_info *db, int reg, int value)
{
writeb(reg, db->io_addr);
writeb(value, db->io_data);
}
static void
-dm9000_reset(board_info_t *db)
+dm9000_reset(struct board_info *db)
{
dev_dbg(db->dev, "resetting device\n");
@@ -272,7 +272,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
* Sleep, either by using msleep() or if we are suspending, then
* use mdelay() to sleep.
*/
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
+static void dm9000_msleep(struct board_info *db, unsigned int ms)
{
if (db->in_suspend || db->in_timeout)
mdelay(ms);
@@ -284,7 +284,7 @@ static void dm9000_msleep(board_info_t *db, unsigned int ms)
static int
dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned int reg_save;
int ret;
@@ -330,7 +330,7 @@ static void
dm9000_phy_write(struct net_device *dev,
int phyaddr_unused, int reg, int value)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned long reg_save;
@@ -408,7 +408,7 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
}
}
-static void dm9000_schedule_poll(board_info_t *db)
+static void dm9000_schedule_poll(struct board_info *db)
{
if (db->type == TYPE_DM9000E)
schedule_delayed_work(&db->phy_poll, HZ * 2);
@@ -416,7 +416,7 @@ static void dm9000_schedule_poll(board_info_t *db)
static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
if (!netif_running(dev))
return -EINVAL;
@@ -425,7 +425,7 @@ static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
}
static unsigned int
-dm9000_read_locked(board_info_t *db, int reg)
+dm9000_read_locked(struct board_info *db, int reg)
{
unsigned long flags;
unsigned int ret;
@@ -437,7 +437,7 @@ dm9000_read_locked(board_info_t *db, int reg)
return ret;
}
-static int dm9000_wait_eeprom(board_info_t *db)
+static int dm9000_wait_eeprom(struct board_info *db)
{
unsigned int status;
int timeout = 8; /* wait max 8msec */
@@ -474,7 +474,7 @@ static int dm9000_wait_eeprom(board_info_t *db)
* Read a word data from EEPROM
*/
static void
-dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
+dm9000_read_eeprom(struct board_info *db, int offset, u8 *to)
{
unsigned long flags;
@@ -514,7 +514,7 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
* Write a word data to SROM
*/
static void
-dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
+dm9000_write_eeprom(struct board_info *db, int offset, u8 *data)
{
unsigned long flags;
@@ -546,7 +546,7 @@ dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
static void dm9000_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
strlcpy(info->driver, CARDNAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
@@ -556,21 +556,21 @@ static void dm9000_get_drvinfo(struct net_device *dev,
static u32 dm9000_get_msglevel(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return dm->msg_enable;
}
static void dm9000_set_msglevel(struct net_device *dev, u32 value)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
dm->msg_enable = value;
}
static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
mii_ethtool_gset(&dm->mii, cmd);
return 0;
@@ -578,21 +578,21 @@ static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return mii_ethtool_sset(&dm->mii, cmd);
}
static int dm9000_nway_reset(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
return mii_nway_restart(&dm->mii);
}
static int dm9000_set_features(struct net_device *dev,
netdev_features_t features)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
netdev_features_t changed = dev->features ^ features;
unsigned long flags;
@@ -608,7 +608,7 @@ static int dm9000_set_features(struct net_device *dev,
static u32 dm9000_get_link(struct net_device *dev)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
u32 ret;
if (dm->flags & DM9000_PLATF_EXT_PHY)
@@ -629,7 +629,7 @@ static int dm9000_get_eeprom_len(struct net_device *dev)
static int dm9000_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int i;
@@ -653,7 +653,7 @@ static int dm9000_get_eeprom(struct net_device *dev,
static int dm9000_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
int offset = ee->offset;
int len = ee->len;
int done;
@@ -691,7 +691,7 @@ static int dm9000_set_eeprom(struct net_device *dev,
static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
memset(w, 0, sizeof(struct ethtool_wolinfo));
@@ -702,7 +702,7 @@ static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)
static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
unsigned long flags;
u32 opts = w->wolopts;
u32 wcr = 0;
@@ -752,7 +752,7 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
.set_eeprom = dm9000_set_eeprom,
};
-static void dm9000_show_carrier(board_info_t *db,
+static void dm9000_show_carrier(struct board_info *db,
unsigned carrier, unsigned nsr)
{
int lpa;
@@ -775,7 +775,7 @@ static void
dm9000_poll_work(struct work_struct *w)
{
struct delayed_work *dw = to_delayed_work(w);
- board_info_t *db = container_of(dw, board_info_t, phy_poll);
+ struct board_info *db = container_of(dw, struct board_info, phy_poll);
struct net_device *ndev = db->ndev;
if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
@@ -817,10 +817,12 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db)
/* release the resources */
- release_resource(db->data_req);
+ if (db->data_req)
+ release_resource(db->data_req);
kfree(db->data_req);
- release_resource(db->addr_req);
+ if (db->addr_req)
+ release_resource(db->addr_req);
kfree(db->addr_req);
}
@@ -841,7 +843,7 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type)
static void
dm9000_hash_table_unlocked(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
struct netdev_hw_addr *ha;
int i, oft;
u32 hash_val;
@@ -877,7 +879,7 @@ dm9000_hash_table_unlocked(struct net_device *dev)
static void
dm9000_hash_table(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&db->lock, flags);
@@ -886,13 +888,13 @@ dm9000_hash_table(struct net_device *dev)
}
static void
-dm9000_mask_interrupts(board_info_t *db)
+dm9000_mask_interrupts(struct board_info *db)
{
iow(db, DM9000_IMR, IMR_PAR);
}
static void
-dm9000_unmask_interrupts(board_info_t *db)
+dm9000_unmask_interrupts(struct board_info *db)
{
iow(db, DM9000_IMR, db->imr_all);
}
@@ -903,7 +905,7 @@ dm9000_unmask_interrupts(board_info_t *db)
static void
dm9000_init_dm9000(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned int imr;
unsigned int ncr;
@@ -968,7 +970,7 @@ dm9000_init_dm9000(struct net_device *dev)
/* Our watchdog timed out. Called by the networking layer */
static void dm9000_timeout(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
u8 reg_save;
unsigned long flags;
@@ -994,7 +996,7 @@ static void dm9000_send_packet(struct net_device *dev,
int ip_summed,
u16 pkt_len)
{
- board_info_t *dm = to_dm9000_board(dev);
+ struct board_info *dm = to_dm9000_board(dev);
/* The DM9000 is not smart enough to leave fragmented packets alone. */
if (dm->ip_summed != ip_summed) {
@@ -1021,7 +1023,7 @@ static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
dm9000_dbg(db, 3, "%s:\n", __func__);
@@ -1060,7 +1062,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
* receive the packet to upper layer, free the transmitted packet
*/
-static void dm9000_tx_done(struct net_device *dev, board_info_t *db)
+static void dm9000_tx_done(struct net_device *dev, struct board_info *db)
{
int tx_status = ior(db, DM9000_NSR); /* Got TX status */
@@ -1092,7 +1094,7 @@ struct dm9000_rxhdr {
static void
dm9000_rx(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
@@ -1194,7 +1196,7 @@ dm9000_rx(struct net_device *dev)
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
int int_status;
unsigned long flags;
u8 reg_save;
@@ -1244,7 +1246,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long flags;
unsigned nsr, wcr;
@@ -1294,7 +1296,7 @@ static void dm9000_poll_controller(struct net_device *dev)
static int
dm9000_open(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
@@ -1340,7 +1342,7 @@ dm9000_open(struct net_device *dev)
static void
dm9000_shutdown(struct net_device *dev)
{
- board_info_t *db = netdev_priv(dev);
+ struct board_info *db = netdev_priv(dev);
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
@@ -1356,7 +1358,7 @@ dm9000_shutdown(struct net_device *dev)
static int
dm9000_stop(struct net_device *ndev)
{
- board_info_t *db = netdev_priv(ndev);
+ struct board_info *db = netdev_priv(ndev);
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -1679,7 +1681,7 @@ dm9000_drv_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
- board_info_t *db;
+ struct board_info *db;
if (ndev) {
db = netdev_priv(ndev);
@@ -1702,7 +1704,7 @@ dm9000_drv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
- board_info_t *db = netdev_priv(ndev);
+ struct board_info *db = netdev_priv(ndev);
if (ndev) {
if (netif_running(ndev)) {
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c
index 38148b0e3a95..a02ecc4f9002 100644
--- a/drivers/net/ethernet/dec/tulip/de2104x.c
+++ b/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -340,7 +340,7 @@ static void de21041_media_timer (unsigned long data);
static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media);
-static DEFINE_PCI_DEVICE_TABLE(de_pci_tbl) = {
+static const struct pci_device_id de_pci_tbl[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c
index c05b66dfcc30..cf8b6ff21613 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -2328,7 +2328,7 @@ static void de4x5_pci_remove(struct pci_dev *pdev)
pci_disable_device (pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(de4x5_pci_tbl) = {
+static const struct pci_device_id de4x5_pci_tbl[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
@@ -3250,7 +3250,6 @@ srom_map_media(struct net_device *dev)
printk("%s: Bad media code [%d] detected in SROM!\n", dev->name,
lp->infoblock_media);
return -1;
- break;
}
return 0;
diff --git a/drivers/net/ethernet/dec/tulip/dmfe.c b/drivers/net/ethernet/dec/tulip/dmfe.c
index 53f0c618045c..322213d901d5 100644
--- a/drivers/net/ethernet/dec/tulip/dmfe.c
+++ b/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -2096,7 +2096,7 @@ static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db)
-static DEFINE_PCI_DEVICE_TABLE(dmfe_pci_tbl) = {
+static const struct pci_device_id dmfe_pci_tbl[] = {
{ 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID },
{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID },
{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID },
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c
index 861660841ce2..3b42556f7f8d 100644
--- a/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ b/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -207,7 +207,7 @@ struct tulip_chip_table tulip_tbl[] = {
};
-static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = {
+static const struct pci_device_id tulip_pci_tbl[] = {
{ 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
{ 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 },
{ 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 },
@@ -1294,7 +1294,7 @@ static const struct net_device_ops tulip_netdev_ops = {
#endif
};
-DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
+const struct pci_device_id early_486_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
{ },
diff --git a/drivers/net/ethernet/dec/tulip/uli526x.c b/drivers/net/ethernet/dec/tulip/uli526x.c
index 80afec335a11..4061f9b22812 100644
--- a/drivers/net/ethernet/dec/tulip/uli526x.c
+++ b/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -1768,7 +1768,7 @@ static u16 phy_read_1bit(struct uli526x_board_info *db)
}
-static DEFINE_PCI_DEVICE_TABLE(uli526x_pci_tbl) = {
+static const struct pci_device_id uli526x_pci_tbl[] = {
{ 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
{ 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID },
{ 0, }
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c
index 62fe512bb216..6aa887e0e1cb 100644
--- a/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -219,7 +219,7 @@ enum chip_capability_flags {
CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,
};
-static DEFINE_PCI_DEVICE_TABLE(w840_pci_tbl) = {
+static const struct pci_device_id w840_pci_tbl[] = {
{ 0x1050, 0x0840, PCI_ANY_ID, 0x8153, 0, 0, 0 },
{ 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
{ 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c
index 6204cdfe43a6..0e721cedfa67 100644
--- a/drivers/net/ethernet/dec/tulip/xircom_cb.c
+++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c
@@ -137,7 +137,7 @@ static int link_status(struct xircom_private *card);
-static DEFINE_PCI_DEVICE_TABLE(xircom_pci_table) = {
+static const struct pci_device_id xircom_pci_table[] = {
{ PCI_VDEVICE(XIRCOM, 0x0003), },
{0,},
};
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
index 7d07a0f5320d..23c07b007069 100644
--- a/drivers/net/ethernet/dlink/dl2k.h
+++ b/drivers/net/ethernet/dlink/dl2k.h
@@ -408,7 +408,7 @@ struct netdev_private {
driver_data Data private to the driver.
*/
-static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = {
+static const struct pci_device_id rio_pci_tbl[] = {
{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
{0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, },
{ }
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c
index 433c1e185442..a28a2e583f0f 100644
--- a/drivers/net/ethernet/dlink/sundance.c
+++ b/drivers/net/ethernet/dlink/sundance.c
@@ -199,7 +199,7 @@ IVc. Errata
#define USE_IO_OPS 1
#endif
-static DEFINE_PCI_DEVICE_TABLE(sundance_pci_tbl) = {
+static const struct pci_device_id sundance_pci_tbl[] = {
{ 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
{ 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
{ 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index e9b0faba3078..a379c3e4b57f 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -323,7 +323,8 @@ static int dnet_mii_init(struct dnet *bp)
bp->mii_bus->priv = bp;
- bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ bp->mii_bus->irq = devm_kmalloc(&bp->pdev->dev,
+ sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!bp->mii_bus->irq) {
err = -ENOMEM;
goto err_out;
@@ -334,7 +335,7 @@ static int dnet_mii_init(struct dnet *bp)
if (mdiobus_register(bp->mii_bus)) {
err = -ENXIO;
- goto err_out_free_mdio_irq;
+ goto err_out;
}
if (dnet_mii_probe(bp->dev) != 0) {
@@ -346,8 +347,6 @@ static int dnet_mii_init(struct dnet *bp)
err_out_unregister_bus:
mdiobus_unregister(bp->mii_bus);
-err_out_free_mdio_irq:
- kfree(bp->mii_bus->irq);
err_out:
mdiobus_free(bp->mii_bus);
return err;
@@ -825,28 +824,14 @@ static int dnet_probe(struct platform_device *pdev)
struct net_device *dev;
struct dnet *bp;
struct phy_device *phydev;
- int err = -ENXIO;
- unsigned int mem_base, mem_size, irq;
+ int err;
+ unsigned int irq;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "no mmio resource defined\n");
- goto err_out;
- }
- mem_base = res->start;
- mem_size = resource_size(res);
irq = platform_get_irq(pdev, 0);
- if (!request_mem_region(mem_base, mem_size, DRV_NAME)) {
- dev_err(&pdev->dev, "no memory region available\n");
- err = -EBUSY;
- goto err_out;
- }
-
- err = -ENOMEM;
dev = alloc_etherdev(sizeof(*bp));
if (!dev)
- goto err_out_release_mem;
+ return -ENOMEM;
/* TODO: Actually, we have some interesting features... */
dev->features |= 0;
@@ -859,10 +844,10 @@ static int dnet_probe(struct platform_device *pdev)
spin_lock_init(&bp->lock);
- bp->regs = ioremap(mem_base, mem_size);
- if (!bp->regs) {
- dev_err(&pdev->dev, "failed to map registers, aborting.\n");
- err = -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ bp->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(bp->regs)) {
+ err = PTR_ERR(bp->regs);
goto err_out_free_dev;
}
@@ -871,7 +856,7 @@ static int dnet_probe(struct platform_device *pdev)
if (err) {
dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
irq, err);
- goto err_out_iounmap;
+ goto err_out_free_dev;
}
dev->netdev_ops = &dnet_netdev_ops;
@@ -908,7 +893,7 @@ static int dnet_probe(struct platform_device *pdev)
goto err_out_unregister_netdev;
dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n",
- bp->regs, mem_base, dev->irq, dev->dev_addr);
+ bp->regs, (unsigned int)res->start, dev->irq, dev->dev_addr);
dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma\n",
(bp->capabilities & DNET_HAS_MDIO) ? "" : "no ",
(bp->capabilities & DNET_HAS_IRQ) ? "" : "no ",
@@ -925,13 +910,8 @@ err_out_unregister_netdev:
unregister_netdev(dev);
err_out_free_irq:
free_irq(dev->irq, dev);
-err_out_iounmap:
- iounmap(bp->regs);
err_out_free_dev:
free_netdev(dev);
-err_out_release_mem:
- release_mem_region(mem_base, mem_size);
-err_out:
return err;
}
@@ -948,11 +928,9 @@ static int dnet_remove(struct platform_device *pdev)
if (bp->phy_dev)
phy_disconnect(bp->phy_dev);
mdiobus_unregister(bp->mii_bus);
- kfree(bp->mii_bus->irq);
mdiobus_free(bp->mii_bus);
unregister_netdev(dev);
free_irq(dev->irq, dev);
- iounmap(bp->regs);
free_netdev(dev);
}
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index c2f5d2d3b932..43e08d0bc3d3 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -34,7 +34,7 @@
#include "be_hw.h"
#include "be_roce.h"
-#define DRV_VER "10.2u"
+#define DRV_VER "10.4u"
#define DRV_NAME "be2net"
#define BE_NAME "Emulex BladeEngine2"
#define BE3_NAME "Emulex BladeEngine3"
@@ -372,6 +372,7 @@ enum vf_state {
};
#define BE_FLAGS_LINK_STATUS_INIT 1
+#define BE_FLAGS_SRIOV_ENABLED (1 << 2)
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_FLAGS_VLAN_PROMISC (1 << 4)
#define BE_FLAGS_MCAST_PROMISC (1 << 5)
@@ -382,8 +383,10 @@ enum vf_state {
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
+
/* Ethtool set_dump flags */
#define LANCER_INITIATE_FW_DUMP 0x1
+#define LANCER_DELETE_FW_DUMP 0x2
struct phy_info {
u8 transceiver;
@@ -411,6 +414,7 @@ struct be_resources {
u16 max_vlans; /* Number of vlans supported */
u16 max_evt_qs;
u32 if_cap_flags;
+ u32 vf_if_cap_flags; /* VF if capability flags */
};
struct rss_info {
@@ -500,6 +504,7 @@ struct be_adapter {
u32 flash_status;
struct completion et_cmd_compl;
+ struct be_resources pool_res; /* resources available for the port */
struct be_resources res; /* resources available for the func */
u16 num_vfs; /* Number of VFs provisioned by PF */
u8 virtfn;
@@ -523,9 +528,9 @@ struct be_adapter {
#define be_physfn(adapter) (!adapter->virtfn)
#define be_virtfn(adapter) (adapter->virtfn)
-#define sriov_enabled(adapter) (adapter->num_vfs > 0)
-#define sriov_want(adapter) (be_physfn(adapter) && \
- (num_vfs || pci_num_vf(adapter->pdev)))
+#define sriov_enabled(adapter) (adapter->flags & \
+ BE_FLAGS_SRIOV_ENABLED)
+
#define for_all_vfs(adapter, vf_cfg, i) \
for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
i++, vf_cfg++)
@@ -536,7 +541,7 @@ struct be_adapter {
#define be_max_vlans(adapter) (adapter->res.max_vlans)
#define be_max_uc(adapter) (adapter->res.max_uc_mac)
#define be_max_mc(adapter) (adapter->res.max_mcast_mac)
-#define be_max_vfs(adapter) (adapter->res.max_vfs)
+#define be_max_vfs(adapter) (adapter->pool_res.max_vfs)
#define be_max_rss(adapter) (adapter->res.max_rss_qs)
#define be_max_txqs(adapter) (adapter->res.max_tx_qs)
#define be_max_prio_txqs(adapter) (adapter->res.max_prio_tx_qs)
@@ -671,6 +676,8 @@ static inline void swap_dws(void *wrb, int len)
#endif /* __BIG_ENDIAN */
}
+#define be_cmd_status(status) (status > 0 ? -EIO : status)
+
static inline u8 is_tcp_pkt(struct sk_buff *skb)
{
u8 val = 0;
@@ -890,5 +897,6 @@ void be_roce_dev_remove(struct be_adapter *);
*/
void be_roce_dev_open(struct be_adapter *);
void be_roce_dev_close(struct be_adapter *);
+void be_roce_dev_shutdown(struct be_adapter *);
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index f4ea3490f446..4370ec1952ac 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1749,8 +1749,7 @@ err:
}
/* Uses synchronous mcc */
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
- char *fw_on_flash)
+int be_cmd_get_fw_ver(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_get_fw_version *req;
@@ -1772,9 +1771,8 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
status = be_mcc_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
- strcpy(fw_ver, resp->firmware_version_string);
- if (fw_on_flash)
- strcpy(fw_on_flash, resp->fw_on_flash_version_string);
+ strcpy(adapter->fw_ver, resp->firmware_version_string);
+ strcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string);
}
err:
spin_unlock_bh(&adapter->mcc_lock);
@@ -1997,8 +1995,7 @@ err:
}
/* Uses mbox */
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
- u32 *mode, u32 *caps, u16 *asic_rev)
+int be_cmd_query_fw_cfg(struct be_adapter *adapter)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_query_fw_cfg *req;
@@ -2017,10 +2014,10 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
status = be_mbox_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
- *port_num = le32_to_cpu(resp->phys_port);
- *mode = le32_to_cpu(resp->function_mode);
- *caps = le32_to_cpu(resp->function_caps);
- *asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
+ adapter->port_num = le32_to_cpu(resp->phys_port);
+ adapter->function_mode = le32_to_cpu(resp->function_mode);
+ adapter->function_caps = le32_to_cpu(resp->function_caps);
+ adapter->asic_rev = le32_to_cpu(resp->asic_revision) & 0xFF;
}
mutex_unlock(&adapter->mbox_lock);
@@ -2224,7 +2221,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(60000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
@@ -2243,6 +2240,34 @@ err_unlock:
return status;
}
+int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
+{
+ struct lancer_cmd_req_delete_object *req;
+ struct be_mcc_wrb *wrb;
+ int status;
+
+ spin_lock_bh(&adapter->mcc_lock);
+
+ wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
+
+ req = embedded_payload(wrb);
+
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_DELETE_OBJECT,
+ sizeof(*req), wrb, NULL);
+
+ strcpy(req->object_name, obj_name);
+
+ status = be_mcc_notify_wait(adapter);
+err:
+ spin_unlock_bh(&adapter->mcc_lock);
+ return status;
+}
+
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, const char *obj_name,
u32 *data_read, u32 *eof, u8 *addn_status)
@@ -2320,7 +2345,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
msecs_to_jiffies(40000)))
- status = -1;
+ status = -ETIMEDOUT;
else
status = adapter->flash_status;
@@ -3313,15 +3338,28 @@ err:
return status;
}
-static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count)
+/* Descriptor type */
+enum {
+ FUNC_DESC = 1,
+ VFT_DESC = 2
+};
+
+static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+ int desc_type)
{
struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+ struct be_nic_res_desc *nic;
int i;
for (i = 0; i < desc_count; i++) {
if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 ||
- hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1)
- return (struct be_nic_res_desc *)hdr;
+ hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) {
+ nic = (struct be_nic_res_desc *)hdr;
+ if (desc_type == FUNC_DESC ||
+ (desc_type == VFT_DESC &&
+ nic->flags & (1 << VFT_SHIFT)))
+ return nic;
+ }
hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
hdr = (void *)hdr + hdr->desc_len;
@@ -3329,6 +3367,16 @@ static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count)
return NULL;
}
+static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count)
+{
+ return be_get_nic_desc(buf, desc_count, VFT_DESC);
+}
+
+static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count)
+{
+ return be_get_nic_desc(buf, desc_count, FUNC_DESC);
+}
+
static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
u32 desc_count)
{
@@ -3424,7 +3472,7 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
u32 desc_count = le32_to_cpu(resp->desc_count);
struct be_nic_res_desc *desc;
- desc = be_get_nic_desc(resp->func_param, desc_count);
+ desc = be_get_func_nic_desc(resp->func_param, desc_count);
if (!desc) {
status = -EINVAL;
goto err;
@@ -3440,76 +3488,17 @@ err:
return status;
}
-/* Uses mbox */
-static int be_cmd_get_profile_config_mbox(struct be_adapter *adapter,
- u8 domain, struct be_dma_mem *cmd)
-{
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_profile_config *req;
- int status;
-
- if (mutex_lock_interruptible(&adapter->mbox_lock))
- return -1;
- wrb = wrb_from_mbox(adapter);
-
- req = cmd->va;
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_PROFILE_CONFIG,
- cmd->size, wrb, cmd);
-
- req->type = ACTIVE_PROFILE_TYPE;
- req->hdr.domain = domain;
- if (!lancer_chip(adapter))
- req->hdr.version = 1;
-
- status = be_mbox_notify_wait(adapter);
-
- mutex_unlock(&adapter->mbox_lock);
- return status;
-}
-
-/* Uses sync mcc */
-static int be_cmd_get_profile_config_mccq(struct be_adapter *adapter,
- u8 domain, struct be_dma_mem *cmd)
-{
- struct be_mcc_wrb *wrb;
- struct be_cmd_req_get_profile_config *req;
- int status;
-
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
-
- req = cmd->va;
- be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_PROFILE_CONFIG,
- cmd->size, wrb, cmd);
-
- req->type = ACTIVE_PROFILE_TYPE;
- req->hdr.domain = domain;
- if (!lancer_chip(adapter))
- req->hdr.version = 1;
-
- status = be_mcc_notify_wait(adapter);
-
-err:
- spin_unlock_bh(&adapter->mcc_lock);
- return status;
-}
-
-/* Uses sync mcc, if MCCQ is already created otherwise mbox */
+/* Will use MBOX only if MCCQ has not been created */
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 domain)
{
struct be_cmd_resp_get_profile_config *resp;
+ struct be_cmd_req_get_profile_config *req;
+ struct be_nic_res_desc *vf_res;
struct be_pcie_res_desc *pcie;
struct be_port_res_desc *port;
struct be_nic_res_desc *nic;
- struct be_queue_info *mccq = &adapter->mcc_obj.q;
+ struct be_mcc_wrb wrb = {0};
struct be_dma_mem cmd;
u32 desc_count;
int status;
@@ -3520,10 +3509,17 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
if (!cmd.va)
return -ENOMEM;
- if (!mccq->created)
- status = be_cmd_get_profile_config_mbox(adapter, domain, &cmd);
- else
- status = be_cmd_get_profile_config_mccq(adapter, domain, &cmd);
+ req = cmd.va;
+ be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_GET_PROFILE_CONFIG,
+ cmd.size, &wrb, &cmd);
+
+ req->hdr.domain = domain;
+ if (!lancer_chip(adapter))
+ req->hdr.version = 1;
+ req->type = ACTIVE_PROFILE_TYPE;
+
+ status = be_cmd_notify_wait(adapter, &wrb);
if (status)
goto err;
@@ -3539,48 +3535,52 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
if (port)
adapter->mc_type = port->mc_type;
- nic = be_get_nic_desc(resp->func_param, desc_count);
+ nic = be_get_func_nic_desc(resp->func_param, desc_count);
if (nic)
be_copy_nic_desc(res, nic);
+ vf_res = be_get_vft_desc(resp->func_param, desc_count);
+ if (vf_res)
+ res->vf_if_cap_flags = vf_res->cap_flags;
err:
if (cmd.va)
pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
-int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
- int size, u8 version, u8 domain)
+/* Will use MBOX only if MCCQ has not been created */
+static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
+ int size, int count, u8 version, u8 domain)
{
struct be_cmd_req_set_profile_config *req;
- struct be_mcc_wrb *wrb;
+ struct be_mcc_wrb wrb = {0};
+ struct be_dma_mem cmd;
int status;
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
+ memset(&cmd, 0, sizeof(struct be_dma_mem));
+ cmd.size = sizeof(struct be_cmd_req_set_profile_config);
+ cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+ if (!cmd.va)
+ return -ENOMEM;
- req = embedded_payload(wrb);
+ req = cmd.va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
- wrb, NULL);
+ OPCODE_COMMON_SET_PROFILE_CONFIG, cmd.size,
+ &wrb, &cmd);
req->hdr.version = version;
req->hdr.domain = domain;
- req->desc_count = cpu_to_le32(1);
+ req->desc_count = cpu_to_le32(count);
memcpy(req->desc, desc, size);
- status = be_mcc_notify_wait(adapter);
-err:
- spin_unlock_bh(&adapter->mcc_lock);
+ status = be_cmd_notify_wait(adapter, &wrb);
+
+ if (cmd.va)
+ pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
return status;
}
/* Mark all fields invalid */
-void be_reset_nic_desc(struct be_nic_res_desc *nic)
+static void be_reset_nic_desc(struct be_nic_res_desc *nic)
{
memset(nic, 0, sizeof(*nic));
nic->unicast_mac_count = 0xFFFF;
@@ -3601,9 +3601,20 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic)
nic->wol_param = 0x0F;
nic->tunnel_iface_count = 0xFFFF;
nic->direct_tenant_iface_count = 0xFFFF;
+ nic->bw_min = 0xFFFFFFFF;
nic->bw_max = 0xFFFFFFFF;
}
+/* Mark all fields invalid */
+static void be_reset_pcie_desc(struct be_pcie_res_desc *pcie)
+{
+ memset(pcie, 0, sizeof(*pcie));
+ pcie->sriov_state = 0xFF;
+ pcie->pf_state = 0xFF;
+ pcie->pf_type = 0xFF;
+ pcie->num_vfs = 0xFFFF;
+}
+
int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
u8 domain)
{
@@ -3634,7 +3645,63 @@ int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
return be_cmd_set_profile_config(adapter, &nic_desc,
nic_desc.hdr.desc_len,
- version, domain);
+ 1, version, domain);
+}
+
+int be_cmd_set_sriov_config(struct be_adapter *adapter,
+ struct be_resources res, u16 num_vfs)
+{
+ struct {
+ struct be_pcie_res_desc pcie;
+ struct be_nic_res_desc nic_vft;
+ } __packed desc;
+ u16 vf_q_count;
+
+ if (BEx_chip(adapter) || lancer_chip(adapter))
+ return 0;
+
+ /* PF PCIE descriptor */
+ be_reset_pcie_desc(&desc.pcie);
+ desc.pcie.hdr.desc_type = PCIE_RESOURCE_DESC_TYPE_V1;
+ desc.pcie.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+ desc.pcie.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+ desc.pcie.pf_num = adapter->pdev->devfn;
+ desc.pcie.sriov_state = num_vfs ? 1 : 0;
+ desc.pcie.num_vfs = cpu_to_le16(num_vfs);
+
+ /* VF NIC Template descriptor */
+ be_reset_nic_desc(&desc.nic_vft);
+ desc.nic_vft.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
+ desc.nic_vft.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+ desc.nic_vft.flags = (1 << VFT_SHIFT) | (1 << IMM_SHIFT) |
+ (1 << NOSV_SHIFT);
+ desc.nic_vft.pf_num = adapter->pdev->devfn;
+ desc.nic_vft.vf_num = 0;
+
+ if (num_vfs && res.vf_if_cap_flags & BE_IF_FLAGS_RSS) {
+ /* If number of VFs requested is 8 less than max supported,
+ * assign 8 queue pairs to the PF and divide the remaining
+ * resources evenly among the VFs
+ */
+ if (num_vfs < (be_max_vfs(adapter) - 8))
+ vf_q_count = (res.max_rss_qs - 8) / num_vfs;
+ else
+ vf_q_count = res.max_rss_qs / num_vfs;
+
+ desc.nic_vft.rq_count = cpu_to_le16(vf_q_count);
+ desc.nic_vft.txq_count = cpu_to_le16(vf_q_count);
+ desc.nic_vft.rssq_count = cpu_to_le16(vf_q_count - 1);
+ desc.nic_vft.cq_count = cpu_to_le16(3 * vf_q_count);
+ } else {
+ desc.nic_vft.txq_count = cpu_to_le16(1);
+ desc.nic_vft.rq_count = cpu_to_le16(1);
+ desc.nic_vft.rssq_count = cpu_to_le16(0);
+ /* One CQ for each TX, RX and MCCQ */
+ desc.nic_vft.cq_count = cpu_to_le16(3);
+ }
+
+ return be_cmd_set_profile_config(adapter, &desc,
+ 2 * RESOURCE_DESC_SIZE_V1, 2, 1, 0);
}
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
@@ -3686,7 +3753,7 @@ int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
}
return be_cmd_set_profile_config(adapter, &port_desc,
- RESOURCE_DESC_SIZE_V1, 1, 0);
+ RESOURCE_DESC_SIZE_V1, 1, 1, 0);
}
int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
@@ -3766,13 +3833,19 @@ bool dump_present(struct be_adapter *adapter)
int lancer_initiate_dump(struct be_adapter *adapter)
{
+ struct device *dev = &adapter->pdev->dev;
int status;
+ if (dump_present(adapter)) {
+ dev_info(dev, "Previous dump not cleared, not forcing dump\n");
+ return -EEXIST;
+ }
+
/* give firmware reset and diagnostic dump */
status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
PHYSDEV_CONTROL_DD_MASK);
if (status < 0) {
- dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
+ dev_err(dev, "FW reset failed\n");
return status;
}
@@ -3781,13 +3854,21 @@ int lancer_initiate_dump(struct be_adapter *adapter)
return status;
if (!dump_present(adapter)) {
- dev_err(&adapter->pdev->dev, "Dump image not present\n");
- return -1;
+ dev_err(dev, "FW dump not generated\n");
+ return -EIO;
}
return 0;
}
+int lancer_delete_dump(struct be_adapter *adapter)
+{
+ int status;
+
+ status = lancer_cmd_delete_object(adapter, LANCER_FW_DUMP_FILE);
+ return be_cmd_status(status);
+}
+
/* Uses sync mcc */
int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
{
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 59b3c056f329..5284b825bba2 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -231,6 +231,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_FN_PRIVILEGES 170
#define OPCODE_COMMON_READ_OBJECT 171
#define OPCODE_COMMON_WRITE_OBJECT 172
+#define OPCODE_COMMON_DELETE_OBJECT 174
#define OPCODE_COMMON_MANAGE_IFACE_FILTERS 193
#define OPCODE_COMMON_GET_IFACE_LIST 194
#define OPCODE_COMMON_ENABLE_DISABLE_VF 196
@@ -1081,11 +1082,6 @@ struct be_cmd_req_modify_eq_delay {
struct be_set_eqd set_eqd[MAX_EVT_QS];
} __packed;
-struct be_cmd_resp_modify_eq_delay {
- struct be_cmd_resp_hdr hdr;
- u32 rsvd0;
-} __packed;
-
/******************** Get FW Config *******************/
/* The HW can come up in either of the following multi-channel modes
* based on the skew/IPL.
@@ -1156,11 +1152,6 @@ struct be_cmd_req_enable_disable_beacon {
u8 status_duration;
} __packed;
-struct be_cmd_resp_enable_disable_beacon {
- struct be_cmd_resp_hdr resp_hdr;
- u32 rsvd0;
-} __packed;
-
struct be_cmd_req_get_beacon_state {
struct be_cmd_req_hdr hdr;
u8 port_num;
@@ -1263,6 +1254,13 @@ struct lancer_cmd_resp_read_object {
u32 eof;
};
+struct lancer_cmd_req_delete_object {
+ struct be_cmd_req_hdr hdr;
+ u32 rsvd1;
+ u32 rsvd2;
+ u8 object_name[104];
+};
+
/************************ WOL *******************************/
struct be_cmd_req_acpi_wol_magic_config{
struct be_cmd_req_hdr hdr;
@@ -1326,11 +1324,6 @@ struct be_cmd_req_set_lmode {
u8 loopback_state;
};
-struct be_cmd_resp_set_lmode {
- struct be_cmd_resp_hdr resp_hdr;
- u8 rsvd0[4];
-};
-
/********************** DDR DMA test *********************/
struct be_cmd_req_ddrdma_test {
struct be_cmd_req_hdr hdr;
@@ -1434,11 +1427,6 @@ struct be_cmd_req_set_qos {
u32 rsvd[7];
};
-struct be_cmd_resp_set_qos {
- struct be_cmd_resp_hdr hdr;
- u32 rsvd;
-};
-
/*********************** Controller Attributes ***********************/
struct be_cmd_req_cntl_attribs {
struct be_cmd_req_hdr hdr;
@@ -1572,11 +1560,6 @@ struct be_cmd_req_set_hsw_config {
u8 context[sizeof(struct amap_set_hsw_context) / 8];
} __packed;
-struct be_cmd_resp_set_hsw_config {
- struct be_cmd_resp_hdr hdr;
- u32 rsvd;
-};
-
struct amap_get_hsw_req_context {
u8 interface_id[16];
u8 rsvd0[14];
@@ -1835,6 +1818,7 @@ struct be_cmd_req_set_ext_fat_caps {
#define PORT_RESOURCE_DESC_TYPE_V1 0x55
#define MAX_RESOURCE_DESC 264
+#define VFT_SHIFT 3 /* VF template */
#define IMM_SHIFT 6 /* Immediate */
#define NOSV_SHIFT 7 /* No save */
@@ -1962,12 +1946,8 @@ struct be_cmd_req_set_profile_config {
struct be_cmd_req_hdr hdr;
u32 rsvd;
u32 desc_count;
- u8 desc[RESOURCE_DESC_SIZE_V1];
-};
-
-struct be_cmd_resp_set_profile_config {
- struct be_cmd_resp_hdr hdr;
-};
+ u8 desc[2 * RESOURCE_DESC_SIZE_V1];
+} __packed;
struct be_cmd_req_get_active_profile {
struct be_cmd_req_hdr hdr;
@@ -2070,16 +2050,14 @@ int be_cmd_reset(struct be_adapter *adapter);
int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd);
int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd);
-int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
- char *fw_on_flash);
+int be_cmd_get_fw_ver(struct be_adapter *adapter);
int be_cmd_modify_eqd(struct be_adapter *adapter, struct be_set_eqd *, int num);
int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
u32 num);
int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc);
int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc);
-int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
- u32 *function_mode, u32 *function_caps, u16 *asic_rev);
+int be_cmd_query_fw_cfg(struct be_adapter *adapter);
int be_cmd_reset_function(struct be_adapter *adapter);
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey);
@@ -2097,6 +2075,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, const char *obj_name,
u32 *data_read, u32 *eof, u8 *addn_status);
+int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
u16 optype, int offset);
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
@@ -2150,6 +2129,7 @@ int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
struct be_fat_conf_params *cfgs);
int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
int lancer_initiate_dump(struct be_adapter *adapter);
+int lancer_delete_dump(struct be_adapter *adapter);
bool dump_present(struct be_adapter *adapter);
int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
@@ -2157,8 +2137,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter,
struct be_resources *res);
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 domain);
-int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
- int size, u8 version, u8 domain);
int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile);
int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
int vf_num);
@@ -2168,3 +2146,5 @@ int be_cmd_set_logical_link_config(struct be_adapter *adapter,
int link_state, u8 domain);
int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port);
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op);
+int be_cmd_set_sriov_config(struct be_adapter *adapter,
+ struct be_resources res, u16 num_vfs);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index e2da4d20dd3d..0cd3311409a8 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -643,7 +643,7 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
if (status)
dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
- return status;
+ return be_cmd_status(status);
}
static int be_set_phys_id(struct net_device *netdev,
@@ -681,22 +681,21 @@ static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
struct device *dev = &adapter->pdev->dev;
int status;
- if (!lancer_chip(adapter)) {
- dev_err(dev, "FW dump not supported\n");
+ if (!lancer_chip(adapter) ||
+ !check_privilege(adapter, MAX_PRIVILEGES))
return -EOPNOTSUPP;
- }
-
- if (dump_present(adapter)) {
- dev_err(dev, "Previous dump not cleared, not forcing dump\n");
- return 0;
- }
switch (dump->flag) {
case LANCER_INITIATE_FW_DUMP:
status = lancer_initiate_dump(adapter);
if (!status)
- dev_info(dev, "F/w dump initiated successfully\n");
+ dev_info(dev, "FW dump initiated successfully\n");
break;
+ case LANCER_DELETE_FW_DUMP:
+ status = lancer_delete_dump(adapter);
+ if (!status)
+ dev_info(dev, "FW dump deleted successfully\n");
+ break;
default:
dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);
return -EINVAL;
@@ -762,7 +761,7 @@ static int be_test_ddr_dma(struct be_adapter *adapter)
err:
dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
ddrdma_cmd.dma);
- return ret;
+ return be_cmd_status(ret);
}
static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
@@ -885,7 +884,7 @@ static int be_read_eeprom(struct net_device *netdev,
dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
eeprom_cmd.dma);
- return status;
+ return be_cmd_status(status);
}
static u32 be_get_msg_level(struct net_device *netdev)
@@ -1042,7 +1041,7 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
if (!status)
adapter->rss_info.rss_flags = rss_flags;
- return status;
+ return be_cmd_status(status);
}
static int be_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
@@ -1080,6 +1079,7 @@ static int be_set_channels(struct net_device *netdev,
struct ethtool_channels *ch)
{
struct be_adapter *adapter = netdev_priv(netdev);
+ int status;
if (ch->rx_count || ch->tx_count || ch->other_count ||
!ch->combined_count || ch->combined_count > be_max_qs(adapter))
@@ -1087,7 +1087,8 @@ static int be_set_channels(struct net_device *netdev,
adapter->cfg_num_qs = ch->combined_count;
- return be_update_queues(adapter);
+ status = be_update_queues(adapter);
+ return be_cmd_status(status);
}
static u32 be_get_rxfh_indir_size(struct net_device *netdev)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 1e187fb760f8..93ff8ef39352 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -39,7 +39,7 @@ static ushort rx_frag_size = 2048;
module_param(rx_frag_size, ushort, S_IRUGO);
MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
-static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
+static const struct pci_device_id be_dev_ids[] = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
@@ -81,10 +81,10 @@ static const char * const ue_status_low_desc[] = {
"P1_OB_LINK ",
"HOST_GPIO ",
"MBOX ",
- "AXGMAC0",
- "AXGMAC1",
- "JTAG",
- "MPU_INTPEND"
+ "ERX2 ",
+ "SPARE ",
+ "JTAG ",
+ "MPU_INTPEND "
};
/* UE Status High CSR */
static const char * const ue_status_hi_desc[] = {
@@ -109,16 +109,16 @@ static const char * const ue_status_hi_desc[] = {
"HOST5",
"HOST6",
"HOST7",
- "HOST8",
- "HOST9",
+ "ECRC",
+ "Poison TLP",
"NETC",
- "Unknown",
- "Unknown",
- "Unknown",
- "Unknown",
- "Unknown",
- "Unknown",
- "Unknown",
+ "PERIPH",
+ "LLTXULP",
+ "D2P",
+ "RCON",
+ "LDMA",
+ "LLTXP",
+ "LLTXPB",
"Unknown"
};
@@ -1172,20 +1172,15 @@ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
{
struct be_adapter *adapter = netdev_priv(netdev);
- int status = 0;
/* Packets with VID 0 are always received by Lancer by default */
if (lancer_chip(adapter) && vid == 0)
- goto ret;
+ return 0;
clear_bit(vid, adapter->vids);
- status = be_vid_config(adapter);
- if (!status)
- adapter->vlans_added--;
- else
- set_bit(vid, adapter->vids);
-ret:
- return status;
+ adapter->vlans_added--;
+
+ return be_vid_config(adapter);
}
static void be_clear_promisc(struct be_adapter *adapter)
@@ -1275,6 +1270,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs)
return -EINVAL;
+ /* Proceed further only if user provided MAC is different
+ * from active MAC
+ */
+ if (ether_addr_equal(mac, vf_cfg->mac_addr))
+ return 0;
+
if (BEx_chip(adapter)) {
be_cmd_pmac_del(adapter, vf_cfg->if_handle, vf_cfg->pmac_id,
vf + 1);
@@ -1286,13 +1287,15 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
vf + 1);
}
- if (status)
- dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
- mac, vf);
- else
- memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
+ if (status) {
+ dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed: %#x",
+ mac, vf, status);
+ return be_cmd_status(status);
+ }
- return status;
+ ether_addr_copy(vf_cfg->mac_addr, mac);
+
+ return 0;
}
static int be_get_vf_config(struct net_device *netdev, int vf,
@@ -1341,12 +1344,16 @@ static int be_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
vf + 1, vf_cfg->if_handle, 0);
}
- if (!status)
- vf_cfg->vlan_tag = vlan;
- else
- dev_info(&adapter->pdev->dev,
- "VLAN %d config on VF %d failed\n", vlan, vf);
- return status;
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "VLAN %d config on VF %d failed : %#x\n", vlan,
+ vf, status);
+ return be_cmd_status(status);
+ }
+
+ vf_cfg->vlan_tag = vlan;
+
+ return 0;
}
static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
@@ -1377,7 +1384,7 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
if (!link_status) {
dev_err(dev, "TX-rate setting not allowed when link is down\n");
- status = -EPERM;
+ status = -ENETDOWN;
goto err;
}
@@ -1408,7 +1415,7 @@ config_qos:
err:
dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n",
max_tx_rate, vf);
- return status;
+ return be_cmd_status(status);
}
static int be_set_vf_link_state(struct net_device *netdev, int vf,
int link_state)
@@ -1423,10 +1430,15 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf,
return -EINVAL;
status = be_cmd_set_logical_link_config(adapter, link_state, vf+1);
- if (!status)
- adapter->vf_cfg[vf].plink_tracking = link_state;
+ if (status) {
+ dev_err(&adapter->pdev->dev,
+ "Link state change on VF %d failed: %#x\n", vf, status);
+ return be_cmd_status(status);
+ }
- return status;
+ adapter->vf_cfg[vf].plink_tracking = link_state;
+
+ return 0;
}
static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
@@ -2028,7 +2040,7 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
*/
for (;;) {
rxcp = be_rx_compl_get(rxo);
- if (rxcp == NULL) {
+ if (!rxcp) {
if (lancer_chip(adapter))
break;
@@ -2935,8 +2947,8 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
GFP_KERNEL);
- if (cmd.va == NULL)
- return -1;
+ if (!cmd.va)
+ return -ENOMEM;
if (enable) {
status = pci_write_config_dword(adapter->pdev,
@@ -3043,6 +3055,7 @@ static void be_vf_clear(struct be_adapter *adapter)
done:
kfree(adapter->vf_cfg);
adapter->num_vfs = 0;
+ adapter->flags &= ~BE_FLAGS_SRIOV_ENABLED;
}
static void be_clear_queues(struct be_adapter *adapter)
@@ -3098,6 +3111,13 @@ static int be_clear(struct be_adapter *adapter)
if (sriov_enabled(adapter))
be_vf_clear(adapter);
+ /* Re-configure FW to distribute resources evenly across max-supported
+ * number of VFs, only when VFs are not already enabled.
+ */
+ if (be_physfn(adapter) && !pci_vfs_assigned(adapter->pdev))
+ be_cmd_set_sriov_config(adapter, adapter->pool_res,
+ pci_sriov_get_totalvfs(adapter->pdev));
+
#ifdef CONFIG_BE2NET_VXLAN
be_disable_vxlan_offloads(adapter);
#endif
@@ -3170,19 +3190,6 @@ static int be_vf_setup(struct be_adapter *adapter)
u32 privileges;
old_vfs = pci_num_vf(adapter->pdev);
- if (old_vfs) {
- dev_info(dev, "%d VFs are already enabled\n", old_vfs);
- if (old_vfs != num_vfs)
- dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
- adapter->num_vfs = old_vfs;
- } else {
- if (num_vfs > be_max_vfs(adapter))
- dev_info(dev, "Device supports %d VFs and not %d\n",
- be_max_vfs(adapter), num_vfs);
- adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter));
- if (!adapter->num_vfs)
- return 0;
- }
status = be_vf_setup_init(adapter);
if (status)
@@ -3194,17 +3201,15 @@ static int be_vf_setup(struct be_adapter *adapter)
if (status)
goto err;
}
- } else {
- status = be_vfs_if_create(adapter);
- if (status)
- goto err;
- }
- if (old_vfs) {
status = be_vfs_mac_query(adapter);
if (status)
goto err;
} else {
+ status = be_vfs_if_create(adapter);
+ if (status)
+ goto err;
+
status = be_vf_eth_addr_config(adapter);
if (status)
goto err;
@@ -3243,6 +3248,8 @@ static int be_vf_setup(struct be_adapter *adapter)
goto err;
}
}
+
+ adapter->flags |= BE_FLAGS_SRIOV_ENABLED;
return 0;
err:
dev_err(dev, "VF setup failed\n");
@@ -3270,19 +3277,7 @@ static u8 be_convert_mc_type(u32 function_mode)
static void BEx_get_resources(struct be_adapter *adapter,
struct be_resources *res)
{
- struct pci_dev *pdev = adapter->pdev;
- bool use_sriov = false;
- int max_vfs = 0;
-
- if (be_physfn(adapter) && BE3_chip(adapter)) {
- be_cmd_get_profile_config(adapter, res, 0);
- /* Some old versions of BE3 FW don't report max_vfs value */
- if (res->max_vfs == 0) {
- max_vfs = pci_sriov_get_totalvfs(pdev);
- res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
- }
- use_sriov = res->max_vfs && sriov_want(adapter);
- }
+ bool use_sriov = adapter->num_vfs ? 1 : 0;
if (be_physfn(adapter))
res->max_uc_mac = BE_UC_PMAC_COUNT;
@@ -3326,7 +3321,7 @@ static void BEx_get_resources(struct be_adapter *adapter,
res->max_rx_qs = res->max_rss_qs + 1;
if (be_physfn(adapter))
- res->max_evt_qs = (res->max_vfs > 0) ?
+ res->max_evt_qs = (be_max_vfs(adapter) > 0) ?
BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
else
res->max_evt_qs = 1;
@@ -3349,6 +3344,51 @@ static void be_setup_init(struct be_adapter *adapter)
adapter->cmd_privileges = MIN_PRIVILEGES;
}
+static int be_get_sriov_config(struct be_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ struct be_resources res = {0};
+ int max_vfs, old_vfs;
+
+ /* Some old versions of BE3 FW don't report max_vfs value */
+ be_cmd_get_profile_config(adapter, &res, 0);
+
+ if (BE3_chip(adapter) && !res.max_vfs) {
+ max_vfs = pci_sriov_get_totalvfs(adapter->pdev);
+ res.max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
+ }
+
+ adapter->pool_res = res;
+
+ if (!be_max_vfs(adapter)) {
+ if (num_vfs)
+ dev_warn(dev, "device doesn't support SRIOV\n");
+ adapter->num_vfs = 0;
+ return 0;
+ }
+
+ pci_sriov_set_totalvfs(adapter->pdev, be_max_vfs(adapter));
+
+ /* validate num_vfs module param */
+ old_vfs = pci_num_vf(adapter->pdev);
+ if (old_vfs) {
+ dev_info(dev, "%d VFs are already enabled\n", old_vfs);
+ if (old_vfs != num_vfs)
+ dev_warn(dev, "Ignoring num_vfs=%d setting\n", num_vfs);
+ adapter->num_vfs = old_vfs;
+ } else {
+ if (num_vfs > be_max_vfs(adapter)) {
+ dev_info(dev, "Resources unavailable to init %d VFs\n",
+ num_vfs);
+ dev_info(dev, "Limiting to %d VFs\n",
+ be_max_vfs(adapter));
+ }
+ adapter->num_vfs = min_t(u16, num_vfs, be_max_vfs(adapter));
+ }
+
+ return 0;
+}
+
static int be_get_resources(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
@@ -3374,13 +3414,6 @@ static int be_get_resources(struct be_adapter *adapter)
res.max_evt_qs /= 2;
adapter->res = res;
- if (be_physfn(adapter)) {
- status = be_cmd_get_profile_config(adapter, &res, 0);
- if (status)
- return status;
- adapter->res.max_vfs = res.max_vfs;
- }
-
dev_info(dev, "Max: txqs %d, rxqs %d, rss %d, eqs %d, vfs %d\n",
be_max_txqs(adapter), be_max_rxqs(adapter),
be_max_rss(adapter), be_max_eqs(adapter),
@@ -3393,16 +3426,41 @@ static int be_get_resources(struct be_adapter *adapter)
return 0;
}
-/* Routine to query per function resource limits */
+static void be_sriov_config(struct be_adapter *adapter)
+{
+ struct device *dev = &adapter->pdev->dev;
+ int status;
+
+ status = be_get_sriov_config(adapter);
+ if (status) {
+ dev_err(dev, "Failed to query SR-IOV configuration\n");
+ dev_err(dev, "SR-IOV cannot be enabled\n");
+ return;
+ }
+
+ /* When the HW is in SRIOV capable configuration, the PF-pool
+ * resources are equally distributed across the max-number of
+ * VFs. The user may request only a subset of the max-vfs to be
+ * enabled. Based on num_vfs, redistribute the resources across
+ * num_vfs so that each VF will have access to more number of
+ * resources. This facility is not available in BE3 FW.
+ * Also, this is done by FW in Lancer chip.
+ */
+ if (be_max_vfs(adapter) && !pci_num_vf(adapter->pdev)) {
+ status = be_cmd_set_sriov_config(adapter,
+ adapter->pool_res,
+ adapter->num_vfs);
+ if (status)
+ dev_err(dev, "Failed to optimize SR-IOV resources\n");
+ }
+}
+
static int be_get_config(struct be_adapter *adapter)
{
u16 profile_id;
int status;
- status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
- &adapter->function_mode,
- &adapter->function_caps,
- &adapter->asic_rev);
+ status = be_cmd_query_fw_cfg(adapter);
if (status)
return status;
@@ -3413,6 +3471,9 @@ static int be_get_config(struct be_adapter *adapter)
"Using profile 0x%x\n", profile_id);
}
+ if (!BE2_chip(adapter) && be_physfn(adapter))
+ be_sriov_config(adapter);
+
status = be_get_resources(adapter);
if (status)
return status;
@@ -3571,7 +3632,7 @@ static int be_setup(struct be_adapter *adapter)
if (status)
goto err;
- be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash);
+ be_cmd_get_fw_ver(adapter);
if (BE2_chip(adapter) && fw_major_num(adapter->fw_ver) < 4) {
dev_err(dev, "Firmware on card is old(%s), IRQs may not work.",
@@ -3596,12 +3657,8 @@ static int be_setup(struct be_adapter *adapter)
be_cmd_set_logical_link_config(adapter,
IFLA_VF_LINK_STATE_AUTO, 0);
- if (sriov_want(adapter)) {
- if (be_max_vfs(adapter))
- be_vf_setup(adapter);
- else
- dev_warn(dev, "device doesn't support SRIOV\n");
- }
+ if (adapter->num_vfs)
+ be_vf_setup(adapter);
status = be_cmd_get_phy_info(adapter);
if (!status && be_pause_supported(adapter))
@@ -3925,7 +3982,7 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
if (!fsec) {
dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
- return -1;
+ return -EINVAL;
}
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
@@ -4094,7 +4151,7 @@ lancer_fw_exit:
static int be_get_ufi_type(struct be_adapter *adapter,
struct flash_file_hdr_g3 *fhdr)
{
- if (fhdr == NULL)
+ if (!fhdr)
goto be_get_ufi_exit;
if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
@@ -4156,7 +4213,7 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
&flash_cmd,
num_imgs);
else {
- status = -1;
+ status = -EINVAL;
dev_err(&adapter->pdev->dev,
"Can't load BE3 UFI on BE3R\n");
}
@@ -4167,7 +4224,7 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
if (ufi_type == UFI_TYPE2)
status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
else if (ufi_type == -1)
- status = -1;
+ status = -EINVAL;
dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
flash_cmd.dma);
@@ -4190,7 +4247,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
if (!netif_running(adapter->netdev)) {
dev_err(&adapter->pdev->dev,
"Firmware load not allowed (interface is down)\n");
- return -1;
+ return -ENETDOWN;
}
status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
@@ -4205,8 +4262,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
status = be_fw_download(adapter, fw);
if (!status)
- be_cmd_get_fw_ver(adapter, adapter->fw_ver,
- adapter->fw_on_flash);
+ be_cmd_get_fw_ver(adapter);
fw_exit:
release_firmware(fw);
@@ -4437,12 +4493,12 @@ static int be_map_pci_bars(struct be_adapter *adapter)
if (BEx_chip(adapter) && be_physfn(adapter)) {
adapter->csr = pci_iomap(adapter->pdev, 2, 0);
- if (adapter->csr == NULL)
+ if (!adapter->csr)
return -ENOMEM;
}
addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
- if (addr == NULL)
+ if (!addr)
goto pci_map_err;
adapter->db = addr;
@@ -4505,7 +4561,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
rx_filter->va = dma_zalloc_coherent(&adapter->pdev->dev,
rx_filter->size, &rx_filter->dma,
GFP_KERNEL);
- if (rx_filter->va == NULL) {
+ if (!rx_filter->va) {
status = -ENOMEM;
goto free_mbox;
}
@@ -4554,8 +4610,8 @@ static int be_stats_init(struct be_adapter *adapter)
cmd->va = dma_zalloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
GFP_KERNEL);
- if (cmd->va == NULL)
- return -1;
+ if (!cmd->va)
+ return -ENOMEM;
return 0;
}
@@ -4776,7 +4832,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
pci_set_master(pdev);
netdev = alloc_etherdev_mqs(sizeof(*adapter), MAX_TX_QS, MAX_RX_QS);
- if (netdev == NULL) {
+ if (!netdev) {
status = -ENOMEM;
goto rel_reg;
}
@@ -4958,6 +5014,7 @@ static void be_shutdown(struct pci_dev *pdev)
if (!adapter)
return;
+ be_roce_dev_shutdown(adapter);
cancel_delayed_work_sync(&adapter->work);
cancel_delayed_work_sync(&adapter->func_recovery_work);
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index 5bf16603a3e9..ef4672dc7357 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -120,7 +120,8 @@ static void _be_roce_dev_open(struct be_adapter *adapter)
{
if (ocrdma_drv && adapter->ocrdma_dev &&
ocrdma_drv->state_change_handler)
- ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 0);
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+ BE_DEV_UP);
}
void be_roce_dev_open(struct be_adapter *adapter)
@@ -136,7 +137,8 @@ static void _be_roce_dev_close(struct be_adapter *adapter)
{
if (ocrdma_drv && adapter->ocrdma_dev &&
ocrdma_drv->state_change_handler)
- ocrdma_drv->state_change_handler(adapter->ocrdma_dev, 1);
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+ BE_DEV_DOWN);
}
void be_roce_dev_close(struct be_adapter *adapter)
@@ -148,6 +150,18 @@ void be_roce_dev_close(struct be_adapter *adapter)
}
}
+void be_roce_dev_shutdown(struct be_adapter *adapter)
+{
+ if (be_roce_supported(adapter)) {
+ mutex_lock(&be_adapter_list_lock);
+ if (ocrdma_drv && adapter->ocrdma_dev &&
+ ocrdma_drv->state_change_handler)
+ ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
+ BE_DEV_SHUTDOWN);
+ mutex_unlock(&be_adapter_list_lock);
+ }
+}
+
int be_roce_register_driver(struct ocrdma_driver *drv)
{
struct be_adapter *dev;
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
index a3d9e96c18eb..e6f7eb1a7d87 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.h
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -62,7 +62,8 @@ struct ocrdma_driver {
enum {
BE_DEV_UP = 0,
- BE_DEV_DOWN = 1
+ BE_DEV_DOWN = 1,
+ BE_DEV_SHUTDOWN = 2
};
/* APIs for RoCE driver to register callback handlers,
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c
index 4b22a9579f85..b1b9ebafb354 100644
--- a/drivers/net/ethernet/fealnx.c
+++ b/drivers/net/ethernet/fealnx.c
@@ -1936,7 +1936,7 @@ static int netdev_close(struct net_device *dev)
return 0;
}
-static DEFINE_PCI_DEVICE_TABLE(fealnx_pci_tbl) = {
+static const struct pci_device_id fealnx_pci_tbl[] = {
{0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
{0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 671d080105a7..9f7fa644a397 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -256,12 +256,6 @@ struct bufdesc_ex {
#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
-struct fec_enet_delayed_work {
- struct delayed_work delay_work;
- bool timeout;
- bool trig_tx;
-};
-
/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
* tx_bd_base always point to the base of the buffer descriptors. The
* cur_rx and cur_tx point to the currently available buffer.
@@ -308,7 +302,6 @@ struct fec_enet_private {
struct platform_device *pdev;
- int opened;
int dev_id;
/* Phylib and MDIO interface */
@@ -317,6 +310,7 @@ struct fec_enet_private {
int mii_timeout;
uint phy_speed;
phy_interface_t phy_interface;
+ struct device_node *phy_node;
int link;
int full_duplex;
int speed;
@@ -328,6 +322,8 @@ struct fec_enet_private {
struct napi_struct napi;
int csum_flags;
+ struct work_struct tx_timeout_work;
+
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_caps;
unsigned long last_overflow_check;
@@ -340,7 +336,6 @@ struct fec_enet_private {
int hwts_rx_en;
int hwts_tx_en;
struct timer_list time_keep;
- struct fec_enet_delayed_work delay_work;
struct regulator *reg_phy;
};
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 77037fd377b8..4f87dffcb9b2 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -52,6 +52,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/regulator/consumer.h>
#include <linux/if_vlan.h>
@@ -320,6 +321,27 @@ static void *swap_buffer(void *bufaddr, int len)
return bufaddr;
}
+static void fec_dump(struct net_device *ndev)
+{
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ struct bufdesc *bdp = fep->tx_bd_base;
+ unsigned int index = 0;
+
+ netdev_info(ndev, "TX ring dump\n");
+ pr_info("Nr SC addr len SKB\n");
+
+ do {
+ pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n",
+ index,
+ bdp == fep->cur_tx ? 'S' : ' ',
+ bdp == fep->dirty_tx ? 'H' : ' ',
+ bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen,
+ fep->tx_skbuff[index]);
+ bdp = fec_enet_get_nextdesc(bdp, fep);
+ index++;
+ } while (bdp != fep->tx_bd_base);
+}
+
static inline bool is_ipv4_pkt(struct sk_buff *skb)
{
return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
@@ -342,22 +364,6 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
return 0;
}
-static void
-fec_enet_submit_work(struct bufdesc *bdp, struct fec_enet_private *fep)
-{
- const struct platform_device_id *id_entry =
- platform_get_device_id(fep->pdev);
- struct bufdesc *bdp_pre;
-
- bdp_pre = fec_enet_get_prevdesc(bdp, fep);
- if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
- !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
- fep->delay_work.trig_tx = true;
- schedule_delayed_work(&(fep->delay_work.delay_work),
- msecs_to_jiffies(1));
- }
-}
-
static int
fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)
{
@@ -373,6 +379,7 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)
skb_frag_t *this_frag;
unsigned int index;
void *bufaddr;
+ dma_addr_t addr;
int i;
for (frag = 0; frag < nr_frags; frag++) {
@@ -415,15 +422,16 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev)
swap_buffer(bufaddr, frag_len);
}
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
- frag_len, DMA_TO_DEVICE);
- if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&fep->pdev->dev, addr)) {
dev_kfree_skb_any(skb);
if (net_ratelimit())
netdev_err(ndev, "Tx DMA memory map failed\n");
goto dma_mapping_error;
}
+ bdp->cbd_bufaddr = addr;
bdp->cbd_datlen = frag_len;
bdp->cbd_sc = status;
}
@@ -450,6 +458,7 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)
int nr_frags = skb_shinfo(skb)->nr_frags;
struct bufdesc *bdp, *last_bdp;
void *bufaddr;
+ dma_addr_t addr;
unsigned short status;
unsigned short buflen;
unsigned int estatus = 0;
@@ -490,12 +499,9 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)
swap_buffer(bufaddr, buflen);
}
- /* Push the data cache so the CPM does not get stale memory
- * data.
- */
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
- buflen, DMA_TO_DEVICE);
- if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ /* Push the data cache so the CPM does not get stale memory data. */
+ addr = dma_map_single(&fep->pdev->dev, bufaddr, buflen, DMA_TO_DEVICE);
+ if (dma_mapping_error(&fep->pdev->dev, addr)) {
dev_kfree_skb_any(skb);
if (net_ratelimit())
netdev_err(ndev, "Tx DMA memory map failed\n");
@@ -537,6 +543,7 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)
fep->tx_skbuff[index] = skb;
bdp->cbd_datlen = buflen;
+ bdp->cbd_bufaddr = addr;
/* Send it on its way. Tell FEC it's ready, interrupt when done,
* it's the last BD of the frame, and to put the CRC on the end.
@@ -544,8 +551,6 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev)
status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
bdp->cbd_sc = status;
- fec_enet_submit_work(bdp, fep);
-
/* If this was the last BD in the ring, start at the beginning again. */
bdp = fec_enet_get_nextdesc(last_bdp, fep);
@@ -570,12 +575,12 @@ fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev,
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
unsigned short status;
unsigned int estatus = 0;
+ dma_addr_t addr;
status = bdp->cbd_sc;
status &= ~BD_ENET_TX_STATS;
status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
- bdp->cbd_datlen = size;
if (((unsigned long) data) & FEC_ALIGNMENT ||
id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) {
@@ -586,15 +591,17 @@ fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev,
swap_buffer(data, size);
}
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
+ if (dma_mapping_error(&fep->pdev->dev, addr)) {
dev_kfree_skb_any(skb);
if (net_ratelimit())
netdev_err(ndev, "Tx DMA memory map failed\n");
return NETDEV_TX_BUSY;
}
+ bdp->cbd_datlen = size;
+ bdp->cbd_bufaddr = addr;
+
if (fep->bufdesc_ex) {
if (skb->ip_summed == CHECKSUM_PARTIAL)
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
@@ -732,8 +739,6 @@ static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev)
/* Save skb pointer */
fep->tx_skbuff[index] = skb;
- fec_enet_submit_work(bdp, fep);
-
skb_tx_timestamp(skb);
fep->cur_tx = bdp;
@@ -801,7 +806,7 @@ static void fec_enet_bd_init(struct net_device *dev)
/* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = 0;
- if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+ if (fep->tx_skbuff[i]) {
dev_kfree_skb_any(fep->tx_skbuff[i]);
fep->tx_skbuff[i] = NULL;
}
@@ -815,12 +820,13 @@ static void fec_enet_bd_init(struct net_device *dev)
fep->dirty_tx = bdp;
}
-/* This function is called to start or restart the FEC during a link
- * change. This only happens when switching between half and full
- * duplex.
+/*
+ * This function is called to start or restart the FEC during a link
+ * change, transmit timeout, or to reconfigure the FEC. The network
+ * packet processing for this device must be stopped before this call.
*/
static void
-fec_restart(struct net_device *ndev, int duplex)
+fec_restart(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry =
@@ -831,13 +837,6 @@ fec_restart(struct net_device *ndev, int duplex)
u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = 0x2; /* ETHEREN */
- if (netif_running(ndev)) {
- netif_device_detach(ndev);
- napi_disable(&fep->napi);
- netif_stop_queue(ndev);
- netif_tx_lock_bh(ndev);
- }
-
/* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
@@ -878,7 +877,7 @@ fec_restart(struct net_device *ndev, int duplex)
}
/* Enable MII mode */
- if (duplex) {
+ if (fep->full_duplex == DUPLEX_FULL) {
/* FD enable */
writel(0x04, fep->hwp + FEC_X_CNTRL);
} else {
@@ -887,8 +886,6 @@ fec_restart(struct net_device *ndev, int duplex)
writel(0x0, fep->hwp + FEC_X_CNTRL);
}
- fep->full_duplex = duplex;
-
/* Set MII speed */
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
@@ -1006,13 +1003,6 @@ fec_restart(struct net_device *ndev, int duplex)
/* Enable interrupts we wish to service */
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-
- if (netif_running(ndev)) {
- netif_tx_unlock_bh(ndev);
- netif_wake_queue(ndev);
- napi_enable(&fep->napi);
- netif_device_attach(ndev);
- }
}
static void
@@ -1050,29 +1040,44 @@ fec_timeout(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ fec_dump(ndev);
+
ndev->stats.tx_errors++;
- fep->delay_work.timeout = true;
- schedule_delayed_work(&(fep->delay_work.delay_work), 0);
+ schedule_work(&fep->tx_timeout_work);
}
-static void fec_enet_work(struct work_struct *work)
+static void fec_enet_timeout_work(struct work_struct *work)
{
struct fec_enet_private *fep =
- container_of(work,
- struct fec_enet_private,
- delay_work.delay_work.work);
+ container_of(work, struct fec_enet_private, tx_timeout_work);
+ struct net_device *ndev = fep->netdev;
- if (fep->delay_work.timeout) {
- fep->delay_work.timeout = false;
- fec_restart(fep->netdev, fep->full_duplex);
- netif_wake_queue(fep->netdev);
+ rtnl_lock();
+ if (netif_device_present(ndev) || netif_running(ndev)) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(ndev);
+ fec_restart(ndev);
+ netif_wake_queue(ndev);
+ netif_tx_unlock_bh(ndev);
+ napi_enable(&fep->napi);
}
+ rtnl_unlock();
+}
- if (fep->delay_work.trig_tx) {
- fep->delay_work.trig_tx = false;
- writel(0, fep->hwp + FEC_X_DES_ACTIVE);
- }
+static void
+fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
+ struct skb_shared_hwtstamps *hwtstamps)
+{
+ unsigned long flags;
+ u64 ns;
+
+ spin_lock_irqsave(&fep->tmreg_lock, flags);
+ ns = timecounter_cyc2time(&fep->tc, ts);
+ spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+ memset(hwtstamps, 0, sizeof(*hwtstamps));
+ hwtstamps->hwtstamp = ns_to_ktime(ns);
}
static void
@@ -1100,6 +1105,7 @@ fec_enet_tx(struct net_device *ndev)
index = fec_enet_get_bd_index(fep->tx_bd_base, bdp, fep);
skb = fep->tx_skbuff[index];
+ fep->tx_skbuff[index] = NULL;
if (!IS_TSO_HEADER(fep, bdp->cbd_bufaddr))
dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
bdp->cbd_datlen, DMA_TO_DEVICE);
@@ -1132,20 +1138,12 @@ fec_enet_tx(struct net_device *ndev)
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
fep->bufdesc_ex) {
struct skb_shared_hwtstamps shhwtstamps;
- unsigned long flags;
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
- memset(&shhwtstamps, 0, sizeof(shhwtstamps));
- spin_lock_irqsave(&fep->tmreg_lock, flags);
- shhwtstamps.hwtstamp = ns_to_ktime(
- timecounter_cyc2time(&fep->tc, ebdp->ts));
- spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+ fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps);
skb_tstamp_tx(skb, &shhwtstamps);
}
- if (status & BD_ENET_TX_READY)
- netdev_err(ndev, "HEY! Enet xmit interrupt and TX_READY\n");
-
/* Deferred means some collisions occurred during transmit,
* but we eventually sent the packet OK.
*/
@@ -1154,7 +1152,6 @@ fec_enet_tx(struct net_device *ndev)
/* Free the sk buffer associated with this last transmit */
dev_kfree_skb_any(skb);
- fep->tx_skbuff[index] = NULL;
fep->dirty_tx = bdp;
@@ -1169,7 +1166,10 @@ fec_enet_tx(struct net_device *ndev)
netif_wake_queue(ndev);
}
}
- return;
+
+ /* ERR006538: Keep the transmitter going */
+ if (bdp != fep->cur_tx && readl(fep->hwp + FEC_X_DES_ACTIVE) == 0)
+ writel(0, fep->hwp + FEC_X_DES_ACTIVE);
}
/* During a receive, the cur_rx points to the current incoming buffer.
@@ -1215,8 +1215,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
if ((status & BD_ENET_RX_LAST) == 0)
netdev_err(ndev, "rcv is not +last\n");
- if (!fep->opened)
- goto rx_processing_done;
+ writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
/* Check for errors. */
if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
@@ -1300,18 +1299,9 @@ fec_enet_rx(struct net_device *ndev, int budget)
skb->protocol = eth_type_trans(skb, ndev);
/* Get receive timestamp from the skb */
- if (fep->hwts_rx_en && fep->bufdesc_ex) {
- struct skb_shared_hwtstamps *shhwtstamps =
- skb_hwtstamps(skb);
- unsigned long flags;
-
- memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-
- spin_lock_irqsave(&fep->tmreg_lock, flags);
- shhwtstamps->hwtstamp = ns_to_ktime(
- timecounter_cyc2time(&fep->tc, ebdp->ts));
- spin_unlock_irqrestore(&fep->tmreg_lock, flags);
- }
+ if (fep->hwts_rx_en && fep->bufdesc_ex)
+ fec_enet_hwtstamp(fep, ebdp->ts,
+ skb_hwtstamps(skb));
if (fep->bufdesc_ex &&
(fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
@@ -1369,29 +1359,25 @@ fec_enet_interrupt(int irq, void *dev_id)
{
struct net_device *ndev = dev_id;
struct fec_enet_private *fep = netdev_priv(ndev);
+ const unsigned napi_mask = FEC_ENET_RXF | FEC_ENET_TXF;
uint int_events;
irqreturn_t ret = IRQ_NONE;
- do {
- int_events = readl(fep->hwp + FEC_IEVENT);
- writel(int_events, fep->hwp + FEC_IEVENT);
+ int_events = readl(fep->hwp + FEC_IEVENT);
+ writel(int_events & ~napi_mask, fep->hwp + FEC_IEVENT);
- if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
- ret = IRQ_HANDLED;
+ if (int_events & napi_mask) {
+ ret = IRQ_HANDLED;
- /* Disable the RX interrupt */
- if (napi_schedule_prep(&fep->napi)) {
- writel(FEC_RX_DISABLED_IMASK,
- fep->hwp + FEC_IMASK);
- __napi_schedule(&fep->napi);
- }
- }
+ /* Disable the NAPI interrupts */
+ writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+ napi_schedule(&fep->napi);
+ }
- if (int_events & FEC_ENET_MII) {
- ret = IRQ_HANDLED;
- complete(&fep->mdio_done);
- }
- } while (int_events);
+ if (int_events & FEC_ENET_MII) {
+ ret = IRQ_HANDLED;
+ complete(&fep->mdio_done);
+ }
return ret;
}
@@ -1399,8 +1385,16 @@ fec_enet_interrupt(int irq, void *dev_id)
static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
{
struct net_device *ndev = napi->dev;
- int pkts = fec_enet_rx(ndev, budget);
struct fec_enet_private *fep = netdev_priv(ndev);
+ int pkts;
+
+ /*
+ * Clear any pending transmit or receive interrupts before
+ * processing the rings to avoid racing with the hardware.
+ */
+ writel(FEC_ENET_RXF | FEC_ENET_TXF, fep->hwp + FEC_IEVENT);
+
+ pkts = fec_enet_rx(ndev, budget);
fec_enet_tx(ndev);
@@ -1498,14 +1492,23 @@ static void fec_enet_adjust_link(struct net_device *ndev)
return;
}
- if (phy_dev->link) {
+ /*
+ * If the netdev is down, or is going down, we're not interested
+ * in link state events, so just mark our idea of the link as down
+ * and ignore the event.
+ */
+ if (!netif_running(ndev) || !netif_device_present(ndev)) {
+ fep->link = 0;
+ } else if (phy_dev->link) {
if (!fep->link) {
fep->link = phy_dev->link;
status_change = 1;
}
- if (fep->full_duplex != phy_dev->duplex)
+ if (fep->full_duplex != phy_dev->duplex) {
+ fep->full_duplex = phy_dev->duplex;
status_change = 1;
+ }
if (phy_dev->speed != fep->speed) {
fep->speed = phy_dev->speed;
@@ -1513,11 +1516,21 @@ static void fec_enet_adjust_link(struct net_device *ndev)
}
/* if any of the above changed restart the FEC */
- if (status_change)
- fec_restart(ndev, phy_dev->duplex);
+ if (status_change) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(ndev);
+ fec_restart(ndev);
+ netif_wake_queue(ndev);
+ netif_tx_unlock_bh(ndev);
+ napi_enable(&fep->napi);
+ }
} else {
if (fep->link) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(ndev);
fec_stop(ndev);
+ netif_tx_unlock_bh(ndev);
+ napi_enable(&fep->napi);
fep->link = phy_dev->link;
status_change = 1;
}
@@ -1636,29 +1649,37 @@ static int fec_enet_mii_probe(struct net_device *ndev)
fep->phy_dev = NULL;
- /* check for attached phy */
- for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
- if ((fep->mii_bus->phy_mask & (1 << phy_id)))
- continue;
- if (fep->mii_bus->phy_map[phy_id] == NULL)
- continue;
- if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
- continue;
- if (dev_id--)
- continue;
- strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
- break;
- }
+ if (fep->phy_node) {
+ phy_dev = of_phy_connect(ndev, fep->phy_node,
+ &fec_enet_adjust_link, 0,
+ fep->phy_interface);
+ } else {
+ /* check for attached phy */
+ for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+ if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+ continue;
+ if (fep->mii_bus->phy_map[phy_id] == NULL)
+ continue;
+ if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+ continue;
+ if (dev_id--)
+ continue;
+ strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+ break;
+ }
+
+ if (phy_id >= PHY_MAX_ADDR) {
+ netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
+ strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+ phy_id = 0;
+ }
- if (phy_id >= PHY_MAX_ADDR) {
- netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
- strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
- phy_id = 0;
+ snprintf(phy_name, sizeof(phy_name),
+ PHY_ID_FMT, mdio_bus_id, phy_id);
+ phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
+ fep->phy_interface);
}
- snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
- phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
- fep->phy_interface);
if (IS_ERR(phy_dev)) {
netdev_err(ndev, "could not attach to PHY\n");
return PTR_ERR(phy_dev);
@@ -1667,6 +1688,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
/* mask with MAC supported features */
if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
phy_dev->supported &= PHY_GBIT_FEATURES;
+ phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
#if !defined(CONFIG_M5272)
phy_dev->supported |= SUPPORTED_Pause;
#endif
@@ -1694,6 +1716,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
struct fec_enet_private *fep = netdev_priv(ndev);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
+ struct device_node *node;
int err = -ENXIO, i;
/*
@@ -1761,7 +1784,15 @@ static int fec_enet_mii_init(struct platform_device *pdev)
for (i = 0; i < PHY_MAX_ADDR; i++)
fep->mii_bus->irq[i] = PHY_POLL;
- if (mdiobus_register(fep->mii_bus))
+ node = of_get_child_by_name(pdev->dev.of_node, "mdio");
+ if (node) {
+ err = of_mdiobus_register(fep->mii_bus, node);
+ of_node_put(node);
+ } else {
+ err = mdiobus_register(fep->mii_bus);
+ }
+
+ if (err)
goto err_out_free_mdio_irq;
mii_cnt++;
@@ -1870,6 +1901,9 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ if (!fep->phy_dev)
+ return -ENODEV;
+
if (pause->tx_pause != pause->rx_pause) {
netdev_info(ndev,
"hardware only support enable/disable both tx and rx");
@@ -1895,8 +1929,14 @@ static int fec_enet_set_pauseparam(struct net_device *ndev,
fec_stop(ndev);
phy_start_aneg(fep->phy_dev);
}
- if (netif_running(ndev))
- fec_restart(ndev, 0);
+ if (netif_running(ndev)) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(ndev);
+ fec_restart(ndev);
+ netif_wake_queue(ndev);
+ netif_tx_unlock_bh(ndev);
+ napi_enable(&fep->napi);
+ }
return 0;
}
@@ -2013,21 +2053,19 @@ static int fec_enet_nway_reset(struct net_device *dev)
}
static const struct ethtool_ops fec_enet_ethtool_ops = {
-#if !defined(CONFIG_M5272)
- .get_pauseparam = fec_enet_get_pauseparam,
- .set_pauseparam = fec_enet_set_pauseparam,
-#endif
.get_settings = fec_enet_get_settings,
.set_settings = fec_enet_set_settings,
.get_drvinfo = fec_enet_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_ts_info = fec_enet_get_ts_info,
.nway_reset = fec_enet_nway_reset,
+ .get_link = ethtool_op_get_link,
#ifndef CONFIG_M5272
- .get_ethtool_stats = fec_enet_get_ethtool_stats,
+ .get_pauseparam = fec_enet_get_pauseparam,
+ .set_pauseparam = fec_enet_set_pauseparam,
.get_strings = fec_enet_get_strings,
+ .get_ethtool_stats = fec_enet_get_ethtool_stats,
.get_sset_count = fec_enet_get_sset_count,
#endif
+ .get_ts_info = fec_enet_get_ts_info,
};
static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
@@ -2061,18 +2099,23 @@ static void fec_enet_free_buffers(struct net_device *ndev)
bdp = fep->rx_bd_base;
for (i = 0; i < fep->rx_ring_size; i++) {
skb = fep->rx_skbuff[i];
-
- if (bdp->cbd_bufaddr)
+ fep->rx_skbuff[i] = NULL;
+ if (skb) {
dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- if (skb)
dev_kfree_skb(skb);
+ }
bdp = fec_enet_get_nextdesc(bdp, fep);
}
bdp = fep->tx_bd_base;
- for (i = 0; i < fep->tx_ring_size; i++)
+ for (i = 0; i < fep->tx_ring_size; i++) {
kfree(fep->tx_bounce[i]);
+ fep->tx_bounce[i] = NULL;
+ skb = fep->tx_skbuff[i];
+ fep->tx_skbuff[i] = NULL;
+ dev_kfree_skb(skb);
+ }
}
static int fec_enet_alloc_buffers(struct net_device *ndev)
@@ -2084,21 +2127,23 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp = fep->rx_bd_base;
for (i = 0; i < fep->rx_ring_size; i++) {
+ dma_addr_t addr;
+
skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
- if (!skb) {
- fec_enet_free_buffers(ndev);
- return -ENOMEM;
- }
- fep->rx_skbuff[i] = skb;
+ if (!skb)
+ goto err_alloc;
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
+ addr = dma_map_single(&fep->pdev->dev, skb->data,
FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
- fec_enet_free_buffers(ndev);
+ if (dma_mapping_error(&fep->pdev->dev, addr)) {
+ dev_kfree_skb(skb);
if (net_ratelimit())
netdev_err(ndev, "Rx DMA memory map failed\n");
- return -ENOMEM;
+ goto err_alloc;
}
+
+ fep->rx_skbuff[i] = skb;
+ bdp->cbd_bufaddr = addr;
bdp->cbd_sc = BD_ENET_RX_EMPTY;
if (fep->bufdesc_ex) {
@@ -2116,6 +2161,8 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp = fep->tx_bd_base;
for (i = 0; i < fep->tx_ring_size; i++) {
fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+ if (!fep->tx_bounce[i])
+ goto err_alloc;
bdp->cbd_sc = 0;
bdp->cbd_bufaddr = 0;
@@ -2133,6 +2180,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp->cbd_sc |= BD_SC_WRAP;
return 0;
+
+ err_alloc:
+ fec_enet_free_buffers(ndev);
+ return -ENOMEM;
}
static int
@@ -2161,10 +2212,10 @@ fec_enet_open(struct net_device *ndev)
return ret;
}
+ fec_restart(ndev);
napi_enable(&fep->napi);
phy_start(fep->phy_dev);
netif_start_queue(ndev);
- fep->opened = 1;
return 0;
}
@@ -2173,17 +2224,17 @@ fec_enet_close(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- /* Don't know what to do yet. */
- napi_disable(&fep->napi);
- fep->opened = 0;
- netif_stop_queue(ndev);
- fec_stop(ndev);
+ phy_stop(fep->phy_dev);
- if (fep->phy_dev) {
- phy_stop(fep->phy_dev);
- phy_disconnect(fep->phy_dev);
+ if (netif_device_present(ndev)) {
+ napi_disable(&fep->napi);
+ netif_tx_disable(ndev);
+ fec_stop(ndev);
}
+ phy_disconnect(fep->phy_dev);
+ fep->phy_dev = NULL;
+
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
fec_enet_free_buffers(ndev);
@@ -2310,12 +2361,21 @@ static void fec_poll_controller(struct net_device *dev)
}
#endif
+#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM
+
static int fec_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct fec_enet_private *fep = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
+ /* Quiesce the device if necessary */
+ if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(netdev);
+ fec_stop(netdev);
+ }
+
netdev->features = features;
/* Receive checksum has been changed */
@@ -2324,14 +2384,14 @@ static int fec_set_features(struct net_device *netdev,
fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
else
fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
+ }
- if (netif_running(netdev)) {
- fec_stop(netdev);
- fec_restart(netdev, fep->phy_dev->duplex);
- netif_wake_queue(netdev);
- } else {
- fec_restart(netdev, fep->phy_dev->duplex);
- }
+ /* Resume the device after updates */
+ if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
+ fec_restart(netdev);
+ netif_wake_queue(netdev);
+ netif_tx_unlock_bh(netdev);
+ napi_enable(&fep->napi);
}
return 0;
@@ -2432,7 +2492,7 @@ static int fec_enet_init(struct net_device *ndev)
ndev->hw_features = ndev->features;
- fec_restart(ndev, 0);
+ fec_restart(ndev);
return 0;
}
@@ -2485,6 +2545,7 @@ fec_probe(struct platform_device *pdev)
struct resource *r;
const struct of_device_id *of_id;
static int dev_id;
+ struct device_node *np = pdev->dev.of_node, *phy_node;
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
@@ -2524,6 +2585,18 @@ fec_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
+ phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (!phy_node && of_phy_is_fixed_link(np)) {
+ ret = of_phy_register_fixed_link(np);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "broken fixed-link specification\n");
+ goto failed_phy;
+ }
+ phy_node = of_node_get(np);
+ }
+ fep->phy_node = phy_node;
+
ret = of_get_phy_mode(pdev->dev.of_node);
if (ret < 0) {
pdata = dev_get_platdata(&pdev->dev);
@@ -2615,7 +2688,7 @@ fec_probe(struct platform_device *pdev)
if (fep->bufdesc_ex && fep->ptp_clock)
netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
- INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
+ INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
return 0;
failed_register:
@@ -2628,6 +2701,8 @@ failed_init:
failed_regulator:
fec_enet_clk_enable(ndev, false);
failed_clk:
+failed_phy:
+ of_node_put(phy_node);
failed_ioremap:
free_netdev(ndev);
@@ -2640,7 +2715,7 @@ fec_drv_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev);
- cancel_delayed_work_sync(&(fep->delay_work.delay_work));
+ cancel_work_sync(&fep->tx_timeout_work);
unregister_netdev(ndev);
fec_enet_mii_remove(fep);
del_timer_sync(&fep->time_keep);
@@ -2649,22 +2724,28 @@ fec_drv_remove(struct platform_device *pdev)
if (fep->ptp_clock)
ptp_clock_unregister(fep->ptp_clock);
fec_enet_clk_enable(ndev, false);
+ of_node_put(fep->phy_node);
free_netdev(ndev);
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int
-fec_suspend(struct device *dev)
+static int __maybe_unused fec_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
+ rtnl_lock();
if (netif_running(ndev)) {
- fec_stop(ndev);
+ phy_stop(fep->phy_dev);
+ napi_disable(&fep->napi);
+ netif_tx_lock_bh(ndev);
netif_device_detach(ndev);
+ netif_tx_unlock_bh(ndev);
+ fec_stop(ndev);
}
+ rtnl_unlock();
+
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
@@ -2674,8 +2755,7 @@ fec_suspend(struct device *dev)
return 0;
}
-static int
-fec_resume(struct device *dev)
+static int __maybe_unused fec_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
@@ -2692,10 +2772,16 @@ fec_resume(struct device *dev)
if (ret)
goto failed_clk;
+ rtnl_lock();
if (netif_running(ndev)) {
- fec_restart(ndev, fep->full_duplex);
+ fec_restart(ndev);
+ netif_tx_lock_bh(ndev);
netif_device_attach(ndev);
+ netif_tx_unlock_bh(ndev);
+ napi_enable(&fep->napi);
+ phy_start(fep->phy_dev);
}
+ rtnl_unlock();
return 0;
@@ -2704,7 +2790,6 @@ failed_clk:
regulator_disable(fep->reg_phy);
return ret;
}
-#endif /* CONFIG_PM_SLEEP */
static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 9947765e90c5..ff55fbb20a75 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -1015,8 +1015,7 @@ mpc52xx_fec_remove(struct platform_device *op)
unregister_netdev(ndev);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
+ of_node_put(priv->phy_node);
priv->phy_node = NULL;
irq_dispose_mapping(ndev->irq);
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index cfaf17b70f3f..748fd24d3d9e 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -1033,7 +1033,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- fpi->phy_node = ofdev->dev.of_node;
+ fpi->phy_node = of_node_get(ofdev->dev.of_node);
}
if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index fc5413488496..1eedfba2ad3c 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -41,7 +41,6 @@
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
-#include <asm/mpc8xx.h>
#include <asm/cpm1.h>
#endif
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
index b4bf02f57d43..90b3b19b7cd3 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
@@ -40,7 +40,6 @@
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
-#include <asm/mpc8xx.h>
#include <asm/cpm1.h>
#endif
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index a6cf40e62f3a..fb29d049f4e1 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -892,12 +892,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(np)) {
+ if (!priv->phy_node && of_phy_is_fixed_link(np)) {
err = of_phy_register_fixed_link(np);
if (err)
goto err_grp_init;
- priv->phy_node = np;
+ priv->phy_node = of_node_get(np);
}
/* Find the TBI PHY. If it's not there, we don't support SGMII */
@@ -1435,10 +1435,8 @@ register_fail:
unmap_group_regs(priv);
gfar_free_rx_queues(priv);
gfar_free_tx_queues(priv);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
- if (priv->tbi_node)
- of_node_put(priv->tbi_node);
+ of_node_put(priv->phy_node);
+ of_node_put(priv->tbi_node);
free_gfar_dev(priv);
return err;
}
@@ -1447,10 +1445,8 @@ static int gfar_remove(struct platform_device *ofdev)
{
struct gfar_private *priv = platform_get_drvdata(ofdev);
- if (priv->phy_node)
- of_node_put(priv->phy_node);
- if (priv->tbi_node)
- of_node_put(priv->tbi_node);
+ of_node_put(priv->phy_node);
+ of_node_put(priv->tbi_node);
unregister_netdev(priv->ndev);
unmap_group_regs(priv);
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 36fc429298e3..3cf0478b3728 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -2396,7 +2396,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
pr_err("Bad number of Rx threads value\n");
return -EINVAL;
- break;
}
switch (ug_info->numThreadsTx) {
@@ -2419,7 +2418,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
pr_err("Bad number of Tx threads value\n");
return -EINVAL;
- break;
}
/* Calculate rx_extended_features */
@@ -3787,16 +3785,15 @@ static int ucc_geth_probe(struct platform_device* ofdev)
ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
- if (!ug_info->phy_node) {
- /* In the case of a fixed PHY, the DT node associated
+ if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
+ /*
+ * In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- if (of_phy_is_fixed_link(np)) {
- err = of_phy_register_fixed_link(np);
- if (err)
- return err;
- }
- ug_info->phy_node = np;
+ err = of_phy_register_fixed_link(np);
+ if (err)
+ return err;
+ ug_info->phy_node = of_node_get(np);
}
/* Find the TBI PHY node. If it's not there, we don't support SGMII */
@@ -3864,8 +3861,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof(*ugeth));
- if (dev == NULL)
+ if (dev == NULL) {
+ of_node_put(ug_info->tbi_node);
+ of_node_put(ug_info->phy_node);
return -ENOMEM;
+ }
ugeth = netdev_priv(dev);
spin_lock_init(&ugeth->lock);
@@ -3899,6 +3899,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
pr_err("%s: Cannot register net device, aborting\n",
dev->name);
free_netdev(dev);
+ of_node_put(ug_info->tbi_node);
+ of_node_put(ug_info->phy_node);
return err;
}
@@ -3922,6 +3924,8 @@ static int ucc_geth_remove(struct platform_device* ofdev)
unregister_netdev(dev);
free_netdev(dev);
ucc_geth_memclean(ugeth);
+ of_node_put(ugeth->ug_info->tbi_node);
+ of_node_put(ugeth->ug_info->phy_node);
return 0;
}
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index 0c9d55c862ae..6e7db66069aa 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -46,7 +46,7 @@ struct tgec_mdio_controller {
#define MDIO_DATA_BSY (1 << 31)
/*
- * Wait untill the MDIO bus is free
+ * Wait until the MDIO bus is free
*/
static int xgmac_wait_until_free(struct device *dev,
struct tgec_mdio_controller __iomem *regs)
@@ -163,7 +163,7 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
/* Return all Fs if nothing was there */
if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER) {
dev_err(&bus->dev,
- "Error while reading PHY%d reg at %d.%d\n",
+ "Error while reading PHY%d reg at %d.%hhu\n",
phy_id, dev_addr, regnum);
return 0xffff;
}
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
index cfe7a7431730..a7139f588ad2 100644
--- a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -99,23 +99,23 @@ static const struct ethtool_ops netdev_ethtool_ops;
/*
card type
*/
-typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
+enum cardtype { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
XXX10304, NEC, KME
-} cardtype_t;
+};
/*
driver specific data structure
*/
-typedef struct local_info_t {
+struct local_info {
struct pcmcia_device *p_dev;
long open_time;
uint tx_started:1;
uint tx_queue;
u_short tx_queue_len;
- cardtype_t cardtype;
+ enum cardtype cardtype;
u_short sent;
u_char __iomem *base;
-} local_info_t;
+};
#define MC_FILTERBREAK 64
@@ -232,13 +232,13 @@ static const struct net_device_ops fjn_netdev_ops = {
static int fmvj18x_probe(struct pcmcia_device *link)
{
- local_info_t *lp;
+ struct local_info *lp;
struct net_device *dev;
dev_dbg(&link->dev, "fmvj18x_attach()\n");
/* Make up a FMVJ18x specific data structure */
- dev = alloc_etherdev(sizeof(local_info_t));
+ dev = alloc_etherdev(sizeof(struct local_info));
if (!dev)
return -ENOMEM;
lp = netdev_priv(dev);
@@ -327,10 +327,10 @@ static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
static int fmvj18x_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
int i, ret;
unsigned int ioaddr;
- cardtype_t cardtype;
+ enum cardtype cardtype;
char *card_name = "unknown";
u8 *buf;
size_t len;
@@ -584,7 +584,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
int i;
struct net_device *dev = link->priv;
unsigned int ioaddr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
/* Allocate a small memory window */
link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,7 +626,7 @@ static void fmvj18x_release(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
u_char __iomem *tmp;
dev_dbg(&link->dev, "fmvj18x_release\n");
@@ -711,7 +711,7 @@ module_pcmcia_driver(fmvj18x_cs_driver);
static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
{
struct net_device *dev = dev_id;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr;
unsigned short tx_stat, rx_stat;
@@ -772,7 +772,7 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
static void fjn_tx_timeout(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
@@ -802,7 +802,7 @@ static void fjn_tx_timeout(struct net_device *dev)
static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
short length = skb->len;
@@ -874,7 +874,7 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
static void fjn_reset(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
int i;
@@ -1058,7 +1058,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){
static int fjn_open(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
pr_debug("fjn_open('%s').\n", dev->name);
@@ -1083,7 +1083,7 @@ static int fjn_open(struct net_device *dev)
static int fjn_close(struct net_device *dev)
{
- struct local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
unsigned int ioaddr = dev->base_addr;
diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c
index 37860096f744..ed7916f6fbcf 100644
--- a/drivers/net/ethernet/hp/hp100.c
+++ b/drivers/net/ethernet/hp/hp100.c
@@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl);
#endif
#ifdef CONFIG_PCI
-static DEFINE_PCI_DEVICE_TABLE(hp100_pci_tbl) = {
+static const struct pci_device_id hp100_pci_tbl[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,},
diff --git a/drivers/net/ethernet/ibm/ehea/Makefile b/drivers/net/ethernet/ibm/ehea/Makefile
index 775d9969b5c2..cd473e295242 100644
--- a/drivers/net/ethernet/ibm/ehea/Makefile
+++ b/drivers/net/ethernet/ibm/ehea/Makefile
@@ -1,6 +1,6 @@
#
# Makefile for the eHEA ethernet device driver for IBM eServer System p
#
-ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o ehea_phyp.o
+ehea-y = ehea_main.o ehea_phyp.o ehea_qmr.o ehea_ethtool.o
obj-$(CONFIG_EHEA) += ehea.o
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
index 5727779a7df2..ff2903652f4b 100644
--- a/drivers/net/ethernet/icplus/ipg.c
+++ b/drivers/net/ethernet/icplus/ipg.c
@@ -95,7 +95,7 @@ static const char * const ipg_brand_name[] = {
"D-Link NIC IP1000A"
};
-static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = {
+static const struct pci_device_id ipg_pci_tbl[] = {
{ PCI_VDEVICE(SUNDANCE, 0x1023), 0 },
{ PCI_VDEVICE(SUNDANCE, 0x2021), 1 },
{ PCI_VDEVICE(DLINK, 0x9021), 2 },
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index 9d979d7debef..781065eb5431 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -208,7 +208,7 @@ MODULE_PARM_DESC(use_io, "Force use of i/o access mode");
#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\
PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \
PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich }
-static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = {
+static const struct pci_device_id e100_id_table[] = {
INTEL_8255X_ETHERNET_DEVICE(0x1029, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1030, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1031, 3),
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index d50f78afb56d..cca5bca44e73 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -1316,7 +1316,6 @@ static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
case e1000_82547:
case e1000_82547_rev_2:
return e1000_integrated_phy_loopback(adapter);
- break;
default:
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
@@ -1325,7 +1324,6 @@ static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
phy_reg |= MII_CR_LOOPBACK;
e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
return 0;
- break;
}
return 8;
@@ -1344,7 +1342,6 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
case e1000_82545_rev_3:
case e1000_82546_rev_3:
return e1000_set_phy_loopback(adapter);
- break;
default:
rctl = er32(RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c
index e9b07ccc0eba..1acf5034db10 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c
@@ -902,7 +902,6 @@ static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
default:
e_dbg("Flow control param set incorrectly\n");
return -E1000_ERR_CONFIG;
- break;
}
/* Since auto-negotiation is enabled, take the link out of reset (the
@@ -5041,7 +5040,6 @@ static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
break;
default:
return -E1000_ERR_PHY;
- break;
}
} else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
u16 cur_agc_value;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 660971f304b2..cbc330b301cd 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -46,7 +46,7 @@ static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation
* Macro expands to...
* {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
*/
-static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
+static const struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1000),
INTEL_E1000_ETHERNET_DEVICE(0x1001),
INTEL_E1000_ETHERNET_DEVICE(0x1004),
diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c
index 218481e509f9..dc79ed85030b 100644
--- a/drivers/net/ethernet/intel/e1000e/82571.c
+++ b/drivers/net/ethernet/intel/e1000e/82571.c
@@ -95,7 +95,6 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
break;
default:
return -E1000_ERR_PHY;
- break;
}
/* This can only be done after all function pointers are setup. */
@@ -422,7 +421,6 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
break;
case e1000_82573:
return e1000e_get_phy_id(hw);
- break;
case e1000_82574:
case e1000_82583:
ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id);
@@ -440,7 +438,6 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
break;
default:
return -E1000_ERR_PHY;
- break;
}
return 0;
@@ -1458,7 +1455,6 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
break;
default:
return -E1000_ERR_PHY;
- break;
}
if (ret_val)
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h
index d18e89212575..bb7ab3c321d6 100644
--- a/drivers/net/ethernet/intel/e1000e/defines.h
+++ b/drivers/net/ethernet/intel/e1000e/defines.h
@@ -342,6 +342,7 @@
#define E1000_TIPG_IPGR2_SHIFT 20
#define MAX_JUMBO_FRAME_SIZE 0x3F00
+#define E1000_TX_PTR_GAP 0x1F
/* Extended Configuration Control and Size */
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 815e26c6d34b..865ce45f9ec3 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -1521,11 +1521,9 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
switch (hw->mac.type) {
case e1000_80003es2lan:
return e1000_set_es2lan_mac_loopback(adapter);
- break;
case e1000_82571:
case e1000_82572:
return e1000_set_82571_fiber_loopback(adapter);
- break;
default:
rctl = er32(RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 8894ab8ed6bd..48b74a549155 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -572,7 +572,6 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
break;
default:
return -E1000_ERR_PHY;
- break;
}
return 0;
@@ -2445,7 +2444,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
return ret_val;
e1e_rphy(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
- data |= (0x1A << 2);
+ data |= (E1000_TX_PTR_GAP << 2);
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
return ret_val;
@@ -4606,14 +4605,23 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
/* Disable LPLU if both link partners support 100BaseT
* EEE and 100Full is advertised on both ends of the
- * link.
+ * link, and enable Auto Enable LPI since there will
+ * be no driver to enable LPI while in Sx.
*/
if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
(dev_spec->eee_lp_ability &
I82579_EEE_100_SUPPORTED) &&
- (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
E1000_PHY_CTRL_NOND0A_LPLU);
+
+ /* Set Auto Enable LPI after link up */
+ e1e_rphy_locked(hw,
+ I217_LPI_GPIO_CTRL, &phy_reg);
+ phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
+ e1e_wphy_locked(hw,
+ I217_LPI_GPIO_CTRL, phy_reg);
+ }
}
/* For i217 Intel Rapid Start Technology support,
@@ -4710,6 +4718,11 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
return;
}
+ /* Clear Auto Enable LPI after link up */
+ e1e_rphy_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg);
+ phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
+ e1e_wphy_locked(hw, I217_LPI_GPIO_CTRL, phy_reg);
+
if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
/* Restore clear on SMB if no manageability engine
* is present
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h
index 5515126c81c1..8066a498eaac 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -217,6 +217,10 @@
#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK 0x3F00
#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT 8
+/* Low Power Idle GPIO Control */
+#define I217_LPI_GPIO_CTRL PHY_REG(772, 18)
+#define I217_LPI_GPIO_CTRL_AUTO_EN_LPI 0x0800
+
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
#define I82579_LPI_CTRL_100_ENABLE 0x2000
diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c
index 8c386f3a15eb..30b74d590bee 100644
--- a/drivers/net/ethernet/intel/e1000e/mac.c
+++ b/drivers/net/ethernet/intel/e1000e/mac.c
@@ -787,7 +787,6 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
default:
e_dbg("Flow control param set incorrectly\n");
return -E1000_ERR_CONFIG;
- break;
}
ew32(TXCW, txcw);
diff --git a/drivers/net/ethernet/intel/e1000e/manage.c b/drivers/net/ethernet/intel/e1000e/manage.c
index cb37ff1f1321..06edfca1a35e 100644
--- a/drivers/net/ethernet/intel/e1000e/manage.c
+++ b/drivers/net/ethernet/intel/e1000e/manage.c
@@ -47,7 +47,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
* e1000_mng_enable_host_if - Checks host interface is enabled
* @hw: pointer to the HW structure
*
- * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
+ * Returns 0 upon success, else -E1000_ERR_HOST_INTERFACE_COMMAND
*
* This function checks whether the HOST IF is enabled for command operation
* and also checks whether the previous command is completed. It busy waits
@@ -78,7 +78,7 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
}
if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
- e_dbg("Previous command timeout failed .\n");
+ e_dbg("Previous command timeout failed.\n");
return -E1000_ERR_HOST_INTERFACE_COMMAND;
}
@@ -327,9 +327,12 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
} else if ((hw->mac.type == e1000_82574) ||
(hw->mac.type == e1000_82583)) {
u16 data;
+ s32 ret_val;
factps = er32(FACTPS);
- e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+ ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+ if (ret_val)
+ return false;
if (!(factps & E1000_FACTPS_MNGCG) &&
((data & E1000_NVM_INIT_CTRL2_MNGM) ==
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 201cc93f3625..65c3aef2bd36 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -6033,6 +6033,28 @@ release:
return retval;
}
+static void e1000e_flush_lpic(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ret_val;
+
+ pm_runtime_get_sync(netdev->dev.parent);
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto fl_out;
+
+ pr_info("EEE TX LPI TIMER: %08X\n",
+ er32(LPIC) >> E1000_LPIC_LPIET_SHIFT);
+
+ hw->phy.ops.release(hw);
+
+fl_out:
+ pm_runtime_put_sync(netdev->dev.parent);
+}
+
static int e1000e_pm_freeze(struct device *dev)
{
struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
@@ -6333,6 +6355,8 @@ static int e1000e_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
+ e1000e_flush_lpic(pdev);
+
e1000e_pm_freeze(dev);
return __e1000_shutdown(pdev, false);
@@ -6357,9 +6381,14 @@ static int e1000e_pm_runtime_idle(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
+ u16 eee_lp;
- if (!e1000e_has_link(adapter))
+ eee_lp = adapter->hw.dev_spec.ich8lan.eee_lp_ability;
+
+ if (!e1000e_has_link(adapter)) {
+ adapter->hw.dev_spec.ich8lan.eee_lp_ability = eee_lp;
pm_schedule_suspend(dev, 5 * MSEC_PER_SEC);
+ }
return -EBUSY;
}
@@ -6411,6 +6440,8 @@ static int e1000e_pm_runtime_suspend(struct device *dev)
static void e1000_shutdown(struct pci_dev *pdev)
{
+ e1000e_flush_lpic(pdev);
+
e1000e_pm_freeze(&pdev->dev);
__e1000_shutdown(pdev, false);
@@ -6708,6 +6739,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int bars, i, err, pci_using_dac;
u16 eeprom_data = 0;
u16 eeprom_apme_mask = E1000_EEPROM_APME;
+ s32 rval = 0;
if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S)
aspm_disable_flag = PCIE_LINK_STATE_L0S;
@@ -6940,15 +6972,19 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
(adapter->hw.bus.func == 1))
- e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_B,
- 1, &eeprom_data);
+ rval = e1000_read_nvm(&adapter->hw,
+ NVM_INIT_CONTROL3_PORT_B,
+ 1, &eeprom_data);
else
- e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_A,
- 1, &eeprom_data);
+ rval = e1000_read_nvm(&adapter->hw,
+ NVM_INIT_CONTROL3_PORT_A,
+ 1, &eeprom_data);
}
/* fetch WoL from EEPROM */
- if (eeprom_data & eeprom_apme_mask)
+ if (rval)
+ e_dbg("NVM read error getting WoL initial values: %d\n", rval);
+ else if (eeprom_data & eeprom_apme_mask)
adapter->eeprom_wol |= E1000_WUFC_MAG;
/* now that we have the eeprom settings, apply the special cases
@@ -6967,7 +7003,12 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
device_wakeup_enable(&pdev->dev);
/* save off EEPROM version number */
- e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
+ rval = e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
+
+ if (rval) {
+ e_dbg("NVM read error getting EEPROM version: %d\n", rval);
+ adapter->eeprom_vers = 0;
+ }
/* reset the hardware with the new settings */
e1000e_reset(adapter);
diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c
index b1f212b7baf7..fa6b1036a327 100644
--- a/drivers/net/ethernet/intel/e1000e/nvm.c
+++ b/drivers/net/ethernet/intel/e1000e/nvm.c
@@ -327,8 +327,10 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
ew32(EERD, eerd);
ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ);
- if (ret_val)
+ if (ret_val) {
+ e_dbg("NVM read error: %d\n", ret_val);
break;
+ }
data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA);
}
diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile
index d9eb80acac4f..4b94ddb29c24 100644
--- a/drivers/net/ethernet/intel/i40e/Makefile
+++ b/drivers/net/ethernet/intel/i40e/Makefile
@@ -44,3 +44,4 @@ i40e-objs := i40e_main.o \
i40e_virtchnl_pf.o
i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o
+i40e-$(CONFIG_FCOE:m=y) += i40e_fcoe.o
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 65985846345d..801da392a20e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -54,6 +54,9 @@
#include <linux/ptp_clock_kernel.h>
#include "i40e_type.h"
#include "i40e_prototype.h"
+#ifdef I40E_FCOE
+#include "i40e_fcoe.h"
+#endif
#include "i40e_virtchnl.h"
#include "i40e_virtchnl_pf.h"
#include "i40e_txrx.h"
@@ -79,11 +82,16 @@
#define I40E_MAX_QUEUES_PER_TC 64 /* should be a power of 2 */
#define I40E_FDIR_RING 0
#define I40E_FDIR_RING_COUNT 32
+#ifdef I40E_FCOE
+#define I40E_DEFAULT_FCOE 8 /* default number of QPs for FCoE */
+#define I40E_MINIMUM_FCOE 1 /* minimum number of QPs for FCoE */
+#endif /* I40E_FCOE */
#define I40E_MAX_AQ_BUF_SIZE 4096
#define I40E_AQ_LEN 32
#define I40E_AQ_WORK_LIMIT 16
#define I40E_MAX_USER_PRIORITY 8
#define I40E_DEFAULT_MSG_ENABLE 4
+#define I40E_QUEUE_WAIT_RETRY_LIMIT 10
#define I40E_NVM_VERSION_LO_SHIFT 0
#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT)
@@ -133,7 +141,9 @@ enum i40e_state_t {
__I40E_EMP_RESET_REQUESTED,
__I40E_FILTER_OVERFLOW_PROMISC,
__I40E_SUSPENDED,
+ __I40E_PTP_TX_IN_PROGRESS,
__I40E_BAD_EEPROM,
+ __I40E_DOWN_REQUESTED,
};
enum i40e_interrupt_policy {
@@ -152,7 +162,7 @@ struct i40e_lump_tracking {
#define I40E_DEFAULT_ATR_SAMPLE_RATE 20
#define I40E_FDIR_MAX_RAW_PACKET_SIZE 512
#define I40E_FDIR_BUFFER_FULL_MARGIN 10
-#define I40E_FDIR_BUFFER_HEAD_ROOM 200
+#define I40E_FDIR_BUFFER_HEAD_ROOM 32
enum i40e_fd_stat_idx {
I40E_FD_STAT_ATR,
@@ -222,6 +232,10 @@ struct i40e_pf {
u16 num_vmdq_msix; /* num queue vectors per vmdq pool */
u16 num_req_vfs; /* num vfs requested for this vf */
u16 num_vf_qps; /* num queue pairs per vf */
+#ifdef I40E_FCOE
+ u16 num_fcoe_qps; /* num fcoe queues this pf has set up */
+ u16 num_fcoe_msix; /* num queue vectors per fcoe pool */
+#endif /* I40E_FCOE */
u16 num_lan_qps; /* num lan queues this pf has set up */
u16 num_lan_msix; /* num queue vectors for the base pf vsi */
int queues_left; /* queues left unclaimed */
@@ -262,6 +276,9 @@ struct i40e_pf {
#define I40E_FLAG_VMDQ_ENABLED (u64)(1 << 7)
#define I40E_FLAG_FDIR_REQUIRES_REINIT (u64)(1 << 8)
#define I40E_FLAG_NEED_LINK_UPDATE (u64)(1 << 9)
+#ifdef I40E_FCOE
+#define I40E_FLAG_FCOE_ENABLED (u64)(1 << 11)
+#endif /* I40E_FCOE */
#define I40E_FLAG_IN_NETPOLL (u64)(1 << 12)
#define I40E_FLAG_16BYTE_RX_DESC_ENABLED (u64)(1 << 13)
#define I40E_FLAG_CLEAN_ADMINQ (u64)(1 << 14)
@@ -277,11 +294,16 @@ struct i40e_pf {
#ifdef CONFIG_I40E_VXLAN
#define I40E_FLAG_VXLAN_FILTER_SYNC (u64)(1 << 27)
#endif
+#define I40E_FLAG_PORT_ID_VALID (u64)(1 << 28)
#define I40E_FLAG_DCB_CAPABLE (u64)(1 << 29)
/* tracks features that get auto disabled by errors */
u64 auto_disable_flags;
+#ifdef I40E_FCOE
+ struct i40e_fcoe fcoe;
+
+#endif /* I40E_FCOE */
bool stat_offsets_loaded;
struct i40e_hw_port_stats stats;
struct i40e_hw_port_stats stats_offsets;
@@ -348,6 +370,7 @@ struct i40e_pf {
u32 rx_hwtstamp_cleared;
bool ptp_tx;
bool ptp_rx;
+ u16 rss_table_size;
};
struct i40e_mac_filter {
@@ -359,6 +382,7 @@ struct i40e_mac_filter {
bool is_vf; /* filter belongs to a VF */
bool is_netdev; /* filter belongs to a netdev */
bool changed; /* filter needs to be sync'd to the HW */
+ bool is_laa; /* filter is a Locally Administered Address */
};
struct i40e_veb {
@@ -402,6 +426,11 @@ struct i40e_vsi {
struct rtnl_link_stats64 net_stats_offsets;
struct i40e_eth_stats eth_stats;
struct i40e_eth_stats eth_stats_offsets;
+#ifdef I40E_FCOE
+ struct i40e_fcoe_stats fcoe_stats;
+ struct i40e_fcoe_stats fcoe_stats_offsets;
+ bool fcoe_stat_offsets_loaded;
+#endif
u32 tx_restart;
u32 tx_busy;
u32 rx_buf_failed;
@@ -578,6 +607,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add);
void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
int i40e_get_current_fd_count(struct i40e_pf *pf);
+int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
void i40e_set_ethtool_ops(struct net_device *netdev);
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
@@ -591,6 +621,11 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
int i40e_vsi_release(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
struct i40e_vsi *start_vsi);
+#ifdef I40E_FCOE
+void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
+ struct i40e_vsi_context *ctxt,
+ u8 enabled_tc, bool is_add);
+#endif
int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
@@ -614,9 +649,24 @@ static inline void i40e_dbg_init(void) {}
static inline void i40e_dbg_exit(void) {}
#endif /* CONFIG_DEBUG_FS*/
void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
+void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
+#ifdef I40E_FCOE
+struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
+ struct net_device *netdev,
+ struct rtnl_link_stats64 *storage);
+int i40e_set_mac(struct net_device *netdev, void *p);
+void i40e_set_rx_mode(struct net_device *netdev);
+#endif
int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
+#ifdef I40E_FCOE
+void i40e_tx_timeout(struct net_device *netdev);
+int i40e_vlan_rx_add_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid);
+int i40e_vlan_rx_kill_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid);
+#endif
int i40e_vsi_open(struct i40e_vsi *vsi);
void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
@@ -626,6 +676,26 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
bool is_vf, bool is_netdev);
+#ifdef I40E_FCOE
+int i40e_open(struct net_device *netdev);
+int i40e_close(struct net_device *netdev);
+int i40e_setup_tc(struct net_device *netdev, u8 tc);
+void i40e_netpoll(struct net_device *netdev);
+int i40e_fcoe_enable(struct net_device *netdev);
+int i40e_fcoe_disable(struct net_device *netdev);
+int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt);
+u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf);
+void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi);
+void i40e_fcoe_vsi_setup(struct i40e_pf *pf);
+int i40e_init_pf_fcoe(struct i40e_pf *pf);
+int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi);
+void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi);
+int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc,
+ struct sk_buff *skb);
+void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc, u8 prog_id);
+#endif /* I40E_FCOE */
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
#ifdef CONFIG_I40E_DCB
void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index 7a027499fc57..b29c157b1f57 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -38,8 +38,8 @@ static void i40e_resume_aq(struct i40e_hw *hw);
**/
static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
{
- return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
- (desc->opcode == i40e_aqc_opc_nvm_update);
+ return (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_erase)) ||
+ (desc->opcode == cpu_to_le16(i40e_aqc_opc_nvm_update));
}
/**
@@ -55,16 +55,24 @@ static void i40e_adminq_init_regs(struct i40e_hw *hw)
hw->aq.asq.tail = I40E_VF_ATQT1;
hw->aq.asq.head = I40E_VF_ATQH1;
hw->aq.asq.len = I40E_VF_ATQLEN1;
+ hw->aq.asq.bal = I40E_VF_ATQBAL1;
+ hw->aq.asq.bah = I40E_VF_ATQBAH1;
hw->aq.arq.tail = I40E_VF_ARQT1;
hw->aq.arq.head = I40E_VF_ARQH1;
hw->aq.arq.len = I40E_VF_ARQLEN1;
+ hw->aq.arq.bal = I40E_VF_ARQBAL1;
+ hw->aq.arq.bah = I40E_VF_ARQBAH1;
} else {
hw->aq.asq.tail = I40E_PF_ATQT;
hw->aq.asq.head = I40E_PF_ATQH;
hw->aq.asq.len = I40E_PF_ATQLEN;
+ hw->aq.asq.bal = I40E_PF_ATQBAL;
+ hw->aq.asq.bah = I40E_PF_ATQBAH;
hw->aq.arq.tail = I40E_PF_ARQT;
hw->aq.arq.head = I40E_PF_ARQH;
hw->aq.arq.len = I40E_PF_ARQLEN;
+ hw->aq.arq.bal = I40E_PF_ARQBAL;
+ hw->aq.arq.bah = I40E_PF_ARQBAH;
}
}
@@ -296,27 +304,18 @@ static i40e_status i40e_config_asq_regs(struct i40e_hw *hw)
i40e_status ret_code = 0;
u32 reg = 0;
- if (hw->mac.type == I40E_MAC_VF) {
- /* configure the transmit queue */
- wr32(hw, I40E_VF_ATQBAH1,
- upper_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_VF_ATQBAL1,
- lower_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
- I40E_VF_ATQLEN1_ATQENABLE_MASK));
- reg = rd32(hw, I40E_VF_ATQBAL1);
- } else {
- /* configure the transmit queue */
- wr32(hw, I40E_PF_ATQBAH,
- upper_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_PF_ATQBAL,
- lower_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
- I40E_PF_ATQLEN_ATQENABLE_MASK));
- reg = rd32(hw, I40E_PF_ATQBAL);
- }
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.asq.head, 0);
+ wr32(hw, hw->aq.asq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
+ I40E_PF_ATQLEN_ATQENABLE_MASK));
+ wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
+ wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
/* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.asq.bal);
if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
@@ -334,30 +333,21 @@ static i40e_status i40e_config_arq_regs(struct i40e_hw *hw)
i40e_status ret_code = 0;
u32 reg = 0;
- if (hw->mac.type == I40E_MAC_VF) {
- /* configure the receive queue */
- wr32(hw, I40E_VF_ARQBAH1,
- upper_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_VF_ARQBAL1,
- lower_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
- I40E_VF_ARQLEN1_ARQENABLE_MASK));
- reg = rd32(hw, I40E_VF_ARQBAL1);
- } else {
- /* configure the receive queue */
- wr32(hw, I40E_PF_ARQBAH,
- upper_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_PF_ARQBAL,
- lower_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
- I40E_PF_ARQLEN_ARQENABLE_MASK));
- reg = rd32(hw, I40E_PF_ARQBAL);
- }
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.arq.head, 0);
+ wr32(hw, hw->aq.arq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
+ I40E_PF_ARQLEN_ARQENABLE_MASK));
+ wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
+ wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
/* Update tail in the HW to post pre-allocated buffers */
wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
/* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.arq.bal);
if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
@@ -499,6 +489,8 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
wr32(hw, hw->aq.asq.head, 0);
wr32(hw, hw->aq.asq.tail, 0);
wr32(hw, hw->aq.asq.len, 0);
+ wr32(hw, hw->aq.asq.bal, 0);
+ wr32(hw, hw->aq.asq.bah, 0);
/* make sure lock is available */
mutex_lock(&hw->aq.asq_mutex);
@@ -530,6 +522,8 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
wr32(hw, hw->aq.arq.head, 0);
wr32(hw, hw->aq.arq.tail, 0);
wr32(hw, hw->aq.arq.len, 0);
+ wr32(hw, hw->aq.arq.bal, 0);
+ wr32(hw, hw->aq.arq.bah, 0);
/* make sure lock is available */
mutex_lock(&hw->aq.arq_mutex);
@@ -577,6 +571,9 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
/* Set up register offsets */
i40e_adminq_init_regs(hw);
+ /* setup ASQ command write back timeout */
+ hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
+
/* allocate the ASQ */
ret_code = i40e_init_asq(hw);
if (ret_code)
@@ -677,6 +674,10 @@ static u16 i40e_clean_asq(struct i40e_hw *hw)
desc = I40E_ADMINQ_DESC(*asq, ntc);
details = I40E_ADMINQ_DETAILS(*asq, ntc);
while (rd32(hw, hw->aq.asq.head) != ntc) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "%s: ntc %d head %d.\n", __func__, ntc,
+ rd32(hw, hw->aq.asq.head));
+
if (details->callback) {
I40E_ADMINQ_CALLBACK cb_func =
(I40E_ADMINQ_CALLBACK)details->callback;
@@ -736,6 +737,15 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
struct i40e_aq_desc *desc_on_ring;
bool cmd_completed = false;
u16 retval = 0;
+ u32 val = 0;
+
+ val = rd32(hw, hw->aq.asq.head);
+ if (val >= hw->aq.num_asq_entries) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: head overrun at %d\n", val);
+ status = I40E_ERR_QUEUE_EMPTY;
+ goto asq_send_command_exit;
+ }
if (hw->aq.asq.count == 0) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
@@ -829,6 +839,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
}
/* bump the tail */
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff);
(hw->aq.asq.next_to_use)++;
if (hw->aq.asq.next_to_use == hw->aq.asq.count)
@@ -852,7 +863,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
/* ugh! delay while spin_lock */
udelay(delay_len);
total_delay += delay_len;
- } while (total_delay < I40E_ASQ_CMD_TIMEOUT);
+ } while (total_delay < hw->aq.asq_cmd_timeout);
}
/* if ready, copy the desc back to temp */
@@ -866,6 +877,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQTX: Command completed with error 0x%X.\n",
retval);
+
/* strip off FW internal code */
retval &= 0xff;
}
@@ -877,8 +889,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
}
- if (i40e_is_nvm_update_op(desc))
- hw->aq.nvm_busy = true;
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: desc and buffer writeback:\n");
+ i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
/* update the error if time out occurred */
if ((!cmd_completed) &&
@@ -889,6 +902,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
status = I40E_ERR_ADMIN_QUEUE_TIMEOUT;
}
+ if (!status && i40e_is_nvm_update_op(desc))
+ hw->aq.nvm_busy = true;
+
asq_send_command_error:
mutex_unlock(&hw->aq.asq_mutex);
asq_send_command_exit:
@@ -951,10 +967,6 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
/* now clean the next descriptor */
desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
desc_idx = ntc;
- i40e_debug_aq(hw,
- I40E_DEBUG_AQ_COMMAND,
- (void *)desc,
- hw->aq.arq.r.arq_bi[desc_idx].va);
flags = le16_to_cpu(desc->flags);
if (flags & I40E_AQ_FLAG_ERR) {
@@ -965,17 +977,17 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
hw->aq.arq_last_status);
- } else {
- e->desc = *desc;
- datalen = le16_to_cpu(desc->datalen);
- e->msg_size = min(datalen, e->msg_size);
- if (e->msg_buf != NULL && (e->msg_size != 0))
- memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
- e->msg_size);
}
- if (i40e_is_nvm_update_op(&e->desc))
- hw->aq.nvm_busy = false;
+ e->desc = *desc;
+ datalen = le16_to_cpu(desc->datalen);
+ e->msg_size = min(datalen, e->msg_size);
+ if (e->msg_buf != NULL && (e->msg_size != 0))
+ memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+ e->msg_size);
+
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
+ i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
/* Restore the original datalen and buffer address in the desc,
* FW updates datalen to indicate the event message
@@ -1006,6 +1018,14 @@ clean_arq_element_out:
*pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
mutex_unlock(&hw->aq.arq_mutex);
+ if (i40e_is_nvm_update_op(&e->desc)) {
+ hw->aq.nvm_busy = false;
+ if (hw->aq.nvm_release_on_done) {
+ i40e_release_nvm(hw);
+ hw->aq.nvm_release_on_done = false;
+ }
+ }
+
return ret_code;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
index b1552fbc48a0..ba38a89c79d6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h
@@ -56,6 +56,8 @@ struct i40e_adminq_ring {
u32 head;
u32 tail;
u32 len;
+ u32 bah;
+ u32 bal;
};
/* ASQ transaction details */
@@ -82,6 +84,7 @@ struct i40e_arq_event_info {
struct i40e_adminq_info {
struct i40e_adminq_ring arq; /* receive queue */
struct i40e_adminq_ring asq; /* send queue */
+ u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
u16 num_arq_entries; /* receive queue depth */
u16 num_asq_entries; /* send queue depth */
u16 arq_buf_size; /* receive queue buffer size */
@@ -91,6 +94,7 @@ struct i40e_adminq_info {
u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */
bool nvm_busy;
+ bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */
@@ -100,6 +104,41 @@ struct i40e_adminq_info {
enum i40e_admin_queue_err arq_last_status;
};
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_rc: AdminQ error code to convert
+ **/
+static inline int i40e_aq_rc_to_posix(u16 aq_rc)
+{
+ int aq_to_posix[] = {
+ 0, /* I40E_AQ_RC_OK */
+ -EPERM, /* I40E_AQ_RC_EPERM */
+ -ENOENT, /* I40E_AQ_RC_ENOENT */
+ -ESRCH, /* I40E_AQ_RC_ESRCH */
+ -EINTR, /* I40E_AQ_RC_EINTR */
+ -EIO, /* I40E_AQ_RC_EIO */
+ -ENXIO, /* I40E_AQ_RC_ENXIO */
+ -E2BIG, /* I40E_AQ_RC_E2BIG */
+ -EAGAIN, /* I40E_AQ_RC_EAGAIN */
+ -ENOMEM, /* I40E_AQ_RC_ENOMEM */
+ -EACCES, /* I40E_AQ_RC_EACCES */
+ -EFAULT, /* I40E_AQ_RC_EFAULT */
+ -EBUSY, /* I40E_AQ_RC_EBUSY */
+ -EEXIST, /* I40E_AQ_RC_EEXIST */
+ -EINVAL, /* I40E_AQ_RC_EINVAL */
+ -ENOTTY, /* I40E_AQ_RC_ENOTTY */
+ -ENOSPC, /* I40E_AQ_RC_ENOSPC */
+ -ENOSYS, /* I40E_AQ_RC_ENOSYS */
+ -ERANGE, /* I40E_AQ_RC_ERANGE */
+ -EPIPE, /* I40E_AQ_RC_EFLUSHED */
+ -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
+ -EROFS, /* I40E_AQ_RC_EMODE */
+ -EFBIG, /* I40E_AQ_RC_EFBIG */
+ };
+
+ return aq_to_posix[aq_rc];
+}
+
/* general information */
#define I40E_AQ_LARGE_BUF 512
#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 6e65f19dd6e5..df43e7c6777c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -554,7 +554,6 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)
break;
default:
return I40E_ERR_DEVICE_NOT_SUPPORTED;
- break;
}
hw->phy.get_link_info = true;
@@ -655,6 +654,31 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
}
/**
+ * i40e_get_port_mac_addr - get Port MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: pointer to Port MAC address
+ *
+ * Reads the adapter's Port MAC address
+ **/
+i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
+{
+ struct i40e_aqc_mac_address_read_data addrs;
+ i40e_status status;
+ u16 flags = 0;
+
+ status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
+ if (status)
+ return status;
+
+ if (flags & I40E_AQC_PORT_ADDR_VALID)
+ memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac));
+ else
+ status = I40E_ERR_INVALID_MAC_ADDR;
+
+ return status;
+}
+
+/**
* i40e_pre_tx_queue_cfg - pre tx queue configure
* @hw: pointer to the HW structure
* @queue: target pf queue index
@@ -669,8 +693,10 @@ void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable)
u32 reg_block = 0;
u32 reg_val;
- if (abs_queue_idx >= 128)
+ if (abs_queue_idx >= 128) {
reg_block = abs_queue_idx / 128;
+ abs_queue_idx %= 128;
+ }
reg_val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block));
reg_val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK;
@@ -683,6 +709,33 @@ void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable)
wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val);
}
+#ifdef I40E_FCOE
+
+/**
+ * i40e_get_san_mac_addr - get SAN MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: pointer to SAN MAC address
+ *
+ * Reads the adapter's SAN MAC address from NVM
+ **/
+i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr)
+{
+ struct i40e_aqc_mac_address_read_data addrs;
+ i40e_status status;
+ u16 flags = 0;
+
+ status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL);
+ if (status)
+ return status;
+
+ if (flags & I40E_AQC_SAN_ADDR_VALID)
+ memcpy(mac_addr, &addrs.pf_san_mac, sizeof(addrs.pf_san_mac));
+ else
+ status = I40E_ERR_INVALID_MAC_ADDR;
+
+ return status;
+}
+#endif
/**
* i40e_get_media_type - Gets media type
@@ -811,6 +864,99 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
}
/**
+ * i40e_clear_hw - clear out any left over hw state
+ * @hw: pointer to the hw struct
+ *
+ * Clear queues and interrupts, typically called at init time,
+ * but after the capabilities have been found so we know how many
+ * queues and msix vectors have been allocated.
+ **/
+void i40e_clear_hw(struct i40e_hw *hw)
+{
+ u32 num_queues, base_queue;
+ u32 num_pf_int;
+ u32 num_vf_int;
+ u32 num_vfs;
+ u32 i, j;
+ u32 val;
+ u32 eol = 0x7ff;
+
+ /* get number of interrupts, queues, and vfs */
+ val = rd32(hw, I40E_GLPCI_CNF2);
+ num_pf_int = (val & I40E_GLPCI_CNF2_MSI_X_PF_N_MASK) >>
+ I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT;
+ num_vf_int = (val & I40E_GLPCI_CNF2_MSI_X_VF_N_MASK) >>
+ I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT;
+
+ val = rd32(hw, I40E_PFLAN_QALLOC);
+ base_queue = (val & I40E_PFLAN_QALLOC_FIRSTQ_MASK) >>
+ I40E_PFLAN_QALLOC_FIRSTQ_SHIFT;
+ j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >>
+ I40E_PFLAN_QALLOC_LASTQ_SHIFT;
+ if (val & I40E_PFLAN_QALLOC_VALID_MASK)
+ num_queues = (j - base_queue) + 1;
+ else
+ num_queues = 0;
+
+ val = rd32(hw, I40E_PF_VT_PFALLOC);
+ i = (val & I40E_PF_VT_PFALLOC_FIRSTVF_MASK) >>
+ I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT;
+ j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >>
+ I40E_PF_VT_PFALLOC_LASTVF_SHIFT;
+ if (val & I40E_PF_VT_PFALLOC_VALID_MASK)
+ num_vfs = (j - i) + 1;
+ else
+ num_vfs = 0;
+
+ /* stop all the interrupts */
+ wr32(hw, I40E_PFINT_ICR0_ENA, 0);
+ val = 0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
+ for (i = 0; i < num_pf_int - 2; i++)
+ wr32(hw, I40E_PFINT_DYN_CTLN(i), val);
+
+ /* Set the FIRSTQ_INDX field to 0x7FF in PFINT_LNKLSTx */
+ val = eol << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT;
+ wr32(hw, I40E_PFINT_LNKLST0, val);
+ for (i = 0; i < num_pf_int - 2; i++)
+ wr32(hw, I40E_PFINT_LNKLSTN(i), val);
+ val = eol << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT;
+ for (i = 0; i < num_vfs; i++)
+ wr32(hw, I40E_VPINT_LNKLST0(i), val);
+ for (i = 0; i < num_vf_int - 2; i++)
+ wr32(hw, I40E_VPINT_LNKLSTN(i), val);
+
+ /* warn the HW of the coming Tx disables */
+ for (i = 0; i < num_queues; i++) {
+ u32 abs_queue_idx = base_queue + i;
+ u32 reg_block = 0;
+
+ if (abs_queue_idx >= 128) {
+ reg_block = abs_queue_idx / 128;
+ abs_queue_idx %= 128;
+ }
+
+ val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block));
+ val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK;
+ val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT);
+ val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK;
+
+ wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), val);
+ }
+ udelay(400);
+
+ /* stop all the queues */
+ for (i = 0; i < num_queues; i++) {
+ wr32(hw, I40E_QINT_TQCTL(i), 0);
+ wr32(hw, I40E_QTX_ENA(i), 0);
+ wr32(hw, I40E_QINT_RQCTL(i), 0);
+ wr32(hw, I40E_QRX_ENA(i), 0);
+ }
+
+ /* short wait for all queue disables to settle */
+ udelay(50);
+}
+
+/**
* i40e_clear_pxe_mode - clear pxe operations mode
* @hw: pointer to the hw struct
*
@@ -942,6 +1088,164 @@ void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
/* Admin command wrappers */
/**
+ * i40e_aq_get_phy_capabilities
+ * @hw: pointer to the hw struct
+ * @abilities: structure for PHY capabilities to be filled
+ * @qualified_modules: report Qualified Modules
+ * @report_init: report init capabilities (active are default)
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Returns the various PHY abilities supported on the Port.
+ **/
+i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
+ bool qualified_modules, bool report_init,
+ struct i40e_aq_get_phy_abilities_resp *abilities,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ i40e_status status;
+ u16 abilities_size = sizeof(struct i40e_aq_get_phy_abilities_resp);
+
+ if (!abilities)
+ return I40E_ERR_PARAM;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_get_phy_abilities);
+
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+ if (abilities_size > I40E_AQ_LARGE_BUF)
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+
+ if (qualified_modules)
+ desc.params.external.param0 |=
+ cpu_to_le32(I40E_AQ_PHY_REPORT_QUALIFIED_MODULES);
+
+ if (report_init)
+ desc.params.external.param0 |=
+ cpu_to_le32(I40E_AQ_PHY_REPORT_INITIAL_VALUES);
+
+ status = i40e_asq_send_command(hw, &desc, abilities, abilities_size,
+ cmd_details);
+
+ if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
+ status = I40E_ERR_UNKNOWN_PHY;
+
+ return status;
+}
+
+/**
+ * i40e_aq_set_phy_config
+ * @hw: pointer to the hw struct
+ * @config: structure with PHY configuration to be set
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Set the various PHY configuration parameters
+ * supported on the Port.One or more of the Set PHY config parameters may be
+ * ignored in an MFP mode as the PF may not have the privilege to set some
+ * of the PHY Config parameters. This status will be indicated by the
+ * command response.
+ **/
+enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
+ struct i40e_aq_set_phy_config *config,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aq_set_phy_config *cmd =
+ (struct i40e_aq_set_phy_config *)&desc.params.raw;
+ enum i40e_status_code status;
+
+ if (!config)
+ return I40E_ERR_PARAM;
+
+ i40e_fill_default_direct_cmd_desc(&desc,
+ i40e_aqc_opc_set_phy_config);
+
+ *cmd = *config;
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
+ * i40e_set_fc
+ * @hw: pointer to the hw struct
+ *
+ * Set the requested flow control mode using set_phy_config.
+ **/
+enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
+ bool atomic_restart)
+{
+ enum i40e_fc_mode fc_mode = hw->fc.requested_mode;
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_aq_set_phy_config config;
+ enum i40e_status_code status;
+ u8 pause_mask = 0x0;
+
+ *aq_failures = 0x0;
+
+ switch (fc_mode) {
+ case I40E_FC_FULL:
+ pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX;
+ pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX;
+ break;
+ case I40E_FC_RX_PAUSE:
+ pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX;
+ break;
+ case I40E_FC_TX_PAUSE:
+ pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX;
+ break;
+ default:
+ break;
+ }
+
+ /* Get the current phy config */
+ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+ NULL);
+ if (status) {
+ *aq_failures |= I40E_SET_FC_AQ_FAIL_GET;
+ return status;
+ }
+
+ memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
+ /* clear the old pause settings */
+ config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) &
+ ~(I40E_AQ_PHY_FLAG_PAUSE_RX);
+ /* set the new abilities */
+ config.abilities |= pause_mask;
+ /* If the abilities have changed, then set the new config */
+ if (config.abilities != abilities.abilities) {
+ /* Auto restart link so settings take effect */
+ if (atomic_restart)
+ config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+ /* Copy over all the old settings */
+ config.phy_type = abilities.phy_type;
+ config.link_speed = abilities.link_speed;
+ config.eee_capability = abilities.eee_capability;
+ config.eeer = abilities.eeer_val;
+ config.low_power_ctrl = abilities.d3_lpan;
+ status = i40e_aq_set_phy_config(hw, &config, NULL);
+
+ if (status)
+ *aq_failures |= I40E_SET_FC_AQ_FAIL_SET;
+ }
+ /* Update the link info */
+ status = i40e_update_link_info(hw, true);
+ if (status) {
+ /* Wait a little bit (on 40G cards it sometimes takes a really
+ * long time for link to come back from the atomic reset)
+ * and try once more
+ */
+ msleep(1000);
+ status = i40e_update_link_info(hw, true);
+ }
+ if (status)
+ *aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE;
+
+ return status;
+}
+
+/**
* i40e_aq_clear_pxe_mode
* @hw: pointer to the hw struct
* @cmd_details: pointer to command details structure or NULL
@@ -971,12 +1275,14 @@ i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
/**
* i40e_aq_set_link_restart_an
* @hw: pointer to the hw struct
+ * @enable_link: if true: enable link, if false: disable link
* @cmd_details: pointer to command details structure or NULL
*
* Sets up the link and restarts the Auto-Negotiation over the link.
**/
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
- struct i40e_asq_cmd_details *cmd_details)
+ bool enable_link,
+ struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_link_restart_an *cmd =
@@ -987,6 +1293,10 @@ i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
i40e_aqc_opc_set_link_restart_an);
cmd->command = I40E_AQ_PHY_RESTART_AN;
+ if (enable_link)
+ cmd->command |= I40E_AQ_PHY_LINK_ENABLE;
+ else
+ cmd->command &= ~I40E_AQ_PHY_LINK_ENABLE;
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
@@ -1011,6 +1321,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
(struct i40e_aqc_get_link_status *)&desc.params.raw;
struct i40e_link_status *hw_link_info = &hw->phy.link_info;
i40e_status status;
+ bool tx_pause, rx_pause;
u16 command_flags;
i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_link_status);
@@ -1040,6 +1351,18 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size);
hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK;
+ /* update fc info */
+ tx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_TX);
+ rx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_RX);
+ if (tx_pause & rx_pause)
+ hw->fc.current_mode = I40E_FC_FULL;
+ else if (tx_pause)
+ hw->fc.current_mode = I40E_FC_TX_PAUSE;
+ else if (rx_pause)
+ hw->fc.current_mode = I40E_FC_RX_PAUSE;
+ else
+ hw->fc.current_mode = I40E_FC_NONE;
+
if (resp->config & I40E_AQ_CONFIG_CRC_ENA)
hw_link_info->crc_enable = true;
else
@@ -1062,6 +1385,35 @@ aq_get_link_info_exit:
}
/**
+ * i40e_update_link_info
+ * @hw: pointer to the hw struct
+ * @enable_lse: enable/disable LinkStatusEvent reporting
+ *
+ * Returns the link status of the adapter
+ **/
+i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse)
+{
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ i40e_status status;
+
+ status = i40e_aq_get_link_info(hw, enable_lse, NULL, NULL);
+ if (status)
+ return status;
+
+ status = i40e_aq_get_phy_capabilities(hw, false, false,
+ &abilities, NULL);
+ if (status)
+ return status;
+
+ if (abilities.abilities & I40E_AQ_PHY_AN_ENABLED)
+ hw->phy.link_info.an_enabled = true;
+ else
+ hw->phy.link_info.an_enabled = false;
+
+ return status;
+}
+
+/**
* i40e_aq_add_vsi
* @hw: pointer to the hw struct
* @vsi_ctx: pointer to a vsi context struct
@@ -1650,6 +2002,35 @@ i40e_status i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid,
}
/**
+ * i40e_aq_debug_write_register
+ * @hw: pointer to the hw struct
+ * @reg_addr: register address
+ * @reg_val: register value
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Write to a register using the admin queue commands
+ **/
+i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
+ u32 reg_addr, u64 reg_val,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_debug_reg_read_write *cmd =
+ (struct i40e_aqc_debug_reg_read_write *)&desc.params.raw;
+ i40e_status status;
+
+ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_write_reg);
+
+ cmd->address = cpu_to_le32(reg_addr);
+ cmd->value_high = cpu_to_le32((u32)(reg_val >> 32));
+ cmd->value_low = cpu_to_le32((u32)(reg_val & 0xFFFFFFFF));
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+ return status;
+}
+
+/**
* i40e_aq_set_hmc_resource_profile
* @hw: pointer to the hw struct
* @profile: type of profile the HMC is to be set as
@@ -1796,6 +2177,47 @@ i40e_aq_read_nvm_exit:
return status;
}
+/**
+ * i40e_aq_erase_nvm
+ * @hw: pointer to the hw struct
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: offset in the module (expressed in 4 KB from module's beginning)
+ * @length: length of the section to be erased (expressed in 4 KB)
+ * @last_command: tells if this is the last command in a series
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Erase the NVM sector using the admin queue commands
+ **/
+i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
+ u32 offset, u16 length, bool last_command,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_nvm_update *cmd =
+ (struct i40e_aqc_nvm_update *)&desc.params.raw;
+ i40e_status status;
+
+ /* In offset the highest byte must be zeroed. */
+ if (offset & 0xFF000000) {
+ status = I40E_ERR_PARAM;
+ goto i40e_aq_erase_nvm_exit;
+ }
+
+ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_erase);
+
+ /* If this is the last command in a series, set the proper flag. */
+ if (last_command)
+ cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
+ cmd->module_pointer = module_pointer;
+ cmd->offset = cpu_to_le32(offset);
+ cmd->length = cpu_to_le16(length);
+
+ status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+i40e_aq_erase_nvm_exit:
+ return status;
+}
+
#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01
#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02
#define I40E_DEV_FUNC_CAP_NPAR 0x03
@@ -1839,7 +2261,6 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
struct i40e_aqc_list_capabilities_element_resp *cap;
u32 number, logical_id, phys_id;
struct i40e_hw_capabilities *p;
- u32 reg_val;
u32 i = 0;
u16 id;
@@ -1910,11 +2331,7 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
break;
case I40E_DEV_FUNC_CAP_RSS:
p->rss = true;
- reg_val = rd32(hw, I40E_PFQF_CTL_0);
- if (reg_val & I40E_PFQF_CTL_0_HASHLUTSIZE_MASK)
- p->rss_table_size = number;
- else
- p->rss_table_size = 128;
+ p->rss_table_size = number;
p->rss_table_entry_width = logical_id;
break;
case I40E_DEV_FUNC_CAP_RX_QUEUES:
@@ -2031,6 +2448,53 @@ exit:
}
/**
+ * i40e_aq_update_nvm
+ * @hw: pointer to the hw struct
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: byte offset from the module beginning
+ * @length: length of the section to be written (in bytes from the offset)
+ * @data: command buffer (size [bytes] = length)
+ * @last_command: tells if this is the last command in a series
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Update the NVM using the admin queue commands
+ **/
+i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
+ u32 offset, u16 length, void *data,
+ bool last_command,
+ struct i40e_asq_cmd_details *cmd_details)
+{
+ struct i40e_aq_desc desc;
+ struct i40e_aqc_nvm_update *cmd =
+ (struct i40e_aqc_nvm_update *)&desc.params.raw;
+ i40e_status status;
+
+ /* In offset the highest byte must be zeroed. */
+ if (offset & 0xFF000000) {
+ status = I40E_ERR_PARAM;
+ goto i40e_aq_update_nvm_exit;
+ }
+
+ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
+
+ /* If this is the last command in a series, set the proper flag. */
+ if (last_command)
+ cmd->command_flags |= I40E_AQ_NVM_LAST_CMD;
+ cmd->module_pointer = module_pointer;
+ cmd->offset = cpu_to_le32(offset);
+ cmd->length = cpu_to_le16(length);
+
+ desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
+ if (length > I40E_AQ_LARGE_BUF)
+ desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+
+ status = i40e_asq_send_command(hw, &desc, data, length, cmd_details);
+
+i40e_aq_update_nvm_exit:
+ return status;
+}
+
+/**
* i40e_aq_get_lldp_mib
* @hw: pointer to the hw struct
* @bridge_type: type of bridge requested
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index cffdfc21290f..5a0cabeb35ed 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -697,6 +697,25 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
vsi->bw_ets_limit_credits[i],
vsi->bw_ets_max_quanta[i]);
}
+#ifdef I40E_FCOE
+ if (vsi->type == I40E_VSI_FCOE) {
+ dev_info(&pf->pdev->dev,
+ " fcoe_stats: rx_packets = %llu, rx_dwords = %llu, rx_dropped = %llu\n",
+ vsi->fcoe_stats.rx_fcoe_packets,
+ vsi->fcoe_stats.rx_fcoe_dwords,
+ vsi->fcoe_stats.rx_fcoe_dropped);
+ dev_info(&pf->pdev->dev,
+ " fcoe_stats: tx_packets = %llu, tx_dwords = %llu\n",
+ vsi->fcoe_stats.tx_fcoe_packets,
+ vsi->fcoe_stats.tx_fcoe_dwords);
+ dev_info(&pf->pdev->dev,
+ " fcoe_stats: bad_crc = %llu, last_error = %llu\n",
+ vsi->fcoe_stats.fcoe_bad_fccrc,
+ vsi->fcoe_stats.fcoe_last_error);
+ dev_info(&pf->pdev->dev, " fcoe_stats: ddp_count = %llu\n",
+ vsi->fcoe_stats.fcoe_ddp_count);
+ }
+#endif
}
/**
@@ -1238,7 +1257,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {
i40e_status ret;
u16 vid;
- int v;
+ unsigned int v;
cnt = sscanf(&cmd_buf[8], "%i %u", &vsi_seid, &v);
if (cnt != 2) {
@@ -1254,7 +1273,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
goto command_write_done;
}
- vid = (unsigned)v;
+ vid = v;
ret = i40e_vsi_add_pvid(vsi, vid);
if (!ret)
dev_info(&pf->pdev->dev,
@@ -1743,6 +1762,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false);
} else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) {
i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true);
+ } else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) {
+ dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n",
+ i40e_get_current_fd_count(pf));
} else if (strncmp(cmd_buf, "lldp", 4) == 0) {
if (strncmp(&cmd_buf[5], "stop", 4) == 0) {
int ret;
@@ -1830,7 +1852,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
ret = i40e_aq_get_lldp_mib(&pf->hw,
I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
- I40E_AQ_LLDP_MIB_LOCAL,
+ I40E_AQ_LLDP_MIB_REMOTE,
buff, I40E_LLDPDU_SIZE,
&llen, &rlen, NULL);
if (ret) {
@@ -1962,6 +1984,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
dev_info(&pf->pdev->dev, " rem fd_filter <dest q_index> <flex_off> <pctype> <dest_vsi> <dest_ctl> <fd_status> <cnt_index> <fd_id> <packet_len> <packet>\n");
dev_info(&pf->pdev->dev, " fd-atr off\n");
dev_info(&pf->pdev->dev, " fd-atr on\n");
+ dev_info(&pf->pdev->dev, " fd current cnt");
dev_info(&pf->pdev->dev, " lldp start\n");
dev_info(&pf->pdev->dev, " lldp stop\n");
dev_info(&pf->pdev->dev, " lldp get local\n");
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 4a488ffcd6b0..e8ba7470700a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -155,6 +155,19 @@ static struct i40e_stats i40e_gstrings_stats[] = {
I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count),
};
+#ifdef I40E_FCOE
+static const struct i40e_stats i40e_gstrings_fcoe_stats[] = {
+ I40E_VSI_STAT("fcoe_bad_fccrc", fcoe_stats.fcoe_bad_fccrc),
+ I40E_VSI_STAT("rx_fcoe_dropped", fcoe_stats.rx_fcoe_dropped),
+ I40E_VSI_STAT("rx_fcoe_packets", fcoe_stats.rx_fcoe_packets),
+ I40E_VSI_STAT("rx_fcoe_dwords", fcoe_stats.rx_fcoe_dwords),
+ I40E_VSI_STAT("fcoe_ddp_count", fcoe_stats.fcoe_ddp_count),
+ I40E_VSI_STAT("fcoe_last_error", fcoe_stats.fcoe_last_error),
+ I40E_VSI_STAT("tx_fcoe_packets", fcoe_stats.tx_fcoe_packets),
+ I40E_VSI_STAT("tx_fcoe_dwords", fcoe_stats.tx_fcoe_dwords),
+};
+
+#endif /* I40E_FCOE */
#define I40E_QUEUE_STATS_LEN(n) \
(((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \
* 2 /* Tx and Rx together */ \
@@ -162,9 +175,17 @@ static struct i40e_stats i40e_gstrings_stats[] = {
#define I40E_GLOBAL_STATS_LEN ARRAY_SIZE(i40e_gstrings_stats)
#define I40E_NETDEV_STATS_LEN ARRAY_SIZE(i40e_gstrings_net_stats)
#define I40E_MISC_STATS_LEN ARRAY_SIZE(i40e_gstrings_misc_stats)
+#ifdef I40E_FCOE
+#define I40E_FCOE_STATS_LEN ARRAY_SIZE(i40e_gstrings_fcoe_stats)
+#define I40E_VSI_STATS_LEN(n) (I40E_NETDEV_STATS_LEN + \
+ I40E_FCOE_STATS_LEN + \
+ I40E_MISC_STATS_LEN + \
+ I40E_QUEUE_STATS_LEN((n)))
+#else
#define I40E_VSI_STATS_LEN(n) (I40E_NETDEV_STATS_LEN + \
I40E_MISC_STATS_LEN + \
I40E_QUEUE_STATS_LEN((n)))
+#endif /* I40E_FCOE */
#define I40E_PFC_STATS_LEN ( \
(FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \
FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_rx) + \
@@ -215,52 +236,135 @@ static int i40e_get_settings(struct net_device *netdev,
/* hardware is either in 40G mode or 10G mode
* NOTE: this section initializes supported and advertising
*/
+ if (!link_up) {
+ /* link is down and the driver needs to fall back on
+ * device ID to determine what kinds of info to display,
+ * it's mostly a guess that may change when link is up
+ */
+ switch (hw->device_id) {
+ case I40E_DEV_ID_QSFP_A:
+ case I40E_DEV_ID_QSFP_B:
+ case I40E_DEV_ID_QSFP_C:
+ /* pluggable QSFP */
+ ecmd->supported = SUPPORTED_40000baseSR4_Full |
+ SUPPORTED_40000baseCR4_Full |
+ SUPPORTED_40000baseLR4_Full;
+ ecmd->advertising = ADVERTISED_40000baseSR4_Full |
+ ADVERTISED_40000baseCR4_Full |
+ ADVERTISED_40000baseLR4_Full;
+ break;
+ case I40E_DEV_ID_KX_B:
+ /* backplane 40G */
+ ecmd->supported = SUPPORTED_40000baseKR4_Full;
+ ecmd->advertising = ADVERTISED_40000baseKR4_Full;
+ break;
+ case I40E_DEV_ID_KX_C:
+ /* backplane 10G */
+ ecmd->supported = SUPPORTED_10000baseKR_Full;
+ ecmd->advertising = ADVERTISED_10000baseKR_Full;
+ break;
+ default:
+ /* all the rest are 10G/1G */
+ ecmd->supported = SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full;
+ ecmd->advertising = ADVERTISED_10000baseT_Full |
+ ADVERTISED_1000baseT_Full;
+ break;
+ }
+
+ /* skip phy_type use as it is zero when link is down */
+ goto no_valid_phy_type;
+ }
+
switch (hw_link_info->phy_type) {
case I40E_PHY_TYPE_40GBASE_CR4:
case I40E_PHY_TYPE_40GBASE_CR4_CU:
- ecmd->supported = SUPPORTED_40000baseCR4_Full;
- ecmd->advertising = ADVERTISED_40000baseCR4_Full;
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_40000baseCR4_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_40000baseCR4_Full;
break;
case I40E_PHY_TYPE_40GBASE_KR4:
- ecmd->supported = SUPPORTED_40000baseKR4_Full;
- ecmd->advertising = ADVERTISED_40000baseKR4_Full;
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_40000baseKR4_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_40000baseKR4_Full;
break;
case I40E_PHY_TYPE_40GBASE_SR4:
+ case I40E_PHY_TYPE_XLPPI:
+ case I40E_PHY_TYPE_XLAUI:
ecmd->supported = SUPPORTED_40000baseSR4_Full;
- ecmd->advertising = ADVERTISED_40000baseSR4_Full;
break;
case I40E_PHY_TYPE_40GBASE_LR4:
ecmd->supported = SUPPORTED_40000baseLR4_Full;
- ecmd->advertising = ADVERTISED_40000baseLR4_Full;
break;
case I40E_PHY_TYPE_10GBASE_KX4:
- ecmd->supported = SUPPORTED_10000baseKX4_Full;
- ecmd->advertising = ADVERTISED_10000baseKX4_Full;
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_10000baseKX4_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_10000baseKX4_Full;
break;
case I40E_PHY_TYPE_10GBASE_KR:
- ecmd->supported = SUPPORTED_10000baseKR_Full;
- ecmd->advertising = ADVERTISED_10000baseKR_Full;
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_10000baseKR_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_10000baseKR_Full;
break;
- default:
- if (i40e_is_40G_device(hw->device_id)) {
- ecmd->supported = SUPPORTED_40000baseSR4_Full;
- ecmd->advertising = ADVERTISED_40000baseSR4_Full;
- } else {
- ecmd->supported = SUPPORTED_10000baseT_Full;
- ecmd->advertising = ADVERTISED_10000baseT_Full;
- }
+ case I40E_PHY_TYPE_10GBASE_SR:
+ case I40E_PHY_TYPE_10GBASE_LR:
+ ecmd->supported = SUPPORTED_10000baseT_Full;
+ break;
+ case I40E_PHY_TYPE_10GBASE_CR1_CU:
+ case I40E_PHY_TYPE_10GBASE_CR1:
+ case I40E_PHY_TYPE_10GBASE_T:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_10000baseT_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_10000baseT_Full;
+ break;
+ case I40E_PHY_TYPE_XAUI:
+ case I40E_PHY_TYPE_XFI:
+ case I40E_PHY_TYPE_SFI:
+ case I40E_PHY_TYPE_10GBASE_SFPP_CU:
+ ecmd->supported = SUPPORTED_10000baseT_Full;
break;
+ case I40E_PHY_TYPE_1000BASE_KX:
+ case I40E_PHY_TYPE_1000BASE_T:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_1000baseT_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_1000baseT_Full;
+ break;
+ case I40E_PHY_TYPE_100BASE_TX:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_100baseT_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_100baseT_Full;
+ break;
+ case I40E_PHY_TYPE_SGMII:
+ ecmd->supported = SUPPORTED_Autoneg |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_100baseT_Full;
+ ecmd->advertising = ADVERTISED_Autoneg |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_100baseT_Full;
+ break;
+ default:
+ /* if we got here and link is up something bad is afoot */
+ WARN_ON(link_up);
}
- ecmd->supported |= SUPPORTED_Autoneg;
- ecmd->advertising |= ADVERTISED_Autoneg;
+no_valid_phy_type:
+ /* this is if autoneg is enabled or disabled */
ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
AUTONEG_ENABLE : AUTONEG_DISABLE);
switch (hw->phy.media_type) {
case I40E_MEDIA_TYPE_BACKPLANE:
- ecmd->supported |= SUPPORTED_Backplane;
- ecmd->advertising |= ADVERTISED_Backplane;
+ ecmd->supported |= SUPPORTED_Autoneg |
+ SUPPORTED_Backplane;
+ ecmd->advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_Backplane;
ecmd->port = PORT_NONE;
break;
case I40E_MEDIA_TYPE_BASET:
@@ -276,7 +380,6 @@ static int i40e_get_settings(struct net_device *netdev,
break;
case I40E_MEDIA_TYPE_FIBER:
ecmd->supported |= SUPPORTED_FIBRE;
- ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
break;
case I40E_MEDIA_TYPE_UNKNOWN:
@@ -287,6 +390,25 @@ static int i40e_get_settings(struct net_device *netdev,
ecmd->transceiver = XCVR_EXTERNAL;
+ ecmd->supported |= SUPPORTED_Pause;
+
+ switch (hw->fc.current_mode) {
+ case I40E_FC_FULL:
+ ecmd->advertising |= ADVERTISED_Pause;
+ break;
+ case I40E_FC_TX_PAUSE:
+ ecmd->advertising |= ADVERTISED_Asym_Pause;
+ break;
+ case I40E_FC_RX_PAUSE:
+ ecmd->advertising |= (ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause);
+ break;
+ default:
+ ecmd->advertising &= ~(ADVERTISED_Pause |
+ ADVERTISED_Asym_Pause);
+ break;
+ }
+
if (link_up) {
switch (link_speed) {
case I40E_LINK_SPEED_40GB:
@@ -296,6 +418,9 @@ static int i40e_get_settings(struct net_device *netdev,
case I40E_LINK_SPEED_10GB:
ethtool_cmd_speed_set(ecmd, SPEED_10000);
break;
+ case I40E_LINK_SPEED_1GB:
+ ethtool_cmd_speed_set(ecmd, SPEED_1000);
+ break;
default:
break;
}
@@ -309,6 +434,182 @@ static int i40e_get_settings(struct net_device *netdev,
}
/**
+ * i40e_set_settings - Set Speed and Duplex
+ * @netdev: network interface device structure
+ * @ecmd: ethtool command
+ *
+ * Set speed/duplex per media_types advertised/forced
+ **/
+static int i40e_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_aq_set_phy_config config;
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_hw *hw = &pf->hw;
+ struct ethtool_cmd safe_ecmd;
+ i40e_status status = 0;
+ bool change = false;
+ int err = 0;
+ u8 autoneg;
+ u32 advertise;
+
+ if (vsi != pf->vsi[pf->lan_vsi])
+ return -EOPNOTSUPP;
+
+ if (hw->phy.media_type != I40E_MEDIA_TYPE_BASET &&
+ hw->phy.media_type != I40E_MEDIA_TYPE_FIBER &&
+ hw->phy.media_type != I40E_MEDIA_TYPE_BACKPLANE)
+ return -EOPNOTSUPP;
+
+ /* get our own copy of the bits to check against */
+ memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd));
+ i40e_get_settings(netdev, &safe_ecmd);
+
+ /* save autoneg and speed out of ecmd */
+ autoneg = ecmd->autoneg;
+ advertise = ecmd->advertising;
+
+ /* set autoneg and speed back to what they currently are */
+ ecmd->autoneg = safe_ecmd.autoneg;
+ ecmd->advertising = safe_ecmd.advertising;
+
+ ecmd->cmd = safe_ecmd.cmd;
+ /* If ecmd and safe_ecmd are not the same now, then they are
+ * trying to set something that we do not support
+ */
+ if (memcmp(ecmd, &safe_ecmd, sizeof(struct ethtool_cmd)))
+ return -EOPNOTSUPP;
+
+ while (test_bit(__I40E_CONFIG_BUSY, &vsi->state))
+ usleep_range(1000, 2000);
+
+ /* Get the current phy config */
+ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
+ NULL);
+ if (status)
+ return -EAGAIN;
+
+ /* Copy link_speed and abilities to config in case they are not
+ * set below
+ */
+ memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
+ config.link_speed = abilities.link_speed;
+ config.abilities = abilities.abilities;
+
+ /* Check autoneg */
+ if (autoneg == AUTONEG_ENABLE) {
+ /* If autoneg is not supported, return error */
+ if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) {
+ netdev_info(netdev, "Autoneg not supported on this phy\n");
+ return -EINVAL;
+ }
+ /* If autoneg was not already enabled */
+ if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) {
+ config.abilities = abilities.abilities |
+ I40E_AQ_PHY_ENABLE_AN;
+ change = true;
+ }
+ } else {
+ /* If autoneg is supported 10GBASE_T is the only phy that
+ * can disable it, so otherwise return error
+ */
+ if (safe_ecmd.supported & SUPPORTED_Autoneg &&
+ hw->phy.link_info.phy_type != I40E_PHY_TYPE_10GBASE_T) {
+ netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
+ return -EINVAL;
+ }
+ /* If autoneg is currently enabled */
+ if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) {
+ config.abilities = abilities.abilities |
+ ~I40E_AQ_PHY_ENABLE_AN;
+ change = true;
+ }
+ }
+
+ if (advertise & ~safe_ecmd.supported)
+ return -EINVAL;
+
+ if (advertise & ADVERTISED_100baseT_Full)
+ if (!(abilities.link_speed & I40E_LINK_SPEED_100MB)) {
+ config.link_speed |= I40E_LINK_SPEED_100MB;
+ change = true;
+ }
+ if (advertise & ADVERTISED_1000baseT_Full ||
+ advertise & ADVERTISED_1000baseKX_Full)
+ if (!(abilities.link_speed & I40E_LINK_SPEED_1GB)) {
+ config.link_speed |= I40E_LINK_SPEED_1GB;
+ change = true;
+ }
+ if (advertise & ADVERTISED_10000baseT_Full ||
+ advertise & ADVERTISED_10000baseKX4_Full ||
+ advertise & ADVERTISED_10000baseKR_Full)
+ if (!(abilities.link_speed & I40E_LINK_SPEED_10GB)) {
+ config.link_speed |= I40E_LINK_SPEED_10GB;
+ change = true;
+ }
+ if (advertise & ADVERTISED_40000baseKR4_Full ||
+ advertise & ADVERTISED_40000baseCR4_Full ||
+ advertise & ADVERTISED_40000baseSR4_Full ||
+ advertise & ADVERTISED_40000baseLR4_Full)
+ if (!(abilities.link_speed & I40E_LINK_SPEED_40GB)) {
+ config.link_speed |= I40E_LINK_SPEED_40GB;
+ change = true;
+ }
+
+ if (change) {
+ /* copy over the rest of the abilities */
+ config.phy_type = abilities.phy_type;
+ config.eee_capability = abilities.eee_capability;
+ config.eeer = abilities.eeer_val;
+ config.low_power_ctrl = abilities.d3_lpan;
+
+ /* If link is up set link and an so changes take effect */
+ if (hw->phy.link_info.link_info & I40E_AQ_LINK_UP)
+ config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+
+ /* make the aq call */
+ status = i40e_aq_set_phy_config(hw, &config, NULL);
+ if (status) {
+ netdev_info(netdev, "Set phy config failed with error %d.\n",
+ status);
+ return -EAGAIN;
+ }
+
+ status = i40e_update_link_info(hw, true);
+ if (status)
+ netdev_info(netdev, "Updating link info failed with error %d\n",
+ status);
+
+ } else {
+ netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
+ }
+
+ return err;
+}
+
+static int i40e_nway_reset(struct net_device *netdev)
+{
+ /* restart autonegotiation */
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ bool link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP;
+ i40e_status ret = 0;
+
+ ret = i40e_aq_set_link_restart_an(hw, link_up, NULL);
+ if (ret) {
+ netdev_info(netdev, "link restart failed, aq_err=%d\n",
+ pf->hw.aq.asq_last_status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
* i40e_get_pauseparam - Get Flow Control status
* Return tx/rx-pause status
**/
@@ -334,6 +635,85 @@ static void i40e_get_pauseparam(struct net_device *netdev,
}
}
+/**
+ * i40e_set_pauseparam - Set Flow Control parameter
+ * @netdev: network interface device structure
+ * @pause: return tx/rx flow control status
+ **/
+static int i40e_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_hw *hw = &pf->hw;
+ struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+ bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP;
+ i40e_status status;
+ u8 aq_failures;
+ int err = 0;
+
+ if (vsi != pf->vsi[pf->lan_vsi])
+ return -EOPNOTSUPP;
+
+ if (pause->autoneg != ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
+ AUTONEG_ENABLE : AUTONEG_DISABLE)) {
+ netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* If we have link and don't have autoneg */
+ if (!test_bit(__I40E_DOWN, &pf->state) &&
+ !(hw_link_info->an_info & I40E_AQ_AN_COMPLETED)) {
+ /* Send message that it might not necessarily work*/
+ netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n");
+ }
+
+ if (hw->fc.current_mode == I40E_FC_PFC) {
+ netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = I40E_FC_FULL;
+ else if (pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = I40E_FC_RX_PAUSE;
+ else if (!pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = I40E_FC_TX_PAUSE;
+ else if (!pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = I40E_FC_NONE;
+ else
+ return -EINVAL;
+
+ /* Set the fc mode and only restart an if link is up*/
+ status = i40e_set_fc(hw, &aq_failures, link_up);
+
+ if (aq_failures & I40E_SET_FC_AQ_FAIL_GET) {
+ netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with error %d and status %d\n",
+ status, hw->aq.asq_last_status);
+ err = -EAGAIN;
+ }
+ if (aq_failures & I40E_SET_FC_AQ_FAIL_SET) {
+ netdev_info(netdev, "Set fc failed on the set_phy_config call with error %d and status %d\n",
+ status, hw->aq.asq_last_status);
+ err = -EAGAIN;
+ }
+ if (aq_failures & I40E_SET_FC_AQ_FAIL_UPDATE) {
+ netdev_info(netdev, "Set fc failed on the update_link_info call with error %d and status %d\n",
+ status, hw->aq.asq_last_status);
+ err = -EAGAIN;
+ }
+
+ if (!test_bit(__I40E_DOWN, &pf->state)) {
+ /* Give it a little more time to try to come back */
+ msleep(75);
+ if (!test_bit(__I40E_DOWN, &pf->state))
+ return i40e_nway_reset(netdev);
+ }
+
+ return err;
+}
+
static u32 i40e_get_msglevel(struct net_device *netdev)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
@@ -404,10 +784,33 @@ static int i40e_get_eeprom(struct net_device *netdev,
u8 *eeprom_buff;
u16 i, sectors;
bool last;
+ u32 magic;
+
#define I40E_NVM_SECTOR_SIZE 4096
if (eeprom->len == 0)
return -EINVAL;
+ /* check for NVMUpdate access method */
+ magic = hw->vendor_id | (hw->device_id << 16);
+ if (eeprom->magic && eeprom->magic != magic) {
+ int errno;
+
+ /* make sure it is the right magic for NVMUpdate */
+ if ((eeprom->magic >> 16) != hw->device_id)
+ return -EINVAL;
+
+ ret_val = i40e_nvmupd_command(hw,
+ (struct i40e_nvm_access *)eeprom,
+ bytes, &errno);
+ if (ret_val)
+ dev_info(&pf->pdev->dev,
+ "NVMUpdate read failed err=%d status=0x%x\n",
+ ret_val, hw->aq.asq_last_status);
+
+ return errno;
+ }
+
+ /* normal ethtool get_eeprom support */
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL);
@@ -434,7 +837,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
ret_val = i40e_aq_read_nvm(hw, 0x0,
eeprom->offset + (I40E_NVM_SECTOR_SIZE * i),
len,
- eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
+ (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i),
last, NULL);
if (ret_val) {
dev_info(&pf->pdev->dev,
@@ -446,7 +849,7 @@ static int i40e_get_eeprom(struct net_device *netdev,
release_nvm:
i40e_release_nvm(hw);
- memcpy(bytes, eeprom_buff, eeprom->len);
+ memcpy(bytes, (u8 *)eeprom_buff, eeprom->len);
free_buff:
kfree(eeprom_buff);
return ret_val;
@@ -466,6 +869,39 @@ static int i40e_get_eeprom_len(struct net_device *netdev)
return val;
}
+static int i40e_set_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_hw *hw = &np->vsi->back->hw;
+ struct i40e_pf *pf = np->vsi->back;
+ int ret_val = 0;
+ int errno;
+ u32 magic;
+
+ /* normal ethtool set_eeprom is not supported */
+ magic = hw->vendor_id | (hw->device_id << 16);
+ if (eeprom->magic == magic)
+ return -EOPNOTSUPP;
+
+ /* check for NVMUpdate access method */
+ if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id)
+ return -EINVAL;
+
+ if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) ||
+ test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state))
+ return -EBUSY;
+
+ ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom,
+ bytes, &errno);
+ if (ret_val)
+ dev_info(&pf->pdev->dev,
+ "NVMUpdate write failed err=%d status=0x%x\n",
+ ret_val, hw->aq.asq_last_status);
+
+ return errno;
+}
+
static void i40e_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
@@ -697,6 +1133,13 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
+#ifdef I40E_FCOE
+ for (j = 0; j < I40E_FCOE_STATS_LEN; j++) {
+ p = (char *)vsi + i40e_gstrings_fcoe_stats[j].stat_offset;
+ data[i++] = (i40e_gstrings_fcoe_stats[j].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+#endif
rcu_read_lock();
for (j = 0; j < vsi->num_queue_pairs; j++) {
tx_ring = ACCESS_ONCE(vsi->tx_rings[j]);
@@ -778,6 +1221,13 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,
i40e_gstrings_misc_stats[i].stat_string);
p += ETH_GSTRING_LEN;
}
+#ifdef I40E_FCOE
+ for (i = 0; i < I40E_FCOE_STATS_LEN; i++) {
+ snprintf(p, ETH_GSTRING_LEN, "%s",
+ i40e_gstrings_fcoe_stats[i].stat_string);
+ p += ETH_GSTRING_LEN;
+ }
+#endif
for (i = 0; i < vsi->num_queue_pairs; i++) {
snprintf(p, ETH_GSTRING_LEN, "tx-%u.tx_packets", i);
p += ETH_GSTRING_LEN;
@@ -1021,24 +1471,6 @@ static int i40e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
return 0;
}
-static int i40e_nway_reset(struct net_device *netdev)
-{
- /* restart autonegotiation */
- struct i40e_netdev_priv *np = netdev_priv(netdev);
- struct i40e_pf *pf = np->vsi->back;
- struct i40e_hw *hw = &pf->hw;
- i40e_status ret = 0;
-
- ret = i40e_aq_set_link_restart_an(hw, NULL);
- if (ret) {
- netdev_info(netdev, "link restart failed, aq_err=%d\n",
- pf->hw.aq.asq_last_status);
- return -EIO;
- }
-
- return 0;
-}
-
static int i40e_set_phys_id(struct net_device *netdev,
enum ethtool_phys_id_state state)
{
@@ -1105,17 +1537,36 @@ static int i40e_set_coalesce(struct net_device *netdev,
if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq)
vsi->work_limit = ec->tx_max_coalesced_frames_irq;
+ vector = vsi->base_vector;
if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
- (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
+ (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
vsi->rx_itr_setting = ec->rx_coalesce_usecs;
- else
+ } else if (ec->rx_coalesce_usecs == 0) {
+ vsi->rx_itr_setting = ec->rx_coalesce_usecs;
+ i40e_irq_dynamic_disable(vsi, vector);
+ if (ec->use_adaptive_rx_coalesce)
+ netif_info(pf, drv, netdev,
+ "Rx-secs=0, need to disable adaptive-Rx for a complete disable\n");
+ } else {
+ netif_info(pf, drv, netdev,
+ "Invalid value, Rx-usecs range is 0, 8-8160\n");
return -EINVAL;
+ }
if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) &&
- (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1)))
+ (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) {
vsi->tx_itr_setting = ec->tx_coalesce_usecs;
- else
+ } else if (ec->tx_coalesce_usecs == 0) {
+ vsi->tx_itr_setting = ec->tx_coalesce_usecs;
+ i40e_irq_dynamic_disable(vsi, vector);
+ if (ec->use_adaptive_tx_coalesce)
+ netif_info(pf, drv, netdev,
+ "Tx-secs=0, need to disable adaptive-Tx for a complete disable\n");
+ } else {
+ netif_info(pf, drv, netdev,
+ "Invalid value, Tx-usecs range is 0, 8-8160\n");
return -EINVAL;
+ }
if (ec->use_adaptive_rx_coalesce)
vsi->rx_itr_setting |= I40E_ITR_DYNAMIC;
@@ -1127,7 +1578,6 @@ static int i40e_set_coalesce(struct net_device *netdev,
else
vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC;
- vector = vsi->base_vector;
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
q_vector = vsi->q_vectors[i];
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
@@ -1498,7 +1948,7 @@ static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi,
/* add filter to the list */
if (parent)
- hlist_add_after(&parent->fdir_node, &input->fdir_node);
+ hlist_add_behind(&input->fdir_node, &parent->fdir_node);
else
hlist_add_head(&input->fdir_node,
&pf->fdir_filter_list);
@@ -1731,6 +2181,7 @@ static int i40e_set_channels(struct net_device *dev,
static const struct ethtool_ops i40e_ethtool_ops = {
.get_settings = i40e_get_settings,
+ .set_settings = i40e_set_settings,
.get_drvinfo = i40e_get_drvinfo,
.get_regs_len = i40e_get_regs_len,
.get_regs = i40e_get_regs,
@@ -1738,11 +2189,13 @@ static const struct ethtool_ops i40e_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_wol = i40e_get_wol,
.set_wol = i40e_set_wol,
+ .set_eeprom = i40e_set_eeprom,
.get_eeprom_len = i40e_get_eeprom_len,
.get_eeprom = i40e_get_eeprom,
.get_ringparam = i40e_get_ringparam,
.set_ringparam = i40e_set_ringparam,
.get_pauseparam = i40e_get_pauseparam,
+ .set_pauseparam = i40e_set_pauseparam,
.get_msglevel = i40e_get_msglevel,
.set_msglevel = i40e_set_msglevel,
.get_rxnfc = i40e_get_rxnfc,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
new file mode 100644
index 000000000000..5d01db1d789b
--- /dev/null
+++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
@@ -0,0 +1,1562 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2014 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, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+
+#include <linux/if_ether.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+#include <uapi/linux/dcbnl.h>
+
+#include "i40e.h"
+#include "i40e_fcoe.h"
+
+/**
+ * i40e_rx_is_fip - returns true if the rx packet type is FIP
+ * @ptype: the packet type field from rx descriptor write-back
+ **/
+static inline bool i40e_rx_is_fip(u16 ptype)
+{
+ return ptype == I40E_RX_PTYPE_L2_FIP_PAY2;
+}
+
+/**
+ * i40e_rx_is_fcoe - returns true if the rx packet type is FCoE
+ * @ptype: the packet type field from rx descriptor write-back
+ **/
+static inline bool i40e_rx_is_fcoe(u16 ptype)
+{
+ return (ptype >= I40E_RX_PTYPE_L2_FCOE_PAY3) &&
+ (ptype <= I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER);
+}
+
+/**
+ * i40e_fcoe_sof_is_class2 - returns true if this is a FC Class 2 SOF
+ * @sof: the FCoE start of frame delimiter
+ **/
+static inline bool i40e_fcoe_sof_is_class2(u8 sof)
+{
+ return (sof == FC_SOF_I2) || (sof == FC_SOF_N2);
+}
+
+/**
+ * i40e_fcoe_sof_is_class3 - returns true if this is a FC Class 3 SOF
+ * @sof: the FCoE start of frame delimiter
+ **/
+static inline bool i40e_fcoe_sof_is_class3(u8 sof)
+{
+ return (sof == FC_SOF_I3) || (sof == FC_SOF_N3);
+}
+
+/**
+ * i40e_fcoe_sof_is_supported - returns true if the FC SOF is supported by HW
+ * @sof: the input SOF value from the frame
+ **/
+static inline bool i40e_fcoe_sof_is_supported(u8 sof)
+{
+ return i40e_fcoe_sof_is_class2(sof) ||
+ i40e_fcoe_sof_is_class3(sof);
+}
+
+/**
+ * i40e_fcoe_fc_sof - pull the SOF from FCoE header in the frame
+ * @skb: the frame whose EOF is to be pulled from
+ **/
+static inline int i40e_fcoe_fc_sof(struct sk_buff *skb, u8 *sof)
+{
+ *sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
+
+ if (!i40e_fcoe_sof_is_supported(*sof))
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * i40e_fcoe_eof_is_supported - returns true if the EOF is supported by HW
+ * @eof: the input EOF value from the frame
+ **/
+static inline bool i40e_fcoe_eof_is_supported(u8 eof)
+{
+ return (eof == FC_EOF_N) || (eof == FC_EOF_T) ||
+ (eof == FC_EOF_NI) || (eof == FC_EOF_A);
+}
+
+/**
+ * i40e_fcoe_fc_eof - pull EOF from FCoE trailer in the frame
+ * @skb: the frame whose EOF is to be pulled from
+ **/
+static inline int i40e_fcoe_fc_eof(struct sk_buff *skb, u8 *eof)
+{
+ /* the first byte of the last dword is EOF */
+ skb_copy_bits(skb, skb->len - 4, eof, 1);
+
+ if (!i40e_fcoe_eof_is_supported(*eof))
+ return -EINVAL;
+ return 0;
+}
+
+/**
+ * i40e_fcoe_ctxt_eof - convert input FC EOF for descriptor programming
+ * @eof: the input eof value from the frame
+ *
+ * The FC EOF is converted to the value understood by HW for descriptor
+ * programming. Never call this w/o calling i40e_fcoe_eof_is_supported()
+ * first.
+ **/
+static inline u32 i40e_fcoe_ctxt_eof(u8 eof)
+{
+ switch (eof) {
+ case FC_EOF_N:
+ return I40E_TX_DESC_CMD_L4T_EOFT_EOF_N;
+ case FC_EOF_T:
+ return I40E_TX_DESC_CMD_L4T_EOFT_EOF_T;
+ case FC_EOF_NI:
+ return I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI;
+ case FC_EOF_A:
+ return I40E_TX_DESC_CMD_L4T_EOFT_EOF_A;
+ default:
+ /* FIXME: still returns 0 */
+ pr_err("Unrecognized EOF %x\n", eof);
+ return 0;
+ }
+}
+
+/**
+ * i40e_fcoe_xid_is_valid - returns true if the exchange id is valid
+ * @xid: the exchange id
+ **/
+static inline bool i40e_fcoe_xid_is_valid(u16 xid)
+{
+ return (xid != FC_XID_UNKNOWN) && (xid < I40E_FCOE_DDP_MAX);
+}
+
+/**
+ * i40e_fcoe_ddp_unmap - unmap the mapped sglist associated
+ * @pf: pointer to pf
+ * @ddp: sw DDP context
+ *
+ * Unmap the scatter-gather list associated with the given SW DDP context
+ *
+ * Returns: data length already ddp-ed in bytes
+ *
+ **/
+static inline void i40e_fcoe_ddp_unmap(struct i40e_pf *pf,
+ struct i40e_fcoe_ddp *ddp)
+{
+ if (test_and_set_bit(__I40E_FCOE_DDP_UNMAPPED, &ddp->flags))
+ return;
+
+ if (ddp->sgl) {
+ dma_unmap_sg(&pf->pdev->dev, ddp->sgl, ddp->sgc,
+ DMA_FROM_DEVICE);
+ ddp->sgl = NULL;
+ ddp->sgc = 0;
+ }
+
+ if (ddp->pool) {
+ dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
+ ddp->pool = NULL;
+ }
+}
+
+/**
+ * i40e_fcoe_ddp_clear - clear the given SW DDP context
+ * @ddp - SW DDP context
+ **/
+static inline void i40e_fcoe_ddp_clear(struct i40e_fcoe_ddp *ddp)
+{
+ memset(ddp, 0, sizeof(struct i40e_fcoe_ddp));
+ ddp->xid = FC_XID_UNKNOWN;
+ ddp->flags = __I40E_FCOE_DDP_NONE;
+}
+
+/**
+ * i40e_fcoe_progid_is_fcoe - check if the prog_id is for FCoE
+ * @id: the prog id for the programming status Rx descriptor write-back
+ **/
+static inline bool i40e_fcoe_progid_is_fcoe(u8 id)
+{
+ return (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
+ (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS);
+}
+
+/**
+ * i40e_fcoe_fc_get_xid - get xid from the frame header
+ * @fh: the fc frame header
+ *
+ * In case the incoming frame's exchange is originated from
+ * the initiator, then received frame's exchange id is ANDed
+ * with fc_cpu_mask bits to get the same cpu on which exchange
+ * was originated, otherwise just use the current cpu.
+ *
+ * Returns ox_id if exchange originator, rx_id if responder
+ **/
+static inline u16 i40e_fcoe_fc_get_xid(struct fc_frame_header *fh)
+{
+ u32 f_ctl = ntoh24(fh->fh_f_ctl);
+
+ return (f_ctl & FC_FC_EX_CTX) ?
+ be16_to_cpu(fh->fh_ox_id) :
+ be16_to_cpu(fh->fh_rx_id);
+}
+
+/**
+ * i40e_fcoe_fc_frame_header - get fc frame header from skb
+ * @skb: packet
+ *
+ * This checks if there is a VLAN header and returns the data
+ * pointer to the start of the fc_frame_header.
+ *
+ * Returns pointer to the fc_frame_header
+ **/
+static inline struct fc_frame_header *i40e_fcoe_fc_frame_header(
+ struct sk_buff *skb)
+{
+ void *fh = skb->data + sizeof(struct fcoe_hdr);
+
+ if (eth_hdr(skb)->h_proto == htons(ETH_P_8021Q))
+ fh += sizeof(struct vlan_hdr);
+
+ return (struct fc_frame_header *)fh;
+}
+
+/**
+ * i40e_fcoe_ddp_put - release the DDP context for a given exchange id
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id that corresponding DDP context will be released
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
+ * and it is expected to be called by ULD, i.e., FCP layer of libfc
+ * to release the corresponding ddp context when the I/O is done.
+ *
+ * Returns : data length already ddp-ed in bytes
+ **/
+static int i40e_fcoe_ddp_put(struct net_device *netdev, u16 xid)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ int len = 0;
+ struct i40e_fcoe_ddp *ddp = &fcoe->ddp[xid];
+
+ if (!fcoe || !ddp)
+ goto out;
+
+ if (test_bit(__I40E_FCOE_DDP_DONE, &ddp->flags))
+ len = ddp->len;
+ i40e_fcoe_ddp_unmap(pf, ddp);
+out:
+ return len;
+}
+
+/**
+ * i40e_fcoe_sw_init - sets up the HW for FCoE
+ * @pf: pointer to pf
+ *
+ * Returns 0 if FCoE is supported otherwise the error code
+ **/
+int i40e_init_pf_fcoe(struct i40e_pf *pf)
+{
+ struct i40e_hw *hw = &pf->hw;
+ u32 val;
+
+ pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+ pf->num_fcoe_qps = 0;
+ pf->fcoe_hmc_cntx_num = 0;
+ pf->fcoe_hmc_filt_num = 0;
+
+ if (!pf->hw.func_caps.fcoe) {
+ dev_info(&pf->pdev->dev, "FCoE capability is disabled\n");
+ return 0;
+ }
+
+ if (!pf->hw.func_caps.dcb) {
+ dev_warn(&pf->pdev->dev,
+ "Hardware is not DCB capable not enabling FCoE.\n");
+ return 0;
+ }
+
+ /* enable FCoE hash filter */
+ val = rd32(hw, I40E_PFQF_HENA(1));
+ val |= 1 << (I40E_FILTER_PCTYPE_FCOE_OX - 32);
+ val |= 1 << (I40E_FILTER_PCTYPE_FCOE_RX - 32);
+ val &= I40E_PFQF_HENA_PTYPE_ENA_MASK;
+ wr32(hw, I40E_PFQF_HENA(1), val);
+
+ /* enable flag */
+ pf->flags |= I40E_FLAG_FCOE_ENABLED;
+ pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
+
+ /* Reserve 4K DDP contexts and 20K filter size for FCoE */
+ pf->fcoe_hmc_cntx_num = (1 << I40E_DMA_CNTX_SIZE_4K) *
+ I40E_DMA_CNTX_BASE_SIZE;
+ pf->fcoe_hmc_filt_num = pf->fcoe_hmc_cntx_num +
+ (1 << I40E_HASH_FILTER_SIZE_16K) *
+ I40E_HASH_FILTER_BASE_SIZE;
+
+ /* FCoE object: max 16K filter buckets and 4K DMA contexts */
+ pf->filter_settings.fcoe_filt_num = I40E_HASH_FILTER_SIZE_16K;
+ pf->filter_settings.fcoe_cntx_num = I40E_DMA_CNTX_SIZE_4K;
+
+ /* Setup max frame with FCoE_MTU plus L2 overheads */
+ val = rd32(hw, I40E_GLFCOE_RCTL);
+ val &= ~I40E_GLFCOE_RCTL_MAX_SIZE_MASK;
+ val |= ((FCOE_MTU + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
+ << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT);
+ wr32(hw, I40E_GLFCOE_RCTL, val);
+
+ dev_info(&pf->pdev->dev, "FCoE is supported.\n");
+ return 0;
+}
+
+/**
+ * i40e_get_fcoe_tc_map - Return TC map for FCoE APP
+ * @pf: pointer to pf
+ *
+ **/
+u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf)
+{
+ struct i40e_ieee_app_priority_table app;
+ struct i40e_hw *hw = &pf->hw;
+ u8 enabled_tc = 0;
+ u8 tc, i;
+ /* Get the FCoE APP TLV */
+ struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
+
+ for (i = 0; i < dcbcfg->numapps; i++) {
+ app = dcbcfg->app[i];
+ if (app.selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
+ app.protocolid == ETH_P_FCOE) {
+ tc = dcbcfg->etscfg.prioritytable[app.priority];
+ enabled_tc |= (1 << tc);
+ break;
+ }
+ }
+
+ /* TC0 if there is no TC defined for FCoE APP TLV */
+ enabled_tc = enabled_tc ? enabled_tc : 0x1;
+
+ return enabled_tc;
+}
+
+/**
+ * i40e_fcoe_vsi_init - prepares the VSI context for creating a FCoE VSI
+ * @vsi: pointer to the associated VSI struct
+ * @ctxt: pointer to the associated VSI context to be passed to HW
+ *
+ * Returns 0 on success or < 0 on error
+ **/
+int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt)
+{
+ struct i40e_aqc_vsi_properties_data *info = &ctxt->info;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ u8 enabled_tc = 0;
+
+ if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+ dev_err(&pf->pdev->dev,
+ "FCoE is not enabled for this device\n");
+ return -EPERM;
+ }
+
+ /* initialize the hardware for FCoE */
+ ctxt->pf_num = hw->pf_id;
+ ctxt->vf_num = 0;
+ ctxt->uplink_seid = vsi->uplink_seid;
+ ctxt->connection_type = 0x1;
+ ctxt->flags = I40E_AQ_VSI_TYPE_PF;
+
+ /* FCoE VSI would need the following sections */
+ info->valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID |
+ I40E_AQ_VSI_PROP_QUEUE_OPT_VALID);
+
+ /* FCoE VSI does not need these sections */
+ info->valid_sections &= cpu_to_le16(~(I40E_AQ_VSI_PROP_SECURITY_VALID |
+ I40E_AQ_VSI_PROP_VLAN_VALID |
+ I40E_AQ_VSI_PROP_CAS_PV_VALID |
+ I40E_AQ_VSI_PROP_INGRESS_UP_VALID |
+ I40E_AQ_VSI_PROP_EGRESS_UP_VALID));
+
+ enabled_tc = i40e_get_fcoe_tc_map(pf);
+ i40e_vsi_setup_queue_map(vsi, ctxt, enabled_tc, true);
+
+ /* set up queue option section: only enable FCoE */
+ info->queueing_opt_flags = I40E_AQ_VSI_QUE_OPT_FCOE_ENA;
+
+ return 0;
+}
+
+/**
+ * i40e_fcoe_enable - this is the implementation of ndo_fcoe_enable,
+ * indicating the upper FCoE protocol stack is ready to use FCoE
+ * offload features.
+ *
+ * @netdev: pointer to the netdev that FCoE is created on
+ *
+ * Returns 0 on success
+ *
+ * in RTNL
+ *
+ **/
+int i40e_fcoe_enable(struct net_device *netdev)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+
+ if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+ netdev_err(netdev, "HW does not support FCoE.\n");
+ return -ENODEV;
+ }
+
+ if (vsi->type != I40E_VSI_FCOE) {
+ netdev_err(netdev, "interface does not support FCoE.\n");
+ return -EBUSY;
+ }
+
+ atomic_inc(&fcoe->refcnt);
+
+ return 0;
+}
+
+/**
+ * i40e_fcoe_disable- disables FCoE for upper FCoE protocol stack.
+ * @dev: pointer to the netdev that FCoE is created on
+ *
+ * Returns 0 on success
+ *
+ **/
+int i40e_fcoe_disable(struct net_device *netdev)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+
+ if (!(pf->flags & I40E_FLAG_FCOE_ENABLED)) {
+ netdev_err(netdev, "device does not support FCoE\n");
+ return -ENODEV;
+ }
+ if (vsi->type != I40E_VSI_FCOE)
+ return -EBUSY;
+
+ if (!atomic_dec_and_test(&fcoe->refcnt))
+ return -EINVAL;
+
+ netdev_info(netdev, "FCoE disabled\n");
+
+ return 0;
+}
+
+/**
+ * i40e_fcoe_dma_pool_free - free the per cpu pool for FCoE DDP
+ * @fcoe: the FCoE sw object
+ * @dev: the device that the pool is associated with
+ * @cpu: the cpu for this pool
+ *
+ **/
+static void i40e_fcoe_dma_pool_free(struct i40e_fcoe *fcoe,
+ struct device *dev,
+ unsigned int cpu)
+{
+ struct i40e_fcoe_ddp_pool *ddp_pool;
+
+ ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
+ if (!ddp_pool->pool) {
+ dev_warn(dev, "DDP pool already freed for cpu %d\n", cpu);
+ return;
+ }
+ dma_pool_destroy(ddp_pool->pool);
+ ddp_pool->pool = NULL;
+}
+
+/**
+ * i40e_fcoe_dma_pool_create - per cpu pool for FCoE DDP
+ * @fcoe: the FCoE sw object
+ * @dev: the device that the pool is associated with
+ * @cpu: the cpu for this pool
+ *
+ * Returns 0 on successful or non zero on failure
+ *
+ **/
+static int i40e_fcoe_dma_pool_create(struct i40e_fcoe *fcoe,
+ struct device *dev,
+ unsigned int cpu)
+{
+ struct i40e_fcoe_ddp_pool *ddp_pool;
+ struct dma_pool *pool;
+ char pool_name[32];
+
+ ddp_pool = per_cpu_ptr(fcoe->ddp_pool, cpu);
+ if (ddp_pool && ddp_pool->pool) {
+ dev_warn(dev, "DDP pool already allocated for cpu %d\n", cpu);
+ return 0;
+ }
+ snprintf(pool_name, sizeof(pool_name), "i40e_fcoe_ddp_%d", cpu);
+ pool = dma_pool_create(pool_name, dev, I40E_FCOE_DDP_PTR_MAX,
+ I40E_FCOE_DDP_PTR_ALIGN, PAGE_SIZE);
+ if (!pool) {
+ dev_err(dev, "dma_pool_create %s failed\n", pool_name);
+ return -ENOMEM;
+ }
+ ddp_pool->pool = pool;
+ return 0;
+}
+
+/**
+ * i40e_fcoe_free_ddp_resources - release FCoE DDP resources
+ * @vsi: the vsi FCoE is associated with
+ *
+ **/
+void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi)
+{
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ int cpu, i;
+
+ /* do nothing if not FCoE VSI */
+ if (vsi->type != I40E_VSI_FCOE)
+ return;
+
+ /* do nothing if no DDP pools were allocated */
+ if (!fcoe->ddp_pool)
+ return;
+
+ for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
+ i40e_fcoe_ddp_put(vsi->netdev, i);
+
+ for_each_possible_cpu(cpu)
+ i40e_fcoe_dma_pool_free(fcoe, &pf->pdev->dev, cpu);
+
+ free_percpu(fcoe->ddp_pool);
+ fcoe->ddp_pool = NULL;
+
+ netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources released\n",
+ vsi->id, vsi->seid);
+}
+
+/**
+ * i40e_fcoe_setup_ddp_resources - allocate per cpu DDP resources
+ * @vsi: the VSI FCoE is associated with
+ *
+ * Returns 0 on successful or non zero on failure
+ *
+ **/
+int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi)
+{
+ struct i40e_pf *pf = vsi->back;
+ struct device *dev = &pf->pdev->dev;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ unsigned int cpu;
+ int i;
+
+ if (vsi->type != I40E_VSI_FCOE)
+ return -ENODEV;
+
+ /* do nothing if no DDP pools were allocated */
+ if (fcoe->ddp_pool)
+ return -EEXIST;
+
+ /* allocate per CPU memory to track DDP pools */
+ fcoe->ddp_pool = alloc_percpu(struct i40e_fcoe_ddp_pool);
+ if (!fcoe->ddp_pool) {
+ dev_err(&pf->pdev->dev, "failed to allocate percpu DDP\n");
+ return -ENOMEM;
+ }
+
+ /* allocate pci pool for each cpu */
+ for_each_possible_cpu(cpu) {
+ if (!i40e_fcoe_dma_pool_create(fcoe, dev, cpu))
+ continue;
+
+ dev_err(dev, "failed to alloc DDP pool on cpu:%d\n", cpu);
+ i40e_fcoe_free_ddp_resources(vsi);
+ return -ENOMEM;
+ }
+
+ /* initialize the sw context */
+ for (i = 0; i < I40E_FCOE_DDP_MAX; i++)
+ i40e_fcoe_ddp_clear(&fcoe->ddp[i]);
+
+ netdev_info(vsi->netdev, "VSI %d,%d FCoE DDP resources allocated\n",
+ vsi->id, vsi->seid);
+
+ return 0;
+}
+
+/**
+ * i40e_fcoe_handle_status - check the Programming Status for FCoE
+ * @rx_ring: the Rx ring for this descriptor
+ * @rx_desc: the Rx descriptor for Programming Status, not a packet descriptor.
+ *
+ * Check if this is the Rx Programming Status descriptor write-back for FCoE.
+ * This is used to verify if the context/filter programming or invalidation
+ * requested by SW to the HW is successful or not and take actions accordingly.
+ **/
+void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc, u8 prog_id)
+{
+ struct i40e_pf *pf = rx_ring->vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ struct i40e_fcoe_ddp *ddp;
+ u32 error;
+ u16 xid;
+ u64 qw;
+
+ /* we only care for FCoE here */
+ if (!i40e_fcoe_progid_is_fcoe(prog_id))
+ return;
+
+ xid = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param) &
+ (I40E_FCOE_DDP_MAX - 1);
+
+ if (!i40e_fcoe_xid_is_valid(xid))
+ return;
+
+ ddp = &fcoe->ddp[xid];
+ WARN_ON(xid != ddp->xid);
+
+ qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ error = (qw & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
+ I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
+
+ /* DDP context programming status: failure or success */
+ if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) {
+ if (I40E_RX_PROG_FCOE_ERROR_TBL_FULL(error)) {
+ dev_err(&pf->pdev->dev, "xid %x ddp->xid %x TABLE FULL\n",
+ xid, ddp->xid);
+ ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT;
+ }
+ if (I40E_RX_PROG_FCOE_ERROR_CONFLICT(error)) {
+ dev_err(&pf->pdev->dev, "xid %x ddp->xid %x CONFLICT\n",
+ xid, ddp->xid);
+ ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT;
+ }
+ }
+
+ /* DDP context invalidation status: failure or success */
+ if (prog_id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS) {
+ if (I40E_RX_PROG_FCOE_ERROR_INVLFAIL(error)) {
+ dev_err(&pf->pdev->dev, "xid %x ddp->xid %x INVALIDATION FAILURE\n",
+ xid, ddp->xid);
+ ddp->prerr |= I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT;
+ }
+ /* clear the flag so we can retry invalidation */
+ clear_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags);
+ }
+
+ /* unmap DMA */
+ i40e_fcoe_ddp_unmap(pf, ddp);
+ i40e_fcoe_ddp_clear(ddp);
+}
+
+/**
+ * i40e_fcoe_handle_offload - check ddp status and mark it done
+ * @adapter: i40e adapter
+ * @rx_desc: advanced rx descriptor
+ * @skb: the skb holding the received data
+ *
+ * This checks ddp status.
+ *
+ * Returns : < 0 indicates an error or not a FCOE ddp, 0 indicates
+ * not passing the skb to ULD, > 0 indicates is the length of data
+ * being ddped.
+ *
+ **/
+int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
+ union i40e_rx_desc *rx_desc,
+ struct sk_buff *skb)
+{
+ struct i40e_pf *pf = rx_ring->vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ struct fc_frame_header *fh = NULL;
+ struct i40e_fcoe_ddp *ddp = NULL;
+ u32 status, fltstat;
+ u32 error, fcerr;
+ int rc = -EINVAL;
+ u16 ptype;
+ u16 xid;
+ u64 qw;
+
+ /* check this rxd is for programming status */
+ qw = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+ /* packet descriptor, check packet type */
+ ptype = (qw & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT;
+ if (!i40e_rx_is_fcoe(ptype))
+ goto out_no_ddp;
+
+ error = (qw & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT;
+ fcerr = (error >> I40E_RX_DESC_ERROR_L3L4E_SHIFT) &
+ I40E_RX_DESC_FCOE_ERROR_MASK;
+
+ /* check stateless offload error */
+ if (unlikely(fcerr == I40E_RX_DESC_ERROR_L3L4E_PROT)) {
+ dev_err(&pf->pdev->dev, "Protocol Error\n");
+ skb->ip_summed = CHECKSUM_NONE;
+ } else {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+
+ /* check hw status on ddp */
+ status = (qw & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT;
+ fltstat = (status >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) &
+ I40E_RX_DESC_FLTSTAT_FCMASK;
+
+ /* now we are ready to check DDP */
+ fh = i40e_fcoe_fc_frame_header(skb);
+ xid = i40e_fcoe_fc_get_xid(fh);
+ if (!i40e_fcoe_xid_is_valid(xid))
+ goto out_no_ddp;
+
+ /* non DDP normal receive, return to the protocol stack */
+ if (fltstat == I40E_RX_DESC_FLTSTAT_NOMTCH)
+ goto out_no_ddp;
+
+ /* do we have a sw ddp context setup ? */
+ ddp = &fcoe->ddp[xid];
+ if (!ddp->sgl)
+ goto out_no_ddp;
+
+ /* fetch xid from hw rxd wb, which should match up the sw ctxt */
+ xid = le16_to_cpu(rx_desc->wb.qword0.lo_dword.mirr_fcoe.fcoe_ctx_id);
+ if (ddp->xid != xid) {
+ dev_err(&pf->pdev->dev, "xid 0x%x does not match ctx_xid 0x%x\n",
+ ddp->xid, xid);
+ goto out_put_ddp;
+ }
+
+ /* the same exchange has already errored out */
+ if (ddp->fcerr) {
+ dev_err(&pf->pdev->dev, "xid 0x%x fcerr 0x%x reported fcer 0x%x\n",
+ xid, ddp->fcerr, fcerr);
+ goto out_put_ddp;
+ }
+
+ /* fcoe param is valid by now with correct DDPed length */
+ ddp->len = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fcoe_param);
+ ddp->fcerr = fcerr;
+ /* header posting only, useful only for target mode and debugging */
+ if (fltstat == I40E_RX_DESC_FLTSTAT_DDP) {
+ /* For target mode, we get header of the last packet but it
+ * does not have the FCoE trailer field, i.e., CRC and EOF
+ * Ordered Set since they are offloaded by the HW, so fill
+ * it up correspondingly to allow the packet to pass through
+ * to the upper protocol stack.
+ */
+ u32 f_ctl = ntoh24(fh->fh_f_ctl);
+
+ if ((f_ctl & FC_FC_END_SEQ) &&
+ (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA)) {
+ struct fcoe_crc_eof *crc = NULL;
+
+ crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
+ crc->fcoe_eof = FC_EOF_T;
+ } else {
+ /* otherwise, drop the header only frame */
+ rc = 0;
+ goto out_no_ddp;
+ }
+ }
+
+out_put_ddp:
+ /* either we got RSP or we have an error, unmap DMA in both cases */
+ i40e_fcoe_ddp_unmap(pf, ddp);
+ if (ddp->len && !ddp->fcerr) {
+ int pkts;
+
+ rc = ddp->len;
+ i40e_fcoe_ddp_clear(ddp);
+ ddp->len = rc;
+ pkts = DIV_ROUND_UP(rc, 2048);
+ rx_ring->stats.bytes += rc;
+ rx_ring->stats.packets += pkts;
+ rx_ring->q_vector->rx.total_bytes += rc;
+ rx_ring->q_vector->rx.total_packets += pkts;
+ set_bit(__I40E_FCOE_DDP_DONE, &ddp->flags);
+ }
+
+out_no_ddp:
+ return rc;
+}
+
+/**
+ * i40e_fcoe_ddp_setup - called to set up ddp context
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ * @target_mode: indicates this is a DDP request for target
+ *
+ * Returns : 1 for success and 0 for no DDP on this I/O
+ **/
+static int i40e_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc,
+ int target_mode)
+{
+ static const unsigned int bufflen = I40E_FCOE_DDP_BUF_MIN;
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_fcoe_ddp_pool *ddp_pool;
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ unsigned int i, j, dmacount;
+ struct i40e_fcoe_ddp *ddp;
+ unsigned int firstoff = 0;
+ unsigned int thisoff = 0;
+ unsigned int thislen = 0;
+ struct scatterlist *sg;
+ dma_addr_t addr = 0;
+ unsigned int len;
+
+ if (xid >= I40E_FCOE_DDP_MAX) {
+ dev_warn(&pf->pdev->dev, "xid=0x%x out-of-range\n", xid);
+ return 0;
+ }
+
+ /* no DDP if we are already down or resetting */
+ if (test_bit(__I40E_DOWN, &pf->state) ||
+ test_bit(__I40E_NEEDS_RESTART, &pf->state)) {
+ dev_info(&pf->pdev->dev, "xid=0x%x device in reset/down\n",
+ xid);
+ return 0;
+ }
+
+ ddp = &fcoe->ddp[xid];
+ if (ddp->sgl) {
+ dev_info(&pf->pdev->dev, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
+ xid, ddp->sgl, ddp->sgc);
+ return 0;
+ }
+ i40e_fcoe_ddp_clear(ddp);
+
+ if (!fcoe->ddp_pool) {
+ dev_info(&pf->pdev->dev, "No DDP pool, xid 0x%x\n", xid);
+ return 0;
+ }
+
+ ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu());
+ if (!ddp_pool->pool) {
+ dev_info(&pf->pdev->dev, "No percpu ddp pool, xid 0x%x\n", xid);
+ goto out_noddp;
+ }
+
+ /* setup dma from scsi command sgl */
+ dmacount = dma_map_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
+ if (dmacount == 0) {
+ dev_info(&pf->pdev->dev, "dma_map_sg for sgl %p, sgc %d failed\n",
+ sgl, sgc);
+ goto out_noddp_unmap;
+ }
+
+ /* alloc the udl from our ddp pool */
+ ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp);
+ if (!ddp->udl) {
+ dev_info(&pf->pdev->dev,
+ "Failed allocated ddp context, xid 0x%x\n", xid);
+ goto out_noddp_unmap;
+ }
+
+ j = 0;
+ ddp->len = 0;
+ for_each_sg(sgl, sg, dmacount, i) {
+ addr = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+ ddp->len += len;
+ while (len) {
+ /* max number of buffers allowed in one DDP context */
+ if (j >= I40E_FCOE_DDP_BUFFCNT_MAX) {
+ dev_info(&pf->pdev->dev,
+ "xid=%x:%d,%d,%d:addr=%llx not enough descriptors\n",
+ xid, i, j, dmacount, (u64)addr);
+ goto out_noddp_free;
+ }
+
+ /* get the offset of length of current buffer */
+ thisoff = addr & ((dma_addr_t)bufflen - 1);
+ thislen = min_t(unsigned int, (bufflen - thisoff), len);
+ /* all but the 1st buffer (j == 0)
+ * must be aligned on bufflen
+ */
+ if ((j != 0) && (thisoff))
+ goto out_noddp_free;
+
+ /* all but the last buffer
+ * ((i == (dmacount - 1)) && (thislen == len))
+ * must end at bufflen
+ */
+ if (((i != (dmacount - 1)) || (thislen != len)) &&
+ ((thislen + thisoff) != bufflen))
+ goto out_noddp_free;
+
+ ddp->udl[j] = (u64)(addr - thisoff);
+ /* only the first buffer may have none-zero offset */
+ if (j == 0)
+ firstoff = thisoff;
+ len -= thislen;
+ addr += thislen;
+ j++;
+ }
+ }
+ /* only the last buffer may have non-full bufflen */
+ ddp->lastsize = thisoff + thislen;
+ ddp->firstoff = firstoff;
+ ddp->list_len = j;
+ ddp->pool = ddp_pool->pool;
+ ddp->sgl = sgl;
+ ddp->sgc = sgc;
+ ddp->xid = xid;
+ if (target_mode)
+ set_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
+ set_bit(__I40E_FCOE_DDP_INITALIZED, &ddp->flags);
+
+ put_cpu();
+ return 1; /* Success */
+
+out_noddp_free:
+ dma_pool_free(ddp->pool, ddp->udl, ddp->udp);
+ i40e_fcoe_ddp_clear(ddp);
+
+out_noddp_unmap:
+ dma_unmap_sg(&pf->pdev->dev, sgl, sgc, DMA_FROM_DEVICE);
+out_noddp:
+ put_cpu();
+ return 0;
+}
+
+/**
+ * i40e_fcoe_ddp_get - called to set up ddp context in initiator mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ **/
+static int i40e_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
+}
+
+/**
+ * i40e_fcoe_ddp_target - called to set up ddp context in target mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O. The DDP in target mode is a write I/O request
+ * from the initiator.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ **/
+static int i40e_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ return i40e_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
+}
+
+/**
+ * i40e_fcoe_program_ddp - programs the HW DDP related descriptors
+ * @tx_ring: transmit ring for this packet
+ * @skb: the packet to be sent out
+ * @sof: the SOF to indicate class of service
+ *
+ * Determine if it is READ/WRITE command, and finds out if there is
+ * a matching SW DDP context for this command. DDP is applicable
+ * only in case of READ if initiator or WRITE in case of
+ * responder (via checking XFER_RDY).
+ *
+ * Note: caller checks sof and ddp sw context
+ *
+ * Returns : none
+ *
+ **/
+static void i40e_fcoe_program_ddp(struct i40e_ring *tx_ring,
+ struct sk_buff *skb,
+ struct i40e_fcoe_ddp *ddp, u8 sof)
+{
+ struct i40e_fcoe_filter_context_desc *filter_desc = NULL;
+ struct i40e_fcoe_queue_context_desc *queue_desc = NULL;
+ struct i40e_fcoe_ddp_context_desc *ddp_desc = NULL;
+ struct i40e_pf *pf = tx_ring->vsi->back;
+ u16 i = tx_ring->next_to_use;
+ struct fc_frame_header *fh;
+ u64 flags_rsvd_lanq = 0;
+ bool target_mode;
+
+ /* check if abort is still pending */
+ if (test_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags)) {
+ dev_warn(&pf->pdev->dev,
+ "DDP abort is still pending xid:%hx and ddp->flags:%lx:\n",
+ ddp->xid, ddp->flags);
+ return;
+ }
+
+ /* set the flag to indicate this is programmed */
+ if (test_and_set_bit(__I40E_FCOE_DDP_PROGRAMMED, &ddp->flags)) {
+ dev_warn(&pf->pdev->dev,
+ "DDP is already programmed for xid:%hx and ddp->flags:%lx:\n",
+ ddp->xid, ddp->flags);
+ return;
+ }
+
+ /* Prepare the DDP context descriptor */
+ ddp_desc = I40E_DDP_CONTEXT_DESC(tx_ring, i);
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
+ ddp_desc->type_cmd_foff_lsize =
+ cpu_to_le64(I40E_TX_DESC_DTYPE_DDP_CTX |
+ ((u64)I40E_FCOE_DDP_CTX_DESC_BSIZE_4K <<
+ I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT) |
+ ((u64)ddp->firstoff <<
+ I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT) |
+ ((u64)ddp->lastsize <<
+ I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT));
+ ddp_desc->rsvd = cpu_to_le64(0);
+
+ /* target mode needs last packet in the sequence */
+ target_mode = test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags);
+ if (target_mode)
+ ddp_desc->type_cmd_foff_lsize |=
+ cpu_to_le64(I40E_FCOE_DDP_CTX_DESC_LASTSEQH);
+
+ /* Prepare queue_context descriptor */
+ queue_desc = I40E_QUEUE_CONTEXT_DESC(tx_ring, i++);
+ if (i == tx_ring->count)
+ i = 0;
+ queue_desc->dmaindx_fbase = cpu_to_le64(ddp->xid | ((u64)ddp->udp));
+ queue_desc->flen_tph = cpu_to_le64(ddp->list_len |
+ ((u64)(I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC |
+ I40E_FCOE_QUEUE_CTX_DESC_TPHDATA) <<
+ I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT));
+
+ /* Prepare filter_context_desc */
+ filter_desc = I40E_FILTER_CONTEXT_DESC(tx_ring, i);
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
+ fh = (struct fc_frame_header *)skb_transport_header(skb);
+ filter_desc->param = cpu_to_le32(ntohl(fh->fh_parm_offset));
+ filter_desc->seqn = cpu_to_le16(ntohs(fh->fh_seq_cnt));
+ filter_desc->rsvd_dmaindx = cpu_to_le16(ddp->xid <<
+ I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT);
+
+ flags_rsvd_lanq = I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP;
+ flags_rsvd_lanq |= (u64)(target_mode ?
+ I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP :
+ I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT);
+
+ flags_rsvd_lanq |= (u64)((sof == FC_SOF_I2 || sof == FC_SOF_N2) ?
+ I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 :
+ I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3);
+
+ flags_rsvd_lanq |= ((u64)skb->queue_mapping <<
+ I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT);
+ filter_desc->flags_rsvd_lanq = cpu_to_le64(flags_rsvd_lanq);
+
+ /* By this time, all offload related descriptors has been programmed */
+ tx_ring->next_to_use = i;
+}
+
+/**
+ * i40e_fcoe_invalidate_ddp - invalidates DDP in case of abort
+ * @tx_ring: transmit ring for this packet
+ * @skb: the packet associated w/ this DDP invalidation, i.e., ABTS
+ * @ddp: the SW DDP context for this DDP
+ *
+ * Programs the Tx context descriptor to do DDP invalidation.
+ **/
+static void i40e_fcoe_invalidate_ddp(struct i40e_ring *tx_ring,
+ struct sk_buff *skb,
+ struct i40e_fcoe_ddp *ddp)
+{
+ struct i40e_tx_context_desc *context_desc;
+ int i;
+
+ if (test_and_set_bit(__I40E_FCOE_DDP_ABORTED, &ddp->flags))
+ return;
+
+ i = tx_ring->next_to_use;
+ context_desc = I40E_TX_CTXTDESC(tx_ring, i);
+ i++;
+ if (i == tx_ring->count)
+ i = 0;
+
+ context_desc->tunneling_params = cpu_to_le32(0);
+ context_desc->l2tag2 = cpu_to_le16(0);
+ context_desc->rsvd = cpu_to_le16(0);
+ context_desc->type_cmd_tso_mss = cpu_to_le64(
+ I40E_TX_DESC_DTYPE_FCOE_CTX |
+ (I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL <<
+ I40E_TXD_CTX_QW1_CMD_SHIFT) |
+ (I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND <<
+ I40E_TXD_CTX_QW1_CMD_SHIFT));
+ tx_ring->next_to_use = i;
+}
+
+/**
+ * i40e_fcoe_handle_ddp - check we should setup or invalidate DDP
+ * @tx_ring: transmit ring for this packet
+ * @skb: the packet to be sent out
+ * @sof: the SOF to indicate class of service
+ *
+ * Determine if it is ABTS/READ/XFER_RDY, and finds out if there is
+ * a matching SW DDP context for this command. DDP is applicable
+ * only in case of READ if initiator or WRITE in case of
+ * responder (via checking XFER_RDY). In case this is an ABTS, send
+ * just invalidate the context.
+ **/
+static void i40e_fcoe_handle_ddp(struct i40e_ring *tx_ring,
+ struct sk_buff *skb, u8 sof)
+{
+ struct i40e_pf *pf = tx_ring->vsi->back;
+ struct i40e_fcoe *fcoe = &pf->fcoe;
+ struct fc_frame_header *fh;
+ struct i40e_fcoe_ddp *ddp;
+ u32 f_ctl;
+ u8 r_ctl;
+ u16 xid;
+
+ fh = (struct fc_frame_header *)skb_transport_header(skb);
+ f_ctl = ntoh24(fh->fh_f_ctl);
+ r_ctl = fh->fh_r_ctl;
+ ddp = NULL;
+
+ if ((r_ctl == FC_RCTL_DD_DATA_DESC) && (f_ctl & FC_FC_EX_CTX)) {
+ /* exchange responder? if so, XFER_RDY for write */
+ xid = ntohs(fh->fh_rx_id);
+ if (i40e_fcoe_xid_is_valid(xid)) {
+ ddp = &fcoe->ddp[xid];
+ if ((ddp->xid == xid) &&
+ (test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+ i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
+ }
+ } else if (r_ctl == FC_RCTL_DD_UNSOL_CMD) {
+ /* exchange originator, check READ cmd */
+ xid = ntohs(fh->fh_ox_id);
+ if (i40e_fcoe_xid_is_valid(xid)) {
+ ddp = &fcoe->ddp[xid];
+ if ((ddp->xid == xid) &&
+ (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+ i40e_fcoe_program_ddp(tx_ring, skb, ddp, sof);
+ }
+ } else if (r_ctl == FC_RCTL_BA_ABTS) {
+ /* exchange originator, check ABTS */
+ xid = ntohs(fh->fh_ox_id);
+ if (i40e_fcoe_xid_is_valid(xid)) {
+ ddp = &fcoe->ddp[xid];
+ if ((ddp->xid == xid) &&
+ (!test_bit(__I40E_FCOE_DDP_TARGET, &ddp->flags)))
+ i40e_fcoe_invalidate_ddp(tx_ring, skb, ddp);
+ }
+ }
+}
+
+/**
+ * i40e_fcoe_tso - set up FCoE TSO
+ * @tx_ring: ring to send buffer on
+ * @skb: send buffer
+ * @tx_flags: collected send information
+ * @hdr_len: the tso header length
+ * @sof: the SOF to indicate class of service
+ *
+ * Note must already have sof checked to be either class 2 or class 3 before
+ * calling this function.
+ *
+ * Returns 1 to indicate sequence segmentation offload is properly setup
+ * or returns 0 to indicate no tso is needed, otherwise returns error
+ * code to drop the frame.
+ **/
+static int i40e_fcoe_tso(struct i40e_ring *tx_ring,
+ struct sk_buff *skb,
+ u32 tx_flags, u8 *hdr_len, u8 sof)
+{
+ struct i40e_tx_context_desc *context_desc;
+ u32 cd_type, cd_cmd, cd_tso_len, cd_mss;
+ struct fc_frame_header *fh;
+ u64 cd_type_cmd_tso_mss;
+
+ /* must match gso type as FCoE */
+ if (!skb_is_gso(skb))
+ return 0;
+
+ /* is it the expected gso type for FCoE ?*/
+ if (skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) {
+ netdev_err(skb->dev,
+ "wrong gso type %d:expecting SKB_GSO_FCOE\n",
+ skb_shinfo(skb)->gso_type);
+ return -EINVAL;
+ }
+
+ /* header and trailer are inserted by hw */
+ *hdr_len = skb_transport_offset(skb) + sizeof(struct fc_frame_header) +
+ sizeof(struct fcoe_crc_eof);
+
+ /* check sof to decide a class 2 or 3 TSO */
+ if (likely(i40e_fcoe_sof_is_class3(sof)))
+ cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3;
+ else
+ cd_cmd = I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2;
+
+ /* param field valid? */
+ fh = (struct fc_frame_header *)skb_transport_header(skb);
+ if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
+ cd_cmd |= I40E_FCOE_TX_CTX_DESC_RELOFF;
+
+ /* fill the field values */
+ cd_type = I40E_TX_DESC_DTYPE_FCOE_CTX;
+ cd_tso_len = skb->len - *hdr_len;
+ cd_mss = skb_shinfo(skb)->gso_size;
+ cd_type_cmd_tso_mss =
+ ((u64)cd_type << I40E_TXD_CTX_QW1_DTYPE_SHIFT) |
+ ((u64)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) |
+ ((u64)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) |
+ ((u64)cd_mss << I40E_TXD_CTX_QW1_MSS_SHIFT);
+
+ /* grab the next descriptor */
+ context_desc = I40E_TX_CTXTDESC(tx_ring, tx_ring->next_to_use);
+ tx_ring->next_to_use++;
+ if (tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+
+ context_desc->tunneling_params = 0;
+ context_desc->l2tag2 = cpu_to_le16((tx_flags & I40E_TX_FLAGS_VLAN_MASK)
+ >> I40E_TX_FLAGS_VLAN_SHIFT);
+ context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
+
+ return 1;
+}
+
+/**
+ * i40e_fcoe_tx_map - build the tx descriptor
+ * @tx_ring: ring to send buffer on
+ * @skb: send buffer
+ * @first: first buffer info buffer to use
+ * @tx_flags: collected send information
+ * @hdr_len: ptr to the size of the packet header
+ * @eof: the frame eof value
+ *
+ * Note, for FCoE, sof and eof are already checked
+ **/
+static void i40e_fcoe_tx_map(struct i40e_ring *tx_ring,
+ struct sk_buff *skb,
+ struct i40e_tx_buffer *first,
+ u32 tx_flags, u8 hdr_len, u8 eof)
+{
+ u32 td_offset = 0;
+ u32 td_cmd = 0;
+ u32 maclen;
+
+ /* insert CRC */
+ td_cmd = I40E_TX_DESC_CMD_ICRC;
+
+ /* setup MACLEN */
+ maclen = skb_network_offset(skb);
+ if (tx_flags & I40E_TX_FLAGS_SW_VLAN)
+ maclen += sizeof(struct vlan_hdr);
+
+ if (skb->protocol == htons(ETH_P_FCOE)) {
+ /* for FCoE, maclen should exclude ether type */
+ maclen -= 2;
+ /* setup type as FCoE and EOF insertion */
+ td_cmd |= (I40E_TX_DESC_CMD_FCOET | i40e_fcoe_ctxt_eof(eof));
+ /* setup FCoELEN and FCLEN */
+ td_offset |= ((((sizeof(struct fcoe_hdr) + 2) >> 2) <<
+ I40E_TX_DESC_LENGTH_IPLEN_SHIFT) |
+ ((sizeof(struct fc_frame_header) >> 2) <<
+ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT));
+ /* trim to exclude trailer */
+ pskb_trim(skb, skb->len - sizeof(struct fcoe_crc_eof));
+ }
+
+ /* MACLEN is ether header length in words not bytes */
+ td_offset |= (maclen >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT;
+
+ return i40e_tx_map(tx_ring, skb, first, tx_flags, hdr_len,
+ td_cmd, td_offset);
+}
+
+/**
+ * i40e_fcoe_set_skb_header - adjust skb header point for FIP/FCoE/FC
+ * @skb: the skb to be adjusted
+ *
+ * Returns true if this skb is a FCoE/FIP or VLAN carried FCoE/FIP and then
+ * adjusts the skb header pointers correspondingly. Otherwise, returns false.
+ **/
+static inline int i40e_fcoe_set_skb_header(struct sk_buff *skb)
+{
+ __be16 protocol = skb->protocol;
+
+ skb_reset_mac_header(skb);
+ skb->mac_len = sizeof(struct ethhdr);
+ if (protocol == htons(ETH_P_8021Q)) {
+ struct vlan_ethhdr *veth = (struct vlan_ethhdr *)eth_hdr(skb);
+
+ protocol = veth->h_vlan_encapsulated_proto;
+ skb->mac_len += sizeof(struct vlan_hdr);
+ }
+
+ /* FCoE or FIP only */
+ if ((protocol != htons(ETH_P_FIP)) &&
+ (protocol != htons(ETH_P_FCOE)))
+ return -EINVAL;
+
+ /* set header to L2 of FCoE/FIP */
+ skb_set_network_header(skb, skb->mac_len);
+ if (protocol == htons(ETH_P_FIP))
+ return 0;
+
+ /* set header to L3 of FC */
+ skb_set_transport_header(skb, skb->mac_len + sizeof(struct fcoe_hdr));
+ return 0;
+}
+
+/**
+ * i40e_fcoe_xmit_frame - transmit buffer
+ * @skb: send buffer
+ * @netdev: the fcoe netdev
+ *
+ * Returns 0 if sent, else an error code
+ **/
+static netdev_tx_t i40e_fcoe_xmit_frame(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct i40e_netdev_priv *np = netdev_priv(skb->dev);
+ struct i40e_vsi *vsi = np->vsi;
+ struct i40e_ring *tx_ring = vsi->tx_rings[skb->queue_mapping];
+ struct i40e_tx_buffer *first;
+ u32 tx_flags = 0;
+ u8 hdr_len = 0;
+ u8 sof = 0;
+ u8 eof = 0;
+ int fso;
+
+ if (i40e_fcoe_set_skb_header(skb))
+ goto out_drop;
+
+ if (!i40e_xmit_descriptor_count(skb, tx_ring))
+ return NETDEV_TX_BUSY;
+
+ /* prepare the xmit flags */
+ if (i40e_tx_prepare_vlan_flags(skb, tx_ring, &tx_flags))
+ goto out_drop;
+
+ /* record the location of the first descriptor for this packet */
+ first = &tx_ring->tx_bi[tx_ring->next_to_use];
+
+ /* FIP is a regular L2 traffic w/o offload */
+ if (skb->protocol == htons(ETH_P_FIP))
+ goto out_send;
+
+ /* check sof and eof, only supports FC Class 2 or 3 */
+ if (i40e_fcoe_fc_sof(skb, &sof) || i40e_fcoe_fc_eof(skb, &eof)) {
+ netdev_err(netdev, "SOF/EOF error:%02x - %02x\n", sof, eof);
+ goto out_drop;
+ }
+
+ /* always do FCCRC for FCoE */
+ tx_flags |= I40E_TX_FLAGS_FCCRC;
+
+ /* check we should do sequence offload */
+ fso = i40e_fcoe_tso(tx_ring, skb, tx_flags, &hdr_len, sof);
+ if (fso < 0)
+ goto out_drop;
+ else if (fso)
+ tx_flags |= I40E_TX_FLAGS_FSO;
+ else
+ i40e_fcoe_handle_ddp(tx_ring, skb, sof);
+
+out_send:
+ /* send out the packet */
+ i40e_fcoe_tx_map(tx_ring, skb, first, tx_flags, hdr_len, eof);
+
+ i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
+ return NETDEV_TX_OK;
+
+out_drop:
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+/**
+ * i40e_fcoe_change_mtu - NDO callback to change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns error as operation not permitted
+ *
+ **/
+static int i40e_fcoe_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ netdev_warn(netdev, "MTU change is not supported on FCoE interfaces\n");
+ return -EPERM;
+}
+
+/**
+ * i40e_fcoe_set_features - set the netdev feature flags
+ * @netdev: ptr to the netdev being adjusted
+ * @features: the feature set that the stack is suggesting
+ *
+ **/
+static int i40e_fcoe_set_features(struct net_device *netdev,
+ netdev_features_t features)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_vsi *vsi = np->vsi;
+
+ if (features & NETIF_F_HW_VLAN_CTAG_RX)
+ i40e_vlan_stripping_enable(vsi);
+ else
+ i40e_vlan_stripping_disable(vsi);
+
+ return 0;
+}
+
+
+static const struct net_device_ops i40e_fcoe_netdev_ops = {
+ .ndo_open = i40e_open,
+ .ndo_stop = i40e_close,
+ .ndo_get_stats64 = i40e_get_netdev_stats_struct,
+ .ndo_set_rx_mode = i40e_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = i40e_set_mac,
+ .ndo_change_mtu = i40e_fcoe_change_mtu,
+ .ndo_do_ioctl = i40e_ioctl,
+ .ndo_tx_timeout = i40e_tx_timeout,
+ .ndo_vlan_rx_add_vid = i40e_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = i40e_vlan_rx_kill_vid,
+ .ndo_setup_tc = i40e_setup_tc,
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = i40e_netpoll,
+#endif
+ .ndo_start_xmit = i40e_fcoe_xmit_frame,
+ .ndo_fcoe_enable = i40e_fcoe_enable,
+ .ndo_fcoe_disable = i40e_fcoe_disable,
+ .ndo_fcoe_ddp_setup = i40e_fcoe_ddp_get,
+ .ndo_fcoe_ddp_done = i40e_fcoe_ddp_put,
+ .ndo_fcoe_ddp_target = i40e_fcoe_ddp_target,
+ .ndo_set_features = i40e_fcoe_set_features,
+};
+
+/**
+ * i40e_fcoe_config_netdev - prepares the VSI context for creating a FCoE VSI
+ * @vsi: pointer to the associated VSI struct
+ * @ctxt: pointer to the associated VSI context to be passed to HW
+ *
+ * Returns 0 on success or < 0 on error
+ **/
+void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi)
+{
+ struct i40e_hw *hw = &vsi->back->hw;
+ struct i40e_pf *pf = vsi->back;
+
+ if (vsi->type != I40E_VSI_FCOE)
+ return;
+
+ netdev->features = (NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER);
+
+ netdev->vlan_features = netdev->features;
+ netdev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER);
+ netdev->fcoe_ddp_xid = I40E_FCOE_DDP_MAX - 1;
+ netdev->features |= NETIF_F_ALL_FCOE;
+ netdev->vlan_features |= NETIF_F_ALL_FCOE;
+ netdev->hw_features |= netdev->features;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+ netdev->priv_flags |= IFF_SUPP_NOFCS;
+
+ strlcpy(netdev->name, "fcoe%d", IFNAMSIZ-1);
+ netdev->mtu = FCOE_MTU;
+ SET_NETDEV_DEV(netdev, &pf->pdev->dev);
+ i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);
+ i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false);
+ i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);
+ i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);
+ i40e_add_filter(vsi, FIP_ALL_VN2VN_MACS, 0, false, false);
+ i40e_add_filter(vsi, FIP_ALL_P2P_MACS, 0, false, false);
+
+ /* use san mac */
+ ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
+ ether_addr_copy(netdev->perm_addr, hw->mac.san_addr);
+ /* fcoe netdev ops */
+ netdev->netdev_ops = &i40e_fcoe_netdev_ops;
+}
+
+/**
+ * i40e_fcoe_vsi_setup - allocate and set up FCoE VSI
+ * @pf: the pf that VSI is associated with
+ *
+ **/
+void i40e_fcoe_vsi_setup(struct i40e_pf *pf)
+{
+ struct i40e_vsi *vsi;
+ u16 seid;
+ int i;
+
+ if (!(pf->flags & I40E_FLAG_FCOE_ENABLED))
+ return;
+
+ BUG_ON(!pf->vsi[pf->lan_vsi]);
+
+ for (i = 0; i < pf->num_alloc_vsi; i++) {
+ vsi = pf->vsi[i];
+ if (vsi && vsi->type == I40E_VSI_FCOE) {
+ dev_warn(&pf->pdev->dev,
+ "FCoE VSI already created\n");
+ return;
+ }
+ }
+
+ seid = pf->vsi[pf->lan_vsi]->seid;
+ vsi = i40e_vsi_setup(pf, I40E_VSI_FCOE, seid, 0);
+ if (vsi) {
+ dev_dbg(&pf->pdev->dev,
+ "Successfully created FCoE VSI seid %d id %d uplink_seid %d pf seid %d\n",
+ vsi->seid, vsi->id, vsi->uplink_seid, seid);
+ } else {
+ dev_info(&pf->pdev->dev, "Failed to create FCoE VSI\n");
+ }
+}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.h b/drivers/net/ethernet/intel/i40e/i40e_fcoe.h
new file mode 100644
index 000000000000..21e0f582031c
--- /dev/null
+++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.h
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ *
+ * Intel Ethernet Controller XL710 Family Linux Driver
+ * Copyright(c) 2013 - 2014 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, see <http://www.gnu.org/licenses/>.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ ******************************************************************************/
+
+#ifndef _I40E_FCOE_H_
+#define _I40E_FCOE_H_
+
+/* FCoE HW context helper macros */
+#define I40E_DDP_CONTEXT_DESC(R, i) \
+ (&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
+
+#define I40E_QUEUE_CONTEXT_DESC(R, i) \
+ (&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
+
+#define I40E_FILTER_CONTEXT_DESC(R, i) \
+ (&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
+
+
+/* receive queue descriptor filter status for FCoE */
+#define I40E_RX_DESC_FLTSTAT_FCMASK 0x3
+#define I40E_RX_DESC_FLTSTAT_NOMTCH 0x0 /* no ddp context match */
+#define I40E_RX_DESC_FLTSTAT_NODDP 0x1 /* no ddp due to error */
+#define I40E_RX_DESC_FLTSTAT_DDP 0x2 /* DDPed payload, post header */
+#define I40E_RX_DESC_FLTSTAT_FCPRSP 0x3 /* FCP_RSP */
+
+/* receive queue descriptor error codes for FCoE */
+#define I40E_RX_DESC_FCOE_ERROR_MASK \
+ (I40E_RX_DESC_ERROR_L3L4E_PROT | \
+ I40E_RX_DESC_ERROR_L3L4E_FC | \
+ I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR | \
+ I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
+
+/* receive queue descriptor programming error */
+#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e) \
+ (((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
+
+#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e) \
+ (((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
+
+#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT \
+ (1 << I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
+#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT \
+ (1 << I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
+
+#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e) \
+ I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
+#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT \
+ I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
+
+/* FCoE DDP related definitions */
+#define I40E_FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
+#define I40E_FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
+#define I40E_FCOE_DDP_BUFFCNT_MAX 512 /* 9 bits bufcnt */
+#define I40E_FCOE_DDP_PTR_ALIGN 16
+#define I40E_FCOE_DDP_PTR_MAX (I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
+#define I40E_FCOE_DDP_BUF_MIN 4096
+#define I40E_FCOE_DDP_MAX 2048
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8
+
+/* supported netdev features for FCoE */
+#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
+ NETIF_F_HW_VLAN_CTAG_TX | \
+ NETIF_F_HW_VLAN_CTAG_RX | \
+ NETIF_F_HW_VLAN_CTAG_FILTER)
+
+/* DDP context flags */
+enum i40e_fcoe_ddp_flags {
+ __I40E_FCOE_DDP_NONE = 1,
+ __I40E_FCOE_DDP_TARGET,
+ __I40E_FCOE_DDP_INITALIZED,
+ __I40E_FCOE_DDP_PROGRAMMED,
+ __I40E_FCOE_DDP_DONE,
+ __I40E_FCOE_DDP_ABORTED,
+ __I40E_FCOE_DDP_UNMAPPED,
+};
+
+/* DDP SW context struct */
+struct i40e_fcoe_ddp {
+ int len;
+ u16 xid;
+ u16 firstoff;
+ u16 lastsize;
+ u16 list_len;
+ u8 fcerr;
+ u8 prerr;
+ unsigned long flags;
+ unsigned int sgc;
+ struct scatterlist *sgl;
+ dma_addr_t udp;
+ u64 *udl;
+ struct dma_pool *pool;
+
+};
+
+struct i40e_fcoe_ddp_pool {
+ struct dma_pool *pool;
+};
+
+struct i40e_fcoe {
+ unsigned long mode;
+ atomic_t refcnt;
+ struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
+ struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
+};
+
+#endif /* _I40E_FCOE_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_hmc.h b/drivers/net/ethernet/intel/i40e/i40e_hmc.h
index b45d8fedc5e7..732a02660330 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_hmc.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_hmc.h
@@ -127,7 +127,7 @@ struct i40e_hmc_info {
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \
(1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \
- val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
+ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
wr32((hw), I40E_PFHMC_SDCMD, val3); \
@@ -146,7 +146,7 @@ struct i40e_hmc_info {
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \
- val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
+ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
wr32((hw), I40E_PFHMC_SDCMD, val3); \
diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
index 870ab1ee072c..4627588f4613 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
@@ -417,7 +417,6 @@ static i40e_status i40e_create_lan_hmc_object(struct i40e_hw *hw,
default:
ret_code = I40E_ERR_INVALID_SD_TYPE;
goto exit;
- break;
}
}
}
@@ -502,7 +501,6 @@ try_type_paged:
hw_dbg(hw, "i40e_configure_lan_hmc: Unknown SD type: %d\n",
ret_code);
goto configure_lan_hmc_out;
- break;
}
/* Configure and program the FPM registers so objects can be created */
@@ -747,6 +745,194 @@ static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = {
};
/**
+ * i40e_write_byte - replace HMC context byte
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_byte(u8 *hmc_bits,
+ struct i40e_context_ele *ce_info,
+ u8 *src)
+{
+ u8 src_byte, dest_byte, mask;
+ u8 *from, *dest;
+ u16 shift_width;
+
+ /* copy from the next struct field */
+ from = src + ce_info->offset;
+
+ /* prepare the bits and mask */
+ shift_width = ce_info->lsb % 8;
+ mask = ((u8)1 << ce_info->width) - 1;
+
+ src_byte = *from;
+ src_byte &= mask;
+
+ /* shift to correct alignment */
+ mask <<= shift_width;
+ src_byte <<= shift_width;
+
+ /* get the current bits from the target bit string */
+ dest = hmc_bits + (ce_info->lsb / 8);
+
+ memcpy(&dest_byte, dest, sizeof(dest_byte));
+
+ dest_byte &= ~mask; /* get the bits not changing */
+ dest_byte |= src_byte; /* add in the new bits */
+
+ /* put it all back */
+ memcpy(dest, &dest_byte, sizeof(dest_byte));
+}
+
+/**
+ * i40e_write_word - replace HMC context word
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_word(u8 *hmc_bits,
+ struct i40e_context_ele *ce_info,
+ u8 *src)
+{
+ u16 src_word, mask;
+ u8 *from, *dest;
+ u16 shift_width;
+ __le16 dest_word;
+
+ /* copy from the next struct field */
+ from = src + ce_info->offset;
+
+ /* prepare the bits and mask */
+ shift_width = ce_info->lsb % 8;
+ mask = ((u16)1 << ce_info->width) - 1;
+
+ /* don't swizzle the bits until after the mask because the mask bits
+ * will be in a different bit position on big endian machines
+ */
+ src_word = *(u16 *)from;
+ src_word &= mask;
+
+ /* shift to correct alignment */
+ mask <<= shift_width;
+ src_word <<= shift_width;
+
+ /* get the current bits from the target bit string */
+ dest = hmc_bits + (ce_info->lsb / 8);
+
+ memcpy(&dest_word, dest, sizeof(dest_word));
+
+ dest_word &= ~(cpu_to_le16(mask)); /* get the bits not changing */
+ dest_word |= cpu_to_le16(src_word); /* add in the new bits */
+
+ /* put it all back */
+ memcpy(dest, &dest_word, sizeof(dest_word));
+}
+
+/**
+ * i40e_write_dword - replace HMC context dword
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_dword(u8 *hmc_bits,
+ struct i40e_context_ele *ce_info,
+ u8 *src)
+{
+ u32 src_dword, mask;
+ u8 *from, *dest;
+ u16 shift_width;
+ __le32 dest_dword;
+
+ /* copy from the next struct field */
+ from = src + ce_info->offset;
+
+ /* prepare the bits and mask */
+ shift_width = ce_info->lsb % 8;
+
+ /* if the field width is exactly 32 on an x86 machine, then the shift
+ * operation will not work because the SHL instructions count is masked
+ * to 5 bits so the shift will do nothing
+ */
+ if (ce_info->width < 32)
+ mask = ((u32)1 << ce_info->width) - 1;
+ else
+ mask = 0xFFFFFFFF;
+
+ /* don't swizzle the bits until after the mask because the mask bits
+ * will be in a different bit position on big endian machines
+ */
+ src_dword = *(u32 *)from;
+ src_dword &= mask;
+
+ /* shift to correct alignment */
+ mask <<= shift_width;
+ src_dword <<= shift_width;
+
+ /* get the current bits from the target bit string */
+ dest = hmc_bits + (ce_info->lsb / 8);
+
+ memcpy(&dest_dword, dest, sizeof(dest_dword));
+
+ dest_dword &= ~(cpu_to_le32(mask)); /* get the bits not changing */
+ dest_dword |= cpu_to_le32(src_dword); /* add in the new bits */
+
+ /* put it all back */
+ memcpy(dest, &dest_dword, sizeof(dest_dword));
+}
+
+/**
+ * i40e_write_qword - replace HMC context qword
+ * @hmc_bits: pointer to the HMC memory
+ * @ce_info: a description of the struct to be read from
+ * @src: the struct to be read from
+ **/
+static void i40e_write_qword(u8 *hmc_bits,
+ struct i40e_context_ele *ce_info,
+ u8 *src)
+{
+ u64 src_qword, mask;
+ u8 *from, *dest;
+ u16 shift_width;
+ __le64 dest_qword;
+
+ /* copy from the next struct field */
+ from = src + ce_info->offset;
+
+ /* prepare the bits and mask */
+ shift_width = ce_info->lsb % 8;
+
+ /* if the field width is exactly 64 on an x86 machine, then the shift
+ * operation will not work because the SHL instructions count is masked
+ * to 6 bits so the shift will do nothing
+ */
+ if (ce_info->width < 64)
+ mask = ((u64)1 << ce_info->width) - 1;
+ else
+ mask = 0xFFFFFFFFFFFFFFFF;
+
+ /* don't swizzle the bits until after the mask because the mask bits
+ * will be in a different bit position on big endian machines
+ */
+ src_qword = *(u64 *)from;
+ src_qword &= mask;
+
+ /* shift to correct alignment */
+ mask <<= shift_width;
+ src_qword <<= shift_width;
+
+ /* get the current bits from the target bit string */
+ dest = hmc_bits + (ce_info->lsb / 8);
+
+ memcpy(&dest_qword, dest, sizeof(dest_qword));
+
+ dest_qword &= ~(cpu_to_le64(mask)); /* get the bits not changing */
+ dest_qword |= cpu_to_le64(src_qword); /* add in the new bits */
+
+ /* put it all back */
+ memcpy(dest, &dest_qword, sizeof(dest_qword));
+}
+
+/**
* i40e_clear_hmc_context - zero out the HMC context bits
* @hw: the hardware struct
* @context_bytes: pointer to the context bit array (DMA memory)
@@ -772,71 +958,28 @@ static i40e_status i40e_set_hmc_context(u8 *context_bytes,
struct i40e_context_ele *ce_info,
u8 *dest)
{
- u16 shift_width;
- u64 bitfield;
- u8 hi_byte;
- u8 hi_mask;
- u64 t_bits;
- u64 mask;
- u8 *p;
int f;
for (f = 0; ce_info[f].width != 0; f++) {
- /* clear out the field */
- bitfield = 0;
- /* copy from the next struct field */
- p = dest + ce_info[f].offset;
+ /* we have to deal with each element of the HMC using the
+ * correct size so that we are correct regardless of the
+ * endianness of the machine
+ */
switch (ce_info[f].size_of) {
case 1:
- bitfield = *p;
+ i40e_write_byte(context_bytes, &ce_info[f], dest);
break;
case 2:
- bitfield = cpu_to_le16(*(u16 *)p);
+ i40e_write_word(context_bytes, &ce_info[f], dest);
break;
case 4:
- bitfield = cpu_to_le32(*(u32 *)p);
+ i40e_write_dword(context_bytes, &ce_info[f], dest);
break;
case 8:
- bitfield = cpu_to_le64(*(u64 *)p);
+ i40e_write_qword(context_bytes, &ce_info[f], dest);
break;
}
-
- /* prepare the bits and mask */
- shift_width = ce_info[f].lsb % 8;
- mask = ((u64)1 << ce_info[f].width) - 1;
-
- /* save upper bytes for special case */
- hi_mask = (u8)((mask >> 56) & 0xff);
- hi_byte = (u8)((bitfield >> 56) & 0xff);
-
- /* shift to correct alignment */
- mask <<= shift_width;
- bitfield <<= shift_width;
-
- /* get the current bits from the target bit string */
- p = context_bytes + (ce_info[f].lsb / 8);
- memcpy(&t_bits, p, sizeof(u64));
-
- t_bits &= ~mask; /* get the bits not changing */
- t_bits |= bitfield; /* add in the new bits */
-
- /* put it all back */
- memcpy(p, &t_bits, sizeof(u64));
-
- /* deal with the special case if needed
- * example: 62 bit field that starts in bit 5 of first byte
- * will overlap 3 bits into byte 9
- */
- if ((shift_width + ce_info[f].width) > 64) {
- u8 byte;
-
- hi_mask >>= (8 - shift_width);
- hi_byte >>= (8 - shift_width);
- byte = p[8] & ~hi_mask; /* get the bits not changing */
- byte |= hi_byte; /* add in the new bits */
- p[8] = byte; /* put it back */
- }
}
return 0;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
index eb65fe23c4a7..e74128db5be5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
@@ -32,16 +32,22 @@ struct i40e_hw;
/* HMC element context information */
-/* Rx queue context data */
+/* Rx queue context data
+ *
+ * The sizes of the variables may be larger than needed due to crossing byte
+ * boundaries. If we do not have the width of the variable set to the correct
+ * size then we could end up shifting bits off the top of the variable when the
+ * variable is at the top of a byte and crosses over into the next byte.
+ */
struct i40e_hmc_obj_rxq {
u16 head;
- u8 cpuid;
+ u16 cpuid; /* bigger than needed, see above for reason */
u64 base;
u16 qlen;
#define I40E_RXQ_CTX_DBUFF_SHIFT 7
- u8 dbuff;
+ u16 dbuff; /* bigger than needed, see above for reason */
#define I40E_RXQ_CTX_HBUFF_SHIFT 6
- u8 hbuff;
+ u16 hbuff; /* bigger than needed, see above for reason */
u8 dtype;
u8 dsize;
u8 crcstrip;
@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
u8 hsplit_0;
u8 hsplit_1;
u8 showiv;
- u16 rxmax;
+ u32 rxmax; /* bigger than needed, see above for reason */
u8 tphrdesc_ena;
u8 tphwdesc_ena;
u8 tphdata_ena;
u8 tphhead_ena;
- u8 lrxqthresh;
+ u16 lrxqthresh; /* bigger than needed, see above for reason */
u8 prefena; /* NOTE: normally must be set to 1 at init */
};
-/* Tx queue context data */
+/* Tx queue context data
+*
+* The sizes of the variables may be larger than needed due to crossing byte
+* boundaries. If we do not have the width of the variable set to the correct
+* size then we could end up shifting bits off the top of the variable when the
+* variable is at the top of a byte and crosses over into the next byte.
+*/
struct i40e_hmc_obj_txq {
u16 head;
u8 new_context;
@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
u8 fd_ena;
u8 alt_vlan_ena;
u16 thead_wb;
- u16 cpuid;
+ u8 cpuid;
u8 head_wb_ena;
u16 qlen;
u8 tphrdesc_ena;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 275ca9a1719e..eddec6ba095b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -39,7 +39,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 0
#define DRV_VERSION_MINOR 4
-#define DRV_VERSION_BUILD 10
+#define DRV_VERSION_BUILD 21
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@@ -65,7 +65,7 @@ static int i40e_veb_get_bw_info(struct i40e_veb *veb);
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(i40e_pci_tbl) = {
+static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_XL710), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_QEMU), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_A), 0},
@@ -269,7 +269,11 @@ static void i40e_service_event_schedule(struct i40e_pf *pf)
* device is munged, not just the one netdev port, so go for the full
* reset.
**/
+#ifdef I40E_FCOE
+void i40e_tx_timeout(struct net_device *netdev)
+#else
static void i40e_tx_timeout(struct net_device *netdev)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -278,7 +282,7 @@ static void i40e_tx_timeout(struct net_device *netdev)
pf->tx_timeout_count++;
if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20)))
- pf->tx_timeout_recovery_level = 0;
+ pf->tx_timeout_recovery_level = 1;
pf->tx_timeout_last_recovery = jiffies;
netdev_info(netdev, "tx_timeout recovery level %d\n",
pf->tx_timeout_recovery_level);
@@ -304,8 +308,8 @@ static void i40e_tx_timeout(struct net_device *netdev)
break;
default:
netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
- set_bit(__I40E_DOWN, &vsi->state);
- i40e_down(vsi);
+ set_bit(__I40E_DOWN_REQUESTED, &pf->state);
+ set_bit(__I40E_DOWN_REQUESTED, &vsi->state);
break;
}
i40e_service_event_schedule(pf);
@@ -349,9 +353,15 @@ struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi)
* Returns the address of the device statistics structure.
* The statistics are actually updated from the service task.
**/
+#ifdef I40E_FCOE
+struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
+ struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
+#else
static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
struct net_device *netdev,
struct rtnl_link_stats64 *stats)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_ring *tx_ring, *rx_ring;
@@ -444,9 +454,21 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi)
**/
void i40e_pf_reset_stats(struct i40e_pf *pf)
{
+ int i;
+
memset(&pf->stats, 0, sizeof(pf->stats));
memset(&pf->stats_offsets, 0, sizeof(pf->stats_offsets));
pf->stat_offsets_loaded = false;
+
+ for (i = 0; i < I40E_MAX_VEB; i++) {
+ if (pf->veb[i]) {
+ memset(&pf->veb[i]->stats, 0,
+ sizeof(pf->veb[i]->stats));
+ memset(&pf->veb[i]->stats_offsets, 0,
+ sizeof(pf->veb[i]->stats_offsets));
+ pf->veb[i]->stat_offsets_loaded = false;
+ }
+ }
}
/**
@@ -624,6 +646,55 @@ static void i40e_update_veb_stats(struct i40e_veb *veb)
veb->stat_offsets_loaded = true;
}
+#ifdef I40E_FCOE
+/**
+ * i40e_update_fcoe_stats - Update FCoE-specific ethernet statistics counters.
+ * @vsi: the VSI that is capable of doing FCoE
+ **/
+static void i40e_update_fcoe_stats(struct i40e_vsi *vsi)
+{
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ struct i40e_fcoe_stats *ofs;
+ struct i40e_fcoe_stats *fs; /* device's eth stats */
+ int idx;
+
+ if (vsi->type != I40E_VSI_FCOE)
+ return;
+
+ idx = (pf->pf_seid - I40E_BASE_PF_SEID) + I40E_FCOE_PF_STAT_OFFSET;
+ fs = &vsi->fcoe_stats;
+ ofs = &vsi->fcoe_stats_offsets;
+
+ i40e_stat_update32(hw, I40E_GL_FCOEPRC(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->rx_fcoe_packets, &fs->rx_fcoe_packets);
+ i40e_stat_update48(hw, I40E_GL_FCOEDWRCH(idx), I40E_GL_FCOEDWRCL(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->rx_fcoe_dwords, &fs->rx_fcoe_dwords);
+ i40e_stat_update32(hw, I40E_GL_FCOERPDC(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->rx_fcoe_dropped, &fs->rx_fcoe_dropped);
+ i40e_stat_update32(hw, I40E_GL_FCOEPTC(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->tx_fcoe_packets, &fs->tx_fcoe_packets);
+ i40e_stat_update48(hw, I40E_GL_FCOEDWTCH(idx), I40E_GL_FCOEDWTCL(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->tx_fcoe_dwords, &fs->tx_fcoe_dwords);
+ i40e_stat_update32(hw, I40E_GL_FCOECRC(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->fcoe_bad_fccrc, &fs->fcoe_bad_fccrc);
+ i40e_stat_update32(hw, I40E_GL_FCOELAST(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->fcoe_last_error, &fs->fcoe_last_error);
+ i40e_stat_update32(hw, I40E_GL_FCOEDDPC(idx),
+ vsi->fcoe_stat_offsets_loaded,
+ &ofs->fcoe_ddp_count, &fs->fcoe_ddp_count);
+
+ vsi->fcoe_stat_offsets_loaded = true;
+}
+
+#endif
/**
* i40e_update_link_xoff_rx - Update XOFF received in link flow control mode
* @pf: the corresponding PF
@@ -1052,6 +1123,9 @@ void i40e_update_stats(struct i40e_vsi *vsi)
i40e_update_pf_stats(pf);
i40e_update_vsi_stats(vsi);
+#ifdef I40E_FCOE
+ i40e_update_fcoe_stats(vsi);
+#endif
}
/**
@@ -1303,7 +1377,11 @@ void i40e_del_filter(struct i40e_vsi *vsi,
*
* Returns 0 on success, negative on failure
**/
+#ifdef I40E_FCOE
+int i40e_set_mac(struct net_device *netdev, void *p)
+#else
static int i40e_set_mac(struct net_device *netdev, void *p)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -1315,9 +1393,6 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
netdev_info(netdev, "set mac address=%pM\n", addr->sa_data);
- if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
- return 0;
-
if (test_bit(__I40E_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return -EADDRNOTAVAIL;
@@ -1325,7 +1400,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
if (vsi->type == I40E_VSI_MAIN) {
i40e_status ret;
ret = i40e_aq_mac_address_write(&vsi->back->hw,
- I40E_AQC_WRITE_TYPE_LAA_ONLY,
+ I40E_AQC_WRITE_TYPE_LAA_WOL,
addr->sa_data, NULL);
if (ret) {
netdev_info(netdev,
@@ -1333,22 +1408,27 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
ret);
return -EADDRNOTAVAIL;
}
-
- ether_addr_copy(vsi->back->hw.mac.addr, addr->sa_data);
}
- /* In order to be sure to not drop any packets, add the new address
- * then delete the old one.
- */
- f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false);
- if (!f)
- return -ENOMEM;
+ f = i40e_find_mac(vsi, addr->sa_data, false, true);
+ if (!f) {
+ /* In order to be sure to not drop any packets, add the
+ * new address first then delete the old one.
+ */
+ f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY,
+ false, false);
+ if (!f)
+ return -ENOMEM;
- i40e_sync_vsi_filters(vsi);
- i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false);
- i40e_sync_vsi_filters(vsi);
+ i40e_sync_vsi_filters(vsi);
+ i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
+ false, false);
+ i40e_sync_vsi_filters(vsi);
+ }
- ether_addr_copy(netdev->dev_addr, addr->sa_data);
+ f->is_laa = true;
+ if (!ether_addr_equal(netdev->dev_addr, addr->sa_data))
+ ether_addr_copy(netdev->dev_addr, addr->sa_data);
return 0;
}
@@ -1362,10 +1442,17 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
*
* Setup VSI queue mapping for enabled traffic classes.
**/
+#ifdef I40E_FCOE
+void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
+ struct i40e_vsi_context *ctxt,
+ u8 enabled_tc,
+ bool is_add)
+#else
static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
struct i40e_vsi_context *ctxt,
u8 enabled_tc,
bool is_add)
+#endif
{
struct i40e_pf *pf = vsi->back;
u16 sections = 0;
@@ -1411,6 +1498,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
case I40E_VSI_MAIN:
qcount = min_t(int, pf->rss_size, num_tc_qps);
break;
+#ifdef I40E_FCOE
+ case I40E_VSI_FCOE:
+ qcount = num_tc_qps;
+ break;
+#endif
case I40E_VSI_FDIR:
case I40E_VSI_SRIOV:
case I40E_VSI_VMDQ2:
@@ -1477,7 +1569,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
* i40e_set_rx_mode - NDO callback to set the netdev filters
* @netdev: network interface device structure
**/
+#ifdef I40E_FCOE
+void i40e_set_rx_mode(struct net_device *netdev)
+#else
static void i40e_set_rx_mode(struct net_device *netdev)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_mac_filter *f, *ftmp;
@@ -2055,8 +2151,13 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
*
* net_device_ops implementation for adding vlan ids
**/
+#ifdef I40E_FCOE
+int i40e_vlan_rx_add_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid)
+#else
static int i40e_vlan_rx_add_vid(struct net_device *netdev,
__always_unused __be16 proto, u16 vid)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -2089,8 +2190,13 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
*
* net_device_ops implementation for removing vlan ids
**/
+#ifdef I40E_FCOE
+int i40e_vlan_rx_kill_vid(struct net_device *netdev,
+ __always_unused __be16 proto, u16 vid)
+#else
static int i40e_vlan_rx_kill_vid(struct net_device *netdev,
__always_unused __be16 proto, u16 vid)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -2222,6 +2328,9 @@ static int i40e_vsi_setup_rx_resources(struct i40e_vsi *vsi)
for (i = 0; i < vsi->num_queue_pairs && !err; i++)
err = i40e_setup_rx_descriptors(vsi->rx_rings[i]);
+#ifdef I40E_FCOE
+ i40e_fcoe_setup_ddp_resources(vsi);
+#endif
return err;
}
@@ -2241,6 +2350,9 @@ static void i40e_vsi_free_rx_resources(struct i40e_vsi *vsi)
for (i = 0; i < vsi->num_queue_pairs; i++)
if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
i40e_free_rx_resources(vsi->rx_rings[i]);
+#ifdef I40E_FCOE
+ i40e_fcoe_free_ddp_resources(vsi);
+#endif
}
/**
@@ -2282,6 +2394,9 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
tx_ctx.qlen = ring->count;
tx_ctx.fd_ena = !!(vsi->back->flags & (I40E_FLAG_FD_SB_ENABLED |
I40E_FLAG_FD_ATR_ENABLED));
+#ifdef I40E_FCOE
+ tx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
+#endif
tx_ctx.timesync_ena = !!(vsi->back->flags & I40E_FLAG_PTP);
/* FDIR VSI tx ring can still use RS bit and writebacks */
if (vsi->type != I40E_VSI_FDIR)
@@ -2387,10 +2502,6 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
rx_ctx.rxmax = min_t(u16, vsi->max_frame,
(chain_len * ring->rx_buf_len));
- rx_ctx.tphrdesc_ena = 1;
- rx_ctx.tphwdesc_ena = 1;
- rx_ctx.tphdata_ena = 1;
- rx_ctx.tphhead_ena = 1;
if (hw->revision_id == 0)
rx_ctx.lrxqthresh = 0;
else
@@ -2398,6 +2509,9 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
rx_ctx.crcstrip = 1;
rx_ctx.l2tsel = 1;
rx_ctx.showiv = 1;
+#ifdef I40E_FCOE
+ rx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
+#endif
/* set the prefena field to 1 because the manual says to */
rx_ctx.prefena = 1;
@@ -2482,6 +2596,17 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi)
break;
}
+#ifdef I40E_FCOE
+ /* setup rx buffer for FCoE */
+ if ((vsi->type == I40E_VSI_FCOE) &&
+ (vsi->back->flags & I40E_FLAG_FCOE_ENABLED)) {
+ vsi->rx_hdr_len = 0;
+ vsi->rx_buf_len = I40E_RXBUFFER_3072;
+ vsi->max_frame = I40E_RXBUFFER_3072;
+ vsi->dtype = I40E_RX_DTYPE_NO_SPLIT;
+ }
+
+#endif /* I40E_FCOE */
/* round up for the chip's needs */
vsi->rx_hdr_len = ALIGN(vsi->rx_hdr_len,
(1 << I40E_RXQ_CTX_HBUFF_SHIFT));
@@ -2756,6 +2881,22 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector)
}
/**
+ * i40e_irq_dynamic_disable - Disable default interrupt generation settings
+ * @vsi: pointer to a vsi
+ * @vector: enable a particular Hw Interrupt vector
+ **/
+void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector)
+{
+ struct i40e_pf *pf = vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+ u32 val;
+
+ val = I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
+ wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val);
+ i40e_flush(hw);
+}
+
+/**
* i40e_msix_clean_rings - MSIX mode Interrupt Handler
* @irq: interrupt number
* @data: pointer to a q_vector
@@ -3057,16 +3198,33 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget)
/* clear next_to_watch to prevent false hangs */
tx_buf->next_to_watch = NULL;
+ tx_desc->buffer_addr = 0;
+ tx_desc->cmd_type_offset_bsz = 0;
+ /* move past filter desc */
+ tx_buf++;
+ tx_desc++;
+ i++;
+ if (unlikely(!i)) {
+ i -= tx_ring->count;
+ tx_buf = tx_ring->tx_bi;
+ tx_desc = I40E_TX_DESC(tx_ring, 0);
+ }
/* unmap skb header data */
dma_unmap_single(tx_ring->dev,
dma_unmap_addr(tx_buf, dma),
dma_unmap_len(tx_buf, len),
DMA_TO_DEVICE);
+ if (tx_buf->tx_flags & I40E_TX_FLAGS_FD_SB)
+ kfree(tx_buf->raw_buf);
+ tx_buf->raw_buf = NULL;
+ tx_buf->tx_flags = 0;
+ tx_buf->next_to_watch = NULL;
dma_unmap_len_set(tx_buf, len, 0);
+ tx_desc->buffer_addr = 0;
+ tx_desc->cmd_type_offset_bsz = 0;
-
- /* move to the next desc and buffer to clean */
+ /* move us past the eop_desc for start of next FD desc */
tx_buf++;
tx_desc++;
i++;
@@ -3151,8 +3309,12 @@ static void i40e_vsi_map_rings_to_vectors(struct i40e_vsi *vsi)
/* If we don't have enough vectors for a 1-to-1 mapping, we'll have to
* group them so there are multiple queues per vector.
+ * It is also important to go through all the vectors available to be
+ * sure that if we don't use all the vectors, that the remaining vectors
+ * are cleared. This is especially important when decreasing the
+ * number of queues in use.
*/
- for (; v_start < q_vectors && qp_remaining; v_start++) {
+ for (; v_start < q_vectors; v_start++) {
struct i40e_q_vector *q_vector = vsi->q_vectors[v_start];
num_ringpairs = DIV_ROUND_UP(qp_remaining, q_vectors - v_start);
@@ -3205,7 +3367,11 @@ static int i40e_vsi_request_irq(struct i40e_vsi *vsi, char *basename)
* This is used by netconsole to send skbs without having to re-enable
* interrupts. It's not called while the normal interrupt routine is executing.
**/
+#ifdef I40E_FCOE
+void i40e_netpoll(struct net_device *netdev)
+#else
static void i40e_netpoll(struct net_device *netdev)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -3228,6 +3394,35 @@ static void i40e_netpoll(struct net_device *netdev)
#endif
/**
+ * i40e_pf_txq_wait - Wait for a PF's Tx queue to be enabled or disabled
+ * @pf: the PF being configured
+ * @pf_q: the PF queue
+ * @enable: enable or disable state of the queue
+ *
+ * This routine will wait for the given Tx queue of the PF to reach the
+ * enabled or disabled state.
+ * Returns -ETIMEDOUT in case of failing to reach the requested state after
+ * multiple retries; else will return 0 in case of success.
+ **/
+static int i40e_pf_txq_wait(struct i40e_pf *pf, int pf_q, bool enable)
+{
+ int i;
+ u32 tx_reg;
+
+ for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) {
+ tx_reg = rd32(&pf->hw, I40E_QTX_ENA(pf_q));
+ if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
+ break;
+
+ udelay(10);
+ }
+ if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/**
* i40e_vsi_control_tx - Start or stop a VSI's rings
* @vsi: the VSI being configured
* @enable: start or stop the rings
@@ -3236,7 +3431,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- int i, j, pf_q;
+ int i, j, pf_q, ret = 0;
u32 tx_reg;
pf_q = vsi->base_queue;
@@ -3269,22 +3464,46 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
wr32(hw, I40E_QTX_ENA(pf_q), tx_reg);
/* wait for the change to finish */
- for (j = 0; j < 10; j++) {
- tx_reg = rd32(hw, I40E_QTX_ENA(pf_q));
- if (enable == !!(tx_reg & I40E_QTX_ENA_QENA_STAT_MASK))
- break;
-
- udelay(10);
- }
- if (j >= 10) {
- dev_info(&pf->pdev->dev, "Tx ring %d %sable timeout\n",
- pf_q, (enable ? "en" : "dis"));
- return -ETIMEDOUT;
+ ret = i40e_pf_txq_wait(pf, pf_q, enable);
+ if (ret) {
+ dev_info(&pf->pdev->dev,
+ "%s: VSI seid %d Tx ring %d %sable timeout\n",
+ __func__, vsi->seid, pf_q,
+ (enable ? "en" : "dis"));
+ break;
}
}
if (hw->revision_id == 0)
mdelay(50);
+ return ret;
+}
+
+/**
+ * i40e_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled
+ * @pf: the PF being configured
+ * @pf_q: the PF queue
+ * @enable: enable or disable state of the queue
+ *
+ * This routine will wait for the given Rx queue of the PF to reach the
+ * enabled or disabled state.
+ * Returns -ETIMEDOUT in case of failing to reach the requested state after
+ * multiple retries; else will return 0 in case of success.
+ **/
+static int i40e_pf_rxq_wait(struct i40e_pf *pf, int pf_q, bool enable)
+{
+ int i;
+ u32 rx_reg;
+
+ for (i = 0; i < I40E_QUEUE_WAIT_RETRY_LIMIT; i++) {
+ rx_reg = rd32(&pf->hw, I40E_QRX_ENA(pf_q));
+ if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
+ break;
+
+ udelay(10);
+ }
+ if (i >= I40E_QUEUE_WAIT_RETRY_LIMIT)
+ return -ETIMEDOUT;
return 0;
}
@@ -3298,7 +3517,7 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
- int i, j, pf_q;
+ int i, j, pf_q, ret = 0;
u32 rx_reg;
pf_q = vsi->base_queue;
@@ -3323,22 +3542,17 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
wr32(hw, I40E_QRX_ENA(pf_q), rx_reg);
/* wait for the change to finish */
- for (j = 0; j < 10; j++) {
- rx_reg = rd32(hw, I40E_QRX_ENA(pf_q));
-
- if (enable == !!(rx_reg & I40E_QRX_ENA_QENA_STAT_MASK))
- break;
-
- udelay(10);
- }
- if (j >= 10) {
- dev_info(&pf->pdev->dev, "Rx ring %d %sable timeout\n",
- pf_q, (enable ? "en" : "dis"));
- return -ETIMEDOUT;
+ ret = i40e_pf_rxq_wait(pf, pf_q, enable);
+ if (ret) {
+ dev_info(&pf->pdev->dev,
+ "%s: VSI seid %d Rx ring %d %sable timeout\n",
+ __func__, vsi->seid, pf_q,
+ (enable ? "en" : "dis"));
+ break;
}
}
- return 0;
+ return ret;
}
/**
@@ -4107,12 +4321,20 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
continue;
/* - Enable all TCs for the LAN VSI
+#ifdef I40E_FCOE
+ * - For FCoE VSI only enable the TC configured
+ * as per the APP TLV
+#endif
* - For all others keep them at TC0 for now
*/
if (v == pf->lan_vsi)
tc_map = i40e_pf_get_tc_map(pf);
else
tc_map = i40e_pf_get_default_tc(pf);
+#ifdef I40E_FCOE
+ if (pf->vsi[v]->type == I40E_VSI_FCOE)
+ tc_map = i40e_get_fcoe_tc_map(pf);
+#endif /* #ifdef I40E_FCOE */
ret = i40e_vsi_config_tc(pf->vsi[v], tc_map);
if (ret) {
@@ -4193,13 +4415,13 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
switch (vsi->back->hw.phy.link_info.link_speed) {
case I40E_LINK_SPEED_40GB:
- strncpy(speed, "40 Gbps", SPEED_SIZE);
+ strlcpy(speed, "40 Gbps", SPEED_SIZE);
break;
case I40E_LINK_SPEED_10GB:
- strncpy(speed, "10 Gbps", SPEED_SIZE);
+ strlcpy(speed, "10 Gbps", SPEED_SIZE);
break;
case I40E_LINK_SPEED_1GB:
- strncpy(speed, "1000 Mbps", SPEED_SIZE);
+ strlcpy(speed, "1000 Mbps", SPEED_SIZE);
break;
default:
break;
@@ -4207,16 +4429,16 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
switch (vsi->back->hw.fc.current_mode) {
case I40E_FC_FULL:
- strncpy(fc, "RX/TX", FC_SIZE);
+ strlcpy(fc, "RX/TX", FC_SIZE);
break;
case I40E_FC_TX_PAUSE:
- strncpy(fc, "TX", FC_SIZE);
+ strlcpy(fc, "TX", FC_SIZE);
break;
case I40E_FC_RX_PAUSE:
- strncpy(fc, "RX", FC_SIZE);
+ strlcpy(fc, "RX", FC_SIZE);
break;
default:
- strncpy(fc, "None", FC_SIZE);
+ strlcpy(fc, "None", FC_SIZE);
break;
}
@@ -4231,8 +4453,12 @@ static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
static int i40e_up_complete(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
+ u8 set_fc_aq_fail = 0;
int err;
+ /* force flow control off */
+ i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
+
if (pf->flags & I40E_FLAG_MSIX_ENABLED)
i40e_vsi_configure_msix(vsi);
else
@@ -4335,7 +4561,11 @@ void i40e_down(struct i40e_vsi *vsi)
* @netdev: net device to configure
* @tc: number of traffic classes to enable
**/
+#ifdef I40E_FCOE
+int i40e_setup_tc(struct net_device *netdev, u8 tc)
+#else
static int i40e_setup_tc(struct net_device *netdev, u8 tc)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -4400,7 +4630,11 @@ exit:
*
* Returns 0 on success, negative value on failure
**/
+#ifdef I40E_FCOE
+int i40e_open(struct net_device *netdev)
+#else
static int i40e_open(struct net_device *netdev)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -4536,7 +4770,11 @@ static void i40e_fdir_filter_exit(struct i40e_pf *pf)
*
* Returns 0, this is not allowed to fail
**/
+#ifdef I40E_FCOE
+int i40e_close(struct net_device *netdev)
+#else
static int i40e_close(struct net_device *netdev)
+#endif
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
@@ -4640,6 +4878,23 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
/* no further action needed, so return now */
return;
+ } else if (reset_flags & (1 << __I40E_DOWN_REQUESTED)) {
+ int v;
+
+ /* Find the VSI(s) that needs to be brought down */
+ dev_info(&pf->pdev->dev, "VSI down requested\n");
+ for (v = 0; v < pf->num_alloc_vsi; v++) {
+ struct i40e_vsi *vsi = pf->vsi[v];
+ if (vsi != NULL &&
+ test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) {
+ set_bit(__I40E_DOWN, &vsi->state);
+ i40e_down(vsi);
+ clear_bit(__I40E_DOWN_REQUESTED, &vsi->state);
+ }
+ }
+
+ /* no further action needed, so return now */
+ return;
} else {
dev_info(&pf->pdev->dev,
"bad reset request 0x%08x\n", reset_flags);
@@ -4845,7 +5100,20 @@ static void i40e_service_event_complete(struct i40e_pf *pf)
}
/**
- * i40e_get_current_fd_count - Get the count of FD filters programmed in the HW
+ * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
+ * @pf: board private structure
+ **/
+int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
+{
+ int val, fcnt_prog;
+
+ val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
+ fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK);
+ return fcnt_prog;
+}
+
+/**
+ * i40e_get_current_fd_count - Get the count of total FD filters programmed
* @pf: board private structure
**/
int i40e_get_current_fd_count(struct i40e_pf *pf)
@@ -4857,7 +5125,6 @@ int i40e_get_current_fd_count(struct i40e_pf *pf)
I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
return fcnt_prog;
}
-
/**
* i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
* @pf: board private structure
@@ -4872,8 +5139,8 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
(pf->flags & I40E_FLAG_FD_SB_ENABLED))
return;
- fcnt_prog = i40e_get_current_fd_count(pf);
- fcnt_avail = i40e_get_fd_cnt_all(pf);
+ fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
+ fcnt_avail = pf->fdir_pf_filter_count;
if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) {
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
(pf->auto_disable_flags & I40E_FLAG_FD_SB_ENABLED)) {
@@ -4922,6 +5189,9 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
switch (vsi->type) {
case I40E_VSI_MAIN:
+#ifdef I40E_FCOE
+ case I40E_VSI_FCOE:
+#endif
if (!vsi->netdev || !vsi->netdev_registered)
break;
@@ -5110,6 +5380,10 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
reset_flags |= (1 << __I40E_GLOBAL_RESET_REQUESTED);
clear_bit(__I40E_GLOBAL_RESET_REQUESTED, &pf->state);
}
+ if (test_bit(__I40E_DOWN_REQUESTED, &pf->state)) {
+ reset_flags |= (1 << __I40E_DOWN_REQUESTED);
+ clear_bit(__I40E_DOWN_REQUESTED, &pf->state);
+ }
/* If there's a recovery already waiting, it takes
* precedence before starting a new reset sequence.
@@ -5164,7 +5438,7 @@ static void i40e_handle_link_event(struct i40e_pf *pf,
* then see if the status changed while processing the
* initial event.
*/
- i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+ i40e_update_link_info(&pf->hw, true);
i40e_link_event(pf);
}
@@ -5182,9 +5456,6 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
u32 oldval;
u32 val;
- if (!test_bit(__I40E_ADMINQ_EVENT_PENDING, &pf->state))
- return;
-
/* check for error indications */
val = rd32(&pf->hw, pf->hw.aq.arq.len);
oldval = val;
@@ -5228,10 +5499,9 @@ static void i40e_clean_adminq_subtask(struct i40e_pf *pf)
do {
event.msg_size = I40E_MAX_AQ_BUF_SIZE; /* reinit each time */
ret = i40e_clean_arq_element(hw, &event, &pending);
- if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
- dev_info(&pf->pdev->dev, "No ARQ event found\n");
+ if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK)
break;
- } else if (ret) {
+ else if (ret) {
dev_info(&pf->pdev->dev, "ARQ event error %d\n", ret);
break;
}
@@ -5463,6 +5733,20 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)
struct i40e_vsi *vsi;
int i;
+ /* quick workaround for an NVM issue that leaves a critical register
+ * uninitialized
+ */
+ if (!rd32(&pf->hw, I40E_GLQF_HKEY(0))) {
+ static const u32 hkey[] = {
+ 0xe640d33f, 0xcdfe98ab, 0x73fa7161, 0x0d7a7d36,
+ 0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb,
+ 0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21,
+ 0x95b3a76d};
+
+ for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++)
+ wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]);
+ }
+
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
return;
@@ -5512,7 +5796,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
*
* Close up the VFs and other things in prep for pf Reset.
**/
-static int i40e_prep_for_reset(struct i40e_pf *pf)
+static void i40e_prep_for_reset(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
i40e_status ret = 0;
@@ -5520,7 +5804,7 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
- return 0;
+ return;
dev_dbg(&pf->pdev->dev, "Tearing down internal switch for reset\n");
@@ -5537,13 +5821,10 @@ static int i40e_prep_for_reset(struct i40e_pf *pf)
/* call shutdown HMC */
if (hw->hmc.hmc_obj) {
ret = i40e_shutdown_lan_hmc(hw);
- if (ret) {
+ if (ret)
dev_warn(&pf->pdev->dev,
"shutdown_lan_hmc failed: %d\n", ret);
- clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
- }
}
- return ret;
}
/**
@@ -5558,7 +5839,7 @@ static void i40e_send_version(struct i40e_pf *pf)
dv.minor_version = DRV_VERSION_MINOR;
dv.build_version = DRV_VERSION_BUILD;
dv.subbuild_version = 0;
- strncpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
+ strlcpy(dv.driver_string, DRV_VERSION, sizeof(dv.driver_string));
i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
}
@@ -5629,7 +5910,12 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
goto end_core_reset;
}
#endif /* CONFIG_I40E_DCB */
+#ifdef I40E_FCOE
+ ret = i40e_init_pf_fcoe(pf);
+ if (ret)
+ dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", ret);
+#endif
/* do basic switch setup */
ret = i40e_setup_pf_switch(pf, reinit);
if (ret)
@@ -5679,7 +5965,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
}
if (pf->vsi[pf->lan_vsi]->uplink_seid == pf->mac_seid) {
- dev_info(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
+ dev_dbg(&pf->pdev->dev, "attempting to rebuild PF VSI\n");
/* no VEB, so rebuild only the Main VSI */
ret = i40e_add_vsi(pf->vsi[pf->lan_vsi]);
if (ret) {
@@ -5717,11 +6003,8 @@ end_core_reset:
**/
static void i40e_handle_reset_warning(struct i40e_pf *pf)
{
- i40e_status ret;
-
- ret = i40e_prep_for_reset(pf);
- if (!ret)
- i40e_reset_and_rebuild(pf, false);
+ i40e_prep_for_reset(pf);
+ i40e_reset_and_rebuild(pf, false);
}
/**
@@ -5734,6 +6017,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
{
struct i40e_hw *hw = &pf->hw;
bool mdd_detected = false;
+ bool pf_mdd_detected = false;
struct i40e_vf *vf;
u32 reg;
int i;
@@ -5744,26 +6028,28 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
/* find what triggered the MDD event */
reg = rd32(hw, I40E_GL_MDET_TX);
if (reg & I40E_GL_MDET_TX_VALID_MASK) {
- u8 func = (reg & I40E_GL_MDET_TX_FUNCTION_MASK)
- >> I40E_GL_MDET_TX_FUNCTION_SHIFT;
- u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT)
- >> I40E_GL_MDET_TX_EVENT_SHIFT;
- u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK)
- >> I40E_GL_MDET_TX_QUEUE_SHIFT;
+ u8 pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >>
+ I40E_GL_MDET_TX_PF_NUM_SHIFT;
+ u8 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
+ I40E_GL_MDET_TX_VF_NUM_SHIFT;
+ u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) >>
+ I40E_GL_MDET_TX_EVENT_SHIFT;
+ u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
+ I40E_GL_MDET_TX_QUEUE_SHIFT;
dev_info(&pf->pdev->dev,
- "Malicious Driver Detection event 0x%02x on TX queue %d of function 0x%02x\n",
- event, queue, func);
+ "Malicious Driver Detection event 0x%02x on TX queue %d pf number 0x%02x vf number 0x%02x\n",
+ event, queue, pf_num, vf_num);
wr32(hw, I40E_GL_MDET_TX, 0xffffffff);
mdd_detected = true;
}
reg = rd32(hw, I40E_GL_MDET_RX);
if (reg & I40E_GL_MDET_RX_VALID_MASK) {
- u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK)
- >> I40E_GL_MDET_RX_FUNCTION_SHIFT;
- u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT)
- >> I40E_GL_MDET_RX_EVENT_SHIFT;
- u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK)
- >> I40E_GL_MDET_RX_QUEUE_SHIFT;
+ u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >>
+ I40E_GL_MDET_RX_FUNCTION_SHIFT;
+ u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT) >>
+ I40E_GL_MDET_RX_EVENT_SHIFT;
+ u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
+ I40E_GL_MDET_RX_QUEUE_SHIFT;
dev_info(&pf->pdev->dev,
"Malicious Driver Detection event 0x%02x on RX queue %d of function 0x%02x\n",
event, queue, func);
@@ -5771,6 +6057,30 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
mdd_detected = true;
}
+ if (mdd_detected) {
+ reg = rd32(hw, I40E_PF_MDET_TX);
+ if (reg & I40E_PF_MDET_TX_VALID_MASK) {
+ wr32(hw, I40E_PF_MDET_TX, 0xFFFF);
+ dev_info(&pf->pdev->dev,
+ "MDD TX event is for this function 0x%08x, requesting PF reset.\n",
+ reg);
+ pf_mdd_detected = true;
+ }
+ reg = rd32(hw, I40E_PF_MDET_RX);
+ if (reg & I40E_PF_MDET_RX_VALID_MASK) {
+ wr32(hw, I40E_PF_MDET_RX, 0xFFFF);
+ dev_info(&pf->pdev->dev,
+ "MDD RX event is for this function 0x%08x, requesting PF reset.\n",
+ reg);
+ pf_mdd_detected = true;
+ }
+ /* Queue belongs to the PF, initiate a reset */
+ if (pf_mdd_detected) {
+ set_bit(__I40E_PF_RESET_REQUESTED, &pf->state);
+ i40e_service_event_schedule(pf);
+ }
+ }
+
/* see if one of the VFs needs its hand slapped */
for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) {
vf = &(pf->vf[i]);
@@ -5860,6 +6170,12 @@ static void i40e_service_task(struct work_struct *work)
service_task);
unsigned long start_time = jiffies;
+ /* don't bother with service tasks if a reset is in progress */
+ if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
+ i40e_service_event_complete(pf);
+ return;
+ }
+
i40e_reset_subtask(pf);
i40e_handle_mdd_event(pf);
i40e_vc_process_vflr_event(pf);
@@ -5938,6 +6254,15 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
I40E_REQ_DESCRIPTOR_MULTIPLE);
break;
+#ifdef I40E_FCOE
+ case I40E_VSI_FCOE:
+ vsi->alloc_queue_pairs = pf->num_fcoe_qps;
+ vsi->num_desc = ALIGN(I40E_DEFAULT_NUM_DESCRIPTORS,
+ I40E_REQ_DESCRIPTOR_MULTIPLE);
+ vsi->num_q_vectors = pf->num_fcoe_msix;
+ break;
+
+#endif /* I40E_FCOE */
default:
WARN_ON(1);
return -ENODATA;
@@ -5968,7 +6293,7 @@ static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors)
if (alloc_qvectors) {
/* allocate memory for q_vector pointers */
- size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
+ size = sizeof(struct i40e_q_vector *) * vsi->num_q_vectors;
vsi->q_vectors = kzalloc(size, GFP_KERNEL);
if (!vsi->q_vectors) {
ret = -ENOMEM;
@@ -6249,6 +6574,9 @@ static int i40e_init_msix(struct i40e_pf *pf)
* is governed by number of cpus in the system.
* - assumes symmetric Tx/Rx pairing
* - The number of VMDq pairs
+#ifdef I40E_FCOE
+ * - The number of FCOE qps.
+#endif
* Once we count this up, try the request.
*
* If we can't get what we want, we'll simplify to nearly nothing
@@ -6261,6 +6589,13 @@ static int i40e_init_msix(struct i40e_pf *pf)
if (pf->flags & I40E_FLAG_FD_SB_ENABLED)
v_budget++;
+#ifdef I40E_FCOE
+ if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+ pf->num_fcoe_msix = pf->num_fcoe_qps;
+ v_budget += pf->num_fcoe_msix;
+ }
+
+#endif
/* Scale down if necessary, and the rings will share vectors */
v_budget = min_t(int, v_budget, hw->func_caps.num_msix_vectors);
@@ -6279,6 +6614,10 @@ static int i40e_init_msix(struct i40e_pf *pf)
* of these features based on the policy and at the end disable
* the features that did not get any vectors.
*/
+#ifdef I40E_FCOE
+ pf->num_fcoe_qps = 0;
+ pf->num_fcoe_msix = 0;
+#endif
pf->num_vmdq_msix = 0;
}
@@ -6309,9 +6648,24 @@ static int i40e_init_msix(struct i40e_pf *pf)
pf->num_lan_msix = 1;
break;
case 3:
+#ifdef I40E_FCOE
+ /* give one vector to FCoE */
+ if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+ pf->num_lan_msix = 1;
+ pf->num_fcoe_msix = 1;
+ }
+#else
pf->num_lan_msix = 2;
+#endif
break;
default:
+#ifdef I40E_FCOE
+ /* give one vector to FCoE */
+ if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+ pf->num_fcoe_msix = 1;
+ vec--;
+ }
+#endif
pf->num_lan_msix = min_t(int, (vec / 2),
pf->num_lan_qps);
pf->num_vmdq_vsis = min_t(int, (vec - pf->num_lan_msix),
@@ -6325,6 +6679,13 @@ static int i40e_init_msix(struct i40e_pf *pf)
dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n");
pf->flags &= ~I40E_FLAG_VMDQ_ENABLED;
}
+#ifdef I40E_FCOE
+
+ if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) {
+ dev_info(&pf->pdev->dev, "FCOE disabled, not enough MSI-X vectors\n");
+ pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+ }
+#endif
return err;
}
@@ -6408,6 +6769,9 @@ static void i40e_init_interrupt_scheme(struct i40e_pf *pf)
err = i40e_init_msix(pf);
if (err) {
pf->flags &= ~(I40E_FLAG_MSIX_ENABLED |
+#ifdef I40E_FCOE
+ I40E_FLAG_FCOE_ENABLED |
+#endif
I40E_FLAG_RSS_ENABLED |
I40E_FLAG_DCB_CAPABLE |
I40E_FLAG_SRIOV_ENABLED |
@@ -6492,6 +6856,7 @@ static int i40e_config_rss(struct i40e_pf *pf)
u32 lut = 0;
int i, j;
u64 hena;
+ u32 reg_val;
/* Fill out hash function seed */
for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
@@ -6504,8 +6869,19 @@ static int i40e_config_rss(struct i40e_pf *pf)
wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
+ /* Check capability and Set table size and register per hw expectation*/
+ reg_val = rd32(hw, I40E_PFQF_CTL_0);
+ if (hw->func_caps.rss_table_size == 512) {
+ reg_val |= I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+ pf->rss_table_size = 512;
+ } else {
+ pf->rss_table_size = 128;
+ reg_val &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_512;
+ }
+ wr32(hw, I40E_PFQF_CTL_0, reg_val);
+
/* Populate the LUT with max no. of queues in round robin fashion */
- for (i = 0, j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) {
+ for (i = 0, j = 0; i < pf->rss_table_size; i++, j++) {
/* The assumption is that lan qp count will be the highest
* qp count for any PF VSI that needs RSS.
@@ -6592,13 +6968,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
* maximum might end up larger than the available queues
*/
pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width;
+ pf->rss_size = 1;
pf->rss_size_max = min_t(int, pf->rss_size_max,
pf->hw.func_caps.num_tx_qp);
if (pf->hw.func_caps.rss) {
pf->flags |= I40E_FLAG_RSS_ENABLED;
pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus());
- } else {
- pf->rss_size = 1;
}
/* MFP mode enabled */
@@ -6634,6 +7009,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
pf->num_vmdq_qps = I40E_DEFAULT_QUEUES_PER_VMDQ;
}
+#ifdef I40E_FCOE
+ err = i40e_init_pf_fcoe(pf);
+ if (err)
+ dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", err);
+
+#endif /* I40E_FCOE */
#ifdef CONFIG_PCI_IOV
if (pf->hw.func_caps.num_vfs) {
pf->num_vf_qps = I40E_DEFAULT_QUEUES_PER_VF;
@@ -6670,6 +7051,8 @@ static int i40e_sw_init(struct i40e_pf *pf)
pf->irq_pile->num_entries = pf->hw.func_caps.num_msix_vectors;
pf->irq_pile->search_hint = 0;
+ pf->tx_timeout_recovery_level = 1;
+
mutex_init(&pf->switch_mutex);
sw_init_done:
@@ -6702,9 +7085,11 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
i40e_fdir_filter_exit(pf);
}
pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
- /* if ATR was disabled it can be re-enabled. */
- if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
- pf->flags |= I40E_FLAG_FD_ATR_ENABLED;
+ pf->auto_disable_flags &= ~I40E_FLAG_FD_SB_ENABLED;
+ /* if ATR was auto disabled it can be re-enabled. */
+ if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+ (pf->auto_disable_flags & I40E_FLAG_FD_ATR_ENABLED))
+ pf->auto_disable_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
}
return need_reset;
}
@@ -6833,6 +7218,22 @@ static void i40e_del_vxlan_port(struct net_device *netdev,
}
#endif
+static int i40e_get_phys_port_id(struct net_device *netdev,
+ struct netdev_phys_port_id *ppid)
+{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+ struct i40e_pf *pf = np->vsi->back;
+ struct i40e_hw *hw = &pf->hw;
+
+ if (!(pf->flags & I40E_FLAG_PORT_ID_VALID))
+ return -EOPNOTSUPP;
+
+ ppid->id_len = min_t(int, sizeof(hw->mac.port_addr), sizeof(ppid->id));
+ memcpy(ppid->id, hw->mac.port_addr, ppid->id_len);
+
+ return 0;
+}
+
#ifdef HAVE_FDB_OPS
#ifdef USE_CONST_DEV_UC_CHAR
static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
@@ -6910,13 +7311,14 @@ static int i40e_ndo_fdb_del(struct ndmsg *ndm,
static int i40e_ndo_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
+ struct net_device *filter_dev,
int idx)
{
struct i40e_netdev_priv *np = netdev_priv(dev);
struct i40e_pf *pf = np->vsi->back;
if (pf->flags & I40E_FLAG_SRIOV_ENABLED)
- idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+ idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx);
return idx;
}
@@ -6940,6 +7342,10 @@ static const struct net_device_ops i40e_netdev_ops = {
.ndo_poll_controller = i40e_netpoll,
#endif
.ndo_setup_tc = i40e_setup_tc,
+#ifdef I40E_FCOE
+ .ndo_fcoe_enable = i40e_fcoe_enable,
+ .ndo_fcoe_disable = i40e_fcoe_disable,
+#endif
.ndo_set_features = i40e_set_features,
.ndo_set_vf_mac = i40e_ndo_set_vf_mac,
.ndo_set_vf_vlan = i40e_ndo_set_vf_port_vlan,
@@ -6951,6 +7357,7 @@ static const struct net_device_ops i40e_netdev_ops = {
.ndo_add_vxlan_port = i40e_add_vxlan_port,
.ndo_del_vxlan_port = i40e_del_vxlan_port,
#endif
+ .ndo_get_phys_port_id = i40e_get_phys_port_id,
#ifdef HAVE_FDB_OPS
.ndo_fdb_add = i40e_ndo_fdb_add,
#ifndef USE_DEFAULT_FDB_DEL_DUMP
@@ -7047,6 +7454,9 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
netdev->netdev_ops = &i40e_netdev_ops;
netdev->watchdog_timeo = 5 * HZ;
i40e_set_ethtool_ops(netdev);
+#ifdef I40E_FCOE
+ i40e_fcoe_config_netdev(netdev, vsi);
+#endif
return 0;
}
@@ -7166,7 +7576,6 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
* should be set to zero by default.
*/
ctxt.info.switch_id = 0;
- ctxt.info.switch_id |= cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB);
ctxt.info.switch_id |= cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB);
/* Setup the VSI tx/rx queue map for TC0 only for now */
@@ -7200,6 +7609,16 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, true);
break;
+#ifdef I40E_FCOE
+ case I40E_VSI_FCOE:
+ ret = i40e_fcoe_vsi_init(vsi, &ctxt);
+ if (ret) {
+ dev_info(&pf->pdev->dev, "failed to initialize FCoE VSI\n");
+ return ret;
+ }
+ break;
+
+#endif /* I40E_FCOE */
default:
return -ENODEV;
}
@@ -7223,6 +7642,12 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
f->changed = true;
f_count++;
+
+ if (f->is_laa && vsi->type == I40E_VSI_MAIN) {
+ i40e_aq_mac_address_write(&vsi->back->hw,
+ I40E_AQC_WRITE_TYPE_LAA_WOL,
+ f->macaddr, NULL);
+ }
}
if (f_count) {
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -7552,6 +7977,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
/* setup the netdev if needed */
case I40E_VSI_MAIN:
case I40E_VSI_VMDQ2:
+ case I40E_VSI_FCOE:
ret = i40e_config_netdev(vsi);
if (ret)
goto err_netdev;
@@ -8090,7 +8516,6 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig)
**/
static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
{
- u32 rxfc = 0, txfc = 0, rxfc_reg;
int ret;
/* find out what's out there already */
@@ -8150,68 +8575,13 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
i40e_config_rss(pf);
/* fill in link information and enable LSE reporting */
- i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
+ i40e_update_link_info(&pf->hw, true);
i40e_link_event(pf);
/* Initialize user-specific link properties */
pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
I40E_AQ_AN_COMPLETED) ? true : false);
- /* requested_mode is set in probe or by ethtool */
- if (!pf->fc_autoneg_status)
- goto no_autoneg;
-
- if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) &&
- (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX))
- pf->hw.fc.current_mode = I40E_FC_FULL;
- else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
- pf->hw.fc.current_mode = I40E_FC_TX_PAUSE;
- else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
- pf->hw.fc.current_mode = I40E_FC_RX_PAUSE;
- else
- pf->hw.fc.current_mode = I40E_FC_NONE;
- /* sync the flow control settings with the auto-neg values */
- switch (pf->hw.fc.current_mode) {
- case I40E_FC_FULL:
- txfc = 1;
- rxfc = 1;
- break;
- case I40E_FC_TX_PAUSE:
- txfc = 1;
- rxfc = 0;
- break;
- case I40E_FC_RX_PAUSE:
- txfc = 0;
- rxfc = 1;
- break;
- case I40E_FC_NONE:
- case I40E_FC_DEFAULT:
- txfc = 0;
- rxfc = 0;
- break;
- case I40E_FC_PFC:
- /* TBD */
- break;
- /* no default case, we have to handle all possibilities here */
- }
-
- wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
-
- rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
- ~I40E_PRTDCB_MFLCN_RFCE_MASK;
- rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
-
- wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg);
-
- goto fc_complete;
-
-no_autoneg:
- /* disable L2 flow control, user can turn it on if they wish */
- wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0);
- wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
- ~I40E_PRTDCB_MFLCN_RFCE_MASK);
-
-fc_complete:
i40e_ptp_init(pf);
return ret;
@@ -8226,6 +8596,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
int queues_left;
pf->num_lan_qps = 0;
+#ifdef I40E_FCOE
+ pf->num_fcoe_qps = 0;
+#endif
/* Find the max queues to be put into basic use. We'll always be
* using TC0, whether or not DCB is running, and TC0 will get the
@@ -8241,6 +8614,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
/* make sure all the fancies are disabled */
pf->flags &= ~(I40E_FLAG_RSS_ENABLED |
+#ifdef I40E_FCOE
+ I40E_FLAG_FCOE_ENABLED |
+#endif
I40E_FLAG_FD_SB_ENABLED |
I40E_FLAG_FD_ATR_ENABLED |
I40E_FLAG_DCB_CAPABLE |
@@ -8255,6 +8631,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
queues_left -= pf->num_lan_qps;
pf->flags &= ~(I40E_FLAG_RSS_ENABLED |
+#ifdef I40E_FCOE
+ I40E_FLAG_FCOE_ENABLED |
+#endif
I40E_FLAG_FD_SB_ENABLED |
I40E_FLAG_FD_ATR_ENABLED |
I40E_FLAG_DCB_ENABLED |
@@ -8270,6 +8649,22 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
queues_left -= pf->num_lan_qps;
}
+#ifdef I40E_FCOE
+ if (pf->flags & I40E_FLAG_FCOE_ENABLED) {
+ if (I40E_DEFAULT_FCOE <= queues_left) {
+ pf->num_fcoe_qps = I40E_DEFAULT_FCOE;
+ } else if (I40E_MINIMUM_FCOE <= queues_left) {
+ pf->num_fcoe_qps = I40E_MINIMUM_FCOE;
+ } else {
+ pf->num_fcoe_qps = 0;
+ pf->flags &= ~I40E_FLAG_FCOE_ENABLED;
+ dev_info(&pf->pdev->dev, "not enough queues for FCoE. FCoE feature will be disabled\n");
+ }
+
+ queues_left -= pf->num_fcoe_qps;
+ }
+
+#endif
if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
if (queues_left > 1) {
queues_left -= 1; /* save 1 queue for FD */
@@ -8294,6 +8689,9 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf)
}
pf->queues_left = queues_left;
+#ifdef I40E_FCOE
+ dev_info(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps);
+#endif
}
/**
@@ -8360,6 +8758,10 @@ static void i40e_print_features(struct i40e_pf *pf)
buf += sprintf(buf, "DCB ");
if (pf->flags & I40E_FLAG_PTP)
buf += sprintf(buf, "PTP ");
+#ifdef I40E_FCOE
+ if (pf->flags & I40E_FLAG_FCOE_ENABLED)
+ buf += sprintf(buf, "FCOE ");
+#endif
BUG_ON(buf > (string + INFO_STRING_LEN));
dev_info(&pf->pdev->dev, "%s\n", string);
@@ -8460,6 +8862,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Reset here to make sure all is clean and to define PF 'n' */
+ i40e_clear_hw(hw);
err = i40e_pf_reset(hw);
if (err) {
dev_info(&pdev->dev, "Initial pf_reset failed: %d\n", err);
@@ -8489,12 +8892,20 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
if (err) {
dev_info(&pdev->dev,
- "init_adminq failed: %d expecting API %02x.%02x\n",
- err,
- I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
+ "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n");
goto err_pf_reset;
}
+ if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
+ hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR)
+ dev_info(&pdev->dev,
+ "The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n");
+ else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
+ hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1))
+ dev_info(&pdev->dev,
+ "The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n");
+
+
i40e_verify_eeprom(pf);
/* Rev 0 hardware was never productized */
@@ -8535,6 +8946,21 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
dev_info(&pdev->dev, "MAC address: %pM\n", hw->mac.addr);
ether_addr_copy(hw->mac.perm_addr, hw->mac.addr);
+ i40e_get_port_mac_addr(hw, hw->mac.port_addr);
+ if (is_valid_ether_addr(hw->mac.port_addr))
+ pf->flags |= I40E_FLAG_PORT_ID_VALID;
+#ifdef I40E_FCOE
+ err = i40e_get_san_mac_addr(hw, hw->mac.san_addr);
+ if (err)
+ dev_info(&pdev->dev,
+ "(non-fatal) SAN MAC retrieval failed: %d\n", err);
+ if (!is_valid_ether_addr(hw->mac.san_addr)) {
+ dev_warn(&pdev->dev, "invalid SAN MAC address %pM, falling back to LAN MAC\n",
+ hw->mac.san_addr);
+ ether_addr_copy(hw->mac.san_addr, hw->mac.addr);
+ }
+ dev_info(&pf->pdev->dev, "SAN MAC: %pM\n", hw->mac.san_addr);
+#endif /* I40E_FCOE */
pci_set_drvdata(pdev, pf);
pci_save_state(pdev);
@@ -8651,6 +9077,11 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mod_timer(&pf->service_timer,
round_jiffies(jiffies + pf->service_timer_period));
+#ifdef I40E_FCOE
+ /* create FCoE interface */
+ i40e_fcoe_vsi_setup(pf);
+
+#endif
/* Get the negotiated link width and speed from PCI config space */
pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status);
@@ -8722,7 +9153,6 @@ static void i40e_remove(struct pci_dev *pdev)
{
struct i40e_pf *pf = pci_get_drvdata(pdev);
i40e_status ret_code;
- u32 reg;
int i;
i40e_dbg_pf_exit(pf);
@@ -8800,11 +9230,6 @@ static void i40e_remove(struct pci_dev *pdev)
kfree(pf->irq_pile);
kfree(pf->vsi);
- /* force a PF reset to clean anything leftover */
- reg = rd32(&pf->hw, I40E_PFGEN_CTRL);
- wr32(&pf->hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK));
- i40e_flush(&pf->hw);
-
iounmap(pf->hw.hw_addr);
kfree(pf);
pci_release_selected_regions(pdev,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
index 81299189a47d..25c4f9a3011f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -241,6 +241,46 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
}
/**
+ * i40e_write_nvm_aq - Writes Shadow RAM.
+ * @hw: pointer to the HW structure.
+ * @module_pointer: module pointer location in words from the NVM beginning
+ * @offset: offset in words from module start
+ * @words: number of words to write
+ * @data: buffer with words to write to the Shadow RAM
+ * @last_command: tells the AdminQ that this is the last command
+ *
+ * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ **/
+static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
+ u32 offset, u16 words, void *data,
+ bool last_command)
+{
+ i40e_status ret_code = I40E_ERR_NVM;
+
+ /* Here we are checking the SR limit only for the flat memory model.
+ * We cannot do it for the module-based model, as we did not acquire
+ * the NVM resource yet (we cannot get the module pointer value).
+ * Firmware will check the module-based model.
+ */
+ if ((offset + words) > hw->nvm.sr_size)
+ hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n");
+ else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
+ /* We can write only up to 4KB (one sector), in one AQ write */
+ hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n");
+ else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
+ != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
+ /* A single write cannot spread over two sectors */
+ hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n");
+ else
+ ret_code = i40e_aq_update_nvm(hw, module_pointer,
+ 2 * offset, /*bytes*/
+ 2 * words, /*bytes*/
+ data, last_command, NULL);
+
+ return ret_code;
+}
+
+/**
* i40e_calc_nvm_checksum - Calculates and returns the checksum
* @hw: pointer to hardware structure
* @checksum: pointer to the checksum
@@ -310,6 +350,27 @@ i40e_calc_nvm_checksum_exit:
}
/**
+ * i40e_update_nvm_checksum - Updates the NVM checksum
+ * @hw: pointer to hardware structure
+ *
+ * NVM ownership must be acquired before calling this function and released
+ * on ARQ completion event reception by caller.
+ * This function will commit SR to NVM.
+ **/
+i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
+{
+ i40e_status ret_code = 0;
+ u16 checksum;
+
+ ret_code = i40e_calc_nvm_checksum(hw, &checksum);
+ if (!ret_code)
+ ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
+ 1, &checksum, true);
+
+ return ret_code;
+}
+
+/**
* i40e_validate_nvm_checksum - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum: calculated checksum
@@ -324,13 +385,9 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 checksum_sr = 0;
u16 checksum_local = 0;
- ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
- if (ret_code)
- goto i40e_validate_nvm_checksum_exit;
-
ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
if (ret_code)
- goto i40e_validate_nvm_checksum_free;
+ goto i40e_validate_nvm_checksum_exit;
/* Do not use i40e_read_nvm_word() because we do not want to take
* the synchronization semaphores twice here.
@@ -347,9 +404,456 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
if (checksum)
*checksum = checksum_local;
-i40e_validate_nvm_checksum_free:
- i40e_release_nvm(hw);
-
i40e_validate_nvm_checksum_exit:
return ret_code;
}
+
+static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno);
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ int *errno);
+static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ int *errno);
+static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno);
+static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno);
+static inline u8 i40e_nvmupd_get_module(u32 val)
+{
+ return (u8)(val & I40E_NVM_MOD_PNT_MASK);
+}
+static inline u8 i40e_nvmupd_get_transaction(u32 val)
+{
+ return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
+}
+
+/**
+ * i40e_nvmupd_command - Process an NVM update command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * Dispatches command depending on what update state is current
+ **/
+i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status;
+
+ /* assume success */
+ *errno = 0;
+
+ switch (hw->nvmupd_state) {
+ case I40E_NVMUPD_STATE_INIT:
+ status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
+ break;
+
+ case I40E_NVMUPD_STATE_READING:
+ status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
+ break;
+
+ case I40E_NVMUPD_STATE_WRITING:
+ status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
+ break;
+
+ default:
+ /* invalid state, should never happen */
+ status = I40E_NOT_SUPPORTED;
+ *errno = -ESRCH;
+ break;
+ }
+ return status;
+}
+
+/**
+ * i40e_nvmupd_state_init - Handle NVM update state Init
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * Process legitimate commands of the Init state and conditionally set next
+ * state. Reject all other commands.
+ **/
+static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status = 0;
+ enum i40e_nvmupd_cmd upd_cmd;
+
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+ switch (upd_cmd) {
+ case I40E_NVMUPD_READ_SA:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ i40e_release_nvm(hw);
+ }
+ break;
+
+ case I40E_NVMUPD_READ_SNT:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
+ }
+ break;
+
+ case I40E_NVMUPD_WRITE_ERA:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
+ if (status)
+ i40e_release_nvm(hw);
+ else
+ hw->aq.nvm_release_on_done = true;
+ }
+ break;
+
+ case I40E_NVMUPD_WRITE_SA:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ if (status)
+ i40e_release_nvm(hw);
+ else
+ hw->aq.nvm_release_on_done = true;
+ }
+ break;
+
+ case I40E_NVMUPD_WRITE_SNT:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+ }
+ break;
+
+ case I40E_NVMUPD_CSUM_SA:
+ status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
+ if (status) {
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+ } else {
+ status = i40e_update_nvm_checksum(hw);
+ if (status) {
+ *errno = hw->aq.asq_last_status ?
+ i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+ -EIO;
+ i40e_release_nvm(hw);
+ } else {
+ hw->aq.nvm_release_on_done = true;
+ }
+ }
+ break;
+
+ default:
+ status = I40E_ERR_NVM;
+ *errno = -ESRCH;
+ break;
+ }
+ return status;
+}
+
+/**
+ * i40e_nvmupd_state_reading - Handle NVM update state Reading
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * NVM ownership is already held. Process legitimate commands and set any
+ * change in state; reject all other commands.
+ **/
+static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status;
+ enum i40e_nvmupd_cmd upd_cmd;
+
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+ switch (upd_cmd) {
+ case I40E_NVMUPD_READ_SA:
+ case I40E_NVMUPD_READ_CON:
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ break;
+
+ case I40E_NVMUPD_READ_LCB:
+ status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
+ i40e_release_nvm(hw);
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ break;
+
+ default:
+ status = I40E_NOT_SUPPORTED;
+ *errno = -ESRCH;
+ break;
+ }
+ return status;
+}
+
+/**
+ * i40e_nvmupd_state_writing - Handle NVM update state Writing
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * NVM ownership is already held. Process legitimate commands and set any
+ * change in state; reject all other commands
+ **/
+static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status;
+ enum i40e_nvmupd_cmd upd_cmd;
+
+ upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
+
+ switch (upd_cmd) {
+ case I40E_NVMUPD_WRITE_CON:
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ break;
+
+ case I40E_NVMUPD_WRITE_LCB:
+ status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
+ if (!status) {
+ hw->aq.nvm_release_on_done = true;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ }
+ break;
+
+ case I40E_NVMUPD_CSUM_CON:
+ status = i40e_update_nvm_checksum(hw);
+ if (status)
+ *errno = hw->aq.asq_last_status ?
+ i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+ -EIO;
+ break;
+
+ case I40E_NVMUPD_CSUM_LCB:
+ status = i40e_update_nvm_checksum(hw);
+ if (status) {
+ *errno = hw->aq.asq_last_status ?
+ i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
+ -EIO;
+ } else {
+ hw->aq.nvm_release_on_done = true;
+ hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+ }
+ break;
+
+ default:
+ status = I40E_NOT_SUPPORTED;
+ *errno = -ESRCH;
+ break;
+ }
+ return status;
+}
+
+/**
+ * i40e_nvmupd_validate_command - Validate given command
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @errno: pointer to return error code
+ *
+ * Return one of the valid command types or I40E_NVMUPD_INVALID
+ **/
+static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ int *errno)
+{
+ enum i40e_nvmupd_cmd upd_cmd;
+ u8 transaction, module;
+
+ /* anything that doesn't match a recognized case is an error */
+ upd_cmd = I40E_NVMUPD_INVALID;
+
+ transaction = i40e_nvmupd_get_transaction(cmd->config);
+ module = i40e_nvmupd_get_module(cmd->config);
+
+ /* limits on data size */
+ if ((cmd->data_size < 1) ||
+ (cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
+ hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n",
+ cmd->data_size);
+ *errno = -EFAULT;
+ return I40E_NVMUPD_INVALID;
+ }
+
+ switch (cmd->command) {
+ case I40E_NVM_READ:
+ switch (transaction) {
+ case I40E_NVM_CON:
+ upd_cmd = I40E_NVMUPD_READ_CON;
+ break;
+ case I40E_NVM_SNT:
+ upd_cmd = I40E_NVMUPD_READ_SNT;
+ break;
+ case I40E_NVM_LCB:
+ upd_cmd = I40E_NVMUPD_READ_LCB;
+ break;
+ case I40E_NVM_SA:
+ upd_cmd = I40E_NVMUPD_READ_SA;
+ break;
+ }
+ break;
+
+ case I40E_NVM_WRITE:
+ switch (transaction) {
+ case I40E_NVM_CON:
+ upd_cmd = I40E_NVMUPD_WRITE_CON;
+ break;
+ case I40E_NVM_SNT:
+ upd_cmd = I40E_NVMUPD_WRITE_SNT;
+ break;
+ case I40E_NVM_LCB:
+ upd_cmd = I40E_NVMUPD_WRITE_LCB;
+ break;
+ case I40E_NVM_SA:
+ upd_cmd = I40E_NVMUPD_WRITE_SA;
+ break;
+ case I40E_NVM_ERA:
+ upd_cmd = I40E_NVMUPD_WRITE_ERA;
+ break;
+ case I40E_NVM_CSUM:
+ upd_cmd = I40E_NVMUPD_CSUM_CON;
+ break;
+ case (I40E_NVM_CSUM|I40E_NVM_SA):
+ upd_cmd = I40E_NVMUPD_CSUM_SA;
+ break;
+ case (I40E_NVM_CSUM|I40E_NVM_LCB):
+ upd_cmd = I40E_NVMUPD_CSUM_LCB;
+ break;
+ }
+ break;
+ }
+
+ if (upd_cmd == I40E_NVMUPD_INVALID) {
+ *errno = -EFAULT;
+ hw_dbg(hw,
+ "i40e_nvmupd_validate_command returns %d errno: %d\n",
+ upd_cmd, *errno);
+ }
+ return upd_cmd;
+}
+
+/**
+ * i40e_nvmupd_nvm_read - Read NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status;
+ u8 module, transaction;
+ bool last;
+
+ transaction = i40e_nvmupd_get_transaction(cmd->config);
+ module = i40e_nvmupd_get_module(cmd->config);
+ last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
+ hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
+ module, cmd->offset, cmd->data_size);
+
+ status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+ bytes, last, NULL);
+ hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status);
+ if (status)
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+ return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_erase - Erase an NVM module
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @errno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ int *errno)
+{
+ i40e_status status = 0;
+ u8 module, transaction;
+ bool last;
+
+ transaction = i40e_nvmupd_get_transaction(cmd->config);
+ module = i40e_nvmupd_get_module(cmd->config);
+ last = (transaction & I40E_NVM_LCB);
+ hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
+ module, cmd->offset, cmd->data_size);
+ status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
+ last, NULL);
+ hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status);
+ if (status)
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+ return status;
+}
+
+/**
+ * i40e_nvmupd_nvm_write - Write NVM
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @errno: pointer to return error code
+ *
+ * module, offset, data_size and data are in cmd structure
+ **/
+static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *errno)
+{
+ i40e_status status = 0;
+ u8 module, transaction;
+ bool last;
+
+ transaction = i40e_nvmupd_get_transaction(cmd->config);
+ module = i40e_nvmupd_get_module(cmd->config);
+ last = (transaction & I40E_NVM_LCB);
+ hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
+ module, cmd->offset, cmd->data_size);
+ status = i40e_aq_update_nvm(hw, module, cmd->offset,
+ (u16)cmd->data_size, bytes, last, NULL);
+ hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status);
+ if (status)
+ *errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
+
+ return status;
+}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
index ecd0f0b663c9..045b5c4b98b3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h
@@ -78,4 +78,7 @@ do { \
} while (0)
typedef enum i40e_status_code i40e_status;
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#define I40E_FCOE
+#endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */
#endif /* _I40E_OSDEP_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index a430699c41d5..949a9a01778b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -70,17 +70,31 @@ i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,
u16 *fw_major_version, u16 *fw_minor_version,
u16 *api_major_version, u16 *api_minor_version,
struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
+ u32 reg_addr, u64 reg_val,
+ struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
+ bool qualified_modules, bool report_init,
+ struct i40e_aq_get_phy_abilities_resp *abilities,
+ struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
+ struct i40e_aq_set_phy_config *config,
+ struct i40e_asq_cmd_details *cmd_details);
+enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
+ bool atomic_reset);
i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
- struct i40e_asq_cmd_details *cmd_details);
+ bool enable_link,
+ struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
bool enable_lse, struct i40e_link_status *link,
struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse);
i40e_status i40e_aq_set_local_advt_reg(struct i40e_hw *hw,
u64 advt_reg,
struct i40e_asq_cmd_details *cmd_details);
@@ -139,6 +153,9 @@ i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, void *data,
bool last_command,
struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
+ u32 offset, u16 length, bool last_command,
+ struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
void *buff, u16 buff_size, u16 *data_size,
enum i40e_admin_queue_opc list_type_opc,
@@ -216,12 +233,16 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,
/* i40e_common */
i40e_status i40e_init_shared_code(struct i40e_hw *hw);
i40e_status i40e_pf_reset(struct i40e_hw *hw);
+void i40e_clear_hw(struct i40e_hw *hw);
void i40e_clear_pxe_mode(struct i40e_hw *hw);
bool i40e_get_link_status(struct i40e_hw *hw);
-i40e_status i40e_get_mac_addr(struct i40e_hw *hw,
- u8 *mac_addr);
+i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
+i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
i40e_status i40e_validate_mac_addr(u8 *mac_addr);
void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable);
+#ifdef I40E_FCOE
+i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
+#endif
/* prototype for functions used for NVM access */
i40e_status i40e_init_nvm(struct i40e_hw *hw);
i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
@@ -233,8 +254,12 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u16 *data);
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data);
+i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 *checksum);
+i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
+ struct i40e_nvm_access *cmd,
+ u8 *bytes, int *);
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index 101f439acda6..bb7fe98b3a6c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -25,7 +25,6 @@
******************************************************************************/
#include "i40e.h"
-#include <linux/export.h>
#include <linux/ptp_classify.h>
/* The XL710 timesync is very much like Intel's 82599 design when it comes to
@@ -216,7 +215,7 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
}
/**
- * i40e_ptp_enable - Enable/disable ancillary features of the PHC subsystem
+ * i40e_ptp_feature_enable - Enable/disable ancillary features of the PHC subsystem
* @ptp: The PTP clock structure
* @rq: The requested feature to change
* @on: Enable/disable flag
@@ -224,8 +223,8 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp,
* The XL710 does not support any of the ancillary features of the PHC
* subsystem, so this function may just return.
**/
-static int i40e_ptp_enable(struct ptp_clock_info *ptp,
- struct ptp_clock_request *rq, int on)
+static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
{
return -EOPNOTSUPP;
}
@@ -315,6 +314,7 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
dev_kfree_skb_any(pf->ptp_tx_skb);
pf->ptp_tx_skb = NULL;
+ clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
}
/**
@@ -423,28 +423,23 @@ int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
}
/**
- * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
+ * i40e_ptp_set_timestamp_mode - setup hardware for requested timestamp mode
* @pf: Board private structure
- * @ifreq: ioctl data
+ * @config: hwtstamp settings requested or saved
*
- * Respond to the user filter requests and make the appropriate hardware
- * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
- * logic, so keep track in software of whether to indicate these timestamps
- * or not.
+ * Control hardware registers to enter the specific mode requested by the
+ * user. Also used during reset path to ensure that timestamp settings are
+ * maintained.
*
- * It is permissible to "upgrade" the user request to a broader filter, as long
- * as the user receives the timestamps they care about and the user is notified
- * the filter has been broadened.
+ * Note: modifies config in place, and may update the requested mode to be
+ * more broad if the specific filter is not directly supported.
**/
-int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
+ struct hwtstamp_config *config)
{
struct i40e_hw *hw = &pf->hw;
- struct hwtstamp_config *config = &pf->tstamp_config;
u32 pf_id, tsyntype, regval;
- if (copy_from_user(config, ifr->ifr_data, sizeof(*config)))
- return -EFAULT;
-
/* Reserved for future extensions. */
if (config->flags)
return -EINVAL;
@@ -452,8 +447,12 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
/* Confirm that 1588 is supported on this PF. */
pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
- if (hw->pf_id != pf_id)
- return -EINVAL;
+ if (hw->pf_id != pf_id) {
+ dev_err(&pf->pdev->dev,
+ "PF %d attempted to control timestamp mode on port %d, which is owned by PF %d\n",
+ hw->pf_id, hw->port, pf_id);
+ return -EPERM;
+ }
switch (config->tx_type) {
case HWTSTAMP_TX_OFF:
@@ -535,23 +534,59 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
wr32(hw, I40E_PRTTSYN_CTL1, regval);
}
- return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
+ return 0;
+}
+
+/**
+ * i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
+ * @pf: Board private structure
+ * @ifreq: ioctl data
+ *
+ * Respond to the user filter requests and make the appropriate hardware
+ * changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
+ * logic, so keep track in software of whether to indicate these timestamps
+ * or not.
+ *
+ * It is permissible to "upgrade" the user request to a broader filter, as long
+ * as the user receives the timestamps they care about and the user is notified
+ * the filter has been broadened.
+ **/
+int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
+{
+ struct hwtstamp_config config;
+ int err;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ err = i40e_ptp_set_timestamp_mode(pf, &config);
+ if (err)
+ return err;
+
+ /* save these settings for future reference */
+ pf->tstamp_config = config;
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
-EFAULT : 0;
}
/**
- * i40e_ptp_init - Initialize the 1588 support and register the PHC
+ * i40e_ptp_create_clock - Create PTP clock device for userspace
* @pf: Board private structure
*
- * This function registers the device clock as a PHC. If it is successful, it
- * starts the clock in the hardware.
+ * This function creates a new PTP clock device. It only creates one if we
+ * don't already have one, so it is safe to call. Will return error if it
+ * can't create one, but success if we already have a device. Should be used
+ * by i40e_ptp_init to create clock initially, and prevent global resets from
+ * creating new clock devices.
**/
-void i40e_ptp_init(struct i40e_pf *pf)
+static long i40e_ptp_create_clock(struct i40e_pf *pf)
{
- struct i40e_hw *hw = &pf->hw;
- struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
+ /* no need to create a clock device if we already have one */
+ if (!IS_ERR_OR_NULL(pf->ptp_clock))
+ return 0;
- strncpy(pf->ptp_caps.name, "i40e", sizeof(pf->ptp_caps.name));
+ strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
pf->ptp_caps.owner = THIS_MODULE;
pf->ptp_caps.max_adj = 999999999;
pf->ptp_caps.n_ext_ts = 0;
@@ -560,11 +595,46 @@ void i40e_ptp_init(struct i40e_pf *pf)
pf->ptp_caps.adjtime = i40e_ptp_adjtime;
pf->ptp_caps.gettime = i40e_ptp_gettime;
pf->ptp_caps.settime = i40e_ptp_settime;
- pf->ptp_caps.enable = i40e_ptp_enable;
+ pf->ptp_caps.enable = i40e_ptp_feature_enable;
/* Attempt to register the clock before enabling the hardware. */
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
if (IS_ERR(pf->ptp_clock)) {
+ return PTR_ERR(pf->ptp_clock);
+ }
+
+ /* clear the hwtstamp settings here during clock create, instead of
+ * during regular init, so that we can maintain settings across a
+ * reset or suspend.
+ */
+ pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+ pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+
+ return 0;
+}
+
+/**
+ * i40e_ptp_init - Initialize the 1588 support after device probe or reset
+ * @pf: Board private structure
+ *
+ * This function sets device up for 1588 support. The first time it is run, it
+ * will create a PHC clock device. It does not create a clock device if one
+ * already exists. It also reconfigures the device after a reset.
+ **/
+void i40e_ptp_init(struct i40e_pf *pf)
+{
+ struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
+ struct i40e_hw *hw = &pf->hw;
+ long err;
+
+ /* we have to initialize the lock first, since we can't control
+ * when the user will enter the PHC device entry points
+ */
+ spin_lock_init(&pf->tmreg_lock);
+
+ /* ensure we have a clock device */
+ err = i40e_ptp_create_clock(pf);
+ if (err) {
pf->ptp_clock = NULL;
dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
__func__);
@@ -572,8 +642,6 @@ void i40e_ptp_init(struct i40e_pf *pf)
struct timespec ts;
u32 regval;
- spin_lock_init(&pf->tmreg_lock);
-
dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
netdev->name);
pf->flags |= I40E_FLAG_PTP;
@@ -589,8 +657,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
/* Set the increment value per clock tick. */
i40e_ptp_set_increment(pf);
- /* reset the tstamp_config */
- memset(&pf->tstamp_config, 0, sizeof(pf->tstamp_config));
+ /* reset timestamping mode */
+ i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
/* Set the clock value. */
ts = ktime_to_timespec(ktime_get_real());
@@ -614,6 +682,7 @@ void i40e_ptp_stop(struct i40e_pf *pf)
if (pf->ptp_tx_skb) {
dev_kfree_skb_any(pf->ptp_tx_skb);
pf->ptp_tx_skb = NULL;
+ clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
}
if (pf->ptp_clock) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h
index 947de98500f3..65d3c8bb2d5b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_register.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_register.h
@@ -27,4648 +27,3343 @@
#ifndef _I40E_REGISTER_H_
#define _I40E_REGISTER_H_
-#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
-#define I40E_GL_GP_FUSE_MAX_INDEX 28
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
-#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
-
-#define I40E_PF_ARQBAH 0x00080180
+#define I40E_GL_ARQBAH 0x000801C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_GL_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAH_ARQBAH_SHIFT)
+#define I40E_GL_ARQBAL 0x000800C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_GL_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAL_ARQBAL_SHIFT)
+#define I40E_GL_ARQH 0x000803C0 /* Reset: EMPR */
+#define I40E_GL_ARQH_ARQH_SHIFT 0
+#define I40E_GL_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_GL_ARQH_ARQH_SHIFT)
+#define I40E_GL_ARQT 0x000804C0 /* Reset: EMPR */
+#define I40E_GL_ARQT_ARQT_SHIFT 0
+#define I40E_GL_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_GL_ARQT_ARQT_SHIFT)
+#define I40E_GL_ATQBAH 0x00080140 /* Reset: EMPR */
+#define I40E_GL_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_GL_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAH_ATQBAH_SHIFT)
+#define I40E_GL_ATQBAL 0x00080040 /* Reset: EMPR */
+#define I40E_GL_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_GL_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAL_ATQBAL_SHIFT)
+#define I40E_GL_ATQH 0x00080340 /* Reset: EMPR */
+#define I40E_GL_ATQH_ATQH_SHIFT 0
+#define I40E_GL_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_GL_ATQH_ATQH_SHIFT)
+#define I40E_GL_ATQLEN 0x00080240 /* Reset: EMPR */
+#define I40E_GL_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_GL_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_GL_ATQLEN_ATQLEN_SHIFT)
+#define I40E_GL_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_GL_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQVFE_SHIFT)
+#define I40E_GL_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_GL_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_GL_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_GL_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_GL_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_GL_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_GL_ATQT 0x00080440 /* Reset: EMPR */
+#define I40E_GL_ATQT_ATQT_SHIFT 0
+#define I40E_GL_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_GL_ATQT_ATQT_SHIFT)
+#define I40E_PF_ARQBAH 0x00080180 /* Reset: EMPR */
#define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_PF_ARQBAL 0x00080080
+#define I40E_PF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_PF_ARQBAL 0x00080080 /* Reset: EMPR */
#define I40E_PF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_PF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_PF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_PF_ARQH 0x00080380
+#define I40E_PF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_PF_ARQH 0x00080380 /* Reset: EMPR */
#define I40E_PF_ARQH_ARQH_SHIFT 0
-#define I40E_PF_ARQH_ARQH_MASK (0x3FF << I40E_PF_ARQH_ARQH_SHIFT)
-#define I40E_PF_ARQLEN 0x00080280
+#define I40E_PF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_PF_ARQH_ARQH_SHIFT)
+#define I40E_PF_ARQLEN 0x00080280 /* Reset: EMPR */
#define I40E_PF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_PF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_PF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_PF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ARQLEN_ARQLEN_SHIFT)
#define I40E_PF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_PF_ARQLEN_ARQVFE_MASK (0x1 << I40E_PF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_PF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQVFE_SHIFT)
#define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_PF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_PF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_PF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQOVFL_SHIFT)
#define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_PF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_PF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT)
#define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_PF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_PF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_PF_ARQT 0x00080480
+#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */
#define I40E_PF_ARQT_ARQT_SHIFT 0
-#define I40E_PF_ARQT_ARQT_MASK (0x3FF << I40E_PF_ARQT_ARQT_SHIFT)
-#define I40E_PF_ATQBAH 0x00080100
+#define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT)
+#define I40E_PF_ATQBAH 0x00080100 /* Reset: EMPR */
#define I40E_PF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_PF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_PF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_PF_ATQBAL 0x00080000
+#define I40E_PF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_PF_ATQBAL 0x00080000 /* Reset: EMPR */
#define I40E_PF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_PF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_PF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_PF_ATQH 0x00080300
+#define I40E_PF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_PF_ATQH 0x00080300 /* Reset: EMPR */
#define I40E_PF_ATQH_ATQH_SHIFT 0
-#define I40E_PF_ATQH_ATQH_MASK (0x3FF << I40E_PF_ATQH_ATQH_SHIFT)
-#define I40E_PF_ATQLEN 0x00080200
+#define I40E_PF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_PF_ATQH_ATQH_SHIFT)
+#define I40E_PF_ATQLEN 0x00080200 /* Reset: EMPR */
#define I40E_PF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_PF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_PF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_PF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ATQLEN_ATQLEN_SHIFT)
#define I40E_PF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_PF_ATQLEN_ATQVFE_MASK (0x1 << I40E_PF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_PF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQVFE_SHIFT)
#define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_PF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_PF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_PF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQOVFL_SHIFT)
#define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_PF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_PF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT)
#define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_PF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_PF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_PF_ATQT 0x00080400
+#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */
#define I40E_PF_ATQT_ATQT_SHIFT 0
-#define I40E_PF_ATQT_ATQT_MASK (0x3FF << I40E_PF_ATQT_ATQT_SHIFT)
-#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT)
+#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQBAH_MAX_INDEX 127
#define I40E_VF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQBAL_MAX_INDEX 127
#define I40E_VF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQH_MAX_INDEX 127
#define I40E_VF_ARQH_ARQH_SHIFT 0
-#define I40E_VF_ARQH_ARQH_MASK (0x3FF << I40E_VF_ARQH_ARQH_SHIFT)
-#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH_ARQH_SHIFT)
+#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQLEN_MAX_INDEX 127
#define I40E_VF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN_ARQLEN_SHIFT)
#define I40E_VF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQVFE_SHIFT)
#define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQOVFL_SHIFT)
#define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT)
#define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQT_MAX_INDEX 127
#define I40E_VF_ARQT_ARQT_SHIFT 0
-#define I40E_VF_ARQT_ARQT_MASK (0x3FF << I40E_VF_ARQT_ARQT_SHIFT)
-#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT_ARQT_SHIFT)
+#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQBAH_MAX_INDEX 127
#define I40E_VF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQBAL_MAX_INDEX 127
#define I40E_VF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQH_MAX_INDEX 127
#define I40E_VF_ATQH_ATQH_SHIFT 0
-#define I40E_VF_ATQH_ATQH_MASK (0x3FF << I40E_VF_ATQH_ATQH_SHIFT)
-#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH_ATQH_SHIFT)
+#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQLEN_MAX_INDEX 127
#define I40E_VF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN_ATQLEN_SHIFT)
#define I40E_VF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQVFE_SHIFT)
#define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQOVFL_SHIFT)
#define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT)
#define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQT_MAX_INDEX 127
#define I40E_VF_ATQT_ATQT_SHIFT 0
-#define I40E_VF_ATQT_ATQT_MASK (0x3FF << I40E_VF_ATQT_ATQT_SHIFT)
-#define I40E_PRT_L2TAGSEN 0x001C0B20
+#define I40E_VF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT_ATQT_SHIFT)
+#define I40E_PRT_L2TAGSEN 0x001C0B20 /* Reset: CORER */
#define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0
-#define I40E_PRT_L2TAGSEN_ENABLE_MASK (0xFF << I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
-#define I40E_PFCM_LAN_ERRDATA 0x0010C080
+#define I40E_PRT_L2TAGSEN_ENABLE_MASK I40E_MASK(0xFF, I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA 0x0010C080 /* Reset: PFR */
#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
#define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK (0xFFF << I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_LAN_ERRINFO 0x0010C000
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO 0x0010C000 /* Reset: PFR */
#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_PFCM_LANCTXCTL 0x0010C300
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LANCTXCTL 0x0010C300 /* Reset: CORER */
#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0
-#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK (0xFFF << I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
#define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12
-#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK (0x7 << I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK I40E_MASK(0x7, I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15
-#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK (0x3 << I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
#define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17
-#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK (0x3 << I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
-#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */
+#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
+#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PFCM_LANCTXDATA_MAX_INDEX 3
#define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0
-#define I40E_PFCM_LANCTXDATA_DATA_MASK (0xFFFFFFFF << I40E_PFCM_LANCTXDATA_DATA_SHIFT)
-#define I40E_PFCM_LANCTXSTAT 0x0010C380
+#define I40E_PFCM_LANCTXDATA_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFCM_LANCTXDATA_DATA_SHIFT)
+#define I40E_PFCM_LANCTXSTAT 0x0010C380 /* Reset: CORER */
#define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0
-#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
#define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1
-#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
-#define I40E_PFCM_PE_ERRDATA 0x00138D00
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_PE_ERRINFO 0x00138C80
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127
#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
#define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127
#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
-#define I40E_GLDCB_GENC 0x00083044
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
+#define I40E_GLDCB_GENC 0x00083044 /* Reset: CORER */
#define I40E_GLDCB_GENC_PCIRTT_SHIFT 0
-#define I40E_GLDCB_GENC_PCIRTT_MASK (0xFFFF << I40E_GLDCB_GENC_PCIRTT_SHIFT)
-#define I40E_GLDCB_RUPTI 0x00122618
+#define I40E_GLDCB_GENC_PCIRTT_MASK I40E_MASK(0xFFFF, I40E_GLDCB_GENC_PCIRTT_SHIFT)
+#define I40E_GLDCB_RUPTI 0x00122618 /* Reset: CORER */
#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0
-#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK (0xFFFFFFFF << I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
-#define I40E_PRTDCB_FCCFG 0x001E4640
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
+#define I40E_PRTDCB_FCCFG 0x001E4640 /* Reset: GLOBR */
#define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3
-#define I40E_PRTDCB_FCCFG_TFCE_MASK (0x3 << I40E_PRTDCB_FCCFG_TFCE_SHIFT)
-#define I40E_PRTDCB_FCRTV 0x001E4600
+#define I40E_PRTDCB_FCCFG_TFCE_MASK I40E_MASK(0x3, I40E_PRTDCB_FCCFG_TFCE_SHIFT)
+#define I40E_PRTDCB_FCRTV 0x001E4600 /* Reset: GLOBR */
#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0
-#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK (0xFFFF << I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
-#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
+#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: GLOBR */
#define I40E_PRTDCB_FCTTVN_MAX_INDEX 3
#define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0
-#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
+#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16
-#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
-#define I40E_PRTDCB_GENC 0x00083000
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
+#define I40E_PRTDCB_GENC 0x00083000 /* Reset: CORER */
#define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0
-#define I40E_PRTDCB_GENC_RESERVED_1_MASK (0x3 << I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
+#define I40E_PRTDCB_GENC_RESERVED_1_MASK I40E_MASK(0x3, I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
#define I40E_PRTDCB_GENC_NUMTC_SHIFT 2
-#define I40E_PRTDCB_GENC_NUMTC_MASK (0xF << I40E_PRTDCB_GENC_NUMTC_SHIFT)
+#define I40E_PRTDCB_GENC_NUMTC_MASK I40E_MASK(0xF, I40E_PRTDCB_GENC_NUMTC_SHIFT)
#define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6
-#define I40E_PRTDCB_GENC_FCOEUP_MASK (0x7 << I40E_PRTDCB_GENC_FCOEUP_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_MASK I40E_MASK(0x7, I40E_PRTDCB_GENC_FCOEUP_SHIFT)
#define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9
-#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK (0x1 << I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK I40E_MASK(0x1, I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
#define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16
-#define I40E_PRTDCB_GENC_PFCLDA_MASK (0xFFFF << I40E_PRTDCB_GENC_PFCLDA_SHIFT)
-#define I40E_PRTDCB_GENS 0x00083020
+#define I40E_PRTDCB_GENC_PFCLDA_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_GENC_PFCLDA_SHIFT)
+#define I40E_PRTDCB_GENS 0x00083020 /* Reset: CORER */
#define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0
-#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK (0x7 << I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
-#define I40E_PRTDCB_MFLCN 0x001E2400
+#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK I40E_MASK(0x7, I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
+#define I40E_PRTDCB_MFLCN 0x001E2400 /* Reset: GLOBR */
#define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0
-#define I40E_PRTDCB_MFLCN_PMCF_MASK (0x1 << I40E_PRTDCB_MFLCN_PMCF_SHIFT)
+#define I40E_PRTDCB_MFLCN_PMCF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_PMCF_SHIFT)
#define I40E_PRTDCB_MFLCN_DPF_SHIFT 1
-#define I40E_PRTDCB_MFLCN_DPF_MASK (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT)
+#define I40E_PRTDCB_MFLCN_DPF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_DPF_SHIFT)
#define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2
-#define I40E_PRTDCB_MFLCN_RPFCM_MASK (0x1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCM_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
#define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3
-#define I40E_PRTDCB_MFLCN_RFCE_MASK (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT)
+#define I40E_PRTDCB_MFLCN_RFCE_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RFCE_SHIFT)
#define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4
-#define I40E_PRTDCB_MFLCN_RPFCE_MASK (0xFF << I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
-#define I40E_PRTDCB_RETSC 0x001223E0
+#define I40E_PRTDCB_MFLCN_RPFCE_MASK I40E_MASK(0xFF, I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
+#define I40E_PRTDCB_RETSC 0x001223E0 /* Reset: CORER */
#define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0
-#define I40E_PRTDCB_RETSC_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
#define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1
-#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2
-#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK (0xF << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK I40E_MASK(0xF, I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
#define I40E_PRTDCB_RETSC_LLTC_SHIFT 8
-#define I40E_PRTDCB_RETSC_LLTC_MASK (0xFF << I40E_PRTDCB_RETSC_LLTC_SHIFT)
-#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_RETSC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_RETSC_LLTC_SHIFT)
+#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTDCB_RETSTCC_MAX_INDEX 7
#define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0
-#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK (0x7F << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK I40E_MASK(0x7F, I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30
-#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK (0x1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
#define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31
-#define I40E_PRTDCB_RETSTCC_ETSTC_MASK (0x1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
-#define I40E_PRTDCB_RPPMC 0x001223A0
+#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
+#define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */
#define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0
-#define I40E_PRTDCB_RPPMC_LANRPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
#define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8
-#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16
-#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK (0xFF << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
-#define I40E_PRTDCB_RUP 0x001C0B00
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
+#define I40E_PRTDCB_RUP 0x001C0B00 /* Reset: CORER */
#define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0
-#define I40E_PRTDCB_RUP_NOVLANUP_MASK (0x7 << I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
-#define I40E_PRTDCB_RUP2TC 0x001C09A0
+#define I40E_PRTDCB_RUP_NOVLANUP_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
+#define I40E_PRTDCB_RUP2TC 0x001C09A0 /* Reset: CORER */
#define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0
-#define I40E_PRTDCB_RUP2TC_UP0TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP0TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3
-#define I40E_PRTDCB_RUP2TC_UP1TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP1TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6
-#define I40E_PRTDCB_RUP2TC_UP2TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP2TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9
-#define I40E_PRTDCB_RUP2TC_UP3TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP3TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12
-#define I40E_PRTDCB_RUP2TC_UP4TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP4TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15
-#define I40E_PRTDCB_RUP2TC_UP5TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP5TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18
-#define I40E_PRTDCB_RUP2TC_UP6TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP6TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21
-#define I40E_PRTDCB_RUP2TC_UP7TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
-#define I40E_PRTDCB_TC2PFC 0x001C0980
+#define I40E_PRTDCB_RUP2TC_UP7TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
+#define I40E_PRTDCB_TC2PFC 0x001C0980 /* Reset: CORER */
#define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0
-#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK (0xFF << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
-#define I40E_PRTDCB_TCPMC 0x000A21A0
+#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
+#define I40E_PRTDCB_TCMSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
+#define I40E_PRTDCB_TCMSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TCMSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TCMSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCMSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TCPMC 0x000A21A0 /* Reset: CORER */
#define I40E_PRTDCB_TCPMC_CPM_SHIFT 0
-#define I40E_PRTDCB_TCPMC_CPM_MASK (0x1FFF << I40E_PRTDCB_TCPMC_CPM_SHIFT)
+#define I40E_PRTDCB_TCPMC_CPM_MASK I40E_MASK(0x1FFF, I40E_PRTDCB_TCPMC_CPM_SHIFT)
#define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13
-#define I40E_PRTDCB_TCPMC_LLTC_MASK (0xFF << I40E_PRTDCB_TCPMC_LLTC_SHIFT)
+#define I40E_PRTDCB_TCPMC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TCPMC_LLTC_SHIFT)
#define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTDCB_TCWSTC_MAX_INDEX 7
#define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TCWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TDPMC 0x000A0180
+#define I40E_PRTDCB_TCWSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TDPMC 0x000A0180 /* Reset: CORER */
#define I40E_PRTDCB_TDPMC_DPM_SHIFT 0
-#define I40E_PRTDCB_TDPMC_DPM_MASK (0xFF << I40E_PRTDCB_TDPMC_DPM_SHIFT)
+#define I40E_PRTDCB_TDPMC_DPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_TDPMC_DPM_SHIFT)
#define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TDPUC 0x00044100
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT 0
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_MASK (0xFFFF << I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT)
-#define I40E_PRTDCB_TETSC_TCB 0x000AE060
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB 0x000AE060 /* Reset: CORER */
#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
#define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
-#define I40E_PRTDCB_TETSC_TPB 0x00098060
+#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB 0x00098060 /* Reset: CORER */
#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
#define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
-#define I40E_PRTDCB_TFCS 0x001E4560
+#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
+#define I40E_PRTDCB_TFCS 0x001E4560 /* Reset: GLOBR */
#define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0
-#define I40E_PRTDCB_TFCS_TXOFF_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8
-#define I40E_PRTDCB_TFCS_TXOFF0_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF0_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9
-#define I40E_PRTDCB_TFCS_TXOFF1_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF1_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10
-#define I40E_PRTDCB_TFCS_TXOFF2_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF2_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11
-#define I40E_PRTDCB_TFCS_TXOFF3_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF3_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12
-#define I40E_PRTDCB_TFCS_TXOFF4_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF4_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13
-#define I40E_PRTDCB_TFCS_TXOFF5_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF5_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14
-#define I40E_PRTDCB_TFCS_TXOFF6_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF6_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15
-#define I40E_PRTDCB_TFCS_TXOFF7_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
-#define I40E_PRTDCB_TFWSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */
-#define I40E_PRTDCB_TFWSTC_MAX_INDEX 7
-#define I40E_PRTDCB_TFWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TFWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TFWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TFCS_TXOFF7_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
+#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */ /* Reset: GLOBR */
#define I40E_PRTDCB_TPFCTS_MAX_INDEX 7
#define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0
-#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK (0x3FFF << I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
-#define I40E_GLFCOE_RCTL 0x00269B94
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
+#define I40E_GLFCOE_RCTL 0x00269B94 /* Reset: CORER */
#define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0
-#define I40E_GLFCOE_RCTL_FCOEVER_MASK (0xF << I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
+#define I40E_GLFCOE_RCTL_FCOEVER_MASK I40E_MASK(0xF, I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
#define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4
-#define I40E_GLFCOE_RCTL_SAVBAD_MASK (0x1 << I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
+#define I40E_GLFCOE_RCTL_SAVBAD_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
#define I40E_GLFCOE_RCTL_ICRC_SHIFT 5
-#define I40E_GLFCOE_RCTL_ICRC_MASK (0x1 << I40E_GLFCOE_RCTL_ICRC_SHIFT)
+#define I40E_GLFCOE_RCTL_ICRC_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_ICRC_SHIFT)
#define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16
-#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK (0x3FFF << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
-#define I40E_GL_FWSTS 0x00083048
+#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK I40E_MASK(0x3FFF, I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
+#define I40E_GL_FWSTS 0x00083048 /* Reset: POR */
#define I40E_GL_FWSTS_FWS0B_SHIFT 0
-#define I40E_GL_FWSTS_FWS0B_MASK (0xFF << I40E_GL_FWSTS_FWS0B_SHIFT)
+#define I40E_GL_FWSTS_FWS0B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS0B_SHIFT)
#define I40E_GL_FWSTS_FWRI_SHIFT 9
-#define I40E_GL_FWSTS_FWRI_MASK (0x1 << I40E_GL_FWSTS_FWRI_SHIFT)
+#define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT)
#define I40E_GL_FWSTS_FWS1B_SHIFT 16
-#define I40E_GL_FWSTS_FWS1B_MASK (0xFF << I40E_GL_FWSTS_FWS1B_SHIFT)
-#define I40E_GLGEN_CLKSTAT 0x000B8184
+#define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT)
+#define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */
#define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0
-#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK (0x1 << I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
+#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4
-#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK (0x3 << I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK I40E_MASK(0x3, I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8
-#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12
-#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16
-#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20
-#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
-#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */ /* Reset: POR */
#define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29
#define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK (0x3 << I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4
-#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
#define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5
-#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
#define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6
-#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7
-#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK (0x7 << I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK I40E_MASK(0x7, I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10
-#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11
-#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12
-#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK (0xF << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
#define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17
-#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK (0x3 << I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19
-#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20
-#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK (0x3F << I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
-#define I40E_GLGEN_GPIO_SET 0x00088184
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK I40E_MASK(0x3F, I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
+#define I40E_GLGEN_GPIO_SET 0x00088184 /* Reset: POR */
#define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0
-#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK (0x1F << I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
#define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5
-#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK (0x1 << I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6
-#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK (0x1 << I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
-#define I40E_GLGEN_GPIO_STAT 0x0008817C
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
+#define I40E_GLGEN_GPIO_STAT 0x0008817C /* Reset: POR */
#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0
-#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
-#define I40E_GLGEN_GPIO_TRANSIT 0x00088180
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
+#define I40E_GLGEN_GPIO_TRANSIT 0x00088180 /* Reset: POR */
#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0
-#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
-#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
+#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_I2CCMD_MAX_INDEX 3
#define I40E_GLGEN_I2CCMD_DATA_SHIFT 0
-#define I40E_GLGEN_I2CCMD_DATA_MASK (0xFFFF << I40E_GLGEN_I2CCMD_DATA_SHIFT)
+#define I40E_GLGEN_I2CCMD_DATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_I2CCMD_DATA_SHIFT)
#define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16
-#define I40E_GLGEN_I2CCMD_REGADD_MASK (0xFF << I40E_GLGEN_I2CCMD_REGADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_REGADD_MASK I40E_MASK(0xFF, I40E_GLGEN_I2CCMD_REGADD_SHIFT)
#define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24
-#define I40E_GLGEN_I2CCMD_PHYADD_MASK (0x7 << I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_PHYADD_MASK I40E_MASK(0x7, I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
#define I40E_GLGEN_I2CCMD_OP_SHIFT 27
-#define I40E_GLGEN_I2CCMD_OP_MASK (0x1 << I40E_GLGEN_I2CCMD_OP_SHIFT)
+#define I40E_GLGEN_I2CCMD_OP_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_OP_SHIFT)
#define I40E_GLGEN_I2CCMD_RESET_SHIFT 28
-#define I40E_GLGEN_I2CCMD_RESET_MASK (0x1 << I40E_GLGEN_I2CCMD_RESET_SHIFT)
+#define I40E_GLGEN_I2CCMD_RESET_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_RESET_SHIFT)
#define I40E_GLGEN_I2CCMD_R_SHIFT 29
-#define I40E_GLGEN_I2CCMD_R_MASK (0x1 << I40E_GLGEN_I2CCMD_R_SHIFT)
+#define I40E_GLGEN_I2CCMD_R_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_R_SHIFT)
#define I40E_GLGEN_I2CCMD_E_SHIFT 31
-#define I40E_GLGEN_I2CCMD_E_MASK (0x1 << I40E_GLGEN_I2CCMD_E_SHIFT)
-#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CCMD_E_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_E_SHIFT)
+#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3
#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0
-#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK (0x1F << I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK I40E_MASK(0x1F, I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
#define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5
-#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK (0x7 << I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK I40E_MASK(0x7, I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8
-#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9
-#define I40E_GLGEN_I2CPARAMS_CLK_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10
-#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11
-#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12
-#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13
-#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14
-#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15
-#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31
-#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
-#define I40E_GLGEN_LED_CTL 0x00088178
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
+#define I40E_GLGEN_LED_CTL 0x00088178 /* Reset: POR */
#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0
-#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK (0x1 << I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
-#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3
#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK (0x1FFFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK I40E_MASK(0x1FFFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
#define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17
-#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK (0x1 << I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK (0x3FFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
-#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK I40E_MASK(0x3FFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3
#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31
-#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
-#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
+#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MSCA_MAX_INDEX 3
#define I40E_GLGEN_MSCA_MDIADD_SHIFT 0
-#define I40E_GLGEN_MSCA_MDIADD_MASK (0xFFFF << I40E_GLGEN_MSCA_MDIADD_SHIFT)
+#define I40E_GLGEN_MSCA_MDIADD_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSCA_MDIADD_SHIFT)
#define I40E_GLGEN_MSCA_DEVADD_SHIFT 16
-#define I40E_GLGEN_MSCA_DEVADD_MASK (0x1F << I40E_GLGEN_MSCA_DEVADD_SHIFT)
+#define I40E_GLGEN_MSCA_DEVADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_DEVADD_SHIFT)
#define I40E_GLGEN_MSCA_PHYADD_SHIFT 21
-#define I40E_GLGEN_MSCA_PHYADD_MASK (0x1F << I40E_GLGEN_MSCA_PHYADD_SHIFT)
+#define I40E_GLGEN_MSCA_PHYADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_PHYADD_SHIFT)
#define I40E_GLGEN_MSCA_OPCODE_SHIFT 26
-#define I40E_GLGEN_MSCA_OPCODE_MASK (0x3 << I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_GLGEN_MSCA_OPCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_GLGEN_MSCA_STCODE_SHIFT 28
-#define I40E_GLGEN_MSCA_STCODE_MASK (0x3 << I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_GLGEN_MSCA_STCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_GLGEN_MSCA_MDICMD_SHIFT 30
-#define I40E_GLGEN_MSCA_MDICMD_MASK (0x1 << I40E_GLGEN_MSCA_MDICMD_SHIFT)
+#define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT)
#define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31
-#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK (0x1 << I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
-#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
+#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MSRWD_MAX_INDEX 3
#define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
-#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
+#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
#define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
-#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
-#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4
+#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4 /* Reset: PCIR */
#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
-#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK (0x1F << I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
-#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK (0xFF << I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
-#define I40E_GLGEN_PE_ENA 0x000B81A0
-#define I40E_GLGEN_PE_ENA_PE_ENA_SHIFT 0
-#define I40E_GLGEN_PE_ENA_PE_ENA_MASK (0x1 << I40E_GLGEN_PE_ENA_PE_ENA_SHIFT)
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT 1
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_MASK (0x3 << I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT)
-#define I40E_GLGEN_RSTAT 0x000B8188
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
+#define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */
#define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
-#define I40E_GLGEN_RSTAT_DEVSTATE_MASK (0x3 << I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
+#define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
#define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2
-#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK (0x3 << I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
+#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
#define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4
-#define I40E_GLGEN_RSTAT_CORERCNT_MASK (0x3 << I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_CORERCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
#define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6
-#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
#define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8
-#define I40E_GLGEN_RSTAT_EMPRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_EMPRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
#define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10
-#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK (0x3F << I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
-#define I40E_GLGEN_RSTCTL 0x000B8180
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
+#define I40E_GLGEN_RSTCTL 0x000B8180 /* Reset: POR */
#define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0
-#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK (0x3F << I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
+#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8
-#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
-#define I40E_GLGEN_RSTENA_EMP 0x000B818C
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
+#define I40E_GLGEN_RSTENA_EMP 0x000B818C /* Reset: POR */
#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT 0
-#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
-#define I40E_GLGEN_RTRIG 0x000B8190
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
+#define I40E_GLGEN_RTRIG 0x000B8190 /* Reset: CORER */
#define I40E_GLGEN_RTRIG_CORER_SHIFT 0
-#define I40E_GLGEN_RTRIG_CORER_MASK (0x1 << I40E_GLGEN_RTRIG_CORER_SHIFT)
+#define I40E_GLGEN_RTRIG_CORER_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_CORER_SHIFT)
#define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1
-#define I40E_GLGEN_RTRIG_GLOBR_MASK (0x1 << I40E_GLGEN_RTRIG_GLOBR_SHIFT)
+#define I40E_GLGEN_RTRIG_GLOBR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_GLOBR_SHIFT)
#define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2
-#define I40E_GLGEN_RTRIG_EMPFWR_MASK (0x1 << I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
-#define I40E_GLGEN_STAT 0x000B612C
+#define I40E_GLGEN_RTRIG_EMPFWR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
+#define I40E_GLGEN_STAT 0x000B612C /* Reset: POR */
#define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0
-#define I40E_GLGEN_STAT_HWRSVD0_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD0_SHIFT)
+#define I40E_GLGEN_STAT_HWRSVD0_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD0_SHIFT)
#define I40E_GLGEN_STAT_DCBEN_SHIFT 2
-#define I40E_GLGEN_STAT_DCBEN_MASK (0x1 << I40E_GLGEN_STAT_DCBEN_SHIFT)
+#define I40E_GLGEN_STAT_DCBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_DCBEN_SHIFT)
#define I40E_GLGEN_STAT_VTEN_SHIFT 3
-#define I40E_GLGEN_STAT_VTEN_MASK (0x1 << I40E_GLGEN_STAT_VTEN_SHIFT)
+#define I40E_GLGEN_STAT_VTEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_VTEN_SHIFT)
#define I40E_GLGEN_STAT_FCOEN_SHIFT 4
-#define I40E_GLGEN_STAT_FCOEN_MASK (0x1 << I40E_GLGEN_STAT_FCOEN_SHIFT)
+#define I40E_GLGEN_STAT_FCOEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_FCOEN_SHIFT)
#define I40E_GLGEN_STAT_EVBEN_SHIFT 5
-#define I40E_GLGEN_STAT_EVBEN_MASK (0x1 << I40E_GLGEN_STAT_EVBEN_SHIFT)
+#define I40E_GLGEN_STAT_EVBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_EVBEN_SHIFT)
#define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6
-#define I40E_GLGEN_STAT_HWRSVD1_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD1_SHIFT)
-#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_STAT_HWRSVD1_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD1_SHIFT)
+#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3
#define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0
-#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK (0xFFFFFFFF << I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
-#define I40E_GLVFGEN_TIMER 0x000881BC
+#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK I40E_MASK(0xFFFFFFFF, I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
+#define I40E_GLVFGEN_TIMER 0x000881BC /* Reset: CORER */
#define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0
-#define I40E_GLVFGEN_TIMER_GTIME_MASK (0xFFFFFFFF << I40E_GLVFGEN_TIMER_GTIME_SHIFT)
-#define I40E_PFGEN_CTRL 0x00092400
+#define I40E_GLVFGEN_TIMER_GTIME_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVFGEN_TIMER_GTIME_SHIFT)
+#define I40E_PFGEN_CTRL 0x00092400 /* Reset: PFR */
#define I40E_PFGEN_CTRL_PFSWR_SHIFT 0
-#define I40E_PFGEN_CTRL_PFSWR_MASK (0x1 << I40E_PFGEN_CTRL_PFSWR_SHIFT)
-#define I40E_PFGEN_DRUN 0x00092500
+#define I40E_PFGEN_CTRL_PFSWR_MASK I40E_MASK(0x1, I40E_PFGEN_CTRL_PFSWR_SHIFT)
+#define I40E_PFGEN_DRUN 0x00092500 /* Reset: CORER */
#define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0
-#define I40E_PFGEN_DRUN_DRVUNLD_MASK (0x1 << I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
-#define I40E_PFGEN_PORTNUM 0x001C0480
+#define I40E_PFGEN_DRUN_DRVUNLD_MASK I40E_MASK(0x1, I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
+#define I40E_PFGEN_PORTNUM 0x001C0480 /* Reset: CORER */
#define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
-#define I40E_PFGEN_STATE 0x00088000
-#define I40E_PFGEN_STATE_PFPEEN_SHIFT 0
-#define I40E_PFGEN_STATE_PFPEEN_MASK (0x1 << I40E_PFGEN_STATE_PFPEEN_SHIFT)
+#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_STATE 0x00088000 /* Reset: CORER */
+#define I40E_PFGEN_STATE_RESERVED_0_SHIFT 0
+#define I40E_PFGEN_STATE_RESERVED_0_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_RESERVED_0_SHIFT)
#define I40E_PFGEN_STATE_PFFCEN_SHIFT 1
-#define I40E_PFGEN_STATE_PFFCEN_MASK (0x1 << I40E_PFGEN_STATE_PFFCEN_SHIFT)
+#define I40E_PFGEN_STATE_PFFCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFFCEN_SHIFT)
#define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2
-#define I40E_PFGEN_STATE_PFLINKEN_MASK (0x1 << I40E_PFGEN_STATE_PFLINKEN_SHIFT)
+#define I40E_PFGEN_STATE_PFLINKEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFLINKEN_SHIFT)
#define I40E_PFGEN_STATE_PFSCEN_SHIFT 3
-#define I40E_PFGEN_STATE_PFSCEN_MASK (0x1 << I40E_PFGEN_STATE_PFSCEN_SHIFT)
-#define I40E_PRTGEN_CNF 0x000B8120
+#define I40E_PFGEN_STATE_PFSCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFSCEN_SHIFT)
+#define I40E_PRTGEN_CNF 0x000B8120 /* Reset: POR */
#define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0
-#define I40E_PRTGEN_CNF_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1
-#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
#define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2
-#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
-#define I40E_PRTGEN_CNF2 0x000B8160
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF2 0x000B8160 /* Reset: POR */
#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0
-#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK (0x1 << I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
-#define I40E_PRTGEN_STATUS 0x000B8100
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
+#define I40E_PRTGEN_STATUS 0x000B8100 /* Reset: POR */
#define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0
-#define I40E_PRTGEN_STATUS_PORT_VALID_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
+#define I40E_PRTGEN_STATUS_PORT_VALID_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
#define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1
-#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
-#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
+#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFGEN_RSTAT1_MAX_INDEX 127
#define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
-#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
+#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPGEN_VFRSTAT_MAX_INDEX 127
#define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0
-#define I40E_VPGEN_VFRSTAT_VFRD_MASK (0x1 << I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
-#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRSTAT_VFRD_MASK I40E_MASK(0x1, I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
+#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPGEN_VFRTRIG_MAX_INDEX 127
#define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0
-#define I40E_VPGEN_VFRTRIG_VFSWR_MASK (0x1 << I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
-#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPGEN_VFRTRIG_VFSWR_MASK I40E_MASK(0x1, I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
+#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_VSIGEN_RSTAT_MAX_INDEX 383
#define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0
-#define I40E_VSIGEN_RSTAT_VMRD_MASK (0x1 << I40E_VSIGEN_RSTAT_VMRD_SHIFT)
-#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RSTAT_VMRD_MASK I40E_MASK(0x1, I40E_VSIGEN_RSTAT_VMRD_SHIFT)
+#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_VSIGEN_RTRIG_MAX_INDEX 383
#define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0
-#define I40E_VSIGEN_RTRIG_VMSWR_MASK (0x1 << I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
-#define I40E_GLHMC_APBVTINUSEBASE(_i) (0x000C4a00 + ((_i) * 4))
-#define I40E_GLHMC_APBVTINUSEBASE_MAX_INDEX 15
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_CEQPART(_i) (0x001312C0 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_CEQPART_MAX_INDEX 15
-#define I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_CEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_DBCQPART(_i) (0x00131240 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBCQPART_MAX_INDEX 15
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_DBQPPART(_i) (0x00138D80 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBQPPART_MAX_INDEX 15
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VSIGEN_RTRIG_VMSWR_MASK I40E_MASK(0x1, I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
+#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15
#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0
-#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
-#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
+#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15
#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0
-#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK (0xFFFFF << I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
-#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK I40E_MASK(0xFFFFF, I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
+#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010 /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK (0xF << I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15
#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0
-#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
-#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
+#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15
#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0
-#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK (0x7FFFFF << I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
-#define I40E_GLHMC_FCOEFMAX 0x000C20D0
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK I40E_MASK(0x7FFFFF, I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
+#define I40E_GLHMC_FCOEFMAX 0x000C20D0 /* Reset: CORER */
#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0
-#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK (0xFFFF << I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
-#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK I40E_MASK(0xFFFF, I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
+#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018 /* Reset: CORER */
#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK (0xF << I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEMAX 0x000C2014
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEMAX 0x000C2014 /* Reset: CORER */
#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0
-#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK (0x1FFF << I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
-#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK I40E_MASK(0x1FFF, I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
+#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15
#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15
#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
#define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_FSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_FSIAVMAX 0x000C2068
+#define I40E_GLHMC_FSIAVCNT_RSVD_MASK I40E_MASK(0x7, I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_FSIAVMAX 0x000C2068 /* Reset: CORER */
#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0
-#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK (0x1FFFF << I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
-#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK I40E_MASK(0x1FFFF, I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
+#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064 /* Reset: CORER */
#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK (0xF << I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
-#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
+#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15
#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0
-#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
-#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
+#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15
#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK (0x1FFFFFFF << I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
-#define I40E_GLHMC_FSIMCMAX 0x000C2060
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
+#define I40E_GLHMC_FSIMCMAX 0x000C2060 /* Reset: CORER */
#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0
-#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK (0x3FFF << I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
-#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK I40E_MASK(0x3FFF, I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
+#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c /* Reset: CORER */
#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK (0xF << I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
-#define I40E_GLHMC_LANQMAX 0x000C2008
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
+#define I40E_GLHMC_LANQMAX 0x000C2008 /* Reset: CORER */
#define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0
-#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK (0x7FF << I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
-#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
+#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANRXBASE_MAX_INDEX 15
#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0
-#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
-#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
+#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANRXCNT_MAX_INDEX 15
#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0
-#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK (0x7FF << I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
-#define I40E_GLHMC_LANRXOBJSZ 0x000C200c
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
+#define I40E_GLHMC_LANRXOBJSZ 0x000C200c /* Reset: CORER */
#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK (0xF << I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
-#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
+#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANTXBASE_MAX_INDEX 15
#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0
-#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
#define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24
-#define I40E_GLHMC_LANTXBASE_RSVD_MASK (0xFF << I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
-#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXBASE_RSVD_MASK I40E_MASK(0xFF, I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
+#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANTXCNT_MAX_INDEX 15
#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0
-#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK (0x7FF << I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
-#define I40E_GLHMC_LANTXOBJSZ 0x000C2004
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
+#define I40E_GLHMC_LANTXOBJSZ 0x000C2004 /* Reset: CORER */
#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK (0xF << I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
-#define I40E_GLHMC_PEARPBASE(_i) (0x000C4800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_PEARPCNT(_i) (0x000C4900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_PEARPMAX 0x000C2038
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT 0
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_MASK (0x1FFFF << I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT)
-#define I40E_GLHMC_PEARPOBJSZ 0x000C2034
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_MASK (0x7 << I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT)
-#define I40E_GLHMC_PECQBASE(_i) (0x000C4200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_PECQCNT(_i) (0x000C4300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_PECQOBJSZ 0x000C2020
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_MASK (0xF << I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTCNT(_i) (0x000C4700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_PEHTEBASE(_i) (0x000C4600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTEBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_PEHTEOBJSZ 0x000C202c
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_MASK (0xF << I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTMAX 0x000C2030
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT 0
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_MASK (0x1FFFFF << I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT)
-#define I40E_GLHMC_PEMRBASE(_i) (0x000C4c00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_PEMRCNT(_i) (0x000C4d00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_PEMRMAX 0x000C2040
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT 0
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_MASK (0x7FFFFF << I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT)
-#define I40E_GLHMC_PEMROBJSZ 0x000C203c
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT 0
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_MASK (0xF << I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT)
-#define I40E_GLHMC_PEPBLBASE(_i) (0x000C5800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_PEPBLCNT(_i) (0x000C5900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_PEPBLMAX 0x000C206c
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT 0
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1BASE(_i) (0x000C5200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1BASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_PEQ1CNT(_i) (0x000C5300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1CNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLBASE(_i) (0x000C5400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_PEQ1FLCNT(_i) (0x000C5500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLMAX 0x000C2058
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1MAX 0x000C2054
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
-#define I40E_GLHMC_PEQ1OBJSZ 0x000C2050
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_MASK (0xF << I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT)
-#define I40E_GLHMC_PEQPBASE(_i) (0x000C4000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_PEQPCNT(_i) (0x000C4100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_PEQPOBJSZ 0x000C201c
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_MASK (0xF << I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQBASE(_i) (0x000C4400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_PESRQCNT(_i) (0x000C4500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_PESRQMAX 0x000C2028
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT 0
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_MASK (0xFFFF << I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ 0x000C2024
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_MASK (0xF << I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PETIMERBASE(_i) (0x000C5A00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERBASE_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_PETIMERCNT(_i) (0x000C5B00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERCNT_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_PETIMERMAX 0x000C2084
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT 0
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT)
-#define I40E_GLHMC_PETIMEROBJSZ 0x000C2080
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT 0
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_MASK (0xF << I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFBASE(_i) (0x000C4e00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_PEXFCNT(_i) (0x000C4f00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLBASE(_i) (0x000C5000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_PEXFFLCNT(_i) (0x000C5100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLMAX 0x000C204c
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
-#define I40E_GLHMC_PEXFMAX 0x000C2048
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ 0x000C2044
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_MASK (0xF << I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
+#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_PFASSIGN_MAX_INDEX 15
#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0
-#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK (0xF << I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
-#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK I40E_MASK(0xF, I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
+#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_SDPART_MAX_INDEX 15
#define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_SDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_SDPART_PMSDBASE_MASK I40E_MASK(0xFFF, I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
#define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_SDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
-#define I40E_GLHMC_VFAPBVTINUSEBASE(_i) (0x000Cca00 + ((_i) * 4))
-#define I40E_GLHMC_VFAPBVTINUSEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART(_i) (0x00132240 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFCEQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART(_i) (0x00132140 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBCQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART(_i) (0x00138E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBQPPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_VFFSIAVBASE(_i) (0x000Cd600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT(_i) (0x000Cd700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_VFPDINV(_i) (0x000C8300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPDINV_MAX_INDEX 31
-#define I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT 0
-#define I40E_GLHMC_VFPDINV_PMSDIDX_MASK (0xFFF << I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT)
-#define I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT 16
-#define I40E_GLHMC_VFPDINV_PMPDIDX_MASK (0x1FF << I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT)
-#define I40E_GLHMC_VFPEARPBASE(_i) (0x000Cc800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_VFPEARPCNT(_i) (0x000Cc900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_VFPECQBASE(_i) (0x000Cc200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_VFPECQCNT(_i) (0x000Cc300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTCNT(_i) (0x000Cc700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTEBASE(_i) (0x000Cc600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRBASE(_i) (0x000Ccc00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRCNT(_i) (0x000Ccd00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_VFPEPBLBASE(_i) (0x000Cd800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_VFPEPBLCNT(_i) (0x000Cd900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1BASE(_i) (0x000Cd200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1BASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1CNT(_i) (0x000Cd300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1CNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLBASE(_i) (0x000Cd400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLCNT(_i) (0x000Cd500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQPBASE(_i) (0x000Cc000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_VFPEQPCNT(_i) (0x000Cc100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_VFPESRQBASE(_i) (0x000Cc400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_VFPESRQCNT(_i) (0x000Cc500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_VFPETIMERBASE(_i) (0x000CDA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_VFPETIMERCNT(_i) (0x000CDB00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFBASE(_i) (0x000Cce00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFCNT(_i) (0x000Ccf00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFFLBASE(_i) (0x000Cd000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFFLCNT(_i) (0x000Cd100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_VFSDPART(_i) (0x000C8800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFSDPART_MAX_INDEX 31
-#define I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_VFSDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT)
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT)
-#define I40E_PFHMC_ERRORDATA 0x000C0500
+#define I40E_GLHMC_SDPART_PMSDSIZE_MASK I40E_MASK(0x1FFF, I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
+#define I40E_PFHMC_ERRORDATA 0x000C0500 /* Reset: PFR */
#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0
-#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK (0x3FFFFFFF << I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
-#define I40E_PFHMC_ERRORINFO 0x000C0400
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK I40E_MASK(0x3FFFFFFF, I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
+#define I40E_PFHMC_ERRORINFO 0x000C0400 /* Reset: PFR */
#define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0
-#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK (0x1F << I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
#define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7
-#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK (0x1 << I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8
-#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK (0xF << I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK I40E_MASK(0xF, I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16
-#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK (0x1F << I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31
-#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK (0x1 << I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
-#define I40E_PFHMC_PDINV 0x000C0300
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
+#define I40E_PFHMC_PDINV 0x000C0300 /* Reset: PFR */
#define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_PDINV_PMSDIDX_MASK (0xFFF << I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
+#define I40E_PFHMC_PDINV_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
#define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16
-#define I40E_PFHMC_PDINV_PMPDIDX_MASK (0x1FF << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
-#define I40E_PFHMC_SDCMD 0x000C0000
+#define I40E_PFHMC_PDINV_PMPDIDX_MASK I40E_MASK(0x1FF, I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD 0x000C0000 /* Reset: PFR */
#define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_SDCMD_PMSDIDX_MASK (0xFFF << I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
#define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31
-#define I40E_PFHMC_SDCMD_PMSDWR_MASK (0x1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
-#define I40E_PFHMC_SDDATAHIGH 0x000C0200
+#define I40E_PFHMC_SDCMD_PMSDWR_MASK I40E_MASK(0x1, I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
+#define I40E_PFHMC_SDDATAHIGH 0x000C0200 /* Reset: PFR */
#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0
-#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK (0xFFFFFFFF << I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
-#define I40E_PFHMC_SDDATALOW 0x000C0100
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
+#define I40E_PFHMC_SDDATALOW 0x000C0100 /* Reset: PFR */
#define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0
-#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1
-#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2
-#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK (0x3FF << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK I40E_MASK(0x3FF, I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12
-#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK (0xFFFFF << I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
-#define I40E_GL_UFUSE 0x00094008
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK I40E_MASK(0xFFFFF, I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ /* Reset: POR */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
+#define I40E_GL_UFUSE 0x00094008 /* Reset: POR */
#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1
-#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK (0x1 << I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK I40E_MASK(0x1, I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
#define I40E_GL_UFUSE_NIC_ID_SHIFT 2
-#define I40E_GL_UFUSE_NIC_ID_MASK (0x1 << I40E_GL_UFUSE_NIC_ID_SHIFT)
+#define I40E_GL_UFUSE_NIC_ID_MASK I40E_MASK(0x1, I40E_GL_UFUSE_NIC_ID_SHIFT)
#define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10
-#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
+#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
#define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11
-#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
-#define I40E_EMPINT_GPIO_ENA 0x00088188
+#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
+#define I40E_EMPINT_GPIO_ENA 0x00088188 /* Reset: POR */
#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100 /* Reset: CORER */
#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4
-#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK (0x1 << I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
-#define I40E_PFINT_AEQCTL 0x00038700
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK I40E_MASK(0x1, I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL 0x00038700 /* Reset: CORER */
#define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
#define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_PFINT_CEQCTL_MAX_INDEX 511
#define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
#define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_DYN_CTL0 0x00038480
+#define I40E_PFINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_DYN_CTL0 0x00038480 /* Reset: PFR */
#define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
#define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
#define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_DYN_CTLN_MAX_INDEX 511
#define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
#define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
#define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_PFINT_GPIO_ENA 0x00088080
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_PFINT_GPIO_ENA 0x00088080 /* Reset: CORER */
#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFINT_ICR0 0x00038780
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
#define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_PFINT_ICR0_INTEVENT_MASK (0x1 << I40E_PFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_PFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_0_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_PFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_1_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_PFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_2_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_PFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_3_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5
-#define I40E_PFINT_ICR0_QUEUE_4_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_4_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_4_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_4_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6
-#define I40E_PFINT_ICR0_QUEUE_5_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_5_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_5_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_5_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7
-#define I40E_PFINT_ICR0_QUEUE_6_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_6_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_6_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_6_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8
-#define I40E_PFINT_ICR0_QUEUE_7_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_7_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_7_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_7_SHIFT)
#define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ECC_ERR_SHIFT)
#define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
#define I40E_PFINT_ICR0_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_GRST_MASK (0x1 << I40E_PFINT_ICR0_GRST_SHIFT)
+#define I40E_PFINT_ICR0_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GRST_SHIFT)
#define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
#define I40E_PFINT_ICR0_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_GPIO_MASK (0x1 << I40E_PFINT_ICR0_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GPIO_SHIFT)
#define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_STORM_DETECT_SHIFT)
#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
#define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_HMC_ERR_SHIFT)
#define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
#define I40E_PFINT_ICR0_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_VFLR_MASK (0x1 << I40E_PFINT_ICR0_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_VFLR_SHIFT)
#define I40E_PFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ADMINQ_SHIFT)
#define I40E_PFINT_ICR0_SWINT_SHIFT 31
-#define I40E_PFINT_ICR0_SWINT_MASK (0x1 << I40E_PFINT_ICR0_SWINT_SHIFT)
-#define I40E_PFINT_ICR0_ENA 0x00038800
+#define I40E_PFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_SWINT_SHIFT)
+#define I40E_PFINT_ICR0_ENA 0x00038800 /* Reset: CORER */
#define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
#define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_ENA_GRST_MASK (0x1 << I40E_PFINT_ICR0_ENA_GRST_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GRST_SHIFT)
#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
#define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_ENA_GPIO_MASK (0x1 << I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
#define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT)
#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
#define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_ENA_VFLR_MASK (0x1 << I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
#define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
#define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_PFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */
+#define I40E_PFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */ /* Reset: PFR */
#define I40E_PFINT_ITR0_MAX_INDEX 2
#define I40E_PFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_PFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4))
+#define I40E_PFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4)) /* _i=0...2, _INTPF=0...511 */ /* Reset: PFR */
#define I40E_PFINT_ITRN_MAX_INDEX 2
#define I40E_PFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_PFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_PFINT_LNKLST0 0x00038500
+#define I40E_PFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_PFINT_LNKLST0 0x00038500 /* Reset: PFR */
#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_LNKLSTN_MAX_INDEX 511
#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_RATE0 0x00038580
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_RATE0 0x00038580 /* Reset: PFR */
#define I40E_PFINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATE0_INTERVAL_MASK (0x3F << I40E_PFINT_RATE0_INTERVAL_SHIFT)
+#define I40E_PFINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATE0_INTERVAL_SHIFT)
#define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_RATEN_MAX_INDEX 511
#define I40E_PFINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATEN_INTERVAL_MASK (0x3F << I40E_PFINT_RATEN_INTERVAL_SHIFT)
+#define I40E_PFINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATEN_INTERVAL_SHIFT)
#define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_PFINT_STAT_CTL0 0x00038400
+#define I40E_PFINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_PFINT_STAT_CTL0 0x00038400 /* Reset: PFR */
#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QINT_RQCTL_MAX_INDEX 1535
#define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_RQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
#define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_RQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_ITR_INDX_SHIFT)
#define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_RQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
#define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
#define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_RQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_RQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
#define I40E_QINT_RQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_RQCTL_INTEVENT_MASK (0x1 << I40E_QINT_RQCTL_INTEVENT_SHIFT)
-#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_RQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_INTEVENT_SHIFT)
+#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QINT_TQCTL_MAX_INDEX 1535
#define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_TQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
#define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_TQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_TQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_ITR_INDX_SHIFT)
#define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_TQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
#define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
#define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_TQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_TQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
#define I40E_QINT_TQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_TQCTL_INTEVENT_MASK (0x1 << I40E_QINT_TQCTL_INTEVENT_SHIFT)
-#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QINT_TQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_INTEVENT_SHIFT)
+#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTL0_MAX_INDEX 127
#define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTLN_MAX_INDEX 511
#define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VFINT_ICR0_MAX_INDEX 127
#define I40E_VFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR0_INTEVENT_MASK (0x1 << I40E_VFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_INTEVENT_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_0_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_1_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_2_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_3_SHIFT)
#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_SWINT_SHIFT 31
-#define I40E_VFINT_ICR0_SWINT_MASK (0x1 << I40E_VFINT_ICR0_SWINT_SHIFT)
-#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_SWINT_SHIFT)
+#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VFINT_ICR0_ENA_MAX_INDEX 127
#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */
+#define I40E_VFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */ /* Reset: VFR */
#define I40E_VFINT_ITR0_MAX_INDEX 2
#define I40E_VFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4))
+#define I40E_VFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...511 */ /* Reset: VFR */
#define I40E_VFINT_ITRN_MAX_INDEX 2
#define I40E_VFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFINT_STAT_CTL0_MAX_INDEX 127
#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPINT_AEQCTL_MAX_INDEX 127
#define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
#define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_VPINT_CEQCTL_MAX_INDEX 511
#define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
#define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPINT_LNKLST0_MAX_INDEX 127
#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VPINT_LNKLSTN_MAX_INDEX 511
#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPINT_RATE0_MAX_INDEX 127
#define I40E_VPINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATE0_INTERVAL_MASK (0x3F << I40E_VPINT_RATE0_INTERVAL_SHIFT)
+#define I40E_VPINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATE0_INTERVAL_SHIFT)
#define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VPINT_RATEN_MAX_INDEX 511
#define I40E_VPINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATEN_INTERVAL_MASK (0x3F << I40E_VPINT_RATEN_INTERVAL_SHIFT)
+#define I40E_VPINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATEN_INTERVAL_SHIFT)
#define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_GL_RDPU_CNTRL 0x00051060
+#define I40E_VPINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_GL_RDPU_CNTRL 0x00051060 /* Reset: CORER */
#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0
-#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK (0x1 << I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK I40E_MASK(0x1, I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
#define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1
-#define I40E_GL_RDPU_CNTRL_ECO_MASK (0x7FFFFFFF << I40E_GL_RDPU_CNTRL_ECO_SHIFT)
-#define I40E_GLLAN_RCTL_0 0x0012A500
+#define I40E_GL_RDPU_CNTRL_ECO_MASK I40E_MASK(0x7FFFFFFF, I40E_GL_RDPU_CNTRL_ECO_SHIFT)
+#define I40E_GLLAN_RCTL_0 0x0012A500 /* Reset: CORER */
#define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0
-#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK (0x1 << I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
-#define I40E_GLLAN_TSOMSK_F 0x000442D8
+#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK I40E_MASK(0x1, I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
+#define I40E_GLLAN_TSOMSK_F 0x000442D8 /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0
-#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK (0xFFF << I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
-#define I40E_GLLAN_TSOMSK_L 0x000442E0
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
+#define I40E_GLLAN_TSOMSK_L 0x000442E0 /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0
-#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK (0xFFF << I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
-#define I40E_GLLAN_TSOMSK_M 0x000442DC
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
+#define I40E_GLLAN_TSOMSK_M 0x000442DC /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0
-#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK (0xFFF << I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
-#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000E6500 + ((_i) * 4)) /* i=0..11 */
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000e6500 + ((_i) * 4)) /* _i=0...11 */ /* Reset: CORER */
+#define I40E_GLLAN_TXPRE_QDIS_MAX_INDEX 11
#define I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT 0
-#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK (0x7FF << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK I40E_MASK(0x7FF, I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT 16
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT)
#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30
-#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31
-#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
-
-#define I40E_PFLAN_QALLOC 0x001C0400
+#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
+#define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */
#define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0
-#define I40E_PFLAN_QALLOC_FIRSTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
#define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16
-#define I40E_PFLAN_QALLOC_LASTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_LASTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT)
#define I40E_PFLAN_QALLOC_VALID_SHIFT 31
-#define I40E_PFLAN_QALLOC_VALID_MASK (0x1 << I40E_PFLAN_QALLOC_VALID_SHIFT)
-#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT)
+#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QRX_ENA_MAX_INDEX 1535
#define I40E_QRX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QRX_ENA_QENA_REQ_MASK (0x1 << I40E_QRX_ENA_QENA_REQ_SHIFT)
+#define I40E_QRX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_REQ_SHIFT)
#define I40E_QRX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QRX_ENA_FAST_QDIS_MASK (0x1 << I40E_QRX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QRX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QRX_ENA_FAST_QDIS_SHIFT)
#define I40E_QRX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QRX_ENA_QENA_STAT_MASK (0x1 << I40E_QRX_ENA_QENA_STAT_SHIFT)
-#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_STAT_SHIFT)
+#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QRX_TAIL_MAX_INDEX 1535
#define I40E_QRX_TAIL_TAIL_SHIFT 0
-#define I40E_QRX_TAIL_TAIL_MASK (0x1FFF << I40E_QRX_TAIL_TAIL_SHIFT)
-#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL_TAIL_SHIFT)
+#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QTX_CTL_MAX_INDEX 1535
#define I40E_QTX_CTL_PFVF_Q_SHIFT 0
-#define I40E_QTX_CTL_PFVF_Q_MASK (0x3 << I40E_QTX_CTL_PFVF_Q_SHIFT)
+#define I40E_QTX_CTL_PFVF_Q_MASK I40E_MASK(0x3, I40E_QTX_CTL_PFVF_Q_SHIFT)
#define I40E_QTX_CTL_PF_INDX_SHIFT 2
-#define I40E_QTX_CTL_PF_INDX_MASK (0xF << I40E_QTX_CTL_PF_INDX_SHIFT)
+#define I40E_QTX_CTL_PF_INDX_MASK I40E_MASK(0xF, I40E_QTX_CTL_PF_INDX_SHIFT)
#define I40E_QTX_CTL_VFVM_INDX_SHIFT 7
-#define I40E_QTX_CTL_VFVM_INDX_MASK (0x1FF << I40E_QTX_CTL_VFVM_INDX_SHIFT)
-#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_CTL_VFVM_INDX_MASK I40E_MASK(0x1FF, I40E_QTX_CTL_VFVM_INDX_SHIFT)
+#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QTX_ENA_MAX_INDEX 1535
#define I40E_QTX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QTX_ENA_QENA_REQ_MASK (0x1 << I40E_QTX_ENA_QENA_REQ_SHIFT)
+#define I40E_QTX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_REQ_SHIFT)
#define I40E_QTX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QTX_ENA_FAST_QDIS_MASK (0x1 << I40E_QTX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QTX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QTX_ENA_FAST_QDIS_SHIFT)
#define I40E_QTX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QTX_ENA_QENA_STAT_MASK (0x1 << I40E_QTX_ENA_QENA_STAT_SHIFT)
-#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_STAT_SHIFT)
+#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QTX_HEAD_MAX_INDEX 1535
#define I40E_QTX_HEAD_HEAD_SHIFT 0
-#define I40E_QTX_HEAD_HEAD_MASK (0x1FFF << I40E_QTX_HEAD_HEAD_SHIFT)
+#define I40E_QTX_HEAD_HEAD_MASK I40E_MASK(0x1FFF, I40E_QTX_HEAD_HEAD_SHIFT)
#define I40E_QTX_HEAD_RS_PENDING_SHIFT 16
-#define I40E_QTX_HEAD_RS_PENDING_MASK (0x1 << I40E_QTX_HEAD_RS_PENDING_SHIFT)
-#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_HEAD_RS_PENDING_MASK I40E_MASK(0x1, I40E_QTX_HEAD_RS_PENDING_SHIFT)
+#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QTX_TAIL_MAX_INDEX 1535
#define I40E_QTX_TAIL_TAIL_SHIFT 0
-#define I40E_QTX_TAIL_TAIL_MASK (0x1FFF << I40E_QTX_TAIL_TAIL_SHIFT)
-#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QTX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL_TAIL_SHIFT)
+#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPLAN_MAPENA_MAX_INDEX 127
#define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0
-#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK (0x1 << I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
-#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK I40E_MASK(0x1, I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
+#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: VFR */
#define I40E_VPLAN_QTABLE_MAX_INDEX 15
#define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0
-#define I40E_VPLAN_QTABLE_QINDEX_MASK (0x7FF << I40E_VPLAN_QTABLE_QINDEX_SHIFT)
-#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPLAN_QTABLE_QINDEX_MASK I40E_MASK(0x7FF, I40E_VPLAN_QTABLE_QINDEX_SHIFT)
+#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
#define I40E_VSILAN_QBASE_MAX_INDEX 383
#define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0
-#define I40E_VSILAN_QBASE_VSIBASE_MASK (0x7FF << I40E_VSILAN_QBASE_VSIBASE_SHIFT)
+#define I40E_VSILAN_QBASE_VSIBASE_MASK I40E_MASK(0x7FF, I40E_VSILAN_QBASE_VSIBASE_SHIFT)
#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
-#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
-#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK I40E_MASK(0x1, I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
+#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...7, _VSI=0...383 */ /* Reset: PFR */
#define I40E_VSILAN_QTABLE_MAX_INDEX 7
#define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
-#define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
+#define I40E_VSILAN_QTABLE_QINDEX_0_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
#define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
-#define I40E_VSILAN_QTABLE_QINDEX_1_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
-#define I40E_PRTGL_SAH 0x001E2140
+#define I40E_VSILAN_QTABLE_QINDEX_1_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
+#define I40E_PRTGL_SAH 0x001E2140 /* Reset: GLOBR */
#define I40E_PRTGL_SAH_FC_SAH_SHIFT 0
-#define I40E_PRTGL_SAH_FC_SAH_MASK (0xFFFF << I40E_PRTGL_SAH_FC_SAH_SHIFT)
+#define I40E_PRTGL_SAH_FC_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_FC_SAH_SHIFT)
#define I40E_PRTGL_SAH_MFS_SHIFT 16
-#define I40E_PRTGL_SAH_MFS_MASK (0xFFFF << I40E_PRTGL_SAH_MFS_SHIFT)
-#define I40E_PRTGL_SAL 0x001E2120
+#define I40E_PRTGL_SAH_MFS_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_MFS_SHIFT)
+#define I40E_PRTGL_SAL 0x001E2120 /* Reset: GLOBR */
#define I40E_PRTGL_SAL_FC_SAL_SHIFT 0
-#define I40E_PRTGL_SAL_FC_SAL_MASK (0xFFFFFFFF << I40E_PRTGL_SAL_FC_SAL_SHIFT)
-#define I40E_PRTMAC_HLCTLA 0x001E4760
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT 1
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_MASK (0x1 << I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT)
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT 2
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT)
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP 0x001E3130
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP 0x001E3290
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP 0x001E3310
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP 0x001E3100
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP 0x001E3280
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP 0x001E3300
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0
+#define I40E_PRTGL_SAL_FC_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTGL_SAL_FC_SAL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE 0x001E3000
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSECTL1 0x001E3560
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT 3
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT 30
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT 31
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480 /* Reset: GLOBR */
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484 /* Reset: GLOBR */
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
-#define I40E_GL_MNG_FWSM 0x000B6134
-#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
-#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
+#define I40E_GL_FWRESETCNT 0x00083100 /* Reset: POR */
+#define I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT 0
+#define I40E_GL_FWRESETCNT_FWRESETCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT)
+#define I40E_GL_MNG_FWSM 0x000B6134 /* Reset: POR */
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK I40E_MASK(0x3, I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
-#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK I40E_MASK(0xF, I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
-#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
#define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
-#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK I40E_MASK(0x7, I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
#define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
-#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
-#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
-#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK I40E_MASK(0x3F, I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
-#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
-#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28
-#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29
-#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
-#define I40E_GL_MNG_HWARB_CTRL 0x000B6130
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_HWARB_CTRL 0x000B6130 /* Reset: POR */
#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0
-#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK (0x1 << I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
-#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK I40E_MASK(0x1, I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
+#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */ /* Reset: POR */
#define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31
#define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0
-#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
-#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
+#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260 /* Reset: POR */
#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK (0xFF << I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7
#define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0
-#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK (0xFFFF << I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
-#define I40E_PRT_MNG_MANC 0x00256A20
+#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
+#define I40E_PRT_MNG_MANC 0x00256A20 /* Reset: POR */
#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0
-#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
#define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1
-#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
#define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17
-#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
#define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19
-#define I40E_PRT_MNG_MANC_RCV_ALL_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_ALL_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25
-#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
#define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26
-#define I40E_PRT_MNG_MANC_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
#define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28
-#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
#define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29
-#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
-#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
+#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MAVTV_MAX_INDEX 7
#define I40E_PRT_MNG_MAVTV_VID_SHIFT 0
-#define I40E_PRT_MNG_MAVTV_VID_MASK (0xFFF << I40E_PRT_MNG_MAVTV_VID_SHIFT)
-#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32))
+#define I40E_PRT_MNG_MAVTV_VID_MASK I40E_MASK(0xFFF, I40E_PRT_MNG_MAVTV_VID_SHIFT)
+#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEF_MAX_INDEX 7
#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4
-#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5
-#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK (0xFF << I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13
-#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17
-#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26
-#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29
-#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30
-#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31
-#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
-#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7
#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK (0xFFFF << I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29
-#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
-#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3
#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
-#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
+#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_METF_MAX_INDEX 3
#define I40E_PRT_MNG_METF_ETYPE_SHIFT 0
-#define I40E_PRT_MNG_METF_ETYPE_MASK (0xFFFF << I40E_PRT_MNG_METF_ETYPE_SHIFT)
+#define I40E_PRT_MNG_METF_ETYPE_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_METF_ETYPE_SHIFT)
#define I40E_PRT_MNG_METF_POLARITY_SHIFT 30
-#define I40E_PRT_MNG_METF_POLARITY_MASK (0x1 << I40E_PRT_MNG_METF_POLARITY_SHIFT)
-#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_METF_POLARITY_MASK I40E_MASK(0x1, I40E_PRT_MNG_METF_POLARITY_SHIFT)
+#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
#define I40E_PRT_MNG_MFUTP_MAX_INDEX 15
#define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0
-#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK (0xFFFF << I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
#define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16
-#define I40E_PRT_MNG_MFUTP_UDP_MASK (0x1 << I40E_PRT_MNG_MFUTP_UDP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_UDP_SHIFT)
#define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17
-#define I40E_PRT_MNG_MFUTP_TCP_MASK (0x1 << I40E_PRT_MNG_MFUTP_TCP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_TCP_SHIFT)
#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18
-#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK (0x1 << I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
-#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
+#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3
#define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
#define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15
#define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MMAH_MAX_INDEX 3
#define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0
-#define I40E_PRT_MNG_MMAH_MMAH_MASK (0xFFFF << I40E_PRT_MNG_MMAH_MMAH_SHIFT)
-#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAH_MMAH_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MMAH_MMAH_SHIFT)
+#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MMAL_MAX_INDEX 3
#define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0
-#define I40E_PRT_MNG_MMAL_MMAL_MASK (0xFFFFFFFF << I40E_PRT_MNG_MMAL_MMAL_SHIFT)
-#define I40E_PRT_MNG_MNGONLY 0x00256A60
+#define I40E_PRT_MNG_MMAL_MMAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MMAL_MMAL_SHIFT)
+#define I40E_PRT_MNG_MNGONLY 0x00256A60 /* Reset: POR */
#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0
-#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK (0xFF << I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
-#define I40E_PRT_MNG_MSFM 0x00256AA0
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
+#define I40E_PRT_MNG_MSFM 0x00256AA0 /* Reset: POR */
#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0
-#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1
-#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2
-#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3
-#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4
-#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5
-#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6
-#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7
-#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
-#define I40E_MSIX_PBA(_i) (0x00004900 + ((_i) * 4)) /* _i=0...5 */
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
+#define I40E_MSIX_PBA(_i) (0x00001000 + ((_i) * 4)) /* _i=0...5 */ /* Reset: FLR */
#define I40E_MSIX_PBA_MAX_INDEX 5
#define I40E_MSIX_PBA_PENBIT_SHIFT 0
-#define I40E_MSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_MSIX_PBA_PENBIT_SHIFT)
-#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_PBA_PENBIT_SHIFT)
+#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TADD_MAX_INDEX 128
#define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_MSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_MSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_MSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_MSIX_TADD_MSIXTADD10_SHIFT)
#define I40E_MSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_MSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_MSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_MSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TMSG_MAX_INDEX 128
#define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_MSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TUADD_MAX_INDEX 128
#define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_MSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TVCTRL_MAX_INDEX 128
#define I40E_MSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_MSIX_TVCTRL_MASK_MASK (0x1 << I40E_MSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFMSIX_PBA1(_i) (0x00004944 + ((_i) * 4)) /* _i=0...19 */
+#define I40E_MSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_MSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */
#define I40E_VFMSIX_PBA1_MAX_INDEX 19
#define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA1_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA1_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TADD1_MAX_INDEX 639
#define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
#define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD1_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TMSG1_MAX_INDEX 639
#define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TUADD1_MAX_INDEX 639
#define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
#define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL1_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
-#define I40E_GLNVM_FLA 0x000B6108
+#define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
+#define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */
#define I40E_GLNVM_FLA_FL_SCK_SHIFT 0
-#define I40E_GLNVM_FLA_FL_SCK_MASK (0x1 << I40E_GLNVM_FLA_FL_SCK_SHIFT)
+#define I40E_GLNVM_FLA_FL_SCK_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SCK_SHIFT)
#define I40E_GLNVM_FLA_FL_CE_SHIFT 1
-#define I40E_GLNVM_FLA_FL_CE_MASK (0x1 << I40E_GLNVM_FLA_FL_CE_SHIFT)
+#define I40E_GLNVM_FLA_FL_CE_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_CE_SHIFT)
#define I40E_GLNVM_FLA_FL_SI_SHIFT 2
-#define I40E_GLNVM_FLA_FL_SI_MASK (0x1 << I40E_GLNVM_FLA_FL_SI_SHIFT)
+#define I40E_GLNVM_FLA_FL_SI_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SI_SHIFT)
#define I40E_GLNVM_FLA_FL_SO_SHIFT 3
-#define I40E_GLNVM_FLA_FL_SO_MASK (0x1 << I40E_GLNVM_FLA_FL_SO_SHIFT)
+#define I40E_GLNVM_FLA_FL_SO_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SO_SHIFT)
#define I40E_GLNVM_FLA_FL_REQ_SHIFT 4
-#define I40E_GLNVM_FLA_FL_REQ_MASK (0x1 << I40E_GLNVM_FLA_FL_REQ_SHIFT)
+#define I40E_GLNVM_FLA_FL_REQ_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_REQ_SHIFT)
#define I40E_GLNVM_FLA_FL_GNT_SHIFT 5
-#define I40E_GLNVM_FLA_FL_GNT_MASK (0x1 << I40E_GLNVM_FLA_FL_GNT_SHIFT)
+#define I40E_GLNVM_FLA_FL_GNT_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_GNT_SHIFT)
#define I40E_GLNVM_FLA_LOCKED_SHIFT 6
-#define I40E_GLNVM_FLA_LOCKED_MASK (0x1 << I40E_GLNVM_FLA_LOCKED_SHIFT)
+#define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SHIFT)
#define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18
-#define I40E_GLNVM_FLA_FL_SADDR_MASK (0x7FF << I40E_GLNVM_FLA_FL_SADDR_SHIFT)
+#define I40E_GLNVM_FLA_FL_SADDR_MASK I40E_MASK(0x7FF, I40E_GLNVM_FLA_FL_SADDR_SHIFT)
#define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30
-#define I40E_GLNVM_FLA_FL_BUSY_MASK (0x1 << I40E_GLNVM_FLA_FL_BUSY_SHIFT)
+#define I40E_GLNVM_FLA_FL_BUSY_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_BUSY_SHIFT)
#define I40E_GLNVM_FLA_FL_DER_SHIFT 31
-#define I40E_GLNVM_FLA_FL_DER_MASK (0x1 << I40E_GLNVM_FLA_FL_DER_SHIFT)
-#define I40E_GLNVM_FLASHID 0x000B6104
+#define I40E_GLNVM_FLA_FL_DER_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_DER_SHIFT)
+#define I40E_GLNVM_FLASHID 0x000B6104 /* Reset: POR */
#define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0
-#define I40E_GLNVM_FLASHID_FLASHID_MASK (0xFFFFFF << I40E_GLNVM_FLASHID_FLASHID_SHIFT)
-#define I40E_GLNVM_GENS 0x000B6100
+#define I40E_GLNVM_FLASHID_FLASHID_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_FLASHID_FLASHID_SHIFT)
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT 31
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_MASK I40E_MASK(0x1, I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT)
+#define I40E_GLNVM_GENS 0x000B6100 /* Reset: POR */
#define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0
-#define I40E_GLNVM_GENS_NVM_PRES_MASK (0x1 << I40E_GLNVM_GENS_NVM_PRES_SHIFT)
+#define I40E_GLNVM_GENS_NVM_PRES_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_NVM_PRES_SHIFT)
#define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5
-#define I40E_GLNVM_GENS_SR_SIZE_MASK (0x7 << I40E_GLNVM_GENS_SR_SIZE_SHIFT)
+#define I40E_GLNVM_GENS_SR_SIZE_MASK I40E_MASK(0x7, I40E_GLNVM_GENS_SR_SIZE_SHIFT)
#define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8
-#define I40E_GLNVM_GENS_BANK1VAL_MASK (0x1 << I40E_GLNVM_GENS_BANK1VAL_SHIFT)
+#define I40E_GLNVM_GENS_BANK1VAL_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_BANK1VAL_SHIFT)
#define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23
-#define I40E_GLNVM_GENS_ALT_PRST_MASK (0x1 << I40E_GLNVM_GENS_ALT_PRST_SHIFT)
+#define I40E_GLNVM_GENS_ALT_PRST_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_ALT_PRST_SHIFT)
#define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25
-#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK (0x1 << I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
-#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */
+#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
+#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */ /* Reset: POR */
#define I40E_GLNVM_PROTCSR_MAX_INDEX 59
#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0
-#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK (0xFFFFFF << I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
-#define I40E_GLNVM_SRCTL 0x000B6110
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
+#define I40E_GLNVM_SRCTL 0x000B6110 /* Reset: POR */
#define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0
-#define I40E_GLNVM_SRCTL_SRBUSY_MASK (0x1 << I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
+#define I40E_GLNVM_SRCTL_SRBUSY_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
#define I40E_GLNVM_SRCTL_ADDR_SHIFT 14
-#define I40E_GLNVM_SRCTL_ADDR_MASK (0x7FFF << I40E_GLNVM_SRCTL_ADDR_SHIFT)
+#define I40E_GLNVM_SRCTL_ADDR_MASK I40E_MASK(0x7FFF, I40E_GLNVM_SRCTL_ADDR_SHIFT)
#define I40E_GLNVM_SRCTL_WRITE_SHIFT 29
-#define I40E_GLNVM_SRCTL_WRITE_MASK (0x1 << I40E_GLNVM_SRCTL_WRITE_SHIFT)
+#define I40E_GLNVM_SRCTL_WRITE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_WRITE_SHIFT)
#define I40E_GLNVM_SRCTL_START_SHIFT 30
-#define I40E_GLNVM_SRCTL_START_MASK (0x1 << I40E_GLNVM_SRCTL_START_SHIFT)
+#define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT)
#define I40E_GLNVM_SRCTL_DONE_SHIFT 31
-#define I40E_GLNVM_SRCTL_DONE_MASK (0x1 << I40E_GLNVM_SRCTL_DONE_SHIFT)
-#define I40E_GLNVM_SRDATA 0x000B6114
+#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT)
+#define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */
#define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0
-#define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
+#define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT)
#define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
-#define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
-#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_SRDATA_RDDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008 /* Reset: POR */
#define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
-#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
-#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
-#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
-#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
-#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
-#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
-#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
-#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
-#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
-#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
-
-#define I40E_GLPCI_BYTCTH 0x0009C484
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+#define I40E_GLPCI_BYTCTH 0x0009C484 /* Reset: PCIR */
#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_BYTCTL 0x0009C488
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_BYTCTL 0x0009C488 /* Reset: PCIR */
#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_CAPCTRL 0x000BE4A4
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_CAPCTRL 0x000BE4A4 /* Reset: PCIR */
#define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0
-#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK (0x1 << I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
-#define I40E_GLPCI_CAPSUP 0x000BE4A8
+#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP 0x000BE4A8 /* Reset: PCIR */
#define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0
-#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK (0x1 << I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
+#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
#define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2
-#define I40E_GLPCI_CAPSUP_LTR_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_LTR_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3
-#define I40E_GLPCI_CAPSUP_TPH_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_TPH_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4
-#define I40E_GLPCI_CAPSUP_ARI_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ARI_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5
-#define I40E_GLPCI_CAPSUP_IOV_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IOV_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6
-#define I40E_GLPCI_CAPSUP_ACS_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ACS_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7
-#define I40E_GLPCI_CAPSUP_SEC_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_SEC_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16
-#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17
-#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18
-#define I40E_GLPCI_CAPSUP_IDO_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IDO_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19
-#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK (0x1 << I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
+#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20
-#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30
-#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31
-#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
-#define I40E_GLPCI_CNF 0x000BE4C0
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
+#define I40E_GLPCI_CNF 0x000BE4C0 /* Reset: POR */
#define I40E_GLPCI_CNF_FLEX10_SHIFT 1
-#define I40E_GLPCI_CNF_FLEX10_MASK (0x1 << I40E_GLPCI_CNF_FLEX10_SHIFT)
+#define I40E_GLPCI_CNF_FLEX10_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_FLEX10_SHIFT)
#define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2
-#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK (0x1 << I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
-#define I40E_GLPCI_CNF2 0x000BE494
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
+#define I40E_GLPCI_CNF2 0x000BE494 /* Reset: PCIR */
#define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0
-#define I40E_GLPCI_CNF2_RO_DIS_MASK (0x1 << I40E_GLPCI_CNF2_RO_DIS_SHIFT)
+#define I40E_GLPCI_CNF2_RO_DIS_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_RO_DIS_SHIFT)
#define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1
-#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK (0x1 << I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
#define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2
-#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
#define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13
-#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
-#define I40E_GLPCI_DREVID 0x0009C480
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
+#define I40E_GLPCI_DREVID 0x0009C480 /* Reset: PCIR */
#define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0
-#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK (0xFF << I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
-#define I40E_GLPCI_GSCL_1 0x0009C48C
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
+#define I40E_GLPCI_GSCL_1 0x0009C48C /* Reset: PCIR */
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28
-#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
-#define I40E_GLPCI_GSCL_2 0x0009C490
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
+#define I40E_GLPCI_GSCL_2 0x0009C490 /* Reset: PCIR */
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
-#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
+#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
#define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3
#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0
-#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16
-#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
-#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
+#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
#define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3
#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0
-#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK (0xFFFFFFFF << I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
-#define I40E_GLPCI_LATCT 0x0009C4B4
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
+#define I40E_GLPCI_LATCT 0x0009C4B4 /* Reset: PCIR */
#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT 0
-#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK (0xFFFFFFFF << I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
-#define I40E_GLPCI_LBARCTRL 0x000BE484
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
+#define I40E_GLPCI_LBARCTRL 0x000BE484 /* Reset: POR */
#define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0
-#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK (0x1 << I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
+#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
#define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1
-#define I40E_GLPCI_LBARCTRL_BAR32_MASK (0x1 << I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
+#define I40E_GLPCI_LBARCTRL_BAR32_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3
-#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK (0x1 << I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT 4
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_MASK (0x3 << I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT 4
+#define I40E_GLPCI_LBARCTRL_RSVD_4_MASK I40E_MASK(0x3, I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT)
#define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6
-#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT 10
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_MASK (0x1 << I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT 10
+#define I40E_GLPCI_LBARCTRL_RSVD_10_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT)
#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11
-#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
-#define I40E_GLPCI_LINKCAP 0x000BE4AC
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
+#define I40E_GLPCI_LINKCAP 0x000BE4AC /* Reset: PCIR */
#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0
-#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK (0x3F << I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK I40E_MASK(0x3F, I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6
-#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK (0x7 << I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK I40E_MASK(0x7, I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9
-#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK (0xF << I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
-#define I40E_GLPCI_PCIERR 0x000BE4FC
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK I40E_MASK(0xF, I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
+#define I40E_GLPCI_PCIERR 0x000BE4FC /* Reset: PCIR */
#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
-#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
-#define I40E_GLPCI_PCITEST2 0x000BE4BC
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
-
-#define I40E_GLPCI_PKTCT 0x0009C4BC
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PKTCT 0x0009C4BC /* Reset: PCIR */
#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
-#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
-#define I40E_GLPCI_PMSUP 0x000BE4B0
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PMSUP 0x000BE4B0 /* Reset: PCIR */
#define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0
-#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
+#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2
-#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5
-#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8
-#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11
-#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14
-#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK (0x1 << I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
+#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK I40E_MASK(0x1, I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
#define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15
-#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
-#define I40E_GLPCI_PWRDATA 0x000BE490
+#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC /* Reset: PCIR */
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
+#define I40E_GLPCI_PWRDATA 0x000BE490 /* Reset: PCIR */
#define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0
-#define I40E_GLPCI_PWRDATA_D0_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D0_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8
-#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16
-#define I40E_GLPCI_PWRDATA_D3_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D3_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24
-#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK (0x3 << I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
-#define I40E_GLPCI_REVID 0x000BE4B4
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK I40E_MASK(0x3, I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
+#define I40E_GLPCI_REVID 0x000BE4B4 /* Reset: PCIR */
#define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0
-#define I40E_GLPCI_REVID_NVM_REVID_MASK (0xFF << I40E_GLPCI_REVID_NVM_REVID_SHIFT)
-#define I40E_GLPCI_SERH 0x000BE49C
+#define I40E_GLPCI_REVID_NVM_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_REVID_NVM_REVID_SHIFT)
+#define I40E_GLPCI_SERH 0x000BE49C /* Reset: PCIR */
#define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0
-#define I40E_GLPCI_SERH_SER_NUM_H_MASK (0xFFFF << I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
-#define I40E_GLPCI_SERL 0x000BE498
+#define I40E_GLPCI_SERH_SER_NUM_H_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
+#define I40E_GLPCI_SERL 0x000BE498 /* Reset: PCIR */
#define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0
-#define I40E_GLPCI_SERL_SER_NUM_L_MASK (0xFFFFFFFF << I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
-#define I40E_GLPCI_SUBSYSID 0x000BE48C
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT 0
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT)
-#define I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT 16
-#define I40E_GLPCI_SUBSYSID_SUB_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT)
-#define I40E_GLPCI_UPADD 0x000BE4F8
+#define I40E_GLPCI_SERL_SER_NUM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SUBVENID 0x000BE48C /* Reset: PCIR */
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT 0
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT)
+#define I40E_GLPCI_UPADD 0x000BE4F8 /* Reset: PCIR */
#define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1
-#define I40E_GLPCI_UPADD_ADDRESS_MASK (0x7FFFFFFF << I40E_GLPCI_UPADD_ADDRESS_SHIFT)
-#define I40E_GLPCI_VFSUP 0x000BE4B8
+#define I40E_GLPCI_UPADD_ADDRESS_MASK I40E_MASK(0x7FFFFFFF, I40E_GLPCI_UPADD_ADDRESS_SHIFT)
+#define I40E_GLPCI_VENDORID 0x000BE518 /* Reset: PCIR */
+#define I40E_GLPCI_VENDORID_VENDORID_SHIFT 0
+#define I40E_GLPCI_VENDORID_VENDORID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_VENDORID_VENDORID_SHIFT)
+#define I40E_GLPCI_VFSUP 0x000BE4B8 /* Reset: PCIR */
#define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0
-#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK (0x1 << I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1
-#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK (0x1 << I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
-#define I40E_PF_FUNC_RID 0x0009C000
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
+#define I40E_PF_FUNC_RID 0x0009C000 /* Reset: PCIR */
#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0
-#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK (0x7 << I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK I40E_MASK(0x7, I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
#define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3
-#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK (0x1F << I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK I40E_MASK(0x1F, I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
#define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8
-#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK (0xFF << I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
-#define I40E_PF_PCI_CIAA 0x0009C080
+#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK I40E_MASK(0xFF, I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
+#define I40E_PF_PCI_CIAA 0x0009C080 /* Reset: FLR */
#define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0
-#define I40E_PF_PCI_CIAA_ADDRESS_MASK (0xFFF << I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
+#define I40E_PF_PCI_CIAA_ADDRESS_MASK I40E_MASK(0xFFF, I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
#define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12
-#define I40E_PF_PCI_CIAA_VF_NUM_MASK (0x7F << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
-#define I40E_PF_PCI_CIAD 0x0009C100
+#define I40E_PF_PCI_CIAA_VF_NUM_MASK I40E_MASK(0x7F, I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
+#define I40E_PF_PCI_CIAD 0x0009C100 /* Reset: FLR */
#define I40E_PF_PCI_CIAD_DATA_SHIFT 0
-#define I40E_PF_PCI_CIAD_DATA_MASK (0xFFFFFFFF << I40E_PF_PCI_CIAD_DATA_SHIFT)
-#define I40E_PFPCI_CLASS 0x000BE400
+#define I40E_PF_PCI_CIAD_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_PCI_CIAD_DATA_SHIFT)
+#define I40E_PFPCI_CLASS 0x000BE400 /* Reset: PCIR */
#define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0
-#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK (0x1 << I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
-#define I40E_PFPCI_CNF 0x000BE000
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
+#define I40E_PFPCI_CLASS_RESERVED_1_SHIFT 1
+#define I40E_PFPCI_CLASS_RESERVED_1_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_RESERVED_1_SHIFT)
+#define I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT 2
+#define I40E_PFPCI_CLASS_PF_IS_LAN_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT)
+#define I40E_PFPCI_CNF 0x000BE000 /* Reset: PCIR */
#define I40E_PFPCI_CNF_MSI_EN_SHIFT 2
-#define I40E_PFPCI_CNF_MSI_EN_MASK (0x1 << I40E_PFPCI_CNF_MSI_EN_SHIFT)
+#define I40E_PFPCI_CNF_MSI_EN_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_MSI_EN_SHIFT)
#define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3
-#define I40E_PFPCI_CNF_EXROM_DIS_MASK (0x1 << I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
+#define I40E_PFPCI_CNF_EXROM_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
#define I40E_PFPCI_CNF_IO_BAR_SHIFT 4
-#define I40E_PFPCI_CNF_IO_BAR_MASK (0x1 << I40E_PFPCI_CNF_IO_BAR_SHIFT)
+#define I40E_PFPCI_CNF_IO_BAR_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_IO_BAR_SHIFT)
#define I40E_PFPCI_CNF_INT_PIN_SHIFT 5
-#define I40E_PFPCI_CNF_INT_PIN_MASK (0x3 << I40E_PFPCI_CNF_INT_PIN_SHIFT)
-#define I40E_PFPCI_FACTPS 0x0009C180
+#define I40E_PFPCI_CNF_INT_PIN_MASK I40E_MASK(0x3, I40E_PFPCI_CNF_INT_PIN_SHIFT)
+#define I40E_PFPCI_DEVID 0x000BE080 /* Reset: PCIR */
+#define I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT 0
+#define I40E_PFPCI_DEVID_PF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT)
+#define I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT 16
+#define I40E_PFPCI_DEVID_VF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT)
+#define I40E_PFPCI_FACTPS 0x0009C180 /* Reset: FLR */
#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0
-#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK (0x3 << I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK I40E_MASK(0x3, I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3
-#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK (0x1 << I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
-#define I40E_PFPCI_FUNC 0x000BE200
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK I40E_MASK(0x1, I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
+#define I40E_PFPCI_FUNC 0x000BE200 /* Reset: POR */
#define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1
-#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2
-#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK (0x1 << I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
-#define I40E_PFPCI_FUNC2 0x000BE180
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
+#define I40E_PFPCI_FUNC2 0x000BE180 /* Reset: PCIR */
#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
-#define I40E_PFPCI_ICAUSE 0x0009C200
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_ICAUSE 0x0009C200 /* Reset: PFR */
#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0
-#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK (0xFFFFFFFF << I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
-#define I40E_PFPCI_IENA 0x0009C280
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
+#define I40E_PFPCI_IENA 0x0009C280 /* Reset: PFR */
#define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0
-#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK (0xFFFFFFFF << I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
-#define I40E_PFPCI_PFDEVID 0x000BE080
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_PM 0x000BE300
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
+#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800 /* Reset: PCIR */
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_PM 0x000BE300 /* Reset: POR */
#define I40E_PFPCI_PM_PME_EN_SHIFT 0
-#define I40E_PFPCI_PM_PME_EN_MASK (0x1 << I40E_PFPCI_PM_PME_EN_SHIFT)
-#define I40E_PFPCI_STATUS1 0x000BE280
+#define I40E_PFPCI_PM_PME_EN_MASK I40E_MASK(0x1, I40E_PFPCI_PM_PME_EN_SHIFT)
+#define I40E_PFPCI_STATUS1 0x000BE280 /* Reset: POR */
#define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0
-#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK (0x1 << I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
-#define I40E_PFPCI_VFDEVID 0x000BE100
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_VMINDEX 0x0009C300
+#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK I40E_MASK(0x1, I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
+#define I40E_PFPCI_SUBSYSID 0x000BE100 /* Reset: PCIR */
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT 0
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT 16
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE 0x0000E400 /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 /* Reset: PCIR */
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VMINDEX 0x0009C300 /* Reset: PCIR */
#define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0
-#define I40E_PFPCI_VMINDEX_VMINDEX_MASK (0x1FF << I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
-#define I40E_PFPCI_VMPEND 0x0009C380
+#define I40E_PFPCI_VMINDEX_VMINDEX_MASK I40E_MASK(0x1FF, I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
+#define I40E_PFPCI_VMPEND 0x0009C380 /* Reset: PCIR */
#define I40E_PFPCI_VMPEND_PENDING_SHIFT 0
-#define I40E_PFPCI_VMPEND_PENDING_MASK (0x1 << I40E_PFPCI_VMPEND_PENDING_SHIFT)
-#define I40E_GLPE_CPUSTATUS0 0x0000D040
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT 0
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT)
-#define I40E_GLPE_CPUSTATUS1 0x0000D044
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT 0
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT)
-#define I40E_GLPE_CPUSTATUS2 0x0000D048
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT 0
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL(_i) (0x0000D480 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPE_PFFLMOBJCTRL_MAX_INDEX 15
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMOBJCTRL_MAX_INDEX 31
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMQ1ALLOCERR(_i) (0x0000C700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMQ1ALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFFLMXMITALLOCERR(_i) (0x0000C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMXMITALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFUDACTRL(_i) (0x0000C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDACTRL_MAX_INDEX 31
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN(_i) (0x0000C100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDAUCFBQPN_MAX_INDEX 31
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT 0
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT 31
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_MASK (0x1 << I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_AEQALLOC 0x00131180
-#define I40E_PFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_PFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_PFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_PFPE_CCQPHIGH 0x00008200
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_PFPE_CCQPLOW 0x00008180
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_PFPE_CCQPSTATUS 0x00008100
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_PFPE_CQACK 0x00131100
-#define I40E_PFPE_CQACK_PECQID_SHIFT 0
-#define I40E_PFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_PFPE_CQACK_PECQID_SHIFT)
-#define I40E_PFPE_CQARM 0x00131080
-#define I40E_PFPE_CQARM_PECQID_SHIFT 0
-#define I40E_PFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_PFPE_CQARM_PECQID_SHIFT)
-#define I40E_PFPE_CQPDB 0x00008000
-#define I40E_PFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_PFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_PFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_PFPE_CQPERRCODES 0x00008880
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_PFPE_CQPTAIL 0x00008080
-#define I40E_PFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_PFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_PFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_PFPE_FLMQ1ALLOCERR 0x00008980
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_FLMXMITALLOCERR 0x00008900
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_IPCONFIG0 0x00008280
-#define I40E_PFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-
-#define I40E_PFPE_MRTEIDXMASK 0x00008600
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_PFPE_RCVUNEXPECTEDERROR 0x00008680
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_PFPE_TCPNOWTIMER 0x00008580
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_PFPE_UDACTRL 0x00008700
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN 0x00008780
-#define I40E_PFPE_UDAUCFBQPN_QPN_SHIFT 0
-#define I40E_PFPE_UDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_PFPE_UDAUCFBQPN_QPN_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN_VALID_SHIFT 31
-#define I40E_PFPE_UDAUCFBQPN_VALID_MASK (0x1 << I40E_PFPE_UDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_WQEALLOC 0x00138C00
-#define I40E_PFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_PFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_PFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFPE_AEQALLOC(_VF) (0x00130C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_AEQALLOC_MAX_INDEX 127
-#define I40E_VFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH(_VF) (0x00001000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPHIGH_MAX_INDEX 127
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW(_VF) (0x00000C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPLOW_MAX_INDEX 127
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS(_VF) (0x00000800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPSTATUS_MAX_INDEX 127
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK(_VF) (0x00130800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQACK_MAX_INDEX 127
-#define I40E_VFPE_CQACK_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK_PECQID_SHIFT)
-#define I40E_VFPE_CQARM(_VF) (0x00130400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQARM_MAX_INDEX 127
-#define I40E_VFPE_CQARM_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB(_VF) (0x00000000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPDB_MAX_INDEX 127
-#define I40E_VFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES(_VF) (0x00001800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPERRCODES_MAX_INDEX 127
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL(_VF) (0x00000400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPTAIL_MAX_INDEX 127
-#define I40E_VFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG0(_VF) (0x00001400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_IPCONFIG0_MAX_INDEX 127
-#define I40E_VFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR(_VF) (0x00003400 + ((_VF) * 4))
-#define I40E_VFPE_RCVUNEXPECTEDERROR_MAX_INDEX 127
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER(_VF) (0x00002C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_TCPNOWTIMER_MAX_INDEX 127
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC(_VF) (0x00138000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_WQEALLOC_MAX_INDEX 127
-#define I40E_VFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_GLPES_PFIP4RXDISCARD(_i) (0x00010600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSHI(_i) (0x00010804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSLO(_i) (0x00010800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSHI(_i) (0x00010A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSLO(_i) (0x00010A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSHI(_i) (0x00010C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSLO(_i) (0x00010C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSHI(_i) (0x00010204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSLO(_i) (0x00010200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSHI(_i) (0x00010404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSLO(_i) (0x00010400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXTRUNC(_i) (0x00010700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSHI(_i) (0x00011E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSLO(_i) (0x00011E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSHI(_i) (0x00012004 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSLO(_i) (0x00012000 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSHI(_i) (0x00012204 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSLO(_i) (0x00012200 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXNOROUTE(_i) (0x00012E00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSHI(_i) (0x00011A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSLO(_i) (0x00011A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSHI(_i) (0x00011C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSLO(_i) (0x00011C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXDISCARD(_i) (0x00011200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSHI(_i) (0x00011404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSLO(_i) (0x00011400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSHI(_i) (0x00011604 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSLO(_i) (0x00011600 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSHI(_i) (0x00011804 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSLO(_i) (0x00011800 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSHI(_i) (0x00010E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSLO(_i) (0x00010E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSHI(_i) (0x00011004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSLO(_i) (0x00011000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXTRUNC(_i) (0x00011300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSHI(_i) (0x00012804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSLO(_i) (0x00012800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSHI(_i) (0x00012A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSLO(_i) (0x00012A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSHI(_i) (0x00012C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSLO(_i) (0x00012C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXNOROUTE(_i) (0x00012F00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSHI(_i) (0x00012404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSLO(_i) (0x00012400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSHI(_i) (0x00012604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSLO(_i) (0x00012600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSHI(_i) (0x00013E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSLO(_i) (0x00013E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSHI(_i) (0x00014004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSLO(_i) (0x00014000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSHI(_i) (0x00013C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSLO(_i) (0x00013C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSHI(_i) (0x00014404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSLO(_i) (0x00014400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSHI(_i) (0x00014604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSLO(_i) (0x00014600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSHI(_i) (0x00014204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSLO(_i) (0x00014200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDHI(_i) (0x00014804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDLO(_i) (0x00014800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_PFRDMAVINVHI(_i) (0x00014A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_PFRDMAVINVLO(_i) (0x00014A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_PFRXVLANERR(_i) (0x00010000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFRXVLANERR_MAX_INDEX 15
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_PFTCPRTXSEG(_i) (0x00013600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRTXSEG_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_PFTCPRXOPTERR(_i) (0x00013200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXOPTERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_PFTCPRXPROTOERR(_i) (0x00013300 + ((_i) * 4))
-#define I40E_GLPES_PFTCPRXPROTOERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSHI(_i) (0x00013004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSLO(_i) (0x00013000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGHI(_i) (0x00013404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGLO(_i) (0x00013400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSHI(_i) (0x00013804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSLO(_i) (0x00013800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSHI(_i) (0x00013A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSLO(_i) (0x00013A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSHI 0x0001E014
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSLO 0x0001E010
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPHI 0x0001E01C
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPLO 0x0001E018
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT)
-#define I40E_GLPES_RDMARXOOONOMARK 0x0001E004
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT 0
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT)
-#define I40E_GLPES_RDMARXUNALIGN 0x0001E000
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT 0
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLEHI 0x0001E044
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLELO 0x0001E040
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLEHI 0x0001E02C
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLELO 0x0001E028
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKHI 0x0001E024
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKSLO 0x0001E020
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLEHI 0x0001E03C
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLELO 0x0001E038
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLEHI 0x0001E034
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLELO 0x0001E030
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXUNEXPERR 0x0001E008
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT 0
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_MASK (0xFFFFFF << I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTHI 0x0001E04C
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTLO 0x0001E048
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTHI 0x0001E054
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTLO 0x0001E050
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSHI 0x0001E05C
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSLO 0x0001E058
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXDISCARD(_i) (0x00018600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSHI(_i) (0x00018804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSLO(_i) (0x00018800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSHI(_i) (0x00018A04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSLO(_i) (0x00018A00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSHI(_i) (0x00018C04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSLO(_i) (0x00018C00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSHI(_i) (0x00018204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSLO(_i) (0x00018200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSHI(_i) (0x00018404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSLO(_i) (0x00018400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXTRUNC(_i) (0x00018700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSHI(_i) (0x00019E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSLO(_i) (0x00019E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSHI(_i) (0x0001A004 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSLO(_i) (0x0001A000 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSHI(_i) (0x0001A204 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSLO(_i) (0x0001A200 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXNOROUTE(_i) (0x0001AE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSHI(_i) (0x00019A04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSLO(_i) (0x00019A00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSHI(_i) (0x00019C04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSLO(_i) (0x00019C00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXDISCARD(_i) (0x00019200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSHI(_i) (0x00019404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSLO(_i) (0x00019400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSHI(_i) (0x00019604 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSLO(_i) (0x00019600 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSHI(_i) (0x00019804 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSLO(_i) (0x00019800 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSHI(_i) (0x00018E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSLO(_i) (0x00018E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSHI(_i) (0x00019004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSLO(_i) (0x00019000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXTRUNC(_i) (0x00019300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSHI(_i) (0x0001A804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSLO(_i) (0x0001A800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSHI(_i) (0x0001AA04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSLO(_i) (0x0001AA00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSHI(_i) (0x0001AC04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSLO(_i) (0x0001AC00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXNOROUTE(_i) (0x0001AF00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSHI(_i) (0x0001A404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSLO(_i) (0x0001A400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSHI(_i) (0x0001A604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSLO(_i) (0x0001A600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSHI(_i) (0x0001BE04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSLO(_i) (0x0001BE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSHI(_i) (0x0001C004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSLO(_i) (0x0001C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSHI(_i) (0x0001BC04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSLO(_i) (0x0001BC00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSHI(_i) (0x0001C404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSLO(_i) (0x0001C400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSHI(_i) (0x0001C604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSLO(_i) (0x0001C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSHI(_i) (0x0001C204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSLO(_i) (0x0001C200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDHI(_i) (0x0001C804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDLO(_i) (0x0001C800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_VFRDMAVINVHI(_i) (0x0001CA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_VFRDMAVINVLO(_i) (0x0001CA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_VFRXVLANERR(_i) (0x00018000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRXVLANERR_MAX_INDEX 31
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_VFTCPRTXSEG(_i) (0x0001B600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRTXSEG_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_VFTCPRXOPTERR(_i) (0x0001B200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXOPTERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_VFTCPRXPROTOERR(_i) (0x0001B300 + ((_i) * 4))
-#define I40E_GLPES_VFTCPRXPROTOERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSHI(_i) (0x0001B004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSLO(_i) (0x0001B000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGHI(_i) (0x0001B404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGLO(_i) (0x0001B400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSHI(_i) (0x0001B804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSLO(_i) (0x0001B800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSHI(_i) (0x0001BA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSLO(_i) (0x0001BA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_PRTPM_EEE_STAT 0x001E4320
+#define I40E_PFPCI_VMPEND_PENDING_MASK I40E_MASK(0x1, I40E_PFPCI_VMPEND_PENDING_SHIFT)
+#define I40E_PRTPM_EEE_STAT 0x001E4320 /* Reset: GLOBR */
#define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
-#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30
-#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31
-#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
-#define I40E_PRTPM_EEEC 0x001E4380
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEEC 0x001E4380 /* Reset: GLOBR */
#define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16
-#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK (0x3F << I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24
-#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK (0x3 << I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK I40E_MASK(0x3, I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
#define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26
-#define I40E_PRTPM_EEEC_TEEE_DLY_MASK (0x3F << I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
-#define I40E_PRTPM_EEEFWD 0x001E4400
+#define I40E_PRTPM_EEEC_TEEE_DLY_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
+#define I40E_PRTPM_EEEFWD 0x001E4400 /* Reset: GLOBR */
#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31
-#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK (0x1 << I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
-#define I40E_PRTPM_EEER 0x001E4360
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK I40E_MASK(0x1, I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
+#define I40E_PRTPM_EEER 0x001E4360 /* Reset: GLOBR */
#define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0
-#define I40E_PRTPM_EEER_TW_SYSTEM_MASK (0xFFFF << I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
+#define I40E_PRTPM_EEER_TW_SYSTEM_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
#define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16
-#define I40E_PRTPM_EEER_TX_LPI_EN_MASK (0x1 << I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
-#define I40E_PRTPM_EEETXC 0x001E43E0
+#define I40E_PRTPM_EEER_TX_LPI_EN_MASK I40E_MASK(0x1, I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
+#define I40E_PRTPM_EEETXC 0x001E43E0 /* Reset: GLOBR */
#define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0
-#define I40E_PRTPM_EEETXC_TW_PHY_MASK (0xFFFF << I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
-#define I40E_PRTPM_GC 0x000B8140
+#define I40E_PRTPM_EEETXC_TW_PHY_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
+#define I40E_PRTPM_GC 0x000B8140 /* Reset: POR */
#define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0
-#define I40E_PRTPM_GC_EMP_LINK_ON_MASK (0x1 << I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
+#define I40E_PRTPM_GC_EMP_LINK_ON_MASK I40E_MASK(0x1, I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
#define I40E_PRTPM_GC_MNG_VETO_SHIFT 1
-#define I40E_PRTPM_GC_MNG_VETO_MASK (0x1 << I40E_PRTPM_GC_MNG_VETO_SHIFT)
+#define I40E_PRTPM_GC_MNG_VETO_MASK I40E_MASK(0x1, I40E_PRTPM_GC_MNG_VETO_SHIFT)
#define I40E_PRTPM_GC_RATD_SHIFT 2
-#define I40E_PRTPM_GC_RATD_MASK (0x1 << I40E_PRTPM_GC_RATD_SHIFT)
+#define I40E_PRTPM_GC_RATD_MASK I40E_MASK(0x1, I40E_PRTPM_GC_RATD_SHIFT)
#define I40E_PRTPM_GC_LCDMP_SHIFT 3
-#define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
+#define I40E_PRTPM_GC_LCDMP_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LCDMP_SHIFT)
#define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
-#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
-#define I40E_PRTPM_RLPIC 0x001E43A0
+#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
+#define I40E_PRTPM_RLPIC 0x001E43A0 /* Reset: GLOBR */
#define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
-#define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
-#define I40E_PRTPM_TLPIC 0x001E43C0
+#define I40E_PRTPM_RLPIC_ERLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
+#define I40E_PRTPM_TLPIC 0x001E43C0 /* Reset: GLOBR */
#define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0
-#define I40E_PRTPM_TLPIC_ETLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
-#define I40E_GLRPB_DPSS 0x000AC828
+#define I40E_PRTPM_TLPIC_ETLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
+#define I40E_GLRPB_DPSS 0x000AC828 /* Reset: CORER */
#define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0
-#define I40E_GLRPB_DPSS_DPS_TCN_MASK (0xFFFFF << I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
-#define I40E_GLRPB_GHW 0x000AC830
+#define I40E_GLRPB_DPSS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
+#define I40E_GLRPB_GHW 0x000AC830 /* Reset: CORER */
#define I40E_GLRPB_GHW_GHW_SHIFT 0
-#define I40E_GLRPB_GHW_GHW_MASK (0xFFFFF << I40E_GLRPB_GHW_GHW_SHIFT)
-#define I40E_GLRPB_GLW 0x000AC834
+#define I40E_GLRPB_GHW_GHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GHW_GHW_SHIFT)
+#define I40E_GLRPB_GLW 0x000AC834 /* Reset: CORER */
#define I40E_GLRPB_GLW_GLW_SHIFT 0
-#define I40E_GLRPB_GLW_GLW_MASK (0xFFFFF << I40E_GLRPB_GLW_GLW_SHIFT)
-#define I40E_GLRPB_PHW 0x000AC844
+#define I40E_GLRPB_GLW_GLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GLW_GLW_SHIFT)
+#define I40E_GLRPB_PHW 0x000AC844 /* Reset: CORER */
#define I40E_GLRPB_PHW_PHW_SHIFT 0
-#define I40E_GLRPB_PHW_PHW_MASK (0xFFFFF << I40E_GLRPB_PHW_PHW_SHIFT)
-#define I40E_GLRPB_PLW 0x000AC848
+#define I40E_GLRPB_PHW_PHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PHW_PHW_SHIFT)
+#define I40E_GLRPB_PLW 0x000AC848 /* Reset: CORER */
#define I40E_GLRPB_PLW_PLW_SHIFT 0
-#define I40E_GLRPB_PLW_PLW_MASK (0xFFFFF << I40E_GLRPB_PLW_PLW_SHIFT)
-#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_GLRPB_PLW_PLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PLW_PLW_SHIFT)
+#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DHW_MAX_INDEX 7
#define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0
-#define I40E_PRTRPB_DHW_DHW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
-#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DHW_DHW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
+#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DLW_MAX_INDEX 7
#define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0
-#define I40E_PRTRPB_DLW_DLW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
-#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DLW_DLW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
+#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DPS_MAX_INDEX 7
#define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0
-#define I40E_PRTRPB_DPS_DPS_TCN_MASK (0xFFFFF << I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
-#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DPS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
+#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_SHT_MAX_INDEX 7
#define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0
-#define I40E_PRTRPB_SHT_SHT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
-#define I40E_PRTRPB_SHW 0x000AC580
+#define I40E_PRTRPB_SHT_SHT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
+#define I40E_PRTRPB_SHW 0x000AC580 /* Reset: CORER */
#define I40E_PRTRPB_SHW_SHW_SHIFT 0
-#define I40E_PRTRPB_SHW_SHW_MASK (0xFFFFF << I40E_PRTRPB_SHW_SHW_SHIFT)
-#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SHW_SHW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHW_SHW_SHIFT)
+#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_SLT_MAX_INDEX 7
#define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0
-#define I40E_PRTRPB_SLT_SLT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
-#define I40E_PRTRPB_SLW 0x000AC6A0
+#define I40E_PRTRPB_SLT_SLT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
+#define I40E_PRTRPB_SLW 0x000AC6A0 /* Reset: CORER */
#define I40E_PRTRPB_SLW_SLW_SHIFT 0
-#define I40E_PRTRPB_SLW_SLW_MASK (0xFFFFF << I40E_PRTRPB_SLW_SLW_SHIFT)
-#define I40E_PRTRPB_SPS 0x000AC7C0
+#define I40E_PRTRPB_SLW_SLW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLW_SLW_SHIFT)
+#define I40E_PRTRPB_SPS 0x000AC7C0 /* Reset: CORER */
#define I40E_PRTRPB_SPS_SPS_SHIFT 0
-#define I40E_PRTRPB_SPS_SPS_MASK (0xFFFFF << I40E_PRTRPB_SPS_SPS_SHIFT)
-#define I40E_GLQF_APBVT(_i) (0x00260000 + ((_i) * 4)) /* _i=0...2047 */
-#define I40E_GLQF_APBVT_MAX_INDEX 2047
-#define I40E_GLQF_APBVT_APBVT_SHIFT 0
-#define I40E_GLQF_APBVT_APBVT_MASK (0xFFFFFFFF << I40E_GLQF_APBVT_APBVT_SHIFT)
-#define I40E_GLQF_CTL 0x00269BA4
+#define I40E_PRTRPB_SPS_SPS_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SPS_SPS_SHIFT)
+#define I40E_GLQF_CTL 0x00269BA4 /* Reset: CORER */
#define I40E_GLQF_CTL_HTOEP_SHIFT 1
-#define I40E_GLQF_CTL_HTOEP_MASK (0x1 << I40E_GLQF_CTL_HTOEP_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_SHIFT)
#define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2
-#define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_FCOE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
#define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
-#define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_PCNT_ALLOC_MASK I40E_MASK(0x7, I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT 6
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT)
#define I40E_GLQF_CTL_RSVD_SHIFT 7
-#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
+#define I40E_GLQF_CTL_RSVD_MASK I40E_MASK(0x1, I40E_GLQF_CTL_RSVD_SHIFT)
#define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
-#define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXPEBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
#define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
-#define I40E_GLQF_CTL_MAXFCBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFCBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
#define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14
-#define I40E_GLQF_CTL_MAXFDBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFDBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
#define I40E_GLQF_CTL_FDBEST_SHIFT 17
-#define I40E_GLQF_CTL_FDBEST_MASK (0xFF << I40E_GLQF_CTL_FDBEST_SHIFT)
+#define I40E_GLQF_CTL_FDBEST_MASK I40E_MASK(0xFF, I40E_GLQF_CTL_FDBEST_SHIFT)
#define I40E_GLQF_CTL_PROGPRIO_SHIFT 25
-#define I40E_GLQF_CTL_PROGPRIO_MASK (0x1 << I40E_GLQF_CTL_PROGPRIO_SHIFT)
+#define I40E_GLQF_CTL_PROGPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_PROGPRIO_SHIFT)
#define I40E_GLQF_CTL_INVALPRIO_SHIFT 26
-#define I40E_GLQF_CTL_INVALPRIO_MASK (0x1 << I40E_GLQF_CTL_INVALPRIO_SHIFT)
+#define I40E_GLQF_CTL_INVALPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_INVALPRIO_SHIFT)
#define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27
-#define I40E_GLQF_CTL_IGNORE_IP_MASK (0x1 << I40E_GLQF_CTL_IGNORE_IP_SHIFT)
-#define I40E_GLQF_FDCNT_0 0x00269BAC
+#define I40E_GLQF_CTL_IGNORE_IP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_IGNORE_IP_SHIFT)
+#define I40E_GLQF_FDCNT_0 0x00269BAC /* Reset: CORER */
#define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0
-#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
#define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13
-#define I40E_GLQF_FDCNT_0_BESTCNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
-#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */
+#define I40E_GLQF_FDCNT_0_BESTCNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
+#define I40E_GLQF_HKEY(_i) (0x00270140 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
+#define I40E_GLQF_HKEY_MAX_INDEX 12
+#define I40E_GLQF_HKEY_KEY_0_SHIFT 0
+#define I40E_GLQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_0_SHIFT)
+#define I40E_GLQF_HKEY_KEY_1_SHIFT 8
+#define I40E_GLQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_1_SHIFT)
+#define I40E_GLQF_HKEY_KEY_2_SHIFT 16
+#define I40E_GLQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_2_SHIFT)
+#define I40E_GLQF_HKEY_KEY_3_SHIFT 24
+#define I40E_GLQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_3_SHIFT)
+#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */ /* Reset: CORER */
#define I40E_GLQF_HSYM_MAX_INDEX 63
#define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0
-#define I40E_GLQF_HSYM_SYMH_ENA_MASK (0x1 << I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
-#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */
+#define I40E_GLQF_HSYM_SYMH_ENA_MASK I40E_MASK(0x1, I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
+#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_GLQF_PCNT_MAX_INDEX 511
#define I40E_GLQF_PCNT_PCNT_SHIFT 0
-#define I40E_GLQF_PCNT_PCNT_MASK (0xFFFFFFFF << I40E_GLQF_PCNT_PCNT_SHIFT)
-#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */
+#define I40E_GLQF_PCNT_PCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLQF_PCNT_PCNT_SHIFT)
+#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */ /* Reset: CORER */
#define I40E_GLQF_SWAP_MAX_INDEX 1
#define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0
-#define I40E_GLQF_SWAP_OFF0_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
#define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6
-#define I40E_GLQF_SWAP_OFF0_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
#define I40E_GLQF_SWAP_FLEN0_SHIFT 12
-#define I40E_GLQF_SWAP_FLEN0_MASK (0xF << I40E_GLQF_SWAP_FLEN0_SHIFT)
+#define I40E_GLQF_SWAP_FLEN0_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN0_SHIFT)
#define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16
-#define I40E_GLQF_SWAP_OFF1_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
#define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22
-#define I40E_GLQF_SWAP_OFF1_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
#define I40E_GLQF_SWAP_FLEN1_SHIFT 28
-#define I40E_GLQF_SWAP_FLEN1_MASK (0xF << I40E_GLQF_SWAP_FLEN1_SHIFT)
-#define I40E_PFQF_CTL_0 0x001C0AC0
+#define I40E_GLQF_SWAP_FLEN1_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN1_SHIFT)
+#define I40E_PFQF_CTL_0 0x001C0AC0 /* Reset: CORER */
#define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0
-#define I40E_PFQF_CTL_0_PEHSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEHSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5
-#define I40E_PFQF_CTL_0_PEDSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEDSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10
-#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14
-#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
#define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16
-#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK (0x1 << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
#define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17
-#define I40E_PFQF_CTL_0_FD_ENA_MASK (0x1 << I40E_PFQF_CTL_0_FD_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_FD_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_FD_ENA_SHIFT)
#define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18
-#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK (0x1 << I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
#define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19
-#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK (0x1 << I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
#define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20
-#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24
-#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
-#define I40E_PFQF_CTL_1 0x00245D80
+#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_1 0x00245D80 /* Reset: CORER */
#define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0
-#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK (0x1 << I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
-#define I40E_PFQF_FDALLOC 0x00246280
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
+#define I40E_PFQF_FDALLOC 0x00246280 /* Reset: CORER */
#define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0
-#define I40E_PFQF_FDALLOC_FDALLOC_MASK (0xFF << I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
+#define I40E_PFQF_FDALLOC_FDALLOC_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
#define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8
-#define I40E_PFQF_FDALLOC_FDBEST_MASK (0xFF << I40E_PFQF_FDALLOC_FDBEST_SHIFT)
-#define I40E_PFQF_FDSTAT 0x00246380
+#define I40E_PFQF_FDALLOC_FDBEST_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDBEST_SHIFT)
+#define I40E_PFQF_FDSTAT 0x00246380 /* Reset: CORER */
#define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0
-#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
#define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16
-#define I40E_PFQF_FDSTAT_BEST_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
-#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */
+#define I40E_PFQF_FDSTAT_BEST_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
+#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */ /* Reset: CORER */
#define I40E_PFQF_HENA_MAX_INDEX 1
#define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_PFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */
+#define I40E_PFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */ /* Reset: CORER */
#define I40E_PFQF_HKEY_MAX_INDEX 12
#define I40E_PFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_PFQF_HKEY_KEY_0_MASK (0xFF << I40E_PFQF_HKEY_KEY_0_SHIFT)
+#define I40E_PFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_0_SHIFT)
#define I40E_PFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_PFQF_HKEY_KEY_1_MASK (0xFF << I40E_PFQF_HKEY_KEY_1_SHIFT)
+#define I40E_PFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_1_SHIFT)
#define I40E_PFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_PFQF_HKEY_KEY_2_MASK (0xFF << I40E_PFQF_HKEY_KEY_2_SHIFT)
+#define I40E_PFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_2_SHIFT)
#define I40E_PFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_PFQF_HKEY_KEY_3_MASK (0xFF << I40E_PFQF_HKEY_KEY_3_SHIFT)
-#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */
+#define I40E_PFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_3_SHIFT)
+#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_PFQF_HLUT_MAX_INDEX 127
#define I40E_PFQF_HLUT_LUT0_SHIFT 0
-#define I40E_PFQF_HLUT_LUT0_MASK (0x3F << I40E_PFQF_HLUT_LUT0_SHIFT)
+#define I40E_PFQF_HLUT_LUT0_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT0_SHIFT)
#define I40E_PFQF_HLUT_LUT1_SHIFT 8
-#define I40E_PFQF_HLUT_LUT1_MASK (0x3F << I40E_PFQF_HLUT_LUT1_SHIFT)
+#define I40E_PFQF_HLUT_LUT1_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT1_SHIFT)
#define I40E_PFQF_HLUT_LUT2_SHIFT 16
-#define I40E_PFQF_HLUT_LUT2_MASK (0x3F << I40E_PFQF_HLUT_LUT2_SHIFT)
+#define I40E_PFQF_HLUT_LUT2_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT2_SHIFT)
#define I40E_PFQF_HLUT_LUT3_SHIFT 24
-#define I40E_PFQF_HLUT_LUT3_MASK (0x3F << I40E_PFQF_HLUT_LUT3_SHIFT)
-#define I40E_PFQF_HREGION(_i) (0x00245400 + ((_i) * 128)) /* _i=0...7 */
-#define I40E_PFQF_HREGION_MAX_INDEX 7
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
-#define I40E_PFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_PFQF_HREGION_REGION_0_MASK (0x7 << I40E_PFQF_HREGION_REGION_0_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
-#define I40E_PFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_PFQF_HREGION_REGION_1_MASK (0x7 << I40E_PFQF_HREGION_REGION_1_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
-#define I40E_PFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_PFQF_HREGION_REGION_2_MASK (0x7 << I40E_PFQF_HREGION_REGION_2_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
-#define I40E_PFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_PFQF_HREGION_REGION_3_MASK (0x7 << I40E_PFQF_HREGION_REGION_3_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
-#define I40E_PFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_PFQF_HREGION_REGION_4_MASK (0x7 << I40E_PFQF_HREGION_REGION_4_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
-#define I40E_PFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_PFQF_HREGION_REGION_5_MASK (0x7 << I40E_PFQF_HREGION_REGION_5_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
-#define I40E_PFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_PFQF_HREGION_REGION_6_MASK (0x7 << I40E_PFQF_HREGION_REGION_6_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
-#define I40E_PFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_PFQF_HREGION_REGION_7_MASK (0x7 << I40E_PFQF_HREGION_REGION_7_SHIFT)
-#define I40E_PRTQF_CTL_0 0x00256E60
+#define I40E_PFQF_HLUT_LUT3_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT3_SHIFT)
+#define I40E_PRTQF_CTL_0 0x00256E60 /* Reset: CORER */
#define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0
-#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK (0x1 << I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
-#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */
+#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK I40E_MASK(0x1, I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
+#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */ /* Reset: CORER */
#define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63
#define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0
-#define I40E_PRTQF_FD_FLXINSET_INSET_MASK (0xFF << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
-#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */
+#define I40E_PRTQF_FD_FLXINSET_INSET_MASK I40E_MASK(0xFF, I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
+#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */ /* Reset: CORER */
#define I40E_PRTQF_FD_MSK_MAX_INDEX 63
#define I40E_PRTQF_FD_MSK_MASK_SHIFT 0
-#define I40E_PRTQF_FD_MSK_MASK_MASK (0xFFFF << I40E_PRTQF_FD_MSK_MASK_SHIFT)
+#define I40E_PRTQF_FD_MSK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRTQF_FD_MSK_MASK_SHIFT)
#define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16
-#define I40E_PRTQF_FD_MSK_OFFSET_MASK (0x3F << I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
-#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
+#define I40E_PRTQF_FD_MSK_OFFSET_MASK I40E_MASK(0x3F, I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
+#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ /* Reset: CORER */
#define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
-#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
-#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
#define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
-#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
-#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK I40E_MASK(0x3F, I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
+#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...1, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HENA1_MAX_INDEX 1
#define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA1_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */
+#define I40E_VFQF_HENA1_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HKEY1_MAX_INDEX 12
#define I40E_VFQF_HKEY1_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY1_KEY_0_MASK (0xFF << I40E_VFQF_HKEY1_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_0_SHIFT)
#define I40E_VFQF_HKEY1_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY1_KEY_1_MASK (0xFF << I40E_VFQF_HKEY1_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_1_SHIFT)
#define I40E_VFQF_HKEY1_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY1_KEY_2_MASK (0xFF << I40E_VFQF_HKEY1_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_2_SHIFT)
#define I40E_VFQF_HKEY1_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY1_KEY_3_MASK (0xFF << I40E_VFQF_HKEY1_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VFQF_HKEY1_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HLUT1_MAX_INDEX 15
#define I40E_VFQF_HLUT1_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT1_LUT0_MASK (0xF << I40E_VFQF_HLUT1_LUT0_SHIFT)
+#define I40E_VFQF_HLUT1_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT0_SHIFT)
#define I40E_VFQF_HLUT1_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT1_LUT1_MASK (0xF << I40E_VFQF_HLUT1_LUT1_SHIFT)
+#define I40E_VFQF_HLUT1_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT1_SHIFT)
#define I40E_VFQF_HLUT1_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT1_LUT2_MASK (0xF << I40E_VFQF_HLUT1_LUT2_SHIFT)
+#define I40E_VFQF_HLUT1_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT2_SHIFT)
#define I40E_VFQF_HLUT1_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT1_LUT3_MASK (0xF << I40E_VFQF_HLUT1_LUT3_SHIFT)
-#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HLUT1_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT3_SHIFT)
+#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...7, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HREGION1_MAX_INDEX 7
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
#define I40E_VFQF_HREGION1_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION1_REGION_0_MASK (0x7 << I40E_VFQF_HREGION1_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_0_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
#define I40E_VFQF_HREGION1_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION1_REGION_1_MASK (0x7 << I40E_VFQF_HREGION1_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_1_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
#define I40E_VFQF_HREGION1_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION1_REGION_2_MASK (0x7 << I40E_VFQF_HREGION1_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_2_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
#define I40E_VFQF_HREGION1_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION1_REGION_3_MASK (0x7 << I40E_VFQF_HREGION1_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_3_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
#define I40E_VFQF_HREGION1_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION1_REGION_4_MASK (0x7 << I40E_VFQF_HREGION1_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_4_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
#define I40E_VFQF_HREGION1_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION1_REGION_5_MASK (0x7 << I40E_VFQF_HREGION1_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_5_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
#define I40E_VFQF_HREGION1_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION1_REGION_6_MASK (0x7 << I40E_VFQF_HREGION1_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_6_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
#define I40E_VFQF_HREGION1_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION1_REGION_7_MASK (0x7 << I40E_VFQF_HREGION1_REGION_7_SHIFT)
-#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFQF_HREGION1_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_7_SHIFT)
+#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPQF_CTL_MAX_INDEX 127
#define I40E_VPQF_CTL_PEHSIZE_SHIFT 0
-#define I40E_VPQF_CTL_PEHSIZE_MASK (0x1F << I40E_VPQF_CTL_PEHSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEHSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEHSIZE_SHIFT)
#define I40E_VPQF_CTL_PEDSIZE_SHIFT 5
-#define I40E_VPQF_CTL_PEDSIZE_MASK (0x1F << I40E_VPQF_CTL_PEDSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEDSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEDSIZE_SHIFT)
#define I40E_VPQF_CTL_FCHSIZE_SHIFT 10
-#define I40E_VPQF_CTL_FCHSIZE_MASK (0xF << I40E_VPQF_CTL_FCHSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCHSIZE_MASK I40E_MASK(0xF, I40E_VPQF_CTL_FCHSIZE_SHIFT)
#define I40E_VPQF_CTL_FCDSIZE_SHIFT 14
-#define I40E_VPQF_CTL_FCDSIZE_MASK (0x3 << I40E_VPQF_CTL_FCDSIZE_SHIFT)
-#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPQF_CTL_FCDSIZE_MASK I40E_MASK(0x3, I40E_VPQF_CTL_FCDSIZE_SHIFT)
+#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
#define I40E_VSIQF_CTL_MAX_INDEX 383
#define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0
-#define I40E_VSIQF_CTL_FCOE_ENA_MASK (0x1 << I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
+#define I40E_VSIQF_CTL_FCOE_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
#define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1
-#define I40E_VSIQF_CTL_PETCP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PETCP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2
-#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3
-#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4
-#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
-#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
-#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
+#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...3, _VSI=0...383 */ /* Reset: PFR */
#define I40E_VSIQF_TCREGION_MAX_INDEX 3
#define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
-#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
#define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
-#define I40E_VSIQF_TCREGION_TC_SIZE_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
#define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16
-#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
#define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25
-#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
-#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
+#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOECRC_MAX_INDEX 143
#define I40E_GL_FCOECRC_FCOECRC_SHIFT 0
-#define I40E_GL_FCOECRC_FCOECRC_MASK (0xFFFFFFFF << I40E_GL_FCOECRC_FCOECRC_SHIFT)
-#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOECRC_FCOECRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOECRC_FCOECRC_SHIFT)
+#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDDPC_MAX_INDEX 143
#define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
-#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
-/* _i=0...143 */
-#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
+#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIFEC_MAX_INDEX 143
#define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFRC(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIFRC_MAX_INDEX 143
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIFTCL_MAX_INDEX 143
#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0
-#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
-#define I40E_GL_FCOEDIXAC(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIXAC_MAX_INDEX 143
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT 0
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT)
-#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
+#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIXEC_MAX_INDEX 143
#define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0
-#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
-#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
+#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIXVC_MAX_INDEX 143
#define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0
-#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
-#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
+#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWRCH_MAX_INDEX 143
#define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0
-#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK (0xFFFF << I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
-#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
+#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWRCL_MAX_INDEX 143
#define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0
-#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
-#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
+#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWTCH_MAX_INDEX 143
#define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0
-#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK (0xFFFF << I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
-#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
+#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWTCL_MAX_INDEX 143
#define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0
-#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
-#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
+#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOELAST_MAX_INDEX 143
#define I40E_GL_FCOELAST_FCOELAST_SHIFT 0
-#define I40E_GL_FCOELAST_FCOELAST_MASK (0xFFFFFFFF << I40E_GL_FCOELAST_FCOELAST_SHIFT)
-#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOELAST_FCOELAST_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOELAST_FCOELAST_SHIFT)
+#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEPRC_MAX_INDEX 143
#define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0
-#define I40E_GL_FCOEPRC_FCOEPRC_MASK (0xFFFFFFFF << I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
-#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPRC_FCOEPRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
+#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEPTC_MAX_INDEX 143
#define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0
-#define I40E_GL_FCOEPTC_FCOEPTC_MASK (0xFFFFFFFF << I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
-#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPTC_FCOEPTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
+#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOERPDC_MAX_INDEX 143
#define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
-#define I40E_GL_FCOERPDC_FCOERPDC_MASK (0xFFFFFFFF << I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
-#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GL_FCOERPDC_FCOERPDC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
+#define I40E_GL_RXERR1_L(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1_L_MAX_INDEX 143
+#define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0
+#define I40E_GL_RXERR1_L_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT)
+#define I40E_GL_RXERR2_L(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR2_L_MAX_INDEX 143
+#define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0
+#define I40E_GL_RXERR2_L_FCOEDIXAC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT)
+#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPRCH_MAX_INDEX 3
#define I40E_GLPRT_BPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPRCL_MAX_INDEX 3
#define I40E_GLPRT_BPRCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPRCL_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPRCL_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPTCH_MAX_INDEX 3
#define I40E_GLPRT_BPTCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPTCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPTCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPTCL_MAX_INDEX 3
#define I40E_GLPRT_BPTCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPTCL_UPRCH_SHIFT)
-#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPTCL_UPRCH_SHIFT)
+#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_CRCERRS_MAX_INDEX 3
#define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0
-#define I40E_GLPRT_CRCERRS_CRCERRS_MASK (0xFFFFFFFF << I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
-#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_CRCERRS_CRCERRS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
+#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GORCH_MAX_INDEX 3
#define I40E_GLPRT_GORCH_GORCH_SHIFT 0
-#define I40E_GLPRT_GORCH_GORCH_MASK (0xFFFF << I40E_GLPRT_GORCH_GORCH_SHIFT)
-#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GORCH_GORCH_SHIFT)
+#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GORCL_MAX_INDEX 3
#define I40E_GLPRT_GORCL_GORCL_SHIFT 0
-#define I40E_GLPRT_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLPRT_GORCL_GORCL_SHIFT)
-#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GORCL_GORCL_SHIFT)
+#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GOTCH_MAX_INDEX 3
#define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLPRT_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLPRT_GOTCH_GOTCH_SHIFT)
-#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GOTCH_GOTCH_SHIFT)
+#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GOTCL_MAX_INDEX 3
#define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLPRT_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLPRT_GOTCL_GOTCL_SHIFT)
-#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GOTCL_GOTCL_SHIFT)
+#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_ILLERRC_MAX_INDEX 3
#define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0
-#define I40E_GLPRT_ILLERRC_ILLERRC_MASK (0xFFFFFFFF << I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
-#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ILLERRC_ILLERRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
+#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LDPC_MAX_INDEX 3
#define I40E_GLPRT_LDPC_LDPC_SHIFT 0
-#define I40E_GLPRT_LDPC_LDPC_MASK (0xFFFFFFFF << I40E_GLPRT_LDPC_LDPC_SHIFT)
-#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LDPC_LDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LDPC_LDPC_SHIFT)
+#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3
#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3
#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0
-#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
-#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
+#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXONRXC_MAX_INDEX 3
#define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0
-#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
-#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
+#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXONTXC_MAX_INDEX 3
#define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0
-#define I40E_GLPRT_LXONTXC_LXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
-#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONTXC_LXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
+#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MLFC_MAX_INDEX 3
#define I40E_GLPRT_MLFC_MLFC_SHIFT 0
-#define I40E_GLPRT_MLFC_MLFC_MASK (0xFFFFFFFF << I40E_GLPRT_MLFC_MLFC_SHIFT)
-#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MLFC_MLFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MLFC_MLFC_SHIFT)
+#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPRCH_MAX_INDEX 3
#define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLPRT_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLPRT_MPRCH_MPRCH_SHIFT)
-#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPRCH_MPRCH_SHIFT)
+#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPRCL_MAX_INDEX 3
#define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLPRT_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPRCL_MPRCL_SHIFT)
-#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPRCL_MPRCL_SHIFT)
+#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPTCH_MAX_INDEX 3
#define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLPRT_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLPRT_MPTCH_MPTCH_SHIFT)
-#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPTCH_MPTCH_SHIFT)
+#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPTCL_MAX_INDEX 3
#define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLPRT_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPTCL_MPTCL_SHIFT)
-#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPTCL_MPTCL_SHIFT)
+#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MRFC_MAX_INDEX 3
#define I40E_GLPRT_MRFC_MRFC_SHIFT 0
-#define I40E_GLPRT_MRFC_MRFC_MASK (0xFFFFFFFF << I40E_GLPRT_MRFC_MRFC_SHIFT)
-#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MRFC_MRFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MRFC_MRFC_SHIFT)
+#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1023H_MAX_INDEX 3
#define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0
-#define I40E_GLPRT_PRC1023H_PRC1023H_MASK (0xFFFF << I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
-#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023H_PRC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
+#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1023L_MAX_INDEX 3
#define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0
-#define I40E_GLPRT_PRC1023L_PRC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
-#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023L_PRC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
+#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC127H_MAX_INDEX 3
#define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0
-#define I40E_GLPRT_PRC127H_PRC127H_MASK (0xFFFF << I40E_GLPRT_PRC127H_PRC127H_SHIFT)
-#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127H_PRC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC127H_PRC127H_SHIFT)
+#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC127L_MAX_INDEX 3
#define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0
-#define I40E_GLPRT_PRC127L_PRC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC127L_PRC127L_SHIFT)
-#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127L_PRC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC127L_PRC127L_SHIFT)
+#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1522H_MAX_INDEX 3
#define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC1522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1522L_MAX_INDEX 3
#define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC1522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC255H_MAX_INDEX 3
#define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0
-#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK (0xFFFF << I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
-#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
+#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC255L_MAX_INDEX 3
#define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0
-#define I40E_GLPRT_PRC255L_PRC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC255L_PRC255L_SHIFT)
-#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255L_PRC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC255L_PRC255L_SHIFT)
+#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC511H_MAX_INDEX 3
#define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0
-#define I40E_GLPRT_PRC511H_PRC511H_MASK (0xFFFF << I40E_GLPRT_PRC511H_PRC511H_SHIFT)
-#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511H_PRC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC511H_PRC511H_SHIFT)
+#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC511L_MAX_INDEX 3
#define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0
-#define I40E_GLPRT_PRC511L_PRC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC511L_PRC511L_SHIFT)
-#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511L_PRC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC511L_PRC511L_SHIFT)
+#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC64H_MAX_INDEX 3
#define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0
-#define I40E_GLPRT_PRC64H_PRC64H_MASK (0xFFFF << I40E_GLPRT_PRC64H_PRC64H_SHIFT)
-#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64H_PRC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC64H_PRC64H_SHIFT)
+#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC64L_MAX_INDEX 3
#define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0
-#define I40E_GLPRT_PRC64L_PRC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC64L_PRC64L_SHIFT)
-#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64L_PRC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC64L_PRC64L_SHIFT)
+#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC9522H_MAX_INDEX 3
#define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC9522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC9522L_MAX_INDEX 3
#define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC9522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1023H_MAX_INDEX 3
#define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0
-#define I40E_GLPRT_PTC1023H_PTC1023H_MASK (0xFFFF << I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
-#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023H_PTC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
+#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1023L_MAX_INDEX 3
#define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0
-#define I40E_GLPRT_PTC1023L_PTC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
-#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023L_PTC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
+#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC127H_MAX_INDEX 3
#define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0
-#define I40E_GLPRT_PTC127H_PTC127H_MASK (0xFFFF << I40E_GLPRT_PTC127H_PTC127H_SHIFT)
-#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127H_PTC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC127H_PTC127H_SHIFT)
+#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC127L_MAX_INDEX 3
#define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0
-#define I40E_GLPRT_PTC127L_PTC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC127L_PTC127L_SHIFT)
-#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127L_PTC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC127L_PTC127L_SHIFT)
+#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1522H_MAX_INDEX 3
#define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0
-#define I40E_GLPRT_PTC1522H_PTC1522H_MASK (0xFFFF << I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
-#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522H_PTC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
+#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1522L_MAX_INDEX 3
#define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0
-#define I40E_GLPRT_PTC1522L_PTC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
-#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522L_PTC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
+#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC255H_MAX_INDEX 3
#define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0
-#define I40E_GLPRT_PTC255H_PTC255H_MASK (0xFFFF << I40E_GLPRT_PTC255H_PTC255H_SHIFT)
-#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255H_PTC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC255H_PTC255H_SHIFT)
+#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC255L_MAX_INDEX 3
#define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0
-#define I40E_GLPRT_PTC255L_PTC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC255L_PTC255L_SHIFT)
-#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255L_PTC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC255L_PTC255L_SHIFT)
+#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC511H_MAX_INDEX 3
#define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0
-#define I40E_GLPRT_PTC511H_PTC511H_MASK (0xFFFF << I40E_GLPRT_PTC511H_PTC511H_SHIFT)
-#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511H_PTC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC511H_PTC511H_SHIFT)
+#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC511L_MAX_INDEX 3
#define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0
-#define I40E_GLPRT_PTC511L_PTC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC511L_PTC511L_SHIFT)
-#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511L_PTC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC511L_PTC511L_SHIFT)
+#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC64H_MAX_INDEX 3
#define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0
-#define I40E_GLPRT_PTC64H_PTC64H_MASK (0xFFFF << I40E_GLPRT_PTC64H_PTC64H_SHIFT)
-#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64H_PTC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC64H_PTC64H_SHIFT)
+#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC64L_MAX_INDEX 3
#define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0
-#define I40E_GLPRT_PTC64L_PTC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC64L_PTC64L_SHIFT)
-#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64L_PTC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC64L_PTC64L_SHIFT)
+#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC9522H_MAX_INDEX 3
#define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0
-#define I40E_GLPRT_PTC9522H_PTC9522H_MASK (0xFFFF << I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
-#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522H_PTC9522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
+#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC9522L_MAX_INDEX 3
#define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0
-#define I40E_GLPRT_PTC9522L_PTC9522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
-#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PTC9522L_PTC9522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
+#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3
#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3
#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
-#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
+#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXONRXC_MAX_INDEX 3
#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0
-#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
-#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
+#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXONTXC_MAX_INDEX 3
#define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0
-#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
-#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
+#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RDPC_MAX_INDEX 3
#define I40E_GLPRT_RDPC_RDPC_SHIFT 0
-#define I40E_GLPRT_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLPRT_RDPC_RDPC_SHIFT)
-#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RDPC_RDPC_SHIFT)
+#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RFC_MAX_INDEX 3
#define I40E_GLPRT_RFC_RFC_SHIFT 0
-#define I40E_GLPRT_RFC_RFC_MASK (0xFFFFFFFF << I40E_GLPRT_RFC_RFC_SHIFT)
-#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RFC_RFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RFC_RFC_SHIFT)
+#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RJC_MAX_INDEX 3
#define I40E_GLPRT_RJC_RJC_SHIFT 0
-#define I40E_GLPRT_RJC_RJC_MASK (0xFFFFFFFF << I40E_GLPRT_RJC_RJC_SHIFT)
-#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RJC_RJC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RJC_RJC_SHIFT)
+#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RLEC_MAX_INDEX 3
#define I40E_GLPRT_RLEC_RLEC_SHIFT 0
-#define I40E_GLPRT_RLEC_RLEC_MASK (0xFFFFFFFF << I40E_GLPRT_RLEC_RLEC_SHIFT)
-#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RLEC_RLEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RLEC_RLEC_SHIFT)
+#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_ROC_MAX_INDEX 3
#define I40E_GLPRT_ROC_ROC_SHIFT 0
-#define I40E_GLPRT_ROC_ROC_MASK (0xFFFFFFFF << I40E_GLPRT_ROC_ROC_SHIFT)
-#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ROC_ROC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ROC_ROC_SHIFT)
+#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RUC_MAX_INDEX 3
#define I40E_GLPRT_RUC_RUC_SHIFT 0
-#define I40E_GLPRT_RUC_RUC_MASK (0xFFFFFFFF << I40E_GLPRT_RUC_RUC_SHIFT)
-#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUC_RUC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUC_RUC_SHIFT)
+#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RUPP_MAX_INDEX 3
#define I40E_GLPRT_RUPP_RUPP_SHIFT 0
-#define I40E_GLPRT_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLPRT_RUPP_RUPP_SHIFT)
-#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUPP_RUPP_SHIFT)
+#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3
#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0
-#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK (0xFFFFFFFF << I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
-#define I40E_GLPRT_STDC(_i) (0x00300640 + ((_i) * 8)) /* _i=0...3 */
-#define I40E_GLPRT_STDC_MAX_INDEX 3
-#define I40E_GLPRT_STDC_STDC_SHIFT 0
-#define I40E_GLPRT_STDC_STDC_MASK (0xFFFFFFFF << I40E_GLPRT_STDC_STDC_SHIFT)
-#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
+#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_TDOLD_MAX_INDEX 3
#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0
-#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK (0xFFFFFFFF << I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
-#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
+#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_TDPC_MAX_INDEX 3
#define I40E_GLPRT_TDPC_TDPC_SHIFT 0
-#define I40E_GLPRT_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLPRT_TDPC_TDPC_SHIFT)
-#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDPC_TDPC_SHIFT)
+#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPRCH_MAX_INDEX 3
#define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_UPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPRCL_MAX_INDEX 3
#define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLPRT_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_UPRCL_UPRCL_SHIFT)
-#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPRCL_UPRCL_SHIFT)
+#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPTCH_MAX_INDEX 3
#define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLPRT_UPTCH_UPTCH_SHIFT)
-#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPTCH_UPTCH_SHIFT)
+#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPTCL_MAX_INDEX 3
#define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCL_VUPTCH_MASK (0xFFFFFFFF << I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
-#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPRT_UPTCL_VUPTCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
+#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPRCH_MAX_INDEX 15
#define I40E_GLSW_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLSW_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLSW_BPRCH_BPRCH_SHIFT)
-#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPRCH_BPRCH_SHIFT)
+#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPRCL_MAX_INDEX 15
#define I40E_GLSW_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLSW_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLSW_BPRCL_BPRCL_SHIFT)
-#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPRCL_BPRCL_SHIFT)
+#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPTCH_MAX_INDEX 15
#define I40E_GLSW_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLSW_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLSW_BPTCH_BPTCH_SHIFT)
-#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPTCH_BPTCH_SHIFT)
+#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPTCL_MAX_INDEX 15
#define I40E_GLSW_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLSW_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLSW_BPTCL_BPTCL_SHIFT)
-#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPTCL_BPTCL_SHIFT)
+#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GORCH_MAX_INDEX 15
#define I40E_GLSW_GORCH_GORCH_SHIFT 0
-#define I40E_GLSW_GORCH_GORCH_MASK (0xFFFF << I40E_GLSW_GORCH_GORCH_SHIFT)
-#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GORCH_GORCH_SHIFT)
+#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GORCL_MAX_INDEX 15
#define I40E_GLSW_GORCL_GORCL_SHIFT 0
-#define I40E_GLSW_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLSW_GORCL_GORCL_SHIFT)
-#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GORCL_GORCL_SHIFT)
+#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GOTCH_MAX_INDEX 15
#define I40E_GLSW_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLSW_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLSW_GOTCH_GOTCH_SHIFT)
-#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GOTCH_GOTCH_SHIFT)
+#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GOTCL_MAX_INDEX 15
#define I40E_GLSW_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLSW_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLSW_GOTCL_GOTCL_SHIFT)
-#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GOTCL_GOTCL_SHIFT)
+#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPRCH_MAX_INDEX 15
#define I40E_GLSW_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLSW_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLSW_MPRCH_MPRCH_SHIFT)
-#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPRCH_MPRCH_SHIFT)
+#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPRCL_MAX_INDEX 15
#define I40E_GLSW_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLSW_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLSW_MPRCL_MPRCL_SHIFT)
-#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPRCL_MPRCL_SHIFT)
+#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPTCH_MAX_INDEX 15
#define I40E_GLSW_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLSW_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLSW_MPTCH_MPTCH_SHIFT)
-#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPTCH_MPTCH_SHIFT)
+#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPTCL_MAX_INDEX 15
#define I40E_GLSW_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLSW_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLSW_MPTCL_MPTCL_SHIFT)
-#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPTCL_MPTCL_SHIFT)
+#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_RUPP_MAX_INDEX 15
#define I40E_GLSW_RUPP_RUPP_SHIFT 0
-#define I40E_GLSW_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLSW_RUPP_RUPP_SHIFT)
-#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_RUPP_RUPP_SHIFT)
+#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_TDPC_MAX_INDEX 15
#define I40E_GLSW_TDPC_TDPC_SHIFT 0
-#define I40E_GLSW_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLSW_TDPC_TDPC_SHIFT)
-#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_TDPC_TDPC_SHIFT)
+#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPRCH_MAX_INDEX 15
#define I40E_GLSW_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLSW_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLSW_UPRCH_UPRCH_SHIFT)
-#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPRCH_UPRCH_SHIFT)
+#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPRCL_MAX_INDEX 15
#define I40E_GLSW_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLSW_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLSW_UPRCL_UPRCL_SHIFT)
-#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPRCL_UPRCL_SHIFT)
+#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPTCH_MAX_INDEX 15
#define I40E_GLSW_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLSW_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLSW_UPTCH_UPTCH_SHIFT)
-#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPTCH_UPTCH_SHIFT)
+#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPTCL_MAX_INDEX 15
#define I40E_GLSW_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLSW_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLSW_UPTCL_UPTCL_SHIFT)
-#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLSW_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPTCL_UPTCL_SHIFT)
+#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPRCH_MAX_INDEX 383
#define I40E_GLV_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLV_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLV_BPRCH_BPRCH_SHIFT)
-#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPRCH_BPRCH_SHIFT)
+#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPRCL_MAX_INDEX 383
#define I40E_GLV_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLV_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLV_BPRCL_BPRCL_SHIFT)
-#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPRCL_BPRCL_SHIFT)
+#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPTCH_MAX_INDEX 383
#define I40E_GLV_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLV_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLV_BPTCH_BPTCH_SHIFT)
-#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPTCH_BPTCH_SHIFT)
+#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPTCL_MAX_INDEX 383
#define I40E_GLV_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLV_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLV_BPTCL_BPTCL_SHIFT)
-#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPTCL_BPTCL_SHIFT)
+#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GORCH_MAX_INDEX 383
#define I40E_GLV_GORCH_GORCH_SHIFT 0
-#define I40E_GLV_GORCH_GORCH_MASK (0xFFFF << I40E_GLV_GORCH_GORCH_SHIFT)
-#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GORCH_GORCH_SHIFT)
+#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GORCL_MAX_INDEX 383
#define I40E_GLV_GORCL_GORCL_SHIFT 0
-#define I40E_GLV_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLV_GORCL_GORCL_SHIFT)
-#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GORCL_GORCL_SHIFT)
+#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GOTCH_MAX_INDEX 383
#define I40E_GLV_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLV_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLV_GOTCH_GOTCH_SHIFT)
-#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GOTCH_GOTCH_SHIFT)
+#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GOTCL_MAX_INDEX 383
#define I40E_GLV_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLV_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLV_GOTCL_GOTCL_SHIFT)
-#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GOTCL_GOTCL_SHIFT)
+#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPRCH_MAX_INDEX 383
#define I40E_GLV_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLV_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLV_MPRCH_MPRCH_SHIFT)
-#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPRCH_MPRCH_SHIFT)
+#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPRCL_MAX_INDEX 383
#define I40E_GLV_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLV_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLV_MPRCL_MPRCL_SHIFT)
-#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPRCL_MPRCL_SHIFT)
+#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPTCH_MAX_INDEX 383
#define I40E_GLV_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLV_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLV_MPTCH_MPTCH_SHIFT)
-#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPTCH_MPTCH_SHIFT)
+#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPTCL_MAX_INDEX 383
#define I40E_GLV_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLV_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLV_MPTCL_MPTCL_SHIFT)
-#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPTCL_MPTCL_SHIFT)
+#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_RDPC_MAX_INDEX 383
#define I40E_GLV_RDPC_RDPC_SHIFT 0
-#define I40E_GLV_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLV_RDPC_RDPC_SHIFT)
-#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RDPC_RDPC_SHIFT)
+#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_RUPP_MAX_INDEX 383
#define I40E_GLV_RUPP_RUPP_SHIFT 0
-#define I40E_GLV_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLV_RUPP_RUPP_SHIFT)
-#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 8)) /* _i=0...383 */
+#define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT)
+#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_TEPC_MAX_INDEX 383
#define I40E_GLV_TEPC_TEPC_SHIFT 0
-#define I40E_GLV_TEPC_TEPC_MASK (0xFFFFFFFF << I40E_GLV_TEPC_TEPC_SHIFT)
-#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT)
+#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPRCH_MAX_INDEX 383
#define I40E_GLV_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLV_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLV_UPRCH_UPRCH_SHIFT)
-#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPRCH_UPRCH_SHIFT)
+#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPRCL_MAX_INDEX 383
#define I40E_GLV_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLV_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLV_UPRCL_UPRCL_SHIFT)
-#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPRCL_UPRCL_SHIFT)
+#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPTCH_MAX_INDEX 383
#define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0
-#define I40E_GLV_UPTCH_GLVUPTCH_MASK (0xFFFF << I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
-#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCH_GLVUPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
+#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPTCL_MAX_INDEX 383
#define I40E_GLV_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLV_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLV_UPTCL_UPTCL_SHIFT)
-#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLV_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPTCL_UPTCL_SHIFT)
+#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RBCH_MAX_INDEX 7
#define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_RBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RBCL_MAX_INDEX 7
#define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_RBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RPCH_MAX_INDEX 7
#define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_RPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RPCL_MAX_INDEX 7
#define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_RPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
-#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
+#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TBCH_MAX_INDEX 7
#define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_TBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TBCL_MAX_INDEX 7
#define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_TBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TPCH_MAX_INDEX 7
#define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_TPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TPCL_MAX_INDEX 7
#define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_TPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
-#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBTC_TPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
+#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_BPCH_MAX_INDEX 127
#define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0
-#define I40E_GLVEBVL_BPCH_VLBPCH_MASK (0xFFFF << I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
-#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCH_VLBPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
+#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_BPCL_MAX_INDEX 127
#define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0
-#define I40E_GLVEBVL_BPCL_VLBPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
-#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCL_VLBPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
+#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GORCH_MAX_INDEX 127
#define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GORCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GORCL_MAX_INDEX 127
#define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GORCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GOTCH_MAX_INDEX 127
#define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GOTCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GOTCL_MAX_INDEX 127
#define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GOTCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_MPCH_MAX_INDEX 127
#define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0
-#define I40E_GLVEBVL_MPCH_VLMPCH_MASK (0xFFFF << I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
-#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCH_VLMPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
+#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_MPCL_MAX_INDEX 127
#define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0
-#define I40E_GLVEBVL_MPCL_VLMPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
-#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCL_VLMPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
+#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_UPCH_MAX_INDEX 127
#define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0
-#define I40E_GLVEBVL_UPCH_VLUPCH_MASK (0xFFFF << I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
-#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCH_VLUPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
+#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_UPCL_MAX_INDEX 127
#define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0
-#define I40E_GLVEBVL_UPCL_VLUPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C
+#define I40E_GLVEBVL_UPCL_VLUPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C /* Reset: CORER */
#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK (0xFFFF << I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_L 0x00269F44
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_MASK (0xFFFFFFFF << I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT)
-#define I40E_GL_SWR_DEF_ACT(_i) (0x0026CF00 + ((_i) * 4)) /* _i=0...25 */
-#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 25
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK I40E_MASK(0xFFFF, I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
+#define I40E_GL_SWR_DEF_ACT(_i) (0x00270200 + ((_i) * 4)) /* _i=0...35 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 35
#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
-#define I40E_GL_SWR_DEF_ACT_EN 0x0026CF84
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
+#define I40E_GL_SWR_DEF_ACT_EN(_i) (0x0026CFB8 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_EN_MAX_INDEX 1
#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
-#define I40E_PRT_MSCCNT 0x00256BA0
-#define I40E_PRT_MSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_MSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_MSCCNT_CCOUNT_SHIFT)
-#define I40E_PRT_SCSTS 0x00256C20
-#define I40E_PRT_SCSTS_BSCA_SHIFT 0
-#define I40E_PRT_SCSTS_BSCA_MASK (0x1 << I40E_PRT_SCSTS_BSCA_SHIFT)
-#define I40E_PRT_SCSTS_BSCAP_SHIFT 1
-#define I40E_PRT_SCSTS_BSCAP_MASK (0x1 << I40E_PRT_SCSTS_BSCAP_SHIFT)
-#define I40E_PRT_SCSTS_MSCA_SHIFT 2
-#define I40E_PRT_SCSTS_MSCA_MASK (0x1 << I40E_PRT_SCSTS_MSCA_SHIFT)
-#define I40E_PRT_SCSTS_MSCAP_SHIFT 3
-#define I40E_PRT_SCSTS_MSCAP_MASK (0x1 << I40E_PRT_SCSTS_MSCAP_SHIFT)
-#define I40E_PRT_SWT_BSCCNT 0x00256C60
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT)
-#define I40E_PRTTSYN_ADJ 0x001E4280
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
+#define I40E_PRTTSYN_ADJ 0x001E4280 /* Reset: GLOBR */
#define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0
-#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK (0x7FFFFFFF << I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
+#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK I40E_MASK(0x7FFFFFFF, I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
#define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31
-#define I40E_PRTTSYN_ADJ_SIGN_MASK (0x1 << I40E_PRTTSYN_ADJ_SIGN_SHIFT)
-#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_ADJ_SIGN_MASK I40E_MASK(0x1, I40E_PRTTSYN_ADJ_SIGN_SHIFT)
+#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_AUX_0_MAX_INDEX 1
#define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0
-#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
#define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1
-#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK (0x3 << I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
#define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3
-#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
#define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8
-#define I40E_PRTTSYN_AUX_0_PULSEW_MASK (0xF << I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
+#define I40E_PRTTSYN_AUX_0_PULSEW_MASK I40E_MASK(0xF, I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
#define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16
-#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK (0x3 << I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
-#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_AUX_1_MAX_INDEX 1
#define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0
-#define I40E_PRTTSYN_AUX_1_INSTNT_MASK (0x1 << I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
+#define I40E_PRTTSYN_AUX_1_INSTNT_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1
-#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK (0x1 << I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
-#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
+#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_CLKO_MAX_INDEX 1
#define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0
-#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK (0xFFFFFFFF << I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
-#define I40E_PRTTSYN_CTL0 0x001E4200
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
+#define I40E_PRTTSYN_CTL0 0x001E4200 /* Reset: GLOBR */
#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0
-#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK (0x1 << I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1
-#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2
-#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3
-#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8
-#define I40E_PRTTSYN_CTL0_PF_ID_MASK (0xF << I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
+#define I40E_PRTTSYN_CTL0_PF_ID_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
#define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12
-#define I40E_PRTTSYN_CTL0_TSYNACT_MASK (0x3 << I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNACT_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
#define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL0_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_CTL1 0x00085020
+#define I40E_PRTTSYN_CTL0_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_CTL1 0x00085020 /* Reset: CORER */
#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
#define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24
-#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK (0x3 << I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
#define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26
-#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK (0x3 << I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
#define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL1_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1
#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0
-#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
-#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
+#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1
#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0
-#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
-#define I40E_PRTTSYN_INC_H 0x001E4060
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
+#define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */
#define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0
-#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK (0x3F << I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
-#define I40E_PRTTSYN_INC_L 0x001E4040
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK I40E_MASK(0x3F, I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
+#define I40E_PRTTSYN_INC_L 0x001E4040 /* Reset: GLOBR */
#define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0
-#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
-#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
+#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3
#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3
#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
-#define I40E_PRTTSYN_STAT_0 0x001E4220
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
+#define I40E_PRTTSYN_STAT_0 0x001E4220 /* Reset: GLOBR */
#define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_0_EVENT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
#define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_0_EVENT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
#define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2
-#define I40E_PRTTSYN_STAT_0_TGT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
#define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3
-#define I40E_PRTTSYN_STAT_0_TGT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
#define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4
-#define I40E_PRTTSYN_STAT_0_TXTIME_MASK (0x1 << I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
-#define I40E_PRTTSYN_STAT_1 0x00085140
+#define I40E_PRTTSYN_STAT_0_TXTIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
+#define I40E_PRTTSYN_STAT_1 0x00085140 /* Reset: CORER */
#define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_1_RXT0_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_1_RXT1_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2
-#define I40E_PRTTSYN_STAT_1_RXT2_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT2_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3
-#define I40E_PRTTSYN_STAT_1_RXT3_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
-#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_STAT_1_RXT3_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
+#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_TGT_H_MAX_INDEX 1
#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0
-#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
-#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
+#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_TGT_L_MAX_INDEX 1
#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0
-#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
-#define I40E_PRTTSYN_TIME_H 0x001E4120
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
+#define I40E_PRTTSYN_TIME_H 0x001E4120 /* Reset: GLOBR */
#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0
-#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
-#define I40E_PRTTSYN_TIME_L 0x001E4100
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
+#define I40E_PRTTSYN_TIME_L 0x001E4100 /* Reset: GLOBR */
#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0
-#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
-#define I40E_PRTTSYN_TXTIME_H 0x001E41E0
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
+#define I40E_PRTTSYN_TXTIME_H 0x001E41E0 /* Reset: GLOBR */
#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_TXTIME_L 0x001E41C0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_TXTIME_L 0x001E41C0 /* Reset: GLOBR */
#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
-#define I40E_GLSCD_QUANTA 0x000B2080
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
+#define I40E_GLSCD_QUANTA 0x000B2080 /* Reset: CORER */
#define I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT 0
-#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK (0x7 << I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
-#define I40E_GL_MDET_RX 0x0012A510
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK I40E_MASK(0x7, I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
+#define I40E_GL_MDET_RX 0x0012A510 /* Reset: CORER */
#define I40E_GL_MDET_RX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_RX_FUNCTION_MASK (0xFF << I40E_GL_MDET_RX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_RX_FUNCTION_MASK I40E_MASK(0xFF, I40E_GL_MDET_RX_FUNCTION_SHIFT)
#define I40E_GL_MDET_RX_EVENT_SHIFT 8
-#define I40E_GL_MDET_RX_EVENT_MASK (0x1FF << I40E_GL_MDET_RX_EVENT_SHIFT)
+#define I40E_GL_MDET_RX_EVENT_MASK I40E_MASK(0x1FF, I40E_GL_MDET_RX_EVENT_SHIFT)
#define I40E_GL_MDET_RX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_RX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_RX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_QUEUE_MASK I40E_MASK(0x3FFF, I40E_GL_MDET_RX_QUEUE_SHIFT)
#define I40E_GL_MDET_RX_VALID_SHIFT 31
-#define I40E_GL_MDET_RX_VALID_MASK (0x1 << I40E_GL_MDET_RX_VALID_SHIFT)
-#define I40E_GL_MDET_TX 0x000E6480
-#define I40E_GL_MDET_TX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_TX_FUNCTION_MASK (0xFF << I40E_GL_MDET_TX_FUNCTION_SHIFT)
-#define I40E_GL_MDET_TX_EVENT_SHIFT 8
-#define I40E_GL_MDET_TX_EVENT_MASK (0x1FF << I40E_GL_MDET_TX_EVENT_SHIFT)
-#define I40E_GL_MDET_TX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_TX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_RX_VALID_SHIFT)
+#define I40E_GL_MDET_TX 0x000E6480 /* Reset: CORER */
+#define I40E_GL_MDET_TX_QUEUE_SHIFT 0
+#define I40E_GL_MDET_TX_QUEUE_MASK I40E_MASK(0xFFF, I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_TX_VF_NUM_SHIFT 12
+#define I40E_GL_MDET_TX_VF_NUM_MASK I40E_MASK(0x1FF, I40E_GL_MDET_TX_VF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_PF_NUM_SHIFT 21
+#define I40E_GL_MDET_TX_PF_NUM_MASK I40E_MASK(0xF, I40E_GL_MDET_TX_PF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_EVENT_SHIFT 25
+#define I40E_GL_MDET_TX_EVENT_MASK I40E_MASK(0x1F, I40E_GL_MDET_TX_EVENT_SHIFT)
#define I40E_GL_MDET_TX_VALID_SHIFT 31
-#define I40E_GL_MDET_TX_VALID_MASK (0x1 << I40E_GL_MDET_TX_VALID_SHIFT)
-#define I40E_PF_MDET_RX 0x0012A400
+#define I40E_GL_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_TX_VALID_SHIFT)
+#define I40E_PF_MDET_RX 0x0012A400 /* Reset: CORER */
#define I40E_PF_MDET_RX_VALID_SHIFT 0
-#define I40E_PF_MDET_RX_VALID_MASK (0x1 << I40E_PF_MDET_RX_VALID_SHIFT)
-#define I40E_PF_MDET_TX 0x000E6400
+#define I40E_PF_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_RX_VALID_SHIFT)
+#define I40E_PF_MDET_TX 0x000E6400 /* Reset: CORER */
#define I40E_PF_MDET_TX_VALID_SHIFT 0
-#define I40E_PF_MDET_TX_VALID_MASK (0x1 << I40E_PF_MDET_TX_VALID_SHIFT)
-#define I40E_PF_VT_PFALLOC 0x001C0500
+#define I40E_PF_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_TX_VALID_SHIFT)
+#define I40E_PF_VT_PFALLOC 0x001C0500 /* Reset: CORER */
#define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0
-#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
#define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8
-#define I40E_PF_VT_PFALLOC_LASTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
#define I40E_PF_VT_PFALLOC_VALID_SHIFT 31
-#define I40E_PF_VT_PFALLOC_VALID_MASK (0x1 << I40E_PF_VT_PFALLOC_VALID_SHIFT)
-#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT)
+#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VP_MDET_RX_MAX_INDEX 127
#define I40E_VP_MDET_RX_VALID_SHIFT 0
-#define I40E_VP_MDET_RX_VALID_MASK (0x1 << I40E_VP_MDET_RX_VALID_SHIFT)
-#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_RX_VALID_SHIFT)
+#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VP_MDET_TX_MAX_INDEX 127
#define I40E_VP_MDET_TX_VALID_SHIFT 0
-#define I40E_VP_MDET_TX_VALID_MASK (0x1 << I40E_VP_MDET_TX_VALID_SHIFT)
-#define I40E_GLPM_WUMC 0x0006C800
+#define I40E_VP_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_TX_VALID_SHIFT)
+#define I40E_GLPM_WUMC 0x0006C800 /* Reset: POR */
#define I40E_GLPM_WUMC_NOTCO_SHIFT 0
-#define I40E_GLPM_WUMC_NOTCO_MASK (0x1 << I40E_GLPM_WUMC_NOTCO_SHIFT)
+#define I40E_GLPM_WUMC_NOTCO_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_NOTCO_SHIFT)
#define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1
-#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK (0x1 << I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
#define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2
-#define I40E_GLPM_WUMC_ROL_MODE_MASK (0x1 << I40E_GLPM_WUMC_ROL_MODE_SHIFT)
+#define I40E_GLPM_WUMC_ROL_MODE_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_ROL_MODE_SHIFT)
#define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3
-#define I40E_GLPM_WUMC_RESERVED_4_MASK (0x1FFF << I40E_GLPM_WUMC_RESERVED_4_SHIFT)
+#define I40E_GLPM_WUMC_RESERVED_4_MASK I40E_MASK(0x1FFF, I40E_GLPM_WUMC_RESERVED_4_SHIFT)
#define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16
-#define I40E_GLPM_WUMC_MNG_WU_PF_MASK (0xFFFF << I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
-#define I40E_PFPM_APM 0x000B8080
+#define I40E_GLPM_WUMC_MNG_WU_PF_MASK I40E_MASK(0xFFFF, I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
+#define I40E_PFPM_APM 0x000B8080 /* Reset: POR */
#define I40E_PFPM_APM_APME_SHIFT 0
-#define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
-#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFPM_APM_APME_MASK I40E_MASK(0x1, I40E_PFPM_APM_APME_SHIFT)
+#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
#define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PFPM_WUC 0x0006B200
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PFPM_WUC 0x0006B200 /* Reset: POR */
#define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
-#define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
-#define I40E_PFPM_WUFC 0x0006B400
+#define I40E_PFPM_WUC_EN_APM_D0_MASK I40E_MASK(0x1, I40E_PFPM_WUC_EN_APM_D0_SHIFT)
+#define I40E_PFPM_WUFC 0x0006B400 /* Reset: POR */
#define I40E_PFPM_WUFC_LNKC_SHIFT 0
-#define I40E_PFPM_WUFC_LNKC_MASK (0x1 << I40E_PFPM_WUFC_LNKC_SHIFT)
+#define I40E_PFPM_WUFC_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_LNKC_SHIFT)
#define I40E_PFPM_WUFC_MAG_SHIFT 1
-#define I40E_PFPM_WUFC_MAG_MASK (0x1 << I40E_PFPM_WUFC_MAG_SHIFT)
+#define I40E_PFPM_WUFC_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MAG_SHIFT)
#define I40E_PFPM_WUFC_MNG_SHIFT 3
-#define I40E_PFPM_WUFC_MNG_MASK (0x1 << I40E_PFPM_WUFC_MNG_SHIFT)
+#define I40E_PFPM_WUFC_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MNG_SHIFT)
#define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4
-#define I40E_PFPM_WUFC_FLX0_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5
-#define I40E_PFPM_WUFC_FLX1_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6
-#define I40E_PFPM_WUFC_FLX2_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7
-#define I40E_PFPM_WUFC_FLX3_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8
-#define I40E_PFPM_WUFC_FLX4_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9
-#define I40E_PFPM_WUFC_FLX5_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10
-#define I40E_PFPM_WUFC_FLX6_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11
-#define I40E_PFPM_WUFC_FLX7_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX0_SHIFT 16
-#define I40E_PFPM_WUFC_FLX0_MASK (0x1 << I40E_PFPM_WUFC_FLX0_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_SHIFT)
#define I40E_PFPM_WUFC_FLX1_SHIFT 17
-#define I40E_PFPM_WUFC_FLX1_MASK (0x1 << I40E_PFPM_WUFC_FLX1_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_SHIFT)
#define I40E_PFPM_WUFC_FLX2_SHIFT 18
-#define I40E_PFPM_WUFC_FLX2_MASK (0x1 << I40E_PFPM_WUFC_FLX2_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_SHIFT)
#define I40E_PFPM_WUFC_FLX3_SHIFT 19
-#define I40E_PFPM_WUFC_FLX3_MASK (0x1 << I40E_PFPM_WUFC_FLX3_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_SHIFT)
#define I40E_PFPM_WUFC_FLX4_SHIFT 20
-#define I40E_PFPM_WUFC_FLX4_MASK (0x1 << I40E_PFPM_WUFC_FLX4_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_SHIFT)
#define I40E_PFPM_WUFC_FLX5_SHIFT 21
-#define I40E_PFPM_WUFC_FLX5_MASK (0x1 << I40E_PFPM_WUFC_FLX5_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_SHIFT)
#define I40E_PFPM_WUFC_FLX6_SHIFT 22
-#define I40E_PFPM_WUFC_FLX6_MASK (0x1 << I40E_PFPM_WUFC_FLX6_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_SHIFT)
#define I40E_PFPM_WUFC_FLX7_SHIFT 23
-#define I40E_PFPM_WUFC_FLX7_MASK (0x1 << I40E_PFPM_WUFC_FLX7_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_SHIFT)
#define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUFC_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
-#define I40E_PFPM_WUS 0x0006B600
+#define I40E_PFPM_WUFC_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
+#define I40E_PFPM_WUS 0x0006B600 /* Reset: POR */
#define I40E_PFPM_WUS_LNKC_SHIFT 0
-#define I40E_PFPM_WUS_LNKC_MASK (0x1 << I40E_PFPM_WUS_LNKC_SHIFT)
+#define I40E_PFPM_WUS_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUS_LNKC_SHIFT)
#define I40E_PFPM_WUS_MAG_SHIFT 1
-#define I40E_PFPM_WUS_MAG_MASK (0x1 << I40E_PFPM_WUS_MAG_SHIFT)
+#define I40E_PFPM_WUS_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MAG_SHIFT)
#define I40E_PFPM_WUS_PME_STATUS_SHIFT 2
-#define I40E_PFPM_WUS_PME_STATUS_MASK (0x1 << I40E_PFPM_WUS_PME_STATUS_SHIFT)
+#define I40E_PFPM_WUS_PME_STATUS_MASK I40E_MASK(0x1, I40E_PFPM_WUS_PME_STATUS_SHIFT)
#define I40E_PFPM_WUS_MNG_SHIFT 3
-#define I40E_PFPM_WUS_MNG_MASK (0x1 << I40E_PFPM_WUS_MNG_SHIFT)
+#define I40E_PFPM_WUS_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MNG_SHIFT)
#define I40E_PFPM_WUS_FLX0_SHIFT 16
-#define I40E_PFPM_WUS_FLX0_MASK (0x1 << I40E_PFPM_WUS_FLX0_SHIFT)
+#define I40E_PFPM_WUS_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX0_SHIFT)
#define I40E_PFPM_WUS_FLX1_SHIFT 17
-#define I40E_PFPM_WUS_FLX1_MASK (0x1 << I40E_PFPM_WUS_FLX1_SHIFT)
+#define I40E_PFPM_WUS_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX1_SHIFT)
#define I40E_PFPM_WUS_FLX2_SHIFT 18
-#define I40E_PFPM_WUS_FLX2_MASK (0x1 << I40E_PFPM_WUS_FLX2_SHIFT)
+#define I40E_PFPM_WUS_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX2_SHIFT)
#define I40E_PFPM_WUS_FLX3_SHIFT 19
-#define I40E_PFPM_WUS_FLX3_MASK (0x1 << I40E_PFPM_WUS_FLX3_SHIFT)
+#define I40E_PFPM_WUS_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX3_SHIFT)
#define I40E_PFPM_WUS_FLX4_SHIFT 20
-#define I40E_PFPM_WUS_FLX4_MASK (0x1 << I40E_PFPM_WUS_FLX4_SHIFT)
+#define I40E_PFPM_WUS_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX4_SHIFT)
#define I40E_PFPM_WUS_FLX5_SHIFT 21
-#define I40E_PFPM_WUS_FLX5_MASK (0x1 << I40E_PFPM_WUS_FLX5_SHIFT)
+#define I40E_PFPM_WUS_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX5_SHIFT)
#define I40E_PFPM_WUS_FLX6_SHIFT 22
-#define I40E_PFPM_WUS_FLX6_MASK (0x1 << I40E_PFPM_WUS_FLX6_SHIFT)
+#define I40E_PFPM_WUS_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX6_SHIFT)
#define I40E_PFPM_WUS_FLX7_SHIFT 23
-#define I40E_PFPM_WUS_FLX7_MASK (0x1 << I40E_PFPM_WUS_FLX7_SHIFT)
+#define I40E_PFPM_WUS_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX7_SHIFT)
#define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUS_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUS_FW_RST_WK_SHIFT)
-#define I40E_PRTPM_FHFHR 0x0006C000
+#define I40E_PFPM_WUS_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FW_RST_WK_SHIFT)
+#define I40E_PRTPM_FHFHR 0x0006C000 /* Reset: POR */
#define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0
-#define I40E_PRTPM_FHFHR_UNICAST_MASK (0x1 << I40E_PRTPM_FHFHR_UNICAST_SHIFT)
+#define I40E_PRTPM_FHFHR_UNICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_UNICAST_SHIFT)
#define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1
-#define I40E_PRTPM_FHFHR_MULTICAST_MASK (0x1 << I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
-#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_FHFHR_MULTICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
+#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
#define I40E_PRTPM_SAH_MAX_INDEX 3
#define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0
-#define I40E_PRTPM_SAH_PFPM_SAH_MASK (0xFFFF << I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
+#define I40E_PRTPM_SAH_PFPM_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
#define I40E_PRTPM_SAH_PF_NUM_SHIFT 26
-#define I40E_PRTPM_SAH_PF_NUM_MASK (0xF << I40E_PRTPM_SAH_PF_NUM_SHIFT)
+#define I40E_PRTPM_SAH_PF_NUM_MASK I40E_MASK(0xF, I40E_PRTPM_SAH_PF_NUM_SHIFT)
#define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30
-#define I40E_PRTPM_SAH_MC_MAG_EN_MASK (0x1 << I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
+#define I40E_PRTPM_SAH_MC_MAG_EN_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
#define I40E_PRTPM_SAH_AV_SHIFT 31
-#define I40E_PRTPM_SAH_AV_MASK (0x1 << I40E_PRTPM_SAH_AV_SHIFT)
-#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAH_AV_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_AV_SHIFT)
+#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
#define I40E_PRTPM_SAL_MAX_INDEX 3
#define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0
-#define I40E_PRTPM_SAL_PFPM_SAL_MASK (0xFFFFFFFF << I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
-#define I40E_VF_ARQBAH1 0x00006000
+#define I40E_PRTPM_SAL_PFPM_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
+#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
#define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH1_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH1_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL1 0x00006C00
+#define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
#define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL1_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL1_ARQBAL_SHIFT)
-#define I40E_VF_ARQH1 0x00007400
+#define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT)
+#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
#define I40E_VF_ARQH1_ARQH_SHIFT 0
-#define I40E_VF_ARQH1_ARQH_MASK (0x3FF << I40E_VF_ARQH1_ARQH_SHIFT)
-#define I40E_VF_ARQLEN1 0x00008000
+#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
#define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN1_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN1_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT)
#define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN1_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
#define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN1_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
#define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN1_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
#define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN1_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT1 0x00007000
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
#define I40E_VF_ARQT1_ARQT_SHIFT 0
-#define I40E_VF_ARQT1_ARQT_MASK (0x3FF << I40E_VF_ARQT1_ARQT_SHIFT)
-#define I40E_VF_ATQBAH1 0x00007800
+#define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT)
+#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
#define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH1_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH1_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL1 0x00007C00
+#define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
#define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL1_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL1_ATQBAL_SHIFT)
-#define I40E_VF_ATQH1 0x00006400
+#define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT)
+#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
#define I40E_VF_ATQH1_ATQH_SHIFT 0
-#define I40E_VF_ATQH1_ATQH_MASK (0x3FF << I40E_VF_ATQH1_ATQH_SHIFT)
-#define I40E_VF_ATQLEN1 0x00006800
+#define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT)
+#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
#define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN1_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN1_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT)
#define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN1_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
#define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN1_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
#define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN1_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
#define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN1_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT1 0x00008400
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
#define I40E_VF_ATQT1_ATQT_SHIFT 0
-#define I40E_VF_ATQT1_ATQT_MASK (0x3FF << I40E_VF_ATQT1_ATQT_SHIFT)
-#define I40E_VFGEN_RSTAT 0x00008800
+#define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT)
+#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
#define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
-#define I40E_VFINT_DYN_CTL01 0x00005C00
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
#define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL01_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4))
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
#define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN1_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0_ENA1 0x00005000
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA1_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
-#define I40E_VFINT_ICR01 0x00004800
+#define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
+#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
#define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR01_INTEVENT_MASK (0x1 << I40E_VFINT_ICR01_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR01_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR01_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR01_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR01_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT)
#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR01_ADMINQ_MASK (0x1 << I40E_VFINT_ICR01_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT)
#define I40E_VFINT_ICR01_SWINT_SHIFT 31
-#define I40E_VFINT_ICR01_SWINT_MASK (0x1 << I40E_VFINT_ICR01_SWINT_SHIFT)
-#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */
+#define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT)
+#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */
#define I40E_VFINT_ITR01_MAX_INDEX 2
#define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR01_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR01_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4))
+#define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
#define I40E_VFINT_ITRN1_MAX_INDEX 2
#define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN1_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN1_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL01 0x00005400
+#define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: VFR */
#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
-#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_QRX_TAIL1_MAX_INDEX 15
#define I40E_QRX_TAIL1_TAIL_SHIFT 0
-#define I40E_QRX_TAIL1_TAIL_MASK (0x1FFF << I40E_QRX_TAIL1_TAIL_SHIFT)
-#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT)
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
#define I40E_QTX_TAIL1_MAX_INDEX 15
#define I40E_QTX_TAIL1_TAIL_SHIFT 0
-#define I40E_QTX_TAIL1_TAIL_MASK (0x1FFF << I40E_QTX_TAIL1_TAIL_SHIFT)
-#define I40E_VFMSIX_PBA 0x00002000
+#define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT)
+#define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */
#define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TADD_MAX_INDEX 16
#define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
#define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TMSG_MAX_INDEX 16
#define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TUADD_MAX_INDEX 16
#define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
#define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFCM_PE_ERRDATA 0x0000DC00
+#define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */
#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
#define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
#define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO 0x0000D800
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */
#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
#define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFPE_AEQALLOC1 0x0000A400
-#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH1 0x00009800
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW1 0x0000AC00
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1 0x0000B800
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK1 0x0000B000
-#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK1_PECQID_SHIFT)
-#define I40E_VFPE_CQARM1 0x0000B400
-#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM1_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB1 0x0000BC00
-#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB1_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES1 0x00009C00
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL1 0x0000A000
-#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG01 0x00008C00
-#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK1 0x00009000
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER1 0x0000A800
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC1 0x0000C000
-#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC1_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
#define I40E_VFQF_HENA_MAX_INDEX 1
#define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */
+#define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
#define I40E_VFQF_HKEY_MAX_INDEX 12
#define I40E_VFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY_KEY_0_MASK (0xFF << I40E_VFQF_HKEY_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT)
#define I40E_VFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY_KEY_1_MASK (0xFF << I40E_VFQF_HKEY_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT)
#define I40E_VFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY_KEY_2_MASK (0xFF << I40E_VFQF_HKEY_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT)
#define I40E_VFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY_KEY_3_MASK (0xFF << I40E_VFQF_HKEY_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_VFQF_HLUT_MAX_INDEX 15
#define I40E_VFQF_HLUT_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT_LUT0_MASK (0xF << I40E_VFQF_HLUT_LUT0_SHIFT)
+#define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT)
#define I40E_VFQF_HLUT_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT_LUT1_MASK (0xF << I40E_VFQF_HLUT_LUT1_SHIFT)
+#define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT)
#define I40E_VFQF_HLUT_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT_LUT2_MASK (0xF << I40E_VFQF_HLUT_LUT2_SHIFT)
+#define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT)
#define I40E_VFQF_HLUT_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT_LUT3_MASK (0xF << I40E_VFQF_HLUT_LUT3_SHIFT)
-#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */
+#define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT)
+#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_VFQF_HREGION_MAX_INDEX 7
#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
#define I40E_VFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION_REGION_0_MASK (0x7 << I40E_VFQF_HREGION_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
#define I40E_VFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION_REGION_1_MASK (0x7 << I40E_VFQF_HREGION_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
#define I40E_VFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION_REGION_2_MASK (0x7 << I40E_VFQF_HREGION_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
#define I40E_VFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION_REGION_3_MASK (0x7 << I40E_VFQF_HREGION_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
#define I40E_VFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION_REGION_4_MASK (0x7 << I40E_VFQF_HREGION_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
#define I40E_VFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION_REGION_5_MASK (0x7 << I40E_VFQF_HREGION_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
#define I40E_VFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION_REGION_6_MASK (0x7 << I40E_VFQF_HREGION_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
#define I40E_VFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
+#define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT)
#endif
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index e49f31dbd5d8..a51aa37b7b5a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -39,6 +39,7 @@ static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
}
#define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
+#define I40E_FD_CLEAN_DELAY 10
/**
* i40e_program_fdir_filter - Program a Flow Director filter
* @fdir_data: Packet data that will be filter parameters
@@ -50,7 +51,7 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
struct i40e_pf *pf, bool add)
{
struct i40e_filter_program_desc *fdir_desc;
- struct i40e_tx_buffer *tx_buf;
+ struct i40e_tx_buffer *tx_buf, *first;
struct i40e_tx_desc *tx_desc;
struct i40e_ring *tx_ring;
unsigned int fpt, dcc;
@@ -58,6 +59,7 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
struct device *dev;
dma_addr_t dma;
u32 td_cmd = 0;
+ u16 delay = 0;
u16 i;
/* find existing FDIR VSI */
@@ -71,6 +73,17 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
tx_ring = vsi->tx_rings[0];
dev = tx_ring->dev;
+ /* we need two descriptors to add/del a filter and we can wait */
+ do {
+ if (I40E_DESC_UNUSED(tx_ring) > 1)
+ break;
+ msleep_interruptible(1);
+ delay++;
+ } while (delay < I40E_FD_CLEAN_DELAY);
+
+ if (!(I40E_DESC_UNUSED(tx_ring) > 1))
+ return -EAGAIN;
+
dma = dma_map_single(dev, raw_packet,
I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma))
@@ -79,8 +92,10 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
/* grab the next descriptor */
i = tx_ring->next_to_use;
fdir_desc = I40E_TX_FDIRDESC(tx_ring, i);
+ first = &tx_ring->tx_bi[i];
+ memset(first, 0, sizeof(struct i40e_tx_buffer));
- tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
+ tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0;
fpt = (fdir_data->q_index << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
I40E_TXD_FLTR_QW0_QINDEX_MASK;
@@ -100,8 +115,6 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
I40E_TXD_FLTR_QW0_DEST_VSI_MASK;
- fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
-
dcc = I40E_TX_DESC_DTYPE_FILTER_PROG;
if (add)
@@ -124,6 +137,8 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
}
+ fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(fpt);
+ fdir_desc->rsvd = cpu_to_le32(0);
fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dcc);
fdir_desc->fd_id = cpu_to_le32(fdir_data->fd_id);
@@ -132,7 +147,9 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
tx_desc = I40E_TX_DESC(tx_ring, i);
tx_buf = &tx_ring->tx_bi[i];
- tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
+ tx_ring->next_to_use = ((i + 1) < tx_ring->count) ? i + 1 : 0;
+
+ memset(tx_buf, 0, sizeof(struct i40e_tx_buffer));
/* record length, and DMA address */
dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_SIZE);
@@ -141,6 +158,9 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
tx_desc->buffer_addr = cpu_to_le64(dma);
td_cmd = I40E_TXD_CMD | I40E_TX_DESC_CMD_DUMMY;
+ tx_buf->tx_flags = I40E_TX_FLAGS_FD_SB;
+ tx_buf->raw_buf = (void *)raw_packet;
+
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_SIZE, 0);
@@ -148,14 +168,12 @@ int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
tx_buf->time_stamp = jiffies;
/* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64).
+ * know there are new descriptors to fetch.
*/
wmb();
/* Mark the data descriptor to be watched */
- tx_buf->next_to_watch = tx_desc;
+ first->next_to_watch = tx_desc;
writel(tx_ring->next_to_use, tx_ring->tail);
return 0;
@@ -170,24 +188,27 @@ dma_fail:
* i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 filters
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
- u8 *raw_packet, bool add)
+ bool add)
{
struct i40e_pf *pf = vsi->back;
struct udphdr *udp;
struct iphdr *ip;
bool err = false;
+ u8 *raw_packet;
int ret;
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+ if (!raw_packet)
+ return -ENOMEM;
memcpy(raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
@@ -220,19 +241,19 @@ static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
* i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 filters
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
- u8 *raw_packet, bool add)
+ bool add)
{
struct i40e_pf *pf = vsi->back;
struct tcphdr *tcp;
struct iphdr *ip;
bool err = false;
+ u8 *raw_packet;
int ret;
/* Dummy packet */
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
@@ -240,6 +261,9 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x11,
0x0, 0x72, 0, 0, 0, 0};
+ raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+ if (!raw_packet)
+ return -ENOMEM;
memcpy(raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
@@ -271,19 +295,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
fd_data->pctype, ret);
}
- fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
-
- ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
- if (ret) {
- dev_info(&pf->pdev->dev,
- "Filter command send failed for PCTYPE %d (ret = %d)\n",
- fd_data->pctype, ret);
- err = true;
- } else {
- dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
- fd_data->pctype, ret);
- }
-
return err ? -EOPNOTSUPP : 0;
}
@@ -292,14 +303,13 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Always returns -EOPNOTSUPP
**/
static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
- u8 *raw_packet, bool add)
+ bool add)
{
return -EOPNOTSUPP;
}
@@ -310,33 +320,36 @@ static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
- * @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
- u8 *raw_packet, bool add)
+ bool add)
{
struct i40e_pf *pf = vsi->back;
struct iphdr *ip;
bool err = false;
+ u8 *raw_packet;
int ret;
int i;
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0};
- memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
- ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
-
- ip->saddr = fd_data->src_ip[0];
- ip->daddr = fd_data->dst_ip[0];
- ip->protocol = 0;
-
for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
i <= I40E_FILTER_PCTYPE_FRAG_IPV4; i++) {
+ raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
+ if (!raw_packet)
+ return -ENOMEM;
+ memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
+ ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
+
+ ip->saddr = fd_data->src_ip[0];
+ ip->daddr = fd_data->dst_ip[0];
+ ip->protocol = 0;
+
fd_data->pctype = i;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
@@ -366,50 +379,34 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add)
{
struct i40e_pf *pf = vsi->back;
- u8 *raw_packet;
int ret;
- /* Populate the Flow Director that we have at the moment
- * and allocate the raw packet buffer for the calling functions
- */
- raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
- if (!raw_packet)
- return -ENOMEM;
-
switch (input->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
- ret = i40e_add_del_fdir_tcpv4(vsi, input, raw_packet,
- add);
+ ret = i40e_add_del_fdir_tcpv4(vsi, input, add);
break;
case UDP_V4_FLOW:
- ret = i40e_add_del_fdir_udpv4(vsi, input, raw_packet,
- add);
+ ret = i40e_add_del_fdir_udpv4(vsi, input, add);
break;
case SCTP_V4_FLOW:
- ret = i40e_add_del_fdir_sctpv4(vsi, input, raw_packet,
- add);
+ ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
break;
case IPV4_FLOW:
- ret = i40e_add_del_fdir_ipv4(vsi, input, raw_packet,
- add);
+ ret = i40e_add_del_fdir_ipv4(vsi, input, add);
break;
case IP_USER_FLOW:
switch (input->ip4_proto) {
case IPPROTO_TCP:
- ret = i40e_add_del_fdir_tcpv4(vsi, input,
- raw_packet, add);
+ ret = i40e_add_del_fdir_tcpv4(vsi, input, add);
break;
case IPPROTO_UDP:
- ret = i40e_add_del_fdir_udpv4(vsi, input,
- raw_packet, add);
+ ret = i40e_add_del_fdir_udpv4(vsi, input, add);
break;
case IPPROTO_SCTP:
- ret = i40e_add_del_fdir_sctpv4(vsi, input,
- raw_packet, add);
+ ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
break;
default:
- ret = i40e_add_del_fdir_ipv4(vsi, input,
- raw_packet, add);
+ ret = i40e_add_del_fdir_ipv4(vsi, input, add);
break;
}
break;
@@ -419,7 +416,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
ret = -EINVAL;
}
- kfree(raw_packet);
+ /* The buffer allocated here is freed by the i40e_clean_tx_ring() */
return ret;
}
@@ -450,22 +447,24 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
rx_desc->wb.qword0.hi_dword.fd_id);
/* filter programming failed most likely due to table full */
- fcnt_prog = i40e_get_current_fd_count(pf);
- fcnt_avail = i40e_get_fd_cnt_all(pf);
+ fcnt_prog = i40e_get_cur_guaranteed_fd_count(pf);
+ fcnt_avail = pf->fdir_pf_filter_count;
/* If ATR is running fcnt_prog can quickly change,
* if we are very close to full, it makes sense to disable
* FD ATR/SB and then re-enable it when there is room.
*/
if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) {
/* Turn off ATR first */
- if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
- pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+ if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+ !(pf->auto_disable_flags &
+ I40E_FLAG_FD_ATR_ENABLED)) {
dev_warn(&pdev->dev, "FD filter space full, ATR for further flows will be turned off\n");
pf->auto_disable_flags |=
I40E_FLAG_FD_ATR_ENABLED;
pf->flags |= I40E_FLAG_FDIR_REQUIRES_REINIT;
- } else if (pf->flags & I40E_FLAG_FD_SB_ENABLED) {
- pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
+ } else if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+ !(pf->auto_disable_flags &
+ I40E_FLAG_FD_SB_ENABLED)) {
dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n");
pf->auto_disable_flags |=
I40E_FLAG_FD_SB_ENABLED;
@@ -491,7 +490,11 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
struct i40e_tx_buffer *tx_buffer)
{
if (tx_buffer->skb) {
- dev_kfree_skb_any(tx_buffer->skb);
+ if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+ kfree(tx_buffer->raw_buf);
+ else
+ dev_kfree_skb_any(tx_buffer->skb);
+
if (dma_unmap_len(tx_buffer, len))
dma_unmap_single(ring->dev,
dma_unmap_addr(tx_buffer, dma),
@@ -893,6 +896,11 @@ static void i40e_clean_programming_status(struct i40e_ring *rx_ring,
if (id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS)
i40e_fd_handle_status(rx_ring, rx_desc, id);
+#ifdef I40E_FCOE
+ else if ((id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS) ||
+ (id == I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS))
+ i40e_fcoe_handle_status(rx_ring, rx_desc, id);
+#endif
}
/**
@@ -1234,8 +1242,6 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
/* likely incorrect csum if alternate IP extension headers found */
if (ipv6 &&
- decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
- rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
/* don't increment checksum err here, non-fatal err */
return;
@@ -1488,6 +1494,12 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
vlan_tag = rx_status & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)
? le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1)
: 0;
+#ifdef I40E_FCOE
+ if (!i40e_fcoe_handle_offload(rx_ring, rx_desc, skb)) {
+ dev_kfree_skb_any(skb);
+ goto next_desc;
+ }
+#endif
i40e_receive_skb(rx_ring, skb, vlan_tag);
rx_ring->netdev->last_rx = jiffies;
@@ -1701,7 +1713,9 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
+ fdir_desc->rsvd = cpu_to_le32(0);
fdir_desc->dtype_cmd_cntindex = cpu_to_le32(dtype_cmd);
+ fdir_desc->fd_id = cpu_to_le32(0);
}
/**
@@ -1716,9 +1730,15 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
* Returns error code indicate the frame should be dropped upon error and the
* otherwise returns 0 to indicate the flags has been set properly.
**/
+#ifdef I40E_FCOE
+int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
+ struct i40e_ring *tx_ring,
+ u32 *flags)
+#else
static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
struct i40e_ring *tx_ring,
u32 *flags)
+#endif
{
__be16 protocol = skb->protocol;
u32 tx_flags = 0;
@@ -1740,9 +1760,8 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
}
/* Insert 802.1p priority into VLAN header */
- if ((tx_ring->vsi->back->flags & I40E_FLAG_DCB_ENABLED) &&
- ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) ||
- (skb->priority != TC_PRIO_CONTROL))) {
+ if ((tx_flags & (I40E_TX_FLAGS_HW_VLAN | I40E_TX_FLAGS_SW_VLAN)) ||
+ (skb->priority != TC_PRIO_CONTROL)) {
tx_flags &= ~I40E_TX_FLAGS_VLAN_PRIO_MASK;
tx_flags |= (skb->priority & 0x7) <<
I40E_TX_FLAGS_VLAN_PRIO_SHIFT;
@@ -1850,7 +1869,8 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb,
* we are not already transmitting a packet to be timestamped
*/
pf = i40e_netdev_to_pf(tx_ring->netdev);
- if (pf->ptp_tx && !pf->ptp_tx_skb) {
+ if (pf->ptp_tx &&
+ !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, &pf->state)) {
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
pf->ptp_tx_skb = skb_get(skb);
} else {
@@ -2000,6 +2020,7 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
/* cpu_to_le32 and assign to struct fields */
context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+ context_desc->rsvd = cpu_to_le16(0);
context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
}
@@ -2013,9 +2034,15 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
* @td_cmd: the command field in the descriptor
* @td_offset: offset for checksum or crc
**/
+#ifdef I40E_FCOE
+void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+ struct i40e_tx_buffer *first, u32 tx_flags,
+ const u8 hdr_len, u32 td_cmd, u32 td_offset)
+#else
static void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
struct i40e_tx_buffer *first, u32 tx_flags,
const u8 hdr_len, u32 td_cmd, u32 td_offset)
+#endif
{
unsigned int data_len = skb->data_len;
unsigned int size = skb_headlen(skb);
@@ -2192,7 +2219,11 @@ static inline int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
*
* Returns 0 if stop is not needed
**/
+#ifdef I40E_FCOE
+int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#else
static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
+#endif
{
if (likely(I40E_DESC_UNUSED(tx_ring) >= size))
return 0;
@@ -2208,8 +2239,13 @@ static int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size)
* there is not enough descriptors available in this ring since we need at least
* one descriptor.
**/
+#ifdef I40E_FCOE
+int i40e_xmit_descriptor_count(struct sk_buff *skb,
+ struct i40e_ring *tx_ring)
+#else
static int i40e_xmit_descriptor_count(struct sk_buff *skb,
struct i40e_ring *tx_ring)
+#endif
{
unsigned int f;
int count = 0;
@@ -2278,13 +2314,13 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
else if (tso)
tx_flags |= I40E_TX_FLAGS_TSO;
- skb_tx_timestamp(skb);
-
tsyn = i40e_tsyn(tx_ring, skb, tx_flags, &cd_type_cmd_tso_mss);
if (tsyn)
tx_flags |= I40E_TX_FLAGS_TSYN;
+ skb_tx_timestamp(skb);
+
/* always enable CRC insertion offload */
td_cmd |= I40E_TX_DESC_CMD_ICRC;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index 0277894fe1c4..73f4fa425697 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
- ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
@@ -132,6 +131,7 @@ enum i40e_dyn_idx_t {
#define I40E_TX_FLAGS_FCCRC (u32)(1 << 6)
#define I40E_TX_FLAGS_FSO (u32)(1 << 7)
#define I40E_TX_FLAGS_TSYN (u32)(1 << 8)
+#define I40E_TX_FLAGS_FD_SB (u32)(1 << 9)
#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000
#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29
@@ -140,7 +140,10 @@ enum i40e_dyn_idx_t {
struct i40e_tx_buffer {
struct i40e_tx_desc *next_to_watch;
unsigned long time_stamp;
- struct sk_buff *skb;
+ union {
+ struct sk_buff *skb;
+ void *raw_buf;
+ };
unsigned int bytecount;
unsigned short gso_segs;
DEFINE_DMA_UNMAP_ADDR(dma);
@@ -287,4 +290,13 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring);
void i40e_free_tx_resources(struct i40e_ring *tx_ring);
void i40e_free_rx_resources(struct i40e_ring *rx_ring);
int i40e_napi_poll(struct napi_struct *napi, int budget);
+#ifdef I40E_FCOE
+void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
+ struct i40e_tx_buffer *first, u32 tx_flags,
+ const u8 hdr_len, u32 td_cmd, u32 td_offset);
+int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
+int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring);
+int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
+ struct i40e_ring *tx_ring, u32 *flags);
+#endif
#endif /* _I40E_TXRX_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index 9d39ff23c5fb..ce04d9093db6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -50,6 +50,9 @@
(d) == I40E_DEV_ID_QSFP_B || \
(d) == I40E_DEV_ID_QSFP_C)
+/* I40E_MASK is a macro used on 32 bit registers */
+#define I40E_MASK(mask, shift) (mask << shift)
+
#define I40E_MAX_VSI_QP 16
#define I40E_MAX_VF_VSI 3
#define I40E_MAX_CHAINED_RX_BUFFERS 5
@@ -137,6 +140,14 @@ enum i40e_fc_mode {
I40E_FC_DEFAULT
};
+enum i40e_set_fc_aq_failures {
+ I40E_SET_FC_AQ_FAIL_NONE = 0,
+ I40E_SET_FC_AQ_FAIL_GET = 1,
+ I40E_SET_FC_AQ_FAIL_SET = 2,
+ I40E_SET_FC_AQ_FAIL_UPDATE = 4,
+ I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6
+};
+
enum i40e_vsi_type {
I40E_VSI_MAIN = 0,
I40E_VSI_VMDQ1,
@@ -163,6 +174,7 @@ struct i40e_link_status {
u8 an_info;
u8 ext_info;
u8 loopback;
+ bool an_enabled;
/* is Link Status Event notification to SW enabled */
bool lse_enable;
u16 max_frame_size;
@@ -234,6 +246,7 @@ struct i40e_mac_info {
u8 addr[ETH_ALEN];
u8 perm_addr[ETH_ALEN];
u8 san_addr[ETH_ALEN];
+ u8 port_addr[ETH_ALEN];
u16 max_fcoeq;
};
@@ -256,6 +269,61 @@ struct i40e_nvm_info {
u32 eetrack; /* NVM data version */
};
+/* definitions used in NVM update support */
+
+enum i40e_nvmupd_cmd {
+ I40E_NVMUPD_INVALID,
+ I40E_NVMUPD_READ_CON,
+ I40E_NVMUPD_READ_SNT,
+ I40E_NVMUPD_READ_LCB,
+ I40E_NVMUPD_READ_SA,
+ I40E_NVMUPD_WRITE_ERA,
+ I40E_NVMUPD_WRITE_CON,
+ I40E_NVMUPD_WRITE_SNT,
+ I40E_NVMUPD_WRITE_LCB,
+ I40E_NVMUPD_WRITE_SA,
+ I40E_NVMUPD_CSUM_CON,
+ I40E_NVMUPD_CSUM_SA,
+ I40E_NVMUPD_CSUM_LCB,
+};
+
+enum i40e_nvmupd_state {
+ I40E_NVMUPD_STATE_INIT,
+ I40E_NVMUPD_STATE_READING,
+ I40E_NVMUPD_STATE_WRITING
+};
+
+/* nvm_access definition and its masks/shifts need to be accessible to
+ * application, core driver, and shared code. Where is the right file?
+ */
+#define I40E_NVM_READ 0xB
+#define I40E_NVM_WRITE 0xC
+
+#define I40E_NVM_MOD_PNT_MASK 0xFF
+
+#define I40E_NVM_TRANS_SHIFT 8
+#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
+#define I40E_NVM_CON 0x0
+#define I40E_NVM_SNT 0x1
+#define I40E_NVM_LCB 0x2
+#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
+#define I40E_NVM_ERA 0x4
+#define I40E_NVM_CSUM 0x8
+
+#define I40E_NVM_ADAPT_SHIFT 16
+#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
+
+#define I40E_NVMUPD_MAX_DATA 4096
+#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
+
+struct i40e_nvm_access {
+ u32 command;
+ u32 config;
+ u32 offset; /* in bytes */
+ u32 data_size; /* in bytes */
+ u8 data[1];
+};
+
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
@@ -391,6 +459,9 @@ struct i40e_hw {
/* Admin Queue info */
struct i40e_adminq_info aq;
+ /* state of nvm update process */
+ enum i40e_nvmupd_state nvmupd_state;
+
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
@@ -875,7 +946,6 @@ enum i40e_filter_pctype {
I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
/* Note: Values 37-40 are reserved for future use */
I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
- I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,
@@ -981,6 +1051,25 @@ struct i40e_eth_stats {
u64 tx_errors; /* tepc */
};
+#ifdef I40E_FCOE
+/* Statistics collected per function for FCoE */
+struct i40e_fcoe_stats {
+ u64 rx_fcoe_packets; /* fcoeprc */
+ u64 rx_fcoe_dwords; /* focedwrc */
+ u64 rx_fcoe_dropped; /* fcoerpdc */
+ u64 tx_fcoe_packets; /* fcoeptc */
+ u64 tx_fcoe_dwords; /* focedwtc */
+ u64 fcoe_bad_fccrc; /* fcoecrc */
+ u64 fcoe_last_error; /* fcoelast */
+ u64 fcoe_ddp_count; /* fcoeddpc */
+};
+
+/* offset to per function FCoE statistics block */
+#define I40E_FCOE_VF_STAT_OFFSET 0
+#define I40E_FCOE_PF_STAT_OFFSET 128
+#define I40E_FCOE_STAT_MAX (I40E_FCOE_PF_STAT_OFFSET + I40E_MAX_PF)
+
+#endif
/* Statistics collected by the MAC */
struct i40e_hw_port_stats {
/* eth stats collected by the port */
@@ -1061,6 +1150,125 @@ struct i40e_hw_port_stats {
#define I40E_SRRD_SRCTL_ATTEMPTS 100000
+#ifdef I40E_FCOE
+/* FCoE Tx context descriptor - Use the i40e_tx_context_desc struct */
+
+enum i40E_fcoe_tx_ctx_desc_cmd_bits {
+ I40E_FCOE_TX_CTX_DESC_OPCODE_SINGLE_SEND = 0x00, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS2 = 0x01, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_TSO_FC_CLASS3 = 0x05, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS2 = 0x02, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_ETSO_FC_CLASS3 = 0x06, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS2 = 0x03, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_FC_CLASS3 = 0x07, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_DDP_CTX_INVL = 0x08, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_OPCODE_DWO_CTX_INVL = 0x09, /* 4 BITS */
+ I40E_FCOE_TX_CTX_DESC_RELOFF = 0x10,
+ I40E_FCOE_TX_CTX_DESC_CLRSEQ = 0x20,
+ I40E_FCOE_TX_CTX_DESC_DIFENA = 0x40,
+ I40E_FCOE_TX_CTX_DESC_IL2TAG2 = 0x80
+};
+
+/* FCoE DDP Context descriptor */
+struct i40e_fcoe_ddp_context_desc {
+ __le64 rsvd;
+ __le64 type_cmd_foff_lsize;
+};
+
+#define I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT 0
+#define I40E_FCOE_DDP_CTX_QW1_DTYPE_MASK (0xFULL << \
+ I40E_FCOE_DDP_CTX_QW1_DTYPE_SHIFT)
+
+#define I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT 4
+#define I40E_FCOE_DDP_CTX_QW1_CMD_MASK (0xFULL << \
+ I40E_FCOE_DDP_CTX_QW1_CMD_SHIFT)
+
+enum i40e_fcoe_ddp_ctx_desc_cmd_bits {
+ I40E_FCOE_DDP_CTX_DESC_BSIZE_512B = 0x00, /* 2 BITS */
+ I40E_FCOE_DDP_CTX_DESC_BSIZE_4K = 0x01, /* 2 BITS */
+ I40E_FCOE_DDP_CTX_DESC_BSIZE_8K = 0x02, /* 2 BITS */
+ I40E_FCOE_DDP_CTX_DESC_BSIZE_16K = 0x03, /* 2 BITS */
+ I40E_FCOE_DDP_CTX_DESC_DIFENA = 0x04, /* 1 BIT */
+ I40E_FCOE_DDP_CTX_DESC_LASTSEQH = 0x08, /* 1 BIT */
+};
+
+#define I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT 16
+#define I40E_FCOE_DDP_CTX_QW1_FOFF_MASK (0x3FFFULL << \
+ I40E_FCOE_DDP_CTX_QW1_FOFF_SHIFT)
+
+#define I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT 32
+#define I40E_FCOE_DDP_CTX_QW1_LSIZE_MASK (0x3FFFULL << \
+ I40E_FCOE_DDP_CTX_QW1_LSIZE_SHIFT)
+
+/* FCoE DDP/DWO Queue Context descriptor */
+struct i40e_fcoe_queue_context_desc {
+ __le64 dmaindx_fbase; /* 0:11 DMAINDX, 12:63 FBASE */
+ __le64 flen_tph; /* 0:12 FLEN, 13:15 TPH */
+};
+
+#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT 0
+#define I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_MASK (0xFFFULL << \
+ I40E_FCOE_QUEUE_CTX_QW0_DMAINDX_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT 12
+#define I40E_FCOE_QUEUE_CTX_QW0_FBASE_MASK (0xFFFFFFFFFFFFFULL << \
+ I40E_FCOE_QUEUE_CTX_QW0_FBASE_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT 0
+#define I40E_FCOE_QUEUE_CTX_QW1_FLEN_MASK (0x1FFFULL << \
+ I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
+
+#define I40E_FCOE_QUEUE_CTX_QW1_TPH_SHIFT 13
+#define I40E_FCOE_QUEUE_CTX_QW1_TPH_MASK (0x7ULL << \
+ I40E_FCOE_QUEUE_CTX_QW1_FLEN_SHIFT)
+
+enum i40e_fcoe_queue_ctx_desc_tph_bits {
+ I40E_FCOE_QUEUE_CTX_DESC_TPHRDESC = 0x1,
+ I40E_FCOE_QUEUE_CTX_DESC_TPHDATA = 0x2
+};
+
+#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT 30
+#define I40E_FCOE_QUEUE_CTX_QW1_RECIPE_MASK (0x3ULL << \
+ I40E_FCOE_QUEUE_CTX_QW1_RECIPE_SHIFT)
+
+/* FCoE DDP/DWO Filter Context descriptor */
+struct i40e_fcoe_filter_context_desc {
+ __le32 param;
+ __le16 seqn;
+
+ /* 48:51(0:3) RSVD, 52:63(4:15) DMAINDX */
+ __le16 rsvd_dmaindx;
+
+ /* 0:7 FLAGS, 8:52 RSVD, 53:63 LANQ */
+ __le64 flags_rsvd_lanq;
+};
+
+#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT 4
+#define I40E_FCOE_FILTER_CTX_QW0_DMAINDX_MASK (0xFFF << \
+ I40E_FCOE_FILTER_CTX_QW0_DMAINDX_SHIFT)
+
+enum i40e_fcoe_filter_ctx_desc_flags_bits {
+ I40E_FCOE_FILTER_CTX_DESC_CTYP_DDP = 0x00,
+ I40E_FCOE_FILTER_CTX_DESC_CTYP_DWO = 0x01,
+ I40E_FCOE_FILTER_CTX_DESC_ENODE_INIT = 0x00,
+ I40E_FCOE_FILTER_CTX_DESC_ENODE_RSP = 0x02,
+ I40E_FCOE_FILTER_CTX_DESC_FC_CLASS2 = 0x00,
+ I40E_FCOE_FILTER_CTX_DESC_FC_CLASS3 = 0x04
+};
+
+#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT 0
+#define I40E_FCOE_FILTER_CTX_QW1_FLAGS_MASK (0xFFULL << \
+ I40E_FCOE_FILTER_CTX_QW1_FLAGS_SHIFT)
+
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8
+#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_MASK (0x3FULL << \
+ I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT)
+
+#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT 53
+#define I40E_FCOE_FILTER_CTX_QW1_LANQINDX_MASK (0x7FFULL << \
+ I40E_FCOE_FILTER_CTX_QW1_LANQINDX_SHIFT)
+
+#endif /* I40E_FCOE */
enum i40e_switch_element_types {
I40E_SWITCH_ELEMENT_TYPE_MAC = 1,
I40E_SWITCH_ELEMENT_TYPE_PF = 2,
@@ -1162,4 +1370,7 @@ enum i40e_reset_type {
I40E_RESET_GLOBR = 2,
I40E_RESET_EMPR = 3,
};
+
+/* RSS Hash Table Size */
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000
#endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index f5b9d2062573..89672551dce9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -347,10 +347,6 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_idx,
rx_ctx.dsize = 1;
/* default values */
- rx_ctx.tphrdesc_ena = 1;
- rx_ctx.tphwdesc_ena = 1;
- rx_ctx.tphdata_ena = 1;
- rx_ctx.tphhead_ena = 1;
rx_ctx.lrxqthresh = 2;
rx_ctx.crcstrip = 1;
rx_ctx.prefena = 1;
@@ -673,7 +669,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
*/
for (i = 0; i < 100; i++) {
/* vf reset requires driver to first reset the
- * vf & than poll the status register to make sure
+ * vf and then poll the status register to make sure
* that the requested op was completed
* successfully
*/
@@ -1009,7 +1005,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
{
struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw;
- int true_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
+ int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
i40e_status aq_ret;
/* single place to detect unsuccessful return values */
@@ -1029,7 +1025,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode,
vf->num_valid_msgs++;
}
- aq_ret = i40e_aq_send_msg_to_vf(hw, true_vf_id, v_opcode, v_retval,
+ aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
msg, msglen, NULL);
if (aq_ret) {
dev_err(&pf->pdev->dev,
@@ -1167,8 +1163,8 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
(struct i40e_virtchnl_promisc_info *)msg;
struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw;
+ struct i40e_vsi *vsi;
bool allmulti = false;
- bool promisc = false;
i40e_status aq_ret;
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
@@ -1178,17 +1174,10 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,
aq_ret = I40E_ERR_PARAM;
goto error_param;
}
-
- if (info->flags & I40E_FLAG_VF_UNICAST_PROMISC)
- promisc = true;
- aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, info->vsi_id,
- promisc, NULL);
- if (aq_ret)
- goto error_param;
-
+ vsi = pf->vsi[info->vsi_id];
if (info->flags & I40E_FLAG_VF_MULTICAST_PROMISC)
allmulti = true;
- aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, info->vsi_id,
+ aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
allmulti, NULL);
error_param:
@@ -1939,15 +1928,17 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
{
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf = pf->vf;
+ int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
int i;
for (i = 0; i < pf->num_alloc_vfs; i++) {
/* Ignore return value on purpose - a given VF may fail, but
* we need to keep going and send to all of them
*/
- i40e_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval,
+ i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval,
msg, msglen, NULL);
vf++;
+ abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
}
}
@@ -1963,6 +1954,7 @@ void i40e_vc_notify_link_state(struct i40e_pf *pf)
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf = pf->vf;
struct i40e_link_status *ls = &pf->hw.phy.link_info;
+ int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
int i;
pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
@@ -1977,10 +1969,11 @@ void i40e_vc_notify_link_state(struct i40e_pf *pf)
ls->link_info & I40E_AQ_LINK_UP;
pfe.event_data.link_event.link_speed = ls->link_speed;
}
- i40e_aq_send_msg_to_vf(hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+ i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe),
NULL);
vf++;
+ abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
}
}
@@ -2009,10 +2002,11 @@ void i40e_vc_notify_reset(struct i40e_pf *pf)
void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
{
struct i40e_virtchnl_pf_event pfe;
+ int abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id;
pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING;
pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM;
- i40e_aq_send_msg_to_vf(&vf->pf->hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+ i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
I40E_SUCCESS, (u8 *)&pfe,
sizeof(struct i40e_virtchnl_pf_event), NULL);
}
@@ -2077,6 +2071,8 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
}
ether_addr_copy(vf->default_lan_addr.addr, mac);
vf->pf_set_mac = true;
+ /* Force the VF driver stop so it has to reload with new MAC address */
+ i40e_vc_disable_vf(pf, vf);
dev_info(&pf->pdev->dev, "Reload the VF driver to make this change effective.\n");
ret = 0;
@@ -2347,6 +2343,7 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
struct i40e_virtchnl_pf_event pfe;
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf;
+ int abs_vf_id;
int ret = 0;
/* validate the request */
@@ -2357,6 +2354,7 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
}
vf = &pf->vf[vf_id];
+ abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
pfe.severity = I40E_PF_EVENT_SEVERITY_INFO;
@@ -2386,7 +2384,7 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
goto error_out;
}
/* Notify the VF of its new link state */
- i40e_aq_send_msg_to_vf(hw, vf->vf_id, I40E_VIRTCHNL_OP_EVENT,
+ i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe), NULL);
error_out:
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
index eb67cce3e8f9..003006033614 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
@@ -53,16 +53,24 @@ static void i40e_adminq_init_regs(struct i40e_hw *hw)
hw->aq.asq.tail = I40E_VF_ATQT1;
hw->aq.asq.head = I40E_VF_ATQH1;
hw->aq.asq.len = I40E_VF_ATQLEN1;
+ hw->aq.asq.bal = I40E_VF_ATQBAL1;
+ hw->aq.asq.bah = I40E_VF_ATQBAH1;
hw->aq.arq.tail = I40E_VF_ARQT1;
hw->aq.arq.head = I40E_VF_ARQH1;
hw->aq.arq.len = I40E_VF_ARQLEN1;
+ hw->aq.arq.bal = I40E_VF_ARQBAL1;
+ hw->aq.arq.bah = I40E_VF_ARQBAH1;
} else {
hw->aq.asq.tail = I40E_PF_ATQT;
hw->aq.asq.head = I40E_PF_ATQH;
hw->aq.asq.len = I40E_PF_ATQLEN;
+ hw->aq.asq.bal = I40E_PF_ATQBAL;
+ hw->aq.asq.bah = I40E_PF_ATQBAH;
hw->aq.arq.tail = I40E_PF_ARQT;
hw->aq.arq.head = I40E_PF_ARQH;
hw->aq.arq.len = I40E_PF_ARQLEN;
+ hw->aq.arq.bal = I40E_PF_ARQBAL;
+ hw->aq.arq.bah = I40E_PF_ARQBAH;
}
}
@@ -294,27 +302,18 @@ static i40e_status i40e_config_asq_regs(struct i40e_hw *hw)
i40e_status ret_code = 0;
u32 reg = 0;
- if (hw->mac.type == I40E_MAC_VF) {
- /* configure the transmit queue */
- wr32(hw, I40E_VF_ATQBAH1,
- upper_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_VF_ATQBAL1,
- lower_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_VF_ATQLEN1, (hw->aq.num_asq_entries |
- I40E_VF_ATQLEN1_ATQENABLE_MASK));
- reg = rd32(hw, I40E_VF_ATQBAL1);
- } else {
- /* configure the transmit queue */
- wr32(hw, I40E_PF_ATQBAH,
- upper_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_PF_ATQBAL,
- lower_32_bits(hw->aq.asq.desc_buf.pa));
- wr32(hw, I40E_PF_ATQLEN, (hw->aq.num_asq_entries |
- I40E_PF_ATQLEN_ATQENABLE_MASK));
- reg = rd32(hw, I40E_PF_ATQBAL);
- }
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.asq.head, 0);
+ wr32(hw, hw->aq.asq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries |
+ I40E_PF_ATQLEN_ATQENABLE_MASK));
+ wr32(hw, hw->aq.asq.bal, lower_32_bits(hw->aq.asq.desc_buf.pa));
+ wr32(hw, hw->aq.asq.bah, upper_32_bits(hw->aq.asq.desc_buf.pa));
/* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.asq.bal);
if (reg != lower_32_bits(hw->aq.asq.desc_buf.pa))
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
@@ -332,30 +331,21 @@ static i40e_status i40e_config_arq_regs(struct i40e_hw *hw)
i40e_status ret_code = 0;
u32 reg = 0;
- if (hw->mac.type == I40E_MAC_VF) {
- /* configure the receive queue */
- wr32(hw, I40E_VF_ARQBAH1,
- upper_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_VF_ARQBAL1,
- lower_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_VF_ARQLEN1, (hw->aq.num_arq_entries |
- I40E_VF_ARQLEN1_ARQENABLE_MASK));
- reg = rd32(hw, I40E_VF_ARQBAL1);
- } else {
- /* configure the receive queue */
- wr32(hw, I40E_PF_ARQBAH,
- upper_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_PF_ARQBAL,
- lower_32_bits(hw->aq.arq.desc_buf.pa));
- wr32(hw, I40E_PF_ARQLEN, (hw->aq.num_arq_entries |
- I40E_PF_ARQLEN_ARQENABLE_MASK));
- reg = rd32(hw, I40E_PF_ARQBAL);
- }
+ /* Clear Head and Tail */
+ wr32(hw, hw->aq.arq.head, 0);
+ wr32(hw, hw->aq.arq.tail, 0);
+
+ /* set starting point */
+ wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries |
+ I40E_PF_ARQLEN_ARQENABLE_MASK));
+ wr32(hw, hw->aq.arq.bal, lower_32_bits(hw->aq.arq.desc_buf.pa));
+ wr32(hw, hw->aq.arq.bah, upper_32_bits(hw->aq.arq.desc_buf.pa));
/* Update tail in the HW to post pre-allocated buffers */
wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1);
/* Check one register to verify that config was applied */
+ reg = rd32(hw, hw->aq.arq.bal);
if (reg != lower_32_bits(hw->aq.arq.desc_buf.pa))
ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
@@ -497,6 +487,8 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
wr32(hw, hw->aq.asq.head, 0);
wr32(hw, hw->aq.asq.tail, 0);
wr32(hw, hw->aq.asq.len, 0);
+ wr32(hw, hw->aq.asq.bal, 0);
+ wr32(hw, hw->aq.asq.bah, 0);
/* make sure lock is available */
mutex_lock(&hw->aq.asq_mutex);
@@ -528,6 +520,8 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
wr32(hw, hw->aq.arq.head, 0);
wr32(hw, hw->aq.arq.tail, 0);
wr32(hw, hw->aq.arq.len, 0);
+ wr32(hw, hw->aq.arq.bal, 0);
+ wr32(hw, hw->aq.arq.bah, 0);
/* make sure lock is available */
mutex_lock(&hw->aq.arq_mutex);
@@ -573,6 +567,9 @@ i40e_status i40evf_init_adminq(struct i40e_hw *hw)
/* Set up register offsets */
i40e_adminq_init_regs(hw);
+ /* setup ASQ command write back timeout */
+ hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT;
+
/* allocate the ASQ */
ret_code = i40e_init_asq(hw);
if (ret_code)
@@ -630,6 +627,10 @@ static u16 i40e_clean_asq(struct i40e_hw *hw)
desc = I40E_ADMINQ_DESC(*asq, ntc);
details = I40E_ADMINQ_DETAILS(*asq, ntc);
while (rd32(hw, hw->aq.asq.head) != ntc) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "%s: ntc %d head %d.\n", __func__, ntc,
+ rd32(hw, hw->aq.asq.head));
+
if (details->callback) {
I40E_ADMINQ_CALLBACK cb_func =
(I40E_ADMINQ_CALLBACK)details->callback;
@@ -690,17 +691,20 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
struct i40e_aq_desc *desc_on_ring;
bool cmd_completed = false;
u16 retval = 0;
+ u32 val = 0;
- if (hw->aq.asq.count == 0) {
+ val = rd32(hw, hw->aq.asq.head);
+ if (val >= hw->aq.num_asq_entries) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
- "AQTX: Admin queue not initialized.\n");
+ "AQTX: head overrun at %d\n", val);
status = I40E_ERR_QUEUE_EMPTY;
goto asq_send_command_exit;
}
- if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
- i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
- status = I40E_ERR_NVM;
+ if (hw->aq.asq.count == 0) {
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: Admin queue not initialized.\n");
+ status = I40E_ERR_QUEUE_EMPTY;
goto asq_send_command_exit;
}
@@ -783,6 +787,7 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
}
/* bump the tail */
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n");
i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff);
(hw->aq.asq.next_to_use)++;
if (hw->aq.asq.next_to_use == hw->aq.asq.count)
@@ -806,7 +811,7 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
/* ugh! delay while spin_lock */
udelay(delay_len);
total_delay += delay_len;
- } while (total_delay < I40E_ASQ_CMD_TIMEOUT);
+ } while (total_delay < hw->aq.asq_cmd_timeout);
}
/* if ready, copy the desc back to temp */
@@ -820,6 +825,7 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQTX: Command completed with error 0x%X.\n",
retval);
+
/* strip off FW internal code */
retval &= 0xff;
}
@@ -834,6 +840,10 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+ "AQTX: desc and buffer writeback:\n");
+ i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff);
+
/* update the error if time out occurred */
if ((!cmd_completed) &&
(!details->async && !details->postpone)) {
@@ -905,10 +915,6 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
/* now clean the next descriptor */
desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
desc_idx = ntc;
- i40evf_debug_aq(hw,
- I40E_DEBUG_AQ_COMMAND,
- (void *)desc,
- hw->aq.arq.r.arq_bi[desc_idx].va);
flags = le16_to_cpu(desc->flags);
if (flags & I40E_AQ_FLAG_ERR) {
@@ -919,18 +925,21 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
I40E_DEBUG_AQ_MESSAGE,
"AQRX: Event received with error 0x%X.\n",
hw->aq.arq_last_status);
- } else {
- e->desc = *desc;
- datalen = le16_to_cpu(desc->datalen);
- e->msg_size = min(datalen, e->msg_size);
- if (e->msg_buf != NULL && (e->msg_size != 0))
- memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
- e->msg_size);
}
+ e->desc = *desc;
+ datalen = le16_to_cpu(desc->datalen);
+ e->msg_size = min(datalen, e->msg_size);
+ if (e->msg_buf != NULL && (e->msg_size != 0))
+ memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va,
+ e->msg_size);
+
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
+ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n");
+ i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf);
+
/* Restore the original datalen and buffer address in the desc,
* FW updates datalen to indicate the event message
* size
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
index e3472c62e155..91a5c5bd80f3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h
@@ -56,6 +56,8 @@ struct i40e_adminq_ring {
u32 head;
u32 tail;
u32 len;
+ u32 bah;
+ u32 bal;
};
/* ASQ transaction details */
@@ -82,6 +84,7 @@ struct i40e_arq_event_info {
struct i40e_adminq_info {
struct i40e_adminq_ring arq; /* receive queue */
struct i40e_adminq_ring asq; /* send queue */
+ u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
u16 num_arq_entries; /* receive queue depth */
u16 num_asq_entries; /* send queue depth */
u16 arq_buf_size; /* receive queue buffer size */
@@ -91,6 +94,7 @@ struct i40e_adminq_info {
u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */
bool nvm_busy;
+ bool nvm_release_on_done;
struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */
@@ -100,6 +104,41 @@ struct i40e_adminq_info {
enum i40e_admin_queue_err arq_last_status;
};
+/**
+ * i40e_aq_rc_to_posix - convert errors to user-land codes
+ * aq_rc: AdminQ error code to convert
+ **/
+static inline int i40e_aq_rc_to_posix(u16 aq_rc)
+{
+ int aq_to_posix[] = {
+ 0, /* I40E_AQ_RC_OK */
+ -EPERM, /* I40E_AQ_RC_EPERM */
+ -ENOENT, /* I40E_AQ_RC_ENOENT */
+ -ESRCH, /* I40E_AQ_RC_ESRCH */
+ -EINTR, /* I40E_AQ_RC_EINTR */
+ -EIO, /* I40E_AQ_RC_EIO */
+ -ENXIO, /* I40E_AQ_RC_ENXIO */
+ -E2BIG, /* I40E_AQ_RC_E2BIG */
+ -EAGAIN, /* I40E_AQ_RC_EAGAIN */
+ -ENOMEM, /* I40E_AQ_RC_ENOMEM */
+ -EACCES, /* I40E_AQ_RC_EACCES */
+ -EFAULT, /* I40E_AQ_RC_EFAULT */
+ -EBUSY, /* I40E_AQ_RC_EBUSY */
+ -EEXIST, /* I40E_AQ_RC_EEXIST */
+ -EINVAL, /* I40E_AQ_RC_EINVAL */
+ -ENOTTY, /* I40E_AQ_RC_ENOTTY */
+ -ENOSPC, /* I40E_AQ_RC_ENOSPC */
+ -ENOSYS, /* I40E_AQ_RC_ENOSYS */
+ -ERANGE, /* I40E_AQ_RC_ERANGE */
+ -EPIPE, /* I40E_AQ_RC_EFLUSHED */
+ -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
+ -EROFS, /* I40E_AQ_RC_EMODE */
+ -EFBIG, /* I40E_AQ_RC_EFBIG */
+ };
+
+ return aq_to_posix[aq_rc];
+}
+
/* general information */
#define I40E_AQ_LARGE_BUF 512
#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
index a43155afdbe2..4ea90bf239bb 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
@@ -551,6 +551,7 @@ i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
+ struct i40e_asq_cmd_details details;
i40e_status status;
i40evf_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf);
@@ -565,7 +566,6 @@ i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
desc.datalen = cpu_to_le16(msglen);
}
if (!cmd_details) {
- struct i40e_asq_cmd_details details;
memset(&details, 0, sizeof(details));
details.async = true;
cmd_details = &details;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
index a2ad9a4e399d..931c88044300 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_hmc.h
@@ -127,7 +127,7 @@ struct i40e_hmc_info {
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \
(1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \
- val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
+ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
wr32((hw), I40E_PFHMC_SDCMD, val3); \
@@ -146,7 +146,7 @@ struct i40e_hmc_info {
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \
- val3 = (sd_index) | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
+ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
wr32((hw), I40E_PFHMC_SDCMD, val3); \
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h b/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
index d6f762241537..a5d79877354c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_lan_hmc.h
@@ -32,16 +32,22 @@ struct i40e_hw;
/* HMC element context information */
-/* Rx queue context data */
+/* Rx queue context data
+ *
+ * The sizes of the variables may be larger than needed due to crossing byte
+ * boundaries. If we do not have the width of the variable set to the correct
+ * size then we could end up shifting bits off the top of the variable when the
+ * variable is at the top of a byte and crosses over into the next byte.
+ */
struct i40e_hmc_obj_rxq {
u16 head;
- u8 cpuid;
+ u16 cpuid; /* bigger than needed, see above for reason */
u64 base;
u16 qlen;
#define I40E_RXQ_CTX_DBUFF_SHIFT 7
- u8 dbuff;
+ u16 dbuff; /* bigger than needed, see above for reason */
#define I40E_RXQ_CTX_HBUFF_SHIFT 6
- u8 hbuff;
+ u16 hbuff; /* bigger than needed, see above for reason */
u8 dtype;
u8 dsize;
u8 crcstrip;
@@ -50,16 +56,22 @@ struct i40e_hmc_obj_rxq {
u8 hsplit_0;
u8 hsplit_1;
u8 showiv;
- u16 rxmax;
+ u32 rxmax; /* bigger than needed, see above for reason */
u8 tphrdesc_ena;
u8 tphwdesc_ena;
u8 tphdata_ena;
u8 tphhead_ena;
- u8 lrxqthresh;
+ u16 lrxqthresh; /* bigger than needed, see above for reason */
u8 prefena; /* NOTE: normally must be set to 1 at init */
};
-/* Tx queue context data */
+/* Tx queue context data
+*
+* The sizes of the variables may be larger than needed due to crossing byte
+* boundaries. If we do not have the width of the variable set to the correct
+* size then we could end up shifting bits off the top of the variable when the
+* variable is at the top of a byte and crosses over into the next byte.
+*/
struct i40e_hmc_obj_txq {
u16 head;
u8 new_context;
@@ -69,7 +81,7 @@ struct i40e_hmc_obj_txq {
u8 fd_ena;
u8 alt_vlan_ena;
u16 thead_wb;
- u16 cpuid;
+ u8 cpuid;
u8 head_wb_ena;
u16 qlen;
u8 tphrdesc_ena;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_register.h b/drivers/net/ethernet/intel/i40evf/i40e_register.h
index 369839655818..c1f6a59bfea0 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_register.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_register.h
@@ -27,4648 +27,3343 @@
#ifndef _I40E_REGISTER_H_
#define _I40E_REGISTER_H_
-#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
-#define I40E_GL_GP_FUSE_MAX_INDEX 28
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
-#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
-#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
-#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
-#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
-#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
-#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
-#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
-#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
-#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
-
-#define I40E_PF_ARQBAH 0x00080180
+#define I40E_GL_ARQBAH 0x000801C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAH_ARQBAH_SHIFT 0
+#define I40E_GL_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAH_ARQBAH_SHIFT)
+#define I40E_GL_ARQBAL 0x000800C0 /* Reset: EMPR */
+#define I40E_GL_ARQBAL_ARQBAL_SHIFT 0
+#define I40E_GL_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAL_ARQBAL_SHIFT)
+#define I40E_GL_ARQH 0x000803C0 /* Reset: EMPR */
+#define I40E_GL_ARQH_ARQH_SHIFT 0
+#define I40E_GL_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_GL_ARQH_ARQH_SHIFT)
+#define I40E_GL_ARQT 0x000804C0 /* Reset: EMPR */
+#define I40E_GL_ARQT_ARQT_SHIFT 0
+#define I40E_GL_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_GL_ARQT_ARQT_SHIFT)
+#define I40E_GL_ATQBAH 0x00080140 /* Reset: EMPR */
+#define I40E_GL_ATQBAH_ATQBAH_SHIFT 0
+#define I40E_GL_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAH_ATQBAH_SHIFT)
+#define I40E_GL_ATQBAL 0x00080040 /* Reset: EMPR */
+#define I40E_GL_ATQBAL_ATQBAL_SHIFT 0
+#define I40E_GL_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAL_ATQBAL_SHIFT)
+#define I40E_GL_ATQH 0x00080340 /* Reset: EMPR */
+#define I40E_GL_ATQH_ATQH_SHIFT 0
+#define I40E_GL_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_GL_ATQH_ATQH_SHIFT)
+#define I40E_GL_ATQLEN 0x00080240 /* Reset: EMPR */
+#define I40E_GL_ATQLEN_ATQLEN_SHIFT 0
+#define I40E_GL_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_GL_ATQLEN_ATQLEN_SHIFT)
+#define I40E_GL_ATQLEN_ATQVFE_SHIFT 28
+#define I40E_GL_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQVFE_SHIFT)
+#define I40E_GL_ATQLEN_ATQOVFL_SHIFT 29
+#define I40E_GL_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_GL_ATQLEN_ATQCRIT_SHIFT 30
+#define I40E_GL_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_GL_ATQLEN_ATQENABLE_SHIFT 31
+#define I40E_GL_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_GL_ATQT 0x00080440 /* Reset: EMPR */
+#define I40E_GL_ATQT_ATQT_SHIFT 0
+#define I40E_GL_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_GL_ATQT_ATQT_SHIFT)
+#define I40E_PF_ARQBAH 0x00080180 /* Reset: EMPR */
#define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_PF_ARQBAL 0x00080080
+#define I40E_PF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_PF_ARQBAL 0x00080080 /* Reset: EMPR */
#define I40E_PF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_PF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_PF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_PF_ARQH 0x00080380
+#define I40E_PF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_PF_ARQH 0x00080380 /* Reset: EMPR */
#define I40E_PF_ARQH_ARQH_SHIFT 0
-#define I40E_PF_ARQH_ARQH_MASK (0x3FF << I40E_PF_ARQH_ARQH_SHIFT)
-#define I40E_PF_ARQLEN 0x00080280
+#define I40E_PF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_PF_ARQH_ARQH_SHIFT)
+#define I40E_PF_ARQLEN 0x00080280 /* Reset: EMPR */
#define I40E_PF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_PF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_PF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_PF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ARQLEN_ARQLEN_SHIFT)
#define I40E_PF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_PF_ARQLEN_ARQVFE_MASK (0x1 << I40E_PF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_PF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQVFE_SHIFT)
#define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_PF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_PF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_PF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQOVFL_SHIFT)
#define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_PF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_PF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT)
#define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_PF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_PF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_PF_ARQT 0x00080480
+#define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */
#define I40E_PF_ARQT_ARQT_SHIFT 0
-#define I40E_PF_ARQT_ARQT_MASK (0x3FF << I40E_PF_ARQT_ARQT_SHIFT)
-#define I40E_PF_ATQBAH 0x00080100
+#define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT)
+#define I40E_PF_ATQBAH 0x00080100 /* Reset: EMPR */
#define I40E_PF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_PF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_PF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_PF_ATQBAL 0x00080000
+#define I40E_PF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_PF_ATQBAL 0x00080000 /* Reset: EMPR */
#define I40E_PF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_PF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_PF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_PF_ATQH 0x00080300
+#define I40E_PF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_PF_ATQH 0x00080300 /* Reset: EMPR */
#define I40E_PF_ATQH_ATQH_SHIFT 0
-#define I40E_PF_ATQH_ATQH_MASK (0x3FF << I40E_PF_ATQH_ATQH_SHIFT)
-#define I40E_PF_ATQLEN 0x00080200
+#define I40E_PF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_PF_ATQH_ATQH_SHIFT)
+#define I40E_PF_ATQLEN 0x00080200 /* Reset: EMPR */
#define I40E_PF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_PF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_PF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_PF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ATQLEN_ATQLEN_SHIFT)
#define I40E_PF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_PF_ATQLEN_ATQVFE_MASK (0x1 << I40E_PF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_PF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQVFE_SHIFT)
#define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_PF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_PF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_PF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQOVFL_SHIFT)
#define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_PF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_PF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT)
#define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_PF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_PF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_PF_ATQT 0x00080400
+#define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */
#define I40E_PF_ATQT_ATQT_SHIFT 0
-#define I40E_PF_ATQT_ATQT_MASK (0x3FF << I40E_PF_ATQT_ATQT_SHIFT)
-#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT)
+#define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQBAH_MAX_INDEX 127
#define I40E_VF_ARQBAH_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQBAL_MAX_INDEX 127
#define I40E_VF_ARQBAL_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL_ARQBAL_SHIFT)
-#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL_ARQBAL_SHIFT)
+#define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQH_MAX_INDEX 127
#define I40E_VF_ARQH_ARQH_SHIFT 0
-#define I40E_VF_ARQH_ARQH_MASK (0x3FF << I40E_VF_ARQH_ARQH_SHIFT)
-#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH_ARQH_SHIFT)
+#define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQLEN_MAX_INDEX 127
#define I40E_VF_ARQLEN_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN_ARQLEN_SHIFT)
#define I40E_VF_ARQLEN_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQVFE_SHIFT)
#define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQOVFL_SHIFT)
#define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT)
#define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ARQT_MAX_INDEX 127
#define I40E_VF_ARQT_ARQT_SHIFT 0
-#define I40E_VF_ARQT_ARQT_MASK (0x3FF << I40E_VF_ARQT_ARQT_SHIFT)
-#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT_ARQT_SHIFT)
+#define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQBAH_MAX_INDEX 127
#define I40E_VF_ATQBAH_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQBAL_MAX_INDEX 127
#define I40E_VF_ATQBAL_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL_ATQBAL_SHIFT)
-#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL_ATQBAL_SHIFT)
+#define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQH_MAX_INDEX 127
#define I40E_VF_ATQH_ATQH_SHIFT 0
-#define I40E_VF_ATQH_ATQH_MASK (0x3FF << I40E_VF_ATQH_ATQH_SHIFT)
-#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH_ATQH_SHIFT)
+#define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQLEN_MAX_INDEX 127
#define I40E_VF_ATQLEN_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN_ATQLEN_SHIFT)
#define I40E_VF_ATQLEN_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQVFE_SHIFT)
#define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQOVFL_SHIFT)
#define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT)
#define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */
#define I40E_VF_ATQT_MAX_INDEX 127
#define I40E_VF_ATQT_ATQT_SHIFT 0
-#define I40E_VF_ATQT_ATQT_MASK (0x3FF << I40E_VF_ATQT_ATQT_SHIFT)
-#define I40E_PRT_L2TAGSEN 0x001C0B20
+#define I40E_VF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT_ATQT_SHIFT)
+#define I40E_PRT_L2TAGSEN 0x001C0B20 /* Reset: CORER */
#define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0
-#define I40E_PRT_L2TAGSEN_ENABLE_MASK (0xFF << I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
-#define I40E_PFCM_LAN_ERRDATA 0x0010C080
+#define I40E_PRT_L2TAGSEN_ENABLE_MASK I40E_MASK(0xFF, I40E_PRT_L2TAGSEN_ENABLE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA 0x0010C080 /* Reset: PFR */
#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT)
#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT)
#define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK (0xFFF << I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_LAN_ERRINFO 0x0010C000
+#define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO 0x0010C000 /* Reset: PFR */
#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT)
#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_PFCM_LANCTXCTL(_pf) (0x0010C300 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_PFCM_LANCTXCTL 0x0010C300 /* Reset: CORER */
#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0
-#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK (0xFFF << I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT)
#define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12
-#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK (0x7 << I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK I40E_MASK(0x7, I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT)
#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15
-#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK (0x3 << I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
+#define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT)
#define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17
-#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK (0x3 << I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
-#define I40E_PFCM_LANCTXDATA(_i, _pf) (0x0010C100 + ((_i) * 4) + ((_pf) * 16))/* _i=0...3 _pf=0..15 */
+#define I40E_PFCM_LANCTXCTL_OP_CODE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT)
+#define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PFCM_LANCTXDATA_MAX_INDEX 3
#define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0
-#define I40E_PFCM_LANCTXDATA_DATA_MASK (0xFFFFFFFF << I40E_PFCM_LANCTXDATA_DATA_SHIFT)
-#define I40E_PFCM_LANCTXSTAT(_pf) (0x0010C380 + ((_pf) * 4))/* _pf=0..15 */
+#define I40E_PFCM_LANCTXDATA_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFCM_LANCTXDATA_DATA_SHIFT)
+#define I40E_PFCM_LANCTXSTAT 0x0010C380 /* Reset: CORER */
#define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0
-#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
+#define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT)
#define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1
-#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK (0x1 << I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
-#define I40E_PFCM_PE_ERRDATA 0x00138D00
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_PFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_PFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_PFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_PFCM_PE_ERRDATA_Q_TYPE_SHIFT)
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_PFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_PFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_PFCM_PE_ERRINFO 0x00138C80
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_PFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_PFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_PFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_PFCM_PE_ERRINFO_ERROR_INST_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_PFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127
#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT)
#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT)
#define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127
#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
-#define I40E_GLDCB_GENC 0x00083044
+#define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT)
+#define I40E_GLDCB_GENC 0x00083044 /* Reset: CORER */
#define I40E_GLDCB_GENC_PCIRTT_SHIFT 0
-#define I40E_GLDCB_GENC_PCIRTT_MASK (0xFFFF << I40E_GLDCB_GENC_PCIRTT_SHIFT)
-#define I40E_GLDCB_RUPTI 0x00122618
+#define I40E_GLDCB_GENC_PCIRTT_MASK I40E_MASK(0xFFFF, I40E_GLDCB_GENC_PCIRTT_SHIFT)
+#define I40E_GLDCB_RUPTI 0x00122618 /* Reset: CORER */
#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0
-#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK (0xFFFFFFFF << I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
-#define I40E_PRTDCB_FCCFG 0x001E4640
+#define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT)
+#define I40E_PRTDCB_FCCFG 0x001E4640 /* Reset: GLOBR */
#define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3
-#define I40E_PRTDCB_FCCFG_TFCE_MASK (0x3 << I40E_PRTDCB_FCCFG_TFCE_SHIFT)
-#define I40E_PRTDCB_FCRTV 0x001E4600
+#define I40E_PRTDCB_FCCFG_TFCE_MASK I40E_MASK(0x3, I40E_PRTDCB_FCCFG_TFCE_SHIFT)
+#define I40E_PRTDCB_FCRTV 0x001E4600 /* Reset: GLOBR */
#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0
-#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK (0xFFFF << I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
-#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT)
+#define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: GLOBR */
#define I40E_PRTDCB_FCTTVN_MAX_INDEX 3
#define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0
-#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
+#define I40E_PRTDCB_FCTTVN_TTV_2N_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT)
#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16
-#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK (0xFFFF << I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
-#define I40E_PRTDCB_GENC 0x00083000
+#define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT)
+#define I40E_PRTDCB_GENC 0x00083000 /* Reset: CORER */
#define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0
-#define I40E_PRTDCB_GENC_RESERVED_1_MASK (0x3 << I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
+#define I40E_PRTDCB_GENC_RESERVED_1_MASK I40E_MASK(0x3, I40E_PRTDCB_GENC_RESERVED_1_SHIFT)
#define I40E_PRTDCB_GENC_NUMTC_SHIFT 2
-#define I40E_PRTDCB_GENC_NUMTC_MASK (0xF << I40E_PRTDCB_GENC_NUMTC_SHIFT)
+#define I40E_PRTDCB_GENC_NUMTC_MASK I40E_MASK(0xF, I40E_PRTDCB_GENC_NUMTC_SHIFT)
#define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6
-#define I40E_PRTDCB_GENC_FCOEUP_MASK (0x7 << I40E_PRTDCB_GENC_FCOEUP_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_MASK I40E_MASK(0x7, I40E_PRTDCB_GENC_FCOEUP_SHIFT)
#define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9
-#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK (0x1 << I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
+#define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK I40E_MASK(0x1, I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT)
#define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16
-#define I40E_PRTDCB_GENC_PFCLDA_MASK (0xFFFF << I40E_PRTDCB_GENC_PFCLDA_SHIFT)
-#define I40E_PRTDCB_GENS 0x00083020
+#define I40E_PRTDCB_GENC_PFCLDA_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_GENC_PFCLDA_SHIFT)
+#define I40E_PRTDCB_GENS 0x00083020 /* Reset: CORER */
#define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0
-#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK (0x7 << I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
-#define I40E_PRTDCB_MFLCN 0x001E2400
+#define I40E_PRTDCB_GENS_DCBX_STATUS_MASK I40E_MASK(0x7, I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT)
+#define I40E_PRTDCB_MFLCN 0x001E2400 /* Reset: GLOBR */
#define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0
-#define I40E_PRTDCB_MFLCN_PMCF_MASK (0x1 << I40E_PRTDCB_MFLCN_PMCF_SHIFT)
+#define I40E_PRTDCB_MFLCN_PMCF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_PMCF_SHIFT)
#define I40E_PRTDCB_MFLCN_DPF_SHIFT 1
-#define I40E_PRTDCB_MFLCN_DPF_MASK (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT)
+#define I40E_PRTDCB_MFLCN_DPF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_DPF_SHIFT)
#define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2
-#define I40E_PRTDCB_MFLCN_RPFCM_MASK (0x1 << I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
+#define I40E_PRTDCB_MFLCN_RPFCM_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RPFCM_SHIFT)
#define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3
-#define I40E_PRTDCB_MFLCN_RFCE_MASK (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT)
+#define I40E_PRTDCB_MFLCN_RFCE_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RFCE_SHIFT)
#define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4
-#define I40E_PRTDCB_MFLCN_RPFCE_MASK (0xFF << I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
-#define I40E_PRTDCB_RETSC 0x001223E0
+#define I40E_PRTDCB_MFLCN_RPFCE_MASK I40E_MASK(0xFF, I40E_PRTDCB_MFLCN_RPFCE_SHIFT)
+#define I40E_PRTDCB_RETSC 0x001223E0 /* Reset: CORER */
#define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0
-#define I40E_PRTDCB_RETSC_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_ETS_MODE_SHIFT)
#define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1
-#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK (0x1 << I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
+#define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT)
#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2
-#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK (0xF << I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
+#define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK I40E_MASK(0xF, I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT)
#define I40E_PRTDCB_RETSC_LLTC_SHIFT 8
-#define I40E_PRTDCB_RETSC_LLTC_MASK (0xFF << I40E_PRTDCB_RETSC_LLTC_SHIFT)
-#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_RETSC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_RETSC_LLTC_SHIFT)
+#define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTDCB_RETSTCC_MAX_INDEX 7
#define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0
-#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK (0x7F << I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_BWSHARE_MASK I40E_MASK(0x7F, I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT)
#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30
-#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK (0x1 << I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
+#define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT)
#define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31
-#define I40E_PRTDCB_RETSTCC_ETSTC_MASK (0x1 << I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
-#define I40E_PRTDCB_RPPMC 0x001223A0
+#define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT)
+#define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */
#define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0
-#define I40E_PRTDCB_RPPMC_LANRPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT)
#define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8
-#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK (0xFF << I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
+#define I40E_PRTDCB_RPPMC_RDMARPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT)
#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16
-#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK (0xFF << I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
-#define I40E_PRTDCB_RUP 0x001C0B00
+#define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT)
+#define I40E_PRTDCB_RUP 0x001C0B00 /* Reset: CORER */
#define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0
-#define I40E_PRTDCB_RUP_NOVLANUP_MASK (0x7 << I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
-#define I40E_PRTDCB_RUP2TC 0x001C09A0
+#define I40E_PRTDCB_RUP_NOVLANUP_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP_NOVLANUP_SHIFT)
+#define I40E_PRTDCB_RUP2TC 0x001C09A0 /* Reset: CORER */
#define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0
-#define I40E_PRTDCB_RUP2TC_UP0TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP0TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP0TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3
-#define I40E_PRTDCB_RUP2TC_UP1TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP1TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP1TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6
-#define I40E_PRTDCB_RUP2TC_UP2TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP2TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP2TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9
-#define I40E_PRTDCB_RUP2TC_UP3TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP3TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP3TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12
-#define I40E_PRTDCB_RUP2TC_UP4TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP4TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP4TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15
-#define I40E_PRTDCB_RUP2TC_UP5TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP5TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP5TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18
-#define I40E_PRTDCB_RUP2TC_UP6TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
+#define I40E_PRTDCB_RUP2TC_UP6TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP6TC_SHIFT)
#define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21
-#define I40E_PRTDCB_RUP2TC_UP7TC_MASK (0x7 << I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
-#define I40E_PRTDCB_TC2PFC 0x001C0980
+#define I40E_PRTDCB_RUP2TC_UP7TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP7TC_SHIFT)
+#define I40E_PRTDCB_TC2PFC 0x001C0980 /* Reset: CORER */
#define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0
-#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK (0xFF << I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
-#define I40E_PRTDCB_TCPMC 0x000A21A0
+#define I40E_PRTDCB_TC2PFC_TC2PFC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT)
+#define I40E_PRTDCB_TCMSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
+#define I40E_PRTDCB_TCMSTC_MAX_INDEX 7
+#define I40E_PRTDCB_TCMSTC_MSTC_SHIFT 0
+#define I40E_PRTDCB_TCMSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCMSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TCPMC 0x000A21A0 /* Reset: CORER */
#define I40E_PRTDCB_TCPMC_CPM_SHIFT 0
-#define I40E_PRTDCB_TCPMC_CPM_MASK (0x1FFF << I40E_PRTDCB_TCPMC_CPM_SHIFT)
+#define I40E_PRTDCB_TCPMC_CPM_MASK I40E_MASK(0x1FFF, I40E_PRTDCB_TCPMC_CPM_SHIFT)
#define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13
-#define I40E_PRTDCB_TCPMC_LLTC_MASK (0xFF << I40E_PRTDCB_TCPMC_LLTC_SHIFT)
+#define I40E_PRTDCB_TCPMC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TCPMC_LLTC_SHIFT)
#define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTDCB_TCWSTC_MAX_INDEX 7
#define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TCWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TDPMC 0x000A0180
+#define I40E_PRTDCB_TCWSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCWSTC_MSTC_SHIFT)
+#define I40E_PRTDCB_TDPMC 0x000A0180 /* Reset: CORER */
#define I40E_PRTDCB_TDPMC_DPM_SHIFT 0
-#define I40E_PRTDCB_TDPMC_DPM_MASK (0xFF << I40E_PRTDCB_TDPMC_DPM_SHIFT)
+#define I40E_PRTDCB_TDPMC_DPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_TDPMC_DPM_SHIFT)
#define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30
-#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK (0x1 << I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
-#define I40E_PRTDCB_TDPUC 0x00044100
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT 0
-#define I40E_PRTDCB_TDPUC_MAX_TXFRAME_MASK (0xFFFF << I40E_PRTDCB_TDPUC_MAX_TXFRAME_SHIFT)
-#define I40E_PRTDCB_TETSC_TCB 0x000AE060
+#define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB 0x000AE060 /* Reset: CORER */
#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT)
#define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
-#define I40E_PRTDCB_TETSC_TPB 0x00098060
+#define I40E_PRTDCB_TETSC_TCB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB 0x00098060 /* Reset: CORER */
#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0
-#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK (0x1 << I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
+#define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT)
#define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8
-#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK (0xFF << I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
-#define I40E_PRTDCB_TFCS 0x001E4560
+#define I40E_PRTDCB_TETSC_TPB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT)
+#define I40E_PRTDCB_TFCS 0x001E4560 /* Reset: GLOBR */
#define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0
-#define I40E_PRTDCB_TFCS_TXOFF_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8
-#define I40E_PRTDCB_TFCS_TXOFF0_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF0_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF0_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9
-#define I40E_PRTDCB_TFCS_TXOFF1_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF1_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF1_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10
-#define I40E_PRTDCB_TFCS_TXOFF2_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF2_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF2_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11
-#define I40E_PRTDCB_TFCS_TXOFF3_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF3_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF3_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12
-#define I40E_PRTDCB_TFCS_TXOFF4_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF4_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF4_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13
-#define I40E_PRTDCB_TFCS_TXOFF5_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF5_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF5_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14
-#define I40E_PRTDCB_TFCS_TXOFF6_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
+#define I40E_PRTDCB_TFCS_TXOFF6_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF6_SHIFT)
#define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15
-#define I40E_PRTDCB_TFCS_TXOFF7_MASK (0x1 << I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
-#define I40E_PRTDCB_TFWSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */
-#define I40E_PRTDCB_TFWSTC_MAX_INDEX 7
-#define I40E_PRTDCB_TFWSTC_MSTC_SHIFT 0
-#define I40E_PRTDCB_TFWSTC_MSTC_MASK (0xFFFFF << I40E_PRTDCB_TFWSTC_MSTC_SHIFT)
-#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTDCB_TFCS_TXOFF7_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF7_SHIFT)
+#define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */ /* Reset: GLOBR */
#define I40E_PRTDCB_TPFCTS_MAX_INDEX 7
#define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0
-#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK (0x3FFF << I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
-#define I40E_GLFCOE_RCTL 0x00269B94
+#define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT)
+#define I40E_GLFCOE_RCTL 0x00269B94 /* Reset: CORER */
#define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0
-#define I40E_GLFCOE_RCTL_FCOEVER_MASK (0xF << I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
+#define I40E_GLFCOE_RCTL_FCOEVER_MASK I40E_MASK(0xF, I40E_GLFCOE_RCTL_FCOEVER_SHIFT)
#define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4
-#define I40E_GLFCOE_RCTL_SAVBAD_MASK (0x1 << I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
+#define I40E_GLFCOE_RCTL_SAVBAD_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_SAVBAD_SHIFT)
#define I40E_GLFCOE_RCTL_ICRC_SHIFT 5
-#define I40E_GLFCOE_RCTL_ICRC_MASK (0x1 << I40E_GLFCOE_RCTL_ICRC_SHIFT)
+#define I40E_GLFCOE_RCTL_ICRC_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_ICRC_SHIFT)
#define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16
-#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK (0x3FFF << I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
-#define I40E_GL_FWSTS 0x00083048
+#define I40E_GLFCOE_RCTL_MAX_SIZE_MASK I40E_MASK(0x3FFF, I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT)
+#define I40E_GL_FWSTS 0x00083048 /* Reset: POR */
#define I40E_GL_FWSTS_FWS0B_SHIFT 0
-#define I40E_GL_FWSTS_FWS0B_MASK (0xFF << I40E_GL_FWSTS_FWS0B_SHIFT)
+#define I40E_GL_FWSTS_FWS0B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS0B_SHIFT)
#define I40E_GL_FWSTS_FWRI_SHIFT 9
-#define I40E_GL_FWSTS_FWRI_MASK (0x1 << I40E_GL_FWSTS_FWRI_SHIFT)
+#define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT)
#define I40E_GL_FWSTS_FWS1B_SHIFT 16
-#define I40E_GL_FWSTS_FWS1B_MASK (0xFF << I40E_GL_FWSTS_FWS1B_SHIFT)
-#define I40E_GLGEN_CLKSTAT 0x000B8184
+#define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT)
+#define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */
#define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0
-#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK (0x1 << I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
+#define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT)
#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4
-#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK (0x3 << I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK I40E_MASK(0x3, I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8
-#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12
-#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16
-#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT)
#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20
-#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK (0x7 << I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
-#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */
+#define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT)
+#define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */ /* Reset: POR */
#define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29
#define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK (0x3 << I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3
-#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4
-#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK (0x1 << I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT)
#define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5
-#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT)
#define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6
-#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7
-#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK (0x7 << I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK I40E_MASK(0x7, I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10
-#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11
-#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK (0x1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT)
#define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12
-#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK (0xF << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
#define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17
-#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK (0x3 << I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT)
#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19
-#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK (0x1 << I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
+#define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT)
#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20
-#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK (0x3F << I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
-#define I40E_GLGEN_GPIO_SET 0x00088184
+#define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK I40E_MASK(0x3F, I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT)
+#define I40E_GLGEN_GPIO_SET 0x00088184 /* Reset: POR */
#define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0
-#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK (0x1F << I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
+#define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT)
#define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5
-#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK (0x1 << I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
+#define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT)
#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6
-#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK (0x1 << I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
-#define I40E_GLGEN_GPIO_STAT 0x0008817C
+#define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT)
+#define I40E_GLGEN_GPIO_STAT 0x0008817C /* Reset: POR */
#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0
-#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
-#define I40E_GLGEN_GPIO_TRANSIT 0x00088180
+#define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT)
+#define I40E_GLGEN_GPIO_TRANSIT 0x00088180 /* Reset: POR */
#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0
-#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK (0x3FFFFFFF << I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
-#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT)
+#define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_I2CCMD_MAX_INDEX 3
#define I40E_GLGEN_I2CCMD_DATA_SHIFT 0
-#define I40E_GLGEN_I2CCMD_DATA_MASK (0xFFFF << I40E_GLGEN_I2CCMD_DATA_SHIFT)
+#define I40E_GLGEN_I2CCMD_DATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_I2CCMD_DATA_SHIFT)
#define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16
-#define I40E_GLGEN_I2CCMD_REGADD_MASK (0xFF << I40E_GLGEN_I2CCMD_REGADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_REGADD_MASK I40E_MASK(0xFF, I40E_GLGEN_I2CCMD_REGADD_SHIFT)
#define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24
-#define I40E_GLGEN_I2CCMD_PHYADD_MASK (0x7 << I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
+#define I40E_GLGEN_I2CCMD_PHYADD_MASK I40E_MASK(0x7, I40E_GLGEN_I2CCMD_PHYADD_SHIFT)
#define I40E_GLGEN_I2CCMD_OP_SHIFT 27
-#define I40E_GLGEN_I2CCMD_OP_MASK (0x1 << I40E_GLGEN_I2CCMD_OP_SHIFT)
+#define I40E_GLGEN_I2CCMD_OP_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_OP_SHIFT)
#define I40E_GLGEN_I2CCMD_RESET_SHIFT 28
-#define I40E_GLGEN_I2CCMD_RESET_MASK (0x1 << I40E_GLGEN_I2CCMD_RESET_SHIFT)
+#define I40E_GLGEN_I2CCMD_RESET_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_RESET_SHIFT)
#define I40E_GLGEN_I2CCMD_R_SHIFT 29
-#define I40E_GLGEN_I2CCMD_R_MASK (0x1 << I40E_GLGEN_I2CCMD_R_SHIFT)
+#define I40E_GLGEN_I2CCMD_R_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_R_SHIFT)
#define I40E_GLGEN_I2CCMD_E_SHIFT 31
-#define I40E_GLGEN_I2CCMD_E_MASK (0x1 << I40E_GLGEN_I2CCMD_E_SHIFT)
-#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_I2CCMD_E_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_E_SHIFT)
+#define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3
#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0
-#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK (0x1F << I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK I40E_MASK(0x1F, I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT)
#define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5
-#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK (0x7 << I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK I40E_MASK(0x7, I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT)
#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8
-#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9
-#define I40E_GLGEN_I2CPARAMS_CLK_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10
-#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11
-#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT)
#define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12
-#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13
-#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14
-#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT)
#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15
-#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK (0x1 << I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
+#define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT)
#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31
-#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK (0x1 << I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
-#define I40E_GLGEN_LED_CTL 0x00088178
+#define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT)
+#define I40E_GLGEN_LED_CTL 0x00088178 /* Reset: POR */
#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0
-#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK (0x1 << I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
-#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3
#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK (0x1FFFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK I40E_MASK(0x1FFFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT)
#define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17
-#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK (0x1 << I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
+#define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT)
#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18
-#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK (0x3FFF << I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
-#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK I40E_MASK(0x3FFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3
#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20
-#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK (0x1F << I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25
-#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK (0xF << I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
+#define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT)
#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31
-#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK (0x1 << I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
-#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT)
+#define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MSCA_MAX_INDEX 3
#define I40E_GLGEN_MSCA_MDIADD_SHIFT 0
-#define I40E_GLGEN_MSCA_MDIADD_MASK (0xFFFF << I40E_GLGEN_MSCA_MDIADD_SHIFT)
+#define I40E_GLGEN_MSCA_MDIADD_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSCA_MDIADD_SHIFT)
#define I40E_GLGEN_MSCA_DEVADD_SHIFT 16
-#define I40E_GLGEN_MSCA_DEVADD_MASK (0x1F << I40E_GLGEN_MSCA_DEVADD_SHIFT)
+#define I40E_GLGEN_MSCA_DEVADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_DEVADD_SHIFT)
#define I40E_GLGEN_MSCA_PHYADD_SHIFT 21
-#define I40E_GLGEN_MSCA_PHYADD_MASK (0x1F << I40E_GLGEN_MSCA_PHYADD_SHIFT)
+#define I40E_GLGEN_MSCA_PHYADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_PHYADD_SHIFT)
#define I40E_GLGEN_MSCA_OPCODE_SHIFT 26
-#define I40E_GLGEN_MSCA_OPCODE_MASK (0x3 << I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_GLGEN_MSCA_OPCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_OPCODE_SHIFT)
#define I40E_GLGEN_MSCA_STCODE_SHIFT 28
-#define I40E_GLGEN_MSCA_STCODE_MASK (0x3 << I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_GLGEN_MSCA_STCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_STCODE_SHIFT)
#define I40E_GLGEN_MSCA_MDICMD_SHIFT 30
-#define I40E_GLGEN_MSCA_MDICMD_MASK (0x1 << I40E_GLGEN_MSCA_MDICMD_SHIFT)
+#define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT)
#define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31
-#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK (0x1 << I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
-#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT)
+#define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */
#define I40E_GLGEN_MSRWD_MAX_INDEX 3
#define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0
-#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
+#define I40E_GLGEN_MSRWD_MDIWRDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT)
#define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16
-#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK (0xFFFF << I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
-#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4
+#define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT 0x001C0AB4 /* Reset: PCIR */
#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0
-#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK (0x1F << I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
+#define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT)
#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16
-#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK (0xFF << I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
-#define I40E_GLGEN_PE_ENA 0x000B81A0
-#define I40E_GLGEN_PE_ENA_PE_ENA_SHIFT 0
-#define I40E_GLGEN_PE_ENA_PE_ENA_MASK (0x1 << I40E_GLGEN_PE_ENA_PE_ENA_SHIFT)
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT 1
-#define I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_MASK (0x3 << I40E_GLGEN_PE_ENA_PE_CLK_SRC_SEL_SHIFT)
-#define I40E_GLGEN_RSTAT 0x000B8188
+#define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT)
+#define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */
#define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0
-#define I40E_GLGEN_RSTAT_DEVSTATE_MASK (0x3 << I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
+#define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT)
#define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2
-#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK (0x3 << I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
+#define I40E_GLGEN_RSTAT_RESET_TYPE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT)
#define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4
-#define I40E_GLGEN_RSTAT_CORERCNT_MASK (0x3 << I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_CORERCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_CORERCNT_SHIFT)
#define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6
-#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_GLOBRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT)
#define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8
-#define I40E_GLGEN_RSTAT_EMPRCNT_MASK (0x3 << I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
+#define I40E_GLGEN_RSTAT_EMPRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_EMPRCNT_SHIFT)
#define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10
-#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK (0x3F << I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
-#define I40E_GLGEN_RSTCTL 0x000B8180
+#define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT)
+#define I40E_GLGEN_RSTCTL 0x000B8180 /* Reset: POR */
#define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0
-#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK (0x3F << I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
+#define I40E_GLGEN_RSTCTL_GRSTDEL_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT)
#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8
-#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
-#define I40E_GLGEN_RSTENA_EMP 0x000B818C
+#define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT)
+#define I40E_GLGEN_RSTENA_EMP 0x000B818C /* Reset: POR */
#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT 0
-#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK (0x1 << I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
-#define I40E_GLGEN_RTRIG 0x000B8190
+#define I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_SHIFT)
+#define I40E_GLGEN_RTRIG 0x000B8190 /* Reset: CORER */
#define I40E_GLGEN_RTRIG_CORER_SHIFT 0
-#define I40E_GLGEN_RTRIG_CORER_MASK (0x1 << I40E_GLGEN_RTRIG_CORER_SHIFT)
+#define I40E_GLGEN_RTRIG_CORER_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_CORER_SHIFT)
#define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1
-#define I40E_GLGEN_RTRIG_GLOBR_MASK (0x1 << I40E_GLGEN_RTRIG_GLOBR_SHIFT)
+#define I40E_GLGEN_RTRIG_GLOBR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_GLOBR_SHIFT)
#define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2
-#define I40E_GLGEN_RTRIG_EMPFWR_MASK (0x1 << I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
-#define I40E_GLGEN_STAT 0x000B612C
+#define I40E_GLGEN_RTRIG_EMPFWR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_EMPFWR_SHIFT)
+#define I40E_GLGEN_STAT 0x000B612C /* Reset: POR */
#define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0
-#define I40E_GLGEN_STAT_HWRSVD0_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD0_SHIFT)
+#define I40E_GLGEN_STAT_HWRSVD0_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD0_SHIFT)
#define I40E_GLGEN_STAT_DCBEN_SHIFT 2
-#define I40E_GLGEN_STAT_DCBEN_MASK (0x1 << I40E_GLGEN_STAT_DCBEN_SHIFT)
+#define I40E_GLGEN_STAT_DCBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_DCBEN_SHIFT)
#define I40E_GLGEN_STAT_VTEN_SHIFT 3
-#define I40E_GLGEN_STAT_VTEN_MASK (0x1 << I40E_GLGEN_STAT_VTEN_SHIFT)
+#define I40E_GLGEN_STAT_VTEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_VTEN_SHIFT)
#define I40E_GLGEN_STAT_FCOEN_SHIFT 4
-#define I40E_GLGEN_STAT_FCOEN_MASK (0x1 << I40E_GLGEN_STAT_FCOEN_SHIFT)
+#define I40E_GLGEN_STAT_FCOEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_FCOEN_SHIFT)
#define I40E_GLGEN_STAT_EVBEN_SHIFT 5
-#define I40E_GLGEN_STAT_EVBEN_MASK (0x1 << I40E_GLGEN_STAT_EVBEN_SHIFT)
+#define I40E_GLGEN_STAT_EVBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_EVBEN_SHIFT)
#define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6
-#define I40E_GLGEN_STAT_HWRSVD1_MASK (0x3 << I40E_GLGEN_STAT_HWRSVD1_SHIFT)
-#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLGEN_STAT_HWRSVD1_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD1_SHIFT)
+#define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3
#define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0
-#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK (0xFFFFFFFF << I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
-#define I40E_GLVFGEN_TIMER 0x000881BC
+#define I40E_GLGEN_VFLRSTAT_VFLRE_MASK I40E_MASK(0xFFFFFFFF, I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT)
+#define I40E_GLVFGEN_TIMER 0x000881BC /* Reset: CORER */
#define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0
-#define I40E_GLVFGEN_TIMER_GTIME_MASK (0xFFFFFFFF << I40E_GLVFGEN_TIMER_GTIME_SHIFT)
-#define I40E_PFGEN_CTRL 0x00092400
+#define I40E_GLVFGEN_TIMER_GTIME_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVFGEN_TIMER_GTIME_SHIFT)
+#define I40E_PFGEN_CTRL 0x00092400 /* Reset: PFR */
#define I40E_PFGEN_CTRL_PFSWR_SHIFT 0
-#define I40E_PFGEN_CTRL_PFSWR_MASK (0x1 << I40E_PFGEN_CTRL_PFSWR_SHIFT)
-#define I40E_PFGEN_DRUN 0x00092500
+#define I40E_PFGEN_CTRL_PFSWR_MASK I40E_MASK(0x1, I40E_PFGEN_CTRL_PFSWR_SHIFT)
+#define I40E_PFGEN_DRUN 0x00092500 /* Reset: CORER */
#define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0
-#define I40E_PFGEN_DRUN_DRVUNLD_MASK (0x1 << I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
-#define I40E_PFGEN_PORTNUM 0x001C0480
+#define I40E_PFGEN_DRUN_DRVUNLD_MASK I40E_MASK(0x1, I40E_PFGEN_DRUN_DRVUNLD_SHIFT)
+#define I40E_PFGEN_PORTNUM 0x001C0480 /* Reset: CORER */
#define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
-#define I40E_PFGEN_STATE 0x00088000
-#define I40E_PFGEN_STATE_PFPEEN_SHIFT 0
-#define I40E_PFGEN_STATE_PFPEEN_MASK (0x1 << I40E_PFGEN_STATE_PFPEEN_SHIFT)
+#define I40E_PFGEN_PORTNUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_STATE 0x00088000 /* Reset: CORER */
+#define I40E_PFGEN_STATE_RESERVED_0_SHIFT 0
+#define I40E_PFGEN_STATE_RESERVED_0_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_RESERVED_0_SHIFT)
#define I40E_PFGEN_STATE_PFFCEN_SHIFT 1
-#define I40E_PFGEN_STATE_PFFCEN_MASK (0x1 << I40E_PFGEN_STATE_PFFCEN_SHIFT)
+#define I40E_PFGEN_STATE_PFFCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFFCEN_SHIFT)
#define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2
-#define I40E_PFGEN_STATE_PFLINKEN_MASK (0x1 << I40E_PFGEN_STATE_PFLINKEN_SHIFT)
+#define I40E_PFGEN_STATE_PFLINKEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFLINKEN_SHIFT)
#define I40E_PFGEN_STATE_PFSCEN_SHIFT 3
-#define I40E_PFGEN_STATE_PFSCEN_MASK (0x1 << I40E_PFGEN_STATE_PFSCEN_SHIFT)
-#define I40E_PRTGEN_CNF 0x000B8120
+#define I40E_PFGEN_STATE_PFSCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFSCEN_SHIFT)
+#define I40E_PRTGEN_CNF 0x000B8120 /* Reset: POR */
#define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0
-#define I40E_PRTGEN_CNF_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_PORT_DIS_SHIFT)
#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1
-#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT)
#define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2
-#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK (0x1 << I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
-#define I40E_PRTGEN_CNF2 0x000B8160
+#define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT)
+#define I40E_PRTGEN_CNF2 0x000B8160 /* Reset: POR */
#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0
-#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK (0x1 << I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
-#define I40E_PRTGEN_STATUS 0x000B8100
+#define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT)
+#define I40E_PRTGEN_STATUS 0x000B8100 /* Reset: POR */
#define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0
-#define I40E_PRTGEN_STATUS_PORT_VALID_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
+#define I40E_PRTGEN_STATUS_PORT_VALID_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_VALID_SHIFT)
#define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1
-#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK (0x1 << I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
-#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT)
+#define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFGEN_RSTAT1_MAX_INDEX 127
#define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
-#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFGEN_RSTAT1_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT)
+#define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPGEN_VFRSTAT_MAX_INDEX 127
#define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0
-#define I40E_VPGEN_VFRSTAT_VFRD_MASK (0x1 << I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
-#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPGEN_VFRSTAT_VFRD_MASK I40E_MASK(0x1, I40E_VPGEN_VFRSTAT_VFRD_SHIFT)
+#define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPGEN_VFRTRIG_MAX_INDEX 127
#define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0
-#define I40E_VPGEN_VFRTRIG_VFSWR_MASK (0x1 << I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
-#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPGEN_VFRTRIG_VFSWR_MASK I40E_MASK(0x1, I40E_VPGEN_VFRTRIG_VFSWR_SHIFT)
+#define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_VSIGEN_RSTAT_MAX_INDEX 383
#define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0
-#define I40E_VSIGEN_RSTAT_VMRD_MASK (0x1 << I40E_VSIGEN_RSTAT_VMRD_SHIFT)
-#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VSIGEN_RSTAT_VMRD_MASK I40E_MASK(0x1, I40E_VSIGEN_RSTAT_VMRD_SHIFT)
+#define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_VSIGEN_RTRIG_MAX_INDEX 383
#define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0
-#define I40E_VSIGEN_RTRIG_VMSWR_MASK (0x1 << I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
-#define I40E_GLHMC_APBVTINUSEBASE(_i) (0x000C4a00 + ((_i) * 4))
-#define I40E_GLHMC_APBVTINUSEBASE_MAX_INDEX 15
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_APBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_CEQPART(_i) (0x001312C0 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_CEQPART_MAX_INDEX 15
-#define I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_CEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_CEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_CEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_CEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_DBCQPART(_i) (0x00131240 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBCQPART_MAX_INDEX 15
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_DBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_DBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_DBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_DBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_DBQPPART(_i) (0x00138D80 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_DBQPPART_MAX_INDEX 15
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_DBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_DBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_DBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_DBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VSIGEN_RTRIG_VMSWR_MASK I40E_MASK(0x1, I40E_VSIGEN_RTRIG_VMSWR_SHIFT)
+#define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15
#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0
-#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
-#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT)
+#define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15
#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0
-#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK (0xFFFFF << I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
-#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010
+#define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK I40E_MASK(0xFFFFF, I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT)
+#define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010 /* Reset: CORER */
#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK (0xF << I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15
#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0
-#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK (0xFFFFFF << I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
-#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT)
+#define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15
#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0
-#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK (0x7FFFFF << I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
-#define I40E_GLHMC_FCOEFMAX 0x000C20D0
+#define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK I40E_MASK(0x7FFFFF, I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT)
+#define I40E_GLHMC_FCOEFMAX 0x000C20D0 /* Reset: CORER */
#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0
-#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK (0xFFFF << I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
-#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018
+#define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK I40E_MASK(0xFFFF, I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT)
+#define I40E_GLHMC_FCOEFOBJSZ 0x000C2018 /* Reset: CORER */
#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0
-#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK (0xF << I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
-#define I40E_GLHMC_FCOEMAX 0x000C2014
+#define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT)
+#define I40E_GLHMC_FCOEMAX 0x000C2014 /* Reset: CORER */
#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0
-#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK (0x1FFF << I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
-#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK I40E_MASK(0x1FFF, I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT)
+#define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15
#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT)
+#define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15
#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
+#define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT)
#define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_FSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_FSIAVMAX 0x000C2068
+#define I40E_GLHMC_FSIAVCNT_RSVD_MASK I40E_MASK(0x7, I40E_GLHMC_FSIAVCNT_RSVD_SHIFT)
+#define I40E_GLHMC_FSIAVMAX 0x000C2068 /* Reset: CORER */
#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0
-#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK (0x1FFFF << I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
-#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064
+#define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK I40E_MASK(0x1FFFF, I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT)
+#define I40E_GLHMC_FSIAVOBJSZ 0x000C2064 /* Reset: CORER */
#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK (0xF << I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
-#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT)
+#define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15
#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0
-#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK (0xFFFFFF << I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
-#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT)
+#define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15
#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK (0x1FFFFFFF << I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
-#define I40E_GLHMC_FSIMCMAX 0x000C2060
+#define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT)
+#define I40E_GLHMC_FSIMCMAX 0x000C2060 /* Reset: CORER */
#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0
-#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK (0x3FFF << I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
-#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c
+#define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK I40E_MASK(0x3FFF, I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT)
+#define I40E_GLHMC_FSIMCOBJSZ 0x000C205c /* Reset: CORER */
#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0
-#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK (0xF << I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
-#define I40E_GLHMC_LANQMAX 0x000C2008
+#define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT)
+#define I40E_GLHMC_LANQMAX 0x000C2008 /* Reset: CORER */
#define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0
-#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK (0x7FF << I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
-#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT)
+#define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANRXBASE_MAX_INDEX 15
#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0
-#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
-#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT)
+#define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANRXCNT_MAX_INDEX 15
#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0
-#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK (0x7FF << I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
-#define I40E_GLHMC_LANRXOBJSZ 0x000C200c
+#define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT)
+#define I40E_GLHMC_LANRXOBJSZ 0x000C200c /* Reset: CORER */
#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK (0xF << I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
-#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT)
+#define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANTXBASE_MAX_INDEX 15
#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0
-#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK (0xFFFFFF << I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
+#define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT)
#define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24
-#define I40E_GLHMC_LANTXBASE_RSVD_MASK (0xFF << I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
-#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXBASE_RSVD_MASK I40E_MASK(0xFF, I40E_GLHMC_LANTXBASE_RSVD_SHIFT)
+#define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_LANTXCNT_MAX_INDEX 15
#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0
-#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK (0x7FF << I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
-#define I40E_GLHMC_LANTXOBJSZ 0x000C2004
+#define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT)
+#define I40E_GLHMC_LANTXOBJSZ 0x000C2004 /* Reset: CORER */
#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0
-#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK (0xF << I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
-#define I40E_GLHMC_PEARPBASE(_i) (0x000C4800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_PEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_PEARPCNT(_i) (0x000C4900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEARPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_PEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_PEARPMAX 0x000C2038
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT 0
-#define I40E_GLHMC_PEARPMAX_PMPEARPMAX_MASK (0x1FFFF << I40E_GLHMC_PEARPMAX_PMPEARPMAX_SHIFT)
-#define I40E_GLHMC_PEARPOBJSZ 0x000C2034
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_MASK (0x7 << I40E_GLHMC_PEARPOBJSZ_PMPEARPOBJSZ_SHIFT)
-#define I40E_GLHMC_PECQBASE(_i) (0x000C4200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_PECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_PECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_PECQCNT(_i) (0x000C4300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PECQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_PECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_PECQOBJSZ 0x000C2020
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_MASK (0xF << I40E_GLHMC_PECQOBJSZ_PMPECQOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTCNT(_i) (0x000C4700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_PEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_PEHTEBASE(_i) (0x000C4600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEHTEBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_PEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_PEHTEOBJSZ 0x000C202c
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_MASK (0xF << I40E_GLHMC_PEHTEOBJSZ_PMPEHTEOBJSZ_SHIFT)
-#define I40E_GLHMC_PEHTMAX 0x000C2030
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT 0
-#define I40E_GLHMC_PEHTMAX_PMPEHTMAX_MASK (0x1FFFFF << I40E_GLHMC_PEHTMAX_PMPEHTMAX_SHIFT)
-#define I40E_GLHMC_PEMRBASE(_i) (0x000C4c00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_PEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_PEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_PEMRCNT(_i) (0x000C4d00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEMRCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_PEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_PEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_PEMRMAX 0x000C2040
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT 0
-#define I40E_GLHMC_PEMRMAX_PMPEMRMAX_MASK (0x7FFFFF << I40E_GLHMC_PEMRMAX_PMPEMRMAX_SHIFT)
-#define I40E_GLHMC_PEMROBJSZ 0x000C203c
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT 0
-#define I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_MASK (0xF << I40E_GLHMC_PEMROBJSZ_PMPEMROBJSZ_SHIFT)
-#define I40E_GLHMC_PEPBLBASE(_i) (0x000C5800 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_PEPBLCNT(_i) (0x000C5900 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEPBLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_PEPBLMAX 0x000C206c
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT 0
-#define I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PEPBLMAX_PMPEPBLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1BASE(_i) (0x000C5200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1BASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_PEQ1CNT(_i) (0x000C5300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1CNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLBASE(_i) (0x000C5400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_PEQ1FLCNT(_i) (0x000C5500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQ1FLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_PEQ1FLMAX 0x000C2058
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
-#define I40E_GLHMC_PEQ1MAX 0x000C2054
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
-#define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
-#define I40E_GLHMC_PEQ1OBJSZ 0x000C2050
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_MASK (0xF << I40E_GLHMC_PEQ1OBJSZ_PMPEQ1OBJSZ_SHIFT)
-#define I40E_GLHMC_PEQPBASE(_i) (0x000C4000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_PEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_PEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_PEQPCNT(_i) (0x000C4100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEQPCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_PEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_PEQPOBJSZ 0x000C201c
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_MASK (0xF << I40E_GLHMC_PEQPOBJSZ_PMPEQPOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQBASE(_i) (0x000C4400 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQBASE_MAX_INDEX 15
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_PESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_PESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_PESRQCNT(_i) (0x000C4500 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PESRQCNT_MAX_INDEX 15
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_PESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_PESRQMAX 0x000C2028
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT 0
-#define I40E_GLHMC_PESRQMAX_PMPESRQMAX_MASK (0xFFFF << I40E_GLHMC_PESRQMAX_PMPESRQMAX_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ 0x000C2024
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT 0
-#define I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_MASK (0xF << I40E_GLHMC_PESRQOBJSZ_PMPESRQOBJSZ_SHIFT)
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PESRQOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PESRQOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PETIMERBASE(_i) (0x000C5A00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERBASE_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_PETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_PETIMERCNT(_i) (0x000C5B00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PETIMERCNT_MAX_INDEX 15
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_PETIMERMAX 0x000C2084
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT 0
-#define I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_MASK (0x1FFFFFFF << I40E_GLHMC_PETIMERMAX_PMPETIMERMAX_SHIFT)
-#define I40E_GLHMC_PETIMEROBJSZ 0x000C2080
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT 0
-#define I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_MASK (0xF << I40E_GLHMC_PETIMEROBJSZ_PMPETIMEROBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFBASE(_i) (0x000C4e00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_PEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_PEXFCNT(_i) (0x000C4f00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_PEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLBASE(_i) (0x000C5000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLBASE_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_PEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_PEXFFLCNT(_i) (0x000C5100 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLHMC_PEXFFLCNT_MAX_INDEX 15
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_PEXFFLMAX 0x000C204c
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
-#define I40E_GLHMC_PEXFMAX 0x000C2048
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
-#define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ 0x000C2044
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT 0
-#define I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_MASK (0xF << I40E_GLHMC_PEXFOBJSZ_PMPEXFOBJSZ_SHIFT)
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT 4
-#define I40E_GLHMC_PEXFOBJSZ_RSVD_MASK (0xFFFFFFF << I40E_GLHMC_PEXFOBJSZ_RSVD_SHIFT)
-#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT)
+#define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_PFASSIGN_MAX_INDEX 15
#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0
-#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK (0xF << I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
-#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK I40E_MASK(0xF, I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT)
+#define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLHMC_SDPART_MAX_INDEX 15
#define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_SDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
+#define I40E_GLHMC_SDPART_PMSDBASE_MASK I40E_MASK(0xFFF, I40E_GLHMC_SDPART_PMSDBASE_SHIFT)
#define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_SDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
-#define I40E_GLHMC_VFAPBVTINUSEBASE(_i) (0x000Cca00 + ((_i) * 4))
-#define I40E_GLHMC_VFAPBVTINUSEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT 0
-#define I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFAPBVTINUSEBASE_FPMAPBINUSEBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART(_i) (0x00132240 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFCEQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT 0
-#define I40E_GLHMC_VFCEQPART_PMCEQBASE_MASK (0xFF << I40E_GLHMC_VFCEQPART_PMCEQBASE_SHIFT)
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT 16
-#define I40E_GLHMC_VFCEQPART_PMCEQSIZE_MASK (0x1FF << I40E_GLHMC_VFCEQPART_PMCEQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART(_i) (0x00132140 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBCQPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT 0
-#define I40E_GLHMC_VFDBCQPART_PMDBCQBASE_MASK (0x3FFF << I40E_GLHMC_VFDBCQPART_PMDBCQBASE_SHIFT)
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBCQPART_PMDBCQSIZE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART(_i) (0x00138E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFDBQPPART_MAX_INDEX 31
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT 0
-#define I40E_GLHMC_VFDBQPPART_PMDBQPBASE_MASK (0x3FFF << I40E_GLHMC_VFDBQPPART_PMDBQPBASE_SHIFT)
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT 16
-#define I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_MASK (0x7FFF << I40E_GLHMC_VFDBQPPART_PMDBQPSIZE_SHIFT)
-#define I40E_GLHMC_VFFSIAVBASE(_i) (0x000Cd600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT 0
-#define I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_MASK (0xFFFFFF << I40E_GLHMC_VFFSIAVBASE_FPMFSIAVBASE_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT(_i) (0x000Cd700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFFSIAVCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT 0
-#define I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFFSIAVCNT_FPMFSIAVCNT_SHIFT)
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT 29
-#define I40E_GLHMC_VFFSIAVCNT_RSVD_MASK (0x7 << I40E_GLHMC_VFFSIAVCNT_RSVD_SHIFT)
-#define I40E_GLHMC_VFPDINV(_i) (0x000C8300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPDINV_MAX_INDEX 31
-#define I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT 0
-#define I40E_GLHMC_VFPDINV_PMSDIDX_MASK (0xFFF << I40E_GLHMC_VFPDINV_PMSDIDX_SHIFT)
-#define I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT 16
-#define I40E_GLHMC_VFPDINV_PMPDIDX_MASK (0x1FF << I40E_GLHMC_VFPDINV_PMPDIDX_SHIFT)
-#define I40E_GLHMC_VFPEARPBASE(_i) (0x000Cc800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEARPBASE_FPMPEARPBASE_SHIFT)
-#define I40E_GLHMC_VFPEARPCNT(_i) (0x000Cc900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEARPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEARPCNT_FPMPEARPCNT_SHIFT)
-#define I40E_GLHMC_VFPECQBASE(_i) (0x000Cc200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT 0
-#define I40E_GLHMC_VFPECQBASE_FPMPECQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPECQBASE_FPMPECQBASE_SHIFT)
-#define I40E_GLHMC_VFPECQCNT(_i) (0x000Cc300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPECQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT 0
-#define I40E_GLHMC_VFPECQCNT_FPMPECQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPECQCNT_FPMPECQCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTCNT(_i) (0x000Cc700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT 0
-#define I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEHTCNT_FPMPEHTCNT_SHIFT)
-#define I40E_GLHMC_VFPEHTEBASE(_i) (0x000Cc600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEHTEBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT 0
-#define I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEHTEBASE_FPMPEHTEBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRBASE(_i) (0x000Ccc00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT 0
-#define I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEMRBASE_FPMPEMRBASE_SHIFT)
-#define I40E_GLHMC_VFPEMRCNT(_i) (0x000Ccd00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEMRCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT 0
-#define I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEMRCNT_FPMPEMRSZ_SHIFT)
-#define I40E_GLHMC_VFPEPBLBASE(_i) (0x000Cd800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEPBLBASE_FPMPEPBLBASE_SHIFT)
-#define I40E_GLHMC_VFPEPBLCNT(_i) (0x000Cd900 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEPBLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEPBLCNT_FPMPEPBLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1BASE(_i) (0x000Cd200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1BASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1BASE_FPMPEQ1BASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1CNT(_i) (0x000Cd300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1CNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1CNT_FPMPEQ1CNT_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLBASE(_i) (0x000Cd400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQ1FLBASE_FPMPEQ1FLBASE_SHIFT)
-#define I40E_GLHMC_VFPEQ1FLCNT(_i) (0x000Cd500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQ1FLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
-#define I40E_GLHMC_VFPEQPBASE(_i) (0x000Cc000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT 0
-#define I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEQPBASE_FPMPEQPBASE_SHIFT)
-#define I40E_GLHMC_VFPEQPCNT(_i) (0x000Cc100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEQPCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT 0
-#define I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEQPCNT_FPMPEQPCNT_SHIFT)
-#define I40E_GLHMC_VFPESRQBASE(_i) (0x000Cc400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT 0
-#define I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPESRQBASE_FPMPESRQBASE_SHIFT)
-#define I40E_GLHMC_VFPESRQCNT(_i) (0x000Cc500 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPESRQCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT 0
-#define I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPESRQCNT_FPMPESRQCNT_SHIFT)
-#define I40E_GLHMC_VFPETIMERBASE(_i) (0x000CDA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT 0
-#define I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPETIMERBASE_FPMPETIMERBASE_SHIFT)
-#define I40E_GLHMC_VFPETIMERCNT(_i) (0x000CDB00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPETIMERCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT 0
-#define I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPETIMERCNT_FPMPETIMERCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFBASE(_i) (0x000Cce00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFBASE_FPMPEXFBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFCNT(_i) (0x000Ccf00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFCNT_FPMPEXFCNT_SHIFT)
-#define I40E_GLHMC_VFPEXFFLBASE(_i) (0x000Cd000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLBASE_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_MASK (0xFFFFFF << I40E_GLHMC_VFPEXFFLBASE_FPMPEXFFLBASE_SHIFT)
-#define I40E_GLHMC_VFPEXFFLCNT(_i) (0x000Cd100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFPEXFFLCNT_MAX_INDEX 31
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT 0
-#define I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_VFPEXFFLCNT_FPMPEXFFLCNT_SHIFT)
-#define I40E_GLHMC_VFSDPART(_i) (0x000C8800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLHMC_VFSDPART_MAX_INDEX 31
-#define I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT 0
-#define I40E_GLHMC_VFSDPART_PMSDBASE_MASK (0xFFF << I40E_GLHMC_VFSDPART_PMSDBASE_SHIFT)
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT 16
-#define I40E_GLHMC_VFSDPART_PMSDSIZE_MASK (0x1FFF << I40E_GLHMC_VFSDPART_PMSDSIZE_SHIFT)
-#define I40E_PFHMC_ERRORDATA 0x000C0500
+#define I40E_GLHMC_SDPART_PMSDSIZE_MASK I40E_MASK(0x1FFF, I40E_GLHMC_SDPART_PMSDSIZE_SHIFT)
+#define I40E_PFHMC_ERRORDATA 0x000C0500 /* Reset: PFR */
#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0
-#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK (0x3FFFFFFF << I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
-#define I40E_PFHMC_ERRORINFO 0x000C0400
+#define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK I40E_MASK(0x3FFFFFFF, I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT)
+#define I40E_PFHMC_ERRORINFO 0x000C0400 /* Reset: PFR */
#define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0
-#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK (0x1F << I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT)
#define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7
-#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK (0x1 << I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
+#define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT)
#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8
-#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK (0xF << I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK I40E_MASK(0xF, I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT)
#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16
-#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK (0x1F << I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
+#define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT)
#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31
-#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK (0x1 << I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
-#define I40E_PFHMC_PDINV 0x000C0300
+#define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT)
+#define I40E_PFHMC_PDINV 0x000C0300 /* Reset: PFR */
#define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_PDINV_PMSDIDX_MASK (0xFFF << I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
+#define I40E_PFHMC_PDINV_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_PDINV_PMSDIDX_SHIFT)
#define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16
-#define I40E_PFHMC_PDINV_PMPDIDX_MASK (0x1FF << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
-#define I40E_PFHMC_SDCMD 0x000C0000
+#define I40E_PFHMC_PDINV_PMPDIDX_MASK I40E_MASK(0x1FF, I40E_PFHMC_PDINV_PMPDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD 0x000C0000 /* Reset: PFR */
#define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0
-#define I40E_PFHMC_SDCMD_PMSDIDX_MASK (0xFFF << I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
+#define I40E_PFHMC_SDCMD_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_SDCMD_PMSDIDX_SHIFT)
#define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31
-#define I40E_PFHMC_SDCMD_PMSDWR_MASK (0x1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
-#define I40E_PFHMC_SDDATAHIGH 0x000C0200
+#define I40E_PFHMC_SDCMD_PMSDWR_MASK I40E_MASK(0x1, I40E_PFHMC_SDCMD_PMSDWR_SHIFT)
+#define I40E_PFHMC_SDDATAHIGH 0x000C0200 /* Reset: PFR */
#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0
-#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK (0xFFFFFFFF << I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
-#define I40E_PFHMC_SDDATALOW 0x000C0100
+#define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT)
+#define I40E_PFHMC_SDDATALOW 0x000C0100 /* Reset: PFR */
#define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0
-#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1
-#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK (0x1 << I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2
-#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK (0x3FF << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
+#define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK I40E_MASK(0x3FF, I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT)
#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12
-#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK (0xFFFFF << I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
-#define I40E_GL_UFUSE 0x00094008
+#define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK I40E_MASK(0xFFFFF, I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT)
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ /* Reset: POR */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
+#define I40E_GL_UFUSE 0x00094008 /* Reset: POR */
#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1
-#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK (0x1 << I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
+#define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK I40E_MASK(0x1, I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT)
#define I40E_GL_UFUSE_NIC_ID_SHIFT 2
-#define I40E_GL_UFUSE_NIC_ID_MASK (0x1 << I40E_GL_UFUSE_NIC_ID_SHIFT)
+#define I40E_GL_UFUSE_NIC_ID_MASK I40E_MASK(0x1, I40E_GL_UFUSE_NIC_ID_SHIFT)
#define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10
-#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
+#define I40E_GL_UFUSE_ULT_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT)
#define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11
-#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK (0x1 << I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
-#define I40E_EMPINT_GPIO_ENA 0x00088188
+#define I40E_GL_UFUSE_CLS_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT)
+#define I40E_EMPINT_GPIO_ENA 0x00088188 /* Reset: POR */
#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT)
#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100
+#define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM 0x0003F100 /* Reset: CORER */
#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0
-#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK (0x3 << I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
+#define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT)
#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4
-#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK (0x1 << I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
-#define I40E_PFINT_AEQCTL 0x00038700
+#define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK I40E_MASK(0x1, I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL 0x00038700 /* Reset: CORER */
#define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT)
#define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT)
#define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_PFINT_CEQCTL_MAX_INDEX 511
#define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_PFINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_ITR_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)
#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT)
#define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_PFINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_PFINT_DYN_CTL0 0x00038480
+#define I40E_PFINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_PFINT_DYN_CTL0 0x00038480 /* Reset: PFR */
#define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_SHIFT)
#define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT)
#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
#define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT)
#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_DYN_CTLN_MAX_INDEX 511
#define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_PFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_SHIFT)
#define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT)
#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
#define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
#define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_PFINT_GPIO_ENA 0x00088080
+#define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_PFINT_GPIO_ENA 0x00088080 /* Reset: CORER */
#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0
-#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1
-#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2
-#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3
-#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4
-#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5
-#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6
-#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7
-#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8
-#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9
-#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10
-#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11
-#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12
-#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13
-#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14
-#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15
-#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16
-#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17
-#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18
-#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19
-#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20
-#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21
-#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22
-#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23
-#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24
-#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25
-#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26
-#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27
-#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28
-#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
+#define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT)
#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29
-#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK (0x1 << I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
-#define I40E_PFINT_ICR0 0x00038780
+#define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT)
+#define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
#define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_PFINT_ICR0_INTEVENT_MASK (0x1 << I40E_PFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_PFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_0_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_PFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_1_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_PFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_2_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_PFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_3_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5
-#define I40E_PFINT_ICR0_QUEUE_4_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_4_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_4_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_4_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6
-#define I40E_PFINT_ICR0_QUEUE_5_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_5_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_5_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_5_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7
-#define I40E_PFINT_ICR0_QUEUE_6_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_6_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_6_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_6_SHIFT)
#define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8
-#define I40E_PFINT_ICR0_QUEUE_7_MASK (0x1 << I40E_PFINT_ICR0_QUEUE_7_SHIFT)
+#define I40E_PFINT_ICR0_QUEUE_7_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_7_SHIFT)
#define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ECC_ERR_SHIFT)
#define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_MAL_DETECT_SHIFT)
#define I40E_PFINT_ICR0_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_GRST_MASK (0x1 << I40E_PFINT_ICR0_GRST_SHIFT)
+#define I40E_PFINT_ICR0_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GRST_SHIFT)
#define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT)
#define I40E_PFINT_ICR0_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_GPIO_MASK (0x1 << I40E_PFINT_ICR0_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GPIO_SHIFT)
#define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_STORM_DETECT_SHIFT)
#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
#define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_HMC_ERR_SHIFT)
#define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PE_CRITERR_SHIFT)
#define I40E_PFINT_ICR0_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_VFLR_MASK (0x1 << I40E_PFINT_ICR0_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_VFLR_SHIFT)
#define I40E_PFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ADMINQ_SHIFT)
#define I40E_PFINT_ICR0_SWINT_SHIFT 31
-#define I40E_PFINT_ICR0_SWINT_MASK (0x1 << I40E_PFINT_ICR0_SWINT_SHIFT)
-#define I40E_PFINT_ICR0_ENA 0x00038800
+#define I40E_PFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_SWINT_SHIFT)
+#define I40E_PFINT_ICR0_ENA 0x00038800 /* Reset: CORER */
#define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16
-#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19
-#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK (0x1 << I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
+#define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT)
#define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20
-#define I40E_PFINT_ICR0_ENA_GRST_MASK (0x1 << I40E_PFINT_ICR0_ENA_GRST_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GRST_SHIFT)
#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21
-#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK (0x1 << I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT)
#define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22
-#define I40E_PFINT_ICR0_ENA_GPIO_MASK (0x1 << I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
+#define I40E_PFINT_ICR0_ENA_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GPIO_SHIFT)
#define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23
-#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK (0x1 << I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT)
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24
+#define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT)
#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
#define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26
-#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28
-#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK (0x1 << I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT)
#define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29
-#define I40E_PFINT_ICR0_ENA_VFLR_MASK (0x1 << I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
+#define I40E_PFINT_ICR0_ENA_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_VFLR_SHIFT)
#define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_PFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT)
#define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_PFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */
+#define I40E_PFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */ /* Reset: PFR */
#define I40E_PFINT_ITR0_MAX_INDEX 2
#define I40E_PFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_PFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4))
+#define I40E_PFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4)) /* _i=0...2, _INTPF=0...511 */ /* Reset: PFR */
#define I40E_PFINT_ITRN_MAX_INDEX 2
#define I40E_PFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_PFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_PFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_PFINT_LNKLST0 0x00038500
+#define I40E_PFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_PFINT_LNKLST0 0x00038500 /* Reset: PFR */
#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT)
#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_LNKLSTN_MAX_INDEX 511
#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_PFINT_RATE0 0x00038580
+#define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_PFINT_RATE0 0x00038580 /* Reset: PFR */
#define I40E_PFINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATE0_INTERVAL_MASK (0x3F << I40E_PFINT_RATE0_INTERVAL_SHIFT)
+#define I40E_PFINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATE0_INTERVAL_SHIFT)
#define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */
+#define I40E_PFINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */
#define I40E_PFINT_RATEN_MAX_INDEX 511
#define I40E_PFINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_PFINT_RATEN_INTERVAL_MASK (0x3F << I40E_PFINT_RATEN_INTERVAL_SHIFT)
+#define I40E_PFINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATEN_INTERVAL_SHIFT)
#define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_PFINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_PFINT_STAT_CTL0 0x00038400
+#define I40E_PFINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_PFINT_STAT_CTL0 0x00038400 /* Reset: PFR */
#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QINT_RQCTL_MAX_INDEX 1535
#define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_RQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_RQCTL_MSIX_INDX_SHIFT)
#define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_RQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_RQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_RQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_ITR_INDX_SHIFT)
#define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_RQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_RQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_RQCTL_MSIX0_INDX_SHIFT)
#define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT)
#define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_RQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_RQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_CAUSE_ENA_SHIFT)
#define I40E_QINT_RQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_RQCTL_INTEVENT_MASK (0x1 << I40E_QINT_RQCTL_INTEVENT_SHIFT)
-#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QINT_RQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_INTEVENT_SHIFT)
+#define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QINT_TQCTL_MAX_INDEX 1535
#define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0
-#define I40E_QINT_TQCTL_MSIX_INDX_MASK (0xFF << I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_TQCTL_MSIX_INDX_SHIFT)
#define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11
-#define I40E_QINT_TQCTL_ITR_INDX_MASK (0x3 << I40E_QINT_TQCTL_ITR_INDX_SHIFT)
+#define I40E_QINT_TQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_ITR_INDX_SHIFT)
#define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_QINT_TQCTL_MSIX0_INDX_MASK (0x7 << I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
+#define I40E_QINT_TQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_TQCTL_MSIX0_INDX_SHIFT)
#define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT)
#define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_QINT_TQCTL_CAUSE_ENA_MASK (0x1 << I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
+#define I40E_QINT_TQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_CAUSE_ENA_SHIFT)
#define I40E_QINT_TQCTL_INTEVENT_SHIFT 31
-#define I40E_QINT_TQCTL_INTEVENT_MASK (0x1 << I40E_QINT_TQCTL_INTEVENT_SHIFT)
-#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QINT_TQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_INTEVENT_SHIFT)
+#define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTL0_MAX_INDEX 127
#define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL0_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTLN_MAX_INDEX 511
#define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VFINT_ICR0_MAX_INDEX 127
#define I40E_VFINT_ICR0_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR0_INTEVENT_MASK (0x1 << I40E_VFINT_ICR0_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_INTEVENT_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR0_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_0_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR0_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_1_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR0_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_2_SHIFT)
#define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR0_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR0_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_3_SHIFT)
#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_SWINT_SHIFT 31
-#define I40E_VFINT_ICR0_SWINT_MASK (0x1 << I40E_VFINT_ICR0_SWINT_SHIFT)
-#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_SWINT_SHIFT)
+#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VFINT_ICR0_ENA_MAX_INDEX 127
#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
-#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */
+#define I40E_VFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_RSVD_SHIFT)
+#define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */ /* Reset: VFR */
#define I40E_VFINT_ITR0_MAX_INDEX 2
#define I40E_VFINT_ITR0_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR0_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR0_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4))
+#define I40E_VFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR0_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...511 */ /* Reset: VFR */
#define I40E_VFINT_ITRN_MAX_INDEX 2
#define I40E_VFINT_ITRN_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VFINT_STAT_CTL0_MAX_INDEX 127
#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
-#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPINT_AEQCTL_MAX_INDEX 127
#define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_AEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT)
#define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT)
#define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_AEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_VPINT_CEQCTL_MAX_INDEX 511
#define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0
-#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK (0xFF << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11
-#define I40E_VPINT_CEQCTL_ITR_INDX_MASK (0x3 << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_ITR_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13
-#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK (0x7 << I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16
-#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK (0x7FF << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)
#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27
-#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK (0x3 << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
+#define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT)
#define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30
-#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK (0x1 << I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
+#define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT)
#define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31
-#define I40E_VPINT_CEQCTL_INTEVENT_MASK (0x1 << I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
-#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_INTEVENT_SHIFT)
+#define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPINT_LNKLST0_MAX_INDEX 127
#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT)
#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VPINT_LNKLSTN_MAX_INDEX 511
#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0
-#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK (0x7FF << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
+#define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT)
#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11
-#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK (0x3 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
-#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
+#define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPINT_RATE0_MAX_INDEX 127
#define I40E_VPINT_RATE0_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATE0_INTERVAL_MASK (0x3F << I40E_VPINT_RATE0_INTERVAL_SHIFT)
+#define I40E_VPINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATE0_INTERVAL_SHIFT)
#define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATE0_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
-#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */
+#define I40E_VPINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATE0_INTRL_ENA_SHIFT)
+#define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VPINT_RATEN_MAX_INDEX 511
#define I40E_VPINT_RATEN_INTERVAL_SHIFT 0
-#define I40E_VPINT_RATEN_INTERVAL_MASK (0x3F << I40E_VPINT_RATEN_INTERVAL_SHIFT)
+#define I40E_VPINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATEN_INTERVAL_SHIFT)
#define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6
-#define I40E_VPINT_RATEN_INTRL_ENA_MASK (0x1 << I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
-#define I40E_GL_RDPU_CNTRL 0x00051060
+#define I40E_VPINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATEN_INTRL_ENA_SHIFT)
+#define I40E_GL_RDPU_CNTRL 0x00051060 /* Reset: CORER */
#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0
-#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK (0x1 << I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
+#define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK I40E_MASK(0x1, I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT)
#define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1
-#define I40E_GL_RDPU_CNTRL_ECO_MASK (0x7FFFFFFF << I40E_GL_RDPU_CNTRL_ECO_SHIFT)
-#define I40E_GLLAN_RCTL_0 0x0012A500
+#define I40E_GL_RDPU_CNTRL_ECO_MASK I40E_MASK(0x7FFFFFFF, I40E_GL_RDPU_CNTRL_ECO_SHIFT)
+#define I40E_GLLAN_RCTL_0 0x0012A500 /* Reset: CORER */
#define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0
-#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK (0x1 << I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
-#define I40E_GLLAN_TSOMSK_F 0x000442D8
+#define I40E_GLLAN_RCTL_0_PXE_MODE_MASK I40E_MASK(0x1, I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT)
+#define I40E_GLLAN_TSOMSK_F 0x000442D8 /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0
-#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK (0xFFF << I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
-#define I40E_GLLAN_TSOMSK_L 0x000442E0
+#define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT)
+#define I40E_GLLAN_TSOMSK_L 0x000442E0 /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0
-#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK (0xFFF << I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
-#define I40E_GLLAN_TSOMSK_M 0x000442DC
+#define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT)
+#define I40E_GLLAN_TSOMSK_M 0x000442DC /* Reset: CORER */
#define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0
-#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK (0xFFF << I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
-#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000E6500 + ((_i) * 4)) /* i=0..11 */
+#define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS(_i) (0x000e6500 + ((_i) * 4)) /* _i=0...11 */ /* Reset: CORER */
+#define I40E_GLLAN_TXPRE_QDIS_MAX_INDEX 11
#define I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT 0
-#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK (0x7FF << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK I40E_MASK(0x7FF, I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT 16
+#define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT)
#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30
-#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
+#define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT)
#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31
-#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK (0x1 << I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
-
-#define I40E_PFLAN_QALLOC 0x001C0400
+#define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT)
+#define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */
#define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0
-#define I40E_PFLAN_QALLOC_FIRSTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT)
#define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16
-#define I40E_PFLAN_QALLOC_LASTQ_MASK (0x7FF << I40E_PFLAN_QALLOC_LASTQ_SHIFT)
+#define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT)
#define I40E_PFLAN_QALLOC_VALID_SHIFT 31
-#define I40E_PFLAN_QALLOC_VALID_MASK (0x1 << I40E_PFLAN_QALLOC_VALID_SHIFT)
-#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT)
+#define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QRX_ENA_MAX_INDEX 1535
#define I40E_QRX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QRX_ENA_QENA_REQ_MASK (0x1 << I40E_QRX_ENA_QENA_REQ_SHIFT)
+#define I40E_QRX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_REQ_SHIFT)
#define I40E_QRX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QRX_ENA_FAST_QDIS_MASK (0x1 << I40E_QRX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QRX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QRX_ENA_FAST_QDIS_SHIFT)
#define I40E_QRX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QRX_ENA_QENA_STAT_MASK (0x1 << I40E_QRX_ENA_QENA_STAT_SHIFT)
-#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_STAT_SHIFT)
+#define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QRX_TAIL_MAX_INDEX 1535
#define I40E_QRX_TAIL_TAIL_SHIFT 0
-#define I40E_QRX_TAIL_TAIL_MASK (0x1FFF << I40E_QRX_TAIL_TAIL_SHIFT)
-#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QRX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL_TAIL_SHIFT)
+#define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QTX_CTL_MAX_INDEX 1535
#define I40E_QTX_CTL_PFVF_Q_SHIFT 0
-#define I40E_QTX_CTL_PFVF_Q_MASK (0x3 << I40E_QTX_CTL_PFVF_Q_SHIFT)
+#define I40E_QTX_CTL_PFVF_Q_MASK I40E_MASK(0x3, I40E_QTX_CTL_PFVF_Q_SHIFT)
#define I40E_QTX_CTL_PF_INDX_SHIFT 2
-#define I40E_QTX_CTL_PF_INDX_MASK (0xF << I40E_QTX_CTL_PF_INDX_SHIFT)
+#define I40E_QTX_CTL_PF_INDX_MASK I40E_MASK(0xF, I40E_QTX_CTL_PF_INDX_SHIFT)
#define I40E_QTX_CTL_VFVM_INDX_SHIFT 7
-#define I40E_QTX_CTL_VFVM_INDX_MASK (0x1FF << I40E_QTX_CTL_VFVM_INDX_SHIFT)
-#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_CTL_VFVM_INDX_MASK I40E_MASK(0x1FF, I40E_QTX_CTL_VFVM_INDX_SHIFT)
+#define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QTX_ENA_MAX_INDEX 1535
#define I40E_QTX_ENA_QENA_REQ_SHIFT 0
-#define I40E_QTX_ENA_QENA_REQ_MASK (0x1 << I40E_QTX_ENA_QENA_REQ_SHIFT)
+#define I40E_QTX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_REQ_SHIFT)
#define I40E_QTX_ENA_FAST_QDIS_SHIFT 1
-#define I40E_QTX_ENA_FAST_QDIS_MASK (0x1 << I40E_QTX_ENA_FAST_QDIS_SHIFT)
+#define I40E_QTX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QTX_ENA_FAST_QDIS_SHIFT)
#define I40E_QTX_ENA_QENA_STAT_SHIFT 2
-#define I40E_QTX_ENA_QENA_STAT_MASK (0x1 << I40E_QTX_ENA_QENA_STAT_SHIFT)
-#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_STAT_SHIFT)
+#define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */
#define I40E_QTX_HEAD_MAX_INDEX 1535
#define I40E_QTX_HEAD_HEAD_SHIFT 0
-#define I40E_QTX_HEAD_HEAD_MASK (0x1FFF << I40E_QTX_HEAD_HEAD_SHIFT)
+#define I40E_QTX_HEAD_HEAD_MASK I40E_MASK(0x1FFF, I40E_QTX_HEAD_HEAD_SHIFT)
#define I40E_QTX_HEAD_RS_PENDING_SHIFT 16
-#define I40E_QTX_HEAD_RS_PENDING_MASK (0x1 << I40E_QTX_HEAD_RS_PENDING_SHIFT)
-#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */
+#define I40E_QTX_HEAD_RS_PENDING_MASK I40E_MASK(0x1, I40E_QTX_HEAD_RS_PENDING_SHIFT)
+#define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */
#define I40E_QTX_TAIL_MAX_INDEX 1535
#define I40E_QTX_TAIL_TAIL_SHIFT 0
-#define I40E_QTX_TAIL_TAIL_MASK (0x1FFF << I40E_QTX_TAIL_TAIL_SHIFT)
-#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_QTX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL_TAIL_SHIFT)
+#define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPLAN_MAPENA_MAX_INDEX 127
#define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0
-#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK (0x1 << I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
-#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VPLAN_MAPENA_TXRX_ENA_MASK I40E_MASK(0x1, I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT)
+#define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: VFR */
#define I40E_VPLAN_QTABLE_MAX_INDEX 15
#define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0
-#define I40E_VPLAN_QTABLE_QINDEX_MASK (0x7FF << I40E_VPLAN_QTABLE_QINDEX_SHIFT)
-#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPLAN_QTABLE_QINDEX_MASK I40E_MASK(0x7FF, I40E_VPLAN_QTABLE_QINDEX_SHIFT)
+#define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
#define I40E_VSILAN_QBASE_MAX_INDEX 383
#define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0
-#define I40E_VSILAN_QBASE_VSIBASE_MASK (0x7FF << I40E_VSILAN_QBASE_VSIBASE_SHIFT)
+#define I40E_VSILAN_QBASE_VSIBASE_MASK I40E_MASK(0x7FF, I40E_VSILAN_QBASE_VSIBASE_SHIFT)
#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
-#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
-#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK I40E_MASK(0x1, I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
+#define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...7, _VSI=0...383 */ /* Reset: PFR */
#define I40E_VSILAN_QTABLE_MAX_INDEX 7
#define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
-#define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
+#define I40E_VSILAN_QTABLE_QINDEX_0_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
#define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
-#define I40E_VSILAN_QTABLE_QINDEX_1_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
-#define I40E_PRTGL_SAH 0x001E2140
+#define I40E_VSILAN_QTABLE_QINDEX_1_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_1_SHIFT)
+#define I40E_PRTGL_SAH 0x001E2140 /* Reset: GLOBR */
#define I40E_PRTGL_SAH_FC_SAH_SHIFT 0
-#define I40E_PRTGL_SAH_FC_SAH_MASK (0xFFFF << I40E_PRTGL_SAH_FC_SAH_SHIFT)
+#define I40E_PRTGL_SAH_FC_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_FC_SAH_SHIFT)
#define I40E_PRTGL_SAH_MFS_SHIFT 16
-#define I40E_PRTGL_SAH_MFS_MASK (0xFFFF << I40E_PRTGL_SAH_MFS_SHIFT)
-#define I40E_PRTGL_SAL 0x001E2120
+#define I40E_PRTGL_SAH_MFS_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_MFS_SHIFT)
+#define I40E_PRTGL_SAL 0x001E2120 /* Reset: GLOBR */
#define I40E_PRTGL_SAL_FC_SAL_SHIFT 0
-#define I40E_PRTGL_SAL_FC_SAL_MASK (0xFFFFFFFF << I40E_PRTGL_SAL_FC_SAL_SHIFT)
-#define I40E_PRTMAC_HLCTLA 0x001E4760
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HLCTLA_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HLCTLA_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT 1
-#define I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_MASK (0x1 << I40E_PRTMAC_HLCTLA_RX_FWRD_CTRL_SHIFT)
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT 2
-#define I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_CHOP_OS_PKT_SHIFT)
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HLCTLA_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HLCTLA_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP 0x001E3130
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GCP_HSEC_CTL_RX_CHECK_SA_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP 0x001E3290
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_GPP_HSEC_CTL_RX_CHECK_SA_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP 0x001E3310
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_SA_PPP_HSEC_CTL_RX_CHECK_SA_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP 0x001E3100
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GCP_HSEC_CTL_RX_CHECK_UCAST_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP 0x001E3280
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_GPP_HSEC_CTL_RX_CHECK_UCAST_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP 0x001E3300
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_CHECK_UCAST_PPP_HSEC_CTL_RX_CHECK_UCAST_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0
+#define I40E_PRTGL_SAL_FC_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTGL_SAL_FC_SAL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360
+#define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110
+#define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE 0x001E3000
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_MASK (0x1 << I40E_PRTMAC_HSEC_CTL_TX_ENABLE_HSEC_CTL_TX_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0
+#define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK (0x1FF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16))
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8
#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0
+#define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK (0xFFFFFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT)
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0 /* Reset: GLOBR */
#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0
-#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK (0xFFFF << I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
-#define I40E_PRTMAC_HSECTL1 0x001E3560
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT 0
-#define I40E_PRTMAC_HSECTL1_DROP_US_PKTS_MASK (0x1 << I40E_PRTMAC_HSECTL1_DROP_US_PKTS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT 3
-#define I40E_PRTMAC_HSECTL1_PAD_US_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_PAD_US_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT 4
-#define I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_MASK (0x7 << I40E_PRTMAC_HSECTL1_TX_HYSTERESIS_SHIFT)
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT 7
-#define I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_MASK (0x1 << I40E_PRTMAC_HSECTL1_HYS_FLUSH_PKT_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT 30
-#define I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_SFD_CHECK_SHIFT)
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT 31
-#define I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_MASK (0x1 << I40E_PRTMAC_HSECTL1_EN_PREAMBLE_CHECK_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480
+#define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480 /* Reset: GLOBR */
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484
+#define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484 /* Reset: GLOBR */
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT)
#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
-#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
-#define I40E_GL_MNG_FWSM 0x000B6134
-#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
-#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
+#define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
+#define I40E_GL_FWRESETCNT 0x00083100 /* Reset: POR */
+#define I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT 0
+#define I40E_GL_FWRESETCNT_FWRESETCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT)
+#define I40E_GL_MNG_FWSM 0x000B6134 /* Reset: POR */
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK I40E_MASK(0x3, I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
-#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
+#define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK I40E_MASK(0xF, I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
-#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
#define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
-#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK I40E_MASK(0x7, I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
#define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
-#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
-#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
-#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
+#define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK I40E_MASK(0x3F, I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
-#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
-#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28
-#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT)
#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29
-#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
-#define I40E_GL_MNG_HWARB_CTRL 0x000B6130
+#define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT)
+#define I40E_GL_MNG_HWARB_CTRL 0x000B6130 /* Reset: POR */
#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0
-#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK (0x1 << I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
-#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */
+#define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK I40E_MASK(0x1, I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT)
+#define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */ /* Reset: POR */
#define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31
#define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0
-#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
-#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260
+#define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT)
+#define I40E_PRT_MNG_FTFT_LENGTH 0x00085260 /* Reset: POR */
#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK (0xFF << I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7
#define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0
-#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK (0xFFFF << I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
-#define I40E_PRT_MNG_MANC 0x00256A20
+#define I40E_PRT_MNG_FTFT_MASK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT)
+#define I40E_PRT_MNG_MANC 0x00256A20 /* Reset: POR */
#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0
-#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT)
#define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1
-#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK (0x1 << I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
+#define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT)
#define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17
-#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT)
#define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19
-#define I40E_PRT_MNG_MANC_RCV_ALL_MASK (0x1 << I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
+#define I40E_PRT_MNG_MANC_RCV_ALL_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_ALL_SHIFT)
#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25
-#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT)
#define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26
-#define I40E_PRT_MNG_MANC_NET_TYPE_MASK (0x1 << I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
+#define I40E_PRT_MNG_MANC_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NET_TYPE_SHIFT)
#define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28
-#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
+#define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT)
#define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29
-#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK (0x1 << I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
-#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT)
+#define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MAVTV_MAX_INDEX 7
#define I40E_PRT_MNG_MAVTV_VID_SHIFT 0
-#define I40E_PRT_MNG_MAVTV_VID_MASK (0xFFF << I40E_PRT_MNG_MAVTV_VID_SHIFT)
-#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32))
+#define I40E_PRT_MNG_MAVTV_VID_MASK I40E_MASK(0xFFF, I40E_PRT_MNG_MAVTV_VID_SHIFT)
+#define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEF_MAX_INDEX 7
#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4
-#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5
-#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK (0xFF << I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_VLAN_AND_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13
-#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17
-#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK (0xF << I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21
-#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK (0xF << I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26
-#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK (0x1 << I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29
-#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30
-#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31
-#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
-#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32))
+#define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7
#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4
-#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK (0xF << I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK (0xFFFF << I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24
-#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27
-#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28
-#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29
-#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_MLD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT)
#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31
-#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK (0x1 << I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
-#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3
#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT)
#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16
-#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK (0xFFFF << I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
-#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT)
+#define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_METF_MAX_INDEX 3
#define I40E_PRT_MNG_METF_ETYPE_SHIFT 0
-#define I40E_PRT_MNG_METF_ETYPE_MASK (0xFFFF << I40E_PRT_MNG_METF_ETYPE_SHIFT)
+#define I40E_PRT_MNG_METF_ETYPE_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_METF_ETYPE_SHIFT)
#define I40E_PRT_MNG_METF_POLARITY_SHIFT 30
-#define I40E_PRT_MNG_METF_POLARITY_MASK (0x1 << I40E_PRT_MNG_METF_POLARITY_SHIFT)
-#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_METF_POLARITY_MASK I40E_MASK(0x1, I40E_PRT_MNG_METF_POLARITY_SHIFT)
+#define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
#define I40E_PRT_MNG_MFUTP_MAX_INDEX 15
#define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0
-#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK (0xFFFF << I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
+#define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT)
#define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16
-#define I40E_PRT_MNG_MFUTP_UDP_MASK (0x1 << I40E_PRT_MNG_MFUTP_UDP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_UDP_SHIFT)
#define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17
-#define I40E_PRT_MNG_MFUTP_TCP_MASK (0x1 << I40E_PRT_MNG_MFUTP_TCP_SHIFT)
+#define I40E_PRT_MNG_MFUTP_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_TCP_SHIFT)
#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18
-#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK (0x1 << I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
-#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT)
+#define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3
#define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */
+#define I40E_PRT_MNG_MIPAF4_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */
#define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15
#define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0
-#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK (0xFFFFFFFF << I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
-#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MIPAF6_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT)
+#define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MMAH_MAX_INDEX 3
#define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0
-#define I40E_PRT_MNG_MMAH_MMAH_MASK (0xFFFF << I40E_PRT_MNG_MMAH_MMAH_SHIFT)
-#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRT_MNG_MMAH_MMAH_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MMAH_MMAH_SHIFT)
+#define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */
#define I40E_PRT_MNG_MMAL_MAX_INDEX 3
#define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0
-#define I40E_PRT_MNG_MMAL_MMAL_MASK (0xFFFFFFFF << I40E_PRT_MNG_MMAL_MMAL_SHIFT)
-#define I40E_PRT_MNG_MNGONLY 0x00256A60
+#define I40E_PRT_MNG_MMAL_MMAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MMAL_MMAL_SHIFT)
+#define I40E_PRT_MNG_MNGONLY 0x00256A60 /* Reset: POR */
#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0
-#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK (0xFF << I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
-#define I40E_PRT_MNG_MSFM 0x00256AA0
+#define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT)
+#define I40E_PRT_MNG_MSFM 0x00256AA0 /* Reset: POR */
#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0
-#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1
-#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2
-#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT)
#define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3
-#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK (0x1 << I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
+#define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4
-#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5
-#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6
-#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
+#define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT)
#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7
-#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK (0x1 << I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
-#define I40E_MSIX_PBA(_i) (0x00004900 + ((_i) * 4)) /* _i=0...5 */
+#define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT)
+#define I40E_MSIX_PBA(_i) (0x00001000 + ((_i) * 4)) /* _i=0...5 */ /* Reset: FLR */
#define I40E_MSIX_PBA_MAX_INDEX 5
#define I40E_MSIX_PBA_PENBIT_SHIFT 0
-#define I40E_MSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_MSIX_PBA_PENBIT_SHIFT)
-#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_PBA_PENBIT_SHIFT)
+#define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TADD_MAX_INDEX 128
#define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_MSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_MSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_MSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_MSIX_TADD_MSIXTADD10_SHIFT)
#define I40E_MSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_MSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_MSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_MSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TMSG_MAX_INDEX 128
#define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_MSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TUADD_MAX_INDEX 128
#define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_MSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */
+#define I40E_MSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */
#define I40E_MSIX_TVCTRL_MAX_INDEX 128
#define I40E_MSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_MSIX_TVCTRL_MASK_MASK (0x1 << I40E_MSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFMSIX_PBA1(_i) (0x00004944 + ((_i) * 4)) /* _i=0...19 */
+#define I40E_MSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_MSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */
#define I40E_VFMSIX_PBA1_MAX_INDEX 19
#define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA1_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA1_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TADD1_MAX_INDEX 639
#define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT)
#define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD1_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TMSG1_MAX_INDEX 639
#define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TUADD1_MAX_INDEX 639
#define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */
+#define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */
#define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639
#define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL1_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
-#define I40E_GLNVM_FLA 0x000B6108
+#define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT)
+#define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */
#define I40E_GLNVM_FLA_FL_SCK_SHIFT 0
-#define I40E_GLNVM_FLA_FL_SCK_MASK (0x1 << I40E_GLNVM_FLA_FL_SCK_SHIFT)
+#define I40E_GLNVM_FLA_FL_SCK_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SCK_SHIFT)
#define I40E_GLNVM_FLA_FL_CE_SHIFT 1
-#define I40E_GLNVM_FLA_FL_CE_MASK (0x1 << I40E_GLNVM_FLA_FL_CE_SHIFT)
+#define I40E_GLNVM_FLA_FL_CE_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_CE_SHIFT)
#define I40E_GLNVM_FLA_FL_SI_SHIFT 2
-#define I40E_GLNVM_FLA_FL_SI_MASK (0x1 << I40E_GLNVM_FLA_FL_SI_SHIFT)
+#define I40E_GLNVM_FLA_FL_SI_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SI_SHIFT)
#define I40E_GLNVM_FLA_FL_SO_SHIFT 3
-#define I40E_GLNVM_FLA_FL_SO_MASK (0x1 << I40E_GLNVM_FLA_FL_SO_SHIFT)
+#define I40E_GLNVM_FLA_FL_SO_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SO_SHIFT)
#define I40E_GLNVM_FLA_FL_REQ_SHIFT 4
-#define I40E_GLNVM_FLA_FL_REQ_MASK (0x1 << I40E_GLNVM_FLA_FL_REQ_SHIFT)
+#define I40E_GLNVM_FLA_FL_REQ_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_REQ_SHIFT)
#define I40E_GLNVM_FLA_FL_GNT_SHIFT 5
-#define I40E_GLNVM_FLA_FL_GNT_MASK (0x1 << I40E_GLNVM_FLA_FL_GNT_SHIFT)
+#define I40E_GLNVM_FLA_FL_GNT_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_GNT_SHIFT)
#define I40E_GLNVM_FLA_LOCKED_SHIFT 6
-#define I40E_GLNVM_FLA_LOCKED_MASK (0x1 << I40E_GLNVM_FLA_LOCKED_SHIFT)
+#define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SHIFT)
#define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18
-#define I40E_GLNVM_FLA_FL_SADDR_MASK (0x7FF << I40E_GLNVM_FLA_FL_SADDR_SHIFT)
+#define I40E_GLNVM_FLA_FL_SADDR_MASK I40E_MASK(0x7FF, I40E_GLNVM_FLA_FL_SADDR_SHIFT)
#define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30
-#define I40E_GLNVM_FLA_FL_BUSY_MASK (0x1 << I40E_GLNVM_FLA_FL_BUSY_SHIFT)
+#define I40E_GLNVM_FLA_FL_BUSY_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_BUSY_SHIFT)
#define I40E_GLNVM_FLA_FL_DER_SHIFT 31
-#define I40E_GLNVM_FLA_FL_DER_MASK (0x1 << I40E_GLNVM_FLA_FL_DER_SHIFT)
-#define I40E_GLNVM_FLASHID 0x000B6104
+#define I40E_GLNVM_FLA_FL_DER_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_DER_SHIFT)
+#define I40E_GLNVM_FLASHID 0x000B6104 /* Reset: POR */
#define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0
-#define I40E_GLNVM_FLASHID_FLASHID_MASK (0xFFFFFF << I40E_GLNVM_FLASHID_FLASHID_SHIFT)
-#define I40E_GLNVM_GENS 0x000B6100
+#define I40E_GLNVM_FLASHID_FLASHID_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_FLASHID_FLASHID_SHIFT)
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT 31
+#define I40E_GLNVM_FLASHID_FLEEP_PERF_MASK I40E_MASK(0x1, I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT)
+#define I40E_GLNVM_GENS 0x000B6100 /* Reset: POR */
#define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0
-#define I40E_GLNVM_GENS_NVM_PRES_MASK (0x1 << I40E_GLNVM_GENS_NVM_PRES_SHIFT)
+#define I40E_GLNVM_GENS_NVM_PRES_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_NVM_PRES_SHIFT)
#define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5
-#define I40E_GLNVM_GENS_SR_SIZE_MASK (0x7 << I40E_GLNVM_GENS_SR_SIZE_SHIFT)
+#define I40E_GLNVM_GENS_SR_SIZE_MASK I40E_MASK(0x7, I40E_GLNVM_GENS_SR_SIZE_SHIFT)
#define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8
-#define I40E_GLNVM_GENS_BANK1VAL_MASK (0x1 << I40E_GLNVM_GENS_BANK1VAL_SHIFT)
+#define I40E_GLNVM_GENS_BANK1VAL_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_BANK1VAL_SHIFT)
#define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23
-#define I40E_GLNVM_GENS_ALT_PRST_MASK (0x1 << I40E_GLNVM_GENS_ALT_PRST_SHIFT)
+#define I40E_GLNVM_GENS_ALT_PRST_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_ALT_PRST_SHIFT)
#define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25
-#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK (0x1 << I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
-#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */
+#define I40E_GLNVM_GENS_FL_AUTO_RD_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT)
+#define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */ /* Reset: POR */
#define I40E_GLNVM_PROTCSR_MAX_INDEX 59
#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0
-#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK (0xFFFFFF << I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
-#define I40E_GLNVM_SRCTL 0x000B6110
+#define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT)
+#define I40E_GLNVM_SRCTL 0x000B6110 /* Reset: POR */
#define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0
-#define I40E_GLNVM_SRCTL_SRBUSY_MASK (0x1 << I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
+#define I40E_GLNVM_SRCTL_SRBUSY_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_SRBUSY_SHIFT)
#define I40E_GLNVM_SRCTL_ADDR_SHIFT 14
-#define I40E_GLNVM_SRCTL_ADDR_MASK (0x7FFF << I40E_GLNVM_SRCTL_ADDR_SHIFT)
+#define I40E_GLNVM_SRCTL_ADDR_MASK I40E_MASK(0x7FFF, I40E_GLNVM_SRCTL_ADDR_SHIFT)
#define I40E_GLNVM_SRCTL_WRITE_SHIFT 29
-#define I40E_GLNVM_SRCTL_WRITE_MASK (0x1 << I40E_GLNVM_SRCTL_WRITE_SHIFT)
+#define I40E_GLNVM_SRCTL_WRITE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_WRITE_SHIFT)
#define I40E_GLNVM_SRCTL_START_SHIFT 30
-#define I40E_GLNVM_SRCTL_START_MASK (0x1 << I40E_GLNVM_SRCTL_START_SHIFT)
+#define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT)
#define I40E_GLNVM_SRCTL_DONE_SHIFT 31
-#define I40E_GLNVM_SRCTL_DONE_MASK (0x1 << I40E_GLNVM_SRCTL_DONE_SHIFT)
-#define I40E_GLNVM_SRDATA 0x000B6114
+#define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT)
+#define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */
#define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0
-#define I40E_GLNVM_SRDATA_WRDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_WRDATA_SHIFT)
+#define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT)
#define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16
-#define I40E_GLNVM_SRDATA_RDDATA_MASK (0xFFFF << I40E_GLNVM_SRDATA_RDDATA_SHIFT)
-#define I40E_GLNVM_ULD 0x000B6008
+#define I40E_GLNVM_SRDATA_RDDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_RDDATA_SHIFT)
+#define I40E_GLNVM_ULD 0x000B6008 /* Reset: POR */
#define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0
-#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1
-#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2
-#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3
-#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4
-#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5
-#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_POR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6
-#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7
-#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8
-#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
+#define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT)
#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9
-#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK (0x1 << I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
-
-#define I40E_GLPCI_BYTCTH 0x0009C484
+#define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT)
+#define I40E_GLPCI_BYTCTH 0x0009C484 /* Reset: PCIR */
#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_BYTCTL 0x0009C488
+#define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_BYTCTL 0x0009C488 /* Reset: PCIR */
#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0
-#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK (0xFFFFFFFF << I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
-#define I40E_GLPCI_CAPCTRL 0x000BE4A4
+#define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT)
+#define I40E_GLPCI_CAPCTRL 0x000BE4A4 /* Reset: PCIR */
#define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0
-#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK (0x1 << I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
-#define I40E_GLPCI_CAPSUP 0x000BE4A8
+#define I40E_GLPCI_CAPCTRL_VPD_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP 0x000BE4A8 /* Reset: PCIR */
#define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0
-#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK (0x1 << I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
+#define I40E_GLPCI_CAPSUP_PCIE_VER_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT)
#define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2
-#define I40E_GLPCI_CAPSUP_LTR_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_LTR_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LTR_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3
-#define I40E_GLPCI_CAPSUP_TPH_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_TPH_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_TPH_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4
-#define I40E_GLPCI_CAPSUP_ARI_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ARI_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ARI_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5
-#define I40E_GLPCI_CAPSUP_IOV_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IOV_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IOV_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6
-#define I40E_GLPCI_CAPSUP_ACS_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ACS_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ACS_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7
-#define I40E_GLPCI_CAPSUP_SEC_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_SEC_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_SEC_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16
-#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17
-#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18
-#define I40E_GLPCI_CAPSUP_IDO_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_IDO_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IDO_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19
-#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK (0x1 << I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
+#define I40E_GLPCI_CAPSUP_MSI_MASK_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT)
#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20
-#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK (0x1 << I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
+#define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT)
#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30
-#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
+#define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT)
#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31
-#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK (0x1 << I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
-#define I40E_GLPCI_CNF 0x000BE4C0
+#define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT)
+#define I40E_GLPCI_CNF 0x000BE4C0 /* Reset: POR */
#define I40E_GLPCI_CNF_FLEX10_SHIFT 1
-#define I40E_GLPCI_CNF_FLEX10_MASK (0x1 << I40E_GLPCI_CNF_FLEX10_SHIFT)
+#define I40E_GLPCI_CNF_FLEX10_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_FLEX10_SHIFT)
#define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2
-#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK (0x1 << I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
-#define I40E_GLPCI_CNF2 0x000BE494
+#define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT)
+#define I40E_GLPCI_CNF2 0x000BE494 /* Reset: PCIR */
#define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0
-#define I40E_GLPCI_CNF2_RO_DIS_MASK (0x1 << I40E_GLPCI_CNF2_RO_DIS_SHIFT)
+#define I40E_GLPCI_CNF2_RO_DIS_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_RO_DIS_SHIFT)
#define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1
-#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK (0x1 << I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
+#define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT)
#define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2
-#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
+#define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT)
#define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13
-#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK (0x7FF << I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
-#define I40E_GLPCI_DREVID 0x0009C480
+#define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT)
+#define I40E_GLPCI_DREVID 0x0009C480 /* Reset: PCIR */
#define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0
-#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK (0xFF << I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
-#define I40E_GLPCI_GSCL_1 0x0009C48C
+#define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT)
+#define I40E_GLPCI_GSCL_1 0x0009C48C /* Reset: PCIR */
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT)
#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7
-#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK (0x1 << I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
+#define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15
-#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK (0x1F << I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
+#define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28
-#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT)
#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31
-#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK (0x1 << I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
-#define I40E_GLPCI_GSCL_2 0x0009C490
+#define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT)
+#define I40E_GLPCI_GSCL_2 0x0009C490 /* Reset: PCIR */
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT)
#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24
-#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK (0xFF << I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
-#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT)
+#define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
#define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3
#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0
-#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
+#define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT)
#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16
-#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK (0xFFFF << I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
-#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */
+#define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT)
+#define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */
#define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3
#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0
-#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK (0xFFFFFFFF << I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
-#define I40E_GLPCI_LATCT 0x0009C4B4
+#define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT)
+#define I40E_GLPCI_LATCT 0x0009C4B4 /* Reset: PCIR */
#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT 0
-#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK (0xFFFFFFFF << I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
-#define I40E_GLPCI_LBARCTRL 0x000BE484
+#define I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_LATCT_PCI_COUNT_LAT_CT_SHIFT)
+#define I40E_GLPCI_LBARCTRL 0x000BE484 /* Reset: POR */
#define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0
-#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK (0x1 << I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
+#define I40E_GLPCI_LBARCTRL_PREFBAR_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT)
#define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1
-#define I40E_GLPCI_LBARCTRL_BAR32_MASK (0x1 << I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
+#define I40E_GLPCI_LBARCTRL_BAR32_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_BAR32_SHIFT)
#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3
-#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK (0x1 << I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT 4
-#define I40E_GLPCI_LBARCTRL_PE_DB_SIZE_MASK (0x3 << I40E_GLPCI_LBARCTRL_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT 4
+#define I40E_GLPCI_LBARCTRL_RSVD_4_MASK I40E_MASK(0x3, I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT)
#define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6
-#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT 10
-#define I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_MASK (0x1 << I40E_GLPCI_LBARCTRL_VF_PE_DB_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT)
+#define I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT 10
+#define I40E_GLPCI_LBARCTRL_RSVD_10_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT)
#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11
-#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK (0x7 << I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
-#define I40E_GLPCI_LINKCAP 0x000BE4AC
+#define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT)
+#define I40E_GLPCI_LINKCAP 0x000BE4AC /* Reset: PCIR */
#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0
-#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK (0x3F << I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
+#define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK I40E_MASK(0x3F, I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT)
#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6
-#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK (0x7 << I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
+#define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK I40E_MASK(0x7, I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT)
#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9
-#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK (0xF << I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
-#define I40E_GLPCI_PCIERR 0x000BE4FC
+#define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK I40E_MASK(0xF, I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT)
+#define I40E_GLPCI_PCIERR 0x000BE4FC /* Reset: PCIR */
#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
-#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
-#define I40E_GLPCI_PCITEST2 0x000BE4BC
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
-#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
-#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
-
-#define I40E_GLPCI_PKTCT 0x0009C4BC
+#define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PKTCT 0x0009C4BC /* Reset: PCIR */
#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
-#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
-#define I40E_GLPCI_PMSUP 0x000BE4B0
+#define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0 /* Reset: PCIR */
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0
+#define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
+#define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PMSUP 0x000BE4B0 /* Reset: PCIR */
#define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0
-#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
+#define I40E_GLPCI_PMSUP_ASPM_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT)
#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2
-#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5
-#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8
-#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11
-#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK (0x7 << I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
+#define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT)
#define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14
-#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK (0x1 << I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
+#define I40E_GLPCI_PMSUP_SLOT_CLK_MASK I40E_MASK(0x1, I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT)
#define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15
-#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK (0x3 << I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
-#define I40E_GLPCI_PWRDATA 0x000BE490
+#define I40E_GLPCI_PMSUP_OBFF_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC /* Reset: PCIR */
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
+#define I40E_GLPCI_PWRDATA 0x000BE490 /* Reset: PCIR */
#define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0
-#define I40E_GLPCI_PWRDATA_D0_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D0_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D0_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8
-#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_COMM_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16
-#define I40E_GLPCI_PWRDATA_D3_POWER_MASK (0xFF << I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
+#define I40E_GLPCI_PWRDATA_D3_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D3_POWER_SHIFT)
#define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24
-#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK (0x3 << I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
-#define I40E_GLPCI_REVID 0x000BE4B4
+#define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK I40E_MASK(0x3, I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT)
+#define I40E_GLPCI_REVID 0x000BE4B4 /* Reset: PCIR */
#define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0
-#define I40E_GLPCI_REVID_NVM_REVID_MASK (0xFF << I40E_GLPCI_REVID_NVM_REVID_SHIFT)
-#define I40E_GLPCI_SERH 0x000BE49C
+#define I40E_GLPCI_REVID_NVM_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_REVID_NVM_REVID_SHIFT)
+#define I40E_GLPCI_SERH 0x000BE49C /* Reset: PCIR */
#define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0
-#define I40E_GLPCI_SERH_SER_NUM_H_MASK (0xFFFF << I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
-#define I40E_GLPCI_SERL 0x000BE498
+#define I40E_GLPCI_SERH_SER_NUM_H_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SERH_SER_NUM_H_SHIFT)
+#define I40E_GLPCI_SERL 0x000BE498 /* Reset: PCIR */
#define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0
-#define I40E_GLPCI_SERL_SER_NUM_L_MASK (0xFFFFFFFF << I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
-#define I40E_GLPCI_SUBSYSID 0x000BE48C
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT 0
-#define I40E_GLPCI_SUBSYSID_SUB_VEN_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_VEN_ID_SHIFT)
-#define I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT 16
-#define I40E_GLPCI_SUBSYSID_SUB_ID_MASK (0xFFFF << I40E_GLPCI_SUBSYSID_SUB_ID_SHIFT)
-#define I40E_GLPCI_UPADD 0x000BE4F8
+#define I40E_GLPCI_SERL_SER_NUM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SERL_SER_NUM_L_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC /* Reset: PCIR */
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0
+#define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT)
+#define I40E_GLPCI_SUBVENID 0x000BE48C /* Reset: PCIR */
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT 0
+#define I40E_GLPCI_SUBVENID_SUB_VEN_ID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT)
+#define I40E_GLPCI_UPADD 0x000BE4F8 /* Reset: PCIR */
#define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1
-#define I40E_GLPCI_UPADD_ADDRESS_MASK (0x7FFFFFFF << I40E_GLPCI_UPADD_ADDRESS_SHIFT)
-#define I40E_GLPCI_VFSUP 0x000BE4B8
+#define I40E_GLPCI_UPADD_ADDRESS_MASK I40E_MASK(0x7FFFFFFF, I40E_GLPCI_UPADD_ADDRESS_SHIFT)
+#define I40E_GLPCI_VENDORID 0x000BE518 /* Reset: PCIR */
+#define I40E_GLPCI_VENDORID_VENDORID_SHIFT 0
+#define I40E_GLPCI_VENDORID_VENDORID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_VENDORID_VENDORID_SHIFT)
+#define I40E_GLPCI_VFSUP 0x000BE4B8 /* Reset: PCIR */
#define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0
-#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK (0x1 << I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
+#define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT)
#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1
-#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK (0x1 << I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
-#define I40E_PF_FUNC_RID 0x0009C000
+#define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT)
+#define I40E_PF_FUNC_RID 0x0009C000 /* Reset: PCIR */
#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0
-#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK (0x7 << I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK I40E_MASK(0x7, I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT)
#define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3
-#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK (0x1F << I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
+#define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK I40E_MASK(0x1F, I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT)
#define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8
-#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK (0xFF << I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
-#define I40E_PF_PCI_CIAA 0x0009C080
+#define I40E_PF_FUNC_RID_BUS_NUMBER_MASK I40E_MASK(0xFF, I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT)
+#define I40E_PF_PCI_CIAA 0x0009C080 /* Reset: FLR */
#define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0
-#define I40E_PF_PCI_CIAA_ADDRESS_MASK (0xFFF << I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
+#define I40E_PF_PCI_CIAA_ADDRESS_MASK I40E_MASK(0xFFF, I40E_PF_PCI_CIAA_ADDRESS_SHIFT)
#define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12
-#define I40E_PF_PCI_CIAA_VF_NUM_MASK (0x7F << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
-#define I40E_PF_PCI_CIAD 0x0009C100
+#define I40E_PF_PCI_CIAA_VF_NUM_MASK I40E_MASK(0x7F, I40E_PF_PCI_CIAA_VF_NUM_SHIFT)
+#define I40E_PF_PCI_CIAD 0x0009C100 /* Reset: FLR */
#define I40E_PF_PCI_CIAD_DATA_SHIFT 0
-#define I40E_PF_PCI_CIAD_DATA_MASK (0xFFFFFFFF << I40E_PF_PCI_CIAD_DATA_SHIFT)
-#define I40E_PFPCI_CLASS 0x000BE400
+#define I40E_PF_PCI_CIAD_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_PCI_CIAD_DATA_SHIFT)
+#define I40E_PFPCI_CLASS 0x000BE400 /* Reset: PCIR */
#define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0
-#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK (0x1 << I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
-#define I40E_PFPCI_CNF 0x000BE000
+#define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT)
+#define I40E_PFPCI_CLASS_RESERVED_1_SHIFT 1
+#define I40E_PFPCI_CLASS_RESERVED_1_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_RESERVED_1_SHIFT)
+#define I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT 2
+#define I40E_PFPCI_CLASS_PF_IS_LAN_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT)
+#define I40E_PFPCI_CNF 0x000BE000 /* Reset: PCIR */
#define I40E_PFPCI_CNF_MSI_EN_SHIFT 2
-#define I40E_PFPCI_CNF_MSI_EN_MASK (0x1 << I40E_PFPCI_CNF_MSI_EN_SHIFT)
+#define I40E_PFPCI_CNF_MSI_EN_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_MSI_EN_SHIFT)
#define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3
-#define I40E_PFPCI_CNF_EXROM_DIS_MASK (0x1 << I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
+#define I40E_PFPCI_CNF_EXROM_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_EXROM_DIS_SHIFT)
#define I40E_PFPCI_CNF_IO_BAR_SHIFT 4
-#define I40E_PFPCI_CNF_IO_BAR_MASK (0x1 << I40E_PFPCI_CNF_IO_BAR_SHIFT)
+#define I40E_PFPCI_CNF_IO_BAR_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_IO_BAR_SHIFT)
#define I40E_PFPCI_CNF_INT_PIN_SHIFT 5
-#define I40E_PFPCI_CNF_INT_PIN_MASK (0x3 << I40E_PFPCI_CNF_INT_PIN_SHIFT)
-#define I40E_PFPCI_FACTPS 0x0009C180
+#define I40E_PFPCI_CNF_INT_PIN_MASK I40E_MASK(0x3, I40E_PFPCI_CNF_INT_PIN_SHIFT)
+#define I40E_PFPCI_DEVID 0x000BE080 /* Reset: PCIR */
+#define I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT 0
+#define I40E_PFPCI_DEVID_PF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT)
+#define I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT 16
+#define I40E_PFPCI_DEVID_VF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT)
+#define I40E_PFPCI_FACTPS 0x0009C180 /* Reset: FLR */
#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0
-#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK (0x3 << I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
+#define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK I40E_MASK(0x3, I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT)
#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3
-#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK (0x1 << I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
-#define I40E_PFPCI_FUNC 0x000BE200
+#define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK I40E_MASK(0x1, I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT)
+#define I40E_PFPCI_FUNC 0x000BE200 /* Reset: POR */
#define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_FUNC_DIS_SHIFT)
#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1
-#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT)
#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2
-#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK (0x1 << I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
-#define I40E_PFPCI_FUNC2 0x000BE180
+#define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT)
+#define I40E_PFPCI_FUNC2 0x000BE180 /* Reset: PCIR */
#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0
-#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK (0x1 << I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
-#define I40E_PFPCI_ICAUSE 0x0009C200
+#define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT)
+#define I40E_PFPCI_ICAUSE 0x0009C200 /* Reset: PFR */
#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0
-#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK (0xFFFFFFFF << I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
-#define I40E_PFPCI_IENA 0x0009C280
+#define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT)
+#define I40E_PFPCI_IENA 0x0009C280 /* Reset: PFR */
#define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0
-#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK (0xFFFFFFFF << I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
-#define I40E_PFPCI_PFDEVID 0x000BE080
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_PFDEVID_PF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_PM 0x000BE300
+#define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT)
+#define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800 /* Reset: PCIR */
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_PM 0x000BE300 /* Reset: POR */
#define I40E_PFPCI_PM_PME_EN_SHIFT 0
-#define I40E_PFPCI_PM_PME_EN_MASK (0x1 << I40E_PFPCI_PM_PME_EN_SHIFT)
-#define I40E_PFPCI_STATUS1 0x000BE280
+#define I40E_PFPCI_PM_PME_EN_MASK I40E_MASK(0x1, I40E_PFPCI_PM_PME_EN_SHIFT)
+#define I40E_PFPCI_STATUS1 0x000BE280 /* Reset: POR */
#define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0
-#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK (0x1 << I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
-#define I40E_PFPCI_VFDEVID 0x000BE100
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT 0
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_LAN_SHIFT)
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT 16
-#define I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_MASK (0xFFFF << I40E_PFPCI_VFDEVID_VF_DEV_ID_SAN_SHIFT)
-#define I40E_PFPCI_VMINDEX 0x0009C300
+#define I40E_PFPCI_STATUS1_FUNC_VALID_MASK I40E_MASK(0x1, I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT)
+#define I40E_PFPCI_SUBSYSID 0x000BE100 /* Reset: PCIR */
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT 0
+#define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT 16
+#define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE 0x0000E400 /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: PCIR */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 /* Reset: PCIR */
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VMINDEX 0x0009C300 /* Reset: PCIR */
#define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0
-#define I40E_PFPCI_VMINDEX_VMINDEX_MASK (0x1FF << I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
-#define I40E_PFPCI_VMPEND 0x0009C380
+#define I40E_PFPCI_VMINDEX_VMINDEX_MASK I40E_MASK(0x1FF, I40E_PFPCI_VMINDEX_VMINDEX_SHIFT)
+#define I40E_PFPCI_VMPEND 0x0009C380 /* Reset: PCIR */
#define I40E_PFPCI_VMPEND_PENDING_SHIFT 0
-#define I40E_PFPCI_VMPEND_PENDING_MASK (0x1 << I40E_PFPCI_VMPEND_PENDING_SHIFT)
-#define I40E_GLPE_CPUSTATUS0 0x0000D040
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT 0
-#define I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS0_PECPUSTATUS0_SHIFT)
-#define I40E_GLPE_CPUSTATUS1 0x0000D044
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT 0
-#define I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS1_PECPUSTATUS1_SHIFT)
-#define I40E_GLPE_CPUSTATUS2 0x0000D048
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT 0
-#define I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_MASK (0xFFFFFFFF << I40E_GLPE_CPUSTATUS2_PECPUSTATUS2_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL(_i) (0x0000D480 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPE_PFFLMOBJCTRL_MAX_INDEX 15
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_PFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMOBJCTRL_MAX_INDEX 31
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT 0
-#define I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_XMIT_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT 8
-#define I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_MASK (0x7 << I40E_GLPE_VFFLMOBJCTRL_Q1_BLOCKSIZE_SHIFT)
-#define I40E_GLPE_VFFLMQ1ALLOCERR(_i) (0x0000C700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMQ1ALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFFLMXMITALLOCERR(_i) (0x0000C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFFLMXMITALLOCERR_MAX_INDEX 31
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_GLPE_VFFLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_GLPE_VFUDACTRL(_i) (0x0000C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDACTRL_MAX_INDEX 31
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_GLPE_VFUDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_GLPE_VFUDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN(_i) (0x0000C100 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPE_VFUDAUCFBQPN_MAX_INDEX 31
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT 0
-#define I40E_GLPE_VFUDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_GLPE_VFUDAUCFBQPN_QPN_SHIFT)
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT 31
-#define I40E_GLPE_VFUDAUCFBQPN_VALID_MASK (0x1 << I40E_GLPE_VFUDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_AEQALLOC 0x00131180
-#define I40E_PFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_PFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_PFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_PFPE_CCQPHIGH 0x00008200
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_PFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_PFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_PFPE_CCQPLOW 0x00008180
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_PFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_PFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_PFPE_CCQPSTATUS 0x00008100
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_PFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_PFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_PFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_PFPE_CQACK 0x00131100
-#define I40E_PFPE_CQACK_PECQID_SHIFT 0
-#define I40E_PFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_PFPE_CQACK_PECQID_SHIFT)
-#define I40E_PFPE_CQARM 0x00131080
-#define I40E_PFPE_CQARM_PECQID_SHIFT 0
-#define I40E_PFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_PFPE_CQARM_PECQID_SHIFT)
-#define I40E_PFPE_CQPDB 0x00008000
-#define I40E_PFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_PFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_PFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_PFPE_CQPERRCODES 0x00008880
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_PFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_PFPE_CQPTAIL 0x00008080
-#define I40E_PFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_PFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_PFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_PFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_PFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_PFPE_FLMQ1ALLOCERR 0x00008980
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMQ1ALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_FLMXMITALLOCERR 0x00008900
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT 0
-#define I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_MASK (0xFFFF << I40E_PFPE_FLMXMITALLOCERR_ERROR_COUNT_SHIFT)
-#define I40E_PFPE_IPCONFIG0 0x00008280
-#define I40E_PFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-
-#define I40E_PFPE_MRTEIDXMASK 0x00008600
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_PFPE_RCVUNEXPECTEDERROR 0x00008680
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_PFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_PFPE_TCPNOWTIMER 0x00008580
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_PFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_PFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_PFPE_UDACTRL 0x00008700
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT 0
-#define I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT 1
-#define I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV4UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT 2
-#define I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6MCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT 3
-#define I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_MASK (0x1 << I40E_PFPE_UDACTRL_IPV6UCFRAGRESBP_SHIFT)
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT 4
-#define I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_MASK (0x1 << I40E_PFPE_UDACTRL_UDPMCFRAGRESFAIL_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN 0x00008780
-#define I40E_PFPE_UDAUCFBQPN_QPN_SHIFT 0
-#define I40E_PFPE_UDAUCFBQPN_QPN_MASK (0x3FFFF << I40E_PFPE_UDAUCFBQPN_QPN_SHIFT)
-#define I40E_PFPE_UDAUCFBQPN_VALID_SHIFT 31
-#define I40E_PFPE_UDAUCFBQPN_VALID_MASK (0x1 << I40E_PFPE_UDAUCFBQPN_VALID_SHIFT)
-#define I40E_PFPE_WQEALLOC 0x00138C00
-#define I40E_PFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_PFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_PFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_PFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFPE_AEQALLOC(_VF) (0x00130C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_AEQALLOC_MAX_INDEX 127
-#define I40E_VFPE_AEQALLOC_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH(_VF) (0x00001000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPHIGH_MAX_INDEX 127
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW(_VF) (0x00000C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPLOW_MAX_INDEX 127
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS(_VF) (0x00000800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CCQPSTATUS_MAX_INDEX 127
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK(_VF) (0x00130800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQACK_MAX_INDEX 127
-#define I40E_VFPE_CQACK_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK_PECQID_SHIFT)
-#define I40E_VFPE_CQARM(_VF) (0x00130400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQARM_MAX_INDEX 127
-#define I40E_VFPE_CQARM_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB(_VF) (0x00000000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPDB_MAX_INDEX 127
-#define I40E_VFPE_CQPDB_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES(_VF) (0x00001800 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPERRCODES_MAX_INDEX 127
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL(_VF) (0x00000400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_CQPTAIL_MAX_INDEX 127
-#define I40E_VFPE_CQPTAIL_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG0(_VF) (0x00001400 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_IPCONFIG0_MAX_INDEX 127
-#define I40E_VFPE_IPCONFIG0_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR(_VF) (0x00003400 + ((_VF) * 4))
-#define I40E_VFPE_RCVUNEXPECTEDERROR_MAX_INDEX 127
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER(_VF) (0x00002C00 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_TCPNOWTIMER_MAX_INDEX 127
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC(_VF) (0x00138000 + ((_VF) * 4)) /* _i=0...127 */
-#define I40E_VFPE_WQEALLOC_MAX_INDEX 127
-#define I40E_VFPE_WQEALLOC_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC_WQE_DESC_INDEX_SHIFT)
-#define I40E_GLPES_PFIP4RXDISCARD(_i) (0x00010600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSHI(_i) (0x00010804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXFRAGSLO(_i) (0x00010800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSHI(_i) (0x00010A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCOCTSLO(_i) (0x00010A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSHI(_i) (0x00010C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXMCPKTSLO(_i) (0x00010C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP4RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSHI(_i) (0x00010204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXOCTSLO(_i) (0x00010200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSHI(_i) (0x00010404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4RXPKTSLO(_i) (0x00010400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4RXTRUNC(_i) (0x00010700 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSHI(_i) (0x00011E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXFRAGSLO(_i) (0x00011E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSHI(_i) (0x00012004 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCOCTSLO(_i) (0x00012000 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSHI(_i) (0x00012204 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXMCPKTSLO(_i) (0x00012200 + ((_i) * 8))
-#define I40E_GLPES_PFIP4TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXNOROUTE(_i) (0x00012E00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSHI(_i) (0x00011A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXOCTSLO(_i) (0x00011A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSHI(_i) (0x00011C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP4TXPKTSLO(_i) (0x00011C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP4TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXDISCARD(_i) (0x00011200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXDISCARD_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSHI(_i) (0x00011404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXFRAGSLO(_i) (0x00011400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSHI(_i) (0x00011604 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCOCTSLO(_i) (0x00011600 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSHI(_i) (0x00011804 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXMCPKTSLO(_i) (0x00011800 + ((_i) * 8))
-#define I40E_GLPES_PFIP6RXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSHI(_i) (0x00010E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXOCTSLO(_i) (0x00010E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSHI(_i) (0x00011004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6RXPKTSLO(_i) (0x00011000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6RXTRUNC(_i) (0x00011300 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6RXTRUNC_MAX_INDEX 15
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSHI(_i) (0x00012804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXFRAGSLO(_i) (0x00012800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXFRAGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSHI(_i) (0x00012A04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCOCTSLO(_i) (0x00012A00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSHI(_i) (0x00012C04 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXMCPKTSLO(_i) (0x00012C00 + ((_i) * 8))
-#define I40E_GLPES_PFIP6TXMCPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXNOROUTE(_i) (0x00012F00 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXNOROUTE_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_PFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSHI(_i) (0x00012404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXOCTSLO(_i) (0x00012400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXOCTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSHI(_i) (0x00012604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_PFIP6TXPKTSLO(_i) (0x00012600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFIP6TXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSHI(_i) (0x00013E04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXRDSLO(_i) (0x00013E00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSHI(_i) (0x00014004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXSNDSLO(_i) (0x00014000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSHI(_i) (0x00013C04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMARXWRSLO(_i) (0x00013C00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMARXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSHI(_i) (0x00014404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXRDSLO(_i) (0x00014400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXRDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSHI(_i) (0x00014604 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXSNDSLO(_i) (0x00014600 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXSNDSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSHI(_i) (0x00014204 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_PFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_PFRDMATXWRSLO(_i) (0x00014200 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMATXWRSLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDHI(_i) (0x00014804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_PFRDMAVBNDLO(_i) (0x00014800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVBNDLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_PFRDMAVINVHI(_i) (0x00014A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVHI_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_PFRDMAVINVLO(_i) (0x00014A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFRDMAVINVLO_MAX_INDEX 15
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_PFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_PFRXVLANERR(_i) (0x00010000 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFRXVLANERR_MAX_INDEX 15
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_PFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_PFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_PFTCPRTXSEG(_i) (0x00013600 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRTXSEG_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_PFTCPRXOPTERR(_i) (0x00013200 + ((_i) * 4)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXOPTERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_PFTCPRXPROTOERR(_i) (0x00013300 + ((_i) * 4))
-#define I40E_GLPES_PFTCPRXPROTOERR_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_PFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSHI(_i) (0x00013004 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_PFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_PFTCPRXSEGSLO(_i) (0x00013000 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPRXSEGSLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGHI(_i) (0x00013404 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGHI_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_PFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_PFTCPTXSEGLO(_i) (0x00013400 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFTCPTXSEGLO_MAX_INDEX 15
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_PFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSHI(_i) (0x00013804 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPRXPKTSLO(_i) (0x00013800 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPRXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSHI(_i) (0x00013A04 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSHI_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_PFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_PFUDPTXPKTSLO(_i) (0x00013A00 + ((_i) * 8)) /* _i=0...15 */
-#define I40E_GLPES_PFUDPTXPKTSLO_MAX_INDEX 15
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_PFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSHI 0x0001E014
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXMULTFPDUSHI_RDMARXMULTFPDUSHI_SHIFT)
-#define I40E_GLPES_RDMARXMULTFPDUSLO 0x0001E010
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT 0
-#define I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXMULTFPDUSLO_RDMARXMULTFPDUSLO_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPHI 0x0001E01C
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_MASK (0xFFFFFF << I40E_GLPES_RDMARXOOODDPHI_RDMARXOOODDPHI_SHIFT)
-#define I40E_GLPES_RDMARXOOODDPLO 0x0001E018
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT 0
-#define I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOODDPLO_RDMARXOOODDPLO_SHIFT)
-#define I40E_GLPES_RDMARXOOONOMARK 0x0001E004
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT 0
-#define I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXOOONOMARK_RDMAOOONOMARK_SHIFT)
-#define I40E_GLPES_RDMARXUNALIGN 0x0001E000
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT 0
-#define I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_MASK (0xFFFFFFFF << I40E_GLPES_RDMARXUNALIGN_RDMRXAUNALIGN_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLEHI 0x0001E044
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXFOURHOLEHI_TCPRXFOURHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXFOURHOLELO 0x0001E040
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXFOURHOLELO_TCPRXFOURHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLEHI 0x0001E02C
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXONEHOLEHI_TCPRXONEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXONEHOLELO 0x0001E028
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXONEHOLELO_TCPRXONEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKHI 0x0001E024
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXPUREACKHI_TCPRXPUREACKSHI_SHIFT)
-#define I40E_GLPES_TCPRXPUREACKSLO 0x0001E020
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT 0
-#define I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXPUREACKSLO_TCPRXPUREACKLO_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLEHI 0x0001E03C
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTHREEHOLEHI_TCPRXTHREEHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTHREEHOLELO 0x0001E038
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTHREEHOLELO_TCPRXTHREEHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLEHI 0x0001E034
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_MASK (0xFFFFFF << I40E_GLPES_TCPRXTWOHOLEHI_TCPRXTWOHOLEHI_SHIFT)
-#define I40E_GLPES_TCPRXTWOHOLELO 0x0001E030
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT 0
-#define I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_MASK (0xFFFFFFFF << I40E_GLPES_TCPRXTWOHOLELO_TCPRXTWOHOLELO_SHIFT)
-#define I40E_GLPES_TCPRXUNEXPERR 0x0001E008
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT 0
-#define I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_MASK (0xFFFFFF << I40E_GLPES_TCPRXUNEXPERR_TCPRXUNEXPERR_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTHI 0x0001E04C
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXRETRANSFASTHI_TCPTXRETRANSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXRETRANSFASTLO 0x0001E048
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXRETRANSFASTLO_TCPTXRETRANSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTHI 0x0001E054
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSFASTHI_TCPTXTOUTSFASTHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSFASTLO 0x0001E050
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSFASTLO_TCPTXTOUTSFASTLO_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSHI 0x0001E05C
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_MASK (0xFFFFFF << I40E_GLPES_TCPTXTOUTSHI_TCPTXTOUTSHI_SHIFT)
-#define I40E_GLPES_TCPTXTOUTSLO 0x0001E058
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT 0
-#define I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_MASK (0xFFFFFFFF << I40E_GLPES_TCPTXTOUTSLO_TCPTXTOUTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXDISCARD(_i) (0x00018600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXDISCARD_IP4RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSHI(_i) (0x00018804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXFRAGSHI_IP4RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXFRAGSLO(_i) (0x00018800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXFRAGSLO_IP4RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSHI(_i) (0x00018A04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCOCTSHI_IP4RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCOCTSLO(_i) (0x00018A00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCOCTSLO_IP4RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSHI(_i) (0x00018C04 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXMCPKTSHI_IP4RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXMCPKTSLO(_i) (0x00018C00 + ((_i) * 4))
-#define I40E_GLPES_VFIP4RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXMCPKTSLO_IP4RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSHI(_i) (0x00018204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXOCTSHI_IP4RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXOCTSLO(_i) (0x00018200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXOCTSLO_IP4RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSHI(_i) (0x00018404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4RXPKTSHI_IP4RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4RXPKTSLO(_i) (0x00018400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXPKTSLO_IP4RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4RXTRUNC(_i) (0x00018700 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4RXTRUNC_IP4RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSHI(_i) (0x00019E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXFRAGSHI_IP4TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXFRAGSLO(_i) (0x00019E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXFRAGSLO_IP4TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSHI(_i) (0x0001A004 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCOCTSHI_IP4TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCOCTSLO(_i) (0x0001A000 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCOCTSLO_IP4TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSHI(_i) (0x0001A204 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXMCPKTSHI_IP4TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXMCPKTSLO(_i) (0x0001A200 + ((_i) * 4))
-#define I40E_GLPES_VFIP4TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXMCPKTSLO_IP4TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXNOROUTE(_i) (0x0001AE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP4TXNOROUTE_IP4TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSHI(_i) (0x00019A04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXOCTSHI_IP4TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXOCTSLO(_i) (0x00019A00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXOCTSLO_IP4TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSHI(_i) (0x00019C04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP4TXPKTSHI_IP4TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP4TXPKTSLO(_i) (0x00019C00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP4TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP4TXPKTSLO_IP4TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXDISCARD(_i) (0x00019200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXDISCARD_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT 0
-#define I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXDISCARD_IP6RXDISCARD_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSHI(_i) (0x00019404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXFRAGSHI_IP6RXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXFRAGSLO(_i) (0x00019400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXFRAGSLO_IP6RXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSHI(_i) (0x00019604 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCOCTSHI_IP6RXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCOCTSLO(_i) (0x00019600 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCOCTSLO_IP6RXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSHI(_i) (0x00019804 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXMCPKTSHI_IP6RXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXMCPKTSLO(_i) (0x00019800 + ((_i) * 4))
-#define I40E_GLPES_VFIP6RXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXMCPKTSLO_IP6RXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSHI(_i) (0x00018E04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXOCTSHI_IP6RXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXOCTSLO(_i) (0x00018E00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXOCTSLO_IP6RXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSHI(_i) (0x00019004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6RXPKTSHI_IP6RXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6RXPKTSLO(_i) (0x00019000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXPKTSLO_IP6RXPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6RXTRUNC(_i) (0x00019300 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6RXTRUNC_MAX_INDEX 31
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT 0
-#define I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6RXTRUNC_IP6RXTRUNC_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSHI(_i) (0x0001A804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXFRAGSHI_IP6TXFRAGSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXFRAGSLO(_i) (0x0001A800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXFRAGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXFRAGSLO_IP6TXFRAGSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSHI(_i) (0x0001AA04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCOCTSHI_IP6TXMCOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCOCTSLO(_i) (0x0001AA00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCOCTSLO_IP6TXMCOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSHI(_i) (0x0001AC04 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXMCPKTSHI_IP6TXMCPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXMCPKTSLO(_i) (0x0001AC00 + ((_i) * 4))
-#define I40E_GLPES_VFIP6TXMCPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXMCPKTSLO_IP6TXMCPKTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXNOROUTE(_i) (0x0001AF00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXNOROUTE_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT 0
-#define I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_MASK (0xFFFFFF << I40E_GLPES_VFIP6TXNOROUTE_IP6TXNOROUTE_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSHI(_i) (0x0001A404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXOCTSHI_IP6TXOCTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXOCTSLO(_i) (0x0001A400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXOCTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXOCTSLO_IP6TXOCTSLO_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSHI(_i) (0x0001A604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFIP6TXPKTSHI_IP6TXPKTSHI_SHIFT)
-#define I40E_GLPES_VFIP6TXPKTSLO(_i) (0x0001A600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFIP6TXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFIP6TXPKTSLO_IP6TXPKTSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSHI(_i) (0x0001BE04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXRDSLO(_i) (0x0001BE00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSHI(_i) (0x0001C004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXSNDSLO(_i) (0x0001C000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSHI(_i) (0x0001BC04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMARXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMARXWRSLO(_i) (0x0001BC00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMARXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMARXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSHI(_i) (0x0001C404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXRDSHI_RDMARXRDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXRDSLO(_i) (0x0001C400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXRDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXRDSLO_RDMARXRDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSHI(_i) (0x0001C604 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXSNDSHI_RDMARXSNDSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXSNDSLO(_i) (0x0001C600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXSNDSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXSNDSLO_RDMARXSNDSLO_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSHI(_i) (0x0001C204 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_MASK (0xFFFF << I40E_GLPES_VFRDMATXWRSHI_RDMARXWRSHI_SHIFT)
-#define I40E_GLPES_VFRDMATXWRSLO(_i) (0x0001C200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMATXWRSLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT 0
-#define I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMATXWRSLO_RDMARXWRSLO_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDHI(_i) (0x0001C804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDHI_RDMAVBNDHI_SHIFT)
-#define I40E_GLPES_VFRDMAVBNDLO(_i) (0x0001C800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVBNDLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVBNDLO_RDMAVBNDLO_SHIFT)
-#define I40E_GLPES_VFRDMAVINVHI(_i) (0x0001CA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVHI_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVHI_RDMAVINVHI_SHIFT)
-#define I40E_GLPES_VFRDMAVINVLO(_i) (0x0001CA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRDMAVINVLO_MAX_INDEX 31
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT 0
-#define I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_MASK (0xFFFFFFFF << I40E_GLPES_VFRDMAVINVLO_RDMAVINVLO_SHIFT)
-#define I40E_GLPES_VFRXVLANERR(_i) (0x00018000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFRXVLANERR_MAX_INDEX 31
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT 0
-#define I40E_GLPES_VFRXVLANERR_RXVLANERR_MASK (0xFFFFFF << I40E_GLPES_VFRXVLANERR_RXVLANERR_SHIFT)
-#define I40E_GLPES_VFTCPRTXSEG(_i) (0x0001B600 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRTXSEG_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT 0
-#define I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRTXSEG_TCPRTXSEG_SHIFT)
-#define I40E_GLPES_VFTCPRXOPTERR(_i) (0x0001B200 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXOPTERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXOPTERR_TCPRXOPTERR_SHIFT)
-#define I40E_GLPES_VFTCPRXPROTOERR(_i) (0x0001B300 + ((_i) * 4))
-#define I40E_GLPES_VFTCPRXPROTOERR_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT 0
-#define I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_MASK (0xFFFFFF << I40E_GLPES_VFTCPRXPROTOERR_TCPRXPROTOERR_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSHI(_i) (0x0001B004 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_MASK (0xFFFF << I40E_GLPES_VFTCPRXSEGSHI_TCPRXSEGSHI_SHIFT)
-#define I40E_GLPES_VFTCPRXSEGSLO(_i) (0x0001B000 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPRXSEGSLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT 0
-#define I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPRXSEGSLO_TCPRXSEGSLO_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGHI(_i) (0x0001B404 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGHI_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_MASK (0xFFFF << I40E_GLPES_VFTCPTXSEGHI_TCPTXSEGHI_SHIFT)
-#define I40E_GLPES_VFTCPTXSEGLO(_i) (0x0001B400 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFTCPTXSEGLO_MAX_INDEX 31
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT 0
-#define I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_MASK (0xFFFFFFFF << I40E_GLPES_VFTCPTXSEGLO_TCPTXSEGLO_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSHI(_i) (0x0001B804 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPRXPKTSHI_UDPRXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPRXPKTSLO(_i) (0x0001B800 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPRXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPRXPKTSLO_UDPRXPKTSLO_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSHI(_i) (0x0001BA04 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSHI_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_MASK (0xFFFF << I40E_GLPES_VFUDPTXPKTSHI_UDPTXPKTSHI_SHIFT)
-#define I40E_GLPES_VFUDPTXPKTSLO(_i) (0x0001BA00 + ((_i) * 4)) /* _i=0...31 */
-#define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
-#define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_PRTPM_EEE_STAT 0x001E4320
+#define I40E_PFPCI_VMPEND_PENDING_MASK I40E_MASK(0x1, I40E_PFPCI_VMPEND_PENDING_SHIFT)
+#define I40E_PRTPM_EEE_STAT 0x001E4320 /* Reset: GLOBR */
#define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
-#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
+#define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30
-#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT)
#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31
-#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK (0x1 << I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
-#define I40E_PRTPM_EEEC 0x001E4380
+#define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT)
+#define I40E_PRTPM_EEEC 0x001E4380 /* Reset: GLOBR */
#define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16
-#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK (0x3F << I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
+#define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT)
#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24
-#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK (0x3 << I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
+#define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK I40E_MASK(0x3, I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT)
#define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26
-#define I40E_PRTPM_EEEC_TEEE_DLY_MASK (0x3F << I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
-#define I40E_PRTPM_EEEFWD 0x001E4400
+#define I40E_PRTPM_EEEC_TEEE_DLY_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TEEE_DLY_SHIFT)
+#define I40E_PRTPM_EEEFWD 0x001E4400 /* Reset: GLOBR */
#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31
-#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK (0x1 << I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
-#define I40E_PRTPM_EEER 0x001E4360
+#define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK I40E_MASK(0x1, I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT)
+#define I40E_PRTPM_EEER 0x001E4360 /* Reset: GLOBR */
#define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0
-#define I40E_PRTPM_EEER_TW_SYSTEM_MASK (0xFFFF << I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
+#define I40E_PRTPM_EEER_TW_SYSTEM_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEER_TW_SYSTEM_SHIFT)
#define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16
-#define I40E_PRTPM_EEER_TX_LPI_EN_MASK (0x1 << I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
-#define I40E_PRTPM_EEETXC 0x001E43E0
+#define I40E_PRTPM_EEER_TX_LPI_EN_MASK I40E_MASK(0x1, I40E_PRTPM_EEER_TX_LPI_EN_SHIFT)
+#define I40E_PRTPM_EEETXC 0x001E43E0 /* Reset: GLOBR */
#define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0
-#define I40E_PRTPM_EEETXC_TW_PHY_MASK (0xFFFF << I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
-#define I40E_PRTPM_GC 0x000B8140
+#define I40E_PRTPM_EEETXC_TW_PHY_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEETXC_TW_PHY_SHIFT)
+#define I40E_PRTPM_GC 0x000B8140 /* Reset: POR */
#define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0
-#define I40E_PRTPM_GC_EMP_LINK_ON_MASK (0x1 << I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
+#define I40E_PRTPM_GC_EMP_LINK_ON_MASK I40E_MASK(0x1, I40E_PRTPM_GC_EMP_LINK_ON_SHIFT)
#define I40E_PRTPM_GC_MNG_VETO_SHIFT 1
-#define I40E_PRTPM_GC_MNG_VETO_MASK (0x1 << I40E_PRTPM_GC_MNG_VETO_SHIFT)
+#define I40E_PRTPM_GC_MNG_VETO_MASK I40E_MASK(0x1, I40E_PRTPM_GC_MNG_VETO_SHIFT)
#define I40E_PRTPM_GC_RATD_SHIFT 2
-#define I40E_PRTPM_GC_RATD_MASK (0x1 << I40E_PRTPM_GC_RATD_SHIFT)
+#define I40E_PRTPM_GC_RATD_MASK I40E_MASK(0x1, I40E_PRTPM_GC_RATD_SHIFT)
#define I40E_PRTPM_GC_LCDMP_SHIFT 3
-#define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
+#define I40E_PRTPM_GC_LCDMP_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LCDMP_SHIFT)
#define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
-#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
-#define I40E_PRTPM_RLPIC 0x001E43A0
+#define I40E_PRTPM_GC_LPLU_ASSERTED_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
+#define I40E_PRTPM_RLPIC 0x001E43A0 /* Reset: GLOBR */
#define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
-#define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
-#define I40E_PRTPM_TLPIC 0x001E43C0
+#define I40E_PRTPM_RLPIC_ERLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
+#define I40E_PRTPM_TLPIC 0x001E43C0 /* Reset: GLOBR */
#define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0
-#define I40E_PRTPM_TLPIC_ETLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
-#define I40E_GLRPB_DPSS 0x000AC828
+#define I40E_PRTPM_TLPIC_ETLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_TLPIC_ETLPIC_SHIFT)
+#define I40E_GLRPB_DPSS 0x000AC828 /* Reset: CORER */
#define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0
-#define I40E_GLRPB_DPSS_DPS_TCN_MASK (0xFFFFF << I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
-#define I40E_GLRPB_GHW 0x000AC830
+#define I40E_GLRPB_DPSS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_DPSS_DPS_TCN_SHIFT)
+#define I40E_GLRPB_GHW 0x000AC830 /* Reset: CORER */
#define I40E_GLRPB_GHW_GHW_SHIFT 0
-#define I40E_GLRPB_GHW_GHW_MASK (0xFFFFF << I40E_GLRPB_GHW_GHW_SHIFT)
-#define I40E_GLRPB_GLW 0x000AC834
+#define I40E_GLRPB_GHW_GHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GHW_GHW_SHIFT)
+#define I40E_GLRPB_GLW 0x000AC834 /* Reset: CORER */
#define I40E_GLRPB_GLW_GLW_SHIFT 0
-#define I40E_GLRPB_GLW_GLW_MASK (0xFFFFF << I40E_GLRPB_GLW_GLW_SHIFT)
-#define I40E_GLRPB_PHW 0x000AC844
+#define I40E_GLRPB_GLW_GLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GLW_GLW_SHIFT)
+#define I40E_GLRPB_PHW 0x000AC844 /* Reset: CORER */
#define I40E_GLRPB_PHW_PHW_SHIFT 0
-#define I40E_GLRPB_PHW_PHW_MASK (0xFFFFF << I40E_GLRPB_PHW_PHW_SHIFT)
-#define I40E_GLRPB_PLW 0x000AC848
+#define I40E_GLRPB_PHW_PHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PHW_PHW_SHIFT)
+#define I40E_GLRPB_PLW 0x000AC848 /* Reset: CORER */
#define I40E_GLRPB_PLW_PLW_SHIFT 0
-#define I40E_GLRPB_PLW_PLW_MASK (0xFFFFF << I40E_GLRPB_PLW_PLW_SHIFT)
-#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_GLRPB_PLW_PLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PLW_PLW_SHIFT)
+#define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DHW_MAX_INDEX 7
#define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0
-#define I40E_PRTRPB_DHW_DHW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
-#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DHW_DHW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DHW_DHW_TCN_SHIFT)
+#define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DLW_MAX_INDEX 7
#define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0
-#define I40E_PRTRPB_DLW_DLW_TCN_MASK (0xFFFFF << I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
-#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DLW_DLW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DLW_DLW_TCN_SHIFT)
+#define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_DPS_MAX_INDEX 7
#define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0
-#define I40E_PRTRPB_DPS_DPS_TCN_MASK (0xFFFFF << I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
-#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_DPS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DPS_DPS_TCN_SHIFT)
+#define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_SHT_MAX_INDEX 7
#define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0
-#define I40E_PRTRPB_SHT_SHT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
-#define I40E_PRTRPB_SHW 0x000AC580
+#define I40E_PRTRPB_SHT_SHT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHT_SHT_TCN_SHIFT)
+#define I40E_PRTRPB_SHW 0x000AC580 /* Reset: CORER */
#define I40E_PRTRPB_SHW_SHW_SHIFT 0
-#define I40E_PRTRPB_SHW_SHW_MASK (0xFFFFF << I40E_PRTRPB_SHW_SHW_SHIFT)
-#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */
+#define I40E_PRTRPB_SHW_SHW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHW_SHW_SHIFT)
+#define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_PRTRPB_SLT_MAX_INDEX 7
#define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0
-#define I40E_PRTRPB_SLT_SLT_TCN_MASK (0xFFFFF << I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
-#define I40E_PRTRPB_SLW 0x000AC6A0
+#define I40E_PRTRPB_SLT_SLT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLT_SLT_TCN_SHIFT)
+#define I40E_PRTRPB_SLW 0x000AC6A0 /* Reset: CORER */
#define I40E_PRTRPB_SLW_SLW_SHIFT 0
-#define I40E_PRTRPB_SLW_SLW_MASK (0xFFFFF << I40E_PRTRPB_SLW_SLW_SHIFT)
-#define I40E_PRTRPB_SPS 0x000AC7C0
+#define I40E_PRTRPB_SLW_SLW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLW_SLW_SHIFT)
+#define I40E_PRTRPB_SPS 0x000AC7C0 /* Reset: CORER */
#define I40E_PRTRPB_SPS_SPS_SHIFT 0
-#define I40E_PRTRPB_SPS_SPS_MASK (0xFFFFF << I40E_PRTRPB_SPS_SPS_SHIFT)
-#define I40E_GLQF_APBVT(_i) (0x00260000 + ((_i) * 4)) /* _i=0...2047 */
-#define I40E_GLQF_APBVT_MAX_INDEX 2047
-#define I40E_GLQF_APBVT_APBVT_SHIFT 0
-#define I40E_GLQF_APBVT_APBVT_MASK (0xFFFFFFFF << I40E_GLQF_APBVT_APBVT_SHIFT)
-#define I40E_GLQF_CTL 0x00269BA4
+#define I40E_PRTRPB_SPS_SPS_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SPS_SPS_SHIFT)
+#define I40E_GLQF_CTL 0x00269BA4 /* Reset: CORER */
#define I40E_GLQF_CTL_HTOEP_SHIFT 1
-#define I40E_GLQF_CTL_HTOEP_MASK (0x1 << I40E_GLQF_CTL_HTOEP_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_SHIFT)
#define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2
-#define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
+#define I40E_GLQF_CTL_HTOEP_FCOE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
#define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
-#define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_PCNT_ALLOC_MASK I40E_MASK(0x7, I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT 6
+#define I40E_GLQF_CTL_FD_AUTO_PCTYPE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT)
#define I40E_GLQF_CTL_RSVD_SHIFT 7
-#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
+#define I40E_GLQF_CTL_RSVD_MASK I40E_MASK(0x1, I40E_GLQF_CTL_RSVD_SHIFT)
#define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
-#define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXPEBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
#define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
-#define I40E_GLQF_CTL_MAXFCBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFCBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFCBLEN_SHIFT)
#define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14
-#define I40E_GLQF_CTL_MAXFDBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
+#define I40E_GLQF_CTL_MAXFDBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFDBLEN_SHIFT)
#define I40E_GLQF_CTL_FDBEST_SHIFT 17
-#define I40E_GLQF_CTL_FDBEST_MASK (0xFF << I40E_GLQF_CTL_FDBEST_SHIFT)
+#define I40E_GLQF_CTL_FDBEST_MASK I40E_MASK(0xFF, I40E_GLQF_CTL_FDBEST_SHIFT)
#define I40E_GLQF_CTL_PROGPRIO_SHIFT 25
-#define I40E_GLQF_CTL_PROGPRIO_MASK (0x1 << I40E_GLQF_CTL_PROGPRIO_SHIFT)
+#define I40E_GLQF_CTL_PROGPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_PROGPRIO_SHIFT)
#define I40E_GLQF_CTL_INVALPRIO_SHIFT 26
-#define I40E_GLQF_CTL_INVALPRIO_MASK (0x1 << I40E_GLQF_CTL_INVALPRIO_SHIFT)
+#define I40E_GLQF_CTL_INVALPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_INVALPRIO_SHIFT)
#define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27
-#define I40E_GLQF_CTL_IGNORE_IP_MASK (0x1 << I40E_GLQF_CTL_IGNORE_IP_SHIFT)
-#define I40E_GLQF_FDCNT_0 0x00269BAC
+#define I40E_GLQF_CTL_IGNORE_IP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_IGNORE_IP_SHIFT)
+#define I40E_GLQF_FDCNT_0 0x00269BAC /* Reset: CORER */
#define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0
-#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
+#define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT)
#define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13
-#define I40E_GLQF_FDCNT_0_BESTCNT_MASK (0x1FFF << I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
-#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */
+#define I40E_GLQF_FDCNT_0_BESTCNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_BESTCNT_SHIFT)
+#define I40E_GLQF_HKEY(_i) (0x00270140 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
+#define I40E_GLQF_HKEY_MAX_INDEX 12
+#define I40E_GLQF_HKEY_KEY_0_SHIFT 0
+#define I40E_GLQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_0_SHIFT)
+#define I40E_GLQF_HKEY_KEY_1_SHIFT 8
+#define I40E_GLQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_1_SHIFT)
+#define I40E_GLQF_HKEY_KEY_2_SHIFT 16
+#define I40E_GLQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_2_SHIFT)
+#define I40E_GLQF_HKEY_KEY_3_SHIFT 24
+#define I40E_GLQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_3_SHIFT)
+#define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */ /* Reset: CORER */
#define I40E_GLQF_HSYM_MAX_INDEX 63
#define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0
-#define I40E_GLQF_HSYM_SYMH_ENA_MASK (0x1 << I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
-#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */
+#define I40E_GLQF_HSYM_SYMH_ENA_MASK I40E_MASK(0x1, I40E_GLQF_HSYM_SYMH_ENA_SHIFT)
+#define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */ /* Reset: CORER */
#define I40E_GLQF_PCNT_MAX_INDEX 511
#define I40E_GLQF_PCNT_PCNT_SHIFT 0
-#define I40E_GLQF_PCNT_PCNT_MASK (0xFFFFFFFF << I40E_GLQF_PCNT_PCNT_SHIFT)
-#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */
+#define I40E_GLQF_PCNT_PCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLQF_PCNT_PCNT_SHIFT)
+#define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */ /* Reset: CORER */
#define I40E_GLQF_SWAP_MAX_INDEX 1
#define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0
-#define I40E_GLQF_SWAP_OFF0_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC0_SHIFT)
#define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6
-#define I40E_GLQF_SWAP_OFF0_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF0_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC1_SHIFT)
#define I40E_GLQF_SWAP_FLEN0_SHIFT 12
-#define I40E_GLQF_SWAP_FLEN0_MASK (0xF << I40E_GLQF_SWAP_FLEN0_SHIFT)
+#define I40E_GLQF_SWAP_FLEN0_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN0_SHIFT)
#define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16
-#define I40E_GLQF_SWAP_OFF1_SRC0_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC0_SHIFT)
#define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22
-#define I40E_GLQF_SWAP_OFF1_SRC1_MASK (0x3F << I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
+#define I40E_GLQF_SWAP_OFF1_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC1_SHIFT)
#define I40E_GLQF_SWAP_FLEN1_SHIFT 28
-#define I40E_GLQF_SWAP_FLEN1_MASK (0xF << I40E_GLQF_SWAP_FLEN1_SHIFT)
-#define I40E_PFQF_CTL_0 0x001C0AC0
+#define I40E_GLQF_SWAP_FLEN1_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN1_SHIFT)
+#define I40E_PFQF_CTL_0 0x001C0AC0 /* Reset: CORER */
#define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0
-#define I40E_PFQF_CTL_0_PEHSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEHSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5
-#define I40E_PFQF_CTL_0_PEDSIZE_MASK (0x1F << I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PEDSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEDSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10
-#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14
-#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_PFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT)
#define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16
-#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK (0x1 << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT)
#define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17
-#define I40E_PFQF_CTL_0_FD_ENA_MASK (0x1 << I40E_PFQF_CTL_0_FD_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_FD_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_FD_ENA_SHIFT)
#define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18
-#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK (0x1 << I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_ETYPE_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT)
#define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19
-#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK (0x1 << I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
+#define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT)
#define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20
-#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK (0xF << I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
+#define I40E_PFQF_CTL_0_VFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT)
#define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24
-#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK (0x3 << I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
-#define I40E_PFQF_CTL_1 0x00245D80
+#define I40E_PFQF_CTL_0_VFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT)
+#define I40E_PFQF_CTL_1 0x00245D80 /* Reset: CORER */
#define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0
-#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK (0x1 << I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
-#define I40E_PFQF_FDALLOC 0x00246280
+#define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT)
+#define I40E_PFQF_FDALLOC 0x00246280 /* Reset: CORER */
#define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0
-#define I40E_PFQF_FDALLOC_FDALLOC_MASK (0xFF << I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
+#define I40E_PFQF_FDALLOC_FDALLOC_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDALLOC_SHIFT)
#define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8
-#define I40E_PFQF_FDALLOC_FDBEST_MASK (0xFF << I40E_PFQF_FDALLOC_FDBEST_SHIFT)
-#define I40E_PFQF_FDSTAT 0x00246380
+#define I40E_PFQF_FDALLOC_FDBEST_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDBEST_SHIFT)
+#define I40E_PFQF_FDSTAT 0x00246380 /* Reset: CORER */
#define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0
-#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
+#define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT)
#define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16
-#define I40E_PFQF_FDSTAT_BEST_CNT_MASK (0x1FFF << I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
-#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */
+#define I40E_PFQF_FDSTAT_BEST_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_BEST_CNT_SHIFT)
+#define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */ /* Reset: CORER */
#define I40E_PFQF_HENA_MAX_INDEX 1
#define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_PFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */
+#define I40E_PFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */ /* Reset: CORER */
#define I40E_PFQF_HKEY_MAX_INDEX 12
#define I40E_PFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_PFQF_HKEY_KEY_0_MASK (0xFF << I40E_PFQF_HKEY_KEY_0_SHIFT)
+#define I40E_PFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_0_SHIFT)
#define I40E_PFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_PFQF_HKEY_KEY_1_MASK (0xFF << I40E_PFQF_HKEY_KEY_1_SHIFT)
+#define I40E_PFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_1_SHIFT)
#define I40E_PFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_PFQF_HKEY_KEY_2_MASK (0xFF << I40E_PFQF_HKEY_KEY_2_SHIFT)
+#define I40E_PFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_2_SHIFT)
#define I40E_PFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_PFQF_HKEY_KEY_3_MASK (0xFF << I40E_PFQF_HKEY_KEY_3_SHIFT)
-#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */
+#define I40E_PFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_3_SHIFT)
+#define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_PFQF_HLUT_MAX_INDEX 127
#define I40E_PFQF_HLUT_LUT0_SHIFT 0
-#define I40E_PFQF_HLUT_LUT0_MASK (0x3F << I40E_PFQF_HLUT_LUT0_SHIFT)
+#define I40E_PFQF_HLUT_LUT0_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT0_SHIFT)
#define I40E_PFQF_HLUT_LUT1_SHIFT 8
-#define I40E_PFQF_HLUT_LUT1_MASK (0x3F << I40E_PFQF_HLUT_LUT1_SHIFT)
+#define I40E_PFQF_HLUT_LUT1_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT1_SHIFT)
#define I40E_PFQF_HLUT_LUT2_SHIFT 16
-#define I40E_PFQF_HLUT_LUT2_MASK (0x3F << I40E_PFQF_HLUT_LUT2_SHIFT)
+#define I40E_PFQF_HLUT_LUT2_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT2_SHIFT)
#define I40E_PFQF_HLUT_LUT3_SHIFT 24
-#define I40E_PFQF_HLUT_LUT3_MASK (0x3F << I40E_PFQF_HLUT_LUT3_SHIFT)
-#define I40E_PFQF_HREGION(_i) (0x00245400 + ((_i) * 128)) /* _i=0...7 */
-#define I40E_PFQF_HREGION_MAX_INDEX 7
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
-#define I40E_PFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_PFQF_HREGION_REGION_0_MASK (0x7 << I40E_PFQF_HREGION_REGION_0_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
-#define I40E_PFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_PFQF_HREGION_REGION_1_MASK (0x7 << I40E_PFQF_HREGION_REGION_1_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
-#define I40E_PFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_PFQF_HREGION_REGION_2_MASK (0x7 << I40E_PFQF_HREGION_REGION_2_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
-#define I40E_PFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_PFQF_HREGION_REGION_3_MASK (0x7 << I40E_PFQF_HREGION_REGION_3_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
-#define I40E_PFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_PFQF_HREGION_REGION_4_MASK (0x7 << I40E_PFQF_HREGION_REGION_4_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
-#define I40E_PFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_PFQF_HREGION_REGION_5_MASK (0x7 << I40E_PFQF_HREGION_REGION_5_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
-#define I40E_PFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_PFQF_HREGION_REGION_6_MASK (0x7 << I40E_PFQF_HREGION_REGION_6_SHIFT)
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_PFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
-#define I40E_PFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_PFQF_HREGION_REGION_7_MASK (0x7 << I40E_PFQF_HREGION_REGION_7_SHIFT)
-#define I40E_PRTQF_CTL_0 0x00256E60
+#define I40E_PFQF_HLUT_LUT3_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT3_SHIFT)
+#define I40E_PRTQF_CTL_0 0x00256E60 /* Reset: CORER */
#define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0
-#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK (0x1 << I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
-#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */
+#define I40E_PRTQF_CTL_0_HSYM_ENA_MASK I40E_MASK(0x1, I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT)
+#define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */ /* Reset: CORER */
#define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63
#define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0
-#define I40E_PRTQF_FD_FLXINSET_INSET_MASK (0xFF << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
-#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */
+#define I40E_PRTQF_FD_FLXINSET_INSET_MASK I40E_MASK(0xFF, I40E_PRTQF_FD_FLXINSET_INSET_SHIFT)
+#define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */ /* Reset: CORER */
#define I40E_PRTQF_FD_MSK_MAX_INDEX 63
#define I40E_PRTQF_FD_MSK_MASK_SHIFT 0
-#define I40E_PRTQF_FD_MSK_MASK_MASK (0xFFFF << I40E_PRTQF_FD_MSK_MASK_SHIFT)
+#define I40E_PRTQF_FD_MSK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRTQF_FD_MSK_MASK_SHIFT)
#define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16
-#define I40E_PRTQF_FD_MSK_OFFSET_MASK (0x3F << I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
-#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
+#define I40E_PRTQF_FD_MSK_OFFSET_MASK I40E_MASK(0x3F, I40E_PRTQF_FD_MSK_OFFSET_SHIFT)
+#define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ /* Reset: CORER */
#define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
-#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
-#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
#define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
-#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
-#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK I40E_MASK(0x3F, I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
+#define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...1, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HENA1_MAX_INDEX 1
#define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA1_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */
+#define I40E_VFQF_HENA1_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA1_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HKEY1_MAX_INDEX 12
#define I40E_VFQF_HKEY1_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY1_KEY_0_MASK (0xFF << I40E_VFQF_HKEY1_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_0_SHIFT)
#define I40E_VFQF_HKEY1_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY1_KEY_1_MASK (0xFF << I40E_VFQF_HKEY1_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_1_SHIFT)
#define I40E_VFQF_HKEY1_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY1_KEY_2_MASK (0xFF << I40E_VFQF_HKEY1_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY1_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_2_SHIFT)
#define I40E_VFQF_HKEY1_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY1_KEY_3_MASK (0xFF << I40E_VFQF_HKEY1_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */
+#define I40E_VFQF_HKEY1_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HLUT1_MAX_INDEX 15
#define I40E_VFQF_HLUT1_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT1_LUT0_MASK (0xF << I40E_VFQF_HLUT1_LUT0_SHIFT)
+#define I40E_VFQF_HLUT1_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT0_SHIFT)
#define I40E_VFQF_HLUT1_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT1_LUT1_MASK (0xF << I40E_VFQF_HLUT1_LUT1_SHIFT)
+#define I40E_VFQF_HLUT1_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT1_SHIFT)
#define I40E_VFQF_HLUT1_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT1_LUT2_MASK (0xF << I40E_VFQF_HLUT1_LUT2_SHIFT)
+#define I40E_VFQF_HLUT1_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT2_SHIFT)
#define I40E_VFQF_HLUT1_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT1_LUT3_MASK (0xF << I40E_VFQF_HLUT1_LUT3_SHIFT)
-#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4))
+#define I40E_VFQF_HLUT1_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT3_SHIFT)
+#define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...7, _VF=0...127 */ /* Reset: CORER */
#define I40E_VFQF_HREGION1_MAX_INDEX 7
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT)
#define I40E_VFQF_HREGION1_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION1_REGION_0_MASK (0x7 << I40E_VFQF_HREGION1_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_0_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT)
#define I40E_VFQF_HREGION1_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION1_REGION_1_MASK (0x7 << I40E_VFQF_HREGION1_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_1_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT)
#define I40E_VFQF_HREGION1_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION1_REGION_2_MASK (0x7 << I40E_VFQF_HREGION1_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_2_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT)
#define I40E_VFQF_HREGION1_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION1_REGION_3_MASK (0x7 << I40E_VFQF_HREGION1_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_3_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT)
#define I40E_VFQF_HREGION1_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION1_REGION_4_MASK (0x7 << I40E_VFQF_HREGION1_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_4_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT)
#define I40E_VFQF_HREGION1_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION1_REGION_5_MASK (0x7 << I40E_VFQF_HREGION1_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_5_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT)
#define I40E_VFQF_HREGION1_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION1_REGION_6_MASK (0x7 << I40E_VFQF_HREGION1_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION1_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_6_SHIFT)
#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT)
#define I40E_VFQF_HREGION1_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION1_REGION_7_MASK (0x7 << I40E_VFQF_HREGION1_REGION_7_SHIFT)
-#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VFQF_HREGION1_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_7_SHIFT)
+#define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */
#define I40E_VPQF_CTL_MAX_INDEX 127
#define I40E_VPQF_CTL_PEHSIZE_SHIFT 0
-#define I40E_VPQF_CTL_PEHSIZE_MASK (0x1F << I40E_VPQF_CTL_PEHSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEHSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEHSIZE_SHIFT)
#define I40E_VPQF_CTL_PEDSIZE_SHIFT 5
-#define I40E_VPQF_CTL_PEDSIZE_MASK (0x1F << I40E_VPQF_CTL_PEDSIZE_SHIFT)
+#define I40E_VPQF_CTL_PEDSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEDSIZE_SHIFT)
#define I40E_VPQF_CTL_FCHSIZE_SHIFT 10
-#define I40E_VPQF_CTL_FCHSIZE_MASK (0xF << I40E_VPQF_CTL_FCHSIZE_SHIFT)
+#define I40E_VPQF_CTL_FCHSIZE_MASK I40E_MASK(0xF, I40E_VPQF_CTL_FCHSIZE_SHIFT)
#define I40E_VPQF_CTL_FCDSIZE_SHIFT 14
-#define I40E_VPQF_CTL_FCDSIZE_MASK (0x3 << I40E_VPQF_CTL_FCDSIZE_SHIFT)
-#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */
+#define I40E_VPQF_CTL_FCDSIZE_MASK I40E_MASK(0x3, I40E_VPQF_CTL_FCDSIZE_SHIFT)
+#define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */
#define I40E_VSIQF_CTL_MAX_INDEX 383
#define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0
-#define I40E_VSIQF_CTL_FCOE_ENA_MASK (0x1 << I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
+#define I40E_VSIQF_CTL_FCOE_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_FCOE_ENA_SHIFT)
#define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1
-#define I40E_VSIQF_CTL_PETCP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PETCP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PETCP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2
-#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3
-#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEMUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4
-#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
+#define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT)
#define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
-#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
-#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
+#define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
+#define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...3, _VSI=0...383 */ /* Reset: PFR */
#define I40E_VSIQF_TCREGION_MAX_INDEX 3
#define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
-#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
#define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
-#define I40E_VSIQF_TCREGION_TC_SIZE_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_SIZE_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE_SHIFT)
#define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16
-#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
+#define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT)
#define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25
-#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK (0x7 << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
-#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_VSIQF_TCREGION_TC_SIZE2_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT)
+#define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOECRC_MAX_INDEX 143
#define I40E_GL_FCOECRC_FCOECRC_SHIFT 0
-#define I40E_GL_FCOECRC_FCOECRC_MASK (0xFFFFFFFF << I40E_GL_FCOECRC_FCOECRC_SHIFT)
-#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOECRC_FCOECRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOECRC_FCOECRC_SHIFT)
+#define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDDPC_MAX_INDEX 143
#define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
-#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
-/* _i=0...143 */
-#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDDPC_FCOEDDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
+#define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIFEC_MAX_INDEX 143
#define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFRC(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIFRC_MAX_INDEX 143
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT 0
-#define I40E_GL_FCOEDIFRC_FCOEDIFRC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFRC_FCOEDIFRC_SHIFT)
-#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT)
+#define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIFTCL_MAX_INDEX 143
#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0
-#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
-#define I40E_GL_FCOEDIXAC(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDIXAC_MAX_INDEX 143
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT 0
-#define I40E_GL_FCOEDIXAC_FCOEDIXAC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXAC_FCOEDIXAC_SHIFT)
-#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT)
+#define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIXEC_MAX_INDEX 143
#define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0
-#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
-#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT)
+#define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDIXVC_MAX_INDEX 143
#define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0
-#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK (0xFFFFFFFF << I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
-#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT)
+#define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWRCH_MAX_INDEX 143
#define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0
-#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK (0xFFFF << I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
-#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT)
+#define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWRCL_MAX_INDEX 143
#define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0
-#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
-#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT)
+#define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWTCH_MAX_INDEX 143
#define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0
-#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK (0xFFFF << I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
-#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT)
+#define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEDWTCL_MAX_INDEX 143
#define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0
-#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK (0xFFFFFFFF << I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
-#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT)
+#define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOELAST_MAX_INDEX 143
#define I40E_GL_FCOELAST_FCOELAST_SHIFT 0
-#define I40E_GL_FCOELAST_FCOELAST_MASK (0xFFFFFFFF << I40E_GL_FCOELAST_FCOELAST_SHIFT)
-#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOELAST_FCOELAST_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOELAST_FCOELAST_SHIFT)
+#define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEPRC_MAX_INDEX 143
#define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0
-#define I40E_GL_FCOEPRC_FCOEPRC_MASK (0xFFFFFFFF << I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
-#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPRC_FCOEPRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPRC_FCOEPRC_SHIFT)
+#define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOEPTC_MAX_INDEX 143
#define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0
-#define I40E_GL_FCOEPTC_FCOEPTC_MASK (0xFFFFFFFF << I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
-#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */
+#define I40E_GL_FCOEPTC_FCOEPTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPTC_FCOEPTC_SHIFT)
+#define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
#define I40E_GL_FCOERPDC_MAX_INDEX 143
#define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0
-#define I40E_GL_FCOERPDC_FCOERPDC_MASK (0xFFFFFFFF << I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
-#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GL_FCOERPDC_FCOERPDC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT)
+#define I40E_GL_RXERR1_L(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR1_L_MAX_INDEX 143
+#define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0
+#define I40E_GL_RXERR1_L_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT)
+#define I40E_GL_RXERR2_L(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */
+#define I40E_GL_RXERR2_L_MAX_INDEX 143
+#define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0
+#define I40E_GL_RXERR2_L_FCOEDIXAC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT)
+#define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPRCH_MAX_INDEX 3
#define I40E_GLPRT_BPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPRCL_MAX_INDEX 3
#define I40E_GLPRT_BPRCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPRCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPRCL_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPRCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPRCL_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPTCH_MAX_INDEX 3
#define I40E_GLPRT_BPTCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_BPTCH_UPRCH_SHIFT)
-#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPTCH_UPRCH_SHIFT)
+#define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_BPTCL_MAX_INDEX 3
#define I40E_GLPRT_BPTCL_UPRCH_SHIFT 0
-#define I40E_GLPRT_BPTCL_UPRCH_MASK (0xFFFFFFFF << I40E_GLPRT_BPTCL_UPRCH_SHIFT)
-#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_BPTCL_UPRCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPTCL_UPRCH_SHIFT)
+#define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_CRCERRS_MAX_INDEX 3
#define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0
-#define I40E_GLPRT_CRCERRS_CRCERRS_MASK (0xFFFFFFFF << I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
-#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_CRCERRS_CRCERRS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_CRCERRS_CRCERRS_SHIFT)
+#define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GORCH_MAX_INDEX 3
#define I40E_GLPRT_GORCH_GORCH_SHIFT 0
-#define I40E_GLPRT_GORCH_GORCH_MASK (0xFFFF << I40E_GLPRT_GORCH_GORCH_SHIFT)
-#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GORCH_GORCH_SHIFT)
+#define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GORCL_MAX_INDEX 3
#define I40E_GLPRT_GORCL_GORCL_SHIFT 0
-#define I40E_GLPRT_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLPRT_GORCL_GORCL_SHIFT)
-#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GORCL_GORCL_SHIFT)
+#define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GOTCH_MAX_INDEX 3
#define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLPRT_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLPRT_GOTCH_GOTCH_SHIFT)
-#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GOTCH_GOTCH_SHIFT)
+#define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_GOTCL_MAX_INDEX 3
#define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLPRT_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLPRT_GOTCL_GOTCL_SHIFT)
-#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GOTCL_GOTCL_SHIFT)
+#define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_ILLERRC_MAX_INDEX 3
#define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0
-#define I40E_GLPRT_ILLERRC_ILLERRC_MASK (0xFFFFFFFF << I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
-#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ILLERRC_ILLERRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ILLERRC_ILLERRC_SHIFT)
+#define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LDPC_MAX_INDEX 3
#define I40E_GLPRT_LDPC_LDPC_SHIFT 0
-#define I40E_GLPRT_LDPC_LDPC_MASK (0xFFFFFFFF << I40E_GLPRT_LDPC_LDPC_SHIFT)
-#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LDPC_LDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LDPC_LDPC_SHIFT)
+#define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3
#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3
#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0
-#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
-#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT)
+#define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXONRXC_MAX_INDEX 3
#define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0
-#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
-#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT)
+#define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_LXONTXC_MAX_INDEX 3
#define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0
-#define I40E_GLPRT_LXONTXC_LXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
-#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_LXONTXC_LXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONTXC_LXONTXC_SHIFT)
+#define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MLFC_MAX_INDEX 3
#define I40E_GLPRT_MLFC_MLFC_SHIFT 0
-#define I40E_GLPRT_MLFC_MLFC_MASK (0xFFFFFFFF << I40E_GLPRT_MLFC_MLFC_SHIFT)
-#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MLFC_MLFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MLFC_MLFC_SHIFT)
+#define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPRCH_MAX_INDEX 3
#define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLPRT_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLPRT_MPRCH_MPRCH_SHIFT)
-#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPRCH_MPRCH_SHIFT)
+#define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPRCL_MAX_INDEX 3
#define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLPRT_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPRCL_MPRCL_SHIFT)
-#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPRCL_MPRCL_SHIFT)
+#define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPTCH_MAX_INDEX 3
#define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLPRT_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLPRT_MPTCH_MPTCH_SHIFT)
-#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPTCH_MPTCH_SHIFT)
+#define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MPTCL_MAX_INDEX 3
#define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLPRT_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLPRT_MPTCL_MPTCL_SHIFT)
-#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPTCL_MPTCL_SHIFT)
+#define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_MRFC_MAX_INDEX 3
#define I40E_GLPRT_MRFC_MRFC_SHIFT 0
-#define I40E_GLPRT_MRFC_MRFC_MASK (0xFFFFFFFF << I40E_GLPRT_MRFC_MRFC_SHIFT)
-#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_MRFC_MRFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MRFC_MRFC_SHIFT)
+#define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1023H_MAX_INDEX 3
#define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0
-#define I40E_GLPRT_PRC1023H_PRC1023H_MASK (0xFFFF << I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
-#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023H_PRC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1023H_PRC1023H_SHIFT)
+#define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1023L_MAX_INDEX 3
#define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0
-#define I40E_GLPRT_PRC1023L_PRC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
-#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1023L_PRC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1023L_PRC1023L_SHIFT)
+#define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC127H_MAX_INDEX 3
#define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0
-#define I40E_GLPRT_PRC127H_PRC127H_MASK (0xFFFF << I40E_GLPRT_PRC127H_PRC127H_SHIFT)
-#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127H_PRC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC127H_PRC127H_SHIFT)
+#define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC127L_MAX_INDEX 3
#define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0
-#define I40E_GLPRT_PRC127L_PRC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC127L_PRC127L_SHIFT)
-#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC127L_PRC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC127L_PRC127L_SHIFT)
+#define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1522H_MAX_INDEX 3
#define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC1522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC1522L_MAX_INDEX 3
#define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC1522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC1522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC255H_MAX_INDEX 3
#define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0
-#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK (0xFFFF << I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
-#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255H_PRTPRC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT)
+#define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC255L_MAX_INDEX 3
#define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0
-#define I40E_GLPRT_PRC255L_PRC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC255L_PRC255L_SHIFT)
-#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC255L_PRC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC255L_PRC255L_SHIFT)
+#define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC511H_MAX_INDEX 3
#define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0
-#define I40E_GLPRT_PRC511H_PRC511H_MASK (0xFFFF << I40E_GLPRT_PRC511H_PRC511H_SHIFT)
-#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511H_PRC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC511H_PRC511H_SHIFT)
+#define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC511L_MAX_INDEX 3
#define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0
-#define I40E_GLPRT_PRC511L_PRC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC511L_PRC511L_SHIFT)
-#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC511L_PRC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC511L_PRC511L_SHIFT)
+#define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC64H_MAX_INDEX 3
#define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0
-#define I40E_GLPRT_PRC64H_PRC64H_MASK (0xFFFF << I40E_GLPRT_PRC64H_PRC64H_SHIFT)
-#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64H_PRC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC64H_PRC64H_SHIFT)
+#define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC64L_MAX_INDEX 3
#define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0
-#define I40E_GLPRT_PRC64L_PRC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC64L_PRC64L_SHIFT)
-#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC64L_PRC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC64L_PRC64L_SHIFT)
+#define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC9522H_MAX_INDEX 3
#define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0
-#define I40E_GLPRT_PRC9522H_PRC1522H_MASK (0xFFFF << I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
-#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC9522H_PRC1522H_SHIFT)
+#define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PRC9522L_MAX_INDEX 3
#define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0
-#define I40E_GLPRT_PRC9522L_PRC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
-#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PRC9522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC9522L_PRC1522L_SHIFT)
+#define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1023H_MAX_INDEX 3
#define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0
-#define I40E_GLPRT_PTC1023H_PTC1023H_MASK (0xFFFF << I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
-#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023H_PTC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1023H_PTC1023H_SHIFT)
+#define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1023L_MAX_INDEX 3
#define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0
-#define I40E_GLPRT_PTC1023L_PTC1023L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
-#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1023L_PTC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1023L_PTC1023L_SHIFT)
+#define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC127H_MAX_INDEX 3
#define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0
-#define I40E_GLPRT_PTC127H_PTC127H_MASK (0xFFFF << I40E_GLPRT_PTC127H_PTC127H_SHIFT)
-#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127H_PTC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC127H_PTC127H_SHIFT)
+#define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC127L_MAX_INDEX 3
#define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0
-#define I40E_GLPRT_PTC127L_PTC127L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC127L_PTC127L_SHIFT)
-#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC127L_PTC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC127L_PTC127L_SHIFT)
+#define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1522H_MAX_INDEX 3
#define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0
-#define I40E_GLPRT_PTC1522H_PTC1522H_MASK (0xFFFF << I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
-#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522H_PTC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1522H_PTC1522H_SHIFT)
+#define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC1522L_MAX_INDEX 3
#define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0
-#define I40E_GLPRT_PTC1522L_PTC1522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
-#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC1522L_PTC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1522L_PTC1522L_SHIFT)
+#define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC255H_MAX_INDEX 3
#define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0
-#define I40E_GLPRT_PTC255H_PTC255H_MASK (0xFFFF << I40E_GLPRT_PTC255H_PTC255H_SHIFT)
-#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255H_PTC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC255H_PTC255H_SHIFT)
+#define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC255L_MAX_INDEX 3
#define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0
-#define I40E_GLPRT_PTC255L_PTC255L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC255L_PTC255L_SHIFT)
-#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC255L_PTC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC255L_PTC255L_SHIFT)
+#define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC511H_MAX_INDEX 3
#define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0
-#define I40E_GLPRT_PTC511H_PTC511H_MASK (0xFFFF << I40E_GLPRT_PTC511H_PTC511H_SHIFT)
-#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511H_PTC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC511H_PTC511H_SHIFT)
+#define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC511L_MAX_INDEX 3
#define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0
-#define I40E_GLPRT_PTC511L_PTC511L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC511L_PTC511L_SHIFT)
-#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC511L_PTC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC511L_PTC511L_SHIFT)
+#define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC64H_MAX_INDEX 3
#define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0
-#define I40E_GLPRT_PTC64H_PTC64H_MASK (0xFFFF << I40E_GLPRT_PTC64H_PTC64H_SHIFT)
-#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64H_PTC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC64H_PTC64H_SHIFT)
+#define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC64L_MAX_INDEX 3
#define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0
-#define I40E_GLPRT_PTC64L_PTC64L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC64L_PTC64L_SHIFT)
-#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC64L_PTC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC64L_PTC64L_SHIFT)
+#define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC9522H_MAX_INDEX 3
#define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0
-#define I40E_GLPRT_PTC9522H_PTC9522H_MASK (0xFFFF << I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
-#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PTC9522H_PTC9522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC9522H_PTC9522H_SHIFT)
+#define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_PTC9522L_MAX_INDEX 3
#define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0
-#define I40E_GLPRT_PTC9522L_PTC9522L_MASK (0xFFFFFFFF << I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
-#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PTC9522L_PTC9522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC9522L_PTC9522L_SHIFT)
+#define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3
#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
-#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT)
+#define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3
#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0
-#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
-#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT)
+#define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXONRXC_MAX_INDEX 3
#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0
-#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK (0xFFFFFFFF << I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
-#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT)
+#define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_PXONTXC_MAX_INDEX 3
#define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0
-#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK (0xFFFFFFFF << I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
-#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT)
+#define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RDPC_MAX_INDEX 3
#define I40E_GLPRT_RDPC_RDPC_SHIFT 0
-#define I40E_GLPRT_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLPRT_RDPC_RDPC_SHIFT)
-#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RDPC_RDPC_SHIFT)
+#define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RFC_MAX_INDEX 3
#define I40E_GLPRT_RFC_RFC_SHIFT 0
-#define I40E_GLPRT_RFC_RFC_MASK (0xFFFFFFFF << I40E_GLPRT_RFC_RFC_SHIFT)
-#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RFC_RFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RFC_RFC_SHIFT)
+#define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RJC_MAX_INDEX 3
#define I40E_GLPRT_RJC_RJC_SHIFT 0
-#define I40E_GLPRT_RJC_RJC_MASK (0xFFFFFFFF << I40E_GLPRT_RJC_RJC_SHIFT)
-#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RJC_RJC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RJC_RJC_SHIFT)
+#define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RLEC_MAX_INDEX 3
#define I40E_GLPRT_RLEC_RLEC_SHIFT 0
-#define I40E_GLPRT_RLEC_RLEC_MASK (0xFFFFFFFF << I40E_GLPRT_RLEC_RLEC_SHIFT)
-#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RLEC_RLEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RLEC_RLEC_SHIFT)
+#define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_ROC_MAX_INDEX 3
#define I40E_GLPRT_ROC_ROC_SHIFT 0
-#define I40E_GLPRT_ROC_ROC_MASK (0xFFFFFFFF << I40E_GLPRT_ROC_ROC_SHIFT)
-#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_ROC_ROC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ROC_ROC_SHIFT)
+#define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RUC_MAX_INDEX 3
#define I40E_GLPRT_RUC_RUC_SHIFT 0
-#define I40E_GLPRT_RUC_RUC_MASK (0xFFFFFFFF << I40E_GLPRT_RUC_RUC_SHIFT)
-#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RUC_RUC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUC_RUC_SHIFT)
+#define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_RUPP_MAX_INDEX 3
#define I40E_GLPRT_RUPP_RUPP_SHIFT 0
-#define I40E_GLPRT_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLPRT_RUPP_RUPP_SHIFT)
-#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32))
+#define I40E_GLPRT_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUPP_RUPP_SHIFT)
+#define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */
#define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3
#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0
-#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK (0xFFFFFFFF << I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
-#define I40E_GLPRT_STDC(_i) (0x00300640 + ((_i) * 8)) /* _i=0...3 */
-#define I40E_GLPRT_STDC_MAX_INDEX 3
-#define I40E_GLPRT_STDC_STDC_SHIFT 0
-#define I40E_GLPRT_STDC_STDC_MASK (0xFFFFFFFF << I40E_GLPRT_STDC_STDC_SHIFT)
-#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT)
+#define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_TDOLD_MAX_INDEX 3
#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0
-#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK (0xFFFFFFFF << I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
-#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT)
+#define I40E_GLPRT_TDPC(_i) (0x00375400 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_TDPC_MAX_INDEX 3
#define I40E_GLPRT_TDPC_TDPC_SHIFT 0
-#define I40E_GLPRT_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLPRT_TDPC_TDPC_SHIFT)
-#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDPC_TDPC_SHIFT)
+#define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPRCH_MAX_INDEX 3
#define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLPRT_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLPRT_UPRCH_UPRCH_SHIFT)
-#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPRCH_UPRCH_SHIFT)
+#define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPRCL_MAX_INDEX 3
#define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLPRT_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLPRT_UPRCL_UPRCL_SHIFT)
-#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPRCL_UPRCL_SHIFT)
+#define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPTCH_MAX_INDEX 3
#define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLPRT_UPTCH_UPTCH_SHIFT)
-#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */
+#define I40E_GLPRT_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPTCH_UPTCH_SHIFT)
+#define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_GLPRT_UPTCL_MAX_INDEX 3
#define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0
-#define I40E_GLPRT_UPTCL_VUPTCH_MASK (0xFFFFFFFF << I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
-#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLPRT_UPTCL_VUPTCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPTCL_VUPTCH_SHIFT)
+#define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPRCH_MAX_INDEX 15
#define I40E_GLSW_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLSW_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLSW_BPRCH_BPRCH_SHIFT)
-#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPRCH_BPRCH_SHIFT)
+#define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPRCL_MAX_INDEX 15
#define I40E_GLSW_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLSW_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLSW_BPRCL_BPRCL_SHIFT)
-#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPRCL_BPRCL_SHIFT)
+#define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPTCH_MAX_INDEX 15
#define I40E_GLSW_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLSW_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLSW_BPTCH_BPTCH_SHIFT)
-#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPTCH_BPTCH_SHIFT)
+#define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_BPTCL_MAX_INDEX 15
#define I40E_GLSW_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLSW_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLSW_BPTCL_BPTCL_SHIFT)
-#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPTCL_BPTCL_SHIFT)
+#define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GORCH_MAX_INDEX 15
#define I40E_GLSW_GORCH_GORCH_SHIFT 0
-#define I40E_GLSW_GORCH_GORCH_MASK (0xFFFF << I40E_GLSW_GORCH_GORCH_SHIFT)
-#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GORCH_GORCH_SHIFT)
+#define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GORCL_MAX_INDEX 15
#define I40E_GLSW_GORCL_GORCL_SHIFT 0
-#define I40E_GLSW_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLSW_GORCL_GORCL_SHIFT)
-#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GORCL_GORCL_SHIFT)
+#define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GOTCH_MAX_INDEX 15
#define I40E_GLSW_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLSW_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLSW_GOTCH_GOTCH_SHIFT)
-#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GOTCH_GOTCH_SHIFT)
+#define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_GOTCL_MAX_INDEX 15
#define I40E_GLSW_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLSW_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLSW_GOTCL_GOTCL_SHIFT)
-#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GOTCL_GOTCL_SHIFT)
+#define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPRCH_MAX_INDEX 15
#define I40E_GLSW_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLSW_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLSW_MPRCH_MPRCH_SHIFT)
-#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPRCH_MPRCH_SHIFT)
+#define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPRCL_MAX_INDEX 15
#define I40E_GLSW_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLSW_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLSW_MPRCL_MPRCL_SHIFT)
-#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPRCL_MPRCL_SHIFT)
+#define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPTCH_MAX_INDEX 15
#define I40E_GLSW_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLSW_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLSW_MPTCH_MPTCH_SHIFT)
-#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPTCH_MPTCH_SHIFT)
+#define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_MPTCL_MAX_INDEX 15
#define I40E_GLSW_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLSW_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLSW_MPTCL_MPTCL_SHIFT)
-#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPTCL_MPTCL_SHIFT)
+#define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_RUPP_MAX_INDEX 15
#define I40E_GLSW_RUPP_RUPP_SHIFT 0
-#define I40E_GLSW_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLSW_RUPP_RUPP_SHIFT)
-#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_RUPP_RUPP_SHIFT)
+#define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_TDPC_MAX_INDEX 15
#define I40E_GLSW_TDPC_TDPC_SHIFT 0
-#define I40E_GLSW_TDPC_TDPC_MASK (0xFFFFFFFF << I40E_GLSW_TDPC_TDPC_SHIFT)
-#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_TDPC_TDPC_SHIFT)
+#define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPRCH_MAX_INDEX 15
#define I40E_GLSW_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLSW_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLSW_UPRCH_UPRCH_SHIFT)
-#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPRCH_UPRCH_SHIFT)
+#define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPRCL_MAX_INDEX 15
#define I40E_GLSW_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLSW_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLSW_UPRCL_UPRCL_SHIFT)
-#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPRCL_UPRCL_SHIFT)
+#define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPTCH_MAX_INDEX 15
#define I40E_GLSW_UPTCH_UPTCH_SHIFT 0
-#define I40E_GLSW_UPTCH_UPTCH_MASK (0xFFFF << I40E_GLSW_UPTCH_UPTCH_SHIFT)
-#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */
+#define I40E_GLSW_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPTCH_UPTCH_SHIFT)
+#define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_GLSW_UPTCL_MAX_INDEX 15
#define I40E_GLSW_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLSW_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLSW_UPTCL_UPTCL_SHIFT)
-#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLSW_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPTCL_UPTCL_SHIFT)
+#define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPRCH_MAX_INDEX 383
#define I40E_GLV_BPRCH_BPRCH_SHIFT 0
-#define I40E_GLV_BPRCH_BPRCH_MASK (0xFFFF << I40E_GLV_BPRCH_BPRCH_SHIFT)
-#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPRCH_BPRCH_SHIFT)
+#define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPRCL_MAX_INDEX 383
#define I40E_GLV_BPRCL_BPRCL_SHIFT 0
-#define I40E_GLV_BPRCL_BPRCL_MASK (0xFFFFFFFF << I40E_GLV_BPRCL_BPRCL_SHIFT)
-#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPRCL_BPRCL_SHIFT)
+#define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPTCH_MAX_INDEX 383
#define I40E_GLV_BPTCH_BPTCH_SHIFT 0
-#define I40E_GLV_BPTCH_BPTCH_MASK (0xFFFF << I40E_GLV_BPTCH_BPTCH_SHIFT)
-#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPTCH_BPTCH_SHIFT)
+#define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_BPTCL_MAX_INDEX 383
#define I40E_GLV_BPTCL_BPTCL_SHIFT 0
-#define I40E_GLV_BPTCL_BPTCL_MASK (0xFFFFFFFF << I40E_GLV_BPTCL_BPTCL_SHIFT)
-#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPTCL_BPTCL_SHIFT)
+#define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GORCH_MAX_INDEX 383
#define I40E_GLV_GORCH_GORCH_SHIFT 0
-#define I40E_GLV_GORCH_GORCH_MASK (0xFFFF << I40E_GLV_GORCH_GORCH_SHIFT)
-#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GORCH_GORCH_SHIFT)
+#define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GORCL_MAX_INDEX 383
#define I40E_GLV_GORCL_GORCL_SHIFT 0
-#define I40E_GLV_GORCL_GORCL_MASK (0xFFFFFFFF << I40E_GLV_GORCL_GORCL_SHIFT)
-#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GORCL_GORCL_SHIFT)
+#define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GOTCH_MAX_INDEX 383
#define I40E_GLV_GOTCH_GOTCH_SHIFT 0
-#define I40E_GLV_GOTCH_GOTCH_MASK (0xFFFF << I40E_GLV_GOTCH_GOTCH_SHIFT)
-#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GOTCH_GOTCH_SHIFT)
+#define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_GOTCL_MAX_INDEX 383
#define I40E_GLV_GOTCL_GOTCL_SHIFT 0
-#define I40E_GLV_GOTCL_GOTCL_MASK (0xFFFFFFFF << I40E_GLV_GOTCL_GOTCL_SHIFT)
-#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GOTCL_GOTCL_SHIFT)
+#define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPRCH_MAX_INDEX 383
#define I40E_GLV_MPRCH_MPRCH_SHIFT 0
-#define I40E_GLV_MPRCH_MPRCH_MASK (0xFFFF << I40E_GLV_MPRCH_MPRCH_SHIFT)
-#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPRCH_MPRCH_SHIFT)
+#define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPRCL_MAX_INDEX 383
#define I40E_GLV_MPRCL_MPRCL_SHIFT 0
-#define I40E_GLV_MPRCL_MPRCL_MASK (0xFFFFFFFF << I40E_GLV_MPRCL_MPRCL_SHIFT)
-#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPRCL_MPRCL_SHIFT)
+#define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPTCH_MAX_INDEX 383
#define I40E_GLV_MPTCH_MPTCH_SHIFT 0
-#define I40E_GLV_MPTCH_MPTCH_MASK (0xFFFF << I40E_GLV_MPTCH_MPTCH_SHIFT)
-#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPTCH_MPTCH_SHIFT)
+#define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_MPTCL_MAX_INDEX 383
#define I40E_GLV_MPTCL_MPTCL_SHIFT 0
-#define I40E_GLV_MPTCL_MPTCL_MASK (0xFFFFFFFF << I40E_GLV_MPTCL_MPTCL_SHIFT)
-#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPTCL_MPTCL_SHIFT)
+#define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_RDPC_MAX_INDEX 383
#define I40E_GLV_RDPC_RDPC_SHIFT 0
-#define I40E_GLV_RDPC_RDPC_MASK (0xFFFFFFFF << I40E_GLV_RDPC_RDPC_SHIFT)
-#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RDPC_RDPC_SHIFT)
+#define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_RUPP_MAX_INDEX 383
#define I40E_GLV_RUPP_RUPP_SHIFT 0
-#define I40E_GLV_RUPP_RUPP_MASK (0xFFFFFFFF << I40E_GLV_RUPP_RUPP_SHIFT)
-#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 8)) /* _i=0...383 */
+#define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT)
+#define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_TEPC_MAX_INDEX 383
#define I40E_GLV_TEPC_TEPC_SHIFT 0
-#define I40E_GLV_TEPC_TEPC_MASK (0xFFFFFFFF << I40E_GLV_TEPC_TEPC_SHIFT)
-#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT)
+#define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPRCH_MAX_INDEX 383
#define I40E_GLV_UPRCH_UPRCH_SHIFT 0
-#define I40E_GLV_UPRCH_UPRCH_MASK (0xFFFF << I40E_GLV_UPRCH_UPRCH_SHIFT)
-#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPRCH_UPRCH_SHIFT)
+#define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPRCL_MAX_INDEX 383
#define I40E_GLV_UPRCL_UPRCL_SHIFT 0
-#define I40E_GLV_UPRCL_UPRCL_MASK (0xFFFFFFFF << I40E_GLV_UPRCL_UPRCL_SHIFT)
-#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPRCL_UPRCL_SHIFT)
+#define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPTCH_MAX_INDEX 383
#define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0
-#define I40E_GLV_UPTCH_GLVUPTCH_MASK (0xFFFF << I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
-#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */
+#define I40E_GLV_UPTCH_GLVUPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPTCH_GLVUPTCH_SHIFT)
+#define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */
#define I40E_GLV_UPTCL_MAX_INDEX 383
#define I40E_GLV_UPTCL_UPTCL_SHIFT 0
-#define I40E_GLV_UPTCL_UPTCL_MASK (0xFFFFFFFF << I40E_GLV_UPTCL_UPTCL_SHIFT)
-#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLV_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPTCL_UPTCL_SHIFT)
+#define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RBCH_MAX_INDEX 7
#define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_RBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RBCL_MAX_INDEX 7
#define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_RBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RPCH_MAX_INDEX 7
#define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_RPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_RPCL_MAX_INDEX 7
#define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_RPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
-#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_RPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RPCL_TCPCL_SHIFT)
+#define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TBCH_MAX_INDEX 7
#define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0
-#define I40E_GLVEBTC_TBCH_TCBCH_MASK (0xFFFF << I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
-#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TBCH_TCBCH_SHIFT)
+#define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TBCL_MAX_INDEX 7
#define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0
-#define I40E_GLVEBTC_TBCL_TCBCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
-#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TBCL_TCBCL_SHIFT)
+#define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TPCH_MAX_INDEX 7
#define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0
-#define I40E_GLVEBTC_TPCH_TCPCH_MASK (0xFFFF << I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
-#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */
+#define I40E_GLVEBTC_TPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TPCH_TCPCH_SHIFT)
+#define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */
#define I40E_GLVEBTC_TPCL_MAX_INDEX 7
#define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0
-#define I40E_GLVEBTC_TPCL_TCPCL_MASK (0xFFFFFFFF << I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
-#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBTC_TPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TPCL_TCPCL_SHIFT)
+#define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_BPCH_MAX_INDEX 127
#define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0
-#define I40E_GLVEBVL_BPCH_VLBPCH_MASK (0xFFFF << I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
-#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCH_VLBPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_BPCH_VLBPCH_SHIFT)
+#define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_BPCL_MAX_INDEX 127
#define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0
-#define I40E_GLVEBVL_BPCL_VLBPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
-#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_BPCL_VLBPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_BPCL_VLBPCL_SHIFT)
+#define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GORCH_MAX_INDEX 127
#define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GORCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GORCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GORCL_MAX_INDEX 127
#define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GORCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GORCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GORCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GOTCH_MAX_INDEX 127
#define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0
-#define I40E_GLVEBVL_GOTCH_VLBCH_MASK (0xFFFF << I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
-#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GOTCH_VLBCH_SHIFT)
+#define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_GOTCL_MAX_INDEX 127
#define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0
-#define I40E_GLVEBVL_GOTCL_VLBCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
-#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_GOTCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GOTCL_VLBCL_SHIFT)
+#define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_MPCH_MAX_INDEX 127
#define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0
-#define I40E_GLVEBVL_MPCH_VLMPCH_MASK (0xFFFF << I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
-#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCH_VLMPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_MPCH_VLMPCH_SHIFT)
+#define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_MPCL_MAX_INDEX 127
#define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0
-#define I40E_GLVEBVL_MPCL_VLMPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
-#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_MPCL_VLMPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_MPCL_VLMPCL_SHIFT)
+#define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_UPCH_MAX_INDEX 127
#define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0
-#define I40E_GLVEBVL_UPCH_VLUPCH_MASK (0xFFFF << I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
-#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */
+#define I40E_GLVEBVL_UPCH_VLUPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_UPCH_VLUPCH_SHIFT)
+#define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_GLVEBVL_UPCL_MAX_INDEX 127
#define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0
-#define I40E_GLVEBVL_UPCL_VLUPCL_MASK (0xFFFFFFFF << I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C
+#define I40E_GLVEBVL_UPCL_VLUPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_UPCL_VLUPCL_SHIFT)
+#define I40E_GL_MTG_FLU_MSK_H 0x00269F4C /* Reset: CORER */
#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK (0xFFFF << I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
-#define I40E_GL_MTG_FLU_MSK_L 0x00269F44
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT 0
-#define I40E_GL_MTG_FLU_MSK_L_MASK_LOW_MASK (0xFFFFFFFF << I40E_GL_MTG_FLU_MSK_L_MASK_LOW_SHIFT)
-#define I40E_GL_SWR_DEF_ACT(_i) (0x0026CF00 + ((_i) * 4)) /* _i=0...25 */
-#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 25
+#define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK I40E_MASK(0xFFFF, I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT)
+#define I40E_GL_SWR_DEF_ACT(_i) (0x00270200 + ((_i) * 4)) /* _i=0...35 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_MAX_INDEX 35
#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
-#define I40E_GL_SWR_DEF_ACT_EN 0x0026CF84
+#define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT)
+#define I40E_GL_SWR_DEF_ACT_EN(_i) (0x0026CFB8 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
+#define I40E_GL_SWR_DEF_ACT_EN_MAX_INDEX 1
#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0
-#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK (0xFFFFFFFF << I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
-#define I40E_PRT_MSCCNT 0x00256BA0
-#define I40E_PRT_MSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_MSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_MSCCNT_CCOUNT_SHIFT)
-#define I40E_PRT_SCSTS 0x00256C20
-#define I40E_PRT_SCSTS_BSCA_SHIFT 0
-#define I40E_PRT_SCSTS_BSCA_MASK (0x1 << I40E_PRT_SCSTS_BSCA_SHIFT)
-#define I40E_PRT_SCSTS_BSCAP_SHIFT 1
-#define I40E_PRT_SCSTS_BSCAP_MASK (0x1 << I40E_PRT_SCSTS_BSCAP_SHIFT)
-#define I40E_PRT_SCSTS_MSCA_SHIFT 2
-#define I40E_PRT_SCSTS_MSCA_MASK (0x1 << I40E_PRT_SCSTS_MSCA_SHIFT)
-#define I40E_PRT_SCSTS_MSCAP_SHIFT 3
-#define I40E_PRT_SCSTS_MSCAP_MASK (0x1 << I40E_PRT_SCSTS_MSCAP_SHIFT)
-#define I40E_PRT_SWT_BSCCNT 0x00256C60
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT 0
-#define I40E_PRT_SWT_BSCCNT_CCOUNT_MASK (0x1FFFFFF << I40E_PRT_SWT_BSCCNT_CCOUNT_SHIFT)
-#define I40E_PRTTSYN_ADJ 0x001E4280
+#define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT)
+#define I40E_PRTTSYN_ADJ 0x001E4280 /* Reset: GLOBR */
#define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0
-#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK (0x7FFFFFFF << I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
+#define I40E_PRTTSYN_ADJ_TSYNADJ_MASK I40E_MASK(0x7FFFFFFF, I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT)
#define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31
-#define I40E_PRTTSYN_ADJ_SIGN_MASK (0x1 << I40E_PRTTSYN_ADJ_SIGN_SHIFT)
-#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_ADJ_SIGN_MASK I40E_MASK(0x1, I40E_PRTTSYN_ADJ_SIGN_SHIFT)
+#define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_AUX_0_MAX_INDEX 1
#define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0
-#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT)
#define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1
-#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK (0x3 << I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTMOD_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT)
#define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3
-#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK (0x1 << I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_0_OUTLVL_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT)
#define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8
-#define I40E_PRTTSYN_AUX_0_PULSEW_MASK (0xF << I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
+#define I40E_PRTTSYN_AUX_0_PULSEW_MASK I40E_MASK(0xF, I40E_PRTTSYN_AUX_0_PULSEW_SHIFT)
#define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16
-#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK (0x3 << I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
-#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT)
+#define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_AUX_1_MAX_INDEX 1
#define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0
-#define I40E_PRTTSYN_AUX_1_INSTNT_MASK (0x1 << I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
+#define I40E_PRTTSYN_AUX_1_INSTNT_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_INSTNT_SHIFT)
#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1
-#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK (0x1 << I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
-#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT)
+#define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_CLKO_MAX_INDEX 1
#define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0
-#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK (0xFFFFFFFF << I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
-#define I40E_PRTTSYN_CTL0 0x001E4200
+#define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT)
+#define I40E_PRTTSYN_CTL0 0x001E4200 /* Reset: GLOBR */
#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0
-#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK (0x1 << I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
+#define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT)
#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1
-#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2
-#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3
-#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT)
#define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8
-#define I40E_PRTTSYN_CTL0_PF_ID_MASK (0xF << I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
+#define I40E_PRTTSYN_CTL0_PF_ID_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL0_PF_ID_SHIFT)
#define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12
-#define I40E_PRTTSYN_CTL0_TSYNACT_MASK (0x3 << I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
+#define I40E_PRTTSYN_CTL0_TSYNACT_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL0_TSYNACT_SHIFT)
#define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL0_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_CTL1 0x00085020
+#define I40E_PRTTSYN_CTL0_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_CTL1 0x00085020 /* Reset: CORER */
#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT)
#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8
-#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK (0xFF << I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT)
#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT)
#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20
-#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK (0xF << I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
+#define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT)
#define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24
-#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK (0x3 << I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
+#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
#define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26
-#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK (0x3 << I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
+#define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT)
#define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31
-#define I40E_PRTTSYN_CTL1_TSYNENA_MASK (0x1 << I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
-#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT)
+#define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1
#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0
-#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
-#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT)
+#define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1
#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0
-#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
-#define I40E_PRTTSYN_INC_H 0x001E4060
+#define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT)
+#define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */
#define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0
-#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK (0x3F << I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
-#define I40E_PRTTSYN_INC_L 0x001E4040
+#define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK I40E_MASK(0x3F, I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT)
+#define I40E_PRTTSYN_INC_L 0x001E4040 /* Reset: GLOBR */
#define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0
-#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
-#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT)
+#define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3
#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */
#define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3
#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
-#define I40E_PRTTSYN_STAT_0 0x001E4220
+#define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT)
+#define I40E_PRTTSYN_STAT_0 0x001E4220 /* Reset: GLOBR */
#define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_0_EVENT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT0_SHIFT)
#define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_0_EVENT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_EVENT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT1_SHIFT)
#define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2
-#define I40E_PRTTSYN_STAT_0_TGT0_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT0_SHIFT)
#define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3
-#define I40E_PRTTSYN_STAT_0_TGT1_MASK (0x1 << I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
+#define I40E_PRTTSYN_STAT_0_TGT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT1_SHIFT)
#define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4
-#define I40E_PRTTSYN_STAT_0_TXTIME_MASK (0x1 << I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
-#define I40E_PRTTSYN_STAT_1 0x00085140
+#define I40E_PRTTSYN_STAT_0_TXTIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TXTIME_SHIFT)
+#define I40E_PRTTSYN_STAT_1 0x00085140 /* Reset: CORER */
#define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0
-#define I40E_PRTTSYN_STAT_1_RXT0_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT0_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1
-#define I40E_PRTTSYN_STAT_1_RXT1_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT1_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2
-#define I40E_PRTTSYN_STAT_1_RXT2_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
+#define I40E_PRTTSYN_STAT_1_RXT2_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT2_SHIFT)
#define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3
-#define I40E_PRTTSYN_STAT_1_RXT3_MASK (0x1 << I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
-#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_STAT_1_RXT3_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT3_SHIFT)
+#define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_TGT_H_MAX_INDEX 1
#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0
-#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
-#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */
+#define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT)
+#define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */
#define I40E_PRTTSYN_TGT_L_MAX_INDEX 1
#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0
-#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
-#define I40E_PRTTSYN_TIME_H 0x001E4120
+#define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT)
+#define I40E_PRTTSYN_TIME_H 0x001E4120 /* Reset: GLOBR */
#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0
-#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
-#define I40E_PRTTSYN_TIME_L 0x001E4100
+#define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT)
+#define I40E_PRTTSYN_TIME_L 0x001E4100 /* Reset: GLOBR */
#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0
-#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
-#define I40E_PRTTSYN_TXTIME_H 0x001E41E0
+#define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT)
+#define I40E_PRTTSYN_TXTIME_H 0x001E41E0 /* Reset: GLOBR */
#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
-#define I40E_PRTTSYN_TXTIME_L 0x001E41C0
+#define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT)
+#define I40E_PRTTSYN_TXTIME_L 0x001E41C0 /* Reset: GLOBR */
#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0
-#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK (0xFFFFFFFF << I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
-#define I40E_GLSCD_QUANTA 0x000B2080
+#define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT)
+#define I40E_GLSCD_QUANTA 0x000B2080 /* Reset: CORER */
#define I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT 0
-#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK (0x7 << I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
-#define I40E_GL_MDET_RX 0x0012A510
+#define I40E_GLSCD_QUANTA_TSCDQUANTA_MASK I40E_MASK(0x7, I40E_GLSCD_QUANTA_TSCDQUANTA_SHIFT)
+#define I40E_GL_MDET_RX 0x0012A510 /* Reset: CORER */
#define I40E_GL_MDET_RX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_RX_FUNCTION_MASK (0xFF << I40E_GL_MDET_RX_FUNCTION_SHIFT)
+#define I40E_GL_MDET_RX_FUNCTION_MASK I40E_MASK(0xFF, I40E_GL_MDET_RX_FUNCTION_SHIFT)
#define I40E_GL_MDET_RX_EVENT_SHIFT 8
-#define I40E_GL_MDET_RX_EVENT_MASK (0x1FF << I40E_GL_MDET_RX_EVENT_SHIFT)
+#define I40E_GL_MDET_RX_EVENT_MASK I40E_MASK(0x1FF, I40E_GL_MDET_RX_EVENT_SHIFT)
#define I40E_GL_MDET_RX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_RX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_RX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_QUEUE_MASK I40E_MASK(0x3FFF, I40E_GL_MDET_RX_QUEUE_SHIFT)
#define I40E_GL_MDET_RX_VALID_SHIFT 31
-#define I40E_GL_MDET_RX_VALID_MASK (0x1 << I40E_GL_MDET_RX_VALID_SHIFT)
-#define I40E_GL_MDET_TX 0x000E6480
-#define I40E_GL_MDET_TX_FUNCTION_SHIFT 0
-#define I40E_GL_MDET_TX_FUNCTION_MASK (0xFF << I40E_GL_MDET_TX_FUNCTION_SHIFT)
-#define I40E_GL_MDET_TX_EVENT_SHIFT 8
-#define I40E_GL_MDET_TX_EVENT_MASK (0x1FF << I40E_GL_MDET_TX_EVENT_SHIFT)
-#define I40E_GL_MDET_TX_QUEUE_SHIFT 17
-#define I40E_GL_MDET_TX_QUEUE_MASK (0x3FFF << I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_RX_VALID_SHIFT)
+#define I40E_GL_MDET_TX 0x000E6480 /* Reset: CORER */
+#define I40E_GL_MDET_TX_QUEUE_SHIFT 0
+#define I40E_GL_MDET_TX_QUEUE_MASK I40E_MASK(0xFFF, I40E_GL_MDET_TX_QUEUE_SHIFT)
+#define I40E_GL_MDET_TX_VF_NUM_SHIFT 12
+#define I40E_GL_MDET_TX_VF_NUM_MASK I40E_MASK(0x1FF, I40E_GL_MDET_TX_VF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_PF_NUM_SHIFT 21
+#define I40E_GL_MDET_TX_PF_NUM_MASK I40E_MASK(0xF, I40E_GL_MDET_TX_PF_NUM_SHIFT)
+#define I40E_GL_MDET_TX_EVENT_SHIFT 25
+#define I40E_GL_MDET_TX_EVENT_MASK I40E_MASK(0x1F, I40E_GL_MDET_TX_EVENT_SHIFT)
#define I40E_GL_MDET_TX_VALID_SHIFT 31
-#define I40E_GL_MDET_TX_VALID_MASK (0x1 << I40E_GL_MDET_TX_VALID_SHIFT)
-#define I40E_PF_MDET_RX 0x0012A400
+#define I40E_GL_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_TX_VALID_SHIFT)
+#define I40E_PF_MDET_RX 0x0012A400 /* Reset: CORER */
#define I40E_PF_MDET_RX_VALID_SHIFT 0
-#define I40E_PF_MDET_RX_VALID_MASK (0x1 << I40E_PF_MDET_RX_VALID_SHIFT)
-#define I40E_PF_MDET_TX 0x000E6400
+#define I40E_PF_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_RX_VALID_SHIFT)
+#define I40E_PF_MDET_TX 0x000E6400 /* Reset: CORER */
#define I40E_PF_MDET_TX_VALID_SHIFT 0
-#define I40E_PF_MDET_TX_VALID_MASK (0x1 << I40E_PF_MDET_TX_VALID_SHIFT)
-#define I40E_PF_VT_PFALLOC 0x001C0500
+#define I40E_PF_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_TX_VALID_SHIFT)
+#define I40E_PF_VT_PFALLOC 0x001C0500 /* Reset: CORER */
#define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0
-#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_FIRSTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT)
#define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8
-#define I40E_PF_VT_PFALLOC_LASTVF_MASK (0xFF << I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
+#define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT)
#define I40E_PF_VT_PFALLOC_VALID_SHIFT 31
-#define I40E_PF_VT_PFALLOC_VALID_MASK (0x1 << I40E_PF_VT_PFALLOC_VALID_SHIFT)
-#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT)
+#define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VP_MDET_RX_MAX_INDEX 127
#define I40E_VP_MDET_RX_VALID_SHIFT 0
-#define I40E_VP_MDET_RX_VALID_MASK (0x1 << I40E_VP_MDET_RX_VALID_SHIFT)
-#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_VP_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_RX_VALID_SHIFT)
+#define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VP_MDET_TX_MAX_INDEX 127
#define I40E_VP_MDET_TX_VALID_SHIFT 0
-#define I40E_VP_MDET_TX_VALID_MASK (0x1 << I40E_VP_MDET_TX_VALID_SHIFT)
-#define I40E_GLPM_WUMC 0x0006C800
+#define I40E_VP_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_TX_VALID_SHIFT)
+#define I40E_GLPM_WUMC 0x0006C800 /* Reset: POR */
#define I40E_GLPM_WUMC_NOTCO_SHIFT 0
-#define I40E_GLPM_WUMC_NOTCO_MASK (0x1 << I40E_GLPM_WUMC_NOTCO_SHIFT)
+#define I40E_GLPM_WUMC_NOTCO_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_NOTCO_SHIFT)
#define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1
-#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK (0x1 << I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
+#define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT)
#define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2
-#define I40E_GLPM_WUMC_ROL_MODE_MASK (0x1 << I40E_GLPM_WUMC_ROL_MODE_SHIFT)
+#define I40E_GLPM_WUMC_ROL_MODE_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_ROL_MODE_SHIFT)
#define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3
-#define I40E_GLPM_WUMC_RESERVED_4_MASK (0x1FFF << I40E_GLPM_WUMC_RESERVED_4_SHIFT)
+#define I40E_GLPM_WUMC_RESERVED_4_MASK I40E_MASK(0x1FFF, I40E_GLPM_WUMC_RESERVED_4_SHIFT)
#define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16
-#define I40E_GLPM_WUMC_MNG_WU_PF_MASK (0xFFFF << I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
-#define I40E_PFPM_APM 0x000B8080
+#define I40E_GLPM_WUMC_MNG_WU_PF_MASK I40E_MASK(0xFFFF, I40E_GLPM_WUMC_MNG_WU_PF_SHIFT)
+#define I40E_PFPM_APM 0x000B8080 /* Reset: POR */
#define I40E_PFPM_APM_APME_SHIFT 0
-#define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
-#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
+#define I40E_PFPM_APM_APME_MASK I40E_MASK(0x1, I40E_PFPM_APM_APME_SHIFT)
+#define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ /* Reset: POR */
#define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
#define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
-#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PFPM_WUC 0x0006B200
+#define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
+#define I40E_PFPM_WUC 0x0006B200 /* Reset: POR */
#define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
-#define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
-#define I40E_PFPM_WUFC 0x0006B400
+#define I40E_PFPM_WUC_EN_APM_D0_MASK I40E_MASK(0x1, I40E_PFPM_WUC_EN_APM_D0_SHIFT)
+#define I40E_PFPM_WUFC 0x0006B400 /* Reset: POR */
#define I40E_PFPM_WUFC_LNKC_SHIFT 0
-#define I40E_PFPM_WUFC_LNKC_MASK (0x1 << I40E_PFPM_WUFC_LNKC_SHIFT)
+#define I40E_PFPM_WUFC_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_LNKC_SHIFT)
#define I40E_PFPM_WUFC_MAG_SHIFT 1
-#define I40E_PFPM_WUFC_MAG_MASK (0x1 << I40E_PFPM_WUFC_MAG_SHIFT)
+#define I40E_PFPM_WUFC_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MAG_SHIFT)
#define I40E_PFPM_WUFC_MNG_SHIFT 3
-#define I40E_PFPM_WUFC_MNG_MASK (0x1 << I40E_PFPM_WUFC_MNG_SHIFT)
+#define I40E_PFPM_WUFC_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MNG_SHIFT)
#define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4
-#define I40E_PFPM_WUFC_FLX0_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5
-#define I40E_PFPM_WUFC_FLX1_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6
-#define I40E_PFPM_WUFC_FLX2_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7
-#define I40E_PFPM_WUFC_FLX3_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8
-#define I40E_PFPM_WUFC_FLX4_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9
-#define I40E_PFPM_WUFC_FLX5_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10
-#define I40E_PFPM_WUFC_FLX6_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11
-#define I40E_PFPM_WUFC_FLX7_ACT_MASK (0x1 << I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_ACT_SHIFT)
#define I40E_PFPM_WUFC_FLX0_SHIFT 16
-#define I40E_PFPM_WUFC_FLX0_MASK (0x1 << I40E_PFPM_WUFC_FLX0_SHIFT)
+#define I40E_PFPM_WUFC_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_SHIFT)
#define I40E_PFPM_WUFC_FLX1_SHIFT 17
-#define I40E_PFPM_WUFC_FLX1_MASK (0x1 << I40E_PFPM_WUFC_FLX1_SHIFT)
+#define I40E_PFPM_WUFC_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_SHIFT)
#define I40E_PFPM_WUFC_FLX2_SHIFT 18
-#define I40E_PFPM_WUFC_FLX2_MASK (0x1 << I40E_PFPM_WUFC_FLX2_SHIFT)
+#define I40E_PFPM_WUFC_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_SHIFT)
#define I40E_PFPM_WUFC_FLX3_SHIFT 19
-#define I40E_PFPM_WUFC_FLX3_MASK (0x1 << I40E_PFPM_WUFC_FLX3_SHIFT)
+#define I40E_PFPM_WUFC_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_SHIFT)
#define I40E_PFPM_WUFC_FLX4_SHIFT 20
-#define I40E_PFPM_WUFC_FLX4_MASK (0x1 << I40E_PFPM_WUFC_FLX4_SHIFT)
+#define I40E_PFPM_WUFC_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_SHIFT)
#define I40E_PFPM_WUFC_FLX5_SHIFT 21
-#define I40E_PFPM_WUFC_FLX5_MASK (0x1 << I40E_PFPM_WUFC_FLX5_SHIFT)
+#define I40E_PFPM_WUFC_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_SHIFT)
#define I40E_PFPM_WUFC_FLX6_SHIFT 22
-#define I40E_PFPM_WUFC_FLX6_MASK (0x1 << I40E_PFPM_WUFC_FLX6_SHIFT)
+#define I40E_PFPM_WUFC_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_SHIFT)
#define I40E_PFPM_WUFC_FLX7_SHIFT 23
-#define I40E_PFPM_WUFC_FLX7_MASK (0x1 << I40E_PFPM_WUFC_FLX7_SHIFT)
+#define I40E_PFPM_WUFC_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_SHIFT)
#define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUFC_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
-#define I40E_PFPM_WUS 0x0006B600
+#define I40E_PFPM_WUFC_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FW_RST_WK_SHIFT)
+#define I40E_PFPM_WUS 0x0006B600 /* Reset: POR */
#define I40E_PFPM_WUS_LNKC_SHIFT 0
-#define I40E_PFPM_WUS_LNKC_MASK (0x1 << I40E_PFPM_WUS_LNKC_SHIFT)
+#define I40E_PFPM_WUS_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUS_LNKC_SHIFT)
#define I40E_PFPM_WUS_MAG_SHIFT 1
-#define I40E_PFPM_WUS_MAG_MASK (0x1 << I40E_PFPM_WUS_MAG_SHIFT)
+#define I40E_PFPM_WUS_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MAG_SHIFT)
#define I40E_PFPM_WUS_PME_STATUS_SHIFT 2
-#define I40E_PFPM_WUS_PME_STATUS_MASK (0x1 << I40E_PFPM_WUS_PME_STATUS_SHIFT)
+#define I40E_PFPM_WUS_PME_STATUS_MASK I40E_MASK(0x1, I40E_PFPM_WUS_PME_STATUS_SHIFT)
#define I40E_PFPM_WUS_MNG_SHIFT 3
-#define I40E_PFPM_WUS_MNG_MASK (0x1 << I40E_PFPM_WUS_MNG_SHIFT)
+#define I40E_PFPM_WUS_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MNG_SHIFT)
#define I40E_PFPM_WUS_FLX0_SHIFT 16
-#define I40E_PFPM_WUS_FLX0_MASK (0x1 << I40E_PFPM_WUS_FLX0_SHIFT)
+#define I40E_PFPM_WUS_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX0_SHIFT)
#define I40E_PFPM_WUS_FLX1_SHIFT 17
-#define I40E_PFPM_WUS_FLX1_MASK (0x1 << I40E_PFPM_WUS_FLX1_SHIFT)
+#define I40E_PFPM_WUS_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX1_SHIFT)
#define I40E_PFPM_WUS_FLX2_SHIFT 18
-#define I40E_PFPM_WUS_FLX2_MASK (0x1 << I40E_PFPM_WUS_FLX2_SHIFT)
+#define I40E_PFPM_WUS_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX2_SHIFT)
#define I40E_PFPM_WUS_FLX3_SHIFT 19
-#define I40E_PFPM_WUS_FLX3_MASK (0x1 << I40E_PFPM_WUS_FLX3_SHIFT)
+#define I40E_PFPM_WUS_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX3_SHIFT)
#define I40E_PFPM_WUS_FLX4_SHIFT 20
-#define I40E_PFPM_WUS_FLX4_MASK (0x1 << I40E_PFPM_WUS_FLX4_SHIFT)
+#define I40E_PFPM_WUS_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX4_SHIFT)
#define I40E_PFPM_WUS_FLX5_SHIFT 21
-#define I40E_PFPM_WUS_FLX5_MASK (0x1 << I40E_PFPM_WUS_FLX5_SHIFT)
+#define I40E_PFPM_WUS_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX5_SHIFT)
#define I40E_PFPM_WUS_FLX6_SHIFT 22
-#define I40E_PFPM_WUS_FLX6_MASK (0x1 << I40E_PFPM_WUS_FLX6_SHIFT)
+#define I40E_PFPM_WUS_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX6_SHIFT)
#define I40E_PFPM_WUS_FLX7_SHIFT 23
-#define I40E_PFPM_WUS_FLX7_MASK (0x1 << I40E_PFPM_WUS_FLX7_SHIFT)
+#define I40E_PFPM_WUS_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX7_SHIFT)
#define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31
-#define I40E_PFPM_WUS_FW_RST_WK_MASK (0x1 << I40E_PFPM_WUS_FW_RST_WK_SHIFT)
-#define I40E_PRTPM_FHFHR 0x0006C000
+#define I40E_PFPM_WUS_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FW_RST_WK_SHIFT)
+#define I40E_PRTPM_FHFHR 0x0006C000 /* Reset: POR */
#define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0
-#define I40E_PRTPM_FHFHR_UNICAST_MASK (0x1 << I40E_PRTPM_FHFHR_UNICAST_SHIFT)
+#define I40E_PRTPM_FHFHR_UNICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_UNICAST_SHIFT)
#define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1
-#define I40E_PRTPM_FHFHR_MULTICAST_MASK (0x1 << I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
-#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_FHFHR_MULTICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_MULTICAST_SHIFT)
+#define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
#define I40E_PRTPM_SAH_MAX_INDEX 3
#define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0
-#define I40E_PRTPM_SAH_PFPM_SAH_MASK (0xFFFF << I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
+#define I40E_PRTPM_SAH_PFPM_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTPM_SAH_PFPM_SAH_SHIFT)
#define I40E_PRTPM_SAH_PF_NUM_SHIFT 26
-#define I40E_PRTPM_SAH_PF_NUM_MASK (0xF << I40E_PRTPM_SAH_PF_NUM_SHIFT)
+#define I40E_PRTPM_SAH_PF_NUM_MASK I40E_MASK(0xF, I40E_PRTPM_SAH_PF_NUM_SHIFT)
#define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30
-#define I40E_PRTPM_SAH_MC_MAG_EN_MASK (0x1 << I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
+#define I40E_PRTPM_SAH_MC_MAG_EN_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_MC_MAG_EN_SHIFT)
#define I40E_PRTPM_SAH_AV_SHIFT 31
-#define I40E_PRTPM_SAH_AV_MASK (0x1 << I40E_PRTPM_SAH_AV_SHIFT)
-#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */
+#define I40E_PRTPM_SAH_AV_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_AV_SHIFT)
+#define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */
#define I40E_PRTPM_SAL_MAX_INDEX 3
#define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0
-#define I40E_PRTPM_SAL_PFPM_SAL_MASK (0xFFFFFFFF << I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
-#define I40E_VF_ARQBAH1 0x00006000
+#define I40E_PRTPM_SAL_PFPM_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_SAL_PFPM_SAL_SHIFT)
+#define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */
#define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0
-#define I40E_VF_ARQBAH1_ARQBAH_MASK (0xFFFFFFFF << I40E_VF_ARQBAH1_ARQBAH_SHIFT)
-#define I40E_VF_ARQBAL1 0x00006C00
+#define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT)
+#define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */
#define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0
-#define I40E_VF_ARQBAL1_ARQBAL_MASK (0xFFFFFFFF << I40E_VF_ARQBAL1_ARQBAL_SHIFT)
-#define I40E_VF_ARQH1 0x00007400
+#define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT)
+#define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */
#define I40E_VF_ARQH1_ARQH_SHIFT 0
-#define I40E_VF_ARQH1_ARQH_MASK (0x3FF << I40E_VF_ARQH1_ARQH_SHIFT)
-#define I40E_VF_ARQLEN1 0x00008000
+#define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT)
+#define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */
#define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0
-#define I40E_VF_ARQLEN1_ARQLEN_MASK (0x3FF << I40E_VF_ARQLEN1_ARQLEN_SHIFT)
+#define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT)
#define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28
-#define I40E_VF_ARQLEN1_ARQVFE_MASK (0x1 << I40E_VF_ARQLEN1_ARQVFE_SHIFT)
+#define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT)
#define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29
-#define I40E_VF_ARQLEN1_ARQOVFL_MASK (0x1 << I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
+#define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT)
#define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30
-#define I40E_VF_ARQLEN1_ARQCRIT_MASK (0x1 << I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
+#define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT)
#define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31
-#define I40E_VF_ARQLEN1_ARQENABLE_MASK (0x1 << I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
-#define I40E_VF_ARQT1 0x00007000
+#define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT)
+#define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */
#define I40E_VF_ARQT1_ARQT_SHIFT 0
-#define I40E_VF_ARQT1_ARQT_MASK (0x3FF << I40E_VF_ARQT1_ARQT_SHIFT)
-#define I40E_VF_ATQBAH1 0x00007800
+#define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT)
+#define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */
#define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0
-#define I40E_VF_ATQBAH1_ATQBAH_MASK (0xFFFFFFFF << I40E_VF_ATQBAH1_ATQBAH_SHIFT)
-#define I40E_VF_ATQBAL1 0x00007C00
+#define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT)
+#define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */
#define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0
-#define I40E_VF_ATQBAL1_ATQBAL_MASK (0xFFFFFFFF << I40E_VF_ATQBAL1_ATQBAL_SHIFT)
-#define I40E_VF_ATQH1 0x00006400
+#define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT)
+#define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */
#define I40E_VF_ATQH1_ATQH_SHIFT 0
-#define I40E_VF_ATQH1_ATQH_MASK (0x3FF << I40E_VF_ATQH1_ATQH_SHIFT)
-#define I40E_VF_ATQLEN1 0x00006800
+#define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT)
+#define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */
#define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0
-#define I40E_VF_ATQLEN1_ATQLEN_MASK (0x3FF << I40E_VF_ATQLEN1_ATQLEN_SHIFT)
+#define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT)
#define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28
-#define I40E_VF_ATQLEN1_ATQVFE_MASK (0x1 << I40E_VF_ATQLEN1_ATQVFE_SHIFT)
+#define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT)
#define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29
-#define I40E_VF_ATQLEN1_ATQOVFL_MASK (0x1 << I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
+#define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT)
#define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30
-#define I40E_VF_ATQLEN1_ATQCRIT_MASK (0x1 << I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
+#define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT)
#define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31
-#define I40E_VF_ATQLEN1_ATQENABLE_MASK (0x1 << I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
-#define I40E_VF_ATQT1 0x00008400
+#define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT)
+#define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */
#define I40E_VF_ATQT1_ATQT_SHIFT 0
-#define I40E_VF_ATQT1_ATQT_MASK (0x3FF << I40E_VF_ATQT1_ATQT_SHIFT)
-#define I40E_VFGEN_RSTAT 0x00008800
+#define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT)
+#define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */
#define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0
-#define I40E_VFGEN_RSTAT_VFR_STATE_MASK (0x3 << I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
-#define I40E_VFINT_DYN_CTL01 0x00005C00
+#define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT)
+#define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */
#define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTL01_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
-#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4))
+#define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT)
+#define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15
#define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0
-#define I40E_VFINT_DYN_CTLN1_INTENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1
-#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
-#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT)
#define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3
-#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5
-#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK (0xFFF << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK (0x1 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT)
#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25
-#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK (0x3 << I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
+#define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT)
#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31
-#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK (0x1 << I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
-#define I40E_VFINT_ICR0_ENA1 0x00005000
+#define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT)
+#define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */
#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK (0x1 << I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31
-#define I40E_VFINT_ICR0_ENA1_RSVD_MASK (0x1 << I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
-#define I40E_VFINT_ICR01 0x00004800
+#define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT)
+#define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */
#define I40E_VFINT_ICR01_INTEVENT_SHIFT 0
-#define I40E_VFINT_ICR01_INTEVENT_MASK (0x1 << I40E_VFINT_ICR01_INTEVENT_SHIFT)
+#define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1
-#define I40E_VFINT_ICR01_QUEUE_0_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_0_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2
-#define I40E_VFINT_ICR01_QUEUE_1_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_1_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3
-#define I40E_VFINT_ICR01_QUEUE_2_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_2_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT)
#define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4
-#define I40E_VFINT_ICR01_QUEUE_3_MASK (0x1 << I40E_VFINT_ICR01_QUEUE_3_SHIFT)
+#define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT)
#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25
-#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK (0x1 << I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
+#define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT)
#define I40E_VFINT_ICR01_ADMINQ_SHIFT 30
-#define I40E_VFINT_ICR01_ADMINQ_MASK (0x1 << I40E_VFINT_ICR01_ADMINQ_SHIFT)
+#define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT)
#define I40E_VFINT_ICR01_SWINT_SHIFT 31
-#define I40E_VFINT_ICR01_SWINT_MASK (0x1 << I40E_VFINT_ICR01_SWINT_SHIFT)
-#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */
+#define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT)
+#define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */
#define I40E_VFINT_ITR01_MAX_INDEX 2
#define I40E_VFINT_ITR01_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITR01_INTERVAL_MASK (0xFFF << I40E_VFINT_ITR01_INTERVAL_SHIFT)
-#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4))
+#define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT)
+#define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */
#define I40E_VFINT_ITRN1_MAX_INDEX 2
#define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0
-#define I40E_VFINT_ITRN1_INTERVAL_MASK (0xFFF << I40E_VFINT_ITRN1_INTERVAL_SHIFT)
-#define I40E_VFINT_STAT_CTL01 0x00005400
+#define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT)
+#define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: VFR */
#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2
-#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK (0x3 << I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
-#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT)
+#define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_QRX_TAIL1_MAX_INDEX 15
#define I40E_QRX_TAIL1_TAIL_SHIFT 0
-#define I40E_QRX_TAIL1_TAIL_MASK (0x1FFF << I40E_QRX_TAIL1_TAIL_SHIFT)
-#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */
+#define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT)
+#define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */
#define I40E_QTX_TAIL1_MAX_INDEX 15
#define I40E_QTX_TAIL1_TAIL_SHIFT 0
-#define I40E_QTX_TAIL1_TAIL_MASK (0x1FFF << I40E_QTX_TAIL1_TAIL_SHIFT)
-#define I40E_VFMSIX_PBA 0x00002000
+#define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT)
+#define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */
#define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
-#define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT)
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TADD_MAX_INDEX 16
#define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
-#define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
+#define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
#define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
-#define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TMSG_MAX_INDEX 16
#define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
-#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TUADD_MAX_INDEX 16
#define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
-#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */
#define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
#define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
-#define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
-#define I40E_VFCM_PE_ERRDATA 0x0000DC00
+#define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT)
+#define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */
#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0
-#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK (0xF << I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT)
#define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4
-#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK (0x7 << I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
+#define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT)
#define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8
-#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK (0x3FFFF << I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
-#define I40E_VFCM_PE_ERRINFO 0x0000D800
+#define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT)
+#define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */
#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0
-#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK (0x1 << I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT)
#define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4
-#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK (0x7 << I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT)
#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8
-#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16
-#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
+#define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT)
#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24
-#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK (0xFF << I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
-#define I40E_VFPE_AEQALLOC1 0x0000A400
-#define I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT 0
-#define I40E_VFPE_AEQALLOC1_AECOUNT_MASK (0xFFFFFFFF << I40E_VFPE_AEQALLOC1_AECOUNT_SHIFT)
-#define I40E_VFPE_CCQPHIGH1 0x00009800
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT 0
-#define I40E_VFPE_CCQPHIGH1_PECCQPHIGH_MASK (0xFFFFFFFF << I40E_VFPE_CCQPHIGH1_PECCQPHIGH_SHIFT)
-#define I40E_VFPE_CCQPLOW1 0x0000AC00
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT 0
-#define I40E_VFPE_CCQPLOW1_PECCQPLOW_MASK (0xFFFFFFFF << I40E_VFPE_CCQPLOW1_PECCQPLOW_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1 0x0000B800
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT 0
-#define I40E_VFPE_CCQPSTATUS1_CCQP_DONE_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_DONE_SHIFT)
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT 31
-#define I40E_VFPE_CCQPSTATUS1_CCQP_ERR_MASK (0x1 << I40E_VFPE_CCQPSTATUS1_CCQP_ERR_SHIFT)
-#define I40E_VFPE_CQACK1 0x0000B000
-#define I40E_VFPE_CQACK1_PECQID_SHIFT 0
-#define I40E_VFPE_CQACK1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQACK1_PECQID_SHIFT)
-#define I40E_VFPE_CQARM1 0x0000B400
-#define I40E_VFPE_CQARM1_PECQID_SHIFT 0
-#define I40E_VFPE_CQARM1_PECQID_MASK (0x1FFFF << I40E_VFPE_CQARM1_PECQID_SHIFT)
-#define I40E_VFPE_CQPDB1 0x0000BC00
-#define I40E_VFPE_CQPDB1_WQHEAD_SHIFT 0
-#define I40E_VFPE_CQPDB1_WQHEAD_MASK (0x7FF << I40E_VFPE_CQPDB1_WQHEAD_SHIFT)
-#define I40E_VFPE_CQPERRCODES1 0x00009C00
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT 0
-#define I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MINOR_CODE_SHIFT)
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT 16
-#define I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_MASK (0xFFFF << I40E_VFPE_CQPERRCODES1_CQP_MAJOR_CODE_SHIFT)
-#define I40E_VFPE_CQPTAIL1 0x0000A000
-#define I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT 0
-#define I40E_VFPE_CQPTAIL1_WQTAIL_MASK (0x7FF << I40E_VFPE_CQPTAIL1_WQTAIL_SHIFT)
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT 31
-#define I40E_VFPE_CQPTAIL1_CQP_OP_ERR_MASK (0x1 << I40E_VFPE_CQPTAIL1_CQP_OP_ERR_SHIFT)
-#define I40E_VFPE_IPCONFIG01 0x00008C00
-#define I40E_VFPE_IPCONFIG01_PEIPID_SHIFT 0
-#define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
-#define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_MRTEIDXMASK1 0x00009000
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
-#define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
-#define I40E_VFPE_RCVUNEXPECTEDERROR1 0x00009400
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT 0
-#define I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_MASK (0xFFFFFF << I40E_VFPE_RCVUNEXPECTEDERROR1_TCP_RX_UNEXP_ERR_SHIFT)
-#define I40E_VFPE_TCPNOWTIMER1 0x0000A800
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT 0
-#define I40E_VFPE_TCPNOWTIMER1_TCP_NOW_MASK (0xFFFFFFFF << I40E_VFPE_TCPNOWTIMER1_TCP_NOW_SHIFT)
-#define I40E_VFPE_WQEALLOC1 0x0000C000
-#define I40E_VFPE_WQEALLOC1_PEQPID_SHIFT 0
-#define I40E_VFPE_WQEALLOC1_PEQPID_MASK (0x3FFFF << I40E_VFPE_WQEALLOC1_PEQPID_SHIFT)
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT 20
-#define I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_MASK (0xFFF << I40E_VFPE_WQEALLOC1_WQE_DESC_INDEX_SHIFT)
-#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */
+#define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT)
+#define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */
#define I40E_VFQF_HENA_MAX_INDEX 1
#define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0
-#define I40E_VFQF_HENA_PTYPE_ENA_MASK (0xFFFFFFFF << I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
-#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */
+#define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT)
+#define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */
#define I40E_VFQF_HKEY_MAX_INDEX 12
#define I40E_VFQF_HKEY_KEY_0_SHIFT 0
-#define I40E_VFQF_HKEY_KEY_0_MASK (0xFF << I40E_VFQF_HKEY_KEY_0_SHIFT)
+#define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT)
#define I40E_VFQF_HKEY_KEY_1_SHIFT 8
-#define I40E_VFQF_HKEY_KEY_1_MASK (0xFF << I40E_VFQF_HKEY_KEY_1_SHIFT)
+#define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT)
#define I40E_VFQF_HKEY_KEY_2_SHIFT 16
-#define I40E_VFQF_HKEY_KEY_2_MASK (0xFF << I40E_VFQF_HKEY_KEY_2_SHIFT)
+#define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT)
#define I40E_VFQF_HKEY_KEY_3_SHIFT 24
-#define I40E_VFQF_HKEY_KEY_3_MASK (0xFF << I40E_VFQF_HKEY_KEY_3_SHIFT)
-#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */
+#define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT)
+#define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */
#define I40E_VFQF_HLUT_MAX_INDEX 15
#define I40E_VFQF_HLUT_LUT0_SHIFT 0
-#define I40E_VFQF_HLUT_LUT0_MASK (0xF << I40E_VFQF_HLUT_LUT0_SHIFT)
+#define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT)
#define I40E_VFQF_HLUT_LUT1_SHIFT 8
-#define I40E_VFQF_HLUT_LUT1_MASK (0xF << I40E_VFQF_HLUT_LUT1_SHIFT)
+#define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT)
#define I40E_VFQF_HLUT_LUT2_SHIFT 16
-#define I40E_VFQF_HLUT_LUT2_MASK (0xF << I40E_VFQF_HLUT_LUT2_SHIFT)
+#define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT)
#define I40E_VFQF_HLUT_LUT3_SHIFT 24
-#define I40E_VFQF_HLUT_LUT3_MASK (0xF << I40E_VFQF_HLUT_LUT3_SHIFT)
-#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */
+#define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT)
+#define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */
#define I40E_VFQF_HREGION_MAX_INDEX 7
#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT)
#define I40E_VFQF_HREGION_REGION_0_SHIFT 1
-#define I40E_VFQF_HREGION_REGION_0_MASK (0x7 << I40E_VFQF_HREGION_REGION_0_SHIFT)
+#define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT)
#define I40E_VFQF_HREGION_REGION_1_SHIFT 5
-#define I40E_VFQF_HREGION_REGION_1_MASK (0x7 << I40E_VFQF_HREGION_REGION_1_SHIFT)
+#define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT)
#define I40E_VFQF_HREGION_REGION_2_SHIFT 9
-#define I40E_VFQF_HREGION_REGION_2_MASK (0x7 << I40E_VFQF_HREGION_REGION_2_SHIFT)
+#define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT)
#define I40E_VFQF_HREGION_REGION_3_SHIFT 13
-#define I40E_VFQF_HREGION_REGION_3_MASK (0x7 << I40E_VFQF_HREGION_REGION_3_SHIFT)
+#define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT)
#define I40E_VFQF_HREGION_REGION_4_SHIFT 17
-#define I40E_VFQF_HREGION_REGION_4_MASK (0x7 << I40E_VFQF_HREGION_REGION_4_SHIFT)
+#define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT)
#define I40E_VFQF_HREGION_REGION_5_SHIFT 21
-#define I40E_VFQF_HREGION_REGION_5_MASK (0x7 << I40E_VFQF_HREGION_REGION_5_SHIFT)
+#define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT)
#define I40E_VFQF_HREGION_REGION_6_SHIFT 25
-#define I40E_VFQF_HREGION_REGION_6_MASK (0x7 << I40E_VFQF_HREGION_REGION_6_SHIFT)
+#define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT)
#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28
-#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
+#define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
#define I40E_VFQF_HREGION_REGION_7_SHIFT 29
-#define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
-#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
+#define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT)
#endif
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 48ebb6cd69f2..79bf96ca6489 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -50,7 +50,11 @@ static void i40e_unmap_and_free_tx_resource(struct i40e_ring *ring,
struct i40e_tx_buffer *tx_buffer)
{
if (tx_buffer->skb) {
- dev_kfree_skb_any(tx_buffer->skb);
+ if (tx_buffer->tx_flags & I40E_TX_FLAGS_FD_SB)
+ kfree(tx_buffer->raw_buf);
+ else
+ dev_kfree_skb_any(tx_buffer->skb);
+
if (dma_unmap_len(tx_buffer, len))
dma_unmap_single(ring->dev,
dma_unmap_addr(tx_buffer, dma),
@@ -769,8 +773,6 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
/* likely incorrect csum if alternate IP extension headers found */
if (ipv6 &&
- decoded.inner_prot == I40E_RX_PTYPE_INNER_PROT_TCP &&
- rx_error & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT) &&
rx_status & (1 << I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT))
/* don't increment checksum err here, non-fatal err */
return;
@@ -1336,6 +1338,7 @@ static void i40e_create_tx_ctx(struct i40e_ring *tx_ring,
/* cpu_to_le32 and assign to struct fields */
context_desc->tunneling_params = cpu_to_le32(cd_tunneling);
context_desc->l2tag2 = cpu_to_le16(cd_l2tag2);
+ context_desc->rsvd = cpu_to_le16(0);
context_desc->type_cmd_tso_mss = cpu_to_le64(cd_type_cmd_tso_mss);
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
index 30d248bc5d19..8bc6858163b0 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
@@ -75,7 +75,6 @@ enum i40e_dyn_idx_t {
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \
- ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
@@ -131,6 +130,7 @@ enum i40e_dyn_idx_t {
#define I40E_TX_FLAGS_IPV6 (u32)(1 << 5)
#define I40E_TX_FLAGS_FCCRC (u32)(1 << 6)
#define I40E_TX_FLAGS_FSO (u32)(1 << 7)
+#define I40E_TX_FLAGS_FD_SB (u32)(1 << 9)
#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000
#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000
#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29
@@ -139,7 +139,10 @@ enum i40e_dyn_idx_t {
struct i40e_tx_buffer {
struct i40e_tx_desc *next_to_watch;
unsigned long time_stamp;
- struct sk_buff *skb;
+ union {
+ struct sk_buff *skb;
+ void *raw_buf;
+ };
unsigned int bytecount;
unsigned short gso_segs;
DEFINE_DMA_UNMAP_ADDR(dma);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index d3cf5a69de54..15376436cead 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -50,6 +50,9 @@
(d) == I40E_DEV_ID_QSFP_B || \
(d) == I40E_DEV_ID_QSFP_C)
+/* I40E_MASK is a macro used on 32 bit registers */
+#define I40E_MASK(mask, shift) (mask << shift)
+
#define I40E_MAX_VSI_QP 16
#define I40E_MAX_VF_VSI 3
#define I40E_MAX_CHAINED_RX_BUFFERS 5
@@ -137,6 +140,14 @@ enum i40e_fc_mode {
I40E_FC_DEFAULT
};
+enum i40e_set_fc_aq_failures {
+ I40E_SET_FC_AQ_FAIL_NONE = 0,
+ I40E_SET_FC_AQ_FAIL_GET = 1,
+ I40E_SET_FC_AQ_FAIL_SET = 2,
+ I40E_SET_FC_AQ_FAIL_UPDATE = 4,
+ I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6
+};
+
enum i40e_vsi_type {
I40E_VSI_MAIN = 0,
I40E_VSI_VMDQ1,
@@ -163,6 +174,7 @@ struct i40e_link_status {
u8 an_info;
u8 ext_info;
u8 loopback;
+ bool an_enabled;
/* is Link Status Event notification to SW enabled */
bool lse_enable;
u16 max_frame_size;
@@ -256,6 +268,61 @@ struct i40e_nvm_info {
u32 eetrack; /* NVM data version */
};
+/* definitions used in NVM update support */
+
+enum i40e_nvmupd_cmd {
+ I40E_NVMUPD_INVALID,
+ I40E_NVMUPD_READ_CON,
+ I40E_NVMUPD_READ_SNT,
+ I40E_NVMUPD_READ_LCB,
+ I40E_NVMUPD_READ_SA,
+ I40E_NVMUPD_WRITE_ERA,
+ I40E_NVMUPD_WRITE_CON,
+ I40E_NVMUPD_WRITE_SNT,
+ I40E_NVMUPD_WRITE_LCB,
+ I40E_NVMUPD_WRITE_SA,
+ I40E_NVMUPD_CSUM_CON,
+ I40E_NVMUPD_CSUM_SA,
+ I40E_NVMUPD_CSUM_LCB,
+};
+
+enum i40e_nvmupd_state {
+ I40E_NVMUPD_STATE_INIT,
+ I40E_NVMUPD_STATE_READING,
+ I40E_NVMUPD_STATE_WRITING
+};
+
+/* nvm_access definition and its masks/shifts need to be accessible to
+ * application, core driver, and shared code. Where is the right file?
+ */
+#define I40E_NVM_READ 0xB
+#define I40E_NVM_WRITE 0xC
+
+#define I40E_NVM_MOD_PNT_MASK 0xFF
+
+#define I40E_NVM_TRANS_SHIFT 8
+#define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT)
+#define I40E_NVM_CON 0x0
+#define I40E_NVM_SNT 0x1
+#define I40E_NVM_LCB 0x2
+#define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB)
+#define I40E_NVM_ERA 0x4
+#define I40E_NVM_CSUM 0x8
+
+#define I40E_NVM_ADAPT_SHIFT 16
+#define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT)
+
+#define I40E_NVMUPD_MAX_DATA 4096
+#define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */
+
+struct i40e_nvm_access {
+ u32 command;
+ u32 config;
+ u32 offset; /* in bytes */
+ u32 data_size; /* in bytes */
+ u8 data[1];
+};
+
/* PCI bus types */
enum i40e_bus_type {
i40e_bus_type_unknown = 0,
@@ -391,6 +458,9 @@ struct i40e_hw {
/* Admin Queue info */
struct i40e_adminq_info aq;
+ /* state of nvm update process */
+ enum i40e_nvmupd_state nvmupd_state;
+
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
@@ -875,7 +945,6 @@ enum i40e_filter_pctype {
I40E_FILTER_PCTYPE_FRAG_IPV4 = 36,
/* Note: Values 37-40 are reserved for future use */
I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41,
- I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN = 42,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43,
I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44,
I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45,
@@ -1162,4 +1231,7 @@ enum i40e_reset_type {
I40E_RESET_GLOBR = 2,
I40E_RESET_EMPR = 3,
};
+
+/* RSS Hash Table Size */
+#define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000
#endif /* _I40E_TYPE_H_ */
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 60407a9df0c1..efee6b290c0f 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -193,7 +193,7 @@ static void i40evf_set_msglevel(struct net_device *netdev, u32 data)
}
/**
- * i40evf_get_drvinto - Get driver info
+ * i40evf_get_drvinfo - Get driver info
* @netdev: network interface device structure
* @drvinfo: ethool driver info structure
*
@@ -632,7 +632,7 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
u32 hlut_val;
int i, j;
- for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX; i++) {
+ for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
hlut_val = rd32(hw, I40E_VFQF_HLUT(i));
indir[j++] = hlut_val & 0xff;
indir[j++] = (hlut_val >> 8) & 0xff;
@@ -659,7 +659,7 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
u32 hlut_val;
int i, j;
- for (i = 0, j = 0; i < I40E_VFQF_HLUT_MAX_INDEX + 1; i++) {
+ for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
hlut_val = indir[j++];
hlut_val |= indir[j++] << 8;
hlut_val |= indir[j++] << 16;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 7fc5f3b5d6bf..38429fae4fcf 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -34,9 +34,9 @@ static int i40evf_close(struct net_device *netdev);
char i40evf_driver_name[] = "i40evf";
static const char i40evf_driver_string[] =
- "Intel(R) XL710 X710 Virtual Function Network Driver";
+ "Intel(R) XL710/X710 Virtual Function Network Driver";
-#define DRV_VERSION "0.9.34"
+#define DRV_VERSION "0.9.40"
const char i40evf_driver_version[] = DRV_VERSION;
static const char i40evf_copyright[] =
"Copyright (c) 2013 - 2014 Intel Corporation.";
@@ -49,7 +49,7 @@ static const char i40evf_copyright[] =
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(i40evf_pci_tbl) = {
+static const struct pci_device_id i40evf_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_VF), 0},
/* required last entry */
{0, }
@@ -260,6 +260,12 @@ static void i40evf_fire_sw_int(struct i40evf_adapter *adapter,
int i;
uint32_t dyn_ctl;
+ if (mask & 1) {
+ dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTL01);
+ dyn_ctl |= I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK |
+ I40E_VFINT_DYN_CTLN_CLEARPBA_MASK;
+ wr32(hw, I40E_VFINT_DYN_CTL01, dyn_ctl);
+ }
for (i = 1; i < adapter->num_msix_vectors; i++) {
if (mask & (1 << i)) {
dyn_ctl = rd32(hw, I40E_VFINT_DYN_CTLN1(i - 1));
@@ -278,6 +284,7 @@ void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush)
{
struct i40e_hw *hw = &adapter->hw;
+ i40evf_misc_irq_enable(adapter);
i40evf_irq_enable_queues(adapter, ~0);
if (flush)
@@ -520,7 +527,8 @@ static int i40evf_request_misc_irq(struct i40evf_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int err;
- sprintf(adapter->misc_vector_name, "i40evf:mbx");
+ snprintf(adapter->misc_vector_name,
+ sizeof(adapter->misc_vector_name) - 1, "i40evf:mbx");
err = request_irq(adapter->msix_entries[0].vector,
&i40evf_msix_aq, 0,
adapter->misc_vector_name, netdev);
@@ -761,7 +769,7 @@ i40evf_mac_filter *i40evf_add_filter(struct i40evf_adapter *adapter,
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section))
- mdelay(1);
+ udelay(1);
f = i40evf_find_filter(adapter, macaddr);
if (NULL == f) {
@@ -833,7 +841,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev)
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section))
- mdelay(1);
+ udelay(1);
/* remove filter if not in netdev list */
list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
bool found = false;
@@ -1290,12 +1298,16 @@ static void i40evf_watchdog_task(struct work_struct *work)
struct i40evf_adapter,
watchdog_task);
struct i40e_hw *hw = &adapter->hw;
+ uint32_t rstat_val;
if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section))
goto restart_watchdog;
if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) {
- if ((rd32(hw, I40E_VFGEN_RSTAT) & 0x3) == I40E_VFR_VFACTIVE) {
+ rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if ((rstat_val == I40E_VFR_VFACTIVE) ||
+ (rstat_val == I40E_VFR_COMPLETED)) {
/* A chance for redemption! */
dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n");
adapter->state = __I40EVF_STARTUP;
@@ -1321,8 +1333,11 @@ static void i40evf_watchdog_task(struct work_struct *work)
goto watchdog_done;
/* check for reset */
+ rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) &&
- (rd32(hw, I40E_VFGEN_RSTAT) & 0x3) != I40E_VFR_VFACTIVE) {
+ (rstat_val != I40E_VFR_VFACTIVE) &&
+ (rstat_val != I40E_VFR_COMPLETED)) {
adapter->state = __I40EVF_RESETTING;
adapter->flags |= I40EVF_FLAG_RESET_PENDING;
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
@@ -1388,6 +1403,8 @@ static void i40evf_watchdog_task(struct work_struct *work)
watchdog_done:
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
restart_watchdog:
+ if (adapter->state == __I40EVF_REMOVE)
+ return;
if (adapter->aq_required)
mod_timer(&adapter->watchdog_timer,
jiffies + msecs_to_jiffies(20));
@@ -1488,7 +1505,8 @@ static void i40evf_reset_task(struct work_struct *work)
for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if (rstat_val != I40E_VFR_VFACTIVE)
+ if ((rstat_val != I40E_VFR_VFACTIVE) &&
+ (rstat_val != I40E_VFR_COMPLETED))
break;
else
msleep(I40EVF_RESET_WAIT_MS);
@@ -1502,12 +1520,16 @@ static void i40evf_reset_task(struct work_struct *work)
for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
rstat_val = rd32(hw, I40E_VFGEN_RSTAT) &
I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- if (rstat_val == I40E_VFR_VFACTIVE)
+ if ((rstat_val == I40E_VFR_VFACTIVE) ||
+ (rstat_val == I40E_VFR_COMPLETED))
break;
else
msleep(I40EVF_RESET_WAIT_MS);
}
if (i == I40EVF_RESET_WAIT_COUNT) {
+ struct i40evf_mac_filter *f, *ftmp;
+ struct i40evf_vlan_filter *fv, *fvtmp;
+
/* reset never finished */
dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
rstat_val);
@@ -1520,9 +1542,23 @@ static void i40evf_reset_task(struct work_struct *work)
i40evf_free_all_tx_resources(adapter);
i40evf_free_all_rx_resources(adapter);
}
+
+ /* Delete all of the filters, both MAC and VLAN. */
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list,
+ list) {
+ list_del(&f->list);
+ kfree(f);
+ }
+ list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list,
+ list) {
+ list_del(&fv->list);
+ kfree(fv);
+ }
+
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
i40evf_free_queues(adapter);
+ i40evf_free_q_vectors(adapter);
kfree(adapter->vf_res);
i40evf_shutdown_adminq(hw);
adapter->netdev->flags &= ~IFF_UP;
@@ -1939,8 +1975,10 @@ static int i40evf_check_reset_complete(struct i40e_hw *hw)
int i;
for (i = 0; i < 100; i++) {
- rstat = rd32(hw, I40E_VFGEN_RSTAT);
- if (rstat == I40E_VFR_VFACTIVE)
+ rstat = rd32(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ if ((rstat == I40E_VFR_VFACTIVE) ||
+ (rstat == I40E_VFR_COMPLETED))
return 0;
udelay(10);
}
@@ -2006,7 +2044,6 @@ static void i40evf_init_task(struct work_struct *work)
}
adapter->state = __I40EVF_INIT_VERSION_CHECK;
goto restart;
- break;
case __I40EVF_INIT_VERSION_CHECK:
if (!i40evf_asq_done(hw)) {
dev_err(&pdev->dev, "Admin queue command never completed\n");
@@ -2018,17 +2055,20 @@ static void i40evf_init_task(struct work_struct *work)
if (err) {
dev_info(&pdev->dev, "Unable to verify API version (%d), retrying\n",
err);
+ if (err == I40E_ERR_ADMIN_QUEUE_NO_WORK) {
+ dev_info(&pdev->dev, "Resending request\n");
+ err = i40evf_send_api_ver(adapter);
+ }
goto err;
}
err = i40evf_send_vf_config_msg(adapter);
if (err) {
- dev_err(&pdev->dev, "Unable send config request (%d)\n",
+ dev_err(&pdev->dev, "Unable to send config request (%d)\n",
err);
goto err;
}
adapter->state = __I40EVF_INIT_GET_RESOURCES;
goto restart;
- break;
case __I40EVF_INIT_GET_RESOURCES:
/* aq msg sent, awaiting reply */
if (!adapter->vf_res) {
@@ -2097,8 +2137,6 @@ static void i40evf_init_task(struct work_struct *work)
ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr);
- INIT_LIST_HEAD(&adapter->mac_filter_list);
- INIT_LIST_HEAD(&adapter->vlan_filter_list);
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (NULL == f)
goto err_sw_init;
@@ -2280,6 +2318,9 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
hw->bus.device = PCI_SLOT(pdev->devfn);
hw->bus.func = PCI_FUNC(pdev->devfn);
+ INIT_LIST_HEAD(&adapter->mac_filter_list);
+ INIT_LIST_HEAD(&adapter->vlan_filter_list);
+
INIT_WORK(&adapter->reset_task, i40evf_reset_task);
INIT_WORK(&adapter->adminq_task, i40evf_adminq_task);
INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task);
@@ -2391,6 +2432,7 @@ static void i40evf_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct i40evf_adapter *adapter = netdev_priv(netdev);
+ struct i40evf_mac_filter *f, *ftmp;
struct i40e_hw *hw = &adapter->hw;
cancel_delayed_work_sync(&adapter->init_task);
@@ -2406,9 +2448,12 @@ static void i40evf_remove(struct pci_dev *pdev)
i40evf_misc_irq_disable(adapter);
i40evf_free_misc_irq(adapter);
i40evf_reset_interrupt_capability(adapter);
+ i40evf_free_q_vectors(adapter);
}
- del_timer_sync(&adapter->watchdog_timer);
+ if (adapter->watchdog_timer.function)
+ del_timer_sync(&adapter->watchdog_timer);
+
flush_scheduled_work();
if (hw->aq.asq.count)
@@ -2419,6 +2464,13 @@ static void i40evf_remove(struct pci_dev *pdev)
i40evf_free_queues(adapter);
kfree(adapter->vf_res);
+ /* If we got removed before an up/down sequence, we've got a filter
+ * hanging out there that we need to get rid of.
+ */
+ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+ list_del(&f->list);
+ kfree(f);
+ }
free_netdev(netdev);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index 2dc0bac76717..66d12f5b4ca8 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -80,8 +80,9 @@ int i40evf_send_api_ver(struct i40evf_adapter *adapter)
* @adapter: adapter structure
*
* Compare API versions with the PF. Must be called after admin queue is
- * initialized. Returns 0 if API versions match, -EIO if
- * they do not, or I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty.
+ * initialized. Returns 0 if API versions match, -EIO if they do not,
+ * I40E_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty, and any errors
+ * from the firmware are propagated.
**/
int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
{
@@ -102,13 +103,13 @@ int i40evf_verify_api_ver(struct i40evf_adapter *adapter)
goto out_alloc;
err = (i40e_status)le32_to_cpu(event.desc.cookie_low);
- if (err) {
- err = -EIO;
+ if (err)
goto out_alloc;
- }
if ((enum i40e_virtchnl_ops)le32_to_cpu(event.desc.cookie_high) !=
I40E_VIRTCHNL_OP_VERSION) {
+ dev_info(&adapter->pdev->dev, "Invalid reply type %d from PF\n",
+ le32_to_cpu(event.desc.cookie_high));
err = -EIO;
goto out_alloc;
}
@@ -247,11 +248,11 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter)
vqpi++;
}
+ adapter->aq_pending |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
(u8 *)vqci, len);
kfree(vqci);
- adapter->aq_pending |= I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_CONFIGURE_QUEUES;
}
/**
@@ -274,10 +275,10 @@ void i40evf_enable_queues(struct i40evf_adapter *adapter)
vqs.vsi_id = adapter->vsi_res->vsi_id;
vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
vqs.rx_queues = vqs.tx_queues;
- i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
- (u8 *)&vqs, sizeof(vqs));
adapter->aq_pending |= I40EVF_FLAG_AQ_ENABLE_QUEUES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_QUEUES;
+ i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
+ (u8 *)&vqs, sizeof(vqs));
}
/**
@@ -300,10 +301,10 @@ void i40evf_disable_queues(struct i40evf_adapter *adapter)
vqs.vsi_id = adapter->vsi_res->vsi_id;
vqs.tx_queues = (1 << adapter->vsi_res->num_queue_pairs) - 1;
vqs.rx_queues = vqs.tx_queues;
- i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
- (u8 *)&vqs, sizeof(vqs));
adapter->aq_pending |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_QUEUES;
+ i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DISABLE_QUEUES,
+ (u8 *)&vqs, sizeof(vqs));
}
/**
@@ -351,11 +352,11 @@ void i40evf_map_queues(struct i40evf_adapter *adapter)
vimi->vecmap[v_idx].txq_map = 0;
vimi->vecmap[v_idx].rxq_map = 0;
+ adapter->aq_pending |= I40EVF_FLAG_AQ_MAP_VECTORS;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
(u8 *)vimi, len);
kfree(vimi);
- adapter->aq_pending |= I40EVF_FLAG_AQ_MAP_VECTORS;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_MAP_VECTORS;
}
/**
@@ -412,12 +413,11 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
f->add = false;
}
}
+ adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
(u8 *)veal, len);
kfree(veal);
- adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_MAC_FILTER;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
-
}
/**
@@ -474,11 +474,11 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
kfree(f);
}
}
+ adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
+ adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
(u8 *)veal, len);
kfree(veal);
- adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
- adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
}
/**
@@ -535,10 +535,10 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
f->add = false;
}
}
- i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
- kfree(vvfl);
adapter->aq_pending |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
+ i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
+ kfree(vvfl);
}
/**
@@ -596,10 +596,10 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
kfree(f);
}
}
- i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
- kfree(vvfl);
adapter->aq_pending |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
+ i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
+ kfree(vvfl);
}
/**
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index ee74f9536b31..236a6183a865 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -579,7 +579,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
break;
default:
return -E1000_ERR_MAC_INIT;
- break;
}
/* Set media type */
@@ -837,7 +836,6 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
default:
ret_val = -E1000_ERR_PHY;
goto out;
- break;
}
ret_val = igb_get_phy_id(hw);
goto out;
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index f5ba4e4eafb9..6f0490d0e981 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -355,6 +355,7 @@
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
+#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
/* These act per VF so an array friendly macro is used */
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index a9537ba7a5a0..cb14bbdfb056 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -57,8 +57,8 @@
#include "igb.h"
#define MAJ 5
-#define MIN 0
-#define BUILD 5
+#define MIN 2
+#define BUILD 13
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
char igb_driver_name[] = "igb";
@@ -1630,6 +1630,8 @@ void igb_power_up_link(struct igb_adapter *adapter)
igb_power_up_phy_copper(&adapter->hw);
else
igb_power_up_serdes_link_82575(&adapter->hw);
+
+ igb_setup_link(&adapter->hw);
}
/**
@@ -4165,6 +4167,26 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event)
}
/**
+ * igb_check_lvmmc - check for malformed packets received
+ * and indicated in LVMMC register
+ * @adapter: pointer to adapter
+ **/
+static void igb_check_lvmmc(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 lvmmc;
+
+ lvmmc = rd32(E1000_LVMMC);
+ if (lvmmc) {
+ if (unlikely(net_ratelimit())) {
+ netdev_warn(adapter->netdev,
+ "malformed Tx packet detected and dropped, LVMMC:0x%08x\n",
+ lvmmc);
+ }
+ }
+}
+
+/**
* igb_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
**/
@@ -4359,6 +4381,11 @@ static void igb_watchdog_task(struct work_struct *work)
igb_spoof_check(adapter);
igb_ptp_rx_hang(adapter);
+ /* Check LVMMC register on i350/i354 only */
+ if ((adapter->hw.mac.type == e1000_i350) ||
+ (adapter->hw.mac.type == e1000_i354))
+ igb_check_lvmmc(adapter);
+
/* Reset the timer */
if (!test_bit(__IGB_DOWN, &adapter->state)) {
if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index d608599e123a..63c807c9b21c 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2853,7 +2853,7 @@ static const struct pci_error_handlers igbvf_err_handler = {
.resume = igbvf_io_resume,
};
-static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = {
+static const struct pci_device_id igbvf_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_VF), board_i350_vf },
{ } /* terminate list */
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 60801273915c..055961b0f24b 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -53,7 +53,7 @@ MODULE_PARM_DESC(copybreak,
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(ixgb_pci_tbl) = {
+static const struct pci_device_id ixgb_pci_tbl[] = {
{PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, IXGB_DEVICE_ID_82597EX_CX4,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
index 15609331ec17..c5c97b483d7c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -122,7 +122,7 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
- s32 ret_val = 0;
+ s32 ret_val;
u16 list_offset, data_offset;
/* Identify the PHY */
@@ -147,28 +147,23 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
/* Call SFP+ identify routine to get the SFP+ module type */
ret_val = phy->ops.identify_sfp(hw);
- if (ret_val != 0)
- goto out;
- else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
- ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
- goto out;
- }
+ if (ret_val)
+ return ret_val;
+ if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
/* Check to see if SFP+ module is supported */
ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
&list_offset,
&data_offset);
- if (ret_val != 0) {
- ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
- goto out;
- }
+ if (ret_val)
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
break;
default:
break;
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -183,7 +178,7 @@ static s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
{
u32 regval;
u32 i;
- s32 ret_val = 0;
+ s32 ret_val;
ret_val = ixgbe_start_hw_generic(hw);
@@ -203,11 +198,13 @@ static s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
}
+ if (ret_val)
+ return ret_val;
+
/* set the completion timeout for interface */
- if (ret_val == 0)
- ixgbe_set_pcie_completion_timeout(hw);
+ ixgbe_set_pcie_completion_timeout(hw);
- return ret_val;
+ return 0;
}
/**
@@ -222,7 +219,6 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg)
{
- s32 status = 0;
u32 autoc = 0;
/*
@@ -262,11 +258,10 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
break;
default:
- status = IXGBE_ERR_LINK_SETUP;
- break;
+ return IXGBE_ERR_LINK_SETUP;
}
- return status;
+ return 0;
}
/**
@@ -277,14 +272,12 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
**/
static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
{
- enum ixgbe_media_type media_type;
-
/* Detect if there is a copper PHY attached. */
switch (hw->phy.type) {
case ixgbe_phy_cu_unknown:
case ixgbe_phy_tn:
- media_type = ixgbe_media_type_copper;
- goto out;
+ return ixgbe_media_type_copper;
+
default:
break;
}
@@ -294,30 +287,27 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598:
case IXGBE_DEV_ID_82598_BX:
/* Default device ID is mezzanine card KX/KX4 */
- media_type = ixgbe_media_type_backplane;
- break;
+ return ixgbe_media_type_backplane;
+
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
case IXGBE_DEV_ID_82598EB_XF_LR:
case IXGBE_DEV_ID_82598EB_SFP_LOM:
- media_type = ixgbe_media_type_fiber;
- break;
+ return ixgbe_media_type_fiber;
+
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
- media_type = ixgbe_media_type_cx4;
- break;
+ return ixgbe_media_type_cx4;
+
case IXGBE_DEV_ID_82598AT:
case IXGBE_DEV_ID_82598AT2:
- media_type = ixgbe_media_type_copper;
- break;
+ return ixgbe_media_type_copper;
+
default:
- media_type = ixgbe_media_type_unknown;
- break;
+ return ixgbe_media_type_unknown;
}
-out:
- return media_type;
}
/**
@@ -328,7 +318,6 @@ out:
**/
static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
u32 fctrl_reg;
u32 rmcs_reg;
u32 reg;
@@ -338,10 +327,8 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
bool link_up;
/* Validate the water mark configuration */
- if (!hw->fc.pause_time) {
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
+ if (!hw->fc.pause_time)
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
/* Low water mark of zero causes XOFF floods */
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -350,8 +337,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
if (!hw->fc.low_water[i] ||
hw->fc.low_water[i] >= hw->fc.high_water[i]) {
hw_dbg(hw, "Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
}
}
}
@@ -428,9 +414,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
break;
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = IXGBE_ERR_CONFIG;
- goto out;
- break;
+ return IXGBE_ERR_CONFIG;
}
/* Set 802.3x based flow control settings. */
@@ -461,8 +445,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw)
/* Configure flow control refresh threshold value */
IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -598,7 +581,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
}
if (!*link_up)
- goto out;
+ return 0;
}
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
@@ -629,7 +612,6 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
(ixgbe_validate_link_ready(hw) != 0))
*link_up = false;
-out:
return 0;
}
@@ -646,7 +628,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
bool autoneg_wait_to_complete)
{
bool autoneg = false;
- s32 status = 0;
ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 autoc = curr_autoc;
@@ -657,7 +638,7 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
speed &= link_capabilities;
if (speed == IXGBE_LINK_SPEED_UNKNOWN)
- status = IXGBE_ERR_LINK_SETUP;
+ return IXGBE_ERR_LINK_SETUP;
/* Set KX4/KX support according to speed requested */
else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
@@ -671,17 +652,11 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
}
- if (status == 0) {
- /*
- * Setup and restart the link based on the new values in
- * ixgbe_hw This will write the AUTOC register based on the new
- * stored values
- */
- status = ixgbe_start_mac_link_82598(hw,
- autoneg_wait_to_complete);
- }
-
- return status;
+ /* Setup and restart the link based on the new values in
+ * ixgbe_hw This will write the AUTOC register based on the new
+ * stored values
+ */
+ return ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
}
@@ -718,7 +693,7 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
**/
static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
{
- s32 status = 0;
+ s32 status;
s32 phy_status = 0;
u32 ctrl;
u32 gheccr;
@@ -728,8 +703,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
/* Call adapter stop to disable tx/rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw);
- if (status != 0)
- goto reset_hw_out;
+ if (status)
+ return status;
/*
* Power up the Atlas Tx lanes if they are currently powered down.
@@ -771,7 +746,7 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
/* Init PHY and function pointers, perform SFP setup */
phy_status = hw->phy.ops.init(hw);
if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
+ return phy_status;
if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
goto mac_reset_top;
@@ -837,7 +812,6 @@ mac_reset_top:
*/
hw->mac.ops.init_rx_addrs(hw);
-reset_hw_out:
if (phy_status)
status = phy_status;
@@ -1110,106 +1084,6 @@ static s32 ixgbe_read_i2c_sff8472_82598(struct ixgbe_hw *hw, u8 byte_offset,
}
/**
- * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
- * @hw: pointer to hardware structure
- *
- * Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
-{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
- u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
- u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
- u16 ext_ability = 0;
-
- hw->phy.ops.identify(hw);
-
- /* Copper PHY must be checked before AUTOC LMS to determine correct
- * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
- switch (hw->phy.type) {
- case ixgbe_phy_tn:
- case ixgbe_phy_cu_unknown:
- hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE,
- MDIO_MMD_PMAPMD, &ext_ability);
- if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
- physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
- goto out;
- default:
- break;
- }
-
- switch (autoc & IXGBE_AUTOC_LMS_MASK) {
- case IXGBE_AUTOC_LMS_1G_AN:
- case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
- if (pma_pmd_1g == IXGBE_AUTOC_1G_KX)
- physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
- else
- physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
- break;
- case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
- if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
- else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
- else /* XAUI */
- physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
- break;
- case IXGBE_AUTOC_LMS_KX4_AN:
- case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
- if (autoc & IXGBE_AUTOC_KX_SUPP)
- physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
- if (autoc & IXGBE_AUTOC_KX4_SUPP)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
- break;
- default:
- break;
- }
-
- if (hw->phy.type == ixgbe_phy_nl) {
- hw->phy.ops.identify_sfp(hw);
-
- switch (hw->phy.sfp_type) {
- case ixgbe_sfp_type_da_cu:
- physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
- break;
- case ixgbe_sfp_type_sr:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
- break;
- case ixgbe_sfp_type_lr:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
- break;
- default:
- physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
- break;
- }
- }
-
- switch (hw->device_id) {
- case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
- physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
- break;
- case IXGBE_DEV_ID_82598AF_DUAL_PORT:
- case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
- case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
- break;
- case IXGBE_DEV_ID_82598EB_XF_LR:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
- break;
- default:
- break;
- }
-
-out:
- return physical_layer;
-}
-
-/**
* ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple
* port devices.
* @hw: pointer to the HW structure
@@ -1286,7 +1160,6 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.start_hw = &ixgbe_start_hw_82598,
.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic,
.get_media_type = &ixgbe_get_media_type_82598,
- .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
.enable_rx_dma = &ixgbe_enable_rx_dma_generic,
.get_mac_addr = &ixgbe_get_mac_addr_generic,
.stop_adapter = &ixgbe_stop_adapter_generic,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index bc7c924240a5..cf55a0df877b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -123,7 +123,7 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
+ s32 ret_val;
u16 list_offset, data_offset, data_value;
if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
@@ -133,16 +133,14 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
&data_offset);
- if (ret_val != 0)
- goto setup_sfp_out;
+ if (ret_val)
+ return ret_val;
/* PHY config will finish before releasing the semaphore */
ret_val = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
- if (ret_val != 0) {
- ret_val = IXGBE_ERR_SWFW_SYNC;
- goto setup_sfp_out;
- }
+ if (ret_val)
+ return IXGBE_ERR_SWFW_SYNC;
if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
goto setup_sfp_err;
@@ -169,13 +167,11 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
if (ret_val) {
hw_dbg(hw, " sfp module setup not complete\n");
- ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
- goto setup_sfp_out;
+ return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
}
}
-setup_sfp_out:
- return ret_val;
+ return 0;
setup_sfp_err:
/* Release the semaphore */
@@ -294,7 +290,7 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
- s32 ret_val = 0;
+ s32 ret_val;
u32 esdp;
if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
@@ -355,7 +351,6 @@ static s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg)
{
- s32 status = 0;
u32 autoc = 0;
/* Determine 1G link capabilities off of SFP+ type */
@@ -367,7 +362,7 @@ static s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
*speed = IXGBE_LINK_SPEED_1GB_FULL;
*autoneg = true;
- goto out;
+ return 0;
}
/*
@@ -430,9 +425,7 @@ static s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
break;
default:
- status = IXGBE_ERR_LINK_SETUP;
- goto out;
- break;
+ return IXGBE_ERR_LINK_SETUP;
}
if (hw->phy.multispeed_fiber) {
@@ -446,8 +439,7 @@ static s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
*autoneg = true;
}
-out:
- return status;
+ return 0;
}
/**
@@ -458,14 +450,12 @@ out:
**/
static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
{
- enum ixgbe_media_type media_type;
-
/* Detect if there is a copper PHY attached. */
switch (hw->phy.type) {
case ixgbe_phy_cu_unknown:
case ixgbe_phy_tn:
- media_type = ixgbe_media_type_copper;
- goto out;
+ return ixgbe_media_type_copper;
+
default:
break;
}
@@ -478,34 +468,31 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82599_BACKPLANE_FCOE:
case IXGBE_DEV_ID_82599_XAUI_LOM:
/* Default device ID is mezzanine card KX/KX4 */
- media_type = ixgbe_media_type_backplane;
- break;
+ return ixgbe_media_type_backplane;
+
case IXGBE_DEV_ID_82599_SFP:
case IXGBE_DEV_ID_82599_SFP_FCOE:
case IXGBE_DEV_ID_82599_SFP_EM:
case IXGBE_DEV_ID_82599_SFP_SF2:
case IXGBE_DEV_ID_82599_SFP_SF_QP:
case IXGBE_DEV_ID_82599EN_SFP:
- media_type = ixgbe_media_type_fiber;
- break;
+ return ixgbe_media_type_fiber;
+
case IXGBE_DEV_ID_82599_CX4:
- media_type = ixgbe_media_type_cx4;
- break;
+ return ixgbe_media_type_cx4;
+
case IXGBE_DEV_ID_82599_T3_LOM:
- media_type = ixgbe_media_type_copper;
- break;
+ return ixgbe_media_type_copper;
+
case IXGBE_DEV_ID_82599_LS:
- media_type = ixgbe_media_type_fiber_lco;
- break;
+ return ixgbe_media_type_fiber_lco;
+
case IXGBE_DEV_ID_82599_QSFP_SF_QP:
- media_type = ixgbe_media_type_fiber_qsfp;
- break;
+ return ixgbe_media_type_fiber_qsfp;
+
default:
- media_type = ixgbe_media_type_unknown;
- break;
+ return ixgbe_media_type_unknown;
}
-out:
- return media_type;
}
/**
@@ -555,7 +542,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
status = hw->mac.ops.acquire_swfw_sync(hw,
IXGBE_GSSR_MAC_CSR_SM);
if (status)
- goto out;
+ return status;
got_lock = true;
}
@@ -592,7 +579,6 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
/* Add delay to filter out noises during initial link setup */
msleep(50);
-out:
return status;
}
@@ -959,7 +945,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
bool autoneg_wait_to_complete)
{
bool autoneg = false;
- s32 status = 0;
+ s32 status;
u32 pma_pmd_1g, link_mode, links_reg, i;
u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
@@ -975,15 +961,13 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
/* Check to see if speed passed in is supported. */
status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
&autoneg);
- if (status != 0)
- goto out;
+ if (status)
+ return status;
speed &= link_capabilities;
- if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
- status = IXGBE_ERR_LINK_SETUP;
- goto out;
- }
+ if (speed == IXGBE_LINK_SPEED_UNKNOWN)
+ return IXGBE_ERR_LINK_SETUP;
/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
if (hw->mac.orig_link_settings_stored)
@@ -1034,7 +1018,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
/* Restart link */
status = hw->mac.ops.prot_autoc_write(hw, autoc, false);
if (status)
- goto out;
+ return status;
/* Only poll for autoneg to complete if specified to do so */
if (autoneg_wait_to_complete) {
@@ -1061,7 +1045,6 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
msleep(50);
}
-out:
return status;
}
@@ -1106,8 +1089,8 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
/* Call adapter stop to disable tx/rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw);
- if (status != 0)
- goto reset_hw_out;
+ if (status)
+ return status;
/* flush pending Tx transactions */
ixgbe_clear_tx_pending(hw);
@@ -1118,7 +1101,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
status = hw->phy.ops.init(hw);
if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
+ return status;
/* Setup SFP module if there is one present. */
if (hw->phy.sfp_setup_needed) {
@@ -1127,7 +1110,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
}
if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
+ return status;
/* Reset PHY */
if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
@@ -1217,7 +1200,7 @@ mac_reset_top:
hw->mac.orig_autoc,
false);
if (status)
- goto reset_hw_out;
+ return status;
}
if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
@@ -1259,7 +1242,6 @@ mac_reset_top:
hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
&hw->mac.wwpn_prefix);
-reset_hw_out:
return status;
}
@@ -1928,20 +1910,20 @@ static s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
s32 ret_val = 0;
ret_val = ixgbe_start_hw_generic(hw);
- if (ret_val != 0)
- goto out;
+ if (ret_val)
+ return ret_val;
ret_val = ixgbe_start_hw_gen2(hw);
- if (ret_val != 0)
- goto out;
+ if (ret_val)
+ return ret_val;
/* We need to run link autotry after the driver loads */
hw->mac.autotry_restart = true;
- if (ret_val == 0)
- ret_val = ixgbe_verify_fw_version_82599(hw);
-out:
- return ret_val;
+ if (ret_val)
+ return ret_val;
+
+ return ixgbe_verify_fw_version_82599(hw);
}
/**
@@ -1954,16 +1936,15 @@ out:
**/
static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+ s32 status;
/* Detect PHY if not unknown - returns success if already detected. */
status = ixgbe_identify_phy_generic(hw);
- if (status != 0) {
+ if (status) {
/* 82599 10GBASE-T requires an external PHY */
if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
- goto out;
- else
- status = ixgbe_identify_module_generic(hw);
+ return status;
+ status = ixgbe_identify_module_generic(hw);
}
/* Set PHY type none if no PHY detected */
@@ -1974,142 +1955,12 @@ static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
/* Return error if SFP module has been detected but is not supported */
if (hw->phy.type == ixgbe_phy_sfp_unsupported)
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
-out:
return status;
}
/**
- * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
- * @hw: pointer to hardware structure
- *
- * Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
-{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
- u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
- u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
- u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
- u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
- u16 ext_ability = 0;
- u8 comp_codes_10g = 0;
- u8 comp_codes_1g = 0;
-
- hw->phy.ops.identify(hw);
-
- switch (hw->phy.type) {
- case ixgbe_phy_tn:
- case ixgbe_phy_cu_unknown:
- hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
- &ext_ability);
- if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
- physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
- goto out;
- default:
- break;
- }
-
- switch (autoc & IXGBE_AUTOC_LMS_MASK) {
- case IXGBE_AUTOC_LMS_1G_AN:
- case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
- if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
- physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
- IXGBE_PHYSICAL_LAYER_1000BASE_BX;
- goto out;
- } else
- /* SFI mode so read SFP module */
- goto sfp_check;
- break;
- case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
- if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
- else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
- else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI;
- goto out;
- break;
- case IXGBE_AUTOC_LMS_10G_SERIAL:
- if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
- goto out;
- } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
- goto sfp_check;
- break;
- case IXGBE_AUTOC_LMS_KX4_KX_KR:
- case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
- if (autoc & IXGBE_AUTOC_KX_SUPP)
- physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
- if (autoc & IXGBE_AUTOC_KX4_SUPP)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
- if (autoc & IXGBE_AUTOC_KR_SUPP)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
- goto out;
- break;
- default:
- goto out;
- break;
- }
-
-sfp_check:
- /* SFP check must be done last since DA modules are sometimes used to
- * test KR mode - we need to id KR mode correctly before SFP module.
- * Call identify_sfp because the pluggable module may have changed */
- hw->phy.ops.identify_sfp(hw);
- if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
- goto out;
-
- switch (hw->phy.type) {
- case ixgbe_phy_sfp_passive_tyco:
- case ixgbe_phy_sfp_passive_unknown:
- case ixgbe_phy_qsfp_passive_unknown:
- physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
- break;
- case ixgbe_phy_sfp_ftl_active:
- case ixgbe_phy_sfp_active_unknown:
- case ixgbe_phy_qsfp_active_unknown:
- physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
- break;
- case ixgbe_phy_sfp_avago:
- case ixgbe_phy_sfp_ftl:
- case ixgbe_phy_sfp_intel:
- case ixgbe_phy_sfp_unknown:
- hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g);
- hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
- if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
- else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
- else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
- physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
- break;
- case ixgbe_phy_qsfp_intel:
- case ixgbe_phy_qsfp_unknown:
- hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
- if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
- else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
- break;
- default:
- break;
- }
-
-out:
- return physical_layer;
-}
-
-/**
* ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
* @hw: pointer to hardware structure
* @regval: register value to write to RXCTRL
@@ -2151,26 +2002,24 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
u16 fw_version = 0;
/* firmware check is only necessary for SFI devices */
- if (hw->phy.media_type != ixgbe_media_type_fiber) {
- status = 0;
- goto fw_version_out;
- }
+ if (hw->phy.media_type != ixgbe_media_type_fiber)
+ return 0;
/* get the offset to the Firmware Module block */
offset = IXGBE_FW_PTR;
if (hw->eeprom.ops.read(hw, offset, &fw_offset))
goto fw_version_err;
- if ((fw_offset == 0) || (fw_offset == 0xFFFF))
- goto fw_version_out;
+ if (fw_offset == 0 || fw_offset == 0xFFFF)
+ return IXGBE_ERR_EEPROM_VERSION;
/* get the offset to the Pass Through Patch Configuration block */
offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR;
if (hw->eeprom.ops.read(hw, offset, &fw_ptp_cfg_offset))
goto fw_version_err;
- if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
- goto fw_version_out;
+ if (fw_ptp_cfg_offset == 0 || fw_ptp_cfg_offset == 0xFFFF)
+ return IXGBE_ERR_EEPROM_VERSION;
/* get the firmware version */
offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4;
@@ -2180,7 +2029,6 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
if (fw_version > 0x5)
status = 0;
-fw_version_out:
return status;
fw_version_err:
@@ -2197,37 +2045,33 @@ fw_version_err:
**/
static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
{
- bool lesm_enabled = false;
u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
s32 status;
/* get the offset to the Firmware Module block */
status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
- if ((status != 0) ||
- (fw_offset == 0) || (fw_offset == 0xFFFF))
- goto out;
+ if (status || fw_offset == 0 || fw_offset == 0xFFFF)
+ return false;
/* get the offset to the LESM Parameters block */
status = hw->eeprom.ops.read(hw, (fw_offset +
IXGBE_FW_LESM_PARAMETERS_PTR),
&fw_lesm_param_offset);
- if ((status != 0) ||
- (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF))
- goto out;
+ if (status ||
+ fw_lesm_param_offset == 0 || fw_lesm_param_offset == 0xFFFF)
+ return false;
/* get the lesm state word */
status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset +
IXGBE_FW_LESM_STATE_1),
&fw_lesm_state);
- if ((status == 0) &&
- (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
- lesm_enabled = true;
+ if (!status && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED))
+ return true;
-out:
- return lesm_enabled;
+ return false;
}
/**
@@ -2245,22 +2089,16 @@ static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data)
{
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
- s32 ret_val = IXGBE_ERR_CONFIG;
- /*
- * If EEPROM is detected and can be addressed using 14 bits,
+ /* If EEPROM is detected and can be addressed using 14 bits,
* use EERD otherwise use bit bang
*/
- if ((eeprom->type == ixgbe_eeprom_spi) &&
- (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR))
- ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words,
- data);
- else
- ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset,
- words,
- data);
+ if (eeprom->type == ixgbe_eeprom_spi &&
+ offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)
+ return ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
- return ret_val;
+ return ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words,
+ data);
}
/**
@@ -2277,19 +2115,15 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
u16 offset, u16 *data)
{
struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
- s32 ret_val = IXGBE_ERR_CONFIG;
/*
* If EEPROM is detected and can be addressed using 14 bits,
* use EERD otherwise use bit bang
*/
- if ((eeprom->type == ixgbe_eeprom_spi) &&
- (offset <= IXGBE_EERD_MAX_ADDR))
- ret_val = ixgbe_read_eerd_generic(hw, offset, data);
- else
- ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
+ if (eeprom->type == ixgbe_eeprom_spi && offset <= IXGBE_EERD_MAX_ADDR)
+ return ixgbe_read_eerd_generic(hw, offset, data);
- return ret_val;
+ return ixgbe_read_eeprom_bit_bang_generic(hw, offset, data);
}
/**
@@ -2458,7 +2292,6 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.start_hw = &ixgbe_start_hw_82599,
.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic,
.get_media_type = &ixgbe_get_media_type_82599,
- .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599,
.enable_rx_dma = &ixgbe_enable_rx_dma_82599,
.disable_rx_buff = &ixgbe_disable_rx_buff_generic,
.enable_rx_buff = &ixgbe_enable_rx_buff_generic,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 4e5385a2a465..b5f484bf3fda 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -122,8 +122,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
*/
if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
}
/*
@@ -143,7 +142,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
/* some MAC's need RMW protection on AUTOC */
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
if (ret_val)
- goto out;
+ return ret_val;
/* only backplane uses autoc so fall though */
case ixgbe_media_type_fiber:
@@ -214,9 +213,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
break;
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = IXGBE_ERR_CONFIG;
- goto out;
- break;
+ return IXGBE_ERR_CONFIG;
}
if (hw->mac.type != ixgbe_mac_X540) {
@@ -247,7 +244,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
*/
ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
if (ret_val)
- goto out;
+ return ret_val;
} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
ixgbe_device_supports_autoneg_fc(hw)) {
@@ -256,7 +253,6 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
}
hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
-out:
return ret_val;
}
@@ -295,12 +291,11 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
/* Setup flow control */
ret_val = ixgbe_setup_fc(hw);
if (!ret_val)
- goto out;
+ return 0;
/* Clear adapter stopped flag */
hw->adapter_stopped = false;
-out:
return ret_val;
}
@@ -837,20 +832,16 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data)
{
- s32 status = 0;
+ s32 status;
u16 i, count;
hw->eeprom.ops.init_params(hw);
- if (words == 0) {
- status = IXGBE_ERR_INVALID_ARGUMENT;
- goto out;
- }
+ if (words == 0)
+ return IXGBE_ERR_INVALID_ARGUMENT;
- if (offset + words > hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
+ if (offset + words > hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
/*
* The EEPROM page size cannot be queried from the chip. We do lazy
@@ -875,7 +866,6 @@ s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
break;
}
-out:
return status;
}
@@ -900,64 +890,61 @@ static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
/* Prepare the EEPROM for writing */
status = ixgbe_acquire_eeprom(hw);
+ if (status)
+ return status;
- if (status == 0) {
- if (ixgbe_ready_eeprom(hw) != 0) {
- ixgbe_release_eeprom(hw);
- status = IXGBE_ERR_EEPROM;
- }
+ if (ixgbe_ready_eeprom(hw) != 0) {
+ ixgbe_release_eeprom(hw);
+ return IXGBE_ERR_EEPROM;
}
- if (status == 0) {
- for (i = 0; i < words; i++) {
- ixgbe_standby_eeprom(hw);
+ for (i = 0; i < words; i++) {
+ ixgbe_standby_eeprom(hw);
+
+ /* Send the WRITE ENABLE command (8 bit opcode) */
+ ixgbe_shift_out_eeprom_bits(hw,
+ IXGBE_EEPROM_WREN_OPCODE_SPI,
+ IXGBE_EEPROM_OPCODE_BITS);
- /* Send the WRITE ENABLE command (8 bit opcode ) */
- ixgbe_shift_out_eeprom_bits(hw,
- IXGBE_EEPROM_WREN_OPCODE_SPI,
- IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_standby_eeprom(hw);
- ixgbe_standby_eeprom(hw);
+ /* Some SPI eeproms use the 8th address bit embedded
+ * in the opcode
+ */
+ if ((hw->eeprom.address_bits == 8) &&
+ ((offset + i) >= 128))
+ write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
- /*
- * Some SPI eeproms use the 8th address bit embedded
- * in the opcode
- */
- if ((hw->eeprom.address_bits == 8) &&
- ((offset + i) >= 128))
- write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
-
- /* Send the Write command (8-bit opcode + addr) */
- ixgbe_shift_out_eeprom_bits(hw, write_opcode,
- IXGBE_EEPROM_OPCODE_BITS);
- ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
- hw->eeprom.address_bits);
-
- page_size = hw->eeprom.word_page_size;
-
- /* Send the data in burst via SPI*/
- do {
- word = data[i];
- word = (word >> 8) | (word << 8);
- ixgbe_shift_out_eeprom_bits(hw, word, 16);
-
- if (page_size == 0)
- break;
-
- /* do not wrap around page */
- if (((offset + i) & (page_size - 1)) ==
- (page_size - 1))
- break;
- } while (++i < words);
-
- ixgbe_standby_eeprom(hw);
- usleep_range(10000, 20000);
- }
- /* Done with writing - release the EEPROM */
- ixgbe_release_eeprom(hw);
+ /* Send the Write command (8-bit opcode + addr) */
+ ixgbe_shift_out_eeprom_bits(hw, write_opcode,
+ IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+ hw->eeprom.address_bits);
+
+ page_size = hw->eeprom.word_page_size;
+
+ /* Send the data in burst via SPI */
+ do {
+ word = data[i];
+ word = (word >> 8) | (word << 8);
+ ixgbe_shift_out_eeprom_bits(hw, word, 16);
+
+ if (page_size == 0)
+ break;
+
+ /* do not wrap around page */
+ if (((offset + i) & (page_size - 1)) ==
+ (page_size - 1))
+ break;
+ } while (++i < words);
+
+ ixgbe_standby_eeprom(hw);
+ usleep_range(10000, 20000);
}
+ /* Done with writing - release the EEPROM */
+ ixgbe_release_eeprom(hw);
- return status;
+ return 0;
}
/**
@@ -971,19 +958,12 @@ static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
**/
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
{
- s32 status;
-
hw->eeprom.ops.init_params(hw);
- if (offset >= hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
-
- status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
+ if (offset >= hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
-out:
- return status;
+ return ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
}
/**
@@ -998,20 +978,16 @@ out:
s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data)
{
- s32 status = 0;
+ s32 status;
u16 i, count;
hw->eeprom.ops.init_params(hw);
- if (words == 0) {
- status = IXGBE_ERR_INVALID_ARGUMENT;
- goto out;
- }
+ if (words == 0)
+ return IXGBE_ERR_INVALID_ARGUMENT;
- if (offset + words > hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
+ if (offset + words > hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
/*
* We cannot hold synchronization semaphores for too long
@@ -1025,12 +1001,11 @@ s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
count, &data[i]);
- if (status != 0)
- break;
+ if (status)
+ return status;
}
-out:
- return status;
+ return 0;
}
/**
@@ -1052,41 +1027,38 @@ static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
/* Prepare the EEPROM for reading */
status = ixgbe_acquire_eeprom(hw);
+ if (status)
+ return status;
- if (status == 0) {
- if (ixgbe_ready_eeprom(hw) != 0) {
- ixgbe_release_eeprom(hw);
- status = IXGBE_ERR_EEPROM;
- }
+ if (ixgbe_ready_eeprom(hw) != 0) {
+ ixgbe_release_eeprom(hw);
+ return IXGBE_ERR_EEPROM;
}
- if (status == 0) {
- for (i = 0; i < words; i++) {
- ixgbe_standby_eeprom(hw);
- /*
- * Some SPI eeproms use the 8th address bit embedded
- * in the opcode
- */
- if ((hw->eeprom.address_bits == 8) &&
- ((offset + i) >= 128))
- read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
-
- /* Send the READ command (opcode + addr) */
- ixgbe_shift_out_eeprom_bits(hw, read_opcode,
- IXGBE_EEPROM_OPCODE_BITS);
- ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
- hw->eeprom.address_bits);
-
- /* Read the data. */
- word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
- data[i] = (word_in >> 8) | (word_in << 8);
- }
+ for (i = 0; i < words; i++) {
+ ixgbe_standby_eeprom(hw);
+ /* Some SPI eeproms use the 8th address bit embedded
+ * in the opcode
+ */
+ if ((hw->eeprom.address_bits == 8) &&
+ ((offset + i) >= 128))
+ read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
- /* End this read operation */
- ixgbe_release_eeprom(hw);
+ /* Send the READ command (opcode + addr) */
+ ixgbe_shift_out_eeprom_bits(hw, read_opcode,
+ IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+ hw->eeprom.address_bits);
+
+ /* Read the data. */
+ word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
+ data[i] = (word_in >> 8) | (word_in << 8);
}
- return status;
+ /* End this read operation */
+ ixgbe_release_eeprom(hw);
+
+ return 0;
}
/**
@@ -1100,19 +1072,12 @@ static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data)
{
- s32 status;
-
hw->eeprom.ops.init_params(hw);
- if (offset >= hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
-
- status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+ if (offset >= hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
-out:
- return status;
+ return ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
}
/**
@@ -1128,20 +1093,16 @@ s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data)
{
u32 eerd;
- s32 status = 0;
+ s32 status;
u32 i;
hw->eeprom.ops.init_params(hw);
- if (words == 0) {
- status = IXGBE_ERR_INVALID_ARGUMENT;
- goto out;
- }
+ if (words == 0)
+ return IXGBE_ERR_INVALID_ARGUMENT;
- if (offset >= hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
+ if (offset >= hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
for (i = 0; i < words; i++) {
eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1155,11 +1116,11 @@ s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
IXGBE_EEPROM_RW_REG_DATA);
} else {
hw_dbg(hw, "Eeprom read timed out\n");
- goto out;
+ return status;
}
}
-out:
- return status;
+
+ return 0;
}
/**
@@ -1175,7 +1136,7 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
u16 offset)
{
u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
- s32 status = 0;
+ s32 status;
u16 i;
for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
@@ -1185,12 +1146,12 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
IXGBE_EEPROM_PAGE_SIZE_MAX, data);
hw->eeprom.word_page_size = 0;
- if (status != 0)
- goto out;
+ if (status)
+ return status;
status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
- if (status != 0)
- goto out;
+ if (status)
+ return status;
/*
* When writing in burst more than the actual page size
@@ -1200,8 +1161,7 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
hw_dbg(hw, "Detected EEPROM page size = %d words.\n",
hw->eeprom.word_page_size);
-out:
- return status;
+ return 0;
}
/**
@@ -1230,20 +1190,16 @@ s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
u16 words, u16 *data)
{
u32 eewr;
- s32 status = 0;
+ s32 status;
u16 i;
hw->eeprom.ops.init_params(hw);
- if (words == 0) {
- status = IXGBE_ERR_INVALID_ARGUMENT;
- goto out;
- }
+ if (words == 0)
+ return IXGBE_ERR_INVALID_ARGUMENT;
- if (offset >= hw->eeprom.word_size) {
- status = IXGBE_ERR_EEPROM;
- goto out;
- }
+ if (offset >= hw->eeprom.word_size)
+ return IXGBE_ERR_EEPROM;
for (i = 0; i < words; i++) {
eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1251,22 +1207,21 @@ s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
IXGBE_EEPROM_RW_REG_START;
status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
- if (status != 0) {
+ if (status) {
hw_dbg(hw, "Eeprom write EEWR timed out\n");
- goto out;
+ return status;
}
IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
- if (status != 0) {
+ if (status) {
hw_dbg(hw, "Eeprom write EEWR timed out\n");
- goto out;
+ return status;
}
}
-out:
- return status;
+ return 0;
}
/**
@@ -1294,7 +1249,6 @@ static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
{
u32 i;
u32 reg;
- s32 status = IXGBE_ERR_EEPROM;
for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) {
if (ee_reg == IXGBE_NVM_POLL_READ)
@@ -1303,12 +1257,11 @@ static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
reg = IXGBE_READ_REG(hw, IXGBE_EEWR);
if (reg & IXGBE_EEPROM_RW_REG_DONE) {
- status = 0;
- break;
+ return 0;
}
udelay(5);
}
- return status;
+ return IXGBE_ERR_EEPROM;
}
/**
@@ -1320,47 +1273,42 @@ static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
**/
static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
{
- s32 status = 0;
u32 eec;
u32 i;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
- status = IXGBE_ERR_SWFW_SYNC;
-
- if (status == 0) {
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ return IXGBE_ERR_SWFW_SYNC;
- /* Request EEPROM Access */
- eec |= IXGBE_EEC_REQ;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
- for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
- eec = IXGBE_READ_REG(hw, IXGBE_EEC);
- if (eec & IXGBE_EEC_GNT)
- break;
- udelay(5);
- }
+ /* Request EEPROM Access */
+ eec |= IXGBE_EEC_REQ;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
- /* Release if grant not acquired */
- if (!(eec & IXGBE_EEC_GNT)) {
- eec &= ~IXGBE_EEC_REQ;
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
- hw_dbg(hw, "Could not acquire EEPROM grant\n");
+ for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ if (eec & IXGBE_EEC_GNT)
+ break;
+ udelay(5);
+ }
- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
- status = IXGBE_ERR_EEPROM;
- }
+ /* Release if grant not acquired */
+ if (!(eec & IXGBE_EEC_GNT)) {
+ eec &= ~IXGBE_EEC_REQ;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ hw_dbg(hw, "Could not acquire EEPROM grant\n");
- /* Setup EEPROM for Read/Write */
- if (status == 0) {
- /* Clear CS and SK */
- eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
- IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
- IXGBE_WRITE_FLUSH(hw);
- udelay(1);
- }
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ return IXGBE_ERR_EEPROM;
}
- return status;
+
+ /* Setup EEPROM for Read/Write */
+ /* Clear CS and SK */
+ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+ IXGBE_WRITE_FLUSH(hw);
+ udelay(1);
+ return 0;
}
/**
@@ -1371,7 +1319,6 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
**/
static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_EEPROM;
u32 timeout = 2000;
u32 i;
u32 swsm;
@@ -1383,68 +1330,60 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
* set and we have the semaphore
*/
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
- if (!(swsm & IXGBE_SWSM_SMBI)) {
- status = 0;
+ if (!(swsm & IXGBE_SWSM_SMBI))
break;
- }
- udelay(50);
+ usleep_range(50, 100);
}
if (i == timeout) {
hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore not granted.\n");
- /*
- * this release is particularly important because our attempts
+ /* this release is particularly important because our attempts
* above to get the semaphore may have succeeded, and if there
* was a timeout, we should unconditionally clear the semaphore
* bits to free the driver to make progress
*/
ixgbe_release_eeprom_semaphore(hw);
- udelay(50);
- /*
- * one last try
+ usleep_range(50, 100);
+ /* one last try
* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
- if (!(swsm & IXGBE_SWSM_SMBI))
- status = 0;
+ if (swsm & IXGBE_SWSM_SMBI) {
+ hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+ return IXGBE_ERR_EEPROM;
+ }
}
/* Now get the semaphore between SW/FW through the SWESMBI bit */
- if (status == 0) {
- for (i = 0; i < timeout; i++) {
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ for (i = 0; i < timeout; i++) {
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
- /* Set the SW EEPROM semaphore bit to request access */
- swsm |= IXGBE_SWSM_SWESMBI;
- IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+ /* Set the SW EEPROM semaphore bit to request access */
+ swsm |= IXGBE_SWSM_SWESMBI;
+ IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
- /*
- * If we set the bit successfully then we got the
- * semaphore.
- */
- swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
- if (swsm & IXGBE_SWSM_SWESMBI)
- break;
+ /* If we set the bit successfully then we got the
+ * semaphore.
+ */
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ if (swsm & IXGBE_SWSM_SWESMBI)
+ break;
- udelay(50);
- }
+ usleep_range(50, 100);
+ }
- /*
- * Release semaphores and return error if SW EEPROM semaphore
- * was not granted because we don't have access to the EEPROM
- */
- if (i >= timeout) {
- hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
- ixgbe_release_eeprom_semaphore(hw);
- status = IXGBE_ERR_EEPROM;
- }
- } else {
- hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+ /* Release semaphores and return error if SW EEPROM semaphore
+ * was not granted because we don't have access to the EEPROM
+ */
+ if (i >= timeout) {
+ hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
+ ixgbe_release_eeprom_semaphore(hw);
+ return IXGBE_ERR_EEPROM;
}
- return status;
+ return 0;
}
/**
@@ -1471,7 +1410,6 @@ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw)
**/
static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
{
- s32 status = 0;
u16 i;
u8 spi_stat_reg;
@@ -1498,10 +1436,10 @@ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw)
*/
if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
hw_dbg(hw, "SPI EEPROM Status error\n");
- status = IXGBE_ERR_EEPROM;
+ return IXGBE_ERR_EEPROM;
}
- return status;
+ return 0;
}
/**
@@ -2100,17 +2038,14 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
**/
s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
u32 mflcn_reg, fccfg_reg;
u32 reg;
u32 fcrtl, fcrth;
int i;
/* Validate the water mark configuration. */
- if (!hw->fc.pause_time) {
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
+ if (!hw->fc.pause_time)
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
/* Low water mark of zero causes XOFF floods */
for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -2119,8 +2054,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
if (!hw->fc.low_water[i] ||
hw->fc.low_water[i] >= hw->fc.high_water[i]) {
hw_dbg(hw, "Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
+ return IXGBE_ERR_INVALID_LINK_SETTINGS;
}
}
}
@@ -2177,9 +2111,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
break;
default:
hw_dbg(hw, "Flow control param set incorrectly\n");
- ret_val = IXGBE_ERR_CONFIG;
- goto out;
- break;
+ return IXGBE_ERR_CONFIG;
}
/* Set 802.3x based flow control settings. */
@@ -2215,8 +2147,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -2277,7 +2208,7 @@ static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
{
u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
- s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ s32 ret_val;
/*
* On multispeed fiber at 1g, bail out if
@@ -2288,7 +2219,7 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
(!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
- goto out;
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
@@ -2299,7 +2230,6 @@ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
IXGBE_PCS1GANA_SYM_PAUSE,
IXGBE_PCS1GANA_ASM_PAUSE);
-out:
return ret_val;
}
@@ -2312,7 +2242,7 @@ out:
static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
{
u32 links2, anlp1_reg, autoc_reg, links;
- s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+ s32 ret_val;
/*
* On backplane, bail out if
@@ -2321,12 +2251,12 @@ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
*/
links = IXGBE_READ_REG(hw, IXGBE_LINKS);
if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
- goto out;
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
if (hw->mac.type == ixgbe_mac_82599EB) {
links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
- goto out;
+ return IXGBE_ERR_FC_NOT_NEGOTIATED;
}
/*
* Read the 10g AN autoc and LP ability registers and resolve
@@ -2339,7 +2269,6 @@ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
-out:
return ret_val;
}
@@ -2485,7 +2414,6 @@ static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
**/
static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
{
- s32 status = 0;
u32 i, poll;
u16 value;
@@ -2495,13 +2423,13 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
/* Exit if master requests are blocked */
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
ixgbe_removed(hw->hw_addr))
- goto out;
+ return 0;
/* Poll for master request bit to clear */
for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
udelay(100);
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
- goto out;
+ return 0;
}
/*
@@ -2524,16 +2452,13 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
udelay(100);
value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
if (ixgbe_removed(hw->hw_addr))
- goto out;
+ return 0;
if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
- goto out;
+ return 0;
}
hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
-
-out:
- return status;
+ return IXGBE_ERR_MASTER_REQUESTS_PENDING;
}
/**
@@ -2708,8 +2633,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
bool link_up = false;
u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
- s32 ret_val = 0;
bool locked = false;
+ s32 ret_val;
/*
* Link must be up to auto-blink the LEDs;
@@ -2720,14 +2645,14 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
if (!link_up) {
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
if (ret_val)
- goto out;
+ return ret_val;
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
autoc_reg |= IXGBE_AUTOC_FLU;
ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
if (ret_val)
- goto out;
+ return ret_val;
IXGBE_WRITE_FLUSH(hw);
@@ -2739,8 +2664,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
IXGBE_WRITE_FLUSH(hw);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -2752,19 +2676,19 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
{
u32 autoc_reg = 0;
u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
- s32 ret_val = 0;
bool locked = false;
+ s32 ret_val;
ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
if (ret_val)
- goto out;
+ return ret_val;
autoc_reg &= ~IXGBE_AUTOC_FLU;
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
if (ret_val)
- goto out;
+ return ret_val;
led_reg &= ~IXGBE_LED_MODE_MASK(index);
led_reg &= ~IXGBE_LED_BLINK(index);
@@ -2772,8 +2696,7 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
IXGBE_WRITE_FLUSH(hw);
-out:
- return ret_val;
+ return 0;
}
/**
@@ -2865,7 +2788,7 @@ san_mac_addr_clr:
**/
u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
{
- u16 msix_count = 1;
+ u16 msix_count;
u16 max_msix_count;
u16 pcie_offset;
@@ -2880,7 +2803,7 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
break;
default:
- return msix_count;
+ return 1;
}
msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset);
@@ -2918,10 +2841,10 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
if (ixgbe_removed(hw->hw_addr))
- goto done;
+ return 0;
if (!mpsar_lo && !mpsar_hi)
- goto done;
+ return 0;
if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
if (mpsar_lo) {
@@ -2943,7 +2866,6 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
/* was that the last pool using this rar? */
if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
hw->mac.ops.clear_rar(hw, rar);
-done:
return 0;
}
@@ -3312,14 +3234,14 @@ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
if ((alt_san_mac_blk_offset == 0) ||
(alt_san_mac_blk_offset == 0xFFFF))
- goto wwn_prefix_out;
+ return 0;
/* check capability in alternative san mac address block */
offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
if (hw->eeprom.ops.read(hw, offset, &caps))
goto wwn_prefix_err;
if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
- goto wwn_prefix_out;
+ return 0;
/* get the corresponding prefix for WWNN/WWPN */
offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
@@ -3330,7 +3252,6 @@ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
if (hw->eeprom.ops.read(hw, offset, wwpn_prefix))
goto wwn_prefix_err;
-wwn_prefix_out:
return 0;
wwn_prefix_err:
@@ -3524,21 +3445,17 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
u8 buf_len, dword_len;
- s32 ret_val = 0;
-
if (length == 0 || length & 0x3 ||
length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
hw_dbg(hw, "Buffer length failure.\n");
- ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
/* Check that the host interface is enabled. */
hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
if ((hicr & IXGBE_HICR_EN) == 0) {
hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
- ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs */
@@ -3566,8 +3483,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
if (i == IXGBE_HI_COMMAND_TIMEOUT ||
(!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
hw_dbg(hw, "Command has failed with no status valid.\n");
- ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs */
@@ -3582,12 +3498,11 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
/* If there is any thing in data position pull it in */
buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
if (buf_len == 0)
- goto out;
+ return 0;
if (length < (buf_len + hdr_size)) {
hw_dbg(hw, "Buffer not large enough for reply message.\n");
- ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
- goto out;
+ return IXGBE_ERR_HOST_INTERFACE_COMMAND;
}
/* Calculate length in DWORDs, add 3 for odd lengths */
@@ -3599,8 +3514,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
le32_to_cpus(&buffer[bi]);
}
-out:
- return ret_val;
+ return 0;
}
/**
@@ -3621,12 +3535,10 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
{
struct ixgbe_hic_drv_info fw_cmd;
int i;
- s32 ret_val = 0;
+ s32 ret_val;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
- ret_val = IXGBE_ERR_SWFW_SYNC;
- goto out;
- }
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM))
+ return IXGBE_ERR_SWFW_SYNC;
fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
@@ -3658,7 +3570,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
}
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
-out:
return ret_val;
}
@@ -3727,28 +3638,23 @@ static const u8 ixgbe_emc_therm_limit[4] = {
static s32 ixgbe_get_ets_data(struct ixgbe_hw *hw, u16 *ets_cfg,
u16 *ets_offset)
{
- s32 status = 0;
+ s32 status;
status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, ets_offset);
if (status)
- goto out;
+ return status;
- if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF)) {
- status = IXGBE_NOT_IMPLEMENTED;
- goto out;
- }
+ if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF))
+ return IXGBE_NOT_IMPLEMENTED;
status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
if (status)
- goto out;
+ return status;
- if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED) {
- status = IXGBE_NOT_IMPLEMENTED;
- goto out;
- }
+ if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED)
+ return IXGBE_NOT_IMPLEMENTED;
-out:
- return status;
+ return 0;
}
/**
@@ -3759,7 +3665,7 @@ out:
**/
s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
{
- s32 status = 0;
+ s32 status;
u16 ets_offset;
u16 ets_cfg;
u16 ets_sensor;
@@ -3768,14 +3674,12 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
/* Only support thermal sensors attached to physical port 0 */
- if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
- status = IXGBE_NOT_IMPLEMENTED;
- goto out;
- }
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
+ return IXGBE_NOT_IMPLEMENTED;
status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
if (status)
- goto out;
+ return status;
num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
if (num_sensors > IXGBE_MAX_SENSORS)
@@ -3788,7 +3692,7 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
&ets_sensor);
if (status)
- goto out;
+ return status;
sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
IXGBE_ETS_DATA_INDEX_SHIFT);
@@ -3801,11 +3705,11 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
IXGBE_I2C_THERMAL_SENSOR_ADDR,
&data->sensor[i].temp);
if (status)
- goto out;
+ return status;
}
}
-out:
- return status;
+
+ return 0;
}
/**
@@ -3817,7 +3721,7 @@ out:
**/
s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
{
- s32 status = 0;
+ s32 status;
u16 ets_offset;
u16 ets_cfg;
u16 ets_sensor;
@@ -3830,14 +3734,12 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
/* Only support thermal sensors attached to physical port 0 */
- if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
- status = IXGBE_NOT_IMPLEMENTED;
- goto out;
- }
+ if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
+ return IXGBE_NOT_IMPLEMENTED;
status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
if (status)
- goto out;
+ return status;
low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
IXGBE_ETS_LTHRES_DELTA_SHIFT);
@@ -3871,7 +3773,7 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
data->sensor[i].caution_thresh = therm_limit;
data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta;
}
-out:
- return status;
+
+ return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
index a689ee0d4bed..48f35fc963f8 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -87,7 +87,6 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
int min_credit;
int min_multiplier;
int min_percent = 100;
- s32 ret_val = 0;
/* Initialization values default for Tx settings */
u32 credit_refill = 0;
u32 credit_max = 0;
@@ -95,10 +94,8 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
u8 bw_percent = 0;
u8 i;
- if (dcb_config == NULL) {
- ret_val = DCB_ERR_CONFIG;
- goto out;
- }
+ if (!dcb_config)
+ return DCB_ERR_CONFIG;
min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
DCB_CREDIT_QUANTUM;
@@ -174,8 +171,7 @@ s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *hw,
p->data_credits_max = (u16)credit_max;
}
-out:
- return ret_val;
+ return 0;
}
void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
@@ -236,7 +232,7 @@ u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
/* If tc is 0 then DCB is likely not enabled or supported */
if (!tc)
- goto out;
+ return 0;
/*
* Test from maximum TC to 1 and report the first match we find. If
@@ -247,7 +243,7 @@ u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap)
break;
}
-out:
+
return tc;
}
@@ -269,7 +265,6 @@ void ixgbe_dcb_unpack_map(struct ixgbe_dcb_config *cfg, int direction, u8 *map)
s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
struct ixgbe_dcb_config *dcb_config)
{
- s32 ret = 0;
u8 pfc_en;
u8 ptype[MAX_TRAFFIC_CLASS];
u8 bwgid[MAX_TRAFFIC_CLASS];
@@ -287,37 +282,31 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- ret = ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
- bwgid, ptype);
- break;
+ return ixgbe_dcb_hw_config_82598(hw, pfc_en, refill, max,
+ bwgid, ptype);
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- ret = ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
- bwgid, ptype, prio_tc);
- break;
+ return ixgbe_dcb_hw_config_82599(hw, pfc_en, refill, max,
+ bwgid, ptype, prio_tc);
default:
break;
}
- return ret;
+ return 0;
}
/* Helper routines to abstract HW specifics from DCB netlink ops */
s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc)
{
- int ret = -EINVAL;
-
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
- ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
- break;
+ return ixgbe_dcb_config_pfc_82598(hw, pfc_en);
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
- ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
- break;
+ return ixgbe_dcb_config_pfc_82599(hw, pfc_en, prio_tc);
default:
break;
}
- return ret;
+ return -EINVAL;
}
s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index 5172b6b12c09..58a7f5312a96 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -153,7 +153,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int err = 0;
/* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
@@ -161,12 +160,10 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
/* verify there is something to do, if not then exit */
if (!state == !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
- goto out;
+ return 0;
- err = ixgbe_setup_tc(netdev,
- state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
-out:
- return !!err;
+ return !!ixgbe_setup_tc(netdev,
+ state ? adapter->dcb_cfg.num_tcs.pg_tcs : 0);
}
static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
@@ -331,12 +328,12 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
/* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
- return ret;
+ return DCB_NO_HW_CHG;
adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter,
MAX_TRAFFIC_CLASS);
if (!adapter->dcb_set_bitmap)
- return ret;
+ return DCB_NO_HW_CHG;
if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
@@ -460,7 +457,6 @@ static int ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
break;
default:
return -EINVAL;
- break;
}
} else {
return -EINVAL;
@@ -495,10 +491,10 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
* @id: id is either ether type or TCP/UDP port number
*
* Returns : on success, returns a non-zero 802.1p user priority bitmap
- * otherwise returns 0 as the invalid user priority bitmap to indicate an
+ * otherwise returns -EINVAL as the invalid user priority bitmap to indicate an
* error.
*/
-static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
+static int ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct dcb_app app = {
@@ -507,7 +503,7 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
};
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
- return 0;
+ return -EINVAL;
return dcb_getapp(netdev, &app);
}
@@ -537,7 +533,7 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
- int i, err = 0;
+ int i, err;
__u8 max_tc = 0;
__u8 map_chg = 0;
@@ -574,17 +570,15 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
if (max_tc > adapter->dcb_cfg.num_tcs.pg_tcs)
return -EINVAL;
- if (max_tc != netdev_get_num_tc(dev))
+ if (max_tc != netdev_get_num_tc(dev)) {
err = ixgbe_setup_tc(dev, max_tc);
- else if (map_chg)
+ if (err)
+ return err;
+ } else if (map_chg) {
ixgbe_dcbnl_devreset(dev);
+ }
- if (err)
- goto err_out;
-
- err = ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
-err_out:
- return err;
+ return ixgbe_dcb_hw_ets(&adapter->hw, ets, max_frame);
}
static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
@@ -648,10 +642,10 @@ static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
struct dcb_app *app)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
- int err = -EINVAL;
+ int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
- return err;
+ return -EINVAL;
err = dcb_ieee_setapp(dev, app);
if (err)
@@ -663,7 +657,7 @@ static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
u8 app_mask = dcb_ieee_getapp_mask(dev, app);
if (app_mask & (1 << adapter->fcoe.up))
- return err;
+ return 0;
adapter->fcoe.up = app->priority;
ixgbe_dcbnl_devreset(dev);
@@ -706,7 +700,7 @@ static int ixgbe_dcbnl_ieee_delapp(struct net_device *dev,
u8 app_mask = dcb_ieee_getapp_mask(dev, app);
if (app_mask & (1 << adapter->fcoe.up))
- return err;
+ return 0;
adapter->fcoe.up = app_mask ?
ffs(app_mask) - 1 : IXGBE_FCOE_DEFTC;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index a452730a3278..e4100b5737b6 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1408,7 +1408,6 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
default:
*data = 1;
return 1;
- break;
}
/*
@@ -2518,7 +2517,7 @@ static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
/* add filter to the list */
if (parent)
- hlist_add_after(&parent->fdir_node, &input->fdir_node);
+ hlist_add_behind(&input->fdir_node, &parent->fdir_node);
else
hlist_add_head(&input->fdir_node,
&adapter->fdir_filter_list);
@@ -2866,7 +2865,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
break;
default:
return ethtool_op_get_ts_info(dev, info);
- break;
}
return 0;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 25a3dfef33e8..2ad91cb04dab 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -67,23 +67,23 @@ static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp)
*/
int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
{
- int len = 0;
+ int len;
struct ixgbe_fcoe *fcoe;
struct ixgbe_adapter *adapter;
struct ixgbe_fcoe_ddp *ddp;
u32 fcbuff;
if (!netdev)
- goto out_ddp_put;
+ return 0;
if (xid >= IXGBE_FCOE_DDP_MAX)
- goto out_ddp_put;
+ return 0;
adapter = netdev_priv(netdev);
fcoe = &adapter->fcoe;
ddp = &fcoe->ddp[xid];
if (!ddp->udl)
- goto out_ddp_put;
+ return 0;
len = ddp->len;
/* if there an error, force to invalidate ddp context */
@@ -114,7 +114,6 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
ixgbe_fcoe_clear_ddp(ddp);
-out_ddp_put:
return len;
}
@@ -394,17 +393,17 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
xid = be16_to_cpu(fh->fh_rx_id);
if (xid >= IXGBE_FCOE_DDP_MAX)
- goto ddp_out;
+ return -EINVAL;
fcoe = &adapter->fcoe;
ddp = &fcoe->ddp[xid];
if (!ddp->udl)
- goto ddp_out;
+ return -EINVAL;
ddp_err = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCEOFE |
IXGBE_RXDADV_ERR_FCERR);
if (ddp_err)
- goto ddp_out;
+ return -EINVAL;
switch (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_FCSTAT)) {
/* return 0 to bypass going to ULD for DDPed data */
@@ -447,7 +446,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
crc->fcoe_eof = FC_EOF_T;
}
-ddp_out:
+
return rc;
}
@@ -878,7 +877,6 @@ int ixgbe_fcoe_disable(struct net_device *netdev)
*/
int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
{
- int rc = -EINVAL;
u16 prefix = 0xffff;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_mac_info *mac = &adapter->hw.mac;
@@ -903,9 +901,9 @@ int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
((u64) mac->san_addr[3] << 16) |
((u64) mac->san_addr[4] << 8) |
((u64) mac->san_addr[5]);
- rc = 0;
+ return 0;
}
- return rc;
+ return -EINVAL;
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f5aa3311ea28..87bd53fdd209 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -84,7 +84,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
+static const struct pci_device_id ixgbe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 },
@@ -570,7 +570,7 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
/* Print TX Ring Summary */
if (!netdev || !netif_running(netdev))
- goto exit;
+ return;
dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
pr_info(" %s %s %s %s\n",
@@ -685,7 +685,7 @@ rx_ring_summary:
/* Print RX Rings */
if (!netif_msg_rx_status(adapter))
- goto exit;
+ return;
dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
@@ -787,9 +787,6 @@ rx_ring_summary:
}
}
-
-exit:
- return;
}
static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
@@ -1011,7 +1008,6 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
u32 tx_done = ixgbe_get_tx_completed(tx_ring);
u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
u32 tx_pending = ixgbe_get_tx_pending(tx_ring);
- bool ret = false;
clear_check_for_tx_hang(tx_ring);
@@ -1027,18 +1023,16 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
* run the check_tx_hang logic with a transmit completion
* pending but without time to complete it yet.
*/
- if ((tx_done_old == tx_done) && tx_pending) {
+ if (tx_done_old == tx_done && tx_pending)
/* make sure it is true for two checks in a row */
- ret = test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
- &tx_ring->state);
- } else {
- /* update completed stats and continue */
- tx_ring->tx_stats.tx_done_old = tx_done;
- /* reset the countdown */
- clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
- }
+ return test_and_set_bit(__IXGBE_HANG_CHECK_ARMED,
+ &tx_ring->state);
+ /* update completed stats and continue */
+ tx_ring->tx_stats.tx_done_old = tx_done;
+ /* reset the countdown */
+ clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
- return ret;
+ return false;
}
/**
@@ -4701,18 +4695,18 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
ret = hw->mac.ops.check_link(hw, &speed, &link_up, false);
if (ret)
- goto link_cfg_out;
+ return ret;
speed = hw->phy.autoneg_advertised;
if ((!speed) && (hw->mac.ops.get_link_capabilities))
ret = hw->mac.ops.get_link_capabilities(hw, &speed,
&autoneg);
if (ret)
- goto link_cfg_out;
+ return ret;
if (hw->mac.ops.setup_link)
ret = hw->mac.ops.setup_link(hw, speed, link_up);
-link_cfg_out:
+
return ret;
}
@@ -7973,23 +7967,32 @@ static const struct net_device_ops ixgbe_netdev_ops = {
**/
static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
{
- struct list_head *entry;
+ struct pci_dev *entry, *pdev = adapter->pdev;
int physfns = 0;
/* Some cards can not use the generic count PCIe functions method,
* because they are behind a parent switch, so we hardcode these with
* the correct number of functions.
*/
- if (ixgbe_pcie_from_parent(&adapter->hw)) {
+ if (ixgbe_pcie_from_parent(&adapter->hw))
physfns = 4;
- } else {
- list_for_each(entry, &adapter->pdev->bus_list) {
- struct pci_dev *pdev =
- list_entry(entry, struct pci_dev, bus_list);
- /* don't count virtual functions */
- if (!pdev->is_virtfn)
- physfns++;
- }
+
+ list_for_each_entry(entry, &adapter->pdev->bus->devices, bus_list) {
+ /* don't count virtual functions */
+ if (entry->is_virtfn)
+ continue;
+
+ /* When the devices on the bus don't all match our device ID,
+ * we can't reliably determine the correct number of
+ * functions. This can occur if a function has been direct
+ * attached to a virtual machine using VT-d, for example. In
+ * this case, simply return -1 to indicate this.
+ */
+ if ((entry->vendor != pdev->vendor) ||
+ (entry->device != pdev->device))
+ return -1;
+
+ physfns++;
}
return physfns;
@@ -8161,7 +8164,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->netdev_ops = &ixgbe_netdev_ops;
ixgbe_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ;
- strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+ strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
adapter->bd_number = cards_found;
@@ -8384,11 +8387,14 @@ skip_sriov:
expected_gts = ixgbe_enumerate_functions(adapter) * 10;
break;
}
- ixgbe_check_minimum_link(adapter, expected_gts);
- err = ixgbe_read_pba_string_generic(hw, part_str, IXGBE_PBANUM_LENGTH);
+ /* don't check link if we failed to enumerate functions */
+ if (expected_gts > 0)
+ ixgbe_check_minimum_link(adapter, expected_gts);
+
+ err = ixgbe_read_pba_string_generic(hw, part_str, sizeof(part_str));
if (err)
- strncpy(part_str, "Unknown", IXGBE_PBANUM_LENGTH);
+ strlcpy(part_str, "Unknown", sizeof(part_str));
if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
hw->mac.type, hw->phy.type, hw->phy.sfp_type,
@@ -8477,7 +8483,7 @@ err_alloc_etherdev:
pci_select_bars(pdev, IORESOURCE_MEM));
err_pci_reg:
err_dma:
- if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+ if (!adapter || !test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
pci_disable_device(pdev);
return err;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
index 1918e0abf734..cc8f0128286c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -43,16 +43,15 @@
s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
/* limit read to size of mailbox */
if (size > mbx->size)
size = mbx->size;
- if (mbx->ops.read)
- ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+ if (!mbx->ops.read)
+ return IXGBE_ERR_MBX;
- return ret_val;
+ return mbx->ops.read(hw, msg, size, mbx_id);
}
/**
@@ -67,15 +66,14 @@ s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = 0;
if (size > mbx->size)
- ret_val = IXGBE_ERR_MBX;
+ return IXGBE_ERR_MBX;
- else if (mbx->ops.write)
- ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+ if (!mbx->ops.write)
+ return IXGBE_ERR_MBX;
- return ret_val;
+ return mbx->ops.write(hw, msg, size, mbx_id);
}
/**
@@ -88,12 +86,11 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
- if (mbx->ops.check_for_msg)
- ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+ if (!mbx->ops.check_for_msg)
+ return IXGBE_ERR_MBX;
- return ret_val;
+ return mbx->ops.check_for_msg(hw, mbx_id);
}
/**
@@ -106,12 +103,11 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
- if (mbx->ops.check_for_ack)
- ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+ if (!mbx->ops.check_for_ack)
+ return IXGBE_ERR_MBX;
- return ret_val;
+ return mbx->ops.check_for_ack(hw, mbx_id);
}
/**
@@ -124,12 +120,11 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
- if (mbx->ops.check_for_rst)
- ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+ if (!mbx->ops.check_for_rst)
+ return IXGBE_ERR_MBX;
- return ret_val;
+ return mbx->ops.check_for_rst(hw, mbx_id);
}
/**
@@ -145,17 +140,16 @@ static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
int countdown = mbx->timeout;
if (!countdown || !mbx->ops.check_for_msg)
- goto out;
+ return IXGBE_ERR_MBX;
- while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+ while (mbx->ops.check_for_msg(hw, mbx_id)) {
countdown--;
if (!countdown)
- break;
+ return IXGBE_ERR_MBX;
udelay(mbx->usec_delay);
}
-out:
- return countdown ? 0 : IXGBE_ERR_MBX;
+ return 0;
}
/**
@@ -171,17 +165,16 @@ static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
int countdown = mbx->timeout;
if (!countdown || !mbx->ops.check_for_ack)
- goto out;
+ return IXGBE_ERR_MBX;
- while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+ while (mbx->ops.check_for_ack(hw, mbx_id)) {
countdown--;
if (!countdown)
- break;
+ return IXGBE_ERR_MBX;
udelay(mbx->usec_delay);
}
-out:
- return countdown ? 0 : IXGBE_ERR_MBX;
+ return 0;
}
/**
@@ -198,18 +191,17 @@ static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
+ s32 ret_val;
if (!mbx->ops.read)
- goto out;
+ return IXGBE_ERR_MBX;
ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+ if (ret_val)
+ return ret_val;
- /* if ack received read message, otherwise we timed out */
- if (!ret_val)
- ret_val = mbx->ops.read(hw, msg, size, mbx_id);
-out:
- return ret_val;
+ /* if ack received read message */
+ return mbx->ops.read(hw, msg, size, mbx_id);
}
/**
@@ -226,33 +218,31 @@ static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
u16 mbx_id)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- s32 ret_val = IXGBE_ERR_MBX;
+ s32 ret_val;
/* exit if either we can't write or there isn't a defined timeout */
if (!mbx->ops.write || !mbx->timeout)
- goto out;
+ return IXGBE_ERR_MBX;
/* send msg */
ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+ if (ret_val)
+ return ret_val;
/* if msg sent wait until we receive an ack */
- if (!ret_val)
- ret_val = ixgbe_poll_for_ack(hw, mbx_id);
-out:
- return ret_val;
+ return ixgbe_poll_for_ack(hw, mbx_id);
}
static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
{
u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
- s32 ret_val = IXGBE_ERR_MBX;
if (mbvficr & mask) {
- ret_val = 0;
IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
+ return 0;
}
- return ret_val;
+ return IXGBE_ERR_MBX;
}
/**
@@ -264,17 +254,16 @@ static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
**/
static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
{
- s32 ret_val = IXGBE_ERR_MBX;
s32 index = IXGBE_MBVFICR_INDEX(vf_number);
u32 vf_bit = vf_number % 16;
if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
index)) {
- ret_val = 0;
hw->mbx.stats.reqs++;
+ return 0;
}
- return ret_val;
+ return IXGBE_ERR_MBX;
}
/**
@@ -286,17 +275,16 @@ static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
**/
static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
{
- s32 ret_val = IXGBE_ERR_MBX;
s32 index = IXGBE_MBVFICR_INDEX(vf_number);
u32 vf_bit = vf_number % 16;
if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
index)) {
- ret_val = 0;
hw->mbx.stats.acks++;
+ return 0;
}
- return ret_val;
+ return IXGBE_ERR_MBX;
}
/**
@@ -311,7 +299,6 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
u32 reg_offset = (vf_number < 32) ? 0 : 1;
u32 vf_shift = vf_number % 32;
u32 vflre = 0;
- s32 ret_val = IXGBE_ERR_MBX;
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
@@ -325,12 +312,12 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
}
if (vflre & (1 << vf_shift)) {
- ret_val = 0;
IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
hw->mbx.stats.rsts++;
+ return 0;
}
- return ret_val;
+ return IXGBE_ERR_MBX;
}
/**
@@ -342,7 +329,6 @@ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
**/
static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
{
- s32 ret_val = IXGBE_ERR_MBX;
u32 p2v_mailbox;
/* Take ownership of the buffer */
@@ -351,9 +337,9 @@ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
/* reserve mailbox for vf use */
p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
- ret_val = 0;
+ return 0;
- return ret_val;
+ return IXGBE_ERR_MBX;
}
/**
@@ -374,7 +360,7 @@ static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
/* lock the mailbox to prevent pf/vf race condition */
ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
if (ret_val)
- goto out_no_write;
+ return ret_val;
/* flush msg and acks as we are overwriting the message buffer */
ixgbe_check_for_msg_pf(hw, vf_number);
@@ -390,9 +376,7 @@ static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
/* update stats */
hw->mbx.stats.msgs_tx++;
-out_no_write:
- return ret_val;
-
+ return 0;
}
/**
@@ -415,7 +399,7 @@ static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
/* lock the mailbox to prevent pf/vf race condition */
ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
if (ret_val)
- goto out_no_read;
+ return ret_val;
/* copy the message to the mailbox memory buffer */
for (i = 0; i < size; i++)
@@ -427,8 +411,7 @@ static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
/* update stats */
hw->mbx.stats.msgs_rx++;
-out_no_read:
- return ret_val;
+ return 0;
}
#ifdef CONFIG_PCI_IOV
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index ff68b7a9deff..11f02ea78c4a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -57,7 +57,6 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
**/
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 phy_addr;
u16 ext_ability = 0;
@@ -84,18 +83,14 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
ixgbe_phy_generic;
}
- status = 0;
- break;
+ return 0;
}
}
/* clear value if nothing found */
- if (status != 0)
- hw->phy.mdio.prtad = 0;
- } else {
- status = 0;
+ hw->phy.mdio.prtad = 0;
+ return IXGBE_ERR_PHY_ADDR_INVALID;
}
-
- return status;
+ return 0;
}
/**
@@ -192,16 +187,16 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
status = ixgbe_identify_phy_generic(hw);
if (status != 0 || hw->phy.type == ixgbe_phy_none)
- goto out;
+ return status;
/* Don't reset PHY if it's shut down due to overtemp. */
if (!hw->phy.reset_if_overtemp &&
(IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
- goto out;
+ return 0;
/* Blocked by MNG FW so bail */
if (ixgbe_check_reset_blocked(hw))
- goto out;
+ return 0;
/*
* Perform soft PHY reset to the PHY_XS.
@@ -227,12 +222,11 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
}
if (ctrl & MDIO_CTRL1_RESET) {
- status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "PHY reset polling failed to complete.\n");
+ return IXGBE_ERR_RESET_FAILED;
}
-out:
- return status;
+ return 0;
}
/**
@@ -333,7 +327,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
phy_data);
hw->mac.ops.release_swfw_sync(hw, gssr);
} else {
- status = IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
}
return status;
@@ -436,7 +430,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
phy_data);
hw->mac.ops.release_swfw_sync(hw, gssr);
} else {
- status = IXGBE_ERR_SWFW_SYNC;
+ return IXGBE_ERR_SWFW_SYNC;
}
return status;
@@ -509,7 +503,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
/* Blocked by MNG FW so don't reset PHY */
if (ixgbe_check_reset_blocked(hw))
- return status;
+ return 0;
/* Restart PHY autonegotiation and wait for completion */
hw->phy.ops.read_reg(hw, MDIO_CTRL1,
@@ -535,8 +529,8 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
}
if (time_out == max_time_out) {
- status = IXGBE_ERR_LINK_SETUP;
hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out\n");
+ return IXGBE_ERR_LINK_SETUP;
}
return status;
@@ -585,7 +579,7 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg)
{
- s32 status = IXGBE_ERR_LINK_SETUP;
+ s32 status;
u16 speed_ability;
*speed = 0;
@@ -616,7 +610,7 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up)
{
- s32 status = 0;
+ s32 status;
u32 time_out;
u32 max_time_out = 10;
u16 phy_link = 0;
@@ -662,7 +656,7 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
**/
s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
{
- s32 status = 0;
+ s32 status;
u32 time_out;
u32 max_time_out = 10;
u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
@@ -719,7 +713,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
/* Blocked by MNG FW so don't reset PHY */
if (ixgbe_check_reset_blocked(hw))
- return status;
+ return 0;
/* Restart PHY autonegotiation and wait for completion */
hw->phy.ops.read_reg(hw, MDIO_CTRL1,
@@ -744,8 +738,8 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
}
if (time_out == max_time_out) {
- status = IXGBE_ERR_LINK_SETUP;
hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out\n");
+ return IXGBE_ERR_LINK_SETUP;
}
return status;
@@ -759,7 +753,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version)
{
- s32 status = 0;
+ s32 status;
status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
MDIO_MMD_VEND1,
@@ -776,7 +770,7 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
u16 *firmware_version)
{
- s32 status = 0;
+ s32 status;
status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
MDIO_MMD_VEND1,
@@ -795,12 +789,12 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
bool end_data = false;
u16 list_offset, data_offset;
u16 phy_data = 0;
- s32 ret_val = 0;
+ s32 ret_val;
u32 i;
/* Blocked by MNG FW so bail */
if (ixgbe_check_reset_blocked(hw))
- goto out;
+ return 0;
hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &phy_data);
@@ -818,15 +812,14 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
if ((phy_data & MDIO_CTRL1_RESET) != 0) {
hw_dbg(hw, "PHY reset did not complete.\n");
- ret_val = IXGBE_ERR_PHY;
- goto out;
+ return IXGBE_ERR_PHY;
}
/* Get init offsets */
ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
&data_offset);
- if (ret_val != 0)
- goto out;
+ if (ret_val)
+ return ret_val;
ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
data_offset++;
@@ -876,18 +869,15 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
hw_dbg(hw, "SOL\n");
} else {
hw_dbg(hw, "Bad control value\n");
- ret_val = IXGBE_ERR_PHY;
- goto out;
+ return IXGBE_ERR_PHY;
}
break;
default:
hw_dbg(hw, "Bad control type\n");
- ret_val = IXGBE_ERR_PHY;
- goto out;
+ return IXGBE_ERR_PHY;
}
}
-out:
return ret_val;
err_eeprom:
@@ -903,34 +893,29 @@ err_eeprom:
**/
s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_SFP_NOT_PRESENT;
-
switch (hw->mac.ops.get_media_type(hw)) {
case ixgbe_media_type_fiber:
- status = ixgbe_identify_sfp_module_generic(hw);
- break;
+ return ixgbe_identify_sfp_module_generic(hw);
case ixgbe_media_type_fiber_qsfp:
- status = ixgbe_identify_qsfp_module_generic(hw);
- break;
+ return ixgbe_identify_qsfp_module_generic(hw);
default:
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
- status = IXGBE_ERR_SFP_NOT_PRESENT;
- break;
+ return IXGBE_ERR_SFP_NOT_PRESENT;
}
- return status;
+ return IXGBE_ERR_SFP_NOT_PRESENT;
}
/**
* ixgbe_identify_sfp_module_generic - Identifies SFP modules
* @hw: pointer to hardware structure
-*
+ *
* Searches for and identifies the SFP module and assigns appropriate PHY type.
**/
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
{
struct ixgbe_adapter *adapter = hw->back;
- s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+ s32 status;
u32 vendor_oui = 0;
enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
u8 identifier = 0;
@@ -943,15 +928,14 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
- status = IXGBE_ERR_SFP_NOT_PRESENT;
- goto out;
+ return IXGBE_ERR_SFP_NOT_PRESENT;
}
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_IDENTIFIER,
&identifier);
- if (status != 0)
+ if (status)
goto err_read_i2c_eeprom;
/* LAN ID is needed for sfp_type determination */
@@ -959,239 +943,224 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
hw->phy.type = ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- } else {
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_1GBE_COMP_CODES,
- &comp_codes_1g);
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_1GBE_COMP_CODES,
+ &comp_codes_1g);
- if (status != 0)
- goto err_read_i2c_eeprom;
+ if (status)
+ goto err_read_i2c_eeprom;
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_10GBE_COMP_CODES,
- &comp_codes_10g);
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_10GBE_COMP_CODES,
+ &comp_codes_10g);
- if (status != 0)
- goto err_read_i2c_eeprom;
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_CABLE_TECHNOLOGY,
- &cable_tech);
+ if (status)
+ goto err_read_i2c_eeprom;
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_CABLE_TECHNOLOGY,
+ &cable_tech);
- if (status != 0)
- goto err_read_i2c_eeprom;
+ if (status)
+ goto err_read_i2c_eeprom;
- /* ID Module
- * =========
- * 0 SFP_DA_CU
- * 1 SFP_SR
- * 2 SFP_LR
- * 3 SFP_DA_CORE0 - 82599-specific
- * 4 SFP_DA_CORE1 - 82599-specific
- * 5 SFP_SR/LR_CORE0 - 82599-specific
- * 6 SFP_SR/LR_CORE1 - 82599-specific
- * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
- * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
- * 9 SFP_1g_cu_CORE0 - 82599-specific
- * 10 SFP_1g_cu_CORE1 - 82599-specific
- * 11 SFP_1g_sx_CORE0 - 82599-specific
- * 12 SFP_1g_sx_CORE1 - 82599-specific
- */
- if (hw->mac.type == ixgbe_mac_82598EB) {
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
- else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_sr;
- else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_lr;
+ /* ID Module
+ * =========
+ * 0 SFP_DA_CU
+ * 1 SFP_SR
+ * 2 SFP_LR
+ * 3 SFP_DA_CORE0 - 82599-specific
+ * 4 SFP_DA_CORE1 - 82599-specific
+ * 5 SFP_SR/LR_CORE0 - 82599-specific
+ * 6 SFP_SR/LR_CORE1 - 82599-specific
+ * 7 SFP_act_lmt_DA_CORE0 - 82599-specific
+ * 8 SFP_act_lmt_DA_CORE1 - 82599-specific
+ * 9 SFP_1g_cu_CORE0 - 82599-specific
+ * 10 SFP_1g_cu_CORE1 - 82599-specific
+ * 11 SFP_1g_sx_CORE0 - 82599-specific
+ * 12 SFP_1g_sx_CORE1 - 82599-specific
+ */
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_sr;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_lr;
+ else
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ } else if (hw->mac.type == ixgbe_mac_82599EB) {
+ if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_cu_core0;
else
- hw->phy.sfp_type = ixgbe_sfp_type_unknown;
- } else if (hw->mac.type == ixgbe_mac_82599EB) {
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) {
- if (hw->bus.lan_id == 0)
- hw->phy.sfp_type =
- ixgbe_sfp_type_da_cu_core0;
- else
- hw->phy.sfp_type =
- ixgbe_sfp_type_da_cu_core1;
- } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
- hw->phy.ops.read_i2c_eeprom(
- hw, IXGBE_SFF_CABLE_SPEC_COMP,
- &cable_spec);
- if (cable_spec &
- IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
- if (hw->bus.lan_id == 0)
- hw->phy.sfp_type =
- ixgbe_sfp_type_da_act_lmt_core0;
- else
- hw->phy.sfp_type =
- ixgbe_sfp_type_da_act_lmt_core1;
- } else {
- hw->phy.sfp_type =
- ixgbe_sfp_type_unknown;
- }
- } else if (comp_codes_10g &
- (IXGBE_SFF_10GBASESR_CAPABLE |
- IXGBE_SFF_10GBASELR_CAPABLE)) {
- if (hw->bus.lan_id == 0)
- hw->phy.sfp_type =
- ixgbe_sfp_type_srlr_core0;
- else
- hw->phy.sfp_type =
- ixgbe_sfp_type_srlr_core1;
- } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
- if (hw->bus.lan_id == 0)
- hw->phy.sfp_type =
- ixgbe_sfp_type_1g_cu_core0;
- else
- hw->phy.sfp_type =
- ixgbe_sfp_type_1g_cu_core1;
- } else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) {
- if (hw->bus.lan_id == 0)
- hw->phy.sfp_type =
- ixgbe_sfp_type_1g_sx_core0;
- else
- hw->phy.sfp_type =
- ixgbe_sfp_type_1g_sx_core1;
- } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_cu_core1;
+ } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) {
+ hw->phy.ops.read_i2c_eeprom(
+ hw, IXGBE_SFF_CABLE_SPEC_COMP,
+ &cable_spec);
+ if (cable_spec &
+ IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) {
if (hw->bus.lan_id == 0)
hw->phy.sfp_type =
- ixgbe_sfp_type_1g_lx_core0;
+ ixgbe_sfp_type_da_act_lmt_core0;
else
hw->phy.sfp_type =
- ixgbe_sfp_type_1g_lx_core1;
+ ixgbe_sfp_type_da_act_lmt_core1;
} else {
- hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_unknown;
}
+ } else if (comp_codes_10g &
+ (IXGBE_SFF_10GBASESR_CAPABLE |
+ IXGBE_SFF_10GBASELR_CAPABLE)) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core1;
+ } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_cu_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_cu_core1;
+ } else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_sx_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_sx_core1;
+ } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) {
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_lx_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_1g_lx_core1;
+ } else {
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
}
+ }
- if (hw->phy.sfp_type != stored_sfp_type)
- hw->phy.sfp_setup_needed = true;
-
- /* Determine if the SFP+ PHY is dual speed or not. */
- hw->phy.multispeed_fiber = false;
- if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
- (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
- ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
- (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
- hw->phy.multispeed_fiber = true;
-
- /* Determine PHY vendor */
- if (hw->phy.type != ixgbe_phy_nl) {
- hw->phy.id = identifier;
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_VENDOR_OUI_BYTE0,
- &oui_bytes[0]);
-
- if (status != 0)
- goto err_read_i2c_eeprom;
-
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_VENDOR_OUI_BYTE1,
- &oui_bytes[1]);
-
- if (status != 0)
- goto err_read_i2c_eeprom;
-
- status = hw->phy.ops.read_i2c_eeprom(hw,
- IXGBE_SFF_VENDOR_OUI_BYTE2,
- &oui_bytes[2]);
-
- if (status != 0)
- goto err_read_i2c_eeprom;
-
- vendor_oui =
- ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
- (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
- (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
-
- switch (vendor_oui) {
- case IXGBE_SFF_VENDOR_OUI_TYCO:
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
- hw->phy.type =
- ixgbe_phy_sfp_passive_tyco;
- break;
- case IXGBE_SFF_VENDOR_OUI_FTL:
- if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
- hw->phy.type = ixgbe_phy_sfp_ftl_active;
- else
- hw->phy.type = ixgbe_phy_sfp_ftl;
- break;
- case IXGBE_SFF_VENDOR_OUI_AVAGO:
- hw->phy.type = ixgbe_phy_sfp_avago;
- break;
- case IXGBE_SFF_VENDOR_OUI_INTEL:
- hw->phy.type = ixgbe_phy_sfp_intel;
- break;
- default:
- if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
- hw->phy.type =
- ixgbe_phy_sfp_passive_unknown;
- else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
- hw->phy.type =
- ixgbe_phy_sfp_active_unknown;
- else
- hw->phy.type = ixgbe_phy_sfp_unknown;
- break;
- }
- }
+ if (hw->phy.sfp_type != stored_sfp_type)
+ hw->phy.sfp_setup_needed = true;
- /* Allow any DA cable vendor */
- if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
- IXGBE_SFF_DA_ACTIVE_CABLE)) {
- status = 0;
- goto out;
- }
+ /* Determine if the SFP+ PHY is dual speed or not. */
+ hw->phy.multispeed_fiber = false;
+ if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+ (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+ ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+ (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+ hw->phy.multispeed_fiber = true;
- /* Verify supported 1G SFP modules */
- if (comp_codes_10g == 0 &&
- !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
- hw->phy.type = ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- goto out;
- }
+ /* Determine PHY vendor */
+ if (hw->phy.type != ixgbe_phy_nl) {
+ hw->phy.id = identifier;
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE0,
+ &oui_bytes[0]);
- /* Anything else 82598-based is supported */
- if (hw->mac.type == ixgbe_mac_82598EB) {
- status = 0;
- goto out;
- }
+ if (status != 0)
+ goto err_read_i2c_eeprom;
- hw->mac.ops.get_device_caps(hw, &enforce_sfp);
- if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
- !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
- /* Make sure we're a supported PHY type */
- if (hw->phy.type == ixgbe_phy_sfp_intel) {
- status = 0;
- } else {
- if (hw->allow_unsupported_sfp) {
- e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
- status = 0;
- } else {
- hw_dbg(hw,
- "SFP+ module not supported\n");
- hw->phy.type =
- ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- }
- }
- } else {
- status = 0;
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE1,
+ &oui_bytes[1]);
+
+ if (status != 0)
+ goto err_read_i2c_eeprom;
+
+ status = hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE2,
+ &oui_bytes[2]);
+
+ if (status != 0)
+ goto err_read_i2c_eeprom;
+
+ vendor_oui =
+ ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+ (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+ (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+
+ switch (vendor_oui) {
+ case IXGBE_SFF_VENDOR_OUI_TYCO:
+ if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+ hw->phy.type =
+ ixgbe_phy_sfp_passive_tyco;
+ break;
+ case IXGBE_SFF_VENDOR_OUI_FTL:
+ if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+ hw->phy.type = ixgbe_phy_sfp_ftl_active;
+ else
+ hw->phy.type = ixgbe_phy_sfp_ftl;
+ break;
+ case IXGBE_SFF_VENDOR_OUI_AVAGO:
+ hw->phy.type = ixgbe_phy_sfp_avago;
+ break;
+ case IXGBE_SFF_VENDOR_OUI_INTEL:
+ hw->phy.type = ixgbe_phy_sfp_intel;
+ break;
+ default:
+ if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
+ hw->phy.type =
+ ixgbe_phy_sfp_passive_unknown;
+ else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
+ hw->phy.type =
+ ixgbe_phy_sfp_active_unknown;
+ else
+ hw->phy.type = ixgbe_phy_sfp_unknown;
+ break;
}
}
-out:
- return status;
+ /* Allow any DA cable vendor */
+ if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
+ IXGBE_SFF_DA_ACTIVE_CABLE))
+ return 0;
+
+ /* Verify supported 1G SFP modules */
+ if (comp_codes_10g == 0 &&
+ !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
+ hw->phy.type = ixgbe_phy_sfp_unsupported;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+
+ /* Anything else 82598-based is supported */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return 0;
+
+ hw->mac.ops.get_device_caps(hw, &enforce_sfp);
+ if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
+ !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
+ hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
+ /* Make sure we're a supported PHY type */
+ if (hw->phy.type == ixgbe_phy_sfp_intel)
+ return 0;
+ if (hw->allow_unsupported_sfp) {
+ e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
+ return 0;
+ }
+ hw_dbg(hw, "SFP+ module not supported\n");
+ hw->phy.type = ixgbe_phy_sfp_unsupported;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+ return 0;
err_read_i2c_eeprom:
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
@@ -1211,7 +1180,7 @@ err_read_i2c_eeprom:
static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
{
struct ixgbe_adapter *adapter = hw->back;
- s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+ s32 status;
u32 vendor_oui = 0;
enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
u8 identifier = 0;
@@ -1226,8 +1195,7 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
- status = IXGBE_ERR_SFP_NOT_PRESENT;
- goto out;
+ return IXGBE_ERR_SFP_NOT_PRESENT;
}
status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
@@ -1238,8 +1206,7 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
hw->phy.type = ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- goto out;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
}
hw->phy.id = identifier;
@@ -1310,8 +1277,7 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
} else {
/* unsupported module type */
hw->phy.type = ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- goto out;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
}
}
@@ -1363,27 +1329,19 @@ static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
hw->mac.ops.get_device_caps(hw, &enforce_sfp);
if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
/* Make sure we're a supported PHY type */
- if (hw->phy.type == ixgbe_phy_qsfp_intel) {
- status = 0;
- } else {
- if (hw->allow_unsupported_sfp == true) {
- e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
- status = 0;
- } else {
- hw_dbg(hw,
- "QSFP module not supported\n");
- hw->phy.type =
- ixgbe_phy_sfp_unsupported;
- status = IXGBE_ERR_SFP_NOT_SUPPORTED;
- }
+ if (hw->phy.type == ixgbe_phy_qsfp_intel)
+ return 0;
+ if (hw->allow_unsupported_sfp) {
+ e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n");
+ return 0;
}
- } else {
- status = 0;
+ hw_dbg(hw, "QSFP module not supported\n");
+ hw->phy.type = ixgbe_phy_sfp_unsupported;
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
}
+ return 0;
}
-
-out:
- return status;
+ return 0;
err_read_i2c_eeprom:
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
@@ -1544,7 +1502,7 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data)
{
- s32 status = 0;
+ s32 status;
u32 max_retry = 10;
u32 retry = 0;
u16 swfw_mask = 0;
@@ -1557,10 +1515,8 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
swfw_mask = IXGBE_GSSR_PHY0_SM;
do {
- if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
- status = IXGBE_ERR_SWFW_SYNC;
- goto read_byte_out;
- }
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ return IXGBE_ERR_SWFW_SYNC;
ixgbe_i2c_start(hw);
@@ -1617,7 +1573,6 @@ fail:
hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-read_byte_out:
return status;
}
@@ -1633,7 +1588,7 @@ read_byte_out:
s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data)
{
- s32 status = 0;
+ s32 status;
u32 max_retry = 1;
u32 retry = 0;
u16 swfw_mask = 0;
@@ -1643,10 +1598,8 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
- if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
- status = IXGBE_ERR_SWFW_SYNC;
- goto write_byte_out;
- }
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
+ return IXGBE_ERR_SWFW_SYNC;
do {
ixgbe_i2c_start(hw);
@@ -1689,7 +1642,6 @@ fail:
hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-write_byte_out:
return status;
}
@@ -1774,7 +1726,7 @@ static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
**/
static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
{
- s32 status = 0;
+ s32 status;
s32 i;
u32 i2cctl;
bool bit = false;
@@ -1893,11 +1845,11 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
*/
udelay(IXGBE_I2C_T_LOW);
} else {
- status = IXGBE_ERR_I2C;
hw_dbg(hw, "I2C data was not set to %X\n", data);
+ return IXGBE_ERR_I2C;
}
- return status;
+ return 0;
}
/**
* ixgbe_raise_i2c_clk - Raises the I2C SCL clock
@@ -1954,8 +1906,6 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
**/
static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
{
- s32 status = 0;
-
if (data)
*i2cctl |= IXGBE_I2C_DATA_OUT;
else
@@ -1970,11 +1920,11 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
/* Verify data was set correctly */
*i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
if (data != ixgbe_get_i2c_data(i2cctl)) {
- status = IXGBE_ERR_I2C;
hw_dbg(hw, "Error - I2C data was not set to %X.\n", data);
+ return IXGBE_ERR_I2C;
}
- return status;
+ return 0;
}
/**
@@ -1986,14 +1936,9 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
**/
static bool ixgbe_get_i2c_data(u32 *i2cctl)
{
- bool data;
-
if (*i2cctl & IXGBE_I2C_DATA_IN)
- data = true;
- else
- data = false;
-
- return data;
+ return true;
+ return false;
}
/**
@@ -2038,20 +1983,17 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
**/
s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
{
- s32 status = 0;
u16 phy_data = 0;
if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
- goto out;
+ return 0;
/* Check that the LASI temp alarm status was triggered */
hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
MDIO_MMD_PMAPMD, &phy_data);
if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
- goto out;
+ return 0;
- status = IXGBE_ERR_OVERTEMP;
-out:
- return status;
+ return IXGBE_ERR_OVERTEMP;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 68f87ecb8a76..5fd4b5271f9a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -98,9 +98,11 @@
#define IXGBE_OVERFLOW_PERIOD (HZ * 30)
#define IXGBE_PTP_TX_TIMEOUT (HZ * 15)
-#ifndef NSECS_PER_SEC
-#define NSECS_PER_SEC 1000000000ULL
-#endif
+/* half of a one second clock period, for use with PPS signal. We have to use
+ * this instead of something pre-defined like IXGBE_PTP_PPS_HALF_SECOND, in
+ * order to force at least 64bits of precision for shifting
+ */
+#define IXGBE_PTP_PPS_HALF_SECOND 500000000ULL
/**
* ixgbe_ptp_setup_sdp
@@ -146,8 +148,8 @@ static void ixgbe_ptp_setup_sdp(struct ixgbe_adapter *adapter)
IXGBE_TSAUXC_SDP0_INT);
/* clock period (or pulse length) */
- clktiml = (u32)(NSECS_PER_SEC << shift);
- clktimh = (u32)((NSECS_PER_SEC << shift) >> 32);
+ clktiml = (u32)(IXGBE_PTP_PPS_HALF_SECOND << shift);
+ clktimh = (u32)((IXGBE_PTP_PPS_HALF_SECOND << shift) >> 32);
/*
* Account for the cyclecounter wrap-around value by
@@ -158,8 +160,8 @@ static void ixgbe_ptp_setup_sdp(struct ixgbe_adapter *adapter)
clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
ns = timecounter_cyc2time(&adapter->tc, clock_edge);
- div_u64_rem(ns, NSECS_PER_SEC, &rem);
- clock_edge += ((NSECS_PER_SEC - (u64)rem) << shift);
+ div_u64_rem(ns, IXGBE_PTP_PPS_HALF_SECOND, &rem);
+ clock_edge += ((IXGBE_PTP_PPS_HALF_SECOND - (u64)rem) << shift);
/* specify the initial clock start time */
trgttiml = (u32)clock_edge;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 16b3a1cd9db6..c14d4d89672f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -245,10 +245,10 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
if (pre_existing_vfs && pre_existing_vfs != num_vfs)
err = ixgbe_disable_sriov(adapter);
else if (pre_existing_vfs && pre_existing_vfs == num_vfs)
- goto out;
+ return num_vfs;
if (err)
- goto err_out;
+ return err;
/* While the SR-IOV capability structure reports total VFs to be
* 64 we limit the actual number that can be allocated to 63 so
@@ -256,16 +256,14 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
* PF. The PCI bus driver already checks for other values out of
* range.
*/
- if (num_vfs > IXGBE_MAX_VFS_DRV_LIMIT) {
- err = -EPERM;
- goto err_out;
- }
+ if (num_vfs > IXGBE_MAX_VFS_DRV_LIMIT)
+ return -EPERM;
adapter->num_vfs = num_vfs;
err = __ixgbe_enable_sriov(adapter);
if (err)
- goto err_out;
+ return err;
for (i = 0; i < adapter->num_vfs; i++)
ixgbe_vf_configuration(dev, (i | 0x10000000));
@@ -273,17 +271,14 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
err = pci_enable_sriov(dev, num_vfs);
if (err) {
e_dev_warn("Failed to enable PCI sriov: %d\n", err);
- goto err_out;
+ return err;
}
ixgbe_sriov_reinit(adapter);
-out:
return num_vfs;
-
-err_out:
- return err;
-#endif
+#else
return 0;
+#endif
}
static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
@@ -807,7 +802,7 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
if (!add && adapter->netdev->flags & IFF_PROMISC) {
reg_ndx = ixgbe_find_vlvf_entry(hw, vid);
if (reg_ndx < 0)
- goto out;
+ return err;
vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(reg_ndx));
/* See if any other pools are set for this VLAN filter
* entry other than the PF.
@@ -833,8 +828,6 @@ static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
ixgbe_set_vf_vlan(adapter, add, vid, VMDQ_P(0));
}
-out:
-
return err;
}
@@ -951,7 +944,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
/* this is a message we already processed, do nothing */
if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK))
- return retval;
+ return 0;
/* flush the ack before we write any messages back */
IXGBE_WRITE_FLUSH(hw);
@@ -966,7 +959,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
if (!adapter->vfinfo[vf].clear_to_send) {
msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
ixgbe_write_mbx(hw, msgbuf, 1, vf);
- return retval;
+ return 0;
}
switch ((msgbuf[0] & 0xFFFF)) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 9a89f98b35f0..e6b07c2a01fe 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -2440,25 +2440,6 @@ typedef u32 ixgbe_link_speed;
IXGBE_LINK_SPEED_1GB_FULL | \
IXGBE_LINK_SPEED_10GB_FULL)
-
-/* Physical layer type */
-typedef u32 ixgbe_physical_layer;
-#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0
-#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001
-#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002
-#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004
-#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010
-#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020
-#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080
-#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100
-#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200
-#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400
-#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800
-#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000
-#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000
-
/* Flow Control Data Sheet defined values
* Calculation and defines taken from 802.1bb Annex O
*/
@@ -2860,7 +2841,6 @@ struct ixgbe_mac_operations {
s32 (*start_hw)(struct ixgbe_hw *);
s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
- u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*get_device_caps)(struct ixgbe_hw *, u16 *);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 40dd798e1290..e88305d5d18d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2013 Intel Corporation.
+ Copyright(c) 1999 - 2014 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,
@@ -99,8 +99,8 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
/* Call adapter stop to disable tx/rx and clear interrupts */
status = hw->mac.ops.stop_adapter(hw);
- if (status != 0)
- goto reset_hw_out;
+ if (status)
+ return status;
/* flush pending Tx transactions */
ixgbe_clear_tx_pending(hw);
@@ -168,7 +168,6 @@ mac_reset_top:
hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
&hw->mac.wwpn_prefix);
-reset_hw_out:
return status;
}
@@ -182,40 +181,13 @@ reset_hw_out:
**/
static s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw)
{
- s32 ret_val = 0;
+ s32 ret_val;
ret_val = ixgbe_start_hw_generic(hw);
- if (ret_val != 0)
- goto out;
+ if (ret_val)
+ return ret_val;
- ret_val = ixgbe_start_hw_gen2(hw);
-out:
- return ret_val;
-}
-
-/**
- * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
- * @hw: pointer to hardware structure
- *
- * Determines physical layer capabilities of the current configuration.
- **/
-static u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
-{
- u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
- u16 ext_ability = 0;
-
- hw->phy.ops.identify(hw);
-
- hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
- &ext_ability);
- if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
- physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
- if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
- physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
-
- return physical_layer;
+ return ixgbe_start_hw_gen2(hw);
}
/**
@@ -258,13 +230,12 @@ static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
**/
static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
- s32 status = 0;
+ s32 status;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
- 0)
- status = ixgbe_read_eerd_generic(hw, offset, data);
- else
- status = IXGBE_ERR_SWFW_SYNC;
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = ixgbe_read_eerd_generic(hw, offset, data);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
@@ -282,14 +253,12 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
static s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
u16 offset, u16 words, u16 *data)
{
- s32 status = 0;
+ s32 status;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
- 0)
- status = ixgbe_read_eerd_buffer_generic(hw, offset,
- words, data);
- else
- status = IXGBE_ERR_SWFW_SYNC;
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
@@ -305,12 +274,12 @@ static s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
**/
static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
{
- s32 status = 0;
+ s32 status;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
- status = ixgbe_write_eewr_generic(hw, offset, data);
- else
- status = IXGBE_ERR_SWFW_SYNC;
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = ixgbe_write_eewr_generic(hw, offset, data);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
@@ -328,14 +297,12 @@ static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
u16 offset, u16 words, u16 *data)
{
- s32 status = 0;
+ s32 status;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
- 0)
- status = ixgbe_write_eewr_buffer_generic(hw, offset,
- words, data);
- else
- status = IXGBE_ERR_SWFW_SYNC;
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
+
+ status = ixgbe_write_eewr_buffer_generic(hw, offset, words, data);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
@@ -430,44 +397,37 @@ static s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
u16 checksum;
u16 read_checksum = 0;
- /*
- * Read the first word from the EEPROM. If this times out or fails, do
+ /* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);
-
- if (status != 0) {
+ if (status) {
hw_dbg(hw, "EEPROM read failed\n");
- goto out;
+ return status;
}
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
- checksum = hw->eeprom.ops.calc_checksum(hw);
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
- /*
- * Do not use hw->eeprom.ops.read because we do not want to take
- * the synchronization semaphores twice here.
- */
- ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
- &read_checksum);
+ checksum = hw->eeprom.ops.calc_checksum(hw);
- /*
- * Verify read checksum from EEPROM is the same as
- * calculated checksum
- */
- if (read_checksum != checksum)
- status = IXGBE_ERR_EEPROM_CHECKSUM;
-
- /* If the user cares, return the calculated checksum */
- if (checksum_val)
- *checksum_val = checksum;
- } else {
- status = IXGBE_ERR_SWFW_SYNC;
- }
+ /* Do not use hw->eeprom.ops.read because we do not want to take
+ * the synchronization semaphores twice here.
+ */
+ status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
+ &read_checksum);
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-out:
+
+ /* If the user cares, return the calculated checksum */
+ if (checksum_val)
+ *checksum_val = checksum;
+
+ /* Verify read and calculated checksums are the same */
+ if (read_checksum != checksum)
+ return IXGBE_ERR_EEPROM_CHECKSUM;
+
return status;
}
@@ -484,34 +444,29 @@ static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
s32 status;
u16 checksum;
- /*
- * Read the first word from the EEPROM. If this times out or fails, do
+ /* Read the first word from the EEPROM. If this times out or fails, do
* not continue or we could be in for a very long wait while every
* EEPROM read fails
*/
status = hw->eeprom.ops.read(hw, 0, &checksum);
-
- if (status != 0)
+ if (status) {
hw_dbg(hw, "EEPROM read failed\n");
+ return status;
+ }
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
- checksum = hw->eeprom.ops.calc_checksum(hw);
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
+ return IXGBE_ERR_SWFW_SYNC;
- /*
- * Do not use hw->eeprom.ops.write because we do not want to
- * take the synchronization semaphores twice here.
- */
- status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
- checksum);
+ checksum = hw->eeprom.ops.calc_checksum(hw);
- if (status == 0)
+ /* Do not use hw->eeprom.ops.write because we do not want to
+ * take the synchronization semaphores twice here.
+ */
+ status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum);
+ if (!status)
status = ixgbe_update_flash_X540(hw);
- else
- status = IXGBE_ERR_SWFW_SYNC;
- }
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-
return status;
}
@@ -525,12 +480,12 @@ static s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
{
u32 flup;
- s32 status = IXGBE_ERR_EEPROM;
+ s32 status;
status = ixgbe_poll_flash_update_done_X540(hw);
if (status == IXGBE_ERR_EEPROM) {
hw_dbg(hw, "Flash update time out\n");
- goto out;
+ return status;
}
flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
@@ -556,7 +511,7 @@ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw)
else
hw_dbg(hw, "Flash update time out\n");
}
-out:
+
return status;
}
@@ -571,17 +526,14 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
{
u32 i;
u32 reg;
- s32 status = IXGBE_ERR_EEPROM;
for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
reg = IXGBE_READ_REG(hw, IXGBE_EEC);
- if (reg & IXGBE_EEC_FLUDONE) {
- status = 0;
- break;
- }
+ if (reg & IXGBE_EEC_FLUDONE)
+ return 0;
udelay(5);
}
- return status;
+ return IXGBE_ERR_EEPROM;
}
/**
@@ -676,46 +628,44 @@ static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
}
/**
- * ixgbe_get_nvm_semaphore - Get hardware semaphore
+ * ixgbe_get_swfw_sync_semaphore - Get hardware semaphore
* @hw: pointer to hardware structure
*
* Sets the hardware semaphores so SW/FW can gain control of shared resources
- **/
+ */
static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
{
- s32 status = IXGBE_ERR_EEPROM;
u32 timeout = 2000;
u32 i;
u32 swsm;
/* Get SMBI software semaphore between device drivers first */
for (i = 0; i < timeout; i++) {
- /*
- * If the SMBI bit is 0 when we read it, then the bit will be
+ /* If the SMBI bit is 0 when we read it, then the bit will be
* set and we have the semaphore
*/
swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
- if (!(swsm & IXGBE_SWSM_SMBI)) {
- status = 0;
+ if (!(swsm & IXGBE_SWSM_SMBI))
break;
- }
- udelay(50);
+ usleep_range(50, 100);
+ }
+
+ if (i == timeout) {
+ hw_dbg(hw,
+ "Software semaphore SMBI between device drivers not granted.\n");
+ return IXGBE_ERR_EEPROM;
}
/* Now get the semaphore between SW/FW through the REGSMP bit */
- if (status) {
- for (i = 0; i < timeout; i++) {
- swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
- if (!(swsm & IXGBE_SWFW_REGSMP))
- break;
+ for (i = 0; i < timeout; i++) {
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ if (!(swsm & IXGBE_SWFW_REGSMP))
+ return 0;
- udelay(50);
- }
- } else {
- hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
+ usleep_range(50, 100);
}
- return status;
+ return IXGBE_ERR_EEPROM;
}
/**
@@ -811,8 +761,6 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.start_hw = &ixgbe_start_hw_X540,
.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic,
.get_media_type = &ixgbe_get_media_type_X540,
- .get_supported_physical_layer =
- &ixgbe_get_supported_physical_layer_X540,
.enable_rx_dma = &ixgbe_enable_rx_dma_generic,
.get_mac_addr = &ixgbe_get_mac_addr_generic,
.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 75467f83772c..c22a00c3621a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -76,7 +76,7 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
* { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
* Class, Class Mask, private data (not used) }
*/
-static DEFINE_PCI_DEVICE_TABLE(ixgbevf_pci_tbl) = {
+static const struct pci_device_id ixgbevf_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },
/* required last entry */
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 3061d1890471..aa8cc8dc25d1 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -49,7 +49,6 @@ struct ixgbe_mac_operations {
s32 (*start_hw)(struct ixgbe_hw *);
s32 (*clear_hw_cntrs)(struct ixgbe_hw *);
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
- u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
s32 (*stop_adapter)(struct ixgbe_hw *);
s32 (*get_bus_info)(struct ixgbe_hw *);
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index b78378cea5e3..4a1be34d7214 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -3334,7 +3334,7 @@ static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume);
#define JME_PM_OPS NULL
#endif
-static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
+static const struct pci_device_id jme_pci_tbl[] = {
{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) },
{ PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) },
{ }
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index 68e6a6613e9a..1b4fc7c639e6 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -54,6 +54,14 @@ config MVNETA
driver, which should be used for the older Marvell SoCs
(Dove, Orion, Discovery, Kirkwood).
+config MVPP2
+ tristate "Marvell Armada 375 network interface support"
+ depends on MACH_ARMADA_375
+ select MVMDIO
+ ---help---
+ This driver supports the network interface units in the
+ Marvell ARMADA 375 SoC.
+
config PXA168_ETH
tristate "Marvell pxa168 ethernet support"
depends on CPU_PXA168
diff --git a/drivers/net/ethernet/marvell/Makefile b/drivers/net/ethernet/marvell/Makefile
index 5c4a7765ff0e..f6425bd2884b 100644
--- a/drivers/net/ethernet/marvell/Makefile
+++ b/drivers/net/ethernet/marvell/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_MVMDIO) += mvmdio.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
obj-$(CONFIG_MVNETA) += mvneta.o
+obj-$(CONFIG_MVPP2) += mvpp2.o
obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SKY2) += sky2.o
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index dadd9a5f6323..c9f1d1b7ef37 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2969,14 +2969,14 @@ static int mvneta_probe(struct platform_device *pdev)
/* In the case of a fixed PHY, the DT node associated
* to the PHY is the Ethernet MAC DT node.
*/
- phy_node = dn;
+ phy_node = of_node_get(dn);
}
phy_mode = of_get_phy_mode(dn);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy-mode\n");
err = -EINVAL;
- goto err_free_irq;
+ goto err_put_phy_node;
}
dev->tx_queue_len = MVNETA_MAX_TXD;
@@ -2992,7 +2992,7 @@ static int mvneta_probe(struct platform_device *pdev)
pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
err = PTR_ERR(pp->clk);
- goto err_free_irq;
+ goto err_put_phy_node;
}
clk_prepare_enable(pp->clk);
@@ -3071,6 +3071,8 @@ err_free_stats:
free_percpu(pp->stats);
err_clk:
clk_disable_unprepare(pp->clk);
+err_put_phy_node:
+ of_node_put(phy_node);
err_free_irq:
irq_dispose_mapping(dev->irq);
err_free_netdev:
@@ -3088,6 +3090,7 @@ static int mvneta_remove(struct platform_device *pdev)
clk_disable_unprepare(pp->clk);
free_percpu(pp->stats);
irq_dispose_mapping(dev->irq);
+ of_node_put(pp->phy_node);
free_netdev(dev);
return 0;
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
new file mode 100644
index 000000000000..ece83f101526
--- /dev/null
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -0,0 +1,6426 @@
+/*
+ * Driver for Marvell PPv2 network controller for Armada 375 SoC.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Marcin Wojtas <mw@semihalf.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/inetdevice.h>
+#include <linux/mbus.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/cpumask.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <uapi/linux/ppp_defs.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+/* RX Fifo Registers */
+#define MVPP2_RX_DATA_FIFO_SIZE_REG(port) (0x00 + 4 * (port))
+#define MVPP2_RX_ATTR_FIFO_SIZE_REG(port) (0x20 + 4 * (port))
+#define MVPP2_RX_MIN_PKT_SIZE_REG 0x60
+#define MVPP2_RX_FIFO_INIT_REG 0x64
+
+/* RX DMA Top Registers */
+#define MVPP2_RX_CTRL_REG(port) (0x140 + 4 * (port))
+#define MVPP2_RX_LOW_LATENCY_PKT_SIZE(s) (((s) & 0xfff) << 16)
+#define MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK BIT(31)
+#define MVPP2_POOL_BUF_SIZE_REG(pool) (0x180 + 4 * (pool))
+#define MVPP2_POOL_BUF_SIZE_OFFSET 5
+#define MVPP2_RXQ_CONFIG_REG(rxq) (0x800 + 4 * (rxq))
+#define MVPP2_SNOOP_PKT_SIZE_MASK 0x1ff
+#define MVPP2_SNOOP_BUF_HDR_MASK BIT(9)
+#define MVPP2_RXQ_POOL_SHORT_OFFS 20
+#define MVPP2_RXQ_POOL_SHORT_MASK 0x700000
+#define MVPP2_RXQ_POOL_LONG_OFFS 24
+#define MVPP2_RXQ_POOL_LONG_MASK 0x7000000
+#define MVPP2_RXQ_PACKET_OFFSET_OFFS 28
+#define MVPP2_RXQ_PACKET_OFFSET_MASK 0x70000000
+#define MVPP2_RXQ_DISABLE_MASK BIT(31)
+
+/* Parser Registers */
+#define MVPP2_PRS_INIT_LOOKUP_REG 0x1000
+#define MVPP2_PRS_PORT_LU_MAX 0xf
+#define MVPP2_PRS_PORT_LU_MASK(port) (0xff << ((port) * 4))
+#define MVPP2_PRS_PORT_LU_VAL(port, val) ((val) << ((port) * 4))
+#define MVPP2_PRS_INIT_OFFS_REG(port) (0x1004 + ((port) & 4))
+#define MVPP2_PRS_INIT_OFF_MASK(port) (0x3f << (((port) % 4) * 8))
+#define MVPP2_PRS_INIT_OFF_VAL(port, val) ((val) << (((port) % 4) * 8))
+#define MVPP2_PRS_MAX_LOOP_REG(port) (0x100c + ((port) & 4))
+#define MVPP2_PRS_MAX_LOOP_MASK(port) (0xff << (((port) % 4) * 8))
+#define MVPP2_PRS_MAX_LOOP_VAL(port, val) ((val) << (((port) % 4) * 8))
+#define MVPP2_PRS_TCAM_IDX_REG 0x1100
+#define MVPP2_PRS_TCAM_DATA_REG(idx) (0x1104 + (idx) * 4)
+#define MVPP2_PRS_TCAM_INV_MASK BIT(31)
+#define MVPP2_PRS_SRAM_IDX_REG 0x1200
+#define MVPP2_PRS_SRAM_DATA_REG(idx) (0x1204 + (idx) * 4)
+#define MVPP2_PRS_TCAM_CTRL_REG 0x1230
+#define MVPP2_PRS_TCAM_EN_MASK BIT(0)
+
+/* Classifier Registers */
+#define MVPP2_CLS_MODE_REG 0x1800
+#define MVPP2_CLS_MODE_ACTIVE_MASK BIT(0)
+#define MVPP2_CLS_PORT_WAY_REG 0x1810
+#define MVPP2_CLS_PORT_WAY_MASK(port) (1 << (port))
+#define MVPP2_CLS_LKP_INDEX_REG 0x1814
+#define MVPP2_CLS_LKP_INDEX_WAY_OFFS 6
+#define MVPP2_CLS_LKP_TBL_REG 0x1818
+#define MVPP2_CLS_LKP_TBL_RXQ_MASK 0xff
+#define MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK BIT(25)
+#define MVPP2_CLS_FLOW_INDEX_REG 0x1820
+#define MVPP2_CLS_FLOW_TBL0_REG 0x1824
+#define MVPP2_CLS_FLOW_TBL1_REG 0x1828
+#define MVPP2_CLS_FLOW_TBL2_REG 0x182c
+#define MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port) (0x1980 + ((port) * 4))
+#define MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS 3
+#define MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK 0x7
+#define MVPP2_CLS_SWFWD_P2HQ_REG(port) (0x19b0 + ((port) * 4))
+#define MVPP2_CLS_SWFWD_PCTRL_REG 0x19d0
+#define MVPP2_CLS_SWFWD_PCTRL_MASK(port) (1 << (port))
+
+/* Descriptor Manager Top Registers */
+#define MVPP2_RXQ_NUM_REG 0x2040
+#define MVPP2_RXQ_DESC_ADDR_REG 0x2044
+#define MVPP2_RXQ_DESC_SIZE_REG 0x2048
+#define MVPP2_RXQ_DESC_SIZE_MASK 0x3ff0
+#define MVPP2_RXQ_STATUS_UPDATE_REG(rxq) (0x3000 + 4 * (rxq))
+#define MVPP2_RXQ_NUM_PROCESSED_OFFSET 0
+#define MVPP2_RXQ_NUM_NEW_OFFSET 16
+#define MVPP2_RXQ_STATUS_REG(rxq) (0x3400 + 4 * (rxq))
+#define MVPP2_RXQ_OCCUPIED_MASK 0x3fff
+#define MVPP2_RXQ_NON_OCCUPIED_OFFSET 16
+#define MVPP2_RXQ_NON_OCCUPIED_MASK 0x3fff0000
+#define MVPP2_RXQ_THRESH_REG 0x204c
+#define MVPP2_OCCUPIED_THRESH_OFFSET 0
+#define MVPP2_OCCUPIED_THRESH_MASK 0x3fff
+#define MVPP2_RXQ_INDEX_REG 0x2050
+#define MVPP2_TXQ_NUM_REG 0x2080
+#define MVPP2_TXQ_DESC_ADDR_REG 0x2084
+#define MVPP2_TXQ_DESC_SIZE_REG 0x2088
+#define MVPP2_TXQ_DESC_SIZE_MASK 0x3ff0
+#define MVPP2_AGGR_TXQ_UPDATE_REG 0x2090
+#define MVPP2_TXQ_THRESH_REG 0x2094
+#define MVPP2_TRANSMITTED_THRESH_OFFSET 16
+#define MVPP2_TRANSMITTED_THRESH_MASK 0x3fff0000
+#define MVPP2_TXQ_INDEX_REG 0x2098
+#define MVPP2_TXQ_PREF_BUF_REG 0x209c
+#define MVPP2_PREF_BUF_PTR(desc) ((desc) & 0xfff)
+#define MVPP2_PREF_BUF_SIZE_4 (BIT(12) | BIT(13))
+#define MVPP2_PREF_BUF_SIZE_16 (BIT(12) | BIT(14))
+#define MVPP2_PREF_BUF_THRESH(val) ((val) << 17)
+#define MVPP2_TXQ_DRAIN_EN_MASK BIT(31)
+#define MVPP2_TXQ_PENDING_REG 0x20a0
+#define MVPP2_TXQ_PENDING_MASK 0x3fff
+#define MVPP2_TXQ_INT_STATUS_REG 0x20a4
+#define MVPP2_TXQ_SENT_REG(txq) (0x3c00 + 4 * (txq))
+#define MVPP2_TRANSMITTED_COUNT_OFFSET 16
+#define MVPP2_TRANSMITTED_COUNT_MASK 0x3fff0000
+#define MVPP2_TXQ_RSVD_REQ_REG 0x20b0
+#define MVPP2_TXQ_RSVD_REQ_Q_OFFSET 16
+#define MVPP2_TXQ_RSVD_RSLT_REG 0x20b4
+#define MVPP2_TXQ_RSVD_RSLT_MASK 0x3fff
+#define MVPP2_TXQ_RSVD_CLR_REG 0x20b8
+#define MVPP2_TXQ_RSVD_CLR_OFFSET 16
+#define MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu) (0x2100 + 4 * (cpu))
+#define MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu) (0x2140 + 4 * (cpu))
+#define MVPP2_AGGR_TXQ_DESC_SIZE_MASK 0x3ff0
+#define MVPP2_AGGR_TXQ_STATUS_REG(cpu) (0x2180 + 4 * (cpu))
+#define MVPP2_AGGR_TXQ_PENDING_MASK 0x3fff
+#define MVPP2_AGGR_TXQ_INDEX_REG(cpu) (0x21c0 + 4 * (cpu))
+
+/* MBUS bridge registers */
+#define MVPP2_WIN_BASE(w) (0x4000 + ((w) << 2))
+#define MVPP2_WIN_SIZE(w) (0x4020 + ((w) << 2))
+#define MVPP2_WIN_REMAP(w) (0x4040 + ((w) << 2))
+#define MVPP2_BASE_ADDR_ENABLE 0x4060
+
+/* Interrupt Cause and Mask registers */
+#define MVPP2_ISR_RX_THRESHOLD_REG(rxq) (0x5200 + 4 * (rxq))
+#define MVPP2_ISR_RXQ_GROUP_REG(rxq) (0x5400 + 4 * (rxq))
+#define MVPP2_ISR_ENABLE_REG(port) (0x5420 + 4 * (port))
+#define MVPP2_ISR_ENABLE_INTERRUPT(mask) ((mask) & 0xffff)
+#define MVPP2_ISR_DISABLE_INTERRUPT(mask) (((mask) << 16) & 0xffff0000)
+#define MVPP2_ISR_RX_TX_CAUSE_REG(port) (0x5480 + 4 * (port))
+#define MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK 0xffff
+#define MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK 0xff0000
+#define MVPP2_CAUSE_RX_FIFO_OVERRUN_MASK BIT(24)
+#define MVPP2_CAUSE_FCS_ERR_MASK BIT(25)
+#define MVPP2_CAUSE_TX_FIFO_UNDERRUN_MASK BIT(26)
+#define MVPP2_CAUSE_TX_EXCEPTION_SUM_MASK BIT(29)
+#define MVPP2_CAUSE_RX_EXCEPTION_SUM_MASK BIT(30)
+#define MVPP2_CAUSE_MISC_SUM_MASK BIT(31)
+#define MVPP2_ISR_RX_TX_MASK_REG(port) (0x54a0 + 4 * (port))
+#define MVPP2_ISR_PON_RX_TX_MASK_REG 0x54bc
+#define MVPP2_PON_CAUSE_RXQ_OCCUP_DESC_ALL_MASK 0xffff
+#define MVPP2_PON_CAUSE_TXP_OCCUP_DESC_ALL_MASK 0x3fc00000
+#define MVPP2_PON_CAUSE_MISC_SUM_MASK BIT(31)
+#define MVPP2_ISR_MISC_CAUSE_REG 0x55b0
+
+/* Buffer Manager registers */
+#define MVPP2_BM_POOL_BASE_REG(pool) (0x6000 + ((pool) * 4))
+#define MVPP2_BM_POOL_BASE_ADDR_MASK 0xfffff80
+#define MVPP2_BM_POOL_SIZE_REG(pool) (0x6040 + ((pool) * 4))
+#define MVPP2_BM_POOL_SIZE_MASK 0xfff0
+#define MVPP2_BM_POOL_READ_PTR_REG(pool) (0x6080 + ((pool) * 4))
+#define MVPP2_BM_POOL_GET_READ_PTR_MASK 0xfff0
+#define MVPP2_BM_POOL_PTRS_NUM_REG(pool) (0x60c0 + ((pool) * 4))
+#define MVPP2_BM_POOL_PTRS_NUM_MASK 0xfff0
+#define MVPP2_BM_BPPI_READ_PTR_REG(pool) (0x6100 + ((pool) * 4))
+#define MVPP2_BM_BPPI_PTRS_NUM_REG(pool) (0x6140 + ((pool) * 4))
+#define MVPP2_BM_BPPI_PTR_NUM_MASK 0x7ff
+#define MVPP2_BM_BPPI_PREFETCH_FULL_MASK BIT(16)
+#define MVPP2_BM_POOL_CTRL_REG(pool) (0x6200 + ((pool) * 4))
+#define MVPP2_BM_START_MASK BIT(0)
+#define MVPP2_BM_STOP_MASK BIT(1)
+#define MVPP2_BM_STATE_MASK BIT(4)
+#define MVPP2_BM_LOW_THRESH_OFFS 8
+#define MVPP2_BM_LOW_THRESH_MASK 0x7f00
+#define MVPP2_BM_LOW_THRESH_VALUE(val) ((val) << \
+ MVPP2_BM_LOW_THRESH_OFFS)
+#define MVPP2_BM_HIGH_THRESH_OFFS 16
+#define MVPP2_BM_HIGH_THRESH_MASK 0x7f0000
+#define MVPP2_BM_HIGH_THRESH_VALUE(val) ((val) << \
+ MVPP2_BM_HIGH_THRESH_OFFS)
+#define MVPP2_BM_INTR_CAUSE_REG(pool) (0x6240 + ((pool) * 4))
+#define MVPP2_BM_RELEASED_DELAY_MASK BIT(0)
+#define MVPP2_BM_ALLOC_FAILED_MASK BIT(1)
+#define MVPP2_BM_BPPE_EMPTY_MASK BIT(2)
+#define MVPP2_BM_BPPE_FULL_MASK BIT(3)
+#define MVPP2_BM_AVAILABLE_BP_LOW_MASK BIT(4)
+#define MVPP2_BM_INTR_MASK_REG(pool) (0x6280 + ((pool) * 4))
+#define MVPP2_BM_PHY_ALLOC_REG(pool) (0x6400 + ((pool) * 4))
+#define MVPP2_BM_PHY_ALLOC_GRNTD_MASK BIT(0)
+#define MVPP2_BM_VIRT_ALLOC_REG 0x6440
+#define MVPP2_BM_PHY_RLS_REG(pool) (0x6480 + ((pool) * 4))
+#define MVPP2_BM_PHY_RLS_MC_BUFF_MASK BIT(0)
+#define MVPP2_BM_PHY_RLS_PRIO_EN_MASK BIT(1)
+#define MVPP2_BM_PHY_RLS_GRNTD_MASK BIT(2)
+#define MVPP2_BM_VIRT_RLS_REG 0x64c0
+#define MVPP2_BM_MC_RLS_REG 0x64c4
+#define MVPP2_BM_MC_ID_MASK 0xfff
+#define MVPP2_BM_FORCE_RELEASE_MASK BIT(12)
+
+/* TX Scheduler registers */
+#define MVPP2_TXP_SCHED_PORT_INDEX_REG 0x8000
+#define MVPP2_TXP_SCHED_Q_CMD_REG 0x8004
+#define MVPP2_TXP_SCHED_ENQ_MASK 0xff
+#define MVPP2_TXP_SCHED_DISQ_OFFSET 8
+#define MVPP2_TXP_SCHED_CMD_1_REG 0x8010
+#define MVPP2_TXP_SCHED_PERIOD_REG 0x8018
+#define MVPP2_TXP_SCHED_MTU_REG 0x801c
+#define MVPP2_TXP_MTU_MAX 0x7FFFF
+#define MVPP2_TXP_SCHED_REFILL_REG 0x8020
+#define MVPP2_TXP_REFILL_TOKENS_ALL_MASK 0x7ffff
+#define MVPP2_TXP_REFILL_PERIOD_ALL_MASK 0x3ff00000
+#define MVPP2_TXP_REFILL_PERIOD_MASK(v) ((v) << 20)
+#define MVPP2_TXP_SCHED_TOKEN_SIZE_REG 0x8024
+#define MVPP2_TXP_TOKEN_SIZE_MAX 0xffffffff
+#define MVPP2_TXQ_SCHED_REFILL_REG(q) (0x8040 + ((q) << 2))
+#define MVPP2_TXQ_REFILL_TOKENS_ALL_MASK 0x7ffff
+#define MVPP2_TXQ_REFILL_PERIOD_ALL_MASK 0x3ff00000
+#define MVPP2_TXQ_REFILL_PERIOD_MASK(v) ((v) << 20)
+#define MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(q) (0x8060 + ((q) << 2))
+#define MVPP2_TXQ_TOKEN_SIZE_MAX 0x7fffffff
+#define MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(q) (0x8080 + ((q) << 2))
+#define MVPP2_TXQ_TOKEN_CNTR_MAX 0xffffffff
+
+/* TX general registers */
+#define MVPP2_TX_SNOOP_REG 0x8800
+#define MVPP2_TX_PORT_FLUSH_REG 0x8810
+#define MVPP2_TX_PORT_FLUSH_MASK(port) (1 << (port))
+
+/* LMS registers */
+#define MVPP2_SRC_ADDR_MIDDLE 0x24
+#define MVPP2_SRC_ADDR_HIGH 0x28
+#define MVPP2_PHY_AN_CFG0_REG 0x34
+#define MVPP2_PHY_AN_STOP_SMI0_MASK BIT(7)
+#define MVPP2_MIB_COUNTERS_BASE(port) (0x1000 + ((port) >> 1) * \
+ 0x400 + (port) * 0x400)
+#define MVPP2_MIB_LATE_COLLISION 0x7c
+#define MVPP2_ISR_SUM_MASK_REG 0x220c
+#define MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG 0x305c
+#define MVPP2_EXT_GLOBAL_CTRL_DEFAULT 0x27
+
+/* Per-port registers */
+#define MVPP2_GMAC_CTRL_0_REG 0x0
+#define MVPP2_GMAC_PORT_EN_MASK BIT(0)
+#define MVPP2_GMAC_MAX_RX_SIZE_OFFS 2
+#define MVPP2_GMAC_MAX_RX_SIZE_MASK 0x7ffc
+#define MVPP2_GMAC_MIB_CNTR_EN_MASK BIT(15)
+#define MVPP2_GMAC_CTRL_1_REG 0x4
+#define MVPP2_GMAC_PERIODIC_XON_EN_MASK BIT(1)
+#define MVPP2_GMAC_GMII_LB_EN_MASK BIT(5)
+#define MVPP2_GMAC_PCS_LB_EN_BIT 6
+#define MVPP2_GMAC_PCS_LB_EN_MASK BIT(6)
+#define MVPP2_GMAC_SA_LOW_OFFS 7
+#define MVPP2_GMAC_CTRL_2_REG 0x8
+#define MVPP2_GMAC_INBAND_AN_MASK BIT(0)
+#define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3)
+#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4)
+#define MVPP2_GMAC_PORT_RESET_MASK BIT(6)
+#define MVPP2_GMAC_AUTONEG_CONFIG 0xc
+#define MVPP2_GMAC_FORCE_LINK_DOWN BIT(0)
+#define MVPP2_GMAC_FORCE_LINK_PASS BIT(1)
+#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5)
+#define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6)
+#define MVPP2_GMAC_AN_SPEED_EN BIT(7)
+#define MVPP2_GMAC_FC_ADV_EN BIT(9)
+#define MVPP2_GMAC_CONFIG_FULL_DUPLEX BIT(12)
+#define MVPP2_GMAC_AN_DUPLEX_EN BIT(13)
+#define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK 0x1fc0
+#define MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
+ MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
+
+#define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
+
+/* Descriptor ring Macros */
+#define MVPP2_QUEUE_NEXT_DESC(q, index) \
+ (((index) < (q)->last_desc) ? ((index) + 1) : 0)
+
+/* Various constants */
+
+/* Coalescing */
+#define MVPP2_TXDONE_COAL_PKTS_THRESH 15
+#define MVPP2_RX_COAL_PKTS 32
+#define MVPP2_RX_COAL_USEC 100
+
+/* The two bytes Marvell header. Either contains a special value used
+ * by Marvell switches when a specific hardware mode is enabled (not
+ * supported by this driver) or is filled automatically by zeroes on
+ * the RX side. Those two bytes being at the front of the Ethernet
+ * header, they allow to have the IP header aligned on a 4 bytes
+ * boundary automatically: the hardware skips those two bytes on its
+ * own.
+ */
+#define MVPP2_MH_SIZE 2
+#define MVPP2_ETH_TYPE_LEN 2
+#define MVPP2_PPPOE_HDR_SIZE 8
+#define MVPP2_VLAN_TAG_LEN 4
+
+/* Lbtd 802.3 type */
+#define MVPP2_IP_LBDT_TYPE 0xfffa
+
+#define MVPP2_CPU_D_CACHE_LINE_SIZE 32
+#define MVPP2_TX_CSUM_MAX_SIZE 9800
+
+/* Timeout constants */
+#define MVPP2_TX_DISABLE_TIMEOUT_MSEC 1000
+#define MVPP2_TX_PENDING_TIMEOUT_MSEC 1000
+
+#define MVPP2_TX_MTU_MAX 0x7ffff
+
+/* Maximum number of T-CONTs of PON port */
+#define MVPP2_MAX_TCONT 16
+
+/* Maximum number of supported ports */
+#define MVPP2_MAX_PORTS 4
+
+/* Maximum number of TXQs used by single port */
+#define MVPP2_MAX_TXQ 8
+
+/* Maximum number of RXQs used by single port */
+#define MVPP2_MAX_RXQ 8
+
+/* Dfault number of RXQs in use */
+#define MVPP2_DEFAULT_RXQ 4
+
+/* Total number of RXQs available to all ports */
+#define MVPP2_RXQ_TOTAL_NUM (MVPP2_MAX_PORTS * MVPP2_MAX_RXQ)
+
+/* Max number of Rx descriptors */
+#define MVPP2_MAX_RXD 128
+
+/* Max number of Tx descriptors */
+#define MVPP2_MAX_TXD 1024
+
+/* Amount of Tx descriptors that can be reserved at once by CPU */
+#define MVPP2_CPU_DESC_CHUNK 64
+
+/* Max number of Tx descriptors in each aggregated queue */
+#define MVPP2_AGGR_TXQ_SIZE 256
+
+/* Descriptor aligned size */
+#define MVPP2_DESC_ALIGNED_SIZE 32
+
+/* Descriptor alignment mask */
+#define MVPP2_TX_DESC_ALIGN (MVPP2_DESC_ALIGNED_SIZE - 1)
+
+/* RX FIFO constants */
+#define MVPP2_RX_FIFO_PORT_DATA_SIZE 0x2000
+#define MVPP2_RX_FIFO_PORT_ATTR_SIZE 0x80
+#define MVPP2_RX_FIFO_PORT_MIN_PKT 0x80
+
+/* RX buffer constants */
+#define MVPP2_SKB_SHINFO_SIZE \
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
+
+#define MVPP2_RX_PKT_SIZE(mtu) \
+ ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \
+ ETH_HLEN + ETH_FCS_LEN, MVPP2_CPU_D_CACHE_LINE_SIZE)
+
+#define MVPP2_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
+#define MVPP2_RX_TOTAL_SIZE(buf_size) ((buf_size) + MVPP2_SKB_SHINFO_SIZE)
+#define MVPP2_RX_MAX_PKT_SIZE(total_size) \
+ ((total_size) - NET_SKB_PAD - MVPP2_SKB_SHINFO_SIZE)
+
+#define MVPP2_BIT_TO_BYTE(bit) ((bit) / 8)
+
+/* IPv6 max L3 address size */
+#define MVPP2_MAX_L3_ADDR_SIZE 16
+
+/* Port flags */
+#define MVPP2_F_LOOPBACK BIT(0)
+
+/* Marvell tag types */
+enum mvpp2_tag_type {
+ MVPP2_TAG_TYPE_NONE = 0,
+ MVPP2_TAG_TYPE_MH = 1,
+ MVPP2_TAG_TYPE_DSA = 2,
+ MVPP2_TAG_TYPE_EDSA = 3,
+ MVPP2_TAG_TYPE_VLAN = 4,
+ MVPP2_TAG_TYPE_LAST = 5
+};
+
+/* Parser constants */
+#define MVPP2_PRS_TCAM_SRAM_SIZE 256
+#define MVPP2_PRS_TCAM_WORDS 6
+#define MVPP2_PRS_SRAM_WORDS 4
+#define MVPP2_PRS_FLOW_ID_SIZE 64
+#define MVPP2_PRS_FLOW_ID_MASK 0x3f
+#define MVPP2_PRS_TCAM_ENTRY_INVALID 1
+#define MVPP2_PRS_TCAM_DSA_TAGGED_BIT BIT(5)
+#define MVPP2_PRS_IPV4_HEAD 0x40
+#define MVPP2_PRS_IPV4_HEAD_MASK 0xf0
+#define MVPP2_PRS_IPV4_MC 0xe0
+#define MVPP2_PRS_IPV4_MC_MASK 0xf0
+#define MVPP2_PRS_IPV4_BC_MASK 0xff
+#define MVPP2_PRS_IPV4_IHL 0x5
+#define MVPP2_PRS_IPV4_IHL_MASK 0xf
+#define MVPP2_PRS_IPV6_MC 0xff
+#define MVPP2_PRS_IPV6_MC_MASK 0xff
+#define MVPP2_PRS_IPV6_HOP_MASK 0xff
+#define MVPP2_PRS_TCAM_PROTO_MASK 0xff
+#define MVPP2_PRS_TCAM_PROTO_MASK_L 0x3f
+#define MVPP2_PRS_DBL_VLANS_MAX 100
+
+/* Tcam structure:
+ * - lookup ID - 4 bits
+ * - port ID - 1 byte
+ * - additional information - 1 byte
+ * - header data - 8 bytes
+ * The fields are represented by MVPP2_PRS_TCAM_DATA_REG(5)->(0).
+ */
+#define MVPP2_PRS_AI_BITS 8
+#define MVPP2_PRS_PORT_MASK 0xff
+#define MVPP2_PRS_LU_MASK 0xf
+#define MVPP2_PRS_TCAM_DATA_BYTE(offs) \
+ (((offs) - ((offs) % 2)) * 2 + ((offs) % 2))
+#define MVPP2_PRS_TCAM_DATA_BYTE_EN(offs) \
+ (((offs) * 2) - ((offs) % 2) + 2)
+#define MVPP2_PRS_TCAM_AI_BYTE 16
+#define MVPP2_PRS_TCAM_PORT_BYTE 17
+#define MVPP2_PRS_TCAM_LU_BYTE 20
+#define MVPP2_PRS_TCAM_EN_OFFS(offs) ((offs) + 2)
+#define MVPP2_PRS_TCAM_INV_WORD 5
+/* Tcam entries ID */
+#define MVPP2_PE_DROP_ALL 0
+#define MVPP2_PE_FIRST_FREE_TID 1
+#define MVPP2_PE_LAST_FREE_TID (MVPP2_PRS_TCAM_SRAM_SIZE - 31)
+#define MVPP2_PE_IP6_EXT_PROTO_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 30)
+#define MVPP2_PE_MAC_MC_IP6 (MVPP2_PRS_TCAM_SRAM_SIZE - 29)
+#define MVPP2_PE_IP6_ADDR_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 28)
+#define MVPP2_PE_IP4_ADDR_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 27)
+#define MVPP2_PE_LAST_DEFAULT_FLOW (MVPP2_PRS_TCAM_SRAM_SIZE - 26)
+#define MVPP2_PE_FIRST_DEFAULT_FLOW (MVPP2_PRS_TCAM_SRAM_SIZE - 19)
+#define MVPP2_PE_EDSA_TAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 18)
+#define MVPP2_PE_EDSA_UNTAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 17)
+#define MVPP2_PE_DSA_TAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 16)
+#define MVPP2_PE_DSA_UNTAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 15)
+#define MVPP2_PE_ETYPE_EDSA_TAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 14)
+#define MVPP2_PE_ETYPE_EDSA_UNTAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 13)
+#define MVPP2_PE_ETYPE_DSA_TAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 12)
+#define MVPP2_PE_ETYPE_DSA_UNTAGGED (MVPP2_PRS_TCAM_SRAM_SIZE - 11)
+#define MVPP2_PE_MH_DEFAULT (MVPP2_PRS_TCAM_SRAM_SIZE - 10)
+#define MVPP2_PE_DSA_DEFAULT (MVPP2_PRS_TCAM_SRAM_SIZE - 9)
+#define MVPP2_PE_IP6_PROTO_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 8)
+#define MVPP2_PE_IP4_PROTO_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 7)
+#define MVPP2_PE_ETH_TYPE_UN (MVPP2_PRS_TCAM_SRAM_SIZE - 6)
+#define MVPP2_PE_VLAN_DBL (MVPP2_PRS_TCAM_SRAM_SIZE - 5)
+#define MVPP2_PE_VLAN_NONE (MVPP2_PRS_TCAM_SRAM_SIZE - 4)
+#define MVPP2_PE_MAC_MC_ALL (MVPP2_PRS_TCAM_SRAM_SIZE - 3)
+#define MVPP2_PE_MAC_PROMISCUOUS (MVPP2_PRS_TCAM_SRAM_SIZE - 2)
+#define MVPP2_PE_MAC_NON_PROMISCUOUS (MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+
+/* Sram structure
+ * The fields are represented by MVPP2_PRS_TCAM_DATA_REG(3)->(0).
+ */
+#define MVPP2_PRS_SRAM_RI_OFFS 0
+#define MVPP2_PRS_SRAM_RI_WORD 0
+#define MVPP2_PRS_SRAM_RI_CTRL_OFFS 32
+#define MVPP2_PRS_SRAM_RI_CTRL_WORD 1
+#define MVPP2_PRS_SRAM_RI_CTRL_BITS 32
+#define MVPP2_PRS_SRAM_SHIFT_OFFS 64
+#define MVPP2_PRS_SRAM_SHIFT_SIGN_BIT 72
+#define MVPP2_PRS_SRAM_UDF_OFFS 73
+#define MVPP2_PRS_SRAM_UDF_BITS 8
+#define MVPP2_PRS_SRAM_UDF_MASK 0xff
+#define MVPP2_PRS_SRAM_UDF_SIGN_BIT 81
+#define MVPP2_PRS_SRAM_UDF_TYPE_OFFS 82
+#define MVPP2_PRS_SRAM_UDF_TYPE_MASK 0x7
+#define MVPP2_PRS_SRAM_UDF_TYPE_L3 1
+#define MVPP2_PRS_SRAM_UDF_TYPE_L4 4
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS 85
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_MASK 0x3
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD 1
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_IP4_ADD 2
+#define MVPP2_PRS_SRAM_OP_SEL_SHIFT_IP6_ADD 3
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS 87
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_BITS 2
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_MASK 0x3
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_ADD 0
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_IP4_ADD 2
+#define MVPP2_PRS_SRAM_OP_SEL_UDF_IP6_ADD 3
+#define MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS 89
+#define MVPP2_PRS_SRAM_AI_OFFS 90
+#define MVPP2_PRS_SRAM_AI_CTRL_OFFS 98
+#define MVPP2_PRS_SRAM_AI_CTRL_BITS 8
+#define MVPP2_PRS_SRAM_AI_MASK 0xff
+#define MVPP2_PRS_SRAM_NEXT_LU_OFFS 106
+#define MVPP2_PRS_SRAM_NEXT_LU_MASK 0xf
+#define MVPP2_PRS_SRAM_LU_DONE_BIT 110
+#define MVPP2_PRS_SRAM_LU_GEN_BIT 111
+
+/* Sram result info bits assignment */
+#define MVPP2_PRS_RI_MAC_ME_MASK 0x1
+#define MVPP2_PRS_RI_DSA_MASK 0x2
+#define MVPP2_PRS_RI_VLAN_MASK 0xc
+#define MVPP2_PRS_RI_VLAN_NONE ~(BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_VLAN_SINGLE BIT(2)
+#define MVPP2_PRS_RI_VLAN_DOUBLE BIT(3)
+#define MVPP2_PRS_RI_VLAN_TRIPLE (BIT(2) | BIT(3))
+#define MVPP2_PRS_RI_CPU_CODE_MASK 0x70
+#define MVPP2_PRS_RI_CPU_CODE_RX_SPEC BIT(4)
+#define MVPP2_PRS_RI_L2_CAST_MASK 0x600
+#define MVPP2_PRS_RI_L2_UCAST ~(BIT(9) | BIT(10))
+#define MVPP2_PRS_RI_L2_MCAST BIT(9)
+#define MVPP2_PRS_RI_L2_BCAST BIT(10)
+#define MVPP2_PRS_RI_PPPOE_MASK 0x800
+#define MVPP2_PRS_RI_L3_PROTO_MASK 0x7000
+#define MVPP2_PRS_RI_L3_UN ~(BIT(12) | BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_IP4 BIT(12)
+#define MVPP2_PRS_RI_L3_IP4_OPT BIT(13)
+#define MVPP2_PRS_RI_L3_IP4_OTHER (BIT(12) | BIT(13))
+#define MVPP2_PRS_RI_L3_IP6 BIT(14)
+#define MVPP2_PRS_RI_L3_IP6_EXT (BIT(12) | BIT(14))
+#define MVPP2_PRS_RI_L3_ARP (BIT(13) | BIT(14))
+#define MVPP2_PRS_RI_L3_ADDR_MASK 0x18000
+#define MVPP2_PRS_RI_L3_UCAST ~(BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_L3_MCAST BIT(15)
+#define MVPP2_PRS_RI_L3_BCAST (BIT(15) | BIT(16))
+#define MVPP2_PRS_RI_IP_FRAG_MASK 0x20000
+#define MVPP2_PRS_RI_UDF3_MASK 0x300000
+#define MVPP2_PRS_RI_UDF3_RX_SPECIAL BIT(21)
+#define MVPP2_PRS_RI_L4_PROTO_MASK 0x1c00000
+#define MVPP2_PRS_RI_L4_TCP BIT(22)
+#define MVPP2_PRS_RI_L4_UDP BIT(23)
+#define MVPP2_PRS_RI_L4_OTHER (BIT(22) | BIT(23))
+#define MVPP2_PRS_RI_UDF7_MASK 0x60000000
+#define MVPP2_PRS_RI_UDF7_IP6_LITE BIT(29)
+#define MVPP2_PRS_RI_DROP_MASK 0x80000000
+
+/* Sram additional info bits assignment */
+#define MVPP2_PRS_IPV4_DIP_AI_BIT BIT(0)
+#define MVPP2_PRS_IPV6_NO_EXT_AI_BIT BIT(0)
+#define MVPP2_PRS_IPV6_EXT_AI_BIT BIT(1)
+#define MVPP2_PRS_IPV6_EXT_AH_AI_BIT BIT(2)
+#define MVPP2_PRS_IPV6_EXT_AH_LEN_AI_BIT BIT(3)
+#define MVPP2_PRS_IPV6_EXT_AH_L4_AI_BIT BIT(4)
+#define MVPP2_PRS_SINGLE_VLAN_AI 0
+#define MVPP2_PRS_DBL_VLAN_AI_BIT BIT(7)
+
+/* DSA/EDSA type */
+#define MVPP2_PRS_TAGGED true
+#define MVPP2_PRS_UNTAGGED false
+#define MVPP2_PRS_EDSA true
+#define MVPP2_PRS_DSA false
+
+/* MAC entries, shadow udf */
+enum mvpp2_prs_udf {
+ MVPP2_PRS_UDF_MAC_DEF,
+ MVPP2_PRS_UDF_MAC_RANGE,
+ MVPP2_PRS_UDF_L2_DEF,
+ MVPP2_PRS_UDF_L2_DEF_COPY,
+ MVPP2_PRS_UDF_L2_USER,
+};
+
+/* Lookup ID */
+enum mvpp2_prs_lookup {
+ MVPP2_PRS_LU_MH,
+ MVPP2_PRS_LU_MAC,
+ MVPP2_PRS_LU_DSA,
+ MVPP2_PRS_LU_VLAN,
+ MVPP2_PRS_LU_L2,
+ MVPP2_PRS_LU_PPPOE,
+ MVPP2_PRS_LU_IP4,
+ MVPP2_PRS_LU_IP6,
+ MVPP2_PRS_LU_FLOWS,
+ MVPP2_PRS_LU_LAST,
+};
+
+/* L3 cast enum */
+enum mvpp2_prs_l3_cast {
+ MVPP2_PRS_L3_UNI_CAST,
+ MVPP2_PRS_L3_MULTI_CAST,
+ MVPP2_PRS_L3_BROAD_CAST
+};
+
+/* Classifier constants */
+#define MVPP2_CLS_FLOWS_TBL_SIZE 512
+#define MVPP2_CLS_FLOWS_TBL_DATA_WORDS 3
+#define MVPP2_CLS_LKP_TBL_SIZE 64
+
+/* BM constants */
+#define MVPP2_BM_POOLS_NUM 8
+#define MVPP2_BM_LONG_BUF_NUM 1024
+#define MVPP2_BM_SHORT_BUF_NUM 2048
+#define MVPP2_BM_POOL_SIZE_MAX (16*1024 - MVPP2_BM_POOL_PTR_ALIGN/4)
+#define MVPP2_BM_POOL_PTR_ALIGN 128
+#define MVPP2_BM_SWF_LONG_POOL(port) ((port > 2) ? 2 : port)
+#define MVPP2_BM_SWF_SHORT_POOL 3
+
+/* BM cookie (32 bits) definition */
+#define MVPP2_BM_COOKIE_POOL_OFFS 8
+#define MVPP2_BM_COOKIE_CPU_OFFS 24
+
+/* BM short pool packet size
+ * These value assure that for SWF the total number
+ * of bytes allocated for each buffer will be 512
+ */
+#define MVPP2_BM_SHORT_PKT_SIZE MVPP2_RX_MAX_PKT_SIZE(512)
+
+enum mvpp2_bm_type {
+ MVPP2_BM_FREE,
+ MVPP2_BM_SWF_LONG,
+ MVPP2_BM_SWF_SHORT
+};
+
+/* Definitions */
+
+/* Shared Packet Processor resources */
+struct mvpp2 {
+ /* Shared registers' base addresses */
+ void __iomem *base;
+ void __iomem *lms_base;
+
+ /* Common clocks */
+ struct clk *pp_clk;
+ struct clk *gop_clk;
+
+ /* List of pointers to port structures */
+ struct mvpp2_port **port_list;
+
+ /* Aggregated TXQs */
+ struct mvpp2_tx_queue *aggr_txqs;
+
+ /* BM pools */
+ struct mvpp2_bm_pool *bm_pools;
+
+ /* PRS shadow table */
+ struct mvpp2_prs_shadow *prs_shadow;
+ /* PRS auxiliary table for double vlan entries control */
+ bool *prs_double_vlans;
+
+ /* Tclk value */
+ u32 tclk;
+};
+
+struct mvpp2_pcpu_stats {
+ struct u64_stats_sync syncp;
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+};
+
+struct mvpp2_port {
+ u8 id;
+
+ int irq;
+
+ struct mvpp2 *priv;
+
+ /* Per-port registers' base address */
+ void __iomem *base;
+
+ struct mvpp2_rx_queue **rxqs;
+ struct mvpp2_tx_queue **txqs;
+ struct net_device *dev;
+
+ int pkt_size;
+
+ u32 pending_cause_rx;
+ struct napi_struct napi;
+
+ /* Flags */
+ unsigned long flags;
+
+ u16 tx_ring_size;
+ u16 rx_ring_size;
+ struct mvpp2_pcpu_stats __percpu *stats;
+
+ struct phy_device *phy_dev;
+ phy_interface_t phy_interface;
+ struct device_node *phy_node;
+ unsigned int link;
+ unsigned int duplex;
+ unsigned int speed;
+
+ struct mvpp2_bm_pool *pool_long;
+ struct mvpp2_bm_pool *pool_short;
+
+ /* Index of first port's physical RXQ */
+ u8 first_rxq;
+};
+
+/* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
+ * layout of the transmit and reception DMA descriptors, and their
+ * layout is therefore defined by the hardware design
+ */
+
+#define MVPP2_TXD_L3_OFF_SHIFT 0
+#define MVPP2_TXD_IP_HLEN_SHIFT 8
+#define MVPP2_TXD_L4_CSUM_FRAG BIT(13)
+#define MVPP2_TXD_L4_CSUM_NOT BIT(14)
+#define MVPP2_TXD_IP_CSUM_DISABLE BIT(15)
+#define MVPP2_TXD_PADDING_DISABLE BIT(23)
+#define MVPP2_TXD_L4_UDP BIT(24)
+#define MVPP2_TXD_L3_IP6 BIT(26)
+#define MVPP2_TXD_L_DESC BIT(28)
+#define MVPP2_TXD_F_DESC BIT(29)
+
+#define MVPP2_RXD_ERR_SUMMARY BIT(15)
+#define MVPP2_RXD_ERR_CODE_MASK (BIT(13) | BIT(14))
+#define MVPP2_RXD_ERR_CRC 0x0
+#define MVPP2_RXD_ERR_OVERRUN BIT(13)
+#define MVPP2_RXD_ERR_RESOURCE (BIT(13) | BIT(14))
+#define MVPP2_RXD_BM_POOL_ID_OFFS 16
+#define MVPP2_RXD_BM_POOL_ID_MASK (BIT(16) | BIT(17) | BIT(18))
+#define MVPP2_RXD_HWF_SYNC BIT(21)
+#define MVPP2_RXD_L4_CSUM_OK BIT(22)
+#define MVPP2_RXD_IP4_HEADER_ERR BIT(24)
+#define MVPP2_RXD_L4_TCP BIT(25)
+#define MVPP2_RXD_L4_UDP BIT(26)
+#define MVPP2_RXD_L3_IP4 BIT(28)
+#define MVPP2_RXD_L3_IP6 BIT(30)
+#define MVPP2_RXD_BUF_HDR BIT(31)
+
+struct mvpp2_tx_desc {
+ u32 command; /* Options used by HW for packet transmitting.*/
+ u8 packet_offset; /* the offset from the buffer beginning */
+ u8 phys_txq; /* destination queue ID */
+ u16 data_size; /* data size of transmitted packet in bytes */
+ u32 buf_phys_addr; /* physical addr of transmitted buffer */
+ u32 buf_cookie; /* cookie for access to TX buffer in tx path */
+ u32 reserved1[3]; /* hw_cmd (for future use, BM, PON, PNC) */
+ u32 reserved2; /* reserved (for future use) */
+};
+
+struct mvpp2_rx_desc {
+ u32 status; /* info about received packet */
+ u16 reserved1; /* parser_info (for future use, PnC) */
+ u16 data_size; /* size of received packet in bytes */
+ u32 buf_phys_addr; /* physical address of the buffer */
+ u32 buf_cookie; /* cookie for access to RX buffer in rx path */
+ u16 reserved2; /* gem_port_id (for future use, PON) */
+ u16 reserved3; /* csum_l4 (for future use, PnC) */
+ u8 reserved4; /* bm_qset (for future use, BM) */
+ u8 reserved5;
+ u16 reserved6; /* classify_info (for future use, PnC) */
+ u32 reserved7; /* flow_id (for future use, PnC) */
+ u32 reserved8;
+};
+
+/* Per-CPU Tx queue control */
+struct mvpp2_txq_pcpu {
+ int cpu;
+
+ /* Number of Tx DMA descriptors in the descriptor ring */
+ int size;
+
+ /* Number of currently used Tx DMA descriptor in the
+ * descriptor ring
+ */
+ int count;
+
+ /* Number of Tx DMA descriptors reserved for each CPU */
+ int reserved_num;
+
+ /* Array of transmitted skb */
+ struct sk_buff **tx_skb;
+
+ /* Index of last TX DMA descriptor that was inserted */
+ int txq_put_index;
+
+ /* Index of the TX DMA descriptor to be cleaned up */
+ int txq_get_index;
+};
+
+struct mvpp2_tx_queue {
+ /* Physical number of this Tx queue */
+ u8 id;
+
+ /* Logical number of this Tx queue */
+ u8 log_id;
+
+ /* Number of Tx DMA descriptors in the descriptor ring */
+ int size;
+
+ /* Number of currently used Tx DMA descriptor in the descriptor ring */
+ int count;
+
+ /* Per-CPU control of physical Tx queues */
+ struct mvpp2_txq_pcpu __percpu *pcpu;
+
+ /* Array of transmitted skb */
+ struct sk_buff **tx_skb;
+
+ u32 done_pkts_coal;
+
+ /* Virtual address of thex Tx DMA descriptors array */
+ struct mvpp2_tx_desc *descs;
+
+ /* DMA address of the Tx DMA descriptors array */
+ dma_addr_t descs_phys;
+
+ /* Index of the last Tx DMA descriptor */
+ int last_desc;
+
+ /* Index of the next Tx DMA descriptor to process */
+ int next_desc_to_proc;
+};
+
+struct mvpp2_rx_queue {
+ /* RX queue number, in the range 0-31 for physical RXQs */
+ u8 id;
+
+ /* Num of rx descriptors in the rx descriptor ring */
+ int size;
+
+ u32 pkts_coal;
+ u32 time_coal;
+
+ /* Virtual address of the RX DMA descriptors array */
+ struct mvpp2_rx_desc *descs;
+
+ /* DMA address of the RX DMA descriptors array */
+ dma_addr_t descs_phys;
+
+ /* Index of the last RX DMA descriptor */
+ int last_desc;
+
+ /* Index of the next RX DMA descriptor to process */
+ int next_desc_to_proc;
+
+ /* ID of port to which physical RXQ is mapped */
+ int port;
+
+ /* Port's logic RXQ number to which physical RXQ is mapped */
+ int logic_rxq;
+};
+
+union mvpp2_prs_tcam_entry {
+ u32 word[MVPP2_PRS_TCAM_WORDS];
+ u8 byte[MVPP2_PRS_TCAM_WORDS * 4];
+};
+
+union mvpp2_prs_sram_entry {
+ u32 word[MVPP2_PRS_SRAM_WORDS];
+ u8 byte[MVPP2_PRS_SRAM_WORDS * 4];
+};
+
+struct mvpp2_prs_entry {
+ u32 index;
+ union mvpp2_prs_tcam_entry tcam;
+ union mvpp2_prs_sram_entry sram;
+};
+
+struct mvpp2_prs_shadow {
+ bool valid;
+ bool finish;
+
+ /* Lookup ID */
+ int lu;
+
+ /* User defined offset */
+ int udf;
+
+ /* Result info */
+ u32 ri;
+ u32 ri_mask;
+};
+
+struct mvpp2_cls_flow_entry {
+ u32 index;
+ u32 data[MVPP2_CLS_FLOWS_TBL_DATA_WORDS];
+};
+
+struct mvpp2_cls_lookup_entry {
+ u32 lkpid;
+ u32 way;
+ u32 data;
+};
+
+struct mvpp2_bm_pool {
+ /* Pool number in the range 0-7 */
+ int id;
+ enum mvpp2_bm_type type;
+
+ /* Buffer Pointers Pool External (BPPE) size */
+ int size;
+ /* Number of buffers for this pool */
+ int buf_num;
+ /* Pool buffer size */
+ int buf_size;
+ /* Packet size */
+ int pkt_size;
+
+ /* BPPE virtual base address */
+ u32 *virt_addr;
+ /* BPPE physical base address */
+ dma_addr_t phys_addr;
+
+ /* Ports using BM pool */
+ u32 port_map;
+
+ /* Occupied buffers indicator */
+ atomic_t in_use;
+ int in_use_thresh;
+
+ spinlock_t lock;
+};
+
+struct mvpp2_buff_hdr {
+ u32 next_buff_phys_addr;
+ u32 next_buff_virt_addr;
+ u16 byte_count;
+ u16 info;
+ u8 reserved1; /* bm_qset (for future use, BM) */
+};
+
+/* Buffer header info bits */
+#define MVPP2_B_HDR_INFO_MC_ID_MASK 0xfff
+#define MVPP2_B_HDR_INFO_MC_ID(info) ((info) & MVPP2_B_HDR_INFO_MC_ID_MASK)
+#define MVPP2_B_HDR_INFO_LAST_OFFS 12
+#define MVPP2_B_HDR_INFO_LAST_MASK BIT(12)
+#define MVPP2_B_HDR_INFO_IS_LAST(info) \
+ ((info & MVPP2_B_HDR_INFO_LAST_MASK) >> MVPP2_B_HDR_INFO_LAST_OFFS)
+
+/* Static declaractions */
+
+/* Number of RXQs used by single port */
+static int rxq_number = MVPP2_DEFAULT_RXQ;
+/* Number of TXQs used by single port */
+static int txq_number = MVPP2_MAX_TXQ;
+
+#define MVPP2_DRIVER_NAME "mvpp2"
+#define MVPP2_DRIVER_VERSION "1.0"
+
+/* Utility/helper methods */
+
+static void mvpp2_write(struct mvpp2 *priv, u32 offset, u32 data)
+{
+ writel(data, priv->base + offset);
+}
+
+static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)
+{
+ return readl(priv->base + offset);
+}
+
+static void mvpp2_txq_inc_get(struct mvpp2_txq_pcpu *txq_pcpu)
+{
+ txq_pcpu->txq_get_index++;
+ if (txq_pcpu->txq_get_index == txq_pcpu->size)
+ txq_pcpu->txq_get_index = 0;
+}
+
+static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
+ struct sk_buff *skb)
+{
+ txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
+ txq_pcpu->txq_put_index++;
+ if (txq_pcpu->txq_put_index == txq_pcpu->size)
+ txq_pcpu->txq_put_index = 0;
+}
+
+/* Get number of physical egress port */
+static inline int mvpp2_egress_port(struct mvpp2_port *port)
+{
+ return MVPP2_MAX_TCONT + port->id;
+}
+
+/* Get number of physical TXQ */
+static inline int mvpp2_txq_phys(int port, int txq)
+{
+ return (MVPP2_MAX_TCONT + port) * MVPP2_MAX_TXQ + txq;
+}
+
+/* Parser configuration routines */
+
+/* Update parser tcam and sram hw entries */
+static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
+{
+ int i;
+
+ if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ return -EINVAL;
+
+ /* Clear entry invalidation bit */
+ pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] &= ~MVPP2_PRS_TCAM_INV_MASK;
+
+ /* Write tcam index - indirect access */
+ mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+ for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+ mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam.word[i]);
+
+ /* Write sram index - indirect access */
+ mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index);
+ for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+ mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), pe->sram.word[i]);
+
+ return 0;
+}
+
+/* Read tcam entry from hw */
+static int mvpp2_prs_hw_read(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
+{
+ int i;
+
+ if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ return -EINVAL;
+
+ /* Write tcam index - indirect access */
+ mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+
+ pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] = mvpp2_read(priv,
+ MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD));
+ if (pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] & MVPP2_PRS_TCAM_INV_MASK)
+ return MVPP2_PRS_TCAM_ENTRY_INVALID;
+
+ for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+ pe->tcam.word[i] = mvpp2_read(priv, MVPP2_PRS_TCAM_DATA_REG(i));
+
+ /* Write sram index - indirect access */
+ mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index);
+ for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+ pe->sram.word[i] = mvpp2_read(priv, MVPP2_PRS_SRAM_DATA_REG(i));
+
+ return 0;
+}
+
+/* Invalidate tcam hw entry */
+static void mvpp2_prs_hw_inv(struct mvpp2 *priv, int index)
+{
+ /* Write index - indirect access */
+ mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, index);
+ mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD),
+ MVPP2_PRS_TCAM_INV_MASK);
+}
+
+/* Enable shadow table entry and set its lookup ID */
+static void mvpp2_prs_shadow_set(struct mvpp2 *priv, int index, int lu)
+{
+ priv->prs_shadow[index].valid = true;
+ priv->prs_shadow[index].lu = lu;
+}
+
+/* Update ri fields in shadow table entry */
+static void mvpp2_prs_shadow_ri_set(struct mvpp2 *priv, int index,
+ unsigned int ri, unsigned int ri_mask)
+{
+ priv->prs_shadow[index].ri_mask = ri_mask;
+ priv->prs_shadow[index].ri = ri;
+}
+
+/* Update lookup field in tcam sw entry */
+static void mvpp2_prs_tcam_lu_set(struct mvpp2_prs_entry *pe, unsigned int lu)
+{
+ int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_LU_BYTE);
+
+ pe->tcam.byte[MVPP2_PRS_TCAM_LU_BYTE] = lu;
+ pe->tcam.byte[enable_off] = MVPP2_PRS_LU_MASK;
+}
+
+/* Update mask for single port in tcam sw entry */
+static void mvpp2_prs_tcam_port_set(struct mvpp2_prs_entry *pe,
+ unsigned int port, bool add)
+{
+ int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+ if (add)
+ pe->tcam.byte[enable_off] &= ~(1 << port);
+ else
+ pe->tcam.byte[enable_off] |= 1 << port;
+}
+
+/* Update port map in tcam sw entry */
+static void mvpp2_prs_tcam_port_map_set(struct mvpp2_prs_entry *pe,
+ unsigned int ports)
+{
+ unsigned char port_mask = MVPP2_PRS_PORT_MASK;
+ int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+ pe->tcam.byte[MVPP2_PRS_TCAM_PORT_BYTE] = 0;
+ pe->tcam.byte[enable_off] &= ~port_mask;
+ pe->tcam.byte[enable_off] |= ~ports & MVPP2_PRS_PORT_MASK;
+}
+
+/* Obtain port map from tcam sw entry */
+static unsigned int mvpp2_prs_tcam_port_map_get(struct mvpp2_prs_entry *pe)
+{
+ int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
+
+ return ~(pe->tcam.byte[enable_off]) & MVPP2_PRS_PORT_MASK;
+}
+
+/* Set byte of data and its enable bits in tcam sw entry */
+static void mvpp2_prs_tcam_data_byte_set(struct mvpp2_prs_entry *pe,
+ unsigned int offs, unsigned char byte,
+ unsigned char enable)
+{
+ pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)] = byte;
+ pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)] = enable;
+}
+
+/* Get byte of data and its enable bits from tcam sw entry */
+static void mvpp2_prs_tcam_data_byte_get(struct mvpp2_prs_entry *pe,
+ unsigned int offs, unsigned char *byte,
+ unsigned char *enable)
+{
+ *byte = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)];
+ *enable = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)];
+}
+
+/* Compare tcam data bytes with a pattern */
+static bool mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *pe, int offs,
+ u16 data)
+{
+ int off = MVPP2_PRS_TCAM_DATA_BYTE(offs);
+ u16 tcam_data;
+
+ tcam_data = (8 << pe->tcam.byte[off + 1]) | pe->tcam.byte[off];
+ if (tcam_data != data)
+ return false;
+ return true;
+}
+
+/* Update ai bits in tcam sw entry */
+static void mvpp2_prs_tcam_ai_update(struct mvpp2_prs_entry *pe,
+ unsigned int bits, unsigned int enable)
+{
+ int i, ai_idx = MVPP2_PRS_TCAM_AI_BYTE;
+
+ for (i = 0; i < MVPP2_PRS_AI_BITS; i++) {
+
+ if (!(enable & BIT(i)))
+ continue;
+
+ if (bits & BIT(i))
+ pe->tcam.byte[ai_idx] |= 1 << i;
+ else
+ pe->tcam.byte[ai_idx] &= ~(1 << i);
+ }
+
+ pe->tcam.byte[MVPP2_PRS_TCAM_EN_OFFS(ai_idx)] |= enable;
+}
+
+/* Get ai bits from tcam sw entry */
+static int mvpp2_prs_tcam_ai_get(struct mvpp2_prs_entry *pe)
+{
+ return pe->tcam.byte[MVPP2_PRS_TCAM_AI_BYTE];
+}
+
+/* Set ethertype in tcam sw entry */
+static void mvpp2_prs_match_etype(struct mvpp2_prs_entry *pe, int offset,
+ unsigned short ethertype)
+{
+ mvpp2_prs_tcam_data_byte_set(pe, offset + 0, ethertype >> 8, 0xff);
+ mvpp2_prs_tcam_data_byte_set(pe, offset + 1, ethertype & 0xff, 0xff);
+}
+
+/* Set bits in sram sw entry */
+static void mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry *pe, int bit_num,
+ int val)
+{
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(bit_num)] |= (val << (bit_num % 8));
+}
+
+/* Clear bits in sram sw entry */
+static void mvpp2_prs_sram_bits_clear(struct mvpp2_prs_entry *pe, int bit_num,
+ int val)
+{
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(bit_num)] &= ~(val << (bit_num % 8));
+}
+
+/* Update ri bits in sram sw entry */
+static void mvpp2_prs_sram_ri_update(struct mvpp2_prs_entry *pe,
+ unsigned int bits, unsigned int mask)
+{
+ unsigned int i;
+
+ for (i = 0; i < MVPP2_PRS_SRAM_RI_CTRL_BITS; i++) {
+ int ri_off = MVPP2_PRS_SRAM_RI_OFFS;
+
+ if (!(mask & BIT(i)))
+ continue;
+
+ if (bits & BIT(i))
+ mvpp2_prs_sram_bits_set(pe, ri_off + i, 1);
+ else
+ mvpp2_prs_sram_bits_clear(pe, ri_off + i, 1);
+
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_RI_CTRL_OFFS + i, 1);
+ }
+}
+
+/* Obtain ri bits from sram sw entry */
+static int mvpp2_prs_sram_ri_get(struct mvpp2_prs_entry *pe)
+{
+ return pe->sram.word[MVPP2_PRS_SRAM_RI_WORD];
+}
+
+/* Update ai bits in sram sw entry */
+static void mvpp2_prs_sram_ai_update(struct mvpp2_prs_entry *pe,
+ unsigned int bits, unsigned int mask)
+{
+ unsigned int i;
+ int ai_off = MVPP2_PRS_SRAM_AI_OFFS;
+
+ for (i = 0; i < MVPP2_PRS_SRAM_AI_CTRL_BITS; i++) {
+
+ if (!(mask & BIT(i)))
+ continue;
+
+ if (bits & BIT(i))
+ mvpp2_prs_sram_bits_set(pe, ai_off + i, 1);
+ else
+ mvpp2_prs_sram_bits_clear(pe, ai_off + i, 1);
+
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_AI_CTRL_OFFS + i, 1);
+ }
+}
+
+/* Read ai bits from sram sw entry */
+static int mvpp2_prs_sram_ai_get(struct mvpp2_prs_entry *pe)
+{
+ u8 bits;
+ int ai_off = MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_AI_OFFS);
+ int ai_en_off = ai_off + 1;
+ int ai_shift = MVPP2_PRS_SRAM_AI_OFFS % 8;
+
+ bits = (pe->sram.byte[ai_off] >> ai_shift) |
+ (pe->sram.byte[ai_en_off] << (8 - ai_shift));
+
+ return bits;
+}
+
+/* In sram sw entry set lookup ID field of the tcam key to be used in the next
+ * lookup interation
+ */
+static void mvpp2_prs_sram_next_lu_set(struct mvpp2_prs_entry *pe,
+ unsigned int lu)
+{
+ int sram_next_off = MVPP2_PRS_SRAM_NEXT_LU_OFFS;
+
+ mvpp2_prs_sram_bits_clear(pe, sram_next_off,
+ MVPP2_PRS_SRAM_NEXT_LU_MASK);
+ mvpp2_prs_sram_bits_set(pe, sram_next_off, lu);
+}
+
+/* In the sram sw entry set sign and value of the next lookup offset
+ * and the offset value generated to the classifier
+ */
+static void mvpp2_prs_sram_shift_set(struct mvpp2_prs_entry *pe, int shift,
+ unsigned int op)
+{
+ /* Set sign */
+ if (shift < 0) {
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
+ shift = 0 - shift;
+ } else {
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
+ }
+
+ /* Set value */
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_SHIFT_OFFS)] =
+ (unsigned char)shift;
+
+ /* Reset and set operation */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_MASK);
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS, op);
+
+ /* Set base offset as current */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
+}
+
+/* In the sram sw entry set sign and value of the user defined offset
+ * generated to the classifier
+ */
+static void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe,
+ unsigned int type, int offset,
+ unsigned int op)
+{
+ /* Set sign */
+ if (offset < 0) {
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
+ offset = 0 - offset;
+ } else {
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
+ }
+
+ /* Set value */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_OFFS,
+ MVPP2_PRS_SRAM_UDF_MASK);
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_OFFS, offset);
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_UDF_OFFS +
+ MVPP2_PRS_SRAM_UDF_BITS)] &=
+ ~(MVPP2_PRS_SRAM_UDF_MASK >> (8 - (MVPP2_PRS_SRAM_UDF_OFFS % 8)));
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_UDF_OFFS +
+ MVPP2_PRS_SRAM_UDF_BITS)] |=
+ (offset >> (8 - (MVPP2_PRS_SRAM_UDF_OFFS % 8)));
+
+ /* Set offset type */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS,
+ MVPP2_PRS_SRAM_UDF_TYPE_MASK);
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS, type);
+
+ /* Set offset operation */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_MASK);
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS, op);
+
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS +
+ MVPP2_PRS_SRAM_OP_SEL_UDF_BITS)] &=
+ ~(MVPP2_PRS_SRAM_OP_SEL_UDF_MASK >>
+ (8 - (MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS % 8)));
+
+ pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS +
+ MVPP2_PRS_SRAM_OP_SEL_UDF_BITS)] |=
+ (op >> (8 - (MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS % 8)));
+
+ /* Set base offset as current */
+ mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
+}
+
+/* Find parser flow entry */
+static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return NULL;
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+
+ /* Go through the all entires with MVPP2_PRS_LU_FLOWS */
+ for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
+ u8 bits;
+
+ if (!priv->prs_shadow[tid].valid ||
+ priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
+ continue;
+
+ pe->index = tid;
+ mvpp2_prs_hw_read(priv, pe);
+ bits = mvpp2_prs_sram_ai_get(pe);
+
+ /* Sram store classification lookup ID in AI bits [5:0] */
+ if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
+ return pe;
+ }
+ kfree(pe);
+
+ return NULL;
+}
+
+/* Return first free tcam index, seeking from start to end */
+static int mvpp2_prs_tcam_first_free(struct mvpp2 *priv, unsigned char start,
+ unsigned char end)
+{
+ int tid;
+
+ if (start > end)
+ swap(start, end);
+
+ if (end >= MVPP2_PRS_TCAM_SRAM_SIZE)
+ end = MVPP2_PRS_TCAM_SRAM_SIZE - 1;
+
+ for (tid = start; tid <= end; tid++) {
+ if (!priv->prs_shadow[tid].valid)
+ return tid;
+ }
+
+ return -EINVAL;
+}
+
+/* Enable/disable dropping all mac da's */
+static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
+{
+ struct mvpp2_prs_entry pe;
+
+ if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
+ /* Entry exist - update port only */
+ pe.index = MVPP2_PE_DROP_ALL;
+ mvpp2_prs_hw_read(priv, &pe);
+ } else {
+ /* Entry doesn't exist - create new */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+ pe.index = MVPP2_PE_DROP_ALL;
+
+ /* Non-promiscuous mode for all ports - DROP unknown packets */
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
+ MVPP2_PRS_RI_DROP_MASK);
+
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(&pe, port, add);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set port to promiscuous mode */
+static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, bool add)
+{
+ struct mvpp2_prs_entry pe;
+
+ /* Promiscous mode - Accept unknown packets */
+
+ if (priv->prs_shadow[MVPP2_PE_MAC_PROMISCUOUS].valid) {
+ /* Entry exist - update port only */
+ pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+ mvpp2_prs_hw_read(priv, &pe);
+ } else {
+ /* Entry doesn't exist - create new */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+ pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+
+ /* Continue - set next lookup */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+
+ /* Set result info bits */
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_UCAST,
+ MVPP2_PRS_RI_L2_CAST_MASK);
+
+ /* Shift to ethertype */
+ mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(&pe, port, add);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Accept multicast */
+static void mvpp2_prs_mac_multi_set(struct mvpp2 *priv, int port, int index,
+ bool add)
+{
+ struct mvpp2_prs_entry pe;
+ unsigned char da_mc;
+
+ /* Ethernet multicast address first byte is
+ * 0x01 for IPv4 and 0x33 for IPv6
+ */
+ da_mc = (index == MVPP2_PE_MAC_MC_ALL) ? 0x01 : 0x33;
+
+ if (priv->prs_shadow[index].valid) {
+ /* Entry exist - update port only */
+ pe.index = index;
+ mvpp2_prs_hw_read(priv, &pe);
+ } else {
+ /* Entry doesn't exist - create new */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+ pe.index = index;
+
+ /* Continue - set next lookup */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+
+ /* Set result info bits */
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_MCAST,
+ MVPP2_PRS_RI_L2_CAST_MASK);
+
+ /* Update tcam entry data first byte */
+ mvpp2_prs_tcam_data_byte_set(&pe, 0, da_mc, 0xff);
+
+ /* Shift to ethertype */
+ mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(&pe, port, add);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set entry for dsa packets */
+static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
+ bool tagged, bool extend)
+{
+ struct mvpp2_prs_entry pe;
+ int tid, shift;
+
+ if (extend) {
+ tid = tagged ? MVPP2_PE_EDSA_TAGGED : MVPP2_PE_EDSA_UNTAGGED;
+ shift = 8;
+ } else {
+ tid = tagged ? MVPP2_PE_DSA_TAGGED : MVPP2_PE_DSA_UNTAGGED;
+ shift = 4;
+ }
+
+ if (priv->prs_shadow[tid].valid) {
+ /* Entry exist - update port only */
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
+ } else {
+ /* Entry doesn't exist - create new */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ pe.index = tid;
+
+ /* Shift 4 bytes if DSA tag or 8 bytes in case of EDSA tag*/
+ mvpp2_prs_sram_shift_set(&pe, shift,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_DSA);
+
+ if (tagged) {
+ /* Set tagged bit in DSA tag */
+ mvpp2_prs_tcam_data_byte_set(&pe, 0,
+ MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
+ MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
+ /* Clear all ai bits for next iteration */
+ mvpp2_prs_sram_ai_update(&pe, 0,
+ MVPP2_PRS_SRAM_AI_MASK);
+ /* If packet is tagged continue check vlans */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ } else {
+ /* Set result info bits to 'no vlans' */
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+ MVPP2_PRS_RI_VLAN_MASK);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+ }
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(&pe, port, add);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set entry for dsa ethertype */
+static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
+ bool add, bool tagged, bool extend)
+{
+ struct mvpp2_prs_entry pe;
+ int tid, shift, port_mask;
+
+ if (extend) {
+ tid = tagged ? MVPP2_PE_ETYPE_EDSA_TAGGED :
+ MVPP2_PE_ETYPE_EDSA_UNTAGGED;
+ port_mask = 0;
+ shift = 8;
+ } else {
+ tid = tagged ? MVPP2_PE_ETYPE_DSA_TAGGED :
+ MVPP2_PE_ETYPE_DSA_UNTAGGED;
+ port_mask = MVPP2_PRS_PORT_MASK;
+ shift = 4;
+ }
+
+ if (priv->prs_shadow[tid].valid) {
+ /* Entry exist - update port only */
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
+ } else {
+ /* Entry doesn't exist - create new */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ pe.index = tid;
+
+ /* Set ethertype */
+ mvpp2_prs_match_etype(&pe, 0, ETH_P_EDSA);
+ mvpp2_prs_match_etype(&pe, 2, 0);
+
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DSA_MASK,
+ MVPP2_PRS_RI_DSA_MASK);
+ /* Shift ethertype + 2 byte reserved + tag*/
+ mvpp2_prs_sram_shift_set(&pe, 2 + MVPP2_ETH_TYPE_LEN + shift,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_DSA);
+
+ if (tagged) {
+ /* Set tagged bit in DSA tag */
+ mvpp2_prs_tcam_data_byte_set(&pe,
+ MVPP2_ETH_TYPE_LEN + 2 + 3,
+ MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
+ MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
+ /* Clear all ai bits for next iteration */
+ mvpp2_prs_sram_ai_update(&pe, 0,
+ MVPP2_PRS_SRAM_AI_MASK);
+ /* If packet is tagged continue check vlans */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ } else {
+ /* Set result info bits to 'no vlans' */
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+ MVPP2_PRS_RI_VLAN_MASK);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+ }
+ /* Mask/unmask all ports, depending on dsa type */
+ mvpp2_prs_tcam_port_map_set(&pe, port_mask);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(&pe, port, add);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Search for existing single/triple vlan entry */
+static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+ unsigned short tpid, int ai)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return NULL;
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+
+ /* Go through the all entries with MVPP2_PRS_LU_VLAN */
+ for (tid = MVPP2_PE_FIRST_FREE_TID;
+ tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+ unsigned int ri_bits, ai_bits;
+ bool match;
+
+ if (!priv->prs_shadow[tid].valid ||
+ priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ continue;
+
+ pe->index = tid;
+
+ mvpp2_prs_hw_read(priv, pe);
+ match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
+ if (!match)
+ continue;
+
+ /* Get vlan type */
+ ri_bits = mvpp2_prs_sram_ri_get(pe);
+ ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+
+ /* Get current ai value from tcam */
+ ai_bits = mvpp2_prs_tcam_ai_get(pe);
+ /* Clear double vlan bit */
+ ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
+
+ if (ai != ai_bits)
+ continue;
+
+ if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+ ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+ return pe;
+ }
+ kfree(pe);
+
+ return NULL;
+}
+
+/* Add/update single/triple vlan entry */
+static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+ unsigned int port_map)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid_aux, tid;
+
+ pe = mvpp2_prs_vlan_find(priv, tpid, ai);
+
+ if (!pe) {
+ /* Create new tcam entry */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID,
+ MVPP2_PE_FIRST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return -ENOMEM;
+
+ /* Get last double vlan tid */
+ for (tid_aux = MVPP2_PE_LAST_FREE_TID;
+ tid_aux >= MVPP2_PE_FIRST_FREE_TID; tid_aux--) {
+ unsigned int ri_bits;
+
+ if (!priv->prs_shadow[tid_aux].valid ||
+ priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ continue;
+
+ pe->index = tid_aux;
+ mvpp2_prs_hw_read(priv, pe);
+ ri_bits = mvpp2_prs_sram_ri_get(pe);
+ if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
+ MVPP2_PRS_RI_VLAN_DOUBLE)
+ break;
+ }
+
+ if (tid <= tid_aux)
+ return -EINVAL;
+
+ memset(pe, 0 , sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ pe->index = tid;
+
+ mvpp2_prs_match_etype(pe, 0, tpid);
+
+ mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_L2);
+ /* Shift 4 bytes - skip 1 vlan tag */
+ mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Clear all ai bits for next iteration */
+ mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+
+ if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
+ mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
+ MVPP2_PRS_RI_VLAN_MASK);
+ } else {
+ ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
+ mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
+ MVPP2_PRS_RI_VLAN_MASK);
+ }
+ mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
+
+ mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+ }
+ /* Update ports' mask */
+ mvpp2_prs_tcam_port_map_set(pe, port_map);
+
+ mvpp2_prs_hw_write(priv, pe);
+
+ kfree(pe);
+
+ return 0;
+}
+
+/* Get first free double vlan ai number */
+static int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2 *priv)
+{
+ int i;
+
+ for (i = 1; i < MVPP2_PRS_DBL_VLANS_MAX; i++) {
+ if (!priv->prs_double_vlans[i])
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+/* Search for existing double vlan entry */
+static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
+ unsigned short tpid1,
+ unsigned short tpid2)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return NULL;
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+
+ /* Go through the all entries with MVPP2_PRS_LU_VLAN */
+ for (tid = MVPP2_PE_FIRST_FREE_TID;
+ tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+ unsigned int ri_mask;
+ bool match;
+
+ if (!priv->prs_shadow[tid].valid ||
+ priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ continue;
+
+ pe->index = tid;
+ mvpp2_prs_hw_read(priv, pe);
+
+ match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
+ && mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
+
+ if (!match)
+ continue;
+
+ ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
+ if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
+ return pe;
+ }
+ kfree(pe);
+
+ return NULL;
+}
+
+/* Add or update double vlan entry */
+static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+ unsigned short tpid2,
+ unsigned int port_map)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid_aux, tid, ai;
+
+ pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
+
+ if (!pe) {
+ /* Create new tcam entry */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return -ENOMEM;
+
+ /* Set ai value for new double vlan entry */
+ ai = mvpp2_prs_double_vlan_ai_free_get(priv);
+ if (ai < 0)
+ return ai;
+
+ /* Get first single/triple vlan tid */
+ for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
+ tid_aux <= MVPP2_PE_LAST_FREE_TID; tid_aux++) {
+ unsigned int ri_bits;
+
+ if (!priv->prs_shadow[tid_aux].valid ||
+ priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ continue;
+
+ pe->index = tid_aux;
+ mvpp2_prs_hw_read(priv, pe);
+ ri_bits = mvpp2_prs_sram_ri_get(pe);
+ ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+ if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+ ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+ break;
+ }
+
+ if (tid >= tid_aux)
+ return -ERANGE;
+
+ memset(pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ pe->index = tid;
+
+ priv->prs_double_vlans[ai] = true;
+
+ mvpp2_prs_match_etype(pe, 0, tpid1);
+ mvpp2_prs_match_etype(pe, 4, tpid2);
+
+ mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ /* Shift 8 bytes - skip 2 vlan tags */
+ mvpp2_prs_sram_shift_set(pe, 2 * MVPP2_VLAN_TAG_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+ MVPP2_PRS_RI_VLAN_MASK);
+ mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
+ MVPP2_PRS_SRAM_AI_MASK);
+
+ mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+ }
+
+ /* Update ports' mask */
+ mvpp2_prs_tcam_port_map_set(pe, port_map);
+ mvpp2_prs_hw_write(priv, pe);
+
+ kfree(pe);
+ return 0;
+}
+
+/* IPv4 header parsing for fragmentation and L4 offset */
+static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
+ unsigned int ri, unsigned int ri_mask)
+{
+ struct mvpp2_prs_entry pe;
+ int tid;
+
+ if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
+ (proto != IPPROTO_IGMP))
+ return -EINVAL;
+
+ /* Fragmented packet */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ pe.index = tid;
+
+ /* Set next lu to IPv4 */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Set L4 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+ sizeof(struct iphdr) - 4,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+ mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+ MVPP2_PRS_IPV4_DIP_AI_BIT);
+ mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_MASK,
+ ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
+
+ mvpp2_prs_tcam_data_byte_set(&pe, 5, proto, MVPP2_PRS_TCAM_PROTO_MASK);
+ mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Not fragmented packet */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe.index = tid;
+ /* Clear ri before updating */
+ pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+ pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+ mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
+
+ mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, MVPP2_PRS_TCAM_PROTO_MASK_L);
+ mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, MVPP2_PRS_TCAM_PROTO_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* IPv4 L3 multicast or broadcast */
+static int mvpp2_prs_ip4_cast(struct mvpp2 *priv, unsigned short l3_cast)
+{
+ struct mvpp2_prs_entry pe;
+ int mask, tid;
+
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ pe.index = tid;
+
+ switch (l3_cast) {
+ case MVPP2_PRS_L3_MULTI_CAST:
+ mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV4_MC,
+ MVPP2_PRS_IPV4_MC_MASK);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
+ MVPP2_PRS_RI_L3_ADDR_MASK);
+ break;
+ case MVPP2_PRS_L3_BROAD_CAST:
+ mask = MVPP2_PRS_IPV4_BC_MASK;
+ mvpp2_prs_tcam_data_byte_set(&pe, 0, mask, mask);
+ mvpp2_prs_tcam_data_byte_set(&pe, 1, mask, mask);
+ mvpp2_prs_tcam_data_byte_set(&pe, 2, mask, mask);
+ mvpp2_prs_tcam_data_byte_set(&pe, 3, mask, mask);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_BCAST,
+ MVPP2_PRS_RI_L3_ADDR_MASK);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+ MVPP2_PRS_IPV4_DIP_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Set entries for protocols over IPv6 */
+static int mvpp2_prs_ip6_proto(struct mvpp2 *priv, unsigned short proto,
+ unsigned int ri, unsigned int ri_mask)
+{
+ struct mvpp2_prs_entry pe;
+ int tid;
+
+ if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
+ (proto != IPPROTO_ICMPV6) && (proto != IPPROTO_IPIP))
+ return -EINVAL;
+
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = tid;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+ sizeof(struct ipv6hdr) - 6,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ mvpp2_prs_tcam_data_byte_set(&pe, 0, proto, MVPP2_PRS_TCAM_PROTO_MASK);
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Write HW */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* IPv6 L3 multicast entry */
+static int mvpp2_prs_ip6_cast(struct mvpp2 *priv, unsigned short l3_cast)
+{
+ struct mvpp2_prs_entry pe;
+ int tid;
+
+ if (l3_cast != MVPP2_PRS_L3_MULTI_CAST)
+ return -EINVAL;
+
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = tid;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
+ MVPP2_PRS_RI_L3_ADDR_MASK);
+ mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Shift back to IPv6 NH */
+ mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV6_MC,
+ MVPP2_PRS_IPV6_MC_MASK);
+ mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Parser per-port initialization */
+static void mvpp2_prs_hw_port_init(struct mvpp2 *priv, int port, int lu_first,
+ int lu_max, int offset)
+{
+ u32 val;
+
+ /* Set lookup ID */
+ val = mvpp2_read(priv, MVPP2_PRS_INIT_LOOKUP_REG);
+ val &= ~MVPP2_PRS_PORT_LU_MASK(port);
+ val |= MVPP2_PRS_PORT_LU_VAL(port, lu_first);
+ mvpp2_write(priv, MVPP2_PRS_INIT_LOOKUP_REG, val);
+
+ /* Set maximum number of loops for packet received from port */
+ val = mvpp2_read(priv, MVPP2_PRS_MAX_LOOP_REG(port));
+ val &= ~MVPP2_PRS_MAX_LOOP_MASK(port);
+ val |= MVPP2_PRS_MAX_LOOP_VAL(port, lu_max);
+ mvpp2_write(priv, MVPP2_PRS_MAX_LOOP_REG(port), val);
+
+ /* Set initial offset for packet header extraction for the first
+ * searching loop
+ */
+ val = mvpp2_read(priv, MVPP2_PRS_INIT_OFFS_REG(port));
+ val &= ~MVPP2_PRS_INIT_OFF_MASK(port);
+ val |= MVPP2_PRS_INIT_OFF_VAL(port, offset);
+ mvpp2_write(priv, MVPP2_PRS_INIT_OFFS_REG(port), val);
+}
+
+/* Default flow entries initialization for all ports */
+static void mvpp2_prs_def_flow_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int port;
+
+ for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ pe.index = MVPP2_PE_FIRST_DEFAULT_FLOW - port;
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+
+ /* Set flow ID*/
+ mvpp2_prs_sram_ai_update(&pe, port, MVPP2_PRS_FLOW_ID_MASK);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_hw_write(priv, &pe);
+ }
+}
+
+/* Set default entry for Marvell Header field */
+static void mvpp2_prs_mh_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+
+ pe.index = MVPP2_PE_MH_DEFAULT;
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MH);
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_MH_SIZE,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MH);
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Set default entires (place holder) for promiscuous, non-promiscuous and
+ * multicast MAC addresses
+ */
+static void mvpp2_prs_mac_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+
+ /* Non-promiscuous mode for all ports - DROP unknown packets */
+ pe.index = MVPP2_PE_MAC_NON_PROMISCUOUS;
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
+ MVPP2_PRS_RI_DROP_MASK);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* place holders only - no ports */
+ mvpp2_prs_mac_drop_all_set(priv, 0, false);
+ mvpp2_prs_mac_promisc_set(priv, 0, false);
+ mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_ALL, 0, false);
+ mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_IP6, 0, false);
+}
+
+/* Set default entries for various types of dsa packets */
+static void mvpp2_prs_dsa_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+
+ /* None tagged EDSA entry - place holder */
+ mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_UNTAGGED,
+ MVPP2_PRS_EDSA);
+
+ /* Tagged EDSA entry - place holder */
+ mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+
+ /* None tagged DSA entry - place holder */
+ mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_UNTAGGED,
+ MVPP2_PRS_DSA);
+
+ /* Tagged DSA entry - place holder */
+ mvpp2_prs_dsa_tag_set(priv, 0, false, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+
+ /* None tagged EDSA ethertype entry - place holder*/
+ mvpp2_prs_dsa_tag_ethertype_set(priv, 0, false,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+
+ /* Tagged EDSA ethertype entry - place holder*/
+ mvpp2_prs_dsa_tag_ethertype_set(priv, 0, false,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+
+ /* None tagged DSA ethertype entry */
+ mvpp2_prs_dsa_tag_ethertype_set(priv, 0, true,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+
+ /* Tagged DSA ethertype entry */
+ mvpp2_prs_dsa_tag_ethertype_set(priv, 0, true,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+
+ /* Set default entry, in case DSA or EDSA tag not found */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ pe.index = MVPP2_PE_DSA_DEFAULT;
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+
+ /* Shift 0 bytes */
+ mvpp2_prs_sram_shift_set(&pe, 0, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+
+ /* Clear all sram ai bits for next iteration */
+ mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ mvpp2_prs_hw_write(priv, &pe);
+}
+
+/* Match basic ethertypes */
+static int mvpp2_prs_etype_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int tid;
+
+ /* Ethertype: PPPoE */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, ETH_P_PPP_SES);
+
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_PPPOE_HDR_SIZE,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_PPPOE_MASK,
+ MVPP2_PRS_RI_PPPOE_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = false;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_PPPOE_MASK,
+ MVPP2_PRS_RI_PPPOE_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Ethertype: ARP */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, ETH_P_ARP);
+
+ /* Generate flow in the next iteration*/
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_ARP,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = true;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_ARP,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Ethertype: LBTD */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, MVPP2_IP_LBDT_TYPE);
+
+ /* Generate flow in the next iteration*/
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+ MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+ MVPP2_PRS_RI_CPU_CODE_MASK |
+ MVPP2_PRS_RI_UDF3_MASK);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = true;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+ MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+ MVPP2_PRS_RI_CPU_CODE_MASK |
+ MVPP2_PRS_RI_UDF3_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Ethertype: IPv4 without options */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, ETH_P_IP);
+ mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
+ MVPP2_PRS_IPV4_HEAD_MASK |
+ MVPP2_PRS_IPV4_IHL_MASK);
+
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Skip eth_type + 4 bytes of IP header */
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = false;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP4,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Ethertype: IPv4 with options */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe.index = tid;
+
+ /* Clear tcam data before updating */
+ pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(MVPP2_ETH_TYPE_LEN)] = 0x0;
+ pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(MVPP2_ETH_TYPE_LEN)] = 0x0;
+
+ mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_IPV4_HEAD,
+ MVPP2_PRS_IPV4_HEAD_MASK);
+
+ /* Clear ri before updating */
+ pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+ pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = false;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP4_OPT,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Ethertype: IPv6 without options */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, ETH_P_IPV6);
+
+ /* Skip DIP of IPV6 header */
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 8 +
+ MVPP2_MAX_L3_ADDR_SIZE,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = false;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_IP6,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Default entry for MVPP2_PRS_LU_L2 - Unknown ethtype */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
+ pe.index = MVPP2_PE_ETH_TYPE_UN;
+
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Generate flow in the next iteration*/
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Set L3 offset even it's unknown L3 */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_L2);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
+ priv->prs_shadow[pe.index].finish = true;
+ mvpp2_prs_shadow_ri_set(priv, pe.index, MVPP2_PRS_RI_L3_UN,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Configure vlan entries and detect up to 2 successive VLAN tags.
+ * Possible options:
+ * 0x8100, 0x88A8
+ * 0x8100, 0x8100
+ * 0x8100
+ * 0x88A8
+ */
+static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int err;
+
+ priv->prs_double_vlans = devm_kcalloc(&pdev->dev, sizeof(bool),
+ MVPP2_PRS_DBL_VLANS_MAX,
+ GFP_KERNEL);
+ if (!priv->prs_double_vlans)
+ return -ENOMEM;
+
+ /* Double VLAN: 0x8100, 0x88A8 */
+ err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021Q, ETH_P_8021AD,
+ MVPP2_PRS_PORT_MASK);
+ if (err)
+ return err;
+
+ /* Double VLAN: 0x8100, 0x8100 */
+ err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021Q, ETH_P_8021Q,
+ MVPP2_PRS_PORT_MASK);
+ if (err)
+ return err;
+
+ /* Single VLAN: 0x88a8 */
+ err = mvpp2_prs_vlan_add(priv, ETH_P_8021AD, MVPP2_PRS_SINGLE_VLAN_AI,
+ MVPP2_PRS_PORT_MASK);
+ if (err)
+ return err;
+
+ /* Single VLAN: 0x8100 */
+ err = mvpp2_prs_vlan_add(priv, ETH_P_8021Q, MVPP2_PRS_SINGLE_VLAN_AI,
+ MVPP2_PRS_PORT_MASK);
+ if (err)
+ return err;
+
+ /* Set default double vlan entry */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ pe.index = MVPP2_PE_VLAN_DBL;
+
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+ /* Clear ai for next iterations */
+ mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+ MVPP2_PRS_RI_VLAN_MASK);
+
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_DBL_VLAN_AI_BIT,
+ MVPP2_PRS_DBL_VLAN_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Set default vlan none entry */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ pe.index = MVPP2_PE_VLAN_NONE;
+
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+ MVPP2_PRS_RI_VLAN_MASK);
+
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Set entries for PPPoE ethertype */
+static int mvpp2_prs_pppoe_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int tid;
+
+ /* IPv4 over PPPoE with options */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, PPP_IP);
+
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Skip eth_type + 4 bytes of IP header */
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* IPv4 over PPPoE without options */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe.index = tid;
+
+ mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
+ MVPP2_PRS_IPV4_HEAD_MASK |
+ MVPP2_PRS_IPV4_IHL_MASK);
+
+ /* Clear ri before updating */
+ pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
+ pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* IPv6 over PPPoE */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+ pe.index = tid;
+
+ mvpp2_prs_match_etype(&pe, 0, PPP_IPV6);
+
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+ /* Skip eth_type + 4 bytes of IPv6 header */
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Set L3 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Non-IP over PPPoE */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+ pe.index = tid;
+
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
+ MVPP2_PRS_RI_L3_PROTO_MASK);
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ /* Set L3 offset even if it's unknown L3 */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+ MVPP2_ETH_TYPE_LEN,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Initialize entries for IPv4 */
+static int mvpp2_prs_ip4_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int err;
+
+ /* Set entries for TCP, UDP and IGMP over IPv4 */
+ err = mvpp2_prs_ip4_proto(priv, IPPROTO_TCP, MVPP2_PRS_RI_L4_TCP,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip4_proto(priv, IPPROTO_UDP, MVPP2_PRS_RI_L4_UDP,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip4_proto(priv, IPPROTO_IGMP,
+ MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+ MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+ MVPP2_PRS_RI_CPU_CODE_MASK |
+ MVPP2_PRS_RI_UDF3_MASK);
+ if (err)
+ return err;
+
+ /* IPv4 Broadcast */
+ err = mvpp2_prs_ip4_cast(priv, MVPP2_PRS_L3_BROAD_CAST);
+ if (err)
+ return err;
+
+ /* IPv4 Multicast */
+ err = mvpp2_prs_ip4_cast(priv, MVPP2_PRS_L3_MULTI_CAST);
+ if (err)
+ return err;
+
+ /* Default IPv4 entry for unknown protocols */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ pe.index = MVPP2_PE_IP4_PROTO_UN;
+
+ /* Set next lu to IPv4 */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ /* Set L4 offset */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+ sizeof(struct iphdr) - 4,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+ mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+ MVPP2_PRS_IPV4_DIP_AI_BIT);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+
+ mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Default IPv4 entry for unicast address */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
+ pe.index = MVPP2_PE_IP4_ADDR_UN;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
+ MVPP2_PRS_RI_L3_ADDR_MASK);
+
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
+ MVPP2_PRS_IPV4_DIP_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Initialize entries for IPv6 */
+static int mvpp2_prs_ip6_init(struct mvpp2 *priv)
+{
+ struct mvpp2_prs_entry pe;
+ int tid, err;
+
+ /* Set entries for TCP, UDP and ICMP over IPv6 */
+ err = mvpp2_prs_ip6_proto(priv, IPPROTO_TCP,
+ MVPP2_PRS_RI_L4_TCP,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip6_proto(priv, IPPROTO_UDP,
+ MVPP2_PRS_RI_L4_UDP,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip6_proto(priv, IPPROTO_ICMPV6,
+ MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
+ MVPP2_PRS_RI_UDF3_RX_SPECIAL,
+ MVPP2_PRS_RI_CPU_CODE_MASK |
+ MVPP2_PRS_RI_UDF3_MASK);
+ if (err)
+ return err;
+
+ /* IPv4 is the last header. This is similar case as 6-TCP or 17-UDP */
+ /* Result Info: UDF7=1, DS lite */
+ err = mvpp2_prs_ip6_proto(priv, IPPROTO_IPIP,
+ MVPP2_PRS_RI_UDF7_IP6_LITE,
+ MVPP2_PRS_RI_UDF7_MASK);
+ if (err)
+ return err;
+
+ /* IPv6 multicast */
+ err = mvpp2_prs_ip6_cast(priv, MVPP2_PRS_L3_MULTI_CAST);
+ if (err)
+ return err;
+
+ /* Entry for checking hop limit */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ MVPP2_PE_LAST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = tid;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN |
+ MVPP2_PRS_RI_DROP_MASK,
+ MVPP2_PRS_RI_L3_PROTO_MASK |
+ MVPP2_PRS_RI_DROP_MASK);
+
+ mvpp2_prs_tcam_data_byte_set(&pe, 1, 0x00, MVPP2_PRS_IPV6_HOP_MASK);
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Default IPv6 entry for unknown protocols */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = MVPP2_PE_IP6_PROTO_UN;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+ /* Set L4 offset relatively to our current place */
+ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+ sizeof(struct ipv6hdr) - 4,
+ MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Default IPv6 entry for unknown ext protocols */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = MVPP2_PE_IP6_EXT_PROTO_UN;
+
+ /* Finished: go to flowid generation */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
+ MVPP2_PRS_RI_L4_PROTO_MASK);
+
+ mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_EXT_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ /* Default IPv6 entry for unicast address */
+ memset(&pe, 0, sizeof(struct mvpp2_prs_entry));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ pe.index = MVPP2_PE_IP6_ADDR_UN;
+
+ /* Finished: go to IPv6 again */
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
+ MVPP2_PRS_RI_L3_ADDR_MASK);
+ mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
+ MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Shift back to IPV6 NH */
+ mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
+ /* Unmask all ports */
+ mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+ /* Update shadow table and hw entry */
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP6);
+ mvpp2_prs_hw_write(priv, &pe);
+
+ return 0;
+}
+
+/* Parser default initialization */
+static int mvpp2_prs_default_init(struct platform_device *pdev,
+ struct mvpp2 *priv)
+{
+ int err, index, i;
+
+ /* Enable tcam table */
+ mvpp2_write(priv, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK);
+
+ /* Clear all tcam and sram entries */
+ for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++) {
+ mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, index);
+ for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+ mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), 0);
+
+ mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, index);
+ for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
+ mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), 0);
+ }
+
+ /* Invalidate all tcam entries */
+ for (index = 0; index < MVPP2_PRS_TCAM_SRAM_SIZE; index++)
+ mvpp2_prs_hw_inv(priv, index);
+
+ priv->prs_shadow = devm_kcalloc(&pdev->dev, MVPP2_PRS_TCAM_SRAM_SIZE,
+ sizeof(struct mvpp2_prs_shadow),
+ GFP_KERNEL);
+ if (!priv->prs_shadow)
+ return -ENOMEM;
+
+ /* Always start from lookup = 0 */
+ for (index = 0; index < MVPP2_MAX_PORTS; index++)
+ mvpp2_prs_hw_port_init(priv, index, MVPP2_PRS_LU_MH,
+ MVPP2_PRS_PORT_LU_MAX, 0);
+
+ mvpp2_prs_def_flow_init(priv);
+
+ mvpp2_prs_mh_init(priv);
+
+ mvpp2_prs_mac_init(priv);
+
+ mvpp2_prs_dsa_init(priv);
+
+ err = mvpp2_prs_etype_init(priv);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_vlan_init(pdev, priv);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_pppoe_init(priv);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip6_init(priv);
+ if (err)
+ return err;
+
+ err = mvpp2_prs_ip4_init(priv);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+/* Compare MAC DA with tcam entry data */
+static bool mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe,
+ const u8 *da, unsigned char *mask)
+{
+ unsigned char tcam_byte, tcam_mask;
+ int index;
+
+ for (index = 0; index < ETH_ALEN; index++) {
+ mvpp2_prs_tcam_data_byte_get(pe, index, &tcam_byte, &tcam_mask);
+ if (tcam_mask != mask[index])
+ return false;
+
+ if ((tcam_mask & tcam_byte) != (da[index] & mask[index]))
+ return false;
+ }
+
+ return true;
+}
+
+/* Find tcam entry with matched pair <MAC DA, port> */
+static struct mvpp2_prs_entry *
+mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ unsigned char *mask, int udf_type)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return NULL;
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+
+ /* Go through the all entires with MVPP2_PRS_LU_MAC */
+ for (tid = MVPP2_PE_FIRST_FREE_TID;
+ tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+ unsigned int entry_pmap;
+
+ if (!priv->prs_shadow[tid].valid ||
+ (priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
+ (priv->prs_shadow[tid].udf != udf_type))
+ continue;
+
+ pe->index = tid;
+ mvpp2_prs_hw_read(priv, pe);
+ entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
+
+ if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
+ entry_pmap == pmap)
+ return pe;
+ }
+ kfree(pe);
+
+ return NULL;
+}
+
+/* Update parser's mac da entry */
+static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
+ const u8 *da, bool add)
+{
+ struct mvpp2_prs_entry *pe;
+ unsigned int pmap, len, ri;
+ unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ int tid;
+
+ /* Scan TCAM and see if entry with this <MAC DA, port> already exist */
+ pe = mvpp2_prs_mac_da_range_find(priv, (1 << port), da, mask,
+ MVPP2_PRS_UDF_MAC_DEF);
+
+ /* No such entry */
+ if (!pe) {
+ if (!add)
+ return 0;
+
+ /* Create new TCAM entry */
+ /* Find first range mac entry*/
+ for (tid = MVPP2_PE_FIRST_FREE_TID;
+ tid <= MVPP2_PE_LAST_FREE_TID; tid++)
+ if (priv->prs_shadow[tid].valid &&
+ (priv->prs_shadow[tid].lu == MVPP2_PRS_LU_MAC) &&
+ (priv->prs_shadow[tid].udf ==
+ MVPP2_PRS_UDF_MAC_RANGE))
+ break;
+
+ /* Go through the all entries from first to last */
+ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ tid - 1);
+ if (tid < 0)
+ return tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return -1;
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+ pe->index = tid;
+
+ /* Mask all ports */
+ mvpp2_prs_tcam_port_map_set(pe, 0);
+ }
+
+ /* Update port mask */
+ mvpp2_prs_tcam_port_set(pe, port, add);
+
+ /* Invalidate the entry if no ports are left enabled */
+ pmap = mvpp2_prs_tcam_port_map_get(pe);
+ if (pmap == 0) {
+ if (add) {
+ kfree(pe);
+ return -1;
+ }
+ mvpp2_prs_hw_inv(priv, pe->index);
+ priv->prs_shadow[pe->index].valid = false;
+ kfree(pe);
+ return 0;
+ }
+
+ /* Continue - set next lookup */
+ mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_DSA);
+
+ /* Set match on DA */
+ len = ETH_ALEN;
+ while (len--)
+ mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
+
+ /* Set result info bits */
+ if (is_broadcast_ether_addr(da))
+ ri = MVPP2_PRS_RI_L2_BCAST;
+ else if (is_multicast_ether_addr(da))
+ ri = MVPP2_PRS_RI_L2_MCAST;
+ else
+ ri = MVPP2_PRS_RI_L2_UCAST | MVPP2_PRS_RI_MAC_ME_MASK;
+
+ mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ MVPP2_PRS_RI_MAC_ME_MASK);
+ mvpp2_prs_shadow_ri_set(priv, pe->index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ MVPP2_PRS_RI_MAC_ME_MASK);
+
+ /* Shift to ethertype */
+ mvpp2_prs_sram_shift_set(pe, 2 * ETH_ALEN,
+ MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+
+ /* Update shadow table and hw entry */
+ priv->prs_shadow[pe->index].udf = MVPP2_PRS_UDF_MAC_DEF;
+ mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_MAC);
+ mvpp2_prs_hw_write(priv, pe);
+
+ kfree(pe);
+
+ return 0;
+}
+
+static int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ int err;
+
+ /* Remove old parser entry */
+ err = mvpp2_prs_mac_da_accept(port->priv, port->id, dev->dev_addr,
+ false);
+ if (err)
+ return err;
+
+ /* Add new parser entry */
+ err = mvpp2_prs_mac_da_accept(port->priv, port->id, da, true);
+ if (err)
+ return err;
+
+ /* Set addr in the device */
+ ether_addr_copy(dev->dev_addr, da);
+
+ return 0;
+}
+
+/* Delete all port's multicast simple (not range) entries */
+static void mvpp2_prs_mcast_del_all(struct mvpp2 *priv, int port)
+{
+ struct mvpp2_prs_entry pe;
+ int index, tid;
+
+ for (tid = MVPP2_PE_FIRST_FREE_TID;
+ tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+ unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
+
+ if (!priv->prs_shadow[tid].valid ||
+ (priv->prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
+ (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
+ continue;
+
+ /* Only simple mac entries */
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
+
+ /* Read mac addr from entry */
+ for (index = 0; index < ETH_ALEN; index++)
+ mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
+ &da_mask[index]);
+
+ if (is_multicast_ether_addr(da) && !is_broadcast_ether_addr(da))
+ /* Delete this entry */
+ mvpp2_prs_mac_da_accept(priv, port, da, false);
+ }
+}
+
+static int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
+{
+ switch (type) {
+ case MVPP2_TAG_TYPE_EDSA:
+ /* Add port to EDSA entries */
+ mvpp2_prs_dsa_tag_set(priv, port, true,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+ mvpp2_prs_dsa_tag_set(priv, port, true,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+ /* Remove port from DSA entries */
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+ break;
+
+ case MVPP2_TAG_TYPE_DSA:
+ /* Add port to DSA entries */
+ mvpp2_prs_dsa_tag_set(priv, port, true,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+ mvpp2_prs_dsa_tag_set(priv, port, true,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+ /* Remove port from EDSA entries */
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+ break;
+
+ case MVPP2_TAG_TYPE_MH:
+ case MVPP2_TAG_TYPE_NONE:
+ /* Remove port form EDSA and DSA entries */
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
+ mvpp2_prs_dsa_tag_set(priv, port, false,
+ MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
+ break;
+
+ default:
+ if ((type < 0) || (type > MVPP2_TAG_TYPE_EDSA))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Set prs flow for the port */
+static int mvpp2_prs_def_flow(struct mvpp2_port *port)
+{
+ struct mvpp2_prs_entry *pe;
+ int tid;
+
+ pe = mvpp2_prs_flow_find(port->priv, port->id);
+
+ /* Such entry not exist */
+ if (!pe) {
+ /* Go through the all entires from last to first */
+ tid = mvpp2_prs_tcam_first_free(port->priv,
+ MVPP2_PE_LAST_FREE_TID,
+ MVPP2_PE_FIRST_FREE_TID);
+ if (tid < 0)
+ return tid;
+
+ pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+ if (!pe)
+ return -ENOMEM;
+
+ mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+ pe->index = tid;
+
+ /* Set flow ID*/
+ mvpp2_prs_sram_ai_update(pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
+ mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+
+ /* Update shadow table */
+ mvpp2_prs_shadow_set(port->priv, pe->index, MVPP2_PRS_LU_FLOWS);
+ }
+
+ mvpp2_prs_tcam_port_map_set(pe, (1 << port->id));
+ mvpp2_prs_hw_write(port->priv, pe);
+ kfree(pe);
+
+ return 0;
+}
+
+/* Classifier configuration routines */
+
+/* Update classification flow table registers */
+static void mvpp2_cls_flow_write(struct mvpp2 *priv,
+ struct mvpp2_cls_flow_entry *fe)
+{
+ mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
+}
+
+/* Update classification lookup table register */
+static void mvpp2_cls_lookup_write(struct mvpp2 *priv,
+ struct mvpp2_cls_lookup_entry *le)
+{
+ u32 val;
+
+ val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid;
+ mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val);
+ mvpp2_write(priv, MVPP2_CLS_LKP_TBL_REG, le->data);
+}
+
+/* Classifier default initialization */
+static void mvpp2_cls_init(struct mvpp2 *priv)
+{
+ struct mvpp2_cls_lookup_entry le;
+ struct mvpp2_cls_flow_entry fe;
+ int index;
+
+ /* Enable classifier */
+ mvpp2_write(priv, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK);
+
+ /* Clear classifier flow table */
+ memset(&fe.data, 0, MVPP2_CLS_FLOWS_TBL_DATA_WORDS);
+ for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) {
+ fe.index = index;
+ mvpp2_cls_flow_write(priv, &fe);
+ }
+
+ /* Clear classifier lookup table */
+ le.data = 0;
+ for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) {
+ le.lkpid = index;
+ le.way = 0;
+ mvpp2_cls_lookup_write(priv, &le);
+
+ le.way = 1;
+ mvpp2_cls_lookup_write(priv, &le);
+ }
+}
+
+static void mvpp2_cls_port_config(struct mvpp2_port *port)
+{
+ struct mvpp2_cls_lookup_entry le;
+ u32 val;
+
+ /* Set way for the port */
+ val = mvpp2_read(port->priv, MVPP2_CLS_PORT_WAY_REG);
+ val &= ~MVPP2_CLS_PORT_WAY_MASK(port->id);
+ mvpp2_write(port->priv, MVPP2_CLS_PORT_WAY_REG, val);
+
+ /* Pick the entry to be accessed in lookup ID decoding table
+ * according to the way and lkpid.
+ */
+ le.lkpid = port->id;
+ le.way = 0;
+ le.data = 0;
+
+ /* Set initial CPU queue for receiving packets */
+ le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK;
+ le.data |= port->first_rxq;
+
+ /* Disable classification engines */
+ le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
+
+ /* Update lookup ID table entry */
+ mvpp2_cls_lookup_write(port->priv, &le);
+}
+
+/* Set CPU queue number for oversize packets */
+static void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
+{
+ u32 val;
+
+ mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id),
+ port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
+
+ mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
+ (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
+
+ val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
+ val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
+ mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
+}
+
+/* Buffer Manager configuration routines */
+
+/* Create pool */
+static int mvpp2_bm_pool_create(struct platform_device *pdev,
+ struct mvpp2 *priv,
+ struct mvpp2_bm_pool *bm_pool, int size)
+{
+ int size_bytes;
+ u32 val;
+
+ size_bytes = sizeof(u32) * size;
+ bm_pool->virt_addr = dma_alloc_coherent(&pdev->dev, size_bytes,
+ &bm_pool->phys_addr,
+ GFP_KERNEL);
+ if (!bm_pool->virt_addr)
+ return -ENOMEM;
+
+ if (!IS_ALIGNED((u32)bm_pool->virt_addr, MVPP2_BM_POOL_PTR_ALIGN)) {
+ dma_free_coherent(&pdev->dev, size_bytes, bm_pool->virt_addr,
+ bm_pool->phys_addr);
+ dev_err(&pdev->dev, "BM pool %d is not %d bytes aligned\n",
+ bm_pool->id, MVPP2_BM_POOL_PTR_ALIGN);
+ return -ENOMEM;
+ }
+
+ mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id),
+ bm_pool->phys_addr);
+ mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size);
+
+ val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
+ val |= MVPP2_BM_START_MASK;
+ mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id), val);
+
+ bm_pool->type = MVPP2_BM_FREE;
+ bm_pool->size = size;
+ bm_pool->pkt_size = 0;
+ bm_pool->buf_num = 0;
+ atomic_set(&bm_pool->in_use, 0);
+ spin_lock_init(&bm_pool->lock);
+
+ return 0;
+}
+
+/* Set pool buffer size */
+static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,
+ struct mvpp2_bm_pool *bm_pool,
+ int buf_size)
+{
+ u32 val;
+
+ bm_pool->buf_size = buf_size;
+
+ val = ALIGN(buf_size, 1 << MVPP2_POOL_BUF_SIZE_OFFSET);
+ mvpp2_write(priv, MVPP2_POOL_BUF_SIZE_REG(bm_pool->id), val);
+}
+
+/* Free all buffers from the pool */
+static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
+{
+ int i;
+
+ for (i = 0; i < bm_pool->buf_num; i++) {
+ u32 vaddr;
+
+ /* Get buffer virtual adress (indirect access) */
+ mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+ vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
+ if (!vaddr)
+ break;
+ dev_kfree_skb_any((struct sk_buff *)vaddr);
+ }
+
+ /* Update BM driver with number of buffers removed from pool */
+ bm_pool->buf_num -= i;
+}
+
+/* Cleanup pool */
+static int mvpp2_bm_pool_destroy(struct platform_device *pdev,
+ struct mvpp2 *priv,
+ struct mvpp2_bm_pool *bm_pool)
+{
+ u32 val;
+
+ mvpp2_bm_bufs_free(priv, bm_pool);
+ if (bm_pool->buf_num) {
+ WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
+ return 0;
+ }
+
+ val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
+ val |= MVPP2_BM_STOP_MASK;
+ mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id), val);
+
+ dma_free_coherent(&pdev->dev, sizeof(u32) * bm_pool->size,
+ bm_pool->virt_addr,
+ bm_pool->phys_addr);
+ return 0;
+}
+
+static int mvpp2_bm_pools_init(struct platform_device *pdev,
+ struct mvpp2 *priv)
+{
+ int i, err, size;
+ struct mvpp2_bm_pool *bm_pool;
+
+ /* Create all pools with maximum size */
+ size = MVPP2_BM_POOL_SIZE_MAX;
+ for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+ bm_pool = &priv->bm_pools[i];
+ bm_pool->id = i;
+ err = mvpp2_bm_pool_create(pdev, priv, bm_pool, size);
+ if (err)
+ goto err_unroll_pools;
+ mvpp2_bm_pool_bufsize_set(priv, bm_pool, 0);
+ }
+ return 0;
+
+err_unroll_pools:
+ dev_err(&pdev->dev, "failed to create BM pool %d, size %d\n", i, size);
+ for (i = i - 1; i >= 0; i--)
+ mvpp2_bm_pool_destroy(pdev, priv, &priv->bm_pools[i]);
+ return err;
+}
+
+static int mvpp2_bm_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+ int i, err;
+
+ for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+ /* Mask BM all interrupts */
+ mvpp2_write(priv, MVPP2_BM_INTR_MASK_REG(i), 0);
+ /* Clear BM cause register */
+ mvpp2_write(priv, MVPP2_BM_INTR_CAUSE_REG(i), 0);
+ }
+
+ /* Allocate and initialize BM pools */
+ priv->bm_pools = devm_kcalloc(&pdev->dev, MVPP2_BM_POOLS_NUM,
+ sizeof(struct mvpp2_bm_pool), GFP_KERNEL);
+ if (!priv->bm_pools)
+ return -ENOMEM;
+
+ err = mvpp2_bm_pools_init(pdev, priv);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/* Attach long pool to rxq */
+static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
+ int lrxq, int long_pool)
+{
+ u32 val;
+ int prxq;
+
+ /* Get queue physical ID */
+ prxq = port->rxqs[lrxq]->id;
+
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~MVPP2_RXQ_POOL_LONG_MASK;
+ val |= ((long_pool << MVPP2_RXQ_POOL_LONG_OFFS) &
+ MVPP2_RXQ_POOL_LONG_MASK);
+
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Attach short pool to rxq */
+static void mvpp2_rxq_short_pool_set(struct mvpp2_port *port,
+ int lrxq, int short_pool)
+{
+ u32 val;
+ int prxq;
+
+ /* Get queue physical ID */
+ prxq = port->rxqs[lrxq]->id;
+
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~MVPP2_RXQ_POOL_SHORT_MASK;
+ val |= ((short_pool << MVPP2_RXQ_POOL_SHORT_OFFS) &
+ MVPP2_RXQ_POOL_SHORT_MASK);
+
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Allocate skb for BM pool */
+static struct sk_buff *mvpp2_skb_alloc(struct mvpp2_port *port,
+ struct mvpp2_bm_pool *bm_pool,
+ dma_addr_t *buf_phys_addr,
+ gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+ dma_addr_t phys_addr;
+
+ skb = __dev_alloc_skb(bm_pool->pkt_size, gfp_mask);
+ if (!skb)
+ return NULL;
+
+ phys_addr = dma_map_single(port->dev->dev.parent, skb->head,
+ MVPP2_RX_BUF_SIZE(bm_pool->pkt_size),
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(port->dev->dev.parent, phys_addr))) {
+ dev_kfree_skb_any(skb);
+ return NULL;
+ }
+ *buf_phys_addr = phys_addr;
+
+ return skb;
+}
+
+/* Set pool number in a BM cookie */
+static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
+{
+ u32 bm;
+
+ bm = cookie & ~(0xFF << MVPP2_BM_COOKIE_POOL_OFFS);
+ bm |= ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS);
+
+ return bm;
+}
+
+/* Get pool number from a BM cookie */
+static inline int mvpp2_bm_cookie_pool_get(u32 cookie)
+{
+ return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
+}
+
+/* Release buffer to BM */
+static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
+ u32 buf_phys_addr, u32 buf_virt_addr)
+{
+ mvpp2_write(port->priv, MVPP2_BM_VIRT_RLS_REG, buf_virt_addr);
+ mvpp2_write(port->priv, MVPP2_BM_PHY_RLS_REG(pool), buf_phys_addr);
+}
+
+/* Release multicast buffer */
+static void mvpp2_bm_pool_mc_put(struct mvpp2_port *port, int pool,
+ u32 buf_phys_addr, u32 buf_virt_addr,
+ int mc_id)
+{
+ u32 val = 0;
+
+ val |= (mc_id & MVPP2_BM_MC_ID_MASK);
+ mvpp2_write(port->priv, MVPP2_BM_MC_RLS_REG, val);
+
+ mvpp2_bm_pool_put(port, pool,
+ buf_phys_addr | MVPP2_BM_PHY_RLS_MC_BUFF_MASK,
+ buf_virt_addr);
+}
+
+/* Refill BM pool */
+static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
+ u32 phys_addr, u32 cookie)
+{
+ int pool = mvpp2_bm_cookie_pool_get(bm);
+
+ mvpp2_bm_pool_put(port, pool, phys_addr, cookie);
+}
+
+/* Allocate buffers for the pool */
+static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
+ struct mvpp2_bm_pool *bm_pool, int buf_num)
+{
+ struct sk_buff *skb;
+ int i, buf_size, total_size;
+ u32 bm;
+ dma_addr_t phys_addr;
+
+ buf_size = MVPP2_RX_BUF_SIZE(bm_pool->pkt_size);
+ total_size = MVPP2_RX_TOTAL_SIZE(buf_size);
+
+ if (buf_num < 0 ||
+ (buf_num + bm_pool->buf_num > bm_pool->size)) {
+ netdev_err(port->dev,
+ "cannot allocate %d buffers for pool %d\n",
+ buf_num, bm_pool->id);
+ return 0;
+ }
+
+ bm = mvpp2_bm_cookie_pool_set(0, bm_pool->id);
+ for (i = 0; i < buf_num; i++) {
+ skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_KERNEL);
+ if (!skb)
+ break;
+
+ mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+ }
+
+ /* Update BM driver with number of buffers added to pool */
+ bm_pool->buf_num += i;
+ bm_pool->in_use_thresh = bm_pool->buf_num / 4;
+
+ netdev_dbg(port->dev,
+ "%s pool %d: pkt_size=%4d, buf_size=%4d, total_size=%4d\n",
+ bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
+ bm_pool->id, bm_pool->pkt_size, buf_size, total_size);
+
+ netdev_dbg(port->dev,
+ "%s pool %d: %d of %d buffers added\n",
+ bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
+ bm_pool->id, i, buf_num);
+ return i;
+}
+
+/* Notify the driver that BM pool is being used as specific type and return the
+ * pool pointer on success
+ */
+static struct mvpp2_bm_pool *
+mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
+ int pkt_size)
+{
+ unsigned long flags = 0;
+ struct mvpp2_bm_pool *new_pool = &port->priv->bm_pools[pool];
+ int num;
+
+ if (new_pool->type != MVPP2_BM_FREE && new_pool->type != type) {
+ netdev_err(port->dev, "mixing pool types is forbidden\n");
+ return NULL;
+ }
+
+ spin_lock_irqsave(&new_pool->lock, flags);
+
+ if (new_pool->type == MVPP2_BM_FREE)
+ new_pool->type = type;
+
+ /* Allocate buffers in case BM pool is used as long pool, but packet
+ * size doesn't match MTU or BM pool hasn't being used yet
+ */
+ if (((type == MVPP2_BM_SWF_LONG) && (pkt_size > new_pool->pkt_size)) ||
+ (new_pool->pkt_size == 0)) {
+ int pkts_num;
+
+ /* Set default buffer number or free all the buffers in case
+ * the pool is not empty
+ */
+ pkts_num = new_pool->buf_num;
+ if (pkts_num == 0)
+ pkts_num = type == MVPP2_BM_SWF_LONG ?
+ MVPP2_BM_LONG_BUF_NUM :
+ MVPP2_BM_SHORT_BUF_NUM;
+ else
+ mvpp2_bm_bufs_free(port->priv, new_pool);
+
+ new_pool->pkt_size = pkt_size;
+
+ /* Allocate buffers for this pool */
+ num = mvpp2_bm_bufs_add(port, new_pool, pkts_num);
+ if (num != pkts_num) {
+ WARN(1, "pool %d: %d of %d allocated\n",
+ new_pool->id, num, pkts_num);
+ /* We need to undo the bufs_add() allocations */
+ spin_unlock_irqrestore(&new_pool->lock, flags);
+ return NULL;
+ }
+ }
+
+ mvpp2_bm_pool_bufsize_set(port->priv, new_pool,
+ MVPP2_RX_BUF_SIZE(new_pool->pkt_size));
+
+ spin_unlock_irqrestore(&new_pool->lock, flags);
+
+ return new_pool;
+}
+
+/* Initialize pools for swf */
+static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+{
+ unsigned long flags = 0;
+ int rxq;
+
+ if (!port->pool_long) {
+ port->pool_long =
+ mvpp2_bm_pool_use(port, MVPP2_BM_SWF_LONG_POOL(port->id),
+ MVPP2_BM_SWF_LONG,
+ port->pkt_size);
+ if (!port->pool_long)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&port->pool_long->lock, flags);
+ port->pool_long->port_map |= (1 << port->id);
+ spin_unlock_irqrestore(&port->pool_long->lock, flags);
+
+ for (rxq = 0; rxq < rxq_number; rxq++)
+ mvpp2_rxq_long_pool_set(port, rxq, port->pool_long->id);
+ }
+
+ if (!port->pool_short) {
+ port->pool_short =
+ mvpp2_bm_pool_use(port, MVPP2_BM_SWF_SHORT_POOL,
+ MVPP2_BM_SWF_SHORT,
+ MVPP2_BM_SHORT_PKT_SIZE);
+ if (!port->pool_short)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&port->pool_short->lock, flags);
+ port->pool_short->port_map |= (1 << port->id);
+ spin_unlock_irqrestore(&port->pool_short->lock, flags);
+
+ for (rxq = 0; rxq < rxq_number; rxq++)
+ mvpp2_rxq_short_pool_set(port, rxq,
+ port->pool_short->id);
+ }
+
+ return 0;
+}
+
+static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_bm_pool *port_pool = port->pool_long;
+ int num, pkts_num = port_pool->buf_num;
+ int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+
+ /* Update BM pool with new buffer size */
+ mvpp2_bm_bufs_free(port->priv, port_pool);
+ if (port_pool->buf_num) {
+ WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
+ return -EIO;
+ }
+
+ port_pool->pkt_size = pkt_size;
+ num = mvpp2_bm_bufs_add(port, port_pool, pkts_num);
+ if (num != pkts_num) {
+ WARN(1, "pool %d: %d of %d allocated\n",
+ port_pool->id, num, pkts_num);
+ return -EIO;
+ }
+
+ mvpp2_bm_pool_bufsize_set(port->priv, port_pool,
+ MVPP2_RX_BUF_SIZE(port_pool->pkt_size));
+ dev->mtu = mtu;
+ netdev_update_features(dev);
+ return 0;
+}
+
+static inline void mvpp2_interrupts_enable(struct mvpp2_port *port)
+{
+ int cpu, cpu_mask = 0;
+
+ for_each_present_cpu(cpu)
+ cpu_mask |= 1 << cpu;
+ mvpp2_write(port->priv, MVPP2_ISR_ENABLE_REG(port->id),
+ MVPP2_ISR_ENABLE_INTERRUPT(cpu_mask));
+}
+
+static inline void mvpp2_interrupts_disable(struct mvpp2_port *port)
+{
+ int cpu, cpu_mask = 0;
+
+ for_each_present_cpu(cpu)
+ cpu_mask |= 1 << cpu;
+ mvpp2_write(port->priv, MVPP2_ISR_ENABLE_REG(port->id),
+ MVPP2_ISR_DISABLE_INTERRUPT(cpu_mask));
+}
+
+/* Mask the current CPU's Rx/Tx interrupts */
+static void mvpp2_interrupts_mask(void *arg)
+{
+ struct mvpp2_port *port = arg;
+
+ mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id), 0);
+}
+
+/* Unmask the current CPU's Rx/Tx interrupts */
+static void mvpp2_interrupts_unmask(void *arg)
+{
+ struct mvpp2_port *port = arg;
+
+ mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id),
+ (MVPP2_CAUSE_MISC_SUM_MASK |
+ MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK |
+ MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK));
+}
+
+/* Port configuration routines */
+
+static void mvpp2_port_mii_set(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ val |= MVPP2_GMAC_INBAND_AN_MASK;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ val |= MVPP2_GMAC_PORT_RGMII_MASK;
+ default:
+ val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
+ }
+
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+}
+
+static void mvpp2_port_fc_adv_enable(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val |= MVPP2_GMAC_FC_ADV_EN;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void mvpp2_port_enable(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val |= MVPP2_GMAC_PORT_EN_MASK;
+ val |= MVPP2_GMAC_MIB_CNTR_EN_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+static void mvpp2_port_disable(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~(MVPP2_GMAC_PORT_EN_MASK);
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+/* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */
+static void mvpp2_port_periodic_xon_disable(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_1_REG) &
+ ~MVPP2_GMAC_PERIODIC_XON_EN_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+}
+
+/* Configure loopback port */
+static void mvpp2_port_loopback_set(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+
+ if (port->speed == 1000)
+ val |= MVPP2_GMAC_GMII_LB_EN_MASK;
+ else
+ val &= ~MVPP2_GMAC_GMII_LB_EN_MASK;
+
+ if (port->phy_interface == PHY_INTERFACE_MODE_SGMII)
+ val |= MVPP2_GMAC_PCS_LB_EN_MASK;
+ else
+ val &= ~MVPP2_GMAC_PCS_LB_EN_MASK;
+
+ writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+}
+
+static void mvpp2_port_reset(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+ ~MVPP2_GMAC_PORT_RESET_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+ MVPP2_GMAC_PORT_RESET_MASK)
+ continue;
+}
+
+/* Change maximum receive size of the port */
+static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
+ val |= (((port->pkt_size - MVPP2_MH_SIZE) / 2) <<
+ MVPP2_GMAC_MAX_RX_SIZE_OFFS);
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+}
+
+/* Set defaults to the MVPP2 port */
+static void mvpp2_defaults_set(struct mvpp2_port *port)
+{
+ int tx_port_num, val, queue, ptxq, lrxq;
+
+ /* Configure port to loopback if needed */
+ if (port->flags & MVPP2_F_LOOPBACK)
+ mvpp2_port_loopback_set(port);
+
+ /* Update TX FIFO MIN Threshold */
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ /* Min. TX threshold must be less than minimal packet length */
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+ /* Disable Legacy WRR, Disable EJP, Release from reset */
+ tx_port_num = mvpp2_egress_port(port);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG,
+ tx_port_num);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0);
+
+ /* Close bandwidth for all queues */
+ for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) {
+ ptxq = mvpp2_txq_phys(port->id, queue);
+ mvpp2_write(port->priv,
+ MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0);
+ }
+
+ /* Set refill period to 1 usec, refill tokens
+ * and bucket size to maximum
+ */
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PERIOD_REG,
+ port->priv->tclk / USEC_PER_SEC);
+ val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_REFILL_REG);
+ val &= ~MVPP2_TXP_REFILL_PERIOD_ALL_MASK;
+ val |= MVPP2_TXP_REFILL_PERIOD_MASK(1);
+ val |= MVPP2_TXP_REFILL_TOKENS_ALL_MASK;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_REFILL_REG, val);
+ val = MVPP2_TXP_TOKEN_SIZE_MAX;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
+
+ /* Set MaximumLowLatencyPacketSize value to 256 */
+ mvpp2_write(port->priv, MVPP2_RX_CTRL_REG(port->id),
+ MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK |
+ MVPP2_RX_LOW_LATENCY_PKT_SIZE(256));
+
+ /* Enable Rx cache snoop */
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val |= MVPP2_SNOOP_PKT_SIZE_MASK |
+ MVPP2_SNOOP_BUF_HDR_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+
+ /* At default, mask all interrupts to all present cpus */
+ mvpp2_interrupts_disable(port);
+}
+
+/* Enable/disable receiving packets */
+static void mvpp2_ingress_enable(struct mvpp2_port *port)
+{
+ u32 val;
+ int lrxq, queue;
+
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val &= ~MVPP2_RXQ_DISABLE_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+}
+
+static void mvpp2_ingress_disable(struct mvpp2_port *port)
+{
+ u32 val;
+ int lrxq, queue;
+
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val |= MVPP2_RXQ_DISABLE_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+}
+
+/* Enable transmit via physical egress queue
+ * - HW starts take descriptors from DRAM
+ */
+static void mvpp2_egress_enable(struct mvpp2_port *port)
+{
+ u32 qmap;
+ int queue;
+ int tx_port_num = mvpp2_egress_port(port);
+
+ /* Enable all initialized TXs. */
+ qmap = 0;
+ for (queue = 0; queue < txq_number; queue++) {
+ struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+ if (txq->descs != NULL)
+ qmap |= (1 << queue);
+ }
+
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG, qmap);
+}
+
+/* Disable transmit via physical egress queue
+ * - HW doesn't take descriptors from DRAM
+ */
+static void mvpp2_egress_disable(struct mvpp2_port *port)
+{
+ u32 reg_data;
+ int delay;
+ int tx_port_num = mvpp2_egress_port(port);
+
+ /* Issue stop command for active channels only */
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+ reg_data = (mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG)) &
+ MVPP2_TXP_SCHED_ENQ_MASK;
+ if (reg_data != 0)
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG,
+ (reg_data << MVPP2_TXP_SCHED_DISQ_OFFSET));
+
+ /* Wait for all Tx activity to terminate. */
+ delay = 0;
+ do {
+ if (delay >= MVPP2_TX_DISABLE_TIMEOUT_MSEC) {
+ netdev_warn(port->dev,
+ "Tx stop timed out, status=0x%08x\n",
+ reg_data);
+ break;
+ }
+ mdelay(1);
+ delay++;
+
+ /* Check port TX Command register that all
+ * Tx queues are stopped
+ */
+ reg_data = mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG);
+ } while (reg_data & MVPP2_TXP_SCHED_ENQ_MASK);
+}
+
+/* Rx descriptors helper methods */
+
+/* Get number of Rx descriptors occupied by received packets */
+static inline int
+mvpp2_rxq_received(struct mvpp2_port *port, int rxq_id)
+{
+ u32 val = mvpp2_read(port->priv, MVPP2_RXQ_STATUS_REG(rxq_id));
+
+ return val & MVPP2_RXQ_OCCUPIED_MASK;
+}
+
+/* Update Rx queue status with the number of occupied and available
+ * Rx descriptor slots.
+ */
+static inline void
+mvpp2_rxq_status_update(struct mvpp2_port *port, int rxq_id,
+ int used_count, int free_count)
+{
+ /* Decrement the number of used descriptors and increment count
+ * increment the number of free descriptors.
+ */
+ u32 val = used_count | (free_count << MVPP2_RXQ_NUM_NEW_OFFSET);
+
+ mvpp2_write(port->priv, MVPP2_RXQ_STATUS_UPDATE_REG(rxq_id), val);
+}
+
+/* Get pointer to next RX descriptor to be processed by SW */
+static inline struct mvpp2_rx_desc *
+mvpp2_rxq_next_desc_get(struct mvpp2_rx_queue *rxq)
+{
+ int rx_desc = rxq->next_desc_to_proc;
+
+ rxq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(rxq, rx_desc);
+ prefetch(rxq->descs + rxq->next_desc_to_proc);
+ return rxq->descs + rx_desc;
+}
+
+/* Set rx queue offset */
+static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
+ int prxq, int offset)
+{
+ u32 val;
+
+ /* Convert offset from bytes to units of 32 bytes */
+ offset = offset >> 5;
+
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(prxq));
+ val &= ~MVPP2_RXQ_PACKET_OFFSET_MASK;
+
+ /* Offset is in */
+ val |= ((offset << MVPP2_RXQ_PACKET_OFFSET_OFFS) &
+ MVPP2_RXQ_PACKET_OFFSET_MASK);
+
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
+}
+
+/* Obtain BM cookie information from descriptor */
+static u32 mvpp2_bm_cookie_build(struct mvpp2_rx_desc *rx_desc)
+{
+ int pool = (rx_desc->status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
+ int cpu = smp_processor_id();
+
+ return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
+ ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
+}
+
+/* Tx descriptors helper methods */
+
+/* Get number of Tx descriptors waiting to be transmitted by HW */
+static int mvpp2_txq_pend_desc_num_get(struct mvpp2_port *port,
+ struct mvpp2_tx_queue *txq)
+{
+ u32 val;
+
+ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+ val = mvpp2_read(port->priv, MVPP2_TXQ_PENDING_REG);
+
+ return val & MVPP2_TXQ_PENDING_MASK;
+}
+
+/* Get pointer to next Tx descriptor to be processed (send) by HW */
+static struct mvpp2_tx_desc *
+mvpp2_txq_next_desc_get(struct mvpp2_tx_queue *txq)
+{
+ int tx_desc = txq->next_desc_to_proc;
+
+ txq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(txq, tx_desc);
+ return txq->descs + tx_desc;
+}
+
+/* Update HW with number of aggregated Tx descriptors to be sent */
+static void mvpp2_aggr_txq_pend_desc_add(struct mvpp2_port *port, int pending)
+{
+ /* aggregated access - relevant TXQ number is written in TX desc */
+ mvpp2_write(port->priv, MVPP2_AGGR_TXQ_UPDATE_REG, pending);
+}
+
+
+/* Check if there are enough free descriptors in aggregated txq.
+ * If not, update the number of occupied descriptors and repeat the check.
+ */
+static int mvpp2_aggr_desc_num_check(struct mvpp2 *priv,
+ struct mvpp2_tx_queue *aggr_txq, int num)
+{
+ if ((aggr_txq->count + num) > aggr_txq->size) {
+ /* Update number of occupied aggregated Tx descriptors */
+ int cpu = smp_processor_id();
+ u32 val = mvpp2_read(priv, MVPP2_AGGR_TXQ_STATUS_REG(cpu));
+
+ aggr_txq->count = val & MVPP2_AGGR_TXQ_PENDING_MASK;
+ }
+
+ if ((aggr_txq->count + num) > aggr_txq->size)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/* Reserved Tx descriptors allocation request */
+static int mvpp2_txq_alloc_reserved_desc(struct mvpp2 *priv,
+ struct mvpp2_tx_queue *txq, int num)
+{
+ u32 val;
+
+ val = (txq->id << MVPP2_TXQ_RSVD_REQ_Q_OFFSET) | num;
+ mvpp2_write(priv, MVPP2_TXQ_RSVD_REQ_REG, val);
+
+ val = mvpp2_read(priv, MVPP2_TXQ_RSVD_RSLT_REG);
+
+ return val & MVPP2_TXQ_RSVD_RSLT_MASK;
+}
+
+/* Check if there are enough reserved descriptors for transmission.
+ * If not, request chunk of reserved descriptors and check again.
+ */
+static int mvpp2_txq_reserved_desc_num_proc(struct mvpp2 *priv,
+ struct mvpp2_tx_queue *txq,
+ struct mvpp2_txq_pcpu *txq_pcpu,
+ int num)
+{
+ int req, cpu, desc_count;
+
+ if (txq_pcpu->reserved_num >= num)
+ return 0;
+
+ /* Not enough descriptors reserved! Update the reserved descriptor
+ * count and check again.
+ */
+
+ desc_count = 0;
+ /* Compute total of used descriptors */
+ for_each_present_cpu(cpu) {
+ struct mvpp2_txq_pcpu *txq_pcpu_aux;
+
+ txq_pcpu_aux = per_cpu_ptr(txq->pcpu, cpu);
+ desc_count += txq_pcpu_aux->count;
+ desc_count += txq_pcpu_aux->reserved_num;
+ }
+
+ req = max(MVPP2_CPU_DESC_CHUNK, num - txq_pcpu->reserved_num);
+ desc_count += req;
+
+ if (desc_count >
+ (txq->size - (num_present_cpus() * MVPP2_CPU_DESC_CHUNK)))
+ return -ENOMEM;
+
+ txq_pcpu->reserved_num += mvpp2_txq_alloc_reserved_desc(priv, txq, req);
+
+ /* OK, the descriptor cound has been updated: check again. */
+ if (txq_pcpu->reserved_num < num)
+ return -ENOMEM;
+ return 0;
+}
+
+/* Release the last allocated Tx descriptor. Useful to handle DMA
+ * mapping failures in the Tx path.
+ */
+static void mvpp2_txq_desc_put(struct mvpp2_tx_queue *txq)
+{
+ if (txq->next_desc_to_proc == 0)
+ txq->next_desc_to_proc = txq->last_desc - 1;
+ else
+ txq->next_desc_to_proc--;
+}
+
+/* Set Tx descriptors fields relevant for CSUM calculation */
+static u32 mvpp2_txq_desc_csum(int l3_offs, int l3_proto,
+ int ip_hdr_len, int l4_proto)
+{
+ u32 command;
+
+ /* fields: L3_offset, IP_hdrlen, L3_type, G_IPv4_chk,
+ * G_L4_chk, L4_type required only for checksum calculation
+ */
+ command = (l3_offs << MVPP2_TXD_L3_OFF_SHIFT);
+ command |= (ip_hdr_len << MVPP2_TXD_IP_HLEN_SHIFT);
+ command |= MVPP2_TXD_IP_CSUM_DISABLE;
+
+ if (l3_proto == swab16(ETH_P_IP)) {
+ command &= ~MVPP2_TXD_IP_CSUM_DISABLE; /* enable IPv4 csum */
+ command &= ~MVPP2_TXD_L3_IP6; /* enable IPv4 */
+ } else {
+ command |= MVPP2_TXD_L3_IP6; /* enable IPv6 */
+ }
+
+ if (l4_proto == IPPROTO_TCP) {
+ command &= ~MVPP2_TXD_L4_UDP; /* enable TCP */
+ command &= ~MVPP2_TXD_L4_CSUM_FRAG; /* generate L4 csum */
+ } else if (l4_proto == IPPROTO_UDP) {
+ command |= MVPP2_TXD_L4_UDP; /* enable UDP */
+ command &= ~MVPP2_TXD_L4_CSUM_FRAG; /* generate L4 csum */
+ } else {
+ command |= MVPP2_TXD_L4_CSUM_NOT;
+ }
+
+ return command;
+}
+
+/* Get number of sent descriptors and decrement counter.
+ * The number of sent descriptors is returned.
+ * Per-CPU access
+ */
+static inline int mvpp2_txq_sent_desc_proc(struct mvpp2_port *port,
+ struct mvpp2_tx_queue *txq)
+{
+ u32 val;
+
+ /* Reading status reg resets transmitted descriptor counter */
+ val = mvpp2_read(port->priv, MVPP2_TXQ_SENT_REG(txq->id));
+
+ return (val & MVPP2_TRANSMITTED_COUNT_MASK) >>
+ MVPP2_TRANSMITTED_COUNT_OFFSET;
+}
+
+static void mvpp2_txq_sent_counter_clear(void *arg)
+{
+ struct mvpp2_port *port = arg;
+ int queue;
+
+ for (queue = 0; queue < txq_number; queue++) {
+ int id = port->txqs[queue]->id;
+
+ mvpp2_read(port->priv, MVPP2_TXQ_SENT_REG(id));
+ }
+}
+
+/* Set max sizes for Tx queues */
+static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
+{
+ u32 val, size, mtu;
+ int txq, tx_port_num;
+
+ mtu = port->pkt_size * 8;
+ if (mtu > MVPP2_TXP_MTU_MAX)
+ mtu = MVPP2_TXP_MTU_MAX;
+
+ /* WA for wrong Token bucket update: Set MTU value = 3*real MTU value */
+ mtu = 3 * mtu;
+
+ /* Indirect access to registers */
+ tx_port_num = mvpp2_egress_port(port);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+
+ /* Set MTU */
+ val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_MTU_REG);
+ val &= ~MVPP2_TXP_MTU_MAX;
+ val |= mtu;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_MTU_REG, val);
+
+ /* TXP token size and all TXQs token size must be larger that MTU */
+ val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG);
+ size = val & MVPP2_TXP_TOKEN_SIZE_MAX;
+ if (size < mtu) {
+ size = mtu;
+ val &= ~MVPP2_TXP_TOKEN_SIZE_MAX;
+ val |= size;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
+ }
+
+ for (txq = 0; txq < txq_number; txq++) {
+ val = mvpp2_read(port->priv,
+ MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq));
+ size = val & MVPP2_TXQ_TOKEN_SIZE_MAX;
+
+ if (size < mtu) {
+ size = mtu;
+ val &= ~MVPP2_TXQ_TOKEN_SIZE_MAX;
+ val |= size;
+ mvpp2_write(port->priv,
+ MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq),
+ val);
+ }
+ }
+}
+
+/* Set the number of packets that will be received before Rx interrupt
+ * will be generated by HW.
+ */
+static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
+ struct mvpp2_rx_queue *rxq, u32 pkts)
+{
+ u32 val;
+
+ val = (pkts & MVPP2_OCCUPIED_THRESH_MASK);
+ mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+ mvpp2_write(port->priv, MVPP2_RXQ_THRESH_REG, val);
+
+ rxq->pkts_coal = pkts;
+}
+
+/* Set the time delay in usec before Rx interrupt */
+static void mvpp2_rx_time_coal_set(struct mvpp2_port *port,
+ struct mvpp2_rx_queue *rxq, u32 usec)
+{
+ u32 val;
+
+ val = (port->priv->tclk / USEC_PER_SEC) * usec;
+ mvpp2_write(port->priv, MVPP2_ISR_RX_THRESHOLD_REG(rxq->id), val);
+
+ rxq->time_coal = usec;
+}
+
+/* Set threshold for TX_DONE pkts coalescing */
+static void mvpp2_tx_done_pkts_coal_set(void *arg)
+{
+ struct mvpp2_port *port = arg;
+ int queue;
+ u32 val;
+
+ for (queue = 0; queue < txq_number; queue++) {
+ struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+ val = (txq->done_pkts_coal << MVPP2_TRANSMITTED_THRESH_OFFSET) &
+ MVPP2_TRANSMITTED_THRESH_MASK;
+ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+ mvpp2_write(port->priv, MVPP2_TXQ_THRESH_REG, val);
+ }
+}
+
+/* Free Tx queue skbuffs */
+static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
+ struct mvpp2_tx_queue *txq,
+ struct mvpp2_txq_pcpu *txq_pcpu, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ struct mvpp2_tx_desc *tx_desc = txq->descs +
+ txq_pcpu->txq_get_index;
+ struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
+
+ mvpp2_txq_inc_get(txq_pcpu);
+
+ if (!skb)
+ continue;
+
+ dma_unmap_single(port->dev->dev.parent, tx_desc->buf_phys_addr,
+ tx_desc->data_size, DMA_TO_DEVICE);
+ dev_kfree_skb_any(skb);
+ }
+}
+
+static inline struct mvpp2_rx_queue *mvpp2_get_rx_queue(struct mvpp2_port *port,
+ u32 cause)
+{
+ int queue = fls(cause) - 1;
+
+ return port->rxqs[queue];
+}
+
+static inline struct mvpp2_tx_queue *mvpp2_get_tx_queue(struct mvpp2_port *port,
+ u32 cause)
+{
+ int queue = fls(cause >> 16) - 1;
+
+ return port->txqs[queue];
+}
+
+/* Handle end of transmission */
+static void mvpp2_txq_done(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
+ struct mvpp2_txq_pcpu *txq_pcpu)
+{
+ struct netdev_queue *nq = netdev_get_tx_queue(port->dev, txq->log_id);
+ int tx_done;
+
+ if (txq_pcpu->cpu != smp_processor_id())
+ netdev_err(port->dev, "wrong cpu on the end of Tx processing\n");
+
+ tx_done = mvpp2_txq_sent_desc_proc(port, txq);
+ if (!tx_done)
+ return;
+ mvpp2_txq_bufs_free(port, txq, txq_pcpu, tx_done);
+
+ txq_pcpu->count -= tx_done;
+
+ if (netif_tx_queue_stopped(nq))
+ if (txq_pcpu->size - txq_pcpu->count >= MAX_SKB_FRAGS + 1)
+ netif_tx_wake_queue(nq);
+}
+
+/* Rx/Tx queue initialization/cleanup methods */
+
+/* Allocate and initialize descriptors for aggr TXQ */
+static int mvpp2_aggr_txq_init(struct platform_device *pdev,
+ struct mvpp2_tx_queue *aggr_txq,
+ int desc_num, int cpu,
+ struct mvpp2 *priv)
+{
+ /* Allocate memory for TX descriptors */
+ aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
+ desc_num * MVPP2_DESC_ALIGNED_SIZE,
+ &aggr_txq->descs_phys, GFP_KERNEL);
+ if (!aggr_txq->descs)
+ return -ENOMEM;
+
+ /* Make sure descriptor address is cache line size aligned */
+ BUG_ON(aggr_txq->descs !=
+ PTR_ALIGN(aggr_txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+ aggr_txq->last_desc = aggr_txq->size - 1;
+
+ /* Aggr TXQ no reset WA */
+ aggr_txq->next_desc_to_proc = mvpp2_read(priv,
+ MVPP2_AGGR_TXQ_INDEX_REG(cpu));
+
+ /* Set Tx descriptors queue starting address */
+ /* indirect access */
+ mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu),
+ aggr_txq->descs_phys);
+ mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu), desc_num);
+
+ return 0;
+}
+
+/* Create a specified Rx queue */
+static int mvpp2_rxq_init(struct mvpp2_port *port,
+ struct mvpp2_rx_queue *rxq)
+
+{
+ rxq->size = port->rx_ring_size;
+
+ /* Allocate memory for RX descriptors */
+ rxq->descs = dma_alloc_coherent(port->dev->dev.parent,
+ rxq->size * MVPP2_DESC_ALIGNED_SIZE,
+ &rxq->descs_phys, GFP_KERNEL);
+ if (!rxq->descs)
+ return -ENOMEM;
+
+ BUG_ON(rxq->descs !=
+ PTR_ALIGN(rxq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+ rxq->last_desc = rxq->size - 1;
+
+ /* Zero occupied and non-occupied counters - direct access */
+ mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
+
+ /* Set Rx descriptors queue starting address - indirect access */
+ mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+ mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq->descs_phys);
+ mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
+ mvpp2_write(port->priv, MVPP2_RXQ_INDEX_REG, 0);
+
+ /* Set Offset */
+ mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD);
+
+ /* Set coalescing pkts and time */
+ mvpp2_rx_pkts_coal_set(port, rxq, rxq->pkts_coal);
+ mvpp2_rx_time_coal_set(port, rxq, rxq->time_coal);
+
+ /* Add number of descriptors ready for receiving packets */
+ mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size);
+
+ return 0;
+}
+
+/* Push packets received by the RXQ to BM pool */
+static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
+ struct mvpp2_rx_queue *rxq)
+{
+ int rx_received, i;
+
+ rx_received = mvpp2_rxq_received(port, rxq->id);
+ if (!rx_received)
+ return;
+
+ for (i = 0; i < rx_received; i++) {
+ struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+ u32 bm = mvpp2_bm_cookie_build(rx_desc);
+
+ mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
+ rx_desc->buf_cookie);
+ }
+ mvpp2_rxq_status_update(port, rxq->id, rx_received, rx_received);
+}
+
+/* Cleanup Rx queue */
+static void mvpp2_rxq_deinit(struct mvpp2_port *port,
+ struct mvpp2_rx_queue *rxq)
+{
+ mvpp2_rxq_drop_pkts(port, rxq);
+
+ if (rxq->descs)
+ dma_free_coherent(port->dev->dev.parent,
+ rxq->size * MVPP2_DESC_ALIGNED_SIZE,
+ rxq->descs,
+ rxq->descs_phys);
+
+ rxq->descs = NULL;
+ rxq->last_desc = 0;
+ rxq->next_desc_to_proc = 0;
+ rxq->descs_phys = 0;
+
+ /* Clear Rx descriptors queue starting address and size;
+ * free descriptor number
+ */
+ mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
+ mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
+ mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, 0);
+ mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, 0);
+}
+
+/* Create and initialize a Tx queue */
+static int mvpp2_txq_init(struct mvpp2_port *port,
+ struct mvpp2_tx_queue *txq)
+{
+ u32 val;
+ int cpu, desc, desc_per_txq, tx_port_num;
+ struct mvpp2_txq_pcpu *txq_pcpu;
+
+ txq->size = port->tx_ring_size;
+
+ /* Allocate memory for Tx descriptors */
+ txq->descs = dma_alloc_coherent(port->dev->dev.parent,
+ txq->size * MVPP2_DESC_ALIGNED_SIZE,
+ &txq->descs_phys, GFP_KERNEL);
+ if (!txq->descs)
+ return -ENOMEM;
+
+ /* Make sure descriptor address is cache line size aligned */
+ BUG_ON(txq->descs !=
+ PTR_ALIGN(txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE));
+
+ txq->last_desc = txq->size - 1;
+
+ /* Set Tx descriptors queue starting address - indirect access */
+ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+ mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, txq->descs_phys);
+ mvpp2_write(port->priv, MVPP2_TXQ_DESC_SIZE_REG, txq->size &
+ MVPP2_TXQ_DESC_SIZE_MASK);
+ mvpp2_write(port->priv, MVPP2_TXQ_INDEX_REG, 0);
+ mvpp2_write(port->priv, MVPP2_TXQ_RSVD_CLR_REG,
+ txq->id << MVPP2_TXQ_RSVD_CLR_OFFSET);
+ val = mvpp2_read(port->priv, MVPP2_TXQ_PENDING_REG);
+ val &= ~MVPP2_TXQ_PENDING_MASK;
+ mvpp2_write(port->priv, MVPP2_TXQ_PENDING_REG, val);
+
+ /* Calculate base address in prefetch buffer. We reserve 16 descriptors
+ * for each existing TXQ.
+ * TCONTS for PON port must be continuous from 0 to MVPP2_MAX_TCONT
+ * GBE ports assumed to be continious from 0 to MVPP2_MAX_PORTS
+ */
+ desc_per_txq = 16;
+ desc = (port->id * MVPP2_MAX_TXQ * desc_per_txq) +
+ (txq->log_id * desc_per_txq);
+
+ mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG,
+ MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
+ MVPP2_PREF_BUF_THRESH(desc_per_txq/2));
+
+ /* WRR / EJP configuration - indirect access */
+ tx_port_num = mvpp2_egress_port(port);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+
+ val = mvpp2_read(port->priv, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id));
+ val &= ~MVPP2_TXQ_REFILL_PERIOD_ALL_MASK;
+ val |= MVPP2_TXQ_REFILL_PERIOD_MASK(1);
+ val |= MVPP2_TXQ_REFILL_TOKENS_ALL_MASK;
+ mvpp2_write(port->priv, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id), val);
+
+ val = MVPP2_TXQ_TOKEN_SIZE_MAX;
+ mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq->log_id),
+ val);
+
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+ txq_pcpu->size = txq->size;
+ txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
+ sizeof(*txq_pcpu->tx_skb),
+ GFP_KERNEL);
+ if (!txq_pcpu->tx_skb) {
+ dma_free_coherent(port->dev->dev.parent,
+ txq->size * MVPP2_DESC_ALIGNED_SIZE,
+ txq->descs, txq->descs_phys);
+ return -ENOMEM;
+ }
+
+ txq_pcpu->count = 0;
+ txq_pcpu->reserved_num = 0;
+ txq_pcpu->txq_put_index = 0;
+ txq_pcpu->txq_get_index = 0;
+ }
+
+ return 0;
+}
+
+/* Free allocated TXQ resources */
+static void mvpp2_txq_deinit(struct mvpp2_port *port,
+ struct mvpp2_tx_queue *txq)
+{
+ struct mvpp2_txq_pcpu *txq_pcpu;
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+ kfree(txq_pcpu->tx_skb);
+ }
+
+ if (txq->descs)
+ dma_free_coherent(port->dev->dev.parent,
+ txq->size * MVPP2_DESC_ALIGNED_SIZE,
+ txq->descs, txq->descs_phys);
+
+ txq->descs = NULL;
+ txq->last_desc = 0;
+ txq->next_desc_to_proc = 0;
+ txq->descs_phys = 0;
+
+ /* Set minimum bandwidth for disabled TXQs */
+ mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
+
+ /* Set Tx descriptors queue starting address and size */
+ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+ mvpp2_write(port->priv, MVPP2_TXQ_DESC_ADDR_REG, 0);
+ mvpp2_write(port->priv, MVPP2_TXQ_DESC_SIZE_REG, 0);
+}
+
+/* Cleanup Tx ports */
+static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
+{
+ struct mvpp2_txq_pcpu *txq_pcpu;
+ int delay, pending, cpu;
+ u32 val;
+
+ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
+ val = mvpp2_read(port->priv, MVPP2_TXQ_PREF_BUF_REG);
+ val |= MVPP2_TXQ_DRAIN_EN_MASK;
+ mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val);
+
+ /* The napi queue has been stopped so wait for all packets
+ * to be transmitted.
+ */
+ delay = 0;
+ do {
+ if (delay >= MVPP2_TX_PENDING_TIMEOUT_MSEC) {
+ netdev_warn(port->dev,
+ "port %d: cleaning queue %d timed out\n",
+ port->id, txq->log_id);
+ break;
+ }
+ mdelay(1);
+ delay++;
+
+ pending = mvpp2_txq_pend_desc_num_get(port, txq);
+ } while (pending);
+
+ val &= ~MVPP2_TXQ_DRAIN_EN_MASK;
+ mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val);
+
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+
+ /* Release all packets */
+ mvpp2_txq_bufs_free(port, txq, txq_pcpu, txq_pcpu->count);
+
+ /* Reset queue */
+ txq_pcpu->count = 0;
+ txq_pcpu->txq_put_index = 0;
+ txq_pcpu->txq_get_index = 0;
+ }
+}
+
+/* Cleanup all Tx queues */
+static void mvpp2_cleanup_txqs(struct mvpp2_port *port)
+{
+ struct mvpp2_tx_queue *txq;
+ int queue;
+ u32 val;
+
+ val = mvpp2_read(port->priv, MVPP2_TX_PORT_FLUSH_REG);
+
+ /* Reset Tx ports and delete Tx queues */
+ val |= MVPP2_TX_PORT_FLUSH_MASK(port->id);
+ mvpp2_write(port->priv, MVPP2_TX_PORT_FLUSH_REG, val);
+
+ for (queue = 0; queue < txq_number; queue++) {
+ txq = port->txqs[queue];
+ mvpp2_txq_clean(port, txq);
+ mvpp2_txq_deinit(port, txq);
+ }
+
+ on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
+
+ val &= ~MVPP2_TX_PORT_FLUSH_MASK(port->id);
+ mvpp2_write(port->priv, MVPP2_TX_PORT_FLUSH_REG, val);
+}
+
+/* Cleanup all Rx queues */
+static void mvpp2_cleanup_rxqs(struct mvpp2_port *port)
+{
+ int queue;
+
+ for (queue = 0; queue < rxq_number; queue++)
+ mvpp2_rxq_deinit(port, port->rxqs[queue]);
+}
+
+/* Init all Rx queues for port */
+static int mvpp2_setup_rxqs(struct mvpp2_port *port)
+{
+ int queue, err;
+
+ for (queue = 0; queue < rxq_number; queue++) {
+ err = mvpp2_rxq_init(port, port->rxqs[queue]);
+ if (err)
+ goto err_cleanup;
+ }
+ return 0;
+
+err_cleanup:
+ mvpp2_cleanup_rxqs(port);
+ return err;
+}
+
+/* Init all tx queues for port */
+static int mvpp2_setup_txqs(struct mvpp2_port *port)
+{
+ struct mvpp2_tx_queue *txq;
+ int queue, err;
+
+ for (queue = 0; queue < txq_number; queue++) {
+ txq = port->txqs[queue];
+ err = mvpp2_txq_init(port, txq);
+ if (err)
+ goto err_cleanup;
+ }
+
+ on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
+ on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
+ return 0;
+
+err_cleanup:
+ mvpp2_cleanup_txqs(port);
+ return err;
+}
+
+/* The callback for per-port interrupt */
+static irqreturn_t mvpp2_isr(int irq, void *dev_id)
+{
+ struct mvpp2_port *port = (struct mvpp2_port *)dev_id;
+
+ mvpp2_interrupts_disable(port);
+
+ napi_schedule(&port->napi);
+
+ return IRQ_HANDLED;
+}
+
+/* Adjust link */
+static void mvpp2_link_event(struct net_device *dev)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ struct phy_device *phydev = port->phy_dev;
+ int status_change = 0;
+ u32 val;
+
+ if (phydev->link) {
+ if ((port->speed != phydev->speed) ||
+ (port->duplex != phydev->duplex)) {
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val &= ~(MVPP2_GMAC_CONFIG_MII_SPEED |
+ MVPP2_GMAC_CONFIG_GMII_SPEED |
+ MVPP2_GMAC_CONFIG_FULL_DUPLEX |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_AN_DUPLEX_EN);
+
+ if (phydev->duplex)
+ val |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
+
+ if (phydev->speed == SPEED_1000)
+ val |= MVPP2_GMAC_CONFIG_GMII_SPEED;
+ else if (phydev->speed == SPEED_100)
+ val |= MVPP2_GMAC_CONFIG_MII_SPEED;
+
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+
+ port->duplex = phydev->duplex;
+ port->speed = phydev->speed;
+ }
+ }
+
+ if (phydev->link != port->link) {
+ if (!phydev->link) {
+ port->duplex = -1;
+ port->speed = 0;
+ }
+
+ port->link = phydev->link;
+ status_change = 1;
+ }
+
+ if (status_change) {
+ if (phydev->link) {
+ val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ val |= (MVPP2_GMAC_FORCE_LINK_PASS |
+ MVPP2_GMAC_FORCE_LINK_DOWN);
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+ } else {
+ mvpp2_ingress_disable(port);
+ mvpp2_egress_disable(port);
+ }
+ phy_print_status(phydev);
+ }
+}
+
+/* Main RX/TX processing routines */
+
+/* Display more error info */
+static void mvpp2_rx_error(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ u32 status = rx_desc->status;
+
+ switch (status & MVPP2_RXD_ERR_CODE_MASK) {
+ case MVPP2_RXD_ERR_CRC:
+ netdev_err(port->dev, "bad rx status %08x (crc error), size=%d\n",
+ status, rx_desc->data_size);
+ break;
+ case MVPP2_RXD_ERR_OVERRUN:
+ netdev_err(port->dev, "bad rx status %08x (overrun error), size=%d\n",
+ status, rx_desc->data_size);
+ break;
+ case MVPP2_RXD_ERR_RESOURCE:
+ netdev_err(port->dev, "bad rx status %08x (resource error), size=%d\n",
+ status, rx_desc->data_size);
+ break;
+ }
+}
+
+/* Handle RX checksum offload */
+static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
+ struct sk_buff *skb)
+{
+ if (((status & MVPP2_RXD_L3_IP4) &&
+ !(status & MVPP2_RXD_IP4_HEADER_ERR)) ||
+ (status & MVPP2_RXD_L3_IP6))
+ if (((status & MVPP2_RXD_L4_UDP) ||
+ (status & MVPP2_RXD_L4_TCP)) &&
+ (status & MVPP2_RXD_L4_CSUM_OK)) {
+ skb->csum = 0;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ return;
+ }
+
+ skb->ip_summed = CHECKSUM_NONE;
+}
+
+/* Reuse skb if possible, or allocate a new skb and add it to BM pool */
+static int mvpp2_rx_refill(struct mvpp2_port *port,
+ struct mvpp2_bm_pool *bm_pool,
+ u32 bm, int is_recycle)
+{
+ struct sk_buff *skb;
+ dma_addr_t phys_addr;
+
+ if (is_recycle &&
+ (atomic_read(&bm_pool->in_use) < bm_pool->in_use_thresh))
+ return 0;
+
+ /* No recycle or too many buffers are in use, so allocate a new skb */
+ skb = mvpp2_skb_alloc(port, bm_pool, &phys_addr, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ mvpp2_pool_refill(port, bm, (u32)phys_addr, (u32)skb);
+ atomic_dec(&bm_pool->in_use);
+ return 0;
+}
+
+/* Handle tx checksum */
+static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb)
+{
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int ip_hdr_len = 0;
+ u8 l4_proto;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct iphdr *ip4h = ip_hdr(skb);
+
+ /* Calculate IPv4 checksum and L4 checksum */
+ ip_hdr_len = ip4h->ihl;
+ l4_proto = ip4h->protocol;
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+ /* Read l4_protocol from one of IPv6 extra headers */
+ if (skb_network_header_len(skb) > 0)
+ ip_hdr_len = (skb_network_header_len(skb) >> 2);
+ l4_proto = ip6h->nexthdr;
+ } else {
+ return MVPP2_TXD_L4_CSUM_NOT;
+ }
+
+ return mvpp2_txq_desc_csum(skb_network_offset(skb),
+ skb->protocol, ip_hdr_len, l4_proto);
+ }
+
+ return MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE;
+}
+
+static void mvpp2_buff_hdr_rx(struct mvpp2_port *port,
+ struct mvpp2_rx_desc *rx_desc)
+{
+ struct mvpp2_buff_hdr *buff_hdr;
+ struct sk_buff *skb;
+ u32 rx_status = rx_desc->status;
+ u32 buff_phys_addr;
+ u32 buff_virt_addr;
+ u32 buff_phys_addr_next;
+ u32 buff_virt_addr_next;
+ int mc_id;
+ int pool_id;
+
+ pool_id = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+ MVPP2_RXD_BM_POOL_ID_OFFS;
+ buff_phys_addr = rx_desc->buf_phys_addr;
+ buff_virt_addr = rx_desc->buf_cookie;
+
+ do {
+ skb = (struct sk_buff *)buff_virt_addr;
+ buff_hdr = (struct mvpp2_buff_hdr *)skb->head;
+
+ mc_id = MVPP2_B_HDR_INFO_MC_ID(buff_hdr->info);
+
+ buff_phys_addr_next = buff_hdr->next_buff_phys_addr;
+ buff_virt_addr_next = buff_hdr->next_buff_virt_addr;
+
+ /* Release buffer */
+ mvpp2_bm_pool_mc_put(port, pool_id, buff_phys_addr,
+ buff_virt_addr, mc_id);
+
+ buff_phys_addr = buff_phys_addr_next;
+ buff_virt_addr = buff_virt_addr_next;
+
+ } while (!MVPP2_B_HDR_INFO_IS_LAST(buff_hdr->info));
+}
+
+/* Main rx processing */
+static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
+ struct mvpp2_rx_queue *rxq)
+{
+ struct net_device *dev = port->dev;
+ int rx_received, rx_filled, i;
+ u32 rcvd_pkts = 0;
+ u32 rcvd_bytes = 0;
+
+ /* Get number of received packets and clamp the to-do */
+ rx_received = mvpp2_rxq_received(port, rxq->id);
+ if (rx_todo > rx_received)
+ rx_todo = rx_received;
+
+ rx_filled = 0;
+ for (i = 0; i < rx_todo; i++) {
+ struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
+ struct mvpp2_bm_pool *bm_pool;
+ struct sk_buff *skb;
+ u32 bm, rx_status;
+ int pool, rx_bytes, err;
+
+ rx_filled++;
+ rx_status = rx_desc->status;
+ rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
+
+ bm = mvpp2_bm_cookie_build(rx_desc);
+ pool = mvpp2_bm_cookie_pool_get(bm);
+ bm_pool = &port->priv->bm_pools[pool];
+ /* Check if buffer header is used */
+ if (rx_status & MVPP2_RXD_BUF_HDR) {
+ mvpp2_buff_hdr_rx(port, rx_desc);
+ continue;
+ }
+
+ /* In case of an error, release the requested buffer pointer
+ * to the Buffer Manager. This request process is controlled
+ * by the hardware, and the information about the buffer is
+ * comprised by the RX descriptor.
+ */
+ if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
+ dev->stats.rx_errors++;
+ mvpp2_rx_error(port, rx_desc);
+ mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
+ rx_desc->buf_cookie);
+ continue;
+ }
+
+ skb = (struct sk_buff *)rx_desc->buf_cookie;
+
+ rcvd_pkts++;
+ rcvd_bytes += rx_bytes;
+ atomic_inc(&bm_pool->in_use);
+
+ skb_reserve(skb, MVPP2_MH_SIZE);
+ skb_put(skb, rx_bytes);
+ skb->protocol = eth_type_trans(skb, dev);
+ mvpp2_rx_csum(port, rx_status, skb);
+
+ napi_gro_receive(&port->napi, skb);
+
+ err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+ if (err) {
+ netdev_err(port->dev, "failed to refill BM pools\n");
+ rx_filled--;
+ }
+ }
+
+ if (rcvd_pkts) {
+ struct mvpp2_pcpu_stats *stats = this_cpu_ptr(port->stats);
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_packets += rcvd_pkts;
+ stats->rx_bytes += rcvd_bytes;
+ u64_stats_update_end(&stats->syncp);
+ }
+
+ /* Update Rx queue management counters */
+ wmb();
+ mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled);
+
+ return rx_todo;
+}
+
+static inline void
+tx_desc_unmap_put(struct device *dev, struct mvpp2_tx_queue *txq,
+ struct mvpp2_tx_desc *desc)
+{
+ dma_unmap_single(dev, desc->buf_phys_addr,
+ desc->data_size, DMA_TO_DEVICE);
+ mvpp2_txq_desc_put(txq);
+}
+
+/* Handle tx fragmentation processing */
+static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
+ struct mvpp2_tx_queue *aggr_txq,
+ struct mvpp2_tx_queue *txq)
+{
+ struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
+ struct mvpp2_tx_desc *tx_desc;
+ int i;
+ dma_addr_t buf_phys_addr;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ void *addr = page_address(frag->page.p) + frag->page_offset;
+
+ tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+ tx_desc->phys_txq = txq->id;
+ tx_desc->data_size = frag->size;
+
+ buf_phys_addr = dma_map_single(port->dev->dev.parent, addr,
+ tx_desc->data_size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(port->dev->dev.parent, buf_phys_addr)) {
+ mvpp2_txq_desc_put(txq);
+ goto error;
+ }
+
+ tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
+ tx_desc->buf_phys_addr = buf_phys_addr & (~MVPP2_TX_DESC_ALIGN);
+
+ if (i == (skb_shinfo(skb)->nr_frags - 1)) {
+ /* Last descriptor */
+ tx_desc->command = MVPP2_TXD_L_DESC;
+ mvpp2_txq_inc_put(txq_pcpu, skb);
+ } else {
+ /* Descriptor in the middle: Not First, Not Last */
+ tx_desc->command = 0;
+ mvpp2_txq_inc_put(txq_pcpu, NULL);
+ }
+ }
+
+ return 0;
+
+error:
+ /* Release all descriptors that were used to map fragments of
+ * this packet, as well as the corresponding DMA mappings
+ */
+ for (i = i - 1; i >= 0; i--) {
+ tx_desc = txq->descs + i;
+ tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+ }
+
+ return -ENOMEM;
+}
+
+/* Main tx processing */
+static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_tx_queue *txq, *aggr_txq;
+ struct mvpp2_txq_pcpu *txq_pcpu;
+ struct mvpp2_tx_desc *tx_desc;
+ dma_addr_t buf_phys_addr;
+ int frags = 0;
+ u16 txq_id;
+ u32 tx_cmd;
+
+ txq_id = skb_get_queue_mapping(skb);
+ txq = port->txqs[txq_id];
+ txq_pcpu = this_cpu_ptr(txq->pcpu);
+ aggr_txq = &port->priv->aggr_txqs[smp_processor_id()];
+
+ frags = skb_shinfo(skb)->nr_frags + 1;
+
+ /* Check number of available descriptors */
+ if (mvpp2_aggr_desc_num_check(port->priv, aggr_txq, frags) ||
+ mvpp2_txq_reserved_desc_num_proc(port->priv, txq,
+ txq_pcpu, frags)) {
+ frags = 0;
+ goto out;
+ }
+
+ /* Get a descriptor for the first part of the packet */
+ tx_desc = mvpp2_txq_next_desc_get(aggr_txq);
+ tx_desc->phys_txq = txq->id;
+ tx_desc->data_size = skb_headlen(skb);
+
+ buf_phys_addr = dma_map_single(dev->dev.parent, skb->data,
+ tx_desc->data_size, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev->dev.parent, buf_phys_addr))) {
+ mvpp2_txq_desc_put(txq);
+ frags = 0;
+ goto out;
+ }
+ tx_desc->packet_offset = buf_phys_addr & MVPP2_TX_DESC_ALIGN;
+ tx_desc->buf_phys_addr = buf_phys_addr & ~MVPP2_TX_DESC_ALIGN;
+
+ tx_cmd = mvpp2_skb_tx_csum(port, skb);
+
+ if (frags == 1) {
+ /* First and Last descriptor */
+ tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
+ tx_desc->command = tx_cmd;
+ mvpp2_txq_inc_put(txq_pcpu, skb);
+ } else {
+ /* First but not Last */
+ tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_PADDING_DISABLE;
+ tx_desc->command = tx_cmd;
+ mvpp2_txq_inc_put(txq_pcpu, NULL);
+
+ /* Continue with other skb fragments */
+ if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
+ tx_desc_unmap_put(port->dev->dev.parent, txq, tx_desc);
+ frags = 0;
+ goto out;
+ }
+ }
+
+ txq_pcpu->reserved_num -= frags;
+ txq_pcpu->count += frags;
+ aggr_txq->count += frags;
+
+ /* Enable transmit */
+ wmb();
+ mvpp2_aggr_txq_pend_desc_add(port, frags);
+
+ if (txq_pcpu->size - txq_pcpu->count < MAX_SKB_FRAGS + 1) {
+ struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id);
+
+ netif_tx_stop_queue(nq);
+ }
+out:
+ if (frags > 0) {
+ struct mvpp2_pcpu_stats *stats = this_cpu_ptr(port->stats);
+
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+ u64_stats_update_end(&stats->syncp);
+ } else {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb_any(skb);
+ }
+
+ return NETDEV_TX_OK;
+}
+
+static inline void mvpp2_cause_error(struct net_device *dev, int cause)
+{
+ if (cause & MVPP2_CAUSE_FCS_ERR_MASK)
+ netdev_err(dev, "FCS error\n");
+ if (cause & MVPP2_CAUSE_RX_FIFO_OVERRUN_MASK)
+ netdev_err(dev, "rx fifo overrun error\n");
+ if (cause & MVPP2_CAUSE_TX_FIFO_UNDERRUN_MASK)
+ netdev_err(dev, "tx fifo underrun error\n");
+}
+
+static void mvpp2_txq_done_percpu(void *arg)
+{
+ struct mvpp2_port *port = arg;
+ u32 cause_rx_tx, cause_tx, cause_misc;
+
+ /* Rx/Tx cause register
+ *
+ * Bits 0-15: each bit indicates received packets on the Rx queue
+ * (bit 0 is for Rx queue 0).
+ *
+ * Bits 16-23: each bit indicates transmitted packets on the Tx queue
+ * (bit 16 is for Tx queue 0).
+ *
+ * Each CPU has its own Rx/Tx cause register
+ */
+ cause_rx_tx = mvpp2_read(port->priv,
+ MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
+ cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
+ cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
+
+ if (cause_misc) {
+ mvpp2_cause_error(port->dev, cause_misc);
+
+ /* Clear the cause register */
+ mvpp2_write(port->priv, MVPP2_ISR_MISC_CAUSE_REG, 0);
+ mvpp2_write(port->priv, MVPP2_ISR_RX_TX_CAUSE_REG(port->id),
+ cause_rx_tx & ~MVPP2_CAUSE_MISC_SUM_MASK);
+ }
+
+ /* Release TX descriptors */
+ if (cause_tx) {
+ struct mvpp2_tx_queue *txq = mvpp2_get_tx_queue(port, cause_tx);
+ struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
+
+ if (txq_pcpu->count)
+ mvpp2_txq_done(port, txq, txq_pcpu);
+ }
+}
+
+static int mvpp2_poll(struct napi_struct *napi, int budget)
+{
+ u32 cause_rx_tx, cause_rx;
+ int rx_done = 0;
+ struct mvpp2_port *port = netdev_priv(napi->dev);
+
+ on_each_cpu(mvpp2_txq_done_percpu, port, 1);
+
+ cause_rx_tx = mvpp2_read(port->priv,
+ MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
+ cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK;
+
+ /* Process RX packets */
+ cause_rx |= port->pending_cause_rx;
+ while (cause_rx && budget > 0) {
+ int count;
+ struct mvpp2_rx_queue *rxq;
+
+ rxq = mvpp2_get_rx_queue(port, cause_rx);
+ if (!rxq)
+ break;
+
+ count = mvpp2_rx(port, budget, rxq);
+ rx_done += count;
+ budget -= count;
+ if (budget > 0) {
+ /* Clear the bit associated to this Rx queue
+ * so that next iteration will continue from
+ * the next Rx queue.
+ */
+ cause_rx &= ~(1 << rxq->logic_rxq);
+ }
+ }
+
+ if (budget > 0) {
+ cause_rx = 0;
+ napi_complete(napi);
+
+ mvpp2_interrupts_enable(port);
+ }
+ port->pending_cause_rx = cause_rx;
+ return rx_done;
+}
+
+/* Set hw internals when starting port */
+static void mvpp2_start_dev(struct mvpp2_port *port)
+{
+ mvpp2_gmac_max_rx_size_set(port);
+ mvpp2_txp_max_tx_size_set(port);
+
+ napi_enable(&port->napi);
+
+ /* Enable interrupts on all CPUs */
+ mvpp2_interrupts_enable(port);
+
+ mvpp2_port_enable(port);
+ phy_start(port->phy_dev);
+ netif_tx_start_all_queues(port->dev);
+}
+
+/* Set hw internals when stopping port */
+static void mvpp2_stop_dev(struct mvpp2_port *port)
+{
+ /* Stop new packets from arriving to RXQs */
+ mvpp2_ingress_disable(port);
+
+ mdelay(10);
+
+ /* Disable interrupts on all CPUs */
+ mvpp2_interrupts_disable(port);
+
+ napi_disable(&port->napi);
+
+ netif_carrier_off(port->dev);
+ netif_tx_stop_all_queues(port->dev);
+
+ mvpp2_egress_disable(port);
+ mvpp2_port_disable(port);
+ phy_stop(port->phy_dev);
+}
+
+/* Return positive if MTU is valid */
+static inline int mvpp2_check_mtu_valid(struct net_device *dev, int mtu)
+{
+ if (mtu < 68) {
+ netdev_err(dev, "cannot change mtu to less than 68\n");
+ return -EINVAL;
+ }
+
+ /* 9676 == 9700 - 20 and rounding to 8 */
+ if (mtu > 9676) {
+ netdev_info(dev, "illegal MTU value %d, round to 9676\n", mtu);
+ mtu = 9676;
+ }
+
+ if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
+ netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
+ ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
+ mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
+ }
+
+ return mtu;
+}
+
+static int mvpp2_check_ringparam_valid(struct net_device *dev,
+ struct ethtool_ringparam *ring)
+{
+ u16 new_rx_pending = ring->rx_pending;
+ u16 new_tx_pending = ring->tx_pending;
+
+ if (ring->rx_pending == 0 || ring->tx_pending == 0)
+ return -EINVAL;
+
+ if (ring->rx_pending > MVPP2_MAX_RXD)
+ new_rx_pending = MVPP2_MAX_RXD;
+ else if (!IS_ALIGNED(ring->rx_pending, 16))
+ new_rx_pending = ALIGN(ring->rx_pending, 16);
+
+ if (ring->tx_pending > MVPP2_MAX_TXD)
+ new_tx_pending = MVPP2_MAX_TXD;
+ else if (!IS_ALIGNED(ring->tx_pending, 32))
+ new_tx_pending = ALIGN(ring->tx_pending, 32);
+
+ if (ring->rx_pending != new_rx_pending) {
+ netdev_info(dev, "illegal Rx ring size value %d, round to %d\n",
+ ring->rx_pending, new_rx_pending);
+ ring->rx_pending = new_rx_pending;
+ }
+
+ if (ring->tx_pending != new_tx_pending) {
+ netdev_info(dev, "illegal Tx ring size value %d, round to %d\n",
+ ring->tx_pending, new_tx_pending);
+ ring->tx_pending = new_tx_pending;
+ }
+
+ return 0;
+}
+
+static void mvpp2_get_mac_address(struct mvpp2_port *port, unsigned char *addr)
+{
+ u32 mac_addr_l, mac_addr_m, mac_addr_h;
+
+ mac_addr_l = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+ mac_addr_m = readl(port->priv->lms_base + MVPP2_SRC_ADDR_MIDDLE);
+ mac_addr_h = readl(port->priv->lms_base + MVPP2_SRC_ADDR_HIGH);
+ addr[0] = (mac_addr_h >> 24) & 0xFF;
+ addr[1] = (mac_addr_h >> 16) & 0xFF;
+ addr[2] = (mac_addr_h >> 8) & 0xFF;
+ addr[3] = mac_addr_h & 0xFF;
+ addr[4] = mac_addr_m & 0xFF;
+ addr[5] = (mac_addr_l >> MVPP2_GMAC_SA_LOW_OFFS) & 0xFF;
+}
+
+static int mvpp2_phy_connect(struct mvpp2_port *port)
+{
+ struct phy_device *phy_dev;
+
+ phy_dev = of_phy_connect(port->dev, port->phy_node, mvpp2_link_event, 0,
+ port->phy_interface);
+ if (!phy_dev) {
+ netdev_err(port->dev, "cannot connect to phy\n");
+ return -ENODEV;
+ }
+ phy_dev->supported &= PHY_GBIT_FEATURES;
+ phy_dev->advertising = phy_dev->supported;
+
+ port->phy_dev = phy_dev;
+ port->link = 0;
+ port->duplex = 0;
+ port->speed = 0;
+
+ return 0;
+}
+
+static void mvpp2_phy_disconnect(struct mvpp2_port *port)
+{
+ phy_disconnect(port->phy_dev);
+ port->phy_dev = NULL;
+}
+
+static int mvpp2_open(struct net_device *dev)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ unsigned char mac_bcast[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ int err;
+
+ err = mvpp2_prs_mac_da_accept(port->priv, port->id, mac_bcast, true);
+ if (err) {
+ netdev_err(dev, "mvpp2_prs_mac_da_accept BC failed\n");
+ return err;
+ }
+ err = mvpp2_prs_mac_da_accept(port->priv, port->id,
+ dev->dev_addr, true);
+ if (err) {
+ netdev_err(dev, "mvpp2_prs_mac_da_accept MC failed\n");
+ return err;
+ }
+ err = mvpp2_prs_tag_mode_set(port->priv, port->id, MVPP2_TAG_TYPE_MH);
+ if (err) {
+ netdev_err(dev, "mvpp2_prs_tag_mode_set failed\n");
+ return err;
+ }
+ err = mvpp2_prs_def_flow(port);
+ if (err) {
+ netdev_err(dev, "mvpp2_prs_def_flow failed\n");
+ return err;
+ }
+
+ /* Allocate the Rx/Tx queues */
+ err = mvpp2_setup_rxqs(port);
+ if (err) {
+ netdev_err(port->dev, "cannot allocate Rx queues\n");
+ return err;
+ }
+
+ err = mvpp2_setup_txqs(port);
+ if (err) {
+ netdev_err(port->dev, "cannot allocate Tx queues\n");
+ goto err_cleanup_rxqs;
+ }
+
+ err = request_irq(port->irq, mvpp2_isr, 0, dev->name, port);
+ if (err) {
+ netdev_err(port->dev, "cannot request IRQ %d\n", port->irq);
+ goto err_cleanup_txqs;
+ }
+
+ /* In default link is down */
+ netif_carrier_off(port->dev);
+
+ err = mvpp2_phy_connect(port);
+ if (err < 0)
+ goto err_free_irq;
+
+ /* Unmask interrupts on all CPUs */
+ on_each_cpu(mvpp2_interrupts_unmask, port, 1);
+
+ mvpp2_start_dev(port);
+
+ return 0;
+
+err_free_irq:
+ free_irq(port->irq, port);
+err_cleanup_txqs:
+ mvpp2_cleanup_txqs(port);
+err_cleanup_rxqs:
+ mvpp2_cleanup_rxqs(port);
+ return err;
+}
+
+static int mvpp2_stop(struct net_device *dev)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+
+ mvpp2_stop_dev(port);
+ mvpp2_phy_disconnect(port);
+
+ /* Mask interrupts on all CPUs */
+ on_each_cpu(mvpp2_interrupts_mask, port, 1);
+
+ free_irq(port->irq, port);
+ mvpp2_cleanup_rxqs(port);
+ mvpp2_cleanup_txqs(port);
+
+ return 0;
+}
+
+static void mvpp2_set_rx_mode(struct net_device *dev)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2 *priv = port->priv;
+ struct netdev_hw_addr *ha;
+ int id = port->id;
+ bool allmulti = dev->flags & IFF_ALLMULTI;
+
+ mvpp2_prs_mac_promisc_set(priv, id, dev->flags & IFF_PROMISC);
+ mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_ALL, allmulti);
+ mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_IP6, allmulti);
+
+ /* Remove all port->id's mcast enries */
+ mvpp2_prs_mcast_del_all(priv, id);
+
+ if (allmulti && !netdev_mc_empty(dev)) {
+ netdev_for_each_mc_addr(ha, dev)
+ mvpp2_prs_mac_da_accept(priv, id, ha->addr, true);
+ }
+}
+
+static int mvpp2_set_mac_address(struct net_device *dev, void *p)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ const struct sockaddr *addr = p;
+ int err;
+
+ if (!is_valid_ether_addr(addr->sa_data)) {
+ err = -EADDRNOTAVAIL;
+ goto error;
+ }
+
+ if (!netif_running(dev)) {
+ err = mvpp2_prs_update_mac_da(dev, addr->sa_data);
+ if (!err)
+ return 0;
+ /* Reconfigure parser to accept the original MAC address */
+ err = mvpp2_prs_update_mac_da(dev, dev->dev_addr);
+ if (err)
+ goto error;
+ }
+
+ mvpp2_stop_dev(port);
+
+ err = mvpp2_prs_update_mac_da(dev, addr->sa_data);
+ if (!err)
+ goto out_start;
+
+ /* Reconfigure parser accept the original MAC address */
+ err = mvpp2_prs_update_mac_da(dev, dev->dev_addr);
+ if (err)
+ goto error;
+out_start:
+ mvpp2_start_dev(port);
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+ return 0;
+
+error:
+ netdev_err(dev, "fail to change MAC address\n");
+ return err;
+}
+
+static int mvpp2_change_mtu(struct net_device *dev, int mtu)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ int err;
+
+ mtu = mvpp2_check_mtu_valid(dev, mtu);
+ if (mtu < 0) {
+ err = mtu;
+ goto error;
+ }
+
+ if (!netif_running(dev)) {
+ err = mvpp2_bm_update_mtu(dev, mtu);
+ if (!err) {
+ port->pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+ return 0;
+ }
+
+ /* Reconfigure BM to the original MTU */
+ err = mvpp2_bm_update_mtu(dev, dev->mtu);
+ if (err)
+ goto error;
+ }
+
+ mvpp2_stop_dev(port);
+
+ err = mvpp2_bm_update_mtu(dev, mtu);
+ if (!err) {
+ port->pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+ goto out_start;
+ }
+
+ /* Reconfigure BM to the original MTU */
+ err = mvpp2_bm_update_mtu(dev, dev->mtu);
+ if (err)
+ goto error;
+
+out_start:
+ mvpp2_start_dev(port);
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+
+ return 0;
+
+error:
+ netdev_err(dev, "fail to change MTU\n");
+ return err;
+}
+
+static struct rtnl_link_stats64 *
+mvpp2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ unsigned int start;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct mvpp2_pcpu_stats *cpu_stats;
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+
+ cpu_stats = per_cpu_ptr(port->stats, cpu);
+ do {
+ start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
+ rx_packets = cpu_stats->rx_packets;
+ rx_bytes = cpu_stats->rx_bytes;
+ tx_packets = cpu_stats->tx_packets;
+ tx_bytes = cpu_stats->tx_bytes;
+ } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ }
+
+ stats->rx_errors = dev->stats.rx_errors;
+ stats->rx_dropped = dev->stats.rx_dropped;
+ stats->tx_dropped = dev->stats.tx_dropped;
+
+ return stats;
+}
+
+static int mvpp2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ int ret;
+
+ if (!port->phy_dev)
+ return -ENOTSUPP;
+
+ ret = phy_mii_ioctl(port->phy_dev, ifr, cmd);
+ if (!ret)
+ mvpp2_link_event(dev);
+
+ return ret;
+}
+
+/* Ethtool methods */
+
+/* Get settings (phy address, speed) for ethtools */
+static int mvpp2_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+
+ if (!port->phy_dev)
+ return -ENODEV;
+ return phy_ethtool_gset(port->phy_dev, cmd);
+}
+
+/* Set settings (phy address, speed) for ethtools */
+static int mvpp2_ethtool_set_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+
+ if (!port->phy_dev)
+ return -ENODEV;
+ return phy_ethtool_sset(port->phy_dev, cmd);
+}
+
+/* Set interrupt coalescing for ethtools */
+static int mvpp2_ethtool_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *c)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ int queue;
+
+ for (queue = 0; queue < rxq_number; queue++) {
+ struct mvpp2_rx_queue *rxq = port->rxqs[queue];
+
+ rxq->time_coal = c->rx_coalesce_usecs;
+ rxq->pkts_coal = c->rx_max_coalesced_frames;
+ mvpp2_rx_pkts_coal_set(port, rxq, rxq->pkts_coal);
+ mvpp2_rx_time_coal_set(port, rxq, rxq->time_coal);
+ }
+
+ for (queue = 0; queue < txq_number; queue++) {
+ struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+ txq->done_pkts_coal = c->tx_max_coalesced_frames;
+ }
+
+ on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
+ return 0;
+}
+
+/* get coalescing for ethtools */
+static int mvpp2_ethtool_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *c)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+
+ c->rx_coalesce_usecs = port->rxqs[0]->time_coal;
+ c->rx_max_coalesced_frames = port->rxqs[0]->pkts_coal;
+ c->tx_max_coalesced_frames = port->txqs[0]->done_pkts_coal;
+ return 0;
+}
+
+static void mvpp2_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strlcpy(drvinfo->driver, MVPP2_DRIVER_NAME,
+ sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, MVPP2_DRIVER_VERSION,
+ sizeof(drvinfo->version));
+ strlcpy(drvinfo->bus_info, dev_name(&dev->dev),
+ sizeof(drvinfo->bus_info));
+}
+
+static void mvpp2_ethtool_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+
+ ring->rx_max_pending = MVPP2_MAX_RXD;
+ ring->tx_max_pending = MVPP2_MAX_TXD;
+ ring->rx_pending = port->rx_ring_size;
+ ring->tx_pending = port->tx_ring_size;
+}
+
+static int mvpp2_ethtool_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ring)
+{
+ struct mvpp2_port *port = netdev_priv(dev);
+ u16 prev_rx_ring_size = port->rx_ring_size;
+ u16 prev_tx_ring_size = port->tx_ring_size;
+ int err;
+
+ err = mvpp2_check_ringparam_valid(dev, ring);
+ if (err)
+ return err;
+
+ if (!netif_running(dev)) {
+ port->rx_ring_size = ring->rx_pending;
+ port->tx_ring_size = ring->tx_pending;
+ return 0;
+ }
+
+ /* The interface is running, so we have to force a
+ * reallocation of the queues
+ */
+ mvpp2_stop_dev(port);
+ mvpp2_cleanup_rxqs(port);
+ mvpp2_cleanup_txqs(port);
+
+ port->rx_ring_size = ring->rx_pending;
+ port->tx_ring_size = ring->tx_pending;
+
+ err = mvpp2_setup_rxqs(port);
+ if (err) {
+ /* Reallocate Rx queues with the original ring size */
+ port->rx_ring_size = prev_rx_ring_size;
+ ring->rx_pending = prev_rx_ring_size;
+ err = mvpp2_setup_rxqs(port);
+ if (err)
+ goto err_out;
+ }
+ err = mvpp2_setup_txqs(port);
+ if (err) {
+ /* Reallocate Tx queues with the original ring size */
+ port->tx_ring_size = prev_tx_ring_size;
+ ring->tx_pending = prev_tx_ring_size;
+ err = mvpp2_setup_txqs(port);
+ if (err)
+ goto err_clean_rxqs;
+ }
+
+ mvpp2_start_dev(port);
+ mvpp2_egress_enable(port);
+ mvpp2_ingress_enable(port);
+
+ return 0;
+
+err_clean_rxqs:
+ mvpp2_cleanup_rxqs(port);
+err_out:
+ netdev_err(dev, "fail to change ring parameters");
+ return err;
+}
+
+/* Device ops */
+
+static const struct net_device_ops mvpp2_netdev_ops = {
+ .ndo_open = mvpp2_open,
+ .ndo_stop = mvpp2_stop,
+ .ndo_start_xmit = mvpp2_tx,
+ .ndo_set_rx_mode = mvpp2_set_rx_mode,
+ .ndo_set_mac_address = mvpp2_set_mac_address,
+ .ndo_change_mtu = mvpp2_change_mtu,
+ .ndo_get_stats64 = mvpp2_get_stats64,
+ .ndo_do_ioctl = mvpp2_ioctl,
+};
+
+static const struct ethtool_ops mvpp2_eth_tool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_settings = mvpp2_ethtool_get_settings,
+ .set_settings = mvpp2_ethtool_set_settings,
+ .set_coalesce = mvpp2_ethtool_set_coalesce,
+ .get_coalesce = mvpp2_ethtool_get_coalesce,
+ .get_drvinfo = mvpp2_ethtool_get_drvinfo,
+ .get_ringparam = mvpp2_ethtool_get_ringparam,
+ .set_ringparam = mvpp2_ethtool_set_ringparam,
+};
+
+/* Driver initialization */
+
+static void mvpp2_port_power_up(struct mvpp2_port *port)
+{
+ mvpp2_port_mii_set(port);
+ mvpp2_port_periodic_xon_disable(port);
+ mvpp2_port_fc_adv_enable(port);
+ mvpp2_port_reset(port);
+}
+
+/* Initialize port HW */
+static int mvpp2_port_init(struct mvpp2_port *port)
+{
+ struct device *dev = port->dev->dev.parent;
+ struct mvpp2 *priv = port->priv;
+ struct mvpp2_txq_pcpu *txq_pcpu;
+ int queue, cpu, err;
+
+ if (port->first_rxq + rxq_number > MVPP2_RXQ_TOTAL_NUM)
+ return -EINVAL;
+
+ /* Disable port */
+ mvpp2_egress_disable(port);
+ mvpp2_port_disable(port);
+
+ port->txqs = devm_kcalloc(dev, txq_number, sizeof(*port->txqs),
+ GFP_KERNEL);
+ if (!port->txqs)
+ return -ENOMEM;
+
+ /* Associate physical Tx queues to this port and initialize.
+ * The mapping is predefined.
+ */
+ for (queue = 0; queue < txq_number; queue++) {
+ int queue_phy_id = mvpp2_txq_phys(port->id, queue);
+ struct mvpp2_tx_queue *txq;
+
+ txq = devm_kzalloc(dev, sizeof(*txq), GFP_KERNEL);
+ if (!txq)
+ return -ENOMEM;
+
+ txq->pcpu = alloc_percpu(struct mvpp2_txq_pcpu);
+ if (!txq->pcpu) {
+ err = -ENOMEM;
+ goto err_free_percpu;
+ }
+
+ txq->id = queue_phy_id;
+ txq->log_id = queue;
+ txq->done_pkts_coal = MVPP2_TXDONE_COAL_PKTS_THRESH;
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+ txq_pcpu->cpu = cpu;
+ }
+
+ port->txqs[queue] = txq;
+ }
+
+ port->rxqs = devm_kcalloc(dev, rxq_number, sizeof(*port->rxqs),
+ GFP_KERNEL);
+ if (!port->rxqs) {
+ err = -ENOMEM;
+ goto err_free_percpu;
+ }
+
+ /* Allocate and initialize Rx queue for this port */
+ for (queue = 0; queue < rxq_number; queue++) {
+ struct mvpp2_rx_queue *rxq;
+
+ /* Map physical Rx queue to port's logical Rx queue */
+ rxq = devm_kzalloc(dev, sizeof(*rxq), GFP_KERNEL);
+ if (!rxq)
+ goto err_free_percpu;
+ /* Map this Rx queue to a physical queue */
+ rxq->id = port->first_rxq + queue;
+ rxq->port = port->id;
+ rxq->logic_rxq = queue;
+
+ port->rxqs[queue] = rxq;
+ }
+
+ /* Configure Rx queue group interrupt for this port */
+ mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(port->id), rxq_number);
+
+ /* Create Rx descriptor rings */
+ for (queue = 0; queue < rxq_number; queue++) {
+ struct mvpp2_rx_queue *rxq = port->rxqs[queue];
+
+ rxq->size = port->rx_ring_size;
+ rxq->pkts_coal = MVPP2_RX_COAL_PKTS;
+ rxq->time_coal = MVPP2_RX_COAL_USEC;
+ }
+
+ mvpp2_ingress_disable(port);
+
+ /* Port default configuration */
+ mvpp2_defaults_set(port);
+
+ /* Port's classifier configuration */
+ mvpp2_cls_oversize_rxq_set(port);
+ mvpp2_cls_port_config(port);
+
+ /* Provide an initial Rx packet size */
+ port->pkt_size = MVPP2_RX_PKT_SIZE(port->dev->mtu);
+
+ /* Initialize pools for swf */
+ err = mvpp2_swf_bm_pool_init(port);
+ if (err)
+ goto err_free_percpu;
+
+ return 0;
+
+err_free_percpu:
+ for (queue = 0; queue < txq_number; queue++) {
+ if (!port->txqs[queue])
+ continue;
+ free_percpu(port->txqs[queue]->pcpu);
+ }
+ return err;
+}
+
+/* Ports initialization */
+static int mvpp2_port_probe(struct platform_device *pdev,
+ struct device_node *port_node,
+ struct mvpp2 *priv,
+ int *next_first_rxq)
+{
+ struct device_node *phy_node;
+ struct mvpp2_port *port;
+ struct net_device *dev;
+ struct resource *res;
+ const char *dt_mac_addr;
+ const char *mac_from;
+ char hw_mac_addr[ETH_ALEN];
+ u32 id;
+ int features;
+ int phy_mode;
+ int priv_common_regs_num = 2;
+ int err, i;
+
+ dev = alloc_etherdev_mqs(sizeof(struct mvpp2_port), txq_number,
+ rxq_number);
+ if (!dev)
+ return -ENOMEM;
+
+ phy_node = of_parse_phandle(port_node, "phy", 0);
+ if (!phy_node) {
+ dev_err(&pdev->dev, "missing phy\n");
+ err = -ENODEV;
+ goto err_free_netdev;
+ }
+
+ phy_mode = of_get_phy_mode(port_node);
+ if (phy_mode < 0) {
+ dev_err(&pdev->dev, "incorrect phy mode\n");
+ err = phy_mode;
+ goto err_free_netdev;
+ }
+
+ if (of_property_read_u32(port_node, "port-id", &id)) {
+ err = -EINVAL;
+ dev_err(&pdev->dev, "missing port-id value\n");
+ goto err_free_netdev;
+ }
+
+ dev->tx_queue_len = MVPP2_MAX_TXD;
+ dev->watchdog_timeo = 5 * HZ;
+ dev->netdev_ops = &mvpp2_netdev_ops;
+ dev->ethtool_ops = &mvpp2_eth_tool_ops;
+
+ port = netdev_priv(dev);
+
+ port->irq = irq_of_parse_and_map(port_node, 0);
+ if (port->irq <= 0) {
+ err = -EINVAL;
+ goto err_free_netdev;
+ }
+
+ if (of_property_read_bool(port_node, "marvell,loopback"))
+ port->flags |= MVPP2_F_LOOPBACK;
+
+ port->priv = priv;
+ port->id = id;
+ port->first_rxq = *next_first_rxq;
+ port->phy_node = phy_node;
+ port->phy_interface = phy_mode;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM,
+ priv_common_regs_num + id);
+ port->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(port->base)) {
+ err = PTR_ERR(port->base);
+ goto err_free_irq;
+ }
+
+ /* Alloc per-cpu stats */
+ port->stats = netdev_alloc_pcpu_stats(struct mvpp2_pcpu_stats);
+ if (!port->stats) {
+ err = -ENOMEM;
+ goto err_free_irq;
+ }
+
+ dt_mac_addr = of_get_mac_address(port_node);
+ if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
+ mac_from = "device tree";
+ ether_addr_copy(dev->dev_addr, dt_mac_addr);
+ } else {
+ mvpp2_get_mac_address(port, hw_mac_addr);
+ if (is_valid_ether_addr(hw_mac_addr)) {
+ mac_from = "hardware";
+ ether_addr_copy(dev->dev_addr, hw_mac_addr);
+ } else {
+ mac_from = "random";
+ eth_hw_addr_random(dev);
+ }
+ }
+
+ port->tx_ring_size = MVPP2_MAX_TXD;
+ port->rx_ring_size = MVPP2_MAX_RXD;
+ port->dev = dev;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ err = mvpp2_port_init(port);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to init port %d\n", id);
+ goto err_free_stats;
+ }
+ mvpp2_port_power_up(port);
+
+ netif_napi_add(dev, &port->napi, mvpp2_poll, NAPI_POLL_WEIGHT);
+ features = NETIF_F_SG | NETIF_F_IP_CSUM;
+ dev->features = features | NETIF_F_RXCSUM;
+ dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
+ dev->vlan_features |= features;
+
+ err = register_netdev(dev);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to register netdev\n");
+ goto err_free_txq_pcpu;
+ }
+ netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
+
+ /* Increment the first Rx queue number to be used by the next port */
+ *next_first_rxq += rxq_number;
+ priv->port_list[id] = port;
+ return 0;
+
+err_free_txq_pcpu:
+ for (i = 0; i < txq_number; i++)
+ free_percpu(port->txqs[i]->pcpu);
+err_free_stats:
+ free_percpu(port->stats);
+err_free_irq:
+ irq_dispose_mapping(port->irq);
+err_free_netdev:
+ free_netdev(dev);
+ return err;
+}
+
+/* Ports removal routine */
+static void mvpp2_port_remove(struct mvpp2_port *port)
+{
+ int i;
+
+ unregister_netdev(port->dev);
+ free_percpu(port->stats);
+ for (i = 0; i < txq_number; i++)
+ free_percpu(port->txqs[i]->pcpu);
+ irq_dispose_mapping(port->irq);
+ free_netdev(port->dev);
+}
+
+/* Initialize decoding windows */
+static void mvpp2_conf_mbus_windows(const struct mbus_dram_target_info *dram,
+ struct mvpp2 *priv)
+{
+ u32 win_enable;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ mvpp2_write(priv, MVPP2_WIN_BASE(i), 0);
+ mvpp2_write(priv, MVPP2_WIN_SIZE(i), 0);
+
+ if (i < 4)
+ mvpp2_write(priv, MVPP2_WIN_REMAP(i), 0);
+ }
+
+ win_enable = 0;
+
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ mvpp2_write(priv, MVPP2_WIN_BASE(i),
+ (cs->base & 0xffff0000) | (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id);
+
+ mvpp2_write(priv, MVPP2_WIN_SIZE(i),
+ (cs->size - 1) & 0xffff0000);
+
+ win_enable |= (1 << i);
+ }
+
+ mvpp2_write(priv, MVPP2_BASE_ADDR_ENABLE, win_enable);
+}
+
+/* Initialize Rx FIFO's */
+static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
+{
+ int port;
+
+ for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+ mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+ MVPP2_RX_FIFO_PORT_DATA_SIZE);
+ mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+ MVPP2_RX_FIFO_PORT_ATTR_SIZE);
+ }
+
+ mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
+ MVPP2_RX_FIFO_PORT_MIN_PKT);
+ mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
+}
+
+/* Initialize network controller common part HW */
+static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+{
+ const struct mbus_dram_target_info *dram_target_info;
+ int err, i;
+ u32 val;
+
+ /* Checks for hardware constraints */
+ if (rxq_number % 4 || (rxq_number > MVPP2_MAX_RXQ) ||
+ (txq_number > MVPP2_MAX_TXQ)) {
+ dev_err(&pdev->dev, "invalid queue size parameter\n");
+ return -EINVAL;
+ }
+
+ /* MBUS windows configuration */
+ dram_target_info = mv_mbus_dram_info();
+ if (dram_target_info)
+ mvpp2_conf_mbus_windows(dram_target_info, priv);
+
+ /* Disable HW PHY polling */
+ val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+ val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
+ writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+
+ /* Allocate and initialize aggregated TXQs */
+ priv->aggr_txqs = devm_kcalloc(&pdev->dev, num_present_cpus(),
+ sizeof(struct mvpp2_tx_queue),
+ GFP_KERNEL);
+ if (!priv->aggr_txqs)
+ return -ENOMEM;
+
+ for_each_present_cpu(i) {
+ priv->aggr_txqs[i].id = i;
+ priv->aggr_txqs[i].size = MVPP2_AGGR_TXQ_SIZE;
+ err = mvpp2_aggr_txq_init(pdev, &priv->aggr_txqs[i],
+ MVPP2_AGGR_TXQ_SIZE, i, priv);
+ if (err < 0)
+ return err;
+ }
+
+ /* Rx Fifo Init */
+ mvpp2_rx_fifo_init(priv);
+
+ /* Reset Rx queue group interrupt configuration */
+ for (i = 0; i < MVPP2_MAX_PORTS; i++)
+ mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(i), rxq_number);
+
+ writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+ priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
+
+ /* Allow cache snoop when transmiting packets */
+ mvpp2_write(priv, MVPP2_TX_SNOOP_REG, 0x1);
+
+ /* Buffer Manager initialization */
+ err = mvpp2_bm_init(pdev, priv);
+ if (err < 0)
+ return err;
+
+ /* Parser default initialization */
+ err = mvpp2_prs_default_init(pdev, priv);
+ if (err < 0)
+ return err;
+
+ /* Classifier default initialization */
+ mvpp2_cls_init(priv);
+
+ return 0;
+}
+
+static int mvpp2_probe(struct platform_device *pdev)
+{
+ struct device_node *dn = pdev->dev.of_node;
+ struct device_node *port_node;
+ struct mvpp2 *priv;
+ struct resource *res;
+ int port_count, first_rxq;
+ int err;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct mvpp2), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->lms_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->lms_base))
+ return PTR_ERR(priv->lms_base);
+
+ priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
+ if (IS_ERR(priv->pp_clk))
+ return PTR_ERR(priv->pp_clk);
+ err = clk_prepare_enable(priv->pp_clk);
+ if (err < 0)
+ return err;
+
+ priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
+ if (IS_ERR(priv->gop_clk)) {
+ err = PTR_ERR(priv->gop_clk);
+ goto err_pp_clk;
+ }
+ err = clk_prepare_enable(priv->gop_clk);
+ if (err < 0)
+ goto err_pp_clk;
+
+ /* Get system's tclk rate */
+ priv->tclk = clk_get_rate(priv->pp_clk);
+
+ /* Initialize network controller */
+ err = mvpp2_init(pdev, priv);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to initialize controller\n");
+ goto err_gop_clk;
+ }
+
+ port_count = of_get_available_child_count(dn);
+ if (port_count == 0) {
+ dev_err(&pdev->dev, "no ports enabled\n");
+ err = -ENODEV;
+ goto err_gop_clk;
+ }
+
+ priv->port_list = devm_kcalloc(&pdev->dev, port_count,
+ sizeof(struct mvpp2_port *),
+ GFP_KERNEL);
+ if (!priv->port_list) {
+ err = -ENOMEM;
+ goto err_gop_clk;
+ }
+
+ /* Initialize ports */
+ first_rxq = 0;
+ for_each_available_child_of_node(dn, port_node) {
+ err = mvpp2_port_probe(pdev, port_node, priv, &first_rxq);
+ if (err < 0)
+ goto err_gop_clk;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ return 0;
+
+err_gop_clk:
+ clk_disable_unprepare(priv->gop_clk);
+err_pp_clk:
+ clk_disable_unprepare(priv->pp_clk);
+ return err;
+}
+
+static int mvpp2_remove(struct platform_device *pdev)
+{
+ struct mvpp2 *priv = platform_get_drvdata(pdev);
+ struct device_node *dn = pdev->dev.of_node;
+ struct device_node *port_node;
+ int i = 0;
+
+ for_each_available_child_of_node(dn, port_node) {
+ if (priv->port_list[i])
+ mvpp2_port_remove(priv->port_list[i]);
+ i++;
+ }
+
+ for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+ struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
+
+ mvpp2_bm_pool_destroy(pdev, priv, bm_pool);
+ }
+
+ for_each_present_cpu(i) {
+ struct mvpp2_tx_queue *aggr_txq = &priv->aggr_txqs[i];
+
+ dma_free_coherent(&pdev->dev,
+ MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+ aggr_txq->descs,
+ aggr_txq->descs_phys);
+ }
+
+ clk_disable_unprepare(priv->pp_clk);
+ clk_disable_unprepare(priv->gop_clk);
+
+ return 0;
+}
+
+static const struct of_device_id mvpp2_match[] = {
+ { .compatible = "marvell,armada-375-pp2" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mvpp2_match);
+
+static struct platform_driver mvpp2_driver = {
+ .probe = mvpp2_probe,
+ .remove = mvpp2_remove,
+ .driver = {
+ .name = MVPP2_DRIVER_NAME,
+ .of_match_table = mvpp2_match,
+ },
+};
+
+module_platform_driver(mvpp2_driver);
+
+MODULE_DESCRIPTION("Marvell PPv2 Ethernet Driver - www.marvell.com");
+MODULE_AUTHOR("Marcin Wojtas <mw@semihalf.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index e912b6887d40..24b242277ea1 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -82,7 +82,7 @@ static int debug = -1; /* defaults above */
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
-static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = {
+static const struct pci_device_id skge_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */
{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */
#ifdef CONFIG_SKGE_GENESIS
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 69693384b58c..dba48a5ce7ab 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -101,7 +101,7 @@ static int legacy_pme = 0;
module_param(legacy_pme, int, 0);
MODULE_PARM_DESC(legacy_pme, "Legacy power management");
-static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
+static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E01) }, /* SK-9E21M */
@@ -1622,11 +1622,10 @@ static int sky2_alloc_buffers(struct sky2_port *sky2)
if (!sky2->tx_ring)
goto nomem;
- sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
- &sky2->rx_le_map);
+ sky2->rx_le = pci_zalloc_consistent(hw->pdev, RX_LE_BYTES,
+ &sky2->rx_le_map);
if (!sky2->rx_le)
goto nomem;
- memset(sky2->rx_le, 0, RX_LE_BYTES);
sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct rx_ring_info),
GFP_KERNEL);
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 5d940a26055c..65a4a0f88ea0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1311,6 +1311,15 @@ static struct mlx4_cmd_info cmd_info[] = {
.wrapper = mlx4_MAD_IFC_wrapper
},
{
+ .opcode = MLX4_CMD_MAD_DEMUX,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .encode_slave_id = false,
+ .verify = NULL,
+ .wrapper = mlx4_CMD_EPERM_wrapper
+ },
+ {
.opcode = MLX4_CMD_QUERY_IF_STAT,
.has_inbox = false,
.has_outbox = true,
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 68d763d2d030..e22f24f784fc 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -98,6 +98,10 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
drvinfo->eedump_len = 0;
}
+static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
+ "blueflame",
+};
+
static const char main_strings[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@@ -235,6 +239,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
+ case ETH_SS_PRIV_FLAGS:
+ return ARRAY_SIZE(mlx4_en_priv_flags);
default:
return -EOPNOTSUPP;
}
@@ -358,6 +364,12 @@ static void mlx4_en_get_strings(struct net_device *dev,
#endif
}
break;
+ case ETH_SS_PRIV_FLAGS:
+ for (i = 0; i < ARRAY_SIZE(mlx4_en_priv_flags); i++)
+ strcpy(data + i * ETH_GSTRING_LEN,
+ mlx4_en_priv_flags[i]);
+ break;
+
}
}
@@ -1209,6 +1221,49 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
return ret;
}
+static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+ bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+ int i;
+
+ if (bf_enabled_new == bf_enabled_old)
+ return 0; /* Nothing to do */
+
+ if (bf_enabled_new) {
+ bool bf_supported = true;
+
+ for (i = 0; i < priv->tx_ring_num; i++)
+ bf_supported &= priv->tx_ring[i]->bf_alloced;
+
+ if (!bf_supported) {
+ en_err(priv, "BlueFlame is not supported\n");
+ return -EINVAL;
+ }
+
+ priv->pflags |= MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+ } else {
+ priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+ }
+
+ for (i = 0; i < priv->tx_ring_num; i++)
+ priv->tx_ring[i]->bf_enabled = bf_enabled_new;
+
+ en_info(priv, "BlueFlame %s\n",
+ bf_enabled_new ? "Enabled" : "Disabled");
+
+ return 0;
+}
+
+static u32 mlx4_en_get_priv_flags(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ return priv->pflags;
+}
+
+
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
@@ -1236,6 +1291,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_channels = mlx4_en_get_channels,
.set_channels = mlx4_en_set_channels,
.get_ts_info = mlx4_en_get_ts_info,
+ .set_priv_flags = mlx4_en_set_priv_flags,
+ .get_priv_flags = mlx4_en_get_priv_flags,
};
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index f953c1d7eae6..3626fdf4cb5d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -129,8 +129,10 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
int i;
params->udp_rss = udp_rss;
- params->num_tx_rings_p_up = min_t(int, num_online_cpus(),
- MLX4_EN_MAX_TX_RING_P_UP);
+ params->num_tx_rings_p_up = mlx4_low_memory_profile() ?
+ MLX4_EN_MIN_TX_RING_P_UP :
+ min_t(int, num_online_cpus(), MLX4_EN_MAX_TX_RING_P_UP);
+
if (params->udp_rss && !(mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
mlx4_warn(mdev, "UDP RSS is not supported on this device\n");
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 7345c43b019e..bb536aa613f4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -644,6 +644,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
goto alloc_err;
}
memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
+ memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
entry->reg_id = reg_id;
hlist_add_head_rcu(&entry->hlist,
@@ -760,21 +761,22 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
return __mlx4_replace_mac(dev, priv->port, qpn, new_mac_u64);
}
-static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
+static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv,
+ unsigned char new_mac[ETH_ALEN + 2])
{
int err = 0;
if (priv->port_up) {
/* Remove old MAC and insert the new one */
err = mlx4_en_replace_mac(priv, priv->base_qpn,
- priv->dev->dev_addr, priv->prev_mac);
+ new_mac, priv->current_mac);
if (err)
en_err(priv, "Failed changing HW MAC address\n");
} else
en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
- memcpy(priv->prev_mac, priv->dev->dev_addr,
- sizeof(priv->prev_mac));
+ if (!err)
+ memcpy(priv->current_mac, new_mac, sizeof(priv->current_mac));
return err;
}
@@ -784,14 +786,17 @@ static int mlx4_en_set_mac(struct net_device *dev, void *addr)
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
struct sockaddr *saddr = addr;
+ unsigned char new_mac[ETH_ALEN + 2];
int err;
if (!is_valid_ether_addr(saddr->sa_data))
return -EADDRNOTAVAIL;
mutex_lock(&mdev->state_lock);
- memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
- err = mlx4_en_do_set_mac(priv);
+ memcpy(new_mac, saddr->sa_data, ETH_ALEN);
+ err = mlx4_en_do_set_mac(priv, new_mac);
+ if (!err)
+ memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
mutex_unlock(&mdev->state_lock);
return err;
@@ -940,11 +945,6 @@ static void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv,
0, MLX4_MCAST_DISABLE);
if (err)
en_err(priv, "Failed disabling multicast filter\n");
-
- /* Disable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
- if (err)
- en_err(priv, "Failed disabling VLAN filter\n");
}
}
@@ -993,11 +993,6 @@ static void mlx4_en_clear_promisc_mode(struct mlx4_en_priv *priv,
en_err(priv, "Failed disabling promiscuous mode\n");
break;
}
-
- /* Enable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
- if (err)
- en_err(priv, "Failed enabling VLAN filter\n");
}
static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
@@ -1166,7 +1161,8 @@ static void mlx4_en_do_uc_filter(struct mlx4_en_priv *priv,
}
/* MAC address of the port is not in uc list */
- if (ether_addr_equal_64bits(entry->mac, dev->dev_addr))
+ if (ether_addr_equal_64bits(entry->mac,
+ priv->current_mac))
found = true;
if (!found) {
@@ -1476,7 +1472,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
}
if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
- mlx4_en_do_set_mac(priv);
+ mlx4_en_do_set_mac(priv, priv->current_mac);
mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
}
mutex_unlock(&mdev->state_lock);
@@ -2469,6 +2465,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
priv->port = port;
priv->port_up = false;
priv->flags = prof->flags;
+ priv->pflags = MLX4_EN_PRIV_FLAGS_BLUEFLAME;
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
MLX4_WQE_CTRL_SOLICITED);
priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
@@ -2535,7 +2532,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
}
}
- memcpy(priv->prev_mac, dev->dev_addr, sizeof(priv->prev_mac));
+ memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac));
priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 5535862f27cc..9c909d23f14c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -335,8 +335,9 @@ void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev)
dev->caps.comp_pool/
dev->caps.num_ports) - 1;
- num_rx_rings = min_t(int, num_of_eqs,
- netif_get_num_default_rss_queues());
+ num_rx_rings = mlx4_low_memory_profile() ? MIN_RX_RINGS :
+ min_t(int, num_of_eqs,
+ netif_get_num_default_rss_queues());
mdev->profile.prof[i].rx_ring_num =
rounddown_pow_of_two(num_rx_rings);
}
@@ -933,7 +934,7 @@ static const int frag_sizes[] = {
void mlx4_en_calc_rx_buf(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN + ETH_LLC_SNAP_SIZE;
+ int eff_mtu = dev->mtu + ETH_HLEN + VLAN_HLEN;
int buf_size = 0;
int i = 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
index 03e5f6ac67e7..49d5afc7cfb8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
@@ -159,7 +159,8 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
if (priv->mdev->dev->caps.flags &
MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
buf[3] = mlx4_en_test_registers(priv);
- buf[4] = mlx4_en_test_loopback(priv);
+ if (priv->port_up)
+ buf[4] = mlx4_en_test_loopback(priv);
}
if (carrier_ok)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 5045bab59633..dae3da6d8dd0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -126,8 +126,13 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
ring->bf.uar = &mdev->priv_uar;
ring->bf.uar->map = mdev->uar_map;
ring->bf_enabled = false;
- } else
- ring->bf_enabled = true;
+ ring->bf_alloced = false;
+ priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
+ } else {
+ ring->bf_alloced = true;
+ ring->bf_enabled = !!(priv->pflags &
+ MLX4_EN_PRIV_FLAGS_BLUEFLAME);
+ }
ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
ring->queue_index = queue_index;
@@ -161,7 +166,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring = *pring;
en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
- if (ring->bf_enabled)
+ if (ring->bf_alloced)
mlx4_bf_free(mdev->dev, &ring->bf);
mlx4_qp_remove(mdev->dev, &ring->qp);
mlx4_qp_free(mdev->dev, &ring->qp);
@@ -195,7 +200,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
ring->cqn, user_prio, &ring->context);
- if (ring->bf_enabled)
+ if (ring->bf_alloced)
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 688e1eabab29..494753e44ae3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -136,7 +136,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
[7] = "FSM (MAC anti-spoofing) support",
[8] = "Dynamic QP updates support",
[9] = "Device managed flow steering IPoIB support",
- [10] = "TCP/IP offloads/flow-steering for VXLAN support"
+ [10] = "TCP/IP offloads/flow-steering for VXLAN support",
+ [11] = "MAD DEMUX (Secure-Host) support"
};
int i;
@@ -571,6 +572,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
#define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d
#define QUERY_DEV_CAP_VXLAN 0x9e
+#define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0
dev_cap->flags2 = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -748,6 +750,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(dev_cap->max_counters, outbox,
QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
+ MLX4_GET(field32, outbox,
+ QUERY_DEV_CAP_MAD_DEMUX_OFFSET);
+ if (field32 & (1 << 0))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX;
+
MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
if (field32 & (1 << 16))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
@@ -2016,3 +2023,85 @@ void mlx4_opreq_action(struct work_struct *work)
out:
mlx4_free_cmd_mailbox(dev, mailbox);
}
+
+static int mlx4_check_smp_firewall_active(struct mlx4_dev *dev,
+ struct mlx4_cmd_mailbox *mailbox)
+{
+#define MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET 0x10
+#define MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET 0x20
+#define MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET 0x40
+#define MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET 0x70
+
+ u32 set_attr_mask, getresp_attr_mask;
+ u32 trap_attr_mask, traprepress_attr_mask;
+
+ MLX4_GET(set_attr_mask, mailbox->buf,
+ MLX4_CMD_MAD_DEMUX_SET_ATTR_OFFSET);
+ mlx4_dbg(dev, "SMP firewall set_attribute_mask = 0x%x\n",
+ set_attr_mask);
+
+ MLX4_GET(getresp_attr_mask, mailbox->buf,
+ MLX4_CMD_MAD_DEMUX_GETRESP_ATTR_OFFSET);
+ mlx4_dbg(dev, "SMP firewall getresp_attribute_mask = 0x%x\n",
+ getresp_attr_mask);
+
+ MLX4_GET(trap_attr_mask, mailbox->buf,
+ MLX4_CMD_MAD_DEMUX_TRAP_ATTR_OFFSET);
+ mlx4_dbg(dev, "SMP firewall trap_attribute_mask = 0x%x\n",
+ trap_attr_mask);
+
+ MLX4_GET(traprepress_attr_mask, mailbox->buf,
+ MLX4_CMD_MAD_DEMUX_TRAP_REPRESS_ATTR_OFFSET);
+ mlx4_dbg(dev, "SMP firewall traprepress_attribute_mask = 0x%x\n",
+ traprepress_attr_mask);
+
+ if (set_attr_mask && getresp_attr_mask && trap_attr_mask &&
+ traprepress_attr_mask)
+ return 1;
+
+ return 0;
+}
+
+int mlx4_config_mad_demux(struct mlx4_dev *dev)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ int secure_host_active;
+ int err;
+
+ /* Check if mad_demux is supported */
+ if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_MAD_DEMUX))
+ return 0;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox)) {
+ mlx4_warn(dev, "Failed to allocate mailbox for cmd MAD_DEMUX");
+ return -ENOMEM;
+ }
+
+ /* Query mad_demux to find out which MADs are handled by internal sma */
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, 0x01 /* subn mgmt class */,
+ MLX4_CMD_MAD_DEMUX_QUERY_RESTR, MLX4_CMD_MAD_DEMUX,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+ if (err) {
+ mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: query restrictions failed (%d)\n",
+ err);
+ goto out;
+ }
+
+ secure_host_active = mlx4_check_smp_firewall_active(dev, mailbox);
+
+ /* Config mad_demux to handle all MADs returned by the query above */
+ err = mlx4_cmd(dev, mailbox->dma, 0x01 /* subn mgmt class */,
+ MLX4_CMD_MAD_DEMUX_CONFIG, MLX4_CMD_MAD_DEMUX,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+ if (err) {
+ mlx4_warn(dev, "MLX4_CMD_MAD_DEMUX: configure failed (%d)\n", err);
+ goto out;
+ }
+
+ if (secure_host_active)
+ mlx4_warn(dev, "HCA operating in secure-host mode. SMP firewall activated.\n");
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 82ab427290c3..7e2d5d57c598 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -120,6 +120,16 @@ static struct mlx4_profile default_profile = {
.num_mtt = 1 << 20, /* It is really num mtt segements */
};
+static struct mlx4_profile low_mem_profile = {
+ .num_qp = 1 << 17,
+ .num_srq = 1 << 6,
+ .rdmarc_per_qp = 1 << 4,
+ .num_cq = 1 << 8,
+ .num_mcg = 1 << 8,
+ .num_mpt = 1 << 9,
+ .num_mtt = 1 << 7,
+};
+
static int log_num_mac = 7;
module_param_named(log_num_mac, log_num_mac, int, 0444);
MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
@@ -129,6 +139,8 @@ module_param_named(log_num_vlan, log_num_vlan, int, 0444);
MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
/* Log2 max number of VLANs per ETH port (0-7) */
#define MLX4_LOG_NUM_VLANS 7
+#define MLX4_MIN_LOG_NUM_VLANS 0
+#define MLX4_MIN_LOG_NUM_MAC 1
static bool use_prio;
module_param_named(use_prio, use_prio, bool, 0444);
@@ -287,8 +299,13 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
if (mlx4_is_mfunc(dev))
dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
- dev->caps.log_num_macs = log_num_mac;
- dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
+ if (mlx4_low_memory_profile()) {
+ dev->caps.log_num_macs = MLX4_MIN_LOG_NUM_MAC;
+ dev->caps.log_num_vlans = MLX4_MIN_LOG_NUM_VLANS;
+ } else {
+ dev->caps.log_num_macs = log_num_mac;
+ dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
+ }
for (i = 1; i <= dev->caps.num_ports; ++i) {
dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE;
@@ -1587,7 +1604,12 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
if (mlx4_is_master(dev))
mlx4_parav_master_pf_caps(dev);
- profile = default_profile;
+ if (mlx4_low_memory_profile()) {
+ mlx4_info(dev, "Running from within kdump kernel. Using low memory profile\n");
+ profile = low_mem_profile;
+ } else {
+ profile = default_profile;
+ }
if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED)
profile.num_mcg = MLX4_FS_NUM_MCG;
@@ -1831,6 +1853,11 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
mlx4_err(dev, "Failed to initialize multicast group table, aborting\n");
goto err_mr_table_free;
}
+ err = mlx4_config_mad_demux(dev);
+ if (err) {
+ mlx4_err(dev, "Failed in config_mad_demux, aborting\n");
+ goto err_mcg_table_free;
+ }
}
err = mlx4_init_eq_table(dev);
@@ -2705,7 +2732,7 @@ int mlx4_restart_one(struct pci_dev *pdev)
return __mlx4_init_one(pdev, pci_dev_data);
}
-static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
+static const struct pci_device_id mlx4_pci_table[] = {
/* MT25408 "Hermon" SDR */
{ PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT },
/* MT25408 "Hermon" DDR */
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index 4c36def8e10f..d80e7a6fac74 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -270,7 +270,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
* we need to add it as a duplicate to this entry
* for future references */
list_for_each_entry(dqp, &entry->duplicates, list) {
- if (qpn == pqp->qpn)
+ if (qpn == dqp->qpn)
return 0; /* qp is already duplicated */
}
@@ -324,24 +324,22 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
return true;
}
-/* I a steering entry contains only promisc QPs, it can be removed. */
-static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
- enum mlx4_steer_type steer,
- unsigned int index, u32 tqpn)
+/* Returns true if all the QPs != tqpn contained in this entry
+ * are Promisc QPs. Returns false otherwise.
+ */
+static bool promisc_steering_entry(struct mlx4_dev *dev, u8 port,
+ enum mlx4_steer_type steer,
+ unsigned int index, u32 tqpn,
+ u32 *members_count)
{
- struct mlx4_steer *s_steer;
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry = NULL, *tmp_entry;
- u32 qpn;
- u32 members_count;
+ u32 m_count;
bool ret = false;
int i;
if (port < 1 || port > dev->caps.num_ports)
- return NULL;
-
- s_steer = &mlx4_priv(dev)->steer[port - 1];
+ return false;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -350,21 +348,61 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
if (mlx4_READ_ENTRY(dev, index, mailbox))
goto out;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (i = 0; i < members_count; i++) {
- qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
+ m_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+ if (members_count)
+ *members_count = m_count;
+
+ for (i = 0; i < m_count; i++) {
+ u32 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
/* the qp is not promisc, the entry can't be removed */
goto out;
}
}
- /* All the qps currently registered for this entry are promiscuous,
+ ret = true;
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return ret;
+}
+
+/* IF a steering entry contains only promisc QPs, it can be removed. */
+static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
+ enum mlx4_steer_type steer,
+ unsigned int index, u32 tqpn)
+{
+ struct mlx4_steer *s_steer;
+ struct mlx4_steer_index *entry = NULL, *tmp_entry;
+ u32 members_count;
+ bool ret = false;
+
+ if (port < 1 || port > dev->caps.num_ports)
+ return NULL;
+
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
+
+ if (!promisc_steering_entry(dev, port, steer, index,
+ tqpn, &members_count))
+ goto out;
+
+ /* All the qps currently registered for this entry are promiscuous,
* Checking for duplicates */
ret = true;
list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
if (entry->index == index) {
- if (list_empty(&entry->duplicates)) {
+ if (list_empty(&entry->duplicates) ||
+ members_count == 1) {
+ struct mlx4_promisc_qp *pqp, *tmp_pqp;
+ /* If there is only 1 entry in duplicates then
+ * this is the QP we want to delete, going over
+ * the list and deleting the entry.
+ */
list_del(&entry->list);
+ list_for_each_entry_safe(pqp, tmp_pqp,
+ &entry->duplicates,
+ list) {
+ list_del(&pqp->list);
+ kfree(pqp);
+ }
kfree(entry);
} else {
/* This entry contains duplicates so it shouldn't be removed */
@@ -375,7 +413,6 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
}
out:
- mlx4_free_cmd_mailbox(dev, mailbox);
return ret;
}
@@ -421,42 +458,57 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
}
mgm = mailbox->buf;
- /* the promisc qp needs to be added for each one of the steering
- * entries, if it already exists, needs to be added as a duplicate
- * for this entry */
- list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
+ if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+ /* The promisc QP needs to be added for each one of the steering
+ * entries. If it already exists, needs to be added as
+ * a duplicate for this entry.
+ */
+ list_for_each_entry(entry,
+ &s_steer->steer_entries[steer],
+ list) {
+ err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+ if (err)
+ goto out_mailbox;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- prot = be32_to_cpu(mgm->members_count) >> 30;
- found = false;
- for (i = 0; i < members_count; i++) {
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
- /* Entry already exists, add to duplicates */
- dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
- if (!dqp) {
+ members_count = be32_to_cpu(mgm->members_count) &
+ 0xffffff;
+ prot = be32_to_cpu(mgm->members_count) >> 30;
+ found = false;
+ for (i = 0; i < members_count; i++) {
+ if ((be32_to_cpu(mgm->qp[i]) &
+ MGM_QPN_MASK) == qpn) {
+ /* Entry already exists.
+ * Add to duplicates.
+ */
+ dqp = kmalloc(sizeof(*dqp), GFP_KERNEL);
+ if (!dqp) {
+ err = -ENOMEM;
+ goto out_mailbox;
+ }
+ dqp->qpn = qpn;
+ list_add_tail(&dqp->list,
+ &entry->duplicates);
+ found = true;
+ }
+ }
+ if (!found) {
+ /* Need to add the qpn to mgm */
+ if (members_count ==
+ dev->caps.num_qp_per_mgm) {
+ /* entry is full */
err = -ENOMEM;
goto out_mailbox;
}
- dqp->qpn = qpn;
- list_add_tail(&dqp->list, &entry->duplicates);
- found = true;
- }
- }
- if (!found) {
- /* Need to add the qpn to mgm */
- if (members_count == dev->caps.num_qp_per_mgm) {
- /* entry is full */
- err = -ENOMEM;
- goto out_mailbox;
+ mgm->qp[members_count++] =
+ cpu_to_be32(qpn & MGM_QPN_MASK);
+ mgm->members_count =
+ cpu_to_be32(members_count |
+ (prot << 30));
+ err = mlx4_WRITE_ENTRY(dev, entry->index,
+ mailbox);
+ if (err)
+ goto out_mailbox;
}
- mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
- mgm->members_count = cpu_to_be32(members_count | (prot << 30));
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
}
}
@@ -465,8 +517,14 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
/* now need to add all the promisc qps to default entry */
memset(mgm, 0, sizeof *mgm);
members_count = 0;
- list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
+ list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) {
+ if (members_count == dev->caps.num_qp_per_mgm) {
+ /* entry is full */
+ err = -ENOMEM;
+ goto out_list;
+ }
mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
+ }
mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
@@ -495,13 +553,13 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
struct mlx4_steer *s_steer;
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry;
+ struct mlx4_steer_index *entry, *tmp_entry;
struct mlx4_promisc_qp *pqp;
struct mlx4_promisc_qp *dqp;
u32 members_count;
bool found;
bool back_to_list = false;
- int loc, i;
+ int i;
int err;
if (port < 1 || port > dev->caps.num_ports)
@@ -538,39 +596,73 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
if (err)
goto out_mailbox;
- /* remove the qp from all the steering entries*/
- list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
- found = false;
- list_for_each_entry(dqp, &entry->duplicates, list) {
- if (dqp->qpn == qpn) {
- found = true;
- break;
+ if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+ /* Remove the QP from all the steering entries */
+ list_for_each_entry_safe(entry, tmp_entry,
+ &s_steer->steer_entries[steer],
+ list) {
+ found = false;
+ list_for_each_entry(dqp, &entry->duplicates, list) {
+ if (dqp->qpn == qpn) {
+ found = true;
+ break;
+ }
}
- }
- if (found) {
- /* a duplicate, no need to change the mgm,
- * only update the duplicates list */
- list_del(&dqp->list);
- kfree(dqp);
- } else {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (loc = -1, i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
- loc = i;
-
- mgm->members_count = cpu_to_be32(--members_count |
- (MLX4_PROT_ETH << 30));
- mgm->qp[loc] = mgm->qp[i - 1];
- mgm->qp[i - 1] = 0;
+ if (found) {
+ /* A duplicate, no need to change the MGM,
+ * only update the duplicates list
+ */
+ list_del(&dqp->list);
+ kfree(dqp);
+ } else {
+ int loc = -1;
+
+ err = mlx4_READ_ENTRY(dev,
+ entry->index,
+ mailbox);
+ if (err)
+ goto out_mailbox;
+ members_count =
+ be32_to_cpu(mgm->members_count) &
+ 0xffffff;
+ if (!members_count) {
+ mlx4_warn(dev, "QP %06x wasn't found in entry %x mcount=0. deleting entry...\n",
+ qpn, entry->index);
+ list_del(&entry->list);
+ kfree(entry);
+ continue;
+ }
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
+ for (i = 0; i < members_count; ++i)
+ if ((be32_to_cpu(mgm->qp[i]) &
+ MGM_QPN_MASK) == qpn) {
+ loc = i;
+ break;
+ }
+
+ if (loc < 0) {
+ mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
+ qpn, entry->index);
+ err = -EINVAL;
goto out_mailbox;
- }
+ }
+ /* Copy the last QP in this MGM
+ * over removed QP
+ */
+ mgm->qp[loc] = mgm->qp[members_count - 1];
+ mgm->qp[members_count - 1] = 0;
+ mgm->members_count =
+ cpu_to_be32(--members_count |
+ (MLX4_PROT_ETH << 30));
+
+ err = mlx4_WRITE_ENTRY(dev,
+ entry->index,
+ mailbox);
+ if (err)
+ goto out_mailbox;
+ }
+ }
}
out_mailbox:
@@ -1062,7 +1154,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
struct mlx4_mgm *mgm;
u32 members_count;
int prev, index;
- int i, loc;
+ int i, loc = -1;
int err;
u8 port = gid[5];
bool removed_entry = false;
@@ -1085,15 +1177,20 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
goto out;
}
- /* if this pq is also a promisc qp, it shouldn't be removed */
+ /* If this QP is also a promisc QP, it shouldn't be removed only if
+ * at least one none promisc QP is also attached to this MCG
+ */
if (prot == MLX4_PROT_ETH &&
- check_duplicate_entry(dev, port, steer, index, qp->qpn))
- goto out;
+ check_duplicate_entry(dev, port, steer, index, qp->qpn) &&
+ !promisc_steering_entry(dev, port, steer, index, qp->qpn, NULL))
+ goto out;
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (loc = -1, i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
+ for (i = 0; i < members_count; ++i)
+ if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
loc = i;
+ break;
+ }
if (loc == -1) {
mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn);
@@ -1101,15 +1198,15 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
goto out;
}
-
+ /* copy the last QP in this MGM over removed QP */
+ mgm->qp[loc] = mgm->qp[members_count - 1];
+ mgm->qp[members_count - 1] = 0;
mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
- mgm->qp[loc] = mgm->qp[i - 1];
- mgm->qp[i - 1] = 0;
if (prot == MLX4_PROT_ETH)
removed_entry = can_remove_steering_entry(dev, port, steer,
index, qp->qpn);
- if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
+ if (members_count && (prot != MLX4_PROT_ETH || !removed_entry)) {
err = mlx4_WRITE_ENTRY(dev, index, mailbox);
goto out;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index 1d8af7336807..b508c7887ef8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -62,11 +62,6 @@
#define INIT_HCA_TPT_MW_ENABLE (1 << 7)
-#define MLX4_NUM_UP 8
-#define MLX4_NUM_TC 8
-#define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */
-#define MLX4_RATELIMIT_DEFAULT 0xffff
-
struct mlx4_set_port_prio2tc_context {
u8 prio2tc[4];
};
@@ -279,6 +274,8 @@ struct mlx4_icm_table {
#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
#define MLX4_MPT_FLAG_REGION (1 << 8)
+#define MLX4_MPT_PD_MASK (0x1FFFFUL)
+#define MLX4_MPT_PD_VF_MASK (0xFE0000UL)
#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
@@ -1311,5 +1308,6 @@ void mlx4_init_quotas(struct mlx4_dev *dev);
int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port);
/* Returns the VF index of slave */
int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave);
+int mlx4_config_mad_demux(struct mlx4_dev *dev);
#endif /* MLX4_H */
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index d72a5a894fc6..3de41be49425 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -93,6 +93,8 @@
* OS related constants and tunables
*/
+#define MLX4_EN_PRIV_FLAGS_BLUEFLAME 1
+
#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
/* Use the maximum between 16384 and a single page */
@@ -119,6 +121,7 @@ enum {
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_SMALL_PKT_SIZE 64
+#define MLX4_EN_MIN_TX_RING_P_UP 1
#define MLX4_EN_MAX_TX_RING_P_UP 32
#define MLX4_EN_NUM_UP 8
#define MLX4_EN_DEF_TX_RING_SIZE 512
@@ -154,8 +157,6 @@ enum {
#define MLX4_EN_TX_POLL_MODER 16
#define MLX4_EN_TX_POLL_TIMEOUT (HZ / 4)
-#define ETH_LLC_SNAP_SIZE 8
-
#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
#define HEADER_COPY_SIZE (128 - NET_IP_ALIGN)
#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETH_HLEN)
@@ -280,6 +281,7 @@ struct mlx4_en_tx_ring {
unsigned long wake_queue;
struct mlx4_bf bf;
bool bf_enabled;
+ bool bf_alloced;
struct netdev_queue *tx_queue;
int hwtstamp_tx_type;
int inline_thold;
@@ -535,7 +537,7 @@ struct mlx4_en_priv {
int registered;
int allocated;
int stride;
- unsigned char prev_mac[ETH_ALEN + 2];
+ unsigned char current_mac[ETH_ALEN + 2];
int mac_index;
unsigned max_mtu;
int base_qpn;
@@ -594,6 +596,8 @@ struct mlx4_en_priv {
#endif
u64 tunnel_reg_id;
__be16 vxlan_port;
+
+ u32 pflags;
};
enum mlx4_en_wol {
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index 2839abb878a6..7d717eccb7b0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -298,6 +298,131 @@ static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
}
+int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
+ struct mlx4_mpt_entry ***mpt_entry)
+{
+ int err;
+ int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1);
+ struct mlx4_cmd_mailbox *mailbox = NULL;
+
+ /* Make sure that at this point we have single-threaded access only */
+
+ if (mmr->enabled != MLX4_MPT_EN_HW)
+ return -EINVAL;
+
+ err = mlx4_HW2SW_MPT(dev, NULL, key);
+
+ if (err) {
+ mlx4_warn(dev, "HW2SW_MPT failed (%d).", err);
+ mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n");
+ return err;
+ }
+
+ mmr->enabled = MLX4_MPT_EN_SW;
+
+ if (!mlx4_is_mfunc(dev)) {
+ **mpt_entry = mlx4_table_find(
+ &mlx4_priv(dev)->mr_table.dmpt_table,
+ key, NULL);
+ } else {
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR_OR_NULL(mailbox))
+ return PTR_ERR(mailbox);
+
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, key,
+ 0, MLX4_CMD_QUERY_MPT,
+ MLX4_CMD_TIME_CLASS_B,
+ MLX4_CMD_WRAPPED);
+
+ if (err)
+ goto free_mailbox;
+
+ *mpt_entry = (struct mlx4_mpt_entry **)&mailbox->buf;
+ }
+
+ if (!(*mpt_entry) || !(**mpt_entry)) {
+ err = -ENOMEM;
+ goto free_mailbox;
+ }
+
+ return 0;
+
+free_mailbox:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_get_mpt);
+
+int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
+ struct mlx4_mpt_entry **mpt_entry)
+{
+ int err;
+
+ if (!mlx4_is_mfunc(dev)) {
+ /* Make sure any changes to this entry are flushed */
+ wmb();
+
+ *(u8 *)(*mpt_entry) = MLX4_MPT_STATUS_HW;
+
+ /* Make sure the new status is written */
+ wmb();
+
+ err = mlx4_SYNC_TPT(dev);
+ } else {
+ int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1);
+
+ struct mlx4_cmd_mailbox *mailbox =
+ container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,
+ buf);
+
+ err = mlx4_SW2HW_MPT(dev, mailbox, key);
+ }
+
+ mmr->pd = be32_to_cpu((*mpt_entry)->pd_flags) & MLX4_MPT_PD_MASK;
+ if (!err)
+ mmr->enabled = MLX4_MPT_EN_HW;
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_write_mpt);
+
+void mlx4_mr_hw_put_mpt(struct mlx4_dev *dev,
+ struct mlx4_mpt_entry **mpt_entry)
+{
+ if (mlx4_is_mfunc(dev)) {
+ struct mlx4_cmd_mailbox *mailbox =
+ container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,
+ buf);
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ }
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_put_mpt);
+
+int mlx4_mr_hw_change_pd(struct mlx4_dev *dev, struct mlx4_mpt_entry *mpt_entry,
+ u32 pdn)
+{
+ u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags);
+ /* The wrapper function will put the slave's id here */
+ if (mlx4_is_mfunc(dev))
+ pd_flags &= ~MLX4_MPT_PD_VF_MASK;
+ mpt_entry->pd_flags = cpu_to_be32((pd_flags & ~MLX4_MPT_PD_MASK) |
+ (pdn & MLX4_MPT_PD_MASK)
+ | MLX4_MPT_PD_FLAG_EN_INV);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_change_pd);
+
+int mlx4_mr_hw_change_access(struct mlx4_dev *dev,
+ struct mlx4_mpt_entry *mpt_entry,
+ u32 access)
+{
+ u32 flags = (be32_to_cpu(mpt_entry->flags) & ~MLX4_PERM_MASK) |
+ (access & MLX4_PERM_MASK);
+
+ mpt_entry->flags = cpu_to_be32(flags);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_hw_change_access);
+
static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
u64 iova, u64 size, u32 access, int npages,
int page_shift, struct mlx4_mr *mr)
@@ -463,6 +588,41 @@ int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
}
EXPORT_SYMBOL_GPL(mlx4_mr_free);
+void mlx4_mr_rereg_mem_cleanup(struct mlx4_dev *dev, struct mlx4_mr *mr)
+{
+ mlx4_mtt_cleanup(dev, &mr->mtt);
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_rereg_mem_cleanup);
+
+int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr,
+ u64 iova, u64 size, int npages,
+ int page_shift, struct mlx4_mpt_entry *mpt_entry)
+{
+ int err;
+
+ mpt_entry->start = cpu_to_be64(mr->iova);
+ mpt_entry->length = cpu_to_be64(mr->size);
+ mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
+
+ err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
+ if (err)
+ return err;
+
+ if (mr->mtt.order < 0) {
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
+ mpt_entry->mtt_addr = 0;
+ } else {
+ mpt_entry->mtt_addr = cpu_to_be64(mlx4_mtt_addr(dev,
+ &mr->mtt));
+ if (mr->mtt.page_shift == 0)
+ mpt_entry->mtt_sz = cpu_to_be32(1 << mr->mtt.order);
+ }
+ mr->enabled = MLX4_MPT_EN_SW;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mr_rereg_mem_write);
+
int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
{
struct mlx4_cmd_mailbox *mailbox;
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 7ab97174886d..9ba0c1ca10d5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -244,10 +244,16 @@ EXPORT_SYMBOL_GPL(mlx4_get_base_qpn);
void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
{
- struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
- struct mlx4_mac_table *table = &info->mac_table;
+ struct mlx4_port_info *info;
+ struct mlx4_mac_table *table;
int index;
+ if (port < 1 || port > dev->caps.num_ports) {
+ mlx4_warn(dev, "invalid port number (%d), aborting...\n", port);
+ return;
+ }
+ info = &mlx4_priv(dev)->port[port];
+ table = &info->mac_table;
mutex_lock(&table->mutex);
index = find_index(dev, table, mac);
@@ -1051,14 +1057,26 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
for (i = 0; i < MLX4_NUM_TC; i++) {
struct mlx4_port_scheduler_tc_cfg_be *tc = &context->tc[i];
- u16 r = ratelimit && ratelimit[i] ? ratelimit[i] :
- MLX4_RATELIMIT_DEFAULT;
+ u16 r;
+
+ if (ratelimit && ratelimit[i]) {
+ if (ratelimit[i] <= MLX4_MAX_100M_UNITS_VAL) {
+ r = ratelimit[i];
+ tc->max_bw_units =
+ htons(MLX4_RATELIMIT_100M_UNITS);
+ } else {
+ r = ratelimit[i]/10;
+ tc->max_bw_units =
+ htons(MLX4_RATELIMIT_1G_UNITS);
+ }
+ tc->max_bw_value = htons(r);
+ } else {
+ tc->max_bw_value = htons(MLX4_RATELIMIT_DEFAULT);
+ tc->max_bw_units = htons(MLX4_RATELIMIT_1G_UNITS);
+ }
tc->pg = htons(pg[i]);
tc->bw_precentage = htons(tc_tx_bw[i]);
-
- tc->max_bw_units = htons(MLX4_RATELIMIT_UNITS);
- tc->max_bw_value = htons(r);
}
in_mod = MLX4_SET_PORT_SCHEDULER << 8 | port;
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 0efc1368e5a8..1089367fed22 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -2613,12 +2613,34 @@ int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave,
if (err)
return err;
- if (mpt->com.from_state != RES_MPT_HW) {
+ if (mpt->com.from_state == RES_MPT_MAPPED) {
+ /* In order to allow rereg in SRIOV, we need to alter the MPT entry. To do
+ * that, the VF must read the MPT. But since the MPT entry memory is not
+ * in the VF's virtual memory space, it must use QUERY_MPT to obtain the
+ * entry contents. To guarantee that the MPT cannot be changed, the driver
+ * must perform HW2SW_MPT before this query and return the MPT entry to HW
+ * ownership fofollowing the change. The change here allows the VF to
+ * perform QUERY_MPT also when the entry is in SW ownership.
+ */
+ struct mlx4_mpt_entry *mpt_entry = mlx4_table_find(
+ &mlx4_priv(dev)->mr_table.dmpt_table,
+ mpt->key, NULL);
+
+ if (NULL == mpt_entry || NULL == outbox->buf) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memcpy(outbox->buf, mpt_entry, sizeof(*mpt_entry));
+
+ err = 0;
+ } else if (mpt->com.from_state == RES_MPT_HW) {
+ err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+ } else {
err = -EBUSY;
goto out;
}
- err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
out:
put_res(dev, slave, id, RES_MPT);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
index b215742b842f..56779c1c7811 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
@@ -56,7 +56,7 @@ int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, int max_direct,
if (size <= max_direct) {
buf->nbufs = 1;
buf->npages = 1;
- buf->page_shift = get_order(size) + PAGE_SHIFT;
+ buf->page_shift = (u8)get_order(size) + PAGE_SHIFT;
buf->direct.buf = dma_zalloc_coherent(&dev->pdev->dev,
size, &t, GFP_KERNEL);
if (!buf->direct.buf)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 87d1b018a9c3..65a7da69e2ac 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -464,7 +464,7 @@ static void dump_command(struct mlx5_core_dev *dev,
struct mlx5_cmd_msg *msg = input ? ent->in : ent->out;
struct mlx5_cmd_mailbox *next = msg->next;
int data_only;
- int offset = 0;
+ u32 offset = 0;
int dump_len;
data_only = !!(mlx5_core_debug_mask & (1 << MLX5_CMD_DATA));
@@ -548,7 +548,7 @@ static void cmd_work_handler(struct work_struct *work)
lay->status_own = CMD_OWNER_HW;
set_signature(ent, !cmd->checksum_disabled);
dump_command(dev, ent, 1);
- ktime_get_ts(&ent->ts1);
+ ent->ts1 = ktime_get_ns();
/* ring doorbell after the descriptor is valid */
wmb();
@@ -637,7 +637,6 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
{
struct mlx5_cmd *cmd = &dev->cmd;
struct mlx5_cmd_work_ent *ent;
- ktime_t t1, t2, delta;
struct mlx5_cmd_stats *stats;
int err = 0;
s64 ds;
@@ -668,10 +667,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
if (err == -ETIMEDOUT)
goto out;
- t1 = timespec_to_ktime(ent->ts1);
- t2 = timespec_to_ktime(ent->ts2);
- delta = ktime_sub(t2, t1);
- ds = ktime_to_ns(delta);
+ ds = ent->ts2 - ent->ts1;
op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
if (op < ARRAY_SIZE(cmd->stats)) {
stats = &cmd->stats[op];
@@ -1135,7 +1131,6 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
void *context;
int err;
int i;
- ktime_t t1, t2, delta;
s64 ds;
struct mlx5_cmd_stats *stats;
unsigned long flags;
@@ -1149,7 +1144,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
sem = &cmd->pages_sem;
else
sem = &cmd->sem;
- ktime_get_ts(&ent->ts2);
+ ent->ts2 = ktime_get_ns();
memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
dump_command(dev, ent, 0);
if (!ent->ret) {
@@ -1163,10 +1158,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector)
}
free_ent(cmd, ent->idx);
if (ent->callback) {
- t1 = timespec_to_ktime(ent->ts1);
- t2 = timespec_to_ktime(ent->ts2);
- delta = ktime_sub(t2, t1);
- ds = ktime_to_ns(delta);
+ ds = ent->ts2 - ent->ts1;
if (ent->op < ARRAY_SIZE(cmd->stats)) {
stats = &cmd->stats[ent->op];
spin_lock_irqsave(&stats->lock, flags);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 7f39ebcd6ad0..4e8bd0b34bb0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -252,7 +252,9 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
case MLX5_PORT_CHANGE_SUBTYPE_GUID:
case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG:
case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED:
- dev->event(dev, port_subtype_event(eqe->sub_type), &port);
+ if (dev->event)
+ dev->event(dev, port_subtype_event(eqe->sub_type),
+ (unsigned long)port);
break;
default:
mlx5_core_warn(dev, "Port event with unrecognized subtype: port %d, sub_type %d\n",
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mad.c b/drivers/net/ethernet/mellanox/mlx5/core/mad.c
index 18d6fd5dd90b..fd80ecfa7195 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mad.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mad.c
@@ -37,7 +37,7 @@
#include "mlx5_core.h"
int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb,
- u16 opmod, int port)
+ u16 opmod, u8 port)
{
struct mlx5_mad_ifc_mbox_in *in = NULL;
struct mlx5_mad_ifc_mbox_out *out = NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index ee24f132e319..f2716cc1f51d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -58,7 +58,100 @@ int mlx5_core_debug_mask;
module_param_named(debug_mask, mlx5_core_debug_mask, int, 0644);
MODULE_PARM_DESC(debug_mask, "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0");
+#define MLX5_DEFAULT_PROF 2
+static int prof_sel = MLX5_DEFAULT_PROF;
+module_param_named(prof_sel, prof_sel, int, 0444);
+MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2");
+
struct workqueue_struct *mlx5_core_wq;
+static LIST_HEAD(intf_list);
+static LIST_HEAD(dev_list);
+static DEFINE_MUTEX(intf_mutex);
+
+struct mlx5_device_context {
+ struct list_head list;
+ struct mlx5_interface *intf;
+ void *context;
+};
+
+static struct mlx5_profile profile[] = {
+ [0] = {
+ .mask = 0,
+ },
+ [1] = {
+ .mask = MLX5_PROF_MASK_QP_SIZE,
+ .log_max_qp = 12,
+ },
+ [2] = {
+ .mask = MLX5_PROF_MASK_QP_SIZE |
+ MLX5_PROF_MASK_MR_CACHE,
+ .log_max_qp = 17,
+ .mr_cache[0] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[1] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[2] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[3] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[4] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[5] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[6] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[7] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[8] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[9] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[10] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[11] = {
+ .size = 500,
+ .limit = 250
+ },
+ .mr_cache[12] = {
+ .size = 64,
+ .limit = 32
+ },
+ .mr_cache[13] = {
+ .size = 32,
+ .limit = 16
+ },
+ .mr_cache[14] = {
+ .size = 16,
+ .limit = 8
+ },
+ .mr_cache[15] = {
+ .size = 8,
+ .limit = 4
+ },
+ },
+};
static int set_dma_caps(struct pci_dev *pdev)
{
@@ -218,7 +311,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
copy_rw_fields(&set_ctx->hca_cap, &query_out->hca_cap);
- if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
+ if (dev->profile && dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp;
flags = be64_to_cpu(query_out->hca_cap.flags);
@@ -299,7 +392,7 @@ static int mlx5_core_disable_hca(struct mlx5_core_dev *dev)
return 0;
}
-int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
+static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
{
struct mlx5_priv *priv = &dev->priv;
int err;
@@ -489,7 +582,7 @@ err_dbg:
}
EXPORT_SYMBOL(mlx5_dev_init);
-void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
+static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
@@ -516,7 +609,190 @@ void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
pci_disable_device(dev->pdev);
debugfs_remove(priv->dbg_root);
}
-EXPORT_SYMBOL(mlx5_dev_cleanup);
+
+static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+ struct mlx5_device_context *dev_ctx;
+ struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+ dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);
+ if (!dev_ctx) {
+ pr_warn("mlx5_add_device: alloc context failed\n");
+ return;
+ }
+
+ dev_ctx->intf = intf;
+ dev_ctx->context = intf->add(dev);
+
+ if (dev_ctx->context) {
+ spin_lock_irq(&priv->ctx_lock);
+ list_add_tail(&dev_ctx->list, &priv->ctx_list);
+ spin_unlock_irq(&priv->ctx_lock);
+ } else {
+ kfree(dev_ctx);
+ }
+}
+
+static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
+{
+ struct mlx5_device_context *dev_ctx;
+ struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
+
+ list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+ if (dev_ctx->intf == intf) {
+ spin_lock_irq(&priv->ctx_lock);
+ list_del(&dev_ctx->list);
+ spin_unlock_irq(&priv->ctx_lock);
+
+ intf->remove(dev, dev_ctx->context);
+ kfree(dev_ctx);
+ return;
+ }
+}
+static int mlx5_register_device(struct mlx5_core_dev *dev)
+{
+ struct mlx5_priv *priv = &dev->priv;
+ struct mlx5_interface *intf;
+
+ mutex_lock(&intf_mutex);
+ list_add_tail(&priv->dev_list, &dev_list);
+ list_for_each_entry(intf, &intf_list, list)
+ mlx5_add_device(intf, priv);
+ mutex_unlock(&intf_mutex);
+
+ return 0;
+}
+static void mlx5_unregister_device(struct mlx5_core_dev *dev)
+{
+ struct mlx5_priv *priv = &dev->priv;
+ struct mlx5_interface *intf;
+
+ mutex_lock(&intf_mutex);
+ list_for_each_entry(intf, &intf_list, list)
+ mlx5_remove_device(intf, priv);
+ list_del(&priv->dev_list);
+ mutex_unlock(&intf_mutex);
+}
+
+int mlx5_register_interface(struct mlx5_interface *intf)
+{
+ struct mlx5_priv *priv;
+
+ if (!intf->add || !intf->remove)
+ return -EINVAL;
+
+ mutex_lock(&intf_mutex);
+ list_add_tail(&intf->list, &intf_list);
+ list_for_each_entry(priv, &dev_list, dev_list)
+ mlx5_add_device(intf, priv);
+ mutex_unlock(&intf_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(mlx5_register_interface);
+
+void mlx5_unregister_interface(struct mlx5_interface *intf)
+{
+ struct mlx5_priv *priv;
+
+ mutex_lock(&intf_mutex);
+ list_for_each_entry(priv, &dev_list, dev_list)
+ mlx5_remove_device(intf, priv);
+ list_del(&intf->list);
+ mutex_unlock(&intf_mutex);
+}
+EXPORT_SYMBOL(mlx5_unregister_interface);
+
+static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
+ unsigned long param)
+{
+ struct mlx5_priv *priv = &dev->priv;
+ struct mlx5_device_context *dev_ctx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->ctx_lock, flags);
+
+ list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+ if (dev_ctx->intf->event)
+ dev_ctx->intf->event(dev, dev_ctx->context, event, param);
+
+ spin_unlock_irqrestore(&priv->ctx_lock, flags);
+}
+
+struct mlx5_core_event_handler {
+ void (*event)(struct mlx5_core_dev *dev,
+ enum mlx5_dev_event event,
+ void *data);
+};
+
+static int init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct mlx5_core_dev *dev;
+ struct mlx5_priv *priv;
+ int err;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ dev_err(&pdev->dev, "kzalloc failed\n");
+ return -ENOMEM;
+ }
+ priv = &dev->priv;
+
+ pci_set_drvdata(pdev, dev);
+
+ if (prof_sel < 0 || prof_sel >= ARRAY_SIZE(profile)) {
+ pr_warn("selected profile out of range, selecting default (%d)\n",
+ MLX5_DEFAULT_PROF);
+ prof_sel = MLX5_DEFAULT_PROF;
+ }
+ dev->profile = &profile[prof_sel];
+ dev->event = mlx5_core_event;
+
+ err = mlx5_dev_init(dev, pdev);
+ if (err) {
+ dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err);
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&priv->ctx_list);
+ spin_lock_init(&priv->ctx_lock);
+ err = mlx5_register_device(dev);
+ if (err) {
+ dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
+ goto out_init;
+ }
+
+ return 0;
+
+out_init:
+ mlx5_dev_cleanup(dev);
+out:
+ kfree(dev);
+ return err;
+}
+static void remove_one(struct pci_dev *pdev)
+{
+ struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+
+ mlx5_unregister_device(dev);
+ mlx5_dev_cleanup(dev);
+ kfree(dev);
+}
+
+static const struct pci_device_id mlx5_core_pci_table[] = {
+ { PCI_VDEVICE(MELLANOX, 4113) }, /* MT4113 Connect-IB */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
+
+static struct pci_driver mlx5_core_driver = {
+ .name = DRIVER_NAME,
+ .id_table = mlx5_core_pci_table,
+ .probe = init_one,
+ .remove = remove_one
+};
static int __init init(void)
{
@@ -530,8 +806,15 @@ static int __init init(void)
}
mlx5_health_init();
+ err = pci_register_driver(&mlx5_core_driver);
+ if (err)
+ goto err_health;
+
return 0;
+err_health:
+ mlx5_health_cleanup();
+ destroy_workqueue(mlx5_core_wq);
err_debug:
mlx5_unregister_debugfs();
return err;
@@ -539,6 +822,7 @@ err_debug:
static void __exit cleanup(void)
{
+ pci_unregister_driver(&mlx5_core_driver);
mlx5_health_cleanup();
destroy_workqueue(mlx5_core_wq);
mlx5_unregister_debugfs();
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index c2a953ef0e67..d476918ef269 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -51,7 +51,7 @@ enum {
struct mlx5_pages_req {
struct mlx5_core_dev *dev;
- u32 func_id;
+ u16 func_id;
s32 npages;
struct work_struct work;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 8c9ac870ecb1..313965853e10 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -86,7 +86,7 @@ struct mlx5_reg_pcap {
__be32 caps_31_0;
};
-int mlx5_set_port_caps(struct mlx5_core_dev *dev, int port_num, u32 caps)
+int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps)
{
struct mlx5_reg_pcap in;
struct mlx5_reg_pcap out;
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index c83d16dc7cd5..0eb47649191b 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -1519,7 +1519,8 @@ static int ks_hw_init(struct ks_net *ks)
ks->all_mcast = 0;
ks->mcast_lst_size = 0;
- ks->frame_head_info = kmalloc(MHEADER_SIZE, GFP_KERNEL);
+ ks->frame_head_info = devm_kmalloc(&ks->pdev->dev, MHEADER_SIZE,
+ GFP_KERNEL);
if (!ks->frame_head_info)
return false;
@@ -1537,44 +1538,41 @@ MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids);
static int ks8851_probe(struct platform_device *pdev)
{
- int err = -ENOMEM;
+ int err;
struct resource *io_d, *io_c;
struct net_device *netdev;
struct ks_net *ks;
u16 id, data;
const char *mac;
- io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
- if (!request_mem_region(io_d->start, resource_size(io_d), DRV_NAME))
- goto err_mem_region;
-
- if (!request_mem_region(io_c->start, resource_size(io_c), DRV_NAME))
- goto err_mem_region1;
-
netdev = alloc_etherdev(sizeof(struct ks_net));
if (!netdev)
- goto err_alloc_etherdev;
+ return -ENOMEM;
SET_NETDEV_DEV(netdev, &pdev->dev);
ks = netdev_priv(netdev);
ks->netdev = netdev;
- ks->hw_addr = ioremap(io_d->start, resource_size(io_d));
- if (!ks->hw_addr)
- goto err_ioremap;
+ io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ks->hw_addr = devm_ioremap_resource(&pdev->dev, io_d);
+ if (IS_ERR(ks->hw_addr)) {
+ err = PTR_ERR(ks->hw_addr);
+ goto err_free;
+ }
- ks->hw_addr_cmd = ioremap(io_c->start, resource_size(io_c));
- if (!ks->hw_addr_cmd)
- goto err_ioremap1;
+ io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ ks->hw_addr_cmd = devm_ioremap_resource(&pdev->dev, io_c);
+ if (IS_ERR(ks->hw_addr_cmd)) {
+ err = PTR_ERR(ks->hw_addr_cmd);
+ goto err_free;
+ }
netdev->irq = platform_get_irq(pdev, 0);
if ((int)netdev->irq < 0) {
err = netdev->irq;
- goto err_get_irq;
+ goto err_free;
}
ks->pdev = pdev;
@@ -1604,18 +1602,18 @@ static int ks8851_probe(struct platform_device *pdev)
if ((ks_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
netdev_err(netdev, "failed to read device ID\n");
err = -ENODEV;
- goto err_register;
+ goto err_free;
}
if (ks_read_selftest(ks)) {
netdev_err(netdev, "failed to read device ID\n");
err = -ENODEV;
- goto err_register;
+ goto err_free;
}
err = register_netdev(netdev);
if (err)
- goto err_register;
+ goto err_free;
platform_set_drvdata(pdev, netdev);
@@ -1663,32 +1661,17 @@ static int ks8851_probe(struct platform_device *pdev)
err_pdata:
unregister_netdev(netdev);
-err_register:
-err_get_irq:
- iounmap(ks->hw_addr_cmd);
-err_ioremap1:
- iounmap(ks->hw_addr);
-err_ioremap:
+err_free:
free_netdev(netdev);
-err_alloc_etherdev:
- release_mem_region(io_c->start, resource_size(io_c));
-err_mem_region1:
- release_mem_region(io_d->start, resource_size(io_d));
-err_mem_region:
return err;
}
static int ks8851_remove(struct platform_device *pdev)
{
struct net_device *netdev = platform_get_drvdata(pdev);
- struct ks_net *ks = netdev_priv(netdev);
- struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- kfree(ks->frame_head_info);
unregister_netdev(netdev);
- iounmap(ks->hw_addr);
free_netdev(netdev);
- release_mem_region(iomem->start, resource_size(iomem));
return 0;
}
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 064a48d0c368..f1ebed6c63b1 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -4409,14 +4409,13 @@ static int ksz_alloc_desc(struct dev_info *adapter)
DESC_ALIGNMENT;
adapter->desc_pool.alloc_virt =
- pci_alloc_consistent(
- adapter->pdev, adapter->desc_pool.alloc_size,
- &adapter->desc_pool.dma_addr);
+ pci_zalloc_consistent(adapter->pdev,
+ adapter->desc_pool.alloc_size,
+ &adapter->desc_pool.dma_addr);
if (adapter->desc_pool.alloc_virt == NULL) {
adapter->desc_pool.alloc_size = 0;
return 1;
}
- memset(adapter->desc_pool.alloc_virt, 0, adapter->desc_pool.alloc_size);
/* Align to the next cache line boundary. */
offset = (((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT) ?
@@ -7222,7 +7221,7 @@ static int pcidev_suspend(struct pci_dev *pdev, pm_message_t state)
static char pcidev_name[] = "ksz884xp";
-static DEFINE_PCI_DEVICE_TABLE(pcidev_table) = {
+static const struct pci_device_id pcidev_table[] = {
{ PCI_VENDOR_ID_MICREL_KS, 0x8841,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_MICREL_KS, 0x8842,
diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index f3d5d79f1cd1..9e7e3f1dce3e 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -574,6 +574,7 @@ myri10ge_validate_firmware(struct myri10ge_priv *mgp,
/* save firmware version for ethtool */
strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+ mgp->fw_version[sizeof(mgp->fw_version) - 1] = '\0';
sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
&mgp->fw_ver_minor, &mgp->fw_ver_tiny);
@@ -872,6 +873,10 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type)
return -ENOMEM;
dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE,
DMA_BIDIRECTIONAL);
+ if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) {
+ __free_page(dmatest_page);
+ return -ENOMEM;
+ }
/* Run a small DMA test.
* The magic multipliers to the length tell the firmware
@@ -1293,6 +1298,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
int bytes, int watchdog)
{
struct page *page;
+ dma_addr_t bus;
int idx;
#if MYRI10GE_ALLOC_SIZE > 4096
int end_offset;
@@ -1317,11 +1323,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
rx->watchdog_needed = 1;
return;
}
+
+ bus = pci_map_page(mgp->pdev, page, 0,
+ MYRI10GE_ALLOC_SIZE,
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) {
+ __free_pages(page, MYRI10GE_ALLOC_ORDER);
+ if (rx->fill_cnt - rx->cnt < 16)
+ rx->watchdog_needed = 1;
+ return;
+ }
+
rx->page = page;
rx->page_offset = 0;
- rx->bus = pci_map_page(mgp->pdev, page, 0,
- MYRI10GE_ALLOC_SIZE,
- PCI_DMA_FROMDEVICE);
+ rx->bus = bus;
+
}
rx->info[idx].page = rx->page;
rx->info[idx].page_offset = rx->page_offset;
@@ -2763,6 +2779,35 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
mb();
}
+static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp,
+ struct myri10ge_tx_buf *tx, int idx)
+{
+ unsigned int len;
+ int last_idx;
+
+ /* Free any DMA resources we've alloced and clear out the skb slot */
+ last_idx = (idx + 1) & tx->mask;
+ idx = tx->req & tx->mask;
+ do {
+ len = dma_unmap_len(&tx->info[idx], len);
+ if (len) {
+ if (tx->info[idx].skb != NULL)
+ pci_unmap_single(mgp->pdev,
+ dma_unmap_addr(&tx->info[idx],
+ bus), len,
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_page(mgp->pdev,
+ dma_unmap_addr(&tx->info[idx],
+ bus), len,
+ PCI_DMA_TODEVICE);
+ dma_unmap_len_set(&tx->info[idx], len, 0);
+ tx->info[idx].skb = NULL;
+ }
+ idx = (idx + 1) & tx->mask;
+ } while (idx != last_idx);
+}
+
/*
* Transmit a packet. We need to split the packet so that a single
* segment does not cross myri10ge->tx_boundary, so this makes segment
@@ -2786,7 +2831,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb,
u32 low;
__be32 high_swapped;
unsigned int len;
- int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+ int idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
u16 pseudo_hdr_offset, cksum_offset, queue;
int cum_len, seglen, boundary, rdma_count;
u8 flags, odd_flag;
@@ -2883,9 +2928,12 @@ again:
/* map the skb for DMA */
len = skb_headlen(skb);
+ bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus)))
+ goto drop;
+
idx = tx->req & tx->mask;
tx->info[idx].skb = skb;
- bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
dma_unmap_addr_set(&tx->info[idx], bus, bus);
dma_unmap_len_set(&tx->info[idx], len, len);
@@ -2984,12 +3032,16 @@ again:
break;
/* map next fragment for DMA */
- idx = (count + tx->req) & tx->mask;
frag = &skb_shinfo(skb)->frags[frag_idx];
frag_idx++;
len = skb_frag_size(frag);
bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len,
DMA_TO_DEVICE);
+ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) {
+ myri10ge_unmap_tx_dma(mgp, tx, idx);
+ goto drop;
+ }
+ idx = (count + tx->req) & tx->mask;
dma_unmap_addr_set(&tx->info[idx], bus, bus);
dma_unmap_len_set(&tx->info[idx], len, len);
}
@@ -3020,31 +3072,8 @@ again:
return NETDEV_TX_OK;
abort_linearize:
- /* Free any DMA resources we've alloced and clear out the skb
- * slot so as to not trip up assertions, and to avoid a
- * double-free if linearizing fails */
+ myri10ge_unmap_tx_dma(mgp, tx, idx);
- last_idx = (idx + 1) & tx->mask;
- idx = tx->req & tx->mask;
- tx->info[idx].skb = NULL;
- do {
- len = dma_unmap_len(&tx->info[idx], len);
- if (len) {
- if (tx->info[idx].skb != NULL)
- pci_unmap_single(mgp->pdev,
- dma_unmap_addr(&tx->info[idx],
- bus), len,
- PCI_DMA_TODEVICE);
- else
- pci_unmap_page(mgp->pdev,
- dma_unmap_addr(&tx->info[idx],
- bus), len,
- PCI_DMA_TODEVICE);
- dma_unmap_len_set(&tx->info[idx], len, 0);
- tx->info[idx].skb = NULL;
- }
- idx = (idx + 1) & tx->mask;
- } while (idx != last_idx);
if (skb_is_gso(skb)) {
netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n");
goto drop;
@@ -4213,7 +4242,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008
#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009
-static DEFINE_PCI_DEVICE_TABLE(myri10ge_pci_tbl) = {
+static const struct pci_device_id myri10ge_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
{PCI_DEVICE
(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)},
diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c
index 291fba8b9f07..b83f7c0fcf99 100644
--- a/drivers/net/ethernet/natsemi/natsemi.c
+++ b/drivers/net/ethernet/natsemi/natsemi.c
@@ -247,7 +247,7 @@ static struct {
{ "NatSemi DP8381[56]", 0, 24 },
};
-static DEFINE_PCI_DEVICE_TABLE(natsemi_pci_tbl) = {
+static const struct pci_device_id natsemi_pci_tbl[] = {
{ PCI_VENDOR_ID_NS, 0x0020, 0x12d9, 0x000c, 0, 0, 0 },
{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
{ } /* terminate list */
diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
index 19bb8244b9e3..2552e550a78c 100644
--- a/drivers/net/ethernet/natsemi/ns83820.c
+++ b/drivers/net/ethernet/natsemi/ns83820.c
@@ -2260,7 +2260,7 @@ static void ns83820_remove_one(struct pci_dev *pci_dev)
free_netdev(ndev);
}
-static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = {
+static const struct pci_device_id ns83820_pci_tbl[] = {
{ 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, .driver_data = 0, },
{ 0, },
};
diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index be587647c706..f5e4b820128b 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -471,7 +471,7 @@ module_param_array(rts_frm_len, uint, NULL, 0);
* S2IO device table.
* This table lists all the devices that this driver supports.
*/
-static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = {
+static const struct pci_device_id s2io_tbl[] = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index 7a0deadd53bf..4f40d7b8629e 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -63,7 +63,7 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("Neterion's X3100 Series 10GbE PCIe I/O"
"Virtualized Server Adapter");
-static DEFINE_PCI_DEVICE_TABLE(vxge_id_table) = {
+static const struct pci_device_id vxge_id_table[] = {
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_WIN, PCI_ANY_ID,
PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_UNI, PCI_ANY_ID,
@@ -503,7 +503,6 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
skb_hwts = skb_hwtstamps(skb);
skb_hwts->hwtstamp = ns_to_ktime(ns);
- skb_hwts->syststamp.tv64 = 0;
}
/* rth_hash_type and rth_it_hit are non-zero regardless of
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 9afc536c5734..925b296d8ab8 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -6185,7 +6185,7 @@ static void nv_shutdown(struct pci_dev *pdev)
#define nv_shutdown NULL
#endif /* CONFIG_PM */
-static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = {
+static const struct pci_device_id pci_tbl[] = {
{ /* nForce Ethernet Controller */
PCI_DEVICE(0x10DE, 0x01C3),
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index 7dc3e9b06d75..979c6980639f 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -247,28 +247,6 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
}
}
-static ktime_t ptp_to_ktime(u64 ptptime)
-{
- ktime_t ktimebase;
- u64 ptpbase;
- unsigned long flags;
-
- local_irq_save(flags);
- /* Fill the icache with the code */
- ktime_get_real();
- /* Flush all pending operations */
- mb();
- /* Read the time and PTP clock as close together as
- * possible. It is important that this sequence take the same
- * amount of time to reduce jitter
- */
- ktimebase = ktime_get_real();
- ptpbase = cvmx_read_csr(CVMX_MIO_PTP_CLOCK_HI);
- local_irq_restore(flags);
-
- return ktime_sub_ns(ktimebase, ptpbase - ptptime);
-}
-
static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
{
union cvmx_mixx_orcnt mix_orcnt;
@@ -312,12 +290,12 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
/* Read the hardware TX timestamp if one was recorded */
if (unlikely(re.s.tstamp)) {
struct skb_shared_hwtstamps ts;
+ memset(&ts, 0, sizeof(ts));
/* Read the timestamp */
u64 ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port));
/* Remove the timestamp from the FIFO */
cvmx_write_csr(CVMX_MIXX_TSCTL(p->port), 0);
/* Tell the kernel about the timestamp */
- ts.syststamp = ptp_to_ktime(ns);
ts.hwtstamp = ns_to_ktime(ns);
skb_tstamp_tx(skb, &ts);
}
@@ -429,7 +407,6 @@ good:
struct skb_shared_hwtstamps *ts;
ts = skb_hwtstamps(skb);
ts->hwtstamp = ns_to_ktime(ns);
- ts->syststamp = ptp_to_ktime(ns);
__skb_pull(skb, 8);
}
skb->protocol = eth_type_trans(skb, netdev);
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 73e66838cfef..3b98b263bad0 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2743,7 +2743,7 @@ static struct pch_gbe_privdata pch_gbe_minnow_privdata = {
.platform_init = pch_gbe_minnow_platform_init,
};
-static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
+static const struct pci_device_id pch_gbe_pcidev_id[] = {
{.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_IOH1_GBE,
.subvendor = PCI_VENDOR_ID_CIRCUITCO,
diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c
index 9a997e4c3e08..319d9d40f922 100644
--- a/drivers/net/ethernet/packetengines/hamachi.c
+++ b/drivers/net/ethernet/packetengines/hamachi.c
@@ -1911,7 +1911,7 @@ static void hamachi_remove_one(struct pci_dev *pdev)
}
}
-static DEFINE_PCI_DEVICE_TABLE(hamachi_pci_tbl) = {
+static const struct pci_device_id hamachi_pci_tbl[] = {
{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }
};
diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c
index 69a8dc095072..2d6b148528dd 100644
--- a/drivers/net/ethernet/packetengines/yellowfin.c
+++ b/drivers/net/ethernet/packetengines/yellowfin.c
@@ -236,7 +236,7 @@ static const struct pci_id_info pci_id_tbl[] = {
{ }
};
-static DEFINE_PCI_DEVICE_TABLE(yellowfin_pci_tbl) = {
+static const struct pci_device_id yellowfin_pci_tbl[] = {
{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
{ }
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 9abf70d74b31..30d934d66356 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1871,7 +1871,7 @@ static void pasemi_mac_remove(struct pci_dev *pdev)
free_netdev(netdev);
}
-static DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = {
+static const struct pci_device_id pasemi_mac_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) },
{ PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) },
{ },
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
index 6f6be57f4690..b8d5270359cd 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
@@ -129,14 +129,12 @@ netxen_get_minidump_template(struct netxen_adapter *adapter)
return NX_RCODE_INVALID_ARGS;
}
- addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr);
-
+ addr = pci_zalloc_consistent(adapter->pdev, size, &md_template_addr);
if (!addr) {
dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n");
return -ENOMEM;
}
- memset(addr, 0, size);
memset(&cmd, 0, sizeof(cmd));
memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR;
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 5bf05818a12c..1159031f885b 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -99,7 +99,7 @@ static int netxen_nic_set_mac(struct net_device *netdev, void *p);
{PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \
.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
-static DEFINE_PCI_DEVICE_TABLE(netxen_pci_tbl) = {
+static const struct pci_device_id netxen_pci_tbl[] = {
ENTRY(PCI_DEVICE_ID_NX2031_10GXSR),
ENTRY(PCI_DEVICE_ID_NX2031_10GCX4),
ENTRY(PCI_DEVICE_ID_NX2031_4GCU),
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index b5d6bc1a8b00..c2f09af5c25b 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -65,7 +65,7 @@ static int msi;
module_param(msi, int, 0);
MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts.");
-static DEFINE_PCI_DEVICE_TABLE(ql3xxx_pci_tbl) = {
+static const struct pci_device_id ql3xxx_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3032_DEVICE_ID)},
/* required last entry */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile
index a848d2979722..3c2c2c7c1559 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/Makefile
+++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile
@@ -8,7 +8,7 @@ qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o \
qlcnic_83xx_init.o qlcnic_83xx_vnic.o \
- qlcnic_minidump.o qlcnic_sriov_common.o
+ qlcnic_sriov_common.o
qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index be618b9e874f..16039d1497b8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -39,8 +39,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 60
-#define QLCNIC_LINUX_VERSIONID "5.3.60"
+#define _QLCNIC_LINUX_SUBVERSION 61
+#define QLCNIC_LINUX_VERSIONID "5.3.61"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 304e247bdf33..ffbae293cef5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -136,7 +136,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
- dev_err(&pdev->dev, "card response timeout.\n");
+ dev_err(&pdev->dev, "command timeout, response = 0x%x\n", rsp);
cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1), &err);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
index 561cb11ca58c..a72bcddf160a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
@@ -926,7 +926,7 @@ static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num)
}
}
-static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
+static int qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct dcb_app app = {
@@ -935,7 +935,7 @@ static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id)
};
if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
- return 0;
+ return -EINVAL;
return dcb_getapp(netdev, &app);
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 1b7f3dbae289..141f116eb868 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1290,17 +1290,25 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
void qlcnic_update_stats(struct qlcnic_adapter *adapter)
{
+ struct qlcnic_tx_queue_stats tx_stats;
struct qlcnic_host_tx_ring *tx_ring;
int ring;
+ memset(&tx_stats, 0, sizeof(tx_stats));
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
- adapter->stats.xmit_on += tx_ring->tx_stats.xmit_on;
- adapter->stats.xmit_off += tx_ring->tx_stats.xmit_off;
- adapter->stats.xmitcalled += tx_ring->tx_stats.xmit_called;
- adapter->stats.xmitfinished += tx_ring->tx_stats.xmit_finished;
- adapter->stats.txbytes += tx_ring->tx_stats.tx_bytes;
+ tx_stats.xmit_on += tx_ring->tx_stats.xmit_on;
+ tx_stats.xmit_off += tx_ring->tx_stats.xmit_off;
+ tx_stats.xmit_called += tx_ring->tx_stats.xmit_called;
+ tx_stats.xmit_finished += tx_ring->tx_stats.xmit_finished;
+ tx_stats.tx_bytes += tx_ring->tx_stats.tx_bytes;
}
+
+ adapter->stats.xmit_on = tx_stats.xmit_on;
+ adapter->stats.xmit_off = tx_stats.xmit_off;
+ adapter->stats.xmitcalled = tx_stats.xmit_called;
+ adapter->stats.xmitfinished = tx_stats.xmit_finished;
+ adapter->stats.txbytes = tx_stats.tx_bytes;
}
static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 4fc186713b66..cf08b2de071e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -108,7 +108,7 @@ static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
.class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
-static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
+static const struct pci_device_id qlcnic_pci_tbl[] = {
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
@@ -427,16 +427,17 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
}
static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
- struct net_device *netdev, int idx)
+ struct net_device *netdev,
+ struct net_device *filter_dev, int idx)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
if (!adapter->fdb_mac_learn)
- return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+ return ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
qlcnic_sriov_check(adapter))
- idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
+ idx = ndo_dflt_fdb_dump(skb, ncb, netdev, filter_dev, idx);
return idx;
}
@@ -2323,14 +2324,14 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
if (err)
return err;
+ qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
+
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "failed to register net device\n");
return err;
}
- qlcnic_dcb_init_dcbnl_ops(adapter->dcb);
-
return 0;
}
@@ -2623,13 +2624,13 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_out_disable_mbx_intr;
+ if (adapter->portnum == 0)
+ qlcnic_set_drv_version(adapter);
+
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
if (err)
goto err_out_disable_mbx_intr;
- if (adapter->portnum == 0)
- qlcnic_set_drv_version(adapter);
-
pci_set_drvdata(pdev, adapter);
if (qlcnic_82xx_check(adapter))
@@ -2980,17 +2981,43 @@ static inline void dump_tx_ring_desc(struct qlcnic_host_tx_ring *tx_ring)
}
}
-static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
+static void qlcnic_dump_rings(struct qlcnic_adapter *adapter)
{
+ struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
struct net_device *netdev = adapter->netdev;
+ struct qlcnic_host_rds_ring *rds_ring;
+ struct qlcnic_host_sds_ring *sds_ring;
struct qlcnic_host_tx_ring *tx_ring;
int ring;
if (!netdev || !netif_running(netdev))
return;
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ if (!rds_ring)
+ continue;
+ netdev_info(netdev,
+ "rds_ring=%d crb_rcv_producer=%d producer=%u num_desc=%u\n",
+ ring, readl(rds_ring->crb_rcv_producer),
+ rds_ring->producer, rds_ring->num_desc);
+ }
+
+ for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
+ sds_ring = &(recv_ctx->sds_rings[ring]);
+ if (!sds_ring)
+ continue;
+ netdev_info(netdev,
+ "sds_ring=%d crb_sts_consumer=%d consumer=%u crb_intr_mask=%d num_desc=%u\n",
+ ring, readl(sds_ring->crb_sts_consumer),
+ sds_ring->consumer, readl(sds_ring->crb_intr_mask),
+ sds_ring->num_desc);
+ }
+
for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring];
+ if (!tx_ring)
+ continue;
netdev_info(netdev, "Tx ring=%d Context Id=0x%x\n",
ring, tx_ring->ctx_id);
netdev_info(netdev,
@@ -3013,9 +3040,10 @@ static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
netdev_info(netdev, "Total desc=%d, Available desc=%d\n",
tx_ring->num_desc, qlcnic_tx_avail(tx_ring));
- if (netif_msg_tx_done(adapter->ahw))
+ if (netif_msg_tx_err(adapter->ahw))
dump_tx_ring_desc(tx_ring);
}
+
}
static void qlcnic_tx_timeout(struct net_device *netdev)
@@ -3025,16 +3053,18 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
if (test_bit(__QLCNIC_RESETTING, &adapter->state))
return;
- if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) {
- netdev_info(netdev, "Tx timeout, reset the adapter.\n");
+ qlcnic_dump_rings(adapter);
+
+ if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS ||
+ netif_msg_tx_err(adapter->ahw)) {
+ netdev_err(netdev, "Tx timeout, reset the adapter.\n");
if (qlcnic_82xx_check(adapter))
adapter->need_fw_reset = 1;
else if (qlcnic_83xx_check(adapter))
qlcnic_83xx_idc_request_reset(adapter,
QLCNIC_FORCE_FW_DUMP_KEY);
} else {
- netdev_info(netdev, "Tx timeout, reset adapter context.\n");
- qlcnic_dump_tx_rings(adapter);
+ netdev_err(netdev, "Tx timeout, reset adapter context.\n");
adapter->ahw->reset_context = 1;
}
}
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b40050e03a56..188626e2a861 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -86,7 +86,7 @@ MODULE_PARM_DESC(qlge_force_coredump,
"Option to allow force of firmware core dump. "
"Default is OFF - Do not allow.");
-static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = {
+static const struct pci_device_id qlge_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)},
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)},
/* required last entry */
@@ -2727,23 +2727,22 @@ static void ql_free_shadow_space(struct ql_adapter *qdev)
static int ql_alloc_shadow_space(struct ql_adapter *qdev)
{
qdev->rx_ring_shadow_reg_area =
- pci_alloc_consistent(qdev->pdev,
- PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma);
+ pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
+ &qdev->rx_ring_shadow_reg_dma);
if (qdev->rx_ring_shadow_reg_area == NULL) {
netif_err(qdev, ifup, qdev->ndev,
"Allocation of RX shadow space failed.\n");
return -ENOMEM;
}
- memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE);
+
qdev->tx_ring_shadow_reg_area =
- pci_alloc_consistent(qdev->pdev, PAGE_SIZE,
- &qdev->tx_ring_shadow_reg_dma);
+ pci_zalloc_consistent(qdev->pdev, PAGE_SIZE,
+ &qdev->tx_ring_shadow_reg_dma);
if (qdev->tx_ring_shadow_reg_area == NULL) {
netif_err(qdev, ifup, qdev->ndev,
"Allocation of TX shadow space failed.\n");
goto err_wqp_sh_area;
}
- memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE);
return 0;
err_wqp_sh_area:
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index cd045ecb9816..9a37247cf4b8 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -1254,7 +1254,7 @@ static void r6040_remove_one(struct pci_dev *pdev)
}
-static DEFINE_PCI_DEVICE_TABLE(r6040_pci_tbl) = {
+static const struct pci_device_id r6040_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) },
{ 0 }
};
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 2bc728e65e24..75b1693ec8bf 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -382,13 +382,6 @@ static int cp_get_eeprom(struct net_device *dev,
static int cp_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *data);
-static DEFINE_PCI_DEVICE_TABLE(cp_pci_tbl) = {
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139), },
- { PCI_DEVICE(PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322), },
- { },
-};
-MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
-
static struct {
const char str[ETH_GSTRING_LEN];
} ethtool_stats_keys[] = {
@@ -1887,11 +1880,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
resource_size_t pciaddr;
unsigned int addr_len, i, pci_using_dac;
-#ifndef MODULE
- static int version_printed;
- if (version_printed++ == 0)
- pr_info("%s", version);
-#endif
+ pr_info_once("%s", version);
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
@@ -2110,6 +2099,13 @@ static int cp_resume (struct pci_dev *pdev)
}
#endif /* CONFIG_PM */
+static const struct pci_device_id cp_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139), },
+ { PCI_DEVICE(PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322), },
+ { },
+};
+MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
+
static struct pci_driver cp_driver = {
.name = DRV_NAME,
.id_table = cp_pci_tbl,
@@ -2121,18 +2117,4 @@ static struct pci_driver cp_driver = {
#endif
};
-static int __init cp_init (void)
-{
-#ifdef MODULE
- pr_info("%s", version);
-#endif
- return pci_register_driver(&cp_driver);
-}
-
-static void __exit cp_exit (void)
-{
- pci_unregister_driver (&cp_driver);
-}
-
-module_init(cp_init);
-module_exit(cp_exit);
+module_pci_driver(cp_driver);
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
index 2e5df148af4c..007b38cce69a 100644
--- a/drivers/net/ethernet/realtek/8139too.c
+++ b/drivers/net/ethernet/realtek/8139too.c
@@ -234,7 +234,7 @@ static const struct {
};
-static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = {
+static const struct pci_device_id rtl8139_pci_tbl[] = {
{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 61623e9af574..91652e7235e4 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -27,6 +27,8 @@
#include <linux/firmware.h>
#include <linux/pci-aspm.h>
#include <linux/prefetch.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -289,7 +291,7 @@ enum cfg_version {
RTL_CFG_2
};
-static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
+static const struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
@@ -627,39 +629,22 @@ enum rtl_tx_desc_bit_0 {
/* 8102e, 8168c and beyond. */
enum rtl_tx_desc_bit_1 {
+ /* First doubleword. */
+ TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */
+ TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */
+#define GTTCPHO_SHIFT 18
+#define GTTCPHO_MAX 0x7fU
+
/* Second doubleword. */
+#define TCPHO_SHIFT 18
+#define TCPHO_MAX 0x3ffU
#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
- TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
+ TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */
+ TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */
TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
};
-static const struct rtl_tx_desc_info {
- struct {
- u32 udp;
- u32 tcp;
- } checksum;
- u16 mss_shift;
- u16 opts_offset;
-} tx_desc_info [] = {
- [RTL_TD_0] = {
- .checksum = {
- .udp = TD0_IP_CS | TD0_UDP_CS,
- .tcp = TD0_IP_CS | TD0_TCP_CS
- },
- .mss_shift = TD0_MSS_SHIFT,
- .opts_offset = 0
- },
- [RTL_TD_1] = {
- .checksum = {
- .udp = TD1_IP_CS | TD1_UDP_CS,
- .tcp = TD1_IP_CS | TD1_TCP_CS
- },
- .mss_shift = TD1_MSS_SHIFT,
- .opts_offset = 1
- }
-};
-
enum rtl_rx_desc_bit {
/* Rx private */
PID1 = (1 << 18), /* Protocol ID bit 1/2 */
@@ -783,6 +768,7 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
unsigned int (*link_ok)(void __iomem *);
int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
+ bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *);
struct {
DECLARE_BITMAP(flags, RTL_FLAG_MAX);
@@ -5968,32 +5954,179 @@ static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
}
-static inline bool rtl8169_tso_csum(struct rtl8169_private *tp,
- struct sk_buff *skb, u32 *opts)
+static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+ struct net_device *dev);
+/* r8169_csum_workaround()
+ * The hw limites the value the transport offset. When the offset is out of the
+ * range, calculate the checksum by sw.
+ */
+static void r8169_csum_workaround(struct rtl8169_private *tp,
+ struct sk_buff *skb)
+{
+ if (skb_shinfo(skb)->gso_size) {
+ netdev_features_t features = tp->dev->features;
+ struct sk_buff *segs, *nskb;
+
+ features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ segs = skb_gso_segment(skb, features);
+ if (IS_ERR(segs) || !segs)
+ goto drop;
+
+ do {
+ nskb = segs;
+ segs = segs->next;
+ nskb->next = NULL;
+ rtl8169_start_xmit(nskb, tp->dev);
+ } while (segs);
+
+ dev_kfree_skb(skb);
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (skb_checksum_help(skb) < 0)
+ goto drop;
+
+ rtl8169_start_xmit(skb, tp->dev);
+ } else {
+ struct net_device_stats *stats;
+
+drop:
+ stats = &tp->dev->stats;
+ stats->tx_dropped++;
+ dev_kfree_skb(skb);
+ }
+}
+
+/* msdn_giant_send_check()
+ * According to the document of microsoft, the TCP Pseudo Header excludes the
+ * packet length for IPv6 TCP large packets.
+ */
+static int msdn_giant_send_check(struct sk_buff *skb)
+{
+ const struct ipv6hdr *ipv6h;
+ struct tcphdr *th;
+ int ret;
+
+ ret = skb_cow_head(skb, 0);
+ if (ret)
+ return ret;
+
+ ipv6h = ipv6_hdr(skb);
+ th = tcp_hdr(skb);
+
+ th->check = 0;
+ th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
+
+ return ret;
+}
+
+static inline __be16 get_protocol(struct sk_buff *skb)
+{
+ __be16 protocol;
+
+ if (skb->protocol == htons(ETH_P_8021Q))
+ protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+ else
+ protocol = skb->protocol;
+
+ return protocol;
+}
+
+static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp,
+ struct sk_buff *skb, u32 *opts)
{
- const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
u32 mss = skb_shinfo(skb)->gso_size;
- int offset = info->opts_offset;
if (mss) {
opts[0] |= TD_LSO;
- opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
+ opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb);
+ if (ip->protocol == IPPROTO_TCP)
+ opts[0] |= TD0_IP_CS | TD0_TCP_CS;
+ else if (ip->protocol == IPPROTO_UDP)
+ opts[0] |= TD0_IP_CS | TD0_UDP_CS;
+ else
+ WARN_ON_ONCE(1);
+ }
+
+ return true;
+}
+
+static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
+ struct sk_buff *skb, u32 *opts)
+{
+ u32 transport_offset = (u32)skb_transport_offset(skb);
+ u32 mss = skb_shinfo(skb)->gso_size;
+
+ if (mss) {
+ if (transport_offset > GTTCPHO_MAX) {
+ netif_warn(tp, tx_err, tp->dev,
+ "Invalid transport offset 0x%x for TSO\n",
+ transport_offset);
+ return false;
+ }
+
+ switch (get_protocol(skb)) {
+ case htons(ETH_P_IP):
+ opts[0] |= TD1_GTSENV4;
+ break;
+
+ case htons(ETH_P_IPV6):
+ if (msdn_giant_send_check(skb))
+ return false;
+
+ opts[0] |= TD1_GTSENV6;
+ break;
+
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ opts[0] |= transport_offset << GTTCPHO_SHIFT;
+ opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 ip_protocol;
+
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
- if (ip->protocol == IPPROTO_TCP)
- opts[offset] |= info->checksum.tcp;
- else if (ip->protocol == IPPROTO_UDP)
- opts[offset] |= info->checksum.udp;
+ if (transport_offset > TCPHO_MAX) {
+ netif_warn(tp, tx_err, tp->dev,
+ "Invalid transport offset 0x%x\n",
+ transport_offset);
+ return false;
+ }
+
+ switch (get_protocol(skb)) {
+ case htons(ETH_P_IP):
+ opts[1] |= TD1_IPv4_CS;
+ ip_protocol = ip_hdr(skb)->protocol;
+ break;
+
+ case htons(ETH_P_IPV6):
+ opts[1] |= TD1_IPv6_CS;
+ ip_protocol = ipv6_hdr(skb)->nexthdr;
+ break;
+
+ default:
+ ip_protocol = IPPROTO_RAW;
+ break;
+ }
+
+ if (ip_protocol == IPPROTO_TCP)
+ opts[1] |= TD1_TCP_CS;
+ else if (ip_protocol == IPPROTO_UDP)
+ opts[1] |= TD1_UDP_CS;
else
WARN_ON_ONCE(1);
+
+ opts[1] |= transport_offset << TCPHO_SHIFT;
} else {
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return rtl_skb_pad(skb);
}
+
return true;
}
@@ -6021,8 +6154,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
opts[0] = DescOwn;
- if (!rtl8169_tso_csum(tp, skb, opts))
- goto err_update_stats;
+ if (!tp->tso_csum(tp, skb, opts)) {
+ r8169_csum_workaround(tp, skb);
+ return NETDEV_TX_OK;
+ }
len = skb_headlen(skb);
mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
@@ -6087,7 +6222,6 @@ err_dma_1:
rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
err_dma_0:
dev_kfree_skb_any(skb);
-err_update_stats:
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
@@ -7172,6 +7306,14 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* 8110SCd requires hardware Rx VLAN - disallow toggling */
dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
+ if (tp->txd_version == RTL_TD_0)
+ tp->tso_csum = rtl8169_tso_csum_v1;
+ else if (tp->txd_version == RTL_TD_1) {
+ tp->tso_csum = rtl8169_tso_csum_v2;
+ dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+ } else
+ WARN_ON_ONCE(1);
+
dev->hw_features |= NETIF_F_RXALL;
dev->hw_features |= NETIF_F_RXFCS;
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 7622213beef1..60e9c2cd051e 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1094,20 +1094,16 @@ static void sh_eth_ring_free(struct net_device *ndev)
/* Free Rx skb ringbuffer */
if (mdp->rx_skbuff) {
- for (i = 0; i < mdp->num_rx_ring; i++) {
- if (mdp->rx_skbuff[i])
- dev_kfree_skb(mdp->rx_skbuff[i]);
- }
+ for (i = 0; i < mdp->num_rx_ring; i++)
+ dev_kfree_skb(mdp->rx_skbuff[i]);
}
kfree(mdp->rx_skbuff);
mdp->rx_skbuff = NULL;
/* Free Tx skb ringbuffer */
if (mdp->tx_skbuff) {
- for (i = 0; i < mdp->num_tx_ring; i++) {
- if (mdp->tx_skbuff[i])
- dev_kfree_skb(mdp->tx_skbuff[i]);
- }
+ for (i = 0; i < mdp->num_tx_ring; i++)
+ dev_kfree_skb(mdp->tx_skbuff[i]);
}
kfree(mdp->tx_skbuff);
mdp->tx_skbuff = NULL;
@@ -2077,13 +2073,11 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
rxdesc = &mdp->rx_ring[i];
rxdesc->status = 0;
rxdesc->addr = 0xBADF00D0;
- if (mdp->rx_skbuff[i])
- dev_kfree_skb(mdp->rx_skbuff[i]);
+ dev_kfree_skb(mdp->rx_skbuff[i]);
mdp->rx_skbuff[i] = NULL;
}
for (i = 0; i < mdp->num_tx_ring; i++) {
- if (mdp->tx_skbuff[i])
- dev_kfree_skb(mdp->tx_skbuff[i]);
+ dev_kfree_skb(mdp->tx_skbuff[i]);
mdp->tx_skbuff[i] = NULL;
}
@@ -2752,6 +2746,7 @@ static const struct of_device_id sh_eth_match_table[] = {
{ .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
{ .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
{ .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
+ { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data },
{ .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
{ }
};
@@ -2978,6 +2973,7 @@ static struct platform_device_id sh_eth_id_table[] = {
{ "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
{ "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
{ "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
+ { "r8a7794-ether", (kernel_ulong_t)&r8a779x_data },
{ }
};
MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index b5ed30a39144..002d4cdc319f 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -755,6 +755,8 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type)
{ NULL, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
#define EF10_OTHER_STAT(ext_name) \
[EF10_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name) \
+ [GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
EF10_DMA_STAT(tx_bytes, TX_BYTES),
@@ -798,6 +800,8 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
EF10_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS),
EF10_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
EF10_DMA_STAT(rx_nodesc_drops, RX_NODESC_DROPS),
+ GENERIC_SW_STAT(rx_nodesc_trunc),
+ GENERIC_SW_STAT(rx_noskb_drops),
EF10_DMA_STAT(rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
EF10_DMA_STAT(rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
EF10_DMA_STAT(rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
@@ -841,7 +845,9 @@ static const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
(1ULL << EF10_STAT_rx_gtjumbo) | \
(1ULL << EF10_STAT_rx_bad_gtjumbo) | \
(1ULL << EF10_STAT_rx_overflow) | \
- (1ULL << EF10_STAT_rx_nodesc_drops))
+ (1ULL << EF10_STAT_rx_nodesc_drops) | \
+ (1ULL << GENERIC_STAT_rx_nodesc_trunc) | \
+ (1ULL << GENERIC_STAT_rx_noskb_drops))
/* These statistics are only provided by the 10G MAC. For a 10G/40G
* switchable port we do not expose these because they might not
@@ -951,7 +957,7 @@ static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
stats[EF10_STAT_rx_bytes_minus_good_bytes];
efx_update_diff_stat(&stats[EF10_STAT_rx_bad_bytes],
stats[EF10_STAT_rx_bytes_minus_good_bytes]);
-
+ efx_update_sw_stats(efx, stats);
return 0;
}
@@ -990,7 +996,9 @@ static size_t efx_ef10_update_stats(struct efx_nic *efx, u64 *full_stats,
core_stats->tx_packets = stats[EF10_STAT_tx_packets];
core_stats->rx_bytes = stats[EF10_STAT_rx_bytes];
core_stats->tx_bytes = stats[EF10_STAT_tx_bytes];
- core_stats->rx_dropped = stats[EF10_STAT_rx_nodesc_drops];
+ core_stats->rx_dropped = stats[EF10_STAT_rx_nodesc_drops] +
+ stats[GENERIC_STAT_rx_nodesc_trunc] +
+ stats[GENERIC_STAT_rx_noskb_drops];
core_stats->multicast = stats[EF10_STAT_rx_multicast];
core_stats->rx_length_errors =
stats[EF10_STAT_rx_gtjumbo] +
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 1e274045970f..b2cc590dd1dd 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -272,6 +272,9 @@ static int efx_poll(struct napi_struct *napi, int budget)
struct efx_nic *efx = channel->efx;
int spent;
+ if (!efx_channel_lock_napi(channel))
+ return budget;
+
netif_vdbg(efx, intr, efx->net_dev,
"channel %d NAPI poll executing on CPU %d\n",
channel->channel, raw_smp_processor_id());
@@ -311,6 +314,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
efx_nic_eventq_read_ack(channel);
}
+ efx_channel_unlock_napi(channel);
return spent;
}
@@ -357,7 +361,7 @@ static int efx_init_eventq(struct efx_channel *channel)
}
/* Enable event queue processing and NAPI */
-static void efx_start_eventq(struct efx_channel *channel)
+void efx_start_eventq(struct efx_channel *channel)
{
netif_dbg(channel->efx, ifup, channel->efx->net_dev,
"chan %d start event queue\n", channel->channel);
@@ -366,17 +370,20 @@ static void efx_start_eventq(struct efx_channel *channel)
channel->enabled = true;
smp_wmb();
+ efx_channel_enable(channel);
napi_enable(&channel->napi_str);
efx_nic_eventq_read_ack(channel);
}
/* Disable event queue processing and NAPI */
-static void efx_stop_eventq(struct efx_channel *channel)
+void efx_stop_eventq(struct efx_channel *channel)
{
if (!channel->enabled)
return;
napi_disable(&channel->napi_str);
+ while (!efx_channel_disable(channel))
+ usleep_range(1000, 20000);
channel->enabled = false;
}
@@ -1960,6 +1967,8 @@ static void efx_init_napi_channel(struct efx_channel *channel)
channel->napi_dev = efx->net_dev;
netif_napi_add(channel->napi_dev, &channel->napi_str,
efx_poll, napi_weight);
+ napi_hash_add(&channel->napi_str);
+ efx_channel_init_lock(channel);
}
static void efx_init_napi(struct efx_nic *efx)
@@ -1972,8 +1981,10 @@ static void efx_init_napi(struct efx_nic *efx)
static void efx_fini_napi_channel(struct efx_channel *channel)
{
- if (channel->napi_dev)
+ if (channel->napi_dev) {
netif_napi_del(&channel->napi_str);
+ napi_hash_del(&channel->napi_str);
+ }
channel->napi_dev = NULL;
}
@@ -2008,6 +2019,37 @@ static void efx_netpoll(struct net_device *net_dev)
#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static int efx_busy_poll(struct napi_struct *napi)
+{
+ struct efx_channel *channel =
+ container_of(napi, struct efx_channel, napi_str);
+ struct efx_nic *efx = channel->efx;
+ int budget = 4;
+ int old_rx_packets, rx_packets;
+
+ if (!netif_running(efx->net_dev))
+ return LL_FLUSH_FAILED;
+
+ if (!efx_channel_lock_poll(channel))
+ return LL_FLUSH_BUSY;
+
+ old_rx_packets = channel->rx_queue.rx_packets;
+ efx_process_channel(channel, budget);
+
+ rx_packets = channel->rx_queue.rx_packets - old_rx_packets;
+
+ /* There is no race condition with NAPI here.
+ * NAPI will automatically be rescheduled if it yielded during busy
+ * polling, because it was not able to take the lock and thus returned
+ * the full budget.
+ */
+ efx_channel_unlock_poll(channel);
+
+ return rx_packets;
+}
+#endif
+
/**************************************************************************
*
* Kernel net device interface
@@ -2177,6 +2219,9 @@ static const struct net_device_ops efx_farch_netdev_ops = {
.ndo_poll_controller = efx_netpoll,
#endif
.ndo_setup_tc = efx_setup_tc,
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = efx_busy_poll,
+#endif
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
@@ -2197,6 +2242,9 @@ static const struct net_device_ops efx_ef10_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = efx_busy_poll,
+#endif
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
@@ -2594,7 +2642,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
**************************************************************************/
/* PCI device ID table */
-static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
+static const struct pci_device_id efx_pci_table[] = {
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE,
PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0),
.driver_data = (unsigned long) &falcon_a1_nic_type},
@@ -2607,6 +2655,8 @@ static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903), /* SFC9120 PF */
.driver_data = (unsigned long) &efx_hunt_a0_nic_type},
+ {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0923), /* SFC9140 PF */
+ .driver_data = (unsigned long) &efx_hunt_a0_nic_type},
{0} /* end of list */
};
@@ -2722,6 +2772,17 @@ static void efx_fini_struct(struct efx_nic *efx)
}
}
+void efx_update_sw_stats(struct efx_nic *efx, u64 *stats)
+{
+ u64 n_rx_nodesc_trunc = 0;
+ struct efx_channel *channel;
+
+ efx_for_each_channel(channel, efx)
+ n_rx_nodesc_trunc += channel->n_rx_nodesc_trunc;
+ stats[GENERIC_STAT_rx_nodesc_trunc] = n_rx_nodesc_trunc;
+ stats[GENERIC_STAT_rx_noskb_drops] = atomic_read(&efx->n_rx_noskb_drops);
+}
+
/**************************************************************************
*
* PCI interface
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 99032581336f..2587c582a821 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -194,11 +194,16 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
bool rx_may_override_tx);
void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
unsigned int *rx_usecs, bool *rx_adaptive);
+void efx_stop_eventq(struct efx_channel *channel);
+void efx_start_eventq(struct efx_channel *channel);
/* Dummy PHY ops for PHY drivers */
int efx_port_dummy_op_int(struct efx_nic *efx);
void efx_port_dummy_op_void(struct efx_nic *efx);
+/* Update the generic software stats in the passed stats array */
+void efx_update_sw_stats(struct efx_nic *efx, u64 *stats);
+
/* MTD */
#ifdef CONFIG_SFC_MTD
int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 74739c4b9997..cad258a78708 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -77,7 +77,6 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
- EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
};
@@ -360,6 +359,37 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
return n;
}
+static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings)
+{
+ size_t n_stats = 0;
+ struct efx_channel *channel;
+
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_has_tx_queues(channel)) {
+ n_stats++;
+ if (strings != NULL) {
+ snprintf(strings, ETH_GSTRING_LEN,
+ "tx-%u.tx_packets",
+ channel->tx_queue[0].queue /
+ EFX_TXQ_TYPES);
+
+ strings += ETH_GSTRING_LEN;
+ }
+ }
+ }
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_has_rx_queue(channel)) {
+ n_stats++;
+ if (strings != NULL) {
+ snprintf(strings, ETH_GSTRING_LEN,
+ "rx-%d.rx_packets", channel->channel);
+ strings += ETH_GSTRING_LEN;
+ }
+ }
+ }
+ return n_stats;
+}
+
static int efx_ethtool_get_sset_count(struct net_device *net_dev,
int string_set)
{
@@ -368,8 +398,9 @@ static int efx_ethtool_get_sset_count(struct net_device *net_dev,
switch (string_set) {
case ETH_SS_STATS:
return efx->type->describe_stats(efx, NULL) +
- EFX_ETHTOOL_SW_STAT_COUNT +
- efx_ptp_describe_stats(efx, NULL);
+ EFX_ETHTOOL_SW_STAT_COUNT +
+ efx_describe_per_queue_stats(efx, NULL) +
+ efx_ptp_describe_stats(efx, NULL);
case ETH_SS_TEST:
return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
default:
@@ -391,6 +422,8 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,
strlcpy(strings + i * ETH_GSTRING_LEN,
efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
+ strings += (efx_describe_per_queue_stats(efx, strings) *
+ ETH_GSTRING_LEN);
efx_ptp_describe_stats(efx, strings);
break;
case ETH_SS_TEST:
@@ -410,6 +443,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
const struct efx_sw_stat_desc *stat;
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue *rx_queue;
int i;
spin_lock_bh(&efx->stats_lock);
@@ -445,6 +479,25 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
spin_unlock_bh(&efx->stats_lock);
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_has_tx_queues(channel)) {
+ *data = 0;
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ *data += tx_queue->tx_packets;
+ }
+ data++;
+ }
+ }
+ efx_for_each_channel(channel, efx) {
+ if (efx_channel_has_rx_queue(channel)) {
+ *data = 0;
+ efx_for_each_channel_rx_queue(rx_queue, channel) {
+ *data += rx_queue->rx_packets;
+ }
+ data++;
+ }
+ }
+
efx_ptp_update_stats(efx, data);
}
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index fae25a418647..157037546d30 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -142,6 +142,8 @@
hw_name ## _ ## offset }
#define FALCON_OTHER_STAT(ext_name) \
[FALCON_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name) \
+ [GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
FALCON_DMA_STAT(tx_bytes, XgTxOctets),
@@ -191,6 +193,8 @@ static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
FALCON_DMA_STAT(rx_length_error, XgRxLengthError),
FALCON_DMA_STAT(rx_internal_error, XgRxInternalMACError),
FALCON_OTHER_STAT(rx_nodesc_drop_cnt),
+ GENERIC_SW_STAT(rx_nodesc_trunc),
+ GENERIC_SW_STAT(rx_noskb_drops),
};
static const unsigned long falcon_stat_mask[] = {
[0 ... BITS_TO_LONGS(FALCON_STAT_COUNT) - 1] = ~0UL,
@@ -2574,6 +2578,7 @@ static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
stats[FALCON_STAT_rx_bytes] -
stats[FALCON_STAT_rx_good_bytes] -
stats[FALCON_STAT_rx_control] * 64);
+ efx_update_sw_stats(efx, stats);
}
if (full_stats)
@@ -2584,7 +2589,9 @@ static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
core_stats->tx_packets = stats[FALCON_STAT_tx_packets];
core_stats->rx_bytes = stats[FALCON_STAT_rx_bytes];
core_stats->tx_bytes = stats[FALCON_STAT_tx_bytes];
- core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt];
+ core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt] +
+ stats[GENERIC_STAT_rx_nodesc_trunc] +
+ stats[GENERIC_STAT_rx_noskb_drops];
core_stats->multicast = stats[FALCON_STAT_rx_multicast];
core_stats->rx_length_errors =
stats[FALCON_STAT_rx_gtjumbo] +
diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c
index e5fc4e1574b5..fb19b70eac01 100644
--- a/drivers/net/ethernet/sfc/mcdi_port.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -183,6 +183,8 @@ static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
result |= SUPPORTED_1000baseKX_Full;
if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
result |= SUPPORTED_10000baseKX4_Full;
+ if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
+ result |= SUPPORTED_40000baseKR4_Full;
break;
case MC_CMD_MEDIA_XFP:
@@ -190,6 +192,12 @@ static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
result |= SUPPORTED_FIBRE;
break;
+ case MC_CMD_MEDIA_QSFP_PLUS:
+ result |= SUPPORTED_FIBRE;
+ if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
+ result |= SUPPORTED_40000baseCR4_Full;
+ break;
+
case MC_CMD_MEDIA_BASE_T:
result |= SUPPORTED_TP;
if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
@@ -237,6 +245,8 @@ static u32 ethtool_to_mcdi_cap(u32 cap)
result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full))
result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
+ if (cap & (SUPPORTED_40000baseCR4_Full | SUPPORTED_40000baseKR4_Full))
+ result |= (1 << MC_CMD_PHY_CAP_40000FDX_LBN);
if (cap & SUPPORTED_Pause)
result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
if (cap & SUPPORTED_Asym_Pause)
@@ -285,6 +295,7 @@ static u32 mcdi_to_ethtool_media(u32 media)
case MC_CMD_MEDIA_XFP:
case MC_CMD_MEDIA_SFP_PLUS:
+ case MC_CMD_MEDIA_QSFP_PLUS:
return PORT_FIBRE;
case MC_CMD_MEDIA_BASE_T:
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 5bdae8ed7c57..9ede32064685 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -28,6 +28,7 @@
#include <linux/vmalloc.h>
#include <linux/i2c.h>
#include <linux/mtd/mtd.h>
+#include <net/busy_poll.h>
#include "enum.h"
#include "bitfield.h"
@@ -249,6 +250,8 @@ struct efx_tx_queue {
unsigned int tso_packets;
unsigned int pushes;
unsigned int pio_packets;
+ /* Statistics to supplement MAC stats */
+ unsigned long tx_packets;
/* Members shared between paths and sometimes updated */
unsigned int empty_read_count ____cacheline_aligned_in_smp;
@@ -358,6 +361,8 @@ struct efx_rx_queue {
unsigned int recycle_count;
struct timer_list slow_fill;
unsigned int slow_fill_count;
+ /* Statistics to supplement MAC stats */
+ unsigned long rx_packets;
};
enum efx_sync_events_state {
@@ -383,6 +388,8 @@ enum efx_sync_events_state {
* @irq_moderation: IRQ moderation value (in hardware ticks)
* @napi_dev: Net device used with NAPI
* @napi_str: NAPI control structure
+ * @state: state for NAPI vs busy polling
+ * @state_lock: lock protecting @state
* @eventq: Event queue buffer
* @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer
@@ -420,6 +427,22 @@ struct efx_channel {
unsigned int irq_moderation;
struct net_device *napi_dev;
struct napi_struct napi_str;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ unsigned int state;
+ spinlock_t state_lock;
+#define EFX_CHANNEL_STATE_IDLE 0
+#define EFX_CHANNEL_STATE_NAPI (1 << 0) /* NAPI owns this channel */
+#define EFX_CHANNEL_STATE_POLL (1 << 1) /* poll owns this channel */
+#define EFX_CHANNEL_STATE_DISABLED (1 << 2) /* channel is disabled */
+#define EFX_CHANNEL_STATE_NAPI_YIELD (1 << 3) /* NAPI yielded this channel */
+#define EFX_CHANNEL_STATE_POLL_YIELD (1 << 4) /* poll yielded this channel */
+#define EFX_CHANNEL_OWNED \
+ (EFX_CHANNEL_STATE_NAPI | EFX_CHANNEL_STATE_POLL)
+#define EFX_CHANNEL_LOCKED \
+ (EFX_CHANNEL_OWNED | EFX_CHANNEL_STATE_DISABLED)
+#define EFX_CHANNEL_USER_PEND \
+ (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_POLL_YIELD)
+#endif /* CONFIG_NET_RX_BUSY_POLL */
struct efx_special_buffer eventq;
unsigned int eventq_mask;
unsigned int eventq_read_ptr;
@@ -453,6 +476,135 @@ struct efx_channel {
u32 sync_timestamp_minor;
};
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void efx_channel_init_lock(struct efx_channel *channel)
+{
+ spin_lock_init(&channel->state_lock);
+}
+
+/* Called from the device poll routine to get ownership of a channel. */
+static inline bool efx_channel_lock_napi(struct efx_channel *channel)
+{
+ bool rc = true;
+
+ spin_lock_bh(&channel->state_lock);
+ if (channel->state & EFX_CHANNEL_LOCKED) {
+ WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
+ channel->state |= EFX_CHANNEL_STATE_NAPI_YIELD;
+ rc = false;
+ } else {
+ /* we don't care if someone yielded */
+ channel->state = EFX_CHANNEL_STATE_NAPI;
+ }
+ spin_unlock_bh(&channel->state_lock);
+ return rc;
+}
+
+static inline void efx_channel_unlock_napi(struct efx_channel *channel)
+{
+ spin_lock_bh(&channel->state_lock);
+ WARN_ON(channel->state &
+ (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_YIELD));
+
+ channel->state &= EFX_CHANNEL_STATE_DISABLED;
+ spin_unlock_bh(&channel->state_lock);
+}
+
+/* Called from efx_busy_poll(). */
+static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+{
+ bool rc = true;
+
+ spin_lock_bh(&channel->state_lock);
+ if ((channel->state & EFX_CHANNEL_LOCKED)) {
+ channel->state |= EFX_CHANNEL_STATE_POLL_YIELD;
+ rc = false;
+ } else {
+ /* preserve yield marks */
+ channel->state |= EFX_CHANNEL_STATE_POLL;
+ }
+ spin_unlock_bh(&channel->state_lock);
+ return rc;
+}
+
+/* Returns true if NAPI tried to get the channel while it was locked. */
+static inline void efx_channel_unlock_poll(struct efx_channel *channel)
+{
+ spin_lock_bh(&channel->state_lock);
+ WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI);
+
+ /* will reset state to idle, unless channel is disabled */
+ channel->state &= EFX_CHANNEL_STATE_DISABLED;
+ spin_unlock_bh(&channel->state_lock);
+}
+
+/* True if a socket is polling, even if it did not get the lock. */
+static inline bool efx_channel_busy_polling(struct efx_channel *channel)
+{
+ WARN_ON(!(channel->state & EFX_CHANNEL_OWNED));
+ return channel->state & EFX_CHANNEL_USER_PEND;
+}
+
+static inline void efx_channel_enable(struct efx_channel *channel)
+{
+ spin_lock_bh(&channel->state_lock);
+ channel->state = EFX_CHANNEL_STATE_IDLE;
+ spin_unlock_bh(&channel->state_lock);
+}
+
+/* False if the channel is currently owned. */
+static inline bool efx_channel_disable(struct efx_channel *channel)
+{
+ bool rc = true;
+
+ spin_lock_bh(&channel->state_lock);
+ if (channel->state & EFX_CHANNEL_OWNED)
+ rc = false;
+ channel->state |= EFX_CHANNEL_STATE_DISABLED;
+ spin_unlock_bh(&channel->state_lock);
+
+ return rc;
+}
+
+#else /* CONFIG_NET_RX_BUSY_POLL */
+
+static inline void efx_channel_init_lock(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_lock_napi(struct efx_channel *channel)
+{
+ return true;
+}
+
+static inline void efx_channel_unlock_napi(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_lock_poll(struct efx_channel *channel)
+{
+ return false;
+}
+
+static inline void efx_channel_unlock_poll(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_busy_polling(struct efx_channel *channel)
+{
+ return false;
+}
+
+static inline void efx_channel_enable(struct efx_channel *channel)
+{
+}
+
+static inline bool efx_channel_disable(struct efx_channel *channel)
+{
+ return true;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
/**
* struct efx_msi_context - Context for each MSI
* @efx: The associated NIC
@@ -777,6 +929,7 @@ struct vfdi_status;
* interrupt has occurred.
* @stats_lock: Statistics update lock. Must be held when calling
* efx_nic_type::{update,start,stop}_stats.
+ * @n_rx_noskb_drops: Count of RX packets dropped due to failure to allocate an skb
*
* This is stored in the private area of the &struct net_device.
*/
@@ -930,6 +1083,7 @@ struct efx_nic {
spinlock_t biu_lock;
int last_irq_cpu;
spinlock_t stats_lock;
+ atomic_t n_rx_noskb_drops;
};
static inline int efx_dev_registered(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index d3ad8ed8d901..60f85149fc4c 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -135,6 +135,13 @@ enum {
/* Size and alignment of buffer table entries (same) */
#define EFX_BUF_SIZE EFX_PAGE_SIZE
+/* NIC-generic software stats */
+enum {
+ GENERIC_STAT_rx_noskb_drops,
+ GENERIC_STAT_rx_nodesc_trunc,
+ GENERIC_STAT_COUNT
+};
+
/**
* struct falcon_board_type - board operations and type information
* @id: Board type id, as found in NVRAM
@@ -205,7 +212,7 @@ static inline bool falcon_spi_present(const struct falcon_spi_device *spi)
}
enum {
- FALCON_STAT_tx_bytes,
+ FALCON_STAT_tx_bytes = GENERIC_STAT_COUNT,
FALCON_STAT_tx_packets,
FALCON_STAT_tx_pause,
FALCON_STAT_tx_control,
@@ -290,7 +297,7 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
}
enum {
- SIENA_STAT_tx_bytes,
+ SIENA_STAT_tx_bytes = GENERIC_STAT_COUNT,
SIENA_STAT_tx_good_bytes,
SIENA_STAT_tx_bad_bytes,
SIENA_STAT_tx_packets,
@@ -361,7 +368,7 @@ struct siena_nic_data {
};
enum {
- EF10_STAT_tx_bytes,
+ EF10_STAT_tx_bytes = GENERIC_STAT_COUNT,
EF10_STAT_tx_packets,
EF10_STAT_tx_pause,
EF10_STAT_tx_control,
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 48588ddf81b0..c0ad95d2f63d 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -462,6 +462,7 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
skb_record_rx_queue(skb, channel->rx_queue.core_index);
+ skb_mark_napi_id(skb, &channel->napi_str);
gro_result = napi_gro_frags(napi);
if (gro_result != GRO_DROP)
channel->irq_mod_score += 2;
@@ -480,8 +481,10 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
skb = netdev_alloc_skb(efx->net_dev,
efx->rx_ip_align + efx->rx_prefix_size +
hdr_len);
- if (unlikely(skb == NULL))
+ if (unlikely(skb == NULL)) {
+ atomic_inc(&efx->n_rx_noskb_drops);
return NULL;
+ }
EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len);
@@ -518,6 +521,8 @@ static struct sk_buff *efx_rx_mk_skb(struct efx_channel *channel,
/* Move past the ethernet header */
skb->protocol = eth_type_trans(skb, efx->net_dev);
+ skb_mark_napi_id(skb, &channel->napi_str);
+
return skb;
}
@@ -528,6 +533,8 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
struct efx_rx_buffer *rx_buf;
+ rx_queue->rx_packets++;
+
rx_buf = efx_rx_buffer(rx_queue, index);
rx_buf->flags |= flags;
@@ -662,7 +669,8 @@ void __efx_rx_packet(struct efx_channel *channel)
if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
- if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb)
+ if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb &&
+ !efx_channel_busy_polling(channel))
efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh);
else
efx_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags);
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 0fc5baef45b1..10b6173d557d 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -188,7 +188,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,
schedule_timeout_uninterruptible(wait);
efx_for_each_channel(channel, efx) {
- napi_disable(&channel->napi_str);
+ efx_stop_eventq(channel);
if (channel->eventq_read_ptr !=
read_ptr[channel->channel]) {
set_bit(channel->channel, &napi_ran);
@@ -200,8 +200,7 @@ static int efx_test_eventq_irq(struct efx_nic *efx,
if (efx_nic_event_test_irq_cpu(channel) >= 0)
clear_bit(channel->channel, &int_pend);
}
- napi_enable(&channel->napi_str);
- efx_nic_eventq_read_ack(channel);
+ efx_start_eventq(channel);
}
wait *= 2;
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 50ffefed492c..ae696855f21a 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -424,6 +424,8 @@ static void siena_remove_nic(struct efx_nic *efx)
{ #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
#define SIENA_OTHER_STAT(ext_name) \
[SIENA_STAT_ ## ext_name] = { #ext_name, 0, 0 }
+#define GENERIC_SW_STAT(ext_name) \
+ [GENERIC_STAT_ ## ext_name] = { #ext_name, 0, 0 }
static const struct efx_hw_stat_desc siena_stat_desc[SIENA_STAT_COUNT] = {
SIENA_DMA_STAT(tx_bytes, TX_BYTES),
@@ -483,6 +485,8 @@ static const struct efx_hw_stat_desc siena_stat_desc[SIENA_STAT_COUNT] = {
SIENA_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
SIENA_DMA_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS),
SIENA_DMA_STAT(rx_nodesc_drop_cnt, RX_NODESC_DROPS),
+ GENERIC_SW_STAT(rx_nodesc_trunc),
+ GENERIC_SW_STAT(rx_noskb_drops),
};
static const unsigned long siena_stat_mask[] = {
[0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL,
@@ -528,6 +532,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
efx_update_diff_stat(&stats[SIENA_STAT_rx_good_bytes],
stats[SIENA_STAT_rx_bytes] -
stats[SIENA_STAT_rx_bad_bytes]);
+ efx_update_sw_stats(efx, stats);
return 0;
}
@@ -554,7 +559,9 @@ static size_t siena_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
core_stats->tx_packets = stats[SIENA_STAT_tx_packets];
core_stats->rx_bytes = stats[SIENA_STAT_rx_bytes];
core_stats->tx_bytes = stats[SIENA_STAT_tx_bytes];
- core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt];
+ core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt] +
+ stats[GENERIC_STAT_rx_nodesc_trunc] +
+ stats[GENERIC_STAT_rx_noskb_drops];
core_stats->multicast = stats[SIENA_STAT_rx_multicast];
core_stats->collisions = stats[SIENA_STAT_tx_collision];
core_stats->rx_length_errors =
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index ede8dcca0ff3..65c220f8661d 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -189,18 +189,6 @@ struct efx_short_copy_buffer {
u8 buf[L1_CACHE_BYTES];
};
-/* Copy in explicit 64-bit writes. */
-static void efx_memcpy_64(void __iomem *dest, void *src, size_t len)
-{
- u64 *src64 = src;
- u64 __iomem *dest64 = dest;
- size_t l64 = len / 8;
- size_t i;
-
- for (i = 0; i < l64; i++)
- writeq(src64[i], &dest64[i]);
-}
-
/* Copy to PIO, respecting that writes to PIO buffers must be dword aligned.
* Advances piobuf pointer. Leaves additional data in the copy buffer.
*/
@@ -210,7 +198,7 @@ static void efx_memcpy_toio_aligned(struct efx_nic *efx, u8 __iomem **piobuf,
{
int block_len = len & ~(sizeof(copy_buf->buf) - 1);
- efx_memcpy_64(*piobuf, data, block_len);
+ __iowrite64_copy(*piobuf, data, block_len >> 3);
*piobuf += block_len;
len -= block_len;
@@ -242,7 +230,8 @@ static void efx_memcpy_toio_aligned_cb(struct efx_nic *efx, u8 __iomem **piobuf,
if (copy_buf->used < sizeof(copy_buf->buf))
return;
- efx_memcpy_64(*piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+ __iowrite64_copy(*piobuf, copy_buf->buf,
+ sizeof(copy_buf->buf) >> 3);
*piobuf += sizeof(copy_buf->buf);
data += copy_to_buf;
len -= copy_to_buf;
@@ -257,7 +246,8 @@ static void efx_flush_copy_buffer(struct efx_nic *efx, u8 __iomem *piobuf,
{
/* if there's anything in it, write the whole buffer, including junk */
if (copy_buf->used)
- efx_memcpy_64(piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+ __iowrite64_copy(piobuf, copy_buf->buf,
+ sizeof(copy_buf->buf) >> 3);
}
/* Traverse skb structure and copy fragments in to PIO buffer.
@@ -316,8 +306,8 @@ efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
*/
BUILD_BUG_ON(L1_CACHE_BYTES >
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
- efx_memcpy_64(tx_queue->piobuf, skb->data,
- ALIGN(skb->len, L1_CACHE_BYTES));
+ __iowrite64_copy(tx_queue->piobuf, skb->data,
+ ALIGN(skb->len, L1_CACHE_BYTES) >> 3);
}
EFX_POPULATE_QWORD_5(buffer->option,
@@ -452,6 +442,8 @@ finish_packet:
/* Pass off to hardware */
efx_nic_push_buffers(tx_queue);
+ tx_queue->tx_packets++;
+
efx_tx_maybe_stop_queue(tx_queue);
return NETDEV_TX_OK;
@@ -1245,6 +1237,8 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
++tx_queue->tso_packets;
+ ++tx_queue->tx_packets;
+
return 0;
}
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 7984ad05357d..7a254da85dd7 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -1384,7 +1384,7 @@ static void ioc3_remove_one(struct pci_dev *pdev)
*/
}
-static DEFINE_PCI_DEVICE_TABLE(ioc3_pci_tbl) = {
+static const struct pci_device_id ioc3_pci_tbl[] = {
{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID },
{ 0 }
};
diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c
index 7daa7d433099..7426f8b21252 100644
--- a/drivers/net/ethernet/silan/sc92031.c
+++ b/drivers/net/ethernet/silan/sc92031.c
@@ -1561,7 +1561,7 @@ out:
return 0;
}
-static DEFINE_PCI_DEVICE_TABLE(sc92031_pci_device_id_table) = {
+static const struct pci_device_id sc92031_pci_device_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
{ PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
{ PCI_DEVICE(0x1088, 0x2031) },
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c
index a86339903b9b..27be6c869315 100644
--- a/drivers/net/ethernet/sis/sis190.c
+++ b/drivers/net/ethernet/sis/sis190.c
@@ -330,7 +330,7 @@ static const struct {
{ "SiS 191 PCI Gigabit Ethernet adapter" },
};
-static DEFINE_PCI_DEVICE_TABLE(sis190_pci_tbl) = {
+static const struct pci_device_id sis190_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
{ 0, },
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index 6072f093e6b4..fd812d2e5e1c 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -106,7 +106,8 @@ static const char * card_names[] = {
"SiS 900 PCI Fast Ethernet",
"SiS 7016 PCI Fast Ethernet"
};
-static DEFINE_PCI_DEVICE_TABLE(sis900_pci_tbl) = {
+
+static const struct pci_device_id sis900_pci_tbl[] = {
{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900},
{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016,
@@ -2258,7 +2259,6 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
case IF_PORT_100BASEFX: /* 100BaseFx */
/* These Modes are not supported (are they?)*/
return -EOPNOTSUPP;
- break;
default:
return -EINVAL;
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c
index 8ae1f8a7bf38..443f1da9fc9e 100644
--- a/drivers/net/ethernet/smsc/epic100.c
+++ b/drivers/net/ethernet/smsc/epic100.c
@@ -173,7 +173,7 @@ static const struct epic_chip_info pci_id_tbl[] = {
};
-static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = {
+static const struct pci_device_id epic_pci_tbl[] = {
{ 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 },
{ 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 },
{ 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 1c44e67c3067..9778cba9fc74 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -730,7 +730,7 @@ static void smc911x_phy_detect(struct net_device *dev)
lp->phy_type = id1 << 16 | id2;
}
- DBG(SMC_DEBUG_MISC, dev, "phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n",
+ DBG(SMC_DEBUG_MISC, dev, "phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%x\n",
id1, id2, lp->mii.phy_id);
}
diff --git a/drivers/net/ethernet/smsc/smsc911x.h b/drivers/net/ethernet/smsc/smsc911x.h
index 23953957fed8..54d648920a1b 100644
--- a/drivers/net/ethernet/smsc/smsc911x.h
+++ b/drivers/net/ethernet/smsc/smsc911x.h
@@ -51,7 +51,7 @@
#ifdef CONFIG_DEBUG_SPINLOCK
#define SMSC_ASSERT_MAC_LOCK(pdata) \
- WARN_ON(!spin_is_locked(&pdata->mac_lock))
+ WARN_ON_SMP(!spin_is_locked(&pdata->mac_lock))
#else
#define SMSC_ASSERT_MAC_LOCK(pdata) do {} while (0)
#endif /* CONFIG_DEBUG_SPINLOCK */
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index d3b967aff9e0..4a90cdae5444 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -83,7 +83,7 @@ struct smsc9420_pdata {
int last_carrier;
};
-static DEFINE_PCI_DEVICE_TABLE(smsc9420_id_table) = {
+static const struct pci_device_id smsc9420_id_table[] = {
{ PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 74610f3aca9e..de507c32036c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -368,34 +368,36 @@ struct stmmac_dma_ops {
void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
};
+struct mac_device_info;
+
struct stmmac_ops {
/* MAC core initialization */
- void (*core_init) (void __iomem *ioaddr, int mtu);
+ void (*core_init)(struct mac_device_info *hw, int mtu);
/* Enable and verify that the IPC module is supported */
- int (*rx_ipc) (void __iomem *ioaddr);
+ int (*rx_ipc)(struct mac_device_info *hw);
/* Dump MAC registers */
- void (*dump_regs) (void __iomem *ioaddr);
+ void (*dump_regs)(struct mac_device_info *hw);
/* Handle extra events on specific interrupts hw dependent */
- int (*host_irq_status) (void __iomem *ioaddr,
- struct stmmac_extra_stats *x);
+ int (*host_irq_status)(struct mac_device_info *hw,
+ struct stmmac_extra_stats *x);
/* Multicast filter setting */
- void (*set_filter) (struct net_device *dev, int id);
+ void (*set_filter)(struct mac_device_info *hw, struct net_device *dev);
/* Flow control setting */
- void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
- unsigned int fc, unsigned int pause_time);
+ void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex,
+ unsigned int fc, unsigned int pause_time);
/* Set power management mode (e.g. magic frame) */
- void (*pmt) (void __iomem *ioaddr, unsigned long mode);
+ void (*pmt)(struct mac_device_info *hw, unsigned long mode);
/* Set/Get Unicast MAC addresses */
- void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
- unsigned int reg_n);
- void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
- unsigned int reg_n);
- void (*set_eee_mode) (void __iomem *ioaddr);
- void (*reset_eee_mode) (void __iomem *ioaddr);
- void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
- void (*set_eee_pls) (void __iomem *ioaddr, int link);
- void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
- void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
+ void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+ unsigned int reg_n);
+ void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+ unsigned int reg_n);
+ void (*set_eee_mode)(struct mac_device_info *hw);
+ void (*reset_eee_mode)(struct mac_device_info *hw);
+ void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
+ void (*set_eee_pls)(struct mac_device_info *hw, int link);
+ void (*ctrl_ane)(struct mac_device_info *hw, bool restart);
+ void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
};
struct stmmac_hwtimestamp {
@@ -439,9 +441,14 @@ struct mac_device_info {
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
unsigned int synopsys_uid;
+ void __iomem *pcsr; /* vpointer to device CSRs */
+ int multicast_filter_bins;
+ int unicast_filter_entries;
+ int mcast_bits_log2;
};
-struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+ int perfect_uc_entries);
struct mac_device_info *dwmac100_setup(void __iomem *ioaddr);
void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index fd8a217556a1..ec632e666c56 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -20,7 +20,9 @@
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/stmmac.h>
+#include "stmmac.h"
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
@@ -34,6 +36,7 @@ struct socfpga_dwmac {
u32 reg_shift;
struct device *dev;
struct regmap *sys_mgr_base_addr;
+ struct reset_control *stmmac_rst;
};
static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
@@ -43,6 +46,13 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
u32 reg_offset, reg_shift;
int ret;
+ dwmac->stmmac_rst = devm_reset_control_get(dev,
+ STMMAC_RESOURCE_NAME);
+ if (IS_ERR(dwmac->stmmac_rst)) {
+ dev_info(dev, "Could not get reset control!\n");
+ return -EINVAL;
+ }
+
dwmac->interface = of_get_phy_mode(np);
sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
@@ -125,6 +135,65 @@ static void *socfpga_dwmac_probe(struct platform_device *pdev)
return dwmac;
}
+static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct socfpga_dwmac *dwmac = priv;
+
+ /* On socfpga platform exit, assert and hold reset to the
+ * enet controller - the default state after a hard reset.
+ */
+ if (dwmac->stmmac_rst)
+ reset_control_assert(dwmac->stmmac_rst);
+}
+
+static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
+{
+ struct socfpga_dwmac *dwmac = priv;
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct stmmac_priv *stpriv = NULL;
+ int ret = 0;
+
+ if (ndev)
+ stpriv = netdev_priv(ndev);
+
+ /* Assert reset to the enet controller before changing the phy mode */
+ if (dwmac->stmmac_rst)
+ reset_control_assert(dwmac->stmmac_rst);
+
+ /* Setup the phy mode in the system manager registers according to
+ * devicetree configuration
+ */
+ ret = socfpga_dwmac_setup(dwmac);
+
+ /* Deassert reset for the phy configuration to be sampled by
+ * the enet controller, and operation to start in requested mode
+ */
+ if (dwmac->stmmac_rst)
+ reset_control_deassert(dwmac->stmmac_rst);
+
+ /* Before the enet controller is suspended, the phy is suspended.
+ * This causes the phy clock to be gated. The enet controller is
+ * resumed before the phy, so the clock is still gated "off" when
+ * the enet controller is resumed. This code makes sure the phy
+ * is "resumed" before reinitializing the enet controller since
+ * the enet controller depends on an active phy clock to complete
+ * a DMA reset. A DMA reset will "time out" if executed
+ * with no phy clock input on the Synopsys enet controller.
+ * Verified through Synopsys Case #8000711656.
+ *
+ * Note that the phy clock is also gated when the phy is isolated.
+ * Phy "suspend" and "isolate" controls are located in phy basic
+ * control register 0, and can be modified by the phy driver
+ * framework.
+ */
+ if (stpriv && stpriv->phydev)
+ phy_resume(stpriv->phydev);
+
+ return ret;
+}
+
const struct stmmac_of_data socfpga_gmac_data = {
.setup = socfpga_dwmac_probe,
+ .init = socfpga_dwmac_init,
+ .exit = socfpga_dwmac_exit,
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
index f37d90f114f5..71b5419256c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -87,7 +87,7 @@ enum power_event {
(reg * 8))
#define GMAC_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \
(reg * 8))
-#define GMAC_MAX_PERFECT_ADDRESSES 32
+#define GMAC_MAX_PERFECT_ADDRESSES 1
/* PCS registers (AN/TBI/SGMII/RGMII) offset */
#define GMAC_AN_CTRL 0x000000c0 /* AN control */
@@ -261,6 +261,7 @@ enum rtc_control {
#define GMAC_MMC_RX_INTR 0x104
#define GMAC_MMC_TX_INTR 0x108
#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208
+#define GMAC_EXTHASH_BASE 0x500
extern const struct stmmac_dma_ops dwmac1000_dma_ops;
#endif /* __DWMAC1000_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 9d3748361a1e..d8ef18786a1c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -32,8 +32,9 @@
#include <asm/io.h>
#include "dwmac1000.h"
-static void dwmac1000_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL);
value |= GMAC_CORE_INIT;
if (mtu > 1500)
@@ -52,8 +53,9 @@ static void dwmac1000_core_init(void __iomem *ioaddr, int mtu)
#endif
}
-static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONTROL);
value |= GMAC_CONTROL_IPC;
@@ -64,8 +66,9 @@ static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
return !!(value & GMAC_CONTROL_IPC);
}
-static void dwmac1000_dump_regs(void __iomem *ioaddr)
+static void dwmac1000_dump_regs(struct mac_device_info *hw)
{
+ void __iomem *ioaddr = hw->pcsr;
int i;
pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
@@ -76,69 +79,98 @@ static void dwmac1000_dump_regs(void __iomem *ioaddr)
}
}
-static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
+ unsigned char *addr,
unsigned int reg_n)
{
+ void __iomem *ioaddr = hw->pcsr;
stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
GMAC_ADDR_LOW(reg_n));
}
-static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
+ unsigned char *addr,
unsigned int reg_n)
{
+ void __iomem *ioaddr = hw->pcsr;
stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
GMAC_ADDR_LOW(reg_n));
}
-static void dwmac1000_set_filter(struct net_device *dev, int id)
+static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
+ int mcbitslog2)
+{
+ int numhashregs, regs;
+
+ switch (mcbitslog2) {
+ case 6:
+ writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW);
+ writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH);
+ return;
+ break;
+ case 7:
+ numhashregs = 4;
+ break;
+ case 8:
+ numhashregs = 8;
+ break;
+ default:
+ pr_debug("STMMAC: err in setting mulitcast filter\n");
+ return;
+ break;
+ }
+ for (regs = 0; regs < numhashregs; regs++)
+ writel(mcfilterbits[regs],
+ ioaddr + GMAC_EXTHASH_BASE + regs * 4);
+}
+
+static void dwmac1000_set_filter(struct mac_device_info *hw,
+ struct net_device *dev)
{
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
unsigned int value = 0;
- unsigned int perfect_addr_number;
+ unsigned int perfect_addr_number = hw->unicast_filter_entries;
+ u32 mc_filter[2];
+ int mcbitslog2 = hw->mcast_bits_log2;
pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
netdev_mc_count(dev), netdev_uc_count(dev));
- if (dev->flags & IFF_PROMISC)
+ memset(mc_filter, 0, sizeof(mc_filter));
+
+ if (dev->flags & IFF_PROMISC) {
value = GMAC_FRAME_FILTER_PR;
- else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE)
- || (dev->flags & IFF_ALLMULTI)) {
+ } else if (dev->flags & IFF_ALLMULTI) {
value = GMAC_FRAME_FILTER_PM; /* pass all multi */
- writel(0xffffffff, ioaddr + GMAC_HASH_HIGH);
- writel(0xffffffff, ioaddr + GMAC_HASH_LOW);
} else if (!netdev_mc_empty(dev)) {
- u32 mc_filter[2];
struct netdev_hw_addr *ha;
/* Hash filter for multicast */
value = GMAC_FRAME_FILTER_HMC;
- memset(mc_filter, 0, sizeof(mc_filter));
netdev_for_each_mc_addr(ha, dev) {
- /* The upper 6 bits of the calculated CRC are used to
- * index the contens of the hash table
+ /* The upper n bits of the calculated CRC are used to
+ * index the contents of the hash table. The number of
+ * bits used depends on the hardware configuration
+ * selected at core configuration time.
*/
- int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26;
+ int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
+ ETH_ALEN)) >>
+ (32 - mcbitslog2);
/* The most significant bit determines the register to
* use (H/L) while the other 5 bits determine the bit
* within the register.
*/
mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
}
- writel(mc_filter[0], ioaddr + GMAC_HASH_LOW);
- writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH);
}
- /* Extra 16 regs are available in cores newer than the 3.40. */
- if (id > DWMAC_CORE_3_40)
- perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES;
- else
- perfect_addr_number = GMAC_MAX_PERFECT_ADDRESSES / 2;
+ dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
/* Handle multiple unicast addresses (perfect filtering) */
if (netdev_uc_count(dev) > perfect_addr_number)
- /* Switch to promiscuous mode if more than 16 addrs
- * are required
+ /* Switch to promiscuous mode if more than unicast
+ * addresses are requested than supported by hardware.
*/
value |= GMAC_FRAME_FILTER_PR;
else {
@@ -146,7 +178,9 @@ static void dwmac1000_set_filter(struct net_device *dev, int id)
struct netdev_hw_addr *ha;
netdev_for_each_uc_addr(ha, dev) {
- dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
+ stmmac_get_mac_addr(ioaddr, ha->addr,
+ GMAC_ADDR_HIGH(reg),
+ GMAC_ADDR_LOW(reg));
reg++;
}
}
@@ -156,15 +190,13 @@ static void dwmac1000_set_filter(struct net_device *dev, int id)
value |= GMAC_FRAME_FILTER_RA;
#endif
writel(value, ioaddr + GMAC_FRAME_FILTER);
-
- pr_debug("\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n",
- readl(ioaddr + GMAC_FRAME_FILTER),
- readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
}
-static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+
+static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
unsigned int fc, unsigned int pause_time)
{
+ void __iomem *ioaddr = hw->pcsr;
unsigned int flow = 0;
pr_debug("GMAC Flow-Control:\n");
@@ -185,8 +217,9 @@ static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
writel(flow, ioaddr + GMAC_FLOW_CTRL);
}
-static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
{
+ void __iomem *ioaddr = hw->pcsr;
unsigned int pmt = 0;
if (mode & WAKE_MAGIC) {
@@ -201,9 +234,10 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
writel(pmt, ioaddr + GMAC_PMT);
}
-static int dwmac1000_irq_status(void __iomem *ioaddr,
+static int dwmac1000_irq_status(struct mac_device_info *hw,
struct stmmac_extra_stats *x)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
int ret = 0;
@@ -268,8 +302,9 @@ static int dwmac1000_irq_status(void __iomem *ioaddr,
return ret;
}
-static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value;
/* Enable the link status receive on RGMII, SGMII ore SMII
@@ -281,8 +316,9 @@ static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
writel(value, ioaddr + LPI_CTRL_STATUS);
}
-static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value;
value = readl(ioaddr + LPI_CTRL_STATUS);
@@ -290,8 +326,9 @@ static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
writel(value, ioaddr + LPI_CTRL_STATUS);
}
-static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value;
value = readl(ioaddr + LPI_CTRL_STATUS);
@@ -304,8 +341,9 @@ static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
writel(value, ioaddr + LPI_CTRL_STATUS);
}
-static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
{
+ void __iomem *ioaddr = hw->pcsr;
int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
/* Program the timers in the LPI timer control register:
@@ -318,8 +356,9 @@ static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
writel(value, ioaddr + LPI_TIMER_CTRL);
}
-static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
+static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart)
{
+ void __iomem *ioaddr = hw->pcsr;
/* auto negotiation enable and External Loopback enable */
u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
@@ -329,8 +368,9 @@ static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
writel(value, ioaddr + GMAC_AN_CTRL);
}
-static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
+static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_ANE_ADV);
if (value & GMAC_ANE_FD)
@@ -368,7 +408,8 @@ static const struct stmmac_ops dwmac1000_ops = {
.get_adv = dwmac1000_get_adv,
};
-struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
+struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+ int perfect_uc_entries)
{
struct mac_device_info *mac;
u32 hwid = readl(ioaddr + GMAC_VERSION);
@@ -377,6 +418,14 @@ struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
if (!mac)
return NULL;
+ mac->pcsr = ioaddr;
+ mac->multicast_filter_bins = mcbins;
+ mac->unicast_filter_entries = perfect_uc_entries;
+ mac->mcast_bits_log2 = 0;
+
+ if (mac->multicast_filter_bins)
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
mac->mac = &dwmac1000_ops;
mac->dma = &dwmac1000_dma_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
index 2ff767bcfdd0..f8dd773f246c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
@@ -32,8 +32,9 @@
#include <asm/io.h>
#include "dwmac100.h"
-static void dwmac100_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac100_core_init(struct mac_device_info *hw, int mtu)
{
+ void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + MAC_CONTROL);
writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
@@ -43,8 +44,9 @@ static void dwmac100_core_init(void __iomem *ioaddr, int mtu)
#endif
}
-static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
+static void dwmac100_dump_mac_regs(struct mac_device_info *hw)
{
+ void __iomem *ioaddr = hw->pcsr;
pr_info("\t----------------------------------------------\n"
"\t DWMAC 100 CSR (base addr = 0x%p)\n"
"\t----------------------------------------------\n", ioaddr);
@@ -66,30 +68,35 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
readl(ioaddr + MAC_VLAN2));
}
-static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac100_rx_ipc_enable(struct mac_device_info *hw)
{
return 0;
}
-static int dwmac100_irq_status(void __iomem *ioaddr,
+static int dwmac100_irq_status(struct mac_device_info *hw,
struct stmmac_extra_stats *x)
{
return 0;
}
-static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_set_umac_addr(struct mac_device_info *hw,
+ unsigned char *addr,
unsigned int reg_n)
{
+ void __iomem *ioaddr = hw->pcsr;
stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
}
-static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_get_umac_addr(struct mac_device_info *hw,
+ unsigned char *addr,
unsigned int reg_n)
{
+ void __iomem *ioaddr = hw->pcsr;
stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
}
-static void dwmac100_set_filter(struct net_device *dev, int id)
+static void dwmac100_set_filter(struct mac_device_info *hw,
+ struct net_device *dev)
{
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
u32 value = readl(ioaddr + MAC_CONTROL);
@@ -137,9 +144,10 @@ static void dwmac100_set_filter(struct net_device *dev, int id)
writel(value, ioaddr + MAC_CONTROL);
}
-static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
unsigned int fc, unsigned int pause_time)
{
+ void __iomem *ioaddr = hw->pcsr;
unsigned int flow = MAC_FLOW_CTRL_ENABLE;
if (duplex)
@@ -148,7 +156,7 @@ static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
}
/* No PMT module supported on ST boards with this Eth chip. */
-static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode)
{
return;
}
@@ -175,6 +183,7 @@ struct mac_device_info *dwmac100_setup(void __iomem *ioaddr)
pr_info("\tDWMAC100\n");
+ mac->pcsr = ioaddr;
mac->mac = &dwmac100_ops;
mac->dma = &dwmac100_dma_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index c62e67f3c2f0..9af50bae4dde 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -262,7 +262,7 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
/* Get and convert ADV/LP_ADV from the HW AN registers */
if (priv->hw->mac->get_adv)
- priv->hw->mac->get_adv(priv->ioaddr, &adv);
+ priv->hw->mac->get_adv(priv->hw, &adv);
else
return -EOPNOTSUPP; /* should never happen indeed */
@@ -350,7 +350,7 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
spin_lock(&priv->lock);
if (priv->hw->mac->ctrl_ane)
- priv->hw->mac->ctrl_ane(priv->ioaddr, 1);
+ priv->hw->mac->ctrl_ane(priv->hw, 1);
spin_unlock(&priv->lock);
}
@@ -464,7 +464,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
if (netif_running(netdev))
ret = phy_start_aneg(phy);
} else
- priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
+ priv->hw->mac->flow_ctrl(priv->hw, phy->duplex,
priv->flow_ctrl, priv->pause);
return ret;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 057a1208e594..08addd653728 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -233,7 +233,7 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
/* Check and enter in LPI mode */
if ((priv->dirty_tx == priv->cur_tx) &&
(priv->tx_path_in_lpi_mode == false))
- priv->hw->mac->set_eee_mode(priv->ioaddr);
+ priv->hw->mac->set_eee_mode(priv->hw);
}
/**
@@ -244,7 +244,7 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
*/
void stmmac_disable_eee_mode(struct stmmac_priv *priv)
{
- priv->hw->mac->reset_eee_mode(priv->ioaddr);
+ priv->hw->mac->reset_eee_mode(priv->hw);
del_timer_sync(&priv->eee_ctrl_timer);
priv->tx_path_in_lpi_mode = false;
}
@@ -298,7 +298,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
if (priv->eee_active) {
pr_debug("stmmac: disable EEE\n");
del_timer_sync(&priv->eee_ctrl_timer);
- priv->hw->mac->set_eee_timer(priv->ioaddr, 0,
+ priv->hw->mac->set_eee_timer(priv->hw, 0,
tx_lpi_timer);
}
priv->eee_active = 0;
@@ -313,12 +313,12 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
add_timer(&priv->eee_ctrl_timer);
- priv->hw->mac->set_eee_timer(priv->ioaddr,
+ priv->hw->mac->set_eee_timer(priv->hw,
STMMAC_DEFAULT_LIT_LS,
tx_lpi_timer);
} else
/* Set HW EEE according to the speed */
- priv->hw->mac->set_eee_pls(priv->ioaddr,
+ priv->hw->mac->set_eee_pls(priv->hw,
priv->phydev->link);
pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
@@ -693,7 +693,7 @@ static void stmmac_adjust_link(struct net_device *dev)
}
/* Flow Control operation */
if (phydev->pause)
- priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
+ priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
fc, pause_time);
if (phydev->speed != priv->speed) {
@@ -1531,8 +1531,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
static void stmmac_check_ether_addr(struct stmmac_priv *priv)
{
if (!is_valid_ether_addr(priv->dev->dev_addr)) {
- priv->hw->mac->get_umac_addr((void __iomem *)
- priv->dev->base_addr,
+ priv->hw->mac->get_umac_addr(priv->hw,
priv->dev->dev_addr, 0);
if (!is_valid_ether_addr(priv->dev->dev_addr))
eth_hw_addr_random(priv->dev);
@@ -1629,14 +1628,14 @@ static int stmmac_hw_setup(struct net_device *dev)
}
/* Copy the MAC addr into the HW */
- priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+ priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
/* If required, perform hw setup of the bus. */
if (priv->plat->bus_setup)
priv->plat->bus_setup(priv->ioaddr);
/* Initialize the MAC Core */
- priv->hw->mac->core_init(priv->ioaddr, dev->mtu);
+ priv->hw->mac->core_init(priv->hw, dev->mtu);
/* Enable the MAC Rx/Tx */
stmmac_set_mac(priv->ioaddr, true);
@@ -1662,7 +1661,7 @@ static int stmmac_hw_setup(struct net_device *dev)
/* Dump DMA/MAC registers */
if (netif_msg_hw(priv)) {
- priv->hw->mac->dump_regs(priv->ioaddr);
+ priv->hw->mac->dump_regs(priv->hw);
priv->hw->dma->dump_regs(priv->ioaddr);
}
priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
@@ -1677,7 +1676,7 @@ static int stmmac_hw_setup(struct net_device *dev)
}
if (priv->pcs && priv->hw->mac->ctrl_ane)
- priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+ priv->hw->mac->ctrl_ane(priv->hw, 0);
return 0;
}
@@ -2226,7 +2225,7 @@ static void stmmac_set_rx_mode(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
spin_lock(&priv->lock);
- priv->hw->mac->set_filter(dev, priv->synopsys_id);
+ priv->hw->mac->set_filter(priv->hw, dev);
spin_unlock(&priv->lock);
}
@@ -2316,8 +2315,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
/* To handle GMAC own interrupts */
if (priv->plat->has_gmac) {
- int status = priv->hw->mac->host_irq_status((void __iomem *)
- dev->base_addr,
+ int status = priv->hw->mac->host_irq_status(priv->hw,
&priv->xstats);
if (unlikely(status)) {
/* For LPI we need to save the tx status */
@@ -2600,7 +2598,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
/* Identify the MAC HW device */
if (priv->plat->has_gmac) {
priv->dev->priv_flags |= IFF_UNICAST_FLT;
- mac = dwmac1000_setup(priv->ioaddr);
+ mac = dwmac1000_setup(priv->ioaddr,
+ priv->plat->multicast_filter_bins,
+ priv->plat->unicast_filter_entries);
} else {
mac = dwmac100_setup(priv->ioaddr);
}
@@ -2649,7 +2649,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
/* To use alternate (extended) or normal descriptor structures */
stmmac_selec_desc_mode(priv);
- ret = priv->hw->mac->rx_ipc(priv->ioaddr);
+ ret = priv->hw->mac->rx_ipc(priv->hw);
if (!ret) {
pr_warn(" RX IPC Checksum Offload not configured.\n");
priv->plat->rx_coe = STMMAC_RX_COE_NONE;
@@ -2869,7 +2869,7 @@ int stmmac_suspend(struct net_device *ndev)
/* Enable Power down mode by programming the PMT regs */
if (device_may_wakeup(priv->device)) {
- priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+ priv->hw->mac->pmt(priv->hw, priv->wolopts);
priv->irq_wake = 1;
} else {
stmmac_set_mac(priv->ioaddr, false);
@@ -2878,6 +2878,10 @@ int stmmac_suspend(struct net_device *ndev)
clk_disable_unprepare(priv->stmmac_clk);
}
spin_unlock_irqrestore(&priv->lock, flags);
+
+ priv->oldlink = 0;
+ priv->speed = 0;
+ priv->oldduplex = -1;
return 0;
}
@@ -2898,7 +2902,7 @@ int stmmac_resume(struct net_device *ndev)
* from another devices (e.g. serial console).
*/
if (device_may_wakeup(priv->device)) {
- priv->hw->mac->pmt(priv->ioaddr, 0);
+ priv->hw->mac->pmt(priv->hw, 0);
priv->irq_wake = 0;
} else {
pinctrl_pm_select_default_state(priv->device);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 291608924849..655a23bbc451 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -170,7 +170,7 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
#define STMMAC_VENDOR_ID 0x700
#define STMMAC_DEVICE_ID 0x1108
-static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
+static const struct pci_device_id stmmac_id_table[] = {
{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
{}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index ea7a65be1f9a..bb524a932be4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -52,6 +52,59 @@ static const struct of_device_id stmmac_dt_ids[] = {
MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
#ifdef CONFIG_OF
+
+/* This function validates the number of Multicast filtering bins specified
+ * by the configuration through the device tree. The Synopsys GMAC supports
+ * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC
+ * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds
+ * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is
+ * invalid and will cause the filtering algorithm to use Multicast
+ * promiscuous mode.
+ */
+static int dwmac1000_validate_mcast_bins(int mcast_bins)
+{
+ int x = mcast_bins;
+
+ switch (x) {
+ case HASH_TABLE_SIZE:
+ case 128:
+ case 256:
+ break;
+ default:
+ x = 0;
+ pr_info("Hash table entries set to unexpected value %d",
+ mcast_bins);
+ break;
+ }
+ return x;
+}
+
+/* This function validates the number of Unicast address entries supported
+ * by a particular Synopsys 10/100/1000 controller. The Synopsys controller
+ * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter
+ * logic. This function validates a valid, supported configuration is
+ * selected, and defaults to 1 Unicast address if an unsupported
+ * configuration is selected.
+ */
+static int dwmac1000_validate_ucast_entries(int ucast_entries)
+{
+ int x = ucast_entries;
+
+ switch (x) {
+ case 1:
+ case 32:
+ case 64:
+ case 128:
+ break;
+ default:
+ x = 1;
+ pr_info("Unicast table entries set to unexpected value %d\n",
+ ucast_entries);
+ break;
+ }
+ return x;
+}
+
static int stmmac_probe_config_dt(struct platform_device *pdev,
struct plat_stmmacenet_data *plat,
const char **mac)
@@ -115,6 +168,12 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
*/
plat->maxmtu = JUMBO_LEN;
+ /* Set default value for multicast hash bins */
+ plat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+ /* Set default value for unicast filter entries */
+ plat->unicast_filter_entries = 1;
+
/*
* Currently only the properties needed on SPEAr600
* are provided. All other properties should be added
@@ -131,6 +190,14 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
* are clearly MTUs
*/
of_property_read_u32(np, "max-frame-size", &plat->maxmtu);
+ of_property_read_u32(np, "snps,multicast-filter-bins",
+ &plat->multicast_filter_bins);
+ of_property_read_u32(np, "snps,perfect-filter-entries",
+ &plat->unicast_filter_entries);
+ plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
+ plat->unicast_filter_entries);
+ plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
+ plat->multicast_filter_bins);
plat->has_gmac = 1;
plat->pmt = 1;
}
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index b9ac20f42651..37f87ff28f03 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -229,7 +229,7 @@ static u16 link_modes[] = {
CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */
};
-static DEFINE_PCI_DEVICE_TABLE(cas_pci_tbl) = {
+static const struct pci_device_id cas_pci_tbl[] = {
{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN,
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 79606f47a08e..8216be46540f 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -59,7 +59,7 @@ static void writeq(u64 val, void __iomem *reg)
}
#endif
-static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = {
+static const struct pci_device_id niu_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)},
{}
};
@@ -2584,7 +2584,6 @@ static int niu_determine_phy_disposition(struct niu *np)
break;
default:
return -EINVAL;
- break;
}
phy_addr_off = niu_atca_port_num[np->port];
break;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 102a66fc54a2..f7415b6bf141 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -85,7 +85,7 @@ MODULE_LICENSE("GPL");
#define GEM_MODULE_NAME "gem"
-static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = {
+static const struct pci_device_id gem_pci_tbl[] = {
{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c
index 0dbf46f08ed5..72c8525d5457 100644
--- a/drivers/net/ethernet/sun/sunhme.c
+++ b/drivers/net/ethernet/sun/sunhme.c
@@ -3172,7 +3172,7 @@ static void happy_meal_pci_remove(struct pci_dev *pdev)
free_netdev(net_dev);
}
-static DEFINE_PCI_DEVICE_TABLE(happymeal_pci_ids) = {
+static const struct pci_device_id happymeal_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) },
{ } /* Terminating entry */
};
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index d813bfb1a847..23c89ab5a6ad 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -32,6 +32,11 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+/* Heuristic for the number of times to exponentially backoff and
+ * retry sending an LDC trigger when EAGAIN is encountered
+ */
+#define VNET_MAX_RETRIES 10
+
/* Ordered from largest major to lowest */
static struct vio_version vnet_versions[] = {
{ .major = 1, .minor = 0 },
@@ -260,6 +265,7 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
.state = vio_dring_state,
};
int err, delay;
+ int retries = 0;
hdr.seq = dr->snd_nxt;
delay = 1;
@@ -272,6 +278,13 @@ static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
udelay(delay);
if ((delay <<= 1) > 128)
delay = 128;
+ if (retries++ > VNET_MAX_RETRIES) {
+ pr_info("ECONNRESET %x:%x:%x:%x:%x:%x\n",
+ port->raddr[0], port->raddr[1],
+ port->raddr[2], port->raddr[3],
+ port->raddr[4], port->raddr[5]);
+ err = -ECONNRESET;
+ }
} while (err == -EAGAIN);
return err;
@@ -475,8 +488,9 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)
return 0;
}
-static void maybe_tx_wakeup(struct vnet *vp)
+static void maybe_tx_wakeup(unsigned long param)
{
+ struct vnet *vp = (struct vnet *)param;
struct net_device *dev = vp->dev;
netif_tx_lock(dev);
@@ -573,8 +587,13 @@ static void vnet_event(void *arg, int event)
break;
}
spin_unlock(&vio->lock);
+ /* Kick off a tasklet to wake the queue. We cannot call
+ * maybe_tx_wakeup directly here because we could deadlock on
+ * netif_tx_lock() with dev_watchdog()
+ */
if (unlikely(tx_wakeup && err != -ECONNRESET))
- maybe_tx_wakeup(port->vp);
+ tasklet_schedule(&port->vp->vnet_tx_wakeup);
+
local_irq_restore(flags);
}
@@ -593,6 +612,7 @@ static int __vnet_tx_trigger(struct vnet_port *port)
.end_idx = (u32) -1,
};
int err, delay;
+ int retries = 0;
hdr.seq = dr->snd_nxt;
delay = 1;
@@ -605,6 +625,8 @@ static int __vnet_tx_trigger(struct vnet_port *port)
udelay(delay);
if ((delay <<= 1) > 128)
delay = 128;
+ if (retries++ > VNET_MAX_RETRIES)
+ break;
} while (err == -EAGAIN);
return err;
@@ -691,7 +713,15 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
}
- d->hdr.ack = VIO_ACK_ENABLE;
+ /* We don't rely on the ACKs to free the skb in vnet_start_xmit(),
+ * thus it is safe to not set VIO_ACK_ENABLE for each transmission:
+ * the protocol itself does not require it as long as the peer
+ * sends a VIO_SUBTYPE_ACK for VIO_DRING_STOPPED.
+ *
+ * An ACK for every packet in the ring is expensive as the
+ * sending of LDC messages is slow and affects performance.
+ */
+ d->hdr.ack = VIO_ACK_DISABLE;
d->size = len;
d->ncookies = port->tx_bufs[dr->prod].ncookies;
for (i = 0; i < d->ncookies; i++)
@@ -1046,6 +1076,7 @@ static struct vnet *vnet_new(const u64 *local_mac)
vp = netdev_priv(dev);
spin_lock_init(&vp->lock);
+ tasklet_init(&vp->vnet_tx_wakeup, maybe_tx_wakeup, (unsigned long)vp);
vp->dev = dev;
INIT_LIST_HEAD(&vp->port_list);
@@ -1105,6 +1136,7 @@ static void vnet_cleanup(void)
vp = list_first_entry(&vnet_list, struct vnet, list);
list_del(&vp->list);
dev = vp->dev;
+ tasklet_kill(&vp->vnet_tx_wakeup);
/* vio_unregister_driver() should have cleaned up port_list */
BUG_ON(!list_empty(&vp->port_list));
unregister_netdev(dev);
diff --git a/drivers/net/ethernet/sun/sunvnet.h b/drivers/net/ethernet/sun/sunvnet.h
index d347a5bf24b0..de5c2c64996f 100644
--- a/drivers/net/ethernet/sun/sunvnet.h
+++ b/drivers/net/ethernet/sun/sunvnet.h
@@ -1,6 +1,8 @@
#ifndef _SUNVNET_H
#define _SUNVNET_H
+#include <linux/interrupt.h>
+
#define DESC_NCOOKIES(entry_size) \
((entry_size) - sizeof(struct vio_net_desc))
@@ -78,6 +80,8 @@ struct vnet {
struct list_head list;
u64 local_mac;
+
+ struct tasklet_struct vnet_tx_wakeup;
};
#endif /* _SUNVNET_H */
diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 38da73a2a886..6ab36d9ff2ab 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -66,7 +66,7 @@
#include "tehuti.h"
-static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = {
+static const struct pci_device_id bdx_pci_tbl[] = {
{ PCI_VDEVICE(TEHUTI, 0x3009), },
{ PCI_VDEVICE(TEHUTI, 0x3010), },
{ PCI_VDEVICE(TEHUTI, 0x3014), },
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 53150c25a96b..1769700a6070 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_TI
bool "Texas Instruments (TI) devices"
default y
- depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
+ depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX || ARCH_KEYSTONE))
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -32,7 +32,7 @@ config TI_DAVINCI_EMAC
config TI_DAVINCI_MDIO
tristate "TI DaVinci MDIO Support"
- depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX )
+ depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX || ARCH_KEYSTONE )
select PHYLIB
---help---
This driver supports TI's DaVinci MDIO module.
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 7399a52f7c26..f9bcf7aa88ca 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -67,42 +67,42 @@ MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
#define CPMAC_RX_CONTROL 0x0014
#define CPMAC_RX_TEARDOWN 0x0018
#define CPMAC_MBP 0x0100
-# define MBP_RXPASSCRC 0x40000000
-# define MBP_RXQOS 0x20000000
-# define MBP_RXNOCHAIN 0x10000000
-# define MBP_RXCMF 0x01000000
-# define MBP_RXSHORT 0x00800000
-# define MBP_RXCEF 0x00400000
-# define MBP_RXPROMISC 0x00200000
-# define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16)
-# define MBP_RXBCAST 0x00002000
-# define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8)
-# define MBP_RXMCAST 0x00000020
-# define MBP_MCASTCHAN(channel) ((channel) & 0x7)
+#define MBP_RXPASSCRC 0x40000000
+#define MBP_RXQOS 0x20000000
+#define MBP_RXNOCHAIN 0x10000000
+#define MBP_RXCMF 0x01000000
+#define MBP_RXSHORT 0x00800000
+#define MBP_RXCEF 0x00400000
+#define MBP_RXPROMISC 0x00200000
+#define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16)
+#define MBP_RXBCAST 0x00002000
+#define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8)
+#define MBP_RXMCAST 0x00000020
+#define MBP_MCASTCHAN(channel) ((channel) & 0x7)
#define CPMAC_UNICAST_ENABLE 0x0104
#define CPMAC_UNICAST_CLEAR 0x0108
#define CPMAC_MAX_LENGTH 0x010c
#define CPMAC_BUFFER_OFFSET 0x0110
#define CPMAC_MAC_CONTROL 0x0160
-# define MAC_TXPTYPE 0x00000200
-# define MAC_TXPACE 0x00000040
-# define MAC_MII 0x00000020
-# define MAC_TXFLOW 0x00000010
-# define MAC_RXFLOW 0x00000008
-# define MAC_MTEST 0x00000004
-# define MAC_LOOPBACK 0x00000002
-# define MAC_FDX 0x00000001
+#define MAC_TXPTYPE 0x00000200
+#define MAC_TXPACE 0x00000040
+#define MAC_MII 0x00000020
+#define MAC_TXFLOW 0x00000010
+#define MAC_RXFLOW 0x00000008
+#define MAC_MTEST 0x00000004
+#define MAC_LOOPBACK 0x00000002
+#define MAC_FDX 0x00000001
#define CPMAC_MAC_STATUS 0x0164
-# define MAC_STATUS_QOS 0x00000004
-# define MAC_STATUS_RXFLOW 0x00000002
-# define MAC_STATUS_TXFLOW 0x00000001
+#define MAC_STATUS_QOS 0x00000004
+#define MAC_STATUS_RXFLOW 0x00000002
+#define MAC_STATUS_TXFLOW 0x00000001
#define CPMAC_TX_INT_ENABLE 0x0178
#define CPMAC_TX_INT_CLEAR 0x017c
#define CPMAC_MAC_INT_VECTOR 0x0180
-# define MAC_INT_STATUS 0x00080000
-# define MAC_INT_HOST 0x00040000
-# define MAC_INT_RX 0x00020000
-# define MAC_INT_TX 0x00010000
+#define MAC_INT_STATUS 0x00080000
+#define MAC_INT_HOST 0x00040000
+#define MAC_INT_RX 0x00020000
+#define MAC_INT_TX 0x00010000
#define CPMAC_MAC_EOI_VECTOR 0x0184
#define CPMAC_RX_INT_ENABLE 0x0198
#define CPMAC_RX_INT_CLEAR 0x019c
@@ -118,8 +118,8 @@ MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
#define CPMAC_TX_ACK(channel) (0x0640 + (channel) * 4)
#define CPMAC_RX_ACK(channel) (0x0660 + (channel) * 4)
#define CPMAC_REG_END 0x0680
-/*
- * Rx/Tx statistics
+
+/* Rx/Tx statistics
* TODO: use some of them to fill stats in cpmac_stats()
*/
#define CPMAC_STATS_RX_GOOD 0x0200
@@ -157,24 +157,24 @@ MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
/* MDIO bus */
#define CPMAC_MDIO_VERSION 0x0000
#define CPMAC_MDIO_CONTROL 0x0004
-# define MDIOC_IDLE 0x80000000
-# define MDIOC_ENABLE 0x40000000
-# define MDIOC_PREAMBLE 0x00100000
-# define MDIOC_FAULT 0x00080000
-# define MDIOC_FAULTDETECT 0x00040000
-# define MDIOC_INTTEST 0x00020000
-# define MDIOC_CLKDIV(div) ((div) & 0xff)
+#define MDIOC_IDLE 0x80000000
+#define MDIOC_ENABLE 0x40000000
+#define MDIOC_PREAMBLE 0x00100000
+#define MDIOC_FAULT 0x00080000
+#define MDIOC_FAULTDETECT 0x00040000
+#define MDIOC_INTTEST 0x00020000
+#define MDIOC_CLKDIV(div) ((div) & 0xff)
#define CPMAC_MDIO_ALIVE 0x0008
#define CPMAC_MDIO_LINK 0x000c
#define CPMAC_MDIO_ACCESS(channel) (0x0080 + (channel) * 8)
-# define MDIO_BUSY 0x80000000
-# define MDIO_WRITE 0x40000000
-# define MDIO_REG(reg) (((reg) & 0x1f) << 21)
-# define MDIO_PHY(phy) (((phy) & 0x1f) << 16)
-# define MDIO_DATA(data) ((data) & 0xffff)
+#define MDIO_BUSY 0x80000000
+#define MDIO_WRITE 0x40000000
+#define MDIO_REG(reg) (((reg) & 0x1f) << 21)
+#define MDIO_PHY(phy) (((phy) & 0x1f) << 16)
+#define MDIO_DATA(data) ((data) & 0xffff)
#define CPMAC_MDIO_PHYSEL(channel) (0x0084 + (channel) * 8)
-# define PHYSEL_LINKSEL 0x00000040
-# define PHYSEL_LINKINT 0x00000020
+#define PHYSEL_LINKSEL 0x00000040
+#define PHYSEL_LINKINT 0x00000020
struct cpmac_desc {
u32 hw_next;
@@ -224,12 +224,12 @@ static void cpmac_dump_regs(struct net_device *dev)
{
int i;
struct cpmac_priv *priv = netdev_priv(dev);
+
for (i = 0; i < CPMAC_REG_END; i += 4) {
if (i % 16 == 0) {
if (i)
- pr_cont("\n");
- printk(KERN_DEBUG "%s: reg[%p]:", dev->name,
- priv->regs + i);
+ printk("\n");
+ printk("%s: reg[%p]:", dev->name, priv->regs + i);
}
printk(" %08x", cpmac_read(priv->regs, i));
}
@@ -239,7 +239,8 @@ static void cpmac_dump_regs(struct net_device *dev)
static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc)
{
int i;
- printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc);
+
+ printk("%s: desc[%p]:", dev->name, desc);
for (i = 0; i < sizeof(*desc) / 4; i++)
printk(" %08x", ((u32 *)desc)[i]);
printk("\n");
@@ -249,6 +250,7 @@ static void cpmac_dump_all_desc(struct net_device *dev)
{
struct cpmac_priv *priv = netdev_priv(dev);
struct cpmac_desc *dump = priv->rx_head;
+
do {
cpmac_dump_desc(dev, dump);
dump = dump->next;
@@ -258,13 +260,13 @@ static void cpmac_dump_all_desc(struct net_device *dev)
static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb)
{
int i;
- printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
+
+ printk("%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len);
for (i = 0; i < skb->len; i++) {
if (i % 16 == 0) {
if (i)
- pr_cont("\n");
- printk(KERN_DEBUG "%s: data[%p]:", dev->name,
- skb->data + i);
+ printk("\n");
+ printk("%s: data[%p]:", dev->name, skb->data + i);
}
printk(" %02x", ((u8 *)skb->data)[i]);
}
@@ -281,6 +283,7 @@ static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
MDIO_PHY(phy_id));
while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY)
cpu_relax();
+
return MDIO_DATA(val);
}
@@ -291,6 +294,7 @@ static int cpmac_mdio_write(struct mii_bus *bus, int phy_id,
cpu_relax();
cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE |
MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val));
+
return 0;
}
@@ -300,12 +304,13 @@ static int cpmac_mdio_reset(struct mii_bus *bus)
cpmac_clk = clk_get(&bus->dev, "cpmac");
if (IS_ERR(cpmac_clk)) {
- printk(KERN_ERR "unable to get cpmac clock\n");
+ pr_err("unable to get cpmac clock\n");
return -1;
}
ar7_device_reset(AR7_RESET_BIT_MDIO);
cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE |
MDIOC_CLKDIV(clk_get_rate(cpmac_clk) / 2200000 - 1));
+
return 0;
}
@@ -331,8 +336,7 @@ static void cpmac_set_multicast_list(struct net_device *dev)
cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff);
cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff);
} else {
- /*
- * cpmac uses some strange mac address hashing
+ /* cpmac uses some strange mac address hashing
* (not crc32)
*/
netdev_for_each_mc_addr(ha, dev) {
@@ -369,8 +373,8 @@ static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping);
if (unlikely(!desc->datalen)) {
if (netif_msg_rx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: rx: spurious interrupt\n",
- priv->dev->name);
+ netdev_warn(priv->dev, "rx: spurious interrupt\n");
+
return NULL;
}
@@ -390,15 +394,14 @@ static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv,
DMA_FROM_DEVICE);
desc->hw_data = (u32)desc->data_mapping;
if (unlikely(netif_msg_pktdata(priv))) {
- printk(KERN_DEBUG "%s: received packet:\n",
- priv->dev->name);
+ netdev_dbg(priv->dev, "received packet:\n");
cpmac_dump_skb(priv->dev, result);
}
} else {
if (netif_msg_rx_err(priv) && net_ratelimit())
- printk(KERN_WARNING
- "%s: low on skbs, dropping packet\n",
- priv->dev->name);
+ netdev_warn(priv->dev,
+ "low on skbs, dropping packet\n");
+
priv->dev->stats.rx_dropped++;
}
@@ -418,8 +421,8 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
spin_lock(&priv->rx_lock);
if (unlikely(!priv->rx_head)) {
if (netif_msg_rx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: rx: polling, but no queue\n",
- priv->dev->name);
+ netdev_warn(priv->dev, "rx: polling, but no queue\n");
+
spin_unlock(&priv->rx_lock);
napi_complete(napi);
return 0;
@@ -432,15 +435,15 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
if ((desc->dataflags & CPMAC_EOQ) != 0) {
/* The last update to eoq->hw_next didn't happen
- * soon enough, and the receiver stopped here.
- *Remember this descriptor so we can restart
- * the receiver after freeing some space.
- */
+ * soon enough, and the receiver stopped here.
+ * Remember this descriptor so we can restart
+ * the receiver after freeing some space.
+ */
if (unlikely(restart)) {
if (netif_msg_rx_err(priv))
- printk(KERN_ERR "%s: poll found a"
- " duplicate EOQ: %p and %p\n",
- priv->dev->name, restart, desc);
+ netdev_err(priv->dev, "poll found a"
+ " duplicate EOQ: %p and %p\n",
+ restart, desc);
goto fatal_error;
}
@@ -457,25 +460,27 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
if (desc != priv->rx_head) {
/* We freed some buffers, but not the whole ring,
- * add what we did free to the rx list */
+ * add what we did free to the rx list
+ */
desc->prev->hw_next = (u32)0;
priv->rx_head->prev->hw_next = priv->rx_head->mapping;
}
/* Optimization: If we did not actually process an EOQ (perhaps because
* of quota limits), check to see if the tail of the queue has EOQ set.
- * We should immediately restart in that case so that the receiver can
- * restart and run in parallel with more packet processing.
- * This lets us handle slightly larger bursts before running
- * out of ring space (assuming dev->weight < ring_size) */
+ * We should immediately restart in that case so that the receiver can
+ * restart and run in parallel with more packet processing.
+ * This lets us handle slightly larger bursts before running
+ * out of ring space (assuming dev->weight < ring_size)
+ */
if (!restart &&
(priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ))
== CPMAC_EOQ &&
(priv->rx_head->dataflags & CPMAC_OWN) != 0) {
/* reset EOQ so the poll loop (above) doesn't try to
- * restart this when it eventually gets to this descriptor.
- */
+ * restart this when it eventually gets to this descriptor.
+ */
priv->rx_head->prev->dataflags &= ~CPMAC_EOQ;
restart = priv->rx_head;
}
@@ -484,15 +489,13 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
priv->dev->stats.rx_errors++;
priv->dev->stats.rx_fifo_errors++;
if (netif_msg_rx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: rx dma ring overrun\n",
- priv->dev->name);
+ netdev_warn(priv->dev, "rx dma ring overrun\n");
if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) {
if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: cpmac_poll is trying to "
- "restart rx from a descriptor that's "
- "not free: %p\n",
- priv->dev->name, restart);
+ netdev_err(priv->dev, "cpmac_poll is trying "
+ "to restart rx from a descriptor "
+ "that's not free: %p\n", restart);
goto fatal_error;
}
@@ -502,11 +505,12 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
priv->rx_head = desc;
spin_unlock(&priv->rx_lock);
if (unlikely(netif_msg_rx_status(priv)))
- printk(KERN_DEBUG "%s: poll processed %d packets\n",
- priv->dev->name, received);
+ netdev_dbg(priv->dev, "poll processed %d packets\n", received);
+
if (processed == 0) {
/* we ran out of packets to read,
- * revert to interrupt-driven mode */
+ * revert to interrupt-driven mode
+ */
napi_complete(napi);
cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
return 0;
@@ -516,16 +520,15 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
fatal_error:
/* Something went horribly wrong.
- * Reset hardware to try to recover rather than wedging. */
-
+ * Reset hardware to try to recover rather than wedging.
+ */
if (netif_msg_drv(priv)) {
- printk(KERN_ERR "%s: cpmac_poll is confused. "
- "Resetting hardware\n", priv->dev->name);
+ netdev_err(priv->dev, "cpmac_poll is confused. "
+ "Resetting hardware\n");
cpmac_dump_all_desc(priv->dev);
- printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
- priv->dev->name,
- cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
- cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
+ netdev_dbg(priv->dev, "RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n",
+ cpmac_read(priv->regs, CPMAC_RX_PTR(0)),
+ cpmac_read(priv->regs, CPMAC_RX_ACK(0)));
}
spin_unlock(&priv->rx_lock);
@@ -537,6 +540,7 @@ fatal_error:
cpmac_hw_stop(priv->dev);
if (!schedule_work(&priv->reset_work))
atomic_dec(&priv->reset_pending);
+
return 0;
}
@@ -560,8 +564,8 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
desc = &priv->desc_ring[queue];
if (unlikely(desc->dataflags & CPMAC_OWN)) {
if (netif_msg_tx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: tx dma ring full\n",
- dev->name);
+ netdev_warn(dev, "tx dma ring full\n");
+
return NETDEV_TX_BUSY;
}
@@ -575,8 +579,7 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
desc->datalen = len;
desc->buflen = len;
if (unlikely(netif_msg_tx_queued(priv)))
- printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb,
- skb->len);
+ netdev_dbg(dev, "sending 0x%p, len=%d\n", skb, skb->len);
if (unlikely(netif_msg_hw(priv)))
cpmac_dump_desc(dev, desc);
if (unlikely(netif_msg_pktdata(priv)))
@@ -602,8 +605,8 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
DMA_TO_DEVICE);
if (unlikely(netif_msg_tx_done(priv)))
- printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name,
- desc->skb, desc->skb->len);
+ netdev_dbg(dev, "sent 0x%p, len=%d\n",
+ desc->skb, desc->skb->len);
dev_kfree_skb_irq(desc->skb);
desc->skb = NULL;
@@ -611,8 +614,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
netif_wake_subqueue(dev, queue);
} else {
if (netif_msg_tx_err(priv) && net_ratelimit())
- printk(KERN_WARNING
- "%s: end_xmit: spurious interrupt\n", dev->name);
+ netdev_warn(dev, "end_xmit: spurious interrupt\n");
if (__netif_subqueue_stopped(dev, queue))
netif_wake_subqueue(dev, queue);
}
@@ -687,14 +689,14 @@ static void cpmac_clear_rx(struct net_device *dev)
struct cpmac_priv *priv = netdev_priv(dev);
struct cpmac_desc *desc;
int i;
+
if (unlikely(!priv->rx_head))
return;
desc = priv->rx_head;
for (i = 0; i < priv->ring_size; i++) {
if ((desc->dataflags & CPMAC_OWN) == 0) {
if (netif_msg_rx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: packet dropped\n",
- dev->name);
+ netdev_warn(dev, "packet dropped\n");
if (unlikely(netif_msg_hw(priv)))
cpmac_dump_desc(dev, desc);
desc->dataflags = CPMAC_OWN;
@@ -710,6 +712,7 @@ static void cpmac_clear_tx(struct net_device *dev)
{
struct cpmac_priv *priv = netdev_priv(dev);
int i;
+
if (unlikely(!priv->desc_ring))
return;
for (i = 0; i < CPMAC_QUEUES; i++) {
@@ -751,16 +754,16 @@ static void cpmac_check_status(struct net_device *dev)
if (rx_code || tx_code) {
if (netif_msg_drv(priv) && net_ratelimit()) {
/* Can't find any documentation on what these
- *error codes actually are. So just log them and hope..
+ * error codes actually are. So just log them and hope..
*/
if (rx_code)
- printk(KERN_WARNING "%s: host error %d on rx "
- "channel %d (macstatus %08x), resetting\n",
- dev->name, rx_code, rx_channel, macstatus);
+ netdev_warn(dev, "host error %d on rx "
+ "channel %d (macstatus %08x), resetting\n",
+ rx_code, rx_channel, macstatus);
if (tx_code)
- printk(KERN_WARNING "%s: host error %d on tx "
- "channel %d (macstatus %08x), resetting\n",
- dev->name, tx_code, tx_channel, macstatus);
+ netdev_warn(dev, "host error %d on tx "
+ "channel %d (macstatus %08x), resetting\n",
+ tx_code, tx_channel, macstatus);
}
netif_tx_stop_all_queues(dev);
@@ -785,8 +788,7 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id)
status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR);
if (unlikely(netif_msg_intr(priv)))
- printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name,
- status);
+ netdev_dbg(dev, "interrupt status: 0x%08x\n", status);
if (status & MAC_INT_TX)
cpmac_end_xmit(dev, (status & 7));
@@ -815,7 +817,7 @@ static void cpmac_tx_timeout(struct net_device *dev)
dev->stats.tx_errors++;
spin_unlock(&priv->lock);
if (netif_msg_tx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: transmit timeout\n", dev->name);
+ netdev_warn(dev, "transmit timeout\n");
atomic_inc(&priv->reset_pending);
barrier();
@@ -829,6 +831,7 @@ static void cpmac_tx_timeout(struct net_device *dev)
static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct cpmac_priv *priv = netdev_priv(dev);
+
if (!(netif_running(dev)))
return -EINVAL;
if (!priv->phy)
@@ -884,6 +887,7 @@ static int cpmac_set_ringparam(struct net_device *dev,
if (netif_running(dev))
return -EBUSY;
priv->ring_size = ring->rx_pending;
+
return 0;
}
@@ -951,8 +955,8 @@ static int cpmac_open(struct net_device *dev)
mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs");
if (!request_mem_region(mem->start, resource_size(mem), dev->name)) {
if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: failed to request registers\n",
- dev->name);
+ netdev_err(dev, "failed to request registers\n");
+
res = -ENXIO;
goto fail_reserve;
}
@@ -960,8 +964,8 @@ static int cpmac_open(struct net_device *dev)
priv->regs = ioremap(mem->start, resource_size(mem));
if (!priv->regs) {
if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: failed to remap registers\n",
- dev->name);
+ netdev_err(dev, "failed to remap registers\n");
+
res = -ENXIO;
goto fail_remap;
}
@@ -1003,8 +1007,8 @@ static int cpmac_open(struct net_device *dev)
res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev);
if (res) {
if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: failed to obtain irq\n",
- dev->name);
+ netdev_err(dev, "failed to obtain irq\n");
+
goto fail_irq;
}
@@ -1077,6 +1081,7 @@ static int cpmac_stop(struct net_device *dev)
dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) *
(CPMAC_QUEUES + priv->ring_size),
priv->desc_ring, priv->dma_ring);
+
return 0;
}
@@ -1121,10 +1126,11 @@ static int cpmac_probe(struct platform_device *pdev)
if (phy_id == PHY_MAX_ADDR) {
dev_err(&pdev->dev, "no PHY present, falling back "
- "to switch on MDIO bus 0\n");
+ "to switch on MDIO bus 0\n");
strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
}
+ mdio_bus_id[sizeof(mdio_bus_id) - 1] = '\0';
dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
if (!dev)
@@ -1137,7 +1143,7 @@ static int cpmac_probe(struct platform_device *pdev)
mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
if (!mem) {
rc = -ENODEV;
- goto fail;
+ goto out;
}
dev->irq = platform_get_irq_byname(pdev, "irq");
@@ -1162,44 +1168,48 @@ static int cpmac_probe(struct platform_device *pdev)
if (IS_ERR(priv->phy)) {
if (netif_msg_drv(priv))
- printk(KERN_ERR "%s: Could not attach to PHY\n",
- dev->name);
+ dev_err(&pdev->dev, "Could not attach to PHY\n");
+
rc = PTR_ERR(priv->phy);
- goto fail;
+ goto out;
}
rc = register_netdev(dev);
if (rc) {
- printk(KERN_ERR "cpmac: error %i registering device %s\n", rc,
- dev->name);
+ dev_err(&pdev->dev, "Could not register net device\n");
goto fail;
}
if (netif_msg_probe(priv)) {
- printk(KERN_INFO
- "cpmac: device %s (regs: %p, irq: %d, phy: %s, "
- "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq,
- priv->phy_name, dev->dev_addr);
+ dev_info(&pdev->dev, "regs: %p, irq: %d, phy: %s, "
+ "mac: %pM\n", (void *)mem->start, dev->irq,
+ priv->phy_name, dev->dev_addr);
}
+
return 0;
fail:
free_netdev(dev);
+out:
return rc;
}
static int cpmac_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
+
unregister_netdev(dev);
free_netdev(dev);
+
return 0;
}
static struct platform_driver cpmac_driver = {
- .driver.name = "cpmac",
- .driver.owner = THIS_MODULE,
- .probe = cpmac_probe,
+ .driver = {
+ .name = "cpmac",
+ .owner = THIS_MODULE,
+ },
+ .probe = cpmac_probe,
.remove = cpmac_remove,
};
@@ -1221,7 +1231,7 @@ int cpmac_init(void)
cpmac_mii->priv = ioremap(AR7_REGS_MDIO, 256);
if (!cpmac_mii->priv) {
- printk(KERN_ERR "Can't ioremap mdio registers\n");
+ pr_err("Can't ioremap mdio registers\n");
res = -ENXIO;
goto fail_alloc;
}
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b988d16cd34e..999fb72688d2 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -884,14 +884,16 @@ static int cpsw_set_coalesce(struct net_device *ndev,
u32 addnl_dvdr = 1;
u32 coal_intvl = 0;
- if (!coal->rx_coalesce_usecs)
- return -EINVAL;
-
coal_intvl = coal->rx_coalesce_usecs;
int_ctrl = readl(&priv->wr_regs->int_control);
prescale = priv->bus_freq_mhz * 4;
+ if (!coal->rx_coalesce_usecs) {
+ int_ctrl &= ~(CPSW_INTPRESCALE_MASK | CPSW_INTPACEEN);
+ goto update_return;
+ }
+
if (coal_intvl < CPSW_CMINTMIN_INTVL)
coal_intvl = CPSW_CMINTMIN_INTVL;
@@ -919,6 +921,8 @@ static int cpsw_set_coalesce(struct net_device *ndev,
int_ctrl |= CPSW_INTPACEEN;
int_ctrl &= (~CPSW_INTPRESCALE_MASK);
int_ctrl |= (prescale & CPSW_INTPRESCALE_MASK);
+
+update_return:
writel(int_ctrl, &priv->wr_regs->int_control);
cpsw_notice(priv, timer, "Set coalesce to %d usecs.\n", coal_intvl);
@@ -999,17 +1003,6 @@ static void cpsw_get_ethtool_stats(struct net_device *ndev,
}
}
-static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
-{
- static char *leader = "........................................";
-
- if (!val)
- return 0;
- else
- return snprintf(buf, maxlen, "%s %s %10d\n", name,
- leader + strlen(name), val);
-}
-
static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
{
u32 i;
@@ -1671,14 +1664,34 @@ static const struct net_device_ops cpsw_netdev_ops = {
.ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
};
+static int cpsw_get_regs_len(struct net_device *ndev)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ return priv->data.ale_entries * ALE_ENTRY_WORDS * sizeof(u32);
+}
+
+static void cpsw_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ u32 *reg = p;
+
+ /* update CPSW IP version */
+ regs->version = priv->version;
+
+ cpsw_ale_dump(priv->ale, reg);
+}
+
static void cpsw_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
{
struct cpsw_priv *priv = netdev_priv(ndev);
- strlcpy(info->driver, "TI CPSW Driver v1.0", sizeof(info->driver));
+ strlcpy(info->driver, "cpsw", sizeof(info->driver));
strlcpy(info->version, "1.0", sizeof(info->version));
strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info));
+ info->regdump_len = cpsw_get_regs_len(ndev);
}
static u32 cpsw_get_msglevel(struct net_device *ndev)
@@ -1786,6 +1799,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
.get_ethtool_stats = cpsw_get_ethtool_stats,
.get_wol = cpsw_get_wol,
.set_wol = cpsw_set_wol,
+ .get_regs_len = cpsw_get_regs_len,
+ .get_regs = cpsw_get_regs,
};
static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 7f893069c418..0579b2243bb6 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -25,8 +25,6 @@
#include "cpsw_ale.h"
#define BITMASK(bits) (BIT(bits) - 1)
-#define ALE_ENTRY_BITS 68
-#define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
#define ALE_VERSION_MAJOR(rev) ((rev >> 8) & 0xff)
#define ALE_VERSION_MINOR(rev) (rev & 0xff)
@@ -763,3 +761,13 @@ int cpsw_ale_destroy(struct cpsw_ale *ale)
kfree(ale);
return 0;
}
+
+void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
+{
+ int i;
+
+ for (i = 0; i < ale->params.ale_entries; i++) {
+ cpsw_ale_read(ale, i, data);
+ data += ALE_ENTRY_WORDS;
+ }
+}
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index de409c33b250..31cf43cab42e 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -80,6 +80,9 @@ enum cpsw_ale_port_state {
#define ALE_MCAST_FWD_LEARN 2
#define ALE_MCAST_FWD_2 3
+#define ALE_ENTRY_BITS 68
+#define ALE_ENTRY_WORDS DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
+
struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params);
int cpsw_ale_destroy(struct cpsw_ale *ale);
@@ -104,5 +107,6 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
int control, int value);
+void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
#endif
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index 6b56f85951e5..ab92f67da035 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -256,23 +256,21 @@ static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
u16 ts_seqid, u8 ts_msgtype)
{
u16 *seqid;
- unsigned int offset;
+ unsigned int offset = 0;
u8 *msgtype, *data = skb->data;
- switch (ptp_class) {
- case PTP_CLASS_V1_IPV4:
- case PTP_CLASS_V2_IPV4:
- offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
- break;
- case PTP_CLASS_V1_IPV6:
- case PTP_CLASS_V2_IPV6:
- offset = OFF_PTP6;
+ if (ptp_class & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (ptp_class & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
break;
- case PTP_CLASS_V2_L2:
- offset = ETH_HLEN;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
break;
- case PTP_CLASS_V2_VLAN:
- offset = ETH_HLEN + VLAN_HLEN;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
break;
default:
return 0;
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 735dc53d4b01..2791f6f2db11 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -38,6 +38,7 @@
#include <linux/davinci_emac.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_mdio.h>
#include <linux/pinctrl/consumer.h>
/*
@@ -95,6 +96,10 @@ struct davinci_mdio_data {
struct mii_bus *bus;
bool suspended;
unsigned long access_time; /* jiffies */
+ /* Indicates that driver shouldn't modify phy_mask in case
+ * if MDIO bus is registered from DT.
+ */
+ bool skip_scan;
};
static void __davinci_mdio_reset(struct davinci_mdio_data *data)
@@ -144,6 +149,9 @@ static int davinci_mdio_reset(struct mii_bus *bus)
dev_info(data->dev, "davinci mdio revision %d.%d\n",
(ver >> 8) & 0xff, ver & 0xff);
+ if (data->skip_scan)
+ return 0;
+
/* get phy mask from the alive register */
phy_mask = __raw_readl(&data->regs->alive);
if (phy_mask) {
@@ -369,8 +377,17 @@ static int davinci_mdio_probe(struct platform_device *pdev)
goto bail_out;
}
- /* register the mii bus */
- ret = mdiobus_register(data->bus);
+ /* register the mii bus
+ * Create PHYs from DT only in case if PHY child nodes are explicitly
+ * defined to support backward compatibility with DTs which assume that
+ * Davinci MDIO will always scan the bus for PHYs detection.
+ */
+ if (dev->of_node && of_get_child_count(dev->of_node)) {
+ data->skip_scan = true;
+ ret = of_mdiobus_register(data->bus, dev->of_node);
+ } else {
+ ret = mdiobus_register(data->bus);
+ }
if (ret)
goto bail_out;
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 62b19be5183d..f2ff0074aac9 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -69,10 +69,6 @@ MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
MODULE_LICENSE("GPL");
-
-/* Define this to enable Link beat monitoring */
-#undef MONITOR
-
/* Turn on debugging. See Documentation/networking/tlan.txt for details */
static int debug;
module_param(debug, int, 0);
@@ -107,8 +103,10 @@ static struct board {
{ "Compaq Netelligent 10/100 TX Embedded UTP",
TLAN_ADAPTER_NONE, 0x83 },
{ "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
- { "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
- { "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
+ { "Olicom OC-2325", TLAN_ADAPTER_ACTIVITY_LED |
+ TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
+ { "Olicom OC-2326", TLAN_ADAPTER_ACTIVITY_LED |
+ TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
{ "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
{ "Compaq Netelligent 10 T/2 PCI UTP/coax", TLAN_ADAPTER_NONE, 0x83 },
{ "Compaq NetFlex-3/E",
@@ -118,7 +116,7 @@ static struct board {
TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
};
-static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = {
+static const struct pci_device_id tlan_pci_tbl[] = {
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
@@ -192,9 +190,7 @@ static void tlan_phy_power_up(struct net_device *);
static void tlan_phy_reset(struct net_device *);
static void tlan_phy_start_link(struct net_device *);
static void tlan_phy_finish_auto_neg(struct net_device *);
-#ifdef MONITOR
-static void tlan_phy_monitor(struct net_device *);
-#endif
+static void tlan_phy_monitor(unsigned long);
/*
static int tlan_phy_nop(struct net_device *);
@@ -337,6 +333,7 @@ static void tlan_stop(struct net_device *dev)
{
struct tlan_priv *priv = netdev_priv(dev);
+ del_timer_sync(&priv->media_timer);
tlan_read_and_clear_stats(dev, TLAN_RECORD);
outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
/* Reset and power down phy */
@@ -368,8 +365,10 @@ static int tlan_suspend(struct pci_dev *pdev, pm_message_t state)
static int tlan_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ int rc = pci_enable_device(pdev);
- pci_set_power_state(pdev, PCI_D0);
+ if (rc)
+ return rc;
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D0, 0);
netif_device_attach(dev);
@@ -781,7 +780,43 @@ static const struct net_device_ops tlan_netdev_ops = {
#endif
};
+static void tlan_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct tlan_priv *priv = netdev_priv(dev);
+
+ strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+ if (priv->pci_dev)
+ strlcpy(info->bus_info, pci_name(priv->pci_dev),
+ sizeof(info->bus_info));
+ else
+ strlcpy(info->bus_info, "EISA", sizeof(info->bus_info));
+ info->eedump_len = TLAN_EEPROM_SIZE;
+}
+
+static int tlan_get_eeprom_len(struct net_device *dev)
+{
+ return TLAN_EEPROM_SIZE;
+}
+
+static int tlan_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < TLAN_EEPROM_SIZE; i++)
+ if (tlan_ee_read_byte(dev, i, &data[i]))
+ return -EIO;
+ return 0;
+}
+
+static const struct ethtool_ops tlan_ethtool_ops = {
+ .get_drvinfo = tlan_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = tlan_get_eeprom_len,
+ .get_eeprom = tlan_get_eeprom,
+};
/***************************************************************
* tlan_init
@@ -830,7 +865,7 @@ static int tlan_init(struct net_device *dev)
priv->rx_list_dma + sizeof(struct tlan_list)*TLAN_NUM_RX_LISTS;
err = 0;
- for (i = 0; i < 6 ; i++)
+ for (i = 0; i < ETH_ALEN; i++)
err |= tlan_ee_read_byte(dev,
(u8) priv->adapter->addr_ofs + i,
(u8 *) &dev->dev_addr[i]);
@@ -838,12 +873,20 @@ static int tlan_init(struct net_device *dev)
pr_err("%s: Error reading MAC from eeprom: %d\n",
dev->name, err);
}
- dev->addr_len = 6;
+ /* Olicom OC-2325/OC-2326 have the address byte-swapped */
+ if (priv->adapter->addr_ofs == 0xf8) {
+ for (i = 0; i < ETH_ALEN; i += 2) {
+ char tmp = dev->dev_addr[i];
+ dev->dev_addr[i] = dev->dev_addr[i + 1];
+ dev->dev_addr[i + 1] = tmp;
+ }
+ }
netif_carrier_off(dev);
/* Device methods */
dev->netdev_ops = &tlan_netdev_ops;
+ dev->ethtool_ops = &tlan_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
return 0;
@@ -886,6 +929,7 @@ static int tlan_open(struct net_device *dev)
}
init_timer(&priv->timer);
+ init_timer(&priv->media_timer);
tlan_start(dev);
@@ -1156,9 +1200,6 @@ static irqreturn_t tlan_handle_interrupt(int irq, void *dev_id)
static int tlan_close(struct net_device *dev)
{
- struct tlan_priv *priv = netdev_priv(dev);
-
- priv->neg_be_verbose = 0;
tlan_stop(dev);
free_irq(dev->irq, dev);
@@ -1808,11 +1849,6 @@ static void tlan_timer(unsigned long data)
priv->timer.function = NULL;
switch (priv->timer_type) {
-#ifdef MONITOR
- case TLAN_TIMER_LINK_BEAT:
- tlan_phy_monitor(dev);
- break;
-#endif
case TLAN_TIMER_PHY_PDOWN:
tlan_phy_power_down(dev);
break;
@@ -1856,8 +1892,6 @@ static void tlan_timer(unsigned long data)
}
-
-
/*****************************************************************************
******************************************************************************
@@ -2205,7 +2239,9 @@ tlan_reset_adapter(struct net_device *dev)
}
}
- if (priv->phy_num == 0)
+ /* don't power down internal PHY if we're going to use it */
+ if (priv->phy_num == 0 ||
+ (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))
data |= TLAN_NET_CFG_PHY_EN;
tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
@@ -2255,42 +2291,39 @@ tlan_finish_reset(struct net_device *dev)
tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
udelay(1000);
tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
- if ((status & MII_GS_LINK) &&
- /* We only support link info on Nat.Sem. PHY's */
- (tlphy_id1 == NAT_SEM_ID1) &&
- (tlphy_id2 == NAT_SEM_ID2)) {
- tlan_mii_read_reg(dev, phy, MII_AN_LPA, &partner);
- tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR, &tlphy_par);
-
- netdev_info(dev,
- "Link active with %s %uMbps %s-Duplex\n",
- !(tlphy_par & TLAN_PHY_AN_EN_STAT)
- ? "forced" : "Autonegotiation enabled,",
- tlphy_par & TLAN_PHY_SPEED_100
- ? 100 : 10,
- tlphy_par & TLAN_PHY_DUPLEX_FULL
- ? "Full" : "Half");
-
- if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
- netdev_info(dev, "Partner capability:");
- for (i = 5; i < 10; i++)
- if (partner & (1 << i))
- pr_cont(" %s", media[i-5]);
- pr_cont("\n");
- }
-
- tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
- TLAN_LED_LINK);
-#ifdef MONITOR
- /* We have link beat..for now anyway */
- priv->link = 1;
- /*Enabling link beat monitoring */
- tlan_set_timer(dev, (10*HZ), TLAN_TIMER_LINK_BEAT);
-#endif
- } else if (status & MII_GS_LINK) {
- netdev_info(dev, "Link active\n");
- tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
- TLAN_LED_LINK);
+ if (status & MII_GS_LINK) {
+ /* We only support link info on Nat.Sem. PHY's */
+ if ((tlphy_id1 == NAT_SEM_ID1) &&
+ (tlphy_id2 == NAT_SEM_ID2)) {
+ tlan_mii_read_reg(dev, phy, MII_AN_LPA,
+ &partner);
+ tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR,
+ &tlphy_par);
+
+ netdev_info(dev,
+ "Link active, %s %uMbps %s-Duplex\n",
+ !(tlphy_par & TLAN_PHY_AN_EN_STAT)
+ ? "forced" : "Autonegotiation enabled,",
+ tlphy_par & TLAN_PHY_SPEED_100
+ ? 100 : 10,
+ tlphy_par & TLAN_PHY_DUPLEX_FULL
+ ? "Full" : "Half");
+
+ if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
+ netdev_info(dev, "Partner capability:");
+ for (i = 5; i < 10; i++)
+ if (partner & (1 << i))
+ pr_cont(" %s",
+ media[i-5]);
+ pr_cont("\n");
+ }
+ } else
+ netdev_info(dev, "Link active\n");
+ /* Enabling link beat monitoring */
+ priv->media_timer.function = tlan_phy_monitor;
+ priv->media_timer.data = (unsigned long) dev;
+ priv->media_timer.expires = jiffies + HZ;
+ add_timer(&priv->media_timer);
}
}
@@ -2312,6 +2345,7 @@ tlan_finish_reset(struct net_device *dev)
dev->base_addr + TLAN_HOST_CMD + 1);
outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM);
outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD);
+ tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
netif_carrier_on(dev);
} else {
netdev_info(dev, "Link inactive, will retry in 10 secs...\n");
@@ -2494,9 +2528,10 @@ static void tlan_phy_power_down(struct net_device *dev)
value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
tlan_mii_sync(dev->base_addr);
tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
- if ((priv->phy_num == 0) &&
- (priv->phy[1] != TLAN_PHY_NONE) &&
- (!(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))) {
+ if ((priv->phy_num == 0) && (priv->phy[1] != TLAN_PHY_NONE)) {
+ /* if using internal PHY, the external PHY must be powered on */
+ if (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10)
+ value = MII_GC_ISOLATE; /* just isolate it from MII */
tlan_mii_sync(dev->base_addr);
tlan_mii_write_reg(dev, priv->phy[1], MII_GEN_CTL, value);
}
@@ -2538,6 +2573,7 @@ static void tlan_phy_reset(struct net_device *dev)
struct tlan_priv *priv = netdev_priv(dev);
u16 phy;
u16 value;
+ unsigned long timeout = jiffies + HZ;
phy = priv->phy[priv->phy_num];
@@ -2545,9 +2581,13 @@ static void tlan_phy_reset(struct net_device *dev)
tlan_mii_sync(dev->base_addr);
value = MII_GC_LOOPBK | MII_GC_RESET;
tlan_mii_write_reg(dev, phy, MII_GEN_CTL, value);
- tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
- while (value & MII_GC_RESET)
+ do {
tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
+ if (time_after(jiffies, timeout)) {
+ netdev_err(dev, "PHY reset timeout\n");
+ return;
+ }
+ } while (value & MII_GC_RESET);
/* Wait for 500 ms and initialize.
* I don't remember why I wait this long.
@@ -2653,7 +2693,6 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
struct tlan_priv *priv = netdev_priv(dev);
u16 an_adv;
u16 an_lpa;
- u16 data;
u16 mode;
u16 phy;
u16 status;
@@ -2668,13 +2707,7 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
/* Wait for 8 sec to give the process
* more time. Perhaps we should fail after a while.
*/
- if (!priv->neg_be_verbose++) {
- pr_info("Giving autonegotiation more time.\n");
- pr_info("Please check that your adapter has\n");
- pr_info("been properly connected to a HUB or Switch.\n");
- pr_info("Trying to establish link in the background...\n");
- }
- tlan_set_timer(dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN);
+ tlan_set_timer(dev, 2 * HZ, TLAN_TIMER_PHY_FINISH_AN);
return;
}
@@ -2687,13 +2720,11 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
else if (!(mode & 0x0080) && (mode & 0x0040))
priv->tlan_full_duplex = true;
+ /* switch to internal PHY for 10 Mbps */
if ((!(mode & 0x0180)) &&
(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) &&
(priv->phy_num != 0)) {
priv->phy_num = 0;
- data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
- | TLAN_NET_CFG_PHY_EN;
- tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
tlan_set_timer(dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN);
return;
}
@@ -2717,7 +2748,6 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
}
-#ifdef MONITOR
/*********************************************************************
*
@@ -2727,18 +2757,18 @@ static void tlan_phy_finish_auto_neg(struct net_device *dev)
* None
*
* Params:
- * dev The device structure of this device.
+ * data The device structure of this device.
*
*
* This function monitors PHY condition by reading the status
- * register via the MII bus. This can be used to give info
- * about link changes (up/down), and possible switch to alternate
- * media.
+ * register via the MII bus, controls LINK LED and notifies the
+ * kernel about link state.
*
*******************************************************************/
-void tlan_phy_monitor(struct net_device *dev)
+static void tlan_phy_monitor(unsigned long data)
{
+ struct net_device *dev = (struct net_device *) data;
struct tlan_priv *priv = netdev_priv(dev);
u16 phy;
u16 phy_status;
@@ -2750,30 +2780,40 @@ void tlan_phy_monitor(struct net_device *dev)
/* Check if link has been lost */
if (!(phy_status & MII_GS_LINK)) {
- if (priv->link) {
- priv->link = 0;
+ if (netif_carrier_ok(dev)) {
printk(KERN_DEBUG "TLAN: %s has lost link\n",
dev->name);
+ tlan_dio_write8(dev->base_addr, TLAN_LED_REG, 0);
netif_carrier_off(dev);
- tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
- return;
+ if (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) {
+ /* power down internal PHY */
+ u16 data = MII_GC_PDOWN | MII_GC_LOOPBK |
+ MII_GC_ISOLATE;
+
+ tlan_mii_sync(dev->base_addr);
+ tlan_mii_write_reg(dev, priv->phy[0],
+ MII_GEN_CTL, data);
+ /* set to external PHY */
+ priv->phy_num = 1;
+ /* restart autonegotiation */
+ tlan_set_timer(dev, 4 * HZ / 10,
+ TLAN_TIMER_PHY_PDOWN);
+ return;
+ }
}
}
/* Link restablished? */
- if ((phy_status & MII_GS_LINK) && !priv->link) {
- priv->link = 1;
+ if ((phy_status & MII_GS_LINK) && !netif_carrier_ok(dev)) {
+ tlan_dio_write8(dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK);
printk(KERN_DEBUG "TLAN: %s has reestablished link\n",
dev->name);
netif_carrier_on(dev);
}
-
- /* Setup a new monitor */
- tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
+ priv->media_timer.expires = jiffies + HZ;
+ add_timer(&priv->media_timer);
}
-#endif /* MONITOR */
-
/*****************************************************************************
******************************************************************************
diff --git a/drivers/net/ethernet/ti/tlan.h b/drivers/net/ethernet/ti/tlan.h
index 2eb33a250788..e9928411827e 100644
--- a/drivers/net/ethernet/ti/tlan.h
+++ b/drivers/net/ethernet/ti/tlan.h
@@ -195,6 +195,7 @@ struct tlan_priv {
u32 timer_set_at;
u32 timer_type;
struct timer_list timer;
+ struct timer_list media_timer;
struct board *adapter;
u32 adapter_rev;
u32 aui;
@@ -206,9 +207,7 @@ struct tlan_priv {
u8 tlan_rev;
u8 tlan_full_duplex;
spinlock_t lock;
- u8 link;
struct work_struct tlan_tqueue;
- u8 neg_be_verbose;
};
@@ -219,7 +218,6 @@ struct tlan_priv {
*
****************************************************************/
-#define TLAN_TIMER_LINK_BEAT 1
#define TLAN_TIMER_ACTIVITY 2
#define TLAN_TIMER_PHY_PDOWN 3
#define TLAN_TIMER_PHY_PUP 4
@@ -241,6 +239,7 @@ struct tlan_priv {
#define TLAN_EEPROM_ACK 0
#define TLAN_EEPROM_STOP 1
+#define TLAN_EEPROM_SIZE 256
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c
index 4c70360967c2..69557a26f749 100644
--- a/drivers/net/ethernet/tile/tilegx.c
+++ b/drivers/net/ethernet/tile/tilegx.c
@@ -2201,8 +2201,8 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac)
/* Allocate the device structure. Normally, "name" is a
* template, instantiated by register_netdev(), but not for us.
*/
- dev = alloc_netdev_mqs(sizeof(*priv), name, tile_net_setup,
- NR_CPUS, 1);
+ dev = alloc_netdev_mqs(sizeof(*priv), name, NET_NAME_UNKNOWN,
+ tile_net_setup, NR_CPUS, 1);
if (!dev) {
pr_err("alloc_netdev_mqs(%s) failed\n", name);
return;
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index e5a5c5d4ce0c..88c712126692 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -2292,7 +2292,8 @@ static struct net_device *tile_net_dev_init(const char *name)
* tile_net_setup(), and saves "name". Normally, "name" is a
* template, instantiated by register_netdev(), but not for us.
*/
- dev = alloc_netdev(sizeof(*priv), name, tile_net_setup);
+ dev = alloc_netdev(sizeof(*priv), name, NET_NAME_UNKNOWN,
+ tile_net_setup);
if (!dev) {
pr_err("alloc_netdev(%s) failed\n", name);
return NULL;
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index d568af1eb4f4..0a7f2e77557f 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -723,13 +723,10 @@ static int gelic_wl_get_scan(struct net_device *netdev,
/* If a scan in progress, caller should call me again */
ret = -EAGAIN;
goto out;
- break;
-
case GELIC_WL_SCAN_STAT_INIT:
/* last scan request failed or never issued */
ret = -ENODEV;
goto out;
- break;
case GELIC_WL_SCAN_STAT_GOT_LIST:
/* ok, use current list */
break;
@@ -1831,25 +1828,18 @@ static const char *wpasecstr(enum gelic_eurus_wpa_security sec)
switch (sec) {
case GELIC_EURUS_WPA_SEC_NONE:
return "NONE";
- break;
case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP:
return "WPA_TKIP_TKIP";
- break;
case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES:
return "WPA_TKIP_AES";
- break;
case GELIC_EURUS_WPA_SEC_WPA_AES_AES:
return "WPA_AES_AES";
- break;
case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP:
return "WPA2_TKIP_TKIP";
- break;
case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES:
return "WPA2_TKIP_AES";
- break;
case GELIC_EURUS_WPA_SEC_WPA2_AES_AES:
return "WPA2_AES_AES";
- break;
}
return "";
};
diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c
index 0282d0161859..3e38f67c6011 100644
--- a/drivers/net/ethernet/toshiba/spider_net.c
+++ b/drivers/net/ethernet/toshiba/spider_net.c
@@ -73,7 +73,7 @@ MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \
char spider_net_driver_name[] = "spidernet";
-static DEFINE_PCI_DEVICE_TABLE(spider_net_pci_tbl) = {
+static const struct pci_device_id spider_net_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ 0, }
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index fef5573dbfca..45ac38d29ed8 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -65,7 +65,7 @@ static const struct {
{ "TOSHIBA TC35815/TX4939" },
};
-static DEFINE_PCI_DEVICE_TABLE(tc35815_pci_tbl) = {
+static const struct pci_device_id tc35815_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815CF), .driver_data = TC35815CF },
{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_NWU), .driver_data = TC35815_NWU },
{PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 },
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 2d72f96a9e2c..68c5260cc322 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -273,7 +273,7 @@ enum rhine_quirks {
/* Beware of PCI posted writes */
#define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
-static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = {
+static const struct pci_device_id rhine_pci_tbl[] = {
{ 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */
{ 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */
{ 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */
diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c
index de08e86db209..f5fbc12d3e10 100644
--- a/drivers/net/ethernet/via/via-velocity.c
+++ b/drivers/net/ethernet/via/via-velocity.c
@@ -381,7 +381,7 @@ static struct velocity_info_tbl chip_info_table[] = {
* device driver. Used for hotplug autoloading.
*/
-static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = {
+static const struct pci_device_id velocity_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
{ }
};
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 4ef818a7a6c6..fda5891835d4 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -72,7 +72,7 @@ void temac_iow(struct temac_local *lp, int offset, u32 value)
int temac_indirect_busywait(struct temac_local *lp)
{
- long end = jiffies + 2;
+ unsigned long end = jiffies + 2;
while (!(temac_ior(lp, XTE_RDY0_OFFSET) & XTE_RDY0_HARD_ACS_RDY_MASK)) {
if (time_before_eq(end, jiffies)) {
@@ -1148,8 +1148,7 @@ static int temac_of_remove(struct platform_device *op)
temac_mdio_teardown(lp);
unregister_netdev(ndev);
sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
lp->phy_node = NULL;
iounmap(lp->regs);
if (lp->sdma_regs)
@@ -1171,7 +1170,6 @@ static struct platform_driver temac_of_driver = {
.probe = temac_of_probe,
.remove = temac_of_remove,
.driver = {
- .owner = THIS_MODULE,
.name = "xilinx_temac",
.of_match_table = temac_of_match,
},
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 7b0a73556264..c8fd94133ecd 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1630,8 +1630,7 @@ static int axienet_of_remove(struct platform_device *op)
axienet_mdio_teardown(lp);
unregister_netdev(ndev);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
lp->phy_node = NULL;
iounmap(lp->regs);
@@ -1646,7 +1645,6 @@ static struct platform_driver axienet_of_driver = {
.probe = axienet_of_probe,
.remove = axienet_of_remove,
.driver = {
- .owner = THIS_MODULE,
.name = "xilinx_axienet",
.of_match_table = axienet_of_match,
},
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index d4abf478e2bb..3b67d60d4378 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -19,7 +19,7 @@
/* Wait till MDIO interface is ready to accept a new transaction.*/
int axienet_mdio_wait_until_ready(struct axienet_local *lp)
{
- long end = jiffies + 2;
+ unsigned long end = jiffies + 2;
while (!(axienet_ior(lp, XAE_MDIO_MCR_OFFSET) &
XAE_MDIO_MCR_READY_MASK)) {
if (time_before_eq(end, jiffies)) {
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 8c4aed3053eb..28dbbdc393eb 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -695,7 +695,7 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
static int xemaclite_mdio_wait(struct net_local *lp)
{
- long end = jiffies + 2;
+ unsigned long end = jiffies + 2;
/* wait for the MDIO interface to not be busy or timeout
after some time.
@@ -1245,7 +1245,6 @@ MODULE_DEVICE_TABLE(of, xemaclite_of_match);
static struct platform_driver xemaclite_of_driver = {
.driver = {
.name = DRIVER_NAME,
- .owner = THIS_MODULE,
.of_match_table = xemaclite_of_match,
},
.probe = xemaclite_of_probe,
diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c
index 7c81ffb861e8..d56f8693202b 100644
--- a/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -266,7 +266,7 @@ static void xirc2ps_detach(struct pcmcia_device *p_dev);
static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id);
-typedef struct local_info_t {
+struct local_info {
struct net_device *dev;
struct pcmcia_device *p_dev;
@@ -281,7 +281,7 @@ typedef struct local_info_t {
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
struct work_struct tx_timeout_task;
-} local_info_t;
+};
/****************
* Some more prototypes
@@ -475,12 +475,12 @@ static int
xirc2ps_probe(struct pcmcia_device *link)
{
struct net_device *dev;
- local_info_t *local;
+ struct local_info *local;
dev_dbg(&link->dev, "attach()\n");
/* Allocate the device structure */
- dev = alloc_etherdev(sizeof(local_info_t));
+ dev = alloc_etherdev(sizeof(struct local_info));
if (!dev)
return -ENOMEM;
local = netdev_priv(dev);
@@ -536,7 +536,7 @@ static int
set_card_type(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
u8 *buf;
unsigned int cisrev, mediaid, prodid;
size_t len;
@@ -690,7 +690,7 @@ static int
xirc2ps_config(struct pcmcia_device * link)
{
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr;
int err;
u8 *buf;
@@ -931,7 +931,7 @@ xirc2ps_release(struct pcmcia_device *link)
if (link->resource[2]->end) {
struct net_device *dev = link->priv;
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
if (local->dingo)
iounmap(local->dingo_ccr - 0x0800);
}
@@ -975,7 +975,7 @@ static irqreturn_t
xirc2ps_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr;
u_char saved_page;
unsigned bytes_rcvd;
@@ -1194,8 +1194,8 @@ xirc2ps_interrupt(int irq, void *dev_id)
static void
xirc2ps_tx_timeout_task(struct work_struct *work)
{
- local_info_t *local =
- container_of(work, local_info_t, tx_timeout_task);
+ struct local_info *local =
+ container_of(work, struct local_info, tx_timeout_task);
struct net_device *dev = local->dev;
/* reset the card */
do_reset(dev,1);
@@ -1206,7 +1206,7 @@ xirc2ps_tx_timeout_task(struct work_struct *work)
static void
xirc_tx_timeout(struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
dev->stats.tx_errors++;
netdev_notice(dev, "transmit timed out\n");
schedule_work(&lp->tx_timeout_task);
@@ -1215,7 +1215,7 @@ xirc_tx_timeout(struct net_device *dev)
static netdev_tx_t
do_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
int okay;
unsigned freespace;
@@ -1300,7 +1300,7 @@ static void set_address(struct set_address_info *sa_info, char *addr)
static void set_addresses(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct netdev_hw_addr *ha;
struct set_address_info sa_info;
int i;
@@ -1362,7 +1362,7 @@ set_multicast_list(struct net_device *dev)
static int
do_config(struct net_device *dev, struct ifmap *map)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
pr_debug("do_config(%p)\n", dev);
if (map->port != 255 && map->port != dev->if_port) {
@@ -1387,7 +1387,7 @@ do_config(struct net_device *dev, struct ifmap *map)
static int
do_open(struct net_device *dev)
{
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
dev_dbg(&link->dev, "do_open(%p)\n", dev);
@@ -1421,7 +1421,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static int
do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
struct mii_ioctl_data *data = if_mii(rq);
@@ -1453,7 +1453,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static void
hardreset(struct net_device *dev)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
SelectPage(4);
@@ -1470,7 +1470,7 @@ hardreset(struct net_device *dev)
static void
do_reset(struct net_device *dev, int full)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
unsigned value;
@@ -1631,7 +1631,7 @@ do_reset(struct net_device *dev, int full)
static int
init_mii(struct net_device *dev)
{
- local_info_t *local = netdev_priv(dev);
+ struct local_info *local = netdev_priv(dev);
unsigned int ioaddr = dev->base_addr;
unsigned control, status, linkpartner;
int i;
@@ -1715,7 +1715,7 @@ static int
do_stop(struct net_device *dev)
{
unsigned int ioaddr = dev->base_addr;
- local_info_t *lp = netdev_priv(dev);
+ struct local_info *lp = netdev_priv(dev);
struct pcmcia_device *link = lp->p_dev;
dev_dbg(&link->dev, "do_stop(%p)\n", dev);
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index 2aa57270838f..c44eaf019dea 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -196,6 +196,7 @@
* 14 Jun 2005 macro Use irqreturn_t.
* 23 Oct 2006 macro Big-endian host support.
* 14 Dec 2006 macro TURBOchannel support.
+ * 01 Jul 2014 macro Fixes for DMA on 64-bit hosts.
*/
/* Include files */
@@ -224,8 +225,8 @@
/* Version information string should be updated prior to each new release! */
#define DRV_NAME "defxx"
-#define DRV_VERSION "v1.10"
-#define DRV_RELDATE "2006/12/14"
+#define DRV_VERSION "v1.11"
+#define DRV_RELDATE "2014/07/01"
static char version[] =
DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -1126,17 +1127,16 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
/* Display virtual and physical addresses if debug driver */
- DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
- print_name,
- (long)bp->descr_block_virt, bp->descr_block_phys);
- DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
- print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
- DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
- print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
- DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
- print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
- DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
- print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
+ DBG_printk("%s: Descriptor block virt = %p, phys = %pad\n",
+ print_name, bp->descr_block_virt, &bp->descr_block_phys);
+ DBG_printk("%s: Command Request buffer virt = %p, phys = %pad\n",
+ print_name, bp->cmd_req_virt, &bp->cmd_req_phys);
+ DBG_printk("%s: Command Response buffer virt = %p, phys = %pad\n",
+ print_name, bp->cmd_rsp_virt, &bp->cmd_rsp_phys);
+ DBG_printk("%s: Receive buffer block virt = %p, phys = %pad\n",
+ print_name, bp->rcv_block_virt, &bp->rcv_block_phys);
+ DBG_printk("%s: Consumer block virt = %p, phys = %pad\n",
+ print_name, bp->cons_block_virt, &bp->cons_block_phys);
return DFX_K_SUCCESS;
}
@@ -2927,21 +2927,35 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
{
- struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
+ struct sk_buff *newskb;
+ dma_addr_t dma_addr;
+
+ newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE,
+ GFP_NOIO);
if (!newskb)
return -ENOMEM;
- bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
- ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
/*
* align to 128 bytes for compatibility with
* the old EISA boards.
*/
my_skb_align(newskb, 128);
+ dma_addr = dma_map_single(bp->bus_dev,
+ newskb->data,
+ PI_RCV_DATA_K_SIZE_MAX,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(bp->bus_dev, dma_addr)) {
+ dev_kfree_skb(newskb);
+ return -ENOMEM;
+ }
+ bp->descr_block_virt->rcv_data[i + j].long_0 =
+ (u32)(PI_RCV_DESCR_M_SOP |
+ ((PI_RCV_DATA_K_SIZE_MAX /
+ PI_ALIGN_K_RCV_DATA_BUFF) <<
+ PI_RCV_DESCR_V_SEG_LEN));
bp->descr_block_virt->rcv_data[i + j].long_1 =
- (u32)dma_map_single(bp->bus_dev, newskb->data,
- NEW_SKB_SIZE,
- DMA_FROM_DEVICE);
+ (u32)dma_addr;
+
/*
* p_rcv_buff_va is only used inside the
* kernel so we put the skb pointer here.
@@ -3008,7 +3022,7 @@ static void dfx_rcv_queue_process(
PI_TYPE_2_CONSUMER *p_type_2_cons; /* ptr to rcv/xmt consumer block register */
char *p_buff; /* ptr to start of packet receive buffer (FMC descriptor) */
u32 descr, pkt_len; /* FMC descriptor field and packet length */
- struct sk_buff *skb; /* pointer to a sk_buff to hold incoming packet data */
+ struct sk_buff *skb = NULL; /* pointer to a sk_buff to hold incoming packet data */
/* Service all consumed LLC receive frames */
@@ -3016,7 +3030,7 @@ static void dfx_rcv_queue_process(
while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
{
/* Process any errors */
-
+ dma_addr_t dma_addr;
int entry;
entry = bp->rcv_xmt_reg.index.rcv_comp;
@@ -3025,6 +3039,11 @@ static void dfx_rcv_queue_process(
#else
p_buff = bp->p_rcv_buff_va[entry];
#endif
+ dma_addr = bp->descr_block_virt->rcv_data[entry].long_1;
+ dma_sync_single_for_cpu(bp->bus_dev,
+ dma_addr + RCV_BUFF_K_DESCR,
+ sizeof(u32),
+ DMA_FROM_DEVICE);
memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
@@ -3046,31 +3065,46 @@ static void dfx_rcv_queue_process(
bp->rcv_length_errors++;
else{
#ifdef DYNAMIC_BUFFERS
+ struct sk_buff *newskb = NULL;
+
if (pkt_len > SKBUFF_RX_COPYBREAK) {
- struct sk_buff *newskb;
+ dma_addr_t new_dma_addr;
- newskb = dev_alloc_skb(NEW_SKB_SIZE);
+ newskb = netdev_alloc_skb(bp->dev,
+ NEW_SKB_SIZE);
if (newskb){
+ my_skb_align(newskb, 128);
+ new_dma_addr = dma_map_single(
+ bp->bus_dev,
+ newskb->data,
+ PI_RCV_DATA_K_SIZE_MAX,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(
+ bp->bus_dev,
+ new_dma_addr)) {
+ dev_kfree_skb(newskb);
+ newskb = NULL;
+ }
+ }
+ if (newskb) {
rx_in_place = 1;
- my_skb_align(newskb, 128);
skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
dma_unmap_single(bp->bus_dev,
- bp->descr_block_virt->rcv_data[entry].long_1,
- NEW_SKB_SIZE,
+ dma_addr,
+ PI_RCV_DATA_K_SIZE_MAX,
DMA_FROM_DEVICE);
skb_reserve(skb, RCV_BUFF_K_PADDING);
bp->p_rcv_buff_va[entry] = (char *)newskb;
- bp->descr_block_virt->rcv_data[entry].long_1 =
- (u32)dma_map_single(bp->bus_dev,
- newskb->data,
- NEW_SKB_SIZE,
- DMA_FROM_DEVICE);
- } else
- skb = NULL;
- } else
+ bp->descr_block_virt->rcv_data[entry].long_1 = (u32)new_dma_addr;
+ }
+ }
+ if (!newskb)
#endif
- skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */
+ /* Alloc new buffer to pass up,
+ * add room for PRH. */
+ skb = netdev_alloc_skb(bp->dev,
+ pkt_len + 3);
if (skb == NULL)
{
printk("%s: Could not allocate receive buffer. Dropping packet.\n", bp->dev->name);
@@ -3080,6 +3114,12 @@ static void dfx_rcv_queue_process(
else {
if (!rx_in_place) {
/* Receive buffer allocated, pass receive packet up */
+ dma_sync_single_for_cpu(
+ bp->bus_dev,
+ dma_addr +
+ RCV_BUFF_K_PADDING,
+ pkt_len + 3,
+ DMA_FROM_DEVICE);
skb_copy_to_linear_data(skb,
p_buff + RCV_BUFF_K_PADDING,
@@ -3182,6 +3222,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
u8 prod; /* local transmit producer index */
PI_XMT_DESCR *p_xmt_descr; /* ptr to transmit descriptor block entry */
XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
+ dma_addr_t dma_addr;
unsigned long flags;
netif_stop_queue(dev);
@@ -3229,6 +3270,20 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
}
}
+ /* Write the three PRH bytes immediately before the FC byte */
+
+ skb_push(skb, 3);
+ skb->data[0] = DFX_PRH0_BYTE; /* these byte values are defined */
+ skb->data[1] = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */
+ skb->data[2] = DFX_PRH2_BYTE; /* specification */
+
+ dma_addr = dma_map_single(bp->bus_dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(bp->bus_dev, dma_addr)) {
+ skb_pull(skb, 3);
+ return NETDEV_TX_BUSY;
+ }
+
spin_lock_irqsave(&bp->lock, flags);
/* Get the current producer and the next free xmt data descriptor */
@@ -3249,13 +3304,6 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]); /* also bump producer index */
- /* Write the three PRH bytes immediately before the FC byte */
-
- skb_push(skb,3);
- skb->data[0] = DFX_PRH0_BYTE; /* these byte values are defined */
- skb->data[1] = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */
- skb->data[2] = DFX_PRH2_BYTE; /* specification */
-
/*
* Write the descriptor with buffer info and bump producer
*
@@ -3284,8 +3332,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
*/
p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
- p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+ p_xmt_descr->long_1 = (u32)dma_addr;
/*
* Verify that descriptor is actually available
@@ -3448,8 +3495,13 @@ static void dfx_rcv_flush( DFX_board_t *bp )
{
struct sk_buff *skb;
skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
- if (skb)
+ if (skb) {
+ dma_unmap_single(bp->bus_dev,
+ bp->descr_block_virt->rcv_data[i+j].long_1,
+ PI_RCV_DATA_K_SIZE_MAX,
+ DMA_FROM_DEVICE);
dev_kfree_skb(skb);
+ }
bp->p_rcv_buff_va[i+j] = NULL;
}
@@ -3612,7 +3664,7 @@ static int __maybe_unused dfx_dev_unregister(struct device *);
static int dfx_pci_register(struct pci_dev *, const struct pci_device_id *);
static void dfx_pci_unregister(struct pci_dev *);
-static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
+static const struct pci_device_id dfx_pci_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
{ }
};
diff --git a/drivers/net/fddi/defxx.h b/drivers/net/fddi/defxx.h
index 19a6f64df198..adb63f3f7b4a 100644
--- a/drivers/net/fddi/defxx.h
+++ b/drivers/net/fddi/defxx.h
@@ -1693,7 +1693,7 @@ typedef union
/* Only execute special print call when debug driver was built */
#ifdef DEFXX_DEBUG
-#define DBG_printk(args...) printk(## args)
+#define DBG_printk(args...) printk(args)
#else
#define DBG_printk(args...)
#endif
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index d5f58121b2e2..51acc6d86e91 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -149,7 +149,7 @@ extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
extern void mac_drv_clear_rx_queue(struct s_smc *smc);
extern void enable_tx_irq(struct s_smc *smc, u_short queue);
-static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = {
+static const struct pci_device_id skfddi_pci_tbl[] = {
{ PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
{ } /* Terminating entry */
};
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 66e2b19ef709..c3c4051a089d 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -596,7 +596,8 @@ static int sixpack_open(struct tty_struct *tty)
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
- dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
+ dev = alloc_netdev(sizeof(struct sixpack), "sp%d", NET_NAME_UNKNOWN,
+ sp_setup);
if (!dev) {
err = -ENOMEM;
goto out;
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 484f77ec2ce1..a98c153f371e 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -1206,7 +1206,7 @@ static int __init init_baycomepp(void)
struct net_device *dev;
dev = alloc_netdev(sizeof(struct baycom_state), "bce%d",
- baycom_epp_dev_setup);
+ NET_NAME_UNKNOWN, baycom_epp_dev_setup);
if (!dev) {
printk(KERN_WARNING "bce%d : out of memory\n", i);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index d50b23cf9ea9..c2894e43840e 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -501,8 +501,8 @@ static int bpq_new_device(struct net_device *edev)
struct net_device *ndev;
struct bpqdev *bpq;
- ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d",
- bpq_setup);
+ ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d", NET_NAME_UNKNOWN,
+ bpq_setup);
if (!ndev)
return -ENOMEM;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 6636022a1027..0fad408f24aa 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -466,7 +466,7 @@ static int __init setup_adapter(int card_base, int type, int n)
if (!info)
goto out;
- info->dev[0] = alloc_netdev(0, "", dev_setup);
+ info->dev[0] = alloc_netdev(0, "", NET_NAME_UNKNOWN, dev_setup);
if (!info->dev[0]) {
printk(KERN_ERR "dmascc: "
"could not allocate memory for %s at %#3x\n",
@@ -474,7 +474,7 @@ static int __init setup_adapter(int card_base, int type, int n)
goto out1;
}
- info->dev[1] = alloc_netdev(0, "", dev_setup);
+ info->dev[1] = alloc_netdev(0, "", NET_NAME_UNKNOWN, dev_setup);
if (!info->dev[1]) {
printk(KERN_ERR "dmascc: "
"could not allocate memory for %s at %#3x\n",
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 5d78c1d08abd..c67a27245072 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -699,7 +699,7 @@ struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
if (privsize < sizeof(struct hdlcdrv_state))
privsize = sizeof(struct hdlcdrv_state);
- dev = alloc_netdev(privsize, ifname, hdlcdrv_setup);
+ dev = alloc_netdev(privsize, ifname, NET_NAME_UNKNOWN, hdlcdrv_setup);
if (!dev)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 8a6c720a4cc9..f990bb1c3e02 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -734,7 +734,8 @@ static int mkiss_open(struct tty_struct *tty)
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
- dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
+ dev = alloc_netdev(sizeof(struct mkiss), "ax%d", NET_NAME_UNKNOWN,
+ ax_setup);
if (!dev) {
err = -ENOMEM;
goto out;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 4bc6ee8e7987..57be9e0e98a6 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1515,7 +1515,7 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
int err;
struct net_device *dev;
- dev = alloc_netdev(0, name, scc_net_setup);
+ dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, scc_net_setup);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 81901659cc9e..717433cfb81d 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1147,7 +1147,7 @@ static int __init yam_init_driver(void)
sprintf(name, "yam%d", i);
dev = alloc_netdev(sizeof(struct yam_port), name,
- yam_setup);
+ NET_NAME_UNKNOWN, yam_setup);
if (!dev) {
pr_err("yam: cannot allocate net device\n");
err = -ENOMEM;
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
index e580583f196d..95c0b45a68fb 100644
--- a/drivers/net/hippi/rrunner.c
+++ b/drivers/net/hippi/rrunner.c
@@ -1668,7 +1668,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
-static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = {
+static const struct pci_device_id rr_pci_tbl[] = {
{ PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0,}
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 6cc37c15e0bf..d5e07def6a59 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -170,6 +170,7 @@ struct rndis_device {
enum rndis_device_state state;
bool link_state;
+ bool link_change;
atomic_t new_req_id;
spinlock_t request_lock;
@@ -185,7 +186,7 @@ int netvsc_device_remove(struct hv_device *device);
int netvsc_send(struct hv_device *device,
struct hv_netvsc_packet *packet);
void netvsc_linkstatus_callback(struct hv_device *device_obj,
- unsigned int status);
+ struct rndis_message *resp);
int netvsc_recv_callback(struct hv_device *device_obj,
struct hv_netvsc_packet *packet,
struct ndis_tcp_ip_checksum_info *csum_info);
@@ -584,7 +585,7 @@ struct nvsp_message {
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
-#define NETVSC_SEND_BUFFER_SIZE (1024 * 1024) /* 1MB */
+#define NETVSC_SEND_BUFFER_SIZE (1024 * 1024 * 15) /* 15MB */
#define NETVSC_INVALID_INDEX -1
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d97d5f39a04e..66979cf7fca6 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -193,8 +193,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
}
if (net_device->send_buf) {
/* Free up the receive buffer */
- free_pages((unsigned long)net_device->send_buf,
- get_order(net_device->send_buf_size));
+ vfree(net_device->send_buf);
net_device->send_buf = NULL;
}
kfree(net_device->send_section_map);
@@ -303,9 +302,7 @@ static int netvsc_init_buf(struct hv_device *device)
/* Now setup the send buffer.
*/
- net_device->send_buf =
- (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
- get_order(net_device->send_buf_size));
+ net_device->send_buf = vzalloc(net_device->send_buf_size);
if (!net_device->send_buf) {
netdev_err(ndev, "unable to allocate send "
"buffer of size %d\n", net_device->send_buf_size);
@@ -1096,9 +1093,7 @@ close:
vmbus_close(device->channel);
cleanup:
-
- if (net_device)
- kfree(net_device);
+ kfree(net_device);
return ret;
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 4fd71b75e666..a9c5eaadc426 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -579,8 +579,9 @@ drop:
* netvsc_linkstatus_callback - Link up/down notification
*/
void netvsc_linkstatus_callback(struct hv_device *device_obj,
- unsigned int status)
+ struct rndis_message *resp)
{
+ struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
struct net_device *net;
struct net_device_context *ndev_ctx;
struct netvsc_device *net_device;
@@ -589,7 +590,19 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
net_device = hv_get_drvdata(device_obj);
rdev = net_device->extension;
- rdev->link_state = status != 1;
+ switch (indicate->status) {
+ case RNDIS_STATUS_MEDIA_CONNECT:
+ rdev->link_state = false;
+ break;
+ case RNDIS_STATUS_MEDIA_DISCONNECT:
+ rdev->link_state = true;
+ break;
+ case RNDIS_STATUS_NETWORK_CHANGE:
+ rdev->link_change = true;
+ break;
+ default:
+ return;
+ }
net = net_device->ndev;
@@ -597,7 +610,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
return;
ndev_ctx = netdev_priv(net);
- if (status == 1) {
+ if (!rdev->link_state) {
schedule_delayed_work(&ndev_ctx->dwork, 0);
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
} else {
@@ -736,6 +749,14 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
return err;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void netvsc_poll_controller(struct net_device *net)
+{
+ /* As netvsc_start_xmit() works synchronous we don't have to
+ * trigger anything here.
+ */
+}
+#endif
static const struct ethtool_ops ethtool_ops = {
.get_drvinfo = netvsc_get_drvinfo,
@@ -751,6 +772,9 @@ static const struct net_device_ops device_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = netvsc_set_mac_addr,
.ndo_select_queue = netvsc_select_queue,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = netvsc_poll_controller,
+#endif
};
/*
@@ -767,7 +791,9 @@ static void netvsc_link_change(struct work_struct *w)
struct net_device *net;
struct netvsc_device *net_device;
struct rndis_device *rdev;
- bool notify;
+ bool notify, refresh = false;
+ char *argv[] = { "/etc/init.d/network", "restart", NULL };
+ char *envp[] = { "HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
rtnl_lock();
@@ -782,10 +808,17 @@ static void netvsc_link_change(struct work_struct *w)
} else {
netif_carrier_on(net);
notify = true;
+ if (rdev->link_change) {
+ rdev->link_change = false;
+ refresh = true;
+ }
}
rtnl_unlock();
+ if (refresh)
+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+
if (notify)
netdev_notify_peers(net);
}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 99c527adae5b..2b86f0b6f6d1 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -320,25 +320,6 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
}
}
-static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
- struct rndis_message *resp)
-{
- struct rndis_indicate_status *indicate =
- &resp->msg.indicate_status;
-
- if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
- netvsc_linkstatus_callback(
- dev->net_dev->dev, 1);
- } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
- netvsc_linkstatus_callback(
- dev->net_dev->dev, 0);
- } else {
- /*
- * TODO:
- */
- }
-}
-
/*
* Get the Per-Packet-Info with the specified type
* return NULL if not found.
@@ -464,7 +445,7 @@ int rndis_filter_receive(struct hv_device *dev,
case RNDIS_MSG_INDICATE:
/* notification msgs */
- rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
+ netvsc_linkstatus_callback(dev, rndis_msg);
break;
default:
netdev_err(ndev,
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 3e89beab64fd..391a916622a9 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -34,6 +34,7 @@ config IEEE802154_AT86RF230
depends on IEEE802154_DRIVERS && MAC802154
tristate "AT86RF230/231/233/212 transceiver driver"
depends on SPI
+ select REGMAP_SPI
---help---
Say Y here to enable the at86rf230/231/233/212 SPI 802.15.4 wireless
controller.
@@ -51,3 +52,14 @@ config IEEE802154_MRF24J40
This driver can also be built as a module. To do so, say M here.
the module will be called 'mrf24j40'.
+
+config IEEE802154_CC2520
+ depends on IEEE802154_DRIVERS && MAC802154
+ tristate "CC2520 transceiver driver"
+ depends on SPI
+ ---help---
+ Say Y here to enable the CC2520 SPI 802.15.4 wireless
+ controller.
+
+ This driver can also be built as a module. To do so, say M here.
+ the module will be called 'cc2520'.
diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
index abb0c08decb0..655cb95e6e24 100644
--- a/drivers/net/ieee802154/Makefile
+++ b/drivers/net/ieee802154/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
+obj-$(CONFIG_IEEE802154_CC2520) += cc2520.o
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 50899416f668..c9d2a752abd7 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -19,6 +19,7 @@
* Written by:
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ * Alexander Aring <aar@pengutronix.de>
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -26,43 +27,75 @@
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/spi/spi.h>
#include <linux/spi/at86rf230.h>
+#include <linux/regmap.h>
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
+#include <net/ieee802154.h>
#include <net/mac802154.h>
#include <net/wpan-phy.h>
-struct at86rf230_local {
- struct spi_device *spi;
+struct at86rf230_local;
+/* at86rf2xx chip depend data.
+ * All timings are in us.
+ */
+struct at86rf2xx_chip_data {
+ u16 t_sleep_cycle;
+ u16 t_channel_switch;
+ u16 t_reset_to_off;
+ u16 t_off_to_aack;
+ u16 t_off_to_tx_on;
+ u16 t_frame;
+ u16 t_p_ack;
+ /* short interframe spacing time */
+ u16 t_sifs;
+ /* long interframe spacing time */
+ u16 t_lifs;
+ /* completion timeout for tx in msecs */
+ u16 t_tx_timeout;
+ int rssi_base_val;
- u8 part;
- u8 vers;
+ int (*set_channel)(struct at86rf230_local *, int, int);
+ int (*get_desense_steps)(struct at86rf230_local *, s32);
+};
- u8 buf[2];
- struct mutex bmux;
+#define AT86RF2XX_MAX_BUF (127 + 3)
- struct work_struct irqwork;
- struct completion tx_complete;
+struct at86rf230_state_change {
+ struct at86rf230_local *lp;
+
+ struct spi_message msg;
+ struct spi_transfer trx;
+ u8 buf[AT86RF2XX_MAX_BUF];
+
+ void (*complete)(void *context);
+ u8 from_state;
+ u8 to_state;
+};
+
+struct at86rf230_local {
+ struct spi_device *spi;
struct ieee802154_dev *dev;
+ struct at86rf2xx_chip_data *data;
+ struct regmap *regmap;
- spinlock_t lock;
- bool irq_busy;
- bool is_tx;
- bool tx_aret;
+ struct completion state_complete;
+ struct at86rf230_state_change state;
- int rssi_base_val;
-};
+ struct at86rf230_state_change irq;
-static bool is_rf212(struct at86rf230_local *local)
-{
- return local->part == 7;
-}
+ bool tx_aret;
+ bool is_tx;
+ /* spinlock for is_tx protection */
+ spinlock_t lock;
+ struct completion tx_complete;
+ struct sk_buff *tx_skb;
+ struct at86rf230_state_change tx;
+};
#define RG_TRX_STATUS (0x01)
#define SR_TRX_STATUS 0x01, 0x1f, 0
@@ -256,344 +289,753 @@ static bool is_rf212(struct at86rf230_local *local)
#define STATE_BUSY_RX_AACK_NOCLK 0x1E
#define STATE_TRANSITION_IN_PROGRESS 0x1F
+#define AT86RF2XX_NUMREGS 0x3F
+
static int
-__at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
- u8 *version)
+at86rf230_async_state_change(struct at86rf230_local *lp,
+ struct at86rf230_state_change *ctx,
+ const u8 state, void (*complete)(void *context));
+
+static inline int
+__at86rf230_write(struct at86rf230_local *lp,
+ unsigned int addr, unsigned int data)
{
- u8 data[4];
- u8 *buf = kmalloc(2, GFP_KERNEL);
- int status;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = buf,
- .rx_buf = buf,
- };
- u8 reg;
-
- if (!buf)
- return -ENOMEM;
+ return regmap_write(lp->regmap, addr, data);
+}
- for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) {
- buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
- buf[1] = 0xff;
- dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
+static inline int
+__at86rf230_read(struct at86rf230_local *lp,
+ unsigned int addr, unsigned int *data)
+{
+ return regmap_read(lp->regmap, addr, data);
+}
- status = spi_sync(spi, &msg);
- dev_vdbg(&spi->dev, "status = %d\n", status);
- if (msg.status)
- status = msg.status;
+static inline int
+at86rf230_read_subreg(struct at86rf230_local *lp,
+ unsigned int addr, unsigned int mask,
+ unsigned int shift, unsigned int *data)
+{
+ int rc;
- dev_vdbg(&spi->dev, "status = %d\n", status);
- dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]);
+ rc = __at86rf230_read(lp, addr, data);
+ if (rc > 0)
+ *data = (*data & mask) >> shift;
- if (status == 0)
- data[reg - RG_PART_NUM] = buf[1];
- else
- break;
+ return rc;
+}
+
+static inline int
+at86rf230_write_subreg(struct at86rf230_local *lp,
+ unsigned int addr, unsigned int mask,
+ unsigned int shift, unsigned int data)
+{
+ return regmap_update_bits(lp->regmap, addr, mask, data << shift);
+}
+
+static bool
+at86rf230_reg_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RG_TRX_STATE:
+ case RG_TRX_CTRL_0:
+ case RG_TRX_CTRL_1:
+ case RG_PHY_TX_PWR:
+ case RG_PHY_ED_LEVEL:
+ case RG_PHY_CC_CCA:
+ case RG_CCA_THRES:
+ case RG_RX_CTRL:
+ case RG_SFD_VALUE:
+ case RG_TRX_CTRL_2:
+ case RG_ANT_DIV:
+ case RG_IRQ_MASK:
+ case RG_VREG_CTRL:
+ case RG_BATMON:
+ case RG_XOSC_CTRL:
+ case RG_RX_SYN:
+ case RG_XAH_CTRL_1:
+ case RG_FTN_CTRL:
+ case RG_PLL_CF:
+ case RG_PLL_DCU:
+ case RG_SHORT_ADDR_0:
+ case RG_SHORT_ADDR_1:
+ case RG_PAN_ID_0:
+ case RG_PAN_ID_1:
+ case RG_IEEE_ADDR_0:
+ case RG_IEEE_ADDR_1:
+ case RG_IEEE_ADDR_2:
+ case RG_IEEE_ADDR_3:
+ case RG_IEEE_ADDR_4:
+ case RG_IEEE_ADDR_5:
+ case RG_IEEE_ADDR_6:
+ case RG_IEEE_ADDR_7:
+ case RG_XAH_CTRL_0:
+ case RG_CSMA_SEED_0:
+ case RG_CSMA_SEED_1:
+ case RG_CSMA_BE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+at86rf230_reg_readable(struct device *dev, unsigned int reg)
+{
+ bool rc;
+
+ /* all writeable are also readable */
+ rc = at86rf230_reg_writeable(dev, reg);
+ if (rc)
+ return rc;
+
+ /* readonly regs */
+ switch (reg) {
+ case RG_TRX_STATUS:
+ case RG_PHY_RSSI:
+ case RG_IRQ_STATUS:
+ case RG_PART_NUM:
+ case RG_VERSION_NUM:
+ case RG_MAN_ID_1:
+ case RG_MAN_ID_0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+at86rf230_reg_volatile(struct device *dev, unsigned int reg)
+{
+ /* can be changed during runtime */
+ switch (reg) {
+ case RG_TRX_STATUS:
+ case RG_TRX_STATE:
+ case RG_PHY_RSSI:
+ case RG_PHY_ED_LEVEL:
+ case RG_IRQ_STATUS:
+ case RG_VREG_CTRL:
+ return true;
+ default:
+ return false;
}
+}
- if (status == 0) {
- *part = data[0];
- *version = data[1];
- *man_id = (data[3] << 8) | data[2];
+static bool
+at86rf230_reg_precious(struct device *dev, unsigned int reg)
+{
+ /* don't clear irq line on read */
+ switch (reg) {
+ case RG_IRQ_STATUS:
+ return true;
+ default:
+ return false;
}
+}
- kfree(buf);
+static struct regmap_config at86rf230_regmap_spi_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .write_flag_mask = CMD_REG | CMD_WRITE,
+ .read_flag_mask = CMD_REG,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = AT86RF2XX_NUMREGS,
+ .writeable_reg = at86rf230_reg_writeable,
+ .readable_reg = at86rf230_reg_readable,
+ .volatile_reg = at86rf230_reg_volatile,
+ .precious_reg = at86rf230_reg_precious,
+};
- return status;
+static void
+at86rf230_async_error_recover(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+
+ at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
}
-static int
-__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
+static void
+at86rf230_async_error(struct at86rf230_local *lp,
+ struct at86rf230_state_change *ctx, int rc)
{
- u8 *buf = lp->buf;
- int status;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = buf,
- };
-
- buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
- buf[1] = data;
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- status = spi_sync(lp->spi, &msg);
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- if (msg.status)
- status = msg.status;
-
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
- return status;
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
+
+ at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+ at86rf230_async_error_recover);
}
+/* Generic function to get some register value in async mode */
static int
-__at86rf230_read_subreg(struct at86rf230_local *lp,
- u8 addr, u8 mask, int shift, u8 *data)
+at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
+ struct at86rf230_state_change *ctx,
+ void (*complete)(void *context))
{
- u8 *buf = lp->buf;
- int status;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = buf,
- .rx_buf = buf,
- };
-
- buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
- buf[1] = 0xff;
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
-
- status = spi_sync(lp->spi, &msg);
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- if (msg.status)
- status = msg.status;
-
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
- if (status == 0)
- *data = (buf[1] & mask) >> shift;
-
- return status;
+ u8 *tx_buf = ctx->buf;
+
+ tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
+ ctx->trx.len = 2;
+ ctx->msg.complete = complete;
+ return spi_async(lp->spi, &ctx->msg);
}
-static int
-at86rf230_read_subreg(struct at86rf230_local *lp,
- u8 addr, u8 mask, int shift, u8 *data)
+static void
+at86rf230_async_state_assert(void *context)
{
- int status;
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ const u8 *buf = ctx->buf;
+ const u8 trx_state = buf[1] & 0x1f;
+
+ /* Assert state change */
+ if (trx_state != ctx->to_state) {
+ /* Special handling if transceiver state is in
+ * STATE_BUSY_RX_AACK and a SHR was detected.
+ */
+ if (trx_state == STATE_BUSY_RX_AACK) {
+ /* Undocumented race condition. If we send a state
+ * change to STATE_RX_AACK_ON the transceiver could
+ * change his state automatically to STATE_BUSY_RX_AACK
+ * if a SHR was detected. This is not an error, but we
+ * can't assert this.
+ */
+ if (ctx->to_state == STATE_RX_AACK_ON)
+ goto done;
+
+ /* If we change to STATE_TX_ON without forcing and
+ * transceiver state is STATE_BUSY_RX_AACK, we wait
+ * 'tFrame + tPAck' receiving time. In this time the
+ * PDU should be received. If the transceiver is still
+ * in STATE_BUSY_RX_AACK, we run a force state change
+ * to STATE_TX_ON. This is a timeout handling, if the
+ * transceiver stucks in STATE_BUSY_RX_AACK.
+ */
+ if (ctx->to_state == STATE_TX_ON) {
+ at86rf230_async_state_change(lp, ctx,
+ STATE_FORCE_TX_ON,
+ ctx->complete);
+ return;
+ }
+ }
+
- mutex_lock(&lp->bmux);
- status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
- mutex_unlock(&lp->bmux);
+ dev_warn(&lp->spi->dev, "unexcept state change from 0x%02x to 0x%02x. Actual state: 0x%02x\n",
+ ctx->from_state, ctx->to_state, trx_state);
+ }
- return status;
+done:
+ if (ctx->complete)
+ ctx->complete(context);
}
-static int
-at86rf230_write_subreg(struct at86rf230_local *lp,
- u8 addr, u8 mask, int shift, u8 data)
+/* Do state change timing delay. */
+static void
+at86rf230_async_state_delay(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ struct at86rf2xx_chip_data *c = lp->data;
+ bool force = false;
+ int rc;
+
+ /* The force state changes are will show as normal states in the
+ * state status subregister. We change the to_state to the
+ * corresponding one and remember if it was a force change, this
+ * differs if we do a state change from STATE_BUSY_RX_AACK.
+ */
+ switch (ctx->to_state) {
+ case STATE_FORCE_TX_ON:
+ ctx->to_state = STATE_TX_ON;
+ force = true;
+ break;
+ case STATE_FORCE_TRX_OFF:
+ ctx->to_state = STATE_TRX_OFF;
+ force = true;
+ break;
+ default:
+ break;
+ }
+
+ switch (ctx->from_state) {
+ case STATE_TRX_OFF:
+ switch (ctx->to_state) {
+ case STATE_RX_AACK_ON:
+ usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10);
+ goto change;
+ case STATE_TX_ON:
+ usleep_range(c->t_off_to_tx_on,
+ c->t_off_to_tx_on + 10);
+ goto change;
+ default:
+ break;
+ }
+ break;
+ case STATE_BUSY_RX_AACK:
+ switch (ctx->to_state) {
+ case STATE_TX_ON:
+ /* Wait for worst case receiving time if we
+ * didn't make a force change from BUSY_RX_AACK
+ * to TX_ON.
+ */
+ if (!force) {
+ usleep_range(c->t_frame + c->t_p_ack,
+ c->t_frame + c->t_p_ack + 1000);
+ goto change;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ /* Default value, means RESET state */
+ case STATE_P_ON:
+ switch (ctx->to_state) {
+ case STATE_TRX_OFF:
+ usleep_range(c->t_reset_to_off, c->t_reset_to_off + 10);
+ goto change;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Default delay is 1us in the most cases */
+ udelay(1);
+
+change:
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_assert);
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
+}
+
+static void
+at86rf230_async_state_change_start(void *context)
{
- int status;
- u8 val;
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ u8 *buf = ctx->buf;
+ const u8 trx_state = buf[1] & 0x1f;
+ int rc;
- mutex_lock(&lp->bmux);
- status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
- if (status)
- goto out;
+ /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
+ if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
+ udelay(1);
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_change_start);
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
+ return;
+ }
- val &= ~mask;
- val |= (data << shift) & mask;
+ /* Check if we already are in the state which we change in */
+ if (trx_state == ctx->to_state) {
+ if (ctx->complete)
+ ctx->complete(context);
+ return;
+ }
- status = __at86rf230_write(lp, addr, val);
-out:
- mutex_unlock(&lp->bmux);
+ /* Set current state to the context of state change */
+ ctx->from_state = trx_state;
- return status;
+ /* Going into the next step for a state change which do a timing
+ * relevant delay.
+ */
+ buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+ buf[1] = ctx->to_state;
+ ctx->trx.len = 2;
+ ctx->msg.complete = at86rf230_async_state_delay;
+ rc = spi_async(lp->spi, &ctx->msg);
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
}
static int
-at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
+at86rf230_async_state_change(struct at86rf230_local *lp,
+ struct at86rf230_state_change *ctx,
+ const u8 state, void (*complete)(void *context))
{
- u8 *buf = lp->buf;
- int status;
- struct spi_message msg;
- struct spi_transfer xfer_head = {
- .len = 2,
- .tx_buf = buf,
-
- };
- struct spi_transfer xfer_buf = {
- .len = len,
- .tx_buf = data,
- };
-
- mutex_lock(&lp->bmux);
- buf[0] = CMD_WRITE | CMD_FB;
- buf[1] = len + 2; /* 2 bytes for CRC that isn't written */
-
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
- spi_message_init(&msg);
- spi_message_add_tail(&xfer_head, &msg);
- spi_message_add_tail(&xfer_buf, &msg);
-
- status = spi_sync(lp->spi, &msg);
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- if (msg.status)
- status = msg.status;
-
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
- mutex_unlock(&lp->bmux);
- return status;
+ /* Initialization for the state change context */
+ ctx->to_state = state;
+ ctx->complete = complete;
+ return at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_change_start);
}
+static void
+at86rf230_sync_state_change_complete(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+
+ complete(&lp->state_complete);
+}
+
+/* This function do a sync framework above the async state change.
+ * Some callbacks of the IEEE 802.15.4 driver interface need to be
+ * handled synchronously.
+ */
static int
-at86rf230_read_fbuf(struct at86rf230_local *lp, u8 *data, u8 *len, u8 *lqi)
+at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state)
{
- u8 *buf = lp->buf;
- int status;
- struct spi_message msg;
- struct spi_transfer xfer_head = {
- .len = 2,
- .tx_buf = buf,
- .rx_buf = buf,
- };
- struct spi_transfer xfer_head1 = {
- .len = 2,
- .tx_buf = buf,
- .rx_buf = buf,
- };
- struct spi_transfer xfer_buf = {
- .len = 0,
- .rx_buf = data,
- };
-
- mutex_lock(&lp->bmux);
+ int rc;
- buf[0] = CMD_FB;
- buf[1] = 0x00;
+ rc = at86rf230_async_state_change(lp, &lp->state, state,
+ at86rf230_sync_state_change_complete);
+ if (rc) {
+ at86rf230_async_error(lp, &lp->state, rc);
+ return rc;
+ }
- spi_message_init(&msg);
- spi_message_add_tail(&xfer_head, &msg);
+ rc = wait_for_completion_timeout(&lp->state_complete,
+ msecs_to_jiffies(100));
+ if (!rc)
+ return -ETIMEDOUT;
- status = spi_sync(lp->spi, &msg);
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
+ return 0;
+}
- xfer_buf.len = *(buf + 1) + 1;
- *len = buf[1];
+static void
+at86rf230_tx_complete(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
- buf[0] = CMD_FB;
- buf[1] = 0x00;
+ complete(&lp->tx_complete);
+}
- spi_message_init(&msg);
- spi_message_add_tail(&xfer_head1, &msg);
- spi_message_add_tail(&xfer_buf, &msg);
+static void
+at86rf230_tx_on(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ int rc;
+
+ rc = at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
+ at86rf230_tx_complete);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+}
- status = spi_sync(lp->spi, &msg);
+static void
+at86rf230_tx_trac_error(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ int rc;
- if (msg.status)
- status = msg.status;
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+ at86rf230_tx_on);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+}
- dev_vdbg(&lp->spi->dev, "status = %d\n", status);
- dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
- dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
+static void
+at86rf230_tx_trac_check(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ const u8 *buf = ctx->buf;
+ const u8 trac = (buf[1] & 0xe0) >> 5;
+ int rc;
- if (status) {
- if (lqi && (*len > lp->buf[1]))
- *lqi = data[lp->buf[1]];
+ /* If trac status is different than zero we need to do a state change
+ * to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver
+ * state to TX_ON.
+ */
+ if (trac) {
+ rc = at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+ at86rf230_tx_trac_error);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+ return;
}
- mutex_unlock(&lp->bmux);
- return status;
+ at86rf230_tx_on(context);
}
-static int
-at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
+
+static void
+at86rf230_tx_trac_status(void *context)
{
- might_sleep();
- BUG_ON(!level);
- *level = 0xbe;
- return 0;
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ int rc;
+
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+ at86rf230_tx_trac_check);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+}
+
+static void
+at86rf230_rx(struct at86rf230_local *lp,
+ const u8 *data, u8 len)
+{
+ u8 lqi;
+ struct sk_buff *skb;
+ u8 rx_local_buf[AT86RF2XX_MAX_BUF];
+
+ if (len < 2)
+ return;
+
+ /* read full frame buffer and invalid lqi value to lowest
+ * indicator if frame was is in a corrupted state.
+ */
+ if (len > IEEE802154_MTU) {
+ lqi = 0;
+ len = IEEE802154_MTU;
+ dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
+ } else {
+ lqi = data[len];
+ }
+
+ memcpy(rx_local_buf, data, len);
+ enable_irq(lp->spi->irq);
+
+ skb = alloc_skb(IEEE802154_MTU, GFP_ATOMIC);
+ if (!skb) {
+ dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
+ return;
+ }
+
+ memcpy(skb_put(skb, len), rx_local_buf, len);
+
+ /* We do not put CRC into the frame */
+ skb_trim(skb, len - 2);
+
+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
+}
+
+static void
+at86rf230_rx_read_frame_complete(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ const u8 *buf = lp->irq.buf;
+ const u8 len = buf[1];
+
+ at86rf230_rx(lp, buf + 2, len);
}
static int
-at86rf230_state(struct ieee802154_dev *dev, int state)
+at86rf230_rx_read_frame(struct at86rf230_local *lp)
{
- struct at86rf230_local *lp = dev->priv;
+ u8 *buf = lp->irq.buf;
+
+ buf[0] = CMD_FB;
+ lp->irq.trx.len = AT86RF2XX_MAX_BUF;
+ lp->irq.msg.complete = at86rf230_rx_read_frame_complete;
+ return spi_async(lp->spi, &lp->irq.msg);
+}
+
+static void
+at86rf230_rx_trac_check(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
int rc;
- u8 val;
- u8 desired_status;
- might_sleep();
+ /* Possible check on trac status here. This could be useful to make
+ * some stats why receive is failed. Not used at the moment, but it's
+ * maybe timing relevant. Datasheet doesn't say anything about this.
+ * The programming guide say do it so.
+ */
- if (state == STATE_FORCE_TX_ON)
- desired_status = STATE_TX_ON;
- else if (state == STATE_FORCE_TRX_OFF)
- desired_status = STATE_TRX_OFF;
- else
- desired_status = state;
+ rc = at86rf230_rx_read_frame(lp);
+ if (rc) {
+ enable_irq(lp->spi->irq);
+ at86rf230_async_error(lp, ctx, rc);
+ }
+}
+
+static int
+at86rf230_irq_trx_end(struct at86rf230_local *lp)
+{
+ spin_lock(&lp->lock);
+ if (lp->is_tx) {
+ lp->is_tx = 0;
+ spin_unlock(&lp->lock);
+ enable_irq(lp->spi->irq);
+
+ if (lp->tx_aret)
+ return at86rf230_async_state_change(lp, &lp->irq,
+ STATE_FORCE_TX_ON,
+ at86rf230_tx_trac_status);
+ else
+ return at86rf230_async_state_change(lp, &lp->irq,
+ STATE_RX_AACK_ON,
+ at86rf230_tx_complete);
+ } else {
+ spin_unlock(&lp->lock);
+ return at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
+ at86rf230_rx_trac_check);
+ }
+}
- do {
- rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
+static void
+at86rf230_irq_status(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ const u8 *buf = lp->irq.buf;
+ const u8 irq = buf[1];
+ int rc;
+
+ if (irq & IRQ_TRX_END) {
+ rc = at86rf230_irq_trx_end(lp);
if (rc)
- goto err;
- } while (val == STATE_TRANSITION_IN_PROGRESS);
+ at86rf230_async_error(lp, ctx, rc);
+ } else {
+ enable_irq(lp->spi->irq);
+ dev_err(&lp->spi->dev, "not supported irq %02x received\n",
+ irq);
+ }
+}
- if (val == desired_status)
- return 0;
+static irqreturn_t at86rf230_isr(int irq, void *data)
+{
+ struct at86rf230_local *lp = data;
+ struct at86rf230_state_change *ctx = &lp->irq;
+ u8 *buf = ctx->buf;
+ int rc;
- /* state is equal to phy states */
- rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
- if (rc)
- goto err;
+ disable_irq_nosync(lp->spi->irq);
- do {
- rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
- if (rc)
- goto err;
- } while (val == STATE_TRANSITION_IN_PROGRESS);
+ buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
+ ctx->trx.len = 2;
+ ctx->msg.complete = at86rf230_irq_status;
+ rc = spi_async(lp->spi, &ctx->msg);
+ if (rc) {
+ at86rf230_async_error(lp, ctx, rc);
+ return IRQ_NONE;
+ }
+ return IRQ_HANDLED;
+}
- if (val == desired_status ||
- (desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
- (desired_status == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK))
- return 0;
+static void
+at86rf230_write_frame_complete(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ u8 *buf = ctx->buf;
+ int rc;
- pr_err("unexpected state change: %d, asked for %d\n", val, state);
- return -EBUSY;
+ buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+ buf[1] = STATE_BUSY_TX;
+ ctx->trx.len = 2;
+ ctx->msg.complete = NULL;
+ rc = spi_async(lp->spi, &ctx->msg);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+}
-err:
- pr_err("error: %d\n", rc);
- return rc;
+static void
+at86rf230_write_frame(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ struct sk_buff *skb = lp->tx_skb;
+ u8 *buf = lp->tx.buf;
+ int rc;
+
+ spin_lock(&lp->lock);
+ lp->is_tx = 1;
+ spin_unlock(&lp->lock);
+
+ buf[0] = CMD_FB | CMD_WRITE;
+ buf[1] = skb->len + 2;
+ memcpy(buf + 2, skb->data, skb->len);
+ lp->tx.trx.len = skb->len + 2;
+ lp->tx.msg.complete = at86rf230_write_frame_complete;
+ rc = spi_async(lp->spi, &lp->tx.msg);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+}
+
+static void
+at86rf230_xmit_tx_on(void *context)
+{
+ struct at86rf230_state_change *ctx = context;
+ struct at86rf230_local *lp = ctx->lp;
+ int rc;
+
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
+ at86rf230_write_frame);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static int
-at86rf230_start(struct ieee802154_dev *dev)
+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
{
struct at86rf230_local *lp = dev->priv;
- u8 rc;
+ struct at86rf230_state_change *ctx = &lp->tx;
- rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
- if (rc)
- return rc;
+ void (*tx_complete)(void *context) = at86rf230_write_frame;
+ int rc;
- rc = at86rf230_state(dev, STATE_TX_ON);
- if (rc)
+ lp->tx_skb = skb;
+
+ /* In ARET mode we need to go into STATE_TX_ARET_ON after we
+ * are in STATE_TX_ON. The pfad differs here, so we change
+ * the complete handler.
+ */
+ if (lp->tx_aret)
+ tx_complete = at86rf230_xmit_tx_on;
+
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+ tx_complete);
+ if (rc) {
+ at86rf230_async_error(lp, ctx, rc);
return rc;
+ }
+ rc = wait_for_completion_interruptible_timeout(&lp->tx_complete,
+ msecs_to_jiffies(lp->data->t_tx_timeout));
+ if (!rc) {
+ at86rf230_async_error(lp, ctx, rc);
+ return -ETIMEDOUT;
+ }
+
+ /* Interfame spacing time, which is phy depend.
+ * TODO
+ * Move this handling in MAC 802.15.4 layer.
+ * This is currently a workaround to avoid fragmenation issues.
+ */
+ if (skb->len > 18)
+ usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10);
+ else
+ usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10);
+
+ return 0;
+}
- return at86rf230_state(dev, STATE_RX_AACK_ON);
+static int
+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
+{
+ might_sleep();
+ BUG_ON(!level);
+ *level = 0xbe;
+ return 0;
+}
+
+static int
+at86rf230_start(struct ieee802154_dev *dev)
+{
+ return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON);
}
static void
at86rf230_stop(struct ieee802154_dev *dev)
{
- at86rf230_state(dev, STATE_FORCE_TRX_OFF);
+ at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF);
}
static int
-at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
+at86rf23x_set_channel(struct at86rf230_local *lp, int page, int channel)
{
- lp->rssi_base_val = -91;
-
return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
}
@@ -611,10 +1053,10 @@ at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
if (page == 0) {
rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
- lp->rssi_base_val = -100;
+ lp->data->rssi_base_val = -100;
} else {
rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
- lp->rssi_base_val = -98;
+ lp->data->rssi_base_val = -98;
}
if (rc < 0)
return rc;
@@ -636,14 +1078,13 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
return -EINVAL;
}
- if (is_rf212(lp))
- rc = at86rf212_set_channel(lp, page, channel);
- else
- rc = at86rf230_set_channel(lp, page, channel);
+ rc = lp->data->set_channel(lp, page, channel);
if (rc < 0)
return rc;
- msleep(1); /* Wait for PLL */
+ /* Wait for PLL */
+ usleep_range(lp->data->t_channel_switch,
+ lp->data->t_channel_switch + 10);
dev->phy->current_channel = channel;
dev->phy->current_page = page;
@@ -651,92 +1092,6 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
}
static int
-at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
-{
- struct at86rf230_local *lp = dev->priv;
- int rc;
- unsigned long flags;
-
- spin_lock_irqsave(&lp->lock, flags);
- if (lp->irq_busy) {
- spin_unlock_irqrestore(&lp->lock, flags);
- return -EBUSY;
- }
- spin_unlock_irqrestore(&lp->lock, flags);
-
- might_sleep();
-
- rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
- if (rc)
- goto err;
-
- spin_lock_irqsave(&lp->lock, flags);
- lp->is_tx = 1;
- reinit_completion(&lp->tx_complete);
- spin_unlock_irqrestore(&lp->lock, flags);
-
- rc = at86rf230_write_fbuf(lp, skb->data, skb->len);
- if (rc)
- goto err_rx;
-
- if (lp->tx_aret) {
- rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
- if (rc)
- goto err_rx;
- }
-
- rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
- if (rc)
- goto err_rx;
-
- rc = wait_for_completion_interruptible(&lp->tx_complete);
- if (rc < 0)
- goto err_rx;
-
- return at86rf230_start(dev);
-err_rx:
- at86rf230_start(dev);
-err:
- pr_err("error: %d\n", rc);
-
- spin_lock_irqsave(&lp->lock, flags);
- lp->is_tx = 0;
- spin_unlock_irqrestore(&lp->lock, flags);
-
- return rc;
-}
-
-static int at86rf230_rx(struct at86rf230_local *lp)
-{
- u8 len = 128, lqi = 0;
- struct sk_buff *skb;
-
- skb = alloc_skb(len, GFP_KERNEL);
-
- if (!skb)
- return -ENOMEM;
-
- if (at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi))
- goto err;
-
- if (len < 2)
- goto err;
-
- skb_trim(skb, len - 2); /* We do not put CRC into the frame */
-
- ieee802154_rx_irqsafe(lp->dev, skb, lqi);
-
- dev_dbg(&lp->spi->dev, "READ_FBUF: %d %x\n", len, lqi);
-
- return 0;
-err:
- pr_debug("received frame is too small\n");
-
- kfree_skb(skb);
- return -EINVAL;
-}
-
-static int
at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
struct ieee802154_hw_addr_filt *filt,
unsigned long changed)
@@ -784,7 +1139,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
}
static int
-at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
+at86rf230_set_txpower(struct ieee802154_dev *dev, int db)
{
struct at86rf230_local *lp = dev->priv;
@@ -803,7 +1158,7 @@ at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
}
static int
-at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
+at86rf230_set_lbt(struct ieee802154_dev *dev, bool on)
{
struct at86rf230_local *lp = dev->priv;
@@ -811,7 +1166,7 @@ at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
}
static int
-at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
+at86rf230_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
{
struct at86rf230_local *lp = dev->priv;
@@ -819,21 +1174,31 @@ at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
}
static int
-at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
+at86rf212_get_desens_steps(struct at86rf230_local *lp, s32 level)
+{
+ return (level - lp->data->rssi_base_val) * 100 / 207;
+}
+
+static int
+at86rf23x_get_desens_steps(struct at86rf230_local *lp, s32 level)
+{
+ return (level - lp->data->rssi_base_val) / 2;
+}
+
+static int
+at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
{
struct at86rf230_local *lp = dev->priv;
- int desens_steps;
- if (level < lp->rssi_base_val || level > 30)
+ if (level < lp->data->rssi_base_val || level > 30)
return -EINVAL;
- desens_steps = (level - lp->rssi_base_val) * 100 / 207;
-
- return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
+ return at86rf230_write_subreg(lp, SR_CCA_ED_THRES,
+ lp->data->get_desense_steps(lp, level));
}
static int
-at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
+at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
u8 retries)
{
struct at86rf230_local *lp = dev->priv;
@@ -854,7 +1219,7 @@ at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
}
static int
-at86rf212_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
+at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
{
struct at86rf230_local *lp = dev->priv;
int rc = 0;
@@ -878,110 +1243,84 @@ static struct ieee802154_ops at86rf230_ops = {
.start = at86rf230_start,
.stop = at86rf230_stop,
.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+ .set_txpower = at86rf230_set_txpower,
+ .set_lbt = at86rf230_set_lbt,
+ .set_cca_mode = at86rf230_set_cca_mode,
+ .set_cca_ed_level = at86rf230_set_cca_ed_level,
+ .set_csma_params = at86rf230_set_csma_params,
+ .set_frame_retries = at86rf230_set_frame_retries,
};
-static struct ieee802154_ops at86rf212_ops = {
- .owner = THIS_MODULE,
- .xmit = at86rf230_xmit,
- .ed = at86rf230_ed,
- .set_channel = at86rf230_channel,
- .start = at86rf230_start,
- .stop = at86rf230_stop,
- .set_hw_addr_filt = at86rf230_set_hw_addr_filt,
- .set_txpower = at86rf212_set_txpower,
- .set_lbt = at86rf212_set_lbt,
- .set_cca_mode = at86rf212_set_cca_mode,
- .set_cca_ed_level = at86rf212_set_cca_ed_level,
- .set_csma_params = at86rf212_set_csma_params,
- .set_frame_retries = at86rf212_set_frame_retries,
+static struct at86rf2xx_chip_data at86rf233_data = {
+ .t_sleep_cycle = 330,
+ .t_channel_switch = 11,
+ .t_reset_to_off = 26,
+ .t_off_to_aack = 80,
+ .t_off_to_tx_on = 80,
+ .t_frame = 4096,
+ .t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
+ .t_tx_timeout = 2000,
+ .rssi_base_val = -91,
+ .set_channel = at86rf23x_set_channel,
+ .get_desense_steps = at86rf23x_get_desens_steps
};
-static void at86rf230_irqwork(struct work_struct *work)
-{
- struct at86rf230_local *lp =
- container_of(work, struct at86rf230_local, irqwork);
- u8 status = 0, val;
- int rc;
- unsigned long flags;
-
- rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
- status |= val;
-
- status &= ~IRQ_PLL_LOCK; /* ignore */
- status &= ~IRQ_RX_START; /* ignore */
- status &= ~IRQ_AMI; /* ignore */
- status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/
-
- if (status & IRQ_TRX_END) {
- status &= ~IRQ_TRX_END;
- spin_lock_irqsave(&lp->lock, flags);
- if (lp->is_tx) {
- lp->is_tx = 0;
- spin_unlock_irqrestore(&lp->lock, flags);
- complete(&lp->tx_complete);
- } else {
- spin_unlock_irqrestore(&lp->lock, flags);
- at86rf230_rx(lp);
- }
- }
-
- spin_lock_irqsave(&lp->lock, flags);
- lp->irq_busy = 0;
- spin_unlock_irqrestore(&lp->lock, flags);
-}
-
-static void at86rf230_irqwork_level(struct work_struct *work)
-{
- struct at86rf230_local *lp =
- container_of(work, struct at86rf230_local, irqwork);
-
- at86rf230_irqwork(work);
-
- enable_irq(lp->spi->irq);
-}
-
-static irqreturn_t at86rf230_isr(int irq, void *data)
-{
- struct at86rf230_local *lp = data;
- unsigned long flags;
-
- spin_lock_irqsave(&lp->lock, flags);
- lp->irq_busy = 1;
- spin_unlock_irqrestore(&lp->lock, flags);
-
- schedule_work(&lp->irqwork);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t at86rf230_isr_level(int irq, void *data)
-{
- disable_irq_nosync(irq);
+static struct at86rf2xx_chip_data at86rf231_data = {
+ .t_sleep_cycle = 330,
+ .t_channel_switch = 24,
+ .t_reset_to_off = 37,
+ .t_off_to_aack = 110,
+ .t_off_to_tx_on = 110,
+ .t_frame = 4096,
+ .t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
+ .t_tx_timeout = 2000,
+ .rssi_base_val = -91,
+ .set_channel = at86rf23x_set_channel,
+ .get_desense_steps = at86rf23x_get_desens_steps
+};
- return at86rf230_isr(irq, data);
-}
+static struct at86rf2xx_chip_data at86rf212_data = {
+ .t_sleep_cycle = 330,
+ .t_channel_switch = 11,
+ .t_reset_to_off = 26,
+ .t_off_to_aack = 200,
+ .t_off_to_tx_on = 200,
+ .t_frame = 4096,
+ .t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
+ .t_tx_timeout = 2000,
+ .rssi_base_val = -100,
+ .set_channel = at86rf212_set_channel,
+ .get_desense_steps = at86rf212_get_desens_steps
+};
static int at86rf230_hw_init(struct at86rf230_local *lp)
{
- int rc, irq_pol, irq_type;
- u8 dvdd;
+ int rc, irq_type, irq_pol = IRQ_ACTIVE_HIGH;
+ unsigned int dvdd;
u8 csma_seed[2];
- rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
+ rc = at86rf230_sync_state_change(lp, STATE_FORCE_TRX_OFF);
if (rc)
return rc;
irq_type = irq_get_trigger_type(lp->spi->irq);
- /* configure irq polarity, defaults to high active */
- if (irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
+ if (irq_type == IRQ_TYPE_EDGE_FALLING)
irq_pol = IRQ_ACTIVE_LOW;
- else
- irq_pol = IRQ_ACTIVE_HIGH;
rc = at86rf230_write_subreg(lp, SR_IRQ_POLARITY, irq_pol);
if (rc)
return rc;
+ rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
+ if (rc)
+ return rc;
+
rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, IRQ_TRX_END);
if (rc)
return rc;
@@ -1004,7 +1343,8 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
if (rc)
return rc;
/* Wait the next SLEEP cycle */
- msleep(100);
+ usleep_range(lp->data->t_sleep_cycle,
+ lp->data->t_sleep_cycle + 100);
rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &dvdd);
if (rc)
@@ -1037,18 +1377,111 @@ done:
return pdata;
}
+static int
+at86rf230_detect_device(struct at86rf230_local *lp)
+{
+ unsigned int part, version, val;
+ u16 man_id = 0;
+ const char *chip;
+ int rc;
+
+ rc = __at86rf230_read(lp, RG_MAN_ID_0, &val);
+ if (rc)
+ return rc;
+ man_id |= val;
+
+ rc = __at86rf230_read(lp, RG_MAN_ID_1, &val);
+ if (rc)
+ return rc;
+ man_id |= (val << 8);
+
+ rc = __at86rf230_read(lp, RG_PART_NUM, &part);
+ if (rc)
+ return rc;
+
+ rc = __at86rf230_read(lp, RG_PART_NUM, &version);
+ if (rc)
+ return rc;
+
+ if (man_id != 0x001f) {
+ dev_err(&lp->spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
+ man_id >> 8, man_id & 0xFF);
+ return -EINVAL;
+ }
+
+ lp->dev->extra_tx_headroom = 0;
+ lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
+ IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA;
+
+ switch (part) {
+ case 2:
+ chip = "at86rf230";
+ rc = -ENOTSUPP;
+ break;
+ case 3:
+ chip = "at86rf231";
+ lp->data = &at86rf231_data;
+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
+ break;
+ case 7:
+ chip = "at86rf212";
+ if (version == 1) {
+ lp->data = &at86rf212_data;
+ lp->dev->flags |= IEEE802154_HW_LBT;
+ lp->dev->phy->channels_supported[0] = 0x00007FF;
+ lp->dev->phy->channels_supported[2] = 0x00007FF;
+ } else {
+ rc = -ENOTSUPP;
+ }
+ break;
+ case 11:
+ chip = "at86rf233";
+ lp->data = &at86rf233_data;
+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
+ break;
+ default:
+ chip = "unkown";
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ dev_info(&lp->spi->dev, "Detected %s chip version %d\n", chip, version);
+
+ return rc;
+}
+
+static void
+at86rf230_setup_spi_messages(struct at86rf230_local *lp)
+{
+ lp->state.lp = lp;
+ spi_message_init(&lp->state.msg);
+ lp->state.msg.context = &lp->state;
+ lp->state.trx.tx_buf = lp->state.buf;
+ lp->state.trx.rx_buf = lp->state.buf;
+ spi_message_add_tail(&lp->state.trx, &lp->state.msg);
+
+ lp->irq.lp = lp;
+ spi_message_init(&lp->irq.msg);
+ lp->irq.msg.context = &lp->irq;
+ lp->irq.trx.tx_buf = lp->irq.buf;
+ lp->irq.trx.rx_buf = lp->irq.buf;
+ spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
+
+ lp->tx.lp = lp;
+ spi_message_init(&lp->tx.msg);
+ lp->tx.msg.context = &lp->tx;
+ lp->tx.trx.tx_buf = lp->tx.buf;
+ lp->tx.trx.rx_buf = lp->tx.buf;
+ spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
+}
+
static int at86rf230_probe(struct spi_device *spi)
{
struct at86rf230_platform_data *pdata;
struct ieee802154_dev *dev;
struct at86rf230_local *lp;
- u16 man_id = 0;
- u8 part = 0, version = 0, status;
- irq_handler_t irq_handler;
- work_func_t irq_worker;
+ unsigned int status;
int rc, irq_type;
- const char *chip;
- struct ieee802154_ops *ops = NULL;
if (!spi->irq) {
dev_err(&spi->dev, "no IRQ specified\n");
@@ -1084,107 +1517,60 @@ static int at86rf230_probe(struct spi_device *spi)
usleep_range(120, 240);
}
- rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
- if (rc < 0)
- return rc;
-
- if (man_id != 0x001f) {
- dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
- man_id >> 8, man_id & 0xFF);
- return -EINVAL;
- }
-
- switch (part) {
- case 2:
- chip = "at86rf230";
- /* FIXME: should be easy to support; */
- break;
- case 3:
- chip = "at86rf231";
- ops = &at86rf230_ops;
- break;
- case 7:
- chip = "at86rf212";
- if (version == 1)
- ops = &at86rf212_ops;
- break;
- case 11:
- chip = "at86rf233";
- ops = &at86rf230_ops;
- break;
- default:
- chip = "UNKNOWN";
- break;
- }
-
- dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
- if (!ops)
- return -ENOTSUPP;
-
- dev = ieee802154_alloc_device(sizeof(*lp), ops);
+ dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
if (!dev)
return -ENOMEM;
lp = dev->priv;
lp->dev = dev;
- lp->part = part;
- lp->vers = version;
-
lp->spi = spi;
-
dev->parent = &spi->dev;
- dev->extra_tx_headroom = 0;
- dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
- irq_type = irq_get_trigger_type(spi->irq);
- if (!irq_type)
- irq_type = IRQF_TRIGGER_RISING;
- if (irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
- irq_worker = at86rf230_irqwork;
- irq_handler = at86rf230_isr;
- } else {
- irq_worker = at86rf230_irqwork_level;
- irq_handler = at86rf230_isr_level;
+ lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
+ if (IS_ERR(lp->regmap)) {
+ rc = PTR_ERR(lp->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ rc);
+ goto free_dev;
}
- mutex_init(&lp->bmux);
- INIT_WORK(&lp->irqwork, irq_worker);
+ at86rf230_setup_spi_messages(lp);
+
+ rc = at86rf230_detect_device(lp);
+ if (rc < 0)
+ goto free_dev;
+
spin_lock_init(&lp->lock);
init_completion(&lp->tx_complete);
+ init_completion(&lp->state_complete);
spi_set_drvdata(spi, lp);
- if (is_rf212(lp)) {
- dev->phy->channels_supported[0] = 0x00007FF;
- dev->phy->channels_supported[2] = 0x00007FF;
- } else {
- dev->phy->channels_supported[0] = 0x7FFF800;
- }
-
rc = at86rf230_hw_init(lp);
if (rc)
- goto err_hw_init;
+ goto free_dev;
/* Read irq status register to reset irq line */
rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
if (rc)
- goto err_hw_init;
+ goto free_dev;
+
+ irq_type = irq_get_trigger_type(spi->irq);
+ if (!irq_type)
+ irq_type = IRQF_TRIGGER_RISING;
- rc = devm_request_irq(&spi->dev, spi->irq, irq_handler,
- IRQF_SHARED | irq_type,
- dev_name(&spi->dev), lp);
+ rc = devm_request_irq(&spi->dev, spi->irq, at86rf230_isr,
+ IRQF_SHARED | irq_type, dev_name(&spi->dev), lp);
if (rc)
- goto err_hw_init;
+ goto free_dev;
rc = ieee802154_register_device(lp->dev);
if (rc)
- goto err_hw_init;
+ goto free_dev;
return rc;
-err_hw_init:
- flush_work(&lp->irqwork);
- mutex_destroy(&lp->bmux);
+free_dev:
ieee802154_free_device(lp->dev);
return rc;
@@ -1197,8 +1583,6 @@ static int at86rf230_remove(struct spi_device *spi)
/* mask all at86rf230 irq's */
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
ieee802154_unregister_device(lp->dev);
- flush_work(&lp->irqwork);
- mutex_destroy(&lp->bmux);
ieee802154_free_device(lp->dev);
dev_dbg(&spi->dev, "unregistered at86rf230\n");
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
new file mode 100644
index 000000000000..8a5ac7ab2300
--- /dev/null
+++ b/drivers/net/ieee802154/cc2520.c
@@ -0,0 +1,1039 @@
+/* Driver for TI CC2520 802.15.4 Wireless-PAN Networking controller
+ *
+ * Copyright (C) 2014 Varka Bhadram <varkab@cdac.in>
+ * Md.Jamal Mohiuddin <mjmohiuddin@cdac.in>
+ * P Sowjanya <sowjanyap@cdac.in>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/cc2520.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of_gpio.h>
+
+#include <net/mac802154.h>
+#include <net/wpan-phy.h>
+#include <net/ieee802154.h>
+
+#define SPI_COMMAND_BUFFER 3
+#define HIGH 1
+#define LOW 0
+#define STATE_IDLE 0
+#define RSSI_VALID 0
+#define RSSI_OFFSET 78
+
+#define CC2520_RAM_SIZE 640
+#define CC2520_FIFO_SIZE 128
+
+#define CC2520RAM_TXFIFO 0x100
+#define CC2520RAM_RXFIFO 0x180
+#define CC2520RAM_IEEEADDR 0x3EA
+#define CC2520RAM_PANID 0x3F2
+#define CC2520RAM_SHORTADDR 0x3F4
+
+#define CC2520_FREG_MASK 0x3F
+
+/* status byte values */
+#define CC2520_STATUS_XOSC32M_STABLE (1 << 7)
+#define CC2520_STATUS_RSSI_VALID (1 << 6)
+#define CC2520_STATUS_TX_UNDERFLOW (1 << 3)
+
+/* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
+#define CC2520_MINCHANNEL 11
+#define CC2520_MAXCHANNEL 26
+#define CC2520_CHANNEL_SPACING 5
+
+/* command strobes */
+#define CC2520_CMD_SNOP 0x00
+#define CC2520_CMD_IBUFLD 0x02
+#define CC2520_CMD_SIBUFEX 0x03
+#define CC2520_CMD_SSAMPLECCA 0x04
+#define CC2520_CMD_SRES 0x0f
+#define CC2520_CMD_MEMORY_MASK 0x0f
+#define CC2520_CMD_MEMORY_READ 0x10
+#define CC2520_CMD_MEMORY_WRITE 0x20
+#define CC2520_CMD_RXBUF 0x30
+#define CC2520_CMD_RXBUFCP 0x38
+#define CC2520_CMD_RXBUFMOV 0x32
+#define CC2520_CMD_TXBUF 0x3A
+#define CC2520_CMD_TXBUFCP 0x3E
+#define CC2520_CMD_RANDOM 0x3C
+#define CC2520_CMD_SXOSCON 0x40
+#define CC2520_CMD_STXCAL 0x41
+#define CC2520_CMD_SRXON 0x42
+#define CC2520_CMD_STXON 0x43
+#define CC2520_CMD_STXONCCA 0x44
+#define CC2520_CMD_SRFOFF 0x45
+#define CC2520_CMD_SXOSCOFF 0x46
+#define CC2520_CMD_SFLUSHRX 0x47
+#define CC2520_CMD_SFLUSHTX 0x48
+#define CC2520_CMD_SACK 0x49
+#define CC2520_CMD_SACKPEND 0x4A
+#define CC2520_CMD_SNACK 0x4B
+#define CC2520_CMD_SRXMASKBITSET 0x4C
+#define CC2520_CMD_SRXMASKBITCLR 0x4D
+#define CC2520_CMD_RXMASKAND 0x4E
+#define CC2520_CMD_RXMASKOR 0x4F
+#define CC2520_CMD_MEMCP 0x50
+#define CC2520_CMD_MEMCPR 0x52
+#define CC2520_CMD_MEMXCP 0x54
+#define CC2520_CMD_MEMXWR 0x56
+#define CC2520_CMD_BCLR 0x58
+#define CC2520_CMD_BSET 0x59
+#define CC2520_CMD_CTR_UCTR 0x60
+#define CC2520_CMD_CBCMAC 0x64
+#define CC2520_CMD_UCBCMAC 0x66
+#define CC2520_CMD_CCM 0x68
+#define CC2520_CMD_UCCM 0x6A
+#define CC2520_CMD_ECB 0x70
+#define CC2520_CMD_ECBO 0x72
+#define CC2520_CMD_ECBX 0x74
+#define CC2520_CMD_INC 0x78
+#define CC2520_CMD_ABORT 0x7F
+#define CC2520_CMD_REGISTER_READ 0x80
+#define CC2520_CMD_REGISTER_WRITE 0xC0
+
+/* status registers */
+#define CC2520_CHIPID 0x40
+#define CC2520_VERSION 0x42
+#define CC2520_EXTCLOCK 0x44
+#define CC2520_MDMCTRL0 0x46
+#define CC2520_MDMCTRL1 0x47
+#define CC2520_FREQEST 0x48
+#define CC2520_RXCTRL 0x4A
+#define CC2520_FSCTRL 0x4C
+#define CC2520_FSCAL0 0x4E
+#define CC2520_FSCAL1 0x4F
+#define CC2520_FSCAL2 0x50
+#define CC2520_FSCAL3 0x51
+#define CC2520_AGCCTRL0 0x52
+#define CC2520_AGCCTRL1 0x53
+#define CC2520_AGCCTRL2 0x54
+#define CC2520_AGCCTRL3 0x55
+#define CC2520_ADCTEST0 0x56
+#define CC2520_ADCTEST1 0x57
+#define CC2520_ADCTEST2 0x58
+#define CC2520_MDMTEST0 0x5A
+#define CC2520_MDMTEST1 0x5B
+#define CC2520_DACTEST0 0x5C
+#define CC2520_DACTEST1 0x5D
+#define CC2520_ATEST 0x5E
+#define CC2520_DACTEST2 0x5F
+#define CC2520_PTEST0 0x60
+#define CC2520_PTEST1 0x61
+#define CC2520_RESERVED 0x62
+#define CC2520_DPUBIST 0x7A
+#define CC2520_ACTBIST 0x7C
+#define CC2520_RAMBIST 0x7E
+
+/* frame registers */
+#define CC2520_FRMFILT0 0x00
+#define CC2520_FRMFILT1 0x01
+#define CC2520_SRCMATCH 0x02
+#define CC2520_SRCSHORTEN0 0x04
+#define CC2520_SRCSHORTEN1 0x05
+#define CC2520_SRCSHORTEN2 0x06
+#define CC2520_SRCEXTEN0 0x08
+#define CC2520_SRCEXTEN1 0x09
+#define CC2520_SRCEXTEN2 0x0A
+#define CC2520_FRMCTRL0 0x0C
+#define CC2520_FRMCTRL1 0x0D
+#define CC2520_RXENABLE0 0x0E
+#define CC2520_RXENABLE1 0x0F
+#define CC2520_EXCFLAG0 0x10
+#define CC2520_EXCFLAG1 0x11
+#define CC2520_EXCFLAG2 0x12
+#define CC2520_EXCMASKA0 0x14
+#define CC2520_EXCMASKA1 0x15
+#define CC2520_EXCMASKA2 0x16
+#define CC2520_EXCMASKB0 0x18
+#define CC2520_EXCMASKB1 0x19
+#define CC2520_EXCMASKB2 0x1A
+#define CC2520_EXCBINDX0 0x1C
+#define CC2520_EXCBINDX1 0x1D
+#define CC2520_EXCBINDY0 0x1E
+#define CC2520_EXCBINDY1 0x1F
+#define CC2520_GPIOCTRL0 0x20
+#define CC2520_GPIOCTRL1 0x21
+#define CC2520_GPIOCTRL2 0x22
+#define CC2520_GPIOCTRL3 0x23
+#define CC2520_GPIOCTRL4 0x24
+#define CC2520_GPIOCTRL5 0x25
+#define CC2520_GPIOPOLARITY 0x26
+#define CC2520_GPIOCTRL 0x28
+#define CC2520_DPUCON 0x2A
+#define CC2520_DPUSTAT 0x2C
+#define CC2520_FREQCTRL 0x2E
+#define CC2520_FREQTUNE 0x2F
+#define CC2520_TXPOWER 0x30
+#define CC2520_TXCTRL 0x31
+#define CC2520_FSMSTAT0 0x32
+#define CC2520_FSMSTAT1 0x33
+#define CC2520_FIFOPCTRL 0x34
+#define CC2520_FSMCTRL 0x35
+#define CC2520_CCACTRL0 0x36
+#define CC2520_CCACTRL1 0x37
+#define CC2520_RSSI 0x38
+#define CC2520_RSSISTAT 0x39
+#define CC2520_RXFIRST 0x3C
+#define CC2520_RXFIFOCNT 0x3E
+#define CC2520_TXFIFOCNT 0x3F
+
+/* Driver private information */
+struct cc2520_private {
+ struct spi_device *spi; /* SPI device structure */
+ struct ieee802154_dev *dev; /* IEEE-802.15.4 device */
+ u8 *buf; /* SPI TX/Rx data buffer */
+ struct mutex buffer_mutex; /* SPI buffer mutex */
+ bool is_tx; /* Flag for sync b/w Tx and Rx */
+ int fifo_pin; /* FIFO GPIO pin number */
+ struct work_struct fifop_irqwork;/* Workqueue for FIFOP */
+ spinlock_t lock; /* Lock for is_tx*/
+ struct completion tx_complete; /* Work completion for Tx */
+};
+
+/* Generic Functions */
+static int
+cc2520_cmd_strobe(struct cc2520_private *priv, u8 cmd)
+{
+ int ret;
+ u8 status = 0xff;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer.len++] = cmd;
+ dev_vdbg(&priv->spi->dev,
+ "command strobe buf[0] = %02x\n",
+ priv->buf[0]);
+
+ ret = spi_sync(priv->spi, &msg);
+ if (!ret)
+ status = priv->buf[0];
+ dev_vdbg(&priv->spi->dev,
+ "buf[0] = %02x\n", priv->buf[0]);
+ mutex_unlock(&priv->buffer_mutex);
+
+ return ret;
+}
+
+static int
+cc2520_get_status(struct cc2520_private *priv, u8 *status)
+{
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer.len++] = CC2520_CMD_SNOP;
+ dev_vdbg(&priv->spi->dev,
+ "get status command buf[0] = %02x\n", priv->buf[0]);
+
+ ret = spi_sync(priv->spi, &msg);
+ if (!ret)
+ *status = priv->buf[0];
+ dev_vdbg(&priv->spi->dev,
+ "buf[0] = %02x\n", priv->buf[0]);
+ mutex_unlock(&priv->buffer_mutex);
+
+ return ret;
+}
+
+static int
+cc2520_write_register(struct cc2520_private *priv, u8 reg, u8 value)
+{
+ int status;
+ struct spi_message msg;
+ struct spi_transfer xfer = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+
+ if (reg <= CC2520_FREG_MASK) {
+ priv->buf[xfer.len++] = CC2520_CMD_REGISTER_WRITE | reg;
+ priv->buf[xfer.len++] = value;
+ } else {
+ priv->buf[xfer.len++] = CC2520_CMD_MEMORY_WRITE;
+ priv->buf[xfer.len++] = reg;
+ priv->buf[xfer.len++] = value;
+ }
+ status = spi_sync(priv->spi, &msg);
+ if (msg.status)
+ status = msg.status;
+
+ mutex_unlock(&priv->buffer_mutex);
+
+ return status;
+}
+
+static int
+cc2520_write_ram(struct cc2520_private *priv, u16 reg, u8 len, u8 *data)
+{
+ int status;
+ struct spi_message msg;
+ struct spi_transfer xfer_head = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+
+ struct spi_transfer xfer_buf = {
+ .len = len,
+ .tx_buf = data,
+ };
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer_head.len++] = (CC2520_CMD_MEMORY_WRITE |
+ ((reg >> 8) & 0xff));
+ priv->buf[xfer_head.len++] = reg & 0xff;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer_head, &msg);
+ spi_message_add_tail(&xfer_buf, &msg);
+
+ status = spi_sync(priv->spi, &msg);
+ dev_dbg(&priv->spi->dev, "spi status = %d\n", status);
+ if (msg.status)
+ status = msg.status;
+
+ mutex_unlock(&priv->buffer_mutex);
+ return status;
+}
+
+static int
+cc2520_read_register(struct cc2520_private *priv, u8 reg, u8 *data)
+{
+ int status;
+ struct spi_message msg;
+ struct spi_transfer xfer1 = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+
+ struct spi_transfer xfer2 = {
+ .len = 1,
+ .rx_buf = data,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer1, &msg);
+ spi_message_add_tail(&xfer2, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer1.len++] = CC2520_CMD_MEMORY_READ;
+ priv->buf[xfer1.len++] = reg;
+
+ status = spi_sync(priv->spi, &msg);
+ dev_dbg(&priv->spi->dev,
+ "spi status = %d\n", status);
+ if (msg.status)
+ status = msg.status;
+
+ mutex_unlock(&priv->buffer_mutex);
+
+ return status;
+}
+
+static int
+cc2520_write_txfifo(struct cc2520_private *priv, u8 *data, u8 len)
+{
+ int status;
+
+ /* length byte must include FCS even
+ * if it is calculated in the hardware
+ */
+ int len_byte = len + 2;
+
+ struct spi_message msg;
+
+ struct spi_transfer xfer_head = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+ struct spi_transfer xfer_len = {
+ .len = 1,
+ .tx_buf = &len_byte,
+ };
+ struct spi_transfer xfer_buf = {
+ .len = len,
+ .tx_buf = data,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer_head, &msg);
+ spi_message_add_tail(&xfer_len, &msg);
+ spi_message_add_tail(&xfer_buf, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer_head.len++] = CC2520_CMD_TXBUF;
+ dev_vdbg(&priv->spi->dev,
+ "TX_FIFO cmd buf[0] = %02x\n", priv->buf[0]);
+
+ status = spi_sync(priv->spi, &msg);
+ dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+ if (msg.status)
+ status = msg.status;
+ dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+ dev_vdbg(&priv->spi->dev, "buf[0] = %02x\n", priv->buf[0]);
+ mutex_unlock(&priv->buffer_mutex);
+
+ return status;
+}
+
+static int
+cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len, u8 *lqi)
+{
+ int status;
+ struct spi_message msg;
+
+ struct spi_transfer xfer_head = {
+ .len = 0,
+ .tx_buf = priv->buf,
+ .rx_buf = priv->buf,
+ };
+ struct spi_transfer xfer_buf = {
+ .len = len,
+ .rx_buf = data,
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer_head, &msg);
+ spi_message_add_tail(&xfer_buf, &msg);
+
+ mutex_lock(&priv->buffer_mutex);
+ priv->buf[xfer_head.len++] = CC2520_CMD_RXBUF;
+
+ dev_vdbg(&priv->spi->dev, "read rxfifo buf[0] = %02x\n", priv->buf[0]);
+ dev_vdbg(&priv->spi->dev, "buf[1] = %02x\n", priv->buf[1]);
+
+ status = spi_sync(priv->spi, &msg);
+ dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+ if (msg.status)
+ status = msg.status;
+ dev_vdbg(&priv->spi->dev, "status = %d\n", status);
+ dev_vdbg(&priv->spi->dev,
+ "return status buf[0] = %02x\n", priv->buf[0]);
+ dev_vdbg(&priv->spi->dev, "length buf[1] = %02x\n", priv->buf[1]);
+
+ mutex_unlock(&priv->buffer_mutex);
+
+ return status;
+}
+
+static int cc2520_start(struct ieee802154_dev *dev)
+{
+ return cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRXON);
+}
+
+static void cc2520_stop(struct ieee802154_dev *dev)
+{
+ cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRFOFF);
+}
+
+static int
+cc2520_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+{
+ struct cc2520_private *priv = dev->priv;
+ unsigned long flags;
+ int rc;
+ u8 status = 0;
+
+ rc = cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
+ if (rc)
+ goto err_tx;
+
+ rc = cc2520_write_txfifo(priv, skb->data, skb->len);
+ if (rc)
+ goto err_tx;
+
+ rc = cc2520_get_status(priv, &status);
+ if (rc)
+ goto err_tx;
+
+ if (status & CC2520_STATUS_TX_UNDERFLOW) {
+ dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
+ goto err_tx;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ BUG_ON(priv->is_tx);
+ priv->is_tx = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ rc = cc2520_cmd_strobe(priv, CC2520_CMD_STXONCCA);
+ if (rc)
+ goto err;
+
+ rc = wait_for_completion_interruptible(&priv->tx_complete);
+ if (rc < 0)
+ goto err;
+
+ cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
+ cc2520_cmd_strobe(priv, CC2520_CMD_SRXON);
+
+ return rc;
+err:
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->is_tx = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+err_tx:
+ return rc;
+}
+
+
+static int cc2520_rx(struct cc2520_private *priv)
+{
+ u8 len = 0, lqi = 0, bytes = 1;
+ struct sk_buff *skb;
+
+ cc2520_read_rxfifo(priv, &len, bytes, &lqi);
+
+ if (len < 2 || len > IEEE802154_MTU)
+ return -EINVAL;
+
+ skb = alloc_skb(len, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ if (cc2520_read_rxfifo(priv, skb_put(skb, len), len, &lqi)) {
+ dev_dbg(&priv->spi->dev, "frame reception failed\n");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ skb_trim(skb, skb->len - 2);
+
+ ieee802154_rx_irqsafe(priv->dev, skb, lqi);
+
+ dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
+
+ return 0;
+}
+
+static int
+cc2520_ed(struct ieee802154_dev *dev, u8 *level)
+{
+ struct cc2520_private *priv = dev->priv;
+ u8 status = 0xff;
+ u8 rssi;
+ int ret;
+
+ ret = cc2520_read_register(priv , CC2520_RSSISTAT, &status);
+ if (ret)
+ return ret;
+
+ if (status != RSSI_VALID)
+ return -EINVAL;
+
+ ret = cc2520_read_register(priv , CC2520_RSSI, &rssi);
+ if (ret)
+ return ret;
+
+ /* level = RSSI(rssi) - OFFSET [dBm] : offset is 76dBm */
+ *level = rssi - RSSI_OFFSET;
+
+ return 0;
+}
+
+static int
+cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel)
+{
+ struct cc2520_private *priv = dev->priv;
+ int ret;
+
+ might_sleep();
+ dev_dbg(&priv->spi->dev, "trying to set channel\n");
+
+ BUG_ON(page != 0);
+ BUG_ON(channel < CC2520_MINCHANNEL);
+ BUG_ON(channel > CC2520_MAXCHANNEL);
+
+ ret = cc2520_write_register(priv, CC2520_FREQCTRL,
+ 11 + 5*(channel - 11));
+
+ return ret;
+}
+
+static int
+cc2520_filter(struct ieee802154_dev *dev,
+ struct ieee802154_hw_addr_filt *filt, unsigned long changed)
+{
+ struct cc2520_private *priv = dev->priv;
+
+ if (changed & IEEE802515_AFILT_PANID_CHANGED) {
+ u16 panid = le16_to_cpu(filt->pan_id);
+
+ dev_vdbg(&priv->spi->dev,
+ "cc2520_filter called for pan id\n");
+ cc2520_write_ram(priv, CC2520RAM_PANID,
+ sizeof(panid), (u8 *)&panid);
+ }
+
+ if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
+ dev_vdbg(&priv->spi->dev,
+ "cc2520_filter called for IEEE addr\n");
+ cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
+ sizeof(filt->ieee_addr),
+ (u8 *)&filt->ieee_addr);
+ }
+
+ if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
+ u16 addr = le16_to_cpu(filt->short_addr);
+
+ dev_vdbg(&priv->spi->dev,
+ "cc2520_filter called for saddr\n");
+ cc2520_write_ram(priv, CC2520RAM_SHORTADDR,
+ sizeof(addr), (u8 *)&addr);
+ }
+
+ if (changed & IEEE802515_AFILT_PANC_CHANGED) {
+ dev_vdbg(&priv->spi->dev,
+ "cc2520_filter called for panc change\n");
+ if (filt->pan_coord)
+ cc2520_write_register(priv, CC2520_FRMFILT0, 0x02);
+ else
+ cc2520_write_register(priv, CC2520_FRMFILT0, 0x00);
+ }
+
+ return 0;
+}
+
+static struct ieee802154_ops cc2520_ops = {
+ .owner = THIS_MODULE,
+ .start = cc2520_start,
+ .stop = cc2520_stop,
+ .xmit = cc2520_tx,
+ .ed = cc2520_ed,
+ .set_channel = cc2520_set_channel,
+ .set_hw_addr_filt = cc2520_filter,
+};
+
+static int cc2520_register(struct cc2520_private *priv)
+{
+ int ret = -ENOMEM;
+
+ priv->dev = ieee802154_alloc_device(sizeof(*priv), &cc2520_ops);
+ if (!priv->dev)
+ goto err_ret;
+
+ priv->dev->priv = priv;
+ priv->dev->parent = &priv->spi->dev;
+ priv->dev->extra_tx_headroom = 0;
+
+ /* We do support only 2.4 Ghz */
+ priv->dev->phy->channels_supported[0] = 0x7FFF800;
+ priv->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
+
+ dev_vdbg(&priv->spi->dev, "registered cc2520\n");
+ ret = ieee802154_register_device(priv->dev);
+ if (ret)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ ieee802154_free_device(priv->dev);
+err_ret:
+ return ret;
+}
+
+static void cc2520_fifop_irqwork(struct work_struct *work)
+{
+ struct cc2520_private *priv
+ = container_of(work, struct cc2520_private, fifop_irqwork);
+
+ dev_dbg(&priv->spi->dev, "fifop interrupt received\n");
+
+ if (gpio_get_value(priv->fifo_pin))
+ cc2520_rx(priv);
+ else
+ dev_dbg(&priv->spi->dev, "rxfifo overflow\n");
+
+ cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
+ cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
+}
+
+static irqreturn_t cc2520_fifop_isr(int irq, void *data)
+{
+ struct cc2520_private *priv = data;
+
+ schedule_work(&priv->fifop_irqwork);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t cc2520_sfd_isr(int irq, void *data)
+{
+ struct cc2520_private *priv = data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->is_tx) {
+ priv->is_tx = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ dev_dbg(&priv->spi->dev, "SFD for TX\n");
+ complete(&priv->tx_complete);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ dev_dbg(&priv->spi->dev, "SFD for RX\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int cc2520_hw_init(struct cc2520_private *priv)
+{
+ u8 status = 0, state = 0xff;
+ int ret;
+ int timeout = 100;
+
+ ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state);
+ if (ret)
+ goto err_ret;
+
+ if (state != STATE_IDLE)
+ return -EINVAL;
+
+ do {
+ ret = cc2520_get_status(priv, &status);
+ if (ret)
+ goto err_ret;
+
+ if (timeout-- <= 0) {
+ dev_err(&priv->spi->dev, "oscillator start failed!\n");
+ return ret;
+ }
+ udelay(1);
+ } while (!(status & CC2520_STATUS_XOSC32M_STABLE));
+
+ dev_vdbg(&priv->spi->dev, "oscillator brought up\n");
+
+ /* Registers default value: section 28.1 in Datasheet */
+ ret = cc2520_write_register(priv, CC2520_TXPOWER, 0xF7);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FRMCTRL0, 0x60);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FRMCTRL1, 0x03);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FRMFILT0, 0x00);
+ if (ret)
+ goto err_ret;
+
+ ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127);
+ if (ret)
+ goto err_ret;
+
+ return 0;
+
+err_ret:
+ return ret;
+}
+
+static struct cc2520_platform_data *
+cc2520_get_platform_data(struct spi_device *spi)
+{
+ struct cc2520_platform_data *pdata;
+ struct device_node *np = spi->dev.of_node;
+ struct cc2520_private *priv = spi_get_drvdata(spi);
+
+ if (!np)
+ return spi->dev.platform_data;
+
+ pdata = devm_kzalloc(&spi->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ goto done;
+
+ pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0);
+ priv->fifo_pin = pdata->fifo;
+
+ pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0);
+
+ pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0);
+ pdata->cca = of_get_named_gpio(np, "cca-gpio", 0);
+ pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0);
+ pdata->reset = of_get_named_gpio(np, "reset-gpio", 0);
+
+ spi->dev.platform_data = pdata;
+
+done:
+ return pdata;
+}
+
+static int cc2520_probe(struct spi_device *spi)
+{
+ struct cc2520_private *priv;
+ struct pinctrl *pinctrl;
+ struct cc2520_platform_data *pdata;
+ int ret;
+
+ priv = devm_kzalloc(&spi->dev,
+ sizeof(struct cc2520_private), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_ret;
+ }
+
+ spi_set_drvdata(spi, priv);
+
+ pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&spi->dev,
+ "pinctrl pins are not configured");
+
+ pdata = cc2520_get_platform_data(spi);
+ if (!pdata) {
+ dev_err(&spi->dev, "no platform data\n");
+ return -EINVAL;
+ }
+
+ priv->spi = spi;
+
+ priv->buf = devm_kzalloc(&spi->dev,
+ SPI_COMMAND_BUFFER, GFP_KERNEL);
+ if (!priv->buf) {
+ ret = -ENOMEM;
+ goto err_ret;
+ }
+
+ mutex_init(&priv->buffer_mutex);
+ INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork);
+ spin_lock_init(&priv->lock);
+ init_completion(&priv->tx_complete);
+
+ /* Request all the gpio's */
+ if (!gpio_is_valid(pdata->fifo)) {
+ dev_err(&spi->dev, "fifo gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->fifo,
+ GPIOF_IN, "fifo");
+ if (ret)
+ goto err_hw_init;
+
+ if (!gpio_is_valid(pdata->cca)) {
+ dev_err(&spi->dev, "cca gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->cca,
+ GPIOF_IN, "cca");
+ if (ret)
+ goto err_hw_init;
+
+ if (!gpio_is_valid(pdata->fifop)) {
+ dev_err(&spi->dev, "fifop gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->fifop,
+ GPIOF_IN, "fifop");
+ if (ret)
+ goto err_hw_init;
+
+ if (!gpio_is_valid(pdata->sfd)) {
+ dev_err(&spi->dev, "sfd gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->sfd,
+ GPIOF_IN, "sfd");
+ if (ret)
+ goto err_hw_init;
+
+ if (!gpio_is_valid(pdata->reset)) {
+ dev_err(&spi->dev, "reset gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->reset,
+ GPIOF_OUT_INIT_LOW, "reset");
+ if (ret)
+ goto err_hw_init;
+
+ if (!gpio_is_valid(pdata->vreg)) {
+ dev_err(&spi->dev, "vreg gpio is not valid\n");
+ ret = -EINVAL;
+ goto err_hw_init;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, pdata->vreg,
+ GPIOF_OUT_INIT_LOW, "vreg");
+ if (ret)
+ goto err_hw_init;
+
+
+ gpio_set_value(pdata->vreg, HIGH);
+ usleep_range(100, 150);
+
+ gpio_set_value(pdata->reset, HIGH);
+ usleep_range(200, 250);
+
+ ret = cc2520_hw_init(priv);
+ if (ret)
+ goto err_hw_init;
+
+ /* Set up fifop interrupt */
+ ret = devm_request_irq(&spi->dev,
+ gpio_to_irq(pdata->fifop),
+ cc2520_fifop_isr,
+ IRQF_TRIGGER_RISING,
+ dev_name(&spi->dev),
+ priv);
+ if (ret) {
+ dev_err(&spi->dev, "could not get fifop irq\n");
+ goto err_hw_init;
+ }
+
+ /* Set up sfd interrupt */
+ ret = devm_request_irq(&spi->dev,
+ gpio_to_irq(pdata->sfd),
+ cc2520_sfd_isr,
+ IRQF_TRIGGER_FALLING,
+ dev_name(&spi->dev),
+ priv);
+ if (ret) {
+ dev_err(&spi->dev, "could not get sfd irq\n");
+ goto err_hw_init;
+ }
+
+ ret = cc2520_register(priv);
+ if (ret)
+ goto err_hw_init;
+
+ return 0;
+
+err_hw_init:
+ mutex_destroy(&priv->buffer_mutex);
+ flush_work(&priv->fifop_irqwork);
+
+err_ret:
+ return ret;
+}
+
+static int cc2520_remove(struct spi_device *spi)
+{
+ struct cc2520_private *priv = spi_get_drvdata(spi);
+
+ mutex_destroy(&priv->buffer_mutex);
+ flush_work(&priv->fifop_irqwork);
+
+ ieee802154_unregister_device(priv->dev);
+ ieee802154_free_device(priv->dev);
+
+ return 0;
+}
+
+static const struct spi_device_id cc2520_ids[] = {
+ {"cc2520", },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, cc2520_ids);
+
+static const struct of_device_id cc2520_of_ids[] = {
+ {.compatible = "ti,cc2520", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cc2520_of_ids);
+
+/* SPI driver structure */
+static struct spi_driver cc2520_driver = {
+ .driver = {
+ .name = "cc2520",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(cc2520_of_ids),
+ },
+ .id_table = cc2520_ids,
+ .probe = cc2520_probe,
+ .remove = cc2520_remove,
+};
+module_spi_driver(cc2520_driver);
+
+MODULE_AUTHOR("Varka Bhadram <varkab@cdac.in>");
+MODULE_DESCRIPTION("CC2520 Transceiver Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
index 78f18be3bbf2..9ce854f43917 100644
--- a/drivers/net/ieee802154/fakehard.c
+++ b/drivers/net/ieee802154/fakehard.c
@@ -343,7 +343,8 @@ static int ieee802154fake_probe(struct platform_device *pdev)
if (!phy)
return -ENOMEM;
- dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d", ieee802154_fake_setup);
+ dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d",
+ NET_NAME_UNKNOWN, ieee802154_fake_setup);
if (!dev) {
wpan_phy_free(phy);
return -ENOMEM;
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 4048062011ba..9e6a124b13f2 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -610,10 +610,95 @@ out:
return IRQ_HANDLED;
}
+static int mrf24j40_hw_init(struct mrf24j40 *devrec)
+{
+ int ret;
+ u8 val;
+
+ /* Initialize the device.
+ From datasheet section 3.2: Initialization. */
+ ret = write_short_reg(devrec, REG_SOFTRST, 0x07);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_PACON2, 0x98);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_TXSTBL, 0x95);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON0, 0x03);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON1, 0x01);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON2, 0x80);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON6, 0x90);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON7, 0x80);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_RFCON8, 0x10);
+ if (ret)
+ goto err_ret;
+
+ ret = write_long_reg(devrec, REG_SLPCON1, 0x21);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_BBREG2, 0x80);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_CCAEDTH, 0x60);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_BBREG6, 0x40);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_RFCTL, 0x04);
+ if (ret)
+ goto err_ret;
+
+ ret = write_short_reg(devrec, REG_RFCTL, 0x0);
+ if (ret)
+ goto err_ret;
+
+ udelay(192);
+
+ /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
+ ret = read_short_reg(devrec, REG_RXMCR, &val);
+ if (ret)
+ goto err_ret;
+
+ val &= ~0x3; /* Clear RX mode (normal) */
+
+ ret = write_short_reg(devrec, REG_RXMCR, val);
+ if (ret)
+ goto err_ret;
+
+ return 0;
+
+err_ret:
+ return ret;
+}
+
static int mrf24j40_probe(struct spi_device *spi)
{
int ret = -ENOMEM;
- u8 val;
struct mrf24j40 *devrec;
printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
@@ -650,31 +735,9 @@ static int mrf24j40_probe(struct spi_device *spi)
if (ret)
goto err_register_device;
- /* Initialize the device.
- From datasheet section 3.2: Initialization. */
- write_short_reg(devrec, REG_SOFTRST, 0x07);
- write_short_reg(devrec, REG_PACON2, 0x98);
- write_short_reg(devrec, REG_TXSTBL, 0x95);
- write_long_reg(devrec, REG_RFCON0, 0x03);
- write_long_reg(devrec, REG_RFCON1, 0x01);
- write_long_reg(devrec, REG_RFCON2, 0x80);
- write_long_reg(devrec, REG_RFCON6, 0x90);
- write_long_reg(devrec, REG_RFCON7, 0x80);
- write_long_reg(devrec, REG_RFCON8, 0x10);
- write_long_reg(devrec, REG_SLPCON1, 0x21);
- write_short_reg(devrec, REG_BBREG2, 0x80);
- write_short_reg(devrec, REG_CCAEDTH, 0x60);
- write_short_reg(devrec, REG_BBREG6, 0x40);
- write_short_reg(devrec, REG_RFCTL, 0x04);
- write_short_reg(devrec, REG_RFCTL, 0x0);
- udelay(192);
-
- /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
- ret = read_short_reg(devrec, REG_RXMCR, &val);
+ ret = mrf24j40_hw_init(devrec);
if (ret)
- goto err_read_reg;
- val &= ~0x3; /* Clear RX mode (normal) */
- write_short_reg(devrec, REG_RXMCR, val);
+ goto err_hw_init;
ret = devm_request_threaded_irq(&spi->dev,
spi->irq,
@@ -692,7 +755,7 @@ static int mrf24j40_probe(struct spi_device *spi)
return 0;
err_irq:
-err_read_reg:
+err_hw_init:
ieee802154_unregister_device(devrec->dev);
err_register_device:
ieee802154_free_device(devrec->dev);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 46a7790be004..d2d4a3d2237f 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -269,8 +269,8 @@ static int __init ifb_init_one(int index)
struct ifb_private *dp;
int err;
- dev_ifb = alloc_netdev(sizeof(struct ifb_private),
- "ifb%d", ifb_setup);
+ dev_ifb = alloc_netdev(sizeof(struct ifb_private), "ifb%d",
+ NET_NAME_UNKNOWN, ifb_setup);
if (!dev_ifb)
return -ENOMEM;
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 5f91e3e01c04..aab2cf72d025 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -18,6 +18,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
@@ -175,6 +176,7 @@ struct au1k_private {
struct resource *ioarea;
struct au1k_irda_platform_data *platdata;
+ struct clk *irda_clk;
};
static int qos_mtt_bits = 0x07; /* 1 ms or more */
@@ -514,9 +516,39 @@ static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id)
static int au1k_init(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
- u32 enable, ring_address;
+ u32 enable, ring_address, phyck;
+ struct clk *c;
int i;
+ c = clk_get(NULL, "irda_clk");
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ i = clk_prepare_enable(c);
+ if (i) {
+ clk_put(c);
+ return i;
+ }
+
+ switch (clk_get_rate(c)) {
+ case 40000000:
+ phyck = IR_PHYCLK_40MHZ;
+ break;
+ case 48000000:
+ phyck = IR_PHYCLK_48MHZ;
+ break;
+ case 56000000:
+ phyck = IR_PHYCLK_56MHZ;
+ break;
+ case 64000000:
+ phyck = IR_PHYCLK_64MHZ;
+ break;
+ default:
+ clk_disable_unprepare(c);
+ clk_put(c);
+ return -EINVAL;
+ }
+ aup->irda_clk = c;
+
enable = IR_HC | IR_CE | IR_C;
#ifndef CONFIG_CPU_LITTLE_ENDIAN
enable |= IR_BE;
@@ -545,7 +577,7 @@ static int au1k_init(struct net_device *dev)
irda_write(aup, IR_RING_SIZE,
(RING_SIZE_64 << 8) | (RING_SIZE_64 << 12));
- irda_write(aup, IR_CONFIG_2, IR_PHYCLK_48MHZ | IR_ONE_PIN);
+ irda_write(aup, IR_CONFIG_2, phyck | IR_ONE_PIN);
irda_write(aup, IR_RING_ADDR_CMPR, 0);
au1k_irda_set_speed(dev, 9600);
@@ -619,6 +651,9 @@ static int au1k_irda_stop(struct net_device *dev)
free_irq(aup->irq_tx, dev);
free_irq(aup->irq_rx, dev);
+ clk_disable_unprepare(aup->irda_clk);
+ clk_put(aup->irda_clk);
+
return 0;
}
@@ -853,6 +888,7 @@ static int au1k_irda_probe(struct platform_device *pdev)
struct au1k_private *aup;
struct net_device *dev;
struct resource *r;
+ struct clk *c;
int err;
dev = alloc_irdadev(sizeof(struct au1k_private));
@@ -886,6 +922,14 @@ static int au1k_irda_probe(struct platform_device *pdev)
if (!aup->ioarea)
goto out;
+ /* bail out early if clock doesn't exist */
+ c = clk_get(NULL, "irda_clk");
+ if (IS_ERR(c)) {
+ err = PTR_ERR(c);
+ goto out;
+ }
+ clk_put(c);
+
aup->iobase = ioremap_nocache(r->start, resource_size(r));
if (!aup->iobase)
goto out2;
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 768dfe9a9315..a87a82ca111f 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -184,7 +184,7 @@
#define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC
#define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX
-static DEFINE_PCI_DEVICE_TABLE(toshoboe_pci_tbl) = {
+static const struct pci_device_id toshoboe_pci_tbl[] = {
{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, },
{ } /* Terminating entry */
@@ -1755,17 +1755,4 @@ static struct pci_driver donauboe_pci_driver = {
.resume = toshoboe_wakeup
};
-static int __init
-donauboe_init (void)
-{
- return pci_register_driver(&donauboe_pci_driver);
-}
-
-static void __exit
-donauboe_cleanup (void)
-{
- pci_unregister_driver(&donauboe_pci_driver);
-}
-
-module_init(donauboe_init);
-module_exit(donauboe_cleanup);
+module_pci_driver(donauboe_pci_driver);
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 96fe3659012d..e638893e98a9 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -553,8 +553,8 @@ static int kingsun_probe(struct usb_interface *intf,
return 0;
free_mem:
- if (kingsun->out_buf) kfree(kingsun->out_buf);
- if (kingsun->in_buf) kfree(kingsun->in_buf);
+ kfree(kingsun->out_buf);
+ kfree(kingsun->in_buf);
free_netdev(net);
err_out1:
return ret;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 998bb89ede71..36e004288ea7 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -115,7 +115,7 @@ static void iodelay(int udelay)
}
}
-static DEFINE_PCI_DEVICE_TABLE(via_pci_tbl) = {
+static const struct pci_device_id via_pci_tbl[] = {
{ PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 },
{ PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 },
{ PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 },
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 485006604bbc..a04af9d0f8f9 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -58,7 +58,7 @@ MODULE_LICENSE("GPL");
static /* const */ char drivername[] = DRIVER_NAME;
-static DEFINE_PCI_DEVICE_TABLE(vlsi_irda_table) = {
+static const struct pci_device_id vlsi_irda_table[] = {
{
.class = PCI_CLASS_WIRELESS_IRDA << 8,
.class_mask = PCI_CLASS_SUBCLASS_MASK << 8,
@@ -485,13 +485,13 @@ static int vlsi_create_hwif(vlsi_irda_dev_t *idev)
idev->virtaddr = NULL;
idev->busaddr = 0;
- ringarea = pci_alloc_consistent(idev->pdev, HW_RING_AREA_SIZE, &idev->busaddr);
+ ringarea = pci_zalloc_consistent(idev->pdev, HW_RING_AREA_SIZE,
+ &idev->busaddr);
if (!ringarea) {
IRDA_ERROR("%s: insufficient memory for descriptor rings\n",
__func__);
goto out;
}
- memset(ringarea, 0, HW_RING_AREA_SIZE);
hwmap = (struct ring_descr_hw *)ringarea;
idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1],
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index bb96409f8c05..8f2262540561 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -195,7 +195,7 @@ static __net_init int loopback_net_init(struct net *net)
int err;
err = -ENOMEM;
- dev = alloc_netdev(0, "lo", loopback_setup);
+ dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup);
if (!dev)
goto out;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 958df383068a..60e4ca01ccbb 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -45,10 +45,9 @@ struct macvlan_port {
struct sk_buff_head bc_queue;
struct work_struct bc_work;
bool passthru;
+ int count;
};
-#define MACVLAN_PORT_IS_EMPTY(port) list_empty(&port->vlans)
-
struct macvlan_skb_cb {
const struct macvlan_dev *src;
};
@@ -646,6 +645,7 @@ static int macvlan_init(struct net_device *dev)
(lowerdev->state & MACVLAN_STATE_MASK);
dev->features = lowerdev->features & MACVLAN_FEATURES;
dev->features |= ALWAYS_ON_FEATURES;
+ dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES;
dev->gso_max_size = lowerdev->gso_max_size;
dev->iflink = lowerdev->ifindex;
dev->hard_header_len = lowerdev->hard_header_len;
@@ -666,7 +666,8 @@ static void macvlan_uninit(struct net_device *dev)
free_percpu(vlan->pcpu_stats);
- if (MACVLAN_PORT_IS_EMPTY(port))
+ port->count -= 1;
+ if (!port->count)
macvlan_port_destroy(port->dev);
}
@@ -1019,12 +1020,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
- if (!MACVLAN_PORT_IS_EMPTY(port))
+ if (port->count)
return -EINVAL;
port->passthru = true;
eth_hw_addr_inherit(dev, lowerdev);
}
+ port->count += 1;
err = register_netdevice(dev);
if (err < 0)
goto destroy_port;
@@ -1042,7 +1044,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
unregister_netdev:
unregister_netdevice(dev);
destroy_port:
- if (MACVLAN_PORT_IS_EMPTY(port))
+ port->count -= 1;
+ if (!port->count)
macvlan_port_destroy(lowerdev);
return err;
diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c
index b57c22442867..f3230eef41fd 100644
--- a/drivers/net/phy/amd-xgbe-phy.c
+++ b/drivers/net/phy/amd-xgbe-phy.c
@@ -74,7 +74,6 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/uaccess.h>
-#include <asm/irq.h>
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
@@ -85,6 +84,8 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#define XGBE_PHY_ID 0x000162d0
#define XGBE_PHY_MASK 0xfffffff0
+#define XGBE_PHY_SPEEDSET_PROPERTY "amd,speed-set"
+
#define XGBE_AN_INT_CMPLT 0x01
#define XGBE_AN_INC_LINK 0x02
#define XGBE_AN_PG_RCV 0x04
@@ -94,6 +95,8 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#define XNP_MP_FORMATTED (1 << 13)
#define XNP_NP_EXCHANGE (1 << 15)
+#define XGBE_PHY_RATECHANGE_COUNT 500
+
#ifndef MDIO_PMA_10GBR_PMD_CTRL
#define MDIO_PMA_10GBR_PMD_CTRL 0x0096
#endif
@@ -116,10 +119,13 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#endif
/* SerDes integration register offsets */
+#define SIR0_KR_RT_1 0x002c
#define SIR0_STATUS 0x0040
#define SIR1_SPEED 0x0000
/* SerDes integration register entry bit positions and sizes */
+#define SIR0_KR_RT_1_RESET_INDEX 11
+#define SIR0_KR_RT_1_RESET_WIDTH 1
#define SIR0_STATUS_RX_READY_INDEX 0
#define SIR0_STATUS_RX_READY_WIDTH 1
#define SIR0_STATUS_TX_READY_INDEX 8
@@ -145,7 +151,7 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#define SPEED_2500_CDR 0x2
#define SPEED_2500_PLL 0x0
-#define SPEED_2500_RATE 0x2
+#define SPEED_2500_RATE 0x1
#define SPEED_2500_TXAMP 0xf
#define SPEED_2500_WORD 0x1
@@ -192,6 +198,16 @@ do { \
(_var) |= (((_val) & ((0x1 << (_width)) - 1)) << (_index)); \
} while (0)
+#define XSIR_GET_BITS(_var, _prefix, _field) \
+ GET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH)
+
+#define XSIR_SET_BITS(_var, _prefix, _field, _val) \
+ SET_BITS((_var), \
+ _prefix##_##_field##_INDEX, \
+ _prefix##_##_field##_WIDTH, (_val))
+
/* Macros for reading or writing SerDes integration registers
* The ioread macros will get bit fields or full values using the
* register definitions formed using the input names
@@ -292,6 +308,11 @@ enum amd_xgbe_phy_mode {
AMD_XGBE_MODE_KX,
};
+enum amd_xgbe_phy_speedset {
+ AMD_XGBE_PHY_SPEEDSET_1000_10000,
+ AMD_XGBE_PHY_SPEEDSET_2500_10000,
+};
+
struct amd_xgbe_phy_priv {
struct platform_device *pdev;
struct device *dev;
@@ -311,6 +332,7 @@ struct amd_xgbe_phy_priv {
/* Maintain link status for re-starting auto-negotiation */
unsigned int link;
enum amd_xgbe_phy_mode mode;
+ unsigned int speed_set;
/* Auto-negotiation state machine support */
struct mutex an_mutex;
@@ -380,14 +402,25 @@ static void amd_xgbe_phy_serdes_start_ratechange(struct phy_device *phydev)
static void amd_xgbe_phy_serdes_complete_ratechange(struct phy_device *phydev)
{
struct amd_xgbe_phy_priv *priv = phydev->priv;
+ unsigned int wait;
+ u16 status;
/* Release Rx and Tx ratechange */
XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, RATECHANGE, 0);
/* Wait for Rx and Tx ready */
- while (!XSIR0_IOREAD_BITS(priv, SIR0_STATUS, RX_READY) &&
- !XSIR0_IOREAD_BITS(priv, SIR0_STATUS, TX_READY))
- usleep_range(10, 20);
+ wait = XGBE_PHY_RATECHANGE_COUNT;
+ while (wait--) {
+ usleep_range(50, 75);
+
+ status = XSIR0_IOREAD(priv, SIR0_STATUS);
+ if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+ XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
+ return;
+ }
+
+ netdev_dbg(phydev->attached_dev, "SerDes rx/tx not ready (%#hx)\n",
+ status);
}
static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
@@ -546,10 +579,14 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
int ret;
/* If we are in KR switch to KX, and vice-versa */
- if (priv->mode == AMD_XGBE_MODE_KR)
- ret = amd_xgbe_phy_gmii_mode(phydev);
- else
+ if (priv->mode == AMD_XGBE_MODE_KR) {
+ if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000)
+ ret = amd_xgbe_phy_gmii_mode(phydev);
+ else
+ ret = amd_xgbe_phy_gmii_2500_mode(phydev);
+ } else {
ret = amd_xgbe_phy_xgmii_mode(phydev);
+ }
return ret;
}
@@ -602,9 +639,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
if (ret < 0)
return AMD_XGBE_AN_ERROR;
+ XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 1);
+
ret |= 0x01;
phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret);
+ XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 0);
+
return AMD_XGBE_AN_EVENT;
}
@@ -713,7 +754,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
else
ret &= ~0x80;
- if (phydev->supported & SUPPORTED_1000baseKX_Full)
+ if ((phydev->supported & SUPPORTED_1000baseKX_Full) ||
+ (phydev->supported & SUPPORTED_2500baseX_Full))
ret |= 0x20;
else
ret &= ~0x20;
@@ -815,6 +857,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
struct phy_device *phydev = priv->phydev;
enum amd_xgbe_phy_an cur_state;
int sleep;
+ unsigned int an_supported = 0;
while (1) {
mutex_lock(&priv->an_mutex);
@@ -824,6 +867,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
switch (priv->an_state) {
case AMD_XGBE_AN_START:
priv->an_state = amd_xgbe_an_start(phydev);
+ an_supported = 0;
break;
case AMD_XGBE_AN_EVENT:
@@ -832,6 +876,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
case AMD_XGBE_AN_PAGE_RECEIVED:
priv->an_state = amd_xgbe_an_page_received(phydev);
+ an_supported++;
break;
case AMD_XGBE_AN_INCOMPAT_LINK:
@@ -839,6 +884,11 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
break;
case AMD_XGBE_AN_COMPLETE:
+ netdev_info(phydev->attached_dev, "%s successful\n",
+ an_supported ? "Auto negotiation"
+ : "Parallel detection");
+ /* fall through */
+
case AMD_XGBE_AN_NO_LINK:
case AMD_XGBE_AN_EXIT:
goto exit_unlock;
@@ -896,14 +946,22 @@ static int amd_xgbe_phy_soft_reset(struct phy_device *phydev)
static int amd_xgbe_phy_config_init(struct phy_device *phydev)
{
+ struct amd_xgbe_phy_priv *priv = phydev->priv;
+
/* Initialize supported features */
phydev->supported = SUPPORTED_Autoneg;
phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
phydev->supported |= SUPPORTED_Backplane;
- phydev->supported |= SUPPORTED_1000baseKX_Full |
- SUPPORTED_2500baseX_Full;
phydev->supported |= SUPPORTED_10000baseKR_Full |
SUPPORTED_10000baseR_FEC;
+ switch (priv->speed_set) {
+ case AMD_XGBE_PHY_SPEEDSET_1000_10000:
+ phydev->supported |= SUPPORTED_1000baseKX_Full;
+ break;
+ case AMD_XGBE_PHY_SPEEDSET_2500_10000:
+ phydev->supported |= SUPPORTED_2500baseX_Full;
+ break;
+ }
phydev->advertising = phydev->supported;
/* Turn off and clear interrupts */
@@ -1020,9 +1078,9 @@ static int amd_xgbe_phy_update_link(struct phy_device *phydev)
* (re-)established (cable connected after the interface is
* up, etc.), the link status may report no link. If there
* is no link, try switching modes and checking the status
- * again.
+ * again if auto negotiation is enabled.
*/
- check_again = 1;
+ check_again = (phydev->autoneg == AUTONEG_ENABLE) ? 1 : 0;
again:
/* Link status is latched low, so read once to clear
* and then read again to get current state
@@ -1038,8 +1096,10 @@ again:
phydev->link = (ret & MDIO_STAT1_LSTATUS) ? 1 : 0;
if (!phydev->link) {
- ret = amd_xgbe_phy_switch_mode(phydev);
if (check_again) {
+ ret = amd_xgbe_phy_switch_mode(phydev);
+ if (ret < 0)
+ return ret;
check_again = 0;
goto again;
}
@@ -1059,6 +1119,7 @@ again:
static int amd_xgbe_phy_read_status(struct phy_device *phydev)
{
+ struct amd_xgbe_phy_priv *priv = phydev->priv;
u32 mmd_mask = phydev->c45_ids.devices_in_package;
int ret, mode, ad_ret, lp_ret;
@@ -1108,9 +1169,19 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
return ret;
}
} else {
- phydev->speed = SPEED_1000;
+ int (*mode_fcn)(struct phy_device *);
+
+ if (priv->speed_set ==
+ AMD_XGBE_PHY_SPEEDSET_1000_10000) {
+ phydev->speed = SPEED_1000;
+ mode_fcn = amd_xgbe_phy_gmii_mode;
+ } else {
+ phydev->speed = SPEED_2500;
+ mode_fcn = amd_xgbe_phy_gmii_2500_mode;
+ }
+
if (mode == MDIO_PCS_CTRL2_10GBR) {
- ret = amd_xgbe_phy_gmii_mode(phydev);
+ ret = mode_fcn(phydev);
if (ret < 0)
return ret;
}
@@ -1118,8 +1189,15 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
phydev->duplex = DUPLEX_FULL;
} else {
- phydev->speed = (mode == MDIO_PCS_CTRL2_10GBR) ? SPEED_10000
- : SPEED_1000;
+ if (mode == MDIO_PCS_CTRL2_10GBR) {
+ phydev->speed = SPEED_10000;
+ } else {
+ if (priv->speed_set ==
+ AMD_XGBE_PHY_SPEEDSET_1000_10000)
+ phydev->speed = SPEED_1000;
+ else
+ phydev->speed = SPEED_2500;
+ }
phydev->duplex = DUPLEX_FULL;
phydev->pause = 0;
phydev->asym_pause = 0;
@@ -1176,6 +1254,8 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
struct platform_device *pdev;
struct device *dev;
char *wq_name;
+ const __be32 *property;
+ unsigned int speed_set;
int ret;
if (!phydev->dev.of_node)
@@ -1227,6 +1307,26 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
goto err_sir0;
}
+ /* Get the device speed set property */
+ speed_set = 0;
+ property = of_get_property(dev->of_node, XGBE_PHY_SPEEDSET_PROPERTY,
+ NULL);
+ if (property)
+ speed_set = be32_to_cpu(*property);
+
+ switch (speed_set) {
+ case 0:
+ priv->speed_set = AMD_XGBE_PHY_SPEEDSET_1000_10000;
+ break;
+ case 1:
+ priv->speed_set = AMD_XGBE_PHY_SPEEDSET_2500_10000;
+ break;
+ default:
+ dev_err(dev, "invalid amd,speed-set property\n");
+ ret = -EINVAL;
+ goto err_sir1;
+ }
+
priv->link = 1;
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 9408157a246c..c301e4cb37ca 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -40,6 +40,7 @@
#define LAYER2 0x01
#define MAX_RXTS 64
#define N_EXT_TS 6
+#define N_PER_OUT 7
#define PSF_PTPVER 2
#define PSF_EVNT 0x4000
#define PSF_RX 0x2000
@@ -47,7 +48,6 @@
#define EXT_EVENT 1
#define CAL_EVENT 7
#define CAL_TRIGGER 7
-#define PER_TRIGGER 6
#define DP83640_N_PINS 12
#define MII_DP83640_MICR 0x11
@@ -74,7 +74,10 @@
#define ENDIAN_FLAG PSF_ENDIAN
#endif
-#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb))
+struct dp83640_skb_info {
+ int ptp_type;
+ unsigned long tmo;
+};
struct phy_rxts {
u16 ns_lo; /* ns[15:0] */
@@ -300,23 +303,23 @@ static u64 phy2txts(struct phy_txts *p)
}
static int periodic_output(struct dp83640_clock *clock,
- struct ptp_clock_request *clkreq, bool on)
+ struct ptp_clock_request *clkreq, bool on,
+ int trigger)
{
struct dp83640_private *dp83640 = clock->chosen;
struct phy_device *phydev = dp83640->phydev;
u32 sec, nsec, pwidth;
- u16 gpio, ptp_trig, trigger, val;
+ u16 gpio, ptp_trig, val;
if (on) {
- gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT, 0);
+ gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT,
+ trigger);
if (gpio < 1)
return -EINVAL;
} else {
gpio = 0;
}
- trigger = PER_TRIGGER;
-
ptp_trig = TRIG_WR |
(trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT |
(gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT |
@@ -353,6 +356,11 @@ static int periodic_output(struct dp83640_clock *clock,
ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16); /* sec[31:16] */
ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff); /* ns[15:0] */
ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16); /* ns[31:16] */
+ /* Triggers 0 and 1 has programmable pulsewidth2 */
+ if (trigger < 2) {
+ ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff);
+ ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16);
+ }
/*enable trigger*/
val &= ~TRIG_LOAD;
@@ -491,9 +499,9 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
return 0;
case PTP_CLK_REQ_PEROUT:
- if (rq->perout.index != 0)
+ if (rq->perout.index >= N_PER_OUT)
return -EINVAL;
- return periodic_output(clock, rq, on);
+ return periodic_output(clock, rq, on, rq->perout.index);
default:
break;
@@ -505,6 +513,16 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
static int ptp_dp83640_verify(struct ptp_clock_info *ptp, unsigned int pin,
enum ptp_pin_function func, unsigned int chan)
{
+ struct dp83640_clock *clock =
+ container_of(ptp, struct dp83640_clock, caps);
+
+ if (clock->caps.pin_config[pin].func == PTP_PF_PHYSYNC &&
+ !list_empty(&clock->phylist))
+ return 1;
+
+ if (func == PTP_PF_PHYSYNC)
+ return 1;
+
return 0;
}
@@ -594,7 +612,11 @@ static void recalibrate(struct dp83640_clock *clock)
u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val;
trigger = CAL_TRIGGER;
- cal_gpio = gpio_tab[CALIBRATE_GPIO];
+ cal_gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PHYSYNC, 0);
+ if (cal_gpio < 1) {
+ pr_err("PHY calibration pin not avaible - PHY is not calibrated.");
+ return;
+ }
mutex_lock(&clock->extreg_lock);
@@ -736,6 +758,9 @@ static int decode_evnt(struct dp83640_private *dp83640,
event.type = PTP_CLOCK_EXTTS;
event.timestamp = phy2txts(&dp83640->edata);
+ /* Compensate for input path and synchronization delays */
+ event.timestamp -= 35;
+
for (i = 0; i < N_EXT_TS; i++) {
if (ext_status & exts_chan_to_edata(i)) {
event.index = i;
@@ -746,10 +771,51 @@ static int decode_evnt(struct dp83640_private *dp83640,
return parsed * sizeof(u16);
}
+static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
+{
+ u16 *seqid;
+ unsigned int offset = 0;
+ u8 *msgtype, *data = skb_mac_header(skb);
+
+ /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
+
+ if (type & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+ break;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+ break;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+ return 0;
+
+ if (unlikely(type & PTP_CLASS_V1))
+ msgtype = data + offset + OFF_PTP_CONTROL;
+ else
+ msgtype = data + offset;
+
+ seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+ return rxts->msgtype == (*msgtype & 0xf) &&
+ rxts->seqid == ntohs(*seqid);
+}
+
static void decode_rxts(struct dp83640_private *dp83640,
struct phy_rxts *phy_rxts)
{
struct rxts *rxts;
+ struct skb_shared_hwtstamps *shhwtstamps = NULL;
+ struct sk_buff *skb;
unsigned long flags;
spin_lock_irqsave(&dp83640->rx_lock, flags);
@@ -763,7 +829,26 @@ static void decode_rxts(struct dp83640_private *dp83640,
rxts = list_first_entry(&dp83640->rxpool, struct rxts, list);
list_del_init(&rxts->list);
phy2rxts(phy_rxts, rxts);
- list_add_tail(&rxts->list, &dp83640->rxts);
+
+ spin_lock_irqsave(&dp83640->rx_queue.lock, flags);
+ skb_queue_walk(&dp83640->rx_queue, skb) {
+ struct dp83640_skb_info *skb_info;
+
+ skb_info = (struct dp83640_skb_info *)skb->cb;
+ if (match(skb, skb_info->ptp_type, rxts)) {
+ __skb_unlink(skb, &dp83640->rx_queue);
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+ netif_rx_ni(skb);
+ list_add(&rxts->list, &dp83640->rxpool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&dp83640->rx_queue.lock, flags);
+
+ if (!shhwtstamps)
+ list_add_tail(&rxts->list, &dp83640->rxts);
out:
spin_unlock_irqrestore(&dp83640->rx_lock, flags);
}
@@ -837,20 +922,18 @@ static int is_sync(struct sk_buff *skb, int type)
u8 *data = skb->data, *msgtype;
unsigned int offset = 0;
- switch (type) {
- case PTP_CLASS_V1_IPV4:
- case PTP_CLASS_V2_IPV4:
- offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
- break;
- case PTP_CLASS_V1_IPV6:
- case PTP_CLASS_V2_IPV6:
- offset = OFF_PTP6;
+ if (type & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
break;
- case PTP_CLASS_V2_L2:
- offset = ETH_HLEN;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
break;
- case PTP_CLASS_V2_VLAN:
- offset = ETH_HLEN + VLAN_HLEN;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
break;
default:
return 0;
@@ -867,47 +950,6 @@ static int is_sync(struct sk_buff *skb, int type)
return (*msgtype & 0xf) == 0;
}
-static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
-{
- u16 *seqid;
- unsigned int offset;
- u8 *msgtype, *data = skb_mac_header(skb);
-
- /* check sequenceID, messageType, 12 bit hash of offset 20-29 */
-
- switch (type) {
- case PTP_CLASS_V1_IPV4:
- case PTP_CLASS_V2_IPV4:
- offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
- break;
- case PTP_CLASS_V1_IPV6:
- case PTP_CLASS_V2_IPV6:
- offset = OFF_PTP6;
- break;
- case PTP_CLASS_V2_L2:
- offset = ETH_HLEN;
- break;
- case PTP_CLASS_V2_VLAN:
- offset = ETH_HLEN + VLAN_HLEN;
- break;
- default:
- return 0;
- }
-
- if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
- return 0;
-
- if (unlikely(type & PTP_CLASS_V1))
- msgtype = data + offset + OFF_PTP_CONTROL;
- else
- msgtype = data + offset;
-
- seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
-
- return rxts->msgtype == (*msgtype & 0xf) &&
- rxts->seqid == ntohs(*seqid);
-}
-
static void dp83640_free_clocks(void)
{
struct dp83640_clock *clock;
@@ -944,7 +986,7 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus)
clock->caps.max_adj = 1953124;
clock->caps.n_alarm = 0;
clock->caps.n_ext_ts = N_EXT_TS;
- clock->caps.n_per_out = 1;
+ clock->caps.n_per_out = N_PER_OUT;
clock->caps.n_pins = DP83640_N_PINS;
clock->caps.pps = 0;
clock->caps.adjfreq = ptp_dp83640_adjfreq;
@@ -1284,44 +1326,34 @@ static void rx_timestamp_work(struct work_struct *work)
{
struct dp83640_private *dp83640 =
container_of(work, struct dp83640_private, ts_work);
- struct list_head *this, *next;
- struct rxts *rxts;
- struct skb_shared_hwtstamps *shhwtstamps;
struct sk_buff *skb;
- unsigned int type;
- unsigned long flags;
- /* Deliver each deferred packet, with or without a time stamp. */
-
- while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) {
- type = SKB_PTP_TYPE(skb);
- spin_lock_irqsave(&dp83640->rx_lock, flags);
- list_for_each_safe(this, next, &dp83640->rxts) {
- rxts = list_entry(this, struct rxts, list);
- if (match(skb, type, rxts)) {
- shhwtstamps = skb_hwtstamps(skb);
- memset(shhwtstamps, 0, sizeof(*shhwtstamps));
- shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
- list_del_init(&rxts->list);
- list_add(&rxts->list, &dp83640->rxpool);
- break;
- }
+ /* Deliver expired packets. */
+ while ((skb = skb_dequeue(&dp83640->rx_queue))) {
+ struct dp83640_skb_info *skb_info;
+
+ skb_info = (struct dp83640_skb_info *)skb->cb;
+ if (!time_after(jiffies, skb_info->tmo)) {
+ skb_queue_head(&dp83640->rx_queue, skb);
+ break;
}
- spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+
netif_rx_ni(skb);
}
- /* Clear out expired time stamps. */
-
- spin_lock_irqsave(&dp83640->rx_lock, flags);
- prune_rx_ts(dp83640);
- spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+ if (!skb_queue_empty(&dp83640->rx_queue))
+ schedule_work(&dp83640->ts_work);
}
static bool dp83640_rxtstamp(struct phy_device *phydev,
struct sk_buff *skb, int type)
{
struct dp83640_private *dp83640 = phydev->priv;
+ struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
+ struct list_head *this, *next;
+ struct rxts *rxts;
+ struct skb_shared_hwtstamps *shhwtstamps = NULL;
+ unsigned long flags;
if (is_status_frame(skb, type)) {
decode_status_frame(dp83640, skb);
@@ -1332,9 +1364,27 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!dp83640->hwts_rx_en)
return false;
- SKB_PTP_TYPE(skb) = type;
- skb_queue_tail(&dp83640->rx_queue, skb);
- schedule_work(&dp83640->ts_work);
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+ list_for_each_safe(this, next, &dp83640->rxts) {
+ rxts = list_entry(this, struct rxts, list);
+ if (match(skb, type, rxts)) {
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns);
+ netif_rx_ni(skb);
+ list_del_init(&rxts->list);
+ list_add(&rxts->list, &dp83640->rxpool);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&dp83640->rx_lock, flags);
+
+ if (!shhwtstamps) {
+ skb_info->ptp_type = type;
+ skb_info->tmo = jiffies + 2;
+ skb_queue_tail(&dp83640->rx_queue, skb);
+ schedule_work(&dp83640->ts_work);
+ }
return true;
}
@@ -1355,7 +1405,6 @@ static void dp83640_txtstamp(struct phy_device *phydev,
case HWTSTAMP_TX_ON:
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
skb_queue_tail(&dp83640->tx_queue, skb);
- schedule_work(&dp83640->ts_work);
break;
case HWTSTAMP_TX_OFF:
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 203651ebccb0..4eaadcfcb0fe 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -255,7 +255,6 @@ int mdiobus_register(struct mii_bus *bus)
bus->dev.parent = bus->parent;
bus->dev.class = &mdio_bus_class;
- bus->dev.driver = bus->parent->driver;
bus->dev.groups = NULL;
dev_set_name(&bus->dev, "%s", bus->id);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index bc7c7d2f75f2..fd0ea7c50ee6 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -420,6 +420,26 @@ static int ksz8873mll_config_aneg(struct phy_device *phydev)
return 0;
}
+/* This routine returns -1 as an indication to the caller that the
+ * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE
+ * MMD extended PHY registers.
+ */
+static int
+ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
+ int regnum)
+{
+ return -1;
+}
+
+/* This routine does nothing since the Micrel ksz9021 does not support
+ * standard IEEE MMD extended PHY registers.
+ */
+static void
+ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
+ int regnum, u32 val)
+{
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -565,6 +585,8 @@ static struct phy_driver ksphy_driver[] = {
.config_intr = ksz9021_config_intr,
.suspend = genphy_suspend,
.resume = genphy_resume,
+ .read_mmd_indirect = ksz9021_rd_mmd_phyreg,
+ .write_mmd_indirect = ksz9021_wr_mmd_phyreg,
.driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ9031,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index f7c61812ea4a..c94e2a27446a 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -138,11 +138,31 @@ struct phy_setting {
/* A mapping of all SUPPORTED settings to speed/duplex */
static const struct phy_setting settings[] = {
{
- .speed = 10000,
+ .speed = SPEED_10000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10000baseKR_Full,
+ },
+ {
+ .speed = SPEED_10000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_10000baseKX4_Full,
+ },
+ {
+ .speed = SPEED_10000,
.duplex = DUPLEX_FULL,
.setting = SUPPORTED_10000baseT_Full,
},
{
+ .speed = SPEED_2500,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_2500baseX_Full,
+ },
+ {
+ .speed = SPEED_1000,
+ .duplex = DUPLEX_FULL,
+ .setting = SUPPORTED_1000baseKX_Full,
+ },
+ {
.speed = SPEED_1000,
.duplex = DUPLEX_FULL,
.setting = SUPPORTED_1000baseT_Full,
@@ -922,7 +942,7 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
/**
* phy_read_mmd_indirect - reads data from the MMD registers
- * @bus: the target MII bus
+ * @phydev: The PHY device bus
* @prtad: MMD Address
* @devad: MMD DEVAD
* @addr: PHY address on the MII bus
@@ -935,18 +955,26 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
* 3) Read reg 14 // Read MMD data
*/
-static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
- int addr)
+static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
+ int devad, int addr)
{
- mmd_phy_indirect(bus, prtad, devad, addr);
+ struct phy_driver *phydrv = phydev->drv;
+ int value = -1;
- /* Read the content of the MMD's selected register */
- return bus->read(bus, addr, MII_MMD_DATA);
+ if (phydrv->read_mmd_indirect == NULL) {
+ mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+
+ /* Read the content of the MMD's selected register */
+ value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA);
+ } else {
+ value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
+ }
+ return value;
}
/**
* phy_write_mmd_indirect - writes data to the MMD registers
- * @bus: the target MII bus
+ * @phydev: The PHY device
* @prtad: MMD Address
* @devad: MMD DEVAD
* @addr: PHY address on the MII bus
@@ -960,13 +988,19 @@ static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
* 3) Write reg 13 // MMD Data Command for MMD DEVAD
* 3) Write reg 14 // Write MMD data
*/
-static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad,
- int addr, u32 data)
+static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
+ int devad, int addr, u32 data)
{
- mmd_phy_indirect(bus, prtad, devad, addr);
+ struct phy_driver *phydrv = phydev->drv;
- /* Write the data into MMD's selected register */
- bus->write(bus, addr, MII_MMD_DATA, data);
+ if (phydrv->write_mmd_indirect == NULL) {
+ mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+
+ /* Write the data into MMD's selected register */
+ phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data);
+ } else {
+ phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
+ }
}
/**
@@ -1000,7 +1034,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
return status;
/* First check if the EEE ability is supported */
- eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+ eee_cap = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,
MDIO_MMD_PCS, phydev->addr);
if (eee_cap < 0)
return eee_cap;
@@ -1012,12 +1046,12 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
/* Check which link settings negotiated and verify it in
* the EEE advertising registers.
*/
- eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+ eee_lp = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,
MDIO_MMD_AN, phydev->addr);
if (eee_lp < 0)
return eee_lp;
- eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+ eee_adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN, phydev->addr);
if (eee_adv < 0)
return eee_adv;
@@ -1032,15 +1066,16 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
/* Configure the PHY to stop receiving xMII
* clock while it is signaling LPI.
*/
- int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1,
+ int val = phy_read_mmd_indirect(phydev, MDIO_CTRL1,
MDIO_MMD_PCS,
phydev->addr);
if (val < 0)
return val;
val |= MDIO_PCS_CTRL1_CLKSTOP_EN;
- phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1,
- MDIO_MMD_PCS, phydev->addr, val);
+ phy_write_mmd_indirect(phydev, MDIO_CTRL1,
+ MDIO_MMD_PCS, phydev->addr,
+ val);
}
return 0; /* EEE supported */
@@ -1059,7 +1094,7 @@ EXPORT_SYMBOL(phy_init_eee);
*/
int phy_get_eee_err(struct phy_device *phydev)
{
- return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR,
+ return phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_WK_ERR,
MDIO_MMD_PCS, phydev->addr);
}
EXPORT_SYMBOL(phy_get_eee_err);
@@ -1077,21 +1112,21 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
int val;
/* Get Supported EEE */
- val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE,
+ val = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,
MDIO_MMD_PCS, phydev->addr);
if (val < 0)
return val;
data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
/* Get advertisement EEE */
- val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV,
+ val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN, phydev->addr);
if (val < 0)
return val;
data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
/* Get LP advertisement EEE */
- val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE,
+ val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,
MDIO_MMD_AN, phydev->addr);
if (val < 0)
return val;
@@ -1112,7 +1147,7 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
- phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
+ phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN,
phydev->addr, val);
return 0;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 22c57be4dfa0..ca5ec3e18d36 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -709,6 +709,7 @@ int phy_suspend(struct phy_device *phydev)
return phydrv->suspend(phydev);
return 0;
}
+EXPORT_SYMBOL(phy_suspend);
int phy_resume(struct phy_device *phydev)
{
@@ -718,6 +719,7 @@ int phy_resume(struct phy_device *phydev)
return phydrv->resume(phydev);
return 0;
}
+EXPORT_SYMBOL(phy_resume);
/* Generic PHY support and helper functions */
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index 22b047f1fcdc..eab57fc5b967 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -277,7 +277,7 @@ static int ks8995_probe(struct spi_device *spi)
/* Chip description */
pdata = spi->dev.platform_data;
- ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+ ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL);
if (!ks)
return -ENOMEM;
@@ -291,14 +291,14 @@ static int ks8995_probe(struct spi_device *spi)
err = spi_setup(spi);
if (err) {
dev_err(&spi->dev, "spi_setup failed, err=%d\n", err);
- goto err_drvdata;
+ return err;
}
err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids));
if (err < 0) {
dev_err(&spi->dev, "unable to read id registers, err=%d\n",
err);
- goto err_drvdata;
+ return err;
}
switch (ids[0]) {
@@ -306,8 +306,7 @@ static int ks8995_probe(struct spi_device *spi)
break;
default:
dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]);
- err = -ENODEV;
- goto err_drvdata;
+ return -ENODEV;
}
memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr));
@@ -320,24 +319,24 @@ static int ks8995_probe(struct spi_device *spi)
dev_err(&spi->dev,
"unable to read chip id register, err=%d\n",
err);
- goto err_drvdata;
+ return err;
}
if ((val & 0x80) == 0) {
dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]);
- goto err_drvdata;
+ return err;
}
ks->regs_attr.size = KSZ8864_REGS_SIZE;
}
err = ks8995_reset(ks);
if (err)
- goto err_drvdata;
+ return err;
err = sysfs_create_bin_file(&spi->dev.kobj, &ks->regs_attr);
if (err) {
dev_err(&spi->dev, "unable to create sysfs file, err=%d\n",
err);
- goto err_drvdata;
+ return err;
}
if (get_chip_id(ids[1]) == CHIPID_M) {
@@ -350,21 +349,12 @@ static int ks8995_probe(struct spi_device *spi)
}
return 0;
-
-err_drvdata:
- kfree(ks);
- return err;
}
static int ks8995_remove(struct spi_device *spi)
{
- struct ks8995_data *ks8995;
-
- ks8995 = spi_get_drvdata(spi);
sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
- kfree(ks8995);
-
return 0;
}
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index d5b77ef3a210..fa0d71727894 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -143,8 +143,8 @@ struct ppp {
struct sk_buff_head mrq; /* MP: receive reconstruction queue */
#endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER
- struct sk_filter *pass_filter; /* filter for packets to pass */
- struct sk_filter *active_filter;/* filter for pkts to reset idle */
+ struct bpf_prog *pass_filter; /* filter for packets to pass */
+ struct bpf_prog *active_filter; /* filter for pkts to reset idle */
#endif /* CONFIG_PPP_FILTER */
struct net *ppp_net; /* the net we belong to */
struct ppp_link_stats stats64; /* 64 bit network stats */
@@ -655,6 +655,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
ppp_lock(ppp);
cflags = ppp->flags & ~val;
+#ifdef CONFIG_PPP_MULTILINK
+ if (!(ppp->flags & SC_MULTILINK) && (val & SC_MULTILINK))
+ ppp->nextseq = 0;
+#endif
ppp->flags = val & SC_FLAG_BITS;
ppp_unlock(ppp);
if (cflags & SC_CCP_OPEN)
@@ -758,12 +762,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ppp_lock(ppp);
if (ppp->pass_filter) {
- sk_unattached_filter_destroy(ppp->pass_filter);
+ bpf_prog_destroy(ppp->pass_filter);
ppp->pass_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&ppp->pass_filter,
- &fprog);
+ err = bpf_prog_create(&ppp->pass_filter,
+ &fprog);
else
err = 0;
kfree(code);
@@ -784,12 +788,12 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ppp_lock(ppp);
if (ppp->active_filter) {
- sk_unattached_filter_destroy(ppp->active_filter);
+ bpf_prog_destroy(ppp->active_filter);
ppp->active_filter = NULL;
}
if (fprog.filter != NULL)
- err = sk_unattached_filter_create(&ppp->active_filter,
- &fprog);
+ err = bpf_prog_create(&ppp->active_filter,
+ &fprog);
else
err = 0;
kfree(code);
@@ -1201,7 +1205,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
a four-byte PPP header on each packet */
*skb_push(skb, 2) = 1;
if (ppp->pass_filter &&
- SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+ BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: outbound frame "
@@ -1211,7 +1215,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
}
/* if this packet passes the active filter, record the time */
if (!(ppp->active_filter &&
- SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+ BPF_PROG_RUN(ppp->active_filter, skb) == 0))
ppp->last_xmit = jiffies;
skb_pull(skb, 2);
#else
@@ -1835,7 +1839,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
*skb_push(skb, 2) = 0;
if (ppp->pass_filter &&
- SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
+ BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: inbound frame "
@@ -1844,7 +1848,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
return;
}
if (!(ppp->active_filter &&
- SK_RUN_FILTER(ppp->active_filter, skb) == 0))
+ BPF_PROG_RUN(ppp->active_filter, skb) == 0))
ppp->last_recv = jiffies;
__skb_pull(skb, 2);
} else
@@ -2669,7 +2673,8 @@ ppp_create_interface(struct net *net, int unit, int *retp)
int ret = -ENOMEM;
int i;
- dev = alloc_netdev(sizeof(struct ppp), "", ppp_setup);
+ dev = alloc_netdev(sizeof(struct ppp), "", NET_NAME_UNKNOWN,
+ ppp_setup);
if (!dev)
goto out1;
@@ -2824,12 +2829,12 @@ static void ppp_destroy_interface(struct ppp *ppp)
#endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER
if (ppp->pass_filter) {
- sk_unattached_filter_destroy(ppp->pass_filter);
+ bpf_prog_destroy(ppp->pass_filter);
ppp->pass_filter = NULL;
}
if (ppp->active_filter) {
- sk_unattached_filter_destroy(ppp->active_filter);
+ bpf_prog_destroy(ppp->active_filter);
ppp->active_filter = NULL;
}
#endif /* CONFIG_PPP_FILTER */
diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
index 1252d9c726a7..079f7adfcde5 100644
--- a/drivers/net/slip/slhc.c
+++ b/drivers/net/slip/slhc.c
@@ -396,7 +396,6 @@ found:
ntohs(cs->cs_ip.tot_len) == hlen)
break;
goto uncompressed;
- break;
case SPECIAL_I:
case SPECIAL_D:
/* actual changes match one of our special case encodings --
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 87526443841f..05387b1e2e95 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -749,7 +749,7 @@ static struct slip *sl_alloc(dev_t line)
return NULL;
sprintf(name, "sl%d", i);
- dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+ dev = alloc_netdev(sizeof(*sl), name, NET_NAME_UNKNOWN, sl_setup);
if (!dev)
return NULL;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index b4958c7ffa84..ef10302ec936 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2045,16 +2045,10 @@ static void team_setup(struct net_device *dev)
static int team_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
- int err;
-
if (tb[IFLA_ADDRESS] == NULL)
eth_hw_addr_random(dev);
- err = register_netdevice(dev);
- if (err)
- return err;
-
- return 0;
+ return register_netdevice(dev);
}
static int team_validate(struct nlattr *tb[], struct nlattr *data[])
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index a58dfebb5512..a1536d0d83a9 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -58,7 +58,7 @@ struct lb_priv_ex {
};
struct lb_priv {
- struct sk_filter __rcu *fp;
+ struct bpf_prog __rcu *fp;
lb_select_tx_port_func_t __rcu *select_tx_port_func;
struct lb_pcpu_stats __percpu *pcpu_stats;
struct lb_priv_ex *ex; /* priv extension */
@@ -174,14 +174,14 @@ static lb_select_tx_port_func_t *lb_select_tx_port_get_func(const char *name)
static unsigned int lb_get_skb_hash(struct lb_priv *lb_priv,
struct sk_buff *skb)
{
- struct sk_filter *fp;
+ struct bpf_prog *fp;
uint32_t lhash;
unsigned char *c;
fp = rcu_dereference_bh(lb_priv->fp);
if (unlikely(!fp))
return 0;
- lhash = SK_RUN_FILTER(fp, skb);
+ lhash = BPF_PROG_RUN(fp, skb);
c = (char *) &lhash;
return c[0] ^ c[1] ^ c[2] ^ c[3];
}
@@ -271,8 +271,8 @@ static void __fprog_destroy(struct sock_fprog_kern *fprog)
static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
{
struct lb_priv *lb_priv = get_lb_priv(team);
- struct sk_filter *fp = NULL;
- struct sk_filter *orig_fp;
+ struct bpf_prog *fp = NULL;
+ struct bpf_prog *orig_fp = NULL;
struct sock_fprog_kern *fprog = NULL;
int err;
@@ -281,7 +281,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
ctx->data.bin_val.ptr);
if (err)
return err;
- err = sk_unattached_filter_create(&fp, fprog);
+ err = bpf_prog_create(&fp, fprog);
if (err) {
__fprog_destroy(fprog);
return err;
@@ -293,11 +293,15 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
__fprog_destroy(lb_priv->ex->orig_fprog);
orig_fp = rcu_dereference_protected(lb_priv->fp,
lockdep_is_held(&team->lock));
- sk_unattached_filter_destroy(orig_fp);
}
rcu_assign_pointer(lb_priv->fp, fp);
lb_priv->ex->orig_fprog = fprog;
+
+ if (orig_fp) {
+ synchronize_rcu();
+ bpf_prog_destroy(orig_fp);
+ }
return 0;
}
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 98bad1fb1bfb..acaaf6784179 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1633,7 +1633,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
name = ifr->ifr_name;
dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
- tun_setup, queues, queues);
+ NET_NAME_UNKNOWN, tun_setup, queues,
+ queues);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 7e7269fd3707..37eed4d84e9c 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -1,12 +1,16 @@
#
# USB Network devices configuration
#
-comment "Networking support is needed for USB Network Adapter support"
- depends on USB && !NET
+comment "Host-side USB support is needed for USB Network Adapter support"
+ depends on !USB && NET
-menu "USB Network Adapters"
+menuconfig USB_NET_DRIVERS
+ tristate "USB Network Adapters"
+ default USB if USB
depends on USB && NET
+if USB_NET_DRIVERS
+
config USB_CATC
tristate "USB CATC NetMate-based Ethernet device support"
select CRC32
@@ -568,5 +572,4 @@ config USB_VL600
http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
-
-endmenu
+endif # USB_NET_DRIVERS
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 054e59ca6946..be4275721039 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -23,6 +23,8 @@
#include <linux/usb.h>
#include <linux/crc32.h>
#include <linux/usb/usbnet.h>
+#include <uapi/linux/mdio.h>
+#include <linux/mdio.h>
#define AX88179_PHY_ID 0x03
#define AX_EEPROM_LEN 0x100
@@ -170,8 +172,12 @@
#define GMII_PHY_PAGE_SELECT 0x1f
#define GMII_PHY_PGSEL_EXT 0x0007
#define GMII_PHY_PGSEL_PAGE0 0x0000
+ #define GMII_PHY_PGSEL_PAGE3 0x0003
+ #define GMII_PHY_PGSEL_PAGE5 0x0005
struct ax88179_data {
+ u8 eee_enabled;
+ u8 eee_active;
u16 rxctl;
u16 reserved;
};
@@ -373,6 +379,60 @@ static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc,
ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res);
}
+static inline int ax88179_phy_mmd_indirect(struct usbnet *dev, u16 prtad,
+ u16 devad)
+{
+ u16 tmp16;
+ int ret;
+
+ tmp16 = devad;
+ ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_MMD_CTRL, 2, &tmp16);
+
+ tmp16 = prtad;
+ ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_MMD_DATA, 2, &tmp16);
+
+ tmp16 = devad | MII_MMD_CTRL_NOINCR;
+ ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_MMD_CTRL, 2, &tmp16);
+
+ return ret;
+}
+
+static int
+ax88179_phy_read_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad)
+{
+ int ret;
+ u16 tmp16;
+
+ ax88179_phy_mmd_indirect(dev, prtad, devad);
+
+ ret = ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_MMD_DATA, 2, &tmp16);
+ if (ret < 0)
+ return ret;
+
+ return tmp16;
+}
+
+static int
+ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad,
+ u16 data)
+{
+ int ret;
+
+ ax88179_phy_mmd_indirect(dev, prtad, devad);
+
+ ret = ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_MMD_DATA, 2, &data);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int ax88179_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usbnet *dev = usb_get_intfdata(intf);
@@ -572,6 +632,185 @@ static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
return mii_ethtool_sset(&dev->mii, cmd);
}
+static int
+ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
+{
+ int val;
+
+ /* Get Supported EEE */
+ val = ax88179_phy_read_mmd_indirect(dev, MDIO_PCS_EEE_ABLE,
+ MDIO_MMD_PCS);
+ if (val < 0)
+ return val;
+ data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
+
+ /* Get advertisement EEE */
+ val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV,
+ MDIO_MMD_AN);
+ if (val < 0)
+ return val;
+ data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+ /* Get LP advertisement EEE */
+ val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE,
+ MDIO_MMD_AN);
+ if (val < 0)
+ return val;
+ data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+
+ return 0;
+}
+
+static int
+ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data)
+{
+ u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+
+ return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV,
+ MDIO_MMD_AN, tmp16);
+}
+
+static int ax88179_chk_eee(struct usbnet *dev)
+{
+ struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+
+ mii_ethtool_gset(&dev->mii, &ecmd);
+
+ if (ecmd.duplex & DUPLEX_FULL) {
+ int eee_lp, eee_cap, eee_adv;
+ u32 lp, cap, adv, supported = 0;
+
+ eee_cap = ax88179_phy_read_mmd_indirect(dev,
+ MDIO_PCS_EEE_ABLE,
+ MDIO_MMD_PCS);
+ if (eee_cap < 0) {
+ priv->eee_active = 0;
+ return false;
+ }
+
+ cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
+ if (!cap) {
+ priv->eee_active = 0;
+ return false;
+ }
+
+ eee_lp = ax88179_phy_read_mmd_indirect(dev,
+ MDIO_AN_EEE_LPABLE,
+ MDIO_MMD_AN);
+ if (eee_lp < 0) {
+ priv->eee_active = 0;
+ return false;
+ }
+
+ eee_adv = ax88179_phy_read_mmd_indirect(dev,
+ MDIO_AN_EEE_ADV,
+ MDIO_MMD_AN);
+
+ if (eee_adv < 0) {
+ priv->eee_active = 0;
+ return false;
+ }
+
+ adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
+ lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
+ supported = (ecmd.speed == SPEED_1000) ?
+ SUPPORTED_1000baseT_Full :
+ SUPPORTED_100baseT_Full;
+
+ if (!(lp & adv & supported)) {
+ priv->eee_active = 0;
+ return false;
+ }
+
+ priv->eee_active = 1;
+ return true;
+ }
+
+ priv->eee_active = 0;
+ return false;
+}
+
+static void ax88179_disable_eee(struct usbnet *dev)
+{
+ u16 tmp16;
+
+ tmp16 = GMII_PHY_PGSEL_PAGE3;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+ tmp16 = 0x3246;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_PHYADDR, 2, &tmp16);
+
+ tmp16 = GMII_PHY_PGSEL_PAGE0;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ GMII_PHY_PAGE_SELECT, 2, &tmp16);
+}
+
+static void ax88179_enable_eee(struct usbnet *dev)
+{
+ u16 tmp16;
+
+ tmp16 = GMII_PHY_PGSEL_PAGE3;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+ tmp16 = 0x3247;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_PHYADDR, 2, &tmp16);
+
+ tmp16 = GMII_PHY_PGSEL_PAGE5;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ GMII_PHY_PAGE_SELECT, 2, &tmp16);
+
+ tmp16 = 0x0680;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ MII_BMSR, 2, &tmp16);
+
+ tmp16 = GMII_PHY_PGSEL_PAGE0;
+ ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID,
+ GMII_PHY_PAGE_SELECT, 2, &tmp16);
+}
+
+static int ax88179_get_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+
+ edata->eee_enabled = priv->eee_enabled;
+ edata->eee_active = priv->eee_active;
+
+ return ax88179_ethtool_get_eee(dev, edata);
+}
+
+static int ax88179_set_eee(struct net_device *net, struct ethtool_eee *edata)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct ax88179_data *priv = (struct ax88179_data *)dev->data;
+ int ret = -EOPNOTSUPP;
+
+ priv->eee_enabled = edata->eee_enabled;
+ if (!priv->eee_enabled) {
+ ax88179_disable_eee(dev);
+ } else {
+ priv->eee_enabled = ax88179_chk_eee(dev);
+ if (!priv->eee_enabled)
+ return -EOPNOTSUPP;
+
+ ax88179_enable_eee(dev);
+ }
+
+ ret = ax88179_ethtool_set_eee(dev, edata);
+ if (ret)
+ return ret;
+
+ mii_nway_restart(&dev->mii);
+
+ usbnet_link_change(dev, 0, 0);
+
+ return ret;
+}
static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
@@ -589,6 +828,8 @@ static const struct ethtool_ops ax88179_ethtool_ops = {
.get_eeprom = ax88179_get_eeprom,
.get_settings = ax88179_get_settings,
.set_settings = ax88179_set_settings,
+ .get_eee = ax88179_get_eee,
+ .set_eee = ax88179_set_eee,
.nway_reset = usbnet_nway_reset,
};
@@ -980,6 +1221,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
u16 *tmp16;
u8 *tmp;
struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+ struct ethtool_eee eee_data;
usbnet_get_endpoints(dev, intf);
@@ -1062,6 +1304,15 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
ax88179_led_setting(dev);
+ ax179_data->eee_enabled = 0;
+ ax179_data->eee_active = 0;
+
+ ax88179_disable_eee(dev);
+
+ ax88179_ethtool_get_eee(dev, &eee_data);
+ eee_data.advertised = 0;
+ ax88179_ethtool_set_eee(dev, &eee_data);
+
/* Restart autoneg */
mii_nway_restart(&dev->mii);
@@ -1261,6 +1512,8 @@ static int ax88179_link_reset(struct usbnet *dev)
ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
2, 2, &mode);
+ ax179_data->eee_enabled = ax88179_chk_eee(dev);
+
netif_carrier_on(dev->net);
return 0;
@@ -1271,6 +1524,8 @@ static int ax88179_reset(struct usbnet *dev)
u8 buf[5];
u16 *tmp16;
u8 *tmp;
+ struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data;
+ struct ethtool_eee eee_data;
tmp16 = (u16 *)buf;
tmp = (u8 *)buf;
@@ -1340,6 +1595,15 @@ static int ax88179_reset(struct usbnet *dev)
ax88179_led_setting(dev);
+ ax179_data->eee_enabled = 0;
+ ax179_data->eee_active = 0;
+
+ ax88179_disable_eee(dev);
+
+ ax88179_ethtool_get_eee(dev, &eee_data);
+ eee_data.advertised = 0;
+ ax88179_ethtool_set_eee(dev, &eee_data);
+
/* Restart autoneg */
mii_nway_restart(&dev->mii);
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 6358d420e185..2ec1500d0077 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -387,7 +387,7 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i
return -EINVAL;
dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
- ifname, usbpn_setup);
+ ifname, NET_NAME_UNKNOWN, usbpn_setup);
if (!dev)
return -ENOMEM;
diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c
index 91f0919fe278..6ea98cff2d3b 100644
--- a/drivers/net/usb/cdc_subset.c
+++ b/drivers/net/usb/cdc_subset.c
@@ -85,14 +85,28 @@ static int always_connected (struct usbnet *dev)
*
*-------------------------------------------------------------------------*/
+static void m5632_recover(struct usbnet *dev)
+{
+ struct usb_device *udev = dev->udev;
+ struct usb_interface *intf = dev->intf;
+ int r;
+
+ r = usb_lock_device_for_reset(udev, intf);
+ if (r < 0)
+ return;
+
+ usb_reset_device(udev);
+ usb_unlock_device(udev);
+}
+
static const struct driver_info ali_m5632_info = {
.description = "ALi M5632",
.flags = FLAG_POINTTOPOINT,
+ .recover = m5632_recover,
};
#endif
-
#ifdef CONFIG_USB_AN2720
#define HAVE_HARDWARE
@@ -326,12 +340,23 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
/*-------------------------------------------------------------------------*/
+static int dummy_prereset(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int dummy_postreset(struct usb_interface *intf)
+{
+ return 0;
+}
static struct usb_driver cdc_subset_driver = {
.name = "cdc_subset",
.probe = usbnet_probe,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
+ .pre_reset = dummy_prereset,
+ .post_reset = dummy_postreset,
.disconnect = usbnet_disconnect,
.id_table = products,
.disable_hub_initiated_lpm = 1,
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index a4272ed62da8..babda7d8693e 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -467,6 +467,7 @@ static const struct usb_device_id hso_ids[] = {
{USB_DEVICE(0x0af0, 0x8800)},
{USB_DEVICE(0x0af0, 0x8900)},
{USB_DEVICE(0x0af0, 0x9000)},
+ {USB_DEVICE(0x0af0, 0x9200)}, /* Option GTM671WFS */
{USB_DEVICE(0x0af0, 0xd035)},
{USB_DEVICE(0x0af0, 0xd055)},
{USB_DEVICE(0x0af0, 0xd155)},
@@ -2504,7 +2505,8 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
/* allocate our network device, then we can put in our private data */
/* call hso_net_init to do the basic initialization */
- net = alloc_netdev(sizeof(struct hso_net), "hso%d", hso_net_init);
+ net = alloc_netdev(sizeof(struct hso_net), "hso%d", NET_NAME_UNKNOWN,
+ hso_net_init);
if (!net) {
dev_err(&interface->dev, "Unable to create ethernet device\n");
goto exit;
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 3eab74c7c554..87f710476217 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -59,6 +59,7 @@
#define PLA_WDT6_CTRL 0xe428
#define PLA_TCR0 0xe610
#define PLA_TCR1 0xe612
+#define PLA_MTPS 0xe615
#define PLA_TXFIFO_CTRL 0xe618
#define PLA_RSTTALLY 0xe800
#define PLA_CR 0xe813
@@ -180,6 +181,10 @@
/* PLA_TCR1 */
#define VERSION_MASK 0x7cf0
+/* PLA_MTPS */
+#define MTPS_JUMBO (12 * 1024 / 64)
+#define MTPS_DEFAULT (6 * 1024 / 64)
+
/* PLA_RSTTALLY */
#define TALLY_RESET 0x0001
@@ -440,8 +445,11 @@ enum rtl_register_content {
#define BYTE_EN_START_MASK 0x0f
#define BYTE_EN_END_MASK 0xf0
+#define RTL8153_MAX_PACKET 9216 /* 9K */
+#define RTL8153_MAX_MTU (RTL8153_MAX_PACKET - VLAN_ETH_HLEN - VLAN_HLEN)
#define RTL8152_RMS (VLAN_ETH_FRAME_LEN + VLAN_HLEN)
-#define RTL8152_TX_TIMEOUT (HZ)
+#define RTL8153_RMS RTL8153_MAX_PACKET
+#define RTL8152_TX_TIMEOUT (5 * HZ)
/* rtl8152 flags */
enum rtl8152_flags {
@@ -2521,7 +2529,8 @@ static void r8153_first_init(struct r8152 *tp)
ocp_data &= ~CPCR_RX_VLAN;
ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
+ ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
ocp_data |= TCR0_AUTO_FIFO;
@@ -2571,7 +2580,7 @@ static void r8153_enter_oob(struct r8152 *tp)
mdelay(1);
}
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8153_RMS);
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
ocp_data &= ~TEREDO_WAKE_MASK;
@@ -3288,6 +3297,26 @@ out:
return res;
}
+static int rtl8152_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct r8152 *tp = netdev_priv(dev);
+
+ switch (tp->version) {
+ case RTL_VER_01:
+ case RTL_VER_02:
+ return eth_change_mtu(dev, new_mtu);
+ default:
+ break;
+ }
+
+ if (new_mtu < 68 || new_mtu > RTL8153_MAX_MTU)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+
+ return 0;
+}
+
static const struct net_device_ops rtl8152_netdev_ops = {
.ndo_open = rtl8152_open,
.ndo_stop = rtl8152_close,
@@ -3296,8 +3325,7 @@ static const struct net_device_ops rtl8152_netdev_ops = {
.ndo_tx_timeout = rtl8152_tx_timeout,
.ndo_set_rx_mode = rtl8152_set_rx_mode,
.ndo_set_mac_address = rtl8152_set_mac_address,
-
- .ndo_change_mtu = eth_change_mtu,
+ .ndo_change_mtu = rtl8152_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f9e96c427558..5173821a9575 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1218,8 +1218,12 @@ void usbnet_tx_timeout (struct net_device *net)
unlink_urbs (dev, &dev->txq);
tasklet_schedule (&dev->bh);
-
- // FIXME: device recovery -- reset?
+ /* this needs to be handled individually because the generic layer
+ * doesn't know what is sufficient and could not restore private
+ * information if a remedy of an unconditional reset were used.
+ */
+ if (dev->driver_info->recover)
+ (dev->driver_info->recover)(dev);
}
EXPORT_SYMBOL_GPL(usbnet_tx_timeout);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index b4a10bcb66a0..8ad596573d17 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -248,6 +248,21 @@ static void veth_dev_free(struct net_device *dev)
free_netdev(dev);
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void veth_poll_controller(struct net_device *dev)
+{
+ /* veth only receives frames when its peer sends one
+ * Since it's a synchronous operation, we are guaranteed
+ * never to have pending data when we poll for it so
+ * there is nothing to do here.
+ *
+ * We need this though so netpoll recognizes us as an interface that
+ * supports polling, which enables bridge devices in virt setups to
+ * still use netconsole
+ */
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init,
.ndo_open = veth_open,
@@ -257,6 +272,9 @@ static const struct net_device_ops veth_netdev_ops = {
.ndo_get_stats64 = veth_get_stats64,
.ndo_set_rx_mode = veth_set_multicast_list,
.ndo_set_mac_address = eth_mac_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = veth_poll_controller,
+#endif
};
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
@@ -317,6 +335,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
struct veth_priv *priv;
char ifname[IFNAMSIZ];
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+ unsigned char name_assign_type;
struct ifinfomsg *ifmp;
struct net *net;
@@ -344,16 +363,20 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
tbp = tb;
}
- if (tbp[IFLA_IFNAME])
+ if (tbp[IFLA_IFNAME]) {
nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
- else
+ name_assign_type = NET_NAME_USER;
+ } else {
snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+ name_assign_type = NET_NAME_ENUM;
+ }
net = rtnl_link_get_net(src_net, tbp);
if (IS_ERR(net))
return PTR_ERR(net);
- peer = rtnl_create_link(net, ifname, &veth_link_ops, tbp);
+ peer = rtnl_create_link(net, ifname, name_assign_type,
+ &veth_link_ops, tbp);
if (IS_ERR(peer)) {
put_net(net);
return PTR_ERR(peer);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 7d9f84a91f37..59caa06f34a6 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/average.h>
+#include <net/busy_poll.h>
static int napi_weight = NAPI_POLL_WEIGHT;
module_param(napi_weight, int, 0444);
@@ -521,6 +522,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
skb_shinfo(skb)->gso_segs = 0;
}
+ skb_mark_napi_id(skb, &rq->napi);
+
netif_receive_skb(skb);
return;
@@ -725,15 +728,12 @@ static void refill_work(struct work_struct *work)
}
}
-static int virtnet_poll(struct napi_struct *napi, int budget)
+static int virtnet_receive(struct receive_queue *rq, int budget)
{
- struct receive_queue *rq =
- container_of(napi, struct receive_queue, napi);
struct virtnet_info *vi = rq->vq->vdev->priv;
+ unsigned int len, received = 0;
void *buf;
- unsigned int r, len, received = 0;
-again:
while (received < budget &&
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
receive_buf(rq, buf, len);
@@ -745,6 +745,18 @@ again:
schedule_delayed_work(&vi->refill, 0);
}
+ return received;
+}
+
+static int virtnet_poll(struct napi_struct *napi, int budget)
+{
+ struct receive_queue *rq =
+ container_of(napi, struct receive_queue, napi);
+ unsigned int r, received = 0;
+
+again:
+ received += virtnet_receive(rq, budget - received);
+
/* Out of packets? */
if (received < budget) {
r = virtqueue_enable_cb_prepare(rq->vq);
@@ -760,6 +772,43 @@ again:
return received;
}
+#ifdef CONFIG_NET_RX_BUSY_POLL
+/* must be called with local_bh_disable()d */
+static int virtnet_busy_poll(struct napi_struct *napi)
+{
+ struct receive_queue *rq =
+ container_of(napi, struct receive_queue, napi);
+ struct virtnet_info *vi = rq->vq->vdev->priv;
+ int r, received = 0, budget = 4;
+
+ if (!(vi->status & VIRTIO_NET_S_LINK_UP))
+ return LL_FLUSH_FAILED;
+
+ if (!napi_schedule_prep(napi))
+ return LL_FLUSH_BUSY;
+
+ virtqueue_disable_cb(rq->vq);
+
+again:
+ received += virtnet_receive(rq, budget);
+
+ r = virtqueue_enable_cb_prepare(rq->vq);
+ clear_bit(NAPI_STATE_SCHED, &napi->state);
+ if (unlikely(virtqueue_poll(rq->vq, r)) &&
+ napi_schedule_prep(napi)) {
+ virtqueue_disable_cb(rq->vq);
+ if (received < budget) {
+ budget -= received;
+ goto again;
+ } else {
+ __napi_schedule(napi);
+ }
+ }
+
+ return received;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
@@ -1347,6 +1396,9 @@ static const struct net_device_ops virtnet_netdev = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll,
#endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ .ndo_busy_poll = virtnet_busy_poll,
+#endif
};
static void virtnet_config_changed_work(struct work_struct *work)
@@ -1552,6 +1604,7 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
vi->rq[i].pages = NULL;
netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
napi_weight);
+ napi_hash_add(&vi->rq[i].napi);
sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
@@ -1853,11 +1906,13 @@ static int virtnet_freeze(struct virtio_device *vdev)
netif_device_detach(vi->dev);
cancel_delayed_work_sync(&vi->refill);
- if (netif_running(vi->dev))
+ if (netif_running(vi->dev)) {
for (i = 0; i < vi->max_queue_pairs; i++) {
napi_disable(&vi->rq[i].napi);
+ napi_hash_del(&vi->rq[i].napi);
netif_napi_del(&vi->rq[i].napi);
}
+ }
remove_vq_common(vi);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index b76f7dcde0db..d6e90c72c257 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -36,7 +36,7 @@ char vmxnet3_driver_name[] = "vmxnet3";
* PCI Device ID Table
* Last entry must be all 0s
*/
-static DEFINE_PCI_DEVICE_TABLE(vmxnet3_pciid_table) = {
+static const struct pci_device_id vmxnet3_pciid_table[] = {
{PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)},
{0}
};
@@ -766,7 +766,7 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
gdesc->dword[3] = 0;
netdev_dbg(adapter->netdev,
- "txd[%u]: 0x%llu %u %u\n",
+ "txd[%u]: 0x%llx %u %u\n",
tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 9f79192c9aa0..1fb7b37d1402 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -33,6 +33,7 @@
#include <net/ip_tunnels.h>
#include <net/icmp.h>
#include <net/udp.h>
+#include <net/udp_tunnel.h>
#include <net/rtnetlink.h>
#include <net/route.h>
#include <net/dsfield.h>
@@ -933,7 +934,8 @@ out:
/* Dump forwarding table */
static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
- struct net_device *dev, int idx)
+ struct net_device *dev,
+ struct net_device *filter_dev, int idx)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
unsigned int h;
@@ -1570,25 +1572,6 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
return false;
}
-/* Compute source port for outgoing packet
- * first choice to use L4 flow hash since it will spread
- * better and maybe available from hardware
- * secondary choice is to use jhash on the Ethernet header
- */
-__be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
-{
- unsigned int range = (port_max - port_min) + 1;
- u32 hash;
-
- hash = skb_get_hash(skb);
- if (!hash)
- hash = jhash(skb->data, 2 * ETH_ALEN,
- (__force u32) skb->protocol);
-
- return htons((((u64) hash * range) >> 32) + port_min);
-}
-EXPORT_SYMBOL_GPL(vxlan_src_port);
-
static inline struct sk_buff *vxlan_handle_offloads(struct sk_buff *skb,
bool udp_csum)
{
@@ -1807,7 +1790,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
if (tos == 1)
tos = ip_tunnel_get_dsfield(old_iph, skb);
- src_port = vxlan_src_port(vxlan->port_min, vxlan->port_max, skb);
+ src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->port_min,
+ vxlan->port_max, true);
if (dst->sa.sa_family == AF_INET) {
memset(&fl4, 0, sizeof(fl4));
@@ -2235,7 +2219,6 @@ static void vxlan_setup(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
unsigned int h;
- int low, high;
eth_hw_addr_random(dev);
ether_setup(dev);
@@ -2272,9 +2255,6 @@ static void vxlan_setup(struct net_device *dev)
vxlan->age_timer.function = vxlan_cleanup;
vxlan->age_timer.data = (unsigned long) vxlan;
- inet_get_local_port_range(dev_net(dev), &low, &high);
- vxlan->port_min = low;
- vxlan->port_max = high;
vxlan->dst_port = htons(vxlan_port);
vxlan->dev = dev;
@@ -2360,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work)
kfree_rcu(vs, rcu);
}
-#if IS_ENABLED(CONFIG_IPV6)
-/* Create UDP socket for encapsulation receive. AF_INET6 socket
- * could be used for both IPv4 and IPv6 communications, but
- * users may set bindv6only=1.
- */
-static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
+static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
+ __be16 port, u32 flags)
{
- struct sock *sk;
struct socket *sock;
- struct sockaddr_in6 vxlan_addr = {
- .sin6_family = AF_INET6,
- .sin6_port = port,
- };
- int rc, val = 1;
-
- rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
- if (rc < 0) {
- pr_debug("UDPv6 socket create failed\n");
- return ERR_PTR(rc);
- }
-
- /* Put in proper namespace */
- sk = sock->sk;
- sk_change_net(sk, net);
-
- kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
- (char *)&val, sizeof(val));
- rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr,
- sizeof(struct sockaddr_in6));
- if (rc < 0) {
- pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n",
- &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc);
- sk_release_kernel(sk);
- return ERR_PTR(rc);
- }
- /* At this point, IPv6 module should have been loaded in
- * sock_create_kern().
- */
- BUG_ON(!ipv6_stub);
-
- /* Disable multicast loopback */
- inet_sk(sk)->mc_loop = 0;
-
- if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX)
- udp_set_no_check6_tx(sk, true);
-
- if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX)
- udp_set_no_check6_rx(sk, true);
-
- return sock;
-}
-
-#else
-
-static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags)
-{
- return ERR_PTR(-EPFNOSUPPORT);
-}
-#endif
+ struct udp_port_cfg udp_conf;
+ int err;
-static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags)
-{
- struct sock *sk;
- struct socket *sock;
- struct sockaddr_in vxlan_addr = {
- .sin_family = AF_INET,
- .sin_addr.s_addr = htonl(INADDR_ANY),
- .sin_port = port,
- };
- int rc;
+ memset(&udp_conf, 0, sizeof(udp_conf));
- /* Create UDP socket for encapsulation receive. */
- rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
- if (rc < 0) {
- pr_debug("UDP socket create failed\n");
- return ERR_PTR(rc);
+ if (ipv6) {
+ udp_conf.family = AF_INET6;
+ udp_conf.use_udp6_tx_checksums =
+ !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
+ udp_conf.use_udp6_rx_checksums =
+ !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
+ } else {
+ udp_conf.family = AF_INET;
+ udp_conf.local_ip.s_addr = INADDR_ANY;
+ udp_conf.use_udp_checksums =
+ !!(flags & VXLAN_F_UDP_CSUM);
}
- /* Put in proper namespace */
- sk = sock->sk;
- sk_change_net(sk, net);
+ udp_conf.local_udp_port = port;
- rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr,
- sizeof(vxlan_addr));
- if (rc < 0) {
- pr_debug("bind for UDP socket %pI4:%u (%d)\n",
- &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
- sk_release_kernel(sk);
- return ERR_PTR(rc);
- }
+ /* Open UDP socket */
+ err = udp_sock_create(net, &udp_conf, &sock);
+ if (err < 0)
+ return ERR_PTR(err);
/* Disable multicast loopback */
- inet_sk(sk)->mc_loop = 0;
-
- if (!(flags & VXLAN_F_UDP_CSUM))
- sock->sk->sk_no_check_tx = 1;
+ inet_sk(sock->sk)->mc_loop = 0;
return sock;
}
@@ -2481,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
INIT_WORK(&vs->del_work, vxlan_del_work);
- if (ipv6)
- sock = create_v6_sock(net, port, flags);
- else
- sock = create_v4_sock(net, port, flags);
+ sock = vxlan_create_sock(net, ipv6, port, flags);
if (IS_ERR(sock)) {
kfree(vs);
return ERR_CAST(sock);
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 19f7cb2cdef3..43c9960dce1c 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -255,7 +255,6 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL;
return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);
- break;
default:
return -EOPNOTSUPP;
@@ -327,8 +326,8 @@ static int dlci_add(struct dlci_add *dlci)
goto err1;
/* create device name */
- master = alloc_netdev( sizeof(struct dlci_local), "dlci%d",
- dlci_setup);
+ master = alloc_netdev(sizeof(struct dlci_local), "dlci%d",
+ NET_NAME_UNKNOWN, dlci_setup);
if (!master) {
err = -ENOMEM;
goto err1;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 288610df205c..08223569cebd 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -2039,7 +2039,7 @@ static int __init dscc4_setup(char *str)
__setup("dscc4.setup=", dscc4_setup);
#endif
-static DEFINE_PCI_DEVICE_TABLE(dscc4_pci_tbl) = {
+static const struct pci_device_id dscc4_pci_tbl[] = {
{ PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4,
PCI_ANY_ID, PCI_ANY_ID, },
{ 0,}
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 1f041271f7fe..44541dbc5c28 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -531,7 +531,7 @@ do { \
/*
* PCI ID lookup table
*/
-static DEFINE_PCI_DEVICE_TABLE(fst_pci_dev_id) = {
+static const struct pci_device_id fst_pci_dev_id[] = {
{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, FST_TYPE_T2P},
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 9c33ca918e19..51f6cee8aab2 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -256,7 +256,8 @@ static void hdlc_setup(struct net_device *dev)
struct net_device *alloc_hdlcdev(void *priv)
{
struct net_device *dev;
- dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", hdlc_setup);
+ dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d",
+ NET_NAME_UNKNOWN, hdlc_setup);
if (dev)
dev_to_hdlc(dev)->priv = priv;
return dev;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7c6cb4f31798..e5c7e6165a4b 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -90,7 +90,7 @@
#define LMI_ANSI_LENGTH 14
-typedef struct {
+struct fr_hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned ea1: 1;
unsigned cr: 1;
@@ -112,14 +112,14 @@ typedef struct {
unsigned de: 1;
unsigned ea2: 1;
#endif
-}__packed fr_hdr;
+} __packed;
-typedef struct pvc_device_struct {
+struct pvc_device {
struct net_device *frad;
struct net_device *main;
struct net_device *ether; /* bridged Ethernet interface */
- struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
+ struct pvc_device *next; /* Sorted in ascending DLCI order */
int dlci;
int open_count;
@@ -132,11 +132,11 @@ typedef struct pvc_device_struct {
unsigned int becn: 1;
unsigned int bandwidth; /* Cisco LMI reporting only */
}state;
-}pvc_device;
+};
struct frad_state {
fr_proto settings;
- pvc_device *first_pvc;
+ struct pvc_device *first_pvc;
int dce_pvc_count;
struct timer_list timer;
@@ -174,9 +174,9 @@ static inline struct frad_state* state(hdlc_device *hdlc)
}
-static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
+static inline struct pvc_device *find_pvc(hdlc_device *hdlc, u16 dlci)
{
- pvc_device *pvc = state(hdlc)->first_pvc;
+ struct pvc_device *pvc = state(hdlc)->first_pvc;
while (pvc) {
if (pvc->dlci == dlci)
@@ -190,10 +190,10 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
}
-static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
+static struct pvc_device *add_pvc(struct net_device *dev, u16 dlci)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
+ struct pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
while (*pvc_p) {
if ((*pvc_p)->dlci == dlci)
@@ -203,7 +203,7 @@ static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
pvc_p = &(*pvc_p)->next;
}
- pvc = kzalloc(sizeof(pvc_device), GFP_ATOMIC);
+ pvc = kzalloc(sizeof(*pvc), GFP_ATOMIC);
#ifdef DEBUG_PVC
printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
#endif
@@ -218,13 +218,13 @@ static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
}
-static inline int pvc_is_used(pvc_device *pvc)
+static inline int pvc_is_used(struct pvc_device *pvc)
{
return pvc->main || pvc->ether;
}
-static inline void pvc_carrier(int on, pvc_device *pvc)
+static inline void pvc_carrier(int on, struct pvc_device *pvc)
{
if (on) {
if (pvc->main)
@@ -246,11 +246,11 @@ static inline void pvc_carrier(int on, pvc_device *pvc)
static inline void delete_unused_pvcs(hdlc_device *hdlc)
{
- pvc_device **pvc_p = &state(hdlc)->first_pvc;
+ struct pvc_device **pvc_p = &state(hdlc)->first_pvc;
while (*pvc_p) {
if (!pvc_is_used(*pvc_p)) {
- pvc_device *pvc = *pvc_p;
+ struct pvc_device *pvc = *pvc_p;
#ifdef DEBUG_PVC
printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
#endif
@@ -263,7 +263,8 @@ static inline void delete_unused_pvcs(hdlc_device *hdlc)
}
-static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
+static inline struct net_device **get_dev_p(struct pvc_device *pvc,
+ int type)
{
if (type == ARPHRD_ETHER)
return &pvc->ether;
@@ -342,7 +343,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
static int pvc_open(struct net_device *dev)
{
- pvc_device *pvc = dev->ml_priv;
+ struct pvc_device *pvc = dev->ml_priv;
if ((pvc->frad->flags & IFF_UP) == 0)
return -EIO; /* Frad must be UP in order to activate PVC */
@@ -362,7 +363,7 @@ static int pvc_open(struct net_device *dev)
static int pvc_close(struct net_device *dev)
{
- pvc_device *pvc = dev->ml_priv;
+ struct pvc_device *pvc = dev->ml_priv;
if (--pvc->open_count == 0) {
hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
@@ -381,7 +382,7 @@ static int pvc_close(struct net_device *dev)
static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- pvc_device *pvc = dev->ml_priv;
+ struct pvc_device *pvc = dev->ml_priv;
fr_proto_pvc_info info;
if (ifr->ifr_settings.type == IF_GET_PROTO) {
@@ -409,7 +410,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
{
- pvc_device *pvc = dev->ml_priv;
+ struct pvc_device *pvc = dev->ml_priv;
if (pvc->state.active) {
if (dev->type == ARPHRD_ETHER) {
@@ -444,7 +445,7 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static inline void fr_log_dlci_active(pvc_device *pvc)
+static inline void fr_log_dlci_active(struct pvc_device *pvc)
{
netdev_info(pvc->frad, "DLCI %d [%s%s%s]%s %s\n",
pvc->dlci,
@@ -469,7 +470,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
struct sk_buff *skb;
- pvc_device *pvc = state(hdlc)->first_pvc;
+ struct pvc_device *pvc = state(hdlc)->first_pvc;
int lmi = state(hdlc)->settings.lmi;
int dce = state(hdlc)->settings.dce;
int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
@@ -566,7 +567,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
static void fr_set_link_state(int reliable, struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- pvc_device *pvc = state(hdlc)->first_pvc;
+ struct pvc_device *pvc = state(hdlc)->first_pvc;
state(hdlc)->reliable = reliable;
if (reliable) {
@@ -652,7 +653,7 @@ static void fr_timer(unsigned long arg)
static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- pvc_device *pvc;
+ struct pvc_device *pvc;
u8 rxseq, txseq;
int lmi = state(hdlc)->settings.lmi;
int dce = state(hdlc)->settings.dce;
@@ -869,10 +870,10 @@ static int fr_rx(struct sk_buff *skb)
{
struct net_device *frad = skb->dev;
hdlc_device *hdlc = dev_to_hdlc(frad);
- fr_hdr *fh = (fr_hdr*)skb->data;
+ struct fr_hdr *fh = (struct fr_hdr *)skb->data;
u8 *data = skb->data;
u16 dlci;
- pvc_device *pvc;
+ struct pvc_device *pvc;
struct net_device *dev = NULL;
if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI)
@@ -1028,7 +1029,7 @@ static void fr_stop(struct net_device *dev)
static void fr_close(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- pvc_device *pvc = state(hdlc)->first_pvc;
+ struct pvc_device *pvc = state(hdlc)->first_pvc;
while (pvc) { /* Shutdown all PVCs for this FRAD */
if (pvc->main)
@@ -1060,7 +1061,7 @@ static const struct net_device_ops pvc_ops = {
static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
{
hdlc_device *hdlc = dev_to_hdlc(frad);
- pvc_device *pvc;
+ struct pvc_device *pvc;
struct net_device *dev;
int used;
@@ -1075,10 +1076,11 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
used = pvc_is_used(pvc);
if (type == ARPHRD_ETHER) {
- dev = alloc_netdev(0, "pvceth%d", ether_setup);
+ dev = alloc_netdev(0, "pvceth%d", NET_NAME_UNKNOWN,
+ ether_setup);
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
} else
- dev = alloc_netdev(0, "pvc%d", pvc_setup);
+ dev = alloc_netdev(0, "pvc%d", NET_NAME_UNKNOWN, pvc_setup);
if (!dev) {
netdev_warn(frad, "Memory squeeze on fr_pvc()\n");
@@ -1116,7 +1118,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
{
- pvc_device *pvc;
+ struct pvc_device *pvc;
struct net_device *dev;
if ((pvc = find_pvc(hdlc, dlci)) == NULL)
@@ -1144,13 +1146,13 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
static void fr_destroy(struct net_device *frad)
{
hdlc_device *hdlc = dev_to_hdlc(frad);
- pvc_device *pvc = state(hdlc)->first_pvc;
+ struct pvc_device *pvc = state(hdlc)->first_pvc;
state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
state(hdlc)->dce_pvc_count = 0;
state(hdlc)->dce_changed = 1;
while (pvc) {
- pvc_device *next = pvc->next;
+ struct pvc_device *next = pvc->next;
/* destructors will free_netdev() main and ether */
if (pvc->main)
unregister_netdevice(pvc->main);
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index a33a46fa88dd..2f5eda8a7227 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -325,8 +325,8 @@ static int lapbeth_new_device(struct net_device *dev)
ASSERT_RTNL();
- ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d",
- lapbeth_setup);
+ ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
+ lapbeth_setup);
if (!ndev)
goto out;
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index b2fe9bb89633..bea0f313a7a8 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -76,7 +76,7 @@
static int LMC_PKT_BUF_SZ = 1542;
-static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = {
+static const struct pci_device_id lmc_pci_tbl[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
PCI_VENDOR_ID_LMC, PCI_ANY_ID },
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index 5b72f7f8c516..db363856e0b5 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -477,7 +477,7 @@ static int pc300_pci_init_one(struct pci_dev *pdev,
-static DEFINE_PCI_DEVICE_TABLE(pc300_pci_tbl) = {
+static const struct pci_device_id pc300_pci_tbl[] = {
{ PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID,
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index fe4e3ece3c42..e8455621390e 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -414,7 +414,7 @@ static int pci200_pci_init_one(struct pci_dev *pdev,
-static DEFINE_PCI_DEVICE_TABLE(pci200_pci_tbl) = {
+static const struct pci_device_id pci200_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
{ 0, }
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 1b89ecf0959e..758c4ba1e97c 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -227,7 +227,8 @@ int __init sbni_probe(int unit)
struct net_device *dev;
int err;
- dev = alloc_netdev(sizeof(struct net_local), "sbni", sbni_devsetup);
+ dev = alloc_netdev(sizeof(struct net_local), "sbni",
+ NET_NAME_UNKNOWN, sbni_devsetup);
if (!dev)
return -ENOMEM;
@@ -1477,8 +1478,8 @@ int __init init_module( void )
int err;
while( num < SBNI_MAX_NUM_CARDS ) {
- dev = alloc_netdev(sizeof(struct net_local),
- "sbni%d", sbni_devsetup);
+ dev = alloc_netdev(sizeof(struct net_local), "sbni%d",
+ NET_NAME_UNKNOWN, sbni_devsetup);
if( !dev)
break;
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index cdd45fb8a1f6..421ac5f85699 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -1631,7 +1631,8 @@ static int __init init_sdla(void)
printk("%s.\n", version);
- sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);
+ sdla = alloc_netdev(sizeof(struct frad_local), "sdla0",
+ NET_NAME_UNKNOWN, setup_sdla);
if (!sdla)
return -ENOMEM;
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index f76aa9081585..e73f13857846 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -54,24 +54,24 @@ static const char* version = "wanXL serial card driver version: 0.48";
#define MBX2_MEMSZ_MASK 0xFFFF0000 /* PUTS Memory Size Register mask */
-typedef struct {
+struct port {
struct net_device *dev;
- struct card_t *card;
+ struct card *card;
spinlock_t lock; /* for wanxl_xmit */
int node; /* physical port #0 - 3 */
unsigned int clock_type;
int tx_in, tx_out;
struct sk_buff *tx_skbs[TX_BUFFERS];
-}port_t;
+};
-typedef struct {
+struct card_status {
desc_t rx_descs[RX_QUEUE_LENGTH];
port_status_t port_status[4];
-}card_status_t;
+};
-typedef struct card_t {
+struct card {
int n_ports; /* 1, 2 or 4 ports */
u8 irq;
@@ -79,20 +79,20 @@ typedef struct card_t {
struct pci_dev *pdev; /* for pci_name(pdev) */
int rx_in;
struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
- card_status_t *status; /* shared between host and card */
+ struct card_status *status; /* shared between host and card */
dma_addr_t status_address;
- port_t ports[0]; /* 1 - 4 port_t structures follow */
-}card_t;
+ struct port ports[0]; /* 1 - 4 port structures follow */
+};
-static inline port_t* dev_to_port(struct net_device *dev)
+static inline struct port *dev_to_port(struct net_device *dev)
{
- return (port_t *)dev_to_hdlc(dev)->priv;
+ return (struct port *)dev_to_hdlc(dev)->priv;
}
-static inline port_status_t* get_status(port_t *port)
+static inline port_status_t *get_status(struct port *port)
{
return &port->card->status->port_status[port->node];
}
@@ -115,7 +115,7 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr,
/* Cable and/or personality module change interrupt service */
-static inline void wanxl_cable_intr(port_t *port)
+static inline void wanxl_cable_intr(struct port *port)
{
u32 value = get_status(port)->cable;
int valid = 1;
@@ -160,7 +160,7 @@ static inline void wanxl_cable_intr(port_t *port)
/* Transmit complete interrupt service */
-static inline void wanxl_tx_intr(port_t *port)
+static inline void wanxl_tx_intr(struct port *port)
{
struct net_device *dev = port->dev;
while (1) {
@@ -193,7 +193,7 @@ static inline void wanxl_tx_intr(port_t *port)
/* Receive complete interrupt service */
-static inline void wanxl_rx_intr(card_t *card)
+static inline void wanxl_rx_intr(struct card *card)
{
desc_t *desc;
while (desc = &card->status->rx_descs[card->rx_in],
@@ -203,7 +203,7 @@ static inline void wanxl_rx_intr(card_t *card)
pci_name(card->pdev));
else {
struct sk_buff *skb = card->rx_skbs[card->rx_in];
- port_t *port = &card->ports[desc->stat &
+ struct port *port = &card->ports[desc->stat &
PACKET_PORT_MASK];
struct net_device *dev = port->dev;
@@ -245,7 +245,7 @@ static inline void wanxl_rx_intr(card_t *card)
static irqreturn_t wanxl_intr(int irq, void* dev_id)
{
- card_t *card = dev_id;
+ struct card *card = dev_id;
int i;
u32 stat;
int handled = 0;
@@ -272,7 +272,7 @@ static irqreturn_t wanxl_intr(int irq, void* dev_id)
static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
{
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
desc_t *desc;
spin_lock(&port->lock);
@@ -319,7 +319,7 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev)
static int wanxl_attach(struct net_device *dev, unsigned short encoding,
unsigned short parity)
{
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
if (encoding != ENCODING_NRZ &&
encoding != ENCODING_NRZI)
@@ -343,7 +343,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
const size_t size = sizeof(sync_serial_settings);
sync_serial_settings line;
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);
@@ -393,7 +393,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int wanxl_open(struct net_device *dev)
{
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
u8 __iomem *dbr = port->card->plx + PLX_DOORBELL_TO_CARD;
unsigned long timeout;
int i;
@@ -429,7 +429,7 @@ static int wanxl_open(struct net_device *dev)
static int wanxl_close(struct net_device *dev)
{
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
unsigned long timeout;
int i;
@@ -467,7 +467,7 @@ static int wanxl_close(struct net_device *dev)
static struct net_device_stats *wanxl_get_stats(struct net_device *dev)
{
- port_t *port = dev_to_port(dev);
+ struct port *port = dev_to_port(dev);
dev->stats.rx_over_errors = get_status(port)->rx_overruns;
dev->stats.rx_frame_errors = get_status(port)->rx_frame_errors;
@@ -478,7 +478,7 @@ static struct net_device_stats *wanxl_get_stats(struct net_device *dev)
-static int wanxl_puts_command(card_t *card, u32 cmd)
+static int wanxl_puts_command(struct card *card, u32 cmd)
{
unsigned long timeout = jiffies + 5 * HZ;
@@ -495,7 +495,7 @@ static int wanxl_puts_command(card_t *card, u32 cmd)
-static void wanxl_reset(card_t *card)
+static void wanxl_reset(struct card *card)
{
u32 old_value = readl(card->plx + PLX_CONTROL) & ~PLX_CTL_RESET;
@@ -511,7 +511,7 @@ static void wanxl_reset(card_t *card)
static void wanxl_pci_remove_one(struct pci_dev *pdev)
{
- card_t *card = pci_get_drvdata(pdev);
+ struct card *card = pci_get_drvdata(pdev);
int i;
for (i = 0; i < card->n_ports; i++) {
@@ -537,7 +537,7 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
iounmap(card->plx);
if (card->status)
- pci_free_consistent(pdev, sizeof(card_status_t),
+ pci_free_consistent(pdev, sizeof(struct card_status),
card->status, card->status_address);
pci_release_regions(pdev);
@@ -560,7 +560,7 @@ static const struct net_device_ops wanxl_ops = {
static int wanxl_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- card_t *card;
+ struct card *card;
u32 ramsize, stat;
unsigned long timeout;
u32 plx_phy; /* PLX PCI base address */
@@ -601,7 +601,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
default: ports = 4;
}
- alloc_size = sizeof(card_t) + ports * sizeof(port_t);
+ alloc_size = sizeof(struct card) + ports * sizeof(struct port);
card = kzalloc(alloc_size, GFP_KERNEL);
if (card == NULL) {
pci_release_regions(pdev);
@@ -612,7 +612,8 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, card);
card->pdev = pdev;
- card->status = pci_alloc_consistent(pdev, sizeof(card_status_t),
+ card->status = pci_alloc_consistent(pdev,
+ sizeof(struct card_status),
&card->status_address);
if (card->status == NULL) {
wanxl_pci_remove_one(pdev);
@@ -766,7 +767,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
for (i = 0; i < ports; i++) {
hdlc_device *hdlc;
- port_t *port = &card->ports[i];
+ struct port *port = &card->ports[i];
struct net_device *dev = alloc_hdlcdev(port);
if (!dev) {
pr_err("%s: unable to allocate memory\n",
@@ -807,7 +808,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev,
return 0;
}
-static DEFINE_PCI_DEVICE_TABLE(wanxl_pci_tbl) = {
+static const struct pci_device_id wanxl_pci_tbl[] = {
{ PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID,
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index fa9fdfa128c1..5c47b011a9d7 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -81,8 +81,8 @@ static struct x25_asy *x25_asy_alloc(void)
char name[IFNAMSIZ];
sprintf(name, "x25asy%d", i);
- dev = alloc_netdev(sizeof(struct x25_asy),
- name, x25_asy_setup);
+ dev = alloc_netdev(sizeof(struct x25_asy), name,
+ NET_NAME_UNKNOWN, x25_asy_setup);
if (!dev)
return NULL;
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index cd15a93d9084..e7f5910a6519 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -472,7 +472,7 @@ int i2400mu_probe(struct usb_interface *iface,
/* Allocate instance [calls i2400m_netdev_setup() on it]. */
result = -ENOMEM;
- net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
+ net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d", NET_NAME_UNKNOWN,
i2400mu_netdev_setup);
if (net_dev == NULL) {
dev_err(dev, "no memory for network device instance\n");
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index b2137e8f7ca6..16604bdf5197 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -189,6 +189,7 @@ config USB_NET_RNDIS_WLAN
tristate "Wireless RNDIS USB support"
depends on USB
depends on CFG80211
+ select USB_NET_DRIVERS
select USB_USBNET
select USB_NET_CDCETHER
select USB_NET_RNDIS_HOST
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index f35f93c31b09..17fcaabb2687 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -41,7 +41,7 @@ static unsigned int rx_ring_size __read_mostly = 16;
module_param(tx_ring_size, uint, 0);
module_param(rx_ring_size, uint, 0);
-static DEFINE_PCI_DEVICE_TABLE(adm8211_pci_id_table) = {
+static const struct pci_device_id adm8211_pci_id_table[] = {
/* ADMtek ADM8211 */
{ PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */
{ PCI_DEVICE(0x1200, 0x8201) }, /* ? */
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 64747d457bb3..e71a2ce7a448 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -57,7 +57,7 @@
#define DRV_NAME "airo"
#ifdef CONFIG_PCI
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
{ 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2685,7 +2685,8 @@ static struct net_device *init_wifidev(struct airo_info *ai,
struct net_device *ethdev)
{
int err;
- struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
+ struct net_device *dev = alloc_netdev(0, "wifi%d", NET_NAME_UNKNOWN,
+ wifi_setup);
if (!dev)
return NULL;
dev->ml_priv = ethdev->ml_priv;
@@ -2785,7 +2786,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
CapabilityRid cap_rid;
/* Create the network device object. */
- dev = alloc_netdev(sizeof(*ai), "", ether_setup);
+ dev = alloc_netdev(sizeof(*ai), "", NET_NAME_UNKNOWN, ether_setup);
if (!dev) {
airo_print_err("", "Couldn't alloc_etherdev");
return NULL;
@@ -7817,7 +7818,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
case AIRORRID: ridcode = comp->ridnum; break;
default:
return -EINVAL;
- break;
}
if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 7e9ede6c5798..d9ed22b4cc6b 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -56,18 +56,18 @@ static void airo_release(struct pcmcia_device *link);
static void airo_detach(struct pcmcia_device *p_dev);
-typedef struct local_info_t {
+struct local_info {
struct net_device *eth_dev;
-} local_info_t;
+};
static int airo_probe(struct pcmcia_device *p_dev)
{
- local_info_t *local;
+ struct local_info *local;
dev_dbg(&p_dev->dev, "airo_attach()\n");
/* Allocate space for private device-specific data */
- local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(*local), GFP_KERNEL);
if (!local)
return -ENOMEM;
@@ -82,10 +82,11 @@ static void airo_detach(struct pcmcia_device *link)
airo_release(link);
- if (((local_info_t *)link->priv)->eth_dev) {
- stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0);
+ if (((struct local_info *)link->priv)->eth_dev) {
+ stop_airo_card(((struct local_info *)link->priv)->eth_dev,
+ 0);
}
- ((local_info_t *)link->priv)->eth_dev = NULL;
+ ((struct local_info *)link->priv)->eth_dev = NULL;
kfree(link->priv);
} /* airo_detach */
@@ -101,7 +102,7 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
static int airo_config(struct pcmcia_device *link)
{
- local_info_t *dev;
+ struct local_info *dev;
int ret;
dev = link->priv;
@@ -121,10 +122,10 @@ static int airo_config(struct pcmcia_device *link)
ret = pcmcia_enable_device(link);
if (ret)
goto failed;
- ((local_info_t *)link->priv)->eth_dev =
+ ((struct local_info *)link->priv)->eth_dev =
init_airo_card(link->irq,
link->resource[0]->start, 1, &link->dev);
- if (!((local_info_t *)link->priv)->eth_dev)
+ if (!((struct local_info *)link->priv)->eth_dev)
goto failed;
return 0;
@@ -142,7 +143,7 @@ static void airo_release(struct pcmcia_device *link)
static int airo_suspend(struct pcmcia_device *link)
{
- local_info_t *local = link->priv;
+ struct local_info *local = link->priv;
netif_device_detach(local->eth_dev);
@@ -151,7 +152,7 @@ static int airo_suspend(struct pcmcia_device *link)
static int airo_resume(struct pcmcia_device *link)
{
- local_info_t *local = link->priv;
+ struct local_info *local = link->priv;
if (link->open) {
reset_airo_card(local->eth_dev);
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index d48776e4f343..334c2ece855a 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1955,8 +1955,9 @@ static void at76_dwork_hw_scan(struct work_struct *work)
static int at76_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
+ struct cfg80211_scan_request *req = &hw_req->req;
struct at76_priv *priv = hw->priv;
struct at76_req_scan scan;
u8 *ssid = NULL;
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index a889fd66fc63..fd9e5305e77f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -63,6 +63,7 @@ enum ath_op_flags {
ATH_OP_PRIM_STA_VIF,
ATH_OP_HW_RESET,
ATH_OP_SCANNING,
+ ATH_OP_MULTI_CHANNEL,
};
enum ath_bus_type {
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index d185dc0cd12b..4333107ecf37 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
if (ret)
return ret;
- src_ring->hw_index =
- ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
- src_ring->hw_index &= nentries_mask;
+ read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+ if (read_index == 0xffffffff)
+ return -ENODEV;
+
+ read_index &= nentries_mask;
+ src_ring->hw_index = read_index;
ath10k_pci_sleep(ar);
}
read_index = src_ring->hw_index;
- if ((read_index == sw_index) || (read_index == 0xffffffff))
+ if (read_index == sw_index)
return -EIO;
sbase = src_ring->shadow_base;
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index e6c56c5bb0f6..93adb8c58969 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar)
INIT_LIST_HEAD(&ar->arvifs);
- if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+ if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name,
ar->target_version,
@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor);
+ ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
+ config_enabled(CONFIG_ATH10K_DEBUG),
+ config_enabled(CONFIG_ATH10K_DEBUGFS),
+ config_enabled(CONFIG_ATH10K_TRACING),
+ config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
+ }
__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
@@ -988,7 +994,9 @@ err_unregister_mac:
err_release_fw:
ath10k_core_free_firmware_files(ar);
err:
- device_release_driver(ar->dev);
+ /* TODO: It's probably a good idea to release device from the driver
+ * but calling device_release_driver() here will cause a deadlock.
+ */
return;
}
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 68ceef61933d..83a5fa91531d 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -290,6 +290,9 @@ struct ath10k_debug {
struct ath_dfs_pool_stats dfs_pool_stats;
u32 fw_dbglog_mask;
+
+ u8 htt_max_amsdu;
+ u8 htt_max_ampdu;
};
enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 1b7ff4ba122c..3030158c478e 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = {
.llseek = default_llseek,
};
+static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ char buf[64];
+ u8 amsdu = 3, ampdu = 64;
+ unsigned int len;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->debug.htt_max_amsdu)
+ amsdu = ar->debug.htt_max_amsdu;
+
+ if (ar->debug.htt_max_ampdu)
+ ampdu = ar->debug.htt_max_ampdu;
+
+ mutex_unlock(&ar->conf_mutex);
+
+ len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ int res;
+ char buf[64];
+ unsigned int amsdu, ampdu;
+
+ simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+
+ /* make sure that buf is null terminated */
+ buf[sizeof(buf) - 1] = 0;
+
+ res = sscanf(buf, "%u %u", &amsdu, &ampdu);
+
+ if (res != 2)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
+ if (res)
+ goto out;
+
+ res = count;
+ ar->debug.htt_max_amsdu = amsdu;
+ ar->debug.htt_max_ampdu = ampdu;
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return res;
+}
+
+static const struct file_operations fops_htt_max_amsdu_ampdu = {
+ .read = ath10k_read_htt_max_amsdu_ampdu,
+ .write = ath10k_write_htt_max_amsdu_ampdu,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static ssize_t ath10k_read_fw_dbglog(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar)
* warning from del_timer(). */
if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork);
+
+ ar->debug.htt_max_amsdu = 0;
+ ar->debug.htt_max_ampdu = 0;
}
static ssize_t ath10k_write_simulate_radar(struct file *file,
@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_htt_stats_mask);
+ debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
+ ar->debug.debugfs_phy, ar,
+ &fops_htt_max_amsdu_ampdu);
+
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog);
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index e493db4b4a41..5fdc40d3b378 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -546,7 +546,7 @@ static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
int ath10k_htc_wait_target(struct ath10k_htc *htc)
{
- int status = 0;
+ int i, status = 0;
struct ath10k_htc_svc_conn_req conn_req;
struct ath10k_htc_svc_conn_resp conn_resp;
struct ath10k_htc_msg *msg;
@@ -556,10 +556,26 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
status = wait_for_completion_timeout(&htc->ctl_resp,
ATH10K_HTC_WAIT_TIMEOUT_HZ);
- if (status <= 0) {
+ if (status == 0) {
+ /* Workaround: In some cases the PCI HIF doesn't
+ * receive interrupt for the control response message
+ * even if the buffer was completed. It is suspected
+ * iomap writes unmasking PCI CE irqs aren't propagated
+ * properly in KVM PCI-passthrough sometimes.
+ */
+ ath10k_warn("failed to receive control response completion, polling..\n");
+
+ for (i = 0; i < CE_COUNT; i++)
+ ath10k_hif_send_complete_check(htc->ar, i, 1);
+
+ status = wait_for_completion_timeout(&htc->ctl_resp,
+ ATH10K_HTC_WAIT_TIMEOUT_HZ);
+
if (status == 0)
status = -ETIMEDOUT;
+ }
+ if (status < 0) {
ath10k_err("ctl_resp never came in (%d)\n", status);
return status;
}
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 9a263462c793..6c93f3885ee5 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -240,16 +240,10 @@ struct htt_oob_sync_req {
__le16 rsvd0;
} __packed;
-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0
-
struct htt_aggr_conf {
u8 max_num_ampdu_subframes;
- union {
- /* dont use bitfields; undefined behaviour */
- u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
- u8 max_num_amsdu_subframes:5;
- } __packed;
+ /* amsdu_subframes is limited by 0x1F mask */
+ u8 max_num_amsdu_subframes;
} __packed;
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
+int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
+ u8 max_subfrms_ampdu,
+ u8 max_subfrms_amsdu);
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index eebc860c3655..80cdac15588a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -21,6 +21,7 @@
#include "txrx.h"
#include "debug.h"
#include "trace.h"
+#include "mac.h"
#include <linux/log2.h>
@@ -307,7 +308,8 @@ static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
u8 **fw_desc, int *fw_desc_len,
struct sk_buff **head_msdu,
- struct sk_buff **tail_msdu)
+ struct sk_buff **tail_msdu,
+ u32 *attention)
{
int msdu_len, msdu_chaining = 0;
struct sk_buff *msdu;
@@ -357,6 +359,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
break;
}
+ *attention |= __le32_to_cpu(rx_desc->attention.flags) &
+ (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+ RX_ATTENTION_FLAGS_DECRYPT_ERR |
+ RX_ATTENTION_FLAGS_FCS_ERR |
+ RX_ATTENTION_FLAGS_MGMT_TYPE);
/*
* Copy the FW rx descriptor for this MSDU from the rx
* indication message into the MSDU's netbuf. HL uses the
@@ -1215,13 +1222,15 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
struct sk_buff *msdu_head, *msdu_tail;
+ attention = 0;
msdu_head = NULL;
msdu_tail = NULL;
ret = ath10k_htt_rx_amsdu_pop(htt,
&fw_desc,
&fw_desc_len,
&msdu_head,
- &msdu_tail);
+ &msdu_tail,
+ &attention);
if (ret < 0) {
ath10k_warn("failed to pop amsdu from htt rx ring %d\n",
@@ -1233,7 +1242,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
rxd = container_of((void *)msdu_head->data,
struct htt_rx_desc,
msdu_payload);
- attention = __le32_to_cpu(rxd->attention.flags);
if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
status,
@@ -1286,6 +1294,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
u8 *fw_desc;
int fw_desc_len, hdrlen, paramlen;
int trim;
+ u32 attention = 0;
fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
fw_desc = (u8 *)frag->fw_msdu_rx_desc;
@@ -1295,7 +1304,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
spin_lock_bh(&htt->rx_ring.lock);
ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
- &msdu_head, &msdu_tail);
+ &msdu_head, &msdu_tail,
+ &attention);
spin_unlock_bh(&htt->rx_ring.lock);
ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
@@ -1312,10 +1322,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
hdr = (struct ieee80211_hdr *)msdu_head->data;
rxd = (void *)msdu_head->data - sizeof(*rxd);
- tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) &
- RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
- decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) &
- RX_ATTENTION_FLAGS_DECRYPT_ERR);
+ tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+ decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT);
@@ -1422,6 +1430,86 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
}
}
+static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
+{
+ struct htt_rx_addba *ev = &resp->rx_addba;
+ struct ath10k_peer *peer;
+ struct ath10k_vif *arvif;
+ u16 info0, tid, peer_id;
+
+ info0 = __le16_to_cpu(ev->info0);
+ tid = MS(info0, HTT_RX_BA_INFO0_TID);
+ peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+ ath10k_dbg(ATH10K_DBG_HTT,
+ "htt rx addba tid %hu peer_id %hu size %hhu\n",
+ tid, peer_id, ev->window_size);
+
+ spin_lock_bh(&ar->data_lock);
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer) {
+ ath10k_warn("received addba event for invalid peer_id: %hu\n",
+ peer_id);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+ }
+
+ arvif = ath10k_get_arvif(ar, peer->vdev_id);
+ if (!arvif) {
+ ath10k_warn("received addba event for invalid vdev_id: %u\n",
+ peer->vdev_id);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+ }
+
+ ath10k_dbg(ATH10K_DBG_HTT,
+ "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
+ peer->addr, tid, ev->window_size);
+
+ ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+ spin_unlock_bh(&ar->data_lock);
+}
+
+static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
+{
+ struct htt_rx_delba *ev = &resp->rx_delba;
+ struct ath10k_peer *peer;
+ struct ath10k_vif *arvif;
+ u16 info0, tid, peer_id;
+
+ info0 = __le16_to_cpu(ev->info0);
+ tid = MS(info0, HTT_RX_BA_INFO0_TID);
+ peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
+
+ ath10k_dbg(ATH10K_DBG_HTT,
+ "htt rx delba tid %hu peer_id %hu\n",
+ tid, peer_id);
+
+ spin_lock_bh(&ar->data_lock);
+ peer = ath10k_peer_find_by_id(ar, peer_id);
+ if (!peer) {
+ ath10k_warn("received addba event for invalid peer_id: %hu\n",
+ peer_id);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+ }
+
+ arvif = ath10k_get_arvif(ar, peer->vdev_id);
+ if (!arvif) {
+ ath10k_warn("received addba event for invalid vdev_id: %u\n",
+ peer->vdev_id);
+ spin_unlock_bh(&ar->data_lock);
+ return;
+ }
+
+ ath10k_dbg(ATH10K_DBG_HTT,
+ "htt rx stop rx ba session sta %pM tid %hu\n",
+ peer->addr, tid);
+
+ ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
+ spin_unlock_bh(&ar->data_lock);
+}
+
void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_htt *htt = &ar->htt;
@@ -1516,9 +1604,25 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
trace_ath10k_htt_stats(skb->data, skb->len);
break;
case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
+ /* Firmware can return tx frames if it's unable to fully
+ * process them and suspects host may be able to fix it. ath10k
+ * sends all tx frames as already inspected so this shouldn't
+ * happen unless fw has a bug.
+ */
+ ath10k_warn("received an unexpected htt tx inspect event\n");
+ break;
case HTT_T2H_MSG_TYPE_RX_ADDBA:
+ ath10k_htt_rx_addba(ar, resp);
+ break;
case HTT_T2H_MSG_TYPE_RX_DELBA:
- case HTT_T2H_MSG_TYPE_RX_FLUSH:
+ ath10k_htt_rx_delba(ar, resp);
+ break;
+ case HTT_T2H_MSG_TYPE_RX_FLUSH: {
+ /* Ignore this event because mac80211 takes care of Rx
+ * aggregation reordering.
+ */
+ break;
+ }
default:
ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
resp->hdr.msg_type);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7064354d1f4f..8b27bfcc1de3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
return 0;
}
+int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
+ u8 max_subfrms_ampdu,
+ u8 max_subfrms_amsdu)
+{
+ struct htt_aggr_conf *aggr_conf;
+ struct sk_buff *skb;
+ struct htt_cmd *cmd;
+ int len;
+ int ret;
+
+ /* Firmware defaults are: amsdu = 3 and ampdu = 64 */
+
+ if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
+ return -EINVAL;
+
+ if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
+ return -EINVAL;
+
+ len = sizeof(cmd->hdr);
+ len += sizeof(cmd->aggr_conf);
+
+ skb = ath10k_htc_alloc_skb(len);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, len);
+ cmd = (struct htt_cmd *)skb->data;
+ cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
+
+ aggr_conf = &cmd->aggr_conf;
+ aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
+ aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
+
+ ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
+ aggr_conf->max_num_amsdu_subframes,
+ aggr_conf->max_num_ampdu_subframes);
+
+ ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
+ if (ret) {
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ return 0;
+}
+
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{
struct device *dev = htt->ar->dev;
@@ -485,6 +531,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
+ /* Prevent firmware from sending up tx inspection requests. There's
+ * nothing ath10k can do with frames requested for inspection so force
+ * it to simply rely a regular tx completion with discard status.
+ */
+ flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
+
skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index a21080028c54..9d61bb157189 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1865,15 +1865,13 @@ static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar,
return 0;
}
-/*
- * Frames sent to the FW have to be in "Native Wifi" format.
- * Strip the QoS field from the 802.11 header.
+/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
+ * Control in the header.
*/
-static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
+static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
u8 *qos_ctl;
if (!ieee80211_is_data_qos(hdr->frame_control))
@@ -1883,6 +1881,16 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
memmove(skb->data + IEEE80211_QOS_CTL_LEN,
skb->data, (void *)qos_ctl - (void *)skb->data);
skb_pull(skb, IEEE80211_QOS_CTL_LEN);
+
+ /* Fw/Hw generates a corrupted QoS Control Field for QoS NullFunc
+ * frames. Powersave is handled by the fw/hw so QoS NyllFunc frames are
+ * used only for CQM purposes (e.g. hostapd station keepalive ping) so
+ * it is safe to downgrade to NullFunc.
+ */
+ if (ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
+ cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+ }
}
static void ath10k_tx_wep_key_work(struct work_struct *work)
@@ -1919,14 +1927,13 @@ unlock:
mutex_unlock(&arvif->ar->conf_mutex);
}
-static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
+static void ath10k_tx_h_update_wep_key(struct ieee80211_vif *vif,
+ struct ieee80211_key_conf *key,
+ struct sk_buff *skb)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_vif *vif = info->control.vif;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct ath10k *ar = arvif->ar;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_key_conf *key = info->control.hw_key;
if (!ieee80211_has_protected(hdr->frame_control))
return;
@@ -1948,11 +1955,11 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
ieee80211_queue_work(ar->hw, &arvif->wep_key_work);
}
-static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
+ struct ieee80211_vif *vif,
+ struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_vif *vif = info->control.vif;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
/* This is case only for P2P_GO */
@@ -2254,33 +2261,28 @@ static void ath10k_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
+ struct ath10k *ar = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_vif *vif = info->control.vif;
+ struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath10k *ar = hw->priv;
- u8 tid, vdev_id;
/* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
- /* we must calculate tid before we apply qos workaround
- * as we'd lose the qos control field */
- tid = ath10k_tx_h_get_tid(hdr);
- vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
+ ATH10K_SKB_CB(skb)->htt.is_offchan = false;
+ ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
+ ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
/* it makes no sense to process injected frames like that */
- if (info->control.vif &&
- info->control.vif->type != NL80211_IFTYPE_MONITOR) {
- ath10k_tx_h_qos_workaround(hw, control, skb);
- ath10k_tx_h_update_wep_key(skb);
- ath10k_tx_h_add_p2p_noa_ie(ar, skb);
- ath10k_tx_h_seq_no(skb);
+ if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
+ ath10k_tx_h_nwifi(hw, skb);
+ ath10k_tx_h_update_wep_key(vif, key, skb);
+ ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
+ ath10k_tx_h_seq_no(vif, skb);
}
- ATH10K_SKB_CB(skb)->vdev_id = vdev_id;
- ATH10K_SKB_CB(skb)->htt.is_offchan = false;
- ATH10K_SKB_CB(skb)->htt.tid = tid;
-
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
spin_lock_bh(&ar->data_lock);
ATH10K_SKB_CB(skb)->htt.is_offchan = true;
@@ -3137,10 +3139,11 @@ exit:
static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct cfg80211_scan_request *req = &hw_req->req;
struct wmi_start_scan_arg arg;
int ret = 0;
int i;
@@ -4330,6 +4333,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
return 0;
}
+static int ath10k_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum ieee80211_ampdu_mlme_action action,
+ struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+ u8 buf_size)
+{
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+ ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
+ arvif->vdev_id, sta->addr, tid, action);
+
+ switch (action) {
+ case IEEE80211_AMPDU_RX_START:
+ case IEEE80211_AMPDU_RX_STOP:
+ /* HTT AddBa/DelBa events trigger mac80211 Rx BA session
+ * creation/removal. Do we need to verify this?
+ */
+ return 0;
+ case IEEE80211_AMPDU_TX_START:
+ case IEEE80211_AMPDU_TX_STOP_CONT:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+ /* Firmware offloads Tx aggregation entirely so deny mac80211
+ * Tx aggregation requests.
+ */
+ return -EOPNOTSUPP;
+ }
+
+ return -EINVAL;
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_tx,
.start = ath10k_start,
@@ -4357,6 +4392,7 @@ static const struct ieee80211_ops ath10k_ops = {
.set_bitrate_mask = ath10k_set_bitrate_mask,
.sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf,
+ .ampdu_action = ath10k_ampdu_action,
#ifdef CONFIG_PM
.suspend = ath10k_suspend,
.resume = ath10k_resume,
@@ -4697,7 +4733,6 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP);
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
@@ -4767,6 +4802,8 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->iface_combinations = ath10k_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_if_comb);
+
+ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
}
ar->hw->netdev_features = NETIF_F_HW_CSUM;
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index ba1021997b8f..ef4f84376d7c 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -43,11 +43,11 @@ static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
return (struct ath10k_vif *)vif->drv_priv;
}
-static inline void ath10k_tx_h_seq_no(struct sk_buff *skb)
+static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
+ struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_vif *vif = info->control.vif;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index d0004d59c97e..3376963a4862 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
#define QCA988X_2_0_DEVICE_ID (0x003c)
-static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
+static const struct pci_device_id ath10k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
{0}
};
@@ -726,18 +726,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
unsigned int nbytes, max_nbytes;
unsigned int transfer_id;
unsigned int flags;
- int err;
+ int err, num_replenish = 0;
while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
&ce_data, &nbytes, &transfer_id,
&flags) == 0) {
- err = ath10k_pci_post_rx_pipe(pipe_info, 1);
- if (unlikely(err)) {
- /* FIXME: retry */
- ath10k_warn("failed to replenish CE rx ring %d: %d\n",
- pipe_info->pipe_num, err);
- }
-
+ num_replenish++;
skb = transfer_context;
max_nbytes = skb->len + skb_tailroom(skb);
dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
@@ -753,6 +747,13 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
skb_put(skb, nbytes);
cb->rx_completion(ar, skb, pipe_info->pipe_num);
}
+
+ err = ath10k_pci_post_rx_pipe(pipe_info, num_replenish);
+ if (unlikely(err)) {
+ /* FIXME: retry */
+ ath10k_warn("failed to replenish CE rx ring %d (%d bufs): %d\n",
+ pipe_info->pipe_num, num_replenish, err);
+ }
}
static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
@@ -1362,8 +1363,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
}
- init_completion(&xfer.done);
-
ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
if (ret)
goto err_resp;
@@ -1414,10 +1413,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
&nbytes, &transfer_id))
return;
- if (xfer->wait_for_resp)
- return;
-
- complete(&xfer->done);
+ xfer->tx_done = true;
}
static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
@@ -1438,7 +1434,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
}
xfer->resp_len = nbytes;
- complete(&xfer->done);
+ xfer->rx_done = true;
}
static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
@@ -1451,7 +1447,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe);
- if (completion_done(&xfer->done))
+ if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
return 0;
schedule();
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index dfdebb4157aa..940129209990 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -38,7 +38,8 @@
#define DIAG_TRANSFER_LIMIT 2048
struct bmi_xfer {
- struct completion done;
+ bool tx_done;
+ bool rx_done;
bool wait_for_resp;
u32 resp_len;
};
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 82669a77e553..f4fa22d1d591 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
return NULL;
}
-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
- int peer_id)
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
{
struct ath10k_peer *peer;
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index aee3e20058f8..a90e09f5c7f2 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
const u8 *addr);
+struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
const u8 *addr);
int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 4b7782a529ac..c2c87c916b5a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1432,7 +1432,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
continue;
}
- ath10k_tx_h_seq_no(bcn);
+ ath10k_tx_h_seq_no(arvif->vif, bcn);
ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_event_id id;
- u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
- len = skb->len;
-
trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) {
@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id;
- u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
- len = skb->len;
-
trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) {
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 74bd54d6aceb..85316bb3f8c6 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1285,6 +1285,7 @@ struct ath5k_hw {
#define ATH_STAT_STARTED 3 /* opened & irqs enabled */
unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ unsigned int fif_filter_flags; /* Current FIF_* filter flags */
struct ieee80211_channel *curchan; /* current h/w channel */
u16 nvifs;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 4b18434ba697..8ad2550bce7f 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1382,6 +1382,9 @@ ath5k_receive_frame(struct ath5k_hw *ah, struct sk_buff *skb,
rxs->flag = 0;
if (unlikely(rs->rs_status & AR5K_RXERR_MIC))
rxs->flag |= RX_FLAG_MMIC_ERROR;
+ if (unlikely(rs->rs_status & AR5K_RXERR_CRC))
+ rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+
/*
* always extend the mac timestamp, since this information is
@@ -1449,6 +1452,8 @@ ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
ah->stats.rx_bytes_count += rs->rs_datalen;
if (unlikely(rs->rs_status)) {
+ unsigned int filters;
+
if (rs->rs_status & AR5K_RXERR_CRC)
ah->stats.rxerr_crc++;
if (rs->rs_status & AR5K_RXERR_FIFO)
@@ -1457,7 +1462,20 @@ ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
ah->stats.rxerr_phy++;
if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32)
ah->stats.rxerr_phy_code[rs->rs_phyerr]++;
- return false;
+
+ /*
+ * Treat packets that underwent a CCK or OFDM reset as having a bad CRC.
+ * These restarts happen when the radio resynchronizes to a stronger frame
+ * while receiving a weaker frame. Here we receive the prefix of the weak
+ * frame. Since these are incomplete packets, mark their CRC as invalid.
+ */
+ if (rs->rs_phyerr == AR5K_RX_PHY_ERROR_OFDM_RESTART ||
+ rs->rs_phyerr == AR5K_RX_PHY_ERROR_CCK_RESTART) {
+ rs->rs_status |= AR5K_RXERR_CRC;
+ rs->rs_status &= ~AR5K_RXERR_PHY;
+ } else {
+ return false;
+ }
}
if (rs->rs_status & AR5K_RXERR_DECRYPT) {
/*
@@ -1480,8 +1498,15 @@ ath5k_receive_frame_ok(struct ath5k_hw *ah, struct ath5k_rx_status *rs)
return true;
}
- /* reject any frames with non-crypto errors */
- if (rs->rs_status & ~(AR5K_RXERR_DECRYPT))
+ /*
+ * Reject any frames with non-crypto errors, and take into account the
+ * current FIF_* filters.
+ */
+ filters = AR5K_RXERR_DECRYPT;
+ if (ah->fif_filter_flags & FIF_FCSFAIL)
+ filters |= AR5K_RXERR_CRC;
+
+ if (rs->rs_status & ~filters)
return false;
}
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index f77ef36acf87..48a6a69b57bc 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -53,7 +53,7 @@
#define ATH_POLARITY(data) ((data) & 0xff)
/* Devices we match on for LED config info (typically laptops) */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {
+static const struct pci_device_id ath5k_led_devices[] = {
/* AR5211 */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },
/* HP Compaq nc6xx, nc4000, nx6000 */
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index afb23b3cc7be..b65c38fdaa4b 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -473,6 +473,8 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
/* Set the cached hw filter flags, this will later actually
* be set in HW */
ah->filter_flags = rfilt;
+ /* Store current FIF filter flags */
+ ah->fif_filter_flags = *new_flags;
mutex_unlock(&ah->lock);
}
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index 859db7c34f87..c6156cc38940 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -28,7 +28,7 @@
#include "reg.h"
/* Known PCI ids */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
+static const struct pci_device_id ath5k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
{ PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
{ PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
index 18fdd69e1f71..397a52f2628b 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.h
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
(void) (check_type == val); \
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
- *val = le32_to_cpu(tmp); \
+ if (!ret) \
+ *val = le32_to_cpu(tmp); \
ret; \
})
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 0e26f4a34fda..e535807c3d89 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (info->inactivity_timeout) {
inactivity_timeout = info->inactivity_timeout;
- if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
+ if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+ ar->fw_capabilities))
inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
60);
@@ -3636,7 +3637,7 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
struct net_device *ndev;
struct ath6kl_vif *vif;
- ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
+ ndev = alloc_netdev(sizeof(*vif), name, NET_NAME_UNKNOWN, ether_setup);
if (!ndev)
return NULL;
@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.ht_supported = false;
}
- if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
+ if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+ ar->fw_capabilities)) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index b0b652042760..0df74b245af4 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
/* FIXME: we should free all firmwares in the error cases below */
+ /*
+ * Backwards compatibility support for older ar6004 firmware images
+ * which do not set these feature flags.
+ */
+ if (ar->target_type == TARGET_TYPE_AR6004 &&
+ ar->fw_api <= 4) {
+ __set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+ ar->fw_capabilities);
+ __set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+ ar->fw_capabilities);
+
+ if (ar->hw.id == AR6004_HW_1_3_VERSION)
+ __set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+ ar->fw_capabilities);
+ }
+
/* Indicate that WMI is enabled (although not ready yet) */
set_bit(WMI_ENABLED, &ar->flag);
ar->wmi = ath6kl_wmi_init(ar);
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 26b0f92424e1..2b78c863d030 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
*/
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
+ /* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */
+ ATH6KL_FW_CAPABILITY_64BIT_RATES,
+
+ /* WMI_AP_CONN_INACT_CMDID uses minutes as units */
+ ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
+
+ /* use low priority endpoint for all data */
+ ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+
+ /* ratetable is the 2 stream version (max MCS15) */
+ ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
+
+ /* firmare doesn't support IP checksumming */
+ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
+
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
};
enum ath6kl_hw_flags {
- ATH6KL_HW_64BIT_RATES = BIT(0),
- ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
- ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
#define ATH6KL_FW_API4_FILE "fw-4.bin"
+#define ATH6KL_FW_API5_FILE "fw-5.bin"
/* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba
@@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_3_VERSION 0x31c8088a
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
-#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
-#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
+#define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin"
+#define AR6004_HW_1_3_UTF_FIRMWARE_FILE "utf.bin"
+#define AR6004_HW_1_3_TESTSCRIPT_FILE "nullTestFlow.bin"
+#define AR6004_HW_1_3_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
+#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
+
+/* AR6004 3.0 definitions */
+#define AR6004_HW_3_0_VERSION 0x31C809F8
+#define AR6004_HW_3_0_FW_DIR "ath6k/AR6004/hw3.0"
+#define AR6004_HW_3_0_FIRMWARE_FILE "fw.ram.bin"
+#define AR6004_HW_3_0_TCMD_FIRMWARE_FILE "utf.bin"
+#define AR6004_HW_3_0_UTF_FIRMWARE_FILE "utf.bin"
+#define AR6004_HW_3_0_TESTSCRIPT_FILE "nullTestFlow.bin"
+#define AR6004_HW_3_0_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
+#define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 756fe52a12c8..ca1a18c86c0d 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
static void htc_rxctrl_complete(struct htc_target *context,
struct htc_packet *packet)
{
- /* TODO, can't really receive HTC control messages yet.... */
- ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__);
+ struct sk_buff *skb = packet->skb;
+
+ if (packet->endpoint == ENDPOINT_0 &&
+ packet->status == -ECANCELED &&
+ skb != NULL)
+ dev_kfree_skb(skb);
}
/* htc pipe initialization */
@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target,
static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target)
{
- /* TODO */
+ struct htc_endpoint *endpoint;
+ struct htc_packet *packet, *tmp_pkt;
+ int i;
+
+ for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
+ endpoint = &target->endpoint[i];
+
+ spin_lock_bh(&target->rx_lock);
+
+ list_for_each_entry_safe(packet, tmp_pkt,
+ &endpoint->rx_bufq, list) {
+ list_del(&packet->list);
+ spin_unlock_bh(&target->rx_lock);
+ ath6kl_dbg(ATH6KL_DBG_HTC,
+ "htc rx flush pkt 0x%p len %d ep %d\n",
+ packet, packet->buf_len,
+ packet->endpoint);
+ dev_kfree_skb(packet->pkt_cntxt);
+ spin_lock_bh(&target->rx_lock);
+ }
+
+ spin_unlock_bh(&target->rx_lock);
+ }
}
static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index d5ef211f261c..fffd52355123 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900,
.refclk_hz = 26000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_64BIT_RATES |
- ATH6KL_HW_AP_INACTIVITY_MINS,
+ .flags = 0,
.fw = {
.dir = AR6004_HW_1_0_FW_DIR,
@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400,
.refclk_hz = 40000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_64BIT_RATES |
- ATH6KL_HW_AP_INACTIVITY_MINS,
+ .flags = 0,
.fw = {
.dir = AR6004_HW_1_1_FW_DIR,
.fw = AR6004_HW_1_1_FIRMWARE_FILE,
@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00,
.refclk_hz = 40000000,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_64BIT_RATES |
- ATH6KL_HW_AP_INACTIVITY_MINS,
+ .flags = 0,
.fw = {
.dir = AR6004_HW_1_2_FW_DIR,
@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = {
.board_ext_data_addr = 0x437000,
.reserved_ram_size = 7168,
.board_addr = 0x436400,
- .refclk_hz = 40000000,
+ .refclk_hz = 0,
.uarttx_pin = 11,
- .flags = ATH6KL_HW_64BIT_RATES |
- ATH6KL_HW_AP_INACTIVITY_MINS |
- ATH6KL_HW_MAP_LP_ENDPOINT,
+ .flags = 0,
.fw = {
.dir = AR6004_HW_1_3_FW_DIR,
.fw = AR6004_HW_1_3_FIRMWARE_FILE,
+ .tcmd = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
+ .utf = AR6004_HW_1_3_UTF_FIRMWARE_FILE,
+ .testscript = AR6004_HW_1_3_TESTSCRIPT_FILE,
},
.fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
},
+ {
+ .id = AR6004_HW_3_0_VERSION,
+ .name = "ar6004 hw 3.0",
+ .dataset_patch_addr = 0,
+ .app_load_addr = 0x1234,
+ .board_ext_data_addr = 0,
+ .reserved_ram_size = 7168,
+ .board_addr = 0x436400,
+ .testscript_addr = 0,
+ .flags = 0,
+
+ .fw = {
+ .dir = AR6004_HW_3_0_FW_DIR,
+ .fw = AR6004_HW_3_0_FIRMWARE_FILE,
+ .tcmd = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
+ .utf = AR6004_HW_3_0_UTF_FIRMWARE_FILE,
+ .testscript = AR6004_HW_3_0_TESTSCRIPT_FILE,
+ },
+
+ .fw_board = AR6004_HW_3_0_BOARD_DATA_FILE,
+ .fw_default_board = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
+ },
};
/*
@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar)
* but possible in theory.
*/
- if (ar->target_type == TARGET_TYPE_AR6003) {
+ if ((ar->target_type == TARGET_TYPE_AR6003) ||
+ (ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
+ (ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
param = ar->hw.board_ext_data_addr;
ram_reserved_size = ar->hw.reserved_ram_size;
@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar)
return status;
/* Configure target refclk_hz */
- status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz);
- if (status)
- return status;
+ if (ar->hw.refclk_hz != 0) {
+ status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
+ ar->hw.refclk_hz);
+ if (status)
+ return status;
+ }
return 0;
}
@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if (ret)
return ret;
+ ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
+ if (ret == 0) {
+ ar->fw_api = 5;
+ goto out;
+ }
+
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
if (ret == 0) {
ar->fw_api = 4;
@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
ath6kl_bmi_write_hi32(ar, hi_board_data,
board_address);
} else {
- ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
+ ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
+ if (ret) {
+ ath6kl_err("Failed to get board file target address.\n");
+ return ret;
+ }
}
/* determine where in target ram to write extended board data */
- ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
+ ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
+ if (ret) {
+ ath6kl_err("Failed to get extended board file target address.\n");
+ return ret;
+ }
if (ar->target_type == TARGET_TYPE_AR6003 &&
board_ext_address == 0) {
@@ -1187,7 +1226,6 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
default:
WARN_ON(1);
return -EINVAL;
- break;
}
if (board_ext_address &&
@@ -1230,7 +1268,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
}
/* record the fact that Board Data IS initialized */
- ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1);
+ if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
+ (ar->version.target_ver == AR6004_HW_3_0_VERSION))
+ param = board_data_size;
+ else
+ param = 1;
+
+ ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
return ret;
}
@@ -1361,7 +1405,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
}
ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
- ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
+
+ if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
+ (ar->version.target_ver != AR6004_HW_3_0_VERSION))
+ ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
+
ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
return 0;
@@ -1567,6 +1615,11 @@ static const struct fw_capa_str_map {
{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
+ { ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
+ { ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
+ { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
+ { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
+ { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
};
static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index d56554674da4..21516bc65785 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
struct ath6kl *ar = vif->ar;
struct target_stats *stats = &vif->target_stats;
struct tkip_ccmp_stats *ccmp_stats;
+ s32 rate;
u8 ac;
if (len < sizeof(*tgt_stats))
@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
stats->tx_rts_fail_cnt +=
le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
- stats->tx_ucast_rate =
- ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate));
+
+ rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate);
+ stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
- stats->rx_ucast_rate =
- ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate));
+
+ rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate);
+ stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = {
void init_netdev(struct net_device *dev)
{
+ struct ath6kl *ar = ath6kl_priv(dev);
+
dev->netdev_ops = &ath6kl_netdev_ops;
dev->destructor = free_netdev;
dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
WMI_MAX_TX_META_SZ +
ATH6KL_HTC_ALIGN_BYTES, 4);
- dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+ if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
+ ar->fw_capabilities))
+ dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
return;
}
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 3afc5a463d06..c44325856b81 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break;
case WMI_DATA_VI_SVC:
- if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+ if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+ ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break;
case WMI_DATA_VO_SVC:
- if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
+ if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
+ ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
/* table of devices that work with this driver */
static struct usb_device_id ath6kl_usb_ids[] = {
+ {USB_DEVICE(0x0cf3, 0x9375)},
{USB_DEVICE(0x0cf3, 0x9374)},
{ /* Terminating entry */ },
};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 4d7f9e4712e9..94df345d08c2 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
{0, 0}
};
+static const s32 wmi_rate_tbl_mcs15[][2] = {
+ /* {W/O SGI, with SGI} */
+ {1000, 1000},
+ {2000, 2000},
+ {5500, 5500},
+ {11000, 11000},
+ {6000, 6000},
+ {9000, 9000},
+ {12000, 12000},
+ {18000, 18000},
+ {24000, 24000},
+ {36000, 36000},
+ {48000, 48000},
+ {54000, 54000},
+ {6500, 7200}, /* HT 20, MCS 0 */
+ {13000, 14400},
+ {19500, 21700},
+ {26000, 28900},
+ {39000, 43300},
+ {52000, 57800},
+ {58500, 65000},
+ {65000, 72200},
+ {13000, 14400}, /* HT 20, MCS 8 */
+ {26000, 28900},
+ {39000, 43300},
+ {52000, 57800},
+ {78000, 86700},
+ {104000, 115600},
+ {117000, 130000},
+ {130000, 144400}, /* HT 20, MCS 15 */
+ {13500, 15000}, /*HT 40, MCS 0 */
+ {27000, 30000},
+ {40500, 45000},
+ {54000, 60000},
+ {81000, 90000},
+ {108000, 120000},
+ {121500, 135000},
+ {135000, 150000},
+ {27000, 30000}, /*HT 40, MCS 8 */
+ {54000, 60000},
+ {81000, 90000},
+ {108000, 120000},
+ {162000, 180000},
+ {216000, 240000},
+ {243000, 270000},
+ {270000, 300000}, /*HT 40, MCS 15 */
+ {0, 0}
+};
+
/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
static const u8 up_to_ac[] = {
WMM_AC_BE,
@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{
struct ath6kl *ar = wmi->parent_dev;
- if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
+ if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
+ ar->fw_capabilities))
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
NO_SYNC_WMIFLAG);
}
-s32 ath6kl_wmi_get_rate(s8 rate_index)
+s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index)
{
+ struct ath6kl *ar = wmi->parent_dev;
u8 sgi = 0;
+ s32 ret;
if (rate_index == RATE_AUTO)
return 0;
@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
sgi = 1;
}
- if (WARN_ON(rate_index > RATE_MCS_7_40))
- rate_index = RATE_MCS_7_40;
+ if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
+ ar->fw_capabilities)) {
+ if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
+ return 0;
+
+ ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
+ } else {
+ if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
+ return 0;
- return wmi_rate_tbl[(u32) rate_index][sgi];
+ ret = wmi_rate_tbl[(u32) rate_index][sgi];
+ }
+
+ return ret;
}
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index bb23fc00111d..19f88b4a24fb 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
struct ath6kl_htcap *htcap);
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
-s32 ath6kl_wmi_get_rate(s8 rate_index);
+s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index);
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1);
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 8fcd586d1c39..6b4020a57984 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -5,7 +5,8 @@ ath9k-y += beacon.o \
recv.o \
xmit.o \
link.o \
- antenna.o
+ antenna.o \
+ channel.o
ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index be3eb2a8d602..4173838f4684 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -113,6 +113,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
irq = res->start;
+ ath9k_fill_chanctx_ops();
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 741b38ddcb37..59af9f9712da 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(i->txpower, AR_XmitPower)
+ | SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@@ -306,6 +306,10 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| set11nRateFlags(i->rates, 2)
| set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate);
+
+ ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
+ ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
+ ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 235053ba7737..80c6eacbda53 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3535,7 +3535,8 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
{
int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl;
- if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+ if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9531(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index ec1da0cc25f5..ddef9eedbac6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -314,10 +314,17 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
qca953x_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
qca953x_1p0_mac_postamble);
- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
- qca953x_1p0_baseband_core);
- INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
- qca953x_1p0_baseband_postamble);
+ if (AR_SREV_9531_20(ah)) {
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ qca953x_2p0_baseband_core);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ qca953x_2p0_baseband_postamble);
+ } else {
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+ qca953x_1p0_baseband_core);
+ INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+ qca953x_1p0_baseband_postamble);
+ }
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
qca953x_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 729ffbf07343..71e38e85aa99 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(i->txpower, AR_XmitPower)
+ | SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
+
+ ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
+ ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
+ ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 8927fc34d84c..542a8d51d3b0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1552,13 +1552,15 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
u8 *ini_reloaded)
{
unsigned int regWrites = 0;
- u32 modesIndex;
+ u32 modesIndex, txgain_index;
if (IS_CHAN_5GHZ(chan))
modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
else
modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
+ txgain_index = AR_SREV_9531(ah) ? 1 : modesIndex;
+
if (modesIndex == ah->modes_index) {
*ini_reloaded = false;
goto set_rfmode;
@@ -1573,7 +1575,7 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
modesIndex);
- REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+ REG_WRITE_ARRAY(&ah->iniModesTxGain, txgain_index, regWrites);
if (AR_SREV_9462_20_OR_LATER(ah)) {
/*
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
index 8e5c3b9786e3..812a9d787bf3 100644
--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
@@ -219,7 +219,7 @@ static const u32 qca953x_1p0_baseband_core[][2] = {
{0x00009d04, 0x40206c10},
{0x00009d08, 0x009c4060},
{0x00009d0c, 0x9883800a},
- {0x00009d10, 0x01884061},
+ {0x00009d10, 0x018848c6},
{0x00009d14, 0x00c0040b},
{0x00009d18, 0x00000000},
{0x00009e08, 0x0038230c},
@@ -715,4 +715,203 @@ static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = {
{0x00016448, 0x6c927a70},
};
+static const u32 qca953x_2p0_baseband_core[][2] = {
+ /* Addr allmodes */
+ {0x00009800, 0xafe68e30},
+ {0x00009804, 0xfd14e000},
+ {0x00009808, 0x9c0a9f6b},
+ {0x0000980c, 0x04900000},
+ {0x00009814, 0x0280c00a},
+ {0x00009818, 0x00000000},
+ {0x0000981c, 0x00020028},
+ {0x00009834, 0x6400a190},
+ {0x00009838, 0x0108ecff},
+ {0x0000983c, 0x14000600},
+ {0x00009880, 0x201fff00},
+ {0x00009884, 0x00001042},
+ {0x000098a4, 0x00200400},
+ {0x000098b0, 0x32840bbe},
+ {0x000098bc, 0x00000002},
+ {0x000098d0, 0x004b6a8e},
+ {0x000098d4, 0x00000820},
+ {0x000098dc, 0x00000000},
+ {0x000098f0, 0x00000000},
+ {0x000098f4, 0x00000000},
+ {0x00009c04, 0xff55ff55},
+ {0x00009c08, 0x0320ff55},
+ {0x00009c0c, 0x00000000},
+ {0x00009c10, 0x00000000},
+ {0x00009c14, 0x00046384},
+ {0x00009c18, 0x05b6b440},
+ {0x00009c1c, 0x00b6b440},
+ {0x00009d00, 0xc080a333},
+ {0x00009d04, 0x40206c10},
+ {0x00009d08, 0x009c4060},
+ {0x00009d0c, 0x9883800a},
+ {0x00009d10, 0x018848c6},
+ {0x00009d14, 0x00c0040b},
+ {0x00009d18, 0x00000000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x990bb515},
+ {0x00009e28, 0x0c6f0000},
+ {0x00009e30, 0x06336f77},
+ {0x00009e34, 0x6af6532f},
+ {0x00009e38, 0x0cc80c00},
+ {0x00009e40, 0x0d261820},
+ {0x00009e4c, 0x00001004},
+ {0x00009e50, 0x00ff03f1},
+ {0x00009fc0, 0x813e4788},
+ {0x00009fc4, 0x0001efb5},
+ {0x00009fcc, 0x40000014},
+ {0x00009fd0, 0x02993b93},
+ {0x0000a20c, 0x00000000},
+ {0x0000a220, 0x00000000},
+ {0x0000a224, 0x00000000},
+ {0x0000a228, 0x10002310},
+ {0x0000a23c, 0x00000000},
+ {0x0000a244, 0x0c000000},
+ {0x0000a248, 0x00000140},
+ {0x0000a2a0, 0x00000007},
+ {0x0000a2c0, 0x00000007},
+ {0x0000a2c8, 0x00000000},
+ {0x0000a2d4, 0x00000000},
+ {0x0000a2ec, 0x00000000},
+ {0x0000a2f0, 0x00000000},
+ {0x0000a2f4, 0x00000000},
+ {0x0000a2f8, 0x00000000},
+ {0x0000a344, 0x00000000},
+ {0x0000a34c, 0x00000000},
+ {0x0000a350, 0x0000a000},
+ {0x0000a364, 0x00000000},
+ {0x0000a370, 0x00000000},
+ {0x0000a390, 0x00000001},
+ {0x0000a394, 0x00000444},
+ {0x0000a398, 0x001f0e0f},
+ {0x0000a39c, 0x0075393f},
+ {0x0000a3a0, 0xb79f6427},
+ {0x0000a3a4, 0x000400ff},
+ {0x0000a3a8, 0x6a6a6a6a},
+ {0x0000a3ac, 0x6a6a6a6a},
+ {0x0000a3b0, 0x00c8641a},
+ {0x0000a3b4, 0x0000001a},
+ {0x0000a3b8, 0x0088642a},
+ {0x0000a3bc, 0x000001fa},
+ {0x0000a3c0, 0x20202020},
+ {0x0000a3c4, 0x22222220},
+ {0x0000a3c8, 0x20200020},
+ {0x0000a3cc, 0x20202020},
+ {0x0000a3d0, 0x20202020},
+ {0x0000a3d4, 0x20202020},
+ {0x0000a3d8, 0x20202020},
+ {0x0000a3dc, 0x20202020},
+ {0x0000a3e0, 0x20202020},
+ {0x0000a3e4, 0x20202020},
+ {0x0000a3e8, 0x20202020},
+ {0x0000a3ec, 0x20202020},
+ {0x0000a3f0, 0x00000000},
+ {0x0000a3f4, 0x00000000},
+ {0x0000a3f8, 0x0c9bd380},
+ {0x0000a3fc, 0x000f0f01},
+ {0x0000a400, 0x8fa91f01},
+ {0x0000a404, 0x00000000},
+ {0x0000a408, 0x0e79e5c6},
+ {0x0000a40c, 0x00820820},
+ {0x0000a414, 0x1ce42108},
+ {0x0000a418, 0x2d001dce},
+ {0x0000a41c, 0x1ce73908},
+ {0x0000a420, 0x000001ce},
+ {0x0000a424, 0x1ce738e7},
+ {0x0000a428, 0x000001ce},
+ {0x0000a42c, 0x1ce739ce},
+ {0x0000a430, 0x1ce739ce},
+ {0x0000a434, 0x00000000},
+ {0x0000a438, 0x00001801},
+ {0x0000a43c, 0x00100000},
+ {0x0000a444, 0x00000000},
+ {0x0000a448, 0x05000080},
+ {0x0000a44c, 0x00000001},
+ {0x0000a450, 0x00010000},
+ {0x0000a458, 0x00000000},
+ {0x0000a644, 0xbfad9d74},
+ {0x0000a648, 0x0048060a},
+ {0x0000a64c, 0x00003c37},
+ {0x0000a670, 0x03020100},
+ {0x0000a674, 0x09080504},
+ {0x0000a678, 0x0d0c0b0a},
+ {0x0000a67c, 0x13121110},
+ {0x0000a680, 0x31301514},
+ {0x0000a684, 0x35343332},
+ {0x0000a688, 0x00000036},
+ {0x0000a690, 0x08000838},
+ {0x0000a7cc, 0x00000000},
+ {0x0000a7d0, 0x00000000},
+ {0x0000a7d4, 0x00000004},
+ {0x0000a7dc, 0x00000000},
+ {0x0000a8d0, 0x004b6a8e},
+ {0x0000a8d4, 0x00000820},
+ {0x0000a8dc, 0x00000000},
+ {0x0000a8f0, 0x00000000},
+ {0x0000a8f4, 0x00000000},
+ {0x0000b2d0, 0x00000080},
+ {0x0000b2d4, 0x00000000},
+ {0x0000b2ec, 0x00000000},
+ {0x0000b2f0, 0x00000000},
+ {0x0000b2f4, 0x00000000},
+ {0x0000b2f8, 0x00000000},
+ {0x0000b408, 0x0e79e5c0},
+ {0x0000b40c, 0x00820820},
+ {0x0000b420, 0x00000000},
+};
+
+static const u32 qca953x_2p0_baseband_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+ {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
+ {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+ {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+ {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+ {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
+ {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
+ {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+ {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222},
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+ {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+ {0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
+ {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+ {0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
+ {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+ {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
+ {0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
+ {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+ {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+ {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+ {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e},
+ {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
+ {0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e},
+ {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+ {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+ {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
+ {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+ {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
+ {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
+ {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
+ {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
+ {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
+ {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+ {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
+};
+
#endif /* INITVALS_953X_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 2ca8f7e06174..7fc13a8da675 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/completion.h>
+#include <linux/time.h>
#include "common.h"
#include "debug.h"
@@ -35,10 +36,7 @@ extern struct ieee80211_ops ath9k_ops;
extern int ath9k_modparam_nohwcrypt;
extern int led_blink;
extern bool is_ath9k_unloaded;
-
-struct ath_config {
- u16 txpowlimit;
-};
+extern int ath9k_use_chanctx;
/*************************/
/* Descriptor Management */
@@ -167,7 +165,6 @@ struct ath_txq {
u32 axq_ampdu_depth;
bool stopped;
bool axq_tx_inprogress;
- struct list_head axq_acq;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
u8 txq_headidx;
u8 txq_tailidx;
@@ -185,7 +182,8 @@ struct ath_atx_ac {
struct ath_frame_info {
struct ath_buf *bf;
- int framelen;
+ u16 framelen;
+ s8 txq;
enum ath9k_key_type keytype;
u8 keyix;
u8 rtscts_rate;
@@ -280,8 +278,9 @@ struct ath_node {
struct ath_tx_control {
struct ath_txq *txq;
struct ath_node *an;
- u8 paprd;
struct ieee80211_sta *sta;
+ u8 paprd;
+ bool force_channel;
};
@@ -325,6 +324,116 @@ struct ath_rx {
u32 ampdu_ref;
};
+struct ath_chanctx {
+ struct cfg80211_chan_def chandef;
+ struct list_head vifs;
+ struct list_head acq[IEEE80211_NUM_ACS];
+ int hw_queue_base;
+
+ /* do not dereference, use for comparison only */
+ struct ieee80211_vif *primary_sta;
+
+ struct ath_beacon_config beacon;
+ struct ath9k_hw_cal_data caldata;
+ struct timespec tsf_ts;
+ u64 tsf_val;
+ u32 last_beacon;
+
+ u16 txpower;
+ bool offchannel;
+ bool stopped;
+ bool active;
+ bool assigned;
+ bool switch_after_beacon;
+};
+
+enum ath_chanctx_event {
+ ATH_CHANCTX_EVENT_BEACON_PREPARE,
+ ATH_CHANCTX_EVENT_BEACON_SENT,
+ ATH_CHANCTX_EVENT_TSF_TIMER,
+ ATH_CHANCTX_EVENT_BEACON_RECEIVED,
+ ATH_CHANCTX_EVENT_ASSOC,
+ ATH_CHANCTX_EVENT_SWITCH,
+ ATH_CHANCTX_EVENT_UNASSIGN,
+ ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL,
+};
+
+enum ath_chanctx_state {
+ ATH_CHANCTX_STATE_IDLE,
+ ATH_CHANCTX_STATE_WAIT_FOR_BEACON,
+ ATH_CHANCTX_STATE_WAIT_FOR_TIMER,
+ ATH_CHANCTX_STATE_SWITCH,
+ ATH_CHANCTX_STATE_FORCE_ACTIVE,
+};
+
+struct ath_chanctx_sched {
+ bool beacon_pending;
+ bool offchannel_pending;
+ enum ath_chanctx_state state;
+ u8 beacon_miss;
+
+ u32 next_tbtt;
+ u32 switch_start_time;
+ unsigned int offchannel_duration;
+ unsigned int channel_switch_time;
+
+ /* backup, in case the hardware timer fails */
+ struct timer_list timer;
+};
+
+enum ath_offchannel_state {
+ ATH_OFFCHANNEL_IDLE,
+ ATH_OFFCHANNEL_PROBE_SEND,
+ ATH_OFFCHANNEL_PROBE_WAIT,
+ ATH_OFFCHANNEL_SUSPEND,
+ ATH_OFFCHANNEL_ROC_START,
+ ATH_OFFCHANNEL_ROC_WAIT,
+ ATH_OFFCHANNEL_ROC_DONE,
+};
+
+struct ath_offchannel {
+ struct ath_chanctx chan;
+ struct timer_list timer;
+ struct cfg80211_scan_request *scan_req;
+ struct ieee80211_vif *scan_vif;
+ int scan_idx;
+ enum ath_offchannel_state state;
+ struct ieee80211_channel *roc_chan;
+ struct ieee80211_vif *roc_vif;
+ int roc_duration;
+ int duration;
+};
+#define ath_for_each_chanctx(_sc, _ctx) \
+ for (ctx = &sc->chanctx[0]; \
+ ctx <= &sc->chanctx[ARRAY_SIZE(sc->chanctx) - 1]; \
+ ctx++)
+
+void ath9k_fill_chanctx_ops(void);
+void ath9k_chanctx_force_active(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+static inline struct ath_chanctx *
+ath_chanctx_get(struct ieee80211_chanctx_conf *ctx)
+{
+ struct ath_chanctx **ptr = (void *) ctx->drv_priv;
+ return *ptr;
+}
+void ath_chanctx_init(struct ath_softc *sc);
+void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
+ struct cfg80211_chan_def *chandef);
+void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
+ struct cfg80211_chan_def *chandef);
+void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
+void ath_offchannel_timer(unsigned long data);
+void ath_offchannel_channel_change(struct ath_softc *sc);
+void ath_chanctx_offchan_switch(struct ath_softc *sc,
+ struct ieee80211_channel *chan);
+struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc,
+ bool active);
+void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
+ enum ath_chanctx_event ev);
+void ath_chanctx_timer(unsigned long data);
+
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan);
int ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
@@ -341,6 +450,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
+void ath_txq_schedule_all(struct ath_softc *sc);
int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
@@ -370,32 +480,47 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
/********/
struct ath_vif {
+ struct list_head list;
+
struct ieee80211_vif *vif;
struct ath_node mcast_node;
int av_bslot;
- bool primary_sta_vif;
__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
struct ath_buf *av_bcbuf;
+ struct ath_chanctx *chanctx;
/* P2P Client */
struct ieee80211_noa_data noa;
+
+ /* P2P GO */
+ u8 noa_index;
+ u32 offchannel_start;
+ u32 offchannel_duration;
+
+ u32 periodic_noa_start;
+ u32 periodic_noa_duration;
};
struct ath9k_vif_iter_data {
u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
u8 mask[ETH_ALEN]; /* bssid mask */
bool has_hw_macaddr;
+ u8 slottime;
+ bool beacons;
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */
+ struct ieee80211_vif *primary_sta;
};
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+ struct ath_chanctx *ctx,
struct ath9k_vif_iter_data *iter_data);
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+ struct ath_chanctx *ctx);
/*******************/
/* Beacon Handling */
@@ -458,6 +583,7 @@ void ath9k_csa_update(struct ath_softc *sc);
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
#define ATH_PLL_WORK_INTERVAL 100
+void ath_chanctx_work(struct work_struct *work);
void ath_tx_complete_poll_work(struct work_struct *work);
void ath_reset_work(struct work_struct *work);
bool ath_hw_check(struct ath_softc *sc);
@@ -473,6 +599,7 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
void ath_ps_full_sleep(unsigned long data);
void ath9k_p2p_ps_timer(void *priv);
void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif);
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
/**********/
/* BTCOEX */
@@ -702,6 +829,8 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
#define PS_BEACON_SYNC BIT(4)
#define PS_WAIT_FOR_ANI BIT(5)
+#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
+
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
@@ -720,6 +849,7 @@ struct ath_softc {
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_reset_work;
+ struct work_struct chanctx_work;
struct completion paprd_complete;
wait_queue_head_t tx_wait;
@@ -738,23 +868,27 @@ struct ath_softc {
short nvifs;
unsigned long ps_usecount;
- struct ath_config config;
struct ath_rx rx;
struct ath_tx tx;
struct ath_beacon beacon;
+ struct cfg80211_chan_def cur_chandef;
+ struct ath_chanctx chanctx[ATH9K_NUM_CHANCTX];
+ struct ath_chanctx *cur_chan;
+ struct ath_chanctx *next_chan;
+ spinlock_t chan_lock;
+ struct ath_offchannel offchannel;
+ struct ath_chanctx_sched sched;
+
#ifdef CONFIG_MAC80211_LEDS
bool led_registered;
char led_name[32];
struct led_classdev led_cdev;
#endif
- struct ath9k_hw_cal_data caldata;
-
#ifdef CONFIG_ATH9K_DEBUGFS
struct ath9k_debug debug;
#endif
- struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work;
struct delayed_work hw_pll_work;
struct timer_list sleep_timer;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index e387f0b2954a..eaf8f058c151 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -80,7 +80,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
u8 chainmask = ah->txchainmask;
u8 rate = 0;
- sband = &common->sbands[common->hw->conf.chandef.chan->band];
+ sband = &common->sbands[sc->cur_chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value;
if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short;
@@ -108,6 +108,55 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
}
+static void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
+ struct sk_buff *skb)
+{
+ static const u8 noa_ie_hdr[] = {
+ WLAN_EID_VENDOR_SPECIFIC, /* type */
+ 0, /* length */
+ 0x50, 0x6f, 0x9a, /* WFA OUI */
+ 0x09, /* P2P subtype */
+ 0x0c, /* Notice of Absence */
+ 0x00, /* LSB of little-endian len */
+ 0x00, /* MSB of little-endian len */
+ };
+
+ struct ieee80211_p2p_noa_attr *noa;
+ int noa_len, noa_desc, i = 0;
+ u8 *hdr;
+
+ if (!avp->offchannel_duration && !avp->periodic_noa_duration)
+ return;
+
+ noa_desc = !!avp->offchannel_duration + !!avp->periodic_noa_duration;
+ noa_len = 2 + sizeof(struct ieee80211_p2p_noa_desc) * noa_desc;
+
+ hdr = skb_put(skb, sizeof(noa_ie_hdr));
+ memcpy(hdr, noa_ie_hdr, sizeof(noa_ie_hdr));
+ hdr[1] = sizeof(noa_ie_hdr) + noa_len - 2;
+ hdr[7] = noa_len;
+
+ noa = (void *) skb_put(skb, noa_len);
+ memset(noa, 0, noa_len);
+
+ noa->index = avp->noa_index;
+ if (avp->periodic_noa_duration) {
+ u32 interval = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+
+ noa->desc[i].count = 255;
+ noa->desc[i].start_time = cpu_to_le32(avp->periodic_noa_start);
+ noa->desc[i].duration = cpu_to_le32(avp->periodic_noa_duration);
+ noa->desc[i].interval = cpu_to_le32(interval);
+ i++;
+ }
+
+ if (avp->offchannel_duration) {
+ noa->desc[i].count = 1;
+ noa->desc[i].start_time = cpu_to_le32(avp->offchannel_start);
+ noa->desc[i].duration = cpu_to_le32(avp->offchannel_duration);
+ }
+}
+
static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -155,6 +204,9 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
+ if (vif->p2p)
+ ath9k_beacon_add_noa(sc, avp, skb);
+
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
@@ -249,7 +301,7 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
static int ath9k_beacon_choose_slot(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
u16 intval;
u32 tsftu;
u64 tsf;
@@ -277,8 +329,8 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
u32 tsfadjust;
if (avp->av_bslot == 0)
@@ -374,12 +426,19 @@ void ath9k_beacon_tasklet(unsigned long data)
vif = sc->beacon.bslot[slot];
/* EDMA devices check that in the tx completion function. */
- if (!edma && ath9k_csa_is_finished(sc, vif))
- return;
+ if (!edma) {
+ if (sc->sched.beacon_pending)
+ ath_chanctx_event(sc, NULL,
+ ATH_CHANCTX_EVENT_BEACON_SENT);
+
+ if (ath9k_csa_is_finished(sc, vif))
+ return;
+ }
if (!vif || !vif->bss_conf.enable_beacon)
return;
+ ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_BEACON_PREPARE);
bf = ath9k_beacon_generate(sc->hw, vif);
if (sc->beacon.bmisscnt != 0) {
@@ -500,7 +559,6 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_vif *avp = (void *)vif->drv_priv;
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
if ((vif->type != NL80211_IFTYPE_AP) ||
@@ -514,7 +572,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
if ((vif->type == NL80211_IFTYPE_STATION) &&
test_bit(ATH_OP_BEACONS, &common->op_flags) &&
- !avp->primary_sta_vif) {
+ vif != sc->cur_chan->primary_sta) {
ath_dbg(common, CONFIG,
"Beacon already configured for a station interface\n");
return false;
@@ -525,10 +583,11 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc,
}
static void ath9k_cache_beacon_config(struct ath_softc *sc,
+ struct ath_chanctx *ctx,
struct ieee80211_bss_conf *bss_conf)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_beacon_config *cur_conf = &ctx->beacon;
ath_dbg(common, BEACON,
"Caching beacon data for BSS: %pM\n", bss_conf->bssid);
@@ -564,20 +623,29 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
u32 changed)
{
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_chanctx *ctx = avp->chanctx;
+ struct ath_beacon_config *cur_conf;
unsigned long flags;
bool skip_beacon = false;
+ if (!ctx)
+ return;
+
+ cur_conf = &avp->chanctx->beacon;
if (vif->type == NL80211_IFTYPE_AP)
ath9k_set_tsfadjust(sc, vif);
if (!ath9k_allow_beacon_config(sc, vif))
return;
- if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
- ath9k_cache_beacon_config(sc, bss_conf);
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ ath9k_cache_beacon_config(sc, ctx, bss_conf);
+ if (ctx != sc->cur_chan)
+ return;
+
ath9k_set_beacon(sc);
set_bit(ATH_OP_BEACONS, &common->op_flags);
return;
@@ -593,10 +661,13 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
cur_conf->enable_beacon = false;
} else if (bss_conf->enable_beacon) {
cur_conf->enable_beacon = true;
- ath9k_cache_beacon_config(sc, bss_conf);
+ ath9k_cache_beacon_config(sc, ctx, bss_conf);
}
}
+ if (ctx != sc->cur_chan)
+ return;
+
/*
* Configure the HW beacon registers only when we have a valid
* beacon interval.
@@ -631,7 +702,7 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
void ath9k_set_beacon(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
switch (sc->sc_ah->opmode) {
case NL80211_IFTYPE_AP:
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
new file mode 100644
index 000000000000..ba214ebdcd16
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+/* Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+ */
+static int ath_set_channel(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath9k_channel *hchan;
+ struct cfg80211_chan_def *chandef = &sc->cur_chan->chandef;
+ struct ieee80211_channel *chan = chandef->chan;
+ int pos = chan->hw_value;
+ int old_pos = -1;
+ int r;
+
+ if (test_bit(ATH_OP_INVALID, &common->op_flags))
+ return -EIO;
+
+ if (ah->curchan)
+ old_pos = ah->curchan - &ah->channels[0];
+
+ ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
+ chan->center_freq, chandef->width);
+
+ /* update survey stats for the old channel before switching */
+ spin_lock_bh(&common->cc_lock);
+ ath_update_survey_stats(sc);
+ spin_unlock_bh(&common->cc_lock);
+
+ ath9k_cmn_get_channel(hw, ah, chandef);
+
+ /* If the operating channel changes, change the survey in-use flags
+ * along with it.
+ * Reset the survey data for the new channel, unless we're switching
+ * back to the operating channel from an off-channel operation.
+ */
+ if (!sc->cur_chan->offchannel && sc->cur_survey != &sc->survey[pos]) {
+ if (sc->cur_survey)
+ sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
+
+ sc->cur_survey = &sc->survey[pos];
+
+ memset(sc->cur_survey, 0, sizeof(struct survey_info));
+ sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
+ } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
+ memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+ }
+
+ hchan = &sc->sc_ah->channels[pos];
+ r = ath_reset_internal(sc, hchan);
+ if (r)
+ return r;
+
+ /* The most recent snapshot of channel->noisefloor for the old
+ * channel is only available after the hardware reset. Copy it to
+ * the survey stats now.
+ */
+ if (old_pos >= 0)
+ ath_update_survey_nf(sc, old_pos);
+
+ /* Enable radar pulse detection if on a DFS channel. Spectral
+ * scanning and radar detection can not be used concurrently.
+ */
+ if (hw->conf.radar_enabled) {
+ u32 rxfilter;
+
+ /* set HW specific DFS configuration */
+ ath9k_hw_set_radar_params(ah);
+ rxfilter = ath9k_hw_getrxfilter(ah);
+ rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
+ ATH9K_RX_FILTER_PHYERR;
+ ath9k_hw_setrxfilter(ah, rxfilter);
+ ath_dbg(common, DFS, "DFS enabled at freq %d\n",
+ chan->center_freq);
+ } else {
+ /* perform spectral scan if requested. */
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
+ sc->spectral_mode == SPECTRAL_CHANSCAN)
+ ath9k_spectral_scan_trigger(hw);
+ }
+
+ return 0;
+}
+
+static bool
+ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
+ bool powersave)
+{
+ struct ieee80211_vif *vif = avp->vif;
+ struct ieee80211_sta *sta = NULL;
+ struct ieee80211_hdr_3addr *nullfunc;
+ struct ath_tx_control txctl;
+ struct sk_buff *skb;
+ int band = sc->cur_chan->chandef.chan->band;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ if (!vif->bss_conf.assoc)
+ return false;
+
+ skb = ieee80211_nullfunc_get(sc->hw, vif);
+ if (!skb)
+ return false;
+
+ nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
+ if (powersave)
+ nullfunc->frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_PM);
+
+ skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
+ dev_kfree_skb_any(skb);
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ memset(&txctl, 0, sizeof(txctl));
+ txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
+ txctl.sta = sta;
+ txctl.force_channel = true;
+ if (ath_tx_start(sc->hw, skb, &txctl)) {
+ ieee80211_free_txskb(sc->hw, skb);
+ return false;
+ }
+
+ return true;
+}
+
+void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_vif *avp;
+ bool active = false;
+ u8 n_active = 0;
+
+ if (!ctx)
+ return;
+
+ list_for_each_entry(avp, &ctx->vifs, list) {
+ struct ieee80211_vif *vif = avp->vif;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_STATION:
+ if (vif->bss_conf.assoc)
+ active = true;
+ break;
+ default:
+ active = true;
+ break;
+ }
+ }
+ ctx->active = active;
+
+ ath_for_each_chanctx(sc, ctx) {
+ if (!ctx->assigned || list_empty(&ctx->vifs))
+ continue;
+ n_active++;
+ }
+
+ if (n_active <= 1) {
+ clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
+ return;
+ }
+ if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
+ return;
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL);
+}
+
+static bool
+ath_chanctx_send_ps_frame(struct ath_softc *sc, bool powersave)
+{
+ struct ath_vif *avp;
+ bool sent = false;
+
+ rcu_read_lock();
+ list_for_each_entry(avp, &sc->cur_chan->vifs, list) {
+ if (ath_chanctx_send_vif_ps_frame(sc, avp, powersave))
+ sent = true;
+ }
+ rcu_read_unlock();
+
+ return sent;
+}
+
+static bool ath_chanctx_defer_switch(struct ath_softc *sc)
+{
+ if (sc->cur_chan == &sc->offchannel.chan)
+ return false;
+
+ switch (sc->sched.state) {
+ case ATH_CHANCTX_STATE_SWITCH:
+ return false;
+ case ATH_CHANCTX_STATE_IDLE:
+ if (!sc->cur_chan->switch_after_beacon)
+ return false;
+
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static void ath_chanctx_set_next(struct ath_softc *sc, bool force)
+{
+ struct timespec ts;
+ bool measure_time = false;
+ bool send_ps = false;
+
+ spin_lock_bh(&sc->chan_lock);
+ if (!sc->next_chan) {
+ spin_unlock_bh(&sc->chan_lock);
+ return;
+ }
+
+ if (!force && ath_chanctx_defer_switch(sc)) {
+ spin_unlock_bh(&sc->chan_lock);
+ return;
+ }
+
+ if (sc->cur_chan != sc->next_chan) {
+ sc->cur_chan->stopped = true;
+ spin_unlock_bh(&sc->chan_lock);
+
+ if (sc->next_chan == &sc->offchannel.chan) {
+ getrawmonotonic(&ts);
+ measure_time = true;
+ }
+ __ath9k_flush(sc->hw, ~0, true);
+
+ if (ath_chanctx_send_ps_frame(sc, true))
+ __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
+
+ send_ps = true;
+ spin_lock_bh(&sc->chan_lock);
+
+ if (sc->cur_chan != &sc->offchannel.chan) {
+ getrawmonotonic(&sc->cur_chan->tsf_ts);
+ sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
+ }
+ }
+ sc->cur_chan = sc->next_chan;
+ sc->cur_chan->stopped = false;
+ sc->next_chan = NULL;
+ sc->sched.offchannel_duration = 0;
+ if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE)
+ sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+
+ spin_unlock_bh(&sc->chan_lock);
+
+ if (sc->sc_ah->chip_fullsleep ||
+ memcmp(&sc->cur_chandef, &sc->cur_chan->chandef,
+ sizeof(sc->cur_chandef))) {
+ ath_set_channel(sc);
+ if (measure_time)
+ sc->sched.channel_switch_time =
+ ath9k_hw_get_tsf_offset(&ts, NULL);
+ }
+ if (send_ps)
+ ath_chanctx_send_ps_frame(sc, false);
+
+ ath_offchannel_channel_change(sc);
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_SWITCH);
+}
+
+void ath_chanctx_work(struct work_struct *work)
+{
+ struct ath_softc *sc = container_of(work, struct ath_softc,
+ chanctx_work);
+ mutex_lock(&sc->mutex);
+ ath_chanctx_set_next(sc, false);
+ mutex_unlock(&sc->mutex);
+}
+
+void ath_chanctx_init(struct ath_softc *sc)
+{
+ struct ath_chanctx *ctx;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *chan;
+ int i, j;
+
+ sband = &common->sbands[IEEE80211_BAND_2GHZ];
+ if (!sband->n_channels)
+ sband = &common->sbands[IEEE80211_BAND_5GHZ];
+
+ chan = &sband->channels[0];
+ for (i = 0; i < ATH9K_NUM_CHANCTX; i++) {
+ ctx = &sc->chanctx[i];
+ cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
+ INIT_LIST_HEAD(&ctx->vifs);
+ ctx->txpower = ATH_TXPOWER_MAX;
+ for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
+ INIT_LIST_HEAD(&ctx->acq[j]);
+ }
+ ctx = &sc->offchannel.chan;
+ cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
+ INIT_LIST_HEAD(&ctx->vifs);
+ ctx->txpower = ATH_TXPOWER_MAX;
+ for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
+ INIT_LIST_HEAD(&ctx->acq[j]);
+ sc->offchannel.chan.offchannel = true;
+
+}
+
+void ath9k_chanctx_force_active(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
+ bool changed = false;
+
+ if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
+ return;
+
+ if (!avp->chanctx)
+ return;
+
+ mutex_lock(&sc->mutex);
+
+ spin_lock_bh(&sc->chan_lock);
+ if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
+ sc->next_chan = avp->chanctx;
+ changed = true;
+ }
+ sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
+ spin_unlock_bh(&sc->chan_lock);
+
+ if (changed)
+ ath_chanctx_set_next(sc, true);
+
+ mutex_unlock(&sc->mutex);
+}
+
+void ath_chanctx_switch(struct ath_softc *sc, struct ath_chanctx *ctx,
+ struct cfg80211_chan_def *chandef)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ spin_lock_bh(&sc->chan_lock);
+
+ if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) &&
+ (sc->cur_chan != ctx) && (ctx == &sc->offchannel.chan)) {
+ sc->sched.offchannel_pending = true;
+ spin_unlock_bh(&sc->chan_lock);
+ return;
+ }
+
+ sc->next_chan = ctx;
+ if (chandef)
+ ctx->chandef = *chandef;
+
+ if (sc->next_chan == &sc->offchannel.chan) {
+ sc->sched.offchannel_duration =
+ TU_TO_USEC(sc->offchannel.duration) +
+ sc->sched.channel_switch_time;
+ }
+ spin_unlock_bh(&sc->chan_lock);
+ ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+}
+
+void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx,
+ struct cfg80211_chan_def *chandef)
+{
+ bool cur_chan;
+
+ spin_lock_bh(&sc->chan_lock);
+ if (chandef)
+ memcpy(&ctx->chandef, chandef, sizeof(*chandef));
+ cur_chan = sc->cur_chan == ctx;
+ spin_unlock_bh(&sc->chan_lock);
+
+ if (!cur_chan)
+ return;
+
+ ath_set_channel(sc);
+}
+
+struct ath_chanctx *ath_chanctx_get_oper_chan(struct ath_softc *sc, bool active)
+{
+ struct ath_chanctx *ctx;
+
+ ath_for_each_chanctx(sc, ctx) {
+ if (!ctx->assigned || list_empty(&ctx->vifs))
+ continue;
+ if (active && !ctx->active)
+ continue;
+
+ if (ctx->switch_after_beacon)
+ return ctx;
+ }
+
+ return &sc->chanctx[0];
+}
+
+void ath_chanctx_offchan_switch(struct ath_softc *sc,
+ struct ieee80211_channel *chan)
+{
+ struct cfg80211_chan_def chandef;
+
+ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+
+ ath_chanctx_switch(sc, &sc->offchannel.chan, &chandef);
+}
+
+static struct ath_chanctx *
+ath_chanctx_get_next(struct ath_softc *sc, struct ath_chanctx *ctx)
+{
+ int idx = ctx - &sc->chanctx[0];
+
+ return &sc->chanctx[!idx];
+}
+
+static void ath_chanctx_adjust_tbtt_delta(struct ath_softc *sc)
+{
+ struct ath_chanctx *prev, *cur;
+ struct timespec ts;
+ u32 cur_tsf, prev_tsf, beacon_int;
+ s32 offset;
+
+ beacon_int = TU_TO_USEC(sc->cur_chan->beacon.beacon_interval);
+
+ cur = sc->cur_chan;
+ prev = ath_chanctx_get_next(sc, cur);
+
+ getrawmonotonic(&ts);
+ cur_tsf = (u32) cur->tsf_val +
+ ath9k_hw_get_tsf_offset(&cur->tsf_ts, &ts);
+
+ prev_tsf = prev->last_beacon - (u32) prev->tsf_val + cur_tsf;
+ prev_tsf -= ath9k_hw_get_tsf_offset(&prev->tsf_ts, &ts);
+
+ /* Adjust the TSF time of the AP chanctx to keep its beacons
+ * at half beacon interval offset relative to the STA chanctx.
+ */
+ offset = cur_tsf - prev_tsf;
+
+ /* Ignore stale data or spurious timestamps */
+ if (offset < 0 || offset > 3 * beacon_int)
+ return;
+
+ offset = beacon_int / 2 - (offset % beacon_int);
+ prev->tsf_val += offset;
+}
+
+void ath_chanctx_timer(unsigned long data)
+{
+ struct ath_softc *sc = (struct ath_softc *) data;
+
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
+}
+
+/* Configure the TSF based hardware timer for a channel switch.
+ * Also set up backup software timer, in case the gen timer fails.
+ * This could be caused by a hardware reset.
+ */
+static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
+ tsf_time -= ath9k_hw_gettsf32(ah);
+ tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
+ mod_timer(&sc->sched.timer, tsf_time);
+}
+
+void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
+ enum ath_chanctx_event ev)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_beacon_config *cur_conf;
+ struct ath_vif *avp = NULL;
+ struct ath_chanctx *ctx;
+ u32 tsf_time;
+ u32 beacon_int;
+ bool noa_changed = false;
+
+ if (vif)
+ avp = (struct ath_vif *) vif->drv_priv;
+
+ spin_lock_bh(&sc->chan_lock);
+
+ switch (ev) {
+ case ATH_CHANCTX_EVENT_BEACON_PREPARE:
+ if (avp->offchannel_duration)
+ avp->offchannel_duration = 0;
+
+ if (avp->chanctx != sc->cur_chan)
+ break;
+
+ if (sc->sched.offchannel_pending) {
+ sc->sched.offchannel_pending = false;
+ sc->next_chan = &sc->offchannel.chan;
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+ }
+
+ ctx = ath_chanctx_get_next(sc, sc->cur_chan);
+ if (ctx->active && sc->sched.state == ATH_CHANCTX_STATE_IDLE) {
+ sc->next_chan = ctx;
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+ }
+
+ /* if the timer missed its window, use the next interval */
+ if (sc->sched.state == ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
+
+ if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
+ break;
+
+ sc->sched.beacon_pending = true;
+ sc->sched.next_tbtt = REG_READ(ah, AR_NEXT_TBTT_TIMER);
+
+ cur_conf = &sc->cur_chan->beacon;
+ beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
+
+ /* defer channel switch by a quarter beacon interval */
+ tsf_time = sc->sched.next_tbtt + beacon_int / 4;
+ sc->sched.switch_start_time = tsf_time;
+ sc->cur_chan->last_beacon = sc->sched.next_tbtt;
+
+ /* Prevent wrap-around issues */
+ if (avp->periodic_noa_duration &&
+ tsf_time - avp->periodic_noa_start > BIT(30))
+ avp->periodic_noa_duration = 0;
+
+ if (ctx->active && !avp->periodic_noa_duration) {
+ avp->periodic_noa_start = tsf_time;
+ avp->periodic_noa_duration =
+ TU_TO_USEC(cur_conf->beacon_interval) / 2 -
+ sc->sched.channel_switch_time;
+ noa_changed = true;
+ } else if (!ctx->active && avp->periodic_noa_duration) {
+ avp->periodic_noa_duration = 0;
+ noa_changed = true;
+ }
+
+ /* If at least two consecutive beacons were missed on the STA
+ * chanctx, stay on the STA channel for one extra beacon period,
+ * to resync the timer properly.
+ */
+ if (ctx->active && sc->sched.beacon_miss >= 2)
+ sc->sched.offchannel_duration = 3 * beacon_int / 2;
+
+ if (sc->sched.offchannel_duration) {
+ noa_changed = true;
+ avp->offchannel_start = tsf_time;
+ avp->offchannel_duration =
+ sc->sched.offchannel_duration;
+ }
+
+ if (noa_changed)
+ avp->noa_index++;
+ break;
+ case ATH_CHANCTX_EVENT_BEACON_SENT:
+ if (!sc->sched.beacon_pending)
+ break;
+
+ sc->sched.beacon_pending = false;
+ if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
+ break;
+
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
+ ath_chanctx_setup_timer(sc, sc->sched.switch_start_time);
+ break;
+ case ATH_CHANCTX_EVENT_TSF_TIMER:
+ if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_TIMER)
+ break;
+
+ if (!sc->cur_chan->switch_after_beacon &&
+ sc->sched.beacon_pending)
+ sc->sched.beacon_miss++;
+
+ sc->sched.state = ATH_CHANCTX_STATE_SWITCH;
+ ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+ break;
+ case ATH_CHANCTX_EVENT_BEACON_RECEIVED:
+ if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
+ sc->cur_chan == &sc->offchannel.chan)
+ break;
+
+ ath_chanctx_adjust_tbtt_delta(sc);
+ sc->sched.beacon_pending = false;
+ sc->sched.beacon_miss = 0;
+
+ /* TSF time might have been updated by the incoming beacon,
+ * need update the channel switch timer to reflect the change.
+ */
+ tsf_time = sc->sched.switch_start_time;
+ tsf_time -= (u32) sc->cur_chan->tsf_val +
+ ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
+ tsf_time += ath9k_hw_gettsf32(ah);
+
+
+ ath_chanctx_setup_timer(sc, tsf_time);
+ break;
+ case ATH_CHANCTX_EVENT_ASSOC:
+ if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
+ avp->chanctx != sc->cur_chan)
+ break;
+
+ sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+ /* fall through */
+ case ATH_CHANCTX_EVENT_SWITCH:
+ if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
+ sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
+ sc->cur_chan->switch_after_beacon ||
+ sc->cur_chan == &sc->offchannel.chan)
+ break;
+
+ /* If this is a station chanctx, stay active for a half
+ * beacon period (minus channel switch time)
+ */
+ sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
+ cur_conf = &sc->cur_chan->beacon;
+
+ sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_TIMER;
+
+ tsf_time = TU_TO_USEC(cur_conf->beacon_interval) / 2;
+ if (sc->sched.beacon_miss >= 2) {
+ sc->sched.beacon_miss = 0;
+ tsf_time *= 3;
+ }
+
+ tsf_time -= sc->sched.channel_switch_time;
+ tsf_time += ath9k_hw_gettsf32(sc->sc_ah);
+ sc->sched.switch_start_time = tsf_time;
+
+ ath_chanctx_setup_timer(sc, tsf_time);
+ sc->sched.beacon_pending = true;
+ break;
+ case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
+ if (sc->cur_chan == &sc->offchannel.chan ||
+ sc->cur_chan->switch_after_beacon)
+ break;
+
+ sc->next_chan = ath_chanctx_get_next(sc, sc->cur_chan);
+ ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+ break;
+ case ATH_CHANCTX_EVENT_UNASSIGN:
+ if (sc->cur_chan->assigned) {
+ if (sc->next_chan && !sc->next_chan->assigned &&
+ sc->next_chan != &sc->offchannel.chan)
+ sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+ break;
+ }
+
+ ctx = ath_chanctx_get_next(sc, sc->cur_chan);
+ sc->sched.state = ATH_CHANCTX_STATE_IDLE;
+ if (!ctx->assigned)
+ break;
+
+ sc->next_chan = ctx;
+ ieee80211_queue_work(sc->hw, &sc->chanctx_work);
+ break;
+ }
+
+ spin_unlock_bh(&sc->chan_lock);
+}
diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.c b/drivers/net/wireless/ath/ath9k/common-beacon.c
index 775d1d20ce0b..733be5178481 100644
--- a/drivers/net/wireless/ath/ath9k/common-beacon.c
+++ b/drivers/net/wireless/ath/ath9k/common-beacon.c
@@ -57,7 +57,7 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah,
struct ath9k_beacon_state *bs)
{
struct ath_common *common = ath9k_hw_common(ah);
- int dtim_intval;
+ int dtim_intval, sleepduration;
u64 tsf;
/* No need to configure beacon if we are not associated */
@@ -75,6 +75,7 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah,
* last beacon we received (which may be none).
*/
dtim_intval = conf->intval * conf->dtim_period;
+ sleepduration = ah->hw->conf.listen_interval * conf->intval;
/*
* Pull nexttbtt forward to reflect the current
@@ -112,7 +113,7 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah,
*/
bs->bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100),
- conf->intval));
+ sleepduration));
if (bs->bs_sleepduration > bs->bs_dtimperiod)
bs->bs_sleepduration = bs->bs_dtimperiod;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 6cc42be48d4e..d2279365be6f 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file,
if (kstrtoul(buf, 0, &ani))
return -EINVAL;
- if (ani < 0 || ani > 1)
+ if (ani > 1)
return -EINVAL;
common->disable_ani = !ani;
@@ -750,13 +750,13 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
{
struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ieee80211_hw *hw = sc->hw;
struct ath9k_vif_iter_data iter_data;
+ struct ath_chanctx *ctx;
char buf[512];
unsigned int len = 0;
ssize_t retval = 0;
unsigned int reg;
- u32 rxfilter;
+ u32 rxfilter, i;
len += scnprintf(buf + len, sizeof(buf) - len,
"BSSID: %pM\n", common->curbssid);
@@ -826,14 +826,20 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, sizeof(buf) - len, "\n");
- ath9k_calculate_iter_data(hw, NULL, &iter_data);
-
- len += scnprintf(buf + len, sizeof(buf) - len,
- "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
- " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
- iter_data.naps, iter_data.nstations, iter_data.nmeshes,
- iter_data.nwds, iter_data.nadhocs,
- sc->nvifs, sc->nbcnvifs);
+ i = 0;
+ ath_for_each_chanctx(sc, ctx) {
+ if (!ctx->assigned || list_empty(&ctx->vifs))
+ continue;
+ ath9k_calculate_iter_data(sc, ctx, &iter_data);
+
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i",
+ i++, iter_data.naps, iter_data.nstations,
+ iter_data.nmeshes, iter_data.nwds);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+ iter_data.nadhocs, sc->nvifs, sc->nbcnvifs);
+ }
if (len > sizeof(buf))
len = sizeof(buf);
@@ -1080,7 +1086,7 @@ static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
- struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+ struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
u32 len = 0, size = 1500;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2a8ed8375ec0..69bbea1184d2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -791,7 +791,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
refdiv = 5;
} else {
pll2_divint = 0x11;
- pll2_divfrac = 0x26666;
+ pll2_divfrac =
+ AR_SREV_9531(ah) ? 0x26665 : 0x26666;
refdiv = 1;
}
}
@@ -1730,11 +1731,27 @@ fail:
return -EINVAL;
}
+u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur)
+{
+ struct timespec ts;
+ s64 usec;
+
+ if (!cur) {
+ getrawmonotonic(&ts);
+ cur = &ts;
+ }
+
+ usec = cur->tv_sec * 1000000ULL + cur->tv_nsec / 1000;
+ usec -= last->tv_sec * 1000000ULL + last->tv_nsec / 1000;
+
+ return (u32) usec;
+}
+EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool fastcc)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct timespec ts;
u32 saveLedState;
u32 saveDefAntenna;
u32 macStaId1;
@@ -1784,8 +1801,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
/* Save TSF before chip reset, a cold reset clears it */
tsf = ath9k_hw_gettsf64(ah);
- getrawmonotonic(&ts);
- usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
+ usec = ktime_to_us(ktime_get_raw());
saveLedState = REG_READ(ah, AR_CFG_LED) &
(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1818,8 +1834,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}
/* Restore TSF */
- getrawmonotonic(&ts);
- usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec;
+ usec = ktime_to_us(ktime_get_raw()) - usec;
ath9k_hw_settsf64(ah, tsf + usec);
if (AR_SREV_9280_20_OR_LATER(ah))
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 0acd4b5a4892..51b4ebe04c04 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -1000,6 +1000,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
u64 ath9k_hw_gettsf64(struct ath_hw *ah);
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
void ath9k_hw_reset_tsf(struct ath_hw *ah);
+u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
void ath9k_hw_init_global_settings(struct ath_hw *ah);
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 0246b990fe87..39419ea845cc 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -61,7 +61,7 @@ static int ath9k_ps_enable;
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
-static int ath9k_use_chanctx;
+int ath9k_use_chanctx;
module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444);
MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency");
@@ -169,9 +169,9 @@ static void ath9k_reg_notifier(struct wiphy *wiphy,
/* Set tx power */
if (ah->curchan) {
- sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
+ sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
ath9k_ps_wakeup(sc);
- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+ ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
/* synchronize DFS detector if regulatory domain changed */
if (sc->dfs_detector != NULL)
@@ -335,7 +335,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
- sc->config.txpowlimit = ATH_TXPOWER_MAX;
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
@@ -511,6 +510,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
sc->tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(&sc->tx_wait);
+ sc->cur_chan = &sc->chanctx[0];
+ if (!ath9k_use_chanctx)
+ sc->cur_chan->hw_queue_base = 0;
if (!pdata || pdata->use_eeprom) {
ah->ah_flags |= AH_USE_EEPROM;
@@ -556,6 +558,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->sc_pm_lock);
+ spin_lock_init(&sc->chan_lock);
mutex_init(&sc->mutex);
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
@@ -564,7 +567,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+ INIT_WORK(&sc->chanctx_work, ath_chanctx_work);
INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+ setup_timer(&sc->offchannel.timer, ath_offchannel_timer,
+ (unsigned long)sc);
+ setup_timer(&sc->sched.timer, ath_chanctx_timer, (unsigned long)sc);
/*
* Cache line size is used to size and align various
@@ -599,6 +606,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc);
ath_fill_led_pin(sc);
+ ath_chanctx_init(sc);
if (common->bus_ops->aspm_init)
common->bus_ops->aspm_init(common);
@@ -664,6 +672,12 @@ static const struct ieee80211_iface_limit wds_limits[] = {
{ .max = 2048, .types = BIT(NL80211_IFTYPE_WDS) },
};
+static const struct ieee80211_iface_limit if_limits_multi[] = {
+ { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) },
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
+};
+
static const struct ieee80211_iface_limit if_dfs_limits[] = {
{ .max = 1, .types = BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
@@ -672,6 +686,16 @@ static const struct ieee80211_iface_limit if_dfs_limits[] = {
BIT(NL80211_IFTYPE_ADHOC) },
};
+static const struct ieee80211_iface_combination if_comb_multi[] = {
+ {
+ .limits = if_limits_multi,
+ .n_limits = ARRAY_SIZE(if_limits_multi),
+ .max_interfaces = 2,
+ .num_different_channels = 2,
+ .beacon_int_infra_match = true,
+ },
+};
+
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
@@ -712,6 +736,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_RC_TABLE |
+ IEEE80211_HW_QUEUE_CONTROL |
IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
if (ath9k_ps_enable)
@@ -739,12 +764,21 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
- hw->wiphy->iface_combinations = if_comb;
if (!ath9k_use_chanctx) {
+ hw->wiphy->iface_combinations = if_comb;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS);
- } else
- hw->wiphy->n_iface_combinations = 1;
+ } else {
+ hw->wiphy->iface_combinations = if_comb_multi;
+ hw->wiphy->n_iface_combinations =
+ ARRAY_SIZE(if_comb_multi);
+ hw->wiphy->max_scan_ssids = 255;
+ hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+ hw->wiphy->max_remain_on_channel_duration = 10000;
+ hw->chanctx_data_size = sizeof(void *);
+ hw->extra_beacon_tailroom =
+ sizeof(struct ieee80211_p2p_noa_attr) + 9;
+ }
}
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -756,9 +790,14 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
- hw->queues = 4;
+ /* allow 4 queues per channel context +
+ * 1 cab queue + 1 offchannel tx queue
+ */
+ hw->queues = 10;
+ /* last queue for offchannel */
+ hw->offchannel_tx_hw_queue = hw->queues - 1;
hw->max_rates = 4;
- hw->max_listen_interval = 1;
+ hw->max_listen_interval = 10;
hw->max_rate_tries = 10;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 72a715fe8f24..2343f56e6498 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -178,7 +178,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
- tx_info->band = hw->conf.chandef.chan->band;
+ tx_info->band = sc->cur_chandef.chan->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
@@ -416,7 +416,7 @@ void ath_start_ani(struct ath_softc *sc)
if (common->disable_ani ||
!test_bit(ATH_OP_ANI_RUN, &common->op_flags) ||
- (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+ sc->cur_chan->offchannel)
return;
common->ani.longcal_timer = timestamp;
@@ -440,7 +440,7 @@ void ath_check_ani(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
/*
* Check for the various conditions in which ANI has to
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index da7686757535..6c56cafa5ca4 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -346,8 +346,14 @@ struct ar5416_desc {
#define AR_FrameLen 0x00000fff
#define AR_VirtMoreFrag 0x00001000
#define AR_TxCtlRsvd00 0x0000e000
-#define AR_XmitPower 0x003f0000
-#define AR_XmitPower_S 16
+#define AR_XmitPower0 0x003f0000
+#define AR_XmitPower0_S 16
+#define AR_XmitPower1 0x3f000000
+#define AR_XmitPower1_S 24
+#define AR_XmitPower2 0x3f000000
+#define AR_XmitPower2_S 24
+#define AR_XmitPower3 0x3f000000
+#define AR_XmitPower3_S 24
#define AR_RTSEnable 0x00400000
#define AR_VEOL 0x00800000
#define AR_ClrDestMask 0x01000000
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 62ac95d6bb9d..e6ac8d2e610c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -19,9 +19,6 @@
#include "ath9k.h"
#include "btcoex.h"
-static void ath9k_set_assoc_state(struct ath_softc *sc,
- struct ieee80211_vif *vif);
-
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
{
/*
@@ -63,9 +60,16 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
spin_lock_bh(&txq->axq_lock);
- if (txq->axq_depth || !list_empty(&txq->axq_acq))
+ if (txq->axq_depth)
pending = true;
+ if (txq->mac80211_qnum >= 0) {
+ struct list_head *list;
+
+ list = &sc->cur_chan->acq[txq->mac80211_qnum];
+ if (!list_empty(list))
+ pending = true;
+ }
spin_unlock_bh(&txq->axq_lock);
return pending;
}
@@ -227,13 +231,22 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
+ sc->cur_chan->txpower, &sc->curtxpow);
clear_bit(ATH_OP_HW_RESET, &common->op_flags);
- ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
+ ath9k_calculate_summary_state(sc, sc->cur_chan);
+
+ if (!sc->cur_chan->offchannel && start) {
+ /* restore per chanctx TSF timer */
+ if (sc->cur_chan->tsf_val) {
+ u32 offset;
+
+ offset = ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts,
+ NULL);
+ ath9k_hw_settsf64(ah, sc->cur_chan->tsf_val + offset);
+ }
+
- if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) {
if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
goto work;
@@ -247,26 +260,35 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
work:
ath_restart_work(sc);
+ ath_txq_schedule_all(sc);
+ }
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
+ sc->gtt_cnt = 0;
- spin_lock_bh(&sc->tx.txq[i].axq_lock);
- ath_txq_schedule(sc, &sc->tx.txq[i]);
- spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+ ath9k_hw_set_interrupts(ah);
+ ath9k_hw_enable_interrupts(ah);
+
+ if (!ath9k_use_chanctx)
+ ieee80211_wake_queues(sc->hw);
+ else {
+ if (sc->cur_chan == &sc->offchannel.chan)
+ ieee80211_wake_queue(sc->hw,
+ sc->hw->offchannel_tx_hw_queue);
+ else {
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ ieee80211_wake_queue(sc->hw,
+ sc->cur_chan->hw_queue_base + i);
}
+ if (ah->opmode == NL80211_IFTYPE_AP)
+ ieee80211_wake_queue(sc->hw, sc->hw->queues - 2);
}
- sc->gtt_cnt = 0;
- ieee80211_wake_queues(sc->hw);
-
ath9k_p2p_ps_timer(sc);
return true;
}
-static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -279,9 +301,9 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
tasklet_disable(&sc->intr_tq);
spin_lock_bh(&sc->sc_pcu_lock);
- if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
+ if (!sc->cur_chan->offchannel) {
fastcc = false;
- caldata = &sc->caldata;
+ caldata = &sc->cur_chan->caldata;
}
if (!hchan) {
@@ -292,6 +314,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
if (!ath_prepare_reset(sc))
fastcc = false;
+ spin_lock_bh(&sc->chan_lock);
+ sc->cur_chandef = sc->cur_chan->chandef;
+ spin_unlock_bh(&sc->chan_lock);
+
ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
hchan->channel, IS_CHAN_HT40(hchan), fastcc);
@@ -307,7 +333,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
}
if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
- (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+ sc->cur_chan->offchannel)
ath9k_mci_set_txpower(sc, true, false);
if (!ath_complete_reset(sc, true))
@@ -320,98 +346,6 @@ out:
return r;
}
-
-/*
- * Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
- * DMA, then restart stuff.
-*/
-static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef)
-{
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
- struct ath9k_channel *hchan;
- struct ieee80211_channel *chan = chandef->chan;
- bool offchannel;
- int pos = chan->hw_value;
- int old_pos = -1;
- int r;
-
- if (test_bit(ATH_OP_INVALID, &common->op_flags))
- return -EIO;
-
- offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
-
- if (ah->curchan)
- old_pos = ah->curchan - &ah->channels[0];
-
- ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
- chan->center_freq, chandef->width);
-
- /* update survey stats for the old channel before switching */
- spin_lock_bh(&common->cc_lock);
- ath_update_survey_stats(sc);
- spin_unlock_bh(&common->cc_lock);
-
- ath9k_cmn_get_channel(hw, ah, chandef);
-
- /*
- * If the operating channel changes, change the survey in-use flags
- * along with it.
- * Reset the survey data for the new channel, unless we're switching
- * back to the operating channel from an off-channel operation.
- */
- if (!offchannel && sc->cur_survey != &sc->survey[pos]) {
- if (sc->cur_survey)
- sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
-
- sc->cur_survey = &sc->survey[pos];
-
- memset(sc->cur_survey, 0, sizeof(struct survey_info));
- sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
- } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
- memset(&sc->survey[pos], 0, sizeof(struct survey_info));
- }
-
- hchan = &sc->sc_ah->channels[pos];
- r = ath_reset_internal(sc, hchan);
- if (r)
- return r;
-
- /*
- * The most recent snapshot of channel->noisefloor for the old
- * channel is only available after the hardware reset. Copy it to
- * the survey stats now.
- */
- if (old_pos >= 0)
- ath_update_survey_nf(sc, old_pos);
-
- /*
- * Enable radar pulse detection if on a DFS channel. Spectral
- * scanning and radar detection can not be used concurrently.
- */
- if (hw->conf.radar_enabled) {
- u32 rxfilter;
-
- /* set HW specific DFS configuration */
- ath9k_hw_set_radar_params(ah);
- rxfilter = ath9k_hw_getrxfilter(ah);
- rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
- ATH9K_RX_FILTER_PHYERR;
- ath9k_hw_setrxfilter(ah, rxfilter);
- ath_dbg(common, DFS, "DFS enabled at freq %d\n",
- chan->center_freq);
- } else {
- /* perform spectral scan if requested. */
- if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
- sc->spectral_mode == SPECTRAL_CHANSCAN)
- ath9k_spectral_scan_trigger(hw);
- }
-
- return 0;
-}
-
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{
@@ -712,7 +646,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
+ struct ath_chanctx *ctx = sc->cur_chan;
struct ath9k_channel *init_channel;
int r;
@@ -723,7 +658,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
- init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
+ init_channel = ath9k_cmn_get_channel(hw, ah, &ctx->chandef);
+ sc->cur_chandef = hw->conf.chandef;
/* Reset SERDES registers */
ath9k_hw_configpcipowersave(ah, false);
@@ -886,6 +822,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
struct ath_common *common = ath9k_hw_common(ah);
bool prev_idle;
+ cancel_work_sync(&sc->chanctx_work);
mutex_lock(&sc->mutex);
ath_cancel_work(sc);
@@ -934,7 +871,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
}
if (!ah->curchan)
- ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
+ ah->curchan = ath9k_cmn_get_channel(hw, ah,
+ &sc->cur_chan->chandef);
ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
ath9k_hw_phy_disable(ah);
@@ -979,18 +917,29 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
iter_data->has_hw_macaddr = true;
}
+ if (!vif->bss_conf.use_short_slot)
+ iter_data->slottime = ATH9K_SLOT_TIME_20;
+
switch (vif->type) {
case NL80211_IFTYPE_AP:
iter_data->naps++;
+ if (vif->bss_conf.enable_beacon)
+ iter_data->beacons = true;
break;
case NL80211_IFTYPE_STATION:
iter_data->nstations++;
+ if (vif->bss_conf.assoc && !iter_data->primary_sta)
+ iter_data->primary_sta = vif;
break;
case NL80211_IFTYPE_ADHOC:
iter_data->nadhocs++;
+ if (vif->bss_conf.enable_beacon)
+ iter_data->beacons = true;
break;
case NL80211_IFTYPE_MESH_POINT:
iter_data->nmeshes++;
+ if (vif->bss_conf.enable_beacon)
+ iter_data->beacons = true;
break;
case NL80211_IFTYPE_WDS:
iter_data->nwds++;
@@ -1000,26 +949,12 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
}
}
-static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
- struct ath_softc *sc = data;
- struct ath_vif *avp = (void *)vif->drv_priv;
-
- if (vif->type != NL80211_IFTYPE_STATION)
- return;
-
- if (avp->primary_sta_vif)
- ath9k_set_assoc_state(sc, vif);
-}
-
/* Called with sc->mutex held. */
-void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
+void ath9k_calculate_iter_data(struct ath_softc *sc,
+ struct ath_chanctx *ctx,
struct ath9k_vif_iter_data *iter_data)
{
- struct ath_softc *sc = hw->priv;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
+ struct ath_vif *avp;
/*
* Pick the MAC address of the first interface as the new hardware
@@ -1028,29 +963,80 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
*/
memset(iter_data, 0, sizeof(*iter_data));
memset(&iter_data->mask, 0xff, ETH_ALEN);
+ iter_data->slottime = ATH9K_SLOT_TIME_9;
+
+ list_for_each_entry(avp, &ctx->vifs, list)
+ ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
+
+ if (ctx == &sc->offchannel.chan) {
+ struct ieee80211_vif *vif;
+
+ if (sc->offchannel.state < ATH_OFFCHANNEL_ROC_START)
+ vif = sc->offchannel.scan_vif;
+ else
+ vif = sc->offchannel.roc_vif;
+
+ if (vif)
+ ath9k_vif_iter(iter_data, vif->addr, vif);
+ iter_data->beacons = false;
+ }
+}
+
+static void ath9k_set_assoc_state(struct ath_softc *sc,
+ struct ieee80211_vif *vif, bool changed)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+ unsigned long flags;
- if (vif)
- ath9k_vif_iter(iter_data, vif->addr, vif);
+ set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+ /* Set the AID, BSSID and do beacon-sync only when
+ * the HW opmode is STATION.
+ *
+ * But the primary bit is set above in any case.
+ */
+ if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
+ ether_addr_copy(common->curbssid, bss_conf->bssid);
+ common->curaid = bss_conf->aid;
+ ath9k_hw_write_associd(sc->sc_ah);
- /* Get list of all active MAC addresses */
- ieee80211_iterate_active_interfaces_atomic(
- sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
- ath9k_vif_iter, iter_data);
+ if (changed) {
+ common->last_rssi = ATH_RSSI_DUMMY_MARKER;
+ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
- memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ }
+
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ ath9k_mci_update_wlan_channels(sc, false);
+
+ ath_dbg(common, CONFIG,
+ "Primary Station interface: %pM, BSSID: %pM\n",
+ vif->addr, common->curbssid);
}
/* Called with sc->mutex held. */
-static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void ath9k_calculate_summary_state(struct ath_softc *sc,
+ struct ath_chanctx *ctx)
{
- struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_vif_iter_data iter_data;
- enum nl80211_iftype old_opmode = ah->opmode;
- ath9k_calculate_iter_data(hw, vif, &iter_data);
+ ath_chanctx_check_active(sc, ctx);
+
+ if (ctx != sc->cur_chan)
+ return;
+
+ ath9k_ps_wakeup(sc);
+ ath9k_calculate_iter_data(sc, ctx, &iter_data);
+
+ if (iter_data.has_hw_macaddr)
+ ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
ath_hw_setbssidmask(common);
@@ -1073,24 +1059,57 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ath9k_hw_setopmode(ah);
+ ctx->switch_after_beacon = false;
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
ah->imask |= ATH9K_INT_TSFOOR;
- else
+ else {
ah->imask &= ~ATH9K_INT_TSFOOR;
+ if (iter_data.naps == 1 && iter_data.beacons)
+ ctx->switch_after_beacon = true;
+ }
+
+ ah->imask &= ~ATH9K_INT_SWBA;
+ if (ah->opmode == NL80211_IFTYPE_STATION) {
+ bool changed = (iter_data.primary_sta != ctx->primary_sta);
+ iter_data.beacons = true;
+ if (iter_data.primary_sta) {
+ ath9k_set_assoc_state(sc, iter_data.primary_sta,
+ changed);
+ if (!ctx->primary_sta ||
+ !ctx->primary_sta->bss_conf.assoc)
+ ctx->primary_sta = iter_data.primary_sta;
+ } else {
+ ctx->primary_sta = NULL;
+ memset(common->curbssid, 0, ETH_ALEN);
+ common->curaid = 0;
+ ath9k_hw_write_associd(sc->sc_ah);
+ if (ath9k_hw_mci_is_enabled(sc->sc_ah))
+ ath9k_mci_update_wlan_channels(sc, true);
+ }
+ } else if (iter_data.beacons) {
+ ah->imask |= ATH9K_INT_SWBA;
+ }
ath9k_hw_set_interrupts(ah);
- /*
- * If we are changing the opmode to STATION,
- * a beacon sync needs to be done.
- */
- if (ah->opmode == NL80211_IFTYPE_STATION &&
- old_opmode == NL80211_IFTYPE_AP &&
- test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
- ieee80211_iterate_active_interfaces_atomic(
- sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
- ath9k_sta_vif_iter, sc);
+ if (iter_data.beacons)
+ set_bit(ATH_OP_BEACONS, &common->op_flags);
+ else
+ clear_bit(ATH_OP_BEACONS, &common->op_flags);
+
+ if (ah->slottime != iter_data.slottime) {
+ ah->slottime = iter_data.slottime;
+ ath9k_hw_init_global_settings(ah);
}
+
+ if (iter_data.primary_sta)
+ set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+ else
+ clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
+
+ ctx->primary_sta = iter_data.primary_sta;
+
+ ath9k_ps_restore(sc);
}
static int ath9k_add_interface(struct ieee80211_hw *hw,
@@ -1101,6 +1120,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
struct ath_node *an = &avp->mcast_node;
+ int i;
mutex_lock(&sc->mutex);
@@ -1115,14 +1135,20 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
sc->nvifs++;
- ath9k_ps_wakeup(sc);
- ath9k_calculate_summary_state(hw, vif);
- ath9k_ps_restore(sc);
-
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
avp->vif = vif;
+ if (!ath9k_use_chanctx) {
+ avp->chanctx = sc->cur_chan;
+ list_add_tail(&avp->list, &avp->chanctx->vifs);
+ }
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ vif->hw_queue[i] = i;
+ if (vif->type == NL80211_IFTYPE_AP)
+ vif->cab_queue = hw->queues - 2;
+ else
+ vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
an->sc = sc;
an->sta = NULL;
@@ -1141,6 +1167,8 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_vif *avp = (void *)vif->drv_priv;
+ int i;
mutex_lock(&sc->mutex);
@@ -1157,13 +1185,19 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
vif->type = new_type;
vif->p2p = p2p;
- ath9k_ps_wakeup(sc);
- ath9k_calculate_summary_state(hw, vif);
- ath9k_ps_restore(sc);
-
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ vif->hw_queue[i] = i;
+
+ if (vif->type == NL80211_IFTYPE_AP)
+ vif->cab_queue = hw->queues - 2;
+ else
+ vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
+
+ ath9k_calculate_summary_state(sc, avp->chanctx);
+
mutex_unlock(&sc->mutex);
return 0;
}
@@ -1211,14 +1245,12 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
sc->nvifs--;
sc->tx99_vif = NULL;
+ if (!ath9k_use_chanctx)
+ list_del(&avp->list);
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_remove_slot(sc, vif);
- ath9k_ps_wakeup(sc);
- ath9k_calculate_summary_state(hw, NULL);
- ath9k_ps_restore(sc);
-
ath_tx_node_cleanup(sc, &avp->mcast_node);
mutex_unlock(&sc->mutex);
@@ -1345,7 +1377,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf;
- bool reset_channel = false;
+ struct ath_chanctx *ctx = sc->cur_chan;
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
@@ -1361,7 +1393,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
* The chip needs a reset to properly wake up from
* full sleep
*/
- reset_channel = ah->chip_fullsleep;
+ ath_chanctx_set_channel(sc, ctx, &ctx->chandef);
}
}
@@ -1391,20 +1423,16 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
}
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
- if (ath_set_channel(sc, &hw->conf.chandef) < 0) {
- ath_err(common, "Unable to set channel\n");
- mutex_unlock(&sc->mutex);
- ath9k_ps_restore(sc);
- return -EINVAL;
- }
+ if (!ath9k_use_chanctx && (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+ ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL);
+ ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
- sc->config.txpowlimit = 2 * conf->power_level;
+ sc->cur_chan->txpower = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
+ sc->cur_chan->txpower, &sc->curtxpow);
}
mutex_unlock(&sc->mutex);
@@ -1659,58 +1687,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
return ret;
}
-static void ath9k_set_assoc_state(struct ath_softc *sc,
- struct ieee80211_vif *vif)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_vif *avp = (void *)vif->drv_priv;
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
- unsigned long flags;
-
- set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
- avp->primary_sta_vif = true;
-
- /*
- * Set the AID, BSSID and do beacon-sync only when
- * the HW opmode is STATION.
- *
- * But the primary bit is set above in any case.
- */
- if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
- return;
-
- memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
- common->curaid = bss_conf->aid;
- ath9k_hw_write_associd(sc->sc_ah);
-
- common->last_rssi = ATH_RSSI_DUMMY_MARKER;
- sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
-
- spin_lock_irqsave(&sc->sc_pm_lock, flags);
- sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
-
- if (ath9k_hw_mci_is_enabled(sc->sc_ah))
- ath9k_mci_update_wlan_channels(sc, false);
-
- ath_dbg(common, CONFIG,
- "Primary Station interface: %pM, BSSID: %pM\n",
- vif->addr, common->curbssid);
-}
-
-static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
- struct ath_softc *sc = data;
- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- if (test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
- return;
-
- if (bss_conf->assoc)
- ath9k_set_assoc_state(sc, vif);
-}
-
void ath9k_p2p_ps_timer(void *priv)
{
struct ath_softc *sc = priv;
@@ -1720,7 +1696,11 @@ void ath9k_p2p_ps_timer(void *priv)
struct ath_node *an;
u32 tsf;
- if (!avp)
+ del_timer_sync(&sc->sched.timer);
+ ath9k_hw_gen_timer_stop(sc->sc_ah, sc->p2p_ps_timer);
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
+
+ if (!avp || avp->chanctx != sc->cur_chan)
return;
tsf = ath9k_hw_gettsf32(sc->sc_ah);
@@ -1795,26 +1775,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
bss_conf->bssid, bss_conf->assoc);
- if (avp->primary_sta_vif && !bss_conf->assoc) {
- clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
- avp->primary_sta_vif = false;
-
- if (ah->opmode == NL80211_IFTYPE_STATION)
- clear_bit(ATH_OP_BEACONS, &common->op_flags);
- }
-
- ieee80211_iterate_active_interfaces_atomic(
- sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
- ath9k_bss_assoc_iter, sc);
-
- if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags) &&
- ah->opmode == NL80211_IFTYPE_STATION) {
- memset(common->curbssid, 0, ETH_ALEN);
- common->curaid = 0;
- ath9k_hw_write_associd(sc->sc_ah);
- if (ath9k_hw_mci_is_enabled(sc->sc_ah))
- ath9k_mci_update_wlan_channels(sc, true);
- }
+ ath9k_calculate_summary_state(sc, avp->chanctx);
+ if (bss_conf->assoc)
+ ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_ASSOC);
}
if (changed & BSS_CHANGED_IBSS) {
@@ -1824,10 +1787,15 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
}
if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
- (changed & BSS_CHANGED_BEACON_INT))
+ (changed & BSS_CHANGED_BEACON_INT) ||
+ (changed & BSS_CHANGED_BEACON_INFO)) {
+ if (changed & BSS_CHANGED_BEACON_ENABLED)
+ ath9k_calculate_summary_state(sc, avp->chanctx);
ath9k_beacon_config(sc, vif, changed);
+ }
- if (changed & BSS_CHANGED_ERP_SLOT) {
+ if ((avp->chanctx == sc->cur_chan) &&
+ (changed & BSS_CHANGED_ERP_SLOT)) {
if (bss_conf->use_short_slot)
slottime = 9;
else
@@ -2032,23 +2000,30 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
+
+ mutex_lock(&sc->mutex);
+ __ath9k_flush(hw, queues, drop);
+ mutex_unlock(&sc->mutex);
+}
+
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
+{
+ struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
int timeout = HZ / 5; /* 200 ms */
bool drain_txq;
+ int i;
- mutex_lock(&sc->mutex);
cancel_delayed_work_sync(&sc->tx_complete_work);
if (ah->ah_flags & AH_UNPLUGGED) {
ath_dbg(common, ANY, "Device has been unplugged!\n");
- mutex_unlock(&sc->mutex);
return;
}
if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
ath_dbg(common, ANY, "Device not present\n");
- mutex_unlock(&sc->mutex);
return;
}
@@ -2066,11 +2041,13 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
ath_reset(sc);
ath9k_ps_restore(sc);
- ieee80211_wake_queues(hw);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ ieee80211_wake_queue(sc->hw,
+ sc->cur_chan->hw_queue_base + i);
+ }
}
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
- mutex_unlock(&sc->mutex);
}
static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
@@ -2230,6 +2207,403 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
clear_bit(ATH_OP_SCANNING, &common->op_flags);
}
+static int ath_scan_channel_duration(struct ath_softc *sc,
+ struct ieee80211_channel *chan)
+{
+ struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+
+ if (!req->n_ssids || (chan->flags & IEEE80211_CHAN_NO_IR))
+ return (HZ / 9); /* ~110 ms */
+
+ return (HZ / 16); /* ~60 ms */
+}
+
+static void
+ath_scan_next_channel(struct ath_softc *sc)
+{
+ struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+ struct ieee80211_channel *chan;
+
+ if (sc->offchannel.scan_idx >= req->n_channels) {
+ sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+ ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
+ NULL);
+ return;
+ }
+
+ chan = req->channels[sc->offchannel.scan_idx++];
+ sc->offchannel.duration = ath_scan_channel_duration(sc, chan);
+ sc->offchannel.state = ATH_OFFCHANNEL_PROBE_SEND;
+ ath_chanctx_offchan_switch(sc, chan);
+}
+
+static void ath_offchannel_next(struct ath_softc *sc)
+{
+ struct ieee80211_vif *vif;
+
+ if (sc->offchannel.scan_req) {
+ vif = sc->offchannel.scan_vif;
+ sc->offchannel.chan.txpower = vif->bss_conf.txpower;
+ ath_scan_next_channel(sc);
+ } else if (sc->offchannel.roc_vif) {
+ vif = sc->offchannel.roc_vif;
+ sc->offchannel.chan.txpower = vif->bss_conf.txpower;
+ sc->offchannel.duration = sc->offchannel.roc_duration;
+ sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
+ ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
+ } else {
+ ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
+ NULL);
+ sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+ if (sc->ps_idle)
+ ath_cancel_work(sc);
+ }
+}
+
+static void ath_roc_complete(struct ath_softc *sc, bool abort)
+{
+ sc->offchannel.roc_vif = NULL;
+ sc->offchannel.roc_chan = NULL;
+ if (!abort)
+ ieee80211_remain_on_channel_expired(sc->hw);
+ ath_offchannel_next(sc);
+ ath9k_ps_restore(sc);
+}
+
+static void ath_scan_complete(struct ath_softc *sc, bool abort)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+
+ sc->offchannel.scan_req = NULL;
+ sc->offchannel.scan_vif = NULL;
+ sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
+ ieee80211_scan_completed(sc->hw, abort);
+ clear_bit(ATH_OP_SCANNING, &common->op_flags);
+ ath_offchannel_next(sc);
+ ath9k_ps_restore(sc);
+}
+
+static void ath_scan_send_probe(struct ath_softc *sc,
+ struct cfg80211_ssid *ssid)
+{
+ struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+ struct ieee80211_vif *vif = sc->offchannel.scan_vif;
+ struct ath_tx_control txctl = {};
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *info;
+ int band = sc->offchannel.chan.chandef.chan->band;
+
+ skb = ieee80211_probereq_get(sc->hw, vif,
+ ssid->ssid, ssid->ssid_len, req->ie_len);
+ if (!skb)
+ return;
+
+ info = IEEE80211_SKB_CB(skb);
+ if (req->no_cck)
+ info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
+
+ if (req->ie_len)
+ memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
+
+ skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+
+ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL))
+ goto error;
+
+ txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
+ txctl.force_channel = true;
+ if (ath_tx_start(sc->hw, skb, &txctl))
+ goto error;
+
+ return;
+
+error:
+ ieee80211_free_txskb(sc->hw, skb);
+}
+
+static void ath_scan_channel_start(struct ath_softc *sc)
+{
+ struct cfg80211_scan_request *req = sc->offchannel.scan_req;
+ int i;
+
+ if (!(sc->cur_chan->chandef.chan->flags & IEEE80211_CHAN_NO_IR) &&
+ req->n_ssids) {
+ for (i = 0; i < req->n_ssids; i++)
+ ath_scan_send_probe(sc, &req->ssids[i]);
+
+ }
+
+ sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT;
+ mod_timer(&sc->offchannel.timer, jiffies + sc->offchannel.duration);
+}
+
+void ath_offchannel_channel_change(struct ath_softc *sc)
+{
+ switch (sc->offchannel.state) {
+ case ATH_OFFCHANNEL_PROBE_SEND:
+ if (!sc->offchannel.scan_req)
+ return;
+
+ if (sc->cur_chan->chandef.chan !=
+ sc->offchannel.chan.chandef.chan)
+ return;
+
+ ath_scan_channel_start(sc);
+ break;
+ case ATH_OFFCHANNEL_IDLE:
+ if (!sc->offchannel.scan_req)
+ return;
+
+ ath_scan_complete(sc, false);
+ break;
+ case ATH_OFFCHANNEL_ROC_START:
+ if (sc->cur_chan != &sc->offchannel.chan)
+ break;
+
+ sc->offchannel.state = ATH_OFFCHANNEL_ROC_WAIT;
+ mod_timer(&sc->offchannel.timer, jiffies +
+ msecs_to_jiffies(sc->offchannel.duration));
+ ieee80211_ready_on_channel(sc->hw);
+ break;
+ case ATH_OFFCHANNEL_ROC_DONE:
+ ath_roc_complete(sc, false);
+ break;
+ default:
+ break;
+ }
+}
+
+void ath_offchannel_timer(unsigned long data)
+{
+ struct ath_softc *sc = (struct ath_softc *)data;
+ struct ath_chanctx *ctx;
+
+ switch (sc->offchannel.state) {
+ case ATH_OFFCHANNEL_PROBE_WAIT:
+ if (!sc->offchannel.scan_req)
+ return;
+
+ /* get first active channel context */
+ ctx = ath_chanctx_get_oper_chan(sc, true);
+ if (ctx->active) {
+ sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND;
+ ath_chanctx_switch(sc, ctx, NULL);
+ mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
+ break;
+ }
+ /* fall through */
+ case ATH_OFFCHANNEL_SUSPEND:
+ if (!sc->offchannel.scan_req)
+ return;
+
+ ath_scan_next_channel(sc);
+ break;
+ case ATH_OFFCHANNEL_ROC_START:
+ case ATH_OFFCHANNEL_ROC_WAIT:
+ ctx = ath_chanctx_get_oper_chan(sc, false);
+ sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
+ ath_chanctx_switch(sc, ctx, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *hw_req)
+{
+ struct cfg80211_scan_request *req = &hw_req->req;
+ struct ath_softc *sc = hw->priv;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ int ret = 0;
+
+ mutex_lock(&sc->mutex);
+
+ if (WARN_ON(sc->offchannel.scan_req)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ath9k_ps_wakeup(sc);
+ set_bit(ATH_OP_SCANNING, &common->op_flags);
+ sc->offchannel.scan_vif = vif;
+ sc->offchannel.scan_req = req;
+ sc->offchannel.scan_idx = 0;
+
+ if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
+ ath_offchannel_next(sc);
+
+out:
+ mutex_unlock(&sc->mutex);
+
+ return ret;
+}
+
+static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath_softc *sc = hw->priv;
+
+ mutex_lock(&sc->mutex);
+ del_timer_sync(&sc->offchannel.timer);
+ ath_scan_complete(sc, true);
+ mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_remain_on_channel(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, int duration,
+ enum ieee80211_roc_type type)
+{
+ struct ath_softc *sc = hw->priv;
+ int ret = 0;
+
+ mutex_lock(&sc->mutex);
+
+ if (WARN_ON(sc->offchannel.roc_vif)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ath9k_ps_wakeup(sc);
+ sc->offchannel.roc_vif = vif;
+ sc->offchannel.roc_chan = chan;
+ sc->offchannel.roc_duration = duration;
+
+ if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
+ ath_offchannel_next(sc);
+
+out:
+ mutex_unlock(&sc->mutex);
+
+ return ret;
+}
+
+static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+ struct ath_softc *sc = hw->priv;
+
+ mutex_lock(&sc->mutex);
+
+ del_timer_sync(&sc->offchannel.timer);
+
+ if (sc->offchannel.roc_vif) {
+ if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
+ ath_roc_complete(sc, true);
+ }
+
+ mutex_unlock(&sc->mutex);
+
+ return 0;
+}
+
+static int ath9k_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_chanctx *ctx, **ptr;
+ int pos;
+
+ mutex_lock(&sc->mutex);
+
+ ath_for_each_chanctx(sc, ctx) {
+ if (ctx->assigned)
+ continue;
+
+ ptr = (void *) conf->drv_priv;
+ *ptr = ctx;
+ ctx->assigned = true;
+ pos = ctx - &sc->chanctx[0];
+ ctx->hw_queue_base = pos * IEEE80211_NUM_ACS;
+ ath_chanctx_set_channel(sc, ctx, &conf->def);
+ mutex_unlock(&sc->mutex);
+ return 0;
+ }
+ mutex_unlock(&sc->mutex);
+ return -ENOSPC;
+}
+
+
+static void ath9k_remove_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_chanctx *ctx = ath_chanctx_get(conf);
+
+ mutex_lock(&sc->mutex);
+ ctx->assigned = false;
+ ctx->hw_queue_base = -1;
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
+ mutex_unlock(&sc->mutex);
+}
+
+static void ath9k_change_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *conf,
+ u32 changed)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_chanctx *ctx = ath_chanctx_get(conf);
+
+ mutex_lock(&sc->mutex);
+ ath_chanctx_set_channel(sc, ctx, &conf->def);
+ mutex_unlock(&sc->mutex);
+}
+
+static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_chanctx *ctx = ath_chanctx_get(conf);
+ int i;
+
+ mutex_lock(&sc->mutex);
+ avp->chanctx = ctx;
+ list_add_tail(&avp->list, &ctx->vifs);
+ ath9k_calculate_summary_state(sc, ctx);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ vif->hw_queue[i] = ctx->hw_queue_base + i;
+ mutex_unlock(&sc->mutex);
+
+ return 0;
+}
+
+static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *conf)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_chanctx *ctx = ath_chanctx_get(conf);
+ int ac;
+
+ mutex_lock(&sc->mutex);
+ avp->chanctx = NULL;
+ list_del(&avp->list);
+ ath9k_calculate_summary_state(sc, ctx);
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+ vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
+ mutex_unlock(&sc->mutex);
+}
+
+void ath9k_fill_chanctx_ops(void)
+{
+ if (!ath9k_use_chanctx)
+ return;
+
+ ath9k_ops.hw_scan = ath9k_hw_scan;
+ ath9k_ops.cancel_hw_scan = ath9k_cancel_hw_scan;
+ ath9k_ops.remain_on_channel = ath9k_remain_on_channel;
+ ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
+ ath9k_ops.add_chanctx = ath9k_add_chanctx;
+ ath9k_ops.remove_chanctx = ath9k_remove_chanctx;
+ ath9k_ops.change_chanctx = ath9k_change_chanctx;
+ ath9k_ops.assign_vif_chanctx = ath9k_assign_vif_chanctx;
+ ath9k_ops.unassign_vif_chanctx = ath9k_unassign_vif_chanctx;
+ ath9k_ops.mgd_prepare_tx = ath9k_chanctx_force_active;
+}
+
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
index a0dbcc412384..3f7a11edb82a 100644
--- a/drivers/net/wireless/ath/ath9k/mci.c
+++ b/drivers/net/wireless/ath/ath9k/mci.c
@@ -706,7 +706,7 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
return;
if (setchannel) {
- struct ath9k_hw_cal_data *caldata = &sc->caldata;
+ struct ath9k_hw_cal_data *caldata = &sc->cur_chan->caldata;
if (IS_CHAN_HT40PLUS(ah->curchan) &&
(ah->curchan->channel > caldata->channel) &&
(ah->curchan->channel <= caldata->channel + 20))
@@ -720,7 +720,7 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
mci_hw->concur_tx = concur_tx;
if (old_concur_tx != mci_hw->concur_tx)
- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+ ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
}
static void ath9k_mci_stomp_audio(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 4dec09e565ed..c018dea0b2e8 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -23,7 +23,7 @@
#include <linux/module.h>
#include "ath9k.h"
-static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
+static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
@@ -843,6 +843,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENODEV;
}
+ ath9k_fill_chanctx_ops();
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
if (!hw) {
dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 9105a92364f7..74ab1d02013b 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -259,7 +259,7 @@ static void ath_edma_start_recv(struct ath_softc *sc)
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
ath_opmode_init(sc);
- ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+ ath9k_hw_startpcureceive(sc->sc_ah, sc->cur_chan->offchannel);
}
static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -374,6 +374,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
u32 ath_calcrxfilter(struct ath_softc *sc)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u32 rfilt;
if (config_enabled(CONFIG_ATH9K_TX99))
@@ -424,6 +425,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah))
rfilt |= ATH9K_RX_FILTER_4ADDRESS;
+ if (ath9k_use_chanctx &&
+ test_bit(ATH_OP_SCANNING, &common->op_flags))
+ rfilt |= ATH9K_RX_FILTER_BEACON;
+
return rfilt;
}
@@ -457,7 +462,7 @@ int ath_startrecv(struct ath_softc *sc)
start_recv:
ath_opmode_init(sc);
- ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
+ ath9k_hw_startpcureceive(ah, sc->cur_chan->offchannel);
return 0;
}
@@ -540,7 +545,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
sc->ps_flags &= ~PS_BEACON_SYNC;
ath_dbg(common, PS,
"Reconfigure beacon timers based on synchronized timestamp\n");
- if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0)))
+ if (!(WARN_ON_ONCE(sc->cur_chan->beacon.beacon_interval == 0)))
ath9k_set_beacon(sc);
if (sc->p2p_ps_vif)
ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
@@ -887,6 +892,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
return -EINVAL;
}
+ if (rx_stats->is_mybeacon) {
+ sc->sched.next_tbtt = rx_stats->rs_tstamp;
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_BEACON_RECEIVED);
+ }
+
ath9k_cmn_process_rssi(common, hw, rx_stats, rx_status);
rx_status->band = ah->curchan->chan->band;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index f1bbce3f7774..a1499700bcf2 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -813,6 +813,7 @@
#define AR_SREV_VERSION_9531 0x500
#define AR_SREV_REVISION_9531_10 0
#define AR_SREV_REVISION_9531_11 1
+#define AR_SREV_REVISION_9531_20 2
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -958,6 +959,9 @@
#define AR_SREV_9531_11(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_11))
+#define AR_SREV_9531_20(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_20))
/* NOTE: When adding chips newer than Peacock, add chip check here */
#define AR_SREV_9580_10_OR_LATER(_ah) \
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c
index 99f4de95c264..5fe29b9f8fa2 100644
--- a/drivers/net/wireless/ath/ath9k/spectral.c
+++ b/drivers/net/wireless/ath/ath9k/spectral.c
@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- if (val < 0 || val > 1)
+ if (val > 1)
return -EINVAL;
sc->spec_config.short_repeat = val;
@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- if (val < 0 || val > 255)
+ if (val > 255)
return -EINVAL;
sc->spec_config.count = val;
@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- if (val < 0 || val > 255)
+ if (val > 255)
return -EINVAL;
sc->spec_config.period = val;
@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- if (val < 0 || val > 15)
+ if (val > 15)
return -EINVAL;
sc->spec_config.fft_period = val;
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index a65cfb91adca..23972924c774 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -76,7 +76,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
tx_info = IEEE80211_SKB_CB(skb);
memset(tx_info, 0, sizeof(*tx_info));
rate = &tx_info->control.rates[0];
- tx_info->band = hw->conf.chandef.chan->band;
+ tx_info->band = sc->cur_chan->chandef.chan->band;
tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
tx_info->control.vif = sc->tx99_vif;
rate->count = 1;
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index 2879887f5691..a4f4f0da81f6 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -193,6 +193,7 @@ int ath9k_suspend(struct ieee80211_hw *hw,
u32 wow_triggers_enabled = 0;
int ret = 0;
+ cancel_work_sync(&sc->chanctx_work);
mutex_lock(&sc->mutex);
ath_cancel_work(sc);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 7c28cb55610b..704fcbcbe20b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -103,9 +103,16 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
ieee80211_tx_status(sc->hw, skb);
}
-static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid)
{
struct ath_atx_ac *ac = tid->ac;
+ struct list_head *list;
+ struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
+ struct ath_chanctx *ctx = avp->chanctx;
+
+ if (!ctx)
+ return;
if (tid->sched)
return;
@@ -117,7 +124,9 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
return;
ac->sched = true;
- list_add_tail(&ac->list, &txq->axq_acq);
+
+ list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
+ list_add_tail(&ac->list, list);
}
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
@@ -147,21 +156,22 @@ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
- int q;
-
- q = skb_get_queue_mapping(skb);
- if (txq == sc->tx.uapsdq)
- txq = sc->tx.txq_map[q];
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ath_frame_info *fi = get_frame_info(skb);
+ int hw_queue;
+ int q = fi->txq;
- if (txq != sc->tx.txq_map[q])
+ if (q < 0)
return;
+ txq = sc->tx.txq_map[q];
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
+ hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
- ieee80211_wake_queue(sc->hw, q);
+ ieee80211_wake_queue(sc->hw, hw_queue);
txq->stopped = false;
}
}
@@ -626,7 +636,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
skb_queue_splice_tail(&bf_pending, &tid->retry_q);
if (!an->sleeping) {
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(sc, txq, tid);
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->ac->clear_ps_filter = true;
@@ -1492,7 +1502,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ac->clear_ps_filter = true;
if (ath_tid_has_buffered(tid)) {
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(sc, txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1516,7 +1526,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
if (ath_tid_has_buffered(tid)) {
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(sc, txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1651,7 +1661,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->axq_link = NULL;
__skb_queue_head_init(&txq->complete_q);
INIT_LIST_HEAD(&txq->axq_q);
- INIT_LIST_HEAD(&txq->axq_acq);
spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0;
txq->axq_ampdu_depth = 0;
@@ -1695,7 +1704,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int ath_cabq_update(struct ath_softc *sc)
{
struct ath9k_tx_queue_info qi;
- struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
+ struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
int qnum = sc->beacon.cabq->axq_qnum;
ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@@ -1813,7 +1822,7 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
}
-/* For each axq_acq entry, for each tid, try to schedule packets
+/* For each acq entry, for each tid, try to schedule packets
* for transmit until ampdu_depth has reached min Q depth.
*/
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
@@ -1821,19 +1830,31 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_ac *ac, *last_ac;
struct ath_atx_tid *tid, *last_tid;
+ struct list_head *ac_list;
bool sent = false;
+ if (txq->mac80211_qnum < 0)
+ return;
+
+ spin_lock_bh(&sc->chan_lock);
+ ac_list = &sc->cur_chan->acq[txq->mac80211_qnum];
+ spin_unlock_bh(&sc->chan_lock);
+
if (test_bit(ATH_OP_HW_RESET, &common->op_flags) ||
- list_empty(&txq->axq_acq))
+ list_empty(ac_list))
return;
+ spin_lock_bh(&sc->chan_lock);
rcu_read_lock();
- last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
- while (!list_empty(&txq->axq_acq)) {
+ last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list);
+ while (!list_empty(ac_list)) {
bool stop = false;
- ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+ if (sc->cur_chan->stopped)
+ break;
+
+ ac = list_first_entry(ac_list, struct ath_atx_ac, list);
last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
list_del(&ac->list);
ac->sched = false;
@@ -1853,7 +1874,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
* are pending for the tid
*/
if (ath_tid_has_buffered(tid))
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(sc, txq, tid);
if (stop || tid == last_tid)
break;
@@ -1861,7 +1882,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (!list_empty(&ac->tid_q) && !ac->sched) {
ac->sched = true;
- list_add_tail(&ac->list, &txq->axq_acq);
+ list_add_tail(&ac->list, ac_list);
}
if (stop)
@@ -1872,12 +1893,27 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
break;
sent = false;
- last_ac = list_entry(txq->axq_acq.prev,
+ last_ac = list_entry(ac_list->prev,
struct ath_atx_ac, list);
}
}
rcu_read_unlock();
+ spin_unlock_bh(&sc->chan_lock);
+}
+
+void ath_txq_schedule_all(struct ath_softc *sc)
+{
+ struct ath_txq *txq;
+ int i;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ txq = sc->tx.txq_map[i];
+
+ spin_lock_bh(&txq->axq_lock);
+ ath_txq_schedule(sc, txq);
+ spin_unlock_bh(&txq->axq_lock);
+ }
}
/***********/
@@ -2008,6 +2044,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
an = (struct ath_node *) sta->drv_priv;
memset(fi, 0, sizeof(*fi));
+ fi->txq = -1;
if (hw_key)
fi->keyix = hw_key->hw_key_idx;
else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
@@ -2159,13 +2196,22 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txctl->sta;
struct ieee80211_vif *vif = info->control.vif;
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct ath_vif *avp = NULL;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf;
- int q;
+ bool queue;
+ int q, hw_queue;
int ret;
+ if (vif)
+ avp = (void *)vif->drv_priv;
+
+ if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+ txctl->force_channel = true;
+
ret = ath_tx_prepare(hw, skb, txctl);
if (ret)
return ret;
@@ -2177,24 +2223,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
q = skb_get_queue_mapping(skb);
+ hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
ath_txq_lock(sc, txq);
- if (txq == sc->tx.txq_map[q] &&
- ++txq->pending_frames > sc->tx.txq_max_pending[q] &&
- !txq->stopped) {
- ieee80211_stop_queue(sc->hw, q);
- txq->stopped = true;
+ if (txq == sc->tx.txq_map[q]) {
+ fi->txq = q;
+ if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
+ !txq->stopped) {
+ ieee80211_stop_queue(sc->hw, hw_queue);
+ txq->stopped = true;
+ }
+ }
+
+ queue = ieee80211_is_data_present(hdr->frame_control);
+
+ /* Force queueing of all frames that belong to a virtual interface on
+ * a different channel context, to ensure that they are sent on the
+ * correct channel.
+ */
+ if (((avp && avp->chanctx != sc->cur_chan) ||
+ sc->cur_chan->stopped) && !txctl->force_channel) {
+ if (!txctl->an)
+ txctl->an = &avp->mcast_node;
+ info->flags &= ~IEEE80211_TX_CTL_PS_RESPONSE;
+ queue = true;
}
- if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
+ if (txctl->an && queue)
tid = ath_get_skb_tid(sc, txctl->an, skb);
- if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
+ if (info->flags & (IEEE80211_TX_CTL_PS_RESPONSE |
+ IEEE80211_TX_CTL_TX_OFFCHAN)) {
ath_txq_unlock(sc, txq);
txq = sc->tx.uapsdq;
ath_txq_lock(sc, txq);
- } else if (txctl->an &&
- ieee80211_is_data_present(hdr->frame_control)) {
+ } else if (txctl->an && queue) {
WARN_ON(tid->ac->txq != txctl->txq);
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
@@ -2207,7 +2270,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
TX_STAT_INC(txq->axq_qnum, a_queued_sw);
__skb_queue_tail(&tid->buf_q, skb);
if (!txctl->an->sleeping)
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(sc, txq, tid);
ath_txq_schedule(sc, txq);
goto out;
@@ -2253,8 +2316,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int max_duration;
max_duration =
- sc->cur_beacon_conf.beacon_interval * 1000 *
- sc->cur_beacon_conf.dtim_period / ATH_BCBUF;
+ sc->cur_chan->beacon.beacon_interval * 1000 *
+ sc->cur_chan->beacon.dtim_period / ATH_BCBUF;
do {
struct ath_frame_info *fi = get_frame_info(skb);
@@ -2569,6 +2632,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
sc->beacon.tx_processed = true;
sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
+ ath_chanctx_event(sc, NULL,
+ ATH_CHANCTX_EVENT_BEACON_SENT);
ath9k_csa_update(sc);
continue;
}
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 8596aba34f96..237d0cda1bcb 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -256,6 +256,7 @@ struct ar9170 {
atomic_t rx_work_urbs;
atomic_t rx_pool_urbs;
kernel_ulong_t features;
+ bool usb_ep_cmd_is_bulk;
/* firmware settings */
struct completion fw_load_wait;
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index ab4ee7d39ad3..b80b2138ce3c 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1139,7 +1139,6 @@ static int carl9170_set_freq_cal_data(struct ar9170 *ar,
default:
return -EINVAL;
- break;
}
for (; i >= 0; i--) {
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index f35c7f30f9a6..c9f93310c0d6 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd,
goto err_free;
}
- usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev,
- AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4,
- carl9170_usb_cmd_complete, ar, 1);
+ if (ar->usb_ep_cmd_is_bulk)
+ usb_fill_bulk_urb(urb, ar->udev,
+ usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD),
+ cmd, cmd->hdr.len + 4,
+ carl9170_usb_cmd_complete, ar);
+ else
+ usb_fill_int_urb(urb, ar->udev,
+ usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD),
+ cmd, cmd->hdr.len + 4,
+ carl9170_usb_cmd_complete, ar, 1);
if (free_buf)
urb->transfer_flags |= URB_FREE_BUFFER;
@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw,
static int carl9170_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct usb_endpoint_descriptor *ep;
struct ar9170 *ar;
struct usb_device *udev;
- int err;
+ int i, err;
err = usb_reset_device(interface_to_usbdev(intf));
if (err)
@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf,
ar->intf = intf;
ar->features = id->driver_info;
+ /* We need to remember the type of endpoint 4 because it differs
+ * between high- and full-speed configuration. The high-speed
+ * configuration specifies it as interrupt and the full-speed
+ * configuration as bulk endpoint. This information is required
+ * later when sending urbs to that endpoint.
+ */
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) {
+ ep = &intf->cur_altsetting->endpoint[i].desc;
+
+ if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD &&
+ usb_endpoint_dir_out(ep) &&
+ usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK)
+ ar->usb_ep_cmd_is_bulk = true;
+ }
+
usb_set_intfdata(intf, ar);
SET_IEEE80211_DEV(ar->hw, &intf->dev);
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 4ab5370ab7a6..b71d2b33532d 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -488,7 +488,6 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
ret = -EOPNOTSUPP;
goto out;
- break;
}
out:
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 820d4ebd9322..4ac2c208c9ba 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -104,8 +104,8 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type)
return -EOPNOTSUPP;
}
-static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
- struct station_info *sinfo)
+int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+ struct station_info *sinfo)
{
struct wmi_notify_req_cmd cmd = {
.cid = cid,
@@ -287,6 +287,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
return -EBUSY;
}
+ wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
wil->scan_request = request;
mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
@@ -443,15 +444,15 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
return rc;
}
-static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
- struct wireless_dev *wdev,
- struct cfg80211_mgmt_tx_params *params,
- u64 *cookie)
+int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_mgmt_tx_params *params,
+ u64 *cookie)
{
const u8 *buf = params->buf;
size_t len = params->len;
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int rc;
+ bool tx_status = false;
struct ieee80211_mgmt *mgmt_frame = (void *)buf;
struct wmi_sw_tx_req_cmd *cmd;
struct {
@@ -460,8 +461,10 @@ static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
} __packed evt;
cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ if (!cmd) {
+ rc = -ENOMEM;
+ goto out;
+ }
memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN);
cmd->len = cpu_to_le16(len);
@@ -470,10 +473,12 @@ static int wil_cfg80211_mgmt_tx(struct wiphy *wiphy,
rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, sizeof(*cmd) + len,
WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
if (rc == 0)
- rc = evt.evt.status;
+ tx_status = !evt.evt.status;
kfree(cmd);
-
+ out:
+ cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len,
+ tx_status, GFP_KERNEL);
return rc;
}
@@ -562,6 +567,34 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
return rc;
}
+static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
+{
+ print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET,
+ b->head, b->head_len);
+ print_hex_dump_bytes("tail ", DUMP_PREFIX_OFFSET,
+ b->tail, b->tail_len);
+ print_hex_dump_bytes("BCON IE ", DUMP_PREFIX_OFFSET,
+ b->beacon_ies, b->beacon_ies_len);
+ print_hex_dump_bytes("PROBE ", DUMP_PREFIX_OFFSET,
+ b->probe_resp, b->probe_resp_len);
+ print_hex_dump_bytes("PROBE IE ", DUMP_PREFIX_OFFSET,
+ b->proberesp_ies, b->proberesp_ies_len);
+ print_hex_dump_bytes("ASSOC IE ", DUMP_PREFIX_OFFSET,
+ b->assocresp_ies, b->assocresp_ies_len);
+}
+
+static void wil_print_crypto(struct wil6210_priv *wil,
+ struct cfg80211_crypto_settings *c)
+{
+ wil_dbg_misc(wil, "WPA versions: 0x%08x cipher group 0x%08x\n",
+ c->wpa_versions, c->cipher_group);
+ wil_dbg_misc(wil, "Pairwise ciphers [%d]\n", c->n_ciphers_pairwise);
+ wil_dbg_misc(wil, "AKM suites [%d]\n", c->n_akm_suites);
+ wil_dbg_misc(wil, "Control port : %d, eth_type 0x%04x no_encrypt %d\n",
+ c->control_port, be16_to_cpu(c->control_port_ethertype),
+ c->control_port_no_encrypt);
+}
+
static int wil_fix_bcon(struct wil6210_priv *wil,
struct cfg80211_beacon_data *bcon)
{
@@ -595,8 +628,11 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
struct wireless_dev *wdev = ndev->ieee80211_ptr;
struct ieee80211_channel *channel = info->chandef.chan;
struct cfg80211_beacon_data *bcon = &info->beacon;
+ struct cfg80211_crypto_settings *crypto = &info->crypto;
u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+ wil_dbg_misc(wil, "%s()\n", __func__);
+
if (!channel) {
wil_err(wil, "AP: No channel???\n");
return -EINVAL;
@@ -604,11 +640,19 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
channel->center_freq, info->privacy ? "secure" : "open");
+ wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
+ info->privacy, info->auth_type);
+ wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
+ info->dtim_period);
print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
info->ssid, info->ssid_len);
+ wil_print_bcon_data(bcon);
+ wil_print_crypto(wil, crypto);
- if (wil_fix_bcon(wil, bcon))
+ if (wil_fix_bcon(wil, bcon)) {
wil_dbg_misc(wil, "Fixed bcon\n");
+ wil_print_bcon_data(bcon);
+ }
mutex_lock(&wil->mutex);
@@ -663,6 +707,8 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
int rc = 0;
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ wil_dbg_misc(wil, "%s()\n", __func__);
+
mutex_lock(&wil->mutex);
rc = wmi_pcp_stop(wil);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 8d4bc4bfb664..8f66186adb8c 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -19,6 +19,7 @@
#include <linux/seq_file.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
+#include <linux/power_supply.h>
#include "wil6210.h"
#include "txrx.h"
@@ -69,14 +70,32 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
struct vring *vring = &(wil->vring_tx[i]);
+ struct vring_tx_data *txdata = &wil->vring_tx_data[i];
+
if (vring->va) {
int cid = wil->vring2cid_tid[i][0];
int tid = wil->vring2cid_tid[i][1];
+ u32 swhead = vring->swhead;
+ u32 swtail = vring->swtail;
+ int used = (vring->size + swhead - swtail)
+ % vring->size;
+ int avail = vring->size - used - 1;
char name[10];
+ /* performance monitoring */
+ cycles_t now = get_cycles();
+ cycles_t idle = txdata->idle * 100;
+ cycles_t total = now - txdata->begin;
+
+ do_div(idle, total);
+ txdata->begin = now;
+ txdata->idle = 0ULL;
+
snprintf(name, sizeof(name), "tx_%2d", i);
- seq_printf(s, "\n%pM CID %d TID %d\n",
- wil->sta[cid].addr, cid, tid);
+ seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
+ wil->sta[cid].addr, cid, tid, used, avail,
+ (int)idle);
+
wil_print_vring(s, wil, name, vring, '_', 'H');
}
}
@@ -231,6 +250,26 @@ static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
&fops_iomem_x32);
}
+static int wil_debugfs_ulong_set(void *data, u64 val)
+{
+ *(ulong *)data = val;
+ return 0;
+}
+static int wil_debugfs_ulong_get(void *data, u64 *val)
+{
+ *val = *(ulong *)data;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
+ wil_debugfs_ulong_set, "%llu\n");
+
+static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
+ struct dentry *parent,
+ ulong *value)
+{
+ return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong);
+}
+
static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
const char *name,
struct dentry *parent, u32 off)
@@ -284,11 +323,11 @@ static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
if (IS_ERR_OR_NULL(d))
return -ENODEV;
- wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("TRSH", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
- wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("DATA", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_DATA));
- wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr +
+ wil_debugfs_create_iomem_x32("CTL", S_IRUGO | S_IWUSR, d, wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_CRL));
return 0;
@@ -397,6 +436,126 @@ static const struct file_operations fops_reset = {
.write = wil_write_file_reset,
.open = simple_open,
};
+/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
+static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ int rc;
+ long channel;
+ bool on;
+
+ char *kbuf = kmalloc(len + 1, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ if (copy_from_user(kbuf, buf, len)) {
+ kfree(kbuf);
+ return -EIO;
+ }
+
+ kbuf[len] = '\0';
+ rc = kstrtol(kbuf, 0, &channel);
+ kfree(kbuf);
+ if (rc)
+ return rc;
+
+ if ((channel < 0) || (channel > 4)) {
+ wil_err(wil, "Invalid channel %ld\n", channel);
+ return -EINVAL;
+ }
+ on = !!channel;
+
+ if (on) {
+ rc = wmi_set_channel(wil, (int)channel);
+ if (rc)
+ return rc;
+ }
+
+ rc = wmi_rxon(wil, on);
+ if (rc)
+ return rc;
+
+ return len;
+}
+
+static const struct file_operations fops_rxon = {
+ .write = wil_write_file_rxon,
+ .open = simple_open,
+};
+/*---tx_mgmt---*/
+/* Write mgmt frame to this file to send it */
+static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ struct wiphy *wiphy = wil_to_wiphy(wil);
+ struct wireless_dev *wdev = wil_to_wdev(wil);
+ struct cfg80211_mgmt_tx_params params;
+ int rc;
+
+ void *frame = kmalloc(len, GFP_KERNEL);
+ if (!frame)
+ return -ENOMEM;
+
+ if (copy_from_user(frame, buf, len))
+ return -EIO;
+
+ params.buf = frame;
+ params.len = len;
+ params.chan = wdev->preset_chandef.chan;
+
+ rc = wil_cfg80211_mgmt_tx(wiphy, wdev, &params, NULL);
+
+ kfree(frame);
+ wil_info(wil, "%s() -> %d\n", __func__, rc);
+
+ return len;
+}
+
+static const struct file_operations fops_txmgmt = {
+ .write = wil_write_file_txmgmt,
+ .open = simple_open,
+};
+
+/* Write WMI command (w/o mbox header) to this file to send it
+ * WMI starts from wil6210_mbox_hdr_wmi header
+ */
+static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ struct wil6210_mbox_hdr_wmi *wmi;
+ void *cmd;
+ int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
+ u16 cmdid;
+ int rc, rc1;
+
+ if (cmdlen <= 0)
+ return -EINVAL;
+
+ wmi = kmalloc(len, GFP_KERNEL);
+ if (!wmi)
+ return -ENOMEM;
+
+ rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
+ if (rc < 0)
+ return rc;
+
+ cmd = &wmi[1];
+ cmdid = le16_to_cpu(wmi->id);
+
+ rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
+ kfree(wmi);
+
+ wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1);
+
+ return rc;
+}
+
+static const struct file_operations fops_wmi = {
+ .write = wil_write_file_wmi,
+ .open = simple_open,
+};
static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
const char *prefix)
@@ -600,8 +759,8 @@ static int wil_temp_debugfs_show(struct seq_file *s, void *data)
return 0;
}
- print_temp(s, "MAC temperature :", t_m);
- print_temp(s, "Radio temperature :", t_r);
+ print_temp(s, "T_mac =", t_m);
+ print_temp(s, "T_radio =", t_r);
return 0;
}
@@ -618,6 +777,130 @@ static const struct file_operations fops_temp = {
.llseek = seq_lseek,
};
+/*---------freq------------*/
+static int wil_freq_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct wireless_dev *wdev = wil_to_wdev(wil);
+ u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
+
+ seq_printf(s, "Freq = %d\n", freq);
+
+ return 0;
+}
+
+static int wil_freq_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_freq_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_freq = {
+ .open = wil_freq_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+/*---------link------------*/
+static int wil_link_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct station_info sinfo;
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
+ struct wil_sta_info *p = &wil->sta[i];
+ char *status = "unknown";
+ switch (p->status) {
+ case wil_sta_unused:
+ status = "unused ";
+ break;
+ case wil_sta_conn_pending:
+ status = "pending ";
+ break;
+ case wil_sta_connected:
+ status = "connected";
+ break;
+ }
+ seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
+ (p->data_port_open ? " data_port_open" : ""));
+
+ if (p->status == wil_sta_connected) {
+ rc = wil_cid_fill_sinfo(wil, i, &sinfo);
+ if (rc)
+ return rc;
+
+ seq_printf(s, " Tx_mcs = %d\n", sinfo.txrate.mcs);
+ seq_printf(s, " Rx_mcs = %d\n", sinfo.rxrate.mcs);
+ seq_printf(s, " SQ = %d\n", sinfo.signal);
+ }
+ }
+
+ return 0;
+}
+
+static int wil_link_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_link_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_link = {
+ .open = wil_link_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+/*---------info------------*/
+static int wil_info_debugfs_show(struct seq_file *s, void *data)
+{
+ struct wil6210_priv *wil = s->private;
+ struct net_device *ndev = wil_to_ndev(wil);
+ int is_ac = power_supply_is_system_supplied();
+ int rx = atomic_xchg(&wil->isr_count_rx, 0);
+ int tx = atomic_xchg(&wil->isr_count_tx, 0);
+ static ulong rxf_old, txf_old;
+ ulong rxf = ndev->stats.rx_packets;
+ ulong txf = ndev->stats.tx_packets;
+ unsigned int i;
+
+ /* >0 : AC; 0 : battery; <0 : error */
+ seq_printf(s, "AC powered : %d\n", is_ac);
+ seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old);
+ seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old);
+ rxf_old = rxf;
+ txf_old = txf;
+
+
+#define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
+ " " __stringify(x) : ""
+
+ for (i = 0; i < ndev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
+ unsigned long state = txq->state;
+
+ seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state,
+ CHECK_QSTATE(DRV_XOFF),
+ CHECK_QSTATE(STACK_XOFF),
+ CHECK_QSTATE(FROZEN)
+ );
+ }
+#undef CHECK_QSTATE
+ return 0;
+}
+
+static int wil_info_seq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, wil_info_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_info = {
+ .open = wil_info_seq_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
/*---------Station matrix------------*/
static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
{
@@ -630,7 +913,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
else
seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
}
- seq_puts(s, "]\n");
+ seq_printf(s, "] last drop 0x%03x\n", r->ssn_last_drop);
}
static int wil_sta_debugfs_show(struct seq_file *s, void *data)
@@ -682,6 +965,26 @@ static const struct file_operations fops_sta = {
};
/*----------------*/
+static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
+ struct dentry *dbg)
+{
+ int i;
+ char name[32];
+
+ for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+ struct debugfs_blob_wrapper *blob = &wil->blobs[i];
+ const struct fw_map *map = &fw_mapping[i];
+
+ if (!map->name)
+ continue;
+
+ blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
+ blob->size = map->to - map->from;
+ snprintf(name, sizeof(name), "blob_%s", map->name);
+ wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
+ }
+}
+
int wil6210_debugfs_init(struct wil6210_priv *wil)
{
struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
@@ -703,6 +1006,10 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
&wil->secure_pcp);
+ wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
+ &wil->status);
+ debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version);
+ debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version);
wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
HOSTADDR(RGF_USER_USER_ICR));
@@ -715,40 +1022,22 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
wil6210_debugfs_create_pseudo_ISR(wil, dbg);
wil6210_debugfs_create_ITR_CNT(wil, dbg);
+ wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg,
+ wil->csr +
+ HOSTADDR(RGF_USER_USAGE_1));
debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+ debugfs_create_file("rxon", S_IWUSR, dbg, wil, &fops_rxon);
+ debugfs_create_file("tx_mgmt", S_IWUSR, dbg, wil, &fops_txmgmt);
+ debugfs_create_file("wmi_send", S_IWUSR, dbg, wil, &fops_wmi);
debugfs_create_file("temp", S_IRUGO, dbg, wil, &fops_temp);
+ debugfs_create_file("freq", S_IRUGO, dbg, wil, &fops_freq);
+ debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
+ debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
- wil->rgf_blob.data = (void * __force)wil->csr + 0;
- wil->rgf_blob.size = 0xa000;
- wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
-
- wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
- wil->fw_code_blob.size = 0x40000;
- wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
- &wil->fw_code_blob);
-
- wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
- wil->fw_data_blob.size = 0x8000;
- wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
- &wil->fw_data_blob);
-
- wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
- wil->fw_peri_blob.size = 0x18000;
- wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
- &wil->fw_peri_blob);
-
- wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
- wil->uc_code_blob.size = 0x10000;
- wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
- &wil->uc_code_blob);
-
- wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
- wil->uc_data_blob.size = 0x4000;
- wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
- &wil->uc_data_blob);
+ wil6210_debugfs_init_blobs(wil, dbg);
return 0;
}
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 73593aa3cd98..67f1002a03a1 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -208,6 +208,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
/* Rx IRQ will be enabled when NAPI processing finished */
+ atomic_inc(&wil->isr_count_rx);
return IRQ_HANDLED;
}
@@ -246,6 +247,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
/* Tx IRQ will be enabled when NAPI processing finished */
+ atomic_inc(&wil->isr_count_tx);
return IRQ_HANDLED;
}
@@ -257,6 +259,7 @@ static void wil_notify_fw_error(struct wil6210_priv *wil)
[1] = "EVENT=FW_ERROR",
[2] = NULL,
};
+ wil_err(wil, "Notify about firmware error\n");
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 11e6d9d22eae..3704d2a434f3 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -61,11 +61,24 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
{
uint i;
+ struct net_device *ndev = wil_to_ndev(wil);
+ struct wireless_dev *wdev = wil->wdev;
struct wil_sta_info *sta = &wil->sta[cid];
+ wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
+ sta->status);
sta->data_port_open = false;
if (sta->status != wil_sta_unused) {
wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ /* AP-like interface */
+ cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL);
+ break;
+ default:
+ break;
+ }
sta->status = wil_sta_unused;
}
@@ -119,11 +132,6 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
clear_bit(wil_status_fwconnecting, &wil->status);
break;
default:
- /* AP-like interface and monitor:
- * never scan, always connected
- */
- if (bssid)
- cfg80211_del_sta(ndev, bssid, GFP_KERNEL);
break;
}
}
@@ -306,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil)
int delay = 0;
u32 hw_state;
u32 rev_id;
+ bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
- wil_dbg_misc(wil, "Resetting...\n");
+ wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
/* register read */
#define R(a) ioread32(wil->csr + HOSTADDR(a))
@@ -320,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil)
wil->hw_version = R(RGF_USER_FW_REV_ID);
rev_id = wil->hw_version & 0xff;
+
+ /* Clear MAC link up */
+ S(RGF_HP_CTRL, BIT(15));
/* hpal_perst_from_pad_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
/* car_perst_rst_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
wmb(); /* order is important here */
+ if (is_sparrow) {
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
+ wmb(); /* order is important here */
+ }
+
W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
wmb(); /* order is important here */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000B0 : 0x00000170);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
wmb(); /* order is important here */
+ if (is_sparrow) {
+ W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
+ wmb(); /* order is important here */
+ }
+
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
- if (rev_id == 1) {
- W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
- } else {
- W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
+ if (is_sparrow) {
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
+ /* reset A2 PCIE AHB */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
+
+ } else {
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
+ if (rev_id == 1) {
+ /* reset A1 BOTH PCIE AHB & PCIE RGF */
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
+ } else {
+ W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
+ W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
+ }
+
}
+
+ /* TODO: check order here!!! Erez code is different */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */
@@ -363,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
}
} while (hw_state != HW_MACHINE_BOOT_DONE);
- if (rev_id == 2)
+ /* TODO: Erez check rev_id != 1 */
+ if (!is_sparrow && (rev_id != 1))
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
@@ -465,6 +499,7 @@ void wil_link_on(struct wil6210_priv *wil)
wil_dbg_misc(wil, "%s()\n", __func__);
netif_carrier_on(ndev);
+ wil_dbg_misc(wil, "netif_tx_wake : link on\n");
netif_tx_wake_all_queues(ndev);
}
@@ -475,6 +510,7 @@ void wil_link_off(struct wil6210_priv *wil)
wil_dbg_misc(wil, "%s()\n", __func__);
netif_tx_stop_all_queues(ndev);
+ wil_dbg_misc(wil, "netif_tx_stop : link off\n");
netif_carrier_off(ndev);
}
@@ -552,6 +588,8 @@ static int __wil_down(struct wil6210_priv *wil)
napi_disable(&wil->napi_tx);
if (wil->scan_request) {
+ wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
+ wil->scan_request);
del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, true);
wil->scan_request = NULL;
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 106b6dcb773a..7afce6e8c507 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -132,7 +132,7 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
- ndev = alloc_netdev(0, "wlan%d", ether_setup);
+ ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup);
if (!ndev) {
dev_err(dev, "alloc_netdev_mqs failed\n");
rc = -ENOMEM;
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 1e2e07b9d13d..d3fbfa28db62 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -15,7 +15,6 @@
*/
#include <linux/module.h>
-#include <linux/debugfs.h>
#include <linux/pci.h>
#include <linux/moduleparam.h>
@@ -27,11 +26,22 @@ MODULE_PARM_DESC(use_msi,
" Use MSI interrupt: "
"0 - don't, 1 - (default) - single, or 3");
+static bool debug_fw; /* = false; */
+module_param(debug_fw, bool, S_IRUGO);
+MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug");
+
/* Bus ops */
static int wil_if_pcie_enable(struct wil6210_priv *wil)
{
struct pci_dev *pdev = wil->pdev;
int rc;
+ /* on platforms with buggy ACPI, pdev->msi_enabled may be set to
+ * allow pci_enable_device to work. This indicates INTx was not routed
+ * and only MSI should be used
+ */
+ int msi_only = pdev->msi_enabled;
+
+ pdev->msi_enabled = 0;
pci_set_master(pdev);
@@ -63,6 +73,12 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
wil->n_msi = use_msi;
+ if ((wil->n_msi == 0) && msi_only) {
+ wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
+ rc = -ENODEV;
+ goto stop_master;
+ }
+
rc = wil6210_init_irq(wil, pdev->irq);
if (rc)
goto stop_master;
@@ -71,6 +87,8 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
mutex_lock(&wil->mutex);
rc = wil_reset(wil);
mutex_unlock(&wil->mutex);
+ if (debug_fw)
+ rc = 0;
if (rc)
goto release_irq;
@@ -104,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct wil6210_priv *wil;
struct device *dev = &pdev->dev;
void __iomem *csr;
+ struct wil_board *board = (struct wil_board *)id->driver_data;
int rc;
/* check HW */
- dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
+ dev_info(&pdev->dev, WIL_NAME
+ " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name,
(int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
@@ -119,9 +139,16 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rc = pci_enable_device(pdev);
if (rc) {
- dev_err(&pdev->dev, "pci_enable_device failed\n");
- return -ENODEV;
+ dev_err(&pdev->dev,
+ "pci_enable_device failed, retry with MSI only\n");
+ /* Work around for platforms that can't allocate IRQ:
+ * retry with MSI only
+ */
+ pdev->msi_enabled = 1;
+ rc = pci_enable_device(pdev);
}
+ if (rc)
+ return -ENODEV;
/* rollback to err_disable_pdev */
rc = pci_request_region(pdev, 0, WIL_NAME);
@@ -150,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, wil);
wil->pdev = pdev;
+ wil->board = board;
wil6210_clear_irq(wil);
/* FW should raise IRQ when ready */
@@ -200,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
- { PCI_DEVICE(0x1ae9, 0x0301) },
+static const struct wil_board wil_board_marlon = {
+ .board = WIL_BOARD_MARLON,
+ .name = "marlon",
+};
+
+static const struct wil_board wil_board_sparrow = {
+ .board = WIL_BOARD_SPARROW,
+ .name = "sparrow",
+};
+
+static const struct pci_device_id wil6210_pcie_ids[] = {
+ { PCI_DEVICE(0x1ae9, 0x0301),
+ .driver_data = (kernel_ulong_t)&wil_board_marlon },
+ { PCI_DEVICE(0x1ae9, 0x0310),
+ .driver_data = (kernel_ulong_t)&wil_board_sparrow },
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 747ae1275877..180ca4793904 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -116,6 +116,7 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
/* frame with out of date sequence number */
if (seq_less(seq, r->head_seq_num)) {
+ r->ssn_last_drop = seq;
dev_kfree_skb(skb);
goto out;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 0784ef3d4ce2..d3467943d39d 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -525,6 +525,17 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
ndev->stats.rx_bytes += len;
stats->rx_bytes += len;
}
+ {
+ static const char * const gro_res_str[] = {
+ [GRO_MERGED] = "GRO_MERGED",
+ [GRO_MERGED_FREE] = "GRO_MERGED_FREE",
+ [GRO_HELD] = "GRO_HELD",
+ [GRO_NORMAL] = "GRO_NORMAL",
+ [GRO_DROP] = "GRO_DROP",
+ };
+ wil_dbg_txrx(wil, "Rx complete %d bytes => %s,\n",
+ len, gro_res_str[rc]);
+ }
}
/**
@@ -760,7 +771,7 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil,
goto found;
}
- wil_err(wil, "Tx while no vrings active?\n");
+ wil_dbg_txrx(wil, "Tx while no vrings active?\n");
return NULL;
@@ -881,6 +892,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
int nr_frags = skb_shinfo(skb)->nr_frags;
uint f = 0;
int vring_index = vring - wil->vring_tx;
+ struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
uint i = swhead;
dma_addr_t pa;
@@ -953,6 +965,9 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
(const void *)d, sizeof(*d), false);
+ if (wil_vring_is_empty(vring)) /* performance monitoring */
+ txdata->idle += get_cycles() - txdata->last_idle;
+
/* advance swhead */
wil_vring_advance_head(vring, nr_frags + 1);
wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
@@ -1016,15 +1031,17 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
vring = wil_tx_bcast(wil, skb);
}
if (!vring) {
- wil_err(wil, "No Tx VRING found for %pM\n", eth->h_dest);
+ wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
goto drop;
}
/* set up vring entry */
rc = wil_tx_vring(wil, vring, skb);
/* do we still have enough room in the vring? */
- if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))
+ if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring)) {
netif_tx_stop_all_queues(wil_to_ndev(wil));
+ wil_dbg_txrx(wil, "netif_tx_stop : ring full\n");
+ }
switch (rc) {
case 0:
@@ -1091,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
while (vring->swtail != new_swtail) {
struct vring_tx_desc dd, *d = &dd;
u16 dmalen;
- struct wil_ctx *ctx = &vring->ctx[vring->swtail];
- struct sk_buff *skb = ctx->skb;
+ struct sk_buff *skb;
+
+ ctx = &vring->ctx[vring->swtail];
+ skb = ctx->skb;
_d = &vring->va[vring->swtail].tx;
*d = *_d;
@@ -1132,8 +1151,16 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
done++;
}
}
- if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring))
+
+ if (wil_vring_is_empty(vring)) { /* performance monitoring */
+ wil_dbg_txrx(wil, "Ring[%2d] empty\n", ringid);
+ txdata->last_idle = get_cycles();
+ }
+
+ if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring)) {
+ wil_dbg_txrx(wil, "netif_tx_wake : ring not full\n");
netif_tx_wake_all_queues(wil_to_ndev(wil));
+ }
return done;
}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index e25edc52398f..67e9624f7111 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -20,9 +20,17 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/cfg80211.h>
+#include <linux/timex.h>
#define WIL_NAME "wil6210"
+struct wil_board {
+ int board;
+#define WIL_BOARD_MARLON (1)
+#define WIL_BOARD_SPARROW (2)
+ const char * const name;
+};
+
/**
* extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect
@@ -77,6 +85,7 @@ struct RGF_ICR {
} __packed;
/* registers - FW addresses */
+#define RGF_USER_USAGE_1 (0x880004)
#define RGF_USER_HW_MACHINE_STATE (0x8801dc)
#define HW_MACHINE_BOOT_DONE (0x3fffffd)
#define RGF_USER_USER_CPU_0 (0x8801e0)
@@ -92,6 +101,7 @@ struct RGF_ICR {
#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14)
#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */
#define BIT_USER_USER_ICR_SW_INT_2 BIT(18)
+#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18)
#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
#define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
@@ -120,6 +130,7 @@ struct RGF_ICR {
#define BIT_DMA_PSEUDO_CAUSE_TX BIT(1)
#define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
+#define RGF_HP_CTRL (0x88265c)
#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
/* popular locations */
@@ -134,6 +145,14 @@ struct RGF_ICR {
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
/* Hardware definitions end */
+struct fw_map {
+ u32 from; /* linker address - from, inclusive */
+ u32 to; /* linker address - to, exclusive */
+ u32 host; /* PCI/Host address - BAR0 + 0x880000 */
+ const char *name; /* for debugfs */
+};
+/* array size should be in sync with actual definition in the wmi.c */
+extern const struct fw_map fw_mapping[7];
/**
* mk_cidxtid - construct @cidxtid field
@@ -251,7 +270,7 @@ struct vring {
*/
struct vring_tx_data {
int enabled;
-
+ cycles_t idle, last_idle, begin;
};
enum { /* for wil6210_priv.status */
@@ -303,6 +322,7 @@ struct wil_tid_ampdu_rx {
u16 ssn;
u16 buf_size;
u16 timeout;
+ u16 ssn_last_drop;
u8 dialog_token;
bool first_time; /* is it 1-st time this buffer used? */
};
@@ -363,6 +383,7 @@ struct wil6210_priv {
ulong status;
u32 fw_version;
u32 hw_version;
+ struct wil_board *board;
u8 n_mids; /* number of additional MIDs as reported by FW */
int recovery_count; /* num of FW recovery attempts in a short time */
unsigned long last_fw_recovery; /* jiffies of last fw recovery */
@@ -410,14 +431,10 @@ struct wil6210_priv {
struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
/* statistics */
struct wil6210_stats stats;
+ atomic_t isr_count_rx, isr_count_tx;
/* debugfs */
struct dentry *debug;
- struct debugfs_blob_wrapper fw_code_blob;
- struct debugfs_blob_wrapper fw_data_blob;
- struct debugfs_blob_wrapper fw_peri_blob;
- struct debugfs_blob_wrapper uc_code_blob;
- struct debugfs_blob_wrapper uc_data_blob;
- struct debugfs_blob_wrapper rgf_blob;
+ struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
};
#define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -504,9 +521,14 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq);
void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
void wil6210_disable_irq(struct wil6210_priv *wil);
void wil6210_enable_irq(struct wil6210_priv *wil);
+int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_mgmt_tx_params *params,
+ u64 *cookie);
int wil6210_debugfs_init(struct wil6210_priv *wil);
void wil6210_debugfs_remove(struct wil6210_priv *wil);
+int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+ struct station_info *sinfo);
struct wireless_dev *wil_cfg80211_init(struct device *dev);
void wil_wdev_free(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 6cc0e182cc70..1d1d0afdd2e1 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -65,17 +65,17 @@
/**
* @fw_mapping provides memory remapping table
+ *
+ * array size should be in sync with the declaration in the wil6210.h
*/
-static const struct {
- u32 from; /* linker address - from, inclusive */
- u32 to; /* linker address - to, exclusive */
- u32 host; /* PCI/Host address - BAR0 + 0x880000 */
-} fw_mapping[] = {
- {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */
- {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */
- {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */
- {0x880000, 0x88a000, 0x880000}, /* various RGF */
- {0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */
+const struct fw_map fw_mapping[] = {
+ {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */
+ {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */
+ {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
+ {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
+ {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
+ {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
+ {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
/*
* 920000..930000 ucode code RAM
* 930000..932000 ucode data RAM
@@ -327,6 +327,17 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
struct cfg80211_bss *bss;
+ u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
+ u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
+ u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
+ const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
+ size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
+ u.beacon.variable);
+ wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
+ wil_dbg_wmi(wil, "TSF : 0x%016llx\n", tsf);
+ wil_dbg_wmi(wil, "Beacon interval : %d\n", bi);
+ wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
+ ie_len, true);
bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
d_len, signal, GFP_KERNEL);
@@ -351,6 +362,9 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
bool aborted = (data->status != WMI_SCAN_SUCCESS);
wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+ wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
+ wil->scan_request, aborted);
+
del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, aborted);
wil->scan_request = NULL;
@@ -668,14 +682,12 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
for (n = 0;; n++) {
u16 len;
+ bool q;
r->head = ioread32(wil->csr + HOST_MBOX +
offsetof(struct wil6210_mbox_ctl, rx.head));
- if (r->tail == r->head) {
- if (n == 0)
- wil_dbg_wmi(wil, "No events?\n");
- return;
- }
+ if (r->tail == r->head)
+ break;
wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
r->head, r->tail);
@@ -684,14 +696,14 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
sizeof(struct wil6210_mbox_ring_desc));
if (d_tail.sync == 0) {
wil_err(wil, "Mbox evt not owned by FW?\n");
- return;
+ break;
}
/* read cmd header from descriptor */
if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
wil_err(wil, "Mbox evt at 0x%08x?\n",
le32_to_cpu(d_tail.addr));
- return;
+ break;
}
len = le16_to_cpu(hdr.len);
wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
@@ -705,7 +717,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
event.wmi) + len, 4),
GFP_KERNEL);
if (!evt)
- return;
+ break;
evt->event.hdr = hdr;
cmd = (void *)&evt->event.wmi;
@@ -737,14 +749,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
spin_lock_irqsave(&wil->wmi_ev_lock, flags);
list_add_tail(&evt->list, &wil->pending_wmi_ev);
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
- {
- int q = queue_work(wil->wmi_wq,
- &wil->wmi_event_worker);
- wil_dbg_wmi(wil, "queue_work -> %d\n", q);
- }
+ q = queue_work(wil->wmi_wq, &wil->wmi_event_worker);
+ wil_dbg_wmi(wil, "queue_work -> %d\n", q);
}
- if (n > 1)
- wil_dbg_wmi(wil, "%s -> %d events processed\n", __func__, n);
+ /* normally, 1 event per IRQ should be processed */
+ wil_dbg_wmi(wil, "%s -> %d events queued\n", __func__, n);
}
int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 1fe41af81a59..9183f1cf89a7 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2598,11 +2598,11 @@ static const iw_handler atmel_private_handler[] =
NULL, /* SIOCIWFIRSTPRIV */
};
-typedef struct atmel_priv_ioctl {
+struct atmel_priv_ioctl {
char id[32];
unsigned char __user *data;
unsigned short len;
-} atmel_priv_ioctl;
+};
#define ATMELFWL SIOCIWFIRSTPRIV
#define ATMELIDIFC ATMELFWL + 1
@@ -2615,7 +2615,7 @@ static const struct iw_priv_args atmel_private_args[] = {
.cmd = ATMELFWL,
.set_args = IW_PRIV_TYPE_BYTE
| IW_PRIV_SIZE_FIXED
- | sizeof (atmel_priv_ioctl),
+ | sizeof(struct atmel_priv_ioctl),
.get_args = IW_PRIV_TYPE_NONE,
.name = "atmelfwl"
}, {
@@ -2645,7 +2645,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
int i, rc = 0;
struct atmel_private *priv = netdev_priv(dev);
- atmel_priv_ioctl com;
+ struct atmel_priv_ioctl com;
struct iwreq *wrq = (struct iwreq *) rq;
unsigned char *new_firmware;
char domain[REGDOMAINSZ + 1];
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index 5cd97e3cbee3..bcf1f274a251 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -30,7 +30,7 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.")
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards");
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
{ 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID },
{ 0, }
};
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 40fd9b7b1426..64a5b672e30a 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -122,36 +122,41 @@ config B43_PIO
select SSB_BLOCKIO
default y
+config B43_PHY_G
+ bool "Support for G-PHY (802.11g) devices"
+ depends on B43 && B43_SSB
+ default y
+ ---help---
+ This PHY type can be found in the following chipsets:
+ PCI: BCM4306, BCM4311, BCM4318
+ SoC: BCM4712, BCM5352E
+
config B43_PHY_N
- bool "Support for 802.11n (N-PHY) devices"
+ bool "Support for N-PHY (the main 802.11n series) devices"
depends on B43
default y
---help---
- Support for the N-PHY.
-
- This enables support for devices with N-PHY.
-
- Say N if you expect high stability and performance. Saying Y will not
- affect other devices support and may provide support for basic needs.
+ This PHY type can be found in the following chipsets:
+ PCI: BCM4321, BCM4322,
+ BCM43222, BCM43224, BCM43225,
+ BCM43131, BCM43217, BCM43227, BCM43228
+ SoC: BCM4716, BCM4717, BCM4718, BCM5356, BCM5357, BCM5358
config B43_PHY_LP
- bool "Support for low-power (LP-PHY) devices"
+ bool "Support for LP-PHY (low-power 802.11g) devices"
depends on B43 && B43_SSB
default y
---help---
- Support for the LP-PHY.
The LP-PHY is a low-power PHY built into some notebooks
and embedded devices. It supports 802.11a/b/g
(802.11a support is optional, and currently disabled).
config B43_PHY_HT
- bool "Support for HT-PHY (high throughput) devices"
+ bool "Support for HT-PHY (high throughput 802.11n) devices"
depends on B43 && B43_BCMA
default y
---help---
- Support for the HT-PHY.
-
- Enables support for BCM4331 and possibly other chipsets with that PHY.
+ This PHY type with 3x3:3 MIMO can be found in the BCM4331 PCI chipset.
config B43_PHY_LCN
bool "Support for LCN-PHY devices (BROKEN)"
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 098fe9ee7096..6e00b8804ada 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,13 +1,11 @@
b43-y += main.o
b43-y += bus.o
-b43-y += tables.o
+b43-$(CONFIG_B43_PHY_G) += phy_a.o phy_g.o tables.o lo.o wa.o
b43-$(CONFIG_B43_PHY_N) += tables_nphy.o
b43-$(CONFIG_B43_PHY_N) += radio_2055.o
b43-$(CONFIG_B43_PHY_N) += radio_2056.o
b43-$(CONFIG_B43_PHY_N) += radio_2057.o
b43-y += phy_common.o
-b43-y += phy_g.o
-b43-y += phy_a.o
b43-$(CONFIG_B43_PHY_N) += phy_n.o
b43-$(CONFIG_B43_PHY_LP) += phy_lp.o
b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o
@@ -17,8 +15,6 @@ b43-$(CONFIG_B43_PHY_HT) += radio_2059.o
b43-$(CONFIG_B43_PHY_LCN) += phy_lcn.o tables_phy_lcn.o
b43-y += sysfs.o
b43-y += xmit.o
-b43-y += lo.o
-b43-y += wa.o
b43-y += dma.o
b43-y += pio.o
b43-y += rfkill.o
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 0d6a0bb1f876..2af1ac396eb4 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -122,7 +122,11 @@ static const struct bcma_device_id b43_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1E, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x28, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x2A, BCMA_ANY_CLASS),
BCMA_CORETABLE_END
};
MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
@@ -206,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
CHAN2G(13, 2472, 0),
CHAN2G(14, 2484, 0),
};
+
+/* No support for the last 3 channels (12, 13, 14) */
+#define b43_2ghz_chantable_limited_size 11
#undef CHAN2G
#define CHAN4G(_channel, _flags) { \
@@ -283,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
CHAN5G(182, 0),
};
+static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = {
+ CHAN5G(36, 0), CHAN5G(40, 0),
+ CHAN5G(44, 0), CHAN5G(48, 0),
+ CHAN5G(149, 0), CHAN5G(153, 0),
+ CHAN5G(157, 0), CHAN5G(161, 0),
+ CHAN5G(165, 0),
+};
+
static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
CHAN5G(34, 0), CHAN5G(36, 0),
CHAN5G(38, 0), CHAN5G(40, 0),
@@ -315,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = {
.n_bitrates = b43_a_ratetable_size,
};
+static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
+ .band = IEEE80211_BAND_5GHZ,
+ .channels = b43_5ghz_nphy_chantable_limited,
+ .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited),
+ .bitrates = b43_a_ratetable,
+ .n_bitrates = b43_a_ratetable_size,
+};
+
static struct ieee80211_supported_band b43_band_5GHz_aphy = {
.band = IEEE80211_BAND_5GHZ,
.channels = b43_5ghz_aphy_chantable,
@@ -331,6 +354,14 @@ static struct ieee80211_supported_band b43_band_2GHz = {
.n_bitrates = b43_g_ratetable_size,
};
+static struct ieee80211_supported_band b43_band_2ghz_limited = {
+ .band = IEEE80211_BAND_2GHZ,
+ .channels = b43_2ghz_chantable,
+ .n_channels = b43_2ghz_chantable_limited_size,
+ .bitrates = b43_g_ratetable,
+ .n_bitrates = b43_g_ratetable_size,
+};
+
static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
@@ -2201,52 +2232,82 @@ err_format:
return -EPROTO;
}
+/* http://bcm-v4.sipsolutions.net/802.11/Init/Firmware */
static int b43_try_request_fw(struct b43_request_fw_context *ctx)
{
struct b43_wldev *dev = ctx->dev;
struct b43_firmware *fw = &ctx->dev->fw;
+ struct b43_phy *phy = &dev->phy;
const u8 rev = ctx->dev->dev->core_rev;
const char *filename;
- u32 tmshigh;
int err;
- /* Files for HT and LCN were found by trying one by one */
-
/* Get microcode */
- if ((rev >= 5) && (rev <= 10)) {
- filename = "ucode5";
- } else if ((rev >= 11) && (rev <= 12)) {
- filename = "ucode11";
- } else if (rev == 13) {
- filename = "ucode13";
- } else if (rev == 14) {
- filename = "ucode14";
- } else if (rev == 15) {
+ filename = NULL;
+ switch (rev) {
+ case 42:
+ if (phy->type == B43_PHYTYPE_AC)
+ filename = "ucode42";
+ break;
+ case 40:
+ if (phy->type == B43_PHYTYPE_AC)
+ filename = "ucode40";
+ break;
+ case 33:
+ if (phy->type == B43_PHYTYPE_LCN40)
+ filename = "ucode33_lcn40";
+ break;
+ case 30:
+ if (phy->type == B43_PHYTYPE_N)
+ filename = "ucode30_mimo";
+ break;
+ case 29:
+ if (phy->type == B43_PHYTYPE_HT)
+ filename = "ucode29_mimo";
+ break;
+ case 26:
+ if (phy->type == B43_PHYTYPE_HT)
+ filename = "ucode26_mimo";
+ break;
+ case 28:
+ case 25:
+ if (phy->type == B43_PHYTYPE_N)
+ filename = "ucode25_mimo";
+ else if (phy->type == B43_PHYTYPE_LCN)
+ filename = "ucode25_lcn";
+ break;
+ case 24:
+ if (phy->type == B43_PHYTYPE_LCN)
+ filename = "ucode24_lcn";
+ break;
+ case 23:
+ if (phy->type == B43_PHYTYPE_N)
+ filename = "ucode16_mimo";
+ break;
+ case 16 ... 19:
+ if (phy->type == B43_PHYTYPE_N)
+ filename = "ucode16_mimo";
+ else if (phy->type == B43_PHYTYPE_LP)
+ filename = "ucode16_lp";
+ break;
+ case 15:
filename = "ucode15";
- } else {
- switch (dev->phy.type) {
- case B43_PHYTYPE_N:
- if (rev >= 16)
- filename = "ucode16_mimo";
- else
- goto err_no_ucode;
- break;
- case B43_PHYTYPE_HT:
- if (rev == 29)
- filename = "ucode29_mimo";
- else
- goto err_no_ucode;
- break;
- case B43_PHYTYPE_LCN:
- if (rev == 24)
- filename = "ucode24_mimo";
- else
- goto err_no_ucode;
- break;
- default:
- goto err_no_ucode;
- }
+ break;
+ case 14:
+ filename = "ucode14";
+ break;
+ case 13:
+ filename = "ucode13";
+ break;
+ case 11 ... 12:
+ filename = "ucode11";
+ break;
+ case 5 ... 10:
+ filename = "ucode5";
+ break;
}
+ if (!filename)
+ goto err_no_ucode;
err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
if (err)
goto err_load;
@@ -2268,117 +2329,121 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
goto err_load;
/* Get initvals */
+ filename = NULL;
switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
- if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
- filename = "a0g1initvals5";
- else
- filename = "a0g0initvals5";
- } else
- goto err_no_initvals;
- break;
case B43_PHYTYPE_G:
- if ((rev >= 5) && (rev <= 10))
- filename = "b0g0initvals5";
- else if (rev >= 13)
+ if (rev == 13)
filename = "b0g0initvals13";
- else
- goto err_no_initvals;
+ else if (rev >= 5 && rev <= 10)
+ filename = "b0g0initvals5";
break;
case B43_PHYTYPE_N:
- if (rev >= 16)
+ if (rev == 30)
+ filename = "n16initvals30";
+ else if (rev == 28 || rev == 25)
+ filename = "n0initvals25";
+ else if (rev == 24)
+ filename = "n0initvals24";
+ else if (rev == 23)
+ filename = "n0initvals16"; /* What about n0initvals22? */
+ else if (rev >= 16 && rev <= 18)
filename = "n0initvals16";
- else if ((rev >= 11) && (rev <= 12))
+ else if (rev >= 11 && rev <= 12)
filename = "n0initvals11";
- else
- goto err_no_initvals;
break;
case B43_PHYTYPE_LP:
- if (rev == 13)
- filename = "lp0initvals13";
+ if (rev >= 16 && rev <= 18)
+ filename = "lp0initvals16";
+ else if (rev == 15)
+ filename = "lp0initvals15";
else if (rev == 14)
filename = "lp0initvals14";
- else if (rev >= 15)
- filename = "lp0initvals15";
- else
- goto err_no_initvals;
+ else if (rev == 13)
+ filename = "lp0initvals13";
break;
case B43_PHYTYPE_HT:
if (rev == 29)
filename = "ht0initvals29";
- else
- goto err_no_initvals;
+ else if (rev == 26)
+ filename = "ht0initvals26";
break;
case B43_PHYTYPE_LCN:
if (rev == 24)
filename = "lcn0initvals24";
- else
- goto err_no_initvals;
break;
- default:
- goto err_no_initvals;
+ case B43_PHYTYPE_LCN40:
+ if (rev == 33)
+ filename = "lcn400initvals33";
+ break;
+ case B43_PHYTYPE_AC:
+ if (rev == 42)
+ filename = "ac1initvals42";
+ else if (rev == 40)
+ filename = "ac0initvals40";
+ break;
}
+ if (!filename)
+ goto err_no_initvals;
err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
if (err)
goto err_load;
/* Get bandswitch initvals */
+ filename = NULL;
switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- if ((rev >= 5) && (rev <= 10)) {
- tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
- if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
- filename = "a0g1bsinitvals5";
- else
- filename = "a0g0bsinitvals5";
- } else if (rev >= 11)
- filename = NULL;
- else
- goto err_no_initvals;
- break;
case B43_PHYTYPE_G:
- if ((rev >= 5) && (rev <= 10))
+ if (rev == 13)
+ filename = "b0g0bsinitvals13";
+ else if (rev >= 5 && rev <= 10)
filename = "b0g0bsinitvals5";
- else if (rev >= 11)
- filename = NULL;
- else
- goto err_no_initvals;
break;
case B43_PHYTYPE_N:
- if (rev >= 16)
+ if (rev == 30)
+ filename = "n16bsinitvals30";
+ else if (rev == 28 || rev == 25)
+ filename = "n0bsinitvals25";
+ else if (rev == 24)
+ filename = "n0bsinitvals24";
+ else if (rev == 23)
+ filename = "n0bsinitvals16"; /* What about n0bsinitvals22? */
+ else if (rev >= 16 && rev <= 18)
filename = "n0bsinitvals16";
- else if ((rev >= 11) && (rev <= 12))
+ else if (rev >= 11 && rev <= 12)
filename = "n0bsinitvals11";
- else
- goto err_no_initvals;
break;
case B43_PHYTYPE_LP:
- if (rev == 13)
- filename = "lp0bsinitvals13";
+ if (rev >= 16 && rev <= 18)
+ filename = "lp0bsinitvals16";
+ else if (rev == 15)
+ filename = "lp0bsinitvals15";
else if (rev == 14)
filename = "lp0bsinitvals14";
- else if (rev >= 15)
- filename = "lp0bsinitvals15";
- else
- goto err_no_initvals;
+ else if (rev == 13)
+ filename = "lp0bsinitvals13";
break;
case B43_PHYTYPE_HT:
if (rev == 29)
filename = "ht0bsinitvals29";
- else
- goto err_no_initvals;
+ else if (rev == 26)
+ filename = "ht0bsinitvals26";
break;
case B43_PHYTYPE_LCN:
if (rev == 24)
filename = "lcn0bsinitvals24";
- else
- goto err_no_initvals;
break;
- default:
- goto err_no_initvals;
+ case B43_PHYTYPE_LCN40:
+ if (rev == 33)
+ filename = "lcn400bsinitvals33";
+ break;
+ case B43_PHYTYPE_AC:
+ if (rev == 42)
+ filename = "ac1bsinitvals42";
+ else if (rev == 40)
+ filename = "ac0bsinitvals40";
+ break;
}
+ if (!filename)
+ goto err_no_initvals;
err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
if (err)
goto err_load;
@@ -2915,6 +2980,46 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
}
}
+/* brcms_b_switch_macfreq */
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
+{
+ u16 chip_id = dev->dev->chip_id;
+
+ if (chip_id == BCMA_CHIP_ID_BCM43131 ||
+ chip_id == BCMA_CHIP_ID_BCM43217 ||
+ chip_id == BCMA_CHIP_ID_BCM43222 ||
+ chip_id == BCMA_CHIP_ID_BCM43224 ||
+ chip_id == BCMA_CHIP_ID_BCM43225 ||
+ chip_id == BCMA_CHIP_ID_BCM43227 ||
+ chip_id == BCMA_CHIP_ID_BCM43228) {
+ switch (spurmode) {
+ case 2: /* 126 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ case 1: /* 123 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ default: /* 120 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ break;
+ }
+ } else if (dev->phy.type == B43_PHYTYPE_LCN) {
+ switch (spurmode) {
+ case 1: /* 82 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+ break;
+ default: /* 80 Mhz */
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+ break;
+ }
+ }
+}
+
static void b43_adjust_opmode(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
@@ -3798,38 +3903,29 @@ static void b43_set_retry_limits(struct b43_wldev *dev,
static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev;
- struct b43_phy *phy;
+ struct b43_wldev *dev = wl->current_dev;
+ struct b43_phy *phy = &dev->phy;
struct ieee80211_conf *conf = &hw->conf;
int antenna;
int err = 0;
- bool reload_bss = false;
mutex_lock(&wl->mutex);
-
- dev = wl->current_dev;
-
b43_mac_suspend(dev);
- /* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(dev, conf->chandef.chan);
- if (err)
- goto out_unlock_mutex;
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ phy->chandef = &conf->chandef;
+ phy->channel = conf->chandef.chan->hw_value;
- /* Need to reload all settings if the core changed */
- if (dev != wl->current_dev) {
- dev = wl->current_dev;
- changed = ~0;
- reload_bss = true;
- }
-
- phy = &dev->phy;
+ /* Switch the band (if necessary). */
+ err = b43_switch_band(dev, conf->chandef.chan);
+ if (err)
+ goto out_mac_enable;
- if (conf_is_ht(conf))
- phy->is_40mhz =
- (conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf));
- else
- phy->is_40mhz = false;
+ /* Switch to the requested channel.
+ * The firmware takes care of races with the TX handler.
+ */
+ b43_switch_channel(dev, phy->channel);
+ }
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
@@ -3838,11 +3934,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
if (!changed)
goto out_mac_enable;
- /* Switch to the requested channel.
- * The firmware takes care of races with the TX handler. */
- if (conf->chandef.chan->hw_value != phy->channel)
- b43_switch_channel(dev, conf->chandef.chan->hw_value);
-
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
/* Adjust the desired TX power level. */
@@ -3878,12 +3969,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
out_mac_enable:
b43_mac_enable(dev);
-out_unlock_mutex:
mutex_unlock(&wl->mutex);
- if (wl->vif && reload_bss)
- b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
-
return err;
}
@@ -4309,13 +4396,15 @@ static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
static int b43_phy_versioning(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ const u8 core_rev = dev->dev->core_rev;
u32 tmp;
u8 analog_type;
u8 phy_type;
u8 phy_rev;
u16 radio_manuf;
- u16 radio_ver;
+ u16 radio_id;
u16 radio_rev;
+ u8 radio_ver;
int unsupported = 0;
/* Get PHY versioning */
@@ -4323,23 +4412,23 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type = (tmp & B43_PHYVER_ANALOG) >> B43_PHYVER_ANALOG_SHIFT;
phy_type = (tmp & B43_PHYVER_TYPE) >> B43_PHYVER_TYPE_SHIFT;
phy_rev = (tmp & B43_PHYVER_VERSION);
+
+ /* LCNXN is continuation of N which run out of revisions */
+ if (phy_type == B43_PHYTYPE_LCNXN) {
+ phy_type = B43_PHYTYPE_N;
+ phy_rev += 16;
+ }
+
switch (phy_type) {
- case B43_PHYTYPE_A:
- if (phy_rev >= 4)
- unsupported = 1;
- break;
- case B43_PHYTYPE_B:
- if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6
- && phy_rev != 7)
- unsupported = 1;
- break;
+#ifdef CONFIG_B43_PHY_G
case B43_PHYTYPE_G:
if (phy_rev > 9)
unsupported = 1;
break;
+#endif
#ifdef CONFIG_B43_PHY_N
case B43_PHYTYPE_N:
- if (phy_rev > 9)
+ if (phy_rev >= 19)
unsupported = 1;
break;
#endif
@@ -4374,7 +4463,17 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
/* Get RADIO versioning */
- if (dev->dev->core_rev >= 24) {
+ if (core_rev == 40 || core_rev == 42) {
+ radio_manuf = 0x17F;
+
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0);
+ radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
+ radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+ radio_ver = 0; /* Is there version somewhere? */
+ } else if (core_rev >= 24) {
u16 radio24[3];
for (tmp = 0; tmp < 3; tmp++) {
@@ -4382,12 +4481,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
- /* Broadcom uses "id" for our "ver" and has separated "ver" */
- /* radio_ver = (radio24[0] & 0xF0) >> 4; */
-
radio_manuf = 0x17F;
- radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_id = (radio24[2] << 8) | radio24[1];
radio_rev = (radio24[0] & 0xF);
+ radio_ver = (radio24[0] & 0xF0) >> 4;
} else {
if (dev->dev->chip_id == 0x4317) {
if (dev->dev->chip_rev == 0)
@@ -4406,15 +4503,16 @@ static int b43_phy_versioning(struct b43_wldev *dev)
<< 16;
}
radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_id = (tmp & 0x0FFFF000) >> 12;
radio_rev = (tmp & 0xF0000000) >> 28;
+ radio_ver = 0; /* Probably not available on old hw */
}
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
case B43_PHYTYPE_A:
- if (radio_ver != 0x2060)
+ if (radio_id != 0x2060)
unsupported = 1;
if (radio_rev != 1)
unsupported = 1;
@@ -4422,43 +4520,49 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
case B43_PHYTYPE_B:
- if ((radio_ver & 0xFFF0) != 0x2050)
+ if ((radio_id & 0xFFF0) != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_G:
- if (radio_ver != 0x2050)
+ if (radio_id != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_N:
- if (radio_ver != 0x2055 && radio_ver != 0x2056)
+ if (radio_id != 0x2055 && radio_id != 0x2056 &&
+ radio_id != 0x2057)
+ unsupported = 1;
+ if (radio_id == 0x2057 &&
+ !(radio_rev == 9 || radio_rev == 14))
unsupported = 1;
break;
case B43_PHYTYPE_LP:
- if (radio_ver != 0x2062 && radio_ver != 0x2063)
+ if (radio_id != 0x2062 && radio_id != 0x2063)
unsupported = 1;
break;
case B43_PHYTYPE_HT:
- if (radio_ver != 0x2059)
+ if (radio_id != 0x2059)
unsupported = 1;
break;
case B43_PHYTYPE_LCN:
- if (radio_ver != 0x2064)
+ if (radio_id != 0x2064)
unsupported = 1;
break;
default:
B43_WARN_ON(1);
}
if (unsupported) {
- b43err(dev->wl, "FOUND UNSUPPORTED RADIO "
- "(Manuf 0x%X, Version 0x%X, Revision %u)\n",
- radio_manuf, radio_ver, radio_rev);
+ b43err(dev->wl,
+ "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
+ radio_manuf, radio_id, radio_rev, radio_ver);
return -EOPNOTSUPP;
}
- b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n",
- radio_manuf, radio_ver, radio_rev);
+ b43info(dev->wl,
+ "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
+ radio_manuf, radio_id, radio_rev, radio_ver);
+ /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
phy->radio_manuf = radio_manuf;
- phy->radio_ver = radio_ver;
+ phy->radio_ver = radio_id;
phy->radio_rev = radio_rev;
phy->analog = analog_type;
@@ -5066,12 +5170,24 @@ static int b43_setup_bands(struct b43_wldev *dev,
bool have_2ghz_phy, bool have_5ghz_phy)
{
struct ieee80211_hw *hw = dev->wl->hw;
+ struct b43_phy *phy = &dev->phy;
+ bool limited_2g;
+ bool limited_5g;
+
+ /* We don't support all 2 GHz channels on some devices */
+ limited_2g = phy->radio_ver == 0x2057 &&
+ (phy->radio_rev == 9 || phy->radio_rev == 14);
+ limited_5g = phy->radio_ver == 0x2057 &&
+ phy->radio_rev == 9;
if (have_2ghz_phy)
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ?
+ &b43_band_2ghz_limited : &b43_band_2GHz;
if (dev->phy.type == B43_PHYTYPE_N) {
if (have_5ghz_phy)
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ?
+ &b43_band_5GHz_nphy_limited :
+ &b43_band_5GHz_nphy;
} else {
if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
@@ -5219,14 +5335,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
/* We don't support 5 GHz on some PHYs yet */
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- case B43_PHYTYPE_G:
- case B43_PHYTYPE_N:
- case B43_PHYTYPE_LP:
- case B43_PHYTYPE_HT:
- b43warn(wl, "5 GHz band is unsupported on this PHY\n");
- have_5ghz_phy = false;
+ if (have_5ghz_phy) {
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ b43warn(wl, "5 GHz band is unsupported on this PHY\n");
+ have_5ghz_phy = false;
+ }
}
if (!have_2ghz_phy && !have_5ghz_phy) {
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index f476fc337d64..9f22e4b4c132 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
void b43_mac_suspend(struct b43_wldev *dev);
void b43_mac_enable(struct b43_wldev *dev);
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
struct b43_request_fw_context;
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index a6c38104693d..25e40432d68b 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -573,7 +573,7 @@ static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev)
{//TODO
}
-const struct b43_phy_operations b43_phyops_a = {
+static const struct b43_phy_operations b43_phyops_a = {
.allocate = b43_aphy_op_allocate,
.free = b43_aphy_op_free,
.prepare_structs = b43_aphy_op_prepare_structs,
diff --git a/drivers/net/wireless/b43/phy_a.h b/drivers/net/wireless/b43/phy_a.h
index 5cfaab7b16ee..f7d0d929a374 100644
--- a/drivers/net/wireless/b43/phy_a.h
+++ b/drivers/net/wireless/b43/phy_a.h
@@ -123,8 +123,4 @@ struct b43_phy_a {
*/
void b43_phy_inita(struct b43_wldev *dev);
-
-struct b43_phy_operations;
-extern const struct b43_phy_operations b43_phyops_a;
-
#endif /* LINUX_B43_PHY_A_H_ */
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 08244b3b327e..3cbef21b4726 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -45,11 +45,10 @@ int b43_phy_allocate(struct b43_wldev *dev)
phy->ops = NULL;
switch (phy->type) {
- case B43_PHYTYPE_A:
- phy->ops = &b43_phyops_a;
- break;
case B43_PHYTYPE_G:
+#ifdef CONFIG_B43_PHY_G
phy->ops = &b43_phyops_g;
+#endif
break;
case B43_PHYTYPE_N:
#ifdef CONFIG_B43_PHY_N
@@ -94,7 +93,13 @@ int b43_phy_init(struct b43_wldev *dev)
const struct b43_phy_operations *ops = phy->ops;
int err;
- phy->channel = ops->get_default_chan(dev);
+ /* During PHY init we need to use some channel. On the first init this
+ * function is called *before* b43_op_config, so our pointer is NULL.
+ */
+ if (!phy->chandef) {
+ phy->chandef = &dev->wl->hw->conf.chandef;
+ phy->channel = phy->chandef->chan->hw_value;
+ }
phy->ops->switch_analog(dev, true);
b43_software_rfkill(dev, false);
@@ -106,9 +111,7 @@ int b43_phy_init(struct b43_wldev *dev)
}
phy->do_full_init = false;
- /* Make sure to switch hardware and firmware (SHM) to
- * the default channel. */
- err = b43_switch_channel(dev, ops->get_default_chan(dev));
+ err = b43_switch_channel(dev, phy->channel);
if (err) {
b43err(dev->wl, "PHY init: Channel switch to default failed\n");
goto err_phy_exit;
@@ -408,9 +411,6 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
u16 channelcookie, savedcookie;
int err;
- if (new_channel == B43_DEFAULT_CHANNEL)
- new_channel = phy->ops->get_default_chan(dev);
-
/* First we set the channel radio code to prevent the
* firmware from sending ghost packets.
*/
@@ -428,7 +428,6 @@ int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
if (err)
goto err_restore_cookie;
- dev->phy.channel = new_channel;
/* Wait for the radio to tune to the channel and stabilize. */
msleep(8);
@@ -547,10 +546,9 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
}
-bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
+bool b43_is_40mhz(struct b43_wldev *dev)
{
- return (channel_type == NL80211_CHAN_HT40MINUS ||
- channel_type == NL80211_CHAN_HT40PLUS);
+ return dev->phy.chandef->width == NL80211_CHAN_WIDTH_40;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 4ad6240d9ff4..3912274f71e3 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -228,9 +228,6 @@ struct b43_phy {
bool supports_2ghz;
bool supports_5ghz;
- /* HT info */
- bool is_40mhz;
-
/* Is GMODE (2 GHz mode) bit enabled? */
bool gmode;
@@ -267,9 +264,8 @@ struct b43_phy {
unsigned long next_txpwr_check_time;
/* Current channel */
+ struct cfg80211_chan_def *chandef;
unsigned int channel;
- u16 channel_freq;
- enum nl80211_channel_type channel_type;
/* PHY TX errors counter. */
atomic_t txerr_cnt;
@@ -400,10 +396,6 @@ void b43_phy_take_out_of_reset(struct b43_wldev *dev);
* b43_switch_channel - Switch to another channel
*/
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
-/**
- * B43_DEFAULT_CHANNEL - Switch to the default channel.
- */
-#define B43_DEFAULT_CHANNEL UINT_MAX
/**
* b43_software_rfkill - Turn the radio ON or OFF in software.
@@ -454,7 +446,7 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
*/
void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
-bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+bool b43_is_40mhz(struct b43_wldev *dev);
void b43_phy_force_clock(struct b43_wldev *dev, bool force);
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index 5d6833f18498..f2974c6b1c01 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -596,7 +596,7 @@ static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
u8 target[3];
s16 a1[3], b0[3], b1[3];
- u16 freq = dev->phy.channel_freq;
+ u16 freq = dev->phy.chandef->chan->center_freq;
int i, c;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index 0bafa3b17035..e76bbdf3247e 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -54,39 +54,6 @@ enum lcn_sense_type {
B43_SENSE_VBAT,
};
-/* In theory it's PHY common function, move if needed */
-/* brcms_b_switch_macfreq */
-static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
-{
- if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
- switch (spurmode) {
- case 2: /* 126 Mhz */
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
- break;
- case 1: /* 123 Mhz */
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
- break;
- default: /* 120 Mhz */
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
- break;
- }
- } else if (dev->phy.type == B43_PHYTYPE_LCN) {
- switch (spurmode) {
- case 1: /* 82 Mhz */
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
- break;
- default: /* 80 Mhz */
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
- break;
- }
- }
-}
-
/**************************************************
* Radio 2064.
**************************************************/
@@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
}
- b43_phy_switch_macfreq(dev, enable);
+ b43_mac_switch_freq(dev, enable);
}
/**************************************************
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 86569f6a8705..e2a3f0d5bcc2 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -36,6 +36,7 @@
#include "main.h"
struct nphy_txgains {
+ u16 tx_lpf[2];
u16 txgm[2];
u16 pga[2];
u16 pad[2];
@@ -43,6 +44,7 @@ struct nphy_txgains {
};
struct nphy_iqcal_params {
+ u16 tx_lpf;
u16 txgm;
u16 pga;
u16 pad;
@@ -69,6 +71,14 @@ enum b43_nphy_rf_sequence {
B43_RFSEQ_UPDATE_GAINU,
};
+enum n_rf_ctl_over_cmd {
+ N_RF_CTL_OVER_CMD_RXRF_PU = 0,
+ N_RF_CTL_OVER_CMD_RX_PU = 1,
+ N_RF_CTL_OVER_CMD_TX_PU = 2,
+ N_RF_CTL_OVER_CMD_RX_GAIN = 3,
+ N_RF_CTL_OVER_CMD_TX_GAIN = 4,
+};
+
enum n_intc_override {
N_INTC_OVERRIDE_OFF = 0,
N_INTC_OVERRIDE_TRSW = 1,
@@ -140,11 +150,19 @@ ok:
b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
}
+static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
+ u16 value, u8 core, bool off,
+ u8 override_id)
+{
+ /* TODO */
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off,
u8 override)
{
+ struct b43_phy *phy = &dev->phy;
const struct nphy_rf_control_override_rev7 *e;
u16 en_addrs[3][2] = {
{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
@@ -154,6 +172,11 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
u16 val_addr;
u8 i;
+ if (phy->rev >= 19 || phy->rev < 3) {
+ B43_WARN_ON(1);
+ return;
+ }
+
/* Remember: we can get NULL! */
e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
@@ -181,6 +204,50 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
}
}
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
+static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
+ enum n_rf_ctl_over_cmd cmd,
+ u16 value, u8 core, bool off)
+{
+ struct b43_phy *phy = &dev->phy;
+ u16 tmp;
+
+ B43_WARN_ON(phy->rev < 7);
+
+ switch (cmd) {
+ case N_RF_CTL_OVER_CMD_RXRF_PU:
+ b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
+ break;
+ case N_RF_CTL_OVER_CMD_RX_PU:
+ b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
+ break;
+ case N_RF_CTL_OVER_CMD_TX_PU:
+ b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
+ break;
+ case N_RF_CTL_OVER_CMD_RX_GAIN:
+ tmp = value & 0xFF;
+ b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
+ tmp = value >> 8;
+ b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
+ break;
+ case N_RF_CTL_OVER_CMD_TX_GAIN:
+ tmp = value & 0x7FFF;
+ b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
+ tmp = value >> 14;
+ b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
+ break;
+ }
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
u16 value, u8 core, bool off)
@@ -264,6 +331,8 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
u16 reg, tmp, tmp2, val;
int core;
+ /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
+
for (core = 0; core < 2; core++) {
if ((core_sel == 1 && core != 0) ||
(core_sel == 2 && core != 1))
@@ -274,6 +343,7 @@ static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
switch (intc_override) {
case N_INTC_OVERRIDE_OFF:
b43_phy_write(dev, reg, 0);
+ b43_phy_mask(dev, 0x2ff, ~0x2000);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
break;
case N_INTC_OVERRIDE_TRSW:
@@ -505,6 +575,14 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
}
}
+/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
+static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
+{
+ if (!offset)
+ offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
+ return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
{
@@ -590,44 +668,270 @@ static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
* Radio 0x2057
**************************************************/
-/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
+static void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
+ const struct b43_nphy_chantabent_rev7 *e_r7,
+ const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
+{
+ if (e_r7_2g) {
+ b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
+ b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
+ b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
+ b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
+ b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
+ b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
+ b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
+ b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
+ b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
+ b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
+ b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
+
+ } else {
+ b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
+ b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
+ b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
+ b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
+ b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
+ b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
+ b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
+ b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
+ b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
+ b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
+ b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
+ b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
+ b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
+ b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
+ b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
+ b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
+ b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
+ b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
+ b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
+ b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
+ b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
+ }
+}
+
+static void b43_radio_2057_setup(struct b43_wldev *dev,
+ const struct b43_nphy_chantabent_rev7 *tabent_r7,
+ const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);
+
+ switch (phy->radio_rev) {
+ case 0 ... 4:
+ case 6:
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
+ b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+ } else {
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
+ b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+ }
+ break;
+ case 9: /* e.g. PHY rev 16 */
+ b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
+ b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
+ b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
+
+ if (b43_is_40mhz(dev)) {
+ /* TODO */
+ } else {
+ b43_radio_write(dev,
+ R2057_PAD_BIAS_FILTER_BWS_CORE0,
+ 0x3c);
+ b43_radio_write(dev,
+ R2057_PAD_BIAS_FILTER_BWS_CORE1,
+ 0x3c);
+ }
+ }
+ break;
+ case 14: /* 2 GHz only */
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
+ b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
+ b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
+ break;
+ }
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ u16 txmix2g_tune_boost_pu = 0;
+ u16 pad2g_tune_pus = 0;
+
+ if (b43_nphy_ipa(dev)) {
+ switch (phy->radio_rev) {
+ case 9:
+ txmix2g_tune_boost_pu = 0x0041;
+ /* TODO */
+ break;
+ case 14:
+ txmix2g_tune_boost_pu = 0x21;
+ pad2g_tune_pus = 0x23;
+ break;
+ }
+ }
+
+ if (txmix2g_tune_boost_pu)
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+ txmix2g_tune_boost_pu);
+ if (pad2g_tune_pus)
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
+ pad2g_tune_pus);
+ if (txmix2g_tune_boost_pu)
+ b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+ txmix2g_tune_boost_pu);
+ if (pad2g_tune_pus)
+ b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
+ pad2g_tune_pus);
+ }
+
+ usleep_range(50, 100);
+
+ /* VCO calibration */
+ b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
+ b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
+ b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
+ b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
+ usleep_range(300, 600);
+}
+
+/* Calibrate resistors in LPF of PLL?
+ * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
+ */
static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ u16 saved_regs_phy[12];
+ u16 saved_regs_phy_rf[6];
+ u16 saved_regs_radio[2] = { };
+ static const u16 phy_to_store[] = {
+ B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
+ B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
+ B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
+ B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
+ B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+ B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
+ };
+ static const u16 phy_to_store_rf[] = {
+ B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
+ B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+ B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
+ };
u16 tmp;
+ int i;
- if (phy->radio_rev == 5) {
- b43_phy_mask(dev, 0x342, ~0x2);
+ /* Save */
+ for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+ saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
+ for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+ saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
+
+ /* Set */
+ for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+ b43_phy_write(dev, phy_to_store[i], 0);
+ b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
+ b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
+
+ switch (phy->radio_rev) {
+ case 5:
+ b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
udelay(10);
b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
- b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
+ b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
+ break;
+ case 9:
+ b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+ b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+ saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+ b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
+ break;
+ case 14:
+ saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+ saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
+ b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+ b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+ b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
+ b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
+ break;
}
+ /* Enable */
b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
udelay(10);
- b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
- if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
+
+ /* Start */
+ b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
+ usleep_range(100, 200);
+
+ /* Stop */
+ b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
+
+ /* Wait and check for result */
+ if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
return 0;
}
- b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
+
+ /* Disable */
b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
- if (phy->radio_rev == 5) {
- b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
- b43_radio_mask(dev, 0x1ca, ~0x2);
- }
- if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+ /* Restore */
+ for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+ b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
+ for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+ b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
+
+ switch (phy->radio_rev) {
+ case 0 ... 4:
+ case 6:
b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
tmp << 2);
+ break;
+ case 5:
+ b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
+ b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
+ break;
+ case 9:
+ b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+ break;
+ case 14:
+ b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+ b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
+ break;
}
return tmp & 0x3e;
}
-/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */
+/* Calibrate the internal RC oscillator?
+ * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
+ */
static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
@@ -635,49 +939,76 @@ static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
phy->radio_rev == 6);
u16 tmp;
+ /* Setup cal */
if (special) {
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
} else {
- b43_radio_write(dev, 0x1AE, 0x61);
- b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
+ b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
}
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+ /* Start, wait, stop */
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
- if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
5000000))
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+ usleep_range(35, 70);
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ usleep_range(70, 140);
+
+ /* Setup cal */
if (special) {
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
} else {
- b43_radio_write(dev, 0x1AE, 0x69);
+ b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
}
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+ /* Start, wait, stop */
+ usleep_range(35, 70);
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
- if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ usleep_range(70, 140);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
5000000))
b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+ usleep_range(35, 70);
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ usleep_range(70, 140);
+
+ /* Setup cal */
if (special) {
b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
} else {
- b43_radio_write(dev, 0x1AE, 0x73);
+ b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
}
+
+ /* Start, wait, stop */
+ usleep_range(35, 70);
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
- if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ usleep_range(70, 140);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
5000000)) {
b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
return 0;
}
tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
+ usleep_range(35, 70);
b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ usleep_range(70, 140);
+
+ if (special)
+ b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
+ else
+ b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);
+
return tmp;
}
@@ -694,6 +1025,9 @@ static void b43_radio_2057_init_post(struct b43_wldev *dev)
{
b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
+ if (0) /* FIXME: Is this BCM43217 specific? */
+ b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
+
b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
mdelay(2);
@@ -798,6 +1132,7 @@ static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
static void b43_radio_2056_setup(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry_rev3 *e)
{
+ struct b43_phy *phy = &dev->phy;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
enum ieee80211_band band = b43_current_band(dev->wl);
u16 offset;
@@ -895,7 +1230,7 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
offset | B2056_TX_MIXG_BOOST_TUNE,
mixg_boost);
} else {
- bias = dev->phy.is_40mhz ? 0x40 : 0x20;
+ bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
b43_radio_write(dev,
offset | B2056_TX_INTPAG_IMAIN_STAT,
bias);
@@ -909,7 +1244,7 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
}
} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
- u16 freq = dev->phy.channel_freq;
+ u16 freq = phy->chandef->chan->center_freq;
if (freq < 5100) {
paa_boost = 0xA;
pada_boost = 0x77;
@@ -1210,8 +1545,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
u16 bw, len, rot, angle;
struct b43_c32 *samples;
-
- bw = (dev->phy.is_40mhz) ? 40 : 20;
+ bw = b43_is_40mhz(dev) ? 40 : 20;
len = bw << 3;
if (test) {
@@ -1220,7 +1554,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
else
bw = 80;
- if (dev->phy.is_40mhz)
+ if (b43_is_40mhz(dev))
bw <<= 1;
len = bw << 1;
@@ -1248,8 +1582,10 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
- u16 wait, bool iqmode, bool dac_test)
+ u16 wait, bool iqmode, bool dac_test,
+ bool modify_bbmult)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
int i;
u16 seq_mode;
@@ -1257,17 +1593,35 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
b43_nphy_stay_in_carrier_search(dev, true);
+ if (phy->rev >= 7) {
+ bool lpf_bw3, lpf_bw4;
+
+ lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
+ lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
+
+ if (lpf_bw3 || lpf_bw4) {
+ /* TODO */
+ } else {
+ u16 value = b43_nphy_read_lpf_ctl(dev, 0);
+ if (phy->rev >= 19)
+ b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
+ 0, false, 1);
+ else
+ b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
+ 0, false, 1);
+ nphy->lpf_bw_overrode_for_sample_play = true;
+ }
+ }
+
if ((nphy->bb_mult_save & 0x80000000) == 0) {
tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
}
- /* TODO: add modify_bbmult argument */
- if (!dev->phy.is_40mhz)
- tmp = 0x6464;
- else
- tmp = 0x4747;
- b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+ if (modify_bbmult) {
+ tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
+ b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+ }
b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
@@ -1285,10 +1639,8 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
} else {
- if (dac_test)
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
- else
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
+ tmp = dac_test ? 5 : 1;
+ b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
}
for (i = 0; i < 100; i++) {
if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
@@ -1388,6 +1740,12 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
}
}
+static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type rssi_type)
+{
+ /* TODO */
+}
+
static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
enum n_rssi_type rssi_type)
{
@@ -1457,13 +1815,15 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
enum ieee80211_band band =
b43_current_band(dev->wl);
- if (b43_nphy_ipa(dev))
- val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
- else
- val = 0x11;
- reg = (i == 0) ? 0x2000 : 0x3000;
- reg |= B2055_PADDRV;
- b43_radio_write(dev, reg, val);
+ if (dev->phy.rev < 7) {
+ if (b43_nphy_ipa(dev))
+ val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
+ else
+ val = 0x11;
+ reg = (i == 0) ? B2056_TX0 : B2056_TX1;
+ reg |= B2056_TX_TX_SSI_MUX;
+ b43_radio_write(dev, reg, val);
+ }
reg = (i == 0) ?
B43_NPHY_AFECTL_OVER1 :
@@ -1550,7 +1910,9 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
enum n_rssi_type type)
{
- if (dev->phy.rev >= 3)
+ if (dev->phy.rev >= 19)
+ b43_nphy_rssi_select_rev19(dev, code, type);
+ else if (dev->phy.rev >= 3)
b43_nphy_rev3_rssi_select(dev, code, type);
else
b43_nphy_rev2_rssi_select(dev, code, type);
@@ -1594,6 +1956,8 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
u16 save_regs_phy[9];
u16 s[2];
+ /* TODO: rev7+ is treated like rev3+, what about rev19+? */
+
if (dev->phy.rev >= 3) {
save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
@@ -1675,6 +2039,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
u16 saved_regs_phy_rfctl[2];
@@ -1692,12 +2057,14 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
- 0x342, 0x343, 0x346, 0x347,
+ B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+ B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
0x2ff,
B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
B43_NPHY_RFCTL_CMD,
B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
- 0x340, 0x341, 0x344, 0x345,
+ B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+ B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
};
u16 *regs_to_store;
@@ -1744,9 +2111,24 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
if (dev->phy.rev >= 7) {
- /* TODO */
+ b43_nphy_rf_ctl_override_one_to_many(dev,
+ N_RF_CTL_OVER_CMD_RXRF_PU,
+ 0, 0, false);
+ b43_nphy_rf_ctl_override_one_to_many(dev,
+ N_RF_CTL_OVER_CMD_RX_PU,
+ 1, 0, false);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
+ 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
+ 0);
} else {
+ b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
+ 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
+ 0);
}
} else {
b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
@@ -1775,7 +2157,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
/* Grab RSSI results for every possible VCM */
for (vcm = 0; vcm < 8; vcm++) {
if (dev->phy.rev >= 7)
- ;
+ b43_radio_maskset(dev,
+ core ? R2057_NB_MASTER_CORE1 :
+ R2057_NB_MASTER_CORE0,
+ ~R2057_VCM_MASK, vcm);
else
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
0xE3, vcm << 2);
@@ -1806,7 +2191,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
/* Select the best VCM */
if (dev->phy.rev >= 7)
- ;
+ b43_radio_maskset(dev,
+ core ? R2057_NB_MASTER_CORE1 :
+ R2057_NB_MASTER_CORE0,
+ ~R2057_VCM_MASK, vcm);
else
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
0xE3, vcm_final << 2);
@@ -1876,6 +2264,10 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
if (dev->phy.rev >= 7) {
+ rssical_radio_regs[0] = b43_radio_read(dev,
+ R2057_NB_MASTER_CORE0);
+ rssical_radio_regs[1] = b43_radio_read(dev,
+ R2057_NB_MASTER_CORE1);
} else {
rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
B2056_RX_RSSI_MISC);
@@ -1897,9 +2289,9 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
/* Remember for which channel we store configuration */
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq;
+ nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq;
else
- nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_freq;
+ nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq;
/* End of calibration, restore configuration */
b43_nphy_classifier(dev, 7, class);
@@ -2076,7 +2468,9 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
*/
static void b43_nphy_rssi_cal(struct b43_wldev *dev)
{
- if (dev->phy.rev >= 3) {
+ if (dev->phy.rev >= 19) {
+ /* TODO */
+ } else if (dev->phy.rev >= 3) {
b43_nphy_rev3_rssi_cal(dev);
} else {
b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
@@ -2089,7 +2483,21 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev)
* Workarounds
**************************************************/
-static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
+static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
+{
+ /* TODO */
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ switch (phy->rev) {
+ /* TODO */
+ }
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -2192,7 +2600,7 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
- if (!dev->phy.is_40mhz) {
+ if (!b43_is_40mhz(dev)) {
/* Set dwell lengths */
b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
@@ -2206,7 +2614,7 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
- if (!dev->phy.is_40mhz) {
+ if (!b43_is_40mhz(dev)) {
b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
@@ -2221,12 +2629,12 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
if (nphy->gain_boost) {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
- dev->phy.is_40mhz)
+ b43_is_40mhz(dev))
code = 4;
else
code = 5;
} else {
- code = dev->phy.is_40mhz ? 6 : 7;
+ code = b43_is_40mhz(dev) ? 6 : 7;
}
/* Set HPVGA2 index */
@@ -2286,46 +2694,54 @@ static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
{
- if (dev->phy.rev >= 7)
- ; /* TODO */
+ if (dev->phy.rev >= 19)
+ b43_nphy_gain_ctl_workarounds_rev19(dev);
+ else if (dev->phy.rev >= 7)
+ b43_nphy_gain_ctl_workarounds_rev7(dev);
else if (dev->phy.rev >= 3)
- b43_nphy_gain_ctl_workarounds_rev3plus(dev);
+ b43_nphy_gain_ctl_workarounds_rev3(dev);
else
b43_nphy_gain_ctl_workarounds_rev1_2(dev);
}
-/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
-static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
-{
- if (!offset)
- offset = (dev->phy.is_40mhz) ? 0x159 : 0x154;
- return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
-}
-
static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
+ /* TX to RX */
+ u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
+ u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
+ /* RX to TX */
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
0x1F };
u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
- u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
+ static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
u8 ntab7_138_146[] = { 0x11, 0x11 };
u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
- u16 lpf_20, lpf_40, lpf_11b;
- u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
- u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
+ u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
+ u16 bcap_val;
+ s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
+ u16 scap_val;
+ s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
bool rccal_ovrd = false;
- u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
u16 bias, conv, filt;
+ u32 noise_tbl[2];
+
u32 tmp32;
u8 core;
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
if (phy->rev == 7) {
b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
@@ -2345,11 +2761,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
}
- if (phy->rev <= 8) {
+
+ if (phy->rev >= 16) {
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
+ } else if (phy->rev <= 8) {
b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
}
- if (phy->rev >= 8)
+
+ if (phy->rev >= 16)
+ b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
+ else if (phy->rev >= 8)
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
@@ -2357,9 +2780,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
+ b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+ ARRAY_SIZE(tx2rx_events));
if (b43_nphy_ipa(dev))
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
@@ -2367,84 +2792,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
- lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
- lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
- lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
+ for (core = 0; core < 2; core++) {
+ lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
+ lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
+ lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
+ }
+
+ bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
+ scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
+
if (b43_nphy_ipa(dev)) {
- if ((phy->radio_rev == 5 && phy->is_40mhz) ||
- phy->radio_rev == 7 || phy->radio_rev == 8) {
- bcap_val = b43_radio_read(dev, 0x16b);
- scap_val = b43_radio_read(dev, 0x16a);
- scap_val_11b = scap_val;
- bcap_val_11b = bcap_val;
- if (phy->radio_rev == 5 && phy->is_40mhz) {
- scap_val_11n_20 = scap_val;
- bcap_val_11n_20 = bcap_val;
- scap_val_11n_40 = bcap_val_11n_40 = 0xc;
+ bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ;
+
+ switch (phy->radio_rev) {
+ case 5:
+ /* Check radio version (to be 0) by PHY rev for now */
+ if (phy->rev == 8 && b43_is_40mhz(dev)) {
+ for (core = 0; core < 2; core++) {
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11n_20[core] = scap_val;
+ bcap_val_11n_20[core] = bcap_val;
+ scap_val_11n_40[core] = 0xc;
+ bcap_val_11n_40[core] = 0xc;
+ }
+
rccal_ovrd = true;
- } else { /* Rev 7/8 */
- lpf_20 = 4;
- lpf_11b = 1;
+ }
+ if (phy->rev == 9) {
+ /* TODO: Radio version 1 (e.g. BCM5357B0) */
+ }
+ break;
+ case 7:
+ case 8:
+ for (core = 0; core < 2; core++) {
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ lpf_ofdm_20mhz[core] = 4;
+ lpf_11b[core] = 1;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- scap_val_11n_20 = 0xc;
- bcap_val_11n_20 = 0xc;
- scap_val_11n_40 = 0xa;
- bcap_val_11n_40 = 0xa;
+ scap_val_11n_20[core] = 0xc;
+ bcap_val_11n_20[core] = 0xc;
+ scap_val_11n_40[core] = 0xa;
+ bcap_val_11n_40[core] = 0xa;
} else {
- scap_val_11n_20 = 0x14;
- bcap_val_11n_20 = 0x14;
- scap_val_11n_40 = 0xf;
- bcap_val_11n_40 = 0xf;
+ scap_val_11n_20[core] = 0x14;
+ bcap_val_11n_20[core] = 0x14;
+ scap_val_11n_40[core] = 0xf;
+ bcap_val_11n_40[core] = 0xf;
}
- rccal_ovrd = true;
}
+
+ rccal_ovrd = true;
+ break;
+ case 9:
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11b[core] = scap_val;
+ lpf_11b[core] = 1;
+
+ if (ghz2) {
+ bcap_val_11n_20[core] = bcap_val + 13;
+ scap_val_11n_20[core] = scap_val + 15;
+ } else {
+ bcap_val_11n_20[core] = bcap_val + 14;
+ scap_val_11n_20[core] = scap_val + 15;
+ }
+ lpf_ofdm_20mhz[core] = 4;
+
+ if (ghz2) {
+ bcap_val_11n_40[core] = bcap_val - 7;
+ scap_val_11n_40[core] = scap_val - 5;
+ } else {
+ bcap_val_11n_40[core] = bcap_val + 2;
+ scap_val_11n_40[core] = scap_val + 4;
+ }
+ lpf_ofdm_40mhz[core] = 4;
+ }
+
+ rccal_ovrd = true;
+ break;
+ case 14:
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11b[core] = scap_val;
+ lpf_11b[core] = 1;
+ }
+
+ bcap_val_11n_20[0] = bcap_val + 20;
+ scap_val_11n_20[0] = scap_val + 20;
+ lpf_ofdm_20mhz[0] = 3;
+
+ bcap_val_11n_20[1] = bcap_val + 16;
+ scap_val_11n_20[1] = scap_val + 16;
+ lpf_ofdm_20mhz[1] = 3;
+
+ bcap_val_11n_40[0] = bcap_val + 20;
+ scap_val_11n_40[0] = scap_val + 20;
+ lpf_ofdm_40mhz[0] = 4;
+
+ bcap_val_11n_40[1] = bcap_val + 10;
+ scap_val_11n_40[1] = scap_val + 10;
+ lpf_ofdm_40mhz[1] = 4;
+
+ rccal_ovrd = true;
+ break;
}
} else {
if (phy->radio_rev == 5) {
- lpf_20 = 1;
- lpf_40 = 3;
- bcap_val = b43_radio_read(dev, 0x16b);
- scap_val = b43_radio_read(dev, 0x16a);
- scap_val_11b = scap_val;
- bcap_val_11b = bcap_val;
- scap_val_11n_20 = 0x11;
- scap_val_11n_40 = 0x11;
- bcap_val_11n_20 = 0x13;
- bcap_val_11n_40 = 0x13;
+ for (core = 0; core < 2; core++) {
+ lpf_ofdm_20mhz[core] = 1;
+ lpf_ofdm_40mhz[core] = 3;
+ scap_val_11b[core] = scap_val;
+ bcap_val_11b[core] = bcap_val;
+ scap_val_11n_20[core] = 0x11;
+ scap_val_11n_40[core] = 0x11;
+ bcap_val_11n_20[core] = 0x13;
+ bcap_val_11n_40[core] = 0x13;
+ }
+
rccal_ovrd = true;
}
}
if (rccal_ovrd) {
- rx2tx_lut_20_11b = (bcap_val_11b << 8) |
- (scap_val_11b << 3) |
- lpf_11b;
- rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
- (scap_val_11n_20 << 3) |
- lpf_20;
- rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
- (scap_val_11n_40 << 3) |
- lpf_40;
+ u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
+ u8 rx2tx_lut_extra = 1;
+
+ for (core = 0; core < 2; core++) {
+ bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
+ scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
+ bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
+ scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
+ bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
+ scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
+
+ rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11b[core] << 8) |
+ (scap_val_11b[core] << 3) |
+ lpf_11b[core];
+ rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11n_20[core] << 8) |
+ (scap_val_11n_20[core] << 3) |
+ lpf_ofdm_20mhz[core];
+ rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
+ (bcap_val_11n_40[core] << 8) |
+ (scap_val_11n_40[core] << 3) |
+ lpf_ofdm_40mhz[core];
+ }
+
for (core = 0; core < 2; core++) {
b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
- rx2tx_lut_20_11b);
+ rx2tx_lut_20_11b[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
- rx2tx_lut_20_11n);
+ rx2tx_lut_20_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
- rx2tx_lut_20_11n);
+ rx2tx_lut_20_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
- rx2tx_lut_40_11n);
+ rx2tx_lut_40_11n[core]);
}
- b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
}
+
b43_phy_write(dev, 0x32F, 0x3);
+
if (phy->radio_rev == 4 || phy->radio_rev == 6)
b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
@@ -2492,7 +3009,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
0x7f);
}
}
- if (phy->radio_rev == 3) {
+ switch (phy->radio_rev) {
+ case 3:
for (core = 0; core < 2; core++) {
if (core == 0) {
b43_radio_write(dev, 0x64,
@@ -2518,17 +3036,34 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
0x3E);
}
}
- } else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
- if (!phy->is_40mhz) {
+ break;
+ case 7:
+ case 8:
+ if (!b43_is_40mhz(dev)) {
b43_radio_write(dev, 0x5F, 0x14);
b43_radio_write(dev, 0xE8, 0x12);
} else {
b43_radio_write(dev, 0x5F, 0x16);
b43_radio_write(dev, 0xE8, 0x16);
}
+ break;
+ case 14:
+ for (core = 0; core < 2; core++) {
+ int o = core ? 0x85 : 0;
+
+ b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
+ b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
+ b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
+ b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
+ b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
+ b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
+ b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
+ b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
+ }
+ break;
}
} else {
- u16 freq = phy->channel_freq;
+ u16 freq = phy->chandef->chan->center_freq;
if ((freq >= 5180 && freq <= 5230) ||
(freq >= 5745 && freq <= 5805)) {
b43_radio_write(dev, 0x7D, 0xFF);
@@ -2573,8 +3108,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
- b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
- b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
@@ -2585,20 +3120,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
- b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
+ b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
- if (!phy->is_40mhz) {
- b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
- b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
- } else {
- b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
- b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
- }
+ b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
+ noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+ b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
+
+ b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
+ noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+ b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
b43_nphy_gain_ctl_workarounds(dev);
@@ -2691,7 +3226,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
- if (!dev->phy.is_40mhz) {
+ if (!b43_is_40mhz(dev)) {
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
} else {
@@ -2926,6 +3461,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_IQFLIP,
B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+ /* TODO: rev19+ */
if (dev->phy.rev >= 7)
b43_nphy_workarounds_rev7plus(dev);
else if (dev->phy.rev >= 3)
@@ -2946,12 +3482,13 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
*/
static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
- bool iqmode, bool dac_test)
+ bool iqmode, bool dac_test, bool modify_bbmult)
{
u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
if (samp == 0)
return -1;
- b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
+ b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,
+ modify_bbmult);
return 0;
}
@@ -2986,6 +3523,7 @@ static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
static void b43_nphy_stop_playback(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
u16 tmp;
@@ -3006,6 +3544,15 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev)
nphy->bb_mult_save = 0;
}
+ if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
+ if (phy->rev >= 19)
+ b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
+ 1);
+ else
+ b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
+ nphy->lpf_bw_overrode_for_sample_play = false;
+ }
+
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 0);
}
@@ -3015,16 +3562,23 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
struct nphy_txgains target,
struct nphy_iqcal_params *params)
{
+ struct b43_phy *phy = &dev->phy;
int i, j, indx;
u16 gain;
if (dev->phy.rev >= 3) {
+ params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
params->txgm = target.txgm[core];
params->pga = target.pga[core];
params->pad = target.pad[core];
params->ipa = target.ipa[core];
- params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
- (params->pad << 4) | (params->ipa);
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
+ } else {
+ params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
+ }
for (j = 0; j < 5; j++)
params->ncorr[j] = 0x79;
} else {
@@ -3065,6 +3619,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
u8 i;
u16 bmask, val, tmp;
@@ -3114,7 +3669,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
- if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ if (dev->phy.rev < 2 && b43_is_40mhz(dev))
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
} else {
b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
@@ -3134,12 +3689,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
if (band == IEEE80211_BAND_5GHZ) {
- b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
- ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
- if (dev->phy.rev > 1)
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT,
+ 0x32);
b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
~B43_NPHY_TXPCTL_INIT_PIDXI1,
+ 0x32);
+ } else {
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT,
0x64);
+ if (phy->rev > 1)
+ b43_phy_maskset(dev,
+ B43_NPHY_TXPCTL_INIT,
+ ~B43_NPHY_TXPCTL_INIT_PIDXI1,
+ 0x64);
+ }
}
if (dev->phy.rev >= 3) {
@@ -3156,6 +3724,10 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
}
}
+ if (phy->rev >= 7) {
+ /* TODO */
+ }
+
if (dev->phy.rev >= 3) {
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
@@ -3168,7 +3740,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
else if (dev->phy.rev < 2)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
- if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ if (dev->phy.rev < 2 && b43_is_40mhz(dev))
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
if (b43_nphy_ipa(dev)) {
@@ -3184,18 +3756,20 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
u8 txpi[2], bbmult, i;
u16 tmp, radio_gain, dac_gain;
- u16 freq = dev->phy.channel_freq;
+ u16 freq = phy->chandef->chan->center_freq;
u32 txgain;
/* u32 gaintbl; rev3+ */
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1);
+ /* TODO: rev19+ */
if (dev->phy.rev >= 7) {
txpi[0] = txpi[1] = 30;
} else if (dev->phy.rev >= 3) {
@@ -3234,7 +3808,11 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
*/
for (i = 0; i < 2; i++) {
- txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]);
+ const u32 *table = b43_nphy_get_tx_gain_table(dev);
+
+ if (!table)
+ break;
+ txgain = *(table + txpi[i]);
if (dev->phy.rev >= 3)
radio_gain = (txgain >> 16) & 0x1FFFF;
@@ -3294,7 +3872,9 @@ static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
u8 core;
u16 r; /* routing */
- if (phy->rev >= 7) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
for (core = 0; core < 2; core++) {
r = core ? 0x190 : 0x170;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
@@ -3377,29 +3957,38 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
u32 tmp;
s32 rssi[4] = { };
- /* TODO: check if we can transmit */
+ if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
+ return;
if (b43_nphy_ipa(dev))
b43_nphy_ipa_internal_tssi_setup(dev);
- if (phy->rev >= 7)
- b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0);
+ if (phy->rev >= 19)
+ b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
+ else if (phy->rev >= 7)
+ b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
else if (phy->rev >= 3)
b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
b43_nphy_stop_playback(dev);
- b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
+ b43_nphy_tx_tone(dev, 4000, 0, false, false, false);
udelay(20);
tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
b43_nphy_stop_playback(dev);
+
b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
- if (phy->rev >= 7)
- b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0);
+ if (phy->rev >= 19)
+ b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
+ else if (phy->rev >= 7)
+ b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
else if (phy->rev >= 3)
b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
- if (phy->rev >= 3) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ return;
+ } else if (phy->rev >= 3) {
nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
} else {
@@ -3439,21 +4028,21 @@ static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
delta = 0;
switch (stf_mode) {
case 0:
- if (dev->phy.is_40mhz && dev->phy.rev >= 5) {
+ if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {
idx = 68;
} else {
delta = 1;
- idx = dev->phy.is_40mhz ? 52 : 4;
+ idx = b43_is_40mhz(dev) ? 52 : 4;
}
break;
case 1:
- idx = dev->phy.is_40mhz ? 76 : 28;
+ idx = b43_is_40mhz(dev) ? 76 : 28;
break;
case 2:
- idx = dev->phy.is_40mhz ? 84 : 36;
+ idx = b43_is_40mhz(dev) ? 84 : 36;
break;
case 3:
- idx = dev->phy.is_40mhz ? 92 : 44;
+ idx = b43_is_40mhz(dev) ? 92 : 44;
break;
}
@@ -3474,6 +4063,7 @@ static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -3483,7 +4073,7 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
s32 num, den, pwr;
u32 regval[64];
- u16 freq = dev->phy.channel_freq;
+ u16 freq = phy->chandef->chan->center_freq;
u16 tmp;
u16 r; /* routing */
u8 i, c;
@@ -3590,7 +4180,9 @@ static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
udelay(1);
}
- if (dev->phy.rev >= 7) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
@@ -3647,27 +4239,36 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
int i;
table = b43_nphy_get_tx_gain_table(dev);
+ if (!table)
+ return;
+
b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
- if (phy->rev >= 3) {
+ if (phy->rev < 3)
+ return;
+
#if 0
- nphy->gmval = (table[0] >> 16) & 0x7000;
+ nphy->gmval = (table[0] >> 16) & 0x7000;
#endif
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < 128; i++) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ return;
+ } else if (phy->rev >= 7) {
+ /* TODO */
+ return;
+ } else {
pga_gain = (table[i] >> 24) & 0xF;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
- rfpwr_offset =
- b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+ rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
else
- rfpwr_offset =
- 0; /* FIXME */
- b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
- rfpwr_offset);
- b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
- rfpwr_offset);
+ rfpwr_offset = 0; /* FIXME */
}
+
+ b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
+ b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
}
}
@@ -3684,7 +4285,9 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
nphy->rfctrl_intc2_save = b43_phy_read(dev,
B43_NPHY_RFCTL_INTC2);
band = b43_current_band(dev->wl);
- if (dev->phy.rev >= 3) {
+ if (dev->phy.rev >= 7) {
+ tmp = 0x1480;
+ } else if (dev->phy.rev >= 3) {
if (band == IEEE80211_BAND_5GHZ)
tmp = 0x600;
else
@@ -3705,21 +4308,28 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
-static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
+/*
+ * TX low-pass filter bandwidth setup
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
+ */
+static void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)
{
u16 tmp;
- if (dev->phy.rev >= 3) {
- if (b43_nphy_ipa(dev)) {
- tmp = 4;
- b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
- (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
- }
+ if (dev->phy.rev < 3 || dev->phy.rev >= 7)
+ return;
+
+ if (b43_nphy_ipa(dev))
+ tmp = b43_is_40mhz(dev) ? 5 : 4;
+ else
+ tmp = b43_is_40mhz(dev) ? 3 : 1;
+ b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
+ (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
- tmp = 1;
+ if (b43_nphy_ipa(dev)) {
+ tmp = b43_is_40mhz(dev) ? 4 : 1;
b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
- (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
+ (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
}
}
@@ -3992,7 +4602,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
if (nphy->gband_spurwar_en) {
/* TODO: N PHY Adjust Analog Pfbw (7) */
- if (channel == 11 && dev->phy.is_40mhz)
+ if (channel == 11 && b43_is_40mhz(dev))
; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
else
; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
@@ -4124,7 +4734,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- if (dev->phy.rev >= 7) {
+ if (dev->phy.rev >= 19) {
+ /* TODO */
+ } else if (dev->phy.rev >= 7) {
+ b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
+ rssical_radio_regs[0]);
+ b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
+ rssical_radio_regs[1]);
} else {
b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
rssical_radio_regs[0]);
@@ -4148,15 +4764,78 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
}
+static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
+{
+ /* TODO */
+}
+
+static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = dev->phy.n;
+ u16 *save = nphy->tx_rx_cal_radio_saveregs;
+ int core, off;
+ u16 r, tmp;
+
+ for (core = 0; core < 2; core++) {
+ r = core ? 0x20 : 0;
+ off = core * 11;
+
+ save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
+ save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
+ save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
+ save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
+ save[off + 4] = 0;
+ save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
+ if (phy->radio_rev != 5)
+ save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
+ save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
+ save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
+ b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+ b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+ b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+ b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
+ if (nphy->use_int_tx_iq_lo_cal) {
+ b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
+ tmp = true ? 0x31 : 0x21; /* TODO */
+ b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
+ }
+ b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
+ } else {
+ b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
+ b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+ b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+ b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+
+ if (phy->radio_rev != 5)
+ b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
+ if (nphy->use_int_tx_iq_lo_cal) {
+ b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
+ tmp = true ? 0x31 : 0x21; /* TODO */
+ b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
+ }
+ b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
+ }
+ }
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
u16 *save = nphy->tx_rx_cal_radio_saveregs;
u16 tmp;
u8 offset, i;
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ b43_nphy_tx_cal_radio_setup_rev19(dev);
+ } else if (phy->rev >= 7) {
+ b43_nphy_tx_cal_radio_setup_rev7(dev);
+ } else if (phy->rev >= 3) {
for (i = 0; i < 2; i++) {
tmp = (i == 0) ? 0x2000 : 0x3000;
offset = i * 11;
@@ -4265,41 +4944,62 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
}
}
+static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
+ const s16 *filter)
+{
+ int i;
+
+ offset = B43_PHY_N(offset);
+
+ for (i = 0; i < 15; i++, offset++)
+ b43_phy_write(dev, offset, filter[i]);
+}
+
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
{
- int i;
- for (i = 0; i < 15; i++)
- b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
- tbl_tx_filter_coef_rev4[2][i]);
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
+ tbl_tx_filter_coef_rev4[2]);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
{
- int i, j;
/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
+ static const s16 dig_filter_phy_rev16[] = {
+ -375, 136, -407, 208, -1527,
+ 956, 93, 186, 93, 230,
+ -44, 230, 201, -191, 201,
+ };
+ int i;
for (i = 0; i < 3; i++)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[i] + j),
- tbl_tx_filter_coef_rev4[i][j]);
-
- if (dev->phy.is_40mhz) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[3][j]);
- } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[5][j]);
- }
-
- if (dev->phy.channel == 14)
- for (j = 0; j < 15; j++)
- b43_phy_write(dev, B43_PHY_N(offset[0] + j),
- tbl_tx_filter_coef_rev4[6][j]);
+ b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
+ tbl_tx_filter_coef_rev4[i]);
+
+ /* Verified with BCM43227 and BCM43228 */
+ if (dev->phy.rev == 16)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+
+ /* Verified with BCM43131 and BCM43217 */
+ if (dev->phy.rev == 17) {
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
+ tbl_tx_filter_coef_rev4[1]);
+ }
+
+ if (b43_is_40mhz(dev)) {
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[3]);
+ } else {
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[5]);
+ if (dev->phy.channel == 14)
+ b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+ tbl_tx_filter_coef_rev4[6]);
+ }
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
@@ -4321,7 +5021,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, false);
for (i = 0; i < 2; ++i) {
- if (dev->phy.rev >= 3) {
+ if (dev->phy.rev >= 7) {
+ target.ipa[i] = curr_gain[i] & 0x0007;
+ target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
+ target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
+ target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
+ target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
+ } else if (dev->phy.rev >= 3) {
target.ipa[i] = curr_gain[i] & 0x000F;
target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
@@ -4345,7 +5051,16 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
for (i = 0; i < 2; ++i) {
table = b43_nphy_get_tx_gain_table(dev);
- if (dev->phy.rev >= 3) {
+ if (!table)
+ break;
+
+ if (dev->phy.rev >= 7) {
+ target.ipa[i] = (table[index[i]] >> 16) & 0x7;
+ target.pad[i] = (table[index[i]] >> 19) & 0x1F;
+ target.pga[i] = (table[index[i]] >> 24) & 0xF;
+ target.txgm[i] = (table[index[i]] >> 28) & 0x7;
+ target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
+ } else if (dev->phy.rev >= 3) {
target.ipa[i] = (table[index[i]] >> 16) & 0xF;
target.pad[i] = (table[index[i]] >> 20) & 0xF;
target.pga[i] = (table[index[i]] >> 24) & 0xF;
@@ -4394,6 +5109,8 @@ static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = dev->phy.n;
u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
u16 tmp;
@@ -4425,7 +5142,12 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3);
+ if (!nphy->use_int_tx_iq_lo_cal)
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+ 1, 3);
+ else
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+ 0, 3);
b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
@@ -4433,6 +5155,33 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
+
+ tmp = b43_nphy_read_lpf_ctl(dev, 0);
+ if (phy->rev >= 19)
+ b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
+ 1);
+ else if (phy->rev >= 7)
+ b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
+ 1);
+
+ if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
+ if (phy->rev >= 19) {
+ b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
+ false, 0);
+ } else if (phy->rev >= 8) {
+ b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
+ false, 0);
+ } else if (phy->rev == 7) {
+ b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
+ b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
+ } else {
+ b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
+ b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
+ }
+ }
+ }
} else {
b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
@@ -4461,6 +5210,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
static void b43_nphy_save_cal(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
@@ -4485,7 +5235,26 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
/* TODO use some definitions */
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ txcal_radio_regs[0] = b43_radio_read(dev,
+ R2057_TX0_LOFT_FINE_I);
+ txcal_radio_regs[1] = b43_radio_read(dev,
+ R2057_TX0_LOFT_FINE_Q);
+ txcal_radio_regs[4] = b43_radio_read(dev,
+ R2057_TX0_LOFT_COARSE_I);
+ txcal_radio_regs[5] = b43_radio_read(dev,
+ R2057_TX0_LOFT_COARSE_Q);
+ txcal_radio_regs[2] = b43_radio_read(dev,
+ R2057_TX1_LOFT_FINE_I);
+ txcal_radio_regs[3] = b43_radio_read(dev,
+ R2057_TX1_LOFT_FINE_Q);
+ txcal_radio_regs[6] = b43_radio_read(dev,
+ R2057_TX1_LOFT_COARSE_I);
+ txcal_radio_regs[7] = b43_radio_read(dev,
+ R2057_TX1_LOFT_COARSE_Q);
+ } else if (phy->rev >= 3) {
txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
@@ -4500,8 +5269,9 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
}
- iqcal_chanspec->center_freq = dev->phy.channel_freq;
- iqcal_chanspec->channel_type = dev->phy.channel_type;
+ iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;
+ iqcal_chanspec->channel_type =
+ cfg80211_get_chandef_type(dev->phy.chandef);
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
if (nphy->hang_avoid)
@@ -4511,6 +5281,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
static void b43_nphy_restore_cal(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
u16 coef[4];
@@ -4558,7 +5329,26 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
}
/* TODO use some definitions */
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
+ txcal_radio_regs[0]);
+ b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
+ txcal_radio_regs[1]);
+ b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
+ txcal_radio_regs[4]);
+ b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
+ txcal_radio_regs[5]);
+ b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
+ txcal_radio_regs[2]);
+ b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
+ txcal_radio_regs[3]);
+ b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
+ txcal_radio_regs[6]);
+ b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
+ txcal_radio_regs[7]);
+ } else if (phy->rev >= 3) {
b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
@@ -4581,6 +5371,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
struct nphy_txgains target,
bool full, bool mphase)
{
+ struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
int i;
int error = 0;
@@ -4621,7 +5412,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
(dev->phy.rev == 5 && nphy->ipa2g_on &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
if (phy6or5x) {
- if (dev->phy.is_40mhz) {
+ if (b43_is_40mhz(dev)) {
b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
tbl_tx_iqlo_cal_loft_ladder_40);
b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
@@ -4634,18 +5425,24 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
}
}
- b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
+ } else {
+ b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
+ }
- if (!dev->phy.is_40mhz)
+ if (!b43_is_40mhz(dev))
freq = 2500;
else
freq = 5000;
if (nphy->mphase_cal_phase_id > 2)
- b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
- 0xFFFF, 0, true, false);
+ b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,
+ 0xFFFF, 0, true, false, false);
else
- error = b43_nphy_tx_tone(dev, freq, 250, true, false);
+ error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);
if (error == 0) {
if (nphy->mphase_cal_phase_id > 2) {
@@ -4773,9 +5570,9 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
nphy->txiqlocal_bestc);
nphy->txiqlocal_coeffsvalid = true;
nphy->txiqlocal_chanspec.center_freq =
- dev->phy.channel_freq;
+ phy->chandef->chan->center_freq;
nphy->txiqlocal_chanspec.channel_type =
- dev->phy.channel_type;
+ cfg80211_get_chandef_type(phy->chandef);
} else {
length = 11;
if (dev->phy.rev < 3)
@@ -4811,8 +5608,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
bool equal = true;
if (!nphy->txiqlocal_coeffsvalid ||
- nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
- nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
+ nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||
+ nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))
return;
b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
@@ -4968,11 +5765,11 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
if (playtone) {
ret = b43_nphy_tx_tone(dev, 4000,
(nphy->rxcalparams & 0xFFFF),
- false, false);
+ false, false, true);
playtone = false;
} else {
- b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
- false, false);
+ b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,
+ false, true);
}
if (ret == 0) {
@@ -5028,6 +5825,9 @@ static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
struct nphy_txgains target, u8 type, bool debug)
{
+ if (dev->phy.rev >= 7)
+ type = 0;
+
if (dev->phy.rev >= 3)
return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
else
@@ -5114,6 +5914,9 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
{
+ if (dev->phy.rev >= 7)
+ return;
+
if (dev->phy.rev >= 3) {
if (!init)
return;
@@ -5189,6 +5992,10 @@ static int b43_phy_initn(struct b43_wldev *dev)
#endif
}
}
+ nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
+ phy->rev >= 7 ||
+ (phy->rev >= 5 &&
+ sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
nphy->deaf_count = 0;
b43_nphy_tables_init(dev);
nphy->crsminpwr_adjusted = false;
@@ -5198,6 +6005,16 @@ static int b43_phy_initn(struct b43_wldev *dev)
if (dev->phy.rev >= 3) {
b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+ if (phy->rev >= 7) {
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
+ b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
+ }
+ if (phy->rev >= 19) {
+ /* TODO */
+ }
+
b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
} else {
@@ -5235,7 +6052,9 @@ static int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
- b43_nphy_update_mimo_config(dev, nphy->preamble_override);
+ if (phy->rev < 8)
+ b43_nphy_update_mimo_config(dev, nphy->preamble_override);
+
b43_nphy_update_txrx_chain(dev);
if (phy->rev < 2) {
@@ -5267,10 +6086,12 @@ static int b43_phy_initn(struct b43_wldev *dev)
b43_mac_phy_clock_set(dev, true);
- b43_nphy_pa_override(dev, false);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- b43_nphy_pa_override(dev, true);
+ if (phy->rev < 7) {
+ b43_nphy_pa_override(dev, false);
+ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+ b43_nphy_pa_override(dev, true);
+ }
b43_nphy_classifier(dev, 0, 0);
b43_nphy_read_clip_detection(dev, clip);
@@ -5344,7 +6165,7 @@ static int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
if (phy->rev >= 3 && phy->rev <= 6)
b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
- b43_nphy_tx_lp_fbw(dev);
+ b43_nphy_tx_lpf_bw(dev);
if (phy->rev >= 3)
b43_nphy_spur_workaround(dev);
@@ -5393,23 +6214,26 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
int ch = new_channel->hw_value;
-
- u16 old_band_5ghz;
u16 tmp16;
- old_band_5ghz =
- b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
- if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+ if (new_channel->band == IEEE80211_BAND_5GHZ) {
+ /* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
+ b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+
tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
- b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
+ /* Put BPHY in the reset */
+ b43_phy_set(dev, B43_PHY_B_BBCFG,
+ B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
- } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+ } else if (new_channel->band == IEEE80211_BAND_2GHZ) {
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
- b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
+ /* Take BPHY out of the reset */
+ b43_phy_mask(dev, B43_PHY_B_BBCFG,
+ (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
}
@@ -5430,35 +6254,49 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
if (dev->phy.rev < 3)
b43_nphy_adjust_lna_gain_table(dev);
- b43_nphy_tx_lp_fbw(dev);
+ b43_nphy_tx_lpf_bw(dev);
if (dev->phy.rev >= 3 &&
dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
- bool avoid = false;
+ u8 spuravoid = 0;
+
if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
- avoid = true;
- } else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
- if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
- avoid = true;
- } else { /* 40MHz */
- if (nphy->aband_spurwar_en &&
- (ch == 38 || ch == 102 || ch == 118))
- avoid = dev->dev->chip_id == 0x4716;
+ spuravoid = 1;
+ } else if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 18) {
+ /* TODO */
+ } else if (phy->rev >= 17) {
+ /* TODO: Off for channels 1-11, but check 12-14! */
+ } else if (phy->rev >= 16) {
+ /* TODO: Off for 2 GHz, but check 5 GHz! */
+ } else if (phy->rev >= 7) {
+ if (!b43_is_40mhz(dev)) { /* 20MHz */
+ if (ch == 13 || ch == 14 || ch == 153)
+ spuravoid = 1;
+ } else { /* 40 MHz */
+ if (ch == 54)
+ spuravoid = 1;
+ }
+ } else {
+ if (!b43_is_40mhz(dev)) { /* 20MHz */
+ if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
+ spuravoid = 1;
+ } else { /* 40MHz */
+ if (nphy->aband_spurwar_en &&
+ (ch == 38 || ch == 102 || ch == 118))
+ spuravoid = dev->dev->chip_id == 0x4716;
+ }
}
- b43_nphy_pmu_spur_avoid(dev, avoid);
+ b43_nphy_pmu_spur_avoid(dev, spuravoid);
- if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
- dev->dev->chip_id == 43225) {
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
- avoid ? 0x5341 : 0x8889);
- b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
- }
+ b43_mac_switch_freq(dev, spuravoid);
if (dev->phy.rev == 3 || dev->phy.rev == 4)
; /* TODO: reset PLL */
- if (avoid)
+ if (spuravoid)
b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
else
b43_phy_mask(dev, B43_NPHY_BBCFG,
@@ -5484,10 +6322,20 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
+ const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;
+ const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
u8 tmp;
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ return -ESRCH;
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ r2057_get_chantabent_rev7(dev, channel->center_freq,
+ &tabent_r7, &tabent_r7_2g);
+ if (!tabent_r7 && !tabent_r7_2g)
+ return -ESRCH;
+ } else if (phy->rev >= 3) {
tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
channel->center_freq);
if (!tabent_r3)
@@ -5502,20 +6350,38 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
/* Channel is set later in common code, but we need to set it on our
own to let this function's subcalls work properly. */
phy->channel = channel->hw_value;
- phy->channel_freq = channel->center_freq;
+#if 0
if (b43_channel_type_is_40mhz(phy->channel_type) !=
b43_channel_type_is_40mhz(channel_type))
; /* TODO: BMAC BW Set (channel_type) */
+#endif
- if (channel_type == NL80211_CHAN_HT40PLUS)
- b43_phy_set(dev, B43_NPHY_RXCTL,
- B43_NPHY_RXCTL_BSELU20);
- else if (channel_type == NL80211_CHAN_HT40MINUS)
- b43_phy_mask(dev, B43_NPHY_RXCTL,
- ~B43_NPHY_RXCTL_BSELU20);
+ if (channel_type == NL80211_CHAN_HT40PLUS) {
+ b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);
+ if (phy->rev >= 7)
+ b43_phy_set(dev, 0x310, 0x8000);
+ } else if (channel_type == NL80211_CHAN_HT40MINUS) {
+ b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);
+ if (phy->rev >= 7)
+ b43_phy_mask(dev, 0x310, (u16)~0x8000);
+ }
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
+ const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
+ &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
+
+ if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+ tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 2 : 0;
+ b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);
+ b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);
+ }
+
+ b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);
+ b43_nphy_channel_setup(dev, phy_regs, channel);
+ } else if (phy->rev >= 3) {
tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
b43_radio_2056_setup(dev, tabent_r3);
@@ -5656,7 +6522,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* Register 1 is a 32-bit register. */
- B43_WARN_ON(reg == 1);
+ B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
if (dev->phy.rev >= 7)
reg |= 0x200; /* Radio 0x2057 */
@@ -5670,7 +6536,7 @@ static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
{
/* Register 1 is a 32-bit register. */
- B43_WARN_ON(reg == 1);
+ B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
@@ -5680,15 +6546,23 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
+ struct b43_phy *phy = &dev->phy;
+
if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
b43err(dev->wl, "MAC not suspended\n");
if (blocked) {
- b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
- ~B43_NPHY_RFCTL_CMD_CHIP0PU);
- if (dev->phy.rev >= 7) {
+ if (phy->rev >= 19) {
/* TODO */
- } else if (dev->phy.rev >= 3) {
+ } else if (phy->rev >= 8) {
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+ } else if (phy->rev >= 7) {
+ /* Nothing needed */
+ } else if (phy->rev >= 3) {
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+
b43_radio_mask(dev, 0x09, ~0x2);
b43_radio_write(dev, 0x204D, 0);
@@ -5706,11 +6580,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
b43_radio_write(dev, 0x3064, 0);
}
} else {
- if (dev->phy.rev >= 7) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 7) {
if (!dev->phy.radio_on)
b43_radio_2057_init(dev);
b43_switch_channel(dev, dev->phy.channel);
- } else if (dev->phy.rev >= 3) {
+ } else if (phy->rev >= 3) {
if (!dev->phy.radio_on)
b43_radio_init2056(dev);
b43_switch_channel(dev, dev->phy.channel);
@@ -5723,10 +6599,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
+ struct b43_phy *phy = &dev->phy;
u16 override = on ? 0x0 : 0x7FFF;
u16 core = on ? 0xD : 0x00FD;
- if (dev->phy.rev >= 3) {
+ if (phy->rev >= 19) {
+ /* TODO */
+ } else if (phy->rev >= 3) {
if (on) {
b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index ecfbf66dbc3b..30bec815b969 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -366,11 +366,13 @@
#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
+#define B43_NPHY_REV3_RFCTL_OVER0 B43_PHY_N(0x0E7)
#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */
#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */
#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */
+#define B43_NPHY_REV3_RFCTL_OVER1 B43_PHY_N(0x0EC)
#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */
#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */
#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */
@@ -857,7 +859,18 @@
#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG3 B43_PHY_N(0x340)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG4 B43_PHY_N(0x341)
+#define B43_NPHY_REV7_RF_CTL_OVER3 B43_PHY_N(0x342)
+#define B43_NPHY_REV7_RF_CTL_OVER4 B43_PHY_N(0x343)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG5 B43_PHY_N(0x344)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG6 B43_PHY_N(0x345)
+#define B43_NPHY_REV7_RF_CTL_OVER5 B43_PHY_N(0x346)
+#define B43_NPHY_REV7_RF_CTL_OVER6 B43_PHY_N(0x347)
+
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
+#define B43_PHY_B_BBCFG_RSTCCA 0x4000 /* Reset CCA */
+#define B43_PHY_B_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
struct b43_wldev;
@@ -935,6 +948,8 @@ struct b43_phy_n {
bool gain_boost;
bool elna_gain_config;
bool band5g_pwrgain;
+ bool use_int_tx_iq_lo_cal;
+ bool lpf_bw_overrode_for_sample_play;
u8 mphase_cal_phase_id;
u16 mphase_txcal_cmdidx;
diff --git a/drivers/net/wireless/b43/radio_2057.c b/drivers/net/wireless/b43/radio_2057.c
index d61d6830c5c7..ff1e026a61a1 100644
--- a/drivers/net/wireless/b43/radio_2057.c
+++ b/drivers/net/wireless/b43/radio_2057.c
@@ -26,7 +26,7 @@
#include "radio_2057.h"
#include "phy_common.h"
-static u16 r2057_rev4_init[42][2] = {
+static u16 r2057_rev4_init[][2] = {
{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
@@ -40,7 +40,7 @@ static u16 r2057_rev4_init[42][2] = {
{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
};
-static u16 r2057_rev5_init[44][2] = {
+static u16 r2057_rev5_init[][2] = {
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
@@ -54,7 +54,7 @@ static u16 r2057_rev5_init[44][2] = {
{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
};
-static u16 r2057_rev5a_init[45][2] = {
+static u16 r2057_rev5a_init[][2] = {
{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
@@ -69,7 +69,7 @@ static u16 r2057_rev5a_init[45][2] = {
{ 0x1C2, 0x80 },
};
-static u16 r2057_rev7_init[54][2] = {
+static u16 r2057_rev7_init[][2] = {
{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
@@ -86,7 +86,8 @@ static u16 r2057_rev7_init[54][2] = {
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
};
-static u16 r2057_rev8_init[54][2] = {
+/* TODO: Which devices should use it?
+static u16 r2057_rev8_init[][2] = {
{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
@@ -102,6 +103,436 @@ static u16 r2057_rev8_init[54][2] = {
{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
};
+*/
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static u16 r2057_rev9_init[][2] = {
+ { 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
+ { 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
+ { 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
+ { 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
+ { 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
+ { 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
+ { 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
+ { 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static u16 r2057_rev14_init[][2] = {
+ { 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
+ { 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
+ { 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
+ { 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
+ { 0x1d4, 0x0f },
+};
+
+#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+ r20, r21, r22, r23, r24, r25, r26, r27) \
+ .radio_vcocal_countval0 = r00, \
+ .radio_vcocal_countval1 = r01, \
+ .radio_rfpll_refmaster_sparextalsize = r02, \
+ .radio_rfpll_loopfilter_r1 = r03, \
+ .radio_rfpll_loopfilter_c2 = r04, \
+ .radio_rfpll_loopfilter_c1 = r05, \
+ .radio_cp_kpd_idac = r06, \
+ .radio_rfpll_mmd0 = r07, \
+ .radio_rfpll_mmd1 = r08, \
+ .radio_vcobuf_tune = r09, \
+ .radio_logen_mx2g_tune = r10, \
+ .radio_logen_mx5g_tune = r11, \
+ .radio_logen_indbuf2g_tune = r12, \
+ .radio_logen_indbuf5g_tune = r13, \
+ .radio_txmix2g_tune_boost_pu_core0 = r14, \
+ .radio_pad2g_tune_pus_core0 = r15, \
+ .radio_pga_boost_tune_core0 = r16, \
+ .radio_txmix5g_boost_tune_core0 = r17, \
+ .radio_pad5g_tune_misc_pus_core0 = r18, \
+ .radio_lna2g_tune_core0 = r19, \
+ .radio_lna5g_tune_core0 = r20, \
+ .radio_txmix2g_tune_boost_pu_core1 = r21, \
+ .radio_pad2g_tune_pus_core1 = r22, \
+ .radio_pga_boost_tune_core1 = r23, \
+ .radio_txmix5g_boost_tune_core1 = r24, \
+ .radio_pad5g_tune_misc_pus_core1 = r25, \
+ .radio_lna2g_tune_core1 = r26, \
+ .radio_lna5g_tune_core1 = r27
+
+#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+ r10, r11, r12, r13, r14, r15, r16, r17) \
+ .radio_vcocal_countval0 = r00, \
+ .radio_vcocal_countval1 = r01, \
+ .radio_rfpll_refmaster_sparextalsize = r02, \
+ .radio_rfpll_loopfilter_r1 = r03, \
+ .radio_rfpll_loopfilter_c2 = r04, \
+ .radio_rfpll_loopfilter_c1 = r05, \
+ .radio_cp_kpd_idac = r06, \
+ .radio_rfpll_mmd0 = r07, \
+ .radio_rfpll_mmd1 = r08, \
+ .radio_vcobuf_tune = r09, \
+ .radio_logen_mx2g_tune = r10, \
+ .radio_logen_indbuf2g_tune = r11, \
+ .radio_txmix2g_tune_boost_pu_core0 = r12, \
+ .radio_pad2g_tune_pus_core0 = r13, \
+ .radio_lna2g_tune_core0 = r14, \
+ .radio_txmix2g_tune_boost_pu_core1 = r15, \
+ .radio_pad2g_tune_pus_core1 = r16, \
+ .radio_lna2g_tune_core1 = r17
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
+ .phy_regs.phy_bw1a = r0, \
+ .phy_regs.phy_bw2 = r1, \
+ .phy_regs.phy_bw3 = r2, \
+ .phy_regs.phy_bw4 = r3, \
+ .phy_regs.phy_bw5 = r4, \
+ .phy_regs.phy_bw6 = r5
+
+/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
+ {
+ .freq = 2412,
+ RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+ 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+ 0x03, 0xff),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ {
+ .freq = 2417,
+ RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+ 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+ 0x03, 0xff),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ {
+ .freq = 2422,
+ RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+ 0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
+ 0x03, 0xef),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ {
+ .freq = 2427,
+ RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+ 0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
+ 0x03, 0xdf),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ {
+ .freq = 2432,
+ RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+ 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
+ 0x03, 0xcf),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ {
+ .freq = 2437,
+ RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+ 0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
+ 0x03, 0xbf),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ {
+ .freq = 2442,
+ RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+ 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
+ 0x03, 0xaf),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ {
+ .freq = 2447,
+ RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+ 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
+ 0x03, 0x9f),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ {
+ .freq = 2452,
+ RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+ 0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
+ 0x03, 0x8f),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ {
+ .freq = 2457,
+ RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+ 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
+ 0x03, 0x7f),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ {
+ .freq = 2462,
+ RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+ 0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
+ 0x03, 0x6f),
+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+ },
+ {
+ .freq = 2467,
+ RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+ 0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
+ 0x03, 0x5f),
+ PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+ },
+ {
+ .freq = 2472,
+ RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+ 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
+ 0x03, 0x4f),
+ PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+ },
+ {
+ .freq = 2484,
+ RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
+ 0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
+ 0x03, 0x3f),
+ PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+ }
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
+ {
+ .freq = 2412,
+ RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
+ 0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ {
+ .freq = 2417,
+ RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
+ 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ {
+ .freq = 2422,
+ RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
+ 0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ {
+ .freq = 2427,
+ RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ {
+ .freq = 2432,
+ RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ {
+ .freq = 2437,
+ RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+ 0x53, 0xff),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ {
+ .freq = 2442,
+ RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+ 0x43, 0xff),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ {
+ .freq = 2447,
+ RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+ 0x43, 0xff),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ {
+ .freq = 2452,
+ RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
+ 0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+ 0x43, 0xff),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ {
+ .freq = 2457,
+ RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
+ 0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
+ 0x43, 0xff),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ {
+ .freq = 2462,
+ RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
+ 0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
+ 0x43, 0xff),
+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+ },
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
+ {
+ .freq = 2412,
+ RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ {
+ .freq = 2417,
+ RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ {
+ .freq = 2422,
+ RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ {
+ .freq = 2427,
+ RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ {
+ .freq = 2432,
+ RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ {
+ .freq = 2437,
+ RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ {
+ .freq = 2442,
+ RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ {
+ .freq = 2447,
+ RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ {
+ .freq = 2452,
+ RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ {
+ .freq = 2457,
+ RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ {
+ .freq = 2462,
+ RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+ 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+ },
+ {
+ .freq = 5180,
+ RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
+ 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+ 0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
+ 0x3a, 0x83, 0x00, 0xfc),
+ PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+ },
+ {
+ .freq = 5200,
+ RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
+ 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+ 0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
+ 0x4a, 0x83, 0x00, 0xf8),
+ PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+ },
+ {
+ .freq = 5220,
+ RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
+ 0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+ 0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
+ 0x2a, 0x73, 0x00, 0xf8),
+ PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+ },
+ {
+ .freq = 5240,
+ RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
+ 0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
+ 0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
+ 0x2b, 0x73, 0x00, 0xf8),
+ PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+ },
+ {
+ .freq = 5745,
+ RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
+ 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+ 0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
+ 0x02, 0x03, 0x00, 0x30),
+ PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+ },
+ {
+ .freq = 5765,
+ RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
+ 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+ 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x02, 0x03, 0x00, 0x00),
+ PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+ },
+ {
+ .freq = 5785,
+ RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
+ 0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+ 0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x21, 0x03, 0x00, 0x00),
+ PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+ },
+ {
+ .freq = 5805,
+ RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
+ 0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
+ 0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x03, 0x00, 0x00),
+ PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+ },
+ {
+ .freq = 5825,
+ RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
+ 0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
+ 0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x03, 0x00, 0x00),
+ PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+ },
+};
void r2057_upload_inittabs(struct b43_wldev *dev)
{
@@ -109,33 +540,98 @@ void r2057_upload_inittabs(struct b43_wldev *dev)
u16 *table = NULL;
u16 size, i;
- if (phy->rev == 7) {
+ switch (phy->rev) {
+ case 7:
table = r2057_rev4_init[0];
size = ARRAY_SIZE(r2057_rev4_init);
- } else if (phy->rev == 8 || phy->rev == 9) {
+ break;
+ case 8:
if (phy->radio_rev == 5) {
- if (phy->radio_rev == 8) {
- table = r2057_rev5_init[0];
- size = ARRAY_SIZE(r2057_rev5_init);
- } else {
- table = r2057_rev5a_init[0];
- size = ARRAY_SIZE(r2057_rev5a_init);
- }
+ table = r2057_rev5_init[0];
+ size = ARRAY_SIZE(r2057_rev5_init);
} else if (phy->radio_rev == 7) {
table = r2057_rev7_init[0];
size = ARRAY_SIZE(r2057_rev7_init);
- } else if (phy->radio_rev == 9) {
- table = r2057_rev8_init[0];
- size = ARRAY_SIZE(r2057_rev8_init);
}
+ break;
+ case 9:
+ if (phy->radio_rev == 5) {
+ table = r2057_rev5a_init[0];
+ size = ARRAY_SIZE(r2057_rev5a_init);
+ }
+ break;
+ case 16:
+ if (phy->radio_rev == 9) {
+ table = r2057_rev9_init[0];
+ size = ARRAY_SIZE(r2057_rev9_init);
+ }
+ break;
+ case 17:
+ if (phy->radio_rev == 14) {
+ table = r2057_rev14_init[0];
+ size = ARRAY_SIZE(r2057_rev14_init);
+ }
+ break;
}
+ B43_WARN_ON(!table);
+
if (table) {
- for (i = 0; i < 10; i++) {
- pr_info("radio_write 0x%X ", *table);
- table++;
- pr_info("0x%X\n", *table);
- table++;
+ for (i = 0; i < size; i++, table += 2)
+ b43_radio_write(dev, table[0], table[1]);
+ }
+}
+
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+ const struct b43_nphy_chantabent_rev7 **tabent_r7,
+ const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g)
+{
+ struct b43_phy *phy = &dev->phy;
+ const struct b43_nphy_chantabent_rev7 *e_r7 = NULL;
+ const struct b43_nphy_chantabent_rev7_2g *e_r7_2g = NULL;
+ unsigned int len, i;
+
+ *tabent_r7 = NULL;
+ *tabent_r7_2g = NULL;
+
+ switch (phy->rev) {
+ case 8:
+ if (phy->radio_rev == 5) {
+ e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
+ len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
+ }
+ break;
+ case 16:
+ if (phy->radio_rev == 9) {
+ e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
+ len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
+ }
+ break;
+ case 17:
+ if (phy->radio_rev == 14) {
+ e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
+ len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (e_r7) {
+ for (i = 0; i < len; i++, e_r7++) {
+ if (e_r7->freq == freq) {
+ *tabent_r7 = e_r7;
+ return;
+ }
+ }
+ } else if (e_r7_2g) {
+ for (i = 0; i < len; i++, e_r7_2g++) {
+ if (e_r7_2g->freq == freq) {
+ *tabent_r7_2g = e_r7_2g;
+ return;
+ }
}
+ } else {
+ B43_WARN_ON(1);
}
}
diff --git a/drivers/net/wireless/b43/radio_2057.h b/drivers/net/wireless/b43/radio_2057.h
index eeebd8fbeb0d..220d080238ff 100644
--- a/drivers/net/wireless/b43/radio_2057.h
+++ b/drivers/net/wireless/b43/radio_2057.h
@@ -84,6 +84,8 @@
#define R2057_CMOSBUF_RX_RCCR 0x04c
#define R2057_LOGEN_SEL_PKDET 0x04d
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
+
+/* MISC core 0 */
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
#define R2057_TXGM_TXRF_PUS_CORE0 0x050
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
@@ -204,6 +206,8 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
#define R2057_LPF_GAIN_CORE0 0x0d2
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
+
+/* MISC core 1 */
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
@@ -324,6 +328,7 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
#define R2057_LPF_GAIN_CORE1 0x157
#define R2057_DACBUF_IDACS_BW_CORE1 0x158
+
#define R2057_DACBUF_VINCM_CORE1 0x159
#define R2057_RCCAL_START_R1_Q1_P1 0x15a
#define R2057_RCCAL_X1 0x15b
@@ -345,6 +350,8 @@
#define R2057_RCCAL_BCAP_VAL 0x16b
#define R2057_RCCAL_HPC_VAL 0x16c
#define R2057_RCCAL_OVERRIDES 0x16d
+
+/* TX core 0 */
#define R2057_TX0_IQCAL_GAIN_BW 0x170
#define R2057_TX0_LOFT_FINE_I 0x171
#define R2057_TX0_LOFT_FINE_Q 0x172
@@ -362,6 +369,8 @@
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
+
+/* TX core 1 */
#define R2057_TX1_IQCAL_GAIN_BW 0x190
#define R2057_TX1_LOFT_FINE_I 0x191
#define R2057_TX1_LOFT_FINE_Q 0x192
@@ -379,6 +388,7 @@
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
+
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
@@ -425,6 +435,72 @@
#define R2057_VCM_MASK 0x7
+struct b43_nphy_chantabent_rev7 {
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* Radio regs values on channelswitch */
+ u8 radio_vcocal_countval0;
+ u8 radio_vcocal_countval1;
+ u8 radio_rfpll_refmaster_sparextalsize;
+ u8 radio_rfpll_loopfilter_r1;
+ u8 radio_rfpll_loopfilter_c2;
+ u8 radio_rfpll_loopfilter_c1;
+ u8 radio_cp_kpd_idac;
+ u8 radio_rfpll_mmd0;
+ u8 radio_rfpll_mmd1;
+ u8 radio_vcobuf_tune;
+ u8 radio_logen_mx2g_tune;
+ u8 radio_logen_mx5g_tune;
+ u8 radio_logen_indbuf2g_tune;
+ u8 radio_logen_indbuf5g_tune;
+ u8 radio_txmix2g_tune_boost_pu_core0;
+ u8 radio_pad2g_tune_pus_core0;
+ u8 radio_pga_boost_tune_core0;
+ u8 radio_txmix5g_boost_tune_core0;
+ u8 radio_pad5g_tune_misc_pus_core0;
+ u8 radio_lna2g_tune_core0;
+ u8 radio_lna5g_tune_core0;
+ u8 radio_txmix2g_tune_boost_pu_core1;
+ u8 radio_pad2g_tune_pus_core1;
+ u8 radio_pga_boost_tune_core1;
+ u8 radio_txmix5g_boost_tune_core1;
+ u8 radio_pad5g_tune_misc_pus_core1;
+ u8 radio_lna2g_tune_core1;
+ u8 radio_lna5g_tune_core1;
+ /* PHY res values on channelswitch */
+ struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+struct b43_nphy_chantabent_rev7_2g {
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* Radio regs values on channelswitch */
+ u8 radio_vcocal_countval0;
+ u8 radio_vcocal_countval1;
+ u8 radio_rfpll_refmaster_sparextalsize;
+ u8 radio_rfpll_loopfilter_r1;
+ u8 radio_rfpll_loopfilter_c2;
+ u8 radio_rfpll_loopfilter_c1;
+ u8 radio_cp_kpd_idac;
+ u8 radio_rfpll_mmd0;
+ u8 radio_rfpll_mmd1;
+ u8 radio_vcobuf_tune;
+ u8 radio_logen_mx2g_tune;
+ u8 radio_logen_indbuf2g_tune;
+ u8 radio_txmix2g_tune_boost_pu_core0;
+ u8 radio_pad2g_tune_pus_core0;
+ u8 radio_lna2g_tune_core0;
+ u8 radio_txmix2g_tune_boost_pu_core1;
+ u8 radio_pad2g_tune_pus_core1;
+ u8 radio_lna2g_tune_core1;
+ /* PHY regs values on channelswitch */
+ struct b43_phy_n_sfo_cfg phy_regs;
+};
+
void r2057_upload_inittabs(struct b43_wldev *dev);
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+ const struct b43_nphy_chantabent_rev7 **tabent_r7,
+ const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g);
+
#endif /* B43_RADIO_2057_H_ */
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 4047c05e3807..4b5885077b01 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2146,7 +2146,196 @@ static const u16 b43_ntab_antswctl_r3[4][32] = {
}
};
-/* TX gain tables */
+/* static tables, PHY revision >= 7 */
+
+/* Copied from brcmsmac (5.75.11) */
+static const u32 b43_ntab_tmap_r7[] = {
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+ 0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+ 0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+ 0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+ 0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+ 0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+ 0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+ 0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+ 0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+ 0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+ 0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+ 0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+ 0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+ 0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+ 0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+ 0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+ 0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+ 0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+ 0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+ 0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+ 0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+ 0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+ 0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+ 0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+ 0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+ 0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+ 0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+ 0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+ 0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+ 0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+ 0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+ 0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+ 0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+ 0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+ 0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+ 0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+ 0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+ 0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+ 0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+ 0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+ 0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+ 0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+ 0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+ 0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+ 0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+ 0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+ 0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+ 0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+ 0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+ 0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+ 0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+ 0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+ 0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+ 0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+ 0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+ 0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+ 0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+ 0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+ 0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+ 0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+ 0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+ 0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+ 0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+ 0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+ 0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_noisevar_r7[] = {
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+ 0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+};
+
+/**************************************************
+ * TX gain tables
+ **************************************************/
+
static const u32 b43_ntab_tx_gain_rev0_1_2[] = {
0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
@@ -2182,7 +2371,9 @@ static const u32 b43_ntab_tx_gain_rev0_1_2[] = {
0x03801442, 0x03801344, 0x03801342, 0x00002b00,
};
-static const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
+/* EPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = {
0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
@@ -2217,7 +2408,44 @@ static const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
};
-static const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = {
+ 0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+ 0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+ 0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+ 0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+ 0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+ 0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+ 0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+ 0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+ 0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+ 0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+ 0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+ 0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+ 0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+ 0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+ 0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+ 0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+ 0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+ 0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+ 0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+ 0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+ 0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+ 0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+ 0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+ 0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+ 0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+ 0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+ 0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+ 0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+ 0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+ 0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+ 0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+ 0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+/* EPA 5 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = {
0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
@@ -2252,7 +2480,7 @@ static const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037,
};
-static const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = {
0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
@@ -2287,7 +2515,42 @@ static const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
};
-static const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
+static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = {
+ 0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+ 0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+ 0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+ 0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+ 0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+ 0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+ 0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+ 0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+ 0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+ 0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+ 0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+ 0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+ 0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+ 0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+ 0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+ 0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+ 0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+ 0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+ 0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+ 0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+ 0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+ 0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+ 0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+ 0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+ 0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+ 0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+ 0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+ 0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+ 0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+ 0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+ 0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+ 0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = {
0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
@@ -2322,7 +2585,9 @@ static const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
0x0062003b, 0x00620039, 0x00620037, 0x00620035,
};
-static const u32 txpwrctrl_tx_gain_ipa[] = {
+/* IPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_2g[] = {
0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
@@ -2357,7 +2622,7 @@ static const u32 txpwrctrl_tx_gain_ipa[] = {
0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025,
};
-static const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
+static const u32 b43_ntab_tx_gain_ipa_rev5_2g[] = {
0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
@@ -2392,7 +2657,7 @@ static const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025,
};
-static const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
+static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = {
0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
@@ -2427,7 +2692,117 @@ static const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
};
-static const u32 txpwrctrl_tx_gain_ipa_5g[] = {
+/* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
+ 0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+ 0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+ 0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+ 0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+ 0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+ 0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+ 0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+ 0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+ 0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+ 0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+ 0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+ 0x30170028, 0x30170026, 0x30170024, 0x30170022,
+ 0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+ 0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+ 0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+ 0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+ 0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+ 0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+ 0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+ 0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
+ 0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
+ 0x60b70029, 0x60a70029, 0x609f002a, 0x6097002b,
+ 0x6087002e, 0x60770031, 0x606f0032, 0x60670034,
+ 0x60670031, 0x605f0033, 0x605f0031, 0x60570033,
+ 0x60570030, 0x6057002d, 0x6057002b, 0x604f002d,
+ 0x604f002b, 0x604f0029, 0x604f0026, 0x60470029,
+ 0x60470027, 0x603f0029, 0x603f0027, 0x603f0025,
+ 0x60370029, 0x60370027, 0x60370024, 0x602f002a,
+ 0x602f0028, 0x602f0026, 0x602f0024, 0x6027002a,
+ 0x60270028, 0x60270026, 0x60270024, 0x60270022,
+ 0x601f002b, 0x601f0029, 0x601f0027, 0x601f0024,
+ 0x601f0022, 0x601f0020, 0x601f001f, 0x601f001d,
+ 0x60170029, 0x60170027, 0x60170025, 0x60170023,
+ 0x60170021, 0x6017001f, 0x6017001d, 0x6017001c,
+ 0x6017001a, 0x60170018, 0x60170018, 0x60170016,
+ 0x60170015, 0x600f0029, 0x600f0027, 0x600f0025,
+ 0x600f0023, 0x600f0021, 0x600f001f, 0x600f001d,
+ 0x600f001c, 0x600f001a, 0x600f0019, 0x600f0018,
+ 0x600f0016, 0x600f0015, 0x600f0115, 0x600f0215,
+ 0x600f0315, 0x600f0415, 0x600f0515, 0x600f0615,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+ 0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = {
+ 0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b,
+ 0x50af002a, 0x50a70029, 0x509f0029, 0x50970028,
+ 0x508f0027, 0x50870027, 0x507f0027, 0x50770027,
+ 0x506f0027, 0x50670027, 0x505f0028, 0x50570029,
+ 0x504f002b, 0x5047002e, 0x5047002b, 0x50470029,
+ 0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a,
+ 0x50370028, 0x502f002d, 0x502f002b, 0x502f0028,
+ 0x502f0026, 0x5027002d, 0x5027002a, 0x50270028,
+ 0x50270026, 0x50270024, 0x501f002e, 0x501f002b,
+ 0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022,
+ 0x501f0020, 0x501f001f, 0x5017002c, 0x50170029,
+ 0x50170027, 0x50170024, 0x50170022, 0x50170021,
+ 0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a,
+ 0x50170018, 0x50170017, 0x50170015, 0x500f002c,
+ 0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023,
+ 0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c,
+ 0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+ 0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+};
+
+/* IPA 2 5Hz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = {
0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
@@ -2462,6 +2837,42 @@ static const u32 txpwrctrl_tx_gain_ipa_5g[] = {
0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f,
};
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_5g[] = {
+ 0x7f7f0053, 0x7f7f004b, 0x7f7f0044, 0x7f7f003f,
+ 0x7f7f0039, 0x7f7f0035, 0x7f7f0032, 0x7f7f0030,
+ 0x7f7f002d, 0x7e7f0030, 0x7e7f002d, 0x7d7f0032,
+ 0x7d7f002f, 0x7d7f002c, 0x7c7f0032, 0x7c7f0030,
+ 0x7c7f002d, 0x7b7f0030, 0x7b7f002e, 0x7b7f002b,
+ 0x7a7f0032, 0x7a7f0030, 0x7a7f002d, 0x7a7f002b,
+ 0x797f0030, 0x797f002e, 0x797f002b, 0x797f0029,
+ 0x787f0030, 0x787f002d, 0x787f002b, 0x777f0032,
+ 0x777f0030, 0x777f002d, 0x777f002b, 0x767f0031,
+ 0x767f002f, 0x767f002c, 0x767f002a, 0x757f0031,
+ 0x757f002f, 0x757f002c, 0x757f002a, 0x747f0030,
+ 0x747f002d, 0x747f002b, 0x737f0032, 0x737f002f,
+ 0x737f002c, 0x737f002a, 0x727f0030, 0x727f002d,
+ 0x727f002b, 0x727f0029, 0x717f0030, 0x717f002d,
+ 0x717f002b, 0x707f0031, 0x707f002f, 0x707f002c,
+ 0x707f002a, 0x707f0027, 0x707f0025, 0x707f0023,
+ 0x707f0021, 0x707f001f, 0x707f001d, 0x707f001c,
+ 0x707f001a, 0x707f0019, 0x707f0017, 0x707f0016,
+ 0x707f0015, 0x707f0014, 0x707f0012, 0x707f0012,
+ 0x707f0011, 0x707f0010, 0x707f000f, 0x707f000e,
+ 0x707f000d, 0x707f000d, 0x707f000c, 0x707f000b,
+ 0x707f000a, 0x707f000a, 0x707f0009, 0x707f0008,
+ 0x707f0008, 0x707f0008, 0x707f0008, 0x707f0007,
+ 0x707f0007, 0x707f0006, 0x707f0006, 0x707f0006,
+ 0x707f0005, 0x707f0005, 0x707f0005, 0x707f0004,
+ 0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+ 0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+ 0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+ 0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+ 0x707f0002, 0x707f0001, 0x707f0001, 0x707f0001,
+ 0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+};
+
const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[] = {
-114, -108, -98, -91, -84, -78, -70, -62,
-54, -46, -39, -31, -23, -15, -8, 0
@@ -2698,11 +3109,11 @@ static const struct nphy_rf_control_override_rev7
{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
- { 0x0080, 0x0F8, 0x0FA, 0x0080, 7 },
+ { 0x0080, 0x07A, 0x07D, 0x0080, 7 },
{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
- { 0x6000, 0x348, 0x349, 0xFFFF, 0 },
+ { 0x6000, 0x348, 0x349, 0x00FF, 0 },
{ 0x2000, 0x348, 0x349, 0x000F, 0 },
};
@@ -3031,6 +3442,91 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
+static void b43_nphy_tables_init_shared_lut(struct b43_wldev *dev)
+{
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+ ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+}
+
+static void b43_nphy_tables_init_rev7_volatile(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ u8 antswlut;
+ int core, offset, i;
+
+ const int antswlut0_offsets[] = { 0, 4, 8, }; /* Offsets for values */
+ const u8 antswlut0_values[][3] = {
+ { 0x2, 0x12, 0x8 }, /* Core 0 */
+ { 0x2, 0x18, 0x2 }, /* Core 1 */
+ };
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ antswlut = sprom->fem.ghz5.antswlut;
+ else
+ antswlut = sprom->fem.ghz2.antswlut;
+
+ switch (antswlut) {
+ case 0:
+ for (core = 0; core < 2; core++) {
+ for (i = 0; i < ARRAY_SIZE(antswlut0_values[0]); i++) {
+ offset = core ? 0x20 : 0x00;
+ offset += antswlut0_offsets[i];
+ b43_ntab_write(dev, B43_NTAB8(9, offset),
+ antswlut0_values[core][i]);
+ }
+ }
+ break;
+ default:
+ b43err(dev->wl, "Unsupported antswlut: %d\n", antswlut);
+ break;
+ }
+}
+
+static void b43_nphy_tables_init_rev16(struct b43_wldev *dev)
+{
+ /* Static tables */
+ if (dev->phy.do_full_init) {
+ ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+ b43_nphy_tables_init_shared_lut(dev);
+ }
+
+ /* Volatile tables */
+ b43_nphy_tables_init_rev7_volatile(dev);
+}
+
+static void b43_nphy_tables_init_rev7(struct b43_wldev *dev)
+{
+ /* Static tables */
+ if (dev->phy.do_full_init) {
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+ ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+ ntab_upload(dev, B43_NTAB_TMAP_R7, b43_ntab_tmap_r7);
+ ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+ ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+ ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+ ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+ ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+ ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+ b43_nphy_tables_init_shared_lut(dev);
+ }
+
+ /* Volatile tables */
+ b43_nphy_tables_init_rev7_volatile(dev);
+}
+
static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -3057,16 +3553,7 @@ static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
- ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
- ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
- ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
- ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
- ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
- ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
- ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+ b43_nphy_tables_init_shared_lut(dev);
}
/* Volatile tables */
@@ -3115,7 +3602,11 @@ static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
void b43_nphy_tables_init(struct b43_wldev *dev)
{
- if (dev->phy.rev >= 3)
+ if (dev->phy.rev >= 16)
+ b43_nphy_tables_init_rev16(dev);
+ else if (dev->phy.rev >= 7)
+ b43_nphy_tables_init_rev7(dev);
+ else if (dev->phy.rev >= 3)
b43_nphy_tables_init_rev3(dev);
else
b43_nphy_tables_init_rev0(dev);
@@ -3124,23 +3615,55 @@ void b43_nphy_tables_init(struct b43_wldev *dev)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
+
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (dev->phy.rev >= 6) {
- if (dev->dev->chip_id == 47162)
- return txpwrctrl_tx_gain_ipa_rev5;
- return txpwrctrl_tx_gain_ipa_rev6;
- } else if (dev->phy.rev >= 5) {
- return txpwrctrl_tx_gain_ipa_rev5;
- } else {
- return txpwrctrl_tx_gain_ipa;
+ switch (phy->rev) {
+ case 17:
+ if (phy->radio_rev == 14)
+ return b43_ntab_tx_gain_ipa_2057_rev14_2g;
+ break;
+ case 16:
+ if (phy->radio_rev == 9)
+ return b43_ntab_tx_gain_ipa_2057_rev9_2g;
+ break;
+ case 8:
+ if (phy->radio_rev == 5)
+ return b43_ntab_tx_gain_ipa_2057_rev5_2g;
+ break;
+ case 6:
+ if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
+ return b43_ntab_tx_gain_ipa_rev5_2g;
+ return b43_ntab_tx_gain_ipa_rev6_2g;
+ case 5:
+ return b43_ntab_tx_gain_ipa_rev5_2g;
+ case 4:
+ case 3:
+ return b43_ntab_tx_gain_ipa_rev3_2g;
}
+
+ b43err(dev->wl,
+ "No 2GHz IPA gain table available for this device\n");
+ return NULL;
} else {
- return txpwrctrl_tx_gain_ipa_5g;
+ switch (phy->rev) {
+ case 16:
+ if (phy->radio_rev == 9)
+ return b43_ntab_tx_gain_ipa_2057_rev9_5g;
+ break;
+ case 3 ... 6:
+ return b43_ntab_tx_gain_ipa_rev3_5g;
+ }
+
+ b43err(dev->wl,
+ "No 5GHz IPA gain table available for this device\n");
+ return NULL;
}
}
const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
{
+ struct b43_phy *phy = &dev->phy;
enum ieee80211_band band = b43_current_band(dev->wl);
struct ssb_sprom *sprom = dev->dev->bus_sprom;
@@ -3152,19 +3675,36 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
(dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)) {
return b43_nphy_get_ipa_gain_table(dev);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- if (dev->phy.rev == 3)
- return b43_ntab_tx_gain_rev3_5ghz;
- if (dev->phy.rev == 4)
+ switch (phy->rev) {
+ case 6:
+ case 5:
+ return b43_ntab_tx_gain_epa_rev5_5g;
+ case 4:
return sprom->fem.ghz5.extpa_gain == 3 ?
- b43_ntab_tx_gain_rev4_5ghz :
- b43_ntab_tx_gain_rev4_5ghz; /* FIXME */
- else
- return b43_ntab_tx_gain_rev5plus_5ghz;
+ b43_ntab_tx_gain_epa_rev4_5g :
+ b43_ntab_tx_gain_epa_rev4_hi_pwr_5g;
+ case 3:
+ return b43_ntab_tx_gain_epa_rev3_5g;
+ default:
+ b43err(dev->wl,
+ "No 5GHz EPA gain table available for this device\n");
+ return NULL;
+ }
} else {
- if (dev->phy.rev >= 5 && sprom->fem.ghz5.extpa_gain == 3)
- return b43_ntab_tx_gain_rev3plus_2ghz; /* FIXME */
- else
- return b43_ntab_tx_gain_rev3plus_2ghz;
+ switch (phy->rev) {
+ case 6:
+ case 5:
+ if (sprom->fem.ghz5.extpa_gain == 3)
+ return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
+ /* fall through */
+ case 4:
+ case 3:
+ return b43_ntab_tx_gain_epa_rev3_2g;
+ default:
+ b43err(dev->wl,
+ "No 2GHz EPA gain table available for this device\n");
+ return NULL;
+ }
}
}
@@ -3191,7 +3731,7 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
/* Some workarounds to the workarounds... */
if (ghz5 && dev->phy.rev >= 6) {
if (dev->phy.radio_rev == 11 &&
- !b43_channel_type_is_40mhz(dev->phy.channel_type))
+ !b43_is_40mhz(dev))
e->cliplo_gain = 0x2d;
} else if (!ghz5 && dev->phy.rev >= 5) {
static const int gain_data[] = {0x0062, 0x0064, 0x006a, 0x106a,
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 3a58aee4c4cf..3ce2e6f3a278 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -165,6 +165,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
+/* Static N-PHY tables, PHY revision >= 7 */
+#define B43_NTAB_TMAP_R7 B43_NTAB32(12, 0) /* TM AP */
+#define B43_NTAB_NOISEVAR_R7 B43_NTAB32(16, 0) /* noise variance */
+
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 6e6ef3fc2247..426dc13c44cd 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -80,9 +80,10 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
}
/* Extract the bitrate index out of an OFDM PLCP header. */
-static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
+static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
{
- int base = aphy ? 0 : 4;
+ /* For 2 GHz band first OFDM rate is at index 4, see main.c */
+ int base = ghz5 ? 0 : 4;
switch (plcp->raw[0] & 0xF) {
case 0xB:
@@ -767,7 +768,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
if (phystat0 & B43_RX_PHYST0_OFDM)
rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
- phytype == B43_PHYTYPE_A);
+ !!(chanstat & B43_RX_CHAN_5GHZ));
else
rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
if (unlikely(rate_idx == -1)) {
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index fcfed6b99a62..b8e2561ea645 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -48,6 +48,16 @@ config BRCMFMAC_USB
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
use the driver for an USB wireless card.
+config BRCMFMAC_PCIE
+ bool "PCIE bus interface support for FullMAC driver"
+ depends on BRCMFMAC
+ depends on PCI
+ select FW_LOADER
+ ---help---
+ This option enables the PCIE bus interface support for Broadcom
+ IEEE802.11ac embedded FullMAC WLAN driver. Say Y if you want to
+ use the driver for an PCIE wireless card.
+
config BRCM_TRACING
bool "Broadcom device tracing"
depends on BRCMSMAC || BRCMFMAC
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 98e67c18f276..c35adf4bc70b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -31,16 +31,25 @@ brcmfmac-objs += \
p2p.o \
proto.o \
bcdc.o \
+ commonring.o \
+ flowring.o \
+ msgbuf.o \
dhd_common.o \
dhd_linux.o \
firmware.o \
- btcoex.o
+ feature.o \
+ btcoex.o \
+ vendor.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
bcmsdh.o
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
usb.o
+brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \
+ pcie.o
brcmfmac-$(CONFIG_BRCMDBG) += \
dhd_dbg.o
brcmfmac-$(CONFIG_BRCM_TRACING) += \
tracepoint.o
+brcmfmac-$(CONFIG_OF) += \
+ of.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
index c229210d50ba..a159ff3427de 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
@@ -337,6 +337,23 @@ brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
return brcmf_bus_txdata(drvr->bus_if, pktbuf);
}
+static void
+brcmf_proto_bcdc_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+ enum proto_addr_mode addr_mode)
+{
+}
+
+static void
+brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
+ u8 peer[ETH_ALEN])
+{
+}
+
+static void
+brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
+ u8 peer[ETH_ALEN])
+{
+}
int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
{
@@ -356,6 +373,9 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
drvr->proto->txdata = brcmf_proto_bcdc_txdata;
+ drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
+ drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
+ drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
drvr->proto->pd = bcdc;
drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index a16e644e7c08..8dbd5dbb78fd 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -25,7 +25,6 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/core.h>
#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
@@ -39,10 +38,13 @@
#include <brcm_hw_ids.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
+#include <chipcommon.h>
#include <soc.h>
+#include "chip.h"
#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "sdio_host.h"
+#include "of.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
@@ -118,6 +120,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
{
int ret = 0;
u8 data;
+ u32 addr, gpiocontrol;
unsigned long flags;
if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
@@ -147,6 +150,19 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
sdio_claim_host(sdiodev->func[1]);
+ if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
+ /* assign GPIO to SDIO core */
+ addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol);
+ gpiocontrol = brcmf_sdiod_regrl(sdiodev, addr, &ret);
+ gpiocontrol |= 0x2;
+ brcmf_sdiod_regwl(sdiodev, addr, gpiocontrol, &ret);
+
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_SELECT, 0xf,
+ &ret);
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
+ }
+
/* must configure SDIO_CCCR_IENx to enable irq */
data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
@@ -979,18 +995,20 @@ out:
return ret;
}
+#define BRCMF_SDIO_DEVICE(dev_id) \
+ {SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
+
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
- SDIO_DEVICE_ID_BROADCOM_4335_4339)},
- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)},
- { /* end: all zeroes */ },
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
+ BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
+ { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
@@ -1043,6 +1061,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
sdiodev->dev = &sdiodev->func[1]->dev;
sdiodev->pdata = brcmfmac_sdio_pdata;
+ if (!sdiodev->pdata)
+ brcmf_of_probe(sdiodev);
+
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_word_wait);
init_waitqueue_head(&sdiodev->request_buffer_wait);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
index 0cb591b050b3..a29ac4977b3a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -157,7 +157,7 @@ static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
*/
/* save current */
- brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n");
+ brcmf_dbg(INFO, "new SCO/eSCO coex algo {save & override}\n");
brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
@@ -165,7 +165,7 @@ static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
btci->saved_regs_part2 = true;
- brcmf_dbg(TRACE,
+ brcmf_dbg(INFO,
"saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
btci->reg50, btci->reg51, btci->reg64,
btci->reg65, btci->reg71);
@@ -179,21 +179,21 @@ static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
} else if (btci->saved_regs_part2) {
/* restore previously saved bt params */
- brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n");
+ brcmf_dbg(INFO, "Do new SCO/eSCO coex algo {restore}\n");
brcmf_btcoex_params_write(ifp, 50, btci->reg50);
brcmf_btcoex_params_write(ifp, 51, btci->reg51);
brcmf_btcoex_params_write(ifp, 64, btci->reg64);
brcmf_btcoex_params_write(ifp, 65, btci->reg65);
brcmf_btcoex_params_write(ifp, 71, btci->reg71);
- brcmf_dbg(TRACE,
+ brcmf_dbg(INFO,
"restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
btci->reg50, btci->reg51, btci->reg64,
btci->reg65, btci->reg71);
btci->saved_regs_part2 = false;
} else {
- brcmf_err("attempted to restore not saved BTCOEX params\n");
+ brcmf_dbg(INFO, "attempted to restore not saved BTCOEX params\n");
}
}
@@ -219,14 +219,14 @@ static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
break;
}
- brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27);
+ brcmf_dbg(INFO, "sample[%d], btc_params 27:%x\n", i, param27);
if ((param27 & 0x6) == 2) { /* count both sco & esco */
sco_id_cnt++;
}
if (sco_id_cnt > 2) {
- brcmf_dbg(TRACE,
+ brcmf_dbg(INFO,
"sco/esco detected, pkt id_cnt:%d samples:%d\n",
sco_id_cnt, i);
res = true;
@@ -250,7 +250,7 @@ static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
btci->saved_regs_part1 = true;
- brcmf_dbg(TRACE,
+ brcmf_dbg(INFO,
"saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
btci->reg66, btci->reg41,
btci->reg68);
@@ -270,7 +270,7 @@ static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
brcmf_btcoex_params_write(ifp, 66, btci->reg66);
brcmf_btcoex_params_write(ifp, 41, btci->reg41);
brcmf_btcoex_params_write(ifp, 68, btci->reg68);
- brcmf_dbg(TRACE,
+ brcmf_dbg(INFO,
"restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
btci->reg66, btci->reg41,
btci->reg68);
@@ -307,7 +307,7 @@ static void brcmf_btcoex_handler(struct work_struct *work)
/* DHCP started provide OPPORTUNITY window
to get DHCP address
*/
- brcmf_dbg(TRACE, "DHCP started\n");
+ brcmf_dbg(INFO, "DHCP started\n");
btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
mod_timer(&btci->timer, btci->timer.expires);
@@ -322,12 +322,12 @@ static void brcmf_btcoex_handler(struct work_struct *work)
case BRCMF_BT_DHCP_OPPR_WIN:
if (btci->dhcp_done) {
- brcmf_dbg(TRACE, "DHCP done before T1 expiration\n");
+ brcmf_dbg(INFO, "DHCP done before T1 expiration\n");
goto idle;
}
/* DHCP is not over yet, start lowering BT priority */
- brcmf_dbg(TRACE, "DHCP T1:%d expired\n",
+ brcmf_dbg(INFO, "DHCP T1:%d expired\n",
BRCMF_BTCOEX_OPPR_WIN_TIME);
brcmf_btcoex_boost_wifi(btci, true);
@@ -339,9 +339,9 @@ static void brcmf_btcoex_handler(struct work_struct *work)
case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
if (btci->dhcp_done)
- brcmf_dbg(TRACE, "DHCP done before T2 expiration\n");
+ brcmf_dbg(INFO, "DHCP done before T2 expiration\n");
else
- brcmf_dbg(TRACE, "DHCP T2:%d expired\n",
+ brcmf_dbg(INFO, "DHCP T2:%d expired\n",
BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
goto idle;
@@ -440,13 +440,13 @@ static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
/* Stop any bt timer because DHCP session is done */
btci->dhcp_done = true;
if (btci->timer_on) {
- brcmf_dbg(TRACE, "disable BT DHCP Timer\n");
+ brcmf_dbg(INFO, "disable BT DHCP Timer\n");
btci->timer_on = false;
del_timer_sync(&btci->timer);
/* schedule worker if transition to IDLE is needed */
if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
- brcmf_dbg(TRACE, "bt_state:%d\n",
+ brcmf_dbg(INFO, "bt_state:%d\n",
btci->bt_state);
schedule_work(&btci->work);
}
@@ -472,7 +472,7 @@ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
switch (mode) {
case BRCMF_BTCOEX_DISABLED:
- brcmf_dbg(TRACE, "DHCP session starts\n");
+ brcmf_dbg(INFO, "DHCP session starts\n");
if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
return -EBUSY;
/* Start BT timer only for SCO connection */
@@ -484,14 +484,14 @@ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
break;
case BRCMF_BTCOEX_ENABLED:
- brcmf_dbg(TRACE, "DHCP session ends\n");
+ brcmf_dbg(INFO, "DHCP session ends\n");
if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
vif == btci->vif) {
brcmf_btcoex_dhcp_end(btci);
}
break;
default:
- brcmf_dbg(TRACE, "Unknown mode, ignored\n");
+ brcmf_dbg(INFO, "Unknown mode, ignored\n");
}
return 0;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index c7c9f15c0fe0..95efde868db8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -482,33 +482,41 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
{
switch (ci->pub.chip) {
- case BCM4329_CHIP_ID:
+ case BRCM_CC_4329_CHIP_ID:
ci->pub.ramsize = BCM4329_RAMSIZE;
break;
- case BCM43143_CHIP_ID:
+ case BRCM_CC_43143_CHIP_ID:
ci->pub.ramsize = BCM43143_RAMSIZE;
break;
- case BCM43241_CHIP_ID:
+ case BRCM_CC_43241_CHIP_ID:
ci->pub.ramsize = 0x90000;
break;
- case BCM4330_CHIP_ID:
+ case BRCM_CC_4330_CHIP_ID:
ci->pub.ramsize = 0x48000;
break;
- case BCM4334_CHIP_ID:
+ case BRCM_CC_4334_CHIP_ID:
ci->pub.ramsize = 0x80000;
break;
- case BCM4335_CHIP_ID:
+ case BRCM_CC_4335_CHIP_ID:
ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000;
break;
- case BCM43362_CHIP_ID:
+ case BRCM_CC_43362_CHIP_ID:
ci->pub.ramsize = 0x3c000;
break;
- case BCM4339_CHIP_ID:
- case BCM4354_CHIP_ID:
+ case BRCM_CC_4339_CHIP_ID:
+ case BRCM_CC_4354_CHIP_ID:
+ case BRCM_CC_4356_CHIP_ID:
+ case BRCM_CC_43567_CHIP_ID:
+ case BRCM_CC_43569_CHIP_ID:
+ case BRCM_CC_43570_CHIP_ID:
ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000;
break;
+ case BRCM_CC_43602_CHIP_ID:
+ ci->pub.ramsize = 0xf0000;
+ ci->pub.rambase = 0x180000;
+ break;
default:
brcmf_err("unknown chip: %s\n", ci->pub.name);
break;
@@ -682,7 +690,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
ci->pub.chiprev);
if (socitype == SOCI_SB) {
- if (ci->pub.chip != BCM4329_CHIP_ID) {
+ if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
brcmf_err("SB chip is not supported\n");
return -ENODEV;
}
@@ -1008,13 +1016,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
chip = container_of(pub, struct brcmf_chip_priv, pub);
switch (pub->chip) {
- case BCM4354_CHIP_ID:
+ case BRCM_CC_4354_CHIP_ID:
/* explicitly check SR engine enable bit */
pmu_cc3_mask = BIT(2);
/* fall-through */
- case BCM43241_CHIP_ID:
- case BCM4335_CHIP_ID:
- case BCM4339_CHIP_ID:
+ case BRCM_CC_43241_CHIP_ID:
+ case BRCM_CC_4335_CHIP_ID:
+ case BRCM_CC_4339_CHIP_ID:
/* read PMU chipcontrol register 3 */
addr = CORE_CC_REG(base, chipcontrol_addr);
chip->ops->write32(chip->ctx, addr, 3);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
new file mode 100644
index 000000000000..c6d65b8e1e15
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
@@ -0,0 +1,273 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "commonring.h"
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ * SEE ALSO msgbuf.c
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+ int (*cr_ring_bell)(void *ctx),
+ int (*cr_update_rptr)(void *ctx),
+ int (*cr_update_wptr)(void *ctx),
+ int (*cr_write_rptr)(void *ctx),
+ int (*cr_write_wptr)(void *ctx), void *ctx)
+{
+ commonring->cr_ring_bell = cr_ring_bell;
+ commonring->cr_update_rptr = cr_update_rptr;
+ commonring->cr_update_wptr = cr_update_wptr;
+ commonring->cr_write_rptr = cr_write_rptr;
+ commonring->cr_write_wptr = cr_write_wptr;
+ commonring->cr_ctx = ctx;
+}
+
+
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+ u16 item_len, void *buf_addr)
+{
+ commonring->depth = depth;
+ commonring->item_len = item_len;
+ commonring->buf_addr = buf_addr;
+ if (!commonring->inited) {
+ spin_lock_init(&commonring->lock);
+ commonring->inited = true;
+ }
+ commonring->r_ptr = 0;
+ if (commonring->cr_write_rptr)
+ commonring->cr_write_rptr(commonring->cr_ctx);
+ commonring->w_ptr = 0;
+ if (commonring->cr_write_wptr)
+ commonring->cr_write_wptr(commonring->cr_ctx);
+ commonring->f_ptr = 0;
+}
+
+
+void brcmf_commonring_lock(struct brcmf_commonring *commonring)
+ __acquires(&commonring->lock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&commonring->lock, flags);
+ commonring->flags = flags;
+}
+
+
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
+ __releases(&commonring->lock)
+{
+ spin_unlock_irqrestore(&commonring->lock, commonring->flags);
+}
+
+
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
+{
+ u16 available;
+ bool retry = true;
+
+again:
+ if (commonring->r_ptr <= commonring->w_ptr)
+ available = commonring->depth - commonring->w_ptr +
+ commonring->r_ptr;
+ else
+ available = commonring->r_ptr - commonring->w_ptr;
+
+ if (available > 1) {
+ if (!commonring->was_full)
+ return true;
+ if (available > commonring->depth / 8) {
+ commonring->was_full = false;
+ return true;
+ }
+ if (retry) {
+ if (commonring->cr_update_rptr)
+ commonring->cr_update_rptr(commonring->cr_ctx);
+ retry = false;
+ goto again;
+ }
+ return false;
+ }
+
+ if (retry) {
+ if (commonring->cr_update_rptr)
+ commonring->cr_update_rptr(commonring->cr_ctx);
+ retry = false;
+ goto again;
+ }
+
+ commonring->was_full = true;
+ return false;
+}
+
+
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
+{
+ void *ret_ptr;
+ u16 available;
+ bool retry = true;
+
+again:
+ if (commonring->r_ptr <= commonring->w_ptr)
+ available = commonring->depth - commonring->w_ptr +
+ commonring->r_ptr;
+ else
+ available = commonring->r_ptr - commonring->w_ptr;
+
+ if (available > 1) {
+ ret_ptr = commonring->buf_addr +
+ (commonring->w_ptr * commonring->item_len);
+ commonring->w_ptr++;
+ if (commonring->w_ptr == commonring->depth)
+ commonring->w_ptr = 0;
+ return ret_ptr;
+ }
+
+ if (retry) {
+ if (commonring->cr_update_rptr)
+ commonring->cr_update_rptr(commonring->cr_ctx);
+ retry = false;
+ goto again;
+ }
+
+ commonring->was_full = true;
+ return NULL;
+}
+
+
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+ u16 n_items, u16 *alloced)
+{
+ void *ret_ptr;
+ u16 available;
+ bool retry = true;
+
+again:
+ if (commonring->r_ptr <= commonring->w_ptr)
+ available = commonring->depth - commonring->w_ptr +
+ commonring->r_ptr;
+ else
+ available = commonring->r_ptr - commonring->w_ptr;
+
+ if (available > 1) {
+ ret_ptr = commonring->buf_addr +
+ (commonring->w_ptr * commonring->item_len);
+ *alloced = min_t(u16, n_items, available - 1);
+ if (*alloced + commonring->w_ptr > commonring->depth)
+ *alloced = commonring->depth - commonring->w_ptr;
+ commonring->w_ptr += *alloced;
+ if (commonring->w_ptr == commonring->depth)
+ commonring->w_ptr = 0;
+ return ret_ptr;
+ }
+
+ if (retry) {
+ if (commonring->cr_update_rptr)
+ commonring->cr_update_rptr(commonring->cr_ctx);
+ retry = false;
+ goto again;
+ }
+
+ commonring->was_full = true;
+ return NULL;
+}
+
+
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
+{
+ void *address;
+
+ address = commonring->buf_addr;
+ address += (commonring->f_ptr * commonring->item_len);
+ if (commonring->f_ptr > commonring->w_ptr) {
+ brcmf_dma_flush(address,
+ (commonring->depth - commonring->f_ptr) *
+ commonring->item_len);
+ address = commonring->buf_addr;
+ commonring->f_ptr = 0;
+ }
+ brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
+ commonring->item_len);
+
+ commonring->f_ptr = commonring->w_ptr;
+
+ if (commonring->cr_write_wptr)
+ commonring->cr_write_wptr(commonring->cr_ctx);
+ if (commonring->cr_ring_bell)
+ return commonring->cr_ring_bell(commonring->cr_ctx);
+
+ return -EIO;
+}
+
+
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+ u16 n_items)
+{
+ if (commonring->w_ptr == 0)
+ commonring->w_ptr = commonring->depth - n_items;
+ else
+ commonring->w_ptr -= n_items;
+}
+
+
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+ u16 *n_items)
+{
+ void *ret_addr;
+
+ if (commonring->cr_update_wptr)
+ commonring->cr_update_wptr(commonring->cr_ctx);
+
+ *n_items = (commonring->w_ptr >= commonring->r_ptr) ?
+ (commonring->w_ptr - commonring->r_ptr) :
+ (commonring->depth - commonring->r_ptr);
+
+ if (*n_items == 0)
+ return NULL;
+
+ ret_addr = commonring->buf_addr +
+ (commonring->r_ptr * commonring->item_len);
+
+ commonring->r_ptr += *n_items;
+ if (commonring->r_ptr == commonring->depth)
+ commonring->r_ptr = 0;
+
+ brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
+
+ return ret_addr;
+}
+
+
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
+{
+ if (commonring->cr_write_rptr)
+ return commonring->cr_write_rptr(commonring->cr_ctx);
+
+ return -EIO;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
new file mode 100644
index 000000000000..002336e35764
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_COMMONRING_H
+#define BRCMFMAC_COMMONRING_H
+
+
+struct brcmf_commonring {
+ u16 r_ptr;
+ u16 w_ptr;
+ u16 f_ptr;
+ u16 depth;
+ u16 item_len;
+
+ void *buf_addr;
+
+ int (*cr_ring_bell)(void *ctx);
+ int (*cr_update_rptr)(void *ctx);
+ int (*cr_update_wptr)(void *ctx);
+ int (*cr_write_rptr)(void *ctx);
+ int (*cr_write_wptr)(void *ctx);
+
+ void *cr_ctx;
+
+ spinlock_t lock;
+ unsigned long flags;
+ bool inited;
+ bool was_full;
+};
+
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+ int (*cr_ring_bell)(void *ctx),
+ int (*cr_update_rptr)(void *ctx),
+ int (*cr_update_wptr)(void *ctx),
+ int (*cr_write_rptr)(void *ctx),
+ int (*cr_write_wptr)(void *ctx), void *ctx);
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+ u16 item_len, void *buf_addr);
+void brcmf_commonring_lock(struct brcmf_commonring *commonring);
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring);
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring);
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring);
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+ u16 n_items, u16 *alloced);
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring);
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+ u16 n_items);
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+ u16 *n_items);
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
+
+#define brcmf_commonring_n_items(commonring) (commonring->depth)
+#define brcmf_commonring_len_item(commonring) (commonring->item_len)
+
+
+#endif /* BRCMFMAC_COMMONRING_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 16f9ab2568a8..5e4317dbc2b0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -49,16 +49,6 @@
*/
#define BRCMF_DRIVER_FIRMWARE_VERSION_LEN 32
-/* Bus independent dongle command */
-struct brcmf_dcmd {
- uint cmd; /* common dongle cmd definition */
- void *buf; /* pointer to user buffer */
- uint len; /* length of user buffer */
- u8 set; /* get or set request (optional) */
- uint used; /* bytes read or written (optional) */
- uint needed; /* bytes needed (optional) */
-};
-
/**
* struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info
*
@@ -113,6 +103,10 @@ struct brcmf_pub {
struct brcmf_ampdu_rx_reorder
*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
+
+ u32 feat_flags;
+ u32 chip_quirks;
+
#ifdef DEBUG
struct dentry *dbgfs_dir;
#endif
@@ -127,12 +121,12 @@ struct brcmf_fws_mac_descriptor;
*
* @BRCMF_NETIF_STOP_REASON_FWS_FC:
* netif stopped due to firmware signalling flow control.
- * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS:
- * netif stopped due to bus blocking.
+ * @BRCMF_NETIF_STOP_REASON_FLOW:
+ * netif stopped due to flowring full.
*/
enum brcmf_netif_stop_reason {
BRCMF_NETIF_STOP_REASON_FWS_FC = 1,
- BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2
+ BRCMF_NETIF_STOP_REASON_FLOW = 2
};
/**
@@ -185,9 +179,9 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
-u32 brcmf_get_chip_info(struct brcmf_if *ifp);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success);
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
/* Sets dongle media info (drv_version, mac address). */
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 7735328fff21..3122b86050a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -19,6 +19,18 @@
#include "dhd_dbg.h"
+/* IDs of the 6 default common rings of msgbuf protocol */
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2
+#define BRCMF_D2H_MSGRING_TX_COMPLETE 3
+#define BRCMF_D2H_MSGRING_RX_COMPLETE 4
+
+#define BRCMF_NROF_H2D_COMMON_MSGRINGS 2
+#define BRCMF_NROF_D2H_COMMON_MSGRINGS 3
+#define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \
+ BRCMF_NROF_D2H_COMMON_MSGRINGS)
+
/* The level of bus communication with the dongle */
enum brcmf_bus_state {
BRCMF_BUS_UNKNOWN, /* Not determined yet */
@@ -70,6 +82,25 @@ struct brcmf_bus_ops {
struct pktq * (*gettxq)(struct device *dev);
};
+
+/**
+ * struct brcmf_bus_msgbuf - bus ringbuf if in case of msgbuf.
+ *
+ * @commonrings: commonrings which are always there.
+ * @flowrings: commonrings which are dynamically created and destroyed for data.
+ * @rx_dataoffset: if set then all rx data has this this offset.
+ * @max_rxbufpost: maximum number of buffers to post for rx.
+ * @nrof_flowrings: number of flowrings.
+ */
+struct brcmf_bus_msgbuf {
+ struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+ struct brcmf_commonring **flowrings;
+ u32 rx_dataoffset;
+ u32 max_rxbufpost;
+ u32 nrof_flowrings;
+};
+
+
/**
* struct brcmf_bus - interface structure between common and bus layer
*
@@ -89,6 +120,7 @@ struct brcmf_bus {
union {
struct brcmf_sdio_dev *sdio;
struct brcmf_usbdev *usb;
+ struct brcmf_pciedev *pcie;
} bus_priv;
enum brcmf_bus_protocol_type proto_type;
struct device *dev;
@@ -101,6 +133,7 @@ struct brcmf_bus {
bool always_use_fws_queue;
struct brcmf_bus_ops *ops;
+ struct brcmf_bus_msgbuf *msgbuf;
};
/*
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index ed3e32ce8c23..d991f8e3d9ec 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -282,6 +282,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
ptr = strrchr(buf, ' ') + 1;
strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+ /* set mpc */
+ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
+ if (err) {
+ brcmf_err("failed setting mpc\n");
+ goto done;
+ }
+
/*
* Setup timeout if Beacons are lost and roam is off to report
* link down
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 03fe8aca4d32..be9f4f829192 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void)
root_folder = NULL;
}
-static
-ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
- size_t count, loff_t *ppos)
+static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
{
- struct brcmf_pub *drvr = f->private_data;
- struct brcmf_bus *bus = drvr->bus_if;
- char buf[40];
- int res;
-
- /* only allow read from start */
- if (*ppos > 0)
- return 0;
-
- res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n",
- bus->chip, bus->chip, bus->chiprev);
- return simple_read_from_buffer(data, count, ppos, buf, res);
-}
-
-static const struct file_operations brcmf_debugfs_chipinfo_ops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = brcmf_debugfs_chipinfo_read
-};
-
-static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr)
-{
- struct dentry *dentry = drvr->dbgfs_dir;
+ struct brcmf_bus *bus = dev_get_drvdata(seq->private);
- if (!IS_ERR_OR_NULL(dentry))
- debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr,
- &brcmf_debugfs_chipinfo_ops);
+ seq_printf(seq, "chip: %x(%u) rev %u\n",
+ bus->chip, bus->chip, bus->chiprev);
return 0;
}
@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
return -ENODEV;
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
- brcmf_debugfs_create_chipinfo(drvr);
+ brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
+
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
}
@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
return drvr->dbgfs_dir;
}
-static
-ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data,
- size_t count, loff_t *ppos)
-{
- struct brcmf_sdio_count *sdcnt = f->private_data;
- char buf[750];
- int res;
-
- /* only allow read from start */
- if (*ppos > 0)
- return 0;
-
- res = scnprintf(buf, sizeof(buf),
- "intrcount: %u\nlastintrs: %u\n"
- "pollcnt: %u\nregfails: %u\n"
- "tx_sderrs: %u\nfcqueued: %u\n"
- "rxrtx: %u\nrx_toolong: %u\n"
- "rxc_errors: %u\nrx_hdrfail: %u\n"
- "rx_badhdr: %u\nrx_badseq: %u\n"
- "fc_rcvd: %u\nfc_xoff: %u\n"
- "fc_xon: %u\nrxglomfail: %u\n"
- "rxglomframes: %u\nrxglompkts: %u\n"
- "f2rxhdrs: %u\nf2rxdata: %u\n"
- "f2txdata: %u\nf1regdata: %u\n"
- "tickcnt: %u\ntx_ctlerrs: %lu\n"
- "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
- "rx_ctlpkts: %lu\nrx_readahead: %lu\n",
- sdcnt->intrcount, sdcnt->lastintrs,
- sdcnt->pollcnt, sdcnt->regfails,
- sdcnt->tx_sderrs, sdcnt->fcqueued,
- sdcnt->rxrtx, sdcnt->rx_toolong,
- sdcnt->rxc_errors, sdcnt->rx_hdrfail,
- sdcnt->rx_badhdr, sdcnt->rx_badseq,
- sdcnt->fc_rcvd, sdcnt->fc_xoff,
- sdcnt->fc_xon, sdcnt->rxglomfail,
- sdcnt->rxglomframes, sdcnt->rxglompkts,
- sdcnt->f2rxhdrs, sdcnt->f2rxdata,
- sdcnt->f2txdata, sdcnt->f1regdata,
- sdcnt->tickcnt, sdcnt->tx_ctlerrs,
- sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
- sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
-
- return simple_read_from_buffer(data, count, ppos, buf, res);
-}
-
-static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = brcmf_debugfs_sdio_counter_read
+struct brcmf_debugfs_entry {
+ int (*read)(struct seq_file *seq, void *data);
+ struct brcmf_pub *drvr;
};
-void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
- struct brcmf_sdio_count *sdcnt)
+static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
{
- struct dentry *dentry = drvr->dbgfs_dir;
+ struct brcmf_debugfs_entry *entry = inode->i_private;
- if (!IS_ERR_OR_NULL(dentry))
- debugfs_create_file("counters", S_IRUGO, dentry,
- sdcnt, &brcmf_debugfs_sdio_counter_ops);
-}
-
-static
-ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
- size_t count, loff_t *ppos)
-{
- struct brcmf_fws_stats *fwstats = f->private_data;
- char buf[650];
- int res;
-
- /* only allow read from start */
- if (*ppos > 0)
- return 0;
-
- res = scnprintf(buf, sizeof(buf),
- "header_pulls: %u\n"
- "header_only_pkt: %u\n"
- "tlv_parse_failed: %u\n"
- "tlv_invalid_type: %u\n"
- "mac_update_fails: %u\n"
- "ps_update_fails: %u\n"
- "if_update_fails: %u\n"
- "pkt2bus: %u\n"
- "generic_error: %u\n"
- "rollback_success: %u\n"
- "rollback_failed: %u\n"
- "delayq_full: %u\n"
- "supprq_full: %u\n"
- "txs_indicate: %u\n"
- "txs_discard: %u\n"
- "txs_suppr_core: %u\n"
- "txs_suppr_ps: %u\n"
- "txs_tossed: %u\n"
- "txs_host_tossed: %u\n"
- "bus_flow_block: %u\n"
- "fws_flow_block: %u\n"
- "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
- "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
- fwstats->header_pulls,
- fwstats->header_only_pkt,
- fwstats->tlv_parse_failed,
- fwstats->tlv_invalid_type,
- fwstats->mac_update_failed,
- fwstats->mac_ps_update_failed,
- fwstats->if_update_failed,
- fwstats->pkt2bus,
- fwstats->generic_error,
- fwstats->rollback_success,
- fwstats->rollback_failed,
- fwstats->delayq_full_error,
- fwstats->supprq_full_error,
- fwstats->txs_indicate,
- fwstats->txs_discard,
- fwstats->txs_supp_core,
- fwstats->txs_supp_ps,
- fwstats->txs_tossed,
- fwstats->txs_host_tossed,
- fwstats->bus_flow_block,
- fwstats->fws_flow_block,
- fwstats->send_pkts[0], fwstats->send_pkts[1],
- fwstats->send_pkts[2], fwstats->send_pkts[3],
- fwstats->send_pkts[4],
- fwstats->requested_sent[0],
- fwstats->requested_sent[1],
- fwstats->requested_sent[2],
- fwstats->requested_sent[3],
- fwstats->requested_sent[4]);
-
- return simple_read_from_buffer(data, count, ppos, buf, res);
+ return single_open(f, entry->read, entry->drvr->bus_if->dev);
}
-static const struct file_operations brcmf_debugfs_fws_stats_ops = {
+static const struct file_operations brcmf_debugfs_def_ops = {
.owner = THIS_MODULE,
- .open = simple_open,
- .read = brcmf_debugfs_fws_stats_read
+ .open = brcmf_debugfs_entry_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek
};
-void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
- struct brcmf_fws_stats *stats)
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+ int (*read_fn)(struct seq_file *seq, void *data))
{
struct dentry *dentry = drvr->dbgfs_dir;
+ struct brcmf_debugfs_entry *entry;
+
+ if (IS_ERR_OR_NULL(dentry))
+ return -ENOENT;
+
+ entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->read = read_fn;
+ entry->drvr = drvr;
+
+ dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
+ &brcmf_debugfs_def_ops);
- if (!IS_ERR_OR_NULL(dentry))
- debugfs_create_file("fws_stats", S_IRUGO, dentry,
- stats, &brcmf_debugfs_fws_stats_ops);
+ return PTR_ERR_OR_ZERO(dentry);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index ef52ed7abc69..dec40d316c82 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -18,23 +18,25 @@
#define _BRCMF_DBG_H_
/* message levels */
-#define BRCMF_TRACE_VAL 0x00000002
-#define BRCMF_INFO_VAL 0x00000004
-#define BRCMF_DATA_VAL 0x00000008
-#define BRCMF_CTL_VAL 0x00000010
-#define BRCMF_TIMER_VAL 0x00000020
-#define BRCMF_HDRS_VAL 0x00000040
-#define BRCMF_BYTES_VAL 0x00000080
-#define BRCMF_INTR_VAL 0x00000100
-#define BRCMF_GLOM_VAL 0x00000200
-#define BRCMF_EVENT_VAL 0x00000400
-#define BRCMF_BTA_VAL 0x00000800
-#define BRCMF_FIL_VAL 0x00001000
-#define BRCMF_USB_VAL 0x00002000
-#define BRCMF_SCAN_VAL 0x00004000
-#define BRCMF_CONN_VAL 0x00008000
-#define BRCMF_BCDC_VAL 0x00010000
-#define BRCMF_SDIO_VAL 0x00020000
+#define BRCMF_TRACE_VAL 0x00000002
+#define BRCMF_INFO_VAL 0x00000004
+#define BRCMF_DATA_VAL 0x00000008
+#define BRCMF_CTL_VAL 0x00000010
+#define BRCMF_TIMER_VAL 0x00000020
+#define BRCMF_HDRS_VAL 0x00000040
+#define BRCMF_BYTES_VAL 0x00000080
+#define BRCMF_INTR_VAL 0x00000100
+#define BRCMF_GLOM_VAL 0x00000200
+#define BRCMF_EVENT_VAL 0x00000400
+#define BRCMF_BTA_VAL 0x00000800
+#define BRCMF_FIL_VAL 0x00001000
+#define BRCMF_USB_VAL 0x00002000
+#define BRCMF_SCAN_VAL 0x00004000
+#define BRCMF_CONN_VAL 0x00008000
+#define BRCMF_BCDC_VAL 0x00010000
+#define BRCMF_SDIO_VAL 0x00020000
+#define BRCMF_MSGBUF_VAL 0x00040000
+#define BRCMF_PCIE_VAL 0x00080000
/* set default print format */
#undef pr_fmt
@@ -100,68 +102,6 @@ do { \
extern int brcmf_msg_level;
-/*
- * hold counter variables used in brcmfmac sdio driver.
- */
-struct brcmf_sdio_count {
- uint intrcount; /* Count of device interrupt callbacks */
- uint lastintrs; /* Count as of last watchdog timer */
- uint pollcnt; /* Count of active polls */
- uint regfails; /* Count of R_REG failures */
- uint tx_sderrs; /* Count of tx attempts with sd errors */
- uint fcqueued; /* Tx packets that got queued */
- uint rxrtx; /* Count of rtx requests (NAK to dongle) */
- uint rx_toolong; /* Receive frames too long to receive */
- uint rxc_errors; /* SDIO errors when reading control frames */
- uint rx_hdrfail; /* SDIO errors on header reads */
- uint rx_badhdr; /* Bad received headers (roosync?) */
- uint rx_badseq; /* Mismatched rx sequence number */
- uint fc_rcvd; /* Number of flow-control events received */
- uint fc_xoff; /* Number which turned on flow-control */
- uint fc_xon; /* Number which turned off flow-control */
- uint rxglomfail; /* Failed deglom attempts */
- uint rxglomframes; /* Number of glom frames (superframes) */
- uint rxglompkts; /* Number of packets from glom frames */
- uint f2rxhdrs; /* Number of header reads */
- uint f2rxdata; /* Number of frame data reads */
- uint f2txdata; /* Number of f2 frame writes */
- uint f1regdata; /* Number of f1 register accesses */
- uint tickcnt; /* Number of watchdog been schedule */
- ulong tx_ctlerrs; /* Err of sending ctrl frames */
- ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
- ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
- ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
- ulong rx_readahead_cnt; /* packets where header read-ahead was used */
-};
-
-struct brcmf_fws_stats {
- u32 tlv_parse_failed;
- u32 tlv_invalid_type;
- u32 header_only_pkt;
- u32 header_pulls;
- u32 pkt2bus;
- u32 send_pkts[5];
- u32 requested_sent[5];
- u32 generic_error;
- u32 mac_update_failed;
- u32 mac_ps_update_failed;
- u32 if_update_failed;
- u32 packet_request_failed;
- u32 credit_request_failed;
- u32 rollback_success;
- u32 rollback_failed;
- u32 delayq_full_error;
- u32 supprq_full_error;
- u32 txs_indicate;
- u32 txs_discard;
- u32 txs_supp_core;
- u32 txs_supp_ps;
- u32 txs_tossed;
- u32 txs_host_tossed;
- u32 bus_flow_block;
- u32 fws_flow_block;
-};
-
struct brcmf_pub;
#ifdef DEBUG
void brcmf_debugfs_init(void);
@@ -169,10 +109,8 @@ void brcmf_debugfs_exit(void);
int brcmf_debugfs_attach(struct brcmf_pub *drvr);
void brcmf_debugfs_detach(struct brcmf_pub *drvr);
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
-void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
- struct brcmf_sdio_count *sdcnt);
-void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
- struct brcmf_fws_stats *stats);
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+ int (*read_fn)(struct seq_file *seq, void *data));
#else
static inline void brcmf_debugfs_init(void)
{
@@ -187,9 +125,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
{
}
-static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
- struct brcmf_fws_stats *stats)
+static inline
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+ int (*read_fn)(struct seq_file *seq, void *data))
{
+ return 0;
}
#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 09dd8c13d844..fb1043908a23 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -30,7 +30,9 @@
#include "wl_cfg80211.h"
#include "fwil.h"
#include "fwsignal.h"
+#include "feature.h"
#include "proto.h"
+#include "pcie.h"
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -287,7 +289,7 @@ void brcmf_txflowblock(struct device *dev, bool state)
brcmf_fws_bus_blocked(drvr, state);
}
-static void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{
skb->dev = ifp->ndev;
skb->protocol = eth_type_trans(skb, skb->dev);
@@ -808,7 +810,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
} else {
brcmf_dbg(INFO, "allocate netdev interface\n");
/* Allocate netdev, including space for private structure */
- ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
+ ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN,
+ ether_setup);
if (!ndev)
return ERR_PTR(-ENOMEM);
@@ -936,6 +939,8 @@ int brcmf_bus_start(struct device *dev)
if (ret < 0)
goto fail;
+ brcmf_feat_attach(drvr);
+
ret = brcmf_fws_init(drvr);
if (ret < 0)
goto fail;
@@ -1073,16 +1078,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
return !err;
}
-/*
- * return chip id and rev of the device encoded in u32.
- */
-u32 brcmf_get_chip_info(struct brcmf_if *ifp)
-{
- struct brcmf_bus *bus = ifp->drvr->bus_if;
-
- return bus->chip << 4 | bus->chiprev;
-}
-
static void brcmf_driver_register(struct work_struct *work)
{
#ifdef CONFIG_BRCMFMAC_SDIO
@@ -1091,6 +1086,9 @@ static void brcmf_driver_register(struct work_struct *work)
#ifdef CONFIG_BRCMFMAC_USB
brcmf_usb_register();
#endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+ brcmf_pcie_register();
+#endif
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
@@ -1116,6 +1114,9 @@ static void __exit brcmfmac_module_exit(void)
#ifdef CONFIG_BRCMFMAC_USB
brcmf_usb_exit();
#endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+ brcmf_pcie_exit();
+#endif
brcmf_debugfs_exit();
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 8fa0dbbbda72..f55f625fd06b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo {
u16 tail_pad;
};
+/*
+ * hold counter variables
+ */
+struct brcmf_sdio_count {
+ uint intrcount; /* Count of device interrupt callbacks */
+ uint lastintrs; /* Count as of last watchdog timer */
+ uint pollcnt; /* Count of active polls */
+ uint regfails; /* Count of R_REG failures */
+ uint tx_sderrs; /* Count of tx attempts with sd errors */
+ uint fcqueued; /* Tx packets that got queued */
+ uint rxrtx; /* Count of rtx requests (NAK to dongle) */
+ uint rx_toolong; /* Receive frames too long to receive */
+ uint rxc_errors; /* SDIO errors when reading control frames */
+ uint rx_hdrfail; /* SDIO errors on header reads */
+ uint rx_badhdr; /* Bad received headers (roosync?) */
+ uint rx_badseq; /* Mismatched rx sequence number */
+ uint fc_rcvd; /* Number of flow-control events received */
+ uint fc_xoff; /* Number which turned on flow-control */
+ uint fc_xon; /* Number which turned off flow-control */
+ uint rxglomfail; /* Failed deglom attempts */
+ uint rxglomframes; /* Number of glom frames (superframes) */
+ uint rxglompkts; /* Number of packets from glom frames */
+ uint f2rxhdrs; /* Number of header reads */
+ uint f2rxdata; /* Number of frame data reads */
+ uint f2txdata; /* Number of f2 frame writes */
+ uint f1regdata; /* Number of f1 register accesses */
+ uint tickcnt; /* Number of watchdog been schedule */
+ ulong tx_ctlerrs; /* Err of sending ctrl frames */
+ ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
+ ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
+ ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
+ ulong rx_readahead_cnt; /* packets where header read-ahead was used */
+};
+
/* misc chip info needed by some of the routines */
/* Private data for SDIO bus interaction */
struct brcmf_sdio {
@@ -620,40 +654,57 @@ enum brcmf_firmware_type {
name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
static const struct brcmf_firmware_names brcmf_fwname_data[] = {
- { BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
- { BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
- { BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
- { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
- { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
- { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
- { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
- { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
- { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
- { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
+ { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
+ { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
+ { BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
+ { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
+ { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
+ { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
+ { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+ { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
+ { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
+ { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
};
-static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci,
- enum brcmf_firmware_type type)
+static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
+ struct brcmf_sdio_dev *sdiodev)
{
int i;
+ uint fw_len, nv_len;
+ char end;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
if (brcmf_fwname_data[i].chipid == ci->chip &&
- brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) {
- switch (type) {
- case BRCMF_FIRMWARE_BIN:
- return brcmf_fwname_data[i].bin;
- case BRCMF_FIRMWARE_NVRAM:
- return brcmf_fwname_data[i].nv;
- default:
- brcmf_err("invalid firmware type (%d)\n", type);
- return NULL;
- }
+ brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(brcmf_fwname_data)) {
+ brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
+ return -ENODEV;
+ }
+
+ fw_len = sizeof(sdiodev->fw_name) - 1;
+ nv_len = sizeof(sdiodev->nvram_name) - 1;
+ /* check if firmware path is provided by module parameter */
+ if (brcmf_firmware_path[0] != '\0') {
+ strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
+ strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
+ fw_len -= strlen(sdiodev->fw_name);
+ nv_len -= strlen(sdiodev->nvram_name);
+
+ end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+ if (end != '/') {
+ strncat(sdiodev->fw_name, "/", fw_len);
+ strncat(sdiodev->nvram_name, "/", nv_len);
+ fw_len--;
+ nv_len--;
}
}
- brcmf_err("Unknown chipid %d [%d]\n",
- ci->chip, ci->chiprev);
- return NULL;
+ strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
+ strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
+
+ return 0;
}
static void pkt_align(struct sk_buff *p, int len, int align)
@@ -2898,16 +2949,13 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
}
#ifdef DEBUG
-static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
- struct sdpcm_shared *sh, char __user *data,
- size_t count)
+static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh)
{
u32 addr, console_ptr, console_size, console_index;
char *conbuf = NULL;
__le32 sh_val;
int rv;
- loff_t pos = 0;
- int nbytes = 0;
/* obtain console information from device memory */
addr = sh->console_addr + offsetof(struct rte_console, log_le);
@@ -2945,33 +2993,24 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
if (rv < 0)
goto done;
- rv = simple_read_from_buffer(data, count, &pos,
- conbuf + console_index,
- console_size - console_index);
+ rv = seq_write(seq, conbuf + console_index,
+ console_size - console_index);
if (rv < 0)
goto done;
- nbytes = rv;
- if (console_index > 0) {
- pos = 0;
- rv = simple_read_from_buffer(data+nbytes, count, &pos,
- conbuf, console_index - 1);
- if (rv < 0)
- goto done;
- rv += nbytes;
- }
+ if (console_index > 0)
+ rv = seq_write(seq, conbuf, console_index - 1);
+
done:
vfree(conbuf);
return rv;
}
-static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
- char __user *data, size_t count)
+static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh)
{
- int error, res;
- char buf[350];
+ int error;
struct brcmf_trap_info tr;
- loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
brcmf_dbg(INFO, "no trap in firmware\n");
@@ -2983,34 +3022,30 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
if (error < 0)
return error;
- res = scnprintf(buf, sizeof(buf),
- "dongle trap info: type 0x%x @ epc 0x%08x\n"
- " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
- " lr 0x%08x pc 0x%08x offset 0x%x\n"
- " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
- " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
- le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
- le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
- le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
- le32_to_cpu(tr.pc), sh->trap_addr,
- le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
- le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
- le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
- le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
-
- return simple_read_from_buffer(data, count, &pos, buf, res);
+ seq_printf(seq,
+ "dongle trap info: type 0x%x @ epc 0x%08x\n"
+ " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+ " lr 0x%08x pc 0x%08x offset 0x%x\n"
+ " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
+ " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
+ le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+ le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+ le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+ le32_to_cpu(tr.pc), sh->trap_addr,
+ le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+ le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+ le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+ le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+
+ return 0;
}
-static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
- struct sdpcm_shared *sh, char __user *data,
- size_t count)
+static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus,
+ struct sdpcm_shared *sh)
{
int error = 0;
- char buf[200];
char file[80] = "?";
char expr[80] = "<???>";
- int res;
- loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
brcmf_dbg(INFO, "firmware not built with -assert\n");
@@ -3035,10 +3070,9 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
}
sdio_release_host(bus->sdiodev->func[1]);
- res = scnprintf(buf, sizeof(buf),
- "dongle assert: %s:%d: assert(%s)\n",
- file, sh->assert_line, expr);
- return simple_read_from_buffer(data, count, &pos, buf, res);
+ seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
+ file, sh->assert_line, expr);
+ return 0;
}
static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
@@ -3062,59 +3096,75 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
return 0;
}
-static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data,
- size_t count, loff_t *ppos)
+static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus)
{
int error = 0;
struct sdpcm_shared sh;
- int nbytes = 0;
- loff_t pos = *ppos;
-
- if (pos != 0)
- return 0;
error = brcmf_sdio_readshared(bus, &sh);
if (error < 0)
goto done;
- error = brcmf_sdio_assert_info(bus, &sh, data, count);
+ error = brcmf_sdio_assert_info(seq, bus, &sh);
if (error < 0)
goto done;
- nbytes = error;
- error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
+ error = brcmf_sdio_trap_info(seq, bus, &sh);
if (error < 0)
goto done;
- nbytes += error;
- error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
- if (error < 0)
- goto done;
- nbytes += error;
+ error = brcmf_sdio_dump_console(seq, bus, &sh);
- error = nbytes;
- *ppos += nbytes;
done:
return error;
}
-static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
- size_t count, loff_t *ppos)
+static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data)
{
- struct brcmf_sdio *bus = f->private_data;
- int res;
+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+ struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus;
- res = brcmf_sdio_died_dump(bus, data, count, ppos);
- if (res > 0)
- *ppos += res;
- return (ssize_t)res;
+ return brcmf_sdio_died_dump(seq, bus);
}
-static const struct file_operations brcmf_sdio_forensic_ops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = brcmf_sdio_forensic_read
-};
+static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt;
+
+ seq_printf(seq,
+ "intrcount: %u\nlastintrs: %u\n"
+ "pollcnt: %u\nregfails: %u\n"
+ "tx_sderrs: %u\nfcqueued: %u\n"
+ "rxrtx: %u\nrx_toolong: %u\n"
+ "rxc_errors: %u\nrx_hdrfail: %u\n"
+ "rx_badhdr: %u\nrx_badseq: %u\n"
+ "fc_rcvd: %u\nfc_xoff: %u\n"
+ "fc_xon: %u\nrxglomfail: %u\n"
+ "rxglomframes: %u\nrxglompkts: %u\n"
+ "f2rxhdrs: %u\nf2rxdata: %u\n"
+ "f2txdata: %u\nf1regdata: %u\n"
+ "tickcnt: %u\ntx_ctlerrs: %lu\n"
+ "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
+ "rx_ctlpkts: %lu\nrx_readahead: %lu\n",
+ sdcnt->intrcount, sdcnt->lastintrs,
+ sdcnt->pollcnt, sdcnt->regfails,
+ sdcnt->tx_sderrs, sdcnt->fcqueued,
+ sdcnt->rxrtx, sdcnt->rx_toolong,
+ sdcnt->rxc_errors, sdcnt->rx_hdrfail,
+ sdcnt->rx_badhdr, sdcnt->rx_badseq,
+ sdcnt->fc_rcvd, sdcnt->fc_xoff,
+ sdcnt->fc_xon, sdcnt->rxglomfail,
+ sdcnt->rxglomframes, sdcnt->rxglompkts,
+ sdcnt->f2rxhdrs, sdcnt->f2rxdata,
+ sdcnt->f2txdata, sdcnt->f1regdata,
+ sdcnt->tickcnt, sdcnt->tx_ctlerrs,
+ sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
+ sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
+
+ return 0;
+}
static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
{
@@ -3124,9 +3174,9 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
if (IS_ERR_OR_NULL(dentry))
return;
- debugfs_create_file("forensics", S_IRUGO, dentry, bus,
- &brcmf_sdio_forensic_ops);
- brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
+ brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
+ brcmf_debugfs_add_entry(drvr, "counters",
+ brcmf_debugfs_sdio_count_read);
debugfs_create_u32("console_interval", 0644, dentry,
&bus->console_interval);
}
@@ -3598,17 +3648,17 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
- case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
+ case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12):
str_tab = sdiod_drvstr_tab1_1v8;
str_mask = 0x00003800;
str_shift = 11;
break;
- case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
+ case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17):
str_tab = sdiod_drvstr_tab6_1v8;
str_mask = 0x00001800;
str_shift = 11;
break;
- case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+ case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17):
/* note: 43143 does not support tristate */
i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
@@ -3619,7 +3669,7 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
ci->name, drivestrength);
break;
- case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
+ case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13):
str_tab = sdiod_drive_strength_tab5_1v8;
str_mask = 0x00003800;
str_shift = 11;
@@ -3720,12 +3770,12 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
u32 val, rev;
val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
- if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
+ if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID &&
addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
if (rev >= 2) {
val &= ~CID_ID_MASK;
- val |= BCM4339_CHIP_ID;
+ val |= BRCM_CC_4339_CHIP_ID;
}
}
return val;
@@ -4127,11 +4177,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n");
+ ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev);
+ if (ret)
+ goto fail;
+
ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
- brcmf_sdio_get_fwname(bus->ci,
- BRCMF_FIRMWARE_BIN),
- brcmf_sdio_get_fwname(bus->ci,
- BRCMF_FIRMWARE_NVRAM),
+ sdiodev->fw_name, sdiodev->nvram_name,
brcmf_sdio_firmware_callback);
if (ret != 0) {
brcmf_err("async firmware request failed: %d\n", ret);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
new file mode 100644
index 000000000000..50877e3c5d2f
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+
+#include <brcm_hw_ids.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+#include "feature.h"
+
+/*
+ * firmware error code received if iovar is unsupported.
+ */
+#define EBRCMF_FEAT_UNSUPPORTED 23
+
+/*
+ * expand feature list to array of feature strings.
+ */
+#define BRCMF_FEAT_DEF(_f) \
+ #_f,
+static const char *brcmf_feat_names[] = {
+ BRCMF_FEAT_LIST
+};
+#undef BRCMF_FEAT_DEF
+
+#ifdef DEBUG
+/*
+ * expand quirk list to array of quirk strings.
+ */
+#define BRCMF_QUIRK_DEF(_q) \
+ #_q,
+static const char * const brcmf_quirk_names[] = {
+ BRCMF_QUIRK_LIST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_debugfs_read() - expose feature info to debugfs.
+ *
+ * @seq: sequence for debugfs entry.
+ * @data: raw data pointer.
+ */
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+ u32 feats = bus_if->drvr->feat_flags;
+ u32 quirks = bus_if->drvr->chip_quirks;
+ int id;
+
+ seq_printf(seq, "Features: %08x\n", feats);
+ for (id = 0; id < BRCMF_FEAT_LAST; id++)
+ if (feats & BIT(id))
+ seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
+ seq_printf(seq, "\nQuirks: %08x\n", quirks);
+ for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
+ if (quirks & BIT(id))
+ seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
+ return 0;
+}
+#else
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+ return 0;
+}
+#endif /* DEBUG */
+
+/**
+ * brcmf_feat_iovar_int_get() - determine feature through iovar query.
+ *
+ * @ifp: interface to query.
+ * @id: feature id.
+ * @name: iovar name.
+ */
+static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
+ enum brcmf_feat_id id, char *name)
+{
+ u32 data;
+ int err;
+
+ err = brcmf_fil_iovar_int_get(ifp, name, &data);
+ if (err == 0) {
+ brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+ ifp->drvr->feat_flags |= BIT(id);
+ } else {
+ brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+ brcmf_feat_names[id], err);
+ }
+}
+
+void brcmf_feat_attach(struct brcmf_pub *drvr)
+{
+ struct brcmf_if *ifp = drvr->iflist[0];
+
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
+
+ /* set chip related quirks */
+ switch (drvr->bus_if->chip) {
+ case BRCM_CC_43236_CHIP_ID:
+ drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
+ break;
+ case BRCM_CC_4329_CHIP_ID:
+ drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
+ break;
+ default:
+ /* no quirks */
+ break;
+ }
+
+ brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
+}
+
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
+{
+ return (ifp->drvr->feat_flags & BIT(id));
+}
+
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+ enum brcmf_feat_quirk quirk)
+{
+ return (ifp->drvr->chip_quirks & BIT(quirk));
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
new file mode 100644
index 000000000000..961d175f8afb
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMF_FEATURE_H
+#define _BRCMF_FEATURE_H
+
+/*
+ * Features:
+ *
+ * MCHAN: multi-channel for concurrent P2P.
+ */
+#define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MCHAN)
+/*
+ * Quirks:
+ *
+ * AUTO_AUTH: workaround needed for automatic authentication type.
+ * NEED_MPC: driver needs to disable MPC during scanning operation.
+ */
+#define BRCMF_QUIRK_LIST \
+ BRCMF_QUIRK_DEF(AUTO_AUTH) \
+ BRCMF_QUIRK_DEF(NEED_MPC)
+
+#define BRCMF_FEAT_DEF(_f) \
+ BRCMF_FEAT_ ## _f,
+/*
+ * expand feature list to enumeration.
+ */
+enum brcmf_feat_id {
+ BRCMF_FEAT_LIST
+ BRCMF_FEAT_LAST
+};
+#undef BRCMF_FEAT_DEF
+
+#define BRCMF_QUIRK_DEF(_q) \
+ BRCMF_FEAT_QUIRK_ ## _q,
+/*
+ * expand quirk list to enumeration.
+ */
+enum brcmf_feat_quirk {
+ BRCMF_QUIRK_LIST
+ BRCMF_FEAT_QUIRK_LAST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_attach() - determine features and quirks.
+ *
+ * @drvr: driver instance.
+ */
+void brcmf_feat_attach(struct brcmf_pub *drvr);
+
+/**
+ * brcmf_feat_is_enabled() - query feature.
+ *
+ * @ifp: interface instance.
+ * @id: feature id to check.
+ *
+ * Return: true is feature is enabled; otherwise false.
+ */
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
+
+/**
+ * brcmf_feat_is_quirk_enabled() - query chip quirk.
+ *
+ * @ifp: interface instance.
+ * @quirk: quirk id to check.
+ *
+ * Return: true is quirk is enabled; otherwise false.
+ */
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+ enum brcmf_feat_quirk quirk);
+
+#endif /* _BRCMF_FEATURE_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 7b7d237c1ddb..8ea9f283d2b8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -18,10 +18,15 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/module.h>
#include "dhd_dbg.h"
#include "firmware.h"
+char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
+module_param_string(firmware_path, brcmf_firmware_path,
+ BRCMF_FW_PATH_LEN, 0440);
+
enum nvram_parser_state {
IDLE,
KEY,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
index 6431bfd7afff..4d3482356b77 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
@@ -21,6 +21,11 @@
#define BRCMF_FW_REQ_FLAGS 0x00F0
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
+#define BRCMF_FW_PATH_LEN 256
+#define BRCMF_FW_NAME_LEN 32
+
+extern char brcmf_firmware_path[];
+
void brcmf_fw_nvram_free(void *nvram);
/*
* Request firmware(s) asynchronously. When the asynchronous request
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
new file mode 100644
index 000000000000..a1016b811284
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
@@ -0,0 +1,501 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <brcmu_utils.h>
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
+#include "proto.h"
+#include "flowring.h"
+#include "msgbuf.h"
+
+
+#define BRCMF_FLOWRING_HIGH 1024
+#define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256)
+#define BRCMF_FLOWRING_INVALID_IFIDX 0xff
+
+#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
+#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
+
+static const u8 ALLZEROMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static const u8 brcmf_flowring_prio2fifo[] = {
+ 1,
+ 0,
+ 0,
+ 1,
+ 2,
+ 2,
+ 3,
+ 3
+};
+
+
+static bool
+brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
+{
+ struct brcmf_flowring_tdls_entry *search;
+
+ search = flow->tdls_entry;
+
+ while (search) {
+ if (memcmp(search->mac, mac, ETH_ALEN) == 0)
+ return true;
+ search = search->next;
+ }
+
+ return false;
+}
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+ u8 prio, u8 ifidx)
+{
+ struct brcmf_flowring_hash *hash;
+ u8 hash_idx;
+ u32 i;
+ bool found;
+ bool sta;
+ u8 fifo;
+ u8 *mac;
+
+ fifo = brcmf_flowring_prio2fifo[prio];
+ sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+ mac = da;
+ if ((!sta) && (is_multicast_ether_addr(da))) {
+ mac = (u8 *)ALLFFMAC;
+ fifo = 0;
+ }
+ if ((sta) && (flow->tdls_active) &&
+ (brcmf_flowring_is_tdls_mac(flow, da))) {
+ sta = false;
+ }
+ hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+ BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+ found = false;
+ hash = flow->hash;
+ for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+ if ((sta || (memcmp(hash[hash_idx].mac, mac, ETH_ALEN) == 0)) &&
+ (hash[hash_idx].fifo == fifo) &&
+ (hash[hash_idx].ifidx == ifidx)) {
+ found = true;
+ break;
+ }
+ hash_idx++;
+ }
+ if (found)
+ return hash[hash_idx].flowid;
+
+ return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+ u8 prio, u8 ifidx)
+{
+ struct brcmf_flowring_ring *ring;
+ struct brcmf_flowring_hash *hash;
+ u8 hash_idx;
+ u32 i;
+ bool found;
+ u8 fifo;
+ bool sta;
+ u8 *mac;
+
+ fifo = brcmf_flowring_prio2fifo[prio];
+ sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+ mac = da;
+ if ((!sta) && (is_multicast_ether_addr(da))) {
+ mac = (u8 *)ALLFFMAC;
+ fifo = 0;
+ }
+ if ((sta) && (flow->tdls_active) &&
+ (brcmf_flowring_is_tdls_mac(flow, da))) {
+ sta = false;
+ }
+ hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+ BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+ found = false;
+ hash = flow->hash;
+ for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+ if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
+ (memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
+ found = true;
+ break;
+ }
+ hash_idx++;
+ }
+ if (found) {
+ for (i = 0; i < flow->nrofrings; i++) {
+ if (flow->rings[i] == NULL)
+ break;
+ }
+ if (i == flow->nrofrings)
+ return -ENOMEM;
+
+ ring = kzalloc(sizeof(*ring), GFP_ATOMIC);
+ if (!ring)
+ return -ENOMEM;
+
+ memcpy(hash[hash_idx].mac, mac, ETH_ALEN);
+ hash[hash_idx].fifo = fifo;
+ hash[hash_idx].ifidx = ifidx;
+ hash[hash_idx].flowid = i;
+
+ ring->hash_id = hash_idx;
+ ring->status = RING_CLOSED;
+ skb_queue_head_init(&ring->skblist);
+ flow->rings[i] = ring;
+
+ return i;
+ }
+ return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+
+ ring = flow->rings[flowid];
+
+ return flow->hash[ring->hash_id].fifo;
+}
+
+
+static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid,
+ bool blocked)
+{
+ struct brcmf_flowring_ring *ring;
+ struct brcmf_bus *bus_if;
+ struct brcmf_pub *drvr;
+ struct brcmf_if *ifp;
+ bool currently_blocked;
+ int i;
+ u8 ifidx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&flow->block_lock, flags);
+
+ ring = flow->rings[flowid];
+ ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+
+ currently_blocked = false;
+ for (i = 0; i < flow->nrofrings; i++) {
+ if (flow->rings[i]) {
+ ring = flow->rings[i];
+ if ((ring->status == RING_OPEN) &&
+ (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
+ if (ring->blocked) {
+ currently_blocked = true;
+ break;
+ }
+ }
+ }
+ }
+ ring->blocked = blocked;
+ if (currently_blocked == blocked) {
+ spin_unlock_irqrestore(&flow->block_lock, flags);
+ return;
+ }
+
+ bus_if = dev_get_drvdata(flow->dev);
+ drvr = bus_if->drvr;
+ ifp = drvr->iflist[ifidx];
+ brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
+
+ spin_unlock_irqrestore(&flow->block_lock, flags);
+}
+
+
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+ u8 hash_idx;
+ struct sk_buff *skb;
+
+ ring = flow->rings[flowid];
+ if (!ring)
+ return;
+ brcmf_flowring_block(flow, flowid, false);
+ hash_idx = ring->hash_id;
+ flow->hash[hash_idx].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+ memset(flow->hash[hash_idx].mac, 0, ETH_ALEN);
+ flow->rings[flowid] = NULL;
+
+ skb = skb_dequeue(&ring->skblist);
+ while (skb) {
+ brcmu_pkt_buf_free_skb(skb);
+ skb = skb_dequeue(&ring->skblist);
+ }
+
+ kfree(ring);
+}
+
+
+void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+ struct sk_buff *skb)
+{
+ struct brcmf_flowring_ring *ring;
+
+ ring = flow->rings[flowid];
+
+ skb_queue_tail(&ring->skblist, skb);
+
+ if (!ring->blocked &&
+ (skb_queue_len(&ring->skblist) > BRCMF_FLOWRING_HIGH)) {
+ brcmf_flowring_block(flow, flowid, true);
+ brcmf_dbg(MSGBUF, "Flowcontrol: BLOCK for ring %d\n", flowid);
+ /* To prevent (work around) possible race condition, check
+ * queue len again. It is also possible to use locking to
+ * protect, but that is undesirable for every enqueue and
+ * dequeue. This simple check will solve a possible race
+ * condition if it occurs.
+ */
+ if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
+ brcmf_flowring_block(flow, flowid, false);
+ }
+}
+
+
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+ struct sk_buff *skb;
+
+ ring = flow->rings[flowid];
+ if (ring->status != RING_OPEN)
+ return NULL;
+
+ skb = skb_dequeue(&ring->skblist);
+
+ if (ring->blocked &&
+ (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)) {
+ brcmf_flowring_block(flow, flowid, false);
+ brcmf_dbg(MSGBUF, "Flowcontrol: OPEN for ring %d\n", flowid);
+ }
+
+ return skb;
+}
+
+
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
+ struct sk_buff *skb)
+{
+ struct brcmf_flowring_ring *ring;
+
+ ring = flow->rings[flowid];
+
+ skb_queue_head(&ring->skblist, skb);
+}
+
+
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+
+ ring = flow->rings[flowid];
+ if (!ring)
+ return 0;
+
+ if (ring->status != RING_OPEN)
+ return 0;
+
+ return skb_queue_len(&ring->skblist);
+}
+
+
+void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+
+ ring = flow->rings[flowid];
+ if (!ring) {
+ brcmf_err("Ring NULL, for flowid %d\n", flowid);
+ return;
+ }
+
+ ring->status = RING_OPEN;
+}
+
+
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid)
+{
+ struct brcmf_flowring_ring *ring;
+ u8 hash_idx;
+
+ ring = flow->rings[flowid];
+ hash_idx = ring->hash_id;
+
+ return flow->hash[hash_idx].ifidx;
+}
+
+
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)
+{
+ struct brcmf_flowring *flow;
+ u32 i;
+
+ flow = kzalloc(sizeof(*flow), GFP_ATOMIC);
+ if (flow) {
+ flow->dev = dev;
+ flow->nrofrings = nrofrings;
+ spin_lock_init(&flow->block_lock);
+ for (i = 0; i < ARRAY_SIZE(flow->addr_mode); i++)
+ flow->addr_mode[i] = ADDR_INDIRECT;
+ for (i = 0; i < ARRAY_SIZE(flow->hash); i++)
+ flow->hash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+ flow->rings = kcalloc(nrofrings, sizeof(*flow->rings),
+ GFP_ATOMIC);
+ if (!flow->rings) {
+ kfree(flow);
+ flow = NULL;
+ }
+ }
+
+ return flow;
+}
+
+
+void brcmf_flowring_detach(struct brcmf_flowring *flow)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_flowring_tdls_entry *search;
+ struct brcmf_flowring_tdls_entry *remove;
+ u8 flowid;
+
+ for (flowid = 0; flowid < flow->nrofrings; flowid++) {
+ if (flow->rings[flowid])
+ brcmf_msgbuf_delete_flowring(drvr, flowid);
+ }
+
+ search = flow->tdls_entry;
+ while (search) {
+ remove = search;
+ search = search->next;
+ kfree(remove);
+ }
+ kfree(flow->rings);
+ kfree(flow);
+}
+
+
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+ enum proto_addr_mode addr_mode)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ u32 i;
+ u8 flowid;
+
+ if (flow->addr_mode[ifidx] != addr_mode) {
+ for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
+ if (flow->hash[i].ifidx == ifidx) {
+ flowid = flow->hash[i].flowid;
+ if (flow->rings[flowid]->status != RING_OPEN)
+ continue;
+ flow->rings[flowid]->status = RING_CLOSING;
+ brcmf_msgbuf_delete_flowring(drvr, flowid);
+ }
+ }
+ flow->addr_mode[ifidx] = addr_mode;
+ }
+}
+
+
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+ u8 peer[ETH_ALEN])
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_flowring_hash *hash;
+ struct brcmf_flowring_tdls_entry *prev;
+ struct brcmf_flowring_tdls_entry *search;
+ u32 i;
+ u8 flowid;
+ bool sta;
+
+ sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+
+ search = flow->tdls_entry;
+ prev = NULL;
+ while (search) {
+ if (memcmp(search->mac, peer, ETH_ALEN) == 0) {
+ sta = false;
+ break;
+ }
+ prev = search;
+ search = search->next;
+ }
+
+ hash = flow->hash;
+ for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+ if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
+ (hash[i].ifidx == ifidx)) {
+ flowid = flow->hash[i].flowid;
+ if (flow->rings[flowid]->status == RING_OPEN) {
+ flow->rings[flowid]->status = RING_CLOSING;
+ brcmf_msgbuf_delete_flowring(drvr, flowid);
+ }
+ }
+ }
+
+ if (search) {
+ if (prev)
+ prev->next = search->next;
+ else
+ flow->tdls_entry = search->next;
+ kfree(search);
+ if (flow->tdls_entry == NULL)
+ flow->tdls_active = false;
+ }
+}
+
+
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+ u8 peer[ETH_ALEN])
+{
+ struct brcmf_flowring_tdls_entry *tdls_entry;
+ struct brcmf_flowring_tdls_entry *search;
+
+ tdls_entry = kzalloc(sizeof(*tdls_entry), GFP_ATOMIC);
+ if (tdls_entry == NULL)
+ return;
+
+ memcpy(tdls_entry->mac, peer, ETH_ALEN);
+ tdls_entry->next = NULL;
+ if (flow->tdls_entry == NULL) {
+ flow->tdls_entry = tdls_entry;
+ } else {
+ search = flow->tdls_entry;
+ if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+ return;
+ while (search->next) {
+ search = search->next;
+ if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+ return;
+ }
+ search->next = tdls_entry;
+ }
+
+ flow->tdls_active = true;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
new file mode 100644
index 000000000000..a34cd394c616
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_FLOWRING_H
+#define BRCMFMAC_FLOWRING_H
+
+
+#define BRCMF_FLOWRING_HASHSIZE 256
+#define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
+
+
+struct brcmf_flowring_hash {
+ u8 mac[ETH_ALEN];
+ u8 fifo;
+ u8 ifidx;
+ u8 flowid;
+};
+
+enum ring_status {
+ RING_CLOSED,
+ RING_CLOSING,
+ RING_OPEN
+};
+
+struct brcmf_flowring_ring {
+ u8 hash_id;
+ bool blocked;
+ enum ring_status status;
+ struct sk_buff_head skblist;
+};
+
+struct brcmf_flowring_tdls_entry {
+ u8 mac[ETH_ALEN];
+ struct brcmf_flowring_tdls_entry *next;
+};
+
+struct brcmf_flowring {
+ struct device *dev;
+ struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
+ struct brcmf_flowring_ring **rings;
+ spinlock_t block_lock;
+ enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
+ u16 nrofrings;
+ bool tdls_active;
+ struct brcmf_flowring_tdls_entry *tdls_entry;
+};
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+ u8 prio, u8 ifidx);
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+ u8 prio, u8 ifidx);
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid);
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
+ struct sk_buff *skb);
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid);
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid,
+ struct sk_buff *skb);
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid);
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid);
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
+void brcmf_flowring_detach(struct brcmf_flowring *flow);
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+ enum proto_addr_mode addr_mode);
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+ u8 peer[ETH_ALEN]);
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+ u8 peer[ETH_ALEN]);
+
+
+#endif /* BRCMFMAC_FLOWRING_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index fad77dd2a3a5..4f1daabc551b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -293,7 +293,11 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
goto event_free;
}
- ifp = drvr->iflist[emsg.bsscfgidx];
+ if ((event->code == BRCMF_E_TDLS_PEER_EVENT) &&
+ (emsg.bsscfgidx == 1))
+ ifp = drvr->iflist[0];
+ else
+ ifp = drvr->iflist[emsg.bsscfgidx];
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
event->data);
if (err) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
index 51b53a73d074..dd20b1862d44 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
@@ -102,6 +102,7 @@ struct brcmf_event;
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
+ BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \
BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128)
@@ -155,6 +156,10 @@ enum brcmf_fweh_event_code {
#define BRCMF_E_REASON_TSPEC_REJECTED 7
#define BRCMF_E_REASON_BETTER_AP 8
+#define BRCMF_E_REASON_TDLS_PEER_DISCOVERED 0
+#define BRCMF_E_REASON_TDLS_PEER_CONNECTED 1
+#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED 2
+
/* action field values for brcmf_ifevent */
#define BRCMF_E_IF_ADD 1
#define BRCMF_E_IF_DEL 2
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
index 59a5af5bf994..ded328f80cd1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -54,7 +54,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
if (err >= 0)
err = 0;
else
- brcmf_err("Failed err=%d\n", err);
+ brcmf_dbg(FIL, "Failed err=%d\n", err);
return err;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 699908de314a..d42f7d04b65f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table {
struct brcmf_fws_mac_descriptor other;
};
+struct brcmf_fws_stats {
+ u32 tlv_parse_failed;
+ u32 tlv_invalid_type;
+ u32 header_only_pkt;
+ u32 header_pulls;
+ u32 pkt2bus;
+ u32 send_pkts[5];
+ u32 requested_sent[5];
+ u32 generic_error;
+ u32 mac_update_failed;
+ u32 mac_ps_update_failed;
+ u32 if_update_failed;
+ u32 packet_request_failed;
+ u32 credit_request_failed;
+ u32 rollback_success;
+ u32 rollback_failed;
+ u32 delayq_full_error;
+ u32 supprq_full_error;
+ u32 txs_indicate;
+ u32 txs_discard;
+ u32 txs_supp_core;
+ u32 txs_supp_ps;
+ u32 txs_tossed;
+ u32 txs_host_tossed;
+ u32 bus_flow_block;
+ u32 fws_flow_block;
+};
+
struct brcmf_fws_info {
struct brcmf_pub *drvr;
spinlock_t spinlock;
@@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
brcmf_fws_unlock(fws);
}
+#ifdef DEBUG
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+ struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats;
+
+ seq_printf(seq,
+ "header_pulls: %u\n"
+ "header_only_pkt: %u\n"
+ "tlv_parse_failed: %u\n"
+ "tlv_invalid_type: %u\n"
+ "mac_update_fails: %u\n"
+ "ps_update_fails: %u\n"
+ "if_update_fails: %u\n"
+ "pkt2bus: %u\n"
+ "generic_error: %u\n"
+ "rollback_success: %u\n"
+ "rollback_failed: %u\n"
+ "delayq_full: %u\n"
+ "supprq_full: %u\n"
+ "txs_indicate: %u\n"
+ "txs_discard: %u\n"
+ "txs_suppr_core: %u\n"
+ "txs_suppr_ps: %u\n"
+ "txs_tossed: %u\n"
+ "txs_host_tossed: %u\n"
+ "bus_flow_block: %u\n"
+ "fws_flow_block: %u\n"
+ "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
+ "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
+ fwstats->header_pulls,
+ fwstats->header_only_pkt,
+ fwstats->tlv_parse_failed,
+ fwstats->tlv_invalid_type,
+ fwstats->mac_update_failed,
+ fwstats->mac_ps_update_failed,
+ fwstats->if_update_failed,
+ fwstats->pkt2bus,
+ fwstats->generic_error,
+ fwstats->rollback_success,
+ fwstats->rollback_failed,
+ fwstats->delayq_full_error,
+ fwstats->supprq_full_error,
+ fwstats->txs_indicate,
+ fwstats->txs_discard,
+ fwstats->txs_supp_core,
+ fwstats->txs_supp_ps,
+ fwstats->txs_tossed,
+ fwstats->txs_host_tossed,
+ fwstats->bus_flow_block,
+ fwstats->fws_flow_block,
+ fwstats->send_pkts[0], fwstats->send_pkts[1],
+ fwstats->send_pkts[2], fwstats->send_pkts[3],
+ fwstats->send_pkts[4],
+ fwstats->requested_sent[0],
+ fwstats->requested_sent[1],
+ fwstats->requested_sent[2],
+ fwstats->requested_sent[3],
+ fwstats->requested_sent[4]);
+
+ return 0;
+}
+#else
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+ return 0;
+}
+#endif
+
int brcmf_fws_init(struct brcmf_pub *drvr)
{
struct brcmf_fws_info *fws;
@@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
BRCMF_FWS_PSQ_LEN);
/* create debugfs file for statistics */
- brcmf_debugfs_create_fws_stats(drvr, &fws->stats);
+ brcmf_debugfs_add_entry(drvr, "fws_stats",
+ brcmf_debugfs_fws_stats_read);
brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
fws->fw_signals ? "enabled" : "disabled", tlv);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
new file mode 100644
index 000000000000..8f8b9373de95
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -0,0 +1,1401 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "proto.h"
+#include "msgbuf.h"
+#include "commonring.h"
+#include "flowring.h"
+#include "dhd_bus.h"
+#include "tracepoint.h"
+
+
+#define MSGBUF_IOCTL_RESP_TIMEOUT 2000
+
+#define MSGBUF_TYPE_GEN_STATUS 0x1
+#define MSGBUF_TYPE_RING_STATUS 0x2
+#define MSGBUF_TYPE_FLOW_RING_CREATE 0x3
+#define MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT 0x4
+#define MSGBUF_TYPE_FLOW_RING_DELETE 0x5
+#define MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT 0x6
+#define MSGBUF_TYPE_FLOW_RING_FLUSH 0x7
+#define MSGBUF_TYPE_FLOW_RING_FLUSH_CMPLT 0x8
+#define MSGBUF_TYPE_IOCTLPTR_REQ 0x9
+#define MSGBUF_TYPE_IOCTLPTR_REQ_ACK 0xA
+#define MSGBUF_TYPE_IOCTLRESP_BUF_POST 0xB
+#define MSGBUF_TYPE_IOCTL_CMPLT 0xC
+#define MSGBUF_TYPE_EVENT_BUF_POST 0xD
+#define MSGBUF_TYPE_WL_EVENT 0xE
+#define MSGBUF_TYPE_TX_POST 0xF
+#define MSGBUF_TYPE_TX_STATUS 0x10
+#define MSGBUF_TYPE_RXBUF_POST 0x11
+#define MSGBUF_TYPE_RX_CMPLT 0x12
+#define MSGBUF_TYPE_LPBK_DMAXFER 0x13
+#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT 0x14
+
+#define NR_TX_PKTIDS 2048
+#define NR_RX_PKTIDS 1024
+
+#define BRCMF_IOCTL_REQ_PKTID 0xFFFE
+
+#define BRCMF_MSGBUF_MAX_PKT_SIZE 2048
+#define BRCMF_MSGBUF_RXBUFPOST_THRESHOLD 32
+#define BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST 8
+#define BRCMF_MSGBUF_MAX_EVENTBUF_POST 8
+
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3 0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
+
+#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
+#define BRCMF_MSGBUF_TX_FLUSH_CNT2 96
+
+
+struct msgbuf_common_hdr {
+ u8 msgtype;
+ u8 ifidx;
+ u8 flags;
+ u8 rsvd0;
+ __le32 request_id;
+};
+
+struct msgbuf_buf_addr {
+ __le32 low_addr;
+ __le32 high_addr;
+};
+
+struct msgbuf_ioctl_req_hdr {
+ struct msgbuf_common_hdr msg;
+ __le32 cmd;
+ __le16 trans_id;
+ __le16 input_buf_len;
+ __le16 output_buf_len;
+ __le16 rsvd0[3];
+ struct msgbuf_buf_addr req_buf_addr;
+ __le32 rsvd1[2];
+};
+
+struct msgbuf_tx_msghdr {
+ struct msgbuf_common_hdr msg;
+ u8 txhdr[ETH_HLEN];
+ u8 flags;
+ u8 seg_cnt;
+ struct msgbuf_buf_addr metadata_buf_addr;
+ struct msgbuf_buf_addr data_buf_addr;
+ __le16 metadata_buf_len;
+ __le16 data_len;
+ __le32 rsvd0;
+};
+
+struct msgbuf_rx_bufpost {
+ struct msgbuf_common_hdr msg;
+ __le16 metadata_buf_len;
+ __le16 data_buf_len;
+ __le32 rsvd0;
+ struct msgbuf_buf_addr metadata_buf_addr;
+ struct msgbuf_buf_addr data_buf_addr;
+};
+
+struct msgbuf_rx_ioctl_resp_or_event {
+ struct msgbuf_common_hdr msg;
+ __le16 host_buf_len;
+ __le16 rsvd0[3];
+ struct msgbuf_buf_addr host_buf_addr;
+ __le32 rsvd1[4];
+};
+
+struct msgbuf_completion_hdr {
+ __le16 status;
+ __le16 flow_ring_id;
+};
+
+struct msgbuf_rx_event {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 event_data_len;
+ __le16 seqnum;
+ __le16 rsvd0[4];
+};
+
+struct msgbuf_ioctl_resp_hdr {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 resp_len;
+ __le16 trans_id;
+ __le32 cmd;
+ __le32 rsvd0;
+};
+
+struct msgbuf_tx_status {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 metadata_len;
+ __le16 tx_status;
+};
+
+struct msgbuf_rx_complete {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le16 metadata_len;
+ __le16 data_len;
+ __le16 data_offset;
+ __le16 flags;
+ __le32 rx_status_0;
+ __le32 rx_status_1;
+ __le32 rsvd0;
+};
+
+struct msgbuf_tx_flowring_create_req {
+ struct msgbuf_common_hdr msg;
+ u8 da[ETH_ALEN];
+ u8 sa[ETH_ALEN];
+ u8 tid;
+ u8 if_flags;
+ __le16 flow_ring_id;
+ u8 tc;
+ u8 priority;
+ __le16 int_vector;
+ __le16 max_items;
+ __le16 len_item;
+ struct msgbuf_buf_addr flow_ring_addr;
+};
+
+struct msgbuf_tx_flowring_delete_req {
+ struct msgbuf_common_hdr msg;
+ __le16 flow_ring_id;
+ __le16 reason;
+ __le32 rsvd0[7];
+};
+
+struct msgbuf_flowring_create_resp {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le32 rsvd0[3];
+};
+
+struct msgbuf_flowring_delete_resp {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le32 rsvd0[3];
+};
+
+struct msgbuf_flowring_flush_resp {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le32 rsvd0[3];
+};
+
+struct brcmf_msgbuf {
+ struct brcmf_pub *drvr;
+
+ struct brcmf_commonring **commonrings;
+ struct brcmf_commonring **flowrings;
+ dma_addr_t *flowring_dma_handle;
+ u16 nrof_flowrings;
+
+ u16 rx_dataoffset;
+ u32 max_rxbufpost;
+ u16 rx_metadata_offset;
+ u32 rxbufpost;
+
+ u32 max_ioctlrespbuf;
+ u32 cur_ioctlrespbuf;
+ u32 max_eventbuf;
+ u32 cur_eventbuf;
+
+ void *ioctbuf;
+ dma_addr_t ioctbuf_handle;
+ u32 ioctbuf_phys_hi;
+ u32 ioctbuf_phys_lo;
+ u32 ioctl_resp_status;
+ u32 ioctl_resp_ret_len;
+ u32 ioctl_resp_pktid;
+
+ u16 data_seq_no;
+ u16 ioctl_seq_no;
+ u32 reqid;
+ wait_queue_head_t ioctl_resp_wait;
+ bool ctl_completed;
+
+ struct brcmf_msgbuf_pktids *tx_pktids;
+ struct brcmf_msgbuf_pktids *rx_pktids;
+ struct brcmf_flowring *flow;
+
+ struct workqueue_struct *txflow_wq;
+ struct work_struct txflow_work;
+ unsigned long *flow_map;
+ unsigned long *txstatus_done_map;
+};
+
+struct brcmf_msgbuf_pktid {
+ atomic_t allocated;
+ u16 data_offset;
+ struct sk_buff *skb;
+ dma_addr_t physaddr;
+};
+
+struct brcmf_msgbuf_pktids {
+ u32 array_size;
+ u32 last_allocated_idx;
+ enum dma_data_direction direction;
+ struct brcmf_msgbuf_pktid *array;
+};
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
+
+
+static struct brcmf_msgbuf_pktids *
+brcmf_msgbuf_init_pktids(u32 nr_array_entries,
+ enum dma_data_direction direction)
+{
+ struct brcmf_msgbuf_pktid *array;
+ struct brcmf_msgbuf_pktids *pktids;
+
+ array = kcalloc(nr_array_entries, sizeof(*array), GFP_ATOMIC);
+ if (!array)
+ return NULL;
+
+ pktids = kzalloc(sizeof(*pktids), GFP_ATOMIC);
+ if (!pktids) {
+ kfree(array);
+ return NULL;
+ }
+ pktids->array = array;
+ pktids->array_size = nr_array_entries;
+
+ return pktids;
+}
+
+
+static int
+brcmf_msgbuf_alloc_pktid(struct device *dev,
+ struct brcmf_msgbuf_pktids *pktids,
+ struct sk_buff *skb, u16 data_offset,
+ dma_addr_t *physaddr, u32 *idx)
+{
+ struct brcmf_msgbuf_pktid *array;
+ u32 count;
+
+ array = pktids->array;
+
+ *physaddr = dma_map_single(dev, skb->data + data_offset,
+ skb->len - data_offset, pktids->direction);
+
+ if (dma_mapping_error(dev, *physaddr)) {
+ brcmf_err("dma_map_single failed !!\n");
+ return -ENOMEM;
+ }
+
+ *idx = pktids->last_allocated_idx;
+
+ count = 0;
+ do {
+ (*idx)++;
+ if (*idx == pktids->array_size)
+ *idx = 0;
+ if (array[*idx].allocated.counter == 0)
+ if (atomic_cmpxchg(&array[*idx].allocated, 0, 1) == 0)
+ break;
+ count++;
+ } while (count < pktids->array_size);
+
+ if (count == pktids->array_size)
+ return -ENOMEM;
+
+ array[*idx].data_offset = data_offset;
+ array[*idx].physaddr = *physaddr;
+ array[*idx].skb = skb;
+
+ pktids->last_allocated_idx = *idx;
+
+ return 0;
+}
+
+
+static struct sk_buff *
+brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids,
+ u32 idx)
+{
+ struct brcmf_msgbuf_pktid *pktid;
+ struct sk_buff *skb;
+
+ if (idx >= pktids->array_size) {
+ brcmf_err("Invalid packet id %d (max %d)\n", idx,
+ pktids->array_size);
+ return NULL;
+ }
+ if (pktids->array[idx].allocated.counter) {
+ pktid = &pktids->array[idx];
+ dma_unmap_single(dev, pktid->physaddr,
+ pktid->skb->len - pktid->data_offset,
+ pktids->direction);
+ skb = pktid->skb;
+ pktid->allocated.counter = 0;
+ return skb;
+ } else {
+ brcmf_err("Invalid packet id %d (not in use)\n", idx);
+ }
+
+ return NULL;
+}
+
+
+static void
+brcmf_msgbuf_release_array(struct device *dev,
+ struct brcmf_msgbuf_pktids *pktids)
+{
+ struct brcmf_msgbuf_pktid *array;
+ struct brcmf_msgbuf_pktid *pktid;
+ u32 count;
+
+ array = pktids->array;
+ count = 0;
+ do {
+ if (array[count].allocated.counter) {
+ pktid = &array[count];
+ dma_unmap_single(dev, pktid->physaddr,
+ pktid->skb->len - pktid->data_offset,
+ pktids->direction);
+ brcmu_pkt_buf_free_skb(pktid->skb);
+ }
+ count++;
+ } while (count < pktids->array_size);
+
+ kfree(array);
+ kfree(pktids);
+}
+
+
+static void brcmf_msgbuf_release_pktids(struct brcmf_msgbuf *msgbuf)
+{
+ if (msgbuf->rx_pktids)
+ brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids);
+ if (msgbuf->tx_pktids)
+ brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+ msgbuf->tx_pktids);
+}
+
+
+static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
+ uint cmd, void *buf, uint len)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ struct brcmf_commonring *commonring;
+ struct msgbuf_ioctl_req_hdr *request;
+ u16 buf_len;
+ void *ret_ptr;
+ int err;
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+ brcmf_commonring_lock(commonring);
+ ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+ if (!ret_ptr) {
+ brcmf_err("Failed to reserve space in commonring\n");
+ brcmf_commonring_unlock(commonring);
+ return -ENOMEM;
+ }
+
+ msgbuf->reqid++;
+
+ request = (struct msgbuf_ioctl_req_hdr *)ret_ptr;
+ request->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;
+ request->msg.ifidx = (u8)ifidx;
+ request->msg.flags = 0;
+ request->msg.request_id = cpu_to_le32(BRCMF_IOCTL_REQ_PKTID);
+ request->cmd = cpu_to_le32(cmd);
+ request->output_buf_len = cpu_to_le16(len);
+ request->trans_id = cpu_to_le16(msgbuf->reqid);
+
+ buf_len = min_t(u16, len, BRCMF_TX_IOCTL_MAX_MSG_SIZE);
+ request->input_buf_len = cpu_to_le16(buf_len);
+ request->req_buf_addr.high_addr = cpu_to_le32(msgbuf->ioctbuf_phys_hi);
+ request->req_buf_addr.low_addr = cpu_to_le32(msgbuf->ioctbuf_phys_lo);
+ if (buf)
+ memcpy(msgbuf->ioctbuf, buf, buf_len);
+ else
+ memset(msgbuf->ioctbuf, 0, buf_len);
+ brcmf_dma_flush(ioctl_buf, buf_len);
+
+ err = brcmf_commonring_write_complete(commonring);
+ brcmf_commonring_unlock(commonring);
+
+ return err;
+}
+
+
+static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)
+{
+ return wait_event_timeout(msgbuf->ioctl_resp_wait,
+ msgbuf->ctl_completed,
+ msecs_to_jiffies(MSGBUF_IOCTL_RESP_TIMEOUT));
+}
+
+
+static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
+{
+ if (waitqueue_active(&msgbuf->ioctl_resp_wait)) {
+ msgbuf->ctl_completed = true;
+ wake_up(&msgbuf->ioctl_resp_wait);
+ }
+}
+
+
+static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+ uint cmd, void *buf, uint len)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ struct sk_buff *skb = NULL;
+ int timeout;
+ int err;
+
+ brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
+ msgbuf->ctl_completed = false;
+ err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
+ if (err)
+ return err;
+
+ timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf);
+ if (!timeout) {
+ brcmf_err("Timeout on response for query command\n");
+ return -EIO;
+ }
+
+ skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids,
+ msgbuf->ioctl_resp_pktid);
+ if (msgbuf->ioctl_resp_ret_len != 0) {
+ if (!skb) {
+ brcmf_err("Invalid packet id idx recv'd %d\n",
+ msgbuf->ioctl_resp_pktid);
+ return -EBADF;
+ }
+ memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
+ len : msgbuf->ioctl_resp_ret_len);
+ }
+ if (skb)
+ brcmu_pkt_buf_free_skb(skb);
+
+ return msgbuf->ioctl_resp_status;
+}
+
+
+static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
+ uint cmd, void *buf, uint len)
+{
+ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
+}
+
+
+static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+ u8 *ifidx, struct sk_buff *skb)
+{
+ return -ENODEV;
+}
+
+
+static void
+brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
+{
+ u32 dma_sz;
+ void *dma_buf;
+
+ brcmf_dbg(MSGBUF, "Removing flowring %d\n", flowid);
+
+ dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+ dma_buf = msgbuf->flowrings[flowid]->buf_addr;
+ dma_free_coherent(msgbuf->drvr->bus_if->dev, dma_sz, dma_buf,
+ msgbuf->flowring_dma_handle[flowid]);
+
+ brcmf_flowring_delete(msgbuf->flow, flowid);
+}
+
+
+static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx,
+ struct sk_buff *skb)
+{
+ struct msgbuf_tx_flowring_create_req *create;
+ struct ethhdr *eh = (struct ethhdr *)(skb->data);
+ struct brcmf_commonring *commonring;
+ void *ret_ptr;
+ u32 flowid;
+ void *dma_buf;
+ u32 dma_sz;
+ long long address;
+ int err;
+
+ flowid = brcmf_flowring_create(msgbuf->flow, eh->h_dest,
+ skb->priority, ifidx);
+ if (flowid == BRCMF_FLOWRING_INVALID_ID)
+ return flowid;
+
+ dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+
+ dma_buf = dma_alloc_coherent(msgbuf->drvr->bus_if->dev, dma_sz,
+ &msgbuf->flowring_dma_handle[flowid],
+ GFP_ATOMIC);
+ if (!dma_buf) {
+ brcmf_err("dma_alloc_coherent failed\n");
+ brcmf_flowring_delete(msgbuf->flow, flowid);
+ return BRCMF_FLOWRING_INVALID_ID;
+ }
+
+ brcmf_commonring_config(msgbuf->flowrings[flowid],
+ BRCMF_H2D_TXFLOWRING_MAX_ITEM,
+ BRCMF_H2D_TXFLOWRING_ITEMSIZE, dma_buf);
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+ brcmf_commonring_lock(commonring);
+ ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+ if (!ret_ptr) {
+ brcmf_err("Failed to reserve space in commonring\n");
+ brcmf_commonring_unlock(commonring);
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+ return BRCMF_FLOWRING_INVALID_ID;
+ }
+
+ create = (struct msgbuf_tx_flowring_create_req *)ret_ptr;
+ create->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;
+ create->msg.ifidx = ifidx;
+ create->msg.request_id = 0;
+ create->tid = brcmf_flowring_tid(msgbuf->flow, flowid);
+ create->flow_ring_id = cpu_to_le16(flowid +
+ BRCMF_NROF_H2D_COMMON_MSGRINGS);
+ memcpy(create->sa, eh->h_source, ETH_ALEN);
+ memcpy(create->da, eh->h_dest, ETH_ALEN);
+ address = (long long)(long)msgbuf->flowring_dma_handle[flowid];
+ create->flow_ring_addr.high_addr = cpu_to_le32(address >> 32);
+ create->flow_ring_addr.low_addr = cpu_to_le32(address & 0xffffffff);
+ create->max_items = cpu_to_le16(BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+ create->len_item = cpu_to_le16(BRCMF_H2D_TXFLOWRING_ITEMSIZE);
+
+ brcmf_dbg(MSGBUF, "Send Flow Create Req flow ID %d for peer %pM prio %d ifindex %d\n",
+ flowid, eh->h_dest, create->tid, ifidx);
+
+ err = brcmf_commonring_write_complete(commonring);
+ brcmf_commonring_unlock(commonring);
+ if (err) {
+ brcmf_err("Failed to write commonring\n");
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+ return BRCMF_FLOWRING_INVALID_ID;
+ }
+
+ return flowid;
+}
+
+
+static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
+{
+ struct brcmf_flowring *flow = msgbuf->flow;
+ struct brcmf_commonring *commonring;
+ void *ret_ptr;
+ u32 count;
+ struct sk_buff *skb;
+ dma_addr_t physaddr;
+ u32 pktid;
+ struct msgbuf_tx_msghdr *tx_msghdr;
+ long long address;
+
+ commonring = msgbuf->flowrings[flowid];
+ if (!brcmf_commonring_write_available(commonring))
+ return;
+
+ brcmf_commonring_lock(commonring);
+
+ count = BRCMF_MSGBUF_TX_FLUSH_CNT2 - BRCMF_MSGBUF_TX_FLUSH_CNT1;
+ while (brcmf_flowring_qlen(flow, flowid)) {
+ skb = brcmf_flowring_dequeue(flow, flowid);
+ if (skb == NULL) {
+ brcmf_err("No SKB, but qlen %d\n",
+ brcmf_flowring_qlen(flow, flowid));
+ break;
+ }
+ skb_orphan(skb);
+ if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->tx_pktids, skb, ETH_HLEN,
+ &physaddr, &pktid)) {
+ brcmf_flowring_reinsert(flow, flowid, skb);
+ brcmf_err("No PKTID available !!\n");
+ break;
+ }
+ ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+ if (!ret_ptr) {
+ brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->tx_pktids, pktid);
+ brcmf_flowring_reinsert(flow, flowid, skb);
+ break;
+ }
+ count++;
+
+ tx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr;
+
+ tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST;
+ tx_msghdr->msg.request_id = cpu_to_le32(pktid);
+ tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+ tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;
+ tx_msghdr->flags |= (skb->priority & 0x07) <<
+ BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
+ tx_msghdr->seg_cnt = 1;
+ memcpy(tx_msghdr->txhdr, skb->data, ETH_HLEN);
+ tx_msghdr->data_len = cpu_to_le16(skb->len - ETH_HLEN);
+ address = (long long)(long)physaddr;
+ tx_msghdr->data_buf_addr.high_addr = cpu_to_le32(address >> 32);
+ tx_msghdr->data_buf_addr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+ tx_msghdr->metadata_buf_len = 0;
+ tx_msghdr->metadata_buf_addr.high_addr = 0;
+ tx_msghdr->metadata_buf_addr.low_addr = 0;
+ if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) {
+ brcmf_commonring_write_complete(commonring);
+ count = 0;
+ }
+ }
+ if (count)
+ brcmf_commonring_write_complete(commonring);
+ brcmf_commonring_unlock(commonring);
+}
+
+
+static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)
+{
+ struct brcmf_msgbuf *msgbuf;
+ u32 flowid;
+
+ msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);
+ for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) {
+ clear_bit(flowid, msgbuf->flow_map);
+ brcmf_msgbuf_txflow(msgbuf, flowid);
+ }
+}
+
+
+static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid)
+{
+ set_bit(flowid, msgbuf->flow_map);
+ queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+
+ return 0;
+}
+
+
+static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
+ u8 offset, struct sk_buff *skb)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ struct brcmf_flowring *flow = msgbuf->flow;
+ struct ethhdr *eh = (struct ethhdr *)(skb->data);
+ u32 flowid;
+
+ flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
+ if (flowid == BRCMF_FLOWRING_INVALID_ID) {
+ flowid = brcmf_msgbuf_flowring_create(msgbuf, ifidx, skb);
+ if (flowid == BRCMF_FLOWRING_INVALID_ID)
+ return -ENOMEM;
+ }
+ brcmf_flowring_enqueue(flow, flowid, skb);
+ brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+
+ return 0;
+}
+
+
+static void
+brcmf_msgbuf_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+ enum proto_addr_mode addr_mode)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+ brcmf_flowring_configure_addr_mode(msgbuf->flow, ifidx, addr_mode);
+}
+
+
+static void
+brcmf_msgbuf_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+ brcmf_flowring_delete_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+ brcmf_flowring_add_tdls_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+ struct msgbuf_ioctl_resp_hdr *ioctl_resp;
+
+ ioctl_resp = (struct msgbuf_ioctl_resp_hdr *)buf;
+
+ msgbuf->ioctl_resp_status = le16_to_cpu(ioctl_resp->compl_hdr.status);
+ msgbuf->ioctl_resp_ret_len = le16_to_cpu(ioctl_resp->resp_len);
+ msgbuf->ioctl_resp_pktid = le32_to_cpu(ioctl_resp->msg.request_id);
+
+ brcmf_msgbuf_ioctl_resp_wake(msgbuf);
+
+ if (msgbuf->cur_ioctlrespbuf)
+ msgbuf->cur_ioctlrespbuf--;
+ brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+}
+
+
+static void
+brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+ struct msgbuf_tx_status *tx_status;
+ u32 idx;
+ struct sk_buff *skb;
+ u16 flowid;
+
+ tx_status = (struct msgbuf_tx_status *)buf;
+ idx = le32_to_cpu(tx_status->msg.request_id);
+ flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);
+ flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->tx_pktids, idx);
+ if (!skb) {
+ brcmf_err("Invalid packet id idx recv'd %d\n", idx);
+ return;
+ }
+
+ set_bit(flowid, msgbuf->txstatus_done_map);
+
+ brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true);
+}
+
+
+static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
+{
+ struct brcmf_commonring *commonring;
+ void *ret_ptr;
+ struct sk_buff *skb;
+ u16 alloced;
+ u32 pktlen;
+ dma_addr_t physaddr;
+ struct msgbuf_rx_bufpost *rx_bufpost;
+ long long address;
+ u32 pktid;
+ u32 i;
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+ ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+ count,
+ &alloced);
+ if (!ret_ptr) {
+ brcmf_err("Failed to reserve space in commonring\n");
+ return 0;
+ }
+
+ for (i = 0; i < alloced; i++) {
+ rx_bufpost = (struct msgbuf_rx_bufpost *)ret_ptr;
+ memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+ skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+ if (skb == NULL) {
+ brcmf_err("Failed to alloc SKB\n");
+ brcmf_commonring_write_cancel(commonring, alloced - i);
+ break;
+ }
+
+ pktlen = skb->len;
+ if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids, skb, 0,
+ &physaddr, &pktid)) {
+ dev_kfree_skb_any(skb);
+ brcmf_err("No PKTID available !!\n");
+ brcmf_commonring_write_cancel(commonring, alloced - i);
+ break;
+ }
+
+ if (msgbuf->rx_metadata_offset) {
+ address = (long long)(long)physaddr;
+ rx_bufpost->metadata_buf_len =
+ cpu_to_le16(msgbuf->rx_metadata_offset);
+ rx_bufpost->metadata_buf_addr.high_addr =
+ cpu_to_le32(address >> 32);
+ rx_bufpost->metadata_buf_addr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+
+ skb_pull(skb, msgbuf->rx_metadata_offset);
+ pktlen = skb->len;
+ physaddr += msgbuf->rx_metadata_offset;
+ }
+ rx_bufpost->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
+ rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+ address = (long long)(long)physaddr;
+ rx_bufpost->data_buf_len = cpu_to_le16((u16)pktlen);
+ rx_bufpost->data_buf_addr.high_addr =
+ cpu_to_le32(address >> 32);
+ rx_bufpost->data_buf_addr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+
+ ret_ptr += brcmf_commonring_len_item(commonring);
+ }
+
+ if (i)
+ brcmf_commonring_write_complete(commonring);
+
+ return i;
+}
+
+
+static void
+brcmf_msgbuf_rxbuf_data_fill(struct brcmf_msgbuf *msgbuf)
+{
+ u32 fillbufs;
+ u32 retcount;
+
+ fillbufs = msgbuf->max_rxbufpost - msgbuf->rxbufpost;
+
+ while (fillbufs) {
+ retcount = brcmf_msgbuf_rxbuf_data_post(msgbuf, fillbufs);
+ if (!retcount)
+ break;
+ msgbuf->rxbufpost += retcount;
+ fillbufs -= retcount;
+ }
+}
+
+
+static void
+brcmf_msgbuf_update_rxbufpost_count(struct brcmf_msgbuf *msgbuf, u16 rxcnt)
+{
+ msgbuf->rxbufpost -= rxcnt;
+ if (msgbuf->rxbufpost <= (msgbuf->max_rxbufpost -
+ BRCMF_MSGBUF_RXBUFPOST_THRESHOLD))
+ brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+}
+
+
+static u32
+brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
+ u32 count)
+{
+ struct brcmf_commonring *commonring;
+ void *ret_ptr;
+ struct sk_buff *skb;
+ u16 alloced;
+ u32 pktlen;
+ dma_addr_t physaddr;
+ struct msgbuf_rx_ioctl_resp_or_event *rx_bufpost;
+ long long address;
+ u32 pktid;
+ u32 i;
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+ brcmf_commonring_lock(commonring);
+ ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+ count,
+ &alloced);
+ if (!ret_ptr) {
+ brcmf_err("Failed to reserve space in commonring\n");
+ brcmf_commonring_unlock(commonring);
+ return 0;
+ }
+
+ for (i = 0; i < alloced; i++) {
+ rx_bufpost = (struct msgbuf_rx_ioctl_resp_or_event *)ret_ptr;
+ memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+ skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+ if (skb == NULL) {
+ brcmf_err("Failed to alloc SKB\n");
+ brcmf_commonring_write_cancel(commonring, alloced - i);
+ break;
+ }
+
+ pktlen = skb->len;
+ if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids, skb, 0,
+ &physaddr, &pktid)) {
+ dev_kfree_skb_any(skb);
+ brcmf_err("No PKTID available !!\n");
+ brcmf_commonring_write_cancel(commonring, alloced - i);
+ break;
+ }
+ if (event_buf)
+ rx_bufpost->msg.msgtype = MSGBUF_TYPE_EVENT_BUF_POST;
+ else
+ rx_bufpost->msg.msgtype =
+ MSGBUF_TYPE_IOCTLRESP_BUF_POST;
+ rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+ address = (long long)(long)physaddr;
+ rx_bufpost->host_buf_len = cpu_to_le16((u16)pktlen);
+ rx_bufpost->host_buf_addr.high_addr =
+ cpu_to_le32(address >> 32);
+ rx_bufpost->host_buf_addr.low_addr =
+ cpu_to_le32(address & 0xffffffff);
+
+ ret_ptr += brcmf_commonring_len_item(commonring);
+ }
+
+ if (i)
+ brcmf_commonring_write_complete(commonring);
+
+ brcmf_commonring_unlock(commonring);
+
+ return i;
+}
+
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf)
+{
+ u32 count;
+
+ count = msgbuf->max_ioctlrespbuf - msgbuf->cur_ioctlrespbuf;
+ count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, false, count);
+ msgbuf->cur_ioctlrespbuf += count;
+}
+
+
+static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf)
+{
+ u32 count;
+
+ count = msgbuf->max_eventbuf - msgbuf->cur_eventbuf;
+ count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, true, count);
+ msgbuf->cur_eventbuf += count;
+}
+
+
+static void
+brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb,
+ u8 ifidx)
+{
+ struct brcmf_if *ifp;
+
+ ifp = msgbuf->drvr->iflist[ifidx];
+ if (!ifp || !ifp->ndev) {
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+ }
+ brcmf_netif_rx(ifp, skb);
+}
+
+
+static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+ struct msgbuf_rx_event *event;
+ u32 idx;
+ u16 buflen;
+ struct sk_buff *skb;
+
+ event = (struct msgbuf_rx_event *)buf;
+ idx = le32_to_cpu(event->msg.request_id);
+ buflen = le16_to_cpu(event->event_data_len);
+
+ if (msgbuf->cur_eventbuf)
+ msgbuf->cur_eventbuf--;
+ brcmf_msgbuf_rxbuf_event_post(msgbuf);
+
+ skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids, idx);
+ if (!skb)
+ return;
+
+ if (msgbuf->rx_dataoffset)
+ skb_pull(skb, msgbuf->rx_dataoffset);
+
+ skb_trim(skb, buflen);
+
+ brcmf_msgbuf_rx_skb(msgbuf, skb, event->msg.ifidx);
+}
+
+
+static void
+brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+ struct msgbuf_rx_complete *rx_complete;
+ struct sk_buff *skb;
+ u16 data_offset;
+ u16 buflen;
+ u32 idx;
+
+ brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
+
+ rx_complete = (struct msgbuf_rx_complete *)buf;
+ data_offset = le16_to_cpu(rx_complete->data_offset);
+ buflen = le16_to_cpu(rx_complete->data_len);
+ idx = le32_to_cpu(rx_complete->msg.request_id);
+
+ skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+ msgbuf->rx_pktids, idx);
+
+ if (data_offset)
+ skb_pull(skb, data_offset);
+ else if (msgbuf->rx_dataoffset)
+ skb_pull(skb, msgbuf->rx_dataoffset);
+
+ skb_trim(skb, buflen);
+
+ brcmf_msgbuf_rx_skb(msgbuf, skb, rx_complete->msg.ifidx);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
+ void *buf)
+{
+ struct msgbuf_flowring_create_resp *flowring_create_resp;
+ u16 status;
+ u16 flowid;
+
+ flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf;
+
+ flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id);
+ flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ status = le16_to_cpu(flowring_create_resp->compl_hdr.status);
+
+ if (status) {
+ brcmf_err("Flowring creation failed, code %d\n", status);
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+ return;
+ }
+ brcmf_dbg(MSGBUF, "Flowring %d Create response status %d\n", flowid,
+ status);
+
+ brcmf_flowring_open(msgbuf->flow, flowid);
+
+ brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
+ void *buf)
+{
+ struct msgbuf_flowring_delete_resp *flowring_delete_resp;
+ u16 status;
+ u16 flowid;
+
+ flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf;
+
+ flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id);
+ flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ status = le16_to_cpu(flowring_delete_resp->compl_hdr.status);
+
+ if (status) {
+ brcmf_err("Flowring deletion failed, code %d\n", status);
+ brcmf_flowring_delete(msgbuf->flow, flowid);
+ return;
+ }
+ brcmf_dbg(MSGBUF, "Flowring %d Delete response status %d\n", flowid,
+ status);
+
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+}
+
+
+static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+ struct msgbuf_common_hdr *msg;
+
+ msg = (struct msgbuf_common_hdr *)buf;
+ switch (msg->msgtype) {
+ case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT\n");
+ brcmf_msgbuf_process_flow_ring_create_response(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT\n");
+ brcmf_msgbuf_process_flow_ring_delete_response(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_IOCTLPTR_REQ_ACK:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTLPTR_REQ_ACK\n");
+ break;
+ case MSGBUF_TYPE_IOCTL_CMPLT:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTL_CMPLT\n");
+ brcmf_msgbuf_process_ioctl_complete(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_WL_EVENT:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_WL_EVENT\n");
+ brcmf_msgbuf_process_event(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_TX_STATUS:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_TX_STATUS\n");
+ brcmf_msgbuf_process_txstatus(msgbuf, buf);
+ break;
+ case MSGBUF_TYPE_RX_CMPLT:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RX_CMPLT\n");
+ brcmf_msgbuf_process_rx_complete(msgbuf, buf);
+ break;
+ default:
+ brcmf_err("Unsupported msgtype %d\n", msg->msgtype);
+ break;
+ }
+}
+
+
+static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
+ struct brcmf_commonring *commonring)
+{
+ void *buf;
+ u16 count;
+
+again:
+ buf = brcmf_commonring_get_read_ptr(commonring, &count);
+ if (buf == NULL)
+ return;
+
+ while (count) {
+ brcmf_msgbuf_process_msgtype(msgbuf,
+ buf + msgbuf->rx_dataoffset);
+ buf += brcmf_commonring_len_item(commonring);
+ count--;
+ }
+ brcmf_commonring_read_complete(commonring);
+
+ if (commonring->r_ptr == 0)
+ goto again;
+}
+
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ void *buf;
+ u32 flowid;
+
+ buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+ brcmf_msgbuf_process_rx(msgbuf, buf);
+ buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+ brcmf_msgbuf_process_rx(msgbuf, buf);
+ buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+ brcmf_msgbuf_process_rx(msgbuf, buf);
+
+ for_each_set_bit(flowid, msgbuf->txstatus_done_map,
+ msgbuf->nrof_flowrings) {
+ clear_bit(flowid, msgbuf->txstatus_done_map);
+ if (brcmf_flowring_qlen(msgbuf->flow, flowid))
+ brcmf_msgbuf_schedule_txdata(msgbuf, flowid);
+ }
+
+ return 0;
+}
+
+
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ struct msgbuf_tx_flowring_delete_req *delete;
+ struct brcmf_commonring *commonring;
+ void *ret_ptr;
+ u8 ifidx;
+ int err;
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+ brcmf_commonring_lock(commonring);
+ ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+ if (!ret_ptr) {
+ brcmf_err("FW unaware, flowring will be removed !!\n");
+ brcmf_commonring_unlock(commonring);
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+ return;
+ }
+
+ delete = (struct msgbuf_tx_flowring_delete_req *)ret_ptr;
+
+ ifidx = brcmf_flowring_ifidx_get(msgbuf->flow, flowid);
+
+ delete->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE;
+ delete->msg.ifidx = ifidx;
+ delete->msg.request_id = 0;
+
+ delete->flow_ring_id = cpu_to_le16(flowid +
+ BRCMF_NROF_H2D_COMMON_MSGRINGS);
+ delete->reason = 0;
+
+ brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n",
+ flowid, ifidx);
+
+ err = brcmf_commonring_write_complete(commonring);
+ brcmf_commonring_unlock(commonring);
+ if (err) {
+ brcmf_err("Failed to submit RING_DELETE, flowring will be removed\n");
+ brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+ }
+}
+
+
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+{
+ struct brcmf_bus_msgbuf *if_msgbuf;
+ struct brcmf_msgbuf *msgbuf;
+ long long address;
+ u32 count;
+
+ if_msgbuf = drvr->bus_if->msgbuf;
+ msgbuf = kzalloc(sizeof(*msgbuf), GFP_ATOMIC);
+ if (!msgbuf)
+ goto fail;
+
+ msgbuf->txflow_wq = create_singlethread_workqueue("msgbuf_txflow");
+ if (msgbuf->txflow_wq == NULL) {
+ brcmf_err("workqueue creation failed\n");
+ goto fail;
+ }
+ INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
+ count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
+ msgbuf->flow_map = kzalloc(count, GFP_ATOMIC);
+ if (!msgbuf->flow_map)
+ goto fail;
+
+ msgbuf->txstatus_done_map = kzalloc(count, GFP_ATOMIC);
+ if (!msgbuf->txstatus_done_map)
+ goto fail;
+
+ msgbuf->drvr = drvr;
+ msgbuf->ioctbuf = dma_alloc_coherent(drvr->bus_if->dev,
+ BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+ &msgbuf->ioctbuf_handle,
+ GFP_ATOMIC);
+ if (!msgbuf->ioctbuf)
+ goto fail;
+ address = (long long)(long)msgbuf->ioctbuf_handle;
+ msgbuf->ioctbuf_phys_hi = address >> 32;
+ msgbuf->ioctbuf_phys_lo = address & 0xffffffff;
+
+ drvr->proto->hdrpull = brcmf_msgbuf_hdrpull;
+ drvr->proto->query_dcmd = brcmf_msgbuf_query_dcmd;
+ drvr->proto->set_dcmd = brcmf_msgbuf_set_dcmd;
+ drvr->proto->txdata = brcmf_msgbuf_txdata;
+ drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
+ drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
+ drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
+ drvr->proto->pd = msgbuf;
+
+ init_waitqueue_head(&msgbuf->ioctl_resp_wait);
+
+ msgbuf->commonrings =
+ (struct brcmf_commonring **)if_msgbuf->commonrings;
+ msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
+ msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings;
+ msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings *
+ sizeof(*msgbuf->flowring_dma_handle), GFP_ATOMIC);
+ if (!msgbuf->flowring_dma_handle)
+ goto fail;
+
+ msgbuf->rx_dataoffset = if_msgbuf->rx_dataoffset;
+ msgbuf->max_rxbufpost = if_msgbuf->max_rxbufpost;
+
+ msgbuf->max_ioctlrespbuf = BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST;
+ msgbuf->max_eventbuf = BRCMF_MSGBUF_MAX_EVENTBUF_POST;
+
+ msgbuf->tx_pktids = brcmf_msgbuf_init_pktids(NR_TX_PKTIDS,
+ DMA_TO_DEVICE);
+ if (!msgbuf->tx_pktids)
+ goto fail;
+ msgbuf->rx_pktids = brcmf_msgbuf_init_pktids(NR_RX_PKTIDS,
+ DMA_FROM_DEVICE);
+ if (!msgbuf->rx_pktids)
+ goto fail;
+
+ msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev,
+ if_msgbuf->nrof_flowrings);
+ if (!msgbuf->flow)
+ goto fail;
+
+
+ brcmf_dbg(MSGBUF, "Feeding buffers, rx data %d, rx event %d, rx ioctl resp %d\n",
+ msgbuf->max_rxbufpost, msgbuf->max_eventbuf,
+ msgbuf->max_ioctlrespbuf);
+ count = 0;
+ do {
+ brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+ if (msgbuf->max_rxbufpost != msgbuf->rxbufpost)
+ msleep(10);
+ else
+ break;
+ count++;
+ } while (count < 10);
+ brcmf_msgbuf_rxbuf_event_post(msgbuf);
+ brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+
+ return 0;
+
+fail:
+ if (msgbuf) {
+ kfree(msgbuf->flow_map);
+ kfree(msgbuf->txstatus_done_map);
+ brcmf_msgbuf_release_pktids(msgbuf);
+ kfree(msgbuf->flowring_dma_handle);
+ if (msgbuf->ioctbuf)
+ dma_free_coherent(drvr->bus_if->dev,
+ BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+ msgbuf->ioctbuf,
+ msgbuf->ioctbuf_handle);
+ kfree(msgbuf);
+ }
+ return -ENOMEM;
+}
+
+
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr)
+{
+ struct brcmf_msgbuf *msgbuf;
+
+ brcmf_dbg(TRACE, "Enter\n");
+ if (drvr->proto->pd) {
+ msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+ kfree(msgbuf->flow_map);
+ kfree(msgbuf->txstatus_done_map);
+ if (msgbuf->txflow_wq)
+ destroy_workqueue(msgbuf->txflow_wq);
+
+ brcmf_flowring_detach(msgbuf->flow);
+ dma_free_coherent(drvr->bus_if->dev,
+ BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+ msgbuf->ioctbuf, msgbuf->ioctbuf_handle);
+ brcmf_msgbuf_release_pktids(msgbuf);
+ kfree(msgbuf->flowring_dma_handle);
+ kfree(msgbuf);
+ drvr->proto->pd = NULL;
+ }
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
new file mode 100644
index 000000000000..f901ae52bf2b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_MSGBUF_H
+#define BRCMFMAC_MSGBUF_H
+
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 20
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 256
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 20
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 256
+#define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE 32
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE 24
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE 16
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32
+#define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48
+
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid);
+
+
+#endif /* BRCMFMAC_MSGBUF_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.c b/drivers/net/wireless/brcm80211/brcmfmac/of.c
new file mode 100644
index 000000000000..f05f5270fec1
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/mmc/card.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
+#include <linux/mmc/sdio_func.h>
+
+#include <defs.h>
+#include "dhd_dbg.h"
+#include "sdio_host.h"
+
+void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
+{
+ struct device *dev = sdiodev->dev;
+ struct device_node *np = dev->of_node;
+ int irq;
+ u32 irqf;
+ u32 val;
+
+ if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+ return;
+
+ sdiodev->pdata = devm_kzalloc(dev, sizeof(*sdiodev->pdata), GFP_KERNEL);
+ if (!sdiodev->pdata)
+ return;
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0) {
+ brcmf_err("interrupt could not be mapped: err=%d\n", irq);
+ devm_kfree(dev, sdiodev->pdata);
+ return;
+ }
+ irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+
+ sdiodev->pdata->oob_irq_supported = true;
+ sdiodev->pdata->oob_irq_nr = irq;
+ sdiodev->pdata->oob_irq_flags = irqf;
+
+ if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+ sdiodev->pdata->drive_strength = val;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.h b/drivers/net/wireless/brcm80211/brcmfmac/of.h
new file mode 100644
index 000000000000..5f7c3550deda
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef CONFIG_OF
+void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev);
+#else
+static void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
+{
+}
+#endif /* CONFIG_OF */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index f3445ac627e4..057b982ea8b3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -708,7 +708,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
active = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
else if (num_chans == AF_PEER_SEARCH_CNT)
active = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
- else if (wl_get_vif_state_all(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
+ else if (brcmf_get_vif_state_any(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
active = -1;
else
active = P2PAPI_SCAN_DWELL_TIME_MS;
@@ -2364,7 +2364,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
return 0;
default:
return -ENOTSUPP;
- break;
}
clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
new file mode 100644
index 000000000000..e5101b287e4e
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -0,0 +1,1847 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/interrupt.h>
+#include <linux/bcma/bcma.h>
+#include <linux/sched.h>
+
+#include <soc.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcm_hw_ids.h>
+
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
+#include "commonring.h"
+#include "msgbuf.h"
+#include "pcie.h"
+#include "firmware.h"
+#include "chip.h"
+
+
+enum brcmf_pcie_state {
+ BRCMFMAC_PCIE_STATE_DOWN,
+ BRCMFMAC_PCIE_STATE_UP
+};
+
+
+#define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin"
+#define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt"
+#define BRCMF_PCIE_4354_FW_NAME "brcm/brcmfmac4354-pcie.bin"
+#define BRCMF_PCIE_4354_NVRAM_NAME "brcm/brcmfmac4354-pcie.txt"
+#define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin"
+#define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt"
+#define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin"
+#define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt"
+
+#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
+
+#define BRCMF_PCIE_TCM_MAP_SIZE (4096 * 1024)
+#define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024)
+
+/* backplane addres space accessed by BAR0 */
+#define BRCMF_PCIE_BAR0_WINDOW 0x80
+#define BRCMF_PCIE_BAR0_REG_SIZE 0x1000
+#define BRCMF_PCIE_BAR0_WRAPPERBASE 0x70
+
+#define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET 0x1000
+#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET 0x2000
+
+#define BRCMF_PCIE_ARMCR4REG_BANKIDX 0x40
+#define BRCMF_PCIE_ARMCR4REG_BANKPDA 0x4C
+
+#define BRCMF_PCIE_REG_INTSTATUS 0x90
+#define BRCMF_PCIE_REG_INTMASK 0x94
+#define BRCMF_PCIE_REG_SBMBX 0x98
+
+#define BRCMF_PCIE_PCIE2REG_INTMASK 0x24
+#define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48
+#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C
+#define BRCMF_PCIE_PCIE2REG_CONFIGADDR 0x120
+#define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124
+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX 0x140
+
+#define BRCMF_PCIE_GENREV1 1
+#define BRCMF_PCIE_GENREV2 2
+
+#define BRCMF_PCIE2_INTA 0x01
+#define BRCMF_PCIE2_INTB 0x02
+
+#define BRCMF_PCIE_INT_0 0x01
+#define BRCMF_PCIE_INT_1 0x02
+#define BRCMF_PCIE_INT_DEF (BRCMF_PCIE_INT_0 | \
+ BRCMF_PCIE_INT_1)
+
+#define BRCMF_PCIE_MB_INT_FN0_0 0x0100
+#define BRCMF_PCIE_MB_INT_FN0_1 0x0200
+#define BRCMF_PCIE_MB_INT_D2H0_DB0 0x10000
+#define BRCMF_PCIE_MB_INT_D2H0_DB1 0x20000
+#define BRCMF_PCIE_MB_INT_D2H1_DB0 0x40000
+#define BRCMF_PCIE_MB_INT_D2H1_DB1 0x80000
+#define BRCMF_PCIE_MB_INT_D2H2_DB0 0x100000
+#define BRCMF_PCIE_MB_INT_D2H2_DB1 0x200000
+#define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000
+#define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000
+
+#define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \
+ BRCMF_PCIE_MB_INT_D2H0_DB1 | \
+ BRCMF_PCIE_MB_INT_D2H1_DB0 | \
+ BRCMF_PCIE_MB_INT_D2H1_DB1 | \
+ BRCMF_PCIE_MB_INT_D2H2_DB0 | \
+ BRCMF_PCIE_MB_INT_D2H2_DB1 | \
+ BRCMF_PCIE_MB_INT_D2H3_DB0 | \
+ BRCMF_PCIE_MB_INT_D2H3_DB1)
+
+#define BRCMF_PCIE_MIN_SHARED_VERSION 4
+#define BRCMF_PCIE_MAX_SHARED_VERSION 5
+#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
+#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT 0x4000
+
+#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
+#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
+
+#define BRCMF_SHARED_MAX_RXBUFPOST_OFFSET 34
+#define BRCMF_SHARED_RING_BASE_OFFSET 52
+#define BRCMF_SHARED_RX_DATAOFFSET_OFFSET 36
+#define BRCMF_SHARED_CONSOLE_ADDR_OFFSET 20
+#define BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET 40
+#define BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET 44
+#define BRCMF_SHARED_RING_INFO_ADDR_OFFSET 48
+#define BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET 52
+#define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET 56
+#define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET 64
+#define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET 68
+
+#define BRCMF_RING_H2D_RING_COUNT_OFFSET 0
+#define BRCMF_RING_D2H_RING_COUNT_OFFSET 1
+#define BRCMF_RING_H2D_RING_MEM_OFFSET 4
+#define BRCMF_RING_H2D_RING_STATE_OFFSET 8
+
+#define BRCMF_RING_MEM_BASE_ADDR_OFFSET 8
+#define BRCMF_RING_MAX_ITEM_OFFSET 4
+#define BRCMF_RING_LEN_ITEMS_OFFSET 6
+#define BRCMF_RING_MEM_SZ 16
+#define BRCMF_RING_STATE_SZ 8
+
+#define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET 4
+#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8
+#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12
+#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16
+#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0
+#define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52
+
+#define BRCMF_DEF_MAX_RXBUFPOST 255
+
+#define BRCMF_CONSOLE_BUFADDR_OFFSET 8
+#define BRCMF_CONSOLE_BUFSIZE_OFFSET 12
+#define BRCMF_CONSOLE_WRITEIDX_OFFSET 16
+
+#define BRCMF_DMA_D2H_SCRATCH_BUF_LEN 8
+#define BRCMF_DMA_D2H_RINGUPD_BUF_LEN 1024
+
+#define BRCMF_D2H_DEV_D3_ACK 0x00000001
+#define BRCMF_D2H_DEV_DS_ENTER_REQ 0x00000002
+#define BRCMF_D2H_DEV_DS_EXIT_NOTE 0x00000004
+
+#define BRCMF_H2D_HOST_D3_INFORM 0x00000001
+#define BRCMF_H2D_HOST_DS_ACK 0x00000002
+
+#define BRCMF_PCIE_MBDATA_TIMEOUT 2000
+
+#define BRCMF_PCIE_CFGREG_STATUS_CMD 0x4
+#define BRCMF_PCIE_CFGREG_PM_CSR 0x4C
+#define BRCMF_PCIE_CFGREG_MSI_CAP 0x58
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_L 0x5C
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_H 0x60
+#define BRCMF_PCIE_CFGREG_MSI_DATA 0x64
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL 0xBC
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2 0xDC
+#define BRCMF_PCIE_CFGREG_RBAR_CTRL 0x228
+#define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1 0x248
+#define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG 0x4E0
+#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4
+#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3
+
+
+MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
+MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
+
+
+struct brcmf_pcie_console {
+ u32 base_addr;
+ u32 buf_addr;
+ u32 bufsize;
+ u32 read_idx;
+ u8 log_str[256];
+ u8 log_idx;
+};
+
+struct brcmf_pcie_shared_info {
+ u32 tcm_base_address;
+ u32 flags;
+ struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+ struct brcmf_pcie_ringbuf *flowrings;
+ u16 max_rxbufpost;
+ u32 nrof_flowrings;
+ u32 rx_dataoffset;
+ u32 htod_mb_data_addr;
+ u32 dtoh_mb_data_addr;
+ u32 ring_info_addr;
+ struct brcmf_pcie_console console;
+ void *scratch;
+ dma_addr_t scratch_dmahandle;
+ void *ringupd;
+ dma_addr_t ringupd_dmahandle;
+};
+
+struct brcmf_pcie_core_info {
+ u32 base;
+ u32 wrapbase;
+};
+
+struct brcmf_pciedev_info {
+ enum brcmf_pcie_state state;
+ bool in_irq;
+ bool irq_requested;
+ struct pci_dev *pdev;
+ char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+ char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+ void __iomem *regs;
+ void __iomem *tcm;
+ u32 tcm_size;
+ u32 ram_base;
+ u32 ram_size;
+ struct brcmf_chip *ci;
+ u32 coreid;
+ u32 generic_corerev;
+ struct brcmf_pcie_shared_info shared;
+ void (*ringbell)(struct brcmf_pciedev_info *devinfo);
+ wait_queue_head_t mbdata_resp_wait;
+ bool mbdata_completed;
+ bool irq_allocated;
+};
+
+struct brcmf_pcie_ringbuf {
+ struct brcmf_commonring commonring;
+ dma_addr_t dma_handle;
+ u32 w_idx_addr;
+ u32 r_idx_addr;
+ struct brcmf_pciedev_info *devinfo;
+ u8 id;
+};
+
+
+static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
+ BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
+ BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM,
+ BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM,
+ BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM,
+ BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM
+};
+
+static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
+ BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
+ BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
+ BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
+ BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE,
+ BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
+};
+
+
+/* dma flushing needs implementation for mips and arm platforms. Should
+ * be put in util. Note, this is not real flushing. It is virtual non
+ * cached memory. Only write buffers should have to be drained. Though
+ * this may be different depending on platform......
+ */
+#define brcmf_dma_flush(addr, len)
+#define brcmf_dma_invalidate_cache(addr, len)
+
+
+static u32
+brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+{
+ void __iomem *address = devinfo->regs + reg_offset;
+
+ return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
+ u32 value)
+{
+ void __iomem *address = devinfo->regs + reg_offset;
+
+ iowrite32(value, address);
+}
+
+
+static u8
+brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+
+ return (ioread8(address));
+}
+
+
+static u16
+brcmf_pcie_read_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+
+ return (ioread16(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ u16 value)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+
+ iowrite16(value, address);
+}
+
+
+static u32
+brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+
+ return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ u32 value)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+
+ iowrite32(value, address);
+}
+
+
+static u32
+brcmf_pcie_read_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+ void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+ return (ioread32(addr));
+}
+
+
+static void
+brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ u32 value)
+{
+ void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+ iowrite32(value, addr);
+}
+
+
+static void
+brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+ void *srcaddr, u32 len)
+{
+ void __iomem *address = devinfo->tcm + mem_offset;
+ __le32 *src32;
+ __le16 *src16;
+ u8 *src8;
+
+ if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) {
+ if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) {
+ src8 = (u8 *)srcaddr;
+ while (len) {
+ iowrite8(*src8, address);
+ address++;
+ src8++;
+ len--;
+ }
+ } else {
+ len = len / 2;
+ src16 = (__le16 *)srcaddr;
+ while (len) {
+ iowrite16(le16_to_cpu(*src16), address);
+ address += 2;
+ src16++;
+ len--;
+ }
+ }
+ } else {
+ len = len / 4;
+ src32 = (__le32 *)srcaddr;
+ while (len) {
+ iowrite32(le32_to_cpu(*src32), address);
+ address += 4;
+ src32++;
+ len--;
+ }
+ }
+}
+
+
+#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
+ CHIPCREGOFFS(reg), value)
+
+
+static void
+brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
+{
+ const struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_core *core;
+ u32 bar0_win;
+
+ core = brcmf_chip_get_core(devinfo->ci, coreid);
+ if (core) {
+ bar0_win = core->base;
+ pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, bar0_win);
+ if (pci_read_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW,
+ &bar0_win) == 0) {
+ if (bar0_win != core->base) {
+ bar0_win = core->base;
+ pci_write_config_dword(pdev,
+ BRCMF_PCIE_BAR0_WINDOW,
+ bar0_win);
+ }
+ }
+ } else {
+ brcmf_err("Unsupported core selected %x\n", coreid);
+ }
+}
+
+
+static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
+{
+ u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
+ BRCMF_PCIE_CFGREG_PM_CSR,
+ BRCMF_PCIE_CFGREG_MSI_CAP,
+ BRCMF_PCIE_CFGREG_MSI_ADDR_L,
+ BRCMF_PCIE_CFGREG_MSI_ADDR_H,
+ BRCMF_PCIE_CFGREG_MSI_DATA,
+ BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
+ BRCMF_PCIE_CFGREG_RBAR_CTRL,
+ BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
+ BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
+ BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG };
+ u32 i;
+ u32 val;
+ u32 lsc;
+
+ if (!devinfo->ci)
+ return;
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+ BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+ lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+ val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val);
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
+ WRITECC32(devinfo, watchdog, 4);
+ msleep(100);
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+ BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc);
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+ cfg_offset[i]);
+ val = brcmf_pcie_read_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+ brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+ cfg_offset[i], val);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+ val);
+ }
+}
+
+
+static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
+{
+ u32 config;
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0)
+ brcmf_pcie_reset_device(devinfo);
+ /* BAR1 window may not be sized properly */
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
+ config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
+
+ device_wakeup_enable(&devinfo->pdev->dev);
+}
+
+
+static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
+{
+ brcmf_chip_enter_download(devinfo->ci);
+
+ if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+ 5);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+ 0);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+ 7);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+ 0);
+ }
+ return 0;
+}
+
+
+static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
+ u32 resetintr)
+{
+ struct brcmf_core *core;
+
+ if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_INTERNAL_MEM);
+ brcmf_chip_resetcore(core, 0, 0, 0);
+ }
+
+ return !brcmf_chip_exit_download(devinfo->ci, resetintr);
+}
+
+
+static void
+brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
+{
+ struct brcmf_pcie_shared_info *shared;
+ u32 addr;
+ u32 cur_htod_mb_data;
+ u32 i;
+
+ shared = &devinfo->shared;
+ addr = shared->htod_mb_data_addr;
+ cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ if (cur_htod_mb_data != 0)
+ brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",
+ cur_htod_mb_data);
+
+ i = 0;
+ while (cur_htod_mb_data != 0) {
+ msleep(10);
+ i++;
+ if (i > 100)
+ break;
+ cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+ }
+
+ brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+}
+
+
+static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
+{
+ struct brcmf_pcie_shared_info *shared;
+ u32 addr;
+ u32 dtoh_mb_data;
+
+ shared = &devinfo->shared;
+ addr = shared->dtoh_mb_data_addr;
+ dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ if (!dtoh_mb_data)
+ return;
+
+ brcmf_pcie_write_tcm32(devinfo, addr, 0);
+
+ brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
+ if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
+ brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
+ brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
+ brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
+ }
+ if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
+ brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
+ if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
+ brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
+ if (waitqueue_active(&devinfo->mbdata_resp_wait)) {
+ devinfo->mbdata_completed = true;
+ wake_up(&devinfo->mbdata_resp_wait);
+ }
+ }
+}
+
+
+static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
+{
+ struct brcmf_pcie_shared_info *shared;
+ struct brcmf_pcie_console *console;
+ u32 addr;
+
+ shared = &devinfo->shared;
+ console = &shared->console;
+ addr = shared->tcm_base_address + BRCMF_SHARED_CONSOLE_ADDR_OFFSET;
+ console->base_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ addr = console->base_addr + BRCMF_CONSOLE_BUFADDR_OFFSET;
+ console->buf_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+ addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
+ console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n",
+ console->base_addr, console->buf_addr, console->bufsize);
+}
+
+
+static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
+{
+ struct brcmf_pcie_console *console;
+ u32 addr;
+ u8 ch;
+ u32 newidx;
+
+ console = &devinfo->shared.console;
+ addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
+ newidx = brcmf_pcie_read_tcm32(devinfo, addr);
+ while (newidx != console->read_idx) {
+ addr = console->buf_addr + console->read_idx;
+ ch = brcmf_pcie_read_tcm8(devinfo, addr);
+ console->read_idx++;
+ if (console->read_idx == console->bufsize)
+ console->read_idx = 0;
+ if (ch == '\r')
+ continue;
+ console->log_str[console->log_idx] = ch;
+ console->log_idx++;
+ if ((ch != '\n') &&
+ (console->log_idx == (sizeof(console->log_str) - 2))) {
+ ch = '\n';
+ console->log_str[console->log_idx] = ch;
+ console->log_idx++;
+ }
+
+ if (ch == '\n') {
+ console->log_str[console->log_idx] = 0;
+ brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str);
+ console->log_idx = 0;
+ }
+ }
+}
+
+
+static __used void brcmf_pcie_ringbell_v1(struct brcmf_pciedev_info *devinfo)
+{
+ u32 reg_value;
+
+ brcmf_dbg(PCIE, "RING !\n");
+ reg_value = brcmf_pcie_read_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ reg_value |= BRCMF_PCIE2_INTB;
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ reg_value);
+}
+
+
+static void brcmf_pcie_ringbell_v2(struct brcmf_pciedev_info *devinfo)
+{
+ brcmf_dbg(PCIE, "RING !\n");
+ /* Any arbitrary value will do, lets use 1 */
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1);
+}
+
+
+static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
+{
+ if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+ 0);
+ else
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+ 0);
+}
+
+
+static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
+{
+ if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1)
+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK,
+ BRCMF_PCIE_INT_DEF);
+ else
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+ BRCMF_PCIE_MB_INT_D2H_DB |
+ BRCMF_PCIE_MB_INT_FN0_0 |
+ BRCMF_PCIE_MB_INT_FN0_1);
+}
+
+
+static irqreturn_t brcmf_pcie_quick_check_isr_v1(int irq, void *arg)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+ u32 status;
+
+ status = 0;
+ pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+ if (status) {
+ brcmf_pcie_intr_disable(devinfo);
+ brcmf_dbg(PCIE, "Enter\n");
+ return IRQ_WAKE_THREAD;
+ }
+ return IRQ_NONE;
+}
+
+
+static irqreturn_t brcmf_pcie_quick_check_isr_v2(int irq, void *arg)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+
+ if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
+ brcmf_pcie_intr_disable(devinfo);
+ brcmf_dbg(PCIE, "Enter\n");
+ return IRQ_WAKE_THREAD;
+ }
+ return IRQ_NONE;
+}
+
+
+static irqreturn_t brcmf_pcie_isr_thread_v1(int irq, void *arg)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+ const struct pci_dev *pdev = devinfo->pdev;
+ u32 status;
+
+ devinfo->in_irq = true;
+ status = 0;
+ pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+ brcmf_dbg(PCIE, "Enter %x\n", status);
+ if (status) {
+ pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+ if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+ brcmf_proto_msgbuf_rx_trigger(&devinfo->pdev->dev);
+ }
+ if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+ brcmf_pcie_intr_enable(devinfo);
+ devinfo->in_irq = false;
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t brcmf_pcie_isr_thread_v2(int irq, void *arg)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+ u32 status;
+
+ devinfo->in_irq = true;
+ status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ brcmf_dbg(PCIE, "Enter %x\n", status);
+ if (status) {
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ status);
+ if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
+ BRCMF_PCIE_MB_INT_FN0_1))
+ brcmf_pcie_handle_mb_data(devinfo);
+ if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
+ if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+ brcmf_proto_msgbuf_rx_trigger(
+ &devinfo->pdev->dev);
+ }
+ }
+ brcmf_pcie_bus_console_read(devinfo);
+ if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+ brcmf_pcie_intr_enable(devinfo);
+ devinfo->in_irq = false;
+ return IRQ_HANDLED;
+}
+
+
+static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
+{
+ struct pci_dev *pdev;
+
+ pdev = devinfo->pdev;
+
+ brcmf_pcie_intr_disable(devinfo);
+
+ brcmf_dbg(PCIE, "Enter\n");
+ /* is it a v1 or v2 implementation */
+ devinfo->irq_requested = false;
+ if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+ if (request_threaded_irq(pdev->irq,
+ brcmf_pcie_quick_check_isr_v1,
+ brcmf_pcie_isr_thread_v1,
+ IRQF_SHARED, "brcmf_pcie_intr",
+ devinfo)) {
+ brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+ return -EIO;
+ }
+ } else {
+ if (request_threaded_irq(pdev->irq,
+ brcmf_pcie_quick_check_isr_v2,
+ brcmf_pcie_isr_thread_v2,
+ IRQF_SHARED, "brcmf_pcie_intr",
+ devinfo)) {
+ brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+ return -EIO;
+ }
+ }
+ devinfo->irq_requested = true;
+ devinfo->irq_allocated = true;
+ return 0;
+}
+
+
+static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
+{
+ struct pci_dev *pdev;
+ u32 status;
+ u32 count;
+
+ if (!devinfo->irq_allocated)
+ return;
+
+ pdev = devinfo->pdev;
+
+ brcmf_pcie_intr_disable(devinfo);
+ if (!devinfo->irq_requested)
+ return;
+ devinfo->irq_requested = false;
+ free_irq(pdev->irq, devinfo);
+
+ msleep(50);
+ count = 0;
+ while ((devinfo->in_irq) && (count < 20)) {
+ msleep(50);
+ count++;
+ }
+ if (devinfo->in_irq)
+ brcmf_err("Still in IRQ (processing) !!!\n");
+
+ if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
+ status = 0;
+ pci_read_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, &status);
+ pci_write_config_dword(pdev, BRCMF_PCIE_REG_INTSTATUS, status);
+ } else {
+ status = brcmf_pcie_read_reg32(devinfo,
+ BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ status);
+ }
+ devinfo->irq_allocated = false;
+}
+
+
+static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
+{
+ struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+ struct brcmf_pciedev_info *devinfo = ring->devinfo;
+ struct brcmf_commonring *commonring = &ring->commonring;
+
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+ brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+ commonring->w_ptr, ring->id);
+
+ brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
+{
+ struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+ struct brcmf_pciedev_info *devinfo = ring->devinfo;
+ struct brcmf_commonring *commonring = &ring->commonring;
+
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+ brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+ commonring->r_ptr, ring->id);
+
+ brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
+{
+ struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+ struct brcmf_pciedev_info *devinfo = ring->devinfo;
+
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+ devinfo->ringbell(devinfo);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
+{
+ struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+ struct brcmf_pciedev_info *devinfo = ring->devinfo;
+ struct brcmf_commonring *commonring = &ring->commonring;
+
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+ commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
+
+ brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+ commonring->w_ptr, ring->id);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
+{
+ struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+ struct brcmf_pciedev_info *devinfo = ring->devinfo;
+ struct brcmf_commonring *commonring = &ring->commonring;
+
+ if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+ return -EIO;
+
+ commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
+
+ brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+ commonring->r_ptr, ring->id);
+
+ return 0;
+}
+
+
+static void *
+brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
+ u32 size, u32 tcm_dma_phys_addr,
+ dma_addr_t *dma_handle)
+{
+ void *ring;
+ long long address;
+
+ ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,
+ GFP_KERNEL);
+ if (!ring)
+ return NULL;
+
+ address = (long long)(long)*dma_handle;
+ brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,
+ address & 0xffffffff);
+ brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
+
+ memset(ring, 0, size);
+
+ return (ring);
+}
+
+
+static struct brcmf_pcie_ringbuf *
+brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info *devinfo, u32 ring_id,
+ u32 tcm_ring_phys_addr)
+{
+ void *dma_buf;
+ dma_addr_t dma_handle;
+ struct brcmf_pcie_ringbuf *ring;
+ u32 size;
+ u32 addr;
+
+ size = brcmf_ring_max_item[ring_id] * brcmf_ring_itemsize[ring_id];
+ dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,
+ tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,
+ &dma_handle);
+ if (!dma_buf)
+ return NULL;
+
+ addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;
+ brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);
+ addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;
+ brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_itemsize[ring_id]);
+
+ ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+ if (!ring) {
+ dma_free_coherent(&devinfo->pdev->dev, size, dma_buf,
+ dma_handle);
+ return NULL;
+ }
+ brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],
+ brcmf_ring_itemsize[ring_id], dma_buf);
+ ring->dma_handle = dma_handle;
+ ring->devinfo = devinfo;
+ brcmf_commonring_register_cb(&ring->commonring,
+ brcmf_pcie_ring_mb_ring_bell,
+ brcmf_pcie_ring_mb_update_rptr,
+ brcmf_pcie_ring_mb_update_wptr,
+ brcmf_pcie_ring_mb_write_rptr,
+ brcmf_pcie_ring_mb_write_wptr, ring);
+
+ return (ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffer(struct device *dev,
+ struct brcmf_pcie_ringbuf *ring)
+{
+ void *dma_buf;
+ u32 size;
+
+ if (!ring)
+ return;
+
+ dma_buf = ring->commonring.buf_addr;
+ if (dma_buf) {
+ size = ring->commonring.depth * ring->commonring.item_len;
+ dma_free_coherent(dev, size, dma_buf, ring->dma_handle);
+ }
+ kfree(ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+ u32 i;
+
+ for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+ brcmf_pcie_release_ringbuffer(&devinfo->pdev->dev,
+ devinfo->shared.commonrings[i]);
+ devinfo->shared.commonrings[i] = NULL;
+ }
+ kfree(devinfo->shared.flowrings);
+ devinfo->shared.flowrings = NULL;
+}
+
+
+static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+ struct brcmf_pcie_ringbuf *ring;
+ struct brcmf_pcie_ringbuf *rings;
+ u32 ring_addr;
+ u32 d2h_w_idx_ptr;
+ u32 d2h_r_idx_ptr;
+ u32 h2d_w_idx_ptr;
+ u32 h2d_r_idx_ptr;
+ u32 addr;
+ u32 ring_mem_ptr;
+ u32 i;
+ u16 max_sub_queues;
+
+ ring_addr = devinfo->shared.ring_info_addr;
+ brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr);
+
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET;
+ d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+ addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET;
+ d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET;
+ h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+ addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET;
+ h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET;
+ ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
+ ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+ if (!ring)
+ goto fail;
+ ring->w_idx_addr = h2d_w_idx_ptr;
+ ring->r_idx_addr = h2d_r_idx_ptr;
+ ring->id = i;
+ devinfo->shared.commonrings[i] = ring;
+
+ h2d_w_idx_ptr += sizeof(u32);
+ h2d_r_idx_ptr += sizeof(u32);
+ ring_mem_ptr += BRCMF_RING_MEM_SZ;
+ }
+
+ for (i = BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+ ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+ if (!ring)
+ goto fail;
+ ring->w_idx_addr = d2h_w_idx_ptr;
+ ring->r_idx_addr = d2h_r_idx_ptr;
+ ring->id = i;
+ devinfo->shared.commonrings[i] = ring;
+
+ d2h_w_idx_ptr += sizeof(u32);
+ d2h_r_idx_ptr += sizeof(u32);
+ ring_mem_ptr += BRCMF_RING_MEM_SZ;
+ }
+
+ addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
+ max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
+ devinfo->shared.nrof_flowrings =
+ max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
+ rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
+ GFP_KERNEL);
+ if (!rings)
+ goto fail;
+
+ brcmf_dbg(PCIE, "Nr of flowrings is %d\n",
+ devinfo->shared.nrof_flowrings);
+
+ for (i = 0; i < devinfo->shared.nrof_flowrings; i++) {
+ ring = &rings[i];
+ ring->devinfo = devinfo;
+ ring->id = i + BRCMF_NROF_COMMON_MSGRINGS;
+ brcmf_commonring_register_cb(&ring->commonring,
+ brcmf_pcie_ring_mb_ring_bell,
+ brcmf_pcie_ring_mb_update_rptr,
+ brcmf_pcie_ring_mb_update_wptr,
+ brcmf_pcie_ring_mb_write_rptr,
+ brcmf_pcie_ring_mb_write_wptr,
+ ring);
+ ring->w_idx_addr = h2d_w_idx_ptr;
+ ring->r_idx_addr = h2d_r_idx_ptr;
+ h2d_w_idx_ptr += sizeof(u32);
+ h2d_r_idx_ptr += sizeof(u32);
+ }
+ devinfo->shared.flowrings = rings;
+
+ return 0;
+
+fail:
+ brcmf_err("Allocating commonring buffers failed\n");
+ brcmf_pcie_release_ringbuffers(devinfo);
+ return -ENOMEM;
+}
+
+
+static void
+brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+ if (devinfo->shared.scratch)
+ dma_free_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+ devinfo->shared.scratch,
+ devinfo->shared.scratch_dmahandle);
+ if (devinfo->shared.ringupd)
+ dma_free_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+ devinfo->shared.ringupd,
+ devinfo->shared.ringupd_dmahandle);
+}
+
+static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+ long long address;
+ u32 addr;
+
+ devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+ &devinfo->shared.scratch_dmahandle, GFP_KERNEL);
+ if (!devinfo->shared.scratch)
+ goto fail;
+
+ memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+ brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+
+ addr = devinfo->shared.tcm_base_address +
+ BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
+ address = (long long)(long)devinfo->shared.scratch_dmahandle;
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+ addr = devinfo->shared.tcm_base_address +
+ BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
+ brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+
+ devinfo->shared.ringupd = dma_alloc_coherent(&devinfo->pdev->dev,
+ BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+ &devinfo->shared.ringupd_dmahandle, GFP_KERNEL);
+ if (!devinfo->shared.ringupd)
+ goto fail;
+
+ memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+ brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+
+ addr = devinfo->shared.tcm_base_address +
+ BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
+ address = (long long)(long)devinfo->shared.ringupd_dmahandle;
+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+ addr = devinfo->shared.tcm_base_address +
+ BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET;
+ brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+ return 0;
+
+fail:
+ brcmf_err("Allocating scratch buffers failed\n");
+ brcmf_pcie_release_scratchbuffers(devinfo);
+ return -ENOMEM;
+}
+
+
+static void brcmf_pcie_down(struct device *dev)
+{
+}
+
+
+static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
+{
+ return 0;
+}
+
+
+static int brcmf_pcie_tx_ctlpkt(struct device *dev, unsigned char *msg,
+ uint len)
+{
+ return 0;
+}
+
+
+static int brcmf_pcie_rx_ctlpkt(struct device *dev, unsigned char *msg,
+ uint len)
+{
+ return 0;
+}
+
+
+static struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+ .txdata = brcmf_pcie_tx,
+ .stop = brcmf_pcie_down,
+ .txctl = brcmf_pcie_tx_ctlpkt,
+ .rxctl = brcmf_pcie_rx_ctlpkt,
+};
+
+
+static int
+brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
+ u32 sharedram_addr)
+{
+ struct brcmf_pcie_shared_info *shared;
+ u32 addr;
+ u32 version;
+
+ shared = &devinfo->shared;
+ shared->tcm_base_address = sharedram_addr;
+
+ shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
+ version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK;
+ brcmf_dbg(PCIE, "PCIe protocol version %d\n", version);
+ if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
+ (version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
+ brcmf_err("Unsupported PCIE version %d\n", version);
+ return -EINVAL;
+ }
+ if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
+ brcmf_err("Unsupported legacy TX mode 0x%x\n",
+ shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
+ return -EINVAL;
+ }
+
+ addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
+ shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
+ if (shared->max_rxbufpost == 0)
+ shared->max_rxbufpost = BRCMF_DEF_MAX_RXBUFPOST;
+
+ addr = sharedram_addr + BRCMF_SHARED_RX_DATAOFFSET_OFFSET;
+ shared->rx_dataoffset = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ addr = sharedram_addr + BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET;
+ shared->htod_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ addr = sharedram_addr + BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET;
+ shared->dtoh_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;
+ shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",
+ shared->max_rxbufpost, shared->rx_dataoffset);
+
+ brcmf_pcie_bus_console_init(devinfo);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
+{
+ char *fw_name;
+ char *nvram_name;
+ uint fw_len, nv_len;
+ char end;
+
+ brcmf_dbg(PCIE, "Enter, chip 0x%04x chiprev %d\n", devinfo->ci->chip,
+ devinfo->ci->chiprev);
+
+ switch (devinfo->ci->chip) {
+ case BRCM_CC_43602_CHIP_ID:
+ fw_name = BRCMF_PCIE_43602_FW_NAME;
+ nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
+ break;
+ case BRCM_CC_4354_CHIP_ID:
+ fw_name = BRCMF_PCIE_4354_FW_NAME;
+ nvram_name = BRCMF_PCIE_4354_NVRAM_NAME;
+ break;
+ case BRCM_CC_4356_CHIP_ID:
+ fw_name = BRCMF_PCIE_4356_FW_NAME;
+ nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
+ break;
+ case BRCM_CC_43567_CHIP_ID:
+ case BRCM_CC_43569_CHIP_ID:
+ case BRCM_CC_43570_CHIP_ID:
+ fw_name = BRCMF_PCIE_43570_FW_NAME;
+ nvram_name = BRCMF_PCIE_43570_NVRAM_NAME;
+ break;
+ default:
+ brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
+ return -ENODEV;
+ }
+
+ fw_len = sizeof(devinfo->fw_name) - 1;
+ nv_len = sizeof(devinfo->nvram_name) - 1;
+ /* check if firmware path is provided by module parameter */
+ if (brcmf_firmware_path[0] != '\0') {
+ strncpy(devinfo->fw_name, brcmf_firmware_path, fw_len);
+ strncpy(devinfo->nvram_name, brcmf_firmware_path, nv_len);
+ fw_len -= strlen(devinfo->fw_name);
+ nv_len -= strlen(devinfo->nvram_name);
+
+ end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
+ if (end != '/') {
+ strncat(devinfo->fw_name, "/", fw_len);
+ strncat(devinfo->nvram_name, "/", nv_len);
+ fw_len--;
+ nv_len--;
+ }
+ }
+ strncat(devinfo->fw_name, fw_name, fw_len);
+ strncat(devinfo->nvram_name, nvram_name, nv_len);
+
+ return 0;
+}
+
+
+static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ const struct firmware *fw, void *nvram,
+ u32 nvram_len)
+{
+ u32 sharedram_addr;
+ u32 sharedram_addr_written;
+ u32 loop_counter;
+ int err;
+ u32 address;
+ u32 resetintr;
+
+ devinfo->ringbell = brcmf_pcie_ringbell_v2;
+ devinfo->generic_corerev = BRCMF_PCIE_GENREV2;
+
+ brcmf_dbg(PCIE, "Halt ARM.\n");
+ err = brcmf_pcie_enter_download_state(devinfo);
+ if (err)
+ return err;
+
+ brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
+ brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase,
+ (void *)fw->data, fw->size);
+
+ resetintr = get_unaligned_le32(fw->data);
+ release_firmware(fw);
+
+ /* reset last 4 bytes of RAM address. to be used for shared
+ * area. This identifies when FW is running
+ */
+ brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
+
+ if (nvram) {
+ brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
+ address = devinfo->ci->rambase + devinfo->ci->ramsize -
+ nvram_len;
+ brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
+ brcmf_fw_nvram_free(nvram);
+ } else {
+ brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
+ devinfo->nvram_name);
+ }
+
+ sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
+ devinfo->ci->ramsize -
+ 4);
+ brcmf_dbg(PCIE, "Bring ARM in running state\n");
+ err = brcmf_pcie_exit_download_state(devinfo, resetintr);
+ if (err)
+ return err;
+
+ brcmf_dbg(PCIE, "Wait for FW init\n");
+ sharedram_addr = sharedram_addr_written;
+ loop_counter = BRCMF_PCIE_FW_UP_TIMEOUT / 50;
+ while ((sharedram_addr == sharedram_addr_written) && (loop_counter)) {
+ msleep(50);
+ sharedram_addr = brcmf_pcie_read_ram32(devinfo,
+ devinfo->ci->ramsize -
+ 4);
+ loop_counter--;
+ }
+ if (sharedram_addr == sharedram_addr_written) {
+ brcmf_err("FW failed to initialize\n");
+ return -ENODEV;
+ }
+ brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);
+
+ return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr));
+}
+
+
+static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
+{
+ struct pci_dev *pdev;
+ int err;
+ phys_addr_t bar0_addr, bar1_addr;
+ ulong bar1_size;
+
+ pdev = devinfo->pdev;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ brcmf_err("pci_enable_device failed err=%d\n", err);
+ return err;
+ }
+
+ pci_set_master(pdev);
+
+ /* Bar-0 mapped address */
+ bar0_addr = pci_resource_start(pdev, 0);
+ /* Bar-1 mapped address */
+ bar1_addr = pci_resource_start(pdev, 2);
+ /* read Bar-1 mapped memory range */
+ bar1_size = pci_resource_len(pdev, 2);
+ if ((bar1_size == 0) || (bar1_addr == 0)) {
+ brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
+ bar1_size, (unsigned long long)bar1_addr);
+ return -EINVAL;
+ }
+
+ devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
+ devinfo->tcm = ioremap_nocache(bar1_addr, BRCMF_PCIE_TCM_MAP_SIZE);
+ devinfo->tcm_size = BRCMF_PCIE_TCM_MAP_SIZE;
+
+ if (!devinfo->regs || !devinfo->tcm) {
+ brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
+ devinfo->tcm);
+ return -EINVAL;
+ }
+ brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
+ devinfo->regs, (unsigned long long)bar0_addr);
+ brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx\n",
+ devinfo->tcm, (unsigned long long)bar1_addr);
+
+ return 0;
+}
+
+
+static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
+{
+ if (devinfo->tcm)
+ iounmap(devinfo->tcm);
+ if (devinfo->regs)
+ iounmap(devinfo->regs);
+
+ pci_disable_device(devinfo->pdev);
+}
+
+
+static int brcmf_pcie_attach_bus(struct device *dev)
+{
+ int ret;
+
+ /* Attach to the common driver interface */
+ ret = brcmf_attach(dev);
+ if (ret) {
+ brcmf_err("brcmf_attach failed\n");
+ } else {
+ ret = brcmf_bus_start(dev);
+ if (ret)
+ brcmf_err("dongle is not responding\n");
+ }
+
+ return ret;
+}
+
+
+static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
+{
+ u32 ret_addr;
+
+ ret_addr = addr & (BRCMF_PCIE_BAR0_REG_SIZE - 1);
+ addr &= ~(BRCMF_PCIE_BAR0_REG_SIZE - 1);
+ pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, addr);
+
+ return ret_addr;
+}
+
+
+static u32 brcmf_pcie_buscore_read32(void *ctx, u32 addr)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+ addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+ return brcmf_pcie_read_reg32(devinfo, addr);
+}
+
+
+static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+ addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+ brcmf_pcie_write_reg32(devinfo, addr, value);
+}
+
+
+static int brcmf_pcie_buscoreprep(void *ctx)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+ int err;
+
+ err = brcmf_pcie_get_resource(devinfo);
+ if (err == 0) {
+ /* Set CC watchdog to reset all the cores on the chip to bring
+ * back dongle to a sane state.
+ */
+ brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
+ watchdog), 4);
+ msleep(100);
+ }
+
+ return err;
+}
+
+
+static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip,
+ u32 rstvec)
+{
+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+ brcmf_pcie_write_tcm32(devinfo, 0, rstvec);
+}
+
+
+static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
+ .prepare = brcmf_pcie_buscoreprep,
+ .exit_dl = brcmf_pcie_buscore_exitdl,
+ .read32 = brcmf_pcie_buscore_read32,
+ .write32 = brcmf_pcie_buscore_write32,
+};
+
+static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw,
+ void *nvram, u32 nvram_len)
+{
+ struct brcmf_bus *bus = dev_get_drvdata(dev);
+ struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
+ struct brcmf_commonring **flowrings;
+ int ret;
+ u32 i;
+
+ brcmf_pcie_attach(devinfo);
+
+ ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
+ if (ret)
+ goto fail;
+
+ devinfo->state = BRCMFMAC_PCIE_STATE_UP;
+
+ ret = brcmf_pcie_init_ringbuffers(devinfo);
+ if (ret)
+ goto fail;
+
+ ret = brcmf_pcie_init_scratchbuffers(devinfo);
+ if (ret)
+ goto fail;
+
+ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+ ret = brcmf_pcie_request_irq(devinfo);
+ if (ret)
+ goto fail;
+
+ /* hook the commonrings in the bus structure. */
+ for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++)
+ bus->msgbuf->commonrings[i] =
+ &devinfo->shared.commonrings[i]->commonring;
+
+ flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(flowrings),
+ GFP_KERNEL);
+ if (!flowrings)
+ goto fail;
+
+ for (i = 0; i < devinfo->shared.nrof_flowrings; i++)
+ flowrings[i] = &devinfo->shared.flowrings[i].commonring;
+ bus->msgbuf->flowrings = flowrings;
+
+ bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
+ bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
+ bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings;
+
+ init_waitqueue_head(&devinfo->mbdata_resp_wait);
+
+ brcmf_pcie_intr_enable(devinfo);
+ if (brcmf_pcie_attach_bus(bus->dev) == 0)
+ return;
+
+ brcmf_pcie_bus_console_read(devinfo);
+
+fail:
+ device_release_driver(dev);
+}
+
+static int
+brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int ret;
+ struct brcmf_pciedev_info *devinfo;
+ struct brcmf_pciedev *pcie_bus_dev;
+ struct brcmf_bus *bus;
+
+ brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
+
+ ret = -ENOMEM;
+ devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+ if (devinfo == NULL)
+ return ret;
+
+ devinfo->pdev = pdev;
+ pcie_bus_dev = NULL;
+ devinfo->ci = brcmf_chip_attach(devinfo, &brcmf_pcie_buscore_ops);
+ if (IS_ERR(devinfo->ci)) {
+ ret = PTR_ERR(devinfo->ci);
+ devinfo->ci = NULL;
+ goto fail;
+ }
+
+ pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
+ if (pcie_bus_dev == NULL) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
+ if (!bus->msgbuf) {
+ ret = -ENOMEM;
+ kfree(bus);
+ goto fail;
+ }
+
+ /* hook it all together. */
+ pcie_bus_dev->devinfo = devinfo;
+ pcie_bus_dev->bus = bus;
+ bus->dev = &pdev->dev;
+ bus->bus_priv.pcie = pcie_bus_dev;
+ bus->ops = &brcmf_pcie_bus_ops;
+ bus->proto_type = BRCMF_PROTO_MSGBUF;
+ bus->chip = devinfo->coreid;
+ dev_set_drvdata(&pdev->dev, bus);
+
+ ret = brcmf_pcie_get_fwnames(devinfo);
+ if (ret)
+ goto fail_bus;
+
+ ret = brcmf_fw_get_firmwares(bus->dev, BRCMF_FW_REQUEST_NVRAM |
+ BRCMF_FW_REQ_NV_OPTIONAL,
+ devinfo->fw_name, devinfo->nvram_name,
+ brcmf_pcie_setup);
+ if (ret == 0)
+ return 0;
+fail_bus:
+ kfree(bus->msgbuf);
+ kfree(bus);
+fail:
+ brcmf_err("failed %x:%x\n", pdev->vendor, pdev->device);
+ brcmf_pcie_release_resource(devinfo);
+ if (devinfo->ci)
+ brcmf_chip_detach(devinfo->ci);
+ kfree(pcie_bus_dev);
+ kfree(devinfo);
+ return ret;
+}
+
+
+static void
+brcmf_pcie_remove(struct pci_dev *pdev)
+{
+ struct brcmf_pciedev_info *devinfo;
+ struct brcmf_bus *bus;
+
+ brcmf_dbg(PCIE, "Enter\n");
+
+ bus = dev_get_drvdata(&pdev->dev);
+ if (bus == NULL)
+ return;
+
+ devinfo = bus->bus_priv.pcie->devinfo;
+
+ devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
+ if (devinfo->ci)
+ brcmf_pcie_intr_disable(devinfo);
+
+ brcmf_detach(&pdev->dev);
+
+ kfree(bus->bus_priv.pcie);
+ kfree(bus->msgbuf->flowrings);
+ kfree(bus->msgbuf);
+ kfree(bus);
+
+ brcmf_pcie_release_irq(devinfo);
+ brcmf_pcie_release_scratchbuffers(devinfo);
+ brcmf_pcie_release_ringbuffers(devinfo);
+ brcmf_pcie_reset_device(devinfo);
+ brcmf_pcie_release_resource(devinfo);
+
+ if (devinfo->ci)
+ brcmf_chip_detach(devinfo->ci);
+
+ kfree(devinfo);
+ dev_set_drvdata(&pdev->dev, NULL);
+}
+
+
+#ifdef CONFIG_PM
+
+
+static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct brcmf_pciedev_info *devinfo;
+ struct brcmf_bus *bus;
+ int err;
+
+ brcmf_dbg(PCIE, "Enter, state=%d, pdev=%p\n", state.event, pdev);
+
+ bus = dev_get_drvdata(&pdev->dev);
+ devinfo = bus->bus_priv.pcie->devinfo;
+
+ brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
+
+ devinfo->mbdata_completed = false;
+ brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
+
+ wait_event_timeout(devinfo->mbdata_resp_wait,
+ devinfo->mbdata_completed,
+ msecs_to_jiffies(BRCMF_PCIE_MBDATA_TIMEOUT));
+ if (!devinfo->mbdata_completed) {
+ brcmf_err("Timeout on response for entering D3 substate\n");
+ return -EIO;
+ }
+ brcmf_pcie_release_irq(devinfo);
+
+ err = pci_save_state(pdev);
+ if (err) {
+ brcmf_err("pci_save_state failed, err=%d\n", err);
+ return err;
+ }
+
+ brcmf_chip_detach(devinfo->ci);
+ devinfo->ci = NULL;
+
+ brcmf_pcie_remove(pdev);
+
+ return pci_prepare_to_sleep(pdev);
+}
+
+
+static int brcmf_pcie_resume(struct pci_dev *pdev)
+{
+ int err;
+
+ brcmf_dbg(PCIE, "Enter, pdev=%p\n", pdev);
+
+ err = pci_set_power_state(pdev, PCI_D0);
+ if (err) {
+ brcmf_err("pci_set_power_state failed, err=%d\n", err);
+ return err;
+ }
+ pci_restore_state(pdev);
+
+ err = brcmf_pcie_probe(pdev, NULL);
+ if (err)
+ brcmf_err("probe after resume failed, err=%d\n", err);
+
+ return err;
+}
+
+
+#endif /* CONFIG_PM */
+
+
+#define BRCMF_PCIE_DEVICE(dev_id) { BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
+ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+
+static struct pci_device_id brcmf_pcie_devid_table[] = {
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+ { /* end: all zeroes */ }
+};
+
+
+MODULE_DEVICE_TABLE(pci, brcmf_pcie_devid_table);
+
+
+static struct pci_driver brcmf_pciedrvr = {
+ .node = {},
+ .name = KBUILD_MODNAME,
+ .id_table = brcmf_pcie_devid_table,
+ .probe = brcmf_pcie_probe,
+ .remove = brcmf_pcie_remove,
+#ifdef CONFIG_PM
+ .suspend = brcmf_pcie_suspend,
+ .resume = brcmf_pcie_resume
+#endif /* CONFIG_PM */
+};
+
+
+void brcmf_pcie_register(void)
+{
+ int err;
+
+ brcmf_dbg(PCIE, "Enter\n");
+ err = pci_register_driver(&brcmf_pciedrvr);
+ if (err)
+ brcmf_err("PCIE driver registration failed, err=%d\n", err);
+}
+
+
+void brcmf_pcie_exit(void)
+{
+ brcmf_dbg(PCIE, "Enter\n");
+ pci_unregister_driver(&brcmf_pciedrvr);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.h b/drivers/net/wireless/brcm80211/brcmfmac/pcie.h
new file mode 100644
index 000000000000..6edaaf8ef5ce
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_PCIE_H
+#define BRCMFMAC_PCIE_H
+
+
+struct brcmf_pciedev {
+ struct brcmf_bus *bus;
+ struct brcmf_pciedev_info *devinfo;
+};
+
+
+void brcmf_pcie_exit(void);
+void brcmf_pcie_register(void);
+
+
+#endif /* BRCMFMAC_PCIE_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
index b6b464184946..62b940723339 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
@@ -21,26 +21,40 @@
#include <brcmu_wifi.h>
#include "dhd.h"
+#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "proto.h"
#include "bcdc.h"
+#include "msgbuf.h"
int brcmf_proto_attach(struct brcmf_pub *drvr)
{
struct brcmf_proto *proto;
+ brcmf_dbg(TRACE, "Enter\n");
+
proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
if (!proto)
goto fail;
drvr->proto = proto;
- /* BCDC protocol is only protocol supported for the moment */
- if (brcmf_proto_bcdc_attach(drvr))
- goto fail;
+ if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) {
+ if (brcmf_proto_bcdc_attach(drvr))
+ goto fail;
+ } else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) {
+ if (brcmf_proto_msgbuf_attach(drvr))
+ goto fail;
+ } else {
+ brcmf_err("Unsupported proto type %d\n",
+ drvr->bus_if->proto_type);
+ goto fail;
+ }
if ((proto->txdata == NULL) || (proto->hdrpull == NULL) ||
- (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) {
+ (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
+ (proto->configure_addr_mode == NULL) ||
+ (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
brcmf_err("Not all proto handlers have been installed\n");
goto fail;
}
@@ -54,8 +68,13 @@ fail:
void brcmf_proto_detach(struct brcmf_pub *drvr)
{
+ brcmf_dbg(TRACE, "Enter\n");
+
if (drvr->proto) {
- brcmf_proto_bcdc_detach(drvr);
+ if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
+ brcmf_proto_bcdc_detach(drvr);
+ else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
+ brcmf_proto_msgbuf_detach(drvr);
kfree(drvr->proto);
drvr->proto = NULL;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
index 482fb0ba4a30..971172ff686c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
@@ -16,6 +16,13 @@
#ifndef BRCMFMAC_PROTO_H
#define BRCMFMAC_PROTO_H
+
+enum proto_addr_mode {
+ ADDR_INDIRECT = 0,
+ ADDR_DIRECT
+};
+
+
struct brcmf_proto {
int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
struct sk_buff *skb);
@@ -25,6 +32,12 @@ struct brcmf_proto {
uint len);
int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *skb);
+ void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
+ enum proto_addr_mode addr_mode);
+ void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
+ u8 peer[ETH_ALEN]);
+ void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
+ u8 peer[ETH_ALEN]);
void *pd;
};
@@ -48,10 +61,26 @@ static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
}
static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
- u8 offset, struct sk_buff *skb)
+ u8 offset, struct sk_buff *skb)
{
return drvr->proto->txdata(drvr, ifidx, offset, skb);
}
+static inline void
+brcmf_proto_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+ enum proto_addr_mode addr_mode)
+{
+ drvr->proto->configure_addr_mode(drvr, ifidx, addr_mode);
+}
+static inline void
+brcmf_proto_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+ drvr->proto->delete_peer(drvr, ifidx, peer);
+}
+static inline void
+brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+ drvr->proto->add_tdls_peer(drvr, ifidx, peer);
+}
#endif /* BRCMFMAC_PROTO_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 3deab7959a0d..f2d06cae366a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -18,6 +18,8 @@
#define _BRCM_SDH_H_
#include <linux/skbuff.h>
+#include <linux/firmware.h>
+#include "firmware.h"
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
@@ -72,12 +74,12 @@
#define SBSDIO_SPROM_DATA_HIGH 0x10003
/* sprom indirect access addr byte 0 */
#define SBSDIO_SPROM_ADDR_LOW 0x10004
-/* sprom indirect access addr byte 0 */
-#define SBSDIO_SPROM_ADDR_HIGH 0x10005
-/* xtal_pu (gpio) output */
-#define SBSDIO_CHIP_CTRL_DATA 0x10006
-/* xtal_pu (gpio) enable */
-#define SBSDIO_CHIP_CTRL_EN 0x10007
+/* gpio select */
+#define SBSDIO_GPIO_SELECT 0x10005
+/* gpio output */
+#define SBSDIO_GPIO_OUT 0x10006
+/* gpio enable */
+#define SBSDIO_GPIO_EN 0x10007
/* rev < 7, watermark for sdio device */
#define SBSDIO_WATERMARK 0x10008
/* control busy signal generation */
@@ -182,6 +184,8 @@ struct brcmf_sdio_dev {
uint max_segment_size;
uint txglomsz;
struct sg_table sgtable;
+ char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
+ char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
};
/* sdio core registers */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index d06fcb05adf2..dc135915470d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
#include <dhd_bus.h>
#include <dhd_dbg.h>
@@ -29,32 +30,24 @@
#include "usb_rdl.h"
#include "usb.h"
-#define IOCTL_RESP_TIMEOUT 2000
+#define IOCTL_RESP_TIMEOUT 2000
#define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */
#define BRCMF_USB_RESET_GETVER_LOOP_CNT 10
#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle
has boot up */
-#define BRCMF_USB_NRXQ 50
-#define BRCMF_USB_NTXQ 50
+#define BRCMF_USB_NRXQ 50
+#define BRCMF_USB_NTXQ 50
-#define CONFIGDESC(usb) (&((usb)->actconfig)->desc)
-#define IFPTR(usb, idx) ((usb)->actconfig->interface[(idx)])
-#define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0])
-#define IFDESC(usb, idx) IFALTS((usb), (idx)).desc
-#define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[(ep)]).desc
+#define BRCMF_USB_CBCTL_WRITE 0
+#define BRCMF_USB_CBCTL_READ 1
+#define BRCMF_USB_MAX_PKT_SIZE 1600
-#define CONTROL_IF 0
-#define BULK_IF 0
-
-#define BRCMF_USB_CBCTL_WRITE 0
-#define BRCMF_USB_CBCTL_READ 1
-#define BRCMF_USB_MAX_PKT_SIZE 1600
-
-#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin"
-#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
-#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
+#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin"
+#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
+#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
+#define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin"
struct brcmf_usb_image {
struct list_head list;
@@ -70,7 +63,7 @@ struct brcmf_usbdev_info {
struct list_head rx_postq;
struct list_head tx_freeq;
struct list_head tx_postq;
- uint rx_pipe, tx_pipe, rx_pipe2;
+ uint rx_pipe, tx_pipe;
int rx_low_watermark;
int tx_low_watermark;
@@ -97,6 +90,7 @@ struct brcmf_usbdev_info {
int ctl_completed;
wait_queue_head_t ioctl_resp_wait;
ulong ctl_op;
+ u8 ifnum;
struct urb *bulk_urb; /* used for FW download */
};
@@ -576,7 +570,6 @@ fail:
static int brcmf_usb_up(struct device *dev)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
- u16 ifnum;
brcmf_dbg(USB, "Enter\n");
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
@@ -589,21 +582,19 @@ static int brcmf_usb_up(struct device *dev)
devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
- ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber;
-
/* CTL Write */
devinfo->ctl_write.bRequestType =
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
devinfo->ctl_write.bRequest = 0;
devinfo->ctl_write.wValue = cpu_to_le16(0);
- devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum);
+ devinfo->ctl_write.wIndex = cpu_to_le16(devinfo->ifnum);
/* CTL Read */
devinfo->ctl_read.bRequestType =
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
devinfo->ctl_read.bRequest = 1;
devinfo->ctl_read.wValue = cpu_to_le16(0);
- devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum);
+ devinfo->ctl_read.wIndex = cpu_to_le16(devinfo->ifnum);
}
brcmf_usb_rx_fill_all(devinfo);
return 0;
@@ -642,19 +633,19 @@ brcmf_usb_sync_complete(struct urb *urb)
brcmf_usb_ioctl_resp_wake(devinfo);
}
-static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
- void *buffer, int buflen)
+static int brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
+ void *buffer, int buflen)
{
- int ret = 0;
+ int ret;
char *tmpbuf;
u16 size;
if ((!devinfo) || (devinfo->ctl_urb == NULL))
- return false;
+ return -EINVAL;
tmpbuf = kmalloc(buflen, GFP_ATOMIC);
if (!tmpbuf)
- return false;
+ return -ENOMEM;
size = buflen;
devinfo->ctl_urb->transfer_buffer_length = size;
@@ -675,14 +666,16 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
if (ret < 0) {
brcmf_err("usb_submit_urb failed %d\n", ret);
- kfree(tmpbuf);
- return false;
+ goto finalize;
}
- ret = brcmf_usb_ioctl_resp_wait(devinfo);
- memcpy(buffer, tmpbuf, buflen);
- kfree(tmpbuf);
+ if (!brcmf_usb_ioctl_resp_wait(devinfo))
+ ret = -ETIMEDOUT;
+ else
+ memcpy(buffer, tmpbuf, buflen);
+finalize:
+ kfree(tmpbuf);
return ret;
}
@@ -724,6 +717,7 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
{
struct bootrom_id_le id;
u32 loop_cnt;
+ int err;
brcmf_dbg(USB, "Enter\n");
@@ -732,7 +726,9 @@ brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
loop_cnt++;
id.chip = cpu_to_le32(0xDEAD); /* Get the ID */
- brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+ err = brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+ if ((err) && (err != -ETIMEDOUT))
+ return err;
if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
break;
} while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
@@ -794,8 +790,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
}
/* 1) Prepare USB boot loader for runtime image */
- brcmf_usb_dl_cmd(devinfo, DL_START, &state,
- sizeof(struct rdl_state_le));
+ brcmf_usb_dl_cmd(devinfo, DL_START, &state, sizeof(state));
rdlstate = le32_to_cpu(state.state);
rdlbytes = le32_to_cpu(state.bytes);
@@ -839,10 +834,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
dlpos += sendlen;
sent += sendlen;
}
- if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
- sizeof(struct rdl_state_le))) {
- brcmf_err("DL_GETSTATE Failed xxxx\n");
- err = -EINVAL;
+ err = brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
+ sizeof(state));
+ if (err) {
+ brcmf_err("DL_GETSTATE Failed\n");
goto fail;
}
@@ -898,13 +893,12 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
return -EINVAL;
/* Check we are runnable */
- brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
- sizeof(struct rdl_state_le));
+ state.state = 0;
+ brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, sizeof(state));
/* Start the image */
if (state.state == cpu_to_le32(DL_RUNNABLE)) {
- if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state,
- sizeof(struct rdl_state_le)))
+ if (brcmf_usb_dl_cmd(devinfo, DL_GO, &state, sizeof(state)))
return -ENODEV;
if (brcmf_usb_resetcfg(devinfo))
return -ENODEV;
@@ -920,13 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
static bool brcmf_usb_chip_support(int chipid, int chiprev)
{
switch(chipid) {
- case 43143:
+ case BRCM_CC_43143_CHIP_ID:
return true;
- case 43235:
- case 43236:
- case 43238:
+ case BRCM_CC_43235_CHIP_ID:
+ case BRCM_CC_43236_CHIP_ID:
+ case BRCM_CC_43238_CHIP_ID:
return (chiprev == 3);
- case 43242:
+ case BRCM_CC_43242_CHIP_ID:
+ return true;
+ case BRCM_CC_43566_CHIP_ID:
+ case BRCM_CC_43569_CHIP_ID:
return true;
default:
break;
@@ -1020,14 +1017,17 @@ static int check_file(const u8 *headers)
static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
{
switch (devinfo->bus_pub.devid) {
- case 43143:
+ case BRCM_CC_43143_CHIP_ID:
return BRCMF_USB_43143_FW_NAME;
- case 43235:
- case 43236:
- case 43238:
+ case BRCM_CC_43235_CHIP_ID:
+ case BRCM_CC_43236_CHIP_ID:
+ case BRCM_CC_43238_CHIP_ID:
return BRCMF_USB_43236_FW_NAME;
- case 43242:
+ case BRCM_CC_43242_CHIP_ID:
return BRCMF_USB_43242_FW_NAME;
+ case BRCM_CC_43566_CHIP_ID:
+ case BRCM_CC_43569_CHIP_ID:
+ return BRCMF_USB_43569_FW_NAME;
default:
return NULL;
}
@@ -1222,15 +1222,15 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
static int
brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- int ep;
- struct usb_endpoint_descriptor *endpoint;
- int ret = 0;
struct usb_device *usb = interface_to_usbdev(intf);
- int num_of_eps;
- u8 endpoint_num;
struct brcmf_usbdev_info *devinfo;
+ struct usb_interface_descriptor *desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int ret = 0;
+ u32 num_of_eps;
+ u8 endpoint_num, ep;
- brcmf_dbg(USB, "Enter\n");
+ brcmf_dbg(USB, "Enter 0x%04x:0x%04x\n", id->idVendor, id->idProduct);
devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
if (devinfo == NULL)
@@ -1238,92 +1238,71 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
devinfo->usbdev = usb;
devinfo->dev = &usb->dev;
-
usb_set_intfdata(intf, devinfo);
/* Check that the device supports only one configuration */
if (usb->descriptor.bNumConfigurations != 1) {
- ret = -1;
- goto fail;
- }
-
- if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
- ret = -1;
+ brcmf_err("Number of configurations: %d not supported\n",
+ usb->descriptor.bNumConfigurations);
+ ret = -ENODEV;
goto fail;
}
- /*
- * Only the BDC interface configuration is supported:
- * Device class: USB_CLASS_VENDOR_SPEC
- * if0 class: USB_CLASS_VENDOR_SPEC
- * if0/ep0: control
- * if0/ep1: bulk in
- * if0/ep2: bulk out (ok if swapped with bulk in)
- */
- if (CONFIGDESC(usb)->bNumInterfaces != 1) {
- ret = -1;
+ if ((usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) &&
+ (usb->descriptor.bDeviceClass != USB_CLASS_MISC) &&
+ (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS_CONTROLLER)) {
+ brcmf_err("Device class: 0x%x not supported\n",
+ usb->descriptor.bDeviceClass);
+ ret = -ENODEV;
goto fail;
}
- /* Check interface */
- if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
- IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
- IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
- brcmf_err("invalid control interface: class %d, subclass %d, proto %d\n",
- IFDESC(usb, CONTROL_IF).bInterfaceClass,
- IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
- IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
- ret = -1;
+ desc = &intf->altsetting[0].desc;
+ if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+ (desc->bInterfaceSubClass != 2) ||
+ (desc->bInterfaceProtocol != 0xff)) {
+ brcmf_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n",
+ desc->bInterfaceNumber, desc->bInterfaceClass,
+ desc->bInterfaceSubClass, desc->bInterfaceProtocol);
+ ret = -ENODEV;
goto fail;
}
- /* Check control endpoint */
- endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_INT) {
- brcmf_err("invalid control endpoint %d\n",
- endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
- ret = -1;
- goto fail;
- }
-
- devinfo->rx_pipe = 0;
- devinfo->rx_pipe2 = 0;
- devinfo->tx_pipe = 0;
- num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
-
- /* Check data endpoints and get pipes */
- for (ep = 1; ep <= num_of_eps; ep++) {
- endpoint = &IFEPDESC(usb, BULK_IF, ep);
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
- USB_ENDPOINT_XFER_BULK) {
- brcmf_err("invalid data endpoint %d\n", ep);
- ret = -1;
- goto fail;
- }
-
- endpoint_num = endpoint->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_IN) {
- if (!devinfo->rx_pipe) {
+ num_of_eps = desc->bNumEndpoints;
+ for (ep = 0; ep < num_of_eps; ep++) {
+ endpoint = &intf->altsetting[0].endpoint[ep].desc;
+ endpoint_num = usb_endpoint_num(endpoint);
+ if (!usb_endpoint_xfer_bulk(endpoint))
+ continue;
+ if (usb_endpoint_dir_in(endpoint)) {
+ if (!devinfo->rx_pipe)
devinfo->rx_pipe =
usb_rcvbulkpipe(usb, endpoint_num);
- } else {
- devinfo->rx_pipe2 =
- usb_rcvbulkpipe(usb, endpoint_num);
- }
} else {
- devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num);
+ if (!devinfo->tx_pipe)
+ devinfo->tx_pipe =
+ usb_sndbulkpipe(usb, endpoint_num);
}
}
+ if (devinfo->rx_pipe == 0) {
+ brcmf_err("No RX (in) Bulk EP found\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+ if (devinfo->tx_pipe == 0) {
+ brcmf_err("No TX (out) Bulk EP found\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ devinfo->ifnum = desc->bInterfaceNumber;
if (usb->speed == USB_SPEED_SUPER)
- brcmf_dbg(USB, "Broadcom super speed USB wireless device detected\n");
+ brcmf_dbg(USB, "Broadcom super speed USB WLAN interface detected\n");
else if (usb->speed == USB_SPEED_HIGH)
- brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
+ brcmf_dbg(USB, "Broadcom high speed USB WLAN interface detected\n");
else
- brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
+ brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n");
ret = brcmf_usb_probe_cb(devinfo);
if (ret)
@@ -1333,11 +1312,9 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0;
fail:
- brcmf_err("failed with errno %d\n", ret);
kfree(devinfo);
usb_set_intfdata(intf, NULL);
return ret;
-
}
static void
@@ -1382,6 +1359,7 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
{
struct usb_device *usb = interface_to_usbdev(intf);
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
brcmf_dbg(USB, "Enter\n");
return brcmf_fw_get_firmwares(&usb->dev, 0,
@@ -1389,25 +1367,24 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
brcmf_usb_probe_phase2);
}
-#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
-#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
-#define BRCMF_USB_DEVICE_ID_43236 0xbd17
-#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
-#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
+#define BRCMF_USB_DEVICE(dev_id) \
+ { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
static struct usb_device_id brcmf_usb_devid_table[] = {
- { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) },
- { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
- { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) },
+ BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
+ BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
/* special entry for device with firmware loaded and running */
- { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
- { }
+ BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
+ { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
+MODULE_FIRMWARE(BRCMF_USB_43569_FW_NAME);
static struct usb_driver brcmf_usbdrvr = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
new file mode 100644
index 000000000000..5960d827508c
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include <brcmu_wifi.h>
+#include "fwil_types.h"
+#include "dhd.h"
+#include "p2p.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
+#include "vendor.h"
+#include "fwil.h"
+
+static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int len)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg);
+ const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
+ struct sk_buff *reply;
+ int ret, payload, ret_len;
+ void *dcmd_buf = NULL, *wr_pointer;
+ u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
+
+ brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
+ cmdhdr->len);
+
+ len -= sizeof(struct brcmf_vndr_dcmd_hdr);
+ ret_len = cmdhdr->len;
+ if (ret_len > 0 || len > 0) {
+ if (len > BRCMF_DCMD_MAXLEN) {
+ brcmf_err("oversize input buffer %d\n", len);
+ len = BRCMF_DCMD_MAXLEN;
+ }
+ if (ret_len > BRCMF_DCMD_MAXLEN) {
+ brcmf_err("oversize return buffer %d\n", ret_len);
+ ret_len = BRCMF_DCMD_MAXLEN;
+ }
+ payload = max(ret_len, len) + 1;
+ dcmd_buf = vzalloc(payload);
+ if (NULL == dcmd_buf)
+ return -ENOMEM;
+
+ memcpy(dcmd_buf, (void *)cmdhdr + cmdhdr->offset, len);
+ *(char *)(dcmd_buf + len) = '\0';
+ }
+
+ if (cmdhdr->set)
+ ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), cmdhdr->cmd,
+ dcmd_buf, ret_len);
+ else
+ ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), cmdhdr->cmd,
+ dcmd_buf, ret_len);
+ if (ret != 0)
+ goto exit;
+
+ wr_pointer = dcmd_buf;
+ while (ret_len > 0) {
+ msglen = ret_len > maxmsglen ? maxmsglen : ret_len;
+ ret_len -= msglen;
+ payload = msglen + sizeof(msglen);
+ reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
+ if (NULL == reply) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ if (nla_put(reply, BRCMF_NLATTR_DATA, msglen, wr_pointer) ||
+ nla_put_u16(reply, BRCMF_NLATTR_LEN, msglen)) {
+ kfree_skb(reply);
+ ret = -ENOBUFS;
+ break;
+ }
+
+ ret = cfg80211_vendor_cmd_reply(reply);
+ if (ret)
+ break;
+
+ wr_pointer += msglen;
+ }
+
+exit:
+ vfree(dcmd_buf);
+
+ return ret;
+}
+
+const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
+ {
+ {
+ .vendor_id = BROADCOM_OUI,
+ .subcmd = BRCMF_VNDR_CMDS_DCMD
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV,
+ .doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
+ },
+};
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.h b/drivers/net/wireless/brcm80211/brcmfmac/vendor.h
new file mode 100644
index 000000000000..061b7bfa2e1c
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _vendor_h_
+#define _vendor_h_
+
+#define BROADCOM_OUI 0x001018
+
+enum brcmf_vndr_cmds {
+ BRCMF_VNDR_CMDS_UNSPEC,
+ BRCMF_VNDR_CMDS_DCMD,
+ BRCMF_VNDR_CMDS_LAST
+};
+
+/**
+ * enum brcmf_nlattrs - nl80211 message attributes
+ *
+ * @BRCMF_NLATTR_LEN: message body length
+ * @BRCMF_NLATTR_DATA: message body
+ */
+enum brcmf_nlattrs {
+ BRCMF_NLATTR_UNSPEC,
+
+ BRCMF_NLATTR_LEN,
+ BRCMF_NLATTR_DATA,
+
+ __BRCMF_NLATTR_AFTER_LAST,
+ BRCMF_NLATTR_MAX = __BRCMF_NLATTR_AFTER_LAST - 1
+};
+
+/**
+ * struct brcmf_vndr_dcmd_hdr - message header for cfg80211 vendor command dcmd
+ * support
+ *
+ * @cmd: common dongle cmd definition
+ * @len: length of expecting return buffer
+ * @offset: offset of data buffer
+ * @set: get or set request(optional)
+ * @magic: magic number for verification
+ */
+struct brcmf_vndr_dcmd_hdr {
+ uint cmd;
+ int len;
+ uint offset;
+ uint set;
+ uint magic;
+};
+
+extern const struct wiphy_vendor_command brcmf_vendor_cmds[];
+
+#endif /* _vendor_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index d8fa276e368b..02fe706fc9ec 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/vmalloc.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
@@ -32,7 +33,10 @@
#include "p2p.h"
#include "btcoex.h"
#include "wl_cfg80211.h"
+#include "feature.h"
#include "fwil.h"
+#include "proto.h"
+#include "vendor.h"
#define BRCMF_SCAN_IE_LEN_MAX 2048
#define BRCMF_PNO_VERSION 2
@@ -100,24 +104,6 @@ static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
return true;
}
-#define CHAN2G(_channel, _freq, _flags) { \
- .band = IEEE80211_BAND_2GHZ, \
- .center_freq = (_freq), \
- .hw_value = (_channel), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
-#define CHAN5G(_channel, _flags) { \
- .band = IEEE80211_BAND_5GHZ, \
- .center_freq = 5000 + (5 * (_channel)), \
- .hw_value = (_channel), \
- .flags = (_flags), \
- .max_antenna_gain = 0, \
- .max_power = 30, \
-}
-
#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
#define RATETAB_ENT(_rateid, _flags) \
{ \
@@ -146,58 +132,17 @@ static struct ieee80211_rate __wl_rates[] = {
#define wl_g_rates (__wl_rates + 0)
#define wl_g_rates_size 12
-static struct ieee80211_channel __wl_2ghz_channels[] = {
- CHAN2G(1, 2412, 0),
- CHAN2G(2, 2417, 0),
- CHAN2G(3, 2422, 0),
- CHAN2G(4, 2427, 0),
- CHAN2G(5, 2432, 0),
- CHAN2G(6, 2437, 0),
- CHAN2G(7, 2442, 0),
- CHAN2G(8, 2447, 0),
- CHAN2G(9, 2452, 0),
- CHAN2G(10, 2457, 0),
- CHAN2G(11, 2462, 0),
- CHAN2G(12, 2467, 0),
- CHAN2G(13, 2472, 0),
- CHAN2G(14, 2484, 0),
-};
-
-static struct ieee80211_channel __wl_5ghz_a_channels[] = {
- CHAN5G(34, 0), CHAN5G(36, 0),
- CHAN5G(38, 0), CHAN5G(40, 0),
- CHAN5G(42, 0), CHAN5G(44, 0),
- CHAN5G(46, 0), CHAN5G(48, 0),
- CHAN5G(52, 0), CHAN5G(56, 0),
- CHAN5G(60, 0), CHAN5G(64, 0),
- CHAN5G(100, 0), CHAN5G(104, 0),
- CHAN5G(108, 0), CHAN5G(112, 0),
- CHAN5G(116, 0), CHAN5G(120, 0),
- CHAN5G(124, 0), CHAN5G(128, 0),
- CHAN5G(132, 0), CHAN5G(136, 0),
- CHAN5G(140, 0), CHAN5G(149, 0),
- CHAN5G(153, 0), CHAN5G(157, 0),
- CHAN5G(161, 0), CHAN5G(165, 0),
- CHAN5G(184, 0), CHAN5G(188, 0),
- CHAN5G(192, 0), CHAN5G(196, 0),
- CHAN5G(200, 0), CHAN5G(204, 0),
- CHAN5G(208, 0), CHAN5G(212, 0),
- CHAN5G(216, 0),
-};
-
-static struct ieee80211_supported_band __wl_band_2ghz = {
+/* Band templates duplicated per wiphy. The channel info
+ * is filled in after querying the device.
+ */
+static const struct ieee80211_supported_band __wl_band_2ghz = {
.band = IEEE80211_BAND_2GHZ,
- .channels = __wl_2ghz_channels,
- .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
.bitrates = wl_g_rates,
.n_bitrates = wl_g_rates_size,
- .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true},
};
-static struct ieee80211_supported_band __wl_band_5ghz_a = {
+static const struct ieee80211_supported_band __wl_band_5ghz_a = {
.band = IEEE80211_BAND_5GHZ,
- .channels = __wl_5ghz_a_channels,
- .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
.bitrates = wl_a_rates,
.n_bitrates = wl_a_rates_size,
};
@@ -549,6 +494,22 @@ brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable)
return err;
}
+static void
+brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
+{
+ struct net_device *ndev = wdev->netdev;
+ struct brcmf_if *ifp = netdev_priv(ndev);
+
+ if ((wdev->iftype == NL80211_IFTYPE_ADHOC) ||
+ (wdev->iftype == NL80211_IFTYPE_AP) ||
+ (wdev->iftype == NL80211_IFTYPE_P2P_GO))
+ brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+ ADDR_DIRECT);
+ else
+ brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+ ADDR_INDIRECT);
+}
+
static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
{
enum nl80211_iftype iftype;
@@ -568,6 +529,8 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
u32 *flags,
struct vif_params *params)
{
+ struct wireless_dev *wdev;
+
brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
switch (type) {
case NL80211_IFTYPE_ADHOC:
@@ -581,13 +544,22 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
- return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
+ wdev = brcmf_p2p_add_vif(wiphy, name, type, flags, params);
+ if (!IS_ERR(wdev))
+ brcmf_cfg80211_update_proto_addr_mode(wdev);
+ return wdev;
case NL80211_IFTYPE_UNSPECIFIED:
default:
return ERR_PTR(-EINVAL);
}
}
+static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
+{
+ if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC))
+ brcmf_set_mpc(ifp, mpc);
+}
+
void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
{
s32 err = 0;
@@ -641,7 +613,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
brcmf_err("Scan abort failed\n");
}
- brcmf_set_mpc(ifp, 1);
+ brcmf_scan_config_mpc(ifp, 1);
/*
* e-scan can be initiated by scheduled scan
@@ -770,6 +742,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
}
ndev->ieee80211_ptr->iftype = type;
+ brcmf_cfg80211_update_proto_addr_mode(&vif->wdev);
+
done:
brcmf_dbg(TRACE, "Exit\n");
@@ -920,7 +894,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
brcmf_err("error (%d)\n", err);
return err;
}
- brcmf_set_mpc(ifp, 0);
+ brcmf_scan_config_mpc(ifp, 0);
results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
results->version = 0;
results->count = 0;
@@ -928,7 +902,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START);
if (err)
- brcmf_set_mpc(ifp, 1);
+ brcmf_scan_config_mpc(ifp, 1);
return err;
}
@@ -1019,7 +993,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
goto scan_out;
}
- brcmf_set_mpc(ifp, 0);
+ brcmf_scan_config_mpc(ifp, 0);
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&sr->ssid_le, sizeof(sr->ssid_le));
if (err) {
@@ -1029,7 +1003,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
else
brcmf_err("WLC_SCAN error (%d)\n", err);
- brcmf_set_mpc(ifp, 1);
+ brcmf_scan_config_mpc(ifp, 1);
goto scan_out;
}
}
@@ -1331,7 +1305,6 @@ static s32
brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
- s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
@@ -1341,7 +1314,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
brcmf_dbg(TRACE, "Exit\n");
- return err;
+ return 0;
}
static s32 brcmf_set_wpa_version(struct net_device *ndev,
@@ -1612,17 +1585,10 @@ static
enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
enum nl80211_auth_type type)
{
- u32 ci;
- if (type == NL80211_AUTHTYPE_AUTOMATIC) {
- /* shift to ignore chip revision */
- ci = brcmf_get_chip_info(ifp) >> 4;
- switch (ci) {
- case 43236:
- brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n");
- return NL80211_AUTHTYPE_OPEN_SYSTEM;
- default:
- break;
- }
+ if (type == NL80211_AUTHTYPE_AUTOMATIC &&
+ brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) {
+ brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n");
+ type = NL80211_AUTHTYPE_OPEN_SYSTEM;
}
return type;
}
@@ -2388,7 +2354,6 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
struct cfg80211_bss *bss;
struct ieee80211_supported_band *band;
struct brcmu_chan ch;
- s32 err = 0;
u16 channel;
u32 freq;
u16 notify_capability;
@@ -2438,7 +2403,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
cfg80211_put_bss(wiphy, bss);
- return err;
+ return 0;
}
static struct brcmf_bss_info_le *
@@ -2690,7 +2655,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
s32 status;
- s32 err = 0;
struct brcmf_escan_result_le *escan_result_le;
struct brcmf_bss_info_le *bss_info_le;
struct brcmf_bss_info_le *bss = NULL;
@@ -2781,7 +2745,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
status);
}
exit:
- return err;
+ return 0;
}
static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
@@ -3260,35 +3224,6 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
return 0;
}
-#ifdef CONFIG_NL80211_TESTMODE
-static int brcmf_cfg80211_testmode(struct wiphy *wiphy,
- struct wireless_dev *wdev,
- void *data, int len)
-{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = cfg_to_ndev(cfg);
- struct brcmf_dcmd *dcmd = data;
- struct sk_buff *reply;
- int ret;
-
- brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
- dcmd->buf, dcmd->len);
-
- if (dcmd->set)
- ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
- dcmd->buf, dcmd->len);
- else
- ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
- dcmd->buf, dcmd->len);
- if (ret == 0) {
- reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
- nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
- ret = cfg80211_testmode_reply(reply);
- }
- return ret;
-}
-#endif
-
static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
{
s32 err;
@@ -3507,7 +3442,6 @@ static s32
brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
struct parsed_vndr_ies *vndr_ies)
{
- s32 err = 0;
struct brcmf_vs_tlv *vndrie;
struct brcmf_tlv *ie;
struct parsed_vndr_ie_info *parsed_info;
@@ -3560,7 +3494,7 @@ next:
ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
TLV_HDR_LEN);
}
- return err;
+ return 0;
}
static u32
@@ -4221,6 +4155,27 @@ static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
}
+static s32
+brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e, void *data)
+{
+ switch (e->reason) {
+ case BRCMF_E_REASON_TDLS_PEER_DISCOVERED:
+ brcmf_dbg(TRACE, "TDLS Peer Discovered\n");
+ break;
+ case BRCMF_E_REASON_TDLS_PEER_CONNECTED:
+ brcmf_dbg(TRACE, "TDLS Peer Connected\n");
+ brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+ break;
+ case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:
+ brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");
+ brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+ break;
+ }
+
+ return 0;
+}
+
static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
{
int ret;
@@ -4307,120 +4262,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.crit_proto_start = brcmf_cfg80211_crit_proto_start,
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
.tdls_oper = brcmf_cfg80211_tdls_oper,
- CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode)
};
-static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
-{
- /* scheduled scan settings */
- wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
- wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
- wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
- wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-}
-
-static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
- {
- .max = 2,
- .types = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_AP)
- },
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO)
- },
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
- }
-};
-static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
- {
- .max_interfaces = BRCMF_IFACE_MAX_CNT,
- .num_different_channels = 2,
- .n_limits = ARRAY_SIZE(brcmf_iface_limits),
- .limits = brcmf_iface_limits
- }
-};
-
-static const struct ieee80211_txrx_stypes
-brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
- [NL80211_IFTYPE_STATION] = {
- .tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
- },
- [NL80211_IFTYPE_P2P_CLIENT] = {
- .tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
- },
- [NL80211_IFTYPE_P2P_GO] = {
- .tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
- BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
- BIT(IEEE80211_STYPE_DISASSOC >> 4) |
- BIT(IEEE80211_STYPE_AUTH >> 4) |
- BIT(IEEE80211_STYPE_DEAUTH >> 4) |
- BIT(IEEE80211_STYPE_ACTION >> 4)
- },
- [NL80211_IFTYPE_P2P_DEVICE] = {
- .tx = 0xffff,
- .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
- }
-};
-
-static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
-{
- struct wiphy *wiphy;
- s32 err = 0;
-
- wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
- if (!wiphy) {
- brcmf_err("Could not allocate wiphy device\n");
- return ERR_PTR(-ENOMEM);
- }
- set_wiphy_dev(wiphy, phydev);
- wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
- wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
- wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO) |
- BIT(NL80211_IFTYPE_P2P_DEVICE);
- wiphy->iface_combinations = brcmf_iface_combos;
- wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
- wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
- wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
- wiphy->cipher_suites = __wl_cipher_suites;
- wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
- wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
- WIPHY_FLAG_OFFCHAN_TX |
- WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
- WIPHY_FLAG_SUPPORTS_TDLS;
- if (!brcmf_roamoff)
- wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
- wiphy->mgmt_stypes = brcmf_txrx_stypes;
- wiphy->max_remain_on_channel_duration = 5000;
- brcmf_wiphy_pno_params(wiphy);
- brcmf_dbg(INFO, "Registering custom regulatory\n");
- wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
- wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
- err = wiphy_register(wiphy);
- if (err < 0) {
- brcmf_err("Could not register wiphy device (%d)\n", err);
- wiphy_free(wiphy);
- return ERR_PTR(err);
- }
- return wiphy;
-}
-
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype type,
bool pm_block)
@@ -4650,7 +4493,6 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
- s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -4676,7 +4518,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
completed ? "succeeded" : "failed");
}
brcmf_dbg(TRACE, "Exit\n");
- return err;
+ return 0;
}
static s32
@@ -4728,6 +4570,13 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
struct ieee80211_channel *chan;
s32 err = 0;
+ if ((e->event_code == BRCMF_E_DEAUTH) ||
+ (e->event_code == BRCMF_E_DEAUTH_IND) ||
+ (e->event_code == BRCMF_E_DISASSOC_IND) ||
+ ((e->event_code == BRCMF_E_LINK) && (!e->flags))) {
+ brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+ }
+
if (brcmf_is_apmode(ifp->vif)) {
err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
} else if (brcmf_is_linkup(e)) {
@@ -4768,7 +4617,6 @@ brcmf_notify_roaming_status(struct brcmf_if *ifp,
const struct brcmf_event_msg *e, void *data)
{
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
- s32 err = 0;
u32 event = e->event_code;
u32 status = e->status;
@@ -4779,7 +4627,7 @@ brcmf_notify_roaming_status(struct brcmf_if *ifp,
brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
}
- return err;
+ return 0;
}
static s32
@@ -4966,135 +4814,6 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
mutex_init(&event->vif_event_lock);
}
-static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
-{
- struct brcmf_fil_bwcap_le band_bwcap;
- u32 val;
- int err;
-
- /* verify support for bw_cap command */
- val = WLC_BAND_5G;
- err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
-
- if (!err) {
- /* only set 2G bandwidth using bw_cap command */
- band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
- band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
- err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
- sizeof(band_bwcap));
- } else {
- brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
- val = WLC_N_BW_40ALL;
- err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
- }
- return err;
-}
-
-struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
- struct device *busdev)
-{
- struct net_device *ndev = drvr->iflist[0]->ndev;
- struct brcmf_cfg80211_info *cfg;
- struct wiphy *wiphy;
- struct brcmf_cfg80211_vif *vif;
- struct brcmf_if *ifp;
- s32 err = 0;
- s32 io_type;
-
- if (!ndev) {
- brcmf_err("ndev is invalid\n");
- return NULL;
- }
-
- ifp = netdev_priv(ndev);
- wiphy = brcmf_setup_wiphy(busdev);
- if (IS_ERR(wiphy))
- return NULL;
-
- cfg = wiphy_priv(wiphy);
- cfg->wiphy = wiphy;
- cfg->pub = drvr;
- init_vif_event(&cfg->vif_event);
- INIT_LIST_HEAD(&cfg->vif_list);
-
- vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
- if (IS_ERR(vif)) {
- wiphy_free(wiphy);
- return NULL;
- }
-
- vif->ifp = ifp;
- vif->wdev.netdev = ndev;
- ndev->ieee80211_ptr = &vif->wdev;
- SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
-
- err = wl_init_priv(cfg);
- if (err) {
- brcmf_err("Failed to init iwm_priv (%d)\n", err);
- goto cfg80211_attach_out;
- }
- ifp->vif = vif;
-
- err = brcmf_p2p_attach(cfg);
- if (err) {
- brcmf_err("P2P initilisation failed (%d)\n", err);
- goto cfg80211_p2p_attach_out;
- }
- err = brcmf_btcoex_attach(cfg);
- if (err) {
- brcmf_err("BT-coex initialisation failed (%d)\n", err);
- brcmf_p2p_detach(&cfg->p2p);
- goto cfg80211_p2p_attach_out;
- }
-
- /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
- * setup 40MHz in 2GHz band and enable OBSS scanning.
- */
- if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap &
- IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
- err = brcmf_enable_bw40_2g(ifp);
- if (!err)
- err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
- BRCMF_OBSS_COEX_AUTO);
- }
-
- err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
- if (err) {
- brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
- wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
- }
-
- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
- &io_type);
- if (err) {
- brcmf_err("Failed to get D11 version (%d)\n", err);
- goto cfg80211_p2p_attach_out;
- }
- cfg->d11inf.io_type = (u8)io_type;
- brcmu_d11_attach(&cfg->d11inf);
-
- return cfg;
-
-cfg80211_p2p_attach_out:
- wl_deinit_priv(cfg);
-
-cfg80211_attach_out:
- brcmf_free_vif(vif);
- return NULL;
-}
-
-void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
-{
- if (!cfg)
- return;
-
- WARN_ON(!list_empty(&cfg->vif_list));
- wiphy_unregister(cfg->wiphy);
- brcmf_btcoex_detach(cfg);
- wl_deinit_priv(cfg);
- wiphy_free(cfg->wiphy);
-}
-
static s32
brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
{
@@ -5187,25 +4906,77 @@ dongle_scantime_out:
return err;
}
+/* Filter the list of channels received from firmware counting only
+ * the 20MHz channels. The wiphy band data only needs those which get
+ * flagged to indicate if they can take part in higher bandwidth.
+ */
+static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_chanspec_list *chlist,
+ u32 chcnt[])
+{
+ u32 total = le32_to_cpu(chlist->count);
+ struct brcmu_chan ch;
+ int i;
+
+ for (i = 0; i <= total; i++) {
+ ch.chspec = (u16)le32_to_cpu(chlist->element[i]);
+ cfg->d11inf.decchspec(&ch);
+
+ /* Firmware gives a ordered list. We skip non-20MHz
+ * channels is 2G. For 5G we can abort upon reaching
+ * a non-20MHz channel in the list.
+ */
+ if (ch.bw != BRCMU_CHAN_BW_20) {
+ if (ch.band == BRCMU_CHAN_BAND_5G)
+ break;
+ else
+ continue;
+ }
+
+ if (ch.band == BRCMU_CHAN_BAND_2G)
+ chcnt[0] += 1;
+ else if (ch.band == BRCMU_CHAN_BAND_5G)
+ chcnt[1] += 1;
+ }
+}
+
+static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
+ struct brcmu_chan *ch)
+{
+ u32 ht40_flag;
+
+ ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;
+ if (ch->sb == BRCMU_CHAN_SB_U) {
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+ channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
+ } else {
+ /* It should be one of
+ * IEEE80211_CHAN_NO_HT40 or
+ * IEEE80211_CHAN_NO_HT40PLUS
+ */
+ channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+ if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+ channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
+ }
+}
-static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
- u32 bw_cap[])
+static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
+ u32 bw_cap[])
{
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- struct ieee80211_channel *band_chan_arr;
+ struct ieee80211_supported_band *band;
+ struct ieee80211_channel *channel;
+ struct wiphy *wiphy;
struct brcmf_chanspec_list *list;
struct brcmu_chan ch;
- s32 err;
+ int err;
u8 *pbuf;
u32 i, j;
u32 total;
- enum ieee80211_band band;
- u32 channel;
- u32 *n_cnt;
+ u32 chaninfo;
+ u32 chcnt[2] = { 0, 0 };
u32 index;
- u32 ht40_flag;
- bool update;
- u32 array_size;
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
@@ -5218,11 +4989,45 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
BRCMF_DCMD_MEDLEN);
if (err) {
brcmf_err("get chanspecs error (%d)\n", err);
- goto exit;
+ goto fail_pbuf;
}
- __wl_band_2ghz.n_channels = 0;
- __wl_band_5ghz_a.n_channels = 0;
+ brcmf_count_20mhz_channels(cfg, list, chcnt);
+ wiphy = cfg_to_wiphy(cfg);
+ if (chcnt[0]) {
+ band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
+ GFP_KERNEL);
+ if (band == NULL) {
+ err = -ENOMEM;
+ goto fail_pbuf;
+ }
+ band->channels = kcalloc(chcnt[0], sizeof(*channel),
+ GFP_KERNEL);
+ if (band->channels == NULL) {
+ kfree(band);
+ err = -ENOMEM;
+ goto fail_pbuf;
+ }
+ band->n_channels = 0;
+ wiphy->bands[IEEE80211_BAND_2GHZ] = band;
+ }
+ if (chcnt[1]) {
+ band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a),
+ GFP_KERNEL);
+ if (band == NULL) {
+ err = -ENOMEM;
+ goto fail_band2g;
+ }
+ band->channels = kcalloc(chcnt[1], sizeof(*channel),
+ GFP_KERNEL);
+ if (band->channels == NULL) {
+ kfree(band);
+ err = -ENOMEM;
+ goto fail_band2g;
+ }
+ band->n_channels = 0;
+ wiphy->bands[IEEE80211_BAND_5GHZ] = band;
+ }
total = le32_to_cpu(list->count);
for (i = 0; i < total; i++) {
@@ -5230,100 +5035,151 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
cfg->d11inf.decchspec(&ch);
if (ch.band == BRCMU_CHAN_BAND_2G) {
- band_chan_arr = __wl_2ghz_channels;
- array_size = ARRAY_SIZE(__wl_2ghz_channels);
- n_cnt = &__wl_band_2ghz.n_channels;
- band = IEEE80211_BAND_2GHZ;
+ band = wiphy->bands[IEEE80211_BAND_2GHZ];
} else if (ch.band == BRCMU_CHAN_BAND_5G) {
- band_chan_arr = __wl_5ghz_a_channels;
- array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
- n_cnt = &__wl_band_5ghz_a.n_channels;
- band = IEEE80211_BAND_5GHZ;
+ band = wiphy->bands[IEEE80211_BAND_5GHZ];
} else {
brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
continue;
}
- if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
+ if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
ch.bw == BRCMU_CHAN_BW_40)
continue;
- if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
+ if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&
ch.bw == BRCMU_CHAN_BW_80)
continue;
- update = false;
- for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
- if (band_chan_arr[j].hw_value == ch.chnum) {
- update = true;
+
+ channel = band->channels;
+ index = band->n_channels;
+ for (j = 0; j < band->n_channels; j++) {
+ if (channel[j].hw_value == ch.chnum) {
+ index = j;
break;
}
}
- if (update)
- index = j;
- else
- index = *n_cnt;
- if (index < array_size) {
- band_chan_arr[index].center_freq =
- ieee80211_channel_to_frequency(ch.chnum, band);
- band_chan_arr[index].hw_value = ch.chnum;
-
- /* assuming the chanspecs order is HT20,
- * HT40 upper, HT40 lower, and VHT80.
+ channel[index].center_freq =
+ ieee80211_channel_to_frequency(ch.chnum, band->band);
+ channel[index].hw_value = ch.chnum;
+
+ /* assuming the chanspecs order is HT20,
+ * HT40 upper, HT40 lower, and VHT80.
+ */
+ if (ch.bw == BRCMU_CHAN_BW_80) {
+ channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
+ } else if (ch.bw == BRCMU_CHAN_BW_40) {
+ brcmf_update_bw40_channel_flag(&channel[index], &ch);
+ } else {
+ /* disable other bandwidths for now as mentioned
+ * order assure they are enabled for subsequent
+ * chanspecs.
*/
- if (ch.bw == BRCMU_CHAN_BW_80) {
- band_chan_arr[index].flags &=
- ~IEEE80211_CHAN_NO_80MHZ;
- } else if (ch.bw == BRCMU_CHAN_BW_40) {
- ht40_flag = band_chan_arr[index].flags &
- IEEE80211_CHAN_NO_HT40;
- if (ch.sb == BRCMU_CHAN_SB_U) {
- if (ht40_flag == IEEE80211_CHAN_NO_HT40)
- band_chan_arr[index].flags &=
- ~IEEE80211_CHAN_NO_HT40;
- band_chan_arr[index].flags |=
- IEEE80211_CHAN_NO_HT40PLUS;
- } else {
- /* It should be one of
- * IEEE80211_CHAN_NO_HT40 or
- * IEEE80211_CHAN_NO_HT40PLUS
- */
- band_chan_arr[index].flags &=
- ~IEEE80211_CHAN_NO_HT40;
- if (ht40_flag == IEEE80211_CHAN_NO_HT40)
- band_chan_arr[index].flags |=
- IEEE80211_CHAN_NO_HT40MINUS;
- }
- } else {
- /* disable other bandwidths for now as mentioned
- * order assure they are enabled for subsequent
- * chanspecs.
- */
- band_chan_arr[index].flags =
- IEEE80211_CHAN_NO_HT40 |
- IEEE80211_CHAN_NO_80MHZ;
- ch.bw = BRCMU_CHAN_BW_20;
- cfg->d11inf.encchspec(&ch);
- channel = ch.chspec;
- err = brcmf_fil_bsscfg_int_get(ifp,
- "per_chan_info",
- &channel);
- if (!err) {
- if (channel & WL_CHAN_RADAR)
- band_chan_arr[index].flags |=
- (IEEE80211_CHAN_RADAR |
- IEEE80211_CHAN_NO_IR);
- if (channel & WL_CHAN_PASSIVE)
- band_chan_arr[index].flags |=
- IEEE80211_CHAN_NO_IR;
- }
+ channel[index].flags = IEEE80211_CHAN_NO_HT40 |
+ IEEE80211_CHAN_NO_80MHZ;
+ ch.bw = BRCMU_CHAN_BW_20;
+ cfg->d11inf.encchspec(&ch);
+ chaninfo = ch.chspec;
+ err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info",
+ &chaninfo);
+ if (!err) {
+ if (chaninfo & WL_CHAN_RADAR)
+ channel[index].flags |=
+ (IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_NO_IR);
+ if (chaninfo & WL_CHAN_PASSIVE)
+ channel[index].flags |=
+ IEEE80211_CHAN_NO_IR;
}
- if (!update)
- (*n_cnt)++;
}
+ if (index == band->n_channels)
+ band->n_channels++;
}
-exit:
+ kfree(pbuf);
+ return 0;
+
+fail_band2g:
+ kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+ kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+ wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+fail_pbuf:
kfree(pbuf);
return err;
}
+static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+ struct ieee80211_supported_band *band;
+ struct brcmf_fil_bwcap_le band_bwcap;
+ struct brcmf_chanspec_list *list;
+ u8 *pbuf;
+ u32 val;
+ int err;
+ struct brcmu_chan ch;
+ u32 num_chan;
+ int i, j;
+
+ /* verify support for bw_cap command */
+ val = WLC_BAND_5G;
+ err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
+
+ if (!err) {
+ /* only set 2G bandwidth using bw_cap command */
+ band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
+ band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
+ err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
+ sizeof(band_bwcap));
+ } else {
+ brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
+ val = WLC_N_BW_40ALL;
+ err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
+ }
+
+ if (!err) {
+ /* update channel info in 2G band */
+ pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+
+ if (pbuf == NULL)
+ return -ENOMEM;
+
+ ch.band = BRCMU_CHAN_BAND_2G;
+ ch.bw = BRCMU_CHAN_BW_40;
+ ch.chnum = 0;
+ cfg->d11inf.encchspec(&ch);
+
+ /* pass encoded chanspec in query */
+ *(__le16 *)pbuf = cpu_to_le16(ch.chspec);
+
+ err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
+ BRCMF_DCMD_MEDLEN);
+ if (err) {
+ brcmf_err("get chanspecs error (%d)\n", err);
+ kfree(pbuf);
+ return err;
+ }
+
+ band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
+ list = (struct brcmf_chanspec_list *)pbuf;
+ num_chan = le32_to_cpu(list->count);
+ for (i = 0; i < num_chan; i++) {
+ ch.chspec = (u16)le32_to_cpu(list->element[i]);
+ cfg->d11inf.decchspec(&ch);
+ if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))
+ continue;
+ if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
+ continue;
+ for (j = 0; j < band->n_channels; j++) {
+ if (band->channels[j].hw_value == ch.chnum)
+ break;
+ }
+ if (WARN_ON(j == band->n_channels))
+ continue;
+
+ brcmf_update_bw40_channel_flag(&band->channels[j], &ch);
+ }
+ }
+ return err;
+}
+
static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
{
u32 band, mimo_bwcap;
@@ -5414,44 +5270,19 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
}
-static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
+static int brcmf_setup_wiphybands(struct wiphy *wiphy)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- struct wiphy *wiphy;
- s32 phy_list;
- u32 band_list[3];
u32 nmode = 0;
u32 vhtmode = 0;
- u32 bw_cap[2] = { 0, 0 };
+ u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
u32 rxchain;
u32 nchain;
- s8 phy;
- s32 err;
- u32 nband;
+ int err;
s32 i;
- struct ieee80211_supported_band *bands[2] = { NULL, NULL };
struct ieee80211_supported_band *band;
- err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
- &phy_list, sizeof(phy_list));
- if (err) {
- brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
- return err;
- }
-
- phy = ((char *)&phy_list)[0];
- brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
-
-
- err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
- &band_list, sizeof(band_list));
- if (err) {
- brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
- return err;
- }
- brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
- band_list[0], band_list[1], band_list[2]);
-
(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
if (err) {
@@ -5473,44 +5304,129 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
}
brcmf_dbg(INFO, "nchain=%d\n", nchain);
- err = brcmf_construct_reginfo(cfg, bw_cap);
+ err = brcmf_construct_chaninfo(cfg, bw_cap);
if (err) {
- brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
+ brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
return err;
}
- nband = band_list[0];
-
- for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
- band = NULL;
- if ((band_list[i] == WLC_BAND_5G) &&
- (__wl_band_5ghz_a.n_channels > 0))
- band = &__wl_band_5ghz_a;
- else if ((band_list[i] == WLC_BAND_2G) &&
- (__wl_band_2ghz.n_channels > 0))
- band = &__wl_band_2ghz;
- else
+ wiphy = cfg_to_wiphy(cfg);
+ for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
+ band = wiphy->bands[i];
+ if (band == NULL)
continue;
if (nmode)
brcmf_update_ht_cap(band, bw_cap, nchain);
if (vhtmode)
brcmf_update_vht_cap(band, bw_cap, nchain);
- bands[band->band] = band;
}
- wiphy = cfg_to_wiphy(cfg);
- wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
- wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
- wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
-
- return err;
+ return 0;
}
+static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
+ {
+ .max = 2,
+ .types = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP)
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO)
+ },
+ {
+ .max = 1,
+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
+ }
+};
+static struct ieee80211_iface_combination brcmf_iface_combos[] = {
+ {
+ .max_interfaces = BRCMF_IFACE_MAX_CNT,
+ .num_different_channels = 1,
+ .n_limits = ARRAY_SIZE(brcmf_iface_limits),
+ .limits = brcmf_iface_limits
+ }
+};
-static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
+static const struct ieee80211_txrx_stypes
+brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
+ [NL80211_IFTYPE_STATION] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_CLIENT] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ },
+ [NL80211_IFTYPE_P2P_GO] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4) |
+ BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+ BIT(IEEE80211_STYPE_ACTION >> 4)
+ },
+ [NL80211_IFTYPE_P2P_DEVICE] = {
+ .tx = 0xffff,
+ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+ }
+};
+
+static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
{
- return brcmf_update_wiphybands(cfg);
+ /* scheduled scan settings */
+ wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
+ wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+ wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+}
+
+static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+ struct ieee80211_iface_combination ifc_combo;
+ wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+ wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+ wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) |
+ BIT(NL80211_IFTYPE_P2P_DEVICE);
+ /* need VSDB firmware feature for concurrent channels */
+ ifc_combo = brcmf_iface_combos[0];
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+ ifc_combo.num_different_channels = 2;
+ wiphy->iface_combinations = kmemdup(&ifc_combo,
+ sizeof(ifc_combo),
+ GFP_KERNEL);
+ wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wiphy->cipher_suites = __wl_cipher_suites;
+ wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
+ wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
+ WIPHY_FLAG_OFFCHAN_TX |
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+ WIPHY_FLAG_SUPPORTS_TDLS;
+ if (!brcmf_roamoff)
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+ wiphy->mgmt_stypes = brcmf_txrx_stypes;
+ wiphy->max_remain_on_channel_duration = 5000;
+ brcmf_wiphy_pno_params(wiphy);
+
+ /* vendor commands/events support */
+ wiphy->vendor_commands = brcmf_vendor_cmds;
+ wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
+
+ return brcmf_setup_wiphybands(wiphy);
}
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
@@ -5548,9 +5464,6 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
NULL, NULL);
if (err)
goto default_conf_out;
- err = brcmf_dongle_probecap(cfg);
- if (err)
- goto default_conf_out;
brcmf_configure_arp_offload(ifp, true);
@@ -5625,16 +5538,15 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
return wdev->iftype;
}
-u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state)
{
struct brcmf_cfg80211_vif *vif;
- bool result = 0;
list_for_each_entry(vif, &cfg->vif_list, list) {
if (test_bit(state, &vif->sme_state))
- result++;
+ return true;
}
- return result;
+ return false;
}
static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,
@@ -5679,3 +5591,153 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
vif_event_equals(event, action), timeout);
}
+static void brcmf_free_wiphy(struct wiphy *wiphy)
+{
+ kfree(wiphy->iface_combinations);
+ if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+ kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+ kfree(wiphy->bands[IEEE80211_BAND_2GHZ]);
+ }
+ if (wiphy->bands[IEEE80211_BAND_5GHZ]) {
+ kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels);
+ kfree(wiphy->bands[IEEE80211_BAND_5GHZ]);
+ }
+ wiphy_free(wiphy);
+}
+
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+ struct device *busdev)
+{
+ struct net_device *ndev = drvr->iflist[0]->ndev;
+ struct brcmf_cfg80211_info *cfg;
+ struct wiphy *wiphy;
+ struct brcmf_cfg80211_vif *vif;
+ struct brcmf_if *ifp;
+ s32 err = 0;
+ s32 io_type;
+ u16 *cap = NULL;
+
+ if (!ndev) {
+ brcmf_err("ndev is invalid\n");
+ return NULL;
+ }
+
+ ifp = netdev_priv(ndev);
+ wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
+ if (!wiphy) {
+ brcmf_err("Could not allocate wiphy device\n");
+ return NULL;
+ }
+ set_wiphy_dev(wiphy, busdev);
+
+ cfg = wiphy_priv(wiphy);
+ cfg->wiphy = wiphy;
+ cfg->pub = drvr;
+ init_vif_event(&cfg->vif_event);
+ INIT_LIST_HEAD(&cfg->vif_list);
+
+ vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
+ if (IS_ERR(vif))
+ goto wiphy_out;
+
+ vif->ifp = ifp;
+ vif->wdev.netdev = ndev;
+ ndev->ieee80211_ptr = &vif->wdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
+
+ err = wl_init_priv(cfg);
+ if (err) {
+ brcmf_err("Failed to init iwm_priv (%d)\n", err);
+ brcmf_free_vif(vif);
+ goto wiphy_out;
+ }
+ ifp->vif = vif;
+
+ /* determine d11 io type before wiphy setup */
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
+ if (err) {
+ brcmf_err("Failed to get D11 version (%d)\n", err);
+ goto priv_out;
+ }
+ cfg->d11inf.io_type = (u8)io_type;
+ brcmu_d11_attach(&cfg->d11inf);
+
+ err = brcmf_setup_wiphy(wiphy, ifp);
+ if (err < 0)
+ goto priv_out;
+
+ brcmf_dbg(INFO, "Registering custom regulatory\n");
+ wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+ wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
+
+ /* firmware defaults to 40MHz disabled in 2G band. We signal
+ * cfg80211 here that we do and have it decide we can enable
+ * it. But first check if device does support 2G operation.
+ */
+ if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
+ cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap;
+ *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+ err = wiphy_register(wiphy);
+ if (err < 0) {
+ brcmf_err("Could not register wiphy device (%d)\n", err);
+ goto priv_out;
+ }
+
+ /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
+ * setup 40MHz in 2GHz band and enable OBSS scanning.
+ */
+ if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
+ err = brcmf_enable_bw40_2g(cfg);
+ if (!err)
+ err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
+ BRCMF_OBSS_COEX_AUTO);
+ else
+ *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+
+ err = brcmf_p2p_attach(cfg);
+ if (err) {
+ brcmf_err("P2P initilisation failed (%d)\n", err);
+ goto wiphy_unreg_out;
+ }
+ err = brcmf_btcoex_attach(cfg);
+ if (err) {
+ brcmf_err("BT-coex initialisation failed (%d)\n", err);
+ brcmf_p2p_detach(&cfg->p2p);
+ goto wiphy_unreg_out;
+ }
+
+ err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
+ if (err) {
+ brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
+ wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
+ } else {
+ brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
+ brcmf_notify_tdls_peer_event);
+ }
+
+ return cfg;
+
+wiphy_unreg_out:
+ wiphy_unregister(cfg->wiphy);
+priv_out:
+ wl_deinit_priv(cfg);
+ brcmf_free_vif(vif);
+wiphy_out:
+ brcmf_free_wiphy(wiphy);
+ return NULL;
+}
+
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
+{
+ if (!cfg)
+ return;
+
+ WARN_ON(!list_empty(&cfg->vif_list));
+ wiphy_unregister(cfg->wiphy);
+ brcmf_btcoex_detach(cfg);
+ brcmf_p2p_detach(&cfg->p2p);
+ wl_deinit_priv(cfg);
+ brcmf_free_wiphy(cfg->wiphy);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 283c525a44f7..f9fb10998e79 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -477,7 +477,7 @@ const struct brcmf_tlv *
brcmf_parse_tlvs(const void *buf, int buflen, uint key);
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
struct ieee80211_channel *ch);
-u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state);
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif);
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index af8ba64ace39..1b474828d5b8 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
return err;
}
-static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
-{
- uint unit;
- unit = wlc->pub->unit;
-
- if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
- /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
- wlc->band->antgain = 8;
- } else if (wlc->band->antgain == -1) {
- wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
- " srom, using 2dB\n", unit, __func__);
- wlc->band->antgain = 8;
- } else {
- s8 gain, fract;
- /* Older sroms specified gain in whole dbm only. In order
- * be able to specify qdbm granularity and remain backward
- * compatible the whole dbms are now encoded in only
- * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
- * 6 bit signed number ranges from -32 - 31.
- *
- * Examples:
- * 0x1 = 1 db,
- * 0xc1 = 1.75 db (1 + 3 quarters),
- * 0x3f = -1 (-1 + 0 quarters),
- * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
- * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
- */
- gain = wlc->band->antgain & 0x3f;
- gain <<= 2; /* Sign extend */
- gain >>= 2;
- fract = (wlc->band->antgain & 0xc0) >> 6;
- wlc->band->antgain = 4 * gain + fract;
- }
-}
-
static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
{
int aa;
@@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
else
wlc->band->antgain = sprom->antenna_gain.a0;
- brcms_c_attach_antgain_init(wlc);
-
return true;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
index b0fd807f2b2b..57ecc05802e9 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -1538,11 +1538,7 @@ static s8
wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
u8 rate)
{
- s8 offset = 0;
-
- if (!pi->user_txpwr_at_rfport)
- return offset;
- return offset;
+ return 0;
}
void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index 3e9f5b25be63..93869e89aa3d 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -22916,7 +22916,6 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
break;
default:
return;
- break;
}
classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index d816270db3be..af26e0de1e5c 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -17,32 +17,67 @@
#ifndef _BRCM_HW_IDS_H_
#define _BRCM_HW_IDS_H_
-#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
+#include <linux/pci_ids.h>
+#include <linux/mmc/sdio_ids.h>
+
+#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
+#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
+#define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM
+
+/* Chipcommon Core Chip IDs */
+#define BRCM_CC_43143_CHIP_ID 43143
+#define BRCM_CC_43235_CHIP_ID 43235
+#define BRCM_CC_43236_CHIP_ID 43236
+#define BRCM_CC_43238_CHIP_ID 43238
+#define BRCM_CC_43241_CHIP_ID 0x4324
+#define BRCM_CC_43242_CHIP_ID 43242
+#define BRCM_CC_4329_CHIP_ID 0x4329
+#define BRCM_CC_4330_CHIP_ID 0x4330
+#define BRCM_CC_4334_CHIP_ID 0x4334
+#define BRCM_CC_43362_CHIP_ID 43362
+#define BRCM_CC_4335_CHIP_ID 0x4335
+#define BRCM_CC_4339_CHIP_ID 0x4339
+#define BRCM_CC_4354_CHIP_ID 0x4354
+#define BRCM_CC_4356_CHIP_ID 0x4356
+#define BRCM_CC_43566_CHIP_ID 43566
+#define BRCM_CC_43567_CHIP_ID 43567
+#define BRCM_CC_43569_CHIP_ID 43569
+#define BRCM_CC_43570_CHIP_ID 43570
+#define BRCM_CC_43602_CHIP_ID 43602
+
+/* SDIO Device IDs */
+#define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID
+#define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID
+#define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID
+#define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID
+#define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID
+#define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID
+#define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID
+#define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID
+
+/* USB Device IDs */
+#define BRCM_USB_43143_DEVICE_ID 0xbd1e
+#define BRCM_USB_43236_DEVICE_ID 0xbd17
+#define BRCM_USB_43242_DEVICE_ID 0xbd1f
+#define BRCM_USB_43569_DEVICE_ID 0xbd27
+#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc
+/* PCIE Device IDs */
+#define BRCM_PCIE_4354_DEVICE_ID 0x43df
+#define BRCM_PCIE_4356_DEVICE_ID 0x43ec
+#define BRCM_PCIE_43567_DEVICE_ID 0x43d3
+#define BRCM_PCIE_43570_DEVICE_ID 0x43d9
+#define BRCM_PCIE_43602_DEVICE_ID 0x43ba
+
+/* brcmsmac IDs */
+#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */
#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */
-
#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */
-
#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */
#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */
-/* Chipcommon Core Chip IDs */
#define BCM4313_CHIP_ID 0x4313
-#define BCM43143_CHIP_ID 43143
#define BCM43224_CHIP_ID 43224
-#define BCM43225_CHIP_ID 43225
-#define BCM43235_CHIP_ID 43235
-#define BCM43236_CHIP_ID 43236
-#define BCM43238_CHIP_ID 43238
-#define BCM43241_CHIP_ID 0x4324
-#define BCM4329_CHIP_ID 0x4329
-#define BCM4330_CHIP_ID 0x4330
-#define BCM4331_CHIP_ID 0x4331
-#define BCM4334_CHIP_ID 0x4334
-#define BCM4335_CHIP_ID 0x4335
-#define BCM43362_CHIP_ID 43362
-#define BCM4339_CHIP_ID 0x4339
-#define BCM4354_CHIP_ID 0x4354
#endif /* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c
index e23d67e0bfe6..6f1b9aace8b3 100644
--- a/drivers/net/wireless/cw1200/fwio.c
+++ b/drivers/net/wireless/cw1200/fwio.c
@@ -290,7 +290,6 @@ static int config_reg_write(struct cw1200_common *priv, u32 val)
case HIF_8601_SILICON:
default:
return cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val);
- break;
}
return 0;
}
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c
index 9afcd4ce3368..b2fb6c632092 100644
--- a/drivers/net/wireless/cw1200/scan.c
+++ b/drivers/net/wireless/cw1200/scan.c
@@ -53,9 +53,10 @@ static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan)
int cw1200_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
struct cw1200_common *priv = hw->priv;
+ struct cfg80211_scan_request *req = &hw_req->req;
struct wsm_template_frame frame = {
.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
};
diff --git a/drivers/net/wireless/cw1200/scan.h b/drivers/net/wireless/cw1200/scan.h
index 5a8296ccfa82..cc75459e5784 100644
--- a/drivers/net/wireless/cw1200/scan.h
+++ b/drivers/net/wireless/cw1200/scan.h
@@ -41,7 +41,7 @@ struct cw1200_scan {
int cw1200_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req);
+ struct ieee80211_scan_request *hw_req);
void cw1200_scan_work(struct work_struct *work);
void cw1200_scan_timeout(struct work_struct *work);
void cw1200_clear_recent_scan_work(struct work_struct *work);
diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c
index cd0cad7f7759..5b84664db13b 100644
--- a/drivers/net/wireless/cw1200/sta.c
+++ b/drivers/net/wireless/cw1200/sta.c
@@ -2289,7 +2289,6 @@ static int cw1200_upload_null(struct cw1200_common *priv)
static int cw1200_upload_qosnull(struct cw1200_common *priv)
{
- int ret = 0;
/* TODO: This needs to be implemented
struct wsm_template_frame frame = {
@@ -2306,7 +2305,7 @@ static int cw1200_upload_qosnull(struct cw1200_common *priv)
dev_kfree_skb(frame.skb);
*/
- return ret;
+ return 0;
}
static int cw1200_enable_beaconing(struct cw1200_common *priv,
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 91158e2e961c..c864ef4b0015 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -39,7 +39,7 @@ struct hostap_pci_priv {
/* FIX: do we need mb/wmb/rmb with memory operations? */
-static DEFINE_PCI_DEVICE_TABLE(prism2_pci_id_table) = {
+static const struct pci_device_id prism2_pci_id_table[] = {
/* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
{ 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
/* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index 3bf530d9a40f..4901a99c6c59 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -60,7 +60,7 @@ struct hostap_plx_priv {
#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID }
-static DEFINE_PCI_DEVICE_TABLE(prism2_plx_id_table) = {
+static const struct pci_device_id prism2_plx_id_table[] = {
PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
PLXDEV(0x126c, 0x8030, "Nortel emobility"),
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index dfc6dfc56d52..c3d726f334e3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -3449,8 +3449,9 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
return -ENOMEM;
for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
- v = pci_alloc_consistent(priv->pci_dev,
- sizeof(struct ipw2100_cmd_header), &p);
+ v = pci_zalloc_consistent(priv->pci_dev,
+ sizeof(struct ipw2100_cmd_header),
+ &p);
if (!v) {
printk(KERN_ERR DRV_NAME ": "
"%s: PCI alloc failed for msg "
@@ -3459,8 +3460,6 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
break;
}
- memset(v, 0, sizeof(struct ipw2100_cmd_header));
-
priv->msg_buffers[i].type = COMMAND;
priv->msg_buffers[i].info.c_struct.cmd =
(struct ipw2100_cmd_header *)v;
@@ -4336,16 +4335,12 @@ static int status_queue_allocate(struct ipw2100_priv *priv, int entries)
IPW_DEBUG_INFO("enter\n");
q->size = entries * sizeof(struct ipw2100_status);
- q->drv =
- (struct ipw2100_status *)pci_alloc_consistent(priv->pci_dev,
- q->size, &q->nic);
+ q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
if (!q->drv) {
IPW_DEBUG_WARNING("Can not allocate status queue.\n");
return -ENOMEM;
}
- memset(q->drv, 0, q->size);
-
IPW_DEBUG_INFO("exit\n");
return 0;
@@ -4374,13 +4369,12 @@ static int bd_queue_allocate(struct ipw2100_priv *priv,
q->entries = entries;
q->size = entries * sizeof(struct ipw2100_bd);
- q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic);
+ q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
if (!q->drv) {
IPW_DEBUG_INFO
("can't allocate shared memory for buffer descriptors\n");
return -ENOMEM;
}
- memset(q->drv, 0, q->size);
IPW_DEBUG_INFO("exit\n");
@@ -6511,7 +6505,7 @@ static void ipw2100_shutdown(struct pci_dev *pci_dev)
#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
-static DEFINE_PCI_DEVICE_TABLE(ipw2100_pci_id_table) = {
+static const struct pci_device_id ipw2100_pci_id_table[] = {
IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */
IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */
IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index c5aa404069f3..a42f9c335090 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -9853,6 +9853,7 @@ static int ipw_wx_get_wireless_mode(struct net_device *dev,
strncpy(extra, "unknown", MAX_WX_STRING);
break;
}
+ extra[MAX_WX_STRING - 1] = '\0';
IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra);
@@ -11542,7 +11543,7 @@ out:
}
/* PCI driver stuff */
-static DEFINE_PCI_DEVICE_TABLE(card_ids) = {
+static const struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0},
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index 3adb24021a28..5f31b72a4921 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -100,8 +100,7 @@ static inline void libipw_networks_free(struct libipw_device *ieee)
int i;
for (i = 0; i < MAX_NETWORK_COUNT; i++) {
- if (ieee->networks[i]->ibss_dfs)
- kfree(ieee->networks[i]->ibss_dfs);
+ kfree(ieee->networks[i]->ibss_dfs);
kfree(ieee->networks[i]);
}
}
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index b598e2803500..93bdf684babe 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -2728,7 +2728,7 @@ static struct il_cfg il3945_abg_cfg = {
},
};
-DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = {
+const struct pci_device_id il3945_hw_card_ids[] = {
{IL_PCI_DEVICE(0x4222, 0x1005, il3945_bg_cfg)},
{IL_PCI_DEVICE(0x4222, 0x1034, il3945_bg_cfg)},
{IL_PCI_DEVICE(0x4222, 0x1044, il3945_bg_cfg)},
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index c159c05db6ef..3dcbe2cd2b28 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6800,7 +6800,7 @@ il4965_txq_set_sched(struct il_priv *il, u32 mask)
*****************************************************************************/
/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = {
+static const struct pci_device_id il4965_hw_card_ids[] = {
{IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
{IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
{0}
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index ecc674627e6e..2c4fa49686ef 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -1572,8 +1572,9 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif)
int
il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
+ struct cfg80211_scan_request *req = &hw_req->req;
struct il_priv *il = hw->priv;
int ret;
@@ -2979,7 +2980,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id)
/* Driver ilate data, only for Tx (not command) queues,
* not shared with device. */
if (id != il->cmd_queue) {
- txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(struct skb *),
+ txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX,
+ sizeof(struct sk_buff *),
GFP_KERNEL);
if (!txq->skbs) {
IL_ERR("Fail to alloc skbs\n");
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index ea5c0f863c4e..5b972798bdff 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1787,7 +1787,7 @@ int il_scan_cancel(struct il_priv *il);
int il_scan_cancel_timeout(struct il_priv *il, unsigned long ms);
void il_force_scan_end(struct il_priv *il);
int il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req);
+ struct ieee80211_scan_request *hw_req);
void il_internal_short_hw_scan(struct il_priv *il);
int il_force_reset(struct il_priv *il, bool external);
u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame,
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 7fd50428b934..6451d2b6abcf 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -20,16 +20,17 @@ config IWLWIFI
Intel 2000 Series Wi-Fi Adapters
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
+ Intel 7265 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
- In order to use this driver, you will need a microcode (uCode)
+ In order to use this driver, you will need a firmware
image for it. You can obtain the microcode from:
- <http://intellinuxwireless.org/>.
+ <http://wireless.kernel.org/en/users/Drivers/iwlwifi>.
- The microcode is typically installed in /lib/firmware. You can
+ The firmware is typically installed in /lib/firmware. You can
look in the hotplug script /etc/hotplug/firmware.agent to
determine which directory FIRMWARE_DIR is set to when the script
runs.
@@ -39,9 +40,10 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
+if IWLWIFI
+
config IWLWIFI_LEDS
bool
- depends on IWLWIFI
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
select LEDS_TRIGGERS
select MAC80211_LEDS
@@ -49,7 +51,7 @@ config IWLWIFI_LEDS
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
- depends on IWLWIFI
+ depends on m
default IWLWIFI
help
This is the driver that supports the DVM firmware which is
@@ -58,7 +60,7 @@ config IWLDVM
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
- depends on IWLWIFI
+ depends on m
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
@@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLMVM=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
- depends on IWLWIFI && IWLDVM=n && IWLMVM=n
+ depends on IWLDVM=n && IWLMVM=n
config IWLWIFI_BCAST_FILTERING
bool "Enable broadcast filtering"
@@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
expect incoming broadcasts for their normal operations.
menu "Debugging Options"
- depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlwifi driver"
- depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
@@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
config IWLWIFI_DEBUGFS
bool "iwlwifi debugfs support"
- depends on IWLWIFI && MAC80211_DEBUGFS
+ depends on MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
@@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
- depends on IWLWIFI && IWLWIFI_DEBUG
+ depends on IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
- depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
@@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
If unsure, say Y so we can help you better when problems
occur.
endmenu
+
+endif
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 29af7b51e370..afb98f4fdaf3 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1495,9 +1495,10 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+ struct cfg80211_scan_request *req = &hw_req->req;
int ret;
IWL_DEBUG_MAC80211(priv, "enter\n");
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c
index f2c1439566b5..760c45c34ef3 100644
--- a/drivers/net/wireless/iwlwifi/dvm/power.c
+++ b/drivers/net/wireless/iwlwifi/dvm/power.c
@@ -40,6 +40,10 @@
#include "commands.h"
#include "power.h"
+static bool force_cam;
+module_param(force_cam, bool, 0644);
+MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)");
+
/*
* Setting power level allows the card to go to sleep when not busy.
*
@@ -288,6 +292,11 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
int dtimper;
+ if (force_cam) {
+ iwl_power_sleep_cam_cmd(priv, cmd);
+ return;
+ }
+
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
if (priv->wowlan)
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index 51c41531d81d..44b19e015102 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -67,7 +67,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX 8
+#define IWL8000_UCODE_API_MAX 9
/* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK 8
@@ -85,6 +85,9 @@
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
+/* Max SDIO RX aggregation size of the ADDBA request/response */
+#define MAX_RX_AGG_SIZE_8260_SDIO 28
+
static const struct iwl_base_params iwl8000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
.num_of_queues = IWLAGN_NUM_QUEUES,
@@ -119,10 +122,9 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
- .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
};
-const struct iwl_cfg iwl8260_n_cfg = {
+const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.name = "Intel(R) Dual Band Wireless-AC 8260",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000,
@@ -130,6 +132,7 @@ const struct iwl_cfg iwl8260_n_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
+ .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
};
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index b7047905f41a..8da596db9abe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
+ * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -276,6 +277,7 @@ struct iwl_cfg {
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init;
const char *default_nvm_file;
+ unsigned int max_rx_agg_size;
};
/*
@@ -337,7 +339,7 @@ extern const struct iwl_cfg iwl7265_2ac_cfg;
extern const struct iwl_cfg iwl7265_2n_cfg;
extern const struct iwl_cfg iwl7265_n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg;
-extern const struct iwl_cfg iwl8260_n_cfg;
+extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
#endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index f2a5c12269a3..77e3178040b2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -155,6 +155,8 @@ static struct iwlwifi_opmode_table {
[MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL },
};
+#define IWL_DEFAULT_SCAN_CHANNELS 40
+
/*
* struct fw_sec: Just for the image parsing proccess.
* For the fw storage we are using struct fw_desc.
@@ -565,6 +567,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
}
drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
+ memcpy(drv->fw.human_readable, ucode->human_readable,
+ sizeof(drv->fw.human_readable));
build = le32_to_cpu(ucode->build);
if (build)
@@ -819,6 +823,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len))
goto invalid_tlv_len;
break;
+ case IWL_UCODE_TLV_N_SCAN_CHANNELS:
+ if (tlv_len != sizeof(u32))
+ goto invalid_tlv_len;
+ capa->n_scan_channels =
+ le32_to_cpup((__le32 *)tlv_data);
+ break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
@@ -973,6 +983,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size =
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+ fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
if (!api_ok)
api_ok = api_max;
@@ -1394,3 +1405,7 @@ module_param_named(power_level, iwlwifi_mod_params.power_level,
int, S_IRUGO);
MODULE_PARM_DESC(power_level,
"default power save level (range from 1 - 5, default: 1)");
+
+module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
+MODULE_PARM_DESC(fw_monitor,
+ "firmware monitor - to debug FW (default: false - needs lots of memory)");
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index c44cf1149648..07ff7e0028ee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -779,7 +779,6 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
if (cfg->ht_params->ht40_bands & BIT(band)) {
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
- ht_info->mcs.rx_mask[4] = 0x01;
max_bit_rate = MAX_BIT_RATE_40_MHZ;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index 2953ffceda38..de5994a776c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -70,16 +70,24 @@
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_SRAM:
- * @IWL_FW_ERROR_DUMP_REG:
+ * @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
+ * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
+ * info on the device / firmware.
+ * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
+ * @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
+ * sections like this in a single file.
*/
enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0,
- IWL_FW_ERROR_DUMP_REG = 1,
+ IWL_FW_ERROR_DUMP_CSR = 1,
IWL_FW_ERROR_DUMP_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3,
+ IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
+ IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
+ IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_MAX,
};
@@ -87,8 +95,8 @@ enum iwl_fw_error_dump_type {
/**
* struct iwl_fw_error_dump_data - data for one type
* @type: %enum iwl_fw_error_dump_type
- * @len: the length starting from %data - must be a multiplier of 4.
- * @data: the data itself padded to be a multiplier of 4.
+ * @len: the length starting from %data
+ * @data: the data itself
*/
struct iwl_fw_error_dump_data {
__le32 type;
@@ -120,13 +128,60 @@ struct iwl_fw_error_dump_txcmd {
u8 data[];
} __packed;
+enum iwl_fw_error_dump_family {
+ IWL_FW_ERROR_DUMP_FAMILY_7 = 7,
+ IWL_FW_ERROR_DUMP_FAMILY_8 = 8,
+};
+
+/**
+ * struct iwl_fw_error_dump_info - info on the device / firmware
+ * @device_family: the family of the device (7 / 8)
+ * @hw_step: the step of the device
+ * @fw_human_readable: human readable FW version
+ * @dev_human_readable: name of the device
+ * @bus_human_readable: name of the bus used
+ */
+struct iwl_fw_error_dump_info {
+ __le32 device_family;
+ __le32 hw_step;
+ u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
+ u8 dev_human_readable[64];
+ u8 bus_human_readable[8];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_fw_mon - FW monitor data
+ * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
+ * @fw_mon_base_ptr: base pointer of the data
+ * @fw_mon_cycle_cnt: number of wrap arounds
+ * @reserved: for future use
+ * @data: captured data
+ */
+struct iwl_fw_error_dump_fw_mon {
+ __le32 fw_mon_wr_ptr;
+ __le32 fw_mon_base_ptr;
+ __le32 fw_mon_cycle_cnt;
+ __le32 reserved[3];
+ u8 data[];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_prph - periphery registers data
+ * @prph_start: address of the first register in this chunk
+ * @data: the content of the registers
+ */
+struct iwl_fw_error_dump_prph {
+ __le32 prph_start;
+ __le32 data[];
+};
+
/**
- * iwl_mvm_fw_error_next_data - advance fw error dump data pointer
+ * iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block
* Returns: next data block
*/
static inline struct iwl_fw_error_dump_data *
-iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data)
+iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
{
return (void *)(data->data + le32_to_cpu(data->len));
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index b45e576a4b57..929a8063354c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -128,6 +128,7 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_CSCHEME = 28,
IWL_UCODE_TLV_API_CHANGES_SET = 29,
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
+ IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
};
struct iwl_ucode_tlv {
@@ -136,7 +137,8 @@ struct iwl_ucode_tlv {
u8 data[0];
};
-#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
+#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
+#define FW_VER_HUMAN_READABLE_SZ 64
struct iwl_tlv_ucode_header {
/*
@@ -147,7 +149,7 @@ struct iwl_tlv_ucode_header {
*/
__le32 zero;
__le32 magic;
- u8 human_readable[64];
+ u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
__le32 ver; /* major/minor/API/serial */
__le32 build;
__le64 ignore;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index b1a33322b9ba..1bb5193c5b1b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -65,6 +65,8 @@
#include <linux/types.h>
#include <net/mac80211.h>
+#include "iwl-fw-file.h"
+
/**
* enum iwl_ucode_tlv_flag - ucode API flags
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
@@ -118,11 +120,19 @@ enum iwl_ucode_tlv_flag {
/**
* enum iwl_ucode_tlv_api - ucode api
* @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
+ * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
* @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
+ * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
+ * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
+ IWL_UCODE_TLV_CAPA_EXTENDED_BEACON = BIT(1),
+ IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3),
IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
+ IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5),
+ IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6),
};
/**
@@ -179,6 +189,7 @@ enum iwl_ucode_sec {
struct iwl_ucode_capabilities {
u32 max_probe_length;
+ u32 n_scan_channels;
u32 standard_phy_calibration_size;
u32 flags;
u32 api[IWL_API_ARRAY_SIZE];
@@ -312,6 +323,7 @@ struct iwl_fw {
bool mvm_fw;
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
+ u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
};
#endif /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index d051857729ab..71507cf490e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -99,10 +99,11 @@ enum iwl_disable_11n {
* @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
- * @power_save: disable power save, default = false
+ * @power_save: enable power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
+ * @fw_monitor: allow to use firmware monitor
*/
struct iwl_mod_params {
int sw_crypto;
@@ -120,6 +121,7 @@ struct iwl_mod_params {
int ant_coupling;
char *nvm_file;
bool uapsd_disable;
+ bool fw_monitor;
};
#endif /* #__iwl_modparams_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 85eee79c495c..018af2957d3b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -63,6 +63,7 @@
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/etherdevice.h>
+#include <linux/pci.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
@@ -87,8 +88,10 @@ enum wkp_nvm_offsets {
enum family_8000_nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
- HW_ADDR0_FAMILY_8000 = 0x12,
- HW_ADDR1_FAMILY_8000 = 0x16,
+ HW_ADDR0_WFPM_FAMILY_8000 = 0x12,
+ HW_ADDR1_WFPM_FAMILY_8000 = 0x16,
+ HW_ADDR0_PCIE_FAMILY_8000 = 0x8A,
+ HW_ADDR1_PCIE_FAMILY_8000 = 0x8E,
MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1,
/* NVM SW-Section offset (in words) definitions */
@@ -174,7 +177,9 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
* @NVM_CHANNEL_IBSS: usable as an IBSS channel
* @NVM_CHANNEL_ACTIVE: active scanning allowed
* @NVM_CHANNEL_RADAR: radar detection required
- * @NVM_CHANNEL_DFS: dynamic freq selection candidate
+ * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
+ * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
+ * on same channel on 2.4 or same UNII band on 5.2
* @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
* @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
@@ -185,7 +190,8 @@ enum iwl_nvm_channel_flags {
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
- NVM_CHANNEL_DFS = BIT(7),
+ NVM_CHANNEL_INDOOR_ONLY = BIT(5),
+ NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_WIDE = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
@@ -273,6 +279,16 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
if (ch_flags & NVM_CHANNEL_RADAR)
channel->flags |= IEEE80211_CHAN_RADAR;
+ if (ch_flags & NVM_CHANNEL_INDOOR_ONLY)
+ channel->flags |= IEEE80211_CHAN_INDOOR_ONLY;
+
+ /* Set the GO concurrent flag only in case that NO_IR is set.
+ * Otherwise it is meaningless
+ */
+ if ((ch_flags & NVM_CHANNEL_GO_CONCURRENT) &&
+ (channel->flags & IEEE80211_CHAN_NO_IR))
+ channel->flags |= IEEE80211_CHAN_GO_CONCURRENT;
+
/* Initialize regulatory-based run-time data */
/*
@@ -282,7 +298,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
channel->max_power = DEFAULT_MAX_TX_POWER;
is_5ghz = channel->band == IEEE80211_BAND_5GHZ;
IWL_DEBUG_EEPROM(dev,
- "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
+ "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n",
channel->hw_value,
is_5ghz ? "5.2" : "2.4",
CHECK_AND_PRINT_I(VALID),
@@ -290,7 +306,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
CHECK_AND_PRINT_I(ACTIVE),
CHECK_AND_PRINT_I(RADAR),
CHECK_AND_PRINT_I(WIDE),
- CHECK_AND_PRINT_I(DFS),
+ CHECK_AND_PRINT_I(INDOOR_ONLY),
+ CHECK_AND_PRINT_I(GO_CONCURRENT),
ch_flags,
channel->max_power,
((ch_flags & NVM_CHANNEL_IBSS) &&
@@ -462,7 +479,8 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
data->hw_addr[5] = hw_addr[4];
}
-static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
+static void iwl_set_hw_address_family_8000(struct device *dev,
+ const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 *mac_override,
const __le16 *nvm_hw)
@@ -481,20 +499,64 @@ static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
data->hw_addr[4] = hw_addr[5];
data->hw_addr[5] = hw_addr[4];
- if (is_valid_ether_addr(hw_addr))
+ if (is_valid_ether_addr(data->hw_addr))
return;
+
+ IWL_ERR_DEV(dev,
+ "mac address from nvm override section is not valid\n");
}
- /* take the MAC address from the OTP */
- hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
- data->hw_addr[0] = hw_addr[3];
- data->hw_addr[1] = hw_addr[2];
- data->hw_addr[2] = hw_addr[1];
- data->hw_addr[3] = hw_addr[0];
+ if (nvm_hw) {
+ /* read the MAC address from OTP */
+ if (!dev_is_pci(dev) || (data->nvm_version < 0xE08)) {
+ /* read the mac address from the WFPM location */
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR0_WFPM_FAMILY_8000);
+ data->hw_addr[0] = hw_addr[3];
+ data->hw_addr[1] = hw_addr[2];
+ data->hw_addr[2] = hw_addr[1];
+ data->hw_addr[3] = hw_addr[0];
+
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR1_WFPM_FAMILY_8000);
+ data->hw_addr[4] = hw_addr[1];
+ data->hw_addr[5] = hw_addr[0];
+ } else if ((data->nvm_version >= 0xE08) &&
+ (data->nvm_version < 0xE0B)) {
+ /* read "reverse order" from the PCIe location */
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR0_PCIE_FAMILY_8000);
+ data->hw_addr[5] = hw_addr[2];
+ data->hw_addr[4] = hw_addr[1];
+ data->hw_addr[3] = hw_addr[0];
+
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR1_PCIE_FAMILY_8000);
+ data->hw_addr[2] = hw_addr[3];
+ data->hw_addr[1] = hw_addr[2];
+ data->hw_addr[0] = hw_addr[1];
+ } else {
+ /* read from the PCIe location */
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR0_PCIE_FAMILY_8000);
+ data->hw_addr[5] = hw_addr[0];
+ data->hw_addr[4] = hw_addr[1];
+ data->hw_addr[3] = hw_addr[2];
+
+ hw_addr = (const u8 *)(nvm_hw +
+ HW_ADDR1_PCIE_FAMILY_8000);
+ data->hw_addr[2] = hw_addr[1];
+ data->hw_addr[1] = hw_addr[2];
+ data->hw_addr[0] = hw_addr[3];
+ }
+ if (!is_valid_ether_addr(data->hw_addr))
+ IWL_ERR_DEV(dev,
+ "mac address from hw section is not valid\n");
+
+ return;
+ }
- hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
- data->hw_addr[4] = hw_addr[1];
- data->hw_addr[5] = hw_addr[0];
+ IWL_ERR_DEV(dev, "mac address is not found\n");
}
struct iwl_nvm_data *
@@ -556,7 +618,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
rx_chains);
} else {
/* MAC address in family 8000 */
- iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
+ iwl_set_hw_address_family_8000(dev, cfg, data, mac_override,
+ nvm_hw);
iwl_init_sbands(dev, cfg, data, regulatory,
sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 4997e27672b3..47033a35a402 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -359,4 +359,10 @@ enum secure_load_status_reg {
#define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10)
#define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c)
+/* FW monitor */
+#define MON_BUFF_BASE_ADDR (0xa03c3c)
+#define MON_BUFF_END_ADDR (0xa03c40)
+#define MON_BUFF_WRPTR (0xa03c44)
+#define MON_BUFF_CYCLE_CNT (0xa03c48)
+
#endif /* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 34d49e171fb4..656371a668da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -394,6 +394,11 @@ struct iwl_trans_config {
const char *const *command_names;
};
+struct iwl_trans_dump_data {
+ u32 len;
+ u8 data[];
+};
+
struct iwl_trans;
/**
@@ -461,10 +466,8 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
- * @dump_data: fill a data dump with debug data, maybe containing last
- * TX'ed commands and similar. When called with a NULL buffer and
- * zero buffer length, provide only the (estimated) required buffer
- * length. Return the used buffer length.
+ * @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
+ * TX'ed commands and similar. The buffer will be vfree'd by the caller.
* Note that the transport must fill in the proper file headers.
*/
struct iwl_trans_ops {
@@ -518,7 +521,7 @@ struct iwl_trans_ops {
void (*unref)(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
- u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
+ struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
#endif
};
@@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
-static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
- void *buf, u32 buflen)
+static inline struct iwl_trans_dump_data *
+iwl_trans_dump_data(struct iwl_trans *trans)
{
if (!trans->ops->dump_data)
- return 0;
- return trans->ops->dump_data(trans, buf, buflen);
+ return NULL;
+ return trans->ops->dump_data(trans);
}
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index c30d7f64ec1e..a28235913c2c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o
-iwlmvm-y += power.o coex.o
+iwlmvm-y += power.o coex.o coex_legacy.o
iwlmvm-y += tt.o offloading.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index c8c3b38228f0..2291bbcaaeab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -70,57 +70,58 @@
#include "mvm.h"
#include "iwl-debug.h"
-#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \
- [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \
- ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
-
-static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
- BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
- BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
- BT_COEX_PRIO_TBL_PRIO_LOW, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
- BT_COEX_PRIO_TBL_PRIO_LOW, 1),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
- BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
- BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
- BT_COEX_PRIO_TBL_DISABLED, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
- BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
- BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
- EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
- BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
- 0, 0, 0, 0, 0, 0,
-};
-
-#undef EVENT_PRIO_ANT
-
-#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
-#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
#define BT_ANTENNA_COUPLING_THRESHOLD (30)
-static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
-{
- return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
- sizeof(struct iwl_bt_coex_prio_tbl_cmd),
- &iwl_bt_prio_tbl);
-}
+const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
+ [BT_KILL_MSK_DEFAULT] = 0xfffffc00,
+ [BT_KILL_MSK_NEVER] = 0xffffffff,
+ [BT_KILL_MSK_ALWAYS] = 0,
+};
-const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
- [BT_KILL_MSK_DEFAULT] = 0xffff0000,
- [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
- [BT_KILL_MSK_REDUCED_TXPOW] = 0,
+const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
+ {
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ },
+ {
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_NEVER,
+ },
+ {
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_NEVER,
+ },
+ {
+ BT_KILL_MSK_DEFAULT,
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_DEFAULT,
+ },
};
-const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
- [BT_KILL_MSK_DEFAULT] = 0xffff0000,
- [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
- [BT_KILL_MSK_REDUCED_TXPOW] = 0,
+const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
+ {
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ },
+ {
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ },
+ {
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_ALWAYS,
+ },
+ {
+ BT_KILL_MSK_DEFAULT,
+ BT_KILL_MSK_ALWAYS,
+ BT_KILL_MSK_DEFAULT,
+ },
};
static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
@@ -519,6 +520,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
struct ieee80211_chanctx_conf *chanctx_conf;
enum iwl_bt_coex_lut_type ret;
u16 phy_ctx_id;
+ u32 primary_ch_phy_id, secondary_ch_phy_id;
/*
* Checking that we hold mvm->mutex is a good idea, but the rate
@@ -535,7 +537,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
if (!chanctx_conf ||
chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
rcu_read_unlock();
- return BT_COEX_LOOSE_LUT;
+ return BT_COEX_INVALID_LUT;
}
ret = BT_COEX_TX_DIS_LUT;
@@ -546,10 +548,13 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
}
phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
+ primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
+ secondary_ch_phy_id =
+ le32_to_cpu(mvm->last_bt_ci_cmd.secondary_ch_phy_id);
- if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id)
+ if (primary_ch_phy_id == phy_ctx_id)
ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
- else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id)
+ else if (secondary_ch_phy_id == phy_ctx_id)
ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
/* else - default = TX TX disallowed */
@@ -567,59 +572,63 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
};
int ret;
- u32 flags;
+ u32 mode;
- ret = iwl_send_bt_prio_tbl(mvm);
- if (ret)
- return ret;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_send_bt_init_conf_old(mvm);
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
if (!bt_cmd)
return -ENOMEM;
cmd.data[0] = bt_cmd;
- bt_cmd->max_kill = 5;
- bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
- bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
- bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
- bt_cmd->bt4_tx_rx_max_freq0 = 15;
- bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
- bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
-
- flags = iwlwifi_mod_params.bt_coex_active ?
- BT_COEX_NW : BT_COEX_DISABLE;
- bt_cmd->flags = cpu_to_le32(flags);
-
- bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
- BT_VALID_BT_PRIO_BOOST |
- BT_VALID_MAX_KILL |
- BT_VALID_3W_TMRS |
- BT_VALID_KILL_ACK |
- BT_VALID_KILL_CTS |
- BT_VALID_REDUCED_TX_POWER |
- BT_VALID_LUT |
- BT_VALID_WIFI_RX_SW_PRIO_BOOST |
- BT_VALID_WIFI_TX_SW_PRIO_BOOST |
- BT_VALID_ANT_ISOLATION |
- BT_VALID_ANT_ISOLATION_THRS |
- BT_VALID_TXTX_DELTA_FREQ_THRS |
- BT_VALID_TXRX_MAX_FREQ_0 |
- BT_VALID_SYNC_TO_SCO);
+ lockdep_assert_held(&mvm->mutex);
- if (IWL_MVM_BT_COEX_SYNC2SCO)
- bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
+ u32 mode;
- if (IWL_MVM_BT_COEX_CORUNNING) {
- bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
- BT_VALID_CORUN_LUT_40);
- bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
+ switch (mvm->bt_force_ant_mode) {
+ case BT_FORCE_ANT_BT:
+ mode = BT_COEX_BT;
+ break;
+ case BT_FORCE_ANT_WIFI:
+ mode = BT_COEX_WIFI;
+ break;
+ default:
+ WARN_ON(1);
+ mode = 0;
+ }
+
+ bt_cmd->mode = cpu_to_le32(mode);
+ goto send_cmd;
}
+ bt_cmd->max_kill = cpu_to_le32(5);
+ bt_cmd->bt4_antenna_isolation_thr =
+ cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
+ bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
+ bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
+ bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
+ bt_cmd->override_secondary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
+
+ mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE;
+ bt_cmd->mode = cpu_to_le32(mode);
+
+ if (IWL_MVM_BT_COEX_SYNC2SCO)
+ bt_cmd->enabled_modules |=
+ cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
+
+ if (IWL_MVM_BT_COEX_CORUNNING)
+ bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
+
if (IWL_MVM_BT_COEX_MPLUT) {
- bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
- bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+ bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
+ bt_cmd->enabled_modules |=
+ cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
}
+ bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
+
if (mvm->cfg->bt_shared_single_ant)
memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
sizeof(iwl_single_shared_ant));
@@ -627,21 +636,12 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
sizeof(iwl_combined_lookup));
- /* Take first Co-running block LUT to get started */
- memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
- sizeof(bt_cmd->bt4_corun_lut20));
- memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
- sizeof(bt_cmd->bt4_corun_lut40));
-
- memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
+ memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost));
- memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+ memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
sizeof(iwl_bt_mprio_lut));
- bt_cmd->kill_ack_msk =
- cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
- bt_cmd->kill_cts_msk =
- cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
+send_cmd:
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
@@ -651,82 +651,54 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
return ret;
}
-static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
- bool reduced_tx_power)
+static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm)
{
- enum iwl_bt_kill_msk bt_kill_msk;
- struct iwl_bt_coex_cmd *bt_cmd;
struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
- struct iwl_host_cmd cmd = {
- .id = BT_CONFIG,
- .data[0] = &bt_cmd,
- .len = { sizeof(*bt_cmd), },
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- };
- int ret = 0;
+ u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
+ u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut);
+ u32 ag = le32_to_cpu(notif->bt_activity_grading);
+ struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
+ u8 ack_kill_msk[NUM_PHY_CTX] = {};
+ u8 cts_kill_msk[NUM_PHY_CTX] = {};
+ int i;
lockdep_assert_held(&mvm->mutex);
- if (reduced_tx_power) {
- /* Reduced Tx power has precedence on the type of the profile */
- bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
- } else {
- /* Low latency BT profile is active: give higher prio to BT */
- if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
- BT_MBOX_MSG(notif, 3, SNIFF_STATE))
- bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
- else
- bt_kill_msk = BT_KILL_MSK_DEFAULT;
- }
+ ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut];
+ cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut];
- IWL_DEBUG_COEX(mvm,
- "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
- bt_kill_msk,
- BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+ ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut];
+ cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut];
/* Don't send HCMD if there is no update */
- if (bt_kill_msk == mvm->bt_kill_msk)
+ if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) ||
+ !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk)))
return 0;
- mvm->bt_kill_msk = bt_kill_msk;
-
- bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
- if (!bt_cmd)
- return -ENOMEM;
- cmd.data[0] = bt_cmd;
- bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
-
- bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
- bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
- bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
- BT_VALID_KILL_ACK |
- BT_VALID_KILL_CTS);
+ memcpy(mvm->bt_ack_kill_msk, ack_kill_msk,
+ sizeof(mvm->bt_ack_kill_msk));
+ memcpy(mvm->bt_cts_kill_msk, cts_kill_msk,
+ sizeof(mvm->bt_cts_kill_msk));
- IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
- iwl_bt_ack_kill_msk[bt_kill_msk],
- iwl_bt_cts_kill_msk[bt_kill_msk]);
+ BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values));
- ret = iwl_mvm_send_cmd(mvm, &cmd);
+ for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) {
+ cmd.boost_values[i].kill_ack_msk =
+ cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]);
+ cmd.boost_values[i].kill_cts_msk =
+ cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]);
+ }
- kfree(bt_cmd);
- return ret;
+ return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
+ sizeof(cmd), &cmd);
}
static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
bool enable)
{
- struct iwl_bt_coex_cmd *bt_cmd;
- /* Send ASYNC since this can be sent from an atomic context */
- struct iwl_host_cmd cmd = {
- .id = BT_CONFIG,
- .len = { sizeof(*bt_cmd), },
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- .flags = CMD_ASYNC,
- };
+ struct iwl_bt_coex_reduced_txp_update_cmd cmd = {};
struct iwl_mvm_sta *mvmsta;
+ u32 value;
int ret;
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
@@ -737,35 +709,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
if (mvmsta->bt_reduced_txpower == enable)
return 0;
- bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
- if (!bt_cmd)
- return -ENOMEM;
- cmd.data[0] = bt_cmd;
- bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
-
- bt_cmd->valid_bit_msk =
- cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
- bt_cmd->bt_reduced_tx_power = sta_id;
+ value = mvmsta->sta_id;
if (enable)
- bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+ value |= BT_REDUCED_TX_POWER_BIT;
IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
enable ? "en" : "dis", sta_id);
+ cmd.reduced_txp = cpu_to_le32(value);
mvmsta->bt_reduced_txpower = enable;
- ret = iwl_mvm_send_cmd(mvm, &cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC,
+ sizeof(cmd), &cmd);
- kfree(bt_cmd);
return ret;
}
struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif *notif;
struct iwl_mvm *mvm;
- u32 num_bss_ifaces;
- bool reduced_tx_power;
struct ieee80211_chanctx_conf *primary;
struct ieee80211_chanctx_conf *secondary;
bool primary_ll;
@@ -780,9 +743,9 @@ void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
mvmvif->bf_data.last_bt_coex_event = rssi;
mvmvif->bf_data.bt_coex_max_thold =
- enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0;
+ enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
mvmvif->bf_data.bt_coex_min_thold =
- enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0;
+ enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
}
/* must be called under rcu_read_lock */
@@ -801,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- /* Count BSSes vifs */
- data->num_bss_ifaces++;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode = IEEE80211_SMPS_AUTOMATIC;
break;
case NL80211_IFTYPE_AP:
- /* default smps_mode for AP / GO is OFF */
- smps_mode = IEEE80211_SMPS_OFF;
- if (!mvmvif->ap_ibss_active) {
- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
+ if (!mvmvif->ap_ibss_active)
return;
- }
-
- /* the Ack / Cts kill mask must be default if AP / GO */
- data->reduced_tx_power = false;
break;
default:
return;
@@ -827,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if ((!chanctx_conf ||
chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
- /* ... relax constraints and disable rssi events */
- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
- data->reduced_tx_power = false;
if (vif->type == NL80211_IFTYPE_STATION) {
+ /* ... relax constraints and disable rssi events */
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+ smps_mode);
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@@ -843,20 +795,23 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (bt_activity_grading >= BT_HIGH_TRAFFIC)
smps_mode = IEEE80211_SMPS_STATIC;
else if (bt_activity_grading >= BT_LOW_TRAFFIC)
- smps_mode = vif->type == NL80211_IFTYPE_AP ?
- IEEE80211_SMPS_OFF :
- IEEE80211_SMPS_DYNAMIC;
+ smps_mode = IEEE80211_SMPS_DYNAMIC;
/* relax SMPS contraints for next association */
if (!vif->bss_conf.assoc)
smps_mode = IEEE80211_SMPS_AUTOMATIC;
+ if (IWL_COEX_IS_RRC_ON(mvm->last_bt_notif.ttc_rrc_status,
+ mvmvif->phy_ctxt->id))
+ smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
IWL_DEBUG_COEX(data->mvm,
- "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
- mvmvif->id, data->notif->bt_status, bt_activity_grading,
- smps_mode);
+ "mac %d: bt_activity_grading %d smps_req %d\n",
+ mvmvif->id, bt_activity_grading, smps_mode);
- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
+ if (vif->type == NL80211_IFTYPE_STATION)
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+ smps_mode);
/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
@@ -906,8 +861,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
*/
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
- !data->notif->bt_status) {
- data->reduced_tx_power = false;
+ le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
@@ -919,26 +873,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* if the RSSI isn't valid, fake it is very low */
if (!ave_rssi)
ave_rssi = -100;
- if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) {
+ if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
-
- /*
- * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
- * BSS / P2P clients have rssi above threshold.
- * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
- * the iteration, if one interface's rssi isn't good enough,
- * bt_kill_msk will be set to default values.
- */
- } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) {
+ } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
-
- /*
- * One interface hasn't rssi above threshold, bt_kill_msk must
- * be set to default values.
- */
- data->reduced_tx_power = false;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
@@ -950,11 +890,14 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.notif = &mvm->last_bt_notif,
- .reduced_tx_power = true,
};
struct iwl_bt_coex_ci_cmd cmd = {};
u8 ci_bw_idx;
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return;
+
rcu_read_lock();
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
@@ -969,9 +912,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
ci_bw_idx = 0;
- cmd.co_run_bw_primary = 0;
} else {
- cmd.co_run_bw_primary = 1;
if (chan->def.center_freq1 >
chan->def.chan->center_freq)
ci_bw_idx = 2;
@@ -981,7 +922,8 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
cmd.bt_primary_ci =
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
- cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
+ cmd.primary_ch_phy_id =
+ cpu_to_le32(*((u16 *)data.primary->drv_priv));
}
if (data.secondary) {
@@ -993,9 +935,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
if (chan->def.width < NL80211_CHAN_WIDTH_40) {
ci_bw_idx = 0;
- cmd.co_run_bw_secondary = 0;
} else {
- cmd.co_run_bw_secondary = 1;
if (chan->def.center_freq1 >
chan->def.chan->center_freq)
ci_bw_idx = 2;
@@ -1005,7 +945,8 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
cmd.bt_secondary_ci =
iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
- cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
+ cmd.secondary_ch_phy_id =
+ cpu_to_le32(*((u16 *)data.secondary->drv_priv));
}
rcu_read_unlock();
@@ -1018,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
}
- /*
- * If there are no BSS / P2P client interfaces, reduced Tx Power is
- * irrelevant since it is based on the RSSI coming from the beacon.
- * Use BT_KILL_MSK_DEFAULT in that case.
- */
- data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
-
- if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ if (iwl_mvm_bt_udpate_sw_boost(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
@@ -1036,11 +970,10 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_rx_bt_coex_notif_old(mvm, rxb, dev_cmd);
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
- IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
- notif->bt_status ? "ON" : "OFF");
- IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
le32_to_cpu(notif->primary_ch_lut));
@@ -1048,8 +981,6 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
le32_to_cpu(notif->secondary_ch_lut));
IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
le32_to_cpu(notif->bt_activity_grading));
- IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
- notif->bt_agg_traffic_load);
/* remember this notification for future use: rssi fluctuations */
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
@@ -1097,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
- data->num_bss_ifaces++;
-
- /*
- * This interface doesn't support reduced Tx power (because of low
- * RSSI probably), then set bt_kill_msk to default values.
- */
- if (!mvmsta->bt_reduced_txpower)
- data->reduced_tx_power = false;
- /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1115,12 +1036,20 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
struct iwl_bt_iterator_data data = {
.mvm = mvm,
- .reduced_tx_power = true,
};
int ret;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+ iwl_mvm_bt_rssi_event_old(mvm, vif, rssi_event);
+ return;
+ }
+
lockdep_assert_held(&mvm->mutex);
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return;
+
/*
* Rssi update while not associated - can happen since the statistics
* are handled asynchronously
@@ -1129,7 +1058,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return;
/* No BT - reports should be disabled */
- if (!mvm->last_bt_notif.bt_status)
+ if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF)
return;
IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
@@ -1153,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_rssi_iterator, &data);
- /*
- * If there are no BSS / P2P client interfaces, reduced Tx Power is
- * irrelevant since it is based on the RSSI coming from the beacon.
- * Use BT_KILL_MSK_DEFAULT in that case.
- */
- data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
-
- if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ if (iwl_mvm_bt_udpate_sw_boost(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
@@ -1171,15 +1093,23 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
enum iwl_bt_coex_lut_type lut_type;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
+
+ if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
+ return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC)
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
- if (lut_type == BT_COEX_LOOSE_LUT)
+ if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
return LINK_QUAL_AGG_TIME_LIMIT_DEF;
/* tight coex, high bt traffic, reduce AGG time limit */
@@ -1190,18 +1120,37 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta *sta)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+ struct iwl_mvm_phy_ctxt *phy_ctxt = mvmvif->phy_ctxt;
+ enum iwl_bt_coex_lut_type lut_type;
+
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
+
+ if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
+ return true;
if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
BT_HIGH_TRAFFIC)
return true;
/*
- * In Tight, BT can't Rx while we Tx, so use both antennas since BT is
- * already killed.
- * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we
- * Tx.
+ * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
+ * since BT is already killed.
+ * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
+ * we Tx.
+ * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
*/
- return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT;
+ lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+ return lut_type != BT_COEX_LOOSE_LUT;
+}
+
+bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
+{
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
+
+ return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF;
}
bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
@@ -1209,6 +1158,9 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
{
u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_bt_coex_is_tpc_allowed_old(mvm, band);
+
if (band != IEEE80211_BAND_2GHZ)
return false;
@@ -1249,6 +1201,11 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
{
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+ iwl_mvm_bt_coex_vif_change_old(mvm);
+ return;
+ }
+
iwl_mvm_bt_coex_notif_handle(mvm);
}
@@ -1258,22 +1215,22 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+ struct iwl_bt_coex_corun_lut_update_cmd cmd = {};
u8 __maybe_unused lower_bound, upper_bound;
- int ret;
u8 lut;
- struct iwl_bt_coex_cmd *bt_cmd;
- struct iwl_host_cmd cmd = {
- .id = BT_CONFIG,
- .len = { sizeof(*bt_cmd), },
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- };
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
+ return iwl_mvm_rx_ant_coupling_notif_old(mvm, rxb, dev_cmd);
if (!IWL_MVM_BT_COEX_CORUNNING)
return 0;
lockdep_assert_held(&mvm->mutex);
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return 0;
+
if (ant_isolation == mvm->last_ant_isol)
return 0;
@@ -1298,25 +1255,13 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
mvm->last_corun_lut = lut;
- bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
- if (!bt_cmd)
- return 0;
- cmd.data[0] = bt_cmd;
-
- bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
- bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
- BT_VALID_CORUN_LUT_20 |
- BT_VALID_CORUN_LUT_40);
-
/* For the moment, use the same LUT for 20GHz and 40GHz */
- memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
- sizeof(bt_cmd->bt4_corun_lut20));
+ memcpy(&cmd.corun_lut20, antenna_coupling_ranges[lut].lut20,
+ sizeof(cmd.corun_lut20));
- memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
- sizeof(bt_cmd->bt4_corun_lut40));
+ memcpy(&cmd.corun_lut40, antenna_coupling_ranges[lut].lut20,
+ sizeof(cmd.corun_lut40));
- ret = iwl_mvm_send_cmd(mvm, &cmd);
-
- kfree(bt_cmd);
- return ret;
+ return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_CORUN_LUT, 0,
+ sizeof(cmd), &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
new file mode 100644
index 000000000000..a3be33359927
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -0,0 +1,1257 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <linux/ieee80211.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "fw-api-coex.h"
+#include "iwl-modparams.h"
+#include "mvm.h"
+#include "iwl-debug.h"
+
+#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \
+ [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \
+ ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
+
+static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
+ BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
+ BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
+ BT_COEX_PRIO_TBL_PRIO_LOW, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
+ BT_COEX_PRIO_TBL_PRIO_LOW, 1),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
+ BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
+ BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
+ BT_COEX_PRIO_TBL_DISABLED, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
+ BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
+ BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
+ EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
+ BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
+ 0, 0, 0, 0, 0, 0,
+};
+
+#undef EVENT_PRIO_ANT
+
+#define BT_ANTENNA_COUPLING_THRESHOLD (30)
+
+static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
+{
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return 0;
+
+ return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
+ sizeof(struct iwl_bt_coex_prio_tbl_cmd),
+ &iwl_bt_prio_tbl);
+}
+
+static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
+ cpu_to_le32(0xf0f0f0f0), /* 50% */
+ cpu_to_le32(0xc0c0c0c0), /* 25% */
+ cpu_to_le32(0xfcfcfcfc), /* 75% */
+ cpu_to_le32(0xfefefefe), /* 87.5% */
+};
+
+static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
+ {
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ },
+ {
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ },
+ {
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x40000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x44000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ },
+};
+
+static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
+ {
+ /* Tight */
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaeaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xcc00ff28),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xcc00aaaa),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0x00004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xf0005000),
+ },
+ {
+ /* Loose */
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xcc00ff28),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xcc00aaaa),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xf0005000),
+ },
+ {
+ /* Tx Tx disabled */
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xeeaaaaaa),
+ cpu_to_le32(0xaaaaaaaa),
+ cpu_to_le32(0xcc00ff28),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xcc00aaaa),
+ cpu_to_le32(0x0000aaaa),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xc0004000),
+ cpu_to_le32(0xf0005000),
+ cpu_to_le32(0xf0005000),
+ },
+};
+
+/* 20MHz / 40MHz below / 40Mhz above*/
+static const __le64 iwl_ci_mask[][3] = {
+ /* dummy entry for channel 0 */
+ {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
+ {
+ cpu_to_le64(0x0000001FFFULL),
+ cpu_to_le64(0x0ULL),
+ cpu_to_le64(0x00007FFFFFULL),
+ },
+ {
+ cpu_to_le64(0x000000FFFFULL),
+ cpu_to_le64(0x0ULL),
+ cpu_to_le64(0x0003FFFFFFULL),
+ },
+ {
+ cpu_to_le64(0x000003FFFCULL),
+ cpu_to_le64(0x0ULL),
+ cpu_to_le64(0x000FFFFFFCULL),
+ },
+ {
+ cpu_to_le64(0x00001FFFE0ULL),
+ cpu_to_le64(0x0ULL),
+ cpu_to_le64(0x007FFFFFE0ULL),
+ },
+ {
+ cpu_to_le64(0x00007FFF80ULL),
+ cpu_to_le64(0x00007FFFFFULL),
+ cpu_to_le64(0x01FFFFFF80ULL),
+ },
+ {
+ cpu_to_le64(0x0003FFFC00ULL),
+ cpu_to_le64(0x0003FFFFFFULL),
+ cpu_to_le64(0x0FFFFFFC00ULL),
+ },
+ {
+ cpu_to_le64(0x000FFFF000ULL),
+ cpu_to_le64(0x000FFFFFFCULL),
+ cpu_to_le64(0x3FFFFFF000ULL),
+ },
+ {
+ cpu_to_le64(0x007FFF8000ULL),
+ cpu_to_le64(0x007FFFFFE0ULL),
+ cpu_to_le64(0xFFFFFF8000ULL),
+ },
+ {
+ cpu_to_le64(0x01FFFE0000ULL),
+ cpu_to_le64(0x01FFFFFF80ULL),
+ cpu_to_le64(0xFFFFFE0000ULL),
+ },
+ {
+ cpu_to_le64(0x0FFFF00000ULL),
+ cpu_to_le64(0x0FFFFFFC00ULL),
+ cpu_to_le64(0x0ULL),
+ },
+ {
+ cpu_to_le64(0x3FFFC00000ULL),
+ cpu_to_le64(0x3FFFFFF000ULL),
+ cpu_to_le64(0x0)
+ },
+ {
+ cpu_to_le64(0xFFFE000000ULL),
+ cpu_to_le64(0xFFFFFF8000ULL),
+ cpu_to_le64(0x0)
+ },
+ {
+ cpu_to_le64(0xFFF8000000ULL),
+ cpu_to_le64(0xFFFFFE0000ULL),
+ cpu_to_le64(0x0)
+ },
+ {
+ cpu_to_le64(0xFFC0000000ULL),
+ cpu_to_le64(0x0ULL),
+ cpu_to_le64(0x0ULL)
+ },
+};
+
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+ cpu_to_le32(0x28412201),
+ cpu_to_le32(0x11118451),
+};
+
+struct corunning_block_luts {
+ u8 range;
+ __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
+};
+
+/*
+ * Ranges for the antenna coupling calibration / co-running block LUT:
+ * LUT0: [ 0, 12[
+ * LUT1: [12, 20[
+ * LUT2: [20, 21[
+ * LUT3: [21, 23[
+ * LUT4: [23, 27[
+ * LUT5: [27, 30[
+ * LUT6: [30, 32[
+ * LUT7: [32, 33[
+ * LUT8: [33, - [
+ */
+static const struct corunning_block_luts antenna_coupling_ranges[] = {
+ {
+ .range = 0,
+ .lut20 = {
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 12,
+ .lut20 = {
+ cpu_to_le32(0x00000001), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 20,
+ .lut20 = {
+ cpu_to_le32(0x00000002), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 21,
+ .lut20 = {
+ cpu_to_le32(0x00000003), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 23,
+ .lut20 = {
+ cpu_to_le32(0x00000004), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 27,
+ .lut20 = {
+ cpu_to_le32(0x00000005), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 30,
+ .lut20 = {
+ cpu_to_le32(0x00000006), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 32,
+ .lut20 = {
+ cpu_to_le32(0x00000007), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+ {
+ .range = 33,
+ .lut20 = {
+ cpu_to_le32(0x00000008), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
+ },
+ },
+};
+
+static enum iwl_bt_coex_lut_type
+iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum iwl_bt_coex_lut_type ret;
+ u16 phy_ctx_id;
+
+ /*
+ * Checking that we hold mvm->mutex is a good idea, but the rate
+ * control can't acquire the mutex since it runs in Tx path.
+ * So this is racy in that case, but in the worst case, the AMPDU
+ * size limit will be wrong for a short time which is not a big
+ * issue.
+ */
+
+ rcu_read_lock();
+
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+
+ if (!chanctx_conf ||
+ chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
+ rcu_read_unlock();
+ return BT_COEX_INVALID_LUT;
+ }
+
+ ret = BT_COEX_TX_DIS_LUT;
+
+ if (mvm->cfg->bt_shared_single_ant) {
+ rcu_read_unlock();
+ return ret;
+ }
+
+ phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
+
+ if (mvm->last_bt_ci_cmd_old.primary_ch_phy_id == phy_ctx_id)
+ ret = le32_to_cpu(mvm->last_bt_notif_old.primary_ch_lut);
+ else if (mvm->last_bt_ci_cmd_old.secondary_ch_phy_id == phy_ctx_id)
+ ret = le32_to_cpu(mvm->last_bt_notif_old.secondary_ch_lut);
+ /* else - default = TX TX disallowed */
+
+ rcu_read_unlock();
+
+ return ret;
+}
+
+int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
+{
+ struct iwl_bt_coex_cmd_old *bt_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = BT_CONFIG,
+ .len = { sizeof(*bt_cmd), },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ };
+ int ret;
+ u32 flags;
+
+ ret = iwl_send_bt_prio_tbl(mvm);
+ if (ret)
+ return ret;
+
+ bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+ if (!bt_cmd)
+ return -ENOMEM;
+ cmd.data[0] = bt_cmd;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
+ switch (mvm->bt_force_ant_mode) {
+ case BT_FORCE_ANT_AUTO:
+ flags = BT_COEX_AUTO_OLD;
+ break;
+ case BT_FORCE_ANT_BT:
+ flags = BT_COEX_BT_OLD;
+ break;
+ case BT_FORCE_ANT_WIFI:
+ flags = BT_COEX_WIFI_OLD;
+ break;
+ default:
+ WARN_ON(1);
+ flags = 0;
+ }
+
+ bt_cmd->flags = cpu_to_le32(flags);
+ bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE);
+ goto send_cmd;
+ }
+
+ bt_cmd->max_kill = 5;
+ bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
+ bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
+ bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
+ bt_cmd->bt4_tx_rx_max_freq0 = 15;
+ bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
+ bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
+
+ flags = iwlwifi_mod_params.bt_coex_active ?
+ BT_COEX_NW_OLD : BT_COEX_DISABLE_OLD;
+ bt_cmd->flags = cpu_to_le32(flags);
+
+ bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
+ BT_VALID_BT_PRIO_BOOST |
+ BT_VALID_MAX_KILL |
+ BT_VALID_3W_TMRS |
+ BT_VALID_KILL_ACK |
+ BT_VALID_KILL_CTS |
+ BT_VALID_REDUCED_TX_POWER |
+ BT_VALID_LUT |
+ BT_VALID_WIFI_RX_SW_PRIO_BOOST |
+ BT_VALID_WIFI_TX_SW_PRIO_BOOST |
+ BT_VALID_ANT_ISOLATION |
+ BT_VALID_ANT_ISOLATION_THRS |
+ BT_VALID_TXTX_DELTA_FREQ_THRS |
+ BT_VALID_TXRX_MAX_FREQ_0 |
+ BT_VALID_SYNC_TO_SCO);
+
+ if (IWL_MVM_BT_COEX_SYNC2SCO)
+ bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
+
+ if (IWL_MVM_BT_COEX_CORUNNING) {
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
+ BT_VALID_CORUN_LUT_40);
+ bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
+ }
+
+ if (IWL_MVM_BT_COEX_MPLUT) {
+ bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+ }
+
+ if (mvm->cfg->bt_shared_single_ant)
+ memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
+ sizeof(iwl_single_shared_ant));
+ else
+ memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
+ sizeof(iwl_combined_lookup));
+
+ /* Take first Co-running block LUT to get started */
+ memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
+ sizeof(bt_cmd->bt4_corun_lut20));
+ memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
+ sizeof(bt_cmd->bt4_corun_lut40));
+
+ memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
+ sizeof(iwl_bt_prio_boost));
+ memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+ sizeof(iwl_bt_mprio_lut));
+
+send_cmd:
+ memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
+ memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+ kfree(bt_cmd);
+ return ret;
+}
+
+static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
+{
+ struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
+ u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
+ u32 ag = le32_to_cpu(notif->bt_activity_grading);
+ struct iwl_bt_coex_cmd_old *bt_cmd;
+ u8 ack_kill_msk, cts_kill_msk;
+ struct iwl_host_cmd cmd = {
+ .id = BT_CONFIG,
+ .data[0] = &bt_cmd,
+ .len = { sizeof(*bt_cmd), },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ };
+ int ret = 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
+ cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
+
+ if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
+ mvm->bt_cts_kill_msk[0] == cts_kill_msk)
+ return 0;
+
+ mvm->bt_ack_kill_msk[0] = ack_kill_msk;
+ mvm->bt_cts_kill_msk[0] = cts_kill_msk;
+
+ bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+ if (!bt_cmd)
+ return -ENOMEM;
+ cmd.data[0] = bt_cmd;
+ bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+
+ bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
+ bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
+ BT_VALID_KILL_ACK |
+ BT_VALID_KILL_CTS);
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+ kfree(bt_cmd);
+ return ret;
+}
+
+static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
+ bool enable)
+{
+ struct iwl_bt_coex_cmd_old *bt_cmd;
+ /* Send ASYNC since this can be sent from an atomic context */
+ struct iwl_host_cmd cmd = {
+ .id = BT_CONFIG,
+ .len = { sizeof(*bt_cmd), },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ .flags = CMD_ASYNC,
+ };
+ struct iwl_mvm_sta *mvmsta;
+ int ret;
+
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
+ if (!mvmsta)
+ return 0;
+
+ /* nothing to do */
+ if (mvmsta->bt_reduced_txpower == enable)
+ return 0;
+
+ bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
+ if (!bt_cmd)
+ return -ENOMEM;
+ cmd.data[0] = bt_cmd;
+ bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+
+ bt_cmd->valid_bit_msk =
+ cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
+ bt_cmd->bt_reduced_tx_power = sta_id;
+
+ if (enable)
+ bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+
+ IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
+ enable ? "en" : "dis", sta_id);
+
+ mvmsta->bt_reduced_txpower = enable;
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+ kfree(bt_cmd);
+ return ret;
+}
+
+struct iwl_bt_iterator_data {
+ struct iwl_bt_coex_profile_notif_old *notif;
+ struct iwl_mvm *mvm;
+ struct ieee80211_chanctx_conf *primary;
+ struct ieee80211_chanctx_conf *secondary;
+ bool primary_ll;
+};
+
+static inline
+void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ bool enable, int rssi)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ mvmvif->bf_data.last_bt_coex_event = rssi;
+ mvmvif->bf_data.bt_coex_max_thold =
+ enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
+ mvmvif->bf_data.bt_coex_min_thold =
+ enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
+}
+
+/* must be called under rcu_read_lock */
+static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum ieee80211_smps_mode smps_mode;
+ u32 bt_activity_grading;
+ int ave_rssi;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ /* default smps_mode for BSS / P2P client is AUTOMATIC */
+ smps_mode = IEEE80211_SMPS_AUTOMATIC;
+ break;
+ case NL80211_IFTYPE_AP:
+ if (!mvmvif->ap_ibss_active)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+
+ /* If channel context is invalid or not on 2.4GHz .. */
+ if ((!chanctx_conf ||
+ chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ /* ... relax constraints and disable rssi events */
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+ smps_mode);
+ iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ false);
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+ }
+ return;
+ }
+
+ bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
+ if (bt_activity_grading >= BT_HIGH_TRAFFIC)
+ smps_mode = IEEE80211_SMPS_STATIC;
+ else if (bt_activity_grading >= BT_LOW_TRAFFIC)
+ smps_mode = vif->type == NL80211_IFTYPE_AP ?
+ IEEE80211_SMPS_OFF :
+ IEEE80211_SMPS_DYNAMIC;
+
+ /* relax SMPS contraints for next association */
+ if (!vif->bss_conf.assoc)
+ smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
+ IWL_DEBUG_COEX(data->mvm,
+ "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
+ mvmvif->id, data->notif->bt_status, bt_activity_grading,
+ smps_mode);
+
+ if (vif->type == NL80211_IFTYPE_STATION)
+ iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
+ smps_mode);
+
+ /* low latency is always primary */
+ if (iwl_mvm_vif_low_latency(mvmvif)) {
+ data->primary_ll = true;
+
+ data->secondary = data->primary;
+ data->primary = chanctx_conf;
+ }
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ if (!mvmvif->ap_ibss_active)
+ return;
+
+ if (chanctx_conf == data->primary)
+ return;
+
+ if (!data->primary_ll) {
+ /*
+ * downgrade the current primary no matter what its
+ * type is.
+ */
+ data->secondary = data->primary;
+ data->primary = chanctx_conf;
+ } else {
+ /* there is low latency vif - we will be secondary */
+ data->secondary = chanctx_conf;
+ }
+ return;
+ }
+
+ /*
+ * STA / P2P Client, try to be primary if first vif. If we are in low
+ * latency mode, we are already in primary and just don't do much
+ */
+ if (!data->primary || data->primary == chanctx_conf)
+ data->primary = chanctx_conf;
+ else if (!data->secondary)
+ /* if secondary is not NULL, it might be a GO */
+ data->secondary = chanctx_conf;
+
+ /*
+ * don't reduce the Tx power if one of these is true:
+ * we are in LOOSE
+ * single share antenna product
+ * BT is active
+ * we are associated
+ */
+ if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
+ mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
+ !data->notif->bt_status) {
+ iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+ return;
+ }
+
+ /* try to get the avg rssi from fw */
+ ave_rssi = mvmvif->bf_data.ave_beacon_signal;
+
+ /* if the RSSI isn't valid, fake it is very low */
+ if (!ave_rssi)
+ ave_rssi = -100;
+ if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+ } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+ }
+
+ /* Begin to monitor the RSSI: it may influence the reduced Tx power */
+ iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
+}
+
+static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
+{
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ .notif = &mvm->last_bt_notif_old,
+ };
+ struct iwl_bt_coex_ci_cmd_old cmd = {};
+ u8 ci_bw_idx;
+
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return;
+
+ rcu_read_lock();
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_notif_iterator, &data);
+
+ if (data.primary) {
+ struct ieee80211_chanctx_conf *chan = data.primary;
+
+ if (WARN_ON(!chan->def.chan)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (chan->def.width < NL80211_CHAN_WIDTH_40) {
+ ci_bw_idx = 0;
+ cmd.co_run_bw_primary = 0;
+ } else {
+ cmd.co_run_bw_primary = 1;
+ if (chan->def.center_freq1 >
+ chan->def.chan->center_freq)
+ ci_bw_idx = 2;
+ else
+ ci_bw_idx = 1;
+ }
+
+ cmd.bt_primary_ci =
+ iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
+ cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
+ }
+
+ if (data.secondary) {
+ struct ieee80211_chanctx_conf *chan = data.secondary;
+
+ if (WARN_ON(!data.secondary->def.chan)) {
+ rcu_read_unlock();
+ return;
+ }
+
+ if (chan->def.width < NL80211_CHAN_WIDTH_40) {
+ ci_bw_idx = 0;
+ cmd.co_run_bw_secondary = 0;
+ } else {
+ cmd.co_run_bw_secondary = 1;
+ if (chan->def.center_freq1 >
+ chan->def.chan->center_freq)
+ ci_bw_idx = 2;
+ else
+ ci_bw_idx = 1;
+ }
+
+ cmd.bt_secondary_ci =
+ iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
+ cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
+ }
+
+ rcu_read_unlock();
+
+ /* Don't spam the fw with the same command over and over */
+ if (memcmp(&cmd, &mvm->last_bt_ci_cmd_old, sizeof(cmd))) {
+ if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
+ sizeof(cmd), &cmd))
+ IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
+ memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
+ }
+
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
+}
+
+int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *dev_cmd)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_bt_coex_profile_notif_old *notif = (void *)pkt->data;
+
+ IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
+ IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
+ notif->bt_status ? "ON" : "OFF");
+ IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
+ IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
+ IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
+ le32_to_cpu(notif->primary_ch_lut));
+ IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
+ le32_to_cpu(notif->secondary_ch_lut));
+ IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
+ le32_to_cpu(notif->bt_activity_grading));
+ IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
+ notif->bt_agg_traffic_load);
+
+ /* remember this notification for future use: rssi fluctuations */
+ memcpy(&mvm->last_bt_notif_old, notif, sizeof(mvm->last_bt_notif_old));
+
+ iwl_mvm_bt_coex_notif_handle(mvm);
+
+ /*
+ * This is an async handler for a notification, returning anything other
+ * than 0 doesn't make sense even if HCMD failed.
+ */
+ return 0;
+}
+
+static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
+
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ /* If channel context is invalid or not on 2.4GHz - don't count it */
+ if (!chanctx_conf ||
+ chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
+ rcu_read_unlock();
+ return;
+ }
+ rcu_read_unlock();
+
+ if (vif->type != NL80211_IFTYPE_STATION ||
+ mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+ return;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+
+ /* This can happen if the station has been removed right now */
+ if (IS_ERR_OR_NULL(sta))
+ return;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+}
+
+void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ };
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return;
+
+ /*
+ * Rssi update while not associated - can happen since the statistics
+ * are handled asynchronously
+ */
+ if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+ return;
+
+ /* No BT - reports should be disabled */
+ if (!mvm->last_bt_notif_old.bt_status)
+ return;
+
+ IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
+ rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
+
+ /*
+ * Check if rssi is good enough for reduced Tx power, but not in loose
+ * scheme.
+ */
+ if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
+ iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ false);
+ else
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
+
+ if (ret)
+ IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_rssi_iterator, &data);
+
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
+}
+
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000)
+#define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
+
+u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ enum iwl_bt_coex_lut_type lut_type;
+
+ if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
+ BT_HIGH_TRAFFIC)
+ return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+ if (mvm->last_bt_notif_old.ttc_enabled)
+ return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+ lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+
+ if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
+ return LINK_QUAL_AGG_TIME_LIMIT_DEF;
+
+ /* tight coex, high bt traffic, reduce AGG time limit */
+ return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
+}
+
+bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ enum iwl_bt_coex_lut_type lut_type;
+
+ if (mvm->last_bt_notif_old.ttc_enabled)
+ return true;
+
+ if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
+ BT_HIGH_TRAFFIC)
+ return true;
+
+ /*
+ * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
+ * since BT is already killed.
+ * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
+ * we Tx.
+ * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
+ */
+ lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
+ return lut_type != BT_COEX_LOOSE_LUT;
+}
+
+bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm)
+{
+ u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
+ return ag == BT_OFF;
+}
+
+bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm,
+ enum ieee80211_band band)
+{
+ u32 bt_activity =
+ le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
+
+ if (band != IEEE80211_BAND_2GHZ)
+ return false;
+
+ return bt_activity >= BT_LOW_TRAFFIC;
+}
+
+void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm)
+{
+ iwl_mvm_bt_coex_notif_handle(mvm);
+}
+
+int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *dev_cmd)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ u32 ant_isolation = le32_to_cpup((void *)pkt->data);
+ u8 __maybe_unused lower_bound, upper_bound;
+ int ret;
+ u8 lut;
+
+ struct iwl_bt_coex_cmd_old *bt_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = BT_CONFIG,
+ .len = { sizeof(*bt_cmd), },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ };
+
+ if (!IWL_MVM_BT_COEX_CORUNNING)
+ return 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* Ignore updates if we are in force mode */
+ if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
+ return 0;
+
+ if (ant_isolation == mvm->last_ant_isol)
+ return 0;
+
+ for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++)
+ if (ant_isolation < antenna_coupling_ranges[lut + 1].range)
+ break;
+
+ lower_bound = antenna_coupling_ranges[lut].range;
+
+ if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1)
+ upper_bound = antenna_coupling_ranges[lut + 1].range;
+ else
+ upper_bound = antenna_coupling_ranges[lut].range;
+
+ IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n",
+ ant_isolation, lower_bound, upper_bound, lut);
+
+ mvm->last_ant_isol = ant_isolation;
+
+ if (mvm->last_corun_lut == lut)
+ return 0;
+
+ mvm->last_corun_lut = lut;
+
+ bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
+ if (!bt_cmd)
+ return 0;
+ cmd.data[0] = bt_cmd;
+
+ bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
+ BT_VALID_CORUN_LUT_20 |
+ BT_VALID_CORUN_LUT_40);
+
+ /* For the moment, use the same LUT for 20GHz and 40GHz */
+ memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
+ sizeof(bt_cmd->bt4_corun_lut20));
+
+ memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
+ sizeof(bt_cmd->bt4_corun_lut40));
+
+ ret = iwl_mvm_send_cmd(mvm, &cmd);
+
+ kfree(bt_cmd);
+ return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index 51685693af2e..ca79f7160573 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -79,6 +79,8 @@
#define IWL_MVM_PS_SNOOZE_WINDOW 50
#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25
#define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64
+#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH 62
+#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH 65
#define IWL_MVM_BT_COEX_SYNC2SCO 1
#define IWL_MVM_BT_COEX_CORUNNING 1
#define IWL_MVM_BT_COEX_MPLUT 1
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 29ca72695eaa..7d18f466fbb3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct iwl_fw_error_dump_file *dump_file = file->private_data;
+ struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+ ssize_t bytes_read = 0;
+ ssize_t bytes_read_trans = 0;
+
+ if (*ppos < dump_ptrs->op_mode_len)
+ bytes_read +=
+ simple_read_from_buffer(user_buf, count, ppos,
+ dump_ptrs->op_mode_ptr,
+ dump_ptrs->op_mode_len);
+
+ if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
+ return bytes_read;
+
+ if (dump_ptrs->trans_ptr) {
+ *ppos -= dump_ptrs->op_mode_len;
+ bytes_read_trans =
+ simple_read_from_buffer(user_buf + bytes_read,
+ count - bytes_read, ppos,
+ dump_ptrs->trans_ptr->data,
+ dump_ptrs->trans_ptr->len);
+ *ppos += dump_ptrs->op_mode_len;
+
+ if (bytes_read_trans >= 0)
+ bytes_read += bytes_read_trans;
+ else if (!bytes_read)
+ /* propagate the failure */
+ return bytes_read_trans;
+ }
+
+ return bytes_read;
- return simple_read_from_buffer(user_buf, count, ppos,
- dump_file,
- le32_to_cpu(dump_file->file_len));
}
static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
struct file *file)
{
- vfree(file->private_data);
+ struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+
+ vfree(dump_ptrs->op_mode_ptr);
+ vfree(dump_ptrs->trans_ptr);
+ kfree(dump_ptrs);
return 0;
}
@@ -312,20 +342,69 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
BT_MBOX_MSG(notif, _num, _field), \
true ? "\n" : ", ");
-static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
+static
+int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
+ int pos, int bufsz)
{
- struct iwl_mvm *mvm = file->private_data;
- struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
- char *buf;
- int ret, pos = 0, bufsz = sizeof(char) * 1024;
+ pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
- buf = kmalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
+ BT_MBOX_PRINT(0, LE_PROF1, false);
+ BT_MBOX_PRINT(0, LE_PROF2, false);
+ BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
+ BT_MBOX_PRINT(0, CHL_SEQ_N, false);
+ BT_MBOX_PRINT(0, INBAND_S, false);
+ BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
+ BT_MBOX_PRINT(0, LE_SCAN, false);
+ BT_MBOX_PRINT(0, LE_ADV, false);
+ BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
+ BT_MBOX_PRINT(0, OPEN_CON_1, true);
- mutex_lock(&mvm->mutex);
+ pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
+
+ BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
+ BT_MBOX_PRINT(1, IP_SR, false);
+ BT_MBOX_PRINT(1, LE_MSTR, false);
+ BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
+ BT_MBOX_PRINT(1, MSG_TYPE, false);
+ BT_MBOX_PRINT(1, SSN, true);
+
+ pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
+
+ BT_MBOX_PRINT(2, SNIFF_ACT, false);
+ BT_MBOX_PRINT(2, PAG, false);
+ BT_MBOX_PRINT(2, INQUIRY, false);
+ BT_MBOX_PRINT(2, CONN, false);
+ BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
+ BT_MBOX_PRINT(2, DISC, false);
+ BT_MBOX_PRINT(2, SCO_TX_ACT, false);
+ BT_MBOX_PRINT(2, SCO_RX_ACT, false);
+ BT_MBOX_PRINT(2, ESCO_RE_TX, false);
+ BT_MBOX_PRINT(2, SCO_DURATION, true);
+
+ pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
+
+ BT_MBOX_PRINT(3, SCO_STATE, false);
+ BT_MBOX_PRINT(3, SNIFF_STATE, false);
+ BT_MBOX_PRINT(3, A2DP_STATE, false);
+ BT_MBOX_PRINT(3, ACL_STATE, false);
+ BT_MBOX_PRINT(3, MSTR_STATE, false);
+ BT_MBOX_PRINT(3, OBX_STATE, false);
+ BT_MBOX_PRINT(3, OPEN_CON_2, false);
+ BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
+ BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
+ BT_MBOX_PRINT(3, INBAND_P, false);
+ BT_MBOX_PRINT(3, MSG_TYPE_2, false);
+ BT_MBOX_PRINT(3, SSN_2, false);
+ BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
+
+ return pos;
+}
+static
+int iwl_mvm_coex_dump_mbox_old(struct iwl_bt_coex_profile_notif_old *notif,
+ char *buf, int pos, int bufsz)
+{
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
@@ -378,25 +457,59 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
BT_MBOX_PRINT(3, SSN_2, false);
BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
- pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
- notif->bt_status);
- pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
- notif->bt_open_conn);
- pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
- notif->bt_traffic_load);
- pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
- notif->bt_agg_traffic_load);
- pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
- notif->bt_ci_compliance);
- pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
- le32_to_cpu(notif->primary_ch_lut));
- pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
- le32_to_cpu(notif->secondary_ch_lut));
- pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n",
- le32_to_cpu(notif->bt_activity_grading));
- pos += scnprintf(buf+pos, bufsz-pos,
- "antenna isolation = %d CORUN LUT index = %d\n",
- mvm->last_ant_isol, mvm->last_corun_lut);
+ return pos;
+}
+
+static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ char *buf;
+ int ret, pos = 0, bufsz = sizeof(char) * 1024;
+
+ buf = kmalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&mvm->mutex);
+
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+ struct iwl_bt_coex_profile_notif_old *notif =
+ &mvm->last_bt_notif_old;
+
+ pos += iwl_mvm_coex_dump_mbox_old(notif, buf, pos, bufsz);
+
+ pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
+ notif->bt_ci_compliance);
+ pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
+ le32_to_cpu(notif->primary_ch_lut));
+ pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
+ le32_to_cpu(notif->secondary_ch_lut));
+ pos += scnprintf(buf+pos,
+ bufsz-pos, "bt_activity_grading = %d\n",
+ le32_to_cpu(notif->bt_activity_grading));
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "antenna isolation = %d CORUN LUT index = %d\n",
+ mvm->last_ant_isol, mvm->last_corun_lut);
+ } else {
+ struct iwl_bt_coex_profile_notif *notif =
+ &mvm->last_bt_notif;
+
+ pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
+
+ pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
+ notif->bt_ci_compliance);
+ pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n",
+ le32_to_cpu(notif->primary_ch_lut));
+ pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n",
+ le32_to_cpu(notif->secondary_ch_lut));
+ pos += scnprintf(buf+pos,
+ bufsz-pos, "bt_activity_grading = %d\n",
+ le32_to_cpu(notif->bt_activity_grading));
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "antenna isolation = %d CORUN LUT index = %d\n",
+ mvm->last_ant_isol, mvm->last_corun_lut);
+ }
mutex_unlock(&mvm->mutex);
@@ -411,28 +524,57 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
- struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
char buf[256];
int bufsz = sizeof(buf);
int pos = 0;
mutex_lock(&mvm->mutex);
- pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n");
- pos += scnprintf(buf+pos, bufsz-pos,
- "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n",
- le64_to_cpu(cmd->bt_primary_ci),
- !!cmd->co_run_bw_primary);
- pos += scnprintf(buf+pos, bufsz-pos,
- "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n",
- le64_to_cpu(cmd->bt_secondary_ci),
- !!cmd->co_run_bw_secondary);
-
- pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
- pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
- iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
- pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
- iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
+ struct iwl_bt_coex_ci_cmd_old *cmd = &mvm->last_bt_ci_cmd_old;
+
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "Channel inhibition CMD\n");
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tPrimary Channel Bitmap 0x%016llx\n",
+ le64_to_cpu(cmd->bt_primary_ci));
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tSecondary Channel Bitmap 0x%016llx\n",
+ le64_to_cpu(cmd->bt_secondary_ci));
+
+ pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
+ pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
+ pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
+
+ } else {
+ struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
+
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "Channel inhibition CMD\n");
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tPrimary Channel Bitmap 0x%016llx\n",
+ le64_to_cpu(cmd->bt_primary_ci));
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tSecondary Channel Bitmap 0x%016llx\n",
+ le64_to_cpu(cmd->bt_secondary_ci));
+
+ pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tPrimary: ACK Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tPrimary: CTS Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tSecondary: ACK Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]);
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\tSecondary: CTS Kill Mask 0x%08x\n",
+ iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]);
+
+ }
mutex_unlock(&mvm->mutex);
@@ -455,6 +597,43 @@ iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
return count;
}
+static ssize_t
+iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
+ size_t count, loff_t *ppos)
+{
+ static const char * const modes_str[BT_FORCE_ANT_MAX] = {
+ [BT_FORCE_ANT_DIS] = "dis",
+ [BT_FORCE_ANT_AUTO] = "auto",
+ [BT_FORCE_ANT_BT] = "bt",
+ [BT_FORCE_ANT_WIFI] = "wifi",
+ };
+ int ret, bt_force_ant_mode;
+
+ for (bt_force_ant_mode = 0;
+ bt_force_ant_mode < ARRAY_SIZE(modes_str);
+ bt_force_ant_mode++) {
+ if (!strcmp(buf, modes_str[bt_force_ant_mode]))
+ break;
+ }
+
+ if (bt_force_ant_mode >= ARRAY_SIZE(modes_str))
+ return -EINVAL;
+
+ ret = 0;
+ mutex_lock(&mvm->mutex);
+ if (mvm->bt_force_ant_mode == bt_force_ant_mode)
+ goto out;
+
+ mvm->bt_force_ant_mode = bt_force_ant_mode;
+ IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
+ modes_str[mvm->bt_force_ant_mode]);
+ ret = iwl_send_bt_init_conf(mvm);
+
+out:
+ mutex_unlock(&mvm->mutex);
+ return ret ?: count;
+}
+
#define PRINT_STATS_LE32(_str, _val) \
pos += scnprintf(buf + pos, bufsz - pos, \
fmt_table, _str, \
@@ -690,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
+ int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
+ if (ret)
+ return ret;
+
iwl_force_nmi(mvm->trans);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
+
return count;
}
@@ -975,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
}
#endif
-#define PRINT_MVM_REF(ref) do { \
- if (test_bit(ref, mvm->ref_bitmap)) \
- pos += scnprintf(buf + pos, bufsz - pos, \
- "\t(0x%lx) %s\n", \
- BIT(ref), #ref); \
+#define PRINT_MVM_REF(ref) do { \
+ if (mvm->refs[ref]) \
+ pos += scnprintf(buf + pos, bufsz - pos, \
+ "\t(0x%lx): %d %s\n", \
+ BIT(ref), mvm->refs[ref], #ref); \
} while (0)
static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@@ -987,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
- int pos = 0;
+ int i, pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
+ u32 refs = 0;
+
+ for (i = 0; i < IWL_MVM_REF_COUNT; i++)
+ if (mvm->refs[i])
+ refs |= BIT(i);
- pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
- mvm->ref_bitmap[0]);
+ pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
+ refs);
PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@@ -1018,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
mutex_lock(&mvm->mutex);
- taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
+ taken = mvm->refs[IWL_MVM_REF_USER];
if (value == 1 && !taken)
iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
else if (value == 0 && taken)
@@ -1054,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
+ int ret;
if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
+ if (ret)
+ return ret;
+
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
+
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1071,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8 args;
u32 value;
+ int ret;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */
@@ -1081,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if (args != 2)
return -EINVAL;
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
+ if (ret)
+ return ret;
+
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
out:
return count;
}
@@ -1101,6 +1305,7 @@ MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
+MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
@@ -1142,6 +1347,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR);
+ MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index 5fe82c29c8ad..69875716dcdb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -72,10 +72,13 @@
* enum iwl_bt_coex_flags - flags for BT_COEX command
* @BT_COEX_MODE_POS:
* @BT_COEX_MODE_MSK:
- * @BT_COEX_DISABLE:
- * @BT_COEX_2W:
- * @BT_COEX_3W:
- * @BT_COEX_NW:
+ * @BT_COEX_DISABLE_OLD:
+ * @BT_COEX_2W_OLD:
+ * @BT_COEX_3W_OLD:
+ * @BT_COEX_NW_OLD:
+ * @BT_COEX_AUTO_OLD:
+ * @BT_COEX_BT_OLD: Antenna is for BT (manufacuring tests)
+ * @BT_COEX_WIFI_OLD: Antenna is for BT (manufacuring tests)
* @BT_COEX_SYNC2SCO:
* @BT_COEX_CORUNNING:
* @BT_COEX_MPLUT:
@@ -85,10 +88,13 @@
enum iwl_bt_coex_flags {
BT_COEX_MODE_POS = 3,
BT_COEX_MODE_MSK = BITS(3) << BT_COEX_MODE_POS,
- BT_COEX_DISABLE = 0x0 << BT_COEX_MODE_POS,
- BT_COEX_2W = 0x1 << BT_COEX_MODE_POS,
- BT_COEX_3W = 0x2 << BT_COEX_MODE_POS,
- BT_COEX_NW = 0x3 << BT_COEX_MODE_POS,
+ BT_COEX_DISABLE_OLD = 0x0 << BT_COEX_MODE_POS,
+ BT_COEX_2W_OLD = 0x1 << BT_COEX_MODE_POS,
+ BT_COEX_3W_OLD = 0x2 << BT_COEX_MODE_POS,
+ BT_COEX_NW_OLD = 0x3 << BT_COEX_MODE_POS,
+ BT_COEX_AUTO_OLD = 0x5 << BT_COEX_MODE_POS,
+ BT_COEX_BT_OLD = 0x6 << BT_COEX_MODE_POS,
+ BT_COEX_WIFI_OLD = 0x7 << BT_COEX_MODE_POS,
BT_COEX_SYNC2SCO = BIT(7),
BT_COEX_CORUNNING = BIT(8),
BT_COEX_MPLUT = BIT(9),
@@ -151,7 +157,7 @@ enum iwl_bt_coex_lut_type {
#define BT_REDUCED_TX_POWER_BIT BIT(7)
/**
- * struct iwl_bt_coex_cmd - bt coex configuration command
+ * struct iwl_bt_coex_cmd_old - bt coex configuration command
* @flags:&enum iwl_bt_coex_flags
* @max_kill:
* @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
@@ -176,7 +182,7 @@ enum iwl_bt_coex_lut_type {
*
* The structure is used for the BT_COEX command.
*/
-struct iwl_bt_coex_cmd {
+struct iwl_bt_coex_cmd_old {
__le32 flags;
u8 max_kill;
u8 bt_reduced_tx_power;
@@ -202,26 +208,117 @@ struct iwl_bt_coex_cmd {
__le32 valid_bit_msk;
} __packed; /* BT_COEX_CMD_API_S_VER_5 */
+enum iwl_bt_coex_mode {
+ BT_COEX_DISABLE = 0x0,
+ BT_COEX_NW = 0x1,
+ BT_COEX_BT = 0x2,
+ BT_COEX_WIFI = 0x3,
+}; /* BT_COEX_MODES_E */
+
+enum iwl_bt_coex_enabled_modules {
+ BT_COEX_MPLUT_ENABLED = BIT(0),
+ BT_COEX_MPLUT_BOOST_ENABLED = BIT(1),
+ BT_COEX_SYNC2SCO_ENABLED = BIT(2),
+ BT_COEX_CORUN_ENABLED = BIT(3),
+ BT_COEX_HIGH_BAND_RET = BIT(4),
+}; /* BT_COEX_MODULES_ENABLE_E_VER_1 */
+
+/**
+ * struct iwl_bt_coex_cmd - bt coex configuration command
+ * @mode: enum %iwl_bt_coex_mode
+ * @enabled_modules: enum %iwl_bt_coex_enabled_modules
+ * @max_kill: max count of Tx retries due to kill from PTA
+ * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ * should be set by default
+ * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ * should be set by default
+ * @bt4_antenna_isolation_thr: antenna threshold value
+ * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency
+ * @bt4_tx_rx_max_freq0: TxRx max frequency
+ * @multiprio_lut: multi priority LUT configuration
+ * @mplut_prio_boost: BT priority boost registers
+ * @decision_lut: PTA decision LUT, per Prio-Ch
+ *
+ * The structure is used for the BT_COEX command.
+ */
+struct iwl_bt_coex_cmd {
+ __le32 mode;
+ __le32 enabled_modules;
+
+ __le32 max_kill;
+ __le32 override_primary_lut;
+ __le32 override_secondary_lut;
+ __le32 bt4_antenna_isolation_thr;
+
+ __le32 bt4_tx_tx_delta_freq_thr;
+ __le32 bt4_tx_rx_max_freq0;
+
+ __le32 multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE];
+ __le32 mplut_prio_boost[BT_COEX_BOOST_SIZE];
+
+ __le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE];
+} __packed; /* BT_COEX_CMD_API_S_VER_6 */
+
+/**
+ * struct iwl_bt_coex_corun_lut_update - bt coex update the corun lut
+ * @corun_lut20: co-running 20 MHz LUT configuration
+ * @corun_lut40: co-running 40 MHz LUT configuration
+ *
+ * The structure is used for the BT_COEX_UPDATE_CORUN_LUT command.
+ */
+struct iwl_bt_coex_corun_lut_update_cmd {
+ __le32 corun_lut20[BT_COEX_CORUN_LUT_SIZE];
+ __le32 corun_lut40[BT_COEX_CORUN_LUT_SIZE];
+} __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_sw_boost - SW boost values
+ * @wifi_tx_prio_boost: SW boost of wifi tx priority
+ * @wifi_rx_prio_boost: SW boost of wifi rx priority
+ * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK.
+ * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS.
+ */
+struct iwl_bt_coex_sw_boost {
+ __le32 wifi_tx_prio_boost;
+ __le32 wifi_rx_prio_boost;
+ __le32 kill_ack_msk;
+ __le32 kill_cts_msk;
+};
+
+/**
+ * struct iwl_bt_coex_sw_boost_update_cmd - command to update the SW boost
+ * @boost_values: check struct %iwl_bt_coex_sw_boost - one for each channel
+ * primary / secondary / low priority
+ */
+struct iwl_bt_coex_sw_boost_update_cmd {
+ struct iwl_bt_coex_sw_boost boost_values[3];
+} __packed; /* BT_COEX_UPDATE_SW_BOOST_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_reduced_txp_update_cmd
+ * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the
+ * bits are the sta_id (value)
+ */
+struct iwl_bt_coex_reduced_txp_update_cmd {
+ __le32 reduced_txp;
+} __packed; /* BT_COEX_UPDATE_REDUCED_TX_POWER_API_S_VER_1 */
+
/**
* struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
* @bt_primary_ci:
- * @bt_secondary_ci:
- * @co_run_bw_primary:
- * @co_run_bw_secondary:
* @primary_ch_phy_id:
+ * @bt_secondary_ci:
* @secondary_ch_phy_id:
*
* Used for BT_COEX_CI command
*/
struct iwl_bt_coex_ci_cmd {
__le64 bt_primary_ci;
- __le64 bt_secondary_ci;
+ __le32 primary_ch_phy_id;
- u8 co_run_bw_primary;
- u8 co_run_bw_secondary;
- u8 primary_ch_phy_id;
- u8 secondary_ch_phy_id;
-} __packed; /* BT_CI_MSG_API_S_VER_1 */
+ __le64 bt_secondary_ci;
+ __le32 secondary_ch_phy_id;
+} __packed; /* BT_CI_MSG_API_S_VER_2 */
#define BT_MBOX(n_dw, _msg, _pos, _nbits) \
BT_MBOX##n_dw##_##_msg##_POS = (_pos), \
@@ -288,35 +385,44 @@ enum iwl_bt_activity_grading {
BT_ON_NO_CONNECTION = 1,
BT_LOW_TRAFFIC = 2,
BT_HIGH_TRAFFIC = 3,
+
+ BT_MAX_AG,
}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
+enum iwl_bt_ci_compliance {
+ BT_CI_COMPLIANCE_NONE = 0,
+ BT_CI_COMPLIANCE_PRIMARY = 1,
+ BT_CI_COMPLIANCE_SECONDARY = 2,
+ BT_CI_COMPLIANCE_BOTH = 3,
+}; /* BT_COEX_CI_COMPLIENCE_E_VER_1 */
+
+#define IWL_COEX_IS_TTC_ON(_ttc_rrc_status, _phy_id) \
+ (_ttc_rrc_status & BIT(_phy_id))
+
+#define IWL_COEX_IS_RRC_ON(_ttc_rrc_status, _phy_id) \
+ ((_ttc_rrc_status >> 4) & BIT(_phy_id))
+
/**
* struct iwl_bt_coex_profile_notif - notification about BT coex
* @mbox_msg: message from BT to WiFi
* @msg_idx: the index of the message
- * @bt_status: 0 - off, 1 - on
- * @bt_open_conn: number of BT connections open
- * @bt_traffic_load: load of BT traffic
- * @bt_agg_traffic_load: aggregated load of BT traffic
- * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
- * @primary_ch_lut: LUT used for primary channel
- * @secondary_ch_lut: LUT used for secondary channel
+ * @bt_ci_compliance: enum %iwl_bt_ci_compliance
+ * @primary_ch_lut: LUT used for primary channel enum %iwl_bt_coex_lut_type
+ * @secondary_ch_lut: LUT used for secondary channel enume %iwl_bt_coex_lut_type
* @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ * @ttc_rrc_status: is TTC or RRC enabled - one bit per PHY
*/
struct iwl_bt_coex_profile_notif {
__le32 mbox_msg[4];
__le32 msg_idx;
- u8 bt_status;
- u8 bt_open_conn;
- u8 bt_traffic_load;
- u8 bt_agg_traffic_load;
- u8 bt_ci_compliance;
- u8 reserved[3];
+ __le32 bt_ci_compliance;
__le32 primary_ch_lut;
__le32 secondary_ch_lut;
__le32 bt_activity_grading;
-} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */
+ u8 ttc_rrc_status;
+ u8 reserved[3];
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_4 */
enum iwl_bt_coex_prio_table_event {
BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0,
@@ -355,4 +461,54 @@ struct iwl_bt_coex_prio_tbl_cmd {
u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
} __packed;
+/**
+ * struct iwl_bt_coex_ci_cmd_old - bt coex channel inhibition command
+ * @bt_primary_ci:
+ * @bt_secondary_ci:
+ * @co_run_bw_primary:
+ * @co_run_bw_secondary:
+ * @primary_ch_phy_id:
+ * @secondary_ch_phy_id:
+ *
+ * Used for BT_COEX_CI command
+ */
+struct iwl_bt_coex_ci_cmd_old {
+ __le64 bt_primary_ci;
+ __le64 bt_secondary_ci;
+
+ u8 co_run_bw_primary;
+ u8 co_run_bw_secondary;
+ u8 primary_ch_phy_id;
+ u8 secondary_ch_phy_id;
+} __packed; /* BT_CI_MSG_API_S_VER_1 */
+
+/**
+ * struct iwl_bt_coex_profile_notif_old - notification about BT coex
+ * @mbox_msg: message from BT to WiFi
+ * @msg_idx: the index of the message
+ * @bt_status: 0 - off, 1 - on
+ * @bt_open_conn: number of BT connections open
+ * @bt_traffic_load: load of BT traffic
+ * @bt_agg_traffic_load: aggregated load of BT traffic
+ * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
+ * @primary_ch_lut: LUT used for primary channel
+ * @secondary_ch_lut: LUT used for secondary channel
+ * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading
+ */
+struct iwl_bt_coex_profile_notif_old {
+ __le32 mbox_msg[4];
+ __le32 msg_idx;
+ u8 bt_status;
+ u8 bt_open_conn;
+ u8 bt_traffic_load;
+ u8 bt_agg_traffic_load;
+ u8 bt_ci_compliance;
+ u8 ttc_enabled;
+ __le16 reserved;
+
+ __le32 primary_ch_lut;
+ __le32 secondary_ch_lut;
+ __le32 bt_activity_grading;
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */
+
#endif /* __fw_api_bt_coex_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index cbbcd8e284e4..c3a8c86b550d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -336,7 +336,7 @@ struct iwl_beacon_filter_cmd {
#define IWL_BF_DEBUG_FLAG_D0I3 0
#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
-#define IWL_BF_ESCAPE_TIMER_D0I3 1024
+#define IWL_BF_ESCAPE_TIMER_D0I3 0
#define IWL_BF_ESCAPE_TIMER_MAX 1024
#define IWL_BF_ESCAPE_TIMER_MIN 0
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 6959fda3fe09..c02a9e45ec5e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -170,18 +170,12 @@ enum iwl_scan_type {
}; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
/**
- * Maximal number of channels to scan
- * it should be equal to:
- * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000)
- */
-#define MAX_NUM_SCAN_CHANNELS 50
-
-/**
* struct iwl_scan_cmd - scan request command
* ( SCAN_REQUEST_CMD = 0x80 )
* @len: command length in bytes
* @scan_flags: scan flags from SCAN_FLAGS_*
- * @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS)
+ * @channel_count: num of channels in channel list
+ * (1 - ucode_capa.n_scan_channels)
* @quiet_time: in msecs, dwell this time for active scan on quiet channels
* @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
* this number of packets were received (typically 1)
@@ -345,7 +339,7 @@ struct iwl_scan_results_notif {
* @last_channel: last channel that was scanned
* @tsf_low: TSF timer (lower half) in usecs
* @tsf_high: TSF timer (higher half) in usecs
- * @results: all scan results, only "scanned_channels" of them are valid
+ * @results: array of scan results, only "scanned_channels" of them are valid
*/
struct iwl_scan_complete_notif {
u8 scanned_channels;
@@ -354,11 +348,10 @@ struct iwl_scan_complete_notif {
u8 last_channel;
__le32 tsf_low;
__le32 tsf_high;
- struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS];
+ struct iwl_scan_results_notif results[];
} __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
/* scan offload */
-#define IWL_MAX_SCAN_CHANNELS 40
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
#define IWL_SCAN_MAX_PROFILES 11
@@ -423,36 +416,24 @@ enum iwl_scan_offload_channel_flags {
IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL = BIT(25),
};
-/**
- * iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S
- * @type: bitmap - see enum iwl_scan_offload_channel_flags.
- * 0: passive (0) or active (1) scan.
- * 1-20: directed scan to i'th ssid.
- * 22: channel width configuation - 1 for narrow.
- * 24: full scan.
- * 25: partial scan.
- * @channel_number: channel number 1-13 etc.
- * @iter_count: repetition count for the channel.
- * @iter_interval: interval between two innteration on one channel.
- * @dwell_time: entry 0 - active scan, entry 1 - passive scan.
+/* channel configuration for struct iwl_scan_offload_cfg. Each channels needs:
+ * __le32 type: bitmap; bits 1-20 are for directed scan to i'th ssid and
+ * see enum iwl_scan_offload_channel_flags.
+ * __le16 channel_number: channel number 1-13 etc.
+ * __le16 iter_count: repetition count for the channel.
+ * __le32 iter_interval: interval between two innteration on one channel.
+ * u8 active_dwell.
+ * u8 passive_dwell.
*/
-struct iwl_scan_channel_cfg {
- __le32 type[IWL_MAX_SCAN_CHANNELS];
- __le16 channel_number[IWL_MAX_SCAN_CHANNELS];
- __le16 iter_count[IWL_MAX_SCAN_CHANNELS];
- __le32 iter_interval[IWL_MAX_SCAN_CHANNELS];
- u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2];
-} __packed;
+#define IWL_SCAN_CHAN_SIZE 14
/**
* iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S
* @scan_cmd: scan command fixed part
- * @channel_cfg: scan channel configuration
- * @data: probe request frames (one per band)
+ * @data: scan channel configuration and probe request frames
*/
struct iwl_scan_offload_cfg {
struct iwl_scan_offload_cmd scan_cmd;
- struct iwl_scan_channel_cfg channel_cfg;
u8 data[0];
} __packed;
@@ -528,7 +509,7 @@ struct iwl_scan_offload_profile_cfg {
* @full_scan_mul: number of partial scans before each full scan
*/
struct iwl_scan_offload_schedule {
- u16 delay;
+ __le16 delay;
u8 iterations;
u8 full_scan_mul;
} __packed;
@@ -601,4 +582,211 @@ struct iwl_sched_scan_results {
u8 reserved;
};
+/* Unified LMAC scan API */
+
+#define IWL_MVM_BASIC_PASSIVE_DWELL 110
+
+/**
+ * iwl_scan_req_tx_cmd - SCAN_REQ_TX_CMD_API_S
+ * @tx_flags: combination of TX_CMD_FLG_*
+ * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
+ * cleared. Combination of RATE_MCS_*
+ * @sta_id: index of destination station in FW station table
+ * @reserved: for alignment and future use
+ */
+struct iwl_scan_req_tx_cmd {
+ __le32 tx_flags;
+ __le32 rate_n_flags;
+ u8 sta_id;
+ u8 reserved[3];
+} __packed;
+
+enum iwl_scan_channel_flags_lmac {
+ IWL_UNIFIED_SCAN_CHANNEL_FULL = BIT(27),
+ IWL_UNIFIED_SCAN_CHANNEL_PARTIAL = BIT(28),
+};
+
+/**
+ * iwl_scan_channel_cfg_lmac - SCAN_CHANNEL_CFG_S_VER2
+ * @flags: bits 1-20: directed scan to i'th ssid
+ * other bits &enum iwl_scan_channel_flags_lmac
+ * @channel_number: channel number 1-13 etc
+ * @iter_count: scan iteration on this channel
+ * @iter_interval: interval in seconds between iterations on one channel
+ */
+struct iwl_scan_channel_cfg_lmac {
+ __le32 flags;
+ __le16 channel_num;
+ __le16 iter_count;
+ __le32 iter_interval;
+} __packed;
+
+/*
+ * iwl_scan_probe_segment - PROBE_SEGMENT_API_S_VER_1
+ * @offset: offset in the data block
+ * @len: length of the segment
+ */
+struct iwl_scan_probe_segment {
+ __le16 offset;
+ __le16 len;
+} __packed;
+
+/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_2
+ * @mac_header: first (and common) part of the probe
+ * @band_data: band specific data
+ * @common_data: last (and common) part of the probe
+ * @buf: raw data block
+ */
+struct iwl_scan_probe_req {
+ struct iwl_scan_probe_segment mac_header;
+ struct iwl_scan_probe_segment band_data[2];
+ struct iwl_scan_probe_segment common_data;
+ u8 buf[SCAN_OFFLOAD_PROBE_REQ_SIZE];
+} __packed;
+
+enum iwl_scan_channel_flags {
+ IWL_SCAN_CHANNEL_FLAG_EBS = BIT(0),
+ IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE = BIT(1),
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD = BIT(2),
+};
+
+/* iwl_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S
+ * @flags: enum iwl_scan_channel_flgs
+ * @non_ebs_ratio: how many regular scan iteration before EBS
+ */
+struct iwl_scan_channel_opt {
+ __le16 flags;
+ __le16 non_ebs_ratio;
+} __packed;
+
+/**
+ * iwl_mvm_lmac_scan_flags
+ * @IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL: pass all beacons and probe responses
+ * without filtering.
+ * @IWL_MVM_LMAC_SCAN_FLAG_PASSIVE: force passive scan on all channels
+ * @IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION: single channel scan
+ * @IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE: send iteration complete notification
+ * @IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS multiple SSID matching
+ * @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented
+ */
+enum iwl_mvm_lmac_scan_flags {
+ IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL = BIT(0),
+ IWL_MVM_LMAC_SCAN_FLAG_PASSIVE = BIT(1),
+ IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION = BIT(2),
+ IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE = BIT(3),
+ IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS = BIT(4),
+ IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED = BIT(5),
+};
+
+enum iwl_scan_priority {
+ IWL_SCAN_PRIORITY_LOW,
+ IWL_SCAN_PRIORITY_MEDIUM,
+ IWL_SCAN_PRIORITY_HIGH,
+};
+
+/**
+ * iwl_scan_req_unified_lmac - SCAN_REQUEST_CMD_API_S_VER_1
+ * @reserved1: for alignment and future use
+ * @channel_num: num of channels to scan
+ * @active-dwell: dwell time for active channels
+ * @passive-dwell: dwell time for passive channels
+ * @fragmented-dwell: dwell time for fragmented passive scan
+ * @reserved2: for alignment and future use
+ * @rx_chain_selct: PHY_RX_CHAIN_* flags
+ * @scan_flags: &enum iwl_mvm_lmac_scan_flags
+ * @max_out_time: max time (in TU) to be out of associated channel
+ * @suspend_time: pause scan this long (TUs) when returning to service channel
+ * @flags: RXON flags
+ * @filter_flags: RXON filter
+ * @tx_cmd: tx command for active scan; for 2GHz and for 5GHz
+ * @direct_scan: list of SSIDs for directed active scan
+ * @scan_prio: enum iwl_scan_priority
+ * @iter_num: number of scan iterations
+ * @delay: delay in seconds before first iteration
+ * @schedule: two scheduling plans. The first one is finite, the second one can
+ * be infinite.
+ * @channel_opt: channel optimization options, for full and partial scan
+ * @data: channel configuration and probe request packet.
+ */
+struct iwl_scan_req_unified_lmac {
+ /* SCAN_REQUEST_FIXED_PART_API_S_VER_7 */
+ __le32 reserved1;
+ u8 n_channels;
+ u8 active_dwell;
+ u8 passive_dwell;
+ u8 fragmented_dwell;
+ __le16 reserved2;
+ __le16 rx_chain_select;
+ __le32 scan_flags;
+ __le32 max_out_time;
+ __le32 suspend_time;
+ /* RX_ON_FLAGS_API_S_VER_1 */
+ __le32 flags;
+ __le32 filter_flags;
+ struct iwl_scan_req_tx_cmd tx_cmd[2];
+ struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
+ __le32 scan_prio;
+ /* SCAN_REQ_PERIODIC_PARAMS_API_S */
+ __le32 iter_num;
+ __le32 delay;
+ struct iwl_scan_offload_schedule schedule[2];
+ struct iwl_scan_channel_opt channel_opt[2];
+ u8 data[];
+} __packed;
+
+/**
+ * struct iwl_lmac_scan_results_notif - scan results for one channel -
+ * SCAN_RESULT_NTF_API_S_VER_3
+ * @channel: which channel the results are from
+ * @band: 0 for 5.2 GHz, 1 for 2.4 GHz
+ * @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
+ * @num_probe_not_sent: # of request that weren't sent due to not enough time
+ * @duration: duration spent in channel, in usecs
+ */
+struct iwl_lmac_scan_results_notif {
+ u8 channel;
+ u8 band;
+ u8 probe_status;
+ u8 num_probe_not_sent;
+ __le32 duration;
+} __packed;
+
+/**
+ * struct iwl_lmac_scan_complete_notif - notifies end of scanning (all channels)
+ * SCAN_COMPLETE_NTF_API_S_VER_3
+ * @scanned_channels: number of channels scanned (and number of valid results)
+ * @status: one of SCAN_COMP_STATUS_*
+ * @bt_status: BT on/off status
+ * @last_channel: last channel that was scanned
+ * @tsf_low: TSF timer (lower half) in usecs
+ * @tsf_high: TSF timer (higher half) in usecs
+ * @results: an array of scan results, only "scanned_channels" of them are valid
+ */
+struct iwl_lmac_scan_complete_notif {
+ u8 scanned_channels;
+ u8 status;
+ u8 bt_status;
+ u8 last_channel;
+ __le32 tsf_low;
+ __le32 tsf_high;
+ struct iwl_scan_results_notif results[];
+} __packed;
+
+/**
+ * iwl_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2
+ * @last_schedule_line: last schedule line executed (fast or regular)
+ * @last_schedule_iteration: last scan iteration executed before scan abort
+ * @status: enum iwl_scan_offload_complete_status
+ * @ebs_status: EBS success status &enum iwl_scan_ebs_status
+ * @time_after_last_iter; time in seconds elapsed after last iteration
+ */
+struct iwl_periodic_scan_complete {
+ u8 last_schedule_line;
+ u8 last_schedule_iteration;
+ u8 status;
+ u8 ebs_status;
+ __le32 time_after_last_iter;
+ __le32 reserved;
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
index 39cebee8016f..47bd0406355d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
@@ -67,7 +67,7 @@
* enum iwl_sta_flags - flags for the ADD_STA host command
* @STA_FLG_REDUCED_TX_PWR_CTRL:
* @STA_FLG_REDUCED_TX_PWR_DATA:
- * @STA_FLG_FLG_ANT_MSK: Antenna selection
+ * @STA_FLG_DISABLE_TX: set if TX should be disabled
* @STA_FLG_PS: set if STA is in Power Save
* @STA_FLG_INVALID: set if STA is invalid
* @STA_FLG_DLP_EN: Direct Link Protocol is enabled
@@ -91,10 +91,7 @@ enum iwl_sta_flags {
STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3),
STA_FLG_REDUCED_TX_PWR_DATA = BIT(6),
- STA_FLG_FLG_ANT_A = (1 << 4),
- STA_FLG_FLG_ANT_B = (2 << 4),
- STA_FLG_FLG_ANT_MSK = (STA_FLG_FLG_ANT_A |
- STA_FLG_FLG_ANT_B),
+ STA_FLG_DISABLE_TX = BIT(4),
STA_FLG_PS = BIT(8),
STA_FLG_DRAIN_FLOW = BIT(12),
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
index 6cc5f52b807f..d6073f67b212 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
@@ -69,10 +69,8 @@
* @TX_CMD_FLG_ACK: expect ACK from receiving station
* @TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.
* Otherwise, use rate_n_flags from the TX command
- * @TX_CMD_FLG_BA: this frame is a block ack
* @TX_CMD_FLG_BAR: this frame is a BA request, immediate BAR is expected
* Must set TX_CMD_FLG_ACK with this flag.
- * @TX_CMD_FLG_TXOP_PROT: protect frame with full TXOP protection
* @TX_CMD_FLG_VHT_NDPA: mark frame is NDPA for VHT beamformer sequence
* @TX_CMD_FLG_HT_NDPA: mark frame is NDPA for HT beamformer sequence
* @TX_CMD_FLG_CSI_FDBK2HOST: mark to send feedback to host (only if good CRC)
@@ -82,12 +80,10 @@
* @TX_CMD_FLG_SEQ_CTL: set if FW should override the sequence control.
* Should be set for mgmt, non-QOS data, mcast, bcast and in scan command
* @TX_CMD_FLG_MORE_FRAG: this frame is non-last MPDU
- * @TX_CMD_FLG_NEXT_FRAME: this frame includes information of the next frame
* @TX_CMD_FLG_TSF: FW should calculate and insert TSF in the frame
* Should be set for beacons and probe responses
* @TX_CMD_FLG_CALIB: activate PA TX power calibrations
* @TX_CMD_FLG_KEEP_SEQ_CTL: if seq_ctl is set, don't increase inner seq count
- * @TX_CMD_FLG_AGG_START: allow this frame to start aggregation
* @TX_CMD_FLG_MH_PAD: driver inserted 2 byte padding after MAC header.
* Should be set for 26/30 length MAC headers
* @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
@@ -103,7 +99,6 @@ enum iwl_tx_flags {
TX_CMD_FLG_PROT_REQUIRE = BIT(0),
TX_CMD_FLG_ACK = BIT(3),
TX_CMD_FLG_STA_RATE = BIT(4),
- TX_CMD_FLG_BA = BIT(5),
TX_CMD_FLG_BAR = BIT(6),
TX_CMD_FLG_TXOP_PROT = BIT(7),
TX_CMD_FLG_VHT_NDPA = BIT(8),
@@ -113,11 +108,9 @@ enum iwl_tx_flags {
TX_CMD_FLG_BT_DIS = BIT(12),
TX_CMD_FLG_SEQ_CTL = BIT(13),
TX_CMD_FLG_MORE_FRAG = BIT(14),
- TX_CMD_FLG_NEXT_FRAME = BIT(15),
TX_CMD_FLG_TSF = BIT(16),
TX_CMD_FLG_CALIB = BIT(17),
TX_CMD_FLG_KEEP_SEQ_CTL = BIT(18),
- TX_CMD_FLG_AGG_START = BIT(19),
TX_CMD_FLG_MH_PAD = BIT(20),
TX_CMD_FLG_RESP_TO_DRV = BIT(21),
TX_CMD_FLG_CCMP_AGG = BIT(22),
@@ -191,8 +184,6 @@ enum iwl_tx_flags {
* struct iwl_tx_cmd - TX command struct to FW
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
- * @next_frame_len: same as len, but for next frame (0 if not applicable)
- * Used for fragmentation and bursting, but not in 11n aggregation.
* @tx_flags: combination of TX_CMD_FLG_*
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
@@ -210,8 +201,6 @@ enum iwl_tx_flags {
* @data_retry_limit: max attempts to send the data packet
* @tid_spec: TID/tspec
* @pm_frame_timeout: PM TX frame timeout
- * @driver_txop: duration od EDCA TXOP, in 32-usec units. Set this if not
- * specified by HCCA protocol
*
* The byte count (both len and next_frame_len) includes MAC header
* (24/26/30/32 bytes)
@@ -241,8 +230,7 @@ struct iwl_tx_cmd {
u8 initial_rate_index;
u8 reserved2;
u8 key[16];
- __le16 next_frame_flags;
- __le16 reserved3;
+ __le32 reserved3;
__le32 life_time;
__le32 dram_lsb_ptr;
u8 dram_msb_ptr;
@@ -250,7 +238,7 @@ struct iwl_tx_cmd {
u8 data_retry_limit;
u8 tid_tspec;
__le16 pm_frame_timeout;
- __le16 driver_txop;
+ __le16 reserved4;
u8 payload[0];
struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_3 */
@@ -549,6 +537,20 @@ struct iwl_beacon_notif {
} __packed;
/**
+ * struct iwl_extended_beacon_notif - notifies about beacon transmission
+ * @beacon_notify_hdr: tx response command associated with the beacon
+ * @tsf: last beacon tsf
+ * @ibss_mgr_status: whether IBSS is manager
+ * @gp2: last beacon time in gp2
+ */
+struct iwl_extended_beacon_notif {
+ struct iwl_mvm_tx_resp beacon_notify_hdr;
+ __le64 tsf;
+ __le32 ibss_mgr_status;
+ __le32 gp2;
+} __packed; /* BEACON_NTFY_API_S_VER_5 */
+
+/**
* enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
* and the TFD queues are empty.
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 309a9b9a94fe..95f5b3274efb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -86,6 +86,8 @@ enum {
#define IWL_MVM_STATION_COUNT 16
+#define IWL_MVM_TDLS_STA_COUNT 4
+
/* commands */
enum {
MVM_ALIVE = 0x1,
@@ -131,10 +133,12 @@ enum {
/* Scan offload */
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
SCAN_OFFLOAD_ABORT_CMD = 0x52,
+ HOT_SPOT_CMD = 0x53,
SCAN_OFFLOAD_COMPLETE = 0x6D,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
MATCH_FOUND_NOTIFICATION = 0xd9,
+ SCAN_ITERATION_COMPLETE = 0xe7,
/* Phy */
PHY_CONFIGURATION_CMD = 0x6a,
@@ -163,7 +167,6 @@ enum {
BEACON_NOTIFICATION = 0x90,
BEACON_TEMPLATE_CMD = 0x91,
TX_ANT_CONFIGURATION_CMD = 0x98,
- BT_CONFIG = 0x9b,
STATISTICS_NOTIFICATION = 0x9d,
EOSP_NOTIFICATION = 0x9e,
REDUCE_TX_POWER_CMD = 0x9f,
@@ -185,6 +188,10 @@ enum {
BT_COEX_PRIO_TABLE = 0xcc,
BT_COEX_PROT_ENV = 0xcd,
BT_PROFILE_NOTIFICATION = 0xce,
+ BT_CONFIG = 0x9b,
+ BT_COEX_UPDATE_SW_BOOST = 0x5a,
+ BT_COEX_UPDATE_CORUN_LUT = 0x5b,
+ BT_COEX_UPDATE_REDUCED_TXP = 0x5c,
BT_COEX_CI = 0x5d,
REPLY_SF_CFG_CMD = 0xd1,
@@ -534,6 +541,9 @@ enum iwl_time_event_type {
/* WiDi Sync Events */
TE_WIDI_TX_SYNC,
+ /* Channel Switch NoA */
+ TE_P2P_GO_CSA_NOA,
+
TE_MAX
}; /* MAC_EVENT_TYPE_API_E_VER_1 */
@@ -901,6 +911,72 @@ struct iwl_phy_context_cmd {
__le32 dsp_cfg_flags;
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
+/*
+ * Aux ROC command
+ *
+ * Command requests the firmware to create a time event for a certain duration
+ * and remain on the given channel. This is done by using the Aux framework in
+ * the FW.
+ * The command was first used for Hot Spot issues - but can be used regardless
+ * to Hot Spot.
+ *
+ * ( HOT_SPOT_CMD 0x53 )
+ *
+ * @id_and_color: ID and color of the MAC
+ * @action: action to perform, one of FW_CTXT_ACTION_*
+ * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
+ * event_unique_id should be the id of the time event assigned by ucode.
+ * Otherwise ignore the event_unique_id.
+ * @sta_id_and_color: station id and color, resumed during "Remain On Channel"
+ * activity.
+ * @channel_info: channel info
+ * @node_addr: Our MAC Address
+ * @reserved: reserved for alignment
+ * @apply_time: GP2 value to start (should always be the current GP2 value)
+ * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
+ * time by which start of the event is allowed to be postponed.
+ * @duration: event duration in TU To calculate event duration:
+ * timeEventDuration = min(duration, remainingQuota)
+ */
+struct iwl_hs20_roc_req {
+ /* COMMON_INDEX_HDR_API_S_VER_1 hdr */
+ __le32 id_and_color;
+ __le32 action;
+ __le32 event_unique_id;
+ __le32 sta_id_and_color;
+ struct iwl_fw_channel_info channel_info;
+ u8 node_addr[ETH_ALEN];
+ __le16 reserved;
+ __le32 apply_time;
+ __le32 apply_time_max_delay;
+ __le32 duration;
+} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
+
+/*
+ * values for AUX ROC result values
+ */
+enum iwl_mvm_hot_spot {
+ HOT_SPOT_RSP_STATUS_OK,
+ HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
+ HOT_SPOT_MAX_NUM_OF_SESSIONS,
+};
+
+/*
+ * Aux ROC command response
+ *
+ * In response to iwl_hs20_roc_req the FW sends this command to notify the
+ * driver the uid of the timevent.
+ *
+ * ( HOT_SPOT_CMD 0x53 )
+ *
+ * @event_unique_id: Unique ID of time event assigned by ucode
+ * @status: Return status 0 is success, all the rest used for specific errors
+ */
+struct iwl_hs20_roc_res {
+ __le32 event_unique_id;
+ __le32 status;
+} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
+
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 8b79081d4885..0e523e28cabf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -67,6 +67,7 @@
#include "iwl-prph.h"
#include "fw-api.h"
#include "mvm.h"
+#include "time-event.h"
const u8 iwl_mvm_ac_to_tx_fifo[] = {
IWL_MVM_TX_FIFO_VO,
@@ -903,7 +904,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct iwl_mac_beacon_cmd beacon_cmd = {};
struct ieee80211_tx_info *info;
u32 beacon_skb_len;
- u32 rate;
+ u32 rate, tx_flags;
if (WARN_ON(!beacon))
return -EINVAL;
@@ -913,14 +914,17 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
/* TODO: for now the beacon template id is set to be the mac context id.
* Might be better to handle it as another resource ... */
beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
+ info = IEEE80211_SKB_CB(beacon);
/* Set up TX command fields */
beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len);
beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id;
beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
- beacon_cmd.tx.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
- TX_CMD_FLG_BT_DIS |
- TX_CMD_FLG_TSF);
+ tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
+ tx_flags |=
+ iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
+ TX_CMD_FLG_BT_PRIO_POS;
+ beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags);
mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
@@ -930,8 +934,6 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
RATE_MCS_ANT_POS);
- info = IEEE80211_SKB_CB(beacon);
-
if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) {
rate = IWL_FIRST_OFDM_RATE;
} else {
@@ -968,7 +970,7 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC);
- beacon = ieee80211_beacon_get(mvm->hw, vif);
+ beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
if (!beacon)
return -ENOMEM;
@@ -1210,31 +1212,94 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return 0;
}
+static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
+ struct ieee80211_vif *csa_vif, u32 gp2)
+{
+ struct iwl_mvm_vif *mvmvif =
+ iwl_mvm_vif_from_mac80211(csa_vif);
+
+ if (!ieee80211_csa_is_complete(csa_vif)) {
+ int c = ieee80211_csa_update_counter(csa_vif);
+
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
+ if (csa_vif->p2p &&
+ !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
+ u32 rel_time = (c + 1) *
+ csa_vif->bss_conf.beacon_int -
+ IWL_MVM_CHANNEL_SWITCH_TIME;
+ u32 apply_time = gp2 + rel_time * 1024;
+
+ iwl_mvm_schedule_csa_noa(mvm, csa_vif,
+ IWL_MVM_CHANNEL_SWITCH_TIME -
+ IWL_MVM_CHANNEL_SWITCH_MARGIN,
+ apply_time);
+ }
+ } else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
+ /* we don't have CSA NoA scheduled yet, switch now */
+ ieee80211_csa_finish(csa_vif);
+ RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ }
+}
+
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_beacon_notif *beacon = (void *)pkt->data;
- u16 status __maybe_unused =
- le16_to_cpu(beacon->beacon_notify_hdr.status.status);
- u32 rate __maybe_unused =
- le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
+ struct iwl_mvm_tx_resp *beacon_notify_hdr;
+ struct ieee80211_vif *csa_vif;
+ struct ieee80211_vif *tx_blocked_vif;
+ u64 tsf;
lockdep_assert_held(&mvm->mutex);
- IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
- status & TX_STATUS_MSK,
- beacon->beacon_notify_hdr.failure_frame,
- le64_to_cpu(beacon->tsf),
- rate);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) {
+ struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
- if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {
- if (!ieee80211_csa_is_complete(mvm->csa_vif)) {
- iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);
- } else {
- ieee80211_csa_finish(mvm->csa_vif);
- mvm->csa_vif = NULL;
+ beacon_notify_hdr = &beacon->beacon_notify_hdr;
+ tsf = le64_to_cpu(beacon->tsf);
+ mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+ } else {
+ struct iwl_beacon_notif *beacon = (void *)pkt->data;
+
+ beacon_notify_hdr = &beacon->beacon_notify_hdr;
+ tsf = le64_to_cpu(beacon->tsf);
+ }
+
+ IWL_DEBUG_RX(mvm,
+ "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
+ le16_to_cpu(beacon_notify_hdr->status.status) &
+ TX_STATUS_MSK,
+ beacon_notify_hdr->failure_frame, tsf,
+ mvm->ap_last_beacon_gp2,
+ le32_to_cpu(beacon_notify_hdr->initial_rate));
+
+ csa_vif = rcu_dereference_protected(mvm->csa_vif,
+ lockdep_is_held(&mvm->mutex));
+ if (unlikely(csa_vif && csa_vif->csa_active))
+ iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2);
+
+ tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
+ lockdep_is_held(&mvm->mutex));
+ if (unlikely(tx_blocked_vif)) {
+ struct iwl_mvm_vif *mvmvif =
+ iwl_mvm_vif_from_mac80211(tx_blocked_vif);
+
+ /*
+ * The channel switch is started and we have blocked the
+ * stations. If this is the first beacon (the timeout wasn't
+ * set), set the unblock timeout, otherwise countdown
+ */
+ if (!mvm->csa_tx_block_bcn_timeout)
+ mvm->csa_tx_block_bcn_timeout =
+ IWL_MVM_CS_UNBLOCK_TX_TIMEOUT;
+ else
+ mvm->csa_tx_block_bcn_timeout--;
+
+ /* Check if the timeout is expired, and unblock tx */
+ if (mvm->csa_tx_block_bcn_timeout == 0) {
+ iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, false);
+ RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
}
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 98556d03c1ed..7c8796584c25 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -80,6 +80,8 @@
#include "fw-api-scan.h"
#include "iwl-phy-db.h"
#include "testmode.h"
+#include "iwl-fw-error-dump.h"
+#include "iwl-prph.h"
static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
{
@@ -209,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return;
IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
- WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap));
+ spin_lock_bh(&mvm->refs_lock);
+ mvm->refs[ref_type]++;
+ spin_unlock_bh(&mvm->refs_lock);
iwl_trans_ref(mvm->trans);
}
@@ -219,26 +223,47 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return;
IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
- WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap));
+ spin_lock_bh(&mvm->refs_lock);
+ WARN_ON(!mvm->refs[ref_type]--);
+ spin_unlock_bh(&mvm->refs_lock);
iwl_trans_unref(mvm->trans);
}
-static void
-iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref)
+static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
+ enum iwl_mvm_ref_type except_ref)
{
- int i;
+ int i, j;
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
- for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) {
- if (ref == i)
+ spin_lock_bh(&mvm->refs_lock);
+ for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
+ if (except_ref == i || !mvm->refs[i])
continue;
- IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i);
- clear_bit(i, mvm->ref_bitmap);
- iwl_trans_unref(mvm->trans);
+ IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
+ i, mvm->refs[i]);
+ for (j = 0; j < mvm->refs[i]; j++)
+ iwl_trans_unref(mvm->trans);
+ mvm->refs[i] = 0;
+ }
+ spin_unlock_bh(&mvm->refs_lock);
+}
+
+int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
+{
+ iwl_mvm_ref(mvm, ref_type);
+
+ if (!wait_event_timeout(mvm->d0i3_exit_waitq,
+ !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status),
+ HZ)) {
+ WARN_ON_ONCE(1);
+ iwl_mvm_unref(mvm, ref_type);
+ return -EIO;
}
+
+ return 0;
}
static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
@@ -276,6 +301,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_TIMING_BEACON_ONLY |
IEEE80211_HW_CONNECTION_MONITOR |
+ IEEE80211_HW_CHANCTX_STA_CSA |
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -303,6 +329,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
}
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
+
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
hw->chanctx_data_size = sizeof(u16);
@@ -367,13 +396,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
else
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+ /* TODO: enable that only for firmwares that don't crash */
+ /* hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; */
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
+ NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_P2P_GO_OPPPS;
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
@@ -549,9 +580,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
case IEEE80211_AMPDU_TX_OPERATIONAL:
- iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);
- tx_agg_ref = true;
-
/*
* for tx start, wait synchronously until D0i3 exit to
* get the correct sequence number for the tid.
@@ -560,12 +588,11 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
* by the trans layer (unlike commands), so wait for
* d0i3 exit in these cases as well.
*/
- if (!wait_event_timeout(mvm->d0i3_exit_waitq,
- !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {
- WARN_ON_ONCE(1);
- iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
- return -EIO;
- }
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG);
+ if (ret)
+ return ret;
+
+ tx_agg_ref = true;
break;
default:
break;
@@ -635,8 +662,106 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
spin_unlock_bh(&mvm->time_event_lock);
mvmvif->phy_ctxt = NULL;
+ memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
}
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
+{
+ struct iwl_fw_error_dump_file *dump_file;
+ struct iwl_fw_error_dump_data *dump_data;
+ struct iwl_fw_error_dump_info *dump_info;
+ struct iwl_mvm_dump_ptrs *fw_error_dump;
+ const struct fw_img *img;
+ u32 sram_len, sram_ofs;
+ u32 file_len, rxf_len;
+ unsigned long flags;
+ int reg_val;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (mvm->fw_error_dump)
+ return;
+
+ fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
+ if (!fw_error_dump)
+ return;
+
+ img = &mvm->fw->img[mvm->cur_ucode];
+ sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
+ sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
+
+ /* reading buffer size */
+ reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR);
+ rxf_len = (reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS;
+
+ /* the register holds the value divided by 128 */
+ rxf_len = rxf_len << 7;
+
+ file_len = sizeof(*dump_file) +
+ sizeof(*dump_data) * 3 +
+ sram_len +
+ rxf_len +
+ sizeof(*dump_info);
+
+ dump_file = vzalloc(file_len);
+ if (!dump_file) {
+ kfree(fw_error_dump);
+ return;
+ }
+
+ fw_error_dump->op_mode_ptr = dump_file;
+
+ dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
+ dump_data = (void *)dump_file->data;
+
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
+ dump_data->len = cpu_to_le32(sizeof(*dump_info));
+ dump_info = (void *) dump_data->data;
+ dump_info->device_family =
+ mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
+ cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
+ cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
+ memcpy(dump_info->fw_human_readable, mvm->fw->human_readable,
+ sizeof(dump_info->fw_human_readable));
+ strncpy(dump_info->dev_human_readable, mvm->cfg->name,
+ sizeof(dump_info->dev_human_readable));
+ strncpy(dump_info->bus_human_readable, mvm->dev->bus->name,
+ sizeof(dump_info->bus_human_readable));
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
+ dump_data->len = cpu_to_le32(rxf_len);
+
+ if (iwl_trans_grab_nic_access(mvm->trans, false, &flags)) {
+ u32 *rxf = (void *)dump_data->data;
+ int i;
+
+ for (i = 0; i < (rxf_len / sizeof(u32)); i++) {
+ iwl_trans_write_prph(mvm->trans,
+ RXF_LD_FENCE_OFFSET_ADDR,
+ i * sizeof(u32));
+ rxf[i] = iwl_trans_read_prph(mvm->trans,
+ RXF_FIFO_RD_FENCE_ADDR);
+ }
+ iwl_trans_release_nic_access(mvm->trans, &flags);
+ }
+
+ dump_data = iwl_fw_error_next_data(dump_data);
+ dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
+ dump_data->len = cpu_to_le32(sram_len);
+ iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
+ sram_len);
+
+ fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
+ fw_error_dump->op_mode_len = file_len;
+ if (fw_error_dump->trans_ptr)
+ file_len += fw_error_dump->trans_ptr->len;
+ dump_file->file_len = cpu_to_le32(file_len);
+ mvm->fw_error_dump = fw_error_dump;
+}
+#endif
+
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -665,6 +790,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
+ memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+ memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
+ memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
+ memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
+ memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk));
+ memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk));
ieee80211_wake_queues(mvm->hw);
@@ -688,6 +819,16 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
iwl_mvm_restart_cleanup(mvm);
ret = iwl_mvm_up(mvm);
+
+ if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+ /* Something went wrong - we need to finish some cleanup
+ * that normally iwl_mvm_mac_restart_complete() below
+ * would do.
+ */
+ clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+ iwl_mvm_d0i3_enable_tx(mvm, NULL);
+ }
+
mutex_unlock(&mvm->mutex);
return ret;
@@ -786,6 +927,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
int ret;
/*
+ * make sure D0i3 exit is completed, otherwise a target access
+ * during tx queue configuration could be done when still in
+ * D0i3 state.
+ */
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF);
+ if (ret)
+ return ret;
+
+ /*
* Not much to do here. The stack will not allow interface
* types or combinations that we didn't advertise, so we
* don't really have to check the types.
@@ -899,6 +1049,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unlock:
mutex_unlock(&mvm->mutex);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF);
+
return ret;
}
@@ -1255,6 +1407,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
}
#endif
+static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
+{
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+ int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+ lockdep_is_held(&mvm->mutex));
+ if (!sta || IS_ERR(sta) || !sta->tdls)
+ continue;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
+ NL80211_TDLS_TEARDOWN,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
+ GFP_KERNEL);
+ }
+}
+
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@@ -1278,7 +1452,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
/* add quota for this interface */
- ret = iwl_mvm_update_quotas(mvm, vif);
+ ret = iwl_mvm_update_quotas(mvm, NULL);
if (ret) {
IWL_ERR(mvm, "failed to update quotas\n");
return;
@@ -1350,14 +1524,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
- iwl_mvm_sf_update(mvm, vif, false);
- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_QOS)) {
ret = iwl_mvm_power_update_mac(mvm);
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
+
+ if (changes & BSS_CHANGED_BEACON_INFO) {
+ iwl_mvm_sf_update(mvm, vif, false);
+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+ }
+
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
bss_conf->txpower);
@@ -1389,6 +1567,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
+ /*
+ * iwl_mvm_mac_ctxt_add() might read directly from the device
+ * (the system time), so make sure it is available.
+ */
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
+ if (ret)
+ return ret;
+
mutex_lock(&mvm->mutex);
/* Send the beacon template */
@@ -1425,7 +1611,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
/* power updated needs to be done before quotas */
iwl_mvm_power_update_mac(mvm);
- ret = iwl_mvm_update_quotas(mvm, vif);
+ ret = iwl_mvm_update_quotas(mvm, NULL);
if (ret)
goto out_quota_failed;
@@ -1437,6 +1623,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_bt_coex_vif_change(mvm);
+ /* we don't support TDLS during DCM */
+ if (iwl_mvm_phy_ctx_count(mvm) > 1)
+ iwl_mvm_teardown_tdls_peers(mvm);
+
mutex_unlock(&mvm->mutex);
return 0;
@@ -1450,6 +1640,7 @@ out_remove:
iwl_mvm_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
return ret;
}
@@ -1463,7 +1654,20 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
+ /* Handle AP stop while in CSA */
+ if (rcu_access_pointer(mvm->csa_vif) == vif) {
+ iwl_mvm_remove_time_event(mvm, mvmvif,
+ &mvmvif->time_event_data);
+ RCU_INIT_POINTER(mvm->csa_vif, NULL);
+ }
+
+ if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
+ RCU_INIT_POINTER(mvm->csa_tx_blocked_vif, NULL);
+ mvm->csa_tx_block_bcn_timeout = 0;
+ }
+
mvmvif->ap_ibss_active = false;
+ mvm->ap_last_beacon_gp2 = 0;
iwl_mvm_bt_coex_vif_change(mvm);
@@ -1514,10 +1718,18 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ /*
+ * iwl_mvm_bss_info_changed_station() might call
+ * iwl_mvm_protect_session(), which reads directly from
+ * the device (the system time), so make sure it is available.
+ */
+ if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
+ return;
+
mutex_lock(&mvm->mutex);
if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
- iwl_mvm_sched_scan_stop(mvm, true);
+ iwl_mvm_scan_offload_stop(mvm, true);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
@@ -1533,44 +1745,84 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
}
mutex_unlock(&mvm->mutex);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
}
+static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
+ enum iwl_scan_status scan_type)
+{
+ int ret;
+ bool wait_for_handlers = false;
+
+ mutex_lock(&mvm->mutex);
+
+ if (mvm->scan_status != scan_type) {
+ ret = 0;
+ /* make sure there are no pending notifications */
+ wait_for_handlers = true;
+ goto out;
+ }
+
+ switch (scan_type) {
+ case IWL_MVM_SCAN_SCHED:
+ ret = iwl_mvm_scan_offload_stop(mvm, true);
+ break;
+ case IWL_MVM_SCAN_OS:
+ ret = iwl_mvm_cancel_scan(mvm);
+ break;
+ case IWL_MVM_SCAN_NONE:
+ default:
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ break;
+ }
+ if (ret)
+ goto out;
+
+ wait_for_handlers = true;
+out:
+ mutex_unlock(&mvm->mutex);
+
+ /* make sure we consume the completion notification */
+ if (wait_for_handlers)
+ iwl_mvm_wait_for_async_handlers(mvm);
+
+ return ret;
+}
static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct cfg80211_scan_request *req = &hw_req->req;
int ret;
- if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS)
+ if (req->n_channels == 0 ||
+ req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
return -EINVAL;
+ ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
+ if (ret)
+ return ret;
+
mutex_lock(&mvm->mutex);
- switch (mvm->scan_status) {
- case IWL_MVM_SCAN_SCHED:
- ret = iwl_mvm_sched_scan_stop(mvm, true);
- if (ret) {
- ret = -EBUSY;
- goto out;
- }
- break;
- case IWL_MVM_SCAN_NONE:
- break;
- default:
+ if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
- ret = iwl_mvm_scan_request(mvm, vif, req);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
+ else
+ ret = iwl_mvm_scan_request(mvm, vif, req);
+
if (ret)
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
out:
mutex_unlock(&mvm->mutex);
- /* make sure to flush the Rx handler before the next scan arrives */
- iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
@@ -1680,6 +1932,48 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}
+int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+ int count = 0;
+ int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+ lockdep_is_held(&mvm->mutex));
+ if (!sta || IS_ERR(sta) || !sta->tdls)
+ continue;
+
+ if (vif) {
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ if (mvmsta->vif != vif)
+ continue;
+ }
+
+ count++;
+ }
+
+ return count;
+}
+
+static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ bool sta_added)
+{
+ int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
+
+ /*
+ * Disable ps when the first TDLS sta is added and re-enable it
+ * when the last TDLS sta is removed
+ */
+ if ((tdls_sta_cnt == 1 && sta_added) ||
+ (tdls_sta_cnt == 0 && !sta_added))
+ iwl_mvm_power_update_mac(mvm);
+}
+
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1718,7 +2012,20 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
ret = -EINVAL;
goto out_unlock;
}
+
+ if (sta->tdls &&
+ (vif->p2p ||
+ iwl_mvm_tdls_sta_count(mvm, NULL) ==
+ IWL_MVM_TDLS_STA_COUNT ||
+ iwl_mvm_phy_ctx_count(mvm) > 1)) {
+ IWL_DEBUG_MAC80211(mvm, "refusing TDLS sta\n");
+ ret = -EBUSY;
+ goto out_unlock;
+ }
+
ret = iwl_mvm_add_sta(mvm, vif, sta);
+ if (sta->tdls && ret == 0)
+ iwl_mvm_recalc_tdls_state(mvm, vif, true);
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_AUTH) {
/*
@@ -1736,6 +2043,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
true);
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
+
+ /* we don't support TDLS during DCM */
+ if (iwl_mvm_phy_ctx_count(mvm) > 1)
+ iwl_mvm_teardown_tdls_peers(mvm);
+
/* enable beacon filtering */
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
ret = 0;
@@ -1753,6 +2065,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) {
ret = iwl_mvm_rm_sta(mvm, vif, sta);
+ if (sta->tdls)
+ iwl_mvm_recalc_tdls_state(mvm, vif, false);
} else {
ret = -EIO;
}
@@ -1818,20 +2132,54 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
if (WARN_ON_ONCE(vif->bss_conf.assoc))
return;
+ /*
+ * iwl_mvm_protect_session() reads directly from the device
+ * (the system time), so make sure it is available.
+ */
+ if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
+ return;
+
mutex_lock(&mvm->mutex);
/* Try really hard to protect the session and hear a beacon */
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
mutex_unlock(&mvm->mutex);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
+}
+
+static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
+
+ /*
+ * iwl_mvm_protect_session() reads directly from the device
+ * (the system time), so make sure it is available.
+ */
+ if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
+ return;
+
+ mutex_lock(&mvm->mutex);
+ /* Protect the session to hear the TDLS setup response on the channel */
+ iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
+ mutex_unlock(&mvm->mutex);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
}
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
+ ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
+ if (ret)
+ return ret;
+
mutex_lock(&mvm->mutex);
if (!iwl_mvm_is_idle(mvm)) {
@@ -1839,49 +2187,34 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
goto out;
}
- switch (mvm->scan_status) {
- case IWL_MVM_SCAN_OS:
- IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
- ret = iwl_mvm_cancel_scan(mvm);
- if (ret) {
- ret = -EBUSY;
- goto out;
- }
-
- /*
- * iwl_mvm_rx_scan_complete() will be called soon but will
- * not reset the scan status as it won't be IWL_MVM_SCAN_OS
- * any more since we queue the next scan immediately (below).
- * We make sure it is called before the next scan starts by
- * flushing the async-handlers work.
- */
- break;
- case IWL_MVM_SCAN_NONE:
- break;
- default:
+ if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
mvm->scan_status = IWL_MVM_SCAN_SCHED;
- ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
- if (ret)
- goto err;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+ ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
+ if (ret)
+ goto err;
+ }
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
goto err;
- ret = iwl_mvm_sched_scan_start(mvm, req);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
+ else
+ ret = iwl_mvm_sched_scan_start(mvm, req);
+
if (!ret)
goto out;
err:
mvm->scan_status = IWL_MVM_SCAN_NONE;
out:
mutex_unlock(&mvm->mutex);
- /* make sure to flush the Rx handler before the next scan arrives */
- iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
@@ -1892,7 +2225,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
int ret;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_sched_scan_stop(mvm, false);
+ ret = iwl_mvm_scan_offload_stop(mvm, false);
mutex_unlock(&mvm->mutex);
iwl_mvm_wait_for_async_handlers(mvm);
@@ -2001,6 +2334,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
}
+static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt, void *data)
+{
+ struct iwl_mvm *mvm =
+ container_of(notif_wait, struct iwl_mvm, notif_wait);
+ struct iwl_hs20_roc_res *resp;
+ int resp_len = iwl_rx_packet_payload_len(pkt);
+ struct iwl_mvm_time_event_data *te_data = data;
+
+ if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD))
+ return true;
+
+ if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
+ IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n");
+ return true;
+ }
+
+ resp = (void *)pkt->data;
+
+ IWL_DEBUG_TE(mvm,
+ "Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
+ resp->status, resp->event_unique_id);
+
+ te_data->uid = le32_to_cpu(resp->event_unique_id);
+ IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
+ te_data->uid);
+
+ spin_lock_bh(&mvm->time_event_lock);
+ list_add_tail(&te_data->list, &mvm->aux_roc_te_list);
+ spin_unlock_bh(&mvm->time_event_lock);
+
+ return true;
+}
+
+#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
+static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
+ struct ieee80211_channel *channel,
+ struct ieee80211_vif *vif,
+ int duration)
+{
+ int res, time_reg = DEVICE_SYSTEM_TIME_REG;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
+ static const u8 time_event_response[] = { HOT_SPOT_CMD };
+ struct iwl_notification_wait wait_time_event;
+ struct iwl_hs20_roc_req aux_roc_req = {
+ .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
+ .id_and_color =
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
+ .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
+ /* Set the channel info data */
+ .channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ?
+ PHY_BAND_24 : PHY_BAND_5,
+ .channel_info.channel = channel->hw_value,
+ .channel_info.width = PHY_VHT_CHANNEL_MODE20,
+ /* Set the time and duration */
+ .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
+ .apply_time_max_delay =
+ cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
+ .duration = cpu_to_le32(MSEC_TO_TU(duration)),
+ };
+
+ /* Set the node address */
+ memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
+
+ te_data->vif = vif;
+ te_data->duration = duration;
+ te_data->id = HOT_SPOT_CMD;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ spin_lock_bh(&mvm->time_event_lock);
+ list_add_tail(&te_data->list, &mvm->time_event_list);
+ spin_unlock_bh(&mvm->time_event_lock);
+
+ /*
+ * Use a notification wait, which really just processes the
+ * command response and doesn't wait for anything, in order
+ * to be able to process the response and get the UID inside
+ * the RX path. Using CMD_WANT_SKB doesn't work because it
+ * stores the buffer and then wakes up this thread, by which
+ * time another notification (that the time event started)
+ * might already be processed unsuccessfully.
+ */
+ iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
+ time_event_response,
+ ARRAY_SIZE(time_event_response),
+ iwl_mvm_rx_aux_roc, te_data);
+
+ res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
+ &aux_roc_req);
+
+ if (res) {
+ IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res);
+ iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
+ goto out_clear_te;
+ }
+
+ /* No need to wait for anything, so just pass 1 (0 isn't valid) */
+ res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
+ /* should never fail */
+ WARN_ON_ONCE(res);
+
+ if (res) {
+ out_clear_te:
+ spin_lock_bh(&mvm->time_event_lock);
+ iwl_mvm_te_clear_data(mvm, te_data);
+ spin_unlock_bh(&mvm->time_event_lock);
+ }
+
+ return res;
+}
+
static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
@@ -2016,8 +2462,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type);
- if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
- IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ /* Use aux roc framework (HS20) */
+ ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+ vif, duration);
+ return ret;
+ case NL80211_IFTYPE_P2P_DEVICE:
+ /* handle below */
+ break;
+ default:
+ IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
return -EINVAL;
}
@@ -2126,17 +2581,17 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
return 0;
}
-static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_chanctx_conf *ctx)
+static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_chanctx_conf *ctx)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret;
+ lockdep_assert_held(&mvm->mutex);
+
IWL_DEBUG_MAC80211(mvm, "Add channel context\n");
- mutex_lock(&mvm->mutex);
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!phy_ctxt) {
ret = -ENOSPC;
@@ -2154,19 +2609,40 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
*phy_ctxt_id = phy_ctxt->id;
out:
+ return ret;
+}
+
+static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+ ret = __iwl_mvm_add_chanctx(mvm, ctx);
mutex_unlock(&mvm->mutex);
+
return ret;
}
+static void __iwl_mvm_remove_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+
+ lockdep_assert_held(&mvm->mutex);
+
+ iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
+}
+
static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
- struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
mutex_lock(&mvm->mutex);
- iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt);
+ __iwl_mvm_remove_chanctx(mvm, ctx);
mutex_unlock(&mvm->mutex);
}
@@ -2195,17 +2671,17 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex);
}
-static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx)
+static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx,
+ bool switching_chanctx)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
- mutex_lock(&mvm->mutex);
+ lockdep_assert_held(&mvm->mutex);
mvmvif->phy_ctxt = phy_ctxt;
@@ -2222,18 +2698,18 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* (in bss_info_changed), similarly for IBSS.
*/
ret = 0;
- goto out_unlock;
+ goto out;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_MONITOR:
break;
default:
ret = -EINVAL;
- goto out_unlock;
+ goto out;
}
ret = iwl_mvm_binding_add_vif(mvm, vif);
if (ret)
- goto out_unlock;
+ goto out;
/*
* Power state must be updated before quotas,
@@ -2247,67 +2723,168 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_MONITOR) {
mvmvif->monitor_active = true;
- ret = iwl_mvm_update_quotas(mvm, vif);
+ ret = iwl_mvm_update_quotas(mvm, NULL);
if (ret)
goto out_remove_binding;
}
/* Handle binding during CSA */
- if (vif->type == NL80211_IFTYPE_AP) {
- iwl_mvm_update_quotas(mvm, vif);
+ if ((vif->type == NL80211_IFTYPE_AP) ||
+ (switching_chanctx && (vif->type == NL80211_IFTYPE_STATION))) {
+ iwl_mvm_update_quotas(mvm, NULL);
iwl_mvm_mac_ctxt_changed(mvm, vif, false);
}
- goto out_unlock;
+ goto out;
- out_remove_binding:
+out_remove_binding:
iwl_mvm_binding_remove_vif(mvm, vif);
iwl_mvm_power_update_mac(mvm);
- out_unlock:
- mutex_unlock(&mvm->mutex);
+out:
if (ret)
mvmvif->phy_ctxt = NULL;
return ret;
}
-
-static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_chanctx_conf *ctx)
+static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ret;
mutex_lock(&mvm->mutex);
+ ret = __iwl_mvm_assign_vif_chanctx(mvm, vif, ctx, false);
+ mutex_unlock(&mvm->mutex);
+
+ return ret;
+}
+
+static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx,
+ bool switching_chanctx)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct ieee80211_vif *disabled_vif = NULL;
+
+ lockdep_assert_held(&mvm->mutex);
iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
switch (vif->type) {
case NL80211_IFTYPE_ADHOC:
- goto out_unlock;
+ goto out;
case NL80211_IFTYPE_MONITOR:
mvmvif->monitor_active = false;
- iwl_mvm_update_quotas(mvm, NULL);
break;
case NL80211_IFTYPE_AP:
/* This part is triggered only during CSA */
if (!vif->csa_active || !mvmvif->ap_ibss_active)
- goto out_unlock;
+ goto out;
+
+ /* Set CS bit on all the stations */
+ iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
+
+ /* Save blocked iface, the timeout is set on the next beacon */
+ rcu_assign_pointer(mvm->csa_tx_blocked_vif, vif);
mvmvif->ap_ibss_active = false;
- iwl_mvm_update_quotas(mvm, NULL);
- /*TODO: bt_coex notification here? */
+ break;
+ case NL80211_IFTYPE_STATION:
+ if (!switching_chanctx)
+ break;
+
+ disabled_vif = vif;
+
+ iwl_mvm_mac_ctxt_changed(mvm, vif, true);
+ break;
default:
break;
}
+ iwl_mvm_update_quotas(mvm, disabled_vif);
iwl_mvm_binding_remove_vif(mvm, vif);
-out_unlock:
+out:
mvmvif->phy_ctxt = NULL;
iwl_mvm_power_update_mac(mvm);
+}
+
+static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ mutex_lock(&mvm->mutex);
+ __iwl_mvm_unassign_vif_chanctx(mvm, vif, ctx, false);
mutex_unlock(&mvm->mutex);
}
+static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif_chanctx_switch *vifs,
+ int n_vifs,
+ enum ieee80211_chanctx_switch_mode mode)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ int ret;
+
+ /* we only support SWAP_CONTEXTS and with a single-vif right now */
+ if (mode != CHANCTX_SWMODE_SWAP_CONTEXTS || n_vifs > 1)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&mvm->mutex);
+ __iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
+ __iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
+
+ ret = __iwl_mvm_add_chanctx(mvm, vifs[0].new_ctx);
+ if (ret) {
+ IWL_ERR(mvm, "failed to add new_ctx during channel switch\n");
+ goto out_reassign;
+ }
+
+ ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+ true);
+ if (ret) {
+ IWL_ERR(mvm,
+ "failed to assign new_ctx during channel switch\n");
+ goto out_remove;
+ }
+
+ /* we don't support TDLS during DCM - can be caused by channel switch */
+ if (iwl_mvm_phy_ctx_count(mvm) > 1)
+ iwl_mvm_teardown_tdls_peers(mvm);
+
+ goto out;
+
+out_remove:
+ __iwl_mvm_remove_chanctx(mvm, vifs[0].new_ctx);
+
+out_reassign:
+ ret = __iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx);
+ if (ret) {
+ IWL_ERR(mvm, "failed to add old_ctx back after failure.\n");
+ goto out_restart;
+ }
+
+ ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
+ true);
+ if (ret) {
+ IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
+ goto out_restart;
+ }
+
+ goto out;
+
+out_restart:
+ /* things keep failing, better restart the hw */
+ iwl_mvm_nic_restart(mvm, false);
+
+out:
+ mutex_unlock(&mvm->mutex);
+ return ret;
+}
+
static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
bool set)
@@ -2395,15 +2972,19 @@ static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,
struct cfg80211_chan_def *chandef)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *csa_vif;
mutex_lock(&mvm->mutex);
- if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active,
+
+ csa_vif = rcu_dereference_protected(mvm->csa_vif,
+ lockdep_is_held(&mvm->mutex));
+ if (WARN(csa_vif && csa_vif->csa_active,
"Another CSA is already in progress"))
goto out_unlock;
IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
chandef->center_freq1);
- mvm->csa_vif = vif;
+ rcu_assign_pointer(mvm->csa_vif, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
@@ -2460,6 +3041,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+ .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
.flush = iwl_mvm_mac_flush,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
@@ -2472,6 +3054,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.change_chanctx = iwl_mvm_change_chanctx,
.assign_vif_chanctx = iwl_mvm_assign_vif_chanctx,
.unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx,
+ .switch_vif_chanctx = iwl_mvm_switch_vif_chanctx,
.start_ap = iwl_mvm_start_ap_ibss,
.stop_ap = iwl_mvm_stop_ap_ibss,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index fcc6c29482d0..2e73d3bd7757 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -82,6 +82,26 @@
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
+/* A TimeUnit is 1024 microsecond */
+#define MSEC_TO_TU(_msec) (_msec*1000/1024)
+
+/*
+ * The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
+ * TBTT. This value should be big enough to ensure that we switch in time.
+ */
+#define IWL_MVM_CHANNEL_SWITCH_TIME 40
+
+/*
+ * This value (in TUs) is used to fine tune the CSA NoA end time which should
+ * be just before "beacon 0" TBTT.
+ */
+#define IWL_MVM_CHANNEL_SWITCH_MARGIN 4
+
+/*
+ * Number of beacons to transmit on a new channel until we unblock tx to
+ * the stations, even if we didn't identify them on a new channel
+ */
+#define IWL_MVM_CS_UNBLOCK_TX_TIMEOUT 3
enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_BK = 0,
@@ -108,6 +128,21 @@ struct iwl_mvm_mod_params {
};
extern struct iwl_mvm_mod_params iwlmvm_mod_params;
+/**
+ * struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
+ *
+ * @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
+ * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
+ * transport's data.
+ * @trans_len: length of the valid data in trans_ptr
+ * @op_mode_len: length of the valid data in op_mode_ptr
+ */
+struct iwl_mvm_dump_ptrs {
+ struct iwl_trans_dump_data *trans_ptr;
+ void *op_mode_ptr;
+ u32 op_mode_len;
+};
+
struct iwl_mvm_phy_ctxt {
u16 id;
u16 color;
@@ -230,11 +265,30 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_USER,
IWL_MVM_REF_TX,
IWL_MVM_REF_TX_AGG,
+ IWL_MVM_REF_ADD_IF,
+ IWL_MVM_REF_START_AP,
+ IWL_MVM_REF_BSS_CHANGED,
+ IWL_MVM_REF_PREPARE_TX,
+ IWL_MVM_REF_PROTECT_TDLS,
+ IWL_MVM_REF_CHECK_CTKILL,
+ IWL_MVM_REF_PRPH_READ,
+ IWL_MVM_REF_PRPH_WRITE,
+ IWL_MVM_REF_NMI,
+ IWL_MVM_REF_TM_CMD,
IWL_MVM_REF_EXIT_WORK,
IWL_MVM_REF_COUNT,
};
+enum iwl_bt_force_ant_mode {
+ BT_FORCE_ANT_DIS = 0,
+ BT_FORCE_ANT_AUTO,
+ BT_FORCE_ANT_BT,
+ BT_FORCE_ANT_WIFI,
+
+ BT_FORCE_ANT_MAX,
+};
+
/**
* struct iwl_mvm_vif_bf_data - beacon filtering related data
* @bf_enabled: indicates if beacon filtering is enabled
@@ -299,6 +353,7 @@ struct iwl_mvm_vif {
*/
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct iwl_mvm_time_event_data time_event_data;
+ struct iwl_mvm_time_event_data hs_time_event_data;
struct iwl_mvm_int_sta bcast_sta;
@@ -523,7 +578,7 @@ struct iwl_mvm {
/* Scan status, cmd (pre-allocated) and auxiliary station */
enum iwl_scan_status scan_status;
- struct iwl_scan_cmd *scan_cmd;
+ void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
/* rx chain antennas set through debugfs for the scan command */
@@ -578,18 +633,15 @@ struct iwl_mvm {
*/
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
- /* A bitmap of reference types taken by the driver. */
- unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)];
+ /* references taken by the driver and spinlock protecting them */
+ spinlock_t refs_lock;
+ u8 refs[IWL_MVM_REF_COUNT];
u8 vif_count;
/* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw;
- void *fw_error_dump;
- void *fw_error_sram;
- u32 fw_error_sram_len;
- u32 *fw_error_rxf;
- u32 fw_error_rxf_len;
+ struct iwl_mvm_dump_ptrs *fw_error_dump;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
@@ -623,12 +675,21 @@ struct iwl_mvm {
wait_queue_head_t d0i3_exit_waitq;
/* BT-Coex */
- u8 bt_kill_msk;
+ u8 bt_ack_kill_msk[NUM_PHY_CTX];
+ u8 bt_cts_kill_msk[NUM_PHY_CTX];
+
+ struct iwl_bt_coex_profile_notif_old last_bt_notif_old;
+ struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old;
struct iwl_bt_coex_profile_notif last_bt_notif;
struct iwl_bt_coex_ci_cmd last_bt_ci_cmd;
+
u32 last_ant_isol;
u8 last_corun_lut;
u8 bt_tx_prio;
+ enum iwl_bt_force_ant_mode bt_force_ant_mode;
+
+ /* Aux ROC */
+ struct list_head aux_roc_te_list;
/* Thermal Throttling and CTkill */
struct iwl_mvm_tt_mgmt thermal_throttle;
@@ -647,7 +708,12 @@ struct iwl_mvm {
/* Indicate if device power save is allowed */
bool ps_disabled;
- struct ieee80211_vif *csa_vif;
+ struct ieee80211_vif __rcu *csa_vif;
+ struct ieee80211_vif __rcu *csa_tx_blocked_vif;
+ u8 csa_tx_block_bcn_timeout;
+
+ /* system time of last beacon (for AP/GO interface) */
+ u32 ap_last_beacon_gp2;
};
/* Extract MVM priv from op_mode and _hw */
@@ -663,6 +729,7 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING,
IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3,
+ IWL_MVM_STATUS_ROC_AUX_RUNNING,
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -719,11 +786,6 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
struct ieee80211_tx_rate *r);
u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
-void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm);
-void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm);
-#endif
u8 first_antenna(u8 mask);
u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
@@ -809,6 +871,7 @@ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm,
struct iwl_mvm_phy_ctxt *ctxt);
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
struct iwl_mvm_phy_ctxt *ctxt);
+int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
/* MAC (virtual interface) programming */
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -835,7 +898,8 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
/* Quota management */
-int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif);
+int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
+ struct ieee80211_vif *disabled_vif);
/* Scanning */
int iwl_mvm_scan_request(struct iwl_mvm *mvm,
@@ -854,15 +918,24 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies);
+ struct ieee80211_scan_ies *ies);
int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify);
-int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd);
+int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
+int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+
+/* Unified scan */
+int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *req);
+int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies);
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -948,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
/* D0i3 */
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
+int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
@@ -963,19 +1037,40 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm);
bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
enum ieee80211_band band);
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac);
+bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm);
+void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm);
+int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm);
+int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event);
+u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm,
+ enum ieee80211_band band);
+int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+
enum iwl_bt_kill_msk {
BT_KILL_MSK_DEFAULT,
- BT_KILL_MSK_SCO_HID_A2DP,
- BT_KILL_MSK_REDUCED_TXPOW,
+ BT_KILL_MSK_NEVER,
+ BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_MAX,
};
-extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX];
-extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX];
+
+extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
+extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
+extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX];
/* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1039,4 +1134,9 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool added_vif);
+/* TDLS */
+int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+
+void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
+
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 808f78f6fbf9..cfdd314fdd5d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -69,7 +69,9 @@
/* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
-#define IWL_MAX_NVM_SECTION_SIZE 7000
+#define IWL_MAX_NVM_SECTION_SIZE 0x1b58
+#define IWL_MAX_NVM_8000A_SECTION_SIZE 0xffc
+#define IWL_MAX_NVM_8000B_SECTION_SIZE 0x1ffc
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
@@ -219,7 +221,7 @@ static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section,
* without overflowing, so no check is needed.
*/
static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
- u8 *data)
+ u8 *data, u32 size_read)
{
u16 length, offset = 0;
int ret;
@@ -231,6 +233,13 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
/* Read the NVM until exhausted (reading less than requested) */
while (ret == length) {
+ /* Check no memory assumptions fail and cause an overflow */
+ if ((size_read + offset + length) >
+ mvm->cfg->base_params->eeprom_size) {
+ IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
+ return -ENOBUFS;
+ }
+
ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);
if (ret < 0) {
IWL_DEBUG_EEPROM(mvm->trans->dev,
@@ -256,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
- IWL_ERR(mvm, "Can't parse empty NVM sections\n");
+ IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
} else {
@@ -264,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
IWL_ERR(mvm,
- "Can't parse empty family 8000 NVM sections\n");
+ "Can't parse empty family 8000 OTP/NVM sections\n");
return NULL;
}
/* MAC_OVERRIDE or at least HW section must exist */
@@ -326,6 +335,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
u8 data[];
} *file_sec;
const u8 *eof, *temp;
+ int max_section_size;
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
@@ -334,6 +344,14 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
+ /* Maximal size depends on HW family and step */
+ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ max_section_size = IWL_MAX_NVM_SECTION_SIZE;
+ else if ((mvm->trans->hw_rev & 0xc) == 0) /* Family 8000 A-step */
+ max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE;
+ else /* Family 8000 B-step */
+ max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE;
+
/*
* Obtain NVM image via request_firmware. Since we already used
* request_firmware_nowait() for the firmware binary load and only
@@ -392,7 +410,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
le16_to_cpu(file_sec->word1));
}
- if (section_size > IWL_MAX_NVM_SECTION_SIZE) {
+ if (section_size > max_section_size) {
IWL_ERR(mvm, "ERROR - section too large (%d)\n",
section_size);
ret = -EINVAL;
@@ -459,6 +477,7 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
{
int ret, section;
+ u32 size_read = 0;
u8 *nvm_buffer, *temp;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
@@ -475,9 +494,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
return -ENOMEM;
for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) {
/* we override the constness for initial read */
- ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
+ ret = iwl_nvm_read_section(mvm, section, nvm_buffer,
+ size_read);
if (ret < 0)
continue;
+ size_read += ret;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
@@ -509,6 +530,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
}
#endif
}
+ if (!size_read)
+ IWL_ERR(mvm, "OTP is blank\n");
kfree(nvm_buffer);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index cc2f7de396de..610dbcb0dc27 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -166,8 +166,15 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
WARN_ON((radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE) &
~CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE);
- /* silicon bits */
- reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
+ /*
+ * TODO: Bits 7-8 of CSR in 8000 HW family set the ADC sampling, and
+ * shouldn't be set to any non-zero value. The same is supposed to be
+ * true of the other HW, but unsetting them (such as the 7260) causes
+ * automatic tests to fail on seemingly unrelated errors. Need to
+ * further investigate this, but for now we'll separate cases.
+ */
+ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
+ reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
@@ -233,7 +240,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true),
RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
iwl_mvm_rx_scan_offload_complete_notif, true),
- RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
+ RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
false),
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
@@ -282,8 +289,10 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(MATCH_FOUND_NOTIFICATION),
CMD(SCAN_OFFLOAD_REQUEST_CMD),
CMD(SCAN_OFFLOAD_ABORT_CMD),
+ CMD(HOT_SPOT_CMD),
CMD(SCAN_OFFLOAD_COMPLETE),
CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
+ CMD(SCAN_ITERATION_COMPLETE),
CMD(POWER_TABLE_CMD),
CMD(WEP_KEY),
CMD(REPLY_RX_PHY_CMD),
@@ -324,6 +333,9 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(REPLY_THERMAL_MNG_BACKOFF),
CMD(MAC_PM_POWER_TABLE),
CMD(BT_COEX_CI),
+ CMD(BT_COEX_UPDATE_SW_BOOST),
+ CMD(BT_COEX_UPDATE_CORUN_LUT),
+ CMD(BT_COEX_UPDATE_REDUCED_TXP),
CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
CMD(ANTENNA_COUPLING_NOTIFICATION),
};
@@ -380,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (!hw)
return NULL;
+ if (cfg->max_rx_agg_size)
+ hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
+
op_mode = hw->priv;
op_mode->ops = &iwl_mvm_ops;
@@ -405,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_init(&mvm->d0i3_suspend_mutex);
spin_lock_init(&mvm->async_handlers_lock);
INIT_LIST_HEAD(&mvm->time_event_list);
+ INIT_LIST_HEAD(&mvm->aux_roc_te_list);
INIT_LIST_HEAD(&mvm->async_handlers_list);
spin_lock_init(&mvm->time_event_lock);
@@ -414,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
spin_lock_init(&mvm->d0i3_tx_lock);
+ spin_lock_init(&mvm->refs_lock);
skb_queue_head_init(&mvm->d0i3_tx);
init_waitqueue_head(&mvm->d0i3_exit_waitq);
@@ -502,9 +519,17 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
}
- scan_size = sizeof(struct iwl_scan_cmd) +
- mvm->fw->ucode_capa.max_probe_length +
- (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel));
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ scan_size = sizeof(struct iwl_scan_req_unified_lmac) +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels +
+ sizeof(struct iwl_scan_probe_req);
+ else
+ scan_size = sizeof(struct iwl_scan_cmd) +
+ mvm->fw->ucode_capa.max_probe_length +
+ mvm->fw->ucode_capa.n_scan_channels *
+ sizeof(struct iwl_scan_channel);
+
mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
if (!mvm->scan_cmd)
goto out_free;
@@ -520,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
/* rpm starts with a taken ref. only set the appropriate bit here. */
- set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap);
+ mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
return op_mode;
@@ -548,9 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd);
- vfree(mvm->fw_error_dump);
- kfree(mvm->fw_error_sram);
- kfree(mvm->fw_error_rxf);
+ if (mvm->fw_error_dump) {
+ vfree(mvm->fw_error_dump->op_mode_ptr);
+ vfree(mvm->fw_error_dump->trans_ptr);
+ kfree(mvm->fw_error_dump);
+ }
kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL;
@@ -754,7 +781,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
module_put(THIS_MODULE);
}
-static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
+void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
{
iwl_abort_notification_waits(&mvm->notif_wait);
@@ -811,93 +838,24 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
reprobe->dev = mvm->trans->dev;
INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
schedule_work(&reprobe->work);
- } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
+ } else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
+ (!fw_error || mvm->restart_fw)) {
/* don't let the transport/FW power down */
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
- if (mvm->restart_fw > 0)
+ if (fw_error && mvm->restart_fw > 0)
mvm->restart_fw--;
ieee80211_restart_hw(mvm->hw);
}
}
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
-{
- struct iwl_fw_error_dump_file *dump_file;
- struct iwl_fw_error_dump_data *dump_data;
- u32 file_len;
- u32 trans_len;
-
- lockdep_assert_held(&mvm->mutex);
-
- if (mvm->fw_error_dump)
- return;
-
- file_len = mvm->fw_error_sram_len +
- mvm->fw_error_rxf_len +
- sizeof(*dump_file) +
- sizeof(*dump_data) * 2;
-
- trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
- if (trans_len)
- file_len += trans_len;
-
- dump_file = vmalloc(file_len);
- if (!dump_file)
- return;
-
- mvm->fw_error_dump = dump_file;
-
- dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
- dump_file->file_len = cpu_to_le32(file_len);
- dump_data = (void *)dump_file->data;
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
- dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);
- memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);
-
- dump_data = iwl_mvm_fw_error_next_data(dump_data);
- dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
- dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
-
- /*
- * No need for lock since at the stage the FW isn't loaded. So it
- * can't assert - we are the only one who can possibly be accessing
- * mvm->fw_error_sram right now.
- */
- memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len);
-
- kfree(mvm->fw_error_rxf);
- mvm->fw_error_rxf = NULL;
- mvm->fw_error_rxf_len = 0;
-
- kfree(mvm->fw_error_sram);
- mvm->fw_error_sram = NULL;
- mvm->fw_error_sram_len = 0;
-
- if (trans_len) {
- void *buf = iwl_mvm_fw_error_next_data(dump_data);
- u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
- trans_len);
- dump_data = (void *)((u8 *)buf + real_trans_len);
- dump_file->file_len =
- cpu_to_le32(file_len - trans_len + real_trans_len);
- }
-}
-#endif
-
static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
iwl_mvm_dump_nic_error_log(mvm);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- iwl_mvm_fw_error_sram_dump(mvm);
- iwl_mvm_fw_error_rxf_dump(mvm);
-#endif
-
- iwl_mvm_nic_restart(mvm);
+ iwl_mvm_nic_restart(mvm, true);
}
static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
@@ -905,7 +863,7 @@ static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
WARN_ON(1);
- iwl_mvm_nic_restart(mvm);
+ iwl_mvm_nic_restart(mvm, true);
}
struct iwl_d0i3_iter_data {
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 539f3a942d43..6cc243f7cf60 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -261,3 +261,29 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
ctxt->ref--;
}
+
+static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ unsigned long *data = _data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ if (!mvmvif->phy_ctxt)
+ return;
+
+ if (vif->type == NL80211_IFTYPE_STATION ||
+ vif->type == NL80211_IFTYPE_AP)
+ __set_bit(mvmvif->phy_ctxt->id, data);
+}
+
+int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm)
+{
+ unsigned long phy_ctxt_counter = 0;
+
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_binding_iterator,
+ &phy_ctxt_counter);
+
+ return hweight8(phy_ctxt_counter);
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index c182a8baf685..2b2d10800a55 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -246,30 +246,10 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
}
-static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- unsigned long *data = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (!mvmvif->phy_ctxt)
- return;
-
- if (vif->type == NL80211_IFTYPE_STATION ||
- vif->type == NL80211_IFTYPE_AP)
- __set_bit(mvmvif->phy_ctxt->id, data);
-}
-
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- unsigned long phy_ctxt_counter = 0;
-
- ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_binding_iterator,
- &phy_ctxt_counter);
if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
ETH_ALEN))
@@ -291,7 +271,7 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
* Avoid using uAPSD if client is in DCM -
* low latency issue in Miracast
*/
- if (hweight8(phy_ctxt_counter) >= 2)
+ if (iwl_mvm_phy_ctx_count(mvm) >= 2)
return false;
return true;
@@ -503,6 +483,7 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
}
struct iwl_power_vifs {
+ struct iwl_mvm *mvm;
struct ieee80211_vif *bf_vif;
struct ieee80211_vif *bss_vif;
struct ieee80211_vif *p2p_vif;
@@ -512,6 +493,8 @@ struct iwl_power_vifs {
bool bss_active;
bool ap_active;
bool monitor_active;
+ bool bss_tdls;
+ bool p2p_tdls;
};
static void iwl_mvm_power_iterator(void *_data, u8 *mac,
@@ -548,6 +531,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
/* only a single MAC of the same type */
WARN_ON(power_iterator->p2p_vif);
power_iterator->p2p_vif = vif;
+ power_iterator->p2p_tdls =
+ !!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
if (mvmvif->phy_ctxt)
if (mvmvif->phy_ctxt->id < MAX_PHYS)
power_iterator->p2p_active = true;
@@ -557,6 +542,8 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac,
/* only a single MAC of the same type */
WARN_ON(power_iterator->bss_vif);
power_iterator->bss_vif = vif;
+ power_iterator->bss_tdls =
+ !!iwl_mvm_tdls_sta_count(power_iterator->mvm, vif);
if (mvmvif->phy_ctxt)
if (mvmvif->phy_ctxt->id < MAX_PHYS)
power_iterator->bss_active = true;
@@ -599,13 +586,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
/* enable PM on bss if bss stand alone */
- if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) {
+ if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active &&
+ !vifs->bss_tdls) {
bss_mvmvif->pm_enabled = true;
return;
}
/* enable PM on p2p if p2p stand alone */
- if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active) {
+ if (vifs->p2p_active && !vifs->bss_active && !vifs->ap_active &&
+ !vifs->p2p_tdls) {
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM)
p2p_mvmvif->pm_enabled = true;
return;
@@ -831,7 +820,9 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
{
struct iwl_mvm_vif *mvmvif;
- struct iwl_power_vifs vifs = {};
+ struct iwl_power_vifs vifs = {
+ .mvm = mvm,
+ };
bool ba_enable;
int ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index ba68d7b84505..4e20b3ce2b6a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -73,7 +73,7 @@ struct iwl_mvm_quota_iterator_data {
int colors[MAX_BINDINGS];
int low_latency[MAX_BINDINGS];
int n_low_latency_bindings;
- struct ieee80211_vif *new_vif;
+ struct ieee80211_vif *disabled_vif;
};
static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
@@ -83,13 +83,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u16 id;
- /*
- * We'll account for the new interface (if any) below,
- * skip it here in case we're not called from within
- * the add_interface callback (otherwise it won't show
- * up in iteration)
- */
- if (vif == data->new_vif)
+ /* skip disabled interfaces here immediately */
+ if (vif == data->disabled_vif)
return;
if (!mvmvif->phy_ctxt)
@@ -104,11 +99,6 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
if (WARN_ON_ONCE(id >= MAX_BINDINGS))
return;
- if (data->colors[id] < 0)
- data->colors[id] = mvmvif->phy_ctxt->color;
- else
- WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
-
switch (vif->type) {
case NL80211_IFTYPE_STATION:
if (vif->bss_conf.assoc)
@@ -130,6 +120,11 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
return;
}
+ if (data->colors[id] < 0)
+ data->colors[id] = mvmvif->phy_ctxt->color;
+ else
+ WARN_ON_ONCE(data->colors[id] != mvmvif->phy_ctxt->color);
+
data->n_interfaces[id]++;
if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) {
@@ -171,14 +166,15 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm,
#endif
}
-int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
+int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
+ struct ieee80211_vif *disabled_vif)
{
struct iwl_time_quota_cmd cmd = {};
int i, idx, ret, num_active_macs, quota, quota_rem, n_non_lowlat;
struct iwl_mvm_quota_iterator_data data = {
.n_interfaces = {},
.colors = { -1, -1, -1, -1 },
- .new_vif = newvif,
+ .disabled_vif = disabled_vif,
};
lockdep_assert_held(&mvm->mutex);
@@ -193,10 +189,6 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_quota_iterator, &data);
- if (newvif) {
- data.new_vif = NULL;
- iwl_mvm_quota_iterator(&data, newvif->addr, newvif);
- }
/*
* The FW's scheduling session consists of
@@ -285,6 +277,14 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
+ /* check that we have non-zero quota for all valid bindings */
+ for (i = 0; i < MAX_BINDINGS; i++) {
+ if (cmd.quotas[i].id_and_color == cpu_to_le32(FW_CTXT_INVALID))
+ continue;
+ WARN_ONCE(cmd.quotas[i].quota == 0,
+ "zero quota on binding %d\n", i);
+ }
+
ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
sizeof(cmd), &cmd);
if (ret)
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 306a6caa4868..c70e959bf0e3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -927,7 +927,7 @@ static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
u8 low;
u16 high_low;
u16 rate_mask;
- struct iwl_mvm *mvm = lq_sta->drv;
+ struct iwl_mvm *mvm = lq_sta->pers.drv;
rate_mask = rs_get_supported_rates(lq_sta, rate);
high_low = rs_get_adjacent_rate(mvm, rate->index, rate_mask,
@@ -946,7 +946,7 @@ static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
struct rs_rate *rate)
{
- struct iwl_mvm *mvm = lq_sta->drv;
+ struct iwl_mvm *mvm = lq_sta->pers.drv;
if (is_legacy(rate)) {
/* No column to downgrade from Legacy */
@@ -1026,14 +1026,14 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
if (!lq_sta) {
IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
return;
- } else if (!lq_sta->drv) {
+ } else if (!lq_sta->pers.drv) {
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
return;
}
#ifdef CONFIG_MAC80211_DEBUGFS
/* Disable last tx check if we are debugging with fixed rate */
- if (lq_sta->dbg_fixed_rate) {
+ if (lq_sta->pers.dbg_fixed_rate) {
IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
return;
}
@@ -1405,7 +1405,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
int flush_interval_passed = 0;
struct iwl_mvm *mvm;
- mvm = lq_sta->drv;
+ mvm = lq_sta->pers.drv;
active_tbl = lq_sta->active_tbl;
tbl = &(lq_sta->lq_info[active_tbl]);
@@ -1865,11 +1865,11 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE;
#ifdef CONFIG_MAC80211_DEBUGFS
- if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
+ if (lq_sta->pers.dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
IWL_DEBUG_RATE(mvm, "fixed tpc: %d\n",
- lq_sta->dbg_fixed_txp_reduction);
- lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction;
- return cur != lq_sta->dbg_fixed_txp_reduction;
+ lq_sta->pers.dbg_fixed_txp_reduction);
+ lq_sta->lq.reduced_tpc = lq_sta->pers.dbg_fixed_txp_reduction;
+ return cur != lq_sta->pers.dbg_fixed_txp_reduction;
}
#endif
@@ -2382,7 +2382,7 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
}
/* Treat uninitialized rate scaling data same as non-existing. */
- if (lq_sta && !lq_sta->drv) {
+ if (lq_sta && !lq_sta->pers.drv) {
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
mvm_sta = NULL;
}
@@ -2401,12 +2401,18 @@ static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
gfp_t gfp)
{
struct iwl_mvm_sta *sta_priv = (struct iwl_mvm_sta *)sta->drv_priv;
- struct iwl_op_mode *op_mode __maybe_unused =
- (struct iwl_op_mode *)mvm_rate;
- struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode);
+ struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_rate;
+ struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+ struct iwl_lq_sta *lq_sta = &sta_priv->lq_sta;
IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
+ lq_sta->pers.drv = mvm;
+#ifdef CONFIG_MAC80211_DEBUGFS
+ lq_sta->pers.dbg_fixed_rate = 0;
+ lq_sta->pers.dbg_fixed_txp_reduction = TPC_INVALID;
+#endif
+
return &sta_priv->lq_sta;
}
@@ -2552,7 +2558,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
sta_priv = (struct iwl_mvm_sta *)sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
- memset(lq_sta, 0, sizeof(*lq_sta));
+
+ /* clear all non-persistent lq data */
+ memset(lq_sta, 0, offsetof(typeof(*lq_sta), pers));
sband = hw->wiphy->bands[band];
@@ -2630,17 +2638,12 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* as default allow aggregation for all tids */
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
- lq_sta->drv = mvm;
/* Set last_txrate_idx to lowest rate */
lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0;
-#ifdef CONFIG_MAC80211_DEBUGFS
- lq_sta->dbg_fixed_rate = 0;
- lq_sta->dbg_fixed_txp_reduction = TPC_INVALID;
-#endif
#ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
#endif
@@ -2811,12 +2814,12 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
u8 ant = initial_rate->ant;
#ifdef CONFIG_MAC80211_DEBUGFS
- if (lq_sta->dbg_fixed_rate) {
+ if (lq_sta->pers.dbg_fixed_rate) {
rs_build_rates_table_from_fixed(mvm, lq_cmd,
lq_sta->band,
- lq_sta->dbg_fixed_rate);
+ lq_sta->pers.dbg_fixed_rate);
lq_cmd->reduced_tpc = 0;
- ant = (lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
+ ant = (lq_sta->pers.dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) >>
RATE_MCS_ANT_POS;
} else
#endif
@@ -2926,14 +2929,14 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n",
- lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
+ lq_sta->lq.sta_id, lq_sta->pers.dbg_fixed_rate);
- if (lq_sta->dbg_fixed_rate) {
+ if (lq_sta->pers.dbg_fixed_rate) {
struct rs_rate rate;
- rs_rate_from_ucode_rate(lq_sta->dbg_fixed_rate,
+ rs_rate_from_ucode_rate(lq_sta->pers.dbg_fixed_rate,
lq_sta->band, &rate);
rs_fill_lq_cmd(mvm, NULL, lq_sta, &rate);
- iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false);
+ iwl_mvm_send_lq_cmd(lq_sta->pers.drv, &lq_sta->lq, false);
}
}
@@ -2946,16 +2949,16 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
size_t buf_size;
u32 parsed_rate;
- mvm = lq_sta->drv;
+ mvm = lq_sta->pers.drv;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
if (sscanf(buf, "%x", &parsed_rate) == 1)
- lq_sta->dbg_fixed_rate = parsed_rate;
+ lq_sta->pers.dbg_fixed_rate = parsed_rate;
else
- lq_sta->dbg_fixed_rate = 0;
+ lq_sta->pers.dbg_fixed_rate = 0;
rs_program_fix_rate(mvm, lq_sta);
@@ -2974,7 +2977,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
struct iwl_mvm *mvm;
struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
struct rs_rate *rate = &tbl->rate;
- mvm = lq_sta->drv;
+ mvm = lq_sta->pers.drv;
buff = kmalloc(2048, GFP_KERNEL);
if (!buff)
return -ENOMEM;
@@ -2984,7 +2987,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
lq_sta->total_failed, lq_sta->total_success,
lq_sta->active_legacy_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
- lq_sta->dbg_fixed_rate);
+ lq_sta->pers.dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
(mvm->fw->valid_tx_ant & ANT_A) ? "ANT_A," : "",
(mvm->fw->valid_tx_ant & ANT_B) ? "ANT_B," : "",
@@ -3182,31 +3185,20 @@ static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = {
static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
{
struct iwl_lq_sta *lq_sta = mvm_sta;
- lq_sta->rs_sta_dbgfs_scale_table_file =
- debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
- lq_sta, &rs_sta_dbgfs_scale_table_ops);
- lq_sta->rs_sta_dbgfs_stats_table_file =
- debugfs_create_file("rate_stats_table", S_IRUSR, dir,
- lq_sta, &rs_sta_dbgfs_stats_table_ops);
- lq_sta->rs_sta_dbgfs_drv_tx_stats_file =
- debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir,
- lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops);
- lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
- debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
- &lq_sta->tx_agg_tid_en);
- lq_sta->rs_sta_dbgfs_reduced_txp_file =
- debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir,
- &lq_sta->dbg_fixed_txp_reduction);
+ debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
+ lq_sta, &rs_sta_dbgfs_scale_table_ops);
+ debugfs_create_file("rate_stats_table", S_IRUSR, dir,
+ lq_sta, &rs_sta_dbgfs_stats_table_ops);
+ debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir,
+ lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops);
+ debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
+ &lq_sta->tx_agg_tid_en);
+ debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir,
+ &lq_sta->pers.dbg_fixed_txp_reduction);
}
static void rs_remove_debugfs(void *mvm, void *mvm_sta)
{
- struct iwl_lq_sta *lq_sta = mvm_sta;
- debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
- debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
- debugfs_remove(lq_sta->rs_sta_dbgfs_drv_tx_stats_file);
- debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
- debugfs_remove(lq_sta->rs_sta_dbgfs_reduced_txp_file);
}
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 374a83d7db25..f27b9d687a25 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -349,16 +349,6 @@ struct iwl_lq_sta {
struct iwl_lq_cmd lq;
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
u8 tx_agg_tid_en;
-#ifdef CONFIG_MAC80211_DEBUGFS
- struct dentry *rs_sta_dbgfs_scale_table_file;
- struct dentry *rs_sta_dbgfs_stats_table_file;
- struct dentry *rs_sta_dbgfs_drv_tx_stats_file;
- struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
- struct dentry *rs_sta_dbgfs_reduced_txp_file;
- u32 dbg_fixed_rate;
- u8 dbg_fixed_txp_reduction;
-#endif
- struct iwl_mvm *drv;
/* used to be in sta_info */
int last_txrate_idx;
@@ -369,6 +359,15 @@ struct iwl_lq_sta {
/* tx power reduce for this sta */
int tpc_reduce;
+
+ /* persistent fields - initialized only once - keep last! */
+ struct {
+#ifdef CONFIG_MAC80211_DEBUGFS
+ u32 dbg_fixed_rate;
+ u8 dbg_fixed_txp_reduction;
+#endif
+ struct iwl_mvm *drv;
+ } pers;
};
/* Initialize station's rate scaling information after adding station */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index cf7276967acd..4b98987fc413 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -259,6 +259,23 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
memset(&rx_status, 0, sizeof(rx_status));
/*
+ * We have tx blocked stations (with CS bit). If we heard frames from
+ * a blocked station on a new channel we can TX to it again.
+ */
+ if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
+ struct ieee80211_sta *sta;
+
+ rcu_read_lock();
+
+ sta = ieee80211_find_sta(
+ rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
+ if (sta)
+ iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
+
+ rcu_read_unlock();
+ }
+
+ /*
* drop the packet if it has failed being decrypted by HW
*/
if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, &rx_status, rx_pkt_status)) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index eac2b424f6a0..004b1f5d0314 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -97,10 +97,9 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
return cpu_to_le16(rx_chain);
}
-static inline __le32
-iwl_mvm_scan_rxon_flags(struct cfg80211_scan_request *req)
+static __le32 iwl_mvm_scan_rxon_flags(enum ieee80211_band band)
{
- if (req->channels[0]->band == IEEE80211_BAND_2GHZ)
+ if (band == IEEE80211_BAND_2GHZ)
return cpu_to_le32(PHY_BAND_24);
else
return cpu_to_le32(PHY_BAND_5);
@@ -130,19 +129,19 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
* request list, is not copied here, but inserted directly to the probe
* request.
*/
-static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
- struct cfg80211_scan_request *req,
- int first)
+static void iwl_mvm_scan_fill_ssids(struct iwl_ssid_ie *cmd_ssid,
+ struct cfg80211_ssid *ssids,
+ int n_ssids, int first)
{
int fw_idx, req_idx;
- for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx >= first;
+ for (req_idx = n_ssids - 1, fw_idx = 0; req_idx >= first;
req_idx--, fw_idx++) {
- cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
- cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
- memcpy(cmd->direct_scan[fw_idx].ssid,
- req->ssids[req_idx].ssid,
- req->ssids[req_idx].ssid_len);
+ cmd_ssid[fw_idx].id = WLAN_EID_SSID;
+ cmd_ssid[fw_idx].len = ssids[req_idx].ssid_len;
+ memcpy(cmd_ssid[fw_idx].ssid,
+ ssids[req_idx].ssid,
+ ssids[req_idx].ssid_len);
}
}
@@ -204,7 +203,8 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
*/
static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
int n_ssids, const u8 *ssid, int ssid_len,
- const u8 *ie, int ie_len,
+ const u8 *band_ie, int band_ie_len,
+ const u8 *common_ie, int common_ie_len,
int left)
{
int len = 0;
@@ -244,12 +244,19 @@ static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
len += ssid_len + 2;
- if (WARN_ON(left < ie_len))
+ if (WARN_ON(left < band_ie_len + common_ie_len))
return len;
- if (ie && ie_len) {
- memcpy(pos, ie, ie_len);
- len += ie_len;
+ if (band_ie && band_ie_len) {
+ memcpy(pos, band_ie, band_ie_len);
+ pos += band_ie_len;
+ len += band_ie_len;
+ }
+
+ if (common_ie && common_ie_len) {
+ memcpy(pos, common_ie, common_ie_len);
+ pos += common_ie_len;
+ len += common_ie_len;
}
return (u16)len;
@@ -267,7 +274,7 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac,
static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- int n_ssids,
+ int n_ssids, u32 flags,
struct iwl_mvm_scan_params *params)
{
bool global_bound = false;
@@ -289,6 +296,9 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
params->max_out_time = 250;
}
+ if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+ params->max_out_time = 200;
+
not_bound:
for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
@@ -325,22 +335,20 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n");
mvm->scan_status = IWL_MVM_SCAN_OS;
- memset(cmd, 0, sizeof(struct iwl_scan_cmd) +
- mvm->fw->ucode_capa.max_probe_length +
- (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel)));
+ memset(cmd, 0, ksize(cmd));
cmd->channel_count = (u8)req->n_channels;
cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME);
cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH);
cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm);
- iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, &params);
+ iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags, &params);
cmd->max_out_time = cpu_to_le32(params.max_out_time);
cmd->suspend_time = cpu_to_le32(params.suspend_time);
if (params.passive_fragmented)
cmd->scan_flags |= SCAN_FLAGS_FRAGMENTED_SCAN;
- cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req);
+ cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band);
cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
MAC_FILTER_IN_BEACON);
@@ -367,7 +375,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
}
- iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0);
+ iwl_mvm_scan_fill_ssids(cmd->direct_scan, req->ssids, req->n_ssids,
+ basic_ssid ? 1 : 0);
cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
TX_CMD_FLG_BT_DIS);
@@ -382,7 +391,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
(struct ieee80211_mgmt *)cmd->data,
vif->addr,
req->n_ssids, ssid, ssid_len,
- req->ie, req->ie_len,
+ req->ie, req->ie_len, NULL, 0,
mvm->fw->ucode_capa.max_probe_length));
iwl_mvm_scan_fill_channels(cmd, req, basic_ssid, &params);
@@ -441,16 +450,27 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
return 0;
}
-int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd)
+int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_sched_scan_results *notif = (void *)pkt->data;
+ u8 client_bitmap = 0;
- if (notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
- IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
- ieee80211_sched_scan_results(mvm->hw);
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+ struct iwl_sched_scan_results *notif = (void *)pkt->data;
+
+ client_bitmap = notif->client_bitmap;
+ }
+
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
+ client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
+ if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
+ IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
+ ieee80211_sched_scan_results(mvm->hw);
+ } else {
+ IWL_DEBUG_SCAN(mvm, "Scan results\n");
+ }
}
return 0;
@@ -494,7 +514,7 @@ static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait,
};
}
-int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
+static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm)
{
struct iwl_notification_wait wait_scan_abort;
static const u8 scan_abort_notif[] = { SCAN_ABORT_CMD,
@@ -535,33 +555,52 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scan_offload_complete *scan_notif = (void *)pkt->data;
+ u8 status, ebs_status;
+
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) {
+ struct iwl_periodic_scan_complete *scan_notif;
+
+ scan_notif = (void *)pkt->data;
+ status = scan_notif->status;
+ ebs_status = scan_notif->ebs_status;
+ } else {
+ struct iwl_scan_offload_complete *scan_notif;
+ scan_notif = (void *)pkt->data;
+ status = scan_notif->status;
+ ebs_status = scan_notif->ebs_status;
+ }
/* scan status must be locked for proper checking */
lockdep_assert_held(&mvm->mutex);
IWL_DEBUG_SCAN(mvm,
- "Scheduled scan completed, status %s EBS status %s:%d\n",
- scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
- "completed" : "aborted", scan_notif->ebs_status ==
- IWL_SCAN_EBS_SUCCESS ? "success" : "failed",
- scan_notif->ebs_status);
+ "%s completed, status %s, EBS status %s\n",
+ mvm->scan_status == IWL_MVM_SCAN_SCHED ?
+ "Scheduled scan" : "Scan",
+ status == IWL_SCAN_OFFLOAD_COMPLETED ?
+ "completed" : "aborted",
+ ebs_status == IWL_SCAN_EBS_SUCCESS ?
+ "success" : "failed");
/* only call mac80211 completion if the stop was initiated by FW */
if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
mvm->scan_status = IWL_MVM_SCAN_NONE;
ieee80211_sched_scan_stopped(mvm->hw);
+ } else if (mvm->scan_status == IWL_MVM_SCAN_OS) {
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
+ ieee80211_scan_completed(mvm->hw,
+ status == IWL_SCAN_OFFLOAD_ABORTED);
}
- mvm->last_ebs_successful = !scan_notif->ebs_status;
+ mvm->last_ebs_successful = !ebs_status;
return 0;
}
static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct ieee80211_sched_scan_ies *ies,
+ struct ieee80211_scan_ies *ies,
enum ieee80211_band band,
struct iwl_tx_cmd *cmd,
u8 *data)
@@ -577,7 +616,8 @@ static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm,
cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data,
vif->addr,
1, NULL, 0,
- ies->ie[band], ies->len[band],
+ ies->ies[band], ies->len[band],
+ ies->common_ies, ies->common_ie_len,
SCAN_OFFLOAD_PROBE_REQ_SIZE);
cmd->len = cpu_to_le16(cmd_len);
}
@@ -621,8 +661,8 @@ static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list)
}
static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
- struct iwl_scan_offload_cmd *scan,
- u32 *ssid_bitmap)
+ struct iwl_ssid_ie *direct_scan,
+ u32 *ssid_bitmap, bool basic_ssid)
{
int i, j;
int index;
@@ -636,10 +676,10 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
/* skip empty SSID matchsets */
if (!req->match_sets[i].ssid.ssid_len)
continue;
- scan->direct_scan[i].id = WLAN_EID_SSID;
- scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
- memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
- scan->direct_scan[i].len);
+ direct_scan[i].id = WLAN_EID_SSID;
+ direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
+ memcpy(direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
+ direct_scan[i].len);
}
/* add SSIDs from scan SSID list */
@@ -647,14 +687,14 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
for (j = 0; j < req->n_ssids && i < PROBE_OPTION_MAX; j++) {
index = iwl_ssid_exist(req->ssids[j].ssid,
req->ssids[j].ssid_len,
- scan->direct_scan);
+ direct_scan);
if (index < 0) {
- if (!req->ssids[j].ssid_len)
+ if (!req->ssids[j].ssid_len && basic_ssid)
continue;
- scan->direct_scan[i].id = WLAN_EID_SSID;
- scan->direct_scan[i].len = req->ssids[j].ssid_len;
- memcpy(scan->direct_scan[i].ssid, req->ssids[j].ssid,
- scan->direct_scan[i].len);
+ direct_scan[i].id = WLAN_EID_SSID;
+ direct_scan[i].len = req->ssids[j].ssid_len;
+ memcpy(direct_scan[i].ssid, req->ssids[j].ssid,
+ direct_scan[i].len);
*ssid_bitmap |= BIT(i + 1);
i++;
} else {
@@ -665,12 +705,19 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req,
static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req,
- struct iwl_scan_channel_cfg *channels,
+ u8 *channels_buffer,
enum ieee80211_band band,
int *head,
u32 ssid_bitmap,
struct iwl_mvm_scan_params *params)
{
+ u32 n_channels = mvm->fw->ucode_capa.n_scan_channels;
+ __le32 *type = (__le32 *)channels_buffer;
+ __le16 *channel_number = (__le16 *)(type + n_channels);
+ __le16 *iter_count = channel_number + n_channels;
+ __le32 *iter_interval = (__le32 *)(iter_count + n_channels);
+ u8 *active_dwell = (u8 *)(iter_interval + n_channels);
+ u8 *passive_dwell = active_dwell + n_channels;
int i, index = 0;
for (i = 0; i < req->n_channels; i++) {
@@ -682,34 +729,33 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
index = *head;
(*head)++;
- channels->channel_number[index] = cpu_to_le16(chan->hw_value);
- channels->dwell_time[index][0] = params->dwell[band].active;
- channels->dwell_time[index][1] = params->dwell[band].passive;
+ channel_number[index] = cpu_to_le16(chan->hw_value);
+ active_dwell[index] = params->dwell[band].active;
+ passive_dwell[index] = params->dwell[band].passive;
- channels->iter_count[index] = cpu_to_le16(1);
- channels->iter_interval[index] = 0;
+ iter_count[index] = cpu_to_le16(1);
+ iter_interval[index] = 0;
if (!(chan->flags & IEEE80211_CHAN_NO_IR))
- channels->type[index] |=
+ type[index] |=
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
- channels->type[index] |=
- cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
- IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
+ type[index] |= cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
+ IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
if (chan->flags & IEEE80211_CHAN_NO_HT40)
- channels->type[index] |=
+ type[index] |=
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW);
/* scan for all SSIDs from req->ssids */
- channels->type[index] |= cpu_to_le32(ssid_bitmap);
+ type[index] |= cpu_to_le32(ssid_bitmap);
}
}
int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
@@ -717,6 +763,9 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
u32 ssid_bitmap;
int cmd_len;
int ret;
+ u8 *probes;
+ bool basic_ssid = !(mvm->fw->ucode_capa.flags &
+ IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID);
struct iwl_scan_offload_cfg *scan_cfg;
struct iwl_host_cmd cmd = {
@@ -727,24 +776,29 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
cmd_len = sizeof(struct iwl_scan_offload_cfg) +
+ mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE +
2 * SCAN_OFFLOAD_PROBE_REQ_SIZE;
scan_cfg = kzalloc(cmd_len, GFP_KERNEL);
if (!scan_cfg)
return -ENOMEM;
- iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, &params);
+ probes = scan_cfg->data +
+ mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE;
+
+ iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, &params);
iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, &params);
scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len);
- iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap);
+ iwl_scan_offload_build_ssid(req, scan_cfg->scan_cmd.direct_scan,
+ &ssid_bitmap, basic_ssid);
/* build tx frames for supported bands */
if (band_2ghz) {
iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
IEEE80211_BAND_2GHZ,
&scan_cfg->scan_cmd.tx_cmd[0],
- scan_cfg->data);
- iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+ probes);
+ iwl_build_channel_cfg(mvm, req, scan_cfg->data,
IEEE80211_BAND_2GHZ, &head,
ssid_bitmap, &params);
}
@@ -752,9 +806,9 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
iwl_scan_offload_build_tx_cmd(mvm, vif, ies,
IEEE80211_BAND_5GHZ,
&scan_cfg->scan_cmd.tx_cmd[1],
- scan_cfg->data +
+ probes +
SCAN_OFFLOAD_PROBE_REQ_SIZE);
- iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
+ iwl_build_channel_cfg(mvm, req, scan_cfg->data,
IEEE80211_BAND_5GHZ, &head,
ssid_bitmap, &params);
}
@@ -845,11 +899,11 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
.watchdog = IWL_SCHED_SCAN_WATCHDOG,
.schedule_line[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS,
- .schedule_line[0].delay = req->interval / 1000,
+ .schedule_line[0].delay = cpu_to_le16(req->interval / 1000),
.schedule_line[0].full_scan_mul = 1,
.schedule_line[1].iterations = 0xff,
- .schedule_line[1].delay = req->interval / 1000,
+ .schedule_line[1].delay = cpu_to_le16(req->interval / 1000),
.schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER,
};
@@ -872,7 +926,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
sizeof(scan_req), &scan_req);
}
-static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
+static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
{
int ret;
struct iwl_host_cmd cmd = {
@@ -883,7 +937,9 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
/* Exit instantly with error when device is not ready
* to receive scan abort command or it does not perform
* scheduled scan currently */
- if (mvm->scan_status != IWL_MVM_SCAN_SCHED)
+ if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+ (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
+ mvm->scan_status != IWL_MVM_SCAN_OS))
return -EIO;
ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
@@ -905,16 +961,19 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
return ret;
}
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify)
+int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
{
int ret;
struct iwl_notification_wait wait_scan_done;
static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
+ bool sched = mvm->scan_status == IWL_MVM_SCAN_SCHED;
lockdep_assert_held(&mvm->mutex);
- if (mvm->scan_status != IWL_MVM_SCAN_SCHED) {
- IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n");
+ if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+ (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
+ mvm->scan_status != IWL_MVM_SCAN_OS)) {
+ IWL_DEBUG_SCAN(mvm, "No scan to stop\n");
return 0;
}
@@ -923,14 +982,16 @@ int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify)
ARRAY_SIZE(scan_done_notif),
NULL, NULL);
- ret = iwl_mvm_send_sched_scan_abort(mvm);
+ ret = iwl_mvm_send_scan_offload_abort(mvm);
if (ret) {
- IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret);
+ IWL_DEBUG_SCAN(mvm, "Send stop %sscan failed %d\n",
+ sched ? "offloaded " : "", ret);
iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
return ret;
}
- IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n");
+ IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
+ sched ? "offloaded " : "");
ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
if (ret)
@@ -943,8 +1004,317 @@ int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify)
*/
mvm->scan_status = IWL_MVM_SCAN_NONE;
- if (notify)
- ieee80211_sched_scan_stopped(mvm->hw);
+ if (notify) {
+ if (sched)
+ ieee80211_sched_scan_stopped(mvm->hw);
+ else
+ ieee80211_scan_completed(mvm->hw, true);
+ }
return 0;
}
+
+static void iwl_mvm_unified_scan_fill_tx_cmd(struct iwl_mvm *mvm,
+ struct iwl_scan_req_tx_cmd *tx_cmd,
+ bool no_cck)
+{
+ tx_cmd[0].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
+ TX_CMD_FLG_BT_DIS);
+ tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
+ IEEE80211_BAND_2GHZ,
+ no_cck);
+ tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
+
+ tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
+ TX_CMD_FLG_BT_DIS);
+ tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm,
+ IEEE80211_BAND_5GHZ,
+ no_cck);
+ tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
+}
+
+static void
+iwl_mvm_lmac_scan_cfg_channels(struct iwl_mvm *mvm,
+ struct ieee80211_channel **channels,
+ int n_channels, u32 ssid_bitmap,
+ struct iwl_scan_req_unified_lmac *cmd)
+{
+ struct iwl_scan_channel_cfg_lmac *channel_cfg = (void *)&cmd->data;
+ int i;
+
+ for (i = 0; i < n_channels; i++) {
+ channel_cfg[i].channel_num =
+ cpu_to_le16(channels[i]->hw_value);
+ channel_cfg[i].iter_count = cpu_to_le16(1);
+ channel_cfg[i].iter_interval = 0;
+ channel_cfg[i].flags =
+ cpu_to_le32(IWL_UNIFIED_SCAN_CHANNEL_PARTIAL |
+ ssid_bitmap);
+ }
+}
+
+static void
+iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct ieee80211_scan_ies *ies,
+ struct iwl_scan_req_unified_lmac *cmd)
+{
+ struct iwl_scan_probe_req *preq = (void *)(cmd->data +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels);
+ struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
+ u8 *pos;
+
+ frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+ eth_broadcast_addr(frame->da);
+ memcpy(frame->sa, vif->addr, ETH_ALEN);
+ eth_broadcast_addr(frame->bssid);
+ frame->seq_ctrl = 0;
+
+ pos = frame->u.probe_req.variable;
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = 0;
+
+ preq->mac_header.offset = 0;
+ preq->mac_header.len = cpu_to_le16(24 + 2);
+
+ memcpy(pos, ies->ies[IEEE80211_BAND_2GHZ],
+ ies->len[IEEE80211_BAND_2GHZ]);
+ preq->band_data[0].offset = cpu_to_le16(pos - preq->buf);
+ preq->band_data[0].len = cpu_to_le16(ies->len[IEEE80211_BAND_2GHZ]);
+ pos += ies->len[IEEE80211_BAND_2GHZ];
+
+ memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ],
+ ies->len[IEEE80211_BAND_5GHZ]);
+ preq->band_data[1].offset = cpu_to_le16(pos - preq->buf);
+ preq->band_data[1].len = cpu_to_le16(ies->len[IEEE80211_BAND_5GHZ]);
+ pos += ies->len[IEEE80211_BAND_5GHZ];
+
+ memcpy(pos, ies->common_ies, ies->common_ie_len);
+ preq->common_data.offset = cpu_to_le16(pos - preq->buf);
+ preq->common_data.len = cpu_to_le16(ies->common_ie_len);
+}
+
+static void
+iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
+ struct iwl_scan_req_unified_lmac *cmd,
+ struct iwl_mvm_scan_params *params)
+{
+ memset(cmd, 0, ksize(cmd));
+ cmd->active_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].active;
+ cmd->passive_dwell = (u8)params->dwell[IEEE80211_BAND_2GHZ].passive;
+ /* TODO: Use params; now fragmented isn't used. */
+ cmd->fragmented_dwell = 0;
+ cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
+ cmd->max_out_time = cpu_to_le32(params->max_out_time);
+ cmd->suspend_time = cpu_to_le32(params->suspend_time);
+ cmd->scan_prio = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
+ cmd->iter_num = cpu_to_le32(1);
+
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT &&
+ mvm->last_ebs_successful) {
+ cmd->channel_opt[0].flags =
+ cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
+ IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
+ cmd->channel_opt[1].flags =
+ cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
+ IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
+ IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
+ }
+}
+
+int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *req)
+{
+ struct iwl_host_cmd hcmd = {
+ .id = SCAN_OFFLOAD_REQUEST_CMD,
+ .len = { sizeof(struct iwl_scan_req_unified_lmac) +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels +
+ sizeof(struct iwl_scan_probe_req), },
+ .data = { mvm->scan_cmd, },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ };
+ struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
+ struct iwl_mvm_scan_params params = {};
+ u32 flags;
+ int ssid_bitmap = 0;
+ int ret, i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* we should have failed registration if scan_cmd was NULL */
+ if (WARN_ON(mvm->scan_cmd == NULL))
+ return -ENOMEM;
+
+ if (WARN_ON_ONCE(req->req.n_ssids > PROBE_OPTION_MAX ||
+ req->ies.common_ie_len + req->ies.len[0] +
+ req->ies.len[1] + 24 + 2 >
+ SCAN_OFFLOAD_PROBE_REQ_SIZE ||
+ req->req.n_channels >
+ mvm->fw->ucode_capa.n_scan_channels))
+ return -1;
+
+ mvm->scan_status = IWL_MVM_SCAN_OS;
+
+ iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
+ &params);
+
+ iwl_mvm_build_generic_unified_scan_cmd(mvm, cmd, &params);
+
+ cmd->n_channels = (u8)req->req.n_channels;
+
+ flags = IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+
+ if (req->req.n_ssids == 1 && req->req.ssids[0].ssid_len != 0)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
+
+ if (params.passive_fragmented)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
+
+ if (req->req.n_ssids == 0)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
+
+ cmd->scan_flags = cpu_to_le32(flags);
+
+ cmd->flags = iwl_mvm_scan_rxon_flags(req->req.channels[0]->band);
+ cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
+ MAC_FILTER_IN_BEACON);
+ iwl_mvm_unified_scan_fill_tx_cmd(mvm, cmd->tx_cmd, req->req.no_cck);
+ iwl_mvm_scan_fill_ssids(cmd->direct_scan, req->req.ssids,
+ req->req.n_ssids, 0);
+
+ cmd->schedule[0].delay = 0;
+ cmd->schedule[0].iterations = 1;
+ cmd->schedule[0].full_scan_mul = 0;
+ cmd->schedule[1].delay = 0;
+ cmd->schedule[1].iterations = 0;
+ cmd->schedule[1].full_scan_mul = 0;
+
+ for (i = 1; i <= req->req.n_ssids; i++)
+ ssid_bitmap |= BIT(i);
+
+ iwl_mvm_lmac_scan_cfg_channels(mvm, req->req.channels,
+ req->req.n_channels, ssid_bitmap,
+ cmd);
+
+ iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, cmd);
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
+ if (!ret) {
+ IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
+ } else {
+ /*
+ * If the scan failed, it usually means that the FW was unable
+ * to allocate the time events. Warn on it, but maybe we
+ * should try to send the command again with different params.
+ */
+ IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
+ ret = -EIO;
+ }
+ return ret;
+}
+
+int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies)
+{
+ struct iwl_host_cmd hcmd = {
+ .id = SCAN_OFFLOAD_REQUEST_CMD,
+ .len = { sizeof(struct iwl_scan_req_unified_lmac) +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels +
+ sizeof(struct iwl_scan_probe_req), },
+ .data = { mvm->scan_cmd, },
+ .dataflags = { IWL_HCMD_DFL_NOCOPY, },
+ };
+ struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
+ struct iwl_mvm_scan_params params = {};
+ int ret;
+ u32 flags = 0, ssid_bitmap = 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* we should have failed registration if scan_cmd was NULL */
+ if (WARN_ON(mvm->scan_cmd == NULL))
+ return -ENOMEM;
+
+ if (WARN_ON_ONCE(req->n_ssids > PROBE_OPTION_MAX ||
+ ies->common_ie_len + ies->len[0] + ies->len[1] + 24 + 2
+ > SCAN_OFFLOAD_PROBE_REQ_SIZE ||
+ req->n_channels > mvm->fw->ucode_capa.n_scan_channels))
+ return -ENOBUFS;
+
+ iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, &params);
+
+ iwl_mvm_build_generic_unified_scan_cmd(mvm, cmd, &params);
+
+ cmd->n_channels = (u8)req->n_channels;
+
+ if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending scheduled scan with filtering, n_match_sets %d\n",
+ req->n_match_sets);
+ } else {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending Scheduled scan without filtering\n");
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+ }
+
+ if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
+
+ if (params.passive_fragmented)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED;
+
+ if (req->n_ssids == 0)
+ flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
+
+ cmd->scan_flags = cpu_to_le32(flags);
+
+ cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band);
+ cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
+ MAC_FILTER_IN_BEACON);
+ iwl_mvm_unified_scan_fill_tx_cmd(mvm, cmd->tx_cmd, false);
+ iwl_scan_offload_build_ssid(req, cmd->direct_scan, &ssid_bitmap, false);
+
+ cmd->schedule[0].delay = cpu_to_le16(req->interval / MSEC_PER_SEC);
+ cmd->schedule[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS;
+ cmd->schedule[0].full_scan_mul = 1;
+
+ cmd->schedule[1].delay = cpu_to_le16(req->interval / MSEC_PER_SEC);
+ cmd->schedule[1].iterations = 0xff;
+ cmd->schedule[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER;
+
+ iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels,
+ ssid_bitmap, cmd);
+
+ iwl_mvm_build_unified_scan_probe(mvm, vif, ies, cmd);
+
+ ret = iwl_mvm_send_cmd(mvm, &hcmd);
+ if (!ret) {
+ IWL_DEBUG_SCAN(mvm,
+ "Sched scan request was sent successfully\n");
+ } else {
+ /*
+ * If the scan failed, it usually means that the FW was unable
+ * to allocate the time events. Warn on it, but maybe we
+ * should try to send the command again with different params.
+ */
+ IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
+ ret = -EIO;
+ }
+ return ret;
+}
+
+
+int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
+{
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ return iwl_mvm_scan_offload_stop(mvm, true);
+ return iwl_mvm_cancel_regular_scan(mvm);
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 1fb01ea2e704..763548880399 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update)
{
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
- struct iwl_mvm_add_sta_cmd add_sta_cmd;
+ struct iwl_mvm_add_sta_cmd add_sta_cmd = {
+ .sta_id = mvm_sta->sta_id,
+ .mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
+ .add_modify = update ? 1 : 0,
+ .station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
+ STA_FLG_MIMO_EN_MSK),
+ };
int ret;
u32 status;
u32 agg_size = 0, mpdu_dens = 0;
- memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
-
- add_sta_cmd.sta_id = mvm_sta->sta_id;
- add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
if (!update) {
add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
}
- add_sta_cmd.add_modify = update ? 1 : 0;
-
- add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
- STA_FLG_MIMO_EN_MSK);
switch (sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
@@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- /* Add the aux station, but without any queues */
- ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0,
+ /* Map Aux queue to fifo - needs to happen before adding Aux station */
+ iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
+ IWL_MVM_TX_FIFO_MCAST);
+
+ /* Allocate aux station and assign to it the aux queue */
+ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
NL80211_IFTYPE_UNSPECIFIED);
if (ret)
return ret;
@@ -1448,3 +1450,77 @@ int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
return 0;
}
+
+void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvmsta, bool disable)
+{
+ struct iwl_mvm_add_sta_cmd cmd = {
+ .add_modify = STA_MODE_MODIFY,
+ .sta_id = mvmsta->sta_id,
+ .station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0,
+ .station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX),
+ .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
+ };
+ int ret;
+
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_DISABLE_STA_TX))
+ return;
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
+ if (ret)
+ IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
+}
+
+void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ bool disable)
+{
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+
+ spin_lock_bh(&mvm_sta->lock);
+
+ if (mvm_sta->disable_tx == disable) {
+ spin_unlock_bh(&mvm_sta->lock);
+ return;
+ }
+
+ mvm_sta->disable_tx = disable;
+
+ /*
+ * Tell mac80211 to start/stop queueing tx for this station,
+ * but don't stop queueing if there are still pending frames
+ * for this station.
+ */
+ if (disable || !atomic_read(&mvm->pending_frames[mvm_sta->sta_id]))
+ ieee80211_sta_block_awake(mvm->hw, sta, disable);
+
+ iwl_mvm_sta_modify_disable_tx(mvm, mvm_sta, disable);
+
+ spin_unlock_bh(&mvm_sta->lock);
+}
+
+void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif *mvmvif,
+ bool disable)
+{
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvm_sta;
+ int i;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ /* Block/unblock all the stations of the given mvmvif */
+ for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
+ lockdep_is_held(&mvm->mutex));
+ if (IS_ERR_OR_NULL(sta))
+ continue;
+
+ mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+ if (mvm_sta->mac_id_n_color !=
+ FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color))
+ continue;
+
+ iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, disable);
+ }
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index d98e8a2142b8..3b1c8bd6cb54 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -73,6 +73,7 @@
#include "rs.h"
struct iwl_mvm;
+struct iwl_mvm_vif;
/**
* DOC: station table - introduction
@@ -295,6 +296,7 @@ static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
* @tid_data: per tid data. Look at %iwl_mvm_tid_data.
* @tx_protection: reference counter for controlling the Tx protection.
* @tt_tx_protection: is thermal throttling enable Tx protection?
+ * @disable_tx: is tx to this STA disabled?
*
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
* in the structure for use by driver. This structure is placed in that
@@ -317,6 +319,8 @@ struct iwl_mvm_sta {
/* Temporary, until the new TLC will control the Tx protection */
s8 tx_protection;
bool tt_tx_protection;
+
+ bool disable_tx;
};
static inline struct iwl_mvm_sta *
@@ -404,5 +408,13 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
bool agg);
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool drain);
+void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_sta *mvmsta, bool disable);
+void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
+ bool disable);
+void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif *mvmvif,
+ bool disable);
#endif /* __sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 80100f6cc12a..33e5041f1efc 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -72,9 +72,6 @@
#include "iwl-io.h"
#include "iwl-prph.h"
-/* A TimeUnit is 1024 microsecond */
-#define MSEC_TO_TU(_msec) (_msec*1000/1024)
-
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
@@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void iwl_mvm_roc_done_wk(struct work_struct *wk)
{
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk);
+ u32 queues = 0;
+
+ /*
+ * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
+ * This will cause the TX path to drop offchannel transmissions.
+ * That would also be done by mac80211, but it is racy, in particular
+ * in the case that the time event actually completed in the firmware
+ * (which is handled in iwl_mvm_te_handle_notif).
+ */
+ if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
+ queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
+ if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
+ queues |= BIT(mvm->aux_queue);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
synchronize_net();
@@ -113,22 +125,12 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
- iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
+ iwl_mvm_flush_tx_path(mvm, queues, false);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
{
/*
- * First, clear the ROC_RUNNING status bit. This will cause the TX
- * path to drop offchannel transmissions. That would also be done
- * by mac80211, but it is racy, in particular in the case that the
- * time event actually completed in the firmware (which is handled
- * in iwl_mvm_te_handle_notif).
- */
- clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
- iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
-
- /*
* Of course, our status bit is just as racy as mac80211, so in
* addition, fire off the work struct which will drop all frames
* from the hardware queues that made it through the race. First
@@ -138,6 +140,41 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
schedule_work(&mvm->roc_done_wk);
}
+static void iwl_mvm_csa_noa_start(struct iwl_mvm *mvm)
+{
+ struct ieee80211_vif *csa_vif;
+
+ rcu_read_lock();
+
+ csa_vif = rcu_dereference(mvm->csa_vif);
+ if (!csa_vif || !csa_vif->csa_active)
+ goto out_unlock;
+
+ IWL_DEBUG_TE(mvm, "CSA NOA started\n");
+
+ /*
+ * CSA NoA is started but we still have beacons to
+ * transmit on the current channel.
+ * So we just do nothing here and the switch
+ * will be performed on the last TBTT.
+ */
+ if (!ieee80211_csa_is_complete(csa_vif)) {
+ IWL_WARN(mvm, "CSA NOA started too early\n");
+ goto out_unlock;
+ }
+
+ ieee80211_csa_finish(csa_vif);
+
+ rcu_read_unlock();
+
+ RCU_INIT_POINTER(mvm->csa_vif, NULL);
+
+ return;
+
+out_unlock:
+ rcu_read_unlock();
+}
+
static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
const char *errmsg)
@@ -213,6 +250,14 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
ieee80211_ready_on_channel(mvm->hw);
+ } else if (te_data->vif->type == NL80211_IFTYPE_AP) {
+ if (le32_to_cpu(notif->status))
+ iwl_mvm_csa_noa_start(mvm);
+ else
+ IWL_DEBUG_TE(mvm, "CSA NOA failed to start\n");
+
+ /* we don't need it anymore */
+ iwl_mvm_te_clear_data(mvm, te_data);
}
} else {
IWL_WARN(mvm, "Got TE with unknown action\n");
@@ -220,6 +265,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
/*
+ * Handle A Aux ROC time event
+ */
+static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
+ struct iwl_time_event_notif *notif)
+{
+ struct iwl_mvm_time_event_data *te_data, *tmp;
+ bool aux_roc_te = false;
+
+ list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
+ if (le32_to_cpu(notif->unique_id) == te_data->uid) {
+ aux_roc_te = true;
+ break;
+ }
+ }
+ if (!aux_roc_te) /* Not a Aux ROC time event */
+ return -EINVAL;
+
+ if (!le32_to_cpu(notif->status)) {
+ IWL_DEBUG_TE(mvm,
+ "ERROR: Aux ROC Time Event %s notification failure\n",
+ (le32_to_cpu(notif->action) &
+ TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end");
+ return -EINVAL;
+ }
+
+ IWL_DEBUG_TE(mvm,
+ "Aux ROC time event notification - UID = 0x%x action %d\n",
+ le32_to_cpu(notif->unique_id),
+ le32_to_cpu(notif->action));
+
+ if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
+ /* End TE, notify mac80211 */
+ ieee80211_remain_on_channel_expired(mvm->hw);
+ iwl_mvm_roc_finished(mvm); /* flush aux queue */
+ list_del(&te_data->list); /* remove from list */
+ te_data->running = false;
+ te_data->vif = NULL;
+ te_data->uid = 0;
+ } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
+ set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
+ set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
+ te_data->running = true;
+ ieee80211_ready_on_channel(mvm->hw); /* Start TE */
+ } else {
+ IWL_DEBUG_TE(mvm,
+ "ERROR: Unknown Aux ROC Time Event (action = %d)\n",
+ le32_to_cpu(notif->action));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
* The Rx handler for time event notifications
*/
int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
@@ -235,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
le32_to_cpu(notif->action));
spin_lock_bh(&mvm->time_event_lock);
+ /* This time event is triggered for Aux ROC request */
+ if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif))
+ goto unlock;
+
list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
if (le32_to_cpu(notif->unique_id) == te_data->uid)
iwl_mvm_te_handle_notif(mvm, te_data, notif);
}
+unlock:
spin_unlock_bh(&mvm->time_event_lock);
return 0;
@@ -538,3 +642,33 @@ void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
iwl_mvm_roc_finished(mvm);
}
+
+int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ u32 duration, u32 apply_time)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
+ struct iwl_time_event_cmd time_cmd = {};
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (te_data->running) {
+ IWL_DEBUG_TE(mvm, "CS NOA is already scheduled\n");
+ return -EBUSY;
+ }
+
+ time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
+ time_cmd.id_and_color =
+ cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
+ time_cmd.id = cpu_to_le32(TE_P2P_GO_CSA_NOA);
+ time_cmd.apply_time = cpu_to_le32(apply_time);
+ time_cmd.max_frags = TE_V2_FRAG_NONE;
+ time_cmd.duration = cpu_to_le32(duration);
+ time_cmd.repeat = 1;
+ time_cmd.interval = cpu_to_le32(1);
+ time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
+ TE_V2_ABSENCE);
+
+ return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index 4a61c8c02372..2f48a90d4ad3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -214,4 +214,33 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void iwl_mvm_roc_done_wk(struct work_struct *wk);
+/**
+ * iwl_mvm_schedule_csa_noa - request NoA for channel switch
+ * @mvm: the mvm component
+ * @vif: the virtual interface for which the channel switch is issued
+ * @duration: the duration of the NoA in TU.
+ * @apply_time: NoA start time in GP2.
+ *
+ * This function is used to schedule NoA time event and is used to perform
+ * the channel switch flow.
+ */
+int iwl_mvm_schedule_csa_noa(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ u32 duration, u32 apply_time);
+
+/**
+ * iwl_mvm_te_scheduled - check if the fw received the TE cmd
+ * @te_data: the time event data that corresponds to that time event
+ *
+ * This function returns true iff this TE is added to the fw.
+ */
+static inline bool
+iwl_mvm_te_scheduled(struct iwl_mvm_time_event_data *te_data)
+{
+ if (!te_data)
+ return false;
+
+ return !!te_data->uid;
+}
+
#endif /* __time_event_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 868561512783..0464599c111e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
/* TODO: move parsing to NVM code */
calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
- ptat = calib[OTP_DTS_DIODE_DEVIATION];
- pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1];
- pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2];
+ ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
+ pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
+ pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
/* get the median: */
if (ptat > pa1) {
@@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
duration = tt->params->ct_kill_duration;
+ /* make sure the device is available for direct read/writes */
+ if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
+ goto reschedule;
+
iwl_trans_start_hw(mvm->trans);
temp = check_nic_temperature(mvm);
iwl_trans_stop_device(mvm->trans);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
+
if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
goto reschedule;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 3846a6c41eb1..dbc870713882 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -131,7 +131,6 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
!is_multicast_ether_addr(ieee80211_get_DA(hdr)))
tx_flags |= TX_CMD_FLG_PROT_REQUIRE;
- tx_cmd->driver_txop = 0;
tx_cmd->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted */
tx_cmd->len = cpu_to_le16((u16)skb->len);
@@ -205,7 +204,13 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant,
mvm->mgmt_last_antenna_idx);
- rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
+
+ if (info->band == IEEE80211_BAND_2GHZ &&
+ !iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
+ rate_flags = BIT(ANT_A) << RATE_MCS_ANT_POS;
+ else
+ rate_flags =
+ BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
/* Set CCK flag as needed */
if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
@@ -306,6 +311,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
return -1;
/*
+ * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
+ * in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
+ * queue. STATION (HS2.0) uses the auxiliary context of the FW,
+ * and hence needs to be sent on the aux queue
+ */
+ if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
+ info->control.vif->type == NL80211_IFTYPE_STATION)
+ IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
+
+ /*
* If the interface on which frame is sent is the P2P_DEVICE
* or an AP/GO interface use the broadcast station associated
* with it; otherwise use the AUX station.
@@ -717,18 +732,26 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
/* We can't free more than one frame at once on a shared queue */
WARN_ON(skb_freed > 1);
- /* If we have still frames from this STA nothing to do here */
+ /* If we have still frames for this STA nothing to do here */
if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
goto out;
if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) {
+
/*
- * If there are no pending frames for this STA, notify
- * mac80211 that this station can go to sleep in its
+ * If there are no pending frames for this STA and
+ * the tx to this station is not disabled, notify
+ * mac80211 that this station can now wake up in its
* STA table.
* If mvmsta is not NULL, sta is valid.
*/
- ieee80211_sta_block_awake(mvm->hw, sta, false);
+
+ spin_lock_bh(&mvmsta->lock);
+
+ if (!mvmsta->disable_tx)
+ ieee80211_sta_block_awake(mvm->hw, sta, false);
+
+ spin_unlock_bh(&mvmsta->lock);
}
if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index aa9fc77e8413..ac249da8a22b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -519,71 +519,6 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
iwl_mvm_dump_umac_error_log(mvm);
}
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm)
-{
- const struct fw_img *img;
- u32 ofs, sram_len;
- void *sram;
-
- if (!mvm->ucode_loaded || mvm->fw_error_sram || mvm->fw_error_dump)
- return;
-
- img = &mvm->fw->img[mvm->cur_ucode];
- ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
- sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
-
- sram = kzalloc(sram_len, GFP_ATOMIC);
- if (!sram)
- return;
-
- iwl_trans_read_mem_bytes(mvm->trans, ofs, sram, sram_len);
- mvm->fw_error_sram = sram;
- mvm->fw_error_sram_len = sram_len;
-}
-
-void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm)
-{
- int i, reg_val;
- unsigned long flags;
-
- if (!mvm->ucode_loaded || mvm->fw_error_rxf || mvm->fw_error_dump)
- return;
-
- /* reading buffer size */
- reg_val = iwl_trans_read_prph(mvm->trans, RXF_SIZE_ADDR);
- mvm->fw_error_rxf_len =
- (reg_val & RXF_SIZE_BYTE_CNT_MSK) >> RXF_SIZE_BYTE_CND_POS;
-
- /* the register holds the value divided by 128 */
- mvm->fw_error_rxf_len = mvm->fw_error_rxf_len << 7;
-
- if (!mvm->fw_error_rxf_len)
- return;
-
- mvm->fw_error_rxf = kzalloc(mvm->fw_error_rxf_len, GFP_ATOMIC);
- if (!mvm->fw_error_rxf) {
- mvm->fw_error_rxf_len = 0;
- return;
- }
-
- if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags)) {
- kfree(mvm->fw_error_rxf);
- mvm->fw_error_rxf = NULL;
- mvm->fw_error_rxf_len = 0;
- return;
- }
-
- for (i = 0; i < (mvm->fw_error_rxf_len / sizeof(u32)); i++) {
- iwl_trans_write_prph(mvm->trans, RXF_LD_FENCE_OFFSET_ADDR,
- i * sizeof(u32));
- mvm->fw_error_rxf[i] =
- iwl_trans_read_prph(mvm->trans, RXF_FIFO_RD_FENCE_ADDR);
- }
- iwl_trans_release_nic_access(mvm->trans, &flags);
-}
-#endif
-
/**
* iwl_mvm_send_lq_cmd() - Send link quality command
* @init: This command is sent as part of station initialization right
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 98950e45c7b0..f0e722ced080 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -78,7 +78,7 @@
.driver_data = (kernel_ulong_t)&(cfg)
/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+static const struct pci_device_id iwl_hw_card_ids[] = {
#if IS_ENABLED(CONFIG_IWLDVM)
{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 6c22b23a2845..78f72c34438a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -260,6 +260,9 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
* @wd_timeout: queue watchdog timeout (jiffies)
* @reg_lock: protect hw register access
* @cmd_in_flight: true when we have a host command in flight
+ * @fw_mon_phys: physical address of the buffer for the firmware monitor
+ * @fw_mon_page: points to the first page of the buffer for the firmware monitor
+ * @fw_mon_size: size of the buffer for the firmware monitor
*/
struct iwl_trans_pcie {
struct iwl_rxq rxq;
@@ -312,6 +315,10 @@ struct iwl_trans_pcie {
/*protect hw register */
spinlock_t reg_lock;
bool cmd_in_flight;
+
+ dma_addr_t fw_mon_phys;
+ struct page *fw_mon_page;
+ u32 fw_mon_size;
};
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 788085bc65d7..06e04aaf61ee 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -67,6 +67,7 @@
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
+#include <linux/vmalloc.h>
#include "iwl-drv.h"
#include "iwl-trans.h"
@@ -76,6 +77,68 @@
#include "iwl-fw-error-dump.h"
#include "internal.h"
+static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ if (!trans_pcie->fw_mon_page)
+ return;
+
+ dma_unmap_page(trans->dev, trans_pcie->fw_mon_phys,
+ trans_pcie->fw_mon_size, DMA_FROM_DEVICE);
+ __free_pages(trans_pcie->fw_mon_page,
+ get_order(trans_pcie->fw_mon_size));
+ trans_pcie->fw_mon_page = NULL;
+ trans_pcie->fw_mon_phys = 0;
+ trans_pcie->fw_mon_size = 0;
+}
+
+static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct page *page;
+ dma_addr_t phys;
+ u32 size;
+ u8 power;
+
+ if (trans_pcie->fw_mon_page) {
+ dma_sync_single_for_device(trans->dev, trans_pcie->fw_mon_phys,
+ trans_pcie->fw_mon_size,
+ DMA_FROM_DEVICE);
+ return;
+ }
+
+ phys = 0;
+ for (power = 26; power >= 11; power--) {
+ int order;
+
+ size = BIT(power);
+ order = get_order(size);
+ page = alloc_pages(__GFP_COMP | __GFP_NOWARN | __GFP_ZERO,
+ order);
+ if (!page)
+ continue;
+
+ phys = dma_map_page(trans->dev, page, 0, PAGE_SIZE << order,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(trans->dev, phys)) {
+ __free_pages(page, order);
+ continue;
+ }
+ IWL_INFO(trans,
+ "Allocated 0x%08x bytes (order %d) for firmware monitor.\n",
+ size, order);
+ break;
+ }
+
+ if (!page)
+ return;
+
+ trans_pcie->fw_mon_page = page;
+ trans_pcie->fw_mon_phys = phys;
+ trans_pcie->fw_mon_size = size;
+}
+
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
{
iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG,
@@ -675,6 +738,7 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
const struct fw_img *image)
{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
int ret = 0;
int first_ucode_section;
@@ -733,6 +797,20 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
return ret;
}
+ /* supported for 7000 only for the moment */
+ if (iwlwifi_mod_params.fw_monitor &&
+ trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ iwl_pcie_alloc_fw_monitor(trans);
+
+ if (trans_pcie->fw_mon_size) {
+ iwl_write_prph(trans, MON_BUFF_BASE_ADDR,
+ trans_pcie->fw_mon_phys >> 4);
+ iwl_write_prph(trans, MON_BUFF_END_ADDR,
+ (trans_pcie->fw_mon_phys +
+ trans_pcie->fw_mon_size) >> 4);
+ }
+ }
+
/* release CPU reset */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
@@ -1126,6 +1204,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
if (trans_pcie->napi.poll)
netif_napi_del(&trans_pcie->napi);
+ iwl_pcie_free_fw_monitor(trans);
+
kfree(trans);
}
@@ -1494,10 +1574,12 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
txq = &trans_pcie->txq[cnt];
q = &txq->q;
pos += scnprintf(buf + pos, bufsz - pos,
- "hwq %.2d: read=%u write=%u use=%d stop=%d\n",
+ "hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d%s\n",
cnt, q->read_ptr, q->write_ptr,
!!test_bit(cnt, trans_pcie->queue_used),
- !!test_bit(cnt, trans_pcie->queue_stopped));
+ !!test_bit(cnt, trans_pcie->queue_stopped),
+ txq->need_update,
+ (cnt == trans_pcie->cmd_queue ? " HCMD" : ""));
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
@@ -1519,6 +1601,10 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
rxq->read);
pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
rxq->write);
+ pos += scnprintf(buf + pos, bufsz - pos, "write_actual: %u\n",
+ rxq->write_actual);
+ pos += scnprintf(buf + pos, bufsz - pos, "need_update: %d\n",
+ rxq->need_update);
pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
rxq->free_count);
if (rxq->rb_stts) {
@@ -1688,23 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
return cmdlen;
}
-static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
- void *buf, u32 buflen)
+static const struct {
+ u32 start, end;
+} iwl_prph_dump_addr[] = {
+ { .start = 0x00a00000, .end = 0x00a00000 },
+ { .start = 0x00a0000c, .end = 0x00a00024 },
+ { .start = 0x00a0002c, .end = 0x00a0003c },
+ { .start = 0x00a00410, .end = 0x00a00418 },
+ { .start = 0x00a00420, .end = 0x00a00420 },
+ { .start = 0x00a00428, .end = 0x00a00428 },
+ { .start = 0x00a00430, .end = 0x00a0043c },
+ { .start = 0x00a00444, .end = 0x00a00444 },
+ { .start = 0x00a004c0, .end = 0x00a004cc },
+ { .start = 0x00a004d8, .end = 0x00a004d8 },
+ { .start = 0x00a004e0, .end = 0x00a004f0 },
+ { .start = 0x00a00840, .end = 0x00a00840 },
+ { .start = 0x00a00850, .end = 0x00a00858 },
+ { .start = 0x00a01004, .end = 0x00a01008 },
+ { .start = 0x00a01010, .end = 0x00a01010 },
+ { .start = 0x00a01018, .end = 0x00a01018 },
+ { .start = 0x00a01024, .end = 0x00a01024 },
+ { .start = 0x00a0102c, .end = 0x00a01034 },
+ { .start = 0x00a0103c, .end = 0x00a01040 },
+ { .start = 0x00a01048, .end = 0x00a01094 },
+ { .start = 0x00a01c00, .end = 0x00a01c20 },
+ { .start = 0x00a01c58, .end = 0x00a01c58 },
+ { .start = 0x00a01c7c, .end = 0x00a01c7c },
+ { .start = 0x00a01c28, .end = 0x00a01c54 },
+ { .start = 0x00a01c5c, .end = 0x00a01c5c },
+ { .start = 0x00a01c84, .end = 0x00a01c84 },
+ { .start = 0x00a01ce0, .end = 0x00a01d0c },
+ { .start = 0x00a01d18, .end = 0x00a01d20 },
+ { .start = 0x00a01d2c, .end = 0x00a01d30 },
+ { .start = 0x00a01d40, .end = 0x00a01d5c },
+ { .start = 0x00a01d80, .end = 0x00a01d80 },
+ { .start = 0x00a01d98, .end = 0x00a01d98 },
+ { .start = 0x00a01dc0, .end = 0x00a01dfc },
+ { .start = 0x00a01e00, .end = 0x00a01e2c },
+ { .start = 0x00a01e40, .end = 0x00a01e60 },
+ { .start = 0x00a01e84, .end = 0x00a01e90 },
+ { .start = 0x00a01e9c, .end = 0x00a01ec4 },
+ { .start = 0x00a01ed0, .end = 0x00a01ed0 },
+ { .start = 0x00a01f00, .end = 0x00a01f14 },
+ { .start = 0x00a01f44, .end = 0x00a01f58 },
+ { .start = 0x00a01f80, .end = 0x00a01fa8 },
+ { .start = 0x00a01fb0, .end = 0x00a01fbc },
+ { .start = 0x00a01ff8, .end = 0x00a01ffc },
+ { .start = 0x00a02000, .end = 0x00a02048 },
+ { .start = 0x00a02068, .end = 0x00a020f0 },
+ { .start = 0x00a02100, .end = 0x00a02118 },
+ { .start = 0x00a02140, .end = 0x00a0214c },
+ { .start = 0x00a02168, .end = 0x00a0218c },
+ { .start = 0x00a021c0, .end = 0x00a021c0 },
+ { .start = 0x00a02400, .end = 0x00a02410 },
+ { .start = 0x00a02418, .end = 0x00a02420 },
+ { .start = 0x00a02428, .end = 0x00a0242c },
+ { .start = 0x00a02434, .end = 0x00a02434 },
+ { .start = 0x00a02440, .end = 0x00a02460 },
+ { .start = 0x00a02468, .end = 0x00a024b0 },
+ { .start = 0x00a024c8, .end = 0x00a024cc },
+ { .start = 0x00a02500, .end = 0x00a02504 },
+ { .start = 0x00a0250c, .end = 0x00a02510 },
+ { .start = 0x00a02540, .end = 0x00a02554 },
+ { .start = 0x00a02580, .end = 0x00a025f4 },
+ { .start = 0x00a02600, .end = 0x00a0260c },
+ { .start = 0x00a02648, .end = 0x00a02650 },
+ { .start = 0x00a02680, .end = 0x00a02680 },
+ { .start = 0x00a026c0, .end = 0x00a026d0 },
+ { .start = 0x00a02700, .end = 0x00a0270c },
+ { .start = 0x00a02804, .end = 0x00a02804 },
+ { .start = 0x00a02818, .end = 0x00a0281c },
+ { .start = 0x00a02c00, .end = 0x00a02db4 },
+ { .start = 0x00a02df4, .end = 0x00a02fb0 },
+ { .start = 0x00a03000, .end = 0x00a03014 },
+ { .start = 0x00a0301c, .end = 0x00a0302c },
+ { .start = 0x00a03034, .end = 0x00a03038 },
+ { .start = 0x00a03040, .end = 0x00a03048 },
+ { .start = 0x00a03060, .end = 0x00a03068 },
+ { .start = 0x00a03070, .end = 0x00a03074 },
+ { .start = 0x00a0307c, .end = 0x00a0307c },
+ { .start = 0x00a03080, .end = 0x00a03084 },
+ { .start = 0x00a0308c, .end = 0x00a03090 },
+ { .start = 0x00a03098, .end = 0x00a03098 },
+ { .start = 0x00a030a0, .end = 0x00a030a0 },
+ { .start = 0x00a030a8, .end = 0x00a030b4 },
+ { .start = 0x00a030bc, .end = 0x00a030bc },
+ { .start = 0x00a030c0, .end = 0x00a0312c },
+ { .start = 0x00a03c00, .end = 0x00a03c5c },
+ { .start = 0x00a04400, .end = 0x00a04454 },
+ { .start = 0x00a04460, .end = 0x00a04474 },
+ { .start = 0x00a044c0, .end = 0x00a044ec },
+ { .start = 0x00a04500, .end = 0x00a04504 },
+ { .start = 0x00a04510, .end = 0x00a04538 },
+ { .start = 0x00a04540, .end = 0x00a04548 },
+ { .start = 0x00a04560, .end = 0x00a0457c },
+ { .start = 0x00a04590, .end = 0x00a04598 },
+ { .start = 0x00a045c0, .end = 0x00a045f4 },
+};
+
+static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
+ struct iwl_fw_error_dump_data **data)
+{
+ struct iwl_fw_error_dump_prph *prph;
+ unsigned long flags;
+ u32 prph_len = 0, i;
+
+ if (!iwl_trans_grab_nic_access(trans, false, &flags))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
+ /* The range includes both boundaries */
+ int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4;
+ int reg;
+ __le32 *val;
+
+ prph_len += sizeof(*data) + sizeof(*prph) +
+ num_bytes_in_chunk;
+
+ (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
+ (*data)->len = cpu_to_le32(sizeof(*prph) +
+ num_bytes_in_chunk);
+ prph = (void *)(*data)->data;
+ prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
+ val = (void *)prph->data;
+
+ for (reg = iwl_prph_dump_addr[i].start;
+ reg <= iwl_prph_dump_addr[i].end;
+ reg += 4)
+ *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
+ reg));
+ *data = iwl_fw_error_next_data(*data);
+ }
+
+ iwl_trans_release_nic_access(trans, &flags);
+
+ return prph_len;
+}
+
+#define IWL_CSR_TO_DUMP (0x250)
+
+static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans,
+ struct iwl_fw_error_dump_data **data)
+{
+ u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP;
+ __le32 *val;
+ int i;
+
+ (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
+ (*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP);
+ val = (void *)(*data)->data;
+
+ for (i = 0; i < IWL_CSR_TO_DUMP; i += 4)
+ *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
+
+ *data = iwl_fw_error_next_data(*data);
+
+ return csr_len;
+}
+
+static
+struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_fw_error_dump_data *data;
struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_fw_error_dump_txcmd *txcmd;
+ struct iwl_trans_dump_data *dump_data;
u32 len;
int i, ptr;
- if (!buf)
- return sizeof(*data) +
- cmdq->q.n_window * (sizeof(*txcmd) +
- TFD_MAX_PAYLOAD_SIZE);
+ /* transport dump header */
+ len = sizeof(*dump_data);
+
+ /* host commands */
+ len += sizeof(*data) +
+ cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
+
+ /* CSR registers */
+ len += sizeof(*data) + IWL_CSR_TO_DUMP;
+
+ /* PRPH registers */
+ for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
+ /* The range includes both boundaries */
+ int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
+ iwl_prph_dump_addr[i].start + 4;
+
+ len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
+ num_bytes_in_chunk;
+ }
+
+ /* FW monitor */
+ if (trans_pcie->fw_mon_page)
+ len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
+ trans_pcie->fw_mon_size;
+
+ dump_data = vzalloc(len);
+ if (!dump_data)
+ return NULL;
len = 0;
- data = buf;
+ data = (void *)dump_data->data;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
txcmd = (void *)data->data;
spin_lock_bh(&cmdq->lock);
@@ -1729,7 +1999,46 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
spin_unlock_bh(&cmdq->lock);
data->len = cpu_to_le32(len);
- return sizeof(*data) + len;
+ len += sizeof(*data);
+ data = iwl_fw_error_next_data(data);
+
+ len += iwl_trans_pcie_dump_prph(trans, &data);
+ len += iwl_trans_pcie_dump_csr(trans, &data);
+ /* data is already pointing to the next section */
+
+ if (trans_pcie->fw_mon_page) {
+ struct iwl_fw_error_dump_fw_mon *fw_mon_data;
+
+ data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
+ data->len = cpu_to_le32(trans_pcie->fw_mon_size +
+ sizeof(*fw_mon_data));
+ fw_mon_data = (void *)data->data;
+ fw_mon_data->fw_mon_wr_ptr =
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_WRPTR));
+ fw_mon_data->fw_mon_cycle_cnt =
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_CYCLE_CNT));
+ fw_mon_data->fw_mon_base_ptr =
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_BASE_ADDR));
+
+ /*
+ * The firmware is now asserted, it won't write anything to
+ * the buffer. CPU can take ownership to fetch the data.
+ * The buffer will be handed back to the device before the
+ * firmware will be restarted.
+ */
+ dma_sync_single_for_cpu(trans->dev, trans_pcie->fw_mon_phys,
+ trans_pcie->fw_mon_size,
+ DMA_FROM_DEVICE);
+ memcpy(fw_mon_data->data, page_address(trans_pcie->fw_mon_page),
+ trans_pcie->fw_mon_size);
+
+ len += sizeof(*data) + sizeof(*fw_mon_data) +
+ trans_pcie->fw_mon_size;
+ }
+
+ dump_data->len = len;
+
+ return dump_data;
}
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
@@ -1870,6 +2179,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
+ /*
+ * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have
+ * changed, and now the revision step also includes bit 0-1 (no more
+ * "dash" value). To keep hw_rev backwards compatible - we'll store it
+ * in the old format.
+ */
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ trans->hw_rev = (trans->hw_rev & 0xfff0) |
+ ((trans->hw_rev << 2) & 0xc);
+
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
"PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device);
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 038940afbdc5..6acccb19c4f3 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1438,6 +1438,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
trans_pcie->cmd_in_flight = false;
+ IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
idx = -EIO;
goto out;
}
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig
index 0485c9957575..e6268ceacbf1 100644
--- a/drivers/net/wireless/libertas/Kconfig
+++ b/drivers/net/wireless/libertas/Kconfig
@@ -16,7 +16,7 @@ config LIBERTAS_USB
config LIBERTAS_CS
tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
- depends on LIBERTAS && PCMCIA
+ depends on LIBERTAS && PCMCIA && HAS_IOPORT_MAP
---help---
A driver for Marvell Libertas 8385 CompactFlash devices.
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index aaa297315c47..0387a5b380c8 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1111,6 +1111,7 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on)
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
+ cmd.control = 0;
/* Only v8 and below support setting the preamble */
if (priv->fwrelease < 0x09000000) {
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 0c02f0483d1f..569b64ecc607 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -981,7 +981,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
goto err_wdev;
}
- dev = alloc_netdev(0, "wlan%d", ether_setup);
+ dev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup);
if (!dev) {
dev_err(dmdev, "no memory for network device instance\n");
goto err_adapter;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 6fef746345bc..01a67f62696f 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -1000,7 +1000,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
goto done;
}
- mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+ mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup);
if (!mesh_dev) {
lbs_deb_mesh("init mshX device failed\n");
ret = -ENOMEM;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index a312c653d116..1326f6121835 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -685,11 +685,16 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
struct mac80211_hwsim_data *data = hw->priv;
u64 now = mac80211_hwsim_get_tsf(hw, vif);
u32 bcn_int = data->beacon_int;
- s64 delta = tsf - now;
+ u64 delta = abs64(tsf - now);
- data->tsf_offset += delta;
/* adjust after beaconing with new timestamp at old TBTT */
- data->bcn_delta = do_div(delta, bcn_int);
+ if (tsf > now) {
+ data->tsf_offset += delta;
+ data->bcn_delta = do_div(delta, bcn_int);
+ } else {
+ data->tsf_offset -= delta;
+ data->bcn_delta = -do_div(delta, bcn_int);
+ }
}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
@@ -781,6 +786,36 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
netif_rx(skb);
}
+struct mac80211_hwsim_addr_match_data {
+ u8 addr[ETH_ALEN];
+ bool ret;
+};
+
+static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_addr_match_data *md = data;
+
+ if (memcmp(mac, md->addr, ETH_ALEN) == 0)
+ md->ret = true;
+}
+
+static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
+ const u8 *addr)
+{
+ struct mac80211_hwsim_addr_match_data md = {
+ .ret = false,
+ };
+
+ memcpy(md.addr, addr, ETH_ALEN);
+
+ ieee80211_iterate_active_interfaces_atomic(data->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ mac80211_hwsim_addr_iter,
+ &md);
+
+ return md.ret;
+}
static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
struct sk_buff *skb)
@@ -798,8 +833,7 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
/* Allow unicast frames to own address if there is a pending
* PS-Poll */
if (data->ps_poll_pending &&
- memcmp(data->hw->wiphy->perm_addr, skb->data + 4,
- ETH_ALEN) == 0) {
+ mac80211_hwsim_addr_match(data, skb->data + 4)) {
data->ps_poll_pending = false;
return true;
}
@@ -809,39 +843,6 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
return true;
}
-
-struct mac80211_hwsim_addr_match_data {
- bool ret;
- const u8 *addr;
-};
-
-static void mac80211_hwsim_addr_iter(void *data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct mac80211_hwsim_addr_match_data *md = data;
- if (memcmp(mac, md->addr, ETH_ALEN) == 0)
- md->ret = true;
-}
-
-
-static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
- const u8 *addr)
-{
- struct mac80211_hwsim_addr_match_data md;
-
- if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0)
- return true;
-
- md.ret = false;
- md.addr = addr;
- ieee80211_iterate_active_interfaces_atomic(data->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- mac80211_hwsim_addr_iter,
- &md);
-
- return md.ret;
-}
-
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
struct sk_buff *my_skb,
int dst_portid)
@@ -1740,9 +1741,10 @@ static void hw_scan_work(struct work_struct *work)
static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
struct mac80211_hwsim_data *hwsim = hw->priv;
+ struct cfg80211_scan_request *req = &hw_req->req;
mutex_lock(&hwsim->mutex);
if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) {
@@ -2679,7 +2681,8 @@ static int __init init_mac80211_hwsim(void)
goto out_free_radios;
}
- hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
+ hwsim_mon = alloc_netdev(0, "hwsim%d", NET_NAME_UNKNOWN,
+ hwsim_mon_setup);
if (hwsim_mon == NULL) {
err = -ENOMEM;
goto out_free_radios;
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
index 706831df1fa2..59d23fb2365f 100644
--- a/drivers/net/wireless/mwifiex/11ac.c
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11ac
*
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h
index 0b02cb6cfcb4..1ca92c7a8a4a 100644
--- a/drivers/net/wireless/mwifiex/11ac.h
+++ b/drivers/net/wireless/mwifiex/11ac.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11ac
*
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c
index e76b0db4e3e6..2668e83afbb6 100644
--- a/drivers/net/wireless/mwifiex/11h.c
+++ b/drivers/net/wireless/mwifiex/11h.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11h
*
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index e1c2f67ae85e..62f5dbe602d3 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -541,7 +541,6 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
{
struct host_cmd_ds_11n_addba_req add_ba_req;
- struct mwifiex_sta_node *sta_ptr;
u32 tx_win_size = priv->add_ba_param.tx_win_size;
static u8 dialog_tok;
int ret;
@@ -553,6 +552,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
priv->adapter->is_hw_11ac_capable &&
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
+ struct mwifiex_sta_node *sta_ptr;
+
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
if (!sta_ptr) {
dev_warn(priv->adapter->dev,
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 0b73fa08f5d4..2ee268b632be 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index fe0f66f73507..8720a3d3c755 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n Aggregation
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h
index 892098d6a696..0cd2a3eb6c17 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.h
+++ b/drivers/net/wireless/mwifiex/11n_aggr.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n Aggregation
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 0c3571f830b0..06a2c215ef5e 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n RX Re-ordering
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -249,13 +249,22 @@ void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
* buffered in Rx reordering table.
*/
static int
-mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr)
+mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
{
+ struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
+ struct mwifiex_private *priv = ctx->priv;
+ unsigned long flags;
int i;
- for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i)
- if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
+ spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+ for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
+ if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+ flags);
return i;
+ }
+ }
+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
return -1;
}
@@ -274,7 +283,7 @@ mwifiex_flush_data(unsigned long context)
(struct reorder_tmr_cnxt *) context;
int start_win, seq_num;
- seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr);
+ seq_num = mwifiex_11n_find_last_seq_num(ctx);
if (seq_num < 0)
return;
@@ -729,9 +738,9 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
}
+ INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
- INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
mwifiex_reset_11n_rx_seq_num(priv);
}
@@ -749,10 +758,14 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
priv = adapter->priv[i];
if (!priv)
continue;
- if (list_empty(&priv->rx_reorder_tbl_ptr))
- continue;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
+ if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+ spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+ lock_flags);
+ continue;
+ }
+
list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
tbl->flags = flags;
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 0fc76e4a60f8..3a87bb0e3a62 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: 802.11n RX Re-ordering
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 2aa208ffbe23..9487d728ac20 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011, Marvell International Ltd.
+# Copyright (C) 2011-2014, Marvell International Ltd.
#
# This software file (the "File") is distributed by Marvell International
# Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README
index 3b55ce5690a5..31928caeeed2 100644
--- a/drivers/net/wireless/mwifiex/README
+++ b/drivers/net/wireless/mwifiex/README
@@ -1,4 +1,4 @@
-# Copyright (C) 2011, Marvell International Ltd.
+# Copyright (C) 2011-2014, Marvell International Ltd.
#
# This software file (the "File") is distributed by Marvell International
# Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -194,6 +194,36 @@ rdeeprom
Example:
echo "0 20" > rdeeprom : Read 20 bytes of EEPROM data from offset 0
+hscfg
+ This command is used to debug/simulate host sleep feature using
+ different configuration parameters.
+
+ Usage:
+ echo "<condition> [GPIO# [gap]]]" > hscfg
+ cat hscfg
+
+ where the parameters are,
+ <condition>: bit 0 = 1 -- broadcast data
+ bit 1 = 1 -- unicast data
+ bit 2 = 1 -- mac event
+ bit 3 = 1 -- multicast data
+ [GPIO#]: pin number of GPIO used to wakeup the host.
+ GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO
+ will be used instead).
+ [gap]: the gap in milliseconds between wakeup signal and
+ wakeup event or 0xff for special setting (host
+ acknowledge required) when GPIO is used to wakeup host.
+
+ Examples:
+ echo "-1" > hscfg : Cancel host sleep mode
+ echo "3" > hscfg : Broadcast and unicast data;
+ Use GPIO and gap set previously
+ echo "2 3" > hscfg : Unicast data and GPIO 3;
+ Use gap set previously
+ echo "2 1 160" > hscfg : Unicast data, GPIO 1 and gap 160 ms
+ echo "2 1 0xff" > hscfg : Unicast data, GPIO 1; Wait for host
+ to ack before sending wakeup event
+
getlog
This command is used to get the statistics available in the station.
Usage:
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index b511613bba2d..e2e6bf13c2d8 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: CFG80211
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -42,36 +42,6 @@ static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
.beacon_int_infra_match = true,
};
-static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
- .n_reg_rules = 7,
- .alpha2 = "99",
- .reg_rules = {
- /* Channel 1 - 11 */
- REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
- /* Channel 12 - 13 */
- REG_RULE(2467-10, 2472+10, 20, 3, 20,
- NL80211_RRF_NO_IR),
- /* Channel 14 */
- REG_RULE(2484-10, 2484+10, 20, 3, 20,
- NL80211_RRF_NO_IR |
- NL80211_RRF_NO_OFDM),
- /* Channel 36 - 48 */
- REG_RULE(5180-10, 5240+10, 40, 3, 20,
- NL80211_RRF_NO_IR),
- /* Channel 149 - 165 */
- REG_RULE(5745-10, 5825+10, 40, 3, 20,
- NL80211_RRF_NO_IR),
- /* Channel 52 - 64 */
- REG_RULE(5260-10, 5320+10, 40, 3, 30,
- NL80211_RRF_NO_IR |
- NL80211_RRF_DFS),
- /* Channel 100 - 140 */
- REG_RULE(5500-10, 5700+10, 40, 3, 30,
- NL80211_RRF_NO_IR |
- NL80211_RRF_DFS),
- }
-};
-
/*
* This function maps the nl802.11 channel type into driver channel type.
*
@@ -151,7 +121,6 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
u16 pkt_len;
u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
- struct timeval tv;
pkt_len = len + ETH_ALEN;
@@ -173,8 +142,7 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
len - sizeof(struct ieee80211_hdr_3addr));
skb->priority = LOW_PRIO_TID;
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
+ __net_timestamp(skb);
return 0;
}
@@ -1636,9 +1604,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
return -EINVAL;
}
- /* disconnect before try to associate */
- mwifiex_deauthenticate(priv, NULL);
-
/* As this is new association, clear locally stored
* keys and security related flags */
priv->sec_info.wpa_enabled = false;
@@ -1776,6 +1741,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}
+ if (priv->wdev && priv->wdev->current_bss) {
+ wiphy_warn(wiphy, "%s: already connected\n", dev->name);
+ return -EALREADY;
+ }
+
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
(char *) sme->ssid, sme->bssid);
@@ -2264,7 +2234,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
}
dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
- ether_setup, IEEE80211_NUM_ACS, 1);
+ NET_NAME_UNKNOWN, ether_setup,
+ IEEE80211_NUM_ACS, 1);
if (!dev) {
wiphy_err(wiphy, "no memory available for netdevice\n");
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2484,6 +2455,16 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
mef_entry->filter[filt_num].filt_type = TYPE_EQ;
if (filt_num)
mef_entry->filter[filt_num].filt_action = TYPE_OR;
+
+ filt_num++;
+ mef_entry->filter[filt_num].repeat = 16;
+ memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+ ETH_ALEN);
+ mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
+ ETH_ALEN;
+ mef_entry->filter[filt_num].offset = 56;
+ mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+ mef_entry->filter[filt_num].filt_action = TYPE_OR;
}
if (!mef_cfg.criteria)
@@ -2632,7 +2613,8 @@ static int
mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capability,
- const u8 *extra_ies, size_t extra_ies_len)
+ bool initiator, const u8 *extra_ies,
+ size_t extra_ies_len)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int ret;
@@ -2917,12 +2899,6 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
- wiphy->regulatory_flags |=
- REGULATORY_CUSTOM_REG |
- REGULATORY_STRICT_REG;
-
- wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
-
#ifdef CONFIG_PM
wiphy->wowlan = &mwifiex_wowlan_support;
#endif
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h
index c5848934f111..908367857d58 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.h
+++ b/drivers/net/wireless/mwifiex/cfg80211.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: CFG80211
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index 0ddec3d4b059..b8242eb2be6f 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: Channel, Frequence and Power
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index c161141f6c39..baf0aab63c04 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: commands and events
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -137,7 +137,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
struct host_cmd_ds_command *host_cmd;
uint16_t cmd_code;
uint16_t cmd_size;
- struct timeval tstamp;
unsigned long flags;
__le32 tmp;
@@ -198,10 +197,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
*/
skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
- do_gettimeofday(&tstamp);
- dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
- " seqno %#x\n",
- tstamp.tv_sec, tstamp.tv_usec, cmd_code,
+ dev_dbg(adapter->dev,
+ "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code,
le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
le16_to_cpu(host_cmd->seq_num));
@@ -283,6 +280,13 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
(adapter->seq_num, priv->bss_num,
priv->bss_type)));
+ dev_dbg(adapter->dev,
+ "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
+ le16_to_cpu(sleep_cfm_buf->command),
+ le16_to_cpu(sleep_cfm_buf->action),
+ le16_to_cpu(sleep_cfm_buf->size),
+ le16_to_cpu(sleep_cfm_buf->seq_num));
+
if (adapter->iface_type == MWIFIEX_USB) {
sleep_cfm_tmp =
dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm)
@@ -433,7 +437,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
struct sk_buff *skb = adapter->event_skb;
u32 eventcause = adapter->event_cause;
- struct timeval tstamp;
struct mwifiex_rxinfo *rx_info;
/* Save the last event to debug log */
@@ -458,11 +461,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
rx_info->bss_type = priv->bss_type;
}
- if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) {
- do_gettimeofday(&tstamp);
- dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n",
- tstamp.tv_sec, tstamp.tv_usec, eventcause);
- } else {
+ dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause);
+ if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) {
/* Handle PS_SLEEP/AWAKE events on STA */
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
if (!priv)
@@ -773,7 +773,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
uint16_t orig_cmdresp_no;
uint16_t cmdresp_no;
uint16_t cmdresp_result;
- struct timeval tstamp;
unsigned long flags;
/* Now we got response from FW, cancel the command timer */
@@ -831,11 +830,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
orig_cmdresp_no;
- do_gettimeofday(&tstamp);
- dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d,"
- " len %d, seqno 0x%x\n",
- tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result,
- le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
+ dev_dbg(adapter->dev,
+ "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+ orig_cmdresp_no, cmdresp_result,
+ le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
@@ -895,7 +893,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
struct mwifiex_adapter *adapter =
(struct mwifiex_adapter *) function_context;
struct cmd_ctrl_node *cmd_node;
- struct timeval tstamp;
adapter->is_cmd_timedout = 1;
if (!adapter->curr_cmd) {
@@ -908,10 +905,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
adapter->dbg.timeout_cmd_act =
adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
- do_gettimeofday(&tstamp);
dev_err(adapter->dev,
- "%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n",
- __func__, tstamp.tv_sec, tstamp.tv_usec,
+ "%s: Timeout cmd id = %#x, act = %#x\n", __func__,
adapter->dbg.timeout_cmd_id,
adapter->dbg.timeout_cmd_act);
@@ -961,6 +956,9 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
mwifiex_init_fw_complete(adapter);
+ if (adapter->if_ops.fw_dump)
+ adapter->if_ops.fw_dump(adapter);
+
if (adapter->if_ops.card_reset)
adapter->if_ops.card_reset(adapter);
}
@@ -1232,6 +1230,10 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
return;
}
+ dev_dbg(adapter->dev,
+ "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
+ command, result, le16_to_cpu(cmd->size), seq_num);
+
/* Get BSS number and corresponding priv */
priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),
HostCmd_GET_BSS_TYPE(seq_num));
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 7b419bbcd544..2713f7acd35e 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: debugfs
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -692,6 +692,97 @@ done:
return ret;
}
+/* Proc hscfg file write handler
+ * This function can be used to configure the host sleep parameters.
+ */
+static ssize_t
+mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct mwifiex_private *priv = (void *)file->private_data;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+ size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+ int ret, arg_num;
+ struct mwifiex_ds_hs_cfg hscfg;
+ int conditions = HS_CFG_COND_DEF;
+ u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
+
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, ubuf, buf_size)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
+
+ memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));
+
+ if (arg_num > 3) {
+ dev_err(priv->adapter->dev, "Too many arguments\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (arg_num >= 1 && arg_num < 3)
+ mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+ MWIFIEX_SYNC_CMD, &hscfg);
+
+ if (arg_num) {
+ if (conditions == HS_CFG_CANCEL) {
+ mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
+ ret = count;
+ goto done;
+ }
+ hscfg.conditions = conditions;
+ }
+ if (arg_num >= 2)
+ hscfg.gpio = gpio;
+ if (arg_num == 3)
+ hscfg.gap = gap;
+
+ hscfg.is_invoke_hostcmd = false;
+ mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
+ MWIFIEX_SYNC_CMD, &hscfg);
+
+ mwifiex_enable_hs(priv->adapter);
+ priv->adapter->hs_enabling = false;
+ ret = count;
+done:
+ free_page(addr);
+ return ret;
+}
+
+/* Proc hscfg file read handler
+ * This function can be used to read host sleep configuration
+ * parameters from driver.
+ */
+static ssize_t
+mwifiex_hscfg_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct mwifiex_private *priv = (void *)file->private_data;
+ unsigned long addr = get_zeroed_page(GFP_KERNEL);
+ char *buf = (char *)addr;
+ int pos, ret;
+ struct mwifiex_ds_hs_cfg hscfg;
+
+ if (!buf)
+ return -ENOMEM;
+
+ mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
+ MWIFIEX_SYNC_CMD, &hscfg);
+
+ pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions,
+ hscfg.gpio, hscfg.gap);
+
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+
+ free_page(addr);
+ return ret;
+}
#define MWIFIEX_DFS_ADD_FILE(name) do { \
if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \
@@ -725,6 +816,7 @@ MWIFIEX_DFS_FILE_READ_OPS(getlog);
MWIFIEX_DFS_FILE_READ_OPS(fw_dump);
MWIFIEX_DFS_FILE_OPS(regrdwr);
MWIFIEX_DFS_FILE_OPS(rdeeprom);
+MWIFIEX_DFS_FILE_OPS(hscfg);
/*
* This function creates the debug FS directory structure and the files.
@@ -747,6 +839,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
MWIFIEX_DFS_ADD_FILE(regrdwr);
MWIFIEX_DFS_ADD_FILE(rdeeprom);
MWIFIEX_DFS_ADD_FILE(fw_dump);
+ MWIFIEX_DFS_ADD_FILE(hscfg);
}
/*
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 38da6ff6f416..0e03fe39fc35 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: generic data structures and APIs
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c
index bfb39908b2c6..04e56b5fc535 100644
--- a/drivers/net/wireless/mwifiex/ethtool.c
+++ b/drivers/net/wireless/mwifiex/ethtool.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: ethtool
*
- * Copyright (C) 2013, Marvell International Ltd.
+ * Copyright (C) 2013-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -64,7 +64,90 @@ static int mwifiex_ethtool_set_wol(struct net_device *dev,
return 0;
}
+static int
+mwifiex_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct memory_type_mapping *entry;
+
+ if (!adapter->if_ops.fw_dump)
+ return -ENOTSUPP;
+
+ dump->flag = adapter->curr_mem_idx;
+ dump->version = 1;
+ if (adapter->curr_mem_idx != MWIFIEX_FW_DUMP_IDX) {
+ entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
+ dump->len = entry->mem_size;
+ } else {
+ dump->len = 0;
+ }
+
+ return 0;
+}
+
+static int
+mwifiex_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
+ void *buffer)
+{
+ u8 *p = buffer;
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct memory_type_mapping *entry;
+
+ if (!adapter->if_ops.fw_dump)
+ return -ENOTSUPP;
+
+ if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
+ dev_err(adapter->dev, "firmware dump in progress!!\n");
+ return -EBUSY;
+ }
+
+ entry = &adapter->mem_type_mapping_tbl[adapter->curr_mem_idx];
+
+ if (!entry->mem_ptr)
+ return -EFAULT;
+
+ memcpy(p, entry->mem_ptr, entry->mem_size);
+
+ entry->mem_size = 0;
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+
+ return 0;
+}
+
+static int mwifiex_set_dump(struct net_device *dev, struct ethtool_dump *val)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ if (!adapter->if_ops.fw_dump)
+ return -ENOTSUPP;
+
+ if (adapter->curr_mem_idx == MWIFIEX_FW_DUMP_IDX) {
+ dev_err(adapter->dev, "firmware dump in progress!!\n");
+ return -EBUSY;
+ }
+
+ if (val->flag == MWIFIEX_FW_DUMP_IDX) {
+ adapter->curr_mem_idx = val->flag;
+ adapter->if_ops.fw_dump(adapter);
+ return 0;
+ }
+
+ if (val->flag < 0 || val->flag >= adapter->num_mem_types)
+ return -EINVAL;
+
+ adapter->curr_mem_idx = val->flag;
+
+ return 0;
+}
+
const struct ethtool_ops mwifiex_ethtool_ops = {
.get_wol = mwifiex_ethtool_get_wol,
.set_wol = mwifiex_ethtool_set_wol,
+ .get_dump_flag = mwifiex_get_dump_flag,
+ .get_dump_data = mwifiex_get_dump_data,
+ .set_dump = mwifiex_set_dump,
};
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 3175dd04834b..49da2d53d294 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: Firmware specific macros & structures
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -713,7 +713,7 @@ struct mwifiex_ie_types_vendor_param_set {
u8 ie[MWIFIEX_MAX_VSIE_LEN];
};
-#define MWIFIEX_TDLS_IDLE_TIMEOUT 60
+#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC 60
struct mwifiex_ie_types_tdls_idle_timeout {
struct mwifiex_ie_types_header header;
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
index 3bf3d58bbc02..b933794758b7 100644
--- a/drivers/net/wireless/mwifiex/ie.c
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -2,7 +2,7 @@
* Marvell Wireless LAN device driver: management IE handling- setting and
* deleting IE.
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 4ecd0b208ac6..269a277d0a2e 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: HW/FW Initialization
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -382,6 +382,8 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
static void
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
+ int idx;
+
if (!adapter) {
pr_err("%s: adapter is NULL\n", __func__);
return;
@@ -396,7 +398,16 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
dev_dbg(adapter->dev, "info: free cmd buffer\n");
mwifiex_free_cmd_buffer(adapter);
- dev_dbg(adapter->dev, "info: free scan table\n");
+ for (idx = 0; idx < adapter->num_mem_types; idx++) {
+ struct memory_type_mapping *entry =
+ &adapter->mem_type_mapping_tbl[idx];
+
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+ }
if (adapter->sleep_cfm)
dev_kfree_skb_any(adapter->sleep_cfm);
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 1b576722671d..0847f3e07ab7 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: ioctl data structures & APIs
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 89dc62a467f4..8d6c25908b6d 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: association and ad-hoc start/join
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -949,7 +949,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
chan_tlv->chan_scan_param[0].radio_type |=
(IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
else if (adapter->sec_chan_offset ==
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+ IEEE80211_HT_PARAM_CHA_SEC_BELOW)
chan_tlv->chan_scan_param[0].radio_type |=
(IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
}
@@ -1288,8 +1288,6 @@ done:
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc)
{
- u8 current_bssid[ETH_ALEN];
-
/* Return error if the adapter is not STA role or table entry
* is not marked as infra.
*/
@@ -1304,10 +1302,6 @@ int mwifiex_associate(struct mwifiex_private *priv,
else
mwifiex_set_ba_params(priv);
- memcpy(&current_bssid,
- &priv->curr_bss_params.bss_descriptor.mac_address,
- sizeof(current_bssid));
-
/* Clear any past association response stored for application
retrieval */
priv->assoc_rsp_size = 0;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index e91cd0fa5ca8..dfa37eadc4db 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: major functions
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned long data)
struct mwifiex_private *priv = (struct mwifiex_private *)data;
struct mwifiex_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmd_node, *tmp_node;
+ spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
unsigned long flags;
if (adapter->surprise_removed)
@@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned long data)
* Abort scan operation by cancelling all pending scan
* commands
*/
- spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+ spin_lock_irqsave(scan_q_lock, flags);
list_for_each_entry_safe(cmd_node, tmp_node,
&adapter->scan_pending_q, list) {
list_del(&cmd_node->list);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
}
- spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+ spin_unlock_irqrestore(scan_q_lock, flags);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
@@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned long data)
*/
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
- spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+ spin_lock_irqsave(scan_q_lock, flags);
+
+ if (list_empty(&adapter->scan_pending_q)) {
+ spin_unlock_irqrestore(scan_q_lock, flags);
+ goto done;
+ }
+
cmd_node = list_first_entry(&adapter->scan_pending_q,
struct cmd_ctrl_node, list);
list_del(&cmd_node->list);
- spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
- flags);
+ spin_unlock_irqrestore(scan_q_lock, flags);
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);
@@ -609,7 +615,6 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct sk_buff *new_skb;
struct mwifiex_txinfo *tx_info;
- struct timeval tv;
dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
jiffies, priv->bss_type, priv->bss_num);
@@ -657,8 +662,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
* firmware for aggregate delay calculation for stats and
* MSDU lifetime expiry.
*/
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
+ __net_timestamp(skb);
mwifiex_queue_tx_pkt(priv, skb);
@@ -882,6 +886,8 @@ mwifiex_add_card(void *card, struct semaphore *sem,
goto err_kmalloc;
INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
+ if (adapter->if_ops.iface_work)
+ INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work);
/* Register the device. Fill up the private data structure with relevant
information from the card. */
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 1398afa84064..a2733b1e63f9 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: major data structures and prototypes
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -30,6 +30,7 @@
#include <linux/etherdevice.h>
#include <net/sock.h>
#include <net/lib80211.h>
+#include <linux/vmalloc.h>
#include <linux/firmware.h>
#include <linux/ctype.h>
#include <linux/of.h>
@@ -410,6 +411,29 @@ struct mwifiex_roc_cfg {
struct ieee80211_channel chan;
};
+#define MWIFIEX_FW_DUMP_IDX 0xff
+#define FW_DUMP_MAX_NAME_LEN 8
+#define FW_DUMP_HOST_READY 0xEE
+#define FW_DUMP_DONE 0xFF
+
+struct memory_type_mapping {
+ u8 mem_name[FW_DUMP_MAX_NAME_LEN];
+ u8 *mem_ptr;
+ u32 mem_size;
+ u8 done_flag;
+};
+
+enum rdwr_status {
+ RDWR_STATUS_SUCCESS = 0,
+ RDWR_STATUS_FAILURE = 1,
+ RDWR_STATUS_DONE = 2
+};
+
+enum mwifiex_iface_work_flags {
+ MWIFIEX_IFACE_WORK_FW_DUMP,
+ MWIFIEX_IFACE_WORK_CARD_RESET,
+};
+
struct mwifiex_adapter;
struct mwifiex_private;
@@ -674,6 +698,7 @@ struct mwifiex_if_ops {
void (*card_reset) (struct mwifiex_adapter *);
void (*fw_dump)(struct mwifiex_adapter *);
int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
+ void (*iface_work)(struct work_struct *work);
};
struct mwifiex_adapter {
@@ -809,6 +834,11 @@ struct mwifiex_adapter {
bool ext_scan;
u8 fw_api_ver;
u8 fw_key_api_major_ver, fw_key_api_minor_ver;
+ struct work_struct iface_work;
+ unsigned long iface_work_flags;
+ struct memory_type_mapping *mem_type_mapping_tbl;
+ u8 num_mem_types;
+ u8 curr_mem_idx;
};
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -890,6 +920,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
void mwifiex_hs_activated_event(struct mwifiex_private *priv,
u8 activated);
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+ int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg);
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
int mwifiex_process_rx_packet(struct mwifiex_private *priv,
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 2cc9b6fca490..ff0545888dd0 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: PCIE specific handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -37,6 +37,13 @@ static struct mwifiex_if_ops pcie_ops;
static struct semaphore add_remove_card_sem;
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+ {"ITCM", NULL, 0, 0xF0},
+ {"DTCM", NULL, 0, 0xF1},
+ {"SQRAM", NULL, 0, 0xF2},
+ {"IRAM", NULL, 0, 0xF3},
+};
+
static int
mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
size_t size, int flags)
@@ -192,6 +199,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
card->pcie.reg = data->reg;
card->pcie.blksz_fw_dl = data->blksz_fw_dl;
card->pcie.tx_buf_size = data->tx_buf_size;
+ card->pcie.supports_fw_dump = data->supports_fw_dump;
}
if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
@@ -221,6 +229,8 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
if (!adapter || !adapter->priv_num)
return;
+ cancel_work_sync(&adapter->iface_work);
+
if (user_rmmod) {
#ifdef CONFIG_PM_SLEEP
if (adapter->is_suspended)
@@ -247,7 +257,7 @@ static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
return;
}
-static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
+static const struct pci_device_id mwifiex_ids[] = {
{
PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -307,6 +317,17 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
return 0;
}
+/* This function reads u8 data from PCIE card register. */
+static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
+ int reg, u8 *data)
+{
+ struct pcie_service_card *card = adapter->card;
+
+ *data = ioread8(card->pci_mmap1 + reg);
+
+ return 0;
+}
+
/*
* This function adds delay loop to ensure FW is awake before proceeding.
*/
@@ -2173,6 +2194,168 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
return 0;
}
+/* This function read/write firmware */
+static enum rdwr_status
+mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
+{
+ int ret, tries;
+ u8 ctrl_data;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+ ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
+ if (ret) {
+ dev_err(adapter->dev, "PCIE write err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
+ if (ctrl_data == FW_DUMP_DONE)
+ return RDWR_STATUS_SUCCESS;
+ if (doneflag && ctrl_data == doneflag)
+ return RDWR_STATUS_DONE;
+ if (ctrl_data != FW_DUMP_HOST_READY) {
+ dev_info(adapter->dev,
+ "The ctrl reg was changed, re-try again!\n");
+ mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
+ FW_DUMP_HOST_READY);
+ if (ret) {
+ dev_err(adapter->dev, "PCIE write err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+ }
+ usleep_range(100, 200);
+ }
+
+ dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+ return RDWR_STATUS_FAILURE;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
+ unsigned int reg, reg_start, reg_end;
+ u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+ enum rdwr_status stat;
+ u32 memory_size;
+ static char *env[] = { "DRIVER=mwifiex_pcie", "EVENT=fw_dump", NULL };
+
+ if (!card->pcie.supports_fw_dump)
+ return;
+
+ for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+ struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+ }
+
+ dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+
+ /* Read the number of the memories which will dump */
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ reg = creg->fw_dump_start;
+ mwifiex_read_reg_byte(adapter, reg, &dump_num);
+
+ /* Read the length of every memory which will dump */
+ for (idx = 0; idx < dump_num; idx++) {
+ struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ memory_size = 0;
+ reg = creg->fw_dump_start;
+ for (i = 0; i < 4; i++) {
+ mwifiex_read_reg_byte(adapter, reg, &read_reg);
+ memory_size |= (read_reg << (i * 8));
+ reg++;
+ }
+
+ if (memory_size == 0) {
+ dev_info(adapter->dev, "Firmware dump Finished!\n");
+ break;
+ }
+
+ dev_info(adapter->dev,
+ "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+ entry->mem_ptr = vmalloc(memory_size + 1);
+ entry->mem_size = memory_size;
+ if (!entry->mem_ptr) {
+ dev_err(adapter->dev,
+ "Vmalloc %s failed\n", entry->mem_name);
+ goto done;
+ }
+ dbg_ptr = entry->mem_ptr;
+ end_ptr = dbg_ptr + memory_size;
+
+ doneflag = entry->done_flag;
+ dev_info(adapter->dev, "Start %s output, please wait...\n",
+ entry->mem_name);
+
+ do {
+ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
+ if (RDWR_STATUS_FAILURE == stat)
+ goto done;
+
+ reg_start = creg->fw_dump_start;
+ reg_end = creg->fw_dump_end;
+ for (reg = reg_start; reg <= reg_end; reg++) {
+ mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
+ if (dbg_ptr < end_ptr)
+ dbg_ptr++;
+ else
+ dev_err(adapter->dev,
+ "Allocated buf not enough\n");
+ }
+
+ if (stat != RDWR_STATUS_DONE)
+ continue;
+
+ dev_info(adapter->dev, "%s done: size=0x%tx\n",
+ entry->mem_name, dbg_ptr - entry->mem_ptr);
+ break;
+ } while (true);
+ }
+ dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
+
+ kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+
+done:
+ adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_pcie_work(struct work_struct *work)
+{
+ struct mwifiex_adapter *adapter =
+ container_of(work, struct mwifiex_adapter, iface_work);
+
+ if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+ &adapter->iface_work_flags))
+ mwifiex_pcie_fw_dump_work(adapter);
+}
+
+/* This function dumps FW information */
+static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
+{
+ if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags))
+ return;
+
+ set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags);
+
+ schedule_work(&adapter->iface_work);
+}
+
/*
* This function initializes the PCI-E host memory space, WCB rings, etc.
*
@@ -2342,6 +2525,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
adapter->dev = &pdev->dev;
adapter->tx_buf_size = card->pcie.tx_buf_size;
+ adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+ adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
strcpy(adapter->fw_name, card->pcie.firmware);
return 0;
@@ -2394,6 +2579,8 @@ static struct mwifiex_if_ops pcie_ops = {
.cleanup_mpa_buf = NULL,
.init_fw_port = mwifiex_pcie_init_fw_port,
.clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
+ .fw_dump = mwifiex_pcie_fw_dump,
+ .iface_work = mwifiex_pcie_work,
};
/*
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
index e8ec561f8a64..a1a8fd3bc1be 100644
--- a/drivers/net/wireless/mwifiex/pcie.h
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -3,7 +3,7 @@
* @brief This file contains definitions for PCI-E interface.
* driver.
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -129,6 +129,9 @@ struct mwifiex_pcie_card_reg {
u32 ring_tx_start_ptr;
u8 pfu_enabled;
u8 sleep_cookie;
+ u16 fw_dump_ctrl;
+ u16 fw_dump_start;
+ u16 fw_dump_end;
};
static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
@@ -191,6 +194,9 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
.ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
.pfu_enabled = 1,
.sleep_cookie = 0,
+ .fw_dump_ctrl = 0xcf4,
+ .fw_dump_start = 0xcf8,
+ .fw_dump_end = 0xcff
};
struct mwifiex_pcie_device {
@@ -198,6 +204,7 @@ struct mwifiex_pcie_device {
const struct mwifiex_pcie_card_reg *reg;
u16 blksz_fw_dl;
u16 tx_buf_size;
+ bool supports_fw_dump;
};
static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
@@ -205,6 +212,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
.reg = &mwifiex_reg_8766,
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
+ .supports_fw_dump = false,
};
static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
@@ -212,6 +220,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
.reg = &mwifiex_reg_8897,
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
+ .supports_fw_dump = true,
};
struct mwifiex_evt_buf_desc {
@@ -322,4 +331,5 @@ mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
return 0;
}
+
#endif /* _MWIFIEX_PCIE_H */
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 45c5b3450cf5..dee717a19ddb 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: scan ioctl and command handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 4ce3d7b33991..1770fa3fc1e6 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: SDIO specific handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -50,6 +50,24 @@ static struct mwifiex_if_ops sdio_ops;
static struct semaphore add_remove_card_sem;
+static struct memory_type_mapping mem_type_mapping_tbl[] = {
+ {"ITCM", NULL, 0, 0xF0},
+ {"DTCM", NULL, 0, 0xF1},
+ {"SQRAM", NULL, 0, 0xF2},
+ {"APU", NULL, 0, 0xF3},
+ {"CIU", NULL, 0, 0xF4},
+ {"ICU", NULL, 0, 0xF5},
+ {"MAC", NULL, 0, 0xF6},
+ {"EXT7", NULL, 0, 0xF7},
+ {"EXT8", NULL, 0, 0xF8},
+ {"EXT9", NULL, 0, 0xF9},
+ {"EXT10", NULL, 0, 0xFA},
+ {"EXT11", NULL, 0, 0xFB},
+ {"EXT12", NULL, 0, 0xFC},
+ {"EXT13", NULL, 0, 0xFD},
+ {"EXTLAST", NULL, 0, 0xFE},
+};
+
/*
* SDIO probe.
*
@@ -87,6 +105,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
card->tx_buf_size = data->tx_buf_size;
card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
+ card->supports_fw_dump = data->supports_fw_dump;
}
sdio_claim_host(func);
@@ -179,6 +198,8 @@ mwifiex_sdio_remove(struct sdio_func *func)
if (!adapter || !adapter->priv_num)
return;
+ cancel_work_sync(&adapter->iface_work);
+
if (user_rmmod) {
if (adapter->is_suspended)
mwifiex_sdio_resume(adapter->dev);
@@ -1777,6 +1798,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
adapter->dev = &func->dev;
strcpy(adapter->fw_name, card->firmware);
+ adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
+ adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
return 0;
}
@@ -1914,10 +1937,10 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port)
port, card->mp_data_port_mask);
}
-static struct mmc_host *reset_host;
-static void sdio_card_reset_worker(struct work_struct *work)
+static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter)
{
- struct mmc_host *target = reset_host;
+ struct sdio_mmc_card *card = adapter->card;
+ struct mmc_host *target = card->func->card->host;
/* The actual reset operation must be run outside of driver thread.
* This is because mmc_remove_host() will cause the device to be
@@ -1931,17 +1954,210 @@ static void sdio_card_reset_worker(struct work_struct *work)
mmc_remove_host(target);
/* 20ms delay is based on experiment with sdhci controller */
mdelay(20);
+ target->rescan_entered = 0; /* rescan non-removable cards */
mmc_add_host(target);
}
-static DECLARE_WORK(card_reset_work, sdio_card_reset_worker);
+
+/* This function read/write firmware */
+static enum
+rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter,
+ u8 doneflag)
+{
+ struct sdio_mmc_card *card = adapter->card;
+ int ret, tries;
+ u8 ctrl_data = 0;
+
+ sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
+ &ret);
+ if (ret) {
+ dev_err(adapter->dev, "SDIO Write ERR\n");
+ return RDWR_STATUS_FAILURE;
+ }
+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
+ ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
+ &ret);
+ if (ret) {
+ dev_err(adapter->dev, "SDIO read err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+ if (ctrl_data == FW_DUMP_DONE)
+ break;
+ if (doneflag && ctrl_data == doneflag)
+ return RDWR_STATUS_DONE;
+ if (ctrl_data != FW_DUMP_HOST_READY) {
+ dev_info(adapter->dev,
+ "The ctrl reg was changed, re-try again!\n");
+ sdio_writeb(card->func, FW_DUMP_HOST_READY,
+ card->reg->fw_dump_ctrl, &ret);
+ if (ret) {
+ dev_err(adapter->dev, "SDIO write err\n");
+ return RDWR_STATUS_FAILURE;
+ }
+ }
+ usleep_range(100, 200);
+ }
+ if (ctrl_data == FW_DUMP_HOST_READY) {
+ dev_err(adapter->dev, "Fail to pull ctrl_data\n");
+ return RDWR_STATUS_FAILURE;
+ }
+
+ return RDWR_STATUS_SUCCESS;
+}
+
+/* This function dump firmware memory to file */
+static void mwifiex_sdio_fw_dump_work(struct work_struct *work)
+{
+ struct mwifiex_adapter *adapter =
+ container_of(work, struct mwifiex_adapter, iface_work);
+ struct sdio_mmc_card *card = adapter->card;
+ int ret = 0;
+ unsigned int reg, reg_start, reg_end;
+ u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
+ enum rdwr_status stat;
+ u32 memory_size;
+ static char *env[] = { "DRIVER=mwifiex_sdio", "EVENT=fw_dump", NULL };
+
+ if (!card->supports_fw_dump)
+ return;
+
+ for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
+ struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+ if (entry->mem_ptr) {
+ vfree(entry->mem_ptr);
+ entry->mem_ptr = NULL;
+ }
+ entry->mem_size = 0;
+ }
+
+ mwifiex_pm_wakeup_card(adapter);
+ sdio_claim_host(card->func);
+
+ dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
+
+ stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ reg = card->reg->fw_dump_start;
+ /* Read the number of the memories which will dump */
+ dump_num = sdio_readb(card->func, reg, &ret);
+ if (ret) {
+ dev_err(adapter->dev, "SDIO read memory length err\n");
+ goto done;
+ }
+
+ /* Read the length of every memory which will dump */
+ for (idx = 0; idx < dump_num; idx++) {
+ struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
+
+ stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ memory_size = 0;
+ reg = card->reg->fw_dump_start;
+ for (i = 0; i < 4; i++) {
+ read_reg = sdio_readb(card->func, reg, &ret);
+ if (ret) {
+ dev_err(adapter->dev, "SDIO read err\n");
+ goto done;
+ }
+ memory_size |= (read_reg << i*8);
+ reg++;
+ }
+
+ if (memory_size == 0) {
+ dev_info(adapter->dev, "Firmware dump Finished!\n");
+ break;
+ }
+
+ dev_info(adapter->dev,
+ "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
+ entry->mem_ptr = vmalloc(memory_size + 1);
+ entry->mem_size = memory_size;
+ if (!entry->mem_ptr) {
+ dev_err(adapter->dev, "Vmalloc %s failed\n",
+ entry->mem_name);
+ goto done;
+ }
+ dbg_ptr = entry->mem_ptr;
+ end_ptr = dbg_ptr + memory_size;
+
+ doneflag = entry->done_flag;
+ dev_info(adapter->dev, "Start %s output, please wait...\n",
+ entry->mem_name);
+
+ do {
+ stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag);
+ if (stat == RDWR_STATUS_FAILURE)
+ goto done;
+
+ reg_start = card->reg->fw_dump_start;
+ reg_end = card->reg->fw_dump_end;
+ for (reg = reg_start; reg <= reg_end; reg++) {
+ *dbg_ptr = sdio_readb(card->func, reg, &ret);
+ if (ret) {
+ dev_err(adapter->dev,
+ "SDIO read err\n");
+ goto done;
+ }
+ if (dbg_ptr < end_ptr)
+ dbg_ptr++;
+ else
+ dev_err(adapter->dev,
+ "Allocated buf not enough\n");
+ }
+
+ if (stat != RDWR_STATUS_DONE)
+ continue;
+
+ dev_info(adapter->dev, "%s done: size=0x%tx\n",
+ entry->mem_name, dbg_ptr - entry->mem_ptr);
+ break;
+ } while (1);
+ }
+ dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
+
+ kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);
+
+done:
+ sdio_release_host(card->func);
+ adapter->curr_mem_idx = 0;
+}
+
+static void mwifiex_sdio_work(struct work_struct *work)
+{
+ struct mwifiex_adapter *adapter =
+ container_of(work, struct mwifiex_adapter, iface_work);
+
+ if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
+ &adapter->iface_work_flags))
+ mwifiex_sdio_card_reset_work(adapter);
+ if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP,
+ &adapter->iface_work_flags))
+ mwifiex_sdio_fw_dump_work(work);
+}
/* This function resets the card */
static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter)
{
- struct sdio_mmc_card *card = adapter->card;
+ if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags))
+ return;
+
+ set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags);
+
+ schedule_work(&adapter->iface_work);
+}
+
+/* This function dumps FW information */
+static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter)
+{
+ if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags))
+ return;
- reset_host = card->func->card->host;
- schedule_work(&card_reset_work);
+ set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags);
+ schedule_work(&adapter->iface_work);
}
static struct mwifiex_if_ops sdio_ops = {
@@ -1964,6 +2180,8 @@ static struct mwifiex_if_ops sdio_ops = {
.cmdrsp_complete = mwifiex_sdio_cmdrsp_complete,
.event_complete = mwifiex_sdio_event_complete,
.card_reset = mwifiex_sdio_card_reset,
+ .iface_work = mwifiex_sdio_work,
+ .fw_dump = mwifiex_sdio_fw_dump,
};
/*
@@ -2001,7 +2219,6 @@ mwifiex_sdio_cleanup_module(void)
/* Set the flag as user is removing this module. */
user_rmmod = 1;
- cancel_work_sync(&card_reset_work);
sdio_unregister_driver(&mwifiex_sdio);
}
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 6eea30b43ed7..6b8835ec88f1 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: SDIO specific definitions
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -219,6 +219,9 @@ struct mwifiex_sdio_card_reg {
u8 rd_len_p0_l;
u8 rd_len_p0_u;
u8 card_misc_cfg_reg;
+ u8 fw_dump_ctrl;
+ u8 fw_dump_start;
+ u8 fw_dump_end;
};
struct sdio_mmc_card {
@@ -231,6 +234,7 @@ struct sdio_mmc_card {
u8 mp_agg_pkt_limit;
bool supports_sdio_new_mode;
bool has_control_mask;
+ bool supports_fw_dump;
u16 tx_buf_size;
u32 mp_tx_agg_buf_size;
u32 mp_rx_agg_buf_size;
@@ -257,6 +261,7 @@ struct mwifiex_sdio_device {
u8 mp_agg_pkt_limit;
bool supports_sdio_new_mode;
bool has_control_mask;
+ bool supports_fw_dump;
u16 tx_buf_size;
u32 mp_tx_agg_buf_size;
u32 mp_rx_agg_buf_size;
@@ -307,6 +312,9 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = {
.rd_len_p0_l = 0x0c,
.rd_len_p0_u = 0x0d,
.card_misc_cfg_reg = 0xcc,
+ .fw_dump_ctrl = 0xe2,
+ .fw_dump_start = 0xe3,
+ .fw_dump_end = 0xea,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
@@ -319,6 +327,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = {
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+ .supports_fw_dump = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
@@ -331,6 +340,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+ .supports_fw_dump = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
@@ -343,6 +353,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K,
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
+ .supports_fw_dump = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
@@ -355,6 +366,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
.tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K,
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
+ .supports_fw_dump = true,
};
/*
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 88202ce0c139..733de92a4c61 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: station command handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -1647,7 +1647,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
timeout = (void *)(pos + config_len);
timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
timeout->header.len = cpu_to_le16(sizeof(timeout->value));
- timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT);
+ timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC);
config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
break;
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 577f2979ed8f..08b78baeb846 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: station command response handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -908,7 +908,7 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
break;
default:
dev_err(priv->adapter->dev,
- "Unknown TDLS command action respnse %d", action);
+ "Unknown TDLS command action response %d", action);
return -1;
}
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index f6395ef11a72..f1c240eca0cd 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: station event handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 536c14aa71f3..caae9738100a 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: functions for station ioctl
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -26,7 +26,7 @@
#include "11n.h"
#include "cfg80211.h"
-static int disconnect_on_suspend = 1;
+static int disconnect_on_suspend;
module_param(disconnect_on_suspend, int, 0644);
/*
@@ -283,10 +283,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
u8 config_bands;
- ret = mwifiex_deauthenticate(priv, NULL);
- if (ret)
- goto done;
-
if (!bss_desc)
return -1;
@@ -345,12 +341,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
goto done;
}
- /* Exit Adhoc mode first */
- dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
- ret = mwifiex_deauthenticate(priv, NULL);
- if (ret)
- goto done;
-
priv->adhoc_is_link_sensed = false;
ret = mwifiex_check_network_compatibility(priv, bss_desc);
@@ -389,8 +379,8 @@ done:
* This function prepares the correct firmware command and
* issues it.
*/
-static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
- int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
+int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
+ int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg)
{
struct mwifiex_adapter *adapter = priv->adapter;
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 8b639d7fe6df..9ceb1dbe34c5 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: station RX data handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 70eb863c7249..dab7b33c54be 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: station TX data handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 0e88364e0c67..4c5fd953893d 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -530,7 +530,6 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
{
struct sk_buff *skb;
struct mwifiex_txinfo *tx_info;
- struct timeval tv;
int ret;
u16 skb_len;
@@ -609,8 +608,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
tx_info->bss_num = priv->bss_num;
tx_info->bss_type = priv->bss_type;
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
+ __net_timestamp(skb);
mwifiex_queue_tx_pkt(priv, skb);
return 0;
@@ -703,7 +701,6 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
{
struct sk_buff *skb;
struct mwifiex_txinfo *tx_info;
- struct timeval tv;
u8 *pos;
u32 pkt_type, tx_control;
u16 pkt_len, skb_len;
@@ -769,8 +766,7 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
sizeof(pkt_len));
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
+ __net_timestamp(skb);
mwifiex_queue_tx_pkt(priv, skb);
return 0;
@@ -785,6 +781,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
struct mwifiex_sta_node *sta_ptr;
u8 *peer, *pos, *end;
u8 i, action, basic;
+ __le16 cap = 0;
int ie_len = 0;
if (len < (sizeof(struct ethhdr) + 3))
@@ -796,18 +793,9 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
peer = buf + ETH_ALEN;
action = *(buf + sizeof(struct ethhdr) + 2);
-
- /* just handle TDLS setup request/response/confirm */
- if (action > WLAN_TDLS_SETUP_CONFIRM)
- return;
-
dev_dbg(priv->adapter->dev,
"rx:tdls action: peer=%pM, action=%d\n", peer, action);
- sta_ptr = mwifiex_add_sta_entry(priv, peer);
- if (!sta_ptr)
- return;
-
switch (action) {
case WLAN_TDLS_SETUP_REQUEST:
if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
@@ -815,7 +803,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
pos = buf + sizeof(struct ethhdr) + 4;
/* payload 1+ category 1 + action 1 + dialog 1 */
- sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+ cap = cpu_to_le16(*(u16 *)pos);
ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
pos += 2;
break;
@@ -825,7 +813,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
return;
/* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
pos = buf + sizeof(struct ethhdr) + 6;
- sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
+ cap = cpu_to_le16(*(u16 *)pos);
ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
pos += 2;
break;
@@ -837,10 +825,16 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
break;
default:
- dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
+ dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
return;
}
+ sta_ptr = mwifiex_add_sta_entry(priv, peer);
+ if (!sta_ptr)
+ return;
+
+ sta_ptr->tdls_cap.capab = cap;
+
for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
if (pos + 2 + pos[1] > end)
break;
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index fd7e5b9b4581..96a2126cc44b 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: generic TX/RX data handling
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 32643555dd2a..300bab438011 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: AP specific command handling
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 92e77a398ecf..7c2b97660a03 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: AP event handling
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index b0601b91cc4f..ec7309d096ab 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: AP TX and RX data handling
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -96,7 +96,6 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
struct sk_buff *new_skb;
struct mwifiex_txinfo *tx_info;
int hdr_chop;
- struct timeval tv;
struct ethhdr *p_ethhdr;
uap_rx_pd = (struct uap_rxpd *)(skb->data);
@@ -193,8 +192,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
tx_info->pkt_len = skb->len;
}
- do_gettimeofday(&tv);
- skb->tstamp = timeval_to_ktime(tv);
+ __net_timestamp(skb);
mwifiex_wmm_add_buf_txqueue(priv, skb);
atomic_inc(&adapter->tx_pending);
atomic_inc(&adapter->pending_bridged_pkts);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index a8ce8130cfae..7118a18b91ba 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: USB specific handling
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
index 15b73d12e998..4c41c2a193c5 100644
--- a/drivers/net/wireless/mwifiex/usb.h
+++ b/drivers/net/wireless/mwifiex/usb.h
@@ -1,7 +1,7 @@
/*
* This file contains definitions for mwifiex USB interface driver.
*
- * Copyright (C) 2012, Marvell International Ltd.
+ * Copyright (C) 2012-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 6da5abf52e61..cee028321a9a 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: utility functions
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
index caadb3737b9e..40296cb4a3f1 100644
--- a/drivers/net/wireless/mwifiex/util.h
+++ b/drivers/net/wireless/mwifiex/util.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: utility functions
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index d3671d009f6c..94c98a86ebbe 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: WMM
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
@@ -878,15 +878,8 @@ u8
mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
const struct sk_buff *skb)
{
+ u32 queue_delay = ktime_to_ms(net_timedelta(skb->tstamp));
u8 ret_val;
- struct timeval out_tstamp, in_tstamp;
- u32 queue_delay;
-
- do_gettimeofday(&out_tstamp);
- in_tstamp = ktime_to_timeval(skb->tstamp);
-
- queue_delay = (out_tstamp.tv_sec - in_tstamp.tv_sec) * 1000;
- queue_delay += (out_tstamp.tv_usec - in_tstamp.tv_usec) / 1000;
/*
* Queue delay is passed as a uint8 in units of 2ms (ms shifted
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index eca56e371a57..569bd73f33c5 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -1,7 +1,7 @@
/*
* Marvell Wireless LAN device driver: WMM
*
- * Copyright (C) 2011, Marvell International Ltd.
+ * Copyright (C) 2011-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 3c0a0a86ba12..ef1104476bd8 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1159,12 +1159,11 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
- rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
+ rxq->rxd = pci_zalloc_consistent(priv->pdev, size, &rxq->rxd_dma);
if (rxq->rxd == NULL) {
wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n");
return -ENOMEM;
}
- memset(rxq->rxd, 0, size);
rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
if (rxq->buf == NULL) {
@@ -1451,12 +1450,11 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
- txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
+ txq->txd = pci_zalloc_consistent(priv->pdev, size, &txq->txd_dma);
if (txq->txd == NULL) {
wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n");
return -ENOMEM;
}
- memset(txq->txd, 0, size);
txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
if (txq->skb == NULL) {
@@ -1633,22 +1631,17 @@ static int mwl8k_tid_queue_mapping(u8 tid)
case 0:
case 3:
return IEEE80211_AC_BE;
- break;
case 1:
case 2:
return IEEE80211_AC_BK;
- break;
case 4:
case 5:
return IEEE80211_AC_VI;
- break;
case 6:
case 7:
return IEEE80211_AC_VO;
- break;
default:
return -1;
- break;
}
}
@@ -5681,7 +5674,7 @@ MODULE_FIRMWARE("mwl8k/helper_8366.fw");
MODULE_FIRMWARE("mwl8k/fmimage_8366.fw");
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
-static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
+static const struct pci_device_id mwl8k_pci_id_table[] = {
{ PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
{ PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
{ PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig
index 60819bcf4377..60698b020851 100644
--- a/drivers/net/wireless/orinoco/Kconfig
+++ b/drivers/net/wireless/orinoco/Kconfig
@@ -107,7 +107,7 @@ config PCI_HERMES
config PCMCIA_HERMES
tristate "Hermes PCMCIA card support"
- depends on PCMCIA && HERMES
+ depends on PCMCIA && HERMES && HAS_IOPORT_MAP
---help---
A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -122,7 +122,7 @@ config PCMCIA_HERMES
config PCMCIA_SPECTRUM
tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
- depends on PCMCIA && HERMES
+ depends on PCMCIA && HERMES && HAS_IOPORT_MAP
---help---
This is a driver for 802.11b cards using RAM-loadable Symbol
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index ffb2469eb679..1b543e30eff7 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -272,7 +272,7 @@ static void orinoco_nortel_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(orinoco_nortel_id_table) = {
+static const struct pci_device_id orinoco_nortel_id_table[] = {
/* Nortel emobility PCI */
{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
/* Symbol LA-4123 PCI */
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 5ae1191d2532..b6bdad632842 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -210,7 +210,7 @@ static void orinoco_pci_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(orinoco_pci_id_table) = {
+static const struct pci_device_id orinoco_pci_id_table[] = {
/* Intersil Prism 3 */
{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
/* Intersil Prism 2.5 */
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index bbd36d1676ff..b8f6e5c431ae 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -308,7 +308,7 @@ static void orinoco_plx_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(orinoco_plx_id_table) = {
+static const struct pci_device_id orinoco_plx_id_table[] = {
{0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 04b08de5fd5d..79d0e33b625e 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -201,7 +201,7 @@ static void orinoco_tmd_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static DEFINE_PCI_DEVICE_TABLE(orinoco_tmd_id_table) = {
+static const struct pci_device_id orinoco_tmd_id_table[] = {
{0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
{0,},
};
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index c90939ced0e4..d3cf7c3ebfd6 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -921,7 +921,6 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
retval = -EFAULT;
}
goto exit;
- break;
}
if (ctx->in_rid) {
struct ezusb_packet *ans = ctx->buf;
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index d411de409050..d4aee64fb5ea 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54pci");
MODULE_FIRMWARE("isl3886pci");
-static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
+static const struct pci_device_id p54p_table[] = {
/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
{ PCI_DEVICE(0x1260, 0x3890) },
/* 3COM 3CRWE154G72 Wireless LAN adapter */
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index de15171e2cd8..63de5eed25cf 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -193,7 +193,7 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev)
/* allow users to customize their eeprom.
*/
- ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev);
+ ret = request_firmware_direct(&eeprom, "3826.eeprom", &priv->spi->dev);
if (ret < 0) {
#ifdef CONFIG_P54_SPI_DEFAULT_EEPROM
dev_info(&priv->spi->dev, "loading default eeprom...\n");
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 1105a12dbde8..300c846ea087 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -39,7 +39,7 @@ module_param(init_pcitm, int, 0);
* driver_data
* If you have an update for this please contact prism54-devel@prism54.org
* The latest list can be found at http://wireless.kernel.org/en/users/Drivers/p54 */
-static DEFINE_PCI_DEVICE_TABLE(prism54_id_tbl) = {
+static const struct pci_device_id prism54_id_tbl[] = {
/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
{
0x1260, 0x3890,
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index 47b34bfe890a..3a8d2dbcfecd 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -793,7 +793,6 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str)
switch (isl_oid[n].flags & OID_FLAG_TYPE) {
case OID_TYPE_U32:
return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u);
- break;
case OID_TYPE_BUFFER:{
struct obj_buffer *buff = r->ptr;
return snprintf(str, PRIV_STR_SIZE,
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index cf61d6e3eaa7..f3d3995d8f6b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -77,6 +77,52 @@ static bool rsi_recalculate_weights(struct rsi_common *common)
}
/**
+ * rsi_get_num_pkts_dequeue() - This function determines the number of
+ * packets to be dequeued based on the number
+ * of bytes calculated using txop.
+ *
+ * @common: Pointer to the driver private structure.
+ * @q_num: the queue from which pkts have to be dequeued
+ *
+ * Return: pkt_num: Number of pkts to be dequeued.
+ */
+static u32 rsi_get_num_pkts_dequeue(struct rsi_common *common, u8 q_num)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct sk_buff *skb;
+ u32 pkt_cnt = 0;
+ s16 txop = common->tx_qinfo[q_num].txop * 32;
+ __le16 r_txop;
+ struct ieee80211_rate rate;
+
+ rate.bitrate = RSI_RATE_MCS0 * 5 * 10; /* Convert to Kbps */
+ if (q_num == VI_Q)
+ txop = ((txop << 5) / 80);
+
+ if (skb_queue_len(&common->tx_queue[q_num]))
+ skb = skb_peek(&common->tx_queue[q_num]);
+ else
+ return 0;
+
+ do {
+ r_txop = ieee80211_generic_frame_duration(adapter->hw,
+ adapter->vifs[0],
+ common->band,
+ skb->len, &rate);
+ txop -= le16_to_cpu(r_txop);
+ pkt_cnt += 1;
+ /*checking if pkts are still there*/
+ if (skb_queue_len(&common->tx_queue[q_num]) - pkt_cnt)
+ skb = skb->next;
+ else
+ break;
+
+ } while (txop > 0);
+
+ return pkt_cnt;
+}
+
+/**
* rsi_core_determine_hal_queue() - This function determines the queue from
* which packet has to be dequeued.
* @common: Pointer to the driver private structure.
@@ -88,7 +134,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
bool recontend_queue = false;
u32 q_len = 0;
u8 q_num = INVALID_QUEUE;
- u8 ii = 0, min = 0;
+ u8 ii = 0;
if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
if (!common->mgmt_q_block)
@@ -96,6 +142,9 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
return q_num;
}
+ if (common->hw_data_qs_blocked)
+ return q_num;
+
if (common->pkt_cnt != 0) {
--common->pkt_cnt;
return common->selected_qnum;
@@ -106,14 +155,15 @@ get_queue_num:
q_num = rsi_determine_min_weight_queue(common);
- q_len = skb_queue_len(&common->tx_queue[ii]);
ii = q_num;
/* Selecting the queue with least back off */
for (; ii < NUM_EDCA_QUEUES; ii++) {
+ q_len = skb_queue_len(&common->tx_queue[ii]);
if (((common->tx_qinfo[ii].pkt_contended) &&
- (common->tx_qinfo[ii].weight < min)) && q_len) {
- min = common->tx_qinfo[ii].weight;
+ (common->tx_qinfo[ii].weight < common->min_weight)) &&
+ q_len) {
+ common->min_weight = common->tx_qinfo[ii].weight;
q_num = ii;
}
}
@@ -140,25 +190,9 @@ get_queue_num:
common->selected_qnum = q_num;
q_len = skb_queue_len(&common->tx_queue[q_num]);
- switch (common->selected_qnum) {
- case VO_Q:
- if (q_len > MAX_CONTINUOUS_VO_PKTS)
- common->pkt_cnt = (MAX_CONTINUOUS_VO_PKTS - 1);
- else
- common->pkt_cnt = --q_len;
- break;
-
- case VI_Q:
- if (q_len > MAX_CONTINUOUS_VI_PKTS)
- common->pkt_cnt = (MAX_CONTINUOUS_VI_PKTS - 1);
- else
- common->pkt_cnt = --q_len;
-
- break;
-
- default:
- common->pkt_cnt = 0;
- break;
+ if (q_num == VO_Q || q_num == VI_Q) {
+ common->pkt_cnt = rsi_get_num_pkts_dequeue(common, q_num);
+ common->pkt_cnt -= 1;
}
return q_num;
@@ -252,6 +286,7 @@ void rsi_core_qos_processor(struct rsi_common *common)
skb = rsi_core_dequeue_pkt(common, q_num);
if (skb == NULL) {
+ rsi_dbg(ERR_ZONE, "skb null\n");
mutex_unlock(&common->tx_rxlock);
break;
}
@@ -306,7 +341,8 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
}
if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||
- (ieee80211_is_ctl(tmp_hdr->frame_control))) {
+ (ieee80211_is_ctl(tmp_hdr->frame_control)) ||
+ (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) {
q_num = MGMT_SOFT_Q;
skb->priority = q_num;
} else {
@@ -325,6 +361,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
if ((q_num != MGMT_SOFT_Q) &&
((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
DATA_QUEUE_WATER_MARK)) {
+ rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
ieee80211_stop_queue(adapter->hw, WME_AC(q_num));
rsi_set_event(&common->tx_thread.event);
diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
index c466246a323f..828a042f903f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c
+++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c
@@ -145,7 +145,7 @@ static int rsi_stats_read(struct seq_file *seq, void *data)
seq_printf(seq, "total_mgmt_pkt_send : %d\n",
common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
- skb_queue_len(&common->tx_queue[4]));
+ skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
seq_printf(seq, "total_mgmt_pkt_freed : %d\n",
common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
@@ -153,25 +153,25 @@ static int rsi_stats_read(struct seq_file *seq, void *data)
seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
common->tx_stats.total_tx_pkt_send[VO_Q]);
seq_printf(seq, "total_data_vo_pkt_queued: %8d\t",
- skb_queue_len(&common->tx_queue[0]));
+ skb_queue_len(&common->tx_queue[VO_Q]));
seq_printf(seq, "total_vo_pkt_freed: %8d\n",
common->tx_stats.total_tx_pkt_freed[VO_Q]);
seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
common->tx_stats.total_tx_pkt_send[VI_Q]);
seq_printf(seq, "total_data_vi_pkt_queued: %8d\t",
- skb_queue_len(&common->tx_queue[1]));
+ skb_queue_len(&common->tx_queue[VI_Q]));
seq_printf(seq, "total_vi_pkt_freed: %8d\n",
common->tx_stats.total_tx_pkt_freed[VI_Q]);
seq_printf(seq, "total_data_be_pkt_send: %8d\t",
common->tx_stats.total_tx_pkt_send[BE_Q]);
seq_printf(seq, "total_data_be_pkt_queued: %8d\t",
- skb_queue_len(&common->tx_queue[2]));
+ skb_queue_len(&common->tx_queue[BE_Q]));
seq_printf(seq, "total_be_pkt_freed: %8d\n",
common->tx_stats.total_tx_pkt_freed[BE_Q]);
seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
common->tx_stats.total_tx_pkt_send[BK_Q]);
seq_printf(seq, "total_data_bk_pkt_queued: %8d\t",
- skb_queue_len(&common->tx_queue[3]));
+ skb_queue_len(&common->tx_queue[BK_Q]));
seq_printf(seq, "total_bk_pkt_freed: %8d\n",
common->tx_stats.total_tx_pkt_freed[BK_Q]);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 54aaeb09debf..aeaf87bb5518 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -177,7 +177,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
sbands->ht_cap.cap = (IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40);
- sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+ sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
sbands->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
sbands->ht_cap.mcs.rx_mask[0] = 0xff;
sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
@@ -185,7 +185,7 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
}
/**
- * rsi_mac80211_attach() - This function is used to de-initialize the
+ * rsi_mac80211_detach() - This function is used to de-initialize the
* Mac80211 stack.
* @adapter: Pointer to the adapter structure.
*
@@ -341,6 +341,59 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
}
/**
+ * rsi_channel_change() - This function is a performs the checks
+ * required for changing a channel and sets
+ * the channel accordingly.
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_channel_change(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ int status = -EOPNOTSUPP;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ u16 channel = curchan->hw_value;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Set channel: %d MHz type: %d channel_no %d\n",
+ __func__, curchan->center_freq,
+ curchan->flags, channel);
+
+ if (bss->assoc) {
+ if (!common->hw_data_qs_blocked &&
+ (rsi_get_connected_channel(adapter) != channel)) {
+ rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, true))
+ common->hw_data_qs_blocked = true;
+ }
+ }
+
+ status = rsi_band_check(common);
+ if (!status)
+ status = rsi_set_channel(adapter->priv, channel);
+
+ if (bss->assoc) {
+ if (common->hw_data_qs_blocked &&
+ (rsi_get_connected_channel(adapter) == channel)) {
+ rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ }
+ } else {
+ if (common->hw_data_qs_blocked) {
+ rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ }
+ }
+
+ return status;
+}
+
+/**
* rsi_mac80211_config() - This function is a handler for configuration
* requests. The stack calls this function to
* change hardware configuration, e.g., channel.
@@ -357,17 +410,10 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
int status = -EOPNOTSUPP;
mutex_lock(&common->mutex);
- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- struct ieee80211_channel *curchan = hw->conf.chandef.chan;
- u16 channel = curchan->hw_value;
-
- rsi_dbg(INFO_ZONE,
- "%s: Set channel: %d MHz type: %d channel_no %d\n",
- __func__, curchan->center_freq,
- curchan->flags, channel);
- common->band = curchan->band;
- status = rsi_set_channel(adapter->priv, channel);
- }
+
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
+ status = rsi_channel_change(hw);
+
mutex_unlock(&common->mutex);
return status;
@@ -421,6 +467,15 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->qos,
bss_conf->aid);
}
+
+ if (changed & BSS_CHANGED_CQM) {
+ common->cqm_info.last_cqm_event_rssi = 0;
+ common->cqm_info.rssi_thold = bss_conf->cqm_rssi_thold;
+ common->cqm_info.rssi_hyst = bss_conf->cqm_rssi_hyst;
+ rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n",
+ common->cqm_info.rssi_thold,
+ common->cqm_info.rssi_hyst);
+ }
mutex_unlock(&common->mutex);
}
@@ -723,17 +778,17 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw,
{
struct rsi_hw *adapter = hw->priv;
struct rsi_common *common = adapter->priv;
+ enum ieee80211_band band = hw->conf.chandef.chan->band;
mutex_lock(&common->mutex);
+ common->fixedrate_mask[band] = 0;
- common->fixedrate_mask[IEEE80211_BAND_2GHZ] = 0;
-
- if (mask->control[IEEE80211_BAND_2GHZ].legacy == 0xfff) {
- common->fixedrate_mask[IEEE80211_BAND_2GHZ] =
- (mask->control[IEEE80211_BAND_2GHZ].ht_mcs[0] << 12);
+ if (mask->control[band].legacy == 0xfff) {
+ common->fixedrate_mask[band] =
+ (mask->control[band].ht_mcs[0] << 12);
} else {
- common->fixedrate_mask[IEEE80211_BAND_2GHZ] =
- mask->control[IEEE80211_BAND_2GHZ].legacy;
+ common->fixedrate_mask[band] =
+ mask->control[band].legacy;
}
mutex_unlock(&common->mutex);
@@ -741,6 +796,37 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw,
}
/**
+ * rsi_perform_cqm() - This function performs cqm.
+ * @common: Pointer to the driver private structure.
+ * @bssid: pointer to the bssid.
+ * @rssi: RSSI value.
+ */
+static void rsi_perform_cqm(struct rsi_common *common,
+ u8 *bssid,
+ s8 rssi)
+{
+ struct rsi_hw *adapter = common->priv;
+ s8 last_event = common->cqm_info.last_cqm_event_rssi;
+ int thold = common->cqm_info.rssi_thold;
+ u32 hyst = common->cqm_info.rssi_hyst;
+ enum nl80211_cqm_rssi_threshold_event event;
+
+ if (rssi < thold && (last_event == 0 || rssi < (last_event - hyst)))
+ event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+ else if (rssi > thold &&
+ (last_event == 0 || rssi > (last_event + hyst)))
+ event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+ else
+ return;
+
+ common->cqm_info.last_cqm_event_rssi = rssi;
+ rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
+ ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
+
+ return;
+}
+
+/**
* rsi_fill_rx_status() - This function fills rx status in
* ieee80211_rx_status structure.
* @hw: Pointer to the ieee80211_hw structure.
@@ -755,6 +841,7 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
struct rsi_common *common,
struct ieee80211_rx_status *rxs)
{
+ struct ieee80211_bss_conf *bss = &common->priv->vifs[0]->bss_conf;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct skb_info *rx_params = (struct skb_info *)info->driver_data;
struct ieee80211_hdr *hdr;
@@ -770,10 +857,7 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
rxs->signal = -(rssi);
- if (channel <= 14)
- rxs->band = IEEE80211_BAND_2GHZ;
- else
- rxs->band = IEEE80211_BAND_5GHZ;
+ rxs->band = common->band;
freq = ieee80211_channel_to_frequency(channel, rxs->band);
@@ -792,6 +876,14 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
rxs->flag |= RX_FLAG_DECRYPTED;
rxs->flag |= RX_FLAG_IV_STRIPPED;
}
+
+ /* CQM only for connected AP beacons, the RSSI is a weighted avg */
+ if (bss->assoc && !(memcmp(bss->bssid, hdr->addr2, ETH_ALEN))) {
+ if (ieee80211_is_beacon(hdr->frame_control))
+ rsi_perform_cqm(common, hdr->addr2, rxs->signal);
+ }
+
+ return;
}
/**
@@ -983,6 +1075,7 @@ int rsi_mac80211_attach(struct rsi_common *common)
hw->max_tx_aggregation_subframes = 6;
rsi_register_rates_channels(adapter, IEEE80211_BAND_2GHZ);
+ rsi_register_rates_channels(adapter, IEEE80211_BAND_5GHZ);
hw->rate_control_algorithm = "AARF";
SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
@@ -1000,6 +1093,8 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->available_antennas_tx = 1;
wiphy->bands[IEEE80211_BAND_2GHZ] =
&adapter->sbands[IEEE80211_BAND_2GHZ];
+ wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &adapter->sbands[IEEE80211_BAND_5GHZ];
status = ieee80211_register_hw(hw);
if (status)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 2eefbf159bc0..8d110fd9eba1 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -217,6 +217,7 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->min_rate = 0xffff;
common->fsm_state = FSM_CARD_NOT_READY;
common->iface_down = true;
+ common->endpoint = EP_2GHZ_20MHZ;
}
/**
@@ -276,7 +277,6 @@ static int rsi_load_radio_caps(struct rsi_common *common)
{
struct rsi_radio_caps *radio_caps;
struct rsi_hw *adapter = common->priv;
- struct ieee80211_hw *hw = adapter->hw;
u16 inx = 0;
u8 ii;
u8 radio_id = 0;
@@ -285,7 +285,6 @@ static int rsi_load_radio_caps(struct rsi_common *common)
0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0};
- struct ieee80211_conf *conf = &hw->conf;
struct sk_buff *skb;
rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);
@@ -307,29 +306,36 @@ static int rsi_load_radio_caps(struct rsi_common *common)
if (common->channel_width == BW_40MHZ) {
radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);
radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ);
- if (common->channel_width) {
- radio_caps->desc_word[5] =
- cpu_to_le16(common->channel_width << 12);
- radio_caps->desc_word[5] |= cpu_to_le16(FULL40M_ENABLE);
- }
- if (conf_is_ht40_minus(conf)) {
- radio_caps->desc_word[5] = 0;
- radio_caps->desc_word[5] |=
- cpu_to_le16(LOWER_20_ENABLE);
- radio_caps->desc_word[5] |=
- cpu_to_le16(LOWER_20_ENABLE >> 12);
- }
-
- if (conf_is_ht40_plus(conf)) {
- radio_caps->desc_word[5] = 0;
- radio_caps->desc_word[5] |=
- cpu_to_le16(UPPER_20_ENABLE);
- radio_caps->desc_word[5] |=
- cpu_to_le16(UPPER_20_ENABLE >> 12);
+ if (common->fsm_state == FSM_MAC_INIT_DONE) {
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ if (conf_is_ht40_plus(conf)) {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(LOWER_20_ENABLE);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(LOWER_20_ENABLE >> 12);
+ } else if (conf_is_ht40_minus(conf)) {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(UPPER_20_ENABLE);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(UPPER_20_ENABLE >> 12);
+ } else {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(BW_40MHZ << 12);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(FULL40M_ENABLE);
+ }
}
}
+ radio_caps->sifs_tx_11n = cpu_to_le16(SIFS_TX_11N_VALUE);
+ radio_caps->sifs_tx_11b = cpu_to_le16(SIFS_TX_11B_VALUE);
+ radio_caps->slot_rx_11n = cpu_to_le16(SHORT_SLOT_VALUE);
+ radio_caps->ofdm_ack_tout = cpu_to_le16(OFDM_ACK_TOUT_VALUE);
+ radio_caps->cck_ack_tout = cpu_to_le16(CCK_ACK_TOUT_VALUE);
+ radio_caps->preamble_type = cpu_to_le16(LONG_PREAMBLE);
+
radio_caps->desc_word[7] |= cpu_to_le16(radio_id << 8);
for (ii = 0; ii < MAX_HW_QUEUES; ii++) {
@@ -588,7 +594,7 @@ static int rsi_program_bb_rf(struct rsi_common *common)
mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA);
- mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint << 8);
+ mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint);
if (common->rf_reset) {
mgmt_frame->desc_word[7] = cpu_to_le16(RF_RESET_ENABLE);
@@ -615,6 +621,9 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
{
struct sk_buff *skb = NULL;
struct rsi_vap_caps *vap_caps;
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
u16 vap_id = 0;
rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__);
@@ -644,13 +653,24 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)
vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD);
vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold);
- vap_caps->default_mgmt_rate = 0;
- if (conf_is_ht40(&common->priv->hw->conf)) {
- vap_caps->default_ctrl_rate =
- cpu_to_le32(RSI_RATE_6 | FULL40M_ENABLE << 16);
- } else {
+ vap_caps->default_mgmt_rate = cpu_to_le32(RSI_RATE_6);
+
+ if (common->band == IEEE80211_BAND_5GHZ) {
vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6);
+ if (conf_is_ht40(&common->priv->hw->conf)) {
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(FULL40M_ENABLE << 16);
+ }
+ } else {
+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_1);
+ if (conf_is_ht40_minus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(UPPER_20_ENABLE << 16);
+ else if (conf_is_ht40_plus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(LOWER_20_ENABLE << 16);
}
+
vap_caps->default_data_rate = 0;
vap_caps->beacon_interval = cpu_to_le16(200);
vap_caps->dtim_period = cpu_to_le16(4);
@@ -827,6 +847,63 @@ static int rsi_send_reset_mac(struct rsi_common *common)
}
/**
+ * rsi_band_check() - This function programs the band
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_band_check(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hw *hw = adapter->hw;
+ u8 prev_bw = common->channel_width;
+ u8 prev_ep = common->endpoint;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ int status = 0;
+
+ if (common->band != curchan->band) {
+ common->rf_reset = 1;
+ common->band = curchan->band;
+ }
+
+ if ((hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) ||
+ (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20))
+ common->channel_width = BW_20MHZ;
+ else
+ common->channel_width = BW_40MHZ;
+
+ if (common->band == IEEE80211_BAND_2GHZ) {
+ if (common->channel_width)
+ common->endpoint = EP_2GHZ_40MHZ;
+ else
+ common->endpoint = EP_2GHZ_20MHZ;
+ } else {
+ if (common->channel_width)
+ common->endpoint = EP_5GHZ_40MHZ;
+ else
+ common->endpoint = EP_5GHZ_20MHZ;
+ }
+
+ if (common->endpoint != prev_ep) {
+ status = rsi_program_bb_rf(common);
+ if (status)
+ return status;
+ }
+
+ if (common->channel_width != prev_bw) {
+ status = rsi_load_bootup_params(common);
+ if (status)
+ return status;
+
+ status = rsi_load_radio_caps(common);
+ if (status)
+ return status;
+ }
+
+ return status;
+}
+
+/**
* rsi_set_channel() - This function programs the channel.
* @common: Pointer to the driver private structure.
* @channel: Channel value to be set.
@@ -841,23 +918,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
rsi_dbg(MGMT_TX_ZONE,
"%s: Sending scan req frame\n", __func__);
- if (common->band == IEEE80211_BAND_5GHZ) {
- if ((channel >= 36) && (channel <= 64))
- channel = ((channel - 32) / 4);
- else if ((channel > 64) && (channel <= 140))
- channel = ((channel - 102) / 4) + 8;
- else if (channel >= 149)
- channel = ((channel - 151) / 4) + 18;
- else
- return -EINVAL;
- } else {
- if (channel > 14) {
- rsi_dbg(ERR_ZONE, "%s: Invalid chno %d, band = %d\n",
- __func__, channel, common->band);
- return -EINVAL;
- }
- }
-
skb = dev_alloc_skb(FRAME_DESC_SZ);
if (!skb) {
rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
@@ -877,6 +937,7 @@ int rsi_set_channel(struct rsi_common *common, u16 channel)
(RSI_RF_TYPE << 4));
mgmt_frame->desc_word[5] = cpu_to_le16(0x01);
+ mgmt_frame->desc_word[6] = cpu_to_le16(0x12);
if (common->channel_width == BW_40MHZ)
mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);
@@ -950,7 +1011,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
struct ieee80211_hw *hw = common->priv->hw;
u8 band = hw->conf.chandef.chan->band;
u8 num_supported_rates = 0;
- u8 rate_offset = 0;
+ u8 rate_table_offset, rate_offset = 0;
u32 rate_bitmap = common->bitrate_mask[band];
u16 *selected_rates, min_rate;
@@ -986,14 +1047,19 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
if (common->channel_width == BW_40MHZ)
auto_rate->desc_word[7] |= cpu_to_le16(1);
- if (band == IEEE80211_BAND_2GHZ)
- min_rate = STD_RATE_01;
- else
- min_rate = STD_RATE_06;
+ if (band == IEEE80211_BAND_2GHZ) {
+ min_rate = RSI_RATE_1;
+ rate_table_offset = 0;
+ } else {
+ min_rate = RSI_RATE_6;
+ rate_table_offset = 4;
+ }
- for (ii = 0, jj = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
+ for (ii = 0, jj = 0;
+ ii < (ARRAY_SIZE(rsi_rates) - rate_table_offset); ii++) {
if (rate_bitmap & BIT(ii)) {
- selected_rates[jj++] = (rsi_rates[ii].bitrate / 5);
+ selected_rates[jj++] =
+ (rsi_rates[ii + rate_table_offset].bitrate / 5);
rate_offset++;
}
}
@@ -1006,13 +1072,6 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
rate_offset += ARRAY_SIZE(mcs);
}
- if (rate_offset < (RSI_TBL_SZ / 2) - 1) {
- for (ii = jj; ii < (RSI_TBL_SZ / 2); ii++) {
- selected_rates[jj++] = min_rate;
- rate_offset++;
- }
- }
-
sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL);
/* mapping the rates to RSI rates */
@@ -1028,25 +1087,25 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
/* loading HT rates in the bottom half of the auto rate table */
if (common->vif_info[0].is_ht) {
- if (common->vif_info[0].sgi)
- auto_rate->supported_rates[rate_offset++] =
- cpu_to_le16(RSI_RATE_MCS7_SG);
-
for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;
ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {
- if (common->vif_info[0].sgi)
+ if (common->vif_info[0].sgi ||
+ conf_is_ht40(&common->priv->hw->conf))
auto_rate->supported_rates[ii++] =
cpu_to_le16(rsi_mcsrates[kk] | BIT(9));
auto_rate->supported_rates[ii] =
cpu_to_le16(rsi_mcsrates[kk--]);
}
- for (; ii < RSI_TBL_SZ; ii++) {
+ for (; ii < (RSI_TBL_SZ - 1); ii++) {
auto_rate->supported_rates[ii] =
cpu_to_le16(rsi_mcsrates[0]);
}
}
+ for (; ii < RSI_TBL_SZ; ii++)
+ auto_rate->supported_rates[ii] = cpu_to_le16(min_rate);
+
auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);
auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);
auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);
@@ -1141,6 +1200,49 @@ static int rsi_eeprom_read(struct rsi_common *common)
}
/**
+ * This function sends a frame to block/unblock
+ * data queues in the firmware
+ *
+ * @param common Pointer to the driver private structure.
+ * @param block event - block if true, unblock if false
+ * @return 0 on success, -1 on failure.
+ */
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending block/unblock frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(BLOCK_HW_QUEUE);
+
+ if (block_event == true) {
+ rsi_dbg(INFO_ZONE, "blocking the data qs\n");
+ mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
+ } else {
+ rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
+ mgmt_frame->desc_word[5] = cpu_to_le16(0xf);
+ }
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+
+}
+
+
+/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
* @msg: Pointer to received packet.
@@ -1164,7 +1266,7 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
common->fsm_state = FSM_EEPROM_READ_MAC_ADDR;
}
} else {
- rsi_dbg(ERR_ZONE,
+ rsi_dbg(INFO_ZONE,
"%s: Received bootup params cfm in %d state\n",
__func__, common->fsm_state);
return 0;
@@ -1227,7 +1329,7 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
__func__);
}
} else {
- rsi_dbg(ERR_ZONE,
+ rsi_dbg(INFO_ZONE,
"%s: Received radio caps cfm in %d state\n",
__func__, common->fsm_state);
return 0;
@@ -1245,7 +1347,10 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
return rsi_mac80211_attach(common);
}
} else {
- goto out;
+ rsi_dbg(INFO_ZONE,
+ "%s: Received bbb_rf cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
}
break;
diff --git a/drivers/net/wireless/rsi/rsi_91x_pkt.c b/drivers/net/wireless/rsi/rsi_91x_pkt.c
index 8e48e72bae20..702593f19997 100644
--- a/drivers/net/wireless/rsi/rsi_91x_pkt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_pkt.c
@@ -81,6 +81,16 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
/* Send fixed rate */
frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
frame_desc[4] = cpu_to_le16(common->min_rate);
+
+ if (conf_is_ht40(&common->priv->hw->conf))
+ frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
+
+ if (common->vif_info[0].sgi) {
+ if (common->min_rate & 0x100) /* Only MCS rates */
+ frame_desc[4] |=
+ cpu_to_le16(ENABLE_SHORTGI_RATE);
+ }
+
}
frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
@@ -116,6 +126,8 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
struct ieee80211_hdr *wh = NULL;
struct ieee80211_tx_info *info;
struct ieee80211_bss_conf *bss = NULL;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
struct skb_info *tx_params;
int status = -E2BIG;
__le16 *msg = NULL;
@@ -175,6 +187,11 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
else
msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
+ if (conf_is_ht40(conf)) {
+ msg[4] = cpu_to_le16(0xB | RSI_11G_MODE);
+ msg[5] = cpu_to_le16(0x6);
+ }
+
/* Indicate to firmware to give cfm */
if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {
msg[1] |= cpu_to_le16(BIT(10));
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 46e7af446f01..8428858204a6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -820,9 +820,11 @@ static struct sdio_driver rsi_driver = {
*/
static int rsi_module_init(void)
{
- sdio_register_driver(&rsi_driver);
+ int ret;
+
+ ret = sdio_register_driver(&rsi_driver);
rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
- return 0;
+ return ret;
}
/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 20d11ccfffe3..4834a9abc171 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -401,14 +401,16 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
case BUFFER_AVAILABLE:
dev->rx_info.watch_bufferfull_count = 0;
dev->rx_info.buffer_full = false;
+ dev->rx_info.semi_buffer_full = false;
dev->rx_info.mgmt_buffer_full = false;
rsi_sdio_ack_intr(common->priv,
(1 << PKT_BUFF_AVAILABLE));
- rsi_set_event((&common->tx_thread.event));
+ rsi_set_event(&common->tx_thread.event);
+
rsi_dbg(ISR_ZONE,
- "%s: ==> BUFFER_AVILABLE <==\n",
+ "%s: ==> BUFFER_AVAILABLE <==\n",
__func__);
- dev->rx_info.buf_avilable_counter++;
+ dev->rx_info.buf_available_counter++;
break;
case FIRMWARE_ASSERT_IND:
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 4c46e5631e2f..ef5d394f185b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -25,7 +25,7 @@
* @len: Length to be written.
* @endpoint: Type of endpoint.
*
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
*/
static int rsi_usb_card_write(struct rsi_hw *adapter,
void *buf,
@@ -60,7 +60,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
* @data: Pointer to the data that has to be written.
* @count: Number of multiple bytes to be written.
*
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
*/
static int rsi_write_multiple(struct rsi_hw *adapter,
u8 endpoint,
@@ -147,7 +147,7 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
* @value: Value to be read.
* @len: length of data to be read.
*
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
*/
static int rsi_usb_reg_read(struct usb_device *usbdev,
u32 reg,
@@ -189,7 +189,7 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
* @value: Value to write.
* @len: Length of data to be written.
*
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
*/
static int rsi_usb_reg_write(struct usb_device *usbdev,
u32 reg,
@@ -249,7 +249,7 @@ static void rsi_rx_done_handler(struct urb *urb)
* rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
* @adapter: Pointer to the adapter structure.
*
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
*/
static int rsi_rx_urb_submit(struct rsi_hw *adapter)
{
@@ -281,7 +281,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
* @data: Pointer to the data that has to be written.
* @count: Number of multiple bytes to be written on to the registers.
*
- * Return: status: 0 on success, -1 on failure.
+ * Return: status: 0 on success, a negative error code on failure.
*/
int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
u32 addr,
@@ -331,7 +331,7 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
* @pkt: Pointer to the data to be written on to the card.
* @len: Length of the data to be written on to the card.
*
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
*/
static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
u8 *pkt,
@@ -359,6 +359,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
rsi_kill_thread(&dev->rx_thread);
+ usb_free_urb(dev->rx_usb_urb[0]);
kfree(adapter->priv->rx_data_pkt);
kfree(dev->tx_buffer);
}
@@ -368,7 +369,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
* @adapter: Pointer to the adapter structure.
* @pfunction: Pointer to USB interface structure.
*
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
*/
static int rsi_init_usb_interface(struct rsi_hw *adapter,
struct usb_interface *pfunction)
@@ -397,8 +398,16 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
return -ENOMEM;
}
- rsi_dev->tx_buffer = kmalloc(2048, GFP_ATOMIC);
+ rsi_dev->tx_buffer = kmalloc(2048, GFP_KERNEL);
+ if (!rsi_dev->tx_buffer) {
+ status = -ENOMEM;
+ goto fail_tx;
+ }
rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rsi_dev->rx_usb_urb[0]) {
+ status = -ENOMEM;
+ goto fail_rx;
+ }
rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
rsi_dev->tx_blk_size = 252;
@@ -413,7 +422,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
rsi_usb_rx_thread, "RX-Thread");
if (status) {
rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
- goto fail;
+ goto fail_thread;
}
#ifdef CONFIG_RSI_DEBUGFS
@@ -424,8 +433,11 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
return 0;
-fail:
+fail_thread:
+ usb_free_urb(rsi_dev->rx_usb_urb[0]);
+fail_rx:
kfree(rsi_dev->tx_buffer);
+fail_tx:
kfree(common->rx_data_pkt);
return status;
}
@@ -437,7 +449,7 @@ fail:
* @pfunction: Pointer to the USB interface structure.
* @id: Pointer to the usb_device_id structure.
*
- * Return: 0 on success, -1 on failure.
+ * Return: 0 on success, a negative error code on failure.
*/
static int rsi_probe(struct usb_interface *pfunction,
const struct usb_device_id *id)
@@ -445,6 +457,7 @@ static int rsi_probe(struct usb_interface *pfunction,
struct rsi_hw *adapter;
struct rsi_91x_usbdev *dev;
u16 fw_status;
+ int status;
rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
@@ -452,10 +465,11 @@ static int rsi_probe(struct usb_interface *pfunction,
if (!adapter) {
rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
__func__);
- return 1;
+ return -ENOMEM;
}
- if (rsi_init_usb_interface(adapter, pfunction)) {
+ status = rsi_init_usb_interface(adapter, pfunction);
+ if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",
__func__);
goto err;
@@ -465,26 +479,30 @@ static int rsi_probe(struct usb_interface *pfunction,
dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- if (rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2) < 0)
+ status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
+ if (status)
goto err1;
else
fw_status &= 1;
if (!fw_status) {
- if (rsi_usb_device_init(adapter->priv)) {
+ status = rsi_usb_device_init(adapter->priv);
+ if (status) {
rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
__func__);
goto err1;
}
- if (rsi_usb_reg_write(dev->usbdev,
- USB_INTERNAL_REG_1,
- RSI_USB_READY_MAGIC_NUM, 1) < 0)
+ status = rsi_usb_reg_write(dev->usbdev,
+ USB_INTERNAL_REG_1,
+ RSI_USB_READY_MAGIC_NUM, 1);
+ if (status)
goto err1;
rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);
}
- if (rsi_rx_urb_submit(adapter))
+ status = rsi_rx_urb_submit(adapter);
+ if (status)
goto err1;
return 0;
@@ -493,7 +511,7 @@ err1:
err:
rsi_91x_deinit(adapter);
rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
- return 1;
+ return status;
}
/**
@@ -550,33 +568,7 @@ static struct usb_driver rsi_driver = {
#endif
};
-/**
- * rsi_module_init() - This function registers the client driver.
- * @void: Void.
- *
- * Return: 0 on success.
- */
-static int rsi_module_init(void)
-{
- usb_register(&rsi_driver);
- rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
- return 0;
-}
-
-/**
- * rsi_module_exit() - This function unregisters the client driver.
- * @void: Void.
- *
- * Return: None.
- */
-static void rsi_module_exit(void)
-{
- usb_deregister(&rsi_driver);
- rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);
-}
-
-module_init(rsi_module_init);
-module_exit(rsi_module_exit);
+module_usb_driver(rsi_driver);
MODULE_AUTHOR("Redpine Signals Inc");
MODULE_DESCRIPTION("Common USB layer for RSI drivers");
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 2cb73e7edb98..5baed945f60e 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -115,6 +115,7 @@ struct wmm_qinfo {
s32 weight;
s32 wme_params;
s32 pkt_contended;
+ s32 txop;
};
struct transmit_q_stats {
@@ -141,6 +142,12 @@ struct rsi_thread {
atomic_t thread_done;
};
+struct cqm_info {
+ s8 last_cqm_event_rssi;
+ int rssi_thold;
+ u32 rssi_hyst;
+};
+
struct rsi_hw;
struct rsi_common {
@@ -192,6 +199,11 @@ struct rsi_common {
u8 selected_qnum;
u32 pkt_cnt;
u8 min_weight;
+
+ /* bgscan related */
+ struct cqm_info cqm_info;
+
+ bool hw_data_qs_blocked;
};
struct rsi_hw {
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 225215a3b8bb..3741173fd3ac 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -69,6 +69,7 @@
#define RSI_LMAC_CLOCK_80MHZ 0x1
#define RSI_ENABLE_40MHZ (0x1 << 3)
+#define ENABLE_SHORTGI_RATE BIT(9)
#define RX_BA_INDICATION 1
#define RSI_TBL_SZ 40
@@ -123,6 +124,20 @@
#define BW_20MHZ 0
#define BW_40MHZ 1
+#define EP_2GHZ_20MHZ 0
+#define EP_2GHZ_40MHZ 1
+#define EP_5GHZ_20MHZ 2
+#define EP_5GHZ_40MHZ 3
+
+#define SIFS_TX_11N_VALUE 580
+#define SIFS_TX_11B_VALUE 346
+#define SHORT_SLOT_VALUE 360
+#define LONG_SLOT_VALUE 640
+#define OFDM_ACK_TOUT_VALUE 2720
+#define CCK_ACK_TOUT_VALUE 9440
+#define LONG_PREAMBLE 0x0000
+#define SHORT_PREAMBLE 0x0001
+
#define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\
FIF_BCN_PRBRESP_PROMISC)
enum opmode {
@@ -153,7 +168,7 @@ enum cmd_frame_type {
SCAN_REQUEST,
TSF_UPDATE,
PEER_NOTIFY,
- BLOCK_UNBLOCK,
+ BLOCK_HW_QUEUE,
SET_KEY_REQ,
AUTO_RATE_IND,
BOOTUP_PARAMS_REQUEST,
@@ -238,6 +253,12 @@ struct rsi_radio_caps {
u8 num_11n_rates;
u8 num_11ac_rates;
__le16 gcpd_per_rate[20];
+ __le16 sifs_tx_11n;
+ __le16 sifs_tx_11b;
+ __le16 slot_rx_11n;
+ __le16 ofdm_ack_tout;
+ __le16 cck_ack_tout;
+ __le16 preamble_type;
} __packed;
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
@@ -272,6 +293,7 @@ int rsi_send_aggregation_params_frame(struct rsi_common *common, u16 tid,
int rsi_hal_load_key(struct rsi_common *common, u8 *data, u16 key_len,
u8 key_type, u8 key_id, u32 cipher);
int rsi_set_channel(struct rsi_common *common, u16 chno);
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
void rsi_inform_bss_status(struct rsi_common *common, u8 status,
const u8 *bssid, u8 qos_enable, u16 aid);
void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
@@ -283,4 +305,5 @@ void rsi_core_qos_processor(struct rsi_common *common);
void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_band_check(struct rsi_common *common);
#endif
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index df4b5e20e05f..c7e8f2be7901 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -30,7 +30,7 @@
enum sdio_interrupt_type {
BUFFER_FULL = 0x0,
- BUFFER_AVAILABLE = 0x1,
+ BUFFER_AVAILABLE = 0x2,
FIRMWARE_ASSERT_IND = 0x3,
MSDU_PACKET_PENDING = 0x4,
UNKNOWN_INT = 0XE
@@ -42,7 +42,7 @@ enum sdio_interrupt_type {
#define PKT_MGMT_BUFF_FULL 2
#define MSDU_PKT_PENDING 3
/* Interrupt Bit Related Macros */
-#define PKT_BUFF_AVAILABLE 0
+#define PKT_BUFF_AVAILABLE 1
#define FW_ASSERT_IND 2
#define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf3
@@ -84,7 +84,7 @@ enum sdio_interrupt_type {
#define TA_HOLD_THREAD_VALUE cpu_to_le32(0xF)
#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF)
#define TA_BASE_ADDR 0x2200
-#define MISC_CFG_BASE_ADDR 0x4150
+#define MISC_CFG_BASE_ADDR 0x4105
struct receive_info {
bool buffer_full;
@@ -98,7 +98,7 @@ struct receive_info {
u32 total_sdio_msdu_pending_intr;
u32 total_sdio_unknown_intr;
u32 buf_full_counter;
- u32 buf_avilable_counter;
+ u32 buf_available_counter;
};
struct rsi_91x_sdiodev {
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 4ccfef5094e0..bdf5590ba304 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1821,7 +1821,7 @@ static const struct rt2x00_ops rt2400pci_ops = {
/*
* RT2400pci module information.
*/
-static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
+static const struct pci_device_id rt2400pci_device_table[] = {
{ PCI_DEVICE(0x1814, 0x0101) },
{ 0, }
};
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index a511cccc9f01..79f4fe65a119 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2120,7 +2120,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
/*
* RT2500pci module information.
*/
-static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
+static const struct pci_device_id rt2500pci_device_table[] = {
{ PCI_DEVICE(0x1814, 0x0201) },
{ 0, }
};
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index c17fcf272728..893c9d5f3d6f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev,
return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
}
+static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue = rt2x00dev->bcn;
+ struct queue_entry *entry;
+ int i, bcn_num = 0;
+ u64 off, reg = 0;
+ u32 bssid_dw1;
+
+ /*
+ * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
+ */
+ for (i = 0; i < queue->limit; i++) {
+ entry = &queue->entries[i];
+ if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
+ continue;
+ off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
+ reg |= off << (8 * bcn_num);
+ bcn_num++;
+ }
+
+ WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+
+ rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
+ rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
+
+ /*
+ * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
+ */
+ rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+ rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
+ bcn_num > 0 ? bcn_num - 1 : 0);
+ rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
+}
+
void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
+ __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+ /*
+ * Change global beacons settings.
+ */
+ rt2800_update_beacons_setup(rt2x00dev);
/*
* Restore beaconing state.
@@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_entry *entry)
* Clear beacon.
*/
rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
+ __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
/*
+ * Change global beacons settings.
+ */
+ rt2800_update_beacons_setup(rt2x00dev);
+ /*
* Restore beaconing state.
*/
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
@@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
conf->bssid[1] = cpu_to_le32(reg);
}
@@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
if (ret)
return ret;
- rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
- rt2800_get_beacon_offset(rt2x00dev, 0));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
- rt2800_get_beacon_offset(rt2x00dev, 1));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
- rt2800_get_beacon_offset(rt2x00dev, 2));
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
- rt2800_get_beacon_offset(rt2x00dev, 3));
- rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
-
- rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
- rt2800_get_beacon_offset(rt2x00dev, 4));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
- rt2800_get_beacon_offset(rt2x00dev, 5));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
- rt2800_get_beacon_offset(rt2x00dev, 6));
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
- rt2800_get_beacon_offset(rt2x00dev, 7));
- rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
-
rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index a5b32ca2cf0f..cc1b3cc73c5a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -400,7 +400,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
/*
* RT2800pci module information.
*/
-static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
+static const struct pci_device_id rt2800pci_device_table[] = {
{ PCI_DEVICE(0x1814, 0x0601) },
{ PCI_DEVICE(0x1814, 0x0681) },
{ PCI_DEVICE(0x1814, 0x0701) },
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 832006b5aab1..573897b8e878 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1284,6 +1284,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Arcadyan */
{ USB_DEVICE(0x043e, 0x7a12) },
{ USB_DEVICE(0x043e, 0x7a32) },
+ /* ASUS */
+ { USB_DEVICE(0x0b05, 0x17e8) },
/* Azurewave */
{ USB_DEVICE(0x13d3, 0x3329) },
{ USB_DEVICE(0x13d3, 0x3365) },
@@ -1320,6 +1322,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x057c, 0x8501) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x0241) },
+ { USB_DEVICE(0x0411, 0x0253) },
/* D-Link */
{ USB_DEVICE(0x2001, 0x3c1a) },
{ USB_DEVICE(0x2001, 0x3c21) },
@@ -1410,6 +1413,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x0053) },
{ USB_DEVICE(0x0df6, 0x0069) },
{ USB_DEVICE(0x0df6, 0x006f) },
+ { USB_DEVICE(0x0df6, 0x0078) },
/* SMC */
{ USB_DEVICE(0x083a, 0xa512) },
{ USB_DEVICE(0x083a, 0xc522) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 4fa43a2eeb73..9967a1d9f0ec 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
+ if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
+ mutex_lock(&intf->beacon_skb_mutex);
rt2x00queue_update_beacon(rt2x00dev, vif);
+ mutex_unlock(&intf->beacon_skb_mutex);
+ }
}
static void rt2x00lib_intf_scheduled(struct work_struct *work)
@@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
* never be called for USB devices.
*/
WARN_ON(rt2x00_is_usb(rt2x00dev));
- rt2x00queue_update_beacon_locked(rt2x00dev, vif);
+ rt2x00queue_update_beacon(rt2x00dev, vif);
}
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -1470,8 +1473,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
/*
* Free the driver data.
*/
- if (rt2x00dev->drv_data)
- kfree(rt2x00dev->drv_data);
+ kfree(rt2x00dev->drv_data);
}
EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 004dff9b962d..ad6e5a8d1e10 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -626,25 +626,24 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
* Start/stop beaconing.
*/
if (changes & BSS_CHANGED_BEACON_ENABLED) {
+ mutex_lock(&intf->beacon_skb_mutex);
if (!bss_conf->enable_beacon && intf->enable_beacon) {
rt2x00dev->intf_beaconing--;
intf->enable_beacon = false;
- /*
- * Clear beacon in the H/W for this vif. This is needed
- * to disable beaconing on this particular interface
- * and keep it running on other interfaces.
- */
- rt2x00queue_clear_beacon(rt2x00dev, vif);
if (rt2x00dev->intf_beaconing == 0) {
/*
* Last beaconing interface disabled
* -> stop beacon queue.
*/
- mutex_lock(&intf->beacon_skb_mutex);
rt2x00queue_stop_queue(rt2x00dev->bcn);
- mutex_unlock(&intf->beacon_skb_mutex);
}
+ /*
+ * Clear beacon in the H/W for this vif. This is needed
+ * to disable beaconing on this particular interface
+ * and keep it running on other interfaces.
+ */
+ rt2x00queue_clear_beacon(rt2x00dev, vif);
} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
rt2x00dev->intf_beaconing++;
intf->enable_beacon = true;
@@ -660,11 +659,10 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
* First beaconing interface enabled
* -> start beacon queue.
*/
- mutex_lock(&intf->beacon_skb_mutex);
rt2x00queue_start_queue(rt2x00dev->bcn);
- mutex_unlock(&intf->beacon_skb_mutex);
}
}
+ mutex_unlock(&intf->beacon_skb_mutex);
}
/*
@@ -801,6 +799,8 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
setup.tx = tx_ant;
setup.rx = rx_ant;
+ setup.rx_chain_num = 0;
+ setup.tx_chain_num = 0;
rt2x00lib_config_antenna(rt2x00dev, setup);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
index 6f236ea180aa..f0178fd4fe5f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c
@@ -119,14 +119,12 @@ static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
/*
* Allocate DMA memory for descriptor and buffer.
*/
- addr = dma_alloc_coherent(rt2x00dev->dev,
- queue->limit * queue->desc_size,
- &dma, GFP_KERNEL);
+ addr = dma_zalloc_coherent(rt2x00dev->dev,
+ queue->limit * queue->desc_size, &dma,
+ GFP_KERNEL);
if (!addr)
return -ENOMEM;
- memset(addr, 0, queue->limit * queue->desc_size);
-
/*
* Initialize all queue entries to contain valid addresses.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 5642ccceca7c..8e68f87ab13c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
if (unlikely(!intf->beacon))
return -ENOBUFS;
- mutex_lock(&intf->beacon_skb_mutex);
-
/*
* Clean up the beacon skb.
*/
@@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
if (rt2x00dev->ops->lib->clear_beacon)
rt2x00dev->ops->lib->clear_beacon(intf->beacon);
- mutex_unlock(&intf->beacon_skb_mutex);
-
return 0;
}
-int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_vif *vif)
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif)
{
struct rt2x00_intf *intf = vif_to_intf(vif);
struct skb_frame_desc *skbdesc;
@@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
}
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_vif *vif)
-{
- struct rt2x00_intf *intf = vif_to_intf(vif);
- int ret;
-
- mutex_lock(&intf->beacon_skb_mutex);
- ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
- mutex_unlock(&intf->beacon_skb_mutex);
-
- return ret;
-}
-
bool rt2x00queue_for_each_entry(struct data_queue *queue,
enum queue_index start,
enum queue_index end,
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index c48125be0e34..2233b911a1d7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -353,6 +353,7 @@ struct txentry_desc {
*/
enum queue_entry_flags {
ENTRY_BCN_ASSIGNED,
+ ENTRY_BCN_ENABLED,
ENTRY_OWNER_DEVICE_DATA,
ENTRY_DATA_PENDING,
ENTRY_DATA_IO_FAILED,
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9048a9cbe52c..819455009fe4 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3075,7 +3075,7 @@ static const struct rt2x00_ops rt61pci_ops = {
/*
* RT61pci module information.
*/
-static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
+static const struct pci_device_id rt61pci_device_table[] = {
/* RT2561s */
{ PCI_DEVICE(0x1814, 0x0301) },
/* RT2561 v2 */
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 2c1c02bafa10..026d912f516b 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -16,6 +16,7 @@
*
* based also on:
* - portions of rtl8187se Linux staging driver, Copyright Realtek corp.
+ * (available in drivers/staging/rtl8187se directory of Linux 3.14)
* - other GPL, unpublished (until now), Linux driver code,
* Copyright Larry Finger <Larry.Finger@lwfinger.net>
*
@@ -63,7 +64,7 @@ MODULE_AUTHOR("Andrea Merello <andrea.merello@gmail.com>");
MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver");
MODULE_LICENSE("GPL");
-static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = {
+static const struct pci_device_id rtl8180_table[] = {
/* rtl8187se */
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) },
@@ -209,7 +210,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
struct rtl8180_priv *priv = dev->priv;
struct rtl818x_rx_cmd_desc *cmd_desc;
unsigned int count = 32;
- u8 signal, agc, sq;
+ u8 agc, sq, signal = 1;
dma_addr_t mapping;
while (count--) {
@@ -222,12 +223,20 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
struct rtl8187se_rx_desc *desc = entry;
flags = le32_to_cpu(desc->flags);
+ /* if ownership flag is set, then we can trust the
+ * HW has written other fields. We must not trust
+ * other descriptor data read before we checked (read)
+ * the ownership flag
+ */
+ rmb();
flags2 = le32_to_cpu(desc->flags2);
tsft = le64_to_cpu(desc->tsft);
} else {
struct rtl8180_rx_desc *desc = entry;
flags = le32_to_cpu(desc->flags);
+ /* same as above */
+ rmb();
flags2 = le32_to_cpu(desc->flags2);
tsft = le64_to_cpu(desc->tsft);
}
@@ -266,18 +275,21 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.rate_idx = (flags >> 20) & 0xF;
agc = (flags2 >> 17) & 0x7F;
- if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) {
+ switch (priv->chip_family) {
+ case RTL818X_CHIP_FAMILY_RTL8185:
if (rx_status.rate_idx > 3)
- signal = 90 - clamp_t(u8, agc, 25, 90);
+ signal = -clamp_t(u8, agc, 25, 90) - 9;
else
- signal = 95 - clamp_t(u8, agc, 30, 95);
- } else if (priv->chip_family ==
- RTL818X_CHIP_FAMILY_RTL8180) {
+ signal = -clamp_t(u8, agc, 30, 95);
+ break;
+ case RTL818X_CHIP_FAMILY_RTL8180:
sq = flags2 & 0xff;
signal = priv->rf->calc_rssi(agc, sq);
- } else {
+ break;
+ case RTL818X_CHIP_FAMILY_RTL8187SE:
/* TODO: rtl8187se rssi */
signal = 10;
+ break;
}
rx_status.signal = signal;
rx_status.freq = dev->conf.chandef.chan->center_freq;
@@ -336,7 +348,6 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
info->flags |= IEEE80211_TX_STAT_ACK;
info->status.rates[0].count = (flags & 0xFF) + 1;
- info->status.rates[1].idx = -1;
ieee80211_tx_status_irqsafe(dev, skb);
if (ring->entries - skb_queue_len(&ring->queue) == 2)
@@ -528,9 +539,7 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(mapping);
- entry->flags2 = info->control.rates[1].idx >= 0 ?
- ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
- entry->retry_limit = info->control.rates[0].count;
+ entry->retry_limit = info->control.rates[0].count - 1;
/* We must be sure that tx_flags is written last because the HW
* looks at it to check if the rest of data is valid or not
@@ -852,7 +861,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) {
rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
- rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0);
} else {
rtl818x_iowrite8(priv, &priv->map->SECURITY, 0);
@@ -868,6 +877,16 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2));
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ /* fix eccessive IFS after CTS-to-self */
+ if (priv->map_pio) {
+ u8 reg;
+
+ reg = rtl818x_ioread8(priv, &priv->map->PGSELECT);
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1);
+ rtl818x_iowrite8(priv, REG_ADDR1(0xff), 0x35);
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
+ } else
+ rtl818x_iowrite8(priv, REG_ADDR1(0x1ff), 0x35);
}
if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) {
@@ -953,16 +972,13 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
else
priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc);
- priv->rx_ring = pci_alloc_consistent(priv->pdev,
- priv->rx_ring_sz * 32,
- &priv->rx_ring_dma);
-
+ priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32,
+ &priv->rx_ring_dma);
if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
wiphy_err(dev->wiphy, "Cannot allocate RX ring\n");
return -ENOMEM;
}
- memset(priv->rx_ring, 0, priv->rx_ring_sz * 32);
priv->rx_idx = 0;
for (i = 0; i < 32; i++) {
@@ -1021,14 +1037,14 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,
dma_addr_t dma;
int i;
- ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+ ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries,
+ &dma);
if (!ring || (unsigned long)ring & 0xFF) {
wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n",
prio);
return -ENOMEM;
}
- memset(ring, 0, sizeof(*ring)*entries);
priv->tx_ring[prio].desc = ring;
priv->tx_ring[prio].dma = dma;
priv->tx_ring[prio].idx = 0;
@@ -1450,9 +1466,10 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
vif_priv = (struct rtl8180_vif *)&vif->drv_priv;
if (changed & BSS_CHANGED_BSSID) {
- for (i = 0; i < ETH_ALEN; i++)
- rtl818x_iowrite8(priv, &priv->map->BSSID[i],
- info->bssid[i]);
+ rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->BSSID[0],
+ le16_to_cpu(*(__le16 *)info->bssid));
+ rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->BSSID[2],
+ le32_to_cpu(*(__le32 *)(info->bssid + 2)));
if (is_valid_ether_addr(info->bssid)) {
if (vif->type == NL80211_IFTYPE_ADHOC)
@@ -1723,17 +1740,20 @@ static int rtl8180_probe(struct pci_dev *pdev,
priv = dev->priv;
priv->pdev = pdev;
- dev->max_rates = 2;
+ dev->max_rates = 1;
SET_IEEE80211_DEV(dev, &pdev->dev);
pci_set_drvdata(pdev, dev);
+ priv->map_pio = false;
priv->map = pci_iomap(pdev, 1, mem_len);
- if (!priv->map)
+ if (!priv->map) {
priv->map = pci_iomap(pdev, 0, io_len);
+ priv->map_pio = true;
+ }
if (!priv->map) {
- printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n",
- pci_name(pdev));
+ dev_err(&pdev->dev, "Cannot map device memory/PIO\n");
+ err = -ENOMEM;
goto err_free_dev;
}
@@ -1751,8 +1771,7 @@ static int rtl8180_probe(struct pci_dev *pdev,
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SIGNAL_UNSPEC;
+ IEEE80211_HW_RX_INCLUDES_FCS;
dev->vif_data_size = sizeof(struct rtl8180_vif);
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
@@ -1783,12 +1802,19 @@ static int rtl8180_probe(struct pci_dev *pdev,
case RTL818X_TX_CONF_RTL8187SE:
chip_name = "RTL8187SE";
+ if (priv->map_pio) {
+ dev_err(&pdev->dev,
+ "MMIO failed. PIO not supported on RTL8187SE\n");
+ err = -ENOMEM;
+ goto err_iounmap;
+ }
priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE;
break;
default:
printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n",
pci_name(pdev), reg >> 25);
+ err = -ENODEV;
goto err_iounmap;
}
@@ -1809,6 +1835,11 @@ static int rtl8180_probe(struct pci_dev *pdev,
pci_try_set_mwi(pdev);
}
+ if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185)
+ dev->flags |= IEEE80211_HW_SIGNAL_DBM;
+ else
+ dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
+
rtl8180_eeprom_read(priv);
switch (priv->rf_type) {
@@ -1834,12 +1865,14 @@ static int rtl8180_probe(struct pci_dev *pdev,
default:
printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n",
pci_name(pdev), priv->rf_type);
+ err = -ENODEV;
goto err_iounmap;
}
if (!priv->rf) {
printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",
pci_name(pdev), rf_name);
+ err = -ENODEV;
goto err_iounmap;
}
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
index 291a55970d1a..e8243a44d6b6 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
+++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h
@@ -107,6 +107,7 @@ struct rtl8180_priv {
struct ieee80211_vif *vif;
/* rtl8180 driver specific */
+ bool map_pio;
spinlock_t lock;
void *rx_ring;
u8 rx_ring_sz;
diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
index 871fc3c6d559..049f4c8d98a8 100644
--- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -114,7 +114,7 @@ extern u32 btc_dbg_type[];
#define CL_SPRINTF snprintf
-#define CL_PRINTF printk
+#define CL_PRINTF(buf) printk("%s", buf)
#define BTC_PRINT(dbgtype, dbgflag, printstr, ...) \
do { \
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index b1ed6d0796f6..56e218e0469c 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -1064,7 +1064,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
"IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
return rtl_tx_agg_start(hw, sta, tid, ssn);
- break;
case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index dae55257f0e8..67d1ee6edcad 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -1092,16 +1092,14 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
u32 nextdescaddress;
int i;
- ring = pci_alloc_consistent(rtlpci->pdev,
- sizeof(*ring) * entries, &dma);
-
+ ring = pci_zalloc_consistent(rtlpci->pdev, sizeof(*ring) * entries,
+ &dma);
if (!ring || (unsigned long)ring & 0xFF) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Cannot allocate TX ring (prio = %d)\n", prio);
return -ENOMEM;
}
- memset(ring, 0, sizeof(*ring) * entries);
rtlpci->tx_ring[prio].desc = ring;
rtlpci->tx_ring[prio].dma = dma;
rtlpci->tx_ring[prio].idx = 0;
@@ -1139,10 +1137,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
for (rx_queue_idx = 0; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE;
rx_queue_idx++) {
rtlpci->rx_ring[rx_queue_idx].desc =
- pci_alloc_consistent(rtlpci->pdev,
- sizeof(*rtlpci->rx_ring[rx_queue_idx].
- desc) * rtlpci->rxringcount,
- &rtlpci->rx_ring[rx_queue_idx].dma);
+ pci_zalloc_consistent(rtlpci->pdev,
+ sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) * rtlpci->rxringcount,
+ &rtlpci->rx_ring[rx_queue_idx].dma);
if (!rtlpci->rx_ring[rx_queue_idx].desc ||
(unsigned long)rtlpci->rx_ring[rx_queue_idx].desc & 0xFF) {
@@ -1151,10 +1148,6 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
return -ENOMEM;
}
- memset(rtlpci->rx_ring[rx_queue_idx].desc, 0,
- sizeof(*rtlpci->rx_ring[rx_queue_idx].desc) *
- rtlpci->rxringcount);
-
rtlpci->rx_ring[rx_queue_idx].idx = 0;
/* If amsdu_8k is disabled, set buffersize to 4096. This
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
index b14cf5a10f44..d840ad7bdf65 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
@@ -1231,7 +1231,7 @@ static int _rtl88ee_set_media_status(struct ieee80211_hw *hw,
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0xfc) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
index a9cfa13be3a8..0f9314205526 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c
@@ -125,7 +125,6 @@ bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl88_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
return true;
- break;
default:
RT_ASSERT(false,
"rtl88_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
index 7af85cfa8f87..cd7e7a527133 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h
@@ -411,6 +411,7 @@
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
+#define MSR_MASK 0x03
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
index 842d69349a37..631b6907c17d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
@@ -364,7 +364,7 @@ static struct rtl_hal_cfg rtl88ee_hal_cfg = {
.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
};
-static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = {
+static const struct pci_device_id rtl88ee_pci_ids[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)},
{},
};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index cdecb0fd4d8e..df98a5e4729a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -1200,13 +1200,12 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Network type %d not supported!\n", type);
return 1;
- break;
}
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0xfc) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index ed703a1b3b7c..dc8460c0b32f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -375,6 +375,7 @@
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
+#define MSR_MASK 0x03
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index 12f21f4073e8..4bbdfb2df363 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -344,7 +344,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {
.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,
};
-static DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = {
+static const struct pci_device_id rtl92ce_pci_ids[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)},
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)},
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index a903c2671b4d..270cbffcac70 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -1360,7 +1360,7 @@ static int _rtl92cu_set_media_status(struct ieee80211_hw *hw,
}
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0xfc) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
index 2b08671004a0..280c3da42993 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
@@ -1128,7 +1128,7 @@ static int _rtl92de_set_media_status(struct ieee80211_hw *hw,
}
rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0xfc) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
index 3d1f0dd4e52d..592125a5f19c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -203,11 +203,12 @@ u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u32 returnvalue, originalvalue, bitshift;
- u8 dbi_direct;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
regaddr, bitmask);
if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) {
+ u8 dbi_direct = 0;
+
/* mac1 use phy0 read radio_b. */
/* mac0 use phy1 read radio_b. */
if (rtlhal->during_mac1init_radioa)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
index 7f29b8d765b3..315a298bab06 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h
@@ -369,6 +369,7 @@
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
+#define MSR_MASK 0x03
/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
/* ----------------------------------------------------- */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 380e7d4b1ccf..331b1584a1a2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -112,13 +112,10 @@ static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw)
switch (rtlphy->rf_type) {
case RF_1T1R:
return 0x11;
- break;
case RF_1T2R:
return 0x12;
- break;
case RF_2T2R:
return 0x22;
- break;
default:
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown RF type(%x)\n",
rtlphy->rf_type);
@@ -438,7 +435,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Unexpected Download step!!\n");
goto fail;
- break;
}
/* <2> Download image file */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 1c7101bcd790..00e067044c08 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1198,7 +1198,6 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Network type %d not supported!\n", type);
return 1;
- break;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
index 87f69166a7ed..662a079f76f3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
@@ -1103,13 +1103,12 @@ static int _rtl8723ae_set_media_status(struct ieee80211_hw *hw,
"Network type %d not supported!\n",
type);
return 1;
- break;
}
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0x03) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
index 64376b38708b..ce2c66fd9eee 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h
@@ -361,6 +361,7 @@
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
+#define MSR_MASK 0x03
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
index 3d555495b453..3cd286930fe0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
@@ -1197,7 +1197,7 @@ static int _rtl8723be_set_media_status(struct ieee80211_hw *hw,
}
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
- if ((bt_msr & 0x03) == MSR_AP)
+ if ((bt_msr & MSR_MASK) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c
index e4a507a756fb..4573310c707f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/pwrseqcmd.c
@@ -124,7 +124,6 @@ bool rtlbe_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
"rtlbe_hal_pwrseqcmdparsing(): "
"PWR_CMD_END\n");
return true;
- break;
default:
RT_ASSERT(false,
"rtlbe_hal_pwrseqcmdparsing(): "
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/rtlwifi/rtl8723be/reg.h
index 4c653fab8795..3006849ed439 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/reg.h
@@ -412,6 +412,7 @@
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
+#define MSR_MASK 0x03
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
index ff12bf41644b..532913c6622a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
@@ -348,7 +348,7 @@ static struct rtl_hal_cfg rtl8723be_hal_cfg = {
.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
};
-static DEFINE_PCI_DEVICE_TABLE(rtl8723be_pci_id) = {
+static const struct pci_device_id rtl8723be_pci_id[] = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xb723, rtl8723be_hal_cfg)},
{},
};
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 4e782f18ae34..38234851457e 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -991,8 +991,9 @@ out:
static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
+ struct cfg80211_scan_request *req = &hw_req->req;
struct wl1251 *wl = hw->priv;
struct sk_buff *skb;
size_t ssid_len = 0;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d50dfac91631..0bccf123831e 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1668,7 +1668,7 @@ static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
{
u8 thold;
- if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
+ if (test_bit(hlid, &wl->fw_fast_lnk_map))
thold = wl->conf.tx.fast_link_thold;
else
thold = wl->conf.tx.slow_link_thold;
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c
index 7541bd1a4a4b..0c0d5cd98514 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.c
+++ b/drivers/net/wireless/ti/wl12xx/scan.c
@@ -156,7 +156,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
cmd->params.role_id, band,
wl->scan.ssid, wl->scan.ssid_len,
wl->scan.req->ie,
- wl->scan.req->ie_len, false);
+ wl->scan.req->ie_len, NULL, 0, false);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
@@ -317,7 +317,7 @@ static void wl12xx_adjust_channels(struct wl1271_cmd_sched_scan_config *cmd,
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
struct wl1271_cmd_sched_scan_config *cfg = NULL;
struct wlcore_scan_channels *cfg_channels = NULL;
@@ -378,8 +378,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
wlvif->role_id, band,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
- ies->ie[band],
- ies->len[band], true);
+ ies->ies[band],
+ ies->len[band],
+ ies->common_ies,
+ ies->common_ie_len,
+ true);
if (ret < 0) {
wl1271_error("2.4GHz PROBE request template failed");
goto out;
@@ -392,8 +395,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
wlvif->role_id, band,
req->ssids[0].ssid,
req->ssids[0].ssid_len,
- ies->ie[band],
- ies->len[band], true);
+ ies->ies[band],
+ ies->len[band],
+ ies->common_ies,
+ ies->common_ie_len,
+ true);
if (ret < 0) {
wl1271_error("5GHz PROBE request template failed");
goto out;
@@ -449,7 +455,7 @@ out_free:
int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
int ret;
diff --git a/drivers/net/wireless/ti/wl12xx/scan.h b/drivers/net/wireless/ti/wl12xx/scan.h
index 264af7ac2785..427f9af85a00 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.h
+++ b/drivers/net/wireless/ti/wl12xx/scan.h
@@ -135,6 +135,6 @@ int wl12xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl12xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies);
+ struct ieee80211_scan_ies *ies);
void wl12xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
#endif
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c
index 7649c75cd68d..44f0b205b065 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.c
+++ b/drivers/net/wireless/ti/wl18xx/cmd.c
@@ -78,3 +78,92 @@ out_free:
out:
return ret;
}
+
+int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
+{
+ struct wl18xx_cmd_smart_config_start *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x",
+ group_bitmap);
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->group_id_bitmask = cpu_to_le32(group_bitmap);
+
+ ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send smart config start command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+out:
+ return ret;
+}
+
+int wl18xx_cmd_smart_config_stop(struct wl1271 *wl)
+{
+ struct wl1271_cmd_header *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd smart config stop");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send smart config stop command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+out:
+ return ret;
+}
+
+int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+ u8 key_len, u8 *key)
+{
+ struct wl18xx_cmd_smart_config_set_group_key *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x",
+ group_id);
+
+ if (key_len != sizeof(cmd->key)) {
+ wl1271_error("invalid group key size: %d", key_len);
+ return -E2BIG;
+ }
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->group_id = cpu_to_le32(group_id);
+ memcpy(cmd->key, key, key_len);
+
+ ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send smart config set group key cmd");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.h b/drivers/net/wireless/ti/wl18xx/cmd.h
index 6687d10899ac..92499e2dfa83 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.h
+++ b/drivers/net/wireless/ti/wl18xx/cmd.h
@@ -45,8 +45,25 @@ struct wl18xx_cmd_channel_switch {
u8 padding[2];
} __packed;
+struct wl18xx_cmd_smart_config_start {
+ struct wl1271_cmd_header header;
+
+ __le32 group_id_bitmask;
+} __packed;
+
+struct wl18xx_cmd_smart_config_set_group_key {
+ struct wl1271_cmd_header header;
+
+ __le32 group_id;
+
+ u8 key[16];
+} __packed;
+
int wl18xx_cmd_channel_switch(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
-
+int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap);
+int wl18xx_cmd_smart_config_stop(struct wl1271 *wl);
+int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+ u8 key_len, u8 *key);
#endif
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index c9199d7804c6..eb1848e08424 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -19,10 +19,12 @@
*
*/
+#include <net/genetlink.h>
#include "event.h"
#include "scan.h"
#include "../wlcore/cmd.h"
#include "../wlcore/debug.h"
+#include "../wlcore/vendor_cmd.h"
int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
bool *timeout)
@@ -45,6 +47,58 @@ int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event,
return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout);
}
+static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel,
+ u8 sync_band)
+{
+ struct sk_buff *skb;
+ enum ieee80211_band band;
+ int freq;
+
+ if (sync_band == WLCORE_BAND_5GHZ)
+ band = IEEE80211_BAND_5GHZ;
+ else
+ band = IEEE80211_BAND_2GHZ;
+
+ freq = ieee80211_channel_to_frequency(sync_channel, band);
+
+ wl1271_debug(DEBUG_EVENT,
+ "SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)",
+ freq, sync_channel, sync_band);
+ skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, 20,
+ WLCORE_VENDOR_EVENT_SC_SYNC,
+ GFP_KERNEL);
+
+ if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) {
+ kfree_skb(skb);
+ return -EMSGSIZE;
+ }
+ cfg80211_vendor_event(skb, GFP_KERNEL);
+ return 0;
+}
+
+static int wlcore_smart_config_decode_event(struct wl1271 *wl,
+ u8 ssid_len, u8 *ssid,
+ u8 pwd_len, u8 *pwd)
+{
+ struct sk_buff *skb;
+
+ wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID");
+ wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len);
+
+ skb = cfg80211_vendor_event_alloc(wl->hw->wiphy,
+ ssid_len + pwd_len + 20,
+ WLCORE_VENDOR_EVENT_SC_DECODE,
+ GFP_KERNEL);
+
+ if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) ||
+ nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) {
+ kfree_skb(skb);
+ return -EMSGSIZE;
+ }
+ cfg80211_vendor_event(skb, GFP_KERNEL);
+ return 0;
+}
+
int wl18xx_process_mailbox_events(struct wl1271 *wl)
{
struct wl18xx_event_mailbox *mbox = wl->mbox;
@@ -107,5 +161,16 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID)
wlcore_event_roc_complete(wl);
+ if (vector & SMART_CONFIG_SYNC_EVENT_ID)
+ wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel,
+ mbox->sc_sync_band);
+
+ if (vector & SMART_CONFIG_DECODE_EVENT_ID)
+ wlcore_smart_config_decode_event(wl,
+ mbox->sc_ssid_len,
+ mbox->sc_ssid,
+ mbox->sc_pwd_len,
+ mbox->sc_pwd);
+
return 0;
}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index a76e98eb8372..0680312d4943 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -38,6 +38,8 @@ enum {
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(18),
DFS_CHANNELS_CONFIG_COMPLETE_EVENT = BIT(19),
PERIODIC_SCAN_REPORT_EVENT_ID = BIT(20),
+ SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
+ SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
};
struct wl18xx_event_mailbox {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index de5b4fa5d166..7af1936719eb 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -992,7 +992,10 @@ static int wl18xx_boot(struct wl1271 *wl)
REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
INACTIVE_STA_EVENT_ID |
CHANNEL_SWITCH_COMPLETE_EVENT_ID |
- DFS_CHANNELS_CONFIG_COMPLETE_EVENT;
+ DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
+ SMART_CONFIG_SYNC_EVENT_ID |
+ SMART_CONFIG_DECODE_EVENT_ID;
+;
wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
@@ -1606,15 +1609,20 @@ static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
u8 thold;
struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
- u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+ unsigned long suspend_bitmap;
+
+ /* if we don't have the link map yet, assume they all low prio */
+ if (!status_priv)
+ return false;
/* suspended links are never high priority */
- if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+ suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+ if (test_bit(hlid, &suspend_bitmap))
return false;
/* the priority thresholds are taken from FW */
- if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) &&
- !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map))
+ if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
+ !test_bit(hlid, &wl->ap_fw_ps_map))
thold = status_priv->tx_fast_link_prio_threshold;
else
thold = status_priv->tx_slow_link_prio_threshold;
@@ -1628,12 +1636,17 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
u8 thold;
struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
- u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+ unsigned long suspend_bitmap;
+
+ /* if we don't have the link map yet, assume they all low prio */
+ if (!status_priv)
+ return true;
- if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+ suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+ if (test_bit(hlid, &suspend_bitmap))
thold = status_priv->tx_suspend_threshold;
- else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map) &&
- !test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map))
+ else if (test_bit(hlid, &wl->fw_fast_lnk_map) &&
+ !test_bit(hlid, &wl->ap_fw_ps_map))
thold = status_priv->tx_fast_stop_threshold;
else
thold = status_priv->tx_slow_stop_threshold;
@@ -1687,6 +1700,9 @@ static struct wlcore_ops wl18xx_ops = {
.convert_hwaddr = wl18xx_convert_hwaddr,
.lnk_high_prio = wl18xx_lnk_high_prio,
.lnk_low_prio = wl18xx_lnk_low_prio,
+ .smart_config_start = wl18xx_cmd_smart_config_start,
+ .smart_config_stop = wl18xx_cmd_smart_config_stop,
+ .smart_config_set_group_key = wl18xx_cmd_smart_config_set_group_key,
};
/* HT cap appropriate for wide channels in 2Ghz */
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index 2b642f8c9266..98666f235a12 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -113,6 +113,8 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
req->ssids ? req->ssids[0].ssid_len : 0,
req->ie,
req->ie_len,
+ NULL,
+ 0,
false);
if (ret < 0) {
wl1271_error("2.4GHz PROBE request template failed");
@@ -128,6 +130,8 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
req->ssids ? req->ssids[0].ssid_len : 0,
req->ie,
req->ie_len,
+ NULL,
+ 0,
false);
if (ret < 0) {
wl1271_error("5GHz PROBE request template failed");
@@ -161,7 +165,7 @@ static
int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
struct wl18xx_cmd_scan_params *cmd;
struct wlcore_scan_channels *cmd_channels = NULL;
@@ -237,8 +241,10 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd->role_id, band,
req->ssids ? req->ssids[0].ssid : NULL,
req->ssids ? req->ssids[0].ssid_len : 0,
- ies->ie[band],
+ ies->ies[band],
ies->len[band],
+ ies->common_ies,
+ ies->common_ie_len,
true);
if (ret < 0) {
wl1271_error("2.4GHz PROBE request template failed");
@@ -252,8 +258,10 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,
cmd->role_id, band,
req->ssids ? req->ssids[0].ssid : NULL,
req->ssids ? req->ssids[0].ssid_len : 0,
- ies->ie[band],
+ ies->ies[band],
ies->len[band],
+ ies->common_ies,
+ ies->common_ie_len,
true);
if (ret < 0) {
wl1271_error("5GHz PROBE request template failed");
@@ -277,7 +285,7 @@ out:
int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
return wl18xx_scan_sched_scan_config(wl, wlvif, req, ies);
}
diff --git a/drivers/net/wireless/ti/wl18xx/scan.h b/drivers/net/wireless/ti/wl18xx/scan.h
index eadee42689d1..2e636aa5dba9 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.h
+++ b/drivers/net/wireless/ti/wl18xx/scan.h
@@ -122,6 +122,6 @@ int wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl18xx_scan_completed(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int wl18xx_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies);
+ struct ieee80211_scan_ies *ies);
void wl18xx_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif);
#endif
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c b/drivers/net/wireless/ti/wl18xx/tx.c
index be1ebd55ac88..3406ffb53325 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -30,7 +30,7 @@
static
void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
- struct ieee80211_tx_rate *rate)
+ u8 band, struct ieee80211_tx_rate *rate)
{
u8 fw_rate = wl->fw_status->counters.tx_last_rate;
@@ -43,6 +43,8 @@ void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
if (fw_rate <= CONF_HW_RATE_INDEX_54MBPS) {
rate->idx = fw_rate;
+ if (band == IEEE80211_BAND_5GHZ)
+ rate->idx -= CONF_HW_RATE_INDEX_6MBPS;
rate->flags = 0;
} else {
rate->flags = IEEE80211_TX_RC_MCS;
@@ -102,7 +104,8 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
* first pass info->control.vif while it's valid, and then fill out
* the info->status structures
*/
- wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]);
+ wl18xx_get_last_tx_rate(wl, info->control.vif,
+ info->band, &info->status.rates[0]);
info->status.rates[0].count = 1; /* no data about retries */
info->status.ack_signal = -1;
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index eb7cfe817010..6a2b88030c1d 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -38,7 +38,7 @@
#define WL18XX_NUM_TX_DESCRIPTORS 32
#define WL18XX_NUM_RX_DESCRIPTORS 32
-#define WL18XX_NUM_MAC_ADDRESSES 3
+#define WL18XX_NUM_MAC_ADDRESSES 2
#define WL18XX_RX_BA_MAX_SESSIONS 13
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile
index 4f23931d7bd5..0a69c1373643 100644
--- a/drivers/net/wireless/ti/wlcore/Makefile
+++ b/drivers/net/wireless/ti/wlcore/Makefile
@@ -1,5 +1,5 @@
wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
- boot.o init.o debugfs.o scan.o sysfs.o
+ boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o
wlcore_spi-objs = spi.o
wlcore_sdio-objs = sdio.o
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 40dc30f4faaa..05604ee31224 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -372,9 +372,9 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
wl1271_tx_reset_link_queues(wl, *hlid);
wl->links[*hlid].wlvif = NULL;
- if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
- (wlvif->bss_type == BSS_TYPE_AP_BSS &&
- *hlid == wlvif->ap.bcast_hlid)) {
+ if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
+ *hlid == wlvif->ap.bcast_hlid) {
+ u32 sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
/*
* save the total freed packets in the wlvif, in case this is
* recovery or suspend
@@ -385,9 +385,11 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
* increment the initial seq number on recovery to account for
* transmitted packets that we haven't yet got in the FW status
*/
+ if (wlvif->encryption_type == KEY_GEM)
+ sqn_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
+
if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
- wlvif->total_freed_pkts +=
- WL1271_TX_SQN_POST_RECOVERY_PADDING;
+ wlvif->total_freed_pkts += sqn_padding;
}
wl->links[*hlid].total_freed_pkts = 0;
@@ -1124,7 +1126,8 @@ out:
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 role_id, u8 band,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len, bool sched_scan)
+ const u8 *ie0, size_t ie0_len, const u8 *ie1,
+ size_t ie1_len, bool sched_scan)
{
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
struct sk_buff *skb;
@@ -1136,13 +1139,15 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
- ie_len);
+ ie0_len + ie1_len);
if (!skb) {
ret = -ENOMEM;
goto out;
}
- if (ie_len)
- memcpy(skb_put(skb, ie_len), ie, ie_len);
+ if (ie0_len)
+ memcpy(skb_put(skb, ie0_len), ie0, ie0_len);
+ if (ie1_len)
+ memcpy(skb_put(skb, ie1_len), ie1, ie1_len);
if (sched_scan &&
(wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index b084830a61cf..ca6a28b03f8f 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -64,7 +64,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
u8 role_id, u8 band,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len, bool sched_scan);
+ const u8 *ie, size_t ie_len, const u8 *common_ie,
+ size_t common_ie_len, bool sched_scan);
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct sk_buff *skb);
@@ -169,6 +170,9 @@ enum wl1271_commands {
/* start of 18xx specific commands */
CMD_DFS_CHANNEL_CONFIG = 60,
+ CMD_SMART_CONFIG_START = 61,
+ CMD_SMART_CONFIG_STOP = 62,
+ CMD_SMART_CONFIG_SET_GROUP_KEY = 63,
MAX_COMMAND_ID = 0xFFFF,
};
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 89893c717025..0be21f62fcb0 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -496,7 +496,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_INT(sg_enabled);
DRIVER_STATE_PRINT_INT(enable_11a);
DRIVER_STATE_PRINT_INT(noise);
- DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
+ DRIVER_STATE_PRINT_LHEX(ap_fw_ps_map);
DRIVER_STATE_PRINT_LHEX(ap_ps_map);
DRIVER_STATE_PRINT_HEX(quirks);
DRIVER_STATE_PRINT_HEX(irq);
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 1555ff970050..aa9f82c72296 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -260,4 +260,31 @@ wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid,
return wl->ops->lnk_low_prio(wl, hlid, lnk);
}
+static inline int
+wlcore_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
+{
+ if (!wl->ops->smart_config_start)
+ return -EINVAL;
+
+ return wl->ops->smart_config_start(wl, group_bitmap);
+}
+
+static inline int
+wlcore_smart_config_stop(struct wl1271 *wl)
+{
+ if (!wl->ops->smart_config_stop)
+ return -EINVAL;
+
+ return wl->ops->smart_config_stop(wl);
+}
+
+static inline int
+wlcore_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
+ u8 key_len, u8 *key)
+{
+ if (!wl->ops->smart_config_set_group_key)
+ return -EINVAL;
+
+ return wl->ops->smart_config_set_group_key(wl, group_id, key_len, key);
+}
#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 3d6028e62750..575c8f6d4009 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -37,6 +37,7 @@
#include "init.h"
#include "debugfs.h"
#include "testmode.h"
+#include "vendor_cmd.h"
#include "scan.h"
#include "hw_ops.h"
#include "sysfs.h"
@@ -332,7 +333,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
{
bool fw_ps;
- fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
/*
* Wake up from high level PS if the STA is asleep with too little
@@ -359,13 +360,13 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct wl_fw_status *status)
{
- u32 cur_fw_ps_map;
+ unsigned long cur_fw_ps_map;
u8 hlid;
cur_fw_ps_map = status->link_ps_bitmap;
if (wl->ap_fw_ps_map != cur_fw_ps_map) {
wl1271_debug(DEBUG_PSM,
- "link ps prev 0x%x cur 0x%x changed 0x%x",
+ "link ps prev 0x%lx cur 0x%lx changed 0x%lx",
wl->ap_fw_ps_map, cur_fw_ps_map,
wl->ap_fw_ps_map ^ cur_fw_ps_map);
@@ -898,6 +899,44 @@ out:
wlcore_set_partition(wl, &old_part);
}
+static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ u8 hlid, struct ieee80211_sta *sta)
+{
+ struct wl1271_station *wl_sta;
+ u32 sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING;
+
+ wl_sta = (void *)sta->drv_priv;
+ wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
+
+ /*
+ * increment the initial seq number on recovery to account for
+ * transmitted packets that we haven't yet got in the FW status
+ */
+ if (wlvif->encryption_type == KEY_GEM)
+ sqn_recovery_padding = WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM;
+
+ if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
+ wl_sta->total_freed_pkts += sqn_recovery_padding;
+}
+
+static void wlcore_save_freed_pkts_addr(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ u8 hlid, const u8 *addr)
+{
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+ if (WARN_ON(hlid == WL12XX_INVALID_LINK_ID ||
+ is_zero_ether_addr(addr)))
+ return;
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(vif, addr);
+ if (sta)
+ wlcore_save_freed_pkts(wl, wlvif, hlid, sta);
+ rcu_read_unlock();
+}
+
static void wlcore_print_recovery(struct wl1271 *wl)
{
u32 pc = 0;
@@ -961,6 +1000,13 @@ static void wl1271_recovery_work(struct work_struct *work)
wlvif = list_first_entry(&wl->wlvif_list,
struct wl12xx_vif, list);
vif = wl12xx_wlvif_to_vif(wlvif);
+
+ if (wlvif->bss_type == BSS_TYPE_STA_BSS &&
+ test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
+ wlcore_save_freed_pkts_addr(wl, wlvif, wlvif->sta.hlid,
+ vif->bss_conf.bssid);
+ }
+
__wl1271_op_remove_interface(wl, vif, false);
}
@@ -3540,8 +3586,9 @@ out:
static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
- struct cfg80211_scan_request *req)
+ struct ieee80211_scan_request *hw_req)
{
+ struct cfg80211_scan_request *req = &hw_req->req;
struct wl1271 *wl = hw->priv;
int ret;
u8 *ssid = NULL;
@@ -3636,7 +3683,7 @@ out:
static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies)
+ struct ieee80211_scan_ies *ies)
{
struct wl1271 *wl = hw->priv;
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
@@ -4702,36 +4749,18 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
{
- struct wl1271_station *wl_sta;
- struct ieee80211_sta *sta;
- struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
-
if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
return;
clear_bit(hlid, wlvif->ap.sta_hlid_map);
__clear_bit(hlid, &wl->ap_ps_map);
- __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ __clear_bit(hlid, &wl->ap_fw_ps_map);
/*
* save the last used PN in the private part of iee80211_sta,
* in case of recovery/suspend
*/
- rcu_read_lock();
- sta = ieee80211_find_sta(vif, wl->links[hlid].addr);
- if (sta) {
- wl_sta = (void *)sta->drv_priv;
- wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts;
-
- /*
- * increment the initial seq number on recovery to account for
- * transmitted packets that we haven't yet got in the FW status
- */
- if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
- wl_sta->total_freed_pkts +=
- WL1271_TX_SQN_POST_RECOVERY_PADDING;
- }
- rcu_read_unlock();
+ wlcore_save_freed_pkts_addr(wl, wlvif, hlid, wl->links[hlid].addr);
wl12xx_free_link(wl, wlvif, &hlid);
wl->active_sta_count--;
@@ -4914,6 +4943,21 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
clear_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags);
}
+ /* save seq number on disassoc (suspend) */
+ if (is_sta &&
+ old_state == IEEE80211_STA_ASSOC &&
+ new_state == IEEE80211_STA_AUTH) {
+ wlcore_save_freed_pkts(wl, wlvif, wlvif->sta.hlid, sta);
+ wlvif->total_freed_pkts = 0;
+ }
+
+ /* restore seq number on assoc (resume) */
+ if (is_sta &&
+ old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC) {
+ wlvif->total_freed_pkts = wl_sta->total_freed_pkts;
+ }
+
/* clear ROCs on failure or authorization */
if (is_sta &&
(new_state == IEEE80211_STA_AUTHORIZED ||
@@ -5148,6 +5192,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
if (unlikely(wl->state == WLCORE_STATE_OFF)) {
wl12xx_for_each_wlvif_sta(wl, wlvif) {
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ continue;
+
ieee80211_chswitch_done(vif, false);
}
goto out;
@@ -5163,6 +5211,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
wl12xx_for_each_wlvif_sta(wl, wlvif) {
unsigned long delay_usec;
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ continue;
+
ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
if (ret)
goto out_sleep;
@@ -5618,7 +5669,7 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic)
memcpy(&wl->addresses[idx], &wl->addresses[0],
sizeof(wl->addresses[0]));
/* LAA bit */
- wl->addresses[idx].addr[2] |= BIT(1);
+ wl->addresses[idx].addr[0] |= BIT(1);
}
wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES;
@@ -5763,7 +5814,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
sizeof(struct ieee80211_header);
- wl->hw->wiphy->max_remain_on_channel_duration = 5000;
+ wl->hw->wiphy->max_remain_on_channel_duration = 30000;
wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
@@ -5832,6 +5883,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->iface_combinations = wl->iface_combinations;
wl->hw->wiphy->n_iface_combinations = wl->n_iface_combinations;
+ /* register vendor commands */
+ wlcore_set_vendor_commands(wl->hw->wiphy);
+
SET_IEEE80211_DEV(wl->hw, wl->dev);
wl->hw->sta_data_size = sizeof(struct wl1271_station);
diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h
index a6ab24b5c0f9..4dadd0c62cde 100644
--- a/drivers/net/wireless/ti/wlcore/scan.h
+++ b/drivers/net/wireless/ti/wlcore/scan.h
@@ -37,7 +37,7 @@ void wl1271_scan_complete_work(struct work_struct *work);
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies);
+ struct ieee80211_scan_ies *ies);
int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wlcore_scan_sched_scan_results(struct wl1271 *wl);
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 40b43115f835..f0ac36139bcc 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -126,7 +126,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl,
if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
return;
- fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+ fw_ps = test_bit(hlid, &wl->ap_fw_ps_map);
tx_pkts = wl->links[hlid].allocated_pkts;
/*
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
new file mode 100644
index 000000000000..ad86a48dcfcb
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
@@ -0,0 +1,197 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2014 Texas Instruments. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <net/mac80211.h>
+#include <net/netlink.h>
+
+#include "wlcore.h"
+#include "debug.h"
+#include "ps.h"
+#include "hw_ops.h"
+#include "vendor_cmd.h"
+
+static const
+struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
+ [WLCORE_VENDOR_ATTR_FREQ] = { .type = NLA_U32 },
+ [WLCORE_VENDOR_ATTR_GROUP_ID] = { .type = NLA_U32 },
+ [WLCORE_VENDOR_ATTR_GROUP_KEY] = { .type = NLA_U32,
+ .len = WLAN_MAX_KEY_LEN },
+};
+
+static int
+wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct wl1271 *wl = hw->priv;
+ struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
+
+ if (!data)
+ return -EINVAL;
+
+ ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
+ wlcore_vendor_attr_policy);
+ if (ret)
+ return ret;
+
+ if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
+ return -EINVAL;
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_smart_config_start(wl,
+ nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+
+ return 0;
+}
+
+static int
+wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct wl1271 *wl = hw->priv;
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_smart_config_stop(wl);
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static int
+wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct wl1271 *wl = hw->priv;
+ struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
+ int ret;
+
+ wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
+
+ if (!data)
+ return -EINVAL;
+
+ ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
+ wlcore_vendor_attr_policy);
+ if (ret)
+ return ret;
+
+ if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
+ !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
+ return -EINVAL;
+
+ mutex_lock(&wl->mutex);
+
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_smart_config_set_group_key(wl,
+ nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
+ nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
+ nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
+
+ wl1271_ps_elp_sleep(wl);
+out:
+ mutex_unlock(&wl->mutex);
+
+ return ret;
+}
+
+static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
+ {
+ .info = {
+ .vendor_id = TI_OUI,
+ .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlcore_vendor_cmd_smart_config_start,
+ },
+ {
+ .info = {
+ .vendor_id = TI_OUI,
+ .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlcore_vendor_cmd_smart_config_stop,
+ },
+ {
+ .info = {
+ .vendor_id = TI_OUI,
+ .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
+ },
+ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlcore_vendor_cmd_smart_config_set_group_key,
+ },
+};
+
+static const struct nl80211_vendor_cmd_info wlcore_vendor_events[] = {
+ {
+ .vendor_id = TI_OUI,
+ .subcmd = WLCORE_VENDOR_EVENT_SC_SYNC,
+ },
+ {
+ .vendor_id = TI_OUI,
+ .subcmd = WLCORE_VENDOR_EVENT_SC_DECODE,
+ },
+};
+
+void wlcore_set_vendor_commands(struct wiphy *wiphy)
+{
+ wiphy->vendor_commands = wlcore_vendor_commands;
+ wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
+ wiphy->vendor_events = wlcore_vendor_events;
+ wiphy->n_vendor_events = ARRAY_SIZE(wlcore_vendor_events);
+}
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.h b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
new file mode 100644
index 000000000000..6e0c15e30f03
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2014 Texas Instruments. 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 __WLCORE_VENDOR_H__
+#define __WLCORE_VENDOR_H__
+
+#ifdef __KERNEL__
+void wlcore_set_vendor_commands(struct wiphy *wiphy);
+#endif
+
+#define TI_OUI 0x080028
+
+enum wlcore_vendor_commands {
+ WLCORE_VENDOR_CMD_SMART_CONFIG_START,
+ WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
+ WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
+
+ NUM_WLCORE_VENDOR_CMD,
+ MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1
+};
+
+enum wlcore_vendor_attributes {
+ WLCORE_VENDOR_ATTR_FREQ,
+ WLCORE_VENDOR_ATTR_PSK,
+ WLCORE_VENDOR_ATTR_SSID,
+ WLCORE_VENDOR_ATTR_GROUP_ID,
+ WLCORE_VENDOR_ATTR_GROUP_KEY,
+
+ NUM_WLCORE_VENDOR_ATTR,
+ MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1
+};
+
+enum wlcore_vendor_events {
+ WLCORE_VENDOR_EVENT_SC_SYNC,
+ WLCORE_VENDOR_EVENT_SC_DECODE,
+};
+
+#endif /* __WLCORE_VENDOR_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 95a54504f0cc..df78cf12ef15 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -95,7 +95,7 @@ struct wlcore_ops {
int (*scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int (*sched_scan_start)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct cfg80211_sched_scan_request *req,
- struct ieee80211_sched_scan_ies *ies);
+ struct ieee80211_scan_ies *ies);
void (*sched_scan_stop)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem);
int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd,
@@ -117,6 +117,10 @@ struct wlcore_ops {
struct wl1271_link *lnk);
bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
struct wl1271_link *lnk);
+ int (*smart_config_start)(struct wl1271 *wl, u32 group_bitmap);
+ int (*smart_config_stop)(struct wl1271 *wl);
+ int (*smart_config_set_group_key)(struct wl1271 *wl, u16 group_id,
+ u8 key_len, u8 *key);
};
enum wlcore_partitions {
@@ -384,10 +388,10 @@ struct wl1271 {
int active_link_count;
/* Fast/slow links bitmap according to FW */
- u32 fw_fast_lnk_map;
+ unsigned long fw_fast_lnk_map;
/* AP-mode - a bitmap of links currently in PS mode according to FW */
- u32 ap_fw_ps_map;
+ unsigned long ap_fw_ps_map;
/* AP-mode - a bitmap of links currently in PS mode in mac80211 */
unsigned long ap_ps_map;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index c2c34a84ff3d..0e52556044d9 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -45,6 +45,9 @@
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff
+/* Use smaller padding for GEM, as some APs have issues when it's too big */
+#define WL1271_TX_SQN_POST_RECOVERY_PADDING_GEM 0x20
+
#define WL1271_CIPHER_SUITE_GEM 0x00147201
@@ -324,6 +327,7 @@ struct wl1271_station {
* total freed FW packets on the link to the STA - used for tracking the
* AES/TKIP PN across recoveries. Re-initialized each time from the
* wl1271_station structure.
+ * Used in both AP and STA mode.
*/
u64 total_freed_pkts;
};
@@ -460,21 +464,19 @@ struct wl12xx_vif {
struct delayed_work pending_auth_complete_work;
/*
+ * total freed FW packets on the link.
+ * For STA this holds the PN of the link to the AP.
+ * For AP this holds the PN of the broadcast link.
+ */
+ u64 total_freed_pkts;
+
+ /*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
* should be declared in this struct.
*/
struct {
u8 persistent[0];
-
- /*
- * total freed FW packets on the link - used for
- * storing the AES/TKIP PN during recovery, as this
- * structure is not zeroed out.
- * For STA this holds the PN of the link to the AP.
- * For AP this holds the PN of the broadcast link.
- */
- u64 total_freed_pkts;
};
};
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
index 96c8e1de0879..95920581860a 100644
--- a/drivers/net/wireless/zd1211rw/Kconfig
+++ b/drivers/net/wireless/zd1211rw/Kconfig
@@ -3,11 +3,11 @@ config ZD1211RW
depends on USB && MAC80211
select FW_LOADER
---help---
- This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
+ This is a driver for the ZyDAS ZD1211/ZD1211B wireless
chip, present in many USB-wireless adapters.
Device firmware is required alongside this driver. You can download
- the firmware distribution from http://zd1211.ath.cx/get-firmware
+ the firmware distribution from http://sf.net/projects/zd1211/files/
config ZD1211RW_DEBUG
bool "ZyDAS ZD1211 debugging"
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 2532ce85d718..d4eb8d2e9cb7 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -44,6 +44,7 @@
#include <xen/interface/grant_table.h>
#include <xen/grant_table.h>
#include <xen/xenbus.h>
+#include <linux/debugfs.h>
typedef unsigned int pending_ring_idx_t;
#define INVALID_PENDING_RING_IDX (~0U)
@@ -164,6 +165,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
u16 dealloc_ring[MAX_PENDING_REQS];
struct task_struct *dealloc_task;
wait_queue_head_t dealloc_wq;
+ atomic_t inflight_packets;
/* Use kthread for guest RX */
struct task_struct *task;
@@ -175,9 +177,9 @@ struct xenvif_queue { /* Per-queue data for xenvif */
struct xen_netif_rx_back_ring rx;
struct sk_buff_head rx_queue;
RING_IDX rx_last_skb_slots;
- bool rx_queue_purge;
+ unsigned long status;
- struct timer_list wake_queue;
+ struct timer_list rx_stalled;
struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS];
@@ -197,6 +199,20 @@ struct xenvif_queue { /* Per-queue data for xenvif */
struct xenvif_stats stats;
};
+enum state_bit_shift {
+ /* This bit marks that the vif is connected */
+ VIF_STATUS_CONNECTED,
+ /* This bit signals the RX thread that queuing was stopped (in
+ * start_xmit), and either the timer fired or an RX interrupt came
+ */
+ QUEUE_STATUS_RX_PURGE_EVENT,
+ /* This bit tells the interrupt handler that this queue was the reason
+ * for the carrier off, so it should kick the thread. Only queues which
+ * brought it down can turn on the carrier.
+ */
+ QUEUE_STATUS_RX_STALLED
+};
+
struct xenvif {
/* Unique identifier for this interface. */
domid_t domid;
@@ -219,11 +235,16 @@ struct xenvif {
* frontend is rogue.
*/
bool disabled;
+ unsigned long status;
/* Queues */
struct xenvif_queue *queues;
unsigned int num_queues; /* active queues, resource allocated */
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *xenvif_dbg_root;
+#endif
+
/* Miscellaneous private stuff. */
struct net_device *dev;
};
@@ -297,10 +318,20 @@ static inline pending_ring_idx_t nr_pending_reqs(struct xenvif_queue *queue)
/* Callback from stack when TX packet can be released */
void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success);
+irqreturn_t xenvif_interrupt(int irq, void *dev_id);
+
extern bool separate_tx_rx_irq;
extern unsigned int rx_drain_timeout_msecs;
extern unsigned int rx_drain_timeout_jiffies;
extern unsigned int xenvif_max_queues;
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *xen_netback_dbg_root;
+#endif
+
+void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
+ struct sk_buff *skb);
+void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue);
+
#endif /* __XEN_NETBACK__COMMON_H__ */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 9e97c7ca0ddd..e29e15dca86e 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -43,6 +43,23 @@
#define XENVIF_QUEUE_LENGTH 32
#define XENVIF_NAPI_WEIGHT 64
+/* This function is used to set SKBTX_DEV_ZEROCOPY as well as
+ * increasing the inflight counter. We need to increase the inflight
+ * counter because core driver calls into xenvif_zerocopy_callback
+ * which calls xenvif_skb_zerocopy_complete.
+ */
+void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue,
+ struct sk_buff *skb)
+{
+ skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ atomic_inc(&queue->inflight_packets);
+}
+
+void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
+{
+ atomic_dec(&queue->inflight_packets);
+}
+
static inline void xenvif_stop_queue(struct xenvif_queue *queue)
{
struct net_device *dev = queue->vif->dev;
@@ -55,7 +72,8 @@ static inline void xenvif_stop_queue(struct xenvif_queue *queue)
int xenvif_schedulable(struct xenvif *vif)
{
- return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
+ return netif_running(vif->dev) &&
+ test_bit(VIF_STATUS_CONNECTED, &vif->status);
}
static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
@@ -96,13 +114,22 @@ int xenvif_poll(struct napi_struct *napi, int budget)
static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
{
struct xenvif_queue *queue = dev_id;
+ struct netdev_queue *net_queue =
+ netdev_get_tx_queue(queue->vif->dev, queue->id);
+ /* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR
+ * the carrier went down and this queue was previously blocked
+ */
+ if (unlikely(netif_tx_queue_stopped(net_queue) ||
+ (!netif_carrier_ok(queue->vif->dev) &&
+ test_bit(QUEUE_STATUS_RX_STALLED, &queue->status))))
+ set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
xenvif_kick_thread(queue);
return IRQ_HANDLED;
}
-static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+irqreturn_t xenvif_interrupt(int irq, void *dev_id)
{
xenvif_tx_interrupt(irq, dev_id);
xenvif_rx_interrupt(irq, dev_id);
@@ -124,16 +151,14 @@ void xenvif_wake_queue(struct xenvif_queue *queue)
netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
}
-/* Callback to wake the queue and drain it on timeout */
-static void xenvif_wake_queue_callback(unsigned long data)
+/* Callback to wake the queue's thread and turn the carrier off on timeout */
+static void xenvif_rx_stalled(unsigned long data)
{
struct xenvif_queue *queue = (struct xenvif_queue *)data;
if (xenvif_queue_stopped(queue)) {
- netdev_err(queue->vif->dev, "draining TX queue\n");
- queue->rx_queue_purge = true;
+ set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
xenvif_kick_thread(queue);
- xenvif_wake_queue(queue);
}
}
@@ -182,11 +207,11 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
* drain.
*/
if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) {
- queue->wake_queue.function = xenvif_wake_queue_callback;
- queue->wake_queue.data = (unsigned long)queue;
+ queue->rx_stalled.function = xenvif_rx_stalled;
+ queue->rx_stalled.data = (unsigned long)queue;
xenvif_stop_queue(queue);
- mod_timer(&queue->wake_queue,
- jiffies + rx_drain_timeout_jiffies);
+ mod_timer(&queue->rx_stalled,
+ jiffies + rx_drain_timeout_jiffies);
}
skb_queue_tail(&queue->rx_queue, skb);
@@ -267,7 +292,7 @@ static void xenvif_down(struct xenvif *vif)
static int xenvif_open(struct net_device *dev)
{
struct xenvif *vif = netdev_priv(dev);
- if (netif_carrier_ok(dev))
+ if (test_bit(VIF_STATUS_CONNECTED, &vif->status))
xenvif_up(vif);
netif_tx_start_all_queues(dev);
return 0;
@@ -276,7 +301,7 @@ static int xenvif_open(struct net_device *dev)
static int xenvif_close(struct net_device *dev)
{
struct xenvif *vif = netdev_priv(dev);
- if (netif_carrier_ok(dev))
+ if (test_bit(VIF_STATUS_CONNECTED, &vif->status))
xenvif_down(vif);
netif_tx_stop_all_queues(dev);
return 0;
@@ -418,8 +443,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
* When the guest selects the desired number, it will be updated
* via netif_set_real_num_*_queues().
*/
- dev = alloc_netdev_mq(sizeof(struct xenvif), name, ether_setup,
- xenvif_max_queues);
+ dev = alloc_netdev_mq(sizeof(struct xenvif), name, NET_NAME_UNKNOWN,
+ ether_setup, xenvif_max_queues);
if (dev == NULL) {
pr_warn("Could not allocate netdev for %s\n", name);
return ERR_PTR(-ENOMEM);
@@ -514,10 +539,7 @@ int xenvif_init_queue(struct xenvif_queue *queue)
queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE;
}
- init_timer(&queue->wake_queue);
-
- netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
- XENVIF_NAPI_WEIGHT);
+ init_timer(&queue->rx_stalled);
return 0;
}
@@ -528,6 +550,7 @@ void xenvif_carrier_on(struct xenvif *vif)
if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
dev_set_mtu(vif->dev, ETH_DATA_LEN);
netdev_update_features(vif->dev);
+ set_bit(VIF_STATUS_CONNECTED, &vif->status);
netif_carrier_on(vif->dev);
if (netif_running(vif->dev))
xenvif_up(vif);
@@ -551,6 +574,7 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
init_waitqueue_head(&queue->wq);
init_waitqueue_head(&queue->dealloc_wq);
+ atomic_set(&queue->inflight_packets, 0);
if (tx_evtchn == rx_evtchn) {
/* feature-split-event-channels == 0 */
@@ -605,6 +629,9 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
wake_up_process(queue->task);
wake_up_process(queue->dealloc_task);
+ netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
+ XENVIF_NAPI_WEIGHT);
+
return 0;
err_rx_unbind:
@@ -625,29 +652,12 @@ void xenvif_carrier_off(struct xenvif *vif)
struct net_device *dev = vif->dev;
rtnl_lock();
- netif_carrier_off(dev); /* discard queued packets */
- if (netif_running(dev))
- xenvif_down(vif);
- rtnl_unlock();
-}
-
-static void xenvif_wait_unmap_timeout(struct xenvif_queue *queue,
- unsigned int worst_case_skb_lifetime)
-{
- int i, unmap_timeout = 0;
-
- for (i = 0; i < MAX_PENDING_REQS; ++i) {
- if (queue->grant_tx_handle[i] != NETBACK_INVALID_HANDLE) {
- unmap_timeout++;
- schedule_timeout(msecs_to_jiffies(1000));
- if (unmap_timeout > worst_case_skb_lifetime &&
- net_ratelimit())
- netdev_err(queue->vif->dev,
- "Page still granted! Index: %x\n",
- i);
- i = -1;
- }
+ if (test_and_clear_bit(VIF_STATUS_CONNECTED, &vif->status)) {
+ netif_carrier_off(dev); /* discard queued packets */
+ if (netif_running(dev))
+ xenvif_down(vif);
}
+ rtnl_unlock();
}
void xenvif_disconnect(struct xenvif *vif)
@@ -656,14 +666,15 @@ void xenvif_disconnect(struct xenvif *vif)
unsigned int num_queues = vif->num_queues;
unsigned int queue_index;
- if (netif_carrier_ok(vif->dev))
- xenvif_carrier_off(vif);
+ xenvif_carrier_off(vif);
for (queue_index = 0; queue_index < num_queues; ++queue_index) {
queue = &vif->queues[queue_index];
+ netif_napi_del(&queue->napi);
+
if (queue->task) {
- del_timer_sync(&queue->wake_queue);
+ del_timer_sync(&queue->rx_stalled);
kthread_stop(queue->task);
queue->task = NULL;
}
@@ -694,7 +705,6 @@ void xenvif_disconnect(struct xenvif *vif)
void xenvif_deinit_queue(struct xenvif_queue *queue)
{
free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages);
- netif_napi_del(&queue->napi);
}
void xenvif_free(struct xenvif *vif)
@@ -702,25 +712,11 @@ void xenvif_free(struct xenvif *vif)
struct xenvif_queue *queue = NULL;
unsigned int num_queues = vif->num_queues;
unsigned int queue_index;
- /* Here we want to avoid timeout messages if an skb can be legitimately
- * stuck somewhere else. Realistically this could be an another vif's
- * internal or QDisc queue. That another vif also has this
- * rx_drain_timeout_msecs timeout, but the timer only ditches the
- * internal queue. After that, the QDisc queue can put in worst case
- * XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS skbs into that another vif's
- * internal queue, so we need several rounds of such timeouts until we
- * can be sure that no another vif should have skb's from us. We are
- * not sending more skb's, so newly stuck packets are not interesting
- * for us here.
- */
- unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000) *
- DIV_ROUND_UP(XENVIF_QUEUE_LENGTH, (XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS));
unregister_netdev(vif->dev);
for (queue_index = 0; queue_index < num_queues; ++queue_index) {
queue = &vif->queues[queue_index];
- xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime);
xenvif_deinit_queue(queue);
}
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index c65b636bcab9..08f65996534c 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1525,10 +1525,12 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s
/* remove traces of mapped pages and frag_list */
skb_frag_list_init(skb);
uarg = skb_shinfo(skb)->destructor_arg;
+ /* increase inflight counter to offset decrement in callback */
+ atomic_inc(&queue->inflight_packets);
uarg->callback(uarg, true);
skb_shinfo(skb)->destructor_arg = NULL;
- skb_shinfo(nskb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ xenvif_skb_zerocopy_prepare(queue, nskb);
kfree_skb(nskb);
return 0;
@@ -1589,7 +1591,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
if (net_ratelimit())
netdev_err(queue->vif->dev,
"Not enough memory to consolidate frag_list!\n");
- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ xenvif_skb_zerocopy_prepare(queue, skb);
kfree_skb(skb);
continue;
}
@@ -1609,7 +1611,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
"Can't setup checksum in net_tx_action\n");
/* We have to set this flag to trigger the callback */
if (skb_shinfo(skb)->destructor_arg)
- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ xenvif_skb_zerocopy_prepare(queue, skb);
kfree_skb(skb);
continue;
}
@@ -1641,7 +1643,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
* skb. E.g. the __pskb_pull_tail earlier can do such thing.
*/
if (skb_shinfo(skb)->destructor_arg) {
- skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ xenvif_skb_zerocopy_prepare(queue, skb);
queue->stats.tx_zerocopy_sent++;
}
@@ -1681,6 +1683,7 @@ void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success)
queue->stats.tx_zerocopy_success++;
else
queue->stats.tx_zerocopy_fail++;
+ xenvif_skb_zerocopy_complete(queue);
}
static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue)
@@ -1869,8 +1872,7 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
static inline int rx_work_todo(struct xenvif_queue *queue)
{
return (!skb_queue_empty(&queue->rx_queue) &&
- xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots)) ||
- queue->rx_queue_purge;
+ xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots));
}
static inline int tx_work_todo(struct xenvif_queue *queue)
@@ -1935,6 +1937,75 @@ static void xenvif_start_queue(struct xenvif_queue *queue)
xenvif_wake_queue(queue);
}
+/* Only called from the queue's thread, it handles the situation when the guest
+ * doesn't post enough requests on the receiving ring.
+ * First xenvif_start_xmit disables QDisc and start a timer, and then either the
+ * timer fires, or the guest send an interrupt after posting new request. If it
+ * is the timer, the carrier is turned off here.
+ * */
+static void xenvif_rx_purge_event(struct xenvif_queue *queue)
+{
+ /* Either the last unsuccesful skb or at least 1 slot should fit */
+ int needed = queue->rx_last_skb_slots ?
+ queue->rx_last_skb_slots : 1;
+
+ /* It is assumed that if the guest post new slots after this, the RX
+ * interrupt will set the QUEUE_STATUS_RX_PURGE_EVENT bit and wake up
+ * the thread again
+ */
+ set_bit(QUEUE_STATUS_RX_STALLED, &queue->status);
+ if (!xenvif_rx_ring_slots_available(queue, needed)) {
+ rtnl_lock();
+ if (netif_carrier_ok(queue->vif->dev)) {
+ /* Timer fired and there are still no slots. Turn off
+ * everything except the interrupts
+ */
+ netif_carrier_off(queue->vif->dev);
+ skb_queue_purge(&queue->rx_queue);
+ queue->rx_last_skb_slots = 0;
+ if (net_ratelimit())
+ netdev_err(queue->vif->dev, "Carrier off due to lack of guest response on queue %d\n", queue->id);
+ } else {
+ /* Probably an another queue already turned the carrier
+ * off, make sure nothing is stucked in the internal
+ * queue of this queue
+ */
+ skb_queue_purge(&queue->rx_queue);
+ queue->rx_last_skb_slots = 0;
+ }
+ rtnl_unlock();
+ } else if (!netif_carrier_ok(queue->vif->dev)) {
+ unsigned int num_queues = queue->vif->num_queues;
+ unsigned int i;
+ /* The carrier was down, but an interrupt kicked
+ * the thread again after new requests were
+ * posted
+ */
+ clear_bit(QUEUE_STATUS_RX_STALLED,
+ &queue->status);
+ rtnl_lock();
+ netif_carrier_on(queue->vif->dev);
+ netif_tx_wake_all_queues(queue->vif->dev);
+ rtnl_unlock();
+
+ for (i = 0; i < num_queues; i++) {
+ struct xenvif_queue *temp = &queue->vif->queues[i];
+
+ xenvif_napi_schedule_or_enable_events(temp);
+ }
+ if (net_ratelimit())
+ netdev_err(queue->vif->dev, "Carrier on again\n");
+ } else {
+ /* Queuing were stopped, but the guest posted
+ * new requests and sent an interrupt
+ */
+ clear_bit(QUEUE_STATUS_RX_STALLED,
+ &queue->status);
+ del_timer_sync(&queue->rx_stalled);
+ xenvif_start_queue(queue);
+ }
+}
+
int xenvif_kthread_guest_rx(void *data)
{
struct xenvif_queue *queue = data;
@@ -1944,8 +2015,12 @@ int xenvif_kthread_guest_rx(void *data)
wait_event_interruptible(queue->wq,
rx_work_todo(queue) ||
queue->vif->disabled ||
+ test_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status) ||
kthread_should_stop());
+ if (kthread_should_stop())
+ break;
+
/* This frontend is found to be rogue, disable it in
* kthread context. Currently this is only set when
* netback finds out frontend sends malformed packet,
@@ -1953,26 +2028,29 @@ int xenvif_kthread_guest_rx(void *data)
* context so we defer it here, if this thread is
* associated with queue 0.
*/
- if (unlikely(queue->vif->disabled && netif_carrier_ok(queue->vif->dev) && queue->id == 0))
+ if (unlikely(queue->vif->disabled && queue->id == 0)) {
xenvif_carrier_off(queue->vif);
-
- if (kthread_should_stop())
- break;
-
- if (queue->rx_queue_purge) {
+ } else if (unlikely(queue->vif->disabled)) {
+ /* kthread_stop() would be called upon this thread soon,
+ * be a bit proactive
+ */
+ skb_queue_purge(&queue->rx_queue);
+ queue->rx_last_skb_slots = 0;
+ } else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT,
+ &queue->status))) {
+ xenvif_rx_purge_event(queue);
+ } else if (!netif_carrier_ok(queue->vif->dev)) {
+ /* Another queue stalled and turned the carrier off, so
+ * purge the internal queue of queues which were not
+ * blocked
+ */
skb_queue_purge(&queue->rx_queue);
- queue->rx_queue_purge = false;
+ queue->rx_last_skb_slots = 0;
}
if (!skb_queue_empty(&queue->rx_queue))
xenvif_rx_action(queue);
- if (skb_queue_empty(&queue->rx_queue) &&
- xenvif_queue_stopped(queue)) {
- del_timer_sync(&queue->wake_queue);
- xenvif_start_queue(queue);
- }
-
cond_resched();
}
@@ -1983,15 +2061,24 @@ int xenvif_kthread_guest_rx(void *data)
return 0;
}
+static bool xenvif_dealloc_kthread_should_stop(struct xenvif_queue *queue)
+{
+ /* Dealloc thread must remain running until all inflight
+ * packets complete.
+ */
+ return kthread_should_stop() &&
+ !atomic_read(&queue->inflight_packets);
+}
+
int xenvif_dealloc_kthread(void *data)
{
struct xenvif_queue *queue = data;
- while (!kthread_should_stop()) {
+ for (;;) {
wait_event_interruptible(queue->dealloc_wq,
tx_dealloc_work_todo(queue) ||
- kthread_should_stop());
- if (kthread_should_stop())
+ xenvif_dealloc_kthread_should_stop(queue));
+ if (xenvif_dealloc_kthread_should_stop(queue))
break;
xenvif_tx_dealloc_action(queue);
@@ -2027,6 +2114,13 @@ static int __init netback_init(void)
rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs);
+#ifdef CONFIG_DEBUG_FS
+ xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL);
+ if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+ pr_warn("Init of debugfs returned %ld!\n",
+ PTR_ERR(xen_netback_dbg_root));
+#endif /* CONFIG_DEBUG_FS */
+
return 0;
failed_init:
@@ -2037,6 +2131,10 @@ module_init(netback_init);
static void __exit netback_fini(void)
{
+#ifdef CONFIG_DEBUG_FS
+ if (!IS_ERR_OR_NULL(xen_netback_dbg_root))
+ debugfs_remove_recursive(xen_netback_dbg_root);
+#endif /* CONFIG_DEBUG_FS */
xenvif_xenbus_fini();
}
module_exit(netback_fini);
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 3d85acd84bad..9c47b897b6d2 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -44,6 +44,177 @@ static void unregister_hotplug_status_watch(struct backend_info *be);
static void set_backend_state(struct backend_info *be,
enum xenbus_state state);
+#ifdef CONFIG_DEBUG_FS
+struct dentry *xen_netback_dbg_root = NULL;
+
+static int xenvif_read_io_ring(struct seq_file *m, void *v)
+{
+ struct xenvif_queue *queue = m->private;
+ struct xen_netif_tx_back_ring *tx_ring = &queue->tx;
+ struct xen_netif_rx_back_ring *rx_ring = &queue->rx;
+
+ if (tx_ring->sring) {
+ struct xen_netif_tx_sring *sring = tx_ring->sring;
+
+ seq_printf(m, "Queue %d\nTX: nr_ents %u\n", queue->id,
+ tx_ring->nr_ents);
+ seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
+ sring->req_prod,
+ sring->req_prod - sring->rsp_prod,
+ tx_ring->req_cons,
+ tx_ring->req_cons - sring->rsp_prod,
+ sring->req_event,
+ sring->req_event - sring->rsp_prod);
+ seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n",
+ sring->rsp_prod,
+ tx_ring->rsp_prod_pvt,
+ tx_ring->rsp_prod_pvt - sring->rsp_prod,
+ sring->rsp_event,
+ sring->rsp_event - sring->rsp_prod);
+ seq_printf(m, "pending prod %u pending cons %u nr_pending_reqs %u\n",
+ queue->pending_prod,
+ queue->pending_cons,
+ nr_pending_reqs(queue));
+ seq_printf(m, "dealloc prod %u dealloc cons %u dealloc_queue %u\n\n",
+ queue->dealloc_prod,
+ queue->dealloc_cons,
+ queue->dealloc_prod - queue->dealloc_cons);
+ }
+
+ if (rx_ring->sring) {
+ struct xen_netif_rx_sring *sring = rx_ring->sring;
+
+ seq_printf(m, "RX: nr_ents %u\n", rx_ring->nr_ents);
+ seq_printf(m, "req prod %u (%d) cons %u (%d) event %u (%d)\n",
+ sring->req_prod,
+ sring->req_prod - sring->rsp_prod,
+ rx_ring->req_cons,
+ rx_ring->req_cons - sring->rsp_prod,
+ sring->req_event,
+ sring->req_event - sring->rsp_prod);
+ seq_printf(m, "rsp prod %u (base) pvt %u (%d) event %u (%d)\n\n",
+ sring->rsp_prod,
+ rx_ring->rsp_prod_pvt,
+ rx_ring->rsp_prod_pvt - sring->rsp_prod,
+ sring->rsp_event,
+ sring->rsp_event - sring->rsp_prod);
+ }
+
+ seq_printf(m, "NAPI state: %lx NAPI weight: %d TX queue len %u\n"
+ "Credit timer_pending: %d, credit: %lu, usec: %lu\n"
+ "remaining: %lu, expires: %lu, now: %lu\n",
+ queue->napi.state, queue->napi.weight,
+ skb_queue_len(&queue->tx_queue),
+ timer_pending(&queue->credit_timeout),
+ queue->credit_bytes,
+ queue->credit_usec,
+ queue->remaining_credit,
+ queue->credit_timeout.expires,
+ jiffies);
+
+ return 0;
+}
+
+#define XENVIF_KICK_STR "kick"
+#define BUFFER_SIZE 32
+
+static ssize_t
+xenvif_write_io_ring(struct file *filp, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct xenvif_queue *queue =
+ ((struct seq_file *)filp->private_data)->private;
+ int len;
+ char write[BUFFER_SIZE];
+
+ /* don't allow partial writes and check the length */
+ if (*ppos != 0)
+ return 0;
+ if (count >= sizeof(write))
+ return -ENOSPC;
+
+ len = simple_write_to_buffer(write,
+ sizeof(write) - 1,
+ ppos,
+ buf,
+ count);
+ if (len < 0)
+ return len;
+
+ write[len] = '\0';
+
+ if (!strncmp(write, XENVIF_KICK_STR, sizeof(XENVIF_KICK_STR) - 1))
+ xenvif_interrupt(0, (void *)queue);
+ else {
+ pr_warn("Unknown command to io_ring_q%d. Available: kick\n",
+ queue->id);
+ count = -EINVAL;
+ }
+ return count;
+}
+
+static int xenvif_dump_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+ void *queue = NULL;
+
+ if (inode->i_private)
+ queue = inode->i_private;
+ ret = single_open(filp, xenvif_read_io_ring, queue);
+ filp->f_mode |= FMODE_PWRITE;
+ return ret;
+}
+
+static const struct file_operations xenvif_dbg_io_ring_ops_fops = {
+ .owner = THIS_MODULE,
+ .open = xenvif_dump_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = xenvif_write_io_ring,
+};
+
+static void xenvif_debugfs_addif(struct xenvif *vif)
+{
+ struct dentry *pfile;
+ int i;
+
+ if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+ return;
+
+ vif->xenvif_dbg_root = debugfs_create_dir(vif->dev->name,
+ xen_netback_dbg_root);
+ if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root)) {
+ for (i = 0; i < vif->num_queues; ++i) {
+ char filename[sizeof("io_ring_q") + 4];
+
+ snprintf(filename, sizeof(filename), "io_ring_q%d", i);
+ pfile = debugfs_create_file(filename,
+ S_IRUSR | S_IWUSR,
+ vif->xenvif_dbg_root,
+ &vif->queues[i],
+ &xenvif_dbg_io_ring_ops_fops);
+ if (IS_ERR_OR_NULL(pfile))
+ pr_warn("Creation of io_ring file returned %ld!\n",
+ PTR_ERR(pfile));
+ }
+ } else
+ netdev_warn(vif->dev,
+ "Creation of vif debugfs dir returned %ld!\n",
+ PTR_ERR(vif->xenvif_dbg_root));
+}
+
+static void xenvif_debugfs_delif(struct xenvif *vif)
+{
+ if (IS_ERR_OR_NULL(xen_netback_dbg_root))
+ return;
+
+ if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root))
+ debugfs_remove_recursive(vif->xenvif_dbg_root);
+ vif->xenvif_dbg_root = NULL;
+}
+#endif /* CONFIG_DEBUG_FS */
+
static int netback_remove(struct xenbus_device *dev)
{
struct backend_info *be = dev_get_drvdata(&dev->dev);
@@ -246,8 +417,12 @@ static void backend_create_xenvif(struct backend_info *be)
static void backend_disconnect(struct backend_info *be)
{
- if (be->vif)
+ if (be->vif) {
+#ifdef CONFIG_DEBUG_FS
+ xenvif_debugfs_delif(be->vif);
+#endif /* CONFIG_DEBUG_FS */
xenvif_disconnect(be->vif);
+ }
}
static void backend_connect(struct backend_info *be)
@@ -562,6 +737,10 @@ static void connect(struct backend_info *be)
}
}
+#ifdef CONFIG_DEBUG_FS
+ xenvif_debugfs_addif(be->vif);
+#endif /* CONFIG_DEBUG_FS */
+
/* Initialisation completed, tell core driver the number of
* active queues.
*/
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 055222bae6e4..ca82f545ec2c 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -628,9 +628,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
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;
+ net_dbg_ratelimited("xennet: skb rides the rocket: %d slots, %d bytes\n",
+ slots, skb->len);
+ if (skb_linearize(skb))
+ goto drop;
}
spin_lock_irqsave(&queue->tx_lock, flags);
@@ -1196,22 +1197,6 @@ static void xennet_release_rx_bufs(struct netfront_queue *queue)
spin_unlock_bh(&queue->rx_lock);
}
-static void xennet_uninit(struct net_device *dev)
-{
- struct netfront_info *np = netdev_priv(dev);
- unsigned int num_queues = dev->real_num_tx_queues;
- struct netfront_queue *queue;
- unsigned int i;
-
- for (i = 0; i < num_queues; ++i) {
- queue = &np->queues[i];
- xennet_release_tx_bufs(queue);
- xennet_release_rx_bufs(queue);
- gnttab_free_grant_references(queue->gref_tx_head);
- gnttab_free_grant_references(queue->gref_rx_head);
- }
-}
-
static netdev_features_t xennet_fix_features(struct net_device *dev,
netdev_features_t features)
{
@@ -1313,7 +1298,6 @@ static void xennet_poll_controller(struct net_device *dev)
static const struct net_device_ops xennet_netdev_ops = {
.ndo_open = xennet_open,
- .ndo_uninit = xennet_uninit,
.ndo_stop = xennet_close,
.ndo_start_xmit = xennet_start_xmit,
.ndo_change_mtu = xennet_change_mtu,
@@ -1455,6 +1439,11 @@ static void xennet_disconnect_backend(struct netfront_info *info)
napi_synchronize(&queue->napi);
+ xennet_release_tx_bufs(queue);
+ xennet_release_rx_bufs(queue);
+ gnttab_free_grant_references(queue->gref_tx_head);
+ gnttab_free_grant_references(queue->gref_rx_head);
+
/* End access and free the pages */
xennet_end_access(queue->tx_ring_ref, queue->tx.sring);
xennet_end_access(queue->rx_ring_ref, queue->rx.sring);
@@ -1827,8 +1816,8 @@ static int xennet_create_queues(struct netfront_info *info,
ret = xennet_init_queue(queue);
if (ret < 0) {
- dev_warn(&info->netdev->dev, "only created %d queues\n",
- num_queues);
+ dev_warn(&info->netdev->dev,
+ "only created %d queues\n", i);
num_queues = i;
break;
}
@@ -2001,7 +1990,7 @@ abort_transaction_no_dev_fatal:
info->queues = NULL;
rtnl_lock();
netif_set_real_num_tx_queues(info->netdev, 0);
- rtnl_lock();
+ rtnl_unlock();
out:
return err;
}
@@ -2010,10 +1999,7 @@ static int xennet_connect(struct net_device *dev)
{
struct netfront_info *np = netdev_priv(dev);
unsigned int num_queues = 0;
- int i, requeue_idx, err;
- struct sk_buff *skb;
- grant_ref_t ref;
- struct xen_netif_rx_request *req;
+ int err;
unsigned int feature_rx_copy;
unsigned int j = 0;
struct netfront_queue *queue = NULL;
@@ -2040,47 +2026,8 @@ static int xennet_connect(struct net_device *dev)
netdev_update_features(dev);
rtnl_unlock();
- /* By now, the queue structures have been set up */
- for (j = 0; j < num_queues; ++j) {
- queue = &np->queues[j];
-
- /* Step 1: Discard all pending TX packet fragments. */
- spin_lock_irq(&queue->tx_lock);
- xennet_release_tx_bufs(queue);
- spin_unlock_irq(&queue->tx_lock);
-
- /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
- spin_lock_bh(&queue->rx_lock);
-
- for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
- skb_frag_t *frag;
- const struct page *page;
- if (!queue->rx_skbs[i])
- continue;
-
- skb = queue->rx_skbs[requeue_idx] = xennet_get_rx_skb(queue, i);
- ref = queue->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(queue, i);
- req = RING_GET_REQUEST(&queue->rx, requeue_idx);
-
- frag = &skb_shinfo(skb)->frags[0];
- page = skb_frag_page(frag);
- gnttab_grant_foreign_access_ref(
- ref, queue->info->xbdev->otherend_id,
- pfn_to_mfn(page_to_pfn(page)),
- 0);
- req->gref = ref;
- req->id = requeue_idx;
-
- requeue_idx++;
- }
-
- queue->rx.req_prod_pvt = requeue_idx;
-
- spin_unlock_bh(&queue->rx_lock);
- }
-
/*
- * Step 3: All public and private state should now be sane. Get
+ * All public and private state should now be sane. Get
* ready to start sending and receiving packets and give the driver
* domain a kick because we've probably just requeued some
* packets.
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 26c66a126551..7929fac13e1c 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -72,5 +72,5 @@ source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
source "drivers/nfc/nfcmrvl/Kconfig"
source "drivers/nfc/st21nfca/Kconfig"
-
+source "drivers/nfc/st21nfcb/Kconfig"
endmenu
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 23225b0287fd..6b23a2c6e34a 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_NFC_SIM) += nfcsim.o
obj-$(CONFIG_NFC_PORT100) += port100.o
obj-$(CONFIG_NFC_MRVL) += nfcmrvl/
obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
-obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
+obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/
+obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb/
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile
index 038ed093a119..db7a38ae05f7 100644
--- a/drivers/nfc/st21nfca/Makefile
+++ b/drivers/nfc/st21nfca/Makefile
@@ -4,5 +4,5 @@
st21nfca_i2c-objs = i2c.o
-obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o
+obj-$(CONFIG_NFC_ST21NFCA) += st21nfca.o st21nfca_dep.o
obj-$(CONFIG_NFC_ST21NFCA_I2C) += st21nfca_i2c.o
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 3f954ed86d98..ff31939978ae 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -93,7 +93,7 @@ struct st21nfca_i2c_phy {
int hard_fault;
struct mutex phy_lock;
};
-static u8 len_seq[] = { 13, 24, 15, 29 };
+static u8 len_seq[] = { 16, 24, 12, 29 };
static u16 wait_tab[] = { 2, 3, 5, 15, 20, 40};
#define I2C_DUMP_SKB(info, skb) \
@@ -397,12 +397,11 @@ static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy,
* The first read sequence does not start with SOF.
* Data is corrupeted so we drop it.
*/
- if (!phy->current_read_len && buf[0] != ST21NFCA_SOF_EOF) {
+ if (!phy->current_read_len && !IS_START_OF_FRAME(buf)) {
skb_trim(skb, 0);
phy->current_read_len = 0;
return -EIO;
- } else if (phy->current_read_len &&
- IS_START_OF_FRAME(buf)) {
+ } else if (phy->current_read_len && IS_START_OF_FRAME(buf)) {
/*
* Previous frame transmission was interrupted and
* the frame got repeated.
@@ -487,6 +486,8 @@ static irqreturn_t st21nfca_hci_irq_thread_fn(int irq, void *phy_id)
*/
nfc_hci_recv_frame(phy->hdev, phy->pending_skb);
phy->crc_trials = 0;
+ } else {
+ kfree_skb(phy->pending_skb);
}
phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL);
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index 51e0f00b3a4f..a902b0551c86 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -22,6 +22,7 @@
#include <net/nfc/llc.h>
#include "st21nfca.h"
+#include "st21nfca_dep.h"
#define DRIVER_DESC "HCI NFC driver for ST21NFCA"
@@ -53,6 +54,7 @@
#define ST21NFCA_DM_PIPE_CREATED 0x02
#define ST21NFCA_DM_PIPE_OPEN 0x04
#define ST21NFCA_DM_RF_ACTIVE 0x80
+#define ST21NFCA_DM_DISCONNECT 0x30
#define ST21NFCA_DM_IS_PIPE_OPEN(p) \
((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
@@ -72,6 +74,7 @@ static struct nfc_hci_gate st21nfca_gates[] = {
{ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE},
{ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE},
{ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE},
+ {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE},
};
struct st21nfca_pipe_info {
@@ -299,6 +302,9 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
u32 im_protocols, u32 tm_protocols)
{
int r;
+ u32 pol_req;
+ u8 param[19];
+ struct sk_buff *datarate_skb;
pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
__func__, im_protocols, tm_protocols);
@@ -331,6 +337,31 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
ST21NFCA_RF_READER_F_GATE);
if (r < 0)
return r;
+ } else {
+ hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
+ &hdev->gb_len);
+
+ if (hdev->gb == NULL || hdev->gb_len == 0) {
+ im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+ tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
+ }
+
+ param[0] = ST21NFCA_RF_READER_F_DATARATE_106 |
+ ST21NFCA_RF_READER_F_DATARATE_212 |
+ ST21NFCA_RF_READER_F_DATARATE_424;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_RF_READER_F_DATARATE,
+ param, 1);
+ if (r < 0)
+ return r;
+
+ pol_req =
+ be32_to_cpu(ST21NFCA_RF_READER_F_POL_REQ_DEFAULT);
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_RF_READER_F_POL_REQ,
+ (u8 *) &pol_req, 4);
+ if (r < 0)
+ return r;
}
if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) {
@@ -353,9 +384,104 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev,
nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
NFC_HCI_EVT_END_OPERATION, NULL, 0);
}
+
+ if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_DATARATE,
+ &datarate_skb);
+ if (r < 0)
+ return r;
+
+ /* Configure the maximum supported datarate to 424Kbps */
+ if (datarate_skb->len > 0 &&
+ datarate_skb->data[0] !=
+ ST21NFCA_RF_CARD_F_DATARATE_212_424) {
+ param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_DATARATE,
+ param, 1);
+ if (r < 0)
+ return r;
+ }
+
+ /*
+ * Configure sens_res
+ *
+ * NFC Forum Digital Spec Table 7:
+ * NFCID1 size: triple (10 bytes)
+ */
+ param[0] = 0x00;
+ param[1] = 0x08;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_SENS_RES, param, 2);
+ if (r < 0)
+ return r;
+
+ /*
+ * Configure sel_res
+ *
+ * NFC Forum Digistal Spec Table 17:
+ * b3 set to 0b (value b7-b6):
+ * - 10b: Configured for NFC-DEP Protocol
+ */
+ param[0] = 0x40;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_SEL_RES, param, 1);
+ if (r < 0)
+ return r;
+
+ /* Configure NFCID1 Random uid */
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_NFCID1, NULL, 0);
+ if (r < 0)
+ return r;
+
+ /* Configure NFCID2_LIST */
+ /* System Code */
+ param[0] = 0x00;
+ param[1] = 0x00;
+ /* NFCID2 */
+ param[2] = 0x01;
+ param[3] = 0xfe;
+ param[4] = 'S';
+ param[5] = 'T';
+ param[6] = 'M';
+ param[7] = 'i';
+ param[8] = 'c';
+ param[9] = 'r';
+ /* 8 byte Pad bytes used for polling respone frame */
+
+ /*
+ * Configuration byte:
+ * - bit 0: define the default NFCID2 entry used when the
+ * system code is equal to 'FFFF'
+ * - bit 1: use a random value for lowest 6 bytes of
+ * NFCID2 value
+ * - bit 2: ignore polling request frame if request code
+ * is equal to '01'
+ * - Other bits are RFU
+ */
+ param[18] = 0x01;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_NFCID2_LIST, param,
+ 19);
+ if (r < 0)
+ return r;
+
+ param[0] = 0x02;
+ r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_RF_CARD_F_MODE, param, 1);
+ }
+
return r;
}
+static void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev)
+{
+ nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
static int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa)
{
int r;
@@ -451,6 +577,26 @@ exit:
return r;
}
+static int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev,
+ struct nfc_target *target, u8 comm_mode,
+ u8 *gb, size_t gb_len)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ info->dep_info.idx = target->idx;
+ return st21nfca_im_send_atr_req(hdev, gb, gb_len);
+}
+
+static int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ info->state = ST21NFCA_ST_READY;
+
+ return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
+ ST21NFCA_DM_DISCONNECT, NULL, 0, NULL);
+}
+
static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target)
{
@@ -505,6 +651,69 @@ static int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
return 0;
}
+static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
+ u8 gate,
+ struct nfc_target *target)
+{
+ int r;
+ struct sk_buff *nfcid2_skb = NULL, *nfcid1_skb;
+
+ if (gate == ST21NFCA_RF_READER_F_GATE) {
+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_RF_READER_F_NFCID2, &nfcid2_skb);
+ if (r < 0)
+ goto exit;
+
+ if (nfcid2_skb->len > NFC_SENSF_RES_MAXSIZE) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ /*
+ * - After the recepton of polling response for type F frame
+ * at 212 or 424 Kbit/s, NFCID2 registry parameters will be
+ * updated.
+ * - After the reception of SEL_RES with NFCIP-1 compliant bit
+ * set for type A frame NFCID1 will be updated
+ */
+ if (nfcid2_skb->len > 0) {
+ /* P2P in type F */
+ memcpy(target->sensf_res, nfcid2_skb->data,
+ nfcid2_skb->len);
+ target->sensf_res_len = nfcid2_skb->len;
+ /* NFC Forum Digital Protocol Table 44 */
+ if (target->sensf_res[0] == 0x01 &&
+ target->sensf_res[1] == 0xfe)
+ target->supported_protocols =
+ NFC_PROTO_NFC_DEP_MASK;
+ else
+ target->supported_protocols =
+ NFC_PROTO_FELICA_MASK;
+ } else {
+ /* P2P in type A */
+ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_RF_READER_F_NFCID1,
+ &nfcid1_skb);
+ if (r < 0)
+ goto exit;
+
+ if (nfcid1_skb->len > NFC_NFCID1_MAXSIZE) {
+ r = -EPROTO;
+ goto exit;
+ }
+ memcpy(target->sensf_res, nfcid1_skb->data,
+ nfcid1_skb->len);
+ target->sensf_res_len = nfcid1_skb->len;
+ target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+ }
+ target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE;
+ }
+ r = 1;
+exit:
+ kfree_skb(nfcid2_skb);
+ return r;
+}
+
#define ST21NFCA_CB_TYPE_READER_ISO15693 1
static void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb,
int err)
@@ -541,6 +750,9 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev,
switch (target->hci_reader_gate) {
case ST21NFCA_RF_READER_F_GATE:
+ if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK)
+ return st21nfca_im_send_dep_req(hdev, skb);
+
*skb_push(skb, 1) = 0x1a;
return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
ST21NFCA_WR_XCHG_DATA, skb->data,
@@ -569,6 +781,11 @@ static int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev,
}
}
+static int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+ return st21nfca_tm_send_dep_res(hdev, skb);
+}
+
static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
struct nfc_target *target)
{
@@ -594,6 +811,50 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
}
}
+/*
+ * Returns:
+ * <= 0: driver handled the event, skb consumed
+ * 1: driver does not handle the event, please do standard processing
+ */
+static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
+ u8 event, struct sk_buff *skb)
+{
+ int r;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ pr_debug("hci event: %d\n", event);
+
+ switch (event) {
+ case ST21NFCA_EVT_CARD_ACTIVATED:
+ if (gate == ST21NFCA_RF_CARD_F_GATE)
+ info->dep_info.curr_nfc_dep_pni = 0;
+ break;
+ case ST21NFCA_EVT_CARD_DEACTIVATED:
+ break;
+ case ST21NFCA_EVT_FIELD_ON:
+ break;
+ case ST21NFCA_EVT_FIELD_OFF:
+ break;
+ case ST21NFCA_EVT_SEND_DATA:
+ if (gate == ST21NFCA_RF_CARD_F_GATE) {
+ r = st21nfca_tm_event_send_data(hdev, skb, gate);
+ if (r < 0)
+ goto exit;
+ return 0;
+ } else {
+ info->dep_info.curr_nfc_dep_pni = 0;
+ return 1;
+ }
+ break;
+ default:
+ return 1;
+ }
+ kfree_skb(skb);
+ return 0;
+exit:
+ return r;
+}
+
static struct nfc_hci_ops st21nfca_hci_ops = {
.open = st21nfca_hci_open,
.close = st21nfca_hci_close,
@@ -601,9 +862,15 @@ static struct nfc_hci_ops st21nfca_hci_ops = {
.hci_ready = st21nfca_hci_ready,
.xmit = st21nfca_hci_xmit,
.start_poll = st21nfca_hci_start_poll,
+ .stop_poll = st21nfca_hci_stop_poll,
+ .dep_link_up = st21nfca_hci_dep_link_up,
+ .dep_link_down = st21nfca_hci_dep_link_down,
.target_from_gate = st21nfca_hci_target_from_gate,
+ .complete_target_discovered = st21nfca_hci_complete_target_discovered,
.im_transceive = st21nfca_hci_im_transceive,
+ .tm_send = st21nfca_hci_tm_send,
.check_presence = st21nfca_hci_check_presence,
+ .event_received = st21nfca_hci_event_received,
};
int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
@@ -648,7 +915,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
NFC_PROTO_FELICA_MASK |
NFC_PROTO_ISO14443_MASK |
NFC_PROTO_ISO14443_B_MASK |
- NFC_PROTO_ISO15693_MASK;
+ NFC_PROTO_ISO15693_MASK |
+ NFC_PROTO_NFC_DEP_MASK;
set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);
@@ -671,6 +939,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops,
goto err_regdev;
*hdev = info->hdev;
+ st21nfca_dep_init(info->hdev);
return 0;
@@ -688,6 +957,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev)
{
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+ st21nfca_dep_deinit(hdev);
nfc_hci_unregister_device(hdev);
nfc_hci_free_device(hdev);
kfree(info);
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 334cd90bcc8c..96fe5a62dc0d 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -19,6 +19,8 @@
#include <net/nfc/hci.h>
+#include "st21nfca_dep.h"
+
#define HCI_MODE 0
/* framing in HCI mode */
@@ -73,7 +75,8 @@ struct st21nfca_hci_info {
data_exchange_cb_t async_cb;
void *async_cb_context;
-} __packed;
+ struct st21nfca_dep_info dep_info;
+};
/* Reader RF commands */
#define ST21NFCA_WR_XCHG_DATA 0x10
@@ -83,5 +86,26 @@ struct st21nfca_hci_info {
#define ST21NFCA_RF_READER_F_DATARATE_106 0x01
#define ST21NFCA_RF_READER_F_DATARATE_212 0x02
#define ST21NFCA_RF_READER_F_DATARATE_424 0x04
+#define ST21NFCA_RF_READER_F_POL_REQ 0x02
+#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000
+#define ST21NFCA_RF_READER_F_NFCID2 0x03
+#define ST21NFCA_RF_READER_F_NFCID1 0x04
+#define ST21NFCA_RF_READER_F_SENS_RES 0x05
+
+#define ST21NFCA_RF_CARD_F_GATE 0x24
+#define ST21NFCA_RF_CARD_F_MODE 0x01
+#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04
+#define ST21NFCA_RF_CARD_F_NFCID1 0x05
+#define ST21NFCA_RF_CARD_F_SENS_RES 0x06
+#define ST21NFCA_RF_CARD_F_SEL_RES 0x07
+#define ST21NFCA_RF_CARD_F_DATARATE 0x08
+#define ST21NFCA_RF_CARD_F_DATARATE_106 0x00
+#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01
+
+#define ST21NFCA_EVT_SEND_DATA 0x10
+#define ST21NFCA_EVT_FIELD_ON 0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
+#define ST21NFCA_EVT_FIELD_OFF 0x14
#endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c
new file mode 100644
index 000000000000..b2d9957b57f8
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_dep.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <net/nfc/hci.h>
+
+#include "st21nfca.h"
+#include "st21nfca_dep.h"
+
+#define ST21NFCA_NFCIP1_INITIATOR 0x00
+#define ST21NFCA_NFCIP1_REQ 0xd4
+#define ST21NFCA_NFCIP1_RES 0xd5
+#define ST21NFCA_NFCIP1_ATR_REQ 0x00
+#define ST21NFCA_NFCIP1_ATR_RES 0x01
+#define ST21NFCA_NFCIP1_PSL_REQ 0x04
+#define ST21NFCA_NFCIP1_PSL_RES 0x05
+#define ST21NFCA_NFCIP1_DEP_REQ 0x06
+#define ST21NFCA_NFCIP1_DEP_RES 0x07
+
+#define ST21NFCA_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
+#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+ ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
+#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
+#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10
+
+#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
+ ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT)
+
+#define ST21NFCA_NFC_DEP_PFB_I_PDU 0x00
+#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU 0x40
+#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
+
+#define ST21NFCA_ATR_REQ_MIN_SIZE 17
+#define ST21NFCA_ATR_REQ_MAX_SIZE 65
+#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define ST21NFCA_GB_BIT 0x02
+
+#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
+#define ST21NFCA_EVT_READER_F_BITRATE 0x13
+#define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
+#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07)
+#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4)
+#define ST21NFCA_CARD_BITRATE_212 0x01
+#define ST21NFCA_CARD_BITRATE_424 0x02
+
+#define ST21NFCA_DEFAULT_TIMEOUT 0x0a
+
+
+#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \
+ __LINE__, req)
+
+struct st21nfca_atr_req {
+ u8 length;
+ u8 cmd0;
+ u8 cmd1;
+ u8 nfcid3[NFC_NFCID3_MAXSIZE];
+ u8 did;
+ u8 bsi;
+ u8 bri;
+ u8 ppi;
+ u8 gbi[0];
+} __packed;
+
+struct st21nfca_atr_res {
+ u8 length;
+ u8 cmd0;
+ u8 cmd1;
+ u8 nfcid3[NFC_NFCID3_MAXSIZE];
+ u8 did;
+ u8 bsi;
+ u8 bri;
+ u8 to;
+ u8 ppi;
+ u8 gbi[0];
+} __packed;
+
+struct st21nfca_psl_req {
+ u8 length;
+ u8 cmd0;
+ u8 cmd1;
+ u8 did;
+ u8 brs;
+ u8 fsl;
+} __packed;
+
+struct st21nfca_psl_res {
+ u8 length;
+ u8 cmd0;
+ u8 cmd1;
+ u8 did;
+} __packed;
+
+struct st21nfca_dep_req_res {
+ u8 length;
+ u8 cmd0;
+ u8 cmd1;
+ u8 pfb;
+ u8 did;
+ u8 nad;
+} __packed;
+
+static void st21nfca_tx_work(struct work_struct *work)
+{
+ struct st21nfca_hci_info *info = container_of(work,
+ struct st21nfca_hci_info,
+ dep_info.tx_work);
+
+ struct nfc_dev *dev;
+ struct sk_buff *skb;
+ if (info) {
+ dev = info->hdev->ndev;
+ skb = info->dep_info.tx_pending;
+
+ device_lock(&dev->dev);
+
+ nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_WR_XCHG_DATA,
+ skb->data, skb->len,
+ info->async_cb, info);
+ device_unlock(&dev->dev);
+ kfree_skb(skb);
+ }
+}
+
+static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
+ struct sk_buff *skb)
+{
+ info->dep_info.tx_pending = skb;
+ schedule_work(&info->dep_info.tx_work);
+}
+
+static int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev,
+ struct st21nfca_atr_req *atr_req)
+{
+ struct st21nfca_atr_res *atr_res;
+ struct sk_buff *skb;
+ size_t gb_len;
+ int r;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ gb_len = atr_req->length - sizeof(struct st21nfca_atr_req);
+ skb = alloc_skb(atr_req->length + 1, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_put(skb, sizeof(struct st21nfca_atr_res));
+
+ atr_res = (struct st21nfca_atr_res *)skb->data;
+ memset(atr_res, 0, sizeof(struct st21nfca_atr_res));
+
+ atr_res->length = atr_req->length + 1;
+ atr_res->cmd0 = ST21NFCA_NFCIP1_RES;
+ atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES;
+
+ memcpy(atr_res->nfcid3, atr_req->nfcid3, 6);
+ atr_res->bsi = 0x00;
+ atr_res->bri = 0x00;
+ atr_res->to = ST21NFCA_DEFAULT_TIMEOUT;
+ atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+
+ if (gb_len) {
+ skb_put(skb, gb_len);
+
+ atr_res->ppi |= ST21NFCA_GB_BIT;
+ memcpy(atr_res->gbi, atr_req->gbi, gb_len);
+ r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
+ gb_len);
+ if (r < 0)
+ return r;
+ }
+
+ info->dep_info.curr_nfc_dep_pni = 0;
+
+ return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+}
+
+static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct st21nfca_atr_req *atr_req;
+ size_t gb_len;
+ int r;
+
+ skb_trim(skb, skb->len - 1);
+ if (IS_ERR(skb)) {
+ r = PTR_ERR(skb);
+ goto exit;
+ }
+
+ if (!skb->len) {
+ r = -EIO;
+ goto exit;
+ }
+
+ if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) {
+ r = -EPROTO;
+ goto exit;
+ }
+
+ atr_req = (struct st21nfca_atr_req *)skb->data;
+
+ r = st21nfca_tm_send_atr_res(hdev, atr_req);
+ if (r)
+ goto exit;
+
+ gb_len = skb->len - sizeof(struct st21nfca_atr_req);
+
+ r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
+ NFC_COMM_PASSIVE, atr_req->gbi, gb_len);
+ if (r)
+ goto exit;
+
+ r = 0;
+
+exit:
+ return r;
+}
+
+static int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev,
+ struct st21nfca_psl_req *psl_req)
+{
+ struct st21nfca_psl_res *psl_res;
+ struct sk_buff *skb;
+ u8 bitrate[2] = {0, 0};
+
+ int r;
+
+ skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+ skb_put(skb, sizeof(struct st21nfca_psl_res));
+
+ psl_res = (struct st21nfca_psl_res *)skb->data;
+
+ psl_res->length = sizeof(struct st21nfca_psl_res);
+ psl_res->cmd0 = ST21NFCA_NFCIP1_RES;
+ psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES;
+ psl_res->did = psl_req->did;
+
+ r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+
+ /*
+ * ST21NFCA only support P2P passive.
+ * PSL_REQ BRS value != 0 has only a meaning to
+ * change technology to type F.
+ * We change to BITRATE 424Kbits.
+ * In other case switch to BITRATE 106Kbits.
+ */
+ if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) &&
+ ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) {
+ bitrate[0] = ST21NFCA_CARD_BITRATE_424;
+ bitrate[1] = ST21NFCA_CARD_BITRATE_424;
+ }
+
+ /* Send an event to change bitrate change event to card f */
+ return nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2);
+}
+
+static int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct st21nfca_psl_req *psl_req;
+ int r;
+
+ skb_trim(skb, skb->len - 1);
+ if (IS_ERR(skb)) {
+ r = PTR_ERR(skb);
+ skb = NULL;
+ goto exit;
+ }
+
+ if (!skb->len) {
+ r = -EIO;
+ goto exit;
+ }
+
+ psl_req = (struct st21nfca_psl_req *)skb->data;
+
+ if (skb->len < sizeof(struct st21nfca_psl_req)) {
+ r = -EIO;
+ goto exit;
+ }
+
+ r = st21nfca_tm_send_psl_res(hdev, psl_req);
+exit:
+ return r;
+}
+
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+ int r;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ *skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES;
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_RES;
+ *skb_push(skb, 1) = skb->len;
+
+ r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE,
+ ST21NFCA_EVT_SEND_DATA, skb->data, skb->len);
+ kfree_skb(skb);
+
+ return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_send_dep_res);
+
+static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct st21nfca_dep_req_res *dep_req;
+ u8 size;
+ int r;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ skb_trim(skb, skb->len - 1);
+ if (IS_ERR(skb)) {
+ r = PTR_ERR(skb);
+ skb = NULL;
+ goto exit;
+ }
+
+ size = 4;
+
+ dep_req = (struct st21nfca_dep_req_res *)skb->data;
+ if (skb->len < size) {
+ r = -EIO;
+ goto exit;
+ }
+
+ if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+ size++;
+ if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb))
+ size++;
+
+ if (skb->len < size) {
+ r = -EIO;
+ goto exit;
+ }
+
+ /* Receiving DEP_REQ - Decoding */
+ switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+ case ST21NFCA_NFC_DEP_PFB_I_PDU:
+ info->dep_info.curr_nfc_dep_pni =
+ ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb);
+ break;
+ case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+ pr_err("Received a ACK/NACK PDU\n");
+ break;
+ case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+ pr_err("Received a SUPERVISOR PDU\n");
+ break;
+ }
+
+ if (IS_ERR(skb)) {
+ r = PTR_ERR(skb);
+ skb = NULL;
+ goto exit;
+ }
+
+ skb_pull(skb, size);
+
+ return nfc_tm_data_received(hdev->ndev, skb);
+exit:
+ return r;
+}
+
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+ u8 gate)
+{
+ u8 cmd0, cmd1;
+ int r;
+
+ cmd0 = skb->data[1];
+ switch (cmd0) {
+ case ST21NFCA_NFCIP1_REQ:
+ cmd1 = skb->data[2];
+ switch (cmd1) {
+ case ST21NFCA_NFCIP1_ATR_REQ:
+ r = st21nfca_tm_recv_atr_req(hdev, skb);
+ break;
+ case ST21NFCA_NFCIP1_PSL_REQ:
+ r = st21nfca_tm_recv_psl_req(hdev, skb);
+ break;
+ case ST21NFCA_NFCIP1_DEP_REQ:
+ r = st21nfca_tm_recv_dep_req(hdev, skb);
+ break;
+ default:
+ return 1;
+ }
+ default:
+ return 1;
+ }
+ return r;
+}
+EXPORT_SYMBOL(st21nfca_tm_event_send_data);
+
+static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
+ u8 bri, u8 lri)
+{
+ struct sk_buff *skb;
+ struct st21nfca_psl_req *psl_req;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ skb =
+ alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL);
+ if (!skb)
+ return;
+ skb_reserve(skb, 1);
+
+ skb_put(skb, sizeof(struct st21nfca_psl_req));
+ psl_req = (struct st21nfca_psl_req *) skb->data;
+
+ psl_req->length = sizeof(struct st21nfca_psl_req);
+ psl_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+ psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ;
+ psl_req->did = did;
+ psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03);
+ psl_req->fsl = lri;
+
+ *skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+ st21nfca_im_send_pdu(info, skb);
+
+ kfree_skb(skb);
+}
+
+#define ST21NFCA_CB_TYPE_READER_F 1
+static void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb,
+ int err)
+{
+ struct st21nfca_hci_info *info = context;
+ struct st21nfca_atr_res *atr_res;
+ int r;
+
+ if (err != 0)
+ return;
+
+ if (IS_ERR(skb))
+ return;
+
+ switch (info->async_cb_type) {
+ case ST21NFCA_CB_TYPE_READER_F:
+ skb_trim(skb, skb->len - 1);
+ atr_res = (struct st21nfca_atr_res *)skb->data;
+ r = nfc_set_remote_general_bytes(info->hdev->ndev,
+ atr_res->gbi,
+ skb->len - sizeof(struct st21nfca_atr_res));
+ if (r < 0)
+ return;
+
+ if (atr_res->to >= 0x0e)
+ info->dep_info.to = 0x0e;
+ else
+ info->dep_info.to = atr_res->to + 1;
+
+ info->dep_info.to |= 0x10;
+
+ r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx,
+ NFC_COMM_PASSIVE, NFC_RF_INITIATOR);
+ if (r < 0)
+ return;
+
+ info->dep_info.curr_nfc_dep_pni = 0;
+ if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri)
+ st21nfca_im_send_psl_req(info->hdev, atr_res->did,
+ atr_res->bsi, atr_res->bri,
+ ST21NFCA_PP2LRI(atr_res->ppi));
+ break;
+ default:
+ if (err == 0)
+ kfree_skb(skb);
+ break;
+ }
+}
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len)
+{
+ struct sk_buff *skb;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+ struct st21nfca_atr_req *atr_req;
+ struct nfc_target *target;
+ uint size;
+
+ info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+ size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len;
+ if (size > ST21NFCA_ATR_REQ_MAX_SIZE) {
+ PROTOCOL_ERR("14.6.1.1");
+ return -EINVAL;
+ }
+
+ skb =
+ alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ skb_reserve(skb, 1);
+
+ skb_put(skb, sizeof(struct st21nfca_atr_req));
+
+ atr_req = (struct st21nfca_atr_req *)skb->data;
+ memset(atr_req, 0, sizeof(struct st21nfca_atr_req));
+
+ atr_req->cmd0 = ST21NFCA_NFCIP1_REQ;
+ atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ;
+ memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE);
+ target = hdev->ndev->targets;
+
+ if (target->sensf_res)
+ memcpy(atr_req->nfcid3, target->sensf_res,
+ target->sensf_res_len);
+ else
+ get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
+
+ atr_req->did = 0x0;
+
+ atr_req->bsi = 0x00;
+ atr_req->bri = 0x00;
+ atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B;
+ if (gb_len) {
+ atr_req->ppi |= ST21NFCA_GB_BIT;
+ memcpy(skb_put(skb, gb_len), gb, gb_len);
+ }
+ atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len;
+
+ *skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */
+
+ info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+ info->async_cb_context = info;
+ info->async_cb = st21nfca_im_recv_atr_res_cb;
+ info->dep_info.bri = atr_req->bri;
+ info->dep_info.bsi = atr_req->bsi;
+ info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi);
+
+ return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_WR_XCHG_DATA, skb->data,
+ skb->len, info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_atr_req);
+
+static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb,
+ int err)
+{
+ struct st21nfca_hci_info *info = context;
+ struct st21nfca_dep_req_res *dep_res;
+
+ int size;
+
+ if (err != 0)
+ return;
+
+ if (IS_ERR(skb))
+ return;
+
+ switch (info->async_cb_type) {
+ case ST21NFCA_CB_TYPE_READER_F:
+ dep_res = (struct st21nfca_dep_req_res *)skb->data;
+
+ size = 3;
+ if (skb->len < size)
+ goto exit;
+
+ if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb))
+ size++;
+ if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb))
+ size++;
+
+ if (skb->len < size)
+ goto exit;
+
+ skb_trim(skb, skb->len - 1);
+
+ /* Receiving DEP_REQ - Decoding */
+ switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) {
+ case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU:
+ pr_err("Received a ACK/NACK PDU\n");
+ case ST21NFCA_NFC_DEP_PFB_I_PDU:
+ info->dep_info.curr_nfc_dep_pni =
+ ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1);
+ size++;
+ skb_pull(skb, size);
+ nfc_tm_data_received(info->hdev->ndev, skb);
+ break;
+ case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU:
+ pr_err("Received a SUPERVISOR PDU\n");
+ skb_pull(skb, size);
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+ *skb_push(skb, 1) = skb->len;
+ *skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+ st21nfca_im_send_pdu(info, skb);
+ break;
+ }
+
+ return;
+ default:
+ break;
+ }
+
+exit:
+ if (err == 0)
+ kfree_skb(skb);
+}
+
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ info->async_cb_type = ST21NFCA_CB_TYPE_READER_F;
+ info->async_cb_context = info;
+ info->async_cb = st21nfca_im_recv_dep_res_cb;
+
+ *skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni;
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ;
+ *skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ;
+ *skb_push(skb, 1) = skb->len;
+
+ *skb_push(skb, 1) = info->dep_info.to | 0x10;
+
+ return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_WR_XCHG_DATA,
+ skb->data, skb->len,
+ info->async_cb, info);
+}
+EXPORT_SYMBOL(st21nfca_im_send_dep_req);
+
+void st21nfca_dep_init(struct nfc_hci_dev *hdev)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work);
+ info->dep_info.curr_nfc_dep_pni = 0;
+ info->dep_info.idx = 0;
+ info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT;
+}
+EXPORT_SYMBOL(st21nfca_dep_init);
+
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev)
+{
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
+
+ cancel_work_sync(&info->dep_info.tx_work);
+}
+EXPORT_SYMBOL(st21nfca_dep_deinit);
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h
new file mode 100644
index 000000000000..ca213dee9c6e
--- /dev/null
+++ b/drivers/nfc/st21nfca/st21nfca_dep.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ST21NFCA_DEP_H
+#define __ST21NFCA_DEP_H
+
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+
+struct st21nfca_dep_info {
+ struct sk_buff *tx_pending;
+ struct work_struct tx_work;
+ u8 curr_nfc_dep_pni;
+ u32 idx;
+ u8 to;
+ u8 did;
+ u8 bsi;
+ u8 bri;
+ u8 lri;
+} __packed;
+
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+ u8 gate);
+int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+
+int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
+int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb);
+void st21nfca_dep_init(struct nfc_hci_dev *hdev);
+void st21nfca_dep_deinit(struct nfc_hci_dev *hdev);
+#endif /* __ST21NFCA_DEP_H */
diff --git a/drivers/nfc/st21nfcb/Kconfig b/drivers/nfc/st21nfcb/Kconfig
new file mode 100644
index 000000000000..e0322dd03a70
--- /dev/null
+++ b/drivers/nfc/st21nfcb/Kconfig
@@ -0,0 +1,22 @@
+config NFC_ST21NFCB
+ tristate "STMicroelectronics ST21NFCB NFC driver"
+ depends on NFC_NCI
+ default n
+ ---help---
+ STMicroelectronics ST21NFCB core driver. It implements the chipset
+ NCI logic and hooks into the NFC kernel APIs. Physical layers will
+ register against it.
+
+ To compile this driver as a module, choose m here. The module will
+ be called st21nfcb.
+ Say N if unsure.
+
+config NFC_ST21NFCB_I2C
+ tristate "NFC ST21NFCB i2c support"
+ depends on NFC_ST21NFCB && I2C
+ ---help---
+ This module adds support for the STMicroelectronics st21nfcb i2c interface.
+ Select this if your platform is using the i2c bus.
+
+ If you choose to build a module, it'll be called st21nfcb_i2c.
+ Say N if unsure.
diff --git a/drivers/nfc/st21nfcb/Makefile b/drivers/nfc/st21nfcb/Makefile
new file mode 100644
index 000000000000..13d9f03b2fea
--- /dev/null
+++ b/drivers/nfc/st21nfcb/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for ST21NFCB NCI based NFC driver
+#
+
+st21nfcb_i2c-objs = i2c.o
+
+obj-$(CONFIG_NFC_ST21NFCB) += st21nfcb.o ndlc.o
+obj-$(CONFIG_NFC_ST21NFCB_I2C) += st21nfcb_i2c.o
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c
new file mode 100644
index 000000000000..8af880ead5db
--- /dev/null
+++ b/drivers/nfc/st21nfcb/i2c.c
@@ -0,0 +1,462 @@
+/*
+ * I2C Link Layer for ST21NFCB NCI based Driver
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/crc-ccitt.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/nfc.h>
+#include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/platform_data/st21nfcb.h>
+
+#include <net/nfc/nci.h>
+#include <net/nfc/llc.h>
+#include <net/nfc/nfc.h>
+
+#include "ndlc.h"
+
+#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
+
+/* ndlc header */
+#define ST21NFCB_FRAME_HEADROOM 1
+#define ST21NFCB_FRAME_TAILROOM 0
+
+#define ST21NFCB_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
+#define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
+
+#define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c"
+
+static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = {
+ {ST21NFCB_NCI_DRIVER_NAME, 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table);
+
+struct st21nfcb_i2c_phy {
+ struct i2c_client *i2c_dev;
+ struct llt_ndlc *ndlc;
+
+ unsigned int gpio_irq;
+ unsigned int gpio_reset;
+ unsigned int irq_polarity;
+
+ int powered;
+
+ /*
+ * < 0 if hardware error occured (e.g. i2c err)
+ * and prevents normal operation.
+ */
+ int hard_fault;
+};
+
+#define I2C_DUMP_SKB(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, 0); \
+} while (0)
+
+static int st21nfcb_nci_i2c_enable(void *phy_id)
+{
+ struct st21nfcb_i2c_phy *phy = phy_id;
+
+ gpio_set_value(phy->gpio_reset, 0);
+ usleep_range(10000, 15000);
+ gpio_set_value(phy->gpio_reset, 1);
+ phy->powered = 1;
+ usleep_range(80000, 85000);
+
+ return 0;
+}
+
+static void st21nfcb_nci_i2c_disable(void *phy_id)
+{
+ struct st21nfcb_i2c_phy *phy = phy_id;
+
+ pr_info("\n");
+
+ phy->powered = 0;
+ /* reset chip in order to flush clf */
+ gpio_set_value(phy->gpio_reset, 0);
+ usleep_range(10000, 15000);
+ gpio_set_value(phy->gpio_reset, 1);
+}
+
+static void st21nfcb_nci_remove_header(struct sk_buff *skb)
+{
+ skb_pull(skb, ST21NFCB_FRAME_HEADROOM);
+}
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
+{
+ int r = -1;
+ struct st21nfcb_i2c_phy *phy = phy_id;
+ struct i2c_client *client = phy->i2c_dev;
+
+ I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);
+
+ if (phy->hard_fault != 0)
+ return phy->hard_fault;
+
+ r = i2c_master_send(client, skb->data, skb->len);
+ if (r == -EREMOTEIO) { /* Retry, chip was in standby */
+ usleep_range(1000, 4000);
+ r = i2c_master_send(client, skb->data, skb->len);
+ }
+
+ if (r >= 0) {
+ if (r != skb->len)
+ r = -EREMOTEIO;
+ else
+ r = 0;
+ }
+
+ st21nfcb_nci_remove_header(skb);
+
+ return r;
+}
+
+/*
+ * Reads an ndlc frame and returns it in a newly allocated sk_buff.
+ * returns:
+ * frame size : if received frame is complete (find ST21NFCB_SOF_EOF at
+ * end of read)
+ * -EAGAIN : if received frame is incomplete (not find ST21NFCB_SOF_EOF
+ * at end of read)
+ * -EREMOTEIO : i2c read error (fatal)
+ * -EBADMSG : frame was incorrect and discarded
+ * (value returned from st21nfcb_nci_i2c_repack)
+ * -EIO : if no ST21NFCB_SOF_EOF is found after reaching
+ * the read length end sequence
+ */
+static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
+ struct sk_buff **skb)
+{
+ int r;
+ u8 len;
+ u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE];
+ struct i2c_client *client = phy->i2c_dev;
+
+ r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+ if (r == -EREMOTEIO) { /* Retry, chip was in standby */
+ usleep_range(1000, 4000);
+ r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+ } else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) {
+ nfc_err(&client->dev, "cannot read ndlc & nci header\n");
+ return -EREMOTEIO;
+ }
+
+ len = be16_to_cpu(*(__be16 *) (buf + 2));
+ if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
+ nfc_err(&client->dev, "invalid frame len\n");
+ return -EBADMSG;
+ }
+
+ *skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
+ if (*skb == NULL)
+ return -ENOMEM;
+
+ skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
+ skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
+ memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
+
+ if (!len)
+ return 0;
+
+ r = i2c_master_recv(client, buf, len);
+ if (r != len) {
+ kfree_skb(*skb);
+ return -EREMOTEIO;
+ }
+
+ skb_put(*skb, len);
+ memcpy((*skb)->data + ST21NFCB_NCI_I2C_MIN_SIZE, buf, len);
+
+ I2C_DUMP_SKB("i2c frame read", *skb);
+
+ return 0;
+}
+
+/*
+ * Reads an ndlc frame from the chip.
+ *
+ * On ST21NFCB, IRQ goes in idle state when read starts.
+ */
+static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id)
+{
+ struct st21nfcb_i2c_phy *phy = phy_id;
+ struct i2c_client *client;
+ struct sk_buff *skb = NULL;
+ int r;
+
+ if (!phy || irq != phy->i2c_dev->irq) {
+ WARN_ON_ONCE(1);
+ return IRQ_NONE;
+ }
+
+ client = phy->i2c_dev;
+ dev_dbg(&client->dev, "IRQ\n");
+
+ if (phy->hard_fault)
+ return IRQ_HANDLED;
+
+ if (!phy->powered) {
+ st21nfcb_nci_i2c_disable(phy);
+ return IRQ_HANDLED;
+ }
+
+ r = st21nfcb_nci_i2c_read(phy, &skb);
+ if (r == -EREMOTEIO) {
+ phy->hard_fault = r;
+ ndlc_recv(phy->ndlc, NULL);
+ return IRQ_HANDLED;
+ } else if (r == -ENOMEM || r == -EBADMSG) {
+ return IRQ_HANDLED;
+ }
+
+ ndlc_recv(phy->ndlc, skb);
+
+ return IRQ_HANDLED;
+}
+
+static struct nfc_phy_ops i2c_phy_ops = {
+ .write = st21nfcb_nci_i2c_write,
+ .enable = st21nfcb_nci_i2c_enable,
+ .disable = st21nfcb_nci_i2c_disable,
+};
+
+#ifdef CONFIG_OF
+static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+{
+ struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+ struct device_node *pp;
+ int gpio;
+ int r;
+
+ pp = client->dev.of_node;
+ if (!pp)
+ return -ENODEV;
+
+ /* Get GPIO from device tree */
+ gpio = of_get_named_gpio(pp, "reset-gpios", 0);
+ if (gpio < 0) {
+ nfc_err(&client->dev,
+ "Failed to retrieve reset-gpios from device tree\n");
+ return gpio;
+ }
+
+ /* GPIO request and configuration */
+ r = devm_gpio_request(&client->dev, gpio, "clf_reset");
+ if (r) {
+ nfc_err(&client->dev, "Failed to request reset pin\n");
+ return -ENODEV;
+ }
+
+ r = gpio_direction_output(gpio, 1);
+ if (r) {
+ nfc_err(&client->dev,
+ "Failed to set reset pin direction as output\n");
+ return -ENODEV;
+ }
+ phy->gpio_reset = gpio;
+
+ /* IRQ */
+ r = irq_of_parse_and_map(pp, 0);
+ if (r < 0) {
+ nfc_err(&client->dev,
+ "Unable to get irq, error: %d\n", r);
+ return r;
+ }
+
+ phy->irq_polarity = irq_get_trigger_type(r);
+ client->irq = r;
+
+ return 0;
+}
+#else
+static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
+{
+ return -ENODEV;
+}
+#endif
+
+static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
+{
+ struct st21nfcb_nfc_platform_data *pdata;
+ struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+ int r;
+ int irq;
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL) {
+ nfc_err(&client->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
+ /* store for later use */
+ phy->gpio_irq = pdata->gpio_irq;
+ phy->gpio_reset = pdata->gpio_reset;
+ phy->irq_polarity = pdata->irq_polarity;
+
+ r = devm_gpio_request(&client->dev, phy->gpio_irq, "wake_up");
+ if (r) {
+ pr_err("%s : gpio_request failed\n", __FILE__);
+ return -ENODEV;
+ }
+
+ r = gpio_direction_input(phy->gpio_irq);
+ if (r) {
+ pr_err("%s : gpio_direction_input failed\n", __FILE__);
+ return -ENODEV;
+ }
+
+ r = devm_gpio_request(&client->dev,
+ phy->gpio_reset, "clf_reset");
+ if (r) {
+ pr_err("%s : reset gpio_request failed\n", __FILE__);
+ return -ENODEV;
+ }
+
+ r = gpio_direction_output(phy->gpio_reset, 1);
+ if (r) {
+ pr_err("%s : reset gpio_direction_output failed\n",
+ __FILE__);
+ return -ENODEV;
+ }
+
+ /* IRQ */
+ irq = gpio_to_irq(phy->gpio_irq);
+ if (irq < 0) {
+ nfc_err(&client->dev,
+ "Unable to get irq number for GPIO %d error %d\n",
+ phy->gpio_irq, r);
+ return -ENODEV;
+ }
+ client->irq = irq;
+
+ return 0;
+}
+
+static int st21nfcb_nci_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct st21nfcb_i2c_phy *phy;
+ struct st21nfcb_nfc_platform_data *pdata;
+ int r;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
+ return -ENODEV;
+ }
+
+ phy = devm_kzalloc(&client->dev, sizeof(struct st21nfcb_i2c_phy),
+ GFP_KERNEL);
+ if (!phy) {
+ nfc_err(&client->dev,
+ "Cannot allocate memory for st21nfcb i2c phy.\n");
+ return -ENOMEM;
+ }
+
+ phy->i2c_dev = client;
+
+ i2c_set_clientdata(client, phy);
+
+ pdata = client->dev.platform_data;
+ if (!pdata && client->dev.of_node) {
+ r = st21nfcb_nci_i2c_of_request_resources(client);
+ if (r) {
+ nfc_err(&client->dev, "No platform data\n");
+ return r;
+ }
+ } else if (pdata) {
+ r = st21nfcb_nci_i2c_request_resources(client);
+ if (r) {
+ nfc_err(&client->dev,
+ "Cannot get platform resources\n");
+ return r;
+ }
+ } else {
+ nfc_err(&client->dev,
+ "st21nfcb platform resources not available\n");
+ return -ENODEV;
+ }
+
+ r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ st21nfcb_nci_irq_thread_fn,
+ phy->irq_polarity | IRQF_ONESHOT,
+ ST21NFCB_NCI_DRIVER_NAME, phy);
+ if (r < 0) {
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+ return r;
+ }
+
+ return ndlc_probe(phy, &i2c_phy_ops, &client->dev,
+ ST21NFCB_FRAME_HEADROOM, ST21NFCB_FRAME_TAILROOM,
+ &phy->ndlc);
+}
+
+static int st21nfcb_nci_i2c_remove(struct i2c_client *client)
+{
+ struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ ndlc_remove(phy->ndlc);
+
+ if (phy->powered)
+ st21nfcb_nci_i2c_disable(phy);
+
+ return 0;
+}
+
+static const struct of_device_id of_st21nfcb_i2c_match[] = {
+ { .compatible = "st,st21nfcb_i2c", },
+ {}
+};
+
+static struct i2c_driver st21nfcb_nci_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = ST21NFCB_NCI_I2C_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(of_st21nfcb_i2c_match),
+ },
+ .probe = st21nfcb_nci_i2c_probe,
+ .id_table = st21nfcb_nci_i2c_id_table,
+ .remove = st21nfcb_nci_i2c_remove,
+};
+
+module_i2c_driver(st21nfcb_nci_i2c_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c
new file mode 100644
index 000000000000..83c97c36112b
--- /dev/null
+++ b/drivers/nfc/st21nfcb/ndlc.c
@@ -0,0 +1,298 @@
+/*
+ * Low Level Transport (NDLC) Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched.h>
+#include <net/nfc/nci_core.h>
+
+#include "ndlc.h"
+#include "st21nfcb.h"
+
+#define NDLC_TIMER_T1 100
+#define NDLC_TIMER_T1_WAIT 400
+#define NDLC_TIMER_T2 1200
+
+#define PCB_TYPE_DATAFRAME 0x80
+#define PCB_TYPE_SUPERVISOR 0xc0
+#define PCB_TYPE_MASK PCB_TYPE_SUPERVISOR
+
+#define PCB_SYNC_ACK 0x20
+#define PCB_SYNC_NACK 0x10
+#define PCB_SYNC_WAIT 0x30
+#define PCB_SYNC_NOINFO 0x00
+#define PCB_SYNC_MASK PCB_SYNC_WAIT
+
+#define PCB_DATAFRAME_RETRANSMIT_YES 0x00
+#define PCB_DATAFRAME_RETRANSMIT_NO 0x04
+#define PCB_DATAFRAME_RETRANSMIT_MASK PCB_DATAFRAME_RETRANSMIT_NO
+
+#define PCB_SUPERVISOR_RETRANSMIT_YES 0x00
+#define PCB_SUPERVISOR_RETRANSMIT_NO 0x02
+#define PCB_SUPERVISOR_RETRANSMIT_MASK PCB_SUPERVISOR_RETRANSMIT_NO
+
+#define PCB_FRAME_CRC_INFO_PRESENT 0x08
+#define PCB_FRAME_CRC_INFO_NOTPRESENT 0x00
+#define PCB_FRAME_CRC_INFO_MASK PCB_FRAME_CRC_INFO_PRESENT
+
+#define NDLC_DUMP_SKB(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump(KERN_DEBUG, "ndlc: ", DUMP_PREFIX_OFFSET, \
+ 16, 1, skb->data, skb->len, 0); \
+} while (0)
+
+int ndlc_open(struct llt_ndlc *ndlc)
+{
+ /* toggle reset pin */
+ ndlc->ops->enable(ndlc->phy_id);
+ return 0;
+}
+EXPORT_SYMBOL(ndlc_open);
+
+void ndlc_close(struct llt_ndlc *ndlc)
+{
+ /* toggle reset pin */
+ ndlc->ops->disable(ndlc->phy_id);
+}
+EXPORT_SYMBOL(ndlc_close);
+
+int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb)
+{
+ /* add ndlc header */
+ u8 pcb = PCB_TYPE_DATAFRAME | PCB_DATAFRAME_RETRANSMIT_NO |
+ PCB_FRAME_CRC_INFO_NOTPRESENT;
+
+ *skb_push(skb, 1) = pcb;
+ skb_queue_tail(&ndlc->send_q, skb);
+
+ schedule_work(&ndlc->sm_work);
+
+ return 0;
+}
+EXPORT_SYMBOL(ndlc_send);
+
+static void llt_ndlc_send_queue(struct llt_ndlc *ndlc)
+{
+ struct sk_buff *skb;
+ int r;
+ unsigned long time_sent;
+
+ if (ndlc->send_q.qlen)
+ pr_debug("sendQlen=%d unackQlen=%d\n",
+ ndlc->send_q.qlen, ndlc->ack_pending_q.qlen);
+
+ while (ndlc->send_q.qlen) {
+ skb = skb_dequeue(&ndlc->send_q);
+ NDLC_DUMP_SKB("ndlc frame written", skb);
+ r = ndlc->ops->write(ndlc->phy_id, skb);
+ if (r < 0) {
+ ndlc->hard_fault = r;
+ break;
+ }
+ time_sent = jiffies;
+ *(unsigned long *)skb->cb = time_sent;
+
+ skb_queue_tail(&ndlc->ack_pending_q, skb);
+
+ /* start timer t1 for ndlc aknowledge */
+ ndlc->t1_active = true;
+ mod_timer(&ndlc->t1_timer, time_sent +
+ msecs_to_jiffies(NDLC_TIMER_T1));
+ }
+}
+
+static void llt_ndlc_requeue_data_pending(struct llt_ndlc *ndlc)
+{
+ struct sk_buff *skb;
+ u8 pcb;
+
+ while ((skb = skb_dequeue_tail(&ndlc->ack_pending_q))) {
+ pcb = skb->data[0];
+ switch (pcb & PCB_TYPE_MASK) {
+ case PCB_TYPE_SUPERVISOR:
+ skb->data[0] = (pcb & ~PCB_SUPERVISOR_RETRANSMIT_MASK) |
+ PCB_SUPERVISOR_RETRANSMIT_YES;
+ break;
+ case PCB_TYPE_DATAFRAME:
+ skb->data[0] = (pcb & ~PCB_DATAFRAME_RETRANSMIT_MASK) |
+ PCB_DATAFRAME_RETRANSMIT_YES;
+ break;
+ default:
+ pr_err("UNKNOWN Packet Control Byte=%d\n", pcb);
+ kfree_skb(skb);
+ break;
+ }
+ skb_queue_head(&ndlc->send_q, skb);
+ }
+}
+
+static void llt_ndlc_rcv_queue(struct llt_ndlc *ndlc)
+{
+ struct sk_buff *skb;
+ u8 pcb;
+ unsigned long time_sent;
+
+ if (ndlc->rcv_q.qlen)
+ pr_debug("rcvQlen=%d\n", ndlc->rcv_q.qlen);
+
+ while ((skb = skb_dequeue(&ndlc->rcv_q)) != NULL) {
+ pcb = skb->data[0];
+ skb_pull(skb, 1);
+ if ((pcb & PCB_TYPE_MASK) == PCB_TYPE_SUPERVISOR) {
+ switch (pcb & PCB_SYNC_MASK) {
+ case PCB_SYNC_ACK:
+ del_timer_sync(&ndlc->t1_timer);
+ del_timer_sync(&ndlc->t2_timer);
+ ndlc->t2_active = false;
+ ndlc->t1_active = false;
+ break;
+ case PCB_SYNC_NACK:
+ llt_ndlc_requeue_data_pending(ndlc);
+ llt_ndlc_send_queue(ndlc);
+ /* start timer t1 for ndlc aknowledge */
+ time_sent = jiffies;
+ ndlc->t1_active = true;
+ mod_timer(&ndlc->t1_timer, time_sent +
+ msecs_to_jiffies(NDLC_TIMER_T1));
+ break;
+ case PCB_SYNC_WAIT:
+ time_sent = jiffies;
+ ndlc->t1_active = true;
+ mod_timer(&ndlc->t1_timer, time_sent +
+ msecs_to_jiffies(NDLC_TIMER_T1_WAIT));
+ break;
+ default:
+ pr_err("UNKNOWN Packet Control Byte=%d\n", pcb);
+ kfree_skb(skb);
+ break;
+ }
+ } else {
+ nci_recv_frame(ndlc->ndev, skb);
+ }
+ }
+}
+
+static void llt_ndlc_sm_work(struct work_struct *work)
+{
+ struct llt_ndlc *ndlc = container_of(work, struct llt_ndlc, sm_work);
+
+ llt_ndlc_send_queue(ndlc);
+ llt_ndlc_rcv_queue(ndlc);
+
+ if (ndlc->t1_active && timer_pending(&ndlc->t1_timer) == 0) {
+ pr_debug
+ ("Handle T1(recv SUPERVISOR) elapsed (T1 now inactive)\n");
+ ndlc->t1_active = false;
+
+ llt_ndlc_requeue_data_pending(ndlc);
+ llt_ndlc_send_queue(ndlc);
+ }
+
+ if (ndlc->t2_active && timer_pending(&ndlc->t2_timer) == 0) {
+ pr_debug("Handle T2(recv DATA) elapsed (T2 now inactive)\n");
+ ndlc->t2_active = false;
+ ndlc->t1_active = false;
+ del_timer_sync(&ndlc->t1_timer);
+
+ ndlc_close(ndlc);
+ ndlc->hard_fault = -EREMOTEIO;
+ }
+}
+
+void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb)
+{
+ if (skb == NULL) {
+ pr_err("NULL Frame -> link is dead\n");
+ ndlc->hard_fault = -EREMOTEIO;
+ ndlc_close(ndlc);
+ } else {
+ NDLC_DUMP_SKB("incoming frame", skb);
+ skb_queue_tail(&ndlc->rcv_q, skb);
+ }
+
+ schedule_work(&ndlc->sm_work);
+}
+EXPORT_SYMBOL(ndlc_recv);
+
+static void ndlc_t1_timeout(unsigned long data)
+{
+ struct llt_ndlc *ndlc = (struct llt_ndlc *)data;
+
+ pr_debug("\n");
+
+ schedule_work(&ndlc->sm_work);
+}
+
+static void ndlc_t2_timeout(unsigned long data)
+{
+ struct llt_ndlc *ndlc = (struct llt_ndlc *)data;
+
+ pr_debug("\n");
+
+ schedule_work(&ndlc->sm_work);
+}
+
+int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id)
+{
+ struct llt_ndlc *ndlc;
+
+ ndlc = devm_kzalloc(dev, sizeof(struct llt_ndlc), GFP_KERNEL);
+ if (!ndlc) {
+ nfc_err(dev, "Cannot allocate memory for ndlc.\n");
+ return -ENOMEM;
+ }
+ ndlc->ops = phy_ops;
+ ndlc->phy_id = phy_id;
+ ndlc->dev = dev;
+
+ *ndlc_id = ndlc;
+
+ /* start timers */
+ init_timer(&ndlc->t1_timer);
+ ndlc->t1_timer.data = (unsigned long)ndlc;
+ ndlc->t1_timer.function = ndlc_t1_timeout;
+
+ init_timer(&ndlc->t2_timer);
+ ndlc->t2_timer.data = (unsigned long)ndlc;
+ ndlc->t2_timer.function = ndlc_t2_timeout;
+
+ skb_queue_head_init(&ndlc->rcv_q);
+ skb_queue_head_init(&ndlc->send_q);
+ skb_queue_head_init(&ndlc->ack_pending_q);
+
+ INIT_WORK(&ndlc->sm_work, llt_ndlc_sm_work);
+
+ return st21nfcb_nci_probe(ndlc, phy_headroom, phy_tailroom);
+}
+EXPORT_SYMBOL(ndlc_probe);
+
+void ndlc_remove(struct llt_ndlc *ndlc)
+{
+ /* cancel timers */
+ del_timer_sync(&ndlc->t1_timer);
+ del_timer_sync(&ndlc->t2_timer);
+ ndlc->t2_active = false;
+ ndlc->t1_active = false;
+
+ skb_queue_purge(&ndlc->rcv_q);
+ skb_queue_purge(&ndlc->send_q);
+
+ st21nfcb_nci_remove(ndlc->ndev);
+ kfree(ndlc);
+}
+EXPORT_SYMBOL(ndlc_remove);
diff --git a/drivers/nfc/st21nfcb/ndlc.h b/drivers/nfc/st21nfcb/ndlc.h
new file mode 100644
index 000000000000..c30a2f0faa5f
--- /dev/null
+++ b/drivers/nfc/st21nfcb/ndlc.h
@@ -0,0 +1,55 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LOCAL_NDLC_H_
+#define __LOCAL_NDLC_H_
+
+#include <linux/skbuff.h>
+#include <net/nfc/nfc.h>
+
+/* Low Level Transport description */
+struct llt_ndlc {
+ struct nci_dev *ndev;
+ struct nfc_phy_ops *ops;
+ void *phy_id;
+
+ struct timer_list t1_timer;
+ bool t1_active;
+
+ struct timer_list t2_timer;
+ bool t2_active;
+
+ struct sk_buff_head rcv_q;
+ struct sk_buff_head send_q;
+ struct sk_buff_head ack_pending_q;
+
+ struct work_struct sm_work;
+
+ struct device *dev;
+
+ int hard_fault;
+};
+
+int ndlc_open(struct llt_ndlc *ndlc);
+void ndlc_close(struct llt_ndlc *ndlc);
+int ndlc_send(struct llt_ndlc *ndlc, struct sk_buff *skb);
+void ndlc_recv(struct llt_ndlc *ndlc, struct sk_buff *skb);
+int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
+ int phy_headroom, int phy_tailroom, struct llt_ndlc **ndlc_id);
+void ndlc_remove(struct llt_ndlc *ndlc);
+#endif /* __LOCAL_NDLC_H__ */
diff --git a/drivers/nfc/st21nfcb/st21nfcb.c b/drivers/nfc/st21nfcb/st21nfcb.c
new file mode 100644
index 000000000000..4d95863e3063
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb.c
@@ -0,0 +1,129 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>
+
+#include "st21nfcb.h"
+#include "ndlc.h"
+
+#define DRIVER_DESC "NCI NFC driver for ST21NFCB"
+
+static int st21nfcb_nci_open(struct nci_dev *ndev)
+{
+ struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+ int r;
+
+ if (test_and_set_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+ return 0;
+
+ r = ndlc_open(info->ndlc);
+ if (r)
+ clear_bit(ST21NFCB_NCI_RUNNING, &info->flags);
+
+ return r;
+}
+
+static int st21nfcb_nci_close(struct nci_dev *ndev)
+{
+ struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+ if (!test_and_clear_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+ return 0;
+
+ ndlc_close(info->ndlc);
+
+ return 0;
+}
+
+static int st21nfcb_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+ struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+ skb->dev = (void *)ndev;
+
+ if (!test_bit(ST21NFCB_NCI_RUNNING, &info->flags))
+ return -EBUSY;
+
+ return ndlc_send(info->ndlc, skb);
+}
+
+static struct nci_ops st21nfcb_nci_ops = {
+ .open = st21nfcb_nci_open,
+ .close = st21nfcb_nci_close,
+ .send = st21nfcb_nci_send,
+};
+
+int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+ int phy_tailroom)
+{
+ struct st21nfcb_nci_info *info;
+ int r;
+ u32 protocols;
+
+ info = devm_kzalloc(ndlc->dev,
+ sizeof(struct st21nfcb_nci_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ protocols = NFC_PROTO_JEWEL_MASK
+ | NFC_PROTO_MIFARE_MASK
+ | NFC_PROTO_FELICA_MASK
+ | NFC_PROTO_ISO14443_MASK
+ | NFC_PROTO_ISO14443_B_MASK
+ | NFC_PROTO_NFC_DEP_MASK;
+
+ ndlc->ndev = nci_allocate_device(&st21nfcb_nci_ops, protocols,
+ phy_headroom, phy_tailroom);
+ if (!ndlc->ndev) {
+ pr_err("Cannot allocate nfc ndev\n");
+ r = -ENOMEM;
+ goto err_alloc_ndev;
+ }
+ info->ndlc = ndlc;
+
+ nci_set_drvdata(ndlc->ndev, info);
+
+ r = nci_register_device(ndlc->ndev);
+ if (r)
+ goto err_regdev;
+
+ return r;
+err_regdev:
+ nci_free_device(ndlc->ndev);
+
+err_alloc_ndev:
+ kfree(info);
+ return r;
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_probe);
+
+void st21nfcb_nci_remove(struct nci_dev *ndev)
+{
+ struct st21nfcb_nci_info *info = nci_get_drvdata(ndev);
+
+ nci_unregister_device(ndev);
+ nci_free_device(ndev);
+ kfree(info);
+}
+EXPORT_SYMBOL_GPL(st21nfcb_nci_remove);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/nfc/st21nfcb/st21nfcb.h b/drivers/nfc/st21nfcb/st21nfcb.h
new file mode 100644
index 000000000000..4bbbebb9f34d
--- /dev/null
+++ b/drivers/nfc/st21nfcb/st21nfcb.h
@@ -0,0 +1,38 @@
+/*
+ * NCI based Driver for STMicroelectronics NFC Chip
+ *
+ * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LOCAL_ST21NFCB_H_
+#define __LOCAL_ST21NFCB_H_
+
+#include <net/nfc/nci_core.h>
+
+#include "ndlc.h"
+
+/* Define private flags: */
+#define ST21NFCB_NCI_RUNNING 1
+
+struct st21nfcb_nci_info {
+ struct llt_ndlc *ndlc;
+ unsigned long flags;
+};
+
+void st21nfcb_nci_remove(struct nci_dev *ndev);
+int st21nfcb_nci_probe(struct llt_ndlc *ndlc, int phy_headroom,
+ int phy_tailroom);
+
+#endif /* __LOCAL_ST21NFCB_H_ */
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 2dcb0541012d..5160c4eb73c2 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -9,7 +9,8 @@ menu "Device Tree and Open Firmware support"
config OF_SELFTEST
bool "Device Tree Runtime self tests"
- depends on OF_IRQ
+ depends on OF_IRQ && OF_EARLY_FLATTREE
+ select OF_DYNAMIC
help
This option builds in test cases for the device tree infrastructure
that are executed once at boot time, and the results dumped to the
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 099b1fb00af4..2b6a7b129d10 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,11 +1,13 @@
obj-y = base.o device.o platform.o
+obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
obj-$(CONFIG_OF_PROMTREE) += pdt.o
obj-$(CONFIG_OF_ADDRESS) += address.o
obj-$(CONFIG_OF_IRQ) += irq.o
obj-$(CONFIG_OF_NET) += of_net.o
-obj-$(CONFIG_OF_SELFTEST) += selftest.o
+obj-$(CONFIG_OF_SELFTEST) += of_selftest.o
+of_selftest-objs := selftest.o testcase-data/testcases.dtb.o
obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 5edfcb0da37d..e3718250d66e 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -702,6 +702,42 @@ void __iomem *of_iomap(struct device_node *np, int index)
}
EXPORT_SYMBOL(of_iomap);
+/*
+ * of_io_request_and_map - Requests a resource and maps the memory mapped IO
+ * for a given device_node
+ * @device: the device whose io range will be mapped
+ * @index: index of the io range
+ * @name: name of the resource
+ *
+ * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
+ * error code on failure. Usage example:
+ *
+ * base = of_io_request_and_map(node, 0, "foo");
+ * if (IS_ERR(base))
+ * return PTR_ERR(base);
+ */
+void __iomem *of_io_request_and_map(struct device_node *np, int index,
+ char *name)
+{
+ struct resource res;
+ void __iomem *mem;
+
+ if (of_address_to_resource(np, index, &res))
+ return IOMEM_ERR_PTR(-EINVAL);
+
+ if (!request_mem_region(res.start, resource_size(&res), name))
+ return IOMEM_ERR_PTR(-EBUSY);
+
+ mem = ioremap(res.start, resource_size(&res));
+ if (!mem) {
+ release_mem_region(res.start, resource_size(&res));
+ return IOMEM_ERR_PTR(-ENOMEM);
+ }
+
+ return mem;
+}
+EXPORT_SYMBOL(of_io_request_and_map);
+
/**
* of_dma_get_range - Get DMA range info
* @np: device node to get DMA range info
diff --git a/drivers/of/base.c b/drivers/of/base.c
index b9864806e9b8..d8574adf0d62 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,6 +17,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/console.h>
#include <linux/ctype.h>
#include <linux/cpu.h>
#include <linux/module.h>
@@ -35,15 +36,17 @@ struct device_node *of_allnodes;
EXPORT_SYMBOL(of_allnodes);
struct device_node *of_chosen;
struct device_node *of_aliases;
-static struct device_node *of_stdout;
+struct device_node *of_stdout;
-static struct kset *of_kset;
+struct kset *of_kset;
/*
- * Used to protect the of_aliases; but also overloaded to hold off addition of
- * nodes to sysfs
+ * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
+ * This mutex must be held whenever modifications are being made to the
+ * device tree. The of_{attach,detach}_node() and
+ * of_{add,remove,update}_property() helpers make sure this happens.
*/
-DEFINE_MUTEX(of_aliases_mutex);
+DEFINE_MUTEX(of_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -89,79 +92,7 @@ int __weak of_node_to_nid(struct device_node *np)
}
#endif
-#if defined(CONFIG_OF_DYNAMIC)
-/**
- * of_node_get - Increment refcount of a node
- * @node: Node to inc refcount, NULL is supported to
- * simplify writing of callers
- *
- * Returns node.
- */
-struct device_node *of_node_get(struct device_node *node)
-{
- if (node)
- kobject_get(&node->kobj);
- return node;
-}
-EXPORT_SYMBOL(of_node_get);
-
-static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
-{
- return container_of(kobj, struct device_node, kobj);
-}
-
-/**
- * of_node_release - release a dynamically allocated node
- * @kref: kref element of the node to be released
- *
- * In of_node_put() this function is passed to kref_put()
- * as the destructor.
- */
-static void of_node_release(struct kobject *kobj)
-{
- struct device_node *node = kobj_to_device_node(kobj);
- struct property *prop = node->properties;
-
- /* We should never be releasing nodes that haven't been detached. */
- if (!of_node_check_flag(node, OF_DETACHED)) {
- pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
- dump_stack();
- return;
- }
-
- if (!of_node_check_flag(node, OF_DYNAMIC))
- return;
-
- while (prop) {
- struct property *next = prop->next;
- kfree(prop->name);
- kfree(prop->value);
- kfree(prop);
- prop = next;
-
- if (!prop) {
- prop = node->deadprops;
- node->deadprops = NULL;
- }
- }
- kfree(node->full_name);
- kfree(node->data);
- kfree(node);
-}
-
-/**
- * of_node_put - Decrement refcount of a node
- * @node: Node to dec refcount, NULL is supported to
- * simplify writing of callers
- *
- */
-void of_node_put(struct device_node *node)
-{
- if (node)
- kobject_put(&node->kobj);
-}
-EXPORT_SYMBOL(of_node_put);
-#else
+#ifndef CONFIG_OF_DYNAMIC
static void of_node_release(struct kobject *kobj)
{
/* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
@@ -200,13 +131,16 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name)
return name;
}
-static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
+int __of_add_property_sysfs(struct device_node *np, struct property *pp)
{
int rc;
/* Important: Don't leak passwords */
bool secure = strncmp(pp->name, "security-", 9) == 0;
+ if (!of_kset || !of_node_is_attached(np))
+ return 0;
+
sysfs_bin_attr_init(&pp->attr);
pp->attr.attr.name = safe_name(&np->kobj, pp->name);
pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
@@ -218,12 +152,15 @@ static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
return rc;
}
-static int __of_node_add(struct device_node *np)
+int __of_attach_node_sysfs(struct device_node *np)
{
const char *name;
struct property *pp;
int rc;
+ if (!of_kset)
+ return 0;
+
np->kobj.kset = of_kset;
if (!np->parent) {
/* Nodes without parents are new top level trees */
@@ -245,59 +182,20 @@ static int __of_node_add(struct device_node *np)
return 0;
}
-int of_node_add(struct device_node *np)
-{
- int rc = 0;
-
- BUG_ON(!of_node_is_initialized(np));
-
- /*
- * Grab the mutex here so that in a race condition between of_init() and
- * of_node_add(), node addition will still be consistent.
- */
- mutex_lock(&of_aliases_mutex);
- if (of_kset)
- rc = __of_node_add(np);
- else
- /* This scenario may be perfectly valid, but report it anyway */
- pr_info("of_node_add(%s) before of_init()\n", np->full_name);
- mutex_unlock(&of_aliases_mutex);
- return rc;
-}
-
-#if defined(CONFIG_OF_DYNAMIC)
-static void of_node_remove(struct device_node *np)
-{
- struct property *pp;
-
- BUG_ON(!of_node_is_initialized(np));
-
- /* only remove properties if on sysfs */
- if (of_node_is_attached(np)) {
- for_each_property_of_node(np, pp)
- sysfs_remove_bin_file(&np->kobj, &pp->attr);
- kobject_del(&np->kobj);
- }
-
- /* finally remove the kobj_init ref */
- of_node_put(np);
-}
-#endif
-
static int __init of_init(void)
{
struct device_node *np;
/* Create the kset, and register existing nodes */
- mutex_lock(&of_aliases_mutex);
+ mutex_lock(&of_mutex);
of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
if (!of_kset) {
- mutex_unlock(&of_aliases_mutex);
+ mutex_unlock(&of_mutex);
return -ENOMEM;
}
for_each_of_allnodes(np)
- __of_node_add(np);
- mutex_unlock(&of_aliases_mutex);
+ __of_attach_node_sysfs(np);
+ mutex_unlock(&of_mutex);
/* Symlink in /proc as required by userspace ABI */
if (of_allnodes)
@@ -369,8 +267,8 @@ EXPORT_SYMBOL(of_find_all_nodes);
* Find a property with a given name for a given node
* and return the value.
*/
-static const void *__of_get_property(const struct device_node *np,
- const char *name, int *lenp)
+const void *__of_get_property(const struct device_node *np,
+ const char *name, int *lenp)
{
struct property *pp = __of_find_property(np, name, lenp);
@@ -1748,32 +1646,10 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na
}
EXPORT_SYMBOL(of_count_phandle_with_args);
-#if defined(CONFIG_OF_DYNAMIC)
-static int of_property_notify(int action, struct device_node *np,
- struct property *prop)
-{
- struct of_prop_reconfig pr;
-
- /* only call notifiers if the node is attached */
- if (!of_node_is_attached(np))
- return 0;
-
- pr.dn = np;
- pr.prop = prop;
- return of_reconfig_notify(action, &pr);
-}
-#else
-static int of_property_notify(int action, struct device_node *np,
- struct property *prop)
-{
- return 0;
-}
-#endif
-
/**
* __of_add_property - Add a property to a node without lock operations
*/
-static int __of_add_property(struct device_node *np, struct property *prop)
+int __of_add_property(struct device_node *np, struct property *prop)
{
struct property **next;
@@ -1799,22 +1675,49 @@ int of_add_property(struct device_node *np, struct property *prop)
unsigned long flags;
int rc;
- rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
- if (rc)
- return rc;
+ mutex_lock(&of_mutex);
raw_spin_lock_irqsave(&devtree_lock, flags);
rc = __of_add_property(np, prop);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (rc)
- return rc;
- if (of_node_is_attached(np))
+ if (!rc)
__of_add_property_sysfs(np, prop);
+ mutex_unlock(&of_mutex);
+
+ if (!rc)
+ of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
+
return rc;
}
+int __of_remove_property(struct device_node *np, struct property *prop)
+{
+ struct property **next;
+
+ for (next = &np->properties; *next; next = &(*next)->next) {
+ if (*next == prop)
+ break;
+ }
+ if (*next == NULL)
+ return -ENODEV;
+
+ /* found the node */
+ *next = prop->next;
+ prop->next = np->deadprops;
+ np->deadprops = prop;
+
+ return 0;
+}
+
+void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
+{
+ /* at early boot, bail here and defer setup to of_init() */
+ if (of_kset && of_node_is_attached(np))
+ sysfs_remove_bin_file(&np->kobj, &prop->attr);
+}
+
/**
* of_remove_property - Remove a property from a node.
*
@@ -1825,211 +1728,98 @@ int of_add_property(struct device_node *np, struct property *prop)
*/
int of_remove_property(struct device_node *np, struct property *prop)
{
- struct property **next;
unsigned long flags;
- int found = 0;
int rc;
- rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
- if (rc)
- return rc;
+ mutex_lock(&of_mutex);
raw_spin_lock_irqsave(&devtree_lock, flags);
- next = &np->properties;
- while (*next) {
- if (*next == prop) {
- /* found the node */
- *next = prop->next;
- prop->next = np->deadprops;
- np->deadprops = prop;
- found = 1;
- break;
- }
- next = &(*next)->next;
- }
+ rc = __of_remove_property(np, prop);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (!found)
- return -ENODEV;
+ if (!rc)
+ __of_remove_property_sysfs(np, prop);
- /* at early boot, bail hear and defer setup to of_init() */
- if (!of_kset)
- return 0;
+ mutex_unlock(&of_mutex);
- sysfs_remove_bin_file(&np->kobj, &prop->attr);
+ if (!rc)
+ of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
- return 0;
+ return rc;
}
-/*
- * of_update_property - Update a property in a node, if the property does
- * not exist, add it.
- *
- * Note that we don't actually remove it, since we have given out
- * who-knows-how-many pointers to the data using get-property.
- * Instead we just move the property to the "dead properties" list,
- * and add the new property to the property list
- */
-int of_update_property(struct device_node *np, struct property *newprop)
+int __of_update_property(struct device_node *np, struct property *newprop,
+ struct property **oldpropp)
{
struct property **next, *oldprop;
- unsigned long flags;
- int rc;
-
- rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
- if (rc)
- return rc;
- if (!newprop->name)
- return -EINVAL;
+ for (next = &np->properties; *next; next = &(*next)->next) {
+ if (of_prop_cmp((*next)->name, newprop->name) == 0)
+ break;
+ }
+ *oldpropp = oldprop = *next;
- raw_spin_lock_irqsave(&devtree_lock, flags);
- next = &np->properties;
- oldprop = __of_find_property(np, newprop->name, NULL);
- if (!oldprop) {
- /* add the new node */
- rc = __of_add_property(np, newprop);
- } else while (*next) {
+ if (oldprop) {
/* replace the node */
- if (*next == oldprop) {
- newprop->next = oldprop->next;
- *next = newprop;
- oldprop->next = np->deadprops;
- np->deadprops = oldprop;
- break;
- }
- next = &(*next)->next;
+ newprop->next = oldprop->next;
+ *next = newprop;
+ oldprop->next = np->deadprops;
+ np->deadprops = oldprop;
+ } else {
+ /* new node */
+ newprop->next = NULL;
+ *next = newprop;
}
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (rc)
- return rc;
+ return 0;
+}
+
+void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
+ struct property *oldprop)
+{
/* At early boot, bail out and defer setup to of_init() */
if (!of_kset)
- return 0;
+ return;
- /* Update the sysfs attribute */
if (oldprop)
sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
__of_add_property_sysfs(np, newprop);
-
- return 0;
}
-#if defined(CONFIG_OF_DYNAMIC)
/*
- * Support for dynamic device trees.
+ * of_update_property - Update a property in a node, if the property does
+ * not exist, add it.
*
- * On some platforms, the device tree can be manipulated at runtime.
- * The routines in this section support adding, removing and changing
- * device tree nodes.
- */
-
-static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
-
-int of_reconfig_notifier_register(struct notifier_block *nb)
-{
- return blocking_notifier_chain_register(&of_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
-
-int of_reconfig_notifier_unregister(struct notifier_block *nb)
-{
- return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
-}
-EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
-
-int of_reconfig_notify(unsigned long action, void *p)
-{
- int rc;
-
- rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
- return notifier_to_errno(rc);
-}
-
-/**
- * of_attach_node - Plug a device node into the tree and global list.
+ * Note that we don't actually remove it, since we have given out
+ * who-knows-how-many pointers to the data using get-property.
+ * Instead we just move the property to the "dead properties" list,
+ * and add the new property to the property list
*/
-int of_attach_node(struct device_node *np)
+int of_update_property(struct device_node *np, struct property *newprop)
{
+ struct property *oldprop;
unsigned long flags;
int rc;
- rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
- if (rc)
- return rc;
-
- raw_spin_lock_irqsave(&devtree_lock, flags);
- np->sibling = np->parent->child;
- np->allnext = np->parent->allnext;
- np->parent->allnext = np;
- np->parent->child = np;
- of_node_clear_flag(np, OF_DETACHED);
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
-
- of_node_add(np);
- return 0;
-}
-
-/**
- * of_detach_node - "Unplug" a node from the device tree.
- *
- * The caller must hold a reference to the node. The memory associated with
- * the node is not freed until its refcount goes to zero.
- */
-int of_detach_node(struct device_node *np)
-{
- struct device_node *parent;
- unsigned long flags;
- int rc = 0;
+ if (!newprop->name)
+ return -EINVAL;
- rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
- if (rc)
- return rc;
+ mutex_lock(&of_mutex);
raw_spin_lock_irqsave(&devtree_lock, flags);
+ rc = __of_update_property(np, newprop, &oldprop);
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (of_node_check_flag(np, OF_DETACHED)) {
- /* someone already detached it */
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
- return rc;
- }
-
- parent = np->parent;
- if (!parent) {
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
- return rc;
- }
+ if (!rc)
+ __of_update_property_sysfs(np, newprop, oldprop);
- if (of_allnodes == np)
- of_allnodes = np->allnext;
- else {
- struct device_node *prev;
- for (prev = of_allnodes;
- prev->allnext != np;
- prev = prev->allnext)
- ;
- prev->allnext = np->allnext;
- }
+ mutex_unlock(&of_mutex);
- if (parent->child == np)
- parent->child = np->sibling;
- else {
- struct device_node *prevsib;
- for (prevsib = np->parent->child;
- prevsib->sibling != np;
- prevsib = prevsib->sibling)
- ;
- prevsib->sibling = np->sibling;
- }
-
- of_node_set_flag(np, OF_DETACHED);
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
+ if (!rc)
+ of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
- of_node_remove(np);
return rc;
}
-#endif /* defined(CONFIG_OF_DYNAMIC) */
static void of_alias_add(struct alias_prop *ap, struct device_node *np,
int id, const char *stem, int stem_len)
@@ -2062,9 +1852,12 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
of_chosen = of_find_node_by_path("/chosen@0");
if (of_chosen) {
+ /* linux,stdout-path and /aliases/stdout are for legacy compatibility */
const char *name = of_get_property(of_chosen, "stdout-path", NULL);
if (!name)
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+ if (IS_ENABLED(CONFIG_PPC) && !name)
+ name = of_get_property(of_aliases, "stdout", NULL);
if (name)
of_stdout = of_find_node_by_path(name);
}
@@ -2122,7 +1915,7 @@ int of_alias_get_id(struct device_node *np, const char *stem)
struct alias_prop *app;
int id = -ENODEV;
- mutex_lock(&of_aliases_mutex);
+ mutex_lock(&of_mutex);
list_for_each_entry(app, &aliases_lookup, link) {
if (strcmp(app->stem, stem) != 0)
continue;
@@ -2132,7 +1925,7 @@ int of_alias_get_id(struct device_node *np, const char *stem)
break;
}
}
- mutex_unlock(&of_aliases_mutex);
+ mutex_unlock(&of_mutex);
return id;
}
@@ -2180,20 +1973,22 @@ const char *of_prop_next_string(struct property *prop, const char *cur)
EXPORT_SYMBOL_GPL(of_prop_next_string);
/**
- * of_device_is_stdout_path - check if a device node matches the
- * linux,stdout-path property
- *
- * Check if this device node matches the linux,stdout-path property
- * in the chosen node. return true if yes, false otherwise.
+ * of_console_check() - Test and setup console for DT setup
+ * @dn - Pointer to device node
+ * @name - Name to use for preferred console without index. ex. "ttyS"
+ * @index - Index to use for preferred console.
+ *
+ * Check if the given device node matches the stdout-path property in the
+ * /chosen node. If it does then register it as the preferred console and return
+ * TRUE. Otherwise return FALSE.
*/
-int of_device_is_stdout_path(struct device_node *dn)
+bool of_console_check(struct device_node *dn, char *name, int index)
{
- if (!of_stdout)
+ if (!dn || dn != of_stdout || console_set_on_cmdline)
return false;
-
- return of_stdout == dn;
+ return add_preferred_console(name, index, NULL);
}
-EXPORT_SYMBOL_GPL(of_device_is_stdout_path);
+EXPORT_SYMBOL_GPL(of_console_check);
/**
* of_find_next_cache_node - Find a node's subsidiary cache
diff --git a/drivers/of/device.c b/drivers/of/device.c
index dafb9736ab9b..46d6c75c1404 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -160,7 +160,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
seen = 0;
- mutex_lock(&of_aliases_mutex);
+ mutex_lock(&of_mutex);
list_for_each_entry(app, &aliases_lookup, link) {
if (dev->of_node == app->np) {
add_uevent_var(env, "OF_ALIAS_%d=%s", seen,
@@ -168,7 +168,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
seen++;
}
}
- mutex_unlock(&of_aliases_mutex);
+ mutex_unlock(&of_mutex);
}
int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
new file mode 100644
index 000000000000..54fecc49a1fe
--- /dev/null
+++ b/drivers/of/dynamic.c
@@ -0,0 +1,660 @@
+/*
+ * Support for dynamic device trees.
+ *
+ * On some platforms, the device tree can be manipulated at runtime.
+ * The routines in this section support adding, removing and changing
+ * device tree nodes.
+ */
+
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+
+#include "of_private.h"
+
+/**
+ * of_node_get() - Increment refcount of a node
+ * @node: Node to inc refcount, NULL is supported to simplify writing of
+ * callers
+ *
+ * Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+ if (node)
+ kobject_get(&node->kobj);
+ return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+/**
+ * of_node_put() - Decrement refcount of a node
+ * @node: Node to dec refcount, NULL is supported to simplify writing of
+ * callers
+ */
+void of_node_put(struct device_node *node)
+{
+ if (node)
+ kobject_put(&node->kobj);
+}
+EXPORT_SYMBOL(of_node_put);
+
+void __of_detach_node_sysfs(struct device_node *np)
+{
+ struct property *pp;
+
+ BUG_ON(!of_node_is_initialized(np));
+ if (!of_kset)
+ return;
+
+ /* only remove properties if on sysfs */
+ if (of_node_is_attached(np)) {
+ for_each_property_of_node(np, pp)
+ sysfs_remove_bin_file(&np->kobj, &pp->attr);
+ kobject_del(&np->kobj);
+ }
+
+ /* finally remove the kobj_init ref */
+ of_node_put(np);
+}
+
+static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
+
+int of_reconfig_notifier_register(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
+
+int of_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
+}
+EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
+
+int of_reconfig_notify(unsigned long action, void *p)
+{
+ int rc;
+
+ rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
+ return notifier_to_errno(rc);
+}
+
+int of_property_notify(int action, struct device_node *np,
+ struct property *prop, struct property *oldprop)
+{
+ struct of_prop_reconfig pr;
+
+ /* only call notifiers if the node is attached */
+ if (!of_node_is_attached(np))
+ return 0;
+
+ pr.dn = np;
+ pr.prop = prop;
+ pr.old_prop = oldprop;
+ return of_reconfig_notify(action, &pr);
+}
+
+void __of_attach_node(struct device_node *np)
+{
+ const __be32 *phandle;
+ int sz;
+
+ np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
+ np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
+
+ phandle = __of_get_property(np, "phandle", &sz);
+ if (!phandle)
+ phandle = __of_get_property(np, "linux,phandle", &sz);
+ if (IS_ENABLED(PPC_PSERIES) && !phandle)
+ phandle = __of_get_property(np, "ibm,phandle", &sz);
+ np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
+
+ np->child = NULL;
+ np->sibling = np->parent->child;
+ np->allnext = np->parent->allnext;
+ np->parent->allnext = np;
+ np->parent->child = np;
+ of_node_clear_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_attach_node() - Plug a device node into the tree and global list.
+ */
+int of_attach_node(struct device_node *np)
+{
+ unsigned long flags;
+
+ mutex_lock(&of_mutex);
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ __of_attach_node(np);
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+ __of_attach_node_sysfs(np);
+ mutex_unlock(&of_mutex);
+
+ of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
+
+ return 0;
+}
+
+void __of_detach_node(struct device_node *np)
+{
+ struct device_node *parent;
+
+ if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
+ return;
+
+ parent = np->parent;
+ if (WARN_ON(!parent))
+ return;
+
+ if (of_allnodes == np)
+ of_allnodes = np->allnext;
+ else {
+ struct device_node *prev;
+ for (prev = of_allnodes;
+ prev->allnext != np;
+ prev = prev->allnext)
+ ;
+ prev->allnext = np->allnext;
+ }
+
+ if (parent->child == np)
+ parent->child = np->sibling;
+ else {
+ struct device_node *prevsib;
+ for (prevsib = np->parent->child;
+ prevsib->sibling != np;
+ prevsib = prevsib->sibling)
+ ;
+ prevsib->sibling = np->sibling;
+ }
+
+ of_node_set_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_detach_node() - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node. The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+int of_detach_node(struct device_node *np)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ mutex_lock(&of_mutex);
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ __of_detach_node(np);
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+ __of_detach_node_sysfs(np);
+ mutex_unlock(&of_mutex);
+
+ of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+
+ return rc;
+}
+
+/**
+ * of_node_release() - release a dynamically allocated node
+ * @kref: kref element of the node to be released
+ *
+ * In of_node_put() this function is passed to kref_put() as the destructor.
+ */
+void of_node_release(struct kobject *kobj)
+{
+ struct device_node *node = kobj_to_device_node(kobj);
+ struct property *prop = node->properties;
+
+ /* We should never be releasing nodes that haven't been detached. */
+ if (!of_node_check_flag(node, OF_DETACHED)) {
+ pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
+ dump_stack();
+ return;
+ }
+
+ if (!of_node_check_flag(node, OF_DYNAMIC))
+ return;
+
+ while (prop) {
+ struct property *next = prop->next;
+ kfree(prop->name);
+ kfree(prop->value);
+ kfree(prop);
+ prop = next;
+
+ if (!prop) {
+ prop = node->deadprops;
+ node->deadprops = NULL;
+ }
+ }
+ kfree(node->full_name);
+ kfree(node->data);
+ kfree(node);
+}
+
+/**
+ * __of_prop_dup - Copy a property dynamically.
+ * @prop: Property to copy
+ * @allocflags: Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Copy a property by dynamically allocating the memory of both the
+ * property stucture and the property name & contents. The property's
+ * flags have the OF_DYNAMIC bit set so that we can differentiate between
+ * dynamically allocated properties and not.
+ * Returns the newly allocated property or NULL on out of memory error.
+ */
+struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
+{
+ struct property *new;
+
+ new = kzalloc(sizeof(*new), allocflags);
+ if (!new)
+ return NULL;
+
+ /*
+ * NOTE: There is no check for zero length value.
+ * In case of a boolean property, this will allocate a value
+ * of zero bytes. We do this to work around the use
+ * of of_get_property() calls on boolean values.
+ */
+ new->name = kstrdup(prop->name, allocflags);
+ new->value = kmemdup(prop->value, prop->length, allocflags);
+ new->length = prop->length;
+ if (!new->name || !new->value)
+ goto err_free;
+
+ /* mark the property as dynamic */
+ of_property_set_flag(new, OF_DYNAMIC);
+
+ return new;
+
+ err_free:
+ kfree(new->name);
+ kfree(new->value);
+ kfree(new);
+ return NULL;
+}
+
+/**
+ * __of_node_alloc() - Create an empty device node dynamically.
+ * @full_name: Full name of the new device node
+ * @allocflags: Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Create an empty device tree node, suitable for further modification.
+ * The node data are dynamically allocated and all the node flags
+ * have the OF_DYNAMIC & OF_DETACHED bits set.
+ * Returns the newly allocated node or NULL on out of memory error.
+ */
+struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags)
+{
+ struct device_node *node;
+
+ node = kzalloc(sizeof(*node), allocflags);
+ if (!node)
+ return NULL;
+
+ node->full_name = kstrdup(full_name, allocflags);
+ of_node_set_flag(node, OF_DYNAMIC);
+ of_node_set_flag(node, OF_DETACHED);
+ if (!node->full_name)
+ goto err_free;
+
+ of_node_init(node);
+
+ return node;
+
+ err_free:
+ kfree(node->full_name);
+ kfree(node);
+ return NULL;
+}
+
+static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
+{
+ of_node_put(ce->np);
+ list_del(&ce->node);
+ kfree(ce);
+}
+
+#ifdef DEBUG
+static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
+{
+ switch (ce->action) {
+ case OF_RECONFIG_ADD_PROPERTY:
+ pr_debug("%p: %s %s/%s\n",
+ ce, "ADD_PROPERTY ", ce->np->full_name,
+ ce->prop->name);
+ break;
+ case OF_RECONFIG_REMOVE_PROPERTY:
+ pr_debug("%p: %s %s/%s\n",
+ ce, "REMOVE_PROPERTY", ce->np->full_name,
+ ce->prop->name);
+ break;
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ pr_debug("%p: %s %s/%s\n",
+ ce, "UPDATE_PROPERTY", ce->np->full_name,
+ ce->prop->name);
+ break;
+ case OF_RECONFIG_ATTACH_NODE:
+ pr_debug("%p: %s %s\n",
+ ce, "ATTACH_NODE ", ce->np->full_name);
+ break;
+ case OF_RECONFIG_DETACH_NODE:
+ pr_debug("%p: %s %s\n",
+ ce, "DETACH_NODE ", ce->np->full_name);
+ break;
+ }
+}
+#else
+static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
+{
+ /* empty */
+}
+#endif
+
+static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
+ struct of_changeset_entry *rce)
+{
+ memcpy(rce, ce, sizeof(*rce));
+
+ switch (ce->action) {
+ case OF_RECONFIG_ATTACH_NODE:
+ rce->action = OF_RECONFIG_DETACH_NODE;
+ break;
+ case OF_RECONFIG_DETACH_NODE:
+ rce->action = OF_RECONFIG_ATTACH_NODE;
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ rce->action = OF_RECONFIG_REMOVE_PROPERTY;
+ break;
+ case OF_RECONFIG_REMOVE_PROPERTY:
+ rce->action = OF_RECONFIG_ADD_PROPERTY;
+ break;
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ rce->old_prop = ce->prop;
+ rce->prop = ce->old_prop;
+ break;
+ }
+}
+
+static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert)
+{
+ struct of_changeset_entry ce_inverted;
+ int ret;
+
+ if (revert) {
+ __of_changeset_entry_invert(ce, &ce_inverted);
+ ce = &ce_inverted;
+ }
+
+ switch (ce->action) {
+ case OF_RECONFIG_ATTACH_NODE:
+ case OF_RECONFIG_DETACH_NODE:
+ ret = of_reconfig_notify(ce->action, ce->np);
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ case OF_RECONFIG_REMOVE_PROPERTY:
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
+ break;
+ default:
+ pr_err("%s: invalid devicetree changeset action: %i\n", __func__,
+ (int)ce->action);
+ return;
+ }
+
+ if (ret)
+ pr_err("%s: notifier error @%s\n", __func__, ce->np->full_name);
+}
+
+static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
+{
+ struct property *old_prop, **propp;
+ unsigned long flags;
+ int ret = 0;
+
+ __of_changeset_entry_dump(ce);
+
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ switch (ce->action) {
+ case OF_RECONFIG_ATTACH_NODE:
+ __of_attach_node(ce->np);
+ break;
+ case OF_RECONFIG_DETACH_NODE:
+ __of_detach_node(ce->np);
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ /* If the property is in deadprops then it must be removed */
+ for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
+ if (*propp == ce->prop) {
+ *propp = ce->prop->next;
+ ce->prop->next = NULL;
+ break;
+ }
+ }
+
+ ret = __of_add_property(ce->np, ce->prop);
+ if (ret) {
+ pr_err("%s: add_property failed @%s/%s\n",
+ __func__, ce->np->full_name,
+ ce->prop->name);
+ break;
+ }
+ break;
+ case OF_RECONFIG_REMOVE_PROPERTY:
+ ret = __of_remove_property(ce->np, ce->prop);
+ if (ret) {
+ pr_err("%s: remove_property failed @%s/%s\n",
+ __func__, ce->np->full_name,
+ ce->prop->name);
+ break;
+ }
+ break;
+
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ /* If the property is in deadprops then it must be removed */
+ for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
+ if (*propp == ce->prop) {
+ *propp = ce->prop->next;
+ ce->prop->next = NULL;
+ break;
+ }
+ }
+
+ ret = __of_update_property(ce->np, ce->prop, &old_prop);
+ if (ret) {
+ pr_err("%s: update_property failed @%s/%s\n",
+ __func__, ce->np->full_name,
+ ce->prop->name);
+ break;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+ if (ret)
+ return ret;
+
+ switch (ce->action) {
+ case OF_RECONFIG_ATTACH_NODE:
+ __of_attach_node_sysfs(ce->np);
+ break;
+ case OF_RECONFIG_DETACH_NODE:
+ __of_detach_node_sysfs(ce->np);
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ /* ignore duplicate names */
+ __of_add_property_sysfs(ce->np, ce->prop);
+ break;
+ case OF_RECONFIG_REMOVE_PROPERTY:
+ __of_remove_property_sysfs(ce->np, ce->prop);
+ break;
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ __of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
+ break;
+ }
+
+ return 0;
+}
+
+static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
+{
+ struct of_changeset_entry ce_inverted;
+
+ __of_changeset_entry_invert(ce, &ce_inverted);
+ return __of_changeset_entry_apply(&ce_inverted);
+}
+
+/**
+ * of_changeset_init - Initialize a changeset for use
+ *
+ * @ocs: changeset pointer
+ *
+ * Initialize a changeset structure
+ */
+void of_changeset_init(struct of_changeset *ocs)
+{
+ memset(ocs, 0, sizeof(*ocs));
+ INIT_LIST_HEAD(&ocs->entries);
+}
+
+/**
+ * of_changeset_destroy - Destroy a changeset
+ *
+ * @ocs: changeset pointer
+ *
+ * Destroys a changeset. Note that if a changeset is applied,
+ * its changes to the tree cannot be reverted.
+ */
+void of_changeset_destroy(struct of_changeset *ocs)
+{
+ struct of_changeset_entry *ce, *cen;
+
+ list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
+ __of_changeset_entry_destroy(ce);
+}
+
+/**
+ * of_changeset_apply - Applies a changeset
+ *
+ * @ocs: changeset pointer
+ *
+ * Applies a changeset to the live tree.
+ * Any side-effects of live tree state changes are applied here on
+ * sucess, like creation/destruction of devices and side-effects
+ * like creation of sysfs properties and directories.
+ * Returns 0 on success, a negative error value in case of an error.
+ * On error the partially applied effects are reverted.
+ */
+int of_changeset_apply(struct of_changeset *ocs)
+{
+ struct of_changeset_entry *ce;
+ int ret;
+
+ /* perform the rest of the work */
+ pr_debug("of_changeset: applying...\n");
+ list_for_each_entry(ce, &ocs->entries, node) {
+ ret = __of_changeset_entry_apply(ce);
+ if (ret) {
+ pr_err("%s: Error applying changeset (%d)\n", __func__, ret);
+ list_for_each_entry_continue_reverse(ce, &ocs->entries, node)
+ __of_changeset_entry_revert(ce);
+ return ret;
+ }
+ }
+ pr_debug("of_changeset: applied, emitting notifiers.\n");
+
+ /* drop the global lock while emitting notifiers */
+ mutex_unlock(&of_mutex);
+ list_for_each_entry(ce, &ocs->entries, node)
+ __of_changeset_entry_notify(ce, 0);
+ mutex_lock(&of_mutex);
+ pr_debug("of_changeset: notifiers sent.\n");
+
+ return 0;
+}
+
+/**
+ * of_changeset_revert - Reverts an applied changeset
+ *
+ * @ocs: changeset pointer
+ *
+ * Reverts a changeset returning the state of the tree to what it
+ * was before the application.
+ * Any side-effects like creation/destruction of devices and
+ * removal of sysfs properties and directories are applied.
+ * Returns 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_revert(struct of_changeset *ocs)
+{
+ struct of_changeset_entry *ce;
+ int ret;
+
+ pr_debug("of_changeset: reverting...\n");
+ list_for_each_entry_reverse(ce, &ocs->entries, node) {
+ ret = __of_changeset_entry_revert(ce);
+ if (ret) {
+ pr_err("%s: Error reverting changeset (%d)\n", __func__, ret);
+ list_for_each_entry_continue(ce, &ocs->entries, node)
+ __of_changeset_entry_apply(ce);
+ return ret;
+ }
+ }
+ pr_debug("of_changeset: reverted, emitting notifiers.\n");
+
+ /* drop the global lock while emitting notifiers */
+ mutex_unlock(&of_mutex);
+ list_for_each_entry_reverse(ce, &ocs->entries, node)
+ __of_changeset_entry_notify(ce, 1);
+ mutex_lock(&of_mutex);
+ pr_debug("of_changeset: notifiers sent.\n");
+
+ return 0;
+}
+
+/**
+ * of_changeset_action - Perform a changeset action
+ *
+ * @ocs: changeset pointer
+ * @action: action to perform
+ * @np: Pointer to device node
+ * @prop: Pointer to property
+ *
+ * On action being one of:
+ * + OF_RECONFIG_ATTACH_NODE
+ * + OF_RECONFIG_DETACH_NODE,
+ * + OF_RECONFIG_ADD_PROPERTY
+ * + OF_RECONFIG_REMOVE_PROPERTY,
+ * + OF_RECONFIG_UPDATE_PROPERTY
+ * Returns 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_action(struct of_changeset *ocs, unsigned long action,
+ struct device_node *np, struct property *prop)
+{
+ struct of_changeset_entry *ce;
+
+ ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+ if (!ce) {
+ pr_err("%s: Failed to allocate\n", __func__);
+ return -ENOMEM;
+ }
+ /* get a reference to the node */
+ ce->action = action;
+ ce->np = of_node_get(np);
+ ce->prop = prop;
+
+ if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
+ ce->old_prop = of_find_property(np, prop->name, NULL);
+
+ /* add it to the list */
+ list_add_tail(&ce->node, &ocs->entries);
+ return 0;
+}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 9aa012e6ea0a..f46a24ffa3fe 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -923,24 +923,24 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
}
#ifdef CONFIG_HAVE_MEMBLOCK
+#define MAX_PHYS_ADDR ((phys_addr_t)~0)
+
void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
{
const u64 phys_offset = __pa(PAGE_OFFSET);
base &= PAGE_MASK;
size &= PAGE_MASK;
- if (sizeof(phys_addr_t) < sizeof(u64)) {
- if (base > ULONG_MAX) {
- pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
- base, base + size);
- return;
- }
+ if (base > MAX_PHYS_ADDR) {
+ pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
+ base, base + size);
+ return;
+ }
- if (base + size > ULONG_MAX) {
- pr_warning("Ignoring memory range 0x%lx - 0x%llx\n",
- ULONG_MAX, base + size);
- size = ULONG_MAX - base;
- }
+ if (base + size > MAX_PHYS_ADDR) {
+ pr_warning("Ignoring memory range 0x%lx - 0x%llx\n",
+ ULONG_MAX, base + size);
+ size = MAX_PHYS_ADDR - base;
}
if (base + size < phys_offset) {
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index ff350c8fa7ac..858e0a5d9a11 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -31,6 +31,63 @@ struct alias_prop {
char stem[0];
};
-extern struct mutex of_aliases_mutex;
+extern struct mutex of_mutex;
extern struct list_head aliases_lookup;
+extern struct kset *of_kset;
+
+
+static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
+{
+ return container_of(kobj, struct device_node, kobj);
+}
+
+#if defined(CONFIG_OF_DYNAMIC)
+extern int of_property_notify(int action, struct device_node *np,
+ struct property *prop, struct property *old_prop);
+extern void of_node_release(struct kobject *kobj);
+#else /* CONFIG_OF_DYNAMIC */
+static inline int of_property_notify(int action, struct device_node *np,
+ struct property *prop, struct property *old_prop)
+{
+ return 0;
+}
+#endif /* CONFIG_OF_DYNAMIC */
+
+/**
+ * General utilities for working with live trees.
+ *
+ * All functions with two leading underscores operate
+ * without taking node references, so you either have to
+ * own the devtree lock or work on detached trees only.
+ */
+struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
+struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags);
+
+extern const void *__of_get_property(const struct device_node *np,
+ const char *name, int *lenp);
+extern int __of_add_property(struct device_node *np, struct property *prop);
+extern int __of_add_property_sysfs(struct device_node *np,
+ struct property *prop);
+extern int __of_remove_property(struct device_node *np, struct property *prop);
+extern void __of_remove_property_sysfs(struct device_node *np,
+ struct property *prop);
+extern int __of_update_property(struct device_node *np,
+ struct property *newprop, struct property **oldprop);
+extern void __of_update_property_sysfs(struct device_node *np,
+ struct property *newprop, struct property *oldprop);
+
+extern void __of_attach_node(struct device_node *np);
+extern int __of_attach_node_sysfs(struct device_node *np);
+extern void __of_detach_node(struct device_node *np);
+extern void __of_detach_node_sysfs(struct device_node *np);
+
+/* iterators for transactions, used for overlays */
+/* forward iterator */
+#define for_each_transaction_entry(_oft, _te) \
+ list_for_each_entry(_te, &(_oft)->te_list, node)
+
+/* reverse iterator */
+#define for_each_transaction_entry_reverse(_oft, _te) \
+ list_for_each_entry_reverse(_te, &(_oft)->te_list, node)
+
#endif /* _LINUX_OF_PRIVATE_H */
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 632aae861375..59fb12e84e6b 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -206,8 +206,16 @@ void __init fdt_init_reserved_mem(void)
for (i = 0; i < reserved_mem_count; i++) {
struct reserved_mem *rmem = &reserved_mem[i];
unsigned long node = rmem->fdt_node;
+ int len;
+ const __be32 *prop;
int err = 0;
+ prop = of_get_flat_dt_prop(node, "phandle", &len);
+ if (!prop)
+ prop = of_get_flat_dt_prop(node, "linux,phandle", &len);
+ if (prop)
+ rmem->phandle = of_read_number(prop, len/4);
+
if (rmem->size == 0)
err = __reserved_mem_alloc_size(node, rmem->name,
&rmem->base, &rmem->size);
@@ -215,3 +223,65 @@ void __init fdt_init_reserved_mem(void)
__reserved_mem_init_node(rmem);
}
}
+
+static inline struct reserved_mem *__find_rmem(struct device_node *node)
+{
+ unsigned int i;
+
+ if (!node->phandle)
+ return NULL;
+
+ for (i = 0; i < reserved_mem_count; i++)
+ if (reserved_mem[i].phandle == node->phandle)
+ return &reserved_mem[i];
+ return NULL;
+}
+
+/**
+ * of_reserved_mem_device_init() - assign reserved memory region to given device
+ *
+ * This function assign memory region pointed by "memory-region" device tree
+ * property to the given device.
+ */
+void of_reserved_mem_device_init(struct device *dev)
+{
+ struct reserved_mem *rmem;
+ struct device_node *np;
+
+ np = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (!np)
+ return;
+
+ rmem = __find_rmem(np);
+ of_node_put(np);
+
+ if (!rmem || !rmem->ops || !rmem->ops->device_init)
+ return;
+
+ rmem->ops->device_init(rmem, dev);
+ dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
+}
+
+/**
+ * of_reserved_mem_device_release() - release reserved memory device structures
+ *
+ * This function releases structures allocated for memory region handling for
+ * the given device.
+ */
+void of_reserved_mem_device_release(struct device *dev)
+{
+ struct reserved_mem *rmem;
+ struct device_node *np;
+
+ np = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (!np)
+ return;
+
+ rmem = __find_rmem(np);
+ of_node_put(np);
+
+ if (!rmem || !rmem->ops || !rmem->ops->device_release)
+ return;
+
+ rmem->ops->device_release(rmem, dev);
+}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 500436f9be7f..0197725e033a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -422,6 +422,7 @@ static int of_platform_bus_create(struct device_node *bus,
break;
}
}
+ of_node_set_flag(bus, OF_POPULATED_BUS);
return rc;
}
@@ -508,19 +509,13 @@ EXPORT_SYMBOL_GPL(of_platform_populate);
static int of_platform_device_destroy(struct device *dev, void *data)
{
- bool *children_left = data;
-
/* Do not touch devices not populated from the device tree */
- if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
- *children_left = true;
+ if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
return 0;
- }
- /* Recurse, but don't touch this device if it has any children left */
- if (of_platform_depopulate(dev) != 0) {
- *children_left = true;
- return 0;
- }
+ /* Recurse for any nodes that were treated as busses */
+ if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+ device_for_each_child(dev, NULL, of_platform_device_destroy);
if (dev->bus == &platform_bus_type)
platform_device_unregister(to_platform_device(dev));
@@ -528,19 +523,15 @@ static int of_platform_device_destroy(struct device *dev, void *data)
else if (dev->bus == &amba_bustype)
amba_device_unregister(to_amba_device(dev));
#endif
- else {
- *children_left = true;
- return 0;
- }
of_node_clear_flag(dev->of_node, OF_POPULATED);
-
+ of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
return 0;
}
/**
* of_platform_depopulate() - Remove devices populated from device tree
- * @parent: device which childred will be removed
+ * @parent: device which children will be removed
*
* Complementary to of_platform_populate(), this function removes children
* of the given device (and, recurrently, their children) that have been
@@ -550,14 +541,9 @@ static int of_platform_device_destroy(struct device *dev, void *data)
* Returns 0 when all children devices have been removed or
* -EBUSY when some children remained.
*/
-int of_platform_depopulate(struct device *parent)
+void of_platform_depopulate(struct device *parent)
{
- bool children_left = false;
-
- device_for_each_child(parent, &children_left,
- of_platform_device_destroy);
-
- return children_left ? -EBUSY : 0;
+ device_for_each_child(parent, NULL, of_platform_device_destroy);
}
EXPORT_SYMBOL_GPL(of_platform_depopulate);
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 077314eebb95..d41002667833 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/list.h>
@@ -16,11 +17,17 @@
#include <linux/slab.h>
#include <linux/device.h>
+#include "of_private.h"
+
static struct selftest_results {
int passed;
int failed;
} selftest_results;
+#define NO_OF_NODES 2
+static struct device_node *nodes[NO_OF_NODES];
+static int last_node_index;
+
#define selftest(result, fmt, ...) { \
if (!(result)) { \
selftest_results.failed++; \
@@ -266,6 +273,81 @@ static void __init of_selftest_property_match_string(void)
selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
}
+#define propcmp(p1, p2) (((p1)->length == (p2)->length) && \
+ (p1)->value && (p2)->value && \
+ !memcmp((p1)->value, (p2)->value, (p1)->length) && \
+ !strcmp((p1)->name, (p2)->name))
+static void __init of_selftest_property_copy(void)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ struct property p1 = { .name = "p1", .length = 0, .value = "" };
+ struct property p2 = { .name = "p2", .length = 5, .value = "abcd" };
+ struct property *new;
+
+ new = __of_prop_dup(&p1, GFP_KERNEL);
+ selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n");
+ kfree(new->value);
+ kfree(new->name);
+ kfree(new);
+
+ new = __of_prop_dup(&p2, GFP_KERNEL);
+ selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n");
+ kfree(new->value);
+ kfree(new->name);
+ kfree(new);
+#endif
+}
+
+static void __init of_selftest_changeset(void)
+{
+#ifdef CONFIG_OF_DYNAMIC
+ struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
+ struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
+ struct property *ppremove;
+ struct device_node *n1, *n2, *n21, *nremove, *parent;
+ struct of_changeset chgset;
+
+ of_changeset_init(&chgset);
+ n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL);
+ selftest(n1, "testcase setup failure\n");
+ n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL);
+ selftest(n2, "testcase setup failure\n");
+ n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL);
+ selftest(n21, "testcase setup failure %p\n", n21);
+ nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
+ selftest(nremove, "testcase setup failure\n");
+ ppadd = __of_prop_dup(&padd, GFP_KERNEL);
+ selftest(ppadd, "testcase setup failure\n");
+ ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
+ selftest(ppupdate, "testcase setup failure\n");
+ parent = nremove->parent;
+ n1->parent = parent;
+ n2->parent = parent;
+ n21->parent = n2;
+ n2->child = n21;
+ ppremove = of_find_property(parent, "prop-remove", NULL);
+ selftest(ppremove, "failed to find removal prop");
+
+ of_changeset_init(&chgset);
+ selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
+ selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
+ selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
+ selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
+ selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
+ selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
+ selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
+ mutex_lock(&of_mutex);
+ selftest(!of_changeset_apply(&chgset), "apply failed\n");
+ mutex_unlock(&of_mutex);
+
+ mutex_lock(&of_mutex);
+ selftest(!of_changeset_revert(&chgset), "revert failed\n");
+ mutex_unlock(&of_mutex);
+
+ of_changeset_destroy(&chgset);
+#endif
+}
+
static void __init of_selftest_parse_interrupts(void)
{
struct device_node *np;
@@ -517,9 +599,156 @@ static void __init of_selftest_platform_populate(void)
}
}
+/**
+ * update_node_properties - adds the properties
+ * of np into dup node (present in live tree) and
+ * updates parent of children of np to dup.
+ *
+ * @np: node already present in live tree
+ * @dup: node present in live tree to be updated
+ */
+static void update_node_properties(struct device_node *np,
+ struct device_node *dup)
+{
+ struct property *prop;
+ struct device_node *child;
+
+ for_each_property_of_node(np, prop)
+ of_add_property(dup, prop);
+
+ for_each_child_of_node(np, child)
+ child->parent = dup;
+}
+
+/**
+ * attach_node_and_children - attaches nodes
+ * and its children to live tree
+ *
+ * @np: Node to attach to live tree
+ */
+static int attach_node_and_children(struct device_node *np)
+{
+ struct device_node *next, *root = np, *dup;
+
+ if (!np) {
+ pr_warn("%s: No tree to attach; not running tests\n",
+ __func__);
+ return -ENODATA;
+ }
+
+
+ /* skip root node */
+ np = np->child;
+ /* storing a copy in temporary node */
+ dup = np;
+
+ while (dup) {
+ nodes[last_node_index++] = dup;
+ dup = dup->sibling;
+ }
+ dup = NULL;
+
+ while (np) {
+ next = np->allnext;
+ dup = of_find_node_by_path(np->full_name);
+ if (dup)
+ update_node_properties(np, dup);
+ else {
+ np->child = NULL;
+ if (np->parent == root)
+ np->parent = of_allnodes;
+ of_attach_node(np);
+ }
+ np = next;
+ }
+
+ return 0;
+}
+
+/**
+ * selftest_data_add - Reads, copies data from
+ * linked tree and attaches it to the live tree
+ */
+static int __init selftest_data_add(void)
+{
+ void *selftest_data;
+ struct device_node *selftest_data_node;
+ extern uint8_t __dtb_testcases_begin[];
+ extern uint8_t __dtb_testcases_end[];
+ const int size = __dtb_testcases_end - __dtb_testcases_begin;
+
+ if (!size || !of_allnodes) {
+ pr_warn("%s: No testcase data to attach; not running tests\n",
+ __func__);
+ return -ENODATA;
+ }
+
+ /* creating copy */
+ selftest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL);
+
+ if (!selftest_data) {
+ pr_warn("%s: Failed to allocate memory for selftest_data; "
+ "not running tests\n", __func__);
+ return -ENOMEM;
+ }
+ of_fdt_unflatten_tree(selftest_data, &selftest_data_node);
+
+ /* attach the sub-tree to live tree */
+ return attach_node_and_children(selftest_data_node);
+}
+
+/**
+ * detach_node_and_children - detaches node
+ * and its children from live tree
+ *
+ * @np: Node to detach from live tree
+ */
+static void detach_node_and_children(struct device_node *np)
+{
+ while (np->child)
+ detach_node_and_children(np->child);
+
+ while (np->sibling)
+ detach_node_and_children(np->sibling);
+
+ of_detach_node(np);
+}
+
+/**
+ * selftest_data_remove - removes the selftest data
+ * nodes from the live tree
+ */
+static void selftest_data_remove(void)
+{
+ struct device_node *np;
+ struct property *prop;
+
+ while (last_node_index >= 0) {
+ if (nodes[last_node_index]) {
+ np = of_find_node_by_path(nodes[last_node_index]->full_name);
+ if (strcmp(np->full_name, "/aliases") != 0) {
+ detach_node_and_children(np->child);
+ of_detach_node(np);
+ } else {
+ for_each_property_of_node(np, prop) {
+ if (strcmp(prop->name, "testcase-alias") == 0)
+ of_remove_property(np, prop);
+ }
+ }
+ }
+ last_node_index--;
+ }
+}
+
static int __init of_selftest(void)
{
struct device_node *np;
+ int res;
+
+ /* adding data for selftest */
+ res = selftest_data_add();
+ if (res)
+ return res;
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
if (!np) {
@@ -533,12 +762,18 @@ static int __init of_selftest(void)
of_selftest_dynamic();
of_selftest_parse_phandle_with_args();
of_selftest_property_match_string();
+ of_selftest_property_copy();
+ of_selftest_changeset();
of_selftest_parse_interrupts();
of_selftest_parse_interrupts_extended();
of_selftest_match_node();
of_selftest_platform_populate();
pr_info("end of selftest - %i passed, %i failed\n",
selftest_results.passed, selftest_results.failed);
+
+ /* removing selftest data from live tree */
+ selftest_data_remove();
+
return 0;
}
late_initcall(of_selftest);
diff --git a/drivers/of/testcase-data/testcases.dts b/drivers/of/testcase-data/testcases.dts
new file mode 100644
index 000000000000..219ef9324e9c
--- /dev/null
+++ b/drivers/of/testcase-data/testcases.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/ {
+ testcase-data {
+ changeset {
+ prop-update = "hello";
+ prop-remove = "world";
+ node-remove {
+ };
+ };
+ };
+};
+#include "tests-phandle.dtsi"
+#include "tests-interrupts.dtsi"
+#include "tests-match.dtsi"
+#include "tests-platform.dtsi"
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi
deleted file mode 100644
index 6d8d980ac858..000000000000
--- a/drivers/of/testcase-data/testcases.dtsi
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "tests-phandle.dtsi"
-#include "tests-interrupts.dtsi"
-#include "tests-match.dtsi"
-#include "tests-platform.dtsi"
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
index c864f82bd37d..30e981be14c2 100644
--- a/drivers/parport/parport_ip32.c
+++ b/drivers/parport/parport_ip32.c
@@ -2204,7 +2204,7 @@ static int __init parport_ip32_init(void)
{
pr_info(PPIP32 "SGI IP32 built-in parallel port driver v0.6\n");
this_port = parport_ip32_probe_port();
- return IS_ERR(this_port) ? PTR_ERR(this_port) : 0;
+ return PTR_ERR_OR_ZERO(this_port);
}
/**
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 21df477be0c8..2d8a4d05d78f 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -46,4 +46,12 @@ config PCI_HOST_GENERIC
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
+config PCIE_SPEAR13XX
+ tristate "STMicroelectronics SPEAr PCIe controller"
+ depends on ARCH_SPEAR13XX
+ select PCIEPORTBUS
+ select PCIE_DW
+ help
+ Say Y here if you want PCIe support on SPEAr13XX SoCs.
+
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 611ba4b48c94..0daec7941aba 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
+obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 44fe6aa6a43f..3d2076f59911 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -385,4 +385,4 @@ module_platform_driver(gen_pci_driver);
MODULE_DESCRIPTION("Generic PCI host driver");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index ce23e0f076b6..a8c6f1a92e0f 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -1094,4 +1094,4 @@ module_platform_driver(mvebu_pcie_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell EBU PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 083cf37ca047..abd65784618d 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -41,11 +41,12 @@
#include <linux/reset.h>
#include <linux/sizes.h>
#include <linux/slab.h>
-#include <linux/tegra-cpuidle.h>
-#include <linux/tegra-powergate.h>
#include <linux/vmalloc.h>
#include <linux/regulator/consumer.h>
+#include <soc/tegra/cpuidle.h>
+#include <soc/tegra/pmc.h>
+
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <asm/mach/pci.h>
@@ -233,7 +234,6 @@ struct tegra_pcie_soc_data {
bool has_pex_clkreq_en;
bool has_pex_bias_ctrl;
bool has_intr_prsnt_sense;
- bool has_avdd_supply;
bool has_cml_clk;
};
@@ -272,9 +272,8 @@ struct tegra_pcie {
unsigned int num_ports;
u32 xbar_config;
- struct regulator *pex_clk_supply;
- struct regulator *vdd_supply;
- struct regulator *avdd_supply;
+ struct regulator_bulk_data *supplies;
+ unsigned int num_supplies;
const struct tegra_pcie_soc_data *soc_data;
};
@@ -894,7 +893,6 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
static void tegra_pcie_power_off(struct tegra_pcie *pcie)
{
- const struct tegra_pcie_soc_data *soc = pcie->soc_data;
int err;
/* TODO: disable and unprepare clocks? */
@@ -905,23 +903,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
- if (soc->has_avdd_supply) {
- err = regulator_disable(pcie->avdd_supply);
- if (err < 0)
- dev_warn(pcie->dev,
- "failed to disable AVDD regulator: %d\n",
- err);
- }
-
- err = regulator_disable(pcie->pex_clk_supply);
- if (err < 0)
- dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n",
- err);
-
- err = regulator_disable(pcie->vdd_supply);
+ err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
if (err < 0)
- dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n",
- err);
+ dev_warn(pcie->dev, "failed to disable regulators: %d\n", err);
}
static int tegra_pcie_power_on(struct tegra_pcie *pcie)
@@ -936,28 +920,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
/* enable regulators */
- err = regulator_enable(pcie->vdd_supply);
- if (err < 0) {
- dev_err(pcie->dev, "failed to enable VDD regulator: %d\n", err);
- return err;
- }
-
- err = regulator_enable(pcie->pex_clk_supply);
- if (err < 0) {
- dev_err(pcie->dev, "failed to enable pex-clk regulator: %d\n",
- err);
- return err;
- }
-
- if (soc->has_avdd_supply) {
- err = regulator_enable(pcie->avdd_supply);
- if (err < 0) {
- dev_err(pcie->dev,
- "failed to enable AVDD regulator: %d\n",
- err);
- return err;
- }
- }
+ err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies);
+ if (err < 0)
+ dev_err(pcie->dev, "failed to enable regulators: %d\n", err);
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
pcie->pex_clk,
@@ -1394,14 +1359,157 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
return -EINVAL;
}
+/*
+ * Check whether a given set of supplies is available in a device tree node.
+ * This is used to check whether the new or the legacy device tree bindings
+ * should be used.
+ */
+static bool of_regulator_bulk_available(struct device_node *np,
+ struct regulator_bulk_data *supplies,
+ unsigned int num_supplies)
+{
+ char property[32];
+ unsigned int i;
+
+ for (i = 0; i < num_supplies; i++) {
+ snprintf(property, 32, "%s-supply", supplies[i].supply);
+
+ if (of_find_property(np, property, NULL) == NULL)
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Old versions of the device tree binding for this device used a set of power
+ * supplies that didn't match the hardware inputs. This happened to work for a
+ * number of cases but is not future proof. However to preserve backwards-
+ * compatibility with old device trees, this function will try to use the old
+ * set of supplies.
+ */
+static int tegra_pcie_get_legacy_regulators(struct tegra_pcie *pcie)
+{
+ struct device_node *np = pcie->dev->of_node;
+
+ if (of_device_is_compatible(np, "nvidia,tegra30-pcie"))
+ pcie->num_supplies = 3;
+ else if (of_device_is_compatible(np, "nvidia,tegra20-pcie"))
+ pcie->num_supplies = 2;
+
+ if (pcie->num_supplies == 0) {
+ dev_err(pcie->dev, "device %s not supported in legacy mode\n",
+ np->full_name);
+ return -ENODEV;
+ }
+
+ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+ sizeof(*pcie->supplies),
+ GFP_KERNEL);
+ if (!pcie->supplies)
+ return -ENOMEM;
+
+ pcie->supplies[0].supply = "pex-clk";
+ pcie->supplies[1].supply = "vdd";
+
+ if (pcie->num_supplies > 2)
+ pcie->supplies[2].supply = "avdd";
+
+ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
+ pcie->supplies);
+}
+
+/*
+ * Obtains the list of regulators required for a particular generation of the
+ * IP block.
+ *
+ * This would've been nice to do simply by providing static tables for use
+ * with the regulator_bulk_*() API, but unfortunately Tegra30 is a bit quirky
+ * in that it has two pairs or AVDD_PEX and VDD_PEX supplies (PEXA and PEXB)
+ * and either seems to be optional depending on which ports are being used.
+ */
+static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
+{
+ struct device_node *np = pcie->dev->of_node;
+ unsigned int i = 0;
+
+ if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
+ bool need_pexa = false, need_pexb = false;
+
+ /* VDD_PEXA and AVDD_PEXA supply lanes 0 to 3 */
+ if (lane_mask & 0x0f)
+ need_pexa = true;
+
+ /* VDD_PEXB and AVDD_PEXB supply lanes 4 to 5 */
+ if (lane_mask & 0x30)
+ need_pexb = true;
+
+ pcie->num_supplies = 4 + (need_pexa ? 2 : 0) +
+ (need_pexb ? 2 : 0);
+
+ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+ sizeof(*pcie->supplies),
+ GFP_KERNEL);
+ if (!pcie->supplies)
+ return -ENOMEM;
+
+ pcie->supplies[i++].supply = "avdd-pex-pll";
+ pcie->supplies[i++].supply = "hvdd-pex";
+ pcie->supplies[i++].supply = "vddio-pex-ctl";
+ pcie->supplies[i++].supply = "avdd-plle";
+
+ if (need_pexa) {
+ pcie->supplies[i++].supply = "avdd-pexa";
+ pcie->supplies[i++].supply = "vdd-pexa";
+ }
+
+ if (need_pexb) {
+ pcie->supplies[i++].supply = "avdd-pexb";
+ pcie->supplies[i++].supply = "vdd-pexb";
+ }
+ } else if (of_device_is_compatible(np, "nvidia,tegra20-pcie")) {
+ pcie->num_supplies = 5;
+
+ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
+ sizeof(*pcie->supplies),
+ GFP_KERNEL);
+ if (!pcie->supplies)
+ return -ENOMEM;
+
+ pcie->supplies[0].supply = "avdd-pex";
+ pcie->supplies[1].supply = "vdd-pex";
+ pcie->supplies[2].supply = "avdd-pex-pll";
+ pcie->supplies[3].supply = "avdd-plle";
+ pcie->supplies[4].supply = "vddio-pex-clk";
+ }
+
+ if (of_regulator_bulk_available(pcie->dev->of_node, pcie->supplies,
+ pcie->num_supplies))
+ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
+ pcie->supplies);
+
+ /*
+ * If not all regulators are available for this new scheme, assume
+ * that the device tree complies with an older version of the device
+ * tree binding.
+ */
+ dev_info(pcie->dev, "using legacy DT binding for power supplies\n");
+
+ devm_kfree(pcie->dev, pcie->supplies);
+ pcie->num_supplies = 0;
+
+ return tegra_pcie_get_legacy_regulators(pcie);
+}
+
static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
{
const struct tegra_pcie_soc_data *soc = pcie->soc_data;
struct device_node *np = pcie->dev->of_node, *port;
struct of_pci_range_parser parser;
struct of_pci_range range;
+ u32 lanes = 0, mask = 0;
+ unsigned int lane = 0;
struct resource res;
- u32 lanes = 0;
int err;
if (of_pci_range_parser_init(&parser, np)) {
@@ -1409,20 +1517,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
return -EINVAL;
}
- pcie->vdd_supply = devm_regulator_get(pcie->dev, "vdd");
- if (IS_ERR(pcie->vdd_supply))
- return PTR_ERR(pcie->vdd_supply);
-
- pcie->pex_clk_supply = devm_regulator_get(pcie->dev, "pex-clk");
- if (IS_ERR(pcie->pex_clk_supply))
- return PTR_ERR(pcie->pex_clk_supply);
-
- if (soc->has_avdd_supply) {
- pcie->avdd_supply = devm_regulator_get(pcie->dev, "avdd");
- if (IS_ERR(pcie->avdd_supply))
- return PTR_ERR(pcie->avdd_supply);
- }
-
for_each_of_pci_range(&parser, &range) {
of_pci_range_to_resource(&range, np, &res);
@@ -1490,8 +1584,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
lanes |= value << (index << 3);
- if (!of_device_is_available(port))
+ if (!of_device_is_available(port)) {
+ lane += value;
continue;
+ }
+
+ mask |= ((1 << value) - 1) << lane;
+ lane += value;
rp = devm_kzalloc(pcie->dev, sizeof(*rp), GFP_KERNEL);
if (!rp)
@@ -1522,6 +1621,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
return err;
}
+ err = tegra_pcie_get_regulators(pcie, mask);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -1615,7 +1718,6 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
.has_pex_clkreq_en = false,
.has_pex_bias_ctrl = false,
.has_intr_prsnt_sense = false,
- .has_avdd_supply = false,
.has_cml_clk = false,
};
@@ -1627,7 +1729,6 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
- .has_avdd_supply = true,
.has_cml_clk = true,
};
@@ -1716,4 +1817,4 @@ module_platform_driver(tegra_pcie_driver);
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index f7d3de32c9a0..4884ee5e07d4 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -105,7 +105,7 @@
#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
-#define PCI_MAX_RESOURCES 4
+#define RCAR_PCI_MAX_RESOURCES 4
#define MAX_NR_INBOUND_MAPS 6
struct rcar_msi {
@@ -127,7 +127,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_chip *chip)
struct rcar_pcie {
struct device *dev;
void __iomem *base;
- struct resource res[PCI_MAX_RESOURCES];
+ struct resource res[RCAR_PCI_MAX_RESOURCES];
struct resource busn;
int root_bus_nr;
struct clk *clk;
@@ -140,36 +140,37 @@ static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys)
return sys->private_data;
}
-static void pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
- unsigned long reg)
+static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val,
+ unsigned long reg)
{
writel(val, pcie->base + reg);
}
-static unsigned long pci_read_reg(struct rcar_pcie *pcie, unsigned long reg)
+static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie,
+ unsigned long reg)
{
return readl(pcie->base + reg);
}
enum {
- PCI_ACCESS_READ,
- PCI_ACCESS_WRITE,
+ RCAR_PCI_ACCESS_READ,
+ RCAR_PCI_ACCESS_WRITE,
};
static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
{
int shift = 8 * (where & 3);
- u32 val = pci_read_reg(pcie, where & ~3);
+ u32 val = rcar_pci_read_reg(pcie, where & ~3);
val &= ~(mask << shift);
val |= data << shift;
- pci_write_reg(pcie, val, where & ~3);
+ rcar_pci_write_reg(pcie, val, where & ~3);
}
static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
{
int shift = 8 * (where & 3);
- u32 val = pci_read_reg(pcie, where & ~3);
+ u32 val = rcar_pci_read_reg(pcie, where & ~3);
return val >> shift;
}
@@ -205,14 +206,14 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
if (dev != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (access_type == PCI_ACCESS_READ) {
- *data = pci_read_reg(pcie, PCICONF(index));
+ if (access_type == RCAR_PCI_ACCESS_READ) {
+ *data = rcar_pci_read_reg(pcie, PCICONF(index));
} else {
/* Keep an eye out for changes to the root bus number */
if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
pcie->root_bus_nr = *data & 0xff;
- pci_write_reg(pcie, *data, PCICONF(index));
+ rcar_pci_write_reg(pcie, *data, PCICONF(index));
}
return PCIBIOS_SUCCESSFUL;
@@ -222,20 +223,20 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;
/* Clear errors */
- pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+ rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
/* Set the PIO address */
- pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) |
- PCIE_CONF_FUNC(func) | reg, PCIECAR);
+ rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
+ PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
/* Enable the configuration access */
if (bus->parent->number == pcie->root_bus_nr)
- pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+ rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
else
- pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+ rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
/* Check for errors */
- if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+ if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
return PCIBIOS_DEVICE_NOT_FOUND;
/* Check for master and target aborts */
@@ -243,13 +244,13 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
return PCIBIOS_DEVICE_NOT_FOUND;
- if (access_type == PCI_ACCESS_READ)
- *data = pci_read_reg(pcie, PCIECDR);
+ if (access_type == RCAR_PCI_ACCESS_READ)
+ *data = rcar_pci_read_reg(pcie, PCIECDR);
else
- pci_write_reg(pcie, *data, PCIECDR);
+ rcar_pci_write_reg(pcie, *data, PCIECDR);
/* Disable the configuration access */
- pci_write_reg(pcie, 0, PCIECCTLR);
+ rcar_pci_write_reg(pcie, 0, PCIECCTLR);
return PCIBIOS_SUCCESSFUL;
}
@@ -260,12 +261,7 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
int ret;
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+ ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
bus, devfn, where, val);
if (ret != PCIBIOS_SUCCESSFUL) {
*val = 0xffffffff;
@@ -291,12 +287,7 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
int shift, ret;
u32 data;
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ,
+ ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,
bus, devfn, where, &data);
if (ret != PCIBIOS_SUCCESSFUL)
return ret;
@@ -315,7 +306,7 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
} else
data = val;
- ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE,
+ ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_WRITE,
bus, devfn, where, &data);
return ret;
@@ -326,14 +317,15 @@ static struct pci_ops rcar_pcie_ops = {
.write = rcar_pcie_write_conf,
};
-static void rcar_pcie_setup_window(int win, struct resource *res,
- struct rcar_pcie *pcie)
+static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
{
+ struct resource *res = &pcie->res[win];
+
/* Setup PCIe address space mappings for each resource */
resource_size_t size;
u32 mask;
- pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
+ rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
/*
* The PAMR mask is calculated in units of 128Bytes, which
@@ -341,17 +333,17 @@ static void rcar_pcie_setup_window(int win, struct resource *res,
*/
size = resource_size(res);
mask = (roundup_pow_of_two(size) / SZ_128) - 1;
- pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
+ rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
- pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
- pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
+ rcar_pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win));
+ rcar_pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win));
/* First resource is for IO */
mask = PAR_ENABLE;
if (res->flags & IORESOURCE_IO)
mask |= IO_SPACE;
- pci_write_reg(pcie, mask, PCIEPTCTLR(win));
+ rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
}
static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
@@ -363,13 +355,13 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys)
pcie->root_bus_nr = -1;
/* Setup PCI resources */
- for (i = 0; i < PCI_MAX_RESOURCES; i++) {
+ for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
res = &pcie->res[i];
if (!res->flags)
continue;
- rcar_pcie_setup_window(i, res, pcie);
+ rcar_pcie_setup_window(i, pcie);
if (res->flags & IORESOURCE_IO)
pci_ioremap_io(nr * SZ_64K, res->start);
@@ -415,7 +407,7 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
unsigned int timeout = 100;
while (timeout--) {
- if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+ if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
return 0;
udelay(100);
@@ -438,15 +430,15 @@ static void phy_write_reg(struct rcar_pcie *pcie,
((addr & 0xff) << ADR_POS);
/* Set write data */
- pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
- pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);
/* Clear command */
- pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
- pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);
@@ -457,7 +449,7 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
unsigned int timeout = 10;
while (timeout--) {
- if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+ if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
return 0;
msleep(5);
@@ -471,17 +463,17 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
int err;
/* Begin initialization */
- pci_write_reg(pcie, 0, PCIETCTLR);
+ rcar_pci_write_reg(pcie, 0, PCIETCTLR);
/* Set mode */
- pci_write_reg(pcie, 1, PCIEMSR);
+ rcar_pci_write_reg(pcie, 1, PCIEMSR);
/*
* Initial header for port config space is type 1, set the device
* class to match. Hardware takes care of propagating the IDSETR
* settings, so there is no need to bother with a quirk.
*/
- pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+ rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
/*
* Setup Secondary Bus Number & Subordinate Bus Number, even though
@@ -491,33 +483,31 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
/* Initialize default capabilities. */
- rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
PCI_HEADER_TYPE_BRIDGE);
/* Enable data link layer active state reporting */
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC);
+ rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
+ PCI_EXP_LNKCAP_DLLLARC);
/* Write out the physical slot number = 0 */
rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
/* Set the completion timer timeout to the maximum 50ms. */
- rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50);
+ rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
/* Terminate list of capabilities (Next Capability Offset=0) */
- rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0);
-
- /* Enable MAC data scrambling. */
- rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0);
+ rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
/* Enable MSI */
if (IS_ENABLED(CONFIG_PCI_MSI))
- pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
+ rcar_pci_write_reg(pcie, 0x101f0000, PCIEMSITXR);
/* Finish initialization - establish a PCI Express link */
- pci_write_reg(pcie, CFINIT, PCIETCTLR);
+ rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
/* This will timeout if we don't have a link. */
err = rcar_pcie_wait_for_dl(pcie);
@@ -527,11 +517,6 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
/* Enable INTx interrupts */
rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
- /* Enable slave Bus Mastering */
- rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
- PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST);
-
wmb();
return 0;
@@ -560,7 +545,7 @@ static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie)
phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
while (timeout--) {
- if (pci_read_reg(pcie, H1_PCIEPHYSR))
+ if (rcar_pci_read_reg(pcie, H1_PCIEPHYSR))
return rcar_pcie_hw_init(pcie);
msleep(5);
@@ -599,7 +584,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
struct rcar_msi *msi = &pcie->msi;
unsigned long reg;
- reg = pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
/* MSI & INTx share an interrupt - we only handle MSI here */
if (!reg)
@@ -610,7 +595,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
unsigned int irq;
/* clear the interrupt */
- pci_write_reg(pcie, 1 << index, PCIEMSIFR);
+ rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
irq = irq_find_mapping(msi->domain, index);
if (irq) {
@@ -624,7 +609,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
}
/* see if there's any more pending in this vector */
- reg = pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
}
return IRQ_HANDLED;
@@ -651,8 +636,8 @@ static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev,
irq_set_msi_desc(irq, desc);
- msg.address_lo = pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
- msg.address_hi = pci_read_reg(pcie, PCIEMSIAUR);
+ msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
+ msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
msg.data = hwirq;
write_msi_msg(irq, &msg);
@@ -729,11 +714,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
msi->pages = __get_free_pages(GFP_KERNEL, 0);
base = virt_to_phys((void *)msi->pages);
- pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
- pci_write_reg(pcie, 0, PCIEMSIAUR);
+ rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR);
+ rcar_pci_write_reg(pcie, 0, PCIEMSIAUR);
/* enable all MSI interrupts */
- pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+ rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
return 0;
@@ -826,6 +811,7 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
if (cpu_addr > 0) {
unsigned long nr_zeros = __ffs64(cpu_addr);
u64 alignment = 1ULL << nr_zeros;
+
size = min(range->size, alignment);
} else {
size = range->size;
@@ -841,13 +827,13 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
* Set up 64-bit inbound regions as the range parser doesn't
* distinguish between 32 and 64-bit types.
*/
- pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
- pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
- pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
+ rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx));
+ rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
+ rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx));
- pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
- pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
- pci_write_reg(pcie, 0, PCIELAMR(idx+1));
+ rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1));
+ rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1));
+ rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
pci_addr += size;
cpu_addr += size;
@@ -952,7 +938,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
of_pci_range_to_resource(&range, pdev->dev.of_node,
&pcie->res[win++]);
- if (win > PCI_MAX_RESOURCES)
+ if (win > RCAR_PCI_MAX_RESOURCES)
break;
}
@@ -982,7 +968,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return 0;
}
- data = pci_read_reg(pcie, MACSR);
+ data = rcar_pci_read_reg(pcie, MACSR);
dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
rcar_pcie_enable(pcie);
@@ -1003,4 +989,4 @@ module_platform_driver(rcar_pcie_driver);
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
new file mode 100644
index 000000000000..6dea9e43a75c
--- /dev/null
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -0,0 +1,393 @@
+/*
+ * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs
+ *
+ * SPEAr13xx PCIe Glue Layer Source Code
+ *
+ * Copyright (C) 2010-2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+
+#include "pcie-designware.h"
+
+struct spear13xx_pcie {
+ void __iomem *app_base;
+ struct phy *phy;
+ struct clk *clk;
+ struct pcie_port pp;
+ bool is_gen1;
+};
+
+struct pcie_app_reg {
+ u32 app_ctrl_0; /* cr0 */
+ u32 app_ctrl_1; /* cr1 */
+ u32 app_status_0; /* cr2 */
+ u32 app_status_1; /* cr3 */
+ u32 msg_status; /* cr4 */
+ u32 msg_payload; /* cr5 */
+ u32 int_sts; /* cr6 */
+ u32 int_clr; /* cr7 */
+ u32 int_mask; /* cr8 */
+ u32 mst_bmisc; /* cr9 */
+ u32 phy_ctrl; /* cr10 */
+ u32 phy_status; /* cr11 */
+ u32 cxpl_debug_info_0; /* cr12 */
+ u32 cxpl_debug_info_1; /* cr13 */
+ u32 ven_msg_ctrl_0; /* cr14 */
+ u32 ven_msg_ctrl_1; /* cr15 */
+ u32 ven_msg_data_0; /* cr16 */
+ u32 ven_msg_data_1; /* cr17 */
+ u32 ven_msi_0; /* cr18 */
+ u32 ven_msi_1; /* cr19 */
+ u32 mst_rmisc; /* cr20 */
+};
+
+/* CR0 ID */
+#define RX_LANE_FLIP_EN_ID 0
+#define TX_LANE_FLIP_EN_ID 1
+#define SYS_AUX_PWR_DET_ID 2
+#define APP_LTSSM_ENABLE_ID 3
+#define SYS_ATTEN_BUTTON_PRESSED_ID 4
+#define SYS_MRL_SENSOR_STATE_ID 5
+#define SYS_PWR_FAULT_DET_ID 6
+#define SYS_MRL_SENSOR_CHGED_ID 7
+#define SYS_PRE_DET_CHGED_ID 8
+#define SYS_CMD_CPLED_INT_ID 9
+#define APP_INIT_RST_0_ID 11
+#define APP_REQ_ENTR_L1_ID 12
+#define APP_READY_ENTR_L23_ID 13
+#define APP_REQ_EXIT_L1_ID 14
+#define DEVICE_TYPE_EP (0 << 25)
+#define DEVICE_TYPE_LEP (1 << 25)
+#define DEVICE_TYPE_RC (4 << 25)
+#define SYS_INT_ID 29
+#define MISCTRL_EN_ID 30
+#define REG_TRANSLATION_ENABLE 31
+
+/* CR1 ID */
+#define APPS_PM_XMT_TURNOFF_ID 2
+#define APPS_PM_XMT_PME_ID 5
+
+/* CR3 ID */
+#define XMLH_LTSSM_STATE_DETECT_QUIET 0x00
+#define XMLH_LTSSM_STATE_DETECT_ACT 0x01
+#define XMLH_LTSSM_STATE_POLL_ACTIVE 0x02
+#define XMLH_LTSSM_STATE_POLL_COMPLIANCE 0x03
+#define XMLH_LTSSM_STATE_POLL_CONFIG 0x04
+#define XMLH_LTSSM_STATE_PRE_DETECT_QUIET 0x05
+#define XMLH_LTSSM_STATE_DETECT_WAIT 0x06
+#define XMLH_LTSSM_STATE_CFG_LINKWD_START 0x07
+#define XMLH_LTSSM_STATE_CFG_LINKWD_ACEPT 0x08
+#define XMLH_LTSSM_STATE_CFG_LANENUM_WAIT 0x09
+#define XMLH_LTSSM_STATE_CFG_LANENUM_ACEPT 0x0A
+#define XMLH_LTSSM_STATE_CFG_COMPLETE 0x0B
+#define XMLH_LTSSM_STATE_CFG_IDLE 0x0C
+#define XMLH_LTSSM_STATE_RCVRY_LOCK 0x0D
+#define XMLH_LTSSM_STATE_RCVRY_SPEED 0x0E
+#define XMLH_LTSSM_STATE_RCVRY_RCVRCFG 0x0F
+#define XMLH_LTSSM_STATE_RCVRY_IDLE 0x10
+#define XMLH_LTSSM_STATE_L0 0x11
+#define XMLH_LTSSM_STATE_L0S 0x12
+#define XMLH_LTSSM_STATE_L123_SEND_EIDLE 0x13
+#define XMLH_LTSSM_STATE_L1_IDLE 0x14
+#define XMLH_LTSSM_STATE_L2_IDLE 0x15
+#define XMLH_LTSSM_STATE_L2_WAKE 0x16
+#define XMLH_LTSSM_STATE_DISABLED_ENTRY 0x17
+#define XMLH_LTSSM_STATE_DISABLED_IDLE 0x18
+#define XMLH_LTSSM_STATE_DISABLED 0x19
+#define XMLH_LTSSM_STATE_LPBK_ENTRY 0x1A
+#define XMLH_LTSSM_STATE_LPBK_ACTIVE 0x1B
+#define XMLH_LTSSM_STATE_LPBK_EXIT 0x1C
+#define XMLH_LTSSM_STATE_LPBK_EXIT_TIMEOUT 0x1D
+#define XMLH_LTSSM_STATE_HOT_RESET_ENTRY 0x1E
+#define XMLH_LTSSM_STATE_HOT_RESET 0x1F
+#define XMLH_LTSSM_STATE_MASK 0x3F
+#define XMLH_LINK_UP (1 << 6)
+
+/* CR4 ID */
+#define CFG_MSI_EN_ID 18
+
+/* CR6 */
+#define INTA_CTRL_INT (1 << 7)
+#define INTB_CTRL_INT (1 << 8)
+#define INTC_CTRL_INT (1 << 9)
+#define INTD_CTRL_INT (1 << 10)
+#define MSI_CTRL_INT (1 << 26)
+
+/* CR19 ID */
+#define VEN_MSI_REQ_ID 11
+#define VEN_MSI_FUN_NUM_ID 8
+#define VEN_MSI_TC_ID 5
+#define VEN_MSI_VECTOR_ID 0
+#define VEN_MSI_REQ_EN ((u32)0x1 << VEN_MSI_REQ_ID)
+#define VEN_MSI_FUN_NUM_MASK ((u32)0x7 << VEN_MSI_FUN_NUM_ID)
+#define VEN_MSI_TC_MASK ((u32)0x7 << VEN_MSI_TC_ID)
+#define VEN_MSI_VECTOR_MASK ((u32)0x1F << VEN_MSI_VECTOR_ID)
+
+#define EXP_CAP_ID_OFFSET 0x70
+
+#define to_spear13xx_pcie(x) container_of(x, struct spear13xx_pcie, pp)
+
+static int spear13xx_pcie_establish_link(struct pcie_port *pp)
+{
+ u32 val;
+ int count = 0;
+ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+ struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+ u32 exp_cap_off = EXP_CAP_ID_OFFSET;
+
+ if (dw_pcie_link_up(pp)) {
+ dev_err(pp->dev, "link already up\n");
+ return 0;
+ }
+
+ dw_pcie_setup_rc(pp);
+
+ /*
+ * this controller support only 128 bytes read size, however its
+ * default value in capability register is 512 bytes. So force
+ * it to 128 here.
+ */
+ dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
+ val &= ~PCI_EXP_DEVCTL_READRQ;
+ dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
+
+ dw_pcie_cfg_write(pp->dbi_base, PCI_VENDOR_ID, 2, 0x104A);
+ dw_pcie_cfg_write(pp->dbi_base, PCI_DEVICE_ID, 2, 0xCD80);
+
+ /*
+ * if is_gen1 is set then handle it, so that some buggy card
+ * also works
+ */
+ if (spear13xx_pcie->is_gen1) {
+ dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCAP, 4,
+ &val);
+ if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
+ val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+ val |= PCI_EXP_LNKCAP_SLS_2_5GB;
+ dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
+ PCI_EXP_LNKCAP, 4, val);
+ }
+
+ dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCTL2, 4,
+ &val);
+ if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
+ val &= ~((u32)PCI_EXP_LNKCAP_SLS);
+ val |= PCI_EXP_LNKCAP_SLS_2_5GB;
+ dw_pcie_cfg_write(pp->dbi_base, exp_cap_off +
+ PCI_EXP_LNKCTL2, 4, val);
+ }
+ }
+
+ /* enable ltssm */
+ writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
+ | (1 << APP_LTSSM_ENABLE_ID)
+ | ((u32)1 << REG_TRANSLATION_ENABLE),
+ &app_reg->app_ctrl_0);
+
+ /* check if the link is up or not */
+ while (!dw_pcie_link_up(pp)) {
+ mdelay(100);
+ count++;
+ if (count == 10) {
+ dev_err(pp->dev, "link Fail\n");
+ return -EINVAL;
+ }
+ }
+ dev_info(pp->dev, "link up\n");
+
+ return 0;
+}
+
+static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
+{
+ struct pcie_port *pp = arg;
+ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+ struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+ unsigned int status;
+
+ status = readl(&app_reg->int_sts);
+
+ if (status & MSI_CTRL_INT) {
+ if (!IS_ENABLED(CONFIG_PCI_MSI))
+ BUG();
+ dw_handle_msi_irq(pp);
+ }
+
+ writel(status, &app_reg->int_clr);
+
+ return IRQ_HANDLED;
+}
+
+static void spear13xx_pcie_enable_interrupts(struct pcie_port *pp)
+{
+ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+ struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+
+ /* Enable MSI interrupt */
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
+ dw_pcie_msi_init(pp);
+ writel(readl(&app_reg->int_mask) |
+ MSI_CTRL_INT, &app_reg->int_mask);
+ }
+}
+
+static int spear13xx_pcie_link_up(struct pcie_port *pp)
+{
+ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
+ struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
+
+ if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
+ return 1;
+
+ return 0;
+}
+
+static void spear13xx_pcie_host_init(struct pcie_port *pp)
+{
+ spear13xx_pcie_establish_link(pp);
+ spear13xx_pcie_enable_interrupts(pp);
+}
+
+static struct pcie_host_ops spear13xx_pcie_host_ops = {
+ .link_up = spear13xx_pcie_link_up,
+ .host_init = spear13xx_pcie_host_init,
+};
+
+static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ pp->irq = platform_get_irq(pdev, 0);
+ if (!pp->irq) {
+ dev_err(dev, "failed to get irq\n");
+ return -ENODEV;
+ }
+ ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
+ IRQF_SHARED, "spear1340-pcie", pp);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", pp->irq);
+ return ret;
+ }
+
+ pp->root_bus_nr = -1;
+ pp->ops = &spear13xx_pcie_host_ops;
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init spear13xx_pcie_probe(struct platform_device *pdev)
+{
+ struct spear13xx_pcie *spear13xx_pcie;
+ struct pcie_port *pp;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *dbi_base;
+ int ret;
+
+ spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
+ if (!spear13xx_pcie) {
+ dev_err(dev, "no memory for SPEAr13xx pcie\n");
+ return -ENOMEM;
+ }
+
+ spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
+ if (IS_ERR(spear13xx_pcie->phy)) {
+ ret = PTR_ERR(spear13xx_pcie->phy);
+ if (ret == -EPROBE_DEFER)
+ dev_info(dev, "probe deferred\n");
+ else
+ dev_err(dev, "couldn't get pcie-phy\n");
+ return ret;
+ }
+
+ phy_init(spear13xx_pcie->phy);
+
+ spear13xx_pcie->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(spear13xx_pcie->clk)) {
+ dev_err(dev, "couldn't get clk for pcie\n");
+ return PTR_ERR(spear13xx_pcie->clk);
+ }
+ ret = clk_prepare_enable(spear13xx_pcie->clk);
+ if (ret) {
+ dev_err(dev, "couldn't enable clk for pcie\n");
+ return ret;
+ }
+
+ pp = &spear13xx_pcie->pp;
+
+ pp->dev = dev;
+
+ dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
+ if (IS_ERR(pp->dbi_base)) {
+ dev_err(dev, "couldn't remap dbi base %p\n", dbi_base);
+ ret = PTR_ERR(pp->dbi_base);
+ goto fail_clk;
+ }
+ spear13xx_pcie->app_base = pp->dbi_base + 0x2000;
+
+ if (of_property_read_bool(np, "st,pcie-is-gen1"))
+ spear13xx_pcie->is_gen1 = true;
+
+ ret = add_pcie_port(pp, pdev);
+ if (ret < 0)
+ goto fail_clk;
+
+ platform_set_drvdata(pdev, spear13xx_pcie);
+ return 0;
+
+fail_clk:
+ clk_disable_unprepare(spear13xx_pcie->clk);
+
+ return ret;
+}
+
+static const struct of_device_id spear13xx_pcie_of_match[] = {
+ { .compatible = "st,spear1340-pcie", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, spear13xx_pcie_of_match);
+
+static struct platform_driver spear13xx_pcie_driver __initdata = {
+ .probe = spear13xx_pcie_probe,
+ .driver = {
+ .name = "spear-pcie",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(spear13xx_pcie_of_match),
+ },
+};
+
+/* SPEAr13xx PCIe driver does not allow module unload */
+
+static int __init pcie_init(void)
+{
+ return platform_driver_register(&spear13xx_pcie_driver);
+}
+module_init(pcie_init);
+
+MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 602d153c7055..70741c8c46a0 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -80,8 +80,9 @@ static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
return NULL;
context->refcount = 1;
- acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL,
- acpiphp_post_dock_fixup);
+ context->hp.notify = acpiphp_hotplug_notify;
+ context->hp.fixup = acpiphp_post_dock_fixup;
+ acpi_set_hp_context(adev, &context->hp);
return context;
}
@@ -369,20 +370,6 @@ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data,
return AE_OK;
}
-static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev)
-{
- struct acpiphp_bridge *bridge = NULL;
-
- acpi_lock_hp_context();
- if (adev->hp) {
- bridge = to_acpiphp_root_context(adev->hp)->root_bridge;
- if (bridge)
- get_bridge(bridge);
- }
- acpi_unlock_hp_context();
- return bridge;
-}
-
static void cleanup_bridge(struct acpiphp_bridge *bridge)
{
struct acpiphp_slot *slot;
@@ -753,9 +740,15 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
void acpiphp_check_host_bridge(struct acpi_device *adev)
{
- struct acpiphp_bridge *bridge;
+ struct acpiphp_bridge *bridge = NULL;
- bridge = acpiphp_dev_to_bridge(adev);
+ acpi_lock_hp_context();
+ if (adev->hp) {
+ bridge = to_acpiphp_root_context(adev->hp)->root_bridge;
+ if (bridge)
+ get_bridge(bridge);
+ }
+ acpi_unlock_hp_context();
if (bridge) {
pci_lock_rescan_remove();
@@ -884,7 +877,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
goto err;
root_context->root_bridge = bridge;
- acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL);
+ acpi_set_hp_context(adev, &root_context->hp);
} else {
struct acpiphp_context *context;
@@ -927,7 +920,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)
kfree(bridge);
}
-void acpiphp_drop_bridge(struct acpiphp_bridge *bridge)
+static void acpiphp_drop_bridge(struct acpiphp_bridge *bridge)
{
if (pci_is_root_bus(bridge->pci_bus)) {
struct acpiphp_root_context *root_context;
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 4a392c44e3d3..d81648f71425 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -216,8 +216,7 @@ void cpqhp_create_debugfs_files(struct controller *ctrl)
void cpqhp_remove_debugfs_files(struct controller *ctrl)
{
- if (ctrl->dentry)
- debugfs_remove(ctrl->dentry);
+ debugfs_remove(ctrl->dentry);
ctrl->dentry = NULL;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 8e9012dca450..9e5a9fbb93d7 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -92,9 +92,10 @@ struct controller {
struct slot *slot;
wait_queue_head_t queue; /* sleep & wake process */
u32 slot_cap;
+ u32 slot_ctrl;
struct timer_list poll_timer;
+ unsigned long cmd_started; /* jiffies */
unsigned int cmd_busy:1;
- unsigned int no_cmd_complete:1;
unsigned int link_active_reporting:1;
unsigned int notification_enabled:1;
unsigned int power_fault_detected;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index a2297db80813..07aa722bb12c 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -255,6 +255,13 @@ static int pciehp_probe(struct pcie_device *dev)
else if (pciehp_acpi_slot_detection_check(dev->port))
goto err_out_none;
+ if (!dev->port->subordinate) {
+ /* Can happen if we run out of bus numbers during probe */
+ dev_err(&dev->device,
+ "Hotplug bridge without secondary bus, ignoring\n");
+ goto err_out_none;
+ }
+
ctrl = pcie_init(dev);
if (!ctrl) {
dev_err(&dev->device, "Controller initialization failed\n");
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 42914e04d110..9da84b8b27d8 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -104,11 +104,10 @@ static inline void pciehp_free_irq(struct controller *ctrl)
free_irq(ctrl->pcie->irq, ctrl);
}
-static int pcie_poll_cmd(struct controller *ctrl)
+static int pcie_poll_cmd(struct controller *ctrl, int timeout)
{
struct pci_dev *pdev = ctrl_dev(ctrl);
u16 slot_status;
- int timeout = 1000;
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
if (slot_status & PCI_EXP_SLTSTA_CC) {
@@ -129,18 +128,52 @@ static int pcie_poll_cmd(struct controller *ctrl)
return 0; /* timeout */
}
-static void pcie_wait_cmd(struct controller *ctrl, int poll)
+static void pcie_wait_cmd(struct controller *ctrl)
{
unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
- unsigned long timeout = msecs_to_jiffies(msecs);
+ unsigned long duration = msecs_to_jiffies(msecs);
+ unsigned long cmd_timeout = ctrl->cmd_started + duration;
+ unsigned long now, timeout;
int rc;
- if (poll)
- rc = pcie_poll_cmd(ctrl);
+ /*
+ * If the controller does not generate notifications for command
+ * completions, we never need to wait between writes.
+ */
+ if (NO_CMD_CMPL(ctrl))
+ return;
+
+ if (!ctrl->cmd_busy)
+ return;
+
+ /*
+ * Even if the command has already timed out, we want to call
+ * pcie_poll_cmd() so it can clear PCI_EXP_SLTSTA_CC.
+ */
+ now = jiffies;
+ if (time_before_eq(cmd_timeout, now))
+ timeout = 1;
else
+ timeout = cmd_timeout - now;
+
+ if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE &&
+ ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE)
rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout);
+ else
+ rc = pcie_poll_cmd(ctrl, timeout);
+
+ /*
+ * Controllers with errata like Intel CF118 don't generate
+ * completion notifications unless the power/indicator/interlock
+ * control bits are changed. On such controllers, we'll emit this
+ * timeout message when we wait for completion of commands that
+ * don't change those bits, e.g., commands that merely enable
+ * interrupts.
+ */
if (!rc)
- ctrl_dbg(ctrl, "Command not completed in 1000 msec\n");
+ ctrl_info(ctrl, "Timeout on hotplug command %#010x (issued %u msec ago)\n",
+ ctrl->slot_ctrl,
+ jiffies_to_msecs(now - ctrl->cmd_started));
}
/**
@@ -152,34 +185,12 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)
static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
{
struct pci_dev *pdev = ctrl_dev(ctrl);
- u16 slot_status;
u16 slot_ctrl;
mutex_lock(&ctrl->ctrl_lock);
- pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
- if (slot_status & PCI_EXP_SLTSTA_CC) {
- pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_CC);
- if (!ctrl->no_cmd_complete) {
- /*
- * After 1 sec and CMD_COMPLETED still not set, just
- * proceed forward to issue the next command according
- * to spec. Just print out the error message.
- */
- ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n");
- } else if (!NO_CMD_CMPL(ctrl)) {
- /*
- * This controller seems to notify of command completed
- * event even though it supports none of power
- * controller, attention led, power led and EMI.
- */
- ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to wait for command completed event\n");
- ctrl->no_cmd_complete = 0;
- } else {
- ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe the controller is broken\n");
- }
- }
+ /* Wait for any previous command that might still be in progress */
+ pcie_wait_cmd(ctrl);
pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);
slot_ctrl &= ~mask;
@@ -187,22 +198,9 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
ctrl->cmd_busy = 1;
smp_mb();
pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);
+ ctrl->cmd_started = jiffies;
+ ctrl->slot_ctrl = slot_ctrl;
- /*
- * Wait for command completion.
- */
- if (!ctrl->no_cmd_complete) {
- int poll = 0;
- /*
- * if hotplug interrupt is not enabled or command
- * completed interrupt is not enabled, we need to poll
- * command completed event.
- */
- if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) ||
- !(slot_ctrl & PCI_EXP_SLTCTL_CCIE))
- poll = 1;
- pcie_wait_cmd(ctrl, poll);
- }
mutex_unlock(&ctrl->ctrl_lock);
}
@@ -773,15 +771,6 @@ struct controller *pcie_init(struct pcie_device *dev)
mutex_init(&ctrl->ctrl_lock);
init_waitqueue_head(&ctrl->queue);
dbg_ctrl(ctrl);
- /*
- * Controller doesn't notify of command completion if the "No
- * Command Completed Support" bit is set in Slot Capability
- * register or the controller supports none of power
- * controller, attention led, power led and EMI.
- */
- if (NO_CMD_CMPL(ctrl) ||
- !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
- ctrl->no_cmd_complete = 1;
/* Check if Data Link Layer Link Active Reporting is implemented */
pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);
@@ -794,7 +783,7 @@ struct controller *pcie_init(struct pcie_device *dev)
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
- PCI_EXP_SLTSTA_CC);
+ PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);
/* Disable software notification */
pcie_disable_notification(ctrl);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 93aa29f6d39c..f2945fa73d4f 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -375,11 +375,11 @@ static void __exit cleanup_slots(void)
static int __init rpaphp_init(void)
{
- struct device_node *dn = NULL;
+ struct device_node *dn;
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- while ((dn = of_find_node_by_name(dn, "pci")))
+ for_each_node_by_name(dn, "pci")
rpaphp_add_slot(dn);
return 0;
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index d1332d2f8730..d77e46bca54c 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -7,8 +7,8 @@
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
-#define COMPONENT "zPCI hpc"
-#define pr_fmt(fmt) COMPONENT ": " fmt
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 6b2b7dddbbdb..f6219d36227f 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -98,7 +98,7 @@ static void ioapic_remove(struct pci_dev *dev)
}
-static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
+static const struct pci_device_id ioapic_devices[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
{ }
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 13f3d3037272..5a40516444f3 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -149,15 +149,14 @@ static void msi_set_enable(struct pci_dev *dev, int enable)
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
-static void msix_set_enable(struct pci_dev *dev, int enable)
+static void msix_clear_and_set_ctrl(struct pci_dev *dev, u16 clear, u16 set)
{
- u16 control;
+ u16 ctrl;
- pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
- control &= ~PCI_MSIX_FLAGS_ENABLE;
- if (enable)
- control |= PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
+ ctrl &= ~clear;
+ ctrl |= set;
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, ctrl);
}
static inline __attribute_const__ u32 msi_mask(unsigned x)
@@ -168,16 +167,6 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
return (1 << (1 << x)) - 1;
}
-static inline __attribute_const__ u32 msi_capable_mask(u16 control)
-{
- return msi_mask((control >> 1) & 7);
-}
-
-static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
-{
- return msi_mask((control >> 4) & 7);
-}
-
/*
* PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to
* mask all MSI interrupts by clearing the MSI enable bit does not work
@@ -246,7 +235,7 @@ static void msi_set_mask_bit(struct irq_data *data, u32 flag)
msix_mask_irq(desc, flag);
readl(desc->mask_base); /* Flush write to device */
} else {
- unsigned offset = data->irq - desc->dev->irq;
+ unsigned offset = data->irq - desc->irq;
msi_mask_irq(desc, 1 << offset, flag << offset);
}
}
@@ -460,7 +449,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
arch_restore_msi_irqs(dev);
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
- msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
+ msi_mask_irq(entry, msi_mask(entry->msi_attrib.multi_cap),
+ entry->masked);
control &= ~PCI_MSI_FLAGS_QSIZE;
control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE;
pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
@@ -469,26 +459,22 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
static void __pci_restore_msix_state(struct pci_dev *dev)
{
struct msi_desc *entry;
- u16 control;
if (!dev->msix_enabled)
return;
BUG_ON(list_empty(&dev->msi_list));
- entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
- pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
/* route the table */
pci_intx_for_msi(dev, 0);
- control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ msix_clear_and_set_ctrl(dev, 0,
+ PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
arch_restore_msi_irqs(dev);
list_for_each_entry(entry, &dev->msi_list, list) {
msix_mask_irq(entry, entry->masked);
}
- control &= ~PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
}
void pci_restore_msi_state(struct pci_dev *dev)
@@ -501,7 +487,6 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state);
static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct pci_dev *pdev = to_pci_dev(dev);
struct msi_desc *entry;
unsigned long irq;
int retval;
@@ -510,12 +495,11 @@ static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
if (retval)
return retval;
- list_for_each_entry(entry, &pdev->msi_list, list) {
- if (entry->irq == irq) {
- return sprintf(buf, "%s\n",
- entry->msi_attrib.is_msix ? "msix" : "msi");
- }
- }
+ entry = irq_get_msi_desc(irq);
+ if (entry)
+ return sprintf(buf, "%s\n",
+ entry->msi_attrib.is_msix ? "msix" : "msi");
+
return -ENODEV;
}
@@ -594,6 +578,38 @@ error_attrs:
return ret;
}
+static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
+{
+ u16 control;
+ struct msi_desc *entry;
+
+ /* MSI Entry Initialization */
+ entry = alloc_msi_entry(dev);
+ if (!entry)
+ return NULL;
+
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
+
+ entry->msi_attrib.is_msix = 0;
+ entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
+ entry->msi_attrib.entry_nr = 0;
+ entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
+ entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
+ entry->msi_attrib.pos = dev->msi_cap;
+ entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1;
+
+ if (control & PCI_MSI_FLAGS_64BIT)
+ entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
+ else
+ entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
+
+ /* Save the initial mask status */
+ if (entry->msi_attrib.maskbit)
+ pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
+
+ return entry;
+}
+
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -609,32 +625,16 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
{
struct msi_desc *entry;
int ret;
- u16 control;
unsigned mask;
msi_set_enable(dev, 0); /* Disable MSI during set up */
- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
- /* MSI Entry Initialization */
- entry = alloc_msi_entry(dev);
+ entry = msi_setup_entry(dev);
if (!entry)
return -ENOMEM;
- entry->msi_attrib.is_msix = 0;
- entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
- entry->msi_attrib.entry_nr = 0;
- entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
- entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
- entry->msi_attrib.pos = dev->msi_cap;
-
- if (control & PCI_MSI_FLAGS_64BIT)
- entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
- else
- entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
/* All MSIs are unmasked by default, Mask them all */
- if (entry->msi_attrib.maskbit)
- pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
- mask = msi_capable_mask(control);
+ mask = msi_mask(entry->msi_attrib.multi_cap);
msi_mask_irq(entry, mask, mask);
list_add_tail(&entry->list, &dev->msi_list);
@@ -743,12 +743,10 @@ static int msix_capability_init(struct pci_dev *dev,
u16 control;
void __iomem *base;
- pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
-
/* Ensure MSI-X is disabled while it is set up */
- control &= ~PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
/* Request & Map MSI-X table region */
base = msix_map_region(dev, msix_table_size(control));
if (!base)
@@ -767,8 +765,8 @@ static int msix_capability_init(struct pci_dev *dev,
* MSI-X registers. We need to mask all the vectors to prevent
* interrupts coming in before they're fully set up.
*/
- control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ msix_clear_and_set_ctrl(dev, 0,
+ PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
msix_program_entries(dev, entries);
@@ -780,8 +778,7 @@ static int msix_capability_init(struct pci_dev *dev,
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
- control &= ~PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
+ msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
return 0;
@@ -882,7 +879,6 @@ void pci_msi_shutdown(struct pci_dev *dev)
{
struct msi_desc *desc;
u32 mask;
- u16 ctrl;
if (!pci_msi_enable || !dev || !dev->msi_enabled)
return;
@@ -895,8 +891,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
dev->msi_enabled = 0;
/* Return the device with MSI unmasked as initial states */
- pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);
- mask = msi_capable_mask(ctrl);
+ mask = msi_mask(desc->msi_attrib.multi_cap);
/* Keep cached state to be restored */
arch_msi_mask_irq(desc, mask, ~mask);
@@ -1001,7 +996,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
arch_msix_mask_irq(entry, 1);
}
- msix_set_enable(dev, 0);
+ msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
}
@@ -1016,24 +1011,6 @@ void pci_disable_msix(struct pci_dev *dev)
}
EXPORT_SYMBOL(pci_disable_msix);
-/**
- * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
- * @dev: pointer to the pci_dev data structure of MSI(X) device function
- *
- * Being called during hotplug remove, from which the device function
- * is hot-removed. All previous assigned MSI/MSI-X irqs, if
- * allocated for this device function, are reclaimed to unused state,
- * which may be used later on.
- **/
-void msi_remove_pci_irq_vectors(struct pci_dev *dev)
-{
- if (!pci_msi_enable || !dev)
- return;
-
- if (dev->msi_enabled || dev->msix_enabled)
- free_msi_irqs(dev);
-}
-
void pci_no_msi(void)
{
pci_msi_enable = 0;
@@ -1065,7 +1042,7 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
if (dev->msix_cap)
- msix_set_enable(dev, 0);
+ msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
}
/**
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index ca4927ba8433..37263b0ebfe3 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -18,31 +18,31 @@
#include "pci.h"
/**
- * pci_acpi_wake_bus - Wake-up notification handler for root buses.
- * @handle: ACPI handle of a device the notification is for.
- * @event: Type of the signaled event.
- * @context: PCI root bus to wake up devices on.
+ * pci_acpi_wake_bus - Root bus wakeup notification fork function.
+ * @work: Work item to handle.
*/
-static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context)
+static void pci_acpi_wake_bus(struct work_struct *work)
{
- struct pci_bus *pci_bus = context;
+ struct acpi_device *adev;
+ struct acpi_pci_root *root;
- if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus)
- pci_pme_wakeup_bus(pci_bus);
+ adev = container_of(work, struct acpi_device, wakeup.context.work);
+ root = acpi_driver_data(adev);
+ pci_pme_wakeup_bus(root->bus);
}
/**
- * pci_acpi_wake_dev - Wake-up notification handler for PCI devices.
+ * pci_acpi_wake_dev - PCI device wakeup notification work function.
* @handle: ACPI handle of a device the notification is for.
- * @event: Type of the signaled event.
- * @context: PCI device object to wake up.
+ * @work: Work item to handle.
*/
-static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
+static void pci_acpi_wake_dev(struct work_struct *work)
{
- struct pci_dev *pci_dev = context;
+ struct acpi_device_wakeup_context *context;
+ struct pci_dev *pci_dev;
- if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
- return;
+ context = container_of(work, struct acpi_device_wakeup_context, work);
+ pci_dev = to_pci_dev(context->dev);
if (pci_dev->pme_poll)
pci_dev->pme_poll = false;
@@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
}
/**
- * 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.
- */
-acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
- struct pci_bus *pci_bus)
-{
- return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
-}
-
-/**
- * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier.
- * @dev: ACPI device to remove the notifier from.
+ * pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus.
+ * @dev: PCI root bridge ACPI device.
*/
-acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
+acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev)
{
- return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
+ return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus);
}
/**
@@ -92,16 +81,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 acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
-}
-
-/**
- * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier.
- * @dev: ACPI device to remove the notifier from.
- */
-acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
-{
- return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
+ return acpi_add_pm_notifier(dev, &pci_dev->dev, pci_acpi_wake_dev);
}
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -170,14 +150,13 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
static bool acpi_pci_power_manageable(struct pci_dev *dev)
{
- acpi_handle handle = ACPI_HANDLE(&dev->dev);
-
- return handle ? acpi_bus_power_manageable(handle) : false;
+ struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
+ return adev ? acpi_device_power_manageable(adev) : false;
}
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
- acpi_handle handle = ACPI_HANDLE(&dev->dev);
+ struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
static const u8 state_conv[] = {
[PCI_D0] = ACPI_STATE_D0,
[PCI_D1] = ACPI_STATE_D1,
@@ -188,7 +167,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
int error = -EINVAL;
/* If the ACPI device has _EJ0, ignore the device */
- if (!handle || acpi_has_method(handle, "_EJ0"))
+ if (!adev || acpi_has_method(adev->handle, "_EJ0"))
return -ENODEV;
switch (state) {
@@ -202,7 +181,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
case PCI_D1:
case PCI_D2:
case PCI_D3hot:
- error = acpi_bus_set_power(handle, state_conv[state]);
+ error = acpi_device_set_power(adev, state_conv[state]);
}
if (!error)
@@ -214,9 +193,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
static bool acpi_pci_can_wakeup(struct pci_dev *dev)
{
- acpi_handle handle = ACPI_HANDLE(&dev->dev);
-
- return handle ? acpi_bus_can_wakeup(handle) : false;
+ struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
+ return adev ? acpi_device_can_wakeup(adev) : false;
}
static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3f8e3dbcaa7c..d04c5adafc16 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -582,7 +582,7 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: Device state not saved by %pF\n",
drv->suspend_late);
- return 0;
+ goto Fixup;
}
}
@@ -591,6 +591,9 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
pci_pm_set_unknown_state(pci_dev);
+Fixup:
+ pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
return 0;
}
@@ -734,7 +737,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
if (!pm) {
pci_save_state(pci_dev);
- return 0;
+ goto Fixup;
}
if (pm->suspend_noirq) {
@@ -751,7 +754,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
WARN_ONCE(pci_dev->current_state != prev,
"PCI PM: State of device not saved by %pF\n",
pm->suspend_noirq);
- return 0;
+ goto Fixup;
}
}
@@ -775,6 +778,9 @@ static int pci_pm_suspend_noirq(struct device *dev)
if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+Fixup:
+ pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
return 0;
}
@@ -999,8 +1005,10 @@ static int pci_pm_poweroff_noirq(struct device *dev)
if (pci_has_legacy_pm_support(to_pci_dev(dev)))
return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
- if (!drv || !drv->pm)
+ if (!drv || !drv->pm) {
+ pci_fixup_device(pci_fixup_suspend_late, pci_dev);
return 0;
+ }
if (drv->pm->poweroff_noirq) {
int error;
@@ -1021,6 +1029,8 @@ static int pci_pm_poweroff_noirq(struct device *dev)
if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+ pci_fixup_device(pci_fixup_suspend_late, pci_dev);
+
if (pcibios_pm_ops.poweroff_noirq)
return pcibios_pm_ops.poweroff_noirq(dev);
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index a3fbe2012ea3..2ab1b47c7651 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -161,8 +161,8 @@ enum acpi_attr_enum {
static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
{
int len;
- len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer,
- obj->string.length,
+ len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
+ obj->buffer.length,
UTF16_LITTLE_ENDIAN,
buf, PAGE_SIZE);
buf[len] = '\n';
@@ -187,16 +187,22 @@ static int dsm_get_label(struct device *dev, char *buf,
tmp = obj->package.elements;
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 &&
tmp[0].type == ACPI_TYPE_INTEGER &&
- tmp[1].type == ACPI_TYPE_STRING) {
+ (tmp[1].type == ACPI_TYPE_STRING ||
+ tmp[1].type == ACPI_TYPE_BUFFER)) {
/*
* The second string element is optional even when
* this _DSM is implemented; when not implemented,
* this entry must return a null string.
*/
- if (attr == ACPI_ATTR_INDEX_SHOW)
+ if (attr == ACPI_ATTR_INDEX_SHOW) {
scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value);
- else if (attr == ACPI_ATTR_LABEL_SHOW)
- dsm_label_utf16s_to_utf8s(tmp + 1, buf);
+ } else if (attr == ACPI_ATTR_LABEL_SHOW) {
+ if (tmp[1].type == ACPI_TYPE_STRING)
+ scnprintf(buf, PAGE_SIZE, "%s\n",
+ tmp[1].string.pointer);
+ else if (tmp[1].type == ACPI_TYPE_BUFFER)
+ dsm_label_utf16s_to_utf8s(tmp + 1, buf);
+ }
len = strlen(buf) > 0 ? strlen(buf) : -1;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1c8592b0e146..2c9ac70254e2 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -839,12 +839,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if (!__pci_complete_power_transition(dev, state))
error = 0;
- /*
- * When aspm_policy is "powersave" this call ensures
- * that ASPM is configured.
- */
- if (!error && dev->bus->self)
- pcie_aspm_powersave_config_link(dev->bus->self);
return error;
}
@@ -1195,12 +1189,18 @@ int __weak pcibios_enable_device(struct pci_dev *dev, int bars)
static int do_pci_enable_device(struct pci_dev *dev, int bars)
{
int err;
+ struct pci_dev *bridge;
u16 cmd;
u8 pin;
err = pci_set_power_state(dev, PCI_D0);
if (err < 0 && err != -EIO)
return err;
+
+ bridge = pci_upstream_bridge(dev);
+ if (bridge)
+ pcie_aspm_powersave_config_link(bridge);
+
err = pcibios_enable_device(dev, bars);
if (err < 0)
return err;
@@ -3198,7 +3198,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
return 0;
}
-void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
+void pci_reset_secondary_bus(struct pci_dev *dev)
{
u16 ctrl;
@@ -3224,6 +3224,11 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
ssleep(1);
}
+void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
+{
+ pci_reset_secondary_bus(dev);
+}
+
/**
* pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
* @dev: Bridge device
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
index 50e94e02378a..389440228c1d 100644
--- a/drivers/pci/pcie/aer/Kconfig
+++ b/drivers/pci/pcie/aer/Kconfig
@@ -5,6 +5,7 @@
config PCIEAER
boolean "Root Port Advanced Error Reporting support"
depends on PCIEPORTBUS
+ select RAS
default y
help
This enables PCI Express Root Port Advanced Error Reporting
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 36ed31b52198..35d06e177917 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -22,9 +22,7 @@
#include <linux/cper.h>
#include "aerdrv.h"
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/ras.h>
+#include <ras/ras_event.h>
#define AER_AGENT_RECEIVER 0
#define AER_AGENT_REQUESTER 1
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 80887eaa0668..2ccc9b926ea7 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
(pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
return -ENODEV;
- if (!dev->irq && dev->pin) {
- dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n",
- dev->vendor, dev->device);
- }
status = pcie_port_device_register(dev);
if (status)
return status;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index d0f69269eb6c..80c2d014283d 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2986,6 +2986,103 @@ DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169,
quirk_broken_intx_masking);
+#ifdef CONFIG_ACPI
+/*
+ * Apple: Shutdown Cactus Ridge Thunderbolt controller.
+ *
+ * On Apple hardware the Cactus Ridge Thunderbolt controller needs to be
+ * shutdown before suspend. Otherwise the native host interface (NHI) will not
+ * be present after resume if a device was plugged in before suspend.
+ *
+ * The thunderbolt controller consists of a pcie switch with downstream
+ * bridges leading to the NHI and to the tunnel pci bridges.
+ *
+ * This quirk cuts power to the whole chip. Therefore we have to apply it
+ * during suspend_noirq of the upstream bridge.
+ *
+ * Power is automagically restored before resume. No action is needed.
+ */
+static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev)
+{
+ acpi_handle bridge, SXIO, SXFP, SXLV;
+
+ if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
+ return;
+ if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM)
+ return;
+ bridge = ACPI_HANDLE(&dev->dev);
+ if (!bridge)
+ return;
+ /*
+ * SXIO and SXLV are present only on machines requiring this quirk.
+ * TB bridges in external devices might have the same device id as those
+ * on the host, but they will not have the associated ACPI methods. This
+ * implicitly checks that we are at the right bridge.
+ */
+ if (ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXIO", &SXIO))
+ || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXFP", &SXFP))
+ || ACPI_FAILURE(acpi_get_handle(bridge, "DSB0.NHI0.SXLV", &SXLV)))
+ return;
+ dev_info(&dev->dev, "quirk: cutting power to thunderbolt controller...\n");
+
+ /* magic sequence */
+ acpi_execute_simple_method(SXIO, NULL, 1);
+ acpi_execute_simple_method(SXFP, NULL, 0);
+ msleep(300);
+ acpi_execute_simple_method(SXLV, NULL, 0);
+ acpi_execute_simple_method(SXIO, NULL, 0);
+ acpi_execute_simple_method(SXLV, NULL, 0);
+}
+DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, 0x1547,
+ quirk_apple_poweroff_thunderbolt);
+
+/*
+ * Apple: Wait for the thunderbolt controller to reestablish pci tunnels.
+ *
+ * During suspend the thunderbolt controller is reset and all pci
+ * tunnels are lost. The NHI driver will try to reestablish all tunnels
+ * during resume. We have to manually wait for the NHI since there is
+ * no parent child relationship between the NHI and the tunneled
+ * bridges.
+ */
+static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev)
+{
+ struct pci_dev *sibling = NULL;
+ struct pci_dev *nhi = NULL;
+
+ if (!dmi_match(DMI_BOARD_VENDOR, "Apple Inc."))
+ return;
+ if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ /*
+ * Find the NHI and confirm that we are a bridge on the tb host
+ * controller and not on a tb endpoint.
+ */
+ sibling = pci_get_slot(dev->bus, 0x0);
+ if (sibling == dev)
+ goto out; /* we are the downstream bridge to the NHI */
+ if (!sibling || !sibling->subordinate)
+ goto out;
+ nhi = pci_get_slot(sibling->subordinate, 0x0);
+ if (!nhi)
+ goto out;
+ if (nhi->vendor != PCI_VENDOR_ID_INTEL
+ || (nhi->device != 0x1547 && nhi->device != 0x156c)
+ || nhi->subsystem_vendor != 0x2222
+ || nhi->subsystem_device != 0x1111)
+ goto out;
+ dev_info(&dev->dev, "quirk: wating for thunderbolt to reestablish pci tunnels...\n");
+ device_pm_wait_for_dev(&dev->dev, &nhi->dev);
+out:
+ pci_dev_put(nhi);
+ pci_dev_put(sibling);
+}
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x1547,
+ quirk_apple_wait_for_thunderbolt);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, 0x156d,
+ quirk_apple_wait_for_thunderbolt);
+#endif
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
@@ -3018,6 +3115,8 @@ extern struct pci_fixup __start_pci_fixups_resume_early[];
extern struct pci_fixup __end_pci_fixups_resume_early[];
extern struct pci_fixup __start_pci_fixups_suspend[];
extern struct pci_fixup __end_pci_fixups_suspend[];
+extern struct pci_fixup __start_pci_fixups_suspend_late[];
+extern struct pci_fixup __end_pci_fixups_suspend_late[];
static bool pci_apply_fixup_final_quirks;
@@ -3063,6 +3162,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
end = __end_pci_fixups_suspend;
break;
+ case pci_fixup_suspend_late:
+ start = __start_pci_fixups_suspend_late;
+ end = __end_pci_fixups_suspend_late;
+ break;
+
default:
/* stupid compiler warning, you would think with an enum... */
return;
@@ -3405,6 +3509,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1080,
DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias);
/* ITE 8892, https://bugzilla.kernel.org/show_bug.cgi?id=73551 */
DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
+/* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
+DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
{
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index a5a63ecfb628..6373985ad3f7 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -925,7 +925,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
{
struct pci_dev *dev;
resource_size_t min_align, align, size, size0, size1;
- resource_size_t aligns[14]; /* Alignments from 1Mb to 8Gb */
+ resource_size_t aligns[18]; /* Alignments from 1Mb to 128Gb */
int order, max_order;
struct resource *b_res = find_free_bus_resource(bus,
mask | IORESOURCE_PREFETCH, type);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index caed1ce6facd..b7c3a5ea1fca 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -166,11 +166,10 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
{
struct resource *root, *conflict;
resource_size_t fw_addr, start, end;
- int ret = 0;
fw_addr = pcibios_retrieve_fw_addr(dev, resno);
if (!fw_addr)
- return 1;
+ return -ENOMEM;
start = res->start;
end = res->end;
@@ -189,14 +188,13 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
resno, res);
conflict = request_resource_conflict(root, res);
if (conflict) {
- dev_info(&dev->dev,
- "BAR %d: %pR conflicts with %s %pR\n", resno,
- res, conflict->name, conflict);
+ dev_info(&dev->dev, "BAR %d: %pR conflicts with %s %pR\n",
+ resno, res, conflict->name, conflict);
res->start = start;
res->end = end;
- ret = 1;
+ return -EBUSY;
}
- return ret;
+ return 0;
}
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
@@ -250,10 +248,8 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
static int _pci_assign_resource(struct pci_dev *dev, int resno,
resource_size_t size, resource_size_t min_align)
{
- struct resource *res = dev->resource + resno;
struct pci_bus *bus;
int ret;
- char *type;
bus = dev->bus;
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
@@ -262,21 +258,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
bus = bus->parent;
}
- if (ret) {
- if (res->flags & IORESOURCE_MEM)
- if (res->flags & IORESOURCE_PREFETCH)
- type = "mem pref";
- else
- type = "mem";
- else if (res->flags & IORESOURCE_IO)
- type = "io";
- else
- type = "unknown";
- dev_info(&dev->dev,
- "BAR %d: can't assign %s (size %#llx)\n",
- resno, type, (unsigned long long) resource_size(res));
- }
-
return ret;
}
@@ -302,17 +283,24 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
* where firmware left it. That at least has a chance of
* working, which is better than just leaving it disabled.
*/
- if (ret < 0)
+ if (ret < 0) {
+ dev_info(&dev->dev, "BAR %d: no space for %pR\n", resno, res);
ret = pci_revert_fw_address(res, dev, resno, size);
+ }
- if (!ret) {
- res->flags &= ~IORESOURCE_UNSET;
- res->flags &= ~IORESOURCE_STARTALIGN;
- dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
- if (resno < PCI_BRIDGE_RESOURCES)
- pci_update_resource(dev, resno);
+ if (ret < 0) {
+ dev_info(&dev->dev, "BAR %d: failed to assign %pR\n", resno,
+ res);
+ return ret;
}
- return ret;
+
+ res->flags &= ~IORESOURCE_UNSET;
+ res->flags &= ~IORESOURCE_STARTALIGN;
+ dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
+ if (resno < PCI_BRIDGE_RESOURCES)
+ pci_update_resource(dev, resno);
+
+ return 0;
}
EXPORT_SYMBOL(pci_assign_resource);
@@ -320,9 +308,11 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
resource_size_t min_align)
{
struct resource *res = dev->resource + resno;
+ unsigned long flags;
resource_size_t new_size;
int ret;
+ flags = res->flags;
res->flags |= IORESOURCE_UNSET;
if (!res->parent) {
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR\n",
@@ -333,14 +323,21 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
/* already aligned with min_align */
new_size = resource_size(res) + addsize;
ret = _pci_assign_resource(dev, resno, new_size, min_align);
- if (!ret) {
- res->flags &= ~IORESOURCE_UNSET;
- res->flags &= ~IORESOURCE_STARTALIGN;
- dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
- if (resno < PCI_BRIDGE_RESOURCES)
- pci_update_resource(dev, resno);
+ if (ret) {
+ res->flags = flags;
+ dev_info(&dev->dev, "BAR %d: %pR (failed to expand by %#llx)\n",
+ resno, res, (unsigned long long) addsize);
+ return ret;
}
- return ret;
+
+ res->flags &= ~IORESOURCE_UNSET;
+ res->flags &= ~IORESOURCE_STARTALIGN;
+ dev_info(&dev->dev, "BAR %d: reassigned %pR (expanded by %#llx)\n",
+ resno, res, (unsigned long long) addsize);
+ if (resno < PCI_BRIDGE_RESOURCES)
+ pci_update_resource(dev, resno);
+
+ return 0;
}
int pci_enable_resources(struct pci_dev *dev, int mask)
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 0c657d6af03d..b0ce7cdee0c2 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -144,16 +144,6 @@ config TCIC
"Bridge" is the name used for the hardware inside your computer that
PCMCIA cards are plugged into. If unsure, say N.
-config PCMCIA_M8XX
- tristate "MPC8xx PCMCIA support"
- depends on PCCARD && PPC && 8xx
- select PCCARD_IODYN if PCMCIA != n
- help
- Say Y here to include support for PowerPC 8xx series PCMCIA
- controller.
-
- This driver is also available as a module called m8xx_pcmcia.
-
config PCMCIA_ALCHEMY_DEVBOARD
tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
depends on MIPS_ALCHEMY && PCMCIA
@@ -202,6 +192,7 @@ config PCMCIA_SA1111
depends on ARM && SA1111 && PCMCIA
select PCMCIA_SOC_COMMON
select PCMCIA_SA11XX_BASE if ARCH_SA1100
+ select PCMCIA_PXA2XX if ARCH_LUBBOCK && SA1111
help
Say Y here to include support for SA1111-based PCMCIA or CF
sockets, found on the Jornada 720, Graphicsmaster and other
@@ -217,7 +208,6 @@ config PCMCIA_PXA2XX
|| ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
|| MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
|| MACH_COLIBRI320 || MACH_H4700)
- select PCMCIA_SA1111 if ARCH_LUBBOCK && SA1111
select PCMCIA_SOC_COMMON
help
Say Y here to include support for the PXA2xx PCMCIA controller
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 7745b512a87c..27e94b30cf96 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -23,7 +23,6 @@ obj-$(CONFIG_PD6729) += pd6729.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
-obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
obj-$(CONFIG_PCMCIA_SOC_COMMON) += soc_common.o
obj-$(CONFIG_PCMCIA_SA11XX_BASE) += sa11xx_base.o
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
@@ -49,6 +48,7 @@ sa1100_cs-y += sa1100_generic.o
sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_H3100) += sa1100_h3600.o
sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-$(CONFIG_SA1100_NANOENGINE) += sa1100_nanoengine.o
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
index 0c6aac1232fc..0802e0bc7d0c 100644
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -475,7 +475,7 @@ static void bcm63xx_cb_exit(struct pci_dev *dev)
bcm63xx_cb_dev = NULL;
}
-static DEFINE_PCI_DEVICE_TABLE(bcm63xx_cb_table) = {
+static const struct pci_device_id bcm63xx_cb_table[] = {
{
.vendor = PCI_VENDOR_ID_BROADCOM,
.device = BCM6348_CPU_ID,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 7d47456429a1..aae7e6df99cd 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -25,7 +25,7 @@
MODULE_LICENSE("GPL");
/* PCI core routines */
-static DEFINE_PCI_DEVICE_TABLE(i82092aa_pci_ids) = {
+static const struct pci_device_id i82092aa_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
{ }
};
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
deleted file mode 100644
index 182034d2ef58..000000000000
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ /dev/null
@@ -1,1168 +0,0 @@
-/*
- * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
- *
- * (C) 1999-2000 Magnus Damm <damm@opensource.se>
- * (C) 2001-2002 Montavista Software, Inc.
- * <mlocke@mvista.com>
- *
- * Support for two slots by Cyclades Corporation
- * <oliver.kurth@cyclades.de>
- * Further fixes, v2.6 kernel port
- * <marcelo.tosatti@cyclades.com>
- *
- * Some fixes, additions (C) 2005-2007 Montavista Software, Inc.
- * <vbordug@ru.mvista.com>
- *
- * "The ExCA standard specifies that socket controllers should provide
- * two IO and five memory windows per socket, which can be independently
- * configured and positioned in the host address space and mapped to
- * arbitrary segments of card address space. " - David A Hinds. 1999
- *
- * This controller does _not_ meet the ExCA standard.
- *
- * m8xx pcmcia controller brief info:
- * + 8 windows (attrib, mem, i/o)
- * + up to two slots (SLOT_A and SLOT_B)
- * + inputpins, outputpins, event and mask registers.
- * - no offset register. sigh.
- *
- * Because of the lacking offset register we must map the whole card.
- * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
- * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
- * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
- * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
- * They are maximum 64KByte each...
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/string.h>
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/bitops.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/mpc8xx.h>
-#include <asm/8xx_immap.h>
-#include <asm/irq.h>
-#include <asm/fs_pd.h>
-
-#include <pcmcia/ss.h>
-
-#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
-#define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args)
-
-static const char *version = "Version 0.06, Aug 2005";
-MODULE_LICENSE("Dual MPL/GPL");
-
-#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
-
-/* The ADS board use SLOT_A */
-#ifdef CONFIG_ADS
-#define CONFIG_PCMCIA_SLOT_A
-#define CONFIG_BD_IS_MHZ
-#endif
-
-/* The FADS series are a mess */
-#ifdef CONFIG_FADS
-#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
-#define CONFIG_PCMCIA_SLOT_A
-#else
-#define CONFIG_PCMCIA_SLOT_B
-#endif
-#endif
-
-#if defined(CONFIG_MPC885ADS)
-#define CONFIG_PCMCIA_SLOT_A
-#define PCMCIA_GLITCHY_CD
-#endif
-
-/* Cyclades ACS uses both slots */
-#ifdef CONFIG_PRxK
-#define CONFIG_PCMCIA_SLOT_A
-#define CONFIG_PCMCIA_SLOT_B
-#endif
-
-#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
-
-#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
-
-#define PCMCIA_SOCKETS_NO 2
-/* We have only 8 windows, dualsocket support will be limited. */
-#define PCMCIA_MEM_WIN_NO 2
-#define PCMCIA_IO_WIN_NO 2
-#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"
-
-#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)
-
-#define PCMCIA_SOCKETS_NO 1
-/* full support for one slot */
-#define PCMCIA_MEM_WIN_NO 5
-#define PCMCIA_IO_WIN_NO 2
-
-/* define _slot_ to be able to optimize macros */
-
-#ifdef CONFIG_PCMCIA_SLOT_A
-#define _slot_ 0
-#define PCMCIA_SLOT_MSG "SLOT_A"
-#else
-#define _slot_ 1
-#define PCMCIA_SLOT_MSG "SLOT_B"
-#endif
-
-#else
-#error m8xx_pcmcia: Bad configuration!
-#endif
-
-/* ------------------------------------------------------------------------- */
-
-#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */
-#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */
-#define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */
-/* ------------------------------------------------------------------------- */
-
-static int pcmcia_schlvl;
-
-static DEFINE_SPINLOCK(events_lock);
-
-#define PCMCIA_SOCKET_KEY_5V 1
-#define PCMCIA_SOCKET_KEY_LV 2
-
-/* look up table for pgcrx registers */
-static u32 *m8xx_pgcrx[2];
-
-/*
- * This structure is used to address each window in the PCMCIA controller.
- *
- * Keep in mind that we assume that pcmcia_win[n+1] is mapped directly
- * after pcmcia_win[n]...
- */
-
-struct pcmcia_win {
- u32 br;
- u32 or;
-};
-
-/*
- * For some reason the hardware guys decided to make both slots share
- * some registers.
- *
- * Could someone invent object oriented hardware ?
- *
- * The macros are used to get the right bit from the registers.
- * SLOT_A : slot = 0
- * SLOT_B : slot = 1
- */
-
-#define M8XX_PCMCIA_VS1(slot) (0x80000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS2(slot) (0x40000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS_MASK(slot) (0xc0000000 >> (slot << 4))
-#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))
-
-#define M8XX_PCMCIA_WP(slot) (0x20000000 >> (slot << 4))
-#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
-#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
-#define M8XX_PCMCIA_BVD2(slot) (0x04000000 >> (slot << 4))
-#define M8XX_PCMCIA_BVD1(slot) (0x02000000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY(slot) (0x01000000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_L(slot) (0x00800000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_H(slot) (0x00400000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_R(slot) (0x00200000 >> (slot << 4))
-#define M8XX_PCMCIA_RDY_F(slot) (0x00100000 >> (slot << 4))
-#define M8XX_PCMCIA_MASK(slot) (0xFFFF0000 >> (slot << 4))
-
-#define M8XX_PCMCIA_POR_VALID 0x00000001
-#define M8XX_PCMCIA_POR_WRPROT 0x00000002
-#define M8XX_PCMCIA_POR_ATTRMEM 0x00000010
-#define M8XX_PCMCIA_POR_IO 0x00000018
-#define M8XX_PCMCIA_POR_16BIT 0x00000040
-
-#define M8XX_PGCRX(slot) m8xx_pgcrx[slot]
-
-#define M8XX_PGCRX_CXOE 0x00000080
-#define M8XX_PGCRX_CXRESET 0x00000040
-
-/* we keep one lookup table per socket to check flags */
-
-#define PCMCIA_EVENTS_MAX 5 /* 4 max at a time + termination */
-
-struct event_table {
- u32 regbit;
- u32 eventbit;
-};
-
-static const char driver_name[] = "m8xx-pcmcia";
-
-struct socket_info {
- void (*handler) (void *info, u32 events);
- void *info;
-
- u32 slot;
- pcmconf8xx_t *pcmcia;
- u32 bus_freq;
- int hwirq;
-
- socket_state_t state;
- struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];
- struct pccard_io_map io_win[PCMCIA_IO_WIN_NO];
- struct event_table events[PCMCIA_EVENTS_MAX];
- struct pcmcia_socket socket;
-};
-
-static struct socket_info socket[PCMCIA_SOCKETS_NO];
-
-/*
- * Search this table to see if the windowsize is
- * supported...
- */
-
-#define M8XX_SIZES_NO 32
-
-static const u32 m8xx_size_to_gray[M8XX_SIZES_NO] = {
- 0x00000001, 0x00000002, 0x00000008, 0x00000004,
- 0x00000080, 0x00000040, 0x00000010, 0x00000020,
- 0x00008000, 0x00004000, 0x00001000, 0x00002000,
- 0x00000100, 0x00000200, 0x00000800, 0x00000400,
-
- 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
- 0x00010000, 0x00020000, 0x00080000, 0x00040000,
- 0x00800000, 0x00400000, 0x00100000, 0x00200000
-};
-
-/* ------------------------------------------------------------------------- */
-
-static irqreturn_t m8xx_interrupt(int irq, void *dev);
-
-#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
-
-/* FADS Boards from Motorola */
-
-#if defined(CONFIG_FADS)
-
-#define PCMCIA_BOARD_MSG "FADS"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
- u32 reg = 0;
-
- switch (vcc) {
- case 0:
- break;
- case 33:
- reg |= BCSR1_PCCVCC0;
- break;
- case 50:
- reg |= BCSR1_PCCVCC1;
- break;
- default:
- return 1;
- }
-
- switch (vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if (vcc == vpp)
- reg |= BCSR1_PCCVPP1;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= BCSR1_PCCVPP0;
- else
- return 1;
- default:
- return 1;
- }
-
- /* first, turn off all power */
- out_be32((u32 *) BCSR1,
- in_be32((u32 *) BCSR1) & ~(BCSR1_PCCVCC_MASK |
- BCSR1_PCCVPP_MASK));
-
- /* enable new powersettings */
- out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | reg);
-
- return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static void hardware_enable(int slot)
-{
- out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) & ~BCSR1_PCCEN);
-}
-
-static void hardware_disable(int slot)
-{
- out_be32((u32 *) BCSR1, in_be32((u32 *) BCSR1) | BCSR1_PCCEN);
-}
-
-#endif
-
-/* MPC885ADS Boards */
-
-#if defined(CONFIG_MPC885ADS)
-
-#define PCMCIA_BOARD_MSG "MPC885ADS"
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-
-static inline void hardware_enable(int slot)
-{
- m8xx_pcmcia_ops.hw_ctrl(slot, 1);
-}
-
-static inline void hardware_disable(int slot)
-{
- m8xx_pcmcia_ops.hw_ctrl(slot, 0);
-}
-
-static inline int voltage_set(int slot, int vcc, int vpp)
-{
- return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp);
-}
-
-#endif
-
-#if defined(CONFIG_PRxK)
-#include <asm/cpld.h>
-extern volatile fpga_pc_regs *fpga_pc;
-
-#define PCMCIA_BOARD_MSG "MPC855T"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
- u8 reg = 0;
- u8 regread;
- cpld_regs *ccpld = get_cpld();
-
- switch (vcc) {
- case 0:
- break;
- case 33:
- reg |= PCMCIA_VCC_33;
- break;
- case 50:
- reg |= PCMCIA_VCC_50;
- break;
- default:
- return 1;
- }
-
- switch (vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if (vcc == vpp)
- reg |= PCMCIA_VPP_VCC;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= PCMCIA_VPP_12;
- else
- return 1;
- default:
- return 1;
- }
-
- reg = reg >> (slot << 2);
- regread = in_8(&ccpld->fpga_pc_ctl);
- if (reg !=
- (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
- /* enable new powersettings */
- regread =
- regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >>
- (slot << 2));
- out_8(&ccpld->fpga_pc_ctl, reg | regread);
- msleep(100);
- }
-
- return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
-
-#endif /* CONFIG_PRxK */
-
-static u32 pending_events[PCMCIA_SOCKETS_NO];
-static DEFINE_SPINLOCK(pending_event_lock);
-
-static irqreturn_t m8xx_interrupt(int irq, void *dev)
-{
- struct socket_info *s;
- struct event_table *e;
- unsigned int i, events, pscr, pipr, per;
- pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
- pr_debug("m8xx_pcmcia: Interrupt!\n");
- /* get interrupt sources */
-
- pscr = in_be32(&pcmcia->pcmc_pscr);
- pipr = in_be32(&pcmcia->pcmc_pipr);
- per = in_be32(&pcmcia->pcmc_per);
-
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
- s = &socket[i];
- e = &s->events[0];
- events = 0;
-
- while (e->regbit) {
- if (pscr & e->regbit)
- events |= e->eventbit;
-
- e++;
- }
-
- /*
- * report only if both card detect signals are the same
- * not too nice done,
- * we depend on that CD2 is the bit to the left of CD1...
- */
- if (events & SS_DETECT)
- if (((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
- (pipr & M8XX_PCMCIA_CD1(i))) {
- events &= ~SS_DETECT;
- }
-#ifdef PCMCIA_GLITCHY_CD
- /*
- * I've experienced CD problems with my ADS board.
- * We make an extra check to see if there was a
- * real change of Card detection.
- */
-
- if ((events & SS_DETECT) &&
- ((pipr &
- (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
- (s->state.Vcc | s->state.Vpp)) {
- events &= ~SS_DETECT;
- /*printk( "CD glitch workaround - CD = 0x%08x!\n",
- (pipr & (M8XX_PCMCIA_CD2(i)
- | M8XX_PCMCIA_CD1(i)))); */
- }
-#endif
-
- /* call the handler */
-
- pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, "
- "pipr = 0x%08x\n", i, events, pscr, pipr);
-
- if (events) {
- spin_lock(&pending_event_lock);
- pending_events[i] |= events;
- spin_unlock(&pending_event_lock);
- /*
- * Turn off RDY_L bits in the PER mask on
- * CD interrupt receival.
- *
- * They can generate bad interrupts on the
- * ACS4,8,16,32. - marcelo
- */
- per &= ~M8XX_PCMCIA_RDY_L(0);
- per &= ~M8XX_PCMCIA_RDY_L(1);
-
- out_be32(&pcmcia->pcmc_per, per);
-
- if (events)
- pcmcia_parse_events(&socket[i].socket, events);
- }
- }
-
- /* clear the interrupt sources */
- out_be32(&pcmcia->pcmc_pscr, pscr);
-
- pr_debug("m8xx_pcmcia: Interrupt done.\n");
-
- return IRQ_HANDLED;
-}
-
-static u32 m8xx_get_graycode(u32 size)
-{
- u32 k;
-
- for (k = 0; k < M8XX_SIZES_NO; k++)
- if (m8xx_size_to_gray[k] == size)
- break;
-
- if ((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
- k = -1;
-
- return k;
-}
-
-static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq)
-{
- u32 reg, clocks, psst, psl, psht;
-
- if (!ns) {
-
- /*
- * We get called with IO maps setup to 0ns
- * if not specified by the user.
- * They should be 255ns.
- */
-
- if (is_io)
- ns = 255;
- else
- ns = 100; /* fast memory if 0 */
- }
-
- /*
- * In PSST, PSL, PSHT fields we tell the controller
- * timing parameters in CLKOUT clock cycles.
- * CLKOUT is the same as GCLK2_50.
- */
-
-/* how we want to adjust the timing - in percent */
-
-#define ADJ 180 /* 80 % longer accesstime - to be sure */
-
- clocks = ((bus_freq / 1000) * ns) / 1000;
- clocks = (clocks * ADJ) / (100 * 1000);
- if (clocks >= PCMCIA_BMT_LIMIT) {
- printk("Max access time limit reached\n");
- clocks = PCMCIA_BMT_LIMIT - 1;
- }
-
- psst = clocks / 7; /* setup time */
- psht = clocks / 7; /* hold time */
- psl = (clocks * 5) / 7; /* strobe length */
-
- psst += clocks - (psst + psht + psl);
-
- reg = psst << 12;
- reg |= psl << 7;
- reg |= psht << 16;
-
- return reg;
-}
-
-static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
-{
- int lsock = container_of(sock, struct socket_info, socket)->slot;
- struct socket_info *s = &socket[lsock];
- unsigned int pipr, reg;
- pcmconf8xx_t *pcmcia = s->pcmcia;
-
- pipr = in_be32(&pcmcia->pcmc_pipr);
-
- *value = ((pipr & (M8XX_PCMCIA_CD1(lsock)
- | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0;
- *value |= (pipr & M8XX_PCMCIA_WP(lsock)) ? SS_WRPROT : 0;
-
- if (s->state.flags & SS_IOCARD)
- *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_STSCHG : 0;
- else {
- *value |= (pipr & M8XX_PCMCIA_RDY(lsock)) ? SS_READY : 0;
- *value |= (pipr & M8XX_PCMCIA_BVD1(lsock)) ? SS_BATDEAD : 0;
- *value |= (pipr & M8XX_PCMCIA_BVD2(lsock)) ? SS_BATWARN : 0;
- }
-
- if (s->state.Vcc | s->state.Vpp)
- *value |= SS_POWERON;
-
- /*
- * Voltage detection:
- * This driver only supports 16-Bit pc-cards.
- * Cardbus is not handled here.
- *
- * To determine what voltage to use we must read the VS1 and VS2 pin.
- * Depending on what socket type is present,
- * different combinations mean different things.
- *
- * Card Key Socket Key VS1 VS2 Card Vcc for CIS parse
- *
- * 5V 5V, LV* NC NC 5V only 5V (if available)
- *
- * 5V 5V, LV* GND NC 5 or 3.3V as low as possible
- *
- * 5V 5V, LV* GND GND 5, 3.3, x.xV as low as possible
- *
- * LV* 5V - - shall not fit into socket
- *
- * LV* LV* GND NC 3.3V only 3.3V
- *
- * LV* LV* NC GND x.xV x.xV (if avail.)
- *
- * LV* LV* GND GND 3.3 or x.xV as low as possible
- *
- * *LV means Low Voltage
- *
- *
- * That gives us the following table:
- *
- * Socket VS1 VS2 Voltage
- *
- * 5V NC NC 5V
- * 5V NC GND none (should not be possible)
- * 5V GND NC >= 3.3V
- * 5V GND GND >= x.xV
- *
- * LV NC NC 5V (if available)
- * LV NC GND x.xV (if available)
- * LV GND NC 3.3V
- * LV GND GND >= x.xV
- *
- * So, how do I determine if I have a 5V or a LV
- * socket on my board? Look at the socket!
- *
- *
- * Socket with 5V key:
- * ++--------------------------------------------+
- * || |
- * || ||
- * || ||
- * | |
- * +---------------------------------------------+
- *
- * Socket with LV key:
- * ++--------------------------------------------+
- * || |
- * | ||
- * | ||
- * | |
- * +---------------------------------------------+
- *
- *
- * With other words - LV only cards does not fit
- * into the 5V socket!
- */
-
- /* read out VS1 and VS2 */
-
- reg = (pipr & M8XX_PCMCIA_VS_MASK(lsock))
- >> M8XX_PCMCIA_VS_SHIFT(lsock);
-
- if (socket_get(lsock) == PCMCIA_SOCKET_KEY_LV) {
- switch (reg) {
- case 1:
- *value |= SS_3VCARD;
- break; /* GND, NC - 3.3V only */
- case 2:
- *value |= SS_XVCARD;
- break; /* NC. GND - x.xV only */
- };
- }
-
- pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value);
- return 0;
-}
-
-static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
-{
- int lsock = container_of(sock, struct socket_info, socket)->slot;
- struct socket_info *s = &socket[lsock];
- struct event_table *e;
- unsigned int reg;
- unsigned long flags;
- pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
- pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-
- /* First, set voltage - bail out if invalid */
- if (voltage_set(lsock, state->Vcc, state->Vpp))
- return -EINVAL;
-
- /* Take care of reset... */
- if (state->flags & SS_RESET)
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */
- else
- out_be32(M8XX_PGCRX(lsock),
- in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXRESET);
-
- /* ... and output enable. */
-
- /* The CxOE signal is connected to a 74541 on the ADS.
- I guess most other boards used the ADS as a reference.
- I tried to control the CxOE signal with SS_OUTPUT_ENA,
- but the reset signal seems connected via the 541.
- If the CxOE is left high are some signals tristated and
- no pullups are present -> the cards act weird.
- So right now the buffers are enabled if the power is on. */
-
- if (state->Vcc || state->Vpp)
- out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) & ~M8XX_PGCRX_CXOE); /* active low */
- else
- out_be32(M8XX_PGCRX(lsock),
- in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXOE);
-
- /*
- * We'd better turn off interrupts before
- * we mess with the events-table..
- */
-
- spin_lock_irqsave(&events_lock, flags);
-
- /*
- * Play around with the interrupt mask to be able to
- * give the events the generic pcmcia driver wants us to.
- */
-
- e = &s->events[0];
- reg = 0;
-
- if (state->csc_mask & SS_DETECT) {
- e->eventbit = SS_DETECT;
- reg |= e->regbit = (M8XX_PCMCIA_CD2(lsock)
- | M8XX_PCMCIA_CD1(lsock));
- e++;
- }
- if (state->flags & SS_IOCARD) {
- /*
- * I/O card
- */
- if (state->csc_mask & SS_STSCHG) {
- e->eventbit = SS_STSCHG;
- reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
- e++;
- }
- /*
- * If io_irq is non-zero we should enable irq.
- */
- if (state->io_irq) {
- out_be32(M8XX_PGCRX(lsock),
- in_be32(M8XX_PGCRX(lsock)) |
- mk_int_int_mask(s->hwirq) << 24);
- /*
- * Strange thing here:
- * The manual does not tell us which interrupt
- * the sources generate.
- * Anyhow, I found out that RDY_L generates IREQLVL.
- *
- * We use level triggerd interrupts, and they don't
- * have to be cleared in PSCR in the interrupt handler.
- */
- reg |= M8XX_PCMCIA_RDY_L(lsock);
- } else
- out_be32(M8XX_PGCRX(lsock),
- in_be32(M8XX_PGCRX(lsock)) & 0x00ffffff);
- } else {
- /*
- * Memory card
- */
- if (state->csc_mask & SS_BATDEAD) {
- e->eventbit = SS_BATDEAD;
- reg |= e->regbit = M8XX_PCMCIA_BVD1(lsock);
- e++;
- }
- if (state->csc_mask & SS_BATWARN) {
- e->eventbit = SS_BATWARN;
- reg |= e->regbit = M8XX_PCMCIA_BVD2(lsock);
- e++;
- }
- /* What should I trigger on - low/high,raise,fall? */
- if (state->csc_mask & SS_READY) {
- e->eventbit = SS_READY;
- reg |= e->regbit = 0; //??
- e++;
- }
- }
-
- e->regbit = 0; /* terminate list */
-
- /*
- * Clear the status changed .
- * Port A and Port B share the same port.
- * Writing ones will clear the bits.
- */
-
- out_be32(&pcmcia->pcmc_pscr, reg);
-
- /*
- * Write the mask.
- * Port A and Port B share the same port.
- * Need for read-modify-write.
- * Ones will enable the interrupt.
- */
-
- reg |=
- in_be32(&pcmcia->
- pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
- out_be32(&pcmcia->pcmc_per, reg);
-
- spin_unlock_irqrestore(&events_lock, flags);
-
- /* copy the struct and modify the copy */
-
- s->state = *state;
-
- return 0;
-}
-
-static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
-{
- int lsock = container_of(sock, struct socket_info, socket)->slot;
-
- struct socket_info *s = &socket[lsock];
- struct pcmcia_win *w;
- unsigned int reg, winnr;
- pcmconf8xx_t *pcmcia = s->pcmcia;
-
-#define M8XX_SIZE (io->stop - io->start + 1)
-#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
-
- pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
- io->speed, (unsigned long long)io->start,
- (unsigned long long)io->stop);
-
- if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
- || (io->stop > 0xffff) || (io->stop < io->start))
- return -EINVAL;
-
- if ((reg = m8xx_get_graycode(M8XX_SIZE)) == -1)
- return -EINVAL;
-
- if (io->flags & MAP_ACTIVE) {
-
- pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n");
-
- winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
- + (lsock * PCMCIA_IO_WIN_NO) + io->map;
-
- /* setup registers */
-
- w = (void *)&pcmcia->pcmc_pbr0;
- w += winnr;
-
- out_be32(&w->or, 0); /* turn off window first */
- out_be32(&w->br, M8XX_BASE);
-
- reg <<= 27;
- reg |= M8XX_PCMCIA_POR_IO | (lsock << 2);
-
- reg |= m8xx_get_speed(io->speed, 1, s->bus_freq);
-
- if (io->flags & MAP_WRPROT)
- reg |= M8XX_PCMCIA_POR_WRPROT;
-
- /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) */
- if (io->flags & MAP_16BIT)
- reg |= M8XX_PCMCIA_POR_16BIT;
-
- if (io->flags & MAP_ACTIVE)
- reg |= M8XX_PCMCIA_POR_VALID;
-
- out_be32(&w->or, reg);
-
- pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at "
- "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
- } else {
- /* shutdown IO window */
- winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)
- + (lsock * PCMCIA_IO_WIN_NO) + io->map;
-
- /* setup registers */
-
- w = (void *)&pcmcia->pcmc_pbr0;
- w += winnr;
-
- out_be32(&w->or, 0); /* turn off window */
- out_be32(&w->br, 0); /* turn off base address */
-
- pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at "
- "%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);
- }
-
- /* copy the struct and modify the copy */
- s->io_win[io->map] = *io;
- s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
- pr_debug("m8xx_pcmcia: SetIOMap exit\n");
-
- return 0;
-}
-
-static int m8xx_set_mem_map(struct pcmcia_socket *sock,
- struct pccard_mem_map *mem)
-{
- int lsock = container_of(sock, struct socket_info, socket)->slot;
- struct socket_info *s = &socket[lsock];
- struct pcmcia_win *w;
- struct pccard_mem_map *old;
- unsigned int reg, winnr;
- pcmconf8xx_t *pcmcia = s->pcmcia;
-
- pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, (unsigned long long)mem->static_start,
- mem->card_start);
-
- if ((mem->map >= PCMCIA_MEM_WIN_NO)
-// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
- || (mem->card_start >= 0x04000000)
- || (mem->static_start & 0xfff) /* 4KByte resolution */
- ||(mem->card_start & 0xfff))
- return -EINVAL;
-
- if ((reg = m8xx_get_graycode(PCMCIA_MEM_WIN_SIZE)) == -1) {
- printk("Cannot set size to 0x%08x.\n", PCMCIA_MEM_WIN_SIZE);
- return -EINVAL;
- }
- reg <<= 27;
-
- winnr = (lsock * PCMCIA_MEM_WIN_NO) + mem->map;
-
- /* Setup the window in the pcmcia controller */
-
- w = (void *)&pcmcia->pcmc_pbr0;
- w += winnr;
-
- reg |= lsock << 2;
-
- reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq);
-
- if (mem->flags & MAP_ATTRIB)
- reg |= M8XX_PCMCIA_POR_ATTRMEM;
-
- if (mem->flags & MAP_WRPROT)
- reg |= M8XX_PCMCIA_POR_WRPROT;
-
- if (mem->flags & MAP_16BIT)
- reg |= M8XX_PCMCIA_POR_16BIT;
-
- if (mem->flags & MAP_ACTIVE)
- reg |= M8XX_PCMCIA_POR_VALID;
-
- out_be32(&w->or, reg);
-
- pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, "
- "OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);
-
- if (mem->flags & MAP_ACTIVE) {
- /* get the new base address */
- mem->static_start = PCMCIA_MEM_WIN_BASE +
- (PCMCIA_MEM_WIN_SIZE * winnr)
- + mem->card_start;
- }
-
- pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, (unsigned long long)mem->static_start,
- mem->card_start);
-
- /* copy the struct and modify the copy */
-
- old = &s->mem_win[mem->map];
-
- *old = *mem;
- old->flags &= (MAP_ATTRIB | MAP_WRPROT | MAP_16BIT | MAP_ACTIVE);
-
- return 0;
-}
-
-static int m8xx_sock_init(struct pcmcia_socket *sock)
-{
- int i;
- pccard_io_map io = { 0, 0, 0, 0, 1 };
- pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
-
- pr_debug("m8xx_pcmcia: sock_init(%d)\n", s);
-
- m8xx_set_socket(sock, &dead_socket);
- for (i = 0; i < PCMCIA_IO_WIN_NO; i++) {
- io.map = i;
- m8xx_set_io_map(sock, &io);
- }
- for (i = 0; i < PCMCIA_MEM_WIN_NO; i++) {
- mem.map = i;
- m8xx_set_mem_map(sock, &mem);
- }
-
- return 0;
-
-}
-
-static int m8xx_sock_suspend(struct pcmcia_socket *sock)
-{
- return m8xx_set_socket(sock, &dead_socket);
-}
-
-static struct pccard_operations m8xx_services = {
- .init = m8xx_sock_init,
- .suspend = m8xx_sock_suspend,
- .get_status = m8xx_get_status,
- .set_socket = m8xx_set_socket,
- .set_io_map = m8xx_set_io_map,
- .set_mem_map = m8xx_set_mem_map,
-};
-
-static int __init m8xx_probe(struct platform_device *ofdev)
-{
- struct pcmcia_win *w;
- unsigned int i, m, hwirq;
- pcmconf8xx_t *pcmcia;
- int status;
- struct device_node *np = ofdev->dev.of_node;
-
- pcmcia_info("%s\n", version);
-
- pcmcia = of_iomap(np, 0);
- if (pcmcia == NULL)
- return -EINVAL;
-
- pcmcia_schlvl = irq_of_parse_and_map(np, 0);
- hwirq = irq_map[pcmcia_schlvl].hwirq;
- if (pcmcia_schlvl < 0) {
- iounmap(pcmcia);
- return -EINVAL;
- }
-
- m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
- m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
-
- pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG
- " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq);
-
- /* Configure Status change interrupt */
-
- if (request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED,
- driver_name, socket)) {
- pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
- pcmcia_schlvl);
- iounmap(pcmcia);
- return -1;
- }
-
- w = (void *)&pcmcia->pcmc_pbr0;
-
- out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
- clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1));
-
- /* connect interrupt and disable CxOE */
-
- out_be32(M8XX_PGCRX(0),
- M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
- out_be32(M8XX_PGCRX(1),
- M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
-
- /* initialize the fixed memory windows */
-
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
- for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
- out_be32(&w->br, PCMCIA_MEM_WIN_BASE +
- (PCMCIA_MEM_WIN_SIZE
- * (m + i * PCMCIA_MEM_WIN_NO)));
-
- out_be32(&w->or, 0); /* set to not valid */
-
- w++;
- }
- }
-
- /* turn off voltage */
- voltage_set(0, 0, 0);
- voltage_set(1, 0, 0);
-
- /* Enable external hardware */
- hardware_enable(0);
- hardware_enable(1);
-
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
- socket[i].slot = i;
- socket[i].socket.owner = THIS_MODULE;
- socket[i].socket.features =
- SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP;
- socket[i].socket.irq_mask = 0x000;
- socket[i].socket.map_size = 0x1000;
- socket[i].socket.io_offset = 0;
- socket[i].socket.pci_irq = pcmcia_schlvl;
- socket[i].socket.ops = &m8xx_services;
- socket[i].socket.resource_ops = &pccard_iodyn_ops;
- socket[i].socket.cb_dev = NULL;
- socket[i].socket.dev.parent = &ofdev->dev;
- socket[i].pcmcia = pcmcia;
- socket[i].bus_freq = ppc_proc_freq;
- socket[i].hwirq = hwirq;
-
- }
-
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
- status = pcmcia_register_socket(&socket[i].socket);
- if (status < 0)
- pcmcia_error("Socket register failed\n");
- }
-
- return 0;
-}
-
-static int m8xx_remove(struct platform_device *ofdev)
-{
- u32 m, i;
- struct pcmcia_win *w;
- pcmconf8xx_t *pcmcia = socket[0].pcmcia;
-
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
- w = (void *)&pcmcia->pcmc_pbr0;
-
- out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i));
- out_be32(&pcmcia->pcmc_per,
- in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i));
-
- /* turn off interrupt and disable CxOE */
- out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE);
-
- /* turn off memory windows */
- for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
- out_be32(&w->or, 0); /* set to not valid */
- w++;
- }
-
- /* turn off voltage */
- voltage_set(i, 0, 0);
-
- /* disable external hardware */
- hardware_disable(i);
- }
- for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
- pcmcia_unregister_socket(&socket[i].socket);
- iounmap(pcmcia);
-
- free_irq(pcmcia_schlvl, NULL);
-
- return 0;
-}
-
-static const struct of_device_id m8xx_pcmcia_match[] = {
- {
- .type = "pcmcia",
- .compatible = "fsl,pq-pcmcia",
- },
- {},
-};
-
-MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
-
-static struct platform_driver m8xx_pcmcia_driver = {
- .driver = {
- .name = driver_name,
- .owner = THIS_MODULE,
- .of_match_table = m8xx_pcmcia_match,
- },
- .probe = m8xx_probe,
- .remove = m8xx_remove,
-};
-
-module_platform_driver(m8xx_pcmcia_driver);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 622dd6fe7347..34ace4854dc2 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -764,7 +764,7 @@ static void pd6729_pci_remove(struct pci_dev *dev)
kfree(socket);
}
-static DEFINE_PCI_DEVICE_TABLE(pd6729_pci_ids) = {
+static const struct pci_device_id pd6729_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) },
{ }
};
diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c
index 3baa3ef09682..40e040314503 100644
--- a/drivers/pcmcia/sa1111_jornada720.c
+++ b/drivers/pcmcia/sa1111_jornada720.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/hardware/sa1111.h>
@@ -94,6 +95,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
int pcmcia_jornada720_init(struct device *dev)
{
int ret = -ENODEV;
+ struct sa1111_dev *sadev = SA1111_DEV(dev);
if (machine_is_jornada720()) {
unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
@@ -101,12 +103,12 @@ int pcmcia_jornada720_init(struct device *dev)
GRER |= 0x00000002;
/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
- sa1111_set_io_dir(dev, pin, 0, 0);
- sa1111_set_io(dev, pin, 0);
- sa1111_set_sleep_io(dev, pin, 0);
+ sa1111_set_io_dir(sadev, pin, 0, 0);
+ sa1111_set_io(sadev, pin, 0);
+ sa1111_set_sleep_io(sadev, pin, 0);
sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops);
- ret = sa1111_pcmcia_add(dev, &jornada720_pcmcia_ops,
+ ret = sa1111_pcmcia_add(sadev, &jornada720_pcmcia_ops,
sa11xx_drv_pcmcia_add_one);
}
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index d92692056e24..9fb0c3addfd4 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -563,7 +563,7 @@ static int vrc4173_cardu_setup(char *options)
__setup("vrc4173_cardu=", vrc4173_cardu_setup);
-static DEFINE_PCI_DEVICE_TABLE(vrc4173_cardu_id_table) = {
+static const struct pci_device_id vrc4173_cardu_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) },
{0, }
};
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 946f90ef6020..8a23ccb41213 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1352,7 +1352,7 @@ static const struct dev_pm_ops yenta_pm_ops = {
.driver_data = CARDBUS_TYPE_##type, \
}
-static DEFINE_PCI_DEVICE_TABLE(yenta_table) = {
+static const struct pci_device_id yenta_table[] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI),
/*
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 64b98d242ea6..0dd742719154 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,13 @@ config GENERIC_PHY
phy users can obtain reference to the PHY. All the users of this
framework should select this config.
+config PHY_BERLIN_SATA
+ tristate "Marvell Berlin SATA PHY driver"
+ depends on ARCH_BERLIN && HAS_IOMEM && OF
+ select GENERIC_PHY
+ help
+ Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
config PHY_EXYNOS_MIPI_VIDEO
tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
depends on HAS_IOMEM
@@ -27,10 +34,20 @@ config PHY_EXYNOS_MIPI_VIDEO
config PHY_MVEBU_SATA
def_bool y
- depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+ depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
depends on OF
select GENERIC_PHY
+config PHY_MIPHY365X
+ tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
+ depends on ARCH_STI
+ depends on GENERIC_PHY
+ depends on HAS_IOMEM
+ depends on OF
+ help
+ Enable this to support the miphy transceiver (for SATA/PCIE)
+ that is part of STMicroelectronics STiH41x SoC series.
+
config OMAP_CONTROL_PHY
tristate "OMAP CONTROL PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
@@ -109,6 +126,14 @@ config PHY_EXYNOS5250_SATA
SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
port to accept one SATA device.
+config PHY_HIX5HD2_SATA
+ tristate "HIX5HD2 SATA PHY Driver"
+ depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Support for SATA PHY on Hisilicon hix5hd2 Soc.
+
config PHY_SUN4I_USB
tristate "Allwinner sunxi SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
@@ -124,55 +149,80 @@ config PHY_SUN4I_USB
config PHY_SAMSUNG_USB2
tristate "Samsung USB 2.0 PHY driver"
depends on HAS_IOMEM
+ depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
select GENERIC_PHY
select MFD_SYSCON
+ default ARCH_EXYNOS
help
Enable this to support the Samsung USB 2.0 PHY driver for Samsung
- SoCs. This driver provides the interface for USB 2.0 PHY. Support for
- particular SoCs has to be enabled in addition to this driver. Number
- and type of supported phys depends on the SoC.
+ SoCs. This driver provides the interface for USB 2.0 PHY. Support
+ for particular PHYs will be enabled based on the SoC type in addition
+ to this driver.
-config PHY_EXYNOS4210_USB2
- bool "Support for Exynos 4210"
+config PHY_S5PV210_USB2
+ bool "Support for S5PV210"
depends on PHY_SAMSUNG_USB2
- depends on CPU_EXYNOS4210
+ depends on ARCH_S5PV210
help
- Enable USB PHY support for Exynos 4210. This option requires that
- Samsung USB 2.0 PHY driver is enabled and means that support for this
- particular SoC is compiled in the driver. In case of Exynos 4210 four
- phys are available - device, host, HSIC0 and HSIC1.
+ Enable USB PHY support for S5PV210. This option requires that Samsung
+ USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of S5PV210 two phys
+ are available - device and host.
+
+config PHY_EXYNOS4210_USB2
+ bool
+ depends on PHY_SAMSUNG_USB2
+ default CPU_EXYNOS4210
config PHY_EXYNOS4X12_USB2
- bool "Support for Exynos 4x12"
+ bool
depends on PHY_SAMSUNG_USB2
- depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
- help
- Enable USB PHY support for Exynos 4x12. This option requires that
- Samsung USB 2.0 PHY driver is enabled and means that support for this
- particular SoC is compiled in the driver. In case of Exynos 4x12 four
- phys are available - device, host, HSIC0 and HSIC1.
+ default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
config PHY_EXYNOS5250_USB2
- bool "Support for Exynos 5250"
+ bool
depends on PHY_SAMSUNG_USB2
- depends on SOC_EXYNOS5250
- help
- Enable USB PHY support for Exynos 5250. This option requires that
- Samsung USB 2.0 PHY driver is enabled and means that support for this
- particular SoC is compiled in the driver. In case of Exynos 5250 four
- phys are available - device, host, HSIC0 and HSIC.
+ default SOC_EXYNOS5250 || SOC_EXYNOS5420
config PHY_EXYNOS5_USBDRD
tristate "Exynos5 SoC series USB DRD PHY driver"
depends on ARCH_EXYNOS5 && OF
depends on HAS_IOMEM
+ depends on USB_DWC3_EXYNOS
select GENERIC_PHY
select MFD_SYSCON
+ default y
help
Enable USB DRD PHY support for Exynos 5 SoC series.
This driver provides PHY interface for USB 3.0 DRD controller
present on Exynos5 SoC series.
+config PHY_QCOM_APQ8064_SATA
+ tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+
+config PHY_QCOM_IPQ806X_SATA
+ tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+
+config PHY_ST_SPEAR1310_MIPHY
+ tristate "ST SPEAR1310-MIPHY driver"
+ select GENERIC_PHY
+ help
+ Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
+
+config PHY_ST_SPEAR1340_MIPHY
+ tristate "ST SPEAR1340-MIPHY driver"
+ select GENERIC_PHY
+ help
+ Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
+
config PHY_XGENE
tristate "APM X-Gene 15Gbps PHY support"
depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b4f1d5770601..95c69ed5ed45 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,20 +3,28 @@
#
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
+obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
+obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o
obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
+obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
+obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
index e94f5a6a5645..894fe74c1e44 100644
--- a/drivers/phy/phy-bcm-kona-usb2.c
+++ b/drivers/phy/phy-bcm-kona-usb2.c
@@ -117,7 +117,7 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, phy);
- gphy = devm_phy_create(dev, &ops, NULL);
+ gphy = devm_phy_create(dev, NULL, &ops, NULL);
if (IS_ERR(gphy))
return PTR_ERR(gphy);
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
new file mode 100644
index 000000000000..5c3a0424aeb4
--- /dev/null
+++ b/drivers/phy/phy-berlin-sata.c
@@ -0,0 +1,284 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR 0x0
+#define HOST_VSA_DATA 0x4
+#define PORT_SCR_CTL 0x2c
+#define PORT_VSR_ADDR 0x78
+#define PORT_VSR_DATA 0x7c
+
+#define CONTROL_REGISTER 0x0
+#define MBUS_SIZE_CONTROL 0x4
+
+#define POWER_DOWN_PHY0 BIT(6)
+#define POWER_DOWN_PHY1 BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128 (BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128 (BIT(2) << 19)
+
+#define PHY_BASE 0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25 BIT(0)
+#define PHY_MODE_SATA (0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10 (0x0 << 10)
+#define DATA_BIT_WIDTH_20 (0x1 << 10)
+#define DATA_BIT_WIDTH_40 (0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5 (0x0 << 10)
+#define PHY_GEN_MAX_3_0 (0x1 << 10)
+#define PHY_GEN_MAX_6_0 (0x2 << 10)
+
+struct phy_berlin_desc {
+ struct phy *phy;
+ u32 power_bit;
+ unsigned index;
+};
+
+struct phy_berlin_priv {
+ void __iomem *base;
+ spinlock_t lock;
+ struct clk *clk;
+ struct phy_berlin_desc **phys;
+ unsigned nphys;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
+ u32 mask, u32 val)
+{
+ u32 regval;
+
+ /* select register */
+ writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+
+ /* set bits */
+ regval = readl(ctrl_reg + PORT_VSR_DATA);
+ regval &= ~mask;
+ regval |= val;
+ writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+ struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+ struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+ void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+ int ret = 0;
+ u32 regval;
+
+ clk_prepare_enable(priv->clk);
+
+ spin_lock(&priv->lock);
+
+ /* Power on PHY */
+ writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+ regval = readl(priv->base + HOST_VSA_DATA);
+ regval &= ~desc->power_bit;
+ writel(regval, priv->base + HOST_VSA_DATA);
+
+ /* Configure MBus */
+ writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+ regval = readl(priv->base + HOST_VSA_DATA);
+ regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+ writel(regval, priv->base + HOST_VSA_DATA);
+
+ /* set PHY mode and ref freq to 25 MHz */
+ phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
+ REF_FREF_SEL_25 | PHY_MODE_SATA);
+
+ /* set PHY up to 6 Gbps */
+ phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+
+ /* set 40 bits width */
+ phy_berlin_sata_reg_setbits(ctrl_reg, 0x23, 0xc00, DATA_BIT_WIDTH_40);
+
+ /* use max pll rate */
+ phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+
+ /* set Gen3 controller speed */
+ regval = readl(ctrl_reg + PORT_SCR_CTL);
+ regval &= ~GENMASK(7, 4);
+ regval |= 0x30;
+ writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+ spin_unlock(&priv->lock);
+
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+ struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+ struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+ u32 regval;
+
+ clk_prepare_enable(priv->clk);
+
+ spin_lock(&priv->lock);
+
+ /* Power down PHY */
+ writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+ regval = readl(priv->base + HOST_VSA_DATA);
+ regval |= desc->power_bit;
+ writel(regval, priv->base + HOST_VSA_DATA);
+
+ spin_unlock(&priv->lock);
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+ int i;
+
+ if (WARN_ON(args->args[0] >= priv->nphys))
+ return ERR_PTR(-ENODEV);
+
+ for (i = 0; i < priv->nphys; i++) {
+ if (priv->phys[i]->index == args->args[0])
+ break;
+ }
+
+ if (i == priv->nphys)
+ return ERR_PTR(-ENODEV);
+
+ return priv->phys[i]->phy;
+}
+
+static struct phy_ops phy_berlin_sata_ops = {
+ .power_on = phy_berlin_sata_power_on,
+ .power_off = phy_berlin_sata_power_off,
+ .owner = THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+ POWER_DOWN_PHY0,
+ POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *child;
+ struct phy *phy;
+ struct phy_provider *phy_provider;
+ struct phy_berlin_priv *priv;
+ struct resource *res;
+ int i = 0;
+ u32 phy_id;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ priv->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!priv->base)
+ return -ENOMEM;
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ priv->nphys = of_get_child_count(dev->of_node);
+ if (priv->nphys == 0)
+ return -ENODEV;
+
+ priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+ GFP_KERNEL);
+ if (!priv->phys)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, priv);
+ spin_lock_init(&priv->lock);
+
+ for_each_available_child_of_node(dev->of_node, child) {
+ struct phy_berlin_desc *phy_desc;
+
+ if (of_property_read_u32(child, "reg", &phy_id)) {
+ dev_err(dev, "missing reg property in node %s\n",
+ child->name);
+ return -EINVAL;
+ }
+
+ if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+ dev_err(dev, "invalid reg in node %s\n", child->name);
+ return -EINVAL;
+ }
+
+ phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+ if (!phy_desc)
+ return -ENOMEM;
+
+ phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY %d\n", phy_id);
+ return PTR_ERR(phy);
+ }
+
+ phy_desc->phy = phy;
+ phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+ phy_desc->index = phy_id;
+ phy_set_drvdata(phy, phy_desc);
+
+ priv->phys[i++] = phy_desc;
+
+ /* Make sure the PHY is off */
+ phy_berlin_sata_power_off(phy);
+ }
+
+ phy_provider =
+ devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+ { .compatible = "marvell,berlin2q-sata-phy" },
+ { },
+};
+
+static struct platform_driver phy_berlin_sata_driver = {
+ .probe = phy_berlin_sata_probe,
+ .driver = {
+ .name = "phy-berlin-sata",
+ .owner = THIS_MODULE,
+ .of_match_table = phy_berlin_sata_of_match,
+ },
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 49c446530101..ff5eec5af817 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -21,6 +21,7 @@
#include <linux/phy/phy.h>
#include <linux/idr.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
static struct class *phy_class;
static DEFINE_MUTEX(phy_provider_mutex);
@@ -86,10 +87,15 @@ static struct phy *phy_lookup(struct device *device, const char *port)
static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
{
struct phy_provider *phy_provider;
+ struct device_node *child;
list_for_each_entry(phy_provider, &phy_provider_list, list) {
if (phy_provider->dev->of_node == node)
return phy_provider;
+
+ for_each_child_of_node(phy_provider->dev->of_node, child)
+ if (child == node)
+ return phy_provider;
}
return ERR_PTR(-EPROBE_DEFER);
@@ -226,6 +232,12 @@ int phy_power_on(struct phy *phy)
if (!phy)
return 0;
+ if (phy->pwr) {
+ ret = regulator_enable(phy->pwr);
+ if (ret)
+ return ret;
+ }
+
ret = phy_pm_runtime_get_sync(phy);
if (ret < 0 && ret != -ENOTSUPP)
return ret;
@@ -247,6 +259,8 @@ int phy_power_on(struct phy *phy)
out:
mutex_unlock(&phy->mutex);
phy_pm_runtime_put_sync(phy);
+ if (phy->pwr)
+ regulator_disable(phy->pwr);
return ret;
}
@@ -272,6 +286,9 @@ int phy_power_off(struct phy *phy)
mutex_unlock(&phy->mutex);
phy_pm_runtime_put(phy);
+ if (phy->pwr)
+ regulator_disable(phy->pwr);
+
return 0;
}
EXPORT_SYMBOL_GPL(phy_power_off);
@@ -398,13 +415,20 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
struct phy *phy;
struct class_dev_iter iter;
struct device_node *node = dev->of_node;
+ struct device_node *child;
class_dev_iter_init(&iter, phy_class, NULL, NULL);
while ((dev = class_dev_iter_next(&iter))) {
phy = to_phy(dev);
- if (node != phy->dev.of_node)
+ if (node != phy->dev.of_node) {
+ for_each_child_of_node(node, child) {
+ if (child == phy->dev.of_node)
+ goto phy_found;
+ }
continue;
+ }
+phy_found:
class_dev_iter_exit(&iter);
return phy;
}
@@ -562,13 +586,15 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
/**
* phy_create() - create a new phy
* @dev: device that is creating the new phy
+ * @node: device node of the phy
* @ops: function pointers for performing phy operations
* @init_data: contains the list of PHY consumers or NULL
*
* Called to create a phy using phy framework.
*/
-struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
- struct phy_init_data *init_data)
+struct phy *phy_create(struct device *dev, struct device_node *node,
+ const struct phy_ops *ops,
+ struct phy_init_data *init_data)
{
int ret;
int id;
@@ -588,12 +614,22 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
goto free_phy;
}
+ /* phy-supply */
+ phy->pwr = regulator_get_optional(dev, "phy");
+ if (IS_ERR(phy->pwr)) {
+ if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto free_ida;
+ }
+ phy->pwr = NULL;
+ }
+
device_initialize(&phy->dev);
mutex_init(&phy->mutex);
phy->dev.class = phy_class;
phy->dev.parent = dev;
- phy->dev.of_node = dev->of_node;
+ phy->dev.of_node = node ?: dev->of_node;
phy->id = id;
phy->ops = ops;
phy->init_data = init_data;
@@ -617,6 +653,9 @@ put_dev:
put_device(&phy->dev); /* calls phy_release() which frees resources */
return ERR_PTR(ret);
+free_ida:
+ ida_simple_remove(&phy_ida, phy->id);
+
free_phy:
kfree(phy);
return ERR_PTR(ret);
@@ -626,6 +665,7 @@ EXPORT_SYMBOL_GPL(phy_create);
/**
* devm_phy_create() - create a new phy
* @dev: device that is creating the new phy
+ * @node: device node of the phy
* @ops: function pointers for performing phy operations
* @init_data: contains the list of PHY consumers or NULL
*
@@ -634,8 +674,9 @@ EXPORT_SYMBOL_GPL(phy_create);
* On driver detach, release function is invoked on the devres data,
* then, devres data is freed.
*/
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
- struct phy_init_data *init_data)
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+ const struct phy_ops *ops,
+ struct phy_init_data *init_data)
{
struct phy **ptr, *phy;
@@ -643,7 +684,7 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
if (!ptr)
return ERR_PTR(-ENOMEM);
- phy = phy_create(dev, ops, init_data);
+ phy = phy_create(dev, node, ops, init_data);
if (!IS_ERR(phy)) {
*ptr = phy;
devres_add(dev, ptr);
@@ -800,6 +841,7 @@ static void phy_release(struct device *dev)
phy = to_phy(dev);
dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+ regulator_put(phy->pwr);
ida_simple_remove(&phy_ida, phy->id);
kfree(phy);
}
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 0786fef842e7..8b3026e2af7f 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -76,7 +77,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
if (IS_ERR(state->regs))
return PTR_ERR(state->regs);
- phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
+ phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create Display Port PHY\n");
return PTR_ERR(phy);
@@ -84,10 +85,8 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
phy_set_drvdata(phy, state);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
- return 0;
+ return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id exynos_dp_video_phy_of_match[] = {
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index ff026689358c..b55a92e12496 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -135,7 +136,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
spin_lock_init(&state->slock);
for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
- struct phy *phy = devm_phy_create(dev,
+ struct phy *phy = devm_phy_create(dev, NULL,
&exynos_mipi_video_phy_ops, NULL);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create PHY %d\n", i);
@@ -149,10 +150,8 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev,
exynos_mipi_video_phy_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
- return 0;
+ return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index d92a7cc5698a..0b9de88579b1 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -67,6 +67,8 @@
#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0)
#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0)
+#define EXYNOS_3250_UPHYCLK_REFCLKSEL (0x2 << 8)
+
#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3)
#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4)
#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7)
@@ -86,13 +88,23 @@
#define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1)
#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
#define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0 BIT(5)
-#define EXYNOS_4x12_URSTCON_HSIC1 BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC0 BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(10)
#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(8)
/* Isolation, configured in the power management unit */
#define EXYNOS_4x12_USB_ISOL_OFFSET 0x704
@@ -187,7 +199,12 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+
+ if (drv->cfg->has_refclk_sel)
+ clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
+
clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+ clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
}
@@ -198,27 +215,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
u32 phypwr = 0;
u32 rst;
u32 pwr;
- u32 mode = 0;
- u32 switch_mode = 0;
switch (inst->cfg->id) {
case EXYNOS4x12_DEVICE:
phypwr = EXYNOS_4x12_UPHYPWR_PHY0;
rstbits = EXYNOS_4x12_URSTCON_PHY0;
- mode = EXYNOS_4x12_MODE_SWITCH_DEVICE;
- switch_mode = 1;
break;
case EXYNOS4x12_HOST:
phypwr = EXYNOS_4x12_UPHYPWR_PHY1;
- rstbits = EXYNOS_4x12_URSTCON_HOST_PHY;
- mode = EXYNOS_4x12_MODE_SWITCH_HOST;
- switch_mode = 1;
+ rstbits = EXYNOS_4x12_URSTCON_HOST_PHY |
+ EXYNOS_4x12_URSTCON_PHY1 |
+ EXYNOS_4x12_URSTCON_HOST_LINK_P0;
break;
case EXYNOS4x12_HSIC0:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
- rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
- EXYNOS_4x12_URSTCON_HOST_PHY;
+ rstbits = EXYNOS_4x12_URSTCON_HSIC0 |
+ EXYNOS_4x12_URSTCON_HOST_LINK_P1;
break;
case EXYNOS4x12_HSIC1:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
@@ -228,11 +240,6 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
};
if (on) {
- if (switch_mode)
- regmap_update_bits(drv->reg_sys,
- EXYNOS_4x12_MODE_SWITCH_OFFSET,
- EXYNOS_4x12_MODE_SWITCH_MASK, mode);
-
pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
pwr &= ~phypwr;
writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
@@ -253,41 +260,78 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
}
}
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
{
- struct samsung_usb2_phy_driver *drv = inst->drv;
+ if (inst->int_cnt++ > 0)
+ return;
- inst->enabled = 1;
exynos4x12_setup_clk(inst);
- exynos4x12_phy_pwr(inst, 1);
exynos4x12_isol(inst, 0);
+ exynos4x12_phy_pwr(inst, 1);
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+
+ if (inst->ext_cnt++ > 0)
+ return 0;
- /* Power on the device, as it is necessary for HSIC to work */
- if (inst->cfg->id == EXYNOS4x12_HSIC0) {
- struct samsung_usb2_phy_instance *device =
- &drv->instances[EXYNOS4x12_DEVICE];
- exynos4x12_phy_pwr(device, 1);
- exynos4x12_isol(device, 0);
+ if (inst->cfg->id == EXYNOS4x12_HOST) {
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_HOST);
+ exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
}
+ if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_DEVICE);
+
+ if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+ exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
+ }
+
+ exynos4x12_power_on_int(inst);
+
return 0;
}
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- struct samsung_usb2_phy_instance *device =
- &drv->instances[EXYNOS4x12_DEVICE];
+ if (inst->int_cnt-- > 1)
+ return;
- inst->enabled = 0;
exynos4x12_isol(inst, 1);
exynos4x12_phy_pwr(inst, 0);
+}
+
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+
+ if (inst->ext_cnt-- > 1)
+ return 0;
+
+ if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
+ regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK,
+ EXYNOS_4x12_MODE_SWITCH_HOST);
+
+ if (inst->cfg->id == EXYNOS4x12_HOST)
+ exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
- if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
- exynos4x12_isol(device, 1);
- exynos4x12_phy_pwr(device, 0);
+ if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+ exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
}
+ exynos4x12_power_off_int(inst);
+
return 0;
}
@@ -320,6 +364,13 @@ static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
{},
};
+const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
+ .has_refclk_sel = 1,
+ .num_phys = 1,
+ .phys = exynos4x12_phys,
+ .rate_to_clk = exynos4x12_rate_to_clk,
+};
+
const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
.has_mode_switch = 1,
.num_phys = EXYNOS4x12_NUM_PHYS,
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 76d862b2202f..b05302b09c9f 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -506,7 +506,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
.owner = THIS_MODULE,
};
-const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
{
.id = EXYNOS5_DRDPHY_UTMI,
.phy_isol = exynos5_usbdrd_phy_isol,
@@ -521,13 +521,13 @@ const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
},
};
-const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
.pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
};
-const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
};
@@ -635,7 +635,8 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
dev_vdbg(dev, "Creating usbdrd_phy phy\n");
for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
- struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops,
+ struct phy *phy = devm_phy_create(dev, NULL,
+ &exynos5_usbdrd_phy_ops,
NULL);
if (IS_ERR(phy)) {
dev_err(dev, "Failed to create usbdrd_phy phy\n");
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index 05689450f93b..19a679aca4ac 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/phy-exynos5250-sata.c
@@ -210,7 +210,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
return ret;
}
- sata_phy->phy = devm_phy_create(dev, &exynos_sata_phy_ops, NULL);
+ sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
if (IS_ERR(sata_phy->phy)) {
clk_disable_unprepare(sata_phy->phyclk);
dev_err(dev, "failed to create PHY\n");
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c
index 94179afda951..1c139aa0d074 100644
--- a/drivers/phy/phy-exynos5250-usb2.c
+++ b/drivers/phy/phy-exynos5250-usb2.c
@@ -318,7 +318,6 @@ static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
break;
}
- inst->enabled = 1;
exynos5250_isol(inst, 0);
return 0;
@@ -331,7 +330,6 @@ static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
u32 otg;
u32 hsic;
- inst->enabled = 0;
exynos5250_isol(inst, 1);
switch (inst->cfg->id) {
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
new file mode 100644
index 000000000000..6a08fa5f81eb
--- /dev/null
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014 Linaro Ltd.
+ * Copyright (c) 2014 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SATA_PHY0_CTLL 0xa0
+#define MPLL_MULTIPLIER_SHIFT 1
+#define MPLL_MULTIPLIER_MASK 0xfe
+#define MPLL_MULTIPLIER_50M 0x3c
+#define MPLL_MULTIPLIER_100M 0x1e
+#define PHY_RESET BIT(0)
+#define REF_SSP_EN BIT(9)
+#define SSC_EN BIT(10)
+#define REF_USE_PAD BIT(23)
+
+#define SATA_PORT_PHYCTL 0x174
+#define SPEED_MODE_MASK 0x6f0000
+#define HALF_RATE_SHIFT 16
+#define PHY_CONFIG_SHIFT 18
+#define GEN2_EN_SHIFT 21
+#define SPEED_CTRL BIT(20)
+
+#define SATA_PORT_PHYCTL1 0x148
+#define AMPLITUDE_MASK 0x3ffffe
+#define AMPLITUDE_GEN3 0x68
+#define AMPLITUDE_GEN3_SHIFT 15
+#define AMPLITUDE_GEN2 0x56
+#define AMPLITUDE_GEN2_SHIFT 8
+#define AMPLITUDE_GEN1 0x56
+#define AMPLITUDE_GEN1_SHIFT 1
+
+#define SATA_PORT_PHYCTL2 0x14c
+#define PREEMPH_MASK 0x3ffff
+#define PREEMPH_GEN3 0x20
+#define PREEMPH_GEN3_SHIFT 12
+#define PREEMPH_GEN2 0x15
+#define PREEMPH_GEN2_SHIFT 6
+#define PREEMPH_GEN1 0x5
+#define PREEMPH_GEN1_SHIFT 0
+
+struct hix5hd2_priv {
+ void __iomem *base;
+ struct regmap *peri_ctrl;
+};
+
+enum phy_speed_mode {
+ SPEED_MODE_GEN1 = 0,
+ SPEED_MODE_GEN2 = 1,
+ SPEED_MODE_GEN3 = 2,
+};
+
+static int hix5hd2_sata_phy_init(struct phy *phy)
+{
+ struct hix5hd2_priv *priv = phy_get_drvdata(phy);
+ u32 val, data[2];
+ int ret;
+
+ if (priv->peri_ctrl) {
+ ret = of_property_read_u32_array(phy->dev.of_node,
+ "hisilicon,power-reg",
+ &data[0], 2);
+ if (ret) {
+ dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
+ return ret;
+ }
+
+ regmap_update_bits(priv->peri_ctrl, data[0],
+ BIT(data[1]), BIT(data[1]));
+ }
+
+ /* reset phy */
+ val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
+ val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
+ val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
+ REF_SSP_EN | PHY_RESET;
+ writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+ msleep(20);
+ val &= ~PHY_RESET;
+ writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+
+ val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
+ val &= ~AMPLITUDE_MASK;
+ val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
+ AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
+ AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
+ writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
+
+ val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
+ val &= ~PREEMPH_MASK;
+ val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
+ PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
+ PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
+ writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
+
+ /* ensure PHYCTRL setting takes effect */
+ val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
+ val &= ~SPEED_MODE_MASK;
+ val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
+ SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
+ SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
+ writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+ msleep(20);
+ val &= ~SPEED_MODE_MASK;
+ val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
+ SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
+ SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
+ writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+ val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
+ val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
+ SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
+ SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
+ writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+ return 0;
+}
+
+static struct phy_ops hix5hd2_sata_phy_ops = {
+ .init = hix5hd2_sata_phy_init,
+ .owner = THIS_MODULE,
+};
+
+static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct phy *phy;
+ struct hix5hd2_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!priv->base)
+ return -ENOMEM;
+
+ priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "hisilicon,peripheral-syscon");
+ if (IS_ERR(priv->peri_ctrl))
+ priv->peri_ctrl = NULL;
+
+ phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy, priv);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
+ {.compatible = "hisilicon,hix5hd2-sata-phy",},
+ { },
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
+
+static struct platform_driver hix5hd2_sata_phy_driver = {
+ .probe = hix5hd2_sata_phy_probe,
+ .driver = {
+ .name = "hix5hd2-sata-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = hix5hd2_sata_phy_of_match,
+ }
+};
+module_platform_driver(hix5hd2_sata_phy_driver);
+
+MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
+MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
+MODULE_ALIAS("platform:hix5hd2-sata-phy");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
new file mode 100644
index 000000000000..e111baf187ce
--- /dev/null
+++ b/drivers/phy/phy-miphy365x.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics – All Rights Reserved
+ *
+ * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
+ *
+ * Authors: Alexandre Torgue <alexandre.torgue@st.com>
+ * Lee Jones <lee.jones@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.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+#define HFC_TIMEOUT 100
+
+#define SYSCFG_SELECT_SATA_MASK BIT(1)
+#define SYSCFG_SELECT_SATA_POS 1
+
+/* MiPHY365x register definitions */
+#define RESET_REG 0x00
+#define RST_PLL BIT(1)
+#define RST_PLL_CAL BIT(2)
+#define RST_RX BIT(4)
+#define RST_MACRO BIT(7)
+
+#define STATUS_REG 0x01
+#define IDLL_RDY BIT(0)
+#define PLL_RDY BIT(1)
+#define DES_BIT_LOCK BIT(2)
+#define DES_SYMBOL_LOCK BIT(3)
+
+#define CTRL_REG 0x02
+#define TERM_EN BIT(0)
+#define PCI_EN BIT(2)
+#define DES_BIT_LOCK_EN BIT(3)
+#define TX_POL BIT(5)
+
+#define INT_CTRL_REG 0x03
+
+#define BOUNDARY1_REG 0x10
+#define SPDSEL_SEL BIT(0)
+
+#define BOUNDARY3_REG 0x12
+#define TX_SPDSEL_GEN1_VAL 0
+#define TX_SPDSEL_GEN2_VAL 0x01
+#define TX_SPDSEL_GEN3_VAL 0x02
+#define RX_SPDSEL_GEN1_VAL 0
+#define RX_SPDSEL_GEN2_VAL (0x01 << 3)
+#define RX_SPDSEL_GEN3_VAL (0x02 << 3)
+
+#define PCIE_REG 0x16
+
+#define BUF_SEL_REG 0x20
+#define CONF_GEN_SEL_GEN3 0x02
+#define CONF_GEN_SEL_GEN2 0x01
+#define PD_VDDTFILTER BIT(4)
+
+#define TXBUF1_REG 0x21
+#define SWING_VAL 0x04
+#define SWING_VAL_GEN1 0x03
+#define PREEMPH_VAL (0x3 << 5)
+
+#define TXBUF2_REG 0x22
+#define TXSLEW_VAL 0x2
+#define TXSLEW_VAL_GEN1 0x4
+
+#define RXBUF_OFFSET_CTRL_REG 0x23
+
+#define RXBUF_REG 0x25
+#define SDTHRES_VAL 0x01
+#define EQ_ON3 (0x03 << 4)
+#define EQ_ON1 (0x01 << 4)
+
+#define COMP_CTRL1_REG 0x40
+#define START_COMSR BIT(0)
+#define START_COMZC BIT(1)
+#define COMSR_DONE BIT(2)
+#define COMZC_DONE BIT(3)
+#define COMP_AUTO_LOAD BIT(4)
+
+#define COMP_CTRL2_REG 0x41
+#define COMP_2MHZ_RAT_GEN1 0x1e
+#define COMP_2MHZ_RAT 0xf
+
+#define COMP_CTRL3_REG 0x42
+#define COMSR_COMP_REF 0x33
+
+#define COMP_IDLL_REG 0x47
+#define COMZC_IDLL 0x2a
+
+#define PLL_CTRL1_REG 0x50
+#define PLL_START_CAL BIT(0)
+#define BUF_EN BIT(2)
+#define SYNCHRO_TX BIT(3)
+#define SSC_EN BIT(6)
+#define CONFIG_PLL BIT(7)
+
+#define PLL_CTRL2_REG 0x51
+#define BYPASS_PLL_CAL BIT(1)
+
+#define PLL_RAT_REG 0x52
+
+#define PLL_SSC_STEP_MSB_REG 0x56
+#define PLL_SSC_STEP_MSB_VAL 0x03
+
+#define PLL_SSC_STEP_LSB_REG 0x57
+#define PLL_SSC_STEP_LSB_VAL 0x63
+
+#define PLL_SSC_PER_MSB_REG 0x58
+#define PLL_SSC_PER_MSB_VAL 0
+
+#define PLL_SSC_PER_LSB_REG 0x59
+#define PLL_SSC_PER_LSB_VAL 0xf1
+
+#define IDLL_TEST_REG 0x72
+#define START_CLK_HF BIT(6)
+
+#define DES_BITLOCK_REG 0x86
+#define BIT_LOCK_LEVEL 0x01
+#define BIT_LOCK_CNT_512 (0x03 << 5)
+
+struct miphy365x_phy {
+ struct phy *phy;
+ void __iomem *base;
+ bool pcie_tx_pol_inv;
+ bool sata_tx_pol_inv;
+ u32 sata_gen;
+ u64 ctrlreg;
+ u8 type;
+};
+
+struct miphy365x_dev {
+ struct device *dev;
+ struct regmap *regmap;
+ struct mutex miphy_mutex;
+ struct miphy365x_phy **phys;
+};
+
+/*
+ * These values are represented in Device tree. They are considered to be ABI
+ * and although they can be extended any existing values must not change.
+ */
+enum miphy_sata_gen {
+ SATA_GEN1 = 1,
+ SATA_GEN2,
+ SATA_GEN3
+};
+
+static u8 rx_tx_spd[] = {
+ TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
+ TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
+ TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
+};
+
+/*
+ * This function selects the system configuration,
+ * either two SATA, one SATA and one PCIe, or two PCIe lanes.
+ */
+static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
+
+ return regmap_update_bits(miphy_dev->regmap,
+ (unsigned int)miphy_phy->ctrlreg,
+ SYSCFG_SELECT_SATA_MASK,
+ sata << SYSCFG_SELECT_SATA_POS);
+}
+
+static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ u8 val;
+
+ if (miphy_phy->pcie_tx_pol_inv) {
+ /* Invert Tx polarity and clear pci_txdetect_pol bit */
+ val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
+ writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+ writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
+ }
+
+ return 0;
+}
+
+static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+ u8 mask = IDLL_RDY | PLL_RDY;
+ u8 regval;
+
+ do {
+ regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+ if (!(regval & mask))
+ return 0;
+
+ usleep_range(2000, 2500);
+ } while (time_before(jiffies, timeout));
+
+ dev_err(miphy_dev->dev, "HFC ready timeout!\n");
+ return -EBUSY;
+}
+
+static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+ u8 mask = IDLL_RDY | PLL_RDY;
+ u8 regval;
+
+ do {
+ regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+ if ((regval & mask) == mask)
+ return 0;
+
+ usleep_range(2000, 2500);
+ } while (time_before(jiffies, timeout));
+
+ dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
+ return -EBUSY;
+}
+
+static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ u8 val, mask;
+
+ if (miphy_phy->sata_gen == SATA_GEN1)
+ writeb_relaxed(COMP_2MHZ_RAT_GEN1,
+ miphy_phy->base + COMP_CTRL2_REG);
+ else
+ writeb_relaxed(COMP_2MHZ_RAT,
+ miphy_phy->base + COMP_CTRL2_REG);
+
+ if (miphy_phy->sata_gen != SATA_GEN3) {
+ writeb_relaxed(COMSR_COMP_REF,
+ miphy_phy->base + COMP_CTRL3_REG);
+ /*
+ * Force VCO current to value defined by address 0x5A
+ * and disable PCIe100Mref bit
+ * Enable auto load compensation for pll_i_bias
+ */
+ writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
+ writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
+ }
+
+ /*
+ * Force restart compensation and enable auto load
+ * for Comzc_Tx, Comzc_Rx and Comsr on macro
+ */
+ val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
+ writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
+
+ mask = COMSR_DONE | COMZC_DONE;
+ while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask) != mask)
+ cpu_relax();
+}
+
+static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ u8 val;
+
+ /*
+ * SSC Settings. SSC will be enabled through Link
+ * SSC Ampl. = 0.4%
+ * SSC Freq = 31KHz
+ */
+ writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
+ miphy_phy->base + PLL_SSC_STEP_MSB_REG);
+ writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
+ miphy_phy->base + PLL_SSC_STEP_LSB_REG);
+ writeb_relaxed(PLL_SSC_PER_MSB_VAL,
+ miphy_phy->base + PLL_SSC_PER_MSB_REG);
+ writeb_relaxed(PLL_SSC_PER_LSB_VAL,
+ miphy_phy->base + PLL_SSC_PER_LSB_REG);
+
+ /* SSC Settings complete */
+ if (miphy_phy->sata_gen == SATA_GEN1) {
+ val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+ writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+ } else {
+ val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+ writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+ }
+}
+
+static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
+ struct miphy365x_dev *miphy_dev)
+{
+ int ret;
+ u8 val;
+
+ /*
+ * Force PHY macro reset, PLL calibration reset, PLL reset
+ * and assert Deserializer Reset
+ */
+ val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
+ writeb_relaxed(val, miphy_phy->base + RESET_REG);
+
+ if (miphy_phy->sata_tx_pol_inv)
+ writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
+
+ /*
+ * Force macro1 to use rx_lspd, tx_lspd
+ * Force Rx_Clock on first I-DLL phase
+ * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
+ */
+ writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
+ writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
+ val = rx_tx_spd[miphy_phy->sata_gen];
+ writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
+
+ /* Wait for HFC_READY = 0 */
+ ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
+ if (ret)
+ return ret;
+
+ /* Compensation Recalibration */
+ miphy365x_set_comp(miphy_phy, miphy_dev);
+
+ switch (miphy_phy->sata_gen) {
+ case SATA_GEN3:
+ /*
+ * TX Swing target 550-600mv peak to peak diff
+ * Tx Slew target 90-110ps rising/falling time
+ * Rx Eq ON3, Sigdet threshold SDTH1
+ */
+ val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
+ writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
+ val = SWING_VAL | PREEMPH_VAL;
+ writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
+ writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+ writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
+ val = SDTHRES_VAL | EQ_ON3;
+ writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+ break;
+ case SATA_GEN2:
+ /*
+ * conf gen sel=0x1 to program Gen2 banked registers
+ * VDDT filter ON
+ * Tx Swing target 550-600mV peak-to-peak diff
+ * Tx Slew target 90-110 ps rising/falling time
+ * RX Equalization ON1, Sigdet threshold SDTH1
+ */
+ writeb_relaxed(CONF_GEN_SEL_GEN2,
+ miphy_phy->base + BUF_SEL_REG);
+ writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
+ writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+ val = SDTHRES_VAL | EQ_ON1;
+ writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+ break;
+ case SATA_GEN1:
+ /*
+ * conf gen sel = 00b to program Gen1 banked registers
+ * VDDT filter ON
+ * Tx Swing target 500-550mV peak-to-peak diff
+ * Tx Slew target120-140 ps rising/falling time
+ */
+ writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
+ writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
+ writeb_relaxed(TXSLEW_VAL_GEN1, miphy_phy->base + TXBUF2_REG);
+ break;
+ default:
+ break;
+ }
+
+ /* Force Macro1 in partial mode & release pll cal reset */
+ writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+ usleep_range(100, 150);
+
+ miphy365x_set_ssc(miphy_phy, miphy_dev);
+
+ /* Wait for phy_ready */
+ ret = miphy365x_rdy(miphy_phy, miphy_dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable macro1 to use rx_lspd & tx_lspd
+ * Release Rx_Clock on first I-DLL phase on macro1
+ * Assert deserializer reset
+ * des_bit_lock_en is set
+ * bit lock detection strength
+ * Deassert deserializer reset
+ */
+ writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
+ writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
+ writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+ val = miphy_phy->sata_tx_pol_inv ?
+ (TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
+ writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+
+ val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
+ writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
+ writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
+
+ return 0;
+}
+
+static int miphy365x_init(struct phy *phy)
+{
+ struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
+ struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
+ int ret = 0;
+
+ mutex_lock(&miphy_dev->miphy_mutex);
+
+ ret = miphy365x_set_path(miphy_phy, miphy_dev);
+ if (ret) {
+ mutex_unlock(&miphy_dev->miphy_mutex);
+ return ret;
+ }
+
+ /* Initialise Miphy for PCIe or SATA */
+ if (miphy_phy->type == MIPHY_TYPE_PCIE)
+ ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
+ else
+ ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
+
+ mutex_unlock(&miphy_dev->miphy_mutex);
+
+ return ret;
+}
+
+int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
+ int index)
+{
+ struct device_node *phynode = miphy_phy->phy->dev.of_node;
+ const char *name;
+ const __be32 *taddr;
+ int type = miphy_phy->type;
+ int ret;
+
+ ret = of_property_read_string_index(phynode, "reg-names", index, &name);
+ if (ret) {
+ dev_err(dev, "no reg-names property not found\n");
+ return ret;
+ }
+
+ if (!strncmp(name, "syscfg", 6)) {
+ taddr = of_get_address(phynode, index, NULL, NULL);
+ if (!taddr) {
+ dev_err(dev, "failed to fetch syscfg address\n");
+ return -EINVAL;
+ }
+
+ miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
+ if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
+ dev_err(dev, "failed to translate syscfg address\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
+ (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
+ return 0;
+
+ miphy_phy->base = of_iomap(phynode, index);
+ if (!miphy_phy->base) {
+ dev_err(dev, "Failed to map %s\n", phynode->full_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct phy *miphy365x_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
+ struct miphy365x_phy *miphy_phy = NULL;
+ struct device_node *phynode = args->np;
+ int ret, index;
+
+ if (!of_device_is_available(phynode)) {
+ dev_warn(dev, "Requested PHY is disabled\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ if (args->args_count != 1) {
+ dev_err(dev, "Invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (index = 0; index < of_get_child_count(dev->of_node); index++)
+ if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
+ miphy_phy = miphy_dev->phys[index];
+ break;
+ }
+
+ if (!miphy_phy) {
+ dev_err(dev, "Failed to find appropriate phy\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ miphy_phy->type = args->args[0];
+
+ if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
+ miphy_phy->type == MIPHY_TYPE_PCIE)) {
+ dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Each port handles SATA and PCIE - third entry is always sysconf. */
+ for (index = 0; index < 3; index++) {
+ ret = miphy365x_get_addr(dev, miphy_phy, index);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ }
+
+ return miphy_phy->phy;
+}
+
+static struct phy_ops miphy365x_ops = {
+ .init = miphy365x_init,
+ .owner = THIS_MODULE,
+};
+
+static int miphy365x_of_probe(struct device_node *phynode,
+ struct miphy365x_phy *miphy_phy)
+{
+ of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
+ if (!miphy_phy->sata_gen)
+ miphy_phy->sata_gen = SATA_GEN1;
+
+ miphy_phy->pcie_tx_pol_inv =
+ of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
+
+ miphy_phy->sata_tx_pol_inv =
+ of_property_read_bool(phynode, "st,sata-tx-pol-inv");
+
+ return 0;
+}
+
+static int miphy365x_probe(struct platform_device *pdev)
+{
+ struct device_node *child, *np = pdev->dev.of_node;
+ struct miphy365x_dev *miphy_dev;
+ struct phy_provider *provider;
+ struct phy *phy;
+ int chancount, port = 0;
+ int ret;
+
+ miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+ if (!miphy_dev)
+ return -ENOMEM;
+
+ chancount = of_get_child_count(np);
+ miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
+ GFP_KERNEL);
+ if (!miphy_dev->phys)
+ return -ENOMEM;
+
+ miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(miphy_dev->regmap)) {
+ dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
+ return PTR_ERR(miphy_dev->regmap);
+ }
+
+ miphy_dev->dev = &pdev->dev;
+
+ dev_set_drvdata(&pdev->dev, miphy_dev);
+
+ mutex_init(&miphy_dev->miphy_mutex);
+
+ for_each_child_of_node(np, child) {
+ struct miphy365x_phy *miphy_phy;
+
+ miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+ GFP_KERNEL);
+ if (!miphy_phy)
+ return -ENOMEM;
+
+ miphy_dev->phys[port] = miphy_phy;
+
+ phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ miphy_dev->phys[port]->phy = phy;
+
+ ret = miphy365x_of_probe(child, miphy_phy);
+ if (ret)
+ return ret;
+
+ phy_set_drvdata(phy, miphy_dev->phys[port]);
+ port++;
+ }
+
+ provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
+ if (IS_ERR(provider))
+ return PTR_ERR(provider);
+
+ return 0;
+}
+
+static const struct of_device_id miphy365x_of_match[] = {
+ { .compatible = "st,miphy365x-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, miphy365x_of_match);
+
+static struct platform_driver miphy365x_driver = {
+ .probe = miphy365x_probe,
+ .driver = {
+ .name = "miphy365x-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = miphy365x_of_match,
+ }
+};
+module_platform_driver(miphy365x_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index d70ecd6a1b3f..cc3c0e166daf 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -99,7 +99,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
- phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
+ phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
if (IS_ERR(phy))
return PTR_ERR(phy);
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 311b4f9a5132..9487bf112267 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -27,6 +27,41 @@
#include <linux/phy/omap_control_phy.h>
/**
+ * omap_control_pcie_pcs - set the PCS delay count
+ * @dev: the control module device
+ * @id: index of the pcie PHY (should be 1 or 2)
+ * @delay: 8 bit delay value
+ */
+void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
+{
+ u32 val;
+ struct omap_control_phy *control_phy;
+
+ if (IS_ERR(dev) || !dev) {
+ pr_err("%s: invalid device\n", __func__);
+ return;
+ }
+
+ control_phy = dev_get_drvdata(dev);
+ if (!control_phy) {
+ dev_err(dev, "%s: invalid control phy device\n", __func__);
+ return;
+ }
+
+ if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
+ dev_err(dev, "%s: unsupported operation\n", __func__);
+ return;
+ }
+
+ val = readl(control_phy->pcie_pcs);
+ val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
+ (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
+ val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+ writel(val, control_phy->pcie_pcs);
+}
+EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
+
+/**
* omap_control_phy_power - power on/off the phy using control module reg
* @dev: the control module device
* @on: 0 or 1, based on powering on or off the PHY
@@ -61,6 +96,7 @@ void omap_control_phy_power(struct device *dev, int on)
val |= OMAP_CTRL_DEV_PHY_PD;
break;
+ case OMAP_CTRL_TYPE_PCIE:
case OMAP_CTRL_TYPE_PIPE3:
rate = clk_get_rate(control_phy->sys_clk);
rate = rate/1000000;
@@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
@@ -228,6 +265,10 @@ static const struct of_device_id omap_control_phy_id_table[] = {
.data = &pipe3_data,
},
{
+ .compatible = "ti,control-phy-pcie",
+ .data = &pcie_data,
+ },
+ {
.compatible = "ti,control-phy-usb2-dra7",
.data = &dra7usb2_data,
},
@@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct platform_device *pdev)
}
}
- if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) {
+ if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
+ control_phy->type == OMAP_CTRL_TYPE_PCIE) {
control_phy->sys_clk = devm_clk_get(control_phy->dev,
"sys_clkin");
if (IS_ERR(control_phy->sys_clk)) {
@@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct platform_device *pdev)
}
}
+ if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "pcie_pcs");
+ control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_phy->pcie_pcs))
+ return PTR_ERR(control_phy->pcie_pcs);
+ }
+
dev_set_drvdata(control_phy->dev, control_phy);
return 0;
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 34b396146c8a..93d78359246c 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -263,7 +263,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, phy);
- generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+ generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
new file mode 100644
index 000000000000..b3ef7d805765
--- /dev/null
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* PHY registers */
+#define UNIPHY_PLL_REFCLK_CFG 0x000
+#define UNIPHY_PLL_PWRGEN_CFG 0x014
+#define UNIPHY_PLL_GLB_CFG 0x020
+#define UNIPHY_PLL_SDM_CFG0 0x038
+#define UNIPHY_PLL_SDM_CFG1 0x03C
+#define UNIPHY_PLL_SDM_CFG2 0x040
+#define UNIPHY_PLL_SDM_CFG3 0x044
+#define UNIPHY_PLL_SDM_CFG4 0x048
+#define UNIPHY_PLL_SSC_CFG0 0x04C
+#define UNIPHY_PLL_SSC_CFG1 0x050
+#define UNIPHY_PLL_SSC_CFG2 0x054
+#define UNIPHY_PLL_SSC_CFG3 0x058
+#define UNIPHY_PLL_LKDET_CFG0 0x05C
+#define UNIPHY_PLL_LKDET_CFG1 0x060
+#define UNIPHY_PLL_LKDET_CFG2 0x064
+#define UNIPHY_PLL_CAL_CFG0 0x06C
+#define UNIPHY_PLL_CAL_CFG8 0x08C
+#define UNIPHY_PLL_CAL_CFG9 0x090
+#define UNIPHY_PLL_CAL_CFG10 0x094
+#define UNIPHY_PLL_CAL_CFG11 0x098
+#define UNIPHY_PLL_STATUS 0x0C0
+
+#define SATA_PHY_SER_CTRL 0x100
+#define SATA_PHY_TX_DRIV_CTRL0 0x104
+#define SATA_PHY_TX_DRIV_CTRL1 0x108
+#define SATA_PHY_TX_IMCAL0 0x11C
+#define SATA_PHY_TX_IMCAL2 0x124
+#define SATA_PHY_RX_IMCAL0 0x128
+#define SATA_PHY_EQUAL 0x13C
+#define SATA_PHY_OOB_TERM 0x144
+#define SATA_PHY_CDR_CTRL0 0x148
+#define SATA_PHY_CDR_CTRL1 0x14C
+#define SATA_PHY_CDR_CTRL2 0x150
+#define SATA_PHY_CDR_CTRL3 0x154
+#define SATA_PHY_PI_CTRL0 0x168
+#define SATA_PHY_POW_DWN_CTRL0 0x180
+#define SATA_PHY_POW_DWN_CTRL1 0x184
+#define SATA_PHY_TX_DATA_CTRL 0x188
+#define SATA_PHY_ALIGNP 0x1A4
+#define SATA_PHY_TX_IMCAL_STAT 0x1E4
+#define SATA_PHY_RX_IMCAL_STAT 0x1E8
+
+#define UNIPHY_PLL_LOCK BIT(0)
+#define SATA_PHY_TX_CAL BIT(0)
+#define SATA_PHY_RX_CAL BIT(0)
+
+/* default timeout set to 1 sec */
+#define TIMEOUT_MS 10000
+#define DELAY_INTERVAL_US 100
+
+struct qcom_apq8064_sata_phy {
+ void __iomem *mmio;
+ struct clk *cfg_clk;
+ struct device *dev;
+};
+
+/* Helper function to do poll and timeout */
+static int read_poll_timeout(void __iomem *addr, u32 mask)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+ do {
+ if (readl_relaxed(addr) & mask)
+ return 0;
+
+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+ } while (!time_after(jiffies, timeout));
+
+ return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
+}
+
+static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
+{
+ struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+ void __iomem *base = phy->mmio;
+ int ret = 0;
+
+ /* SATA phy initialization */
+ writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
+ writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
+ /* Make sure the power down happens before power up */
+ mb();
+ usleep_range(10, 60);
+
+ writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+ writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+ writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+ writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+ writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
+
+ /* Write UNIPHYPLL registers to configure PLL */
+ writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
+ writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
+
+ writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
+ writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
+ writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
+ writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
+ writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
+
+ writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
+ writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
+ writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
+ writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
+ writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
+
+ writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
+ writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
+ writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
+ writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
+
+ writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
+ writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
+
+ writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
+ /* make sure global config LDO power down happens before power up */
+ mb();
+
+ writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
+ writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
+
+ /* PLL Lock wait */
+ ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
+ if (ret) {
+ dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
+ return ret;
+ }
+
+ /* TX Calibration */
+ ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
+ if (ret) {
+ dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
+ return ret;
+ }
+
+ /* RX Calibration */
+ ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
+ if (ret) {
+ dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
+ return ret;
+ }
+
+ /* SATA phy calibrated succesfully, power up to functional mode */
+ writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+ writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+ writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+
+ writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
+ writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
+ writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
+ writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
+ writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
+ writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
+ writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+
+ writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
+ writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
+ writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
+
+ writel_relaxed(0x01, base + SATA_PHY_EQUAL);
+ writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
+ writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
+
+ return 0;
+}
+
+static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
+{
+ struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+ void __iomem *base = phy->mmio;
+
+ /* Power down PHY */
+ writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
+ writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
+
+ /* Power down PLL block */
+ writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
+
+ return 0;
+}
+
+static struct phy_ops qcom_apq8064_sata_phy_ops = {
+ .init = qcom_apq8064_sata_phy_init,
+ .exit = qcom_apq8064_sata_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
+{
+ struct qcom_apq8064_sata_phy *phy;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct phy_provider *phy_provider;
+ struct phy *generic_phy;
+ int ret;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ phy->mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(phy->mmio))
+ return PTR_ERR(phy->mmio);
+
+ generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
+ NULL);
+ if (IS_ERR(generic_phy)) {
+ dev_err(dev, "%s: failed to create phy\n", __func__);
+ return PTR_ERR(generic_phy);
+ }
+
+ phy->dev = dev;
+ phy_set_drvdata(generic_phy, phy);
+ platform_set_drvdata(pdev, phy);
+
+ phy->cfg_clk = devm_clk_get(dev, "cfg");
+ if (IS_ERR(phy->cfg_clk)) {
+ dev_err(dev, "Failed to get sata cfg clock\n");
+ return PTR_ERR(phy->cfg_clk);
+ }
+
+ ret = clk_prepare_enable(phy->cfg_clk);
+ if (ret)
+ return ret;
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ clk_disable_unprepare(phy->cfg_clk);
+ dev_err(dev, "%s: failed to register phy\n", __func__);
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
+{
+ struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(phy->cfg_clk);
+
+ return 0;
+}
+
+static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
+ { .compatible = "qcom,apq8064-sata-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
+
+static struct platform_driver qcom_apq8064_sata_phy_driver = {
+ .probe = qcom_apq8064_sata_phy_probe,
+ .remove = qcom_apq8064_sata_phy_remove,
+ .driver = {
+ .name = "qcom-apq8064-sata-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = qcom_apq8064_sata_phy_of_match,
+ }
+};
+module_platform_driver(qcom_apq8064_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
new file mode 100644
index 000000000000..909b5a87fc6a
--- /dev/null
+++ b/drivers/phy/phy-qcom-ipq806x-sata.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+struct qcom_ipq806x_sata_phy {
+ void __iomem *mmio;
+ struct clk *cfg_clk;
+ struct device *dev;
+};
+
+#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b))
+
+#define SATA_PHY_P0_PARAM0 0x200
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x) __set(x, 17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK GENMASK(17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x) __set(x, 11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK GENMASK(11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x) __set(x, 5, 0)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK GENMASK(5, 0)
+
+#define SATA_PHY_P0_PARAM1 0x204
+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x) __set(x, 31, 21)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x) __set(x, 20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK GENMASK(20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x) __set(x, 13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK GENMASK(13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x) __set(x, 6, 0)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK GENMASK(6, 0)
+
+#define SATA_PHY_P0_PARAM2 0x208
+#define SATA_PHY_P0_PARAM2_RX_EQ(x) __set(x, 20, 18)
+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK GENMASK(20, 18)
+
+#define SATA_PHY_P0_PARAM3 0x20C
+#define SATA_PHY_SSC_EN 0x8
+#define SATA_PHY_P0_PARAM4 0x210
+#define SATA_PHY_REF_SSP_EN 0x2
+#define SATA_PHY_RESET 0x1
+
+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
+{
+ struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+ u32 reg;
+
+ /* Setting SSC_EN to 1 */
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
+ reg = reg | SATA_PHY_SSC_EN;
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
+
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
+ ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
+ SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
+ SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
+ reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
+
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
+ ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
+ reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
+
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
+ ~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
+ reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
+
+ /* Setting PHY_RESET to 1 */
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+ reg = reg | SATA_PHY_RESET;
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+ /* Setting REF_SSP_EN to 1 */
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+ reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+ /* make sure all changes complete before we let the PHY out of reset */
+ mb();
+
+ /* sleep for max. 50us more to combine processor wakeups */
+ usleep_range(20, 20 + 50);
+
+ /* Clearing PHY_RESET to 0 */
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+ reg = reg & ~SATA_PHY_RESET;
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+ return 0;
+}
+
+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
+{
+ struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+ u32 reg;
+
+ /* Setting PHY_RESET to 1 */
+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+ reg = reg | SATA_PHY_RESET;
+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+ return 0;
+}
+
+static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+ .init = qcom_ipq806x_sata_phy_init,
+ .exit = qcom_ipq806x_sata_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
+{
+ struct qcom_ipq806x_sata_phy *phy;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct phy_provider *phy_provider;
+ struct phy *generic_phy;
+ int ret;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ phy->mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(phy->mmio))
+ return PTR_ERR(phy->mmio);
+
+ generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
+ NULL);
+ if (IS_ERR(generic_phy)) {
+ dev_err(dev, "%s: failed to create phy\n", __func__);
+ return PTR_ERR(generic_phy);
+ }
+
+ phy->dev = dev;
+ phy_set_drvdata(generic_phy, phy);
+ platform_set_drvdata(pdev, phy);
+
+ phy->cfg_clk = devm_clk_get(dev, "cfg");
+ if (IS_ERR(phy->cfg_clk)) {
+ dev_err(dev, "Failed to get sata cfg clock\n");
+ return PTR_ERR(phy->cfg_clk);
+ }
+
+ ret = clk_prepare_enable(phy->cfg_clk);
+ if (ret)
+ return ret;
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ clk_disable_unprepare(phy->cfg_clk);
+ dev_err(dev, "%s: failed to register phy\n", __func__);
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
+{
+ struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(phy->cfg_clk);
+
+ return 0;
+}
+
+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
+ { .compatible = "qcom,ipq806x-sata-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
+
+static struct platform_driver qcom_ipq806x_sata_phy_driver = {
+ .probe = qcom_ipq806x_sata_phy_probe,
+ .remove = qcom_ipq806x_sata_phy_remove,
+ .driver = {
+ .name = "qcom-ipq806x-sata-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = qcom_ipq806x_sata_phy_of_match,
+ }
+};
+module_platform_driver(qcom_ipq806x_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c
new file mode 100644
index 000000000000..004d320767e4
--- /dev/null
+++ b/drivers/phy/phy-s5pv210-usb2.c
@@ -0,0 +1,187 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Kamil Debski <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define S5PV210_UPHYPWR 0x0
+
+#define S5PV210_UPHYPWR_PHY0_SUSPEND BIT(0)
+#define S5PV210_UPHYPWR_PHY0_PWR BIT(3)
+#define S5PV210_UPHYPWR_PHY0_OTG_PWR BIT(4)
+#define S5PV210_UPHYPWR_PHY0 ( \
+ S5PV210_UPHYPWR_PHY0_SUSPEND | \
+ S5PV210_UPHYPWR_PHY0_PWR | \
+ S5PV210_UPHYPWR_PHY0_OTG_PWR)
+
+#define S5PV210_UPHYPWR_PHY1_SUSPEND BIT(6)
+#define S5PV210_UPHYPWR_PHY1_PWR BIT(7)
+#define S5PV210_UPHYPWR_PHY1 ( \
+ S5PV210_UPHYPWR_PHY1_SUSPEND | \
+ S5PV210_UPHYPWR_PHY1_PWR)
+
+/* PHY clock control */
+#define S5PV210_UPHYCLK 0x4
+
+#define S5PV210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
+
+#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
+#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
+#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
+
+/* PHY reset control */
+#define S5PV210_UPHYRST 0x8
+
+#define S5PV210_URSTCON_PHY0 BIT(0)
+#define S5PV210_URSTCON_OTG_HLINK BIT(1)
+#define S5PV210_URSTCON_OTG_PHYLINK BIT(2)
+#define S5PV210_URSTCON_PHY1_ALL BIT(3)
+#define S5PV210_URSTCON_HOST_LINK_ALL BIT(4)
+
+/* Isolation, configured in the power management unit */
+#define S5PV210_USB_ISOL_OFFSET 0x680c
+#define S5PV210_USB_ISOL_DEVICE BIT(0)
+#define S5PV210_USB_ISOL_HOST BIT(1)
+
+
+enum s5pv210_phy_id {
+ S5PV210_DEVICE,
+ S5PV210_HOST,
+ S5PV210_NUM_PHYS,
+};
+
+/*
+ * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ switch (rate) {
+ case 12 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
+ break;
+ case 48 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 mask;
+
+ switch (inst->cfg->id) {
+ case S5PV210_DEVICE:
+ mask = S5PV210_USB_ISOL_DEVICE;
+ break;
+ case S5PV210_HOST:
+ mask = S5PV210_USB_ISOL_HOST;
+ break;
+ default:
+ return;
+ };
+
+ regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
+ mask, on ? 0 : mask);
+}
+
+static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 rstbits = 0;
+ u32 phypwr = 0;
+ u32 rst;
+ u32 pwr;
+
+ switch (inst->cfg->id) {
+ case S5PV210_DEVICE:
+ phypwr = S5PV210_UPHYPWR_PHY0;
+ rstbits = S5PV210_URSTCON_PHY0;
+ break;
+ case S5PV210_HOST:
+ phypwr = S5PV210_UPHYPWR_PHY1;
+ rstbits = S5PV210_URSTCON_PHY1_ALL |
+ S5PV210_URSTCON_HOST_LINK_ALL;
+ break;
+ };
+
+ if (on) {
+ writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
+
+ pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+ pwr &= ~phypwr;
+ writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+
+ rst = readl(drv->reg_phy + S5PV210_UPHYRST);
+ rst |= rstbits;
+ writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+ udelay(10);
+ rst &= ~rstbits;
+ writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+ } else {
+ pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+ pwr |= phypwr;
+ writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+ }
+}
+
+static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ s5pv210_isol(inst, 0);
+ s5pv210_phy_pwr(inst, 1);
+
+ return 0;
+}
+
+static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ s5pv210_phy_pwr(inst, 0);
+ s5pv210_isol(inst, 1);
+
+ return 0;
+}
+
+static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
+ [S5PV210_DEVICE] = {
+ .label = "device",
+ .id = S5PV210_DEVICE,
+ .power_on = s5pv210_power_on,
+ .power_off = s5pv210_power_off,
+ },
+ [S5PV210_HOST] = {
+ .label = "host",
+ .id = S5PV210_HOST,
+ .power_on = s5pv210_power_on,
+ .power_off = s5pv210_power_off,
+ },
+};
+
+const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
+ .num_phys = ARRAY_SIZE(s5pv210_phys),
+ .phys = s5pv210_phys,
+ .rate_to_clk = s5pv210_rate_to_clk,
+};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 1e69a32c221d..3732ca25e09f 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev,
}
static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+ {
+ .compatible = "samsung,exynos3250-usb2-phy",
+ .data = &exynos3250_usb2_phy_config,
+ },
+#endif
#ifdef CONFIG_PHY_EXYNOS4210_USB2
{
.compatible = "samsung,exynos4210-usb2-phy",
@@ -105,6 +111,12 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = {
.data = &exynos5250_usb2_phy_config,
},
#endif
+#ifdef CONFIG_PHY_S5PV210_USB2
+ {
+ .compatible = "samsung,s5pv210-usb2-phy",
+ .data = &s5pv210_usb2_phy_config,
+ },
+#endif
{ },
};
MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
@@ -190,7 +202,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
struct samsung_usb2_phy_instance *p = &drv->instances[i];
dev_dbg(dev, "Creating phy \"%s\"\n", label);
- p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL);
+ p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
+ NULL);
if (IS_ERR(p->phy)) {
dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
label);
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 45b3170652bd..44bead9b8f34 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance {
const struct samsung_usb2_common_phy *cfg;
struct phy *phy;
struct samsung_usb2_phy_driver *drv;
- bool enabled;
+ int int_cnt;
+ int ext_cnt;
};
struct samsung_usb2_phy_driver {
@@ -59,9 +60,12 @@ struct samsung_usb2_phy_config {
int (*rate_to_clk)(unsigned long, u32 *);
unsigned int num_phys;
bool has_mode_switch;
+ bool has_refclk_sel;
};
+extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
#endif
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c
new file mode 100644
index 000000000000..6dcbfcddb372
--- /dev/null
+++ b/drivers/phy/phy-spear1310-miphy.c
@@ -0,0 +1,274 @@
+/*
+ * ST SPEAr1310-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@st.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/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1310 Registers */
+#define SPEAR1310_PCIE_SATA_CFG 0x3A4
+ #define SPEAR1310_PCIE_SATA2_SEL_PCIE (0 << 31)
+ #define SPEAR1310_PCIE_SATA1_SEL_PCIE (0 << 30)
+ #define SPEAR1310_PCIE_SATA0_SEL_PCIE (0 << 29)
+ #define SPEAR1310_PCIE_SATA2_SEL_SATA BIT(31)
+ #define SPEAR1310_PCIE_SATA1_SEL_SATA BIT(30)
+ #define SPEAR1310_PCIE_SATA0_SEL_SATA BIT(29)
+ #define SPEAR1310_SATA2_CFG_TX_CLK_EN BIT(27)
+ #define SPEAR1310_SATA2_CFG_RX_CLK_EN BIT(26)
+ #define SPEAR1310_SATA2_CFG_POWERUP_RESET BIT(25)
+ #define SPEAR1310_SATA2_CFG_PM_CLK_EN BIT(24)
+ #define SPEAR1310_SATA1_CFG_TX_CLK_EN BIT(23)
+ #define SPEAR1310_SATA1_CFG_RX_CLK_EN BIT(22)
+ #define SPEAR1310_SATA1_CFG_POWERUP_RESET BIT(21)
+ #define SPEAR1310_SATA1_CFG_PM_CLK_EN BIT(20)
+ #define SPEAR1310_SATA0_CFG_TX_CLK_EN BIT(19)
+ #define SPEAR1310_SATA0_CFG_RX_CLK_EN BIT(18)
+ #define SPEAR1310_SATA0_CFG_POWERUP_RESET BIT(17)
+ #define SPEAR1310_SATA0_CFG_PM_CLK_EN BIT(16)
+ #define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT BIT(11)
+ #define SPEAR1310_PCIE2_CFG_POWERUP_RESET BIT(10)
+ #define SPEAR1310_PCIE2_CFG_CORE_CLK_EN BIT(9)
+ #define SPEAR1310_PCIE2_CFG_AUX_CLK_EN BIT(8)
+ #define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT BIT(7)
+ #define SPEAR1310_PCIE1_CFG_POWERUP_RESET BIT(6)
+ #define SPEAR1310_PCIE1_CFG_CORE_CLK_EN BIT(5)
+ #define SPEAR1310_PCIE1_CFG_AUX_CLK_EN BIT(4)
+ #define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT BIT(3)
+ #define SPEAR1310_PCIE0_CFG_POWERUP_RESET BIT(2)
+ #define SPEAR1310_PCIE0_CFG_CORE_CLK_EN BIT(1)
+ #define SPEAR1310_PCIE0_CFG_AUX_CLK_EN BIT(0)
+
+ #define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
+ #define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+ BIT((x + 29)))
+ #define SPEAR1310_PCIE_CFG_VAL(x) \
+ (SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+ SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+ SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+ SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+ SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+ #define SPEAR1310_SATA_CFG_VAL(x) \
+ (SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+ SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+ SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+ SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+ SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define SPEAR1310_PCIE_MIPHY_CFG_1 0x3A8
+ #define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT BIT(31)
+ #define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 BIT(28)
+ #define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x) (x << 16)
+ #define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT BIT(15)
+ #define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 BIT(12)
+ #define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x) (x << 0)
+ #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+ #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+ #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+ (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+ SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+ SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+ SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+ SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+ SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+ #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+ (SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+ #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+ (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+ SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+ SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+ SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define SPEAR1310_PCIE_MIPHY_CFG_2 0x3AC
+
+enum spear1310_miphy_mode {
+ SATA,
+ PCIE,
+};
+
+struct spear1310_miphy_priv {
+ /* instance id of this phy */
+ u32 id;
+ /* phy mode: 0 for SATA 1 for PCIe */
+ enum spear1310_miphy_mode mode;
+ /* regmap for any soc specific misc registers */
+ struct regmap *misc;
+ /* phy struct pointer */
+ struct phy *phy;
+};
+
+static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
+{
+ u32 val;
+
+ regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+ SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+ SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
+
+ switch (priv->id) {
+ case 0:
+ val = SPEAR1310_PCIE_CFG_VAL(0);
+ break;
+ case 1:
+ val = SPEAR1310_PCIE_CFG_VAL(1);
+ break;
+ case 2:
+ val = SPEAR1310_PCIE_CFG_VAL(2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+ SPEAR1310_PCIE_CFG_MASK(priv->id), val);
+
+ return 0;
+}
+
+static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
+{
+ regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+ SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
+
+ regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+ SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
+
+ return 0;
+}
+
+static int spear1310_miphy_init(struct phy *phy)
+{
+ struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+ int ret = 0;
+
+ if (priv->mode == PCIE)
+ ret = spear1310_miphy_pcie_init(priv);
+
+ return ret;
+}
+
+static int spear1310_miphy_exit(struct phy *phy)
+{
+ struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+ int ret = 0;
+
+ if (priv->mode == PCIE)
+ ret = spear1310_miphy_pcie_exit(priv);
+
+ return ret;
+}
+
+static const struct of_device_id spear1310_miphy_of_match[] = {
+ { .compatible = "st,spear1310-miphy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
+
+static struct phy_ops spear1310_miphy_ops = {
+ .init = spear1310_miphy_init,
+ .exit = spear1310_miphy_exit,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *spear1310_miphy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
+
+ if (args->args_count < 1) {
+ dev_err(dev, "DT did not pass correct no of args\n");
+ return NULL;
+ }
+
+ priv->mode = args->args[0];
+
+ if (priv->mode != SATA && priv->mode != PCIE) {
+ dev_err(dev, "DT did not pass correct phy mode\n");
+ return NULL;
+ }
+
+ return priv->phy;
+}
+
+static int spear1310_miphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct spear1310_miphy_priv *priv;
+ struct phy_provider *phy_provider;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev, "can't alloc spear1310_miphy private date memory\n");
+ return -ENOMEM;
+ }
+
+ priv->misc =
+ syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+ if (IS_ERR(priv->misc)) {
+ dev_err(dev, "failed to find misc regmap\n");
+ return PTR_ERR(priv->misc);
+ }
+
+ if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
+ dev_err(dev, "failed to find phy id\n");
+ return -EINVAL;
+ }
+
+ priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL);
+ if (IS_ERR(priv->phy)) {
+ dev_err(dev, "failed to create SATA PCIe PHY\n");
+ return PTR_ERR(priv->phy);
+ }
+
+ dev_set_drvdata(dev, priv);
+ phy_set_drvdata(priv->phy, priv);
+
+ phy_provider =
+ devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(dev, "failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static struct platform_driver spear1310_miphy_driver = {
+ .probe = spear1310_miphy_probe,
+ .driver = {
+ .name = "spear1310-miphy",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(spear1310_miphy_of_match),
+ },
+};
+
+static int __init spear1310_miphy_phy_init(void)
+{
+ return platform_driver_register(&spear1310_miphy_driver);
+}
+module_init(spear1310_miphy_phy_init);
+
+static void __exit spear1310_miphy_phy_exit(void)
+{
+ platform_driver_unregister(&spear1310_miphy_driver);
+}
+module_exit(spear1310_miphy_phy_exit);
+
+MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c
new file mode 100644
index 000000000000..7135ba2603b6
--- /dev/null
+++ b/drivers/phy/phy-spear1340-miphy.c
@@ -0,0 +1,307 @@
+/*
+ * ST spear1340-miphy driver
+ *
+ * Copyright (C) 2014 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ * Mohit Kumar <mohit.kumar@st.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/bitops.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+/* SPEAr1340 Registers */
+/* Power Management Registers */
+#define SPEAR1340_PCM_CFG 0x100
+ #define SPEAR1340_PCM_CFG_SATA_POWER_EN BIT(11)
+#define SPEAR1340_PCM_WKUP_CFG 0x104
+#define SPEAR1340_SWITCH_CTR 0x108
+
+#define SPEAR1340_PERIP1_SW_RST 0x318
+ #define SPEAR1340_PERIP1_SW_RSATA BIT(12)
+#define SPEAR1340_PERIP2_SW_RST 0x31C
+#define SPEAR1340_PERIP3_SW_RST 0x320
+
+/* PCIE - SATA configuration registers */
+#define SPEAR1340_PCIE_SATA_CFG 0x424
+ /* PCIE CFG MASks */
+ #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT BIT(11)
+ #define SPEAR1340_PCIE_CFG_POWERUP_RESET BIT(10)
+ #define SPEAR1340_PCIE_CFG_CORE_CLK_EN BIT(9)
+ #define SPEAR1340_PCIE_CFG_AUX_CLK_EN BIT(8)
+ #define SPEAR1340_SATA_CFG_TX_CLK_EN BIT(4)
+ #define SPEAR1340_SATA_CFG_RX_CLK_EN BIT(3)
+ #define SPEAR1340_SATA_CFG_POWERUP_RESET BIT(2)
+ #define SPEAR1340_SATA_CFG_PM_CLK_EN BIT(1)
+ #define SPEAR1340_PCIE_SATA_SEL_PCIE (0)
+ #define SPEAR1340_PCIE_SATA_SEL_SATA (1)
+ #define SPEAR1340_PCIE_SATA_CFG_MASK 0xF1F
+ #define SPEAR1340_PCIE_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_PCIE | \
+ SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
+ SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
+ SPEAR1340_PCIE_CFG_POWERUP_RESET | \
+ SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
+ #define SPEAR1340_SATA_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_SATA | \
+ SPEAR1340_SATA_CFG_PM_CLK_EN | \
+ SPEAR1340_SATA_CFG_POWERUP_RESET | \
+ SPEAR1340_SATA_CFG_RX_CLK_EN | \
+ SPEAR1340_SATA_CFG_TX_CLK_EN)
+
+#define SPEAR1340_PCIE_MIPHY_CFG 0x428
+ #define SPEAR1340_MIPHY_OSC_BYPASS_EXT BIT(31)
+ #define SPEAR1340_MIPHY_CLK_REF_DIV2 BIT(27)
+ #define SPEAR1340_MIPHY_CLK_REF_DIV4 (2 << 27)
+ #define SPEAR1340_MIPHY_CLK_REF_DIV8 (3 << 27)
+ #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x) (x << 0)
+ #define SPEAR1340_PCIE_MIPHY_CFG_MASK 0xF80000FF
+ #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
+ (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+ SPEAR1340_MIPHY_CLK_REF_DIV2 | \
+ SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
+ #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+ (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
+ #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
+ (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+ SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+
+enum spear1340_miphy_mode {
+ SATA,
+ PCIE,
+};
+
+struct spear1340_miphy_priv {
+ /* phy mode: 0 for SATA 1 for PCIe */
+ enum spear1340_miphy_mode mode;
+ /* regmap for any soc specific misc registers */
+ struct regmap *misc;
+ /* phy struct pointer */
+ struct phy *phy;
+};
+
+static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
+{
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ SPEAR1340_PCIE_SATA_CFG_MASK,
+ SPEAR1340_SATA_CFG_VAL);
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ SPEAR1340_PCIE_MIPHY_CFG_MASK,
+ SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
+ /* Switch on sata power domain */
+ regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+ SPEAR1340_PCM_CFG_SATA_POWER_EN,
+ SPEAR1340_PCM_CFG_SATA_POWER_EN);
+ /* Wait for SATA power domain on */
+ msleep(20);
+
+ /* Disable PCIE SATA Controller reset */
+ regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+ SPEAR1340_PERIP1_SW_RSATA, 0);
+ /* Wait for SATA reset de-assert completion */
+ msleep(20);
+
+ return 0;
+}
+
+static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
+{
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+
+ /* Enable PCIE SATA Controller reset */
+ regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+ SPEAR1340_PERIP1_SW_RSATA,
+ SPEAR1340_PERIP1_SW_RSATA);
+ /* Wait for SATA power domain off */
+ msleep(20);
+ /* Switch off sata power domain */
+ regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+ SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
+ /* Wait for SATA reset assert completion */
+ msleep(20);
+
+ return 0;
+}
+
+static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
+{
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ SPEAR1340_PCIE_MIPHY_CFG_MASK,
+ SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ SPEAR1340_PCIE_SATA_CFG_MASK,
+ SPEAR1340_PCIE_CFG_VAL);
+
+ return 0;
+}
+
+static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
+{
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+ regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+
+ return 0;
+}
+
+static int spear1340_miphy_init(struct phy *phy)
+{
+ struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+ int ret = 0;
+
+ if (priv->mode == SATA)
+ ret = spear1340_miphy_sata_init(priv);
+ else if (priv->mode == PCIE)
+ ret = spear1340_miphy_pcie_init(priv);
+
+ return ret;
+}
+
+static int spear1340_miphy_exit(struct phy *phy)
+{
+ struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+ int ret = 0;
+
+ if (priv->mode == SATA)
+ ret = spear1340_miphy_sata_exit(priv);
+ else if (priv->mode == PCIE)
+ ret = spear1340_miphy_pcie_exit(priv);
+
+ return ret;
+}
+
+static const struct of_device_id spear1340_miphy_of_match[] = {
+ { .compatible = "st,spear1340-miphy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
+
+static struct phy_ops spear1340_miphy_ops = {
+ .init = spear1340_miphy_init,
+ .exit = spear1340_miphy_exit,
+ .owner = THIS_MODULE,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int spear1340_miphy_suspend(struct device *dev)
+{
+ struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (priv->mode == SATA)
+ ret = spear1340_miphy_sata_exit(priv);
+
+ return ret;
+}
+
+static int spear1340_miphy_resume(struct device *dev)
+{
+ struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (priv->mode == SATA)
+ ret = spear1340_miphy_sata_init(priv);
+
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
+ spear1340_miphy_resume);
+
+static struct phy *spear1340_miphy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+
+ if (args->args_count < 1) {
+ dev_err(dev, "DT did not pass correct no of args\n");
+ return NULL;
+ }
+
+ priv->mode = args->args[0];
+
+ if (priv->mode != SATA && priv->mode != PCIE) {
+ dev_err(dev, "DT did not pass correct phy mode\n");
+ return NULL;
+ }
+
+ return priv->phy;
+}
+
+static int spear1340_miphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct spear1340_miphy_priv *priv;
+ struct phy_provider *phy_provider;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev, "can't alloc spear1340_miphy private date memory\n");
+ return -ENOMEM;
+ }
+
+ priv->misc =
+ syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+ if (IS_ERR(priv->misc)) {
+ dev_err(dev, "failed to find misc regmap\n");
+ return PTR_ERR(priv->misc);
+ }
+
+ priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL);
+ if (IS_ERR(priv->phy)) {
+ dev_err(dev, "failed to create SATA PCIe PHY\n");
+ return PTR_ERR(priv->phy);
+ }
+
+ dev_set_drvdata(dev, priv);
+ phy_set_drvdata(priv->phy, priv);
+
+ phy_provider =
+ devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(dev, "failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static struct platform_driver spear1340_miphy_driver = {
+ .probe = spear1340_miphy_probe,
+ .driver = {
+ .name = "spear1340-miphy",
+ .owner = THIS_MODULE,
+ .pm = &spear1340_miphy_pm_ops,
+ .of_match_table = of_match_ptr(spear1340_miphy_of_match),
+ },
+};
+
+static int __init spear1340_miphy_phy_init(void)
+{
+ return platform_driver_register(&spear1340_miphy_driver);
+}
+module_init(spear1340_miphy_phy_init);
+
+static void __exit spear1340_miphy_phy_exit(void)
+{
+ platform_driver_unregister(&spear1340_miphy_driver);
+}
+module_exit(spear1340_miphy_phy_exit);
+
+MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
+MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 115d8d5190d5..61ebea49709b 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -22,6 +22,7 @@
*/
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -294,7 +295,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->pmu);
}
- phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+ phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
if (IS_ERR(phy->phy)) {
dev_err(dev, "failed to create PHY %d\n", i);
return PTR_ERR(phy->phy);
@@ -306,10 +307,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
dev_set_drvdata(dev, data);
phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
- return 0;
+ return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id sun4i_usb_phy_of_match[] = {
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 591367654613..b964aa967b46 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -80,7 +80,9 @@ struct ti_pipe3 {
struct clk *wkupclk;
struct clk *sys_clk;
struct clk *refclk;
+ struct clk *div_clk;
struct pipe3_dpll_map *dpll_map;
+ u8 id;
};
static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,11 @@ static int ti_pipe3_init(struct phy *x)
u32 val;
int ret = 0;
+ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+ omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
+ return 0;
+ }
+
/* Bring it out of IDLE if it is IDLE */
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
if (val & PLL_IDLE) {
@@ -238,8 +245,11 @@ static int ti_pipe3_exit(struct phy *x)
u32 val;
unsigned long timeout;
- /* SATA DPLL can't be powered down due to Errata i783 */
- if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
+ /* SATA DPLL can't be powered down due to Errata i783 and PCIe
+ * does not have internal DPLL
+ */
+ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
+ of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
return 0;
/* Put DPLL in IDLE mode */
@@ -286,32 +296,41 @@ static int ti_pipe3_probe(struct platform_device *pdev)
struct device_node *control_node;
struct platform_device *control_pdev;
const struct of_device_id *match;
-
- match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
- if (!match)
- return -EINVAL;
+ struct clk *clk;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
return -ENOMEM;
}
+ phy->dev = &pdev->dev;
- phy->dpll_map = (struct pipe3_dpll_map *)match->data;
- if (!phy->dpll_map) {
- dev_err(&pdev->dev, "no DPLL data\n");
- return -EINVAL;
- }
+ if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+ match = of_match_device(of_match_ptr(ti_pipe3_id_table),
+ &pdev->dev);
+ if (!match)
+ return -EINVAL;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
- phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(phy->pll_ctrl_base))
- return PTR_ERR(phy->pll_ctrl_base);
+ phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+ if (!phy->dpll_map) {
+ dev_err(&pdev->dev, "no DPLL data\n");
+ return -EINVAL;
+ }
- phy->dev = &pdev->dev;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "pll_ctrl");
+ phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(phy->pll_ctrl_base))
+ return PTR_ERR(phy->pll_ctrl_base);
- if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+ phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
+ if (IS_ERR(phy->sys_clk)) {
+ dev_err(&pdev->dev, "unable to get sysclk\n");
+ return -EINVAL;
+ }
+ }
+ if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +347,38 @@ static int ti_pipe3_probe(struct platform_device *pdev)
phy->refclk = ERR_PTR(-ENODEV);
}
- phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
- if (IS_ERR(phy->sys_clk)) {
- dev_err(&pdev->dev, "unable to get sysclk\n");
- return -EINVAL;
+ if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+ if (of_property_read_u8(node, "id", &phy->id) < 0)
+ phy->id = 1;
+
+ clk = devm_clk_get(phy->dev, "dpll_ref");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get dpll ref clk\n");
+ return PTR_ERR(clk);
+ }
+ clk_set_rate(clk, 1500000000);
+
+ clk = devm_clk_get(phy->dev, "dpll_ref_m2");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
+ return PTR_ERR(clk);
+ }
+ clk_set_rate(clk, 100000000);
+
+ clk = devm_clk_get(phy->dev, "phy-div");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get phy-div clk\n");
+ return PTR_ERR(clk);
+ }
+ clk_set_rate(clk, 100000000);
+
+ phy->div_clk = devm_clk_get(phy->dev, "div-clk");
+ if (IS_ERR(phy->div_clk)) {
+ dev_err(&pdev->dev, "unable to get div-clk\n");
+ return PTR_ERR(phy->div_clk);
+ }
+ } else {
+ phy->div_clk = ERR_PTR(-ENODEV);
}
control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -353,7 +400,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, phy);
pm_runtime_enable(phy->dev);
- generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+ generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
@@ -387,6 +434,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
clk_disable_unprepare(phy->wkupclk);
if (!IS_ERR(phy->refclk))
clk_disable_unprepare(phy->refclk);
+ if (!IS_ERR(phy->div_clk))
+ clk_disable_unprepare(phy->div_clk);
return 0;
}
@@ -412,8 +461,19 @@ static int ti_pipe3_runtime_resume(struct device *dev)
}
}
+ if (!IS_ERR(phy->div_clk)) {
+ ret = clk_prepare_enable(phy->div_clk);
+ if (ret) {
+ dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
+ goto err3;
+ }
+ }
return 0;
+err3:
+ if (!IS_ERR(phy->wkupclk))
+ clk_disable_unprepare(phy->wkupclk);
+
err2:
if (!IS_ERR(phy->refclk))
clk_disable_unprepare(phy->refclk);
@@ -446,6 +506,9 @@ static const struct of_device_id ti_pipe3_id_table[] = {
.compatible = "ti,phy-pipe3-sata",
.data = dpll_map_sata,
},
+ {
+ .compatible = "ti,phy-pipe3-pcie",
+ },
{}
};
MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 2e0e9b3774c8..e1a6623d4696 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -695,7 +695,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
otg->set_host = twl4030_set_host;
otg->set_peripheral = twl4030_set_peripheral;
- phy = devm_phy_create(twl->dev, &ops, init_data);
+ phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
if (IS_ERR(phy)) {
dev_dbg(&pdev->dev, "Failed to create PHY\n");
return PTR_ERR(phy);
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index 4aa1ccd1511f..db809b97219e 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1707,7 +1707,7 @@ static int xgene_phy_probe(struct platform_device *pdev)
ctx->dev = &pdev->dev;
platform_set_drvdata(pdev, ctx);
- ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL);
+ ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
if (IS_ERR(ctx->phy)) {
dev_dbg(&pdev->dev, "Failed to create PHY\n");
rc = PTR_ERR(ctx->phy);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0042ccb46b9a..bfd2c2e9f6cd 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -11,10 +11,10 @@ menu "Pin controllers"
depends on PINCTRL
config PINMUX
- bool "Support pin multiplexing controllers"
+ bool "Support pin multiplexing controllers" if COMPILE_TEST
config PINCONF
- bool "Support pin configuration controllers"
+ bool "Support pin configuration controllers" if COMPILE_TEST
config GENERIC_PINCONF
bool
@@ -26,29 +26,6 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
-config PINCTRL_ABX500
- bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions"
- depends on AB8500_CORE
- select GENERIC_PINCONF
- help
- Select this to enable the ABx500 family IC GPIO driver
-
-config PINCTRL_AB8500
- bool "AB8500 pin controller driver"
- depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB8540
- bool "AB8540 pin controller driver"
- depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB9540
- bool "AB9540 pin controller driver"
- depends on PINCTRL_ABX500 && ARCH_U8500
-
-config PINCTRL_AB8505
- bool "AB8505 pin controller driver"
- depends on PINCTRL_ABX500 && ARCH_U8500
-
config PINCTRL_ADI2
bool "ADI pin controller driver"
depends on BLACKFIN
@@ -93,7 +70,7 @@ config PINCTRL_AT91
config PINCTRL_BAYTRAIL
bool "Intel Baytrail GPIO pin control"
depends on GPIOLIB && ACPI && X86
- select IRQ_DOMAIN
+ select GPIOLIB_IRQCHIP
help
driver for memory mapped GPIO functionality on Intel Baytrail
platforms. Supports 3 banks with 102, 28 and 44 gpios.
@@ -130,6 +107,13 @@ config PINCTRL_IMX1_CORE
select PINMUX
select PINCONF
+config PINCTRL_IMX1
+ bool "IMX1 pinctrl driver"
+ depends on SOC_IMX1
+ select PINCTRL_IMX1_CORE
+ help
+ Say Y here to enable the imx1 pinctrl driver
+
config PINCTRL_IMX27
bool "IMX27 pinctrl driver"
depends on SOC_IMX27
@@ -226,58 +210,6 @@ config PINCTRL_IMX28
bool
select PINCTRL_MXS
-config PINCTRL_MSM
- bool
- select PINMUX
- select PINCONF
- select GENERIC_PINCONF
- select GPIOLIB_IRQCHIP
-
-config PINCTRL_APQ8064
- tristate "Qualcomm APQ8064 pin controller driver"
- depends on GPIOLIB && OF
- select PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
-
-config PINCTRL_IPQ8064
- tristate "Qualcomm IPQ8064 pin controller driver"
- depends on GPIOLIB && OF
- select PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
-
-config PINCTRL_MSM8X74
- tristate "Qualcomm 8x74 pin controller driver"
- depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST)
- select PINCTRL_MSM
- help
- This is the pinctrl, pinmux, pinconf and gpiolib driver for the
- Qualcomm TLMM block found in the Qualcomm 8974 platform.
-
-config PINCTRL_NOMADIK
- bool "Nomadik pin controller driver"
- depends on ARCH_U8500 || ARCH_NOMADIK
- select PINMUX
- select PINCONF
- select GPIOLIB
- select OF_GPIO
- select GPIOLIB_IRQCHIP
-
-config PINCTRL_STN8815
- bool "STN8815 pin controller driver"
- depends on PINCTRL_NOMADIK && ARCH_NOMADIK
-
-config PINCTRL_DB8500
- bool "DB8500 pin controller driver"
- depends on PINCTRL_NOMADIK && ARCH_U8500
-
-config PINCTRL_DB8540
- bool "DB8540 pin controller driver"
- depends on PINCTRL_NOMADIK && ARCH_U8500
-
config PINCTRL_ROCKCHIP
bool
select PINMUX
@@ -328,6 +260,12 @@ config PINCTRL_TEGRA124
bool
select PINCTRL_TEGRA
+config PINCTRL_TEGRA_XUSB
+ def_bool y if ARCH_TEGRA
+ select GENERIC_PHY
+ select PINCONF
+ select PINMUX
+
config PINCTRL_TZ1090
bool "Toumaz Xenif TZ1090 pin control driver"
depends on SOC_TZ1090
@@ -356,22 +294,6 @@ config PINCTRL_COH901
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
-config PINCTRL_SAMSUNG
- bool
- select PINMUX
- select PINCONF
-
-config PINCTRL_EXYNOS
- bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440"
- depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210)
- select PINCTRL_SAMSUNG
-
-config PINCTRL_EXYNOS5440
- bool "Samsung EXYNOS5440 SoC pinctrl driver"
- depends on SOC_EXYNOS5440
- select PINMUX
- select PINCONF
-
config PINCTRL_PALMAS
bool "Pinctrl driver for the PALMAS Series MFD devices"
depends on OF && MFD_PALMAS
@@ -383,18 +305,11 @@ config PINCTRL_PALMAS
open drain configuration for the Palmas series devices like
TPS65913, TPS80036 etc.
-config PINCTRL_S3C24XX
- bool "Samsung S3C24XX SoC pinctrl driver"
- depends on ARCH_S3C24XX
- select PINCTRL_SAMSUNG
-
-config PINCTRL_S3C64XX
- bool "Samsung S3C64XX SoC pinctrl driver"
- depends on ARCH_S3C64XX
- select PINCTRL_SAMSUNG
-
source "drivers/pinctrl/berlin/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
+source "drivers/pinctrl/nomadik/Kconfig"
+source "drivers/pinctrl/qcom/Kconfig"
+source "drivers/pinctrl/samsung/Kconfig"
source "drivers/pinctrl/sh-pfc/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index c4b5d405b8f5..05d227508c95 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,11 +9,6 @@ ifeq ($(CONFIG_OF),y)
obj-$(CONFIG_PINCTRL) += devicetree.o
endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
-obj-$(CONFIG_PINCTRL_ABX500) += pinctrl-abx500.o
-obj-$(CONFIG_PINCTRL_AB8500) += pinctrl-ab8500.o
-obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o
-obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
-obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
@@ -24,6 +19,7 @@ obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o
obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
obj-$(CONFIG_PINCTRL_IMX1_CORE) += pinctrl-imx1-core.o
+obj-$(CONFIG_PINCTRL_IMX1) += pinctrl-imx1.o
obj-$(CONFIG_PINCTRL_IMX27) += pinctrl-imx27.o
obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o
obj-$(CONFIG_PINCTRL_IMX50) += pinctrl-imx50.o
@@ -38,14 +34,6 @@ obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o
obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
-obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o
-obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o
-obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
-obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
-obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
-obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
-obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
-obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
@@ -55,15 +43,11 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
+obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o
obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
-obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
-obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
-obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o
-obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
@@ -72,8 +56,11 @@ obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_PLAT_ORION) += mvebu/
+obj-y += nomadik/
+obj-$(CONFIG_ARCH_QCOM) += qcom/
+obj-$(CONFIG_PLAT_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/
obj-$(CONFIG_SUPERH) += sh-pfc/
obj-$(CONFIG_PLAT_SPEAR) += spear/
-obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
+obj-$(CONFIG_ARCH_VT8500) += vt8500/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index e09474ecde23..e4f65510c87e 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -992,29 +992,15 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
if (p->state) {
/*
- * The set of groups with a mux configuration in the old state
- * may not be identical to the set of groups with a mux setting
- * in the new state. While this might be unusual, it's entirely
- * possible for the "user"-supplied mapping table to be written
- * that way. For each group that was configured in the old state
- * but not in the new state, this code puts that group into a
- * safe/disabled state.
+ * For each pinmux setting in the old state, forget SW's record
+ * of mux owner for that pingroup. Any pingroups which are
+ * still owned by the new state will be re-acquired by the call
+ * to pinmux_enable_setting() in the loop below.
*/
list_for_each_entry(setting, &p->state->settings, node) {
- bool found = false;
if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
continue;
- list_for_each_entry(setting2, &state->settings, node) {
- if (setting2->type != PIN_MAP_TYPE_MUX_GROUP)
- continue;
- if (setting2->data.mux.group ==
- setting->data.mux.group) {
- found = true;
- break;
- }
- }
- if (!found)
- pinmux_disable_setting(setting);
+ pinmux_disable_setting(setting);
}
}
diff --git a/drivers/pinctrl/nomadik/Kconfig b/drivers/pinctrl/nomadik/Kconfig
new file mode 100644
index 000000000000..d48a5aa24a29
--- /dev/null
+++ b/drivers/pinctrl/nomadik/Kconfig
@@ -0,0 +1,51 @@
+if ARCH_U8500
+
+config PINCTRL_ABX500
+ bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions"
+ depends on AB8500_CORE
+ select GENERIC_PINCONF
+ help
+ Select this to enable the ABx500 family IC GPIO driver
+
+config PINCTRL_AB8500
+ bool "AB8500 pin controller driver"
+ depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB8540
+ bool "AB8540 pin controller driver"
+ depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB9540
+ bool "AB9540 pin controller driver"
+ depends on PINCTRL_ABX500 && ARCH_U8500
+
+config PINCTRL_AB8505
+ bool "AB8505 pin controller driver"
+ depends on PINCTRL_ABX500 && ARCH_U8500
+
+endif
+
+if (ARCH_U8500 || ARCH_NOMADIK)
+
+config PINCTRL_NOMADIK
+ bool "Nomadik pin controller driver"
+ depends on ARCH_U8500 || ARCH_NOMADIK
+ select PINMUX
+ select PINCONF
+ select GPIOLIB
+ select OF_GPIO
+ select GPIOLIB_IRQCHIP
+
+config PINCTRL_STN8815
+ bool "STN8815 pin controller driver"
+ depends on PINCTRL_NOMADIK && ARCH_NOMADIK
+
+config PINCTRL_DB8500
+ bool "DB8500 pin controller driver"
+ depends on PINCTRL_NOMADIK && ARCH_U8500
+
+config PINCTRL_DB8540
+ bool "DB8540 pin controller driver"
+ depends on PINCTRL_NOMADIK && ARCH_U8500
+
+endif
diff --git a/drivers/pinctrl/nomadik/Makefile b/drivers/pinctrl/nomadik/Makefile
new file mode 100644
index 000000000000..30b27f18cd52
--- /dev/null
+++ b/drivers/pinctrl/nomadik/Makefile
@@ -0,0 +1,10 @@
+# Nomadik family pin control drivers
+obj-$(CONFIG_PINCTRL_ABX500) += pinctrl-abx500.o
+obj-$(CONFIG_PINCTRL_AB8500) += pinctrl-ab8500.o
+obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o
+obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
+obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
+obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o
+obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
+obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
+obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o
diff --git a/drivers/pinctrl/pinctrl-ab8500.c b/drivers/pinctrl/nomadik/pinctrl-ab8500.c
index 2ac2d0ad3025..2ac2d0ad3025 100644
--- a/drivers/pinctrl/pinctrl-ab8500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-ab8500.c
diff --git a/drivers/pinctrl/pinctrl-ab8505.c b/drivers/pinctrl/nomadik/pinctrl-ab8505.c
index bf0ef4ac376f..bf0ef4ac376f 100644
--- a/drivers/pinctrl/pinctrl-ab8505.c
+++ b/drivers/pinctrl/nomadik/pinctrl-ab8505.c
diff --git a/drivers/pinctrl/pinctrl-ab8540.c b/drivers/pinctrl/nomadik/pinctrl-ab8540.c
index 9867535d49c1..9867535d49c1 100644
--- a/drivers/pinctrl/pinctrl-ab8540.c
+++ b/drivers/pinctrl/nomadik/pinctrl-ab8540.c
diff --git a/drivers/pinctrl/pinctrl-ab9540.c b/drivers/pinctrl/nomadik/pinctrl-ab9540.c
index 1a281ca95dac..1a281ca95dac 100644
--- a/drivers/pinctrl/pinctrl-ab9540.c
+++ b/drivers/pinctrl/nomadik/pinctrl-ab9540.c
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index 163da9c3ea0e..a53a689a2bfa 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -32,8 +32,8 @@
#include <linux/pinctrl/machine.h>
#include "pinctrl-abx500.h"
-#include "core.h"
-#include "pinconf.h"
+#include "../core.h"
+#include "../pinconf.h"
/*
* The AB9540 and AB8540 GPIO support are extended versions
@@ -737,20 +737,6 @@ static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
return ret;
}
-static void abx500_pmx_disable(struct pinctrl_dev *pctldev,
- unsigned function, unsigned group)
-{
- struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
- const struct abx500_pingroup *g;
-
- g = &pct->soc->groups[group];
- if (g->altsetting < 0)
- return;
-
- /* FIXME: poke out the mux, set the pin to some default state? */
- dev_dbg(pct->dev, "disable group %s, %u pins\n", g->name, g->npins);
-}
-
static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
@@ -799,7 +785,6 @@ static const struct pinmux_ops abx500_pinmux_ops = {
.get_function_name = abx500_pmx_get_func_name,
.get_function_groups = abx500_pmx_get_func_groups,
.enable = abx500_pmx_enable,
- .disable = abx500_pmx_disable,
.gpio_request_enable = abx500_gpio_request_enable,
.gpio_disable_free = abx500_gpio_disable_free,
};
diff --git a/drivers/pinctrl/pinctrl-abx500.h b/drivers/pinctrl/nomadik/pinctrl-abx500.h
index 2beef3bfe9ca..2beef3bfe9ca 100644
--- a/drivers/pinctrl/pinctrl-abx500.h
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.h
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
index c74840729648..c74840729648 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8540.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c
index d7ba5443bae0..d7ba5443bae0 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8540.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c
diff --git a/drivers/pinctrl/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
index ed39dcafd4f8..ed39dcafd4f8 100644
--- a/drivers/pinctrl/pinctrl-nomadik-stn8815.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index 8f6f16ef73f3..e7cab07eef47 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -31,7 +31,7 @@
/* Since we request GPIOs from ourself */
#include <linux/pinctrl/consumer.h>
#include "pinctrl-nomadik.h"
-#include "core.h"
+#include "../core.h"
/*
* The GPIO module in the Nomadik family of Systems-on-Chip is an
@@ -1765,21 +1765,6 @@ out_glitch:
return ret;
}
-static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
- unsigned function, unsigned group)
-{
- struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
- const struct nmk_pingroup *g;
-
- g = &npct->soc->groups[group];
-
- if (g->altsetting < 0)
- return;
-
- /* Poke out the mux, set the pin to some default state? */
- dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins);
-}
-
static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
@@ -1826,7 +1811,6 @@ static const struct pinmux_ops nmk_pinmux_ops = {
.get_function_name = nmk_pmx_get_func_name,
.get_function_groups = nmk_pmx_get_func_groups,
.enable = nmk_pmx_enable,
- .disable = nmk_pmx_disable,
.gpio_request_enable = nmk_gpio_request_enable,
.gpio_disable_free = nmk_gpio_disable_free,
};
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/nomadik/pinctrl-nomadik.h
index d8215f1e70c7..d8215f1e70c7 100644
--- a/drivers/pinctrl/pinctrl-nomadik.h
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.h
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 5c44feb54ebb..b092b93c67a1 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -401,7 +401,7 @@ static int adi_gpio_irq_type(struct irq_data *d, unsigned int type)
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
- snprintf(buf, 16, "gpio-irq%d", irq);
+ snprintf(buf, 16, "gpio-irq%u", irq);
port_setup(port, d->hwirq, true);
} else
goto out;
@@ -652,35 +652,6 @@ static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned func_id,
return 0;
}
-static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned func_id,
- unsigned group_id)
-{
- struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
- struct gpio_port *port;
- struct pinctrl_gpio_range *range;
- unsigned long flags;
- unsigned short *mux, pin;
-
- mux = (unsigned short *)pinctrl->soc->groups[group_id].mux;
-
- while (*mux) {
- pin = P_IDENT(*mux);
-
- range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
- if (range == NULL) /* should not happen */
- return;
-
- port = container_of(range->gc, struct gpio_port, chip);
-
- spin_lock_irqsave(&port->lock, flags);
-
- port_setup(port, pin_to_offset(range, pin), true);
- mux++;
-
- spin_unlock_irqrestore(&port->lock, flags);
- }
-}
-
static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
{
struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -728,7 +699,6 @@ static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev,
static struct pinmux_ops adi_pinmux_ops = {
.enable = adi_pinmux_enable,
- .disable = adi_pinmux_disable,
.get_functions_count = adi_pinmux_get_funcs_count,
.get_function_name = adi_pinmux_get_func_name,
.get_function_groups = adi_pinmux_get_groups,
@@ -979,7 +949,7 @@ static int adi_gpio_probe(struct platform_device *pdev)
struct gpio_port *port;
char pinctrl_devname[DEVNAME_SIZE];
static int gpio;
- int ret = 0, ret1;
+ int ret = 0;
pdata = dev->platform_data;
if (!pdata)
@@ -1057,7 +1027,7 @@ static int adi_gpio_probe(struct platform_device *pdev)
return 0;
out_remove_gpiochip:
- ret1 = gpiochip_remove(&port->chip);
+ gpiochip_remove(&port->chip);
out_remove_domain:
if (port->pint)
irq_domain_remove(port->domain);
@@ -1068,12 +1038,11 @@ out_remove_domain:
static int adi_gpio_remove(struct platform_device *pdev)
{
struct gpio_port *port = platform_get_drvdata(pdev);
- int ret;
u8 offset;
list_del(&port->node);
gpiochip_remove_pin_ranges(&port->chip);
- ret = gpiochip_remove(&port->chip);
+ gpiochip_remove(&port->chip);
if (port->pint) {
for (offset = 0; offset < port->width; offset++)
irq_dispose_mapping(irq_find_mapping(port->domain,
@@ -1081,7 +1050,7 @@ static int adi_gpio_remove(struct platform_device *pdev)
irq_domain_remove(port->domain);
}
- return ret;
+ return 0;
}
static int adi_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
index c862f9c0e9ce..0e4ec91f4d49 100644
--- a/drivers/pinctrl/pinctrl-as3722.c
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -565,7 +565,6 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
{
struct as3722_pctrl_info *as_pci;
int ret;
- int tret;
as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL);
if (!as_pci)
@@ -611,10 +610,7 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
return 0;
fail_range_add:
- tret = gpiochip_remove(&as_pci->gpio_chip);
- if (tret < 0)
- dev_warn(&pdev->dev, "Couldn't remove gpio chip, %d\n", tret);
-
+ gpiochip_remove(&as_pci->gpio_chip);
fail_chip_add:
pinctrl_unregister(as_pci->pctl);
return ret;
@@ -623,11 +619,8 @@ fail_chip_add:
static int as3722_pinctrl_remove(struct platform_device *pdev)
{
struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
- int ret;
- ret = gpiochip_remove(&as_pci->gpio_chip);
- if (ret < 0)
- return ret;
+ gpiochip_remove(&as_pci->gpio_chip);
pinctrl_unregister(as_pci->pctl);
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 421493cb490c..af1ba4fc150d 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -611,26 +611,6 @@ static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
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);
@@ -705,7 +685,6 @@ static const struct pinmux_ops at91_pmx_ops = {
.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,
};
@@ -793,9 +772,9 @@ static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
unsigned long config;
- int ret, val, num_conf = 0;
+ int val, num_conf = 0;
- ret = at91_pinconf_get(pctldev, pin_id, &config);
+ at91_pinconf_get(pctldev, pin_id, &config);
DBG_SHOW_FLAG(MULTI_DRIVE);
DBG_SHOW_FLAG(PULL_UP);
@@ -945,7 +924,7 @@ static int at91_pinctrl_parse_functions(struct device_node *np,
/* Initialise function */
func->name = np->name;
func->ngroups = of_get_child_count(np);
- if (func->ngroups <= 0) {
+ if (func->ngroups == 0) {
dev_err(info->dev, "no groups defined\n");
return -EINVAL;
}
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c
index 975572e2f260..9ca59a018743 100644
--- a/drivers/pinctrl/pinctrl-baytrail.c
+++ b/drivers/pinctrl/pinctrl-baytrail.c
@@ -25,9 +25,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/gpio.h>
-#include <linux/irqdomain.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
@@ -44,6 +42,7 @@
/* BYT_CONF0_REG register bits */
#define BYT_IODEN BIT(31)
+#define BYT_DIRECT_IRQ_EN BIT(27)
#define BYT_TRIG_NEG BIT(26)
#define BYT_TRIG_POS BIT(25)
#define BYT_TRIG_LVL BIT(24)
@@ -137,7 +136,6 @@ static struct pinctrl_gpio_range byt_ranges[] = {
struct byt_gpio {
struct gpio_chip chip;
- struct irq_domain *domain;
struct platform_device *pdev;
spinlock_t lock;
void __iomem *reg_base;
@@ -217,7 +215,7 @@ static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
static int byt_irq_type(struct irq_data *d, unsigned type)
{
- struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
+ struct byt_gpio *vg = to_byt_gpio(irq_data_get_irq_chip_data(d));
u32 offset = irqd_to_hwirq(d);
u32 value;
unsigned long flags;
@@ -303,12 +301,22 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct byt_gpio *vg = to_byt_gpio(chip);
+ void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG);
void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
unsigned long flags;
u32 reg_val;
spin_lock_irqsave(&vg->lock, flags);
+ /*
+ * Before making any direction modifications, do a check if gpio
+ * is set for direct IRQ. On baytrail, setting GPIO to output does
+ * not make sense, so let's at least warn the caller before they shoot
+ * themselves in the foot.
+ */
+ WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
+ "Potential Error: Setting GPIO with direct_irq_en to output");
+
reg_val = readl(reg) | BYT_DIR_MASK;
reg_val &= ~BYT_OUTPUT_EN;
@@ -393,16 +401,10 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
spin_unlock_irqrestore(&vg->lock, flags);
}
-static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct byt_gpio *vg = to_byt_gpio(chip);
- return irq_create_mapping(vg->domain, offset);
-}
-
static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
- struct byt_gpio *vg = irq_data_get_irq_handler_data(data);
+ struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, pin, mask;
void __iomem *reg;
@@ -421,7 +423,7 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
/* Clear before handling so we can't lose an edge */
writel(mask, reg);
- virq = irq_find_mapping(vg->domain, base + pin);
+ virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
generic_handle_irq(virq);
/* In case bios or user sets triggering incorretly a pin
@@ -454,33 +456,11 @@ static void byt_irq_mask(struct irq_data *d)
{
}
-static int byt_irq_reqres(struct irq_data *d)
-{
- struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
-
- if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) {
- dev_err(vg->chip.dev,
- "unable to lock HW IRQ %lu for IRQ\n",
- irqd_to_hwirq(d));
- return -EINVAL;
- }
- return 0;
-}
-
-static void byt_irq_relres(struct irq_data *d)
-{
- struct byt_gpio *vg = irq_data_get_irq_chip_data(d);
-
- gpio_unlock_as_irq(&vg->chip, irqd_to_hwirq(d));
-}
-
static struct irq_chip byt_irqchip = {
.name = "BYT-GPIO",
.irq_mask = byt_irq_mask,
.irq_unmask = byt_irq_unmask,
.irq_set_type = byt_irq_type,
- .irq_request_resources = byt_irq_reqres,
- .irq_release_resources = byt_irq_relres,
};
static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
@@ -501,23 +481,6 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
}
}
-static int byt_gpio_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct byt_gpio *vg = d->host_data;
-
- irq_set_chip_and_handler_name(virq, &byt_irqchip, handle_simple_irq,
- "demux");
- irq_set_chip_data(virq, vg);
- irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static const struct irq_domain_ops byt_gpio_irq_ops = {
- .map = byt_gpio_irq_map,
-};
-
static int byt_gpio_probe(struct platform_device *pdev)
{
struct byt_gpio *vg;
@@ -527,7 +490,6 @@ static int byt_gpio_probe(struct platform_device *pdev)
struct acpi_device *acpi_dev;
struct pinctrl_gpio_range *range;
acpi_handle handle = ACPI_HANDLE(dev);
- unsigned hwirq;
int ret;
if (acpi_bus_get_device(handle, &acpi_dev))
@@ -574,27 +536,27 @@ static int byt_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false;
gc->dev = dev;
+ ret = gpiochip_add(gc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
+ return ret;
+ }
+
/* set up interrupts */
irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_rc && irq_rc->start) {
- hwirq = irq_rc->start;
- gc->to_irq = byt_gpio_to_irq;
-
- vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
- &byt_gpio_irq_ops, vg);
- if (!vg->domain)
- return -ENXIO;
-
byt_gpio_irq_init_hw(vg);
+ ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(dev, "failed to add irqchip\n");
+ gpiochip_remove(gc);
+ return ret;
+ }
- irq_set_handler_data(hwirq, vg);
- irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
- }
-
- ret = gpiochip_add(gc);
- if (ret) {
- dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
- return ret;
+ gpiochip_set_chained_irqchip(gc, &byt_irqchip,
+ (unsigned)irq_rc->start,
+ byt_gpio_irq_handler);
}
pm_runtime_enable(dev);
@@ -627,12 +589,9 @@ MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
static int byt_gpio_remove(struct platform_device *pdev)
{
struct byt_gpio *vg = platform_get_drvdata(pdev);
- int err;
pm_runtime_disable(&pdev->dev);
- err = gpiochip_remove(&vg->chip);
- if (err)
- dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
+ gpiochip_remove(&vg->chip);
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-bcm281xx.c b/drivers/pinctrl/pinctrl-bcm281xx.c
index 3bed792b2c03..c5ca9e633fff 100644
--- a/drivers/pinctrl/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/pinctrl-bcm281xx.c
@@ -1396,7 +1396,7 @@ static struct pinctrl_desc bcm281xx_pinctrl_desc = {
.owner = THIS_MODULE,
};
-int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
+static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
{
struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
struct resource *res;
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 3d907de9bc91..5bcfd7ace0cd 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -841,16 +841,6 @@ static int bcm2835_pmx_enable(struct pinctrl_dev *pctldev,
return 0;
}
-static void bcm2835_pmx_disable(struct pinctrl_dev *pctldev,
- unsigned func_selector,
- unsigned group_selector)
-{
- struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-
- /* disable by setting to GPIO_IN */
- bcm2835_pinctrl_fsel_set(pc, group_selector, BCM2835_FSEL_GPIO_IN);
-}
-
static void bcm2835_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
@@ -880,7 +870,6 @@ static const struct pinmux_ops bcm2835_pmx_ops = {
.get_function_name = bcm2835_pmx_get_function_name,
.get_function_groups = bcm2835_pmx_get_function_groups,
.enable = bcm2835_pmx_enable,
- .disable = bcm2835_pmx_disable,
.gpio_disable_free = bcm2835_pmx_gpio_disable_free,
.gpio_set_direction = bcm2835_pmx_gpio_set_direction,
};
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index d182fdd2e715..29cbbab8c3a6 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -756,8 +756,7 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
err_no_range:
err_no_irqchip:
- if (gpiochip_remove(&gpio->chip))
- dev_err(&pdev->dev, "failed to remove gpio chip\n");
+ gpiochip_remove(&gpio->chip);
err_no_chip:
clk_disable_unprepare(gpio->clk);
dev_err(&pdev->dev, "module ERROR:%d\n", err);
@@ -767,16 +766,11 @@ err_no_chip:
static int __exit u300_gpio_remove(struct platform_device *pdev)
{
struct u300_gpio *gpio = platform_get_drvdata(pdev);
- int err;
/* Turn off the GPIO block */
writel(0x00000000U, gpio->base + U300_GPIO_CR);
- err = gpiochip_remove(&gpio->chip);
- if (err < 0) {
- dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err);
- return err;
- }
+ gpiochip_remove(&gpio->chip);
clk_disable_unprepare(gpio->clk);
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index a24448e5d399..946d594a64dd 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -515,7 +515,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
/* Initialise function */
func->name = np->name;
func->num_groups = of_get_child_count(np);
- if (func->num_groups <= 0) {
+ if (func->num_groups == 0) {
dev_err(info->dev, "no groups defined in %s\n", np->full_name);
return -EINVAL;
}
diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/pinctrl-imx1-core.c
index 815384b377b5..483420757c9f 100644
--- a/drivers/pinctrl/pinctrl-imx1-core.c
+++ b/drivers/pinctrl/pinctrl-imx1-core.c
@@ -526,7 +526,7 @@ static int imx1_pinctrl_parse_functions(struct device_node *np,
/* Initialise function */
func->name = np->name;
func->num_groups = of_get_child_count(np);
- if (func->num_groups <= 0)
+ if (func->num_groups == 0)
return -EINVAL;
func->groups = devm_kzalloc(info->dev,
diff --git a/drivers/pinctrl/pinctrl-imx1.c b/drivers/pinctrl/pinctrl-imx1.c
new file mode 100644
index 000000000000..533a6e519648
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx1.c
@@ -0,0 +1,279 @@
+/*
+ * i.MX1 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2014 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx1.h"
+
+#define PAD_ID(port, pin) ((port) * 32 + (pin))
+#define PA 0
+#define PB 1
+#define PC 2
+#define PD 3
+
+enum imx1_pads {
+ MX1_PAD_A24 = PAD_ID(PA, 0),
+ MX1_PAD_TIN = PAD_ID(PA, 1),
+ MX1_PAD_PWMO = PAD_ID(PA, 2),
+ MX1_PAD_CSI_MCLK = PAD_ID(PA, 3),
+ MX1_PAD_CSI_D0 = PAD_ID(PA, 4),
+ MX1_PAD_CSI_D1 = PAD_ID(PA, 5),
+ MX1_PAD_CSI_D2 = PAD_ID(PA, 6),
+ MX1_PAD_CSI_D3 = PAD_ID(PA, 7),
+ MX1_PAD_CSI_D4 = PAD_ID(PA, 8),
+ MX1_PAD_CSI_D5 = PAD_ID(PA, 9),
+ MX1_PAD_CSI_D6 = PAD_ID(PA, 10),
+ MX1_PAD_CSI_D7 = PAD_ID(PA, 11),
+ MX1_PAD_CSI_VSYNC = PAD_ID(PA, 12),
+ MX1_PAD_CSI_HSYNC = PAD_ID(PA, 13),
+ MX1_PAD_CSI_PIXCLK = PAD_ID(PA, 14),
+ MX1_PAD_I2C_SDA = PAD_ID(PA, 15),
+ MX1_PAD_I2C_SCL = PAD_ID(PA, 16),
+ MX1_PAD_DTACK = PAD_ID(PA, 17),
+ MX1_PAD_BCLK = PAD_ID(PA, 18),
+ MX1_PAD_LBA = PAD_ID(PA, 19),
+ MX1_PAD_ECB = PAD_ID(PA, 20),
+ MX1_PAD_A0 = PAD_ID(PA, 21),
+ MX1_PAD_CS4 = PAD_ID(PA, 22),
+ MX1_PAD_CS5 = PAD_ID(PA, 23),
+ MX1_PAD_A16 = PAD_ID(PA, 24),
+ MX1_PAD_A17 = PAD_ID(PA, 25),
+ MX1_PAD_A18 = PAD_ID(PA, 26),
+ MX1_PAD_A19 = PAD_ID(PA, 27),
+ MX1_PAD_A20 = PAD_ID(PA, 28),
+ MX1_PAD_A21 = PAD_ID(PA, 29),
+ MX1_PAD_A22 = PAD_ID(PA, 30),
+ MX1_PAD_A23 = PAD_ID(PA, 31),
+ MX1_PAD_SD_DAT0 = PAD_ID(PB, 8),
+ MX1_PAD_SD_DAT1 = PAD_ID(PB, 9),
+ MX1_PAD_SD_DAT2 = PAD_ID(PB, 10),
+ MX1_PAD_SD_DAT3 = PAD_ID(PB, 11),
+ MX1_PAD_SD_SCLK = PAD_ID(PB, 12),
+ MX1_PAD_SD_CMD = PAD_ID(PB, 13),
+ MX1_PAD_SIM_SVEN = PAD_ID(PB, 14),
+ MX1_PAD_SIM_PD = PAD_ID(PB, 15),
+ MX1_PAD_SIM_TX = PAD_ID(PB, 16),
+ MX1_PAD_SIM_RX = PAD_ID(PB, 17),
+ MX1_PAD_SIM_RST = PAD_ID(PB, 18),
+ MX1_PAD_SIM_CLK = PAD_ID(PB, 19),
+ MX1_PAD_USBD_AFE = PAD_ID(PB, 20),
+ MX1_PAD_USBD_OE = PAD_ID(PB, 21),
+ MX1_PAD_USBD_RCV = PAD_ID(PB, 22),
+ MX1_PAD_USBD_SUSPND = PAD_ID(PB, 23),
+ MX1_PAD_USBD_VP = PAD_ID(PB, 24),
+ MX1_PAD_USBD_VM = PAD_ID(PB, 25),
+ MX1_PAD_USBD_VPO = PAD_ID(PB, 26),
+ MX1_PAD_USBD_VMO = PAD_ID(PB, 27),
+ MX1_PAD_UART2_CTS = PAD_ID(PB, 28),
+ MX1_PAD_UART2_RTS = PAD_ID(PB, 29),
+ MX1_PAD_UART2_TXD = PAD_ID(PB, 30),
+ MX1_PAD_UART2_RXD = PAD_ID(PB, 31),
+ MX1_PAD_SSI_RXFS = PAD_ID(PC, 3),
+ MX1_PAD_SSI_RXCLK = PAD_ID(PC, 4),
+ MX1_PAD_SSI_RXDAT = PAD_ID(PC, 5),
+ MX1_PAD_SSI_TXDAT = PAD_ID(PC, 6),
+ MX1_PAD_SSI_TXFS = PAD_ID(PC, 7),
+ MX1_PAD_SSI_TXCLK = PAD_ID(PC, 8),
+ MX1_PAD_UART1_CTS = PAD_ID(PC, 9),
+ MX1_PAD_UART1_RTS = PAD_ID(PC, 10),
+ MX1_PAD_UART1_TXD = PAD_ID(PC, 11),
+ MX1_PAD_UART1_RXD = PAD_ID(PC, 12),
+ MX1_PAD_SPI1_RDY = PAD_ID(PC, 13),
+ MX1_PAD_SPI1_SCLK = PAD_ID(PC, 14),
+ MX1_PAD_SPI1_SS = PAD_ID(PC, 15),
+ MX1_PAD_SPI1_MISO = PAD_ID(PC, 16),
+ MX1_PAD_SPI1_MOSI = PAD_ID(PC, 17),
+ MX1_PAD_BT13 = PAD_ID(PC, 19),
+ MX1_PAD_BT12 = PAD_ID(PC, 20),
+ MX1_PAD_BT11 = PAD_ID(PC, 21),
+ MX1_PAD_BT10 = PAD_ID(PC, 22),
+ MX1_PAD_BT9 = PAD_ID(PC, 23),
+ MX1_PAD_BT8 = PAD_ID(PC, 24),
+ MX1_PAD_BT7 = PAD_ID(PC, 25),
+ MX1_PAD_BT6 = PAD_ID(PC, 26),
+ MX1_PAD_BT5 = PAD_ID(PC, 27),
+ MX1_PAD_BT4 = PAD_ID(PC, 28),
+ MX1_PAD_BT3 = PAD_ID(PC, 29),
+ MX1_PAD_BT2 = PAD_ID(PC, 30),
+ MX1_PAD_BT1 = PAD_ID(PC, 31),
+ MX1_PAD_LSCLK = PAD_ID(PD, 6),
+ MX1_PAD_REV = PAD_ID(PD, 7),
+ MX1_PAD_CLS = PAD_ID(PD, 8),
+ MX1_PAD_PS = PAD_ID(PD, 9),
+ MX1_PAD_SPL_SPR = PAD_ID(PD, 10),
+ MX1_PAD_CONTRAST = PAD_ID(PD, 11),
+ MX1_PAD_ACD_OE = PAD_ID(PD, 12),
+ MX1_PAD_LP_HSYNC = PAD_ID(PD, 13),
+ MX1_PAD_FLM_VSYNC = PAD_ID(PD, 14),
+ MX1_PAD_LD0 = PAD_ID(PD, 15),
+ MX1_PAD_LD1 = PAD_ID(PD, 16),
+ MX1_PAD_LD2 = PAD_ID(PD, 17),
+ MX1_PAD_LD3 = PAD_ID(PD, 18),
+ MX1_PAD_LD4 = PAD_ID(PD, 19),
+ MX1_PAD_LD5 = PAD_ID(PD, 20),
+ MX1_PAD_LD6 = PAD_ID(PD, 21),
+ MX1_PAD_LD7 = PAD_ID(PD, 22),
+ MX1_PAD_LD8 = PAD_ID(PD, 23),
+ MX1_PAD_LD9 = PAD_ID(PD, 24),
+ MX1_PAD_LD10 = PAD_ID(PD, 25),
+ MX1_PAD_LD11 = PAD_ID(PD, 26),
+ MX1_PAD_LD12 = PAD_ID(PD, 27),
+ MX1_PAD_LD13 = PAD_ID(PD, 28),
+ MX1_PAD_LD14 = PAD_ID(PD, 29),
+ MX1_PAD_LD15 = PAD_ID(PD, 30),
+ MX1_PAD_TMR2OUT = PAD_ID(PD, 31),
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx1_pinctrl_pads[] = {
+ IMX_PINCTRL_PIN(MX1_PAD_A24),
+ IMX_PINCTRL_PIN(MX1_PAD_TIN),
+ IMX_PINCTRL_PIN(MX1_PAD_PWMO),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_MCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D0),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D1),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D2),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D3),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D4),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D5),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D6),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_D7),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_VSYNC),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_HSYNC),
+ IMX_PINCTRL_PIN(MX1_PAD_CSI_PIXCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_I2C_SDA),
+ IMX_PINCTRL_PIN(MX1_PAD_I2C_SCL),
+ IMX_PINCTRL_PIN(MX1_PAD_DTACK),
+ IMX_PINCTRL_PIN(MX1_PAD_BCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_LBA),
+ IMX_PINCTRL_PIN(MX1_PAD_ECB),
+ IMX_PINCTRL_PIN(MX1_PAD_A0),
+ IMX_PINCTRL_PIN(MX1_PAD_CS4),
+ IMX_PINCTRL_PIN(MX1_PAD_CS5),
+ IMX_PINCTRL_PIN(MX1_PAD_A16),
+ IMX_PINCTRL_PIN(MX1_PAD_A17),
+ IMX_PINCTRL_PIN(MX1_PAD_A18),
+ IMX_PINCTRL_PIN(MX1_PAD_A19),
+ IMX_PINCTRL_PIN(MX1_PAD_A20),
+ IMX_PINCTRL_PIN(MX1_PAD_A21),
+ IMX_PINCTRL_PIN(MX1_PAD_A22),
+ IMX_PINCTRL_PIN(MX1_PAD_A23),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_DAT0),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_DAT1),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_DAT2),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_DAT3),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_SCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_SD_CMD),
+ IMX_PINCTRL_PIN(MX1_PAD_SIM_SVEN),
+ IMX_PINCTRL_PIN(MX1_PAD_SIM_PD),
+ IMX_PINCTRL_PIN(MX1_PAD_SIM_TX),
+ IMX_PINCTRL_PIN(MX1_PAD_SIM_RX),
+ IMX_PINCTRL_PIN(MX1_PAD_SIM_CLK),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_AFE),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_OE),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_RCV),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_SUSPND),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_VP),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_VM),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_VPO),
+ IMX_PINCTRL_PIN(MX1_PAD_USBD_VMO),
+ IMX_PINCTRL_PIN(MX1_PAD_UART2_CTS),
+ IMX_PINCTRL_PIN(MX1_PAD_UART2_RTS),
+ IMX_PINCTRL_PIN(MX1_PAD_UART2_TXD),
+ IMX_PINCTRL_PIN(MX1_PAD_UART2_RXD),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_RXFS),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_RXCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_RXDAT),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_TXDAT),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_TXFS),
+ IMX_PINCTRL_PIN(MX1_PAD_SSI_TXCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_UART1_CTS),
+ IMX_PINCTRL_PIN(MX1_PAD_UART1_RTS),
+ IMX_PINCTRL_PIN(MX1_PAD_UART1_TXD),
+ IMX_PINCTRL_PIN(MX1_PAD_UART1_RXD),
+ IMX_PINCTRL_PIN(MX1_PAD_SPI1_RDY),
+ IMX_PINCTRL_PIN(MX1_PAD_SPI1_SCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_SPI1_SS),
+ IMX_PINCTRL_PIN(MX1_PAD_SPI1_MISO),
+ IMX_PINCTRL_PIN(MX1_PAD_SPI1_MOSI),
+ IMX_PINCTRL_PIN(MX1_PAD_BT13),
+ IMX_PINCTRL_PIN(MX1_PAD_BT12),
+ IMX_PINCTRL_PIN(MX1_PAD_BT11),
+ IMX_PINCTRL_PIN(MX1_PAD_BT10),
+ IMX_PINCTRL_PIN(MX1_PAD_BT9),
+ IMX_PINCTRL_PIN(MX1_PAD_BT8),
+ IMX_PINCTRL_PIN(MX1_PAD_BT7),
+ IMX_PINCTRL_PIN(MX1_PAD_BT6),
+ IMX_PINCTRL_PIN(MX1_PAD_BT5),
+ IMX_PINCTRL_PIN(MX1_PAD_BT4),
+ IMX_PINCTRL_PIN(MX1_PAD_BT3),
+ IMX_PINCTRL_PIN(MX1_PAD_BT2),
+ IMX_PINCTRL_PIN(MX1_PAD_BT1),
+ IMX_PINCTRL_PIN(MX1_PAD_LSCLK),
+ IMX_PINCTRL_PIN(MX1_PAD_REV),
+ IMX_PINCTRL_PIN(MX1_PAD_CLS),
+ IMX_PINCTRL_PIN(MX1_PAD_PS),
+ IMX_PINCTRL_PIN(MX1_PAD_SPL_SPR),
+ IMX_PINCTRL_PIN(MX1_PAD_CONTRAST),
+ IMX_PINCTRL_PIN(MX1_PAD_ACD_OE),
+ IMX_PINCTRL_PIN(MX1_PAD_LP_HSYNC),
+ IMX_PINCTRL_PIN(MX1_PAD_FLM_VSYNC),
+ IMX_PINCTRL_PIN(MX1_PAD_LD0),
+ IMX_PINCTRL_PIN(MX1_PAD_LD1),
+ IMX_PINCTRL_PIN(MX1_PAD_LD2),
+ IMX_PINCTRL_PIN(MX1_PAD_LD3),
+ IMX_PINCTRL_PIN(MX1_PAD_LD4),
+ IMX_PINCTRL_PIN(MX1_PAD_LD5),
+ IMX_PINCTRL_PIN(MX1_PAD_LD6),
+ IMX_PINCTRL_PIN(MX1_PAD_LD7),
+ IMX_PINCTRL_PIN(MX1_PAD_LD8),
+ IMX_PINCTRL_PIN(MX1_PAD_LD9),
+ IMX_PINCTRL_PIN(MX1_PAD_LD10),
+ IMX_PINCTRL_PIN(MX1_PAD_LD11),
+ IMX_PINCTRL_PIN(MX1_PAD_LD12),
+ IMX_PINCTRL_PIN(MX1_PAD_LD13),
+ IMX_PINCTRL_PIN(MX1_PAD_LD14),
+ IMX_PINCTRL_PIN(MX1_PAD_LD15),
+ IMX_PINCTRL_PIN(MX1_PAD_TMR2OUT),
+};
+
+static struct imx1_pinctrl_soc_info imx1_pinctrl_info = {
+ .pins = imx1_pinctrl_pads,
+ .npins = ARRAY_SIZE(imx1_pinctrl_pads),
+};
+
+static int __init imx1_pinctrl_probe(struct platform_device *pdev)
+{
+ return imx1_pinctrl_core_probe(pdev, &imx1_pinctrl_info);
+}
+
+static const struct of_device_id imx1_pinctrl_of_match[] = {
+ { .compatible = "fsl,imx1-iomuxc", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, imx1_pinctrl_of_match);
+
+static struct platform_driver imx1_pinctrl_driver = {
+ .driver = {
+ .name = "imx1-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = imx1_pinctrl_of_match,
+ },
+ .remove = imx1_pinctrl_core_remove,
+};
+module_platform_driver_probe(imx1_pinctrl_driver, imx1_pinctrl_probe);
+
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("Freescale i.MX1 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-imx27.c b/drivers/pinctrl/pinctrl-imx27.c
index 417c99205bc2..f8dfefb69968 100644
--- a/drivers/pinctrl/pinctrl-imx27.c
+++ b/drivers/pinctrl/pinctrl-imx27.c
@@ -63,10 +63,6 @@ enum imx27_pads {
MX27_PAD_CONTRAST = PAD_ID(PA, 30),
MX27_PAD_OE_ACD = PAD_ID(PA, 31),
- MX27_PAD_UNUSED0 = PAD_ID(PB, 0),
- MX27_PAD_UNUSED1 = PAD_ID(PB, 1),
- MX27_PAD_UNUSED2 = PAD_ID(PB, 2),
- MX27_PAD_UNUSED3 = PAD_ID(PB, 3),
MX27_PAD_SD2_D0 = PAD_ID(PB, 4),
MX27_PAD_SD2_D1 = PAD_ID(PB, 5),
MX27_PAD_SD2_D2 = PAD_ID(PB, 6),
@@ -96,11 +92,6 @@ enum imx27_pads {
MX27_PAD_USBH1_RXDM = PAD_ID(PB, 30),
MX27_PAD_USBH1_RXDP = PAD_ID(PB, 31),
- MX27_PAD_UNUSED4 = PAD_ID(PC, 0),
- MX27_PAD_UNUSED5 = PAD_ID(PC, 1),
- MX27_PAD_UNUSED6 = PAD_ID(PC, 2),
- MX27_PAD_UNUSED7 = PAD_ID(PC, 3),
- MX27_PAD_UNUSED8 = PAD_ID(PC, 4),
MX27_PAD_I2C2_SDA = PAD_ID(PC, 5),
MX27_PAD_I2C2_SCL = PAD_ID(PC, 6),
MX27_PAD_USBOTG_DATA5 = PAD_ID(PC, 7),
@@ -188,12 +179,6 @@ enum imx27_pads {
MX27_PAD_SD1_CLK = PAD_ID(PE, 23),
MX27_PAD_USBOTG_CLK = PAD_ID(PE, 24),
MX27_PAD_USBOTG_DATA7 = PAD_ID(PE, 25),
- MX27_PAD_UNUSED9 = PAD_ID(PE, 26),
- MX27_PAD_UNUSED10 = PAD_ID(PE, 27),
- MX27_PAD_UNUSED11 = PAD_ID(PE, 28),
- MX27_PAD_UNUSED12 = PAD_ID(PE, 29),
- MX27_PAD_UNUSED13 = PAD_ID(PE, 30),
- MX27_PAD_UNUSED14 = PAD_ID(PE, 31),
MX27_PAD_NFRB = PAD_ID(PF, 0),
MX27_PAD_NFCLE = PAD_ID(PF, 1),
@@ -219,14 +204,6 @@ enum imx27_pads {
MX27_PAD_CS4_B = PAD_ID(PF, 21),
MX27_PAD_CS5_B = PAD_ID(PF, 22),
MX27_PAD_ATA_DATA15 = PAD_ID(PF, 23),
- MX27_PAD_UNUSED15 = PAD_ID(PF, 24),
- MX27_PAD_UNUSED16 = PAD_ID(PF, 25),
- MX27_PAD_UNUSED17 = PAD_ID(PF, 26),
- MX27_PAD_UNUSED18 = PAD_ID(PF, 27),
- MX27_PAD_UNUSED19 = PAD_ID(PF, 28),
- MX27_PAD_UNUSED20 = PAD_ID(PF, 29),
- MX27_PAD_UNUSED21 = PAD_ID(PF, 30),
- MX27_PAD_UNUSED22 = PAD_ID(PF, 31),
};
/* Pad names for the pinmux subsystem */
@@ -264,10 +241,6 @@ static const struct pinctrl_pin_desc imx27_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX27_PAD_CONTRAST),
IMX_PINCTRL_PIN(MX27_PAD_OE_ACD),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED0),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED1),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED2),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED3),
IMX_PINCTRL_PIN(MX27_PAD_SD2_D0),
IMX_PINCTRL_PIN(MX27_PAD_SD2_D1),
IMX_PINCTRL_PIN(MX27_PAD_SD2_D2),
@@ -297,11 +270,6 @@ static const struct pinctrl_pin_desc imx27_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDM),
IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDP),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED4),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED5),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED6),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED7),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED8),
IMX_PINCTRL_PIN(MX27_PAD_I2C2_SDA),
IMX_PINCTRL_PIN(MX27_PAD_I2C2_SCL),
IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA5),
@@ -389,12 +357,6 @@ static const struct pinctrl_pin_desc imx27_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX27_PAD_SD1_CLK),
IMX_PINCTRL_PIN(MX27_PAD_USBOTG_CLK),
IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA7),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED9),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED10),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED11),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED12),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED13),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED14),
IMX_PINCTRL_PIN(MX27_PAD_NFRB),
IMX_PINCTRL_PIN(MX27_PAD_NFCLE),
@@ -420,14 +382,6 @@ static const struct pinctrl_pin_desc imx27_pinctrl_pads[] = {
IMX_PINCTRL_PIN(MX27_PAD_CS4_B),
IMX_PINCTRL_PIN(MX27_PAD_CS5_B),
IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA15),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED15),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED16),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED17),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED18),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED19),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED20),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED21),
- IMX_PINCTRL_PIN(MX27_PAD_UNUSED22),
};
static struct imx1_pinctrl_soc_info imx27_pinctrl_info = {
@@ -440,12 +394,6 @@ static struct of_device_id imx27_pinctrl_of_match[] = {
{ /* sentinel */ }
};
-struct imx27_pinctrl_private {
- int num_gpio_childs;
- struct platform_device **gpio_dev;
- struct mxc_gpio_platform_data *gpio_pdata;
-};
-
static int imx27_pinctrl_probe(struct platform_device *pdev)
{
return imx1_pinctrl_core_probe(pdev, &imx27_pinctrl_info);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index bb805d5e9ff0..5e8b2e04cd7a 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -62,11 +62,26 @@ enum rockchip_pinctrl_type {
RK2928,
RK3066B,
RK3188,
+ RK3288,
};
-enum rockchip_pin_bank_type {
- COMMON_BANK,
- RK3188_BANK0,
+/**
+ * Encode variants of iomux registers into a type variable
+ */
+#define IOMUX_GPIO_ONLY BIT(0)
+#define IOMUX_WIDTH_4BIT BIT(1)
+#define IOMUX_SOURCE_PMU BIT(2)
+#define IOMUX_UNROUTED BIT(3)
+
+/**
+ * @type: iomux variant using IOMUX_* constants
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ * an initial offset value the relevant source offset can be reset
+ * to a new value for autocalculating the following iomux registers.
+ */
+struct rockchip_iomux {
+ int type;
+ int offset;
};
/**
@@ -78,6 +93,7 @@ enum rockchip_pin_bank_type {
* @nr_pins: number of pins in this bank
* @name: name of the bank
* @bank_num: number of the bank, to account for holes
+ * @iomux: array describing the 4 iomux sources of the bank
* @valid: are all necessary informations present
* @of_node: dt node of this bank
* @drvdata: common pinctrl basedata
@@ -95,7 +111,7 @@ struct rockchip_pin_bank {
u8 nr_pins;
char *name;
u8 bank_num;
- enum rockchip_pin_bank_type bank_type;
+ struct rockchip_iomux iomux[4];
bool valid;
struct device_node *of_node;
struct rockchip_pinctrl *drvdata;
@@ -111,6 +127,25 @@ struct rockchip_pin_bank {
.bank_num = id, \
.nr_pins = pins, \
.name = label, \
+ .iomux = { \
+ { .offset = -1 }, \
+ { .offset = -1 }, \
+ { .offset = -1 }, \
+ { .offset = -1 }, \
+ }, \
+ }
+
+#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \
+ { \
+ .bank_num = id, \
+ .nr_pins = pins, \
+ .name = label, \
+ .iomux = { \
+ { .type = iom0, .offset = -1 }, \
+ { .type = iom1, .offset = -1 }, \
+ { .type = iom2, .offset = -1 }, \
+ { .type = iom3, .offset = -1 }, \
+ }, \
}
/**
@@ -121,7 +156,8 @@ struct rockchip_pin_ctrl {
u32 nr_pins;
char *label;
enum rockchip_pinctrl_type type;
- int mux_offset;
+ int grf_mux_offset;
+ int pmu_mux_offset;
void (*pull_calc_reg)(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit);
@@ -343,24 +379,42 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
{
struct rockchip_pinctrl *info = bank->drvdata;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
unsigned int val;
- int reg, ret;
+ int reg, ret, mask;
u8 bit;
- if (bank->bank_type == RK3188_BANK0 && pin < 16)
+ if (iomux_num > 3)
+ return -EINVAL;
+
+ if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+ dev_err(info->dev, "pin %d is unrouted\n", pin);
+ return -EINVAL;
+ }
+
+ if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
return RK_FUNC_GPIO;
+ regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+ ? info->regmap_pmu : info->regmap_base;
+
/* get basic quadrupel of mux registers and the correct reg inside */
- reg = info->ctrl->mux_offset;
- reg += bank->bank_num * 0x10;
- reg += (pin / 8) * 4;
- bit = (pin % 8) * 2;
+ mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+ reg = bank->iomux[iomux_num].offset;
+ if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ } else {
+ bit = (pin % 8) * 2;
+ }
- ret = regmap_read(info->regmap_base, reg, &val);
+ ret = regmap_read(regmap, reg, &val);
if (ret)
return ret;
- return ((val >> bit) & 3);
+ return ((val >> bit) & mask);
}
/*
@@ -379,16 +433,22 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{
struct rockchip_pinctrl *info = bank->drvdata;
- int reg, ret;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ int reg, ret, mask;
unsigned long flags;
u8 bit;
u32 data;
- /*
- * The first 16 pins of rk3188_bank0 are always gpios and do not have
- * a mux register at all.
- */
- if (bank->bank_type == RK3188_BANK0 && pin < 16) {
+ if (iomux_num > 3)
+ return -EINVAL;
+
+ if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
+ dev_err(info->dev, "pin %d is unrouted\n", pin);
+ return -EINVAL;
+ }
+
+ if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
if (mux != RK_FUNC_GPIO) {
dev_err(info->dev,
"pin %d only supports a gpio mux\n", pin);
@@ -401,17 +461,25 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n",
bank->bank_num, pin, mux);
+ regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+ ? info->regmap_pmu : info->regmap_base;
+
/* get basic quadrupel of mux registers and the correct reg inside */
- reg = info->ctrl->mux_offset;
- reg += bank->bank_num * 0x10;
- reg += (pin / 8) * 4;
- bit = (pin % 8) * 2;
+ mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3;
+ reg = bank->iomux[iomux_num].offset;
+ if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) {
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ } else {
+ bit = (pin % 8) * 2;
+ }
spin_lock_irqsave(&bank->slock, flags);
- data = (3 << (bit + 16));
- data |= (mux & 3) << bit;
- ret = regmap_write(info->regmap_base, reg, data);
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
spin_unlock_irqrestore(&bank->slock, flags);
@@ -449,7 +517,7 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
struct rockchip_pinctrl *info = bank->drvdata;
/* The first 12 pins of the first bank are located elsewhere */
- if (bank->bank_type == RK3188_BANK0 && pin_num < 12) {
+ if (bank->bank_num == 0 && pin_num < 12) {
*regmap = info->regmap_pmu ? info->regmap_pmu
: bank->regmap_pull;
*reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0;
@@ -476,6 +544,127 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
}
}
+#define RK3288_PULL_OFFSET 0x140
+static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ *regmap = info->regmap_pmu;
+ *reg = RK3188_PULL_PMU_OFFSET;
+
+ *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3188_PULL_PINS_PER_REG;
+ *bit *= RK3188_PULL_BITS_PER_PIN;
+ } else {
+ *regmap = info->regmap_base;
+ *reg = RK3288_PULL_OFFSET;
+
+ /* correct the offset, as we're starting with the 2nd bank */
+ *reg -= 0x10;
+ *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+ *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+ *bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+ *bit *= RK3188_PULL_BITS_PER_PIN;
+ }
+}
+
+#define RK3288_DRV_PMU_OFFSET 0x70
+#define RK3288_DRV_GRF_OFFSET 0x1c0
+#define RK3288_DRV_BITS_PER_PIN 2
+#define RK3288_DRV_PINS_PER_REG 8
+#define RK3288_DRV_BANK_STRIDE 16
+static int rk3288_drv_list[] = { 2, 4, 8, 12 };
+
+static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ *regmap = info->regmap_pmu;
+ *reg = RK3288_DRV_PMU_OFFSET;
+
+ *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RK3288_DRV_PINS_PER_REG;
+ *bit *= RK3288_DRV_BITS_PER_PIN;
+ } else {
+ *regmap = info->regmap_base;
+ *reg = RK3288_DRV_GRF_OFFSET;
+
+ /* correct the offset, as we're starting with the 2nd bank */
+ *reg -= 0x10;
+ *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+ *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+ *bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+ *bit *= RK3288_DRV_BITS_PER_PIN;
+ }
+}
+
+static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
+{
+ struct regmap *regmap;
+ int reg, ret;
+ u32 data;
+ u8 bit;
+
+ rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ ret = regmap_read(regmap, reg, &data);
+ if (ret)
+ return ret;
+
+ data >>= bit;
+ data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
+
+ return rk3288_drv_list[data];
+}
+
+static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
+ int strength)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+ struct regmap *regmap;
+ unsigned long flags;
+ int reg, ret, i;
+ u32 data;
+ u8 bit;
+
+ rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+ ret = -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) {
+ if (rk3288_drv_list[i] == strength) {
+ ret = i;
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ dev_err(info->dev, "unsupported driver strength %d\n",
+ strength);
+ return ret;
+ }
+
+ spin_lock_irqsave(&bank->slock, flags);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (ret << bit);
+
+ ret = regmap_write(regmap, reg, data);
+ spin_unlock_irqrestore(&bank->slock, flags);
+
+ return ret;
+}
+
static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
{
struct rockchip_pinctrl *info = bank->drvdata;
@@ -501,6 +690,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE;
case RK3188:
+ case RK3288:
data >>= bit;
data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
@@ -555,6 +745,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
spin_unlock_irqrestore(&bank->slock, flags);
break;
case RK3188:
+ case RK3288:
spin_lock_irqsave(&bank->slock, flags);
/* enable the write to the equivalent lower bits */
@@ -657,23 +848,6 @@ static int rockchip_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
-static void rockchip_pmx_disable(struct pinctrl_dev *pctldev,
- unsigned selector, unsigned group)
-{
- struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
- const unsigned int *pins = info->groups[group].pins;
- struct rockchip_pin_bank *bank;
- int cnt;
-
- dev_dbg(info->dev, "disable function %s group %s\n",
- info->functions[selector].name, info->groups[group].name);
-
- for (cnt = 0; cnt < info->groups[group].npins; cnt++) {
- bank = pin_to_bank(info, pins[cnt]);
- rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
- }
-}
-
/*
* The calls to gpio_direction_output() and gpio_direction_input()
* leads to this function call (via the pinctrl_gpio_direction_{input|output}()
@@ -716,7 +890,6 @@ static const struct pinmux_ops rockchip_pmx_ops = {
.get_function_name = rockchip_pmx_get_func_name,
.get_function_groups = rockchip_pmx_get_groups,
.enable = rockchip_pmx_enable,
- .disable = rockchip_pmx_disable,
.gpio_set_direction = rockchip_pmx_gpio_set_direction,
};
@@ -734,6 +907,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
case RK3066B:
return pull ? false : true;
case RK3188:
+ case RK3288:
return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
}
@@ -788,6 +962,15 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
if (rc)
return rc;
break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* rk3288 is the first with per-pin drive-strength */
+ if (info->ctrl->type != RK3288)
+ return -ENOTSUPP;
+
+ rc = rk3288_set_drive(bank, pin - bank->pin_base, arg);
+ if (rc < 0)
+ return rc;
+ break;
default:
return -ENOTSUPP;
break;
@@ -837,6 +1020,17 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
arg = rc ? 1 : 0;
break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* rk3288 is the first with per-pin drive-strength */
+ if (info->ctrl->type != RK3288)
+ return -ENOTSUPP;
+
+ rc = rk3288_get_drive(bank, pin - bank->pin_base);
+ if (rc < 0)
+ return rc;
+
+ arg = rc;
+ break;
default:
return -ENOTSUPP;
break;
@@ -850,6 +1044,7 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
static const struct pinconf_ops rockchip_pinconf_ops = {
.pin_config_get = rockchip_pinconf_get,
.pin_config_set = rockchip_pinconf_set,
+ .is_generic = true,
};
static const struct of_device_id rockchip_bank_match[] = {
@@ -1414,10 +1609,7 @@ fail:
for (--i, --bank; i >= 0; --i, --bank) {
if (!bank->valid)
continue;
-
- if (gpiochip_remove(&bank->gpio_chip))
- dev_err(&pdev->dev, "gpio chip %s remove failed\n",
- bank->gpio_chip.label);
+ gpiochip_remove(&bank->gpio_chip);
}
return ret;
}
@@ -1427,20 +1619,15 @@ static int rockchip_gpiolib_unregister(struct platform_device *pdev,
{
struct rockchip_pin_ctrl *ctrl = info->ctrl;
struct rockchip_pin_bank *bank = ctrl->pin_banks;
- int ret = 0;
int i;
- for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank) {
+ for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
if (!bank->valid)
continue;
-
- ret = gpiochip_remove(&bank->gpio_chip);
+ gpiochip_remove(&bank->gpio_chip);
}
- if (ret)
- dev_err(&pdev->dev, "gpio chip remove failed\n");
-
- return ret;
+ return 0;
}
static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
@@ -1466,8 +1653,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
"rockchip,rk3188-gpio-bank0")) {
struct device_node *node;
- bank->bank_type = RK3188_BANK0;
-
node = of_parse_phandle(bank->of_node->parent,
"rockchip,pmu", 0);
if (!node) {
@@ -1487,9 +1672,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank,
base,
&rockchip_regmap_config);
}
-
- } else {
- bank->bank_type = COMMON_BANK;
}
bank->irq = irq_of_parse_and_map(bank->of_node, 0);
@@ -1513,7 +1695,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
struct device_node *np;
struct rockchip_pin_ctrl *ctrl;
struct rockchip_pin_bank *bank;
- int i;
+ int grf_offs, pmu_offs, i, j;
match = of_match_node(rockchip_pinctrl_dt_match, node);
ctrl = (struct rockchip_pin_ctrl *)match->data;
@@ -1535,12 +1717,51 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
}
}
+ grf_offs = ctrl->grf_mux_offset;
+ pmu_offs = ctrl->pmu_mux_offset;
bank = ctrl->pin_banks;
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+ int bank_pins = 0;
+
spin_lock_init(&bank->slock);
bank->drvdata = d;
bank->pin_base = ctrl->nr_pins;
ctrl->nr_pins += bank->nr_pins;
+
+ /* calculate iomux offsets */
+ for (j = 0; j < 4; j++) {
+ struct rockchip_iomux *iom = &bank->iomux[j];
+ int inc;
+
+ if (bank_pins >= bank->nr_pins)
+ break;
+
+ /* preset offset value, set new start value */
+ if (iom->offset >= 0) {
+ if (iom->type & IOMUX_SOURCE_PMU)
+ pmu_offs = iom->offset;
+ else
+ grf_offs = iom->offset;
+ } else { /* set current offset */
+ iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
+ pmu_offs : grf_offs;
+ }
+
+ dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n",
+ i, j, iom->offset);
+
+ /*
+ * Increase offset according to iomux width.
+ * 4bit iomux'es are spread over two registers.
+ */
+ inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4;
+ if (iom->type & IOMUX_SOURCE_PMU)
+ pmu_offs += inc;
+ else
+ grf_offs += inc;
+
+ bank_pins += 8;
+ }
}
return ctrl;
@@ -1644,7 +1865,7 @@ static struct rockchip_pin_ctrl rk2928_pin_ctrl = {
.nr_banks = ARRAY_SIZE(rk2928_pin_banks),
.label = "RK2928-GPIO",
.type = RK2928,
- .mux_offset = 0xa8,
+ .grf_mux_offset = 0xa8,
.pull_calc_reg = rk2928_calc_pull_reg_and_bit,
};
@@ -1662,7 +1883,7 @@ static struct rockchip_pin_ctrl rk3066a_pin_ctrl = {
.nr_banks = ARRAY_SIZE(rk3066a_pin_banks),
.label = "RK3066a-GPIO",
.type = RK2928,
- .mux_offset = 0xa8,
+ .grf_mux_offset = 0xa8,
.pull_calc_reg = rk2928_calc_pull_reg_and_bit,
};
@@ -1678,11 +1899,11 @@ static struct rockchip_pin_ctrl rk3066b_pin_ctrl = {
.nr_banks = ARRAY_SIZE(rk3066b_pin_banks),
.label = "RK3066b-GPIO",
.type = RK3066B,
- .mux_offset = 0x60,
+ .grf_mux_offset = 0x60,
};
static struct rockchip_pin_bank rk3188_pin_banks[] = {
- PIN_BANK(0, 32, "gpio0"),
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0),
PIN_BANK(1, 32, "gpio1"),
PIN_BANK(2, 32, "gpio2"),
PIN_BANK(3, 32, "gpio3"),
@@ -1693,10 +1914,52 @@ static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
.nr_banks = ARRAY_SIZE(rk3188_pin_banks),
.label = "RK3188-GPIO",
.type = RK3188,
- .mux_offset = 0x60,
+ .grf_mux_offset = 0x60,
.pull_calc_reg = rk3188_calc_pull_reg_and_bit,
};
+static struct rockchip_pin_bank rk3288_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
+ IOMUX_SOURCE_PMU,
+ IOMUX_SOURCE_PMU,
+ IOMUX_UNROUTED
+ ),
+ PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED,
+ IOMUX_UNROUTED,
+ IOMUX_UNROUTED,
+ 0
+ ),
+ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED),
+ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT),
+ PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0,
+ 0
+ ),
+ PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED,
+ 0,
+ 0,
+ IOMUX_UNROUTED
+ ),
+ PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED),
+ PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0,
+ 0,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_UNROUTED
+ ),
+ PIN_BANK(8, 16, "gpio8"),
+};
+
+static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
+ .pin_banks = rk3288_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3288_pin_banks),
+ .label = "RK3288-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
+ .pmu_mux_offset = 0x84,
+ .pull_calc_reg = rk3288_calc_pull_reg_and_bit,
+};
+
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
{ .compatible = "rockchip,rk2928-pinctrl",
.data = (void *)&rk2928_pin_ctrl },
@@ -1706,6 +1969,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
.data = (void *)&rk3066b_pin_ctrl },
{ .compatible = "rockchip,rk3188-pinctrl",
.data = (void *)&rk3188_pin_ctrl },
+ { .compatible = "rockchip,rk3288-pinctrl",
+ .data = (void *)&rk3288_pin_ctrl },
{},
};
MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 2960557bfed9..95dd9cf55cb3 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -488,61 +488,6 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
return 0;
}
-static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
- unsigned group)
-{
- struct pcs_device *pcs;
- struct pcs_function *func;
- int i;
-
- pcs = pinctrl_dev_get_drvdata(pctldev);
- /* If function mask is null, needn't disable it. */
- if (!pcs->fmask)
- return;
-
- func = radix_tree_lookup(&pcs->ftree, fselector);
- if (!func) {
- dev_err(pcs->dev, "%s could not find function%i\n",
- __func__, fselector);
- return;
- }
-
- /*
- * Ignore disable if function-off is not specified. Some hardware
- * does not have clearly defined disable function. For pin specific
- * off modes, you can use alternate named states as described in
- * pinctrl-bindings.txt.
- */
- if (pcs->foff == PCS_OFF_DISABLED) {
- dev_dbg(pcs->dev, "ignoring disable for %s function%i\n",
- func->name, fselector);
- return;
- }
-
- dev_dbg(pcs->dev, "disabling function%i %s\n",
- fselector, func->name);
-
- for (i = 0; i < func->nvals; i++) {
- struct pcs_func_vals *vals;
- unsigned long flags;
- unsigned val, mask;
-
- vals = &func->vals[i];
- raw_spin_lock_irqsave(&pcs->lock, flags);
- val = pcs->read(vals->reg);
-
- if (pcs->bits_per_mux)
- mask = vals->mask;
- else
- mask = pcs->fmask;
-
- val &= ~mask;
- val |= pcs->foff << pcs->fshift;
- pcs->write(val, vals->reg);
- raw_spin_unlock_irqrestore(&pcs->lock, flags);
- }
-}
-
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned pin)
{
@@ -575,7 +520,6 @@ static const struct pinmux_ops pcs_pinmux_ops = {
.get_function_name = pcs_get_function_name,
.get_function_groups = pcs_get_function_groups,
.enable = pcs_enable,
- .disable = pcs_disable,
.gpio_request_enable = pcs_request_gpio,
};
@@ -836,7 +780,7 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
pin = &pcs->pins.pa[i];
pn = &pcs->names[i];
- sprintf(pn->name, "%lx.%d",
+ sprintf(pn->name, "%lx.%u",
(unsigned long)pcs->res->start + offset, pin_pos);
pin->name = pn->name;
pin->number = i;
@@ -1739,11 +1683,10 @@ static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
{
struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
struct irq_chip *chip;
- int res;
chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
- res = pcs_irq_handle(pcs_soc);
+ pcs_irq_handle(pcs_soc);
/* REVISIT: export and add handle_bad_irq(irq, desc)? */
chained_irq_exit(chip, desc);
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 9f43916637ca..5475374d803f 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -930,11 +930,6 @@ static int st_pmx_enable(struct pinctrl_dev *pctldev, unsigned fselector,
return 0;
}
-static void st_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
- unsigned group)
-{
-}
-
static int st_pmx_set_gpio_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned gpio,
bool input)
@@ -957,7 +952,6 @@ static struct pinmux_ops st_pmxops = {
.get_function_name = st_pmx_get_fname,
.get_function_groups = st_pmx_get_groups,
.enable = st_pmx_enable,
- .disable = st_pmx_disable,
.gpio_set_direction = st_pmx_set_gpio_direction,
};
@@ -1178,9 +1172,7 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
const __be32 *list;
struct property *pp;
struct st_pinconf *conf;
- phandle phandle;
struct device_node *pins;
- u32 pin;
int i = 0, npins = 0, nr_props;
pins = of_get_child_by_name(np, "st,pins");
@@ -1218,8 +1210,8 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
conf = &grp->pin_conf[i];
/* bank & offset */
- phandle = be32_to_cpup(list++);
- pin = be32_to_cpup(list++);
+ be32_to_cpup(list++);
+ be32_to_cpup(list++);
conf->pin = of_get_named_gpio(pins, pp->name, 0);
conf->name = pp->name;
grp->pins[i] = conf->pin;
@@ -1256,7 +1248,7 @@ static int st_pctl_parse_functions(struct device_node *np,
func = &info->functions[index];
func->name = np->name;
func->ngroups = of_get_child_count(np);
- if (func->ngroups <= 0) {
+ if (func->ngroups == 0) {
dev_err(info->dev, "No groups defined\n");
return -EINVAL;
}
@@ -1454,6 +1446,7 @@ static struct irq_chip st_gpio_irqchip = {
.irq_mask = st_gpio_irq_mask,
.irq_unmask = st_gpio_irq_unmask,
.irq_set_type = st_gpio_irq_set_type,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
};
static int st_gpiolib_register_bank(struct st_pinctrl *info,
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index 26ca6855f478..71c5d4f0c538 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -738,22 +738,6 @@ static int tb10x_pctl_enable(struct pinctrl_dev *pctl,
return 0;
}
-static void tb10x_pctl_disable(struct pinctrl_dev *pctl,
- unsigned func_selector, unsigned group_selector)
-{
- struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
- const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
-
- if (grp->port < 0)
- return;
-
- mutex_lock(&state->mutex);
-
- state->ports[grp->port].count--;
-
- mutex_unlock(&state->mutex);
-}
-
static struct pinmux_ops tb10x_pinmux_ops = {
.get_functions_count = tb10x_get_functions_count,
.get_function_name = tb10x_get_function_name,
@@ -761,7 +745,6 @@ static struct pinmux_ops tb10x_pinmux_ops = {
.gpio_request_enable = tb10x_gpio_request_enable,
.gpio_disable_free = tb10x_gpio_disable_free,
.enable = tb10x_pctl_enable,
- .disable = tb10x_pctl_disable,
};
static struct pinctrl_desc tb10x_pindesc = {
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
new file mode 100644
index 000000000000..a06620474845
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -0,0 +1,973 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+struct tegra_xusb_padctl_function {
+ const char *name;
+ const char * const *groups;
+ unsigned int num_groups;
+};
+
+struct tegra_xusb_padctl_group {
+ const unsigned int *funcs;
+ unsigned int num_funcs;
+};
+
+struct tegra_xusb_padctl_soc {
+ const struct pinctrl_pin_desc *pins;
+ unsigned int num_pins;
+
+ const struct tegra_xusb_padctl_function *functions;
+ unsigned int num_functions;
+
+ const struct tegra_xusb_padctl_lane *lanes;
+ unsigned int num_lanes;
+};
+
+struct tegra_xusb_padctl_lane {
+ const char *name;
+
+ unsigned int offset;
+ unsigned int shift;
+ unsigned int mask;
+ unsigned int iddq;
+
+ const unsigned int *funcs;
+ unsigned int num_funcs;
+};
+
+struct tegra_xusb_padctl {
+ struct device *dev;
+ void __iomem *regs;
+ struct mutex lock;
+ struct reset_control *rst;
+
+ const struct tegra_xusb_padctl_soc *soc;
+ struct pinctrl_dev *pinctrl;
+ struct pinctrl_desc desc;
+
+ struct phy_provider *provider;
+ struct phy *phys[2];
+
+ unsigned int enable;
+};
+
+static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
+ unsigned long offset)
+{
+ writel(value, padctl->regs + offset);
+}
+
+static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
+ unsigned long offset)
+{
+ return readl(padctl->regs + offset);
+}
+
+static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+ return padctl->soc->num_pins;
+}
+
+static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
+ unsigned int group)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+ return padctl->soc->pins[group].name;
+}
+
+enum tegra_xusb_padctl_param {
+ TEGRA_XUSB_PADCTL_IDDQ,
+};
+
+static const struct tegra_xusb_padctl_property {
+ const char *name;
+ enum tegra_xusb_padctl_param param;
+} properties[] = {
+ { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
+};
+
+#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
+#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
+#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
+
+static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
+ struct device_node *np,
+ struct pinctrl_map **maps,
+ unsigned int *reserved_maps,
+ unsigned int *num_maps)
+{
+ unsigned int i, reserve = 0, num_configs = 0;
+ unsigned long config, *configs = NULL;
+ const char *function, *group;
+ struct property *prop;
+ int err = 0;
+ u32 value;
+
+ err = of_property_read_string(np, "nvidia,function", &function);
+ if (err < 0) {
+ if (err != -EINVAL)
+ return err;
+
+ function = NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(properties); i++) {
+ err = of_property_read_u32(np, properties[i].name, &value);
+ if (err < 0) {
+ if (err == -EINVAL)
+ continue;
+
+ return err;
+ }
+
+ config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
+
+ err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
+ &num_configs, config);
+ if (err < 0)
+ return err;
+ }
+
+ if (function)
+ reserve++;
+
+ if (num_configs)
+ reserve++;
+
+ err = of_property_count_strings(np, "nvidia,lanes");
+ if (err < 0)
+ return err;
+
+ reserve *= err;
+
+ err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
+ num_maps, reserve);
+ if (err < 0)
+ return err;
+
+ of_property_for_each_string(np, "nvidia,lanes", prop, group) {
+ if (function) {
+ err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
+ reserved_maps, num_maps, group,
+ function);
+ if (err < 0)
+ return err;
+ }
+
+ if (num_configs) {
+ err = pinctrl_utils_add_map_configs(padctl->pinctrl,
+ maps, reserved_maps, num_maps, group,
+ configs, num_configs,
+ PIN_MAP_TYPE_CONFIGS_GROUP);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
+ struct device_node *parent,
+ struct pinctrl_map **maps,
+ unsigned int *num_maps)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+ unsigned int reserved_maps = 0;
+ struct device_node *np;
+ int err;
+
+ *num_maps = 0;
+ *maps = NULL;
+
+ for_each_child_of_node(parent, np) {
+ err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
+ &reserved_maps,
+ num_maps);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
+ .get_groups_count = tegra_xusb_padctl_get_groups_count,
+ .get_group_name = tegra_xusb_padctl_get_group_name,
+ .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
+ .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+ return padctl->soc->num_functions;
+}
+
+static const char *
+tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
+ unsigned int function)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+ return padctl->soc->functions[function].name;
+}
+
+static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
+ unsigned int function,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+ *num_groups = padctl->soc->functions[function].num_groups;
+ *groups = padctl->soc->functions[function].groups;
+
+ return 0;
+}
+
+static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl,
+ unsigned int function,
+ unsigned int group)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+ const struct tegra_xusb_padctl_lane *lane;
+ unsigned int i;
+ u32 value;
+
+ lane = &padctl->soc->lanes[group];
+
+ for (i = 0; i < lane->num_funcs; i++)
+ if (lane->funcs[i] == function)
+ break;
+
+ if (i >= lane->num_funcs)
+ return -EINVAL;
+
+ value = padctl_readl(padctl, lane->offset);
+ value &= ~(lane->mask << lane->shift);
+ value |= i << lane->shift;
+ padctl_writel(padctl, value, lane->offset);
+
+ return 0;
+}
+
+static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
+ .get_functions_count = tegra_xusb_padctl_get_functions_count,
+ .get_function_name = tegra_xusb_padctl_get_function_name,
+ .get_function_groups = tegra_xusb_padctl_get_function_groups,
+ .enable = tegra_xusb_padctl_pinmux_enable,
+};
+
+static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
+ unsigned int group,
+ unsigned long *config)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+ const struct tegra_xusb_padctl_lane *lane;
+ enum tegra_xusb_padctl_param param;
+ u32 value;
+
+ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
+ lane = &padctl->soc->lanes[group];
+
+ switch (param) {
+ case TEGRA_XUSB_PADCTL_IDDQ:
+ /* lanes with iddq == 0 don't support this parameter */
+ if (lane->iddq == 0)
+ return -EINVAL;
+
+ value = padctl_readl(padctl, lane->offset);
+
+ if (value & BIT(lane->iddq))
+ value = 0;
+ else
+ value = 1;
+
+ *config = TEGRA_XUSB_PADCTL_PACK(param, value);
+ break;
+
+ default:
+ dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
+ param);
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
+ unsigned int group,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+ const struct tegra_xusb_padctl_lane *lane;
+ enum tegra_xusb_padctl_param param;
+ unsigned long value;
+ unsigned int i;
+ u32 regval;
+
+ lane = &padctl->soc->lanes[group];
+
+ for (i = 0; i < num_configs; i++) {
+ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
+ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
+
+ switch (param) {
+ case TEGRA_XUSB_PADCTL_IDDQ:
+ /* lanes with iddq == 0 don't support this parameter */
+ if (lane->iddq == 0)
+ return -EINVAL;
+
+ regval = padctl_readl(padctl, lane->offset);
+
+ if (value)
+ regval &= ~BIT(lane->iddq);
+ else
+ regval |= BIT(lane->iddq);
+
+ padctl_writel(padctl, regval, lane->offset);
+ break;
+
+ default:
+ dev_err(padctl->dev,
+ "invalid configuration parameter: %04x\n",
+ param);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const char *strip_prefix(const char *s)
+{
+ const char *comma = strchr(s, ',');
+ if (!comma)
+ return s;
+
+ return comma + 1;
+}
+
+static void
+tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
+ struct seq_file *s,
+ unsigned int group)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(properties); i++) {
+ unsigned long config, value;
+ int err;
+
+ config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
+
+ err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
+ &config);
+ if (err < 0)
+ continue;
+
+ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+ seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
+ value);
+ }
+}
+
+static void
+tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
+ struct seq_file *s,
+ unsigned long config)
+{
+ enum tegra_xusb_padctl_param param;
+ const char *name = "unknown";
+ unsigned long value;
+ unsigned int i;
+
+ param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
+ value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+ for (i = 0; i < ARRAY_SIZE(properties); i++) {
+ if (properties[i].param == param) {
+ name = properties[i].name;
+ break;
+ }
+ }
+
+ seq_printf(s, "%s=%lu", strip_prefix(name), value);
+}
+#endif
+
+static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
+ .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
+ .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+ .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
+ .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
+#endif
+};
+
+static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+{
+ u32 value;
+
+ mutex_lock(&padctl->lock);
+
+ if (padctl->enable++ > 0)
+ goto out;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+ usleep_range(100, 200);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+ usleep_range(100, 200);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+ mutex_unlock(&padctl->lock);
+ return 0;
+}
+
+static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+ u32 value;
+
+ mutex_lock(&padctl->lock);
+
+ if (WARN_ON(padctl->enable == 0))
+ goto out;
+
+ if (--padctl->enable > 0)
+ goto out;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+ usleep_range(100, 200);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+ usleep_range(100, 200);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+ value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+ padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+ mutex_unlock(&padctl->lock);
+ return 0;
+}
+
+static int tegra_xusb_phy_init(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+ return tegra_xusb_padctl_enable(padctl);
+}
+
+static int tegra_xusb_phy_exit(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+ return tegra_xusb_padctl_disable(padctl);
+}
+
+static int pcie_phy_power_on(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+ unsigned long timeout;
+ int err = -ETIMEDOUT;
+ u32 value;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+ value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
+ XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
+ XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+ timeout = jiffies + msecs_to_jiffies(50);
+
+ while (time_before(jiffies, timeout)) {
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
+ err = 0;
+ break;
+ }
+
+ usleep_range(100, 200);
+ }
+
+ return err;
+}
+
+static int pcie_phy_power_off(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+ u32 value;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+ return 0;
+}
+
+static const struct phy_ops pcie_phy_ops = {
+ .init = tegra_xusb_phy_init,
+ .exit = tegra_xusb_phy_exit,
+ .power_on = pcie_phy_power_on,
+ .power_off = pcie_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int sata_phy_power_on(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+ unsigned long timeout;
+ int err = -ETIMEDOUT;
+ u32 value;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+ value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ timeout = jiffies + msecs_to_jiffies(50);
+
+ while (time_before(jiffies, timeout)) {
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
+ err = 0;
+ break;
+ }
+
+ usleep_range(100, 200);
+ }
+
+ return err;
+}
+
+static int sata_phy_power_off(struct phy *phy)
+{
+ struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+ u32 value;
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+ value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+ value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+ value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+ padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+ return 0;
+}
+
+static const struct phy_ops sata_phy_ops = {
+ .init = tegra_xusb_phy_init,
+ .exit = tegra_xusb_phy_exit,
+ .power_on = sata_phy_power_on,
+ .power_off = sata_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+ unsigned int index = args->args[0];
+
+ if (args->args_count <= 0)
+ return ERR_PTR(-EINVAL);
+
+ if (index > ARRAY_SIZE(padctl->phys))
+ return ERR_PTR(-EINVAL);
+
+ return padctl->phys[index];
+}
+
+#define PIN_OTG_0 0
+#define PIN_OTG_1 1
+#define PIN_OTG_2 2
+#define PIN_ULPI_0 3
+#define PIN_HSIC_0 4
+#define PIN_HSIC_1 5
+#define PIN_PCIE_0 6
+#define PIN_PCIE_1 7
+#define PIN_PCIE_2 8
+#define PIN_PCIE_3 9
+#define PIN_PCIE_4 10
+#define PIN_SATA_0 11
+
+static const struct pinctrl_pin_desc tegra124_pins[] = {
+ PINCTRL_PIN(PIN_OTG_0, "otg-0"),
+ PINCTRL_PIN(PIN_OTG_1, "otg-1"),
+ PINCTRL_PIN(PIN_OTG_2, "otg-2"),
+ PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
+ PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
+ PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
+ PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
+ PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
+ PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
+ PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
+ PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
+ PINCTRL_PIN(PIN_SATA_0, "sata-0"),
+};
+
+static const char * const tegra124_snps_groups[] = {
+ "otg-0",
+ "otg-1",
+ "otg-2",
+ "ulpi-0",
+ "hsic-0",
+ "hsic-1",
+};
+
+static const char * const tegra124_xusb_groups[] = {
+ "otg-0",
+ "otg-1",
+ "otg-2",
+ "ulpi-0",
+ "hsic-0",
+ "hsic-1",
+};
+
+static const char * const tegra124_uart_groups[] = {
+ "otg-0",
+ "otg-1",
+ "otg-2",
+};
+
+static const char * const tegra124_pcie_groups[] = {
+ "pcie-0",
+ "pcie-1",
+ "pcie-2",
+ "pcie-3",
+ "pcie-4",
+ "sata-0",
+};
+
+static const char * const tegra124_usb3_groups[] = {
+ "pcie-0",
+ "pcie-1",
+ "pcie-2",
+ "pcie-3",
+ "pcie-4",
+ "sata-0",
+};
+
+static const char * const tegra124_sata_groups[] = {
+ "pcie-0",
+ "pcie-1",
+ "pcie-2",
+ "pcie-3",
+ "pcie-4",
+ "sata-0",
+};
+
+static const char * const tegra124_rsvd_groups[] = {
+ "otg-0",
+ "otg-1",
+ "otg-2",
+ "pcie-0",
+ "pcie-1",
+ "pcie-2",
+ "pcie-3",
+ "pcie-4",
+ "sata-0",
+};
+
+#define TEGRA124_FUNCTION(_name) \
+ { \
+ .name = #_name, \
+ .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \
+ .groups = tegra124_##_name##_groups, \
+ }
+
+static struct tegra_xusb_padctl_function tegra124_functions[] = {
+ TEGRA124_FUNCTION(snps),
+ TEGRA124_FUNCTION(xusb),
+ TEGRA124_FUNCTION(uart),
+ TEGRA124_FUNCTION(pcie),
+ TEGRA124_FUNCTION(usb3),
+ TEGRA124_FUNCTION(sata),
+ TEGRA124_FUNCTION(rsvd),
+};
+
+enum tegra124_function {
+ TEGRA124_FUNC_SNPS,
+ TEGRA124_FUNC_XUSB,
+ TEGRA124_FUNC_UART,
+ TEGRA124_FUNC_PCIE,
+ TEGRA124_FUNC_USB3,
+ TEGRA124_FUNC_SATA,
+ TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_otg_functions[] = {
+ TEGRA124_FUNC_SNPS,
+ TEGRA124_FUNC_XUSB,
+ TEGRA124_FUNC_UART,
+ TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_usb_functions[] = {
+ TEGRA124_FUNC_SNPS,
+ TEGRA124_FUNC_XUSB,
+};
+
+static const unsigned int tegra124_pci_functions[] = {
+ TEGRA124_FUNC_PCIE,
+ TEGRA124_FUNC_USB3,
+ TEGRA124_FUNC_SATA,
+ TEGRA124_FUNC_RSVD,
+};
+
+#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \
+ { \
+ .name = _name, \
+ .offset = _offset, \
+ .shift = _shift, \
+ .mask = _mask, \
+ .iddq = _iddq, \
+ .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
+ .funcs = tegra124_##_funcs##_functions, \
+ }
+
+static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
+ TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg),
+ TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg),
+ TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg),
+ TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
+ TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+ TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+ TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
+ TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
+ TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
+ TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
+ TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
+ TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
+};
+
+static const struct tegra_xusb_padctl_soc tegra124_soc = {
+ .num_pins = ARRAY_SIZE(tegra124_pins),
+ .pins = tegra124_pins,
+ .num_functions = ARRAY_SIZE(tegra124_functions),
+ .functions = tegra124_functions,
+ .num_lanes = ARRAY_SIZE(tegra124_lanes),
+ .lanes = tegra124_lanes,
+};
+
+static const struct of_device_id tegra_xusb_padctl_of_match[] = {
+ { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
+
+static int tegra_xusb_padctl_probe(struct platform_device *pdev)
+{
+ struct tegra_xusb_padctl *padctl;
+ const struct of_device_id *match;
+ struct resource *res;
+ struct phy *phy;
+ int err;
+
+ padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
+ if (!padctl)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, padctl);
+ mutex_init(&padctl->lock);
+ padctl->dev = &pdev->dev;
+
+ match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
+ padctl->soc = match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ padctl->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(padctl->regs))
+ return PTR_ERR(padctl->regs);
+
+ padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(padctl->rst))
+ return PTR_ERR(padctl->rst);
+
+ err = reset_control_deassert(padctl->rst);
+ if (err < 0)
+ return err;
+
+ memset(&padctl->desc, 0, sizeof(padctl->desc));
+ padctl->desc.name = dev_name(padctl->dev);
+ padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
+ padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
+ padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
+ padctl->desc.owner = THIS_MODULE;
+
+ padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
+ if (!padctl->pinctrl) {
+ dev_err(&pdev->dev, "failed to register pincontrol\n");
+ err = -ENODEV;
+ goto reset;
+ }
+
+ phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ err = PTR_ERR(phy);
+ goto unregister;
+ }
+
+ padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
+ phy_set_drvdata(phy, padctl);
+
+ phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ err = PTR_ERR(phy);
+ goto unregister;
+ }
+
+ padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
+ phy_set_drvdata(phy, padctl);
+
+ padctl->provider = devm_of_phy_provider_register(&pdev->dev,
+ tegra_xusb_padctl_xlate);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
+ goto unregister;
+ }
+
+ return 0;
+
+unregister:
+ pinctrl_unregister(padctl->pinctrl);
+reset:
+ reset_control_assert(padctl->rst);
+ return err;
+}
+
+static int tegra_xusb_padctl_remove(struct platform_device *pdev)
+{
+ struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
+ int err;
+
+ pinctrl_unregister(padctl->pinctrl);
+
+ err = reset_control_assert(padctl->rst);
+ if (err < 0)
+ dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
+
+ return err;
+}
+
+static struct platform_driver tegra_xusb_padctl_driver = {
+ .driver = {
+ .name = "tegra-xusb-padctl",
+ .of_match_table = tegra_xusb_padctl_of_match,
+ },
+ .probe = tegra_xusb_padctl_probe,
+ .remove = tegra_xusb_padctl_remove,
+};
+module_platform_driver(tegra_xusb_padctl_driver);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 2d43bff74f59..150af5503c09 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -290,24 +290,11 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
return 0;
}
-static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
- unsigned function, unsigned group)
-{
- struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- const struct tegra_pingroup *g;
-
- g = &pmx->soc->groups[group];
-
- if (WARN_ON(g->mux_reg < 0))
- return;
-}
-
static const struct pinmux_ops tegra_pinmux_ops = {
.get_functions_count = tegra_pinctrl_get_funcs_count,
.get_function_name = tegra_pinctrl_get_func_name,
.get_function_groups = tegra_pinctrl_get_func_groups,
.enable = tegra_pinctrl_enable,
- .disable = tegra_pinctrl_disable,
};
static int tegra_pinconf_reg(struct tegra_pmx *pmx,
diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c
index 5bf01c28925e..41e81a35cabb 100644
--- a/drivers/pinctrl/pinctrl-tz1090-pdc.c
+++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c
@@ -574,33 +574,6 @@ static int tz1090_pdc_pinctrl_enable(struct pinctrl_dev *pctldev,
return 0;
}
-static void tz1090_pdc_pinctrl_disable(struct pinctrl_dev *pctldev,
- unsigned int function,
- unsigned int group)
-{
- struct tz1090_pdc_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- const struct tz1090_pdc_pingroup *grp = &tz1090_pdc_groups[group];
-
- dev_dbg(pctldev->dev, "%s(func=%u (%s), group=%u (%s))\n",
- __func__,
- function, tz1090_pdc_functions[function].name,
- group, tz1090_pdc_groups[group].name);
-
- /* is it even a mux? */
- if (grp->drv)
- return;
-
- /* does this group even control the function? */
- if (function != grp->func)
- return;
-
- /* record the pin being unmuxed and update mux bit */
- spin_lock(&pmx->lock);
- pmx->mux_en &= ~BIT(grp->pins[0]);
- tz1090_pdc_pinctrl_mux(pmx, grp);
- spin_unlock(&pmx->lock);
-}
-
static const struct tz1090_pdc_pingroup *find_mux_group(
struct tz1090_pdc_pmx *pmx,
unsigned int pin)
@@ -662,7 +635,6 @@ static struct pinmux_ops tz1090_pdc_pinmux_ops = {
.get_function_name = tz1090_pdc_pinctrl_get_func_name,
.get_function_groups = tz1090_pdc_pinctrl_get_func_groups,
.enable = tz1090_pdc_pinctrl_enable,
- .disable = tz1090_pdc_pinctrl_disable,
.gpio_request_enable = tz1090_pdc_pinctrl_gpio_request_enable,
.gpio_disable_free = tz1090_pdc_pinctrl_gpio_disable_free,
};
diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c
index bc9cd7a7602e..24082216842e 100644
--- a/drivers/pinctrl/pinctrl-tz1090.c
+++ b/drivers/pinctrl/pinctrl-tz1090.c
@@ -1479,63 +1479,6 @@ mux_pins:
}
/**
- * tz1090_pinctrl_disable() - Disable a function on a pin group.
- * @pctldev: Pin control data
- * @function: Function index to disable
- * @group: Group index to disable
- *
- * Disable a particular function on a group of pins. The per GPIO pin pseudo pin
- * groups can be used (in which case the pin will be taken out of peripheral
- * mode. Some convenience pin groups can also be used in which case the effect
- * is the same as enabling the function on each individual pin in the group.
- */
-static void tz1090_pinctrl_disable(struct pinctrl_dev *pctldev,
- unsigned int function, unsigned int group)
-{
- struct tz1090_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
- struct tz1090_pingroup *grp;
- unsigned int pin_num, mux_group, i, npins;
- const unsigned int *pins;
-
- /* group of pins? */
- if (group < ARRAY_SIZE(tz1090_groups)) {
- grp = &tz1090_groups[group];
- npins = grp->npins;
- pins = grp->pins;
- /*
- * All pins in the group must belong to the same mux group,
- * which allows us to just use the mux group of the first pin.
- * By explicitly listing permitted pingroups for each function
- * the pinmux core should ensure this is always the case.
- */
- } else {
- pin_num = group - ARRAY_SIZE(tz1090_groups);
- npins = 1;
- pins = &pin_num;
- }
- mux_group = tz1090_mux_pins[*pins];
-
- /* no mux group, but can still be individually muxed to peripheral */
- if (mux_group >= TZ1090_MUX_GROUP_MAX) {
- if (function == TZ1090_MUX_PERIP)
- goto unmux_pins;
- return;
- }
-
- /* mux group already set to a different function? */
- grp = &tz1090_mux_groups[mux_group];
- dev_dbg(pctldev->dev, "%s: unmuxing %u pin(s) in '%s' from '%s'\n",
- __func__, npins, grp->name, tz1090_functions[function].name);
-
- /* subtract pins from ref count and unmux individually */
- WARN_ON(grp->func_count < npins);
- grp->func_count -= npins;
-unmux_pins:
- for (i = 0; i < npins; ++i)
- tz1090_pinctrl_perip_select(pmx, pins[i], false);
-}
-
-/**
* tz1090_pinctrl_gpio_request_enable() - Put pin in GPIO mode.
* @pctldev: Pin control data
* @range: GPIO range
@@ -1575,7 +1518,6 @@ static struct pinmux_ops tz1090_pinmux_ops = {
.get_function_name = tz1090_pinctrl_get_func_name,
.get_function_groups = tz1090_pinctrl_get_func_groups,
.enable = tz1090_pinctrl_enable,
- .disable = tz1090_pinctrl_disable,
.gpio_request_enable = tz1090_pinctrl_gpio_request_enable,
.gpio_disable_free = tz1090_pinctrl_gpio_disable_free,
};
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 209a01b8bd3b..0959bb36450f 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -970,19 +970,6 @@ static int u300_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
-static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
- unsigned group)
-{
- struct u300_pmx *upmx;
-
- /* There is nothing to do with the power pins */
- if (selector == 0)
- return;
-
- upmx = pinctrl_dev_get_drvdata(pctldev);
- u300_pmx_endisable(upmx, selector, false);
-}
-
static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(u300_pmx_functions);
@@ -1008,7 +995,6 @@ static const struct pinmux_ops u300_pmx_ops = {
.get_function_name = u300_pmx_get_func_name,
.get_function_groups = u300_pmx_get_groups,
.enable = u300_pmx_enable,
- .disable = u300_pmx_disable,
};
static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 051e8592990e..c055daf9a80f 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -471,7 +471,6 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const struct pinmux_ops *ops = pctldev->desc->pmxops;
int ret = 0;
const unsigned *pins = NULL;
unsigned num_pins = 0;
@@ -518,9 +517,6 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
pins[i], desc->name, gname);
}
}
-
- if (ops->disable)
- ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
new file mode 100644
index 000000000000..d160a710d704
--- /dev/null
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -0,0 +1,42 @@
+if (ARCH_QCOM || COMPILE_TEST)
+
+config PINCTRL_MSM
+ bool
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+ select GPIOLIB_IRQCHIP
+
+config PINCTRL_APQ8064
+ tristate "Qualcomm APQ8064 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm APQ8064 platform.
+
+config PINCTRL_IPQ8064
+ tristate "Qualcomm IPQ8064 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm IPQ8064 platform.
+
+config PINCTRL_MSM8960
+ tristate "Qualcomm 8960 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8960 platform.
+
+config PINCTRL_MSM8X74
+ tristate "Qualcomm 8x74 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm 8974 platform.
+
+endif
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
new file mode 100644
index 000000000000..2a02602d715c
--- /dev/null
+++ b/drivers/pinctrl/qcom/Makefile
@@ -0,0 +1,6 @@
+# Qualcomm pin control drivers
+obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o
+obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o
+obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o
+obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
+obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
diff --git a/drivers/pinctrl/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c
index 519f7886b0f1..feb6f152f9b7 100644
--- a/drivers/pinctrl/pinctrl-apq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c
@@ -230,7 +230,7 @@ static const unsigned int sdc3_data_pins[] = { 95 };
.pins = gpio##id##_pins, \
.npins = ARRAY_SIZE(gpio##id##_pins), \
.funcs = (int[]){ \
- APQ_MUX_NA, /* gpio mode */ \
+ APQ_MUX_gpio, \
APQ_MUX_##f1, \
APQ_MUX_##f2, \
APQ_MUX_##f3, \
@@ -293,6 +293,7 @@ enum apq8064_functions {
APQ_MUX_cam_mclk,
APQ_MUX_codec_mic_i2s,
APQ_MUX_codec_spkr_i2s,
+ APQ_MUX_gpio,
APQ_MUX_gsbi1,
APQ_MUX_gsbi2,
APQ_MUX_gsbi3,
@@ -335,6 +336,21 @@ static const char * const codec_mic_i2s_groups[] = {
static const char * const codec_spkr_i2s_groups[] = {
"gpio39", "gpio40", "gpio41", "gpio42"
};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89"
+};
static const char * const gsbi1_groups[] = {
"gpio18", "gpio19", "gpio20", "gpio21"
};
@@ -430,6 +446,7 @@ static const struct msm_function apq8064_functions[] = {
FUNCTION(cam_mclk),
FUNCTION(codec_mic_i2s),
FUNCTION(codec_spkr_i2s),
+ FUNCTION(gpio),
FUNCTION(gsbi1),
FUNCTION(gsbi2),
FUNCTION(gsbi3),
diff --git a/drivers/pinctrl/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
index acafea4c3a33..767cf1120b20 100644
--- a/drivers/pinctrl/pinctrl-ipq8064.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c
@@ -183,7 +183,7 @@ static const unsigned int sdc3_data_pins[] = { 71 };
.pins = gpio##id##_pins, \
.npins = ARRAY_SIZE(gpio##id##_pins), \
.funcs = (int[]){ \
- IPQ_MUX_NA, /* gpio mode */ \
+ IPQ_MUX_gpio, \
IPQ_MUX_##f1, \
IPQ_MUX_##f2, \
IPQ_MUX_##f3, \
@@ -243,6 +243,7 @@ static const unsigned int sdc3_data_pins[] = { 71 };
}
enum ipq8064_functions {
+ IPQ_MUX_gpio,
IPQ_MUX_mdio,
IPQ_MUX_mi2s,
IPQ_MUX_pdm,
@@ -291,6 +292,19 @@ enum ipq8064_functions {
IPQ_MUX_NA,
};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"
+};
+
static const char * const mdio_groups[] = {
"gpio0", "gpio1", "gpio10", "gpio11",
};
@@ -481,6 +495,7 @@ static const char * const ps_hold_groups[] = {
};
static const struct msm_function ipq8064_functions[] = {
+ FUNCTION(gpio),
FUNCTION(mdio),
FUNCTION(ssbi),
FUNCTION(spmi),
diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index df6dda4ce803..2738108caff2 100644
--- a/drivers/pinctrl/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -27,10 +27,10 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include "core.h"
-#include "pinconf.h"
+#include "../core.h"
+#include "../pinconf.h"
#include "pinctrl-msm.h"
-#include "pinctrl-utils.h"
+#include "../pinctrl-utils.h"
#define MAX_NR_GPIO 300
@@ -142,9 +142,6 @@ static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
g = &pctrl->soc->groups[group];
- if (WARN_ON(g->mux_bit < 0))
- return -EINVAL;
-
for (i = 0; i < g->nfuncs; i++) {
if (g->funcs[i] == function)
break;
@@ -165,36 +162,11 @@ static int msm_pinmux_enable(struct pinctrl_dev *pctldev,
return 0;
}
-static void msm_pinmux_disable(struct pinctrl_dev *pctldev,
- unsigned function,
- unsigned group)
-{
- struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
- const struct msm_pingroup *g;
- unsigned long flags;
- u32 val;
-
- g = &pctrl->soc->groups[group];
-
- if (WARN_ON(g->mux_bit < 0))
- return;
-
- spin_lock_irqsave(&pctrl->lock, flags);
-
- /* Clear the mux bits to select gpio mode */
- val = readl(pctrl->regs + g->ctl_reg);
- val &= ~(0x7 << g->mux_bit);
- writel(val, pctrl->regs + g->ctl_reg);
-
- spin_unlock_irqrestore(&pctrl->lock, flags);
-}
-
static const struct pinmux_ops msm_pinmux_ops = {
.get_functions_count = msm_get_functions_count,
.get_function_name = msm_get_function_name,
.get_function_groups = msm_get_function_groups,
.enable = msm_pinmux_enable,
- .disable = msm_pinmux_disable,
};
static int msm_config_reg(struct msm_pinctrl *pctrl,
@@ -206,6 +178,7 @@ static int msm_config_reg(struct msm_pinctrl *pctrl,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_BUS_HOLD:
case PIN_CONFIG_BIAS_PULL_UP:
*bit = g->pull_bit;
*mask = 3;
@@ -243,6 +216,7 @@ static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
#define MSM_NO_PULL 0
#define MSM_PULL_DOWN 1
+#define MSM_KEEPER 2
#define MSM_PULL_UP 3
static unsigned msm_regval_to_drive(u32 val)
@@ -280,6 +254,9 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
case PIN_CONFIG_BIAS_PULL_DOWN:
arg = arg == MSM_PULL_DOWN;
break;
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ arg = arg == MSM_KEEPER;
+ break;
case PIN_CONFIG_BIAS_PULL_UP:
arg = arg == MSM_PULL_UP;
break;
@@ -339,6 +316,9 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
case PIN_CONFIG_BIAS_PULL_DOWN:
arg = MSM_PULL_DOWN;
break;
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ arg = MSM_KEEPER;
+ break;
case PIN_CONFIG_BIAS_PULL_UP:
arg = MSM_PULL_UP;
break;
diff --git a/drivers/pinctrl/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 7b2a227a590a..7b2a227a590a 100644
--- a/drivers/pinctrl/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c
new file mode 100644
index 000000000000..35047036a053
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc msm8960_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "GPIO_150"),
+ PINCTRL_PIN(151, "GPIO_151"),
+
+ PINCTRL_PIN(152, "SDC1_CLK"),
+ PINCTRL_PIN(153, "SDC1_CMD"),
+ PINCTRL_PIN(154, "SDC1_DATA"),
+ PINCTRL_PIN(155, "SDC3_CLK"),
+ PINCTRL_PIN(156, "SDC3_CMD"),
+ PINCTRL_PIN(157, "SDC3_DATA"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+DECLARE_MSM_GPIO_PINS(150);
+DECLARE_MSM_GPIO_PINS(151);
+
+static const unsigned int sdc1_clk_pins[] = { 152 };
+static const unsigned int sdc1_cmd_pins[] = { 153 };
+static const unsigned int sdc1_data_pins[] = { 154 };
+static const unsigned int sdc3_clk_pins[] = { 155 };
+static const unsigned int sdc3_cmd_pins[] = { 156 };
+static const unsigned int sdc3_data_pins[] = { 157 };
+
+#define FUNCTION(fname) \
+ [MSM_MUX_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ MSM_MUX_gpio, \
+ MSM_MUX_##f1, \
+ MSM_MUX_##f2, \
+ MSM_MUX_##f3, \
+ MSM_MUX_##f4, \
+ MSM_MUX_##f5, \
+ MSM_MUX_##f6, \
+ MSM_MUX_##f7, \
+ MSM_MUX_##f8, \
+ MSM_MUX_##f9, \
+ MSM_MUX_##f10, \
+ MSM_MUX_##f11 \
+ }, \
+ .nfuncs = 12, \
+ .ctl_reg = 0x1000 + 0x10 * id, \
+ .io_reg = 0x1004 + 0x10 * id, \
+ .intr_cfg_reg = 0x1008 + 0x10 * id, \
+ .intr_status_reg = 0x100c + 0x10 * id, \
+ .intr_target_reg = 0x400 + 0x4 * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_ack_high = 1, \
+ .intr_target_bit = 0, \
+ .intr_raw_status_bit = 3, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 1, \
+ }
+
+#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+
+enum msm8960_functions {
+ MSM_MUX_audio_pcm,
+ MSM_MUX_bt,
+ MSM_MUX_cam_mclk0,
+ MSM_MUX_cam_mclk1,
+ MSM_MUX_cam_mclk2,
+ MSM_MUX_codec_mic_i2s,
+ MSM_MUX_codec_spkr_i2s,
+ MSM_MUX_ext_gps,
+ MSM_MUX_fm,
+ MSM_MUX_gps_blanking,
+ MSM_MUX_gps_pps_in,
+ MSM_MUX_gps_pps_out,
+ MSM_MUX_gp_clk_0a,
+ MSM_MUX_gp_clk_0b,
+ MSM_MUX_gp_clk_1a,
+ MSM_MUX_gp_clk_1b,
+ MSM_MUX_gp_clk_2a,
+ MSM_MUX_gp_clk_2b,
+ MSM_MUX_gp_mn,
+ MSM_MUX_gp_pdm_0a,
+ MSM_MUX_gp_pdm_0b,
+ MSM_MUX_gp_pdm_1a,
+ MSM_MUX_gp_pdm_1b,
+ MSM_MUX_gp_pdm_2a,
+ MSM_MUX_gp_pdm_2b,
+ MSM_MUX_gpio,
+ MSM_MUX_gsbi1,
+ MSM_MUX_gsbi1_spi_cs1_n,
+ MSM_MUX_gsbi1_spi_cs2a_n,
+ MSM_MUX_gsbi1_spi_cs2b_n,
+ MSM_MUX_gsbi1_spi_cs3_n,
+ MSM_MUX_gsbi2,
+ MSM_MUX_gsbi2_spi_cs1_n,
+ MSM_MUX_gsbi2_spi_cs2_n,
+ MSM_MUX_gsbi2_spi_cs3_n,
+ MSM_MUX_gsbi3,
+ MSM_MUX_gsbi4,
+ MSM_MUX_gsbi4_3d_cam_i2c_l,
+ MSM_MUX_gsbi4_3d_cam_i2c_r,
+ MSM_MUX_gsbi5,
+ MSM_MUX_gsbi5_3d_cam_i2c_l,
+ MSM_MUX_gsbi5_3d_cam_i2c_r,
+ MSM_MUX_gsbi6,
+ MSM_MUX_gsbi7,
+ MSM_MUX_gsbi8,
+ MSM_MUX_gsbi9,
+ MSM_MUX_gsbi10,
+ MSM_MUX_gsbi11,
+ MSM_MUX_gsbi11_spi_cs1a_n,
+ MSM_MUX_gsbi11_spi_cs1b_n,
+ MSM_MUX_gsbi11_spi_cs2a_n,
+ MSM_MUX_gsbi11_spi_cs2b_n,
+ MSM_MUX_gsbi11_spi_cs3_n,
+ MSM_MUX_gsbi12,
+ MSM_MUX_hdmi_cec,
+ MSM_MUX_hdmi_ddc_clock,
+ MSM_MUX_hdmi_ddc_data,
+ MSM_MUX_hdmi_hot_plug_detect,
+ MSM_MUX_hsic,
+ MSM_MUX_mdp_vsync,
+ MSM_MUX_mi2s,
+ MSM_MUX_mic_i2s,
+ MSM_MUX_pmb_clk,
+ MSM_MUX_pmb_ext_ctrl,
+ MSM_MUX_ps_hold,
+ MSM_MUX_rpm_wdog,
+ MSM_MUX_sdc2,
+ MSM_MUX_sdc4,
+ MSM_MUX_sdc5,
+ MSM_MUX_slimbus1,
+ MSM_MUX_slimbus2,
+ MSM_MUX_spkr_i2s,
+ MSM_MUX_ssbi1,
+ MSM_MUX_ssbi2,
+ MSM_MUX_ssbi_ext_gps,
+ MSM_MUX_ssbi_pmic2,
+ MSM_MUX_ssbi_qpa1,
+ MSM_MUX_ssbi_ts,
+ MSM_MUX_tsif1,
+ MSM_MUX_tsif2,
+ MSM_MUX_ts_eoc,
+ MSM_MUX_usb_fs1,
+ MSM_MUX_usb_fs1_oe,
+ MSM_MUX_usb_fs1_oe_n,
+ MSM_MUX_usb_fs2,
+ MSM_MUX_usb_fs2_oe,
+ MSM_MUX_usb_fs2_oe_n,
+ MSM_MUX_vfe_camif_timer1_a,
+ MSM_MUX_vfe_camif_timer1_b,
+ MSM_MUX_vfe_camif_timer2,
+ MSM_MUX_vfe_camif_timer3_a,
+ MSM_MUX_vfe_camif_timer3_b,
+ MSM_MUX_vfe_camif_timer4_a,
+ MSM_MUX_vfe_camif_timer4_b,
+ MSM_MUX_vfe_camif_timer4_c,
+ MSM_MUX_vfe_camif_timer5_a,
+ MSM_MUX_vfe_camif_timer5_b,
+ MSM_MUX_vfe_camif_timer6_a,
+ MSM_MUX_vfe_camif_timer6_b,
+ MSM_MUX_vfe_camif_timer6_c,
+ MSM_MUX_vfe_camif_timer7_a,
+ MSM_MUX_vfe_camif_timer7_b,
+ MSM_MUX_vfe_camif_timer7_c,
+ MSM_MUX_wlan,
+ MSM_MUX_NA,
+};
+
+static const char * const audio_pcm_groups[] = {
+ "gpio63", "gpio64", "gpio65", "gpio66"
+};
+
+static const char * const bt_groups[] = {
+ "gpio28", "gpio29", "gpio83"
+};
+
+static const char * const cam_mclk0_groups[] = {
+ "gpio5"
+};
+
+static const char * const cam_mclk1_groups[] = {
+ "gpio4"
+};
+
+static const char * const cam_mclk2_groups[] = {
+ "gpio2"
+};
+
+static const char * const codec_mic_i2s_groups[] = {
+ "gpio54", "gpio55", "gpio56", "gpio57", "gpio58"
+};
+
+static const char * const codec_spkr_i2s_groups[] = {
+ "gpio59", "gpio60", "gpio61", "gpio62"
+};
+
+static const char * const ext_gps_groups[] = {
+ "gpio22", "gpio23", "gpio24", "gpio25"
+};
+
+static const char * const fm_groups[] = {
+ "gpio26", "gpio27"
+};
+
+static const char * const gps_blanking_groups[] = {
+ "gpio137"
+};
+
+static const char * const gps_pps_in_groups[] = {
+ "gpio37"
+};
+
+static const char * const gps_pps_out_groups[] = {
+ "gpio37"
+};
+
+static const char * const gp_clk_0a_groups[] = {
+ "gpio3"
+};
+
+static const char * const gp_clk_0b_groups[] = {
+ "gpio54"
+};
+
+static const char * const gp_clk_1a_groups[] = {
+ "gpio4"
+};
+
+static const char * const gp_clk_1b_groups[] = {
+ "gpio70"
+};
+
+static const char * const gp_clk_2a_groups[] = {
+ "gpio52"
+};
+
+static const char * const gp_clk_2b_groups[] = {
+ "gpio37"
+};
+
+static const char * const gp_mn_groups[] = {
+ "gpio2"
+};
+
+static const char * const gp_pdm_0a_groups[] = {
+ "gpio58"
+};
+
+static const char * const gp_pdm_0b_groups[] = {
+ "gpio39"
+};
+
+static const char * const gp_pdm_1a_groups[] = {
+ "gpio94"
+};
+
+static const char * const gp_pdm_1b_groups[] = {
+ "gpio64"
+};
+
+static const char * const gp_pdm_2a_groups[] = {
+ "gpio69"
+};
+
+static const char * const gp_pdm_2b_groups[] = {
+ "gpio53"
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+ "gpio147", "gpio148", "gpio149", "gpio150", "gpio151"
+};
+
+static const char * const gsbi1_groups[] = {
+ "gpio6", "gpio7", "gpio8", "gpio9"
+};
+
+static const char * const gsbi1_spi_cs1_n_groups[] = {
+ "gpio14"
+};
+
+static const char * const gsbi1_spi_cs2a_n_groups[] = {
+ "gpio15"
+};
+
+static const char * const gsbi1_spi_cs2b_n_groups[] = {
+ "gpio17"
+};
+
+static const char * const gsbi1_spi_cs3_n_groups[] = {
+ "gpio16"
+};
+
+static const char * const gsbi2_groups[] = {
+ "gpio10", "gpio11", "gpio12", "gpio13"
+};
+
+static const char * const gsbi2_spi_cs1_n_groups[] = {
+ "gpio52"
+};
+
+static const char * const gsbi2_spi_cs2_n_groups[] = {
+ "gpio68"
+};
+
+static const char * const gsbi2_spi_cs3_n_groups[] = {
+ "gpio56"
+};
+
+static const char * const gsbi3_groups[] = {
+ "gpio14", "gpio15", "gpio16", "gpio17"
+};
+
+static const char * const gsbi4_groups[] = {
+ "gpio18", "gpio19", "gpio20", "gpio21"
+};
+
+static const char * const gsbi4_3d_cam_i2c_l_groups[] = {
+ "gpio18", "gpio19"
+};
+
+static const char * const gsbi4_3d_cam_i2c_r_groups[] = {
+ "gpio20", "gpio21"
+};
+
+static const char * const gsbi5_groups[] = {
+ "gpio22", "gpio23", "gpio24", "gpio25"
+};
+
+static const char * const gsbi5_3d_cam_i2c_l_groups[] = {
+ "gpio22", "gpio23"
+};
+
+static const char * const gsbi5_3d_cam_i2c_r_groups[] = {
+ "gpio24", "gpio25"
+};
+
+static const char * const gsbi6_groups[] = {
+ "gpio26", "gpio27", "gpio28", "gpio29"
+};
+
+static const char * const gsbi7_groups[] = {
+ "gpio30", "gpio31", "gpio32", "gpio33"
+};
+
+static const char * const gsbi8_groups[] = {
+ "gpio34", "gpio35", "gpio36", "gpio37"
+};
+
+static const char * const gsbi9_groups[] = {
+ "gpio93", "gpio94", "gpio95", "gpio96"
+};
+
+static const char * const gsbi10_groups[] = {
+ "gpio71", "gpio72", "gpio73", "gpio74"
+};
+
+static const char * const gsbi11_groups[] = {
+ "gpio38", "gpio39", "gpio40", "gpio41"
+};
+
+static const char * const gsbi11_spi_cs1a_n_groups[] = {
+ "gpio36"
+};
+
+static const char * const gsbi11_spi_cs1b_n_groups[] = {
+ "gpio18"
+};
+
+static const char * const gsbi11_spi_cs2a_n_groups[] = {
+ "gpio37"
+};
+
+static const char * const gsbi11_spi_cs2b_n_groups[] = {
+ "gpio19"
+};
+
+static const char * const gsbi11_spi_cs3_n_groups[] = {
+ "gpio76"
+};
+
+static const char * const gsbi12_groups[] = {
+ "gpio42", "gpio43", "gpio44", "gpio45"
+};
+
+static const char * const hdmi_cec_groups[] = {
+ "gpio99"
+};
+
+static const char * const hdmi_ddc_clock_groups[] = {
+ "gpio100"
+};
+
+static const char * const hdmi_ddc_data_groups[] = {
+ "gpio101"
+};
+
+static const char * const hdmi_hot_plug_detect_groups[] = {
+ "gpio102"
+};
+
+static const char * const hsic_groups[] = {
+ "gpio150", "gpio151"
+};
+
+static const char * const mdp_vsync_groups[] = {
+ "gpio0", "gpio1", "gpio19"
+};
+
+static const char * const mi2s_groups[] = {
+ "gpio47", "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53"
+};
+
+static const char * const mic_i2s_groups[] = {
+ "gpio71", "gpio72", "gpio73", "gpio74"
+};
+
+static const char * const pmb_clk_groups[] = {
+ "gpio21", "gpio86", "gpio112"
+};
+
+static const char * const pmb_ext_ctrl_groups[] = {
+ "gpio4", "gpio5"
+};
+
+static const char * const ps_hold_groups[] = {
+ "gpio108"
+};
+
+static const char * const rpm_wdog_groups[] = {
+ "gpio12"
+};
+
+static const char * const sdc2_groups[] = {
+ "gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", "gpio95",
+ "gpio96", "gpio97", "gpio98"
+};
+
+static const char * const sdc4_groups[] = {
+ "gpio83", "gpio84", "gpio85", "gpio86", "gpio87", "gpio88"
+};
+
+static const char * const sdc5_groups[] = {
+ "gpio77", "gpio78", "gpio79", "gpio80", "gpio81", "gpio82"
+};
+
+static const char * const slimbus1_groups[] = {
+ "gpio50", "gpio51", "gpio60", "gpio61"
+};
+
+static const char * const slimbus2_groups[] = {
+ "gpio42", "gpio43"
+};
+
+static const char * const spkr_i2s_groups[] = {
+ "gpio67", "gpio68", "gpio69", "gpio70"
+};
+
+static const char * const ssbi1_groups[] = {
+ "gpio141", "gpio143"
+};
+
+static const char * const ssbi2_groups[] = {
+ "gpio140", "gpio142"
+};
+
+static const char * const ssbi_ext_gps_groups[] = {
+ "gpio23"
+};
+
+static const char * const ssbi_pmic2_groups[] = {
+ "gpio149"
+};
+
+static const char * const ssbi_qpa1_groups[] = {
+ "gpio131"
+};
+
+static const char * const ssbi_ts_groups[] = {
+ "gpio10"
+};
+
+static const char * const tsif1_groups[] = {
+ "gpio75", "gpio76", "gpio77", "gpio82"
+};
+
+static const char * const tsif2_groups[] = {
+ "gpio78", "gpio79", "gpio80", "gpio81"
+};
+
+static const char * const ts_eoc_groups[] = {
+ "gpio11"
+};
+
+static const char * const usb_fs1_groups[] = {
+ "gpio32", "gpio33"
+};
+
+static const char * const usb_fs1_oe_groups[] = {
+ "gpio31"
+};
+
+static const char * const usb_fs1_oe_n_groups[] = {
+ "gpio31"
+};
+
+static const char * const usb_fs2_groups[] = {
+ "gpio34", "gpio35"
+};
+
+static const char * const usb_fs2_oe_groups[] = {
+ "gpio36"
+};
+
+static const char * const usb_fs2_oe_n_groups[] = {
+ "gpio36"
+};
+
+static const char * const vfe_camif_timer1_a_groups[] = {
+ "gpio2"
+};
+
+static const char * const vfe_camif_timer1_b_groups[] = {
+ "gpio38"
+};
+
+static const char * const vfe_camif_timer2_groups[] = {
+ "gpio3"
+};
+
+static const char * const vfe_camif_timer3_a_groups[] = {
+ "gpio4"
+};
+
+static const char * const vfe_camif_timer3_b_groups[] = {
+ "gpio151"
+};
+
+static const char * const vfe_camif_timer4_a_groups[] = {
+ "gpio65"
+};
+
+static const char * const vfe_camif_timer4_b_groups[] = {
+ "gpio150"
+};
+
+static const char * const vfe_camif_timer4_c_groups[] = {
+ "gpio10"
+};
+
+static const char * const vfe_camif_timer5_a_groups[] = {
+ "gpio66"
+};
+
+static const char * const vfe_camif_timer5_b_groups[] = {
+ "gpio39"
+};
+
+static const char * const vfe_camif_timer6_a_groups[] = {
+ "gpio71"
+};
+
+static const char * const vfe_camif_timer6_b_groups[] = {
+ "gpio0"
+};
+
+static const char * const vfe_camif_timer6_c_groups[] = {
+ "gpio18"
+};
+
+static const char * const vfe_camif_timer7_a_groups[] = {
+ "gpio67"
+};
+
+static const char * const vfe_camif_timer7_b_groups[] = {
+ "gpio1"
+};
+
+static const char * const vfe_camif_timer7_c_groups[] = {
+ "gpio19"
+};
+
+static const char * const wlan_groups[] = {
+ "gpio84", "gpio85", "gpio86", "gpio87", "gpio88"
+};
+
+static const struct msm_function msm8960_functions[] = {
+ FUNCTION(audio_pcm),
+ FUNCTION(bt),
+ FUNCTION(cam_mclk0),
+ FUNCTION(cam_mclk1),
+ FUNCTION(cam_mclk2),
+ FUNCTION(codec_mic_i2s),
+ FUNCTION(codec_spkr_i2s),
+ FUNCTION(ext_gps),
+ FUNCTION(fm),
+ FUNCTION(gps_blanking),
+ FUNCTION(gps_pps_in),
+ FUNCTION(gps_pps_out),
+ FUNCTION(gp_clk_0a),
+ FUNCTION(gp_clk_0b),
+ FUNCTION(gp_clk_1a),
+ FUNCTION(gp_clk_1b),
+ FUNCTION(gp_clk_2a),
+ FUNCTION(gp_clk_2b),
+ FUNCTION(gp_mn),
+ FUNCTION(gp_pdm_0a),
+ FUNCTION(gp_pdm_0b),
+ FUNCTION(gp_pdm_1a),
+ FUNCTION(gp_pdm_1b),
+ FUNCTION(gp_pdm_2a),
+ FUNCTION(gp_pdm_2b),
+ FUNCTION(gpio),
+ FUNCTION(gsbi1),
+ FUNCTION(gsbi1_spi_cs1_n),
+ FUNCTION(gsbi1_spi_cs2a_n),
+ FUNCTION(gsbi1_spi_cs2b_n),
+ FUNCTION(gsbi1_spi_cs3_n),
+ FUNCTION(gsbi2),
+ FUNCTION(gsbi2_spi_cs1_n),
+ FUNCTION(gsbi2_spi_cs2_n),
+ FUNCTION(gsbi2_spi_cs3_n),
+ FUNCTION(gsbi3),
+ FUNCTION(gsbi4),
+ FUNCTION(gsbi4_3d_cam_i2c_l),
+ FUNCTION(gsbi4_3d_cam_i2c_r),
+ FUNCTION(gsbi5),
+ FUNCTION(gsbi5_3d_cam_i2c_l),
+ FUNCTION(gsbi5_3d_cam_i2c_r),
+ FUNCTION(gsbi6),
+ FUNCTION(gsbi7),
+ FUNCTION(gsbi8),
+ FUNCTION(gsbi9),
+ FUNCTION(gsbi10),
+ FUNCTION(gsbi11),
+ FUNCTION(gsbi11_spi_cs1a_n),
+ FUNCTION(gsbi11_spi_cs1b_n),
+ FUNCTION(gsbi11_spi_cs2a_n),
+ FUNCTION(gsbi11_spi_cs2b_n),
+ FUNCTION(gsbi11_spi_cs3_n),
+ FUNCTION(gsbi12),
+ FUNCTION(hdmi_cec),
+ FUNCTION(hdmi_ddc_clock),
+ FUNCTION(hdmi_ddc_data),
+ FUNCTION(hdmi_hot_plug_detect),
+ FUNCTION(hsic),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mi2s),
+ FUNCTION(mic_i2s),
+ FUNCTION(pmb_clk),
+ FUNCTION(pmb_ext_ctrl),
+ FUNCTION(ps_hold),
+ FUNCTION(rpm_wdog),
+ FUNCTION(sdc2),
+ FUNCTION(sdc4),
+ FUNCTION(sdc5),
+ FUNCTION(slimbus1),
+ FUNCTION(slimbus2),
+ FUNCTION(spkr_i2s),
+ FUNCTION(ssbi1),
+ FUNCTION(ssbi2),
+ FUNCTION(ssbi_ext_gps),
+ FUNCTION(ssbi_pmic2),
+ FUNCTION(ssbi_qpa1),
+ FUNCTION(ssbi_ts),
+ FUNCTION(tsif1),
+ FUNCTION(tsif2),
+ FUNCTION(ts_eoc),
+ FUNCTION(usb_fs1),
+ FUNCTION(usb_fs1_oe),
+ FUNCTION(usb_fs1_oe_n),
+ FUNCTION(usb_fs2),
+ FUNCTION(usb_fs2_oe),
+ FUNCTION(usb_fs2_oe_n),
+ FUNCTION(vfe_camif_timer1_a),
+ FUNCTION(vfe_camif_timer1_b),
+ FUNCTION(vfe_camif_timer2),
+ FUNCTION(vfe_camif_timer3_a),
+ FUNCTION(vfe_camif_timer3_b),
+ FUNCTION(vfe_camif_timer4_a),
+ FUNCTION(vfe_camif_timer4_b),
+ FUNCTION(vfe_camif_timer4_c),
+ FUNCTION(vfe_camif_timer5_a),
+ FUNCTION(vfe_camif_timer5_b),
+ FUNCTION(vfe_camif_timer6_a),
+ FUNCTION(vfe_camif_timer6_b),
+ FUNCTION(vfe_camif_timer6_c),
+ FUNCTION(vfe_camif_timer7_a),
+ FUNCTION(vfe_camif_timer7_b),
+ FUNCTION(vfe_camif_timer7_c),
+ FUNCTION(wlan),
+};
+
+static const struct msm_pingroup msm8960_groups[] = {
+ PINGROUP(0, mdp_vsync, vfe_camif_timer6_b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(1, mdp_vsync, vfe_camif_timer7_b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(2, vfe_camif_timer1_a, gp_mn, NA, cam_mclk2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(3, vfe_camif_timer2, gp_clk_0a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(4, vfe_camif_timer3_a, cam_mclk1, gp_clk_1a, pmb_ext_ctrl, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(5, cam_mclk0, pmb_ext_ctrl, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(6, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(7, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(8, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(9, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(10, gsbi2, ssbi_ts, NA, vfe_camif_timer4_c, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(11, gsbi2, ts_eoc, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(12, gsbi2, rpm_wdog, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(13, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(14, gsbi3, gsbi1_spi_cs1_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(15, gsbi3, gsbi1_spi_cs2a_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(16, gsbi3, gsbi1_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(17, gsbi3, gsbi1_spi_cs2b_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(18, gsbi4, gsbi11_spi_cs1b_n, NA, NA, gsbi4_3d_cam_i2c_l, vfe_camif_timer6_c, NA, NA, NA, NA, NA),
+ PINGROUP(19, gsbi4, gsbi11_spi_cs2b_n, NA, mdp_vsync, NA, gsbi4_3d_cam_i2c_l, vfe_camif_timer7_c, NA, NA, NA, NA),
+ PINGROUP(20, gsbi4, gsbi4_3d_cam_i2c_r, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(21, gsbi4, pmb_clk, gsbi4_3d_cam_i2c_r, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(22, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_l, NA),
+ PINGROUP(23, gsbi5, ssbi_ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_l, NA),
+ PINGROUP(24, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_r, NA),
+ PINGROUP(25, gsbi5, ext_gps, NA, NA, NA, NA, NA, NA, NA, gsbi5_3d_cam_i2c_r, NA),
+ PINGROUP(26, fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(27, fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(28, bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(29, bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(30, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(31, gsbi7, usb_fs1_oe, usb_fs1_oe_n, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(32, gsbi7, usb_fs1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(33, gsbi7, usb_fs1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(34, gsbi8, usb_fs2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(35, gsbi8, usb_fs2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(36, gsbi8, usb_fs2_oe, usb_fs2_oe_n, gsbi11_spi_cs1a_n, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(37, gsbi8, gps_pps_out, gps_pps_in, gsbi11_spi_cs2a_n, gp_clk_2b, NA, NA, NA, NA, NA, NA),
+ PINGROUP(38, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, vfe_camif_timer1_b, NA),
+ PINGROUP(39, gsbi11, gp_pdm_0b, NA, NA, NA, NA, NA, NA, NA, NA, vfe_camif_timer5_b),
+ PINGROUP(40, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, gsbi11, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(42, gsbi12, slimbus2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(43, gsbi12, slimbus2, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(44, gsbi12, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(45, gsbi12, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(47, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(48, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(49, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(50, mi2s, slimbus1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(51, mi2s, slimbus1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(52, mi2s, gp_clk_2a, gsbi2_spi_cs1_n, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(53, mi2s, gp_pdm_2b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(54, codec_mic_i2s, gp_clk_0b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(55, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(56, codec_mic_i2s, gsbi2_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(57, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(58, codec_mic_i2s, gp_pdm_0a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(59, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(60, slimbus1, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(61, slimbus1, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(62, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(63, audio_pcm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(64, audio_pcm, gp_pdm_1b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(65, audio_pcm, vfe_camif_timer4_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(66, audio_pcm, vfe_camif_timer5_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(67, spkr_i2s, vfe_camif_timer7_a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(68, spkr_i2s, gsbi2_spi_cs2_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(69, spkr_i2s, gp_pdm_2a, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, spkr_i2s, gp_clk_1b, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(71, mic_i2s, gsbi10, vfe_camif_timer6_a, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, mic_i2s, gsbi10, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(75, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(76, tsif1, gsbi11_spi_cs3_n, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(77, tsif1, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(78, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(81, tsif2, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, tsif1, sdc5, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(83, bt, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(84, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(85, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(86, wlan, sdc4, pmb_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(87, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(88, wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(89, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(90, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(91, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(92, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(93, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(94, sdc2, gsbi9, gp_pdm_1a, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(95, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(96, sdc2, gsbi9, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(97, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, sdc2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(99, hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(100, hdmi_ddc_clock, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(101, hdmi_ddc_data, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(102, hdmi_hot_plug_detect, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(112, NA, pmb_clk, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(113, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(114, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(115, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(118, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(121, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(122, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(123, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(130, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(131, NA, ssbi_qpa1, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(132, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(133, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(134, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(135, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(137, gps_blanking, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(138, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(139, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(140, ssbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(141, ssbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(142, ssbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(143, ssbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(144, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(145, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(146, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(147, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(148, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(149, ssbi_pmic2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(150, hsic, NA, vfe_camif_timer4_b, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(151, hsic, NA, vfe_camif_timer3_b, NA, NA, NA, NA, NA, NA, NA, NA),
+
+ SDC_PINGROUP(sdc1_clk, 0x20a0, 13, 6),
+ SDC_PINGROUP(sdc1_cmd, 0x20a0, 11, 3),
+ SDC_PINGROUP(sdc1_data, 0x20a0, 9, 0),
+
+ SDC_PINGROUP(sdc3_clk, 0x20a4, 14, 6),
+ SDC_PINGROUP(sdc3_cmd, 0x20a4, 11, 3),
+ SDC_PINGROUP(sdc3_data, 0x20a4, 9, 0),
+};
+
+#define NUM_GPIO_PINGROUPS 152
+
+static const struct msm_pinctrl_soc_data msm8960_pinctrl = {
+ .pins = msm8960_pins,
+ .npins = ARRAY_SIZE(msm8960_pins),
+ .functions = msm8960_functions,
+ .nfunctions = ARRAY_SIZE(msm8960_functions),
+ .groups = msm8960_groups,
+ .ngroups = ARRAY_SIZE(msm8960_groups),
+ .ngpios = NUM_GPIO_PINGROUPS,
+};
+
+static int msm8960_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &msm8960_pinctrl);
+}
+
+static const struct of_device_id msm8960_pinctrl_of_match[] = {
+ { .compatible = "qcom,msm8960-pinctrl", },
+ { },
+};
+
+static struct platform_driver msm8960_pinctrl_driver = {
+ .driver = {
+ .name = "msm8960-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = msm8960_pinctrl_of_match,
+ },
+ .probe = msm8960_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init msm8960_pinctrl_init(void)
+{
+ return platform_driver_register(&msm8960_pinctrl_driver);
+}
+arch_initcall(msm8960_pinctrl_init);
+
+static void __exit msm8960_pinctrl_exit(void)
+{
+ platform_driver_unregister(&msm8960_pinctrl_driver);
+}
+module_exit(msm8960_pinctrl_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm MSM8960 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8960_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
index 418306911a6f..8c9720154d1e 100644
--- a/drivers/pinctrl/pinctrl-msm8x74.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c
@@ -342,7 +342,7 @@ static const unsigned int sdc2_data_pins[] = { 151 };
.pins = gpio##id##_pins, \
.npins = ARRAY_SIZE(gpio##id##_pins), \
.funcs = (int[]){ \
- MSM_MUX_NA, /* gpio mode */ \
+ MSM_MUX_gpio, \
MSM_MUX_##f1, \
MSM_MUX_##f2, \
MSM_MUX_##f3, \
@@ -402,6 +402,7 @@ static const unsigned int sdc2_data_pins[] = { 151 };
* the pingroup table below.
*/
enum msm8x74_functions {
+ MSM_MUX_gpio,
MSM_MUX_cci_i2c0,
MSM_MUX_cci_i2c1,
MSM_MUX_blsp_i2c1,
@@ -509,6 +510,31 @@ enum msm8x74_functions {
MSM_MUX_NA,
};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145"
+};
+
static const char * const blsp_uart1_groups[] = {
"gpio0", "gpio1", "gpio2", "gpio3"
};
@@ -728,6 +754,7 @@ static const char * const wlan_groups[] = {
static const char * const slimbus_groups[] = { "gpio70", "gpio71" };
static const struct msm_function msm8x74_functions[] = {
+ FUNCTION(gpio),
FUNCTION(cci_i2c0),
FUNCTION(cci_i2c1),
FUNCTION(uim1),
diff --git a/drivers/pinctrl/samsung/Kconfig b/drivers/pinctrl/samsung/Kconfig
new file mode 100644
index 000000000000..d0461cd5d707
--- /dev/null
+++ b/drivers/pinctrl/samsung/Kconfig
@@ -0,0 +1,28 @@
+#
+# Samsung Pin control drivers
+#
+config PINCTRL_SAMSUNG
+ bool
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_EXYNOS
+ bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440"
+ depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210)
+ select PINCTRL_SAMSUNG
+
+config PINCTRL_EXYNOS5440
+ bool "Samsung EXYNOS5440 SoC pinctrl driver"
+ depends on SOC_EXYNOS5440
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_S3C24XX
+ bool "Samsung S3C24XX SoC pinctrl driver"
+ depends on ARCH_S3C24XX
+ select PINCTRL_SAMSUNG
+
+config PINCTRL_S3C64XX
+ bool "Samsung S3C64XX SoC pinctrl driver"
+ depends on ARCH_S3C64XX
+ select PINCTRL_SAMSUNG
diff --git a/drivers/pinctrl/samsung/Makefile b/drivers/pinctrl/samsung/Makefile
new file mode 100644
index 000000000000..70160c059edd
--- /dev/null
+++ b/drivers/pinctrl/samsung/Makefile
@@ -0,0 +1,7 @@
+# Samsung pin control drivers
+
+obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
+obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
+obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
+obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o
+obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 9609c23834ce..003bfd874a61 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -33,6 +33,18 @@
#include "pinctrl-samsung.h"
#include "pinctrl-exynos.h"
+struct exynos_irq_chip {
+ struct irq_chip chip;
+
+ u32 eint_con;
+ u32 eint_mask;
+ u32 eint_pend;
+};
+
+static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
+{
+ return container_of(chip, struct exynos_irq_chip, chip);
+}
static struct samsung_pin_bank_type bank_type_off = {
.fld_width = { 4, 1, 2, 2, 2, 2, },
@@ -50,11 +62,13 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
{ }
};
-static void exynos_gpio_irq_mask(struct irq_data *irqd)
+static void exynos_irq_mask(struct irq_data *irqd)
{
+ struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+ struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
- unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
+ unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
@@ -67,20 +81,24 @@ static void exynos_gpio_irq_mask(struct irq_data *irqd)
spin_unlock_irqrestore(&bank->slock, flags);
}
-static void exynos_gpio_irq_ack(struct irq_data *irqd)
+static void exynos_irq_ack(struct irq_data *irqd)
{
+ struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+ struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
- unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
+ unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
writel(1 << irqd->hwirq, d->virt_base + reg_pend);
}
-static void exynos_gpio_irq_unmask(struct irq_data *irqd)
+static void exynos_irq_unmask(struct irq_data *irqd)
{
+ struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+ struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
- unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
+ unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
@@ -93,7 +111,7 @@ static void exynos_gpio_irq_unmask(struct irq_data *irqd)
* masked.
*/
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
- exynos_gpio_irq_ack(irqd);
+ exynos_irq_ack(irqd);
spin_lock_irqsave(&bank->slock, flags);
@@ -104,16 +122,17 @@ static void exynos_gpio_irq_unmask(struct irq_data *irqd)
spin_unlock_irqrestore(&bank->slock, flags);
}
-static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
{
+ struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+ struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank_type *bank_type = bank->type;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
- struct samsung_pin_ctrl *ctrl = d->ctrl;
unsigned int pin = irqd->hwirq;
unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
unsigned int con, trig_type;
- unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
+ unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long flags;
unsigned int mask;
@@ -167,12 +186,17 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
/*
* irq_chip for gpio interrupts.
*/
-static struct irq_chip exynos_gpio_irq_chip = {
- .name = "exynos_gpio_irq_chip",
- .irq_unmask = exynos_gpio_irq_unmask,
- .irq_mask = exynos_gpio_irq_mask,
- .irq_ack = exynos_gpio_irq_ack,
- .irq_set_type = exynos_gpio_irq_set_type,
+static struct exynos_irq_chip exynos_gpio_irq_chip = {
+ .chip = {
+ .name = "exynos_gpio_irq_chip",
+ .irq_unmask = exynos_irq_unmask,
+ .irq_mask = exynos_irq_mask,
+ .irq_ack = exynos_irq_ack,
+ .irq_set_type = exynos_irq_set_type,
+ },
+ .eint_con = EXYNOS_GPIO_ECON_OFFSET,
+ .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
+ .eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
};
static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
@@ -181,7 +205,7 @@ static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
struct samsung_pin_bank *b = h->host_data;
irq_set_chip_data(virq, b);
- irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
+ irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip.chip,
handle_level_irq);
set_irq_flags(virq, IRQF_VALID);
return 0;
@@ -202,7 +226,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
struct samsung_pin_bank *bank = ctrl->pin_banks;
unsigned int svc, group, pin, virq;
- svc = readl(d->virt_base + ctrl->svc);
+ svc = readl(d->virt_base + EXYNOS_SVC_OFFSET);
group = EXYNOS_SVC_GROUP(svc);
pin = svc & EXYNOS_SVC_NUM_MASK;
@@ -279,119 +303,6 @@ err_domains:
return ret;
}
-static void exynos_wkup_irq_mask(struct irq_data *irqd)
-{
- struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = b->drvdata;
- unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
- unsigned long mask;
- unsigned long flags;
-
- spin_lock_irqsave(&b->slock, flags);
-
- mask = readl(d->virt_base + reg_mask);
- mask |= 1 << irqd->hwirq;
- writel(mask, d->virt_base + reg_mask);
-
- spin_unlock_irqrestore(&b->slock, flags);
-}
-
-static void exynos_wkup_irq_ack(struct irq_data *irqd)
-{
- struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = b->drvdata;
- unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
-
- writel(1 << irqd->hwirq, d->virt_base + pend);
-}
-
-static void exynos_wkup_irq_unmask(struct irq_data *irqd)
-{
- struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
- struct samsung_pinctrl_drv_data *d = b->drvdata;
- unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
- unsigned long mask;
- unsigned long flags;
-
- /*
- * Ack level interrupts right before unmask
- *
- * If we don't do this we'll get a double-interrupt. Level triggered
- * interrupts must not fire an interrupt if the level is not
- * _currently_ active, even if it was active while the interrupt was
- * masked.
- */
- if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
- exynos_wkup_irq_ack(irqd);
-
- spin_lock_irqsave(&b->slock, flags);
-
- mask = readl(d->virt_base + reg_mask);
- mask &= ~(1 << irqd->hwirq);
- writel(mask, d->virt_base + reg_mask);
-
- spin_unlock_irqrestore(&b->slock, flags);
-}
-
-static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
-{
- struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
- struct samsung_pin_bank_type *bank_type = bank->type;
- struct samsung_pinctrl_drv_data *d = bank->drvdata;
- unsigned int pin = irqd->hwirq;
- unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
- unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
- unsigned long con, trig_type;
- unsigned long flags;
- unsigned int mask;
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- trig_type = EXYNOS_EINT_EDGE_RISING;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- trig_type = EXYNOS_EINT_EDGE_FALLING;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- trig_type = EXYNOS_EINT_EDGE_BOTH;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- trig_type = EXYNOS_EINT_LEVEL_HIGH;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- trig_type = EXYNOS_EINT_LEVEL_LOW;
- break;
- default:
- pr_err("unsupported external interrupt type\n");
- return -EINVAL;
- }
-
- if (type & IRQ_TYPE_EDGE_BOTH)
- __irq_set_handler_locked(irqd->irq, handle_edge_irq);
- else
- __irq_set_handler_locked(irqd->irq, handle_level_irq);
-
- con = readl(d->virt_base + reg_con);
- con &= ~(EXYNOS_EINT_CON_MASK << shift);
- con |= trig_type << shift;
- writel(con, d->virt_base + reg_con);
-
- reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
- shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
- mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
-
- spin_lock_irqsave(&bank->slock, flags);
-
- con = readl(d->virt_base + reg_con);
- con &= ~(mask << shift);
- con |= EXYNOS_EINT_FUNC << shift;
- writel(con, d->virt_base + reg_con);
-
- spin_unlock_irqrestore(&bank->slock, flags);
-
- return 0;
-}
-
static u32 exynos_eint_wake_mask = 0xffffffff;
u32 exynos_get_eint_wake_mask(void)
@@ -417,13 +328,18 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
/*
* irq_chip for wakeup interrupts
*/
-static struct irq_chip exynos_wkup_irq_chip = {
- .name = "exynos_wkup_irq_chip",
- .irq_unmask = exynos_wkup_irq_unmask,
- .irq_mask = exynos_wkup_irq_mask,
- .irq_ack = exynos_wkup_irq_ack,
- .irq_set_type = exynos_wkup_irq_set_type,
- .irq_set_wake = exynos_wkup_irq_set_wake,
+static struct exynos_irq_chip exynos_wkup_irq_chip = {
+ .chip = {
+ .name = "exynos_wkup_irq_chip",
+ .irq_unmask = exynos_irq_unmask,
+ .irq_mask = exynos_irq_mask,
+ .irq_ack = exynos_irq_ack,
+ .irq_set_type = exynos_irq_set_type,
+ .irq_set_wake = exynos_wkup_irq_set_wake,
+ },
+ .eint_con = EXYNOS_WKUP_ECON_OFFSET,
+ .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
+ .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
};
/* interrupt handler for wakeup interrupts 0..15 */
@@ -464,7 +380,6 @@ static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
struct irq_chip *chip = irq_get_chip(irq);
struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
- struct samsung_pin_ctrl *ctrl = d->ctrl;
unsigned long pend;
unsigned long mask;
int i;
@@ -473,8 +388,10 @@ static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
for (i = 0; i < eintd->nr_banks; ++i) {
struct samsung_pin_bank *b = eintd->banks[i];
- pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
- mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
+ pend = readl(d->virt_base + EXYNOS_WKUP_EPEND_OFFSET
+ + b->eint_offset);
+ mask = readl(d->virt_base + EXYNOS_WKUP_EMASK_OFFSET
+ + b->eint_offset);
exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
}
@@ -484,7 +401,8 @@ static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
static int exynos_wkup_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
- irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip, handle_level_irq);
+ irq_set_chip_and_handler(virq, &exynos_wkup_irq_chip.chip,
+ handle_level_irq);
irq_set_chip_data(virq, h->host_data);
set_irq_flags(virq, IRQF_VALID);
return 0;
@@ -703,13 +621,6 @@ struct samsung_pin_ctrl s5pv210_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = s5pv210_pin_bank,
.nr_banks = ARRAY_SIZE(s5pv210_pin_bank),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
@@ -758,10 +669,6 @@ struct samsung_pin_ctrl exynos3250_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos3250_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos3250_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -770,13 +677,6 @@ struct samsung_pin_ctrl exynos3250_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos3250_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos3250_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
@@ -843,10 +743,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos4210_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -855,13 +751,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos4210_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos4210_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
@@ -942,10 +831,6 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos4x12_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos4x12_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -954,13 +839,6 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos4x12_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos4x12_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
@@ -970,10 +848,6 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
/* pin-controller instance 2 data */
.pin_banks = exynos4x12_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos4x12_pin_banks2),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -982,10 +856,6 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
/* pin-controller instance 3 data */
.pin_banks = exynos4x12_pin_banks3,
.nr_banks = ARRAY_SIZE(exynos4x12_pin_banks3),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -1058,13 +928,6 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos5250_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos5250_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
@@ -1074,10 +937,6 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos5250_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos5250_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -1086,10 +945,6 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
/* pin-controller instance 2 data */
.pin_banks = exynos5250_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos5250_pin_banks2),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -1098,10 +953,6 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
/* pin-controller instance 3 data */
.pin_banks = exynos5250_pin_banks3,
.nr_banks = ARRAY_SIZE(exynos5250_pin_banks3),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
@@ -1158,13 +1009,6 @@ struct samsung_pin_ctrl exynos5260_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos5260_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos5260_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.label = "exynos5260-gpio-ctrl0",
@@ -1172,20 +1016,12 @@ struct samsung_pin_ctrl exynos5260_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos5260_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos5260_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5260-gpio-ctrl1",
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos5260_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos5260_pin_banks2),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5260-gpio-ctrl2",
},
@@ -1256,13 +1092,6 @@ struct samsung_pin_ctrl exynos5420_pin_ctrl[] = {
/* pin-controller instance 0 data */
.pin_banks = exynos5420_pin_banks0,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks0),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .weint_con = EXYNOS_WKUP_ECON_OFFSET,
- .weint_mask = EXYNOS_WKUP_EMASK_OFFSET,
- .weint_pend = EXYNOS_WKUP_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.eint_wkup_init = exynos_eint_wkup_init,
.label = "exynos5420-gpio-ctrl0",
@@ -1270,40 +1099,24 @@ struct samsung_pin_ctrl exynos5420_pin_ctrl[] = {
/* pin-controller instance 1 data */
.pin_banks = exynos5420_pin_banks1,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks1),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5420-gpio-ctrl1",
}, {
/* pin-controller instance 2 data */
.pin_banks = exynos5420_pin_banks2,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks2),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5420-gpio-ctrl2",
}, {
/* pin-controller instance 3 data */
.pin_banks = exynos5420_pin_banks3,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks3),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5420-gpio-ctrl3",
}, {
/* pin-controller instance 4 data */
.pin_banks = exynos5420_pin_banks4,
.nr_banks = ARRAY_SIZE(exynos5420_pin_banks4),
- .geint_con = EXYNOS_GPIO_ECON_OFFSET,
- .geint_mask = EXYNOS_GPIO_EMASK_OFFSET,
- .geint_pend = EXYNOS_GPIO_EPEND_OFFSET,
- .svc = EXYNOS_SVC_OFFSET,
.eint_gpio_init = exynos_eint_gpio_init,
.label = "exynos5420-gpio-ctrl4",
},
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h
index 3c91c357792f..3c91c357792f 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.h
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 8fe2ab0a7698..603da2f9dd95 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -23,7 +23,7 @@
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
-#include "core.h"
+#include "../core.h"
/* EXYNOS5440 GPIO and Pinctrl register offsets */
#define GPIO_MUX 0x00
@@ -371,13 +371,6 @@ static int exynos5440_pinmux_enable(struct pinctrl_dev *pctldev, unsigned select
return 0;
}
-/* disable a specified pinmux by writing to registers */
-static void exynos5440_pinmux_disable(struct pinctrl_dev *pctldev,
- unsigned selector, unsigned group)
-{
- exynos5440_pinmux_setup(pctldev, selector, group, false);
-}
-
/*
* The calls to gpio_direction_output() and gpio_direction_input()
* leads to this function call (via the pinctrl_gpio_direction_{input|output}()
@@ -395,7 +388,6 @@ static const struct pinmux_ops exynos5440_pinmux_ops = {
.get_function_name = exynos5440_pinmux_get_fname,
.get_function_groups = exynos5440_pinmux_get_groups,
.enable = exynos5440_pinmux_enable,
- .disable = exynos5440_pinmux_disable,
.gpio_set_direction = exynos5440_pinmux_gpio_set_direction,
};
diff --git a/drivers/pinctrl/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
index ad3eaad17001..ad3eaad17001 100644
--- a/drivers/pinctrl/pinctrl-s3c24xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
diff --git a/drivers/pinctrl/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index 89143c903000..89143c903000 100644
--- a/drivers/pinctrl/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 3e61d0f8f146..b07406da333c 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -30,7 +30,7 @@
#include <linux/spinlock.h>
#include <linux/syscore_ops.h>
-#include "core.h"
+#include "../core.h"
#include "pinctrl-samsung.h"
#define GROUP_SUFFIX "-grp"
@@ -40,13 +40,14 @@
/* list of all possible config options supported */
static struct pin_config {
- char *prop_cfg;
- unsigned int cfg_type;
-} pcfgs[] = {
+ const char *property;
+ enum pincfg_type param;
+} cfg_params[] = {
{ "samsung,pin-pud", PINCFG_TYPE_PUD },
{ "samsung,pin-drv", PINCFG_TYPE_DRV },
{ "samsung,pin-con-pdn", PINCFG_TYPE_CON_PDN },
{ "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN },
+ { "samsung,pin-val", PINCFG_TYPE_DAT },
};
/* Global list of devices (struct samsung_pinctrl_drv_data) */
@@ -59,163 +60,242 @@ static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
return container_of(gc, struct samsung_pin_bank, gpio_chip);
}
-/* check if the selector is a valid pin group selector */
static int samsung_get_group_count(struct pinctrl_dev *pctldev)
{
- struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
- drvdata = pinctrl_dev_get_drvdata(pctldev);
- return drvdata->nr_groups;
+ return pmx->nr_groups;
}
-/* return the name of the group selected by the group selector */
static const char *samsung_get_group_name(struct pinctrl_dev *pctldev,
- unsigned selector)
+ unsigned group)
{
- struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
- drvdata = pinctrl_dev_get_drvdata(pctldev);
- return drvdata->pin_groups[selector].name;
+ return pmx->pin_groups[group].name;
}
-/* return the pin numbers associated with the specified group */
static int samsung_get_group_pins(struct pinctrl_dev *pctldev,
- unsigned selector, const unsigned **pins, unsigned *num_pins)
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
{
- struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pinctrl_drv_data *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = pmx->pin_groups[group].pins;
+ *num_pins = pmx->pin_groups[group].num_pins;
- drvdata = pinctrl_dev_get_drvdata(pctldev);
- *pins = drvdata->pin_groups[selector].pins;
- *num_pins = drvdata->pin_groups[selector].num_pins;
return 0;
}
-/* create pinctrl_map entries by parsing device tree nodes */
-static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
- struct device_node *np, struct pinctrl_map **maps,
- unsigned *nmaps)
+static int reserve_map(struct device *dev, struct pinctrl_map **map,
+ unsigned *reserved_maps, unsigned *num_maps,
+ unsigned reserve)
{
- struct device *dev = pctldev->dev;
- struct pinctrl_map *map;
- unsigned long *cfg = NULL;
- char *gname, *fname;
- int cfg_cnt = 0, map_cnt = 0, idx = 0;
-
- /* count the number of config options specfied in the node */
- for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
- if (of_find_property(np, pcfgs[idx].prop_cfg, NULL))
- cfg_cnt++;
- }
+ unsigned old_num = *reserved_maps;
+ unsigned new_num = *num_maps + reserve;
+ struct pinctrl_map *new_map;
- /*
- * Find out the number of map entries to create. All the config options
- * can be accomadated into a single config map entry.
- */
- if (cfg_cnt)
- map_cnt = 1;
- if (of_find_property(np, "samsung,pin-function", NULL))
- map_cnt++;
- if (!map_cnt) {
- dev_err(dev, "node %s does not have either config or function "
- "configurations\n", np->name);
- return -EINVAL;
- }
+ if (old_num >= new_num)
+ return 0;
- /* Allocate memory for pin-map entries */
- map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL);
- if (!map) {
- dev_err(dev, "could not alloc memory for pin-maps\n");
+ new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
+ if (!new_map) {
+ dev_err(dev, "krealloc(map) failed\n");
return -ENOMEM;
}
- *nmaps = 0;
- /*
- * Allocate memory for pin group name. The pin group name is derived
- * from the node name from which these map entries are be created.
- */
- gname = kzalloc(strlen(np->name) + GSUFFIX_LEN, GFP_KERNEL);
- if (!gname) {
- dev_err(dev, "failed to alloc memory for group name\n");
- goto free_map;
+ memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
+
+ *map = new_map;
+ *reserved_maps = new_num;
+
+ return 0;
+}
+
+static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
+ unsigned *num_maps, const char *group,
+ const char *function)
+{
+ if (WARN_ON(*num_maps == *reserved_maps))
+ return -ENOSPC;
+
+ (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)[*num_maps].data.mux.group = group;
+ (*map)[*num_maps].data.mux.function = function;
+ (*num_maps)++;
+
+ return 0;
+}
+
+static int add_map_configs(struct device *dev, struct pinctrl_map **map,
+ unsigned *reserved_maps, unsigned *num_maps,
+ const char *group, unsigned long *configs,
+ unsigned num_configs)
+{
+ unsigned long *dup_configs;
+
+ if (WARN_ON(*num_maps == *reserved_maps))
+ return -ENOSPC;
+
+ dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
+ GFP_KERNEL);
+ if (!dup_configs) {
+ dev_err(dev, "kmemdup(configs) failed\n");
+ return -ENOMEM;
}
- sprintf(gname, "%s%s", np->name, GROUP_SUFFIX);
- /*
- * don't have config options? then skip over to creating function
- * map entries.
- */
- if (!cfg_cnt)
- goto skip_cfgs;
-
- /* Allocate memory for config entries */
- cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL);
- if (!cfg) {
- dev_err(dev, "failed to alloc memory for configs\n");
- goto free_gname;
+ (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ (*map)[*num_maps].data.configs.group_or_pin = group;
+ (*map)[*num_maps].data.configs.configs = dup_configs;
+ (*map)[*num_maps].data.configs.num_configs = num_configs;
+ (*num_maps)++;
+
+ return 0;
+}
+
+static int add_config(struct device *dev, unsigned long **configs,
+ unsigned *num_configs, unsigned long config)
+{
+ unsigned old_num = *num_configs;
+ unsigned new_num = old_num + 1;
+ unsigned long *new_configs;
+
+ new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
+ GFP_KERNEL);
+ if (!new_configs) {
+ dev_err(dev, "krealloc(configs) failed\n");
+ return -ENOMEM;
}
- /* Prepare a list of config settings */
- for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) {
- u32 value;
- if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value))
- cfg[cfg_cnt++] =
- PINCFG_PACK(pcfgs[idx].cfg_type, value);
+ new_configs[old_num] = config;
+
+ *configs = new_configs;
+ *num_configs = new_num;
+
+ return 0;
+}
+
+static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map,
+ unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++)
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+ kfree(map[i].data.configs.configs);
+
+ kfree(map);
+}
+
+static int samsung_dt_subnode_to_map(struct samsung_pinctrl_drv_data *drvdata,
+ struct device *dev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *reserved_maps,
+ unsigned *num_maps)
+{
+ int ret, i;
+ u32 val;
+ unsigned long config;
+ unsigned long *configs = NULL;
+ unsigned num_configs = 0;
+ unsigned reserve;
+ struct property *prop;
+ const char *group;
+ bool has_func = false;
+
+ ret = of_property_read_u32(np, "samsung,pin-function", &val);
+ if (!ret)
+ has_func = true;
+
+ for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+ ret = of_property_read_u32(np, cfg_params[i].property, &val);
+ if (!ret) {
+ config = PINCFG_PACK(cfg_params[i].param, val);
+ ret = add_config(dev, &configs, &num_configs, config);
+ if (ret < 0)
+ goto exit;
+ /* EINVAL=missing, which is fine since it's optional */
+ } else if (ret != -EINVAL) {
+ dev_err(dev, "could not parse property %s\n",
+ cfg_params[i].property);
+ }
}
- /* create the config map entry */
- map[*nmaps].data.configs.group_or_pin = gname;
- map[*nmaps].data.configs.configs = cfg;
- map[*nmaps].data.configs.num_configs = cfg_cnt;
- map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
- *nmaps += 1;
-
-skip_cfgs:
- /* create the function map entry */
- if (of_find_property(np, "samsung,pin-function", NULL)) {
- fname = kzalloc(strlen(np->name) + FSUFFIX_LEN, GFP_KERNEL);
- if (!fname) {
- dev_err(dev, "failed to alloc memory for func name\n");
- goto free_cfg;
+ reserve = 0;
+ if (has_func)
+ reserve++;
+ if (num_configs)
+ reserve++;
+ ret = of_property_count_strings(np, "samsung,pins");
+ if (ret < 0) {
+ dev_err(dev, "could not parse property samsung,pins\n");
+ goto exit;
+ }
+ reserve *= ret;
+
+ ret = reserve_map(dev, map, reserved_maps, num_maps, reserve);
+ if (ret < 0)
+ goto exit;
+
+ of_property_for_each_string(np, "samsung,pins", prop, group) {
+ if (has_func) {
+ ret = add_map_mux(map, reserved_maps,
+ num_maps, group, np->full_name);
+ if (ret < 0)
+ goto exit;
}
- sprintf(fname, "%s%s", np->name, FUNCTION_SUFFIX);
- map[*nmaps].data.mux.group = gname;
- map[*nmaps].data.mux.function = fname;
- map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
- *nmaps += 1;
+ if (num_configs) {
+ ret = add_map_configs(dev, map, reserved_maps,
+ num_maps, group, configs,
+ num_configs);
+ if (ret < 0)
+ goto exit;
+ }
}
- *maps = map;
- return 0;
+ ret = 0;
-free_cfg:
- kfree(cfg);
-free_gname:
- kfree(gname);
-free_map:
- kfree(map);
- return -ENOMEM;
+exit:
+ kfree(configs);
+ return ret;
}
-/* free the memory allocated to hold the pin-map table */
-static void samsung_dt_free_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map *map, unsigned num_maps)
+static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
{
- int idx;
-
- for (idx = 0; idx < num_maps; idx++) {
- if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) {
- kfree(map[idx].data.mux.function);
- if (!idx)
- kfree(map[idx].data.mux.group);
- } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) {
- kfree(map[idx].data.configs.configs);
- if (!idx)
- kfree(map[idx].data.configs.group_or_pin);
+ struct samsung_pinctrl_drv_data *drvdata;
+ unsigned reserved_maps;
+ struct device_node *np;
+ int ret;
+
+ drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+ reserved_maps = 0;
+ *map = NULL;
+ *num_maps = 0;
+
+ if (!of_get_child_count(np_config))
+ return samsung_dt_subnode_to_map(drvdata, pctldev->dev,
+ np_config, map,
+ &reserved_maps,
+ num_maps);
+
+ for_each_child_of_node(np_config, np) {
+ ret = samsung_dt_subnode_to_map(drvdata, pctldev->dev, np, map,
+ &reserved_maps, num_maps);
+ if (ret < 0) {
+ samsung_dt_free_map(pctldev, *map, *num_maps);
+ return ret;
}
- };
+ }
- kfree(map);
+ return 0;
}
/* list of pinctrl callbacks for the pinctrl core */
@@ -286,83 +366,21 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group, bool enable)
{
struct samsung_pinctrl_drv_data *drvdata;
- const unsigned int *pins;
- struct samsung_pin_bank *bank;
- void __iomem *reg;
- u32 mask, shift, data, pin_offset, cnt;
- unsigned long flags;
-
- drvdata = pinctrl_dev_get_drvdata(pctldev);
- pins = drvdata->pin_groups[group].pins;
-
- /*
- * for each pin in the pin group selected, program the correspoding pin
- * pin function number in the config register.
- */
- for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
- struct samsung_pin_bank_type *type;
-
- pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
- &reg, &pin_offset, &bank);
- type = bank->type;
- mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
- shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
- if (shift >= 32) {
- /* Some banks have two config registers */
- shift -= 32;
- reg += 4;
- }
-
- spin_lock_irqsave(&bank->slock, flags);
-
- data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
- data &= ~(mask << shift);
- if (enable)
- data |= drvdata->pin_groups[group].func << shift;
- writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
-
- spin_unlock_irqrestore(&bank->slock, flags);
- }
-}
-
-/* enable a specified pinmux by writing to registers */
-static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
- unsigned group)
-{
- samsung_pinmux_setup(pctldev, selector, group, true);
- return 0;
-}
-
-/* disable a specified pinmux by writing to registers */
-static void samsung_pinmux_disable(struct pinctrl_dev *pctldev,
- unsigned selector, unsigned group)
-{
- samsung_pinmux_setup(pctldev, selector, group, false);
-}
-
-/*
- * The calls to gpio_direction_output() and gpio_direction_input()
- * leads to this function call (via the pinctrl_gpio_direction_{input|output}()
- * function called from the gpiolib interface).
- */
-static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range, unsigned offset, bool input)
-{
struct samsung_pin_bank_type *type;
struct samsung_pin_bank *bank;
- struct samsung_pinctrl_drv_data *drvdata;
void __iomem *reg;
- u32 data, pin_offset, mask, shift;
+ u32 mask, shift, data, pin_offset;
unsigned long flags;
+ const struct samsung_pmx_func *func;
+ const struct samsung_pin_group *grp;
- bank = gc_to_pin_bank(range->gc);
- type = bank->type;
drvdata = pinctrl_dev_get_drvdata(pctldev);
+ func = &drvdata->pmx_functions[selector];
+ grp = &drvdata->pin_groups[group];
- pin_offset = offset - bank->pin_base;
- reg = drvdata->virt_base + bank->pctl_offset +
- type->reg_offset[PINCFG_TYPE_FUNC];
-
+ pin_to_reg_bank(drvdata, grp->pins[0] - drvdata->ctrl->base,
+ &reg, &pin_offset, &bank);
+ type = bank->type;
mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
if (shift >= 32) {
@@ -373,14 +391,20 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
spin_lock_irqsave(&bank->slock, flags);
- data = readl(reg);
+ data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
data &= ~(mask << shift);
- if (!input)
- data |= FUNC_OUTPUT << shift;
- writel(data, reg);
+ if (enable)
+ data |= func->val << shift;
+ writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
spin_unlock_irqrestore(&bank->slock, flags);
+}
+/* enable a specified pinmux by writing to registers */
+static int samsung_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ samsung_pinmux_setup(pctldev, selector, group, true);
return 0;
}
@@ -390,8 +414,6 @@ static const struct pinmux_ops samsung_pinmux_ops = {
.get_function_name = samsung_pinmux_get_fname,
.get_function_groups = samsung_pinmux_get_groups,
.enable = samsung_pinmux_enable,
- .disable = samsung_pinmux_disable,
- .gpio_set_direction = samsung_pinmux_gpio_set_direction,
};
/* set or get the pin config settings for a specified pin */
@@ -540,25 +562,59 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
}
/*
- * gpiolib gpio_direction_input callback function. The setting of the pin
- * mux function as 'gpio input' will be handled by the pinctrl susbsystem
- * interface.
+ * The calls to gpio_direction_output() and gpio_direction_input()
+ * leads to this function call.
*/
+static int samsung_gpio_set_direction(struct gpio_chip *gc,
+ unsigned offset, bool input)
+{
+ struct samsung_pin_bank_type *type;
+ struct samsung_pin_bank *bank;
+ struct samsung_pinctrl_drv_data *drvdata;
+ void __iomem *reg;
+ u32 data, mask, shift;
+ unsigned long flags;
+
+ bank = gc_to_pin_bank(gc);
+ type = bank->type;
+ drvdata = bank->drvdata;
+
+ reg = drvdata->virt_base + bank->pctl_offset +
+ type->reg_offset[PINCFG_TYPE_FUNC];
+
+ mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+ shift = offset * type->fld_width[PINCFG_TYPE_FUNC];
+ if (shift >= 32) {
+ /* Some banks have two config registers */
+ shift -= 32;
+ reg += 4;
+ }
+
+ spin_lock_irqsave(&bank->slock, flags);
+
+ data = readl(reg);
+ data &= ~(mask << shift);
+ if (!input)
+ data |= FUNC_OUTPUT << shift;
+ writel(data, reg);
+
+ spin_unlock_irqrestore(&bank->slock, flags);
+
+ return 0;
+}
+
+/* gpiolib gpio_direction_input callback function. */
static int samsung_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
- return pinctrl_gpio_direction_input(gc->base + offset);
+ return samsung_gpio_set_direction(gc, offset, true);
}
-/*
- * gpiolib gpio_direction_output callback function. The setting of the pin
- * mux function as 'gpio output' will be handled by the pinctrl susbsystem
- * interface.
- */
+/* gpiolib gpio_direction_output callback function. */
static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
samsung_gpio_set(gc, offset, value);
- return pinctrl_gpio_direction_output(gc->base + offset);
+ return samsung_gpio_set_direction(gc, offset, false);
}
/*
@@ -578,87 +634,115 @@ static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return (virq) ? : -ENXIO;
}
-/*
- * Parse the pin names listed in the 'samsung,pins' property and convert it
- * into a list of gpio numbers are create a pin group from it.
- */
-static int samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
- struct device_node *cfg_np,
- struct pinctrl_desc *pctl,
- unsigned int **pin_list,
- unsigned int *npins)
+static struct samsung_pin_group *samsung_pinctrl_create_groups(
+ struct device *dev,
+ struct samsung_pinctrl_drv_data *drvdata,
+ unsigned int *cnt)
{
- struct device *dev = &pdev->dev;
- struct property *prop;
- struct pinctrl_pin_desc const *pdesc = pctl->pins;
- unsigned int idx = 0, cnt;
- const char *pin_name;
+ struct pinctrl_desc *ctrldesc = &drvdata->pctl;
+ struct samsung_pin_group *groups, *grp;
+ const struct pinctrl_pin_desc *pdesc;
+ int i;
- *npins = of_property_count_strings(cfg_np, "samsung,pins");
- if (IS_ERR_VALUE(*npins)) {
- dev_err(dev, "invalid pin list in %s node", cfg_np->name);
+ groups = devm_kzalloc(dev, ctrldesc->npins * sizeof(*groups),
+ GFP_KERNEL);
+ if (!groups)
+ return ERR_PTR(-EINVAL);
+ grp = groups;
+
+ pdesc = ctrldesc->pins;
+ for (i = 0; i < ctrldesc->npins; ++i, ++pdesc, ++grp) {
+ grp->name = pdesc->name;
+ grp->pins = &pdesc->number;
+ grp->num_pins = 1;
+ }
+
+ *cnt = ctrldesc->npins;
+ return groups;
+}
+
+static int samsung_pinctrl_create_function(struct device *dev,
+ struct samsung_pinctrl_drv_data *drvdata,
+ struct device_node *func_np,
+ struct samsung_pmx_func *func)
+{
+ int npins;
+ int ret;
+ int i;
+
+ if (of_property_read_u32(func_np, "samsung,pin-function", &func->val))
+ return 0;
+
+ npins = of_property_count_strings(func_np, "samsung,pins");
+ if (npins < 1) {
+ dev_err(dev, "invalid pin list in %s node", func_np->name);
return -EINVAL;
}
- *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL);
- if (!*pin_list) {
- dev_err(dev, "failed to allocate memory for pin list\n");
+ func->name = func_np->full_name;
+
+ func->groups = devm_kzalloc(dev, npins * sizeof(char *), GFP_KERNEL);
+ if (!func->groups)
return -ENOMEM;
- }
- of_property_for_each_string(cfg_np, "samsung,pins", prop, pin_name) {
- for (cnt = 0; cnt < pctl->npins; cnt++) {
- if (pdesc[cnt].name) {
- if (!strcmp(pin_name, pdesc[cnt].name)) {
- (*pin_list)[idx++] = pdesc[cnt].number;
- break;
- }
- }
- }
- if (cnt == pctl->npins) {
- dev_err(dev, "pin %s not valid in %s node\n",
- pin_name, cfg_np->name);
- devm_kfree(dev, *pin_list);
- return -EINVAL;
+ for (i = 0; i < npins; ++i) {
+ const char *gname;
+
+ ret = of_property_read_string_index(func_np, "samsung,pins",
+ i, &gname);
+ if (ret) {
+ dev_err(dev,
+ "failed to read pin name %d from %s node\n",
+ i, func_np->name);
+ return ret;
}
+
+ func->groups[i] = gname;
}
- return 0;
+ func->num_groups = npins;
+ return 1;
}
-/*
- * Parse the information about all the available pin groups and pin functions
- * from device node of the pin-controller. A pin group is formed with all
- * the pins listed in the "samsung,pins" property.
- */
-static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
- struct samsung_pinctrl_drv_data *drvdata)
+static struct samsung_pmx_func *samsung_pinctrl_create_functions(
+ struct device *dev,
+ struct samsung_pinctrl_drv_data *drvdata,
+ unsigned int *cnt)
{
- struct device *dev = &pdev->dev;
+ struct samsung_pmx_func *functions, *func;
struct device_node *dev_np = dev->of_node;
struct device_node *cfg_np;
- struct samsung_pin_group *groups, *grp;
- struct samsung_pmx_func *functions, *func;
- unsigned *pin_list;
- unsigned int npins, grp_cnt, func_idx = 0;
- char *gname, *fname;
+ unsigned int func_cnt = 0;
int ret;
- grp_cnt = of_get_child_count(dev_np);
- if (!grp_cnt)
- return -EINVAL;
+ /*
+ * Iterate over all the child nodes of the pin controller node
+ * and create pin groups and pin function lists.
+ */
+ for_each_child_of_node(dev_np, cfg_np) {
+ struct device_node *func_np;
- groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL);
- if (!groups) {
- dev_err(dev, "failed allocate memory for ping group list\n");
- return -EINVAL;
+ if (!of_get_child_count(cfg_np)) {
+ if (!of_find_property(cfg_np,
+ "samsung,pin-function", NULL))
+ continue;
+ ++func_cnt;
+ continue;
+ }
+
+ for_each_child_of_node(cfg_np, func_np) {
+ if (!of_find_property(func_np,
+ "samsung,pin-function", NULL))
+ continue;
+ ++func_cnt;
+ }
}
- grp = groups;
- functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL);
+ functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
+ GFP_KERNEL);
if (!functions) {
dev_err(dev, "failed to allocate memory for function list\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
func = functions;
@@ -666,61 +750,68 @@ static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
* Iterate over all the child nodes of the pin controller node
* and create pin groups and pin function lists.
*/
+ func_cnt = 0;
for_each_child_of_node(dev_np, cfg_np) {
- u32 function;
- if (!of_find_property(cfg_np, "samsung,pins", NULL))
+ struct device_node *func_np;
+
+ if (!of_get_child_count(cfg_np)) {
+ ret = samsung_pinctrl_create_function(dev, drvdata,
+ cfg_np, func);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ if (ret > 0) {
+ ++func;
+ ++func_cnt;
+ }
continue;
+ }
- ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np,
- &drvdata->pctl, &pin_list, &npins);
- if (ret)
- return ret;
-
- /* derive pin group name from the node name */
- gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
- GFP_KERNEL);
- if (!gname) {
- dev_err(dev, "failed to alloc memory for group name\n");
- return -ENOMEM;
+ for_each_child_of_node(cfg_np, func_np) {
+ ret = samsung_pinctrl_create_function(dev, drvdata,
+ func_np, func);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ if (ret > 0) {
+ ++func;
+ ++func_cnt;
+ }
}
- sprintf(gname, "%s%s", cfg_np->name, GROUP_SUFFIX);
+ }
- grp->name = gname;
- grp->pins = pin_list;
- grp->num_pins = npins;
- of_property_read_u32(cfg_np, "samsung,pin-function", &function);
- grp->func = function;
- grp++;
+ *cnt = func_cnt;
+ return functions;
+}
- if (!of_find_property(cfg_np, "samsung,pin-function", NULL))
- continue;
+/*
+ * Parse the information about all the available pin groups and pin functions
+ * from device node of the pin-controller. A pin group is formed with all
+ * the pins listed in the "samsung,pins" property.
+ */
- /* derive function name from the node name */
- fname = devm_kzalloc(dev, strlen(cfg_np->name) + FSUFFIX_LEN,
- GFP_KERNEL);
- if (!fname) {
- dev_err(dev, "failed to alloc memory for func name\n");
- return -ENOMEM;
- }
- sprintf(fname, "%s%s", cfg_np->name, FUNCTION_SUFFIX);
-
- func->name = fname;
- func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL);
- if (!func->groups) {
- dev_err(dev, "failed to alloc memory for group list "
- "in pin function");
- return -ENOMEM;
- }
- func->groups[0] = gname;
- func->num_groups = 1;
- func++;
- func_idx++;
+static int samsung_pinctrl_parse_dt(struct platform_device *pdev,
+ struct samsung_pinctrl_drv_data *drvdata)
+{
+ struct device *dev = &pdev->dev;
+ struct samsung_pin_group *groups;
+ struct samsung_pmx_func *functions;
+ unsigned int grp_cnt = 0, func_cnt = 0;
+
+ groups = samsung_pinctrl_create_groups(dev, drvdata, &grp_cnt);
+ if (IS_ERR(groups)) {
+ dev_err(dev, "failed to parse pin groups\n");
+ return PTR_ERR(groups);
+ }
+
+ functions = samsung_pinctrl_create_functions(dev, drvdata, &func_cnt);
+ if (IS_ERR(functions)) {
+ dev_err(dev, "failed to parse pin functions\n");
+ return PTR_ERR(groups);
}
drvdata->pin_groups = groups;
drvdata->nr_groups = grp_cnt;
drvdata->pmx_functions = functions;
- drvdata->nr_functions = func_idx;
+ drvdata->nr_functions = func_cnt;
return 0;
}
@@ -790,7 +881,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
pin_bank = &drvdata->ctrl->pin_banks[bank];
pin_bank->grange.name = pin_bank->name;
pin_bank->grange.id = bank;
- pin_bank->grange.pin_base = pin_bank->pin_base;
+ pin_bank->grange.pin_base = drvdata->ctrl->base
+ + pin_bank->pin_base;
pin_bank->grange.base = pin_bank->gpio_chip.base;
pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
pin_bank->grange.gc = &pin_bank->gpio_chip;
@@ -800,7 +892,19 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
return 0;
}
+static int samsung_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void samsung_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
static const struct gpio_chip samsung_gpiolib_chip = {
+ .request = samsung_gpio_request,
+ .free = samsung_gpio_free,
.set = samsung_gpio_set,
.get = samsung_gpio_get,
.direction_input = samsung_gpio_direction_input,
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index b3e41fa5798b..2b882320e8e9 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -156,13 +156,6 @@ struct samsung_pin_bank {
* @nr_banks: number of pin banks.
* @base: starting system wide pin number.
* @nr_pins: number of pins supported by the controller.
- * @geint_con: offset of the ext-gpio controller registers.
- * @geint_mask: offset of the ext-gpio interrupt mask registers.
- * @geint_pend: offset of the ext-gpio interrupt pending registers.
- * @weint_con: offset of the ext-wakeup controller registers.
- * @weint_mask: offset of the ext-wakeup interrupt mask registers.
- * @weint_pend: offset of the ext-wakeup interrupt pending registers.
- * @svc: offset of the interrupt service register.
* @eint_gpio_init: platform specific callback to setup the external gpio
* interrupts for the controller.
* @eint_wkup_init: platform specific callback to setup the external wakeup
@@ -176,16 +169,6 @@ struct samsung_pin_ctrl {
u32 base;
u32 nr_pins;
- u32 geint_con;
- u32 geint_mask;
- u32 geint_pend;
-
- u32 weint_con;
- u32 weint_mask;
- u32 weint_pend;
-
- u32 svc;
-
int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
void (*suspend)(struct samsung_pinctrl_drv_data *);
@@ -248,6 +231,7 @@ struct samsung_pmx_func {
const char *name;
const char **groups;
u8 num_groups;
+ u32 val;
};
/* list of all exported SoC specific data */
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index a9288ab01f7b..80f641ee4dea 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -409,11 +409,8 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc)
{
- int err;
- int ret;
-
- ret = gpiochip_remove(&pfc->gpio->gpio_chip);
- err = gpiochip_remove(&pfc->func->gpio_chip);
+ gpiochip_remove(&pfc->gpio->gpio_chip);
+ gpiochip_remove(&pfc->func->gpio_chip);
- return ret < 0 ? ret : err;
+ return 0;
}
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 2e688dc4a3c8..576d41b459e9 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -1726,6 +1726,133 @@ static const unsigned int audio_clkout_mux[] = {
AUDIO_CLKOUT_MARK,
};
+/* - CAN -------------------------------------------------------------------- */
+
+static const unsigned int can0_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 29),
+};
+
+static const unsigned int can0_data_mux[] = {
+ CAN0_TX_MARK, CAN0_RX_MARK,
+};
+
+static const unsigned int can0_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(7, 4), RCAR_GP_PIN(7, 3),
+};
+
+static const unsigned int can0_data_b_mux[] = {
+ CAN0_TX_B_MARK, CAN0_RX_B_MARK,
+};
+
+static const unsigned int can0_data_c_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 18),
+};
+
+static const unsigned int can0_data_c_mux[] = {
+ CAN0_TX_C_MARK, CAN0_RX_C_MARK,
+};
+
+static const unsigned int can0_data_d_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 27),
+};
+
+static const unsigned int can0_data_d_mux[] = {
+ CAN0_TX_D_MARK, CAN0_RX_D_MARK,
+};
+
+static const unsigned int can0_data_e_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 18), RCAR_GP_PIN(4, 28),
+};
+
+static const unsigned int can0_data_e_mux[] = {
+ CAN0_TX_E_MARK, CAN0_RX_E_MARK,
+};
+
+static const unsigned int can0_data_f_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+};
+
+static const unsigned int can0_data_f_mux[] = {
+ CAN0_TX_F_MARK, CAN0_RX_F_MARK,
+};
+
+static const unsigned int can1_data_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 20),
+};
+
+static const unsigned int can1_data_mux[] = {
+ CAN1_TX_MARK, CAN1_RX_MARK,
+};
+
+static const unsigned int can1_data_b_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(7, 8), RCAR_GP_PIN(7, 9),
+};
+
+static const unsigned int can1_data_b_mux[] = {
+ CAN1_TX_B_MARK, CAN1_RX_B_MARK,
+};
+
+static const unsigned int can1_data_c_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 19),
+};
+
+static const unsigned int can1_data_c_mux[] = {
+ CAN1_TX_C_MARK, CAN1_RX_C_MARK,
+};
+
+static const unsigned int can1_data_d_pins[] = {
+ /* TX, RX */
+ RCAR_GP_PIN(4, 29), RCAR_GP_PIN(4, 31),
+};
+
+static const unsigned int can1_data_d_mux[] = {
+ CAN1_TX_D_MARK, CAN1_RX_D_MARK,
+};
+
+static const unsigned int can_clk_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(7, 2),
+};
+
+static const unsigned int can_clk_mux[] = {
+ CAN_CLK_MARK,
+};
+
+static const unsigned int can_clk_b_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(5, 21),
+};
+
+static const unsigned int can_clk_b_mux[] = {
+ CAN_CLK_B_MARK,
+};
+
+static const unsigned int can_clk_c_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(4, 30),
+};
+
+static const unsigned int can_clk_c_mux[] = {
+ CAN_CLK_C_MARK,
+};
+
+static const unsigned int can_clk_d_pins[] = {
+ /* CLK */
+ RCAR_GP_PIN(7, 19),
+};
+
+static const unsigned int can_clk_d_mux[] = {
+ CAN_CLK_D_MARK,
+};
/* - DU --------------------------------------------------------------------- */
static const unsigned int du_rgb666_pins[] = {
@@ -1867,6 +1994,192 @@ static const unsigned int eth_rmii_mux[] = {
ETH_RXD0_MARK, ETH_RXD1_MARK, ETH_RX_ER_MARK, ETH_CRS_DV_MARK,
ETH_TXD0_MARK, ETH_TXD1_MARK, ETH_TX_EN_MARK, ETH_REFCLK_MARK,
};
+
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(7, 3), RCAR_GP_PIN(7, 4),
+};
+static const unsigned int hscif0_data_mux[] = {
+ HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(7, 2),
+};
+static const unsigned int hscif0_clk_mux[] = {
+ HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(7, 1), RCAR_GP_PIN(7, 0),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+ HRTS0_N_MARK, HCTS0_N_MARK,
+};
+static const unsigned int hscif0_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int hscif0_data_b_mux[] = {
+ HRX0_B_MARK, HTX0_B_MARK,
+};
+static const unsigned int hscif0_ctrl_b_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int hscif0_ctrl_b_mux[] = {
+ HRTS0_N_B_MARK, HCTS0_N_B_MARK,
+};
+static const unsigned int hscif0_data_c_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int hscif0_data_c_mux[] = {
+ HRX0_C_MARK, HTX0_C_MARK,
+};
+static const unsigned int hscif0_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif0_clk_c_mux[] = {
+ HSCK0_C_MARK,
+};
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(7, 5), RCAR_GP_PIN(7, 6),
+};
+static const unsigned int hscif1_data_mux[] = {
+ HRX1_MARK, HTX1_MARK,
+};
+static const unsigned int hscif1_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(7, 7),
+};
+static const unsigned int hscif1_clk_mux[] = {
+ HSCK1_MARK,
+};
+static const unsigned int hscif1_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(7, 9), RCAR_GP_PIN(7, 8),
+};
+static const unsigned int hscif1_ctrl_mux[] = {
+ HRTS1_N_MARK, HCTS1_N_MARK,
+};
+static const unsigned int hscif1_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 18),
+};
+static const unsigned int hscif1_data_b_mux[] = {
+ HRX1_B_MARK, HTX1_B_MARK,
+};
+static const unsigned int hscif1_data_c_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(7, 14), RCAR_GP_PIN(7, 15),
+};
+static const unsigned int hscif1_data_c_mux[] = {
+ HRX1_C_MARK, HTX1_C_MARK,
+};
+static const unsigned int hscif1_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(7, 16),
+};
+static const unsigned int hscif1_clk_c_mux[] = {
+ HSCK1_C_MARK,
+};
+static const unsigned int hscif1_ctrl_c_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(7, 18), RCAR_GP_PIN(7, 17),
+};
+static const unsigned int hscif1_ctrl_c_mux[] = {
+ HRTS1_N_C_MARK, HCTS1_N_C_MARK,
+};
+static const unsigned int hscif1_data_d_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 18),
+};
+static const unsigned int hscif1_data_d_mux[] = {
+ HRX1_D_MARK, HTX1_D_MARK,
+};
+static const unsigned int hscif1_data_e_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(7, 14), RCAR_GP_PIN(7, 15),
+};
+static const unsigned int hscif1_data_e_mux[] = {
+ HRX1_C_MARK, HTX1_C_MARK,
+};
+static const unsigned int hscif1_clk_e_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 6),
+};
+static const unsigned int hscif1_clk_e_mux[] = {
+ HSCK1_E_MARK,
+};
+static const unsigned int hscif1_ctrl_e_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 7),
+};
+static const unsigned int hscif1_ctrl_e_mux[] = {
+ HRTS1_N_E_MARK, HCTS1_N_E_MARK,
+};
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(4, 16), RCAR_GP_PIN(4, 17),
+};
+static const unsigned int hscif2_data_mux[] = {
+ HRX2_MARK, HTX2_MARK,
+};
+static const unsigned int hscif2_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(4, 15),
+};
+static const unsigned int hscif2_clk_mux[] = {
+ HSCK2_MARK,
+};
+static const unsigned int hscif2_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13),
+};
+static const unsigned int hscif2_ctrl_mux[] = {
+ HRTS2_N_MARK, HCTS2_N_MARK,
+};
+static const unsigned int hscif2_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 20), RCAR_GP_PIN(1, 22),
+};
+static const unsigned int hscif2_data_b_mux[] = {
+ HRX2_B_MARK, HTX2_B_MARK,
+};
+static const unsigned int hscif2_ctrl_b_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 21),
+};
+static const unsigned int hscif2_ctrl_b_mux[] = {
+ HRTS2_N_B_MARK, HCTS2_N_B_MARK,
+};
+static const unsigned int hscif2_data_c_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int hscif2_data_c_mux[] = {
+ HRX2_C_MARK, HTX2_C_MARK,
+};
+static const unsigned int hscif2_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif2_clk_c_mux[] = {
+ HSCK2_C_MARK,
+};
+static const unsigned int hscif2_data_d_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 20), RCAR_GP_PIN(5, 31),
+};
+static const unsigned int hscif2_data_d_mux[] = {
+ HRX2_B_MARK, HTX2_D_MARK,
+};
/* - I2C0 ------------------------------------------------------------------- */
static const unsigned int i2c0_pins[] = {
/* SCL, SDA */
@@ -3869,6 +4182,20 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(audio_clk_b_b),
SH_PFC_PIN_GROUP(audio_clk_c),
SH_PFC_PIN_GROUP(audio_clkout),
+ SH_PFC_PIN_GROUP(can0_data),
+ SH_PFC_PIN_GROUP(can0_data_b),
+ SH_PFC_PIN_GROUP(can0_data_c),
+ SH_PFC_PIN_GROUP(can0_data_d),
+ SH_PFC_PIN_GROUP(can0_data_e),
+ SH_PFC_PIN_GROUP(can0_data_f),
+ SH_PFC_PIN_GROUP(can1_data),
+ SH_PFC_PIN_GROUP(can1_data_b),
+ SH_PFC_PIN_GROUP(can1_data_c),
+ SH_PFC_PIN_GROUP(can1_data_d),
+ SH_PFC_PIN_GROUP(can_clk),
+ SH_PFC_PIN_GROUP(can_clk_b),
+ SH_PFC_PIN_GROUP(can_clk_c),
+ SH_PFC_PIN_GROUP(can_clk_d),
SH_PFC_PIN_GROUP(du_rgb666),
SH_PFC_PIN_GROUP(du_rgb888),
SH_PFC_PIN_GROUP(du_clk_out_0),
@@ -3885,6 +4212,32 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(eth_magic),
SH_PFC_PIN_GROUP(eth_mdio),
SH_PFC_PIN_GROUP(eth_rmii),
+ SH_PFC_PIN_GROUP(hscif0_data),
+ SH_PFC_PIN_GROUP(hscif0_clk),
+ SH_PFC_PIN_GROUP(hscif0_ctrl),
+ SH_PFC_PIN_GROUP(hscif0_data_b),
+ SH_PFC_PIN_GROUP(hscif0_ctrl_b),
+ SH_PFC_PIN_GROUP(hscif0_data_c),
+ SH_PFC_PIN_GROUP(hscif0_clk_c),
+ SH_PFC_PIN_GROUP(hscif1_data),
+ SH_PFC_PIN_GROUP(hscif1_clk),
+ SH_PFC_PIN_GROUP(hscif1_ctrl),
+ SH_PFC_PIN_GROUP(hscif1_data_b),
+ SH_PFC_PIN_GROUP(hscif1_data_c),
+ SH_PFC_PIN_GROUP(hscif1_clk_c),
+ SH_PFC_PIN_GROUP(hscif1_ctrl_c),
+ SH_PFC_PIN_GROUP(hscif1_data_d),
+ SH_PFC_PIN_GROUP(hscif1_data_e),
+ SH_PFC_PIN_GROUP(hscif1_clk_e),
+ SH_PFC_PIN_GROUP(hscif1_ctrl_e),
+ SH_PFC_PIN_GROUP(hscif2_data),
+ SH_PFC_PIN_GROUP(hscif2_clk),
+ SH_PFC_PIN_GROUP(hscif2_ctrl),
+ SH_PFC_PIN_GROUP(hscif2_data_b),
+ SH_PFC_PIN_GROUP(hscif2_ctrl_b),
+ SH_PFC_PIN_GROUP(hscif2_data_c),
+ SH_PFC_PIN_GROUP(hscif2_clk_c),
+ SH_PFC_PIN_GROUP(hscif2_data_d),
SH_PFC_PIN_GROUP(i2c0),
SH_PFC_PIN_GROUP(i2c0_b),
SH_PFC_PIN_GROUP(i2c0_c),
@@ -4155,6 +4508,30 @@ static const char * const audio_clk_groups[] = {
"audio_clkout",
};
+static const char * const can0_groups[] = {
+ "can0_data_a",
+ "can0_data_b",
+ "can0_data_c",
+ "can0_data_d",
+ "can0_data_e",
+ "can0_data_f",
+ "can_clk_a",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
+static const char * const can1_groups[] = {
+ "can1_data_a",
+ "can1_data_b",
+ "can1_data_c",
+ "can1_data_d",
+ "can_clk_a",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+};
+
static const char * const du_groups[] = {
"du_rgb666",
"du_rgb888",
@@ -4183,6 +4560,41 @@ static const char * const eth_groups[] = {
"eth_rmii",
};
+static const char * const hscif0_groups[] = {
+ "hscif0_data",
+ "hscif0_clk",
+ "hscif0_ctrl",
+ "hscif0_data_b",
+ "hscif0_ctrl_b",
+ "hscif0_data_c",
+ "hscif0_clk_c",
+};
+
+static const char * const hscif1_groups[] = {
+ "hscif1_data",
+ "hscif1_clk",
+ "hscif1_ctrl",
+ "hscif1_data_b",
+ "hscif1_data_c",
+ "hscif1_clk_c",
+ "hscif1_ctrl_c",
+ "hscif1_data_d",
+ "hscif1_data_e",
+ "hscif1_clk_e",
+ "hscif1_ctrl_e",
+};
+
+static const char * const hscif2_groups[] = {
+ "hscif2_data",
+ "hscif2_clk",
+ "hscif2_ctrl",
+ "hscif2_data_b",
+ "hscif2_ctrl_b",
+ "hscif2_data_c",
+ "hscif2_clk_c",
+ "hscif2_data_d",
+};
+
static const char * const i2c0_groups[] = {
"i2c0",
"i2c0_b",
@@ -4543,10 +4955,15 @@ static const char * const vin2_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
+ SH_PFC_FUNCTION(can0),
+ SH_PFC_FUNCTION(can1),
SH_PFC_FUNCTION(du),
SH_PFC_FUNCTION(du0),
SH_PFC_FUNCTION(du1),
SH_PFC_FUNCTION(eth),
+ SH_PFC_FUNCTION(hscif0),
+ SH_PFC_FUNCTION(hscif1),
+ SH_PFC_FUNCTION(hscif2),
SH_PFC_FUNCTION(i2c0),
SH_PFC_FUNCTION(i2c1),
SH_PFC_FUNCTION(i2c2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index ee370de4609a..0bd8f4401b42 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -3842,7 +3842,8 @@ static int sh73a0_pinmux_soc_init(struct sh_pfc *pfc)
cfg.init_data = &sh73a0_vccq_mc0_init_data;
cfg.driver_data = pfc;
- data->vccq_mc0 = regulator_register(&sh73a0_vccq_mc0_desc, &cfg);
+ data->vccq_mc0 = devm_regulator_register(pfc->dev,
+ &sh73a0_vccq_mc0_desc, &cfg);
if (IS_ERR(data->vccq_mc0)) {
ret = PTR_ERR(data->vccq_mc0);
dev_err(pfc->dev, "Failed to register VCCQ MC0 regulator: %d\n",
@@ -3855,16 +3856,8 @@ static int sh73a0_pinmux_soc_init(struct sh_pfc *pfc)
return 0;
}
-static void sh73a0_pinmux_soc_exit(struct sh_pfc *pfc)
-{
- struct sh73a0_pinmux_data *data = pfc->soc_data;
-
- regulator_unregister(data->vccq_mc0);
-}
-
static const struct sh_pfc_soc_operations sh73a0_pinmux_ops = {
.init = sh73a0_pinmux_soc_init,
- .exit = sh73a0_pinmux_soc_exit,
.get_bias = sh73a0_pinmux_get_bias,
.set_bias = sh73a0_pinmux_set_bias,
};
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index e758af95c209..11db3ee39d40 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -345,27 +345,6 @@ done:
return ret;
}
-static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector,
- unsigned group)
-{
- struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
- struct sh_pfc *pfc = pmx->pfc;
- const struct sh_pfc_pin_group *grp = &pfc->info->groups[group];
- unsigned long flags;
- unsigned int i;
-
- spin_lock_irqsave(&pfc->lock, flags);
-
- for (i = 0; i < grp->nr_pins; ++i) {
- int idx = sh_pfc_get_pin_index(pfc, grp->pins[i]);
- struct sh_pfc_pin_config *cfg = &pmx->configs[idx];
-
- cfg->type = PINMUX_TYPE_NONE;
- }
-
- spin_unlock_irqrestore(&pfc->lock, flags);
-}
-
static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
@@ -464,7 +443,6 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = {
.get_function_name = sh_pfc_get_function_name,
.get_function_groups = sh_pfc_get_function_groups,
.enable = sh_pfc_func_enable,
- .disable = sh_pfc_func_disable,
.gpio_request_enable = sh_pfc_gpio_request_enable,
.gpio_disable_free = sh_pfc_gpio_disable_free,
.gpio_set_direction = sh_pfc_gpio_set_direction,
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 014f5b1fee55..4c1d7c68666d 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -186,15 +186,6 @@ static int sirfsoc_pinmux_enable(struct pinctrl_dev *pmxdev, unsigned selector,
return 0;
}
-static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector,
- unsigned group)
-{
- struct sirfsoc_pmx *spmx;
-
- spmx = pinctrl_dev_get_drvdata(pmxdev);
- sirfsoc_pinmux_endisable(spmx, selector, false);
-}
-
static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
{
return sirfsoc_pmxfunc_cnt;
@@ -240,7 +231,6 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
static struct pinmux_ops sirfsoc_pinmux_ops = {
.enable = sirfsoc_pinmux_enable,
- .disable = sirfsoc_pinmux_disable,
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
.get_function_name = sirfsoc_pinmux_get_func_name,
.get_function_groups = sirfsoc_pinmux_get_groups,
diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 04d93e602674..9ef18eb958e1 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -48,6 +48,7 @@ config PINCTRL_SPEAR1340
config PINCTRL_SPEAR_PLGPIO
bool "SPEAr SoC PLGPIO Controller"
depends on GPIOLIB && PINCTRL_SPEAR
+ select GPIOLIB_IRQCHIP
help
Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
SoCs.
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index ff2940e9f2a7..bddb79105d67 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -11,12 +11,11 @@
#include <linux/clk.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
@@ -54,7 +53,6 @@ struct plgpio_regs {
*
* 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.
@@ -68,8 +66,6 @@ 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 */
@@ -280,21 +276,12 @@ disable_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;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+ int offset = d->hwirq;
unsigned long flags;
/* get correct offset for "offset" pin */
@@ -311,8 +298,9 @@ static void plgpio_irq_disable(struct irq_data *d)
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;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+ int offset = d->hwirq;
unsigned long flags;
/* get correct offset for "offset" pin */
@@ -329,8 +317,9 @@ static void plgpio_irq_enable(struct irq_data *d)
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;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
+ int offset = d->hwirq;
void __iomem *reg_off;
unsigned int supported_type = 0, val;
@@ -369,7 +358,8 @@ static struct irq_chip plgpio_irqchip = {
static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
- struct plgpio *plgpio = irq_get_handler_data(irq);
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
int regs_count, count, pin, offset, i = 0;
unsigned long pending;
@@ -410,7 +400,8 @@ static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
/* get correct irq line number */
pin = i * MAX_GPIO_PER_REG + pin;
- generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+ generic_handle_irq(
+ irq_find_mapping(gc->irqdomain, pin));
}
}
chained_irq_exit(irqchip, desc);
@@ -523,10 +514,9 @@ end:
}
static int plgpio_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
struct plgpio *plgpio;
struct resource *res;
- int ret, irq, i;
+ int ret, irq;
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
if (!plgpio) {
@@ -563,7 +553,6 @@ static int plgpio_probe(struct platform_device *pdev)
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;
@@ -571,10 +560,10 @@ static int plgpio_probe(struct platform_device *pdev)
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;
+ plgpio->chip.of_node = pdev->dev.of_node;
if (!IS_ERR(plgpio->clk)) {
ret = clk_prepare(plgpio->clk);
@@ -592,43 +581,32 @@ static int plgpio_probe(struct platform_device *pdev)
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");
+ dev_info(&pdev->dev, "PLGPIO registered without IRQs\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;
+ ret = gpiochip_irqchip_add(&plgpio->chip,
+ &plgpio_irqchip,
+ 0,
+ handle_simple_irq,
+ IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add irqchip to gpiochip\n");
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);
- }
+ gpiochip_set_chained_irqchip(&plgpio->chip,
+ &plgpio_irqchip,
+ irq,
+ plgpio_irq_handler);
- 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");
+ gpiochip_remove(&plgpio->chip);
unprepare_clk:
if (!IS_ERR(plgpio->clk))
clk_unprepare(plgpio->clk);
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 58bf6867aa17..f72cc4e192bd 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -274,12 +274,6 @@ static int spear_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
return spear_pinctrl_endisable(pctldev, function, group, true);
}
-static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
- unsigned function, unsigned group)
-{
- spear_pinctrl_endisable(pctldev, function, group, false);
-}
-
/* gpio with pinmux */
static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
unsigned pin)
@@ -345,7 +339,6 @@ static const struct pinmux_ops spear_pinmux_ops = {
.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,
};
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 73e0a305ea13..a5e10f777ed2 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -1,36 +1,42 @@
if ARCH_SUNXI
-config PINCTRL_SUNXI
- bool
-
config PINCTRL_SUNXI_COMMON
bool
select PINMUX
select GENERIC_PINCONF
config PINCTRL_SUN4I_A10
- def_bool PINCTRL_SUNXI || MACH_SUN4I
+ def_bool MACH_SUN4I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN5I_A10S
- def_bool PINCTRL_SUNXI || MACH_SUN5I
+ def_bool MACH_SUN5I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN5I_A13
- def_bool PINCTRL_SUNXI || MACH_SUN5I
+ def_bool MACH_SUN5I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN6I_A31
- def_bool PINCTRL_SUNXI || MACH_SUN6I
+ def_bool MACH_SUN6I
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN6I_A31_R
- def_bool PINCTRL_SUNXI || MACH_SUN6I
+ def_bool MACH_SUN6I
depends on RESET_CONTROLLER
select PINCTRL_SUNXI_COMMON
config PINCTRL_SUN7I_A20
- def_bool PINCTRL_SUNXI || MACH_SUN7I
+ def_bool MACH_SUN7I
+ select PINCTRL_SUNXI_COMMON
+
+config PINCTRL_SUN8I_A23
+ def_bool MACH_SUN8I
+ select PINCTRL_SUNXI_COMMON
+
+config PINCTRL_SUN8I_A23_R
+ def_bool MACH_SUN8I
+ depends on RESET_CONTROLLER
select PINCTRL_SUNXI_COMMON
endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 0f4461cbe11d..e797efb02901 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -8,3 +8,5 @@ obj-$(CONFIG_PINCTRL_SUN5I_A13) += pinctrl-sun5i-a13.o
obj-$(CONFIG_PINCTRL_SUN6I_A31) += pinctrl-sun6i-a31.o
obj-$(CONFIG_PINCTRL_SUN6I_A31_R) += pinctrl-sun6i-a31-r.o
obj-$(CONFIG_PINCTRL_SUN7I_A20) += pinctrl-sun7i-a20.o
+obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o
+obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
index fa1ff7c7e357..86b608bedca6 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c
@@ -1010,6 +1010,7 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = {
static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
.pins = sun4i_a10_pins,
.npins = ARRAY_SIZE(sun4i_a10_pins),
+ .irq_banks = 1,
};
static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
index 164d743f526c..2fa7430cabaf 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
@@ -661,6 +661,7 @@ static const struct sunxi_desc_pin sun5i_a10s_pins[] = {
static const struct sunxi_pinctrl_desc sun5i_a10s_pinctrl_data = {
.pins = sun5i_a10s_pins,
.npins = ARRAY_SIZE(sun5i_a10s_pins),
+ .irq_banks = 1,
};
static int sun5i_a10s_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c b/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
index 1188a2b7b988..e47c33dbae3a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c
@@ -330,15 +330,12 @@ static const struct sunxi_desc_pin sun5i_a13_pins[] = {
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION_IRQ(0x6, 0)), /* EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION_IRQ(0x6, 1)), /* EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION_IRQ(0x6, 2)), /* EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -382,6 +379,7 @@ static const struct sunxi_desc_pin sun5i_a13_pins[] = {
static const struct sunxi_pinctrl_desc sun5i_a13_pinctrl_data = {
.pins = sun5i_a13_pins,
.npins = ARRAY_SIZE(sun5i_a13_pins),
+ .irq_banks = 1,
};
static int sun5i_a13_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
index 8fcba48e0a42..9a2517b65113 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c
@@ -93,6 +93,7 @@ static const struct sunxi_pinctrl_desc sun6i_a31_r_pinctrl_data = {
.pins = sun6i_a31_r_pins,
.npins = ARRAY_SIZE(sun6i_a31_r_pins),
.pin_base = PL_BASE,
+ .irq_banks = 2,
};
static int sun6i_a31_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
index 8dea5856458b..a2b4b85c5ad5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c
@@ -24,208 +24,244 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD0 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D0 */
- SUNXI_FUNCTION(0x4, "uart1")), /* DTR */
+ SUNXI_FUNCTION(0x4, "uart1"), /* DTR */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD1 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D1 */
- SUNXI_FUNCTION(0x4, "uart1")), /* DSR */
+ SUNXI_FUNCTION(0x4, "uart1"), /* DSR */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD2 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D2 */
- SUNXI_FUNCTION(0x4, "uart1")), /* DCD */
+ SUNXI_FUNCTION(0x4, "uart1"), /* DCD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD3 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D3 */
- SUNXI_FUNCTION(0x4, "uart1")), /* RING */
+ SUNXI_FUNCTION(0x4, "uart1"), /* RING */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD4 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D4 */
- SUNXI_FUNCTION(0x4, "uart1")), /* TX */
+ SUNXI_FUNCTION(0x4, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD5 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D5 */
- SUNXI_FUNCTION(0x4, "uart1")), /* RX */
+ SUNXI_FUNCTION(0x4, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD6 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D6 */
- SUNXI_FUNCTION(0x4, "uart1")), /* RTS */
+ SUNXI_FUNCTION(0x4, "uart1"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXD7 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D7 */
- SUNXI_FUNCTION(0x4, "uart1")), /* CTS */
+ SUNXI_FUNCTION(0x4, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXCLK */
- SUNXI_FUNCTION(0x3, "lcd1")), /* D8 */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* D8 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXEN */
SUNXI_FUNCTION(0x3, "lcd1"), /* D9 */
SUNXI_FUNCTION(0x4, "mmc3"), /* CMD */
- SUNXI_FUNCTION(0x5, "mmc2")), /* CMD */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* GTXCLK */
SUNXI_FUNCTION(0x3, "lcd1"), /* D10 */
SUNXI_FUNCTION(0x4, "mmc3"), /* CLK */
- SUNXI_FUNCTION(0x5, "mmc2")), /* CLK */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD0 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D11 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D0 */
- SUNXI_FUNCTION(0x5, "mmc2")), /* D0 */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD1 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D12 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D1 */
- SUNXI_FUNCTION(0x5, "mmc2")), /* D1 */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD2 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D13 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D2 */
- SUNXI_FUNCTION(0x5, "mmc2")), /* D2 */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD3 */
SUNXI_FUNCTION(0x3, "lcd1"), /* D14 */
SUNXI_FUNCTION(0x4, "mmc3"), /* D3 */
- SUNXI_FUNCTION(0x5, "mmc2")), /* D3 */
+ SUNXI_FUNCTION(0x5, "mmc2"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD4 */
- SUNXI_FUNCTION(0x3, "lcd1")), /* D15 */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* D15 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD5 */
- SUNXI_FUNCTION(0x3, "lcd1")), /* D16 */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* D16 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD6 */
- SUNXI_FUNCTION(0x3, "lcd1")), /* D17 */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* D17 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXD7 */
- SUNXI_FUNCTION(0x3, "lcd1")), /* D18 */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* D18 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXDV */
SUNXI_FUNCTION(0x3, "lcd1"), /* D19 */
- SUNXI_FUNCTION(0x4, "pwm3")), /* Positive */
+ SUNXI_FUNCTION(0x4, "pwm3"), /* Positive */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXCLK */
SUNXI_FUNCTION(0x3, "lcd1"), /* D20 */
- SUNXI_FUNCTION(0x4, "pwm3")), /* Negative */
+ SUNXI_FUNCTION(0x4, "pwm3"), /* Negative */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* TXERR */
SUNXI_FUNCTION(0x3, "lcd1"), /* D21 */
- SUNXI_FUNCTION(0x4, "spi3")), /* CS0 */
+ SUNXI_FUNCTION(0x4, "spi3"), /* CS0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 22),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* RXERR */
SUNXI_FUNCTION(0x3, "lcd1"), /* D22 */
- SUNXI_FUNCTION(0x4, "spi3")), /* CLK */
+ SUNXI_FUNCTION(0x4, "spi3"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 22)), /* PA_EINT22 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 23),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* COL */
SUNXI_FUNCTION(0x3, "lcd1"), /* D23 */
- SUNXI_FUNCTION(0x4, "spi3")), /* MOSI */
+ SUNXI_FUNCTION(0x4, "spi3"), /* MOSI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 23)), /* PA_EINT23 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 24),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* CRS */
SUNXI_FUNCTION(0x3, "lcd1"), /* CLK */
- SUNXI_FUNCTION(0x4, "spi3")), /* MISO */
+ SUNXI_FUNCTION(0x4, "spi3"), /* MISO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 24)), /* PA_EINT24 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 25),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* CLKIN */
SUNXI_FUNCTION(0x3, "lcd1"), /* DE */
- SUNXI_FUNCTION(0x4, "spi3")), /* CS1 */
+ SUNXI_FUNCTION(0x4, "spi3"), /* CS1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 25)), /* PA_EINT25 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 26),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* MDC */
- SUNXI_FUNCTION(0x3, "lcd1")), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* HSYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 26)), /* PA_EINT26 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 27),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "gmac"), /* MDIO */
- SUNXI_FUNCTION(0x3, "lcd1")), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "lcd1"), /* VSYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 27)), /* PA_EINT27 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* MCLK */
SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
- SUNXI_FUNCTION(0x4, "csi")), /* MCLK1 */
+ SUNXI_FUNCTION(0x4, "csi"), /* MCLK1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PB_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "i2s0")), /* BCLK */
+ SUNXI_FUNCTION(0x2, "i2s0"), /* BCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PB_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "i2s0")), /* LRCK */
+ SUNXI_FUNCTION(0x2, "i2s0"), /* LRCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PB_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "i2s0")), /* DO0 */
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DO0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PB_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO1 */
- SUNXI_FUNCTION(0x3, "uart3")), /* RTS */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PB_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO2 */
SUNXI_FUNCTION(0x3, "uart3"), /* TX */
- SUNXI_FUNCTION(0x4, "i2c3")), /* SCK */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PB_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2s0"), /* DO3 */
SUNXI_FUNCTION(0x3, "uart3"), /* RX */
- SUNXI_FUNCTION(0x4, "i2c3")), /* SDA */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PB_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x3, "i2s0")), /* DI */
+ SUNXI_FUNCTION(0x3, "i2s0"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PB_EINT7 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -510,86 +546,103 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
- SUNXI_FUNCTION(0x3, "ts")), /* CLK */
+ SUNXI_FUNCTION(0x3, "ts"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)), /* PE_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
- SUNXI_FUNCTION(0x3, "ts")), /* ERR */
+ SUNXI_FUNCTION(0x3, "ts"), /* ERR */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)), /* PE_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
- SUNXI_FUNCTION(0x3, "ts")), /* SYNC */
+ SUNXI_FUNCTION(0x3, "ts"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)), /* PE_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
- SUNXI_FUNCTION(0x3, "ts")), /* DVLD */
+ SUNXI_FUNCTION(0x3, "ts"), /* DVLD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)), /* PE_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D0 */
- SUNXI_FUNCTION(0x3, "uart5")), /* TX */
+ SUNXI_FUNCTION(0x3, "uart5"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)), /* PE_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D1 */
- SUNXI_FUNCTION(0x3, "uart5")), /* RX */
+ SUNXI_FUNCTION(0x3, "uart5"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)), /* PE_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D2 */
- SUNXI_FUNCTION(0x3, "uart5")), /* RTS */
+ SUNXI_FUNCTION(0x3, "uart5"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)), /* PE_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D3 */
- SUNXI_FUNCTION(0x3, "uart5")), /* CTS */
+ SUNXI_FUNCTION(0x3, "uart5"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)), /* PE_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D4 */
- SUNXI_FUNCTION(0x3, "ts")), /* D0 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)), /* PE_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D5 */
- SUNXI_FUNCTION(0x3, "ts")), /* D1 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)), /* PE_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D6 */
- SUNXI_FUNCTION(0x3, "ts")), /* D2 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)), /* PE_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D7 */
- SUNXI_FUNCTION(0x3, "ts")), /* D3 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)), /* PE_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D8 */
- SUNXI_FUNCTION(0x3, "ts")), /* D4 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D4 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 12)), /* PE_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D9 */
- SUNXI_FUNCTION(0x3, "ts")), /* D5 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D5 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 13)), /* PE_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D10 */
- SUNXI_FUNCTION(0x3, "ts")), /* D6 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D6 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 14)), /* PE_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "csi"), /* D11 */
- SUNXI_FUNCTION(0x3, "ts")), /* D7 */
+ SUNXI_FUNCTION(0x3, "ts"), /* D7 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 15)), /* PE_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "csi")), /* MIPI CSI MCLK */
+ SUNXI_FUNCTION(0x2, "csi"), /* MIPI CSI MCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 16)), /* PE_EINT16 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -625,86 +678,105 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* CLK */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 0)), /* PG_EINT0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* CMD */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 1)), /* PG_EINT1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* D0 */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 2)), /* PG_EINT2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* D1 */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 3)), /* PG_EINT3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* D2 */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 4)), /* PG_EINT4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "mmc1")), /* D3 */
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 5)), /* PG_EINT5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart2")), /* TX */
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 6)), /* PG_EINT6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart2")), /* RX */
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 7)), /* PG_EINT7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart2")), /* RTS */
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 8)), /* PG_EINT8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart2")), /* CTS */
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 9)), /* PG_EINT9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c3"), /* SCK */
- SUNXI_FUNCTION(0x3, "usb")), /* DP3 */
+ SUNXI_FUNCTION(0x3, "usb"), /* DP3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 10)), /* PG_EINT10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "i2c3"), /* SDA */
- SUNXI_FUNCTION(0x3, "usb")), /* DM3 */
+ SUNXI_FUNCTION(0x3, "usb"), /* DM3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 11)), /* PG_EINT11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */
- SUNXI_FUNCTION(0x3, "i2s1")), /* MCLK */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* MCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 12)), /* PG_EINT12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CS0 */
- SUNXI_FUNCTION(0x3, "i2s1")), /* BCLK */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 13)), /* PG_EINT13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
- SUNXI_FUNCTION(0x3, "i2s1")), /* LRCK */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* LRCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 14)), /* PG_EINT14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
- SUNXI_FUNCTION(0x3, "i2s1")), /* DIN */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 15)), /* PG_EINT15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
- SUNXI_FUNCTION(0x3, "i2s1")), /* DOUT */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 16)), /* PG_EINT16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart4")), /* TX */
+ SUNXI_FUNCTION(0x2, "uart4"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 17)), /* PG_EINT17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart4")), /* RX */
+ SUNXI_FUNCTION(0x2, "uart4"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 3, 18)), /* PG_EINT18 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -836,6 +908,7 @@ static const struct sunxi_desc_pin sun6i_a31_pins[] = {
static const struct sunxi_pinctrl_desc sun6i_a31_pinctrl_data = {
.pins = sun6i_a31_pins,
.npins = ARRAY_SIZE(sun6i_a31_pins),
+ .irq_banks = 4,
};
static int sun6i_a31_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
index d8577ce5f1a4..dac99e02bfdb 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
@@ -1036,6 +1036,7 @@ static const struct sunxi_desc_pin sun7i_a20_pins[] = {
static const struct sunxi_pinctrl_desc sun7i_a20_pinctrl_data = {
.pins = sun7i_a20_pins,
.npins = ARRAY_SIZE(sun7i_a20_pins),
+ .irq_banks = 1,
};
static int sun7i_a20_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
new file mode 100644
index 000000000000..90f3b3a7c51e
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c
@@ -0,0 +1,142 @@
+/*
+ * Allwinner A23 SoCs special pins pinctrl driver.
+ *
+ * Copyright (C) 2014 Chen-Yu Tsai
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Copyright (C) 2014 Boris Brezillon
+ * Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_a23_r_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
+ SUNXI_FUNCTION(0x3, "s_twi"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 0)), /* PL_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
+ SUNXI_FUNCTION(0x3, "s_twi"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 1)), /* PL_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_uart"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 2)), /* PL_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_uart"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 3)), /* PL_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 4)), /* PL_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 5)), /* PL_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 6)), /* PL_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 7)), /* PL_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_twi"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 8)), /* PL_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_twi"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 9)), /* PL_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_pwm"),
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 10)), /* PL_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 11)), /* PL_EINT11 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_a23_r_pinctrl_data = {
+ .pins = sun8i_a23_r_pins,
+ .npins = ARRAY_SIZE(sun8i_a23_r_pins),
+ .pin_base = PL_BASE,
+ .irq_banks = 1,
+};
+
+static int sun8i_a23_r_pinctrl_probe(struct platform_device *pdev)
+{
+ struct reset_control *rstc;
+ int ret;
+
+ rstc = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(rstc)) {
+ dev_err(&pdev->dev, "Reset controller missing\n");
+ return PTR_ERR(rstc);
+ }
+
+ ret = reset_control_deassert(rstc);
+ if (ret)
+ return ret;
+
+ ret = sunxi_pinctrl_init(pdev,
+ &sun8i_a23_r_pinctrl_data);
+
+ if (ret)
+ reset_control_assert(rstc);
+
+ return ret;
+}
+
+static struct of_device_id sun8i_a23_r_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-a23-r-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match);
+
+static struct platform_driver sun8i_a23_r_pinctrl_driver = {
+ .probe = sun8i_a23_r_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-a23-r-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = sun8i_a23_r_pinctrl_match,
+ },
+};
+module_platform_driver(sun8i_a23_r_pinctrl_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner A23 R_PIO pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
new file mode 100644
index 000000000000..ac71e8c5901b
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c
@@ -0,0 +1,593 @@
+/*
+ * Allwinner A23 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_a23_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 0)), /* PA_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CKO */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 1)), /* PA_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DOO */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 2)), /* PA_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DIO */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 3)), /* PA_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart4"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 4)), /* PA_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart4"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 5)), /* PA_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart4"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 6)), /* PA_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart4"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 0, 7)), /* PA_EINT7 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PB_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)), /* PB_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)), /* PB_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)), /* PB_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)), /* PB_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)), /* PB_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)), /* PB_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)), /* PB_EINT7 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQS */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE3 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */
+ SUNXI_FUNCTION(0x3, "mmc1")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D8 */
+ SUNXI_FUNCTION(0x3, "uart3")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D9 */
+ SUNXI_FUNCTION(0x3, "uart3")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D10 */
+ SUNXI_FUNCTION(0x3, "uart1")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D11 */
+ SUNXI_FUNCTION(0x3, "uart1")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D12 */
+ SUNXI_FUNCTION(0x3, "uart1")), /* RTS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D13 */
+ SUNXI_FUNCTION(0x3, "uart1")), /* CTS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D14 */
+ SUNXI_FUNCTION(0x3, "i2s1")), /* SYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D15 */
+ SUNXI_FUNCTION(0x3, "i2s1")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D16 */
+ SUNXI_FUNCTION(0x3, "i2s1")), /* DOUT */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D17 */
+ SUNXI_FUNCTION(0x3, "i2s1")), /* DIN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D18 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D19 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D20 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D21 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D22 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 23),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D23 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 24),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VPC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 25),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* DE */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 26),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 27),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN3 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* PCLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* MCLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* HSYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* VSYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK1 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 2, 13)), /* PG_EINT13 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm0")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm1")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* CS */
+ SUNXI_FUNCTION(0x3, "uart3")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart3")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "uart3")), /* RTS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "uart3")), /* CTS */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_a23_pinctrl_data = {
+ .pins = sun8i_a23_pins,
+ .npins = ARRAY_SIZE(sun8i_a23_pins),
+ .irq_banks = 3,
+};
+
+static int sun8i_a23_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun8i_a23_pinctrl_data);
+}
+
+static struct of_device_id sun8i_a23_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-a23-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match);
+
+static struct platform_driver sun8i_a23_pinctrl_driver = {
+ .probe = sun8i_a23_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-a23-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = sun8i_a23_pinctrl_match,
+ },
+};
+module_platform_driver(sun8i_a23_pinctrl_driver);
+
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner A23 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 5f38c7f67834..3df66e366c87 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -31,6 +31,9 @@
#include "../core.h"
#include "pinctrl-sunxi.h"
+static struct irq_chip sunxi_pinctrl_edge_irq_chip;
+static struct irq_chip sunxi_pinctrl_level_irq_chip;
+
static struct sunxi_pinctrl_group *
sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
{
@@ -508,7 +511,7 @@ static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
base = PINS_PER_BANK * gpiospec->args[0];
pin = base + gpiospec->args[1];
- if (pin > (gc->base + gc->ngpio))
+ if (pin > gc->ngpio)
return -EINVAL;
if (flags)
@@ -521,25 +524,61 @@ static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
struct sunxi_desc_function *desc;
+ unsigned pinnum = pctl->desc->pin_base + offset;
+ unsigned irqnum;
if (offset >= chip->ngpio)
return -ENXIO;
- desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq");
+ desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pinnum, "irq");
if (!desc)
return -EINVAL;
+ irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum;
+
dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
- chip->label, offset + chip->base, desc->irqnum);
+ chip->label, offset + chip->base, irqnum);
- return irq_find_mapping(pctl->domain, desc->irqnum);
+ return irq_find_mapping(pctl->domain, irqnum);
}
+static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
+{
+ struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+ struct sunxi_desc_function *func;
+ int ret;
+
+ func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
+ pctl->irq_array[d->hwirq], "irq");
+ if (!func)
+ return -EINVAL;
+
+ ret = gpio_lock_as_irq(pctl->chip,
+ pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
+ if (ret) {
+ dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
+ irqd_to_hwirq(d));
+ return ret;
+ }
+
+ /* Change muxing to INT mode */
+ sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
-static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
- unsigned int type)
+ return 0;
+}
+
+static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
+{
+ struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+
+ gpio_unlock_as_irq(pctl->chip,
+ pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
+}
+
+static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
+ struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
u32 reg = sunxi_irq_cfg_reg(d->hwirq);
u8 index = sunxi_irq_cfg_offset(d->hwirq);
unsigned long flags;
@@ -566,6 +605,14 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
return -EINVAL;
}
+ if (type & IRQ_TYPE_LEVEL_MASK) {
+ d->chip = &sunxi_pinctrl_level_irq_chip;
+ desc->handle_irq = handle_fasteoi_irq;
+ } else {
+ d->chip = &sunxi_pinctrl_edge_irq_chip;
+ desc->handle_irq = handle_edge_irq;
+ }
+
spin_lock_irqsave(&pctl->lock, flags);
regval = readl(pctl->membase + reg);
@@ -577,26 +624,14 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
return 0;
}
-static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d)
+static void sunxi_pinctrl_irq_ack(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- u32 ctrl_reg = sunxi_irq_ctrl_reg(d->hwirq);
- u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
u32 status_reg = sunxi_irq_status_reg(d->hwirq);
u8 status_idx = sunxi_irq_status_offset(d->hwirq);
- unsigned long flags;
- u32 val;
-
- spin_lock_irqsave(&pctl->lock, flags);
-
- /* Mask the IRQ */
- val = readl(pctl->membase + ctrl_reg);
- writel(val & ~(1 << ctrl_idx), pctl->membase + ctrl_reg);
/* Clear the IRQ */
writel(1 << status_idx, pctl->membase + status_reg);
-
- spin_unlock_irqrestore(&pctl->lock, flags);
}
static void sunxi_pinctrl_irq_mask(struct irq_data *d)
@@ -619,19 +654,11 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)
static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
- struct sunxi_desc_function *func;
u32 reg = sunxi_irq_ctrl_reg(d->hwirq);
u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
unsigned long flags;
u32 val;
- func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
- pctl->irq_array[d->hwirq],
- "irq");
-
- /* Change muxing to INT mode */
- sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
-
spin_lock_irqsave(&pctl->lock, flags);
/* Unmask the IRQ */
@@ -641,28 +668,60 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
spin_unlock_irqrestore(&pctl->lock, flags);
}
-static struct irq_chip sunxi_pinctrl_irq_chip = {
+static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
+{
+ sunxi_pinctrl_irq_ack(d);
+ sunxi_pinctrl_irq_unmask(d);
+}
+
+static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
+ .irq_ack = sunxi_pinctrl_irq_ack,
+ .irq_mask = sunxi_pinctrl_irq_mask,
+ .irq_unmask = sunxi_pinctrl_irq_unmask,
+ .irq_request_resources = sunxi_pinctrl_irq_request_resources,
+ .irq_release_resources = sunxi_pinctrl_irq_release_resources,
+ .irq_set_type = sunxi_pinctrl_irq_set_type,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static struct irq_chip sunxi_pinctrl_level_irq_chip = {
+ .irq_eoi = sunxi_pinctrl_irq_ack,
.irq_mask = sunxi_pinctrl_irq_mask,
- .irq_mask_ack = sunxi_pinctrl_irq_mask_ack,
.irq_unmask = sunxi_pinctrl_irq_unmask,
+ /* Define irq_enable / disable to avoid spurious irqs for drivers
+ * using these to suppress irqs while they clear the irq source */
+ .irq_enable = sunxi_pinctrl_irq_ack_unmask,
+ .irq_disable = sunxi_pinctrl_irq_mask,
+ .irq_request_resources = sunxi_pinctrl_irq_request_resources,
+ .irq_release_resources = sunxi_pinctrl_irq_release_resources,
.irq_set_type = sunxi_pinctrl_irq_set_type,
+ .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED |
+ IRQCHIP_EOI_IF_HANDLED,
};
static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
- const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
+ unsigned long bank, reg, val;
+
+ for (bank = 0; bank < pctl->desc->irq_banks; bank++)
+ if (irq == pctl->irq[bank])
+ break;
+
+ if (bank == pctl->desc->irq_banks)
+ return;
- /* Clear all interrupts */
- writel(reg, pctl->membase + IRQ_STATUS_REG);
+ reg = sunxi_irq_status_reg_from_bank(bank);
+ val = readl(pctl->membase + reg);
- if (reg) {
+ if (val) {
int irqoffset;
chained_irq_enter(chip, desc);
- for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
- int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
+ for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
+ int pin_irq = irq_find_mapping(pctl->domain,
+ bank * IRQ_PER_BANK + irqoffset);
generic_handle_irq(pin_irq);
}
chained_irq_exit(chip, desc);
@@ -730,8 +789,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
while (func->name) {
/* Create interrupt mapping while we're at it */
- if (!strcmp(func->name, "irq"))
- pctl->irq_array[func->irqnum] = pin->pin.number;
+ if (!strcmp(func->name, "irq")) {
+ int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
+ pctl->irq_array[irqnum] = pin->pin.number;
+ }
+
sunxi_pinctrl_add_function(pctl, func->name);
func++;
}
@@ -801,6 +863,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
pctl->dev = &pdev->dev;
pctl->desc = desc;
+ pctl->irq_array = devm_kcalloc(&pdev->dev,
+ IRQ_PER_BANK * pctl->desc->irq_banks,
+ sizeof(*pctl->irq_array),
+ GFP_KERNEL);
+ if (!pctl->irq_array)
+ return -ENOMEM;
+
ret = sunxi_pinctrl_build_state(pdev);
if (ret) {
dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
@@ -869,7 +938,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
- pin->pin.number,
+ pin->pin.number - pctl->desc->pin_base,
pin->pin.number, 1);
if (ret)
goto gpiochip_error;
@@ -885,30 +954,51 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
if (ret)
goto gpiochip_error;
- pctl->irq = irq_of_parse_and_map(node, 0);
+ pctl->irq = devm_kcalloc(&pdev->dev,
+ pctl->desc->irq_banks,
+ sizeof(*pctl->irq),
+ GFP_KERNEL);
if (!pctl->irq) {
- ret = -EINVAL;
+ ret = -ENOMEM;
goto clk_error;
}
- pctl->domain = irq_domain_add_linear(node, SUNXI_IRQ_NUMBER,
- &irq_domain_simple_ops, NULL);
+ for (i = 0; i < pctl->desc->irq_banks; i++) {
+ pctl->irq[i] = platform_get_irq(pdev, i);
+ if (pctl->irq[i] < 0) {
+ ret = pctl->irq[i];
+ goto clk_error;
+ }
+ }
+
+ pctl->domain = irq_domain_add_linear(node,
+ pctl->desc->irq_banks * IRQ_PER_BANK,
+ &irq_domain_simple_ops,
+ NULL);
if (!pctl->domain) {
dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
ret = -ENOMEM;
goto clk_error;
}
- for (i = 0; i < SUNXI_IRQ_NUMBER; i++) {
+ for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) {
int irqno = irq_create_mapping(pctl->domain, i);
- irq_set_chip_and_handler(irqno, &sunxi_pinctrl_irq_chip,
- handle_simple_irq);
+ irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
+ handle_edge_irq);
irq_set_chip_data(irqno, pctl);
};
- irq_set_chained_handler(pctl->irq, sunxi_pinctrl_irq_handler);
- irq_set_handler_data(pctl->irq, pctl);
+ for (i = 0; i < pctl->desc->irq_banks; i++) {
+ /* Mask and clear all IRQs before registering a handler */
+ writel(0, pctl->membase + sunxi_irq_ctrl_reg_from_bank(i));
+ writel(0xffffffff,
+ pctl->membase + sunxi_irq_status_reg_from_bank(i));
+
+ irq_set_chained_handler(pctl->irq[i],
+ sunxi_pinctrl_irq_handler);
+ irq_set_handler_data(pctl->irq[i], pctl);
+ }
dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
@@ -917,8 +1007,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
clk_error:
clk_disable_unprepare(clk);
gpiochip_error:
- if (gpiochip_remove(pctl->chip))
- dev_err(&pdev->dev, "failed to remove gpio chip\n");
+ gpiochip_remove(pctl->chip);
pinctrl_error:
pinctrl_unregister(pctl->pctl_dev);
return ret;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 8169ba598876..4245b96c7996 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -53,7 +53,7 @@
#define PULL_PINS_BITS 2
#define PULL_PINS_MASK 0x03
-#define SUNXI_IRQ_NUMBER 32
+#define IRQ_PER_BANK 32
#define IRQ_CFG_REG 0x200
#define IRQ_CFG_IRQ_PER_REG 8
@@ -68,6 +68,8 @@
#define IRQ_STATUS_IRQ_BITS 1
#define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
+#define IRQ_MEM_SIZE 0x20
+
#define IRQ_EDGE_RISING 0x00
#define IRQ_EDGE_FALLING 0x01
#define IRQ_LEVEL_HIGH 0x02
@@ -77,6 +79,7 @@
struct sunxi_desc_function {
const char *name;
u8 muxval;
+ u8 irqbank;
u8 irqnum;
};
@@ -89,6 +92,7 @@ struct sunxi_pinctrl_desc {
const struct sunxi_desc_pin *pins;
int npins;
unsigned pin_base;
+ unsigned irq_banks;
};
struct sunxi_pinctrl_function {
@@ -113,8 +117,8 @@ struct sunxi_pinctrl {
unsigned nfunctions;
struct sunxi_pinctrl_group *groups;
unsigned ngroups;
- int irq;
- int irq_array[SUNXI_IRQ_NUMBER];
+ int *irq;
+ unsigned *irq_array;
spinlock_t lock;
struct pinctrl_dev *pctl_dev;
};
@@ -139,6 +143,14 @@ struct sunxi_pinctrl {
.irqnum = _irq, \
}
+#define SUNXI_FUNCTION_IRQ_BANK(_val, _bank, _irq) \
+ { \
+ .name = "irq", \
+ .muxval = _val, \
+ .irqbank = _bank, \
+ .irqnum = _irq, \
+ }
+
/*
* The sunXi PIO registers are organized as is:
* 0x00 - 0x0c Muxing values.
@@ -218,8 +230,10 @@ static inline u32 sunxi_pull_offset(u16 pin)
static inline u32 sunxi_irq_cfg_reg(u16 irq)
{
- u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
- return reg + IRQ_CFG_REG;
+ u8 bank = irq / IRQ_PER_BANK;
+ u8 reg = (irq % IRQ_PER_BANK) / IRQ_CFG_IRQ_PER_REG * 0x04;
+
+ return IRQ_CFG_REG + bank * IRQ_MEM_SIZE + reg;
}
static inline u32 sunxi_irq_cfg_offset(u16 irq)
@@ -228,10 +242,16 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
return irq_num * IRQ_CFG_IRQ_BITS;
}
+static inline u32 sunxi_irq_ctrl_reg_from_bank(u8 bank)
+{
+ return IRQ_CTRL_REG + bank * IRQ_MEM_SIZE;
+}
+
static inline u32 sunxi_irq_ctrl_reg(u16 irq)
{
- u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
- return reg + IRQ_CTRL_REG;
+ u8 bank = irq / IRQ_PER_BANK;
+
+ return sunxi_irq_ctrl_reg_from_bank(bank);
}
static inline u32 sunxi_irq_ctrl_offset(u16 irq)
@@ -240,10 +260,16 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
return irq_num * IRQ_CTRL_IRQ_BITS;
}
+static inline u32 sunxi_irq_status_reg_from_bank(u8 bank)
+{
+ return IRQ_STATUS_REG + bank * IRQ_MEM_SIZE;
+}
+
static inline u32 sunxi_irq_status_reg(u16 irq)
{
- u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
- return reg + IRQ_STATUS_REG;
+ u8 bank = irq / IRQ_PER_BANK;
+
+ return sunxi_irq_status_reg_from_bank(bank);
}
static inline u32 sunxi_irq_status_offset(u16 irq)
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index 2c61281bebd7..8cea355f9a81 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -141,17 +141,6 @@ static int wmt_pmx_enable(struct pinctrl_dev *pctldev,
return wmt_set_pinmux(data, func_selector, pinnum);
}
-static void wmt_pmx_disable(struct pinctrl_dev *pctldev,
- unsigned func_selector,
- unsigned group_selector)
-{
- struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
- u32 pinnum = data->pins[group_selector].number;
-
- /* disable by setting GPIO_IN */
- wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, pinnum);
-}
-
static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
@@ -180,7 +169,6 @@ static struct pinmux_ops wmt_pinmux_ops = {
.get_function_name = wmt_pmx_get_function_name,
.get_function_groups = wmt_pmx_get_function_groups,
.enable = wmt_pmx_enable,
- .disable = wmt_pmx_disable,
.gpio_disable_free = wmt_pmx_gpio_disable_free,
.gpio_set_direction = wmt_pmx_gpio_set_direction,
};
@@ -627,8 +615,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
return 0;
fail_range:
- if (gpiochip_remove(&data->gpio_chip))
- dev_err(&pdev->dev, "failed to remove gpio chip\n");
+ gpiochip_remove(&data->gpio_chip);
fail_gpio:
pinctrl_unregister(data->pctl_dev);
return err;
@@ -637,12 +624,8 @@ fail_gpio:
int wmt_pinctrl_remove(struct platform_device *pdev)
{
struct wmt_pinctrl_data *data = platform_get_drvdata(pdev);
- int err;
-
- err = gpiochip_remove(&data->gpio_chip);
- if (err)
- dev_err(&pdev->dev, "failed to remove gpio chip\n");
+ gpiochip_remove(&data->gpio_chip);
pinctrl_unregister(data->pctl_dev);
return 0;
diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index 7f1a2e2711bd..d866db80b4fd 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -37,6 +37,8 @@
#define ISL_ALS_I2C_ADDR 0x44
#define TAOS_ALS_I2C_ADDR 0x29
+#define MAX_I2C_DEVICE_DEFERRALS 5
+
static struct i2c_client *als;
static struct i2c_client *tp;
static struct i2c_client *ts;
@@ -45,6 +47,8 @@ static const char *i2c_adapter_names[] = {
"SMBus I801 adapter",
"i915 gmbus vga",
"i915 gmbus panel",
+ "i2c-designware-pci",
+ "i2c-designware-pci",
};
/* Keep this enum consistent with i2c_adapter_names */
@@ -52,11 +56,21 @@ enum i2c_adapter_type {
I2C_ADAPTER_SMBUS = 0,
I2C_ADAPTER_VGADDC,
I2C_ADAPTER_PANEL,
+ I2C_ADAPTER_DESIGNWARE_0,
+ I2C_ADAPTER_DESIGNWARE_1,
+};
+
+enum i2c_peripheral_state {
+ UNPROBED = 0,
+ PROBED,
+ TIMEDOUT,
};
struct i2c_peripheral {
int (*add)(enum i2c_adapter_type type);
enum i2c_adapter_type type;
+ enum i2c_peripheral_state state;
+ int tries;
};
#define MAX_I2C_PERIPHERALS 3
@@ -97,8 +111,6 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = {
.irqflags = IRQF_TRIGGER_FALLING,
.t19_num_keys = ARRAY_SIZE(mxt_t19_keys),
.t19_keymap = mxt_t19_keys,
- .config = NULL,
- .config_length = 0,
};
static struct i2c_board_info atmel_224s_tp_device = {
@@ -109,8 +121,6 @@ static struct i2c_board_info atmel_224s_tp_device = {
static struct mxt_platform_data atmel_1664s_platform_data = {
.irqflags = IRQF_TRIGGER_FALLING,
- .config = NULL,
- .config_length = 0,
};
static struct i2c_board_info atmel_1664s_device = {
@@ -162,8 +172,8 @@ static struct i2c_client *__add_probed_i2c_device(
/* add the i2c device */
client = i2c_new_probed_device(adapter, info, addrs, NULL);
if (!client)
- pr_err("%s failed to register device %d-%02x\n",
- __func__, bus, info->addr);
+ pr_notice("%s failed to register device %d-%02x\n",
+ __func__, bus, info->addr);
else
pr_debug("%s added i2c device %d-%02x\n",
__func__, bus, info->addr);
@@ -172,29 +182,43 @@ static struct i2c_client *__add_probed_i2c_device(
return client;
}
+struct i2c_lookup {
+ const char *name;
+ int instance;
+ int n;
+};
+
static int __find_i2c_adap(struct device *dev, void *data)
{
- const char *name = data;
+ struct i2c_lookup *lookup = data;
static const char *prefix = "i2c-";
struct i2c_adapter *adapter;
+
if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
return 0;
adapter = to_i2c_adapter(dev);
- return (strncmp(adapter->name, name, strlen(name)) == 0);
+ if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 &&
+ lookup->n++ == lookup->instance)
+ return 1;
+ return 0;
}
static int find_i2c_adapter_num(enum i2c_adapter_type type)
{
struct device *dev = NULL;
struct i2c_adapter *adapter;
- const char *name = i2c_adapter_names[type];
+ struct i2c_lookup lookup;
+
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.name = i2c_adapter_names[type];
+ lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0;
+
/* find the adapter by name */
- dev = bus_find_device(&i2c_bus_type, NULL, (void *)name,
- __find_i2c_adap);
+ dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap);
if (!dev) {
/* Adapters may appear later. Deferred probing will retry */
pr_notice("%s: i2c adapter %s not found on system.\n", __func__,
- name);
+ lookup.name);
return -ENODEV;
}
adapter = to_i2c_adapter(dev);
@@ -231,6 +255,7 @@ static struct i2c_client *add_i2c_device(const char *name,
struct i2c_board_info *info)
{
const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
+
return __add_probed_i2c_device(name,
find_i2c_adapter_num(type),
info,
@@ -328,9 +353,36 @@ static int chromeos_laptop_probe(struct platform_device *pdev)
if (i2c_dev->add == NULL)
break;
- /* Add the device. Set -EPROBE_DEFER on any failure */
- if (i2c_dev->add(i2c_dev->type))
+ if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED)
+ continue;
+
+ /*
+ * Check that the i2c adapter is present.
+ * -EPROBE_DEFER if missing as the adapter may appear much
+ * later.
+ */
+ if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) {
ret = -EPROBE_DEFER;
+ continue;
+ }
+
+ /* Add the device. */
+ if (i2c_dev->add(i2c_dev->type) == -EAGAIN) {
+ /*
+ * Set -EPROBE_DEFER a limited num of times
+ * if device is not successfully added.
+ */
+ if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) {
+ ret = -EPROBE_DEFER;
+ } else {
+ /* Ran out of tries. */
+ pr_notice("%s: Ran out of tries for device.\n",
+ __func__);
+ i2c_dev->state = TIMEDOUT;
+ }
+ } else {
+ i2c_dev->state = PROBED;
+ }
}
return ret;
@@ -363,6 +415,27 @@ static struct chromeos_laptop chromebook_pixel = {
},
};
+static struct chromeos_laptop hp_chromebook_14 = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+ },
+};
+
+static struct chromeos_laptop dell_chromebook_11 = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+ },
+};
+
+static struct chromeos_laptop toshiba_cb35 = {
+ .i2c_peripherals = {
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+ },
+};
+
static struct chromeos_laptop acer_c7_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
@@ -377,6 +450,17 @@ static struct chromeos_laptop acer_ac700 = {
},
};
+static struct chromeos_laptop acer_c720 = {
+ .i2c_peripherals = {
+ /* Touchscreen. */
+ { .add = setup_atmel_1664s_ts, I2C_ADAPTER_DESIGNWARE_1 },
+ /* Touchpad. */
+ { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 },
+ /* Light Sensor. */
+ { .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 },
+ },
+};
+
static struct chromeos_laptop hp_pavilion_14_chromebook = {
.i2c_peripherals = {
/* Touchpad. */
@@ -420,6 +504,30 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
_CBDD(chromebook_pixel),
},
{
+ .ident = "Wolf",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"),
+ },
+ _CBDD(dell_chromebook_11),
+ },
+ {
+ .ident = "HP Chromebook 14",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Falco"),
+ },
+ _CBDD(hp_chromebook_14),
+ },
+ {
+ .ident = "Toshiba CB35",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Leon"),
+ },
+ _CBDD(toshiba_cb35),
+ },
+ {
.ident = "Acer C7 Chromebook",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
@@ -434,6 +542,13 @@ static struct dmi_system_id chromeos_laptop_dmi_table[] __initdata = {
_CBDD(acer_ac700),
},
{
+ .ident = "Acer C720",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
+ },
+ _CBDD(acer_c720),
+ },
+ {
.ident = "HP Pavilion 14 Chromebook",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
@@ -464,6 +579,7 @@ static struct platform_driver cros_platform_driver = {
static int __init chromeos_laptop_init(void)
{
int ret;
+
if (!dmi_check_system(chromeos_laptop_dmi_table)) {
pr_debug("%s unsupported system.\n", __func__);
return -ENODEV;
diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c
index e0e0e65cf442..34749200e4ab 100644
--- a/drivers/platform/chrome/chromeos_pstore.c
+++ b/drivers/platform/chrome/chromeos_pstore.c
@@ -16,23 +16,13 @@
static struct dmi_system_id chromeos_pstore_dmi_table[] __initdata = {
{
/*
- * Today all Chromebooks/boxes ship with GOOGLE as vendor and
+ * Today all Chromebooks/boxes ship with Google_* as version and
* coreboot as bios vendor. No other systems with this
* combination are known to date.
*/
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
- DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
- },
- },
- {
- /*
- * The first Samsung Chromebox and Chromebook Series 5 550 use
- * coreboot but with Samsung as the system vendor.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+ DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
},
},
{
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 18dcb58ba965..a0d1f576cf40 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -1478,7 +1478,7 @@ ips_link_to_i915_driver(void)
}
EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
-static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
+static const struct pci_device_id ips_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
{ 0, }
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 76ca094ed012..66a4d3284aab 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -640,7 +640,7 @@ static void ipc_remove(struct pci_dev *pdev)
intel_scu_devices_destroy();
}
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
+static const struct pci_device_id pci_ids[] = {
{
PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT),
(kernel_ulong_t)&intel_scu_ipc_lincroft_pdata,
diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
index 5413f62d2e61..28d12bda3ac1 100644
--- a/drivers/platform/x86/samsung-q10.c
+++ b/drivers/platform/x86/samsung-q10.c
@@ -46,13 +46,7 @@ static int samsungq10_bl_set_intensity(struct backlight_device *bd)
return 0;
}
-static int samsungq10_bl_get_intensity(struct backlight_device *bd)
-{
- return bd->props.brightness;
-}
-
static const struct backlight_ops samsungq10_bl_ops = {
- .get_brightness = samsungq10_bl_get_intensity,
.update_status = samsungq10_bl_set_intensity,
};
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index a5c6cb773e5f..d2b780aade89 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -67,8 +67,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
pnp_dbg(&dev->dev, "set resources\n");
- handle = ACPI_HANDLE(&dev->dev);
- if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+ acpi_dev = ACPI_COMPANION(&dev->dev);
+ if (!acpi_dev) {
dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
return -ENODEV;
}
@@ -76,6 +76,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
if (WARN_ON_ONCE(acpi_dev != dev->data))
dev->data = acpi_dev;
+ handle = acpi_dev->handle;
if (acpi_has_method(handle, METHOD_NAME__SRS)) {
struct acpi_buffer buffer;
@@ -93,8 +94,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
}
kfree(buffer.pointer);
}
- if (!ret && acpi_bus_power_manageable(handle))
- ret = acpi_bus_set_power(handle, ACPI_STATE_D0);
+ if (!ret && acpi_device_power_manageable(acpi_dev))
+ ret = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
return ret;
}
@@ -102,23 +103,22 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
static int pnpacpi_disable_resources(struct pnp_dev *dev)
{
struct acpi_device *acpi_dev;
- acpi_handle handle;
acpi_status status;
dev_dbg(&dev->dev, "disable resources\n");
- handle = ACPI_HANDLE(&dev->dev);
- if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+ acpi_dev = ACPI_COMPANION(&dev->dev);
+ if (!acpi_dev) {
dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
return 0;
}
/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
- if (acpi_bus_power_manageable(handle))
- acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
+ if (acpi_device_power_manageable(acpi_dev))
+ acpi_device_set_power(acpi_dev, ACPI_STATE_D3_COLD);
- /* continue even if acpi_bus_set_power() fails */
- status = acpi_evaluate_object(handle, "_DIS", NULL, NULL);
+ /* continue even if acpi_device_set_power() fails */
+ status = acpi_evaluate_object(acpi_dev->handle, "_DIS", NULL, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
return -ENODEV;
@@ -128,26 +128,22 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
#ifdef CONFIG_ACPI_SLEEP
static bool pnpacpi_can_wakeup(struct pnp_dev *dev)
{
- struct acpi_device *acpi_dev;
- acpi_handle handle;
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
- handle = ACPI_HANDLE(&dev->dev);
- if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+ if (!acpi_dev) {
dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
return false;
}
- return acpi_bus_can_wakeup(handle);
+ return acpi_bus_can_wakeup(acpi_dev->handle);
}
static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
{
- struct acpi_device *acpi_dev;
- acpi_handle handle;
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
int error = 0;
- handle = ACPI_HANDLE(&dev->dev);
- if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+ if (!acpi_dev) {
dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
return 0;
}
@@ -159,7 +155,7 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
return error;
}
- if (acpi_bus_power_manageable(handle)) {
+ if (acpi_device_power_manageable(acpi_dev)) {
int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
ACPI_STATE_D3_COLD);
if (power_state < 0)
@@ -167,12 +163,12 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
ACPI_STATE_D0 : ACPI_STATE_D3_COLD;
/*
- * acpi_bus_set_power() often fails (keyboard port can't be
+ * acpi_device_set_power() can fail (keyboard port can't be
* powered-down?), and in any case, our return value is ignored
* by pnp_bus_suspend(). Hence we don't revert the wakeup
* setting if the set_power fails.
*/
- error = acpi_bus_set_power(handle, power_state);
+ error = acpi_device_set_power(acpi_dev, power_state);
}
return error;
@@ -180,11 +176,10 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
static int pnpacpi_resume(struct pnp_dev *dev)
{
- struct acpi_device *acpi_dev;
- acpi_handle handle = ACPI_HANDLE(&dev->dev);
+ struct acpi_device *acpi_dev = ACPI_COMPANION(&dev->dev);
int error = 0;
- if (!handle || acpi_bus_get_device(handle, &acpi_dev)) {
+ if (!acpi_dev) {
dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__);
return -ENODEV;
}
@@ -192,8 +187,8 @@ static int pnpacpi_resume(struct pnp_dev *dev)
if (device_may_wakeup(&dev->dev))
acpi_pm_device_sleep_wake(&dev->dev, false);
- if (acpi_bus_power_manageable(handle))
- error = acpi_bus_set_power(handle, ACPI_STATE_D0);
+ if (acpi_device_power_manageable(acpi_dev))
+ error = acpi_device_set_power(acpi_dev, ACPI_STATE_D0);
return error;
}
@@ -295,9 +290,11 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
return error;
}
+ error = acpi_bind_one(&dev->dev, device);
+
num++;
- return 0;
+ return error;
}
static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
@@ -313,40 +310,6 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
return AE_OK;
}
-static int __init acpi_pnp_match(struct device *dev, void *_pnp)
-{
- struct acpi_device *acpi = to_acpi_device(dev);
- struct pnp_dev *pnp = _pnp;
-
- /* true means it matched */
- return pnp->data == acpi;
-}
-
-static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev)
-{
- dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev),
- acpi_pnp_match);
- if (!dev)
- return NULL;
-
- put_device(dev);
- return to_acpi_device(dev);
-}
-
-/* complete initialization of a PNPACPI device includes having
- * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling.
- */
-static bool acpi_pnp_bus_match(struct device *dev)
-{
- return dev->bus == &pnp_bus_type;
-}
-
-static struct acpi_bus_type __initdata acpi_pnp_bus = {
- .name = "PNP",
- .match = acpi_pnp_bus_match,
- .find_companion = acpi_pnp_find_companion,
-};
-
int pnpacpi_disabled __initdata;
static int __init pnpacpi_init(void)
{
@@ -356,10 +319,8 @@ static int __init pnpacpi_init(void)
}
printk(KERN_INFO "pnp: PnP ACPI init\n");
pnp_register_protocol(&pnpacpi_protocol);
- register_acpi_bus_type(&acpi_pnp_bus);
acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num);
- unregister_acpi_bus_type(&acpi_pnp_bus);
pnp_platform_devices = 1;
return 0;
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ba6975123071..73cfcdf28a36 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -137,6 +137,13 @@ config BATTERY_COLLIE
Say Y to enable support for the battery on the Sharp Zaurus
SL-5500 (collie) models.
+config BATTERY_IPAQ_MICRO
+ tristate "iPAQ Atmel Micro ASIC battery driver"
+ depends on MFD_IPAQ_MICRO
+ help
+ Choose this option if you want to monitor battery status on
+ Compaq/HP iPAQ h3100 and h3600.
+
config BATTERY_WM97XX
bool "WM97xx generic battery driver"
depends on TOUCHSCREEN_WM97XX=y
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee54a3e4c90a..dfa894273926 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
+obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 79a37f6d3307..e384844a1ae1 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -840,8 +840,7 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
if (bq->automode < 1)
return NOTIFY_OK;
- sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
- bq2415x_set_mode(bq, bq->reported_mode);
+ schedule_delayed_work(&bq->work, 0);
return NOTIFY_OK;
}
@@ -892,6 +891,11 @@ static void bq2415x_timer_work(struct work_struct *work)
int error;
int boost;
+ if (bq->automode > 0 && (bq->reported_mode != bq->mode)) {
+ sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
+ bq2415x_set_mode(bq, bq->reported_mode);
+ }
+
if (!bq->autotimer)
return;
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index b309713b63bc..e10763e3a1d5 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -25,6 +25,7 @@
* http://www.ti.com/product/bq27425-g1
*/
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/jiffies.h>
@@ -415,6 +416,9 @@ static void bq27x00_update(struct bq27x00_device_info *di)
bool is_bq27425 = di->chip == BQ27425;
cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
+ if ((cache.flags & 0xff) == 0xff)
+ /* read error */
+ cache.flags = -1;
if (cache.flags >= 0) {
if (!is_bq27500 && !is_bq27425
&& (cache.flags & BQ27000_FLAG_CI)) {
@@ -804,7 +808,7 @@ static int bq27x00_battery_probe(struct i2c_client *client,
goto batt_failed_1;
}
- di = kzalloc(sizeof(*di), GFP_KERNEL);
+ di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&client->dev, "failed to allocate device info data\n");
retval = -ENOMEM;
@@ -819,14 +823,12 @@ static int bq27x00_battery_probe(struct i2c_client *client,
retval = bq27x00_powersupply_init(di);
if (retval)
- goto batt_failed_3;
+ goto batt_failed_2;
i2c_set_clientdata(client, di);
return 0;
-batt_failed_3:
- kfree(di);
batt_failed_2:
kfree(name);
batt_failed_1:
@@ -849,8 +851,6 @@ static int bq27x00_battery_remove(struct i2c_client *client)
idr_remove(&battery_id, di->id);
mutex_unlock(&battery_mutex);
- kfree(di);
-
return 0;
}
@@ -933,7 +933,6 @@ static int bq27000_battery_probe(struct platform_device *pdev)
{
struct bq27x00_device_info *di;
struct bq27000_platform_data *pdata = pdev->dev.platform_data;
- int ret;
if (!pdata) {
dev_err(&pdev->dev, "no platform_data supplied\n");
@@ -945,7 +944,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
return -EINVAL;
}
- di = kzalloc(sizeof(*di), GFP_KERNEL);
+ di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&pdev->dev, "failed to allocate device info data\n");
return -ENOMEM;
@@ -959,16 +958,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
di->bat.name = pdata->name ?: dev_name(&pdev->dev);
di->bus.read = &bq27000_read_platform;
- ret = bq27x00_powersupply_init(di);
- if (ret)
- goto err_free;
-
- return 0;
-
-err_free:
- kfree(di);
-
- return ret;
+ return bq27x00_powersupply_init(di);
}
static int bq27000_battery_remove(struct platform_device *pdev)
@@ -977,8 +967,6 @@ static int bq27000_battery_remove(struct platform_device *pdev)
bq27x00_powersupply_unregister(di);
- kfree(di);
-
return 0;
}
diff --git a/drivers/power/ipaq_micro_battery.c b/drivers/power/ipaq_micro_battery.c
new file mode 100644
index 000000000000..9d694605cdb7
--- /dev/null
+++ b/drivers/power/ipaq_micro_battery.c
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ *
+ * h3xxx atmel micro companion support, battery subdevice
+ * based on previous kernel 2.4 version
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ipaq-micro.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+
+#define BATT_PERIOD 100000 /* 100 seconds in milliseconds */
+
+#define MICRO_BATT_CHEM_ALKALINE 0x01
+#define MICRO_BATT_CHEM_NICD 0x02
+#define MICRO_BATT_CHEM_NIMH 0x03
+#define MICRO_BATT_CHEM_LION 0x04
+#define MICRO_BATT_CHEM_LIPOLY 0x05
+#define MICRO_BATT_CHEM_NOT_INSTALLED 0x06
+#define MICRO_BATT_CHEM_UNKNOWN 0xff
+
+#define MICRO_BATT_STATUS_HIGH 0x01
+#define MICRO_BATT_STATUS_LOW 0x02
+#define MICRO_BATT_STATUS_CRITICAL 0x04
+#define MICRO_BATT_STATUS_CHARGING 0x08
+#define MICRO_BATT_STATUS_CHARGEMAIN 0x10
+#define MICRO_BATT_STATUS_DEAD 0x20 /* Battery will not charge */
+#define MICRO_BATT_STATUS_NOTINSTALLED 0x20 /* For expansion pack batteries */
+#define MICRO_BATT_STATUS_FULL 0x40 /* Battery fully charged */
+#define MICRO_BATT_STATUS_NOBATTERY 0x80
+#define MICRO_BATT_STATUS_UNKNOWN 0xff
+
+struct micro_battery {
+ struct ipaq_micro *micro;
+ struct workqueue_struct *wq;
+ struct delayed_work update;
+ u8 ac;
+ u8 chemistry;
+ unsigned int voltage;
+ u16 temperature;
+ u8 flag;
+};
+
+static void micro_battery_work(struct work_struct *work)
+{
+ struct micro_battery *mb = container_of(work,
+ struct micro_battery, update.work);
+ struct ipaq_micro_msg msg_battery = {
+ .id = MSG_BATTERY,
+ };
+ struct ipaq_micro_msg msg_sensor = {
+ .id = MSG_THERMAL_SENSOR,
+ };
+
+ /* First send battery message */
+ ipaq_micro_tx_msg_sync(mb->micro, &msg_battery);
+ if (msg_battery.rx_len < 4)
+ pr_info("ERROR");
+
+ /*
+ * Returned message format:
+ * byte 0: 0x00 = Not plugged in
+ * 0x01 = AC adapter plugged in
+ * byte 1: chemistry
+ * byte 2: voltage LSB
+ * byte 3: voltage MSB
+ * byte 4: flags
+ * byte 5-9: same for battery 2
+ */
+ mb->ac = msg_battery.rx_data[0];
+ mb->chemistry = msg_battery.rx_data[1];
+ mb->voltage = ((((unsigned short)msg_battery.rx_data[3] << 8) +
+ msg_battery.rx_data[2]) * 5000L) * 1000 / 1024;
+ mb->flag = msg_battery.rx_data[4];
+
+ if (msg_battery.rx_len == 9)
+ pr_debug("second battery ignored\n");
+
+ /* Then read the sensor */
+ ipaq_micro_tx_msg_sync(mb->micro, &msg_sensor);
+ mb->temperature = msg_sensor.rx_data[1] << 8 | msg_sensor.rx_data[0];
+
+ queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
+}
+
+static int get_capacity(struct power_supply *b)
+{
+ struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+ switch (mb->flag & 0x07) {
+ case MICRO_BATT_STATUS_HIGH:
+ return 100;
+ break;
+ case MICRO_BATT_STATUS_LOW:
+ return 50;
+ break;
+ case MICRO_BATT_STATUS_CRITICAL:
+ return 5;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int get_status(struct power_supply *b)
+{
+ struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+ if (mb->flag == MICRO_BATT_STATUS_UNKNOWN)
+ return POWER_SUPPLY_STATUS_UNKNOWN;
+
+ if (mb->flag & MICRO_BATT_STATUS_FULL)
+ return POWER_SUPPLY_STATUS_FULL;
+
+ if ((mb->flag & MICRO_BATT_STATUS_CHARGING) ||
+ (mb->flag & MICRO_BATT_STATUS_CHARGEMAIN))
+ return POWER_SUPPLY_STATUS_CHARGING;
+
+ return POWER_SUPPLY_STATUS_DISCHARGING;
+}
+
+static int micro_batt_get_property(struct power_supply *b,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ switch (mb->chemistry) {
+ case MICRO_BATT_CHEM_NICD:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd;
+ break;
+ case MICRO_BATT_CHEM_NIMH:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+ break;
+ case MICRO_BATT_CHEM_LION:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case MICRO_BATT_CHEM_LIPOLY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+ break;
+ };
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = get_status(b);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = 4700000;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = get_capacity(b);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = mb->temperature;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = mb->voltage;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ return 0;
+}
+
+static int micro_ac_get_property(struct power_supply *b,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mb->ac;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ return 0;
+}
+
+static enum power_supply_property micro_batt_power_props[] = {
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static struct power_supply micro_batt_power = {
+ .name = "main-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = micro_batt_power_props,
+ .num_properties = ARRAY_SIZE(micro_batt_power_props),
+ .get_property = micro_batt_get_property,
+ .use_for_apm = 1,
+};
+
+static enum power_supply_property micro_ac_power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply micro_ac_power = {
+ .name = "ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = micro_ac_power_props,
+ .num_properties = ARRAY_SIZE(micro_ac_power_props),
+ .get_property = micro_ac_get_property,
+};
+
+static int micro_batt_probe(struct platform_device *pdev)
+{
+ struct micro_battery *mb;
+
+ mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
+ if (!mb)
+ return -ENOMEM;
+
+ mb->micro = dev_get_drvdata(pdev->dev.parent);
+ mb->wq = create_singlethread_workqueue("ipaq-battery-wq");
+ INIT_DELAYED_WORK(&mb->update, micro_battery_work);
+ platform_set_drvdata(pdev, mb);
+ queue_delayed_work(mb->wq, &mb->update, 1);
+ power_supply_register(&pdev->dev, &micro_batt_power);
+ power_supply_register(&pdev->dev, &micro_ac_power);
+
+ dev_info(&pdev->dev, "iPAQ micro battery driver\n");
+ return 0;
+}
+
+static int micro_batt_remove(struct platform_device *pdev)
+
+{
+ struct micro_battery *mb = platform_get_drvdata(pdev);
+
+ power_supply_unregister(&micro_ac_power);
+ power_supply_unregister(&micro_batt_power);
+ cancel_delayed_work_sync(&mb->update);
+
+ return 0;
+}
+
+static int micro_batt_suspend(struct device *dev)
+{
+ struct micro_battery *mb = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&mb->update);
+ return 0;
+}
+
+static int micro_batt_resume(struct device *dev)
+{
+ struct micro_battery *mb = dev_get_drvdata(dev);
+
+ queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
+ return 0;
+}
+
+static const struct dev_pm_ops micro_batt_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(micro_batt_suspend, micro_batt_resume)
+};
+
+static struct platform_driver micro_batt_device_driver = {
+ .driver = {
+ .name = "ipaq-micro-battery",
+ .pm = &micro_batt_dev_pm_ops,
+ },
+ .probe = micro_batt_probe,
+ .remove = micro_batt_remove,
+};
+module_platform_driver(micro_batt_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro battery");
+MODULE_ALIAS("platform:battery-ipaq-micro");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 5a5a24e7d43c..078afd61490d 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -537,7 +537,8 @@ static void psy_unregister_cooler(struct power_supply *psy)
}
#endif
-int __power_supply_register(struct device *parent, struct power_supply *psy, bool ws)
+static int __power_supply_register(struct device *parent,
+ struct power_supply *psy, bool ws)
{
struct device *dev;
int rc;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 44420d1e9094..750a20275664 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -167,6 +167,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(constant_charge_voltage_max),
POWER_SUPPLY_ATTR(charge_control_limit),
POWER_SUPPLY_ATTR(charge_control_limit_max),
+ POWER_SUPPLY_ATTR(input_current_limit),
POWER_SUPPLY_ATTR(energy_full_design),
POWER_SUPPLY_ATTR(energy_empty_design),
POWER_SUPPLY_ATTR(energy_full),
@@ -178,6 +179,8 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(capacity_alert_max),
POWER_SUPPLY_ATTR(capacity_level),
POWER_SUPPLY_ATTR(temp),
+ POWER_SUPPLY_ATTR(temp_max),
+ POWER_SUPPLY_ATTR(temp_min),
POWER_SUPPLY_ATTR(temp_alert_min),
POWER_SUPPLY_ATTR(temp_alert_max),
POWER_SUPPLY_ATTR(temp_ambient),
@@ -189,6 +192,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(time_to_full_avg),
POWER_SUPPLY_ATTR(type),
POWER_SUPPLY_ATTR(scope),
+ POWER_SUPPLY_ATTR(charge_term_current),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index bdcf5173e377..ca41523bbebf 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -20,6 +20,17 @@ config POWER_RESET_AXXIA
Say Y if you have an Axxia family SoC.
+config POWER_RESET_BRCMSTB
+ bool "Broadcom STB reset driver" if COMPILE_TEST
+ depends on POWER_RESET && ARM
+ default ARCH_BRCMSTB
+ help
+ This driver provides restart support for ARM-based Broadcom STB
+ boards.
+
+ Say Y here if you have an ARM-based Broadcom STB board and you wish
+ to have restart support.
+
config POWER_RESET_GPIO
bool "GPIO power-off driver"
depends on OF_GPIO && POWER_RESET
@@ -28,6 +39,12 @@ config POWER_RESET_GPIO
If your board needs a GPIO high/low to power down, say Y and
create a binding in your devicetree.
+config POWER_RESET_HISI
+ bool "Hisilicon power-off driver"
+ depends on POWER_RESET && ARCH_HISI
+ help
+ Reboot support for Hisilicon boards.
+
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on POWER_RESET && ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index dde2e8bbac53..a42e70edd037 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,6 +1,8 @@
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
+obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
+obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c
new file mode 100644
index 000000000000..3f236924742a
--- /dev/null
+++ b/drivers/power/reset/brcmstb-reboot.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+#include <linux/smp.h>
+#include <linux/mfd/syscon.h>
+
+#include <asm/system_misc.h>
+
+#define RESET_SOURCE_ENABLE_REG 1
+#define SW_MASTER_RESET_REG 2
+
+static struct regmap *regmap;
+static u32 rst_src_en;
+static u32 sw_mstr_rst;
+
+static void brcmstb_reboot(enum reboot_mode mode, const char *cmd)
+{
+ int rc;
+ u32 tmp;
+
+ rc = regmap_write(regmap, rst_src_en, 1);
+ if (rc) {
+ pr_err("failed to write rst_src_en (%d)\n", rc);
+ return;
+ }
+
+ rc = regmap_read(regmap, rst_src_en, &tmp);
+ if (rc) {
+ pr_err("failed to read rst_src_en (%d)\n", rc);
+ return;
+ }
+
+ rc = regmap_write(regmap, sw_mstr_rst, 1);
+ if (rc) {
+ pr_err("failed to write sw_mstr_rst (%d)\n", rc);
+ return;
+ }
+
+ rc = regmap_read(regmap, sw_mstr_rst, &tmp);
+ if (rc) {
+ pr_err("failed to read sw_mstr_rst (%d)\n", rc);
+ return;
+ }
+
+ while (1)
+ ;
+}
+
+static int brcmstb_reboot_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct device_node *np = pdev->dev.of_node;
+
+ regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
+ if (IS_ERR(regmap)) {
+ pr_err("failed to get syscon phandle\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_index(np, "syscon", RESET_SOURCE_ENABLE_REG,
+ &rst_src_en);
+ if (rc) {
+ pr_err("can't get rst_src_en offset (%d)\n", rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_index(np, "syscon", SW_MASTER_RESET_REG,
+ &sw_mstr_rst);
+ if (rc) {
+ pr_err("can't get sw_mstr_rst offset (%d)\n", rc);
+ return -EINVAL;
+ }
+
+ arm_pm_restart = brcmstb_reboot;
+
+ return 0;
+}
+
+static const struct of_device_id of_match[] = {
+ { .compatible = "brcm,brcmstb-reboot", },
+ {},
+};
+
+static struct platform_driver brcmstb_reboot_driver = {
+ .probe = brcmstb_reboot_probe,
+ .driver = {
+ .name = "brcmstb-reboot",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match,
+ },
+};
+
+static int __init brcmstb_reboot_init(void)
+{
+ return platform_driver_probe(&brcmstb_reboot_driver,
+ brcmstb_reboot_probe);
+}
+subsys_initcall(brcmstb_reboot_init);
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index e290d48ddd99..ce849bc9b269 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -15,31 +15,29 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
#include <linux/module.h>
/*
* Hold configuration here, cannot be more than one instance of the driver
* since pm_power_off itself is global.
*/
-static int gpio_num = -1;
-static int gpio_active_low;
+static struct gpio_desc *reset_gpio;
static void gpio_poweroff_do_poweroff(void)
{
- BUG_ON(!gpio_is_valid(gpio_num));
+ BUG_ON(!reset_gpio);
/* drive it active, also inactive->active edge */
- gpio_direction_output(gpio_num, !gpio_active_low);
+ gpiod_direction_output(reset_gpio, 1);
mdelay(100);
/* drive inactive, also active->inactive edge */
- gpio_set_value(gpio_num, gpio_active_low);
+ gpiod_set_value(reset_gpio, 0);
mdelay(100);
/* drive it active, also inactive->active edge */
- gpio_set_value(gpio_num, !gpio_active_low);
+ gpiod_set_value(reset_gpio, 1);
/* give it some time */
mdelay(3000);
@@ -49,54 +47,42 @@ static void gpio_poweroff_do_poweroff(void)
static int gpio_poweroff_probe(struct platform_device *pdev)
{
- enum of_gpio_flags flags;
bool input = false;
- int ret;
/* If a pm_power_off function has already been added, leave it alone */
if (pm_power_off != NULL) {
- pr_err("%s: pm_power_off function already registered",
+ dev_err(&pdev->dev,
+ "%s: pm_power_off function already registered",
__func__);
return -EBUSY;
}
- gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
- if (!gpio_is_valid(gpio_num))
- return gpio_num;
-
- gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
+ reset_gpio = devm_gpiod_get(&pdev->dev, NULL);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
input = of_property_read_bool(pdev->dev.of_node, "input");
- ret = gpio_request(gpio_num, "poweroff-gpio");
- if (ret) {
- pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
- return ret;
- }
if (input) {
- if (gpio_direction_input(gpio_num)) {
- pr_err("Could not set direction of GPIO %d to input",
- gpio_num);
- goto err;
+ if (gpiod_direction_input(reset_gpio)) {
+ dev_err(&pdev->dev,
+ "Could not set direction of reset GPIO to input\n");
+ return -ENODEV;
}
} else {
- if (gpio_direction_output(gpio_num, gpio_active_low)) {
- pr_err("Could not set direction of GPIO %d", gpio_num);
- goto err;
+ if (gpiod_direction_output(reset_gpio, 0)) {
+ dev_err(&pdev->dev,
+ "Could not set direction of reset GPIO\n");
+ return -ENODEV;
}
}
pm_power_off = &gpio_poweroff_do_poweroff;
return 0;
-
-err:
- gpio_free(gpio_num);
- return -ENODEV;
}
static int gpio_poweroff_remove(struct platform_device *pdev)
{
- gpio_free(gpio_num);
if (pm_power_off == &gpio_poweroff_do_poweroff)
pm_power_off = NULL;
diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c
new file mode 100644
index 000000000000..0c91d0231d36
--- /dev/null
+++ b/drivers/power/reset/hisi-reboot.c
@@ -0,0 +1,67 @@
+/*
+ * Hisilicon SoC reset code
+ *
+ * Copyright (c) 2014 Hisilicon Ltd.
+ * Copyright (c) 2014 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/proc-fns.h>
+#include <asm/system_misc.h>
+
+static void __iomem *base;
+static u32 reboot_offset;
+
+static void hisi_restart(enum reboot_mode mode, const char *cmd)
+{
+ writel_relaxed(0xdeadbeef, base + reboot_offset);
+
+ while (1)
+ cpu_do_idle();
+}
+
+static int hisi_reboot_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ WARN(1, "failed to map base address");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
+ pr_err("failed to find reboot-offset property\n");
+ return -EINVAL;
+ }
+
+ arm_pm_restart = hisi_restart;
+
+ return 0;
+}
+
+static struct of_device_id hisi_reboot_of_match[] = {
+ { .compatible = "hisilicon,sysctrl" },
+ {}
+};
+
+static struct platform_driver hisi_reboot_driver = {
+ .probe = hisi_reboot_probe,
+ .driver = {
+ .name = "hisi-reboot",
+ .of_match_table = hisi_reboot_of_match,
+ },
+};
+module_platform_driver(hisi_reboot_driver);
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index 5758033e0c16..3e51f8d29bfe 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -62,5 +62,5 @@ module_platform_driver(restart_poweroff_driver);
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch");
MODULE_DESCRIPTION("restart poweroff driver");
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:poweroff-restart");
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
index 1bc5857b8bd5..d5a2acfb8821 100644
--- a/drivers/power/rx51_battery.c
+++ b/drivers/power/rx51_battery.c
@@ -24,34 +24,27 @@
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/i2c/twl4030-madc.h>
-
-/* RX51 specific channels */
-#define TWL4030_MADC_BTEMP_RX51 TWL4030_MADC_ADCIN0
-#define TWL4030_MADC_BCI_RX51 TWL4030_MADC_ADCIN4
+#include <linux/iio/consumer.h>
+#include <linux/of.h>
struct rx51_device_info {
struct device *dev;
struct power_supply bat;
+ struct iio_channel *channel_temp;
+ struct iio_channel *channel_bsi;
+ struct iio_channel *channel_vbat;
};
/*
* Read ADCIN channel value, code copied from maemo kernel
*/
-static int rx51_battery_read_adc(int channel)
+static int rx51_battery_read_adc(struct iio_channel *channel)
{
- struct twl4030_madc_request req;
-
- req.channels = channel;
- req.do_avg = 1;
- req.method = TWL4030_MADC_SW1;
- req.func_cb = NULL;
- req.type = TWL4030_MADC_WAIT;
- req.raw = true;
-
- if (twl4030_madc_conversion(&req) <= 0)
- return -ENODATA;
-
- return req.rbuf[ffs(channel) - 1];
+ int val, err;
+ err = iio_read_channel_average_raw(channel, &val);
+ if (err < 0)
+ return err;
+ return val;
}
/*
@@ -60,10 +53,12 @@ static int rx51_battery_read_adc(int channel)
*/
static int rx51_battery_read_voltage(struct rx51_device_info *di)
{
- int voltage = rx51_battery_read_adc(TWL4030_MADC_VBAT);
+ int voltage = rx51_battery_read_adc(di->channel_vbat);
- if (voltage < 0)
+ if (voltage < 0) {
+ dev_err(di->dev, "Could not read ADC: %d\n", voltage);
return voltage;
+ }
return 1000 * (10000 * voltage / 1705);
}
@@ -112,7 +107,10 @@ static int rx51_battery_read_temperature(struct rx51_device_info *di)
{
int min = 0;
int max = ARRAY_SIZE(rx51_temp_table2) - 1;
- int raw = rx51_battery_read_adc(TWL4030_MADC_BTEMP_RX51);
+ int raw = rx51_battery_read_adc(di->channel_temp);
+
+ if (raw < 0)
+ dev_err(di->dev, "Could not read ADC: %d\n", raw);
/* Zero and negative values are undefined */
if (raw <= 0)
@@ -146,10 +144,12 @@ static int rx51_battery_read_temperature(struct rx51_device_info *di)
*/
static int rx51_battery_read_capacity(struct rx51_device_info *di)
{
- int capacity = rx51_battery_read_adc(TWL4030_MADC_BCI_RX51);
+ int capacity = rx51_battery_read_adc(di->channel_bsi);
- if (capacity < 0)
+ if (capacity < 0) {
+ dev_err(di->dev, "Could not read ADC: %d\n", capacity);
return capacity;
+ }
return 1280 * (1200 * capacity)/(1024 - capacity);
}
@@ -213,17 +213,46 @@ static int rx51_battery_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, di);
+ di->dev = &pdev->dev;
di->bat.name = dev_name(&pdev->dev);
di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
di->bat.properties = rx51_battery_props;
di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
di->bat.get_property = rx51_battery_get_property;
+ di->channel_temp = iio_channel_get(di->dev, "temp");
+ if (IS_ERR(di->channel_temp)) {
+ ret = PTR_ERR(di->channel_temp);
+ goto error;
+ }
+
+ di->channel_bsi = iio_channel_get(di->dev, "bsi");
+ if (IS_ERR(di->channel_bsi)) {
+ ret = PTR_ERR(di->channel_bsi);
+ goto error_channel_temp;
+ }
+
+ di->channel_vbat = iio_channel_get(di->dev, "vbat");
+ if (IS_ERR(di->channel_vbat)) {
+ ret = PTR_ERR(di->channel_vbat);
+ goto error_channel_bsi;
+ }
+
ret = power_supply_register(di->dev, &di->bat);
if (ret)
- return ret;
+ goto error_channel_vbat;
return 0;
+
+error_channel_vbat:
+ iio_channel_release(di->channel_vbat);
+error_channel_bsi:
+ iio_channel_release(di->channel_bsi);
+error_channel_temp:
+ iio_channel_release(di->channel_temp);
+error:
+
+ return ret;
}
static int rx51_battery_remove(struct platform_device *pdev)
@@ -232,15 +261,28 @@ static int rx51_battery_remove(struct platform_device *pdev)
power_supply_unregister(&di->bat);
+ iio_channel_release(di->channel_vbat);
+ iio_channel_release(di->channel_bsi);
+ iio_channel_release(di->channel_temp);
+
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id n900_battery_of_match[] = {
+ {.compatible = "nokia,n900-battery", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, n900_battery_of_match);
+#endif
+
static struct platform_driver rx51_battery_driver = {
.probe = rx51_battery_probe,
.remove = rx51_battery_remove,
.driver = {
.name = "rx51-battery",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(n900_battery_of_match),
},
};
module_platform_driver(rx51_battery_driver);
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 1685f63b9e5d..3e8ba97c8169 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -17,9 +17,11 @@
*/
#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/freezer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -32,11 +34,15 @@
#define TPS65090_VACG BIT(1)
#define TPS65090_NOITERM BIT(5)
+#define POLL_INTERVAL (HZ * 2) /* Used when no irq */
+
struct tps65090_charger {
struct device *dev;
int ac_online;
int prev_ac_online;
int irq;
+ struct task_struct *poll_task;
+ bool passive_mode;
struct power_supply ac;
struct tps65090_platform_data *pdata;
};
@@ -49,6 +55,9 @@ static int tps65090_low_chrg_current(struct tps65090_charger *charger)
{
int ret;
+ if (charger->passive_mode)
+ return 0;
+
ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
TPS65090_NOITERM);
if (ret < 0) {
@@ -64,6 +73,9 @@ static int tps65090_enable_charging(struct tps65090_charger *charger)
int ret;
uint8_t ctrl0 = 0;
+ if (charger->passive_mode)
+ return 0;
+
ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
&ctrl0);
if (ret < 0) {
@@ -87,6 +99,9 @@ static int tps65090_config_charger(struct tps65090_charger *charger)
uint8_t intrmask = 0;
int ret;
+ if (charger->passive_mode)
+ return 0;
+
if (charger->pdata->enable_low_current_chrg) {
ret = tps65090_low_chrg_current(charger);
if (ret < 0) {
@@ -164,10 +179,14 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
}
/* Clear interrupts. */
- ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_STS, 0x00);
- if (ret < 0) {
- dev_err(charger->dev, "%s(): Error in writing reg 0x%x\n",
+ if (!charger->passive_mode) {
+ ret = tps65090_write(charger->dev->parent,
+ TPS65090_REG_INTR_STS, 0x00);
+ if (ret < 0) {
+ dev_err(charger->dev,
+ "%s(): Error in writing reg 0x%x\n",
__func__, TPS65090_REG_INTR_STS);
+ }
}
if (charger->prev_ac_online != charger->ac_online)
@@ -198,6 +217,18 @@ static struct tps65090_platform_data *
}
+static int tps65090_charger_poll_task(void *data)
+{
+ set_freezable();
+
+ while (!kthread_should_stop()) {
+ schedule_timeout_interruptible(POLL_INTERVAL);
+ try_to_freeze();
+ tps65090_charger_isr(-1, data);
+ }
+ return 0;
+}
+
static int tps65090_charger_probe(struct platform_device *pdev)
{
struct tps65090_charger *cdata;
@@ -244,22 +275,10 @@ static int tps65090_charger_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq);
- ret = irq;
- goto fail_unregister_supply;
- }
-
+ if (irq < 0)
+ irq = -ENXIO;
cdata->irq = irq;
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
- tps65090_charger_isr, 0, "tps65090-charger", cdata);
- if (ret) {
- dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq,
- ret);
- goto fail_unregister_supply;
- }
-
ret = tps65090_config_charger(cdata);
if (ret < 0) {
dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
@@ -285,6 +304,27 @@ static int tps65090_charger_probe(struct platform_device *pdev)
power_supply_changed(&cdata->ac);
}
+ if (irq != -ENXIO) {
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ tps65090_charger_isr, 0, "tps65090-charger", cdata);
+ if (ret) {
+ dev_err(cdata->dev,
+ "Unable to register irq %d err %d\n", irq,
+ ret);
+ goto fail_unregister_supply;
+ }
+ } else {
+ cdata->poll_task = kthread_run(tps65090_charger_poll_task,
+ cdata, "ktps65090charger");
+ cdata->passive_mode = true;
+ if (IS_ERR(cdata->poll_task)) {
+ ret = PTR_ERR(cdata->poll_task);
+ dev_err(cdata->dev,
+ "Unable to run kthread err %d\n", ret);
+ goto fail_unregister_supply;
+ }
+ }
+
return 0;
fail_unregister_supply:
@@ -297,6 +337,8 @@ static int tps65090_charger_remove(struct platform_device *pdev)
{
struct tps65090_charger *cdata = platform_get_drvdata(pdev);
+ if (cdata->irq == -ENXIO)
+ kthread_stop(cdata->poll_task);
power_supply_unregister(&cdata->ac);
return 0;
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index f14108844e1a..2598c588006e 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -28,10 +28,13 @@
#define TWL4030_BCIICHG 0x08
#define TWL4030_BCIVAC 0x0a
#define TWL4030_BCIVBUS 0x0c
+#define TWL4030_BCIMFSTS3 0x0F
#define TWL4030_BCIMFSTS4 0x10
#define TWL4030_BCICTL1 0x23
#define TWL4030_BB_CFG 0x12
+#define TWL4030_BCIMFSTS1 0x01
+
#define TWL4030_BCIAUTOWEN BIT(5)
#define TWL4030_CONFIG_DONE BIT(4)
#define TWL4030_BCIAUTOUSB BIT(1)
@@ -52,6 +55,9 @@
#define TWL4030_BBISEL_500uA 0x02
#define TWL4030_BBISEL_1000uA 0x03
+#define TWL4030_BATSTSPCHG BIT(2)
+#define TWL4030_BATSTSMCHG BIT(6)
+
/* BCI interrupts */
#define TWL4030_WOVF BIT(0) /* Watchdog overflow */
#define TWL4030_TMOVF BIT(1) /* Timer overflow */
@@ -145,6 +151,35 @@ static int twl4030bci_read_adc_val(u8 reg)
}
/*
+ * Check if Battery Pack was present
+ */
+static int twl4030_is_battery_present(struct twl4030_bci *bci)
+{
+ int ret;
+ u8 val = 0;
+
+ /* Battery presence in Main charge? */
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMFSTS3);
+ if (ret)
+ return ret;
+ if (val & TWL4030_BATSTSMCHG)
+ return 0;
+
+ /*
+ * OK, It could be that bootloader did not enable main charger,
+ * pre-charge is h/w auto. So, Battery presence in Pre-charge?
+ */
+ ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE, &val,
+ TWL4030_BCIMFSTS1);
+ if (ret)
+ return ret;
+ if (val & TWL4030_BATSTSPCHG)
+ return 0;
+
+ return -ENODEV;
+}
+
+/*
* Check if VBUS power is present
*/
static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
@@ -541,8 +576,14 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
bci->irq_chg = platform_get_irq(pdev, 0);
bci->irq_bci = platform_get_irq(pdev, 1);
- platform_set_drvdata(pdev, bci);
+ /* Only proceed further *IF* battery is physically present */
+ ret = twl4030_is_battery_present(bci);
+ if (ret) {
+ dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
+ goto fail_no_battery;
+ }
+ platform_set_drvdata(pdev, bci);
bci->ac.name = "twl4030_ac";
bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
bci->ac.properties = twl4030_charger_props;
@@ -633,6 +674,7 @@ fail_chg_irq:
fail_register_usb:
power_supply_unregister(&bci->ac);
fail_register_ac:
+fail_no_battery:
kfree(bci);
return ret;
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 419056d7887e..f8a76090cbca 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -86,17 +86,12 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin,
return -EINVAL;
break;
case PTP_PF_PHYSYNC:
- pr_err("sorry, cannot reassign the calibration pin\n");
- return -EINVAL;
+ if (chan != 0)
+ return -EINVAL;
default:
return -EINVAL;
}
- if (pin2->func == PTP_PF_PHYSYNC) {
- pr_err("sorry, cannot reprogram the calibration pin\n");
- return -EINVAL;
- }
-
if (info->verify(info, pin, func, chan)) {
pr_err("driver cannot use function %u on pin %u\n", func, chan);
return -EOPNOTSUPP;
diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index 90a106308c4f..255487272859 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -691,7 +691,7 @@ err_pci_en:
return ret;
}
-static DEFINE_PCI_DEVICE_TABLE(pch_ieee1588_pcidev_id) = {
+static const struct pci_device_id pch_ieee1588_pcidev_id[] = {
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_PCH_1588
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4ad7b89a4cb4..b800783800a3 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -43,7 +43,7 @@ config PWM_AB8500
config PWM_ATMEL
tristate "Atmel PWM support"
- depends on ARCH_AT91
+ depends on ARCH_AT91 || AVR32
help
Generic PWM framework driver for Atmel SoC.
@@ -206,6 +206,13 @@ config PWM_RENESAS_TPU
To compile this driver as a module, choose M here: the module
will be called pwm-renesas-tpu.
+config PWM_ROCKCHIP
+ tristate "Rockchip PWM support"
+ depends on ARCH_ROCKCHIP
+ help
+ Generic PWM framework driver for the PWM controller found on
+ Rockchip SoCs.
+
config PWM_SAMSUNG
tristate "Samsung PWM support"
depends on PLAT_SAMSUNG
@@ -226,6 +233,16 @@ config PWM_SPEAR
To compile this driver as a module, choose M here: the module
will be called pwm-spear.
+config PWM_STI
+ tristate "STiH4xx PWM support"
+ depends on ARCH_STI
+ depends on OF
+ help
+ Generic PWM framework driver for STiH4xx SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-sti.
+
config PWM_TEGRA
tristate "NVIDIA Tegra PWM support"
depends on ARCH_TEGRA
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 5c86a19d5d39..f8c577d41091 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -18,8 +18,10 @@ obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
+obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
+obj-$(CONFIG_PWM_STI) += pwm-sti.o
obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index d797c7b84c3f..5449d9150d40 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -262,6 +262,7 @@ static int imx_pwm_probe(struct platform_device *pdev)
imx->chip.dev = &pdev->dev;
imx->chip.base = -1;
imx->chip.npwm = 1;
+ imx->chip.can_sleep = true;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 44ce6c6103ae..4df994f72d96 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -14,7 +14,6 @@
*/
#include <linux/acpi.h>
-#include <linux/clk.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -37,7 +36,6 @@ static int pci_drv, plat_drv; /* So we know which drivers registered */
struct pwm_lpss_chip {
struct pwm_chip chip;
void __iomem *regs;
- struct clk *clk;
unsigned long clk_rate;
};
@@ -97,11 +95,6 @@ static int pwm_lpss_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct pwm_lpss_chip *lpwm = to_lpwm(chip);
u32 ctrl;
- int ret;
-
- ret = clk_prepare_enable(lpwm->clk);
- if (ret)
- return ret;
ctrl = readl(lpwm->regs + PWM);
writel(ctrl | PWM_ENABLE, lpwm->regs + PWM);
@@ -116,8 +109,6 @@ static void pwm_lpss_disable(struct pwm_chip *chip, struct pwm_device *pwm)
ctrl = readl(lpwm->regs + PWM);
writel(ctrl & ~PWM_ENABLE, lpwm->regs + PWM);
-
- clk_disable_unprepare(lpwm->clk);
}
static const struct pwm_ops pwm_lpss_ops = {
@@ -142,17 +133,7 @@ static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
if (IS_ERR(lpwm->regs))
return ERR_CAST(lpwm->regs);
- if (info) {
- lpwm->clk_rate = info->clk_rate;
- } else {
- lpwm->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(lpwm->clk)) {
- dev_err(dev, "failed to get PWM clock\n");
- return ERR_CAST(lpwm->clk);
- }
- lpwm->clk_rate = clk_get_rate(lpwm->clk);
- }
-
+ lpwm->clk_rate = info->clk_rate;
lpwm->chip.dev = dev;
lpwm->chip.ops = &pwm_lpss_ops;
lpwm->chip.base = -1;
@@ -221,12 +202,19 @@ static struct pci_driver pwm_lpss_driver_pci = {
static int pwm_lpss_probe_platform(struct platform_device *pdev)
{
+ const struct pwm_lpss_boardinfo *info;
+ const struct acpi_device_id *id;
struct pwm_lpss_chip *lpwm;
struct resource *r;
+ id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+ if (!id)
+ return -ENODEV;
+
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- lpwm = pwm_lpss_probe(&pdev->dev, r, NULL);
+ info = (struct pwm_lpss_boardinfo *)id->driver_data;
+ lpwm = pwm_lpss_probe(&pdev->dev, r, info);
if (IS_ERR(lpwm))
return PTR_ERR(lpwm);
@@ -242,7 +230,7 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
}
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
- { "80860F09", 0 },
+ { "80860F09", (unsigned long)&byt_info },
{ },
};
MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
new file mode 100644
index 000000000000..bdd8644c01cf
--- /dev/null
+++ b/drivers/pwm/pwm-rockchip.c
@@ -0,0 +1,264 @@
+/*
+ * PWM driver for Rockchip SoCs
+ *
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ * Copyright (C) 2014 ROCKCHIP, 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/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/time.h>
+
+#define PWM_CTRL_TIMER_EN (1 << 0)
+#define PWM_CTRL_OUTPUT_EN (1 << 3)
+
+#define PWM_ENABLE (1 << 0)
+#define PWM_CONTINUOUS (1 << 1)
+#define PWM_DUTY_POSITIVE (1 << 3)
+#define PWM_INACTIVE_NEGATIVE (0 << 4)
+#define PWM_OUTPUT_LEFT (0 << 5)
+#define PWM_LP_DISABLE (0 << 8)
+
+struct rockchip_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ const struct rockchip_pwm_data *data;
+ void __iomem *base;
+};
+
+struct rockchip_pwm_regs {
+ unsigned long duty;
+ unsigned long period;
+ unsigned long cntr;
+ unsigned long ctrl;
+};
+
+struct rockchip_pwm_data {
+ struct rockchip_pwm_regs regs;
+ unsigned int prescaler;
+
+ void (*set_enable)(struct pwm_chip *chip, bool enable);
+};
+
+static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
+{
+ return container_of(c, struct rockchip_pwm_chip, chip);
+}
+
+static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
+ u32 val;
+
+ val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+ if (enable)
+ val |= enable_conf;
+ else
+ val &= ~enable_conf;
+
+ writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
+static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
+ PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
+ PWM_INACTIVE_NEGATIVE;
+ u32 val;
+
+ val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+
+ if (enable)
+ val |= enable_conf;
+ else
+ val &= ~enable_conf;
+
+ writel_relaxed(val, pc->base + pc->data->regs.ctrl);
+}
+
+static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ unsigned long period, duty;
+ u64 clk_rate, div;
+ int ret;
+
+ clk_rate = clk_get_rate(pc->clk);
+
+ /*
+ * Since period and duty cycle registers have a width of 32
+ * bits, every possible input period can be obtained using the
+ * default prescaler value for all practical clock rate values.
+ */
+ div = clk_rate * period_ns;
+ do_div(div, pc->data->prescaler * NSEC_PER_SEC);
+ period = div;
+
+ div = clk_rate * duty_ns;
+ do_div(div, pc->data->prescaler * NSEC_PER_SEC);
+ duty = div;
+
+ ret = clk_enable(pc->clk);
+ if (ret)
+ return ret;
+
+ writel(period, pc->base + pc->data->regs.period);
+ writel(duty, pc->base + pc->data->regs.duty);
+ writel(0, pc->base + pc->data->regs.cntr);
+
+ clk_disable(pc->clk);
+
+ return 0;
+}
+
+static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ int ret;
+
+ ret = clk_enable(pc->clk);
+ if (ret)
+ return ret;
+
+ pc->data->set_enable(chip, true);
+
+ return 0;
+}
+
+static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+
+ pc->data->set_enable(chip, false);
+
+ clk_disable(pc->clk);
+}
+
+static const struct pwm_ops rockchip_pwm_ops = {
+ .config = rockchip_pwm_config,
+ .enable = rockchip_pwm_enable,
+ .disable = rockchip_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static const struct rockchip_pwm_data pwm_data_v1 = {
+ .regs = {
+ .duty = 0x04,
+ .period = 0x08,
+ .cntr = 0x00,
+ .ctrl = 0x0c,
+ },
+ .prescaler = 2,
+ .set_enable = rockchip_pwm_set_enable_v1,
+};
+
+static const struct rockchip_pwm_data pwm_data_v2 = {
+ .regs = {
+ .duty = 0x08,
+ .period = 0x04,
+ .cntr = 0x00,
+ .ctrl = 0x0c,
+ },
+ .prescaler = 1,
+ .set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct rockchip_pwm_data pwm_data_vop = {
+ .regs = {
+ .duty = 0x08,
+ .period = 0x04,
+ .cntr = 0x0c,
+ .ctrl = 0x00,
+ },
+ .prescaler = 1,
+ .set_enable = rockchip_pwm_set_enable_v2,
+};
+
+static const struct of_device_id rockchip_pwm_dt_ids[] = {
+ { .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
+ { .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
+ { .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
+
+static int rockchip_pwm_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *id;
+ struct rockchip_pwm_chip *pc;
+ struct resource *r;
+ int ret;
+
+ id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
+ if (!id)
+ return -EINVAL;
+
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pc->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(pc->base))
+ return PTR_ERR(pc->base);
+
+ pc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pc->clk))
+ return PTR_ERR(pc->clk);
+
+ ret = clk_prepare(pc->clk);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, pc);
+
+ pc->data = id->data;
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &rockchip_pwm_ops;
+ pc->chip.base = -1;
+ pc->chip.npwm = 1;
+
+ ret = pwmchip_add(&pc->chip);
+ if (ret < 0) {
+ clk_unprepare(pc->clk);
+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static int rockchip_pwm_remove(struct platform_device *pdev)
+{
+ struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
+
+ clk_unprepare(pc->clk);
+
+ return pwmchip_remove(&pc->chip);
+}
+
+static struct platform_driver rockchip_pwm_driver = {
+ .driver = {
+ .name = "rockchip-pwm",
+ .of_match_table = rockchip_pwm_dt_ids,
+ },
+ .probe = rockchip_pwm_probe,
+ .remove = rockchip_pwm_remove,
+};
+module_platform_driver(rockchip_pwm_driver);
+
+MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
+MODULE_DESCRIPTION("Rockchip SoC PWM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
new file mode 100644
index 000000000000..b95115cdaea7
--- /dev/null
+++ b/drivers/pwm/pwm-sti.c
@@ -0,0 +1,418 @@
+/*
+ * PWM device driver for ST SoCs.
+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>
+ *
+ * Copyright (C) 2013-2014 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/math64.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+
+#define STI_DS_REG(ch) (4 * (ch)) /* Channel's Duty Cycle register */
+#define STI_PWMCR 0x50 /* Control/Config register */
+#define STI_INTEN 0x54 /* Interrupt Enable/Disable register */
+#define PWM_PRESCALE_LOW_MASK 0x0f
+#define PWM_PRESCALE_HIGH_MASK 0xf0
+
+/* Regfield IDs */
+enum {
+ PWMCLK_PRESCALE_LOW,
+ PWMCLK_PRESCALE_HIGH,
+ PWM_EN,
+ PWM_INT_EN,
+
+ /* Keep last */
+ MAX_REGFIELDS
+};
+
+struct sti_pwm_compat_data {
+ const struct reg_field *reg_fields;
+ unsigned int num_chan;
+ unsigned int max_pwm_cnt;
+ unsigned int max_prescale;
+};
+
+struct sti_pwm_chip {
+ struct device *dev;
+ struct clk *clk;
+ unsigned long clk_rate;
+ struct regmap *regmap;
+ struct sti_pwm_compat_data *cdata;
+ struct regmap_field *prescale_low;
+ struct regmap_field *prescale_high;
+ struct regmap_field *pwm_en;
+ struct regmap_field *pwm_int_en;
+ struct pwm_chip chip;
+ struct pwm_device *cur;
+ unsigned int en_count;
+ struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
+ void __iomem *mmio;
+};
+
+static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
+ [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWMCR, 0, 3),
+ [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWMCR, 11, 14),
+ [PWM_EN] = REG_FIELD(STI_PWMCR, 9, 9),
+ [PWM_INT_EN] = REG_FIELD(STI_INTEN, 0, 0),
+};
+
+static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct sti_pwm_chip, chip);
+}
+
+/*
+ * Calculate the prescaler value corresponding to the period.
+ */
+static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
+ unsigned int *prescale)
+{
+ struct sti_pwm_compat_data *cdata = pc->cdata;
+ unsigned long val;
+ unsigned int ps;
+
+ /*
+ * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_count + 1)) - 1
+ */
+ val = NSEC_PER_SEC / pc->clk_rate;
+ val *= cdata->max_pwm_cnt + 1;
+
+ if (period % val) {
+ return -EINVAL;
+ } else {
+ ps = period / val - 1;
+ if (ps > cdata->max_prescale)
+ return -EINVAL;
+ }
+ *prescale = ps;
+
+ return 0;
+}
+
+/* Calculate the number of PWM devices configured with a period. */
+static unsigned int sti_pwm_count_configured(struct pwm_chip *chip)
+{
+ struct pwm_device *pwm;
+ unsigned int ncfg = 0;
+ unsigned int i;
+
+ for (i = 0; i < chip->npwm; i++) {
+ pwm = &chip->pwms[i];
+ if (test_bit(PWMF_REQUESTED, &pwm->flags)) {
+ if (pwm_get_period(pwm))
+ ncfg++;
+ }
+ }
+
+ return ncfg;
+}
+
+/*
+ * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
+ * The only way to change the period (apart from changing the PWM input clock)
+ * is to change the PWM clock prescaler.
+ * The prescaler is of 8 bits, so 256 prescaler values and hence
+ * 256 possible period values are supported (for a particular clock rate).
+ * The requested period will be applied only if it matches one of these
+ * 256 values.
+ */
+static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+ struct sti_pwm_compat_data *cdata = pc->cdata;
+ struct pwm_device *cur = pc->cur;
+ struct device *dev = pc->dev;
+ unsigned int prescale = 0, pwmvalx;
+ int ret;
+ unsigned int ncfg;
+ bool period_same = false;
+
+ ncfg = sti_pwm_count_configured(chip);
+ if (ncfg)
+ period_same = (period_ns == pwm_get_period(cur));
+
+ /* Allow configuration changes if one of the
+ * following conditions satisfy.
+ * 1. No channels have been configured.
+ * 2. Only one channel has been configured and the new request
+ * is for the same channel.
+ * 3. Only one channel has been configured and the new request is
+ * for a new channel and period of the new channel is same as
+ * the current configured period.
+ * 4. More than one channels are configured and period of the new
+ * requestis the same as the current period.
+ */
+ if (!ncfg ||
+ ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) ||
+ ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) ||
+ ((ncfg > 1) && period_same)) {
+ /* Enable clock before writing to PWM registers. */
+ ret = clk_enable(pc->clk);
+ if (ret)
+ return ret;
+
+ if (!period_same) {
+ ret = sti_pwm_get_prescale(pc, period_ns, &prescale);
+ if (ret)
+ goto clk_dis;
+
+ ret =
+ regmap_field_write(pc->prescale_low,
+ prescale & PWM_PRESCALE_LOW_MASK);
+ if (ret)
+ goto clk_dis;
+
+ ret =
+ regmap_field_write(pc->prescale_high,
+ (prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
+ if (ret)
+ goto clk_dis;
+ }
+
+ /*
+ * When PWMVal == 0, PWM pulse = 1 local clock cycle.
+ * When PWMVal == max_pwm_count,
+ * PWM pulse = (max_pwm_count + 1) local cycles,
+ * that is continuous pulse: signal never goes low.
+ */
+ pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns;
+
+ ret = regmap_write(pc->regmap, STI_DS_REG(pwm->hwpwm), pwmvalx);
+ if (ret)
+ goto clk_dis;
+
+ ret = regmap_field_write(pc->pwm_int_en, 0);
+
+ pc->cur = pwm;
+
+ dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n",
+ prescale, period_ns, duty_ns, pwmvalx);
+ } else {
+ return -EINVAL;
+ }
+
+clk_dis:
+ clk_disable(pc->clk);
+ return ret;
+}
+
+static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+ struct device *dev = pc->dev;
+ int ret = 0;
+
+ /*
+ * Since we have a common enable for all PWM channels,
+ * do not enable if already enabled.
+ */
+ mutex_lock(&pc->sti_pwm_lock);
+ if (!pc->en_count) {
+ ret = clk_enable(pc->clk);
+ if (ret)
+ goto out;
+
+ ret = regmap_field_write(pc->pwm_en, 1);
+ if (ret) {
+ dev_err(dev, "failed to enable PWM device:%d\n",
+ pwm->hwpwm);
+ goto out;
+ }
+ }
+ pc->en_count++;
+out:
+ mutex_unlock(&pc->sti_pwm_lock);
+ return ret;
+}
+
+static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
+
+ mutex_lock(&pc->sti_pwm_lock);
+ if (--pc->en_count) {
+ mutex_unlock(&pc->sti_pwm_lock);
+ return;
+ }
+ regmap_field_write(pc->pwm_en, 0);
+
+ clk_disable(pc->clk);
+ mutex_unlock(&pc->sti_pwm_lock);
+}
+
+static const struct pwm_ops sti_pwm_ops = {
+ .config = sti_pwm_config,
+ .enable = sti_pwm_enable,
+ .disable = sti_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
+{
+ struct device *dev = pc->dev;
+ const struct reg_field *reg_fields;
+ struct device_node *np = dev->of_node;
+ struct sti_pwm_compat_data *cdata = pc->cdata;
+ u32 num_chan;
+
+ of_property_read_u32(np, "st,pwm-num-chan", &num_chan);
+ if (num_chan)
+ cdata->num_chan = num_chan;
+
+ reg_fields = cdata->reg_fields;
+
+ pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
+ reg_fields[PWMCLK_PRESCALE_LOW]);
+ if (IS_ERR(pc->prescale_low))
+ return PTR_ERR(pc->prescale_low);
+
+ pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
+ reg_fields[PWMCLK_PRESCALE_HIGH]);
+ if (IS_ERR(pc->prescale_high))
+ return PTR_ERR(pc->prescale_high);
+
+ pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
+ reg_fields[PWM_EN]);
+ if (IS_ERR(pc->pwm_en))
+ return PTR_ERR(pc->pwm_en);
+
+ pc->pwm_int_en = devm_regmap_field_alloc(dev, pc->regmap,
+ reg_fields[PWM_INT_EN]);
+ if (IS_ERR(pc->pwm_int_en))
+ return PTR_ERR(pc->pwm_int_en);
+
+ return 0;
+}
+
+static const struct regmap_config sti_pwm_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int sti_pwm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sti_pwm_compat_data *cdata;
+ struct sti_pwm_chip *pc;
+ struct resource *res;
+ int ret;
+
+ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
+
+ cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
+ if (!cdata)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ pc->mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pc->mmio))
+ return PTR_ERR(pc->mmio);
+
+ pc->regmap = devm_regmap_init_mmio(dev, pc->mmio,
+ &sti_pwm_regmap_config);
+ if (IS_ERR(pc->regmap))
+ return PTR_ERR(pc->regmap);
+
+ /*
+ * Setup PWM data with default values: some values could be replaced
+ * with specific ones provided from Device Tree.
+ */
+ cdata->reg_fields = &sti_pwm_regfields[0];
+ cdata->max_prescale = 0xff;
+ cdata->max_pwm_cnt = 255;
+ cdata->num_chan = 1;
+
+ pc->cdata = cdata;
+ pc->dev = dev;
+ pc->en_count = 0;
+ mutex_init(&pc->sti_pwm_lock);
+
+ ret = sti_pwm_probe_dt(pc);
+ if (ret)
+ return ret;
+
+ pc->clk = of_clk_get_by_name(dev->of_node, "pwm");
+ if (IS_ERR(pc->clk)) {
+ dev_err(dev, "failed to get PWM clock\n");
+ return PTR_ERR(pc->clk);
+ }
+
+ pc->clk_rate = clk_get_rate(pc->clk);
+ if (!pc->clk_rate) {
+ dev_err(dev, "failed to get clock rate\n");
+ return -EINVAL;
+ }
+
+ ret = clk_prepare(pc->clk);
+ if (ret) {
+ dev_err(dev, "failed to prepare clock\n");
+ return ret;
+ }
+
+ pc->chip.dev = dev;
+ pc->chip.ops = &sti_pwm_ops;
+ pc->chip.base = -1;
+ pc->chip.npwm = pc->cdata->num_chan;
+ pc->chip.can_sleep = true;
+
+ ret = pwmchip_add(&pc->chip);
+ if (ret < 0) {
+ clk_unprepare(pc->clk);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pc);
+
+ return 0;
+}
+
+static int sti_pwm_remove(struct platform_device *pdev)
+{
+ struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
+ unsigned int i;
+
+ for (i = 0; i < pc->cdata->num_chan; i++)
+ pwm_disable(&pc->chip.pwms[i]);
+
+ clk_unprepare(pc->clk);
+
+ return pwmchip_remove(&pc->chip);
+}
+
+static const struct of_device_id sti_pwm_of_match[] = {
+ { .compatible = "st,sti-pwm", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sti_pwm_of_match);
+
+static struct platform_driver sti_pwm_driver = {
+ .driver = {
+ .name = "sti-pwm",
+ .of_match_table = sti_pwm_of_match,
+ },
+ .probe = sti_pwm_probe,
+ .remove = sti_pwm_remove,
+};
+module_platform_driver(sti_pwm_driver);
+
+MODULE_AUTHOR("Ajit Pal Singh <ajitpal.singh@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST PWM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
index 3b119bc2c3c6..67481dc6da3f 100644
--- a/drivers/pwm/pwm-tipwmss.c
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -62,10 +62,8 @@ static int pwmss_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ if (!info)
return -ENOMEM;
- }
mutex_init(&info->pwmss_lock);
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 2ca1a0b3ad57..8bcfecd66281 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2493,7 +2493,7 @@ err_exit:
return err;
}
-static DEFINE_PCI_DEVICE_TABLE(tsi721_pci_tbl) = {
+static const struct pci_device_id tsi721_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_TSI721) },
{ 0, } /* terminate list */
};
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 0305675270ee..a7b42680a06a 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -644,27 +644,26 @@ enum tsi721_smsg_int_flag {
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
-#define TSI721_BDMA_BD_RING_SZ 128
#define TSI721_BDMA_MAX_BCOUNT (TSI721_DMAD_BCOUNT1 + 1)
struct tsi721_tx_desc {
struct dma_async_tx_descriptor txd;
- struct tsi721_dma_desc *hw_desc;
u16 destid;
/* low 64-bits of 66-bit RIO address */
u64 rio_addr;
/* upper 2-bits of 66-bit RIO address */
u8 rio_addr_u;
- u32 bcount;
- bool interrupt;
+ enum dma_rtype rtype;
struct list_head desc_node;
- struct list_head tx_list;
+ struct scatterlist *sg;
+ unsigned int sg_len;
+ enum dma_status status;
};
struct tsi721_bdma_chan {
int id;
void __iomem *regs;
- int bd_num; /* number of buffer descriptors */
+ int bd_num; /* number of HW buffer descriptors */
void *bd_base; /* start of DMA descriptors */
dma_addr_t bd_phys;
void *sts_base; /* start of DMA BD status FIFO */
@@ -680,7 +679,6 @@ struct tsi721_bdma_chan {
struct list_head active_list;
struct list_head queue;
struct list_head free_list;
- dma_cookie_t completed_cookie;
struct tasklet_struct tasklet;
bool active;
};
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index 44341dc5b148..f64c5decb747 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -1,7 +1,7 @@
/*
* DMA Engine support for Tsi721 PCIExpress-to-SRIO bridge
*
- * Copyright 2011 Integrated Device Technology, Inc.
+ * Copyright (c) 2011-2014 Integrated Device Technology, Inc.
* Alexandre Bounine <alexandre.bounine@idt.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,9 +14,8 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
*/
#include <linux/io.h>
@@ -32,9 +31,22 @@
#include <linux/interrupt.h>
#include <linux/kfifo.h>
#include <linux/delay.h>
+#include "../../dma/dmaengine.h"
#include "tsi721.h"
+#define TSI721_DMA_TX_QUEUE_SZ 16 /* number of transaction descriptors */
+
+#ifdef CONFIG_PCI_MSI
+static irqreturn_t tsi721_bdma_msix(int irq, void *ptr);
+#endif
+static int tsi721_submit_sg(struct tsi721_tx_desc *desc);
+
+static unsigned int dma_desc_per_channel = 128;
+module_param(dma_desc_per_channel, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(dma_desc_per_channel,
+ "Number of DMA descriptors per channel (default: 128)");
+
static inline struct tsi721_bdma_chan *to_tsi721_chan(struct dma_chan *chan)
{
return container_of(chan, struct tsi721_bdma_chan, dchan);
@@ -59,7 +71,7 @@ struct tsi721_tx_desc *tsi721_dma_first_active(
struct tsi721_tx_desc, desc_node);
}
-static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
+static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
{
struct tsi721_dma_desc *bd_ptr;
struct device *dev = bdma_chan->dchan.device->dev;
@@ -67,17 +79,23 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
dma_addr_t bd_phys;
dma_addr_t sts_phys;
int sts_size;
- int bd_num = bdma_chan->bd_num;
+#ifdef CONFIG_PCI_MSI
+ struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
+#endif
dev_dbg(dev, "Init Block DMA Engine, CH%d\n", bdma_chan->id);
- /* Allocate space for DMA descriptors */
+ /*
+ * Allocate space for DMA descriptors
+ * (add an extra element for link descriptor)
+ */
bd_ptr = dma_zalloc_coherent(dev,
- bd_num * sizeof(struct tsi721_dma_desc),
+ (bd_num + 1) * sizeof(struct tsi721_dma_desc),
&bd_phys, GFP_KERNEL);
if (!bd_ptr)
return -ENOMEM;
+ bdma_chan->bd_num = bd_num;
bdma_chan->bd_phys = bd_phys;
bdma_chan->bd_base = bd_ptr;
@@ -85,8 +103,8 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
bd_ptr, (unsigned long long)bd_phys);
/* Allocate space for descriptor status FIFO */
- sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
- bd_num : TSI721_DMA_MINSTSSZ;
+ sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ?
+ (bd_num + 1) : TSI721_DMA_MINSTSSZ;
sts_size = roundup_pow_of_two(sts_size);
sts_ptr = dma_zalloc_coherent(dev,
sts_size * sizeof(struct tsi721_dma_sts),
@@ -94,7 +112,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
if (!sts_ptr) {
/* Free space allocated for DMA descriptors */
dma_free_coherent(dev,
- bd_num * sizeof(struct tsi721_dma_desc),
+ (bd_num + 1) * sizeof(struct tsi721_dma_desc),
bd_ptr, bd_phys);
bdma_chan->bd_base = NULL;
return -ENOMEM;
@@ -108,11 +126,11 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
"desc status FIFO @ %p (phys = %llx) size=0x%x\n",
sts_ptr, (unsigned long long)sts_phys, sts_size);
- /* Initialize DMA descriptors ring */
- bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29);
- bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys &
+ /* Initialize DMA descriptors ring using added link descriptor */
+ bd_ptr[bd_num].type_id = cpu_to_le32(DTYPE3 << 29);
+ bd_ptr[bd_num].next_lo = cpu_to_le32((u64)bd_phys &
TSI721_DMAC_DPTRL_MASK);
- bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32);
+ bd_ptr[bd_num].next_hi = cpu_to_le32((u64)bd_phys >> 32);
/* Setup DMA descriptor pointers */
iowrite32(((u64)bd_phys >> 32),
@@ -134,6 +152,55 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
ioread32(bdma_chan->regs + TSI721_DMAC_INT);
+#ifdef CONFIG_PCI_MSI
+ /* Request interrupt service if we are in MSI-X mode */
+ if (priv->flags & TSI721_USING_MSIX) {
+ int rc, idx;
+
+ idx = TSI721_VECT_DMA0_DONE + bdma_chan->id;
+
+ rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0,
+ priv->msix[idx].irq_name, (void *)bdma_chan);
+
+ if (rc) {
+ dev_dbg(dev, "Unable to get MSI-X for BDMA%d-DONE\n",
+ bdma_chan->id);
+ goto err_out;
+ }
+
+ idx = TSI721_VECT_DMA0_INT + bdma_chan->id;
+
+ rc = request_irq(priv->msix[idx].vector, tsi721_bdma_msix, 0,
+ priv->msix[idx].irq_name, (void *)bdma_chan);
+
+ if (rc) {
+ dev_dbg(dev, "Unable to get MSI-X for BDMA%d-INT\n",
+ bdma_chan->id);
+ free_irq(
+ priv->msix[TSI721_VECT_DMA0_DONE +
+ bdma_chan->id].vector,
+ (void *)bdma_chan);
+ }
+
+err_out:
+ if (rc) {
+ /* Free space allocated for DMA descriptors */
+ dma_free_coherent(dev,
+ (bd_num + 1) * sizeof(struct tsi721_dma_desc),
+ bd_ptr, bd_phys);
+ bdma_chan->bd_base = NULL;
+
+ /* Free space allocated for status descriptors */
+ dma_free_coherent(dev,
+ sts_size * sizeof(struct tsi721_dma_sts),
+ sts_ptr, sts_phys);
+ bdma_chan->sts_base = NULL;
+
+ return -EIO;
+ }
+ }
+#endif /* CONFIG_PCI_MSI */
+
/* Toggle DMA channel initialization */
iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL);
ioread32(bdma_chan->regs + TSI721_DMAC_CTL);
@@ -147,6 +214,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan)
static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan)
{
u32 ch_stat;
+#ifdef CONFIG_PCI_MSI
+ struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
+#endif
if (bdma_chan->bd_base == NULL)
return 0;
@@ -159,9 +229,18 @@ static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan)
/* Put DMA channel into init state */
iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL);
+#ifdef CONFIG_PCI_MSI
+ if (priv->flags & TSI721_USING_MSIX) {
+ free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
+ bdma_chan->id].vector, (void *)bdma_chan);
+ free_irq(priv->msix[TSI721_VECT_DMA0_INT +
+ bdma_chan->id].vector, (void *)bdma_chan);
+ }
+#endif /* CONFIG_PCI_MSI */
+
/* Free space allocated for DMA descriptors */
dma_free_coherent(bdma_chan->dchan.device->dev,
- bdma_chan->bd_num * sizeof(struct tsi721_dma_desc),
+ (bdma_chan->bd_num + 1) * sizeof(struct tsi721_dma_desc),
bdma_chan->bd_base, bdma_chan->bd_phys);
bdma_chan->bd_base = NULL;
@@ -243,8 +322,8 @@ static void tsi721_start_dma(struct tsi721_bdma_chan *bdma_chan)
}
dev_dbg(bdma_chan->dchan.device->dev,
- "tx_chan: %p, chan: %d, regs: %p\n",
- bdma_chan, bdma_chan->dchan.chan_id, bdma_chan->regs);
+ "%s: chan_%d (wrc=%d)\n", __func__, bdma_chan->id,
+ bdma_chan->wr_count_next);
iowrite32(bdma_chan->wr_count_next,
bdma_chan->regs + TSI721_DMAC_DWRCNT);
@@ -253,72 +332,19 @@ static void tsi721_start_dma(struct tsi721_bdma_chan *bdma_chan)
bdma_chan->wr_count = bdma_chan->wr_count_next;
}
-static void tsi721_desc_put(struct tsi721_bdma_chan *bdma_chan,
- struct tsi721_tx_desc *desc)
-{
- dev_dbg(bdma_chan->dchan.device->dev,
- "Put desc: %p into free list\n", desc);
-
- if (desc) {
- spin_lock_bh(&bdma_chan->lock);
- list_splice_init(&desc->tx_list, &bdma_chan->free_list);
- list_add(&desc->desc_node, &bdma_chan->free_list);
- bdma_chan->wr_count_next = bdma_chan->wr_count;
- spin_unlock_bh(&bdma_chan->lock);
- }
-}
-
-static
-struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan)
-{
- struct tsi721_tx_desc *tx_desc, *_tx_desc;
- struct tsi721_tx_desc *ret = NULL;
- int i;
-
- spin_lock_bh(&bdma_chan->lock);
- list_for_each_entry_safe(tx_desc, _tx_desc,
- &bdma_chan->free_list, desc_node) {
- if (async_tx_test_ack(&tx_desc->txd)) {
- list_del(&tx_desc->desc_node);
- ret = tx_desc;
- break;
- }
- dev_dbg(bdma_chan->dchan.device->dev,
- "desc %p not ACKed\n", tx_desc);
- }
-
- if (ret == NULL) {
- dev_dbg(bdma_chan->dchan.device->dev,
- "%s: unable to obtain tx descriptor\n", __func__);
- goto err_out;
- }
-
- i = bdma_chan->wr_count_next % bdma_chan->bd_num;
- if (i == bdma_chan->bd_num - 1) {
- i = 0;
- bdma_chan->wr_count_next++; /* skip link descriptor */
- }
-
- bdma_chan->wr_count_next++;
- tx_desc->txd.phys = bdma_chan->bd_phys +
- i * sizeof(struct tsi721_dma_desc);
- tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i];
-err_out:
- spin_unlock_bh(&bdma_chan->lock);
-
- return ret;
-}
-
static int
-tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg,
- enum dma_rtype rtype, u32 sys_size)
+tsi721_desc_fill_init(struct tsi721_tx_desc *desc,
+ struct tsi721_dma_desc *bd_ptr,
+ struct scatterlist *sg, u32 sys_size)
{
- struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
u64 rio_addr;
+ if (bd_ptr == NULL)
+ return -EINVAL;
+
/* Initialize DMA descriptor */
bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) |
- (rtype << 19) | desc->destid);
+ (desc->rtype << 19) | desc->destid);
bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) |
(sys_size << 26));
rio_addr = (desc->rio_addr >> 2) |
@@ -335,51 +361,32 @@ tsi721_desc_fill_init(struct tsi721_tx_desc *desc, struct scatterlist *sg,
}
static int
-tsi721_desc_fill_end(struct tsi721_tx_desc *desc)
+tsi721_desc_fill_end(struct tsi721_dma_desc *bd_ptr, u32 bcount, bool interrupt)
{
- struct tsi721_dma_desc *bd_ptr = desc->hw_desc;
+ if (bd_ptr == NULL)
+ return -EINVAL;
/* Update DMA descriptor */
- if (desc->interrupt)
+ if (interrupt)
bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF);
- bd_ptr->bcount |= cpu_to_le32(desc->bcount & TSI721_DMAD_BCOUNT1);
+ bd_ptr->bcount |= cpu_to_le32(bcount & TSI721_DMAD_BCOUNT1);
return 0;
}
-
-static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan,
- struct tsi721_tx_desc *desc)
+static void tsi721_dma_tx_err(struct tsi721_bdma_chan *bdma_chan,
+ struct tsi721_tx_desc *desc)
{
struct dma_async_tx_descriptor *txd = &desc->txd;
dma_async_tx_callback callback = txd->callback;
void *param = txd->callback_param;
- list_splice_init(&desc->tx_list, &bdma_chan->free_list);
list_move(&desc->desc_node, &bdma_chan->free_list);
- bdma_chan->completed_cookie = txd->cookie;
if (callback)
callback(param);
}
-static void tsi721_dma_complete_all(struct tsi721_bdma_chan *bdma_chan)
-{
- struct tsi721_tx_desc *desc, *_d;
- LIST_HEAD(list);
-
- BUG_ON(!tsi721_dma_is_idle(bdma_chan));
-
- if (!list_empty(&bdma_chan->queue))
- tsi721_start_dma(bdma_chan);
-
- list_splice_init(&bdma_chan->active_list, &list);
- list_splice_init(&bdma_chan->queue, &bdma_chan->active_list);
-
- list_for_each_entry_safe(desc, _d, &list, desc_node)
- tsi721_dma_chain_complete(bdma_chan, desc);
-}
-
static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan)
{
u32 srd_ptr;
@@ -403,20 +410,159 @@ static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan)
bdma_chan->sts_rdptr = srd_ptr;
}
+/* Must be called with the channel spinlock held */
+static int tsi721_submit_sg(struct tsi721_tx_desc *desc)
+{
+ struct dma_chan *dchan = desc->txd.chan;
+ struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
+ u32 sys_size;
+ u64 rio_addr;
+ dma_addr_t next_addr;
+ u32 bcount;
+ struct scatterlist *sg;
+ unsigned int i;
+ int err = 0;
+ struct tsi721_dma_desc *bd_ptr = NULL;
+ u32 idx, rd_idx;
+ u32 add_count = 0;
+
+ if (!tsi721_dma_is_idle(bdma_chan)) {
+ dev_err(bdma_chan->dchan.device->dev,
+ "BUG: Attempt to use non-idle channel\n");
+ return -EIO;
+ }
+
+ /*
+ * Fill DMA channel's hardware buffer descriptors.
+ * (NOTE: RapidIO destination address is limited to 64 bits for now)
+ */
+ rio_addr = desc->rio_addr;
+ next_addr = -1;
+ bcount = 0;
+ sys_size = dma_to_mport(bdma_chan->dchan.device)->sys_size;
+
+ rd_idx = ioread32(bdma_chan->regs + TSI721_DMAC_DRDCNT);
+ rd_idx %= (bdma_chan->bd_num + 1);
+
+ idx = bdma_chan->wr_count_next % (bdma_chan->bd_num + 1);
+ if (idx == bdma_chan->bd_num) {
+ /* wrap around link descriptor */
+ idx = 0;
+ add_count++;
+ }
+
+ dev_dbg(dchan->device->dev, "%s: BD ring status: rdi=%d wri=%d\n",
+ __func__, rd_idx, idx);
+
+ for_each_sg(desc->sg, sg, desc->sg_len, i) {
+
+ dev_dbg(dchan->device->dev, "sg%d/%d addr: 0x%llx len: %d\n",
+ i, desc->sg_len,
+ (unsigned long long)sg_dma_address(sg), sg_dma_len(sg));
+
+ if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) {
+ dev_err(dchan->device->dev,
+ "%s: SG entry %d is too large\n", __func__, i);
+ err = -EINVAL;
+ break;
+ }
+
+ /*
+ * If this sg entry forms contiguous block with previous one,
+ * try to merge it into existing DMA descriptor
+ */
+ if (next_addr == sg_dma_address(sg) &&
+ bcount + sg_dma_len(sg) <= TSI721_BDMA_MAX_BCOUNT) {
+ /* Adjust byte count of the descriptor */
+ bcount += sg_dma_len(sg);
+ goto entry_done;
+ } else if (next_addr != -1) {
+ /* Finalize descriptor using total byte count value */
+ tsi721_desc_fill_end(bd_ptr, bcount, 0);
+ dev_dbg(dchan->device->dev,
+ "%s: prev desc final len: %d\n",
+ __func__, bcount);
+ }
+
+ desc->rio_addr = rio_addr;
+
+ if (i && idx == rd_idx) {
+ dev_dbg(dchan->device->dev,
+ "%s: HW descriptor ring is full @ %d\n",
+ __func__, i);
+ desc->sg = sg;
+ desc->sg_len -= i;
+ break;
+ }
+
+ bd_ptr = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[idx];
+ err = tsi721_desc_fill_init(desc, bd_ptr, sg, sys_size);
+ if (err) {
+ dev_err(dchan->device->dev,
+ "Failed to build desc: err=%d\n", err);
+ break;
+ }
+
+ dev_dbg(dchan->device->dev, "bd_ptr = %p did=%d raddr=0x%llx\n",
+ bd_ptr, desc->destid, desc->rio_addr);
+
+ next_addr = sg_dma_address(sg);
+ bcount = sg_dma_len(sg);
+
+ add_count++;
+ if (++idx == bdma_chan->bd_num) {
+ /* wrap around link descriptor */
+ idx = 0;
+ add_count++;
+ }
+
+entry_done:
+ if (sg_is_last(sg)) {
+ tsi721_desc_fill_end(bd_ptr, bcount, 0);
+ dev_dbg(dchan->device->dev, "%s: last desc final len: %d\n",
+ __func__, bcount);
+ desc->sg_len = 0;
+ } else {
+ rio_addr += sg_dma_len(sg);
+ next_addr += sg_dma_len(sg);
+ }
+ }
+
+ if (!err)
+ bdma_chan->wr_count_next += add_count;
+
+ return err;
+}
+
static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan)
{
- if (list_empty(&bdma_chan->active_list) ||
- list_is_singular(&bdma_chan->active_list)) {
- dev_dbg(bdma_chan->dchan.device->dev,
- "%s: Active_list empty\n", __func__);
- tsi721_dma_complete_all(bdma_chan);
- } else {
- dev_dbg(bdma_chan->dchan.device->dev,
- "%s: Active_list NOT empty\n", __func__);
- tsi721_dma_chain_complete(bdma_chan,
- tsi721_dma_first_active(bdma_chan));
- tsi721_start_dma(bdma_chan);
+ struct tsi721_tx_desc *desc;
+ int err;
+
+ dev_dbg(bdma_chan->dchan.device->dev, "%s: Enter\n", __func__);
+
+ /*
+ * If there are any new transactions in the queue add them
+ * into the processing list
+ */
+ if (!list_empty(&bdma_chan->queue))
+ list_splice_init(&bdma_chan->queue, &bdma_chan->active_list);
+
+ /* Start new transaction (if available) */
+ if (!list_empty(&bdma_chan->active_list)) {
+ desc = tsi721_dma_first_active(bdma_chan);
+ err = tsi721_submit_sg(desc);
+ if (!err)
+ tsi721_start_dma(bdma_chan);
+ else {
+ tsi721_dma_tx_err(bdma_chan, desc);
+ dev_dbg(bdma_chan->dchan.device->dev,
+ "ERR: tsi721_submit_sg failed with err=%d\n",
+ err);
+ }
}
+
+ dev_dbg(bdma_chan->dchan.device->dev, "%s: Exit\n", __func__);
}
static void tsi721_dma_tasklet(unsigned long data)
@@ -444,8 +590,29 @@ static void tsi721_dma_tasklet(unsigned long data)
}
if (dmac_int & (TSI721_DMAC_INT_DONE | TSI721_DMAC_INT_IOFDONE)) {
+ struct tsi721_tx_desc *desc;
+
tsi721_clr_stat(bdma_chan);
spin_lock(&bdma_chan->lock);
+ desc = tsi721_dma_first_active(bdma_chan);
+
+ if (desc->sg_len == 0) {
+ dma_async_tx_callback callback = NULL;
+ void *param = NULL;
+
+ desc->status = DMA_COMPLETE;
+ dma_cookie_complete(&desc->txd);
+ if (desc->txd.flags & DMA_PREP_INTERRUPT) {
+ callback = desc->txd.callback;
+ param = desc->txd.callback_param;
+ }
+ list_move(&desc->desc_node, &bdma_chan->free_list);
+ spin_unlock(&bdma_chan->lock);
+ if (callback)
+ callback(param);
+ spin_lock(&bdma_chan->lock);
+ }
+
tsi721_advance_work(bdma_chan);
spin_unlock(&bdma_chan->lock);
}
@@ -460,21 +627,24 @@ static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd)
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(txd->chan);
dma_cookie_t cookie;
- spin_lock_bh(&bdma_chan->lock);
+ /* Check if the descriptor is detached from any lists */
+ if (!list_empty(&desc->desc_node)) {
+ dev_err(bdma_chan->dchan.device->dev,
+ "%s: wrong state of descriptor %p\n", __func__, txd);
+ return -EIO;
+ }
- cookie = txd->chan->cookie;
- if (++cookie < 0)
- cookie = 1;
- txd->chan->cookie = cookie;
- txd->cookie = cookie;
+ spin_lock_bh(&bdma_chan->lock);
- if (list_empty(&bdma_chan->active_list)) {
- list_add_tail(&desc->desc_node, &bdma_chan->active_list);
- tsi721_start_dma(bdma_chan);
- } else {
- list_add_tail(&desc->desc_node, &bdma_chan->queue);
+ if (!bdma_chan->active) {
+ spin_unlock_bh(&bdma_chan->lock);
+ return -ENODEV;
}
+ cookie = dma_cookie_assign(txd);
+ desc->status = DMA_IN_PROGRESS;
+ list_add_tail(&desc->desc_node, &bdma_chan->queue);
+
spin_unlock_bh(&bdma_chan->lock);
return cookie;
}
@@ -482,115 +652,52 @@ static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd)
static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
{
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-#ifdef CONFIG_PCI_MSI
- struct tsi721_device *priv = to_tsi721(dchan->device);
-#endif
struct tsi721_tx_desc *desc = NULL;
- LIST_HEAD(tmp_list);
int i;
- int rc;
+
+ dev_dbg(dchan->device->dev, "%s: for channel %d\n",
+ __func__, bdma_chan->id);
if (bdma_chan->bd_base)
- return bdma_chan->bd_num - 1;
+ return TSI721_DMA_TX_QUEUE_SZ;
/* Initialize BDMA channel */
- if (tsi721_bdma_ch_init(bdma_chan)) {
+ if (tsi721_bdma_ch_init(bdma_chan, dma_desc_per_channel)) {
dev_err(dchan->device->dev, "Unable to initialize data DMA"
" channel %d, aborting\n", bdma_chan->id);
- return -ENOMEM;
+ return -ENODEV;
}
- /* Alocate matching number of logical descriptors */
- desc = kcalloc((bdma_chan->bd_num - 1), sizeof(struct tsi721_tx_desc),
+ /* Allocate queue of transaction descriptors */
+ desc = kcalloc(TSI721_DMA_TX_QUEUE_SZ, sizeof(struct tsi721_tx_desc),
GFP_KERNEL);
if (!desc) {
dev_err(dchan->device->dev,
"Failed to allocate logical descriptors\n");
- rc = -ENOMEM;
- goto err_out;
+ tsi721_bdma_ch_free(bdma_chan);
+ return -ENOMEM;
}
bdma_chan->tx_desc = desc;
- for (i = 0; i < bdma_chan->bd_num - 1; i++) {
+ for (i = 0; i < TSI721_DMA_TX_QUEUE_SZ; i++) {
dma_async_tx_descriptor_init(&desc[i].txd, dchan);
desc[i].txd.tx_submit = tsi721_tx_submit;
desc[i].txd.flags = DMA_CTRL_ACK;
- INIT_LIST_HEAD(&desc[i].tx_list);
- list_add_tail(&desc[i].desc_node, &tmp_list);
+ list_add(&desc[i].desc_node, &bdma_chan->free_list);
}
- spin_lock_bh(&bdma_chan->lock);
- list_splice(&tmp_list, &bdma_chan->free_list);
- bdma_chan->completed_cookie = dchan->cookie = 1;
- spin_unlock_bh(&bdma_chan->lock);
-
-#ifdef CONFIG_PCI_MSI
- if (priv->flags & TSI721_USING_MSIX) {
- /* Request interrupt service if we are in MSI-X mode */
- rc = request_irq(
- priv->msix[TSI721_VECT_DMA0_DONE +
- bdma_chan->id].vector,
- tsi721_bdma_msix, 0,
- priv->msix[TSI721_VECT_DMA0_DONE +
- bdma_chan->id].irq_name,
- (void *)bdma_chan);
-
- if (rc) {
- dev_dbg(dchan->device->dev,
- "Unable to allocate MSI-X interrupt for "
- "BDMA%d-DONE\n", bdma_chan->id);
- goto err_out;
- }
-
- rc = request_irq(priv->msix[TSI721_VECT_DMA0_INT +
- bdma_chan->id].vector,
- tsi721_bdma_msix, 0,
- priv->msix[TSI721_VECT_DMA0_INT +
- bdma_chan->id].irq_name,
- (void *)bdma_chan);
-
- if (rc) {
- dev_dbg(dchan->device->dev,
- "Unable to allocate MSI-X interrupt for "
- "BDMA%d-INT\n", bdma_chan->id);
- free_irq(
- priv->msix[TSI721_VECT_DMA0_DONE +
- bdma_chan->id].vector,
- (void *)bdma_chan);
- rc = -EIO;
- goto err_out;
- }
- }
-#endif /* CONFIG_PCI_MSI */
+ dma_cookie_init(dchan);
bdma_chan->active = true;
tsi721_bdma_interrupt_enable(bdma_chan, 1);
- return bdma_chan->bd_num - 1;
-
-err_out:
- kfree(desc);
- tsi721_bdma_ch_free(bdma_chan);
- return rc;
+ return TSI721_DMA_TX_QUEUE_SZ;
}
-static void tsi721_free_chan_resources(struct dma_chan *dchan)
+static void tsi721_sync_dma_irq(struct tsi721_bdma_chan *bdma_chan)
{
- struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
- struct tsi721_device *priv = to_tsi721(dchan->device);
- LIST_HEAD(list);
-
- dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
-
- if (bdma_chan->bd_base == NULL)
- return;
-
- BUG_ON(!list_empty(&bdma_chan->active_list));
- BUG_ON(!list_empty(&bdma_chan->queue));
-
- tsi721_bdma_interrupt_enable(bdma_chan, 0);
- bdma_chan->active = false;
+ struct tsi721_device *priv = to_tsi721(bdma_chan->dchan.device);
#ifdef CONFIG_PCI_MSI
if (priv->flags & TSI721_USING_MSIX) {
@@ -601,64 +708,48 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan)
} else
#endif
synchronize_irq(priv->pdev->irq);
+}
- tasklet_kill(&bdma_chan->tasklet);
+static void tsi721_free_chan_resources(struct dma_chan *dchan)
+{
+ struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
- spin_lock_bh(&bdma_chan->lock);
- list_splice_init(&bdma_chan->free_list, &list);
- spin_unlock_bh(&bdma_chan->lock);
+ dev_dbg(dchan->device->dev, "%s: for channel %d\n",
+ __func__, bdma_chan->id);
-#ifdef CONFIG_PCI_MSI
- if (priv->flags & TSI721_USING_MSIX) {
- free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
- bdma_chan->id].vector, (void *)bdma_chan);
- free_irq(priv->msix[TSI721_VECT_DMA0_INT +
- bdma_chan->id].vector, (void *)bdma_chan);
- }
-#endif /* CONFIG_PCI_MSI */
+ if (bdma_chan->bd_base == NULL)
+ return;
- tsi721_bdma_ch_free(bdma_chan);
+ BUG_ON(!list_empty(&bdma_chan->active_list));
+ BUG_ON(!list_empty(&bdma_chan->queue));
+
+ tsi721_bdma_interrupt_enable(bdma_chan, 0);
+ bdma_chan->active = false;
+ tsi721_sync_dma_irq(bdma_chan);
+ tasklet_kill(&bdma_chan->tasklet);
+ INIT_LIST_HEAD(&bdma_chan->free_list);
kfree(bdma_chan->tx_desc);
+ tsi721_bdma_ch_free(bdma_chan);
}
static
enum dma_status tsi721_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
- struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
- dma_cookie_t last_used;
- dma_cookie_t last_completed;
- int ret;
-
- spin_lock_bh(&bdma_chan->lock);
- last_completed = bdma_chan->completed_cookie;
- last_used = dchan->cookie;
- spin_unlock_bh(&bdma_chan->lock);
-
- ret = dma_async_is_complete(cookie, last_completed, last_used);
-
- dma_set_tx_state(txstate, last_completed, last_used, 0);
-
- dev_dbg(dchan->device->dev,
- "%s: exit, ret: %d, last_completed: %d, last_used: %d\n",
- __func__, ret, last_completed, last_used);
-
- return ret;
+ return dma_cookie_status(dchan, cookie, txstate);
}
static void tsi721_issue_pending(struct dma_chan *dchan)
{
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
- dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
+ dev_dbg(dchan->device->dev, "%s: Enter\n", __func__);
- if (tsi721_dma_is_idle(bdma_chan)) {
+ if (tsi721_dma_is_idle(bdma_chan) && bdma_chan->active) {
spin_lock_bh(&bdma_chan->lock);
tsi721_advance_work(bdma_chan);
spin_unlock_bh(&bdma_chan->lock);
- } else
- dev_dbg(dchan->device->dev,
- "%s: DMA channel still busy\n", __func__);
+ }
}
static
@@ -668,21 +759,19 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan,
void *tinfo)
{
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
- struct tsi721_tx_desc *desc = NULL;
- struct tsi721_tx_desc *first = NULL;
- struct scatterlist *sg;
+ struct tsi721_tx_desc *desc, *_d;
struct rio_dma_ext *rext = tinfo;
- u64 rio_addr = rext->rio_addr; /* limited to 64-bit rio_addr for now */
- unsigned int i;
- u32 sys_size = dma_to_mport(dchan->device)->sys_size;
enum dma_rtype rtype;
- dma_addr_t next_addr = -1;
+ struct dma_async_tx_descriptor *txd = NULL;
if (!sgl || !sg_len) {
dev_err(dchan->device->dev, "%s: No SG list\n", __func__);
return NULL;
}
+ dev_dbg(dchan->device->dev, "%s: %s\n", __func__,
+ (dir == DMA_DEV_TO_MEM)?"READ":"WRITE");
+
if (dir == DMA_DEV_TO_MEM)
rtype = NREAD;
else if (dir == DMA_MEM_TO_DEV) {
@@ -704,97 +793,26 @@ struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan,
return NULL;
}
- for_each_sg(sgl, sg, sg_len, i) {
- int err;
-
- if (sg_dma_len(sg) > TSI721_BDMA_MAX_BCOUNT) {
- dev_err(dchan->device->dev,
- "%s: SG entry %d is too large\n", __func__, i);
- goto err_desc_put;
- }
-
- /*
- * If this sg entry forms contiguous block with previous one,
- * try to merge it into existing DMA descriptor
- */
- if (desc) {
- if (next_addr == sg_dma_address(sg) &&
- desc->bcount + sg_dma_len(sg) <=
- TSI721_BDMA_MAX_BCOUNT) {
- /* Adjust byte count of the descriptor */
- desc->bcount += sg_dma_len(sg);
- goto entry_done;
- }
-
- /*
- * Finalize this descriptor using total
- * byte count value.
- */
- tsi721_desc_fill_end(desc);
- dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
- __func__, desc->bcount);
- }
-
- /*
- * Obtain and initialize a new descriptor
- */
- desc = tsi721_desc_get(bdma_chan);
- if (!desc) {
- dev_err(dchan->device->dev,
- "%s: Failed to get new descriptor for SG %d\n",
- __func__, i);
- goto err_desc_put;
- }
-
- desc->destid = rext->destid;
- desc->rio_addr = rio_addr;
- desc->rio_addr_u = 0;
- desc->bcount = sg_dma_len(sg);
-
- dev_dbg(dchan->device->dev,
- "sg%d desc: 0x%llx, addr: 0x%llx len: %d\n",
- i, (u64)desc->txd.phys,
- (unsigned long long)sg_dma_address(sg),
- sg_dma_len(sg));
-
- dev_dbg(dchan->device->dev,
- "bd_ptr = %p did=%d raddr=0x%llx\n",
- desc->hw_desc, desc->destid, desc->rio_addr);
-
- err = tsi721_desc_fill_init(desc, sg, rtype, sys_size);
- if (err) {
- dev_err(dchan->device->dev,
- "Failed to build desc: %d\n", err);
- goto err_desc_put;
- }
-
- next_addr = sg_dma_address(sg);
-
- if (!first)
- first = desc;
- else
- list_add_tail(&desc->desc_node, &first->tx_list);
+ spin_lock_bh(&bdma_chan->lock);
-entry_done:
- if (sg_is_last(sg)) {
- desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0;
- tsi721_desc_fill_end(desc);
- dev_dbg(dchan->device->dev, "%s: desc final len: %d\n",
- __func__, desc->bcount);
- } else {
- rio_addr += sg_dma_len(sg);
- next_addr += sg_dma_len(sg);
+ list_for_each_entry_safe(desc, _d, &bdma_chan->free_list, desc_node) {
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del_init(&desc->desc_node);
+ desc->destid = rext->destid;
+ desc->rio_addr = rext->rio_addr;
+ desc->rio_addr_u = 0;
+ desc->rtype = rtype;
+ desc->sg_len = sg_len;
+ desc->sg = sgl;
+ txd = &desc->txd;
+ txd->flags = flags;
+ break;
}
}
- first->txd.cookie = -EBUSY;
- desc->txd.flags = flags;
-
- return &first->txd;
+ spin_unlock_bh(&bdma_chan->lock);
-err_desc_put:
- tsi721_desc_put(bdma_chan, first);
- return NULL;
+ return txd;
}
static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
@@ -802,23 +820,34 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
{
struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
struct tsi721_tx_desc *desc, *_d;
+ u32 dmac_int;
LIST_HEAD(list);
dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
if (cmd != DMA_TERMINATE_ALL)
- return -ENXIO;
+ return -ENOSYS;
spin_lock_bh(&bdma_chan->lock);
- /* make sure to stop the transfer */
- iowrite32(TSI721_DMAC_CTL_SUSP, bdma_chan->regs + TSI721_DMAC_CTL);
+ bdma_chan->active = false;
+
+ if (!tsi721_dma_is_idle(bdma_chan)) {
+ /* make sure to stop the transfer */
+ iowrite32(TSI721_DMAC_CTL_SUSP,
+ bdma_chan->regs + TSI721_DMAC_CTL);
+
+ /* Wait until DMA channel stops */
+ do {
+ dmac_int = ioread32(bdma_chan->regs + TSI721_DMAC_INT);
+ } while ((dmac_int & TSI721_DMAC_INT_SUSP) == 0);
+ }
list_splice_init(&bdma_chan->active_list, &list);
list_splice_init(&bdma_chan->queue, &list);
list_for_each_entry_safe(desc, _d, &list, desc_node)
- tsi721_dma_chain_complete(bdma_chan, desc);
+ tsi721_dma_tx_err(bdma_chan, desc);
spin_unlock_bh(&bdma_chan->lock);
@@ -828,22 +857,18 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
int tsi721_register_dma(struct tsi721_device *priv)
{
int i;
- int nr_channels = TSI721_DMA_MAXCH;
+ int nr_channels = 0;
int err;
struct rio_mport *mport = priv->mport;
- mport->dma.dev = &priv->pdev->dev;
- mport->dma.chancnt = nr_channels;
-
INIT_LIST_HEAD(&mport->dma.channels);
- for (i = 0; i < nr_channels; i++) {
+ for (i = 0; i < TSI721_DMA_MAXCH; i++) {
struct tsi721_bdma_chan *bdma_chan = &priv->bdma[i];
if (i == TSI721_DMACH_MAINT)
continue;
- bdma_chan->bd_num = TSI721_BDMA_BD_RING_SZ;
bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i);
bdma_chan->dchan.device = &mport->dma;
@@ -862,12 +887,15 @@ int tsi721_register_dma(struct tsi721_device *priv)
(unsigned long)bdma_chan);
list_add_tail(&bdma_chan->dchan.device_node,
&mport->dma.channels);
+ nr_channels++;
}
+ mport->dma.chancnt = nr_channels;
dma_cap_zero(mport->dma.cap_mask);
dma_cap_set(DMA_PRIVATE, mport->dma.cap_mask);
dma_cap_set(DMA_SLAVE, mport->dma.cap_mask);
+ mport->dma.dev = &priv->pdev->dev;
mport->dma.device_alloc_chan_resources = tsi721_alloc_chan_resources;
mport->dma.device_free_chan_resources = tsi721_free_chan_resources;
mport->dma.device_tx_status = tsi721_tx_status;
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index a54ba0494dd3..d7b87c64b7cd 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1509,30 +1509,39 @@ EXPORT_SYMBOL_GPL(rio_route_clr_table);
static bool rio_chan_filter(struct dma_chan *chan, void *arg)
{
- struct rio_dev *rdev = arg;
+ struct rio_mport *mport = arg;
/* Check that DMA device belongs to the right MPORT */
- return (rdev->net->hport ==
- container_of(chan->device, struct rio_mport, dma));
+ return mport == container_of(chan->device, struct rio_mport, dma);
}
/**
- * rio_request_dma - request RapidIO capable DMA channel that supports
- * specified target RapidIO device.
- * @rdev: RIO device control structure
+ * rio_request_mport_dma - request RapidIO capable DMA channel associated
+ * with specified local RapidIO mport device.
+ * @mport: RIO mport to perform DMA data transfers
*
* Returns pointer to allocated DMA channel or NULL if failed.
*/
-struct dma_chan *rio_request_dma(struct rio_dev *rdev)
+struct dma_chan *rio_request_mport_dma(struct rio_mport *mport)
{
dma_cap_mask_t mask;
- struct dma_chan *dchan;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- dchan = dma_request_channel(mask, rio_chan_filter, rdev);
+ return dma_request_channel(mask, rio_chan_filter, mport);
+}
+EXPORT_SYMBOL_GPL(rio_request_mport_dma);
- return dchan;
+/**
+ * rio_request_dma - request RapidIO capable DMA channel that supports
+ * specified target RapidIO device.
+ * @rdev: RIO device associated with DMA transfer
+ *
+ * Returns pointer to allocated DMA channel or NULL if failed.
+ */
+struct dma_chan *rio_request_dma(struct rio_dev *rdev)
+{
+ return rio_request_mport_dma(rdev->net->hport);
}
EXPORT_SYMBOL_GPL(rio_request_dma);
@@ -1547,10 +1556,10 @@ void rio_release_dma(struct dma_chan *dchan)
EXPORT_SYMBOL_GPL(rio_release_dma);
/**
- * rio_dma_prep_slave_sg - RapidIO specific wrapper
+ * rio_dma_prep_xfer - RapidIO specific wrapper
* for device_prep_slave_sg callback defined by DMAENGINE.
- * @rdev: RIO device control structure
* @dchan: DMA channel to configure
+ * @destid: target RapidIO device destination ID
* @data: RIO specific data descriptor
* @direction: DMA data transfer direction (TO or FROM the device)
* @flags: dmaengine defined flags
@@ -1560,11 +1569,10 @@ EXPORT_SYMBOL_GPL(rio_release_dma);
* target RIO device.
* Returns pointer to DMA transaction descriptor or NULL if failed.
*/
-struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
- struct dma_chan *dchan, struct rio_dma_data *data,
+struct dma_async_tx_descriptor *rio_dma_prep_xfer(struct dma_chan *dchan,
+ u16 destid, struct rio_dma_data *data,
enum dma_transfer_direction direction, unsigned long flags)
{
- struct dma_async_tx_descriptor *txd = NULL;
struct rio_dma_ext rio_ext;
if (dchan->device->device_prep_slave_sg == NULL) {
@@ -1572,15 +1580,35 @@ struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
return NULL;
}
- rio_ext.destid = rdev->destid;
+ rio_ext.destid = destid;
rio_ext.rio_addr_u = data->rio_addr_u;
rio_ext.rio_addr = data->rio_addr;
rio_ext.wr_type = data->wr_type;
- txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len,
- direction, flags, &rio_ext);
+ return dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len,
+ direction, flags, &rio_ext);
+}
+EXPORT_SYMBOL_GPL(rio_dma_prep_xfer);
- return txd;
+/**
+ * rio_dma_prep_slave_sg - RapidIO specific wrapper
+ * for device_prep_slave_sg callback defined by DMAENGINE.
+ * @rdev: RIO device control structure
+ * @dchan: DMA channel to configure
+ * @data: RIO specific data descriptor
+ * @direction: DMA data transfer direction (TO or FROM the device)
+ * @flags: dmaengine defined flags
+ *
+ * Initializes RapidIO capable DMA channel for the specified data transfer.
+ * Uses DMA channel private extension to pass information related to remote
+ * target RIO device.
+ * Returns pointer to DMA transaction descriptor or NULL if failed.
+ */
+struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev,
+ struct dma_chan *dchan, struct rio_dma_data *data,
+ enum dma_transfer_direction direction, unsigned long flags)
+{
+ return rio_dma_prep_xfer(dchan, rdev->destid, data, direction, flags);
}
EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);
diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig
new file mode 100644
index 000000000000..f9da613052c2
--- /dev/null
+++ b/drivers/ras/Kconfig
@@ -0,0 +1,2 @@
+config RAS
+ bool
diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile
new file mode 100644
index 000000000000..d7f73341ced3
--- /dev/null
+++ b/drivers/ras/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RAS) += ras.o debugfs.o
diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c
new file mode 100644
index 000000000000..0322acf67ea5
--- /dev/null
+++ b/drivers/ras/debugfs.c
@@ -0,0 +1,56 @@
+#include <linux/debugfs.h>
+
+static struct dentry *ras_debugfs_dir;
+
+static atomic_t trace_count = ATOMIC_INIT(0);
+
+int ras_userspace_consumers(void)
+{
+ return atomic_read(&trace_count);
+}
+EXPORT_SYMBOL_GPL(ras_userspace_consumers);
+
+static int trace_show(struct seq_file *m, void *v)
+{
+ return atomic_read(&trace_count);
+}
+
+static int trace_open(struct inode *inode, struct file *file)
+{
+ atomic_inc(&trace_count);
+ return single_open(file, trace_show, NULL);
+}
+
+static int trace_release(struct inode *inode, struct file *file)
+{
+ atomic_dec(&trace_count);
+ return single_release(inode, file);
+}
+
+static const struct file_operations trace_fops = {
+ .open = trace_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = trace_release,
+};
+
+int __init ras_add_daemon_trace(void)
+{
+ struct dentry *fentry;
+
+ if (!ras_debugfs_dir)
+ return -ENOENT;
+
+ fentry = debugfs_create_file("daemon_active", S_IRUSR, ras_debugfs_dir,
+ NULL, &trace_fops);
+ if (!fentry)
+ return -ENODEV;
+
+ return 0;
+
+}
+
+void __init ras_debugfs_init(void)
+{
+ ras_debugfs_dir = debugfs_create_dir("ras", NULL);
+}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
new file mode 100644
index 000000000000..b67dd362b7b6
--- /dev/null
+++ b/drivers/ras/ras.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Authors:
+ * Chen, Gong <gong.chen@linux.intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/ras.h>
+
+#define CREATE_TRACE_POINTS
+#define TRACE_INCLUDE_PATH ../../include/ras
+#include <ras/ras_event.h>
+
+static int __init ras_init(void)
+{
+ int rc = 0;
+
+ ras_debugfs_init();
+ rc = ras_add_daemon_trace();
+
+ return rc;
+}
+subsys_initcall(ras_init);
+
+#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
+EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
+#endif
+EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
index 7a721d67e6ac..4e6c8c611905 100644
--- a/drivers/regulator/88pm800.c
+++ b/drivers/regulator/88pm800.c
@@ -52,7 +52,6 @@
#define PM800_BUCK1_3 (0x3F)
#define PM800_BUCK2 (0x40)
#define PM800_BUCK3 (0x41)
-#define PM800_BUCK3 (0x41)
#define PM800_BUCK4 (0x42)
#define PM800_BUCK4_1 (0x43)
#define PM800_BUCK4_2 (0x44)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 789eb46090e3..2dc8289e5dba 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -198,6 +198,16 @@ config REGULATOR_DA9210
converter 12A DC-DC Buck controlled through an I2C
interface.
+config REGULATOR_DA9211
+ tristate "Dialog Semiconductor DA9211/DA9212 regulator"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say y here to support for the Dialog Semiconductor DA9211/DA9212.
+ The DA9211/DA9212 is a multi-phase synchronous step down
+ converter 12A DC-DC Buck controlled through an I2C
+ interface.
+
config REGULATOR_DBX500_PRCMU
bool
@@ -457,10 +467,10 @@ config REGULATOR_S2MPA01
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
- tristate "Samsung S2MPS11/S2MPS14 voltage regulator"
+ tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
depends on MFD_SEC_CORE
help
- This driver supports a Samsung S2MPS11/S2MPS14 voltage output
+ This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
regulator via I2C bus. The chip is comprised of high efficient Buck
converters including Dual-Phase Buck converter, Buck-Boost converter,
various LDOs.
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index d461110f4463..aa4a6aa7b558 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o
obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
+obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index c625468c7f2c..1fda14e12ea8 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -3037,28 +3037,12 @@ static int ab8500_regulator_register(struct platform_device *pdev,
return 0;
}
-static int
-ab8500_regulator_of_probe(struct platform_device *pdev,
- struct device_node *np)
-{
- struct of_regulator_match *match = abx500_regulator.match;
- int err, i;
-
- for (i = 0; i < abx500_regulator.info_size; i++) {
- err = ab8500_regulator_register(
- pdev, match[i].init_data, i, match[i].of_node);
- if (err)
- return err;
- }
-
- return 0;
-}
-
static int ab8500_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node;
- int err;
+ struct of_regulator_match *match;
+ int err, i;
if (!ab8500) {
dev_err(&pdev->dev, "null mfd parent\n");
@@ -3075,24 +3059,20 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
"Error parsing regulator init data: %d\n", err);
return err;
}
- return ab8500_regulator_of_probe(pdev, np);
-}
-
-static int ab8500_regulator_remove(struct platform_device *pdev)
-{
- int err;
- /* remove regulator debug */
- err = ab8500_regulator_debug_exit(pdev);
- if (err)
- return err;
+ match = abx500_regulator.match;
+ for (i = 0; i < abx500_regulator.info_size; i++) {
+ err = ab8500_regulator_register(pdev, match[i].init_data, i,
+ match[i].of_node);
+ if (err)
+ return err;
+ }
return 0;
}
static struct platform_driver ab8500_regulator_driver = {
.probe = ab8500_regulator_probe,
- .remove = ab8500_regulator_remove,
.driver = {
.name = "ab8500-regulator",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index b92d7dd01a18..afd06f92dfdf 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -1,6 +1,7 @@
/*
- * act8865-regulator.c - Voltage regulation for the active-semi ACT8865
- * http://www.active-semi.com/sheets/ACT8865_Datasheet.pdf
+ * act8865-regulator.c - Voltage regulation for active-semi ACT88xx PMUs
+ *
+ * http://www.active-semi.com/products/power-management-units/act88xx/
*
* Copyright (C) 2013 Atmel Corporation
*
@@ -28,6 +29,40 @@
#include <linux/regmap.h>
/*
+ * ACT8846 Global Register Map.
+ */
+#define ACT8846_SYS0 0x00
+#define ACT8846_SYS1 0x01
+#define ACT8846_REG1_VSET 0x10
+#define ACT8846_REG1_CTRL 0x12
+#define ACT8846_REG2_VSET0 0x20
+#define ACT8846_REG2_VSET1 0x21
+#define ACT8846_REG2_CTRL 0x22
+#define ACT8846_REG3_VSET0 0x30
+#define ACT8846_REG3_VSET1 0x31
+#define ACT8846_REG3_CTRL 0x32
+#define ACT8846_REG4_VSET0 0x40
+#define ACT8846_REG4_VSET1 0x41
+#define ACT8846_REG4_CTRL 0x42
+#define ACT8846_REG5_VSET 0x50
+#define ACT8846_REG5_CTRL 0x51
+#define ACT8846_REG6_VSET 0x58
+#define ACT8846_REG6_CTRL 0x59
+#define ACT8846_REG7_VSET 0x60
+#define ACT8846_REG7_CTRL 0x61
+#define ACT8846_REG8_VSET 0x68
+#define ACT8846_REG8_CTRL 0x69
+#define ACT8846_REG9_VSET 0x70
+#define ACT8846_REG9_CTRL 0x71
+#define ACT8846_REG10_VSET 0x80
+#define ACT8846_REG10_CTRL 0x81
+#define ACT8846_REG11_VSET 0x90
+#define ACT8846_REG11_CTRL 0x91
+#define ACT8846_REG12_VSET 0xa0
+#define ACT8846_REG12_CTRL 0xa1
+#define ACT8846_REG13_CTRL 0xb1
+
+/*
* ACT8865 Global Register Map.
*/
#define ACT8865_SYS_MODE 0x00
@@ -70,7 +105,7 @@ static const struct regmap_config act8865_regmap_config = {
.val_bits = 8,
};
-static const struct regulator_linear_range act8865_volatge_ranges[] = {
+static const struct regulator_linear_range act8865_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
@@ -86,114 +121,70 @@ static struct regulator_ops act8865_ops = {
.is_enabled = regulator_is_enabled_regmap,
};
-static const struct regulator_desc act8865_reg[] = {
- {
- .name = "DCDC_REG1",
- .id = ACT8865_ID_DCDC1,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_DCDC1_VSET1,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_DCDC1_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "DCDC_REG2",
- .id = ACT8865_ID_DCDC2,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_DCDC2_VSET1,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_DCDC2_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "DCDC_REG3",
- .id = ACT8865_ID_DCDC3,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_DCDC3_VSET1,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_DCDC3_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "LDO_REG1",
- .id = ACT8865_ID_LDO1,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_LDO1_VSET,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_LDO1_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "LDO_REG2",
- .id = ACT8865_ID_LDO2,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_LDO2_VSET,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_LDO2_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "LDO_REG3",
- .id = ACT8865_ID_LDO3,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_LDO3_VSET,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_LDO3_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
- {
- .name = "LDO_REG4",
- .id = ACT8865_ID_LDO4,
- .ops = &act8865_ops,
- .type = REGULATOR_VOLTAGE,
- .n_voltages = ACT8865_VOLTAGE_NUM,
- .linear_ranges = act8865_volatge_ranges,
- .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
- .vsel_reg = ACT8865_LDO4_VSET,
- .vsel_mask = ACT8865_VSEL_MASK,
- .enable_reg = ACT8865_LDO4_CTRL,
- .enable_mask = ACT8865_ENA,
- .owner = THIS_MODULE,
- },
+#define ACT88xx_REG(_name, _family, _id, _vsel_reg) \
+ [_family##_ID_##_id] = { \
+ .name = _name, \
+ .id = _family##_ID_##_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .ops = &act8865_ops, \
+ .n_voltages = ACT8865_VOLTAGE_NUM, \
+ .linear_ranges = act8865_voltage_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(act8865_voltage_ranges), \
+ .vsel_reg = _family##_##_id##_##_vsel_reg, \
+ .vsel_mask = ACT8865_VSEL_MASK, \
+ .enable_reg = _family##_##_id##_CTRL, \
+ .enable_mask = ACT8865_ENA, \
+ .owner = THIS_MODULE, \
+ }
+
+static const struct regulator_desc act8846_regulators[] = {
+ ACT88xx_REG("REG1", ACT8846, REG1, VSET),
+ ACT88xx_REG("REG2", ACT8846, REG2, VSET0),
+ ACT88xx_REG("REG3", ACT8846, REG3, VSET0),
+ ACT88xx_REG("REG4", ACT8846, REG4, VSET0),
+ ACT88xx_REG("REG5", ACT8846, REG5, VSET),
+ ACT88xx_REG("REG6", ACT8846, REG6, VSET),
+ ACT88xx_REG("REG7", ACT8846, REG7, VSET),
+ ACT88xx_REG("REG8", ACT8846, REG8, VSET),
+ ACT88xx_REG("REG9", ACT8846, REG9, VSET),
+ ACT88xx_REG("REG10", ACT8846, REG10, VSET),
+ ACT88xx_REG("REG11", ACT8846, REG11, VSET),
+ ACT88xx_REG("REG12", ACT8846, REG12, VSET),
+};
+
+static const struct regulator_desc act8865_regulators[] = {
+ ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1),
+ ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1),
+ ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1),
+ ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET),
+ ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET),
+ ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET),
+ ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET),
};
#ifdef CONFIG_OF
static const struct of_device_id act8865_dt_ids[] = {
- { .compatible = "active-semi,act8865" },
+ { .compatible = "active-semi,act8846", .data = (void *)ACT8846 },
+ { .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
{ }
};
MODULE_DEVICE_TABLE(of, act8865_dt_ids);
+static struct of_regulator_match act8846_matches[] = {
+ [ACT8846_ID_REG1] = { .name = "REG1" },
+ [ACT8846_ID_REG2] = { .name = "REG2" },
+ [ACT8846_ID_REG3] = { .name = "REG3" },
+ [ACT8846_ID_REG4] = { .name = "REG4" },
+ [ACT8846_ID_REG5] = { .name = "REG5" },
+ [ACT8846_ID_REG6] = { .name = "REG6" },
+ [ACT8846_ID_REG7] = { .name = "REG7" },
+ [ACT8846_ID_REG8] = { .name = "REG8" },
+ [ACT8846_ID_REG9] = { .name = "REG9" },
+ [ACT8846_ID_REG10] = { .name = "REG10" },
+ [ACT8846_ID_REG11] = { .name = "REG11" },
+ [ACT8846_ID_REG12] = { .name = "REG12" },
+};
+
static struct of_regulator_match act8865_matches[] = {
[ACT8865_ID_DCDC1] = { .name = "DCDC_REG1"},
[ACT8865_ID_DCDC2] = { .name = "DCDC_REG2"},
@@ -206,11 +197,13 @@ static struct of_regulator_match act8865_matches[] = {
static int act8865_pdata_from_dt(struct device *dev,
struct device_node **of_node,
- struct act8865_platform_data *pdata)
+ struct act8865_platform_data *pdata,
+ unsigned long type)
{
- int matched, i;
+ int matched, i, num_matches;
struct device_node *np;
struct act8865_regulator_data *regulator;
+ struct of_regulator_match *matches;
np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) {
@@ -218,26 +211,39 @@ static int act8865_pdata_from_dt(struct device *dev,
return -EINVAL;
}
- matched = of_regulator_match(dev, np,
- act8865_matches, ARRAY_SIZE(act8865_matches));
+ switch (type) {
+ case ACT8846:
+ matches = act8846_matches;
+ num_matches = ARRAY_SIZE(act8846_matches);
+ break;
+ case ACT8865:
+ matches = act8865_matches;
+ num_matches = ARRAY_SIZE(act8865_matches);
+ break;
+ default:
+ dev_err(dev, "invalid device id %lu\n", type);
+ return -EINVAL;
+ }
+
+ matched = of_regulator_match(dev, np, matches, num_matches);
of_node_put(np);
if (matched <= 0)
return matched;
pdata->regulators = devm_kzalloc(dev,
- sizeof(struct act8865_regulator_data) *
- ARRAY_SIZE(act8865_matches), GFP_KERNEL);
+ sizeof(struct act8865_regulator_data) *
+ num_matches, GFP_KERNEL);
if (!pdata->regulators)
return -ENOMEM;
- pdata->num_regulators = matched;
+ pdata->num_regulators = num_matches;
regulator = pdata->regulators;
- for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) {
+ for (i = 0; i < num_matches; i++) {
regulator->id = i;
- regulator->name = act8865_matches[i].name;
- regulator->platform_data = act8865_matches[i].init_data;
- of_node[i] = act8865_matches[i].of_node;
+ regulator->name = matches[i].name;
+ regulator->platform_data = matches[i].init_data;
+ of_node[i] = matches[i].of_node;
regulator++;
}
@@ -246,42 +252,84 @@ static int act8865_pdata_from_dt(struct device *dev,
#else
static inline int act8865_pdata_from_dt(struct device *dev,
struct device_node **of_node,
- struct act8865_platform_data *pdata)
+ struct act8865_platform_data *pdata,
+ unsigned long type)
{
return 0;
}
#endif
+static struct regulator_init_data
+*act8865_get_init_data(int id, struct act8865_platform_data *pdata)
+{
+ int i;
+
+ if (!pdata)
+ return NULL;
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ if (pdata->regulators[i].id == id)
+ return pdata->regulators[i].platform_data;
+ }
+
+ return NULL;
+}
+
static int act8865_pmic_probe(struct i2c_client *client,
- const struct i2c_device_id *i2c_id)
+ const struct i2c_device_id *i2c_id)
{
- struct regulator_dev *rdev;
+ static const struct regulator_desc *regulators;
+ struct act8865_platform_data pdata_of, *pdata;
struct device *dev = &client->dev;
- struct act8865_platform_data *pdata = dev_get_platdata(dev);
- struct regulator_config config = { };
+ struct device_node **of_node;
+ int i, ret, num_regulators;
struct act8865 *act8865;
- struct device_node *of_node[ACT8865_REG_NUM];
- int i, id;
- int ret = -EINVAL;
- int error;
+ unsigned long type;
+
+ pdata = dev_get_platdata(dev);
if (dev->of_node && !pdata) {
const struct of_device_id *id;
- struct act8865_platform_data pdata_of;
id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
if (!id)
return -ENODEV;
- ret = act8865_pdata_from_dt(dev, of_node, &pdata_of);
+ type = (unsigned long) id->data;
+ } else {
+ type = i2c_id->driver_data;
+ }
+
+ switch (type) {
+ case ACT8846:
+ regulators = act8846_regulators;
+ num_regulators = ARRAY_SIZE(act8846_regulators);
+ break;
+ case ACT8865:
+ regulators = act8865_regulators;
+ num_regulators = ARRAY_SIZE(act8865_regulators);
+ break;
+ default:
+ dev_err(dev, "invalid device id %lu\n", type);
+ return -EINVAL;
+ }
+
+ of_node = devm_kzalloc(dev, sizeof(struct device_node *) *
+ num_regulators, GFP_KERNEL);
+ if (!of_node)
+ return -ENOMEM;
+
+ if (dev->of_node && !pdata) {
+ ret = act8865_pdata_from_dt(dev, of_node, &pdata_of, type);
if (ret < 0)
return ret;
pdata = &pdata_of;
}
- if (pdata->num_regulators > ACT8865_REG_NUM) {
- dev_err(dev, "Too many regulators found!\n");
+ if (pdata->num_regulators > num_regulators) {
+ dev_err(dev, "too many regulators: %d\n",
+ pdata->num_regulators);
return -EINVAL;
}
@@ -291,39 +339,40 @@ static int act8865_pmic_probe(struct i2c_client *client,
act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
if (IS_ERR(act8865->regmap)) {
- error = PTR_ERR(act8865->regmap);
+ ret = PTR_ERR(act8865->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
- error);
- return error;
+ ret);
+ return ret;
}
/* Finally register devices */
- for (i = 0; i < ACT8865_REG_NUM; i++) {
-
- id = pdata->regulators[i].id;
+ for (i = 0; i < num_regulators; i++) {
+ const struct regulator_desc *desc = &regulators[i];
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
config.dev = dev;
- config.init_data = pdata->regulators[i].platform_data;
+ config.init_data = act8865_get_init_data(desc->id, pdata);
config.of_node = of_node[i];
config.driver_data = act8865;
config.regmap = act8865->regmap;
- rdev = devm_regulator_register(&client->dev, &act8865_reg[i],
- &config);
+ rdev = devm_regulator_register(&client->dev, desc, &config);
if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n",
- act8865_reg[id].name);
+ dev_err(dev, "failed to register %s\n", desc->name);
return PTR_ERR(rdev);
}
}
i2c_set_clientdata(client, act8865);
+ devm_kfree(dev, of_node);
return 0;
}
static const struct i2c_device_id act8865_ids[] = {
- { "act8865", 0 },
+ { .name = "act8846", .driver_data = ACT8846 },
+ { .name = "act8865", .driver_data = ACT8865 },
{ },
};
MODULE_DEVICE_TABLE(i2c, act8865_ids);
@@ -339,6 +388,6 @@ static struct i2c_driver act8865_pmic_driver = {
module_i2c_driver(act8865_pmic_driver);
-MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver");
+MODULE_DESCRIPTION("active-semi act88xx voltage regulator driver");
MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 04f262a836b2..4c9db589f6c1 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -143,8 +143,6 @@ static struct regulator_ops arizona_ldo1_ops = {
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .get_bypass = regulator_get_bypass_regmap,
- .set_bypass = regulator_set_bypass_regmap,
};
static const struct regulator_desc arizona_ldo1 = {
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index ad9e0c9b7daf..b68f05f38537 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -219,7 +219,7 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = {
{
.regulator_id = AS3722_REGULATOR_ID_LDO3,
.name = "as3722-ldo3",
- .name = "vin-ldo3-4",
+ .sname = "vin-ldo3-4",
.vsel_reg = AS3722_LDO3_VOLTAGE_REG,
.vsel_mask = AS3722_LDO3_VSEL_MASK,
.enable_reg = AS3722_LDOCONTROL0_REG,
@@ -231,7 +231,7 @@ static const struct as3722_register_mapping as3722_reg_lookup[] = {
{
.regulator_id = AS3722_REGULATOR_ID_LDO4,
.name = "as3722-ldo4",
- .name = "vin-ldo3-4",
+ .sname = "vin-ldo3-4",
.vsel_reg = AS3722_LDO4_VOLTAGE_REG,
.vsel_mask = AS3722_LDO_VSEL_MASK,
.enable_reg = AS3722_LDOCONTROL0_REG,
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 58ece59367ae..5d1fd6f3d10a 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -331,10 +331,8 @@ static struct bcm590xx_board *bcm590xx_parse_dt_reg_data(
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&pdev->dev, "failed to allocate regulator board data\n");
+ if (!data)
return NULL;
- }
np = of_node_get(np);
regulators = of_get_child_by_name(np, "regulators");
@@ -379,10 +377,8 @@ static int bcm590xx_probe(struct platform_device *pdev)
&bcm590xx_reg_matches);
pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
- if (!pmu) {
- dev_err(&pdev->dev, "Memory allocation failed for pmu\n");
+ if (!pmu)
return -ENOMEM;
- }
pmu->mfd = bcm590xx;
@@ -390,17 +386,13 @@ static int bcm590xx_probe(struct platform_device *pdev)
pmu->desc = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS *
sizeof(struct regulator_desc), GFP_KERNEL);
- if (!pmu->desc) {
- dev_err(&pdev->dev, "Memory alloc fails for desc\n");
+ if (!pmu->desc)
return -ENOMEM;
- }
pmu->info = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS *
sizeof(struct bcm590xx_info *), GFP_KERNEL);
- if (!pmu->info) {
- dev_err(&pdev->dev, "Memory alloc fails for info\n");
+ if (!pmu->info)
return -ENOMEM;
- }
info = bcm590xx_regs;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 4c1f999041dd..a3c3785901f5 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -24,6 +24,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/of_regulator.h>
@@ -77,7 +78,7 @@ struct regulator_map {
*/
struct regulator_enable_gpio {
struct list_head list;
- int gpio;
+ struct gpio_desc *gpiod;
u32 enable_count; /* a number of enabled shared GPIO */
u32 request_count; /* a number of requested shared GPIO */
unsigned int ena_gpio_invert:1;
@@ -846,7 +847,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
rdev->constraints->min_uV == rdev->constraints->max_uV) {
int current_uV = _regulator_get_voltage(rdev);
if (current_uV < 0) {
- rdev_err(rdev, "failed to get the current voltage\n");
+ rdev_err(rdev,
+ "failed to get the current voltage(%d)\n",
+ current_uV);
return current_uV;
}
if (current_uV < rdev->constraints->min_uV ||
@@ -856,8 +859,8 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
rdev->constraints->max_uV);
if (ret < 0) {
rdev_err(rdev,
- "failed to apply %duV constraint\n",
- rdev->constraints->min_uV);
+ "failed to apply %duV constraint(%d)\n",
+ rdev->constraints->min_uV, ret);
return ret;
}
}
@@ -1660,10 +1663,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
const struct regulator_config *config)
{
struct regulator_enable_gpio *pin;
+ struct gpio_desc *gpiod;
int ret;
+ gpiod = gpio_to_desc(config->ena_gpio);
+
list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
- if (pin->gpio == config->ena_gpio) {
+ if (pin->gpiod == gpiod) {
rdev_dbg(rdev, "GPIO %d is already used\n",
config->ena_gpio);
goto update_ena_gpio_to_rdev;
@@ -1682,7 +1688,7 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
return -ENOMEM;
}
- pin->gpio = config->ena_gpio;
+ pin->gpiod = gpiod;
pin->ena_gpio_invert = config->ena_gpio_invert;
list_add(&pin->list, &regulator_ena_gpio_list);
@@ -1701,10 +1707,10 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
/* Free the GPIO only in case of no use */
list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
- if (pin->gpio == rdev->ena_pin->gpio) {
+ if (pin->gpiod == rdev->ena_pin->gpiod) {
if (pin->request_count <= 1) {
pin->request_count = 0;
- gpio_free(pin->gpio);
+ gpiod_put(pin->gpiod);
list_del(&pin->list);
kfree(pin);
} else {
@@ -1732,8 +1738,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
if (enable) {
/* Enable GPIO at initial use */
if (pin->enable_count == 0)
- gpio_set_value_cansleep(pin->gpio,
- !pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod,
+ !pin->ena_gpio_invert);
pin->enable_count++;
} else {
@@ -1744,8 +1750,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
/* Disable GPIO if not used */
if (pin->enable_count <= 1) {
- gpio_set_value_cansleep(pin->gpio,
- pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod,
+ pin->ena_gpio_invert);
pin->enable_count = 0;
}
}
@@ -2180,7 +2186,13 @@ int regulator_count_voltages(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
- return rdev->desc->n_voltages ? : -EINVAL;
+ if (rdev->desc->n_voltages)
+ return rdev->desc->n_voltages;
+
+ if (!rdev->supply)
+ return -EINVAL;
+
+ return regulator_count_voltages(rdev->supply);
}
EXPORT_SYMBOL_GPL(regulator_count_voltages);
@@ -2203,12 +2215,17 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
return rdev->desc->fixed_uV;
- if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
+ if (ops->list_voltage) {
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+ mutex_lock(&rdev->mutex);
+ ret = ops->list_voltage(rdev, selector);
+ mutex_unlock(&rdev->mutex);
+ } else if (rdev->supply) {
+ ret = regulator_list_voltage(rdev->supply, selector);
+ } else {
return -EINVAL;
-
- mutex_lock(&rdev->mutex);
- ret = ops->list_voltage(rdev, selector);
- mutex_unlock(&rdev->mutex);
+ }
if (ret > 0) {
if (ret < rdev->constraints->min_uV)
@@ -2222,6 +2239,77 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
EXPORT_SYMBOL_GPL(regulator_list_voltage);
/**
+ * regulator_get_regmap - get the regulator's register map
+ * @regulator: regulator source
+ *
+ * Returns the register map for the given regulator, or an ERR_PTR value
+ * if the regulator doesn't use regmap.
+ */
+struct regmap *regulator_get_regmap(struct regulator *regulator)
+{
+ struct regmap *map = regulator->rdev->regmap;
+
+ return map ? map : ERR_PTR(-EOPNOTSUPP);
+}
+
+/**
+ * regulator_get_hardware_vsel_register - get the HW voltage selector register
+ * @regulator: regulator source
+ * @vsel_reg: voltage selector register, output parameter
+ * @vsel_mask: mask for voltage selector bitfield, output parameter
+ *
+ * Returns the hardware register offset and bitmask used for setting the
+ * regulator voltage. This might be useful when configuring voltage-scaling
+ * hardware or firmware that can make I2C requests behind the kernel's back,
+ * for example.
+ *
+ * On success, the output parameters @vsel_reg and @vsel_mask are filled in
+ * and 0 is returned, otherwise a negative errno is returned.
+ */
+int regulator_get_hardware_vsel_register(struct regulator *regulator,
+ unsigned *vsel_reg,
+ unsigned *vsel_mask)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ struct regulator_ops *ops = rdev->desc->ops;
+
+ if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
+ return -EOPNOTSUPP;
+
+ *vsel_reg = rdev->desc->vsel_reg;
+ *vsel_mask = rdev->desc->vsel_mask;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
+
+/**
+ * regulator_list_hardware_vsel - get the HW-specific register value for a selector
+ * @regulator: regulator source
+ * @selector: identify voltage to list
+ *
+ * Converts the selector to a hardware-specific voltage selector that can be
+ * directly written to the regulator registers. The address of the voltage
+ * register can be determined by calling @regulator_get_hardware_vsel_register.
+ *
+ * On error a negative errno is returned.
+ */
+int regulator_list_hardware_vsel(struct regulator *regulator,
+ unsigned selector)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ struct regulator_ops *ops = rdev->desc->ops;
+
+ if (selector >= rdev->desc->n_voltages)
+ return -EINVAL;
+ if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
+ return -EOPNOTSUPP;
+
+ return selector;
+}
+EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
+
+/**
* regulator_get_linear_step - return the voltage step size between VSEL values
* @regulator: regulator source
*
@@ -2618,6 +2706,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
ret = rdev->desc->ops->list_voltage(rdev, 0);
} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
ret = rdev->desc->fixed_uV;
+ } else if (rdev->supply) {
+ ret = regulator_get_voltage(rdev->supply);
} else {
return -EINVAL;
}
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
new file mode 100644
index 000000000000..1482adafa1ad
--- /dev/null
+++ b/drivers/regulator/da9211-regulator.c
@@ -0,0 +1,368 @@
+/*
+ * da9211-regulator.c - Regulator device driver for DA9211
+ * Copyright (C) 2014 Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/regulator/da9211.h>
+#include "da9211-regulator.h"
+
+#define DA9211_BUCK_MODE_SLEEP 1
+#define DA9211_BUCK_MODE_SYNC 2
+#define DA9211_BUCK_MODE_AUTO 3
+
+/* DA9211 REGULATOR IDs */
+#define DA9211_ID_BUCKA 0
+#define DA9211_ID_BUCKB 1
+
+struct da9211 {
+ struct device *dev;
+ struct regmap *regmap;
+ struct da9211_pdata *pdata;
+ struct regulator_dev *rdev[DA9211_MAX_REGULATORS];
+ int num_regulator;
+ int chip_irq;
+};
+
+static const struct regmap_range_cfg da9211_regmap_range[] = {
+ {
+ .selector_reg = DA9211_REG_PAGE_CON,
+ .selector_mask = DA9211_REG_PAGE_MASK,
+ .selector_shift = DA9211_REG_PAGE_SHIFT,
+ .window_start = 0,
+ .window_len = 256,
+ .range_min = 0,
+ .range_max = 2*256,
+ },
+};
+
+static const struct regmap_config da9211_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 2 * 256,
+ .ranges = da9211_regmap_range,
+ .num_ranges = ARRAY_SIZE(da9211_regmap_range),
+};
+
+/* Default limits measured in millivolts and milliamps */
+#define DA9211_MIN_MV 300
+#define DA9211_MAX_MV 1570
+#define DA9211_STEP_MV 10
+
+/* Current limits for buck (uA) indices corresponds with register values */
+static const int da9211_current_limits[] = {
+ 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000,
+ 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000
+};
+
+static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
+{
+ int id = rdev_get_id(rdev);
+ struct da9211 *chip = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret, mode = 0;
+
+ ret = regmap_read(chip->regmap, DA9211_REG_BUCKA_CONF+id, &data);
+ if (ret < 0)
+ return ret;
+
+ switch (data & 0x03) {
+ case DA9211_BUCK_MODE_SYNC:
+ mode = REGULATOR_MODE_FAST;
+ break;
+ case DA9211_BUCK_MODE_AUTO:
+ mode = REGULATOR_MODE_NORMAL;
+ break;
+ case DA9211_BUCK_MODE_SLEEP:
+ mode = REGULATOR_MODE_STANDBY;
+ break;
+ }
+
+ return mode;
+}
+
+static int da9211_buck_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ int id = rdev_get_id(rdev);
+ struct da9211 *chip = rdev_get_drvdata(rdev);
+ int val = 0;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = DA9211_BUCK_MODE_SYNC;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ val = DA9211_BUCK_MODE_AUTO;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ val = DA9211_BUCK_MODE_SLEEP;
+ break;
+ }
+
+ return regmap_update_bits(chip->regmap, DA9211_REG_BUCKA_CONF+id,
+ 0x03, val);
+}
+
+static int da9211_set_current_limit(struct regulator_dev *rdev, int min,
+ int max)
+{
+ int id = rdev_get_id(rdev);
+ struct da9211 *chip = rdev_get_drvdata(rdev);
+ int i;
+
+ /* search for closest to maximum */
+ for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) {
+ if (min <= da9211_current_limits[i] &&
+ max >= da9211_current_limits[i]) {
+ return regmap_update_bits(chip->regmap,
+ DA9211_REG_BUCK_ILIM,
+ (0x0F << id*4), (i << id*4));
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int da9211_get_current_limit(struct regulator_dev *rdev)
+{
+ int id = rdev_get_id(rdev);
+ struct da9211 *chip = rdev_get_drvdata(rdev);
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data);
+ if (ret < 0)
+ return ret;
+
+ /* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */
+ data = (data >> id*4) & 0x0F;
+ return da9211_current_limits[data];
+}
+
+static struct regulator_ops da9211_buck_ops = {
+ .get_mode = da9211_buck_get_mode,
+ .set_mode = da9211_buck_set_mode,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .set_current_limit = da9211_set_current_limit,
+ .get_current_limit = da9211_get_current_limit,
+};
+
+#define DA9211_BUCK(_id) \
+{\
+ .name = #_id,\
+ .ops = &da9211_buck_ops,\
+ .type = REGULATOR_VOLTAGE,\
+ .id = DA9211_ID_##_id,\
+ .n_voltages = (DA9211_MAX_MV - DA9211_MIN_MV) / DA9211_STEP_MV + 1,\
+ .min_uV = (DA9211_MIN_MV * 1000),\
+ .uV_step = (DA9211_STEP_MV * 1000),\
+ .enable_reg = DA9211_REG_BUCKA_CONT + DA9211_ID_##_id,\
+ .enable_mask = DA9211_BUCKA_EN,\
+ .vsel_reg = DA9211_REG_VBUCKA_A + DA9211_ID_##_id * 2,\
+ .vsel_mask = DA9211_VBUCK_MASK,\
+ .owner = THIS_MODULE,\
+}
+
+static struct regulator_desc da9211_regulators[] = {
+ DA9211_BUCK(BUCKA),
+ DA9211_BUCK(BUCKB),
+};
+
+static irqreturn_t da9211_irq_handler(int irq, void *data)
+{
+ struct da9211 *chip = data;
+ int reg_val, err, ret = IRQ_NONE;
+
+ err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, &reg_val);
+ if (err < 0)
+ goto error_i2c;
+
+ if (reg_val & DA9211_E_OV_CURR_A) {
+ regulator_notifier_call_chain(chip->rdev[0],
+ REGULATOR_EVENT_OVER_CURRENT,
+ rdev_get_drvdata(chip->rdev[0]));
+
+ err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
+ DA9211_E_OV_CURR_A);
+ if (err < 0)
+ goto error_i2c;
+
+ ret = IRQ_HANDLED;
+ }
+
+ if (reg_val & DA9211_E_OV_CURR_B) {
+ regulator_notifier_call_chain(chip->rdev[1],
+ REGULATOR_EVENT_OVER_CURRENT,
+ rdev_get_drvdata(chip->rdev[1]));
+
+ err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
+ DA9211_E_OV_CURR_B);
+ if (err < 0)
+ goto error_i2c;
+
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+
+error_i2c:
+ dev_err(chip->dev, "I2C error : %d\n", err);
+ return IRQ_NONE;
+}
+
+static int da9211_regulator_init(struct da9211 *chip)
+{
+ struct regulator_config config = { };
+ int i, ret;
+ unsigned int data;
+
+ ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read CONTROL_E reg: %d\n", ret);
+ return ret;
+ }
+
+ data &= DA9211_SLAVE_SEL;
+ /* If configuration for 1/2 bucks is different between platform data
+ * and the register, driver should exit.
+ */
+ if ((chip->pdata->num_buck == 2 && data == 0x40)
+ || (chip->pdata->num_buck == 1 && data == 0x00)) {
+ if (data == 0)
+ chip->num_regulator = 1;
+ else
+ chip->num_regulator = 2;
+ } else {
+ dev_err(chip->dev, "Configuration is mismatched\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < chip->num_regulator; i++) {
+ if (chip->pdata)
+ config.init_data =
+ &(chip->pdata->init_data[i]);
+
+ config.dev = chip->dev;
+ config.driver_data = chip;
+ config.regmap = chip->regmap;
+
+ chip->rdev[i] = devm_regulator_register(chip->dev,
+ &da9211_regulators[i], &config);
+ if (IS_ERR(chip->rdev[i])) {
+ dev_err(chip->dev,
+ "Failed to register DA9211 regulator\n");
+ return PTR_ERR(chip->rdev[i]);
+ }
+
+ if (chip->chip_irq != 0) {
+ ret = regmap_update_bits(chip->regmap,
+ DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 1);
+ if (ret < 0) {
+ dev_err(chip->dev,
+ "Failed to update mask reg: %d\n", ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+/*
+ * I2C driver interface functions
+ */
+static int da9211_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct da9211 *chip;
+ int error, ret;
+
+ chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL);
+
+ chip->dev = &i2c->dev;
+ chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config);
+ if (IS_ERR(chip->regmap)) {
+ error = PTR_ERR(chip->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ error);
+ return error;
+ }
+
+ i2c_set_clientdata(i2c, chip);
+
+ chip->pdata = i2c->dev.platform_data;
+ if (!chip->pdata) {
+ dev_err(&i2c->dev, "No platform init data supplied\n");
+ return -ENODEV;
+ }
+
+ chip->chip_irq = i2c->irq;
+
+ if (chip->chip_irq != 0) {
+ ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+ da9211_irq_handler,
+ IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+ "da9211", chip);
+ if (ret != 0) {
+ dev_err(chip->dev, "Failed to request IRQ: %d\n",
+ chip->chip_irq);
+ return ret;
+ }
+ } else {
+ dev_warn(chip->dev, "No IRQ configured\n");
+ }
+
+ ret = da9211_regulator_init(chip);
+
+ if (ret < 0)
+ dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret);
+
+ return ret;
+}
+
+static const struct i2c_device_id da9211_i2c_id[] = {
+ {"da9211", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
+
+static struct i2c_driver da9211_regulator_driver = {
+ .driver = {
+ .name = "da9211",
+ .owner = THIS_MODULE,
+ },
+ .probe = da9211_i2c_probe,
+ .id_table = da9211_i2c_id,
+};
+
+module_i2c_driver(da9211_regulator_driver);
+
+MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
+MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/da9211-regulator.h b/drivers/regulator/da9211-regulator.h
new file mode 100644
index 000000000000..88b1769e8058
--- /dev/null
+++ b/drivers/regulator/da9211-regulator.h
@@ -0,0 +1,271 @@
+/*
+ * da9211-regulator.h - Regulator definitions for DA9211
+ * Copyright (C) 2014 Dialog Semiconductor Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ */
+
+#ifndef __DA9211_REGISTERS_H__
+#define __DA9211_REGISTERS_H__
+
+/* Page selection */
+#define DA9211_REG_PAGE_CON 0x00
+
+/* System Control and Event Registers */
+#define DA9211_REG_STATUS_A 0x50
+#define DA9211_REG_STATUS_B 0x51
+#define DA9211_REG_EVENT_A 0x52
+#define DA9211_REG_EVENT_B 0x53
+#define DA9211_REG_MASK_A 0x54
+#define DA9211_REG_MASK_B 0x55
+#define DA9211_REG_CONTROL_A 0x56
+
+/* GPIO Control Registers */
+#define DA9211_REG_GPIO_0_1 0x58
+#define DA9211_REG_GPIO_2_3 0x59
+#define DA9211_REG_GPIO_4 0x5A
+
+/* Regulator Registers */
+#define DA9211_REG_BUCKA_CONT 0x5D
+#define DA9211_REG_BUCKB_CONT 0x5E
+#define DA9211_REG_BUCK_ILIM 0xD0
+#define DA9211_REG_BUCKA_CONF 0xD1
+#define DA9211_REG_BUCKB_CONF 0xD2
+#define DA9211_REG_BUCK_CONF 0xD3
+#define DA9211_REG_VBACKA_MAX 0xD5
+#define DA9211_REG_VBACKB_MAX 0xD6
+#define DA9211_REG_VBUCKA_A 0xD7
+#define DA9211_REG_VBUCKA_B 0xD8
+#define DA9211_REG_VBUCKB_A 0xD9
+#define DA9211_REG_VBUCKB_B 0xDA
+
+/* I2C Interface Settings */
+#define DA9211_REG_INTERFACE 0x105
+
+/* BUCK Phase Selection*/
+#define DA9211_REG_CONFIG_E 0x147
+
+/*
+ * Registers bits
+ */
+/* DA9211_REG_PAGE_CON (addr=0x00) */
+#define DA9211_REG_PAGE_SHIFT 1
+#define DA9211_REG_PAGE_MASK 0x02
+/* On I2C registers 0x00 - 0xFF */
+#define DA9211_REG_PAGE0 0
+/* On I2C registers 0x100 - 0x1FF */
+#define DA9211_REG_PAGE2 2
+#define DA9211_PAGE_WRITE_MODE 0x00
+#define DA9211_REPEAT_WRITE_MODE 0x40
+#define DA9211_PAGE_REVERT 0x80
+
+/* DA9211_REG_STATUS_A (addr=0x50) */
+#define DA9211_GPI0 0x01
+#define DA9211_GPI1 0x02
+#define DA9211_GPI2 0x04
+#define DA9211_GPI3 0x08
+#define DA9211_GPI4 0x10
+
+/* DA9211_REG_EVENT_A (addr=0x52) */
+#define DA9211_E_GPI0 0x01
+#define DA9211_E_GPI1 0x02
+#define DA9211_E_GPI2 0x04
+#define DA9211_E_GPI3 0x08
+#define DA9211_E_GPI4 0x10
+#define DA9211_E_UVLO_IO 0x40
+
+/* DA9211_REG_EVENT_B (addr=0x53) */
+#define DA9211_E_PWRGOOD_A 0x01
+#define DA9211_E_PWRGOOD_B 0x02
+#define DA9211_E_TEMP_WARN 0x04
+#define DA9211_E_TEMP_CRIT 0x08
+#define DA9211_E_OV_CURR_A 0x10
+#define DA9211_E_OV_CURR_B 0x20
+
+/* DA9211_REG_MASK_A (addr=0x54) */
+#define DA9211_M_GPI0 0x01
+#define DA9211_M_GPI1 0x02
+#define DA9211_M_GPI2 0x04
+#define DA9211_M_GPI3 0x08
+#define DA9211_M_GPI4 0x10
+#define DA9211_M_UVLO_IO 0x40
+
+/* DA9211_REG_MASK_B (addr=0x55) */
+#define DA9211_M_PWRGOOD_A 0x01
+#define DA9211_M_PWRGOOD_B 0x02
+#define DA9211_M_TEMP_WARN 0x04
+#define DA9211_M_TEMP_CRIT 0x08
+#define DA9211_M_OV_CURR_A 0x10
+#define DA9211_M_OV_CURR_B 0x20
+
+/* DA9211_REG_CONTROL_A (addr=0x56) */
+#define DA9211_DEBOUNCING_SHIFT 0
+#define DA9211_DEBOUNCING_MASK 0x07
+#define DA9211_SLEW_RATE_SHIFT 3
+#define DA9211_SLEW_RATE_A_MASK 0x18
+#define DA9211_SLEW_RATE_B_SHIFT 5
+#define DA9211_SLEW_RATE_B_MASK 0x60
+#define DA9211_V_LOCK 0x80
+
+/* DA9211_REG_GPIO_0_1 (addr=0x58) */
+#define DA9211_GPIO0_PIN_SHIFT 0
+#define DA9211_GPIO0_PIN_MASK 0x03
+#define DA9211_GPIO0_PIN_GPI 0x00
+#define DA9211_GPIO0_PIN_GPO_OD 0x02
+#define DA9211_GPIO0_PIN_GPO 0x03
+#define DA9211_GPIO0_TYPE 0x04
+#define DA9211_GPIO0_TYPE_GPI 0x00
+#define DA9211_GPIO0_TYPE_GPO 0x04
+#define DA9211_GPIO0_MODE 0x08
+#define DA9211_GPIO1_PIN_SHIFT 4
+#define DA9211_GPIO1_PIN_MASK 0x30
+#define DA9211_GPIO1_PIN_GPI 0x00
+#define DA9211_GPIO1_PIN_VERROR 0x10
+#define DA9211_GPIO1_PIN_GPO_OD 0x20
+#define DA9211_GPIO1_PIN_GPO 0x30
+#define DA9211_GPIO1_TYPE_SHIFT 0x40
+#define DA9211_GPIO1_TYPE_GPI 0x00
+#define DA9211_GPIO1_TYPE_GPO 0x40
+#define DA9211_GPIO1_MODE 0x80
+
+/* DA9211_REG_GPIO_2_3 (addr=0x59) */
+#define DA9211_GPIO2_PIN_SHIFT 0
+#define DA9211_GPIO2_PIN_MASK 0x03
+#define DA9211_GPIO2_PIN_GPI 0x00
+#define DA9211_GPIO5_PIN_BUCK_CLK 0x10
+#define DA9211_GPIO2_PIN_GPO_OD 0x02
+#define DA9211_GPIO2_PIN_GPO 0x03
+#define DA9211_GPIO2_TYPE 0x04
+#define DA9211_GPIO2_TYPE_GPI 0x00
+#define DA9211_GPIO2_TYPE_GPO 0x04
+#define DA9211_GPIO2_MODE 0x08
+#define DA9211_GPIO3_PIN_SHIFT 4
+#define DA9211_GPIO3_PIN_MASK 0x30
+#define DA9211_GPIO3_PIN_GPI 0x00
+#define DA9211_GPIO3_PIN_IERROR 0x10
+#define DA9211_GPIO3_PIN_GPO_OD 0x20
+#define DA9211_GPIO3_PIN_GPO 0x30
+#define DA9211_GPIO3_TYPE_SHIFT 0x40
+#define DA9211_GPIO3_TYPE_GPI 0x00
+#define DA9211_GPIO3_TYPE_GPO 0x40
+#define DA9211_GPIO3_MODE 0x80
+
+/* DA9211_REG_GPIO_4 (addr=0x5A) */
+#define DA9211_GPIO4_PIN_SHIFT 0
+#define DA9211_GPIO4_PIN_MASK 0x03
+#define DA9211_GPIO4_PIN_GPI 0x00
+#define DA9211_GPIO4_PIN_GPO_OD 0x02
+#define DA9211_GPIO4_PIN_GPO 0x03
+#define DA9211_GPIO4_TYPE 0x04
+#define DA9211_GPIO4_TYPE_GPI 0x00
+#define DA9211_GPIO4_TYPE_GPO 0x04
+#define DA9211_GPIO4_MODE 0x08
+
+/* DA9211_REG_BUCKA_CONT (addr=0x5D) */
+#define DA9211_BUCKA_EN 0x01
+#define DA9211_BUCKA_GPI_SHIFT 1
+#define DA9211_BUCKA_GPI_MASK 0x06
+#define DA9211_BUCKA_GPI_OFF 0x00
+#define DA9211_BUCKA_GPI_GPIO0 0x02
+#define DA9211_BUCKA_GPI_GPIO1 0x04
+#define DA9211_BUCKA_GPI_GPIO3 0x06
+#define DA9211_BUCKA_PD_DIS 0x08
+#define DA9211_VBUCKA_SEL 0x10
+#define DA9211_VBUCKA_SEL_A 0x00
+#define DA9211_VBUCKA_SEL_B 0x10
+#define DA9211_VBUCKA_GPI_SHIFT 5
+#define DA9211_VBUCKA_GPI_MASK 0x60
+#define DA9211_VBUCKA_GPI_OFF 0x00
+#define DA9211_VBUCKA_GPI_GPIO1 0x20
+#define DA9211_VBUCKA_GPI_GPIO2 0x40
+#define DA9211_VBUCKA_GPI_GPIO4 0x60
+
+/* DA9211_REG_BUCKB_CONT (addr=0x5E) */
+#define DA9211_BUCKB_EN 0x01
+#define DA9211_BUCKB_GPI_SHIFT 1
+#define DA9211_BUCKB_GPI_MASK 0x06
+#define DA9211_BUCKB_GPI_OFF 0x00
+#define DA9211_BUCKB_GPI_GPIO0 0x02
+#define DA9211_BUCKB_GPI_GPIO1 0x04
+#define DA9211_BUCKB_GPI_GPIO3 0x06
+#define DA9211_BUCKB_PD_DIS 0x08
+#define DA9211_VBUCKB_SEL 0x10
+#define DA9211_VBUCKB_SEL_A 0x00
+#define DA9211_VBUCKB_SEL_B 0x10
+#define DA9211_VBUCKB_GPI_SHIFT 5
+#define DA9211_VBUCKB_GPI_MASK 0x60
+#define DA9211_VBUCKB_GPI_OFF 0x00
+#define DA9211_VBUCKB_GPI_GPIO1 0x20
+#define DA9211_VBUCKB_GPI_GPIO2 0x40
+#define DA9211_VBUCKB_GPI_GPIO4 0x60
+
+/* DA9211_REG_BUCK_ILIM (addr=0xD0) */
+#define DA9211_BUCKA_ILIM_SHIFT 0
+#define DA9211_BUCKA_ILIM_MASK 0x0F
+#define DA9211_BUCKB_ILIM_SHIFT 4
+#define DA9211_BUCKB_ILIM_MASK 0xF0
+
+/* DA9211_REG_BUCKA_CONF (addr=0xD1) */
+#define DA9211_BUCKA_MODE_SHIFT 0
+#define DA9211_BUCKA_MODE_MASK 0x03
+#define DA9211_BUCKA_MODE_MANUAL 0x00
+#define DA9211_BUCKA_MODE_SLEEP 0x01
+#define DA9211_BUCKA_MODE_SYNC 0x02
+#define DA9211_BUCKA_MODE_AUTO 0x03
+#define DA9211_BUCKA_UP_CTRL_SHIFT 2
+#define DA9211_BUCKA_UP_CTRL_MASK 0x1C
+#define DA9211_BUCKA_DOWN_CTRL_SHIFT 5
+#define DA9211_BUCKA_DOWN_CTRL_MASK 0xE0
+
+/* DA9211_REG_BUCKB_CONF (addr=0xD2) */
+#define DA9211_BUCKB_MODE_SHIFT 0
+#define DA9211_BUCKB_MODE_MASK 0x03
+#define DA9211_BUCKB_MODE_MANUAL 0x00
+#define DA9211_BUCKB_MODE_SLEEP 0x01
+#define DA9211_BUCKB_MODE_SYNC 0x02
+#define DA9211_BUCKB_MODE_AUTO 0x03
+#define DA9211_BUCKB_UP_CTRL_SHIFT 2
+#define DA9211_BUCKB_UP_CTRL_MASK 0x1C
+#define DA9211_BUCKB_DOWN_CTRL_SHIFT 5
+#define DA9211_BUCKB_DOWN_CTRL_MASK 0xE0
+
+/* DA9211_REG_BUCK_CONF (addr=0xD3) */
+#define DA9211_PHASE_SEL_A_SHIFT 0
+#define DA9211_PHASE_SEL_A_MASK 0x03
+#define DA9211_PHASE_SEL_B_SHIFT 2
+#define DA9211_PHASE_SEL_B_MASK 0x04
+#define DA9211_PH_SH_EN_A_SHIFT 3
+#define DA9211_PH_SH_EN_A_MASK 0x08
+#define DA9211_PH_SH_EN_B_SHIFT 4
+#define DA9211_PH_SH_EN_B_MASK 0x10
+
+/* DA9211_REG_VBUCKA_MAX (addr=0xD5) */
+#define DA9211_VBUCKA_BASE_SHIFT 0
+#define DA9211_VBUCKA_BASE_MASK 0x7F
+
+/* DA9211_REG_VBUCKB_MAX (addr=0xD6) */
+#define DA9211_VBUCKB_BASE_SHIFT 0
+#define DA9211_VBUCKB_BASE_MASK 0x7F
+
+/* DA9211_REG_VBUCKA/B_A/B (addr=0xD7/0xD8/0xD9/0xDA) */
+#define DA9211_VBUCK_SHIFT 0
+#define DA9211_VBUCK_MASK 0x7F
+#define DA9211_VBUCK_BIAS 0
+#define DA9211_BUCK_SL 0x80
+
+/* DA9211_REG_INTERFACE (addr=0x105) */
+#define DA9211_IF_BASE_ADDR_SHIFT 4
+#define DA9211_IF_BASE_ADDR_MASK 0xF0
+
+/* DA9211_REG_CONFIG_E (addr=0x147) */
+#define DA9211_SLAVE_SEL 0x40
+
+#endif /* __DA9211_REGISTERS_H__ */
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 2e022aabd951..021d64d856bb 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -845,7 +845,6 @@ static struct lp872x_platform_data
struct device_node *np = dev->of_node;
struct lp872x_platform_data *pdata;
struct of_regulator_match *match;
- struct regulator_init_data *d;
int num_matches;
int count;
int i;
@@ -892,14 +891,6 @@ static struct lp872x_platform_data
pdata->regulator_data[i].id =
(enum lp872x_regulator_id)match[i].driver_data;
pdata->regulator_data[i].init_data = match[i].init_data;
-
- /* Operation mode configuration for buck/buck1/buck2 */
- if (strncmp(match[i].name, "buck", 4))
- continue;
-
- d = pdata->regulator_data[i].init_data;
- d->constraints.valid_modes_mask |= LP872X_VALID_OPMODE;
- d->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
}
out:
return pdata;
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 785a25e9a437..4a415d4ee463 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -339,22 +339,18 @@ static int lp8755_regulator_init(struct lp8755_chip *pchip)
rconfig.init_data = pdata->buck_data[buck_num];
rconfig.of_node = pchip->dev->of_node;
pchip->rdev[buck_num] =
- regulator_register(&lp8755_regulators[buck_num], &rconfig);
+ devm_regulator_register(pchip->dev,
+ &lp8755_regulators[buck_num], &rconfig);
if (IS_ERR(pchip->rdev[buck_num])) {
ret = PTR_ERR(pchip->rdev[buck_num]);
pchip->rdev[buck_num] = NULL;
dev_err(pchip->dev, "regulator init failed: buck %d\n",
buck_num);
- goto err_buck;
+ return ret;
}
}
return 0;
-
-err_buck:
- for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
- regulator_unregister(pchip->rdev[icnt]);
- return ret;
}
static irqreturn_t lp8755_irq_handler(int irq, void *data)
@@ -490,23 +486,19 @@ static int lp8755_probe(struct i2c_client *client,
ret = lp8755_regulator_init(pchip);
if (ret < 0) {
dev_err(&client->dev, "fail to initialize regulators\n");
- goto err_regulator;
+ goto err;
}
pchip->irq = client->irq;
ret = lp8755_int_config(pchip);
if (ret < 0) {
dev_err(&client->dev, "fail to irq config\n");
- goto err_irq;
+ goto err;
}
return ret;
-err_irq:
- for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++)
- regulator_unregister(pchip->rdev[icnt]);
-
-err_regulator:
+err:
/* output disable */
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
lp8755_write(pchip, icnt, 0x00);
@@ -519,9 +511,6 @@ static int lp8755_remove(struct i2c_client *client)
int icnt;
struct lp8755_chip *pchip = i2c_get_clientdata(client);
- for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++)
- regulator_unregister(pchip->rdev[icnt]);
-
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
lp8755_write(pchip, icnt, 0x00);
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index c8105182b8b8..c756955bfcc5 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -377,7 +377,7 @@ static bool ltc3589_volatile_reg(struct device *dev, unsigned int reg)
return false;
}
-struct reg_default ltc3589_reg_defaults[] = {
+static struct reg_default ltc3589_reg_defaults[] = {
{ LTC3589_SCR1, 0x00 },
{ LTC3589_OVEN, 0x00 },
{ LTC3589_SCR2, 0x00 },
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
index 653a58b49cdf..c67ff05fc1dd 100644
--- a/drivers/regulator/max77693.c
+++ b/drivers/regulator/max77693.c
@@ -31,6 +31,7 @@
#include <linux/mfd/max77693.h>
#include <linux/mfd/max77693-private.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/regmap.h>
#define CHGIN_ILIM_STEP_20mA 20000
@@ -39,9 +40,9 @@
static int max77693_chg_is_enabled(struct regulator_dev *rdev)
{
int ret;
- u8 val;
+ unsigned int val;
- ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val);
+ ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret)
return ret;
@@ -57,12 +58,11 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
{
unsigned int chg_min_uA = rdev->constraints->min_uA;
unsigned int chg_max_uA = rdev->constraints->max_uA;
- u8 reg, sel;
+ unsigned int reg, sel;
unsigned int val;
int ret;
- ret = max77693_read_reg(rdev->regmap,
- MAX77693_CHG_REG_CHG_CNFG_09, &reg);
+ ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, &reg);
if (ret < 0)
return ret;
@@ -96,7 +96,7 @@ static int max77693_chg_set_current_limit(struct regulator_dev *rdev,
/* the first four codes for charger current are all 60mA */
sel += 3;
- return max77693_write_reg(rdev->regmap,
+ return regmap_write(rdev->regmap,
MAX77693_CHG_REG_CHG_CNFG_09, sel);
}
/* end of CHARGER regulator ops */
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index c2792f0271ab..f7f9efcfedb7 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -229,7 +229,6 @@ static int max8952_pmic_probe(struct i2c_client *client,
config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
rdev = devm_regulator_register(&client->dev, &regulator, &config);
-
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&client->dev, "regulator init failed (%d)\n", ret);
@@ -241,21 +240,19 @@ static int max8952_pmic_probe(struct i2c_client *client,
if (gpio_is_valid(pdata->gpio_vid0) &&
gpio_is_valid(pdata->gpio_vid1)) {
- if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
- gpio_direction_output(pdata->gpio_vid0,
- (pdata->default_mode) & 0x1);
- else
+ unsigned long gpio_flags;
+
+ gpio_flags = max8952->vid0 ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ if (devm_gpio_request_one(&client->dev, pdata->gpio_vid0,
+ gpio_flags, "MAX8952 VID0"))
err = 1;
- if (!gpio_request(pdata->gpio_vid1, "MAX8952 VID1"))
- gpio_direction_output(pdata->gpio_vid1,
- (pdata->default_mode >> 1) & 0x1);
- else {
- if (!err)
- gpio_free(pdata->gpio_vid0);
+ gpio_flags = max8952->vid1 ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ if (devm_gpio_request_one(&client->dev, pdata->gpio_vid1,
+ gpio_flags, "MAX8952 VID1"))
err = 2;
- }
-
} else
err = 3;
@@ -314,16 +311,6 @@ static int max8952_pmic_probe(struct i2c_client *client,
return 0;
}
-static int max8952_pmic_remove(struct i2c_client *client)
-{
- struct max8952_data *max8952 = i2c_get_clientdata(client);
- struct max8952_platform_data *pdata = max8952->pdata;
-
- gpio_free(pdata->gpio_vid0);
- gpio_free(pdata->gpio_vid1);
- return 0;
-}
-
static const struct i2c_device_id max8952_ids[] = {
{ "max8952", 0 },
{ },
@@ -332,7 +319,6 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
static struct i2c_driver max8952_pmic_driver = {
.probe = max8952_pmic_probe,
- .remove = max8952_pmic_remove,
.driver = {
.name = "max8952",
.of_match_table = of_match_ptr(max8952_dt_match),
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 05b971726ffa..afba024953e1 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -33,17 +33,12 @@ static int mc13xxx_regulator_enable(struct regulator_dev *rdev)
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
- int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
- mc13xxx_lock(priv->mc13xxx);
- ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
- mc13xxx_regulators[id].enable_bit,
- mc13xxx_regulators[id].enable_bit);
- mc13xxx_unlock(priv->mc13xxx);
-
- return ret;
+ return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
+ mc13xxx_regulators[id].enable_bit,
+ mc13xxx_regulators[id].enable_bit);
}
static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
@@ -51,16 +46,11 @@ static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
- int ret;
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
- mc13xxx_lock(priv->mc13xxx);
- ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
- mc13xxx_regulators[id].enable_bit, 0);
- mc13xxx_unlock(priv->mc13xxx);
-
- return ret;
+ return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
+ mc13xxx_regulators[id].enable_bit, 0);
}
static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
@@ -70,10 +60,7 @@ static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
int ret, id = rdev_get_id(rdev);
unsigned int val;
- mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
- mc13xxx_unlock(priv->mc13xxx);
-
if (ret)
return ret;
@@ -86,15 +73,10 @@ static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
int id = rdev_get_id(rdev);
- int ret;
- mc13xxx_lock(priv->mc13xxx);
- ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
- mc13xxx_regulators[id].vsel_mask,
- selector << mc13xxx_regulators[id].vsel_shift);
- mc13xxx_unlock(priv->mc13xxx);
-
- return ret;
+ return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
+ mc13xxx_regulators[id].vsel_mask,
+ selector << mc13xxx_regulators[id].vsel_shift);
}
static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
@@ -106,11 +88,8 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
- mc13xxx_lock(priv->mc13xxx);
ret = mc13xxx_reg_read(priv->mc13xxx,
mc13xxx_regulators[id].vsel_reg, &val);
- mc13xxx_unlock(priv->mc13xxx);
-
if (ret)
return ret;
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h
index 06c8903f182a..2ab9bfd93b4e 100644
--- a/drivers/regulator/mc13xxx.h
+++ b/drivers/regulator/mc13xxx.h
@@ -21,7 +21,6 @@ struct mc13xxx_regulator {
int vsel_reg;
int vsel_shift;
int vsel_mask;
- int hi_bit;
};
struct mc13xxx_regulator_priv {
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 93b4ad842901..a7ce34d1b5f2 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -27,15 +27,6 @@
#include <linux/of_platform.h>
#include <linux/regulator/of_regulator.h>
-struct regs_info {
- char *name;
- char *sname;
- u8 vsel_addr;
- u8 ctrl_addr;
- u8 tstep_addr;
- int sleep_id;
-};
-
static const struct regulator_linear_range smps_low_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0),
@@ -50,7 +41,7 @@ static const struct regulator_linear_range smps_high_ranges[] = {
REGULATOR_LINEAR_RANGE(3300000, 0x7A, 0x7f, 0),
};
-static const struct regs_info palmas_regs_info[] = {
+static struct palmas_regs_info palmas_generic_regs_info[] = {
{
.name = "SMPS12",
.sname = "smps1-in",
@@ -236,6 +227,153 @@ static const struct regs_info palmas_regs_info[] = {
},
};
+static struct palmas_regs_info tps65917_regs_info[] = {
+ {
+ .name = "SMPS1",
+ .sname = "smps1-in",
+ .vsel_addr = TPS65917_SMPS1_VOLTAGE,
+ .ctrl_addr = TPS65917_SMPS1_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS1,
+ },
+ {
+ .name = "SMPS2",
+ .sname = "smps2-in",
+ .vsel_addr = TPS65917_SMPS2_VOLTAGE,
+ .ctrl_addr = TPS65917_SMPS2_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS2,
+ },
+ {
+ .name = "SMPS3",
+ .sname = "smps3-in",
+ .vsel_addr = TPS65917_SMPS3_VOLTAGE,
+ .ctrl_addr = TPS65917_SMPS3_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS3,
+ },
+ {
+ .name = "SMPS4",
+ .sname = "smps4-in",
+ .vsel_addr = TPS65917_SMPS4_VOLTAGE,
+ .ctrl_addr = TPS65917_SMPS4_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS4,
+ },
+ {
+ .name = "SMPS5",
+ .sname = "smps5-in",
+ .vsel_addr = TPS65917_SMPS5_VOLTAGE,
+ .ctrl_addr = TPS65917_SMPS5_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS5,
+ },
+ {
+ .name = "LDO1",
+ .sname = "ldo1-in",
+ .vsel_addr = TPS65917_LDO1_VOLTAGE,
+ .ctrl_addr = TPS65917_LDO1_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_LDO1,
+ },
+ {
+ .name = "LDO2",
+ .sname = "ldo2-in",
+ .vsel_addr = TPS65917_LDO2_VOLTAGE,
+ .ctrl_addr = TPS65917_LDO2_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_LDO2,
+ },
+ {
+ .name = "LDO3",
+ .sname = "ldo3-in",
+ .vsel_addr = TPS65917_LDO3_VOLTAGE,
+ .ctrl_addr = TPS65917_LDO3_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_LDO3,
+ },
+ {
+ .name = "LDO4",
+ .sname = "ldo4-in",
+ .vsel_addr = TPS65917_LDO4_VOLTAGE,
+ .ctrl_addr = TPS65917_LDO4_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_LDO4,
+ },
+ {
+ .name = "LDO5",
+ .sname = "ldo5-in",
+ .vsel_addr = TPS65917_LDO5_VOLTAGE,
+ .ctrl_addr = TPS65917_LDO5_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_LDO5,
+ },
+ {
+ .name = "REGEN1",
+ .ctrl_addr = TPS65917_REGEN1_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_REGEN1,
+ },
+ {
+ .name = "REGEN2",
+ .ctrl_addr = TPS65917_REGEN2_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_REGEN2,
+ },
+ {
+ .name = "REGEN3",
+ .ctrl_addr = TPS65917_REGEN3_CTRL,
+ .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_REGEN3,
+ },
+};
+
+#define EXTERNAL_REQUESTOR(_id, _offset, _pos) \
+ [PALMAS_EXTERNAL_REQSTR_ID_##_id] = { \
+ .id = PALMAS_EXTERNAL_REQSTR_ID_##_id, \
+ .reg_offset = _offset, \
+ .bit_pos = _pos, \
+ }
+
+static struct palmas_sleep_requestor_info palma_sleep_req_info[] = {
+ EXTERNAL_REQUESTOR(REGEN1, 0, 0),
+ EXTERNAL_REQUESTOR(REGEN2, 0, 1),
+ EXTERNAL_REQUESTOR(SYSEN1, 0, 2),
+ EXTERNAL_REQUESTOR(SYSEN2, 0, 3),
+ EXTERNAL_REQUESTOR(CLK32KG, 0, 4),
+ EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5),
+ EXTERNAL_REQUESTOR(REGEN3, 0, 6),
+ EXTERNAL_REQUESTOR(SMPS12, 1, 0),
+ EXTERNAL_REQUESTOR(SMPS3, 1, 1),
+ EXTERNAL_REQUESTOR(SMPS45, 1, 2),
+ EXTERNAL_REQUESTOR(SMPS6, 1, 3),
+ EXTERNAL_REQUESTOR(SMPS7, 1, 4),
+ EXTERNAL_REQUESTOR(SMPS8, 1, 5),
+ EXTERNAL_REQUESTOR(SMPS9, 1, 6),
+ EXTERNAL_REQUESTOR(SMPS10, 1, 7),
+ EXTERNAL_REQUESTOR(LDO1, 2, 0),
+ EXTERNAL_REQUESTOR(LDO2, 2, 1),
+ EXTERNAL_REQUESTOR(LDO3, 2, 2),
+ EXTERNAL_REQUESTOR(LDO4, 2, 3),
+ EXTERNAL_REQUESTOR(LDO5, 2, 4),
+ EXTERNAL_REQUESTOR(LDO6, 2, 5),
+ EXTERNAL_REQUESTOR(LDO7, 2, 6),
+ EXTERNAL_REQUESTOR(LDO8, 2, 7),
+ EXTERNAL_REQUESTOR(LDO9, 3, 0),
+ EXTERNAL_REQUESTOR(LDOLN, 3, 1),
+ EXTERNAL_REQUESTOR(LDOUSB, 3, 2),
+};
+
+#define EXTERNAL_REQUESTOR_TPS65917(_id, _offset, _pos) \
+ [TPS65917_EXTERNAL_REQSTR_ID_##_id] = { \
+ .id = TPS65917_EXTERNAL_REQSTR_ID_##_id, \
+ .reg_offset = _offset, \
+ .bit_pos = _pos, \
+ }
+
+static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = {
+ EXTERNAL_REQUESTOR_TPS65917(REGEN1, 0, 0),
+ EXTERNAL_REQUESTOR_TPS65917(REGEN2, 0, 1),
+ EXTERNAL_REQUESTOR_TPS65917(REGEN3, 0, 6),
+ EXTERNAL_REQUESTOR_TPS65917(SMPS1, 1, 0),
+ EXTERNAL_REQUESTOR_TPS65917(SMPS2, 1, 1),
+ EXTERNAL_REQUESTOR_TPS65917(SMPS3, 1, 2),
+ EXTERNAL_REQUESTOR_TPS65917(SMPS4, 1, 3),
+ EXTERNAL_REQUESTOR_TPS65917(SMPS5, 1, 4),
+ EXTERNAL_REQUESTOR_TPS65917(LDO1, 2, 0),
+ EXTERNAL_REQUESTOR_TPS65917(LDO2, 2, 1),
+ EXTERNAL_REQUESTOR_TPS65917(LDO3, 2, 2),
+ EXTERNAL_REQUESTOR_TPS65917(LDO4, 2, 3),
+ EXTERNAL_REQUESTOR_TPS65917(LDO5, 2, 4),
+};
+
static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
#define SMPS_CTRL_MODE_OFF 0x00
@@ -296,12 +434,15 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
{
- struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
unsigned int reg;
bool rail_enable = true;
- palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+ palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, &reg);
+
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
if (reg == SMPS_CTRL_MODE_OFF)
@@ -323,8 +464,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
pmic->current_reg_mode[id] = reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
if (rail_enable)
- palmas_smps_write(pmic->palmas,
- palmas_regs_info[id].ctrl_addr, reg);
+ palmas_smps_write(pmic->palmas, rinfo->ctrl_addr, reg);
/* Switch the enable value to ensure this is used for enable */
pmic->desc[id].enable_val = pmic->current_reg_mode[id];
@@ -355,10 +495,11 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev)
static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay)
{
- struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
+ struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
+ struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
unsigned int reg = 0;
- unsigned int addr = palmas_regs_info[id].tstep_addr;
int ret;
/* SMPS3 and SMPS7 do not have tstep_addr setting */
@@ -377,7 +518,7 @@ static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
else
reg = 1;
- ret = palmas_smps_write(pmic->palmas, addr, reg);
+ ret = palmas_smps_write(pmic->palmas, rinfo->tstep_addr, reg);
if (ret < 0) {
dev_err(pmic->palmas->dev, "TSTEP write failed: %d\n", ret);
return ret;
@@ -424,13 +565,37 @@ static struct regulator_ops palmas_ops_smps10 = {
.get_bypass = regulator_get_bypass_regmap,
};
+static struct regulator_ops tps65917_ops_smps = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_mode = palmas_set_mode_smps,
+ .get_mode = palmas_get_mode_smps,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops tps65917_ops_ext_control_smps = {
+ .set_mode = palmas_set_mode_smps,
+ .get_mode = palmas_get_mode_smps,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
static int palmas_is_enabled_ldo(struct regulator_dev *dev)
{
- struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
+ struct palmas_pmic *pmic = rdev_get_drvdata(dev);
+ struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
unsigned int reg;
- palmas_ldo_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
+ palmas_ldo_read(pmic->palmas, rinfo->ctrl_addr, &reg);
reg &= PALMAS_LDO1_CTRL_STATUS;
@@ -463,14 +628,26 @@ static struct regulator_ops palmas_ops_extreg = {
static struct regulator_ops palmas_ops_ext_control_extreg = {
};
+static struct regulator_ops tps65917_ops_ldo = {
+ .is_enabled = palmas_is_enabled_ldo,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
static int palmas_regulator_config_external(struct palmas *palmas, int id,
struct palmas_reg_init *reg_init)
{
- int sleep_id = palmas_regs_info[id].sleep_id;
+ struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
int ret;
- ret = palmas_ext_control_req_config(palmas, sleep_id,
- reg_init->roof_floor, true);
+ ret = palmas_ext_control_req_config(palmas, rinfo->sleep_id,
+ reg_init->roof_floor, true);
if (ret < 0)
dev_err(palmas->dev,
"Ext control config for regulator %d failed %d\n",
@@ -488,10 +665,10 @@ static int palmas_smps_init(struct palmas *palmas, int id,
struct palmas_reg_init *reg_init)
{
unsigned int reg;
- unsigned int addr;
int ret;
-
- addr = palmas_regs_info[id].ctrl_addr;
+ struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
+ unsigned int addr = rinfo->ctrl_addr;
ret = palmas_smps_read(palmas, addr, &reg);
if (ret)
@@ -526,12 +703,11 @@ static int palmas_smps_init(struct palmas *palmas, int id,
if (ret)
return ret;
- if (palmas_regs_info[id].vsel_addr && reg_init->vsel) {
- addr = palmas_regs_info[id].vsel_addr;
+ if (rinfo->vsel_addr && reg_init->vsel) {
reg = reg_init->vsel;
- ret = palmas_smps_write(palmas, addr, reg);
+ ret = palmas_smps_write(palmas, rinfo->vsel_addr, reg);
if (ret)
return ret;
}
@@ -539,7 +715,6 @@ static int palmas_smps_init(struct palmas *palmas, int id,
if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
(id != PALMAS_REG_SMPS10_OUT2)) {
/* Enable externally controlled regulator */
- addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_smps_read(palmas, addr, &reg);
if (ret < 0)
return ret;
@@ -561,8 +736,10 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
unsigned int reg;
unsigned int addr;
int ret;
+ struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
- addr = palmas_regs_info[id].ctrl_addr;
+ addr = rinfo->ctrl_addr;
ret = palmas_ldo_read(palmas, addr, &reg);
if (ret)
@@ -584,7 +761,6 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
if (reg_init->roof_floor) {
/* Enable externally controlled regulator */
- addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
PALMAS_LDO1_CTRL_MODE_ACTIVE);
@@ -605,8 +781,10 @@ static int palmas_extreg_init(struct palmas *palmas, int id,
unsigned int addr;
int ret;
unsigned int val = 0;
+ struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
- addr = palmas_regs_info[id].ctrl_addr;
+ addr = rinfo->ctrl_addr;
if (reg_init->mode_sleep)
val = PALMAS_REGEN1_CTRL_MODE_SLEEP;
@@ -621,7 +799,6 @@ static int palmas_extreg_init(struct palmas *palmas, int id,
if (reg_init->roof_floor) {
/* Enable externally controlled regulator */
- addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
PALMAS_REGEN1_CTRL_MODE_ACTIVE);
@@ -641,8 +818,11 @@ static void palmas_enable_ldo8_track(struct palmas *palmas)
unsigned int reg;
unsigned int addr;
int ret;
+ struct palmas_pmic_driver_data *ddata = palmas->pmic_ddata;
+ struct palmas_regs_info *rinfo;
- addr = palmas_regs_info[PALMAS_REG_LDO8].ctrl_addr;
+ rinfo = &ddata->palmas_regs_info[PALMAS_REG_LDO8];
+ addr = rinfo->ctrl_addr;
ret = palmas_ldo_read(palmas, addr, &reg);
if (ret) {
@@ -661,7 +841,7 @@ static void palmas_enable_ldo8_track(struct palmas *palmas)
* output is defined by the LDO8_VOLTAGE.VSEL register divided by two,
* and can be set from 0.45 to 1.65 V.
*/
- addr = palmas_regs_info[PALMAS_REG_LDO8].vsel_addr;
+ addr = rinfo->vsel_addr;
ret = palmas_ldo_read(palmas, addr, &reg);
if (ret) {
dev_err(palmas->dev, "Error in reading ldo8 voltage reg\n");
@@ -676,169 +856,230 @@ static void palmas_enable_ldo8_track(struct palmas *palmas)
return;
}
-static struct of_regulator_match palmas_matches[] = {
- { .name = "smps12", },
- { .name = "smps123", },
- { .name = "smps3", },
- { .name = "smps45", },
- { .name = "smps457", },
- { .name = "smps6", },
- { .name = "smps7", },
- { .name = "smps8", },
- { .name = "smps9", },
- { .name = "smps10_out2", },
- { .name = "smps10_out1", },
- { .name = "ldo1", },
- { .name = "ldo2", },
- { .name = "ldo3", },
- { .name = "ldo4", },
- { .name = "ldo5", },
- { .name = "ldo6", },
- { .name = "ldo7", },
- { .name = "ldo8", },
- { .name = "ldo9", },
- { .name = "ldoln", },
- { .name = "ldousb", },
- { .name = "regen1", },
- { .name = "regen2", },
- { .name = "regen3", },
- { .name = "sysen1", },
- { .name = "sysen2", },
-};
-
-static void palmas_dt_to_pdata(struct device *dev,
- struct device_node *node,
- struct palmas_pmic_platform_data *pdata)
+static int palmas_ldo_registration(struct palmas_pmic *pmic,
+ struct palmas_pmic_driver_data *ddata,
+ struct palmas_pmic_platform_data *pdata,
+ const char *pdev_name,
+ struct regulator_config config)
{
- struct device_node *regulators;
- u32 prop;
- int idx, ret;
+ int id, ret;
+ struct regulator_dev *rdev;
+ struct palmas_reg_init *reg_init;
+ struct palmas_regs_info *rinfo;
+ struct regulator_desc *desc;
- node = of_node_get(node);
- regulators = of_get_child_by_name(node, "regulators");
- if (!regulators) {
- dev_info(dev, "regulator node not found\n");
- return;
- }
+ for (id = ddata->ldo_begin; id < ddata->max_reg; id++) {
+ if (pdata && pdata->reg_init[id])
+ reg_init = pdata->reg_init[id];
+ else
+ reg_init = NULL;
- ret = of_regulator_match(dev, regulators, palmas_matches,
- PALMAS_NUM_REGS);
- of_node_put(regulators);
- if (ret < 0) {
- dev_err(dev, "Error parsing regulator init data: %d\n", ret);
- return;
- }
+ rinfo = &ddata->palmas_regs_info[id];
+ /* Miss out regulators which are not available due
+ * to alternate functions.
+ */
- for (idx = 0; idx < PALMAS_NUM_REGS; idx++) {
- if (!palmas_matches[idx].init_data ||
- !palmas_matches[idx].of_node)
- continue;
+ /* Register the regulators */
+ desc = &pmic->desc[id];
+ desc->name = rinfo->name;
+ desc->id = id;
+ desc->type = REGULATOR_VOLTAGE;
+ desc->owner = THIS_MODULE;
- pdata->reg_data[idx] = palmas_matches[idx].init_data;
+ if (id < PALMAS_REG_REGEN1) {
+ desc->n_voltages = PALMAS_LDO_NUM_VOLTAGES;
+ if (reg_init && reg_init->roof_floor)
+ desc->ops = &palmas_ops_ext_control_ldo;
+ else
+ desc->ops = &palmas_ops_ldo;
+ desc->min_uV = 900000;
+ desc->uV_step = 50000;
+ desc->linear_min_sel = 1;
+ desc->enable_time = 500;
+ desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+ rinfo->vsel_addr);
+ desc->vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
+ desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
- pdata->reg_init[idx] = devm_kzalloc(dev,
- sizeof(struct palmas_reg_init), GFP_KERNEL);
+ /* Check if LDO8 is in tracking mode or not */
+ if (pdata && (id == PALMAS_REG_LDO8) &&
+ pdata->enable_ldo8_tracking) {
+ palmas_enable_ldo8_track(pmic->palmas);
+ desc->min_uV = 450000;
+ desc->uV_step = 25000;
+ }
- pdata->reg_init[idx]->warm_reset =
- of_property_read_bool(palmas_matches[idx].of_node,
- "ti,warm-reset");
+ /* LOD6 in vibrator mode will have enable time 2000us */
+ if (pdata && pdata->ldo6_vibrator &&
+ (id == PALMAS_REG_LDO6))
+ desc->enable_time = 2000;
+ } else {
+ desc->n_voltages = 1;
+ if (reg_init && reg_init->roof_floor)
+ desc->ops = &palmas_ops_ext_control_extreg;
+ else
+ desc->ops = &palmas_ops_extreg;
+ desc->enable_reg =
+ PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_REGEN1_CTRL_MODE_ACTIVE;
+ }
- ret = of_property_read_u32(palmas_matches[idx].of_node,
- "ti,roof-floor", &prop);
- /* EINVAL: Property not found */
- if (ret != -EINVAL) {
- int econtrol;
+ if (pdata)
+ config.init_data = pdata->reg_data[id];
+ else
+ config.init_data = NULL;
- /* use default value, when no value is specified */
- econtrol = PALMAS_EXT_CONTROL_NSLEEP;
- if (!ret) {
- switch (prop) {
- case 1:
- econtrol = PALMAS_EXT_CONTROL_ENABLE1;
- break;
- case 2:
- econtrol = PALMAS_EXT_CONTROL_ENABLE2;
- break;
- case 3:
- econtrol = PALMAS_EXT_CONTROL_NSLEEP;
- break;
- default:
- WARN_ON(1);
- dev_warn(dev,
- "%s: Invalid roof-floor option: %u\n",
- palmas_matches[idx].name, prop);
- break;
- }
- }
- pdata->reg_init[idx]->roof_floor = econtrol;
- }
+ desc->supply_name = rinfo->sname;
+ config.of_node = ddata->palmas_matches[id].of_node;
- ret = of_property_read_u32(palmas_matches[idx].of_node,
- "ti,mode-sleep", &prop);
- if (!ret)
- pdata->reg_init[idx]->mode_sleep = prop;
+ rdev = devm_regulator_register(pmic->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(pmic->dev,
+ "failed to register %s regulator\n",
+ pdev_name);
+ return PTR_ERR(rdev);
+ }
- ret = of_property_read_bool(palmas_matches[idx].of_node,
- "ti,smps-range");
- if (ret)
- pdata->reg_init[idx]->vsel =
- PALMAS_SMPS12_VOLTAGE_RANGE;
+ /* Save regulator for cleanup */
+ pmic->rdev[id] = rdev;
- if (idx == PALMAS_REG_LDO8)
- pdata->enable_ldo8_tracking = of_property_read_bool(
- palmas_matches[idx].of_node,
- "ti,enable-ldo8-tracking");
+ /* Initialise sleep/init values from platform data */
+ if (pdata) {
+ reg_init = pdata->reg_init[id];
+ if (reg_init) {
+ if (id <= ddata->ldo_end)
+ ret = palmas_ldo_init(pmic->palmas, id,
+ reg_init);
+ else
+ ret = palmas_extreg_init(pmic->palmas,
+ id, reg_init);
+ if (ret)
+ return ret;
+ }
+ }
}
- pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
+ return 0;
}
-
-static int palmas_regulators_probe(struct platform_device *pdev)
+static int tps65917_ldo_registration(struct palmas_pmic *pmic,
+ struct palmas_pmic_driver_data *ddata,
+ struct palmas_pmic_platform_data *pdata,
+ const char *pdev_name,
+ struct regulator_config config)
{
- struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
- struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct device_node *node = pdev->dev.of_node;
+ int id, ret;
struct regulator_dev *rdev;
- struct regulator_config config = { };
- struct palmas_pmic *pmic;
struct palmas_reg_init *reg_init;
- int id = 0, ret;
- unsigned int addr, reg;
+ struct palmas_regs_info *rinfo;
+ struct regulator_desc *desc;
- if (node && !pdata) {
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ for (id = ddata->ldo_begin; id < ddata->max_reg; id++) {
+ if (pdata && pdata->reg_init[id])
+ reg_init = pdata->reg_init[id];
+ else
+ reg_init = NULL;
- if (!pdata)
- return -ENOMEM;
+ /* Miss out regulators which are not available due
+ * to alternate functions.
+ */
+ rinfo = &ddata->palmas_regs_info[id];
- palmas_dt_to_pdata(&pdev->dev, node, pdata);
- }
+ /* Register the regulators */
+ desc = &pmic->desc[id];
+ desc->name = rinfo->name;
+ desc->id = id;
+ desc->type = REGULATOR_VOLTAGE;
+ desc->owner = THIS_MODULE;
+
+ if (id < TPS65917_REG_REGEN1) {
+ desc->n_voltages = PALMAS_LDO_NUM_VOLTAGES;
+ if (reg_init && reg_init->roof_floor)
+ desc->ops = &palmas_ops_ext_control_ldo;
+ else
+ desc->ops = &tps65917_ops_ldo;
+ desc->min_uV = 900000;
+ desc->uV_step = 50000;
+ desc->linear_min_sel = 1;
+ desc->enable_time = 500;
+ desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+ rinfo->vsel_addr);
+ desc->vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
+ desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
+ /*
+ * To be confirmed. Discussion on going with PMIC Team.
+ * It is of the order of ~60mV/uS.
+ */
+ desc->ramp_delay = 2500;
+ } else {
+ desc->n_voltages = 1;
+ if (reg_init && reg_init->roof_floor)
+ desc->ops = &palmas_ops_ext_control_extreg;
+ else
+ desc->ops = &palmas_ops_extreg;
+ desc->enable_reg =
+ PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_REGEN1_CTRL_MODE_ACTIVE;
+ }
- pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
- return -ENOMEM;
+ if (pdata)
+ config.init_data = pdata->reg_data[id];
+ else
+ config.init_data = NULL;
- pmic->dev = &pdev->dev;
- pmic->palmas = palmas;
- palmas->pmic = pmic;
- platform_set_drvdata(pdev, pmic);
+ desc->supply_name = rinfo->sname;
+ config.of_node = ddata->palmas_matches[id].of_node;
- ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
- if (ret)
- return ret;
+ rdev = devm_regulator_register(pmic->dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(pmic->dev,
+ "failed to register %s regulator\n",
+ pdev_name);
+ return PTR_ERR(rdev);
+ }
- if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)
- pmic->smps123 = 1;
+ /* Save regulator for cleanup */
+ pmic->rdev[id] = rdev;
- if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
- pmic->smps457 = 1;
+ /* Initialise sleep/init values from platform data */
+ if (pdata) {
+ reg_init = pdata->reg_init[id];
+ if (reg_init) {
+ if (id < TPS65917_REG_REGEN1)
+ ret = palmas_ldo_init(pmic->palmas,
+ id, reg_init);
+ else
+ ret = palmas_extreg_init(pmic->palmas,
+ id, reg_init);
+ if (ret)
+ return ret;
+ }
+ }
+ }
- config.regmap = palmas->regmap[REGULATOR_SLAVE];
- config.dev = &pdev->dev;
- config.driver_data = pmic;
+ return 0;
+}
+
+static int palmas_smps_registration(struct palmas_pmic *pmic,
+ struct palmas_pmic_driver_data *ddata,
+ struct palmas_pmic_platform_data *pdata,
+ const char *pdev_name,
+ struct regulator_config config)
+{
+ int id, ret;
+ unsigned int addr, reg;
+ struct regulator_dev *rdev;
+ struct palmas_reg_init *reg_init;
+ struct palmas_regs_info *rinfo;
+ struct regulator_desc *desc;
- for (id = 0; id < PALMAS_REG_LDO1; id++) {
+ for (id = ddata->smps_start; id <= ddata->smps_end; id++) {
bool ramp_delay_support = false;
/*
@@ -872,30 +1113,31 @@ static int palmas_regulators_probe(struct platform_device *pdev)
break;
case PALMAS_REG_SMPS10_OUT1:
case PALMAS_REG_SMPS10_OUT2:
- if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST))
+ if (!PALMAS_PMIC_HAS(pmic->palmas, SMPS10_BOOST))
continue;
}
+ rinfo = &ddata->palmas_regs_info[id];
+ desc = &pmic->desc[id];
if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8))
ramp_delay_support = true;
if (ramp_delay_support) {
- addr = palmas_regs_info[id].tstep_addr;
+ addr = rinfo->tstep_addr;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret < 0) {
- dev_err(&pdev->dev,
+ dev_err(pmic->dev,
"reading TSTEP reg failed: %d\n", ret);
return ret;
}
- pmic->desc[id].ramp_delay =
- palmas_smps_ramp_delay[reg & 0x3];
- pmic->ramp_delay[id] = pmic->desc[id].ramp_delay;
+ desc->ramp_delay = palmas_smps_ramp_delay[reg & 0x3];
+ pmic->ramp_delay[id] = desc->ramp_delay;
}
/* Initialise sleep/init values from platform data */
if (pdata && pdata->reg_init[id]) {
reg_init = pdata->reg_init[id];
- ret = palmas_smps_init(palmas, id, reg_init);
+ ret = palmas_smps_init(pmic->palmas, id, reg_init);
if (ret)
return ret;
} else {
@@ -903,31 +1145,28 @@ static int palmas_regulators_probe(struct platform_device *pdev)
}
/* Register the regulators */
- pmic->desc[id].name = palmas_regs_info[id].name;
- pmic->desc[id].id = id;
+ desc->name = rinfo->name;
+ desc->id = id;
switch (id) {
case PALMAS_REG_SMPS10_OUT1:
case PALMAS_REG_SMPS10_OUT2:
- pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
- pmic->desc[id].ops = &palmas_ops_smps10;
- pmic->desc[id].vsel_reg =
- PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
- PALMAS_SMPS10_CTRL);
- pmic->desc[id].vsel_mask = SMPS10_VSEL;
- pmic->desc[id].enable_reg =
- PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
- PALMAS_SMPS10_CTRL);
+ desc->n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
+ desc->ops = &palmas_ops_smps10;
+ desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ PALMAS_SMPS10_CTRL);
+ desc->vsel_mask = SMPS10_VSEL;
+ desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ PALMAS_SMPS10_CTRL);
if (id == PALMAS_REG_SMPS10_OUT1)
- pmic->desc[id].enable_mask = SMPS10_SWITCH_EN;
+ desc->enable_mask = SMPS10_SWITCH_EN;
else
- pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
- pmic->desc[id].bypass_reg =
- PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
- PALMAS_SMPS10_CTRL);
- pmic->desc[id].bypass_mask = SMPS10_BYPASS_EN;
- pmic->desc[id].min_uV = 3750000;
- pmic->desc[id].uV_step = 1250000;
+ desc->enable_mask = SMPS10_BOOST_EN;
+ desc->bypass_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ PALMAS_SMPS10_CTRL);
+ desc->bypass_mask = SMPS10_BYPASS_EN;
+ desc->min_uV = 3750000;
+ desc->uV_step = 1250000;
break;
default:
/*
@@ -936,8 +1175,8 @@ static int palmas_regulators_probe(struct platform_device *pdev)
* otherwise we error in probe with unsupportable
* ranges. Read the current smps mode for later use.
*/
- addr = palmas_regs_info[id].vsel_addr;
- pmic->desc[id].n_linear_ranges = 3;
+ addr = rinfo->vsel_addr;
+ desc->n_linear_ranges = 3;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
@@ -945,56 +1184,50 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1;
if (pmic->range[id])
- pmic->desc[id].linear_ranges = smps_high_ranges;
+ desc->linear_ranges = smps_high_ranges;
else
- pmic->desc[id].linear_ranges = smps_low_ranges;
+ desc->linear_ranges = smps_low_ranges;
if (reg_init && reg_init->roof_floor)
- pmic->desc[id].ops =
- &palmas_ops_ext_control_smps;
+ desc->ops = &palmas_ops_ext_control_smps;
else
- pmic->desc[id].ops = &palmas_ops_smps;
- pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
- pmic->desc[id].vsel_reg =
- PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
- palmas_regs_info[id].vsel_addr);
- pmic->desc[id].vsel_mask =
- PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
+ desc->ops = &palmas_ops_smps;
+ desc->n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+ desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ rinfo->vsel_addr);
+ desc->vsel_mask = PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
/* Read the smps mode for later use. */
- addr = palmas_regs_info[id].ctrl_addr;
+ addr = rinfo->ctrl_addr;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
return ret;
pmic->current_reg_mode[id] = reg &
PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
- pmic->desc[id].enable_reg =
- PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
- palmas_regs_info[id].ctrl_addr);
- pmic->desc[id].enable_mask =
- PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+ desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
/* set_mode overrides this value */
- pmic->desc[id].enable_val = SMPS_CTRL_MODE_ON;
+ desc->enable_val = SMPS_CTRL_MODE_ON;
}
- pmic->desc[id].type = REGULATOR_VOLTAGE;
- pmic->desc[id].owner = THIS_MODULE;
+ desc->type = REGULATOR_VOLTAGE;
+ desc->owner = THIS_MODULE;
if (pdata)
config.init_data = pdata->reg_data[id];
else
config.init_data = NULL;
- pmic->desc[id].supply_name = palmas_regs_info[id].sname;
- config.of_node = palmas_matches[id].of_node;
+ desc->supply_name = rinfo->sname;
+ config.of_node = ddata->palmas_matches[id].of_node;
- rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
- &config);
+ rdev = devm_regulator_register(pmic->dev, desc, &config);
if (IS_ERR(rdev)) {
- dev_err(&pdev->dev,
+ dev_err(pmic->dev,
"failed to register %s regulator\n",
- pdev->name);
+ pdev_name);
return PTR_ERR(rdev);
}
@@ -1002,123 +1235,378 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->rdev[id] = rdev;
}
- /* Start this loop from the id left from previous loop */
- for (; id < PALMAS_NUM_REGS; id++) {
- if (pdata && pdata->reg_init[id])
+ return 0;
+}
+
+static int tps65917_smps_registration(struct palmas_pmic *pmic,
+ struct palmas_pmic_driver_data *ddata,
+ struct palmas_pmic_platform_data *pdata,
+ const char *pdev_name,
+ struct regulator_config config)
+{
+ int id, ret;
+ unsigned int addr, reg;
+ struct regulator_dev *rdev;
+ struct palmas_reg_init *reg_init;
+ struct palmas_regs_info *rinfo;
+ struct regulator_desc *desc;
+
+ for (id = ddata->smps_start; id <= ddata->smps_end; id++) {
+ /*
+ * Miss out regulators which are not available due
+ * to slaving configurations.
+ */
+ desc = &pmic->desc[id];
+ desc->n_linear_ranges = 3;
+ if ((id == TPS65917_REG_SMPS2) && pmic->smps12)
+ continue;
+
+ /* Initialise sleep/init values from platform data */
+ if (pdata && pdata->reg_init[id]) {
reg_init = pdata->reg_init[id];
- else
+ ret = palmas_smps_init(pmic->palmas, id, reg_init);
+ if (ret)
+ return ret;
+ } else {
reg_init = NULL;
+ }
+ rinfo = &ddata->palmas_regs_info[id];
- /* Miss out regulators which are not available due
- * to alternate functions.
+ /* Register the regulators */
+ desc->name = rinfo->name;
+ desc->id = id;
+
+ /*
+ * Read and store the RANGE bit for later use
+ * This must be done before regulator is probed,
+ * otherwise we error in probe with unsupportable
+ * ranges. Read the current smps mode for later use.
*/
+ addr = rinfo->vsel_addr;
- /* Register the regulators */
- pmic->desc[id].name = palmas_regs_info[id].name;
- pmic->desc[id].id = id;
- pmic->desc[id].type = REGULATOR_VOLTAGE;
- pmic->desc[id].owner = THIS_MODULE;
+ ret = palmas_smps_read(pmic->palmas, addr, &reg);
+ if (ret)
+ return ret;
+ if (reg & TPS65917_SMPS1_VOLTAGE_RANGE)
+ pmic->range[id] = 1;
- if (id < PALMAS_REG_REGEN1) {
- pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
- if (reg_init && reg_init->roof_floor)
- pmic->desc[id].ops =
- &palmas_ops_ext_control_ldo;
- else
- pmic->desc[id].ops = &palmas_ops_ldo;
- pmic->desc[id].min_uV = 900000;
- pmic->desc[id].uV_step = 50000;
- pmic->desc[id].linear_min_sel = 1;
- pmic->desc[id].enable_time = 500;
- pmic->desc[id].vsel_reg =
- PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
- palmas_regs_info[id].vsel_addr);
- pmic->desc[id].vsel_mask =
- PALMAS_LDO1_VOLTAGE_VSEL_MASK;
- pmic->desc[id].enable_reg =
- PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
- palmas_regs_info[id].ctrl_addr);
- pmic->desc[id].enable_mask =
- PALMAS_LDO1_CTRL_MODE_ACTIVE;
+ if (pmic->range[id])
+ desc->linear_ranges = smps_high_ranges;
+ else
+ desc->linear_ranges = smps_low_ranges;
- /* Check if LDO8 is in tracking mode or not */
- if (pdata && (id == PALMAS_REG_LDO8) &&
- pdata->enable_ldo8_tracking) {
- palmas_enable_ldo8_track(palmas);
- pmic->desc[id].min_uV = 450000;
- pmic->desc[id].uV_step = 25000;
- }
+ if (reg_init && reg_init->roof_floor)
+ desc->ops = &tps65917_ops_ext_control_smps;
+ else
+ desc->ops = &tps65917_ops_smps;
+ desc->n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+ desc->vsel_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ rinfo->vsel_addr);
+ desc->vsel_mask = PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
+ desc->ramp_delay = 2500;
+
+ /* Read the smps mode for later use. */
+ addr = rinfo->ctrl_addr;
+ ret = palmas_smps_read(pmic->palmas, addr, &reg);
+ if (ret)
+ return ret;
+ pmic->current_reg_mode[id] = reg &
+ PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+ desc->enable_reg = PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+ rinfo->ctrl_addr);
+ desc->enable_mask = PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+ /* set_mode overrides this value */
+ desc->enable_val = SMPS_CTRL_MODE_ON;
- /* LOD6 in vibrator mode will have enable time 2000us */
- if (pdata && pdata->ldo6_vibrator &&
- (id == PALMAS_REG_LDO6))
- pmic->desc[id].enable_time = 2000;
- } else {
- pmic->desc[id].n_voltages = 1;
- if (reg_init && reg_init->roof_floor)
- pmic->desc[id].ops =
- &palmas_ops_ext_control_extreg;
- else
- pmic->desc[id].ops = &palmas_ops_extreg;
- pmic->desc[id].enable_reg =
- PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
- palmas_regs_info[id].ctrl_addr);
- pmic->desc[id].enable_mask =
- PALMAS_REGEN1_CTRL_MODE_ACTIVE;
- }
+ desc->type = REGULATOR_VOLTAGE;
+ desc->owner = THIS_MODULE;
if (pdata)
config.init_data = pdata->reg_data[id];
else
config.init_data = NULL;
- pmic->desc[id].supply_name = palmas_regs_info[id].sname;
- config.of_node = palmas_matches[id].of_node;
+ desc->supply_name = rinfo->sname;
+ config.of_node = ddata->palmas_matches[id].of_node;
- rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
- &config);
+ rdev = devm_regulator_register(pmic->dev, desc, &config);
if (IS_ERR(rdev)) {
- dev_err(&pdev->dev,
+ dev_err(pmic->dev,
"failed to register %s regulator\n",
- pdev->name);
+ pdev_name);
return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
pmic->rdev[id] = rdev;
+ }
- /* Initialise sleep/init values from platform data */
- if (pdata) {
- reg_init = pdata->reg_init[id];
- if (reg_init) {
- if (id < PALMAS_REG_REGEN1)
- ret = palmas_ldo_init(palmas,
- id, reg_init);
- else
- ret = palmas_extreg_init(palmas,
- id, reg_init);
- if (ret)
- return ret;
+ return 0;
+}
+
+static struct of_regulator_match palmas_matches[] = {
+ { .name = "smps12", },
+ { .name = "smps123", },
+ { .name = "smps3", },
+ { .name = "smps45", },
+ { .name = "smps457", },
+ { .name = "smps6", },
+ { .name = "smps7", },
+ { .name = "smps8", },
+ { .name = "smps9", },
+ { .name = "smps10_out2", },
+ { .name = "smps10_out1", },
+ { .name = "ldo1", },
+ { .name = "ldo2", },
+ { .name = "ldo3", },
+ { .name = "ldo4", },
+ { .name = "ldo5", },
+ { .name = "ldo6", },
+ { .name = "ldo7", },
+ { .name = "ldo8", },
+ { .name = "ldo9", },
+ { .name = "ldoln", },
+ { .name = "ldousb", },
+ { .name = "regen1", },
+ { .name = "regen2", },
+ { .name = "regen3", },
+ { .name = "sysen1", },
+ { .name = "sysen2", },
+};
+
+static struct of_regulator_match tps65917_matches[] = {
+ { .name = "smps1", },
+ { .name = "smps2", },
+ { .name = "smps3", },
+ { .name = "smps4", },
+ { .name = "smps5", },
+ { .name = "ldo1", },
+ { .name = "ldo2", },
+ { .name = "ldo3", },
+ { .name = "ldo4", },
+ { .name = "ldo5", },
+ { .name = "regen1", },
+ { .name = "regen2", },
+ { .name = "regen3", },
+ { .name = "sysen1", },
+ { .name = "sysen2", },
+};
+
+static struct palmas_pmic_driver_data palmas_ddata = {
+ .smps_start = PALMAS_REG_SMPS12,
+ .smps_end = PALMAS_REG_SMPS10_OUT1,
+ .ldo_begin = PALMAS_REG_LDO1,
+ .ldo_end = PALMAS_REG_LDOUSB,
+ .max_reg = PALMAS_NUM_REGS,
+ .palmas_regs_info = palmas_generic_regs_info,
+ .palmas_matches = palmas_matches,
+ .sleep_req_info = palma_sleep_req_info,
+ .smps_register = palmas_smps_registration,
+ .ldo_register = palmas_ldo_registration,
+};
+
+static struct palmas_pmic_driver_data tps65917_ddata = {
+ .smps_start = TPS65917_REG_SMPS1,
+ .smps_end = TPS65917_REG_SMPS5,
+ .ldo_begin = TPS65917_REG_LDO1,
+ .ldo_end = TPS65917_REG_LDO5,
+ .max_reg = TPS65917_NUM_REGS,
+ .palmas_regs_info = tps65917_regs_info,
+ .palmas_matches = tps65917_matches,
+ .sleep_req_info = tps65917_sleep_req_info,
+ .smps_register = tps65917_smps_registration,
+ .ldo_register = tps65917_ldo_registration,
+};
+
+static void palmas_dt_to_pdata(struct device *dev,
+ struct device_node *node,
+ struct palmas_pmic_platform_data *pdata,
+ struct palmas_pmic_driver_data *ddata)
+{
+ struct device_node *regulators;
+ u32 prop;
+ int idx, ret;
+
+ node = of_node_get(node);
+ regulators = of_get_child_by_name(node, "regulators");
+ if (!regulators) {
+ dev_info(dev, "regulator node not found\n");
+ return;
+ }
+
+ ret = of_regulator_match(dev, regulators, ddata->palmas_matches,
+ ddata->max_reg);
+ of_node_put(regulators);
+ if (ret < 0) {
+ dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+ return;
+ }
+
+ for (idx = 0; idx < ddata->max_reg; idx++) {
+ if (!ddata->palmas_matches[idx].init_data ||
+ !ddata->palmas_matches[idx].of_node)
+ continue;
+
+ pdata->reg_data[idx] = ddata->palmas_matches[idx].init_data;
+
+ pdata->reg_init[idx] = devm_kzalloc(dev,
+ sizeof(struct palmas_reg_init), GFP_KERNEL);
+
+ pdata->reg_init[idx]->warm_reset =
+ of_property_read_bool(ddata->palmas_matches[idx].of_node,
+ "ti,warm-reset");
+
+ ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
+ "ti,roof-floor", &prop);
+ /* EINVAL: Property not found */
+ if (ret != -EINVAL) {
+ int econtrol;
+
+ /* use default value, when no value is specified */
+ econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+ if (!ret) {
+ switch (prop) {
+ case 1:
+ econtrol = PALMAS_EXT_CONTROL_ENABLE1;
+ break;
+ case 2:
+ econtrol = PALMAS_EXT_CONTROL_ENABLE2;
+ break;
+ case 3:
+ econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+ break;
+ default:
+ WARN_ON(1);
+ dev_warn(dev,
+ "%s: Invalid roof-floor option: %u\n",
+ palmas_matches[idx].name, prop);
+ break;
+ }
}
+ pdata->reg_init[idx]->roof_floor = econtrol;
}
- }
+ ret = of_property_read_u32(ddata->palmas_matches[idx].of_node,
+ "ti,mode-sleep", &prop);
+ if (!ret)
+ pdata->reg_init[idx]->mode_sleep = prop;
+
+ ret = of_property_read_bool(ddata->palmas_matches[idx].of_node,
+ "ti,smps-range");
+ if (ret)
+ pdata->reg_init[idx]->vsel =
+ PALMAS_SMPS12_VOLTAGE_RANGE;
- return 0;
+ if (idx == PALMAS_REG_LDO8)
+ pdata->enable_ldo8_tracking = of_property_read_bool(
+ ddata->palmas_matches[idx].of_node,
+ "ti,enable-ldo8-tracking");
+ }
+
+ pdata->ldo6_vibrator = of_property_read_bool(node, "ti,ldo6-vibrator");
}
-static const struct of_device_id of_palmas_match_tbl[] = {
- { .compatible = "ti,palmas-pmic", },
- { .compatible = "ti,twl6035-pmic", },
- { .compatible = "ti,twl6036-pmic", },
- { .compatible = "ti,twl6037-pmic", },
- { .compatible = "ti,tps65913-pmic", },
- { .compatible = "ti,tps65914-pmic", },
- { .compatible = "ti,tps80036-pmic", },
- { .compatible = "ti,tps659038-pmic", },
+static struct of_device_id of_palmas_match_tbl[] = {
+ {
+ .compatible = "ti,palmas-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,twl6035-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,twl6036-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,twl6037-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,tps65913-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,tps65914-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,tps80036-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,tps659038-pmic",
+ .data = &palmas_ddata,
+ },
+ {
+ .compatible = "ti,tps65917-pmic",
+ .data = &tps65917_ddata,
+ },
{ /* end */ }
};
+static int palmas_regulators_probe(struct platform_device *pdev)
+{
+ struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+ struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct device_node *node = pdev->dev.of_node;
+ struct palmas_pmic_driver_data *driver_data;
+ struct regulator_config config = { };
+ struct palmas_pmic *pmic;
+ const char *pdev_name;
+ const struct of_device_id *match;
+ int ret = 0;
+ unsigned int reg;
+
+ match = of_match_device(of_match_ptr(of_palmas_match_tbl), &pdev->dev);
+
+ if (!match)
+ return -ENODATA;
+
+ driver_data = (struct palmas_pmic_driver_data *)match->data;
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ pmic->dev = &pdev->dev;
+ pmic->palmas = palmas;
+ palmas->pmic = pmic;
+ platform_set_drvdata(pdev, pmic);
+ pmic->palmas->pmic_ddata = driver_data;
+
+ palmas_dt_to_pdata(&pdev->dev, node, pdata, driver_data);
+
+ ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
+ if (ret)
+ return ret;
+
+ if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)
+ pmic->smps123 = 1;
+
+ if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
+ pmic->smps457 = 1;
+
+ config.regmap = palmas->regmap[REGULATOR_SLAVE];
+ config.dev = &pdev->dev;
+ config.driver_data = pmic;
+ pdev_name = pdev->name;
+
+ ret = driver_data->smps_register(pmic, driver_data, pdata, pdev_name,
+ config);
+ if (ret)
+ return ret;
+
+ ret = driver_data->ldo_register(pmic, driver_data, pdata, pdev_name,
+ config);
+
+ return ret;
+}
+
static struct platform_driver palmas_driver = {
.driver = {
.name = "palmas-pmic",
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 02e2fb2fca66..b16c53a8272f 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -31,6 +31,7 @@
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mpu02.h>
struct s2mps11_info {
unsigned int rdev_num;
@@ -40,11 +41,15 @@ struct s2mps11_info {
int ramp_delay16;
int ramp_delay7810;
int ramp_delay9;
+
+ enum sec_device_type dev_type;
+
/*
- * One bit for each S2MPS14 regulator whether the suspend mode
+ * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
* was enabled.
*/
- unsigned int s2mps14_suspend_state:30;
+ unsigned long long s2mps14_suspend_state:35;
+
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
};
@@ -415,12 +420,24 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
- val = S2MPS14_ENABLE_SUSPEND;
- else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
- val = S2MPS14_ENABLE_EXT_CONTROL;
- else
- val = rdev->desc->enable_mask;
+ switch (s2mps11->dev_type) {
+ case S2MPS14X:
+ if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ val = S2MPS14_ENABLE_SUSPEND;
+ else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
+ val = S2MPS14_ENABLE_EXT_CONTROL;
+ else
+ val = rdev->desc->enable_mask;
+ break;
+ case S2MPU02:
+ if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ val = S2MPU02_ENABLE_SUSPEND;
+ else
+ val = rdev->desc->enable_mask;
+ break;
+ default:
+ return -EINVAL;
+ };
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val);
@@ -429,12 +446,38 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
{
int ret;
- unsigned int val;
+ unsigned int val, state;
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
+ int rdev_id = rdev_get_id(rdev);
- /* LDO3 should be always on and does not support suspend mode */
- if (rdev_get_id(rdev) == S2MPS14_LDO3)
- return 0;
+ /* Below LDO should be always on or does not support suspend mode. */
+ switch (s2mps11->dev_type) {
+ case S2MPS14X:
+ switch (rdev_id) {
+ case S2MPS14_LDO3:
+ return 0;
+ default:
+ state = S2MPS14_ENABLE_SUSPEND;
+ break;
+ };
+ break;
+ case S2MPU02:
+ switch (rdev_id) {
+ case S2MPU02_LDO13:
+ case S2MPU02_LDO14:
+ case S2MPU02_LDO15:
+ case S2MPU02_LDO17:
+ case S2MPU02_BUCK7:
+ state = S2MPU02_DISABLE_SUSPEND;
+ break;
+ default:
+ state = S2MPU02_ENABLE_SUSPEND;
+ break;
+ };
+ break;
+ default:
+ return -EINVAL;
+ };
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
if (ret < 0)
@@ -452,7 +495,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
return 0;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
- rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND);
+ rdev->desc->enable_mask, state);
}
static struct regulator_ops s2mps14_reg_ops = {
@@ -605,8 +648,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
}
static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
- struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
- enum sec_device_type dev_type)
+ struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
{
struct device_node *reg_np;
@@ -617,7 +659,7 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
}
of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
- if (dev_type == S2MPS14X)
+ if (s2mps11->dev_type == S2MPS14X)
s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
of_node_put(reg_np);
@@ -625,6 +667,238 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
return 0;
}
+static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ unsigned int ramp_val, ramp_shift, ramp_reg;
+
+ switch (rdev_get_id(rdev)) {
+ case S2MPU02_BUCK1:
+ ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK2:
+ ramp_shift = S2MPU02_BUCK2_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK3:
+ ramp_shift = S2MPU02_BUCK3_RAMP_SHIFT;
+ break;
+ case S2MPU02_BUCK4:
+ ramp_shift = S2MPU02_BUCK4_RAMP_SHIFT;
+ break;
+ default:
+ return 0;
+ }
+ ramp_reg = S2MPU02_REG_RAMP1;
+ ramp_val = get_ramp_delay(ramp_delay);
+
+ return regmap_update_bits(rdev->regmap, ramp_reg,
+ S2MPU02_BUCK1234_RAMP_MASK << ramp_shift,
+ ramp_val << ramp_shift);
+}
+
+static struct regulator_ops s2mpu02_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = s2mps14_regulator_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_disable = s2mps14_regulator_set_suspend_disable,
+};
+
+static struct regulator_ops s2mpu02_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = s2mps14_regulator_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_suspend_disable = s2mps14_regulator_set_suspend_disable,
+ .set_ramp_delay = s2mpu02_set_ramp_delay,
+};
+
+#define regulator_desc_s2mpu02_ldo1(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_900MV, \
+ .uV_step = S2MPU02_LDO_STEP_12_5MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP1_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L1CTRL, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L1CTRL, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo2(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1050MV, \
+ .uV_step = S2MPU02_LDO_STEP_25MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP2_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L2CTRL1, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L2CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo3(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_900MV, \
+ .uV_step = S2MPU02_LDO_STEP_12_5MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP1_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo4(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1050MV, \
+ .uV_step = S2MPU02_LDO_STEP_25MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP2_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_ldo5(num) { \
+ .name = "LDO"#num, \
+ .id = S2MPU02_LDO##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_LDO_MIN_1600MV, \
+ .uV_step = S2MPU02_LDO_STEP_50MV, \
+ .linear_min_sel = S2MPU02_LDO_GROUP3_START_SEL, \
+ .n_voltages = S2MPU02_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .vsel_mask = S2MPU02_LDO_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_L3CTRL + num - 3, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+
+#define regulator_desc_s2mpu02_buck1234(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK1234_MIN_600MV, \
+ .uV_step = S2MPU02_BUCK1234_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK1234_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B1CTRL2 + (num - 1) * 2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B1CTRL1 + (num - 1) * 2, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck5(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK5_MIN_1081_25MV, \
+ .uV_step = S2MPU02_BUCK5_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK5_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B5CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B5CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck6(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK6_MIN_1700MV, \
+ .uV_step = S2MPU02_BUCK6_STEP_2_50MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK6_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B6CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B6CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+#define regulator_desc_s2mpu02_buck7(num) { \
+ .name = "BUCK"#num, \
+ .id = S2MPU02_BUCK##num, \
+ .ops = &s2mpu02_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = S2MPU02_BUCK7_MIN_900MV, \
+ .uV_step = S2MPU02_BUCK7_STEP_6_25MV, \
+ .n_voltages = S2MPU02_BUCK_N_VOLTAGES, \
+ .linear_min_sel = S2MPU02_BUCK7_START_SEL, \
+ .ramp_delay = S2MPU02_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPU02_REG_B7CTRL2, \
+ .vsel_mask = S2MPU02_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPU02_REG_B7CTRL1, \
+ .enable_mask = S2MPU02_ENABLE_MASK \
+}
+
+static const struct regulator_desc s2mpu02_regulators[] = {
+ regulator_desc_s2mpu02_ldo1(1),
+ regulator_desc_s2mpu02_ldo2(2),
+ regulator_desc_s2mpu02_ldo4(3),
+ regulator_desc_s2mpu02_ldo5(4),
+ regulator_desc_s2mpu02_ldo4(5),
+ regulator_desc_s2mpu02_ldo3(6),
+ regulator_desc_s2mpu02_ldo3(7),
+ regulator_desc_s2mpu02_ldo4(8),
+ regulator_desc_s2mpu02_ldo5(9),
+ regulator_desc_s2mpu02_ldo3(10),
+ regulator_desc_s2mpu02_ldo4(11),
+ regulator_desc_s2mpu02_ldo5(12),
+ regulator_desc_s2mpu02_ldo5(13),
+ regulator_desc_s2mpu02_ldo5(14),
+ regulator_desc_s2mpu02_ldo5(15),
+ regulator_desc_s2mpu02_ldo5(16),
+ regulator_desc_s2mpu02_ldo4(17),
+ regulator_desc_s2mpu02_ldo5(18),
+ regulator_desc_s2mpu02_ldo3(19),
+ regulator_desc_s2mpu02_ldo4(20),
+ regulator_desc_s2mpu02_ldo5(21),
+ regulator_desc_s2mpu02_ldo5(22),
+ regulator_desc_s2mpu02_ldo5(23),
+ regulator_desc_s2mpu02_ldo4(24),
+ regulator_desc_s2mpu02_ldo5(25),
+ regulator_desc_s2mpu02_ldo4(26),
+ regulator_desc_s2mpu02_ldo5(27),
+ regulator_desc_s2mpu02_ldo5(28),
+ regulator_desc_s2mpu02_buck1234(1),
+ regulator_desc_s2mpu02_buck1234(2),
+ regulator_desc_s2mpu02_buck1234(3),
+ regulator_desc_s2mpu02_buck1234(4),
+ regulator_desc_s2mpu02_buck5(5),
+ regulator_desc_s2mpu02_buck6(6),
+ regulator_desc_s2mpu02_buck7(7),
+};
+
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -634,15 +908,14 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
struct s2mps11_info *s2mps11;
int i, ret = 0;
const struct regulator_desc *regulators;
- enum sec_device_type dev_type;
s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
GFP_KERNEL);
if (!s2mps11)
return -ENOMEM;
- dev_type = platform_get_device_id(pdev)->driver_data;
- switch (dev_type) {
+ s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
+ switch (s2mps11->dev_type) {
case S2MPS11X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
@@ -651,8 +924,13 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
break;
+ case S2MPU02:
+ s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
+ regulators = s2mpu02_regulators;
+ break;
default:
- dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
+ dev_err(&pdev->dev, "Invalid device type: %u\n",
+ s2mps11->dev_type);
return -EINVAL;
};
@@ -686,7 +964,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
for (i = 0; i < s2mps11->rdev_num; i++)
rdata[i].name = regulators[i].name;
- ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
+ ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
if (ret)
goto out;
@@ -739,6 +1017,7 @@ out:
static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps11-pmic", S2MPS11X},
{ "s2mps14-pmic", S2MPS14X},
+ { "s2mpu02-pmic", S2MPU02},
{ },
};
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
@@ -766,5 +1045,5 @@ module_exit(s2mps11_pmic_exit);
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14 Regulator Driver");
+MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPU02 Regulator Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index c79af943a5c0..0ab5cbeeb797 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -686,7 +686,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
struct sec_platform_data *pdata = iodev->pdata;
struct regulator_config config = { };
struct s5m8767_info *s5m8767;
- int i, ret, size, buck_init;
+ int i, ret, buck_init;
if (!pdata) {
dev_err(pdev->dev.parent, "Platform data not supplied\n");
@@ -725,8 +725,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
if (!s5m8767)
return -ENOMEM;
- size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2);
-
s5m8767->dev = &pdev->dev;
s5m8767->iodev = iodev;
s5m8767->num_regulators = pdata->num_regulators;
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 2064b3fd45f7..d5df1e9ad1da 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -192,12 +192,14 @@ static struct regulator_ops tps65090_fet_control_ops = {
static struct regulator_ops tps65090_ldo_ops = {
};
-#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _ops) \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
{ \
.name = "TPS65090_RAILS"#_id, \
.supply_name = _sname, \
.id = TPS65090_REGULATOR_##_id, \
+ .n_voltages = _nvolt, \
.ops = &_ops, \
+ .fixed_uV = _volt, \
.enable_reg = _en_reg, \
.enable_val = _en_bits, \
.enable_mask = _en_bits, \
@@ -205,40 +207,46 @@ static struct regulator_ops tps65090_ldo_ops = {
.owner = THIS_MODULE, \
}
+#define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \
+ tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 1, _volt, _ops)
+
+#define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \
+ tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 0, 0, _ops)
+
static struct regulator_desc tps65090_regulator_desc[] = {
- tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT),
- tps65090_reg_control_ops),
- tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT),
- tps65090_reg_control_ops),
- tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT),
- tps65090_reg_control_ops),
-
- tps65090_REG_DESC(FET1, "infet1", 0x0F,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET2, "infet2", 0x10,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET3, "infet3", 0x11,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET4, "infet4", 0x12,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET5, "infet5", 0x13,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET6, "infet6", 0x14,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
- tps65090_REG_DESC(FET7, "infet7", 0x15,
- BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
- tps65090_fet_control_ops),
-
- tps65090_REG_DESC(LDO1, "vsys-l1", 0, 0,
- tps65090_ldo_ops),
- tps65090_REG_DESC(LDO2, "vsys-l2", 0, 0,
- tps65090_ldo_ops),
+ tps65090_REG_FIXEDV(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT), 5000000,
+ tps65090_reg_control_ops),
+ tps65090_REG_FIXEDV(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT), 3300000,
+ tps65090_reg_control_ops),
+ tps65090_REG_SWITCH(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT),
+ tps65090_reg_control_ops),
+
+ tps65090_REG_SWITCH(FET1, "infet1", 0x0F,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET2, "infet2", 0x10,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET3, "infet3", 0x11,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET4, "infet4", 0x12,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET5, "infet5", 0x13,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET6, "infet6", 0x14,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+ tps65090_REG_SWITCH(FET7, "infet7", 0x15,
+ BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
+ tps65090_fet_control_ops),
+
+ tps65090_REG_FIXEDV(LDO1, "vsys-l1", 0, 0, 5000000,
+ tps65090_ldo_ops),
+ tps65090_REG_FIXEDV(LDO2, "vsys-l2", 0, 0, 3300000,
+ tps65090_ldo_ops),
};
static inline bool is_dcdc(int id)
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index f7ed20a5a8b9..d58db72a63b0 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -68,7 +68,7 @@ static const struct regulator_linear_range tps65217_uv2_ranges[] = {
static int tps65217_pmic_enable(struct regulator_dev *dev)
{
struct tps65217 *tps = rdev_get_drvdata(dev);
- unsigned int rid = rdev_get_id(dev);
+ int rid = rdev_get_id(dev);
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
return -EINVAL;
@@ -82,7 +82,7 @@ static int tps65217_pmic_enable(struct regulator_dev *dev)
static int tps65217_pmic_disable(struct regulator_dev *dev)
{
struct tps65217 *tps = rdev_get_drvdata(dev);
- unsigned int rid = rdev_get_id(dev);
+ int rid = rdev_get_id(dev);
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
return -EINVAL;
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index 9effe48c605e..f0a40281b9c1 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -29,8 +29,8 @@
enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
-#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \
- _lr, _nlr, _delay) \
+#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, \
+ _lr, _nlr, _delay, _fuv) \
{ \
.name = _name, \
.id = _id, \
@@ -42,14 +42,15 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
.vsel_mask = _vm, \
.enable_reg = _er, \
.enable_mask = _em, \
- .volt_table = _t, \
+ .volt_table = NULL, \
.linear_ranges = _lr, \
.n_linear_ranges = _nlr, \
.ramp_delay = _delay, \
+ .fixed_uV = _fuv \
} \
#define TPS65218_INFO(_id, _nm, _min, _max) \
- { \
+ [_id] = { \
.id = _id, \
.name = _nm, \
.min_uV = _min, \
@@ -68,17 +69,17 @@ static const struct regulator_linear_range ldo1_dcdc3_ranges[] = {
static const struct regulator_linear_range dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
- REGULATOR_LINEAR_RANGE(1550000, 0x10, 0x34, 50000),
+ REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000),
};
static struct tps_info tps65218_pmic_regs[] = {
- TPS65218_INFO(0, "DCDC1", 850000, 167500),
- TPS65218_INFO(1, "DCDC2", 850000, 1675000),
- TPS65218_INFO(2, "DCDC3", 900000, 3400000),
- TPS65218_INFO(3, "DCDC4", 1175000, 3400000),
- TPS65218_INFO(4, "DCDC5", 1000000, 1000000),
- TPS65218_INFO(5, "DCDC6", 1800000, 1800000),
- TPS65218_INFO(6, "LDO1", 900000, 3400000),
+ TPS65218_INFO(DCDC1, "DCDC1", 850000, 167500),
+ TPS65218_INFO(DCDC2, "DCDC2", 850000, 1675000),
+ TPS65218_INFO(DCDC3, "DCDC3", 900000, 3400000),
+ TPS65218_INFO(DCDC4, "DCDC4", 1175000, 3400000),
+ TPS65218_INFO(DCDC5, "DCDC5", 1000000, 1000000),
+ TPS65218_INFO(DCDC6, "DCDC6", 1800000, 1800000),
+ TPS65218_INFO(LDO1, "LDO1", 900000, 3400000),
};
#define TPS65218_OF_MATCH(comp, label) \
@@ -127,7 +128,7 @@ static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev,
static int tps65218_pmic_enable(struct regulator_dev *dev)
{
struct tps65218 *tps = rdev_get_drvdata(dev);
- unsigned int rid = rdev_get_id(dev);
+ int rid = rdev_get_id(dev);
if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
return -EINVAL;
@@ -141,7 +142,7 @@ static int tps65218_pmic_enable(struct regulator_dev *dev)
static int tps65218_pmic_disable(struct regulator_dev *dev)
{
struct tps65218 *tps = rdev_get_drvdata(dev);
- unsigned int rid = rdev_get_id(dev);
+ int rid = rdev_get_id(dev);
if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
return -EINVAL;
@@ -185,34 +186,33 @@ static const struct regulator_desc regulators[] = {
TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64,
TPS65218_REG_CONTROL_DCDC1,
TPS65218_CONTROL_DCDC1_MASK,
- TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL,
- dcdc1_dcdc2_ranges, 2, 4000),
+ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN,
+ dcdc1_dcdc2_ranges, 2, 4000, 0),
TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
TPS65218_REG_CONTROL_DCDC2,
TPS65218_CONTROL_DCDC2_MASK,
- TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL,
- dcdc1_dcdc2_ranges, 2, 4000),
+ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN,
+ dcdc1_dcdc2_ranges, 2, 4000, 0),
TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
64, TPS65218_REG_CONTROL_DCDC3,
TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
- TPS65218_ENABLE1_DC3_EN, NULL,
- ldo1_dcdc3_ranges, 2, 0),
+ TPS65218_ENABLE1_DC3_EN, ldo1_dcdc3_ranges, 2, 0, 0),
TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
53, TPS65218_REG_CONTROL_DCDC4,
TPS65218_CONTROL_DCDC4_MASK,
- TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL,
- dcdc4_ranges, 2, 0),
+ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN,
+ dcdc4_ranges, 2, 0, 0),
TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
1, -1, -1, TPS65218_REG_ENABLE1,
- TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0, 0),
+ TPS65218_ENABLE1_DC5_EN, NULL, 0, 0, 1000000),
TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
1, -1, -1, TPS65218_REG_ENABLE1,
- TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0, 0),
+ TPS65218_ENABLE1_DC6_EN, NULL, 0, 0, 1800000),
TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
TPS65218_REG_CONTROL_LDO1,
TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
- TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges,
- 2, 0),
+ TPS65218_ENABLE2_LDO1_EN, ldo1_dcdc3_ranges,
+ 2, 0, 0),
};
static int tps65218_regulator_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 0a3bb3aecd97..ccbb9f150b4e 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -74,6 +74,16 @@ static struct regulator_ops tps6586x_rw_regulator_ops = {
.disable = regulator_disable_regmap,
};
+static struct regulator_ops tps6586x_rw_linear_regulator_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+};
+
static struct regulator_ops tps6586x_ro_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
@@ -91,48 +101,11 @@ static const unsigned int tps6586x_ldo0_voltages[] = {
1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
};
-static const unsigned int tps6586x_ldo4_voltages[] = {
- 1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
- 1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
- 2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
- 2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
-};
-
-#define tps658623_sm2_voltages tps6586x_ldo4_voltages
-
static const unsigned int tps6586x_ldo_voltages[] = {
1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
};
-static const unsigned int tps6586x_sm2_voltages[] = {
- 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
- 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
- 3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
- 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
-};
-
-static int tps658640_sm2_voltages[] = {
- 2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000,
- 2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000,
- 2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000,
- 3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000,
-};
-
-static const unsigned int tps658643_sm2_voltages[] = {
- 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
- 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
- 1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000,
- 1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,
-};
-
-static const unsigned int tps6586x_dvm_voltages[] = {
- 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
- 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
- 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
- 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
-};
-
-static int tps658640_rtc_voltages[] = {
+static const unsigned int tps658640_rtc_voltages[] = {
2500000, 2850000, 3100000, 3300000,
};
@@ -159,6 +132,31 @@ static int tps658640_rtc_voltages[] = {
.enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
.enable_bit[1] = (ebit1),
+#define TPS6586X_REGULATOR_LINEAR(_id, _ops, _pin_name, n_volt, min_uv, \
+ uv_step, vreg, shift, nbits, ereg0, \
+ ebit0, ereg1, ebit1, goreg, gobit) \
+ .desc = { \
+ .supply_name = _pin_name, \
+ .name = "REG-" #_id, \
+ .ops = &tps6586x_## _ops ## _regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = TPS6586X_ID_##_id, \
+ .n_voltages = n_volt, \
+ .min_uV = min_uv, \
+ .uV_step = uv_step, \
+ .owner = THIS_MODULE, \
+ .enable_reg = TPS6586X_SUPPLY##ereg0, \
+ .enable_mask = 1 << (ebit0), \
+ .vsel_reg = TPS6586X_##vreg, \
+ .vsel_mask = ((1 << (nbits)) - 1) << (shift), \
+ .apply_reg = (goreg), \
+ .apply_bit = (gobit), \
+ }, \
+ .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \
+ .enable_bit[0] = (ebit0), \
+ .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
+ .enable_bit[1] = (ebit1),
+
#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
{ \
@@ -166,6 +164,14 @@ static int tps658640_rtc_voltages[] = {
ereg0, ebit0, ereg1, ebit1, 0, 0) \
}
+#define TPS6586X_LDO_LINEAR(_id, _pname, n_volt, min_uv, uv_step, vreg, \
+ shift, nbits, ereg0, ebit0, ereg1, ebit1) \
+{ \
+ TPS6586X_REGULATOR_LINEAR(_id, rw_linear, _pname, n_volt, \
+ min_uv, uv_step, vreg, shift, nbits, \
+ ereg0, ebit0, ereg1, ebit1, 0, 0) \
+}
+
#define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
{ \
@@ -173,11 +179,13 @@ static int tps658640_rtc_voltages[] = {
ereg0, ebit0, ereg1, ebit1, 0, 0) \
}
-#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \
- ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
+#define TPS6586X_DVM(_id, _pname, n_volt, min_uv, uv_step, vreg, shift, \
+ nbits, ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
{ \
- TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \
- ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
+ TPS6586X_REGULATOR_LINEAR(_id, rw_linear, _pname, n_volt, \
+ min_uv, uv_step, vreg, shift, nbits, \
+ ereg0, ebit0, ereg1, ebit1, goreg, \
+ gobit) \
}
#define TPS6586X_SYS_REGULATOR() \
@@ -210,24 +218,23 @@ static struct tps6586x_regulator tps6586x_regulator[] = {
ENE, 7),
TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7,
V4, 7),
- TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1,
- END, 1),
- TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7,
- END, 7),
-
- TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3,
- ENB, 3, TPS6586X_VCC2, BIT(6)),
- TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3,
- END, 3, TPS6586X_VCC1, BIT(6)),
- TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1,
- ENB, 1, TPS6586X_VCC1, BIT(2)),
- TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0,
- ENB, 0, TPS6586X_VCC1, BIT(0)),
+ TPS6586X_LDO_LINEAR(LDO_1, "vinldo01", 32, 725000, 25000, SUPPLYV1,
+ 0, 5, ENC, 1, END, 1),
+ TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 3000000, 50000, SUPPLYV2,
+ 0, 5, ENC, 7, END, 7),
+ TPS6586X_DVM(LDO_2, "vinldo23", 32, 725000, 25000, LDO2BV1, 0, 5,
+ ENA, 3, ENB, 3, TPS6586X_VCC2, BIT(6)),
+ TPS6586X_DVM(LDO_4, "vinldo4", 32, 1700000, 25000, LDO4V1, 0, 5,
+ ENC, 3, END, 3, TPS6586X_VCC1, BIT(6)),
+ TPS6586X_DVM(SM_0, "vin-sm0", 32, 725000, 25000, SM0V1, 0, 5,
+ ENA, 1, ENB, 1, TPS6586X_VCC1, BIT(2)),
+ TPS6586X_DVM(SM_1, "vin-sm1", 32, 725000, 25000, SM1V1, 0, 5,
+ ENA, 0, ENB, 0, TPS6586X_VCC1, BIT(0)),
};
static struct tps6586x_regulator tps658623_regulator[] = {
- TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7,
- END, 7),
+ TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 1700000, 25000, SUPPLYV2,
+ 0, 5, ENC, 7, END, 7),
};
static struct tps6586x_regulator tps658640_regulator[] = {
@@ -243,16 +250,16 @@ static struct tps6586x_regulator tps658640_regulator[] = {
ENC, 6, END, 6),
TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3,
ENE, 7, ENE, 7),
- TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5,
- ENC, 7, END, 7),
+ TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 2150000, 50000, SUPPLYV2,
+ 0, 5, ENC, 7, END, 7),
TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2,
V4, 7, V4, 7),
};
static struct tps6586x_regulator tps658643_regulator[] = {
- TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
- END, 7),
+ TPS6586X_LDO_LINEAR(SM_2, "vin-sm2", 32, 1025000, 25000, SUPPLYV2,
+ 0, 5, ENC, 7, END, 7),
};
/*
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index fed28abef419..0b4f8660fdb4 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1128,7 +1128,7 @@ static int twlreg_probe(struct platform_device *pdev)
if (!initdata)
return -EINVAL;
- info = kmemdup(template, sizeof(*info), GFP_KERNEL);
+ info = devm_kmemdup(&pdev->dev, template, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -1192,7 +1192,6 @@ static int twlreg_probe(struct platform_device *pdev)
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "can't register %s, %ld\n",
info->desc.name, PTR_ERR(rdev));
- kfree(info);
return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, rdev);
@@ -1212,20 +1211,10 @@ static int twlreg_probe(struct platform_device *pdev)
return 0;
}
-static int twlreg_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
- struct twlreg_info *info = rdev->reg_data;
-
- kfree(info);
- return 0;
-}
-
MODULE_ALIAS("platform:twl_reg");
static struct platform_driver twlreg_driver = {
.probe = twlreg_probe,
- .remove = twlreg_remove,
/* NOTE: short name, to work around driver model truncation of
* "twl_regulator.12" (and friends) to "twl_regulator.1".
*/
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0754f5c7cb3b..a168e96142b9 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -373,6 +373,14 @@ config RTC_DRV_PCF8563
This driver can also be built as a module. If so, the module
will be called rtc-pcf8563.
+config RTC_DRV_PCF85063
+ tristate "nxp PCF85063"
+ help
+ If you say yes here you get support for the PCF85063 RTC chip
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-pcf85063.
+
config RTC_DRV_PCF8583
tristate "Philips PCF8583"
help
@@ -760,6 +768,15 @@ config RTC_DRV_DS1742
This driver can also be built as a module. If so, the module
will be called rtc-ds1742.
+config RTC_DRV_DS2404
+ tristate "Maxim/Dallas DS2404"
+ help
+ If you say yes here you get support for the
+ Dallas DS2404 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds2404.
+
config RTC_DRV_DA9052
tristate "Dialog DA9052/DA9053 RTC"
depends on PMIC_DA9052
@@ -789,7 +806,7 @@ config RTC_DRV_DA9063
config RTC_DRV_EFI
tristate "EFI RTC"
- depends on IA64
+ depends on EFI
help
If you say yes here you will get support for the EFI
Real Time Clock.
@@ -873,15 +890,6 @@ config RTC_DRV_V3020
This driver can also be built as a module. If so, the module
will be called rtc-v3020.
-config RTC_DRV_DS2404
- tristate "Dallas DS2404"
- help
- If you say yes here you get support for the
- Dallas DS2404 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called rtc-ds2404.
-
config RTC_DRV_WM831X
tristate "Wolfson Microelectronics WM831x RTC"
depends on MFD_WM831X
@@ -1349,6 +1357,7 @@ config RTC_DRV_SIRFSOC
config RTC_DRV_MOXART
tristate "MOXA ART RTC"
+ depends on ARCH_MOXART || COMPILE_TEST
help
If you say yes here you get support for the MOXA ART
RTC module.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 70347d041d10..56f061c7c815 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -10,6 +10,10 @@ obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
rtc-core-y := class.o interface.o
+ifdef CONFIG_RTC_DRV_EFI
+rtc-core-y += rtc-efi-platform.o
+endif
+
rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
@@ -93,6 +97,7 @@ obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 589351ef75d0..38e26be705be 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -53,6 +53,7 @@ static int rtc_suspend(struct device *dev)
struct rtc_device *rtc = to_rtc_device(dev);
struct rtc_time tm;
struct timespec delta, delta_delta;
+ int err;
if (has_persistent_clock())
return 0;
@@ -61,7 +62,12 @@ static int rtc_suspend(struct device *dev)
return 0;
/* snapshot the current RTC and system time at suspend*/
- rtc_read_time(rtc, &tm);
+ err = rtc_read_time(rtc, &tm);
+ if (err < 0) {
+ pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev));
+ return 0;
+ }
+
getnstimeofday(&old_system);
rtc_tm_to_time(&tm, &old_rtc.tv_sec);
@@ -94,6 +100,7 @@ static int rtc_resume(struct device *dev)
struct rtc_time tm;
struct timespec new_system, new_rtc;
struct timespec sleep_time;
+ int err;
if (has_persistent_clock())
return 0;
@@ -104,7 +111,12 @@ static int rtc_resume(struct device *dev)
/* snapshot the current rtc and system time at resume */
getnstimeofday(&new_system);
- rtc_read_time(rtc, &tm);
+ err = rtc_read_time(rtc, &tm);
+ if (err < 0) {
+ pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev));
+ return 0;
+ }
+
if (rtc_valid_tm(&tm) != 0) {
pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
return 0;
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 5813fa52c3d4..5b2717f5dafa 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -348,6 +348,8 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
/* Make sure we're not setting alarms in the past */
err = __rtc_read_time(rtc, &tm);
+ if (err)
+ return err;
rtc_tm_to_time(&tm, &now);
if (scheduled <= now)
return -ETIME;
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c
index ed526a192ce0..fd25e2374d4e 100644
--- a/drivers/rtc/rtc-au1xxx.c
+++ b/drivers/rtc/rtc-au1xxx.c
@@ -32,7 +32,7 @@ static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
unsigned long t;
- t = au_readl(SYS_TOYREAD);
+ t = alchemy_rdsys(AU1000_SYS_TOYREAD);
rtc_time_to_tm(t, tm);
@@ -45,13 +45,12 @@ static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_tm_to_time(tm, &t);
- au_writel(t, SYS_TOYWRITE);
- au_sync();
+ alchemy_wrsys(t, AU1000_SYS_TOYWRITE);
/* wait for the pending register write to succeed. This can
* take up to 6 seconds...
*/
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+ while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
msleep(1);
return 0;
@@ -68,7 +67,7 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
unsigned long t;
int ret;
- t = au_readl(SYS_COUNTER_CNTRL);
+ t = alchemy_rdsys(AU1000_SYS_CNTRCTRL);
if (!(t & CNTR_OK)) {
dev_err(&pdev->dev, "counters not working; aborting.\n");
ret = -ENODEV;
@@ -78,10 +77,10 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
ret = -ETIMEDOUT;
/* set counter0 tickrate to 1Hz if necessary */
- if (au_readl(SYS_TOYTRIM) != 32767) {
+ if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) {
/* wait until hardware gives access to TRIM register */
t = 0x00100000;
- while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t)
+ while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T0S) && --t)
msleep(1);
if (!t) {
@@ -93,12 +92,11 @@ static int au1xtoy_rtc_probe(struct platform_device *pdev)
}
/* set 1Hz TOY tick rate */
- au_writel(32767, SYS_TOYTRIM);
- au_sync();
+ alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
}
/* wait until the hardware allows writes to the counter reg */
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+ while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
msleep(1);
rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 595393098b09..731ed1a97f59 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -29,6 +29,8 @@
#define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1)
+#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)
+
#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
#define RTC_SEC 0
#define RTC_MIN 1
@@ -42,6 +44,10 @@ struct da9063_rtc {
struct da9063 *hw;
struct rtc_time alarm_time;
bool rtc_sync;
+ int alarm_year;
+ int alarm_start;
+ int alarm_len;
+ int data_start;
};
static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
@@ -83,7 +89,7 @@ static int da9063_rtc_stop_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);
- return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);
}
@@ -91,7 +97,7 @@ static int da9063_rtc_start_alarm(struct device *dev)
{
struct da9063_rtc *rtc = dev_get_drvdata(dev);
- return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, DA9063_ALARM_ON);
}
@@ -151,8 +157,9 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
unsigned int val;
- ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S,
- &data[RTC_SEC], RTC_DATA_LEN);
+ data[RTC_SEC] = 0;
+ ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0)
return ret;
@@ -186,14 +193,14 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
- ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S,
- data, RTC_DATA_LEN);
+ ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret;
}
- rtc->alarm_time = alrm->time;
+ da9063_data_to_tm(data, &rtc->alarm_time);
if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev);
@@ -218,7 +225,7 @@ static irqreturn_t da9063_alarm_event(int irq, void *data)
{
struct da9063_rtc *rtc = data;
- regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
+ regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
DA9063_ALARM_ON, 0);
rtc->rtc_sync = true;
@@ -257,7 +264,23 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ if (da9063->variant_code == PMIC_DA9063_AD) {
+ rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
+ rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
+ rtc->alarm_len = RTC_ALARM_DATA_LEN;
+ rtc->data_start = RTC_MIN;
+ } else {
+ rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
+ rtc->alarm_start = DA9063_BB_REG_ALARM_S;
+ rtc->alarm_len = RTC_DATA_LEN;
+ rtc->data_start = RTC_SEC;
+ }
+
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
0);
if (ret < 0) {
@@ -265,7 +288,7 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM);
if (ret < 0) {
@@ -273,25 +296,22 @@ static int da9063_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y,
+ ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
DA9063_TICK_ON, 0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
goto err;
}
- ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S,
- data, RTC_DATA_LEN);
+ data[RTC_SEC] = 0;
+ ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
+ &data[rtc->data_start], rtc->alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
goto err;
}
- rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
- if (!rtc)
- return -ENOMEM;
-
platform_set_drvdata(pdev, rtc);
irq_alarm = platform_get_irq_byname(pdev, "ALARM");
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index c3719189dd96..ae9f997223b1 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -4,6 +4,7 @@
* Real Time Clock
*
* Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>
+ * Ankur Srivastava <sankurece@gmail.com> : DS1343 Nvram Support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -45,6 +46,9 @@
#define DS1343_CONTROL_REG 0x0F
#define DS1343_STATUS_REG 0x10
#define DS1343_TRICKLE_REG 0x11
+#define DS1343_NVRAM 0x20
+
+#define DS1343_NVRAM_LEN 96
/* DS1343 Control Registers bits */
#define DS1343_EOSC 0x80
@@ -149,6 +153,64 @@ static ssize_t ds1343_store_glitchfilter(struct device *dev,
static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
ds1343_store_glitchfilter);
+static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ int ret;
+ unsigned char address;
+ struct device *dev = kobj_to_dev(kobj);
+ struct ds1343_priv *priv = dev_get_drvdata(dev);
+
+ if (unlikely(!count))
+ return count;
+
+ if ((count + off) > DS1343_NVRAM_LEN)
+ count = DS1343_NVRAM_LEN - off;
+
+ address = DS1343_NVRAM + off;
+
+ ret = regmap_bulk_write(priv->map, address, buf, count);
+ if (ret < 0)
+ dev_err(&priv->spi->dev, "Error in nvram write %d", ret);
+
+ return (ret < 0) ? ret : count;
+}
+
+
+static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ int ret;
+ unsigned char address;
+ struct device *dev = kobj_to_dev(kobj);
+ struct ds1343_priv *priv = dev_get_drvdata(dev);
+
+ if (unlikely(!count))
+ return count;
+
+ if ((count + off) > DS1343_NVRAM_LEN)
+ count = DS1343_NVRAM_LEN - off;
+
+ address = DS1343_NVRAM + off;
+
+ ret = regmap_bulk_read(priv->map, address, buf, count);
+ if (ret < 0)
+ dev_err(&priv->spi->dev, "Error in nvram read %d\n", ret);
+
+ return (ret < 0) ? ret : count;
+}
+
+
+static struct bin_attribute nvram_attr = {
+ .attr.name = "nvram",
+ .attr.mode = S_IRUGO | S_IWUSR,
+ .read = ds1343_nvram_read,
+ .write = ds1343_nvram_write,
+ .size = DS1343_NVRAM_LEN,
+};
+
static ssize_t ds1343_show_alarmstatus(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -274,12 +336,16 @@ static int ds1343_sysfs_register(struct device *dev)
if (err)
goto error1;
+ err = device_create_bin_file(dev, &nvram_attr);
+ if (err)
+ goto error2;
+
if (priv->irq <= 0)
return err;
err = device_create_file(dev, &dev_attr_alarm_mode);
if (err)
- goto error2;
+ goto error3;
err = device_create_file(dev, &dev_attr_alarm_status);
if (!err)
@@ -287,6 +353,9 @@ static int ds1343_sysfs_register(struct device *dev)
device_remove_file(dev, &dev_attr_alarm_mode);
+error3:
+ device_remove_bin_file(dev, &nvram_attr);
+
error2:
device_remove_file(dev, &dev_attr_trickle_charger);
@@ -302,6 +371,7 @@ static void ds1343_sysfs_unregister(struct device *dev)
device_remove_file(dev, &dev_attr_glitch_filter);
device_remove_file(dev, &dev_attr_trickle_charger);
+ device_remove_bin_file(dev, &nvram_attr);
if (priv->irq <= 0)
return;
@@ -684,6 +754,7 @@ static struct spi_driver ds1343_driver = {
module_spi_driver(ds1343_driver);
MODULE_DESCRIPTION("DS1343 RTC SPI Driver");
-MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>");
+MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>,"
+ "Ankur Srivastava <sankurece@gmail.com>");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DS1343_DRV_VERSION);
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index c6b2191a4128..9822715db8ba 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -231,7 +231,7 @@ static struct platform_driver ds1742_rtc_driver = {
.driver = {
.name = "rtc-ds1742",
.owner = THIS_MODULE,
- .of_match_table = ds1742_rtc_of_match,
+ .of_match_table = of_match_ptr(ds1742_rtc_of_match),
},
};
diff --git a/drivers/rtc/rtc-efi-platform.c b/drivers/rtc/rtc-efi-platform.c
new file mode 100644
index 000000000000..b40fbe332af4
--- /dev/null
+++ b/drivers/rtc/rtc-efi-platform.c
@@ -0,0 +1,31 @@
+/*
+ * Moved from arch/ia64/kernel/time.c
+ *
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ * Copyright (C) 1999-2000 VA Linux Systems
+ * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+#include <linux/platform_device.h>
+
+static struct platform_device rtc_efi_dev = {
+ .name = "rtc-efi",
+ .id = -1,
+};
+
+static int __init rtc_init(void)
+{
+ if (efi_enabled(EFI_RUNTIME_SERVICES))
+ if (platform_device_register(&rtc_efi_dev) < 0)
+ pr_err("unable to register rtc device...\n");
+
+ /* not necessarily an error */
+ return 0;
+}
+module_init(rtc_init);
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index c4c38431012e..8225b89de810 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/stringify.h>
#include <linux/time.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
@@ -48,8 +49,8 @@ compute_wday(efi_time_t *eft)
int y;
int ndays = 0;
- if (eft->year < 1998) {
- pr_err("EFI year < 1998, invalid date\n");
+ if (eft->year < EFI_RTC_EPOCH) {
+ pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", invalid date\n");
return -1;
}
@@ -78,19 +79,36 @@ convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft)
eft->timezone = EFI_UNSPECIFIED_TIMEZONE;
}
-static void
+static bool
convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
{
memset(wtime, 0, sizeof(*wtime));
+
+ if (eft->second >= 60)
+ return false;
wtime->tm_sec = eft->second;
+
+ if (eft->minute >= 60)
+ return false;
wtime->tm_min = eft->minute;
+
+ if (eft->hour >= 24)
+ return false;
wtime->tm_hour = eft->hour;
+
+ if (!eft->day || eft->day > 31)
+ return false;
wtime->tm_mday = eft->day;
+
+ if (!eft->month || eft->month > 12)
+ return false;
wtime->tm_mon = eft->month - 1;
wtime->tm_year = eft->year - 1900;
/* day of the week [0-6], Sunday=0 */
wtime->tm_wday = compute_wday(eft);
+ if (wtime->tm_wday < 0)
+ return false;
/* day in the year [1-365]*/
wtime->tm_yday = compute_yday(eft);
@@ -106,6 +124,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
default:
wtime->tm_isdst = -1;
}
+
+ return true;
}
static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
@@ -122,7 +142,8 @@ static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
if (status != EFI_SUCCESS)
return -EINVAL;
- convert_from_efi_time(&eft, &wkalrm->time);
+ if (!convert_from_efi_time(&eft, &wkalrm->time))
+ return -EIO;
return rtc_valid_tm(&wkalrm->time);
}
@@ -163,7 +184,8 @@ static int efi_read_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
- convert_from_efi_time(&eft, tm);
+ if (!convert_from_efi_time(&eft, tm))
+ return -EIO;
return rtc_valid_tm(tm);
}
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 03b891129428..aa55f081c505 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -17,6 +17,8 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#define DRV_VERSION "0.1"
@@ -271,6 +273,13 @@ static int isl12022_probe(struct i2c_client *client,
return PTR_ERR_OR_ZERO(isl12022->rtc);
}
+#ifdef CONFIG_OF
+static struct of_device_id isl12022_dt_match[] = {
+ { .compatible = "isl,isl12022" },
+ { },
+};
+#endif
+
static const struct i2c_device_id isl12022_id[] = {
{ "isl12022", 0 },
{ }
@@ -280,6 +289,9 @@ MODULE_DEVICE_TABLE(i2c, isl12022_id);
static struct i2c_driver isl12022_driver = {
.driver = {
.name = "rtc-isl12022",
+#ifdef CONFIG_OF
+ .of_match_table = of_match_ptr(isl12022_dt_match),
+#endif
},
.probe = isl12022_probe,
.id_table = isl12022_id,
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 9efe118a28ba..d20a7f0786eb 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -492,16 +492,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
return ret;
}
-static struct regmap_config max77686_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-};
-
static int max77686_rtc_probe(struct platform_device *pdev)
{
struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
struct max77686_rtc_info *info;
- int ret, virq;
+ int ret;
dev_info(&pdev->dev, "%s\n", __func__);
@@ -514,14 +509,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->max77686 = max77686;
info->rtc = max77686->rtc;
- info->max77686->rtc_regmap = devm_regmap_init_i2c(info->max77686->rtc,
- &max77686_rtc_regmap_config);
- if (IS_ERR(info->max77686->rtc_regmap)) {
- ret = PTR_ERR(info->max77686->rtc_regmap);
- dev_err(info->max77686->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
+
platform_set_drvdata(pdev, info);
ret = max77686_rtc_init_reg(info);
@@ -550,15 +538,16 @@ static int max77686_rtc_probe(struct platform_device *pdev)
ret = -EINVAL;
goto err_rtc;
}
- virq = irq_create_mapping(max77686->irq_domain, MAX77686_RTCIRQ_RTCA1);
- if (!virq) {
+
+ info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
+ MAX77686_RTCIRQ_RTCA1);
+ if (!info->virq) {
ret = -ENXIO;
goto err_rtc;
}
- info->virq = virq;
- ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
- max77686_rtc_alarm_irq, 0, "rtc-alarm0", info);
+ ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
+ max77686_rtc_alarm_irq, 0, "rtc-alarm1", info);
if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->virq, ret);
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
new file mode 100644
index 000000000000..6a12bf62c504
--- /dev/null
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -0,0 +1,204 @@
+/*
+ * An I2C driver for the PCF85063 RTC
+ * Copyright 2014 Rose Technology
+ *
+ * Author: Søren Andersen <san@rosetechnology.dk>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * based on the other drivers in this same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/module.h>
+
+#define DRV_VERSION "0.0.1"
+
+#define PCF85063_REG_CTRL1 0x00 /* status */
+#define PCF85063_REG_CTRL2 0x01
+
+#define PCF85063_REG_SC 0x04 /* datetime */
+#define PCF85063_REG_MN 0x05
+#define PCF85063_REG_HR 0x06
+#define PCF85063_REG_DM 0x07
+#define PCF85063_REG_DW 0x08
+#define PCF85063_REG_MO 0x09
+#define PCF85063_REG_YR 0x0A
+
+#define PCF85063_MO_C 0x80 /* century */
+
+static struct i2c_driver pcf85063_driver;
+
+struct pcf85063 {
+ struct rtc_device *rtc;
+ int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
+ int voltage_low; /* indicates if a low_voltage was detected */
+};
+
+/*
+ * In the routines that deal directly with the pcf85063 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ struct pcf85063 *pcf85063 = i2c_get_clientdata(client);
+ unsigned char buf[13] = { PCF85063_REG_CTRL1 };
+ struct i2c_msg msgs[] = {
+ {/* setup read ptr */
+ .addr = client->addr,
+ .len = 1,
+ .buf = buf
+ },
+ {/* read status + date */
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 13,
+ .buf = buf
+ },
+ };
+
+ /* read registers */
+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+
+ tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F);
+ tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F);
+ tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */
+ tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F);
+ tm->tm_wday = buf[PCF85063_REG_DW] & 0x07;
+ tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+ tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]);
+ if (tm->tm_year < 70)
+ tm->tm_year += 100; /* assume we are in 1970...2069 */
+ /* detect the polarity heuristically. see note above. */
+ pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
+ (tm->tm_year >= 100) : (tm->tm_year < 100);
+
+ /* the clock can give out invalid datetime, but we cannot return
+ * -EINVAL otherwise hwclock will refuse to set the time on bootup.
+ */
+ if (rtc_valid_tm(tm) < 0)
+ dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+ return 0;
+}
+
+static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ int i = 0, err = 0;
+ unsigned char buf[11];
+
+ /* Control & status */
+ buf[PCF85063_REG_CTRL1] = 0;
+ buf[PCF85063_REG_CTRL2] = 5;
+
+ /* hours, minutes and seconds */
+ buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F;
+
+ buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min);
+ buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour);
+
+ /* Day of month, 1 - 31 */
+ buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday);
+
+ /* Day, 0 - 6 */
+ buf[PCF85063_REG_DW] = tm->tm_wday & 0x07;
+
+ /* month, 1 - 12 */
+ buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1);
+
+ /* year and century */
+ buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100);
+
+ /* write register's data */
+ for (i = 0; i < sizeof(buf); i++) {
+ unsigned char data[2] = { i, buf[i] };
+
+ err = i2c_master_send(client, data, sizeof(data));
+ if (err != sizeof(data)) {
+ dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n",
+ __func__, err, data[0], data[1]);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int pcf85063_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf85063_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf85063_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return pcf85063_set_datetime(to_i2c_client(dev), tm);
+}
+
+static const struct rtc_class_ops pcf85063_rtc_ops = {
+ .read_time = pcf85063_rtc_read_time,
+ .set_time = pcf85063_rtc_set_time
+};
+
+static int pcf85063_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pcf85063 *pcf85063;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
+ GFP_KERNEL);
+ if (!pcf85063)
+ return -ENOMEM;
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+ i2c_set_clientdata(client, pcf85063);
+
+ pcf85063->rtc = devm_rtc_device_register(&client->dev,
+ pcf85063_driver.driver.name,
+ &pcf85063_rtc_ops, THIS_MODULE);
+
+ return PTR_ERR_OR_ZERO(pcf85063->rtc);
+}
+
+static const struct i2c_device_id pcf85063_id[] = {
+ { "pcf85063", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf85063_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pcf85063_of_match[] = {
+ { .compatible = "nxp,pcf85063" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pcf85063_of_match);
+#endif
+
+static struct i2c_driver pcf85063_driver = {
+ .driver = {
+ .name = "rtc-pcf85063",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(pcf85063_of_match),
+ },
+ .probe = pcf85063_probe,
+ .id_table = pcf85063_id,
+};
+
+module_i2c_driver(pcf85063_driver);
+
+MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>");
+MODULE_DESCRIPTION("PCF85063 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 63b558c48196..5a197d9dc7e7 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -26,6 +26,8 @@
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
+#define PCF8563_BIT_AIE (1 << 1)
+#define PCF8563_BIT_AF (1 << 3)
#define PCF8563_REG_SC 0x02 /* datetime */
#define PCF8563_REG_MN 0x03
@@ -36,9 +38,6 @@
#define PCF8563_REG_YR 0x08
#define PCF8563_REG_AMN 0x09 /* alarm */
-#define PCF8563_REG_AHR 0x0A
-#define PCF8563_REG_ADM 0x0B
-#define PCF8563_REG_ADW 0x0C
#define PCF8563_REG_CLKO 0x0D /* clock out */
#define PCF8563_REG_TMRC 0x0E /* timer control */
@@ -67,37 +66,133 @@ struct pcf8563 {
*/
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
int voltage_low; /* incicates if a low_voltage was detected */
+
+ struct i2c_client *client;
};
-/*
- * In the routines that deal directly with the pcf8563 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- */
-static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
+ unsigned char length, unsigned char *buf)
{
- struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
- unsigned char buf[13] = { PCF8563_REG_ST1 };
-
struct i2c_msg msgs[] = {
{/* setup read ptr */
.addr = client->addr,
.len = 1,
- .buf = buf
+ .buf = &reg,
},
- {/* read status + date */
+ {
.addr = client->addr,
.flags = I2C_M_RD,
- .len = 13,
+ .len = length,
.buf = buf
},
};
- /* read registers */
if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
+ return 0;
+}
+
+static int pcf8563_write_block_data(struct i2c_client *client,
+ unsigned char reg, unsigned char length,
+ unsigned char *buf)
+{
+ int i, err;
+
+ for (i = 0; i < length; i++) {
+ unsigned char data[2] = { reg + i, buf[i] };
+
+ err = i2c_master_send(client, data, sizeof(data));
+ if (err != sizeof(data)) {
+ dev_err(&client->dev,
+ "%s: err=%d addr=%02x, data=%02x\n",
+ __func__, err, data[0], data[1]);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
+{
+ unsigned char buf[2];
+ int err;
+
+ err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, buf + 1);
+ if (err < 0)
+ return err;
+
+ if (on)
+ buf[1] |= PCF8563_BIT_AIE;
+ else
+ buf[1] &= ~PCF8563_BIT_AIE;
+
+ buf[1] &= ~PCF8563_BIT_AF;
+ buf[0] = PCF8563_REG_ST2;
+
+ err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, buf + 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: write error\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
+ unsigned char *pen)
+{
+ unsigned char buf;
+ int err;
+
+ err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ if (err)
+ return err;
+
+ if (en)
+ *en = !!(buf & PCF8563_BIT_AIE);
+ if (pen)
+ *pen = !!(buf & PCF8563_BIT_AF);
+
+ return 0;
+}
+
+static irqreturn_t pcf8563_irq(int irq, void *dev_id)
+{
+ struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id);
+ int err;
+ char pending;
+
+ err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
+ if (err < 0)
+ return err;
+
+ if (pending) {
+ rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
+ pcf8563_set_alarm_mode(pcf8563->client, 1);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+ struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ unsigned char buf[9];
+ int err;
+
+ err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf);
+ if (err)
+ return err;
+
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
pcf8563->voltage_low = 1;
dev_info(&client->dev,
@@ -144,7 +239,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
- int i, err;
+ int err;
unsigned char buf[9];
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
@@ -170,19 +265,10 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
- /* write register's data */
- for (i = 0; i < 7; i++) {
- unsigned char data[2] = { PCF8563_REG_SC + i,
- buf[PCF8563_REG_SC + i] };
-
- err = i2c_master_send(client, data, sizeof(data));
- if (err != sizeof(data)) {
- dev_err(&client->dev,
- "%s: err=%d addr=%02x, data=%02x\n",
- __func__, err, data[0], data[1]);
- return -EIO;
- }
- }
+ err = pcf8563_write_block_data(client, PCF8563_REG_SC,
+ 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
+ if (err)
+ return err;
return 0;
}
@@ -235,16 +321,83 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
return pcf8563_set_datetime(to_i2c_client(dev), tm);
}
+static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char buf[4];
+ int err;
+
+ err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf);
+ if (err)
+ return err;
+
+ dev_dbg(&client->dev,
+ "%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+
+ tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
+ tm->time.tm_hour = bcd2bin(buf[1] & 0x7F);
+ tm->time.tm_mday = bcd2bin(buf[2] & 0x1F);
+ tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
+ tm->time.tm_mon = -1;
+ tm->time.tm_year = -1;
+ tm->time.tm_yday = -1;
+ tm->time.tm_isdst = -1;
+
+ err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
+ if (err < 0)
+ return err;
+
+ dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
+ " enabled=%d, pending=%d\n", __func__, tm->time.tm_min,
+ tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
+ tm->enabled, tm->pending);
+
+ return 0;
+}
+
+static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char buf[4];
+ int err;
+
+ dev_dbg(dev, "%s, min=%d hour=%d wday=%d mday=%d "
+ "enabled=%d pending=%d\n", __func__,
+ tm->time.tm_min, tm->time.tm_hour, tm->time.tm_wday,
+ tm->time.tm_mday, tm->enabled, tm->pending);
+
+ buf[0] = bin2bcd(tm->time.tm_min);
+ buf[1] = bin2bcd(tm->time.tm_hour);
+ buf[2] = bin2bcd(tm->time.tm_mday);
+ buf[3] = tm->time.tm_wday & 0x07;
+
+ err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
+ if (err)
+ return err;
+
+ return pcf8563_set_alarm_mode(client, 1);
+}
+
+static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
+{
+ return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
+}
+
static const struct rtc_class_ops pcf8563_rtc_ops = {
.ioctl = pcf8563_rtc_ioctl,
.read_time = pcf8563_rtc_read_time,
.set_time = pcf8563_rtc_set_time,
+ .read_alarm = pcf8563_rtc_read_alarm,
+ .set_alarm = pcf8563_rtc_set_alarm,
+ .alarm_irq_enable = pcf8563_irq_enable,
};
static int pcf8563_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8563 *pcf8563;
+ int err;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -259,12 +412,30 @@ static int pcf8563_probe(struct i2c_client *client,
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
i2c_set_clientdata(client, pcf8563);
+ pcf8563->client = client;
+ device_set_wakeup_capable(&client->dev, 1);
pcf8563->rtc = devm_rtc_device_register(&client->dev,
pcf8563_driver.driver.name,
&pcf8563_rtc_ops, THIS_MODULE);
- return PTR_ERR_OR_ZERO(pcf8563->rtc);
+ if (IS_ERR(pcf8563->rtc))
+ return PTR_ERR(pcf8563->rtc);
+
+ if (client->irq > 0) {
+ err = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, pcf8563_irq,
+ IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING,
+ pcf8563->rtc->name, client);
+ if (err) {
+ dev_err(&client->dev, "unable to request IRQ %d\n",
+ client->irq);
+ return err;
+ }
+
+ }
+
+ return 0;
}
static const struct i2c_device_id pcf8563_id[] = {
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
index 7af00208d637..2583349fbde5 100644
--- a/drivers/rtc/rtc-tps65910.c
+++ b/drivers/rtc/rtc-tps65910.c
@@ -258,6 +258,8 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ platform_set_drvdata(pdev, tps_rtc);
+
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
@@ -283,8 +285,6 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
return ret;
}
- platform_set_drvdata(pdev, tps_rtc);
-
return 0;
}
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 1eef0f586950..5df05f26b7d9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -42,8 +42,10 @@
* SECTION: exported variables of dasd.c
*/
debug_info_t *dasd_debug_area;
+EXPORT_SYMBOL(dasd_debug_area);
static struct dentry *dasd_debugfs_root_entry;
struct dasd_discipline *dasd_diag_discipline_pointer;
+EXPORT_SYMBOL(dasd_diag_discipline_pointer);
void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
@@ -164,6 +166,7 @@ struct dasd_block *dasd_alloc_block(void)
return block;
}
+EXPORT_SYMBOL_GPL(dasd_alloc_block);
/*
* Free memory of a device structure.
@@ -172,6 +175,7 @@ void dasd_free_block(struct dasd_block *block)
{
kfree(block);
}
+EXPORT_SYMBOL_GPL(dasd_free_block);
/*
* Make a new device known to the system.
@@ -281,10 +285,15 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
{
int rc;
+ if (device->discipline->basic_to_known) {
+ rc = device->discipline->basic_to_known(device);
+ if (rc)
+ return rc;
+ }
+
if (device->block) {
dasd_profile_exit(&device->block->profile);
- if (device->block->debugfs_dentry)
- debugfs_remove(device->block->debugfs_dentry);
+ debugfs_remove(device->block->debugfs_dentry);
dasd_gendisk_free(device->block);
dasd_block_clear_timer(device->block);
}
@@ -293,9 +302,7 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
return rc;
dasd_device_clear_timer(device);
dasd_profile_exit(&device->profile);
- if (device->debugfs_dentry)
- debugfs_remove(device->debugfs_dentry);
-
+ debugfs_remove(device->debugfs_dentry);
DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
if (device->debug_area != NULL) {
debug_unregister(device->debug_area);
@@ -374,11 +381,6 @@ static int dasd_state_ready_to_basic(struct dasd_device *device)
{
int rc;
- if (device->discipline->ready_to_basic) {
- rc = device->discipline->ready_to_basic(device);
- if (rc)
- return rc;
- }
device->state = DASD_STATE_BASIC;
if (device->block) {
struct dasd_block *block = device->block;
@@ -579,6 +581,7 @@ void dasd_kick_device(struct dasd_device *device)
/* queue call to dasd_kick_device to the kernel event daemon. */
schedule_work(&device->kick_work);
}
+EXPORT_SYMBOL(dasd_kick_device);
/*
* dasd_reload_device will schedule a call do do_reload_device to the kernel
@@ -639,6 +642,7 @@ void dasd_set_target_state(struct dasd_device *device, int target)
mutex_unlock(&device->state_mutex);
dasd_put_device(device);
}
+EXPORT_SYMBOL(dasd_set_target_state);
/*
* Enable devices with device numbers in [from..to].
@@ -661,6 +665,7 @@ void dasd_enable_device(struct dasd_device *device)
if (device->discipline->kick_validate)
device->discipline->kick_validate(device);
}
+EXPORT_SYMBOL(dasd_enable_device);
/*
* SECTION: device operation (interrupt handler, start i/o, term i/o ...)
@@ -972,37 +977,37 @@ static void dasd_stats_seq_print(struct seq_file *m,
seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
- seq_printf(m, "histogram_sectors ");
+ seq_puts(m, "histogram_sectors ");
dasd_stats_array(m, data->dasd_io_secs);
- seq_printf(m, "histogram_io_times ");
+ seq_puts(m, "histogram_io_times ");
dasd_stats_array(m, data->dasd_io_times);
- seq_printf(m, "histogram_io_times_weighted ");
+ seq_puts(m, "histogram_io_times_weighted ");
dasd_stats_array(m, data->dasd_io_timps);
- seq_printf(m, "histogram_time_build_to_ssch ");
+ seq_puts(m, "histogram_time_build_to_ssch ");
dasd_stats_array(m, data->dasd_io_time1);
- seq_printf(m, "histogram_time_ssch_to_irq ");
+ seq_puts(m, "histogram_time_ssch_to_irq ");
dasd_stats_array(m, data->dasd_io_time2);
- seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+ seq_puts(m, "histogram_time_ssch_to_irq_weighted ");
dasd_stats_array(m, data->dasd_io_time2ps);
- seq_printf(m, "histogram_time_irq_to_end ");
+ seq_puts(m, "histogram_time_irq_to_end ");
dasd_stats_array(m, data->dasd_io_time3);
- seq_printf(m, "histogram_ccw_queue_length ");
+ seq_puts(m, "histogram_ccw_queue_length ");
dasd_stats_array(m, data->dasd_io_nr_req);
seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
- seq_printf(m, "histogram_read_sectors ");
+ seq_puts(m, "histogram_read_sectors ");
dasd_stats_array(m, data->dasd_read_secs);
- seq_printf(m, "histogram_read_times ");
+ seq_puts(m, "histogram_read_times ");
dasd_stats_array(m, data->dasd_read_times);
- seq_printf(m, "histogram_read_time_build_to_ssch ");
+ seq_puts(m, "histogram_read_time_build_to_ssch ");
dasd_stats_array(m, data->dasd_read_time1);
- seq_printf(m, "histogram_read_time_ssch_to_irq ");
+ seq_puts(m, "histogram_read_time_ssch_to_irq ");
dasd_stats_array(m, data->dasd_read_time2);
- seq_printf(m, "histogram_read_time_irq_to_end ");
+ seq_puts(m, "histogram_read_time_irq_to_end ");
dasd_stats_array(m, data->dasd_read_time3);
- seq_printf(m, "histogram_read_ccw_queue_length ");
+ seq_puts(m, "histogram_read_ccw_queue_length ");
dasd_stats_array(m, data->dasd_read_nr_req);
}
@@ -1016,7 +1021,7 @@ static int dasd_stats_show(struct seq_file *m, void *v)
data = profile->data;
if (!data) {
spin_unlock_bh(&profile->lock);
- seq_printf(m, "disabled\n");
+ seq_puts(m, "disabled\n");
return 0;
}
dasd_stats_seq_print(m, data);
@@ -1069,7 +1074,7 @@ static ssize_t dasd_stats_global_write(struct file *file,
static int dasd_stats_global_show(struct seq_file *m, void *v)
{
if (!dasd_global_profile_level) {
- seq_printf(m, "disabled\n");
+ seq_puts(m, "disabled\n");
return 0;
}
dasd_stats_seq_print(m, &dasd_global_profile_data);
@@ -1111,23 +1116,17 @@ static void dasd_profile_init(struct dasd_profile *profile,
static void dasd_profile_exit(struct dasd_profile *profile)
{
dasd_profile_off(profile);
- if (profile->dentry) {
- debugfs_remove(profile->dentry);
- profile->dentry = NULL;
- }
+ debugfs_remove(profile->dentry);
+ profile->dentry = NULL;
}
static void dasd_statistics_removeroot(void)
{
dasd_global_profile_level = DASD_PROFILE_OFF;
- if (dasd_global_profile_dentry) {
- debugfs_remove(dasd_global_profile_dentry);
- dasd_global_profile_dentry = NULL;
- }
- if (dasd_debugfs_global_entry)
- debugfs_remove(dasd_debugfs_global_entry);
- if (dasd_debugfs_root_entry)
- debugfs_remove(dasd_debugfs_root_entry);
+ debugfs_remove(dasd_global_profile_dentry);
+ dasd_global_profile_dentry = NULL;
+ debugfs_remove(dasd_debugfs_global_entry);
+ debugfs_remove(dasd_debugfs_root_entry);
}
static void dasd_statistics_createroot(void)
@@ -1178,7 +1177,7 @@ static void dasd_statistics_removeroot(void)
int dasd_stats_generic_show(struct seq_file *m, void *v)
{
- seq_printf(m, "Statistics are not activated in this kernel\n");
+ seq_puts(m, "Statistics are not activated in this kernel\n");
return 0;
}
@@ -1243,6 +1242,7 @@ struct dasd_ccw_req *dasd_kmalloc_request(int magic, int cplength,
dasd_get_device(device);
return cqr;
}
+EXPORT_SYMBOL(dasd_kmalloc_request);
struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
int datasize,
@@ -1282,6 +1282,7 @@ struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
dasd_get_device(device);
return cqr;
}
+EXPORT_SYMBOL(dasd_smalloc_request);
/*
* Free memory of a channel program. This function needs to free all the
@@ -1304,6 +1305,7 @@ void dasd_kfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
kfree(cqr);
dasd_put_device(device);
}
+EXPORT_SYMBOL(dasd_kfree_request);
void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
{
@@ -1314,6 +1316,7 @@ void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
spin_unlock_irqrestore(&device->mem_lock, flags);
dasd_put_device(device);
}
+EXPORT_SYMBOL(dasd_sfree_request);
/*
* Check discipline magic in cqr.
@@ -1391,6 +1394,7 @@ int dasd_term_IO(struct dasd_ccw_req *cqr)
dasd_schedule_device_bh(device);
return rc;
}
+EXPORT_SYMBOL(dasd_term_IO);
/*
* Start the i/o. This start_IO can fail if the channel is really busy.
@@ -1509,6 +1513,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
cqr->intrc = rc;
return rc;
}
+EXPORT_SYMBOL(dasd_start_IO);
/*
* Timeout function for dasd devices. This is used for different purposes
@@ -1541,6 +1546,7 @@ void dasd_device_set_timer(struct dasd_device *device, int expires)
else
mod_timer(&device->timer, jiffies + expires);
}
+EXPORT_SYMBOL(dasd_device_set_timer);
/*
* Clear timeout for a device.
@@ -1549,6 +1555,7 @@ void dasd_device_clear_timer(struct dasd_device *device)
{
del_timer(&device->timer);
}
+EXPORT_SYMBOL(dasd_device_clear_timer);
static void dasd_handle_killed_request(struct ccw_device *cdev,
unsigned long intparm)
@@ -1601,6 +1608,7 @@ void dasd_generic_handle_state_change(struct dasd_device *device)
if (device->block)
dasd_schedule_block_bh(device->block);
}
+EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
/*
* Interrupt handler for "normal" ssch-io based dasd devices.
@@ -1667,8 +1675,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
if (cqr->status == DASD_CQR_CLEAR_PENDING &&
scsw_fctl(&irb->scsw) & SCSW_FCTL_CLEAR_FUNC) {
cqr->status = DASD_CQR_CLEARED;
+ if (cqr->callback_data == DASD_SLEEPON_START_TAG)
+ cqr->callback_data = DASD_SLEEPON_END_TAG;
dasd_device_clear_timer(device);
wake_up(&dasd_flush_wq);
+ wake_up(&generic_waitq);
dasd_schedule_device_bh(device);
return;
}
@@ -1722,6 +1733,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
dasd_device_clear_timer(device);
dasd_schedule_device_bh(device);
}
+EXPORT_SYMBOL(dasd_int_handler);
enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb)
{
@@ -1995,6 +2007,7 @@ finished:
__dasd_device_process_final_queue(device, &flush_queue);
return rc;
}
+EXPORT_SYMBOL_GPL(dasd_flush_device_queue);
/*
* Acquire the device lock and process queues for the device.
@@ -2034,6 +2047,7 @@ void dasd_schedule_device_bh(struct dasd_device *device)
dasd_get_device(device);
tasklet_hi_schedule(&device->tasklet);
}
+EXPORT_SYMBOL(dasd_schedule_device_bh);
void dasd_device_set_stop_bits(struct dasd_device *device, int bits)
{
@@ -2066,6 +2080,7 @@ void dasd_add_request_head(struct dasd_ccw_req *cqr)
dasd_schedule_device_bh(device);
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
}
+EXPORT_SYMBOL(dasd_add_request_head);
/*
* Queue a request to the tail of the device ccw_queue.
@@ -2084,6 +2099,7 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr)
dasd_schedule_device_bh(device);
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
}
+EXPORT_SYMBOL(dasd_add_request_tail);
/*
* Wakeup helper for the 'sleep_on' functions.
@@ -2291,13 +2307,27 @@ retry:
rc = 0;
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
- if (__dasd_sleep_on_erp(cqr))
- rc = 1;
+ /*
+ * for alias devices simplify error recovery and
+ * return to upper layer
+ */
+ if (cqr->startdev != cqr->basedev &&
+ (cqr->status == DASD_CQR_TERMINATED ||
+ cqr->status == DASD_CQR_NEED_ERP))
+ return -EAGAIN;
+ else {
+ /* normal recovery for basedev IO */
+ if (__dasd_sleep_on_erp(cqr)) {
+ if (!cqr->status == DASD_CQR_TERMINATED &&
+ !cqr->status == DASD_CQR_NEED_ERP)
+ break;
+ rc = 1;
+ }
+ }
}
if (rc)
goto retry;
-
return 0;
}
@@ -2309,6 +2339,7 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
{
return _dasd_sleep_on(cqr, 0);
}
+EXPORT_SYMBOL(dasd_sleep_on);
/*
* Start requests from a ccw_queue and wait for their completion.
@@ -2327,6 +2358,7 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
{
return _dasd_sleep_on(cqr, 1);
}
+EXPORT_SYMBOL(dasd_sleep_on_interruptible);
/*
* Whoa nelly now it gets really hairy. For some functions (e.g. steal lock
@@ -2401,6 +2433,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
return rc;
}
+EXPORT_SYMBOL(dasd_sleep_on_immediatly);
/*
* Cancels a request that was started with dasd_sleep_on_req.
@@ -2423,6 +2456,8 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr)
case DASD_CQR_QUEUED:
/* request was not started - just set to cleared */
cqr->status = DASD_CQR_CLEARED;
+ if (cqr->callback_data == DASD_SLEEPON_START_TAG)
+ cqr->callback_data = DASD_SLEEPON_END_TAG;
break;
case DASD_CQR_IN_IO:
/* request in IO - terminate IO and release again */
@@ -2442,6 +2477,7 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr)
dasd_schedule_device_bh(device);
return rc;
}
+EXPORT_SYMBOL(dasd_cancel_req);
/*
* SECTION: Operations of the dasd_block layer.
@@ -2475,6 +2511,7 @@ void dasd_block_set_timer(struct dasd_block *block, int expires)
else
mod_timer(&block->timer, jiffies + expires);
}
+EXPORT_SYMBOL(dasd_block_set_timer);
/*
* Clear timeout for a dasd_block.
@@ -2483,6 +2520,7 @@ void dasd_block_clear_timer(struct dasd_block *block)
{
del_timer(&block->timer);
}
+EXPORT_SYMBOL(dasd_block_clear_timer);
/*
* Process finished error recovery ccw.
@@ -2864,6 +2902,7 @@ void dasd_schedule_block_bh(struct dasd_block *block)
dasd_get_device(block->base);
tasklet_hi_schedule(&block->tasklet);
}
+EXPORT_SYMBOL(dasd_schedule_block_bh);
/*
@@ -3202,8 +3241,8 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
ret = ccw_device_set_online(cdev);
if (ret)
- pr_warning("%s: Setting the DASD online failed with rc=%d\n",
- dev_name(&cdev->dev), ret);
+ pr_warn("%s: Setting the DASD online failed with rc=%d\n",
+ dev_name(&cdev->dev), ret);
}
/*
@@ -3234,6 +3273,7 @@ int dasd_generic_probe(struct ccw_device *cdev,
async_schedule(dasd_generic_auto_online, cdev);
return 0;
}
+EXPORT_SYMBOL_GPL(dasd_generic_probe);
/*
* This will one day be called from a global not_oper handler.
@@ -3276,6 +3316,7 @@ void dasd_generic_remove(struct ccw_device *cdev)
dasd_remove_sysfs_files(cdev);
}
+EXPORT_SYMBOL_GPL(dasd_generic_remove);
/*
* Activate a device. This is called from dasd_{eckd,fba}_probe() when either
@@ -3298,9 +3339,8 @@ int dasd_generic_set_online(struct ccw_device *cdev,
discipline = base_discipline;
if (device->features & DASD_FEATURE_USEDIAG) {
if (!dasd_diag_discipline_pointer) {
- pr_warning("%s Setting the DASD online failed because "
- "of missing DIAG discipline\n",
- dev_name(&cdev->dev));
+ pr_warn("%s Setting the DASD online failed because of missing DIAG discipline\n",
+ dev_name(&cdev->dev));
dasd_delete_device(device);
return -ENODEV;
}
@@ -3321,9 +3361,8 @@ int dasd_generic_set_online(struct ccw_device *cdev,
/* check_device will allocate block device if necessary */
rc = discipline->check_device(device);
if (rc) {
- pr_warning("%s Setting the DASD online with discipline %s "
- "failed with rc=%i\n",
- dev_name(&cdev->dev), discipline->name, rc);
+ pr_warn("%s Setting the DASD online with discipline %s failed with rc=%i\n",
+ dev_name(&cdev->dev), discipline->name, rc);
module_put(discipline->owner);
module_put(base_discipline->owner);
dasd_delete_device(device);
@@ -3332,8 +3371,8 @@ int dasd_generic_set_online(struct ccw_device *cdev,
dasd_set_target_state(device, DASD_STATE_ONLINE);
if (device->state <= DASD_STATE_KNOWN) {
- pr_warning("%s Setting the DASD online failed because of a "
- "missing discipline\n", dev_name(&cdev->dev));
+ pr_warn("%s Setting the DASD online failed because of a missing discipline\n",
+ dev_name(&cdev->dev));
rc = -ENODEV;
dasd_set_target_state(device, DASD_STATE_NEW);
if (device->block)
@@ -3348,6 +3387,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
dasd_put_device(device);
return rc;
}
+EXPORT_SYMBOL_GPL(dasd_generic_set_online);
int dasd_generic_set_offline(struct ccw_device *cdev)
{
@@ -3371,13 +3411,11 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
open_count = atomic_read(&device->block->open_count);
if (open_count > max_count) {
if (open_count > 0)
- pr_warning("%s: The DASD cannot be set offline "
- "with open count %i\n",
- dev_name(&cdev->dev), open_count);
+ pr_warn("%s: The DASD cannot be set offline with open count %i\n",
+ dev_name(&cdev->dev), open_count);
else
- pr_warning("%s: The DASD cannot be set offline "
- "while it is in use\n",
- dev_name(&cdev->dev));
+ pr_warn("%s: The DASD cannot be set offline while it is in use\n",
+ dev_name(&cdev->dev));
clear_bit(DASD_FLAG_OFFLINE, &device->flags);
dasd_put_device(device);
return -EBUSY;
@@ -3451,6 +3489,7 @@ interrupted:
dasd_put_device(device);
return rc;
}
+EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
int dasd_generic_last_path_gone(struct dasd_device *device)
{
@@ -3492,6 +3531,10 @@ int dasd_generic_path_operational(struct dasd_device *device)
dasd_schedule_device_bh(device);
if (device->block)
dasd_schedule_block_bh(device->block);
+
+ if (!device->stopped)
+ wake_up(&generic_waitq);
+
return 1;
}
EXPORT_SYMBOL_GPL(dasd_generic_path_operational);
@@ -3523,6 +3566,7 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
dasd_put_device(device);
return ret;
}
+EXPORT_SYMBOL_GPL(dasd_generic_notify);
void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
{
@@ -3872,39 +3916,3 @@ failed:
module_init(dasd_init);
module_exit(dasd_exit);
-
-EXPORT_SYMBOL(dasd_debug_area);
-EXPORT_SYMBOL(dasd_diag_discipline_pointer);
-
-EXPORT_SYMBOL(dasd_add_request_head);
-EXPORT_SYMBOL(dasd_add_request_tail);
-EXPORT_SYMBOL(dasd_cancel_req);
-EXPORT_SYMBOL(dasd_device_clear_timer);
-EXPORT_SYMBOL(dasd_block_clear_timer);
-EXPORT_SYMBOL(dasd_enable_device);
-EXPORT_SYMBOL(dasd_int_handler);
-EXPORT_SYMBOL(dasd_kfree_request);
-EXPORT_SYMBOL(dasd_kick_device);
-EXPORT_SYMBOL(dasd_kmalloc_request);
-EXPORT_SYMBOL(dasd_schedule_device_bh);
-EXPORT_SYMBOL(dasd_schedule_block_bh);
-EXPORT_SYMBOL(dasd_set_target_state);
-EXPORT_SYMBOL(dasd_device_set_timer);
-EXPORT_SYMBOL(dasd_block_set_timer);
-EXPORT_SYMBOL(dasd_sfree_request);
-EXPORT_SYMBOL(dasd_sleep_on);
-EXPORT_SYMBOL(dasd_sleep_on_immediatly);
-EXPORT_SYMBOL(dasd_sleep_on_interruptible);
-EXPORT_SYMBOL(dasd_smalloc_request);
-EXPORT_SYMBOL(dasd_start_IO);
-EXPORT_SYMBOL(dasd_term_IO);
-
-EXPORT_SYMBOL_GPL(dasd_generic_probe);
-EXPORT_SYMBOL_GPL(dasd_generic_remove);
-EXPORT_SYMBOL_GPL(dasd_generic_notify);
-EXPORT_SYMBOL_GPL(dasd_generic_set_online);
-EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
-EXPORT_SYMBOL_GPL(dasd_generic_handle_state_change);
-EXPORT_SYMBOL_GPL(dasd_flush_device_queue);
-EXPORT_SYMBOL_GPL(dasd_alloc_block);
-EXPORT_SYMBOL_GPL(dasd_free_block);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2e8e0755070b..51dea7baf02c 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2039,7 +2039,7 @@ static int dasd_eckd_online_to_ready(struct dasd_device *device)
return 0;
};
-static int dasd_eckd_ready_to_basic(struct dasd_device *device)
+static int dasd_eckd_basic_to_known(struct dasd_device *device)
{
return dasd_alias_remove_device(device);
};
@@ -2061,11 +2061,12 @@ dasd_eckd_fill_geometry(struct dasd_block *block, struct hd_geometry *geo)
static struct dasd_ccw_req *
dasd_eckd_build_format(struct dasd_device *base,
- struct format_data_t *fdata)
+ struct format_data_t *fdata,
+ int enable_pav)
{
struct dasd_eckd_private *base_priv;
struct dasd_eckd_private *start_priv;
- struct dasd_device *startdev;
+ struct dasd_device *startdev = NULL;
struct dasd_ccw_req *fcp;
struct eckd_count *ect;
struct ch_t address;
@@ -2079,7 +2080,9 @@ dasd_eckd_build_format(struct dasd_device *base,
int nr_tracks;
int use_prefix;
- startdev = dasd_alias_get_start_dev(base);
+ if (enable_pav)
+ startdev = dasd_alias_get_start_dev(base);
+
if (!startdev)
startdev = base;
@@ -2309,6 +2312,7 @@ dasd_eckd_build_format(struct dasd_device *base,
fcp->startdev = startdev;
fcp->memdev = startdev;
+ fcp->basedev = base;
fcp->retries = 256;
fcp->expires = startdev->default_expires * HZ;
fcp->buildclk = get_tod_clock();
@@ -2319,7 +2323,8 @@ dasd_eckd_build_format(struct dasd_device *base,
static int
dasd_eckd_format_device(struct dasd_device *base,
- struct format_data_t *fdata)
+ struct format_data_t *fdata,
+ int enable_pav)
{
struct dasd_ccw_req *cqr, *n;
struct dasd_block *block;
@@ -2327,7 +2332,7 @@ dasd_eckd_format_device(struct dasd_device *base,
struct list_head format_queue;
struct dasd_device *device;
int old_stop, format_step;
- int step, rc = 0;
+ int step, rc = 0, sleep_rc;
block = base->block;
private = (struct dasd_eckd_private *) base->private;
@@ -2361,11 +2366,11 @@ dasd_eckd_format_device(struct dasd_device *base,
}
INIT_LIST_HEAD(&format_queue);
- old_stop = fdata->stop_unit;
+ old_stop = fdata->stop_unit;
while (fdata->start_unit <= 1) {
fdata->stop_unit = fdata->start_unit;
- cqr = dasd_eckd_build_format(base, fdata);
+ cqr = dasd_eckd_build_format(base, fdata, enable_pav);
list_add(&cqr->blocklist, &format_queue);
fdata->stop_unit = old_stop;
@@ -2383,7 +2388,7 @@ retry:
if (step > format_step)
fdata->stop_unit = fdata->start_unit + format_step - 1;
- cqr = dasd_eckd_build_format(base, fdata);
+ cqr = dasd_eckd_build_format(base, fdata, enable_pav);
if (IS_ERR(cqr)) {
if (PTR_ERR(cqr) == -ENOMEM) {
/*
@@ -2403,7 +2408,7 @@ retry:
}
sleep:
- dasd_sleep_on_queue(&format_queue);
+ sleep_rc = dasd_sleep_on_queue(&format_queue);
list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
device = cqr->startdev;
@@ -2415,6 +2420,9 @@ sleep:
private->count--;
}
+ if (sleep_rc)
+ return sleep_rc;
+
/*
* in case of ENOMEM we need to retry after
* first requests are finished
@@ -4511,7 +4519,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.verify_path = dasd_eckd_verify_path,
.basic_to_ready = dasd_eckd_basic_to_ready,
.online_to_ready = dasd_eckd_online_to_ready,
- .ready_to_basic = dasd_eckd_ready_to_basic,
+ .basic_to_known = dasd_eckd_basic_to_known,
.fill_geometry = dasd_eckd_fill_geometry,
.start_IO = dasd_start_IO,
.term_IO = dasd_term_IO,
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 690001af0d09..c20170166909 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -175,6 +175,7 @@ struct dasd_ccw_req {
struct dasd_block *block; /* the originating block device */
struct dasd_device *memdev; /* the device used to allocate this */
struct dasd_device *startdev; /* device the request is started on */
+ struct dasd_device *basedev; /* base device if no block->base */
void *cpaddr; /* address of ccw or tcw */
unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */
char status; /* status of this request */
@@ -304,7 +305,7 @@ struct dasd_discipline {
*/
int (*basic_to_ready) (struct dasd_device *);
int (*online_to_ready) (struct dasd_device *);
- int (*ready_to_basic) (struct dasd_device *);
+ int (*basic_to_known)(struct dasd_device *);
/* (struct dasd_device *);
* Device operation functions. build_cp creates a ccw chain for
@@ -321,7 +322,7 @@ struct dasd_discipline {
int (*term_IO) (struct dasd_ccw_req *);
void (*handle_terminated_request) (struct dasd_ccw_req *);
int (*format_device) (struct dasd_device *,
- struct format_data_t *);
+ struct format_data_t *, int enable_pav);
int (*free_cp) (struct dasd_ccw_req *, struct request *);
/*
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 25a0f2f8b0b9..02837d0ad942 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -203,7 +203,9 @@ static int
dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
struct dasd_device *base;
- int rc;
+ int enable_pav = 1;
+ int rc, retries;
+ int start, stop;
base = block->base;
if (base->discipline->format_device == NULL)
@@ -231,11 +233,30 @@ dasd_format(struct dasd_block *block, struct format_data_t *fdata)
bdput(bdev);
}
- rc = base->discipline->format_device(base, fdata);
- if (rc)
- return rc;
-
- return 0;
+ retries = 255;
+ /* backup start- and endtrack for retries */
+ start = fdata->start_unit;
+ stop = fdata->stop_unit;
+ do {
+ rc = base->discipline->format_device(base, fdata, enable_pav);
+ if (rc) {
+ if (rc == -EAGAIN) {
+ retries--;
+ /* disable PAV in case of errors */
+ enable_pav = 0;
+ fdata->start_unit = start;
+ fdata->stop_unit = stop;
+ } else
+ return rc;
+ } else
+ /* success */
+ break;
+ } while (retries);
+
+ if (!retries)
+ return -EIO;
+ else
+ return 0;
}
/*
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 5af7f0bd6125..a6d47e5eee9e 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
unsigned long flags;
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
- if (raw->flags & RAW3215_TIMER_RUNS) {
- del_timer(&raw->timer);
- raw->flags &= ~RAW3215_TIMER_RUNS;
- if (!(raw->port.flags & ASYNC_SUSPENDED)) {
- raw3215_mk_write_req(raw);
- raw3215_start_io(raw);
+ raw->flags &= ~RAW3215_TIMER_RUNS;
+ if (!(raw->port.flags & ASYNC_SUSPENDED)) {
+ raw3215_mk_write_req(raw);
+ raw3215_start_io(raw);
+ if ((raw->queued_read || raw->queued_write) &&
+ !(raw->flags & RAW3215_WORKING) &&
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+ add_timer(&raw->timer);
+ raw->flags |= RAW3215_TIMER_RUNS;
}
}
spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
(raw->flags & RAW3215_FLUSHING)) {
/* execute write requests bigger than minimum size */
raw3215_start_io(raw);
- if (raw->flags & RAW3215_TIMER_RUNS) {
- del_timer(&raw->timer);
- raw->flags &= ~RAW3215_TIMER_RUNS;
- }
- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
- /* delay small writes */
- raw->timer.expires = RAW3215_TIMEOUT + jiffies;
- add_timer(&raw->timer);
- raw->flags |= RAW3215_TIMER_RUNS;
}
}
+ if ((raw->queued_read || raw->queued_write) &&
+ !(raw->flags & RAW3215_WORKING) &&
+ !(raw->flags & RAW3215_TIMER_RUNS)) {
+ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+ add_timer(&raw->timer);
+ raw->flags |= RAW3215_TIMER_RUNS;
+ }
}
/*
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index f5f4a91fab44..f76bff68d1de 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -17,6 +17,8 @@
#include "qdio.h"
#include "qdio_debug.h"
+#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
+
static struct kmem_cache *qdio_q_cache;
static struct kmem_cache *qdio_aob_cache;
@@ -32,6 +34,57 @@ void qdio_release_aob(struct qaob *aob)
}
EXPORT_SYMBOL_GPL(qdio_release_aob);
+/**
+ * qdio_free_buffers() - free qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers to free
+ */
+void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+ int pos;
+
+ for (pos = 0; pos < count; pos += QBUFF_PER_PAGE)
+ free_page((unsigned long) buf[pos]);
+}
+EXPORT_SYMBOL_GPL(qdio_free_buffers);
+
+/**
+ * qdio_alloc_buffers() - allocate qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers to allocate
+ */
+int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+ int pos;
+
+ for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) {
+ buf[pos] = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!buf[pos]) {
+ qdio_free_buffers(buf, count);
+ return -ENOMEM;
+ }
+ }
+ for (pos = 0; pos < count; pos++)
+ if (pos % QBUFF_PER_PAGE)
+ buf[pos] = buf[pos - 1] + 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qdio_alloc_buffers);
+
+/**
+ * qdio_reset_buffers() - reset qdio buffers
+ * @buf: array of pointers to qdio buffers
+ * @count: number of qdio buffers that will be zeroed
+ */
+void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count)
+{
+ int pos;
+
+ for (pos = 0; pos < count; pos++)
+ memset(buf[pos], 0, sizeof(struct qdio_buffer));
+}
+EXPORT_SYMBOL_GPL(qdio_reset_buffers);
+
/*
* qebsm is only available under 64bit but the adapter sets the feature
* flag anyway, so we manually override it.
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index d837c3c5330f..fbc6701bef30 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2915,7 +2915,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
"failed with error code %d\n", ret);
goto out;
}
- dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
+ dev = alloc_netdev(0, "claw%d", NET_NAME_UNKNOWN, claw_init_netdevice);
if (!dev) {
dev_warn(&cgdev->dev,
"Activating the CLAW device failed\n");
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 03b6ad035577..e056dd4fe44d 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1137,9 +1137,11 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv)
return NULL;
if (IS_MPC(priv))
- dev = alloc_netdev(0, MPC_DEVICE_GENE, ctcm_dev_setup);
+ dev = alloc_netdev(0, MPC_DEVICE_GENE, NET_NAME_UNKNOWN,
+ ctcm_dev_setup);
else
- dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
+ dev = alloc_netdev(0, CTC_DEVICE_GENE, NET_NAME_UNKNOWN,
+ ctcm_dev_setup);
if (!dev) {
CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index ce16d1bdb20a..0a87809c8af7 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -2015,7 +2015,7 @@ static struct net_device *netiucv_init_netdevice(char *username, char *userdata)
struct net_device *dev;
dev = alloc_netdev(sizeof(struct netiucv_priv), "iucv%d",
- netiucv_setup_netdevice);
+ NET_NAME_UNKNOWN, netiucv_setup_netdevice);
if (!dev)
return NULL;
rtnl_lock();
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index a2088af51cc5..97ef37b51068 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -439,10 +439,10 @@ struct qeth_qdio_buffer {
};
struct qeth_qdio_q {
- struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qeth_qdio_buffer bufs[QDIO_MAX_BUFFERS_PER_Q];
int next_buf_to_init;
-} __attribute__ ((aligned(256)));
+};
struct qeth_qdio_out_buffer {
struct qdio_buffer *buffer;
@@ -465,7 +465,7 @@ enum qeth_out_q_states {
};
struct qeth_qdio_out_q {
- struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
+ struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q];
struct qdio_outbuf_state *bufstates; /* convenience pointer */
int queue_no;
@@ -483,7 +483,7 @@ struct qeth_qdio_out_q {
atomic_t used_buffers;
/* indicates whether PCI flag must be set (or if one is outstanding) */
atomic_t set_pci_flags_count;
-} __attribute__ ((aligned(256)));
+};
struct qeth_qdio_info {
atomic_t state;
@@ -766,6 +766,11 @@ struct carrier_info {
__u32 port_speed;
};
+struct qeth_switch_info {
+ __u32 capabilities;
+ __u32 settings;
+};
+
#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
struct qeth_card {
@@ -946,6 +951,8 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
int qeth_mdio_read(struct net_device *, int, int);
int qeth_snmp_command(struct qeth_card *, char __user *);
int qeth_query_oat_command(struct qeth_card *, char __user *);
+int qeth_query_switch_attributes(struct qeth_card *card,
+ struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
struct carrier_info *carrier_info);
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index f54bec54d677..c0d6ba8655c7 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -292,14 +292,43 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
}
EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
+static void qeth_free_qdio_queue(struct qeth_qdio_q *q)
+{
+ if (!q)
+ return;
+
+ qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+ kfree(q);
+}
+
+static struct qeth_qdio_q *qeth_alloc_qdio_queue(void)
+{
+ struct qeth_qdio_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+ int i;
+
+ if (!q)
+ return NULL;
+
+ if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
+ kfree(q);
+ return NULL;
+ }
+
+ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i)
+ q->bufs[i].buffer = q->qdio_bufs[i];
+
+ QETH_DBF_HEX(SETUP, 2, &q, sizeof(void *));
+ return q;
+}
+
static inline int qeth_cq_init(struct qeth_card *card)
{
int rc;
if (card->options.cq == QETH_CQ_ENABLED) {
QETH_DBF_TEXT(SETUP, 2, "cqinit");
- memset(card->qdio.c_q->qdio_bufs, 0,
- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+ qdio_reset_buffers(card->qdio.c_q->qdio_bufs,
+ QDIO_MAX_BUFFERS_PER_Q);
card->qdio.c_q->next_buf_to_init = 127;
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT,
card->qdio.no_in_queues - 1, 0,
@@ -323,21 +352,12 @@ static inline int qeth_alloc_cq(struct qeth_card *card)
struct qdio_outbuf_state *outbuf_states;
QETH_DBF_TEXT(SETUP, 2, "cqon");
- card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q),
- GFP_KERNEL);
+ card->qdio.c_q = qeth_alloc_qdio_queue();
if (!card->qdio.c_q) {
rc = -1;
goto kmsg_out;
}
- QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *));
-
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
- card->qdio.c_q->bufs[i].buffer =
- &card->qdio.c_q->qdio_bufs[i];
- }
-
card->qdio.no_in_queues = 2;
-
card->qdio.out_bufstates =
kzalloc(card->qdio.no_out_queues *
QDIO_MAX_BUFFERS_PER_Q *
@@ -361,7 +381,7 @@ static inline int qeth_alloc_cq(struct qeth_card *card)
out:
return rc;
free_cq_out:
- kfree(card->qdio.c_q);
+ qeth_free_qdio_queue(card->qdio.c_q);
card->qdio.c_q = NULL;
kmsg_out:
dev_err(&card->gdev->dev, "Failed to create completion queue\n");
@@ -372,7 +392,7 @@ static inline void qeth_free_cq(struct qeth_card *card)
{
if (card->qdio.c_q) {
--card->qdio.no_in_queues;
- kfree(card->qdio.c_q);
+ qeth_free_qdio_queue(card->qdio.c_q);
card->qdio.c_q = NULL;
}
kfree(card->qdio.out_bufstates);
@@ -1282,35 +1302,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card)
}
}
-static void qeth_free_qdio_buffers(struct qeth_card *card)
-{
- int i, j;
-
- if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
- QETH_QDIO_UNINITIALIZED)
- return;
-
- qeth_free_cq(card);
- cancel_delayed_work_sync(&card->buffer_reclaim_work);
- for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
- if (card->qdio.in_q->bufs[j].rx_skb)
- dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
- }
- kfree(card->qdio.in_q);
- card->qdio.in_q = NULL;
- /* inbound buffer pool */
- qeth_free_buffer_pool(card);
- /* free outbound qdio_qs */
- if (card->qdio.out_qs) {
- for (i = 0; i < card->qdio.no_out_queues; ++i) {
- qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
- kfree(card->qdio.out_qs[i]);
- }
- kfree(card->qdio.out_qs);
- card->qdio.out_qs = NULL;
- }
-}
-
static void qeth_clean_channel(struct qeth_channel *channel)
{
int cnt;
@@ -2392,7 +2383,7 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
rc = -ENOMEM;
goto out;
}
- newbuf->buffer = &q->qdio_bufs[bidx];
+ newbuf->buffer = q->qdio_bufs[bidx];
skb_queue_head_init(&newbuf->skb_list);
lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key);
newbuf->q = q;
@@ -2411,6 +2402,28 @@ out:
return rc;
}
+static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+{
+ if (!q)
+ return;
+
+ qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+ kfree(q);
+}
+
+static struct qeth_qdio_out_q *qeth_alloc_qdio_out_buf(void)
+{
+ struct qeth_qdio_out_q *q = kzalloc(sizeof(*q), GFP_KERNEL);
+
+ if (!q)
+ return NULL;
+
+ if (qdio_alloc_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q)) {
+ kfree(q);
+ return NULL;
+ }
+ return q;
+}
static int qeth_alloc_qdio_buffers(struct qeth_card *card)
{
@@ -2422,19 +2435,11 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
return 0;
- card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q),
- GFP_KERNEL);
+ QETH_DBF_TEXT(SETUP, 2, "inq");
+ card->qdio.in_q = qeth_alloc_qdio_queue();
if (!card->qdio.in_q)
goto out_nomem;
- QETH_DBF_TEXT(SETUP, 2, "inq");
- QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *));
- memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q));
- /* give inbound qeth_qdio_buffers their qdio_buffers */
- for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
- card->qdio.in_q->bufs[i].buffer =
- &card->qdio.in_q->qdio_bufs[i];
- card->qdio.in_q->bufs[i].rx_skb = NULL;
- }
+
/* inbound buffer pool */
if (qeth_alloc_buffer_pool(card))
goto out_freeinq;
@@ -2446,8 +2451,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
if (!card->qdio.out_qs)
goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q),
- GFP_KERNEL);
+ card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf();
if (!card->qdio.out_qs[i])
goto out_freeoutq;
QETH_DBF_TEXT_(SETUP, 2, "outq %i", i);
@@ -2476,7 +2480,7 @@ out_freeoutqbufs:
}
out_freeoutq:
while (i > 0) {
- kfree(card->qdio.out_qs[--i]);
+ qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
}
kfree(card->qdio.out_qs);
@@ -2484,13 +2488,42 @@ out_freeoutq:
out_freepool:
qeth_free_buffer_pool(card);
out_freeinq:
- kfree(card->qdio.in_q);
+ qeth_free_qdio_queue(card->qdio.in_q);
card->qdio.in_q = NULL;
out_nomem:
atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
return -ENOMEM;
}
+static void qeth_free_qdio_buffers(struct qeth_card *card)
+{
+ int i, j;
+
+ if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+ QETH_QDIO_UNINITIALIZED)
+ return;
+
+ qeth_free_cq(card);
+ cancel_delayed_work_sync(&card->buffer_reclaim_work);
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+ if (card->qdio.in_q->bufs[j].rx_skb)
+ dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
+ }
+ qeth_free_qdio_queue(card->qdio.in_q);
+ card->qdio.in_q = NULL;
+ /* inbound buffer pool */
+ qeth_free_buffer_pool(card);
+ /* free outbound qdio_qs */
+ if (card->qdio.out_qs) {
+ for (i = 0; i < card->qdio.no_out_queues; ++i) {
+ qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
+ qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
+ }
+ kfree(card->qdio.out_qs);
+ card->qdio.out_qs = NULL;
+ }
+}
+
static void qeth_create_qib_param_field(struct qeth_card *card,
char *param_field)
{
@@ -2788,8 +2821,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
QETH_DBF_TEXT(SETUP, 2, "initqdqs");
/* inbound queue */
- memset(card->qdio.in_q->qdio_bufs, 0,
- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+ qdio_reset_buffers(card->qdio.in_q->qdio_bufs,
+ QDIO_MAX_BUFFERS_PER_Q);
qeth_initialize_working_pool_list(card);
/*give only as many buffers to hardware as we have buffer pool entries*/
for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
@@ -2811,8 +2844,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
/* outbound queue */
for (i = 0; i < card->qdio.no_out_queues; ++i) {
- memset(card->qdio.out_qs[i]->qdio_bufs, 0,
- QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
+ qdio_reset_buffers(card->qdio.out_qs[i]->qdio_bufs,
+ QDIO_MAX_BUFFERS_PER_Q);
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
qeth_clear_output_buffer(card->qdio.out_qs[i],
card->qdio.out_qs[i]->bufs[j],
@@ -3037,6 +3070,45 @@ int qeth_query_ipassists(struct qeth_card *card, enum qeth_prot_versions prot)
}
EXPORT_SYMBOL_GPL(qeth_query_ipassists);
+static int qeth_query_switch_attributes_cb(struct qeth_card *card,
+ struct qeth_reply *reply, unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd;
+ struct qeth_switch_info *sw_info;
+ struct qeth_query_switch_attributes *attrs;
+
+ QETH_CARD_TEXT(card, 2, "qswiatcb");
+ cmd = (struct qeth_ipa_cmd *) data;
+ sw_info = (struct qeth_switch_info *)reply->param;
+ if (cmd->data.setadapterparms.hdr.return_code == 0) {
+ attrs = &cmd->data.setadapterparms.data.query_switch_attributes;
+ sw_info->capabilities = attrs->capabilities;
+ sw_info->settings = attrs->settings;
+ QETH_CARD_TEXT_(card, 2, "%04x%04x", sw_info->capabilities,
+ sw_info->settings);
+ }
+ qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
+
+ return 0;
+}
+
+int qeth_query_switch_attributes(struct qeth_card *card,
+ struct qeth_switch_info *sw_info)
+{
+ struct qeth_cmd_buffer *iob;
+
+ QETH_CARD_TEXT(card, 2, "qswiattr");
+ if (!qeth_adp_supported(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES))
+ return -EOPNOTSUPP;
+ if (!netif_carrier_ok(card->dev))
+ return -ENOMEDIUM;
+ iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_SWITCH_ATTRIBUTES,
+ sizeof(struct qeth_ipacmd_setadpparms_hdr));
+ return qeth_send_ipa_cmd(card, iob,
+ qeth_query_switch_attributes_cb, sw_info);
+}
+EXPORT_SYMBOL_GPL(qeth_query_switch_attributes);
+
static int qeth_query_setdiagass_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
@@ -3530,7 +3602,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card,
for (i = first_element; i < first_element + count; ++i) {
int bidx = i % QDIO_MAX_BUFFERS_PER_Q;
- struct qdio_buffer *buffer = &cq->qdio_bufs[bidx];
+ struct qdio_buffer *buffer = cq->qdio_bufs[bidx];
int e;
e = 0;
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index cf6a90ed42ae..1558be1af72d 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -242,6 +242,7 @@ enum qeth_ipa_setadp_cmd {
IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L,
IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L,
IPA_SETADP_QUERY_OAT = 0x00080000L,
+ IPA_SETADP_QUERY_SWITCH_ATTRIBUTES = 0x00100000L,
};
enum qeth_ipa_mac_ops {
CHANGE_ADDR_READ_MAC = 0,
@@ -431,6 +432,21 @@ struct qeth_query_card_info {
__u32 reserved2;
};
+#define QETH_SWITCH_FORW_802_1 0x00000001
+#define QETH_SWITCH_FORW_REFL_RELAY 0x00000002
+#define QETH_SWITCH_CAP_RTE 0x00000004
+#define QETH_SWITCH_CAP_ECP 0x00000008
+#define QETH_SWITCH_CAP_VDP 0x00000010
+
+struct qeth_query_switch_attributes {
+ __u8 version;
+ __u8 reserved1;
+ __u16 reserved2;
+ __u32 capabilities;
+ __u32 settings;
+ __u8 reserved3[8];
+};
+
struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds;
__u32 reserved1;
@@ -452,6 +468,7 @@ struct qeth_ipacmd_setadpparms {
struct qeth_set_access_ctrl set_access_ctrl;
struct qeth_query_oat query_oat;
struct qeth_query_card_info card_info;
+ struct qeth_query_switch_attributes query_switch_attributes;
__u32 mode;
} data;
} __attribute__ ((packed));
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 8a25a2be9890..15523f0e4c03 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -543,7 +543,42 @@ out:
}
static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
- qeth_dev_isolation_store);
+ qeth_dev_isolation_store);
+
+static ssize_t qeth_dev_switch_attrs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct qeth_card *card = dev_get_drvdata(dev);
+ struct qeth_switch_info sw_info;
+ int rc = 0;
+
+ if (!card)
+ return -EINVAL;
+
+ if (card->state != CARD_STATE_SOFTSETUP && card->state != CARD_STATE_UP)
+ return sprintf(buf, "n/a\n");
+
+ rc = qeth_query_switch_attributes(card, &sw_info);
+ if (rc)
+ return rc;
+
+ if (!sw_info.capabilities)
+ rc = sprintf(buf, "unknown");
+
+ if (sw_info.capabilities & QETH_SWITCH_FORW_802_1)
+ rc = sprintf(buf, (sw_info.settings & QETH_SWITCH_FORW_802_1 ?
+ "[802.1]" : "802.1"));
+ if (sw_info.capabilities & QETH_SWITCH_FORW_REFL_RELAY)
+ rc += sprintf(buf + rc,
+ (sw_info.settings & QETH_SWITCH_FORW_REFL_RELAY ?
+ " [rr]" : " rr"));
+ rc += sprintf(buf + rc, "\n");
+
+ return rc;
+}
+
+static DEVICE_ATTR(switch_attrs, 0444,
+ qeth_dev_switch_attrs_show, NULL);
static ssize_t qeth_hw_trap_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -728,6 +763,7 @@ static struct attribute *qeth_device_attrs[] = {
&dev_attr_layer2.attr,
&dev_attr_isolation.attr,
&dev_attr_hw_trap.attr,
+ &dev_attr_switch_attrs.attr,
NULL,
};
static struct attribute_group qeth_device_attr_group = {
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 5ef5b4f45758..c2679bfe7f66 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -952,10 +952,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
{
switch (card->info.type) {
case QETH_CARD_TYPE_IQD:
- card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+ card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
+ ether_setup);
break;
case QETH_CARD_TYPE_OSN:
- card->dev = alloc_netdev(0, "osn%d", ether_setup);
+ card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
+ ether_setup);
card->dev->flags |= IFF_NOARP;
break;
default:
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 14e0b5810e8c..f8427a2c4840 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3287,7 +3287,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
}
}
} else if (card->info.type == QETH_CARD_TYPE_IQD) {
- card->dev = alloc_netdev(0, "hsi%d", ether_setup);
+ card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
+ ether_setup);
if (!card->dev)
return -ENODEV;
card->dev->flags |= IFF_NOARP;
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 0ca64484cfa3..5d7fbe4e907e 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -418,7 +418,8 @@ void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf)
rec->scsi_retries = sc->retries;
rec->scsi_allowed = sc->allowed;
rec->scsi_id = sc->device->id;
- rec->scsi_lun = sc->device->lun;
+ /* struct zfcp_dbf_scsi needs to be updated to handle 64bit LUNs */
+ rec->scsi_lun = (u32)sc->device->lun;
rec->host_scribble = (unsigned long)sc->host_scribble;
memcpy(rec->scsi_opcode, sc->cmnd,
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 06025cdaa4ad..495e1cb3afa6 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -14,27 +14,10 @@
#include "zfcp_ext.h"
#include "zfcp_qdio.h"
-#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
-
static bool enable_multibuffer = 1;
module_param_named(datarouter, enable_multibuffer, bool, 0400);
MODULE_PARM_DESC(datarouter, "Enable hardware data router support (default on)");
-static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
-{
- int pos;
-
- for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
- sbal[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
- if (!sbal[pos])
- return -ENOMEM;
- }
- for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
- if (pos % QBUFF_PER_PAGE)
- sbal[pos] = sbal[pos - 1] + 1;
- return 0;
-}
-
static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id,
unsigned int qdio_err)
{
@@ -326,15 +309,30 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
static int zfcp_qdio_allocate(struct zfcp_qdio *qdio)
{
struct qdio_initialize init_data;
+ int ret;
- if (zfcp_qdio_buffers_enqueue(qdio->req_q) ||
- zfcp_qdio_buffers_enqueue(qdio->res_q))
+ ret = qdio_alloc_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+ if (ret)
return -ENOMEM;
+ ret = qdio_alloc_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
+ if (ret)
+ goto free_req_q;
+
zfcp_qdio_setup_init_data(&init_data, qdio);
init_waitqueue_head(&qdio->req_q_wq);
- return qdio_allocate(&init_data);
+ ret = qdio_allocate(&init_data);
+ if (ret)
+ goto free_res_q;
+
+ return 0;
+
+free_res_q:
+ qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
+free_req_q:
+ qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+ return ret;
}
/**
@@ -448,19 +446,14 @@ failed_establish:
void zfcp_qdio_destroy(struct zfcp_qdio *qdio)
{
- int p;
-
if (!qdio)
return;
if (qdio->adapter->ccw_device)
qdio_free(qdio->adapter->ccw_device);
- for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
- free_page((unsigned long) qdio->req_q[p]);
- free_page((unsigned long) qdio->res_q[p]);
- }
-
+ qdio_free_buffers(qdio->req_q, QDIO_MAX_BUFFERS_PER_Q);
+ qdio_free_buffers(qdio->res_q, QDIO_MAX_BUFFERS_PER_Q);
kfree(qdio);
}
@@ -475,7 +468,7 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter)
qdio->adapter = adapter;
if (zfcp_qdio_allocate(qdio)) {
- zfcp_qdio_destroy(qdio);
+ kfree(qdio);
return -ENOMEM;
}
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
index 39f5446f7216..157d3d203ba1 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -21,7 +21,7 @@
void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
{
struct fc_rport *rport = unit->port->rport;
- unsigned int lun;
+ u64 lun;
lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
@@ -188,7 +188,7 @@ struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
{
struct Scsi_Host *shost;
struct zfcp_port *port;
- unsigned int lun;
+ u64 lun;
lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
port = unit->port;
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 160e7510aca6..0787b9756165 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!tp)
return;
+ INIT_LIST_HEAD(&tp->bp_list);
+ INIT_LIST_HEAD(&tp->glob_list);
+
tp->client = bbc_i2c_attach(bp, op);
if (!tp->client) {
kfree(tp);
@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op,
if (!fp)
return;
+ INIT_LIST_HEAD(&fp->bp_list);
+ INIT_LIST_HEAD(&fp->glob_list);
+
fp->client = bbc_i2c_attach(bp, op);
if (!fp->client) {
kfree(fp);
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index c7763e482eb2..812b5f0361b6 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -300,13 +300,18 @@ static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index
if (!bp)
return NULL;
+ INIT_LIST_HEAD(&bp->temps);
+ INIT_LIST_HEAD(&bp->fans);
+
bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs");
if (!bp->i2c_control_regs)
goto fail;
- bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
- if (!bp->i2c_bussel_reg)
- goto fail;
+ if (op->num_resources == 2) {
+ bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel");
+ if (!bp->i2c_bussel_reg)
+ goto fail;
+ }
bp->waiting = 0;
init_waitqueue_head(&bp->wq);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 7c71e7b4febf..2b0ce7c350ee 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -4,6 +4,7 @@
* Copyright (c) 2000 Eric Brower (ebrower@usa.net)
*/
+#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -143,10 +144,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case D7SIOCTM:
/* toggle device mode-- flip display orientation */
- if (regs & D7S_FLIP)
- regs &= ~D7S_FLIP;
- else
- regs |= D7S_FLIP;
+ regs ^= D7S_FLIP;
writeb(regs, p->regs);
break;
}
@@ -180,7 +178,7 @@ static int d7s_probe(struct platform_device *op)
if (d7s_device)
goto out;
- p = kzalloc(sizeof(*p), GFP_KERNEL);
+ p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
err = -ENOMEM;
if (!p)
goto out;
@@ -231,7 +229,6 @@ out_iounmap:
of_iounmap(&op->resource[0], p->regs, sizeof(u8));
out_free:
- kfree(p);
goto out;
}
@@ -251,7 +248,6 @@ static int d7s_remove(struct platform_device *op)
misc_deregister(&d7s_miscdev);
of_iounmap(&op->resource[0], p->regs, sizeof(u8));
- kfree(p);
return 0;
}
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 4de346017e9f..6da6cec9a651 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -683,14 +683,13 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
unsigned long *cpu_addr;
int retval = 1;
- cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
+ cpu_addr = pci_zalloc_consistent(tw_dev->tw_pci_dev, size * TW_Q_LENGTH,
+ &dma_handle);
if (!cpu_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
goto out;
}
- memset(cpu_addr, 0, size*TW_Q_LENGTH);
-
for (i = 0; i < TW_Q_LENGTH; i++) {
switch(which) {
case 0:
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 49dcf03c631a..29b0b84ed69e 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -392,6 +392,8 @@ typedef struct TAG_TW_Passthru
unsigned char padding[12];
} TW_Passthru;
+#pragma pack()
+
typedef struct TAG_TW_Device_Extension {
u32 base_addr;
unsigned long *alignment_virtual_address[TW_Q_LENGTH];
@@ -430,6 +432,4 @@ typedef struct TAG_TW_Device_Extension {
wait_queue_head_t ioctl_wqueue;
} TW_Device_Extension;
-#pragma pack()
-
#endif /* _3W_XXXX_H */
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index a3adfb4357f5..fabd4be2c985 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1005,7 +1005,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
DMA_TO_DEVICE);
cmnd[0] = REQUEST_SENSE;
- cmnd[1] = (SCp->device->lun & 0x7) << 5;
+ cmnd[1] = (lun & 0x7) << 5;
cmnd[2] = 0;
cmnd[3] = 0;
cmnd[4] = SCSI_SENSE_BUFFERSIZE;
@@ -1396,7 +1396,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
__u16 count = 1; /* for IDENTIFY message */
-
+ u8 lun = SCp->device->lun;
+
if(hostdata->state != NCR_700_HOST_FREE) {
/* keep this inside the lock to close the race window where
* the running command finishes on another CPU while we don't
@@ -1415,7 +1416,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE &&
slot->flags != NCR_700_FLAG_AUTOSENSE),
- SCp->device->lun);
+ lun);
/* for INQUIRY or REQUEST_SENSE commands, we cannot be sure
* if the negotiated transfer parameters still hold, so
* always renegotiate them */
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 972f8176665f..64c75143c89a 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -3893,7 +3893,7 @@ __setup("BusLogic=", blogic_setup);
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ }
};*/
-static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = {
+static const struct pci_device_id blogic_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index baca5897039f..18a3358eb1d4 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -40,13 +40,6 @@ config SCSI_DMA
bool
default n
-config SCSI_TGT
- tristate "SCSI target support"
- depends on SCSI
- ---help---
- If you want to use SCSI target mode drivers enable this option.
- If you choose M, the module will be called scsi_tgt.
-
config SCSI_NETLINK
bool
default n
@@ -197,20 +190,6 @@ config SCSI_ENCLOSURE
it has an enclosure device. Selecting this option will just allow
certain enclosure conditions to be reported and is not required.
-config SCSI_MULTI_LUN
- bool "Probe all LUNs on each SCSI device"
- depends on SCSI
- help
- Some devices support more than one LUN (Logical Unit Number) in order
- to allow access to several media, e.g. CD jukebox, USB card reader,
- mobile phone in mass storage mode. This option forces the kernel to
- probe for all LUNs by default. This setting can be overridden by
- max_luns boot/module parameter. Note that this option does not affect
- devices conforming to SCSI-3 or higher as they can explicitly report
- their number of LUNs. It is safe to say Y here unless you have one of
- those rare devices which reacts in an unexpected way when probed for
- multiple LUNs.
-
config SCSI_CONSTANTS
bool "Verbose SCSI error reporting (kernel size +=12K)"
depends on SCSI
@@ -285,13 +264,6 @@ config SCSI_FC_ATTRS
each attached FiberChannel device to sysfs, say Y.
Otherwise, say N.
-config SCSI_FC_TGT_ATTRS
- bool "SCSI target support for FiberChannel Transport Attributes"
- depends on SCSI_FC_ATTRS
- depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS
- help
- If you want to use SCSI target mode drivers enable this option.
-
config SCSI_ISCSI_ATTRS
tristate "iSCSI Transport Attributes"
depends on SCSI && NET
@@ -318,13 +290,6 @@ config SCSI_SRP_ATTRS
If you wish to export transport-specific information about
each attached SRP device to sysfs, say Y.
-config SCSI_SRP_TGT_ATTRS
- bool "SCSI target support for SRP Transport Attributes"
- depends on SCSI_SRP_ATTRS
- depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS
- help
- If you want to use SCSI target mode drivers enable this option.
-
endmenu
menuconfig SCSI_LOWLEVEL
@@ -528,7 +493,7 @@ config SCSI_DPT_I2O
config SCSI_ADVANSYS
tristate "AdvanSys SCSI support"
- depends on SCSI && VIRT_TO_BUS
+ depends on SCSI && VIRT_TO_BUS && !ARM
depends on ISA || EISA || PCI
help
This is a driver for all SCSI host adapters manufactured by
@@ -848,20 +813,6 @@ config SCSI_IBMVSCSI
To compile this driver as a module, choose M here: the
module will be called ibmvscsi.
-config SCSI_IBMVSCSIS
- tristate "IBM Virtual SCSI Server support"
- depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS
- help
- This is the SRP target driver for IBM pSeries virtual environments.
-
- The userspace component needed to initialize the driver and
- documentation can be found:
-
- http://stgt.berlios.de/
-
- To compile this driver as a module, choose M here: the
- module will be called ibmvstgt.
-
config SCSI_IBMVFC
tristate "IBM Virtual FC support"
depends on PPC_PSERIES && SCSI
@@ -1750,16 +1701,6 @@ config SCSI_PM8001
This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip
based host adapters.
-config SCSI_SRP
- tristate "SCSI RDMA Protocol helper library"
- depends on SCSI && PCI
- select SCSI_TGT
- help
- If you wish to use SRP target drivers, say Y.
-
- To compile this driver as a module, choose M here: the
- module will be called libsrp.
-
config SCSI_BFA_FC
tristate "Brocade BFA Fibre Channel Support"
depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index e172d4f8e02f..5f0d299b0093 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -20,7 +20,6 @@ CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS
obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_SCSI) += scsi_mod.o
-obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o
obj-$(CONFIG_RAID_ATTRS) += raid_class.o
@@ -127,9 +126,7 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
obj-$(CONFIG_SCSI_IPR) += ipr.o
-obj-$(CONFIG_SCSI_SRP) += libsrp.o
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/
-obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/
obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/
obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
@@ -173,8 +170,6 @@ scsi_mod-$(CONFIG_PM) += scsi_pm.o
hv_storvsc-y := storvsc_drv.o
-scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o
-
sd_mod-objs := sd.o
sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 93d13fc9a293..45da3c823322 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -762,7 +762,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
{
- SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
+ SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
SPRINTF(" command = ");
lprint_command(cmd->cmnd, m);
}
@@ -1039,9 +1039,10 @@ static void NCR5380_main(struct work_struct *work)
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
{
if (prev != tmp)
- dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
+ dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
/* When we find one, remove it from the issue queue. */
- if (!(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))) {
+ if (!(hostdata->busy[tmp->device->id] &
+ (1 << (u8)(tmp->device->lun & 0xff)))) {
if (prev) {
REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
prev->host_scribble = tmp->host_scribble;
@@ -1057,7 +1058,7 @@ static void NCR5380_main(struct work_struct *work)
* On failure, we must add the command back to the
* issue queue so we can keep trying.
*/
- dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun);
+ dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun);
/*
* A successful selection is defined as one that
@@ -1524,7 +1525,7 @@ part2:
dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no);
/* XXX need to handle errors here */
hostdata->connected = cmd;
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
initialize_SCp(cmd);
@@ -2210,14 +2211,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case LINKED_FLG_CMD_COMPLETE:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun);
+ dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun);
/*
* Sanity check : A linked command should only terminate with
* one of these messages if there are more linked commands
* available.
*/
if (!cmd->next_link) {
- printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun);
+ printk("scsi%d : target %d lun %llu linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun);
sink = 1;
do_abort(instance);
return;
@@ -2226,7 +2227,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
/* The next command is still part of this process */
cmd->next_link->tag = cmd->tag;
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
+ dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
cmd = hostdata->connected;
@@ -2238,8 +2239,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
sink = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
hostdata->connected = NULL;
- dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->device->id, cmd->device->lun);
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %llu completed\n", instance->host_no, cmd->device->id, cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
/*
* I'm not sure what the correct thing to do here is :
@@ -2304,7 +2305,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case ORDERED_QUEUE_TAG:
case SIMPLE_QUEUE_TAG:
cmd->device->simple_tags = 0;
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
break;
default:
break;
@@ -2318,7 +2319,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->disconnected_queue;
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
- dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun);
+ dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %llu was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun);
/*
* Restore phase bits to 0 so an interrupted selection,
* arbitration can resume.
@@ -2426,7 +2427,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->last_message = msgout;
NCR5380_transfer_pio(instance, &phase, &len, &data);
if (msgout == ABORT) {
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
hostdata->connected = NULL;
cmd->result = DID_ERROR << 16;
collect_stats(hostdata, cmd);
@@ -2562,7 +2563,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
- if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+ if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)
) {
if (prev) {
REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
@@ -2588,7 +2589,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
do_abort(instance);
} else {
hostdata->connected = tmp;
- dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag);
+ dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag);
}
}
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index c91888a0a23c..42c7161474f7 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -595,7 +595,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost)
{
if (shost->irq)
free_irq(shost->irq, NULL);
-#ifdef USE_DMA
+#if USE_DMA
if (shost->dma_channel != 0xff)
free_dma(shost->dma_channel);
#endif
@@ -698,7 +698,7 @@ static int NCR53c406a_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
int i;
VDEB(printk("NCR53c406a_queue called\n"));
- DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt)));
+ DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->target, (u8)SCpnt->device->lun, scsi_bufflen(SCpnt)));
#if 0
VDEB(for (i = 0; i < SCpnt->cmd_len; i++)
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 0163457c12bb..7e33a61c1ba4 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -891,7 +891,7 @@ static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struc
printk("max cdb length= %x\b", cmd->cmd_len);
scb->cdb_len = IMAX_CDB;
}
- scb->ident = cmd->device->lun | DISC_ALLOW;
+ scb->ident = (u8)(cmd->device->lun & 0xff) | DISC_ALLOW;
if (cmd->device->tagged_supported) { /* Tag Support */
scb->tag_msg = SIMPLE_QUEUE_TAG; /* Do simple tag only */
} else {
@@ -1125,23 +1125,19 @@ static int inia100_probe_one(struct pci_dev *pdev,
/* Get total memory needed for SCB */
sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
- host->scb_virt = pci_alloc_consistent(pdev, sz,
- &host->scb_phys);
+ host->scb_virt = pci_zalloc_consistent(pdev, sz, &host->scb_phys);
if (!host->scb_virt) {
printk("inia100: SCB memory allocation error\n");
goto out_host_put;
}
- memset(host->scb_virt, 0, sz);
/* Get total memory needed for ESCB */
sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
- host->escb_virt = pci_alloc_consistent(pdev, sz,
- &host->escb_phys);
+ host->escb_virt = pci_zalloc_consistent(pdev, sz, &host->escb_phys);
if (!host->escb_virt) {
printk("inia100: ESCB memory allocation error\n");
goto out_free_scb_array;
}
- memset(host->escb_virt, 0, sz);
biosaddr = host->BIOScfg;
biosaddr = (biosaddr << 4);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 4921ed19a027..63f576c9300a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -551,7 +551,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
int count;
int ret = FAILED;
- printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
+ printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n",
AAC_DRIVERNAME,
host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
switch (cmd->cmnd[0]) {
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index d8145888e66a..43761c1c46f0 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2512,7 +2512,7 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)
printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
printk(" host_busy %u, host_no %d,\n",
- s->host_busy, s->host_no);
+ atomic_read(&s->host_busy), s->host_no);
printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
(ulong)s->base, (ulong)s->io_port, boardp->irq);
@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost)
shost->host_no);
seq_printf(m,
- " host_busy %u, max_id %u, max_lun %u, max_channel %u\n",
- shost->host_busy, shost->max_id,
+ " host_busy %u, max_id %u, max_lun %llu, max_channel %u\n",
+ atomic_read(&shost->host_busy), shost->max_id,
shost->max_lun, shost->max_channel);
seq_printf(m,
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index e86eb6a921fc..e77b72f78006 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -321,7 +321,7 @@ static LIST_HEAD(aha152x_host_list);
#define CMDINFO(cmd) \
(cmd) ? ((cmd)->device->host->host_no) : -1, \
(cmd) ? ((cmd)->device->id & 0x0f) : -1, \
- (cmd) ? ((cmd)->device->lun & 0x07) : -1
+ (cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1
static inline void
CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
@@ -1602,7 +1602,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
#if defined(AHA152X_DEBUG)
int hostno=DONE_SC->device->host->host_no;
int id=DONE_SC->device->id & 0xf;
- int lun=DONE_SC->device->lun & 0x7;
+ int lun=((u8)DONE_SC->device->lun) & 0x7;
#endif
Scsi_Cmnd *ptr = DONE_SC;
DONE_SC=NULL;
@@ -2984,7 +2984,7 @@ static void get_command(struct seq_file *m, Scsi_Cmnd * ptr)
int i;
SPRINTF("%p: target=%d; lun=%d; cmnd=( ",
- ptr, ptr->device->id, ptr->device->lun);
+ ptr, ptr->device->id, (u8)ptr->device->lun);
for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
SPRINTF("0x%02x ", ptr->cmnd[i]);
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index 0cb8ef64b5ce..3d401d02c019 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -85,10 +85,9 @@ aic7770_probe(struct device *dev)
int error;
sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
- name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+ name = kstrdup(buf, GFP_ATOMIC);
if (name == NULL)
return (ENOMEM);
- strcpy(name, buf);
ahc = ahc_alloc(&aic7xxx_driver_template, name);
if (ahc == NULL)
return (ENOMEM);
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 113874c1284b..df2e0e5367d2 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -115,7 +115,7 @@ struct scb_platform_data;
#endif
#define AHD_BUILD_COL_IDX(target, lun) \
- (((lun) << 4) | target)
+ ((((u8)lun) << 4) | target)
#define AHD_GET_SCB_COL_IDX(ahd, scb) \
((SCB_GET_LUN(scb) << 4) | SCB_GET_TARGET(ahd, scb))
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 69d5c43a65e5..ed333669a7dc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -2137,7 +2137,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
if (do_fallback) {
printk("%s: device overrun (status %x) on %d:%d:%d\n",
ahd_name(ahd), status, cmd->device->channel,
- cmd->device->id, cmd->device->lun);
+ cmd->device->id, (u8)cmd->device->lun);
}
ahd_cmd_set_transaction_status(cmd, new_status);
@@ -2253,13 +2253,13 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd)
disconnected = TRUE;
if (ahd_search_qinfifo(ahd, cmd->device->id,
cmd->device->channel + 'A',
- cmd->device->lun,
+ cmd->device->lun,
pending_scb->hscb->tag,
ROLE_INITIATOR, CAM_REQ_ABORTED,
SEARCH_COMPLETE) > 0) {
printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
ahd_name(ahd), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
+ cmd->device->id, (u8)cmd->device->lun);
retval = SUCCESS;
goto done;
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 3c85873b14b9..8466aa784ec1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -178,10 +178,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahd_get_pci_bus(pci),
ahd_get_pci_slot(pci),
ahd_get_pci_function(pci));
- name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+ name = kstrdup(buf, GFP_ATOMIC);
if (name == NULL)
return (-ENOMEM);
- strcpy(name, buf);
ahd = ahd_alloc(NULL, name);
if (ahd == NULL)
return (-ENOMEM);
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index e9778b4f7e32..27dbfccea774 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -197,7 +197,7 @@ ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
sdev->sdev_target->channel + 'A',
- sdev->sdev_target->id, sdev->lun);
+ sdev->sdev_target->id, (u8)sdev->lun);
seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
seq_printf(m, "\t\tCommands Active %d\n", dev->active);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 114ff0c6e311..d2c9bf39033d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -2110,7 +2110,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
*/
printk("%s:%d:%d:%d: Is not an active device\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
+ (u8)cmd->device->lun);
retval = SUCCESS;
goto no_cmd;
}
@@ -2118,11 +2118,11 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
cmd->device->channel + 'A',
- cmd->device->lun,
+ (u8)cmd->device->lun,
CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) {
printk("%s:%d:%d:%d: Command found on untagged queue\n",
ahc_name(ahc), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
+ (u8)cmd->device->lun);
retval = SUCCESS;
goto done;
}
@@ -2188,13 +2188,14 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
SEARCH_COMPLETE) > 0) {
printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
ahc_name(ahc), cmd->device->channel,
- cmd->device->id, cmd->device->lun);
+ cmd->device->id, (u8)cmd->device->lun);
retval = SUCCESS;
goto done;
}
} else if (ahc_search_qinfifo(ahc, cmd->device->id,
cmd->device->channel + 'A',
- cmd->device->lun, pending_scb->hscb->tag,
+ cmd->device->lun,
+ pending_scb->hscb->tag,
ROLE_INITIATOR, /*status*/0,
SEARCH_COUNT) > 0) {
disconnected = FALSE;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index ee05e8410754..0fc14dac7070 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -225,10 +225,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc_get_pci_bus(pci),
ahc_get_pci_slot(pci),
ahc_get_pci_function(pci));
- name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
+ name = kstrdup(buf, GFP_ATOMIC);
if (name == NULL)
return (-ENOMEM);
- strcpy(name, buf);
ahc = ahc_alloc(NULL, name);
if (ahc == NULL)
return (-ENOMEM);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 383a3d11652d..64eec6c07a83 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -175,7 +175,7 @@ ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev)
seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n",
sdev->sdev_target->channel + 'A',
- sdev->sdev_target->id, sdev->lun);
+ sdev->sdev_target->id, (u8)sdev->lun);
seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued);
seq_printf(m, "\t\tCommands Active %d\n", dev->active);
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 652b41b4ddbd..b13764ca23fd 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2335,7 +2335,7 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
" poll command abort successfully \n"
, acb->host->host_no
, ccb->pcmd->device->id
- , ccb->pcmd->device->lun
+ , (u32)ccb->pcmd->device->lun
, ccb);
ccb->pcmd->result = DID_ABORT << 16;
arcmsr_ccb_complete(ccb);
@@ -2399,7 +2399,7 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb,
" poll command abort successfully \n"
,acb->host->host_no
,ccb->pcmd->device->id
- ,ccb->pcmd->device->lun
+ ,(u32)ccb->pcmd->device->lun
,ccb);
ccb->pcmd->result = DID_ABORT << 16;
arcmsr_ccb_complete(ccb);
@@ -2456,7 +2456,7 @@ polling_hbc_ccb_retry:
" poll command abort successfully \n"
, acb->host->host_no
, pCCB->pcmd->device->id
- , pCCB->pcmd->device->lun
+ , (u32)pCCB->pcmd->device->lun
, pCCB);
pCCB->pcmd->result = DID_ABORT << 16;
arcmsr_ccb_complete(pCCB);
@@ -3058,7 +3058,7 @@ static int arcmsr_abort(struct scsi_cmnd *cmd)
int rtn = FAILED;
printk(KERN_NOTICE
"arcmsr%d: abort device command of scsi id = %d lun = %d \n",
- acb->host->host_no, cmd->device->id, cmd->device->lun);
+ acb->host->host_no, cmd->device->id, (u32)cmd->device->lun);
acb->acb_flags |= ACB_F_ABORT;
acb->num_aborts++;
/*
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 2e797a367608..d89b9b4deb3c 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -760,7 +760,8 @@ intr_ret_t acornscsi_kick(AS_Host *host)
SCpnt->tag = SCpnt->device->current_tag;
} else
#endif
- set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+ set_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x07), host->busyluns);
host->stats.removes += 1;
@@ -863,7 +864,8 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
if (!SCpnt->scsi_done)
panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
- clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+ clear_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x7), host->busyluns);
SCpnt->scsi_done(SCpnt);
} else
@@ -1576,7 +1578,8 @@ void acornscsi_message(AS_Host *host)
printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
host->host->host_no, acornscsi_target(host));
host->SCpnt->device->simple_tags = 0;
- set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
+ set_bit(host->SCpnt->device->id * 8 +
+ (u8)(host->SCpnt->device->lun & 0x7), host->busyluns);
break;
#endif
case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
@@ -2671,7 +2674,8 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt)
//#if (DEBUG & DEBUG_ABORT)
printk("clear ");
//#endif
- clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
+ clear_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x7), host->busyluns);
/*
* We found the command, and cleared it out. Either
@@ -2853,7 +2857,7 @@ static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance)
shost_for_each_device(scd, instance) {
seq_printf(m, "Device/Lun TaggedQ Sync\n");
- seq_printf(m, " %d/%d ", scd->id, scd->lun);
+ seq_printf(m, " %d/%llu ", scd->id, scd->lun);
if (scd->tagged_supported)
seq_printf(m, "%3sabled(%3d) ",
scd->simple_tags ? "en" : "dis",
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index b46a6f6c0eb3..71cfb1e504c4 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -1821,7 +1821,8 @@ static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt)
SCpnt->tag = SCpnt->device->current_tag;
} else
#endif
- set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+ set_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x7), info->busyluns);
info->stats.removes += 1;
switch (SCpnt->cmnd[0]) {
@@ -2171,7 +2172,8 @@ static void fas216_done(FAS216_Info *info, unsigned int result)
* status.
*/
info->device[SCpnt->device->id].parity_check = 0;
- clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+ clear_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x7), info->busyluns);
fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble;
fn(info, SCpnt, result);
@@ -2398,7 +2400,8 @@ static enum res_find fas216_find_command(FAS216_Info *info,
* been set.
*/
info->origSCpnt = NULL;
- clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
+ clear_bit(SCpnt->device->id * 8 +
+ (u8)(SCpnt->device->lun & 0x7), info->busyluns);
printk("waiting for execution ");
res = res_success;
} else
@@ -3000,7 +3003,7 @@ void fas216_print_devices(FAS216_Info *info, struct seq_file *m)
shost_for_each_device(scd, info->host) {
dev = &info->device[scd->id];
- seq_printf(m, " %d/%d ", scd->id, scd->lun);
+ seq_printf(m, " %d/%llu ", scd->id, scd->lun);
if (scd->tagged_supported)
seq_printf(m, "%3sabled(%3d) ",
scd->simple_tags ? "en" : "dis",
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
index cb11ccef54e5..3441ce3ebabf 100644
--- a/drivers/scsi/arm/queue.c
+++ b/drivers/scsi/arm/queue.c
@@ -167,7 +167,8 @@ struct scsi_cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
spin_lock_irqsave(&queue->queue_lock, flags);
list_for_each(l, &queue->head) {
QE_t *q = list_entry(l, QE_t, list);
- if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) {
+ if (!test_bit(q->SCpnt->device->id * 8 +
+ (u8)(q->SCpnt->device->lun & 0x7), exclude)) {
SCpnt = __queue_remove(queue, l);
break;
}
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 1814aa20b724..79e6f045c2a9 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -361,17 +361,18 @@ static void __init init_tags(void)
static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
{
+ u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
- if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+ if (hostdata->busy[cmd->device->id] & (1 << lun))
return 1;
if (!should_be_tagged ||
!setup_use_tagged_queuing || !cmd->device->tagged_supported)
return 0;
- if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
- TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
+ if (TagAlloc[cmd->device->id][lun].nr_allocated >=
+ TagAlloc[cmd->device->id][lun].queue_size) {
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun);
+ H_NO(cmd), cmd->device->id, lun);
return 1;
}
return 0;
@@ -385,6 +386,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
{
+ u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
/* If we or the target don't support tagged queuing, allocate the LUN for
@@ -393,11 +395,11 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
if (!should_be_tagged ||
!setup_use_tagged_queuing || !cmd->device->tagged_supported) {
cmd->tag = TAG_NONE;
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] |= (1 << lun);
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged "
- "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
+ "command\n", H_NO(cmd), cmd->device->id, lun);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
set_bit(cmd->tag, ta->allocated);
@@ -405,7 +407,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d "
"(now %d tags in use)\n",
H_NO(cmd), cmd->tag, cmd->device->id,
- cmd->device->lun, ta->nr_allocated);
+ lun, ta->nr_allocated);
}
}
@@ -416,21 +418,22 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
static void cmd_free_tag(Scsi_Cmnd *cmd)
{
+ u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
if (cmd->tag == TAG_NONE) {
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << lun);
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun);
+ H_NO(cmd), cmd->device->id, lun);
} else if (cmd->tag >= MAX_TAGS) {
printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
H_NO(cmd), cmd->tag);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
clear_bit(cmd->tag, ta->allocated);
ta->nr_allocated--;
dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n",
- H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
+ H_NO(cmd), cmd->tag, cmd->device->id, lun);
}
}
@@ -713,7 +716,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
{
int i, s;
unsigned char *command;
- printk("scsi%d: destination target %d, lun %d\n",
+ printk("scsi%d: destination target %d, lun %llu\n",
H_NO(cmd), cmd->device->id, cmd->device->lun);
printk(KERN_CONT " command = ");
command = cmd->cmnd;
@@ -759,7 +762,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
{
int i, s;
unsigned char *command;
- seq_printf(m, "scsi%d: destination target %d, lun %d\n",
+ seq_printf(m, "scsi%d: destination target %d, lun %llu\n",
H_NO(cmd), cmd->device->id, cmd->device->lun);
seq_printf(m, " command = ");
command = cmd->cmnd;
@@ -1060,12 +1063,13 @@ static void NCR5380_main(struct work_struct *work)
#endif
for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
+ u8 lun = tmp->device->lun;
#if (NDEBUG & NDEBUG_LISTS)
if (prev != tmp)
- printk("MAIN tmp=%p target=%d busy=%d lun=%d\n",
+ printk("MAIN tmp=%p target=%d busy=%d lun=%llu\n",
tmp, tmp->device->id, hostdata->busy[tmp->device->id],
- tmp->device->lun);
+ lun);
#endif
/* When we find one, remove it from the issue queue. */
/* ++guenther: possible race with Falcon locking */
@@ -1073,7 +1077,7 @@ static void NCR5380_main(struct work_struct *work)
#ifdef SUPPORT_TAGS
!is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
#else
- !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+ !(hostdata->busy[tmp->device->id] & (1 << lun))
#endif
) {
/* ++guenther: just to be sure, this must be atomic */
@@ -1099,7 +1103,7 @@ static void NCR5380_main(struct work_struct *work)
*/
dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d "
"lun %d removed from issue_queue\n",
- HOSTNO, tmp->device->id, tmp->device->lun);
+ HOSTNO, tmp->device->id, lun);
/*
* REQUEST SENSE commands are issued without tagged
* queueing, even on SCSI-II devices because the
@@ -2061,7 +2065,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* accesses to this device will use the
* polled-IO. */
printk(KERN_NOTICE "scsi%d: switching target %d "
- "lun %d to slow handshake\n", HOSTNO,
+ "lun %llu to slow handshake\n", HOSTNO,
cmd->device->id, cmd->device->lun);
cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
@@ -2113,7 +2117,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command "
+ dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command "
"complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
/* Enable reselect interrupts */
@@ -2125,7 +2129,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
if (!cmd->next_link) {
- printk(KERN_NOTICE "scsi%d: target %d lun %d "
+ printk(KERN_NOTICE "scsi%d: target %d lun %llu "
"linked command complete, no next_link\n",
HOSTNO, cmd->device->id, cmd->device->lun);
sink = 1;
@@ -2138,7 +2142,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* and don't free it! */
cmd->next_link->tag = cmd->tag;
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request "
+ dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
"done, calling scsi_done().\n",
HOSTNO, cmd->device->id, cmd->device->lun);
#ifdef NCR5380_STATS
@@ -2155,7 +2159,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
/* ++guenther: possible race with Falcon locking */
falcon_dont_release++;
hostdata->connected = NULL;
- dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d "
+ dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
"completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
#ifdef SUPPORT_TAGS
cmd_free_tag(cmd);
@@ -2169,7 +2173,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
/* ++Andreas: the mid level code knows about
QUEUE_FULL now. */
TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
- dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned "
+ dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
"QUEUE_FULL after %d commands\n",
HOSTNO, cmd->device->id, cmd->device->lun,
ta->nr_allocated);
@@ -2267,7 +2271,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
cmd->device->tagged_supported = 0;
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
cmd->tag = TAG_NONE;
- dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected "
+ dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected "
"QUEUE_TAG message; tagged queuing "
"disabled\n",
HOSTNO, cmd->device->id, cmd->device->lun);
@@ -2284,7 +2288,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
local_irq_restore(flags);
- dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was "
+ dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was "
"moved from connected to the "
"disconnected_queue\n", HOSTNO,
cmd->device->id, cmd->device->lun);
@@ -2385,12 +2389,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "message %02x from target %d, lun %d\n",
+ "message %02x from target %d, lun %llu\n",
HOSTNO, tmp, cmd->device->id, cmd->device->lun);
else
printk(KERN_DEBUG "scsi%d: rejecting unknown "
"extended message "
- "code %02x, length %d from target %d, lun %d\n",
+ "code %02x, length %d from target %d, lun %llu\n",
HOSTNO, extended_msg[1], extended_msg[0],
cmd->device->id, cmd->device->lun);
@@ -2588,7 +2592,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
hostdata->connected = tmp;
- dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+ dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
falcon_dont_release--;
}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index fd284ff36ecf..86162811812d 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
stats->r2t_pdus = conn->r2t_pdus_cnt;
stats->digest_err = 0;
stats->timeout_err = 0;
- stats->custom_length = 0;
+ stats->custom_length = 1;
strcpy(stats->custom[0].desc, "eh_abort_cnt");
stats->custom[0].value = conn->eh_abort_cnt;
}
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 56467df3d6de..915c26b23ab6 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -539,7 +539,7 @@ static umode_t beiscsi_eth_get_attr_visibility(void *data, int type)
}
/*------------------- PCI Driver operations and data ----------------- */
-static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
+static const struct pci_device_id beiscsi_pci_id_table[] = {
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
@@ -3538,10 +3538,9 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
q->len = len;
q->entry_size = entry_size;
mem->size = len * entry_size;
- mem->va = pci_alloc_consistent(phba->pcidev, mem->size, &mem->dma);
+ mem->va = pci_zalloc_consistent(phba->pcidev, mem->size, &mem->dma);
if (!mem->va)
return -ENOMEM;
- memset(mem->va, 0, mem->size);
return 0;
}
@@ -4320,9 +4319,9 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
"BM_%d : No boot session\n");
return ret;
}
- nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
- sizeof(*session_resp),
- &nonemb_cmd.dma);
+ nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev,
+ sizeof(*session_resp),
+ &nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
@@ -4332,7 +4331,6 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
return -ENOMEM;
}
- memset(nonemb_cmd.va, 0, sizeof(*session_resp));
tag = mgmt_get_session_info(phba, s_handle,
&nonemb_cmd);
if (!tag) {
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 07934b0b9ee1..665afcb74a56 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -900,13 +900,12 @@ free_cmd:
static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd,
int iscsi_cmd, int size)
{
- cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
+ cmd->va = pci_zalloc_consistent(phba->ctrl.pdev, size, &cmd->dma);
if (!cmd->va) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BG_%d : Failed to allocate memory for if info\n");
return -ENOMEM;
}
- memset(cmd->va, 0, size);
cmd->size = size;
be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size);
return 0;
@@ -1015,7 +1014,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
if (if_info->dhcp_state) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : DHCP Already Enabled\n");
- return 0;
+ goto exit;
}
/* The ip_param->len is 1 in DHCP case. Setting
proper IP len as this it is used while
@@ -1033,7 +1032,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
sizeof(*reldhcp));
if (rc)
- return rc;
+ goto exit;
reldhcp = nonemb_cmd.va;
reldhcp->interface_hndl = phba->interface_handle;
@@ -1044,7 +1043,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
beiscsi_log(phba, KERN_WARNING,
BEISCSI_LOG_CONFIG,
"BG_%d : Failed to Delete existing dhcp\n");
- return rc;
+ goto exit;
}
}
}
@@ -1054,7 +1053,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL,
IP_ACTION_DEL);
if (rc)
- return rc;
+ goto exit;
}
/* Delete the Gateway settings if mode change is to DHCP */
@@ -1064,7 +1063,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
if (rc) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : Failed to Get Gateway Addr\n");
- return rc;
+ goto exit;
}
if (gtway_addr_set.ip_addr.addr[0]) {
@@ -1076,7 +1075,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
beiscsi_log(phba, KERN_WARNING,
BEISCSI_LOG_CONFIG,
"BG_%d : Failed to clear Gateway Addr Set\n");
- return rc;
+ goto exit;
}
}
}
@@ -1087,7 +1086,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
sizeof(*dhcpreq));
if (rc)
- return rc;
+ goto exit;
dhcpreq = nonemb_cmd.va;
dhcpreq->flags = BLOCKING;
@@ -1095,12 +1094,14 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
dhcpreq->interface_hndl = phba->interface_handle;
dhcpreq->ip_type = BE2_DHCP_V4;
- return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
+ rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
} else {
- return mgmt_static_ip_modify(phba, if_info, ip_param,
+ rc = mgmt_static_ip_modify(phba, if_info, ip_param,
subnet_param, IP_ACTION_ADD);
}
+exit:
+ kfree(if_info);
return rc;
}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index a3ab5cce4208..0f19455951ec 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -81,7 +81,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
bfa->fcs = BFA_TRUE;
fcbuild_init();
- for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
mod = &fcs_modules[i];
if (mod->attach)
mod->attach(fcs);
@@ -97,7 +97,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs)
int i;
struct bfa_fcs_mod_s *mod;
- for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
mod = &fcs_modules[i];
if (mod->modinit)
mod->modinit(fcs);
@@ -184,7 +184,7 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs)
bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
- nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+ nmods = ARRAY_SIZE(fcs_modules);
for (i = 0; i < nmods; i++) {
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 2e28392c2fb6..a38aafa030b3 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -72,7 +72,7 @@ struct bfa_sge_s {
} while (0)
#define bfa_swap_words(_x) ( \
- ((_x) << 32) | ((_x) >> 32))
+ ((u64)(_x) << 32) | ((u64)(_x) >> 32))
#ifdef __BIG_ENDIAN
#define bfa_sge_to_be(_x)
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 7593b7c1d336..e90a3742f09d 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -1219,7 +1219,7 @@ bfad_install_msix_handler(struct bfad_s *bfad)
int
bfad_setup_intr(struct bfad_s *bfad)
{
- int error = 0;
+ int error;
u32 mask = 0, i, num_bit = 0, max_bit = 0;
struct msix_entry msix_entries[MAX_MSIX_ENTRY];
struct pci_dev *pdev = bfad->pcidev;
@@ -1234,34 +1234,24 @@ bfad_setup_intr(struct bfad_s *bfad)
if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) ||
(bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) {
- error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
- if (error) {
- /* In CT1 & CT2, try to allocate just one vector */
- if (bfa_asic_id_ctc(pdev->device)) {
- printk(KERN_WARNING "bfa %s: trying one msix "
- "vector failed to allocate %d[%d]\n",
- bfad->pci_name, bfad->nvec, error);
- bfad->nvec = 1;
- error = pci_enable_msix(bfad->pcidev,
- msix_entries, bfad->nvec);
- }
+ error = pci_enable_msix_exact(bfad->pcidev,
+ msix_entries, bfad->nvec);
+ /* In CT1 & CT2, try to allocate just one vector */
+ if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) {
+ printk(KERN_WARNING "bfa %s: trying one msix "
+ "vector failed to allocate %d[%d]\n",
+ bfad->pci_name, bfad->nvec, error);
+ bfad->nvec = 1;
+ error = pci_enable_msix_exact(bfad->pcidev,
+ msix_entries, 1);
+ }
- /*
- * Only error number of vector is available.
- * We don't have a mechanism to map multiple
- * interrupts into one vector, so even if we
- * can try to request less vectors, we don't
- * know how to associate interrupt events to
- * vectors. Linux doesn't duplicate vectors
- * in the MSIX table for this case.
- */
- if (error) {
- printk(KERN_WARNING "bfad%d: "
- "pci_enable_msix failed (%d), "
- "use line based.\n",
- bfad->inst_no, error);
- goto line_based;
- }
+ if (error) {
+ printk(KERN_WARNING "bfad%d: "
+ "pci_enable_msix_exact failed (%d), "
+ "use line based.\n",
+ bfad->inst_no, error);
+ goto line_based;
}
/* Disable INTX in MSI-X mode */
@@ -1281,20 +1271,18 @@ bfad_setup_intr(struct bfad_s *bfad)
bfad->bfad_flags |= BFAD_MSIX_ON;
- return error;
+ return 0;
}
line_based:
- error = 0;
- if (request_irq
- (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
- BFAD_DRIVER_NAME, bfad) != 0) {
- /* Enable interrupt handler failed */
- return 1;
- }
+ error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx,
+ BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad);
+ if (error)
+ return error;
+
bfad->bfad_flags |= BFAD_INTX_ON;
- return error;
+ return 0;
}
void
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 8994fb857ee9..023b9d42ad9a 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -26,7 +26,6 @@ int
bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
- int rc = 0;
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -34,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
- return rc;
+ return 0;
}
init_completion(&bfad->enable_comp);
@@ -43,21 +42,20 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
wait_for_completion(&bfad->enable_comp);
- return rc;
+ return 0;
}
int
bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
- int rc = 0;
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
iocmd->status = BFA_STATUS_OK;
- return rc;
+ return 0;
}
if (bfad->disable_active) {
@@ -74,7 +72,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
bfad->disable_active = BFA_FALSE;
iocmd->status = BFA_STATUS_OK;
- return rc;
+ return 0;
}
static int
@@ -3270,13 +3268,13 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
/* Allocate dma coherent memory */
buf_info = buf_base;
buf_info->size = payload_len;
- buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
- &buf_info->phys, GFP_KERNEL);
+ buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
+ buf_info->size, &buf_info->phys,
+ GFP_KERNEL);
if (!buf_info->virt)
goto out_free_mem;
/* copy the linear bsg buffer to buf_info */
- memset(buf_info->virt, 0, buf_info->size);
memcpy(buf_info->virt, payload_kbuf, buf_info->size);
/*
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index e1f1e3448f98..fe2106c91c08 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -1,3 +1,16 @@
+/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
#ifndef __57XX_FCOE_HSI_LINUX_LE__
#define __57XX_FCOE_HSI_LINUX_LE__
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index cfcad8bde7cf..f245d543d7b1 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -1,5 +1,5 @@
config SCSI_BNX2X_FCOE
- tristate "Broadcom NetXtreme II FCoE support"
+ tristate "QLogic NetXtreme II FCoE support"
depends on PCI
select NETDEVICES
select ETHERNET
@@ -8,5 +8,5 @@ config SCSI_BNX2X_FCOE
select LIBFCOE
select CNIC
---help---
- This driver supports FCoE offload for the Broadcom NetXtreme II
+ This driver supports FCoE offload for the QLogic NetXtreme II
devices.
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 6a976657b475..1346e052e03c 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -1,8 +1,7 @@
-#ifndef _BNX2FC_H_
-#define _BNX2FC_H_
-/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,6 +10,8 @@
* Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
*/
+#ifndef _BNX2FC_H_
+#define _BNX2FC_H_
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
index dad9924abbbb..e147cc7ee36c 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_constants.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -1,3 +1,16 @@
+/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
#ifndef __BNX2FC_CONSTANTS_H_
#define __BNX2FC_CONSTANTS_H_
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.c b/drivers/scsi/bnx2fc/bnx2fc_debug.c
index 0cbee1b23ee2..d055df01faa5 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.c
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
#include "bnx2fc.h"
void BNX2FC_IO_DBG(const struct bnx2fc_cmd *io_req, const char *fmt, ...)
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h
index 4808ff99621f..2b9006774f37 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_debug.h
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h
@@ -1,3 +1,16 @@
+/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ */
+
#ifndef __BNX2FC_DEBUG__
#define __BNX2FC_DEBUG__
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
index b1c9a4f8caee..ca75c7ca2559 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_els.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -1,9 +1,10 @@
/*
- * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
* This file contains helper routines that handle ELS requests
* and responses.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 785d0d71781e..79e5c94107a9 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1,9 +1,10 @@
-/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver.
* This file contains the code that interacts with libfc, libfcoe,
* cnic modules to create FCoE instances, send/receive non-offloaded
* FIP/FCoE packets, listen to link events etc.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,12 +27,12 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
static char version[] =
- "Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+ "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver");
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -692,7 +693,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
if (!lport->vport)
fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
snprintf(fc_host_symbolic_name(lport->host), 256,
- "%s (Broadcom %s) v%s over %s",
+ "%s (QLogic %s) v%s over %s",
BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION,
interface->netdev->name);
@@ -2775,7 +2776,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = {
*/
static struct scsi_host_template bnx2fc_shost_template = {
.module = THIS_MODULE,
- .name = "Broadcom Offload FCoE Initiator",
+ .name = "QLogic Offload FCoE Initiator",
.queuecommand = bnx2fc_queuecommand,
.eh_abort_handler = bnx2fc_eh_abort, /* abts */
.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 512aed3ae4f1..c6688d72a846 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1,8 +1,9 @@
-/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver.
* This file contains the code that low level functions that interact
* with 57712 FCoE firmware.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 7bc47fc7c686..4c5891e66038 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1,7 +1,8 @@
-/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver.
* IO manager and SCSI IO processing.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1450,9 +1451,9 @@ static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req)
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct bnx2fc_rport *tgt = io_req->tgt;
struct bnx2fc_cmd *cmd, *tmp;
- int tm_lun = sc_cmd->device->lun;
+ u64 tm_lun = sc_cmd->device->lun;
+ u64 lun;
int rc = 0;
- int lun;
/* called with tgt_lock held */
BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n");
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 6870cf6781d9..c66c708412a6 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -1,8 +1,9 @@
-/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver.
* Handles operations such as session offload/upload etc, and manages
* session resources such as connection id and qp resources.
*
* Copyright (c) 2008 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 3d33767f2f2c..917534109a50 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
+/* 57xx_iscsi_constants.h: QLogic NetXtreme II iSCSI HSI
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#ifndef __57XX_ISCSI_CONSTANTS_H_
#define __57XX_ISCSI_CONSTANTS_H_
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 7052a839b0ea..19b3a97dbacd 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,13 +1,15 @@
-/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
+/* 57xx_iscsi_hsi.h: QLogic NetXtreme II iSCSI HSI.
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#ifndef __57XX_ISCSI_HSI_LINUX_LE__
#define __57XX_ISCSI_HSI_LINUX_LE__
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig
index 01cff1894b6d..44ce54e536e5 100644
--- a/drivers/scsi/bnx2i/Kconfig
+++ b/drivers/scsi/bnx2i/Kconfig
@@ -1,5 +1,5 @@
config SCSI_BNX2_ISCSI
- tristate "Broadcom NetXtreme II iSCSI support"
+ tristate "QLogic NetXtreme II iSCSI support"
depends on NET
depends on PCI
select SCSI_ISCSI_ATTRS
@@ -8,5 +8,5 @@ config SCSI_BNX2_ISCSI
select NET_VENDOR_BROADCOM
select CNIC
---help---
- This driver supports iSCSI offload for the Broadcom NetXtreme II
+ This driver supports iSCSI offload for the QLogic NetXtreme II
devices.
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index c73bbcb63c02..ed7f3228e234 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,15 +1,17 @@
-/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.h: QLogic NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#ifndef _BNX2I_H_
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d6d491c2f004..fb072cc5e9fd 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1,15 +1,17 @@
-/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_hwi.c: QLogic NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#include <linux/gfp.h>
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 80c03b452d61..c8b410c24cf0 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,15 +1,17 @@
-/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i.c: QLogic NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#include "bnx2i.h"
@@ -18,18 +20,18 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
static u32 adapter_count;
#define DRV_MODULE_NAME "bnx2i"
-#define DRV_MODULE_VERSION "2.7.6.2"
-#define DRV_MODULE_RELDATE "Jun 06, 2013"
+#define DRV_MODULE_VERSION "2.7.10.1"
+#define DRV_MODULE_RELDATE "Jul 16, 2014"
static char version[] =
- "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
+ "QLogic NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
"Eddie Wai <eddie.wai@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
+MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/57710/57711/57712"
"/57800/57810/57840 iSCSI Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 166543f7ef55..40e22497d249 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,16 +1,18 @@
/*
- * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
+ * bnx2i_iscsi.c: QLogic NetXtreme II iSCSI driver.
*
* Copyright (c) 2006 - 2013 Broadcom Corporation
* Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
* Copyright (c) 2007, 2008 Mike Christie
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#include <linux/slab.h>
@@ -1643,12 +1645,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
stats->r2t_pdus = conn->r2t_pdus_cnt;
stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
- stats->custom_length = 3;
- strcpy(stats->custom[2].desc, "eh_abort_cnt");
- stats->custom[2].value = conn->eh_abort_cnt;
stats->digest_err = 0;
stats->timeout_err = 0;
- stats->custom_length = 0;
+ strcpy(stats->custom[0].desc, "eh_abort_cnt");
+ stats->custom[0].value = conn->eh_abort_cnt;
+ stats->custom_length = 1;
}
@@ -2249,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int param_type, int param)
*/
static struct scsi_host_template bnx2i_host_template = {
.module = THIS_MODULE,
- .name = "Broadcom Offload iSCSI Initiator",
+ .name = "QLogic Offload iSCSI Initiator",
.proc_name = "bnx2i",
.queuecommand = iscsi_queuecommand,
.eh_abort_handler = iscsi_eh_abort,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index a0a3d9fe61fe..6d56fd60cb2b 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,13 +1,15 @@
-/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
+/* bnx2i_sysfs.c: QLogic NetXtreme II iSCSI driver.
*
* Copyright (c) 2004 - 2013 Broadcom Corporation
+ * Copyright (c) 2014, QLogic Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
- * Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com)
+ * Maintained by: QLogic-Storage-Upstream@qlogic.com
*/
#include "bnx2i.h"
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 2a323742ce04..ef5ae0d03616 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -84,15 +84,19 @@ static const char * vendor_labels[CH_TYPES-4] = {
};
// module_param_string_array(vendor_labels, NULL, 0444);
+#define ch_printk(prefix, ch, fmt, a...) \
+ sdev_printk(prefix, (ch)->device, "[%s] " fmt, \
+ (ch)->name, ##a)
+
#define DPRINTK(fmt, arg...) \
do { \
if (debug) \
- printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \
+ ch_printk(KERN_DEBUG, ch, fmt, ##arg); \
} while (0)
#define VPRINTK(level, fmt, arg...) \
do { \
if (verbose) \
- printk(level "%s: " fmt, ch->name, ##arg); \
+ ch_printk(level, ch, fmt, ##arg); \
} while (0)
/* ------------------------------------------------------------------- */
@@ -196,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
__scsi_print_command(cmd);
}
- result = scsi_execute_req(ch->device, cmd, direction, buffer,
+ result = scsi_execute_req(ch->device, cmd, direction, buffer,
buflength, &sshdr, timeout * HZ,
MAX_RETRIES, NULL);
@@ -247,7 +251,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
retry:
memset(cmd,0,sizeof(cmd));
cmd[0] = READ_ELEMENT_STATUS;
- cmd[1] = (ch->device->lun << 5) |
+ cmd[1] = ((ch->device->lun & 0x7) << 5) |
(ch->voltags ? 0x10 : 0) |
ch_elem_to_typecode(ch,elem);
cmd[2] = (elem >> 8) & 0xff;
@@ -283,7 +287,7 @@ ch_init_elem(scsi_changer *ch)
VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n");
memset(cmd,0,sizeof(cmd));
cmd[0] = INITIALIZE_ELEMENT_STATUS;
- cmd[1] = ch->device->lun << 5;
+ cmd[1] = (ch->device->lun & 0x7) << 5;
err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
VPRINTK(KERN_INFO, "... finished\n");
return err;
@@ -303,7 +307,7 @@ ch_readconfig(scsi_changer *ch)
memset(cmd,0,sizeof(cmd));
cmd[0] = MODE_SENSE;
- cmd[1] = ch->device->lun << 5;
+ cmd[1] = (ch->device->lun & 0x7) << 5;
cmd[2] = 0x1d;
cmd[4] = 255;
result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
@@ -428,7 +432,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
trans = ch->firsts[CHET_MT];
memset(cmd,0,sizeof(cmd));
cmd[0] = POSITION_TO_ELEMENT;
- cmd[1] = ch->device->lun << 5;
+ cmd[1] = (ch->device->lun & 0x7) << 5;
cmd[2] = (trans >> 8) & 0xff;
cmd[3] = trans & 0xff;
cmd[4] = (elem >> 8) & 0xff;
@@ -447,7 +451,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
trans = ch->firsts[CHET_MT];
memset(cmd,0,sizeof(cmd));
cmd[0] = MOVE_MEDIUM;
- cmd[1] = ch->device->lun << 5;
+ cmd[1] = (ch->device->lun & 0x7) << 5;
cmd[2] = (trans >> 8) & 0xff;
cmd[3] = trans & 0xff;
cmd[4] = (src >> 8) & 0xff;
@@ -470,7 +474,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src,
trans = ch->firsts[CHET_MT];
memset(cmd,0,sizeof(cmd));
cmd[0] = EXCHANGE_MEDIUM;
- cmd[1] = ch->device->lun << 5;
+ cmd[1] = (ch->device->lun & 0x7) << 5;
cmd[2] = (trans >> 8) & 0xff;
cmd[3] = trans & 0xff;
cmd[4] = (src >> 8) & 0xff;
@@ -518,7 +522,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
elem, tag);
memset(cmd,0,sizeof(cmd));
cmd[0] = SEND_VOLUME_TAG;
- cmd[1] = (ch->device->lun << 5) |
+ cmd[1] = ((ch->device->lun & 0x7) << 5) |
ch_elem_to_typecode(ch,elem);
cmd[2] = (elem >> 8) & 0xff;
cmd[3] = elem & 0xff;
@@ -754,7 +758,7 @@ static long ch_ioctl(struct file *file,
voltag_retry:
memset(ch_cmd, 0, sizeof(ch_cmd));
ch_cmd[0] = READ_ELEMENT_STATUS;
- ch_cmd[1] = (ch->device->lun << 5) |
+ ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
(ch->voltags ? 0x10 : 0) |
ch_elem_to_typecode(ch,elem);
ch_cmd[2] = (elem >> 8) & 0xff;
@@ -924,8 +928,8 @@ static int ch_probe(struct device *dev)
MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
"s%s", ch->name);
if (IS_ERR(class_dev)) {
- printk(KERN_WARNING "ch%d: device_create failed\n",
- ch->minor);
+ sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n",
+ ch->minor);
ret = PTR_ERR(class_dev);
goto remove_idr;
}
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index 1aafc331ee63..17794add855c 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -1167,7 +1167,7 @@ static struct pci_error_handlers csio_err_handler = {
.resume = csio_pci_resume,
};
-static DEFINE_PCI_DEVICE_TABLE(csio_pci_tbl) = {
+static const struct pci_device_id csio_pci_tbl[] = {
CSIO_DEVICE(CSIO_DEVID_T440DBG_FCOE, 0), /* T4 DEBUG FCOE */
CSIO_DEVICE(CSIO_DEVID_T420CR_FCOE, 0), /* T420CR FCOE */
CSIO_DEVICE(CSIO_DEVID_T422CR_FCOE, 0), /* T422CR FCOE */
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 7494e4bc69cc..86103c8475d8 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -1657,7 +1657,7 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req)
case FW_SCSI_UNDER_FLOW_ERR:
csio_warn(hw,
"Under-flow error,cmnd:0x%x expected"
- " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n",
+ " len:0x%x resid:0x%x lun:0x%llx ssn:0x%x\n",
cmnd->cmnd[0], scsi_bufflen(cmnd),
scsi_get_resid(cmnd), cmnd->device->lun,
rn->flowid);
@@ -1957,7 +1957,7 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd)
csio_dbg(hw,
"Request to abort ioreq:%p cmd:%p cdb:%08llx"
- " ssni:0x%x lun:%d iq:0x%x\n",
+ " ssni:0x%x lun:%llu iq:0x%x\n",
ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid,
cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx));
@@ -2015,13 +2015,13 @@ inval_scmnd:
/* FW successfully aborted the request */
if (host_byte(cmnd->result) == DID_REQUEUE) {
csio_info(hw,
- "Aborted SCSI command to (%d:%d) serial#:0x%lx\n",
+ "Aborted SCSI command to (%d:%llu) serial#:0x%lx\n",
cmnd->device->id, cmnd->device->lun,
cmnd->serial_number);
return SUCCESS;
} else {
csio_info(hw,
- "Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n",
+ "Failed to abort SCSI command, (%d:%llu) serial#:0x%lx\n",
cmnd->device->id, cmnd->device->lun,
cmnd->serial_number);
return FAILED;
@@ -2100,13 +2100,13 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
if (!rn)
goto fail;
- csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n",
+ csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n",
cmnd->device->lun, rn->flowid, rn->scsi_id);
if (!csio_is_lnode_ready(ln)) {
csio_err(hw,
"LUN reset cannot be issued on non-ready"
- " local node vnpi:0x%x (LUN:%d)\n",
+ " local node vnpi:0x%x (LUN:%llu)\n",
ln->vnp_flowid, cmnd->device->lun);
goto fail;
}
@@ -2126,7 +2126,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
if (fc_remote_port_chkready(rn->rport)) {
csio_err(hw,
"LUN reset cannot be issued on non-ready"
- " remote node ssni:0x%x (LUN:%d)\n",
+ " remote node ssni:0x%x (LUN:%llu)\n",
rn->flowid, cmnd->device->lun);
goto fail;
}
@@ -2168,7 +2168,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
sld.level = CSIO_LEV_LUN;
sld.lnode = ioreq->lnode;
sld.rnode = ioreq->rnode;
- sld.oslun = (uint64_t)cmnd->device->lun;
+ sld.oslun = cmnd->device->lun;
spin_lock_irqsave(&hw->lock, flags);
/* Kick off TM SM on the ioreq */
@@ -2190,7 +2190,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
/* LUN reset timed-out */
if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) {
- csio_err(hw, "LUN reset (%d:%d) timed out\n",
+ csio_err(hw, "LUN reset (%d:%llu) timed out\n",
cmnd->device->id, cmnd->device->lun);
spin_lock_irq(&hw->lock);
@@ -2203,7 +2203,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
/* LUN reset returned, check cached status */
if (cmnd->SCp.Status != FW_SUCCESS) {
- csio_err(hw, "LUN reset failed (%d:%d), status: %d\n",
+ csio_err(hw, "LUN reset failed (%d:%llu), status: %d\n",
cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status);
goto fail;
}
@@ -2223,7 +2223,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
/* Aborts may have timed out */
if (retval != 0) {
csio_err(hw,
- "Attempt to abort I/Os during LUN reset of %d"
+ "Attempt to abort I/Os during LUN reset of %llu"
" returned %d\n", cmnd->device->lun, retval);
/* Return I/Os back to active_q */
spin_lock_irq(&hw->lock);
@@ -2234,7 +2234,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
CSIO_INC_STATS(rn, n_lun_rst);
- csio_info(hw, "LUN reset occurred (%d:%d)\n",
+ csio_info(hw, "LUN reset occurred (%d:%llu)\n",
cmnd->device->id, cmnd->device->lun);
return SUCCESS;
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index 4255ce264abf..773da14cfa14 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -232,7 +232,7 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
q = wrm->q_arr[free_idx];
- q->vstart = pci_alloc_consistent(hw->pdev, qsz, &q->pstart);
+ q->vstart = pci_zalloc_consistent(hw->pdev, qsz, &q->pstart);
if (!q->vstart) {
csio_err(hw,
"Failed to allocate DMA memory for "
@@ -240,12 +240,6 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
return -1;
}
- /*
- * We need to zero out the contents, importantly for ingress,
- * since we start with a generatiom bit of 1 for ingress.
- */
- memset(q->vstart, 0, qsz);
-
q->type = type;
q->owner = owner;
q->pidx = q->cidx = q->inc_idx = 0;
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index 6bbc36fbd6ec..e4603985dce3 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -1,6 +1,6 @@
config SCSI_CXGB3_ISCSI
tristate "Chelsio T3 iSCSI support"
- depends on PCI && INET
+ depends on PCI && INET && (IPV6 || IPV6=n)
select NETDEVICES
select ETHERNET
select NET_VENDOR_CHELSIO
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index 16b2c7d26617..8c4e423037b6 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -1,6 +1,6 @@
config SCSI_CXGB4_ISCSI
tristate "Chelsio T4 iSCSI support"
- depends on PCI && INET
+ depends on PCI && INET && (IPV6 || IPV6=n)
select NETDEVICES
select ETHERNET
select NET_VENDOR_CHELSIO
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index e8ee5e5fe0ef..79788a12712d 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -19,6 +19,7 @@
#include <net/tcp.h>
#include <net/dst.h>
#include <linux/netdevice.h>
+#include <net/addrconf.h>
#include "t4_regs.h"
#include "t4_msg.h"
@@ -150,6 +151,7 @@ static struct scsi_transport_template *cxgb4i_stt;
* The section below implments CPLs that related to iscsi tcp connection
* open/close/abort and data send/receive.
*/
+
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#define RCV_BUFSIZ_MASK 0x3FFU
#define MAX_IMM_TX_PKT_LEN 128
@@ -179,6 +181,7 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
struct l2t_entry *e)
{
struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+ int t4 = is_t4(lldi->adapter_type);
int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
unsigned long long opt0;
unsigned int opt2;
@@ -248,6 +251,97 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
}
set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+ pr_info_ipaddr("t%d csk 0x%p,%u,0x%lx,%u, rss_qid %u.\n",
+ (&csk->saddr), (&csk->daddr), t4 ? 4 : 5, csk,
+ csk->state, csk->flags, csk->atid, csk->rss_qid);
+
+ cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_act_open_req6(struct cxgbi_sock *csk, struct sk_buff *skb,
+ struct l2t_entry *e)
+{
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+ int t4 = is_t4(lldi->adapter_type);
+ int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+ unsigned long long opt0;
+ unsigned int opt2;
+ unsigned int qid_atid = ((unsigned int)csk->atid) |
+ (((unsigned int)csk->rss_qid) << 14);
+
+ opt0 = KEEP_ALIVE(1) |
+ WND_SCALE(wscale) |
+ MSS_IDX(csk->mss_idx) |
+ L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+ TX_CHAN(csk->tx_chan) |
+ SMAC_SEL(csk->smac_idx) |
+ ULP_MODE(ULP_MODE_ISCSI) |
+ RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+
+ opt2 = RX_CHANNEL(0) |
+ RSS_QUEUE_VALID |
+ RX_FC_DISABLE |
+ RSS_QUEUE(csk->rss_qid);
+
+ if (t4) {
+ struct cpl_act_open_req6 *req =
+ (struct cpl_act_open_req6 *)skb->head;
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+ qid_atid));
+ req->local_port = csk->saddr6.sin6_port;
+ req->peer_port = csk->daddr6.sin6_port;
+
+ req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+ req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+ 8);
+ req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+ req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+ 8);
+
+ req->opt0 = cpu_to_be64(opt0);
+
+ opt2 |= RX_FC_VALID;
+ req->opt2 = cpu_to_be32(opt2);
+
+ req->params = cpu_to_be32(cxgb4_select_ntuple(
+ csk->cdev->ports[csk->port_id],
+ csk->l2t));
+ } else {
+ struct cpl_t5_act_open_req6 *req =
+ (struct cpl_t5_act_open_req6 *)skb->head;
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+ qid_atid));
+ req->local_port = csk->saddr6.sin6_port;
+ req->peer_port = csk->daddr6.sin6_port;
+ req->local_ip_hi = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr);
+ req->local_ip_lo = *(__be64 *)(csk->saddr6.sin6_addr.s6_addr +
+ 8);
+ req->peer_ip_hi = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr);
+ req->peer_ip_lo = *(__be64 *)(csk->daddr6.sin6_addr.s6_addr +
+ 8);
+ req->opt0 = cpu_to_be64(opt0);
+
+ opt2 |= T5_OPT_2_VALID;
+ req->opt2 = cpu_to_be32(opt2);
+
+ req->params = cpu_to_be64(V_FILTER_TUPLE(cxgb4_select_ntuple(
+ csk->cdev->ports[csk->port_id],
+ csk->l2t)));
+ }
+
+ set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+
+ pr_info("t%d csk 0x%p,%u,0x%lx,%u, [%pI6]:%u-[%pI6]:%u, rss_qid %u.\n",
+ t4 ? 4 : 5, csk, csk->state, csk->flags, csk->atid,
+ &csk->saddr6.sin6_addr, ntohs(csk->saddr.sin_port),
+ &csk->daddr6.sin6_addr, ntohs(csk->daddr.sin_port),
+ csk->rss_qid);
+
cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
}
@@ -586,9 +680,11 @@ static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb)
goto rel_skb;
}
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
- csk, csk->state, csk->flags, tid, atid, rcv_isn);
+ pr_info_ipaddr("atid 0x%x, tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+ (&csk->saddr), (&csk->daddr),
+ atid, tid, csk, csk->state, csk->flags, rcv_isn);
+
+ module_put(THIS_MODULE);
cxgbi_sock_get(csk);
csk->tid = tid;
@@ -663,6 +759,9 @@ static void csk_act_open_retry_timer(unsigned long data)
struct sk_buff *skb;
struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+ void (*send_act_open_func)(struct cxgbi_sock *, struct sk_buff *,
+ struct l2t_entry *);
+ int t4 = is_t4(lldi->adapter_type), size, size6;
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p,%u,0x%lx,%u.\n",
@@ -670,20 +769,35 @@ static void csk_act_open_retry_timer(unsigned long data)
cxgbi_sock_get(csk);
spin_lock_bh(&csk->lock);
- skb = alloc_wr(is_t4(lldi->adapter_type) ?
- sizeof(struct cpl_act_open_req) :
- sizeof(struct cpl_t5_act_open_req),
- 0, GFP_ATOMIC);
+
+ if (t4) {
+ size = sizeof(struct cpl_act_open_req);
+ size6 = sizeof(struct cpl_act_open_req6);
+ } else {
+ size = sizeof(struct cpl_t5_act_open_req);
+ size6 = sizeof(struct cpl_t5_act_open_req6);
+ }
+
+ if (csk->csk_family == AF_INET) {
+ send_act_open_func = send_act_open_req;
+ skb = alloc_wr(size, 0, GFP_ATOMIC);
+ } else {
+ send_act_open_func = send_act_open_req6;
+ skb = alloc_wr(size6, 0, GFP_ATOMIC);
+ }
+
if (!skb)
cxgbi_sock_fail_act_open(csk, -ENOMEM);
else {
skb->sk = (struct sock *)csk;
t4_set_arp_err_handler(skb, csk,
- cxgbi_sock_act_open_req_arp_failure);
- send_act_open_req(csk, skb, csk->l2t);
+ cxgbi_sock_act_open_req_arp_failure);
+ send_act_open_func(csk, skb, csk->l2t);
}
+
spin_unlock_bh(&csk->lock);
cxgbi_sock_put(csk);
+
}
static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
@@ -703,10 +817,9 @@ static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
goto rel_skb;
}
- pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
- &csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
- &csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
- atid, tid, status, csk, csk->state, csk->flags);
+ pr_info_ipaddr("tid %u/%u, status %u.\n"
+ "csk 0x%p,%u,0x%lx. ", (&csk->saddr), (&csk->daddr),
+ atid, tid, status, csk, csk->state, csk->flags);
if (status == CPL_ERR_RTX_NEG_ADVICE)
goto rel_skb;
@@ -746,9 +859,9 @@ static void do_peer_close(struct cxgbi_device *cdev, struct sk_buff *skb)
pr_err("can't find connection for tid %u.\n", tid);
goto rel_skb;
}
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p,%u,0x%lx,%u.\n",
- csk, csk->state, csk->flags, csk->tid);
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+ (&csk->saddr), (&csk->daddr),
+ csk, csk->state, csk->flags, csk->tid);
cxgbi_sock_rcv_peer_close(csk);
rel_skb:
__kfree_skb(skb);
@@ -767,9 +880,9 @@ static void do_close_con_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
pr_err("can't find connection for tid %u.\n", tid);
goto rel_skb;
}
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p,%u,0x%lx,%u.\n",
- csk, csk->state, csk->flags, csk->tid);
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u.\n",
+ (&csk->saddr), (&csk->daddr),
+ csk, csk->state, csk->flags, csk->tid);
cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
rel_skb:
__kfree_skb(skb);
@@ -808,9 +921,9 @@ static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
goto rel_skb;
}
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
- csk, csk->state, csk->flags, csk->tid, req->status);
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+ (&csk->saddr), (&csk->daddr),
+ csk, csk->state, csk->flags, csk->tid, req->status);
if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
req->status == CPL_ERR_PERSIST_NEG_ADVICE)
@@ -851,10 +964,10 @@ static void do_abort_rpl_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
if (!csk)
goto rel_skb;
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
- rpl->status, csk, csk ? csk->state : 0,
- csk ? csk->flags : 0UL);
+ if (csk)
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+ (&csk->saddr), (&csk->daddr), csk,
+ csk->state, csk->flags, csk->tid, rpl->status);
if (rpl->status == CPL_ERR_ABORT_FAILED)
goto rel_skb;
@@ -1163,15 +1276,35 @@ static int init_act_open(struct cxgbi_sock *csk)
struct cxgbi_device *cdev = csk->cdev;
struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
struct net_device *ndev = cdev->ports[csk->port_id];
- struct port_info *pi = netdev_priv(ndev);
struct sk_buff *skb = NULL;
- struct neighbour *n;
+ struct neighbour *n = NULL;
+ void *daddr;
unsigned int step;
+ unsigned int size, size6;
+ int t4 = is_t4(lldi->adapter_type);
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
"csk 0x%p,%u,0x%lx,%u.\n",
csk, csk->state, csk->flags, csk->tid);
+ if (csk->csk_family == AF_INET)
+ daddr = &csk->daddr.sin_addr.s_addr;
+#if IS_ENABLED(CONFIG_IPV6)
+ else if (csk->csk_family == AF_INET6)
+ daddr = &csk->daddr6.sin6_addr;
+#endif
+ else {
+ pr_err("address family 0x%x not supported\n", csk->csk_family);
+ goto rel_resource;
+ }
+
+ n = dst_neigh_lookup(csk->dst, daddr);
+
+ if (!n) {
+ pr_err("%s, can't get neighbour of csk->dst.\n", ndev->name);
+ goto rel_resource;
+ }
+
csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
if (csk->atid < 0) {
pr_err("%s, NO atid available.\n", ndev->name);
@@ -1192,10 +1325,19 @@ static int init_act_open(struct cxgbi_sock *csk)
}
cxgbi_sock_get(csk);
- skb = alloc_wr(is_t4(lldi->adapter_type) ?
- sizeof(struct cpl_act_open_req) :
- sizeof(struct cpl_t5_act_open_req),
- 0, GFP_ATOMIC);
+ if (t4) {
+ size = sizeof(struct cpl_act_open_req);
+ size6 = sizeof(struct cpl_act_open_req6);
+ } else {
+ size = sizeof(struct cpl_t5_act_open_req);
+ size6 = sizeof(struct cpl_t5_act_open_req6);
+ }
+
+ if (csk->csk_family == AF_INET)
+ skb = alloc_wr(size, 0, GFP_NOIO);
+ else
+ skb = alloc_wr(size6, 0, GFP_NOIO);
+
if (!skb)
goto rel_resource;
skb->sk = (struct sock *)csk;
@@ -1211,19 +1353,27 @@ static int init_act_open(struct cxgbi_sock *csk)
csk->txq_idx = cxgb4_port_idx(ndev) * step;
step = lldi->nrxq / lldi->nchan;
csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
- csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+ csk->wr_cred = lldi->wr_cred -
+ DIV_ROUND_UP(sizeof(struct cpl_abort_req), 16);
+ csk->wr_max_cred = csk->wr_cred;
csk->wr_una_cred = 0;
cxgbi_sock_reset_wr_list(csk);
csk->err = 0;
- log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
- "csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
- csk, pi->port_id, ndev->name, csk->tx_chan,
- csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
- csk->smac_idx);
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u,%u,%u, mtu %u,%u, smac %u.\n",
+ (&csk->saddr), (&csk->daddr), csk, csk->state,
+ csk->flags, csk->tx_chan, csk->txq_idx, csk->rss_qid,
+ csk->mtu, csk->mss_idx, csk->smac_idx);
+
+ /* must wait for either a act_open_rpl or act_open_establish */
+ try_module_get(THIS_MODULE);
cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
- send_act_open_req(csk, skb, csk->l2t);
+ if (csk->csk_family == AF_INET)
+ send_act_open_req(csk, skb, csk->l2t);
+ else
+ send_act_open_req6(csk, skb, csk->l2t);
neigh_release(n);
+
return 0;
rel_resource:
@@ -1234,8 +1384,6 @@ rel_resource:
return -EINVAL;
}
-#define CPL_ISCSI_DATA 0xB2
-#define CPL_RX_ISCSI_DDP 0x49
cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
[CPL_ACT_ESTABLISH] = do_act_establish,
[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
@@ -1487,6 +1635,129 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
return 0;
}
+#if IS_ENABLED(CONFIG_IPV6)
+static int cxgbi_inet6addr_handler(struct notifier_block *this,
+ unsigned long event, void *data)
+{
+ struct inet6_ifaddr *ifa = data;
+ struct net_device *event_dev = ifa->idev->dev;
+ struct cxgbi_device *cdev;
+ int ret = NOTIFY_DONE;
+
+ if (event_dev->priv_flags & IFF_802_1Q_VLAN)
+ event_dev = vlan_dev_real_dev(event_dev);
+
+ cdev = cxgbi_device_find_by_netdev(event_dev, NULL);
+
+ if (!cdev)
+ return ret;
+
+ switch (event) {
+ case NETDEV_UP:
+ ret = cxgb4_clip_get(event_dev,
+ (const struct in6_addr *)
+ ((ifa)->addr.s6_addr));
+ if (ret < 0)
+ return ret;
+
+ ret = NOTIFY_OK;
+ break;
+
+ case NETDEV_DOWN:
+ cxgb4_clip_release(event_dev,
+ (const struct in6_addr *)
+ ((ifa)->addr.s6_addr));
+ ret = NOTIFY_OK;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static struct notifier_block cxgbi_inet6addr_notifier = {
+ .notifier_call = cxgbi_inet6addr_handler
+};
+
+/* Retrieve IPv6 addresses from a root device (bond, vlan) associated with
+ * a physical device.
+ * The physical device reference is needed to send the actual CLIP command.
+ */
+static int update_dev_clip(struct net_device *root_dev, struct net_device *dev)
+{
+ struct inet6_dev *idev = NULL;
+ struct inet6_ifaddr *ifa;
+ int ret = 0;
+
+ idev = __in6_dev_get(root_dev);
+ if (!idev)
+ return ret;
+
+ read_lock_bh(&idev->lock);
+ list_for_each_entry(ifa, &idev->addr_list, if_list) {
+ pr_info("updating the clip for addr %pI6\n",
+ ifa->addr.s6_addr);
+ ret = cxgb4_clip_get(dev, (const struct in6_addr *)
+ ifa->addr.s6_addr);
+ if (ret < 0)
+ break;
+ }
+
+ read_unlock_bh(&idev->lock);
+ return ret;
+}
+
+static int update_root_dev_clip(struct net_device *dev)
+{
+ struct net_device *root_dev = NULL;
+ int i, ret = 0;
+
+ /* First populate the real net device's IPv6 address */
+ ret = update_dev_clip(dev, dev);
+ if (ret)
+ return ret;
+
+ /* Parse all bond and vlan devices layered on top of the physical dev */
+ root_dev = netdev_master_upper_dev_get(dev);
+ if (root_dev) {
+ ret = update_dev_clip(root_dev, dev);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < VLAN_N_VID; i++) {
+ root_dev = __vlan_find_dev_deep_rcu(dev, htons(ETH_P_8021Q), i);
+ if (!root_dev)
+ continue;
+
+ ret = update_dev_clip(root_dev, dev);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static void cxgbi_update_clip(struct cxgbi_device *cdev)
+{
+ int i;
+
+ rcu_read_lock();
+
+ for (i = 0; i < cdev->nports; i++) {
+ struct net_device *dev = cdev->ports[i];
+ int ret = 0;
+
+ if (dev)
+ ret = update_root_dev_clip(dev);
+ if (ret < 0)
+ break;
+ }
+ rcu_read_unlock();
+}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+
static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
{
struct cxgbi_device *cdev;
@@ -1605,6 +1876,9 @@ static int t4_uld_state_change(void *handle, enum cxgb4_state state)
switch (state) {
case CXGB4_STATE_UP:
pr_info("cdev 0x%p, UP.\n", cdev);
+#if IS_ENABLED(CONFIG_IPV6)
+ cxgbi_update_clip(cdev);
+#endif
/* re-initialize */
break;
case CXGB4_STATE_START_RECOVERY:
@@ -1635,11 +1909,18 @@ static int __init cxgb4i_init_module(void)
if (rc < 0)
return rc;
cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+
+#if IS_ENABLED(CONFIG_IPV6)
+ register_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+#endif
return 0;
}
static void __exit cxgb4i_exit_module(void)
{
+#if IS_ENABLED(CONFIG_IPV6)
+ unregister_inet6addr_notifier(&cxgbi_inet6addr_notifier);
+#endif
cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index b44c1cff3114..d65df6dc106f 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -24,6 +24,10 @@
#include <linux/inet.h>
#include <net/dst.h>
#include <net/route.h>
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+
#include <linux/inetdevice.h> /* ip_dev_find */
#include <linux/module.h>
#include <net/tcp.h>
@@ -193,8 +197,8 @@ struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev)
}
EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
-static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
- int *port)
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+ int *port)
{
struct net_device *vdev = NULL;
struct cxgbi_device *cdev, *tmp;
@@ -224,6 +228,40 @@ static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
"ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
return NULL;
}
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_netdev);
+
+static struct cxgbi_device *cxgbi_device_find_by_mac(struct net_device *ndev,
+ int *port)
+{
+ struct net_device *vdev = NULL;
+ struct cxgbi_device *cdev, *tmp;
+ int i;
+
+ if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+ vdev = ndev;
+ ndev = vlan_dev_real_dev(ndev);
+ pr_info("vlan dev %s -> %s.\n", vdev->name, ndev->name);
+ }
+
+ mutex_lock(&cdev_mutex);
+ list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+ for (i = 0; i < cdev->nports; i++) {
+ if (!memcmp(ndev->dev_addr, cdev->ports[i]->dev_addr,
+ MAX_ADDR_LEN)) {
+ cdev->hbas[i]->vdev = vdev;
+ mutex_unlock(&cdev_mutex);
+ if (port)
+ *port = i;
+ return cdev;
+ }
+ }
+ }
+ mutex_unlock(&cdev_mutex);
+ log_debug(1 << CXGBI_DBG_DEV,
+ "ndev 0x%p, %s, NO match mac found.\n",
+ ndev, ndev->name);
+ return NULL;
+}
void cxgbi_hbas_remove(struct cxgbi_device *cdev)
{
@@ -245,7 +283,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev)
}
EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
-int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun,
+int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun,
unsigned int max_id, struct scsi_host_template *sht,
struct scsi_transport_template *stt)
{
@@ -320,6 +358,7 @@ static int sock_get_port(struct cxgbi_sock *csk)
struct cxgbi_ports_map *pmap = &cdev->pmap;
unsigned int start;
int idx;
+ __be16 *port;
if (!pmap->max_connect) {
pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
@@ -327,9 +366,14 @@ static int sock_get_port(struct cxgbi_sock *csk)
return -EADDRNOTAVAIL;
}
- if (csk->saddr.sin_port) {
+ if (csk->csk_family == AF_INET)
+ port = &csk->saddr.sin_port;
+ else /* ipv6 */
+ port = &csk->saddr6.sin6_port;
+
+ if (*port) {
pr_err("source port NON-ZERO %u.\n",
- ntohs(csk->saddr.sin_port));
+ ntohs(*port));
return -EADDRINUSE;
}
@@ -347,8 +391,7 @@ static int sock_get_port(struct cxgbi_sock *csk)
idx = 0;
if (!pmap->port_csk[idx]) {
pmap->used++;
- csk->saddr.sin_port =
- htons(pmap->sport_base + idx);
+ *port = htons(pmap->sport_base + idx);
pmap->next = idx;
pmap->port_csk[idx] = csk;
spin_unlock_bh(&pmap->lock);
@@ -374,16 +417,22 @@ static void sock_put_port(struct cxgbi_sock *csk)
{
struct cxgbi_device *cdev = csk->cdev;
struct cxgbi_ports_map *pmap = &cdev->pmap;
+ __be16 *port;
- if (csk->saddr.sin_port) {
- int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+ if (csk->csk_family == AF_INET)
+ port = &csk->saddr.sin_port;
+ else /* ipv6 */
+ port = &csk->saddr6.sin6_port;
- csk->saddr.sin_port = 0;
+ if (*port) {
+ int idx = ntohs(*port) - pmap->sport_base;
+
+ *port = 0;
if (idx < 0 || idx >= pmap->max_connect) {
pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
cdev, csk->port_id,
cdev->ports[csk->port_id]->name,
- ntohs(csk->saddr.sin_port));
+ ntohs(*port));
return;
}
@@ -479,17 +528,11 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
int port = 0xFFFF;
int err = 0;
- if (daddr->sin_family != AF_INET) {
- pr_info("address family 0x%x NOT supported.\n",
- daddr->sin_family);
- err = -EAFNOSUPPORT;
- goto err_out;
- }
-
rt = find_route_ipv4(&fl4, 0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
if (!rt) {
pr_info("no route to ipv4 0x%x, port %u.\n",
- daddr->sin_addr.s_addr, daddr->sin_port);
+ be32_to_cpu(daddr->sin_addr.s_addr),
+ be16_to_cpu(daddr->sin_port));
err = -ENETUNREACH;
goto err_out;
}
@@ -537,9 +580,12 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
csk->port_id = port;
csk->mtu = mtu;
csk->dst = dst;
+
+ csk->csk_family = AF_INET;
csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
csk->daddr.sin_port = daddr->sin_port;
csk->daddr.sin_family = daddr->sin_family;
+ csk->saddr.sin_family = daddr->sin_family;
csk->saddr.sin_addr.s_addr = fl4.saddr;
neigh_release(n);
@@ -556,6 +602,123 @@ err_out:
return ERR_PTR(err);
}
+#if IS_ENABLED(CONFIG_IPV6)
+static struct rt6_info *find_route_ipv6(const struct in6_addr *saddr,
+ const struct in6_addr *daddr)
+{
+ struct flowi6 fl;
+
+ if (saddr)
+ memcpy(&fl.saddr, saddr, sizeof(struct in6_addr));
+ if (daddr)
+ memcpy(&fl.daddr, daddr, sizeof(struct in6_addr));
+ return (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
+}
+
+static struct cxgbi_sock *cxgbi_check_route6(struct sockaddr *dst_addr)
+{
+ struct sockaddr_in6 *daddr6 = (struct sockaddr_in6 *)dst_addr;
+ struct dst_entry *dst;
+ struct net_device *ndev;
+ struct cxgbi_device *cdev;
+ struct rt6_info *rt = NULL;
+ struct neighbour *n;
+ struct in6_addr pref_saddr;
+ struct cxgbi_sock *csk = NULL;
+ unsigned int mtu = 0;
+ int port = 0xFFFF;
+ int err = 0;
+
+ rt = find_route_ipv6(NULL, &daddr6->sin6_addr);
+
+ if (!rt) {
+ pr_info("no route to ipv6 %pI6 port %u\n",
+ daddr6->sin6_addr.s6_addr,
+ be16_to_cpu(daddr6->sin6_port));
+ err = -ENETUNREACH;
+ goto err_out;
+ }
+
+ dst = &rt->dst;
+
+ n = dst_neigh_lookup(dst, &daddr6->sin6_addr);
+
+ if (!n) {
+ pr_info("%pI6, port %u, dst no neighbour.\n",
+ daddr6->sin6_addr.s6_addr,
+ be16_to_cpu(daddr6->sin6_port));
+ err = -ENETUNREACH;
+ goto rel_rt;
+ }
+ ndev = n->dev;
+
+ if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
+ pr_info("multi-cast route %pI6 port %u, dev %s.\n",
+ daddr6->sin6_addr.s6_addr,
+ ntohs(daddr6->sin6_port), ndev->name);
+ err = -ENETUNREACH;
+ goto rel_rt;
+ }
+
+ cdev = cxgbi_device_find_by_netdev(ndev, &port);
+ if (!cdev)
+ cdev = cxgbi_device_find_by_mac(ndev, &port);
+ if (!cdev) {
+ pr_info("dst %pI6 %s, NOT cxgbi device.\n",
+ daddr6->sin6_addr.s6_addr, ndev->name);
+ err = -ENETUNREACH;
+ goto rel_rt;
+ }
+ log_debug(1 << CXGBI_DBG_SOCK,
+ "route to %pI6 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+ daddr6->sin6_addr.s6_addr, ntohs(daddr6->sin6_port), port,
+ ndev->name, cdev);
+
+ csk = cxgbi_sock_create(cdev);
+ if (!csk) {
+ err = -ENOMEM;
+ goto rel_rt;
+ }
+ csk->cdev = cdev;
+ csk->port_id = port;
+ csk->mtu = mtu;
+ csk->dst = dst;
+
+ if (ipv6_addr_any(&rt->rt6i_prefsrc.addr)) {
+ struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt);
+
+ err = ipv6_dev_get_saddr(&init_net, idev ? idev->dev : NULL,
+ &daddr6->sin6_addr, 0, &pref_saddr);
+ if (err) {
+ pr_info("failed to get source address to reach %pI6\n",
+ &daddr6->sin6_addr);
+ goto rel_rt;
+ }
+ } else {
+ pref_saddr = rt->rt6i_prefsrc.addr;
+ }
+
+ csk->csk_family = AF_INET6;
+ csk->daddr6.sin6_addr = daddr6->sin6_addr;
+ csk->daddr6.sin6_port = daddr6->sin6_port;
+ csk->daddr6.sin6_family = daddr6->sin6_family;
+ csk->saddr6.sin6_addr = pref_saddr;
+
+ neigh_release(n);
+ return csk;
+
+rel_rt:
+ if (n)
+ neigh_release(n);
+
+ ip6_rt_put(rt);
+ if (csk)
+ cxgbi_sock_closed(csk);
+err_out:
+ return ERR_PTR(err);
+}
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+
void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
unsigned int opt)
{
@@ -2194,6 +2357,34 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
}
EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
+static inline int csk_print_port(struct cxgbi_sock *csk, char *buf)
+{
+ int len;
+
+ cxgbi_sock_get(csk);
+ len = sprintf(buf, "%hu\n", ntohs(csk->daddr.sin_port));
+ cxgbi_sock_put(csk);
+
+ return len;
+}
+
+static inline int csk_print_ip(struct cxgbi_sock *csk, char *buf)
+{
+ int len;
+
+ cxgbi_sock_get(csk);
+ if (csk->csk_family == AF_INET)
+ len = sprintf(buf, "%pI4",
+ &csk->daddr.sin_addr.s_addr);
+ else
+ len = sprintf(buf, "%pI6",
+ &csk->daddr6.sin6_addr);
+
+ cxgbi_sock_put(csk);
+
+ return len;
+}
+
int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
char *buf)
{
@@ -2447,7 +2638,19 @@ struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
}
}
- csk = cxgbi_check_route(dst_addr);
+ if (dst_addr->sa_family == AF_INET) {
+ csk = cxgbi_check_route(dst_addr);
+#if IS_ENABLED(CONFIG_IPV6)
+ } else if (dst_addr->sa_family == AF_INET6) {
+ csk = cxgbi_check_route6(dst_addr);
+#endif
+ } else {
+ pr_info("address family 0x%x NOT supported.\n",
+ dst_addr->sa_family);
+ err = -EAFNOSUPPORT;
+ return (struct iscsi_endpoint *)ERR_PTR(err);
+ }
+
if (IS_ERR(csk))
return (struct iscsi_endpoint *)csk;
cxgbi_sock_get(csk);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 8135f04671af..b3e6e7541cc5 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -44,6 +44,15 @@ enum cxgbi_dbg_flag {
pr_info(fmt, ##__VA_ARGS__); \
} while (0)
+#define pr_info_ipaddr(fmt_trail, \
+ addr1, addr2, args_trail...) \
+do { \
+ if (!((1 << CXGBI_DBG_SOCK) & dbg_level)) \
+ break; \
+ pr_info("%pISpc - %pISpc, " fmt_trail, \
+ addr1, addr2, args_trail); \
+} while (0)
+
/* max. connections per adapter */
#define CXGBI_MAX_CONN 16384
@@ -202,8 +211,15 @@ struct cxgbi_sock {
spinlock_t lock;
struct kref refcnt;
unsigned int state;
- struct sockaddr_in saddr;
- struct sockaddr_in daddr;
+ unsigned int csk_family;
+ union {
+ struct sockaddr_in saddr;
+ struct sockaddr_in6 saddr6;
+ };
+ union {
+ struct sockaddr_in daddr;
+ struct sockaddr_in6 daddr6;
+ };
struct dst_entry *dst;
struct sk_buff_head receive_queue;
struct sk_buff_head write_queue;
@@ -692,7 +708,8 @@ struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
void cxgbi_device_unregister(struct cxgbi_device *);
void cxgbi_device_unregister_all(unsigned int flag);
struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
-int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
+struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *);
+int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int,
struct scsi_host_template *,
struct scsi_transport_template *);
void cxgbi_hbas_remove(struct cxgbi_device *);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 83d9bf6fa6ca..0c6be0a17f53 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -519,9 +519,7 @@ static struct ParameterData cfg_data[] = {
CFG_PARAM_UNSET,
0,
0x2f,
-#ifdef CONFIG_SCSI_MULTI_LUN
- NAC_SCANLUN |
-#endif
+ NAC_SCANLUN |
NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET
/*| NAC_ACTIVE_NEG*/,
NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08
@@ -1089,7 +1087,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
dprintkdbg(DBG_0, "queue_command: (0x%p) <%02i-%i> cmnd=0x%02x\n",
- cmd, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
+ cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0]);
/* Assume BAD_TARGET; will be cleared later */
cmd->result = DID_BAD_TARGET << 16;
@@ -1104,7 +1102,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s
/* does the specified lun on the specified device exist */
if (!(acb->dcb_map[cmd->device->id] & (1 << cmd->device->lun))) {
dprintkl(KERN_INFO, "queue_command: Ignore target <%02i-%i>\n",
- cmd->device->id, cmd->device->lun);
+ cmd->device->id, (u8)cmd->device->lun);
goto complete;
}
@@ -1113,7 +1111,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s
if (!dcb) {
/* should never happen */
dprintkl(KERN_ERR, "queue_command: No such device <%02i-%i>",
- cmd->device->id, cmd->device->lun);
+ cmd->device->id, (u8)cmd->device->lun);
goto complete;
}
@@ -1209,7 +1207,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb,
"cmnd=0x%02x <%02i-%i>\n",
srb, srb->cmd,
srb->cmd->cmnd[0], srb->cmd->device->id,
- srb->cmd->device->lun);
+ (u8)srb->cmd->device->lun);
printk(" sglist=%p cnt=%i idx=%i len=%zu\n",
srb->segment_x, srb->sg_count, srb->sg_index,
srb->total_xfer_length);
@@ -1304,7 +1302,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
dprintkl(KERN_INFO,
"eh_bus_reset: (0%p) target=<%02i-%i> cmd=%p\n",
- cmd, cmd->device->id, cmd->device->lun, cmd);
+ cmd, cmd->device->id, (u8)cmd->device->lun, cmd);
if (timer_pending(&acb->waiting_timer))
del_timer(&acb->waiting_timer);
@@ -1371,7 +1369,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd)
struct DeviceCtlBlk *dcb;
struct ScsiReqBlk *srb;
dprintkl(KERN_INFO, "eh_abort: (0x%p) target=<%02i-%i> cmd=%p\n",
- cmd, cmd->device->id, cmd->device->lun, cmd);
+ cmd, cmd->device->id, (u8)cmd->device->lun, cmd);
dcb = find_dcb(acb, cmd->device->id, cmd->device->lun);
if (!dcb) {
@@ -1607,7 +1605,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
dprintkl(KERN_WARNING, "start_scsi: (0x%p) "
"Out of tags target=<%02i-%i>)\n",
srb->cmd, srb->cmd->device->id,
- srb->cmd->device->lun);
+ (u8)srb->cmd->device->lun);
srb->state = SRB_READY;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL,
DO_HWRESELECT);
@@ -1625,7 +1623,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
/*polling:*/
/* Send CDB ..command block ......... */
dprintkdbg(DBG_KG, "start_scsi: (0x%p) <%02i-%i> cmnd=0x%02x tag=%i\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun,
srb->cmd->cmnd[0], srb->tag_number);
if (srb->flag & AUTO_REQSENSE) {
DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE);
@@ -2043,7 +2041,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 scsi_status = *pscsi_status;
u32 d_left_counter = 0;
dprintkdbg(DBG_0, "data_out_phase0: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
/*
* KG: We need to drain the buffers before we draw any conclusions!
@@ -2173,7 +2171,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "data_out_phase1: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
clear_fifo(acb, "data_out_phase1");
/* do prepare before transfer when data out phase */
data_io_transfer(acb, srb, XFERDATAOUT);
@@ -2185,7 +2183,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 scsi_status = *pscsi_status;
dprintkdbg(DBG_0, "data_in_phase0: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
/*
* KG: DataIn is much more tricky than DataOut. When the device is finished
@@ -2396,7 +2394,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "data_in_phase1: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
data_io_transfer(acb, srb, XFERDATAIN);
}
@@ -2408,7 +2406,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
u8 bval;
dprintkdbg(DBG_0,
"data_io_transfer: (0x%p) <%02i-%i> %c len=%i, sg=(%i/%i)\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun,
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun,
((io_dir & DMACMD_DIR) ? 'r' : 'w'),
srb->total_xfer_length, srb->sg_index, srb->sg_count);
if (srb == acb->tmp_srb)
@@ -2581,7 +2579,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "status_phase0: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */
srb->state = SRB_COMPLETED;
@@ -2595,7 +2593,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
dprintkdbg(DBG_0, "status_phase1: (0x%p) <%02i-%i>\n",
- srb->cmd, srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun);
srb->state = SRB_STATUS;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP);
@@ -3320,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
int ckc_only = 1;
dprintkdbg(DBG_1, "srb_done: (0x%p) <%02i-%i>\n", srb->cmd,
- srb->cmd->device->id, srb->cmd->device->lun);
+ srb->cmd->device->id, (u8)srb->cmd->device->lun);
dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count,
scsi_sgtalbe(cmd));
@@ -3500,7 +3498,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,